summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-uac110
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-uac210
-rw-r--r--Documentation/ABI/testing/dell-smbios-wmi2
-rw-r--r--Documentation/ABI/testing/ima_policy15
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio-chemical-sgp4031
-rw-r--r--Documentation/ABI/testing/sysfs-bus-thunderbolt2
-rw-r--r--Documentation/ABI/testing/sysfs-class-firmware-attributes19
-rw-r--r--Documentation/ABI/testing/sysfs-devices-system-cpu26
-rw-r--r--Documentation/ABI/testing/sysfs-driver-ge-achc15
-rw-r--r--Documentation/ABI/testing/sysfs-driver-intc_sar54
-rw-r--r--Documentation/ABI/testing/sysfs-driver-ufs236
-rw-r--r--Documentation/ABI/testing/sysfs-fs-f2fs23
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers24
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-iommu_groups6
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-mm-numa24
-rw-r--r--Documentation/ABI/testing/sysfs-platform-dell-smbios2
-rw-r--r--Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt2
-rw-r--r--Documentation/ABI/testing/sysfs-power2
-rw-r--r--Documentation/PCI/pci.rst1
-rw-r--r--Documentation/admin-guide/binderfs.rst13
-rw-r--r--Documentation/admin-guide/cputopology.rst10
-rw-r--r--Documentation/admin-guide/devices.txt6
-rw-r--r--Documentation/admin-guide/hw-vuln/core-scheduling.rst10
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt52
-rw-r--r--Documentation/admin-guide/laptops/lg-laptop.rst4
-rw-r--r--Documentation/admin-guide/mm/numa_memory_policy.rst15
-rw-r--r--Documentation/admin-guide/sysctl/vm.rst3
-rw-r--r--Documentation/admin-guide/sysrq.rst12
-rw-r--r--Documentation/arm/marvell.rst18
-rw-r--r--Documentation/arm64/asymmetric-32bit.rst155
-rw-r--r--Documentation/arm64/booting.rst37
-rw-r--r--Documentation/arm64/index.rst1
-rw-r--r--Documentation/arm64/memory-tagging-extension.rst48
-rw-r--r--Documentation/conf.py121
-rw-r--r--Documentation/core-api/cachetlb.rst86
-rw-r--r--Documentation/core-api/cpu_hotplug.rst38
-rw-r--r--Documentation/core-api/printk-basics.rst5
-rw-r--r--Documentation/core-api/printk-formats.rst1
-rw-r--r--Documentation/dev-tools/kasan.rst13
-rw-r--r--Documentation/dev-tools/kcsan.rst12
-rw-r--r--Documentation/dev-tools/kunit/kunit-tool.rst9
-rw-r--r--Documentation/dev-tools/kunit/running_tips.rst10
-rw-r--r--Documentation/devicetree/bindings/Makefile2
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-at91.yaml5
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-sysregs.txt14
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.yaml29
-rw-r--r--Documentation/devicetree/bindings/arm/gemini.txt108
-rw-r--r--Documentation/devicetree/bindings/arm/gemini.yaml95
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt1
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt31
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml59
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8192-clock.yaml199
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8192-sys-clock.yaml65
-rw-r--r--Documentation/devicetree/bindings/arm/qcom.yaml10
-rw-r--r--Documentation/devicetree/bindings/arm/renesas.yaml50
-rw-r--r--Documentation/devicetree/bindings/arm/tegra.yaml1
-rw-r--r--Documentation/devicetree/bindings/ata/exynos-sata.txt30
-rw-r--r--Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml61
-rw-r--r--Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml44
-rw-r--r--Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt18
-rw-r--r--Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml55
-rw-r--r--Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt17
-rw-r--r--Documentation/devicetree/bindings/bus/intel,ixp4xx-expansion-bus-controller.yaml168
-rw-r--r--Documentation/devicetree/bindings/chosen.txt12
-rw-r--r--Documentation/devicetree/bindings/clock/brcm,iproc-clocks.yaml27
-rw-r--r--Documentation/devicetree/bindings/clock/clk-exynos-audss.txt103
-rw-r--r--Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt53
-rw-r--r--Documentation/devicetree/bindings/clock/exynos3250-clock.txt57
-rw-r--r--Documentation/devicetree/bindings/clock/exynos4-clock.txt86
-rw-r--r--Documentation/devicetree/bindings/clock/exynos5250-clock.txt41
-rw-r--r--Documentation/devicetree/bindings/clock/exynos5420-clock.txt42
-rw-r--r--Documentation/devicetree/bindings/clock/idt,versaclock5.yaml40
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,a53pll.yaml3
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml72
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml76
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gpucc.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,mmcc.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,rpmcc.txt4
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml94
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,videocc.yaml6
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt68
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.yaml92
-rw-r--r--Documentation/devicetree/bindings/clock/samsung,exynos-audss-clock.yaml80
-rw-r--r--Documentation/devicetree/bindings/clock/samsung,exynos-clock.yaml59
-rw-r--r--Documentation/devicetree/bindings/clock/samsung,exynos-ext-clock.yaml46
-rw-r--r--Documentation/devicetree/bindings/clock/samsung,exynos4412-isp-clock.yaml64
-rw-r--r--Documentation/devicetree/bindings/clock/samsung,s5pv210-audss-clock.yaml78
-rw-r--r--Documentation/devicetree/bindings/connector/usb-connector.yaml4
-rw-r--r--Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt26
-rw-r--r--Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt169
-rw-r--r--Documentation/devicetree/bindings/devfreq/event/samsung,exynos-nocp.yaml48
-rw-r--r--Documentation/devicetree/bindings/devfreq/event/samsung,exynos-ppmu.yaml169
-rw-r--r--Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml21
-rw-r--r--Documentation/devicetree/bindings/display/dp-aux-bus.yaml37
-rw-r--r--Documentation/devicetree/bindings/display/fsl,lcdif.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt2
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml23
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml6
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml8
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml72
-rw-r--r--Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml78
-rw-r--r--Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml62
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple.yaml24
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml99
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml18
-rw-r--r--Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt1
-rw-r--r--Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml208
-rw-r--r--Documentation/devicetree/bindings/display/ssd1307fb.txt60
-rw-r--r--Documentation/devicetree/bindings/display/zte,vou.txt120
-rw-r--r--Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml12
-rw-r--r--Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt1
-rw-r--r--Documentation/devicetree/bindings/firmware/arm,scmi.yaml8
-rw-r--r--Documentation/devicetree/bindings/firmware/arm,scpi.yaml6
-rw-r--r--Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt44
-rw-r--r--Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.yaml89
-rw-r--r--Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.yaml33
-rw-r--r--Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt25
-rw-r--r--Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.yaml36
-rw-r--r--Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml77
-rw-r--r--Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt46
-rw-r--r--Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml1
-rw-r--r--Documentation/devicetree/bindings/hwmon/max1619.txt12
-rw-r--r--Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.txt46
-rw-r--r--Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.yaml71
-rw-r--r--Documentation/devicetree/bindings/i2c/renesas,riic.yaml30
-rw-r--r--Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml10
-rw-r--r--Documentation/devicetree/bindings/iio/accel/bosch,bma180.yaml61
-rw-r--r--Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml55
-rw-r--r--Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml19
-rw-r--r--Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml134
-rw-r--r--Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml1
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5064.yaml268
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5360.yaml79
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5380.yaml70
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5421.yaml51
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5449.yaml97
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml50
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5624r.yaml47
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5686.yaml75
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5761.yaml60
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5764.yaml62
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml52
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad8801.yaml60
-rw-r--r--Documentation/devicetree/bindings/iio/dac/microchip,mcp4922.yaml46
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml1
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml11
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/loongson,liointc.yaml8
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/samsung,exynos4210-combiner.txt50
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/samsung,exynos4210-combiner.yaml96
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/ti,pruss-intc.yaml4
-rw-r--r--Documentation/devicetree/bindings/iommu/apple,dart.yaml81
-rw-r--r--Documentation/devicetree/bindings/mailbox/mtk-gce.txt24
-rw-r--r--Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml2
-rw-r--r--Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/media/amlogic,meson-ir-tx.yaml60
-rw-r--r--Documentation/devicetree/bindings/media/atmel,isc.yaml3
-rw-r--r--Documentation/devicetree/bindings/media/i2c/adv7180.yaml8
-rw-r--r--Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml8
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml91
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml91
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml91
-rw-r--r--Documentation/devicetree/bindings/media/microchip,xisc.yaml2
-rw-r--r--Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml12
-rw-r--r--Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml2
-rw-r--r--Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml19
-rw-r--r--Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml174
-rw-r--r--Documentation/devicetree/bindings/media/renesas,drif.yaml3
-rw-r--r--Documentation/devicetree/bindings/media/rockchip-vpu.yaml1
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ath79-ddr-controller.txt35
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.txt27
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.yaml48
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/exynos5422-dmc.txt84
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/marvell,mvebu-sdram-controller.yaml31
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/mvebu-sdram-controller.txt21
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/qca,ath79-ddr-controller.yaml61
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.txt12
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.yaml35
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml17
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/samsung,exynos5422-dmc.yaml137
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/synopsys,ddrc-ecc.yaml73
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/synopsys.txt32
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ti,da8xx-ddrctl.yaml35
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ti-da8xx-ddrctl.txt20
-rw-r--r--Documentation/devicetree/bindings/mfd/axp20x.txt3
-rw-r--r--Documentation/devicetree/bindings/mfd/brcm,cru.yaml86
-rw-r--r--Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml (renamed from drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml)31
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml13
-rw-r--r--Documentation/devicetree/bindings/mfd/syscon.yaml3
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml6
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,tps65086.yaml124
-rw-r--r--Documentation/devicetree/bindings/mfd/tps65086.txt54
-rw-r--r--Documentation/devicetree/bindings/misc/eeprom-93xx46.txt29
-rw-r--r--Documentation/devicetree/bindings/misc/eeprom-93xx46.yaml70
-rw-r--r--Documentation/devicetree/bindings/misc/ge-achc.txt26
-rw-r--r--Documentation/devicetree/bindings/misc/ge-achc.yaml65
-rw-r--r--Documentation/devicetree/bindings/mtd/gpmc-nand.txt2
-rw-r--r--Documentation/devicetree/bindings/mtd/gpmc-nor.txt4
-rw-r--r--Documentation/devicetree/bindings/mtd/mtd-physmap.yaml1
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/redboot-fis.txt27
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml42
-rw-r--r--Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml4
-rw-r--r--Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/micrel,ks8851.yaml96
-rw-r--r--Documentation/devicetree/bindings/net/micrel-ks8851.txt18
-rw-r--r--Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt4
-rw-r--r--Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml3
-rw-r--r--Documentation/devicetree/bindings/net/qca,ar71xx.yaml25
-rw-r--r--Documentation/devicetree/bindings/net/realtek-bluetooth.yaml8
-rw-r--r--Documentation/devicetree/bindings/net/renesas,etheravb.yaml57
-rw-r--r--Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml8
-rw-r--r--Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml6
-rw-r--r--Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml44
-rw-r--r--Documentation/devicetree/bindings/nvmem/nvmem.yaml2
-rw-r--r--Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml3
-rw-r--r--Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml95
-rw-r--r--Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt49
-rw-r--r--Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt4
-rw-r--r--Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt2
-rw-r--r--Documentation/devicetree/bindings/pci/designware-pcie.txt77
-rw-r--r--Documentation/devicetree/bindings/pci/faraday,ftpci100.txt135
-rw-r--r--Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml174
-rw-r--r--Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt100
-rw-r--r--Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml202
-rw-r--r--Documentation/devicetree/bindings/pci/hisilicon,kirin-pcie.yaml167
-rw-r--r--Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt2
-rw-r--r--Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml36
-rw-r--r--Documentation/devicetree/bindings/pci/kirin-pcie.txt50
-rw-r--r--Documentation/devicetree/bindings/pci/layerscape-pci.txt2
-rw-r--r--Documentation/devicetree/bindings/pci/loongson.yaml8
-rw-r--r--Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt5
-rw-r--r--Documentation/devicetree/bindings/pci/pci-armada8k.txt2
-rw-r--r--Documentation/devicetree/bindings/pci/pcie-al.txt2
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie.txt14
-rw-r--r--Documentation/devicetree/bindings/pci/samsung,exynos-pcie.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml90
-rw-r--r--Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml102
-rw-r--r--Documentation/devicetree/bindings/pci/socionext,uniphier-pcie-ep.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/ti-pci.txt4
-rw-r--r--Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml110
-rw-r--r--Documentation/devicetree/bindings/pci/uniphier-pcie.txt2
-rw-r--r--Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.txt20
-rw-r--r--Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml53
-rw-r--r--Documentation/devicetree/bindings/phy/hisilicon,phy-hi3670-pcie.yaml82
-rw-r--r--Documentation/devicetree/bindings/phy/intel,keembay-phy-usb.yaml (renamed from Documentation/devicetree/bindings/phy/intel,phy-keembay-usb.yaml)2
-rw-r--r--Documentation/devicetree/bindings/phy/intel,lgm-emmc-phy.yaml6
-rw-r--r--Documentation/devicetree/bindings/phy/mediatek,tphy.yaml30
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml4
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml2
-rw-r--r--Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml15
-rw-r--r--Documentation/devicetree/bindings/phy/samsung,ufs-phy.yaml1
-rw-r--r--Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.txt82
-rw-r--r--Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.yaml103
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx8ulp-pinctrl.yaml79
-rw-r--r--Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml10
-rw-r--r--Documentation/devicetree/bindings/pinctrl/intel,pinctrl-keembay.yaml135
-rw-r--r--Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt8
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml206
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml173
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml373
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml228
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt156
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-mt6797.txt83
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt490
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-mt8183.txt132
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml5
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.yaml133
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt288
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml239
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml179
-rw-r--r--Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml155
-rw-r--r--Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt1
-rw-r--r--Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml1
-rw-r--r--Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.txt105
-rw-r--r--Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.yaml214
-rw-r--r--Documentation/devicetree/bindings/power/qcom,rpmpd.yaml1
-rw-r--r--Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt61
-rw-r--r--Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml83
-rw-r--r--Documentation/devicetree/bindings/power/rockchip-io-domain.txt135
-rw-r--r--Documentation/devicetree/bindings/power/rockchip-io-domain.yaml360
-rw-r--r--Documentation/devicetree/bindings/regulator/richtek,rt6245-regulator.yaml1
-rw-r--r--Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml1
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml1
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt36
-rw-r--r--Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml1
-rw-r--r--Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml1
-rw-r--r--Documentation/devicetree/bindings/reset/qcom,aoss-reset.yaml5
-rw-r--r--Documentation/devicetree/bindings/reset/qcom,pdc-global.yaml4
-rw-r--r--Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml65
-rw-r--r--Documentation/devicetree/bindings/reset/socionext,uniphier-glue-reset.yaml88
-rw-r--r--Documentation/devicetree/bindings/reset/uniphier-reset.txt61
-rw-r--r--Documentation/devicetree/bindings/riscv/starfive.yaml27
-rw-r--r--Documentation/devicetree/bindings/rng/mtk-rng.yaml1
-rw-r--r--Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt17
-rw-r--r--Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.yaml44
-rw-r--r--Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml1
-rw-r--r--Documentation/devicetree/bindings/serial/8250.yaml6
-rw-r--r--Documentation/devicetree/bindings/serial/8250_omap.yaml10
-rw-r--r--Documentation/devicetree/bindings/serial/cdns,uart.txt27
-rw-r--r--Documentation/devicetree/bindings/serial/cdns,uart.yaml66
-rw-r--r--Documentation/devicetree/bindings/serial/mtk-uart.txt1
-rw-r--r--Documentation/devicetree/bindings/soc/litex/litex,soc-controller.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt87
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml114
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml3
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/rockchip/grf.yaml19
-rw-r--r--Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml41
-rw-r--r--Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt1
-rw-r--r--Documentation/devicetree/bindings/sound/ics43432.txt6
-rw-r--r--Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml184
-rw-r--r--Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml47
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,sm8250.yaml6
-rw-r--r--Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml4
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml118
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-i2s.yaml11
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-spdif.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-sai.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/tlv320adcx140.yaml8
-rw-r--r--Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml12
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-tsens.yaml1
-rw-r--r--Documentation/devicetree/bindings/timer/arm,sp804.yaml6
-rw-r--r--Documentation/devicetree/bindings/timer/energymicro,efm32-timer.txt23
-rw-r--r--Documentation/devicetree/bindings/trivial-devices.yaml8
-rw-r--r--Documentation/devicetree/bindings/usb/generic-ehci.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/generic-ohci.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml47
-rw-r--r--Documentation/devicetree/bindings/usb/mediatek,musb.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/qcom,dwc3.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/renesas,usbhs.yaml26
-rw-r--r--Documentation/devicetree/bindings/usb/snps,dwc3.yaml15
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml24
-rw-r--r--Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml44
-rw-r--r--Documentation/devicetree/bindings/watchdog/mtk-wdt.txt1
-rw-r--r--Documentation/driver-api/dma-buf.rst13
-rw-r--r--Documentation/driver-api/fpga/fpga-bridge.rst10
-rw-r--r--Documentation/driver-api/fpga/fpga-mgr.rst12
-rw-r--r--Documentation/driver-api/fpga/fpga-programming.rst8
-rw-r--r--Documentation/driver-api/fpga/fpga-region.rst20
-rw-r--r--Documentation/driver-api/gpio/consumer.rst10
-rw-r--r--Documentation/driver-api/gpio/driver.rst11
-rw-r--r--Documentation/driver-api/media/camera-sensor.rst45
-rw-r--r--Documentation/driver-api/media/cec-core.rst9
-rw-r--r--Documentation/driver-api/media/csi2.rst94
-rw-r--r--Documentation/driver-api/media/index.rst2
-rw-r--r--Documentation/driver-api/media/tx-rx.rst133
-rw-r--r--Documentation/driver-api/thermal/nouveau_thermal.rst2
-rw-r--r--Documentation/driver-api/vfio.rst4
-rw-r--r--Documentation/fault-injection/provoke-crashes.rst3
-rw-r--r--Documentation/features/vm/THP/arch-support.txt2
-rw-r--r--Documentation/filesystems/erofs.rst19
-rw-r--r--Documentation/filesystems/ext4/globals.rst1
-rw-r--r--Documentation/filesystems/ext4/inodes.rst10
-rw-r--r--Documentation/filesystems/ext4/orphan.rst52
-rw-r--r--Documentation/filesystems/ext4/special_inodes.rst17
-rw-r--r--Documentation/filesystems/ext4/super.rst15
-rw-r--r--Documentation/filesystems/f2fs.rst17
-rw-r--r--Documentation/filesystems/index.rst1
-rw-r--r--Documentation/filesystems/locking.rst2
-rw-r--r--Documentation/filesystems/ntfs3.rst106
-rw-r--r--Documentation/filesystems/overlayfs.rst3
-rw-r--r--Documentation/filesystems/vfs.rst2
-rw-r--r--Documentation/firmware-guide/acpi/dsd/graph.rst2
-rw-r--r--Documentation/fpga/dfl.rst4
-rw-r--r--Documentation/gpu/drm-kms.rst35
-rw-r--r--Documentation/gpu/drm-uapi.rst22
-rw-r--r--Documentation/gpu/i915.rst15
-rw-r--r--Documentation/gpu/rfc/i915_parallel_execbuf.h122
-rw-r--r--Documentation/gpu/rfc/i915_scheduler.rst148
-rw-r--r--Documentation/gpu/rfc/index.rst4
-rw-r--r--Documentation/gpu/vkms.rst38
-rw-r--r--Documentation/kbuild/llvm.rst25
-rw-r--r--Documentation/networking/device_drivers/ethernet/freescale/dpaa2/dpio-driver.rst1
-rw-r--r--Documentation/networking/nf_conntrack-sysctl.rst13
-rw-r--r--Documentation/powerpc/associativity.rst105
-rw-r--r--Documentation/powerpc/index.rst1
-rw-r--r--Documentation/process/deprecated.rst4
-rw-r--r--Documentation/process/submitting-patches.rst10
-rw-r--r--Documentation/sound/alsa-configuration.rst34
-rw-r--r--Documentation/sound/hd-audio/notes.rst11
-rw-r--r--Documentation/sound/kernel-api/writing-an-alsa-driver.rst35
-rw-r--r--Documentation/sphinx/requirements.txt3
-rw-r--r--Documentation/trace/boottime-trace.rst85
-rw-r--r--Documentation/trace/coresight/coresight-config.rst244
-rw-r--r--Documentation/trace/coresight/coresight.rst15
-rw-r--r--Documentation/trace/histogram.rst110
-rw-r--r--Documentation/translations/conf.py12
-rw-r--r--Documentation/translations/index.rst1
-rw-r--r--Documentation/translations/it_IT/core-api/symbol-namespaces.rst26
-rw-r--r--Documentation/translations/it_IT/kernel-hacking/hacking.rst4
-rw-r--r--Documentation/translations/it_IT/process/deprecated.rst8
-rw-r--r--Documentation/translations/it_IT/process/stable-kernel-rules.rst6
-rw-r--r--Documentation/translations/it_IT/process/submitting-patches.rst57
-rw-r--r--Documentation/translations/ja_JP/howto.rst8
-rw-r--r--Documentation/translations/ja_JP/index.rst5
-rw-r--r--Documentation/translations/ko_KR/howto.rst8
-rw-r--r--Documentation/translations/ko_KR/index.rst2
-rw-r--r--Documentation/translations/zh_CN/accounting/index.rst25
-rw-r--r--Documentation/translations/zh_CN/accounting/psi.rst155
-rw-r--r--Documentation/translations/zh_CN/core-api/cachetlb.rst9
-rw-r--r--Documentation/translations/zh_CN/core-api/cpu_hotplug.rst348
-rw-r--r--Documentation/translations/zh_CN/core-api/genericirq.rst409
-rw-r--r--Documentation/translations/zh_CN/core-api/index.rst7
-rw-r--r--Documentation/translations/zh_CN/core-api/memory-hotplug.rst126
-rw-r--r--Documentation/translations/zh_CN/core-api/protection-keys.rst99
-rw-r--r--Documentation/translations/zh_CN/dev-tools/index.rst5
-rw-r--r--Documentation/translations/zh_CN/dev-tools/testing-overview.rst109
-rw-r--r--Documentation/translations/zh_CN/index.rst16
-rw-r--r--Documentation/translations/zh_CN/infiniband/core_locking.rst115
-rw-r--r--Documentation/translations/zh_CN/infiniband/index.rst40
-rw-r--r--Documentation/translations/zh_CN/infiniband/ipoib.rst111
-rw-r--r--Documentation/translations/zh_CN/infiniband/opa_vnic.rst156
-rw-r--r--Documentation/translations/zh_CN/infiniband/sysfs.rst21
-rw-r--r--Documentation/translations/zh_CN/infiniband/tag_matching.rst63
-rw-r--r--Documentation/translations/zh_CN/infiniband/user_mad.rst164
-rw-r--r--Documentation/translations/zh_CN/infiniband/user_verbs.rst72
-rw-r--r--Documentation/translations/zh_CN/process/coding-style.rst3
-rw-r--r--Documentation/translations/zh_CN/virt/acrn/cpuid.rst56
-rw-r--r--Documentation/translations/zh_CN/virt/acrn/index.rst25
-rw-r--r--Documentation/translations/zh_CN/virt/acrn/introduction.rst52
-rw-r--r--Documentation/translations/zh_CN/virt/acrn/io-request.rst99
-rw-r--r--Documentation/translations/zh_CN/virt/guest-halt-polling.rst87
-rw-r--r--Documentation/translations/zh_CN/virt/index.rst38
-rw-r--r--Documentation/translations/zh_CN/virt/ne_overview.rst88
-rw-r--r--Documentation/translations/zh_CN/virt/paravirt_ops.rst41
-rw-r--r--Documentation/translations/zh_TW/IRQ.txt41
-rw-r--r--Documentation/translations/zh_TW/admin-guide/README.rst351
-rw-r--r--Documentation/translations/zh_TW/admin-guide/bug-bisect.rst85
-rw-r--r--Documentation/translations/zh_TW/admin-guide/bug-hunting.rst344
-rw-r--r--Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst16
-rw-r--r--Documentation/translations/zh_TW/admin-guide/cpu-load.rst112
-rw-r--r--Documentation/translations/zh_TW/admin-guide/index.rst135
-rw-r--r--Documentation/translations/zh_TW/admin-guide/init.rst58
-rw-r--r--Documentation/translations/zh_TW/admin-guide/reporting-issues.rst1337
-rw-r--r--Documentation/translations/zh_TW/admin-guide/security-bugs.rst78
-rw-r--r--Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst161
-rw-r--r--Documentation/translations/zh_TW/admin-guide/unicode.rst174
-rw-r--r--Documentation/translations/zh_TW/disclaimer-zh_TW.rst11
-rw-r--r--Documentation/translations/zh_TW/gpio.txt651
-rw-r--r--Documentation/translations/zh_TW/index.rst168
-rw-r--r--Documentation/translations/zh_TW/io_ordering.txt68
-rw-r--r--Documentation/translations/zh_TW/oops-tracing.txt212
-rw-r--r--Documentation/translations/zh_TW/process/1.Intro.rst199
-rw-r--r--Documentation/translations/zh_TW/process/2.Process.rst369
-rw-r--r--Documentation/translations/zh_TW/process/3.Early-stage.rst172
-rw-r--r--Documentation/translations/zh_TW/process/4.Coding.rst297
-rw-r--r--Documentation/translations/zh_TW/process/5.Posting.rst251
-rw-r--r--Documentation/translations/zh_TW/process/6.Followthrough.rst156
-rw-r--r--Documentation/translations/zh_TW/process/7.AdvancedTopics.rst137
-rw-r--r--Documentation/translations/zh_TW/process/8.Conclusion.rst74
-rw-r--r--Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst112
-rw-r--r--Documentation/translations/zh_TW/process/code-of-conduct.rst76
-rw-r--r--Documentation/translations/zh_TW/process/coding-style.rst958
-rw-r--r--Documentation/translations/zh_TW/process/development-process.rst30
-rw-r--r--Documentation/translations/zh_TW/process/email-clients.rst252
-rw-r--r--Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst232
-rw-r--r--Documentation/translations/zh_TW/process/howto.rst500
-rw-r--r--Documentation/translations/zh_TW/process/index.rst67
-rw-r--r--Documentation/translations/zh_TW/process/kernel-driver-statement.rst203
-rw-r--r--Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst155
-rw-r--r--Documentation/translations/zh_TW/process/license-rules.rst374
-rw-r--r--Documentation/translations/zh_TW/process/magic-number.rst148
-rw-r--r--Documentation/translations/zh_TW/process/management-style.rst211
-rw-r--r--Documentation/translations/zh_TW/process/programming-language.rst76
-rw-r--r--Documentation/translations/zh_TW/process/stable-api-nonsense.rst159
-rw-r--r--Documentation/translations/zh_TW/process/stable-kernel-rules.rst68
-rw-r--r--Documentation/translations/zh_TW/process/submit-checklist.rst109
-rw-r--r--Documentation/translations/zh_TW/process/submitting-drivers.rst164
-rw-r--r--Documentation/translations/zh_TW/process/submitting-patches.rst686
-rw-r--r--Documentation/translations/zh_TW/process/volatile-considered-harmful.rst110
-rw-r--r--Documentation/translations/zh_TW/sparse.txt91
-rw-r--r--Documentation/usb/gadget-testing.rst64
-rw-r--r--Documentation/userspace-api/media/cec.h.rst.exceptions2
-rw-r--r--Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst22
-rw-r--r--Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst29
-rw-r--r--Documentation/virt/kvm/api.rst68
-rw-r--r--Documentation/virt/kvm/locking.rst6
-rw-r--r--Documentation/vm/hwpoison.rst1
-rw-r--r--MAINTAINERS276
-rw-r--r--Makefile103
-rw-r--r--arch/Kconfig3
-rw-r--r--arch/alpha/Kconfig2
-rw-r--r--arch/alpha/include/uapi/asm/siginfo.h2
-rw-r--r--arch/alpha/kernel/osf_sys.c2
-rw-r--r--arch/alpha/kernel/pci_iommu.c10
-rw-r--r--arch/alpha/kernel/signal.c4
-rw-r--r--arch/alpha/kernel/srmcons.c8
-rw-r--r--arch/alpha/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/alpha/kernel/traps.c26
-rw-r--r--arch/alpha/mm/fault.c4
-rw-r--r--arch/arc/Kconfig45
-rw-r--r--arch/arc/Makefile3
-rw-r--r--arch/arc/include/asm/atomic-llsc.h97
-rw-r--r--arch/arc/include/asm/atomic-spinlock.h102
-rw-r--r--arch/arc/include/asm/atomic.h444
-rw-r--r--arch/arc/include/asm/atomic64-arcv2.h250
-rw-r--r--arch/arc/include/asm/bitops.h188
-rw-r--r--arch/arc/include/asm/cache.h4
-rw-r--r--arch/arc/include/asm/cmpxchg.h233
-rw-r--r--arch/arc/include/asm/entry-compact.h8
-rw-r--r--arch/arc/include/asm/hugepage.h8
-rw-r--r--arch/arc/include/asm/mmu-arcv2.h103
-rw-r--r--arch/arc/include/asm/mmu.h87
-rw-r--r--arch/arc/include/asm/mmu_context.h28
-rw-r--r--arch/arc/include/asm/page.h74
-rw-r--r--arch/arc/include/asm/pgalloc.h81
-rw-r--r--arch/arc/include/asm/pgtable-bits-arcv2.h149
-rw-r--r--arch/arc/include/asm/pgtable-levels.h189
-rw-r--r--arch/arc/include/asm/pgtable.h339
-rw-r--r--arch/arc/include/asm/processor.h2
-rw-r--r--arch/arc/include/asm/setup.h12
-rw-r--r--arch/arc/include/asm/smp.h14
-rw-r--r--arch/arc/include/asm/tlb-mmu1.h101
-rw-r--r--arch/arc/include/asm/uaccess.h72
-rw-r--r--arch/arc/kernel/entry-arcv2.S1
-rw-r--r--arch/arc/kernel/entry.S7
-rw-r--r--arch/arc/kernel/intc-compact.c2
-rw-r--r--arch/arc/kernel/smp.c4
-rw-r--r--arch/arc/kernel/stacktrace.c2
-rw-r--r--arch/arc/mm/cache.c112
-rw-r--r--arch/arc/mm/extable.c12
-rw-r--r--arch/arc/mm/fault.c20
-rw-r--r--arch/arc/mm/init.c5
-rw-r--r--arch/arc/mm/ioremap.c3
-rw-r--r--arch/arc/mm/tlb.c268
-rw-r--r--arch/arc/mm/tlbex.S84
-rw-r--r--arch/arm/Kconfig12
-rw-r--r--arch/arm/Kconfig.debug10
-rw-r--r--arch/arm/boot/dts/Makefile41
-rw-r--r--arch/arm/boot/dts/am335x-baltos-ir2110.dts10
-rw-r--r--arch/arm/boot/dts/am335x-baltos-ir3220.dts8
-rw-r--r--arch/arm/boot/dts/am335x-baltos-ir5221.dts8
-rw-r--r--arch/arm/boot/dts/am335x-baltos.dtsi5
-rw-r--r--arch/arm/boot/dts/am335x-bone-common.dtsi17
-rw-r--r--arch/arm/boot/dts/am335x-boneblack-common.dtsi135
-rw-r--r--arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi141
-rw-r--r--arch/arm/boot/dts/am335x-boneblack-wireless.dts3
-rw-r--r--arch/arm/boot/dts/am335x-boneblack.dts1
-rw-r--r--arch/arm/boot/dts/am335x-boneblue.dts143
-rw-r--r--arch/arm/boot/dts/am335x-bonegreen-wireless.dts2
-rw-r--r--arch/arm/boot/dts/am335x-chiliboard.dts13
-rw-r--r--arch/arm/boot/dts/am335x-cm-t335.dts13
-rw-r--r--arch/arm/boot/dts/am335x-evm.dts4
-rw-r--r--arch/arm/boot/dts/am335x-evmsk.dts4
-rw-r--r--arch/arm/boot/dts/am335x-icev2.dts4
-rw-r--r--arch/arm/boot/dts/am335x-igep0033.dtsi12
-rw-r--r--arch/arm/boot/dts/am335x-lxm.dts14
-rw-r--r--arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi12
-rw-r--r--arch/arm/boot/dts/am335x-moxa-uc-2101.dts7
-rw-r--r--arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi16
-rw-r--r--arch/arm/boot/dts/am335x-myirtech-myc.dtsi25
-rw-r--r--arch/arm/boot/dts/am335x-myirtech-myd.dts18
-rw-r--r--arch/arm/boot/dts/am335x-nano.dts13
-rw-r--r--arch/arm/boot/dts/am335x-netcan-plus-1xx.dts10
-rw-r--r--arch/arm/boot/dts/am335x-netcom-plus-2xx.dts10
-rw-r--r--arch/arm/boot/dts/am335x-netcom-plus-8xx.dts10
-rw-r--r--arch/arm/boot/dts/am335x-osd3358-sm-red.dts13
-rw-r--r--arch/arm/boot/dts/am335x-pcm-953.dtsi10
-rw-r--r--arch/arm/boot/dts/am335x-pdu001.dts14
-rw-r--r--arch/arm/boot/dts/am335x-pepper.dts14
-rw-r--r--arch/arm/boot/dts/am335x-phycore-som.dtsi14
-rw-r--r--arch/arm/boot/dts/am335x-regor.dtsi11
-rw-r--r--arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi67
-rw-r--r--arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts50
-rw-r--r--arch/arm/boot/dts/am335x-sancloud-bbe.dts96
-rw-r--r--arch/arm/boot/dts/am335x-shc.dts38
-rw-r--r--arch/arm/boot/dts/am335x-sl50.dts12
-rw-r--r--arch/arm/boot/dts/am335x-wega.dtsi11
-rw-r--r--arch/arm/boot/dts/am33xx-l4.dtsi82
-rw-r--r--arch/arm/boot/dts/am33xx.dtsi4
-rw-r--r--arch/arm/boot/dts/am4372.dtsi165
-rw-r--r--arch/arm/boot/dts/am437x-cm-t43.dts4
-rw-r--r--arch/arm/boot/dts/am437x-gp-evm.dts4
-rw-r--r--arch/arm/boot/dts/am437x-idk-evm.dts4
-rw-r--r--arch/arm/boot/dts/am437x-sk-evm.dts4
-rw-r--r--arch/arm/boot/dts/am43x-epos-evm.dts4
-rw-r--r--arch/arm/boot/dts/am57-pruss.dtsi178
-rw-r--r--arch/arm/boot/dts/am571x-idk.dts8
-rw-r--r--arch/arm/boot/dts/am572x-idk.dts8
-rw-r--r--arch/arm/boot/dts/am5748.dtsi6
-rw-r--r--arch/arm/boot/dts/am574x-idk.dts10
-rw-r--r--arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi8
-rw-r--r--arch/arm/boot/dts/am57xx-cl-som-am57x.dts8
-rw-r--r--arch/arm/boot/dts/aspeed-ast2500-evb.dts4
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts544
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts185
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts1251
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-galaxy100.dts4
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts8
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts5
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts4
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts48
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts6
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts2
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-inspur-nf5280m6.dts691
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts2
-rw-r--r--arch/arm/boot/dts/aspeed-g5.dtsi1
-rw-r--r--arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi4
-rw-r--r--arch/arm/boot/dts/aspeed-g6.dtsi28
-rw-r--r--arch/arm/boot/dts/ast2400-facebook-netbmc-common.dtsi4
-rw-r--r--arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi169
-rw-r--r--arch/arm/boot/dts/at91-kizbox3_common.dtsi2
-rw-r--r--arch/arm/boot/dts/at91-sam9x60ek.dts18
-rw-r--r--arch/arm/boot/dts/at91-sama5d27_som1.dtsi12
-rw-r--r--arch/arm/boot/dts/at91-sama5d27_som1_ek.dts6
-rw-r--r--arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dts2
-rw-r--r--arch/arm/boot/dts/at91-sama5d2_icp.dts8
-rw-r--r--arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts6
-rw-r--r--arch/arm/boot/dts/at91-sama5d2_xplained.dts16
-rw-r--r--arch/arm/boot/dts/at91-sama5d3_xplained.dts31
-rw-r--r--arch/arm/boot/dts/at91-sama5d4_xplained.dts32
-rw-r--r--arch/arm/boot/dts/at91-sama7g5ek.dts656
-rw-r--r--arch/arm/boot/dts/dm8148-evm.dts8
-rw-r--r--arch/arm/boot/dts/dm8168-evm.dts8
-rw-r--r--arch/arm/boot/dts/dra74x-p.dtsi27
-rw-r--r--arch/arm/boot/dts/dra76x.dtsi12
-rw-r--r--arch/arm/boot/dts/exynos3250.dtsi11
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi11
-rw-r--r--arch/arm/boot/dts/exynos4412.dtsi17
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi11
-rw-r--r--arch/arm/boot/dts/exynos5260.dtsi38
-rw-r--r--arch/arm/boot/dts/exynos5420-cpus.dtsi32
-rw-r--r--arch/arm/boot/dts/exynos5422-cpus.dtsi32
-rw-r--r--arch/arm/boot/dts/facebook-bmc-flash-layout-128.dtsi60
-rw-r--r--arch/arm/boot/dts/imx53-ppd.dts23
-rw-r--r--arch/arm/boot/dts/imx6dl-dhcom-picoitx.dts20
-rw-r--r--arch/arm/boot/dts/imx6dl-skov-revc-lt2.dts13
-rw-r--r--arch/arm/boot/dts/imx6dl-skov-revc-lt6.dts106
-rw-r--r--arch/arm/boot/dts/imx6dl-solidsense.dts54
-rw-r--r--arch/arm/boot/dts/imx6q-dhcom-pdk2.dts270
-rw-r--r--arch/arm/boot/dts/imx6q-skov-revc-lt2.dts36
-rw-r--r--arch/arm/boot/dts/imx6q-skov-revc-lt6.dts128
-rw-r--r--arch/arm/boot/dts/imx6q-skov-reve-mi1010ait-1cp1.dts127
-rw-r--r--arch/arm/boot/dts/imx6q-solidsense.dts54
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-dhcom-drc02.dtsi139
-rw-r--r--arch/arm/boot/dts/imx6qdl-dhcom-pdk2.dtsi361
-rw-r--r--arch/arm/boot/dts/imx6qdl-dhcom-picoitx.dtsi69
-rw-r--r--arch/arm/boot/dts/imx6qdl-dhcom-som.dtsi (renamed from arch/arm/boot/dts/imx6q-dhcom-som.dtsi)631
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw51xx.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw52xx.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw54xx.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw553x.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw5904.dtsi5
-rw-r--r--arch/arm/boot/dts/imx6qdl-skov-cpu-revc.dtsi54
-rw-r--r--arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi477
-rw-r--r--arch/arm/boot/dts/imx6qdl-solidsense.dtsi160
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi8
-rw-r--r--arch/arm/boot/dts/imx6qp-prtwd3.dts2
-rw-r--r--arch/arm/boot/dts/imx6s-dhcom-drc02.dts30
-rw-r--r--arch/arm/boot/dts/imx7d-remarkable2.dts91
-rw-r--r--arch/arm/boot/dts/imx7s.dtsi28
-rw-r--r--arch/arm/boot/dts/integratorap-im-pd1.dts4
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-adi-coyote.dts110
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-arcom-vulcan.dts167
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-dlink-dsm-g600.dts145
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-freecom-fsg-3.dts158
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-gateworks-gw2348.dts172
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-iomega-nas100d.dts146
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-ixdp425.dts72
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-ixdpg425.dts125
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts30
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-linksys-wrv54g.dts173
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-netgear-wg302v2.dts95
-rw-r--r--arch/arm/boot/dts/intel-ixp42x-welltech-epbx100.dts84
-rw-r--r--arch/arm/boot/dts/intel-ixp42x.dtsi5
-rw-r--r--arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts81
-rw-r--r--arch/arm/boot/dts/intel-ixp43x-kixrp435.dts68
-rw-r--r--arch/arm/boot/dts/intel-ixp43x.dtsi6
-rw-r--r--arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi11
-rw-r--r--arch/arm/boot/dts/intel-ixp46x-ixdp465.dts38
-rw-r--r--arch/arm/boot/dts/intel-ixp4xx-reference-design.dtsi132
-rw-r--r--arch/arm/boot/dts/intel-ixp4xx.dtsi44
-rw-r--r--arch/arm/boot/dts/keystone-k2e-netcp.dtsi2
-rw-r--r--arch/arm/boot/dts/keystone-k2hk-netcp.dtsi2
-rw-r--r--arch/arm/boot/dts/keystone-k2l-netcp.dtsi2
-rw-r--r--arch/arm/boot/dts/meson.dtsi12
-rw-r--r--arch/arm/boot/dts/meson8.dtsi68
-rw-r--r--arch/arm/boot/dts/meson8b-ec100.dts48
-rw-r--r--arch/arm/boot/dts/meson8b-mxq.dts4
-rw-r--r--arch/arm/boot/dts/meson8b-odroidc1.dts4
-rw-r--r--arch/arm/boot/dts/meson8b.dtsi63
-rw-r--r--arch/arm/boot/dts/mt7623.dtsi2
-rw-r--r--arch/arm/boot/dts/mt8135.dtsi2
-rw-r--r--arch/arm/boot/dts/nuvoton-npcm750-evb.dts4
-rw-r--r--arch/arm/boot/dts/omap4-l4-abe.dtsi38
-rw-r--r--arch/arm/boot/dts/owl-s500-roseapplepi.dts45
-rw-r--r--arch/arm/boot/dts/owl-s500.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom-apq8060-dragonboard.dts23
-rw-r--r--arch/arm/boot/dts/qcom-apq8064.dtsi30
-rw-r--r--arch/arm/boot/dts/qcom-ipq8064.dtsi20
-rw-r--r--arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts25
-rw-r--r--arch/arm/boot/dts/qcom-msm8226.dtsi147
-rw-r--r--arch/arm/boot/dts/qcom-msm8974-samsung-klte.dts11
-rw-r--r--arch/arm/boot/dts/qcom-msm8974-sony-xperia-castor.dts81
-rw-r--r--arch/arm/boot/dts/qcom-msm8974.dtsi9
-rw-r--r--arch/arm/boot/dts/qcom-sdx55.dtsi2
-rw-r--r--arch/arm/boot/dts/r7s72100.dtsi8
-rw-r--r--arch/arm/boot/dts/r7s9210.dtsi8
-rw-r--r--arch/arm/boot/dts/r8a73a4.dtsi44
-rw-r--r--arch/arm/boot/dts/r8a7742.dtsi4
-rw-r--r--arch/arm/boot/dts/r8a7743.dtsi4
-rw-r--r--arch/arm/boot/dts/r8a7744.dtsi4
-rw-r--r--arch/arm/boot/dts/rk3066a.dtsi10
-rw-r--r--arch/arm/boot/dts/rk3188.dtsi13
-rw-r--r--arch/arm/boot/dts/rk3288.dtsi6
-rw-r--r--arch/arm/boot/dts/rv1108.dtsi49
-rw-r--r--arch/arm/boot/dts/sama7g5-pinfunc.h923
-rw-r--r--arch/arm/boot/dts/sama7g5.dtsi528
-rw-r--r--arch/arm/boot/dts/ste-ab8500.dtsi36
-rw-r--r--arch/arm/boot/dts/ste-ab8505.dtsi30
-rw-r--r--arch/arm/boot/dts/ste-db8500.dtsi13
-rw-r--r--arch/arm/boot/dts/ste-db8520.dtsi13
-rw-r--r--arch/arm/boot/dts/ste-db9500.dtsi9
-rw-r--r--arch/arm/boot/dts/ste-dbx5x0-pinctrl.dtsi18
-rw-r--r--arch/arm/boot/dts/ste-href.dtsi4
-rw-r--r--arch/arm/boot/dts/ste-snowball.dts2
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-codina.dts863
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-gavini.dts854
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-golden.dts2
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-janice.dts4
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-kyle.dts664
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-skomer.dts2
-rw-r--r--arch/arm/boot/dts/stih407-b2120.dts1
-rw-r--r--arch/arm/boot/dts/stih407-clock.dtsi128
-rw-r--r--arch/arm/boot/dts/stih407-family.dtsi15
-rw-r--r--arch/arm/boot/dts/stih410-b2120.dts1
-rw-r--r--arch/arm/boot/dts/stih410-b2260.dts1
-rw-r--r--arch/arm/boot/dts/stih410-clock.dtsi138
-rw-r--r--arch/arm/boot/dts/stih418-b2199.dts1
-rw-r--r--arch/arm/boot/dts/stih418-b2264.dts151
-rw-r--r--arch/arm/boot/dts/stih418-clock.dtsi136
-rw-r--r--arch/arm/boot/dts/stih418.dtsi12
-rw-r--r--arch/arm/boot/dts/stm32429i-eval.dts2
-rw-r--r--arch/arm/boot/dts/stm32f469-disco.dts2
-rw-r--r--arch/arm/boot/dts/stm32mp157c-ed1.dts4
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dhcom-drc02.dtsi4
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi25
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi6
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dkx.dtsi12
-rw-r--r--arch/arm/boot/dts/tegra114-dalmore.dts2
-rw-r--r--arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra124-apalis.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra124-jetson-tk1.dts2
-rw-r--r--arch/arm/boot/dts/tegra124-nyan.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra20-acer-a500-picasso.dts90
-rw-r--r--arch/arm/boot/dts/tegra20-paz00.dts4
-rw-r--r--arch/arm/boot/dts/tegra20-tamonten.dtsi14
-rw-r--r--arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi60
-rw-r--r--arch/arm/boot/dts/tegra30-cardhu.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra30-ouya.dts13
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi87
-rw-r--r--arch/arm/boot/dts/vf610-zii-dev-rev-b.dts2
-rw-r--r--arch/arm/boot/dts/zynq-7000.dtsi21
-rw-r--r--arch/arm/boot/dts/zynq-ebaz4205.dts12
-rw-r--r--arch/arm/common/locomo.c3
-rw-r--r--arch/arm/common/sa1111.c4
-rw-r--r--arch/arm/configs/aspeed_g4_defconfig16
-rw-r--r--arch/arm/configs/aspeed_g5_defconfig25
-rw-r--r--arch/arm/configs/ep93xx_defconfig1
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig3
-rw-r--r--arch/arm/configs/multi_v7_defconfig8
-rw-r--r--arch/arm/configs/sama7_defconfig209
-rw-r--r--arch/arm/configs/tegra_defconfig25
-rw-r--r--arch/arm/include/asm/cacheflush.h4
-rw-r--r--arch/arm/include/asm/efi.h5
-rw-r--r--arch/arm/include/asm/fpstate.h8
-rw-r--r--arch/arm/include/asm/thread_info.h8
-rw-r--r--arch/arm/include/asm/ucontext.h14
-rw-r--r--arch/arm/include/uapi/asm/hwcap.h2
-rw-r--r--arch/arm/include/uapi/asm/ptrace.h4
-rw-r--r--arch/arm/kernel/asm-offsets.c3
-rw-r--r--arch/arm/kernel/entry-armv.S6
-rw-r--r--arch/arm/kernel/entry-v7m.S2
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/ptrace.c36
-rw-r--r--arch/arm/kernel/setup.c20
-rw-r--r--arch/arm/kernel/signal.c81
-rw-r--r--arch/arm/kernel/smp.c4
-rw-r--r--arch/arm/lib/backtrace-clang.S2
-rw-r--r--arch/arm/lib/backtrace.S2
-rw-r--r--arch/arm/mach-at91/Kconfig18
-rw-r--r--arch/arm/mach-at91/Makefile1
-rw-r--r--arch/arm/mach-at91/generic.h2
-rw-r--r--arch/arm/mach-at91/pm.c343
-rw-r--r--arch/arm/mach-at91/pm.h3
-rw-r--r--arch/arm/mach-at91/pm_data-offsets.c2
-rw-r--r--arch/arm/mach-at91/pm_suspend.S827
-rw-r--r--arch/arm/mach-at91/sama7.c33
-rw-r--r--arch/arm/mach-bcm/bcm_kona_smc.c2
-rw-r--r--arch/arm/mach-ep93xx/Kconfig5
-rw-r--r--arch/arm/mach-ep93xx/Makefile3
-rw-r--r--arch/arm/mach-ep93xx/adssphere.c1
-rw-r--r--arch/arm/mach-ep93xx/core.c5
-rw-r--r--arch/arm/mach-ep93xx/crunch-bits.S310
-rw-r--r--arch/arm/mach-ep93xx/crunch.c86
-rw-r--r--arch/arm/mach-ep93xx/edb93xx.c8
-rw-r--r--arch/arm/mach-ep93xx/gesbc9312.c1
-rw-r--r--arch/arm/mach-ep93xx/micro9.c4
-rw-r--r--arch/arm/mach-ep93xx/platform.h7
-rw-r--r--arch/arm/mach-ep93xx/simone.c1
-rw-r--r--arch/arm/mach-ep93xx/snappercl15.c1
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c2
-rw-r--r--arch/arm/mach-ep93xx/vision_ep9307.c1
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig158
-rw-r--r--arch/arm/mach-ixp4xx/Makefile26
-rw-r--r--arch/arm/mach-ixp4xx/avila-pci.c79
-rw-r--r--arch/arm/mach-ixp4xx/avila-setup.c210
-rw-r--r--arch/arm/mach-ixp4xx/coyote-pci.c62
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c144
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-pci.c77
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c304
-rw-r--r--arch/arm/mach-ixp4xx/fsg-pci.c73
-rw-r--r--arch/arm/mach-ixp4xx/fsg-setup.c311
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-pci.c72
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c167
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c75
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c339
-rw-r--r--arch/arm/mach-ixp4xx/ixdpg425-pci.c56
-rw-r--r--arch/arm/mach-ixp4xx/miccpt-pci.c75
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-pci.c73
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c353
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-pci.c69
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c341
-rw-r--r--arch/arm/mach-ixp4xx/omixp-setup.c298
-rw-r--r--arch/arm/mach-ixp4xx/vulcan-pci.c70
-rw-r--r--arch/arm/mach-ixp4xx/vulcan-setup.c282
-rw-r--r--arch/arm/mach-ixp4xx/wg302v2-pci.c60
-rw-r--r--arch/arm/mach-ixp4xx/wg302v2-setup.c114
-rw-r--r--arch/arm/mach-omap2/Kconfig23
-rw-r--r--arch/arm/mach-omap2/pm34xx.c5
-rw-r--r--arch/arm/mach-rpc/ecard.c4
-rw-r--r--arch/arm/mach-rpc/io-acorn.S2
-rw-r--r--arch/arm/mach-s3c/mach-gta02.c3
-rw-r--r--arch/arm/mach-tegra/board-paz00.c2
-rw-r--r--arch/arm/mach-tegra/pm.c2
-rw-r--r--arch/arm/mach-tegra/pm.h6
-rw-r--r--arch/arm/mach-tegra/tegra.c2
-rw-r--r--arch/arm/mm/dma-mapping-nommu.c173
-rw-r--r--arch/arm/mm/dma-mapping.c26
-rw-r--r--arch/arm/mm/flush.c33
-rw-r--r--arch/arm/mm/nommu.c6
-rw-r--r--arch/arm/tools/syscall.tbl4
-rw-r--r--arch/arm/vfp/vfphw.S6
-rw-r--r--arch/arm64/Kbuild1
-rw-r--r--arch/arm64/Kconfig6
-rw-r--r--arch/arm64/Makefile7
-rw-r--r--arch/arm64/boot/Makefile8
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts27
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts13
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi61
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts2
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts3
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts61
-rw-r--r--arch/arm64/boot/dts/exynos/exynos5433.dtsi102
-rw-r--r--arch/arm64/boot/dts/exynos/exynos7.dtsi37
-rw-r--r--arch/arm64/boot/dts/freescale/Makefile4
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts8
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts7
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts9
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts389
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi18
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi80
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi64
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi5
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts15
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts911
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm.dtsi9
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts884
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp.dtsi31
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-evk.dts14
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-mnt-reform2.dts213
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-nitrogen-som.dtsi275
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq.dtsi105
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi12
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi13
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp.dtsi4
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi3660.dtsi2
-rw-r--r--arch/arm64/boot/dts/marvell/Makefile5
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts17
-rw-r--r--arch/arm64/boot/dts/marvell/armada-37xx.dtsi11
-rw-r--r--arch/arm64/boot/dts/marvell/armada-7040-db.dts2
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts2
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-db.dts4
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-crb-A.dts38
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-crb-B.dts46
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-crb.dtsi222
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-db-B.dts22
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-db.dts403
-rw-r--r--arch/arm64/boot/dts/marvell/cn9130-db.dtsi410
-rw-r--r--arch/arm64/boot/dts/marvell/cn9131-db-B.dts22
-rw-r--r--arch/arm64/boot/dts/marvell/cn9131-db.dts197
-rw-r--r--arch/arm64/boot/dts/marvell/cn9131-db.dtsi206
-rw-r--r--arch/arm64/boot/dts/marvell/cn9132-db-B.dts22
-rw-r--r--arch/arm64/boot/dts/marvell/cn9132-db.dts218
-rw-r--r--arch/arm64/boot/dts/marvell/cn9132-db.dtsi227
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi10
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-evb.dts4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173.dtsi2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183.dtsi4
-rw-r--r--arch/arm64/boot/dts/nvidia/Makefile1
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra132.dtsi4
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra186-p3509-0000+p3636-0001.dts718
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra186.dtsi91
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi2
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra194.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/Makefile9
-rw-r--r--arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts8
-rw-r--r--arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts8
-rw-r--r--arch/arm64/boot/dts/qcom/ipq6018.dtsi157
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074-hk01.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074.dtsi54
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-mtp.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts313
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916.dtsi27
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-dora.dts11
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-kagura.dts11
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-keyaki.dts11
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-dora.dts27
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-kagura.dts15
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-keyaki.dts26
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi956
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-v3.0.dtsi63
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi44
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/pm660.dtsi133
-rw-r--r--arch/arm64/boot/dts/qcom/pm660l.dtsi54
-rw-r--r--arch/arm64/boot/dts/qcom/pm8004.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150b.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/pmi8996.dtsi15
-rw-r--r--arch/arm64/boot/dts/qcom/sa8155p-adp.dts60
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi62
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180.dtsi102
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-idp.dts241
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-idp.dtsi341
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-idp2.dts23
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280.dtsi419
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges-kirin.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges.dtsi40
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-discovery.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-pioneer.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-voyager.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi527
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630.dtsi1441
-rw-r--r--arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/sdm636.dtsi23
-rw-r--r--arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm660.dtsi519
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-mtp.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi11
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi35
-rw-r--r--arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts5
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts139
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125.dtsi566
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-mtp.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150.dtsi797
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250.dtsi217
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-hdk.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-mtp.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350.dtsi53
-rw-r--r--arch/arm64/boot/dts/renesas/Makefile8
-rw-r--r--arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi8
-rw-r--r--arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774a1.dtsi4
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774b1.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774c0.dtsi8
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77950-salvator-x.dts73
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77950-ulcb-kf.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77950-ulcb.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77950.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77951-salvator-x.dts73
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77951-salvator-xs.dts122
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77951-ulcb-kf.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77951-ulcb.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77951.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77960-ulcb-kf.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77960-ulcb.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77961-ulcb-kf.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77961-ulcb.dts3
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77961.dtsi29
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts14
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965-ulcb-kf.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965-ulcb.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970-eagle.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980-condor.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts50
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990.dtsi6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77995-draak.dts169
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77995.dtsi158
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779a0.dtsi26
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779m1-salvator-xs.dts53
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779m1-ulcb-kf.dts19
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779m1-ulcb.dts54
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779m1.dtsi12
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779m3-salvator-xs.dts46
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779m3-ulcb-kf.dts18
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779m3-ulcb.dts45
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779m3.dtsi12
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g044.dtsi184
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-common.dtsi76
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-xs.dtsi56
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-main.dtsi114
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-evm.dts56
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-sk.dts64
-rw-r--r--arch/arm64/configs/defconfig1
-rw-r--r--arch/arm64/hyperv/Makefile2
-rw-r--r--arch/arm64/hyperv/hv_core.c181
-rw-r--r--arch/arm64/hyperv/mshyperv.c87
-rw-r--r--arch/arm64/include/asm/cpufeature.h29
-rw-r--r--arch/arm64/include/asm/efi.h5
-rw-r--r--arch/arm64/include/asm/el2_setup.h13
-rw-r--r--arch/arm64/include/asm/elf.h6
-rw-r--r--arch/arm64/include/asm/exception.h5
-rw-r--r--arch/arm64/include/asm/fpsimd.h1
-rw-r--r--arch/arm64/include/asm/fpsimdmacros.h1
-rw-r--r--arch/arm64/include/asm/hwcap.h2
-rw-r--r--arch/arm64/include/asm/hyperv-tlfs.h69
-rw-r--r--arch/arm64/include/asm/kernel-pgtable.h4
-rw-r--r--arch/arm64/include/asm/kvm_arm.h54
-rw-r--r--arch/arm64/include/asm/kvm_asm.h7
-rw-r--r--arch/arm64/include/asm/kvm_host.h17
-rw-r--r--arch/arm64/include/asm/kvm_hyp.h2
-rw-r--r--arch/arm64/include/asm/kvm_mmu.h17
-rw-r--r--arch/arm64/include/asm/kvm_pgtable.h168
-rw-r--r--arch/arm64/include/asm/memory.h2
-rw-r--r--arch/arm64/include/asm/mmu.h29
-rw-r--r--arch/arm64/include/asm/mmu_context.h13
-rw-r--r--arch/arm64/include/asm/mshyperv.h54
-rw-r--r--arch/arm64/include/asm/mte-kasan.h17
-rw-r--r--arch/arm64/include/asm/mte.h6
-rw-r--r--arch/arm64/include/asm/pgtable.h2
-rw-r--r--arch/arm64/include/asm/pointer_auth.h12
-rw-r--r--arch/arm64/include/asm/processor.h10
-rw-r--r--arch/arm64/include/asm/simd.h2
-rw-r--r--arch/arm64/include/asm/sysreg.h73
-rw-r--r--arch/arm64/include/asm/tlbflush.h13
-rw-r--r--arch/arm64/include/asm/unistd.h2
-rw-r--r--arch/arm64/include/asm/unistd32.h4
-rw-r--r--arch/arm64/kernel/asm-offsets.c2
-rw-r--r--arch/arm64/kernel/cpufeature.c66
-rw-r--r--arch/arm64/kernel/efi.c1
-rw-r--r--arch/arm64/kernel/entry-common.c219
-rw-r--r--arch/arm64/kernel/entry-fpsimd.S13
-rw-r--r--arch/arm64/kernel/entry.S114
-rw-r--r--arch/arm64/kernel/fpsimd.c14
-rw-r--r--arch/arm64/kernel/head.S11
-rw-r--r--arch/arm64/kernel/idreg-override.c2
-rw-r--r--arch/arm64/kernel/mte.c180
-rw-r--r--arch/arm64/kernel/perf_event.c2
-rw-r--r--arch/arm64/kernel/pointer_auth.c10
-rw-r--r--arch/arm64/kernel/process.c81
-rw-r--r--arch/arm64/kernel/ptrace.c5
-rw-r--r--arch/arm64/kernel/signal.c73
-rw-r--r--arch/arm64/kernel/signal32.c45
-rw-r--r--arch/arm64/kernel/suspend.c1
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S4
-rw-r--r--arch/arm64/kvm/Kconfig10
-rw-r--r--arch/arm64/kvm/arm.c161
-rw-r--r--arch/arm64/kvm/debug.c2
-rw-r--r--arch/arm64/kvm/guest.c9
-rw-r--r--arch/arm64/kvm/handle_exit.c43
-rw-r--r--arch/arm64/kvm/hyp/include/hyp/switch.h6
-rw-r--r--arch/arm64/kvm/hyp/include/nvhe/mem_protect.h35
-rw-r--r--arch/arm64/kvm/hyp/include/nvhe/mm.h3
-rw-r--r--arch/arm64/kvm/hyp/include/nvhe/spinlock.h25
-rw-r--r--arch/arm64/kvm/hyp/nvhe/debug-sr.c2
-rw-r--r--arch/arm64/kvm/hyp/nvhe/host.S21
-rw-r--r--arch/arm64/kvm/hyp/nvhe/hyp-main.c20
-rw-r--r--arch/arm64/kvm/hyp/nvhe/mem_protect.c244
-rw-r--r--arch/arm64/kvm/hyp/nvhe/mm.c22
-rw-r--r--arch/arm64/kvm/hyp/nvhe/setup.c82
-rw-r--r--arch/arm64/kvm/hyp/nvhe/switch.c17
-rw-r--r--arch/arm64/kvm/hyp/nvhe/tlb.c4
-rw-r--r--arch/arm64/kvm/hyp/pgtable.c247
-rw-r--r--arch/arm64/kvm/hyp/reserved_mem.c9
-rw-r--r--arch/arm64/kvm/hyp/vhe/debug-sr.c2
-rw-r--r--arch/arm64/kvm/hyp/vhe/switch.c18
-rw-r--r--arch/arm64/kvm/hyp/vhe/sysreg-sr.c2
-rw-r--r--arch/arm64/kvm/hyp/vhe/tlb.c4
-rw-r--r--arch/arm64/kvm/mmu.c76
-rw-r--r--arch/arm64/kvm/perf.c2
-rw-r--r--arch/arm64/kvm/pmu-emul.c14
-rw-r--r--arch/arm64/kvm/psci.c15
-rw-r--r--arch/arm64/kvm/reset.c43
-rw-r--r--arch/arm64/kvm/sys_regs.c134
-rw-r--r--arch/arm64/kvm/sys_regs.h31
-rw-r--r--arch/arm64/kvm/trace_handle_exit.h10
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio-v2.c4
-rw-r--r--arch/arm64/kvm/vgic/vgic-v2.c36
-rw-r--r--arch/arm64/kvm/vgic/vgic-v3.c36
-rw-r--r--arch/arm64/kvm/vgic/vgic.c39
-rw-r--r--arch/arm64/kvm/vgic/vgic.h2
-rw-r--r--arch/arm64/lib/insn.c4
-rw-r--r--arch/arm64/mm/fault.c15
-rw-r--r--arch/arm64/mm/init.c124
-rw-r--r--arch/arm64/mm/proc.S3
-rw-r--r--arch/csky/Kconfig4
-rw-r--r--arch/csky/abiv1/cacheflush.c11
-rw-r--r--arch/csky/abiv1/inc/abi/cacheflush.h4
-rw-r--r--arch/csky/include/asm/uaccess.h6
-rw-r--r--arch/csky/kernel/probes/kprobes.c3
-rw-r--r--arch/csky/lib/usercopy.c102
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c2
-rw-r--r--arch/h8300/lib/Makefile2
-rw-r--r--arch/h8300/lib/strncpy.S35
-rw-r--r--arch/hexagon/Kconfig5
-rw-r--r--arch/hexagon/include/asm/uaccess.h31
-rw-r--r--arch/hexagon/kernel/dma.c57
-rw-r--r--arch/hexagon/kernel/hexagon_ksyms.c1
-rw-r--r--arch/hexagon/mm/Makefile2
-rw-r--r--arch/hexagon/mm/strnlen_user.S126
-rw-r--r--arch/ia64/Kbuild2
-rw-r--r--arch/ia64/Kconfig2
-rw-r--r--arch/ia64/Makefile2
-rw-r--r--arch/ia64/hp/common/sba_iommu.c4
-rw-r--r--arch/ia64/include/asm/meminit.h2
-rw-r--r--arch/ia64/include/uapi/asm/cmpxchg.h4
-rw-r--r--arch/ia64/kernel/acpi.c2
-rw-r--r--arch/ia64/kernel/setup.c53
-rw-r--r--arch/ia64/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/m68k/Kconfig2
-rw-r--r--arch/m68k/Kconfig.bus2
-rw-r--r--arch/m68k/Kconfig.machine1
-rw-r--r--arch/m68k/coldfire/clk.c2
-rw-r--r--arch/m68k/coldfire/device.c44
-rw-r--r--arch/m68k/coldfire/m5441x.c8
-rw-r--r--arch/m68k/coldfire/stmark2.c6
-rw-r--r--arch/m68k/emu/nfcon.c30
-rw-r--r--arch/m68k/fpsp040/skeleton.S3
-rw-r--r--arch/m68k/include/asm/m5441xsim.h19
-rw-r--r--arch/m68k/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/m68k/kernel/traps.c2
-rw-r--r--arch/microblaze/Kconfig1
-rw-r--r--arch/microblaze/Kconfig.debug5
-rw-r--r--arch/microblaze/include/asm/page.h3
-rw-r--r--arch/microblaze/include/asm/pgtable.h2
-rw-r--r--arch/microblaze/include/asm/uaccess.h21
-rw-r--r--arch/microblaze/kernel/microblaze_ksyms.c1
-rw-r--r--arch/microblaze/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/microblaze/lib/uaccess_old.S90
-rw-r--r--arch/microblaze/mm/init.c12
-rw-r--r--arch/microblaze/mm/pgtable.c17
-rw-r--r--arch/mips/Kbuild.platforms1
-rw-r--r--arch/mips/Kconfig33
-rw-r--r--arch/mips/Kconfig.debug4
-rw-r--r--arch/mips/Makefile5
-rw-r--r--arch/mips/alchemy/devboards/db1200.c2
-rw-r--r--arch/mips/boot/dts/Makefile2
-rw-r--r--arch/mips/boot/dts/img/Makefile3
-rw-r--r--arch/mips/boot/dts/img/pistachio.dtsi10
-rw-r--r--arch/mips/boot/dts/mscc/ocelot.dtsi11
-rw-r--r--arch/mips/boot/dts/mscc/ocelot_pcb120.dts12
-rw-r--r--arch/mips/boot/dts/mscc/ocelot_pcb123.dts8
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-bootmem.c10
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c33
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-board.c8
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-rgmii.c12
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c8
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-interrupt-decodes.c17
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-l2c.c9
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-pko.c22
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-spi.c20
-rw-r--r--arch/mips/cavium-octeon/flash_setup.c2
-rw-r--r--arch/mips/cavium-octeon/setup.c81
-rw-r--r--arch/mips/cavium-octeon/smp.c14
-rw-r--r--arch/mips/configs/generic/board-marduk.config53
-rw-r--r--arch/mips/configs/pistachio_defconfig316
-rw-r--r--arch/mips/generic/Kconfig6
-rw-r--r--arch/mips/generic/Platform1
-rw-r--r--arch/mips/generic/board-ingenic.c49
-rw-r--r--arch/mips/generic/board-marduk.its.S22
-rw-r--r--arch/mips/generic/board-ocelot.c6
-rw-r--r--arch/mips/include/asm/asm.h2
-rw-r--r--arch/mips/include/asm/atomic.h2
-rw-r--r--arch/mips/include/asm/bootinfo.h3
-rw-r--r--arch/mips/include/asm/cacheflush.h8
-rw-r--r--arch/mips/include/asm/cpu.h4
-rw-r--r--arch/mips/include/uapi/asm/siginfo.h2
-rw-r--r--arch/mips/jazz/jazzdma.c2
-rw-r--r--arch/mips/kernel/mips-mt-fpaff.c10
-rw-r--r--arch/mips/kernel/process.c4
-rw-r--r--arch/mips/kernel/setup.c14
-rw-r--r--arch/mips/kernel/syscalls/syscall_n32.tbl2
-rw-r--r--arch/mips/kernel/syscalls/syscall_n64.tbl2
-rw-r--r--arch/mips/kernel/syscalls/syscall_o32.tbl4
-rw-r--r--arch/mips/kernel/uprobes.c10
-rw-r--r--arch/mips/kvm/Makefile19
-rw-r--r--arch/mips/kvm/mips.c4
-rw-r--r--arch/mips/kvm/mmu.c4
-rw-r--r--arch/mips/kvm/vz.c3
-rw-r--r--arch/mips/loongson2ef/common/Makefile4
-rw-r--r--arch/mips/mm/c-octeon.c29
-rw-r--r--arch/mips/mti-malta/malta-dtshim.c2
-rw-r--r--arch/mips/netlogic/xlr/fmn-config.c15
-rw-r--r--arch/mips/pistachio/Kconfig14
-rw-r--r--arch/mips/pistachio/Makefile2
-rw-r--r--arch/mips/pistachio/Platform6
-rw-r--r--arch/mips/pistachio/init.c125
-rw-r--r--arch/mips/pistachio/irq.c24
-rw-r--r--arch/mips/pistachio/time.c55
-rw-r--r--arch/mips/sgi-ip22/ip22-gio.c3
-rw-r--r--arch/nds32/Kconfig6
-rw-r--r--arch/nds32/include/asm/cacheflush.h3
-rw-r--r--arch/nds32/mm/cacheflush.c9
-rw-r--r--arch/nios2/Kconfig5
-rw-r--r--arch/openrisc/Kconfig6
-rw-r--r--arch/openrisc/boot/dts/or1klitex.dts13
-rw-r--r--arch/openrisc/configs/or1klitex_defconfig26
-rw-r--r--arch/openrisc/include/asm/pgtable.h6
-rw-r--r--arch/openrisc/include/asm/setup.h15
-rw-r--r--arch/openrisc/include/asm/thread_info.h2
-rw-r--r--arch/openrisc/kernel/entry.S12
-rw-r--r--arch/openrisc/kernel/head.S6
-rw-r--r--arch/openrisc/kernel/process.c2
-rw-r--r--arch/openrisc/kernel/setup.c20
-rw-r--r--arch/openrisc/lib/Makefile2
-rw-r--r--arch/openrisc/mm/fault.c2
-rw-r--r--arch/parisc/Kbuild1
-rw-r--r--arch/parisc/Kconfig3
-rw-r--r--arch/parisc/Kconfig.debug3
-rw-r--r--arch/parisc/Makefile9
-rw-r--r--arch/parisc/boot/Makefile4
-rw-r--r--arch/parisc/boot/compressed/misc.c2
-rw-r--r--arch/parisc/boot/install.sh65
-rw-r--r--arch/parisc/include/asm/cacheflush.h8
-rw-r--r--arch/parisc/include/asm/parisc-device.h4
-rw-r--r--arch/parisc/include/asm/pgalloc.h6
-rw-r--r--arch/parisc/include/asm/pgtable.h4
-rw-r--r--arch/parisc/include/uapi/asm/swab.h68
-rw-r--r--arch/parisc/kernel/cache.c3
-rw-r--r--arch/parisc/kernel/drivers.c5
-rw-r--r--arch/parisc/kernel/firmware.c2
-rw-r--r--arch/parisc/kernel/pdc_cons.c34
-rw-r--r--arch/parisc/kernel/process.c3
-rw-r--r--arch/parisc/kernel/signal.c6
-rw-r--r--arch/parisc/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/parisc/math-emu/decode_exc.c4
-rw-r--r--arch/parisc/math-emu/fpudispatch.c56
-rw-r--r--arch/parisc/mm/init.c4
-rw-r--r--arch/powerpc/Kconfig9
-rw-r--r--arch/powerpc/Kconfig.debug30
-rw-r--r--arch/powerpc/Makefile4
-rw-r--r--arch/powerpc/boot/Makefile11
-rw-r--r--arch/powerpc/boot/dts/fsl/sbc8641d.dts176
-rw-r--r--arch/powerpc/boot/dts/microwatt.dts12
-rw-r--r--arch/powerpc/boot/dts/sbc8548-altflash.dts111
-rw-r--r--arch/powerpc/boot/dts/sbc8548-post.dtsi289
-rw-r--r--arch/powerpc/boot/dts/sbc8548-pre.dtsi48
-rw-r--r--arch/powerpc/boot/dts/sbc8548.dts106
-rw-r--r--arch/powerpc/boot/dts/wii.dts13
-rw-r--r--arch/powerpc/boot/install.sh27
-rwxr-xr-xarch/powerpc/boot/wrapper2
-rw-r--r--arch/powerpc/configs/85xx/sbc8548_defconfig50
-rw-r--r--arch/powerpc/configs/microwatt_defconfig7
-rw-r--r--arch/powerpc/configs/mpc85xx_base.config1
-rw-r--r--arch/powerpc/configs/mpc86xx_base.config1
-rw-r--r--arch/powerpc/configs/mpc885_ads_defconfig49
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig1
-rw-r--r--arch/powerpc/configs/wii_defconfig1
-rw-r--r--arch/powerpc/include/asm/asm-compat.h4
-rw-r--r--arch/powerpc/include/asm/atomic.h4
-rw-r--r--arch/powerpc/include/asm/bitops.h8
-rw-r--r--arch/powerpc/include/asm/book3s/64/kup.h2
-rw-r--r--arch/powerpc/include/asm/bug.h62
-rw-r--r--arch/powerpc/include/asm/debugfs.h13
-rw-r--r--arch/powerpc/include/asm/drmem.h1
-rw-r--r--arch/powerpc/include/asm/extable.h14
-rw-r--r--arch/powerpc/include/asm/firmware.h7
-rw-r--r--arch/powerpc/include/asm/iommu.h1
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h1
-rw-r--r--arch/powerpc/include/asm/kvm_host.h3
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h4
-rw-r--r--arch/powerpc/include/asm/membarrier.h3
-rw-r--r--arch/powerpc/include/asm/mmu.h2
-rw-r--r--arch/powerpc/include/asm/pci-bridge.h5
-rw-r--r--arch/powerpc/include/asm/pmc.h7
-rw-r--r--arch/powerpc/include/asm/pnv-pci.h2
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h2
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h13
-rw-r--r--arch/powerpc/include/asm/prom.h3
-rw-r--r--arch/powerpc/include/asm/ptrace.h37
-rw-r--r--arch/powerpc/include/asm/reg.h3
-rw-r--r--arch/powerpc/include/asm/sections.h8
-rw-r--r--arch/powerpc/include/asm/simple_spinlock.h6
-rw-r--r--arch/powerpc/include/asm/smp.h6
-rw-r--r--arch/powerpc/include/asm/syscall.h20
-rw-r--r--arch/powerpc/include/asm/syscalls.h30
-rw-r--r--arch/powerpc/include/asm/tce.h8
-rw-r--r--arch/powerpc/include/asm/topology.h19
-rw-r--r--arch/powerpc/include/asm/unistd.h2
-rw-r--r--arch/powerpc/include/asm/vdso/processor.h9
-rw-r--r--arch/powerpc/include/asm/xics.h3
-rw-r--r--arch/powerpc/include/asm/xive-regs.h3
-rw-r--r--arch/powerpc/include/asm/xive.h2
-rw-r--r--arch/powerpc/kernel/Makefile3
-rw-r--r--arch/powerpc/kernel/asm-offsets.c15
-rw-r--r--arch/powerpc/kernel/cacheinfo.c124
-rw-r--r--arch/powerpc/kernel/dawr.c3
-rw-r--r--arch/powerpc/kernel/eeh.c16
-rw-r--r--arch/powerpc/kernel/eeh_cache.c4
-rw-r--r--arch/powerpc/kernel/entry_32.S4
-rw-r--r--arch/powerpc/kernel/entry_64.S2
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S24
-rw-r--r--arch/powerpc/kernel/fadump.c4
-rw-r--r--arch/powerpc/kernel/fpu.S3
-rw-r--r--arch/powerpc/kernel/fsl_booke_entry_mapping.S8
-rw-r--r--arch/powerpc/kernel/head_44x.S6
-rw-r--r--arch/powerpc/kernel/head_64.S2
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S8
-rw-r--r--arch/powerpc/kernel/hw_breakpoint.c1
-rw-r--r--arch/powerpc/kernel/interrupt.c12
-rw-r--r--arch/powerpc/kernel/iommu.c67
-rw-r--r--arch/powerpc/kernel/kdebugfs.c14
-rw-r--r--arch/powerpc/kernel/misc.S2
-rw-r--r--arch/powerpc/kernel/misc_32.S4
-rw-r--r--arch/powerpc/kernel/misc_64.S2
-rw-r--r--arch/powerpc/kernel/pci-common.c6
-rw-r--r--arch/powerpc/kernel/process.c2
-rw-r--r--arch/powerpc/kernel/prom.c6
-rw-r--r--arch/powerpc/kernel/prom_init.c5
-rw-r--r--arch/powerpc/kernel/ptrace/ptrace.c4
-rw-r--r--arch/powerpc/kernel/reloc_32.S2
-rw-r--r--arch/powerpc/kernel/rtas.c2
-rw-r--r--arch/powerpc/kernel/rtasd.c4
-rw-r--r--arch/powerpc/kernel/security.c16
-rw-r--r--arch/powerpc/kernel/setup-common.c13
-rw-r--r--arch/powerpc/kernel/setup_64.c1
-rw-r--r--arch/powerpc/kernel/smp.c88
-rw-r--r--arch/powerpc/kernel/stacktrace.c1
-rw-r--r--arch/powerpc/kernel/syscalls.c15
-rw-r--r--arch/powerpc/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/powerpc/kernel/tau_6xx.c2
-rw-r--r--arch/powerpc/kernel/time.c3
-rw-r--r--arch/powerpc/kernel/traps.c24
-rw-r--r--arch/powerpc/kernel/udbg.c2
-rw-r--r--arch/powerpc/kernel/vector.S4
-rw-r--r--arch/powerpc/kernel/watchdog.c5
-rw-r--r--arch/powerpc/kexec/core_64.c10
-rw-r--r--arch/powerpc/kexec/crash.c2
-rw-r--r--arch/powerpc/kexec/relocate_32.S12
-rw-r--r--arch/powerpc/kvm/Kconfig1
-rw-r--r--arch/powerpc/kvm/book3s.c5
-rw-r--r--arch/powerpc/kvm/book3s.h3
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu.c3
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_radix.c12
-rw-r--r--arch/powerpc/kvm/book3s_64_vio.c2
-rw-r--r--arch/powerpc/kvm/book3s_64_vio_hv.c11
-rw-r--r--arch/powerpc/kvm/book3s_hv.c126
-rw-r--r--arch/powerpc/kvm/book3s_hv_builtin.c10
-rw-r--r--arch/powerpc/kvm/book3s_hv_nested.c101
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_xics.c8
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S42
-rw-r--r--arch/powerpc/kvm/book3s_hv_tm.c61
-rw-r--r--arch/powerpc/kvm/book3s_xics.c6
-rw-r--r--arch/powerpc/kvm/book3s_xive.c74
-rw-r--r--arch/powerpc/kvm/book3s_xive.h11
-rw-r--r--arch/powerpc/kvm/book3s_xive_native.c24
-rw-r--r--arch/powerpc/kvm/booke.c5
-rw-r--r--arch/powerpc/mm/Makefile2
-rw-r--r--arch/powerpc/mm/book3s64/hash_native.c2
-rw-r--r--arch/powerpc/mm/book3s64/hash_utils.c4
-rw-r--r--arch/powerpc/mm/book3s64/pgtable.c8
-rw-r--r--arch/powerpc/mm/book3s64/radix_pgtable.c3
-rw-r--r--arch/powerpc/mm/book3s64/radix_tlb.c16
-rw-r--r--arch/powerpc/mm/book3s64/slb.c2
-rw-r--r--arch/powerpc/mm/drmem.c46
-rw-r--r--arch/powerpc/mm/mmu_decl.h2
-rw-r--r--arch/powerpc/mm/nohash/tlb_low.S4
-rw-r--r--arch/powerpc/mm/numa.c491
-rw-r--r--arch/powerpc/mm/ptdump/8xx.c6
-rw-r--r--arch/powerpc/mm/ptdump/Makefile9
-rw-r--r--arch/powerpc/mm/ptdump/bats.c18
-rw-r--r--arch/powerpc/mm/ptdump/book3s64.c6
-rw-r--r--arch/powerpc/mm/ptdump/hashpagetable.c12
-rw-r--r--arch/powerpc/mm/ptdump/ptdump.c178
-rw-r--r--arch/powerpc/mm/ptdump/segment_regs.c16
-rw-r--r--arch/powerpc/mm/ptdump/shared.c6
-rw-r--r--arch/powerpc/perf/core-book3s.c21
-rw-r--r--arch/powerpc/perf/hv-gpci.c2
-rw-r--r--arch/powerpc/platforms/44x/machine_check.c4
-rw-r--r--arch/powerpc/platforms/4xx/machine_check.c2
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig6
-rw-r--r--arch/powerpc/platforms/85xx/Makefile1
-rw-r--r--arch/powerpc/platforms/85xx/sbc8548.c134
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig8
-rw-r--r--arch/powerpc/platforms/86xx/Makefile1
-rw-r--r--arch/powerpc/platforms/86xx/sbc8641d.c87
-rw-r--r--arch/powerpc/platforms/cell/axon_msi.c4
-rw-r--r--arch/powerpc/platforms/embedded6xx/holly.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c2
-rw-r--r--arch/powerpc/platforms/pasemi/idle.c2
-rw-r--r--arch/powerpc/platforms/powernv/idle.c6
-rw-r--r--arch/powerpc/platforms/powernv/memtrace.c3
-rw-r--r--arch/powerpc/platforms/powernv/opal-imc.c12
-rw-r--r--arch/powerpc/platforms/powernv/opal-lpc.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal-xscom.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal.c2
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c260
-rw-r--r--arch/powerpc/platforms/powernv/pci.c67
-rw-r--r--arch/powerpc/platforms/powernv/pci.h6
-rw-r--r--arch/powerpc/platforms/ps3/htab.c3
-rw-r--r--arch/powerpc/platforms/ps3/mm.c8
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c5
-rw-r--r--arch/powerpc/platforms/pseries/dtl.c4
-rw-r--r--arch/powerpc/platforms/pseries/firmware.c3
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c173
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c10
-rw-r--r--arch/powerpc/platforms/pseries/ibmebus.c3
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c514
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c18
-rw-r--r--arch/powerpc/platforms/pseries/msi.c296
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c4
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h2
-rw-r--r--arch/powerpc/platforms/pseries/ras.c2
-rw-r--r--arch/powerpc/platforms/pseries/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/svm.c6
-rw-r--r--arch/powerpc/platforms/pseries/vas.c2
-rw-r--r--arch/powerpc/platforms/pseries/vio.c8
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c2
-rw-r--r--arch/powerpc/sysdev/xics/ics-native.c13
-rw-r--r--arch/powerpc/sysdev/xics/ics-opal.c40
-rw-r--r--arch/powerpc/sysdev/xics/ics-rtas.c40
-rw-r--r--arch/powerpc/sysdev/xics/xics-common.c131
-rw-r--r--arch/powerpc/sysdev/xive/common.c103
-rw-r--r--arch/powerpc/sysdev/xive/native.c10
-rw-r--r--arch/powerpc/tools/head_check.sh24
-rw-r--r--arch/powerpc/xmon/xmon.c22
-rw-r--r--arch/riscv/Kconfig18
-rw-r--r--arch/riscv/Makefile8
-rw-r--r--arch/riscv/include/asm/efi.h5
-rw-r--r--arch/riscv/include/asm/page.h21
-rw-r--r--arch/riscv/include/asm/processor.h8
-rw-r--r--arch/riscv/include/asm/vdso.h23
-rw-r--r--arch/riscv/kernel/probes/decode-insn.c5
-rw-r--r--arch/riscv/kernel/probes/simulate-insn.c112
-rw-r--r--arch/riscv/kernel/setup.c2
-rw-r--r--arch/riscv/kernel/vdso/Makefile26
-rwxr-xr-xarch/riscv/kernel/vdso/gen_vdso_offsets.sh5
-rwxr-xr-xarch/riscv/kernel/vdso/so2s.sh6
-rw-r--r--arch/riscv/mm/init.c194
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/Kconfig.debug3
-rw-r--r--arch/s390/Makefile14
-rw-r--r--arch/s390/boot/pgm_check_info.c2
-rw-r--r--arch/s390/include/asm/eadm.h2
-rw-r--r--arch/s390/include/asm/kvm_host.h10
-rw-r--r--arch/s390/include/asm/uaccess.h18
-rw-r--r--arch/s390/kernel/setup.c9
-rw-r--r--arch/s390/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/s390/kvm/interrupt.c12
-rw-r--r--arch/s390/kvm/kvm-s390.c44
-rw-r--r--arch/s390/kvm/kvm-s390.h2
-rw-r--r--arch/s390/kvm/priv.c15
-rw-r--r--arch/s390/kvm/vsie.c2
-rw-r--r--arch/s390/lib/uaccess.c52
-rw-r--r--arch/s390/mm/init.c2
-rw-r--r--arch/s390/pci/pci_dma.c13
-rw-r--r--arch/sh/Kconfig3
-rw-r--r--arch/sh/Kconfig.debug3
-rw-r--r--arch/sh/boot/compressed/install.sh56
-rw-r--r--arch/sh/include/asm/cacheflush.h8
-rw-r--r--arch/sh/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc/Kconfig.debug4
-rw-r--r--arch/sparc/Makefile3
-rw-r--r--arch/sparc/boot/Makefile4
-rw-r--r--arch/sparc/include/uapi/asm/siginfo.h3
-rw-r--r--arch/sparc/kernel/iommu.c6
-rw-r--r--arch/sparc/kernel/pci_sun4v.c6
-rw-r--r--arch/sparc/kernel/process_32.c3
-rw-r--r--arch/sparc/kernel/process_64.c5
-rw-r--r--arch/sparc/kernel/signal32.c37
-rw-r--r--arch/sparc/kernel/signal_64.c36
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c2
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c2
-rw-r--r--arch/sparc/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/sparc/kernel/traps_32.c22
-rw-r--r--arch/sparc/kernel/traps_64.c44
-rw-r--r--arch/sparc/kernel/unaligned_32.c2
-rw-r--r--arch/sparc/kernel/vio.c4
-rw-r--r--arch/sparc/mm/fault_32.c2
-rw-r--r--arch/sparc/mm/fault_64.c2
-rw-r--r--arch/sparc/mm/iommu.c2
-rw-r--r--arch/um/Kconfig7
-rw-r--r--arch/um/Makefile6
-rw-r--r--arch/um/drivers/line.c13
-rw-r--r--arch/um/drivers/rtc_user.c1
-rw-r--r--arch/um/drivers/vector_user.c1
-rw-r--r--arch/um/include/asm/uaccess.h5
-rw-r--r--arch/um/include/shared/irq_user.h1
-rw-r--r--arch/um/include/shared/os.h1
-rw-r--r--arch/um/include/shared/user.h3
-rw-r--r--arch/um/kernel/skas/uaccess.c14
-rw-r--r--arch/um/os-Linux/signal.c2
-rw-r--r--arch/um/os-Linux/util.c1
-rw-r--r--arch/x86/Kconfig29
-rw-r--r--arch/x86/Kconfig.debug3
-rw-r--r--arch/x86/Makefile2
-rw-r--r--arch/x86/Makefile_32.cpu6
-rw-r--r--arch/x86/boot/boot.h2
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl3
-rw-r--r--arch/x86/entry/syscalls/syscall_64.tbl1
-rw-r--r--arch/x86/entry/vdso/Makefile2
-rw-r--r--arch/x86/hyperv/hv_init.c165
-rw-r--r--arch/x86/ia32/ia32_aout.c8
-rw-r--r--arch/x86/include/asm/hyperv-tlfs.h9
-rw-r--r--arch/x86/include/asm/kvm-x86-ops.h1
-rw-r--r--arch/x86/include/asm/kvm_host.h96
-rw-r--r--arch/x86/include/asm/mshyperv.h4
-rw-r--r--arch/x86/include/uapi/asm/kvm.h1
-rw-r--r--arch/x86/kernel/Makefile3
-rw-r--r--arch/x86/kernel/amd_gart_64.c18
-rw-r--r--arch/x86/kernel/aperture_64.c5
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c38
-rw-r--r--arch/x86/kernel/head_32.S2
-rw-r--r--arch/x86/kernel/kvm.c5
-rw-r--r--arch/x86/kernel/ldt.c6
-rw-r--r--arch/x86/kernel/setup.c1
-rw-r--r--arch/x86/kernel/signal_compat.c6
-rw-r--r--arch/x86/kvm/debugfs.c111
-rw-r--r--arch/x86/kvm/hyperv.c32
-rw-r--r--arch/x86/kvm/i8254.c3
-rw-r--r--arch/x86/kvm/ioapic.h4
-rw-r--r--arch/x86/kvm/lapic.c26
-rw-r--r--arch/x86/kvm/mmu.h25
-rw-r--r--arch/x86/kvm/mmu/mmu.c524
-rw-r--r--arch/x86/kvm/mmu/mmu_audit.c4
-rw-r--r--arch/x86/kvm/mmu/mmu_internal.h18
-rw-r--r--arch/x86/kvm/mmu/mmutrace.h6
-rw-r--r--arch/x86/kvm/mmu/page_track.c1
-rw-r--r--arch/x86/kvm/mmu/paging_tmpl.h6
-rw-r--r--arch/x86/kvm/mmu/tdp_mmu.c139
-rw-r--r--arch/x86/kvm/mmu/tdp_mmu.h29
-rw-r--r--arch/x86/kvm/pmu.c5
-rw-r--r--arch/x86/kvm/pmu.h2
-rw-r--r--arch/x86/kvm/svm/avic.c49
-rw-r--r--arch/x86/kvm/svm/nested.c5
-rw-r--r--arch/x86/kvm/svm/sev.c3
-rw-r--r--arch/x86/kvm/svm/svm.c97
-rw-r--r--arch/x86/kvm/svm/svm.h8
-rw-r--r--arch/x86/kvm/svm/svm_ops.h2
-rw-r--r--arch/x86/kvm/vmx/evmcs.c1
-rw-r--r--arch/x86/kvm/vmx/evmcs.h4
-rw-r--r--arch/x86/kvm/vmx/nested.c56
-rw-r--r--arch/x86/kvm/vmx/pmu_intel.c4
-rw-r--r--arch/x86/kvm/vmx/vmcs.h2
-rw-r--r--arch/x86/kvm/vmx/vmcs12.c1
-rw-r--r--arch/x86/kvm/vmx/vmcs12.h4
-rw-r--r--arch/x86/kvm/vmx/vmx.c333
-rw-r--r--arch/x86/kvm/vmx/vmx.h38
-rw-r--r--arch/x86/kvm/vmx/vmx_ops.h4
-rw-r--r--arch/x86/kvm/x86.c189
-rw-r--r--arch/x86/kvm/x86.h2
-rw-r--r--arch/x86/kvm/xen.c23
-rw-r--r--arch/x86/kvm/xen.h5
-rw-r--r--arch/x86/mm/init.c23
-rw-r--r--arch/x86/mm/numa.c5
-rw-r--r--arch/x86/mm/numa_emulation.c5
-rw-r--r--arch/x86/realmode/init.c2
-rw-r--r--arch/x86/xen/enlighten_pv.c12
-rw-r--r--arch/x86/xen/mmu_pv.c4
-rw-r--r--arch/x86/xen/p2m.c4
-rw-r--r--arch/x86/xen/platform-pci-unplug.c16
-rw-r--r--arch/x86/xen/smp_pv.c1
-rw-r--r--arch/xtensa/Kbuild1
-rw-r--r--arch/xtensa/Kconfig9
-rw-r--r--arch/xtensa/Makefile12
-rw-r--r--arch/xtensa/include/asm/uaccess.h3
-rw-r--r--arch/xtensa/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/xtensa/kernel/traps.c7
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c2
-rw-r--r--arch/xtensa/platforms/Makefile4
-rw-r--r--arch/xtensa/platforms/iss/console.c51
-rw-r--r--block/Kconfig26
-rw-r--r--block/Makefile3
-rw-r--r--block/bfq-iosched.c16
-rw-r--r--block/bio.c2
-rw-r--r--block/blk-map.c2
-rw-r--r--block/blk-mq.c2
-rw-r--r--block/bsg-lib.c90
-rw-r--r--block/bsg.c463
-rw-r--r--block/mq-deadline.c12
-rw-r--r--block/scsi_ioctl.c890
-rw-r--r--drivers/accessibility/speakup/i18n.c14
-rw-r--r--drivers/accessibility/speakup/speakup_soft.c15
-rw-r--r--drivers/acpi/acpi_lpss.c10
-rw-r--r--drivers/acpi/bus.c3
-rw-r--r--drivers/acpi/tables.c5
-rw-r--r--drivers/amba/bus.c4
-rw-r--r--drivers/android/binder.c4
-rw-r--r--drivers/android/binderfs.c39
-rw-r--r--drivers/ata/libata-core.c34
-rw-r--r--drivers/ata/libata-eh.c5
-rw-r--r--drivers/ata/libata-scsi.c10
-rw-r--r--drivers/ata/pata_falcon.c4
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c264
-rw-r--r--drivers/base/arch_numa.c5
-rw-r--r--drivers/base/auxiliary.c4
-rw-r--r--drivers/base/bus.c6
-rw-r--r--drivers/base/cacheinfo.c1
-rw-r--r--drivers/base/core.c12
-rw-r--r--drivers/base/cpu.c4
-rw-r--r--drivers/base/dd.c16
-rw-r--r--drivers/base/firmware_loader/main.c20
-rw-r--r--drivers/base/isa.c4
-rw-r--r--drivers/base/map.c12
-rw-r--r--drivers/base/memory.c4
-rw-r--r--drivers/base/node.c71
-rw-r--r--drivers/base/platform.c24
-rw-r--r--drivers/base/power/clock_ops.c17
-rw-r--r--drivers/base/power/runtime.c17
-rw-r--r--drivers/base/power/wakeup.c2
-rw-r--r--drivers/base/topology.c115
-rw-r--r--drivers/bcma/main.c6
-rw-r--r--drivers/block/Kconfig3
-rw-r--r--drivers/block/loop.c75
-rw-r--r--drivers/block/loop.h1
-rw-r--r--drivers/block/paride/Kconfig1
-rw-r--r--drivers/block/xen-blkback/xenbus.c1
-rw-r--r--drivers/block/xen-blkfront.c126
-rw-r--r--drivers/bus/Kconfig11
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-bus.c134
-rw-r--r--drivers/bus/intel-ixp4xx-eb.c429
-rw-r--r--drivers/bus/mhi/core/boot.c17
-rw-r--r--drivers/bus/mhi/core/init.c93
-rw-r--r--drivers/bus/mhi/core/internal.h20
-rw-r--r--drivers/bus/mhi/core/main.c6
-rw-r--r--drivers/bus/mhi/core/pm.c34
-rw-r--r--drivers/bus/mhi/pci_generic.c38
-rw-r--r--drivers/bus/sunxi-rsb.c4
-rw-r--r--drivers/bus/ti-sysc.c17
-rw-r--r--drivers/cdrom/cdrom.c78
-rw-r--r--drivers/char/Kconfig4
-rw-r--r--drivers/char/ipmi/ipmi_si.h2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c6
-rw-r--r--drivers/char/ipmi/ipmi_si_parisc.c4
-rw-r--r--drivers/char/ipmi/ipmi_si_platform.c4
-rw-r--r--drivers/char/mwave/tp3780i.c4
-rw-r--r--drivers/char/pcmcia/synclink_cs.c4
-rw-r--r--drivers/char/ttyprintk.c4
-rw-r--r--drivers/clk/Kconfig1
-rw-r--r--drivers/clk/Makefile2
-rw-r--r--drivers/clk/at91/clk-generated.c6
-rw-r--r--drivers/clk/at91/sama7g5.c14
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c9
-rw-r--r--drivers/clk/clk-divider.c23
-rw-r--r--drivers/clk/clk-fractional-divider.c56
-rw-r--r--drivers/clk/clk-fractional-divider.h15
-rw-r--r--drivers/clk/clk-lmk04832.c18
-rw-r--r--drivers/clk/clk-palmas.c10
-rw-r--r--drivers/clk/clk-stm32f4.c8
-rw-r--r--drivers/clk/clk-stm32h7.c8
-rw-r--r--drivers/clk/clk-stm32mp1.c10
-rw-r--r--drivers/clk/clk-versaclock5.c42
-rw-r--r--drivers/clk/imx/clk-composite-7ulp.c1
-rw-r--r--drivers/clk/imx/clk-composite-8m.c3
-rw-r--r--drivers/clk/imx/clk-divider-gate.c10
-rw-r--r--drivers/clk/imx/clk-imx8mm.c11
-rw-r--r--drivers/clk/imx/clk-imx8mn.c16
-rw-r--r--drivers/clk/imx/clk-imx8mq.c7
-rw-r--r--drivers/clk/imx/clk.h16
-rw-r--r--drivers/clk/mediatek/Kconfig105
-rw-r--r--drivers/clk/mediatek/Makefile13
-rw-r--r--drivers/clk/mediatek/clk-cpumux.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-aud.c118
-rw-r--r--drivers/clk/mediatek/clk-mt8192-cam.c107
-rw-r--r--drivers/clk/mediatek/clk-mt8192-img.c70
-rw-r--r--drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c119
-rw-r--r--drivers/clk/mediatek/clk-mt8192-ipe.c57
-rw-r--r--drivers/clk/mediatek/clk-mt8192-mdp.c82
-rw-r--r--drivers/clk/mediatek/clk-mt8192-mfg.c50
-rw-r--r--drivers/clk/mediatek/clk-mt8192-mm.c108
-rw-r--r--drivers/clk/mediatek/clk-mt8192-msdc.c85
-rw-r--r--drivers/clk/mediatek/clk-mt8192-scp_adsp.c50
-rw-r--r--drivers/clk/mediatek/clk-mt8192-vdec.c94
-rw-r--r--drivers/clk/mediatek/clk-mt8192-venc.c53
-rw-r--r--drivers/clk/mediatek/clk-mt8192.c1326
-rw-r--r--drivers/clk/mediatek/clk-mtk.c25
-rw-r--r--drivers/clk/mediatek/clk-mtk.h28
-rw-r--r--drivers/clk/mediatek/clk-mux.c11
-rw-r--r--drivers/clk/mediatek/clk-mux.h18
-rw-r--r--drivers/clk/mediatek/clk-pll.c31
-rw-r--r--drivers/clk/mediatek/reset.c2
-rw-r--r--drivers/clk/mvebu/kirkwood.c1
-rw-r--r--drivers/clk/pistachio/Kconfig8
-rw-r--r--drivers/clk/qcom/Kconfig60
-rw-r--r--drivers/clk/qcom/Makefile7
-rw-r--r--drivers/clk/qcom/a53-pll.c68
-rw-r--r--drivers/clk/qcom/apcs-msm8916.c10
-rw-r--r--drivers/clk/qcom/camcc-sc7180.c25
-rw-r--r--drivers/clk/qcom/clk-rpmh.c21
-rw-r--r--drivers/clk/qcom/clk-smd-rpm.c158
-rw-r--r--drivers/clk/qcom/dispcc-sc7280.c908
-rw-r--r--drivers/clk/qcom/dispcc-sm8250.c22
-rw-r--r--drivers/clk/qcom/gcc-msm8953.c4250
-rw-r--r--drivers/clk/qcom/gcc-sdm660.c504
-rw-r--r--drivers/clk/qcom/gcc-sm6115.c3544
-rw-r--r--drivers/clk/qcom/gcc-sm6350.c2588
-rw-r--r--drivers/clk/qcom/gpucc-sc7280.c491
-rw-r--r--drivers/clk/qcom/gpucc-sm8150.c12
-rw-r--r--drivers/clk/qcom/lpass-gfm-sm8250.c21
-rw-r--r--drivers/clk/qcom/lpasscorecc-sc7180.c18
-rw-r--r--drivers/clk/qcom/mmcc-msm8994.c2620
-rw-r--r--drivers/clk/qcom/mss-sc7180.c30
-rw-r--r--drivers/clk/qcom/q6sstop-qcs404.c32
-rw-r--r--drivers/clk/qcom/turingcc-qcs404.c30
-rw-r--r--drivers/clk/qcom/videocc-sc7280.c325
-rw-r--r--drivers/clk/ralink/clk-mt7621.c9
-rw-r--r--drivers/clk/renesas/Kconfig4
-rw-r--r--drivers/clk/renesas/Makefile2
-rw-r--r--drivers/clk/renesas/r8a774a1-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a774b1-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a774c0-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a774e1-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a779a0-cpg-mssr.c5
-rw-r--r--drivers/clk/renesas/r9a07g044-cpg.c72
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c (renamed from drivers/clk/renesas/renesas-rzg2l-cpg.c)22
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.h (renamed from drivers/clk/renesas/renesas-rzg2l-cpg.h)0
-rw-r--r--drivers/clk/rockchip/clk-pll.c2
-rw-r--r--drivers/clk/rockchip/clk-rk3036.c5
-rw-r--r--drivers/clk/rockchip/clk-rk3308.c1
-rw-r--r--drivers/clk/rockchip/clk.c17
-rw-r--r--drivers/clk/socfpga/clk-agilex.c19
-rw-r--r--drivers/clk/tegra/clk-dfll.c2
-rw-r--r--drivers/clk/tegra/clk-tegra-periph.c6
-rw-r--r--drivers/clk/ux500/u8500_of_clk.c3
-rw-r--r--drivers/clk/x86/Makefile2
-rw-r--r--drivers/clk/x86/clk-lpss-atom.c (renamed from drivers/clk/x86/clk-lpt.c)12
-rw-r--r--drivers/clk/zynqmp/clk-gate-zynqmp.c4
-rw-r--r--drivers/clk/zynqmp/clk-mux-zynqmp.c2
-rw-r--r--drivers/clk/zynqmp/clk-zynqmp.h1
-rw-r--r--drivers/clk/zynqmp/clkc.c4
-rw-r--r--drivers/clocksource/Kconfig3
-rw-r--r--drivers/clocksource/hyperv_timer.c3
-rw-r--r--drivers/clocksource/timer-ixp4xx.c48
-rw-r--r--drivers/counter/104-quad-8.c47
-rw-r--r--drivers/counter/counter.c50
-rw-r--r--drivers/counter/ftm-quaddec.c5
-rw-r--r--drivers/counter/intel-qep.c7
-rw-r--r--drivers/counter/interrupt-cnt.c11
-rw-r--r--drivers/counter/microchip-tcb-capture.c16
-rw-r--r--drivers/counter/stm32-lptimer-cnt.c18
-rw-r--r--drivers/counter/stm32-timer-cnt.c10
-rw-r--r--drivers/counter/ti-eqep.c37
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c16
-rw-r--r--drivers/cpuidle/cpuidle-pseries.c77
-rw-r--r--drivers/cpuidle/cpuidle-ux500.c2
-rw-r--r--drivers/cxl/core.c3
-rw-r--r--drivers/dax/bus.c4
-rw-r--r--drivers/dio/dio.c2
-rw-r--r--drivers/dma-buf/Kconfig11
-rw-r--r--drivers/dma-buf/Makefile1
-rw-r--r--drivers/dma-buf/dma-buf-sysfs-stats.c205
-rw-r--r--drivers/dma-buf/dma-buf-sysfs-stats.h35
-rw-r--r--drivers/dma-buf/dma-buf.c26
-rw-r--r--drivers/dma-buf/dma-fence-chain.c2
-rw-r--r--drivers/dma-buf/dma-resv.c33
-rw-r--r--drivers/dma-buf/st-dma-fence-chain.c16
-rw-r--r--drivers/dma-buf/udmabuf.c59
-rw-r--r--drivers/dma/idxd/sysfs.c4
-rw-r--r--drivers/dma/imx-sdma.c93
-rw-r--r--drivers/firewire/core-device.c4
-rw-r--r--drivers/firmware/Kconfig68
-rw-r--r--drivers/firmware/Makefile5
-rw-r--r--drivers/firmware/arm_scmi/Kconfig95
-rw-r--r--drivers/firmware/arm_scmi/Makefile8
-rw-r--r--drivers/firmware/arm_scmi/bus.c4
-rw-r--r--drivers/firmware/arm_scmi/common.h113
-rw-r--r--drivers/firmware/arm_scmi/driver.c686
-rw-r--r--drivers/firmware/arm_scmi/mailbox.c2
-rw-r--r--drivers/firmware/arm_scmi/msg.c111
-rw-r--r--drivers/firmware/arm_scmi/smc.c3
-rw-r--r--drivers/firmware/arm_scmi/virtio.c491
-rw-r--r--drivers/firmware/dmi-id.c6
-rw-r--r--drivers/firmware/efi/Makefile2
-rw-r--r--drivers/firmware/efi/efi-init.c90
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c2
-rw-r--r--drivers/firmware/efi/libstub/vsprintf.c2
-rw-r--r--drivers/firmware/efi/sysfb_efi.c (renamed from arch/x86/kernel/sysfb_efi.c)80
-rw-r--r--drivers/firmware/google/coreboot_table.c4
-rw-r--r--drivers/firmware/iscsi_ibft.c24
-rw-r--r--drivers/firmware/qcom_scm.c8
-rw-r--r--drivers/firmware/raspberrypi.c10
-rw-r--r--drivers/firmware/sysfb.c (renamed from arch/x86/kernel/sysfb.c)37
-rw-r--r--drivers/firmware/sysfb_simplefb.c (renamed from arch/x86/kernel/sysfb_simplefb.c)33
-rw-r--r--drivers/firmware/tegra/bpmp-debugfs.c58
-rw-r--r--drivers/firmware/xilinx/zynqmp.c23
-rw-r--r--drivers/fpga/Kconfig11
-rw-r--r--drivers/fpga/Makefile1
-rw-r--r--drivers/fpga/altera-cvp.c2
-rw-r--r--drivers/fpga/altera-freeze-bridge.c2
-rw-r--r--drivers/fpga/dfl-fme-mgr.c6
-rw-r--r--drivers/fpga/dfl-fme-pr.c2
-rw-r--r--drivers/fpga/dfl-n3000-nios.c2
-rw-r--r--drivers/fpga/dfl-pci.c5
-rw-r--r--drivers/fpga/dfl.c31
-rw-r--r--drivers/fpga/dfl.h3
-rw-r--r--drivers/fpga/fpga-bridge.c8
-rw-r--r--drivers/fpga/fpga-mgr.c111
-rw-r--r--drivers/fpga/stratix10-soc.c6
-rw-r--r--drivers/fpga/ts73xx-fpga.c6
-rw-r--r--drivers/fpga/versal-fpga.c83
-rw-r--r--drivers/fpga/xilinx-pr-decoupler.c2
-rw-r--r--drivers/fpga/xilinx-spi.c2
-rw-r--r--drivers/fpga/zynq-fpga.c6
-rw-r--r--drivers/fpga/zynqmp-fpga.c10
-rw-r--r--drivers/gpio/Kconfig15
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/gpio-aspeed-sgpio.c178
-rw-r--r--drivers/gpio/gpio-brcmstb.c45
-rw-r--r--drivers/gpio/gpio-dwapb.c56
-rw-r--r--drivers/gpio/gpio-mc9s08dz60.c112
-rw-r--r--drivers/gpio/gpio-ml-ioh.c49
-rw-r--r--drivers/gpio/gpio-mlxbf2.c43
-rw-r--r--drivers/gpio/gpio-mpc8xxx.c13
-rw-r--r--drivers/gpio/gpio-mt7621.c1
-rw-r--r--drivers/gpio/gpio-rcar.c4
-rw-r--r--drivers/gpio/gpio-tegra186.c30
-rw-r--r--drivers/gpio/gpio-viperboard.c14
-rw-r--r--drivers/gpio/gpio-virtio.c374
-rw-r--r--drivers/gpio/gpiolib-devres.c2
-rw-r--r--drivers/gpio/gpiolib-of.c16
-rw-r--r--drivers/gpio/gpiolib.c32
-rw-r--r--drivers/gpu/drm/Kconfig8
-rw-r--r--drivers/gpu/drm/Makefile3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c54
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c84
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c33
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c38
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c72
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c167
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c65
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c239
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h37
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c144
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c32
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c26
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c117
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h72
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pll.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c1115
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h165
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c120
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c1279
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h70
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c118
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c102
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c92
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h81
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c643
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h26
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c167
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c140
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_crtc.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c51
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_virtual.c780
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c161
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c32
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mca_v3_0.c125
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mca_v3_0.h26
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c38
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nv.c47
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nv.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v10_0.c40
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0.c77
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c208
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.h (renamed from drivers/gpu/drm/amd/amdgpu/dce_virtual.h)10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v12_0.c28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v13_0.c126
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v3_1.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c324
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15_common.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v6_7.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v6_7.h15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v2_0.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v4_0.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c23
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c47
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c17
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c59
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c60
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c1
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c84
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h1
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c5
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c10
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.c217
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.h5
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.h1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/Makefile4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c372
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h27
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c18
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c16
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c23
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h24
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c144
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h34
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c62
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c118
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c127
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stat.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c109
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h120
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dp_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_helper.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_stat.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_trace.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h83
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_aux.c200
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c53
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h33
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c51
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c90
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c37
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c49
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c33
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/Makefile4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c102
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c393
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h25
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq_types.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/os_types.h35
-rw-r--r--drivers/gpu/drm/amd/display/dmub/dmub_srv.h18
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h60
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c38
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h10
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c17
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c75
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h10
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c6
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c8
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c3
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c4
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c74
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h72
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c109
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h13
-rw-r--r--drivers/gpu/drm/amd/include/amd_shared.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h4
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_offset.h4
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_sh_mask.h54
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mp/mp_11_0_8_offset.h352
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h6
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h3
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h179
-rw-r--r--drivers/gpu/drm/amd/include/cyan_skillfish_ip_offset.h714
-rw-r--r--drivers/gpu/drm/amd/include/kgd_kfd_interface.h3
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h4
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c48
-rw-r--r--drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h9
-rw-r--r--drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h33
-rw-r--r--drivers/gpu/drm/amd/pm/inc/hwmgr.h6
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h95
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h65
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_types.h2
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v11_0.h16
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h152
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h70
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c16
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c24
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c46
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c21
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c7
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c44
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c18
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c14
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c80
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c30
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/si_dpm.c19
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c99
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile1
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c446
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c76
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.h (renamed from include/drm/drm_irq.h)19
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c262
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c561
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c135
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c46
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c20
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c289
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c102
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c14
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c292
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h3
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_kms.c5
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c174
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.h1
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c4
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c4
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c2
-rw-r--r--drivers/gpu/drm/armada/armada_plane.c29
-rw-r--r--drivers/gpu/drm/armada/armada_plane.h2
-rw-r--r--drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c1
-rw-r--r--drivers/gpu/drm/ast/ast_drv.c2
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h6
-rw-r--r--drivers/gpu/drm/ast/ast_main.c5
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c54
-rw-r--r--drivers/gpu/drm/ast/ast_post.c91
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c80
-rw-r--r--drivers/gpu/drm/bochs/Kconfig11
-rw-r--r--drivers/gpu/drm/bochs/Makefile4
-rw-r--r--drivers/gpu/drm/bochs/bochs.h98
-rw-r--r--drivers/gpu/drm/bochs/bochs_drv.c205
-rw-r--r--drivers/gpu/drm/bochs/bochs_hw.c323
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c178
-rw-r--r--drivers/gpu/drm/bochs/bochs_mm.c24
-rw-r--r--drivers/gpu/drm/bridge/Kconfig1
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7533.c2
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c9
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.c36
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.h4
-rw-r--r--drivers/gpu/drm/bridge/cdns-dsi.c4
-rw-r--r--drivers/gpu/drm/bridge/ite-it66121.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt8912b.c2
-rw-r--r--drivers/gpu/drm/bridge/nwl-dsi.c8
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c55
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c68
-rw-r--r--drivers/gpu/drm/bridge/tc358768.c4
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi83.c200
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c760
-rw-r--r--drivers/gpu/drm/drm_aperture.c21
-rw-r--r--drivers/gpu/drm/drm_atomic.c4
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c20
-rw-r--r--drivers/gpu/drm/drm_atomic_uapi.c6
-rw-r--r--drivers/gpu/drm/drm_auth.c96
-rw-r--r--drivers/gpu/drm/drm_bridge.c12
-rw-r--r--drivers/gpu/drm/drm_bufs.c2
-rw-r--r--drivers/gpu/drm/drm_cache.c2
-rw-r--r--drivers/gpu/drm/drm_connector.c5
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h2
-rw-r--r--drivers/gpu/drm/drm_damage_helper.c58
-rw-r--r--drivers/gpu/drm/drm_debugfs.c3
-rw-r--r--drivers/gpu/drm/drm_debugfs_crc.c8
-rw-r--r--drivers/gpu/drm/drm_dp_aux_bus.c323
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c470
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c10
-rw-r--r--drivers/gpu/drm/drm_drv.c4
-rw-r--r--drivers/gpu/drm/drm_dsc.c2
-rw-r--r--drivers/gpu/drm/drm_edid.c4
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c2
-rw-r--r--drivers/gpu/drm/drm_file.c7
-rw-r--r--drivers/gpu/drm/drm_format_helper.c2
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c24
-rw-r--r--drivers/gpu/drm/drm_gem.c38
-rw-r--r--drivers/gpu/drm/drm_gem_atomic_helper.c97
-rw-r--r--drivers/gpu/drm/drm_gem_framebuffer_helper.c199
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c6
-rw-r--r--drivers/gpu/drm/drm_gem_vram_helper.c11
-rw-r--r--drivers/gpu/drm/drm_hdcp.c2
-rw-r--r--drivers/gpu/drm/drm_ioctl.c4
-rw-r--r--drivers/gpu/drm/drm_irq.c104
-rw-r--r--drivers/gpu/drm/drm_lease.c263
-rw-r--r--drivers/gpu/drm/drm_legacy_misc.c3
-rw-r--r--drivers/gpu/drm/drm_mipi_dbi.c75
-rw-r--r--drivers/gpu/drm/drm_mm.c2
-rw-r--r--drivers/gpu/drm/drm_mode_object.c2
-rw-r--r--drivers/gpu/drm/drm_modes.c4
-rw-r--r--drivers/gpu/drm/drm_of.c6
-rw-r--r--drivers/gpu/drm/drm_plane.c106
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c2
-rw-r--r--drivers/gpu/drm/drm_prime.c17
-rw-r--r--drivers/gpu/drm/drm_print.c2
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c2
-rw-r--r--drivers/gpu/drm/drm_property.c2
-rw-r--r--drivers/gpu/drm/drm_scdc_helper.c2
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c51
-rw-r--r--drivers/gpu/drm/drm_syncobj.c8
-rw-r--r--drivers/gpu/drm/drm_vblank.c27
-rw-r--r--drivers/gpu/drm/drm_vma_manager.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c14
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.h3
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem.c18
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c13
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_hwdb.c31
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_sched.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp.c5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dma.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c10
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c14
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c5
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c78
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_lvds.c6
-rw-r--r--drivers/gpu/drm/gma500/power.c1
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c8
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h5
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.c26
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.h4
-rw-r--r--drivers/gpu/drm/gud/gud_drv.c61
-rw-r--r--drivers/gpu/drm/gud/gud_internal.h2
-rw-r--r--drivers/gpu/drm/gud/gud_pipe.c86
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c3
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c15
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c9
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c2
-rw-r--r--drivers/gpu/drm/hyperv/hyperv_drm_drv.c4
-rw-r--r--drivers/gpu/drm/hyperv/hyperv_drm_modeset.c4
-rw-r--r--drivers/gpu/drm/i810/i810_dma.c3
-rw-r--r--drivers/gpu/drm/i915/Kconfig.debug6
-rw-r--r--drivers/gpu/drm/i915/Makefile15
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.c2
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c46
-rw-r--r--drivers/gpu/drm/i915/display/intel_acpi.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_acpi.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c178
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c107
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_combo_phy.c106
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_cursor.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c630
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c2475
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h70
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c385
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c118
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c568
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.h15
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h34
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c232
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.h23
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c65
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c329
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c43
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c631
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c219
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbdev.c96
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.c25
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c53
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_opregion.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c265
-rw-r--r--drivers/gpu/drm/i915/display/intel_quirks.c34
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.c862
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.h35
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c34
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.c13
-rw-r--r--drivers/gpu/drm/i915/display/intel_vbt_defs.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_vga.c12
-rw-r--r--drivers/gpu/drm/i915/display/skl_scaler.c49
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c28
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c13
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_clflush.c4
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_client_blt.c355
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_client_blt.h21
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_context.c2154
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_context.h6
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_context_types.h196
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_create.c188
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c58
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_domain.c11
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c486
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_internal.c6
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_lmem.c160
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_lmem.h12
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_mman.c107
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.c350
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.h69
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object_blt.c461
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object_blt.h39
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object_types.h255
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_pages.c54
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_phys.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_region.c23
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_region.h1
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_shmem.c30
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_stolen.c4
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm.c964
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm.h49
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_userptr.c128
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_wait.c23
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c4
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/huge_pages.c8
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c114
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c127
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c190
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c243
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c164
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c597
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c3
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/mock_context.c67
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/mock_context.h4
-rw-r--r--drivers/gpu/drm/i915/gt/debugfs_gt_pm.c10
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_engine_cs.c17
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_ppgtt.c68
-rw-r--r--drivers/gpu/drm/i915/gt/intel_breadcrumbs.c44
-rw-r--r--drivers/gpu/drm/i915/gt/intel_breadcrumbs.h16
-rw-r--r--drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h7
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context.c88
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context.h56
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context_param.c63
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context_param.h6
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context_types.h64
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine.h87
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_cs.c420
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c74
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_pm.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_types.h93
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_user.c6
-rw-r--r--drivers/gpu/drm/i915/gt/intel_execlists_submission.c604
-rw-r--r--drivers/gpu/drm/i915/gt/intel_execlists_submission.h12
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ggtt.c6
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gpu_commands.h2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.c197
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.h10
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c10
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_irq.c13
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm.c11
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_requests.c21
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_requests.h9
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_types.h37
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.c20
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.h18
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c117
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc_reg.h3
-rw-r--r--drivers/gpu/drm/i915/gt/intel_migrate.c688
-rw-r--r--drivers/gpu/drm/i915/gt/intel_migrate.h65
-rw-r--r--drivers/gpu/drm/i915/gt/intel_migrate_types.h15
-rw-r--r--drivers/gpu/drm/i915/gt/intel_mocs.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rc6.c49
-rw-r--r--drivers/gpu/drm/i915/gt/intel_region_lmem.c7
-rw-r--r--drivers/gpu/drm/i915/gt/intel_renderstate.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.c56
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ring.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ring_submission.c70
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rps.c209
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rps.h10
-rw-r--r--drivers/gpu/drm/i915/gt/intel_sseu.c126
-rw-r--r--drivers/gpu/drm/i915/gt/intel_sseu.h10
-rw-r--r--drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c8
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds.c498
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds_types.h1
-rw-r--r--drivers/gpu/drm/i915/gt/mock_engine.c51
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_context.c10
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c22
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h2
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_engine_pm.c4
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_execlists.c307
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_hangcheck.c330
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_lrc.c6
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_migrate.c669
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_mocs.c52
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_reset.c2
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_slpc.c311
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_timeline.c2
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_workarounds.c162
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h129
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h235
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h127
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h65
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h213
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.c206
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.h119
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c487
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h4
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c703
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h36
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c47
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h167
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_log.c29
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_log.h6
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c80
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h31
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c626
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h42
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h29
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c2753
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h18
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc.c126
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc.h15
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c27
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c8
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.c7
-rw-r--r--drivers/gpu/drm/i915/i915_active.c37
-rw-r--r--drivers/gpu/drm/i915/i915_active.h3
-rw-r--r--drivers/gpu/drm/i915/i915_buddy.c421
-rw-r--r--drivers/gpu/drm/i915/i915_buddy.h135
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c67
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c8
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs_params.c32
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c19
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h270
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c63
-rw-r--r--drivers/gpu/drm/i915/i915_gem.h12
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c1
-rw-r--r--drivers/gpu/drm/i915/i915_gem_ww.c63
-rw-r--r--drivers/gpu/drm/i915/i915_gem_ww.h50
-rw-r--r--drivers/gpu/drm/i915/i915_getparam.c7
-rw-r--r--drivers/gpu/drm/i915/i915_globals.c160
-rw-r--r--drivers/gpu/drm/i915/i915_globals.h37
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c27
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c178
-rw-r--r--drivers/gpu/drm/i915/i915_module.c124
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c209
-rw-r--r--drivers/gpu/drm/i915/i915_pci.h8
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c58
-rw-r--r--drivers/gpu/drm/i915/i915_perf.h2
-rw-r--r--drivers/gpu/drm/i915/i915_pmu.c6
-rw-r--r--drivers/gpu/drm/i915/i915_pmu.h4
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h450
-rw-r--r--drivers/gpu/drm/i915/i915_request.c299
-rw-r--r--drivers/gpu/drm/i915/i915_request.h38
-rw-r--r--drivers/gpu/drm/i915/i915_scatterlist.c80
-rw-r--r--drivers/gpu/drm/i915/i915_scatterlist.h5
-rw-r--r--drivers/gpu/drm/i915/i915_scheduler.c220
-rw-r--r--drivers/gpu/drm/i915/i915_scheduler.h54
-rw-r--r--drivers/gpu/drm/i915/i915_scheduler_types.h111
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence_work.c5
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence_work.h2
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c83
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h201
-rw-r--r--drivers/gpu/drm/i915/i915_ttm_buddy_manager.c258
-rw-r--r--drivers/gpu/drm/i915/i915_ttm_buddy_manager.h56
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c34
-rw-r--r--drivers/gpu/drm/i915/i915_vma.h3
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.c34
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.h20
-rw-r--r--drivers/gpu/drm/i915/intel_dram.c42
-rw-r--r--drivers/gpu/drm/i915/intel_memory_region.c63
-rw-r--r--drivers/gpu/drm/i915/intel_memory_region.h30
-rw-r--r--drivers/gpu/drm/i915/intel_pch.c8
-rw-r--r--drivers/gpu/drm/i915/intel_pch.h2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c304
-rw-r--r--drivers/gpu/drm/i915/intel_region_ttm.c150
-rw-r--r--drivers/gpu/drm/i915/intel_region_ttm.h23
-rw-r--r--drivers/gpu/drm/i915/intel_sideband.c13
-rw-r--r--drivers/gpu/drm/i915/intel_sideband.h2
-rw-r--r--drivers/gpu/drm/i915/intel_step.c149
-rw-r--r--drivers/gpu/drm/i915/intel_step.h33
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c424
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.h20
-rw-r--r--drivers/gpu/drm/i915/intel_wopcm.c10
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_buddy.c787
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_live_selftests.h5
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_mock_selftests.h2
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_perf_selftests.h2
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_request.c4
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_selftest.c4
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_flush_test.c2
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_live_test.c2
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_mmap.c25
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_mmap.h12
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_memory_region.c257
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c88
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.h33
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_uncore.c2
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gem_device.c3
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gtt.c1
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_region.c29
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-kms.c8
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-plane.c1
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c11
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c4
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c1
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c5
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c41
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-ipu.c1
-rw-r--r--drivers/gpu/drm/kmb/kmb_drv.c26
-rw-r--r--drivers/gpu/drm/kmb/kmb_dsi.c1
-rw-r--r--drivers/gpu/drm/lima/lima_sched.c3
-rw-r--r--drivers/gpu/drm/mcde/mcde_display.c1
-rw-r--r--drivers/gpu/drm/mcde/mcde_dsi.c11
-rw-r--r--drivers/gpu/drm/mediatek/Makefile3
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_aal.c169
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_drv.h9
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_rdma.c6
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c4
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_crtc.c173
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c44
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c65
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.h1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_gem.c44
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_gem.h3
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_plane.c1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c4
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c5
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c12
-rw-r--r--drivers/gpu/drm/meson/meson_overlay.c1
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c1
-rw-r--r--drivers/gpu/drm/mga/mga_dma.c2
-rw-r--r--drivers/gpu/drm/mga/mga_drv.h1
-rw-r--r--drivers/gpu/drm/mgag200/Makefile2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c64
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h77
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c797
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_pll.c992
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_reg.h9
-rw-r--r--drivers/gpu/drm/msm/Kconfig7
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_debugfs.c4
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c35
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_power.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_preempt.c7
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c24
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.h1
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c137
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c4
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_hfi.c34
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c40
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h22
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c43
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c12
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c5
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c102
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c10
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c85
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c2
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c11
-rw-r--r--drivers/gpu/drm/msm/disp/msm_disp_snapshot.h2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_aux.c3
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.c8
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.c139
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c76
-rw-r--r--drivers/gpu/drm/msm/dp/dp_link.c50
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.c9
-rw-r--r--drivers/gpu/drm/msm/dp/dp_power.c3
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c15
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h18
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h74
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.c33
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.h3
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c169
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c146
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c83
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h5
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c8
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c190
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c158
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h18
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c14
-rw-r--r--drivers/gpu/drm/msm/msm_fence.c53
-rw-r--r--drivers/gpu/drm/msm/msm_fence.h44
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c134
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h50
-rw-r--r--drivers/gpu/drm/msm/msm_gem_prime.c11
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c350
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c220
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h139
-rw-r--r--drivers/gpu/drm/msm/msm_gpu_devfreq.c203
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h5
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c6
-rw-r--r--drivers/gpu/drm/msm/msm_ringbuffer.c69
-rw-r--r--drivers/gpu/drm/msm/msm_ringbuffer.h12
-rw-r--r--drivers/gpu/drm/msm/msm_submitqueue.c53
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c84
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.h3
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_kms.c74
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_regs.h9
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c34
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c166
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c8
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_irq.c13
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c3
-rw-r--r--drivers/gpu/drm/panel/Kconfig54
-rw-r--r--drivers/gpu/drm/panel/Makefile5
-rw-r--r--drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c2
-rw-r--r--drivers/gpu/drm/panel/panel-dsi-cm.c2
-rw-r--r--drivers/gpu/drm/panel/panel-elida-kd35t133.c2
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9341.c792
-rw-r--r--drivers/gpu/drm/panel/panel-innolux-ej030na.c289
-rw-r--r--drivers/gpu/drm/panel/panel-khadas-ts050.c2
-rw-r--r--drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c2
-rw-r--r--drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c2
-rw-r--r--drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c2
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-atna33xc20.c366
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-db7430.c347
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c2
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c10
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c83
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e63m0.c41
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e63m0.h33
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c4
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c2
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c357
-rw-r--r--drivers/gpu/drm/panel/panel-sony-acx424akp.c82
-rw-r--r--drivers/gpu/drm/panel/panel-widechips-ws2401.c441
-rw-r--r--drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c2
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_devfreq.c3
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_device.c142
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_device.h99
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_drv.c91
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_gem.c20
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_gpu.c2
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_job.c695
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_job.h8
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_mmu.c203
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_mmu.h5
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_regs.h3
-rw-r--r--drivers/gpu/drm/pl111/pl111_display.c2
-rw-r--r--drivers/gpu/drm/pl111/pl111_drv.c1
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c4
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h3
-rw-r--r--drivers/gpu/drm/qxl/qxl_irq.c9
-rw-r--r--drivers/gpu/drm/qxl/qxl_prime.c6
-rw-r--r--drivers/gpu/drm/r128/r128_cce.c3
-rw-r--r--drivers/gpu/drm/radeon/atombios.h4
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c8
-rw-r--r--drivers/gpu/drm/radeon/r100.c9
-rw-r--r--drivers/gpu/drm/radeon/r300_reg.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c19
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c60
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_vm.c2
-rw-r--r--drivers/gpu/drm/radeon/rs600.c8
-rw-r--r--drivers/gpu/drm/radeon/rv770.c8
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c13
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.c26
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds.c126
-rw-r--r--drivers/gpu/drm/rockchip/Kconfig2
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c349
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c8
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_lvds.c5
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_rgb.c5
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c21
-rw-r--r--drivers/gpu/drm/selftests/test-drm_damage_helper.c287
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_drv.c14
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_drv.h1
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.c2
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c4
-rw-r--r--drivers/gpu/drm/stm/dw_mipi_dsi-stm.c17
-rw-r--r--drivers/gpu/drm/stm/ltdc.c12
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.c1
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_lvds.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_rgb.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_ui_layer.c1
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_vi_layer.c1
-rw-r--r--drivers/gpu/drm/tegra/Kconfig1
-rw-r--r--drivers/gpu/drm/tegra/Makefile3
-rw-r--r--drivers/gpu/drm/tegra/dc.c358
-rw-r--r--drivers/gpu/drm/tegra/dc.h17
-rw-r--r--drivers/gpu/drm/tegra/drm.c107
-rw-r--r--drivers/gpu/drm/tegra/drm.h12
-rw-r--r--drivers/gpu/drm/tegra/firewall.c254
-rw-r--r--drivers/gpu/drm/tegra/gem.c13
-rw-r--r--drivers/gpu/drm/tegra/gem.h2
-rw-r--r--drivers/gpu/drm/tegra/plane.c117
-rw-r--r--drivers/gpu/drm/tegra/plane.h16
-rw-r--r--drivers/gpu/drm/tegra/rgb.c5
-rw-r--r--drivers/gpu/drm/tegra/submit.c625
-rw-r--r--drivers/gpu/drm/tegra/submit.h21
-rw-r--r--drivers/gpu/drm/tegra/uapi.c338
-rw-r--r--drivers/gpu/drm/tegra/uapi.h58
-rw-r--r--drivers/gpu/drm/tegra/vic.c112
-rw-r--r--drivers/gpu/drm/tidss/tidss_drv.c15
-rw-r--r--drivers/gpu/drm/tidss/tidss_drv.h2
-rw-r--r--drivers/gpu/drm/tidss/tidss_irq.c30
-rw-r--r--drivers/gpu/drm/tidss/tidss_irq.h4
-rw-r--r--drivers/gpu/drm/tidss/tidss_kms.c4
-rw-r--r--drivers/gpu/drm/tidss/tidss_plane.c1
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c51
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h3
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_external.c4
-rw-r--r--drivers/gpu/drm/tiny/Kconfig17
-rw-r--r--drivers/gpu/drm/tiny/Makefile1
-rw-r--r--drivers/gpu/drm/tiny/bochs.c733
-rw-r--r--drivers/gpu/drm/tiny/cirrus.c6
-rw-r--r--drivers/gpu/drm/tiny/gm12u320.c23
-rw-r--r--drivers/gpu/drm/tiny/hx8357d.c1
-rw-r--r--drivers/gpu/drm/tiny/ili9225.c1
-rw-r--r--drivers/gpu/drm/tiny/ili9341.c1
-rw-r--r--drivers/gpu/drm/tiny/ili9486.c1
-rw-r--r--drivers/gpu/drm/tiny/mi0283qt.c1
-rw-r--r--drivers/gpu/drm/tiny/repaper.c19
-rw-r--r--drivers/gpu/drm/tiny/simpledrm.c4
-rw-r--r--drivers/gpu/drm/tiny/st7586.c19
-rw-r--r--drivers/gpu/drm/tiny/st7735r.c1
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c66
-rw-r--r--drivers/gpu/drm/tve200/tve200_display.c1
-rw-r--r--drivers/gpu/drm/udl/udl_modeset.c33
-rw-r--r--drivers/gpu/drm/v3d/Makefile1
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.c8
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.h63
-rw-r--r--drivers/gpu/drm/v3d/v3d_gem.c31
-rw-r--r--drivers/gpu/drm/v3d/v3d_perfmon.c213
-rw-r--r--drivers/gpu/drm/v3d/v3d_regs.h2
-rw-r--r--drivers/gpu/drm/v3d/v3d_sched.c26
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_drv.c3
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_drv.h1
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_irq.c16
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_mode.c5
-rw-r--r--drivers/gpu/drm/vc4/Kconfig1
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c6
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h8
-rw-r--r--drivers/gpu/drm/vc4/vc4_dsi.c4
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c450
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.h5
-rw-r--r--drivers/gpu/drm/vc4/vc4_irq.c48
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c1
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h30
-rw-r--r--drivers/gpu/drm/vc4/vc4_v3d.c17
-rw-r--r--drivers/gpu/drm/via/via_mm.c3
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_plane.c64
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_prime.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c7
-rw-r--r--drivers/gpu/drm/vkms/vkms_composer.c28
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.c32
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.h13
-rw-r--r--drivers/gpu/drm/vkms/vkms_plane.c57
-rw-r--r--drivers/gpu/drm/vkms/vkms_writeback.c28
-rw-r--r--drivers/gpu/drm/vmwgfx/Kconfig8
-rw-r--r--drivers/gpu/drm/vmwgfx/Makefile2
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/includeCheck.h3
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_caps.h111
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_cmd.h3680
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_devcaps.h793
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_dx.h3503
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_limits.h101
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_reg.h15
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h3132
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_types.h3020
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga_escape.h68
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga_overlay.h203
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga_reg.h2847
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga_types.h51
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h130
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/vmware_pack_begin.h2
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/vmware_pack_end.h2
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_memory.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmw_surface_cache.h539
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_binding.c24
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_bo.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_context.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_devcaps.c142
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_devcaps.h50
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c457
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h50
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c17
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c36
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c111
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_irq.c24
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c18
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h144
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_mob.c45
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg.c579
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c11
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_shader.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_so.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c84
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c49
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_validation.c4
-rw-r--r--drivers/gpu/drm/xen/xen_drm_front_kms.c1
-rw-r--r--drivers/gpu/drm/xlnx/Kconfig2
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_disp.c320
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dp.c22
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dpsub.c2
-rw-r--r--drivers/gpu/drm/zte/zx_drm_drv.c6
-rw-r--r--drivers/gpu/host1x/Makefile1
-rw-r--r--drivers/gpu/host1x/cdma.c58
-rw-r--r--drivers/gpu/host1x/fence.c168
-rw-r--r--drivers/gpu/host1x/fence.h13
-rw-r--r--drivers/gpu/host1x/hw/channel_hw.c87
-rw-r--r--drivers/gpu/host1x/hw/debug_hw.c32
-rw-r--r--drivers/gpu/host1x/hw/debug_hw_1x01.c8
-rw-r--r--drivers/gpu/host1x/hw/debug_hw_1x06.c16
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x02_uclass.h12
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x04_uclass.h12
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x05_uclass.h12
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x06_uclass.h12
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x07_uclass.h12
-rw-r--r--drivers/gpu/host1x/intr.c9
-rw-r--r--drivers/gpu/host1x/intr.h2
-rw-r--r--drivers/gpu/host1x/job.c98
-rw-r--r--drivers/gpu/host1x/job.h16
-rw-r--r--drivers/gpu/host1x/syncpt.c2
-rw-r--r--drivers/gpu/host1x/syncpt.h12
-rw-r--r--drivers/gpu/vga/vgaarb.c67
-rw-r--r--drivers/hid/Kconfig7
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/amd-sfh-hid/amd_sfh_client.c62
-rw-r--r--drivers/hid/amd-sfh-hid/amd_sfh_pcie.c69
-rw-r--r--drivers/hid/amd-sfh-hid/amd_sfh_pcie.h23
-rw-r--r--drivers/hid/hid-apple.c32
-rw-r--r--drivers/hid/hid-asus.c15
-rw-r--r--drivers/hid/hid-cmedia.c90
-rw-r--r--drivers/hid/hid-core.c4
-rw-r--r--drivers/hid/hid-elo.c6
-rw-r--r--drivers/hid/hid-ids.h9
-rw-r--r--drivers/hid/hid-input.c2
-rw-r--r--drivers/hid/hid-logitech-hidpp.c47
-rw-r--r--drivers/hid/hid-magicmouse.c52
-rw-r--r--drivers/hid/hid-quirks.c2
-rw-r--r--drivers/hid/hid-sony.c49
-rw-r--r--drivers/hid/hid-thrustmaster.c7
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c5
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of-goodix.c92
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/bus.c4
-rw-r--r--drivers/hid/usbhid/hid-core.c29
-rw-r--r--drivers/hid/wacom_sys.c9
-rw-r--r--drivers/hid/wacom_wac.c50
-rw-r--r--drivers/hid/wacom_wac.h2
-rw-r--r--drivers/hv/Kconfig7
-rw-r--r--drivers/hv/hv_common.c219
-rw-r--r--drivers/hv/hv_snapshot.c1
-rw-r--r--drivers/hv/hv_util.c5
-rw-r--r--drivers/hv/vmbus_drv.c5
-rw-r--r--drivers/hwtracing/coresight/Kconfig1
-rw-r--r--drivers/hwtracing/coresight/Makefile7
-rw-r--r--drivers/hwtracing/coresight/coresight-cfg-afdo.c153
-rw-r--r--drivers/hwtracing/coresight/coresight-cfg-preload.c31
-rw-r--r--drivers/hwtracing/coresight/coresight-cfg-preload.h13
-rw-r--r--drivers/hwtracing/coresight/coresight-config.c272
-rw-r--r--drivers/hwtracing/coresight/coresight-config.h253
-rw-r--r--drivers/hwtracing/coresight/coresight-core.c12
-rw-r--r--drivers/hwtracing/coresight/coresight-cpu-debug.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c150
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.h12
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-cfg.c182
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-cfg.h30
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-core.c38
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-sysfs.c3
-rw-r--r--drivers/hwtracing/coresight/coresight-syscfg-configfs.c396
-rw-r--r--drivers/hwtracing/coresight/coresight-syscfg-configfs.h45
-rw-r--r--drivers/hwtracing/coresight/coresight-syscfg.c847
-rw-r--r--drivers/hwtracing/coresight/coresight-syscfg.h81
-rw-r--r--drivers/hwtracing/intel_th/core.c4
-rw-r--r--drivers/i2c/i2c-core-acpi.c32
-rw-r--r--drivers/i2c/i2c-core-base.c5
-rw-r--r--drivers/i3c/master.c4
-rw-r--r--drivers/iio/accel/Kconfig5
-rw-r--r--drivers/iio/accel/adxl345.h1
-rw-r--r--drivers/iio/accel/adxl345_core.c29
-rw-r--r--drivers/iio/accel/adxl345_i2c.c6
-rw-r--r--drivers/iio/accel/adxl345_spi.c6
-rw-r--r--drivers/iio/accel/bma220_spi.c79
-rw-r--r--drivers/iio/accel/bmc150-accel-core.c78
-rw-r--r--drivers/iio/accel/bmc150-accel-i2c.c10
-rw-r--r--drivers/iio/accel/bmc150-accel-spi.c10
-rw-r--r--drivers/iio/accel/bmc150-accel.h20
-rw-r--r--drivers/iio/accel/da280.c26
-rw-r--r--drivers/iio/accel/da311.c26
-rw-r--r--drivers/iio/accel/dmard10.c27
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c10
-rw-r--r--drivers/iio/accel/st_accel.h4
-rw-r--r--drivers/iio/accel/st_accel_buffer.c16
-rw-r--r--drivers/iio/accel/st_accel_core.c14
-rw-r--r--drivers/iio/accel/st_accel_i2c.c3
-rw-r--r--drivers/iio/accel/st_accel_spi.c2
-rw-r--r--drivers/iio/adc/Kconfig10
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ep93xx_adc.c6
-rw-r--r--drivers/iio/adc/fsl-imx25-gcq.c17
-rw-r--r--drivers/iio/adc/ingenic-adc.c102
-rw-r--r--drivers/iio/adc/meson_saradc.c20
-rw-r--r--drivers/iio/adc/rockchip_saradc.c69
-rw-r--r--drivers/iio/adc/rzg2l_adc.c600
-rw-r--r--drivers/iio/chemical/Kconfig11
-rw-r--r--drivers/iio/chemical/Makefile1
-rw-r--r--drivers/iio/chemical/sgp40.c378
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_buffer.c2
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.c1
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.h1
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_i2c.c3
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_spi.c3
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_trigger.c1
-rw-r--r--drivers/iio/dac/ad5624r_spi.c18
-rw-r--r--drivers/iio/dac/max5821.c41
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c11
-rw-r--r--drivers/iio/gyro/st_gyro.h4
-rw-r--r--drivers/iio/gyro/st_gyro_buffer.c16
-rw-r--r--drivers/iio/gyro/st_gyro_core.c15
-rw-r--r--drivers/iio/gyro/st_gyro_i2c.c2
-rw-r--r--drivers/iio/gyro/st_gyro_spi.c2
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c22
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h18
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c15
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c1
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c3
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c3
-rw-r--r--drivers/iio/industrialio-buffer.c9
-rw-r--r--drivers/iio/industrialio-core.c33
-rw-r--r--drivers/iio/light/adjd_s311.c53
-rw-r--r--drivers/iio/light/cm3323.c7
-rw-r--r--drivers/iio/light/hid-sensor-als.c11
-rw-r--r--drivers/iio/light/hid-sensor-prox.c11
-rw-r--r--drivers/iio/light/si1145.c1
-rw-r--r--drivers/iio/light/tcs3414.c48
-rw-r--r--drivers/iio/magnetometer/st_magn.h12
-rw-r--r--drivers/iio/magnetometer/st_magn_buffer.c16
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c17
-rw-r--r--drivers/iio/magnetometer/st_magn_i2c.c2
-rw-r--r--drivers/iio/magnetometer/st_magn_spi.c2
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c11
-rw-r--r--drivers/iio/potentiometer/Kconfig10
-rw-r--r--drivers/iio/potentiometer/Makefile1
-rw-r--r--drivers/iio/potentiometer/ad5110.c344
-rw-r--r--drivers/iio/potentiometer/max5481.c22
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c51
-rw-r--r--drivers/iio/pressure/hp03.c36
-rw-r--r--drivers/iio/pressure/st_pressure.h5
-rw-r--r--drivers/iio/pressure/st_pressure_buffer.c16
-rw-r--r--drivers/iio/pressure/st_pressure_core.c16
-rw-r--r--drivers/iio/pressure/st_pressure_i2c.c3
-rw-r--r--drivers/iio/pressure/st_pressure_spi.c2
-rw-r--r--drivers/iio/proximity/rfd77402.c83
-rw-r--r--drivers/iio/proximity/sx9310.c48
-rw-r--r--drivers/iio/proximity/vcnl3020.c351
-rw-r--r--drivers/iio/temperature/ltc2983.c30
-rw-r--r--drivers/iio/temperature/tmp006.c53
-rw-r--r--drivers/infiniband/core/cache.c10
-rw-r--r--drivers/infiniband/core/cma.c3
-rw-r--r--drivers/infiniband/core/core_priv.h46
-rw-r--r--drivers/infiniband/core/device.c12
-rw-r--r--drivers/infiniband/core/iwcm.c19
-rw-r--r--drivers/infiniband/core/iwpm_msg.c34
-rw-r--r--drivers/infiniband/core/iwpm_util.c78
-rw-r--r--drivers/infiniband/core/iwpm_util.h18
-rw-r--r--drivers/infiniband/core/restrack.c2
-rw-r--r--drivers/infiniband/core/sa_query.c186
-rw-r--r--drivers/infiniband/core/umem.c56
-rw-r--r--drivers/infiniband/core/umem_dmabuf.c5
-rw-r--r--drivers/infiniband/core/umem_odp.c3
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c31
-rw-r--r--drivers/infiniband/core/uverbs_std_types_qp.c29
-rw-r--r--drivers/infiniband/core/verbs.c234
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c26
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.h7
-rw-r--r--drivers/infiniband/hw/bnxt_re/main.c1
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h5
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c1
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c37
-rw-r--r--drivers/infiniband/hw/efa/efa.h10
-rw-r--r--drivers/infiniband/hw/efa/efa_main.c20
-rw-r--r--drivers/infiniband/hw/efa/efa_verbs.c147
-rw-r--r--drivers/infiniband/hw/hfi1/affinity.c45
-rw-r--r--drivers/infiniband/hw/hfi1/affinity.h45
-rw-r--r--drivers/infiniband/hw/hfi1/aspm.h45
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c50
-rw-r--r--drivers/infiniband/hw/hfi1/chip.h48
-rw-r--r--drivers/infiniband/hw/hfi1/chip_registers.h50
-rw-r--r--drivers/infiniband/hw/hfi1/common.h44
-rw-r--r--drivers/infiniband/hw/hfi1/debugfs.c58
-rw-r--r--drivers/infiniband/hw/hfi1/debugfs.h49
-rw-r--r--drivers/infiniband/hw/hfi1/device.c44
-rw-r--r--drivers/infiniband/hw/hfi1/device.h49
-rw-r--r--drivers/infiniband/hw/hfi1/driver.c44
-rw-r--r--drivers/infiniband/hw/hfi1/efivar.c44
-rw-r--r--drivers/infiniband/hw/hfi1/efivar.h45
-rw-r--r--drivers/infiniband/hw/hfi1/eprom.c45
-rw-r--r--drivers/infiniband/hw/hfi1/eprom.h44
-rw-r--r--drivers/infiniband/hw/hfi1/exp_rcv.c44
-rw-r--r--drivers/infiniband/hw/hfi1/exp_rcv.h48
-rw-r--r--drivers/infiniband/hw/hfi1/fault.c45
-rw-r--r--drivers/infiniband/hw/hfi1/fault.h50
-rw-r--r--drivers/infiniband/hw/hfi1/file_ops.c51
-rw-r--r--drivers/infiniband/hw/hfi1/firmware.c44
-rw-r--r--drivers/infiniband/hw/hfi1/hfi.h54
-rw-r--r--drivers/infiniband/hw/hfi1/init.c53
-rw-r--r--drivers/infiniband/hw/hfi1/intr.c44
-rw-r--r--drivers/infiniband/hw/hfi1/iowait.h49
-rw-r--r--drivers/infiniband/hw/hfi1/ipoib_tx.c3
-rw-r--r--drivers/infiniband/hw/hfi1/mad.c44
-rw-r--r--drivers/infiniband/hw/hfi1/mad.h45
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.c45
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.h45
-rw-r--r--drivers/infiniband/hw/hfi1/msix.c43
-rw-r--r--drivers/infiniband/hw/hfi1/msix.h44
-rw-r--r--drivers/infiniband/hw/hfi1/opa_compat.h48
-rw-r--r--drivers/infiniband/hw/hfi1/pcie.c55
-rw-r--r--drivers/infiniband/hw/hfi1/pio.c44
-rw-r--r--drivers/infiniband/hw/hfi1/pio.h48
-rw-r--r--drivers/infiniband/hw/hfi1/pio_copy.c44
-rw-r--r--drivers/infiniband/hw/hfi1/platform.c44
-rw-r--r--drivers/infiniband/hw/hfi1/platform.h45
-rw-r--r--drivers/infiniband/hw/hfi1/qp.c44
-rw-r--r--drivers/infiniband/hw/hfi1/qp.h48
-rw-r--r--drivers/infiniband/hw/hfi1/qsfp.c44
-rw-r--r--drivers/infiniband/hw/hfi1/qsfp.h44
-rw-r--r--drivers/infiniband/hw/hfi1/rc.c44
-rw-r--r--drivers/infiniband/hw/hfi1/ruc.c46
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.c46
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.h49
-rw-r--r--drivers/infiniband/hw/hfi1/sdma_txreq.h44
-rw-r--r--drivers/infiniband/hw/hfi1/sysfs.c45
-rw-r--r--drivers/infiniband/hw/hfi1/tid_rdma.c4
-rw-r--r--drivers/infiniband/hw/hfi1/trace.c44
-rw-r--r--drivers/infiniband/hw/hfi1/trace.h44
-rw-r--r--drivers/infiniband/hw/hfi1/trace_ctxts.h45
-rw-r--r--drivers/infiniband/hw/hfi1/trace_dbg.h45
-rw-r--r--drivers/infiniband/hw/hfi1/trace_ibhdrs.h45
-rw-r--r--drivers/infiniband/hw/hfi1/trace_misc.h45
-rw-r--r--drivers/infiniband/hw/hfi1/trace_mmu.h45
-rw-r--r--drivers/infiniband/hw/hfi1/trace_rc.h45
-rw-r--r--drivers/infiniband/hw/hfi1/trace_rx.h45
-rw-r--r--drivers/infiniband/hw/hfi1/trace_tx.h44
-rw-r--r--drivers/infiniband/hw/hfi1/uc.c44
-rw-r--r--drivers/infiniband/hw/hfi1/ud.c44
-rw-r--r--drivers/infiniband/hw/hfi1/user_exp_rcv.c57
-rw-r--r--drivers/infiniband/hw/hfi1/user_exp_rcv.h49
-rw-r--r--drivers/infiniband/hw/hfi1/user_pages.c44
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.c45
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.h49
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.c44
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.h44
-rw-r--r--drivers/infiniband/hw/hfi1/verbs_txreq.c44
-rw-r--r--drivers/infiniband/hw/hfi1/verbs_txreq.h44
-rw-r--r--drivers/infiniband/hw/hfi1/vnic.h48
-rw-r--r--drivers/infiniband/hw/hfi1/vnic_main.c44
-rw-r--r--drivers/infiniband/hw/hfi1/vnic_sdma.c44
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_alloc.c74
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_db.c4
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_device.h30
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v1.c6
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c81
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.h23
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_main.c40
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_mr.c4
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_pd.c31
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_qp.c196
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_srq.c28
-rw-r--r--drivers/infiniband/hw/irdma/protos.h2
-rw-r--r--drivers/infiniband/hw/irdma/utils.c3
-rw-r--r--drivers/infiniband/hw/irdma/verbs.c33
-rw-r--r--drivers/infiniband/hw/mlx4/doorbell.c3
-rw-r--r--drivers/infiniband/hw/mlx4/main.c1
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h5
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c4
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c25
-rw-r--r--drivers/infiniband/hw/mlx5/doorbell.c3
-rw-r--r--drivers/infiniband/hw/mlx5/gsi.c51
-rw-r--r--drivers/infiniband/hw/mlx5/main.c145
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h7
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c3
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c232
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c21
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c15
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c25
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c77
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_main.c1
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c25
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.h5
-rw-r--r--drivers/infiniband/hw/qedr/main.c1
-rw-r--r--drivers/infiniband/hw/qedr/qedr_roce_cm.c13
-rw-r--r--drivers/infiniband/hw/qedr/qedr_roce_cm.h5
-rw-r--r--drivers/infiniband/hw/qedr/verbs.c101
-rw-r--r--drivers/infiniband/hw/qedr/verbs.h4
-rw-r--r--drivers/infiniband/hw/qib/qib_file_ops.c12
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_user_pages.c12
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_main.c1
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c34
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h10
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_verbs.c69
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_verbs.h5
-rw-r--r--drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c15
-rw-r--r--drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c53
-rw-r--r--drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h5
-rw-r--r--drivers/infiniband/sw/rdmavt/ah.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/ah.h50
-rw-r--r--drivers/infiniband/sw/rdmavt/cq.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/cq.h50
-rw-r--r--drivers/infiniband/sw/rdmavt/mad.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/mad.h50
-rw-r--r--drivers/infiniband/sw/rdmavt/mcast.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/mcast.h50
-rw-r--r--drivers/infiniband/sw/rdmavt/mmap.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/mmap.h50
-rw-r--r--drivers/infiniband/sw/rdmavt/mr.c46
-rw-r--r--drivers/infiniband/sw/rdmavt/mr.h50
-rw-r--r--drivers/infiniband/sw/rdmavt/pd.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/pd.h50
-rw-r--r--drivers/infiniband/sw/rdmavt/qp.c146
-rw-r--r--drivers/infiniband/sw/rdmavt/qp.h55
-rw-r--r--drivers/infiniband/sw/rdmavt/rc.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/srq.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/srq.h50
-rw-r--r--drivers/infiniband/sw/rdmavt/trace.c44
-rw-r--r--drivers/infiniband/sw/rdmavt/trace.h44
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_cq.h44
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_mr.h44
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_qp.h44
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_rc.h44
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_rvt.h44
-rw-r--r--drivers/infiniband/sw/rdmavt/trace_tx.h44
-rw-r--r--drivers/infiniband/sw/rdmavt/vt.c53
-rw-r--r--drivers/infiniband/sw/rdmavt/vt.h50
-rw-r--r--drivers/infiniband/sw/rxe/rxe.h22
-rw-r--r--drivers/infiniband/sw/rxe/rxe_comp.c4
-rw-r--r--drivers/infiniband/sw/rxe/rxe_icrc.c124
-rw-r--r--drivers/infiniband/sw/rxe/rxe_loc.h61
-rw-r--r--drivers/infiniband/sw/rxe/rxe_mr.c25
-rw-r--r--drivers/infiniband/sw/rxe/rxe_net.c59
-rw-r--r--drivers/infiniband/sw/rxe/rxe_pool.c2
-rw-r--r--drivers/infiniband/sw/rxe/rxe_recv.c23
-rw-r--r--drivers/infiniband/sw/rxe/rxe_req.c13
-rw-r--r--drivers/infiniband/sw/rxe/rxe_resp.c33
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.c59
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.h2
-rw-r--r--drivers/infiniband/sw/siw/siw_main.c1
-rw-r--r--drivers/infiniband/sw/siw/siw_qp.c2
-rw-r--r--drivers/infiniband/sw/siw/siw_qp_tx.c44
-rw-r--r--drivers/infiniband/sw/siw/siw_verbs.c54
-rw-r--r--drivers/infiniband/sw/siw/siw_verbs.h5
-rw-r--r--drivers/infiniband/ulp/iser/iser_memory.c2
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c2
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c4
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c157
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.h7
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-pri.h6
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-srv.c95
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-srv.h6
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs.c23
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c9
-rw-r--r--drivers/input/gameport/gameport.c3
-rw-r--r--drivers/input/keyboard/hilkbd.c4
-rw-r--r--drivers/input/serio/gscps2.c3
-rw-r--r--drivers/input/serio/serio.c3
-rw-r--r--drivers/interconnect/core.c3
-rw-r--r--drivers/interconnect/qcom/Kconfig9
-rw-r--r--drivers/interconnect/qcom/Makefile2
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.c93
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.h2
-rw-r--r--drivers/interconnect/qcom/osm-l3.c60
-rw-r--r--drivers/interconnect/qcom/sc7180.c96
-rw-r--r--drivers/interconnect/qcom/sc7280.c96
-rw-r--r--drivers/interconnect/qcom/sc8180x.c626
-rw-r--r--drivers/interconnect/qcom/sc8180x.h174
-rw-r--r--drivers/interconnect/qcom/sdm845.c99
-rw-r--r--drivers/interconnect/qcom/sdx55.c96
-rw-r--r--drivers/interconnect/qcom/sm8150.c96
-rw-r--r--drivers/interconnect/qcom/sm8250.c96
-rw-r--r--drivers/interconnect/qcom/sm8350.c97
-rw-r--r--drivers/iommu/Kconfig71
-rw-r--r--drivers/iommu/Makefile1
-rw-r--r--drivers/iommu/amd/amd_iommu_types.h6
-rw-r--r--drivers/iommu/amd/init.c12
-rw-r--r--drivers/iommu/amd/io_pgtable.c3
-rw-r--r--drivers/iommu/amd/iommu.c151
-rw-r--r--drivers/iommu/amd/iommu_v2.c13
-rw-r--r--drivers/iommu/apple-dart.c923
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c121
-rw-r--r--drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c11
-rw-r--r--drivers/iommu/arm/arm-smmu/arm-smmu.c89
-rw-r--r--drivers/iommu/arm/arm-smmu/arm-smmu.h1
-rw-r--r--drivers/iommu/arm/arm-smmu/qcom_iommu.c9
-rw-r--r--drivers/iommu/dma-iommu.c85
-rw-r--r--drivers/iommu/exynos-iommu.c19
-rw-r--r--drivers/iommu/intel/Kconfig19
-rw-r--r--drivers/iommu/intel/dmar.c2
-rw-r--r--drivers/iommu/intel/iommu.c197
-rw-r--r--drivers/iommu/intel/pasid.c18
-rw-r--r--drivers/iommu/intel/pasid.h10
-rw-r--r--drivers/iommu/intel/perf.c2
-rw-r--r--drivers/iommu/intel/svm.c4
-rw-r--r--drivers/iommu/io-pgtable-arm-v7s.c62
-rw-r--r--drivers/iommu/io-pgtable-arm.c282
-rw-r--r--drivers/iommu/io-pgtable.c1
-rw-r--r--drivers/iommu/iommu.c210
-rw-r--r--drivers/iommu/iova.c14
-rw-r--r--drivers/iommu/ipmmu-vmsa.c28
-rw-r--r--drivers/iommu/mtk_iommu.c13
-rw-r--r--drivers/iommu/mtk_iommu_v1.c1
-rw-r--r--drivers/iommu/rockchip-iommu.c12
-rw-r--r--drivers/iommu/sprd-iommu.c7
-rw-r--r--drivers/iommu/sun50i-iommu.c13
-rw-r--r--drivers/iommu/virtio-iommu.c8
-rw-r--r--drivers/ipack/devices/ipoctal.c13
-rw-r--r--drivers/ipack/ipack.c4
-rw-r--r--drivers/isdn/capi/capi.c14
-rw-r--r--drivers/isdn/capi/capiutil.c2
-rw-r--r--drivers/macintosh/macio-adb.c1
-rw-r--r--drivers/macintosh/macio_asic.c4
-rw-r--r--drivers/macintosh/via-cuda.c2
-rw-r--r--drivers/macintosh/via-macii.c2
-rw-r--r--drivers/macintosh/via-pmu.c2
-rw-r--r--drivers/mailbox/Kconfig2
-rw-r--r--drivers/mailbox/mailbox-sti.c16
-rw-r--r--drivers/mailbox/mtk-cmdq-mailbox.c109
-rw-r--r--drivers/mailbox/qcom-apcs-ipc-mailbox.c2
-rw-r--r--drivers/mailbox/qcom-ipcc.c1
-rw-r--r--drivers/mcb/mcb-core.c4
-rw-r--r--drivers/md/dm-ima.c3
-rw-r--r--drivers/media/cec/core/cec-pin-priv.h4
-rw-r--r--drivers/media/cec/core/cec-pin.c20
-rw-r--r--drivers/media/cec/platform/stm32/stm32-cec.c26
-rw-r--r--drivers/media/cec/platform/tegra/tegra_cec.c10
-rw-r--r--drivers/media/dvb-frontends/cx24117.c1
-rw-r--r--drivers/media/dvb-frontends/dib8000.c58
-rw-r--r--drivers/media/i2c/Kconfig42
-rw-r--r--drivers/media/i2c/Makefile4
-rw-r--r--drivers/media/i2c/adv7180.c66
-rw-r--r--drivers/media/i2c/ccs/ccs-core.c58
-rw-r--r--drivers/media/i2c/et8ek8/et8ek8_driver.c5
-rw-r--r--drivers/media/i2c/imx258.c4
-rw-r--r--drivers/media/i2c/imx335.c1129
-rw-r--r--drivers/media/i2c/imx412.c1272
-rw-r--r--drivers/media/i2c/ov2740.c26
-rw-r--r--drivers/media/i2c/ov5640.c4
-rw-r--r--drivers/media/i2c/ov8856.c27
-rw-r--r--drivers/media/i2c/ov9282.c1137
-rw-r--r--drivers/media/i2c/ov9734.c24
-rw-r--r--drivers/media/i2c/tda1997x.c11
-rw-r--r--drivers/media/i2c/tvp5150.c2
-rw-r--r--drivers/media/mc/mc-device.c4
-rw-r--r--drivers/media/pci/bt8xx/bttv-gpio.c3
-rw-r--r--drivers/media/pci/ivtv/ivtv-cards.h68
-rw-r--r--drivers/media/pci/ivtv/ivtv-i2c.c16
-rw-r--r--drivers/media/pci/saa7134/saa7134-alsa.c4
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c7
-rw-r--r--drivers/media/pci/saa7164/saa7164-cmd.c3
-rw-r--r--drivers/media/pci/tw5864/tw5864-reg.h2
-rw-r--r--drivers/media/platform/atmel/atmel-sama5d2-isc.c17
-rw-r--r--drivers/media/platform/coda/coda-bit.c18
-rw-r--r--drivers/media/platform/davinci/vpfe_capture.c2
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.c13
-rw-r--r--drivers/media/platform/marvell-ccic/mcam-core.c2
-rw-r--r--drivers/media/platform/omap3isp/isp.c4
-rw-r--r--drivers/media/platform/qcom/venus/core.h2
-rw-r--r--drivers/media/platform/qcom/venus/helpers.c3
-rw-r--r--drivers/media/platform/qcom/venus/hfi_cmds.c8
-rw-r--r--drivers/media/platform/qcom/venus/hfi_helper.h5
-rw-r--r--drivers/media/platform/qcom/venus/hfi_msgs.c2
-rw-r--r--drivers/media/platform/qcom/venus/venc.c40
-rw-r--r--drivers/media/platform/qcom/venus/venc_ctrls.c38
-rw-r--r--drivers/media/platform/rcar-vin/rcar-v4l2.c4
-rw-r--r--drivers/media/platform/rockchip/rga/rga.c27
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c12
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-common.h6
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-params.c3
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c6
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c2
-rw-r--r--drivers/media/platform/sti/delta/delta-ipc.c3
-rw-r--r--drivers/media/platform/ti-vpe/cal-camerarx.c247
-rw-r--r--drivers/media/platform/ti-vpe/cal-video.c176
-rw-r--r--drivers/media/platform/ti-vpe/cal.c278
-rw-r--r--drivers/media/platform/ti-vpe/cal.h66
-rw-r--r--drivers/media/platform/ti-vpe/cal_regs.h53
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.c4
-rw-r--r--drivers/media/rc/Kconfig10
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/ene_ir.c2
-rw-r--r--drivers/media/rc/lirc_dev.c6
-rw-r--r--drivers/media/rc/mceusb.c2
-rw-r--r--drivers/media/rc/meson-ir-tx.c407
-rw-r--r--drivers/media/rc/rc-loopback.c82
-rw-r--r--drivers/media/rc/rc-main.c2
-rw-r--r--drivers/media/rc/redrat3.c2
-rw-r--r--drivers/media/rc/streamzap.c2
-rw-r--r--drivers/media/spi/cxd2880-spi.c7
-rw-r--r--drivers/media/test-drivers/vivid/vivid-cec.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/Kconfig2
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.c1
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvbsky.c37
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb-i2c.c9
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb-init.c2
-rw-r--r--drivers/media/usb/dvb-usb/nova-t-usb2.c6
-rw-r--r--drivers/media/usb/dvb-usb/vp702x.c12
-rw-r--r--drivers/media/usb/em28xx/em28xx-input.c1
-rw-r--r--drivers/media/usb/go7007/go7007-driver.c26
-rw-r--r--drivers/media/usb/go7007/go7007-usb.c2
-rw-r--r--drivers/media/usb/gspca/Kconfig1
-rw-r--r--drivers/media/usb/gspca/vc032x.c6
-rw-r--r--drivers/media/usb/gspca/zc3xx.c134
-rw-r--r--drivers/media/usb/stkwebcam/stk-webcam.c6
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c34
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls-defs.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-dv-timings.c4
-rw-r--r--drivers/media/v4l2-core/v4l2-flash-led-class.c80
-rw-r--r--drivers/memory/omap-gpmc.c191
-rw-r--r--drivers/memory/tegra/tegra186.c2
-rw-r--r--drivers/memstick/core/memstick.c3
-rw-r--r--drivers/mfd/Kconfig44
-rw-r--r--drivers/mfd/Makefile6
-rw-r--r--drivers/mfd/ab8500-core.c2
-rw-r--r--drivers/mfd/axp20x.c16
-rw-r--r--drivers/mfd/db8500-prcmu-regs.h (renamed from drivers/mfd/dbx500-prcmu-regs.h)0
-rw-r--r--drivers/mfd/db8500-prcmu.c25
-rw-r--r--drivers/mfd/hi6421-spmi-pmic.c72
-rw-r--r--drivers/mfd/intel-lpss-acpi.c18
-rw-r--r--drivers/mfd/intel-lpss.c3
-rw-r--r--drivers/mfd/intel-m10-bmc.c12
-rw-r--r--drivers/mfd/intel_quark_i2c_gpio.c71
-rw-r--r--drivers/mfd/lpc_ich.c1
-rw-r--r--drivers/mfd/lpc_sch.c4
-rw-r--r--drivers/mfd/mcp-core.c3
-rw-r--r--drivers/mfd/mt6360-core.c8
-rw-r--r--drivers/mfd/rsmu.h16
-rw-r--r--drivers/mfd/rsmu_core.c88
-rw-r--r--drivers/mfd/rsmu_i2c.c203
-rw-r--r--drivers/mfd/rsmu_spi.c273
-rw-r--r--drivers/mfd/simple-mfd-i2c.c41
-rw-r--r--drivers/mfd/simple-mfd-i2c.h32
-rw-r--r--drivers/mfd/stmpe.c4
-rw-r--r--drivers/mfd/syscon.c2
-rw-r--r--drivers/mfd/tc3589x.c2
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c5
-rw-r--r--drivers/mfd/tps65086.c22
-rw-r--r--drivers/mfd/tqmx86.c48
-rw-r--r--drivers/mfd/wm8994-irq.c2
-rw-r--r--drivers/misc/Kconfig22
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/bcm-vk/bcm_vk_tty.c8
-rw-r--r--drivers/misc/gehc-achc.c565
-rw-r--r--drivers/misc/hi6421v600-irq.c307
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d.h1
-rw-r--r--drivers/misc/lkdtm/bugs.c51
-rw-r--r--drivers/misc/lkdtm/core.c8
-rw-r--r--drivers/misc/lkdtm/fortify.c53
-rw-r--r--drivers/misc/lkdtm/heap.c9
-rw-r--r--drivers/misc/lkdtm/lkdtm.h24
-rw-r--r--drivers/misc/mei/bus.c22
-rw-r--r--drivers/misc/mei/client.h2
-rw-r--r--drivers/misc/mei/mei_dev.h2
-rw-r--r--drivers/misc/pci_endpoint_test.c1
-rw-r--r--drivers/misc/pvpanic/pvpanic-pci.c2
-rw-r--r--drivers/misc/pvpanic/pvpanic.c2
-rw-r--r--drivers/misc/sgi-gru/grumain.c6
-rw-r--r--drivers/misc/sgi-gru/grutables.h3
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c8
-rw-r--r--drivers/misc/sram.c103
-rw-r--r--drivers/misc/sram.h9
-rw-r--r--drivers/misc/tifm_core.c3
-rw-r--r--drivers/misc/vmw_vmci/vmci_queue_pair.c6
-rw-r--r--drivers/mmc/core/bus.c4
-rw-r--r--drivers/mmc/core/sdio_bus.c4
-rw-r--r--drivers/mmc/core/sdio_uart.c12
-rw-r--r--drivers/mmc/host/jz4740_mmc.c4
-rw-r--r--drivers/mmc/host/mmc_spi.c2
-rw-r--r--drivers/most/most_cdev.c8
-rw-r--r--drivers/mtd/Kconfig10
-rw-r--r--drivers/mtd/ftl.c2
-rw-r--r--drivers/mtd/maps/Kconfig23
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/pmcmsp-flash.c227
-rw-r--r--drivers/mtd/mtd_blkdevs.c60
-rw-r--r--drivers/mtd/mtdblock.c4
-rw-r--r--drivers/mtd/mtdblock_ro.c4
-rw-r--r--drivers/mtd/mtdconcat.c33
-rw-r--r--drivers/mtd/nand/raw/Kconfig4
-rw-r--r--drivers/mtd/nand/raw/cafe_nand.c4
-rw-r--r--drivers/mtd/nand/raw/intel-nand-controller.c27
-rw-r--r--drivers/mtd/nand/raw/meson_nand.c4
-rw-r--r--drivers/mtd/nand/raw/nand_bbt.c33
-rw-r--r--drivers/mtd/nand/raw/omap2.c2
-rw-r--r--drivers/mtd/nand/spi/core.c4
-rw-r--r--drivers/mtd/nand/spi/macronix.c16
-rw-r--r--drivers/mtd/rfd_ftl.c46
-rw-r--r--drivers/net/bonding/bond_3ad.c8
-rw-r--r--drivers/net/bonding/bond_main.c17
-rw-r--r--drivers/net/can/c_can/c_can_ethtool.c4
-rw-r--r--drivers/net/can/rcar/rcar_canfd.c2
-rw-r--r--drivers/net/dsa/b53/b53_common.c34
-rw-r--r--drivers/net/dsa/b53/b53_priv.h1
-rw-r--r--drivers/net/dsa/lantiq_gswip.c9
-rw-r--r--drivers/net/dsa/qca8k.c30
-rw-r--r--drivers/net/ethernet/3com/3c59x.c2
-rw-r--r--drivers/net/ethernet/8390/mac8390.c3
-rw-r--r--drivers/net/ethernet/8390/ne.c22
-rw-r--r--drivers/net/ethernet/amd/ni65.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c88
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h37
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c51
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h4
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c14
-rw-r--r--drivers/net/ethernet/cadence/macb_pci.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/cxgb2.c1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/sge.c3
-rw-r--r--drivers/net/ethernet/cirrus/Kconfig2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c14
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c19
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c6
-rw-r--r--drivers/net/ethernet/i825xx/lasi_82596.c3
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.c2
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c16
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_idc.c6
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c17
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.h1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c42
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h28
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c12
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/devlink.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag.c10
-rw-r--r--drivers/net/ethernet/microsoft/mana/hw_channel.c4
-rw-r--r--drivers/net/ethernet/natsemi/macsonic.c4
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_ethtool.c5
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.c12
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_cxt.c4
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c6
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c1
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-ethtool.c2
-rw-r--r--drivers/net/ethernet/rdc/r6040.c9
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c1
-rw-r--r--drivers/net/ethernet/sfc/efx_channels.c106
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h8
-rw-r--r--drivers/net/ethernet/sfc/tx.c29
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c62
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c44
-rw-r--r--drivers/net/ethernet/xscale/ptp_ixp46x.c1
-rw-r--r--drivers/net/ipa/ipa_table.c3
-rw-r--r--drivers/net/netdevsim/bus.c3
-rw-r--r--drivers/net/phy/phylink.c112
-rw-r--r--drivers/net/usb/cdc_mbim.c5
-rw-r--r--drivers/net/usb/hso.c23
-rw-r--r--drivers/net/usb/qmi_wwan.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/Kconfig1
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c1
-rw-r--r--drivers/net/wireless/intersil/orinoco/hermes.c1
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_imem.h1
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_mmio.c30
-rw-r--r--drivers/ntb/core.c4
-rw-r--r--drivers/ntb/hw/amd/ntb_hw_amd.c12
-rw-r--r--drivers/ntb/hw/idt/ntb_hw_idt.c15
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_gen1.c12
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.h3
-rw-r--r--drivers/ntb/ntb_transport.c4
-rw-r--r--drivers/ntb/test/ntb_msi_test.c4
-rw-r--r--drivers/ntb/test/ntb_perf.c1
-rw-r--r--drivers/ntb/test/ntb_pingpong.c2
-rw-r--r--drivers/nubus/bus.c8
-rw-r--r--drivers/nvdimm/bus.c3
-rw-r--r--drivers/nvmem/Kconfig11
-rw-r--r--drivers/nvmem/Makefile2
-rw-r--r--drivers/nvmem/core.c7
-rw-r--r--drivers/nvmem/nintendo-otp.c124
-rw-r--r--drivers/nvmem/qfprom.c31
-rw-r--r--drivers/of/base.c5
-rw-r--r--drivers/of/device.c40
-rw-r--r--drivers/of/fdt.c137
-rw-r--r--drivers/of/kexec.c40
-rw-r--r--drivers/of/kobj.c2
-rw-r--r--drivers/of/of_reserved_mem.c12
-rw-r--r--drivers/of/property.c10
-rw-r--r--drivers/parisc/ccio-dma.c96
-rw-r--r--drivers/parisc/led.c4
-rw-r--r--drivers/parisc/sba_iommu.c2
-rw-r--r--drivers/parport/ieee1284_ops.c2
-rw-r--r--drivers/parport/parport_gsc.c8
-rw-r--r--drivers/parport/parport_serial.c9
-rw-r--r--drivers/pci/endpoint/pci-epf-core.c7
-rw-r--r--drivers/pci/pci-driver.c31
-rw-r--r--drivers/pci/pci-sysfs.c6
-rw-r--r--drivers/pci/xen-pcifront.c32
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/phy/Kconfig2
-rw-r--r--drivers/phy/amlogic/phy-meson8b-usb2.c8
-rw-r--r--drivers/phy/cadence/phy-cadence-torrent.c2577
-rw-r--r--drivers/phy/mediatek/phy-mtk-hdmi.c7
-rw-r--r--drivers/phy/mediatek/phy-mtk-mipi-dsi.c13
-rw-r--r--drivers/phy/mediatek/phy-mtk-tphy.c224
-rw-r--r--drivers/phy/mediatek/phy-mtk-ufs.c44
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.c321
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.h18
-rw-r--r--drivers/phy/qualcomm/phy-qcom-usb-hs.c2
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb2.c97
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c4
-rw-r--r--drivers/phy/samsung/Makefile5
-rw-r--r--drivers/phy/samsung/phy-exynos7-ufs.c (renamed from drivers/phy/samsung/phy-exynos7-ufs.h)8
-rw-r--r--drivers/phy/samsung/phy-exynosautov9-ufs.c67
-rw-r--r--drivers/phy/samsung/phy-samsung-ufs.c3
-rw-r--r--drivers/phy/samsung/phy-samsung-ufs.h13
-rw-r--r--drivers/phy/tegra/xusb.c4
-rw-r--r--drivers/phy/ti/phy-twl4030-usb.c15
-rw-r--r--drivers/phy/xilinx/phy-zynqmp.c3
-rw-r--r--drivers/pinctrl/Kconfig24
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed.c4
-rw-r--r--drivers/pinctrl/aspeed/pinmux-aspeed.c3
-rw-r--r--drivers/pinctrl/aspeed/pinmux-aspeed.h1
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c3
-rw-r--r--drivers/pinctrl/freescale/Kconfig7
-rw-r--r--drivers/pinctrl/freescale/Makefile1
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx8dxl.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx8mn.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx8qxp.c2
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx8ulp.c278
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt8365.c1
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-37xx.c16
-rw-r--r--drivers/pinctrl/pinctrl-ingenic.c545
-rw-r--r--drivers/pinctrl/pinctrl-keembay.c1731
-rw-r--r--drivers/pinctrl/pinctrl-single.c21
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c6
-rw-r--r--drivers/pinctrl/pinctrl-zynq.c2
-rw-r--r--drivers/pinctrl/pinctrl-zynqmp.c10
-rw-r--r--drivers/pinctrl/qcom/Kconfig17
-rw-r--r--drivers/pinctrl/qcom/Makefile2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-mdm9607.c1087
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6115.c923
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c37
-rw-r--r--drivers/pinctrl/renesas/Kconfig11
-rw-r--r--drivers/pinctrl/renesas/Makefile1
-rw-r--r--drivers/pinctrl/renesas/core.c29
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a77995.c320
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzg2l.c1175
-rw-r--r--drivers/pinctrl/renesas/pinctrl.c16
-rw-r--r--drivers/pinctrl/renesas/sh_pfc.h7
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos-arm64.c116
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.h29
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c4
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h1
-rw-r--r--drivers/pinctrl/stm32/Kconfig6
-rw-r--r--drivers/pinctrl/stm32/Makefile1
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32mp135.c1679
-rw-r--r--drivers/platform/mellanox/mlxbf-pmc.c13
-rw-r--r--drivers/platform/surface/aggregator/Makefile15
-rw-r--r--drivers/platform/surface/aggregator/bus.c4
-rw-r--r--drivers/platform/surface/aggregator/core.c9
-rw-r--r--drivers/platform/surface/surface3_power.c8
-rw-r--r--drivers/platform/x86/Kconfig291
-rw-r--r--drivers/platform/x86/Makefile29
-rw-r--r--drivers/platform/x86/acer-wmi.c179
-rw-r--r--drivers/platform/x86/asus-wmi.c416
-rw-r--r--drivers/platform/x86/dell/Kconfig2
-rw-r--r--drivers/platform/x86/dell/dcdbas.c4
-rw-r--r--drivers/platform/x86/dell/dell-smbios-smm.c31
-rw-r--r--drivers/platform/x86/dell/dell-smbios-wmi.c3
-rw-r--r--drivers/platform/x86/dell/dell-smo8800.c74
-rw-r--r--drivers/platform/x86/dual_accel_detect.h26
-rw-r--r--drivers/platform/x86/hp_accel.c78
-rw-r--r--drivers/platform/x86/i2c-multi-instantiate.c27
-rw-r--r--drivers/platform/x86/ideapad-laptop.c9
-rw-r--r--drivers/platform/x86/intel/Kconfig149
-rw-r--r--drivers/platform/x86/intel/Makefile39
-rw-r--r--drivers/platform/x86/intel/atomisp2/Kconfig43
-rw-r--r--drivers/platform/x86/intel/atomisp2/Makefile9
-rw-r--r--drivers/platform/x86/intel/atomisp2/led.c (renamed from drivers/platform/x86/intel_atomisp2_led.c)0
-rw-r--r--drivers/platform/x86/intel/atomisp2/pm.c (renamed from drivers/platform/x86/intel_atomisp2_pm.c)0
-rw-r--r--drivers/platform/x86/intel/bxtwc_tmu.c (renamed from drivers/platform/x86/intel_bxtwc_tmu.c)0
-rw-r--r--drivers/platform/x86/intel/chtdc_ti_pwrbtn.c (renamed from drivers/platform/x86/intel_chtdc_ti_pwrbtn.c)0
-rw-r--r--drivers/platform/x86/intel/hid.c (renamed from drivers/platform/x86/intel-hid.c)2
-rw-r--r--drivers/platform/x86/intel/int0002_vgpio.c (renamed from drivers/platform/x86/intel_int0002_vgpio.c)0
-rw-r--r--drivers/platform/x86/intel/int1092/Kconfig14
-rw-r--r--drivers/platform/x86/intel/int1092/Makefile1
-rw-r--r--drivers/platform/x86/intel/int1092/intel_sar.c316
-rw-r--r--drivers/platform/x86/intel/int1092/intel_sar.h86
-rw-r--r--drivers/platform/x86/intel/int33fe/Makefile2
-rw-r--r--drivers/platform/x86/intel/int33fe/intel_cht_int33fe_common.c29
-rw-r--r--drivers/platform/x86/intel/int3472/Makefile2
-rw-r--r--drivers/platform/x86/intel/mrfld_pwrbtn.c (renamed from drivers/platform/x86/intel_mrfld_pwrbtn.c)0
-rw-r--r--drivers/platform/x86/intel/oaktrail.c (renamed from drivers/platform/x86/intel_oaktrail.c)0
-rw-r--r--drivers/platform/x86/intel/pmc/Kconfig25
-rw-r--r--drivers/platform/x86/intel/pmc/Makefile9
-rw-r--r--drivers/platform/x86/intel/pmc/core.c (renamed from drivers/platform/x86/intel_pmc_core.c)374
-rw-r--r--drivers/platform/x86/intel/pmc/core.h (renamed from drivers/platform/x86/intel_pmc_core.h)19
-rw-r--r--drivers/platform/x86/intel/pmc/pltdrv.c (renamed from drivers/platform/x86/intel_pmc_core_pltdrv.c)0
-rw-r--r--drivers/platform/x86/intel/pmt/Kconfig40
-rw-r--r--drivers/platform/x86/intel/pmt/Makefile12
-rw-r--r--drivers/platform/x86/intel/pmt/class.c (renamed from drivers/platform/x86/intel_pmt_class.c)2
-rw-r--r--drivers/platform/x86/intel/pmt/class.h (renamed from drivers/platform/x86/intel_pmt_class.h)0
-rw-r--r--drivers/platform/x86/intel/pmt/crashlog.c (renamed from drivers/platform/x86/intel_pmt_crashlog.c)2
-rw-r--r--drivers/platform/x86/intel/pmt/telemetry.c (renamed from drivers/platform/x86/intel_pmt_telemetry.c)10
-rw-r--r--drivers/platform/x86/intel/punit_ipc.c (renamed from drivers/platform/x86/intel_punit_ipc.c)0
-rw-r--r--drivers/platform/x86/intel/rst.c (renamed from drivers/platform/x86/intel-rst.c)0
-rw-r--r--drivers/platform/x86/intel/smartconnect.c (renamed from drivers/platform/x86/intel-smartconnect.c)0
-rw-r--r--drivers/platform/x86/intel/speed_select_if/Kconfig (renamed from drivers/platform/x86/intel_speed_select_if/Kconfig)0
-rw-r--r--drivers/platform/x86/intel/speed_select_if/Makefile (renamed from drivers/platform/x86/intel_speed_select_if/Makefile)0
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_common.c (renamed from drivers/platform/x86/intel_speed_select_if/isst_if_common.c)9
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_common.h (renamed from drivers/platform/x86/intel_speed_select_if/isst_if_common.h)0
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c (renamed from drivers/platform/x86/intel_speed_select_if/isst_if_mbox_msr.c)0
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_mbox_pci.c (renamed from drivers/platform/x86/intel_speed_select_if/isst_if_mbox_pci.c)0
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_mmio.c (renamed from drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c)0
-rw-r--r--drivers/platform/x86/intel/telemetry/Kconfig16
-rw-r--r--drivers/platform/x86/intel/telemetry/Makefile11
-rw-r--r--drivers/platform/x86/intel/telemetry/core.c (renamed from drivers/platform/x86/intel_telemetry_core.c)0
-rw-r--r--drivers/platform/x86/intel/telemetry/debugfs.c (renamed from drivers/platform/x86/intel_telemetry_debugfs.c)0
-rw-r--r--drivers/platform/x86/intel/telemetry/pltdrv.c (renamed from drivers/platform/x86/intel_telemetry_pltdrv.c)0
-rw-r--r--drivers/platform/x86/intel/turbo_max_3.c (renamed from drivers/platform/x86/intel_turbo_max_3.c)0
-rw-r--r--drivers/platform/x86/intel/uncore-frequency.c (renamed from drivers/platform/x86/intel-uncore-frequency.c)0
-rw-r--r--drivers/platform/x86/intel/vbtn.c (renamed from drivers/platform/x86/intel-vbtn.c)2
-rw-r--r--drivers/platform/x86/intel/wmi/Kconfig31
-rw-r--r--drivers/platform/x86/intel/wmi/Makefile9
-rw-r--r--drivers/platform/x86/intel/wmi/sbl-fw-update.c (renamed from drivers/platform/x86/intel-wmi-sbl-fw-update.c)0
-rw-r--r--drivers/platform/x86/intel/wmi/thunderbolt.c (renamed from drivers/platform/x86/intel-wmi-thunderbolt.c)0
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c2
-rw-r--r--drivers/platform/x86/lg-laptop.c107
-rw-r--r--drivers/platform/x86/meraki-mx100.c230
-rw-r--r--drivers/platform/x86/think-lmi.c80
-rw-r--r--drivers/platform/x86/think-lmi.h1
-rw-r--r--drivers/platform/x86/wmi.c4
-rw-r--r--drivers/pnp/driver.c3
-rw-r--r--drivers/pps/clients/pps_parport.c42
-rw-r--r--drivers/rapidio/rio-driver.c4
-rw-r--r--drivers/remoteproc/qcom_q6v5_pas.c1
-rw-r--r--drivers/remoteproc/qcom_wcnss.c49
-rw-r--r--drivers/remoteproc/qcom_wcnss.h4
-rw-r--r--drivers/remoteproc/qcom_wcnss_iris.c120
-rw-r--r--drivers/remoteproc/remoteproc_core.c4
-rw-r--r--drivers/remoteproc/remoteproc_elf_helpers.h2
-rw-r--r--drivers/reset/Kconfig8
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/reset-qcom-pdc.c62
-rw-r--r--drivers/reset/reset-rzg2l-usbphy-ctrl.c175
-rw-r--r--drivers/rpmsg/rpmsg_core.c7
-rw-r--r--drivers/s390/block/scm_drv.c4
-rw-r--r--drivers/s390/char/con3215.c11
-rw-r--r--drivers/s390/char/sclp_tty.c15
-rw-r--r--drivers/s390/char/sclp_vt220.c9
-rw-r--r--drivers/s390/char/tty3270.c4
-rw-r--r--drivers/s390/cio/ccwgroup.c6
-rw-r--r--drivers/s390/cio/chsc_sch.c3
-rw-r--r--drivers/s390/cio/css.c7
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.c9
-rw-r--r--drivers/s390/cio/eadm_sch.c4
-rw-r--r--drivers/s390/cio/scm.c5
-rw-r--r--drivers/s390/cio/vfio_ccw_drv.c3
-rw-r--r--drivers/s390/cio/vfio_ccw_ops.c8
-rw-r--r--drivers/s390/crypto/ap_bus.c4
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c282
-rw-r--r--drivers/s390/crypto/vfio_ap_private.h6
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c6
-rw-r--r--drivers/scsi/53c700.c2
-rw-r--r--drivers/scsi/BusLogic.c8
-rw-r--r--drivers/scsi/Kconfig18
-rw-r--r--drivers/scsi/Makefile9
-rw-r--r--drivers/scsi/NCR5380.c6
-rw-r--r--drivers/scsi/aacraid/aachba.c3
-rw-r--r--drivers/scsi/aacraid/commsup.c2
-rw-r--r--drivers/scsi/advansys.c4
-rw-r--r--drivers/scsi/aha1542.c6
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c84
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c2
-rw-r--r--drivers/scsi/ch.c73
-rw-r--r--drivers/scsi/csiostor/csio_scsi.c6
-rw-r--r--drivers/scsi/cxlflash/main.c2
-rw-r--r--drivers/scsi/dpt_i2o.c4
-rw-r--r--drivers/scsi/elx/efct/efct_driver.h1
-rw-r--r--drivers/scsi/elx/efct/efct_lio.c2
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c51
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c4
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c2
-rw-r--r--drivers/scsi/hpsa.c6
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c15
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h1
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c2
-rw-r--r--drivers/scsi/ips.c2
-rw-r--r--drivers/scsi/isci/request.c4
-rw-r--r--drivers/scsi/lasi700.c4
-rw-r--r--drivers/scsi/libsas/Kconfig1
-rw-r--r--drivers/scsi/libsas/Makefile2
-rw-r--r--drivers/scsi/libsas/sas_ata.c6
-rw-r--r--drivers/scsi/libsas/sas_discover.c2
-rw-r--r--drivers/scsi/libsas/sas_expander.c2
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c2
-rw-r--r--drivers/scsi/libsas/sas_init.c2
-rw-r--r--drivers/scsi/libsas/sas_phy.c2
-rw-r--r--drivers/scsi/libsas/sas_port.c2
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c8
-rw-r--r--drivers/scsi/lpfc/lpfc.h253
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c247
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c89
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.h10
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h30
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c27
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c223
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.h11
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h9
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c1193
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c221
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h275
-rw-r--r--drivers/scsi/lpfc/lpfc_ids.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c1495
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c15
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c43
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c54
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.h9
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.c11
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c396
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c966
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c4
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c10
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr.h19
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c37
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c76
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c317
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h40
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_config.c37
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.c24
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c160
-rw-r--r--drivers/scsi/mvumi.c2
-rw-r--r--drivers/scsi/myrb.c11
-rw-r--r--drivers/scsi/myrs.c11
-rw-r--r--drivers/scsi/ncr53c8xx.c203
-rw-r--r--drivers/scsi/pcmcia/fdomain_cs.c4
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c2
-rw-r--r--drivers/scsi/qedf/qedf_io.c8
-rw-r--r--drivers/scsi/qedf/qedf_main.c10
-rw-r--r--drivers/scsi/qedi/qedi_fw.c23
-rw-r--r--drivers/scsi/qedi/qedi_iscsi.c36
-rw-r--r--drivers/scsi/qedi/qedi_iscsi.h1
-rw-r--r--drivers/scsi/qedi/qedi_main.c14
-rw-r--r--drivers/scsi/qla1280.c7
-rw-r--r--drivers/scsi/qla2xxx/Makefile3
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c42
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c90
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h221
-rw-r--r--drivers/scsi/qla2xxx/qla_edif.c3461
-rw-r--r--drivers/scsi/qla2xxx/qla_edif.h136
-rw-r--r--drivers/scsi/qla2xxx/qla_edif_bsg.h220
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h13
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h51
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c19
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c347
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h16
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c163
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c357
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c59
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c49
-rw-r--r--drivers/scsi/qla2xxx/qla_nvme.c77
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c257
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c196
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h19
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h6
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c30
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c10
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c14
-rw-r--r--drivers/scsi/qlogicpti.c2
-rw-r--r--drivers/scsi/scsi.c2
-rw-r--r--drivers/scsi/scsi_bsg.c106
-rw-r--r--drivers/scsi/scsi_common.c9
-rw-r--r--drivers/scsi/scsi_debug.c128
-rw-r--r--drivers/scsi/scsi_devinfo.c1
-rw-r--r--drivers/scsi/scsi_error.c16
-rw-r--r--drivers/scsi/scsi_ioctl.c851
-rw-r--r--drivers/scsi/scsi_lib.c37
-rw-r--r--drivers/scsi/scsi_logging.c18
-rw-r--r--drivers/scsi/scsi_priv.h3
-rw-r--r--drivers/scsi/scsi_scan.c5
-rw-r--r--drivers/scsi/scsi_sysfs.c24
-rw-r--r--drivers/scsi/scsi_transport_fc.c2
-rw-r--r--drivers/scsi/scsi_transport_spi.c2
-rw-r--r--drivers/scsi/sd.c125
-rw-r--r--drivers/scsi/sd_zbc.c10
-rw-r--r--drivers/scsi/sg.c33
-rw-r--r--drivers/scsi/smartpqi/Kconfig8
-rw-r--r--drivers/scsi/smartpqi/smartpqi.h8
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c72
-rw-r--r--drivers/scsi/smartpqi/smartpqi_sas_transport.c4
-rw-r--r--drivers/scsi/smartpqi/smartpqi_sis.c4
-rw-r--r--drivers/scsi/smartpqi/smartpqi_sis.h4
-rw-r--r--drivers/scsi/snic/snic_scsi.c14
-rw-r--r--drivers/scsi/sr.c143
-rw-r--r--drivers/scsi/st.c73
-rw-r--r--drivers/scsi/stex.c6
-rw-r--r--drivers/scsi/storvsc_drv.c4
-rw-r--r--drivers/scsi/sun3_scsi.c5
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c4
-rw-r--r--drivers/scsi/ufs/Kconfig16
-rw-r--r--drivers/scsi/ufs/Makefile2
-rw-r--r--drivers/scsi/ufs/cdns-pltfrm.c7
-rw-r--r--drivers/scsi/ufs/tc-dwc-g210-pci.c32
-rw-r--r--drivers/scsi/ufs/tc-dwc-g210-pltfrm.c7
-rw-r--r--drivers/scsi/ufs/ufs-exynos.c11
-rw-r--r--drivers/scsi/ufs/ufs-exynos.h2
-rw-r--r--drivers/scsi/ufs/ufs-fault-injection.c70
-rw-r--r--drivers/scsi/ufs/ufs-fault-injection.h24
-rw-r--r--drivers/scsi/ufs/ufs-hisi.c7
-rw-r--r--drivers/scsi/ufs/ufs-mediatek.c7
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c7
-rw-r--r--drivers/scsi/ufs/ufs-sysfs.c25
-rw-r--r--drivers/scsi/ufs/ufs.h54
-rw-r--r--drivers/scsi/ufs/ufs_quirks.h6
-rw-r--r--drivers/scsi/ufs/ufshcd-pci.c48
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.c47
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.h18
-rw-r--r--drivers/scsi/ufs/ufshcd.c634
-rw-r--r--drivers/scsi/ufs/ufshcd.h107
-rw-r--r--drivers/scsi/ufs/ufshci.h1
-rw-r--r--drivers/scsi/ufs/ufshpb.c2933
-rw-r--r--drivers/scsi/ufs/ufshpb.h323
-rw-r--r--drivers/scsi/virtio_scsi.c4
-rw-r--r--drivers/scsi/wd719x.c8
-rw-r--r--drivers/scsi/xen-scsifront.c2
-rw-r--r--drivers/scsi/zalon.c4
-rw-r--r--drivers/sh/superhyway/superhyway.c8
-rw-r--r--drivers/siox/siox-core.c4
-rw-r--r--drivers/slimbus/core.c4
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-ctrl.c35
-rw-r--r--drivers/soc/aspeed/aspeed-p2a-ctrl.c2
-rw-r--r--drivers/soc/aspeed/aspeed-socinfo.c1
-rw-r--r--drivers/soc/mediatek/mt8173-pm-domains.h1
-rw-r--r--drivers/soc/mediatek/mt8183-mmsys.h21
-rw-r--r--drivers/soc/mediatek/mt8365-mmsys.h60
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.c18
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.h137
-rw-r--r--drivers/soc/mediatek/mtk-pm-domains.h2
-rw-r--r--drivers/soc/qcom/apr.c4
-rw-r--r--drivers/soc/qcom/cpr.c43
-rw-r--r--drivers/soc/qcom/mdt_loader.c18
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c30
-rw-r--r--drivers/soc/qcom/qcom_aoss.c9
-rw-r--r--drivers/soc/qcom/rpmhpd.c5
-rw-r--r--drivers/soc/qcom/rpmpd.c28
-rw-r--r--drivers/soc/qcom/smd-rpm.c1
-rw-r--r--drivers/soc/qcom/smsm.c28
-rw-r--r--drivers/soc/qcom/socinfo.c4
-rw-r--r--drivers/soc/renesas/Kconfig2
-rw-r--r--drivers/soc/renesas/r8a779a0-sysc.c6
-rw-r--r--drivers/soc/renesas/rcar-sysc.c6
-rw-r--r--drivers/soc/renesas/renesas-soc.c4
-rw-r--r--drivers/soc/rockchip/Kconfig4
-rw-r--r--drivers/soc/rockchip/io-domain.c88
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c60
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra20.c11
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra30.c16
-rw-r--r--drivers/soc/tegra/fuse/fuse.h2
-rw-r--r--drivers/soc/tegra/pmc.c14
-rw-r--r--drivers/soc/tegra/powergate-bpmp.c1
-rw-r--r--drivers/soc/ti/pruss.c1
-rw-r--r--drivers/soc/ti/smartreflex.c52
-rw-r--r--drivers/soundwire/bus.c14
-rw-r--r--drivers/soundwire/cadence_master.c229
-rw-r--r--drivers/soundwire/cadence_master.h7
-rw-r--r--drivers/soundwire/dmi-quirks.c36
-rw-r--r--drivers/soundwire/intel.c240
-rw-r--r--drivers/soundwire/intel.h1
-rw-r--r--drivers/soundwire/intel_init.c14
-rw-r--r--drivers/soundwire/stream.c5
-rw-r--r--drivers/spi/spi-altera-dfl.c21
-rw-r--r--drivers/spi/spi-imx.c41
-rw-r--r--drivers/spi/spi.c4
-rw-r--r--drivers/spi/spidev.c1
-rw-r--r--drivers/spmi/spmi.c3
-rw-r--r--drivers/ssb/main.c4
-rw-r--r--drivers/staging/Kconfig4
-rw-r--r--drivers/staging/Makefile3
-rw-r--r--drivers/staging/board/board.c7
-rw-r--r--drivers/staging/clocking-wizard/Kconfig2
-rw-r--r--drivers/staging/fbtft/fbtft-core.c23
-rw-r--r--drivers/staging/fieldbus/anybuss/host.c4
-rw-r--r--drivers/staging/fwserial/fwserial.c8
-rw-r--r--drivers/staging/gdm724x/gdm_tty.c13
-rw-r--r--drivers/staging/gdm724x/netlink_k.c4
-rw-r--r--drivers/staging/greybus/gbphy.c4
-rw-r--r--drivers/staging/greybus/uart.c4
-rw-r--r--drivers/staging/hikey9xx/Kconfig19
-rw-r--r--drivers/staging/hikey9xx/Makefile3
-rw-r--r--drivers/staging/hikey9xx/TODO5
-rw-r--r--drivers/staging/hikey9xx/hi6421-spmi-pmic.c311
-rw-r--r--drivers/staging/ks7010/ks7010_sdio.c2
-rw-r--r--drivers/staging/ks7010/ks_wlan_net.c10
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc2235.c13
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c22
-rw-r--r--drivers/staging/media/atomisp/i2c/ov2680.h2
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat.h2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_css20.c38
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2.c3
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_drvfs.c6
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c8
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c4
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c62
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp_local.h2
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/print_support.h2
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_env.h2
-rw-r--r--drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h2
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h4
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_local.h32
-rw-r--r--drivers/staging/media/atomisp/pci/isp_acquisition_defs.h2
-rw-r--r--drivers/staging/media/atomisp/pci/isp_capture_defs.h2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c14
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css.c47
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_firmware.c6
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_internal.h2
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_mipi.c69
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_params.c171
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_sp.c108
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_version.c3
-rw-r--r--drivers/staging/media/hantro/Makefile1
-rw-r--r--drivers/staging/media/hantro/hantro.h4
-rw-r--r--drivers/staging/media/hantro/hantro_drv.c11
-rw-r--r--drivers/staging/media/hantro/hantro_g1_h264_dec.c48
-rw-r--r--drivers/staging/media/hantro/hantro_g1_vp8_dec.c31
-rw-r--r--drivers/staging/media/hantro/hantro_h264.c24
-rw-r--r--drivers/staging/media/hantro/hantro_hw.h8
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c491
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c32
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu_hw.c43
-rw-r--r--drivers/staging/media/hantro/sama5d4_vdec_hw.c6
-rw-r--r--drivers/staging/media/imx/Makefile1
-rw-r--r--drivers/staging/media/imx/imx7-media-csi.c36
-rw-r--r--drivers/staging/media/imx/imx7-mipi-csis.c6
-rw-r--r--drivers/staging/media/imx/imx8mq-mipi-csi2.c991
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_h265.c26
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_video.c1
-rw-r--r--drivers/staging/media/tegra-video/vi.c4
-rw-r--r--drivers/staging/most/video/video.c4
-rw-r--r--drivers/staging/mt7621-pci/pci-mt7621.c13
-rw-r--r--drivers/staging/qlge/qlge_dbg.c4
-rw-r--r--drivers/staging/r8188eu/Kconfig (renamed from drivers/staging/rtl8188eu/Kconfig)7
-rw-r--r--drivers/staging/r8188eu/Makefile105
-rw-r--r--drivers/staging/r8188eu/TODO16
-rw-r--r--drivers/staging/r8188eu/core/rtw_ap.c (renamed from drivers/staging/rtl8188eu/core/rtw_ap.c)763
-rw-r--r--drivers/staging/r8188eu/core/rtw_br_ext.c717
-rw-r--r--drivers/staging/r8188eu/core/rtw_cmd.c2128
-rw-r--r--drivers/staging/r8188eu/core/rtw_debug.c904
-rw-r--r--drivers/staging/r8188eu/core/rtw_efuse.c848
-rw-r--r--drivers/staging/r8188eu/core/rtw_ieee80211.c1539
-rw-r--r--drivers/staging/r8188eu/core/rtw_io.c299
-rw-r--r--drivers/staging/r8188eu/core/rtw_ioctl_set.c891
-rw-r--r--drivers/staging/r8188eu/core/rtw_iol.c192
-rw-r--r--drivers/staging/r8188eu/core/rtw_led.c1612
-rw-r--r--drivers/staging/r8188eu/core/rtw_mlme.c (renamed from drivers/staging/rtl8188eu/core/rtw_mlme.c)1114
-rw-r--r--drivers/staging/r8188eu/core/rtw_mlme_ext.c8327
-rw-r--r--drivers/staging/r8188eu/core/rtw_mp.c935
-rw-r--r--drivers/staging/r8188eu/core/rtw_mp_ioctl.c1170
-rw-r--r--drivers/staging/r8188eu/core/rtw_p2p.c1997
-rw-r--r--drivers/staging/r8188eu/core/rtw_pwrctrl.c (renamed from drivers/staging/rtl8188eu/core/rtw_pwrctrl.c)354
-rw-r--r--drivers/staging/r8188eu/core/rtw_recv.c (renamed from drivers/staging/rtl8188eu/core/rtw_recv.c)888
-rw-r--r--drivers/staging/r8188eu/core/rtw_rf.c (renamed from drivers/staging/rtl8188eu/core/rtw_rf.c)34
-rw-r--r--drivers/staging/r8188eu/core/rtw_security.c1656
-rw-r--r--drivers/staging/r8188eu/core/rtw_sreset.c62
-rw-r--r--drivers/staging/r8188eu/core/rtw_sta_mgt.c (renamed from drivers/staging/rtl8188eu/core/rtw_sta_mgt.c)271
-rw-r--r--drivers/staging/r8188eu/core/rtw_wlan_util.c (renamed from drivers/staging/rtl8188eu/core/rtw_wlan_util.c)940
-rw-r--r--drivers/staging/r8188eu/core/rtw_xmit.c (renamed from drivers/staging/rtl8188eu/core/rtw_xmit.c)840
-rw-r--r--drivers/staging/r8188eu/hal/Hal8188EPwrSeq.c69
-rw-r--r--drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c (renamed from drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c)148
-rw-r--r--drivers/staging/r8188eu/hal/HalHWImg8188E_BB.c (renamed from drivers/staging/rtl8188eu/hal/bb_cfg.c)473
-rw-r--r--drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c213
-rw-r--r--drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c250
-rw-r--r--drivers/staging/r8188eu/hal/HalPhyRf_8188e.c1264
-rw-r--r--drivers/staging/r8188eu/hal/HalPwrSeqCmd.c95
-rw-r--r--drivers/staging/r8188eu/hal/hal_com.c (renamed from drivers/staging/rtl8188eu/hal/hal_com.c)189
-rw-r--r--drivers/staging/r8188eu/hal/hal_intf.c441
-rw-r--r--drivers/staging/r8188eu/hal/odm.c1968
-rw-r--r--drivers/staging/r8188eu/hal/odm_HWConfig.c567
-rw-r--r--drivers/staging/r8188eu/hal/odm_RTL8188E.c337
-rw-r--r--drivers/staging/r8188eu/hal/odm_RegConfig8188E.c98
-rw-r--r--drivers/staging/r8188eu/hal/odm_debug.c6
-rw-r--r--drivers/staging/r8188eu/hal/odm_interface.c178
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_cmd.c (renamed from drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c)422
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_dm.c238
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_hal_init.c2304
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_mp.c798
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_phycfg.c1105
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_rf6052.c550
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c (renamed from drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c)43
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_sreset.c64
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_xmit.c (renamed from drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c)13
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188eu_led.c94
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188eu_recv.c117
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188eu_xmit.c (renamed from drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c)204
-rw-r--r--drivers/staging/r8188eu/hal/usb_halinit.c (renamed from drivers/staging/rtl8188eu/hal/usb_halinit.c)1178
-rw-r--r--drivers/staging/r8188eu/hal/usb_ops_linux.c562
-rw-r--r--drivers/staging/r8188eu/include/Hal8188EPhyCfg.h (renamed from drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h)140
-rw-r--r--drivers/staging/r8188eu/include/Hal8188EPhyReg.h1072
-rw-r--r--drivers/staging/r8188eu/include/Hal8188EPwrSeq.h155
-rw-r--r--drivers/staging/r8188eu/include/Hal8188ERateAdaptive.h64
-rw-r--r--drivers/staging/r8188eu/include/HalHWImg8188E_BB.h27
-rw-r--r--drivers/staging/r8188eu/include/HalHWImg8188E_FW.h16
-rw-r--r--drivers/staging/r8188eu/include/HalHWImg8188E_MAC.h13
-rw-r--r--drivers/staging/r8188eu/include/HalHWImg8188E_RF.h13
-rw-r--r--drivers/staging/r8188eu/include/HalPhyRf_8188e.h41
-rw-r--r--drivers/staging/r8188eu/include/HalPwrSeqCmd.h110
-rw-r--r--drivers/staging/r8188eu/include/HalVerDef.h149
-rw-r--r--drivers/staging/r8188eu/include/basic_types.h (renamed from drivers/staging/rtl8188eu/include/basic_types.h)101
-rw-r--r--drivers/staging/r8188eu/include/drv_types.h323
-rw-r--r--drivers/staging/r8188eu/include/hal_com.h (renamed from drivers/staging/rtl8188eu/include/hal_com.h)28
-rw-r--r--drivers/staging/r8188eu/include/hal_intf.h411
-rw-r--r--drivers/staging/r8188eu/include/ieee80211.h (renamed from drivers/staging/rtl8188eu/include/ieee80211.h)680
-rw-r--r--drivers/staging/r8188eu/include/ieee80211_ext.h271
-rw-r--r--drivers/staging/r8188eu/include/ioctl_cfg80211.h91
-rw-r--r--drivers/staging/r8188eu/include/mlme_osdep.h (renamed from drivers/staging/rtl8188eu/include/mlme_osdep.h)14
-rw-r--r--drivers/staging/r8188eu/include/mp_custom_oid.h333
-rw-r--r--drivers/staging/r8188eu/include/odm.h (renamed from drivers/staging/rtl8188eu/include/odm.h)227
-rw-r--r--drivers/staging/r8188eu/include/odm_HWConfig.h (renamed from drivers/staging/rtl8188eu/include/odm_hwconfig.h)37
-rw-r--r--drivers/staging/r8188eu/include/odm_RTL8188E.h36
-rw-r--r--drivers/staging/r8188eu/include/odm_RegConfig8188E.h27
-rw-r--r--drivers/staging/r8188eu/include/odm_RegDefine11AC.h29
-rw-r--r--drivers/staging/r8188eu/include/odm_RegDefine11N.h143
-rw-r--r--drivers/staging/r8188eu/include/odm_interface.h147
-rw-r--r--drivers/staging/r8188eu/include/odm_precomp.h (renamed from drivers/staging/rtl8188eu/include/odm_precomp.h)45
-rw-r--r--drivers/staging/r8188eu/include/odm_reg.h89
-rw-r--r--drivers/staging/r8188eu/include/odm_types.h45
-rw-r--r--drivers/staging/r8188eu/include/osdep_intf.h64
-rw-r--r--drivers/staging/r8188eu/include/osdep_service.h315
-rw-r--r--drivers/staging/r8188eu/include/recv_osdep.h37
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_cmd.h (renamed from drivers/staging/rtl8188eu/include/rtl8188e_cmd.h)48
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_dm.h (renamed from drivers/staging/rtl8188eu/include/rtl8188e_dm.h)21
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_hal.h (renamed from drivers/staging/rtl8188eu/include/rtl8188e_hal.h)223
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_led.h18
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_recv.h (renamed from drivers/staging/rtl8188eu/include/rtl8188e_recv.h)22
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_rf.h19
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_spec.h (renamed from drivers/staging/rtl8188eu/include/rtl8188e_spec.h)457
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_sreset.h15
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_xmit.h (renamed from drivers/staging/rtl8188eu/include/rtl8188e_xmit.h)51
-rw-r--r--drivers/staging/r8188eu/include/rtw_ap.h (renamed from drivers/staging/rtl8188eu/include/rtw_ap.h)18
-rw-r--r--drivers/staging/r8188eu/include/rtw_br_ext.h49
-rw-r--r--drivers/staging/r8188eu/include/rtw_cmd.h975
-rw-r--r--drivers/staging/r8188eu/include/rtw_debug.h231
-rw-r--r--drivers/staging/r8188eu/include/rtw_eeprom.h (renamed from drivers/staging/rtl8188eu/include/rtw_eeprom.h)32
-rw-r--r--drivers/staging/r8188eu/include/rtw_efuse.h134
-rw-r--r--drivers/staging/r8188eu/include/rtw_event.h97
-rw-r--r--drivers/staging/r8188eu/include/rtw_ht.h28
-rw-r--r--drivers/staging/r8188eu/include/rtw_io.h367
-rw-r--r--drivers/staging/r8188eu/include/rtw_ioctl.h (renamed from drivers/staging/rtl8188eu/include/rtw_ioctl.h)35
-rw-r--r--drivers/staging/r8188eu/include/rtw_ioctl_rtl.h63
-rw-r--r--drivers/staging/r8188eu/include/rtw_ioctl_set.h33
-rw-r--r--drivers/staging/r8188eu/include/rtw_iol.h68
-rw-r--r--drivers/staging/r8188eu/include/rtw_led.h181
-rw-r--r--drivers/staging/r8188eu/include/rtw_mlme.h632
-rw-r--r--drivers/staging/r8188eu/include/rtw_mlme_ext.h (renamed from drivers/staging/rtl8188eu/include/rtw_mlme_ext.h)355
-rw-r--r--drivers/staging/r8188eu/include/rtw_mp.h474
-rw-r--r--drivers/staging/r8188eu/include/rtw_mp_ioctl.h242
-rw-r--r--drivers/staging/r8188eu/include/rtw_mp_phy_regdef.h1063
-rw-r--r--drivers/staging/r8188eu/include/rtw_p2p.h119
-rw-r--r--drivers/staging/r8188eu/include/rtw_pwrctrl.h (renamed from drivers/staging/rtl8188eu/include/rtw_pwrctrl.h)75
-rw-r--r--drivers/staging/r8188eu/include/rtw_recv.h413
-rw-r--r--drivers/staging/r8188eu/include/rtw_rf.h (renamed from drivers/staging/rtl8188eu/include/rtw_rf.h)37
-rw-r--r--drivers/staging/r8188eu/include/rtw_security.h (renamed from drivers/staging/rtl8188eu/include/rtw_security.h)168
-rw-r--r--drivers/staging/r8188eu/include/rtw_sreset.h34
-rw-r--r--drivers/staging/r8188eu/include/rtw_xmit.h (renamed from drivers/staging/rtl8188eu/include/rtw_xmit.h)71
-rw-r--r--drivers/staging/r8188eu/include/sta_info.h (renamed from drivers/staging/rtl8188eu/include/sta_info.h)61
-rw-r--r--drivers/staging/r8188eu/include/usb_ops.h72
-rw-r--r--drivers/staging/r8188eu/include/usb_ops_linux.h39
-rw-r--r--drivers/staging/r8188eu/include/usb_osintf.h29
-rw-r--r--drivers/staging/r8188eu/include/usb_vendor_req.h35
-rw-r--r--drivers/staging/r8188eu/include/wifi.h1029
-rw-r--r--drivers/staging/r8188eu/include/wlan_bssdef.h (renamed from drivers/staging/rtl8188eu/include/wlan_bssdef.h)149
-rw-r--r--drivers/staging/r8188eu/include/xmit_osdep.h51
-rw-r--r--drivers/staging/r8188eu/os_dep/ioctl_linux.c6649
-rw-r--r--drivers/staging/r8188eu/os_dep/mlme_linux.c216
-rw-r--r--drivers/staging/r8188eu/os_dep/os_intfs.c1199
-rw-r--r--drivers/staging/r8188eu/os_dep/osdep_service.c343
-rw-r--r--drivers/staging/r8188eu/os_dep/recv_linux.c (renamed from drivers/staging/rtl8188eu/os_dep/recv_linux.c)128
-rw-r--r--drivers/staging/r8188eu/os_dep/usb_intf.c781
-rw-r--r--drivers/staging/r8188eu/os_dep/usb_ops_linux.c253
-rw-r--r--drivers/staging/r8188eu/os_dep/xmit_linux.c (renamed from drivers/staging/rtl8188eu/os_dep/xmit_linux.c)130
-rw-r--r--drivers/staging/rtl8188eu/Makefile56
-rw-r--r--drivers/staging/rtl8188eu/TODO14
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_cmd.c1219
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_efuse.c876
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ieee80211.c992
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ioctl_set.c512
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_iol.c19
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_led.c460
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme_ext.c5172
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_security.c869
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_sreset.c21
-rw-r--r--drivers/staging/rtl8188eu/hal/fw.c202
-rw-r--r--drivers/staging/rtl8188eu/hal/hal_intf.c60
-rw-r--r--drivers/staging/rtl8188eu/hal/mac_cfg.c120
-rw-r--r--drivers/staging/rtl8188eu/hal/odm.c966
-rw-r--r--drivers/staging/rtl8188eu/hal/odm_hwconfig.c397
-rw-r--r--drivers/staging/rtl8188eu/hal/odm_rtl8188e.c335
-rw-r--r--drivers/staging/rtl8188eu/hal/phy.c1276
-rw-r--r--drivers/staging/rtl8188eu/hal/pwrseq.c88
-rw-r--r--drivers/staging/rtl8188eu/hal/pwrseqcmd.c80
-rw-r--r--drivers/staging/rtl8188eu/hal/rf.c289
-rw-r--r--drivers/staging/rtl8188eu/hal/rf_cfg.c247
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_dm.c217
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c523
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_led.c55
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c83
-rw-r--r--drivers/staging/rtl8188eu/include/HalVerDef.h37
-rw-r--r--drivers/staging/rtl8188eu/include/drv_types.h176
-rw-r--r--drivers/staging/rtl8188eu/include/fw.h44
-rw-r--r--drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h201
-rw-r--r--drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h74
-rw-r--r--drivers/staging/rtl8188eu/include/hal_intf.h223
-rw-r--r--drivers/staging/rtl8188eu/include/mon.h28
-rw-r--r--drivers/staging/rtl8188eu/include/odm_rtl8188e.h39
-rw-r--r--drivers/staging/rtl8188eu/include/odm_types.h24
-rw-r--r--drivers/staging/rtl8188eu/include/osdep_intf.h37
-rw-r--r--drivers/staging/rtl8188eu/include/osdep_service.h81
-rw-r--r--drivers/staging/rtl8188eu/include/phy.h26
-rw-r--r--drivers/staging/rtl8188eu/include/phydm_reg.h22
-rw-r--r--drivers/staging/rtl8188eu/include/phydm_regdefine11n.h53
-rw-r--r--drivers/staging/rtl8188eu/include/pwrseq.h242
-rw-r--r--drivers/staging/rtl8188eu/include/pwrseqcmd.h52
-rw-r--r--drivers/staging/rtl8188eu/include/recv_osdep.h26
-rw-r--r--drivers/staging/rtl8188eu/include/rf.h12
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_android.h51
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_cmd.h361
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_efuse.h67
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_event.h81
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_ht.h26
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_ioctl_set.h28
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_iol.h14
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_led.h98
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mlme.h355
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_recv.h262
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_sreset.h30
-rw-r--r--drivers/staging/rtl8188eu/include/usb_ops_linux.h26
-rw-r--r--drivers/staging/rtl8188eu/include/wifi.h355
-rw-r--r--drivers/staging/rtl8188eu/include/xmit_osdep.h32
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c2777
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mlme_linux.c167
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mon.c183
-rw-r--r--drivers/staging/rtl8188eu/os_dep/os_intfs.c658
-rw-r--r--drivers/staging/rtl8188eu/os_dep/osdep_service.c63
-rw-r--r--drivers/staging/rtl8188eu/os_dep/rtw_android.c231
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_intf.c485
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c644
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c5
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_ccmp.c4
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c57
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c3
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c18
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c49
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c3
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c2
-rw-r--r--drivers/staging/rtl8192u/r819xU_phy.c92
-rw-r--r--drivers/staging/rtl8712/hal_init.c1
-rw-r--r--drivers/staging/rtl8712/os_intfs.c2
-rw-r--r--drivers/staging/rtl8712/osdep_service.h2
-rw-r--r--drivers/staging/rtl8712/wifi.h48
-rw-r--r--drivers/staging/rtl8723bs/Kconfig3
-rw-r--r--drivers/staging/rtl8723bs/Makefile1
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_ap.c135
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_cmd.c54
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_debug.c19
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_ieee80211.c154
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_io.c13
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_ioctl_set.c103
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme.c263
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme_ext.c297
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_recv.c6
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_rf.c1
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_security.c36
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_wlan_util.c147
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c464
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h1
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c414
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h1
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h8
-rw-r--r--drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c17
-rw-r--r--drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c86
-rw-r--r--drivers/staging/rtl8723bs/hal/HalPhyRf.c67
-rw-r--r--drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c191
-rw-r--r--drivers/staging/rtl8723bs/hal/Mp_Precomp.h2
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_btcoex.c111
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com.c172
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com_phycfg.c447
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_sdio.c1
-rw-r--r--drivers/staging/rtl8723bs/hal/odm.c56
-rw-r--r--drivers/staging/rtl8723bs/hal/odm.h25
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_CfoTracking.c36
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_CfoTracking.h2
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DIG.c5
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_HWConfig.c343
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_HWConfig.h29
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c23
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_RTL8723B.c36
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_RTL8723B.h14
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c7
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h11
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h2
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_precomp.h1
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_reg.h4
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c23
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_dm.c12
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c84
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c52
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c21
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c1
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c3
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c1
-rw-r--r--drivers/staging/rtl8723bs/hal/sdio_halinit.c2
-rw-r--r--drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h4
-rw-r--r--drivers/staging/rtl8723bs/include/HalVerDef.h18
-rw-r--r--drivers/staging/rtl8723bs/include/drv_types.h9
-rw-r--r--drivers/staging/rtl8723bs/include/ethernet.h14
-rw-r--r--drivers/staging/rtl8723bs/include/hal_btcoex.h3
-rw-r--r--drivers/staging/rtl8723bs/include/hal_com.h35
-rw-r--r--drivers/staging/rtl8723bs/include/hal_com_phycfg.h20
-rw-r--r--drivers/staging/rtl8723bs/include/hal_com_reg.h19
-rw-r--r--drivers/staging/rtl8723bs/include/hal_data.h24
-rw-r--r--drivers/staging/rtl8723bs/include/hal_pg.h8
-rw-r--r--drivers/staging/rtl8723bs/include/hal_phy.h3
-rw-r--r--drivers/staging/rtl8723bs/include/ieee80211.h42
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_intf.h2
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_service.h4
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_xmit.h8
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_ioctl_set.h1
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mlme.h6
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_recv.h2
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_rf.h10
-rw-r--r--drivers/staging/rtl8723bs/include/wifi.h8
-rw-r--r--drivers/staging/rtl8723bs/include/wlan_bssdef.h92
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c173
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_linux.c3229
-rw-r--r--drivers/staging/rtl8723bs/os_dep/mlme_linux.c4
-rw-r--r--drivers/staging/rtl8723bs/os_dep/os_intfs.c32
-rw-r--r--drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c1
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.c10
-rw-r--r--drivers/staging/sm750fb/sm750.c52
-rw-r--r--drivers/staging/sm750fb/sm750.h12
-rw-r--r--drivers/staging/sm750fb/sm750_cursor.c4
-rw-r--r--drivers/staging/sm750fb/sm750_hw.c62
-rw-r--r--drivers/staging/vc04_services/Kconfig28
-rw-r--r--drivers/staging/vc04_services/Makefile5
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835.h2
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c2
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c564
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c2006
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h82
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c2
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c1440
-rw-r--r--drivers/staging/vt6655/baseband.c2
-rw-r--r--drivers/staging/vt6655/baseband.h2
-rw-r--r--drivers/staging/vt6655/card.c1
-rw-r--r--drivers/staging/vt6655/card.h2
-rw-r--r--drivers/staging/vt6655/channel.c2
-rw-r--r--drivers/staging/vt6655/channel.h1
-rw-r--r--drivers/staging/vt6655/desc.h2
-rw-r--r--drivers/staging/vt6655/device.h2
-rw-r--r--drivers/staging/vt6655/device_cfg.h6
-rw-r--r--drivers/staging/vt6655/device_main.c2
-rw-r--r--drivers/staging/vt6655/dpc.c2
-rw-r--r--drivers/staging/vt6655/dpc.h2
-rw-r--r--drivers/staging/vt6655/key.c2
-rw-r--r--drivers/staging/vt6655/key.h2
-rw-r--r--drivers/staging/vt6655/mac.c3
-rw-r--r--drivers/staging/vt6655/mac.h2
-rw-r--r--drivers/staging/vt6655/power.c2
-rw-r--r--drivers/staging/vt6655/power.h2
-rw-r--r--drivers/staging/vt6655/rf.c2
-rw-r--r--drivers/staging/vt6655/rf.h2
-rw-r--r--drivers/staging/vt6655/rxtx.c2
-rw-r--r--drivers/staging/vt6655/rxtx.h2
-rw-r--r--drivers/staging/vt6655/srom.c2
-rw-r--r--drivers/staging/vt6655/srom.h2
-rw-r--r--drivers/staging/vt6655/tmacro.h2
-rw-r--r--drivers/staging/vt6655/upc.h2
-rw-r--r--drivers/staging/vt6656/baseband.c2
-rw-r--r--drivers/staging/vt6656/baseband.h2
-rw-r--r--drivers/staging/vt6656/card.c1
-rw-r--r--drivers/staging/vt6656/card.h2
-rw-r--r--drivers/staging/vt6656/channel.c2
-rw-r--r--drivers/staging/vt6656/channel.h2
-rw-r--r--drivers/staging/vt6656/desc.h2
-rw-r--r--drivers/staging/vt6656/device.h4
-rw-r--r--drivers/staging/vt6656/key.c2
-rw-r--r--drivers/staging/vt6656/key.h2
-rw-r--r--drivers/staging/vt6656/mac.c2
-rw-r--r--drivers/staging/vt6656/mac.h2
-rw-r--r--drivers/staging/vt6656/main_usb.c2
-rw-r--r--drivers/staging/vt6656/power.c2
-rw-r--r--drivers/staging/vt6656/power.h2
-rw-r--r--drivers/staging/vt6656/rf.c2
-rw-r--r--drivers/staging/vt6656/rf.h2
-rw-r--r--drivers/staging/vt6656/rxtx.c2
-rw-r--r--drivers/staging/vt6656/rxtx.h2
-rw-r--r--drivers/staging/vt6656/usbpipe.c2
-rw-r--r--drivers/staging/vt6656/usbpipe.h2
-rw-r--r--drivers/staging/vt6656/wcmd.c2
-rw-r--r--drivers/staging/vt6656/wcmd.h2
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h19
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c13
-rw-r--r--drivers/staging/wlan-ng/p80211conv.c48
-rw-r--r--drivers/staging/wlan-ng/p80211conv.h2
-rw-r--r--drivers/staging/wlan-ng/p80211hdr.h30
-rw-r--r--drivers/staging/wlan-ng/p80211mgmt.h24
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c12
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.h2
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c8
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c10
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c6
-rw-r--r--drivers/target/Kconfig2
-rw-r--r--drivers/target/iscsi/cxgbit/cxgbit_ddp.c2
-rw-r--r--drivers/target/loopback/tcm_loop.c13
-rw-r--r--drivers/target/sbp/sbp_target.c4
-rw-r--r--drivers/target/target_core_alua.c94
-rw-r--r--drivers/target/target_core_iblock.c2
-rw-r--r--drivers/target/target_core_pscsi.c18
-rw-r--r--drivers/target/target_core_transport.c48
-rw-r--r--drivers/target/target_core_user.c150
-rw-r--r--drivers/target/target_core_xcopy.c26
-rw-r--r--drivers/thermal/intel/Kconfig9
-rw-r--r--drivers/thermal/intel/Makefile1
-rw-r--r--drivers/thermal/intel/intel_menlow.c (renamed from drivers/platform/x86/intel_menlow.c)0
-rw-r--r--drivers/thunderbolt/domain.c4
-rw-r--r--drivers/thunderbolt/nhi.c46
-rw-r--r--drivers/thunderbolt/switch.c28
-rw-r--r--drivers/thunderbolt/test.c98
-rw-r--r--drivers/tty/amiserial.c278
-rw-r--r--drivers/tty/ehv_bytechan.c34
-rw-r--r--drivers/tty/goldfish.c18
-rw-r--r--drivers/tty/hvc/hvc_console.c10
-rw-r--r--drivers/tty/hvc/hvc_xen.c17
-rw-r--r--drivers/tty/hvc/hvcs.c12
-rw-r--r--drivers/tty/hvc/hvsi.c55
-rw-r--r--drivers/tty/ipwireless/tty.c12
-rw-r--r--drivers/tty/mips_ejtag_fdc.c2
-rw-r--r--drivers/tty/moxa.c12
-rw-r--r--drivers/tty/mxser.c24
-rw-r--r--drivers/tty/n_gsm.c13
-rw-r--r--drivers/tty/nozomi.c12
-rw-r--r--drivers/tty/serdev/core.c40
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c2
-rw-r--r--drivers/tty/serial/8250/8250_exar.c36
-rw-r--r--drivers/tty/serial/8250/8250_ingenic.c6
-rw-r--r--drivers/tty/serial/8250/8250_lpss.c10
-rw-r--r--drivers/tty/serial/8250/8250_omap.c27
-rw-r--r--drivers/tty/serial/8250/8250_pci.c2
-rw-r--r--drivers/tty/serial/8250/8250_pnp.c2
-rw-r--r--drivers/tty/serial/8250/8250_port.c3
-rw-r--r--drivers/tty/serial/8250/Kconfig10
-rw-r--r--drivers/tty/serial/Kconfig4
-rw-r--r--drivers/tty/serial/amba-pl011.c163
-rw-r--r--drivers/tty/serial/fsl_linflexuart.c6
-rw-r--r--drivers/tty/serial/fsl_lpuart.c62
-rw-r--r--drivers/tty/serial/jsm/jsm_neo.c2
-rw-r--r--drivers/tty/serial/jsm/jsm_tty.c3
-rw-r--r--drivers/tty/serial/kgdb_nmi.c11
-rw-r--r--drivers/tty/serial/max310x.c15
-rw-r--r--drivers/tty/serial/mux.c3
-rw-r--r--drivers/tty/serial/omap-serial.c75
-rw-r--r--drivers/tty/serial/samsung_tty.c95
-rw-r--r--drivers/tty/serial/serial-tegra.c6
-rw-r--r--drivers/tty/serial/serial_core.c20
-rw-r--r--drivers/tty/serial/sh-sci.c7
-rw-r--r--drivers/tty/serial/stm32-usart.c11
-rw-r--r--drivers/tty/serial/uartlite.c88
-rw-r--r--drivers/tty/serial/vt8500_serial.c7
-rw-r--r--drivers/tty/synclink_gt.c12
-rw-r--r--drivers/tty/sysrq.c4
-rw-r--r--drivers/tty/tty_io.c17
-rw-r--r--drivers/tty/ttynull.c4
-rw-r--r--drivers/tty/vcc.c4
-rw-r--r--drivers/tty/vt/keyboard.c62
-rw-r--r--drivers/tty/vt/vt.c27
-rw-r--r--drivers/usb/Kconfig2
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/cdns3/cdnsp-mem.c2
-rw-r--r--drivers/usb/chipidea/host.c14
-rw-r--r--drivers/usb/class/cdc-acm.c14
-rw-r--r--drivers/usb/common/common.c20
-rw-r--r--drivers/usb/common/ulpi.c4
-rw-r--r--drivers/usb/dwc2/core.c2
-rw-r--r--drivers/usb/dwc2/core.h2
-rw-r--r--drivers/usb/dwc2/gadget.c51
-rw-r--r--drivers/usb/dwc3/core.c24
-rw-r--r--drivers/usb/dwc3/core.h21
-rw-r--r--drivers/usb/dwc3/drd.c8
-rw-r--r--drivers/usb/dwc3/dwc3-imx8mp.c14
-rw-r--r--drivers/usb/dwc3/dwc3-meson-g12a.c2
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c17
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c28
-rw-r--r--drivers/usb/dwc3/ep0.c2
-rw-r--r--drivers/usb/dwc3/gadget.c234
-rw-r--r--drivers/usb/gadget/Kconfig1
-rw-r--r--drivers/usb/gadget/composite.c8
-rw-r--r--drivers/usb/gadget/configfs.c12
-rw-r--r--drivers/usb/gadget/function/f_fs.c4
-rw-r--r--drivers/usb/gadget/function/f_hid.c220
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c30
-rw-r--r--drivers/usb/gadget/function/f_ncm.c50
-rw-r--r--drivers/usb/gadget/function/f_uac1.c674
-rw-r--r--drivers/usb/gadget/function/f_uac2.c652
-rw-r--r--drivers/usb/gadget/function/f_uvc.c1
-rw-r--r--drivers/usb/gadget/function/u_audio.c369
-rw-r--r--drivers/usb/gadget/function/u_audio.h22
-rw-r--r--drivers/usb/gadget/function/u_ether.c5
-rw-r--r--drivers/usb/gadget/function/u_hid.h1
-rw-r--r--drivers/usb/gadget/function/u_serial.c36
-rw-r--r--drivers/usb/gadget/function/u_uac1.h20
-rw-r--r--drivers/usb/gadget/function/u_uac2.h23
-rw-r--r--drivers/usb/gadget/function/uvc.h15
-rw-r--r--drivers/usb/gadget/function/uvc_queue.c28
-rw-r--r--drivers/usb/gadget/function/uvc_queue.h7
-rw-r--r--drivers/usb/gadget/function/uvc_video.c155
-rw-r--r--drivers/usb/gadget/function/uvc_video.h2
-rw-r--r--drivers/usb/gadget/legacy/Kconfig1
-rw-r--r--drivers/usb/gadget/legacy/inode.c4
-rw-r--r--drivers/usb/gadget/legacy/printer.c1
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/core.c5
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/dev.c5
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/ep0.c5
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/epn.c5
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/hub.c5
-rw-r--r--drivers/usb/gadget/udc/at91_udc.c4
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_cmd.c1
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c30
-rw-r--r--drivers/usb/gadget/udc/core.c19
-rw-r--r--drivers/usb/gadget/udc/mv_u3d_core.c19
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.c2
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c17
-rw-r--r--drivers/usb/gadget/udc/s3c2410_udc.c4
-rw-r--r--drivers/usb/gadget/udc/tegra-xudc.c4
-rw-r--r--drivers/usb/host/Kconfig9
-rw-r--r--drivers/usb/host/ehci-brcm.c11
-rw-r--r--drivers/usb/host/ehci-hcd.c5
-rw-r--r--drivers/usb/host/ehci-mv.c23
-rw-r--r--drivers/usb/host/ehci-orion.c8
-rw-r--r--drivers/usb/host/ehci-pmcmsp.c328
-rw-r--r--drivers/usb/host/fotg210-hcd.c48
-rw-r--r--drivers/usb/host/fotg210.h5
-rw-r--r--drivers/usb/host/ohci-spear.c2
-rw-r--r--drivers/usb/host/ohci-tmio.c3
-rw-r--r--drivers/usb/host/xhci-dbgtty.c4
-rw-r--r--drivers/usb/host/xhci-debugfs.c14
-rw-r--r--drivers/usb/host/xhci-hub.c6
-rw-r--r--drivers/usb/host/xhci-mtk-sch.c180
-rw-r--r--drivers/usb/host/xhci-mtk.c79
-rw-r--r--drivers/usb/host/xhci-mtk.h17
-rw-r--r--drivers/usb/host/xhci-pci-renesas.c7
-rw-r--r--drivers/usb/host/xhci-pci.c2
-rw-r--r--drivers/usb/host/xhci-pci.h3
-rw-r--r--drivers/usb/host/xhci-rcar.c7
-rw-r--r--drivers/usb/host/xhci-ring.c76
-rw-r--r--drivers/usb/host/xhci-trace.h26
-rw-r--r--drivers/usb/host/xhci.c30
-rw-r--r--drivers/usb/host/xhci.h73
-rw-r--r--drivers/usb/isp1760/isp1760-core.c54
-rw-r--r--drivers/usb/isp1760/isp1760-hcd.c87
-rw-r--r--drivers/usb/isp1760/isp1760-regs.h16
-rw-r--r--drivers/usb/isp1760/isp1760-udc.c12
-rw-r--r--drivers/usb/misc/adutux.c5
-rw-r--r--drivers/usb/misc/brcmstb-usb-pinmap.c2
-rw-r--r--drivers/usb/mtu3/mtu3.h8
-rw-r--r--drivers/usb/mtu3/mtu3_core.c119
-rw-r--r--drivers/usb/mtu3/mtu3_dr.c26
-rw-r--r--drivers/usb/mtu3/mtu3_dr.h30
-rw-r--r--drivers/usb/mtu3/mtu3_gadget.c11
-rw-r--r--drivers/usb/mtu3/mtu3_host.c108
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c170
-rw-r--r--drivers/usb/musb/musb_dsps.c13
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c2
-rw-r--r--drivers/usb/phy/phy-isp1301-omap.c2
-rw-r--r--drivers/usb/phy/phy-tahvo.c4
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c5
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c2
-rw-r--r--drivers/usb/serial/bus.c4
-rw-r--r--drivers/usb/serial/cp210x.c77
-rw-r--r--drivers/usb/serial/cypress_m8.c6
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/garmin_gps.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c33
-rw-r--r--drivers/usb/serial/io_ti.c4
-rw-r--r--drivers/usb/serial/ipaq.c4
-rw-r--r--drivers/usb/serial/iuu_phoenix.c10
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/serial/usb-serial.c13
-rw-r--r--drivers/usb/storage/transport.c2
-rw-r--r--drivers/usb/typec/bus.c4
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c91
-rw-r--r--drivers/usb/usbip/vhci_hcd.c36
-rw-r--r--drivers/vdpa/vdpa.c4
-rw-r--r--drivers/vfio/Kconfig31
-rw-r--r--drivers/vfio/fsl-mc/Kconfig3
-rw-r--r--drivers/vfio/fsl-mc/vfio_fsl_mc.c159
-rw-r--r--drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c6
-rw-r--r--drivers/vfio/fsl-mc/vfio_fsl_mc_private.h7
-rw-r--r--drivers/vfio/mdev/Kconfig1
-rw-r--r--drivers/vfio/mdev/mdev_core.c6
-rw-r--r--drivers/vfio/mdev/mdev_driver.c4
-rw-r--r--drivers/vfio/mdev/vfio_mdev.c33
-rw-r--r--drivers/vfio/pci/Kconfig40
-rw-r--r--drivers/vfio/pci/Makefile8
-rw-r--r--drivers/vfio/pci/vfio_pci.c2271
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c70
-rw-r--r--drivers/vfio/pci/vfio_pci_core.c2157
-rw-r--r--drivers/vfio/pci/vfio_pci_igd.c23
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c42
-rw-r--r--drivers/vfio/pci/vfio_pci_rdwr.c18
-rw-r--r--drivers/vfio/pci/vfio_pci_zdev.c11
-rw-r--r--drivers/vfio/platform/Kconfig6
-rw-r--r--drivers/vfio/platform/reset/Kconfig4
-rw-r--r--drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c10
-rw-r--r--drivers/vfio/platform/vfio_platform_common.c86
-rw-r--r--drivers/vfio/platform/vfio_platform_private.h1
-rw-r--r--drivers/vfio/vfio.c144
-rw-r--r--drivers/vfio/vfio_iommu_type1.c8
-rw-r--r--drivers/vhost/net.c11
-rw-r--r--drivers/video/backlight/ktd253-backlight.c75
-rw-r--r--drivers/video/backlight/pwm_bl.c54
-rw-r--r--drivers/video/fbdev/arcfb.c2
-rw-r--r--drivers/video/fbdev/asiliantfb.c3
-rw-r--r--drivers/video/fbdev/core/fbmem.c6
-rw-r--r--drivers/video/fbdev/ep93xx-fb.c4
-rw-r--r--drivers/video/fbdev/kyro/fbdev.c8
-rw-r--r--drivers/video/fbdev/neofb.c2
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/apply.c4
-rw-r--r--drivers/video/fbdev/riva/fbdev.c3
-rw-r--r--drivers/video/fbdev/ssd1307fb.c151
-rw-r--r--drivers/virtio/virtio.c3
-rw-r--r--drivers/vlynq/vlynq.c4
-rw-r--r--drivers/vme/vme.c4
-rw-r--r--drivers/watchdog/Kconfig13
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/bcm2835_wdt.c10
-rw-r--r--drivers/watchdog/bd70528_wdt.c291
-rw-r--r--drivers/watchdog/iTCO_wdt.c2
-rw-r--r--drivers/watchdog/imx2_wdt.c1
-rw-r--r--drivers/watchdog/ixp4xx_wdt.c283
-rw-r--r--drivers/watchdog/max63xx_wdt.c24
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c2
-rw-r--r--drivers/watchdog/mtk_wdt.c6
-rw-r--r--drivers/watchdog/sl28cpld_wdt.c2
-rw-r--r--drivers/watchdog/tqmx86_wdt.c2
-rw-r--r--drivers/watchdog/watchdog_core.c37
-rw-r--r--drivers/watchdog/watchdog_dev.c57
-rw-r--r--drivers/xen/features.c18
-rw-r--r--drivers/xen/gntdev.c36
-rw-r--r--drivers/xen/swiotlb-xen.c10
-rw-r--r--drivers/xen/xen-scsiback.c2
-rw-r--r--drivers/xen/xenbus/xenbus.h2
-rw-r--r--drivers/xen/xenbus/xenbus_client.c9
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c4
-rw-r--r--drivers/zorro/zorro-driver.c16
-rw-r--r--fs/9p/acl.c5
-rw-r--r--fs/9p/acl.h2
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/Makefile1
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/befs/debug.c2
-rw-r--r--fs/binfmt_aout.c7
-rw-r--r--fs/binfmt_elf.c6
-rw-r--r--fs/binfmt_elf_fdpic.c2
-rw-r--r--fs/btrfs/acl.c5
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/buffer.c27
-rw-r--r--fs/cachefiles/Kconfig19
-rw-r--r--fs/cachefiles/Makefile2
-rw-r--r--fs/cachefiles/bind.c2
-rw-r--r--fs/cachefiles/interface.c6
-rw-r--r--fs/cachefiles/internal.h25
-rw-r--r--fs/cachefiles/io.c6
-rw-r--r--fs/cachefiles/key.c2
-rw-r--r--fs/cachefiles/main.c7
-rw-r--r--fs/cachefiles/namei.c61
-rw-r--r--fs/cachefiles/proc.c114
-rw-r--r--fs/cachefiles/xattr.c4
-rw-r--r--fs/ceph/acl.c5
-rw-r--r--fs/ceph/super.h2
-rw-r--r--fs/configfs/dir.c87
-rw-r--r--fs/d_path.c93
-rw-r--r--fs/debugfs/file.c8
-rw-r--r--fs/dlm/dir.c4
-rw-r--r--fs/dlm/dlm_internal.h2
-rw-r--r--fs/dlm/lockspace.c3
-rw-r--r--fs/dlm/lowcomms.c770
-rw-r--r--fs/dlm/lowcomms.h1
-rw-r--r--fs/dlm/member.c4
-rw-r--r--fs/dlm/midcomms.c56
-rw-r--r--fs/dlm/rcom.c29
-rw-r--r--fs/dlm/recoverd.c4
-rw-r--r--fs/drop_caches.c3
-rw-r--r--fs/erofs/Kconfig1
-rw-r--r--fs/erofs/data.c415
-rw-r--r--fs/erofs/erofs_fs.h47
-rw-r--r--fs/erofs/inode.c29
-rw-r--r--fs/erofs/internal.h22
-rw-r--r--fs/erofs/namei.c1
-rw-r--r--fs/erofs/super.c61
-rw-r--r--fs/erofs/xattr.c5
-rw-r--r--fs/erofs/xattr.h2
-rw-r--r--fs/erofs/zdata.c6
-rw-r--r--fs/erofs/zmap.c133
-rw-r--r--fs/exec.c12
-rw-r--r--fs/ext2/acl.c5
-rw-r--r--fs/ext2/acl.h2
-rw-r--r--fs/ext4/Makefile2
-rw-r--r--fs/ext4/acl.c5
-rw-r--r--fs/ext4/acl.h2
-rw-r--r--fs/ext4/balloc.c8
-rw-r--r--fs/ext4/ext4.h108
-rw-r--r--fs/ext4/ext4_extents.h5
-rw-r--r--fs/ext4/ext4_jbd2.c43
-rw-r--r--fs/ext4/ext4_jbd2.h18
-rw-r--r--fs/ext4/extents.c17
-rw-r--r--fs/ext4/fast_commit.c27
-rw-r--r--fs/ext4/file.c3
-rw-r--r--fs/ext4/ialloc.c19
-rw-r--r--fs/ext4/indirect.c15
-rw-r--r--fs/ext4/inline.c32
-rw-r--r--fs/ext4/inode.c301
-rw-r--r--fs/ext4/ioctl.c4
-rw-r--r--fs/ext4/mballoc.c259
-rw-r--r--fs/ext4/namei.c214
-rw-r--r--fs/ext4/orphan.c652
-rw-r--r--fs/ext4/resize.c38
-rw-r--r--fs/ext4/super.c238
-rw-r--r--fs/ext4/xattr.c26
-rw-r--r--fs/f2fs/Kconfig19
-rw-r--r--fs/f2fs/Makefile1
-rw-r--r--fs/f2fs/acl.c5
-rw-r--r--fs/f2fs/acl.h2
-rw-r--r--fs/f2fs/checkpoint.c57
-rw-r--r--fs/f2fs/compress.c97
-rw-r--r--fs/f2fs/data.c202
-rw-r--r--fs/f2fs/debug.c39
-rw-r--r--fs/f2fs/dir.c18
-rw-r--r--fs/f2fs/extent_cache.c46
-rw-r--r--fs/f2fs/f2fs.h177
-rw-r--r--fs/f2fs/file.c70
-rw-r--r--fs/f2fs/gc.c14
-rw-r--r--fs/f2fs/iostat.c287
-rw-r--r--fs/f2fs/iostat.h84
-rw-r--r--fs/f2fs/node.c165
-rw-r--r--fs/f2fs/recovery.c3
-rw-r--r--fs/f2fs/segment.c137
-rw-r--r--fs/f2fs/segment.h4
-rw-r--r--fs/f2fs/super.c242
-rw-r--r--fs/f2fs/sysfs.c156
-rw-r--r--fs/f2fs/xattr.c3
-rw-r--r--fs/fat/.kunitconfig5
-rw-r--r--fs/fat/Kconfig14
-rw-r--r--fs/fat/Makefile2
-rw-r--r--fs/fat/fat_test.c196
-rw-r--r--fs/fat/misc.c3
-rw-r--r--fs/fcntl.c3
-rw-r--r--fs/fs-writeback.c28
-rw-r--r--fs/fs_context.c4
-rw-r--r--fs/fscache/Kconfig25
-rw-r--r--fs/fscache/Makefile2
-rw-r--r--fs/fscache/cache.c11
-rw-r--r--fs/fscache/cookie.c201
-rw-r--r--fs/fscache/fsdef.c3
-rw-r--r--fs/fscache/histogram.c87
-rw-r--r--fs/fscache/internal.h57
-rw-r--r--fs/fscache/main.c39
-rw-r--r--fs/fscache/netfs.c2
-rw-r--r--fs/fscache/object-list.c414
-rw-r--r--fs/fscache/object.c8
-rw-r--r--fs/fscache/operation.c3
-rw-r--r--fs/fscache/page.c6
-rw-r--r--fs/fscache/proc.c20
-rw-r--r--fs/fuse/acl.c5
-rw-r--r--fs/fuse/control.c10
-rw-r--r--fs/fuse/dev.c4
-rw-r--r--fs/fuse/file.c45
-rw-r--r--fs/fuse/fuse_i.h22
-rw-r--r--fs/fuse/inode.c203
-rw-r--r--fs/fuse/virtio_fs.c12
-rw-r--r--fs/gfs2/acl.c5
-rw-r--r--fs/gfs2/acl.h2
-rw-r--r--fs/inode.c2
-rw-r--r--fs/io-wq.c424
-rw-r--r--fs/io_uring.c76
-rw-r--r--fs/jbd2/recovery.c29
-rw-r--r--fs/jbd2/transaction.c21
-rw-r--r--fs/jffs2/acl.c5
-rw-r--r--fs/jffs2/acl.h2
-rw-r--r--fs/jfs/acl.c5
-rw-r--r--fs/jfs/jfs_acl.h2
-rw-r--r--fs/kernfs/dir.c153
-rw-r--r--fs/kernfs/file.c4
-rw-r--r--fs/kernfs/inode.c26
-rw-r--r--fs/kernfs/kernfs-internal.h24
-rw-r--r--fs/kernfs/mount.c12
-rw-r--r--fs/kernfs/symlink.c4
-rw-r--r--fs/lockd/svc.c2
-rw-r--r--fs/namei.c8
-rw-r--r--fs/namespace.c7
-rw-r--r--fs/nfs/callback.c4
-rw-r--r--fs/nfs/callback_xdr.c61
-rw-r--r--fs/nfs/client.c2
-rw-r--r--fs/nfs/fs_context.c7
-rw-r--r--fs/nfs/internal.h2
-rw-r--r--fs/nfs/nfs3_fs.h2
-rw-r--r--fs/nfs/nfs3acl.c5
-rw-r--r--fs/nfs/nfs3proc.c3
-rw-r--r--fs/nfs/nfs4client.c41
-rw-r--r--fs/nfs/nfs4file.c10
-rw-r--r--fs/nfs/pnfs.c20
-rw-r--r--fs/nfs/read.c8
-rw-r--r--fs/nfs/super.c2
-rw-r--r--fs/nfsd/Kconfig2
-rw-r--r--fs/ntfs3/Kconfig46
-rw-r--r--fs/ntfs3/Makefile36
-rw-r--r--fs/ntfs3/attrib.c2093
-rw-r--r--fs/ntfs3/attrlist.c460
-rw-r--r--fs/ntfs3/bitfunc.c134
-rw-r--r--fs/ntfs3/bitmap.c1493
-rw-r--r--fs/ntfs3/debug.h52
-rw-r--r--fs/ntfs3/dir.c599
-rw-r--r--fs/ntfs3/file.c1251
-rw-r--r--fs/ntfs3/frecord.c3257
-rw-r--r--fs/ntfs3/fslog.c5217
-rw-r--r--fs/ntfs3/fsntfs.c2509
-rw-r--r--fs/ntfs3/index.c2650
-rw-r--r--fs/ntfs3/inode.c1957
-rw-r--r--fs/ntfs3/lib/decompress_common.c319
-rw-r--r--fs/ntfs3/lib/decompress_common.h338
-rw-r--r--fs/ntfs3/lib/lib.h26
-rw-r--r--fs/ntfs3/lib/lzx_decompress.c670
-rw-r--r--fs/ntfs3/lib/xpress_decompress.c142
-rw-r--r--fs/ntfs3/lznt.c453
-rw-r--r--fs/ntfs3/namei.c411
-rw-r--r--fs/ntfs3/ntfs.h1216
-rw-r--r--fs/ntfs3/ntfs_fs.h1111
-rw-r--r--fs/ntfs3/record.c605
-rw-r--r--fs/ntfs3/run.c1113
-rw-r--r--fs/ntfs3/super.c1512
-rw-r--r--fs/ntfs3/upcase.c108
-rw-r--r--fs/ntfs3/xattr.c1122
-rw-r--r--fs/ocfs2/acl.c5
-rw-r--r--fs/ocfs2/acl.h2
-rw-r--r--fs/ocfs2/dlmglue.c14
-rw-r--r--fs/ocfs2/quota_global.c1
-rw-r--r--fs/ocfs2/quota_local.c2
-rw-r--r--fs/orangefs/acl.c5
-rw-r--r--fs/orangefs/inode.c7
-rw-r--r--fs/orangefs/orangefs-kernel.h2
-rw-r--r--fs/overlayfs/copy_up.c83
-rw-r--r--fs/overlayfs/dir.c16
-rw-r--r--fs/overlayfs/inode.c105
-rw-r--r--fs/overlayfs/namei.c4
-rw-r--r--fs/overlayfs/overlayfs.h44
-rw-r--r--fs/overlayfs/super.c4
-rw-r--r--fs/overlayfs/util.c92
-rw-r--r--fs/posix_acl.c15
-rw-r--r--fs/proc/task_mmu.c1
-rw-r--r--fs/reiserfs/acl.h2
-rw-r--r--fs/reiserfs/prints.c2
-rw-r--r--fs/reiserfs/xattr_acl.c5
-rw-r--r--fs/signalfd.c4
-rw-r--r--fs/stat.c18
-rw-r--r--fs/sysfs/file.c4
-rw-r--r--fs/sysfs/group.c2
-rw-r--r--fs/ufs/super.c2
-rw-r--r--fs/userfaultfd.c116
-rw-r--r--fs/xfs/kmem.c64
-rw-r--r--fs/xfs/kmem.h2
-rw-r--r--fs/xfs/libxfs/xfs_ag.c25
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c56
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h12
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.c100
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.h2
-rw-r--r--fs/xfs/libxfs/xfs_attr.c56
-rw-r--r--fs/xfs/libxfs/xfs_attr.h1
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.c57
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.c21
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.h2
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c38
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c56
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.h9
-rw-r--r--fs/xfs/libxfs/xfs_btree.c141
-rw-r--r--fs/xfs/libxfs/xfs_btree.h56
-rw-r--r--fs/xfs/libxfs/xfs_btree_staging.c14
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.c18
-rw-r--r--fs/xfs/libxfs/xfs_da_format.h2
-rw-r--r--fs/xfs/libxfs/xfs_dir2.c6
-rw-r--r--fs/xfs/libxfs/xfs_dir2_block.c14
-rw-r--r--fs/xfs/libxfs/xfs_dir2_data.c20
-rw-r--r--fs/xfs/libxfs/xfs_dir2_leaf.c14
-rw-r--r--fs/xfs/libxfs/xfs_dir2_node.c20
-rw-r--r--fs/xfs/libxfs/xfs_dir2_priv.h2
-rw-r--r--fs/xfs/libxfs/xfs_dir2_sf.c12
-rw-r--r--fs/xfs/libxfs/xfs_dquot_buf.c8
-rw-r--r--fs/xfs/libxfs/xfs_format.h226
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c69
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.h3
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c88
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.h2
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c22
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.h11
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h6
-rw-r--r--fs/xfs/libxfs/xfs_log_recover.h2
-rw-r--r--fs/xfs/libxfs/xfs_log_rlimit.c2
-rw-r--r--fs/xfs/libxfs/xfs_quota_defs.h30
-rw-r--r--fs/xfs/libxfs/xfs_refcount.c12
-rw-r--r--fs/xfs/libxfs/xfs_refcount.h2
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.c54
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c34
-rw-r--r--fs/xfs/libxfs/xfs_rmap.h11
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c72
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.h2
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.c14
-rw-r--r--fs/xfs/libxfs/xfs_sb.c263
-rw-r--r--fs/xfs/libxfs/xfs_sb.h4
-rw-r--r--fs/xfs/libxfs/xfs_symlink_remote.c14
-rw-r--r--fs/xfs/libxfs/xfs_trans_inode.c2
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c48
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.h2
-rw-r--r--fs/xfs/libxfs/xfs_trans_space.h6
-rw-r--r--fs/xfs/libxfs/xfs_types.c2
-rw-r--r--fs/xfs/libxfs/xfs_types.h5
-rw-r--r--fs/xfs/scrub/agheader.c47
-rw-r--r--fs/xfs/scrub/agheader_repair.c66
-rw-r--r--fs/xfs/scrub/alloc.c2
-rw-r--r--fs/xfs/scrub/attr.c16
-rw-r--r--fs/xfs/scrub/attr.h3
-rw-r--r--fs/xfs/scrub/bitmap.c4
-rw-r--r--fs/xfs/scrub/bmap.c41
-rw-r--r--fs/xfs/scrub/btree.c9
-rw-r--r--fs/xfs/scrub/btree.h4
-rw-r--r--fs/xfs/scrub/common.c77
-rw-r--r--fs/xfs/scrub/common.h18
-rw-r--r--fs/xfs/scrub/dabtree.c4
-rw-r--r--fs/xfs/scrub/dir.c10
-rw-r--r--fs/xfs/scrub/fscounters.c6
-rw-r--r--fs/xfs/scrub/ialloc.c4
-rw-r--r--fs/xfs/scrub/inode.c14
-rw-r--r--fs/xfs/scrub/quota.c4
-rw-r--r--fs/xfs/scrub/refcount.c4
-rw-r--r--fs/xfs/scrub/repair.c32
-rw-r--r--fs/xfs/scrub/rmap.c2
-rw-r--r--fs/xfs/scrub/rtbitmap.c2
-rw-r--r--fs/xfs/scrub/scrub.c23
-rw-r--r--fs/xfs/scrub/scrub.h3
-rw-r--r--fs/xfs/scrub/trace.c8
-rw-r--r--fs/xfs/scrub/trace.h78
-rw-r--r--fs/xfs/xfs_acl.c7
-rw-r--r--fs/xfs/xfs_acl.h4
-rw-r--r--fs/xfs/xfs_aops.c25
-rw-r--r--fs/xfs/xfs_attr_inactive.c6
-rw-r--r--fs/xfs/xfs_attr_list.c2
-rw-r--r--fs/xfs/xfs_bmap_item.c14
-rw-r--r--fs/xfs/xfs_bmap_util.c20
-rw-r--r--fs/xfs/xfs_buf.c40
-rw-r--r--fs/xfs/xfs_buf.h25
-rw-r--r--fs/xfs/xfs_buf_item.c6
-rw-r--r--fs/xfs/xfs_buf_item_recover.c10
-rw-r--r--fs/xfs/xfs_dir2_readdir.c4
-rw-r--r--fs/xfs/xfs_discard.c2
-rw-r--r--fs/xfs/xfs_dquot.c13
-rw-r--r--fs/xfs/xfs_dquot.h10
-rw-r--r--fs/xfs/xfs_dquot_item.c134
-rw-r--r--fs/xfs/xfs_dquot_item.h17
-rw-r--r--fs/xfs/xfs_dquot_item_recover.c4
-rw-r--r--fs/xfs/xfs_error.c4
-rw-r--r--fs/xfs/xfs_error.h12
-rw-r--r--fs/xfs/xfs_export.c4
-rw-r--r--fs/xfs/xfs_extfree_item.c3
-rw-r--r--fs/xfs/xfs_file.c18
-rw-r--r--fs/xfs/xfs_filestream.c2
-rw-r--r--fs/xfs/xfs_filestream.h2
-rw-r--r--fs/xfs/xfs_fsmap.c68
-rw-r--r--fs/xfs/xfs_fsops.c67
-rw-r--r--fs/xfs/xfs_health.c2
-rw-r--r--fs/xfs/xfs_icache.c754
-rw-r--r--fs/xfs/xfs_icache.h14
-rw-r--r--fs/xfs/xfs_icreate_item.c4
-rw-r--r--fs/xfs/xfs_inode.c102
-rw-r--r--fs/xfs/xfs_inode.h25
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_inode_item_recover.c2
-rw-r--r--fs/xfs/xfs_ioctl.c33
-rw-r--r--fs/xfs/xfs_ioctl32.c4
-rw-r--r--fs/xfs/xfs_iomap.c24
-rw-r--r--fs/xfs/xfs_iops.c32
-rw-r--r--fs/xfs/xfs_itable.c44
-rw-r--r--fs/xfs/xfs_iwalk.c33
-rw-r--r--fs/xfs/xfs_log.c721
-rw-r--r--fs/xfs/xfs_log.h7
-rw-r--r--fs/xfs/xfs_log_cil.c450
-rw-r--r--fs/xfs/xfs_log_priv.h66
-rw-r--r--fs/xfs/xfs_log_recover.c161
-rw-r--r--fs/xfs/xfs_mount.c233
-rw-r--r--fs/xfs/xfs_mount.h248
-rw-r--r--fs/xfs/xfs_pnfs.c2
-rw-r--r--fs/xfs/xfs_qm.c96
-rw-r--r--fs/xfs/xfs_qm.h3
-rw-r--r--fs/xfs/xfs_qm_bhv.c2
-rw-r--r--fs/xfs/xfs_qm_syscalls.c253
-rw-r--r--fs/xfs/xfs_quota.h2
-rw-r--r--fs/xfs/xfs_quotaops.c30
-rw-r--r--fs/xfs/xfs_refcount_item.c5
-rw-r--r--fs/xfs/xfs_reflink.c4
-rw-r--r--fs/xfs/xfs_reflink.h3
-rw-r--r--fs/xfs/xfs_rmap_item.c5
-rw-r--r--fs/xfs/xfs_rtalloc.c6
-rw-r--r--fs/xfs/xfs_rtalloc.h13
-rw-r--r--fs/xfs/xfs_super.c536
-rw-r--r--fs/xfs/xfs_symlink.c13
-rw-r--r--fs/xfs/xfs_sysfs.c1
-rw-r--r--fs/xfs/xfs_trace.c2
-rw-r--r--fs/xfs/xfs_trace.h386
-rw-r--r--fs/xfs/xfs_trans.c33
-rw-r--r--fs/xfs/xfs_trans_ail.c19
-rw-r--r--fs/xfs/xfs_trans_buf.c8
-rw-r--r--fs/xfs/xfs_trans_dquot.c51
-rw-r--r--include/acpi/platform/acgcc.h2
-rw-r--r--include/asm-generic/bitops/builtin-ffs.h2
-rw-r--r--include/asm-generic/bitops/ffs.h2
-rw-r--r--include/asm-generic/bitops/non-atomic.h14
-rw-r--r--include/asm-generic/mshyperv.h13
-rw-r--r--include/asm-generic/uaccess.h53
-rw-r--r--include/asm-generic/vmlinux.lds.h13
-rw-r--r--include/clocksource/hyperv_timer.h11
-rw-r--r--include/drm/amd_asic_type.h17
-rw-r--r--include/drm/bridge/dw_hdmi.h2
-rw-r--r--include/drm/drm_aperture.h14
-rw-r--r--include/drm/drm_auth.h68
-rw-r--r--include/drm/drm_bridge.h26
-rw-r--r--include/drm/drm_connector.h10
-rw-r--r--include/drm/drm_damage_helper.h18
-rw-r--r--include/drm/drm_device.h18
-rw-r--r--include/drm/drm_dp_aux_bus.h57
-rw-r--r--include/drm/drm_dp_helper.h175
-rw-r--r--include/drm/drm_drv.h44
-rw-r--r--include/drm/drm_edid.h2
-rw-r--r--include/drm/drm_file.h22
-rw-r--r--include/drm/drm_fourcc.h13
-rw-r--r--include/drm/drm_framebuffer.h8
-rw-r--r--include/drm/drm_gem.h2
-rw-r--r--include/drm/drm_gem_atomic_helper.h17
-rw-r--r--include/drm/drm_gem_framebuffer_helper.h13
-rw-r--r--include/drm/drm_gem_vram_helper.h16
-rw-r--r--include/drm/drm_legacy.h3
-rw-r--r--include/drm/drm_mipi_dbi.h7
-rw-r--r--include/drm/drm_mipi_dsi.h13
-rw-r--r--include/drm/drm_modeset_helper_vtables.h7
-rw-r--r--include/drm/drm_panel.h8
-rw-r--r--include/drm/drm_plane.h39
-rw-r--r--include/drm/drm_print.h2
-rw-r--r--include/drm/drm_property.h9
-rw-r--r--include/drm/drm_rect.h3
-rw-r--r--include/drm/drm_simple_kms_helper.h34
-rw-r--r--include/drm/drm_vma_manager.h2
-rw-r--r--include/drm/gpu_scheduler.h37
-rw-r--r--include/drm/ttm/ttm_placement.h7
-rw-r--r--include/dt-bindings/clock/imx8mn-clock.h4
-rw-r--r--include/dt-bindings/clock/mt8192-clk.h585
-rw-r--r--include/dt-bindings/clock/qcom,dispcc-sc7280.h55
-rw-r--r--include/dt-bindings/clock/qcom,gcc-msm8953.h234
-rw-r--r--include/dt-bindings/clock/qcom,gcc-sc7280.h2
-rw-r--r--include/dt-bindings/clock/qcom,gcc-sm6115.h201
-rw-r--r--include/dt-bindings/clock/qcom,gcc-sm6350.h178
-rw-r--r--include/dt-bindings/clock/qcom,gpucc-sc7280.h35
-rw-r--r--include/dt-bindings/clock/qcom,mmcc-msm8994.h155
-rw-r--r--include/dt-bindings/clock/qcom,rpmcc.h10
-rw-r--r--include/dt-bindings/clock/qcom,rpmh.h2
-rw-r--r--include/dt-bindings/clock/qcom,videocc-sc7280.h27
-rw-r--r--include/dt-bindings/clock/r9a07g044-cpg.h1
-rw-r--r--include/dt-bindings/clock/rk3036-cru.h1
-rw-r--r--include/dt-bindings/clock/zx296718-clock.h164
-rw-r--r--include/dt-bindings/gce/mt8192-gce.h335
-rw-r--r--include/dt-bindings/gce/mt8195-gce.h812
-rw-r--r--include/dt-bindings/iio/adc/ingenic,adc.h1
-rw-r--r--include/dt-bindings/interconnect/qcom,sc8180x.h185
-rw-r--r--include/dt-bindings/phy/phy.h2
-rw-r--r--include/dt-bindings/pinctrl/mt8135-pinfunc.h (renamed from arch/arm/boot/dts/mt8135-pinfunc.h)0
-rw-r--r--include/dt-bindings/pinctrl/mt8183-pinfunc.h (renamed from arch/arm64/boot/dts/mediatek/mt8183-pinfunc.h)0
-rw-r--r--include/dt-bindings/pinctrl/pinctrl-zynq.h17
-rw-r--r--include/dt-bindings/pinctrl/rzg2l-pinctrl.h23
-rw-r--r--include/dt-bindings/power/qcom-rpmpd.h10
-rw-r--r--include/dt-bindings/reset/mt8195-resets.h29
-rw-r--r--include/dt-bindings/reset/qcom,sdm845-pdc.h2
-rw-r--r--include/dt-bindings/soc/zte,pm_domains.h24
-rw-r--r--include/linux/backing-dev-defs.h2
-rw-r--r--include/linux/backing-dev.h19
-rw-r--r--include/linux/bitmap.h6
-rw-r--r--include/linux/blkdev.h33
-rw-r--r--include/linux/bsg-lib.h1
-rw-r--r--include/linux/bsg.h38
-rw-r--r--include/linux/buffer_head.h2
-rw-r--r--include/linux/cdrom.h6
-rw-r--r--include/linux/clk-provider.h14
-rw-r--r--include/linux/clk/at91_pmc.h26
-rw-r--r--include/linux/compaction.h2
-rw-r--r--include/linux/coresight.h9
-rw-r--r--include/linux/counter.h32
-rw-r--r--include/linux/cpuhotplug.h1
-rw-r--r--include/linux/cpumask.h38
-rw-r--r--include/linux/crash_dump.h3
-rw-r--r--include/linux/dev_printk.h66
-rw-r--r--include/linux/device.h4
-rw-r--r--include/linux/device/bus.h2
-rw-r--r--include/linux/dfl.h1
-rw-r--r--include/linux/dma-buf.h170
-rw-r--r--include/linux/dma-fence-chain.h52
-rw-r--r--include/linux/dma-iommu.h6
-rw-r--r--include/linux/dma-map-ops.h23
-rw-r--r--include/linux/dma-mapping.h44
-rw-r--r--include/linux/entry-kvm.h6
-rw-r--r--include/linux/etherdevice.h12
-rw-r--r--include/linux/fb.h3
-rw-r--r--include/linux/filter.h2
-rw-r--r--include/linux/firmware/xlnx-zynqmp.h10
-rw-r--r--include/linux/fpga/fpga-mgr.h2
-rw-r--r--include/linux/fs.h27
-rw-r--r--include/linux/fscache-cache.h4
-rw-r--r--include/linux/fscache.h4
-rw-r--r--include/linux/gpio/consumer.h14
-rw-r--r--include/linux/gpio/driver.h4
-rw-r--r--include/linux/hardirq.h2
-rw-r--r--include/linux/highmem.h5
-rw-r--r--include/linux/host1x.h27
-rw-r--r--include/linux/hugetlb_cgroup.h12
-rw-r--r--include/linux/hyperv.h16
-rw-r--r--include/linux/i2c.h5
-rw-r--r--include/linux/ima.h23
-rw-r--r--include/linux/intel-iommu.h6
-rw-r--r--include/linux/intel-svm.h5
-rw-r--r--include/linux/io-pgtable.h20
-rw-r--r--include/linux/iommu.h136
-rw-r--r--include/linux/kasan-tags.h15
-rw-r--r--include/linux/kdb.h27
-rw-r--r--include/linux/kernel.h2
-rw-r--r--include/linux/kernfs.h7
-rw-r--r--include/linux/kvm_host.h236
-rw-r--r--include/linux/kvm_types.h7
-rw-r--r--include/linux/libata.h1
-rw-r--r--include/linux/lockdep.h41
-rw-r--r--include/linux/mISDNif.h1
-rw-r--r--include/linux/mdev.h9
-rw-r--r--include/linux/mei_cl_bus.h9
-rw-r--r--include/linux/memblock.h2
-rw-r--r--include/linux/memcontrol.h104
-rw-r--r--include/linux/memory.h2
-rw-r--r--include/linux/mempolicy.h16
-rw-r--r--include/linux/mfd/dbx500-prcmu.h3
-rw-r--r--include/linux/mfd/hi6421-spmi-pmic.h5
-rw-r--r--include/linux/mfd/idt82p33_reg.h112
-rw-r--r--include/linux/mfd/idt8a340_reg.h729
-rw-r--r--include/linux/mfd/rsmu.h36
-rw-r--r--include/linux/mhi.h2
-rw-r--r--include/linux/migrate.h14
-rw-r--r--include/linux/mm.h13
-rw-r--r--include/linux/mman.h4
-rw-r--r--include/linux/mmzone.h4
-rw-r--r--include/linux/mod_devicetable.h6
-rw-r--r--include/linux/module.h5
-rw-r--r--include/linux/netdevice.h18
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h1
-rw-r--r--include/linux/netfs.h2
-rw-r--r--include/linux/nfs_fs.h5
-rw-r--r--include/linux/nfs_fs_sb.h1
-rw-r--r--include/linux/nubus.h2
-rw-r--r--include/linux/of.h7
-rw-r--r--include/linux/of_fdt.h3
-rw-r--r--include/linux/of_gpio.h15
-rw-r--r--include/linux/omap-gpmc.h3
-rw-r--r--include/linux/page-flags.h37
-rw-r--r--include/linux/pagemap.h4
-rw-r--r--include/linux/pci-epf.h2
-rw-r--r--include/linux/pci.h29
-rw-r--r--include/linux/phylink.h3
-rw-r--r--include/linux/platform_data/davinci_asp.h1
-rw-r--r--include/linux/platform_data/gpio-dwapb.h25
-rw-r--r--include/linux/platform_data/pata_ixp4xx_cf.h4
-rw-r--r--include/linux/platform_data/x86/asus-wmi.h7
-rw-r--r--include/linux/platform_data/x86/clk-lpss.h2
-rw-r--r--include/linux/platform_device.h2
-rw-r--r--include/linux/pm_clock.h5
-rw-r--r--include/linux/pm_runtime.h4
-rw-r--r--include/linux/posix_acl.h3
-rw-r--r--include/linux/power/smartreflex.h2
-rw-r--r--include/linux/printk.h173
-rw-r--r--include/linux/qcom-geni-se.h19
-rw-r--r--include/linux/remoteproc.h5
-rw-r--r--include/linux/scatterlist.h56
-rw-r--r--include/linux/sched/mm.h10
-rw-r--r--include/linux/sched/signal.h12
-rw-r--r--include/linux/serdev.h14
-rw-r--r--include/linux/serial_s3c.h9
-rw-r--r--include/linux/shmem_fs.h25
-rw-r--r--include/linux/signal.h2
-rw-r--r--include/linux/skbuff.h2
-rw-r--r--include/linux/soc/marvell/octeontx2/asm.h11
-rw-r--r--include/linux/soc/qcom/smd-rpm.h1
-rw-r--r--include/linux/soundwire/sdw.h3
-rw-r--r--include/linux/soundwire/sdw_intel.h87
-rw-r--r--include/linux/spi/max7301.h2
-rw-r--r--include/linux/stat.h4
-rw-r--r--include/linux/stdarg.h11
-rw-r--r--include/linux/string.h2
-rw-r--r--include/linux/sunrpc/clnt.h5
-rw-r--r--include/linux/sunrpc/svc.h3
-rw-r--r--include/linux/sunrpc/svcauth.h4
-rw-r--r--include/linux/sunrpc/xprt.h1
-rw-r--r--include/linux/sunrpc/xprtmultipath.h1
-rw-r--r--include/linux/swap.h28
-rw-r--r--include/linux/swiotlb.h57
-rw-r--r--include/linux/syscalls.h2
-rw-r--r--include/linux/sysfb.h (renamed from arch/x86/include/asm/sysfb.h)32
-rw-r--r--include/linux/sysfs.h2
-rw-r--r--include/linux/thunderbolt.h2
-rw-r--r--include/linux/trace_events.h52
-rw-r--r--include/linux/tracepoint.h2
-rw-r--r--include/linux/tty.h275
-rw-r--r--include/linux/tty_buffer.h59
-rw-r--r--include/linux/tty_driver.h39
-rw-r--r--include/linux/tty_flip.h8
-rw-r--r--include/linux/tty_ldisc.h17
-rw-r--r--include/linux/tty_port.h208
-rw-r--r--include/linux/usb/audio-v2.h14
-rw-r--r--include/linux/usb/ehci_def.h33
-rw-r--r--include/linux/usb/gadget.h6
-rw-r--r--include/linux/usb/otg.h1
-rw-r--r--include/linux/userfaultfd_k.h8
-rw-r--r--include/linux/vfio.h26
-rw-r--r--include/linux/vfio_pci_core.h (renamed from drivers/vfio/pci/vfio_pci_private.h)96
-rw-r--r--include/linux/vgaarb.h118
-rw-r--r--include/linux/vm_event_item.h2
-rw-r--r--include/linux/vmpressure.h2
-rw-r--r--include/linux/vt_kern.h30
-rw-r--r--include/linux/watchdog.h10
-rw-r--r--include/linux/writeback.h4
-rw-r--r--include/linux/zorro.h1
-rw-r--r--include/media/dvb-usb-ids.h2
-rw-r--r--include/media/hevc-ctrls.h3
-rw-r--r--include/media/rc-core.h5
-rw-r--r--include/media/v4l2-async.h30
-rw-r--r--include/media/v4l2-subdev.h27
-rw-r--r--include/net/flow.h4
-rw-r--r--include/rdma/ib_sa.h24
-rw-r--r--include/rdma/ib_umem.h11
-rw-r--r--include/rdma/ib_verbs.h74
-rw-r--r--include/rdma/rdmavt_qp.h2
-rw-r--r--include/scsi/scsi_cmnd.h39
-rw-r--r--include/scsi/scsi_device.h22
-rw-r--r--include/scsi/scsi_devinfo.h6
-rw-r--r--include/scsi/scsi_ioctl.h9
-rw-r--r--include/scsi/scsi_request.h2
-rw-r--r--include/soc/at91/sama7-ddr.h80
-rw-r--r--include/soc/at91/sama7-sfrbu.h34
-rw-r--r--include/soc/tegra/pm.h6
-rw-r--r--include/sound/compress_driver.h2
-rw-r--r--include/sound/core.h6
-rw-r--r--include/sound/emu10k1.h6
-rw-r--r--include/sound/emu8000.h3
-rw-r--r--include/sound/hda_codec.h1
-rw-r--r--include/sound/hdaudio_ext.h2
-rw-r--r--include/sound/memalloc.h10
-rw-r--r--include/sound/pcm.h47
-rw-r--r--include/sound/pxa2xx-lib.h13
-rw-r--r--include/sound/sof.h1
-rw-r--r--include/target/target_core_backend.h1
-rw-r--r--include/target/target_core_base.h10
-rw-r--r--include/trace/events/cachefiles.h68
-rw-r--r--include/trace/events/f2fs.h97
-rw-r--r--include/trace/events/fscache.h160
-rw-r--r--include/trace/events/io_uring.h6
-rw-r--r--include/trace/events/migrate.h3
-rw-r--r--include/trace/events/mmflags.h1
-rw-r--r--include/trace/events/netfs.h2
-rw-r--r--include/trace/events/rpcrdma.h74
-rw-r--r--include/trace/events/sunrpc.h60
-rw-r--r--include/uapi/asm-generic/siginfo.h5
-rw-r--r--include/uapi/asm-generic/unistd.h4
-rw-r--r--include/uapi/drm/drm.h14
-rw-r--r--include/uapi/drm/drm_fourcc.h109
-rw-r--r--include/uapi/drm/drm_mode.h92
-rw-r--r--include/uapi/drm/i915_drm.h498
-rw-r--r--include/uapi/drm/msm_drm.h14
-rw-r--r--include/uapi/drm/tegra_drm.h425
-rw-r--r--include/uapi/drm/v3d_drm.h136
-rw-r--r--include/uapi/drm/vmwgfx_drm.h41
-rw-r--r--include/uapi/linux/capability.h1
-rw-r--r--include/uapi/linux/cec.h2
-rw-r--r--include/uapi/linux/dma-buf.h50
-rw-r--r--include/uapi/linux/kfd_ioctl.h16
-rw-r--r--include/uapi/linux/kvm.h11
-rw-r--r--include/uapi/linux/mempolicy.h1
-rw-r--r--include/uapi/linux/netfilter/nfnetlink_conntrack.h1
-rw-r--r--include/uapi/linux/pkt_sched.h2
-rw-r--r--include/uapi/linux/prctl.h11
-rw-r--r--include/uapi/linux/serial_reg.h1
-rw-r--r--include/uapi/linux/target_core_user.h2
-rw-r--r--include/uapi/linux/v4l2-controls.h1
-rw-r--r--include/uapi/linux/virtio_gpio.h47
-rw-r--r--include/uapi/linux/virtio_ids.h2
-rw-r--r--include/uapi/linux/virtio_scmi.h24
-rw-r--r--include/uapi/rdma/mlx5-abi.h17
-rw-r--r--include/uapi/scsi/fc/fc_els.h106
-rw-r--r--include/uapi/sound/asound.h1
-rw-r--r--include/uapi/sound/snd_sst_tokens.h6
-rw-r--r--init/Kconfig33
-rw-r--r--ipc/msg.c2
-rw-r--r--ipc/namespace.c2
-rw-r--r--ipc/sem.c9
-rw-r--r--ipc/shm.c2
-rw-r--r--kernel/cgroup/namespace.c2
-rw-r--r--kernel/debug/debug_core.c5
-rw-r--r--kernel/debug/gdbstub.c5
-rw-r--r--kernel/debug/kdb/kdb_bp.c72
-rw-r--r--kernel/debug/kdb/kdb_debugger.c1
-rw-r--r--kernel/debug/kdb/kdb_main.c626
-rw-r--r--kernel/debug/kdb/kdb_private.h18
-rw-r--r--kernel/debug/kdb/kdb_support.c330
-rw-r--r--kernel/dma/Kconfig17
-rw-r--r--kernel/dma/coherent.c161
-rw-r--r--kernel/dma/debug.c21
-rw-r--r--kernel/dma/direct.c74
-rw-r--r--kernel/dma/direct.h8
-rw-r--r--kernel/dma/dummy.c2
-rw-r--r--kernel/dma/mapping.c80
-rw-r--r--kernel/dma/swiotlb.c352
-rw-r--r--kernel/events/core.c2
-rw-r--r--kernel/fork.c95
-rw-r--r--kernel/irq/irqdomain.c1
-rw-r--r--kernel/kcsan/atomic.h23
-rw-r--r--kernel/kcsan/core.c77
-rw-r--r--kernel/kcsan/kcsan_test.c32
-rw-r--r--kernel/kcsan/permissive.h94
-rw-r--r--kernel/kexec_core.c1
-rw-r--r--kernel/livepatch/transition.c4
-rw-r--r--kernel/module.c5
-rw-r--r--kernel/nsproxy.c2
-rw-r--r--kernel/panic.c3
-rw-r--r--kernel/pid_namespace.c5
-rw-r--r--kernel/printk/Makefile1
-rw-r--r--kernel/printk/index.c195
-rw-r--r--kernel/printk/internal.h31
-rw-r--r--kernel/printk/printk.c361
-rw-r--r--kernel/printk/printk_safe.c364
-rw-r--r--kernel/seccomp.c42
-rw-r--r--kernel/signal.c94
-rw-r--r--kernel/sys.c33
-rw-r--r--kernel/sys_ni.c2
-rw-r--r--kernel/sysctl.c2
-rw-r--r--kernel/time/namespace.c4
-rw-r--r--kernel/time/posix-timers.c4
-rw-r--r--kernel/trace/Kconfig6
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/ring_buffer.c8
-rw-r--r--kernel/trace/trace.c12
-rw-r--r--kernel/trace/trace.h18
-rw-r--r--kernel/trace/trace_boot.c302
-rw-r--r--kernel/trace/trace_dynevent.c38
-rw-r--r--kernel/trace/trace_dynevent.h4
-rw-r--r--kernel/trace/trace_eprobe.c903
-rw-r--r--kernel/trace/trace_event_perf.c6
-rw-r--r--kernel/trace/trace_events.c22
-rw-r--r--kernel/trace/trace_events_hist.c143
-rw-r--r--kernel/trace/trace_events_synth.c21
-rw-r--r--kernel/trace/trace_events_trigger.c20
-rw-r--r--kernel/trace/trace_hwlat.c28
-rw-r--r--kernel/trace/trace_kdb.c12
-rw-r--r--kernel/trace/trace_kprobe.c49
-rw-r--r--kernel/trace/trace_osnoise.c16
-rw-r--r--kernel/trace/trace_probe.c109
-rw-r--r--kernel/trace/trace_probe.h16
-rw-r--r--kernel/trace/trace_probe_tmpl.h6
-rw-r--r--kernel/trace/trace_uprobe.c40
-rw-r--r--kernel/tracepoint.c4
-rw-r--r--kernel/user_namespace.c2
-rw-r--r--lib/Kconfig10
-rw-r--r--lib/Kconfig.debug4
-rw-r--r--lib/Kconfig.kcsan42
-rw-r--r--lib/bitmap.c121
-rw-r--r--lib/debug_info.c3
-rw-r--r--lib/kasprintf.c2
-rw-r--r--lib/kunit/string-stream.h2
-rw-r--r--lib/kunit/test.c109
-rw-r--r--lib/nmi_backtrace.c13
-rw-r--r--lib/scatterlist.c160
-rw-r--r--lib/sg_pool.c3
-rw-r--r--lib/string_helpers.c4
-rw-r--r--lib/test-string_helpers.c14
-rw-r--r--lib/test_bitmap.c150
-rw-r--r--lib/test_kasan.c82
-rw-r--r--lib/test_kasan_module.c20
-rw-r--r--lib/test_printf.c5
-rw-r--r--lib/test_scanf.c83
-rw-r--r--lib/test_stackinit.c253
-rw-r--r--lib/test_vmalloc.c5
-rw-r--r--lib/ubsan.c3
-rw-r--r--lib/vsprintf.c2
-rw-r--r--mm/backing-dev.c11
-rw-r--r--mm/bootmem_info.c4
-rw-r--r--mm/compaction.c67
-rw-r--r--mm/debug_vm_pgtable.c918
-rw-r--r--mm/filemap.c15
-rw-r--r--mm/gup.c88
-rw-r--r--mm/huge_memory.c32
-rw-r--r--mm/hugetlb.c171
-rw-r--r--mm/hwpoison-inject.c2
-rw-r--r--mm/internal.h9
-rw-r--r--mm/kasan/hw_tags.c51
-rw-r--r--mm/kasan/kasan.h23
-rw-r--r--mm/kasan/report.c29
-rw-r--r--mm/kfence/report.c2
-rw-r--r--mm/khugepaged.c2
-rw-r--r--mm/ksm.c8
-rw-r--r--mm/madvise.c1
-rw-r--r--mm/memblock.c32
-rw-r--r--mm/memcontrol.c228
-rw-r--r--mm/memory-failure.c51
-rw-r--r--mm/memory_hotplug.c2
-rw-r--r--mm/mempolicy.c177
-rw-r--r--mm/migrate.c315
-rw-r--r--mm/mmap.c36
-rw-r--r--mm/mremap.c2
-rw-r--r--mm/nommu.c2
-rw-r--r--mm/oom_kill.c70
-rw-r--r--mm/page-writeback.c121
-rw-r--r--mm/page_alloc.c62
-rw-r--r--mm/page_isolation.c13
-rw-r--r--mm/percpu.c3
-rw-r--r--mm/shmem.c271
-rw-r--r--mm/sparse.c46
-rw-r--r--mm/swap.c22
-rw-r--r--mm/swapfile.c8
-rw-r--r--mm/truncate.c28
-rw-r--r--mm/userfaultfd.c15
-rw-r--r--mm/util.c19
-rw-r--r--mm/vmalloc.c79
-rw-r--r--mm/vmpressure.c10
-rw-r--r--mm/vmscan.c210
-rw-r--r--mm/vmstat.c25
-rw-r--r--net/batman-adv/log.c2
-rw-r--r--net/bluetooth/rfcomm/tty.c12
-rw-r--r--net/bridge/br_multicast.c4
-rw-r--r--net/caif/chnl_net.c19
-rw-r--r--net/core/pktgen.c1
-rw-r--r--net/core/skbuff.c2
-rw-r--r--net/dccp/minisocks.c2
-rw-r--r--net/dsa/tag_rtl4_a.c7
-rw-r--r--net/ipv4/cipso_ipv4.c18
-rw-r--r--net/ipv4/ip_gre.c9
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/nexthop.c2
-rw-r--r--net/ipv4/ping.c5
-rw-r--r--net/ipv4/raw.c5
-rw-r--r--net/ipv4/udp.c5
-rw-r--r--net/ipv4/udp_tunnel_nic.c2
-rw-r--r--net/ipv6/addrconf.c28
-rw-r--r--net/ipv6/ip6_fib.c3
-rw-r--r--net/ipv6/ip6_gre.c2
-rw-r--r--net/ipv6/mcast.c10
-rw-r--r--net/ipv6/netfilter/nf_socket_ipv6.c4
-rw-r--r--net/ipv6/seg6_iptunnel.c2
-rw-r--r--net/l2tp/l2tp_core.c4
-rw-r--r--net/mac802154/iface.c2
-rw-r--r--net/mctp/route.c2
-rw-r--r--net/mptcp/pm_netlink.c10
-rw-r--r--net/mptcp/protocol.c97
-rw-r--r--net/mptcp/protocol.h3
-rw-r--r--net/ncsi/internal.h3
-rw-r--r--net/ncsi/ncsi-manage.c25
-rw-r--r--net/ncsi/ncsi-pkt.h6
-rw-r--r--net/ncsi/ncsi-rsp.c42
-rw-r--r--net/netfilter/nf_conntrack_core.c103
-rw-r--r--net/netfilter/nf_conntrack_expect.c25
-rw-r--r--net/netfilter/nf_conntrack_netlink.c4
-rw-r--r--net/netfilter/nf_conntrack_standalone.c4
-rw-r--r--net/netfilter/nf_nat_core.c18
-rw-r--r--net/netfilter/nft_ct.c9
-rw-r--r--net/packet/af_packet.c2
-rw-r--r--net/qrtr/qrtr.c2
-rw-r--r--net/sched/sch_fq_codel.c12
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.c2
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c47
-rw-r--r--net/sunrpc/clnt.c66
-rw-r--r--net/sunrpc/debugfs.c2
-rw-r--r--net/sunrpc/rpc_pipe.c2
-rw-r--r--net/sunrpc/svc.c39
-rw-r--r--net/sunrpc/svcauth.c8
-rw-r--r--net/sunrpc/svcauth_unix.c18
-rw-r--r--net/sunrpc/sysfs.c36
-rw-r--r--net/sunrpc/xprt.c32
-rw-r--r--net/sunrpc/xprtmultipath.c1
-rw-r--r--net/sunrpc/xprtrdma/backchannel.c2
-rw-r--r--net/sunrpc/xprtrdma/frwr_ops.c14
-rw-r--r--net/sunrpc/xprtrdma/transport.c13
-rw-r--r--net/sunrpc/xprtrdma/verbs.c28
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h2
-rw-r--r--net/sunrpc/xprtsock.c15
-rw-r--r--net/tipc/socket.c4
-rw-r--r--net/unix/af_unix.c2
-rw-r--r--samples/kdb/kdb_hello.c20
-rw-r--r--samples/mei/mei-amt-version.c51
-rw-r--r--samples/vfio-mdev/mbochs.c40
-rw-r--r--samples/vfio-mdev/mdpy.c40
-rw-r--r--samples/vfio-mdev/mtty.c40
-rw-r--r--scripts/Kbuild.include13
-rw-r--r--scripts/Makefile.build30
-rw-r--r--scripts/Makefile.clang35
-rw-r--r--scripts/Makefile.lib21
-rw-r--r--scripts/Makefile.modfinal21
-rw-r--r--scripts/Makefile.modpost22
-rwxr-xr-xscripts/adjust_autoksyms.sh4
-rwxr-xr-xscripts/as-version.sh8
-rwxr-xr-x[-rw-r--r--]scripts/checkdeclares.pl0
-rwxr-xr-xscripts/checkkconfigsymbols.py2
-rwxr-xr-xscripts/checksyscalls.sh2
-rwxr-xr-xscripts/clang-tools/gen_compile_commands.py2
-rwxr-xr-x[-rw-r--r--]scripts/gcc-plugins/gen-random-seed.sh0
-rwxr-xr-xscripts/gen_autoksyms.sh12
-rwxr-xr-xscripts/gen_ksymdeps.sh11
-rwxr-xr-xscripts/kconfig/merge_config.sh15
-rwxr-xr-xscripts/kernel-doc8
-rwxr-xr-xscripts/link-vmlinux.sh81
-rw-r--r--scripts/mod/devicetable-offsets.c1
-rw-r--r--scripts/mod/file2alias.c17
-rw-r--r--scripts/mod/modpost.c13
-rw-r--r--scripts/mod/modpost.h9
-rw-r--r--scripts/mod/sumversion.c7
-rw-r--r--scripts/spdxcheck-test.sh16
-rw-r--r--scripts/subarch.include2
-rwxr-xr-x[-rw-r--r--]scripts/syscallnr.sh0
-rwxr-xr-x[-rw-r--r--]scripts/xen-hypercalls.sh0
-rw-r--r--security/Kconfig.hardening71
-rw-r--r--security/Makefile11
-rw-r--r--security/integrity/ima/Kconfig1
-rw-r--r--security/integrity/ima/ima.h24
-rw-r--r--security/integrity/ima/ima_api.c6
-rw-r--r--security/integrity/ima/ima_appraise.c78
-rw-r--r--security/integrity/ima/ima_asymmetric_keys.c2
-rw-r--r--security/integrity/ima/ima_init.c3
-rw-r--r--security/integrity/ima/ima_main.c89
-rw-r--r--security/integrity/ima/ima_mok.c2
-rw-r--r--security/integrity/ima/ima_policy.c174
-rw-r--r--security/integrity/ima/ima_queue_keys.c2
-rw-r--r--security/selinux/ima.c6
-rw-r--r--security/tomoyo/domain.c13
-rw-r--r--sound/ac97/bus.c6
-rw-r--r--sound/aoa/codecs/onyx.h1
-rw-r--r--sound/aoa/codecs/tas.c1
-rw-r--r--sound/aoa/soundbus/core.c4
-rw-r--r--sound/arm/pxa2xx-ac97.c18
-rw-r--r--sound/arm/pxa2xx-pcm-lib.c90
-rw-r--r--sound/core/compress_offload.c69
-rw-r--r--sound/core/control_led.c2
-rw-r--r--sound/core/info.c1
-rw-r--r--sound/core/init.c105
-rw-r--r--sound/core/isadma.c38
-rw-r--r--sound/core/memalloc.c177
-rw-r--r--sound/core/memalloc_local.h2
-rw-r--r--sound/core/pcm_lib.c2
-rw-r--r--sound/core/pcm_memory.c67
-rw-r--r--sound/core/pcm_native.c18
-rw-r--r--sound/core/seq/seq_dummy.c8
-rw-r--r--sound/core/sgbuf.c30
-rw-r--r--sound/drivers/Kconfig2
-rw-r--r--sound/drivers/aloop.c26
-rw-r--r--sound/drivers/dummy.c24
-rw-r--r--sound/drivers/mpu401/mpu401.c34
-rw-r--r--sound/drivers/mtpav.c30
-rw-r--r--sound/drivers/pcsp/pcsp.c49
-rw-r--r--sound/drivers/pcsp/pcsp_input.c14
-rw-r--r--sound/drivers/pcsp/pcsp_input.h1
-rw-r--r--sound/drivers/serial-u16550.c57
-rw-r--r--sound/drivers/virmidi.c21
-rw-r--r--sound/drivers/vx/vx_core.c12
-rw-r--r--sound/firewire/motu/motu-protocol-v2.c22
-rw-r--r--sound/firewire/motu/motu.c1
-rw-r--r--sound/firewire/motu/motu.h1
-rw-r--r--sound/isa/ad1816a/ad1816a.c41
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c49
-rw-r--r--sound/isa/ad1848/ad1848.c19
-rw-r--r--sound/isa/adlib.c28
-rw-r--r--sound/isa/als100.c41
-rw-r--r--sound/isa/azt2320.c49
-rw-r--r--sound/isa/cmi8328.c31
-rw-r--r--sound/isa/cmi8330.c27
-rw-r--r--sound/isa/cs423x/cs4231.c21
-rw-r--r--sound/isa/cs423x/cs4236.c52
-rw-r--r--sound/isa/cs423x/cs4236_lib.c2
-rw-r--r--sound/isa/es1688/es1688.c33
-rw-r--r--sound/isa/es18xx.c112
-rw-r--r--sound/isa/galaxy/galaxy.c82
-rw-r--r--sound/isa/gus/gus_main.c44
-rw-r--r--sound/isa/gus/gusclassic.c28
-rw-r--r--sound/isa/gus/gusextreme.c39
-rw-r--r--sound/isa/gus/gusmax.c65
-rw-r--r--sound/isa/gus/interwave.c53
-rw-r--r--sound/isa/msnd/msnd.c8
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c119
-rw-r--r--sound/isa/opl3sa2.c60
-rw-r--r--sound/isa/opti9xx/miro.c76
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c77
-rw-r--r--sound/isa/sb/emu8000.c48
-rw-r--r--sound/isa/sb/jazz16.c39
-rw-r--r--sound/isa/sb/sb16.c42
-rw-r--r--sound/isa/sb/sb8.c48
-rw-r--r--sound/isa/sb/sb_common.c64
-rw-r--r--sound/isa/sc6000.c84
-rw-r--r--sound/isa/sscape.c92
-rw-r--r--sound/isa/wavefront/wavefront.c46
-rw-r--r--sound/isa/wss/wss_lib.c67
-rw-r--r--sound/parisc/harmony.c17
-rw-r--r--sound/pci/ad1889.c144
-rw-r--r--sound/pci/ali5451/ali5451.c90
-rw-r--r--sound/pci/als300.c80
-rw-r--r--sound/pci/als4000.c59
-rw-r--r--sound/pci/atiixp.c92
-rw-r--r--sound/pci/atiixp_modem.c92
-rw-r--r--sound/pci/au88x0/au88x0.c134
-rw-r--r--sound/pci/aw2/aw2-alsa.c102
-rw-r--r--sound/pci/azt3328.c124
-rw-r--r--sound/pci/bt87x.c98
-rw-r--r--sound/pci/ca0106/ca0106.h3
-rw-r--r--sound/pci/ca0106/ca0106_main.c114
-rw-r--r--sound/pci/cmipci.c104
-rw-r--r--sound/pci/cs4281.c114
-rw-r--r--sound/pci/cs46xx/cs46xx.c51
-rw-r--r--sound/pci/cs46xx/cs46xx.h4
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c141
-rw-r--r--sound/pci/cs5530.c86
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c94
-rw-r--r--sound/pci/cs5535audio/cs5535audio_olpc.c7
-rw-r--r--sound/pci/echoaudio/echoaudio.c168
-rw-r--r--sound/pci/echoaudio/echoaudio.h2
-rw-r--r--sound/pci/emu10k1/emu10k1.c53
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c102
-rw-r--r--sound/pci/emu10k1/emu10k1x.c128
-rw-r--r--sound/pci/emu10k1/p16v.c22
-rw-r--r--sound/pci/ens1370.c115
-rw-r--r--sound/pci/es1938.c97
-rw-r--r--sound/pci/es1968.c112
-rw-r--r--sound/pci/fm801.c103
-rw-r--r--sound/pci/hda/Kconfig10
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_auto_parser.c84
-rw-r--r--sound/pci/hda/hda_bind.c8
-rw-r--r--sound/pci/hda/hda_codec.c12
-rw-r--r--sound/pci/hda/hda_controller.c13
-rw-r--r--sound/pci/hda/hda_controller.h3
-rw-r--r--sound/pci/hda/hda_generic.c19
-rw-r--r--sound/pci/hda/hda_generic.h1
-rw-r--r--sound/pci/hda/hda_intel.c52
-rw-r--r--sound/pci/hda/hda_local.h2
-rw-r--r--sound/pci/hda/patch_analog.c11
-rw-r--r--sound/pci/hda/patch_ca0132.c8
-rw-r--r--sound/pci/hda/patch_cirrus.c1074
-rw-r--r--sound/pci/hda/patch_conexant.c15
-rw-r--r--sound/pci/hda/patch_cs8409-tables.c560
-rw-r--r--sound/pci/hda/patch_cs8409.c1299
-rw-r--r--sound/pci/hda/patch_cs8409.h371
-rw-r--r--sound/pci/hda/patch_hdmi.c7
-rw-r--r--sound/pci/hda/patch_realtek.c24
-rw-r--r--sound/pci/hda/patch_sigmatel.c23
-rw-r--r--sound/pci/ice1712/ice1712.c133
-rw-r--r--sound/pci/ice1712/ice1724.c167
-rw-r--r--sound/pci/intel8x0.c144
-rw-r--r--sound/pci/intel8x0m.c139
-rw-r--r--sound/pci/korg1212/korg1212.c211
-rw-r--r--sound/pci/lola/lola.c127
-rw-r--r--sound/pci/lola/lola.h5
-rw-r--r--sound/pci/lola/lola_pcm.c20
-rw-r--r--sound/pci/lx6464es/lx6464es.c112
-rw-r--r--sound/pci/maestro3.c106
-rw-r--r--sound/pci/nm256/nm256.c131
-rw-r--r--sound/pci/oxygen/oxygen.c1
-rw-r--r--sound/pci/oxygen/oxygen.h1
-rw-r--r--sound/pci/oxygen/oxygen_lib.c66
-rw-r--r--sound/pci/oxygen/se6x.c1
-rw-r--r--sound/pci/oxygen/virtuoso.c1
-rw-r--r--sound/pci/pcxhr/pcxhr.c47
-rw-r--r--sound/pci/riptide/riptide.c89
-rw-r--r--sound/pci/rme32.c49
-rw-r--r--sound/pci/rme96.c57
-rw-r--r--sound/pci/rme9652/hdsp.c95
-rw-r--r--sound/pci/rme9652/hdspm.c64
-rw-r--r--sound/pci/rme9652/rme9652.c91
-rw-r--r--sound/pci/sis7019.c87
-rw-r--r--sound/pci/sonicvibes.c117
-rw-r--r--sound/pci/trident/trident.c39
-rw-r--r--sound/pci/trident/trident.h7
-rw-r--r--sound/pci/trident/trident_main.c90
-rw-r--r--sound/pci/trident/trident_memory.c8
-rw-r--r--sound/pci/via82xx.c116
-rw-r--r--sound/pci/via82xx_modem.c88
-rw-r--r--sound/pci/vx222/vx222.c69
-rw-r--r--sound/pci/ymfpci/ymfpci.c66
-rw-r--r--sound/pci/ymfpci/ymfpci.h8
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c149
-rw-r--r--sound/pcmcia/vx/vxpocket.c22
-rw-r--r--sound/soc/amd/Kconfig9
-rw-r--r--sound/soc/amd/Makefile1
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c12
-rw-r--r--sound/soc/amd/acp-pcm-dma.c20
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c14
-rw-r--r--sound/soc/amd/raven/acp3x-pcm-dma.c10
-rw-r--r--sound/soc/amd/renoir/acp3x-pdm-dma.c8
-rw-r--r--sound/soc/amd/renoir/acp3x-rn.c7
-rw-r--r--sound/soc/amd/vangogh/Makefile9
-rw-r--r--sound/soc/amd/vangogh/acp5x-i2s.c427
-rw-r--r--sound/soc/amd/vangogh/acp5x-pcm-dma.c517
-rw-r--r--sound/soc/amd/vangogh/acp5x.h193
-rw-r--r--sound/soc/amd/vangogh/pci-acp5x.c326
-rw-r--r--sound/soc/amd/vangogh/vg_chip_offset_byte.h337
-rw-r--r--sound/soc/atmel/Kconfig1
-rw-r--r--sound/soc/atmel/mchp-spdifrx.c6
-rw-r--r--sound/soc/atmel/mchp-spdiftx.c2
-rw-r--r--sound/soc/atmel/tse850-pcm5142.c2
-rw-r--r--sound/soc/bcm/bcm63xx-pcm-whistler.c82
-rw-r--r--sound/soc/bcm/cygnus-pcm.c2
-rw-r--r--sound/soc/codecs/Kconfig21
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/ad193x.c30
-rw-r--r--sound/soc/codecs/ad193x.h4
-rw-r--r--sound/soc/codecs/cs42l42.c28
-rw-r--r--sound/soc/codecs/cx20442.c8
-rw-r--r--sound/soc/codecs/ics43432.c4
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c65
-rw-r--r--sound/soc/codecs/max98090.c4
-rw-r--r--sound/soc/codecs/max98390.c26
-rw-r--r--sound/soc/codecs/max98390.h1
-rw-r--r--sound/soc/codecs/mt6359-accdet.c25
-rw-r--r--sound/soc/codecs/rt1015.c46
-rw-r--r--sound/soc/codecs/rt1015.h2
-rw-r--r--sound/soc/codecs/rt1015p.c2
-rw-r--r--sound/soc/codecs/rt5514.c2
-rw-r--r--sound/soc/codecs/rt5640.c133
-rw-r--r--sound/soc/codecs/rt5640.h6
-rw-r--r--sound/soc/codecs/rt5682-i2c.c15
-rw-r--r--sound/soc/codecs/rt5682.c57
-rw-r--r--sound/soc/codecs/sdw-mockup.c312
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c10
-rw-r--r--sound/soc/codecs/wcd9335.c23
-rw-r--r--sound/soc/codecs/wcd938x.c854
-rw-r--r--sound/soc/codecs/wcd938x.h1
-rw-r--r--sound/soc/codecs/wm_adsp.c9
-rw-r--r--sound/soc/dwc/dwc-i2s.c2
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c47
-rw-r--r--sound/soc/fsl/fsl_dma.c50
-rw-r--r--sound/soc/fsl/fsl_rpmsg.c20
-rw-r--r--sound/soc/fsl/fsl_xcvr.c4
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c75
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c89
-rw-r--r--sound/soc/fsl/imx-rpmsg.c2
-rw-r--r--sound/soc/fsl/mpc5200_dma.c63
-rw-r--r--sound/soc/generic/simple-card-utils.c4
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c2
-rw-r--r--sound/soc/intel/atom/sst/sst_ipc.c2
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c31
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c328
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c63
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c55
-rw-r--r--sound/soc/intel/boards/sof_cs42l42.c361
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.c17
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.h4
-rw-r--r--sound/soc/intel/boards/sof_pcm512x.c13
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c66
-rw-r--r--sound/soc/intel/boards/sof_sdw.c105
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h64
-rw-r--r--sound/soc/intel/boards/sof_sdw_max98373.c7
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1308.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1316.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt5682.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt700.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711.c51
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711_sdca.c52
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715_sdca.c3
-rw-r--r--sound/soc/intel/common/Makefile3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cml-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-cnl-match.c15
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-jsl-match.c8
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-kbl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c166
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h17
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-tgl-match.c38
-rw-r--r--sound/soc/intel/skylake/skl-messages.c155
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c33
-rw-r--r--sound/soc/intel/skylake/skl-topology.c155
-rw-r--r--sound/soc/intel/skylake/skl-topology.h26
-rw-r--r--sound/soc/mediatek/Kconfig24
-rw-r--r--sound/soc/mediatek/Makefile1
-rw-r--r--sound/soc/mediatek/common/mtk-afe-fe-dai.c22
-rw-r--r--sound/soc/mediatek/common/mtk-base-afe.h10
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-afe-pcm.c43
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-pcm.c27
-rw-r--r--sound/soc/mediatek/mt8195/Makefile15
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.c441
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.h109
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-common.h158
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-pcm.c3281
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clk.c214
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clk.h15
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h93
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-adda.c830
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-etdm.c2639
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-pcm.c389
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c1087
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-reg.h2796
-rw-r--r--sound/soc/pxa/pxa-ssp.c3
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c3
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c3
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c3
-rw-r--r--sound/soc/qcom/apq8016_sbc.c17
-rw-r--r--sound/soc/qcom/lpass-platform.c60
-rw-r--r--sound/soc/qcom/qdsp6/q6adm.c2
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c63
-rw-r--r--sound/soc/qcom/qdsp6/q6asm.c2
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c212
-rw-r--r--sound/soc/rockchip/rockchip_i2s.h10
-rw-r--r--sound/soc/rockchip/rockchip_spdif.c38
-rw-r--r--sound/soc/samsung/aries_wm8994.c2
-rw-r--r--sound/soc/samsung/arndale.c4
-rw-r--r--sound/soc/samsung/h1940_uda1380.c2
-rw-r--r--sound/soc/samsung/littlemill.c2
-rw-r--r--sound/soc/samsung/midas_wm1811.c2
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c4
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c2
-rw-r--r--sound/soc/samsung/smartq_wm8987.c2
-rw-r--r--sound/soc/samsung/smdk_wm8580.c2
-rw-r--r--sound/soc/samsung/smdk_wm8994.c2
-rw-r--r--sound/soc/samsung/smdk_wm8994pcm.c2
-rw-r--r--sound/soc/samsung/tm2_wm5110.c6
-rw-r--r--sound/soc/samsung/tobermory.c2
-rw-r--r--sound/soc/sh/Kconfig6
-rw-r--r--sound/soc/sh/Makefile4
-rw-r--r--sound/soc/sh/rcar/adg.c12
-rw-r--r--sound/soc/sh/rcar/core.c6
-rw-r--r--sound/soc/sh/rcar/dma.c2
-rw-r--r--sound/soc/sh/rcar/ssi.c6
-rw-r--r--sound/soc/sh/rz-ssi.c1074
-rw-r--r--sound/soc/soc-ac97.c14
-rw-r--r--sound/soc/soc-component.c4
-rw-r--r--sound/soc/soc-compress.c1
-rw-r--r--sound/soc/soc-core.c36
-rw-r--r--sound/soc/soc-dai.c18
-rw-r--r--sound/soc/soc-dapm.c65
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c9
-rw-r--r--sound/soc/soc-jack.c15
-rw-r--r--sound/soc/soc-ops.c21
-rw-r--r--sound/soc/soc-pcm.c22
-rw-r--r--sound/soc/soc-topology.c23
-rw-r--r--sound/soc/sof/intel/Kconfig10
-rw-r--r--sound/soc/sof/intel/cnl.c6
-rw-r--r--sound/soc/sof/intel/hda-pcm.c16
-rw-r--r--sound/soc/sof/intel/hda-stream.c11
-rw-r--r--sound/soc/sof/intel/hda.c39
-rw-r--r--sound/soc/sof/intel/hda.h8
-rw-r--r--sound/soc/sof/intel/icl.c3
-rw-r--r--sound/soc/sof/intel/pci-tng.c1
-rw-r--r--sound/soc/sof/intel/shim.h3
-rw-r--r--sound/soc/sof/intel/tgl.c12
-rw-r--r--sound/soc/sof/sof-audio.c42
-rw-r--r--sound/soc/sof/sof-pci-dev.c9
-rw-r--r--sound/soc/sprd/sprd-pcm-dma.c67
-rw-r--r--sound/soc/tegra/tegra210_admaif.c6
-rw-r--r--sound/soc/tegra/tegra30_ahub.c6
-rw-r--r--sound/soc/tegra/tegra30_i2s.c8
-rw-r--r--sound/soc/tegra/tegra_pcm.c93
-rw-r--r--sound/soc/tegra/tegra_pcm.h7
-rw-r--r--sound/soc/ti/Kconfig1
-rw-r--r--sound/soc/ti/davinci-mcasp.c176
-rw-r--r--sound/soc/ti/j721e-evm.c30
-rw-r--r--sound/soc/ti/omap-abe-twl6040.c5
-rw-r--r--sound/soc/uniphier/aio-cpu.c4
-rw-r--r--sound/usb/card.c46
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/clock.c15
-rw-r--r--sound/usb/endpoint.c21
-rw-r--r--sound/usb/format.c6
-rw-r--r--sound/usb/implicit.c6
-rw-r--r--sound/usb/mixer.c10
-rw-r--r--sound/usb/mixer.h3
-rw-r--r--sound/usb/mixer_maps.c22
-rw-r--r--sound/usb/mixer_quirks.c265
-rw-r--r--sound/usb/pcm.c14
-rw-r--r--sound/usb/quirks-table.h70
-rw-r--r--sound/usb/quirks.c361
-rw-r--r--sound/usb/quirks.h5
-rw-r--r--sound/usb/stream.c4
-rw-r--r--sound/usb/usbaudio.h69
-rw-r--r--sound/x86/intel_hdmi_audio.c90
-rw-r--r--sound/x86/intel_hdmi_audio.h1
-rwxr-xr-xtools/bootconfig/scripts/bconf2ftrace.sh101
-rwxr-xr-xtools/bootconfig/scripts/ftrace2bconf.sh24
-rw-r--r--tools/bootconfig/scripts/xbc.sh4
-rw-r--r--tools/build/Makefile2
-rw-r--r--tools/build/Makefile.feature1
-rw-r--r--tools/build/feature/Makefile4
-rw-r--r--tools/build/feature/test-all.c4
-rw-r--r--tools/build/feature/test-libopencsd.c4
-rw-r--r--tools/build/feature/test-sync-compare-and-swap.c15
-rw-r--r--tools/include/linux/compiler_types.h18
-rw-r--r--tools/lib/perf/cpumap.c15
-rw-r--r--tools/lib/perf/include/internal/tests.h2
-rw-r--r--tools/lib/perf/include/perf/cpumap.h1
-rw-r--r--tools/lib/subcmd/parse-options.h1
-rw-r--r--tools/memory-model/Documentation/access-marking.txt151
-rw-r--r--tools/perf/Documentation/Makefile74
-rwxr-xr-xtools/perf/Documentation/build-docdep.perl46
-rwxr-xr-xtools/perf/Documentation/cat-texi.perl46
-rw-r--r--tools/perf/Documentation/intel-hybrid.txt2
-rw-r--r--tools/perf/Documentation/perf-c2c.txt2
-rw-r--r--tools/perf/Documentation/perf-dlfilter.txt12
-rw-r--r--tools/perf/Documentation/perf-iostat.txt4
-rw-r--r--tools/perf/Documentation/perf-record.txt2
-rw-r--r--tools/perf/Documentation/perf-script-python.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt2
-rw-r--r--tools/perf/Documentation/perf-stat.txt14
-rw-r--r--tools/perf/Makefile.config14
-rw-r--r--tools/perf/Makefile.perf17
-rw-r--r--tools/perf/arch/arm/util/auxtrace.c32
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c97
-rw-r--r--tools/perf/arch/powerpc/entry/syscalls/syscall.tbl2
-rw-r--r--tools/perf/arch/s390/entry/syscalls/syscall.tbl2
-rw-r--r--tools/perf/arch/x86/util/pmu.c155
-rw-r--r--tools/perf/bench/Build1
-rw-r--r--tools/perf/bench/bench.h1
-rw-r--r--tools/perf/bench/evlist-open-close.c258
-rw-r--r--tools/perf/bench/futex-hash.c62
-rw-r--r--tools/perf/bench/futex-lock-pi.c60
-rw-r--r--tools/perf/bench/futex-requeue.c159
-rw-r--r--tools/perf/bench/futex-wake-parallel.c66
-rw-r--r--tools/perf/bench/futex-wake.c65
-rw-r--r--tools/perf/bench/futex.h52
-rw-r--r--tools/perf/bench/inject-buildid.c52
-rw-r--r--tools/perf/bench/synthesize.c4
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-bench.c1
-rw-r--r--tools/perf/builtin-buildid-cache.c2
-rw-r--r--tools/perf/builtin-buildid-list.c2
-rw-r--r--tools/perf/builtin-c2c.c2
-rw-r--r--tools/perf/builtin-data.c62
-rw-r--r--tools/perf/builtin-diff.c4
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-inject.c38
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-kvm.c4
-rw-r--r--tools/perf/builtin-lock.c2
-rw-r--r--tools/perf/builtin-mem.c3
-rw-r--r--tools/perf/builtin-record.c50
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-sched.c4
-rw-r--r--tools/perf/builtin-script.c19
-rw-r--r--tools/perf/builtin-stat.c14
-rw-r--r--tools/perf/builtin-timechart.c3
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/builtin-trace.c12
-rw-r--r--tools/perf/dlfilters/dlfilter-test-api-v0.c336
-rw-r--r--tools/perf/include/perf/perf_dlfilter.h (renamed from tools/perf/util/perf_dlfilter.h)0
-rw-r--r--tools/perf/pmu-events/Build5
-rw-r--r--tools/perf/pmu-events/arch/test/test_soc/cpu/branch.json (renamed from tools/perf/pmu-events/arch/test/test_cpu/branch.json)0
-rw-r--r--tools/perf/pmu-events/arch/test/test_soc/cpu/cache.json (renamed from tools/perf/pmu-events/arch/test/test_cpu/cache.json)0
-rw-r--r--tools/perf/pmu-events/arch/test/test_soc/cpu/other.json (renamed from tools/perf/pmu-events/arch/test/test_cpu/other.json)0
-rw-r--r--tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json (renamed from tools/perf/pmu-events/arch/test/test_cpu/uncore.json)23
-rw-r--r--tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json9
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/cache.json5406
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json253
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/floating-point.json48
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/frontend.json548
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/memory.json5432
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/other.json4142
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/pipeline.json1046
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json21
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/uncore-other.json161
-rw-r--r--tools/perf/pmu-events/arch/x86/cascadelakex/virtual-memory.json256
-rw-r--r--tools/perf/pmu-events/arch/x86/elkhartlake/cache.json226
-rw-r--r--tools/perf/pmu-events/arch/x86/elkhartlake/ehl-metrics.json57
-rw-r--r--tools/perf/pmu-events/arch/x86/elkhartlake/floating-point.json24
-rw-r--r--tools/perf/pmu-events/arch/x86/elkhartlake/frontend.json93
-rw-r--r--tools/perf/pmu-events/arch/x86/elkhartlake/memory.json86
-rw-r--r--tools/perf/pmu-events/arch/x86/elkhartlake/other.json424
-rw-r--r--tools/perf/pmu-events/arch/x86/elkhartlake/pipeline.json278
-rw-r--r--tools/perf/pmu-events/arch/x86/elkhartlake/virtual-memory.json273
-rw-r--r--tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json315
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv3
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/cache.json1648
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/floating-point.json56
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/frontend.json576
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/memory.json1282
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/other.json104
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/pipeline.json1030
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json247
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json9
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json171
-rw-r--r--tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json288
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/cache.json595
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/floating-point.json94
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/frontend.json463
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/memory.json295
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/other.json189
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/pipeline.json982
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json231
-rw-r--r--tools/perf/pmu-events/arch/x86/tigerlake/virtual-memory.json225
-rw-r--r--tools/perf/pmu-events/jevents.c5
-rw-r--r--tools/perf/pmu-events/pmu-events.h1
-rwxr-xr-xtools/perf/scripts/python/flamegraph.py108
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/builtin-test.c15
-rw-r--r--tools/perf/tests/dlfilter-test.c416
-rw-r--r--tools/perf/tests/dso-data.c14
-rw-r--r--tools/perf/tests/llvm.c7
-rw-r--r--tools/perf/tests/parse-events.c92
-rw-r--r--tools/perf/tests/pmu-events.c699
-rw-r--r--tools/perf/tests/shell/lib/probe_vfs_getname.sh2
-rwxr-xr-xtools/perf/tests/shell/pipe_test.sh69
-rwxr-xr-xtools/perf/tests/shell/record+zstd_comp_decomp.sh4
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/tests/topology.c4
-rwxr-xr-xtools/perf/trace/beauty/arch_errno_names.sh11
-rw-r--r--tools/perf/ui/browsers/annotate.c1
-rw-r--r--tools/perf/ui/gtk/annotate.c1
-rw-r--r--tools/perf/util/annotate.c26
-rw-r--r--tools/perf/util/auxtrace.c104
-rw-r--r--tools/perf/util/auxtrace.h49
-rw-r--r--tools/perf/util/config.c5
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.c170
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.h13
-rw-r--r--tools/perf/util/cs-etm.c238
-rw-r--r--tools/perf/util/cs-etm.h11
-rw-r--r--tools/perf/util/data-convert-bt.c2
-rw-r--r--tools/perf/util/data-convert-json.c2
-rw-r--r--tools/perf/util/debug.h14
-rw-r--r--tools/perf/util/dlfilter.c6
-rw-r--r--tools/perf/util/dlfilter.h2
-rw-r--r--tools/perf/util/dso.h1
-rw-r--r--tools/perf/util/env.c26
-rw-r--r--tools/perf/util/env.h3
-rw-r--r--tools/perf/util/events_stats.h1
-rw-r--r--tools/perf/util/evlist-hybrid.c73
-rw-r--r--tools/perf/util/evlist-hybrid.h1
-rw-r--r--tools/perf/util/evlist.c3
-rw-r--r--tools/perf/util/evlist.h16
-rw-r--r--tools/perf/util/evsel.c397
-rw-r--r--tools/perf/util/evsel.h14
-rw-r--r--tools/perf/util/get_current_dir_name.c3
-rw-r--r--tools/perf/util/header.c14
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/llvm-utils.c40
-rw-r--r--tools/perf/util/mmap.h1
-rw-r--r--tools/perf/util/parse-events.y3
-rw-r--r--tools/perf/util/parse-sublevel-options.h2
-rw-r--r--tools/perf/util/pmu.c80
-rw-r--r--tools/perf/util/pmu.h10
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c32
-rw-r--r--tools/perf/util/session.c20
-rw-r--r--tools/perf/util/session.h12
-rw-r--r--tools/perf/util/synthetic-events.c53
-rw-r--r--tools/perf/util/synthetic-events.h6
-rw-r--r--tools/perf/util/target.h1
-rw-r--r--tools/perf/util/trace-event.h3
-rw-r--r--tools/testing/ktest/examples/bootconfigs/boottrace.bconf20
-rwxr-xr-xtools/testing/ktest/examples/bootconfigs/verify-boottrace.sh2
-rwxr-xr-xtools/testing/kunit/kunit.py36
-rw-r--r--tools/testing/kunit/kunit_parser.py6
-rwxr-xr-xtools/testing/kunit/kunit_tool_test.py29
-rw-r--r--tools/testing/scatterlist/linux/mm.h1
-rw-r--r--tools/testing/scatterlist/main.c38
-rw-r--r--tools/testing/selftests/arm64/fp/.gitignore2
-rw-r--r--tools/testing/selftests/arm64/fp/Makefile11
-rw-r--r--tools/testing/selftests/arm64/fp/TODO4
-rw-r--r--tools/testing/selftests/arm64/fp/rdvl-sve.c14
-rw-r--r--tools/testing/selftests/arm64/fp/rdvl.S10
-rw-r--r--tools/testing/selftests/arm64/fp/rdvl.h8
-rw-r--r--tools/testing/selftests/arm64/fp/sve-probe-vls.c5
-rw-r--r--tools/testing/selftests/arm64/fp/vec-syscfg.c593
-rw-r--r--tools/testing/selftests/arm64/mte/.gitignore1
-rw-r--r--tools/testing/selftests/arm64/mte/mte_common_util.c2
-rw-r--r--tools/testing/selftests/arm64/pauth/pac.c10
-rw-r--r--tools/testing/selftests/arm64/signal/.gitignore1
-rw-r--r--tools/testing/selftests/arm64/signal/test_signals.h2
-rw-r--r--tools/testing/selftests/arm64/signal/test_signals_utils.c3
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/TODO2
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c92
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/sve_regs.c126
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/sve_vl.c68
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/testcases.c34
-rw-r--r--tools/testing/selftests/bpf/prog_tests/xdp_bonding.c74
-rw-r--r--tools/testing/selftests/cpufreq/config2
-rw-r--r--tools/testing/selftests/filesystems/binderfs/binderfs_test.c17
-rw-r--r--tools/testing/selftests/firmware/fw_namespace.c3
-rw-r--r--tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc40
-rw-r--r--tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc38
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions24
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc53
-rw-r--r--tools/testing/selftests/kvm/.gitignore1
-rw-r--r--tools/testing/selftests/kvm/Makefile1
-rw-r--r--tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c121
-rw-r--r--tools/testing/selftests/kvm/access_tracking_perf_test.c4
-rw-r--r--tools/testing/selftests/kvm/demand_paging_test.c3
-rw-r--r--tools/testing/selftests/kvm/dirty_log_perf_test.c77
-rw-r--r--tools/testing/selftests/kvm/include/aarch64/processor.h3
-rw-r--r--tools/testing/selftests/kvm/include/perf_test_util.h2
-rw-r--r--tools/testing/selftests/kvm/kvm_binary_stats_test.c12
-rw-r--r--tools/testing/selftests/kvm/lib/perf_test_util.c22
-rw-r--r--tools/testing/selftests/kvm/memslot_modification_stress_test.c3
-rw-r--r--tools/testing/selftests/kvm/x86_64/debug_regs.c24
-rw-r--r--tools/testing/selftests/lkdtm/config2
-rw-r--r--tools/testing/selftests/lkdtm/tests.txt3
-rw-r--r--tools/testing/selftests/net/Makefile1
-rwxr-xr-xtools/testing/selftests/net/altnames.sh2
-rwxr-xr-xtools/testing/selftests/net/gre_gso.sh236
-rwxr-xr-xtools/testing/selftests/net/mptcp/simult_flows.sh4
-rw-r--r--tools/testing/selftests/openat2/openat2_test.c4
l---------tools/testing/selftests/powerpc/primitives/asm/extable.h1
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c3
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c3
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c1
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c1
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c1
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c1
-rw-r--r--tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c1
-rw-r--r--tools/testing/selftests/powerpc/signal/signal_tm.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-exec.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-fork.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-poison.c2
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-sigreturn-nt.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-stack.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-sigreturn.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-syscall.c2
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tar.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tmspr.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-trap.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-unavailable.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-vmxcopy.c1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm.h36
-rw-r--r--tools/testing/selftests/safesetid/safesetid-test.c2
-rw-r--r--tools/testing/selftests/sched/cs_prctl_test.c2
-rw-r--r--tools/testing/selftests/sync/config1
-rw-r--r--tools/testing/selftests/vm/.gitignore1
-rw-r--r--tools/testing/selftests/vm/Makefile3
-rw-r--r--tools/testing/selftests/vm/charge_reserved_hugetlb.sh5
-rw-r--r--tools/testing/selftests/vm/hugetlb_reparenting_test.sh5
-rw-r--r--tools/testing/selftests/vm/ksm_tests.c662
-rw-r--r--tools/testing/selftests/vm/mlock-random-test.c2
-rwxr-xr-xtools/testing/selftests/vm/run_vmtests.sh96
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c13
-rw-r--r--tools/testing/selftests/x86/mov_ss_trap.c4
-rw-r--r--tools/testing/selftests/x86/sigreturn.c7
-rw-r--r--tools/testing/selftests/x86/single_step_syscall.c4
-rw-r--r--tools/testing/selftests/x86/syscall_arg_fault.c7
-rw-r--r--virt/kvm/binary_stats.c2
-rw-r--r--virt/kvm/dirty_ring.c5
-rw-r--r--virt/kvm/kvm_main.c197
6141 files changed, 374469 insertions, 153276 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uac1 b/Documentation/ABI/testing/configfs-usb-gadget-uac1
index dc23fd776943..dd647d44d975 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uac1
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uac1
@@ -8,9 +8,19 @@ Description:
c_chmask capture channel mask
c_srate capture sampling rate
c_ssize capture sample size (bytes)
+ c_mute_present capture mute control enable
+ c_volume_present capture volume control enable
+ c_volume_min capture volume control min value (in 1/256 dB)
+ c_volume_max capture volume control max value (in 1/256 dB)
+ c_volume_res capture volume control resolution (in 1/256 dB)
p_chmask playback channel mask
p_srate playback sampling rate
p_ssize playback sample size (bytes)
+ p_mute_present playback mute control enable
+ p_volume_present playback volume control enable
+ p_volume_min playback volume control min value (in 1/256 dB)
+ p_volume_max playback volume control max value (in 1/256 dB)
+ p_volume_res playback volume control resolution (in 1/256 dB)
req_number the number of pre-allocated request
for both capture and playback
========== ===================================
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uac2 b/Documentation/ABI/testing/configfs-usb-gadget-uac2
index 26fb8e9b4e61..cfd160ff8b56 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uac2
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uac2
@@ -9,8 +9,18 @@ Description:
c_srate capture sampling rate
c_ssize capture sample size (bytes)
c_sync capture synchronization type (async/adaptive)
+ c_mute_present capture mute control enable
+ c_volume_present capture volume control enable
+ c_volume_min capture volume control min value (in 1/256 dB)
+ c_volume_max capture volume control max value (in 1/256 dB)
+ c_volume_res capture volume control resolution (in 1/256 dB)
fb_max maximum extra bandwidth in async mode
p_chmask playback channel mask
p_srate playback sampling rate
p_ssize playback sample size (bytes)
+ p_mute_present playback mute control enable
+ p_volume_present playback volume control enable
+ p_volume_min playback volume control min value (in 1/256 dB)
+ p_volume_max playback volume control max value (in 1/256 dB)
+ p_volume_res playback volume control resolution (in 1/256 dB)
========= ============================
diff --git a/Documentation/ABI/testing/dell-smbios-wmi b/Documentation/ABI/testing/dell-smbios-wmi
index 5f3a0dc67050..f58229084469 100644
--- a/Documentation/ABI/testing/dell-smbios-wmi
+++ b/Documentation/ABI/testing/dell-smbios-wmi
@@ -1,7 +1,7 @@
What: /dev/wmi/dell-smbios
Date: November 2017
KernelVersion: 4.15
-Contact: "Mario Limonciello" <mario.limonciello@dell.com>
+Contact: Dell.Client.Kernel@dell.com
Description:
Perform SMBIOS calls on supported Dell machines.
through the Dell ACPI-WMI interface.
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 070779e8d836..5c2798534950 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -27,12 +27,13 @@ Description:
lsm: [[subj_user=] [subj_role=] [subj_type=]
[obj_user=] [obj_role=] [obj_type=]]
option: [[appraise_type=]] [template=] [permit_directio]
- [appraise_flag=] [keyrings=]
+ [appraise_flag=] [appraise_algos=] [keyrings=]
base:
func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
- [FIRMWARE_CHECK]
+ [FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
[KEXEC_CMDLINE] [KEY_CHECK] [CRITICAL_DATA]
+ [SETXATTR_CHECK]
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
[[^]MAY_EXEC]
fsmagic:= hex value
@@ -55,6 +56,10 @@ Description:
label:= [selinux]|[kernel_info]|[data_label]
data_label:= a unique string used for grouping and limiting critical data.
For example, "selinux" to measure critical data for SELinux.
+ appraise_algos:= comma-separated list of hash algorithms
+ For example, "sha256,sha512" to only accept to appraise
+ files where the security.ima xattr was hashed with one
+ of these two algorithms.
default policy:
# PROC_SUPER_MAGIC
@@ -134,3 +139,9 @@ Description:
keys added to .builtin_trusted_keys or .ima keyring:
measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima
+
+ Example of the special SETXATTR_CHECK appraise rule, that
+ restricts the hash algorithms allowed when writing to the
+ security.ima xattr of a file:
+
+ appraise func=SETXATTR_CHECK appraise_algos=sha256,sha384,sha512
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-chemical-sgp40 b/Documentation/ABI/testing/sysfs-bus-iio-chemical-sgp40
new file mode 100644
index 000000000000..469a7c00fad4
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-chemical-sgp40
@@ -0,0 +1,31 @@
+What: /sys/bus/iio/devices/iio:deviceX/out_temp_raw
+Date: August 2021
+KernelVersion: 5.15
+Contact: Andreas Klinger <ak@it-klinger.de>
+Description:
+ Set the temperature. This value is sent to the sensor for
+ temperature compensation.
+ Default value: 25000 (25 °C)
+
+What: /sys/bus/iio/devices/iio:deviceX/out_humidityrelative_raw
+Date: August 2021
+KernelVersion: 5.15
+Contact: Andreas Klinger <ak@it-klinger.de>
+Description:
+ Set the relative humidity. This value is sent to the sensor for
+ humidity compensation.
+ Default value: 50000 (50 % relative humidity)
+
+What: /sys/bus/iio/devices/iio:deviceX/in_resistance_calibbias
+Date: August 2021
+KernelVersion: 5.15
+Contact: Andreas Klinger <ak@it-klinger.de>
+Description:
+ Set the bias value for the resistance which is used for
+ calculation of in_concentration_input as follows:
+
+ x = (in_resistance_raw - in_resistance_calibbias) * 0.65
+
+ in_concentration_input = 500 / (1 + e^x)
+
+ Default value: 30000
diff --git a/Documentation/ABI/testing/sysfs-bus-thunderbolt b/Documentation/ABI/testing/sysfs-bus-thunderbolt
index 95c21d6c9a84..b7e87f6c7d47 100644
--- a/Documentation/ABI/testing/sysfs-bus-thunderbolt
+++ b/Documentation/ABI/testing/sysfs-bus-thunderbolt
@@ -232,7 +232,7 @@ Description: When new NVM image is written to the non-active NVM
What: /sys/bus/thunderbolt/devices/.../nvm_authenticate_on_disconnect
Date: Oct 2020
KernelVersion: v5.9
-Contact: Mario Limonciello <mario.limonciello@dell.com>
+Contact: Mario Limonciello <mario.limonciello@outlook.com>
Description: For supported devices, automatically authenticate the new Thunderbolt
image when the device is disconnected from the host system.
diff --git a/Documentation/ABI/testing/sysfs-class-firmware-attributes b/Documentation/ABI/testing/sysfs-class-firmware-attributes
index 3348bf80a37c..90fdf935aa5e 100644
--- a/Documentation/ABI/testing/sysfs-class-firmware-attributes
+++ b/Documentation/ABI/testing/sysfs-class-firmware-attributes
@@ -2,8 +2,8 @@ What: /sys/class/firmware-attributes/*/attributes/*/
Date: February 2021
KernelVersion: 5.11
Contact: Divya Bharathi <Divya.Bharathi@Dell.com>,
- Mario Limonciello <mario.limonciello@dell.com>,
Prasanth KSR <prasanth.ksr@dell.com>
+ Dell.Client.Kernel@dell.com
Description:
A sysfs interface for systems management software to enable
configuration capability on supported systems. This directory
@@ -130,8 +130,8 @@ What: /sys/class/firmware-attributes/*/authentication/
Date: February 2021
KernelVersion: 5.11
Contact: Divya Bharathi <Divya.Bharathi@Dell.com>,
- Mario Limonciello <mario.limonciello@dell.com>,
Prasanth KSR <prasanth.ksr@dell.com>
+ Dell.Client.Kernel@dell.com
Description:
Devices support various authentication mechanisms which can be exposed
as a separate configuration object.
@@ -220,8 +220,8 @@ What: /sys/class/firmware-attributes/*/attributes/pending_reboot
Date: February 2021
KernelVersion: 5.11
Contact: Divya Bharathi <Divya.Bharathi@Dell.com>,
- Mario Limonciello <mario.limonciello@dell.com>,
Prasanth KSR <prasanth.ksr@dell.com>
+ Dell.Client.Kernel@dell.com
Description:
A read-only attribute reads 1 if a reboot is necessary to apply
pending BIOS attribute changes. Also, an uevent_KOBJ_CHANGE is
@@ -249,8 +249,8 @@ What: /sys/class/firmware-attributes/*/attributes/reset_bios
Date: February 2021
KernelVersion: 5.11
Contact: Divya Bharathi <Divya.Bharathi@Dell.com>,
- Mario Limonciello <mario.limonciello@dell.com>,
Prasanth KSR <prasanth.ksr@dell.com>
+ Dell.Client.Kernel@dell.com
Description:
This attribute can be used to reset the BIOS Configuration.
Specifically, it tells which type of reset BIOS configuration is being
@@ -272,3 +272,14 @@ Description:
Note that any changes to this attribute requires a reboot
for changes to take effect.
+
+What: /sys/class/firmware-attributes/*/attributes/debug_cmd
+Date: July 2021
+KernelVersion: 5.14
+Contact: Mark Pearson <markpearson@lenovo.com>
+Description:
+ This write only attribute can be used to send debug commands to the BIOS.
+ This should only be used when recommended by the BIOS vendor. Vendors may
+ use it to enable extra debug attributes or BIOS features for testing purposes.
+
+ Note that any changes to this attribute requires a reboot for changes to take effect.
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 160b10c029c0..b46ef147616a 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -494,6 +494,15 @@ Description: AArch64 CPU registers
'identification' directory exposes the CPU ID registers for
identifying model and revision of the CPU.
+What: /sys/devices/system/cpu/aarch32_el0
+Date: May 2021
+Contact: Linux ARM Kernel Mailing list <linux-arm-kernel@lists.infradead.org>
+Description: Identifies the subset of CPUs in the system that can execute
+ AArch32 (32-bit ARM) applications. If present, the same format as
+ /sys/devices/system/cpu/{offline,online,possible,present} is used.
+ If absent, then all or none of the CPUs can execute AArch32
+ applications and execve() will behave accordingly.
+
What: /sys/devices/system/cpu/cpu#/cpu_capacity
Date: December 2016
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
@@ -640,3 +649,20 @@ Description: SPURR ticks for cpuX when it was idle.
This sysfs interface exposes the number of SPURR ticks
for cpuX when it was idle.
+
+What: /sys/devices/system/cpu/cpuX/mte_tcf_preferred
+Date: July 2021
+Contact: Linux ARM Kernel Mailing list <linux-arm-kernel@lists.infradead.org>
+Description: Preferred MTE tag checking mode
+
+ When a user program specifies more than one MTE tag checking
+ mode, this sysfs node is used to specify which mode should
+ be preferred when scheduling a task on that CPU. Possible
+ values:
+
+ ================ ==============================================
+ "sync" Prefer synchronous mode
+ "async" Prefer asynchronous mode
+ ================ ==============================================
+
+ See also: Documentation/arm64/memory-tagging-extension.rst
diff --git a/Documentation/ABI/testing/sysfs-driver-ge-achc b/Documentation/ABI/testing/sysfs-driver-ge-achc
new file mode 100644
index 000000000000..a9e7a079190c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-ge-achc
@@ -0,0 +1,15 @@
+What: /sys/bus/spi/<dev>/update_firmware
+Date: Jul 2021
+Contact: sebastian.reichel@collabora.com
+Description: Write 1 to this file to update the ACHC microcontroller
+ firmware via the EzPort interface. For this the kernel
+ will load "achc.bin" via the firmware API (so usually
+ from /lib/firmware). The write will block until the FW
+ has either been flashed successfully or an error occured.
+
+What: /sys/bus/spi/<dev>/reset
+Date: Jul 2021
+Contact: sebastian.reichel@collabora.com
+Description: This file represents the microcontroller's reset line.
+ 1 means the reset line is asserted, 0 means it's not
+ asserted. The file is read and writable.
diff --git a/Documentation/ABI/testing/sysfs-driver-intc_sar b/Documentation/ABI/testing/sysfs-driver-intc_sar
new file mode 100644
index 000000000000..ec334b0e5ed9
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-intc_sar
@@ -0,0 +1,54 @@
+What: /sys/bus/platform/devices/INTC1092:00/intc_reg
+Date: August 2021
+KernelVersion: 5.15
+Contact: Shravan S <s.shravan@intel.com>,
+ An Sudhakar <sudhakar.an@intel.com>
+Description:
+ Specific Absorption Rate (SAR) regulatory mode is typically
+ derived based on information like mcc (Mobile Country Code) and
+ mnc (Mobile Network Code) that is available for the currently
+ attached LTE network. A userspace application is required to set
+ the current SAR regulatory mode on the Dynamic SAR driver using
+ this sysfs node. Such an application can also read back using
+ this sysfs node, the currently configured regulatory mode value
+ from the Dynamic SAR driver.
+
+ Acceptable regulatory modes are:
+ == ====
+ 0 FCC
+ 1 CE
+ 2 ISED
+ == ====
+
+ - The regulatory mode value has one of the above values.
+ - The default regulatory mode used in the driver is 0.
+
+What: /sys/bus/platform/devices/INTC1092:00/intc_data
+Date: August 2021
+KernelVersion: 5.15
+Contact: Shravan S <s.shravan@intel.com>,
+ An Sudhakar <sudhakar.an@intel.com>
+Description:
+ This sysfs entry is used to retrieve Dynamic SAR information
+ emitted/maintained by a BIOS that supports Dynamic SAR.
+
+ The retrieved information is in the order given below:
+ - device_mode
+ - bandtable_index
+ - antennatable_index
+ - sartable_index
+
+ The above information is sent as integer values separated
+ by a single space. This information can then be pushed to a
+ WWAN modem that uses this to control the transmit signal
+ level using the Band/Antenna/SAR table index information.
+ These parameters are derived/decided by aggregating
+ device-mode like laptop/tablet/clamshell etc. and the
+ proximity-sensor data available to the embedded controller on
+ given host. The regulatory mode configured on Dynamic SAR
+ driver also influences these values.
+
+ The userspace applications can poll for changes to this file
+ using POLLPRI event on file-descriptor (fd) obtained by opening
+ this sysfs entry. Application can then read this information from
+ the sysfs node and consume the given information.
diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index b4a5d55fa19f..ec3a7149ced5 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -1298,3 +1298,239 @@ Description: This node is used to set or display whether UFS WriteBooster is
(if the platform supports UFSHCD_CAP_CLK_SCALING). For a
platform that doesn't support UFSHCD_CAP_CLK_SCALING, we can
disable/enable WriteBooster through this sysfs node.
+
+What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/hpb_version
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the HPB specification version.
+ The full information about the descriptor can be found in the UFS
+ HPB (Host Performance Booster) Extension specifications.
+ Example: version 1.2.3 = 0123h
+
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/hpb_control
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows an indication of the HPB control mode.
+ 00h: Host control mode
+ 01h: Device control mode
+
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/hpb_region_size
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the bHPBRegionSize which can be calculated
+ as in the following (in bytes):
+ HPB Region size = 512B * 2^bHPBRegionSize
+
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/hpb_number_lu
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the maximum number of HPB LU supported by
+ the device.
+ 00h: HPB is not supported by the device.
+ 01h ~ 20h: Maximum number of HPB LU supported by the device
+
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/hpb_subregion_size
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the bHPBSubRegionSize, which can be
+ calculated as in the following (in bytes) and shall be a multiple of
+ logical block size:
+ HPB Sub-Region size = 512B x 2^bHPBSubRegionSize
+ bHPBSubRegionSize shall not exceed bHPBRegionSize.
+
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/hpb_max_active_regions
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the maximum number of active HPB regions that
+ is supported by the device.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/hpb_lu_max_active_regions
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the maximum number of HPB regions assigned to
+ the HPB logical unit.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/hpb_pinned_region_start_offset
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the start offset of HPB pinned region.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/hpb_number_pinned_regions
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the number of HPB pinned regions assigned to
+ the HPB logical unit.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/hpb_stats/hit_cnt
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the number of reads that changed to HPB read.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/hpb_stats/miss_cnt
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the number of reads that cannot be changed to
+ HPB read.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/hpb_stats/rb_noti_cnt
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the number of response UPIUs that has
+ recommendations for activating sub-regions and/or inactivating region.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/hpb_stats/rb_active_cnt
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the number of active sub-regions recommended by
+ response UPIUs.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/hpb_stats/rb_inactive_cnt
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the number of inactive regions recommended by
+ response UPIUs.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/hpb_stats/map_req_cnt
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the number of read buffer commands for
+ activating sub-regions recommended by response UPIUs.
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/hpb_params/requeue_timeout_ms
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the requeue timeout threshold for write buffer
+ command in ms. The value can be changed by writing an integer to
+ this entry.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_size_hpb_single_cmd
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the maximum HPB data size for using a single HPB
+ command.
+
+ === ========
+ 00h 4KB
+ 01h 8KB
+ 02h 12KB
+ ...
+ FFh 1024KB
+ === ========
+
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/flags/hpb_enable
+Date: June 2021
+Contact: Daejun Park <daejun7.park@samsung.com>
+Description: This entry shows the status of HPB.
+
+ == ============================
+ 0 HPB is not enabled.
+ 1 HPB is enabled
+ == ============================
+
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/hpb_param_sysfs/activation_thld
+Date: February 2021
+Contact: Avri Altman <avri.altman@wdc.com>
+Description: In host control mode, reads are the major source of activation
+ trials. Once this threshold hs met, the region is added to the
+ "to-be-activated" list. Since we reset the read counter upon
+ write, this include sending a rb command updating the region
+ ppn as well.
+
+What: /sys/class/scsi_device/*/device/hpb_param_sysfs/normalization_factor
+Date: February 2021
+Contact: Avri Altman <avri.altman@wdc.com>
+Description: In host control mode, we think of the regions as "buckets".
+ Those buckets are being filled with reads, and emptied on write.
+ We use entries_per_srgn - the amount of blocks in a subregion as
+ our bucket size. This applies because HPB1.0 only handles
+ single-block reads. Once the bucket size is crossed, we trigger
+ a normalization work - not only to avoid overflow, but mainly
+ because we want to keep those counters normalized, as we are
+ using those reads as a comparative score, to make various decisions.
+ The normalization is dividing (shift right) the read counter by
+ the normalization_factor. If during consecutive normalizations
+ an active region has exhausted its reads - inactivate it.
+
+What: /sys/class/scsi_device/*/device/hpb_param_sysfs/eviction_thld_enter
+Date: February 2021
+Contact: Avri Altman <avri.altman@wdc.com>
+Description: Region deactivation is often due to the fact that eviction took
+ place: A region becomes active at the expense of another. This is
+ happening when the max-active-regions limit has been crossed.
+ In host mode, eviction is considered an extreme measure. We
+ want to verify that the entering region has enough reads, and
+ the exiting region has much fewer reads. eviction_thld_enter is
+ the min reads that a region must have in order to be considered
+ a candidate for evicting another region.
+
+What: /sys/class/scsi_device/*/device/hpb_param_sysfs/eviction_thld_exit
+Date: February 2021
+Contact: Avri Altman <avri.altman@wdc.com>
+Description: Same as above for the exiting region. A region is considered to
+ be a candidate for eviction only if it has fewer reads than
+ eviction_thld_exit.
+
+What: /sys/class/scsi_device/*/device/hpb_param_sysfs/read_timeout_ms
+Date: February 2021
+Contact: Avri Altman <avri.altman@wdc.com>
+Description: In order not to hang on to "cold" regions, we inactivate
+ a region that has no READ access for a predefined amount of
+ time - read_timeout_ms. If read_timeout_ms has expired, and the
+ region is dirty, it is less likely that we can make any use of
+ HPB reading it so we inactivate it. Still, deactivation has
+ its overhead, and we may still benefit from HPB reading this
+ region if it is clean - see read_timeout_expiries.
+
+What: /sys/class/scsi_device/*/device/hpb_param_sysfs/read_timeout_expiries
+Date: February 2021
+Contact: Avri Altman <avri.altman@wdc.com>
+Description: If the region read timeout has expired, but the region is clean,
+ just re-wind its timer for another spin. Do that as long as it
+ is clean and did not exhaust its read_timeout_expiries threshold.
+
+What: /sys/class/scsi_device/*/device/hpb_param_sysfs/timeout_polling_interval_ms
+Date: February 2021
+Contact: Avri Altman <avri.altman@wdc.com>
+Description: The frequency with which the delayed worker that checks the
+ read_timeouts is awakened.
+
+What: /sys/class/scsi_device/*/device/hpb_param_sysfs/inflight_map_req
+Date: February 2021
+Contact: Avri Altman <avri.altman@wdc.com>
+Description: In host control mode the host is the originator of map requests.
+ To avoid flooding the device with map requests, use a simple throttling
+ mechanism that limits the number of inflight map requests.
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index ef4b9218ae1e..f627e705e663 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -41,8 +41,7 @@ Description: This parameter controls the number of prefree segments to be
What: /sys/fs/f2fs/<disk>/main_blkaddr
Date: November 2019
Contact: "Ramon Pantin" <pantin@google.com>
-Description:
- Shows first block address of MAIN area.
+Description: Shows first block address of MAIN area.
What: /sys/fs/f2fs/<disk>/ipu_policy
Date: November 2013
@@ -493,3 +492,23 @@ Contact: "Chao Yu" <yuchao0@huawei.com>
Description: When ATGC is on, it controls age threshold to bypass GCing young
candidates whose age is not beyond the threshold, by default it was
initialized as 604800 seconds (equals to 7 days).
+
+What: /sys/fs/f2fs/<disk>/gc_reclaimed_segments
+Date: July 2021
+Contact: "Daeho Jeong" <daehojeong@google.com>
+Description: Show how many segments have been reclaimed by GC during a specific
+ GC mode (0: GC normal, 1: GC idle CB, 2: GC idle greedy,
+ 3: GC idle AT, 4: GC urgent high, 5: GC urgent low)
+ You can re-initialize this value to "0".
+
+What: /sys/fs/f2fs/<disk>/gc_segment_mode
+Date: July 2021
+Contact: "Daeho Jeong" <daehojeong@google.com>
+Description: You can control for which gc mode the "gc_reclaimed_segments" node shows.
+ Refer to the description of the modes in "gc_reclaimed_segments".
+
+What: /sys/fs/f2fs/<disk>/seq_file_ra_mul
+Date: July 2021
+Contact: "Daeho Jeong" <daehojeong@google.com>
+Description: You can control the multiplier value of bdi device readahead window size
+ between 2 (default) and 256 for POSIX_FADV_SEQUENTIAL advise option.
diff --git a/Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers b/Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers
new file mode 100644
index 000000000000..5d3bc997dc64
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers
@@ -0,0 +1,24 @@
+What: /sys/kernel/dmabuf/buffers
+Date: May 2021
+KernelVersion: v5.13
+Contact: Hridya Valsaraju <hridya@google.com>
+Description: The /sys/kernel/dmabuf/buffers directory contains a
+ snapshot of the internal state of every DMA-BUF.
+ /sys/kernel/dmabuf/buffers/<inode_number> will contain the
+ statistics for the DMA-BUF with the unique inode number
+ <inode_number>
+Users: kernel memory tuning/debugging tools
+
+What: /sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
+Date: May 2021
+KernelVersion: v5.13
+Contact: Hridya Valsaraju <hridya@google.com>
+Description: This file is read-only and contains the name of the exporter of
+ the DMA-BUF.
+
+What: /sys/kernel/dmabuf/buffers/<inode_number>/size
+Date: May 2021
+KernelVersion: v5.13
+Contact: Hridya Valsaraju <hridya@google.com>
+Description: This file is read-only and specifies the size of the DMA-BUF in
+ bytes.
diff --git a/Documentation/ABI/testing/sysfs-kernel-iommu_groups b/Documentation/ABI/testing/sysfs-kernel-iommu_groups
index eae2f1c1e11e..b15af6a5bc08 100644
--- a/Documentation/ABI/testing/sysfs-kernel-iommu_groups
+++ b/Documentation/ABI/testing/sysfs-kernel-iommu_groups
@@ -42,8 +42,12 @@ Description: /sys/kernel/iommu_groups/<grp_id>/type shows the type of default
======== ======================================================
DMA All the DMA transactions from the device in this group
are translated by the iommu.
+ DMA-FQ As above, but using batched invalidation to lazily
+ remove translations after use. This may offer reduced
+ overhead at the cost of reduced memory protection.
identity All the DMA transactions from the device in this group
- are not translated by the iommu.
+ are not translated by the iommu. Maximum performance
+ but zero protection.
auto Change to the type the device was booted with.
======== ======================================================
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-numa b/Documentation/ABI/testing/sysfs-kernel-mm-numa
new file mode 100644
index 000000000000..77e559d4ed80
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-numa
@@ -0,0 +1,24 @@
+What: /sys/kernel/mm/numa/
+Date: June 2021
+Contact: Linux memory management mailing list <linux-mm@kvack.org>
+Description: Interface for NUMA
+
+What: /sys/kernel/mm/numa/demotion_enabled
+Date: June 2021
+Contact: Linux memory management mailing list <linux-mm@kvack.org>
+Description: Enable/disable demoting pages during reclaim
+
+ Page migration during reclaim is intended for systems
+ with tiered memory configurations. These systems have
+ multiple types of memory with varied performance
+ characteristics instead of plain NUMA systems where
+ the same kind of memory is found at varied distances.
+ Allowing page migration during reclaim enables these
+ systems to migrate pages from fast tiers to slow tiers
+ when the fast tier is under pressure. This migration
+ is performed before swap. It may move data to a NUMA
+ node that does not fall into the cpuset of the
+ allocating process which might be construed to violate
+ the guarantees of cpusets. This should not be enabled
+ on systems which need strict cpuset location
+ guarantees.
diff --git a/Documentation/ABI/testing/sysfs-platform-dell-smbios b/Documentation/ABI/testing/sysfs-platform-dell-smbios
index e6e0f7f834a7..5583da581025 100644
--- a/Documentation/ABI/testing/sysfs-platform-dell-smbios
+++ b/Documentation/ABI/testing/sysfs-platform-dell-smbios
@@ -1,7 +1,7 @@
What: /sys/devices/platform/<platform>/tokens/*
Date: November 2017
KernelVersion: 4.15
-Contact: "Mario Limonciello" <mario.limonciello@dell.com>
+Contact: Dell.Client.Kernel@dell.com
Description:
A read-only description of Dell platform tokens
available on the machine.
diff --git a/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt b/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt
index e19144fd5d86..fd3a7ec79760 100644
--- a/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt
+++ b/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt
@@ -1,7 +1,7 @@
What: /sys/devices/platform/<platform>/force_power
Date: September 2017
KernelVersion: 4.15
-Contact: "Mario Limonciello" <mario.limonciello@dell.com>
+Contact: "Mario Limonciello" <mario.limonciello@outlook.com>
Description:
Modify the platform force power state, influencing
Thunderbolt controllers to turn on or off when no
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index 51c0f578bfce..90ec4987074b 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -295,7 +295,7 @@ Description:
What: /sys/power/resume_offset
Date: April 2018
-Contact: Mario Limonciello <mario.limonciello@dell.com>
+Contact: Mario Limonciello <mario.limonciello@outlook.com>
Description:
This file is used for telling the kernel an offset into a disk
to use when hibernating the system such as with a swap file.
diff --git a/Documentation/PCI/pci.rst b/Documentation/PCI/pci.rst
index fa651e25d98c..87c6f4a6ca32 100644
--- a/Documentation/PCI/pci.rst
+++ b/Documentation/PCI/pci.rst
@@ -103,6 +103,7 @@ need pass only as many optional fields as necessary:
- subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
- class and classmask fields default to 0
- driver_data defaults to 0UL.
+ - override_only field defaults to 0.
Note that driver_data must match the value used by any of the pci_device_id
entries defined in the driver. This makes the driver_data field mandatory
diff --git a/Documentation/admin-guide/binderfs.rst b/Documentation/admin-guide/binderfs.rst
index 199d84314a14..41a4db00df8d 100644
--- a/Documentation/admin-guide/binderfs.rst
+++ b/Documentation/admin-guide/binderfs.rst
@@ -72,3 +72,16 @@ that the `rm() <rm_>`_ tool can be used to delete them. Note that the
``binder-control`` device cannot be deleted since this would make the binderfs
instance unusable. The ``binder-control`` device will be deleted when the
binderfs instance is unmounted and all references to it have been dropped.
+
+Binder features
+---------------
+
+Assuming an instance of binderfs has been mounted at ``/dev/binderfs``, the
+features supported by the binder driver can be located under
+``/dev/binderfs/features/``. The presence of individual files can be tested
+to determine whether a particular feature is supported by the driver.
+
+Example::
+
+ cat /dev/binderfs/features/oneway_spam_detection
+ 1
diff --git a/Documentation/admin-guide/cputopology.rst b/Documentation/admin-guide/cputopology.rst
index 8632a1db36e4..b085dbac60a5 100644
--- a/Documentation/admin-guide/cputopology.rst
+++ b/Documentation/admin-guide/cputopology.rst
@@ -58,9 +58,9 @@ source for the output is in brackets ("[]").
[NR_CPUS-1]
offline: CPUs that are not online because they have been
- HOTPLUGGED off (see cpu-hotplug.txt) or exceed the limit
- of CPUs allowed by the kernel configuration (kernel_max
- above). [~cpu_online_mask + cpus >= NR_CPUS]
+ HOTPLUGGED off or exceed the limit of CPUs allowed by the
+ kernel configuration (kernel_max above).
+ [~cpu_online_mask + cpus >= NR_CPUS]
online: CPUs that are online and being scheduled [cpu_online_mask]
@@ -96,5 +96,5 @@ online.)::
possible: 0-127
present: 0-3
-See cpu-hotplug.txt for the possible_cpus=NUM kernel start parameter
-as well as more information on the various cpumasks.
+See Documentation/core-api/cpu_hotplug.rst for the possible_cpus=NUM
+kernel start parameter as well as more information on the various cpumasks.
diff --git a/Documentation/admin-guide/devices.txt b/Documentation/admin-guide/devices.txt
index 9c2be821c225..922c23bb4372 100644
--- a/Documentation/admin-guide/devices.txt
+++ b/Documentation/admin-guide/devices.txt
@@ -2993,10 +2993,10 @@
65 = /dev/infiniband/issm1 Second InfiniBand IsSM device
...
127 = /dev/infiniband/issm63 63rd InfiniBand IsSM device
- 128 = /dev/infiniband/uverbs0 First InfiniBand verbs device
- 129 = /dev/infiniband/uverbs1 Second InfiniBand verbs device
+ 192 = /dev/infiniband/uverbs0 First InfiniBand verbs device
+ 193 = /dev/infiniband/uverbs1 Second InfiniBand verbs device
...
- 159 = /dev/infiniband/uverbs31 31st InfiniBand verbs device
+ 223 = /dev/infiniband/uverbs31 31st InfiniBand verbs device
232 char Biometric Devices
0 = /dev/biometric/sensor0/fingerprint first fingerprint sensor on first device
diff --git a/Documentation/admin-guide/hw-vuln/core-scheduling.rst b/Documentation/admin-guide/hw-vuln/core-scheduling.rst
index 7b410aef9c5c..0febe458597c 100644
--- a/Documentation/admin-guide/hw-vuln/core-scheduling.rst
+++ b/Documentation/admin-guide/hw-vuln/core-scheduling.rst
@@ -181,10 +181,12 @@ Open cross-HT issues that core scheduling does not solve
--------------------------------------------------------
1. For MDS
~~~~~~~~~~
-Core scheduling cannot protect against MDS attacks between an HT running in
-user mode and another running in kernel mode. Even though both HTs run tasks
-which trust each other, kernel memory is still considered untrusted. Such
-attacks are possible for any combination of sibling CPU modes (host or guest mode).
+Core scheduling cannot protect against MDS attacks between the siblings
+running in user mode and the others running in kernel mode. Even though all
+siblings run tasks which trust each other, when the kernel is executing
+code on behalf of a task, it cannot trust the code running in the
+sibling. Such attacks are possible for any combination of sibling CPU modes
+(host or guest mode).
2. For L1TF
~~~~~~~~~~~
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 2102467faad6..828d11441ebf 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -287,13 +287,21 @@
do not want to use tracing_snapshot_alloc() as it needs
to be done where GFP_KERNEL allocations are allowed.
+ allow_mismatched_32bit_el0 [ARM64]
+ Allow execve() of 32-bit applications and setting of the
+ PER_LINUX32 personality on systems where only a strict
+ subset of the CPUs support 32-bit EL0. When this
+ parameter is present, the set of CPUs supporting 32-bit
+ EL0 is indicated by /sys/devices/system/cpu/aarch32_el0
+ and hot-unplug operations may be restricted.
+
+ See Documentation/arm64/asymmetric-32bit.rst for more
+ information.
+
amd_iommu= [HW,X86-64]
Pass parameters to the AMD IOMMU driver in the system.
Possible values are:
- fullflush - enable flushing of IO/TLB entries when
- they are unmapped. Otherwise they are
- flushed before they will be reused, which
- is a lot of faster
+ fullflush - Deprecated, equivalent to iommu.strict=1
off - do not initialize any AMD IOMMU found in
the system
force_isolation - Force device isolation for all
@@ -380,6 +388,9 @@
arm64.nopauth [ARM64] Unconditionally disable Pointer Authentication
support
+ arm64.nomte [ARM64] Unconditionally disable Memory Tagging Extension
+ support
+
ataflop= [HW,M68k]
atarimouse= [HW,MOUSE] Atari Mouse
@@ -1944,18 +1955,17 @@
this case, gfx device will use physical address for
DMA.
strict [Default Off]
- With this option on every unmap_single operation will
- result in a hardware IOTLB flush operation as opposed
- to batching them for performance.
+ Deprecated, equivalent to iommu.strict=1.
sp_off [Default Off]
By default, super page will be supported if Intel IOMMU
has the capability. With this option, super page will
not be supported.
- sm_on [Default Off]
- By default, scalable mode will be disabled even if the
- hardware advertises that it has support for the scalable
- mode translation. With this option set, scalable mode
- will be used on hardware which claims to support it.
+ sm_on
+ Enable the Intel IOMMU scalable mode if the hardware
+ advertises that it has support for the scalable mode
+ translation.
+ sm_off
+ Disallow use of the Intel IOMMU scalable mode.
tboot_noforce [Default Off]
Do not force the Intel IOMMU enabled under tboot.
By default, tboot will force Intel IOMMU on, which
@@ -2047,13 +2057,12 @@
throughput at the cost of reduced device isolation.
Will fall back to strict mode if not supported by
the relevant IOMMU driver.
- 1 - Strict mode (default).
+ 1 - Strict mode.
DMA unmap operations invalidate IOMMU hardware TLBs
synchronously.
- Note: on x86, the default behaviour depends on the
- equivalent driver-specific parameters, but a strict
- mode explicitly specified by either method takes
- precedence.
+ unset - Use value of CONFIG_IOMMU_DEFAULT_DMA_{LAZY,STRICT}.
+ Note: on x86, strict mode specified via one of the
+ legacy driver-specific options takes precedence.
iommu.passthrough=
[ARM64, X86] Configure DMA to bypass the IOMMU by default.
@@ -4184,6 +4193,15 @@
Format: <bool> (1/Y/y=enable, 0/N/n=disable)
default: disabled
+ printk.console_no_auto_verbose=
+ Disable console loglevel raise on oops, panic
+ or lockdep-detected issues (only if lock debug is on).
+ With an exception to setups with low baudrate on
+ serial console, keeping this 0 is a good choice
+ in order to provide more debug information.
+ Format: <bool>
+ default: 0 (auto_verbose is enabled)
+
printk.devkmsg={on,off,ratelimit}
Control writing to /dev/kmsg.
on - unlimited logging to /dev/kmsg from userspace
diff --git a/Documentation/admin-guide/laptops/lg-laptop.rst b/Documentation/admin-guide/laptops/lg-laptop.rst
index ce9b14671cb9..6fbe165dcd27 100644
--- a/Documentation/admin-guide/laptops/lg-laptop.rst
+++ b/Documentation/admin-guide/laptops/lg-laptop.rst
@@ -13,10 +13,8 @@ Hotkeys
The following FN keys are ignored by the kernel without this driver:
- FN-F1 (LG control panel) - Generates F15
-- FN-F5 (Touchpad toggle) - Generates F13
+- FN-F5 (Touchpad toggle) - Generates F21
- FN-F6 (Airplane mode) - Generates RFKILL
-- FN-F8 (Keyboard backlight) - Generates F16.
- This key also changes keyboard backlight mode.
- FN-F9 (Reader mode) - Generates F14
The rest of the FN keys work without a need for a special driver.
diff --git a/Documentation/admin-guide/mm/numa_memory_policy.rst b/Documentation/admin-guide/mm/numa_memory_policy.rst
index 067a90a1499c..64fd0ba0d057 100644
--- a/Documentation/admin-guide/mm/numa_memory_policy.rst
+++ b/Documentation/admin-guide/mm/numa_memory_policy.rst
@@ -245,6 +245,13 @@ MPOL_INTERLEAVED
address range or file. During system boot up, the temporary
interleaved system default policy works in this mode.
+MPOL_PREFERRED_MANY
+ This mode specifices that the allocation should be preferrably
+ satisfied from the nodemask specified in the policy. If there is
+ a memory pressure on all nodes in the nodemask, the allocation
+ can fall back to all existing numa nodes. This is effectively
+ MPOL_PREFERRED allowed for a mask rather than a single node.
+
NUMA memory policy supports the following optional mode flags:
MPOL_F_STATIC_NODES
@@ -253,10 +260,10 @@ MPOL_F_STATIC_NODES
nodes changes after the memory policy has been defined.
Without this flag, any time a mempolicy is rebound because of a
- change in the set of allowed nodes, the node (Preferred) or
- nodemask (Bind, Interleave) is remapped to the new set of
- allowed nodes. This may result in nodes being used that were
- previously undesired.
+ change in the set of allowed nodes, the preferred nodemask (Preferred
+ Many), preferred node (Preferred) or nodemask (Bind, Interleave) is
+ remapped to the new set of allowed nodes. This may result in nodes
+ being used that were previously undesired.
With this flag, if the user-specified nodes overlap with the
nodes allowed by the task's cpuset, then the memory policy is
diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst
index 003d5cc3751b..5e795202111f 100644
--- a/Documentation/admin-guide/sysctl/vm.rst
+++ b/Documentation/admin-guide/sysctl/vm.rst
@@ -118,7 +118,8 @@ compaction_proactiveness
This tunable takes a value in the range [0, 100] with a default value of
20. This tunable determines how aggressively compaction is done in the
-background. Setting it to 0 disables proactive compaction.
+background. Write of a non zero value to this tunable will immediately
+trigger the proactive compaction. Setting it to 0 disables proactive compaction.
Note that compaction has a non-trivial system-wide impact as pages
belonging to different processes are moved around, which could also lead
diff --git a/Documentation/admin-guide/sysrq.rst b/Documentation/admin-guide/sysrq.rst
index 60ce5f5ebab6..0a178ef0111d 100644
--- a/Documentation/admin-guide/sysrq.rst
+++ b/Documentation/admin-guide/sysrq.rst
@@ -72,7 +72,7 @@ On PowerPC
On other
If you know of the key combos for other architectures, please
- let me know so I can add them to this section.
+ submit a patch to be included in this section.
On all
Write a character to /proc/sysrq-trigger. e.g.::
@@ -205,10 +205,12 @@ frozen (probably root) filesystem via the FIFREEZE ioctl.
Sometimes SysRq seems to get 'stuck' after using it, what can I do?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-That happens to me, also. I've found that tapping shift, alt, and control
-on both sides of the keyboard, and hitting an invalid sysrq sequence again
-will fix the problem. (i.e., something like :kbd:`alt-sysrq-z`). Switching to
-another virtual console (:kbd:`ALT+Fn`) and then back again should also help.
+When this happens, try tapping shift, alt and control on both sides of the
+keyboard, and hitting an invalid sysrq sequence again. (i.e., something like
+:kbd:`alt-sysrq-z`).
+
+Switching to another virtual console (:kbd:`ALT+Fn`) and then back again
+should also help.
I hit SysRq, but nothing seems to happen, what's wrong?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/arm/marvell.rst b/Documentation/arm/marvell.rst
index db2246493d18..85169bc3f538 100644
--- a/Documentation/arm/marvell.rst
+++ b/Documentation/arm/marvell.rst
@@ -58,11 +58,19 @@ Kirkwood family
- Product Brief : https://web.archive.org/web/20120616201621/http://www.marvell.com/embedded-processors/kirkwood/assets/88F6180-003_ver1.pdf
- Hardware Spec : https://web.archive.org/web/20130730091654/http://www.marvell.com/embedded-processors/kirkwood/assets/HW_88F6180_OpenSource.pdf
- Functional Spec: https://web.archive.org/web/20130730091033/http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
+ - 88F6280
+
+ - Product Brief : https://web.archive.org/web/20130730091058/http://www.marvell.com/embedded-processors/kirkwood/assets/88F6280_SoC_PB-001.pdf
- 88F6281
- Product Brief : https://web.archive.org/web/20120131133709/http://www.marvell.com/embedded-processors/kirkwood/assets/88F6281-004_ver1.pdf
- Hardware Spec : https://web.archive.org/web/20120620073511/http://www.marvell.com/embedded-processors/kirkwood/assets/HW_88F6281_OpenSource.pdf
- Functional Spec: https://web.archive.org/web/20130730091033/http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
+ - 88F6321
+ - 88F6322
+ - 88F6323
+
+ - Product Brief : https://web.archive.org/web/20120616201639/http://www.marvell.com/embedded-processors/kirkwood/assets/88f632x_pb.pdf
Homepage:
https://web.archive.org/web/20160513194943/http://www.marvell.com/embedded-processors/kirkwood/
Core:
@@ -89,6 +97,10 @@ Discovery family
- MV76100
+ - Product Brief : https://web.archive.org/web/20140722064429/http://www.marvell.com/embedded-processors/discovery-innovation/assets/MV76100-002_WEB.pdf
+ - Hardware Spec : https://web.archive.org/web/20140722064425/http://www.marvell.com/embedded-processors/discovery-innovation/assets/HW_MV76100_OpenSource.pdf
+ - Functional Spec: https://web.archive.org/web/20111110081125/http://www.marvell.com/embedded-processors/discovery-innovation/assets/FS_MV76100_78100_78200_OpenSource.pdf
+
Not supported by the Linux kernel.
Core:
@@ -124,17 +136,23 @@ EBU Armada family
Armada 38x Flavors:
- 88F6810 Armada 380
+ - 88F6811 Armada 381
+ - 88F6821 Armada 382
+ - 88F6W21 Armada 383
- 88F6820 Armada 385
- 88F6828 Armada 388
- Product infos: https://web.archive.org/web/20181006144616/http://www.marvell.com/embedded-processors/armada-38x/
- Functional Spec: https://web.archive.org/web/20200420191927/https://www.marvell.com/content/dam/marvell/en/public-collateral/embedded-processors/marvell-embedded-processors-armada-38x-functional-specifications-2015-11.pdf
+ - Hardware Spec: https://web.archive.org/web/20180713105318/https://www.marvell.com/docs/embedded-processors/assets/marvell-embedded-processors-armada-38x-hardware-specifications-2017-03.pdf
+ - Design guide: https://web.archive.org/web/20180712231737/https://www.marvell.com/docs/embedded-processors/assets/marvell-embedded-processors-armada-38x-hardware-design-guide-2017-08.pdf
Core:
ARM Cortex-A9
Armada 39x Flavors:
- 88F6920 Armada 390
+ - 88F6925 Armada 395
- 88F6928 Armada 398
- Product infos: https://web.archive.org/web/20181020222559/http://www.marvell.com/embedded-processors/armada-39x/
diff --git a/Documentation/arm64/asymmetric-32bit.rst b/Documentation/arm64/asymmetric-32bit.rst
new file mode 100644
index 000000000000..64a0b505da7d
--- /dev/null
+++ b/Documentation/arm64/asymmetric-32bit.rst
@@ -0,0 +1,155 @@
+======================
+Asymmetric 32-bit SoCs
+======================
+
+Author: Will Deacon <will@kernel.org>
+
+This document describes the impact of asymmetric 32-bit SoCs on the
+execution of 32-bit (``AArch32``) applications.
+
+Date: 2021-05-17
+
+Introduction
+============
+
+Some Armv9 SoCs suffer from a big.LITTLE misfeature where only a subset
+of the CPUs are capable of executing 32-bit user applications. On such
+a system, Linux by default treats the asymmetry as a "mismatch" and
+disables support for both the ``PER_LINUX32`` personality and
+``execve(2)`` of 32-bit ELF binaries, with the latter returning
+``-ENOEXEC``. If the mismatch is detected during late onlining of a
+64-bit-only CPU, then the onlining operation fails and the new CPU is
+unavailable for scheduling.
+
+Surprisingly, these SoCs have been produced with the intention of
+running legacy 32-bit binaries. Unsurprisingly, that doesn't work very
+well with the default behaviour of Linux.
+
+It seems inevitable that future SoCs will drop 32-bit support
+altogether, so if you're stuck in the unenviable position of needing to
+run 32-bit code on one of these transitionary platforms then you would
+be wise to consider alternatives such as recompilation, emulation or
+retirement. If neither of those options are practical, then read on.
+
+Enabling kernel support
+=======================
+
+Since the kernel support is not completely transparent to userspace,
+allowing 32-bit tasks to run on an asymmetric 32-bit system requires an
+explicit "opt-in" and can be enabled by passing the
+``allow_mismatched_32bit_el0`` parameter on the kernel command-line.
+
+For the remainder of this document we will refer to an *asymmetric
+system* to mean an asymmetric 32-bit SoC running Linux with this kernel
+command-line option enabled.
+
+Userspace impact
+================
+
+32-bit tasks running on an asymmetric system behave in mostly the same
+way as on a homogeneous system, with a few key differences relating to
+CPU affinity.
+
+sysfs
+-----
+
+The subset of CPUs capable of running 32-bit tasks is described in
+``/sys/devices/system/cpu/aarch32_el0`` and is documented further in
+``Documentation/ABI/testing/sysfs-devices-system-cpu``.
+
+**Note:** CPUs are advertised by this file as they are detected and so
+late-onlining of 32-bit-capable CPUs can result in the file contents
+being modified by the kernel at runtime. Once advertised, CPUs are never
+removed from the file.
+
+``execve(2)``
+-------------
+
+On a homogeneous system, the CPU affinity of a task is preserved across
+``execve(2)``. This is not always possible on an asymmetric system,
+specifically when the new program being executed is 32-bit yet the
+affinity mask contains 64-bit-only CPUs. In this situation, the kernel
+determines the new affinity mask as follows:
+
+ 1. If the 32-bit-capable subset of the affinity mask is not empty,
+ then the affinity is restricted to that subset and the old affinity
+ mask is saved. This saved mask is inherited over ``fork(2)`` and
+ preserved across ``execve(2)`` of 32-bit programs.
+
+ **Note:** This step does not apply to ``SCHED_DEADLINE`` tasks.
+ See `SCHED_DEADLINE`_.
+
+ 2. Otherwise, the cpuset hierarchy of the task is walked until an
+ ancestor is found containing at least one 32-bit-capable CPU. The
+ affinity of the task is then changed to match the 32-bit-capable
+ subset of the cpuset determined by the walk.
+
+ 3. On failure (i.e. out of memory), the affinity is changed to the set
+ of all 32-bit-capable CPUs of which the kernel is aware.
+
+A subsequent ``execve(2)`` of a 64-bit program by the 32-bit task will
+invalidate the affinity mask saved in (1) and attempt to restore the CPU
+affinity of the task using the saved mask if it was previously valid.
+This restoration may fail due to intervening changes to the deadline
+policy or cpuset hierarchy, in which case the ``execve(2)`` continues
+with the affinity unchanged.
+
+Calls to ``sched_setaffinity(2)`` for a 32-bit task will consider only
+the 32-bit-capable CPUs of the requested affinity mask. On success, the
+affinity for the task is updated and any saved mask from a prior
+``execve(2)`` is invalidated.
+
+``SCHED_DEADLINE``
+------------------
+
+Explicit admission of a 32-bit deadline task to the default root domain
+(e.g. by calling ``sched_setattr(2)``) is rejected on an asymmetric
+32-bit system unless admission control is disabled by writing -1 to
+``/proc/sys/kernel/sched_rt_runtime_us``.
+
+``execve(2)`` of a 32-bit program from a 64-bit deadline task will
+return ``-ENOEXEC`` if the root domain for the task contains any
+64-bit-only CPUs and admission control is enabled. Concurrent offlining
+of 32-bit-capable CPUs may still necessitate the procedure described in
+`execve(2)`_, in which case step (1) is skipped and a warning is
+emitted on the console.
+
+**Note:** It is recommended that a set of 32-bit-capable CPUs are placed
+into a separate root domain if ``SCHED_DEADLINE`` is to be used with
+32-bit tasks on an asymmetric system. Failure to do so is likely to
+result in missed deadlines.
+
+Cpusets
+-------
+
+The affinity of a 32-bit task on an asymmetric system may include CPUs
+that are not explicitly allowed by the cpuset to which it is attached.
+This can occur as a result of the following two situations:
+
+ - A 64-bit task attached to a cpuset which allows only 64-bit CPUs
+ executes a 32-bit program.
+
+ - All of the 32-bit-capable CPUs allowed by a cpuset containing a
+ 32-bit task are offlined.
+
+In both of these cases, the new affinity is calculated according to step
+(2) of the process described in `execve(2)`_ and the cpuset hierarchy is
+unchanged irrespective of the cgroup version.
+
+CPU hotplug
+-----------
+
+On an asymmetric system, the first detected 32-bit-capable CPU is
+prevented from being offlined by userspace and any such attempt will
+return ``-EPERM``. Note that suspend is still permitted even if the
+primary CPU (i.e. CPU 0) is 64-bit-only.
+
+KVM
+---
+
+Although KVM will not advertise 32-bit EL0 support to any vCPUs on an
+asymmetric system, a broken guest at EL1 could still attempt to execute
+32-bit code at EL0. In this case, an exit from a vCPU thread in 32-bit
+mode will return to host userspace with an ``exit_reason`` of
+``KVM_EXIT_FAIL_ENTRY`` and will remain non-runnable until successfully
+re-initialised by a subsequent ``KVM_ARM_VCPU_INIT`` operation.
diff --git a/Documentation/arm64/booting.rst b/Documentation/arm64/booting.rst
index a9192e7a231b..3f9d86557c5e 100644
--- a/Documentation/arm64/booting.rst
+++ b/Documentation/arm64/booting.rst
@@ -207,10 +207,17 @@ Before jumping into the kernel, the following conditions must be met:
software at a higher exception level to prevent execution in an UNKNOWN
state.
- - SCR_EL3.FIQ must have the same value across all CPUs the kernel is
- executing on.
- - The value of SCR_EL3.FIQ must be the same as the one present at boot
- time whenever the kernel is executing.
+ For all systems:
+ - If EL3 is present:
+
+ - SCR_EL3.FIQ must have the same value across all CPUs the kernel is
+ executing on.
+ - The value of SCR_EL3.FIQ must be the same as the one present at boot
+ time whenever the kernel is executing.
+
+ - If EL3 is present and the kernel is entered at EL2:
+
+ - SCR_EL3.HCE (bit 8) must be initialised to 0b1.
For systems with a GICv3 interrupt controller to be used in v3 mode:
- If EL3 is present:
@@ -311,6 +318,28 @@ Before jumping into the kernel, the following conditions must be met:
- ZCR_EL2.LEN must be initialised to the same value for all CPUs the
kernel will execute on.
+ For CPUs with the Scalable Matrix Extension (FEAT_SME):
+
+ - If EL3 is present:
+
+ - CPTR_EL3.ESM (bit 12) must be initialised to 0b1.
+
+ - SCR_EL3.EnTP2 (bit 41) must be initialised to 0b1.
+
+ - SMCR_EL3.LEN must be initialised to the same value for all CPUs the
+ kernel will execute on.
+
+ - If the kernel is entered at EL1 and EL2 is present:
+
+ - CPTR_EL2.TSM (bit 12) must be initialised to 0b0.
+
+ - CPTR_EL2.SMEN (bits 25:24) must be initialised to 0b11.
+
+ - SCTLR_EL2.EnTP2 (bit 60) must be initialised to 0b1.
+
+ - SMCR_EL2.LEN must be initialised to the same value for all CPUs the
+ kernel will execute on.
+
The requirements described above for CPU mode, caches, MMUs, architected
timers, coherency and system registers apply to all CPUs. All CPUs must
enter the kernel in the same exception level. Where the values documented
diff --git a/Documentation/arm64/index.rst b/Documentation/arm64/index.rst
index 97d65ba12a35..4f840bac083e 100644
--- a/Documentation/arm64/index.rst
+++ b/Documentation/arm64/index.rst
@@ -10,6 +10,7 @@ ARM64 Architecture
acpi_object_usage
amu
arm-acpi
+ asymmetric-32bit
booting
cpu-feature-registers
elf_hwcaps
diff --git a/Documentation/arm64/memory-tagging-extension.rst b/Documentation/arm64/memory-tagging-extension.rst
index b540178a93f8..7b99c8f428eb 100644
--- a/Documentation/arm64/memory-tagging-extension.rst
+++ b/Documentation/arm64/memory-tagging-extension.rst
@@ -77,14 +77,20 @@ configurable behaviours:
address is unknown).
The user can select the above modes, per thread, using the
-``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)`` system call where
-``flags`` contain one of the following values in the ``PR_MTE_TCF_MASK``
+``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)`` system call where ``flags``
+contains any number of the following values in the ``PR_MTE_TCF_MASK``
bit-field:
-- ``PR_MTE_TCF_NONE`` - *Ignore* tag check faults
+- ``PR_MTE_TCF_NONE``  - *Ignore* tag check faults
+ (ignored if combined with other options)
- ``PR_MTE_TCF_SYNC`` - *Synchronous* tag check fault mode
- ``PR_MTE_TCF_ASYNC`` - *Asynchronous* tag check fault mode
+If no modes are specified, tag check faults are ignored. If a single
+mode is specified, the program will run in that mode. If multiple
+modes are specified, the mode is selected as described in the "Per-CPU
+preferred tag checking modes" section below.
+
The current tag check fault mode can be read using the
``prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)`` system call.
@@ -120,13 +126,39 @@ in the ``PR_MTE_TAG_MASK`` bit-field.
interface provides an include mask. An include mask of ``0`` (exclusion
mask ``0xffff``) results in the CPU always generating tag ``0``.
+Per-CPU preferred tag checking mode
+-----------------------------------
+
+On some CPUs the performance of MTE in stricter tag checking modes
+is similar to that of less strict tag checking modes. This makes it
+worthwhile to enable stricter checks on those CPUs when a less strict
+checking mode is requested, in order to gain the error detection
+benefits of the stricter checks without the performance downsides. To
+support this scenario, a privileged user may configure a stricter
+tag checking mode as the CPU's preferred tag checking mode.
+
+The preferred tag checking mode for each CPU is controlled by
+``/sys/devices/system/cpu/cpu<N>/mte_tcf_preferred``, to which a
+privileged user may write the value ``async`` or ``sync``. The default
+preferred mode for each CPU is ``async``.
+
+To allow a program to potentially run in the CPU's preferred tag
+checking mode, the user program may set multiple tag check fault mode
+bits in the ``flags`` argument to the ``prctl(PR_SET_TAGGED_ADDR_CTRL,
+flags, 0, 0, 0)`` system call. If the CPU's preferred tag checking
+mode is in the task's set of provided tag checking modes (this will
+always be the case at present because the kernel only supports two
+tag checking modes, but future kernels may support more modes), that
+mode will be selected. Otherwise, one of the modes in the task's mode
+set will be selected in a currently unspecified manner.
+
Initial process state
---------------------
On ``execve()``, the new process has the following configuration:
- ``PR_TAGGED_ADDR_ENABLE`` set to 0 (disabled)
-- Tag checking mode set to ``PR_MTE_TCF_NONE``
+- No tag checking modes are selected (tag check faults ignored)
- ``PR_MTE_TAG_MASK`` set to 0 (all tags excluded)
- ``PSTATE.TCO`` set to 0
- ``PROT_MTE`` not set on any of the initial memory maps
@@ -251,11 +283,13 @@ Example of correct usage
return EXIT_FAILURE;
/*
- * Enable the tagged address ABI, synchronous MTE tag check faults and
- * allow all non-zero tags in the randomly generated set.
+ * Enable the tagged address ABI, synchronous or asynchronous MTE
+ * tag check faults (based on per-CPU preference) and allow all
+ * non-zero tags in the randomly generated set.
*/
if (prctl(PR_SET_TAGGED_ADDR_CTRL,
- PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT),
+ PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC |
+ (0xfffe << PR_MTE_TAG_SHIFT),
0, 0, 0)) {
perror("prctl() failed");
return EXIT_FAILURE;
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 7d92ec3e5b6e..75650f6443af 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -16,8 +16,6 @@ import sys
import os
import sphinx
-from subprocess import check_output
-
# Get Sphinx version
major, minor, patch = sphinx.version_info[:3]
@@ -343,6 +341,9 @@ latex_elements = {
verbatimhintsturnover=false,
''',
+ # For CJK One-half spacing, need to be in front of hyperref
+ 'extrapackages': r'\usepackage{setspace}',
+
# Additional stuff for the LaTeX preamble.
'preamble': '''
% Prevent column squeezing of tabulary.
@@ -355,29 +356,117 @@ latex_elements = {
''',
}
-# At least one book (translations) may have Asian characters
-# with are only displayed if xeCJK is used
+# Translations have Asian (CJK) characters which are only displayed if
+# xeCJK is used
-cjk_cmd = check_output(['fc-list', '--format="%{family[0]}\n"']).decode('utf-8', 'ignore')
-if cjk_cmd.find("Noto Sans CJK SC") >= 0:
- latex_elements['preamble'] += '''
+latex_elements['preamble'] += '''
+ \\IfFontExistsTF{Noto Sans CJK SC}{
% This is needed for translations
- \\usepackage{xeCJK}
- \\setCJKmainfont{Noto Sans CJK SC}
+ \\usepackage{xeCJK}
+ \\IfFontExistsTF{Noto Serif CJK SC}{
+ \\setCJKmainfont{Noto Serif CJK SC}[AutoFakeSlant]
+ }{
+ \\setCJKmainfont{Noto Sans CJK SC}[AutoFakeSlant]
+ }
+ \\setCJKsansfont{Noto Sans CJK SC}[AutoFakeSlant]
+ \\setCJKmonofont{Noto Sans Mono CJK SC}[AutoFakeSlant]
+ % CJK Language-specific font choices
+ \\IfFontExistsTF{Noto Serif CJK SC}{
+ \\newCJKfontfamily[SCmain]\\scmain{Noto Serif CJK SC}[AutoFakeSlant]
+ \\newCJKfontfamily[SCserif]\\scserif{Noto Serif CJK SC}[AutoFakeSlant]
+ }{
+ \\newCJKfontfamily[SCmain]\\scmain{Noto Sans CJK SC}[AutoFakeSlant]
+ \\newCJKfontfamily[SCserif]\\scserif{Noto Sans CJK SC}[AutoFakeSlant]
+ }
+ \\newCJKfontfamily[SCsans]\\scsans{Noto Sans CJK SC}[AutoFakeSlant]
+ \\newCJKfontfamily[SCmono]\\scmono{Noto Sans Mono CJK SC}[AutoFakeSlant]
+ \\IfFontExistsTF{Noto Serif CJK TC}{
+ \\newCJKfontfamily[TCmain]\\tcmain{Noto Serif CJK TC}[AutoFakeSlant]
+ \\newCJKfontfamily[TCserif]\\tcserif{Noto Serif CJK TC}[AutoFakeSlant]
+ }{
+ \\newCJKfontfamily[TCmain]\\tcmain{Noto Sans CJK TC}[AutoFakeSlant]
+ \\newCJKfontfamily[TCserif]\\tcserif{Noto Sans CJK TC}[AutoFakeSlant]
+ }
+ \\newCJKfontfamily[TCsans]\\tcsans{Noto Sans CJK TC}[AutoFakeSlant]
+ \\newCJKfontfamily[TCmono]\\tcmono{Noto Sans Mono CJK TC}[AutoFakeSlant]
+ \\IfFontExistsTF{Noto Serif CJK KR}{
+ \\newCJKfontfamily[KRmain]\\krmain{Noto Serif CJK KR}[AutoFakeSlant]
+ \\newCJKfontfamily[KRserif]\\krserif{Noto Serif CJK KR}[AutoFakeSlant]
+ }{
+ \\newCJKfontfamily[KRmain]\\krmain{Noto Sans CJK KR}[AutoFakeSlant]
+ \\newCJKfontfamily[KRserif]\\krserif{Noto Sans CJK KR}[AutoFakeSlant]
+ }
+ \\newCJKfontfamily[KRsans]\\krsans{Noto Sans CJK KR}[AutoFakeSlant]
+ \\newCJKfontfamily[KRmono]\\krmono{Noto Sans Mono CJK KR}[AutoFakeSlant]
+ \\IfFontExistsTF{Noto Serif CJK JP}{
+ \\newCJKfontfamily[JPmain]\\jpmain{Noto Serif CJK JP}[AutoFakeSlant]
+ \\newCJKfontfamily[JPserif]\\jpserif{Noto Serif CJK JP}[AutoFakeSlant]
+ }{
+ \\newCJKfontfamily[JPmain]\\jpmain{Noto Sans CJK JP}[AutoFakeSlant]
+ \\newCJKfontfamily[JPserif]\\jpserif{Noto Sans CJK JP}[AutoFakeSlant]
+ }
+ \\newCJKfontfamily[JPsans]\\jpsans{Noto Sans CJK JP}[AutoFakeSlant]
+ \\newCJKfontfamily[JPmono]\\jpmono{Noto Sans Mono CJK JP}[AutoFakeSlant]
+ % Dummy commands for Sphinx < 2.3 (no 'extrapackages' support)
+ \\providecommand{\\onehalfspacing}{}
+ \\providecommand{\\singlespacing}{}
% Define custom macros to on/off CJK
- \\newcommand{\\kerneldocCJKon}{\\makexeCJKactive}
- \\newcommand{\\kerneldocCJKoff}{\\makexeCJKinactive}
- % To customize \sphinxtableofcontents
+ \\newcommand{\\kerneldocCJKon}{\\makexeCJKactive\\onehalfspacing}
+ \\newcommand{\\kerneldocCJKoff}{\\makexeCJKinactive\\singlespacing}
+ \\newcommand{\\kerneldocBeginSC}{%
+ \\begingroup%
+ \\scmain%
+ }
+ \\newcommand{\\kerneldocEndSC}{\\endgroup}
+ \\newcommand{\\kerneldocBeginTC}{%
+ \\begingroup%
+ \\tcmain%
+ \\renewcommand{\\CJKrmdefault}{TCserif}%
+ \\renewcommand{\\CJKsfdefault}{TCsans}%
+ \\renewcommand{\\CJKttdefault}{TCmono}%
+ }
+ \\newcommand{\\kerneldocEndTC}{\\endgroup}
+ \\newcommand{\\kerneldocBeginKR}{%
+ \\begingroup%
+ \\xeCJKDeclareCharClass{HalfLeft}{`“,`‘}%
+ \\xeCJKDeclareCharClass{HalfRight}{`”,`’}%
+ \\krmain%
+ \\renewcommand{\\CJKrmdefault}{KRserif}%
+ \\renewcommand{\\CJKsfdefault}{KRsans}%
+ \\renewcommand{\\CJKttdefault}{KRmono}%
+ \\xeCJKsetup{CJKspace = true} % For inter-phrase space
+ }
+ \\newcommand{\\kerneldocEndKR}{\\endgroup}
+ \\newcommand{\\kerneldocBeginJP}{%
+ \\begingroup%
+ \\xeCJKDeclareCharClass{HalfLeft}{`“,`‘}%
+ \\xeCJKDeclareCharClass{HalfRight}{`”,`’}%
+ \\jpmain%
+ \\renewcommand{\\CJKrmdefault}{JPserif}%
+ \\renewcommand{\\CJKsfdefault}{JPsans}%
+ \\renewcommand{\\CJKttdefault}{JPmono}%
+ }
+ \\newcommand{\\kerneldocEndJP}{\\endgroup}
+ % Single spacing in literal blocks
+ \\fvset{baselinestretch=1}
+ % To customize \\sphinxtableofcontents
\\usepackage{etoolbox}
% Inactivate CJK after tableofcontents
\\apptocmd{\\sphinxtableofcontents}{\\kerneldocCJKoff}{}{}
- '''
-else:
- latex_elements['preamble'] += '''
+ }{ % No CJK font found
% Custom macros to on/off CJK (Dummy)
\\newcommand{\\kerneldocCJKon}{}
\\newcommand{\\kerneldocCJKoff}{}
- '''
+ \\newcommand{\\kerneldocBeginSC}{}
+ \\newcommand{\\kerneldocEndSC}{}
+ \\newcommand{\\kerneldocBeginTC}{}
+ \\newcommand{\\kerneldocEndTC}{}
+ \\newcommand{\\kerneldocBeginKR}{}
+ \\newcommand{\\kerneldocEndKR}{}
+ \\newcommand{\\kerneldocBeginSC}{}
+ \\newcommand{\\kerneldocEndKR}{}
+ }
+'''
# Fix reference escape troubles with Sphinx 1.4.x
if major == 1:
diff --git a/Documentation/core-api/cachetlb.rst b/Documentation/core-api/cachetlb.rst
index fe4290e26729..8aed9103e48a 100644
--- a/Documentation/core-api/cachetlb.rst
+++ b/Documentation/core-api/cachetlb.rst
@@ -271,10 +271,15 @@ maps this page at its virtual address.
``void flush_dcache_page(struct page *page)``
- Any time the kernel writes to a page cache page, _OR_
- the kernel is about to read from a page cache page and
- user space shared/writable mappings of this page potentially
- exist, this routine is called.
+ This routines must be called when:
+
+ a) the kernel did write to a page that is in the page cache page
+ and / or in high memory
+ b) the kernel is about to read from a page cache page and user space
+ shared/writable mappings of this page potentially exist. Note
+ that {get,pin}_user_pages{_fast} already call flush_dcache_page
+ on any page found in the user address space and thus driver
+ code rarely needs to take this into account.
.. note::
@@ -284,38 +289,34 @@ maps this page at its virtual address.
handling vfs symlinks in the page cache need not call
this interface at all.
- The phrase "kernel writes to a page cache page" means,
- specifically, that the kernel executes store instructions
- that dirty data in that page at the page->virtual mapping
- of that page. It is important to flush here to handle
- D-cache aliasing, to make sure these kernel stores are
- visible to user space mappings of that page.
-
- The corollary case is just as important, if there are users
- which have shared+writable mappings of this file, we must make
- sure that kernel reads of these pages will see the most recent
- stores done by the user.
-
- If D-cache aliasing is not an issue, this routine may
- simply be defined as a nop on that architecture.
-
- There is a bit set aside in page->flags (PG_arch_1) as
- "architecture private". The kernel guarantees that,
- for pagecache pages, it will clear this bit when such
- a page first enters the pagecache.
-
- This allows these interfaces to be implemented much more
- efficiently. It allows one to "defer" (perhaps indefinitely)
- the actual flush if there are currently no user processes
- mapping this page. See sparc64's flush_dcache_page and
- update_mmu_cache implementations for an example of how to go
- about doing this.
-
- The idea is, first at flush_dcache_page() time, if
- page->mapping->i_mmap is an empty tree, just mark the architecture
- private page flag bit. Later, in update_mmu_cache(), a check is
- made of this flag bit, and if set the flush is done and the flag
- bit is cleared.
+ The phrase "kernel writes to a page cache page" means, specifically,
+ that the kernel executes store instructions that dirty data in that
+ page at the page->virtual mapping of that page. It is important to
+ flush here to handle D-cache aliasing, to make sure these kernel stores
+ are visible to user space mappings of that page.
+
+ The corollary case is just as important, if there are users which have
+ shared+writable mappings of this file, we must make sure that kernel
+ reads of these pages will see the most recent stores done by the user.
+
+ If D-cache aliasing is not an issue, this routine may simply be defined
+ as a nop on that architecture.
+
+ There is a bit set aside in page->flags (PG_arch_1) as "architecture
+ private". The kernel guarantees that, for pagecache pages, it will
+ clear this bit when such a page first enters the pagecache.
+
+ This allows these interfaces to be implemented much more efficiently.
+ It allows one to "defer" (perhaps indefinitely) the actual flush if
+ there are currently no user processes mapping this page. See sparc64's
+ flush_dcache_page and update_mmu_cache implementations for an example
+ of how to go about doing this.
+
+ The idea is, first at flush_dcache_page() time, if page_file_mapping()
+ returns a mapping, and mapping_mapped on that mapping returns %false,
+ just mark the architecture private page flag bit. Later, in
+ update_mmu_cache(), a check is made of this flag bit, and if set the
+ flush is done and the flag bit is cleared.
.. important::
@@ -351,19 +352,6 @@ maps this page at its virtual address.
architectures). For incoherent architectures, it should flush
the cache of the page at vmaddr.
- ``void flush_kernel_dcache_page(struct page *page)``
-
- When the kernel needs to modify a user page is has obtained
- with kmap, it calls this function after all modifications are
- complete (but before kunmapping it) to bring the underlying
- page up to date. It is assumed here that the user has no
- incoherent cached copies (i.e. the original page was obtained
- from a mechanism like get_user_pages()). The default
- implementation is a nop and should remain so on all coherent
- architectures. On incoherent architectures, this should flush
- the kernel cache for page (using page_address(page)).
-
-
``void flush_icache_range(unsigned long start, unsigned long end)``
When the kernel stores into addresses that it will execute
diff --git a/Documentation/core-api/cpu_hotplug.rst b/Documentation/core-api/cpu_hotplug.rst
index 1122cd3044c0..b66e3cae1472 100644
--- a/Documentation/core-api/cpu_hotplug.rst
+++ b/Documentation/core-api/cpu_hotplug.rst
@@ -91,9 +91,10 @@ Never use anything other than ``cpumask_t`` to represent bitmap of CPUs.
Using CPU hotplug
=================
+
The kernel option *CONFIG_HOTPLUG_CPU* needs to be enabled. It is currently
available on multiple architectures including ARM, MIPS, PowerPC and X86. The
-configuration is done via the sysfs interface: ::
+configuration is done via the sysfs interface::
$ ls -lh /sys/devices/system/cpu
total 0
@@ -113,14 +114,14 @@ configuration is done via the sysfs interface: ::
The files *offline*, *online*, *possible*, *present* represent the CPU masks.
Each CPU folder contains an *online* file which controls the logical on (1) and
-off (0) state. To logically shutdown CPU4: ::
+off (0) state. To logically shutdown CPU4::
$ echo 0 > /sys/devices/system/cpu/cpu4/online
smpboot: CPU 4 is now offline
Once the CPU is shutdown, it will be removed from */proc/interrupts*,
*/proc/cpuinfo* and should also not be shown visible by the *top* command. To
-bring CPU4 back online: ::
+bring CPU4 back online::
$ echo 1 > /sys/devices/system/cpu/cpu4/online
smpboot: Booting Node 0 Processor 4 APIC 0x1
@@ -142,6 +143,7 @@ The CPU hotplug coordination
The offline case
----------------
+
Once a CPU has been logically shutdown the teardown callbacks of registered
hotplug states will be invoked, starting with ``CPUHP_ONLINE`` and terminating
at state ``CPUHP_OFFLINE``. This includes:
@@ -158,9 +160,10 @@ at state ``CPUHP_OFFLINE``. This includes:
Using the hotplug API
---------------------
+
It is possible to receive notifications once a CPU is offline or onlined. This
might be important to certain drivers which need to perform some kind of setup
-or clean up functions based on the number of available CPUs: ::
+or clean up functions based on the number of available CPUs::
#include <linux/cpuhotplug.h>
@@ -186,9 +189,10 @@ During the removal of a hotplug state the teardown callback will be invoked.
Multiple instances
~~~~~~~~~~~~~~~~~~
+
If a driver has multiple instances and each instance needs to perform the
callback independently then it is likely that a ''multi-state'' should be used.
-First a multi-state state needs to be registered: ::
+First a multi-state state needs to be registered::
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "X/Y:online,
Y_online, Y_prepare_down);
@@ -197,7 +201,7 @@ First a multi-state state needs to be registered: ::
The ``cpuhp_setup_state_multi()`` behaves similar to ``cpuhp_setup_state()``
except it prepares the callbacks for a multi state and does not invoke
the callbacks. This is a one time setup.
-Once a new instance is allocated, you need to register this new instance: ::
+Once a new instance is allocated, you need to register this new instance::
ret = cpuhp_state_add_instance(Y_hp_online, &d->node);
@@ -206,7 +210,8 @@ This function will add this instance to your previously allocated
(*Y_online*) on all online CPUs. The *node* element is a ``struct
hlist_node`` member of your per-instance data structure.
-On removal of the instance: ::
+On removal of the instance::
+
cpuhp_state_remove_instance(Y_hp_online, &d->node)
should be invoked which will invoke the teardown callback on all online
@@ -214,6 +219,7 @@ CPUs.
Manual setup
~~~~~~~~~~~~
+
Usually it is handy to invoke setup and teardown callbacks on registration or
removal of a state because usually the operation needs to performed once a CPU
goes online (offline) and during initial setup (shutdown) of the driver. However
@@ -226,6 +232,7 @@ hotplug operations.
The ordering of the events
--------------------------
+
The hotplug states are defined in ``include/linux/cpuhotplug.h``:
* The states *CPUHP_OFFLINE* … *CPUHP_AP_OFFLINE* are invoked before the
@@ -248,13 +255,14 @@ another hotplug event.
Testing of hotplug states
=========================
+
One way to verify whether a custom state is working as expected or not is to
shutdown a CPU and then put it online again. It is also possible to put the CPU
to certain state (for instance *CPUHP_AP_ONLINE*) and then go back to
*CPUHP_ONLINE*. This would simulate an error one state after *CPUHP_AP_ONLINE*
which would lead to rollback to the online state.
-All registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states``: ::
+All registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states`` ::
$ tail /sys/devices/system/cpu/hotplug/states
138: mm/vmscan:online
@@ -268,7 +276,7 @@ All registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states
168: sched:active
169: online
-To rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue: ::
+To rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue::
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
169
@@ -276,14 +284,14 @@ To rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue: ::
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
140
-It is important to note that the teardown callbac of state 140 have been
-invoked. And now get back online: ::
+It is important to note that the teardown callback of state 140 have been
+invoked. And now get back online::
$ echo 169 > /sys/devices/system/cpu/cpu4/hotplug/target
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
169
-With trace events enabled, the individual steps are visible, too: ::
+With trace events enabled, the individual steps are visible, too::
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
@@ -318,6 +326,7 @@ trace.
Architecture's requirements
===========================
+
The following functions and configurations are required:
``CONFIG_HOTPLUG_CPU``
@@ -339,11 +348,12 @@ The following functions and configurations are required:
User Space Notification
=======================
-After CPU successfully onlined or offline udev events are sent. A udev rule like: ::
+
+After CPU successfully onlined or offline udev events are sent. A udev rule like::
SUBSYSTEM=="cpu", DRIVERS=="processor", DEVPATH=="/devices/system/cpu/*", RUN+="the_hotplug_receiver.sh"
-will receive all events. A script like: ::
+will receive all events. A script like::
#!/bin/sh
diff --git a/Documentation/core-api/printk-basics.rst b/Documentation/core-api/printk-basics.rst
index 965e4281eddd..2dde24ca7d9f 100644
--- a/Documentation/core-api/printk-basics.rst
+++ b/Documentation/core-api/printk-basics.rst
@@ -107,9 +107,6 @@ also ``CONFIG_DYNAMIC_DEBUG`` in the case of pr_debug()) is defined.
Function reference
==================
-.. kernel-doc:: kernel/printk/printk.c
- :functions: printk
-
.. kernel-doc:: include/linux/printk.h
- :functions: pr_emerg pr_alert pr_crit pr_err pr_warn pr_notice pr_info
+ :functions: printk pr_emerg pr_alert pr_crit pr_err pr_warn pr_notice pr_info
pr_fmt pr_debug pr_devel pr_cont
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index d941717a191b..e08bbe9b0cbf 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -130,6 +130,7 @@ printed after the symbol name with an extra ``b`` appended to the end of the
specifier.
::
+
%pS versatile_init+0x0/0x110 [module_name]
%pSb versatile_init+0x0/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
%pSRb versatile_init+0x9/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst
index 83ec4a556c19..21dc03bc10a4 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -181,9 +181,16 @@ By default, KASAN prints a bug report only for the first invalid memory access.
With ``kasan_multi_shot``, KASAN prints a report on every invalid access. This
effectively disables ``panic_on_warn`` for KASAN reports.
+Alternatively, independent of ``panic_on_warn`` the ``kasan.fault=`` boot
+parameter can be used to control panic and reporting behaviour:
+
+- ``kasan.fault=report`` or ``=panic`` controls whether to only print a KASAN
+ report or also panic the kernel (default: ``report``). The panic happens even
+ if ``kasan_multi_shot`` is enabled.
+
Hardware tag-based KASAN mode (see the section about various modes below) is
intended for use in production as a security mitigation. Therefore, it supports
-boot parameters that allow disabling KASAN or controlling its features.
+additional boot parameters that allow disabling KASAN or controlling features:
- ``kasan=off`` or ``=on`` controls whether KASAN is enabled (default: ``on``).
@@ -199,10 +206,6 @@ boot parameters that allow disabling KASAN or controlling its features.
- ``kasan.stacktrace=off`` or ``=on`` disables or enables alloc and free stack
traces collection (default: ``on``).
-- ``kasan.fault=report`` or ``=panic`` controls whether to only print a KASAN
- report or also panic the kernel (default: ``report``). The panic happens even
- if ``kasan_multi_shot`` is enabled.
-
Implementation details
----------------------
diff --git a/Documentation/dev-tools/kcsan.rst b/Documentation/dev-tools/kcsan.rst
index 6a600cf8430b..7db43c7c09b8 100644
--- a/Documentation/dev-tools/kcsan.rst
+++ b/Documentation/dev-tools/kcsan.rst
@@ -127,6 +127,18 @@ Kconfig options:
causes KCSAN to not report data races due to conflicts where the only plain
accesses are aligned writes up to word size.
+* ``CONFIG_KCSAN_PERMISSIVE``: Enable additional permissive rules to ignore
+ certain classes of common data races. Unlike the above, the rules are more
+ complex involving value-change patterns, access type, and address. This
+ option depends on ``CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY=y``. For details
+ please see the ``kernel/kcsan/permissive.h``. Testers and maintainers that
+ only focus on reports from specific subsystems and not the whole kernel are
+ recommended to disable this option.
+
+To use the strictest possible rules, select ``CONFIG_KCSAN_STRICT=y``, which
+configures KCSAN to follow the Linux-kernel memory consistency model (LKMM) as
+closely as possible.
+
DebugFS interface
~~~~~~~~~~~~~~~~~
diff --git a/Documentation/dev-tools/kunit/kunit-tool.rst b/Documentation/dev-tools/kunit/kunit-tool.rst
index c7ff9afe407a..ae52e0f489f9 100644
--- a/Documentation/dev-tools/kunit/kunit-tool.rst
+++ b/Documentation/dev-tools/kunit/kunit-tool.rst
@@ -114,9 +114,12 @@ results in TAP format, you can pass the ``--raw_output`` argument.
./tools/testing/kunit/kunit.py run --raw_output
-.. note::
- The raw output from test runs may contain other, non-KUnit kernel log
- lines.
+The raw output from test runs may contain other, non-KUnit kernel log
+lines. You can see just KUnit output with ``--raw_output=kunit``:
+
+.. code-block:: bash
+
+ ./tools/testing/kunit/kunit.py run --raw_output=kunit
If you have KUnit results in their raw TAP format, you can parse them and print
the human-readable summary with the ``parse`` command for kunit_tool. This
diff --git a/Documentation/dev-tools/kunit/running_tips.rst b/Documentation/dev-tools/kunit/running_tips.rst
index d1626d548fa5..30d2147eb5b5 100644
--- a/Documentation/dev-tools/kunit/running_tips.rst
+++ b/Documentation/dev-tools/kunit/running_tips.rst
@@ -80,6 +80,16 @@ file ``.kunitconfig``, you can just pass in the dir, e.g.
automagically, but tests could theoretically depend on incompatible
options, so handling that would be tricky.
+Setting kernel commandline parameters
+-------------------------------------
+
+You can use ``--kernel_args`` to pass arbitrary kernel arguments, e.g.
+
+.. code-block:: bash
+
+ $ ./tools/testing/kunit/kunit.py run --kernel_args=param=42 --kernel_args=param2=false
+
+
Generating code coverage reports under UML
------------------------------------------
diff --git a/Documentation/devicetree/bindings/Makefile b/Documentation/devicetree/bindings/Makefile
index 5ccfed90cc70..a072e95de626 100644
--- a/Documentation/devicetree/bindings/Makefile
+++ b/Documentation/devicetree/bindings/Makefile
@@ -28,7 +28,7 @@ find_cmd = find $(srctree)/$(src) \( -name '*.yaml' ! \
quiet_cmd_yamllint = LINT $(src)
cmd_yamllint = ($(find_cmd) | \
- xargs $(DT_SCHEMA_LINT) -f parsable -c $(srctree)/$(src)/.yamllint) || true
+ xargs $(DT_SCHEMA_LINT) -f parsable -c $(srctree)/$(src)/.yamllint >&2) || true
quiet_cmd_chk_bindings = CHKDT $@
cmd_chk_bindings = ($(find_cmd) | \
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.yaml b/Documentation/devicetree/bindings/arm/atmel-at91.yaml
index 6fc5a22ad962..fba071b9af1d 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.yaml
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.yaml
@@ -146,6 +146,11 @@ properties:
- const: atmel,sama5
- items:
+ - const: microchip,sama7g5ek # SAMA7G5 Evaluation Kit
+ - const: microchip,sama7g5
+ - const: microchip,sama7
+
+ - items:
- enum:
- atmel,sams70j19
- atmel,sams70j20
diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
index 807264a78edc..16eef600d599 100644
--- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt
@@ -45,7 +45,8 @@ RAMC SDRAM/DDR Controller required properties:
"atmel,at91sam9260-sdramc",
"atmel,at91sam9g45-ddramc",
"atmel,sama5d3-ddramc",
- "microchip,sam9x60-ddramc"
+ "microchip,sam9x60-ddramc",
+ "microchip,sama7g5-uddrc"
- reg: Should contain registers location and length
Examples:
@@ -55,6 +56,17 @@ Examples:
reg = <0xffffe800 0x200>;
};
+RAMC PHY Controller required properties:
+- compatible: Should be "microchip,sama7g5-ddr3phy", "syscon"
+- reg: Should contain registers location and length
+
+Example:
+
+ ddr3phy: ddr3phy@e3804000 {
+ compatible = "microchip,sama7g5-ddr3phy", "syscon";
+ reg = <0xe3804000 0x1000>;
+};
+
SHDWC Shutdown Controller
required properties:
diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 1c827c1954dc..60f4862ba15e 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -221,9 +221,13 @@ properties:
- prt,prti6q # Protonic PRTI6Q board
- prt,prtwd2 # Protonic WD2 board
- rex,imx6q-rex-pro # Rex Pro i.MX6 Quad Board
+ - skov,imx6q-skov-revc-lt2 # SKOV IMX6 CPU QuadCore lt2
+ - skov,imx6q-skov-revc-lt6 # SKOV IMX6 CPU QuadCore lt6
+ - skov,imx6q-skov-reve-mi1010ait-1cp1 # SKOV IMX6 CPU QuadCore mi1010ait-1cp1
- solidrun,cubox-i/q # SolidRun Cubox-i Dual/Quad
- solidrun,hummingboard/q
- solidrun,hummingboard2/q
+ - solidrun,solidsense/q # SolidRun SolidSense Dual/Quad
- tbs,imx6q-tbs2910 # TBS2910 Matrix ARM mini PC
- technexion,imx6q-pico-dwarf # TechNexion i.MX6Q Pico-Dwarf
- technexion,imx6q-pico-hobbit # TechNexion i.MX6Q Pico-Hobbit
@@ -377,9 +381,12 @@ properties:
- prt,prtvt7 # Protonic VT7 board
- rex,imx6dl-rex-basic # Rex Basic i.MX6 Dual Lite Board
- riot,imx6s-riotboard # RIoTboard i.MX6S
+ - skov,imx6dl-skov-revc-lt2 # SKOV IMX6 CPU SoloCore lt2
+ - skov,imx6dl-skov-revc-lt6 # SKOV IMX6 CPU SoloCore lt6
- solidrun,cubox-i/dl # SolidRun Cubox-i Solo/DualLite
- solidrun,hummingboard/dl
- solidrun,hummingboard2/dl # SolidRun HummingBoard2 Solo/DualLite
+ - solidrun,solidsense/dl # SolidRun SolidSense Solo/DualLite
- technexion,imx6dl-pico-dwarf # TechNexion i.MX6DL Pico-Dwarf
- technexion,imx6dl-pico-hobbit # TechNexion i.MX6DL Pico-Hobbit
- technexion,imx6dl-pico-nymph # TechNexion i.MX6DL Pico-Nymph
@@ -418,6 +425,12 @@ properties:
- const: dfi,fs700e-m60
- const: fsl,imx6dl
+ - description: i.MX6DL DHCOM PicoITX Board
+ items:
+ - const: dh,imx6dl-dhcom-picoitx
+ - const: dh,imx6dl-dhcom-som
+ - const: fsl,imx6dl
+
- description: i.MX6DL Gateworks Ventana Boards
items:
- enum:
@@ -469,6 +482,12 @@ properties:
- const: toradex,colibri_imx6dl # Colibri iMX6 Module
- const: fsl,imx6dl
+ - description: i.MX6S DHCOM DRC02 Board
+ items:
+ - const: dh,imx6s-dhcom-drc02
+ - const: dh,imx6s-dhcom-som
+ - const: fsl,imx6dl
+
- description: i.MX6SL based Boards
items:
- enum:
@@ -698,6 +717,7 @@ properties:
- gw,imx8mm-gw72xx-0x # i.MX8MM Gateworks Development Kit
- gw,imx8mm-gw73xx-0x # i.MX8MM Gateworks Development Kit
- gw,imx8mm-gw7901 # i.MX8MM Gateworks Board
+ - gw,imx8mm-gw7902 # i.MX8MM Gateworks Board
- kontron,imx8mm-n801x-som # i.MX8MM Kontron SL (N801X) SOM
- variscite,var-som-mx8mm # i.MX8MM Variscite VAR-SOM-MX8MM module
- const: fsl,imx8mm
@@ -728,6 +748,7 @@ properties:
- beacon,imx8mn-beacon-kit # i.MX8MN Beacon Development Kit
- fsl,imx8mn-ddr4-evk # i.MX8MN DDR4 EVK Board
- fsl,imx8mn-evk # i.MX8MN LPDDR4 EVK Board
+ - gw,imx8mn-gw7902 # i.MX8MM Gateworks Board
- const: fsl,imx8mn
- description: Variscite VAR-SOM-MX8MN based boards
@@ -752,10 +773,12 @@ properties:
items:
- enum:
- boundary,imx8mq-nitrogen8m # i.MX8MQ NITROGEN Board
+ - boundary,imx8mq-nitrogen8m-som # i.MX8MQ NITROGEN SoM
- einfochips,imx8mq-thor96 # i.MX8MQ Thor96 Board
- fsl,imx8mq-evk # i.MX8MQ EVK Board
- google,imx8mq-phanbell # Google Coral Edge TPU
- kontron,pitx-imx8m # Kontron pITX-imx8m Board
+ - mntre,reform2 # MNT Reform2 Laptop
- purism,librem5-devkit # Purism Librem5 devkit
- solidrun,hummingboard-pulse # SolidRun Hummingboard Pulse
- technexion,pico-pi-imx8m # TechNexion PICO-PI-8M evk
@@ -973,6 +996,12 @@ properties:
- fsl,s32v234-evb # S32V234-EVB2 Customer Evaluation Board
- const: fsl,s32v234
+ - description: Traverse LS1088A based Boards
+ items:
+ - enum:
+ - traverse,ten64 # Ten64 Networking Appliance / Board
+ - const: fsl,ls1088a
+
additionalProperties: true
...
diff --git a/Documentation/devicetree/bindings/arm/gemini.txt b/Documentation/devicetree/bindings/arm/gemini.txt
deleted file mode 100644
index 55bf7ce96c44..000000000000
--- a/Documentation/devicetree/bindings/arm/gemini.txt
+++ /dev/null
@@ -1,108 +0,0 @@
-Cortina systems Gemini platforms
-
-The Gemini SoC is the project name for an ARMv4 FA525-based SoC originally
-produced by Storlink Semiconductor around 2005. The company was renamed
-later renamed Storm Semiconductor. The chip product name is Storlink SL3516.
-It was derived from earlier products from Storm named SL3316 (Centroid) and
-SL3512 (Bulverde).
-
-Storm Semiconductor was acquired by Cortina Systems in 2008 and the SoC was
-produced and used for NAS and similar usecases. In 2014 Cortina Systems was
-in turn acquired by Inphi, who seem to have discontinued this product family.
-
-Many of the IP blocks used in the SoC comes from Faraday Technology.
-
-Required properties (in root node):
- compatible = "cortina,gemini";
-
-Required nodes:
-
-- soc: the SoC should be represented by a simple bus encompassing all the
- onchip devices, this is referred to as the soc bus node.
-
-- syscon: the soc bus node must have a system controller node pointing to the
- global control registers, with the compatible string
- "cortina,gemini-syscon", "syscon";
-
- Required properties on the syscon:
- - reg: syscon register location and size.
- - #clock-cells: should be set to <1> - the system controller is also a
- clock provider.
- - #reset-cells: should be set to <1> - the system controller is also a
- reset line provider.
-
- The clock sources have shorthand defines in the include file:
- <dt-bindings/clock/cortina,gemini-clock.h>
-
- The reset lines have shorthand defines in the include file:
- <dt-bindings/reset/cortina,gemini-reset.h>
-
-- timer: the soc bus node must have a timer node pointing to the SoC timer
- block, with the compatible string "cortina,gemini-timer"
- See: clocksource/cortina,gemini-timer.txt
-
-- interrupt-controller: the sob bus node must have an interrupt controller
- node pointing to the SoC interrupt controller block, with the compatible
- string "cortina,gemini-interrupt-controller"
- See interrupt-controller/cortina,gemini-interrupt-controller.txt
-
-Example:
-
-/ {
- model = "Foo Gemini Machine";
- compatible = "cortina,gemini";
- #address-cells = <1>;
- #size-cells = <1>;
-
- memory {
- device_type = "memory";
- reg = <0x00000000 0x8000000>;
- };
-
- soc {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
- compatible = "simple-bus";
- interrupt-parent = <&intcon>;
-
- syscon: syscon@40000000 {
- compatible = "cortina,gemini-syscon", "syscon";
- reg = <0x40000000 0x1000>;
- #clock-cells = <1>;
- #reset-cells = <1>;
- };
-
- uart0: serial@42000000 {
- compatible = "ns16550a";
- reg = <0x42000000 0x100>;
- resets = <&syscon GEMINI_RESET_UART>;
- clocks = <&syscon GEMINI_CLK_UART>;
- interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
- reg-shift = <2>;
- };
-
- timer@43000000 {
- compatible = "cortina,gemini-timer";
- reg = <0x43000000 0x1000>;
- interrupt-parent = <&intcon>;
- interrupts = <14 IRQ_TYPE_EDGE_FALLING>, /* Timer 1 */
- <15 IRQ_TYPE_EDGE_FALLING>, /* Timer 2 */
- <16 IRQ_TYPE_EDGE_FALLING>; /* Timer 3 */
- resets = <&syscon GEMINI_RESET_TIMER>;
- /* APB clock or RTC clock */
- clocks = <&syscon GEMINI_CLK_APB>,
- <&syscon GEMINI_CLK_RTC>;
- clock-names = "PCLK", "EXTCLK";
- syscon = <&syscon>;
- };
-
- intcon: interrupt-controller@48000000 {
- compatible = "cortina,gemini-interrupt-controller";
- reg = <0x48000000 0x1000>;
- resets = <&syscon GEMINI_RESET_INTCON0>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
- };
-};
diff --git a/Documentation/devicetree/bindings/arm/gemini.yaml b/Documentation/devicetree/bindings/arm/gemini.yaml
new file mode 100644
index 000000000000..f6a0b675830f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gemini.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/gemini.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cortina systems Gemini platforms
+
+description: |
+ The Gemini SoC is the project name for an ARMv4 FA525-based SoC originally
+ produced by Storlink Semiconductor around 2005. The company was renamed
+ later renamed Storm Semiconductor. The chip product name is Storlink SL3516.
+ It was derived from earlier products from Storm named SL3316 (Centroid) and
+ SL3512 (Bulverde).
+
+ Storm Semiconductor was acquired by Cortina Systems in 2008 and the SoC was
+ produced and used for NAS and similar usecases. In 2014 Cortina Systems was
+ in turn acquired by Inphi, who seem to have discontinued this product family.
+
+ Many of the IP blocks used in the SoC comes from Faraday Technology.
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+properties:
+ $nodename:
+ const: '/'
+ compatible:
+ oneOf:
+
+ - description: Storlink Semiconductor Gemini324 EV-Board also known
+ as Storm Semiconductor SL93512R_BRD
+ items:
+ - const: storlink,gemini324
+ - const: storm,sl93512r
+ - const: cortina,gemini
+
+ - description: D-Link DIR-685 Xtreme N Storage Router
+ items:
+ - const: dlink,dir-685
+ - const: cortina,gemini
+
+ - description: D-Link DNS-313 1-Bay Network Storage Enclosure
+ items:
+ - const: dlink,dns-313
+ - const: cortina,gemini
+
+ - description: Edimax NS-2502
+ items:
+ - const: edimax,ns-2502
+ - const: cortina,gemini
+
+ - description: ITian Square One SQ201
+ items:
+ - const: itian,sq201
+ - const: cortina,gemini
+
+ - description: Raidsonic NAS IB-4220-B
+ items:
+ - const: raidsonic,ib-4220-b
+ - const: cortina,gemini
+
+ - description: SSI 1328
+ items:
+ - const: ssi,1328
+ - const: cortina,gemini
+
+ - description: Teltonika RUT1xx Mobile Router
+ items:
+ - const: teltonika,rut1xx
+ - const: cortina,gemini
+
+ - description: Wiligear Wiliboard WBD-111
+ items:
+ - const: wiligear,wiliboard-wbd111
+ - const: cortina,gemini
+
+ - description: Wiligear Wiliboard WBD-222
+ items:
+ - const: wiligear,wiliboard-wbd222
+ - const: cortina,gemini
+
+ - description: Wiligear Wiliboard WBD-111 - old incorrect binding
+ items:
+ - const: wiliboard,wbd111
+ - const: cortina,gemini
+ deprecated: true
+
+ - description: Wiligear Wiliboard WBD-222 - old incorrect binding
+ items:
+ - const: wiliboard,wbd222
+ - const: cortina,gemini
+ deprecated: true
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
index b32d374193c7..699776be1dd3 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
@@ -13,6 +13,7 @@ Required Properties:
- "mediatek,mt7623-audsys", "mediatek,mt2701-audsys", "syscon"
- "mediatek,mt8167-audiosys", "syscon"
- "mediatek,mt8183-audiosys", "syscon"
+ - "mediatek,mt8192-audsys", "syscon"
- "mediatek,mt8516-audsys", "syscon"
- #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
deleted file mode 100644
index 78c50733985c..000000000000
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-Mediatek mmsys controller
-============================
-
-The Mediatek mmsys system controller provides clock control, routing control,
-and miscellaneous control in mmsys partition.
-
-Required Properties:
-
-- compatible: Should be one of:
- - "mediatek,mt2701-mmsys", "syscon"
- - "mediatek,mt2712-mmsys", "syscon"
- - "mediatek,mt6765-mmsys", "syscon"
- - "mediatek,mt6779-mmsys", "syscon"
- - "mediatek,mt6797-mmsys", "syscon"
- - "mediatek,mt7623-mmsys", "mediatek,mt2701-mmsys", "syscon"
- - "mediatek,mt8167-mmsys", "syscon"
- - "mediatek,mt8173-mmsys", "syscon"
- - "mediatek,mt8183-mmsys", "syscon"
-- #clock-cells: Must be 1
-
-For the clock control, the mmsys controller uses the common clk binding from
-Documentation/devicetree/bindings/clock/clock-bindings.txt
-The available clocks are defined in dt-bindings/clock/mt*-clk.h.
-
-Example:
-
-mmsys: syscon@14000000 {
- compatible = "mediatek,mt8173-mmsys", "syscon";
- reg = <0 0x14000000 0 0x1000>;
- #clock-cells = <1>;
-};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
new file mode 100644
index 000000000000..f9ffa5b703a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/arm/mediatek/mediatek,mmsys.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: MediaTek mmsys controller
+
+maintainers:
+ - Matthias Brugger <matthias.bgg@gmail.com>
+
+description:
+ The MediaTek mmsys system controller provides clock control, routing control,
+ and miscellaneous control in mmsys partition.
+
+properties:
+ $nodename:
+ pattern: "^syscon@[0-9a-f]+$"
+
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - mediatek,mt2701-mmsys
+ - mediatek,mt2712-mmsys
+ - mediatek,mt6765-mmsys
+ - mediatek,mt6779-mmsys
+ - mediatek,mt6797-mmsys
+ - mediatek,mt8167-mmsys
+ - mediatek,mt8173-mmsys
+ - mediatek,mt8183-mmsys
+ - mediatek,mt8192-mmsys
+ - mediatek,mt8365-mmsys
+ - const: syscon
+ - items:
+ - const: mediatek,mt7623-mmsys
+ - const: mediatek,mt2701-mmsys
+ - const: syscon
+
+ reg:
+ maxItems: 1
+
+ "#clock-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ mmsys: syscon@14000000 {
+ compatible = "mediatek,mt8173-mmsys", "syscon";
+ reg = <0x14000000 0x1000>;
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8192-clock.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8192-clock.yaml
new file mode 100644
index 000000000000..c8c67c033f8c
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8192-clock.yaml
@@ -0,0 +1,199 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/arm/mediatek/mediatek,mt8192-clock.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: MediaTek Functional Clock Controller for MT8192
+
+maintainers:
+ - Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+description:
+ The Mediatek functional clock controller provides various clocks on MT8192.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - mediatek,mt8192-scp_adsp
+ - mediatek,mt8192-imp_iic_wrap_c
+ - mediatek,mt8192-imp_iic_wrap_e
+ - mediatek,mt8192-imp_iic_wrap_s
+ - mediatek,mt8192-imp_iic_wrap_ws
+ - mediatek,mt8192-imp_iic_wrap_w
+ - mediatek,mt8192-imp_iic_wrap_n
+ - mediatek,mt8192-msdc_top
+ - mediatek,mt8192-msdc
+ - mediatek,mt8192-mfgcfg
+ - mediatek,mt8192-imgsys
+ - mediatek,mt8192-imgsys2
+ - mediatek,mt8192-vdecsys_soc
+ - mediatek,mt8192-vdecsys
+ - mediatek,mt8192-vencsys
+ - mediatek,mt8192-camsys
+ - mediatek,mt8192-camsys_rawa
+ - mediatek,mt8192-camsys_rawb
+ - mediatek,mt8192-camsys_rawc
+ - mediatek,mt8192-ipesys
+ - mediatek,mt8192-mdpsys
+
+ reg:
+ maxItems: 1
+
+ '#clock-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ scp_adsp: clock-controller@10720000 {
+ compatible = "mediatek,mt8192-scp_adsp";
+ reg = <0x10720000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ imp_iic_wrap_c: clock-controller@11007000 {
+ compatible = "mediatek,mt8192-imp_iic_wrap_c";
+ reg = <0x11007000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ imp_iic_wrap_e: clock-controller@11cb1000 {
+ compatible = "mediatek,mt8192-imp_iic_wrap_e";
+ reg = <0x11cb1000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ imp_iic_wrap_s: clock-controller@11d03000 {
+ compatible = "mediatek,mt8192-imp_iic_wrap_s";
+ reg = <0x11d03000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ imp_iic_wrap_ws: clock-controller@11d23000 {
+ compatible = "mediatek,mt8192-imp_iic_wrap_ws";
+ reg = <0x11d23000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ imp_iic_wrap_w: clock-controller@11e01000 {
+ compatible = "mediatek,mt8192-imp_iic_wrap_w";
+ reg = <0x11e01000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ imp_iic_wrap_n: clock-controller@11f02000 {
+ compatible = "mediatek,mt8192-imp_iic_wrap_n";
+ reg = <0x11f02000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ msdc_top: clock-controller@11f10000 {
+ compatible = "mediatek,mt8192-msdc_top";
+ reg = <0x11f10000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ msdc: clock-controller@11f60000 {
+ compatible = "mediatek,mt8192-msdc";
+ reg = <0x11f60000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ mfgcfg: clock-controller@13fbf000 {
+ compatible = "mediatek,mt8192-mfgcfg";
+ reg = <0x13fbf000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ imgsys: clock-controller@15020000 {
+ compatible = "mediatek,mt8192-imgsys";
+ reg = <0x15020000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ imgsys2: clock-controller@15820000 {
+ compatible = "mediatek,mt8192-imgsys2";
+ reg = <0x15820000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ vdecsys_soc: clock-controller@1600f000 {
+ compatible = "mediatek,mt8192-vdecsys_soc";
+ reg = <0x1600f000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ vdecsys: clock-controller@1602f000 {
+ compatible = "mediatek,mt8192-vdecsys";
+ reg = <0x1602f000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ vencsys: clock-controller@17000000 {
+ compatible = "mediatek,mt8192-vencsys";
+ reg = <0x17000000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ camsys: clock-controller@1a000000 {
+ compatible = "mediatek,mt8192-camsys";
+ reg = <0x1a000000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ camsys_rawa: clock-controller@1a04f000 {
+ compatible = "mediatek,mt8192-camsys_rawa";
+ reg = <0x1a04f000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ camsys_rawb: clock-controller@1a06f000 {
+ compatible = "mediatek,mt8192-camsys_rawb";
+ reg = <0x1a06f000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ camsys_rawc: clock-controller@1a08f000 {
+ compatible = "mediatek,mt8192-camsys_rawc";
+ reg = <0x1a08f000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ ipesys: clock-controller@1b000000 {
+ compatible = "mediatek,mt8192-ipesys";
+ reg = <0x1b000000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ mdpsys: clock-controller@1f000000 {
+ compatible = "mediatek,mt8192-mdpsys";
+ reg = <0x1f000000 0x1000>;
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8192-sys-clock.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8192-sys-clock.yaml
new file mode 100644
index 000000000000..5705bcf1fe47
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8192-sys-clock.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/arm/mediatek/mediatek,mt8192-sys-clock.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: MediaTek System Clock Controller for MT8192
+
+maintainers:
+ - Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+description:
+ The Mediatek system clock controller provides various clocks and system configuration
+ like reset and bus protection on MT8192.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - mediatek,mt8192-topckgen
+ - mediatek,mt8192-infracfg
+ - mediatek,mt8192-pericfg
+ - mediatek,mt8192-apmixedsys
+ - const: syscon
+
+ reg:
+ maxItems: 1
+
+ '#clock-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ topckgen: syscon@10000000 {
+ compatible = "mediatek,mt8192-topckgen", "syscon";
+ reg = <0x10000000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ infracfg: syscon@10001000 {
+ compatible = "mediatek,mt8192-infracfg", "syscon";
+ reg = <0x10001000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ pericfg: syscon@10003000 {
+ compatible = "mediatek,mt8192-pericfg", "syscon";
+ reg = <0x10003000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ - |
+ apmixedsys: syscon@1000c000 {
+ compatible = "mediatek,mt8192-apmixedsys", "syscon";
+ reg = <0x1000c000 0x1000>;
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index 9720b00c41d2..880ddafc634e 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -31,6 +31,7 @@ description: |
ipq6018
ipq8074
mdm9615
+ msm8226
msm8916
msm8974
msm8992
@@ -116,6 +117,11 @@ properties:
- items:
- enum:
+ - samsung,s3ve3g
+ - const: qcom,msm8226
+
+ - items:
+ - enum:
- qcom,msm8960-cdp
- const: qcom,msm8960
@@ -129,6 +135,8 @@ properties:
- const: qcom,msm8974
- items:
+ - enum:
+ - alcatel,idol347
- const: qcom,msm8916-mtp/1
- const: qcom,msm8916-mtp
- const: qcom,msm8916
@@ -181,6 +189,8 @@ properties:
- items:
- enum:
- qcom,sc7280-idp
+ - qcom,sc7280-idp2
+ - google,piglin
- google,senor
- const: qcom,sc7280
diff --git a/Documentation/devicetree/bindings/arm/renesas.yaml b/Documentation/devicetree/bindings/arm/renesas.yaml
index a0cce4e25039..8a11918866b8 100644
--- a/Documentation/devicetree/bindings/arm/renesas.yaml
+++ b/Documentation/devicetree/bindings/arm/renesas.yaml
@@ -238,17 +238,29 @@ properties:
- const: renesas,r8a77961
- description: Kingfisher (SBEV-RCAR-KF-M03)
- items:
- - const: shimafuji,kingfisher
- - enum:
- - renesas,h3ulcb
- - renesas,m3ulcb
- - renesas,m3nulcb
- - enum:
- - renesas,r8a7795
- - renesas,r8a7796
- - renesas,r8a77961
- - renesas,r8a77965
+ oneOf:
+ - items:
+ - const: shimafuji,kingfisher
+ - enum:
+ - renesas,h3ulcb
+ - renesas,m3ulcb
+ - renesas,m3nulcb
+ - enum:
+ - renesas,r8a7795
+ - renesas,r8a7796
+ - renesas,r8a77961
+ - renesas,r8a77965
+ - items:
+ - const: shimafuji,kingfisher
+ - enum:
+ - renesas,h3ulcb
+ - renesas,m3ulcb
+ - enum:
+ - renesas,r8a779m1
+ - renesas,r8a779m3
+ - enum:
+ - renesas,r8a7795
+ - renesas,r8a77961
- description: R-Car M3-N (R8A77965)
items:
@@ -296,6 +308,22 @@ properties:
- const: renesas,falcon-cpu
- const: renesas,r8a779a0
+ - description: R-Car H3e-2G (R8A779M1)
+ items:
+ - enum:
+ - renesas,h3ulcb # H3ULCB (R-Car Starter Kit Premier)
+ - renesas,salvator-xs # Salvator-XS (Salvator-X 2nd version)
+ - const: renesas,r8a779m1
+ - const: renesas,r8a7795
+
+ - description: R-Car M3e-2G (R8A779M3)
+ items:
+ - enum:
+ - renesas,m3ulcb # M3ULCB (R-Car Starter Kit Pro)
+ - renesas,salvator-xs # Salvator-XS (Salvator-X 2nd version)
+ - const: renesas,r8a779m3
+ - const: renesas,r8a77961
+
- description: RZ/N1D (R9A06G032)
items:
- enum:
diff --git a/Documentation/devicetree/bindings/arm/tegra.yaml b/Documentation/devicetree/bindings/arm/tegra.yaml
index b9f75e20fef5..b962fa6d649c 100644
--- a/Documentation/devicetree/bindings/arm/tegra.yaml
+++ b/Documentation/devicetree/bindings/arm/tegra.yaml
@@ -111,6 +111,7 @@ properties:
- items:
- enum:
- nvidia,p2771-0000
+ - nvidia,p3509-0000+p3636-0001
- const: nvidia,tegra186
- items:
- enum:
diff --git a/Documentation/devicetree/bindings/ata/exynos-sata.txt b/Documentation/devicetree/bindings/ata/exynos-sata.txt
deleted file mode 100644
index cb48448247ea..000000000000
--- a/Documentation/devicetree/bindings/ata/exynos-sata.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-* Samsung AHCI SATA Controller
-
-SATA nodes are defined to describe on-chip Serial ATA controllers.
-Each SATA controller should have its own node.
-
-Required properties:
-- compatible : compatible list, contains "samsung,exynos5-sata"
-- interrupts : <interrupt mapping for SATA IRQ>
-- reg : <registers mapping>
-- samsung,sata-freq : <frequency in MHz>
-- phys : Must contain exactly one entry as specified
- in phy-bindings.txt
-- phy-names : Must be "sata-phy"
-
-Optional properties:
-- clocks : Must contain an entry for each entry in clock-names.
-- clock-names : Shall be "sata" for the external SATA bus clock,
- and "sclk_sata" for the internal controller clock.
-
-Example:
- sata@122f0000 {
- compatible = "snps,dwc-ahci";
- samsung,sata-freq = <66>;
- reg = <0x122f0000 0x1ff>;
- interrupts = <0 115 0>;
- clocks = <&clock 277>, <&clock 143>;
- clock-names = "sata", "sclk_sata";
- phys = <&sata_phy>;
- phy-names = "sata-phy";
- };
diff --git a/Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml b/Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml
new file mode 100644
index 000000000000..52e18600ecff
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ata/intel,ixp4xx-compact-flash.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Intel IXP4xx CompactFlash Card Controller
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+ The IXP4xx network processors have a CompactFlash interface that presents
+ a CompactFlash card to the system as a true IDE (parallel ATA) device. The
+ device is always connected to the expansion bus of the IXP4xx SoCs using one
+ or two chip select areas and address translating logic on the board. The
+ node must be placed inside a chip select node on the IXP4xx expansion bus.
+
+properties:
+ compatible:
+ const: intel,ixp4xx-compact-flash
+
+ reg:
+ items:
+ - description: Command interface registers
+ - description: Control interface registers
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+allOf:
+ - $ref: pata-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ bus@c4000000 {
+ compatible = "intel,ixp43x-expansion-bus-controller", "syscon";
+ reg = <0xc4000000 0x1000>;
+ native-endian;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0x0 0x50000000 0x01000000>, <1 0x0 0x51000000 0x01000000>;
+ dma-ranges = <0 0x0 0x50000000 0x01000000>, <1 0x0 0x51000000 0x01000000>;
+ ide@1,0 {
+ compatible = "intel,ixp4xx-compact-flash";
+ reg = <1 0x00000000 0x1000>, <1 0x00040000 0x1000>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <12 IRQ_TYPE_EDGE_RISING>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml b/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml
new file mode 100644
index 000000000000..5d02bd032a85
--- /dev/null
+++ b/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/auxdisplay/arm,versatile-lcd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ARM Versatile Character LCD
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+ - Rob Herring <robh@kernel.org>
+
+description:
+ This binding defines the character LCD interface found on ARM Versatile AB
+ and PB reference platforms.
+
+properties:
+ compatible:
+ const: arm,versatile-lcd
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ lcd@10008000 {
+ compatible = "arm,versatile-lcd";
+ reg = <0x10008000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt b/Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt
deleted file mode 100644
index e28e2aac47f1..000000000000
--- a/Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-ARM Versatile Character LCD
------------------------------------------------------
-This binding defines the character LCD interface found on ARM Versatile AB
-and PB reference platforms.
-
-Required properties:
-- compatible : "arm,versatile-clcd"
-- reg : Location and size of character LCD registers
-
-Optional properties:
-- interrupts - single interrupt for character LCD. The character LCD can
- operate in polled mode without an interrupt.
-
-Example:
- lcd@10008000 {
- compatible = "arm,versatile-lcd";
- reg = <0x10008000 0x1000>;
- };
diff --git a/Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml b/Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml
new file mode 100644
index 000000000000..1899b23de7d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/auxdisplay/img,ascii-lcd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ASCII LCD displays on Imagination Technologies boards
+
+maintainers:
+ - Paul Burton <paulburton@kernel.org>
+
+properties:
+ compatible:
+ enum:
+ - img,boston-lcd
+ - mti,malta-lcd
+ - mti,sead3-lcd
+
+ reg:
+ maxItems: 1
+
+ offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Offset in bytes to the LCD registers within the system controller
+
+required:
+ - compatible
+
+oneOf:
+ - required:
+ - reg
+ - required:
+ - offset
+
+if:
+ properties:
+ compatible:
+ contains:
+ const: img,boston-lcd
+then:
+ required:
+ - reg
+else:
+ required:
+ - offset
+
+additionalProperties: false
+
+examples:
+ - |
+ lcd: lcd@17fff000 {
+ compatible = "img,boston-lcd";
+ reg = <0x17fff000 0x8>;
+ };
diff --git a/Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt b/Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt
deleted file mode 100644
index b69bb68992fd..000000000000
--- a/Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Binding for ASCII LCD displays on Imagination Technologies boards
-
-Required properties:
-- compatible : should be one of:
- "img,boston-lcd"
- "mti,malta-lcd"
- "mti,sead3-lcd"
-
-Required properties for "img,boston-lcd":
-- reg : memory region locating the device registers
-
-Required properties for "mti,malta-lcd" or "mti,sead3-lcd":
-- regmap: phandle of the system controller containing the LCD registers
-- offset: offset in bytes to the LCD registers within the system controller
-
-The layout of the registers & properties of the display are determined
-from the compatible string, making this binding somewhat trivial.
diff --git a/Documentation/devicetree/bindings/bus/intel,ixp4xx-expansion-bus-controller.yaml b/Documentation/devicetree/bindings/bus/intel,ixp4xx-expansion-bus-controller.yaml
new file mode 100644
index 000000000000..5fb4e7bfa4da
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/intel,ixp4xx-expansion-bus-controller.yaml
@@ -0,0 +1,168 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/bus/intel,ixp4xx-expansion-bus-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Intel IXP4xx Expansion Bus Controller
+
+description: |
+ The IXP4xx expansion bus controller handles access to devices on the
+ memory-mapped expansion bus on the Intel IXP4xx family of system on chips,
+ including IXP42x, IXP43x, IXP45x and IXP46x.
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+properties:
+ $nodename:
+ pattern: '^bus@[0-9a-f]+$'
+
+ compatible:
+ items:
+ - enum:
+ - intel,ixp42x-expansion-bus-controller
+ - intel,ixp43x-expansion-bus-controller
+ - intel,ixp45x-expansion-bus-controller
+ - intel,ixp46x-expansion-bus-controller
+ - const: syscon
+
+ reg:
+ description: Control registers for the expansion bus, these are not
+ inside the memory range handled by the expansion bus.
+ maxItems: 1
+
+ native-endian:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: The IXP4xx has a peculiar MMIO access scheme, as it changes
+ the access pattern for words (swizzling) on the bus depending on whether
+ the SoC is running in big-endian or little-endian mode. Thus the
+ registers must always be accessed using native endianness.
+
+ "#address-cells":
+ description: |
+ The first cell is the chip select number.
+ The second cell is the address offset within the bank.
+ const: 2
+
+ "#size-cells":
+ const: 1
+
+ ranges: true
+ dma-ranges: true
+
+patternProperties:
+ "^.*@[0-7],[0-9a-f]+$":
+ description: Devices attached to chip selects are represented as
+ subnodes.
+ type: object
+
+ properties:
+ intel,ixp4xx-eb-t1:
+ description: Address timing, extend address phase with n cycles.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 3
+
+ intel,ixp4xx-eb-t2:
+ description: Setup chip select timing, extend setup phase with n cycles.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 3
+
+ intel,ixp4xx-eb-t3:
+ description: Strobe timing, extend strobe phase with n cycles.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 15
+
+ intel,ixp4xx-eb-t4:
+ description: Hold timing, extend hold phase with n cycles.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 3
+
+ intel,ixp4xx-eb-t5:
+ description: Recovery timing, extend recovery phase with n cycles.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 15
+
+ intel,ixp4xx-eb-cycle-type:
+ description: The type of cycles to use on the expansion bus for this
+ chip select. 0 = Intel cycles, 1 = Motorola cycles, 2 = HPI cycles.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2]
+
+ intel,ixp4xx-eb-byte-access-on-halfword:
+ description: Allow byte read access on half word devices.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ intel,ixp4xx-eb-hpi-hrdy-pol-high:
+ description: Set HPI HRDY polarity to active high when using HPI.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ intel,ixp4xx-eb-mux-address-and-data:
+ description: Multiplex address and data on the data bus.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ intel,ixp4xx-eb-ahb-split-transfers:
+ description: Enable AHB split transfers.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ intel,ixp4xx-eb-write-enable:
+ description: Enable write cycles.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+ intel,ixp4xx-eb-byte-access:
+ description: Expansion bus uses only 8 bits. The default is to use
+ 16 bits.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
+required:
+ - compatible
+ - reg
+ - native-endian
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+ - dma-ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ bus@50000000 {
+ compatible = "intel,ixp42x-expansion-bus-controller", "syscon";
+ reg = <0xc4000000 0x28>;
+ native-endian;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0x0 0x50000000 0x01000000>,
+ <1 0x0 0x51000000 0x01000000>;
+ dma-ranges = <0 0x0 0x50000000 0x01000000>,
+ <1 0x0 0x51000000 0x01000000>;
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ reg = <0 0x00000000 0x1000000>;
+ intel,ixp4xx-eb-t3 = <3>;
+ intel,ixp4xx-eb-cycle-type = <0>;
+ intel,ixp4xx-eb-byte-access-on-halfword = <1>;
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <0>;
+ };
+ serial@1,0 {
+ compatible = "exar,xr16l2551", "ns8250";
+ reg = <1 0x00000000 0x10>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ clock-frequency = <1843200>;
+ intel,ixp4xx-eb-t3 = <3>;
+ intel,ixp4xx-eb-cycle-type = <1>;
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/chosen.txt b/Documentation/devicetree/bindings/chosen.txt
index 45e79172a646..1cc3aa10dcb1 100644
--- a/Documentation/devicetree/bindings/chosen.txt
+++ b/Documentation/devicetree/bindings/chosen.txt
@@ -79,9 +79,9 @@ a different secondary CPU release mechanism)
linux,usable-memory-range
-------------------------
-This property (arm64 only) holds a base address and size, describing a
-limited region in which memory may be considered available for use by
-the kernel. Memory outside of this range is not available for use.
+This property holds a base address and size, describing a limited region in
+which memory may be considered available for use by the kernel. Memory outside
+of this range is not available for use.
This property describes a limitation: memory within this range is only
valid when also described through another mechanism that the kernel
@@ -106,9 +106,9 @@ respectively, of the root node.
linux,elfcorehdr
----------------
-This property (currently used only on arm64) holds the memory range,
-the address and the size, of the elf core header which mainly describes
-the panicked kernel's memory layout as PT_LOAD segments of elf format.
+This property holds the memory range, the address and the size, of the elf
+core header which mainly describes the panicked kernel's memory layout as
+PT_LOAD segments of elf format.
e.g.
/ {
diff --git a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.yaml b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.yaml
index 1174c9aa9934..5ad147d265e6 100644
--- a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.yaml
+++ b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.yaml
@@ -61,7 +61,7 @@ properties:
maxItems: 1
'#clock-cells':
- const: 1
+ true
clock-output-names:
minItems: 1
@@ -74,6 +74,23 @@ allOf:
contains:
enum:
- brcm,cygnus-armpll
+ - brcm,nsp-armpll
+ then:
+ properties:
+ '#clock-cells':
+ const: 0
+ else:
+ properties:
+ '#clock-cells':
+ const: 1
+ required:
+ - clock-output-names
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - brcm,cygnus-armpll
- brcm,cygnus-genpll
- brcm,cygnus-lcpll0
- brcm,cygnus-mipipll
@@ -358,7 +375,6 @@ required:
- reg
- clocks
- '#clock-cells'
- - clock-output-names
additionalProperties: false
@@ -392,3 +408,10 @@ examples:
clocks = <&osc2>;
clock-output-names = "keypad", "adc/touch", "pwm";
};
+ - |
+ arm_clk@0 {
+ #clock-cells = <0>;
+ compatible = "brcm,nsp-armpll";
+ clocks = <&osc>;
+ reg = <0x0 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
deleted file mode 100644
index 6030afb10b5c..000000000000
--- a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
+++ /dev/null
@@ -1,103 +0,0 @@
-* Samsung Audio Subsystem Clock Controller
-
-The Samsung Audio Subsystem clock controller generates and supplies clocks
-to Audio Subsystem block available in the S5PV210 and Exynos SoCs. The clock
-binding described here is applicable to all SoCs in Exynos family.
-
-Required Properties:
-
-- compatible: should be one of the following:
- - "samsung,exynos4210-audss-clock" - controller compatible with all Exynos4 SoCs.
- - "samsung,exynos5250-audss-clock" - controller compatible with Exynos5250
- SoCs.
- - "samsung,exynos5410-audss-clock" - controller compatible with Exynos5410
- SoCs.
- - "samsung,exynos5420-audss-clock" - controller compatible with Exynos5420
- SoCs.
-- reg: physical base address and length of the controller's register set.
-
-- #clock-cells: should be 1.
-
-- clocks:
- - pll_ref: Fixed rate PLL reference clock, parent of mout_audss. "fin_pll"
- is used if not specified.
- - pll_in: Input PLL to the AudioSS block, parent of mout_audss. "fout_epll"
- is used if not specified.
- - cdclk: External i2s clock, parent of mout_i2s. "cdclk0" is used if not
- specified.
- - sclk_audio: Audio bus clock, parent of mout_i2s. "sclk_audio0" is used if
- not specified.
- - sclk_pcm_in: PCM clock, parent of sclk_pcm. "sclk_pcm0" is used if not
- specified.
-
-- clock-names: Aliases for the above clocks. They should be "pll_ref",
- "pll_in", "cdclk", "sclk_audio", and "sclk_pcm_in" respectively.
-
-Optional Properties:
-
- - power-domains: a phandle to respective power domain node as described by
- generic PM domain bindings (see power/power_domain.txt for more
- information).
-
-The following is the list of clocks generated by the controller. Each clock is
-assigned an identifier and client nodes use this identifier to specify the
-clock which they consume. Some of the clocks are available only on a particular
-Exynos4 SoC and this is specified where applicable.
-
-Provided clocks:
-
-Clock ID SoC (if specific)
------------------------------------------------
-
-mout_audss 0
-mout_i2s 1
-dout_srp 2
-dout_aud_bus 3
-dout_i2s 4
-srp_clk 5
-i2s_bus 6
-sclk_i2s 7
-pcm_bus 8
-sclk_pcm 9
-adma 10 Exynos5420
-
-Example 1: An example of a clock controller node using the default input
- clock names is listed below.
-
-clock_audss: audss-clock-controller@3810000 {
- compatible = "samsung,exynos5250-audss-clock";
- reg = <0x03810000 0x0C>;
- #clock-cells = <1>;
-};
-
-Example 2: An example of a clock controller node with the input clocks
- specified.
-
-clock_audss: audss-clock-controller@3810000 {
- compatible = "samsung,exynos5250-audss-clock";
- reg = <0x03810000 0x0C>;
- #clock-cells = <1>;
- clocks = <&clock 1>, <&clock 7>, <&clock 138>, <&clock 160>,
- <&ext_i2s_clk>;
- clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in", "cdclk";
-};
-
-Example 3: I2S controller node that consumes the clock generated by the clock
- controller. Refer to the standard clock bindings for information
- about 'clocks' and 'clock-names' property.
-
-i2s0: i2s@3830000 {
- compatible = "samsung,i2s-v5";
- reg = <0x03830000 0x100>;
- dmas = <&pdma0 10
- &pdma0 9
- &pdma0 8>;
- dma-names = "tx", "rx", "tx-sec";
- clocks = <&clock_audss EXYNOS_I2S_BUS>,
- <&clock_audss EXYNOS_I2S_BUS>,
- <&clock_audss EXYNOS_SCLK_I2S>,
- <&clock_audss EXYNOS_MOUT_AUDSS>,
- <&clock_audss EXYNOS_MOUT_I2S>;
- clock-names = "iis", "i2s_opclk0", "i2s_opclk1",
- "mout_audss", "mout_i2s";
-};
diff --git a/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt b/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt
deleted file mode 100644
index f6272dcd96f4..000000000000
--- a/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-* Samsung Audio Subsystem Clock Controller
-
-The Samsung Audio Subsystem clock controller generates and supplies clocks
-to Audio Subsystem block available in the S5PV210 and compatible SoCs.
-
-Required Properties:
-
-- compatible: should be "samsung,s5pv210-audss-clock".
-- reg: physical base address and length of the controller's register set.
-
-- #clock-cells: should be 1.
-
-- clocks:
- - hclk: AHB bus clock of the Audio Subsystem.
- - xxti: Optional fixed rate PLL reference clock, parent of mout_audss. If
- not specified (i.e. xusbxti is used for PLL reference), it is fixed to
- a clock named "xxti".
- - fout_epll: Input PLL to the AudioSS block, parent of mout_audss.
- - iiscdclk0: Optional external i2s clock, parent of mout_i2s. If not
- specified, it is fixed to a clock named "iiscdclk0".
- - sclk_audio0: Audio bus clock, parent of mout_i2s.
-
-- clock-names: Aliases for the above clocks. They should be "hclk",
- "xxti", "fout_epll", "iiscdclk0", and "sclk_audio0" respectively.
-
-All available clocks are defined as preprocessor macros in
-dt-bindings/clock/s5pv210-audss-clk.h header and can be used in device
-tree sources.
-
-Example: Clock controller node.
-
- clk_audss: clock-controller@c0900000 {
- compatible = "samsung,s5pv210-audss-clock";
- reg = <0xc0900000 0x1000>;
- #clock-cells = <1>;
- clock-names = "hclk", "xxti",
- "fout_epll", "sclk_audio0";
- clocks = <&clocks DOUT_HCLKP>, <&xxti>,
- <&clocks FOUT_EPLL>, <&clocks SCLK_AUDIO0>;
- };
-
-Example: I2S controller node that consumes the clock generated by the clock
- controller. Refer to the standard clock bindings for information
- about 'clocks' and 'clock-names' property.
-
- i2s0: i2s@3830000 {
- /* ... */
- clock-names = "iis", "i2s_opclk0",
- "i2s_opclk1";
- clocks = <&clk_audss CLK_I2S>, <&clk_audss CLK_I2S>,
- <&clk_audss CLK_DOUT_AUD_BUS>;
- /* ... */
- };
diff --git a/Documentation/devicetree/bindings/clock/exynos3250-clock.txt b/Documentation/devicetree/bindings/clock/exynos3250-clock.txt
deleted file mode 100644
index 7441ed519f02..000000000000
--- a/Documentation/devicetree/bindings/clock/exynos3250-clock.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-* Samsung Exynos3250 Clock Controller
-
-The Exynos3250 clock controller generates and supplies clock to various
-controllers within the Exynos3250 SoC.
-
-Required Properties:
-
-- compatible: should be one of the following.
- - "samsung,exynos3250-cmu" - controller compatible with Exynos3250 SoC.
- - "samsung,exynos3250-cmu-dmc" - controller compatible with
- Exynos3250 SoC for Dynamic Memory Controller domain.
- - "samsung,exynos3250-cmu-isp" - ISP block clock controller compatible
- with Exynos3250 SOC
-
-- reg: physical base address of the 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
-to specify the clock which they consume.
-
-All available clocks are defined as preprocessor macros in
-dt-bindings/clock/exynos3250.h header and can be used in device
-tree sources.
-
-Example 1: Examples of clock controller nodes are listed below.
-
- cmu: clock-controller@10030000 {
- compatible = "samsung,exynos3250-cmu";
- reg = <0x10030000 0x20000>;
- #clock-cells = <1>;
- };
-
- cmu_dmc: clock-controller@105c0000 {
- compatible = "samsung,exynos3250-cmu-dmc";
- reg = <0x105C0000 0x2000>;
- #clock-cells = <1>;
- };
-
- cmu_isp: clock-controller@10048000 {
- compatible = "samsung,exynos3250-cmu-isp";
- reg = <0x10048000 0x1000>;
- #clock-cells = <1>;
- };
-
-Example 2: UART controller node that consumes the clock generated by the clock
- controller. Refer to the standard clock bindings for information
- about 'clocks' and 'clock-names' property.
-
- serial@13800000 {
- compatible = "samsung,exynos4210-uart";
- reg = <0x13800000 0x100>;
- interrupts = <0 109 0>;
- clocks = <&cmu CLK_UART0>, <&cmu CLK_SCLK_UART0>;
- clock-names = "uart", "clk_uart_baud0";
- };
diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
deleted file mode 100644
index 17bb11365354..000000000000
--- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
+++ /dev/null
@@ -1,86 +0,0 @@
-* Samsung Exynos4 Clock Controller
-
-The Exynos4 clock controller generates and supplies clock to various controllers
-within the Exynos4 SoC. The clock binding described here is applicable to all
-SoC's in the Exynos4 family.
-
-Required Properties:
-
-- compatible: should be one of the following.
- - "samsung,exynos4210-clock" - controller compatible with Exynos4210 SoC.
- - "samsung,exynos4412-clock" - controller compatible with Exynos4412 SoC.
-
-- reg: physical base address of the 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
-to specify the clock which they consume.
-
-All available clocks are defined as preprocessor macros in
-dt-bindings/clock/exynos4.h header and can be used in device
-tree sources.
-
-Example 1: An example of a clock controller node is listed below.
-
- clock: clock-controller@10030000 {
- compatible = "samsung,exynos4210-clock";
- reg = <0x10030000 0x20000>;
- #clock-cells = <1>;
- };
-
-Example 2: UART controller node that consumes the clock generated by the clock
- controller. Refer to the standard clock bindings for information
- about 'clocks' and 'clock-names' property.
-
- serial@13820000 {
- compatible = "samsung,exynos4210-uart";
- reg = <0x13820000 0x100>;
- interrupts = <0 54 0>;
- clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
- clock-names = "uart", "clk_uart_baud0";
- };
-
-Exynos4412 SoC contains some additional clocks for FIMC-ISP (Camera ISP)
-subsystem. Registers for those clocks are located in the ISP power domain.
-Because those registers are also located in a different memory region than
-the main clock controller, a separate clock controller has to be defined for
-handling them.
-
-Required Properties:
-
-- compatible: should be "samsung,exynos4412-isp-clock".
-
-- reg: physical base address of the ISP clock controller and length of memory
- mapped region.
-
-- #clock-cells: should be 1.
-
-- clocks: list of the clock controller input clock identifiers,
- from common clock bindings, should point to CLK_ACLK200 and
- CLK_ACLK400_MCUISP clocks from the main clock controller.
-
-- clock-names: list of the clock controller input clock names,
- as described in clock-bindings.txt, should be "aclk200" and
- "aclk400_mcuisp".
-
-- power-domains: a phandle to ISP power domain node as described by
- generic PM domain bindings.
-
-Example 3: The clock controllers bindings for Exynos4412 SoCs.
-
- clock: clock-controller@10030000 {
- compatible = "samsung,exynos4412-clock";
- reg = <0x10030000 0x18000>;
- #clock-cells = <1>;
- };
-
- isp_clock: clock-controller@10048000 {
- compatible = "samsung,exynos4412-isp-clock";
- reg = <0x10048000 0x1000>;
- #clock-cells = <1>;
- power-domains = <&pd_isp>;
- clocks = <&clock CLK_ACLK200>, <&clock CLK_ACLK400_MCUISP>;
- clock-names = "aclk200", "aclk400_mcuisp";
- };
diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
deleted file mode 100644
index aff266a12eeb..000000000000
--- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-* Samsung Exynos5250 Clock Controller
-
-The Exynos5250 clock controller generates and supplies clock to various
-controllers within the Exynos5250 SoC.
-
-Required Properties:
-
-- compatible: should be one of the following.
- - "samsung,exynos5250-clock" - controller compatible with Exynos5250 SoC.
-
-- reg: physical base address of the 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
-to specify the clock which they consume.
-
-All available clocks are defined as preprocessor macros in
-dt-bindings/clock/exynos5250.h header and can be used in device
-tree sources.
-
-Example 1: An example of a clock controller node is listed below.
-
- clock: clock-controller@10010000 {
- compatible = "samsung,exynos5250-clock";
- reg = <0x10010000 0x30000>;
- #clock-cells = <1>;
- };
-
-Example 2: UART controller node that consumes the clock generated by the clock
- controller. Refer to the standard clock bindings for information
- about 'clocks' and 'clock-names' property.
-
- serial@13820000 {
- compatible = "samsung,exynos4210-uart";
- reg = <0x13820000 0x100>;
- interrupts = <0 54 0>;
- clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
- clock-names = "uart", "clk_uart_baud0";
- };
diff --git a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt
deleted file mode 100644
index 717a7b1531c7..000000000000
--- a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-* Samsung Exynos5420 Clock Controller
-
-The Exynos5420 clock controller generates and supplies clock to various
-controllers within the Exynos5420 SoC and for the Exynos5800 SoC.
-
-Required Properties:
-
-- compatible: should be one of the following.
- - "samsung,exynos5420-clock" - controller compatible with Exynos5420 SoC.
- - "samsung,exynos5800-clock" - controller compatible with Exynos5800 SoC.
-
-- reg: physical base address of the 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
-to specify the clock which they consume.
-
-All available clocks are defined as preprocessor macros in
-dt-bindings/clock/exynos5420.h header and can be used in device
-tree sources.
-
-Example 1: An example of a clock controller node is listed below.
-
- clock: clock-controller@10010000 {
- compatible = "samsung,exynos5420-clock";
- reg = <0x10010000 0x30000>;
- #clock-cells = <1>;
- };
-
-Example 2: UART controller node that consumes the clock generated by the clock
- controller. Refer to the standard clock bindings for information
- about 'clocks' and 'clock-names' property.
-
- serial@13820000 {
- compatible = "samsung,exynos4210-uart";
- reg = <0x13820000 0x100>;
- interrupts = <0 54 0>;
- clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
- clock-names = "uart", "clk_uart_baud0";
- };
diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml
index 26ed040bc717..ffd6ae0eed64 100644
--- a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml
+++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml
@@ -30,6 +30,20 @@ description: |
3 -- OUT3
4 -- OUT4
+ The idt,shutdown and idt,output-enable-active properties control the
+ SH (en_global_shutdown) and SP bits of the Primary Source and Shutdown
+ Register, respectively. Their behavior is summarized by the following
+ table:
+
+ SH SP Output when the SD/OE pin is Low/High
+ == == =====================================
+ 0 0 Active/Inactive
+ 0 1 Inactive/Active
+ 1 0 Active/Shutdown
+ 1 1 Inactive/Shutdown
+
+ The case where SH and SP are both 1 is likely not very interesting.
+
maintainers:
- Luca Ceresoli <luca@lucaceresoli.net>
@@ -64,6 +78,26 @@ properties:
maximum: 22760
description: Optional load capacitor for XTAL1 and XTAL2
+ idt,shutdown:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ description: |
+ If 1, this enables the shutdown functionality: the chip will be
+ shut down if the SD/OE pin is driven high. If 0, this disables the
+ shutdown functionality: the chip will never be shut down based on
+ the value of the SD/OE pin. This property corresponds to the SH
+ bit of the Primary Source and Shutdown Register.
+
+ idt,output-enable-active:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ description: |
+ If 1, this enables output when the SD/OE pin is high, and disables
+ output when the SD/OE pin is low. If 0, this disables output when
+ the SD/OE pin is high, and enables output when the SD/OE pin is
+ low. This corresponds to the SP bit of the Primary Source and
+ Shutdown Register.
+
patternProperties:
"^OUT[1-4]$":
type: object
@@ -90,6 +124,8 @@ required:
- compatible
- reg
- '#clock-cells'
+ - idt,shutdown
+ - idt,output-enable-active
allOf:
- if:
@@ -139,6 +175,10 @@ examples:
clocks = <&ref25m>;
clock-names = "xin";
+ /* Set the SD/OE pin's settings */
+ idt,shutdown = <0>;
+ idt,output-enable-active = <0>;
+
OUT1 {
idt,mode = <VC5_CMOSD>;
idt,voltage-microvolt = <1800000>;
diff --git a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
index db3d0ea6bc7a..fbd758470b88 100644
--- a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
@@ -18,6 +18,7 @@ properties:
enum:
- qcom,ipq6018-a53pll
- qcom,msm8916-a53pll
+ - qcom,msm8939-a53pll
reg:
maxItems: 1
@@ -33,6 +34,8 @@ properties:
items:
- const: xo
+ operating-points-v2: true
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml
new file mode 100644
index 000000000000..26050da844d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,gcc-sm6115.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller Binding for SM6115 and SM4250
+
+maintainers:
+ - Iskren Chernev <iskren.chernev@gmail.com>
+
+description: |
+ Qualcomm global clock control module which supports the clocks, resets and
+ power domains on SM4250/6115.
+
+ See also:
+ - dt-bindings/clock/qcom,gcc-sm6115.h
+
+properties:
+ compatible:
+ const: qcom,gcc-sm6115
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: Sleep clock source
+
+ clock-names:
+ items:
+ - const: bi_tcxo
+ - const: sleep_clk
+
+ '#clock-cells':
+ const: 1
+
+ '#reset-cells':
+ const: 1
+
+ '#power-domain-cells':
+ const: 1
+
+ reg:
+ maxItems: 1
+
+ protected-clocks:
+ description:
+ Protected clock specifier list as per common clock binding.
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - reg
+ - '#clock-cells'
+ - '#reset-cells'
+ - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+ clock-controller@1400000 {
+ compatible = "qcom,gcc-sm6115";
+ reg = <0x01400000 0x1f0000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ clock-names = "bi_tcxo", "sleep_clk";
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&sleep_clk>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml
new file mode 100644
index 000000000000..20926cd8293e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,gcc-sm6350.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller Binding for SM6350
+
+maintainers:
+ - Konrad Dybcio <konrad.dybcio@somainline.org>
+
+description: |
+ Qualcomm global clock control module which supports the clocks, resets and
+ power domains on SM6350.
+
+ See also:
+ - dt-bindings/clock/qcom,gcc-sm6350.h
+
+properties:
+ compatible:
+ const: qcom,gcc-sm6350
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: Board active XO source
+ - description: Sleep clock source
+
+ clock-names:
+ items:
+ - const: bi_tcxo
+ - const: bi_tcxo_ao
+ - const: sleep_clk
+
+ '#clock-cells':
+ const: 1
+
+ '#reset-cells':
+ const: 1
+
+ '#power-domain-cells':
+ const: 1
+
+ reg:
+ maxItems: 1
+
+ protected-clocks:
+ description:
+ Protected clock specifier list as per common clock binding.
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - reg
+ - '#clock-cells'
+ - '#reset-cells'
+ - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ clock-controller@100000 {
+ compatible = "qcom,gcc-sm6350";
+ reg = <0x00100000 0x1f0000>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&rpmhcc RPMH_CXO_CLK_A>,
+ <&sleep_clk>;
+ clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml
index 8453eeddf30e..2f20f8aa932a 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml
@@ -23,6 +23,7 @@ description: |
- dt-bindings/clock/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
- dt-bindings/reset/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
- dt-bindings/clock/qcom,gcc-msm8939.h
+ - dt-bindings/clock/qcom,gcc-msm8953.h
- dt-bindings/reset/qcom,gcc-msm8939.h
- dt-bindings/clock/qcom,gcc-msm8660.h
- dt-bindings/reset/qcom,gcc-msm8660.h
@@ -46,6 +47,7 @@ properties:
- qcom,gcc-msm8660
- qcom,gcc-msm8916
- qcom,gcc-msm8939
+ - qcom,gcc-msm8953
- qcom,gcc-msm8960
- qcom,gcc-msm8974
- qcom,gcc-msm8974pro
diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
index df943c4c3234..46dff46d5760 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,gpucc.yaml#
@@ -11,11 +11,12 @@ maintainers:
description: |
Qualcomm graphics clock control module which supports the clocks, resets and
- power domains on SDM845/SC7180/SM8150/SM8250.
+ power domains on Qualcomm SoCs.
See also:
dt-bindings/clock/qcom,gpucc-sdm845.h
dt-bindings/clock/qcom,gpucc-sc7180.h
+ dt-bindings/clock/qcom,gpucc-sc7280.h
dt-bindings/clock/qcom,gpucc-sm8150.h
dt-bindings/clock/qcom,gpucc-sm8250.h
@@ -24,6 +25,8 @@ properties:
enum:
- qcom,sdm845-gpucc
- qcom,sc7180-gpucc
+ - qcom,sc7280-gpucc
+ - qcom,sc8180x-gpucc
- qcom,sm8150-gpucc
- qcom,sm8250-gpucc
diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml
index 8b0b1c56f354..68fdc3d4982a 100644
--- a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml
@@ -22,6 +22,8 @@ properties:
- qcom,mmcc-msm8660
- qcom,mmcc-msm8960
- qcom,mmcc-msm8974
+ - qcom,mmcc-msm8992
+ - qcom,mmcc-msm8994
- qcom,mmcc-msm8996
- qcom,mmcc-msm8998
- qcom,mmcc-sdm630
diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt
index 6cf5a7ec2b4c..a4877881f1d8 100644
--- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt
@@ -10,11 +10,13 @@ Required properties :
- compatible : shall contain only one of the following. The generic
compatible "qcom,rpmcc" should be also included.
+ "qcom,rpmcc-mdm9607", "qcom,rpmcc"
"qcom,rpmcc-msm8660", "qcom,rpmcc"
"qcom,rpmcc-apq8060", "qcom,rpmcc"
"qcom,rpmcc-msm8226", "qcom,rpmcc"
"qcom,rpmcc-msm8916", "qcom,rpmcc"
"qcom,rpmcc-msm8936", "qcom,rpmcc"
+ "qcom,rpmcc-msm8953", "qcom,rpmcc"
"qcom,rpmcc-msm8974", "qcom,rpmcc"
"qcom,rpmcc-msm8976", "qcom,rpmcc"
"qcom,rpmcc-apq8064", "qcom,rpmcc"
@@ -25,6 +27,8 @@ Required properties :
"qcom,rpmcc-msm8998", "qcom,rpmcc"
"qcom,rpmcc-qcs404", "qcom,rpmcc"
"qcom,rpmcc-sdm660", "qcom,rpmcc"
+ "qcom,rpmcc-sm6115", "qcom,rpmcc"
+ "qcom,rpmcc-sm6125", "qcom,rpmcc"
- #clock-cells : shall contain 1
diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
index 9ea0b3f5a4f2..72212970e6f5 100644
--- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
@@ -22,6 +22,7 @@ properties:
- qcom,sc8180x-rpmh-clk
- qcom,sdm845-rpmh-clk
- qcom,sdx55-rpmh-clk
+ - qcom,sm6350-rpmh-clk
- qcom,sm8150-rpmh-clk
- qcom,sm8250-rpmh-clk
- qcom,sm8350-rpmh-clk
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml
new file mode 100644
index 000000000000..2178666fb697
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sc7280-dispcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display Clock & Reset Controller Binding for SC7280
+
+maintainers:
+ - Taniya Das <tdas@codeaurora.org>
+
+description: |
+ Qualcomm display clock control module which supports the clocks, resets and
+ power domains on SC7280.
+
+ See also dt-bindings/clock/qcom,dispcc-sc7280.h.
+
+properties:
+ compatible:
+ const: qcom,sc7280-dispcc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: GPLL0 source from GCC
+ - description: Byte clock from DSI PHY
+ - description: Pixel clock from DSI PHY
+ - description: Link clock from DP PHY
+ - description: VCO DIV clock from DP PHY
+ - description: Link clock from EDP PHY
+ - description: VCO DIV clock from EDP PHY
+
+ clock-names:
+ items:
+ - const: bi_tcxo
+ - const: gcc_disp_gpll0_clk
+ - const: dsi0_phy_pll_out_byteclk
+ - const: dsi0_phy_pll_out_dsiclk
+ - const: dp_phy_pll_link_clk
+ - const: dp_phy_pll_vco_div_clk
+ - const: edp_phy_pll_link_clk
+ - const: edp_phy_pll_vco_div_clk
+
+ '#clock-cells':
+ const: 1
+
+ '#reset-cells':
+ const: 1
+
+ '#power-domain-cells':
+ const: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - '#clock-cells'
+ - '#reset-cells'
+ - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-sc7280.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ clock-controller@af00000 {
+ compatible = "qcom,sc7280-dispcc";
+ reg = <0x0af00000 0x200000>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_DISP_GPLL0_CLK_SRC>,
+ <&dsi_phy 0>,
+ <&dsi_phy 1>,
+ <&dp_phy 0>,
+ <&dp_phy 1>,
+ <&edp_phy 0>,
+ <&edp_phy 1>;
+ clock-names = "bi_tcxo",
+ "gcc_disp_gpll0_clk",
+ "dsi0_phy_pll_out_byteclk",
+ "dsi0_phy_pll_out_dsiclk",
+ "dp_phy_pll_link_clk",
+ "dp_phy_pll_vco_div_clk",
+ "edp_phy_pll_link_clk",
+ "edp_phy_pll_vco_div_clk";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
index 567202942b88..0d224f114b5b 100644
--- a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,videocc.yaml#
@@ -11,10 +11,11 @@ maintainers:
description: |
Qualcomm video clock control module which supports the clocks, resets and
- power domains on SDM845/SC7180/SM8150/SM8250.
+ power domains on Qualcomm SoCs.
See also:
dt-bindings/clock/qcom,videocc-sc7180.h
+ dt-bindings/clock/qcom,videocc-sc7280.h
dt-bindings/clock/qcom,videocc-sdm845.h
dt-bindings/clock/qcom,videocc-sm8150.h
dt-bindings/clock/qcom,videocc-sm8250.h
@@ -23,6 +24,7 @@ properties:
compatible:
enum:
- qcom,sc7180-videocc
+ - qcom,sc7280-videocc
- qcom,sdm845-videocc
- qcom,sm8150-videocc
- qcom,sm8250-videocc
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt
deleted file mode 100644
index 3bc56fae90ac..000000000000
--- a/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-* Rockchip RK3399 Clock and Reset Unit
-
-The RK3399 clock controller generates and supplies clock to various
-controllers within the SoC and also implements a reset controller for SoC
-peripherals.
-
-Required Properties:
-
-- compatible: PMU for CRU should be "rockchip,rk3399-pmucru"
-- compatible: CRU should be "rockchip,rk3399-cru"
-- reg: physical base address of the controller and length of memory mapped
- region.
-- #clock-cells: should be 1.
-- #reset-cells: should be 1.
-
-Optional Properties:
-
-- rockchip,grf: phandle to the syscon managing the "general register files".
- It is used for GRF muxes, if missing any muxes present in the GRF will not
- be available.
-
-Each clock is assigned an identifier and client nodes can use this identifier
-to specify the clock which they consume. All available clocks are defined as
-preprocessor macros in the dt-bindings/clock/rk3399-cru.h headers and can be
-used in device tree sources. Similar macros exist for the reset sources in
-these files.
-
-External clocks:
-
-There are several clocks that are generated outside the SoC. It is expected
-that they are defined using standard clock bindings with following
-clock-output-names:
- - "xin24m" - crystal input - required,
- - "xin32k" - rtc clock - optional,
- - "clkin_gmac" - external GMAC clock - optional,
- - "clkin_i2s" - external I2S clock - optional,
- - "pclkin_cif" - external ISP clock - optional,
- - "clk_usbphy0_480m" - output clock of the pll in the usbphy0
- - "clk_usbphy1_480m" - output clock of the pll in the usbphy1
-
-Example: Clock controller node:
-
- pmucru: pmu-clock-controller@ff750000 {
- compatible = "rockchip,rk3399-pmucru";
- reg = <0x0 0xff750000 0x0 0x1000>;
- #clock-cells = <1>;
- #reset-cells = <1>;
- };
-
- cru: clock-controller@ff760000 {
- compatible = "rockchip,rk3399-cru";
- reg = <0x0 0xff760000 0x0 0x1000>;
- #clock-cells = <1>;
- #reset-cells = <1>;
- };
-
-Example: UART controller node that consumes the clock generated by the clock
- controller:
-
- uart0: serial@ff1a0000 {
- compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
- reg = <0x0 0xff180000 0x0 0x100>;
- clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
- clock-names = "baudclk", "apb_pclk";
- interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
- reg-shift = <2>;
- reg-io-width = <4>;
- };
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.yaml
new file mode 100644
index 000000000000..72b286a1beba
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.yaml
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/rockchip,rk3399-cru.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip RK3399 Clock and Reset Unit
+
+maintainers:
+ - Xing Zheng <zhengxing@rock-chips.com>
+ - Heiko Stuebner <heiko@sntech.de>
+
+description: |
+ The RK3399 clock controller generates and supplies clock to various
+ controllers within the SoC and also implements a reset controller for SoC
+ peripherals.
+ Each clock is assigned an identifier and client nodes can use this identifier
+ to specify the clock which they consume. All available clocks are defined as
+ preprocessor macros in the dt-bindings/clock/rk3399-cru.h headers and can be
+ used in device tree sources. Similar macros exist for the reset sources in
+ these files.
+ There are several clocks that are generated outside the SoC. It is expected
+ that they are defined using standard clock bindings with following
+ clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "clkin_gmac" - external GMAC clock - optional,
+ - "clkin_i2s" - external I2S clock - optional,
+ - "pclkin_cif" - external ISP clock - optional,
+ - "clk_usbphy0_480m" - output clock of the pll in the usbphy0
+ - "clk_usbphy1_480m" - output clock of the pll in the usbphy1
+
+properties:
+ compatible:
+ enum:
+ - rockchip,rk3399-pmucru
+ - rockchip,rk3399-cru
+
+ reg:
+ maxItems: 1
+
+ "#clock-cells":
+ const: 1
+
+ "#reset-cells":
+ const: 1
+
+ clocks:
+ minItems: 1
+
+ assigned-clocks:
+ minItems: 1
+ maxItems: 64
+
+ assigned-clock-parents:
+ minItems: 1
+ maxItems: 64
+
+ assigned-clock-rates:
+ minItems: 1
+ maxItems: 64
+
+ rockchip,grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: >
+ phandle to the syscon managing the "general register files". It is used
+ for GRF muxes, if missing any muxes present in the GRF will not be
+ available.
+
+required:
+ - compatible
+ - reg
+ - "#clock-cells"
+ - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ pmucru: pmu-clock-controller@ff750000 {
+ compatible = "rockchip,rk3399-pmucru";
+ reg = <0xff750000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+ - |
+ cru: clock-controller@ff760000 {
+ compatible = "rockchip,rk3399-cru";
+ reg = <0xff760000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos-audss-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos-audss-clock.yaml
new file mode 100644
index 000000000000..f14f1d39da36
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos-audss-clock.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/samsung,exynos-audss-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos SoC Audio SubSystem clock controller
+
+maintainers:
+ - Chanwoo Choi <cw00.choi@samsung.com>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Sylwester Nawrocki <s.nawrocki@samsung.com>
+ - Tomasz Figa <tomasz.figa@gmail.com>
+
+description: |
+ All available clocks are defined as preprocessor macros in
+ include/dt-bindings/clock/exynos-audss-clk.h header.
+
+properties:
+ compatible:
+ enum:
+ - samsung,exynos4210-audss-clock
+ - samsung,exynos5250-audss-clock
+ - samsung,exynos5410-audss-clock
+ - samsung,exynos5420-audss-clock
+
+ clocks:
+ minItems: 2
+ items:
+ - description:
+ Fixed rate PLL reference clock, parent of mout_audss. "fin_pll" is
+ used if not specified.
+ - description:
+ Input PLL to the AudioSS block, parent of mout_audss. "fout_epll" is
+ used if not specified.
+ - description:
+ Audio bus clock, parent of mout_i2s. "sclk_audio0" is used if not
+ specified.
+ - description:
+ PCM clock, parent of sclk_pcm. "sclk_pcm0" is used if not specified.
+ - description:
+ External i2s clock, parent of mout_i2s. "cdclk0" is used if not
+ specified.
+
+ clock-names:
+ minItems: 2
+ items:
+ - const: pll_ref
+ - const: pll_in
+ - const: sclk_audio
+ - const: sclk_pcm_in
+ - const: cdclk
+
+ "#clock-cells":
+ const: 1
+
+ power-domains:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - "#clock-cells"
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ clock-controller@3810000 {
+ compatible = "samsung,exynos5250-audss-clock";
+ reg = <0x03810000 0x0c>;
+ #clock-cells = <1>;
+ clocks = <&clock 1>, <&clock 7>, <&clock 138>, <&clock 160>, <&ext_i2s_clk>;
+ clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in", "cdclk";
+ };
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos-clock.yaml
new file mode 100644
index 000000000000..4e8062860986
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos-clock.yaml
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/samsung,exynos-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos SoC clock controller
+
+maintainers:
+ - Chanwoo Choi <cw00.choi@samsung.com>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Sylwester Nawrocki <s.nawrocki@samsung.com>
+ - Tomasz Figa <tomasz.figa@gmail.com>
+
+description: |
+ All available clocks are defined as preprocessor macros in
+ dt-bindings/clock/ headers.
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - samsung,exynos3250-cmu
+ - samsung,exynos3250-cmu-dmc
+ - samsung,exynos3250-cmu-isp
+ - samsung,exynos4210-clock
+ - samsung,exynos4412-clock
+ - samsung,exynos5250-clock
+ - items:
+ - enum:
+ - samsung,exynos5420-clock
+ - samsung,exynos5800-clock
+ - const: syscon
+
+ clocks:
+ minItems: 1
+ maxItems: 4
+
+ "#clock-cells":
+ const: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - "#clock-cells"
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/exynos5250.h>
+ clock: clock-controller@10010000 {
+ compatible = "samsung,exynos5250-clock";
+ reg = <0x10010000 0x30000>;
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos-ext-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos-ext-clock.yaml
new file mode 100644
index 000000000000..64d027dbe3b2
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos-ext-clock.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/samsung,exynos-ext-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung SoC external/osc/XXTI/XusbXTI clock
+
+maintainers:
+ - Chanwoo Choi <cw00.choi@samsung.com>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Sylwester Nawrocki <s.nawrocki@samsung.com>
+ - Tomasz Figa <tomasz.figa@gmail.com>
+
+description: |
+ Samsung SoCs require an external clock supplied through XXTI or XusbXTI pins.
+
+properties:
+ compatible:
+ enum:
+ - samsung,clock-xxti
+ - samsung,clock-xusbxti
+ - samsung,exynos5420-oscclk
+
+ "#clock-cells":
+ const: 0
+
+ clock-frequency: true
+
+ clock-output-names:
+ maxItems: 1
+
+required:
+ - compatible
+ - clock-frequency
+
+additionalProperties: false
+
+examples:
+ - |
+ fixed-rate-clocks {
+ clock {
+ compatible = "samsung,clock-xxti";
+ clock-frequency = <24000000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos4412-isp-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos4412-isp-clock.yaml
new file mode 100644
index 000000000000..1ed64add4355
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos4412-isp-clock.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/samsung,exynos4412-isp-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos4412 SoC ISP clock controller
+
+maintainers:
+ - Chanwoo Choi <cw00.choi@samsung.com>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Sylwester Nawrocki <s.nawrocki@samsung.com>
+ - Tomasz Figa <tomasz.figa@gmail.com>
+
+description: |
+ Clock controller for Samsung Exynos4412 SoC FIMC-ISP (Camera ISP)
+ All available clocks are defined as preprocessor macros in
+ dt-bindings/clock/ headers.
+
+properties:
+ compatible:
+ const: samsung,exynos4412-isp-clock
+
+ clocks:
+ items:
+ - description: CLK_ACLK200 from the main clock controller
+ - description: CLK_ACLK400_MCUISP from the main clock controller
+
+ clock-names:
+ items:
+ - const: aclk200
+ - const: aclk400_mcuisp
+
+ "#clock-cells":
+ const: 1
+
+ power-domains:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - "#clock-cells"
+ - clocks
+ - clock-names
+ - power-domains
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/exynos4.h>
+ clock-controller@10048000 {
+ compatible = "samsung,exynos4412-isp-clock";
+ reg = <0x10048000 0x1000>;
+ #clock-cells = <1>;
+ power-domains = <&pd_isp>;
+ clocks = <&clock CLK_ACLK200>, <&clock CLK_ACLK400_MCUISP>;
+ clock-names = "aclk200", "aclk400_mcuisp";
+ };
+
diff --git a/Documentation/devicetree/bindings/clock/samsung,s5pv210-audss-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,s5pv210-audss-clock.yaml
new file mode 100644
index 000000000000..ae8f8fc93233
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,s5pv210-audss-clock.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/samsung,s5pv210-audss-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S5Pv210 SoC Audio SubSystem clock controller
+
+maintainers:
+ - Chanwoo Choi <cw00.choi@samsung.com>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Sylwester Nawrocki <s.nawrocki@samsung.com>
+ - Tomasz Figa <tomasz.figa@gmail.com>
+
+description: |
+ All available clocks are defined as preprocessor macros in
+ include/dt-bindings/clock/s5pv210-audss.h header.
+
+properties:
+ compatible:
+ const: samsung,s5pv210-audss-clock
+
+ clocks:
+ minItems: 4
+ items:
+ - description:
+ AHB bus clock of the Audio Subsystem.
+ - description:
+ Optional fixed rate PLL reference clock, parent of mout_audss. If not
+ specified (i.e. xusbxti is used for PLL reference), it is fixed to a
+ clock named "xxti".
+ - description:
+ Input PLL to the AudioSS block, parent of mout_audss.
+ - description:
+ Audio bus clock, parent of mout_i2s.
+ - description:
+ Optional external i2s clock, parent of mout_i2s. If not specified, it
+ is fixed to a clock named "iiscdclk0".
+
+ clock-names:
+ minItems: 4
+ items:
+ - const: hclk
+ - const: xxti
+ - const: fout_epll
+ - const: sclk_audio0
+ - const: iiscdclk0
+
+ "#clock-cells":
+ const: 1
+
+ power-domains:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - "#clock-cells"
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/s5pv210.h>
+
+ clock-controller@c0900000 {
+ compatible = "samsung,s5pv210-audss-clock";
+ reg = <0xc0900000 0x1000>;
+ #clock-cells = <1>;
+ clock-names = "hclk", "xxti", "fout_epll", "sclk_audio0";
+ clocks = <&clocks DOUT_HCLKP>, <&xxti>, <&clocks FOUT_EPLL>,
+ <&clocks SCLK_AUDIO0>;
+ };
diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml
index 92b49bc37939..7eb8659fa610 100644
--- a/Documentation/devicetree/bindings/connector/usb-connector.yaml
+++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml
@@ -111,6 +111,10 @@ properties:
- 1.5A
- 3.0A
+ pd-disable:
+ description: Set this property if the Type-C connector has no power delivery support.
+ type: boolean
+
# The following are optional properties for "usb-c-connector" with power
# delivery support.
source-pdos:
diff --git a/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt b/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt
deleted file mode 100644
index aeaebd425d1f..000000000000
--- a/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-
-* Samsung Exynos NoC (Network on Chip) Probe device
-
-The Samsung Exynos542x SoC has NoC (Network on Chip) Probe for NoC bus.
-NoC provides the primitive values to get the performance data. The packets
-that the Network on Chip (NoC) probes detects are transported over
-the network infrastructure to observer units. You can configure probes to
-capture packets with header or data on the data request response network,
-or as traffic debug or statistic collectors. Exynos542x bus has multiple
-NoC probes to provide bandwidth information about behavior of the SoC
-that you can use while analyzing system performance.
-
-Required properties:
-- compatible: Should be "samsung,exynos5420-nocp"
-- reg: physical base address of each NoC Probe and length of memory mapped region.
-
-Optional properties:
-- clock-names : the name of clock used by the NoC Probe, "nocp"
-- clocks : phandles for clock specified in "clock-names" property
-
-Example : NoC Probe nodes in Device Tree are listed below.
-
- nocp_mem0_0: nocp@10ca1000 {
- compatible = "samsung,exynos5420-nocp";
- reg = <0x10CA1000 0x200>;
- };
diff --git a/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt b/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
deleted file mode 100644
index fb46b491791c..000000000000
--- a/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
+++ /dev/null
@@ -1,169 +0,0 @@
-
-* Samsung Exynos PPMU (Platform Performance Monitoring Unit) device
-
-The Samsung Exynos SoC has PPMU (Platform Performance Monitoring Unit) for
-each IP. PPMU provides the primitive values to get performance data. These
-PPMU events provide information of the SoC's behaviors so that you may
-use to analyze system performance, to make behaviors visible and to count
-usages of each IP (DMC, CPU, RIGHTBUS, LEFTBUS, CAM interface, LCD, G3D, MFC).
-The Exynos PPMU driver uses the devfreq-event class to provide event data
-to various devfreq devices. The devfreq devices would use the event data when
-derterming the current state of each IP.
-
-Required properties for PPMU device:
-- compatible: Should be "samsung,exynos-ppmu" or "samsung,exynos-ppmu-v2.
-- reg: physical base address of each PPMU and length of memory mapped region.
-
-Optional properties for PPMU device:
-- clock-names : the name of clock used by the PPMU, "ppmu"
-- clocks : phandles for clock specified in "clock-names" property
-
-Required properties for 'events' child node of PPMU device:
-- event-name : the unique event name among PPMU device
-Optional properties for 'events' child node of PPMU device:
-- event-data-type : Define the type of data which shell be counted
-by the counter. You can check include/dt-bindings/pmu/exynos_ppmu.h for
-all possible type, i.e. count read requests, count write data in bytes,
-etc. This field is optional and when it is missing, the driver code
-will use default data type.
-
-Example1 : PPMUv1 nodes in exynos3250.dtsi are listed below.
-
- ppmu_dmc0: ppmu_dmc0@106a0000 {
- compatible = "samsung,exynos-ppmu";
- reg = <0x106a0000 0x2000>;
- status = "disabled";
- };
-
- ppmu_dmc1: ppmu_dmc1@106b0000 {
- compatible = "samsung,exynos-ppmu";
- reg = <0x106b0000 0x2000>;
- status = "disabled";
- };
-
- ppmu_cpu: ppmu_cpu@106c0000 {
- compatible = "samsung,exynos-ppmu";
- reg = <0x106c0000 0x2000>;
- status = "disabled";
- };
-
- ppmu_rightbus: ppmu_rightbus@112a0000 {
- compatible = "samsung,exynos-ppmu";
- reg = <0x112a0000 0x2000>;
- clocks = <&cmu CLK_PPMURIGHT>;
- clock-names = "ppmu";
- status = "disabled";
- };
-
- ppmu_leftbus: ppmu_leftbus0@116a0000 {
- compatible = "samsung,exynos-ppmu";
- reg = <0x116a0000 0x2000>;
- clocks = <&cmu CLK_PPMULEFT>;
- clock-names = "ppmu";
- status = "disabled";
- };
-
-Example2 : Events of each PPMU node in exynos3250-rinato.dts are listed below.
-
- &ppmu_dmc0 {
- status = "okay";
-
- events {
- ppmu_dmc0_3: ppmu-event3-dmc0 {
- event-name = "ppmu-event3-dmc0";
- };
-
- ppmu_dmc0_2: ppmu-event2-dmc0 {
- event-name = "ppmu-event2-dmc0";
- };
-
- ppmu_dmc0_1: ppmu-event1-dmc0 {
- event-name = "ppmu-event1-dmc0";
- };
-
- ppmu_dmc0_0: ppmu-event0-dmc0 {
- event-name = "ppmu-event0-dmc0";
- };
- };
- };
-
- &ppmu_dmc1 {
- status = "okay";
-
- events {
- ppmu_dmc1_3: ppmu-event3-dmc1 {
- event-name = "ppmu-event3-dmc1";
- };
- };
- };
-
- &ppmu_leftbus {
- status = "okay";
-
- events {
- ppmu_leftbus_3: ppmu-event3-leftbus {
- event-name = "ppmu-event3-leftbus";
- };
- };
- };
-
- &ppmu_rightbus {
- status = "okay";
-
- events {
- ppmu_rightbus_3: ppmu-event3-rightbus {
- event-name = "ppmu-event3-rightbus";
- };
- };
- };
-
-Example3 : PPMUv2 nodes in exynos5433.dtsi are listed below.
-
- ppmu_d0_cpu: ppmu_d0_cpu@10480000 {
- compatible = "samsung,exynos-ppmu-v2";
- reg = <0x10480000 0x2000>;
- status = "disabled";
- };
-
- ppmu_d0_general: ppmu_d0_general@10490000 {
- compatible = "samsung,exynos-ppmu-v2";
- reg = <0x10490000 0x2000>;
- status = "disabled";
- };
-
- ppmu_d0_rt: ppmu_d0_rt@104a0000 {
- compatible = "samsung,exynos-ppmu-v2";
- reg = <0x104a0000 0x2000>;
- status = "disabled";
- };
-
- ppmu_d1_cpu: ppmu_d1_cpu@104b0000 {
- compatible = "samsung,exynos-ppmu-v2";
- reg = <0x104b0000 0x2000>;
- status = "disabled";
- };
-
- ppmu_d1_general: ppmu_d1_general@104c0000 {
- compatible = "samsung,exynos-ppmu-v2";
- reg = <0x104c0000 0x2000>;
- status = "disabled";
- };
-
- ppmu_d1_rt: ppmu_d1_rt@104d0000 {
- compatible = "samsung,exynos-ppmu-v2";
- reg = <0x104d0000 0x2000>;
- status = "disabled";
- };
-
-Example4 : 'event-data-type' in exynos4412-ppmu-common.dtsi are listed below.
-
- &ppmu_dmc0 {
- status = "okay";
- events {
- ppmu_dmc0_3: ppmu-event3-dmc0 {
- event-name = "ppmu-event3-dmc0";
- event-data-type = <(PPMU_RO_DATA_CNT |
- PPMU_WO_DATA_CNT)>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/devfreq/event/samsung,exynos-nocp.yaml b/Documentation/devicetree/bindings/devfreq/event/samsung,exynos-nocp.yaml
new file mode 100644
index 000000000000..d318fccf78f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/samsung,exynos-nocp.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/devfreq/event/samsung,exynos-nocp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos NoC (Network on Chip) Probe
+
+maintainers:
+ - Chanwoo Choi <cw00.choi@samsung.com>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+ The Samsung Exynos542x SoC has a NoC (Network on Chip) Probe for NoC bus.
+ NoC provides the primitive values to get the performance data. The packets
+ that the Network on Chip (NoC) probes detects are transported over the
+ network infrastructure to observer units. You can configure probes to capture
+ packets with header or data on the data request response network, or as
+ traffic debug or statistic collectors. Exynos542x bus has multiple NoC probes
+ to provide bandwidth information about behavior of the SoC that you can use
+ while analyzing system performance.
+
+properties:
+ compatible:
+ const: samsung,exynos5420-nocp
+
+ clock-names:
+ items:
+ - const: nocp
+
+ clocks:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ nocp_mem0_0: nocp@10ca1000 {
+ compatible = "samsung,exynos5420-nocp";
+ reg = <0x10ca1000 0x200>;
+ };
diff --git a/Documentation/devicetree/bindings/devfreq/event/samsung,exynos-ppmu.yaml b/Documentation/devicetree/bindings/devfreq/event/samsung,exynos-ppmu.yaml
new file mode 100644
index 000000000000..c9a8cb5fd555
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/samsung,exynos-ppmu.yaml
@@ -0,0 +1,169 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/devfreq/event/samsung,exynos-ppmu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos SoC PPMU (Platform Performance Monitoring Unit)
+
+maintainers:
+ - Chanwoo Choi <cw00.choi@samsung.com>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+ The Samsung Exynos SoC has PPMU (Platform Performance Monitoring Unit) for
+ each IP. PPMU provides the primitive values to get performance data. These
+ PPMU events provide information of the SoC's behaviors so that you may use to
+ analyze system performance, to make behaviors visible and to count usages of
+ each IP (DMC, CPU, RIGHTBUS, LEFTBUS, CAM interface, LCD, G3D, MFC). The
+ Exynos PPMU driver uses the devfreq-event class to provide event data to
+ various devfreq devices. The devfreq devices would use the event data when
+ derterming the current state of each IP.
+
+properties:
+ compatible:
+ enum:
+ - samsung,exynos-ppmu
+ - samsung,exynos-ppmu-v2
+
+ clock-names:
+ items:
+ - const: ppmu
+
+ clocks:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+ events:
+ type: object
+
+ patternProperties:
+ '^ppmu-event[0-9]+(-[a-z0-9]+){,2}$':
+ type: object
+ properties:
+ event-name:
+ description: |
+ The unique event name among PPMU device
+ $ref: /schemas/types.yaml#/definitions/string
+
+ event-data-type:
+ description: |
+ Define the type of data which shell be counted by the counter.
+ You can check include/dt-bindings/pmu/exynos_ppmu.h for all
+ possible type, i.e. count read requests, count write data in
+ bytes, etc. This field is optional and when it is missing, the
+ driver code will use default data type.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ required:
+ - event-name
+
+ additionalProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ // PPMUv1 nodes for Exynos3250 (although the board DTS defines events)
+ #include <dt-bindings/clock/exynos3250.h>
+
+ ppmu_dmc0: ppmu@106a0000 {
+ compatible = "samsung,exynos-ppmu";
+ reg = <0x106a0000 0x2000>;
+
+ events {
+ ppmu_dmc0_3: ppmu-event3-dmc0 {
+ event-name = "ppmu-event3-dmc0";
+ };
+
+ ppmu_dmc0_2: ppmu-event2-dmc0 {
+ event-name = "ppmu-event2-dmc0";
+ };
+
+ ppmu_dmc0_1: ppmu-event1-dmc0 {
+ event-name = "ppmu-event1-dmc0";
+ };
+
+ ppmu_dmc0_0: ppmu-event0-dmc0 {
+ event-name = "ppmu-event0-dmc0";
+ };
+ };
+ };
+
+ ppmu_rightbus: ppmu@112a0000 {
+ compatible = "samsung,exynos-ppmu";
+ reg = <0x112a0000 0x2000>;
+ clocks = <&cmu CLK_PPMURIGHT>;
+ clock-names = "ppmu";
+
+ events {
+ ppmu_rightbus_3: ppmu-event3-rightbus {
+ event-name = "ppmu-event3-rightbus";
+ };
+ };
+ };
+
+ - |
+ // PPMUv2 nodes in Exynos5433
+ ppmu_d0_cpu: ppmu@10480000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x10480000 0x2000>;
+ };
+
+ ppmu_d0_general: ppmu@10490000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x10490000 0x2000>;
+
+ events {
+ ppmu_event0_d0_general: ppmu-event0-d0-general {
+ event-name = "ppmu-event0-d0-general";
+ };
+ };
+ };
+
+ ppmu_d0_rt: ppmu@104a0000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x104a0000 0x2000>;
+ };
+
+ ppmu_d1_cpu: ppmu@104b0000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x104b0000 0x2000>;
+ };
+
+ ppmu_d1_general: ppmu@104c0000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x104c0000 0x2000>;
+ };
+
+ ppmu_d1_rt: ppmu@104d0000 {
+ compatible = "samsung,exynos-ppmu-v2";
+ reg = <0x104d0000 0x2000>;
+ };
+
+ - |
+ // PPMUv1 nodes with event-data-type for Exynos4412
+ #include <dt-bindings/pmu/exynos_ppmu.h>
+
+ ppmu@106a0000 {
+ compatible = "samsung,exynos-ppmu";
+ reg = <0x106a0000 0x2000>;
+ clocks = <&clock 400>;
+ clock-names = "ppmu";
+
+ events {
+ ppmu-event3-dmc0 {
+ event-name = "ppmu-event3-dmc0";
+ event-data-type = <(PPMU_RO_DATA_CNT |
+ PPMU_WO_DATA_CNT)>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml
index 5d42d36608d9..4951b5ef5c6a 100644
--- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-dw-hdmi.yaml
@@ -174,7 +174,6 @@ examples:
phy-names = "phy";
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
- status = "disabled";
ports {
#address-cells = <1>;
@@ -233,7 +232,6 @@ examples:
phy-names = "phy";
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
- status = "disabled";
ports {
#address-cells = <1>;
diff --git a/Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml b/Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml
index 6c7b577fd471..43cf4df9811a 100644
--- a/Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml
@@ -22,6 +22,9 @@ properties:
- ti,ths8134a
- ti,ths8134b
- const: ti,ths8134
+ - items:
+ - const: corpro,gm7123
+ - const: adi,adv7123
- enum:
- adi,adv7123
- dumb-vga-dac
diff --git a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
index d101233ae17f..07b20383cbca 100644
--- a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
@@ -37,7 +37,8 @@ properties:
properties:
port@0:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
description: Video port for MIPI DSI Channel-A input
properties:
@@ -57,7 +58,8 @@ properties:
- const: 4
port@1:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
description: Video port for MIPI DSI Channel-B input
properties:
diff --git a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml
index 26932d2e86ab..1c2daf7c24cc 100644
--- a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml
@@ -70,6 +70,9 @@ properties:
const: 1
description: See ../../pwm/pwm.yaml for description of the cell formats.
+ aux-bus:
+ $ref: /schemas/display/dp-aux-bus.yaml#
+
ports:
$ref: /schemas/graph.yaml#/properties/ports
@@ -150,7 +153,6 @@ properties:
required:
- compatible
- reg
- - enable-gpios
- vccio-supply
- vpll-supply
- vcca-supply
@@ -201,11 +203,26 @@ examples:
port@1 {
reg = <1>;
- endpoint {
+ sn65dsi86_out: endpoint {
remote-endpoint = <&panel_in_edp>;
};
};
};
+
+ aux-bus {
+ panel {
+ compatible = "boe,nv133fhm-n62";
+ power-supply = <&pp3300_dx_edp>;
+ backlight = <&backlight>;
+ hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>;
+
+ port {
+ panel_in_edp: endpoint {
+ remote-endpoint = <&sn65dsi86_out>;
+ };
+ };
+ };
+ };
};
};
- |
diff --git a/Documentation/devicetree/bindings/display/dp-aux-bus.yaml b/Documentation/devicetree/bindings/display/dp-aux-bus.yaml
new file mode 100644
index 000000000000..5e4afe9f98fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/dp-aux-bus.yaml
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/dp-aux-bus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DisplayPort AUX bus
+
+maintainers:
+ - Douglas Anderson <dianders@chromium.org>
+
+description:
+ DisplayPort controllers provide a control channel to the sinks that
+ are hooked up to them. This is the DP AUX bus. Over the DP AUX bus
+ we can query properties about a sink and also configure it. In
+ particular, DP sinks support DDC over DP AUX which allows tunneling
+ a standard I2C DDC connection over the AUX channel.
+
+ To model this relationship, DP sinks should be placed as children
+ of the DP controller under the "aux-bus" node.
+
+ At the moment, this binding only handles the eDP case. It is
+ possible it will be extended in the future to handle the DP case.
+ For DP, presumably a connector would be listed under the DP AUX
+ bus instead of a panel.
+
+properties:
+ $nodename:
+ const: "aux-bus"
+
+ panel:
+ $ref: panel/panel-common.yaml#
+
+additionalProperties: false
+
+required:
+ - panel
diff --git a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
index a4c3064c778c..900a56cae80e 100644
--- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
+++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
@@ -27,6 +27,7 @@ properties:
- fsl,imx6ul-lcdif
- fsl,imx7d-lcdif
- fsl,imx8mm-lcdif
+ - fsl,imx8mn-lcdif
- fsl,imx8mq-lcdif
- const: fsl,imx6sx-lcdif
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt
index 8238a86686be..d30428b9fb33 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt
@@ -7,7 +7,7 @@ channel output.
Required properties:
- compatible: "mediatek,<chip>-dsi"
-- the supported chips are mt2701, mt7623, mt8173 and mt8183.
+- the supported chips are mt2701, mt7623, mt8167, mt8173 and mt8183.
- reg: Physical base address and length of the controller's registers
- interrupts: The interrupt signal from the function block.
- clocks: device clocks
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
index 76348b71f736..35426fde8610 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
@@ -64,6 +64,18 @@ properties:
Indicates if the DSI controller is driving a panel which needs
2 DSI links.
+ assigned-clocks:
+ minItems: 2
+ maxItems: 2
+ description: |
+ Parents of "byte" and "pixel" for the given platform.
+
+ assigned-clock-parents:
+ minItems: 2
+ maxItems: 2
+ description: |
+ The Byte clock and Pixel clock PLL outputs provided by a DSI PHY block.
+
power-domains:
maxItems: 1
@@ -77,7 +89,8 @@ properties:
properties:
port@0:
- $ref: "/schemas/graph.yaml#/properties/port"
+ $ref: "/schemas/graph.yaml#/$defs/port-base"
+ unevaluatedProperties: false
description: |
Input endpoints of the controller.
properties:
@@ -92,7 +105,8 @@ properties:
enum: [ 0, 1, 2, 3 ]
port@1:
- $ref: "/schemas/graph.yaml#/properties/port"
+ $ref: "/schemas/graph.yaml#/$defs/port-base"
+ unevaluatedProperties: false
description: |
Output endpoints of the controller.
properties:
@@ -119,6 +133,8 @@ required:
- clock-names
- phys
- phy-names
+ - assigned-clocks
+ - assigned-clock-parents
- power-domains
- operating-points-v2
- ports
@@ -159,6 +175,9 @@ examples:
phys = <&dsi0_phy>;
phy-names = "dsi";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi_phy 0>, <&dsi_phy 1>;
+
power-domains = <&rpmhpd SC7180_CX>;
operating-points-v2 = <&dsi_opp_table>;
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
index 4a26bef19360..4399715953e1 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
@@ -14,9 +14,9 @@ allOf:
properties:
compatible:
- oneOf:
- - const: qcom,dsi-phy-10nm
- - const: qcom,dsi-phy-10nm-8998
+ enum:
+ - qcom,dsi-phy-10nm
+ - qcom,dsi-phy-10nm-8998
reg:
items:
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
index 72a00cce0147..064df50e21a5 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
@@ -14,9 +14,9 @@ allOf:
properties:
compatible:
- oneOf:
- - const: qcom,dsi-phy-14nm
- - const: qcom,dsi-phy-14nm-660
+ enum:
+ - qcom,dsi-phy-14nm
+ - qcom,dsi-phy-14nm-660
reg:
items:
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml
index 743806d61afe..b8de785ce815 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml
@@ -14,8 +14,7 @@ allOf:
properties:
compatible:
- oneOf:
- - const: qcom,dsi-phy-20nm
+ const: qcom,dsi-phy-20nm
reg:
items:
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml
index b106007116b4..69eecaa64b18 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml
@@ -14,10 +14,10 @@ allOf:
properties:
compatible:
- oneOf:
- - const: qcom,dsi-phy-28nm-hpm
- - const: qcom,dsi-phy-28nm-lp
- - const: qcom,dsi-phy-28nm-8960
+ enum:
+ - qcom,dsi-phy-28nm-hpm
+ - qcom,dsi-phy-28nm-lp
+ - qcom,dsi-phy-28nm-8960
reg:
items:
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
new file mode 100644
index 000000000000..4265399bb154
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/dsi-phy-7nm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DSI 7nm PHY
+
+maintainers:
+ - Jonathan Marek <jonathan@marek.ca>
+
+allOf:
+ - $ref: dsi-phy-common.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - const: qcom,dsi-phy-7nm
+ - const: qcom,dsi-phy-7nm-8150
+ - const: qcom,sc7280-dsi-phy-7nm
+
+ reg:
+ items:
+ - description: dsi phy register set
+ - description: dsi phy lane register set
+ - description: dsi pll register set
+
+ reg-names:
+ items:
+ - const: dsi_phy
+ - const: dsi_phy_lane
+ - const: dsi_pll
+
+ vdds-supply:
+ description: |
+ Connected to VDD_A_DSI_PLL_0P9 pin (or VDDA_DSI{0,1}_PLL_0P9 for sm8150)
+
+ phy-type:
+ description: D-PHY (default) or C-PHY mode
+ enum: [ 10, 11 ]
+ default: 10
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - vdds-supply
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sm8250.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+
+ dsi-phy@ae94400 {
+ compatible = "qcom,dsi-phy-7nm";
+ reg = <0x0ae94400 0x200>,
+ <0x0ae94600 0x280>,
+ <0x0ae94900 0x260>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ vdds-supply = <&vreg_l5a_0p88>;
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+ };
diff --git a/Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml b/Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml
index 38bc1d1b511e..b87a2e28c866 100644
--- a/Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml
+++ b/Documentation/devicetree/bindings/display/panel/boe,tv101wum-nl6.yaml
@@ -70,7 +70,6 @@ examples:
avee-supply = <&ppvarp_lcd>;
pp1800-supply = <&pp1800_lcd>;
backlight = <&backlight_lcd0>;
- status = "okay";
port {
panel_in: endpoint {
remote-endpoint = <&dsi_out>;
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
new file mode 100644
index 000000000000..2ed010f91e2d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/ilitek,ili9341.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Ilitek-9341 Display Panel
+
+maintainers:
+ - Dillon Min <dillon.minfei@gmail.com>
+
+description: |
+ Ilitek ILI9341 TFT panel driver with SPI control bus
+ This is a driver for 320x240 TFT panels, accepting a rgb input
+ streams with 16 bits or 18 bits.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ # ili9341 240*320 Color on stm32f429-disco board
+ - st,sf-tc240t-9370-t
+ - const: ilitek,ili9341
+
+ reg: true
+
+ dc-gpios:
+ maxItems: 1
+ description: Display data/command selection (D/CX) of this DBI panel
+
+ spi-3wire: true
+
+ spi-max-frequency:
+ const: 10000000
+
+ port: true
+
+ vci-supply:
+ description: Analog voltage supply (2.5 .. 3.3V)
+
+ vddi-supply:
+ description: Voltage supply for interface logic (1.65 .. 3.3 V)
+
+ vddi-led-supply:
+ description: Voltage supply for the LED driver (1.65 .. 3.3 V)
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - dc-gpios
+ - port
+
+examples:
+ - |+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ panel: display@0 {
+ compatible = "st,sf-tc240t-9370-t",
+ "ilitek,ili9341";
+ reg = <0>;
+ spi-3wire;
+ spi-max-frequency = <10000000>;
+ dc-gpios = <&gpiod 13 0>;
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&display_out>;
+ };
+ };
+ };
+ };
+...
+
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml b/Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml
new file mode 100644
index 000000000000..cda36c04e85c
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,ej030na.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/innolux,ej030na.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Innolux EJ030NA 3.0" (320x480 pixels) 24-bit TFT LCD panel
+
+description: |
+ The panel must obey the rules for a SPI slave device as specified in
+ spi/spi-controller.yaml
+
+maintainers:
+ - Paul Cercueil <paul@crapouillou.net>
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ const: innolux,ej030na
+
+ backlight: true
+ port: true
+ power-supply: true
+ reg: true
+ reset-gpios: true
+
+required:
+ - compatible
+ - reg
+ - power-supply
+ - reset-gpios
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "innolux,ej030na";
+ reg = <0>;
+
+ spi-max-frequency = <10000000>;
+
+ reset-gpios = <&gpe 4 GPIO_ACTIVE_LOW>;
+ power-supply = <&lcd_power>;
+
+ backlight = <&backlight>;
+
+ port {
+ panel_input: endpoint {
+ remote-endpoint = <&panel_output>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index b3797ba2698b..335776c45474 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -46,9 +46,13 @@ properties:
# AU Optronics Corporation 11.6" HD (1366x768) color TFT-LCD panel
- auo,b116xw03
# AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
+ - auo,b133han05
+ # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
- auo,b133htn01
# AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel
- auo,b133xtn01
+ # AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel
+ - auo,b140han06
# AU Optronics Corporation 7.0" FHD (800 x 480) TFT LCD panel
- auo,g070vvn01
# AU Optronics Corporation 10.1" (1280x800) color TFT LCD panel
@@ -110,6 +114,9 @@ properties:
# Emerging Display Technology Corp. 5.7" VGA TFT LCD panel
- edt,et057090dhu
- edt,et070080dh6
+ # Emerging Display Technology Corp. 3.5" WVGA TFT LCD panel with
+ # capacitive multitouch
+ - edt,etm0350g0dh6
# Emerging Display Technology Corp. 480x272 TFT Display with capacitive touch
- edt,etm043080dh6gp
# Emerging Display Technology Corp. 480x272 TFT Display
@@ -128,6 +135,11 @@ properties:
# Emerging Display Technology Corp. WVGA TFT Display with capacitive touch
- edt,etm0700g0dh6
- edt,etm0700g0edh6
+ # Emerging Display Technology Corp. 5.7" VGA TFT LCD panel with
+ # capacitive touch
+ - edt,etmv570g2dhu
+ # E Ink VB3300-KCA
+ - eink,vb3300-kca
# Evervision Electronics Co. Ltd. VGG804821 5.0" WVGA TFT LCD Panel
- evervision,vgg804821
# Foxlink Group 5" WVGA TFT LCD panel
@@ -202,8 +214,14 @@ properties:
- logictechno,lt161010-2nhr
# Logic Technologies LT170410-2WHC 10.1" 1280x800 IPS TFT Cap Touch Mod.
- logictechno,lt170410-2whc
+ # Logic Technologies LTTD800x480 L2RT 7" 800x480 TFT Resistive Touch Module
+ - logictechno,lttd800480070-l2rt
+ # Logic Technologies LTTD800480070-L6WH-RT 7” 800x480 TFT Resistive Touch Module
+ - logictechno,lttd800480070-l6wh-rt
# Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
- mitsubishi,aa070mc01-ca1
+ # Multi-Inno Technology Co.,Ltd MI1010AIT-1CP 10.1" 1280x800 LVDS IPS Cap Touch Mod.
+ - multi-inno,mi1010ait-1cp
# NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel
- nec,nl12880bc20-05
# NEC LCD Technologies,Ltd. WQVGA TFT LCD panel
@@ -238,10 +256,14 @@ properties:
- powertip,ph800480t013-idf02
# QiaoDian XianShi Corporation 4"3 TFT LCD panel
- qiaodian,qd43003c0-40
+ # Shenzhen QiShenglong Industrialist Co., Ltd. Gopher 2b 4.3" 480(RGB)x272 TFT LCD panel
+ - qishenglong,gopher2b-lcd
# Rocktech Displays Ltd. RK101II01D-CT 10.1" TFT 1280x800
- rocktech,rk101ii01d-ct
# Rocktech Display Ltd. RK070ER9427 800(RGB)x480 TFT LCD panel
- rocktech,rk070er9427
+ # Samsung 13.3" FHD (1920x1080 pixels) eDP AMOLED panel
+ - samsung,atna33xc20
# Samsung 12.2" (2560x1600 pixels) TFT LCD panel
- samsung,lsn122dl01-c01
# Samsung Electronics 10.1" WSVGA TFT LCD panel
@@ -298,6 +320,8 @@ properties:
enable-gpios: true
port: true
power-supply: true
+ no-hpd: true
+ hpd-gpios: true
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml b/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
new file mode 100644
index 000000000000..251f0c7115aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
@@ -0,0 +1,99 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/samsung,lms380kf01.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung LMS380KF01 display panel
+
+description: The LMS380KF01 is a 480x800 DPI display panel from Samsung Mobile
+ Displays (SMD) utilizing the WideChips WS2401 display controller. It can be
+ used with internal or external backlight control.
+ The panel must obey the rules for a SPI slave device as specified in
+ spi/spi-controller.yaml
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ const: samsung,lms380kf01
+
+ reg: true
+
+ interrupts:
+ description: provides an optional ESD (electrostatic discharge)
+ interrupt that signals abnormalities in the display hardware.
+ This can also be raised for other reasons like erroneous
+ configuration.
+ maxItems: 1
+
+ reset-gpios: true
+
+ vci-supply:
+ description: regulator that supplies the VCI analog voltage
+ usually around 3.0 V
+
+ vccio-supply:
+ description: regulator that supplies the VCCIO voltage usually
+ around 1.8 V
+
+ backlight: true
+
+ spi-cpha: true
+
+ spi-cpol: true
+
+ spi-max-frequency:
+ maximum: 1200000
+
+ port: true
+
+required:
+ - compatible
+ - reg
+ - spi-cpha
+ - spi-cpol
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ spi {
+ compatible = "spi-gpio";
+ sck-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+ miso-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
+ mosi-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
+ num-chipselects = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "samsung,lms380kf01";
+ spi-max-frequency = <1200000>;
+ spi-cpha;
+ spi-cpol;
+ reg = <0>;
+ vci-supply = <&lcd_3v0_reg>;
+ vccio-supply = <&lcd_1v8_reg>;
+ reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
+ interrupt-parent = <&gpio>;
+ interrupts = <5 IRQ_TYPE_EDGE_RISING>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&display_out>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml b/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
index 4cb75a5f2e3a..cd62968426fb 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
@@ -33,8 +33,11 @@ properties:
backlight: true
+ spi-cpha: true
+
+ spi-cpol: true
+
spi-max-frequency:
- $ref: /schemas/types.yaml#/definitions/uint32
description: inherited as a SPI client node, the datasheet specifies
maximum 300 ns minimum cycle which gives around 3 MHz max frequency
maximum: 3000000
@@ -44,6 +47,9 @@ properties:
required:
- compatible
- reg
+ - spi-cpha
+ - spi-cpol
+ - port
additionalProperties: false
@@ -52,15 +58,23 @@ examples:
#include <dt-bindings/gpio/gpio.h>
spi {
+ compatible = "spi-gpio";
+ sck-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+ miso-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
+ mosi-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
+ num-chipselects = <1>;
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "samsung,lms397kf04";
spi-max-frequency = <3000000>;
+ spi-cpha;
+ spi-cpol;
reg = <0>;
vci-supply = <&lcd_3v0_reg>;
vccio-supply = <&lcd_1v8_reg>;
- reset-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
backlight = <&ktd259>;
port {
diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
index 151be3bba06f..39792f051d2d 100644
--- a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
+++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -23,6 +23,7 @@ Required properties:
Optional properties:
- phys: from general PHY binding: the phandle for the PHY device.
- phy-names: Should be "dphy" if phys references an external phy.
+- #phy-cells: Defined when used as ISP phy, should be 0.
- power-domains: a phandle to mipi dsi power domain node.
- resets: list of phandle + reset specifier pairs, as described in [3].
- reset-names: string reset name, must be "apb".
diff --git a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
new file mode 100644
index 000000000000..2ed2a7d0ca2f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
@@ -0,0 +1,208 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/solomon,ssd1307fb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Solomon SSD1307 OLED Controller Framebuffer
+
+maintainers:
+ - Maxime Ripard <mripard@kernel.org>
+
+properties:
+ compatible:
+ enum:
+ - solomon,ssd1305fb-i2c
+ - solomon,ssd1306fb-i2c
+ - solomon,ssd1307fb-i2c
+ - solomon,ssd1309fb-i2c
+
+ reg:
+ maxItems: 1
+
+ pwms:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ vbat-supply:
+ description: The supply for VBAT
+
+ solomon,height:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 16
+ description:
+ Height in pixel of the screen driven by the controller
+
+ solomon,width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 96
+ description:
+ Width in pixel of the screen driven by the controller
+
+ solomon,page-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 1
+ description:
+ Offset of pages (band of 8 pixels) that the screen is mapped to
+
+ solomon,segment-no-remap:
+ type: boolean
+ description:
+ Display needs normal (non-inverted) data column to segment mapping
+
+ solomon,col-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+ description:
+ Offset of columns (COL/SEG) that the screen is mapped to
+
+ solomon,com-seq:
+ type: boolean
+ description:
+ Display uses sequential COM pin configuration
+
+ solomon,com-lrremap:
+ type: boolean
+ description:
+ Display uses left-right COM pin remap
+
+ solomon,com-invdir:
+ type: boolean
+ description:
+ Display uses inverted COM pin scan direction
+
+ solomon,com-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+ description:
+ Number of the COM pin wired to the first display line
+
+ solomon,prechargep1:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 2
+ description:
+ Length of deselect period (phase 1) in clock cycles
+
+ solomon,prechargep2:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 2
+ description:
+ Length of precharge period (phase 2) in clock cycles. This needs to be
+ the higher, the higher the capacitance of the OLED's pixels is.
+
+ solomon,dclk-div:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 1
+ maximum: 16
+ description:
+ Clock divisor. The default value is controller-dependent.
+
+ solomon,dclk-frq:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 15
+ description:
+ Clock frequency, higher value means higher frequency.
+ The default value is controller-dependent.
+
+ solomon,lookup-table:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ maxItems: 4
+ description:
+ 8 bit value array of current drive pulse widths for BANK0, and colors A,
+ B, and C. Each value in range of 31 to 63 for pulse widths of 32 to 64.
+ Color D is always width 64.
+
+ solomon,area-color-enable:
+ type: boolean
+ description:
+ Display uses color mode
+
+ solomon,low-power:
+ type: boolean
+ description:
+ Display runs in low power mode
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: solomon,ssd1305fb-i2c
+ then:
+ properties:
+ solomon,dclk-div:
+ default: 1
+ solomon,dclk-frq:
+ default: 7
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: solomon,ssd1306fb-i2c
+ then:
+ properties:
+ solomon,dclk-div:
+ default: 1
+ solomon,dclk-frq:
+ default: 8
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: solomon,ssd1307fb-i2c
+ then:
+ properties:
+ solomon,dclk-div:
+ default: 2
+ solomon,dclk-frq:
+ default: 12
+ required:
+ - pwms
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: solomon,ssd1309fb-i2c
+ then:
+ properties:
+ solomon,dclk-div:
+ default: 1
+ solomon,dclk-frq:
+ default: 10
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ssd1307: oled@3c {
+ compatible = "solomon,ssd1307fb-i2c";
+ reg = <0x3c>;
+ pwms = <&pwm 4 3000>;
+ reset-gpios = <&gpio2 7>;
+ };
+
+ ssd1306: oled@3d {
+ compatible = "solomon,ssd1306fb-i2c";
+ reg = <0x3c>;
+ pwms = <&pwm 4 3000>;
+ reset-gpios = <&gpio2 7>;
+ solomon,com-lrremap;
+ solomon,com-invdir;
+ solomon,com-offset = <32>;
+ solomon,lookup-table = /bits/ 8 <0x3f 0x3f 0x3f 0x3f>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/ssd1307fb.txt b/Documentation/devicetree/bindings/display/ssd1307fb.txt
deleted file mode 100644
index 2dcb6d12d137..000000000000
--- a/Documentation/devicetree/bindings/display/ssd1307fb.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-* Solomon SSD1307 Framebuffer Driver
-
-Required properties:
- - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
- now is i2c, and the supported chips are ssd1305, ssd1306, ssd1307 and
- ssd1309.
- - reg: Should contain address of the controller on the I2C bus. Most likely
- 0x3c or 0x3d
- - pwm: Should contain the pwm to use according to the OF device tree PWM
- specification [0]. Only required for the ssd1307.
- - solomon,height: Height in pixel of the screen driven by the controller
- - solomon,width: Width in pixel of the screen driven by the controller
- - solomon,page-offset: Offset of pages (band of 8 pixels) that the screen is
- mapped to.
-
-Optional properties:
- - reset-gpios: The GPIO used to reset the OLED display, if available. See
- Documentation/devicetree/bindings/gpio/gpio.txt for details.
- - vbat-supply: The supply for VBAT
- - solomon,segment-no-remap: Display needs normal (non-inverted) data column
- to segment mapping
- - solomon,col-offset: Offset of columns (COL/SEG) that the screen is mapped to.
- - solomon,com-seq: Display uses sequential COM pin configuration
- - solomon,com-lrremap: Display uses left-right COM pin remap
- - solomon,com-invdir: Display uses inverted COM pin scan direction
- - solomon,com-offset: Number of the COM pin wired to the first display line
- - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
- - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
- This needs to be the higher, the higher the capacitance
- of the OLED's pixels is
- - solomon,dclk-div: Clock divisor 1 to 16
- - solomon,dclk-frq: Clock frequency 0 to 15, higher value means higher
- frequency
- - solomon,lookup-table: 8 bit value array of current drive pulse widths for
- BANK0, and colors A, B, and C. Each value in range
- of 31 to 63 for pulse widths of 32 to 64. Color D
- is always width 64.
- - solomon,area-color-enable: Display uses color mode
- - solomon,low-power. Display runs in low power mode
-
-[0]: Documentation/devicetree/bindings/pwm/pwm.txt
-
-Examples:
-ssd1307: oled@3c {
- compatible = "solomon,ssd1307fb-i2c";
- reg = <0x3c>;
- pwms = <&pwm 4 3000>;
- reset-gpios = <&gpio2 7>;
-};
-
-ssd1306: oled@3c {
- compatible = "solomon,ssd1306fb-i2c";
- reg = <0x3c>;
- pwms = <&pwm 4 3000>;
- reset-gpios = <&gpio2 7>;
- solomon,com-lrremap;
- solomon,com-invdir;
- solomon,com-offset = <32>;
- solomon,lookup-table = /bits/ 8 <0x3f 0x3f 0x3f 0x3f>;
-};
diff --git a/Documentation/devicetree/bindings/display/zte,vou.txt b/Documentation/devicetree/bindings/display/zte,vou.txt
deleted file mode 100644
index 38476475fd60..000000000000
--- a/Documentation/devicetree/bindings/display/zte,vou.txt
+++ /dev/null
@@ -1,120 +0,0 @@
-ZTE VOU Display Controller
-
-This is a display controller found on ZTE ZX296718 SoC. It includes multiple
-Graphic Layer (GL) and Video Layer (VL), two Mixers/Channels, and a few blocks
-handling scaling, color space conversion etc. VOU also integrates the support
-for typical output devices, like HDMI, TV Encoder, VGA, and RGB LCD.
-
-* Master VOU node
-
-It must be the parent node of all the sub-device nodes.
-
-Required properties:
- - compatible: should be "zte,zx296718-vou"
- - #address-cells: should be <1>
- - #size-cells: should be <1>
- - ranges: list of address translations between VOU and sub-devices
-
-* VOU DPC device
-
-Required properties:
- - compatible: should be "zte,zx296718-dpc"
- - reg: Physical base address and length of DPC register regions, one for each
- entry in 'reg-names'
- - reg-names: The names of register regions. The following regions are required:
- "osd"
- "timing_ctrl"
- "dtrc"
- "vou_ctrl"
- "otfppu"
- - interrupts: VOU DPC interrupt number to CPU
- - clocks: A list of phandle + clock-specifier pairs, one for each entry
- in 'clock-names'
- - clock-names: A list of clock names. The following clocks are required:
- "aclk"
- "ppu_wclk"
- "main_wclk"
- "aux_wclk"
-
-* HDMI output device
-
-Required properties:
- - compatible: should be "zte,zx296718-hdmi"
- - reg: Physical base address and length of the HDMI device IO region
- - interrupts : HDMI interrupt number to CPU
- - clocks: A list of phandle + clock-specifier pairs, one for each entry
- in 'clock-names'
- - clock-names: A list of clock names. The following clocks are required:
- "osc_cec"
- "osc_clk"
- "xclk"
-
-* TV Encoder output device
-
-Required properties:
- - compatible: should be "zte,zx296718-tvenc"
- - reg: Physical base address and length of the TVENC device IO region
- - zte,tvenc-power-control: the phandle to SYSCTRL block followed by two
- integer cells. The first cell is the offset of SYSCTRL register used
- to control TV Encoder DAC power, and the second cell is the bit mask.
-
-* VGA output device
-
-Required properties:
- - compatible: should be "zte,zx296718-vga"
- - reg: Physical base address and length of the VGA device IO region
- - interrupts : VGA interrupt number to CPU
- - clocks: Phandle with clock-specifier pointing to VGA I2C clock.
- - clock-names: Must be "i2c_wclk".
- - zte,vga-power-control: the phandle to SYSCTRL block followed by two
- integer cells. The first cell is the offset of SYSCTRL register used
- to control VGA DAC power, and the second cell is the bit mask.
-
-Example:
-
-vou: vou@1440000 {
- compatible = "zte,zx296718-vou";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 0x1440000 0x10000>;
-
- dpc: dpc@0 {
- compatible = "zte,zx296718-dpc";
- reg = <0x0000 0x1000>, <0x1000 0x1000>,
- <0x5000 0x1000>, <0x6000 0x1000>,
- <0xa000 0x1000>;
- reg-names = "osd", "timing_ctrl",
- "dtrc", "vou_ctrl",
- "otfppu";
- interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&topcrm VOU_ACLK>, <&topcrm VOU_PPU_WCLK>,
- <&topcrm VOU_MAIN_WCLK>, <&topcrm VOU_AUX_WCLK>;
- clock-names = "aclk", "ppu_wclk",
- "main_wclk", "aux_wclk";
- };
-
- vga: vga@8000 {
- compatible = "zte,zx296718-vga";
- reg = <0x8000 0x1000>;
- interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&topcrm VGA_I2C_WCLK>;
- clock-names = "i2c_wclk";
- zte,vga-power-control = <&sysctrl 0x170 0xe0>;
- };
-
- hdmi: hdmi@c000 {
- compatible = "zte,zx296718-hdmi";
- reg = <0xc000 0x4000>;
- interrupts = <GIC_SPI 82 IRQ_TYPE_EDGE_RISING>;
- clocks = <&topcrm HDMI_OSC_CEC>,
- <&topcrm HDMI_OSC_CLK>,
- <&topcrm HDMI_XCLK>;
- clock-names = "osc_cec", "osc_clk", "xclk";
- };
-
- tvenc: tvenc@2000 {
- compatible = "zte,zx296718-tvenc";
- reg = <0x2000 0x1000>;
- zte,tvenc-power-control = <&sysctrl 0x170 0x10>;
- };
-};
diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml
index c1676b96daac..a6df6f8b54db 100644
--- a/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml
@@ -19,12 +19,12 @@ properties:
description: The cell is the request line number.
compatible:
- oneOf:
- - const: allwinner,sun6i-a31-dma
- - const: allwinner,sun8i-a23-dma
- - const: allwinner,sun8i-a83t-dma
- - const: allwinner,sun8i-h3-dma
- - const: allwinner,sun8i-v3s-dma
+ enum:
+ - allwinner,sun6i-a31-dma
+ - allwinner,sun8i-a23-dma
+ - allwinner,sun8i-a83t-dma
+ - allwinner,sun8i-h3-dma
+ - allwinner,sun8i-v3s-dma
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
index c9e97409e853..12c316ff4834 100644
--- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
@@ -9,6 +9,7 @@ Required properties:
"fsl,imx53-sdma"
"fsl,imx6q-sdma"
"fsl,imx7d-sdma"
+ "fsl,imx6ul-sdma"
"fsl,imx8mq-sdma"
"fsl,imx8mm-sdma"
"fsl,imx8mn-sdma"
diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
index cebf6ffe70d5..5c4c6782e052 100644
--- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
@@ -34,6 +34,10 @@ properties:
- description: SCMI compliant firmware with ARM SMC/HVC transport
items:
- const: arm,scmi-smc
+ - description: SCMI compliant firmware with SCMI Virtio transport.
+ The virtio transport only supports a single device.
+ items:
+ - const: arm,scmi-virtio
interrupts:
description:
@@ -172,6 +176,7 @@ patternProperties:
Each sub-node represents a protocol supported. If the platform
supports a dedicated communication channel for a particular protocol,
then the corresponding transport properties must be present.
+ The virtio transport does not support a dedicated communication channel.
properties:
reg:
@@ -195,7 +200,6 @@ patternProperties:
required:
- compatible
- - shmem
if:
properties:
@@ -209,6 +213,7 @@ then:
required:
- mboxes
+ - shmem
else:
if:
@@ -219,6 +224,7 @@ else:
then:
required:
- arm,smc-id
+ - shmem
examples:
- |
diff --git a/Documentation/devicetree/bindings/firmware/arm,scpi.yaml b/Documentation/devicetree/bindings/firmware/arm,scpi.yaml
index d7113b06454b..23b346bd1252 100644
--- a/Documentation/devicetree/bindings/firmware/arm,scpi.yaml
+++ b/Documentation/devicetree/bindings/firmware/arm,scpi.yaml
@@ -131,9 +131,9 @@ properties:
properties:
compatible:
- oneOf:
- - const: arm,scpi-dvfs-clocks
- - const: arm,scpi-variable-clocks
+ enum:
+ - arm,scpi-dvfs-clocks
+ - arm,scpi-variable-clocks
'#clock-cells':
const: 1
diff --git a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
deleted file mode 100644
index 18c3aea90df2..000000000000
--- a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
+++ /dev/null
@@ -1,44 +0,0 @@
------------------------------------------------------------------
-Device Tree Bindings for the Xilinx Zynq MPSoC Firmware Interface
------------------------------------------------------------------
-
-The zynqmp-firmware node describes the interface to platform firmware.
-ZynqMP has an interface to communicate with secure firmware. Firmware
-driver provides an interface to firmware APIs. Interface APIs can be
-used by any driver to communicate to PMUFW(Platform Management Unit).
-These requests include clock management, pin control, device control,
-power management service, FPGA service and other platform management
-services.
-
-Required properties:
- - compatible: Must contain any of below:
- "xlnx,zynqmp-firmware" for Zynq Ultrascale+ MPSoC
- "xlnx,versal-firmware" for Versal
- - method: The method of calling the PM-API firmware layer.
- Permitted values are:
- - "smc" : SMC #0, following the SMCCC
- - "hvc" : HVC #0, following the SMCCC
-
--------
-Example
--------
-
-Zynq Ultrascale+ MPSoC
-----------------------
-firmware {
- zynqmp_firmware: zynqmp-firmware {
- compatible = "xlnx,zynqmp-firmware";
- method = "smc";
- ...
- };
-};
-
-Versal
-------
-firmware {
- versal_firmware: versal-firmware {
- compatible = "xlnx,versal-firmware";
- method = "smc";
- ...
- };
-};
diff --git a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.yaml b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.yaml
new file mode 100644
index 000000000000..f14f7b454f07
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/firmware/xilinx/xlnx,zynqmp-firmware.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx firmware driver
+
+maintainers:
+ - Nava kishore Manne <nava.manne@xilinx.com>
+
+description: The zynqmp-firmware node describes the interface to platform
+ firmware. ZynqMP has an interface to communicate with secure firmware.
+ Firmware driver provides an interface to firmware APIs. Interface APIs
+ can be used by any driver to communicate to PMUFW(Platform Management Unit).
+ These requests include clock management, pin control, device control,
+ power management service, FPGA service and other platform management
+ services.
+
+properties:
+ compatible:
+ oneOf:
+ - description: For implementations complying for Zynq Ultrascale+ MPSoC.
+ const: xlnx,zynqmp-firmware
+
+ - description: For implementations complying for Versal.
+ const: xlnx,versal-firmware
+
+ method:
+ description: |
+ The method of calling the PM-API firmware layer.
+ Permitted values are.
+ - "smc" : SMC #0, following the SMCCC
+ - "hvc" : HVC #0, following the SMCCC
+
+ $ref: /schemas/types.yaml#/definitions/string-array
+ enum:
+ - smc
+ - hvc
+
+ versal_fpga:
+ $ref: /schemas/fpga/xlnx,versal-fpga.yaml#
+ description: Compatible of the FPGA device.
+ type: object
+
+ zynqmp-aes:
+ $ref: /schemas/crypto/xlnx,zynqmp-aes.yaml#
+ description: The ZynqMP AES-GCM hardened cryptographic accelerator is
+ used to encrypt or decrypt the data with provided key and initialization
+ vector.
+ type: object
+
+ clock-controller:
+ $ref: /schemas/clock/xlnx,versal-clk.yaml#
+ description: The clock controller is a hardware block of Xilinx versal
+ clock tree. It reads required input clock frequencies from the devicetree
+ and acts as clock provider for all clock consumers of PS clocks.list of
+ clock specifiers which are external input clocks to the given clock
+ controller.
+ type: object
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ versal-firmware {
+ compatible = "xlnx,versal-firmware";
+ method = "smc";
+
+ versal_fpga: versal_fpga {
+ compatible = "xlnx,versal-fpga";
+ };
+
+ xlnx_aes: zynqmp-aes {
+ compatible = "xlnx,zynqmp-aes";
+ };
+
+ versal_clk: clock-controller {
+ #clock-cells = <1>;
+ compatible = "xlnx,versal-clk";
+ clocks = <&ref>, <&alt_ref>, <&pl_alt_ref>;
+ clock-names = "ref", "alt_ref", "pl_alt_ref";
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.yaml b/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.yaml
new file mode 100644
index 000000000000..ac6a207278d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.yaml
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fpga/xlnx,versal-fpga.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Versal FPGA driver.
+
+maintainers:
+ - Nava kishore Manne <nava.manne@xilinx.com>
+
+description: |
+ Device Tree Versal FPGA bindings for the Versal SoC, controlled
+ using firmware interface.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - xlnx,versal-fpga
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ versal_fpga: versal_fpga {
+ compatible = "xlnx,versal-fpga";
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt b/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt
deleted file mode 100644
index 3052bf619dd5..000000000000
--- a/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Devicetree bindings for Zynq Ultrascale MPSoC FPGA Manager.
-The ZynqMP SoC uses the PCAP (Processor configuration Port) to configure the
-Programmable Logic (PL). The configuration uses the firmware interface.
-
-Required properties:
-- compatible: should contain "xlnx,zynqmp-pcap-fpga"
-
-Example for full FPGA configuration:
-
- fpga-region0 {
- compatible = "fpga-region";
- fpga-mgr = <&zynqmp_pcap>;
- #address-cells = <0x1>;
- #size-cells = <0x1>;
- };
-
- firmware {
- zynqmp_firmware: zynqmp-firmware {
- compatible = "xlnx,zynqmp-firmware";
- method = "smc";
- zynqmp_pcap: pcap {
- compatible = "xlnx,zynqmp-pcap-fpga";
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.yaml b/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.yaml
new file mode 100644
index 000000000000..6cd2bdc06b5f
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.yaml
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fpga/xlnx,zynqmp-pcap-fpga.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Zynq Ultrascale MPSoC FPGA Manager Device Tree Bindings
+
+maintainers:
+ - Nava kishore Manne <navam@xilinx.com>
+
+description: |
+ Device Tree Bindings for Zynq Ultrascale MPSoC FPGA Manager.
+ The ZynqMP SoC uses the PCAP (Processor Configuration Port) to
+ configure the Programmable Logic (PL). The configuration uses the
+ firmware interface.
+
+properties:
+ compatible:
+ const: xlnx,zynqmp-pcap-fpga
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ firmware {
+ zynqmp_firmware: zynqmp-firmware {
+ zynqmp_pcap: pcap {
+ compatible = "xlnx,zynqmp-pcap-fpga";
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml b/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml
new file mode 100644
index 000000000000..46bb121360dc
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/aspeed,sgpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Aspeed SGPIO controller
+
+maintainers:
+ - Andrew Jeffery <andrew@aj.id.au>
+
+description:
+ This SGPIO controller is for ASPEED AST2400, AST2500 and AST2600 SoC,
+ AST2600 have two sgpio master one with 128 pins another one with 80 pins,
+ AST2500/AST2400 have one sgpio master with 80 pins. Each of the Serial
+ GPIO pins can be programmed to support the following options
+ - Support interrupt option for each input port and various interrupt
+ sensitivity option (level-high, level-low, edge-high, edge-low)
+ - Support reset tolerance option for each output port
+ - Directly connected to APB bus and its shift clock is from APB bus clock
+ divided by a programmable value.
+ - Co-work with external signal-chained TTL components (74LV165/74LV595)
+
+properties:
+ compatible:
+ enum:
+ - aspeed,ast2400-sgpio
+ - aspeed,ast2500-sgpio
+ - aspeed,ast2600-sgpiom
+
+ reg:
+ maxItems: 1
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ clocks:
+ maxItems: 1
+
+ ngpios: true
+
+ bus-frequency: true
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - '#gpio-cells'
+ - interrupts
+ - interrupt-controller
+ - ngpios
+ - clocks
+ - bus-frequency
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/aspeed-clock.h>
+ sgpio: sgpio@1e780200 {
+ #gpio-cells = <2>;
+ compatible = "aspeed,ast2500-sgpio";
+ gpio-controller;
+ interrupts = <40>;
+ reg = <0x1e780200 0x0100>;
+ clocks = <&syscon ASPEED_CLK_APB>;
+ interrupt-controller;
+ ngpios = <80>;
+ bus-frequency = <12000000>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
deleted file mode 100644
index be329ea4794f..000000000000
--- a/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-Aspeed SGPIO controller Device Tree Bindings
---------------------------------------------
-
-This SGPIO controller is for ASPEED AST2500 SoC, it supports up to 80 full
-featured Serial GPIOs. Each of the Serial GPIO pins can be programmed to
-support the following options:
-- Support interrupt option for each input port and various interrupt
- sensitivity option (level-high, level-low, edge-high, edge-low)
-- Support reset tolerance option for each output port
-- Directly connected to APB bus and its shift clock is from APB bus clock
- divided by a programmable value.
-- Co-work with external signal-chained TTL components (74LV165/74LV595)
-
-Required properties:
-
-- compatible : Should be one of
- "aspeed,ast2400-sgpio", "aspeed,ast2500-sgpio"
-- #gpio-cells : Should be 2, see gpio.txt
-- reg : Address and length of the register set for the device
-- gpio-controller : Marks the device node as a GPIO controller
-- interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt
-- interrupt-controller : Mark the GPIO controller as an interrupt-controller
-- ngpios : number of *hardware* GPIO lines, see gpio.txt. This will expose
- 2 software GPIOs per hardware GPIO: one for hardware input, one for hardware
- output. Up to 80 pins, must be a multiple of 8.
-- clocks : A phandle to the APB clock for SGPM clock division
-- bus-frequency : SGPM CLK frequency
-
-The sgpio and interrupt properties are further described in their respective
-bindings documentation:
-
-- Documentation/devicetree/bindings/gpio/gpio.txt
-- Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
-
- Example:
- sgpio: sgpio@1e780200 {
- #gpio-cells = <2>;
- compatible = "aspeed,ast2500-sgpio";
- gpio-controller;
- interrupts = <40>;
- reg = <0x1e780200 0x0100>;
- clocks = <&syscon ASPEED_CLK_APB>;
- interrupt-controller;
- ngpios = <8>;
- bus-frequency = <12000000>;
- };
diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml
index 0f73f436bea7..c5f6092a2855 100644
--- a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml
@@ -20,6 +20,7 @@ properties:
- mediatek,mt8183-mali
- realtek,rtd1619-mali
- rockchip,px30-mali
+ - rockchip,rk3568-mali
- const: arm,mali-bifrost # Mali Bifrost GPU model/revision is fully discoverable
reg:
diff --git a/Documentation/devicetree/bindings/hwmon/max1619.txt b/Documentation/devicetree/bindings/hwmon/max1619.txt
deleted file mode 100644
index c70dbbe1e56f..000000000000
--- a/Documentation/devicetree/bindings/hwmon/max1619.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Bindings for MAX1619 Temperature Sensor
-
-Required properties:
-- compatible : "maxim,max1619"
-- reg : I2C address, one of 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, or
- 0x4d, 0x4e
-
-Example:
- temp@4c {
- compatible = "maxim,max1619";
- reg = <0x4c>;
- };
diff --git a/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.txt b/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.txt
deleted file mode 100644
index d12cc33cca6c..000000000000
--- a/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-Broadcom iProc I2C controller
-
-Required properties:
-
-- compatible:
- Must be "brcm,iproc-i2c" or "brcm,iproc-nic-i2c"
-
-- reg:
- Define the base and range of the I/O address space that contain the iProc
- I2C controller registers
-
-- clock-frequency:
- This is the I2C bus clock. Need to be either 100000 or 400000
-
-- #address-cells:
- Always 1 (for I2C addresses)
-
-- #size-cells:
- Always 0
-
-Optional properties:
-
-- interrupts:
- Should contain the I2C interrupt. For certain revisions of the I2C
- controller, I2C interrupt is unwired to the interrupt controller. In such
- case, this property should be left unspecified, and driver will fall back
- to polling mode
-
-- brcm,ape-hsls-addr-mask:
- Required for "brcm,iproc-nic-i2c". Host view of address mask into the
- 'APE' co-processor. Value must be unsigned, 32-bit
-
-Example:
- i2c0: i2c@18008000 {
- compatible = "brcm,iproc-i2c";
- reg = <0x18008000 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
- clock-frequency = <100000>;
-
- codec: wm8750@1a {
- compatible = "wlf,wm8750";
- reg = <0x1a>;
- };
- };
diff --git a/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.yaml b/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.yaml
new file mode 100644
index 000000000000..2aa75b7add7b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/brcm,iproc-i2c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom iProc I2C controller
+
+maintainers:
+ - Rafał Miłecki <rafal@milecki.pl>
+
+properties:
+ compatible:
+ enum:
+ - brcm,iproc-i2c
+ - brcm,iproc-nic-i2c
+
+ reg:
+ maxItems: 1
+
+ clock-frequency:
+ enum: [ 100000, 400000 ]
+
+ interrupts:
+ description: |
+ Should contain the I2C interrupt. For certain revisions of the I2C
+ controller, I2C interrupt is unwired to the interrupt controller. In such
+ case, this property should be left unspecified, and driver will fall back
+ to polling mode
+ maxItems: 1
+
+ brcm,ape-hsls-addr-mask:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Host view of address mask into the 'APE' co-processor
+
+allOf:
+ - $ref: /schemas/i2c/i2c-controller.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: brcm,iproc-nic-i2c
+ then:
+ required:
+ - brcm,ape-hsls-addr-mask
+
+unevaluatedProperties: false
+
+required:
+ - reg
+ - clock-frequency
+ - '#address-cells'
+ - '#size-cells'
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ i2c@18008000 {
+ compatible = "brcm,iproc-i2c";
+ reg = <0x18008000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
+ clock-frequency = <100000>;
+
+ wm8750@1a {
+ compatible = "wlf,wm8750";
+ reg = <0x1a>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/i2c/renesas,riic.yaml b/Documentation/devicetree/bindings/i2c/renesas,riic.yaml
index 52d92ec7ec0b..402fd125e010 100644
--- a/Documentation/devicetree/bindings/i2c/renesas,riic.yaml
+++ b/Documentation/devicetree/bindings/i2c/renesas,riic.yaml
@@ -27,14 +27,25 @@ properties:
interrupts:
items:
- - description: Transmit End Interrupt (TEI)
- - description: Receive Data Full Interrupt (RI)
- - description: Transmit Data Empty Interrupt (TI)
- - description: Stop Condition Detection Interrupt (SPI)
- - description: Start Condition Detection Interrupt (STI)
- - description: NACK Reception Interrupt (NAKI)
- - description: Arbitration-Lost Interrupt (ALI)
- - description: Timeout Interrupt (TMOI)
+ - description: Transmit End Interrupt
+ - description: Receive Data Full Interrupt
+ - description: Transmit Data Empty Interrupt
+ - description: Stop Condition Detection Interrupt
+ - description: Start Condition Detection Interrupt
+ - description: NACK Reception Interrupt
+ - description: Arbitration-Lost Interrupt
+ - description: Timeout Interrupt
+
+ interrupt-names:
+ items:
+ - const: tei
+ - const: ri
+ - const: ti
+ - const: spi
+ - const: sti
+ - const: naki
+ - const: ali
+ - const: tmoi
clock-frequency:
description:
@@ -51,6 +62,7 @@ required:
- compatible
- reg
- interrupts
+ - interrupt-names
- clocks
- clock-frequency
- power-domains
@@ -85,6 +97,8 @@ examples:
<GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti", "naki", "ali",
+ "tmoi";
clocks = <&mstp9_clks R7S72100_CLK_I2C0>;
clock-frequency = <100000>;
power-domains = <&cpg_clocks>;
diff --git a/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml b/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml
index ff165ad1bee8..db0843be91c5 100644
--- a/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml
@@ -72,11 +72,11 @@ additionalProperties: false
if:
properties:
compatible:
- oneOf:
- - const: ti,omap2420-i2c
- - const: ti,omap2430-i2c
- - const: ti,omap3-i2c
- - const: ti,omap4-i2c
+ enum:
+ - ti,omap2420-i2c
+ - ti,omap2430-i2c
+ - ti,omap3-i2c
+ - ti,omap4-i2c
then:
properties:
diff --git a/Documentation/devicetree/bindings/iio/accel/bosch,bma180.yaml b/Documentation/devicetree/bindings/iio/accel/bosch,bma180.yaml
deleted file mode 100644
index a7e84089cc3d..000000000000
--- a/Documentation/devicetree/bindings/iio/accel/bosch,bma180.yaml
+++ /dev/null
@@ -1,61 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/iio/accel/bosch,bma180.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Bosch BMA023 / BMA150/ BMA180 / BMA250 / SMB380 triaxial accelerometers
-
-maintainers:
- - Jonathan Cameron <jic23@kernel.org>
-
-description: |
- https://media.digikey.com/pdf/Data%20Sheets/Bosch/BMA150.pdf
- http://omapworld.com/BMA180_111_1002839.pdf
- http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf
-
-properties:
- compatible:
- enum:
- - bosch,bma023
- - bosch,bma150
- - bosch,bma180
- - bosch,bma250
- - bosch,smb380
-
- reg:
- maxItems: 1
-
- vdd-supply: true
-
- vddio-supply: true
-
- interrupts:
- minItems: 1
- maxItems: 2
- description: |
- Type should be either IRQ_TYPE_LEVEL_HIGH or IRQ_TYPE_EDGE_RISING.
- For the bma250 the first interrupt listed must be the one
- connected to the INT1 pin, the second (optional) interrupt
- listed must be the one connected to the INT2 pin.
-
-required:
- - compatible
- - reg
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/interrupt-controller/irq.h>
- i2c {
- #address-cells = <1>;
- #size-cells = <0>;
- accel@40 {
- compatible = "bosch,bma180";
- reg = <0x40>;
- interrupt-parent = <&gpio6>;
- interrupts = <18 (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING)>;
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml b/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
index e830d5295b92..478e75ae0885 100644
--- a/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
@@ -8,6 +8,7 @@ title: Bosch BMA255 and Similar Accelerometers
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
+ - Stephan Gerhold <stephan@gerhold.net>
description:
3 axis accelerometers with varying range and I2C or SPI
@@ -16,15 +17,24 @@ description:
properties:
compatible:
enum:
- - bosch,bmc150_accel
- - bosch,bmi055_accel
+ # bmc150-accel driver in Linux
+ - bosch,bma222
+ - bosch,bma222e
+ - bosch,bma250e
- bosch,bma253
- bosch,bma254
- bosch,bma255
- - bosch,bma250e
- - bosch,bma222
- - bosch,bma222e
- bosch,bma280
+ - bosch,bmc150_accel
+ - bosch,bmc156_accel
+ - bosch,bmi055_accel
+
+ # bma180 driver in Linux
+ - bosch,bma023
+ - bosch,bma150
+ - bosch,bma180
+ - bosch,bma250
+ - bosch,smb380
reg:
maxItems: 1
@@ -36,9 +46,21 @@ properties:
minItems: 1
maxItems: 2
description: |
- The first interrupt listed must be the one connected to the INT1 pin,
- the second (optional) interrupt listed must be the one connected to the
- INT2 pin (if available).
+ Without interrupt-names, the first interrupt listed must be the one
+ connected to the INT1 pin, the second (optional) interrupt listed must be
+ the one connected to the INT2 pin (if available). The type should be
+ IRQ_TYPE_EDGE_RISING.
+
+ BMC156 does not have an INT1 pin, therefore the first interrupt pin is
+ always treated as INT2.
+
+ interrupt-names:
+ minItems: 1
+ maxItems: 2
+ items:
+ enum:
+ - INT1
+ - INT2
mount-matrix:
description: an optional 3x3 mounting rotation matrix.
@@ -63,7 +85,22 @@ examples:
reg = <0x08>;
vddio-supply = <&vddio>;
vdd-supply = <&vdd>;
- interrupts = <57 IRQ_TYPE_EDGE_FALLING>;
+ interrupts = <57 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "INT1";
+ };
+ };
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ accelerometer@10 {
+ compatible = "bosch,bmc156_accel";
+ reg = <0x10>;
+ vddio-supply = <&vddio>;
+ vdd-supply = <&vdd>;
+ interrupts = <116 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "INT2";
};
};
- |
diff --git a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml
index 433a3fb55a2e..3eb7aa8822c3 100644
--- a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml
@@ -23,6 +23,8 @@ properties:
enum:
- ingenic,jz4725b-adc
- ingenic,jz4740-adc
+ - ingenic,jz4760-adc
+ - ingenic,jz4760b-adc
- ingenic,jz4770-adc
'#io-channel-cells':
@@ -43,6 +45,23 @@ properties:
interrupts:
maxItems: 1
+ ingenic,use-internal-divider:
+ description:
+ If present, battery voltage is read from the VBAT_IR pin, which has an
+ internal 1/4 divider. If absent, it is read through the VBAT_ER pin,
+ which does not have such a divider.
+ type: boolean
+
+if:
+ not:
+ properties:
+ compatible:
+ contains:
+ const: ingenic,jz4760b-adc
+then:
+ properties:
+ ingenic,use-internal-divider: false
+
required:
- compatible
- '#io-channel-cells'
diff --git a/Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml b/Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml
new file mode 100644
index 000000000000..c80201d6a716
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml
@@ -0,0 +1,134 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/renesas,rzg2l-adc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L ADC
+
+maintainers:
+ - Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+description: |
+ A/D Converter block is a successive approximation analog-to-digital converter
+ with a 12-bit accuracy. Up to eight analog input channels can be selected.
+ Conversions can be performed in single or repeat mode. Result of the ADC is
+ stored in a 32-bit data register corresponding to each channel.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a07g044-adc # RZ/G2{L,LC}
+ - const: renesas,rzg2l-adc
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: converter clock
+ - description: peripheral clock
+
+ clock-names:
+ items:
+ - const: adclk
+ - const: pclk
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 2
+
+ reset-names:
+ items:
+ - const: presetn
+ - const: adrst-n
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - power-domains
+ - resets
+ - reset-names
+
+patternProperties:
+ "^channel@[0-7]$":
+ $ref: "adc.yaml"
+ type: object
+ description: |
+ Represents the external channels which are connected to the ADC.
+
+ properties:
+ reg:
+ description: |
+ The channel number. It can have up to 8 channels numbered from 0 to 7.
+ items:
+ - minimum: 0
+ maximum: 7
+
+ required:
+ - reg
+
+ additionalProperties: false
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ adc: adc@10059000 {
+ compatible = "renesas,r9a07g044-adc", "renesas,rzg2l-adc";
+ reg = <0x10059000 0x400>;
+ interrupts = <GIC_SPI 347 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&cpg CPG_MOD R9A07G044_ADC_ADCLK>,
+ <&cpg CPG_MOD R9A07G044_ADC_PCLK>;
+ clock-names = "adclk", "pclk";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G044_ADC_PRESETN>,
+ <&cpg R9A07G044_ADC_ADRST_N>;
+ reset-names = "presetn", "adrst-n";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ reg = <0>;
+ };
+ channel@1 {
+ reg = <1>;
+ };
+ channel@2 {
+ reg = <2>;
+ };
+ channel@3 {
+ reg = <3>;
+ };
+ channel@4 {
+ reg = <4>;
+ };
+ channel@5 {
+ reg = <5>;
+ };
+ channel@6 {
+ reg = <6>;
+ };
+ channel@7 {
+ reg = <7>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml
index 1bb76197787b..e512a14e41b4 100644
--- a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml
@@ -20,6 +20,7 @@ properties:
- rockchip,px30-saradc
- rockchip,rk3308-saradc
- rockchip,rk3328-saradc
+ - rockchip,rk3568-saradc
- rockchip,rv1108-saradc
- const: rockchip,rk3399-saradc
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5064.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5064.yaml
new file mode 100644
index 000000000000..05ed4e0ec364
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5064.yaml
@@ -0,0 +1,268 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5064.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5064 and similar DACs
+
+maintainers:
+ - Lars-Peter Clausen <lars@metafoo.de>
+ - Jonathan Cameron <jic23@kernel.org>
+
+description: |
+ A range of similar DAC devices with between 1 and 12 channels. Some parts
+ have internal references, others require a single shared external reference
+ and the remainder have a separate reference pin for each DAC.
+
+properties:
+ compatible:
+ oneOf:
+ - description: I2C devics
+ enum:
+ - adi,ad5024
+ - adi,ad5025
+ - adi,ad5044
+ - adi,ad5045
+ - adi,ad5064
+ - adi,ad5064-1
+ - adi,ad5065
+ - adi,ad5628-1
+ - adi,ad5628-2
+ - adi,ad5648-1
+ - adi,ad5648-2
+ - adi,ad5666-1
+ - adi,ad5666-2
+ - adi,ad5668-1
+ - adi,ad5668-2
+ - adi,ad5668-3
+ - description: SPI devices
+ enum:
+ - adi,ad5625
+ - adi,ad5625r-1v25
+ - adi,ad5625r-2v5
+ - adi,ad5627
+ - adi,ad5627r-1v25
+ - adi,ad5627r-2v5
+ - adi,ad5629-1
+ - adi,ad5629-2
+ - adi,ad5629-3
+ - adi,ad5645r-1v25
+ - adi,ad5645r-2v5
+ - adi,ad5665
+ - adi,ad5665r-1v25
+ - adi,ad5665r-2v5
+ - adi,ad5667
+ - adi,ad5667r-1v25
+ - adi,ad5667r-2v5
+ - adi,ad5669-1
+ - adi,ad5669-2
+ - adi,ad5669-3
+ - lltc,ltc2606
+ - lltc,ltc2607
+ - lltc,ltc2609
+ - lltc,ltc2616
+ - lltc,ltc2617
+ - lltc,ltc2619
+ - lltc,ltc2626
+ - lltc,ltc2627
+ - lltc,ltc2629
+ - lltc,ltc2631-l12
+ - lltc,ltc2631-h12
+ - lltc,ltc2631-l10
+ - lltc,ltc2631-h10
+ - lltc,ltc2631-l8
+ - lltc,ltc2631-h8
+ - lltc,ltc2633-l12
+ - lltc,ltc2633-h12
+ - lltc,ltc2633-l10
+ - lltc,ltc2633-h10
+ - lltc,ltc2633-l8
+ - lltc,ltc2633-h8
+ - lltc,ltc2635-l12
+ - lltc,ltc2635-h12
+ - lltc,ltc2635-l10
+ - lltc,ltc2635-h10
+ - lltc,ltc2635-l8
+ - lltc,ltc2635-h8
+
+ reg:
+ maxItems: 1
+
+ vrefA-supply: true
+ vrefB-supply: true
+ vrefC-supply: true
+ vrefD-supply: true
+ vref-supply: true
+
+ spi-max-frequency: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - # Shared external vref, no internal reference
+ if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5064-1
+ - adi,ad5625
+ - adi,ad5627
+ - adi,ad5665
+ - adi,ad5667
+ - lltc,ltc2606
+ - lltc,ltc2607
+ - lltc,ltc2616
+ - lltc,ltc2617
+ - lltc,ltc2626
+ - lltc,ltc2627
+ then:
+ properties:
+ vref-supply: true
+ vrefA-supply: false
+ vrefB-supply: false
+ vrefC-supply: false
+ vrefD-supply: false
+ required:
+ - vref-supply
+ - # Shared external vref, internal reference available
+ if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5625r-1v25
+ - adi,ad5625r-2v5
+ - adi,ad5627r-1v25
+ - adi,ad5627r-2v5
+ - adi,ad5628-1
+ - adi,ad5628-2
+ - adi,ad5629-1
+ - adi,ad5629-2
+ - adi,ad5629-3
+ - adi,ad5645r-1v25
+ - adi,ad5645r-2v5
+ - adi,ad5647r-1v25
+ - adi,ad5647r-2v5
+ - adi,ad5648-1
+ - adi,ad5648-2
+ - adi,ad5665r-1v25
+ - adi,ad5665r-2v5
+ - adi,ad5666-1
+ - adi,ad5666-2
+ - adi,ad5667r-1v25
+ - adi,ad5667r-2v5
+ - adi,ad5668-1
+ - adi,ad5668-2
+ - adi,ad5668-3
+ - adi,ad5669-1
+ - adi,ad5669-2
+ - adi,ad5669-3
+ - lltc,ltc2631-l12
+ - lltc,ltc2631-h12
+ - lltc,ltc2631-l10
+ - lltc,ltc2631-h10
+ - lltc,ltc2631-l8
+ - lltc,ltc2631-h8
+ - lltc,ltc2633-l12
+ - lltc,ltc2633-h12
+ - lltc,ltc2633-l10
+ - lltc,ltc2633-h10
+ - lltc,ltc2633-l8
+ - lltc,ltc2633-h8
+ - lltc,ltc2635-l12
+ - lltc,ltc2635-h12
+ - lltc,ltc2635-l10
+ - lltc,ltc2635-h10
+ - lltc,ltc2635-l8
+ - lltc,ltc2635-h8
+ then:
+ properties:
+ vref-supply: true
+ vrefA-supply: false
+ vrefB-supply: false
+ vrefC-supply: false
+ vrefD-supply: false
+ - # 4 input devices, separate vrefs, no internal reference
+ if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5024
+ - adi,ad5044
+ - adi,ad5064
+ - lltc,ltc2609
+ - lltc,ltc2619
+ - lltc,ltc2629
+ then:
+ properties:
+ vrefA-supply: true
+ vrefB-supply: true
+ vrefC-supply: true
+ vrefD-supply: true
+ vref-supply: false
+ required:
+ - vrefA-supply
+ - vrefB-supply
+ - vrefC-supply
+ - vrefD-supply
+ - # 2 input devices, separate vrefs, no internal reference
+ if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5025
+ - adi,ad5045
+ - adi,ad5065
+ then:
+ properties:
+ vrefA-supply: true
+ vrefB-supply: true
+ vrefC-supply: false
+ vrefD-supply: false
+ vref-supply: false
+ required:
+ - vrefA-supply
+ - vrefB-supply
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5625";
+ vref-supply = <&dac_vref>;
+ };
+ };
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5625r-1v25";
+ };
+ };
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@42 {
+ reg = <0x42>;
+ compatible = "adi,ad5024";
+ vrefA-supply = <&dac_vref>;
+ vrefB-supply = <&dac_vref>;
+ vrefC-supply = <&dac_vref2>;
+ vrefD-supply = <&dac_vref2>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5360.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5360.yaml
new file mode 100644
index 000000000000..0d8fb56f4b09
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5360.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5360.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5360 and similar DACs
+
+maintainers:
+ - Lars-Peter Clausen <lars@metafoo.de>
+ - Jonathan Cameron <jic23@kernel.org>
+
+properties:
+ compatible:
+ enum:
+ - adi,ad5360
+ - adi,ad5361
+ - adi,ad5363
+ - adi,ad5370
+ - adi,ad5371
+ - adi,ad5372
+ - adi,ad5373
+
+ reg:
+ maxItems: 1
+
+ vref0-supply: true
+ vref1-supply: true
+ vref2-supply: true
+
+ spi-max-frequency: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - vref0-supply
+ - vref1-supply
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5360
+ - adi,ad5361
+ - adi,ad5363
+ - adi,ad5370
+ - adi,ad5372
+ - adi,ad5373
+ then:
+ properties:
+ vref2-supply: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5371
+ then:
+ required:
+ - vref2-supply
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5371";
+ vref0-supply = <&dac_vref0>;
+ vref1-supply = <&dac_vref1>;
+ vref2-supply = <&dac_vref2>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5380.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5380.yaml
new file mode 100644
index 000000000000..d599b418a020
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5380.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5380.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5380 and similar DACs
+
+maintainers:
+ - Lars-Peter Clausen <lars@metafoo.de>
+ - Jonathan Cameron <jic23@kernel.org>
+
+description: |
+ DAC devices supporting both SPI and I2C interfaces.
+properties:
+ compatible:
+ enum:
+ - adi,ad5380-3
+ - adi,ad5380-5
+ - adi,ad5381-3
+ - adi,ad5381-5
+ - adi,ad5382-3
+ - adi,ad5382-5
+ - adi,ad5383-3
+ - adi,ad5383-5
+ - adi,ad5384-3
+ - adi,ad5384-5
+ - adi,ad5390-3
+ - adi,ad5390-5
+ - adi,ad5391-3
+ - adi,ad5391-5
+ - adi,ad5392-3
+ - adi,ad5392-5
+
+ reg:
+ maxItems: 1
+
+ vref-supply:
+ description:
+ If not supplied devices will use internal regulators.
+
+ spi-max-frequency: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5390-5";
+ vref-supply = <&dacvref>;
+ };
+ };
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@42 {
+ reg = <0x42>;
+ compatible = "adi,ad5380-3";
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5421.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5421.yaml
new file mode 100644
index 000000000000..188f656617e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5421.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5421.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5421 DAC
+
+maintainers:
+ - Lars-Peter Clausen <lars@metafoo.de>
+ - Jonathan Cameron <jic23@kernel.org>
+
+description: |
+ AD5421 is designed for us in loop-powered, 4 mA to 20 mA smart transmitter
+ applications. It provides a 16-bit DAC, current amplifier, voltage regulator
+ to drive the loop and a voltage reference.
+
+properties:
+ compatible:
+ const: adi,ad5421
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+ description: Fault signal.
+
+ spi-max-frequency: true
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad5421";
+ reg = <0>;
+ spi-max-frequency = <30000000>;
+ interrupts = <55 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5449.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5449.yaml
new file mode 100644
index 000000000000..044332c97743
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5449.yaml
@@ -0,0 +1,97 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5449.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5449 and similar DACs
+
+maintainers:
+ - Lars-Peter Clausen <lars@metafoo.de>
+ - Jonathan Cameron <jic23@kernel.org>
+
+description:
+ Family of multiplying DACs from Analog Devices
+
+properties:
+ compatible:
+ enum:
+ - adi,ad5415
+ - adi,ad5426
+ - adi,ad5429
+ - adi,ad5432
+ - adi,ad5439
+ - adi,ad5443
+ - adi,ad5449
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency: true
+
+ VREF-supply: true
+ VREFA-supply: true
+ VREFB-supply: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5415
+ - adi,ad5426
+ - adi,ad5432
+ then:
+ properties:
+ VREF-supply: true
+ VREFA-supply: false
+ VREFB-supply: false
+ required:
+ - VREF-supply
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5429
+ - adi,ad5439
+ - adi,ad5449
+ then:
+ properties:
+ VREF-supply: false
+ VREFA-supply: true
+ VREFB-supply: true
+ required:
+ - VREFA-supply
+ - VREFB-supply
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5415";
+ VREF-supply = <&dac_ref>;
+ };
+ };
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5429";
+ VREFA-supply = <&dac_refA>;
+ VREFB-supply = <&dac_refB>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml
new file mode 100644
index 000000000000..9c2c038683b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5504.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5501 and AD5504 DACs
+
+maintainers:
+ - Lars-Peter Clausen <lars@metafoo.de>
+ - Jonathan Cameron <jic23@kernel.org>
+
+description:
+ High voltage (up to 60V) DACs with temperature sensor alarm function
+
+properties:
+ compatible:
+ enum:
+ - adi,ad5501
+ - adi,ad5504
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ description: Used for temperature alarm.
+ maxItems: 1
+
+ vcc-supply: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5504";
+ vcc-supply = <&dac_vcc>;
+ interrupts = <55 IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5624r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5624r.yaml
new file mode 100644
index 000000000000..330383b85eeb
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5624r.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5624r.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5624r and similar DACs
+
+maintainers:
+ - Jonathan Cameron <jic23@kernel.org>
+
+properties:
+ compatible:
+ enum:
+ - adi,ad5624r3
+ - adi,ad5644r3
+ - adi,ad5664r3
+ - adi,ad5624r5
+ - adi,ad5644r5
+ - adi,ad5664r5
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency: true
+
+ vref-supply:
+ description: If not present, internal reference will be used.
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5624r3";
+ vref-supply = <&vref>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5686.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5686.yaml
new file mode 100644
index 000000000000..5c26441eae9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5686.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5686.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5360 and similar DACs
+
+maintainers:
+ - Michael Hennerich <michael.hennerich@analog.com>
+ - Jonathan Cameron <jic23@kernel.org>
+
+properties:
+ compatible:
+ oneOf:
+ - description: SPI devices
+ enum:
+ - adi,ad5310r
+ - adi,ad5672r
+ - adi,ad5674r
+ - adi,ad5676
+ - adi,ad5676r
+ - adi,ad5679r
+ - adi,ad5681r
+ - adi,ad5682r
+ - adi,ad5683
+ - adi,ad5683r
+ - adi,ad5684
+ - adi,ad5684r
+ - adi,ad5685r
+ - adi,ad5686
+ - adi,ad5686r
+ - description: I2C devices
+ enum:
+ - adi,ad5311r
+ - adi,ad5338r
+ - adi,ad5671r
+ - adi,ad5675r
+ - adi,ad5691r
+ - adi,ad5692r
+ - adi,ad5693
+ - adi,ad5693r
+ - adi,ad5694
+ - adi,ad5694r
+ - adi,ad5695r
+ - adi,ad5696
+ - adi,ad5696r
+
+
+ reg:
+ maxItems: 1
+
+ vcc-supply:
+ description: If not supplied the internal reference is used.
+
+ spi-max-frequency: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dac@0 {
+ reg = <0>;
+ compatible = "adi,ad5310r";
+ vcc-supply = <&dac_vref0>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5761.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5761.yaml
new file mode 100644
index 000000000000..7f95a9ed55fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5761.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5761.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5761 and similar DACs
+
+maintainers:
+ - Ricardo Ribalda <ribalda@kernel.org>
+ - Jonathan Cameron <jic23@kernel.org>
+
+properties:
+
+ compatible:
+ enum:
+ - adi,ad5721
+ - adi,ad5721r
+ - adi,ad5761
+ - adi,ad5761r
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency: true
+
+ vref-supply:
+ description: If not supplied, internal reference will be used.
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5721
+ - adi,ad5761
+ then:
+ required:
+ - vref-supply
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad5721";
+ reg = <0>;
+ vref-supply = <&dac_vref>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5764.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5764.yaml
new file mode 100644
index 000000000000..8e893d52bfb1
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5764.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5764.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5744 and AD5764 DAC families
+
+maintainers:
+ - Lars-Peter Clausen <lars@metafoo.de>
+ - Jonathan Cameron <jic23@kernel.org>
+
+properties:
+
+ compatible:
+ enum:
+ - adi,ad5744
+ - adi,ad5744r
+ - adi,ad5764
+ - adi,ad5764r
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency: true
+
+ vrefAB-supply: true
+ vrefCD-supply: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad5744
+ - adi,ad5764
+ then:
+ required:
+ - vrefAB-supply
+ - vrefCD-supply
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad5744";
+ reg = <0>;
+ vrefAB-supply = <&dac_vref>;
+ vrefCD-supply = <&dac_vref>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml
new file mode 100644
index 000000000000..650d1ebdcec3
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad5791.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD5791 and similar DACs
+
+maintainers:
+ - Michael Hennerich <michael.hennerich@analog.com>
+ - Jonathan Cameron <jic23@kernel.org>
+
+properties:
+
+ compatible:
+ enum:
+ - adi,ad5760
+ - adi,ad5780
+ - adi,ad5781
+ - adi,ad5790
+ - adi,ad5791
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency: true
+
+ vdd-supply: true
+ vss-supply: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vss-supply
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad5791";
+ reg = <0>;
+ vss-supply = <&dac_vss>;
+ vdd-supply = <&dac_vdd>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad8801.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad8801.yaml
new file mode 100644
index 000000000000..6a3990a8d0ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad8801.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad8801.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD8801 and AD8803 DACs
+
+maintainers:
+ - Jonathan Cameron <jic23@kernel.org>
+
+properties:
+
+ compatible:
+ enum:
+ - adi,ad8801
+ - adi,ad8803
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency: true
+
+ vrefh-supply: true
+ vrefl-supply: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - vrefh-supply
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: adi,ad8803
+ then:
+ required:
+ - vrefl-supply
+ else:
+ properties:
+ vrefl-supply: false
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad8803";
+ reg = <0>;
+ vrefl-supply = <&dac_vrefl>;
+ vrefh-supply = <&dac_vrefh>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/microchip,mcp4922.yaml b/Documentation/devicetree/bindings/iio/dac/microchip,mcp4922.yaml
new file mode 100644
index 000000000000..12a14b3f36cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/microchip,mcp4922.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/microchip,mcp4922.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip MCP4902, MCP4912 and MPC4922 dual output SPI DACs
+
+maintainers:
+ - Jonathan Cameron <jic23@kernel.org>
+ - Michael Welling <mwelling@ieee.org>
+
+properties:
+ compatible:
+ enum:
+ - microchip,mcp4902
+ - microchip,mcp4912
+ - microchip,mcp4922
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency: true
+
+ vref-supply: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - vref-supply
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "microchip,mcp4912";
+ reg = <0>;
+ vref-supply = <&dac_vref>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml
index d6a95c3cb26f..e701524ee811 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml
@@ -18,6 +18,7 @@ properties:
compatible:
enum:
- qcom,sc7180-osm-l3
+ - qcom,sc8180x-osm-l3
- qcom,sdm845-osm-l3
- qcom,sm8150-osm-l3
- qcom,sm8250-epss-l3
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml
index 5accc0d113be..3fd1a134162d 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml
@@ -49,6 +49,17 @@ properties:
- qcom,sc7280-mmss-noc
- qcom,sc7280-nsp-noc
- qcom,sc7280-system-noc
+ - qcom,sc8180x-aggre1-noc
+ - qcom,sc8180x-aggre2-noc
+ - qcom,sc8180x-camnoc-virt
+ - qcom,sc8180x-compute-noc
+ - qcom,sc8180x-config-noc
+ - qcom,sc8180x-dc-noc
+ - qcom,sc8180x-gem-noc
+ - qcom,sc8180x-ipa-virt
+ - qcom,sc8180x-mc-virt
+ - qcom,sc8180x-mmss-noc
+ - qcom,sc8180x-system-noc
- qcom,sdm845-aggre1-noc
- qcom,sdm845-aggre2-noc
- qcom,sdm845-config-noc
diff --git a/Documentation/devicetree/bindings/interrupt-controller/loongson,liointc.yaml b/Documentation/devicetree/bindings/interrupt-controller/loongson,liointc.yaml
index edf26452dc72..750cc44628e9 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/loongson,liointc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/loongson,liointc.yaml
@@ -19,10 +19,10 @@ allOf:
properties:
compatible:
- oneOf:
- - const: loongson,liointc-1.0
- - const: loongson,liointc-1.0a
- - const: loongson,liointc-2.0
+ enum:
+ - loongson,liointc-1.0
+ - loongson,liointc-1.0a
+ - loongson,liointc-2.0
reg:
minItems: 1
diff --git a/Documentation/devicetree/bindings/interrupt-controller/samsung,exynos4210-combiner.txt b/Documentation/devicetree/bindings/interrupt-controller/samsung,exynos4210-combiner.txt
deleted file mode 100644
index 19af687858a1..000000000000
--- a/Documentation/devicetree/bindings/interrupt-controller/samsung,exynos4210-combiner.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-* Samsung Exynos Interrupt Combiner Controller
-
-Samsung's Exynos4 architecture includes a interrupt combiner controller which
-can combine interrupt sources as a group and provide a single interrupt request
-for the group. The interrupt request from each group are connected to a parent
-interrupt controller, such as GIC in case of Exynos4210.
-
-The interrupt combiner controller consists of multiple combiners. Up to eight
-interrupt sources can be connected to a combiner. The combiner outputs one
-combined interrupt for its eight interrupt sources. The combined interrupt
-is usually connected to a parent interrupt controller.
-
-A single node in the device tree is used to describe the interrupt combiner
-controller module (which includes multiple combiners). A combiner in the
-interrupt controller module shares config/control registers with other
-combiners. For example, a 32-bit interrupt enable/disable config register
-can accommodate up to 4 interrupt combiners (with each combiner supporting
-up to 8 interrupt sources).
-
-Required properties:
-- compatible: should be "samsung,exynos4210-combiner".
-- interrupt-controller: Identifies the node as an interrupt controller.
-- #interrupt-cells: should be <2>. The meaning of the cells are
- * First Cell: Combiner Group Number.
- * Second Cell: Interrupt number within the group.
-- reg: Base address and size of interrupt combiner registers.
-- interrupts: The list of interrupts generated by the combiners which are then
- connected to a parent interrupt controller. The format of the interrupt
- specifier depends in the interrupt parent controller.
-
-Optional properties:
-- samsung,combiner-nr: The number of interrupt combiners supported. If this
- property is not specified, the default number of combiners is assumed
- to be 16.
-
-
-Example:
-
- The following is a an example from the Exynos4210 SoC dtsi file.
-
- combiner:interrupt-controller@10440000 {
- compatible = "samsung,exynos4210-combiner";
- interrupt-controller;
- #interrupt-cells = <2>;
- reg = <0x10440000 0x1000>;
- interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
- <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
- <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
- <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
- };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/samsung,exynos4210-combiner.yaml b/Documentation/devicetree/bindings/interrupt-controller/samsung,exynos4210-combiner.yaml
new file mode 100644
index 000000000000..d631b7589d50
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/samsung,exynos4210-combiner.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/samsung,exynos4210-combiner.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos SoC Interrupt Combiner Controller
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+ Samsung's Exynos4 architecture includes a interrupt combiner controller which
+ can combine interrupt sources as a group and provide a single interrupt
+ request for the group. The interrupt request from each group are connected to
+ a parent interrupt controller, such as GIC in case of Exynos4210.
+
+ The interrupt combiner controller consists of multiple combiners. Up to eight
+ interrupt sources can be connected to a combiner. The combiner outputs one
+ combined interrupt for its eight interrupt sources. The combined interrupt is
+ usually connected to a parent interrupt controller.
+
+ A single node in the device tree is used to describe the interrupt combiner
+ controller module (which includes multiple combiners). A combiner in the
+ interrupt controller module shares config/control registers with other
+ combiners. For example, a 32-bit interrupt enable/disable config register can
+ accommodate up to 4 interrupt combiners (with each combiner supporting up to
+ 8 interrupt sources).
+
+allOf:
+ - $ref: /schemas/interrupt-controller.yaml#
+
+properties:
+ compatible:
+ const: samsung,exynos4210-combiner
+
+ interrupt-controller: true
+
+ interrupts:
+ minItems: 8
+ maxItems: 32
+
+ "#interrupt-cells":
+ description: |
+ The meaning of the cells are:
+ * First Cell: Combiner Group Number.
+ * Second Cell: Interrupt number within the group.
+ const: 2
+
+ reg:
+ maxItems: 1
+
+ samsung,combiner-nr:
+ description: |
+ The number of interrupt combiners supported. Should match number
+ of interrupts set in "interrupts" property.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 8
+ maximum: 32
+ default: 16
+
+required:
+ - compatible
+ - interrupt-controller
+ - interrupts
+ - "#interrupt-cells"
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ interrupt-controller@10440000 {
+ compatible = "samsung,exynos4210-combiner";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0x10440000 0x1000>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,pruss-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/ti,pruss-intc.yaml
index 051beb45d998..65523d9459d8 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/ti,pruss-intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/ti,pruss-intc.yaml
@@ -46,7 +46,7 @@ properties:
AM437x family of SoCs,
AM57xx family of SoCs
66AK2G family of SoCs
- Use "ti,icssg-intc" for K3 AM65x & J721E family of SoCs
+ Use "ti,icssg-intc" for K3 AM65x, J721E and AM64x family of SoCs
reg:
maxItems: 1
@@ -95,6 +95,8 @@ properties:
- AM65x and J721E SoCs have "host_intr5", "host_intr6" and
"host_intr7" interrupts connected to MPU, and other ICSSG
instances.
+ - AM64x SoCs have all the 8 host interrupts connected to various
+ other SoC entities
required:
- compatible
diff --git a/Documentation/devicetree/bindings/iommu/apple,dart.yaml b/Documentation/devicetree/bindings/iommu/apple,dart.yaml
new file mode 100644
index 000000000000..94aa9e9afa59
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/apple,dart.yaml
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iommu/apple,dart.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple DART IOMMU
+
+maintainers:
+ - Sven Peter <sven@svenpeter.dev>
+
+description: |+
+ Apple SoCs may contain an implementation of their Device Address
+ Resolution Table which provides a mandatory layer of address
+ translations for various masters.
+
+ Each DART instance is capable of handling up to 16 different streams
+ with individual pagetables and page-level read/write protection flags.
+
+ This DART IOMMU also raises interrupts in response to various
+ fault conditions.
+
+properties:
+ compatible:
+ const: apple,t8103-dart
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ description:
+ Reference to the gate clock phandle if required for this IOMMU.
+ Optional since not all IOMMUs are attached to a clock gate.
+
+ '#iommu-cells':
+ const: 1
+ description:
+ Has to be one. The single cell describes the stream id emitted by
+ a master to the IOMMU.
+
+required:
+ - compatible
+ - reg
+ - '#iommu-cells'
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |+
+ dart1: iommu@82f80000 {
+ compatible = "apple,t8103-dart";
+ reg = <0x82f80000 0x4000>;
+ interrupts = <1 781 4>;
+ #iommu-cells = <1>;
+ };
+
+ master1 {
+ iommus = <&dart1 0>;
+ };
+
+ - |+
+ dart2a: iommu@82f00000 {
+ compatible = "apple,t8103-dart";
+ reg = <0x82f00000 0x4000>;
+ interrupts = <1 781 4>;
+ #iommu-cells = <1>;
+ };
+ dart2b: iommu@82f80000 {
+ compatible = "apple,t8103-dart";
+ reg = <0x82f80000 0x4000>;
+ interrupts = <1 781 4>;
+ #iommu-cells = <1>;
+ };
+
+ master2 {
+ iommus = <&dart2a 0>, <&dart2b 1>;
+ };
diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt
index 7771ecaac586..89a59b9c81f9 100644
--- a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt
+++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt
@@ -9,8 +9,8 @@ CMDQ driver uses mailbox framework for communication. Please refer to
mailbox.txt for generic information about mailbox device-tree bindings.
Required properties:
-- compatible: can be "mediatek,mt8173-gce", "mediatek,mt8183-gce" or
- "mediatek,mt6779-gce".
+- compatible: can be "mediatek,mt8173-gce", "mediatek,mt8183-gce",
+ "mediatek,mt8192-gce", "mediatek,mt8195-gce" or "mediatek,mt6779-gce".
- reg: Address range of the GCE unit
- interrupts: The interrupt signal from the GCE block
- clock: Clocks according to the common clock binding
@@ -35,9 +35,14 @@ Optional properties for a client device:
start_offset: the start offset of register address that GCE can access.
size: the total size of register address that GCE can access.
+Optional properties for a client mutex node:
+- mediatek,gce-events: GCE events used by clients. The event numbers are
+ defined in 'dt-bindings/gce/<chip>-gce.h'.
+
Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h',
-'dt-binding/gce/mt8183-gce.h' or 'dt-bindings/gce/mt6779-gce.h'. Such as
-sub-system ids, thread priority, event ids.
+'dt-binding/gce/mt8183-gce.h', 'dt-binding/gce/mt8192-gce.h',
+'dt-binding/gce/mt8195-gce.h' or 'dt-bindings/gce/mt6779-gce.h'.
+Such as sub-system ids, thread priority, event ids.
Example:
@@ -62,3 +67,14 @@ Example for a client device:
<&gce SUBSYS_1401XXXX 0x2000 0x100>;
...
};
+
+Example for a client mutex node:
+ mutex: mutex@14020000 {
+ compatible = "mediatek,mt8173-disp-mutex";
+ reg = <0 0x14020000 0 0x1000>;
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+ clocks = <&mmsys CLK_MM_MUTEX_32K>;
+ mediatek,gce-events = <CMDQ_EVENT_MUTEX0_STREAM_EOF>,
+ <CMDQ_EVENT_MUTEX1_STREAM_EOF>;
+ };
diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
index 8878ec00820e..6395281b0cec 100644
--- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
+++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
@@ -20,6 +20,7 @@ properties:
- qcom,ipq8074-apcs-apps-global
- qcom,msm8916-apcs-kpss-global
- qcom,msm8939-apcs-kpss-global
+ - qcom,msm8953-apcs-kpss-global
- qcom,msm8994-apcs-kpss-global
- qcom,msm8996-apcs-hmss-global
- qcom,msm8998-apcs-hmss-global
@@ -29,6 +30,7 @@ properties:
- qcom,sdm660-apcs-hmss-global
- qcom,sdm845-apss-shared
- qcom,sm6125-apcs-hmss-global
+ - qcom,sm6115-apcs-hmss-global
- qcom,sm8150-apss-shared
reg:
diff --git a/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml b/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
index b222f993b232..866efb278813 100644
--- a/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
+++ b/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
@@ -24,6 +24,7 @@ properties:
compatible:
items:
- enum:
+ - qcom,sm6350-ipcc
- qcom,sm8250-ipcc
- qcom,sm8350-ipcc
- qcom,sc7280-ipcc
diff --git a/Documentation/devicetree/bindings/media/amlogic,meson-ir-tx.yaml b/Documentation/devicetree/bindings/media/amlogic,meson-ir-tx.yaml
new file mode 100644
index 000000000000..4432fea32650
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/amlogic,meson-ir-tx.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Amlogic Meson IR transmitter
+
+maintainers:
+ - Viktor Prutyanov <viktor.prutyanov@phystech.edu>
+
+description: |
+ Some Amlogic SoCs such as A311D and T950D4 have IR transmitter
+ (also called blaster) controller onboard. It is capable of
+ sending IR signals with arbitrary carrier frequency and duty cycle.
+
+properties:
+ compatible:
+ oneOf:
+ - const: amlogic,meson-ir-tx
+ - items:
+ - const: amlogic,meson-g12a-ir-tx
+ - const: amlogic,meson-ir-tx
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: sysclk
+ - const: xtal
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/clock/g12a-clkc.h>
+
+ ir@ff80014c {
+ compatible = "amlogic,meson-g12a-ir-tx", "amlogic,meson-ir-tx";
+ reg = <0xff80014c 0x10>;
+ interrupts = <0 198 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc CLKID_CLK81>, <&xtal>;
+ clock-names = "sysclk", "xtal";
+ };
diff --git a/Documentation/devicetree/bindings/media/atmel,isc.yaml b/Documentation/devicetree/bindings/media/atmel,isc.yaml
index 3e4bb8892d94..cd6d7af0c768 100644
--- a/Documentation/devicetree/bindings/media/atmel,isc.yaml
+++ b/Documentation/devicetree/bindings/media/atmel,isc.yaml
@@ -44,7 +44,8 @@ properties:
const: isc-mck
port:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
description:
Input port node, single endpoint describing the input pad.
diff --git a/Documentation/devicetree/bindings/media/i2c/adv7180.yaml b/Documentation/devicetree/bindings/media/i2c/adv7180.yaml
index 3ce4af143a3a..c8d887eee3bb 100644
--- a/Documentation/devicetree/bindings/media/i2c/adv7180.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/adv7180.yaml
@@ -35,6 +35,14 @@ properties:
powerdown-gpios:
maxItems: 1
+ reset-gpios:
+ maxItems: 1
+
+ adv,force-bt656-4:
+ description:
+ Indicates that the output is a BT.656-4 compatible stream.
+ type: boolean
+
port:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml b/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml
index 701f4e0d138f..39395ea8c318 100644
--- a/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml
@@ -83,10 +83,10 @@ properties:
link-frequencies: true
data-lanes: true
bus-type:
- oneOf:
- - const: 1 # CSI-2 C-PHY
- - const: 3 # CCP2
- - const: 4 # CSI-2 D-PHY
+ enum:
+ - 1 # CSI-2 C-PHY
+ - 3 # CCP2
+ - 4 # CSI-2 D-PHY
required:
- link-frequencies
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
new file mode 100644
index 000000000000..ad42992c6da3
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2021 Intel Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ovti,ov9282.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: OmniVision OV9282 Sensor
+
+maintainers:
+ - Paul J. Murphy <paul.j.murphy@intel.com>
+ - Daniele Alessandrelli <daniele.alessandrelli@intel.com>
+
+description:
+ OV9282 sensor is an OmniVision black & white CMOS active pixel digital image
+ sensor with an active array size of 1296H x 816V. It is programmable through
+ I2C interface. The I2C client address is fixed to 0x60/0x70 as per sensor data
+ sheet. Image data is sent through MIPI CSI-2.
+
+properties:
+ compatible:
+ const: ovti,ov9282
+ reg:
+ description: I2C address
+ maxItems: 1
+
+ assigned-clocks: true
+ assigned-clock-parents: true
+ assigned-clock-rates: true
+
+ clocks:
+ description: Clock frequency from 6 to 27MHz
+ maxItems: 1
+
+ reset-gpios:
+ description: Reference to the GPIO connected to the XCLR pin, if any.
+ maxItems: 1
+
+ port:
+ additionalProperties: false
+ $ref: /schemas/graph.yaml#/properties/port
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes: true
+ link-frequencies: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+ required:
+ - endpoint
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ camera@60 {
+ compatible = "ovti,ov9282";
+ reg = <0x60>;
+ clocks = <&ov9282_clk>;
+
+ assigned-clocks = <&ov9282_clk>;
+ assigned-clock-parents = <&ov9282_clk_parent>;
+ assigned-clock-rates = <24000000>;
+
+ port {
+ ov9282: endpoint {
+ remote-endpoint = <&cam>;
+ data-lanes = <1 2>;
+ link-frequencies = /bits/ 64 <800000000>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
new file mode 100644
index 000000000000..881f79532501
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2021 Intel Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/sony,imx335.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sony IMX335 Sensor
+
+maintainers:
+ - Paul J. Murphy <paul.j.murphy@intel.com>
+ - Daniele Alessandrelli <daniele.alessandrelli@intel.com>
+
+description:
+ IMX335 sensor is a Sony CMOS active pixel digital image sensor with an active
+ array size of 2592H x 1944V. It is programmable through I2C interface. The
+ I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
+ sent through MIPI CSI-2.
+
+properties:
+ compatible:
+ const: sony,imx335
+ reg:
+ description: I2C address
+ maxItems: 1
+
+ assigned-clocks: true
+ assigned-clock-parents: true
+ assigned-clock-rates: true
+
+ clocks:
+ description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
+ maxItems: 1
+
+ reset-gpios:
+ description: Reference to the GPIO connected to the XCLR pin, if any.
+ maxItems: 1
+
+ port:
+ additionalProperties: false
+ $ref: /schemas/graph.yaml#/properties/port
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes: true
+ link-frequencies: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+ required:
+ - endpoint
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ camera@1a {
+ compatible = "sony,imx335";
+ reg = <0x1a>;
+ clocks = <&imx335_clk>;
+
+ assigned-clocks = <&imx335_clk>;
+ assigned-clock-parents = <&imx335_clk_parent>;
+ assigned-clock-rates = <24000000>;
+
+ port {
+ imx335: endpoint {
+ remote-endpoint = <&cam>;
+ data-lanes = <1 2 3 4>;
+ link-frequencies = /bits/ 64 <594000000>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
new file mode 100644
index 000000000000..1edeabf39e6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2021 Intel Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/sony,imx412.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sony IMX412 Sensor
+
+maintainers:
+ - Paul J. Murphy <paul.j.murphy@intel.com>
+ - Daniele Alessandrelli <daniele.alessandrelli@intel.com>
+
+description:
+ IMX412 sensor is a Sony CMOS active pixel digital image sensor with an active
+ array size of 4072H x 3176V. It is programmable through I2C interface. The
+ I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
+ sent through MIPI CSI-2.
+
+properties:
+ compatible:
+ const: sony,imx412
+ reg:
+ description: I2C address
+ maxItems: 1
+
+ assigned-clocks: true
+ assigned-clock-parents: true
+ assigned-clock-rates: true
+
+ clocks:
+ description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz
+ maxItems: 1
+
+ reset-gpios:
+ description: Reference to the GPIO connected to the XCLR pin, if any.
+ maxItems: 1
+
+ port:
+ additionalProperties: false
+ $ref: /schemas/graph.yaml#/properties/port
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes: true
+ link-frequencies: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+ required:
+ - endpoint
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ camera@1a {
+ compatible = "sony,imx412";
+ reg = <0x1a>;
+ clocks = <&imx412_clk>;
+
+ assigned-clocks = <&imx412_clk>;
+ assigned-clock-parents = <&imx412_clk_parent>;
+ assigned-clock-rates = <24000000>;
+
+ port {
+ imx412: endpoint {
+ remote-endpoint = <&cam>;
+ data-lanes = <1 2 3 4>;
+ link-frequencies = /bits/ 64 <600000000>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/media/microchip,xisc.yaml b/Documentation/devicetree/bindings/media/microchip,xisc.yaml
index 41afe2e5f133..086e1430af4f 100644
--- a/Documentation/devicetree/bindings/media/microchip,xisc.yaml
+++ b/Documentation/devicetree/bindings/media/microchip,xisc.yaml
@@ -52,7 +52,7 @@ properties:
of the data and clock lines.
port:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
description:
Input port node, single endpoint describing the input pad.
diff --git a/Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml b/Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
index d91575b8ebb9..5922a2795167 100644
--- a/Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
+++ b/Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/media/nxp,imx7-csi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: i.MX7 CMOS Sensor Interface
+title: i.MX7 and i.MX8 CSI bridge (CMOS Sensor Interface)
maintainers:
- Rui Miguel Silva <rmfrfs@gmail.com>
@@ -15,9 +15,13 @@ description: |
properties:
compatible:
- enum:
- - fsl,imx7-csi
- - fsl,imx6ul-csi
+ oneOf:
+ - enum:
+ - fsl,imx7-csi
+ - fsl,imx6ul-csi
+ - items:
+ - const: fsl,imx8mm-csi
+ - const: fsl,imx7-csi
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml
index 7c09eec78ce5..877183cf4278 100644
--- a/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml
+++ b/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml
@@ -200,8 +200,6 @@ examples:
clock-names = "pclk", "wrap", "phy", "axi";
power-domains = <&mipi_pd>;
- status = "disabled";
-
ports {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml b/Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
index 5d13cbb5251b..3cc6f42aeb76 100644
--- a/Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
+++ b/Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
@@ -16,12 +16,17 @@ description: |-
properties:
compatible:
- items:
- - enum:
- # JPEG decoder
- - nxp,imx8qxp-jpgdec
- # JPEG encoder
- - nxp,imx8qxp-jpgenc
+ oneOf:
+ - items:
+ enum:
+ - nxp,imx8qxp-jpgdec
+ - nxp,imx8qxp-jpgenc
+ - items:
+ - const: nxp,imx8qm-jpgdec
+ - const: nxp,imx8qxp-jpgdec
+ - items:
+ - const: nxp,imx8qm-jpgenc
+ - const: nxp,imx8qxp-jpgenc
reg:
maxItems: 1
@@ -69,7 +74,7 @@ examples:
};
jpegenc: jpegenc@58450000 {
- compatible = "nxp,imx8qxp-jpgenc";
+ compatible = "nxp,imx8qm-jpgenc", "nxp,imx8qxp-jpgenc";
reg = <0x58450000 0x00050000 >;
interrupts = <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml
new file mode 100644
index 000000000000..9c04fa85ee5c
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml
@@ -0,0 +1,174 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/nxp,imx8mq-mipi-csi2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX8MQ MIPI CSI-2 receiver
+
+maintainers:
+ - Martin Kepplinger <martin.kepplinger@puri.sm>
+
+description: |-
+ This binding covers the CSI-2 RX PHY and host controller included in the
+ NXP i.MX8MQ SoC. It handles the sensor/image input and process for all the
+ input imaging devices.
+
+properties:
+ compatible:
+ enum:
+ - fsl,imx8mq-mipi-csi2
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: core is the RX Controller Core Clock input. This clock
+ must be exactly equal to or faster than the receive
+ byteclock from the RX DPHY.
+ - description: esc is the Rx Escape Clock. This must be the same escape
+ clock that the RX DPHY receives.
+ - description: ui is the pixel clock (phy_ref up to 333Mhz).
+ See the reference manual for details.
+
+ clock-names:
+ items:
+ - const: core
+ - const: esc
+ - const: ui
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ items:
+ - description: CORE_RESET reset register bit definition
+ - description: PHY_REF_RESET reset register bit definition
+ - description: ESC_RESET reset register bit definition
+
+ fsl,mipi-phy-gpr:
+ description: |
+ The phandle to the imx8mq syscon iomux-gpr with the register
+ for setting RX_ENABLE for the mipi receiver.
+
+ The format should be as follows:
+ <gpr req_gpr>
+ gpr is the phandle to general purpose register node.
+ req_gpr is the gpr register offset of RX_ENABLE for the mipi phy.
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ items:
+ items:
+ - description: The 'gpr' is the phandle to general purpose register node.
+ - description: The 'req_gpr' is the gpr register offset containing
+ CSI2_1_RX_ENABLE or CSI2_2_RX_ENABLE respectively.
+ maximum: 0xff
+
+ interconnects:
+ maxItems: 1
+
+ interconnect-names:
+ const: dram
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description:
+ Input port node, single endpoint describing the CSI-2 transmitter.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ items:
+ minItems: 1
+ maxItems: 4
+ items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+
+ required:
+ - data-lanes
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Output port node
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - power-domains
+ - resets
+ - fsl,mipi-phy-gpr
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx8mq-clock.h>
+ #include <dt-bindings/interconnect/imx8mq.h>
+ #include <dt-bindings/reset/imx8mq-reset.h>
+
+ csi@30a70000 {
+ compatible = "fsl,imx8mq-mipi-csi2";
+ reg = <0x30a70000 0x1000>;
+ clocks = <&clk IMX8MQ_CLK_CSI1_CORE>,
+ <&clk IMX8MQ_CLK_CSI1_ESC>,
+ <&clk IMX8MQ_CLK_CSI1_PHY_REF>;
+ clock-names = "core", "esc", "ui";
+ assigned-clocks = <&clk IMX8MQ_CLK_CSI1_CORE>,
+ <&clk IMX8MQ_CLK_CSI1_PHY_REF>,
+ <&clk IMX8MQ_CLK_CSI1_ESC>;
+ assigned-clock-rates = <266000000>, <200000000>, <66000000>;
+ assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_266M>,
+ <&clk IMX8MQ_SYS2_PLL_1000M>,
+ <&clk IMX8MQ_SYS1_PLL_800M>;
+ power-domains = <&pgc_mipi_csi1>;
+ resets = <&src IMX8MQ_RESET_MIPI_CSI1_CORE_RESET>,
+ <&src IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET>,
+ <&src IMX8MQ_RESET_MIPI_CSI1_ESC_RESET>;
+ fsl,mipi-phy-gpr = <&iomuxc_gpr 0x88>;
+ interconnects = <&noc IMX8MQ_ICM_CSI1 &noc IMX8MQ_ICS_DRAM>;
+ interconnect-names = "dram";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ imx8mm_mipi_csi_in: endpoint {
+ remote-endpoint = <&imx477_out>;
+ data-lanes = <1 2 3 4>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ imx8mm_mipi_csi_out: endpoint {
+ remote-endpoint = <&csi_in>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/media/renesas,drif.yaml b/Documentation/devicetree/bindings/media/renesas,drif.yaml
index 817a6d566738..9403b235e976 100644
--- a/Documentation/devicetree/bindings/media/renesas,drif.yaml
+++ b/Documentation/devicetree/bindings/media/renesas,drif.yaml
@@ -96,7 +96,7 @@ properties:
Indicates that the channel acts as primary among the bonded channels.
port:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Child port node corresponding to the data input. The port node must
@@ -242,7 +242,6 @@ examples:
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 513>;
renesas,bonding = <&drif11>;
- status = "disabled";
};
drif11: rif@e6f70000 {
diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml
index b88172a59de7..bacb60a34989 100644
--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml
+++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml
@@ -22,6 +22,7 @@ properties:
- rockchip,rk3288-vpu
- rockchip,rk3328-vpu
- rockchip,rk3399-vpu
+ - rockchip,px30-vpu
- items:
- const: rockchip,rk3188-vpu
- const: rockchip,rk3066-vpu
diff --git a/Documentation/devicetree/bindings/memory-controllers/ath79-ddr-controller.txt b/Documentation/devicetree/bindings/memory-controllers/ath79-ddr-controller.txt
deleted file mode 100644
index c81af75bcd88..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/ath79-ddr-controller.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-Binding for Qualcomm Atheros AR7xxx/AR9xxx DDR controller
-
-The DDR controller of the AR7xxx and AR9xxx families provides an interface
-to flush the FIFO between various devices and the DDR. This is mainly used
-by the IRQ controller to flush the FIFO before running the interrupt handler
-of such devices.
-
-Required properties:
-
-- compatible: has to be "qca,<soc-type>-ddr-controller",
- "qca,[ar7100|ar7240]-ddr-controller" as fallback.
- On SoC with PCI support "qca,ar7100-ddr-controller" should be used as
- fallback, otherwise "qca,ar7240-ddr-controller" should be used.
-- reg: Base address and size of the controller's memory area
-- #qca,ddr-wb-channel-cells: Specifies the number of cells needed to encode
- the write buffer channel index, should be 1.
-
-Example:
-
- ddr_ctrl: memory-controller@18000000 {
- compatible = "qca,ar9132-ddr-controller",
- "qca,ar7240-ddr-controller";
- reg = <0x18000000 0x100>;
-
- #qca,ddr-wb-channel-cells = <1>;
- };
-
- ...
-
- interrupt-controller {
- ...
- qca,ddr-wb-channel-interrupts = <2>, <3>, <4>, <5>;
- qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>,
- <&ddr_ctrl 0>, <&ddr_ctrl 1>;
- };
diff --git a/Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.txt b/Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.txt
deleted file mode 100644
index 82d923ef413f..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-DDR PHY Front End (DPFE) for Broadcom STB
-=========================================
-
-DPFE and the DPFE firmware provide an interface for the host CPU to
-communicate with the DCPU, which resides inside the DDR PHY.
-
-There are three memory regions for interacting with the DCPU. These are
-specified in a single reg property.
-
-Required properties:
- - compatible: must be "brcm,bcm7271-dpfe-cpu", "brcm,bcm7268-dpfe-cpu"
- or "brcm,dpfe-cpu"
- - reg: must reference three register ranges
- - start address and length of the DCPU register space
- - start address and length of the DCPU data memory space
- - start address and length of the DCPU instruction memory space
- - reg-names: must contain "dpfe-cpu", "dpfe-dmem", and "dpfe-imem";
- they must be in the same order as the register declarations
-
-Example:
- dpfe_cpu0: dpfe-cpu@f1132000 {
- compatible = "brcm,bcm7271-dpfe-cpu", "brcm,dpfe-cpu";
- reg = <0xf1132000 0x180
- 0xf1134000 0x1000
- 0xf1138000 0x4000>;
- reg-names = "dpfe-cpu", "dpfe-dmem", "dpfe-imem";
- };
diff --git a/Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.yaml b/Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.yaml
new file mode 100644
index 000000000000..769f13250047
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/brcm,dpfe-cpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DDR PHY Front End (DPFE) for Broadcom STB
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Markus Mayer <mmayer@broadcom.com>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - brcm,bcm7271-dpfe-cpu
+ - brcm,bcm7268-dpfe-cpu
+ - const: brcm,dpfe-cpu
+
+ reg:
+ items:
+ - description: DCPU register space
+ - description: DCPU data memory space
+ - description: DCPU instruction memory space
+
+ reg-names:
+ items:
+ - const: dpfe-cpu
+ - const: dpfe-dmem
+ - const: dpfe-imem
+
+required:
+ - compatible
+ - reg
+ - reg-names
+
+additionalProperties: false
+
+examples:
+ - |
+ dpfe-cpu@f1132000 {
+ compatible = "brcm,bcm7271-dpfe-cpu", "brcm,dpfe-cpu";
+ reg = <0xf1132000 0x180>,
+ <0xf1134000 0x1000>,
+ <0xf1138000 0x4000>;
+ reg-names = "dpfe-cpu", "dpfe-dmem", "dpfe-imem";
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/exynos5422-dmc.txt b/Documentation/devicetree/bindings/memory-controllers/exynos5422-dmc.txt
deleted file mode 100644
index 02e4a1f862f1..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/exynos5422-dmc.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-* Exynos5422 frequency and voltage scaling for Dynamic Memory Controller device
-
-The Samsung Exynos5422 SoC has DMC (Dynamic Memory Controller) to which the DRAM
-memory chips are connected. The driver is to monitor the controller in runtime
-and switch frequency and voltage. To monitor the usage of the controller in
-runtime, the driver uses the PPMU (Platform Performance Monitoring Unit), which
-is able to measure the current load of the memory.
-When 'userspace' governor is used for the driver, an application is able to
-switch the DMC and memory frequency.
-
-Required properties for DMC device for Exynos5422:
-- compatible: Should be "samsung,exynos5422-dmc".
-- clocks : list of clock specifiers, must contain an entry for each
- required entry in clock-names for CLK_FOUT_SPLL, CLK_MOUT_SCLK_SPLL,
- CLK_FF_DOUT_SPLL2, CLK_FOUT_BPLL, CLK_MOUT_BPLL, CLK_SCLK_BPLL,
- CLK_MOUT_MX_MSPLL_CCORE, CLK_MOUT_MX_MSPLL_CCORE_PHY, CLK_MOUT_MCLK_CDREX,
-- clock-names : should include "fout_spll", "mout_sclk_spll", "ff_dout_spll2",
- "fout_bpll", "mout_bpll", "sclk_bpll", "mout_mx_mspll_ccore",
- "mout_mclk_cdrex" entries
-- devfreq-events : phandles for PPMU devices connected to this DMC.
-- vdd-supply : phandle for voltage regulator which is connected.
-- reg : registers of two CDREX controllers.
-- operating-points-v2 : phandle for OPPs described in v2 definition.
-- device-handle : phandle of the connected DRAM memory device. For more
- information please refer to documentation file:
- Documentation/devicetree/bindings/ddr/lpddr3.txt
-- devfreq-events : phandles of the PPMU events used by the controller.
-- samsung,syscon-clk : phandle of the clock register set used by the controller,
- these registers are used for enabling a 'pause' feature and are not
- exposed by clock framework but they must be used in a safe way.
- The register offsets are in the driver code and specyfic for this SoC
- type.
-
-Optional properties for DMC device for Exynos5422:
-- interrupt-parent : The parent interrupt controller.
-- interrupts : Contains the IRQ line numbers for the DMC internal performance
- event counters in DREX0 and DREX1 channels. Align with specification of the
- interrupt line(s) in the interrupt-parent controller.
-- interrupt-names : IRQ names "drex_0" and "drex_1", the order should be the
- same as in the 'interrupts' list above.
-
-Example:
-
- ppmu_dmc0_0: ppmu@10d00000 {
- compatible = "samsung,exynos-ppmu";
- reg = <0x10d00000 0x2000>;
- clocks = <&clock CLK_PCLK_PPMU_DREX0_0>;
- clock-names = "ppmu";
- events {
- ppmu_event_dmc0_0: ppmu-event3-dmc0_0 {
- event-name = "ppmu-event3-dmc0_0";
- };
- };
- };
-
- dmc: memory-controller@10c20000 {
- compatible = "samsung,exynos5422-dmc";
- reg = <0x10c20000 0x10000>, <0x10c30000 0x10000>;
- clocks = <&clock CLK_FOUT_SPLL>,
- <&clock CLK_MOUT_SCLK_SPLL>,
- <&clock CLK_FF_DOUT_SPLL2>,
- <&clock CLK_FOUT_BPLL>,
- <&clock CLK_MOUT_BPLL>,
- <&clock CLK_SCLK_BPLL>,
- <&clock CLK_MOUT_MX_MSPLL_CCORE>,
- <&clock CLK_MOUT_MCLK_CDREX>;
- clock-names = "fout_spll",
- "mout_sclk_spll",
- "ff_dout_spll2",
- "fout_bpll",
- "mout_bpll",
- "sclk_bpll",
- "mout_mx_mspll_ccore",
- "mout_mclk_cdrex";
- operating-points-v2 = <&dmc_opp_table>;
- devfreq-events = <&ppmu_event3_dmc0_0>, <&ppmu_event3_dmc0_1>,
- <&ppmu_event3_dmc1_0>, <&ppmu_event3_dmc1_1>;
- device-handle = <&samsung_K3QF2F20DB>;
- vdd-supply = <&buck1_reg>;
- samsung,syscon-clk = <&clock>;
- interrupt-parent = <&combiner>;
- interrupts = <16 0>, <16 1>;
- interrupt-names = "drex_0", "drex_1";
- };
diff --git a/Documentation/devicetree/bindings/memory-controllers/marvell,mvebu-sdram-controller.yaml b/Documentation/devicetree/bindings/memory-controllers/marvell,mvebu-sdram-controller.yaml
new file mode 100644
index 000000000000..14a6bc8f421f
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/marvell,mvebu-sdram-controller.yaml
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/marvell,mvebu-sdram-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell MVEBU SDRAM controller
+
+maintainers:
+ - Jan Luebbe <jlu@pengutronix.de>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+properties:
+ compatible:
+ const: marvell,armada-xp-sdram-controller
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ memory-controller@1400 {
+ compatible = "marvell,armada-xp-sdram-controller";
+ reg = <0x1400 0x500>;
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/mvebu-sdram-controller.txt b/Documentation/devicetree/bindings/memory-controllers/mvebu-sdram-controller.txt
deleted file mode 100644
index 89657d1d4cd4..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/mvebu-sdram-controller.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Device Tree bindings for MVEBU SDRAM controllers
-
-The Marvell EBU SoCs all have a SDRAM controller. The SDRAM controller
-differs from one SoC variant to another, but they also share a number
-of commonalities.
-
-For now, this Device Tree binding documentation only documents the
-Armada XP SDRAM controller.
-
-Required properties:
-
- - compatible: for Armada XP, "marvell,armada-xp-sdram-controller"
- - reg: a resource specifier for the register space, which should
- include all SDRAM controller registers as per the datasheet.
-
-Example:
-
-sdramc@1400 {
- compatible = "marvell,armada-xp-sdram-controller";
- reg = <0x1400 0x500>;
-};
diff --git a/Documentation/devicetree/bindings/memory-controllers/qca,ath79-ddr-controller.yaml b/Documentation/devicetree/bindings/memory-controllers/qca,ath79-ddr-controller.yaml
new file mode 100644
index 000000000000..9566b3421f03
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/qca,ath79-ddr-controller.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/qca,ath79-ddr-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Atheros AR7xxx/AR9xxx DDR controller
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+ The DDR controller of the AR7xxx and AR9xxx families provides an interface to
+ flush the FIFO between various devices and the DDR. This is mainly used by
+ the IRQ controller to flush the FIFO before running the interrupt handler of
+ such devices.
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - const: qca,ar9132-ddr-controller
+ - const: qca,ar7240-ddr-controller
+ - items:
+ - enum:
+ - qca,ar7100-ddr-controller
+ - qca,ar7240-ddr-controller
+
+ "#qca,ddr-wb-channel-cells":
+ description: |
+ Specifies the number of cells needed to encode the write buffer channel
+ index.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ const: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - "#qca,ddr-wb-channel-cells"
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ ddr_ctrl: memory-controller@18000000 {
+ compatible = "qca,ar9132-ddr-controller",
+ "qca,ar7240-ddr-controller";
+ reg = <0x18000000 0x100>;
+
+ #qca,ddr-wb-channel-cells = <1>;
+ };
+
+ interrupt-controller {
+ // ...
+ qca,ddr-wb-channel-interrupts = <2>, <3>, <4>, <5>;
+ qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>,
+ <&ddr_ctrl 0>, <&ddr_ctrl 1>;
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.txt b/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.txt
deleted file mode 100644
index cdf406c902e2..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-* H8/300 bus controller
-
-Required properties:
- - compatible: Must be "renesas,h8300-bsc".
- - reg: Base address and length of BSC registers.
-
-Example.
- bsc: memory-controller@fee01e {
- compatible = "renesas,h8300h-bsc", "renesas,h8300-bsc";
- reg = <0xfee01e 8>;
- };
-
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.yaml
new file mode 100644
index 000000000000..2b18cef99511
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/renesas,h8300-bsc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: H8/300 bus controller
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Yoshinori Sato <ysato@users.sourceforge.jp>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,h8300h-bsc
+ - renesas,h8s-bsc
+ - const: renesas,h8300-bsc
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ memory-controller@fee01e {
+ compatible = "renesas,h8300h-bsc", "renesas,h8300-bsc";
+ reg = <0xfee01e 8>;
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
index 990489fdd2ac..d25072c414e4 100644
--- a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
@@ -61,12 +61,23 @@ patternProperties:
type: object
properties:
compatible:
- enum:
- - cfi-flash
- - jedec,spi-nor
+ contains:
+ enum:
+ - cfi-flash
+ - jedec,spi-nor
unevaluatedProperties: false
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - power-domains
+ - resets
+ - '#address-cells'
+ - '#size-cells'
+
examples:
- |
#include <dt-bindings/clock/renesas-cpg-mssr.h>
diff --git a/Documentation/devicetree/bindings/memory-controllers/samsung,exynos5422-dmc.yaml b/Documentation/devicetree/bindings/memory-controllers/samsung,exynos5422-dmc.yaml
new file mode 100644
index 000000000000..6f4fd5814bf4
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/samsung,exynos5422-dmc.yaml
@@ -0,0 +1,137 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/samsung,exynos5422-dmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: |
+ Samsung Exynos5422 SoC frequency and voltage scaling for Dynamic Memory
+ Controller device
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Lukasz Luba <lukasz.luba@arm.com>
+
+description: |
+ The Samsung Exynos5422 SoC has DMC (Dynamic Memory Controller) to which the
+ DRAM memory chips are connected. The driver is to monitor the controller in
+ runtime and switch frequency and voltage. To monitor the usage of the
+ controller in runtime, the driver uses the PPMU (Platform Performance
+ Monitoring Unit), which is able to measure the current load of the memory.
+ When 'userspace' governor is used for the driver, an application is able to
+ switch the DMC and memory frequency.
+
+properties:
+ compatible:
+ items:
+ - const: samsung,exynos5422-dmc
+
+ clock-names:
+ items:
+ - const: fout_spll
+ - const: mout_sclk_spll
+ - const: ff_dout_spll2
+ - const: fout_bpll
+ - const: mout_bpll
+ - const: sclk_bpll
+ - const: mout_mx_mspll_ccore
+ - const: mout_mclk_cdrex
+
+ clocks:
+ minItems: 8
+ maxItems: 8
+
+ devfreq-events:
+ $ref: '/schemas/types.yaml#/definitions/phandle-array'
+ minItems: 1
+ maxItems: 16
+ description: phandles of the PPMU events used by the controller.
+
+ device-handle:
+ $ref: '/schemas/types.yaml#/definitions/phandle'
+ description: |
+ phandle of the connected DRAM memory device. For more information please
+ refer to documentation file: Documentation/devicetree/bindings/ddr/lpddr3.txt
+
+ operating-points-v2: true
+
+ interrupts:
+ items:
+ - description: DMC internal performance event counters in DREX0
+ - description: DMC internal performance event counters in DREX1
+
+ interrupt-names:
+ items:
+ - const: drex_0
+ - const: drex_1
+
+ reg:
+ items:
+ - description: registers of DREX0
+ - description: registers of DREX1
+
+ samsung,syscon-clk:
+ $ref: '/schemas/types.yaml#/definitions/phandle'
+ description: |
+ Phandle of the clock register set used by the controller, these registers
+ are used for enabling a 'pause' feature and are not exposed by clock
+ framework but they must be used in a safe way. The register offsets are
+ in the driver code and specyfic for this SoC type.
+
+ vdd-supply: true
+
+required:
+ - compatible
+ - clock-names
+ - clocks
+ - devfreq-events
+ - device-handle
+ - reg
+ - samsung,syscon-clk
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/exynos5420.h>
+ ppmu_dmc0_0: ppmu@10d00000 {
+ compatible = "samsung,exynos-ppmu";
+ reg = <0x10d00000 0x2000>;
+ clocks = <&clock CLK_PCLK_PPMU_DREX0_0>;
+ clock-names = "ppmu";
+ events {
+ ppmu_event_dmc0_0: ppmu-event3-dmc0-0 {
+ event-name = "ppmu-event3-dmc0_0";
+ };
+ };
+ };
+
+ memory-controller@10c20000 {
+ compatible = "samsung,exynos5422-dmc";
+ reg = <0x10c20000 0x10000>, <0x10c30000 0x10000>;
+ clocks = <&clock CLK_FOUT_SPLL>,
+ <&clock CLK_MOUT_SCLK_SPLL>,
+ <&clock CLK_FF_DOUT_SPLL2>,
+ <&clock CLK_FOUT_BPLL>,
+ <&clock CLK_MOUT_BPLL>,
+ <&clock CLK_SCLK_BPLL>,
+ <&clock CLK_MOUT_MX_MSPLL_CCORE>,
+ <&clock CLK_MOUT_MCLK_CDREX>;
+ clock-names = "fout_spll",
+ "mout_sclk_spll",
+ "ff_dout_spll2",
+ "fout_bpll",
+ "mout_bpll",
+ "sclk_bpll",
+ "mout_mx_mspll_ccore",
+ "mout_mclk_cdrex";
+ operating-points-v2 = <&dmc_opp_table>;
+ devfreq-events = <&ppmu_event3_dmc0_0>, <&ppmu_event3_dmc0_1>,
+ <&ppmu_event3_dmc1_0>, <&ppmu_event3_dmc1_1>;
+ device-handle = <&samsung_K3QF2F20DB>;
+ vdd-supply = <&buck1_reg>;
+ samsung,syscon-clk = <&clock>;
+ interrupt-parent = <&combiner>;
+ interrupts = <16 0>, <16 1>;
+ interrupt-names = "drex_0", "drex_1";
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys,ddrc-ecc.yaml b/Documentation/devicetree/bindings/memory-controllers/synopsys,ddrc-ecc.yaml
new file mode 100644
index 000000000000..a24588474625
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys,ddrc-ecc.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/synopsys,ddrc-ecc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys IntelliDDR Multi Protocol memory controller
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Manish Narani <manish.narani@xilinx.com>
+ - Michal Simek <michal.simek@xilinx.com>
+
+description: |
+ The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and
+ 32-bit bus width configurations.
+
+ The Zynq DDR ECC controller has an optional ECC support in half-bus width
+ (16-bit) configuration.
+
+ These both ECC controllers correct single bit ECC errors and detect double bit
+ ECC errors.
+
+properties:
+ compatible:
+ enum:
+ - xlnx,zynq-ddrc-a05
+ - xlnx,zynqmp-ddrc-2.40a
+
+ interrupts:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: xlnx,zynqmp-ddrc-2.40a
+ then:
+ required:
+ - interrupts
+ else:
+ properties:
+ interrupts: false
+
+additionalProperties: false
+
+examples:
+ - |
+ memory-controller@f8006000 {
+ compatible = "xlnx,zynq-ddrc-a05";
+ reg = <0xf8006000 0x1000>;
+ };
+
+ - |
+ axi {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ memory-controller@fd070000 {
+ compatible = "xlnx,zynqmp-ddrc-2.40a";
+ reg = <0x0 0xfd070000 0x0 0x30000>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 112 4>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
deleted file mode 100644
index 9d32762c47e1..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
-
-The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and 32-bit
-bus width configurations.
-
-The Zynq DDR ECC controller has an optional ECC support in half-bus width
-(16-bit) configuration.
-
-These both ECC controllers correct single bit ECC errors and detect double bit
-ECC errors.
-
-Required properties:
- - compatible: One of:
- - 'xlnx,zynq-ddrc-a05' : Zynq DDR ECC controller
- - 'xlnx,zynqmp-ddrc-2.40a' : ZynqMP DDR ECC controller
- - reg: Should contain DDR controller registers location and length.
-
-Required properties for "xlnx,zynqmp-ddrc-2.40a":
- - interrupts: Property with a value describing the interrupt number.
-
-Example:
- memory-controller@f8006000 {
- compatible = "xlnx,zynq-ddrc-a05";
- reg = <0xf8006000 0x1000>;
- };
-
- mc: memory-controller@fd070000 {
- compatible = "xlnx,zynqmp-ddrc-2.40a";
- reg = <0x0 0xfd070000 0x0 0x30000>;
- interrupt-parent = <&gic>;
- interrupts = <0 112 4>;
- };
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti,da8xx-ddrctl.yaml b/Documentation/devicetree/bindings/memory-controllers/ti,da8xx-ddrctl.yaml
new file mode 100644
index 000000000000..9ed51185ff99
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ti,da8xx-ddrctl.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ti,da8xx-ddrctl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments da8xx DDR2/mDDR memory controller
+
+maintainers:
+ - Bartosz Golaszewski <bgolaszewski@baylibre.com>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+ Documentation:
+ OMAP-L138 (DA850) - http://www.ti.com/lit/ug/spruh82c/spruh82c.pdf
+
+properties:
+ compatible:
+ const: ti,da850-ddr-controller
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ memory-controller@b0000000 {
+ compatible = "ti,da850-ddr-controller";
+ reg = <0xb0000000 0xe8>;
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti-da8xx-ddrctl.txt b/Documentation/devicetree/bindings/memory-controllers/ti-da8xx-ddrctl.txt
deleted file mode 100644
index ec1dd408d573..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/ti-da8xx-ddrctl.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-* Device tree bindings for Texas Instruments da8xx DDR2/mDDR memory controller
-
-The DDR2/mDDR memory controller present on Texas Instruments da8xx SoCs features
-a set of registers which allow to tweak the controller's behavior.
-
-Documentation:
-OMAP-L138 (DA850) - http://www.ti.com/lit/ug/spruh82c/spruh82c.pdf
-
-Required properties:
-
-- compatible: "ti,da850-ddr-controller" - for da850 SoC based boards
-- reg: a tuple containing the base address of the memory
- controller and the size of the memory area to map
-
-Example for da850 shown below.
-
-ddrctl {
- compatible = "ti,da850-ddr-controller";
- reg = <0xb0000000 0xe8>;
-};
diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 4991a6415796..2b53dcc0ea61 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -26,10 +26,10 @@ Required properties:
* "x-powers,axp803"
* "x-powers,axp806"
* "x-powers,axp805", "x-powers,axp806"
+ * "x-powers,axp305", "x-powers,axp805", "x-powers,axp806"
* "x-powers,axp809"
* "x-powers,axp813"
- reg: The I2C slave address or RSB hardware address for the AXP chip
-- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
- interrupt-controller: The PMIC has its own internal IRQs
- #interrupt-cells: Should be set to 1
@@ -43,6 +43,7 @@ more information:
AXP20x/LDO3: software-based implementation
Optional properties:
+- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
AXP152/20X: range: 750-1875, Default: 1.5 MHz
AXP22X/8XX: range: 1800-4050, Default: 3 MHz
diff --git a/Documentation/devicetree/bindings/mfd/brcm,cru.yaml b/Documentation/devicetree/bindings/mfd/brcm,cru.yaml
new file mode 100644
index 000000000000..fc1317ab3226
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/brcm,cru.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/brcm,cru.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom CRU
+
+maintainers:
+ - Rafał Miłecki <rafal@milecki.pl>
+
+description: |
+ Broadcom CRU ("Clock and Reset Unit" or "Central Resource Unit") is a hardware
+ block grouping smaller blocks. On Broadcom Northstar platform it contains e.g.
+ clocks, pinctrl, USB PHY and thermal.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - brcm,ns-cru
+ - const: simple-mfd
+
+ reg:
+ description: CRU registers
+
+ ranges: true
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+ pinctrl:
+ $ref: ../pinctrl/brcm,ns-pinmux.yaml
+
+patternProperties:
+ '^clock-controller@[a-f0-9]+$':
+ $ref: ../clock/brcm,iproc-clocks.yaml
+
+ '^thermal@[a-f0-9]+$':
+ $ref: ../thermal/brcm,ns-thermal.yaml
+
+additionalProperties: false
+
+required:
+ - reg
+
+examples:
+ - |
+ cru-bus@1800c100 {
+ compatible = "brcm,ns-cru", "simple-mfd";
+ reg = <0x1800c100 0x1d0>;
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ clock-controller@100 {
+ #clock-cells = <1>;
+ compatible = "brcm,nsp-lcpll0";
+ reg = <0x100 0x14>;
+ clocks = <&osc>;
+ clock-output-names = "lcpll0", "pcie_phy", "sdio", "ddr_phy";
+ };
+
+ clock-controller@140 {
+ #clock-cells = <1>;
+ compatible = "brcm,nsp-genpll";
+ reg = <0x140 0x24>;
+ clocks = <&osc>;
+ clock-output-names = "genpll", "phy", "ethernetclk", "usbclk",
+ "iprocfast", "sata1", "sata2";
+ };
+
+ pinctrl {
+ compatible = "brcm,bcm4708-pinmux";
+ offset = <0x1c0>;
+ };
+
+ thermal@2c0 {
+ compatible = "brcm,ns-thermal";
+ reg = <0x2c0 0x10>;
+ #thermal-sensor-cells = <0>;
+ };
+ };
diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
index 8e355cddd437..22edcb4b212f 100644
--- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
@@ -34,13 +34,14 @@ properties:
interrupt-controller: true
- gpios:
+ interrupts:
maxItems: 1
- description: GPIO used for IRQs
regulators:
type: object
+ additionalProperties: false
+
properties:
'#address-cells':
const: 1
@@ -49,11 +50,13 @@ properties:
const: 0
patternProperties:
- '^ldo[0-9]+@[0-9a-f]$':
+ '^ldo[0-9]+$':
type: object
$ref: "/schemas/regulator/regulator.yaml#"
+ unevaluatedProperties: false
+
required:
- compatible
- reg
@@ -63,69 +66,69 @@ additionalProperties: false
examples:
- |
- /* pmic properties */
pmic: pmic@0 {
- compatible = "hisilicon,hi6421-spmi";
+ compatible = "hisilicon,hi6421v600-spmi";
reg = <0 0>;
#interrupt-cells = <2>;
interrupt-controller;
- gpios = <&gpio28 0 0>;
+ interrupt-parent = <&gpio28>;
+ interrupts = <0 0>;
regulators {
#address-cells = <1>;
#size-cells = <0>;
- ldo3: LDO3 {
+ ldo3: ldo3 {
regulator-name = "ldo3";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <2000000>;
regulator-boot-on;
};
- ldo4: LDO4 {
+ ldo4: ldo4 {
regulator-name = "ldo4";
regulator-min-microvolt = <1725000>;
regulator-max-microvolt = <1900000>;
regulator-boot-on;
};
- ldo9: LDO9 {
+ ldo9: ldo9 {
regulator-name = "ldo9";
regulator-min-microvolt = <1750000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
};
- ldo15: LDO15 {
+ ldo15: ldo15 {
regulator-name = "ldo15";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
regulator-always-on;
};
- ldo16: LDO16 {
+ ldo16: ldo16 {
regulator-name = "ldo16";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
regulator-boot-on;
};
- ldo17: LDO17 {
+ ldo17: ldo17 {
regulator-name = "ldo17";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <3300000>;
};
- ldo33: LDO33 {
+ ldo33: ldo33 {
regulator-name = "ldo33";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
};
- ldo34: LDO34 {
+ ldo34: ldo34 {
regulator-name = "ldo34";
regulator-min-microvolt = <2600000>;
regulator-max-microvolt = <3300000>;
diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
index 779936850ee0..ec3138c1bbfc 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
@@ -53,7 +53,9 @@ patternProperties:
properties:
compatible:
- const: qcom,pm8008-gpio
+ items:
+ - const: qcom,pm8008-gpio
+ - const: qcom,spmi-gpio
reg:
description: Peripheral address of one of the two GPIO peripherals.
@@ -61,6 +63,9 @@ patternProperties:
gpio-controller: true
+ gpio-ranges:
+ maxItems: 1
+
interrupt-controller: true
"#interrupt-cells":
@@ -75,6 +80,7 @@ patternProperties:
- gpio-controller
- interrupt-controller
- "#gpio-cells"
+ - gpio-ranges
- "#interrupt-cells"
additionalProperties: false
@@ -107,10 +113,11 @@ examples:
interrupt-parent = <&tlmm>;
interrupts = <32 IRQ_TYPE_EDGE_RISING>;
- gpio@c000 {
- compatible = "qcom,pm8008-gpio";
+ pm8008_gpios: gpio@c000 {
+ compatible = "qcom,pm8008-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
+ gpio-ranges = <&pm8008_gpios 0 0 2>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index f14ae6da0068..abe3fd817e0b 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -45,9 +45,12 @@ properties:
- microchip,sparx5-cpu-syscon
- mstar,msc313-pmsleep
- rockchip,px30-qos
+ - rockchip,rk3036-qos
- rockchip,rk3066-qos
+ - rockchip,rk3228-qos
- rockchip,rk3288-qos
- rockchip,rk3399-qos
+ - rockchip,rk3568-qos
- samsung,exynos3-sysreg
- samsung,exynos4-sysreg
- samsung,exynos5-sysreg
diff --git a/Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml b/Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml
index 48d4d53c25f9..012d25111054 100644
--- a/Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml
@@ -11,9 +11,9 @@ maintainers:
properties:
compatible:
- oneOf:
- - const: ti,lp87565
- - const: ti,lp87565-q1
+ enum:
+ - ti,lp87565
+ - ti,lp87565-q1
reg:
description: I2C slave address
diff --git a/Documentation/devicetree/bindings/mfd/ti,tps65086.yaml b/Documentation/devicetree/bindings/mfd/ti,tps65086.yaml
new file mode 100644
index 000000000000..6aeedda3be15
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/ti,tps65086.yaml
@@ -0,0 +1,124 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/ti,tps65086.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TPS65086 Power Management Integrated Circuit (PMIC)
+
+maintainers:
+ - Emil Renner Berthing <kernel@esmil.dk>
+
+properties:
+ compatible:
+ const: ti,tps65086
+
+ reg:
+ const: 0x5e
+ description: I2C slave address
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+ description: |
+ The first cell is the IRQ number. The second cell is the flags,
+ encoded as trigger masks from ../interrupt-controller/interrupts.txt.
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+ description: |
+ The first cell is the pin number and the second cell is used to specify
+ flags. See ../gpio/gpio.txt for more information.
+
+ regulators:
+ type: object
+ description: |
+ List of child nodes that specify the regulator initialization data.
+ Child nodes must be named after their hardware counterparts:
+ buck[1-6], ldoa[1-3], swa1, swb[1-2], and vtt.
+ Each child node is defined using the standard binding for regulators and
+ the optional regulator properties defined below.
+
+ patternProperties:
+ "^buck[1-6]$":
+ type: object
+ $ref: ../regulator/regulator.yaml
+
+ properties:
+ regulator-name: true
+ regulator-boot-on: true
+ regulator-always-on: true
+ regulator-min-microvolt: true
+ regulator-max-microvolt: true
+ ti,regulator-step-size-25mv:
+ type: boolean
+ description: |
+ Set this if the regulator is factory set with a 25mv step voltage
+ mapping.
+ ti,regulator-decay:
+ type: boolean
+ description: |
+ Set this if the output needs to decay, default is for the output
+ to slew down.
+
+ additionalProperties: false
+
+ "^(ldoa[1-3]|swa1|swb[1-2]|vtt)$":
+ type: object
+ $ref: ../regulator/regulator.yaml
+
+ properties:
+ regulator-name: true
+ regulator-boot-on: true
+ regulator-always-on: true
+ regulator-min-microvolt: true
+ regulator-max-microvolt: true
+
+ additionalProperties: false
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - '#gpio-cells'
+ - regulators
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic: pmic@5e {
+ compatible = "ti,tps65086";
+ reg = <0x5e>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ regulators {
+ buck1 {
+ regulator-name = "vcc1";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <1600000>;
+ regulator-boot-on;
+ ti,regulator-decay;
+ ti,regulator-step-size-25mv;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/mfd/tps65086.txt b/Documentation/devicetree/bindings/mfd/tps65086.txt
deleted file mode 100644
index 67eac0ed32df..000000000000
--- a/Documentation/devicetree/bindings/mfd/tps65086.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-* TPS65086 Power Management Integrated Circuit (PMIC) bindings
-
-Required properties:
- - compatible : Should be "ti,tps65086".
- - reg : I2C slave address.
- - interrupts : The interrupt line the device is connected to.
- - interrupt-controller : Marks the device node as an interrupt controller.
- - #interrupt-cells : The number of cells to describe an IRQ, should be 2.
- The first cell is the IRQ number.
- The second cell is the flags, encoded as trigger
- masks from ../interrupt-controller/interrupts.txt.
- - gpio-controller : Marks the device node as a GPIO Controller.
- - #gpio-cells : Should be two. The first cell is the pin number and
- the second cell is used to specify flags.
- See ../gpio/gpio.txt for more information.
- - regulators: : List of child nodes that specify the regulator
- initialization data. Child nodes must be named
- after their hardware counterparts: buck[1-6],
- ldoa[1-3], swa1, swb[1-2], and vtt. Each child
- node is defined using the standard binding for
- regulators and the optional regulator properties
- defined below.
-
-Optional regulator properties:
- - ti,regulator-step-size-25mv : This is applicable for buck[1-6], set this
- if the regulator is factory set with a 25mv
- step voltage mapping.
- - ti,regulator-decay : This is applicable for buck[1-6], set this if
- the output needs to decay, default is for
- the output to slew down.
-
-Example:
-
- pmic: tps65086@5e {
- compatible = "ti,tps65086";
- reg = <0x5e>;
- interrupt-parent = <&gpio1>;
- interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-controller;
- #gpio-cells = <2>;
-
- regulators {
- buck1 {
- regulator-name = "vcc1";
- regulator-min-microvolt = <1600000>;
- regulator-max-microvolt = <1600000>;
- regulator-boot-on;
- ti,regulator-decay;
- ti,regulator-step-size-25mv;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/misc/eeprom-93xx46.txt b/Documentation/devicetree/bindings/misc/eeprom-93xx46.txt
deleted file mode 100644
index 72ea0af368d4..000000000000
--- a/Documentation/devicetree/bindings/misc/eeprom-93xx46.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-EEPROMs (SPI) compatible with Microchip Technology 93xx46 family.
-
-Required properties:
-- compatible : shall be one of:
- "atmel,at93c46"
- "atmel,at93c46d"
- "atmel,at93c56"
- "atmel,at93c66"
- "eeprom-93xx46"
- "microchip,93lc46b"
-- data-size : number of data bits per word (either 8 or 16)
-
-Optional properties:
-- read-only : parameter-less property which disables writes to the EEPROM
-- select-gpios : if present, specifies the GPIO that will be asserted prior to
- each access to the EEPROM (e.g. for SPI bus multiplexing)
-
-Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
-apply. In particular, "reg" and "spi-max-frequency" properties must be given.
-
-Example:
- eeprom@0 {
- compatible = "eeprom-93xx46";
- reg = <0>;
- spi-max-frequency = <1000000>;
- spi-cs-high;
- data-size = <8>;
- select-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;
- };
diff --git a/Documentation/devicetree/bindings/misc/eeprom-93xx46.yaml b/Documentation/devicetree/bindings/misc/eeprom-93xx46.yaml
new file mode 100644
index 000000000000..44fd2f6f0d8a
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/eeprom-93xx46.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/eeprom-93xx46.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip 93xx46 SPI compatible EEPROM family dt bindings
+
+maintainers:
+ - Cory Tusar <cory.tusar@pid1solutions.com>
+
+properties:
+ compatible:
+ enum:
+ - atmel,at93c46
+ - atmel,at93c46d
+ - atmel,at93c56
+ - atmel,at93c66
+ - eeprom-93xx46
+ - microchip,93lc46b
+
+ data-size:
+ description: number of data bits per word
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [8, 16]
+
+ reg:
+ description: chip select of EEPROM
+ maxItems: 1
+
+ spi-max-frequency: true
+ spi-cs-high: true
+
+ read-only:
+ description:
+ parameter-less property which disables writes to the EEPROM
+ type: boolean
+
+ select-gpios:
+ description:
+ specifies the GPIO that needs to be asserted prior to each access
+ of EEPROM (e.g. for SPI bus multiplexing)
+ maxItems: 1
+
+
+required:
+ - compatible
+ - reg
+ - data-size
+ - spi-max-frequency
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ compatible = "eeprom-93xx46";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ spi-cs-high;
+ data-size = <8>;
+ select-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/misc/ge-achc.txt b/Documentation/devicetree/bindings/misc/ge-achc.txt
deleted file mode 100644
index 77df94d7a32f..000000000000
--- a/Documentation/devicetree/bindings/misc/ge-achc.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-* GE Healthcare USB Management Controller
-
-A device which handles data aquisition from compatible USB based peripherals.
-SPI is used for device management.
-
-Note: This device does not expose the peripherals as USB devices.
-
-Required properties:
-
-- compatible : Should be "ge,achc"
-
-Required SPI properties:
-
-- reg : Should be address of the device chip select within
- the controller.
-
-- spi-max-frequency : Maximum SPI clocking speed of device in Hz, should be
- 1MHz for the GE ACHC.
-
-Example:
-
-spidev0: spi@0 {
- compatible = "ge,achc";
- reg = <0>;
- spi-max-frequency = <1000000>;
-};
diff --git a/Documentation/devicetree/bindings/misc/ge-achc.yaml b/Documentation/devicetree/bindings/misc/ge-achc.yaml
new file mode 100644
index 000000000000..ff07aa62ed57
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/ge-achc.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+# Copyright (C) 2021 GE Inc.
+# Copyright (C) 2021 Collabora Ltd.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/ge-achc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GE Healthcare USB Management Controller
+
+description: |
+ A device which handles data acquisition from compatible USB based peripherals.
+ SPI is used for device management.
+
+ Note: This device does not expose the peripherals as USB devices.
+
+maintainers:
+ - Sebastian Reichel <sre@kernel.org>
+
+properties:
+ compatible:
+ items:
+ - const: ge,achc
+ - const: nxp,kinetis-k20
+
+ clocks:
+ maxItems: 1
+
+ vdd-supply:
+ description: Digital power supply regulator on VDD pin
+
+ vdda-supply:
+ description: Analog power supply regulator on VDDA pin
+
+ reg:
+ items:
+ - description: Control interface
+ - description: Firmware programming interface
+
+ reset-gpios:
+ description: GPIO used for hardware reset.
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - reg
+ - reset-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ spi@1 {
+ compatible = "ge,achc", "nxp,kinetis-k20";
+ reg = <1>, <0>;
+ clocks = <&achc_24M>;
+ reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
index 44919d48d241..c459f169a904 100644
--- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
@@ -122,7 +122,7 @@ on various other factors also like;
so the device should have enough free bytes available its OOB/Spare
area to accommodate ECC for entire page. In general following expression
helps in determining if given device can accommodate ECC syndrome:
- "2 + (PAGESIZE / 512) * ECC_BYTES" >= OOBSIZE"
+ "2 + (PAGESIZE / 512) * ECC_BYTES" <= OOBSIZE"
where
OOBSIZE number of bytes in OOB/spare area
PAGESIZE number of bytes in main-area of device page
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
index c8567b40fe13..2133be0d52f2 100644
--- a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
@@ -10,7 +10,7 @@ Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
Required properties:
- bank-width: Width of NOR flash in bytes. GPMC supports 8-bit and
16-bit devices and so must be either 1 or 2 bytes.
-- compatible: Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+- compatible: Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
- gpmc,cs-on-ns: Chip-select assertion time
- gpmc,cs-rd-off-ns: Chip-select de-assertion time for reads
- gpmc,cs-wr-off-ns: Chip-select de-assertion time for writes
@@ -21,7 +21,7 @@ Required properties:
- gpmc,access-ns: Start cycle to first data capture (read access)
- gpmc,rd-cycle-ns: Total read cycle time
- gpmc,wr-cycle-ns: Total write cycle time
-- linux,mtd-name: Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+- linux,mtd-name: Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
- reg: Chip-select, base address (relative to chip-select)
and size of NOR flash. Note that base address will be
typically 0 as this is the start of the chip-select.
diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml b/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
index 13c29cc91b59..f827984936f6 100644
--- a/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
+++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
@@ -23,6 +23,7 @@ properties:
- amd,s29gl256n
- amd,s29gl512n
- arm,versatile-flash
+ - arm,vexpress-flash
- cortina,gemini-flash
- cypress,hyperflash
- ge,imp3a-firmware-mirror
diff --git a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.txt b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.txt
deleted file mode 100644
index fd0ebe4e3415..000000000000
--- a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-RedBoot FLASH Image System (FIS) Partitions
-===========================================
-
-The FLASH Image System (FIS) directory is a flash description
-format closely associated with the RedBoot boot loader.
-
-It uses one single flash eraseblock in the flash to store an index of
-all images in the flash.
-
-This block size will vary depending on flash but is typically
-32 KB in size.
-
-Required properties:
-- compatible : (required) must be "redboot-fis"
-- fis-index-block : (required) a index to the eraseblock containing
- the FIS directory on this device. On a flash memory with 32KB
- eraseblocks, 0 means the first eraseblock at 0x00000000, 1 means the
- second eraseblock at 0x00008000 and so on.
-
-Example:
-
-flash@0 {
- partitions {
- compatible = "redboot-fis";
- fis-index-block = <0>;
- };
-};
diff --git a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
new file mode 100644
index 000000000000..fee8d81b5276
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/partitions/redboot-fis.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RedBoot FLASH Image System (FIS) Partitions
+
+description: The FLASH Image System (FIS) directory is a flash description
+ format closely associated with the RedBoot boot loader.
+ It uses one single flash eraseblock in the flash to store an index of
+ all images in the flash.
+ This block size will vary depending on flash but is typically
+ 32 KB in size.
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+properties:
+ compatible:
+ const: redboot-fis
+
+ fis-index-block:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: a index to the eraseblock containing the FIS directory on this
+ device. On a flash memory with 32KB eraseblocks, 0 means the first
+ eraseblock at 0x00000000, 1 means the second eraseblock at 0x00008000 and so on.
+
+required:
+ - compatible
+ - fis-index-block
+
+additionalProperties: false
+
+examples:
+ - |
+ flash {
+ partitions {
+ compatible = "redboot-fis";
+ fis-index-block = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
index 7f2578d48e3f..9eb4bb529ad5 100644
--- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
+++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
@@ -19,7 +19,9 @@ properties:
- const: allwinner,sun8i-v3s-emac
- const: allwinner,sun50i-a64-emac
- items:
- - const: allwinner,sun50i-h6-emac
+ - enum:
+ - allwinner,sun20i-d1-emac
+ - allwinner,sun50i-h6-emac
- const: allwinner,sun50i-a64-emac
reg:
diff --git a/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml b/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml
index c1948ce00081..08a3f1f6aea2 100644
--- a/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml
+++ b/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml
@@ -116,7 +116,6 @@ examples:
snps,mtl-rx-config = <&mtl_rx_setup>;
snps,mtl-tx-config = <&mtl_tx_setup>;
snps,tso;
- status = "okay";
mdio0 {
#address-cells = <1>;
diff --git a/Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml b/Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml
index f2e91d1bf7d7..378ed2d3b003 100644
--- a/Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml
+++ b/Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml
@@ -71,7 +71,6 @@ examples:
ethernet@c8009000 {
compatible = "intel,ixp4xx-ethernet";
reg = <0xc8009000 0x1000>;
- status = "disabled";
queue-rx = <&qmgr 4>;
queue-txready = <&qmgr 21>;
intel,npe-handle = <&npe 1>;
@@ -82,7 +81,6 @@ examples:
ethernet@c800c000 {
compatible = "intel,ixp4xx-ethernet";
reg = <0xc800c000 0x1000>;
- status = "disabled";
queue-rx = <&qmgr 3>;
queue-txready = <&qmgr 20>;
intel,npe-handle = <&npe 2>;
diff --git a/Documentation/devicetree/bindings/net/micrel,ks8851.yaml b/Documentation/devicetree/bindings/net/micrel,ks8851.yaml
new file mode 100644
index 000000000000..5aa7cf2eacb1
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/micrel,ks8851.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/micrel,ks8851.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Micrel KS8851 Ethernet MAC (SPI and Parallel bus options)
+
+maintainers:
+ - Marek Vasut <marex@denx.de>
+
+properties:
+ compatible:
+ enum:
+ - micrel,ks8851 # SPI bus option
+ - micrel,ks8851-mll # Parallel bus option
+
+ interrupts:
+ maxItems: 1
+
+ reg:
+ minItems: 1
+ items:
+ - description: SPI or Parallel bus hardware address
+ - description: Parallel bus command mode address
+
+ reset-gpios:
+ maxItems: 1
+ description:
+ The reset_n input pin
+
+ vdd-supply:
+ description: |
+ Analog 3.3V supply for Ethernet MAC
+
+ vdd-io-supply:
+ description: |
+ Digital 1.8V IO supply for Ethernet MAC
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+allOf:
+ - $ref: ethernet-controller.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: micrel,ks8851
+ then:
+ properties:
+ reg:
+ maxItems: 1
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: micrel,ks8851-mll
+ then:
+ properties:
+ reg:
+ minItems: 2
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ /* SPI bus option */
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ethernet@0 {
+ compatible = "micrel,ks8851";
+ reg = <0>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <90 8>;
+ vdd-supply = <&ext_l2>;
+ vdd-io-supply = <&pm8921_lvs6>;
+ reset-gpios = <&msmgpio 89 0>;
+ };
+ };
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ /* Parallel bus option */
+ memory-controller {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ethernet@1,0 {
+ compatible = "micrel,ks8851-mll";
+ reg = <1 0x0 0x2>, <1 0x2 0x20000>;
+ interrupt-parent = <&gpioc>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/micrel-ks8851.txt b/Documentation/devicetree/bindings/net/micrel-ks8851.txt
deleted file mode 100644
index bbdf9a7359a2..000000000000
--- a/Documentation/devicetree/bindings/net/micrel-ks8851.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-Micrel KS8851 Ethernet mac (MLL)
-
-Required properties:
-- compatible = "micrel,ks8851-mll" of parallel interface
-- reg : 2 physical address and size of registers for data and command
-- interrupts : interrupt connection
-
-Micrel KS8851 Ethernet mac (SPI)
-
-Required properties:
-- compatible = "micrel,ks8851" or the deprecated "ks8851"
-- reg : chip select number
-- interrupts : interrupt connection
-
-Optional properties:
-- vdd-supply: analog 3.3V supply for Ethernet mac
-- vdd-io-supply: digital 1.8V IO supply for Ethernet mac
-- reset-gpios: reset_n input pin
diff --git a/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt b/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
index 87a27d775d48..0a3647fe331b 100644
--- a/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
+++ b/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
@@ -67,7 +67,7 @@ Example:
compatible = "ethernet-phy-id0007.0570";
vsc8531,vddmac = <3300>;
vsc8531,edge-slowdown = <7>;
- vsc8531,led-0-mode = <LINK_1000_ACTIVITY>;
- vsc8531,led-1-mode = <LINK_100_ACTIVITY>;
+ vsc8531,led-0-mode = <VSC8531_LINK_1000_ACTIVITY>;
+ vsc8531,led-1-mode = <VSC8531_LINK_100_ACTIVITY>;
load-save-gpios = <&gpio 10 GPIO_ACTIVE_HIGH>;
};
diff --git a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
index 081742c2b726..64995cbb0f97 100644
--- a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
+++ b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
@@ -90,14 +90,11 @@ examples:
# UART example on Raspberry Pi
- |
uart0 {
- status = "okay";
-
nfc {
compatible = "samsung,s3fwrn82";
en-gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
wake-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
- status = "okay";
};
};
diff --git a/Documentation/devicetree/bindings/net/qca,ar71xx.yaml b/Documentation/devicetree/bindings/net/qca,ar71xx.yaml
index f0db22645d73..cf4d35edaa1b 100644
--- a/Documentation/devicetree/bindings/net/qca,ar71xx.yaml
+++ b/Documentation/devicetree/bindings/net/qca,ar71xx.yaml
@@ -101,8 +101,6 @@ examples:
phy-mode = "gmii";
- status = "disabled";
-
fixed-link {
speed = <1000>;
full-duplex;
@@ -148,32 +146,24 @@ examples:
reg = <0x1>;
phy-handle = <&phy_port0>;
phy-mode = "internal";
-
- status = "disabled";
};
switch_port2: port@2 {
reg = <0x2>;
phy-handle = <&phy_port1>;
phy-mode = "internal";
-
- status = "disabled";
};
switch_port3: port@3 {
reg = <0x3>;
phy-handle = <&phy_port2>;
phy-mode = "internal";
-
- status = "disabled";
};
switch_port4: port@4 {
reg = <0x4>;
phy-handle = <&phy_port3>;
phy-mode = "internal";
-
- status = "disabled";
};
};
@@ -183,34 +173,29 @@ examples:
interrupt-parent = <&switch10>;
- phy_port0: phy@0 {
+ phy_port0: ethernet-phy@0 {
reg = <0x0>;
interrupts = <0>;
- status = "disabled";
};
- phy_port1: phy@1 {
+ phy_port1: ethernet-phy@1 {
reg = <0x1>;
interrupts = <0>;
- status = "disabled";
};
- phy_port2: phy@2 {
+ phy_port2: ethernet-phy@2 {
reg = <0x2>;
interrupts = <0>;
- status = "disabled";
};
- phy_port3: phy@3 {
+ phy_port3: ethernet-phy@3 {
reg = <0x3>;
interrupts = <0>;
- status = "disabled";
};
- phy_port4: phy@4 {
+ phy_port4: ethernet-phy@4 {
reg = <0x4>;
interrupts = <0>;
- status = "disabled";
};
};
};
diff --git a/Documentation/devicetree/bindings/net/realtek-bluetooth.yaml b/Documentation/devicetree/bindings/net/realtek-bluetooth.yaml
index 4f485df69ac3..0634e69dd9a6 100644
--- a/Documentation/devicetree/bindings/net/realtek-bluetooth.yaml
+++ b/Documentation/devicetree/bindings/net/realtek-bluetooth.yaml
@@ -17,10 +17,10 @@ description:
properties:
compatible:
- oneOf:
- - const: "realtek,rtl8723bs-bt"
- - const: "realtek,rtl8723cs-bt"
- - const: "realtek,rtl8822cs-bt"
+ enum:
+ - realtek,rtl8723bs-bt
+ - realtek,rtl8723cs-bt
+ - realtek,rtl8822cs-bt
device-wake-gpios:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/net/renesas,etheravb.yaml b/Documentation/devicetree/bindings/net/renesas,etheravb.yaml
index 005868f703a6..4c927d2c17d3 100644
--- a/Documentation/devicetree/bindings/net/renesas,etheravb.yaml
+++ b/Documentation/devicetree/bindings/net/renesas,etheravb.yaml
@@ -43,23 +43,20 @@ properties:
- renesas,etheravb-r8a779a0 # R-Car V3U
- const: renesas,etheravb-rcar-gen3 # R-Car Gen3 and RZ/G2
+ - items:
+ - enum:
+ - renesas,r9a07g044-gbeth # RZ/G2{L,LC}
+ - const: renesas,rzg2l-gbeth # RZ/G2L
+
reg: true
interrupts: true
interrupt-names: true
- clocks:
- minItems: 1
- items:
- - description: AVB functional clock
- - description: Optional TXC reference clock
+ clocks: true
- clock-names:
- minItems: 1
- items:
- - const: fck
- - const: refclk
+ clock-names: true
iommus:
maxItems: 1
@@ -145,14 +142,20 @@ allOf:
properties:
compatible:
contains:
- const: renesas,etheravb-rcar-gen2
+ enum:
+ - renesas,etheravb-rcar-gen2
+ - renesas,rzg2l-gbeth
then:
properties:
interrupts:
- maxItems: 1
+ minItems: 1
+ maxItems: 3
interrupt-names:
+ minItems: 1
items:
- const: mux
+ - const: fil
+ - const: arp_ns
rx-internal-delay-ps: false
else:
properties:
@@ -208,6 +211,36 @@ allOf:
tx-internal-delay-ps:
const: 2000
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,rzg2l-gbeth
+ then:
+ properties:
+ clocks:
+ items:
+ - description: Main clock
+ - description: Register access clock
+ - description: Reference clock for RGMII
+ clock-names:
+ items:
+ - const: axi
+ - const: chi
+ - const: refclk
+ else:
+ properties:
+ clocks:
+ minItems: 1
+ items:
+ - description: AVB functional clock
+ - description: Optional TXC reference clock
+ clock-names:
+ minItems: 1
+ items:
+ - const: fck
+ - const: refclk
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
index 783b9e32cf66..4b97a0f1175b 100644
--- a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
+++ b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
@@ -53,10 +53,10 @@ properties:
"#size-cells": true
compatible:
- oneOf:
- - const: ti,am654-cpsw-nuss
- - const: ti,j721e-cpsw-nuss
- - const: ti,am642-cpsw-nuss
+ enum:
+ - ti,am654-cpsw-nuss
+ - ti,j721e-cpsw-nuss
+ - ti,am642-cpsw-nuss
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml b/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
index 4317eba503ca..1a81bf70c88c 100644
--- a/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
+++ b/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
@@ -45,9 +45,9 @@ properties:
pattern: "^cpts@[0-9a-f]+$"
compatible:
- oneOf:
- - const: ti,am65-cpts
- - const: ti,j721e-cpts
+ enum:
+ - ti,am65-cpts
+ - ti,j721e-cpts
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml b/Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml
new file mode 100644
index 000000000000..dbe4ffdd644c
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/nintendo-otp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nintendo Wii and Wii U OTP Device Tree Bindings
+
+description: |
+ This binding represents the OTP memory as found on a Nintendo Wii or Wii U,
+ which contains common and per-console keys, signatures and related data
+ required to access peripherals.
+
+ See https://wiiubrew.org/wiki/Hardware/OTP
+
+maintainers:
+ - Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+
+allOf:
+ - $ref: "nvmem.yaml#"
+
+properties:
+ compatible:
+ enum:
+ - nintendo,hollywood-otp
+ - nintendo,latte-otp
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ otp@d8001ec {
+ compatible = "nintendo,latte-otp";
+ reg = <0x0d8001ec 0x8>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.yaml b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
index b8dc3d2b6e92..456fb808100a 100644
--- a/Documentation/devicetree/bindings/nvmem/nvmem.yaml
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
@@ -40,7 +40,7 @@ properties:
maxItems: 1
patternProperties:
- "^.*@[0-9a-f]+$":
+ "@[0-9a-f]+(,[0-7])?$":
type: object
properties:
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
index 861b205016b1..dede8892ee01 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
@@ -51,6 +51,9 @@ properties:
vcc-supply:
description: Our power supply.
+ power-domains:
+ maxItems: 1
+
# Needed if any child nodes are present.
"#address-cells":
const: 1
diff --git a/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml b/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
new file mode 100644
index 000000000000..2578e39deda9
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/socionext,uniphier-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Socionext UniPhier eFuse bindings
+
+maintainers:
+ - Keiji Hayashibara <hayashibara.keiji@socionext.com>
+ - Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+allOf:
+ - $ref: "nvmem.yaml#"
+
+properties:
+ "#address-cells": true
+ "#size-cells": true
+
+ compatible:
+ const: socionext,uniphier-efuse
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ // The UniPhier eFuse should be a subnode of a "soc-glue" node.
+
+ soc-glue@5f900000 {
+ compatible = "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x5f900000 0x2000>;
+
+ efuse@100 {
+ compatible = "socionext,uniphier-efuse";
+ reg = <0x100 0x28>;
+ };
+
+ efuse@200 {
+ compatible = "socionext,uniphier-efuse";
+ reg = <0x200 0x68>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Data cells */
+ usb_rterm0: trim@54,4 {
+ reg = <0x54 1>;
+ bits = <4 2>;
+ };
+ usb_rterm1: trim@55,4 {
+ reg = <0x55 1>;
+ bits = <4 2>;
+ };
+ usb_rterm2: trim@58,4 {
+ reg = <0x58 1>;
+ bits = <4 2>;
+ };
+ usb_rterm3: trim@59,4 {
+ reg = <0x59 1>;
+ bits = <4 2>;
+ };
+ usb_sel_t0: trim@54,0 {
+ reg = <0x54 1>;
+ bits = <0 4>;
+ };
+ usb_sel_t1: trim@55,0 {
+ reg = <0x55 1>;
+ bits = <0 4>;
+ };
+ usb_sel_t2: trim@58,0 {
+ reg = <0x58 1>;
+ bits = <0 4>;
+ };
+ usb_sel_t3: trim@59,0 {
+ reg = <0x59 1>;
+ bits = <0 4>;
+ };
+ usb_hs_i0: trim@56,0 {
+ reg = <0x56 1>;
+ bits = <0 4>;
+ };
+ usb_hs_i2: trim@5a,0 {
+ reg = <0x5a 1>;
+ bits = <0 4>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt b/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt
deleted file mode 100644
index eccf490d5a6d..000000000000
--- a/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-= UniPhier eFuse device tree bindings =
-
-This UniPhier eFuse must be under soc-glue.
-
-Required properties:
-- compatible: should be "socionext,uniphier-efuse"
-- reg: should contain the register location and length
-
-= Data cells =
-Are child nodes of efuse, bindings of which as described in
-bindings/nvmem/nvmem.txt
-
-Example:
-
- soc-glue@5f900000 {
- compatible = "socionext,uniphier-ld20-soc-glue-debug",
- "simple-mfd";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x0 0x5f900000 0x2000>;
-
- efuse@100 {
- compatible = "socionext,uniphier-efuse";
- reg = <0x100 0x28>;
- };
-
- efuse@200 {
- compatible = "socionext,uniphier-efuse";
- reg = <0x200 0x68>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- /* Data cells */
- usb_mon: usb-mon@54 {
- reg = <0x54 0xc>;
- };
- };
- };
-
-= Data consumers =
-Are device nodes which consume nvmem data cells.
-
-Example:
-
- usb {
- ...
- nvmem-cells = <&usb_mon>;
- nvmem-cell-names = "usb_mon";
- }
diff --git a/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt b/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt
index b6acbe694ffb..c3a75ac6e59d 100644
--- a/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt
@@ -3,7 +3,7 @@ Amlogic Meson AXG DWC PCIE SoC controller
Amlogic Meson 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-pcie.txt.
+Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml.
Additional properties are described here:
@@ -33,7 +33,7 @@ Required properties:
- phy-names: must contain "pcie"
- device_type:
- should be "pci". As specified in designware-pcie.txt
+ should be "pci". As specified in snps,dw-pcie.yaml
Example configuration:
diff --git a/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt b/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt
index 979dc7b6cfe8..cc6dcdb676b9 100644
--- a/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt
@@ -1,7 +1,7 @@
* Axis ARTPEC-6 PCIe interface
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
-and thus inherits all the common properties defined in designware-pcie.txt.
+and thus inherits all the common properties defined in snps,dw-pcie.yaml.
Required properties:
- compatible: "axis,artpec6-pcie", "snps,dw-pcie" for ARTPEC-6 in RC mode;
diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt
deleted file mode 100644
index 78494c4050f7..000000000000
--- a/Documentation/devicetree/bindings/pci/designware-pcie.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-* Synopsys DesignWare PCIe interface
-
-Required properties:
-- compatible:
- "snps,dw-pcie" for RC mode;
- "snps,dw-pcie-ep" for EP mode;
-- reg: For designware cores version < 4.80 contains the configuration
- address space. For designware core version >= 4.80, contains
- the configuration and ATU address space
-- reg-names: Must be "config" for the PCIe configuration space and "atu" for
- the ATU address space.
- (The old way of getting the configuration address space from "ranges"
- is deprecated and should be avoided.)
-RC mode:
-- #address-cells: set to <3>
-- #size-cells: set to <2>
-- device_type: set to "pci"
-- ranges: ranges for the PCI memory and I/O regions
-- #interrupt-cells: set to <1>
-- interrupt-map-mask and interrupt-map: standard PCI
- properties to define the mapping of the PCIe interface to interrupt
- numbers.
-EP mode:
-- num-ib-windows: number of inbound address translation windows
-- num-ob-windows: number of outbound address translation windows
-
-Optional properties:
-- num-lanes: number of lanes to use (this property should be specified unless
- the link is brought already up in BIOS)
-- reset-gpio: GPIO pin number of power good signal
-- clocks: Must contain an entry for each entry in clock-names.
- See ../clocks/clock-bindings.txt for details.
-- clock-names: Must include the following entries:
- - "pcie"
- - "pcie_bus"
-- snps,enable-cdm-check: This is a boolean property and if present enables
- automatic checking of CDM (Configuration Dependent Module) registers
- for data corruption. CDM registers include standard PCIe configuration
- space registers, Port Logic registers, DMA and iATU (internal Address
- Translation Unit) registers.
-RC mode:
-- num-viewport: number of view ports configured in hardware. If a platform
- does not specify it, the driver assumes 2.
-- bus-range: PCI bus numbers covered (it is recommended for new devicetrees
- to specify this property, to keep backwards compatibility a range of
- 0x00-0xff is assumed if not present)
-
-EP mode:
-- max-functions: maximum number of functions that can be configured
-
-Example configuration:
-
- pcie: pcie@dfc00000 {
- compatible = "snps,dw-pcie";
- reg = <0xdfc00000 0x0001000>, /* IP registers */
- <0xd0000000 0x0002000>; /* Configuration space */
- reg-names = "dbi", "config";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- ranges = <0x81000000 0 0x00000000 0xde000000 0 0x00010000
- 0x82000000 0 0xd0400000 0xd0400000 0 0x0d000000>;
- interrupts = <25>, <24>;
- #interrupt-cells = <1>;
- num-lanes = <1>;
- };
-or
- pcie: pcie@dfc00000 {
- compatible = "snps,dw-pcie-ep";
- reg = <0xdfc00000 0x0001000>, /* IP registers 1 */
- <0xdfc01000 0x0001000>, /* IP registers 2 */
- <0xd0000000 0x2000000>; /* Configuration space */
- reg-names = "dbi", "dbi2", "addr_space";
- num-ib-windows = <6>;
- num-ob-windows = <2>;
- num-lanes = <1>;
- };
diff --git a/Documentation/devicetree/bindings/pci/faraday,ftpci100.txt b/Documentation/devicetree/bindings/pci/faraday,ftpci100.txt
deleted file mode 100644
index 5f8cb4962f8d..000000000000
--- a/Documentation/devicetree/bindings/pci/faraday,ftpci100.txt
+++ /dev/null
@@ -1,135 +0,0 @@
-Faraday Technology FTPCI100 PCI Host Bridge
-
-This PCI bridge is found inside that Cortina Systems Gemini SoC platform and
-is a generic IP block from Faraday Technology. It exists in two variants:
-plain and dual PCI. The plain version embeds a cascading interrupt controller
-into the host bridge. The dual version routes the interrupts to the host
-chips interrupt controller.
-
-The host controller appear on the PCI bus with vendor ID 0x159b (Faraday
-Technology) and product ID 0x4321.
-
-Mandatory properties:
-
-- compatible: ranging from specific to generic, should be one of
- "cortina,gemini-pci", "faraday,ftpci100"
- "cortina,gemini-pci-dual", "faraday,ftpci100-dual"
- "faraday,ftpci100"
- "faraday,ftpci100-dual"
-- reg: memory base and size for the host bridge
-- #address-cells: set to <3>
-- #size-cells: set to <2>
-- #interrupt-cells: set to <1>
-- bus-range: set to <0x00 0xff>
-- device_type, set to "pci"
-- ranges: see pci.txt
-- interrupt-map-mask: see pci.txt
-- interrupt-map: see pci.txt
-- dma-ranges: three ranges for the inbound memory region. The ranges must
- be aligned to a 1MB boundary, and may be 1MB, 2MB, 4MB, 8MB, 16MB, 32MB, 64MB,
- 128MB, 256MB, 512MB, 1GB or 2GB in size. The memory should be marked as
- pre-fetchable.
-
-Optional properties:
-- clocks: when present, this should contain the peripheral clock (PCLK) and the
- PCI clock (PCICLK). If these are not present, they are assumed to be
- hard-wired enabled and always on. The PCI clock will be 33 or 66 MHz.
-- clock-names: when present, this should contain "PCLK" for the peripheral
- clock and "PCICLK" for the PCI-side clock.
-
-Mandatory subnodes:
-- For "faraday,ftpci100" a node representing the interrupt-controller inside the
- host bridge is mandatory. It has the following mandatory properties:
- - interrupt: see interrupt-controller/interrupts.txt
- - interrupt-controller: see interrupt-controller/interrupts.txt
- - #address-cells: set to <0>
- - #interrupt-cells: set to <1>
-
-I/O space considerations:
-
-The plain variant has 128MiB of non-prefetchable memory space, whereas the
-"dual" variant has 64MiB. Take this into account when describing the ranges.
-
-Interrupt map considerations:
-
-The "dual" variant will get INT A, B, C, D from the system interrupt controller
-and should point to respective interrupt in that controller in its
-interrupt-map.
-
-The code which is the only documentation of how the Faraday PCI (the non-dual
-variant) interrupts assigns the default interrupt mapping/swizzling has
-typically been like this, doing the swizzling on the interrupt controller side
-rather than in the interconnect:
-
-interrupt-map-mask = <0xf800 0 0 7>;
-interrupt-map =
- <0x4800 0 0 1 &pci_intc 0>, /* Slot 9 */
- <0x4800 0 0 2 &pci_intc 1>,
- <0x4800 0 0 3 &pci_intc 2>,
- <0x4800 0 0 4 &pci_intc 3>,
- <0x5000 0 0 1 &pci_intc 1>, /* Slot 10 */
- <0x5000 0 0 2 &pci_intc 2>,
- <0x5000 0 0 3 &pci_intc 3>,
- <0x5000 0 0 4 &pci_intc 0>,
- <0x5800 0 0 1 &pci_intc 2>, /* Slot 11 */
- <0x5800 0 0 2 &pci_intc 3>,
- <0x5800 0 0 3 &pci_intc 0>,
- <0x5800 0 0 4 &pci_intc 1>,
- <0x6000 0 0 1 &pci_intc 3>, /* Slot 12 */
- <0x6000 0 0 2 &pci_intc 0>,
- <0x6000 0 0 3 &pci_intc 1>,
- <0x6000 0 0 4 &pci_intc 2>;
-
-Example:
-
-pci@50000000 {
- compatible = "cortina,gemini-pci", "faraday,ftpci100";
- reg = <0x50000000 0x100>;
- interrupts = <8 IRQ_TYPE_LEVEL_HIGH>, /* PCI A */
- <26 IRQ_TYPE_LEVEL_HIGH>, /* PCI B */
- <27 IRQ_TYPE_LEVEL_HIGH>, /* PCI C */
- <28 IRQ_TYPE_LEVEL_HIGH>; /* PCI D */
- #address-cells = <3>;
- #size-cells = <2>;
- #interrupt-cells = <1>;
-
- bus-range = <0x00 0xff>;
- ranges = /* 1MiB I/O space 0x50000000-0x500fffff */
- <0x01000000 0 0 0x50000000 0 0x00100000>,
- /* 128MiB non-prefetchable memory 0x58000000-0x5fffffff */
- <0x02000000 0 0x58000000 0x58000000 0 0x08000000>;
-
- /* DMA ranges */
- dma-ranges =
- /* 128MiB at 0x00000000-0x07ffffff */
- <0x02000000 0 0x00000000 0x00000000 0 0x08000000>,
- /* 64MiB at 0x00000000-0x03ffffff */
- <0x02000000 0 0x00000000 0x00000000 0 0x04000000>,
- /* 64MiB at 0x00000000-0x03ffffff */
- <0x02000000 0 0x00000000 0x00000000 0 0x04000000>;
-
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map =
- <0x4800 0 0 1 &pci_intc 0>, /* Slot 9 */
- <0x4800 0 0 2 &pci_intc 1>,
- <0x4800 0 0 3 &pci_intc 2>,
- <0x4800 0 0 4 &pci_intc 3>,
- <0x5000 0 0 1 &pci_intc 1>, /* Slot 10 */
- <0x5000 0 0 2 &pci_intc 2>,
- <0x5000 0 0 3 &pci_intc 3>,
- <0x5000 0 0 4 &pci_intc 0>,
- <0x5800 0 0 1 &pci_intc 2>, /* Slot 11 */
- <0x5800 0 0 2 &pci_intc 3>,
- <0x5800 0 0 3 &pci_intc 0>,
- <0x5800 0 0 4 &pci_intc 1>,
- <0x6000 0 0 1 &pci_intc 3>, /* Slot 12 */
- <0x6000 0 0 2 &pci_intc 0>,
- <0x6000 0 0 3 &pci_intc 0>,
- <0x6000 0 0 4 &pci_intc 0>;
- pci_intc: interrupt-controller {
- interrupt-parent = <&intcon>;
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- };
-};
diff --git a/Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml b/Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml
new file mode 100644
index 000000000000..92efbf0f1297
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml
@@ -0,0 +1,174 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/faraday,ftpci100.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Faraday Technology FTPCI100 PCI Host Bridge
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+ This PCI bridge is found inside that Cortina Systems Gemini SoC platform and
+ is a generic IP block from Faraday Technology. It exists in two variants:
+ plain and dual PCI. The plain version embeds a cascading interrupt controller
+ into the host bridge. The dual version routes the interrupts to the host
+ chips interrupt controller.
+ The host controller appear on the PCI bus with vendor ID 0x159b (Faraday
+ Technology) and product ID 0x4321.
+ I/O space considerations:
+ The plain variant has 128MiB of non-prefetchable memory space, whereas the
+ "dual" variant has 64MiB. Take this into account when describing the ranges.
+
+ Interrupt map considerations:
+
+ The "dual" variant will get INT A, B, C, D from the system interrupt controller
+ and should point to respective interrupt in that controller in its interrupt-map.
+
+ The code which is the only documentation of how the Faraday PCI (the non-dual
+ variant) interrupts assigns the default interrupt mapping/swizzling has
+ typically been like this, doing the swizzling on the interrupt controller side
+ rather than in the interconnect:
+
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map =
+ <0x4800 0 0 1 &pci_intc 0>, /* Slot 9 */
+ <0x4800 0 0 2 &pci_intc 1>,
+ <0x4800 0 0 3 &pci_intc 2>,
+ <0x4800 0 0 4 &pci_intc 3>,
+ <0x5000 0 0 1 &pci_intc 1>, /* Slot 10 */
+ <0x5000 0 0 2 &pci_intc 2>,
+ <0x5000 0 0 3 &pci_intc 3>,
+ <0x5000 0 0 4 &pci_intc 0>,
+ <0x5800 0 0 1 &pci_intc 2>, /* Slot 11 */
+ <0x5800 0 0 2 &pci_intc 3>,
+ <0x5800 0 0 3 &pci_intc 0>,
+ <0x5800 0 0 4 &pci_intc 1>,
+ <0x6000 0 0 1 &pci_intc 3>, /* Slot 12 */
+ <0x6000 0 0 2 &pci_intc 0>,
+ <0x6000 0 0 3 &pci_intc 1>,
+ <0x6000 0 0 4 &pci_intc 2>;
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - const: cortina,gemini-pci
+ - const: faraday,ftpci100
+ - items:
+ - const: cortina,gemini-pci-dual
+ - const: faraday,ftpci100-dual
+ - const: faraday,ftpci100
+ - const: faraday,ftpci100-dual
+
+ reg:
+ maxItems: 1
+
+ "#address-cells":
+ const: 3
+
+ "#interrupt-cells":
+ const: 1
+
+ ranges:
+ minItems: 2
+
+ dma-ranges:
+ minItems: 3
+ description: |
+ three ranges for the inbound memory region. The ranges must
+ be aligned to a 1MB boundary, and may be 1MB, 2MB, 4MB, 8MB, 16MB, 32MB, 64MB,
+ 128MB, 256MB, 512MB, 1GB or 2GB in size. The memory should be marked as
+ pre-fetchable.
+
+ clocks:
+ items:
+ - description: peripheral clock (PCLK)
+ - description: PCI clock (PCICLK).
+ description: |
+ If these are not present, they are assumed to be
+ hard-wired enabled and always on. The PCI clock will be 33 or 66 MHz.
+
+ clock-names:
+ items:
+ - const: PCLK
+ - const: PCICLK
+
+ interrupt-controller:
+ type: object
+
+required:
+ - reg
+ - compatible
+ - "#interrupt-cells"
+ - interrupt-map-mask
+ - interrupt-map
+ - dma-ranges
+
+if:
+ properties:
+ compatible:
+ contains:
+ const: faraday,ftpci100
+then:
+ required:
+ - interrupt-controller
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ pci@50000000 {
+ compatible = "cortina,gemini-pci", "faraday,ftpci100";
+ reg = <0x50000000 0x100>;
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ bus-range = <0x00 0xff>;
+ ranges = /* 1MiB I/O space 0x50000000-0x500fffff */
+ <0x01000000 0 0 0x50000000 0 0x00100000>,
+ /* 128MiB non-prefetchable memory 0x58000000-0x5fffffff */
+ <0x02000000 0 0x58000000 0x58000000 0 0x08000000>;
+
+ /* DMA ranges */
+ dma-ranges =
+ /* 128MiB at 0x00000000-0x07ffffff */
+ <0x02000000 0 0x00000000 0x00000000 0 0x08000000>,
+ /* 64MiB at 0x00000000-0x03ffffff */
+ <0x02000000 0 0x00000000 0x00000000 0 0x04000000>,
+ /* 64MiB at 0x00000000-0x03ffffff */
+ <0x02000000 0 0x00000000 0x00000000 0 0x04000000>;
+
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map =
+ <0x4800 0 0 1 &pci_intc 0>, /* Slot 9 */
+ <0x4800 0 0 2 &pci_intc 1>,
+ <0x4800 0 0 3 &pci_intc 2>,
+ <0x4800 0 0 4 &pci_intc 3>,
+ <0x5000 0 0 1 &pci_intc 1>, /* Slot 10 */
+ <0x5000 0 0 2 &pci_intc 2>,
+ <0x5000 0 0 3 &pci_intc 3>,
+ <0x5000 0 0 4 &pci_intc 0>,
+ <0x5800 0 0 1 &pci_intc 2>, /* Slot 11 */
+ <0x5800 0 0 2 &pci_intc 3>,
+ <0x5800 0 0 3 &pci_intc 0>,
+ <0x5800 0 0 4 &pci_intc 1>,
+ <0x6000 0 0 1 &pci_intc 3>, /* Slot 12 */
+ <0x6000 0 0 2 &pci_intc 0>,
+ <0x6000 0 0 3 &pci_intc 0>,
+ <0x6000 0 0 4 &pci_intc 0>;
+ pci_intc: interrupt-controller {
+ interrupt-parent = <&intcon>;
+ interrupt-controller;
+ interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
deleted file mode 100644
index d8971ab99274..000000000000
--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
+++ /dev/null
@@ -1,100 +0,0 @@
-* Freescale i.MX6 PCIe interface
-
-This PCIe host controller is based on the Synopsys DesignWare PCIe IP
-and thus inherits all the common properties defined in designware-pcie.txt.
-
-Required properties:
-- compatible:
- - "fsl,imx6q-pcie"
- - "fsl,imx6sx-pcie",
- - "fsl,imx6qp-pcie"
- - "fsl,imx7d-pcie"
- - "fsl,imx8mq-pcie"
-- reg: base address and length of the PCIe controller
-- interrupts: A list of interrupt outputs of the controller. Must contain an
- entry for each entry in the interrupt-names property.
-- interrupt-names: Must include the following entries:
- - "msi": The interrupt that is asserted when an MSI is received
-- clock-names: Must include the following additional entries:
- - "pcie_phy"
-
-Optional properties:
-- fsl,tx-deemph-gen1: Gen1 De-emphasis value. Default: 0
-- fsl,tx-deemph-gen2-3p5db: Gen2 (3.5db) De-emphasis value. Default: 0
-- fsl,tx-deemph-gen2-6db: Gen2 (6db) De-emphasis value. Default: 20
-- fsl,tx-swing-full: Gen2 TX SWING FULL value. Default: 127
-- fsl,tx-swing-low: TX launch amplitude swing_low value. Default: 127
-- fsl,max-link-speed: Specify PCI gen for link capability. Must be '2' for
- gen2, otherwise will default to gen1. Note that the IMX6 LVDS clock outputs
- do not meet gen2 jitter requirements and thus for gen2 capability a gen2
- compliant clock generator should be used and configured.
-- reset-gpio: Should specify the GPIO for controlling the PCI bus device reset
- signal. It's not polarity aware and defaults to active-low reset sequence
- (L=reset state, H=operation state).
-- reset-gpio-active-high: If present then the reset sequence using the GPIO
- specified in the "reset-gpio" property is reversed (H=reset state,
- L=operation state).
-- vpcie-supply: Should specify the regulator in charge of PCIe port power.
- The regulator will be enabled when initializing the PCIe host and
- disabled either as part of the init process or when shutting down the
- host.
-- vph-supply: Should specify the regulator in charge of VPH one of the three
- PCIe PHY powers. This regulator can be supplied by both 1.8v and 3.3v voltage
- supplies.
-
-Additional required properties for imx6sx-pcie:
-- clock names: Must include the following additional entries:
- - "pcie_inbound_axi"
-- power-domains: Must be set to phandles pointing to the DISPLAY and
- PCIE_PHY power domains
-- power-domain-names: Must be "pcie", "pcie_phy"
-
-Additional required properties for imx7d-pcie and imx8mq-pcie:
-- power-domains: Must be set to a phandle pointing to PCIE_PHY power domain
-- resets: Must contain phandles to PCIe-related reset lines exposed by SRC
- IP block
-- reset-names: Must contain the following entries:
- - "pciephy"
- - "apps"
- - "turnoff"
-- fsl,imx7d-pcie-phy: A phandle to an fsl,imx7d-pcie-phy node.
-
-Additional required properties for imx8mq-pcie:
-- clock-names: Must include the following additional entries:
- - "pcie_aux"
-
-Example:
-
- pcie@01000000 {
- compatible = "fsl,imx6q-pcie", "snps,dw-pcie";
- reg = <0x01ffc000 0x04000>,
- <0x01f00000 0x80000>;
- reg-names = "dbi", "config";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- ranges = <0x00000800 0 0x01f00000 0x01f00000 0 0x00080000
- 0x81000000 0 0 0x01f80000 0 0x00010000
- 0x82000000 0 0x01000000 0x01000000 0 0x00f00000>;
- num-lanes = <1>;
- interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 0x7>;
- interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
- <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
- <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
- <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 144>, <&clks 206>, <&clks 189>;
- clock-names = "pcie", "pcie_bus", "pcie_phy";
- };
-
-* Freescale i.MX7d PCIe PHY
-
-This is the PHY associated with the IMX7d PCIe controller. It's used by the
-PCI-e controller via the fsl,imx7d-pcie-phy phandle.
-
-Required properties:
-- compatible:
- - "fsl,imx7d-pcie-phy"
-- reg: base address and length of the PCIe PHY controller
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
new file mode 100644
index 000000000000..2911e565b260
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
@@ -0,0 +1,202 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/fsl,imx6q-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX6 PCIe host controller
+
+maintainers:
+ - Lucas Stach <l.stach@pengutronix.de>
+ - Richard Zhu <hongxing.zhu@nxp.com>
+
+description: |+
+ This PCIe host controller is based on the Synopsys DesignWare PCIe IP
+ and thus inherits all the common properties defined in snps,dw-pcie.yaml.
+
+allOf:
+ - $ref: /schemas/pci/snps,dw-pcie.yaml#
+
+properties:
+ compatible:
+ enum:
+ - fsl,imx6q-pcie
+ - fsl,imx6sx-pcie
+ - fsl,imx6qp-pcie
+ - fsl,imx7d-pcie
+ - fsl,imx8mq-pcie
+
+ reg:
+ items:
+ - description: Data Bus Interface (DBI) registers.
+ - description: PCIe configuration space region.
+
+ reg-names:
+ items:
+ - const: dbi
+ - const: config
+
+ interrupts:
+ items:
+ - description: builtin MSI controller.
+
+ interrupt-names:
+ minItems: 1
+ items:
+ - const: msi
+
+ clocks:
+ minItems: 3
+ items:
+ - description: PCIe bridge clock.
+ - description: PCIe bus clock.
+ - description: PCIe PHY clock.
+ - description: Additional required clock entry for imx6sx-pcie,
+ imx8mq-pcie.
+
+ clock-names:
+ minItems: 3
+ items:
+ - const: pcie
+ - const: pcie_bus
+ - const: pcie_phy
+ - const: pcie_inbound_axi for imx6sx-pcie, pcie_aux for imx8mq-pcie
+
+ num-lanes:
+ const: 1
+
+ fsl,imx7d-pcie-phy:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: A phandle to an fsl,imx7d-pcie-phy node. Additional
+ required properties for imx7d-pcie and imx8mq-pcie.
+
+ power-domains:
+ items:
+ - description: The phandle pointing to the DISPLAY domain for
+ imx6sx-pcie, to PCIE_PHY power domain for imx7d-pcie and
+ imx8mq-pcie.
+ - description: The phandle pointing to the PCIE_PHY power domains
+ for imx6sx-pcie.
+
+ power-domain-names:
+ items:
+ - const: pcie
+ - const: pcie_phy
+
+ resets:
+ maxItems: 3
+ description: Phandles to PCIe-related reset lines exposed by SRC
+ IP block. Additional required by imx7d-pcie and imx8mq-pcie.
+
+ reset-names:
+ items:
+ - const: pciephy
+ - const: apps
+ - const: turnoff
+
+ fsl,tx-deemph-gen1:
+ description: Gen1 De-emphasis value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+
+ fsl,tx-deemph-gen2-3p5db:
+ description: Gen2 (3.5db) De-emphasis value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+
+ fsl,tx-deemph-gen2-6db:
+ description: Gen2 (6db) De-emphasis value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 20
+
+ fsl,tx-swing-full:
+ description: Gen2 TX SWING FULL value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 127
+
+ fsl,tx-swing-low:
+ description: TX launch amplitude swing_low value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 127
+
+ fsl,max-link-speed:
+ description: Specify PCI Gen for link capability (optional required).
+ Note that the IMX6 LVDS clock outputs do not meet gen2 jitter
+ requirements and thus for gen2 capability a gen2 compliant clock
+ generator should be used and configured.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [1, 2, 3, 4]
+ default: 1
+
+ reset-gpio:
+ description: Should specify the GPIO for controlling the PCI bus device
+ reset signal. It's not polarity aware and defaults to active-low reset
+ sequence (L=reset state, H=operation state) (optional required).
+
+ reset-gpio-active-high:
+ description: If present then the reset sequence using the GPIO
+ specified in the "reset-gpio" property is reversed (H=reset state,
+ L=operation state) (optional required).
+
+ vpcie-supply:
+ description: Should specify the regulator in charge of PCIe port power.
+ The regulator will be enabled when initializing the PCIe host and
+ disabled either as part of the init process or when shutting down
+ the host (optional required).
+
+ vph-supply:
+ description: Should specify the regulator in charge of VPH one of
+ the three PCIe PHY powers. This regulator can be supplied by both
+ 1.8v and 3.3v voltage supplies (optional required).
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - "#address-cells"
+ - "#size-cells"
+ - device_type
+ - bus-range
+ - ranges
+ - num-lanes
+ - interrupts
+ - interrupt-names
+ - "#interrupt-cells"
+ - interrupt-map-mask
+ - interrupt-map
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx6qdl-clock.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pcie: pcie@1ffc000 {
+ compatible = "fsl,imx6q-pcie";
+ reg = <0x01ffc000 0x04000>,
+ <0x01f00000 0x80000>;
+ reg-names = "dbi", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ bus-range = <0x00 0xff>;
+ ranges = <0x81000000 0 0 0x01f80000 0 0x00010000>,
+ <0x82000000 0 0x01000000 0x01000000 0 0x00f00000>;
+ num-lanes = <1>;
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &gpc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gpc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gpc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gpc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_PCIE_AXI>,
+ <&clks IMX6QDL_CLK_LVDS1_GATE>,
+ <&clks IMX6QDL_CLK_PCIE_REF_125M>;
+ clock-names = "pcie", "pcie_bus", "pcie_phy";
+ };
+...
diff --git a/Documentation/devicetree/bindings/pci/hisilicon,kirin-pcie.yaml b/Documentation/devicetree/bindings/pci/hisilicon,kirin-pcie.yaml
new file mode 100644
index 000000000000..cbee87802559
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/hisilicon,kirin-pcie.yaml
@@ -0,0 +1,167 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/hisilicon,kirin-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: HiSilicon Kirin SoCs PCIe host DT description
+
+maintainers:
+ - Xiaowei Song <songxiaowei@hisilicon.com>
+ - Binghui Wang <wangbinghui@hisilicon.com>
+
+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/snps,dw-pcie.yaml.
+
+allOf:
+ - $ref: /schemas/pci/snps,dw-pcie.yaml#
+
+properties:
+ compatible:
+ contains:
+ enum:
+ - hisilicon,kirin960-pcie
+ - hisilicon,kirin970-pcie
+
+ reg:
+ description: |
+ Should contain dbi, apb, config registers location and length.
+ For hisilicon,kirin960-pcie, it should also contain phy.
+ minItems: 3
+ maxItems: 4
+
+ reg-names:
+ minItems: 3
+ maxItems: 4
+
+ hisilicon,clken-gpios:
+ description: |
+ Clock input enablement GPIOs from PCI devices like Ethernet, M.2 and
+ mini-PCIe slots.
+
+required:
+ - compatible
+ - reg
+ - reg-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/hi3660-clock.h>
+ #include <dt-bindings/clock/hi3670-clock.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pcie@f4000000 {
+ compatible = "hisilicon,kirin960-pcie";
+ reg = <0x0 0xf4000000 0x0 0x1000>,
+ <0x0 0xff3fe000 0x0 0x1000>,
+ <0x0 0xf3f20000 0x0 0x40000>,
+ <0x0 0xf5000000 0x0 0x2000>;
+ reg-names = "dbi", "apb", "phy", "config";
+ bus-range = <0x0 0xff>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x02000000 0x0 0x00000000
+ 0x0 0xf6000000
+ 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>,
+ <0x0 0 0 2 &gic GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>,
+ <0x0 0 0 3 &gic GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>,
+ <0x0 0 0 4 &gic GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg_ctrl HI3660_PCIEPHY_REF>,
+ <&crg_ctrl HI3660_CLK_GATE_PCIEAUX>,
+ <&crg_ctrl HI3660_PCLK_GATE_PCIE_PHY>,
+ <&crg_ctrl HI3660_PCLK_GATE_PCIE_SYS>,
+ <&crg_ctrl HI3660_ACLK_GATE_PCIE>;
+ clock-names = "pcie_phy_ref", "pcie_aux", "pcie_apb_phy",
+ "pcie_apb_sys", "pcie_aclk";
+ };
+
+ pcie@f5000000 {
+ compatible = "hisilicon,kirin970-pcie";
+ reg = <0x0 0xf4000000 0x0 0x1000000>,
+ <0x0 0xfc180000 0x0 0x1000>,
+ <0x0 0xf5000000 0x0 0x2000>;
+ reg-names = "dbi", "apb", "config";
+ bus-range = <0x0 0xff>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ phys = <&pcie_phy>;
+ ranges = <0x02000000 0x0 0x00000000
+ 0x0 0xf6000000
+ 0x0 0x02000000>;
+ num-lanes = <1>;
+ #interrupt-cells = <1>;
+ interrupts = <GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0x0 0 0 1 &gic GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+ <0x0 0 0 2 &gic GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>,
+ <0x0 0 0 3 &gic GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>,
+ <0x0 0 0 4 &gic GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>;
+ reset-gpios = <&gpio7 0 0>;
+ hisilicon,clken-gpios = <&gpio27 3 0>, <&gpio17 0 0>, <&gpio20 6 0>;
+ pcie@0,0 { // Lane 0: PCIe switch: Bus 1, Device 0
+ reg = <0 0 0 0 0>;
+ compatible = "pciclass,0604";
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ pcie@0,0 { // Lane 0: upstream
+ reg = <0 0 0 0 0>;
+ compatible = "pciclass,0604";
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ pcie@1,0 { // Lane 4: M.2
+ reg = <0x0800 0 0 0 0>;
+ compatible = "pciclass,0604";
+ device_type = "pci";
+ reset-gpios = <&gpio3 1 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ };
+
+ pcie@5,0 { // Lane 5: Mini PCIe
+ reg = <0x2800 0 0 0 0>;
+ compatible = "pciclass,0604";
+ device_type = "pci";
+ reset-gpios = <&gpio27 4 0 >;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ };
+
+ pcie@7,0 { // Lane 6: Ethernet
+ reg = <0x03800 0 0 0 0>;
+ compatible = "pciclass,0604";
+ device_type = "pci";
+ reset-gpios = <&gpio25 2 0 >;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
index 760b4d740616..5f0cf6c2fef3 100644
--- a/Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
@@ -3,7 +3,7 @@ HiSilicon STB PCIe host bridge DT description
The HiSilicon STB PCIe host controller is based on the DesignWare PCIe core.
It shares common functions with the DesignWare PCIe core driver and inherits
common properties defined in
-Documentation/devicetree/bindings/pci/designware-pcie.txt.
+Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml.
Additional properties are described here:
diff --git a/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml b/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
index a1e2be737eec..54e2890ae631 100644
--- a/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: PCIe RC controller on Intel Gateway SoCs
maintainers:
- - Dilip Kota <eswara.kota@linux.intel.com>
+ - Rahul Tanwar <rtanwar@maxlinear.com>
select:
properties:
@@ -17,21 +17,15 @@ select:
required:
- compatible
+allOf:
+ - $ref: /schemas/pci/snps,dw-pcie.yaml#
+
properties:
compatible:
items:
- const: intel,lgm-pcie
- const: snps,dw-pcie
- device_type:
- const: pci
-
- "#address-cells":
- const: 3
-
- "#size-cells":
- const: 2
-
reg:
items:
- description: Controller control and status registers.
@@ -62,30 +56,13 @@ properties:
reset-gpios:
maxItems: 1
- linux,pci-domain: true
-
num-lanes:
maximum: 2
- description: Number of lanes to use for this port.
-
- '#interrupt-cells':
- const: 1
-
- interrupt-map-mask:
- description: Standard PCI IRQ mapping properties.
-
- interrupt-map:
- description: Standard PCI IRQ mapping properties.
max-link-speed:
- description: Specify PCI Gen for link capability.
- $ref: /schemas/types.yaml#/definitions/uint32
enum: [1, 2, 3, 4]
default: 1
- bus-range:
- description: Range of bus numbers associated with this controller.
-
reset-assert-ms:
description: |
Delay after asserting reset to the PCIe device.
@@ -94,9 +71,6 @@ properties:
required:
- compatible
- - device_type
- - "#address-cells"
- - "#size-cells"
- reg
- reg-names
- ranges
@@ -109,7 +83,7 @@ required:
- interrupt-map
- interrupt-map-mask
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/pci/kirin-pcie.txt b/Documentation/devicetree/bindings/pci/kirin-pcie.txt
deleted file mode 100644
index 6bbe43818ad5..000000000000
--- a/Documentation/devicetree/bindings/pci/kirin-pcie.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-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-pcie.txt.
-
-Additional properties are described here:
-
-Required properties
-- compatible:
- "hisilicon,kirin960-pcie" for PCIe of Kirin960 SoC
-- reg: Should contain rc_dbi, apb, phy, config registers location and length.
-- reg-names: Must include the following entries:
- "dbi": controller configuration registers;
- "apb": apb Ctrl register defined by Kirin;
- "phy": apb PHY register defined by Kirin;
- "config": PCIe configuration space registers.
-- reset-gpios: The GPIO to generate PCIe PERST# assert and deassert signal.
-
-Optional properties:
-
-Example based on kirin960:
-
- pcie@f4000000 {
- compatible = "hisilicon,kirin-pcie";
- reg = <0x0 0xf4000000 0x0 0x1000>, <0x0 0xff3fe000 0x0 0x1000>,
- <0x0 0xf3f20000 0x0 0x40000>, <0x0 0xF4000000 0 0x2000>;
- reg-names = "dbi","apb","phy", "config";
- bus-range = <0x0 0x1>;
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- ranges = <0x02000000 0x0 0x00000000 0x0 0xf5000000 0x0 0x2000000>;
- num-lanes = <1>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map = <0x0 0 0 1 &gic 0 0 0 282 4>,
- <0x0 0 0 2 &gic 0 0 0 283 4>,
- <0x0 0 0 3 &gic 0 0 0 284 4>,
- <0x0 0 0 4 &gic 0 0 0 285 4>;
- clocks = <&crg_ctrl HI3660_PCIEPHY_REF>,
- <&crg_ctrl HI3660_CLK_GATE_PCIEAUX>,
- <&crg_ctrl HI3660_PCLK_GATE_PCIE_PHY>,
- <&crg_ctrl HI3660_PCLK_GATE_PCIE_SYS>,
- <&crg_ctrl HI3660_ACLK_GATE_PCIE>;
- clock-names = "pcie_phy_ref", "pcie_aux",
- "pcie_apb_phy", "pcie_apb_sys", "pcie_aclk";
- reset-gpios = <&gpio11 1 0 >;
- };
diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 6d898dd4a8e2..f36efa73a470 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -1,7 +1,7 @@
Freescale Layerscape PCIe controller
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
-and thus inherits all the common properties defined in designware-pcie.txt.
+and thus inherits all the common properties defined in snps,dw-pcie.yaml.
This controller derives its clocks from the Reset Configuration Word (RCW)
which is used to describe the PLL settings at the time of chip-reset.
diff --git a/Documentation/devicetree/bindings/pci/loongson.yaml b/Documentation/devicetree/bindings/pci/loongson.yaml
index 82bc6c486ca3..a8324a9bd002 100644
--- a/Documentation/devicetree/bindings/pci/loongson.yaml
+++ b/Documentation/devicetree/bindings/pci/loongson.yaml
@@ -17,10 +17,10 @@ allOf:
properties:
compatible:
- oneOf:
- - const: loongson,ls2k-pci
- - const: loongson,ls7a-pci
- - const: loongson,rs780e-pci
+ enum:
+ - loongson,ls2k-pci
+ - loongson,ls7a-pci
+ - loongson,rs780e-pci
reg:
minItems: 1
diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt
index bd43f3c3ece4..6a99d2aa8075 100644
--- a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt
@@ -1,7 +1,8 @@
NVIDIA Tegra PCIe controller (Synopsys DesignWare Core based)
This PCIe controller is based on the Synopsis Designware PCIe IP
-and thus inherits all the common properties defined in designware-pcie.txt.
+and thus inherits all the common properties defined in snps,dw-pcie.yaml and
+snps,dw-pcie-ep.yaml.
Some of the controller instances are dual mode where in they can work either
in root port mode or endpoint mode but one at a time.
@@ -22,7 +23,7 @@ Required properties:
property.
- reg-names: Must include the following entries:
"appl": Controller's application logic registers
- "config": As per the definition in designware-pcie.txt
+ "config": As per the definition in snps,dw-pcie.yaml
"atu_dma": iATU and DMA registers. This is where the iATU (internal Address
Translation Unit) registers of the PCIe core are made available
for SW access.
diff --git a/Documentation/devicetree/bindings/pci/pci-armada8k.txt b/Documentation/devicetree/bindings/pci/pci-armada8k.txt
index 7a813d0e6d63..ff25a134befa 100644
--- a/Documentation/devicetree/bindings/pci/pci-armada8k.txt
+++ b/Documentation/devicetree/bindings/pci/pci-armada8k.txt
@@ -1,7 +1,7 @@
* Marvell Armada 7K/8K PCIe interface
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
-and thus inherits all the common properties defined in designware-pcie.txt.
+and thus inherits all the common properties defined in snps,dw-pcie.yaml.
Required properties:
- compatible: "marvell,armada8k-pcie"
diff --git a/Documentation/devicetree/bindings/pci/pcie-al.txt b/Documentation/devicetree/bindings/pci/pcie-al.txt
index 557a5089229d..2ad1fe466eab 100644
--- a/Documentation/devicetree/bindings/pci/pcie-al.txt
+++ b/Documentation/devicetree/bindings/pci/pcie-al.txt
@@ -2,7 +2,7 @@
Amazon's Annapurna Labs PCIe Host Controller is based on the Synopsys DesignWare
PCI core. It inherits common properties defined in
-Documentation/devicetree/bindings/pci/designware-pcie.txt.
+Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml.
Properties of the host controller node that differ from it are:
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
index 25f4def468bf..3f646875f8c2 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
@@ -34,22 +34,22 @@
- device_type:
Usage: required
Value type: <string>
- Definition: Should be "pci". As specified in designware-pcie.txt
+ Definition: Should be "pci". As specified in snps,dw-pcie.yaml
- #address-cells:
Usage: required
Value type: <u32>
- Definition: Should be 3. As specified in designware-pcie.txt
+ Definition: Should be 3. As specified in snps,dw-pcie.yaml
- #size-cells:
Usage: required
Value type: <u32>
- Definition: Should be 2. As specified in designware-pcie.txt
+ Definition: Should be 2. As specified in snps,dw-pcie.yaml
- ranges:
Usage: required
Value type: <prop-encoded-array>
- Definition: As specified in designware-pcie.txt
+ Definition: As specified in snps,dw-pcie.yaml
- interrupts:
Usage: required
@@ -64,17 +64,17 @@
- #interrupt-cells:
Usage: required
Value type: <u32>
- Definition: Should be 1. As specified in designware-pcie.txt
+ Definition: Should be 1. As specified in snps,dw-pcie.yaml
- interrupt-map-mask:
Usage: required
Value type: <prop-encoded-array>
- Definition: As specified in designware-pcie.txt
+ Definition: As specified in snps,dw-pcie.yaml
- interrupt-map:
Usage: required
Value type: <prop-encoded-array>
- Definition: As specified in designware-pcie.txt
+ Definition: As specified in snps,dw-pcie.yaml
- clocks:
Usage: required
diff --git a/Documentation/devicetree/bindings/pci/samsung,exynos-pcie.yaml b/Documentation/devicetree/bindings/pci/samsung,exynos-pcie.yaml
index 1810bf722350..445eed94b53f 100644
--- a/Documentation/devicetree/bindings/pci/samsung,exynos-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/samsung,exynos-pcie.yaml
@@ -13,10 +13,10 @@ maintainers:
description: |+
Exynos5433 SoC PCIe host controller is based on the Synopsys DesignWare
PCIe IP and thus inherits all the common properties defined in
- designware-pcie.txt.
+ snps,dw-pcie.yaml.
allOf:
- - $ref: /schemas/pci/pci-bus.yaml#
+ - $ref: /schemas/pci/snps,dw-pcie.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml b/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
index b03cbb9b6602..2b9d1d6fc661 100644
--- a/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
@@ -10,14 +10,14 @@ description: |+
SiFive FU740 PCIe host controller is based on the Synopsys DesignWare
PCI core. It shares common features with the PCIe DesignWare core and
inherits common properties defined in
- Documentation/devicetree/bindings/pci/designware-pcie.txt.
+ Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml.
maintainers:
- Paul Walmsley <paul.walmsley@sifive.com>
- Greentime Hu <greentime.hu@sifive.com>
allOf:
- - $ref: /schemas/pci/pci-bus.yaml#
+ - $ref: /schemas/pci/snps,dw-pcie.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
new file mode 100644
index 000000000000..b5935b1b153f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/snps,dw-pcie-ep.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare PCIe endpoint interface
+
+maintainers:
+ - Jingoo Han <jingoohan1@gmail.com>
+ - Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+
+description: |
+ Synopsys DesignWare PCIe host controller endpoint
+
+allOf:
+ - $ref: /schemas/pci/pci-ep.yaml#
+
+properties:
+ compatible:
+ anyOf:
+ - {}
+ - const: snps,dw-pcie-ep
+
+ reg:
+ description: |
+ It should contain Data Bus Interface (dbi) and config registers for all
+ versions.
+ For designware core version >= 4.80, it may contain ATU address space.
+ minItems: 2
+ maxItems: 4
+
+ reg-names:
+ minItems: 2
+ maxItems: 4
+ items:
+ enum: [dbi, dbi2, config, atu, addr_space, link, atu_dma, appl]
+
+ reset-gpio:
+ description: GPIO pin number of PERST# signal
+ maxItems: 1
+ deprecated: true
+
+ reset-gpios:
+ description: GPIO controlled connection to PERST# signal
+ maxItems: 1
+
+ snps,enable-cdm-check:
+ type: boolean
+ description: |
+ This is a boolean property and if present enables
+ automatic checking of CDM (Configuration Dependent Module) registers
+ for data corruption. CDM registers include standard PCIe configuration
+ space registers, Port Logic registers, DMA and iATU (internal Address
+ Translation Unit) registers.
+
+ num-ib-windows:
+ description: number of inbound address translation windows
+ maxItems: 1
+ deprecated: true
+
+ num-ob-windows:
+ description: number of outbound address translation windows
+ maxItems: 1
+ deprecated: true
+
+ max-functions:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: maximum number of functions that can be configured
+
+required:
+ - reg
+ - reg-names
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ pcie-ep@dfd00000 {
+ compatible = "snps,dw-pcie-ep";
+ reg = <0xdfc00000 0x0001000>, /* IP registers 1 */
+ <0xdfc01000 0x0001000>, /* IP registers 2 */
+ <0xd0000000 0x2000000>; /* Configuration space */
+ reg-names = "dbi", "dbi2", "addr_space";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
new file mode 100644
index 000000000000..9ed0dfba7f89
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
@@ -0,0 +1,102 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/snps,dw-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare PCIe interface
+
+maintainers:
+ - Jingoo Han <jingoohan1@gmail.com>
+ - Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+
+description: |
+ Synopsys DesignWare PCIe host controller
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+ compatible:
+ anyOf:
+ - {}
+ - const: snps,dw-pcie
+
+ reg:
+ description: |
+ It should contain Data Bus Interface (dbi) and config registers for all
+ versions.
+ For designware core version >= 4.80, it may contain ATU address space.
+ minItems: 2
+ maxItems: 5
+
+ reg-names:
+ minItems: 2
+ maxItems: 5
+ items:
+ enum: [ dbi, dbi2, config, atu, app, elbi, mgmt, ctrl, parf, cfg, link,
+ ulreg, smu, mpu, apb, phy ]
+
+ num-lanes:
+ description: |
+ number of lanes to use (this property should be specified unless
+ the link is brought already up in firmware)
+ maximum: 16
+
+ reset-gpio:
+ description: GPIO pin number of PERST# signal
+ maxItems: 1
+ deprecated: true
+
+ reset-gpios:
+ description: GPIO controlled connection to PERST# signal
+ maxItems: 1
+
+ interrupts: true
+
+ interrupt-names: true
+
+ clocks: true
+
+ snps,enable-cdm-check:
+ type: boolean
+ description: |
+ This is a boolean property and if present enables
+ automatic checking of CDM (Configuration Dependent Module) registers
+ for data corruption. CDM registers include standard PCIe configuration
+ space registers, Port Logic registers, DMA and iATU (internal Address
+ Translation Unit) registers.
+
+ num-viewport:
+ description: |
+ number of view ports configured in hardware. If a platform
+ does not specify it, the driver autodetects it.
+ deprecated: true
+
+unevaluatedProperties: false
+
+required:
+ - reg
+ - reg-names
+ - compatible
+
+examples:
+ - |
+ bus {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ pcie@dfc00000 {
+ device_type = "pci";
+ compatible = "snps,dw-pcie";
+ reg = <0xdfc00000 0x0001000>, /* IP registers */
+ <0xd0000000 0x0002000>; /* Configuration space */
+ reg-names = "dbi", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x81000000 0 0x00000000 0xde000000 0 0x00010000>,
+ <0x82000000 0 0xd0400000 0xd0400000 0 0x0d000000>;
+ interrupts = <25>, <24>;
+ #interrupt-cells = <1>;
+ num-lanes = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/socionext,uniphier-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/socionext,uniphier-pcie-ep.yaml
index d6cf8a560ef0..144cbcd60a1c 100644
--- a/Documentation/devicetree/bindings/pci/socionext,uniphier-pcie-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/socionext,uniphier-pcie-ep.yaml
@@ -10,13 +10,13 @@ description: |
UniPhier PCIe endpoint controller is based on the Synopsys DesignWare
PCI core. It shares common features with the PCIe DesignWare core and
inherits common properties defined in
- Documentation/devicetree/bindings/pci/designware-pcie.txt.
+ Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml.
maintainers:
- Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
allOf:
- - $ref: "pci-ep.yaml#"
+ - $ref: /schemas/pci/snps,dw-pcie-ep.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/pci/ti-pci.txt b/Documentation/devicetree/bindings/pci/ti-pci.txt
index d5cbfe6b0d89..8147e3e3e29b 100644
--- a/Documentation/devicetree/bindings/pci/ti-pci.txt
+++ b/Documentation/devicetree/bindings/pci/ti-pci.txt
@@ -12,7 +12,7 @@ PCIe DesignWare Controller
number of PHYs as specified in *phys* property.
- ti,hwmods : Name of the hwmod associated to the pcie, "pcie<X>",
where <X> is the instance number of the pcie from the HW spec.
- - num-lanes as specified in ../designware-pcie.txt
+ - num-lanes as specified in ../snps,dw-pcie.yaml
- ti,syscon-lane-sel : phandle/offset pair. Phandle to the system control
module and the register offset to specify lane
selection.
@@ -32,7 +32,7 @@ HOST MODE
device_type,
ranges,
interrupt-map-mask,
- interrupt-map : as specified in ../designware-pcie.txt
+ interrupt-map : as specified in ../snps,dw-pcie.yaml
- ti,syscon-unaligned-access: phandle to the syscon DT node. The 1st argument
should contain the register offset within syscon
and the 2nd argument should contain the bit field
diff --git a/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml b/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml
new file mode 100644
index 000000000000..30b6396d83c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml
@@ -0,0 +1,110 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/toshiba,visconti-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Toshiba Visconti5 SoC PCIe Host Controller Device Tree Bindings
+
+maintainers:
+ - Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
+
+description:
+ Toshiba Visconti5 SoC PCIe host controller is based on the Synopsys DesignWare PCIe IP.
+
+allOf:
+ - $ref: /schemas/pci/snps,dw-pcie.yaml#
+
+properties:
+ compatible:
+ const: toshiba,visconti-pcie
+
+ reg:
+ items:
+ - description: Data Bus Interface (DBI) registers.
+ - description: PCIe configuration space region.
+ - description: Visconti specific additional registers.
+ - description: Visconti specific SMU registers
+ - description: Visconti specific memory protection unit registers (MPU)
+
+ reg-names:
+ items:
+ - const: dbi
+ - const: config
+ - const: ulreg
+ - const: smu
+ - const: mpu
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: PCIe reference clock
+ - description: PCIe system clock
+ - description: Auxiliary clock
+
+ clock-names:
+ items:
+ - const: ref
+ - const: core
+ - const: aux
+
+ num-lanes:
+ const: 2
+
+required:
+ - reg
+ - reg-names
+ - interrupts
+ - "#interrupt-cells"
+ - interrupt-map
+ - interrupt-map-mask
+ - num-lanes
+ - clocks
+ - clock-names
+ - max-link-speed
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pcie: pcie@28400000 {
+ compatible = "toshiba,visconti-pcie";
+ reg = <0x0 0x28400000 0x0 0x00400000>,
+ <0x0 0x70000000 0x0 0x10000000>,
+ <0x0 0x28050000 0x0 0x00010000>,
+ <0x0 0x24200000 0x0 0x00002000>,
+ <0x0 0x24162000 0x0 0x00001000>;
+ reg-names = "dbi", "config", "ulreg", "smu", "mpu";
+ device_type = "pci";
+ bus-range = <0x00 0xff>;
+ num-lanes = <2>;
+ num-viewport = <8>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x81000000 0 0x40000000 0 0x40000000 0 0x00010000>,
+ <0x82000000 0 0x50000000 0 0x50000000 0 0x20000000>;
+ interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map =
+ <0 0 0 1 &gic GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH
+ 0 0 0 2 &gic GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH
+ 0 0 0 3 &gic GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH
+ 0 0 0 4 &gic GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&extclk100mhz>, <&clk600mhz>, <&clk25mhz>;
+ clock-names = "ref", "core", "aux";
+ max-link-speed = <2>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pci/uniphier-pcie.txt b/Documentation/devicetree/bindings/pci/uniphier-pcie.txt
index c4b7381733a0..359585db049f 100644
--- a/Documentation/devicetree/bindings/pci/uniphier-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/uniphier-pcie.txt
@@ -6,7 +6,7 @@ on Socionext UniPhier SoCs.
UniPhier 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-pcie.txt.
+Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml.
Required properties:
- compatible: Should be "socionext,uniphier-pcie".
diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.txt b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.txt
deleted file mode 100644
index 7c70f2ad9942..000000000000
--- a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-* Freescale i.MX8MQ USB3 PHY binding
-
-Required properties:
-- compatible: Should be "fsl,imx8mq-usb-phy" or "fsl,imx8mp-usb-phy"
-- #phys-cells: must be 0 (see phy-bindings.txt in this directory)
-- reg: The base address and length of the registers
-- clocks: phandles to the clocks for each clock listed in clock-names
-- clock-names: must contain "phy"
-
-Optional properties:
-- vbus-supply: A phandle to the regulator for USB VBUS.
-
-Example:
- usb3_phy0: phy@381f0040 {
- compatible = "fsl,imx8mq-usb-phy";
- reg = <0x381f0040 0x40>;
- clocks = <&clk IMX8MQ_CLK_USB1_PHY_ROOT>;
- clock-names = "phy";
- #phy-cells = <0>;
- };
diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
new file mode 100644
index 000000000000..2936f3510a6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/fsl,imx8mq-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX8MQ USB3 PHY binding
+
+maintainers:
+ - Li Jun <jun.li@nxp.com>
+
+properties:
+ compatible:
+ enum:
+ - fsl,imx8mq-usb-phy
+ - fsl,imx8mp-usb-phy
+
+ reg:
+ maxItems: 1
+
+ "#phy-cells":
+ const: 0
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: phy
+
+ vbus-supply:
+ description:
+ A phandle to the regulator for USB VBUS.
+
+required:
+ - compatible
+ - reg
+ - "#phy-cells"
+ - clocks
+ - clock-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx8mq-clock.h>
+ usb3_phy0: phy@381f0040 {
+ compatible = "fsl,imx8mq-usb-phy";
+ reg = <0x381f0040 0x40>;
+ clocks = <&clk IMX8MQ_CLK_USB1_PHY_ROOT>;
+ clock-names = "phy";
+ #phy-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/phy/hisilicon,phy-hi3670-pcie.yaml b/Documentation/devicetree/bindings/phy/hisilicon,phy-hi3670-pcie.yaml
new file mode 100644
index 000000000000..17367a0275fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/hisilicon,phy-hi3670-pcie.yaml
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/hisilicon,phy-hi3670-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: HiSilicon Kirin970 PCIe PHY
+
+maintainers:
+ - Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+description: |+
+ Bindings for PCIe PHY on HiSilicon Kirin 970.
+
+properties:
+ compatible:
+ const: hisilicon,hi970-pcie-phy
+
+ "#phy-cells":
+ const: 0
+
+ reg:
+ maxItems: 1
+ description: PHY Control registers
+
+ phy-supply:
+ description: The PCIe PHY power supply
+
+ clocks:
+ items:
+ - description: PCIe PHY clock
+ - description: PCIe AUX clock
+ - description: PCIe APB PHY clock
+ - description: PCIe APB SYS clock
+ - description: PCIe ACLK clock
+
+ clock-names:
+ items:
+ - const: phy_ref
+ - const: aux
+ - const: apb_phy
+ - const: apb_sys
+ - const: aclk
+
+ hisilicon,eye-diagram-param:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: Eye diagram for phy.
+
+required:
+ - "#phy-cells"
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - hisilicon,eye-diagram-param
+ - phy-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/hi3670-clock.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ pcie_phy: pcie-phy@fc000000 {
+ compatible = "hisilicon,hi970-pcie-phy";
+ reg = <0x0 0xfc000000 0x0 0x80000>;
+ #phy-cells = <0>;
+ phy-supply = <&ldo33>;
+ clocks = <&crg_ctrl HI3670_CLK_GATE_PCIEPHY_REF>,
+ <&crg_ctrl HI3670_CLK_GATE_PCIEAUX>,
+ <&crg_ctrl HI3670_PCLK_GATE_PCIE_PHY>,
+ <&crg_ctrl HI3670_PCLK_GATE_PCIE_SYS>,
+ <&crg_ctrl HI3670_ACLK_GATE_PCIE>;
+ clock-names = "phy_ref", "aux",
+ "apb_phy", "apb_sys", "aclk";
+ hisilicon,eye-diagram-param = <0xffffffff 0xffffffff
+ 0xffffffff 0xffffffff 0xffffffff>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/phy/intel,phy-keembay-usb.yaml b/Documentation/devicetree/bindings/phy/intel,keembay-phy-usb.yaml
index a217bb8ac5bc..52815b6c2b88 100644
--- a/Documentation/devicetree/bindings/phy/intel,phy-keembay-usb.yaml
+++ b/Documentation/devicetree/bindings/phy/intel,keembay-phy-usb.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/phy/intel,phy-keembay-usb.yaml#
+$id: http://devicetree.org/schemas/phy/intel,keembay-phy-usb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel Keem Bay USB PHY bindings
diff --git a/Documentation/devicetree/bindings/phy/intel,lgm-emmc-phy.yaml b/Documentation/devicetree/bindings/phy/intel,lgm-emmc-phy.yaml
index edd9d70a672a..954e67571dfd 100644
--- a/Documentation/devicetree/bindings/phy/intel,lgm-emmc-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/intel,lgm-emmc-phy.yaml
@@ -23,9 +23,9 @@ description: |+
properties:
compatible:
- oneOf:
- - const: intel,lgm-emmc-phy
- - const: intel,keembay-emmc-phy
+ enum:
+ - intel,lgm-emmc-phy
+ - intel,keembay-emmc-phy
"#phy-cells":
const: 0
diff --git a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
index ef9d9d4e6875..9e6c0f43f1c6 100644
--- a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
+++ b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
@@ -15,7 +15,7 @@ description: |
controllers on MediaTek SoCs, includes USB2.0, USB3.0, PCIe and SATA.
Layout differences of banks between T-PHY V1 (mt8173/mt2701) and
- T-PHY V2 (mt2712) when works on USB mode:
+ T-PHY V2 (mt2712) / V3 (mt8195) when works on USB mode:
-----------------------------------
Version 1:
port offset bank
@@ -34,7 +34,7 @@ description: |
u2 port2 0x1800 U2PHY_COM
...
- Version 2:
+ Version 2/3:
port offset bank
u2 port0 0x0000 MISC
0x0100 FMREG
@@ -59,7 +59,8 @@ description: |
SPLLC shared by u3 ports and FMREG shared by u2 ports on V1 are put back
into each port; a new bank MISC for u2 ports and CHIP for u3 ports are
- added on V2.
+ added on V2; the FMREG bank for slew rate calibration is not used anymore
+ and reserved on V3;
properties:
$nodename:
@@ -79,8 +80,11 @@ properties:
- mediatek,mt2712-tphy
- mediatek,mt7629-tphy
- mediatek,mt8183-tphy
- - mediatek,mt8195-tphy
- const: mediatek,generic-tphy-v2
+ - items:
+ - enum:
+ - mediatek,mt8195-tphy
+ - const: mediatek,generic-tphy-v3
- const: mediatek,mt2701-u3phy
deprecated: true
- const: mediatek,mt2712-u3phy
@@ -91,7 +95,7 @@ properties:
description:
Register shared by multiple ports, exclude port's private register.
It is needed for T-PHY V1, such as mt2701 and mt8173, but not for
- T-PHY V2, such as mt2712.
+ T-PHY V2/V3, such as mt2712.
maxItems: 1
"#address-cells":
@@ -197,6 +201,22 @@ patternProperties:
Specify the flag to enable BC1.2 if support it
type: boolean
+ mediatek,syscon-type:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ maxItems: 1
+ description:
+ A phandle to syscon used to access the register of type switch,
+ the field should always be 3 cells long.
+ items:
+ items:
+ - description:
+ The first cell represents a phandle to syscon
+ - description:
+ The second cell represents the register offset
+ - description:
+ The third cell represents the index of config segment
+ enum: [0, 1, 2, 3]
+
required:
- reg
- "#phy-cells"
diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
index f0497b8623ad..75be5650a198 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
@@ -18,6 +18,7 @@ properties:
compatible:
enum:
- qcom,ipq6018-qmp-pcie-phy
+ - qcom,ipq6018-qmp-usb3-phy
- qcom,ipq8074-qmp-pcie-phy
- qcom,ipq8074-qmp-usb3-phy
- qcom,msm8996-qmp-pcie-phy
@@ -27,6 +28,7 @@ properties:
- qcom,msm8998-qmp-ufs-phy
- qcom,msm8998-qmp-usb3-phy
- qcom,sc7180-qmp-usb3-phy
+ - qcom,sc8180x-qmp-pcie-phy
- qcom,sc8180x-qmp-ufs-phy
- qcom,sc8180x-qmp-usb3-phy
- qcom,sdm845-qhp-pcie-phy
@@ -34,6 +36,7 @@ properties:
- qcom,sdm845-qmp-ufs-phy
- qcom,sdm845-qmp-usb3-phy
- qcom,sdm845-qmp-usb3-uni-phy
+ - qcom,sm6115-qmp-ufs-phy
- qcom,sm8150-qmp-ufs-phy
- qcom,sm8150-qmp-usb3-phy
- qcom,sm8150-qmp-usb3-uni-phy
@@ -326,6 +329,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,sc8180x-qmp-pcie-phy
- qcom,sdm845-qhp-pcie-phy
- qcom,sdm845-qmp-pcie-phy
- qcom,sdx55-qmp-pcie-phy
diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
index 217aa6c91893..60dc27834e1d 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
@@ -14,6 +14,8 @@ properties:
compatible:
enum:
- qcom,sc7180-qmp-usb3-dp-phy
+ - qcom,sc7280-qmp-usb3-dp-phy
+ - qcom,sc8180x-qmp-usb3-dp-phy
- qcom,sdm845-qmp-usb3-dp-phy
- qcom,sm8250-qmp-usb3-dp-phy
reg:
diff --git a/Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml b/Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml
index d5dc5a3cdceb..3a6e1165419c 100644
--- a/Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml
@@ -30,6 +30,11 @@ properties:
- renesas,usb2-phy-r8a77995 # R-Car D3
- const: renesas,rcar-gen3-usb2-phy
+ - items:
+ - enum:
+ - renesas,usb2-phy-r9a07g044 # RZ/G2{L,LC}
+ - const: renesas,rzg2l-usb2-phy # RZ/G2L family
+
reg:
maxItems: 1
@@ -91,6 +96,16 @@ required:
- clocks
- '#phy-cells'
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,rzg2l-usb2-phy
+ then:
+ required:
+ - resets
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/phy/samsung,ufs-phy.yaml b/Documentation/devicetree/bindings/phy/samsung,ufs-phy.yaml
index 636cc501b54f..f6ed1a005e7a 100644
--- a/Documentation/devicetree/bindings/phy/samsung,ufs-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/samsung,ufs-phy.yaml
@@ -16,6 +16,7 @@ properties:
compatible:
enum:
- samsung,exynos7-ufs-phy
+ - samsung,exynosautov9-ufs-phy
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.txt b/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.txt
deleted file mode 100644
index 64b286d2d398..000000000000
--- a/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-TI AM654 SERDES
-
-Required properties:
- - compatible: Should be "ti,phy-am654-serdes"
- - reg : Address and length of the register set for the device.
- - #phy-cells: determine the number of cells that should be given in the
- phandle while referencing this phy. Should be "2". The 1st cell
- corresponds to the phy type (should be one of the types specified in
- include/dt-bindings/phy/phy.h) and the 2nd cell should be the serdes
- lane function.
- If SERDES0 is referenced 2nd cell should be:
- 0 - USB3
- 1 - PCIe0 Lane0
- 2 - ICSS2 SGMII Lane0
- If SERDES1 is referenced 2nd cell should be:
- 0 - PCIe1 Lane0
- 1 - PCIe0 Lane1
- 2 - ICSS2 SGMII Lane1
- - power-domains: As documented by the generic PM domain bindings in
- Documentation/devicetree/bindings/power/power_domain.txt.
- - clocks: List of clock-specifiers representing the input to the SERDES.
- Should have 3 items representing the left input clock, external
- reference clock and right input clock in that order.
- - clock-output-names: List of clock names for each of the clock outputs of
- SERDES. Should have 3 items for CMU reference clock,
- left output clock and right output clock in that order.
- - assigned-clocks: As defined in
- Documentation/devicetree/bindings/clock/clock-bindings.txt
- - assigned-clock-parents: As defined in
- Documentation/devicetree/bindings/clock/clock-bindings.txt
- - #clock-cells: Should be <1> to choose between the 3 output clocks.
- Defined in Documentation/devicetree/bindings/clock/clock-bindings.txt
-
- The following macros are defined in dt-bindings/phy/phy-am654-serdes.h
- for selecting the correct reference clock. This can be used while
- specifying the clocks created by SERDES.
- => AM654_SERDES_CMU_REFCLK
- => AM654_SERDES_LO_REFCLK
- => AM654_SERDES_RO_REFCLK
-
- - mux-controls: Phandle to the multiplexer that is used to select the lane
- function. See #phy-cells above to see the multiplex values.
-
-Example:
-
-Example for SERDES0 is given below. It has 3 clock inputs;
-left input reference clock as indicated by <&k3_clks 153 4>, external
-reference clock as indicated by <&k3_clks 153 1> and right input
-reference clock as indicated by <&serdes1 AM654_SERDES_LO_REFCLK>. (The
-right input of SERDES0 is connected to the left output of SERDES1).
-
-SERDES0 registers 3 clock outputs as indicated in clock-output-names. The
-first refers to the CMU reference clock, second refers to the left output
-reference clock and the third refers to the right output reference clock.
-
-The assigned-clocks and assigned-clock-parents is used here to set the
-parent of left input reference clock to MAINHSDIV_CLKOUT4 and parent of
-CMU reference clock to left input reference clock.
-
-serdes0: serdes@900000 {
- compatible = "ti,phy-am654-serdes";
- reg = <0x0 0x900000 0x0 0x2000>;
- reg-names = "serdes";
- #phy-cells = <2>;
- power-domains = <&k3_pds 153>;
- clocks = <&k3_clks 153 4>, <&k3_clks 153 1>,
- <&serdes1 AM654_SERDES_LO_REFCLK>;
- clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk",
- "serdes0_ro_refclk";
- assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
- assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>;
- ti,serdes-clk = <&serdes0_clk>;
- mux-controls = <&serdes_mux 0>;
- #clock-cells = <1>;
-};
-
-Example for PCIe consumer node using the SERDES PHY specifier is given below.
-&pcie0_rc {
- num-lanes = <2>;
- phys = <&serdes0 PHY_TYPE_PCIE 1>, <&serdes1 PHY_TYPE_PCIE 1>;
- phy-names = "pcie-phy0", "pcie-phy1";
-};
diff --git a/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.yaml b/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.yaml
new file mode 100644
index 000000000000..62dcb84c08aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.yaml
@@ -0,0 +1,103 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/ti,phy-am654-serdes.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI AM654 SERDES binding
+
+description:
+ This binding describes the TI AM654 SERDES. AM654 SERDES can be configured
+ to be used with either PCIe or USB or SGMII.
+
+maintainers:
+ - Kishon Vijay Abraham I <kishon@ti.com>
+
+properties:
+ compatible:
+ enum:
+ - ti,phy-am654-serdes
+
+ reg:
+ maxItems: 1
+
+ reg-names:
+ items:
+ - const: serdes
+
+ power-domains:
+ maxItems: 1
+
+ clocks:
+ maxItems: 3
+ description:
+ Three input clocks referring to left input reference clock, refclk and right input reference
+ clock.
+
+ assigned-clocks:
+ $ref: "/schemas/types.yaml#/definitions/phandle-array"
+ assigned-clock-parents:
+ $ref: "/schemas/types.yaml#/definitions/phandle-array"
+
+ '#phy-cells':
+ const: 2
+ description:
+ The 1st cell corresponds to the phy type (should be one of the types specified in
+ include/dt-bindings/phy/phy.h) and the 2nd cell should be the serdes lane function.
+
+ ti,serdes-clk:
+ description: Phandle to the SYSCON entry required for configuring SERDES clock selection.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ '#clock-cells':
+ const: 1
+
+ mux-controls:
+ maxItems: 1
+ description: Phandle to the SYSCON entry required for configuring SERDES lane function.
+
+ clock-output-names:
+ oneOf:
+ - description: Clock output names for SERDES 0
+ items:
+ - const: serdes0_cmu_refclk
+ - const: serdes0_lo_refclk
+ - const: serdes0_ro_refclk
+ - description: Clock output names for SERDES 1
+ items:
+ - const: serdes1_cmu_refclk
+ - const: serdes1_lo_refclk
+ - const: serdes1_ro_refclk
+
+required:
+ - compatible
+ - reg
+ - power-domains
+ - clocks
+ - assigned-clocks
+ - assigned-clock-parents
+ - ti,serdes-clk
+ - mux-controls
+ - clock-output-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/phy/phy-am654-serdes.h>
+
+ serdes0: serdes@900000 {
+ compatible = "ti,phy-am654-serdes";
+ reg = <0x900000 0x2000>;
+ reg-names = "serdes";
+ #phy-cells = <2>;
+ power-domains = <&k3_pds 153>;
+ clocks = <&k3_clks 153 4>, <&k3_clks 153 1>,
+ <&serdes1 AM654_SERDES_LO_REFCLK>;
+ clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk", "serdes0_ro_refclk";
+ assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
+ assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>;
+ ti,serdes-clk = <&serdes0_clk>;
+ mux-controls = <&serdes_mux 0>;
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8ulp-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8ulp-pinctrl.yaml
new file mode 100644
index 000000000000..86622c4f374b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8ulp-pinctrl.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/fsl,imx8ulp-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale IMX8ULP IOMUX Controller
+
+maintainers:
+ - Jacky Bai <ping.bai@nxp.com>
+
+description:
+ Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory
+ for common binding part and usage.
+
+properties:
+ compatible:
+ const: fsl,imx8ulp-iomuxc1
+
+ reg:
+ maxItems: 1
+
+# Client device subnode's properties
+patternProperties:
+ 'grp$':
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+
+ properties:
+ fsl,pins:
+ description:
+ each entry consists of 5 integers and represents the mux and config
+ setting for one pin. The first 4 integers <mux_config_reg input_reg
+ mux_mode input_val> are specified using a PIN_FUNC_ID macro, which can
+ be found in <arch/arm64/boot/dts/freescale/imx8ulp-pinfunc.h>. The last
+ integer CONFIG is the pad setting value like pull-up on this pin. Please
+ refer to i.MX8ULP Reference Manual for detailed CONFIG settings.
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ items:
+ items:
+ - description: |
+ "mux_config_reg" indicates the offset of mux register.
+ - description: |
+ "input_reg" indicates the offset of select input register.
+ - description: |
+ "mux_mode" indicates the mux value to be applied.
+ - description: |
+ "input_val" indicates the select input value to be applied.
+ - description: |
+ "pad_setting" indicates the pad configuration value to be applied.
+
+ required:
+ - fsl,pins
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ # Pinmux controller node
+ - |
+ iomuxc: pinctrl@298c0000 {
+ compatible = "fsl,imx8ulp-iomuxc1";
+ reg = <0x298c0000 0x10000>;
+
+ pinctrl_lpuart5: lpuart5grp {
+ fsl,pins =
+ <0x0138 0x08F0 0x4 0x3 0x3>,
+ <0x013C 0x08EC 0x4 0x3 0x3>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml
index a4846d78111c..a12d0ceb7637 100644
--- a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml
@@ -19,10 +19,10 @@ description: >
pin within that GPIO port. For example PA0 is the first pin in GPIO port A,
and PB31 is the last pin in GPIO port B. The JZ4730, the JZ4740, the JZ4725B,
the X1000 and the X1830 contains 4 GPIO ports, PA to PD, for a total of 128
- pins. The X2000 contains 5 GPIO ports, PA to PE, for a total of 160 pins.
- The JZ4750, the JZ4755 the JZ4760, the JZ4770 and the JZ4780 contains 6 GPIO
- ports, PA to PF, for a total of 192 pins. The JZ4775 contains 7 GPIO ports,
- PA to PG, for a total of 224 pins.
+ pins. The X2000 and the X2100 contains 5 GPIO ports, PA to PE, for a total of
+ 160 pins. The JZ4750, the JZ4755 the JZ4760, the JZ4770 and the JZ4780 contains
+ 6 GPIO ports, PA to PF, for a total of 192 pins. The JZ4775 contains 7 GPIO
+ ports, PA to PG, for a total of 224 pins.
maintainers:
- Paul Cercueil <paul@crapouillou.net>
@@ -47,6 +47,7 @@ properties:
- ingenic,x1500-pinctrl
- ingenic,x1830-pinctrl
- ingenic,x2000-pinctrl
+ - ingenic,x2100-pinctrl
- items:
- const: ingenic,jz4760b-pinctrl
- const: ingenic,jz4760-pinctrl
@@ -85,6 +86,7 @@ patternProperties:
- ingenic,x1500-gpio
- ingenic,x1830-gpio
- ingenic,x2000-gpio
+ - ingenic,x2100-gpio
reg:
items:
diff --git a/Documentation/devicetree/bindings/pinctrl/intel,pinctrl-keembay.yaml b/Documentation/devicetree/bindings/pinctrl/intel,pinctrl-keembay.yaml
new file mode 100644
index 000000000000..5e99d79499b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/intel,pinctrl-keembay.yaml
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/intel,pinctrl-keembay.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Intel Keem Bay pin controller Device Tree Bindings
+
+maintainers:
+ - Lakshmi Sowjanya D <lakshmi.sowjanya.d@intel.com>
+
+description: |
+ Intel Keem Bay SoC integrates a pin controller which enables control
+ of pin directions, input/output values and configuration
+ for a total of 80 pins.
+
+properties:
+ compatible:
+ const: intel,keembay-pinctrl
+
+ reg:
+ maxItems: 2
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+
+ ngpios:
+ description: The number of GPIOs exposed.
+ const: 80
+
+ interrupts:
+ description:
+ Specifies the interrupt lines to be used by the controller.
+ Each interrupt line is shared by upto 4 GPIO lines.
+ maxItems: 8
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+patternProperties:
+ '^gpio@[0-9a-f]*$':
+ type: object
+
+ description:
+ Child nodes can be specified to contain pin configuration information,
+ which can then be utilized by pinctrl client devices.
+ The following properties are supported.
+
+ properties:
+ pins:
+ description: |
+ The name(s) of the pins to be configured in the child node.
+ Supported pin names are "GPIO0" up to "GPIO79".
+
+ bias-disable: true
+
+ bias-pull-down: true
+
+ bias-pull-up: true
+
+ drive-strength:
+ description: IO pads drive strength in milli Ampere.
+ enum: [2, 4, 8, 12]
+
+ bias-bus-hold:
+ type: boolean
+
+ input-schmitt-enable:
+ type: boolean
+
+ slew-rate:
+ description: GPIO slew rate control.
+ 0 - Fast(~100MHz)
+ 1 - Slow(~50MHz)
+ enum: [0, 1]
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - ngpios
+ - '#gpio-cells'
+ - interrupts
+ - interrupt-controller
+ - '#interrupt-cells'
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ // Example 1
+ gpio@0 {
+ compatible = "intel,keembay-pinctrl";
+ reg = <0x600b0000 0x88>,
+ <0x600b0190 0x1ac>;
+ gpio-controller;
+ ngpios = <0x50>;
+ #gpio-cells = <0x2>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ // Example 2
+ gpio@1 {
+ compatible = "intel,keembay-pinctrl";
+ reg = <0x600c0000 0x88>,
+ <0x600c0190 0x1ac>;
+ gpio-controller;
+ ngpios = <0x50>;
+ #gpio-cells = <0x2>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
index 38dc56a57760..ecec514b3155 100644
--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
@@ -43,19 +43,19 @@ group emmc_nb
group pwm0
- pin 11 (GPIO1-11)
- - functions pwm, gpio
+ - functions pwm, led, gpio
group pwm1
- pin 12
- - functions pwm, gpio
+ - functions pwm, led, gpio
group pwm2
- pin 13
- - functions pwm, gpio
+ - functions pwm, led, gpio
group pwm3
- pin 14
- - functions pwm, gpio
+ - functions pwm, led, gpio
group pmic1
- pin 7
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
new file mode 100644
index 000000000000..f8e6e138dc13
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
@@ -0,0 +1,206 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/mediatek,mt65xx-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT65xx Pin Controller Device Tree Bindings
+
+maintainers:
+ - Sean Wang <sean.wang@kernel.org>
+
+description: |+
+ The Mediatek's Pin controller is used to control SoC pins.
+
+properties:
+ compatible:
+ enum:
+ - mediatek,mt2701-pinctrl
+ - mediatek,mt2712-pinctrl
+ - mediatek,mt6397-pinctrl
+ - mediatek,mt7623-pinctrl
+ - mediatek,mt8127-pinctrl
+ - mediatek,mt8135-pinctrl
+ - mediatek,mt8167-pinctrl
+ - mediatek,mt8173-pinctrl
+ - mediatek,mt8516-pinctrl
+
+ reg:
+ maxItems: 1
+
+ pins-are-numbered:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: |
+ Specify the subnodes are using numbered pinmux to specify pins.
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+ description: |
+ Number of cells in GPIO specifier. Since the generic GPIO
+ binding is used, the amount of cells must be specified as 2. See the below
+ mentioned gpio binding representation for description of particular cells.
+
+ mediatek,pctl-regmap:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ minItems: 1
+ maxItems: 2
+ description: |
+ Should be phandles of the syscfg node.
+
+ interrupt-controller: true
+
+ interrupts:
+ minItems: 1
+ maxItems: 3
+
+ "#interrupt-cells":
+ const: 2
+
+required:
+ - compatible
+ - pins-are-numbered
+ - gpio-controller
+ - "#gpio-cells"
+
+patternProperties:
+ '-[0-9]+$':
+ type: object
+ additionalProperties: false
+ patternProperties:
+ 'pins':
+ type: object
+ additionalProperties: false
+ description: |
+ A pinctrl node should contain at least one subnodes representing the
+ pinctrl groups available on the machine. Each subnode will list the
+ pins it needs, and how they should be configured, with regard to muxer
+ configuration, pullups, drive strength, input enable/disable and input
+ schmitt.
+ $ref: "/schemas/pinctrl/pincfg-node.yaml"
+
+ properties:
+ pinmux:
+ description:
+ integer array, represents gpio pin number and mux setting.
+ Supported pin number and mux varies for different SoCs, and are
+ defined as macros in <soc>-pinfunc.h directly.
+
+ bias-disable: true
+
+ bias-pull-up:
+ description: |
+ Besides generic pinconfig options, it can be used as the pull up
+ settings for 2 pull resistors, R0 and R1. User can configure those
+ special pins. Some macros have been defined for this usage, such
+ as MTK_PUPD_SET_R1R0_00. See dt-bindings/pinctrl/mt65xx.h for
+ valid arguments.
+
+ bias-pull-down: true
+
+ input-enable: true
+
+ input-disable: true
+
+ output-low: true
+
+ output-high: true
+
+ input-schmitt-enable: true
+
+ input-schmitt-disable: true
+
+ drive-strength:
+ description: |
+ Can support some arguments, such as MTK_DRIVE_4mA, MTK_DRIVE_6mA,
+ etc. See dt-bindings/pinctrl/mt65xx.h for valid arguments.
+
+ required:
+ - pinmux
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/pinctrl/mt8135-pinfunc.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ syscfg_pctl_a: syscfg-pctl-a@10005000 {
+ compatible = "mediatek,mt8135-pctl-a-syscfg", "syscon";
+ reg = <0 0x10005000 0 0x1000>;
+ };
+
+ syscfg_pctl_b: syscfg-pctl-b@1020c020 {
+ compatible = "mediatek,mt8135-pctl-b-syscfg", "syscon";
+ reg = <0 0x1020C020 0 0x1000>;
+ };
+
+ pinctrl@1c20800 {
+ compatible = "mediatek,mt8135-pinctrl";
+ reg = <0 0x1000B000 0 0x1000>;
+ mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
+ pins-are-numbered;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+
+ i2c0_pins_a: i2c0-0 {
+ pins1 {
+ pinmux = <MT8135_PIN_100_SDA0__FUNC_SDA0>,
+ <MT8135_PIN_101_SCL0__FUNC_SCL0>;
+ bias-disable;
+ };
+ };
+
+ i2c1_pins_a: i2c1-0 {
+ pins {
+ pinmux = <MT8135_PIN_195_SDA1__FUNC_SDA1>,
+ <MT8135_PIN_196_SCL1__FUNC_SCL1>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ };
+
+ i2c2_pins_a: i2c2-0 {
+ pins1 {
+ pinmux = <MT8135_PIN_193_SDA2__FUNC_SDA2>;
+ bias-pull-down;
+ };
+
+ pins2 {
+ pinmux = <MT8135_PIN_49_WATCHDOG__FUNC_GPIO49>;
+ bias-pull-up;
+ };
+ };
+
+ i2c3_pins_a: i2c3-0 {
+ pins1 {
+ pinmux = <MT8135_PIN_40_DAC_CLK__FUNC_GPIO40>,
+ <MT8135_PIN_41_DAC_WS__FUNC_GPIO41>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins2 {
+ pinmux = <MT8135_PIN_35_SCL3__FUNC_SCL3>,
+ <MT8135_PIN_36_SDA3__FUNC_SDA3>;
+ output-low;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins3 {
+ pinmux = <MT8135_PIN_57_JTCK__FUNC_GPIO57>,
+ <MT8135_PIN_60_JTDI__FUNC_JTDI>;
+ drive-strength = <32>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml
new file mode 100644
index 000000000000..76a6df75ed9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/mediatek,mt6797-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT6797 Pin Controller Device Tree Bindings
+
+maintainers:
+ - Sean Wang <sean.wang@kernel.org>
+
+description: |+
+ The MediaTek's MT6797 Pin controller is used to control SoC pins.
+
+properties:
+ compatible:
+ const: mediatek,mt6797-pinctrl
+
+ reg:
+ minItems: 5
+ maxItems: 5
+
+ reg-names:
+ items:
+ - const: gpio
+ - const: iocfgl
+ - const: iocfgb
+ - const: iocfgr
+ - const: iocfgt
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+ description: |
+ Number of cells in GPIO specifier. Since the generic GPIO
+ binding is used, the amount of cells must be specified as 2. See the below
+ mentioned gpio binding representation for description of particular cells.
+
+ interrupt-controller: true
+
+ interrupts:
+ maxItems: 1
+
+ "#interrupt-cells":
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - gpio-controller
+ - "#gpio-cells"
+
+patternProperties:
+ '-[0-9]+$':
+ type: object
+ additionalProperties: false
+ patternProperties:
+ 'pins':
+ type: object
+ additionalProperties: false
+ description: |
+ A pinctrl node should contain at least one subnodes representing the
+ pinctrl groups available on the machine. Each subnode will list the
+ pins it needs, and how they should be configured, with regard to muxer
+ configuration, pullups, drive strength, input enable/disable and input
+ schmitt.
+ $ref: "/schemas/pinctrl/pincfg-node.yaml"
+
+ properties:
+ pinmux:
+ description:
+ integer array, represents gpio pin number and mux setting.
+ Supported pin number and mux varies for different SoCs, and are
+ defined as macros in <soc>-pinfunc.h directly.
+
+ bias-disable: true
+
+ bias-pull-up: true
+
+ bias-pull-down: true
+
+ input-enable: true
+
+ input-disable: true
+
+ output-enable: true
+
+ output-low: true
+
+ output-high: true
+
+ input-schmitt-enable: true
+
+ input-schmitt-disable: true
+
+ drive-strength:
+ enum: [2, 4, 8, 12, 16]
+
+ slew-rate:
+ enum: [0, 1]
+
+ mediatek,pull-up-adv:
+ description: |
+ Pull up setings for 2 pull resistors, R0 and R1. User can
+ configure those special pins. Valid arguments are described as below:
+ 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled.
+ 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled.
+ 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled.
+ 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3]
+
+ mediatek,pull-down-adv:
+ description: |
+ Pull down settings for 2 pull resistors, R0 and R1. User can
+ configure those special pins. Valid arguments are described as below:
+ 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled.
+ 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled.
+ 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled.
+ 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3]
+
+ mediatek,tdsel:
+ description: |
+ An integer describing the steps for output level shifter duty
+ cycle when asserted (high pulse width adjustment). Valid arguments
+ are from 0 to 15.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ mediatek,rdsel:
+ description: |
+ An integer describing the steps for input level shifter duty cycle
+ when asserted (high pulse width adjustment). Valid arguments are
+ from 0 to 63.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ required:
+ - pinmux
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/pinctrl/mt6797-pinfunc.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pio: pinctrl@10005000 {
+ compatible = "mediatek,mt6797-pinctrl";
+ reg = <0 0x10005000 0 0x1000>,
+ <0 0x10002000 0 0x400>,
+ <0 0x10002400 0 0x400>,
+ <0 0x10002800 0 0x400>,
+ <0 0x10002C00 0 0x400>;
+ reg-names = "gpio", "iocfgl", "iocfgb", "iocfgr", "iocfgt";
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ uart_pins_a: uart-0 {
+ pins1 {
+ pinmux = <MT6797_GPIO232__FUNC_URXD1>,
+ <MT6797_GPIO233__FUNC_UTXD1>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
new file mode 100644
index 000000000000..0feecd376c69
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
@@ -0,0 +1,373 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/mediatek,mt7622-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT7622 Pin Controller Device Tree Bindings
+
+maintainers:
+ - Sean Wang <sean.wang@kernel.org>
+
+description: |+
+ The MediaTek's MT7622 Pin controller is used to control SoC pins.
+
+properties:
+ compatible:
+ enum:
+ - mediatek,mt7622-pinctrl
+ - mediatek,mt7629-pinctrl
+
+ reg:
+ maxItems: 1
+
+ reg-names:
+ items:
+ - const: eint
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+ description: |
+ Number of cells in GPIO specifier. Since the generic GPIO
+ binding is used, the amount of cells must be specified as 2. See the below
+ mentioned gpio binding representation for description of particular cells.
+
+ interrupt-controller: true
+
+ interrupts:
+ maxItems: 1
+
+ "#interrupt-cells":
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - "#gpio-cells"
+
+if:
+ required:
+ - interrupt-controller
+then:
+ required:
+ - reg-names
+ - interrupts
+ - "#interrupt-cells"
+
+patternProperties:
+ '-[0-9]+$':
+ type: object
+ additionalProperties: false
+ patternProperties:
+ 'mux':
+ type: object
+ additionalProperties: false
+ description: |
+ pinmux configuration nodes.
+ $ref: "/schemas/pinctrl/pinmux-node.yaml"
+ properties:
+ function:
+ description: |
+ A string containing the name of the function to mux to the group.
+ enum: [emmc, eth, i2c, i2s, ir, led, flash, pcie, pmic, pwm, sd,
+ spi, tdm, uart, watchdog, wifi]
+
+ groups:
+ description: |
+ An array of strings. Each string contains the name of a group.
+
+ drive-strength:
+ enum: [4, 8, 12, 16]
+
+ required:
+ - groups
+ - function
+
+ allOf:
+ - if:
+ properties:
+ function:
+ const: emmc
+ then:
+ properties:
+ groups:
+ enum: [emmc, emmc_rst]
+ - if:
+ properties:
+ function:
+ const: eth
+ then:
+ properties:
+ groups:
+ enum: [esw, esw_p0_p1, esw_p2_p3_p4, rgmii_via_esw,
+ rgmii_via_gmac1, rgmii_via_gmac2, mdc_mdio]
+ - if:
+ properties:
+ function:
+ const: i2c
+ then:
+ properties:
+ groups:
+ enum: [i2c0, i2c_0, i2c_1, i2c1_0, i2c1_1, i2c1_2, i2c2_0,
+ i2c2_1, i2c2_2]
+ - if:
+ properties:
+ function:
+ const: i2s
+ then:
+ properties:
+ groups:
+ enum: [i2s_in_mclk_bclk_ws, i2s1_in_data, i2s2_in_data,
+ i2s3_in_data, i2s4_in_data, i2s_out_mclk_bclk_ws,
+ i2s1_out_data, i2s2_out_data, i2s3_out_data,
+ i2s4_out_data]
+ - if:
+ properties:
+ function:
+ const: ir
+ then:
+ properties:
+ groups:
+ enum: [ir_0_tx, ir_1_tx, ir_2_tx, ir_0_rx, ir_1_rx, ir_2_rx]
+ - if:
+ properties:
+ function:
+ const: led
+ then:
+ properties:
+ groups:
+ enum: [ephy_leds, ephy0_led, ephy1_led, ephy2_led, ephy3_led,
+ ephy4_led, wled, wf2g_led, wf5g_led]
+ - if:
+ properties:
+ function:
+ const: flash
+ then:
+ properties:
+ groups:
+ enum: [par_nand, snfi, spi_nor]
+ - if:
+ properties:
+ function:
+ const: pcie
+ then:
+ properties:
+ groups:
+ enum: [pcie0_0_waken, pcie0_1_waken, pcie1_0_waken,
+ pcie0_0_clkreq, pcie0_1_clkreq, pcie1_0_clkreq,
+ pcie0_pad_perst, pcie1_pad_perst, pcie_pereset,
+ pcie_wake, pcie_clkreq]
+ - if:
+ properties:
+ function:
+ const: pmic
+ then:
+ properties:
+ groups:
+ enum: [pmic_bus]
+ - if:
+ properties:
+ function:
+ const: pwm
+ then:
+ properties:
+ groups:
+ enum: [pwm_ch1_0, pwm_ch1_1, pwm_ch1_2, pwm_ch2_0, pwm_ch2_1,
+ pwm_ch2_2, pwm_ch3_0, pwm_ch3_1, pwm_ch3_2, pwm_ch4_0,
+ pwm_ch4_1, pwm_ch4_2, pwm_ch4_3, pwm_ch5_0, pwm_ch5_1,
+ pwm_ch5_2, pwm_ch6_0, pwm_ch6_1, pwm_ch6_2, pwm_ch6_3,
+ pwm_ch7_0, pwm_0, pwm_1]
+ - if:
+ properties:
+ function:
+ const: sd
+ then:
+ properties:
+ groups:
+ enum: [sd_0, sd_1]
+ - if:
+ properties:
+ function:
+ const: spi
+ then:
+ properties:
+ groups:
+ enum: [spic0_0, spic0_1, spic1_0, spic1_1, spic2_0_wp_hold,
+ spic2_0, spi_0, spi_1, spi_wp, spi_hold]
+ - if:
+ properties:
+ function:
+ const: tdm
+ then:
+ properties:
+ groups:
+ enum: [tdm_0_out_mclk_bclk_ws, tdm_0_in_mclk_bclk_ws,
+ tdm_0_out_data, tdm_0_in_data, tdm_1_out_mclk_bclk_ws,
+ tdm_1_in_mclk_bclk_ws, tdm_1_out_data, tdm_1_in_data]
+ - if:
+ properties:
+ function:
+ const: uart
+ then:
+ properties:
+ groups:
+ enum: [uart0_0_tx_rx, uart1_0_tx_rx, uart1_0_rts_cts,
+ uart1_1_tx_rx, uart1_1_rts_cts, uart2_0_tx_rx,
+ uart2_0_rts_cts, uart2_1_tx_rx, uart2_1_rts_cts,
+ uart2_2_tx_rx, uart2_2_rts_cts, uart2_3_tx_rx,
+ uart3_0_tx_rx, uart3_1_tx_rx, uart3_1_rts_cts,
+ uart4_0_tx_rx, uart4_1_tx_rx, uart4_1_rts_cts,
+ uart4_2_tx_rx, uart4_2_rts_cts, uart0_txd_rxd,
+ uart1_0_txd_rxd, uart1_0_cts_rts, uart1_1_txd_rxd,
+ uart1_1_cts_rts, uart2_0_txd_rxd, uart2_0_cts_rts,
+ uart2_1_txd_rxd, uart2_1_cts_rts]
+ - if:
+ properties:
+ function:
+ const: watchdog
+ then:
+ properties:
+ groups:
+ enum: [watchdog]
+ - if:
+ properties:
+ function:
+ const: wifi
+ then:
+ properties:
+ groups:
+ enum: [wf0_2g, wf0_5g]
+
+ 'conf':
+ type: object
+ additionalProperties: false
+ description: |
+ pinconf configuration nodes.
+ $ref: "/schemas/pinctrl/pincfg-node.yaml"
+
+ properties:
+ groups:
+ description: |
+ An array of strings. Each string contains the name of a group.
+ Valid values are the same as the pinmux node.
+
+ pins:
+ description: |
+ An array of strings. Each string contains the name of a pin.
+ enum: [GPIO_A, I2S1_IN, I2S1_OUT, I2S_BCLK, I2S_WS, I2S_MCLK, TXD0,
+ RXD0, SPI_WP, SPI_HOLD, SPI_CLK, SPI_MOSI, SPI_MISO, SPI_CS,
+ I2C_SDA, I2C_SCL, I2S2_IN, I2S3_IN, I2S4_IN, I2S2_OUT,
+ I2S3_OUT, I2S4_OUT, GPIO_B, MDC, MDIO, G2_TXD0, G2_TXD1,
+ G2_TXD2, G2_TXD3, G2_TXEN, G2_TXC, G2_RXD0, G2_RXD1, G2_RXD2,
+ G2_RXD3, G2_RXDV, G2_RXC, NCEB, NWEB, NREB, NDL4, NDL5, NDL6,
+ NDL7, NRB, NCLE, NALE, NDL0, NDL1, NDL2, NDL3, MDI_TP_P0,
+ MDI_TN_P0, MDI_RP_P0, MDI_RN_P0, MDI_TP_P1, MDI_TN_P1,
+ MDI_RP_P1, MDI_RN_P1, MDI_RP_P2, MDI_RN_P2, MDI_TP_P2,
+ MDI_TN_P2, MDI_TP_P3, MDI_TN_P3, MDI_RP_P3, MDI_RN_P3,
+ MDI_RP_P4, MDI_RN_P4, MDI_TP_P4, MDI_TN_P4, PMIC_SCL,
+ PMIC_SDA, SPIC1_CLK, SPIC1_MOSI, SPIC1_MISO, SPIC1_CS,
+ GPIO_D, WATCHDOG, RTS3_N, CTS3_N, TXD3, RXD3, PERST0_N,
+ PERST1_N, WLED_N, EPHY_LED0_N, AUXIN0, AUXIN1, AUXIN2,
+ AUXIN3, TXD4, RXD4, RTS4_N, CST4_N, PWM1, PWM2, PWM3, PWM4,
+ PWM5, PWM6, PWM7, GPIO_E, TOP_5G_CLK, TOP_5G_DATA,
+ WF0_5G_HB0, WF0_5G_HB1, WF0_5G_HB2, WF0_5G_HB3, WF0_5G_HB4,
+ WF0_5G_HB5, WF0_5G_HB6, XO_REQ, TOP_RST_N, SYS_WATCHDOG,
+ EPHY_LED0_N_JTDO, EPHY_LED1_N_JTDI, EPHY_LED2_N_JTMS,
+ EPHY_LED3_N_JTCLK, EPHY_LED4_N_JTRST_N, WF2G_LED_N,
+ WF5G_LED_N, GPIO_9, GPIO_10, GPIO_11, GPIO_12, UART1_TXD,
+ UART1_RXD, UART1_CTS, UART1_RTS, UART2_TXD, UART2_RXD,
+ UART2_CTS, UART2_RTS, SMI_MDC, SMI_MDIO, PCIE_PERESET_N,
+ PWM_0, GPIO_0, GPIO_1, GPIO_2, GPIO_3, GPIO_4, GPIO_5,
+ GPIO_6, GPIO_7, GPIO_8, UART0_TXD, UART0_RXD, TOP_2G_CLK,
+ TOP_2G_DATA, WF0_2G_HB0, WF0_2G_HB1, WF0_2G_HB2, WF0_2G_HB3,
+ WF0_2G_HB4, WF0_2G_HB5, WF0_2G_HB6]
+
+ bias-disable: true
+
+ bias-pull-up: true
+
+ bias-pull-down: true
+
+ input-enable: true
+
+ input-disable: true
+
+ output-enable: true
+
+ output-low: true
+
+ output-high: true
+
+ input-schmitt-enable: true
+
+ input-schmitt-disable: true
+
+ drive-strength:
+ enum: [4, 8, 12, 16]
+
+ slew-rate:
+ enum: [0, 1]
+
+ mediatek,tdsel:
+ description: |
+ An integer describing the steps for output level shifter duty
+ cycle when asserted (high pulse width adjustment). Valid arguments
+ are from 0 to 15.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ mediatek,rdsel:
+ description: |
+ An integer describing the steps for input level shifter duty cycle
+ when asserted (high pulse width adjustment). Valid arguments are
+ from 0 to 63.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ required:
+ - pins
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pio: pinctrl@10211000 {
+ compatible = "mediatek,mt7622-pinctrl";
+ reg = <0 0x10211000 0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ pinctrl_eth_default: eth-0 {
+ mux-mdio {
+ groups = "mdc_mdio";
+ function = "eth";
+ drive-strength = <12>;
+ };
+
+ mux-gmac2 {
+ groups = "rgmii_via_gmac2";
+ function = "eth";
+ drive-strength = <12>;
+ };
+
+ mux-esw {
+ groups = "esw";
+ function = "eth";
+ drive-strength = <8>;
+ };
+
+ conf-mdio {
+ pins = "MDC";
+ bias-pull-up;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
new file mode 100644
index 000000000000..cc1509e9b981
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
@@ -0,0 +1,228 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/mediatek,mt8183-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8183 Pin Controller Device Tree Bindings
+
+maintainers:
+ - Sean Wang <sean.wang@kernel.org>
+
+description: |+
+ The MediaTek's MT8183 Pin controller is used to control SoC pins.
+
+properties:
+ compatible:
+ const: mediatek,mt8183-pinctrl
+
+ reg:
+ minItems: 10
+ maxItems: 10
+
+ reg-names:
+ items:
+ - const: iocfg0
+ - const: iocfg1
+ - const: iocfg2
+ - const: iocfg3
+ - const: iocfg4
+ - const: iocfg5
+ - const: iocfg6
+ - const: iocfg7
+ - const: iocfg8
+ - const: eint
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+ description: |
+ Number of cells in GPIO specifier. Since the generic GPIO
+ binding is used, the amount of cells must be specified as 2. See the below
+ mentioned gpio binding representation for description of particular cells.
+
+ gpio-ranges:
+ minItems: 1
+ maxItems: 5
+ description: |
+ GPIO valid number range.
+
+ interrupt-controller: true
+
+ interrupts:
+ maxItems: 1
+
+ "#interrupt-cells":
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - "#gpio-cells"
+ - gpio-ranges
+
+patternProperties:
+ '-[0-9]+$':
+ type: object
+ additionalProperties: false
+ patternProperties:
+ 'pins':
+ type: object
+ additionalProperties: false
+ description: |
+ A pinctrl node should contain at least one subnodes representing the
+ pinctrl groups available on the machine. Each subnode will list the
+ pins it needs, and how they should be configured, with regard to muxer
+ configuration, pullups, drive strength, input enable/disable and input
+ schmitt.
+ $ref: "/schemas/pinctrl/pincfg-node.yaml"
+
+ properties:
+ pinmux:
+ description:
+ integer array, represents gpio pin number and mux setting.
+ Supported pin number and mux varies for different SoCs, and are
+ defined as macros in <soc>-pinfunc.h directly.
+
+ bias-disable: true
+
+ bias-pull-up: true
+
+ bias-pull-down: true
+
+ input-enable: true
+
+ input-disable: true
+
+ output-low: true
+
+ output-high: true
+
+ input-schmitt-enable: true
+
+ input-schmitt-disable: true
+
+ drive-strength:
+ enum: [2, 4, 6, 8, 10, 12, 14, 16]
+
+ mediatek,drive-strength-adv:
+ description: |
+ Describe the specific driving setup property.
+ For I2C pins, the existing generic driving setup can only support
+ 2/4/6/8/10/12/14/16mA driving. But in specific driving setup, they
+ can support 0.125/0.25/0.5/1mA adjustment. If we enable specific
+ driving setup, the existing generic setup will be disabled.
+ The specific driving setup is controlled by E1E0EN.
+ When E1=0/E0=0, the strength is 0.125mA.
+ When E1=0/E0=1, the strength is 0.25mA.
+ When E1=1/E0=0, the strength is 0.5mA.
+ When E1=1/E0=1, the strength is 1mA.
+ EN is used to enable or disable the specific driving setup.
+ Valid arguments are described as below:
+ 0: (E1, E0, EN) = (0, 0, 0)
+ 1: (E1, E0, EN) = (0, 0, 1)
+ 2: (E1, E0, EN) = (0, 1, 0)
+ 3: (E1, E0, EN) = (0, 1, 1)
+ 4: (E1, E0, EN) = (1, 0, 0)
+ 5: (E1, E0, EN) = (1, 0, 1)
+ 6: (E1, E0, EN) = (1, 1, 0)
+ 7: (E1, E0, EN) = (1, 1, 1)
+ So the valid arguments are from 0 to 7.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3, 4, 5, 6, 7]
+
+ mediatek,pull-up-adv:
+ description: |
+ Pull up setings for 2 pull resistors, R0 and R1. User can
+ configure those special pins. Valid arguments are described as below:
+ 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled.
+ 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled.
+ 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled.
+ 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3]
+
+ mediatek,pull-down-adv:
+ description: |
+ Pull down settings for 2 pull resistors, R0 and R1. User can
+ configure those special pins. Valid arguments are described as below:
+ 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled.
+ 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled.
+ 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled.
+ 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3]
+
+ mediatek,tdsel:
+ description: |
+ An integer describing the steps for output level shifter duty
+ cycle when asserted (high pulse width adjustment). Valid arguments
+ are from 0 to 15.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ mediatek,rdsel:
+ description: |
+ An integer describing the steps for input level shifter duty cycle
+ when asserted (high pulse width adjustment). Valid arguments are
+ from 0 to 63.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ required:
+ - pinmux
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/pinctrl/mt8183-pinfunc.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pio: pinctrl@10005000 {
+ compatible = "mediatek,mt8183-pinctrl";
+ reg = <0 0x10005000 0 0x1000>,
+ <0 0x11f20000 0 0x1000>,
+ <0 0x11e80000 0 0x1000>,
+ <0 0x11e70000 0 0x1000>,
+ <0 0x11e90000 0 0x1000>,
+ <0 0x11d30000 0 0x1000>,
+ <0 0x11d20000 0 0x1000>,
+ <0 0x11c50000 0 0x1000>,
+ <0 0x11f30000 0 0x1000>,
+ <0 0x1000b000 0 0x1000>;
+ reg-names = "iocfg0", "iocfg1", "iocfg2",
+ "iocfg3", "iocfg4", "iocfg5",
+ "iocfg6", "iocfg7", "iocfg8",
+ "eint";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pio 0 0 192>;
+ interrupt-controller;
+ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <2>;
+
+ i2c0_pins_a: i2c-0 {
+ pins1 {
+ pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
+ <PINMUX_GPIO49__FUNC_SDA5>;
+ mediatek,pull-up-adv = <3>;
+ mediatek,drive-strength-adv = <7>;
+ };
+ };
+
+ i2c1_pins_a: i2c-1 {
+ pins {
+ pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
+ <PINMUX_GPIO51__FUNC_SDA3>;
+ mediatek,pull-down-adv = <2>;
+ mediatek,drive-strength-adv = <4>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
deleted file mode 100644
index 5fe2c26c28bf..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
+++ /dev/null
@@ -1,156 +0,0 @@
-* Mediatek MT65XX Pin Controller
-
-The Mediatek's Pin controller is used to control SoC pins.
-
-Required properties:
-- compatible: value should be one of the following.
- "mediatek,mt2701-pinctrl", compatible with mt2701 pinctrl.
- "mediatek,mt2712-pinctrl", compatible with mt2712 pinctrl.
- "mediatek,mt6397-pinctrl", compatible with mt6397 pinctrl.
- "mediatek,mt7623-pinctrl", compatible with mt7623 pinctrl.
- "mediatek,mt8127-pinctrl", compatible with mt8127 pinctrl.
- "mediatek,mt8135-pinctrl", compatible with mt8135 pinctrl.
- "mediatek,mt8167-pinctrl", compatible with mt8167 pinctrl.
- "mediatek,mt8173-pinctrl", compatible with mt8173 pinctrl.
- "mediatek,mt8365-pinctrl", compatible with mt8365 pinctrl.
- "mediatek,mt8516-pinctrl", compatible with mt8516 pinctrl.
-- pins-are-numbered: Specify the subnodes are using numbered pinmux to
- specify pins.
-- gpio-controller : Marks the device node as a gpio controller.
-- #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
- binding is used, the amount of cells must be specified as 2. See the below
- mentioned gpio binding representation for description of particular cells.
-
- Eg: <&pio 6 0>
- <[phandle of the gpio controller node]
- [line number within the gpio controller]
- [flags]>
-
- Values for gpio specifier:
- - Line number: is a value between 0 to 202.
- - Flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
- Only the following flags are supported:
- 0 - GPIO_ACTIVE_HIGH
- 1 - GPIO_ACTIVE_LOW
-
-Optional properties:
-- mediatek,pctl-regmap: Should be a phandle of the syscfg node.
-- reg: physicall address base for EINT registers
-- interrupt-controller: Marks the device node as an interrupt controller
-- #interrupt-cells: Should be two.
-- interrupts : The interrupt outputs from the controller.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices.
-
-Subnode format
-A pinctrl node should contain at least one subnodes representing the
-pinctrl groups available on the machine. Each subnode will list the
-pins it needs, and how they should be configured, with regard to muxer
-configuration, pullups, drive strength, input enable/disable and input schmitt.
-
- node {
- pinmux = <PIN_NUMBER_PINMUX>;
- GENERIC_PINCONFIG;
- };
-
-Required properties:
-- pinmux: integer array, represents gpio pin number and mux setting.
- Supported pin number and mux varies for different SoCs, and are defined
- as macros in boot/dts/<soc>-pinfunc.h directly.
-
-Optional properties:
-- GENERIC_PINCONFIG: is the generic pinconfig options to use, bias-disable,
- bias-pull-down, bias-pull-up, input-enable, input-disable, output-low, output-high,
- input-schmitt-enable, input-schmitt-disable and drive-strength are valid.
-
- Some special pins have extra pull up strength, there are R0 and R1 pull-up
- resistors available, but for user, it's only need to set R1R0 as 00, 01, 10 or 11.
- So when config bias-pull-up, it support arguments for those special pins.
- Some macros have been defined for this usage, such as MTK_PUPD_SET_R1R0_00.
- See dt-bindings/pinctrl/mt65xx.h.
-
- When config drive-strength, it can support some arguments, such as
- MTK_DRIVE_4mA, MTK_DRIVE_6mA, etc. See dt-bindings/pinctrl/mt65xx.h.
-
-Examples:
-
-#include "mt8135-pinfunc.h"
-
-...
-{
- syscfg_pctl_a: syscfg-pctl-a@10005000 {
- compatible = "mediatek,mt8135-pctl-a-syscfg", "syscon";
- reg = <0 0x10005000 0 0x1000>;
- };
-
- syscfg_pctl_b: syscfg-pctl-b@1020c020 {
- compatible = "mediatek,mt8135-pctl-b-syscfg", "syscon";
- reg = <0 0x1020C020 0 0x1000>;
- };
-
- pinctrl@1c20800 {
- compatible = "mediatek,mt8135-pinctrl";
- reg = <0 0x1000B000 0 0x1000>;
- mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
- pins-are-numbered;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
-
- i2c0_pins_a: i2c0@0 {
- pins1 {
- pinmux = <MT8135_PIN_100_SDA0__FUNC_SDA0>,
- <MT8135_PIN_101_SCL0__FUNC_SCL0>;
- bias-disable;
- };
- };
-
- i2c1_pins_a: i2c1@0 {
- pins {
- pinmux = <MT8135_PIN_195_SDA1__FUNC_SDA1>,
- <MT8135_PIN_196_SCL1__FUNC_SCL1>;
- bias-pull-up = <55>;
- };
- };
-
- i2c2_pins_a: i2c2@0 {
- pins1 {
- pinmux = <MT8135_PIN_193_SDA2__FUNC_SDA2>;
- bias-pull-down;
- };
-
- pins2 {
- pinmux = <MT8135_PIN_49_WATCHDOG__FUNC_GPIO49>;
- bias-pull-up;
- };
- };
-
- i2c3_pins_a: i2c3@0 {
- pins1 {
- pinmux = <MT8135_PIN_40_DAC_CLK__FUNC_GPIO40>,
- <MT8135_PIN_41_DAC_WS__FUNC_GPIO41>;
- bias-pull-up = <55>;
- };
-
- pins2 {
- pinmux = <MT8135_PIN_35_SCL3__FUNC_SCL3>,
- <MT8135_PIN_36_SDA3__FUNC_SDA3>;
- output-low;
- bias-pull-up = <55>;
- };
-
- pins3 {
- pinmux = <MT8135_PIN_57_JTCK__FUNC_GPIO57>,
- <MT8135_PIN_60_JTDI__FUNC_JTDI>;
- drive-strength = <32>;
- };
- };
-
- ...
- }
-};
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt6797.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt6797.txt
deleted file mode 100644
index bd83401e6179..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt6797.txt
+++ /dev/null
@@ -1,83 +0,0 @@
-* MediaTek MT6797 Pin Controller
-
-The MediaTek's MT6797 Pin controller is used to control SoC pins.
-
-Required properties:
-- compatible: Value should be one of the following.
- "mediatek,mt6797-pinctrl", compatible with mt6797 pinctrl.
-- reg: Should contain address and size for gpio, iocfgl, iocfgb,
- iocfgr and iocfgt register bases.
-- reg-names: An array of strings describing the "reg" entries. Must
- contain "gpio", "iocfgl", "iocfgb", "iocfgr", "iocfgt".
-- gpio-controller: Marks the device node as a gpio controller.
-- #gpio-cells: Should be two. The first cell is the gpio pin number
- and the second cell is used for optional parameters.
-
-Optional properties:
-- interrupt-controller: Marks the device node as an interrupt controller.
-- #interrupt-cells: Should be two.
-- interrupts : The interrupt outputs from the controller.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices.
-
-Subnode format
-A pinctrl node should contain at least one subnodes representing the
-pinctrl groups available on the machine. Each subnode will list the
-pins it needs, and how they should be configured, with regard to muxer
-configuration, pullups, drive strength, input enable/disable and input schmitt.
-
- node {
- pinmux = <PIN_NUMBER_PINMUX>;
- GENERIC_PINCONFIG;
- };
-
-Required properties:
-- pinmux: Integer array, represents gpio pin number and mux setting.
- Supported pin number and mux varies for different SoCs, and are defined
- as macros in dt-bindings/pinctrl/<soc>-pinfunc.h directly.
-
-Optional properties:
-- GENERIC_PINCONFIG: is the generic pinconfig options to use, bias-disable,
- bias-pull, bias-pull-down, input-enable, input-schmitt-enable,
- input-schmitt-disable, output-enable output-low, output-high,
- drive-strength, and slew-rate are valid.
-
- Valid arguments for 'slew-rate' are '0' for no slew rate controlled and
- '1' for slower slew rate respectively. Valid arguments for 'drive-strength'
- is limited, such as 2, 4, 8, 12, or 16 in mA.
-
- Some optional vendor properties as defined are valid to specify in a
- pinconf subnode:
- - mediatek,tdsel: An integer describing the steps for output level shifter
- duty cycle when asserted (high pulse width adjustment). Valid arguments
- are from 0 to 15.
- - mediatek,rdsel: An integer describing the steps for input level shifter
- duty cycle when asserted (high pulse width adjustment). Valid arguments
- are from 0 to 63.
- - mediatek,pull-up-adv: An integer describing the code R1R0 as 0, 1, 2
- or 3 for the advanced pull-up resistors.
- - mediatek,pull-down-adv: An integer describing the code R1R0 as 0, 1, 2,
- or 3 for the advanced pull-down resistors.
-
-Examples:
-
- pio: pinctrl@10005000 {
- compatible = "mediatek,mt6797-pinctrl";
- reg = <0 0x10005000 0 0x1000>,
- <0 0x10002000 0 0x400>,
- <0 0x10002400 0 0x400>,
- <0 0x10002800 0 0x400>,
- <0 0x10002C00 0 0x400>;
- reg-names = "gpio", "iocfgl", "iocfgb",
- "iocfgr", "iocfgt";
- gpio-controller;
- #gpio-cells = <2>;
-
- uart1_pins_a: uart1 {
- pins1 {
- pinmux = <MT6797_GPIO232__FUNC_URXD1>,
- <MT6797_GPIO233__FUNC_UTXD1>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
deleted file mode 100644
index 7a7aca1ed705..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
+++ /dev/null
@@ -1,490 +0,0 @@
-== MediaTek MT7622 pinctrl controller ==
-
-Required properties for the root node:
- - compatible: Should be one of the following
- "mediatek,mt7622-pinctrl" for MT7622 SoC
- "mediatek,mt7629-pinctrl" for MT7629 SoC
- - reg: offset and length of the pinctrl space
-
- - gpio-controller: Marks the device node as a GPIO controller.
- - #gpio-cells: Should be two. The first cell is the pin number and the
- second is the GPIO flags.
-
-Optional properties:
-- interrupt-controller : Marks the device node as an interrupt controller
-
-If the property interrupt-controller is defined, following property is required
-- reg-names: A string describing the "reg" entries. Must contain "eint".
-- interrupts : The interrupt output from the controller.
-- #interrupt-cells: Should be two.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-MT7622 pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, slew rate, etc.
-
-We support 2 types of configuration nodes. Those nodes can be either pinmux
-nodes or pinconf nodes. Each configuration node can consist of multiple nodes
-describing the pinmux and pinconf options.
-
-The name of each subnode doesn't matter as long as it is unique; all subnodes
-should be enumerated and processed purely based on their content.
-
-== pinmux nodes content ==
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pinmux subnode:
-
-Required properties are:
- - groups: An array of strings. Each string contains the name of a group.
- Valid values for these names are listed below.
- - function: A string containing the name of the function to mux to the
- group. Valid values for function names are listed below.
-
-== pinconf nodes content ==
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pinconf subnode:
-
-Required properties are:
- - pins: An array of strings. Each string contains the name of a pin.
- Valid values for these names are listed below.
- - groups: An array of strings. Each string contains the name of a group.
- Valid values for these names are listed below.
-
-Optional properies are:
- bias-disable, bias-pull, bias-pull-down, input-enable,
- input-schmitt-enable, input-schmitt-disable, output-enable
- output-low, output-high, drive-strength, slew-rate
-
- Valid arguments for 'slew-rate' are '0' for no slew rate controlled and '1' for
- slower slew rate respectively.
- Valid arguments for 'drive-strength', 4, 8, 12, or 16 in mA.
-
-The following specific properties as defined are valid to specify in a pinconf
-subnode:
-
-Optional properties are:
- - mediatek,tdsel: An integer describing the steps for output level shifter duty
- cycle when asserted (high pulse width adjustment). Valid arguments are from 0
- to 15.
- - mediatek,rdsel: An integer describing the steps for input level shifter duty
- cycle when asserted (high pulse width adjustment). Valid arguments are from 0
- to 63.
-
-== Valid values for pins, function and groups on MT7622 ==
-
-Valid values for pins are:
-pins can be referenced via the pin names as the below table shown and the
-related physical number is also put ahead of those names which helps cross
-references to pins between groups to know whether pins assignment conflict
-happens among devices try to acquire those available pins.
-
- Pin #: Valid values for pins
- -----------------------------
- PIN 0: "GPIO_A"
- PIN 1: "I2S1_IN"
- PIN 2: "I2S1_OUT"
- PIN 3: "I2S_BCLK"
- PIN 4: "I2S_WS"
- PIN 5: "I2S_MCLK"
- PIN 6: "TXD0"
- PIN 7: "RXD0"
- PIN 8: "SPI_WP"
- PIN 9: "SPI_HOLD"
- PIN 10: "SPI_CLK"
- PIN 11: "SPI_MOSI"
- PIN 12: "SPI_MISO"
- PIN 13: "SPI_CS"
- PIN 14: "I2C_SDA"
- PIN 15: "I2C_SCL"
- PIN 16: "I2S2_IN"
- PIN 17: "I2S3_IN"
- PIN 18: "I2S4_IN"
- PIN 19: "I2S2_OUT"
- PIN 20: "I2S3_OUT"
- PIN 21: "I2S4_OUT"
- PIN 22: "GPIO_B"
- PIN 23: "MDC"
- PIN 24: "MDIO"
- PIN 25: "G2_TXD0"
- PIN 26: "G2_TXD1"
- PIN 27: "G2_TXD2"
- PIN 28: "G2_TXD3"
- PIN 29: "G2_TXEN"
- PIN 30: "G2_TXC"
- PIN 31: "G2_RXD0"
- PIN 32: "G2_RXD1"
- PIN 33: "G2_RXD2"
- PIN 34: "G2_RXD3"
- PIN 35: "G2_RXDV"
- PIN 36: "G2_RXC"
- PIN 37: "NCEB"
- PIN 38: "NWEB"
- PIN 39: "NREB"
- PIN 40: "NDL4"
- PIN 41: "NDL5"
- PIN 42: "NDL6"
- PIN 43: "NDL7"
- PIN 44: "NRB"
- PIN 45: "NCLE"
- PIN 46: "NALE"
- PIN 47: "NDL0"
- PIN 48: "NDL1"
- PIN 49: "NDL2"
- PIN 50: "NDL3"
- PIN 51: "MDI_TP_P0"
- PIN 52: "MDI_TN_P0"
- PIN 53: "MDI_RP_P0"
- PIN 54: "MDI_RN_P0"
- PIN 55: "MDI_TP_P1"
- PIN 56: "MDI_TN_P1"
- PIN 57: "MDI_RP_P1"
- PIN 58: "MDI_RN_P1"
- PIN 59: "MDI_RP_P2"
- PIN 60: "MDI_RN_P2"
- PIN 61: "MDI_TP_P2"
- PIN 62: "MDI_TN_P2"
- PIN 63: "MDI_TP_P3"
- PIN 64: "MDI_TN_P3"
- PIN 65: "MDI_RP_P3"
- PIN 66: "MDI_RN_P3"
- PIN 67: "MDI_RP_P4"
- PIN 68: "MDI_RN_P4"
- PIN 69: "MDI_TP_P4"
- PIN 70: "MDI_TN_P4"
- PIN 71: "PMIC_SCL"
- PIN 72: "PMIC_SDA"
- PIN 73: "SPIC1_CLK"
- PIN 74: "SPIC1_MOSI"
- PIN 75: "SPIC1_MISO"
- PIN 76: "SPIC1_CS"
- PIN 77: "GPIO_D"
- PIN 78: "WATCHDOG"
- PIN 79: "RTS3_N"
- PIN 80: "CTS3_N"
- PIN 81: "TXD3"
- PIN 82: "RXD3"
- PIN 83: "PERST0_N"
- PIN 84: "PERST1_N"
- PIN 85: "WLED_N"
- PIN 86: "EPHY_LED0_N"
- PIN 87: "AUXIN0"
- PIN 88: "AUXIN1"
- PIN 89: "AUXIN2"
- PIN 90: "AUXIN3"
- PIN 91: "TXD4"
- PIN 92: "RXD4"
- PIN 93: "RTS4_N"
- PIN 94: "CST4_N"
- PIN 95: "PWM1"
- PIN 96: "PWM2"
- PIN 97: "PWM3"
- PIN 98: "PWM4"
- PIN 99: "PWM5"
- PIN 100: "PWM6"
- PIN 101: "PWM7"
- PIN 102: "GPIO_E"
-
-Valid values for function are:
- "emmc", "eth", "i2c", "i2s", "ir", "led", "flash", "pcie",
- "pmic", "pwm", "sd", "spi", "tdm", "uart", "watchdog"
-
-Valid values for groups are:
-additional data is put followingly with valid value allowing us to know which
-applicable function and which relevant pins (in pin#) are able applied for that
-group.
-
- Valid value function pins (in pin#)
- -------------------------------------------------------------------------
- "emmc" "emmc" 40, 41, 42, 43, 44, 45,
- 47, 48, 49, 50
- "emmc_rst" "emmc" 37
- "esw" "eth" 51, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62,
- 63, 64, 65, 66, 67, 68,
- 69, 70
- "esw_p0_p1" "eth" 51, 52, 53, 54, 55, 56,
- 57, 58
- "esw_p2_p3_p4" "eth" 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70
- "rgmii_via_esw" "eth" 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70
- "rgmii_via_gmac1" "eth" 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70
- "rgmii_via_gmac2" "eth" 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36
- "mdc_mdio" "eth" 23, 24
- "i2c0" "i2c" 14, 15
- "i2c1_0" "i2c" 55, 56
- "i2c1_1" "i2c" 73, 74
- "i2c1_2" "i2c" 87, 88
- "i2c2_0" "i2c" 57, 58
- "i2c2_1" "i2c" 75, 76
- "i2c2_2" "i2c" 89, 90
- "i2s_in_mclk_bclk_ws" "i2s" 3, 4, 5
- "i2s1_in_data" "i2s" 1
- "i2s2_in_data" "i2s" 16
- "i2s3_in_data" "i2s" 17
- "i2s4_in_data" "i2s" 18
- "i2s_out_mclk_bclk_ws" "i2s" 3, 4, 5
- "i2s1_out_data" "i2s" 2
- "i2s2_out_data" "i2s" 19
- "i2s3_out_data" "i2s" 20
- "i2s4_out_data" "i2s" 21
- "ir_0_tx" "ir" 16
- "ir_1_tx" "ir" 59
- "ir_2_tx" "ir" 99
- "ir_0_rx" "ir" 17
- "ir_1_rx" "ir" 60
- "ir_2_rx" "ir" 100
- "ephy_leds" "led" 86, 91, 92, 93, 94
- "ephy0_led" "led" 86
- "ephy1_led" "led" 91
- "ephy2_led" "led" 92
- "ephy3_led" "led" 93
- "ephy4_led" "led" 94
- "wled" "led" 85
- "par_nand" "flash" 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48,
- 49, 50
- "snfi" "flash" 8, 9, 10, 11, 12, 13
- "spi_nor" "flash" 8, 9, 10, 11, 12, 13
- "pcie0_0_waken" "pcie" 14
- "pcie0_1_waken" "pcie" 79
- "pcie1_0_waken" "pcie" 14
- "pcie0_0_clkreq" "pcie" 15
- "pcie0_1_clkreq" "pcie" 80
- "pcie1_0_clkreq" "pcie" 15
- "pcie0_pad_perst" "pcie" 83
- "pcie1_pad_perst" "pcie" 84
- "pmic_bus" "pmic" 71, 72
- "pwm_ch1_0" "pwm" 51
- "pwm_ch1_1" "pwm" 73
- "pwm_ch1_2" "pwm" 95
- "pwm_ch2_0" "pwm" 52
- "pwm_ch2_1" "pwm" 74
- "pwm_ch2_2" "pwm" 96
- "pwm_ch3_0" "pwm" 53
- "pwm_ch3_1" "pwm" 75
- "pwm_ch3_2" "pwm" 97
- "pwm_ch4_0" "pwm" 54
- "pwm_ch4_1" "pwm" 67
- "pwm_ch4_2" "pwm" 76
- "pwm_ch4_3" "pwm" 98
- "pwm_ch5_0" "pwm" 68
- "pwm_ch5_1" "pwm" 77
- "pwm_ch5_2" "pwm" 99
- "pwm_ch6_0" "pwm" 69
- "pwm_ch6_1" "pwm" 78
- "pwm_ch6_2" "pwm" 81
- "pwm_ch6_3" "pwm" 100
- "pwm_ch7_0" "pwm" 70
- "pwm_ch7_1" "pwm" 82
- "pwm_ch7_2" "pwm" 101
- "sd_0" "sd" 16, 17, 18, 19, 20, 21
- "sd_1" "sd" 25, 26, 27, 28, 29, 30
- "spic0_0" "spi" 63, 64, 65, 66
- "spic0_1" "spi" 79, 80, 81, 82
- "spic1_0" "spi" 67, 68, 69, 70
- "spic1_1" "spi" 73, 74, 75, 76
- "spic2_0_wp_hold" "spi" 8, 9
- "spic2_0" "spi" 10, 11, 12, 13
- "tdm_0_out_mclk_bclk_ws" "tdm" 8, 9, 10
- "tdm_0_in_mclk_bclk_ws" "tdm" 11, 12, 13
- "tdm_0_out_data" "tdm" 20
- "tdm_0_in_data" "tdm" 21
- "tdm_1_out_mclk_bclk_ws" "tdm" 57, 58, 59
- "tdm_1_in_mclk_bclk_ws" "tdm" 60, 61, 62
- "tdm_1_out_data" "tdm" 55
- "tdm_1_in_data" "tdm" 56
- "uart0_0_tx_rx" "uart" 6, 7
- "uart1_0_tx_rx" "uart" 55, 56
- "uart1_0_rts_cts" "uart" 57, 58
- "uart1_1_tx_rx" "uart" 73, 74
- "uart1_1_rts_cts" "uart" 75, 76
- "uart2_0_tx_rx" "uart" 3, 4
- "uart2_0_rts_cts" "uart" 1, 2
- "uart2_1_tx_rx" "uart" 51, 52
- "uart2_1_rts_cts" "uart" 53, 54
- "uart2_2_tx_rx" "uart" 59, 60
- "uart2_2_rts_cts" "uart" 61, 62
- "uart2_3_tx_rx" "uart" 95, 96
- "uart3_0_tx_rx" "uart" 57, 58
- "uart3_1_tx_rx" "uart" 81, 82
- "uart3_1_rts_cts" "uart" 79, 80
- "uart4_0_tx_rx" "uart" 61, 62
- "uart4_1_tx_rx" "uart" 91, 92
- "uart4_1_rts_cts" "uart" 93, 94
- "uart4_2_tx_rx" "uart" 97, 98
- "uart4_2_rts_cts" "uart" 95, 96
- "watchdog" "watchdog" 78
-
-
-== Valid values for pins, function and groups on MT7629 ==
-
- Pin #: Valid values for pins
- -----------------------------
- PIN 0: "TOP_5G_CLK"
- PIN 1: "TOP_5G_DATA"
- PIN 2: "WF0_5G_HB0"
- PIN 3: "WF0_5G_HB1"
- PIN 4: "WF0_5G_HB2"
- PIN 5: "WF0_5G_HB3"
- PIN 6: "WF0_5G_HB4"
- PIN 7: "WF0_5G_HB5"
- PIN 8: "WF0_5G_HB6"
- PIN 9: "XO_REQ"
- PIN 10: "TOP_RST_N"
- PIN 11: "SYS_WATCHDOG"
- PIN 12: "EPHY_LED0_N_JTDO"
- PIN 13: "EPHY_LED1_N_JTDI"
- PIN 14: "EPHY_LED2_N_JTMS"
- PIN 15: "EPHY_LED3_N_JTCLK"
- PIN 16: "EPHY_LED4_N_JTRST_N"
- PIN 17: "WF2G_LED_N"
- PIN 18: "WF5G_LED_N"
- PIN 19: "I2C_SDA"
- PIN 20: "I2C_SCL"
- PIN 21: "GPIO_9"
- PIN 22: "GPIO_10"
- PIN 23: "GPIO_11"
- PIN 24: "GPIO_12"
- PIN 25: "UART1_TXD"
- PIN 26: "UART1_RXD"
- PIN 27: "UART1_CTS"
- PIN 28: "UART1_RTS"
- PIN 29: "UART2_TXD"
- PIN 30: "UART2_RXD"
- PIN 31: "UART2_CTS"
- PIN 32: "UART2_RTS"
- PIN 33: "MDI_TP_P1"
- PIN 34: "MDI_TN_P1"
- PIN 35: "MDI_RP_P1"
- PIN 36: "MDI_RN_P1"
- PIN 37: "MDI_RP_P2"
- PIN 38: "MDI_RN_P2"
- PIN 39: "MDI_TP_P2"
- PIN 40: "MDI_TN_P2"
- PIN 41: "MDI_TP_P3"
- PIN 42: "MDI_TN_P3"
- PIN 43: "MDI_RP_P3"
- PIN 44: "MDI_RN_P3"
- PIN 45: "MDI_RP_P4"
- PIN 46: "MDI_RN_P4"
- PIN 47: "MDI_TP_P4"
- PIN 48: "MDI_TN_P4"
- PIN 49: "SMI_MDC"
- PIN 50: "SMI_MDIO"
- PIN 51: "PCIE_PERESET_N"
- PIN 52: "PWM_0"
- PIN 53: "GPIO_0"
- PIN 54: "GPIO_1"
- PIN 55: "GPIO_2"
- PIN 56: "GPIO_3"
- PIN 57: "GPIO_4"
- PIN 58: "GPIO_5"
- PIN 59: "GPIO_6"
- PIN 60: "GPIO_7"
- PIN 61: "GPIO_8"
- PIN 62: "SPI_CLK"
- PIN 63: "SPI_CS"
- PIN 64: "SPI_MOSI"
- PIN 65: "SPI_MISO"
- PIN 66: "SPI_WP"
- PIN 67: "SPI_HOLD"
- PIN 68: "UART0_TXD"
- PIN 69: "UART0_RXD"
- PIN 70: "TOP_2G_CLK"
- PIN 71: "TOP_2G_DATA"
- PIN 72: "WF0_2G_HB0"
- PIN 73: "WF0_2G_HB1"
- PIN 74: "WF0_2G_HB2"
- PIN 75: "WF0_2G_HB3"
- PIN 76: "WF0_2G_HB4"
- PIN 77: "WF0_2G_HB5"
- PIN 78: "WF0_2G_HB6"
-
-Valid values for function are:
- "eth", "i2c", "led", "flash", "pcie", "pwm", "spi", "uart",
- "watchdog", "wifi"
-
-Valid values for groups are:
- Valid value function pins (in pin#)
- ----------------------------------------------------------------
- "mdc_mdio" "eth" 23, 24
- "i2c_0" "i2c" 19, 20
- "i2c_1" "i2c" 53, 54
- "ephy_leds" "led" 12, 13, 14, 15, 16,
- 17, 18
- "ephy0_led" "led" 12
- "ephy1_led" "led" 13
- "ephy2_led" "led" 14
- "ephy3_led" "led" 15
- "ephy4_led" "led" 16
- "wf2g_led" "led" 17
- "wf5g_led" "led" 18
- "snfi" "flash" 62, 63, 64, 65, 66, 67
- "spi_nor" "flash" 62, 63, 64, 65, 66, 67
- "pcie_pereset" "pcie" 51
- "pcie_wake" "pcie" 55
- "pcie_clkreq" "pcie" 56
- "pwm_0" "pwm" 52
- "pwm_1" "pwm" 61
- "spi_0" "spi" 21, 22, 23, 24
- "spi_1" "spi" 62, 63, 64, 65
- "spi_wp" "spi" 66
- "spi_hold" "spi" 67
- "uart0_txd_rxd" "uart" 68, 69
- "uart1_0_txd_rxd" "uart" 25, 26
- "uart1_0_cts_rts" "uart" 27, 28
- "uart1_1_txd_rxd" "uart" 53, 54
- "uart1_1_cts_rts" "uart" 55, 56
- "uart2_0_txd_rxd" "uart" 29, 30
- "uart2_0_cts_rts" "uart" 31, 32
- "uart2_1_txd_rxd" "uart" 57, 58
- "uart2_1_cts_rts" "uart" 59, 60
- "watchdog" "watchdog" 11
- "wf0_2g" "wifi" 70, 71, 72, 73, 74,
- 75, 76, 77, 78
- "wf0_5g" "wifi" 0, 1, 2, 3, 4, 5, 6,
- 7, 8, 9, 10
-
-Example:
-
- pio: pinctrl@10211000 {
- compatible = "mediatek,mt7622-pinctrl";
- reg = <0 0x10211000 0 0x1000>;
- gpio-controller;
- #gpio-cells = <2>;
-
- pinctrl_eth_default: eth-default {
- mux-mdio {
- groups = "mdc_mdio";
- function = "eth";
- drive-strength = <12>;
- };
-
- mux-gmac2 {
- groups = "gmac2";
- function = "eth";
- drive-strength = <12>;
- };
-
- mux-esw {
- groups = "esw";
- function = "eth";
- drive-strength = <8>;
- };
-
- conf-mdio {
- pins = "MDC";
- bias-pull-up;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8183.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8183.txt
deleted file mode 100644
index eccbe3f55d3f..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8183.txt
+++ /dev/null
@@ -1,132 +0,0 @@
-* Mediatek MT8183 Pin Controller
-
-The Mediatek's Pin controller is used to control SoC pins.
-
-Required properties:
-- compatible: value should be one of the following.
- "mediatek,mt8183-pinctrl", compatible with mt8183 pinctrl.
-- gpio-controller : Marks the device node as a gpio controller.
-- #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
- binding is used, the amount of cells must be specified as 2. See the below
- mentioned gpio binding representation for description of particular cells.
-- gpio-ranges : gpio valid number range.
-- reg: physical address base for gpio base registers. There are 10 GPIO
- physical address base in mt8183.
-
-Optional properties:
-- reg-names: gpio base register names. There are 10 gpio base register
- names in mt8183. They are "iocfg0", "iocfg1", "iocfg2", "iocfg3", "iocfg4",
- "iocfg5", "iocfg6", "iocfg7", "iocfg8", "eint".
-- interrupt-controller: Marks the device node as an interrupt controller
-- #interrupt-cells: Should be two.
-- interrupts : The interrupt outputs to sysirq.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices.
-
-Subnode format
-A pinctrl node should contain at least one subnodes representing the
-pinctrl groups available on the machine. Each subnode will list the
-pins it needs, and how they should be configured, with regard to muxer
-configuration, pullups, drive strength, input enable/disable and input schmitt.
-
- node {
- pinmux = <PIN_NUMBER_PINMUX>;
- GENERIC_PINCONFIG;
- };
-
-Required properties:
-- pinmux: integer array, represents gpio pin number and mux setting.
- Supported pin number and mux varies for different SoCs, and are defined
- as macros in boot/dts/<soc>-pinfunc.h directly.
-
-Optional properties:
-- GENERIC_PINCONFIG: is the generic pinconfig options to use, bias-disable,
- bias-pull-down, bias-pull-up, input-enable, input-disable, output-low,
- output-high, input-schmitt-enable, input-schmitt-disable
- and drive-strength are valid.
-
- Some special pins have extra pull up strength, there are R0 and R1 pull-up
- resistors available, but for user, it's only need to set R1R0 as 00, 01,
- 10 or 11. So It needs config "mediatek,pull-up-adv" or
- "mediatek,pull-down-adv" to support arguments for those special pins.
- Valid arguments are from 0 to 3.
-
- mediatek,tdsel: An integer describing the steps for output level shifter
- duty cycle when asserted (high pulse width adjustment). Valid arguments
- are from 0 to 15.
- mediatek,rdsel: An integer describing the steps for input level shifter
- duty cycle when asserted (high pulse width adjustment). Valid arguments
- are from 0 to 63.
-
- When config drive-strength, it can support some arguments, such as
- MTK_DRIVE_4mA, MTK_DRIVE_6mA, etc. See dt-bindings/pinctrl/mt65xx.h.
- It can only support 2/4/6/8/10/12/14/16mA in mt8183.
- For I2C pins, there are existing generic driving setup and the specific
- driving setup. I2C pins can only support 2/4/6/8/10/12/14/16mA driving
- adjustment in generic driving setup. But in specific driving setup,
- they can support 0.125/0.25/0.5/1mA adjustment. If we enable specific
- driving setup for I2C pins, the existing generic driving setup will be
- disabled. For some special features, we need the I2C pins specific
- driving setup. The specific driving setup is controlled by E1E0EN.
- So we need add extra vendor driving preperty instead of
- the generic driving property.
- We can add "mediatek,drive-strength-adv = <XXX>;" to describe the specific
- driving setup property. "XXX" means the value of E1E0EN. EN is 0 or 1.
- It is used to enable or disable the specific driving setup.
- E1E0 is used to describe the detail strength specification of the I2C pin.
- When E1=0/E0=0, the strength is 0.125mA.
- When E1=0/E0=1, the strength is 0.25mA.
- When E1=1/E0=0, the strength is 0.5mA.
- When E1=1/E0=1, the strength is 1mA.
- So the valid arguments of "mediatek,drive-strength-adv" are from 0 to 7.
-
-Examples:
-
-#include "mt8183-pinfunc.h"
-
-...
-{
- pio: pinctrl@10005000 {
- compatible = "mediatek,mt8183-pinctrl";
- reg = <0 0x10005000 0 0x1000>,
- <0 0x11f20000 0 0x1000>,
- <0 0x11e80000 0 0x1000>,
- <0 0x11e70000 0 0x1000>,
- <0 0x11e90000 0 0x1000>,
- <0 0x11d30000 0 0x1000>,
- <0 0x11d20000 0 0x1000>,
- <0 0x11c50000 0 0x1000>,
- <0 0x11f30000 0 0x1000>,
- <0 0x1000b000 0 0x1000>;
- reg-names = "iocfg0", "iocfg1", "iocfg2",
- "iocfg3", "iocfg4", "iocfg5",
- "iocfg6", "iocfg7", "iocfg8",
- "eint";
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pio 0 0 192>;
- interrupt-controller;
- interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
- #interrupt-cells = <2>;
-
- i2c0_pins_a: i2c0 {
- pins1 {
- pinmux = <PINMUX_GPIO48__FUNC_SCL5>,
- <PINMUX_GPIO49__FUNC_SDA5>;
- mediatek,pull-up-adv = <3>;
- mediatek,drive-strength-adv = <7>;
- };
- };
-
- i2c1_pins_a: i2c1 {
- pins {
- pinmux = <PINMUX_GPIO50__FUNC_SCL3>,
- <PINMUX_GPIO51__FUNC_SDA3>;
- mediatek,pull-down-adv = <2>;
- mediatek,drive-strength-adv = <4>;
- };
- };
- ...
- };
-};
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml
index 2f12ec59eee5..e17a399e0904 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml
@@ -80,10 +80,7 @@ patternProperties:
as macros in dt-bindings/pinctrl/<soc>-pinfunc.h directly.
drive-strength:
- description: |
- It can support some arguments which is from 0 to 7. It can only support
- 2/4/6/8/10/12/14/16mA in mt8195.
- enum: [0, 1, 2, 3, 4, 5, 6, 7]
+ enum: [2, 4, 6, 8, 10, 12, 14, 16]
bias-pull-down: true
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.yaml
new file mode 100644
index 000000000000..3b02dc6626ed
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.yaml
@@ -0,0 +1,133 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,mdm9607-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. MDM9607 TLMM block
+
+maintainers:
+ - Konrad Dybcio <konrad.dybcio@somainline.org>
+
+description: |
+ This binding describes the Top Level Mode Multiplexer block found in the
+ MDM9607 platform.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,mdm9607-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ '#interrupt-cells': true
+ gpio-controller: true
+ gpio-reserved-ranges: true
+ '#gpio-cells': true
+ gpio-ranges: true
+ wakeup-parent: true
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+patternProperties:
+ '-state$':
+ oneOf:
+ - $ref: "#/$defs/qcom-mdm9607-tlmm-state"
+ - patternProperties:
+ ".*":
+ $ref: "#/$defs/qcom-mdm9607-tlmm-state"
+
+'$defs':
+ qcom-mdm9607-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([1-9]|[1-7][0-9]|80)$"
+ - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd,
+ sdc2_data, qdsd_cmd, qdsd_data0, qdsd_data1, qdsd_data2,
+ qdsd_data3 ]
+ minItems: 1
+ maxItems: 16
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ adsp_ext, atest_bbrx0, atest_bbrx1, atest_char, atest_char0,
+ atest_char1, atest_char2, atest_char3,
+ atest_combodac_to_gpio_native, atest_gpsadc_dtest0_native,
+ atest_gpsadc_dtest1_native, atest_tsens, backlight_en_b,
+ bimc_dte0, bimc_dte1, blsp1_spi, blsp2_spi, blsp3_spi,
+ blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5,
+ blsp_i2c6, blsp_spi1, blsp_spi2, blsp_spi3, blsp_spi4,
+ blsp_spi5, blsp_spi6, blsp_uart1, blsp_uart2, blsp_uart3,
+ blsp_uart4, blsp_uart5, blsp_uart6, blsp_uim1, blsp_uim2,
+ codec_int, codec_rst, coex_uart, cri_trng, cri_trng0,
+ cri_trng1, dbg_out, ebi0_wrcdc, ebi2_a, ebi2_a_d_8_b,
+ ebi2_lcd, ebi2_lcd_cs_n_b, ebi2_lcd_te_b, eth_irq, eth_rst,
+ gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, gcc_gp2_clk_b,
+ gcc_gp3_clk_a, gcc_gp3_clk_b, gcc_plltest, gcc_tlmm, gmac_mdio,
+ gpio, gsm0_tx, lcd_rst, ldo_en, ldo_update, m_voc, modem_tsync,
+ nav_ptp_pps_in_a, nav_ptp_pps_in_b, nav_tsync_out_a,
+ nav_tsync_out_b, pa_indicator, pbs0, pbs1, pbs2,
+ pri_mi2s_data0_a, pri_mi2s_data1_a, pri_mi2s_mclk_a,
+ pri_mi2s_sck_a, pri_mi2s_ws_a, prng_rosc, ptp_pps_out_a,
+ ptp_pps_out_b, pwr_crypto_enabled_a, pwr_crypto_enabled_b,
+ pwr_modem_enabled_a, pwr_modem_enabled_b, pwr_nav_enabled_a,
+ pwr_nav_enabled_b, qdss_cti_trig_in_a0, qdss_cti_trig_in_a1,
+ qdss_cti_trig_in_b0, qdss_cti_trig_in_b1, qdss_cti_trig_out_a0,
+ qdss_cti_trig_out_a1, qdss_cti_trig_out_b0, qdss_cti_trig_out_b1,
+ qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a,
+ qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b, rcm_marker1,
+ rcm_marker2, sd_write, sec_mi2s, sensor_en, sensor_int2,
+ sensor_int3, sensor_rst, ssbi1, ssbi2, touch_rst, ts_int,
+ uim1_clk, uim1_data, uim1_present, uim1_reset, uim2_clk,
+ uim2_data, uim2_present, uim2_reset, uim_batt, wlan_en1, ]
+
+ bias-disable: true
+ bias-pull-down: true
+ bias-pull-up: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+ - function
+
+ additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,mdm9607-tlmm";
+ reg = <0x01000000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&msmgpio 0 0 80>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
deleted file mode 100644
index 161216daf463..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
+++ /dev/null
@@ -1,288 +0,0 @@
-Qualcomm PMIC GPIO block
-
-This binding describes the GPIO block(s) found in the 8xxx series of
-PMIC's from Qualcomm.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be one of:
- "qcom,pm8005-gpio"
- "qcom,pm8018-gpio"
- "qcom,pm8038-gpio"
- "qcom,pm8058-gpio"
- "qcom,pm8916-gpio"
- "qcom,pm8917-gpio"
- "qcom,pm8921-gpio"
- "qcom,pm8941-gpio"
- "qcom,pm8950-gpio"
- "qcom,pm8994-gpio"
- "qcom,pm8998-gpio"
- "qcom,pma8084-gpio"
- "qcom,pmi8950-gpio"
- "qcom,pmi8994-gpio"
- "qcom,pmi8998-gpio"
- "qcom,pms405-gpio"
- "qcom,pm660-gpio"
- "qcom,pm660l-gpio"
- "qcom,pm8150-gpio"
- "qcom,pm8150b-gpio"
- "qcom,pm8350-gpio"
- "qcom,pm8350b-gpio"
- "qcom,pm8350c-gpio"
- "qcom,pmk8350-gpio"
- "qcom,pm7325-gpio"
- "qcom,pmr735a-gpio"
- "qcom,pmr735b-gpio"
- "qcom,pm6150-gpio"
- "qcom,pm6150l-gpio"
- "qcom,pm8008-gpio"
- "qcom,pmx55-gpio"
-
- And must contain either "qcom,spmi-gpio" or "qcom,ssbi-gpio"
- if the device is on an spmi bus or an ssbi bus respectively
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: Register base of the GPIO block and length.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: Must contain an array of encoded interrupt specifiers for
- each available GPIO
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: Mark the device node as a GPIO controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: Must be 2;
- the first cell will be used to define gpio number and the
- second denotes the flags for this gpio
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin or a list of pins. This configuration can include the
-mux function to select on those pin(s), and various pin configuration
-parameters, as listed below.
-
-
-SUBNODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode. Valid pins are:
- gpio1-gpio4 for pm8005
- gpio1-gpio6 for pm8018
- gpio1-gpio12 for pm8038
- gpio1-gpio40 for pm8058
- gpio1-gpio4 for pm8916
- gpio1-gpio38 for pm8917
- gpio1-gpio44 for pm8921
- gpio1-gpio36 for pm8941
- gpio1-gpio8 for pm8950 (hole on gpio3)
- gpio1-gpio22 for pm8994
- gpio1-gpio26 for pm8998
- gpio1-gpio22 for pma8084
- gpio1-gpio2 for pmi8950
- gpio1-gpio10 for pmi8994
- gpio1-gpio12 for pms405 (holes on gpio1, gpio9 and gpio10)
- gpio1-gpio10 for pm8150 (holes on gpio2, gpio5, gpio7
- and gpio8)
- gpio1-gpio12 for pm8150b (holes on gpio3, gpio4, gpio7)
- gpio1-gpio12 for pm8150l (hole on gpio7)
- gpio1-gpio10 for pm8350
- gpio1-gpio8 for pm8350b
- gpio1-gpio9 for pm8350c
- gpio1-gpio4 for pmk8350
- gpio1-gpio10 for pm7325
- gpio1-gpio4 for pmr735a
- gpio1-gpio4 for pmr735b
- gpio1-gpio10 for pm6150
- gpio1-gpio12 for pm6150l
- gpio1-gpio2 for pm8008
- gpio1-gpio11 for pmx55 (holes on gpio3, gpio7, gpio10
- and gpio11)
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Valid values are:
- "normal",
- "paired",
- "func1",
- "func2",
- "dtest1",
- "dtest2",
- "dtest3",
- "dtest4",
- And following values are supported by LV/MV GPIO subtypes:
- "func3",
- "func4"
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <empty>
- Definition: The specified pins should be configured as pull up.
-
-- qcom,pull-up-strength:
- Usage: optional
- Value type: <u32>
- Definition: Specifies the strength to use for pull up, if selected.
- Valid values are; as defined in
- <dt-bindings/pinctrl/qcom,pmic-gpio.h>:
- 1: 30uA (PMIC_GPIO_PULL_UP_30)
- 2: 1.5uA (PMIC_GPIO_PULL_UP_1P5)
- 3: 31.5uA (PMIC_GPIO_PULL_UP_31P5)
- 4: 1.5uA + 30uA boost (PMIC_GPIO_PULL_UP_1P5_30)
- If this property is omitted 30uA strength will be used if
- pull up is selected
-
-- bias-high-impedance:
- Usage: optional
- Value type: <none>
- Definition: The specified pins will put in high-Z mode and disabled.
-
-- input-enable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are put in input mode.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
-
-- power-source:
- Usage: optional
- Value type: <u32>
- Definition: Selects the power source for the specified pins. Valid
- power sources are defined per chip in
- <dt-bindings/pinctrl/qcom,pmic-gpio.h>
-
-- qcom,drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins. Value
- drive strengths are:
- 0: no (PMIC_GPIO_STRENGTH_NO)
- 1: high (PMIC_GPIO_STRENGTH_HIGH) 0.9mA @ 1.8V - 1.9mA @ 2.6V
- 2: medium (PMIC_GPIO_STRENGTH_MED) 0.6mA @ 1.8V - 1.25mA @ 2.6V
- 3: low (PMIC_GPIO_STRENGTH_LOW) 0.15mA @ 1.8V - 0.3mA @ 2.6V
- as defined in <dt-bindings/pinctrl/qcom,pmic-gpio.h>
-
-- drive-push-pull:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in push-pull mode.
-
-- drive-open-drain:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in open-drain mode.
-
-- drive-open-source:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in open-source mode.
-
-- qcom,analog-pass:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in analog-pass-through mode.
-
-- qcom,atest:
- Usage: optional
- Value type: <u32>
- Definition: Selects ATEST rail to route to GPIO when it's configured
- in analog-pass-through mode.
- Valid values are 1-4 corresponding to ATEST1 to ATEST4.
-
-- qcom,dtest-buffer:
- Usage: optional
- Value type: <u32>
- Definition: Selects DTEST rail to route to GPIO when it's configured
- as digital input.
- Valid values are 1-4 corresponding to DTEST1 to DTEST4.
-
-Example:
-
- pm8921_gpio: gpio@150 {
- compatible = "qcom,pm8921-gpio", "qcom,ssbi-gpio";
- reg = <0x150 0x160>;
- interrupts = <192 1>, <193 1>, <194 1>,
- <195 1>, <196 1>, <197 1>,
- <198 1>, <199 1>, <200 1>,
- <201 1>, <202 1>, <203 1>,
- <204 1>, <205 1>, <206 1>,
- <207 1>, <208 1>, <209 1>,
- <210 1>, <211 1>, <212 1>,
- <213 1>, <214 1>, <215 1>,
- <216 1>, <217 1>, <218 1>,
- <219 1>, <220 1>, <221 1>,
- <222 1>, <223 1>, <224 1>,
- <225 1>, <226 1>, <227 1>,
- <228 1>, <229 1>, <230 1>,
- <231 1>, <232 1>, <233 1>,
- <234 1>, <235 1>;
-
- gpio-controller;
- #gpio-cells = <2>;
-
- pm8921_gpio_keys: gpio-keys {
- volume-keys {
- pins = "gpio20", "gpio21";
- function = "normal";
-
- input-enable;
- bias-pull-up;
- drive-push-pull;
- qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
- power-source = <PM8921_GPIO_S4>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml
new file mode 100644
index 000000000000..9bd01db37dcd
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml
@@ -0,0 +1,239 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,pmic-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm PMIC GPIO block
+
+maintainers:
+ - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description:
+ This binding describes the GPIO block(s) found in the 8xxx series of
+ PMIC's from Qualcomm.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - qcom,pm660-gpio
+ - qcom,pm660l-gpio
+ - qcom,pm6150-gpio
+ - qcom,pm6150l-gpio
+ - qcom,pm7325-gpio
+ - qcom,pm8005-gpio
+ - qcom,pm8008-gpio
+ - qcom,pm8018-gpio
+ - qcom,pm8038-gpio
+ - qcom,pm8058-gpio
+ - qcom,pm8150-gpio
+ - qcom,pm8150b-gpio
+ - qcom,pm8350-gpio
+ - qcom,pm8350b-gpio
+ - qcom,pm8350c-gpio
+ - qcom,pm8916-gpio
+ - qcom,pm8917-gpio
+ - qcom,pm8921-gpio
+ - qcom,pm8941-gpio
+ - qcom,pm8950-gpio
+ - qcom,pm8994-gpio
+ - qcom,pm8998-gpio
+ - qcom,pma8084-gpio
+ - qcom,pmi8950-gpio
+ - qcom,pmi8994-gpio
+ - qcom,pmi8998-gpio
+ - qcom,pmk8350-gpio
+ - qcom,pmr735a-gpio
+ - qcom,pmr735b-gpio
+ - qcom,pms405-gpio
+ - qcom,pmx55-gpio
+
+ - enum:
+ - qcom,spmi-gpio
+ - qcom,ssbi-gpio
+
+ reg:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+ gpio-controller: true
+
+ gpio-ranges:
+ maxItems: 1
+
+ '#gpio-cells':
+ const: 2
+ description:
+ The first cell will be used to define gpio number and the
+ second denotes the flags for this gpio
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - '#gpio-cells'
+ - gpio-ranges
+ - interrupt-controller
+
+patternProperties:
+ '-state$':
+ oneOf:
+ - $ref: "#/$defs/qcom-pmic-gpio-state"
+ - patternProperties:
+ ".*":
+ $ref: "#/$defs/qcom-pmic-gpio-state"
+
+$defs:
+ qcom-pmic-gpio-state:
+ type: object
+ allOf:
+ - $ref: "pinmux-node.yaml"
+ - $ref: "pincfg-node.yaml"
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in
+ this subnode. Valid pins are
+ - gpio1-gpio10 for pm6150
+ - gpio1-gpio12 for pm6150l
+ - gpio1-gpio10 for pm7325
+ - gpio1-gpio4 for pm8005
+ - gpio1-gpio2 for pm8008
+ - gpio1-gpio6 for pm8018
+ - gpio1-gpio12 for pm8038
+ - gpio1-gpio40 for pm8058
+ - gpio1-gpio10 for pm8150 (holes on gpio2, gpio5,
+ gpio7 and gpio8)
+ - gpio1-gpio12 for pm8150b (holes on gpio3, gpio4
+ and gpio7)
+ - gpio1-gpio12 for pm8150l (hole on gpio7)
+ - gpio1-gpio4 for pm8916
+ - gpio1-gpio10 for pm8350
+ - gpio1-gpio8 for pm8350b
+ - gpio1-gpio9 for pm8350c
+ - gpio1-gpio38 for pm8917
+ - gpio1-gpio44 for pm8921
+ - gpio1-gpio36 for pm8941
+ - gpio1-gpio8 for pm8950 (hole on gpio3)
+ - gpio1-gpio22 for pm8994
+ - gpio1-gpio26 for pm8998
+ - gpio1-gpio22 for pma8084
+ - gpio1-gpio2 for pmi8950
+ - gpio1-gpio10 for pmi8994
+ - gpio1-gpio4 for pmk8350
+ - gpio1-gpio4 for pmr735a
+ - gpio1-gpio4 for pmr735b
+ - gpio1-gpio12 for pms405 (holes on gpio1, gpio9
+ and gpio10)
+ - gpio1-gpio11 for pmx55 (holes on gpio3, gpio7, gpio10
+ and gpio11)
+
+ items:
+ pattern: "^gpio([0-9]+)$"
+
+ function:
+ items:
+ - enum:
+ - normal
+ - paired
+ - func1
+ - func2
+ - dtest1
+ - dtest2
+ - dtest3
+ - dtest4
+ - func3 # supported by LV/MV GPIO subtypes
+ - func4 # supported by LV/MV GPIO subtypes
+
+ bias-disable: true
+ bias-pull-down: true
+ bias-pull-up: true
+
+ qcom,pull-up-strength:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Specifies the strength to use for pull up, if selected.
+ Valid values are defined in
+ <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+ If this property is omitted 30uA strength will be used
+ if pull up is selected
+ enum: [0, 1, 2, 3]
+
+ bias-high-impedance: true
+ input-enable: true
+ output-high: true
+ output-low: true
+ power-source: true
+
+ qcom,drive-strength:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Selects the drive strength for the specified pins
+ Valid drive strength values are defined in
+ <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+ enum: [0, 1, 2, 3]
+
+ drive-push-pull: true
+ drive-open-drain: true
+ drive-open-source: true
+
+ qcom,analog-pass:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ The specified pins are configured in
+ analog-pass-through mode.
+
+ qcom,atest:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Selects ATEST rail to route to GPIO when it's
+ configured in analog-pass-through mode.
+ enum: [1, 2, 3, 4]
+
+ qcom,dtest-buffer:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Selects DTEST rail to route to GPIO when it's
+ configured as digital input.
+ enum: [1, 2, 3, 4]
+
+ required:
+ - pins
+ - function
+
+ additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+
+ pm8921_gpio: gpio@150 {
+ compatible = "qcom,pm8921-gpio", "qcom,ssbi-gpio";
+ reg = <0x150 0x160>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&pm8921_gpio 0 0 44>;
+ #gpio-cells = <2>;
+
+ pm8921_gpio_keys: gpio-keys-state {
+ volume-keys {
+ pins = "gpio20", "gpio21";
+ function = "normal";
+
+ input-enable;
+ bias-pull-up;
+ drive-push-pull;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8921_GPIO_S4>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml
new file mode 100644
index 000000000000..8fc06f6a3ef4
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml
@@ -0,0 +1,179 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,sm6115-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. SM6115, SM4250 TLMM block
+
+maintainers:
+ - Iskren Chernev <iskren.chernev@gmail.com>
+
+description:
+ This binding describes the Top Level Mode Multiplexer block found in the
+ SM4250/6115 platforms.
+
+properties:
+ compatible:
+ const: qcom,sm6115-tlmm
+
+ reg:
+ minItems: 3
+ maxItems: 3
+
+ reg-names:
+ items:
+ - const: west
+ - const: south
+ - const: east
+
+ interrupts:
+ description: Specifies the TLMM summary IRQ
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ description:
+ Specifies the PIN numbers and Flags, as defined in defined in
+ include/dt-bindings/interrupt-controller/irq.h
+ const: 2
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ description: Specifying the pin number and flags, as defined in
+ include/dt-bindings/gpio/gpio.h
+ const: 2
+
+ gpio-ranges:
+ maxItems: 1
+
+ wakeup-parent:
+ maxItems: 1
+
+#PIN CONFIGURATION NODES
+patternProperties:
+ '-state$':
+ oneOf:
+ - $ref: "#/$defs/qcom-sm6115-tlmm-state"
+ - patternProperties:
+ ".*":
+ $ref: "#/$defs/qcom-sm6115-tlmm-state"
+
+'$defs':
+ qcom-sm6115-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|10[0-9]|11[0-2])$"
+ - enum: [ sdc1_rclk, sdc1_clk, sdc1_cmd, sdc1_data,
+ sdc2_clk, sdc2_cmd, sdc2_data, ufs_reset ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ adsp_ext, agera_pll, atest, cam_mclk, cci_async, cci_i2c,
+ cci_timer, cri_trng, dac_calib, dbg_out, ddr_bist, ddr_pxi0,
+ ddr_pxi1, ddr_pxi2, ddr_pxi3, gcc_gp1, gcc_gp2, gcc_gp3, gpio,
+ gp_pdm0, gp_pdm1, gp_pdm2, gsm0_tx, gsm1_tx, jitter_bist,
+ mdp_vsync, mdp_vsync_out_0, mdp_vsync_out_1, mpm_pwr, mss_lte,
+ m_voc, nav_gpio, pa_indicator, pbs, pbs_out, phase_flag,
+ pll_bist, pll_bypassnl, pll_reset, prng_rosc, qdss_cti,
+ qdss_gpio, qup0, qup1, qup2, qup3, qup4, qup5, sdc1_tb,
+ sdc2_tb, sd_write, ssbi_wtr1, tgu, tsense_pwm, uim1_clk,
+ uim1_data, uim1_present, uim1_reset, uim2_clk, uim2_data,
+ uim2_present, uim2_reset, usb_phy, vfr_1, vsense_trigger,
+ wlan1_adc0, elan1_adc1 ]
+
+ drive-strength:
+ enum: [2, 4, 6, 8, 10, 12, 14, 16]
+ default: 2
+ description:
+ Selects the drive strength for the specified pins, in mA.
+
+ bias-pull-down: true
+
+ bias-pull-up: true
+
+ bias-disable: true
+
+ output-high: true
+
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - interrupt-controller
+ - '#interrupt-cells'
+ - gpio-controller
+ - '#gpio-cells'
+ - gpio-ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@500000 {
+ compatible = "qcom,sm6115-tlmm";
+ reg = <0x500000 0x400000>,
+ <0x900000 0x400000>,
+ <0xd00000 0x400000>;
+ reg-names = "west", "south", "east";
+ interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 114>;
+
+ sdc2_on_state: sdc2-on-state {
+ clk {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ sd-cd {
+ pins = "gpio88";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
new file mode 100644
index 000000000000..ef68dabcf4dc
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
@@ -0,0 +1,155 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/renesas,rzg2l-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L combined Pin and GPIO controller
+
+maintainers:
+ - Geert Uytterhoeven <geert+renesas@glider.be>
+ - Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+description:
+ The Renesas SoCs of the RZ/G2L series feature a combined Pin and GPIO
+ controller.
+ Pin multiplexing and GPIO configuration is performed on a per-pin basis.
+ Each port features up to 8 pins, each of them configurable for GPIO function
+ (port mode) or in alternate function mode.
+ Up to 8 different alternate function modes exist for each single pin.
+
+properties:
+ compatible:
+ enum:
+ - renesas,r9a07g044-pinctrl # RZ/G2{L,LC}
+
+ reg:
+ maxItems: 1
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+ description:
+ The first cell contains the global GPIO port index, constructed using the
+ RZG2L_GPIO() helper macro in <dt-bindings/pinctrl/rzg2l-pinctrl.h> and the
+ second cell represents consumer flag as mentioned in ../gpio/gpio.txt
+ E.g. "RZG2L_GPIO(39, 1)" for P39_1.
+
+ gpio-ranges:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ items:
+ - description: GPIO_RSTN signal
+ - description: GPIO_PORT_RESETN signal
+ - description: GPIO_SPARE_RESETN signal
+
+additionalProperties:
+ anyOf:
+ - type: object
+ allOf:
+ - $ref: pincfg-node.yaml#
+ - $ref: pinmux-node.yaml#
+
+ description:
+ Pin controller client devices use pin configuration subnodes (children
+ and grandchildren) for desired pin configuration.
+ Client device subnodes use below standard properties.
+
+ properties:
+ phandle: true
+ pinmux:
+ description:
+ Values are constructed from GPIO port number, pin number, and
+ alternate function configuration number using the RZG2L_PORT_PINMUX()
+ helper macro in <dt-bindings/pinctrl/rzg2l-pinctrl.h>.
+ pins: true
+ drive-strength:
+ enum: [ 2, 4, 8, 12 ]
+ power-source:
+ enum: [ 1800, 2500, 3300 ]
+ slew-rate: true
+ gpio-hog: true
+ gpios: true
+ input-enable: true
+ output-high: true
+ output-low: true
+ line-name: true
+
+ - type: object
+ properties:
+ phandle: true
+
+ additionalProperties:
+ $ref: "#/additionalProperties/anyOf/0"
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - '#gpio-cells'
+ - gpio-ranges
+ - clocks
+ - power-domains
+ - resets
+
+examples:
+ - |
+ #include <dt-bindings/pinctrl/rzg2l-pinctrl.h>
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+
+ pinctrl: pinctrl@11030000 {
+ compatible = "renesas,r9a07g044-pinctrl";
+ reg = <0x11030000 0x10000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 392>;
+ clocks = <&cpg CPG_MOD R9A07G044_GPIO_HCLK>;
+ resets = <&cpg R9A07G044_GPIO_RSTN>,
+ <&cpg R9A07G044_GPIO_PORT_RESETN>,
+ <&cpg R9A07G044_GPIO_SPARE_RESETN>;
+ power-domains = <&cpg>;
+
+ scif0_pins: serial0 {
+ pinmux = <RZG2L_PORT_PINMUX(38, 0, 1)>, /* Tx */
+ <RZG2L_PORT_PINMUX(38, 1, 1)>; /* Rx */
+ };
+
+ i2c1_pins: i2c1 {
+ pins = "RIIC1_SDA", "RIIC1_SCL";
+ input-enable;
+ };
+
+ sd1-pwr-en-hog {
+ gpio-hog;
+ gpios = <RZG2L_GPIO(39, 2) 0>;
+ output-high;
+ line-name = "sd1_pwr_en";
+ };
+
+ sdhi1_pins: sd1 {
+ sd1_mux {
+ pinmux = <RZG2L_PORT_PINMUX(19, 0, 1)>, /* CD */
+ <RZG2L_PORT_PINMUX(19, 1, 1)>; /* WP */
+ power-source = <3300>;
+ };
+
+ sd1_data {
+ pins = "SD1_DATA0", "SD1_DATA1", "SD1_DATA2", "SD1_DATA3";
+ power-source = <3300>;
+ };
+
+ sd1_ctrl {
+ pins = "SD1_CLK", "SD1_CMD";
+ power-source = <3300>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index 38a1416fd2cd..e7a1b1880375 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -22,6 +22,7 @@ Required Properties:
- "samsung,exynos5420-pinctrl": for Exynos5420 compatible pin-controller.
- "samsung,exynos5433-pinctrl": for Exynos5433 compatible pin-controller.
- "samsung,exynos7-pinctrl": for Exynos7 compatible pin-controller.
+ - "samsung,exynos850-pinctrl": for Exynos850 compatible pin-controller.
- reg: Base address of the pin controller hardware module and length of
the address space it occupies.
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
index 72877544ca78..dfee6d38a701 100644
--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
@@ -24,6 +24,7 @@ properties:
- st,stm32f746-pinctrl
- st,stm32f769-pinctrl
- st,stm32h743-pinctrl
+ - st,stm32mp135-pinctrl
- st,stm32mp157-pinctrl
- st,stm32mp157-z-pinctrl
diff --git a/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.txt
deleted file mode 100644
index f488b0f77406..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.txt
+++ /dev/null
@@ -1,105 +0,0 @@
- Binding for Xilinx Zynq Pinctrl
-
-Required properties:
-- compatible: "xlnx,zynq-pinctrl"
-- syscon: phandle to SLCR
-- reg: Offset and length of pinctrl space in SLCR
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-Zynq's pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, slew rate, etc.
-
-Each configuration node can consist of multiple nodes describing the pinmux and
-pinconf options. Those nodes can be pinmux nodes or pinconf nodes.
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Required properties for pinmux nodes are:
- - groups: A list of pinmux groups.
- - function: The name of a pinmux function to activate for the specified set
- of groups.
-
-Required properties for configuration nodes:
-One of:
- - pins: a list of pin names
- - groups: A list of pinmux groups.
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pinmux subnode:
- groups, function
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pinconf subnode:
- groups, pins, bias-disable, bias-high-impedance, bias-pull-up, slew-rate,
- low-power-disable, low-power-enable
-
- Valid arguments for 'slew-rate' are '0' and '1' to select between slow and fast
- respectively.
-
- Valid values for groups are:
- ethernet0_0_grp, ethernet1_0_grp, mdio0_0_grp, mdio1_0_grp,
- qspi0_0_grp, qspi1_0_grp, qspi_fbclk, qspi_cs1_grp, spi0_0_grp - spi0_2_grp,
- spi0_X_ssY (X=0..2, Y=0..2), spi1_0_grp - spi1_3_grp,
- spi1_X_ssY (X=0..3, Y=0..2), sdio0_0_grp - sdio0_2_grp,
- sdio1_0_grp - sdio1_3_grp, sdio0_emio_wp, sdio0_emio_cd, sdio1_emio_wp,
- sdio1_emio_cd, smc0_nor, smc0_nor_cs1_grp, smc0_nor_addr25_grp, smc0_nand,
- can0_0_grp - can0_10_grp, can1_0_grp - can1_11_grp, uart0_0_grp - uart0_10_grp,
- uart1_0_grp - uart1_11_grp, i2c0_0_grp - i2c0_10_grp, i2c1_0_grp - i2c1_10_grp,
- ttc0_0_grp - ttc0_2_grp, ttc1_0_grp - ttc1_2_grp, swdt0_0_grp - swdt0_4_grp,
- gpio0_0_grp - gpio0_53_grp, usb0_0_grp, usb1_0_grp
-
- Valid values for pins are:
- MIO0 - MIO53
-
- Valid values for function are:
- ethernet0, ethernet1, mdio0, mdio1, qspi0, qspi1, qspi_fbclk, qspi_cs1,
- spi0, spi0_ss, spi1, spi1_ss, sdio0, sdio0_pc, sdio0_cd, sdio0_wp,
- sdio1, sdio1_pc, sdio1_cd, sdio1_wp,
- smc0_nor, smc0_nor_cs1, smc0_nor_addr25, smc0_nand, can0, can1, uart0, uart1,
- i2c0, i2c1, ttc0, ttc1, swdt0, gpio0, usb0, usb1
-
-The following driver-specific properties as defined here are valid to specify in
-a pin configuration subnode:
- - io-standard: Configure the pin to use the selected IO standard according to
- this mapping:
- 1: LVCMOS18
- 2: LVCMOS25
- 3: LVCMOS33
- 4: HSTL
-
-Example:
- pinctrl0: pinctrl@700 {
- compatible = "xlnx,pinctrl-zynq";
- reg = <0x700 0x200>;
- syscon = <&slcr>;
-
- pinctrl_uart1_default: uart1-default {
- mux {
- groups = "uart1_10_grp";
- function = "uart1";
- };
-
- conf {
- groups = "uart1_10_grp";
- slew-rate = <0>;
- io-standard = <1>;
- };
-
- conf-rx {
- pins = "MIO49";
- bias-high-impedance;
- };
-
- conf-tx {
- pins = "MIO48";
- bias-disable;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.yaml
new file mode 100644
index 000000000000..ac97dbf6998e
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.yaml
@@ -0,0 +1,214 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/xlnx,zynq-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Zynq Pinctrl
+
+maintainers:
+ - Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com>
+
+description: |
+ Please refer to pinctrl-bindings.txt in this directory for details of the
+ common pinctrl bindings used by client devices, including the meaning of the
+ phrase "pin configuration node".
+
+ Zynq's pin configuration nodes act as a container for an arbitrary number of
+ subnodes. Each of these subnodes represents some desired configuration for a
+ pin, a group, or a list of pins or groups. This configuration can include the
+ mux function to select on those pin(s)/group(s), and various pin configuration
+ parameters, such as pull-up, slew rate, etc.
+
+ Each configuration node can consist of multiple nodes describing the pinmux and
+ pinconf options. Those nodes can be pinmux nodes or pinconf nodes.
+
+ The name of each subnode is not important; all subnodes should be enumerated
+ and processed purely based on their content.
+
+properties:
+ compatible:
+ const: xlnx,zynq-pinctrl
+
+ reg:
+ description: Specifies the base address and size of the SLCR space.
+ maxItems: 1
+
+ syscon:
+ description:
+ phandle to the SLCR.
+
+patternProperties:
+ '^(.*-)?(default|gpio)$':
+ type: object
+ patternProperties:
+ '^mux':
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for pin muxes,
+ which in turn use below standard properties.
+ $ref: pinmux-node.yaml#
+
+ properties:
+ groups:
+ description:
+ List of groups to select (either this or "pins" must be
+ specified), available groups for this subnode.
+ items:
+ enum: [ethernet0_0_grp, ethernet1_0_grp, mdio0_0_grp,
+ mdio1_0_grp, qspi0_0_grp, qspi1_0_grp, qspi_fbclk,
+ qspi_cs1_grp, spi0_0_grp, spi0_1_grp, spi0_2_grp,
+ spi0_0_ss0, spi0_0_ss1, spi0_0_ss2, spi0_1_ss0,
+ spi0_1_ss1, spi0_1_ss2, spi0_2_ss0, spi0_2_ss1,
+ spi0_2_ss2, spi1_0_grp, spi1_1_grp, spi1_2_grp,
+ spi1_3_grp, spi1_0_ss0, spi1_0_ss1, spi1_0_ss2,
+ spi1_1_ss0, spi1_1_ss1, spi1_1_ss2, spi1_2_ss0,
+ spi1_2_ss1, spi1_2_ss2, spi1_3_ss0, spi1_3_ss1,
+ spi1_3_ss2, sdio0_0_grp, sdio0_1_grp, sdio0_2_grp,
+ sdio1_0_grp, sdio1_1_grp, sdio1_2_grp, sdio1_3_grp,
+ sdio0_emio_wp, sdio0_emio_cd, sdio1_emio_wp,
+ sdio1_emio_cd, smc0_nor, smc0_nor_cs1_grp,
+ smc0_nor_addr25_grp, smc0_nand, can0_0_grp, can0_1_grp,
+ can0_2_grp, can0_3_grp, can0_4_grp, can0_5_grp,
+ can0_6_grp, can0_7_grp, can0_8_grp, can0_9_grp,
+ can0_10_grp, can1_0_grp, can1_1_grp, can1_2_grp,
+ can1_3_grp, can1_4_grp, can1_5_grp, can1_6_grp,
+ can1_7_grp, can1_8_grp, can1_9_grp, can1_10_grp,
+ can1_11_grp, uart0_0_grp, uart0_1_grp, uart0_2_grp,
+ uart0_3_grp, uart0_4_grp, uart0_5_grp, uart0_6_grp,
+ uart0_7_grp, uart0_8_grp, uart0_9_grp, uart0_10_grp,
+ uart1_0_grp, uart1_1_grp, uart1_2_grp, uart1_3_grp,
+ uart1_4_grp, uart1_5_grp, uart1_6_grp, uart1_7_grp,
+ uart1_8_grp, uart1_9_grp, uart1_10_grp, uart1_11_grp,
+ i2c0_0_grp, i2c0_1_grp, i2c0_2_grp, i2c0_3_grp,
+ i2c0_4_grp, i2c0_5_grp, i2c0_6_grp, i2c0_7_grp,
+ i2c0_8_grp, i2c0_9_grp, i2c0_10_grp, i2c1_0_grp,
+ i2c1_1_grp, i2c1_2_grp, i2c1_3_grp, i2c1_4_grp,
+ i2c1_5_grp, i2c1_6_grp, i2c1_7_grp, i2c1_8_grp,
+ i2c1_9_grp, i2c1_10_grp, ttc0_0_grp, ttc0_1_grp,
+ ttc0_2_grp, ttc1_0_grp, ttc1_1_grp, ttc1_2_grp,
+ swdt0_0_grp, swdt0_1_grp, swdt0_2_grp, swdt0_3_grp,
+ swdt0_4_grp, gpio0_0_grp, gpio0_1_grp, gpio0_2_grp,
+ gpio0_3_grp, gpio0_4_grp, gpio0_5_grp, gpio0_6_grp,
+ gpio0_7_grp, gpio0_8_grp, gpio0_9_grp, gpio0_10_grp,
+ gpio0_11_grp, gpio0_12_grp, gpio0_13_grp, gpio0_14_grp,
+ gpio0_15_grp, gpio0_16_grp, gpio0_17_grp, gpio0_18_grp,
+ gpio0_19_grp, gpio0_20_grp, gpio0_21_grp, gpio0_22_grp,
+ gpio0_23_grp, gpio0_24_grp, gpio0_25_grp, gpio0_26_grp,
+ gpio0_27_grp, gpio0_28_grp, gpio0_29_grp, gpio0_30_grp,
+ gpio0_31_grp, gpio0_32_grp, gpio0_33_grp, gpio0_34_grp,
+ gpio0_35_grp, gpio0_36_grp, gpio0_37_grp, gpio0_38_grp,
+ gpio0_39_grp, gpio0_40_grp, gpio0_41_grp, gpio0_42_grp,
+ gpio0_43_grp, gpio0_44_grp, gpio0_45_grp, gpio0_46_grp,
+ gpio0_47_grp, gpio0_48_grp, gpio0_49_grp, gpio0_50_grp,
+ gpio0_51_grp, gpio0_52_grp, gpio0_53_grp, usb0_0_grp,
+ usb1_0_grp]
+ maxItems: 54
+
+ function:
+ description:
+ Specify the alternative function to be configured for the
+ given pin groups.
+ enum: [ethernet0, ethernet1, mdio0, mdio1, qspi0, qspi1, qspi_fbclk,
+ qspi_cs1, spi0, spi0_ss, spi1, spi1_ss, sdio0, sdio0_pc,
+ sdio0_cd, sdio0_wp, sdio1, sdio1_pc, sdio1_cd, sdio1_wp,
+ smc0_nor, smc0_nor_cs1, smc0_nor_addr25, smc0_nand, can0,
+ can1, uart0, uart1, i2c0, i2c1, ttc0, ttc1, swdt0, gpio0,
+ usb0, usb1]
+
+ required:
+ - groups
+ - function
+
+ additionalProperties: false
+
+ '^conf':
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for pin configurations,
+ which in turn use the standard properties below.
+ $ref: pincfg-node.yaml#
+
+ properties:
+ groups:
+ description:
+ List of pin groups as mentioned above.
+
+ pins:
+ description:
+ List of pin names to select in this subnode.
+ items:
+ pattern: '^MIO([0-9]|[1-4][0-9]|5[0-3])$'
+ maxItems: 54
+
+ bias-pull-up: true
+
+ bias-pull-down: true
+
+ bias-disable: true
+
+ bias-high-impedance: true
+
+ low-power-enable: true
+
+ low-power-disable: true
+
+ slew-rate:
+ enum: [0, 1]
+
+ power-source:
+ enum: [1, 2, 3, 4]
+
+ oneOf:
+ - required: [ groups ]
+ - required: [ pins ]
+
+ additionalProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - syscon
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/pinctrl/pinctrl-zynq.h>
+ pinctrl0: pinctrl@700 {
+ compatible = "xlnx,zynq-pinctrl";
+ reg = <0x700 0x200>;
+ syscon = <&slcr>;
+
+ pinctrl_uart1_default: uart1-default {
+ mux {
+ groups = "uart1_10_grp";
+ function = "uart1";
+ };
+
+ conf {
+ groups = "uart1_10_grp";
+ slew-rate = <0>;
+ power-source = <IO_STANDARD_LVCMOS18>;
+ };
+
+ conf-rx {
+ pins = "MIO49";
+ bias-high-impedance;
+ };
+
+ conf-tx {
+ pins = "MIO48";
+ bias-disable;
+ };
+ };
+ };
+
+ uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_default>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
index 4807b560f00d..239f37881cae 100644
--- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
@@ -30,6 +30,7 @@ properties:
- qcom,sc8180x-rpmhpd
- qcom,sdm845-rpmhpd
- qcom,sdx55-rpmhpd
+ - qcom,sm6115-rpmpd
- qcom,sm8150-rpmhpd
- qcom,sm8250-rpmhpd
- qcom,sm8350-rpmhpd
diff --git a/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt
deleted file mode 100644
index bb529ecf8a57..000000000000
--- a/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt
+++ /dev/null
@@ -1,61 +0,0 @@
---------------------------------------------------------------------
-Device Tree Bindings for the Xilinx Zynq MPSoC Power Management
---------------------------------------------------------------------
-The zynqmp-power node describes the power management configurations.
-It will control remote suspend/shutdown interfaces.
-
-Required properties:
- - compatible: Must contain: "xlnx,zynqmp-power"
- - interrupts: Interrupt specifier
-
-Optional properties:
- - mbox-names : Name given to channels seen in the 'mboxes' property.
- "tx" - Mailbox corresponding to transmit path
- "rx" - Mailbox corresponding to receive path
- - mboxes : Standard property to specify a Mailbox. Each value of
- the mboxes property should contain a phandle to the
- mailbox controller device node and an args specifier
- that will be the phandle to the intended sub-mailbox
- child node to be used for communication. See
- Documentation/devicetree/bindings/mailbox/mailbox.txt
- for more details about the generic mailbox controller
- and client driver bindings. Also see
- Documentation/devicetree/bindings/mailbox/ \
- xlnx,zynqmp-ipi-mailbox.txt for typical controller that
- is used to communicate with this System controllers.
-
---------
-Examples
---------
-
-Example with interrupt method:
-
-firmware {
- zynqmp_firmware: zynqmp-firmware {
- compatible = "xlnx,zynqmp-firmware";
- method = "smc";
-
- zynqmp_power: zynqmp-power {
- compatible = "xlnx,zynqmp-power";
- interrupts = <0 35 4>;
- };
- };
-};
-
-Example with IPI mailbox method:
-
-firmware {
- zynqmp_firmware: zynqmp-firmware {
- compatible = "xlnx,zynqmp-firmware";
- method = "smc";
-
- zynqmp_power: zynqmp-power {
- compatible = "xlnx,zynqmp-power";
- interrupt-parent = <&gic>;
- interrupts = <0 35 4>;
- mboxes = <&ipi_mailbox_pmu0 0>,
- <&ipi_mailbox_pmu0 1>;
- mbox-names = "tx", "rx";
- };
- };
-};
diff --git a/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml
new file mode 100644
index 000000000000..68d7c14a7163
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/reset/xlnx,zynqmp-power.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Zynq MPSoC Power Management Device Tree Bindings
+
+maintainers:
+ - Michal Simek <michal.simek@xilinx.com>
+
+description: |
+ The zynqmp-power node describes the power management configurations.
+ It will control remote suspend/shutdown interfaces.
+
+properties:
+ compatible:
+ const: "xlnx,zynqmp-power"
+
+ interrupts:
+ maxItems: 1
+
+ mboxes:
+ description: |
+ Standard property to specify a Mailbox. Each value of
+ the mboxes property should contain a phandle to the
+ mailbox controller device node and an args specifier
+ that will be the phandle to the intended sub-mailbox
+ child node to be used for communication. See
+ Documentation/devicetree/bindings/mailbox/mailbox.txt
+ for more details about the generic mailbox controller
+ and client driver bindings. Also see
+ Documentation/devicetree/bindings/mailbox/ \
+ xlnx,zynqmp-ipi-mailbox.txt for typical controller that
+ is used to communicate with this System controllers.
+ items:
+ - description: tx channel
+ - description: rx channel
+
+ mbox-names:
+ description:
+ Name given to channels seen in the 'mboxes' property.
+ items:
+ - const: tx
+ - const: rx
+
+required:
+ - compatible
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |+
+
+ // Example with interrupt method:
+
+ firmware {
+ zynqmp-firmware {
+ zynqmp-power {
+ compatible = "xlnx,zynqmp-power";
+ interrupts = <0 35 4>;
+ };
+ };
+ };
+
+ - |+
+
+ // Example with IPI mailbox method:
+
+ firmware {
+ zynqmp-firmware {
+ zynqmp-power {
+ compatible = "xlnx,zynqmp-power";
+ interrupt-parent = <&gic>;
+ interrupts = <0 35 4>;
+ mboxes = <&ipi_mailbox_pmu1 0>,
+ <&ipi_mailbox_pmu1 1>;
+ mbox-names = "tx", "rx";
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/power/rockchip-io-domain.txt b/Documentation/devicetree/bindings/power/rockchip-io-domain.txt
deleted file mode 100644
index e66fd4eab71c..000000000000
--- a/Documentation/devicetree/bindings/power/rockchip-io-domain.txt
+++ /dev/null
@@ -1,135 +0,0 @@
-Rockchip SRAM for IO Voltage Domains:
--------------------------------------
-
-IO domain voltages on some Rockchip SoCs are variable but need to be
-kept in sync between the regulators and the SoC using a special
-register.
-
-A specific example using rk3288:
-- If the regulator hooked up to a pin like SDMMC0_VDD is 3.3V then
- bit 7 of GRF_IO_VSEL needs to be 0. If the regulator hooked up to
- that same pin is 1.8V then bit 7 of GRF_IO_VSEL needs to be 1.
-
-Said another way, this driver simply handles keeping bits in the SoC's
-general register file (GRF) in sync with the actual value of a voltage
-hooked up to the pins.
-
-Note that this driver specifically doesn't include:
-- any logic for deciding what voltage we should set regulators to
-- any logic for deciding whether regulators (or internal SoC blocks)
- should have power or not have power
-
-If there were some other software that had the smarts of making
-decisions about regulators, it would work in conjunction with this
-driver. When that other software adjusted a regulator's voltage then
-this driver would handle telling the SoC about it. A good example is
-vqmmc for SD. In that case the dw_mmc driver simply is told about a
-regulator. It changes the regulator between 3.3V and 1.8V at the
-right time. This driver notices the change and makes sure that the
-SoC is on the same page.
-
-
-Required properties:
-- compatible: should be one of:
- - "rockchip,px30-io-voltage-domain" for px30
- - "rockchip,px30-pmu-io-voltage-domain" for px30 pmu-domains
- - "rockchip,rk3188-io-voltage-domain" for rk3188
- - "rockchip,rk3228-io-voltage-domain" for rk3228
- - "rockchip,rk3288-io-voltage-domain" for rk3288
- - "rockchip,rk3328-io-voltage-domain" for rk3328
- - "rockchip,rk3368-io-voltage-domain" for rk3368
- - "rockchip,rk3368-pmu-io-voltage-domain" for rk3368 pmu-domains
- - "rockchip,rk3399-io-voltage-domain" for rk3399
- - "rockchip,rk3399-pmu-io-voltage-domain" for rk3399 pmu-domains
- - "rockchip,rv1108-io-voltage-domain" for rv1108
- - "rockchip,rv1108-pmu-io-voltage-domain" for rv1108 pmu-domains
-
-Deprecated properties:
-- rockchip,grf: phandle to the syscon managing the "general register files"
- Systems should move the io-domains to a sub-node of the grf simple-mfd.
-
-You specify supplies using the standard regulator bindings by including
-a phandle the relevant regulator. All specified supplies must be able
-to report their voltage. The IO Voltage Domain for any non-specified
-supplies will be not be touched.
-
-Possible supplies for PX30:
-- vccio6-supply: The supply connected to VCCIO6.
-- vccio1-supply: The supply connected to VCCIO1.
-- vccio2-supply: The supply connected to VCCIO2.
-- vccio3-supply: The supply connected to VCCIO3.
-- vccio4-supply: The supply connected to VCCIO4.
-- vccio5-supply: The supply connected to VCCIO5.
-- vccio-oscgpi-supply: The supply connected to VCCIO_OSCGPI.
-
-Possible supplies for PX30 pmu-domains:
-- pmuio1-supply: The supply connected to PMUIO1.
-- pmuio2-supply: The supply connected to PMUIO2.
-
-Possible supplies for rk3188:
-- ap0-supply: The supply connected to AP0_VCC.
-- ap1-supply: The supply connected to AP1_VCC.
-- cif-supply: The supply connected to CIF_VCC.
-- flash-supply: The supply connected to FLASH_VCC.
-- lcdc0-supply: The supply connected to LCD0_VCC.
-- lcdc1-supply: The supply connected to LCD1_VCC.
-- vccio0-supply: The supply connected to VCCIO0.
-- vccio1-supply: The supply connected to VCCIO1.
- Sometimes also labeled VCCIO1 and VCCIO2.
-
-Possible supplies for rk3228:
-- vccio1-supply: The supply connected to VCCIO1.
-- vccio2-supply: The supply connected to VCCIO2.
-- vccio3-supply: The supply connected to VCCIO3.
-- vccio4-supply: The supply connected to VCCIO4.
-
-Possible supplies for rk3288:
-- audio-supply: The supply connected to APIO4_VDD.
-- bb-supply: The supply connected to APIO5_VDD.
-- dvp-supply: The supply connected to DVPIO_VDD.
-- flash0-supply: The supply connected to FLASH0_VDD. Typically for eMMC
-- flash1-supply: The supply connected to FLASH1_VDD. Also known as SDIO1.
-- gpio30-supply: The supply connected to APIO1_VDD.
-- gpio1830 The supply connected to APIO2_VDD.
-- lcdc-supply: The supply connected to LCDC_VDD.
-- sdcard-supply: The supply connected to SDMMC0_VDD.
-- wifi-supply: The supply connected to APIO3_VDD. Also known as SDIO0.
-
-Possible supplies for rk3368:
-- audio-supply: The supply connected to APIO3_VDD.
-- dvp-supply: The supply connected to DVPIO_VDD.
-- flash0-supply: The supply connected to FLASH0_VDD. Typically for eMMC
-- gpio30-supply: The supply connected to APIO1_VDD.
-- gpio1830 The supply connected to APIO4_VDD.
-- sdcard-supply: The supply connected to SDMMC0_VDD.
-- wifi-supply: The supply connected to APIO2_VDD. Also known as SDIO0.
-
-Possible supplies for rk3368 pmu-domains:
-- pmu-supply: The supply connected to PMUIO_VDD.
-- vop-supply: The supply connected to LCDC_VDD.
-
-Possible supplies for rk3399:
-- bt656-supply: The supply connected to APIO2_VDD.
-- audio-supply: The supply connected to APIO5_VDD.
-- sdmmc-supply: The supply connected to SDMMC0_VDD.
-- gpio1830 The supply connected to APIO4_VDD.
-
-Possible supplies for rk3399 pmu-domains:
-- pmu1830-supply:The supply connected to PMUIO2_VDD.
-
-Example:
-
- io-domains {
- compatible = "rockchip,rk3288-io-voltage-domain";
- rockchip,grf = <&grf>;
-
- audio-supply = <&vcc18_codec>;
- bb-supply = <&vcc33_io>;
- dvp-supply = <&vcc_18>;
- flash0-supply = <&vcc18_flashio>;
- gpio1830-supply = <&vcc33_io>;
- gpio30-supply = <&vcc33_pmuio>;
- lcdc-supply = <&vcc33_lcd>;
- sdcard-supply = <&vccio_sd>;
- wifi-supply = <&vcc18_wl>;
- };
diff --git a/Documentation/devicetree/bindings/power/rockchip-io-domain.yaml b/Documentation/devicetree/bindings/power/rockchip-io-domain.yaml
new file mode 100644
index 000000000000..1727bf108979
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rockchip-io-domain.yaml
@@ -0,0 +1,360 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/rockchip-io-domain.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SRAM for IO Voltage Domains
+
+maintainers:
+ - Heiko Stuebner <heiko@sntech.de>
+
+description: |
+ IO domain voltages on some Rockchip SoCs are variable but need to be
+ kept in sync between the regulators and the SoC using a special
+ register.
+
+ A specific example using rk3288
+ If the regulator hooked up to a pin like SDMMC0_VDD is 3.3V then
+ bit 7 of GRF_IO_VSEL needs to be 0. If the regulator hooked up to
+ that same pin is 1.8V then bit 7 of GRF_IO_VSEL needs to be 1.
+
+ Said another way, this driver simply handles keeping bits in the SoCs
+ General Register File (GRF) in sync with the actual value of a voltage
+ hooked up to the pins.
+
+ Note that this driver specifically does not include
+ any logic for deciding what voltage we should set regulators to
+ any logic for deciding whether regulators (or internal SoC blocks)
+ should have power or not have power
+
+ If there were some other software that had the smarts of making
+ decisions about regulators, it would work in conjunction with this
+ driver. When that other software adjusted a regulators voltage then
+ this driver would handle telling the SoC about it. A good example is
+ vqmmc for SD. In that case the dw_mmc driver simply is told about a
+ regulator. It changes the regulator between 3.3V and 1.8V at the
+ right time. This driver notices the change and makes sure that the
+ SoC is on the same page.
+
+ You specify supplies using the standard regulator bindings by including
+ a phandle the relevant regulator. All specified supplies must be able
+ to report their voltage. The IO Voltage Domain for any non-specified
+ supplies will be not be touched.
+
+properties:
+ compatible:
+ enum:
+ - rockchip,px30-io-voltage-domain
+ - rockchip,px30-pmu-io-voltage-domain
+ - rockchip,rk3188-io-voltage-domain
+ - rockchip,rk3228-io-voltage-domain
+ - rockchip,rk3288-io-voltage-domain
+ - rockchip,rk3328-io-voltage-domain
+ - rockchip,rk3368-io-voltage-domain
+ - rockchip,rk3368-pmu-io-voltage-domain
+ - rockchip,rk3399-io-voltage-domain
+ - rockchip,rk3399-pmu-io-voltage-domain
+ - rockchip,rk3568-pmu-io-voltage-domain
+ - rockchip,rv1108-io-voltage-domain
+ - rockchip,rv1108-pmu-io-voltage-domain
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+allOf:
+ - $ref: "#/$defs/px30"
+ - $ref: "#/$defs/px30-pmu"
+ - $ref: "#/$defs/rk3188"
+ - $ref: "#/$defs/rk3228"
+ - $ref: "#/$defs/rk3288"
+ - $ref: "#/$defs/rk3328"
+ - $ref: "#/$defs/rk3368"
+ - $ref: "#/$defs/rk3368-pmu"
+ - $ref: "#/$defs/rk3399"
+ - $ref: "#/$defs/rk3399-pmu"
+ - $ref: "#/$defs/rk3568-pmu"
+ - $ref: "#/$defs/rv1108"
+ - $ref: "#/$defs/rv1108-pmu"
+
+$defs:
+ px30:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,px30-io-voltage-domain
+
+ then:
+ properties:
+ vccio1-supply:
+ description: The supply connected to VCCIO1.
+ vccio2-supply:
+ description: The supply connected to VCCIO2.
+ vccio3-supply:
+ description: The supply connected to VCCIO3.
+ vccio4-supply:
+ description: The supply connected to VCCIO4.
+ vccio5-supply:
+ description: The supply connected to VCCIO5.
+ vccio6-supply:
+ description: The supply connected to VCCIO6.
+ vccio-oscgpi-supply:
+ description: The supply connected to VCCIO_OSCGPI.
+
+ px30-pmu:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,px30-pmu-io-voltage-domain
+
+ then:
+ properties:
+ pmuio1-supply:
+ description: The supply connected to PMUIO1.
+ pmuio2-supply:
+ description: The supply connected to PMUIO2.
+
+ rk3188:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3188-io-voltage-domain
+
+ then:
+ properties:
+ ap0-supply:
+ description: The supply connected to AP0_VCC.
+ ap1-supply:
+ description: The supply connected to AP1_VCC.
+ cif-supply:
+ description: The supply connected to CIF_VCC.
+ flash-supply:
+ description: The supply connected to FLASH_VCC.
+ lcdc0-supply:
+ description: The supply connected to LCD0_VCC.
+ lcdc1-supply:
+ description: The supply connected to LCD1_VCC.
+ vccio0-supply:
+ description: The supply connected to VCCIO0.
+ vccio1-supply:
+ description: The supply connected to VCCIO1. Also labeled as VCCIO2.
+
+ rk3228:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3228-io-voltage-domain
+
+ then:
+ properties:
+ vccio1-supply:
+ description: The supply connected to VCCIO1.
+ vccio2-supply:
+ description: The supply connected to VCCIO2.
+ vccio3-supply:
+ description: The supply connected to VCCIO3.
+ vccio4-supply:
+ description: The supply connected to VCCIO4.
+
+ rk3288:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3288-io-voltage-domain
+
+ then:
+ properties:
+ audio-supply:
+ description: The supply connected to APIO4_VDD.
+ bb-supply:
+ description: The supply connected to APIO5_VDD.
+ dvp-supply:
+ description: The supply connected to DVPIO_VDD.
+ flash0-supply:
+ description: The supply connected to FLASH0_VDD. Typically for eMMC.
+ flash1-supply:
+ description: The supply connected to FLASH1_VDD. Also known as SDIO1.
+ gpio30-supply:
+ description: The supply connected to APIO1_VDD.
+ gpio1830-supply:
+ description: The supply connected to APIO2_VDD.
+ lcdc-supply:
+ description: The supply connected to LCDC_VDD.
+ sdcard-supply:
+ description: The supply connected to SDMMC0_VDD.
+ wifi-supply:
+ description: The supply connected to APIO3_VDD. Also known as SDIO0.
+
+ rk3328:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3328-io-voltage-domain
+
+ then:
+ properties:
+ vccio1-supply:
+ description: The supply connected to VCCIO1.
+ vccio2-supply:
+ description: The supply connected to VCCIO2.
+ vccio3-supply:
+ description: The supply connected to VCCIO3.
+ vccio4-supply:
+ description: The supply connected to VCCIO4.
+ vccio5-supply:
+ description: The supply connected to VCCIO5.
+ vccio6-supply:
+ description: The supply connected to VCCIO6.
+ pmuio-supply:
+ description: The supply connected to VCCIO_PMU.
+
+ rk3368:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3368-io-voltage-domain
+
+ then:
+ properties:
+ audio-supply:
+ description: The supply connected to APIO3_VDD.
+ dvp-supply:
+ description: The supply connected to DVPIO_VDD.
+ flash0-supply:
+ description: The supply connected to FLASH0_VDD. Typically for eMMC.
+ gpio30-supply:
+ description: The supply connected to APIO1_VDD.
+ gpio1830-supply:
+ description: The supply connected to APIO4_VDD.
+ sdcard-supply:
+ description: The supply connected to SDMMC0_VDD.
+ wifi-supply:
+ description: The supply connected to APIO2_VDD. Also known as SDIO0.
+
+ rk3368-pmu:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3368-pmu-io-voltage-domain
+
+ then:
+ properties:
+ pmu-supply:
+ description: The supply connected to PMUIO_VDD.
+ vop-supply:
+ description: The supply connected to LCDC_VDD.
+
+ rk3399:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3399-io-voltage-domain
+
+ then:
+ properties:
+ audio-supply:
+ description: The supply connected to APIO5_VDD.
+ bt656-supply:
+ description: The supply connected to APIO2_VDD.
+ gpio1830-supply:
+ description: The supply connected to APIO4_VDD.
+ sdmmc-supply:
+ description: The supply connected to SDMMC0_VDD.
+
+ rk3399-pmu:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3399-pmu-io-voltage-domain
+
+ then:
+ properties:
+ pmu1830-supply:
+ description: The supply connected to PMUIO2_VDD.
+
+ rk3568-pmu:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3568-pmu-io-voltage-domain
+
+ then:
+ properties:
+ pmuio1-supply:
+ description: The supply connected to PMUIO1.
+ pmuio2-supply:
+ description: The supply connected to PMUIO2.
+ vccio1-supply:
+ description: The supply connected to VCCIO1.
+ vccio2-supply:
+ description: The supply connected to VCCIO2.
+ vccio3-supply:
+ description: The supply connected to VCCIO3.
+ vccio4-supply:
+ description: The supply connected to VCCIO4.
+ vccio5-supply:
+ description: The supply connected to VCCIO5.
+ vccio6-supply:
+ description: The supply connected to VCCIO6.
+ vccio7-supply:
+ description: The supply connected to VCCIO7.
+
+ rv1108:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rv1108-io-voltage-domain
+
+ then:
+ properties:
+ vccio1-supply:
+ description: The supply connected to APIO1_VDD.
+ vccio2-supply:
+ description: The supply connected to APIO2_VDD.
+ vccio3-supply:
+ description: The supply connected to APIO3_VDD.
+ vccio5-supply:
+ description: The supply connected to APIO5_VDD.
+ vccio6-supply:
+ description: The supply connected to APIO6_VDD.
+
+ rv1108-pmu:
+ if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rv1108-pmu-io-voltage-domain
+
+ then:
+ properties:
+ pmu-supply:
+ description: The supply connected to PMUIO_VDD.
+
+examples:
+ - |
+ io-domains {
+ compatible = "rockchip,rk3288-io-voltage-domain";
+ audio-supply = <&vcc18_codec>;
+ bb-supply = <&vcc33_io>;
+ dvp-supply = <&vcc_18>;
+ flash0-supply = <&vcc18_flashio>;
+ gpio1830-supply = <&vcc33_io>;
+ gpio30-supply = <&vcc33_pmuio>;
+ lcdc-supply = <&vcc33_lcd>;
+ sdcard-supply = <&vccio_sd>;
+ wifi-supply = <&vcc18_wl>;
+ };
diff --git a/Documentation/devicetree/bindings/regulator/richtek,rt6245-regulator.yaml b/Documentation/devicetree/bindings/regulator/richtek,rt6245-regulator.yaml
index 796ceac87445..e983d0e70c9b 100644
--- a/Documentation/devicetree/bindings/regulator/richtek,rt6245-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/richtek,rt6245-regulator.yaml
@@ -77,7 +77,6 @@ examples:
rt6245@34 {
compatible = "richtek,rt6245";
- status = "okay";
reg = <0x34>;
enable-gpios = <&gpio26 2 0>;
diff --git a/Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml b/Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
index 6f45582c914e..dd7a2f92634c 100644
--- a/Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
@@ -39,6 +39,5 @@ examples:
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <3000000>;
regulator-always-on;
- status = "disabled";
};
...
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
index c597ccced623..0c112f3264a9 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
@@ -28,6 +28,7 @@ properties:
- qcom,sc8180x-adsp-pas
- qcom,sc8180x-cdsp-pas
- qcom,sc8180x-mpss-pas
+ - qcom,sdm660-adsp-pas
- qcom,sdm845-adsp-pas
- qcom,sdm845-cdsp-pas
- qcom,sdx55-mpss-pas
diff --git a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
index e8d3096d922c..39b5f4c5a511 100644
--- a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
@@ -51,6 +51,23 @@ compatible (optional) - standard definition
used as a shared pool of DMA buffers for a set of devices. It can
be used by an operating system to instantiate the necessary pool
management subsystem if necessary.
+ - restricted-dma-pool: This indicates a region of memory meant to be
+ used as a pool of restricted DMA buffers for a set of devices. The
+ memory region would be the only region accessible to those devices.
+ When using this, the no-map and reusable properties must not be set,
+ so the operating system can create a virtual mapping that will be used
+ for synchronization. The main purpose for restricted DMA is to
+ mitigate the lack of DMA access control on systems without an IOMMU,
+ which could result in the DMA accessing the system memory at
+ unexpected times and/or unexpected addresses, possibly leading to data
+ leakage or corruption. The feature on its own provides a basic level
+ of protection against the DMA overwriting buffer contents at
+ unexpected times. However, to protect against general data leakage and
+ system memory corruption, the system needs to provide way to lock down
+ the memory access, e.g., MPU. Note that since coherent allocation
+ needs remapping, one must set up another device coherent pool by
+ shared-dma-pool and use dma_alloc_from_dev_coherent instead for atomic
+ coherent allocation.
- vendor specific string in the form <vendor>,[<device>-]<usage>
no-map (optional) - empty property
- Indicates the operating system must not create a virtual mapping
@@ -85,10 +102,11 @@ memory-region-names (optional) - a list of names, one for each corresponding
Example
-------
-This example defines 3 contiguous regions are defined for Linux kernel:
+This example defines 4 contiguous regions for Linux kernel:
one default of all device drivers (named linux,cma@72000000 and 64MiB in size),
-one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB), and
-one for multimedia processing (named multimedia-memory@77000000, 64MiB).
+one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB),
+one for multimedia processing (named multimedia-memory@77000000, 64MiB), and
+one for restricted dma pool (named restricted_dma_reserved@0x50000000, 64MiB).
/ {
#address-cells = <1>;
@@ -120,6 +138,11 @@ one for multimedia processing (named multimedia-memory@77000000, 64MiB).
compatible = "acme,multimedia-memory";
reg = <0x77000000 0x4000000>;
};
+
+ restricted_dma_reserved: restricted_dma_reserved {
+ compatible = "restricted-dma-pool";
+ reg = <0x50000000 0x4000000>;
+ };
};
/* ... */
@@ -138,4 +161,11 @@ one for multimedia processing (named multimedia-memory@77000000, 64MiB).
memory-region = <&multimedia_reserved>;
/* ... */
};
+
+ pcie_device: pcie_device@0,0 {
+ reg = <0x83010000 0x0 0x00000000 0x0 0x00100000
+ 0x83010000 0x0 0x00100000 0x0 0x00100000>;
+ memory-region = <&restricted_dma_reserved>;
+ /* ... */
+ };
};
diff --git a/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml
index 9bf40952e5b7..b0c41ab1a746 100644
--- a/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml
+++ b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.yaml
@@ -72,6 +72,5 @@ examples:
resets = <&iomcu_rst 0x20 3>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pmx_func &i2c0_cfg_func>;
- status = "disabled";
};
...
diff --git a/Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml b/Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml
index 6b2d56cc3f38..13bf6bb3f097 100644
--- a/Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml
+++ b/Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml
@@ -57,7 +57,6 @@ examples:
};
pwm: pwm@e0d00000 {
- status = "disabled";
compatible = "intel,lgm-pwm";
reg = <0xe0d00000 0x30>;
clocks = <&cgu0 1>;
diff --git a/Documentation/devicetree/bindings/reset/qcom,aoss-reset.yaml b/Documentation/devicetree/bindings/reset/qcom,aoss-reset.yaml
index e2d85a1e1d63..a054757f4d9f 100644
--- a/Documentation/devicetree/bindings/reset/qcom,aoss-reset.yaml
+++ b/Documentation/devicetree/bindings/reset/qcom,aoss-reset.yaml
@@ -21,6 +21,11 @@ properties:
- const: "qcom,sc7180-aoss-cc"
- const: "qcom,sdm845-aoss-cc"
+ - description: on SC7280 SoCs the following compatibles must be specified
+ items:
+ - const: "qcom,sc7280-aoss-cc"
+ - const: "qcom,sdm845-aoss-cc"
+
- description: on SDM845 SoCs the following compatibles must be specified
items:
- const: "qcom,sdm845-aoss-cc"
diff --git a/Documentation/devicetree/bindings/reset/qcom,pdc-global.yaml b/Documentation/devicetree/bindings/reset/qcom,pdc-global.yaml
index d7d8cec9419f..831ea8d5d83f 100644
--- a/Documentation/devicetree/bindings/reset/qcom,pdc-global.yaml
+++ b/Documentation/devicetree/bindings/reset/qcom,pdc-global.yaml
@@ -21,6 +21,10 @@ properties:
- const: "qcom,sc7180-pdc-global"
- const: "qcom,sdm845-pdc-global"
+ - description: on SC7280 SoCs the following compatibles must be specified
+ items:
+ - const: "qcom,sc7280-pdc-global"
+
- description: on SDM845 SoCs the following compatibles must be specified
items:
- const: "qcom,sdm845-pdc-global"
diff --git a/Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml b/Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml
new file mode 100644
index 000000000000..b13514e6783d
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/renesas,rzg2l-usbphy-ctrl.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/renesas,rzg2l-usbphy-ctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L USBPHY Control
+
+maintainers:
+ - Biju Das <biju.das.jz@bp.renesas.com>
+
+description:
+ The RZ/G2L USBPHY Control mainly controls reset and power down of the
+ USB/PHY.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a07g044-usbphy-ctrl # RZ/G2{L,LC}
+ - const: renesas,rzg2l-usbphy-ctrl
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ '#reset-cells':
+ const: 1
+ description: |
+ The phandle's argument in the reset specifier is the PHY reset associated
+ with the USB port.
+ 0 = Port 1 Phy reset
+ 1 = Port 2 Phy reset
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+ - power-domains
+ - '#reset-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+
+ phyrst: usbphy-ctrl@11c40000 {
+ compatible = "renesas,r9a07g044-usbphy-ctrl",
+ "renesas,rzg2l-usbphy-ctrl";
+ reg = <0x11c40000 0x10000>;
+ clocks = <&cpg CPG_MOD R9A07G044_USB_PCLK>;
+ resets = <&cpg R9A07G044_USB_PRESETN>;
+ power-domains = <&cpg>;
+ #reset-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/reset/socionext,uniphier-glue-reset.yaml b/Documentation/devicetree/bindings/reset/socionext,uniphier-glue-reset.yaml
new file mode 100644
index 000000000000..29e4a900cad7
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/socionext,uniphier-glue-reset.yaml
@@ -0,0 +1,88 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/socionext,uniphier-glue-reset.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Socionext UniPhier peripheral core reset in glue layer
+
+description: |
+ Some peripheral core reset belongs to its own glue layer. Before using
+ this core reset, it is necessary to control the clocks and resets to
+ enable this layer. These clocks and resets should be described in each
+ property.
+
+maintainers:
+ - Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+properties:
+ compatible:
+ enum:
+ - socionext,uniphier-pro4-usb3-reset
+ - socionext,uniphier-pro5-usb3-reset
+ - socionext,uniphier-pxs2-usb3-reset
+ - socionext,uniphier-ld20-usb3-reset
+ - socionext,uniphier-pxs3-usb3-reset
+ - socionext,uniphier-pro4-ahci-reset
+ - socionext,uniphier-pxs2-ahci-reset
+ - socionext,uniphier-pxs3-ahci-reset
+
+ reg:
+ maxItems: 1
+
+ "#reset-cells":
+ const: 1
+
+ clocks:
+ minItems: 1
+ maxItems: 2
+
+ clock-names:
+ oneOf:
+ - items: # for Pro4, Pro5
+ - const: gio
+ - const: link
+ - items: # for others
+ - const: link
+
+ resets:
+ minItems: 1
+ maxItems: 2
+
+ reset-names:
+ oneOf:
+ - items: # for Pro4, Pro5
+ - const: gio
+ - const: link
+ - items: # for others
+ - const: link
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - "#reset-cells"
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+
+examples:
+ - |
+ usb-glue@65b00000 {
+ compatible = "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x65b00000 0x400>;
+
+ usb_rst: reset@0 {
+ compatible = "socionext,uniphier-ld20-usb3-reset";
+ reg = <0x0 0x4>;
+ #reset-cells = <1>;
+ clock-names = "link";
+ clocks = <&sys_clk 14>;
+ reset-names = "link";
+ resets = <&sys_rst 14>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/reset/uniphier-reset.txt b/Documentation/devicetree/bindings/reset/uniphier-reset.txt
deleted file mode 100644
index 88e06e5e8d23..000000000000
--- a/Documentation/devicetree/bindings/reset/uniphier-reset.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-UniPhier glue reset controller
-
-
-Peripheral core reset in glue layer
------------------------------------
-
-Some peripheral core reset belongs to its own glue layer. Before using
-this core reset, it is necessary to control the clocks and resets to enable
-this layer. These clocks and resets should be described in each property.
-
-Required properties:
-- compatible: Should be
- "socionext,uniphier-pro4-usb3-reset" - for Pro4 SoC USB3
- "socionext,uniphier-pro5-usb3-reset" - for Pro5 SoC USB3
- "socionext,uniphier-pxs2-usb3-reset" - for PXs2 SoC USB3
- "socionext,uniphier-ld20-usb3-reset" - for LD20 SoC USB3
- "socionext,uniphier-pxs3-usb3-reset" - for PXs3 SoC USB3
- "socionext,uniphier-pro4-ahci-reset" - for Pro4 SoC AHCI
- "socionext,uniphier-pxs2-ahci-reset" - for PXs2 SoC AHCI
- "socionext,uniphier-pxs3-ahci-reset" - for PXs3 SoC AHCI
-- #reset-cells: Should be 1.
-- reg: Specifies offset and length of the register set for the device.
-- clocks: A list of phandles to the clock gate for the glue layer.
- According to the clock-names, appropriate clocks are required.
-- clock-names: Should contain
- "gio", "link" - for Pro4 and Pro5 SoCs
- "link" - for others
-- resets: A list of phandles to the reset control for the glue layer.
- According to the reset-names, appropriate resets are required.
-- reset-names: Should contain
- "gio", "link" - for Pro4 and Pro5 SoCs
- "link" - for others
-
-Example:
-
- usb-glue@65b00000 {
- compatible = "socionext,uniphier-ld20-dwc3-glue",
- "simple-mfd";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 0x65b00000 0x400>;
-
- usb_rst: reset@0 {
- compatible = "socionext,uniphier-ld20-usb3-reset";
- reg = <0x0 0x4>;
- #reset-cells = <1>;
- clock-names = "link";
- clocks = <&sys_clk 14>;
- reset-names = "link";
- resets = <&sys_rst 14>;
- };
-
- regulator {
- ...
- };
-
- phy {
- ...
- };
- ...
- };
diff --git a/Documentation/devicetree/bindings/riscv/starfive.yaml b/Documentation/devicetree/bindings/riscv/starfive.yaml
new file mode 100644
index 000000000000..5b36243fd674
--- /dev/null
+++ b/Documentation/devicetree/bindings/riscv/starfive.yaml
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/riscv/starfive.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive SoC-based boards
+
+maintainers:
+ - Michael Zhu <michael.zhu@starfivetech.com>
+ - Drew Fustini <drew@beagleboard.org>
+
+description:
+ StarFive SoC-based boards
+
+properties:
+ $nodename:
+ const: '/'
+ compatible:
+ oneOf:
+ - items:
+ - const: beagle,beaglev-starlight-jh7100-r0
+ - const: starfive,jh7100
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/rng/mtk-rng.yaml b/Documentation/devicetree/bindings/rng/mtk-rng.yaml
index 61888e07bda0..bb32491ee8ae 100644
--- a/Documentation/devicetree/bindings/rng/mtk-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/mtk-rng.yaml
@@ -21,6 +21,7 @@ properties:
- enum:
- mediatek,mt7622-rng
- mediatek,mt7629-rng
+ - mediatek,mt7986-rng
- mediatek,mt8365-rng
- mediatek,mt8516-rng
- const: mediatek,mt7623-rng
diff --git a/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt b/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
deleted file mode 100644
index 5a613a4ec780..000000000000
--- a/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Exynos True Random Number Generator
-
-Required properties:
-
-- compatible : Should be "samsung,exynos5250-trng".
-- reg : Specifies base physical address and size of the registers map.
-- clocks : Phandle to clock-controller plus clock-specifier pair.
-- clock-names : "secss" as a clock name.
-
-Example:
-
- rng@10830600 {
- compatible = "samsung,exynos5250-trng";
- reg = <0x10830600 0x100>;
- clocks = <&clock CLK_SSS>;
- clock-names = "secss";
- };
diff --git a/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.yaml b/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.yaml
new file mode 100644
index 000000000000..a50c34d5d199
--- /dev/null
+++ b/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rng/samsung,exynos5250-trng.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos SoC True Random Number Generator
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+ - Łukasz Stelmach <l.stelmach@samsung.com>
+
+properties:
+ compatible:
+ const: samsung,exynos5250-trng
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: secss
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/exynos5250.h>
+
+ rng@10830600 {
+ compatible = "samsung,exynos5250-trng";
+ reg = <0x10830600 0x100>;
+ clocks = <&clock CLK_SSS>;
+ clock-names = "secss";
+ };
diff --git a/Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml b/Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml
index a2c55303810d..9593840a4a2b 100644
--- a/Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml
+++ b/Documentation/devicetree/bindings/rtc/microcrystal,rv3032.yaml
@@ -53,7 +53,6 @@ examples:
rtc@51 {
compatible = "microcrystal,rv3032";
reg = <0x51>;
- status = "okay";
pinctrl-0 = <&rtc_nint_pins>;
interrupts-extended = <&gpio1 16 IRQ_TYPE_LEVEL_HIGH>;
trickle-resistor-ohms = <7000>;
diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml
index a0bf061b80fe..fa767440f281 100644
--- a/Documentation/devicetree/bindings/serial/8250.yaml
+++ b/Documentation/devicetree/bindings/serial/8250.yaml
@@ -66,6 +66,12 @@ properties:
- const: nxp,lpc3220-uart
- items:
- enum:
+ - exar,xr16l2552
+ - exar,xr16l2551
+ - exar,xr16l2550
+ - const: ns8250
+ - items:
+ - enum:
- altr,16550-FIFO32
- altr,16550-FIFO64
- altr,16550-FIFO128
diff --git a/Documentation/devicetree/bindings/serial/8250_omap.yaml b/Documentation/devicetree/bindings/serial/8250_omap.yaml
index 1c826fcf5828..70ca61688bb9 100644
--- a/Documentation/devicetree/bindings/serial/8250_omap.yaml
+++ b/Documentation/devicetree/bindings/serial/8250_omap.yaml
@@ -79,6 +79,7 @@ properties:
power-domains: true
clock-frequency: true
current-speed: true
+ overrun-throttle-ms: true
required:
- compatible
@@ -90,10 +91,11 @@ additionalProperties: false
if:
properties:
compatible:
- oneOf:
- - const: ti,omap2-uart
- - const: ti,omap3-uart
- - const: ti,omap4-uart
+ contains:
+ enum:
+ - ti,omap2-uart
+ - ti,omap3-uart
+ - ti,omap4-uart
then:
properties:
diff --git a/Documentation/devicetree/bindings/serial/cdns,uart.txt b/Documentation/devicetree/bindings/serial/cdns,uart.txt
deleted file mode 100644
index 4efc560f90ab..000000000000
--- a/Documentation/devicetree/bindings/serial/cdns,uart.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-Binding for Cadence UART Controller
-
-Required properties:
-- compatible :
- Use "xlnx,xuartps","cdns,uart-r1p8" for Zynq-7xxx SoC.
- Use "xlnx,zynqmp-uart","cdns,uart-r1p12" for Zynq Ultrascale+ MPSoC.
-- reg: Should contain UART controller registers location and length.
-- interrupts: Should contain UART controller interrupts.
-- clocks: Must contain phandles to the UART clocks
- See ../clocks/clock-bindings.txt for details.
-- clock-names: Tuple to identify input clocks, must contain "uart_clk" and "pclk"
- See ../clocks/clock-bindings.txt for details.
-
-
-Optional properties:
-- cts-override : Override the CTS modem status signal. This signal will
- always be reported as active instead of being obtained from the modem status
- register. Define this if your serial port does not use this pin
-
-Example:
- uart@e0000000 {
- compatible = "cdns,uart-r1p8";
- clocks = <&clkc 23>, <&clkc 40>;
- clock-names = "uart_clk", "pclk";
- reg = <0xE0000000 0x1000>;
- interrupts = <0 27 4>;
- };
diff --git a/Documentation/devicetree/bindings/serial/cdns,uart.yaml b/Documentation/devicetree/bindings/serial/cdns,uart.yaml
new file mode 100644
index 000000000000..fcdbe6f87e98
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/cdns,uart.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/cdns,uart.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cadence UART Controller Device Tree Bindings
+
+maintainers:
+ - Michal Simek <michal.simek@xilinx.com>
+
+allOf:
+ - $ref: /schemas/serial.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - description: UART controller for Zynq-7xxx SoC
+ items:
+ - const: xlnx,xuartps
+ - const: cdns,uart-r1p8
+ - description: UART controller for Zynq Ultrascale+ MPSoC
+ items:
+ - const: xlnx,zynqmp-uart
+ - const: cdns,uart-r1p12
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: uart_clk
+ - const: pclk
+
+ cts-override:
+ description: |
+ Override the CTS modem status signal. This signal will
+ always be reported as active instead of being obtained
+ from the modem status register. Define this if your serial
+ port does not use this pin.
+ type: boolean
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ uart0: serial@e0000000 {
+ compatible = "xlnx,xuartps", "cdns,uart-r1p8";
+ clocks = <&clkc 23>, <&clkc 40>;
+ clock-names = "uart_clk", "pclk";
+ reg = <0xE0000000 0x1000>;
+ interrupts = <0 27 4>;
+ };
diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt
index 64c4fb59acd1..b3a0bfef0d54 100644
--- a/Documentation/devicetree/bindings/serial/mtk-uart.txt
+++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt
@@ -15,6 +15,7 @@ Required properties:
* "mediatek,mt7622-uart" for MT7622 compatible UARTS
* "mediatek,mt7623-uart" for MT7623 compatible UARTS
* "mediatek,mt7629-uart" for MT7629 compatible UARTS
+ * "mediatek,mt7986-uart", "mediatek,mt6577-uart" for MT7986 compatible UARTS
* "mediatek,mt8127-uart" for MT8127 compatible UARTS
* "mediatek,mt8135-uart" for MT8135 compatible UARTS
* "mediatek,mt8173-uart" for MT8173 compatible UARTS
diff --git a/Documentation/devicetree/bindings/soc/litex/litex,soc-controller.yaml b/Documentation/devicetree/bindings/soc/litex/litex,soc-controller.yaml
index c8b57c7fd08c..ecae9fa8561b 100644
--- a/Documentation/devicetree/bindings/soc/litex/litex,soc-controller.yaml
+++ b/Documentation/devicetree/bindings/soc/litex/litex,soc-controller.yaml
@@ -35,7 +35,6 @@ examples:
soc_ctrl0: soc-controller@f0000000 {
compatible = "litex,soc-controller";
reg = <0xf0000000 0xc>;
- status = "okay";
};
...
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt
deleted file mode 100644
index 783dc81b0f26..000000000000
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-Qualcomm Always-On Subsystem side channel binding
-
-This binding describes the hardware component responsible for side channel
-requests to the always-on subsystem (AOSS), used for certain power management
-requests that is not handled by the standard RPMh interface. Each client in the
-SoC has it's own block of message RAM and IRQ for communication with the AOSS.
-The protocol used to communicate in the message RAM is known as Qualcomm
-Messaging Protocol (QMP)
-
-The AOSS side channel exposes control over a set of resources, used to control
-a set of debug related clocks and to affect the low power state of resources
-related to the secondary subsystems. These resources are exposed as a set of
-power-domains.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be one of:
- "qcom,sc7180-aoss-qmp"
- "qcom,sc7280-aoss-qmp"
- "qcom,sdm845-aoss-qmp"
- "qcom,sm8150-aoss-qmp"
- "qcom,sm8250-aoss-qmp"
- "qcom,sm8350-aoss-qmp"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the message RAM for this
- client's communication with the AOSS
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the AOSS message IRQ for this client
-
-- mboxes:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: reference to the mailbox representing the outgoing doorbell
- in APCS for this client, as described in mailbox/mailbox.txt
-
-- #clock-cells:
- Usage: optional
- Value type: <u32>
- Definition: must be 0
- The single clock represents the QDSS clock.
-
-- #power-domain-cells:
- Usage: optional
- Value type: <u32>
- Definition: must be 1
- The provided power-domains are:
- CDSP state (0), LPASS state (1), modem state (2), SLPI
- state (3), SPSS state (4) and Venus state (5).
-
-= SUBNODES
-The AOSS side channel also provides the controls for three cooling devices,
-these are expressed as subnodes of the QMP node. The name of the node is used
-to identify the resource and must therefor be "cx", "mx" or "ebi".
-
-- #cooling-cells:
- Usage: optional
- Value type: <u32>
- Definition: must be 2
-
-= EXAMPLE
-
-The following example represents the AOSS side-channel message RAM and the
-mechanism exposing the power-domains, as found in SDM845.
-
- aoss_qmp: qmp@c300000 {
- compatible = "qcom,sdm845-aoss-qmp";
- reg = <0x0c300000 0x100000>;
- interrupts = <GIC_SPI 389 IRQ_TYPE_EDGE_RISING>;
- mboxes = <&apss_shared 0>;
-
- #power-domain-cells = <1>;
-
- cx_cdev: cx {
- #cooling-cells = <2>;
- };
-
- mx_cdev: mx {
- #cooling-cells = <2>;
- };
- };
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
new file mode 100644
index 000000000000..93e4b737ee1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/qcom/qcom,aoss-qmp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Always-On Subsystem side channel binding
+
+maintainers:
+ - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description:
+ This binding describes the hardware component responsible for side channel
+ requests to the always-on subsystem (AOSS), used for certain power management
+ requests that is not handled by the standard RPMh interface. Each client in the
+ SoC has it's own block of message RAM and IRQ for communication with the AOSS.
+ The protocol used to communicate in the message RAM is known as Qualcomm
+ Messaging Protocol (QMP)
+
+ The AOSS side channel exposes control over a set of resources, used to control
+ a set of debug related clocks and to affect the low power state of resources
+ related to the secondary subsystems. These resources are exposed as a set of
+ power-domains.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - qcom,sc7180-aoss-qmp
+ - qcom,sc7280-aoss-qmp
+ - qcom,sc8180x-aoss-qmp
+ - qcom,sdm845-aoss-qmp
+ - qcom,sm8150-aoss-qmp
+ - qcom,sm8250-aoss-qmp
+ - qcom,sm8350-aoss-qmp
+ - const: qcom,aoss-qmp
+
+ reg:
+ maxItems: 1
+ description:
+ The base address and size of the message RAM for this client's
+ communication with the AOSS
+
+ interrupts:
+ maxItems: 1
+ description:
+ Should specify the AOSS message IRQ for this client
+
+ mboxes:
+ maxItems: 1
+ description:
+ Reference to the mailbox representing the outgoing doorbell in APCS for
+ this client, as described in mailbox/mailbox.txt
+
+ "#clock-cells":
+ const: 0
+ description:
+ The single clock represents the QDSS clock.
+
+ "#power-domain-cells":
+ const: 1
+ description: |
+ The provided power-domains are:
+ CDSP state (0), LPASS state (1), modem state (2), SLPI
+ state (3), SPSS state (4) and Venus state (5).
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - mboxes
+ - "#clock-cells"
+
+additionalProperties: false
+
+patternProperties:
+ "^(cx|mx|ebi)$":
+ type: object
+ description:
+ The AOSS side channel also provides the controls for three cooling devices,
+ these are expressed as subnodes of the QMP node. The name of the node is
+ used to identify the resource and must therefor be "cx", "mx" or "ebi".
+
+ properties:
+ "#cooling-cells":
+ const: 2
+
+ required:
+ - "#cooling-cells"
+
+ additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ aoss_qmp: qmp@c300000 {
+ compatible = "qcom,sdm845-aoss-qmp", "qcom,aoss-qmp";
+ reg = <0x0c300000 0x100000>;
+ interrupts = <GIC_SPI 389 IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&apss_shared 0>;
+
+ #clock-cells = <0>;
+ #power-domain-cells = <1>;
+
+ cx_cdev: cx {
+ #cooling-cells = <2>;
+ };
+
+ mx_cdev: mx {
+ #cooling-cells = <2>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml
index 4663c2bcad50..a776cd37c297 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml
@@ -51,6 +51,9 @@ properties:
interconnect-names:
const: qup-core
+ iommus:
+ maxItems: 1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
index d511f01fcac6..cc3fe5ed7421 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
@@ -39,6 +39,7 @@ properties:
- qcom,rpm-msm8996
- qcom,rpm-msm8998
- qcom,rpm-sdm660
+ - qcom,rpm-sm6115
- qcom,rpm-sm6125
- qcom,rpm-qcs404
diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
index 62fa72cfea34..dfebf425ca49 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
@@ -15,7 +15,6 @@ properties:
- items:
- enum:
- rockchip,rk3288-sgrf
- - rockchip,rv1108-pmugrf
- rockchip,rv1108-usbgrf
- const: syscon
- items:
@@ -41,6 +40,7 @@ properties:
- rockchip,rk3568-grf
- rockchip,rk3568-pmugrf
- rockchip,rv1108-grf
+ - rockchip,rv1108-pmugrf
- const: syscon
- const: simple-mfd
@@ -198,21 +198,28 @@ allOf:
compatible:
contains:
enum:
- - rockchip,px30-pmugrf
- rockchip,px30-grf
+ - rockchip,px30-pmugrf
+ - rockchip,rk3188-grf
- rockchip,rk3228-grf
- rockchip,rk3288-grf
- rockchip,rk3328-grf
- - rockchip,rk3368-pmugrf
- rockchip,rk3368-grf
- - rockchip,rk3399-pmugrf
+ - rockchip,rk3368-pmugrf
- rockchip,rk3399-grf
+ - rockchip,rk3399-pmugrf
+ - rockchip,rk3568-pmugrf
+ - rockchip,rv1108-grf
+ - rockchip,rv1108-pmugrf
then:
properties:
io-domains:
- description:
- Documentation/devicetree/bindings/power/rockchip-io-domain.txt
+ type: object
+
+ $ref: "/schemas/power/rockchip-io-domain.yaml#"
+
+ unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml
index 9790617af1bc..9d128b9e7deb 100644
--- a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml
+++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml
@@ -68,6 +68,7 @@ properties:
- ti,k2g-pruss # for 66AK2G SoC family
- ti,am654-icssg # for K3 AM65x SoC family
- ti,j721e-icssg # for K3 J721E SoC family
+ - ti,am642-icssg # for K3 AM64x SoC family
reg:
maxItems: 1
@@ -84,6 +85,8 @@ properties:
dma-ranges:
maxItems: 1
+ dma-coherent: true
+
power-domains:
description: |
This property is as per sci-pm-domain.txt.
@@ -231,8 +234,8 @@ patternProperties:
description: |
Industrial Ethernet Peripheral to manage/generate Industrial Ethernet
functions such as time stamping. Each PRUSS has either 1 IEP (on AM335x,
- AM437x, AM57xx & 66AK2G SoCs) or 2 IEPs (on K3 AM65x & J721E SoCs ). IEP
- is used for creating PTP clocks and generating PPS signals.
+ AM437x, AM57xx & 66AK2G SoCs) or 2 IEPs (on K3 AM65x, J721E & AM64x SoCs).
+ IEP is used for creating PTP clocks and generating PPS signals.
type: object
@@ -323,17 +326,29 @@ additionalProperties: false
# - interrupt-controller
# - pru
-if:
- properties:
- compatible:
- contains:
- enum:
- - ti,k2g-pruss
- - ti,am654-icssg
- - ti,j721e-icssg
-then:
- required:
- - power-domains
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - ti,k2g-pruss
+ - ti,am654-icssg
+ - ti,j721e-icssg
+ - ti,am642-icssg
+ then:
+ required:
+ - power-domains
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - ti,k2g-pruss
+ then:
+ required:
+ - dma-coherent
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
index c483dcec01f8..bd863bd69501 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
@@ -6,6 +6,7 @@ Required properties:
"ti,da830-mcasp-audio" : for both DA830 & DA850 platforms
"ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, AM43xx, TI81xx)
"ti,dra7-mcasp-audio" : for DRA7xx platforms
+ "ti,omap4-mcasp-audio" : for OMAP4
- reg : Should contain reg specifiers for the entries in the reg-names property.
- reg-names : Should contain:
diff --git a/Documentation/devicetree/bindings/sound/ics43432.txt b/Documentation/devicetree/bindings/sound/ics43432.txt
index b02e3a6c0fef..e6f05f2f6c4e 100644
--- a/Documentation/devicetree/bindings/sound/ics43432.txt
+++ b/Documentation/devicetree/bindings/sound/ics43432.txt
@@ -1,4 +1,4 @@
-Invensense ICS-43432 MEMS microphone with I2S output.
+Invensense ICS-43432-compatible MEMS microphone with I2S output.
There are no software configuration options for this device, indeed, the only
host connection is the I2S interface. Apart from requirements on clock
@@ -8,7 +8,9 @@ contain audio data. A hardware pin determines if the device outputs data
on the left or right channel of the I2S frame.
Required properties:
- - compatible : Must be "invensense,ics43432"
+ - compatible: should be one of the following.
+ "invensense,ics43432": For the Invensense ICS43432
+ "cui,cmm-4030d-261": For the CUI CMM-4030D-261-I2S-TR
Example:
diff --git a/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
new file mode 100644
index 000000000000..53e9434a6d9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
@@ -0,0 +1,184 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8195-afe-pcm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek AFE PCM controller for mt8195
+
+maintainers:
+ - Trevor Wu <trevor.wu@mediatek.com>
+
+properties:
+ compatible:
+ const: mediatek,mt8195-audio
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ mediatek,topckgen:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of the mediatek topckgen controller
+
+ power-domains:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: 26M clock
+ - description: audio pll1 clock
+ - description: audio pll2 clock
+ - description: clock divider for i2si1_mck
+ - description: clock divider for i2si2_mck
+ - description: clock divider for i2so1_mck
+ - description: clock divider for i2so2_mck
+ - description: clock divider for dptx_mck
+ - description: a1sys hoping clock
+ - description: audio intbus clock
+ - description: audio hires clock
+ - description: audio local bus clock
+ - description: mux for dptx_mck
+ - description: mux for i2so1_mck
+ - description: mux for i2so2_mck
+ - description: mux for i2si1_mck
+ - description: mux for i2si2_mck
+ - description: audio infra 26M clock
+ - description: infra bus clock
+
+ clock-names:
+ items:
+ - const: clk26m
+ - const: apll1_ck
+ - const: apll2_ck
+ - const: apll12_div0
+ - const: apll12_div1
+ - const: apll12_div2
+ - const: apll12_div3
+ - const: apll12_div9
+ - const: a1sys_hp_sel
+ - const: aud_intbus_sel
+ - const: audio_h_sel
+ - const: audio_local_bus_sel
+ - const: dptx_m_sel
+ - const: i2so1_m_sel
+ - const: i2so2_m_sel
+ - const: i2si1_m_sel
+ - const: i2si2_m_sel
+ - const: infra_ao_audio_26m_b
+ - const: scp_adsp_audiodsp
+
+ mediatek,etdm-in1-chn-disabled:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ maxItems: 24
+ description: Specify which input channel should be disabled.
+
+ mediatek,etdm-in2-chn-disabled:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ maxItems: 16
+ description: Specify which input channel should be disabled.
+
+patternProperties:
+ "^mediatek,etdm-in[1-2]-mclk-always-on-rate-hz$":
+ description: Specify etdm in mclk output rate for always on case.
+
+ "^mediatek,etdm-out[1-3]-mclk-always-on-rate-hz$":
+ description: Specify etdm out mclk output rate for always on case.
+
+ "^mediatek,etdm-in[1-2]-multi-pin-mode$":
+ type: boolean
+ description: if present, the etdm data mode is I2S.
+
+ "^mediatek,etdm-out[1-3]-multi-pin-mode$":
+ type: boolean
+ description: if present, the etdm data mode is I2S.
+
+ "^mediatek,etdm-in[1-2]-cowork-source$":
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ etdm modules can share the same external clock pin. Specify
+ which etdm clock source is required by this etdm in moudule.
+ enum:
+ - 0 # etdm1_in
+ - 1 # etdm2_in
+ - 2 # etdm1_out
+ - 3 # etdm2_out
+
+ "^mediatek,etdm-out[1-2]-cowork-source$":
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ etdm modules can share the same external clock pin. Specify
+ which etdm clock source is required by this etdm out moudule.
+ enum:
+ - 0 # etdm1_in
+ - 1 # etdm2_in
+ - 2 # etdm1_out
+ - 3 # etdm2_out
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - mediatek,topckgen
+ - power-domains
+ - clocks
+ - clock-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8195-clk.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/power/mt8195-power.h>
+
+ afe: mt8195-afe-pcm@10890000 {
+ compatible = "mediatek,mt8195-audio";
+ reg = <0x10890000 0x10000>;
+ interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
+ mediatek,topckgen = <&topckgen>;
+ power-domains = <&spm MT8195_POWER_DOMAIN_AUDIO>;
+ clocks = <&clk26m>,
+ <&topckgen CLK_TOP_APLL1>,
+ <&topckgen CLK_TOP_APLL2>,
+ <&topckgen CLK_TOP_APLL12_DIV0>,
+ <&topckgen CLK_TOP_APLL12_DIV1>,
+ <&topckgen CLK_TOP_APLL12_DIV2>,
+ <&topckgen CLK_TOP_APLL12_DIV3>,
+ <&topckgen CLK_TOP_APLL12_DIV9>,
+ <&topckgen CLK_TOP_A1SYS_HP_SEL>,
+ <&topckgen CLK_TOP_AUD_INTBUS_SEL>,
+ <&topckgen CLK_TOP_AUDIO_H_SEL>,
+ <&topckgen CLK_TOP_AUDIO_LOCAL_BUS_SEL>,
+ <&topckgen CLK_TOP_DPTX_M_SEL>,
+ <&topckgen CLK_TOP_I2SO1_M_SEL>,
+ <&topckgen CLK_TOP_I2SO2_M_SEL>,
+ <&topckgen CLK_TOP_I2SI1_M_SEL>,
+ <&topckgen CLK_TOP_I2SI2_M_SEL>,
+ <&infracfg_ao CLK_INFRA_AO_AUDIO_26M_B>,
+ <&scp_adsp CLK_SCP_ADSP_AUDIODSP>;
+ clock-names = "clk26m",
+ "apll1_ck",
+ "apll2_ck",
+ "apll12_div0",
+ "apll12_div1",
+ "apll12_div2",
+ "apll12_div3",
+ "apll12_div9",
+ "a1sys_hp_sel",
+ "aud_intbus_sel",
+ "audio_h_sel",
+ "audio_local_bus_sel",
+ "dptx_m_sel",
+ "i2so1_m_sel",
+ "i2so2_m_sel",
+ "i2si1_m_sel",
+ "i2si2_m_sel",
+ "infra_ao_audio_26m_b",
+ "scp_adsp_audiodsp";
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml
new file mode 100644
index 000000000000..20bc0ffd0e34
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8195-mt6359-rt1019-rt5682.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8195 with MT6359, RT1019 and RT5682 ASoC sound card driver
+
+maintainers:
+ - Trevor Wu <trevor.wu@mediatek.com>
+
+description:
+ This binding describes the MT8195 sound card.
+
+properties:
+ compatible:
+ const: mediatek,mt8195_mt6359_rt1019_rt5682
+
+ mediatek,platform:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of MT8195 ASoC platform.
+
+ mediatek,dptx-codec:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of MT8195 Display Port Tx codec node.
+
+ mediatek,hdmi-codec:
+ $ref: "/schemas/types.yaml#/definitions/phandle"
+ description: The phandle of MT8195 HDMI codec node.
+
+additionalProperties: false
+
+required:
+ - compatible
+ - mediatek,platform
+
+examples:
+ - |
+
+ sound: mt8195-sound {
+ compatible = "mediatek,mt8195_mt6359_rt1019_rt5682";
+ mediatek,platform = <&afe>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&aud_pins_default>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
index 72ad9ab91832..7d57eb91657a 100644
--- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
@@ -15,9 +15,9 @@ description:
properties:
compatible:
- oneOf:
- - const: qcom,sm8250-sndcard
- - const: qcom,qrb5165-rb5-sndcard
+ enum:
+ - qcom,sm8250-sndcard
+ - qcom,qrb5165-rb5-sndcard
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
diff --git a/Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml b/Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml
index 644b68edf3e1..fdb7f295ef2d 100644
--- a/Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml
+++ b/Documentation/devicetree/bindings/sound/realtek,rt1015p.yaml
@@ -15,7 +15,9 @@ description: |
properties:
compatible:
- const: realtek,rt1015p
+ enum:
+ - realtek,rt1015p
+ - realtek,rt1019p
sdb-gpios:
description:
diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
new file mode 100644
index 000000000000..414ff8035a4e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/renesas,rz-ssi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L ASoC Sound Serial Interface (SSIF-2)
+
+maintainers:
+ - Biju Das <biju.das.jz@bp.renesas.com>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a07g044-ssi # RZ/G2{L,LC}
+ - const: renesas,rz-ssi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 4
+
+ interrupt-names:
+ items:
+ - const: int_req
+ - const: dma_rx
+ - const: dma_tx
+ - const: dma_rt
+
+ clocks:
+ maxItems: 4
+
+ clock-names:
+ items:
+ - const: ssi
+ - const: ssi_sfr
+ - const: audio_clk1
+ - const: audio_clk2
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ dmas:
+ minItems: 1
+ maxItems: 2
+ description:
+ The first cell represents a phandle to dmac
+ The second cell specifies the encoded MID/RID values of the SSI port
+ connected to the DMA client and the slave channel configuration
+ parameters.
+ bits[0:9] - Specifies MID/RID value of a SSI channel as below
+ MID/RID value of SSI rx0 = 0x256
+ MID/RID value of SSI tx0 = 0x255
+ MID/RID value of SSI rx1 = 0x25a
+ MID/RID value of SSI tx1 = 0x259
+ MID/RID value of SSI rt2 = 0x25f
+ MID/RID value of SSI rx3 = 0x262
+ MID/RID value of SSI tx3 = 0x261
+ bit[10] - HIEN = 1, Detects a request in response to the rising edge
+ of the signal
+ bit[11] - LVL = 0, Detects based on the edge
+ bits[12:14] - AM = 2, Bus cycle mode
+ bit[15] - TM = 0, Single transfer mode
+
+ dma-names:
+ oneOf:
+ - items:
+ - const: tx
+ - const: rx
+ - items:
+ - const: rt
+
+ '#sound-dai-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - resets
+ - '#sound-dai-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+
+ ssi0: ssi@10049c00 {
+ compatible = "renesas,r9a07g044-ssi",
+ "renesas,rz-ssi";
+ reg = <0x10049c00 0x400>;
+ interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
+ clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
+ <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
+ <&audio_clk1>,
+ <&audio_clk2>;
+ clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
+ dmas = <&dmac 0x2655>,
+ <&dmac 0x2656>;
+ dma-names = "tx", "rx";
+ #sound-dai-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
index 245895b58a2f..5ea16b8ef93f 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
@@ -20,7 +20,9 @@ properties:
- items:
- enum:
- rockchip,px30-i2s
+ - rockchip,rk1808-i2s
- rockchip,rk3036-i2s
+ - rockchip,rk3128-i2s
- rockchip,rk3188-i2s
- rockchip,rk3228-i2s
- rockchip,rk3288-i2s
@@ -29,6 +31,7 @@ properties:
- rockchip,rk3366-i2s
- rockchip,rk3368-i2s
- rockchip,rk3399-i2s
+ - rockchip,rv1126-i2s
- const: rockchip,rk3066-i2s
reg:
@@ -61,6 +64,14 @@ properties:
power-domains:
maxItems: 1
+ reset-names:
+ items:
+ - const: reset-m
+ - const: reset-h
+
+ resets:
+ maxItems: 2
+
rockchip,capture-channels:
$ref: /schemas/types.yaml#/definitions/uint32
default: 2
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
index 62a61b68dfef..d0a24bf928d6 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
@@ -23,6 +23,7 @@ properties:
- const: rockchip,rk3366-spdif
- const: rockchip,rk3368-spdif
- const: rockchip,rk3399-spdif
+ - const: rockchip,rk3568-spdif
- items:
- enum:
- rockchip,rk3188-spdif
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
index 06e83461705c..f97132400bb6 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
@@ -180,7 +180,6 @@ examples:
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>;
pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>;
- status = "okay";
sai2a: audio-controller@4400b004 {
#sound-dai-cells = <0>;
@@ -190,7 +189,6 @@ examples:
dma-names = "tx";
clocks = <&rcc SAI2_K>;
clock-names = "sai_ck";
- status = "okay";
};
};
diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml
index ec06789b21df..6806f53a4aed 100644
--- a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml
@@ -127,8 +127,6 @@ examples:
compatible = "ti,j721e-cpb-audio";
model = "j721e-cpb";
- status = "okay";
-
ti,cpb-mcasp = <&mcasp10>;
ti,cpb-codec = <&pcm3168a_1>;
diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml
index ee9f960de36b..859d369c71e2 100644
--- a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml
@@ -119,8 +119,6 @@ examples:
compatible = "ti,j721e-cpb-ivi-audio";
model = "j721e-cpb-ivi";
- status = "okay";
-
ti,cpb-mcasp = <&mcasp10>;
ti,cpb-codec = <&pcm3168a_1>;
diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
index 54d64785aad2..d77c8283526d 100644
--- a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
+++ b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
@@ -24,10 +24,10 @@ description: |
properties:
compatible:
- oneOf:
- - const: ti,tlv320adc3140
- - const: ti,tlv320adc5140
- - const: ti,tlv320adc6140
+ enum:
+ - ti,tlv320adc3140
+ - ti,tlv320adc5140
+ - ti,tlv320adc6140
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml b/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml
index 30a62a211984..2f938c293f70 100644
--- a/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml
@@ -15,12 +15,12 @@ allOf:
properties:
compatible:
- oneOf:
- - const: realtek,rtl8380-spi
- - const: realtek,rtl8382-spi
- - const: realtek,rtl8391-spi
- - const: realtek,rtl8392-spi
- - const: realtek,rtl8393-spi
+ enum:
+ - realtek,rtl8380-spi
+ - realtek,rtl8382-spi
+ - realtek,rtl8391-spi
+ - realtek,rtl8392-spi
+ - realtek,rtl8393-spi
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
index 4a2eaf28e3fd..d3b9e9b600a2 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
@@ -48,6 +48,7 @@ properties:
- qcom,sc7180-tsens
- qcom,sc7280-tsens
- qcom,sc8180x-tsens
+ - qcom,sdm630-tsens
- qcom,sdm845-tsens
- qcom,sm8150-tsens
- qcom,sm8250-tsens
diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.yaml b/Documentation/devicetree/bindings/timer/arm,sp804.yaml
index 960e2bd66a97..41be7cdab2ec 100644
--- a/Documentation/devicetree/bindings/timer/arm,sp804.yaml
+++ b/Documentation/devicetree/bindings/timer/arm,sp804.yaml
@@ -23,9 +23,9 @@ select:
properties:
compatible:
contains:
- oneOf:
- - const: arm,sp804
- - const: hisilicon,sp804
+ enum:
+ - arm,sp804
+ - hisilicon,sp804
required:
- compatible
diff --git a/Documentation/devicetree/bindings/timer/energymicro,efm32-timer.txt b/Documentation/devicetree/bindings/timer/energymicro,efm32-timer.txt
deleted file mode 100644
index e502c11b2211..000000000000
--- a/Documentation/devicetree/bindings/timer/energymicro,efm32-timer.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-* EFM32 timer hardware
-
-The efm32 Giant Gecko SoCs come with four 16 bit timers. Two counters can be
-connected to form a 32 bit counter. Each timer has three Compare/Capture
-channels and can be used as PWM or Quadrature Decoder. Available clock sources
-are the cpu's HFPERCLK (with a 10-bit prescaler) or an external pin.
-
-Required properties:
-- compatible : Should be "energymicro,efm32-timer"
-- reg : Address and length of the register set
-- clocks : Should contain a reference to the HFPERCLK
-
-Optional properties:
-- interrupts : Reference to the timer interrupt
-
-Example:
-
-timer@40010c00 {
- compatible = "energymicro,efm32-timer";
- reg = <0x40010c00 0x400>;
- interrupts = <14>;
- clocks = <&cmu clk_HFPERCLKTIMER3>;
-};
diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml
index 919a4bf03a5a..1e4b3464d734 100644
--- a/Documentation/devicetree/bindings/trivial-devices.yaml
+++ b/Documentation/devicetree/bindings/trivial-devices.yaml
@@ -33,6 +33,8 @@ properties:
- ad,ad7414
# ADM9240: Complete System Hardware Monitor for uProcessor-Based Systems
- ad,adm9240
+ # AD5110 - Nonvolatile Digital Potentiometer
+ - adi,ad5110
# Analog Devices ADP5585 Keypad Decoder and I/O Expansion
- adi,adp5585
# Analog Devices ADP5585 Keypad Decoder and I/O Expansion with support for Row5
@@ -61,6 +63,8 @@ properties:
- capella,cm32181
# CM3232: Ambient Light Sensor
- capella,cm3232
+ # CM3323: Ambient Light Sensor
+ - capella,cm3323
# High-Precision Digital Thermometer
- dallas,ds1631
# Total-Elapsed-Time Recorder with Alarm
@@ -143,6 +147,8 @@ properties:
- maxim,ds1803-100
# Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
- maxim,max1237
+ # Temperature Sensor, I2C interface
+ - maxim,max1619
# 10-bit 10 kOhm linear programable voltage divider
- maxim,max5481
# 10-bit 50 kOhm linear programable voltage divider
@@ -269,6 +275,8 @@ properties:
- sensirion,sgpc3
# Sensirion multi-pixel gas sensor with I2C interface
- sensirion,sgp30
+ # Sensirion gas sensor with I2C interface
+ - sensirion,sgp40
# Sensortek 3 axis accelerometer
- sensortek,stk8312
# Sensortek 3 axis accelerometer
diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
index 8089dc956ba3..8913497624de 100644
--- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
@@ -34,6 +34,7 @@ properties:
- allwinner,sun6i-a31-ehci
- allwinner,sun7i-a20-ehci
- allwinner,sun8i-a23-ehci
+ - allwinner,sun8i-a83t-ehci
- allwinner,sun8i-h3-ehci
- allwinner,sun8i-r40-ehci
- allwinner,sun9i-a80-ehci
@@ -142,6 +143,11 @@ properties:
iommus:
maxItems: 1
+ dr_mode:
+ enum:
+ - host
+ - otg
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
index 0f5f6ea702d0..acbf94fa5f74 100644
--- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
@@ -24,6 +24,7 @@ properties:
- allwinner,sun6i-a31-ohci
- allwinner,sun7i-a20-ohci
- allwinner,sun8i-a23-ohci
+ - allwinner,sun8i-a83t-ohci
- allwinner,sun8i-h3-ohci
- allwinner,sun8i-r40-ohci
- allwinner,sun9i-a80-ohci
@@ -109,6 +110,11 @@ properties:
iommus:
maxItems: 1
+ dr_mode:
+ enum:
+ - host
+ - otg
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
index 240882b12565..11f7bacd4e2b 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
@@ -31,6 +31,7 @@ properties:
- mediatek,mt8173-xhci
- mediatek,mt8183-xhci
- mediatek,mt8192-xhci
+ - mediatek,mt8195-xhci
- const: mediatek,mtk-xhci
reg:
@@ -152,6 +153,11 @@ properties:
description: The mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc
+ mediatek,u2p-dis-msk:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: The mask to disable u2ports, bit0 for u2port0,
+ bit1 for u2port1, ... etc
+
"#address-cells":
const: 1
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
index dbc7876e0a0b..77db1233516e 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
@@ -38,7 +38,18 @@ properties:
- const: ippc
interrupts:
- maxItems: 1
+ description:
+ use "interrupts-extended" when the interrupts are connected to the
+ separate interrupt controllers
+ minItems: 1
+ items:
+ - description: SSUSB device controller interrupt
+ - description: optional, wakeup interrupt used to support runtime PM
+
+ interrupt-names:
+ items:
+ - const: device
+ - const: wakeup
power-domains:
description: A phandle to USB power domain node to control USB's MTCMOS
@@ -106,7 +117,7 @@ properties:
extcon:
deprecated: true
description: |
- Phandle to the extcon device detecting the IDDIG/VBUS state, neede
+ Phandle to the extcon device detecting the IDDIG state, needed
when supports dual-role mode.
It's considered valid for compatibility reasons, not allowed for
new bindings, and use "usb-role-switch" property instead.
@@ -116,6 +127,10 @@ properties:
description: Support role switch.
type: boolean
+ role-switch-default-mode:
+ enum: [host, peripheral]
+ default: host
+
connector:
$ref: /connector/usb-connector.yaml#
description:
@@ -166,6 +181,12 @@ properties:
description: The mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc
+ mediatek,u2p-dis-msk:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: The mask to disable u2ports, bit0 for u2port0,
+ bit1 for u2port1, ... etc; but can't disable u2port0 if dual role mode
+ is enabled, so will be skipped in this case.
+
# Required child node when support dual-role
patternProperties:
"^usb@[0-9a-f]+$":
@@ -178,6 +199,7 @@ patternProperties:
dependencies:
connector: [ 'usb-role-switch' ]
port: [ 'usb-role-switch' ]
+ role-switch-default-mode: [ 'usb-role-switch' ]
wakeup-source: [ 'mediatek,syscon-wakeup' ]
required:
@@ -230,7 +252,7 @@ examples:
};
};
- # Enable/disable device by an input gpio for VBUS pin
+ # Dual role switch by gpio-usb-b-connector
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power/mt2712-power.h>
@@ -244,13 +266,27 @@ examples:
power-domains = <&scpsys MT2712_POWER_DOMAIN_USB2>;
clocks = <&topckgen CLK_TOP_USB30_SEL>;
clock-names = "sys_ck";
- dr_mode = "peripheral";
+ dr_mode = "otg";
usb-role-switch;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ host0: usb@11270000 {
+ compatible = "mediatek,mt2712-xhci", "mediatek,mtk-xhci";
+ reg = <0x11270000 0x1000>;
+ reg-names = "mac";
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&scpsys MT2712_POWER_DOMAIN_USB>;
+ clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
+ clock-names = "sys_ck", "ref_ck";
+ };
connector {
compatible = "gpio-usb-b-connector", "usb-b-connector";
type = "micro";
- vbus-gpios = <&pio 13 GPIO_ACTIVE_HIGH>;
+ id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
+ vbus-supply = <&usb_p0_vbus>;
};
};
@@ -268,6 +304,7 @@ examples:
wakeup-source;
dr_mode = "otg";
usb-role-switch;
+ role-switch-default-mode = "host";
#address-cells = <1>;
#size-cells = <1>;
ranges;
diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.yaml b/Documentation/devicetree/bindings/usb/mediatek,musb.yaml
index 84ddacfdbe9b..03d62d60ce5f 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,musb.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.yaml
@@ -19,6 +19,7 @@ properties:
- enum:
- mediatek,mt8516-musb
- mediatek,mt2701-musb
+ - mediatek,mt7623-musb
- const: mediatek,mtk-musb
reg:
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index 4e6451789806..e70afc40edb2 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -17,6 +17,7 @@ properties:
- qcom,msm8998-dwc3
- qcom,sc7180-dwc3
- qcom,sc7280-dwc3
+ - qcom,sdm660-dwc3
- qcom,sdm845-dwc3
- qcom,sdx55-dwc3
- qcom,sm4250-dwc3
diff --git a/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml b/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
index ad73339ffe1d..012fe80a7611 100644
--- a/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
+++ b/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
@@ -17,7 +17,9 @@ properties:
- const: renesas,rza1-usbhs
- items:
- - const: renesas,usbhs-r7s9210 # RZ/A2
+ - enum:
+ - renesas,usbhs-r7s9210 # RZ/A2
+ - renesas,usbhs-r9a07g044 # RZ/G2{L,LC}
- const: renesas,rza2-usbhs
- items:
@@ -59,7 +61,8 @@ properties:
- description: USB 2.0 clock selector
interrupts:
- maxItems: 1
+ minItems: 1
+ maxItems: 4
renesas,buswait:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -108,6 +111,25 @@ required:
- clocks
- interrupts
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: renesas,usbhs-r9a07g044
+ then:
+ properties:
+ interrupts:
+ items:
+ - description: U2P_IXL_INT
+ - description: U2P_INT_DMA[0]
+ - description: U2P_INT_DMA[1]
+ - description: U2P_INT_DMAERR
+ else:
+ properties:
+ interrupts:
+ maxItems: 1
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
index 41416fbd92aa..078fb7889593 100644
--- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
@@ -289,10 +289,21 @@ properties:
maximum: 16
tx-fifo-resize:
- description: Determines if the FIFO *has* to be reallocated
- deprecated: true
+ description: Determines if the TX fifos can be dynamically resized depending
+ on the number of IN endpoints used and if bursting is supported. This
+ may help improve bandwidth on platforms with higher system latencies, as
+ increased fifo space allows for the controller to prefetch data into its
+ internal memory.
type: boolean
+ tx-fifo-max-num:
+ description: Specifies the max number of packets the txfifo resizing logic
+ can account for when higher endpoint bursting is used. (bMaxBurst > 6) The
+ higher the number, the more fifo space the txfifo resizing logic will
+ allocate for that endpoint.
+ $ref: /schemas/types.yaml#/definitions/uint8
+ minimum: 3
+
snps,incr-burst-type-adjustment:
description:
Value for INCR burst type of GSBUSCFG0 register, undefined length INCR
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 07fb0d25fc15..a867f7102c35 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -271,6 +271,8 @@ patternProperties:
description: Shenzen Chuangsiqi Technology Co.,Ltd.
"^cubietech,.*":
description: Cubietech, Ltd.
+ "^cui,.*":
+ description: CUI Devices
"^cypress,.*":
description: Cypress Semiconductor Corporation
"^cznic,.*":
@@ -339,6 +341,8 @@ patternProperties:
description: eGalax_eMPIA Technology Inc
"^einfochips,.*":
description: Einfochips
+ "^eink,.*":
+ description: E Ink Corporation
"^elan,.*":
description: Elan Microelectronic Corp.
"^element14,.*":
@@ -563,6 +567,8 @@ patternProperties:
description: ITE Tech. Inc.
"^itead,.*":
description: ITEAD Intelligent Systems Co.Ltd
+ "^itian,.*":
+ description: ITian Corporation
"^iwave,.*":
description: iWave Systems Technologies Pvt. Ltd.
"^jdi,.*":
@@ -735,6 +741,8 @@ patternProperties:
description: MiraMEMS Sensing Technology Co., Ltd.
"^mitsubishi,.*":
description: Mitsubishi Electric Corporation
+ "^mntre,.*":
+ description: MNT Research GmbH
"^modtronix,.*":
description: Modtronix Engineering
"^mosaixtech,.*":
@@ -936,6 +944,8 @@ patternProperties:
description: Chengdu Kaixuan Information Technology Co., Ltd.
"^qiaodian,.*":
description: QiaoDian XianShi Corporation
+ "^qishenglong,.*":
+ description: Shenzhen QiShenglong Industrialist Co., Ltd.
"^qnap,.*":
description: QNAP Systems, Inc.
"^radxa,.*":
@@ -1066,6 +1076,8 @@ patternProperties:
description: Silicon Integrated Systems Corp.
"^sitronix,.*":
description: Sitronix Technology Corporation
+ "^skov,.*":
+ description: SKOV A/S
"^skyworks,.*":
description: Skyworks Solutions, Inc.
"^smartlabs,.*":
@@ -1111,6 +1123,10 @@ patternProperties:
"^st-ericsson,.*":
description: ST-Ericsson
deprecated: true
+ "^storlink,.*":
+ description: StorLink Semiconductors, Inc.
+ "^storm,.*":
+ description: Storm Semiconductor, Inc.
"^summit,.*":
description: Summit microelectronics
"^sunchip,.*":
@@ -1143,6 +1159,8 @@ patternProperties:
description: TechNexion
"^technologic,.*":
description: Technologic Systems
+ "^teltonika,.*":
+ description: Teltonika Networks
"^tempo,.*":
description: Tempo Semiconductor
"^techstar,.*":
@@ -1165,6 +1183,8 @@ patternProperties:
description: Tecon Microprocessor Technologies, LLC.
"^topeet,.*":
description: Topeet
+ "^topic,.*":
+ description: Topic Embedded Systems
"^toppoly,.*":
description: TPO (deprecated, use tpo)
deprecated: true
@@ -1184,6 +1204,8 @@ patternProperties:
description: TPO
"^tq,.*":
description: TQ-Systems GmbH
+ "^traverse,.*":
+ description: Traverse Technologies Australia Pty Ltd
"^tronfy,.*":
description: Tronfy
"^tronsmart,.*":
@@ -1268,6 +1290,8 @@ patternProperties:
description: Shenzhen whwave Electronics, Inc.
"^wi2wi,.*":
description: Wi2Wi, Inc.
+ "^wiligear,.*":
+ description: Wiligear, Ltd.
"^winbond,.*":
description: Winbond Electronics corp.
"^winstar,.*":
diff --git a/Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml b/Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml
new file mode 100644
index 000000000000..f2105eedac2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/maxim,max63xx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim 63xx Watchdog Timers
+
+allOf:
+ - $ref: "watchdog.yaml#"
+
+maintainers:
+ - Marc Zyngier <maz@kernel.org>
+ - Linus Walleij <linus.walleij@linaro.org>
+
+properties:
+ compatible:
+ oneOf:
+ - const: maxim,max6369
+ - const: maxim,max6370
+ - const: maxim,max6371
+ - const: maxim,max6372
+ - const: maxim,max6373
+ - const: maxim,max6374
+
+ reg:
+ description: This is a 1-byte memory-mapped address
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ wdt: watchdog@50000000 {
+ compatible = "maxim,max6369";
+ reg = <0x50000000 0x1>;
+ timeout-sec = <10>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
index 416d716403f6..a4e31ce96e0e 100644
--- a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
@@ -13,6 +13,7 @@ Required properties:
"mediatek,mt7622-wdt", "mediatek,mt6589-wdt": for MT7622
"mediatek,mt7623-wdt", "mediatek,mt6589-wdt": for MT7623
"mediatek,mt7629-wdt", "mediatek,mt6589-wdt": for MT7629
+ "mediatek,mt7986-wdt", "mediatek,mt6589-wdt": for MT7986
"mediatek,mt8183-wdt": for MT8183
"mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516
"mediatek,mt8192-wdt": for MT8192
diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst
index 7f21425d9435..f5ac4c90b237 100644
--- a/Documentation/driver-api/dma-buf.rst
+++ b/Documentation/driver-api/dma-buf.rst
@@ -88,6 +88,9 @@ consider though:
- The DMA buffer FD is also pollable, see `Implicit Fence Poll Support`_ below for
details.
+- The DMA buffer FD also supports a few dma-buf-specific ioctls, see
+ `DMA Buffer ioctls`_ below for details.
+
Basic Operation and Device DMA Access
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -106,6 +109,16 @@ Implicit Fence Poll Support
.. kernel-doc:: drivers/dma-buf/dma-buf.c
:doc: implicit fence polling
+DMA-BUF statistics
+~~~~~~~~~~~~~~~~~~
+.. kernel-doc:: drivers/dma-buf/dma-buf-sysfs-stats.c
+ :doc: overview
+
+DMA Buffer ioctls
+~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: include/uapi/linux/dma-buf.h
+
Kernel Functions and Structures Reference
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst
index 198aadafd3e7..8d650b4e2ce6 100644
--- a/Documentation/driver-api/fpga/fpga-bridge.rst
+++ b/Documentation/driver-api/fpga/fpga-bridge.rst
@@ -4,11 +4,11 @@ FPGA Bridge
API to implement a new FPGA bridge
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* struct fpga_bridge — The FPGA Bridge structure
-* struct fpga_bridge_ops — Low level Bridge driver ops
-* devm_fpga_bridge_create() — Allocate and init a bridge struct
-* fpga_bridge_register() — Register a bridge
-* fpga_bridge_unregister() — Unregister a bridge
+* struct fpga_bridge - The FPGA Bridge structure
+* struct fpga_bridge_ops - Low level Bridge driver ops
+* devm_fpga_bridge_create() - Allocate and init a bridge struct
+* fpga_bridge_register() - Register a bridge
+* fpga_bridge_unregister() - Unregister a bridge
.. kernel-doc:: include/linux/fpga/fpga-bridge.h
:functions: fpga_bridge
diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst
index 917ee22db429..4d926b452cb3 100644
--- a/Documentation/driver-api/fpga/fpga-mgr.rst
+++ b/Documentation/driver-api/fpga/fpga-mgr.rst
@@ -101,12 +101,12 @@ in state.
API for implementing a new FPGA Manager driver
----------------------------------------------
-* ``fpga_mgr_states`` — Values for :c:expr:`fpga_manager->state`.
-* struct fpga_manager — the FPGA manager struct
-* struct fpga_manager_ops — Low level FPGA manager driver ops
-* devm_fpga_mgr_create() — Allocate and init a manager struct
-* fpga_mgr_register() — Register an FPGA manager
-* fpga_mgr_unregister() — Unregister an FPGA manager
+* ``fpga_mgr_states`` - Values for :c:expr:`fpga_manager->state`.
+* struct fpga_manager - the FPGA manager struct
+* struct fpga_manager_ops - Low level FPGA manager driver ops
+* devm_fpga_mgr_create() - Allocate and init a manager struct
+* fpga_mgr_register() - Register an FPGA manager
+* fpga_mgr_unregister() - Unregister an FPGA manager
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_mgr_states
diff --git a/Documentation/driver-api/fpga/fpga-programming.rst b/Documentation/driver-api/fpga/fpga-programming.rst
index 002392dab04f..fb4da4240e96 100644
--- a/Documentation/driver-api/fpga/fpga-programming.rst
+++ b/Documentation/driver-api/fpga/fpga-programming.rst
@@ -84,10 +84,10 @@ will generate that list. Here's some sample code of what to do next::
API for programming an FPGA
---------------------------
-* fpga_region_program_fpga() — Program an FPGA
-* fpga_image_info() — Specifies what FPGA image to program
-* fpga_image_info_alloc() — Allocate an FPGA image info struct
-* fpga_image_info_free() — Free an FPGA image info struct
+* fpga_region_program_fpga() - Program an FPGA
+* fpga_image_info() - Specifies what FPGA image to program
+* fpga_image_info_alloc() - Allocate an FPGA image info struct
+* fpga_image_info_free() - Free an FPGA image info struct
.. kernel-doc:: drivers/fpga/fpga-region.c
:functions: fpga_region_program_fpga
diff --git a/Documentation/driver-api/fpga/fpga-region.rst b/Documentation/driver-api/fpga/fpga-region.rst
index 363a8171ab0a..2636a27c11b2 100644
--- a/Documentation/driver-api/fpga/fpga-region.rst
+++ b/Documentation/driver-api/fpga/fpga-region.rst
@@ -45,19 +45,19 @@ An example of usage can be seen in the probe function of [#f2]_.
API to add a new FPGA region
----------------------------
-* struct fpga_region — The FPGA region struct
-* devm_fpga_region_create() — Allocate and init a region struct
-* fpga_region_register() — Register an FPGA region
-* fpga_region_unregister() — Unregister an FPGA region
+* struct fpga_region - The FPGA region struct
+* devm_fpga_region_create() - Allocate and init a region struct
+* fpga_region_register() - Register an FPGA region
+* fpga_region_unregister() - Unregister an FPGA region
The FPGA region's probe function will need to get a reference to the FPGA
Manager it will be using to do the programming. This usually would happen
during the region's probe function.
-* fpga_mgr_get() — Get a reference to an FPGA manager, raise ref count
-* of_fpga_mgr_get() — Get a reference to an FPGA manager, raise ref count,
+* fpga_mgr_get() - Get a reference to an FPGA manager, raise ref count
+* of_fpga_mgr_get() - Get a reference to an FPGA manager, raise ref count,
given a device node.
-* fpga_mgr_put() — Put an FPGA manager
+* fpga_mgr_put() - Put an FPGA manager
The FPGA region will need to specify which bridges to control while programming
the FPGA. The region driver can build a list of bridges during probe time
@@ -66,11 +66,11 @@ the list of bridges to program just before programming
(:c:expr:`fpga_region->get_bridges`). The FPGA bridge framework supplies the
following APIs to handle building or tearing down that list.
-* fpga_bridge_get_to_list() — Get a ref of an FPGA bridge, add it to a
+* fpga_bridge_get_to_list() - Get a ref of an FPGA bridge, add it to a
list
-* of_fpga_bridge_get_to_list() — Get a ref of an FPGA bridge, add it to a
+* of_fpga_bridge_get_to_list() - Get a ref of an FPGA bridge, add it to a
list, given a device node
-* fpga_bridges_put() — Given a list of bridges, put them
+* fpga_bridges_put() - Given a list of bridges, put them
.. kernel-doc:: include/linux/fpga/fpga-region.h
:functions: fpga_region
diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst
index 3366a991b4aa..47869ca8ccf0 100644
--- a/Documentation/driver-api/gpio/consumer.rst
+++ b/Documentation/driver-api/gpio/consumer.rst
@@ -72,6 +72,10 @@ for the GPIO. Values can be:
* GPIOD_OUT_HIGH_OPEN_DRAIN same as GPIOD_OUT_HIGH but also enforce the line
to be electrically used with open drain.
+Note that the initial value is *logical* and the physical line level depends on
+whether the line is configured active high or active low (see
+:ref:`active_low_semantics`).
+
The two last flags are used for use cases where open drain is mandatory, such
as I2C: if the line is not already configured as open drain in the mappings
(see board.txt), then open drain will be enforced anyway and a warning will be
@@ -252,6 +256,8 @@ that can't be accessed from hardIRQ handlers, these calls act the same as the
spinlock-safe calls.
+.. _active_low_semantics:
+
The active low and open drain semantics
---------------------------------------
As a consumer should not have to care about the physical line level, all of the
@@ -309,9 +315,11 @@ work on the raw line value::
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
-The active low state of a GPIO can also be queried using the following call::
+The active low state of a GPIO can also be queried and toggled using the
+following calls::
int gpiod_is_active_low(const struct gpio_desc *desc)
+ void gpiod_toggle_active_low(struct gpio_desc *desc)
Note that these functions should only be used with great moderation; a driver
should not have to care about the physical line level or open drain semantics.
diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst
index d6b0d779859b..bbc53920d4dd 100644
--- a/Documentation/driver-api/gpio/driver.rst
+++ b/Documentation/driver-api/gpio/driver.rst
@@ -547,13 +547,10 @@ To use the helpers please keep the following in mind:
the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
properly.
-- Nominally set all handlers to handle_bad_irq() in the setup call and pass
- handle_bad_irq() as flow handler parameter in gpiochip_irqchip_add() if it is
- expected for GPIO driver that irqchip .set_type() callback will be called
- before using/enabling each GPIO IRQ. Then set the handler to
- handle_level_irq() and/or handle_edge_irq() in the irqchip .set_type()
- callback depending on what your controller supports and what is requested
- by the consumer.
+- Nominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchip
+ is cascaded, set the handler to handle_level_irq() and/or handle_edge_irq()
+ in the irqchip .set_type() callback depending on what your controller
+ supports and what is requested by the consumer.
Locking IRQ usage
diff --git a/Documentation/driver-api/media/camera-sensor.rst b/Documentation/driver-api/media/camera-sensor.rst
index 7160336aa475..c7d4891bd24e 100644
--- a/Documentation/driver-api/media/camera-sensor.rst
+++ b/Documentation/driver-api/media/camera-sensor.rst
@@ -3,10 +3,10 @@
Writing camera sensor drivers
=============================
-CSI-2
------
+CSI-2 and parallel (BT.601 and BT.656) busses
+---------------------------------------------
-Please see what is written on :ref:`MIPI_CSI_2`.
+Please see :ref:`transmitter-receiver`.
Handling clocks
---------------
@@ -26,15 +26,16 @@ user.
ACPI
~~~~
-Read the "clock-frequency" _DSD property to denote the frequency. The driver can
-rely on this frequency being used.
+Read the ``clock-frequency`` _DSD property to denote the frequency. The driver
+can rely on this frequency being used.
Devicetree
~~~~~~~~~~
-The currently preferred way to achieve this is using "assigned-clock-rates"
-property. See Documentation/devicetree/bindings/clock/clock-bindings.txt for
-more information. The driver then gets the frequency using clk_get_rate().
+The currently preferred way to achieve this is using ``assigned-clocks``,
+``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See
+``Documentation/devicetree/bindings/clock/clock-bindings.txt`` for more
+information. The driver then gets the frequency using ``clk_get_rate()``.
This approach has the drawback that there's no guarantee that the frequency
hasn't been modified directly or indirectly by another driver, or supported by
@@ -55,7 +56,7 @@ processing pipeline as one or more sub-devices with different cropping and
scaling configurations. The output size of the device is the result of a series
of cropping and scaling operations from the device's pixel array's size.
-An example of such a driver is the smiapp driver (see drivers/media/i2c/smiapp).
+An example of such a driver is the CCS driver (see ``drivers/media/i2c/ccs``).
Register list based drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -67,7 +68,7 @@ level are independent. How a driver picks such configuration is based on the
format set on a source pad at the end of the device's internal pipeline.
Most sensor drivers are implemented this way, see e.g.
-drivers/media/i2c/imx319.c for an example.
+``drivers/media/i2c/imx319.c`` for an example.
Frame interval configuration
----------------------------
@@ -94,9 +95,10 @@ large variety of devices beyond camera sensors. Devices that have no analogue
crop, use the full source image size, i.e. pixel array size.
Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and
-``V4L2_CID_VBLANK``, respectively. The unit of these controls are lines. The
-pixel rate is specified by ``V4L2_CID_PIXEL_RATE`` in the same sub-device. The
-unit of that control is Hz.
+``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control
+is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in
+the sensor's **pixel array** is specified by ``V4L2_CID_PIXEL_RATE`` in the same
+sub-device. The unit of that control is pixels per second.
Register list based drivers need to implement read-only sub-device nodes for the
purpose. Devices that are not register list based need these to configure the
@@ -125,14 +127,14 @@ general, the device must be powered on at least when its registers are being
accessed and when it is streaming.
Existing camera sensor drivers may rely on the old
-:c:type:`v4l2_subdev_core_ops`->s_power() callback for bridge or ISP drivers to
+struct v4l2_subdev_core_ops->s_power() callback for bridge or ISP drivers to
manage their power state. This is however **deprecated**. If you feel you need
to begin calling an s_power from an ISP or a bridge driver, instead please add
runtime PM support to the sensor driver you are using. Likewise, new drivers
should not use s_power.
Please see examples in e.g. ``drivers/media/i2c/ov8856.c`` and
-``drivers/media/i2c/smiapp/smiapp-core.c``. The two drivers work in both ACPI
+``drivers/media/i2c/ccs/ccs-core.c``. The two drivers work in both ACPI
and DT based systems.
Control framework
@@ -149,16 +151,3 @@ used to obtain device's power state after the power state transition:
The function returns a non-zero value if it succeeded getting the power count or
runtime PM was disabled, in either of which cases the driver may proceed to
access the device.
-
-Controls
---------
-
-For camera sensors that are connected to a bus where transmitter and receiver
-require common configuration set by drivers, such as CSI-2 or parallel (BT.601
-or BT.656) bus, the ``V4L2_CID_LINK_FREQ`` control is mandatory on transmitter
-drivers. Receiver drivers can use the ``V4L2_CID_LINK_FREQ`` to query the
-frequency used on the bus.
-
-The transmitter drivers should also implement ``V4L2_CID_PIXEL_RATE`` control in
-order to tell the maximum pixel rate to the receiver. This is required on raw
-camera sensors.
diff --git a/Documentation/driver-api/media/cec-core.rst b/Documentation/driver-api/media/cec-core.rst
index 56345eae9a26..c6194ee81c41 100644
--- a/Documentation/driver-api/media/cec-core.rst
+++ b/Documentation/driver-api/media/cec-core.rst
@@ -130,9 +130,12 @@ To enable/disable the hardware::
int (*adap_enable)(struct cec_adapter *adap, bool enable);
This callback enables or disables the CEC hardware. Enabling the CEC hardware
-means powering it up in a state where no logical addresses are claimed. This
-op assumes that the physical address (adap->phys_addr) is valid when enable is
-true and will not change while the CEC adapter remains enabled. The initial
+means powering it up in a state where no logical addresses are claimed. The
+physical address will always be valid if CEC_CAP_NEEDS_HPD is set. If that
+capability is not set, then the physical address can change while the CEC
+hardware is enabled. CEC drivers should not set CEC_CAP_NEEDS_HPD unless
+the hardware design requires that as this will make it impossible to wake
+up displays that pull the HPD low when in standby mode. The initial
state of the CEC adapter after calling cec_allocate_adapter() is disabled.
Note that adap_enable must return 0 if enable is false.
diff --git a/Documentation/driver-api/media/csi2.rst b/Documentation/driver-api/media/csi2.rst
deleted file mode 100644
index 11c52b0be8b8..000000000000
--- a/Documentation/driver-api/media/csi2.rst
+++ /dev/null
@@ -1,94 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. _MIPI_CSI_2:
-
-MIPI CSI-2
-==========
-
-CSI-2 is a data bus intended for transferring images from cameras to
-the host SoC. It is defined by the `MIPI alliance`_.
-
-.. _`MIPI alliance`: http://www.mipi.org/
-
-Media bus formats
------------------
-
-See :ref:`v4l2-mbus-pixelcode` for details on which media bus formats should
-be used for CSI-2 interfaces.
-
-Transmitter drivers
--------------------
-
-CSI-2 transmitter, such as a sensor or a TV tuner, drivers need to
-provide the CSI-2 receiver with information on the CSI-2 bus
-configuration. These include the V4L2_CID_LINK_FREQ and
-V4L2_CID_PIXEL_RATE controls and
-(:c:type:`v4l2_subdev_video_ops`->s_stream() callback). These
-interface elements must be present on the sub-device represents the
-CSI-2 transmitter.
-
-The V4L2_CID_LINK_FREQ control is used to tell the receiver driver the
-frequency (and not the symbol rate) of the link. The V4L2_CID_PIXEL_RATE
-control may be used by the receiver to obtain the pixel rate the transmitter
-uses. The :c:type:`v4l2_subdev_video_ops`->s_stream() callback provides an
-ability to start and stop the stream.
-
-The value of the V4L2_CID_PIXEL_RATE is calculated as follows::
-
- pixel_rate = link_freq * 2 * nr_of_lanes * 16 / k / bits_per_sample
-
-where
-
-.. list-table:: variables in pixel rate calculation
- :header-rows: 1
-
- * - variable or constant
- - description
- * - link_freq
- - The value of the V4L2_CID_LINK_FREQ integer64 menu item.
- * - nr_of_lanes
- - Number of data lanes used on the CSI-2 link. This can
- be obtained from the OF endpoint configuration.
- * - 2
- - Two bits are transferred per clock cycle per lane.
- * - bits_per_sample
- - Number of bits per sample.
- * - k
- - 16 for D-PHY and 7 for C-PHY
-
-The transmitter drivers must, if possible, configure the CSI-2
-transmitter to *LP-11 mode* whenever the transmitter is powered on but
-not active, and maintain *LP-11 mode* until stream on. Only at stream
-on should the transmitter activate the clock on the clock lane and
-transition to *HS mode*.
-
-Some transmitters do this automatically but some have to be explicitly
-programmed to do so, and some are unable to do so altogether due to
-hardware constraints.
-
-Stopping the transmitter
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-A transmitter stops sending the stream of images as a result of
-calling the ``.s_stream()`` callback. Some transmitters may stop the
-stream at a frame boundary whereas others stop immediately,
-effectively leaving the current frame unfinished. The receiver driver
-should not make assumptions either way, but function properly in both
-cases.
-
-Receiver drivers
-----------------
-
-Before the receiver driver may enable the CSI-2 transmitter by using
-the :c:type:`v4l2_subdev_video_ops`->s_stream(), it must have powered
-the transmitter up by using the
-:c:type:`v4l2_subdev_core_ops`->s_power() callback. This may take
-place either indirectly by using :c:func:`v4l2_pipeline_pm_get` or
-directly.
-
-Formats
--------
-
-The media bus pixel codes document parallel formats. Should the pixel data be
-transported over a serial bus, the media bus pixel code that describes a
-parallel format that transfers a sample on a single clock cycle is used.
diff --git a/Documentation/driver-api/media/index.rst b/Documentation/driver-api/media/index.rst
index 813d7db59da7..08e206567408 100644
--- a/Documentation/driver-api/media/index.rst
+++ b/Documentation/driver-api/media/index.rst
@@ -37,7 +37,7 @@ Documentation/userspace-api/media/index.rst
rc-core
mc-core
cec-core
- csi2
+ tx-rx
camera-sensor
drivers/index
diff --git a/Documentation/driver-api/media/tx-rx.rst b/Documentation/driver-api/media/tx-rx.rst
new file mode 100644
index 000000000000..e1e9258dd862
--- /dev/null
+++ b/Documentation/driver-api/media/tx-rx.rst
@@ -0,0 +1,133 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _transmitter-receiver:
+
+Pixel data transmitter and receiver drivers
+===========================================
+
+V4L2 supports various devices that transmit and receive pixel data. Examples of
+these devices include a camera sensor, a TV tuner and a parallel or a CSI-2
+receiver in an SoC.
+
+Bus types
+---------
+
+The following busses are the most common. This section discusses these two only.
+
+MIPI CSI-2
+^^^^^^^^^^
+
+CSI-2 is a data bus intended for transferring images from cameras to
+the host SoC. It is defined by the `MIPI alliance`_.
+
+.. _`MIPI alliance`: https://www.mipi.org/
+
+Parallel
+^^^^^^^^
+
+`BT.601`_ and `BT.656`_ are the most common parallel busses.
+
+.. _`BT.601`: https://en.wikipedia.org/wiki/Rec._601
+.. _`BT.656`: https://en.wikipedia.org/wiki/ITU-R_BT.656
+
+Transmitter drivers
+-------------------
+
+Transmitter drivers generally need to provide the receiver drivers with the
+configuration of the transmitter. What is required depends on the type of the
+bus. These are common for both busses.
+
+Media bus pixel code
+^^^^^^^^^^^^^^^^^^^^
+
+See :ref:`v4l2-mbus-pixelcode`.
+
+Link frequency
+^^^^^^^^^^^^^^
+
+The :ref:`V4L2_CID_LINK_FREQ <v4l2-cid-link-freq>` control is used to tell the
+receiver the frequency of the bus (i.e. it is not the same as the symbol rate).
+
+``.s_stream()`` callback
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The struct struct v4l2_subdev_video_ops->s_stream() callback is used by the
+receiver driver to control the transmitter driver's streaming state.
+
+
+CSI-2 transmitter drivers
+-------------------------
+
+Pixel rate
+^^^^^^^^^^
+
+The pixel rate on the bus is calculated as follows::
+
+ pixel_rate = link_freq * 2 * nr_of_lanes * 16 / k / bits_per_sample
+
+where
+
+.. list-table:: variables in pixel rate calculation
+ :header-rows: 1
+
+ * - variable or constant
+ - description
+ * - link_freq
+ - The value of the ``V4L2_CID_LINK_FREQ`` integer64 menu item.
+ * - nr_of_lanes
+ - Number of data lanes used on the CSI-2 link. This can
+ be obtained from the OF endpoint configuration.
+ * - 2
+ - Data is transferred on both rising and falling edge of the signal.
+ * - bits_per_sample
+ - Number of bits per sample.
+ * - k
+ - 16 for D-PHY and 7 for C-PHY
+
+.. note::
+
+ The pixel rate calculated this way is **not** the same thing as the
+ pixel rate on the camera sensor's pixel array which is indicated by the
+ :ref:`V4L2_CID_PIXEL_RATE <v4l2-cid-pixel-rate>` control.
+
+LP-11 and LP-111 modes
+^^^^^^^^^^^^^^^^^^^^^^
+
+As part of transitioning to high speed mode, a CSI-2 transmitter typically
+briefly sets the bus to LP-11 or LP-111 state, depending on the PHY. This period
+may be as short as 100 µs, during which the receiver observes this state and
+proceeds its own part of high speed mode transition.
+
+Most receivers are capable of autonomously handling this once the software has
+configured them to do so, but there are receivers which require software
+involvement in observing LP-11 or LP-111 state. 100 µs is a brief period to hit
+in software, especially when there is no interrupt telling something is
+happening.
+
+One way to address this is to configure the transmitter side explicitly to LP-11
+or LP-111 mode, which requires support from the transmitter hardware. This is
+not universally available. Many devices return to this state once streaming is
+stopped while the state after power-on is LP-00 or LP-000.
+
+The ``.pre_streamon()`` callback may be used to prepare a transmitter for
+transitioning to streaming state, but not yet start streaming. Similarly, the
+``.post_streamoff()`` callback is used to undo what was done by the
+``.pre_streamon()`` callback. The caller of ``.pre_streamon()`` is thus required
+to call ``.post_streamoff()`` for each successful call of ``.pre_streamon()``.
+
+In the context of CSI-2, the ``.pre_streamon()`` callback is used to transition
+the transmitter to the LP-11 or LP-111 mode. This also requires powering on the
+device, so this should be only done when it is needed.
+
+Receiver drivers that do not need explicit LP-11 or LP-111 mode setup are waived
+from calling the two callbacks.
+
+Stopping the transmitter
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+A transmitter stops sending the stream of images as a result of
+calling the ``.s_stream()`` callback. Some transmitters may stop the
+stream at a frame boundary whereas others stop immediately,
+effectively leaving the current frame unfinished. The receiver driver
+should not make assumptions either way, but function properly in both
+cases.
diff --git a/Documentation/driver-api/thermal/nouveau_thermal.rst b/Documentation/driver-api/thermal/nouveau_thermal.rst
index 79ece266cf6d..aa10db6df309 100644
--- a/Documentation/driver-api/thermal/nouveau_thermal.rst
+++ b/Documentation/driver-api/thermal/nouveau_thermal.rst
@@ -90,7 +90,7 @@ Bug reports
-----------
Thermal management on Nouveau is new and may not work on all cards. If you have
-inquiries, please ping mupuf on IRC (#nouveau, freenode).
+inquiries, please ping mupuf on IRC (#nouveau, OFTC).
Bug reports should be filled on Freedesktop's bug tracker. Please follow
https://nouveau.freedesktop.org/wiki/Bugs
diff --git a/Documentation/driver-api/vfio.rst b/Documentation/driver-api/vfio.rst
index 606eed8823ce..c663b6f97825 100644
--- a/Documentation/driver-api/vfio.rst
+++ b/Documentation/driver-api/vfio.rst
@@ -255,11 +255,13 @@ vfio_unregister_group_dev() respectively::
void vfio_init_group_dev(struct vfio_device *device,
struct device *dev,
const struct vfio_device_ops *ops);
+ void vfio_uninit_group_dev(struct vfio_device *device);
int vfio_register_group_dev(struct vfio_device *device);
void vfio_unregister_group_dev(struct vfio_device *device);
The driver should embed the vfio_device in its own structure and call
-vfio_init_group_dev() to pre-configure it before going to registration.
+vfio_init_group_dev() to pre-configure it before going to registration
+and call vfio_uninit_group_dev() after completing the un-registration.
vfio_register_group_dev() indicates to the core to begin tracking the
iommu_group of the specified dev and register the dev as owned by a VFIO bus
driver. Once vfio_register_group_dev() returns it is possible for userspace to
diff --git a/Documentation/fault-injection/provoke-crashes.rst b/Documentation/fault-injection/provoke-crashes.rst
index a20ba5d93932..3abe84225613 100644
--- a/Documentation/fault-injection/provoke-crashes.rst
+++ b/Documentation/fault-injection/provoke-crashes.rst
@@ -29,8 +29,7 @@ recur_count
cpoint_name
Where in the kernel to trigger the action. It can be
one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY,
- FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_DISPATCH_CMD,
- IDE_CORE_CP, or DIRECT
+ FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_QUEUE_RQ, or DIRECT.
cpoint_type
Indicates the action to be taken on hitting the crash point.
diff --git a/Documentation/features/vm/THP/arch-support.txt b/Documentation/features/vm/THP/arch-support.txt
index e8238cb2a4da..7dbd6967b37e 100644
--- a/Documentation/features/vm/THP/arch-support.txt
+++ b/Documentation/features/vm/THP/arch-support.txt
@@ -22,7 +22,7 @@
| openrisc: | .. |
| parisc: | TODO |
| powerpc: | ok |
- | riscv: | TODO |
+ | riscv: | ok |
| s390: | ok |
| sh: | .. |
| sparc: | ok |
diff --git a/Documentation/filesystems/erofs.rst b/Documentation/filesystems/erofs.rst
index 832839fcf4c3..b97579b7d8fb 100644
--- a/Documentation/filesystems/erofs.rst
+++ b/Documentation/filesystems/erofs.rst
@@ -84,6 +84,9 @@ cache_strategy=%s Select a strategy for cached decompression from now on:
It still does in-place I/O decompression
for the rest compressed physical clusters.
========== =============================================
+dax={always,never} Use direct access (no page cache). See
+ Documentation/filesystems/dax.rst.
+dax A legacy option which is an alias for ``dax=always``.
=================== =========================================================
On-disk details
@@ -153,13 +156,14 @@ may not. All metadatas can be now observed in two different spaces (views):
Xattrs, extents, data inline are followed by the corresponding inode with
proper alignment, and they could be optional for different data mappings.
- _currently_ total 4 valid data mappings are supported:
+ _currently_ total 5 data layouts are supported:
== ====================================================================
0 flat file data without data inline (no extent);
1 fixed-sized output data compression (with non-compacted indexes);
2 flat file data with tail packing data inline (no extent);
- 3 fixed-sized output data compression (with compacted indexes, v5.3+).
+ 3 fixed-sized output data compression (with compacted indexes, v5.3+);
+ 4 chunk-based file (v5.15+).
== ====================================================================
The size of the optional xattrs is indicated by i_xattr_count in inode
@@ -210,6 +214,17 @@ Note that apart from the offset of the first filename, nameoff0 also indicates
the total number of directory entries in this block since it is no need to
introduce another on-disk field at all.
+Chunk-based file
+----------------
+In order to support chunk-based data deduplication, a new inode data layout has
+been supported since Linux v5.15: Files are split in equal-sized data chunks
+with ``extents`` area of the inode metadata indicating how to get the chunk
+data: these can be simply as a 4-byte block address array or in the 8-byte
+chunk index form (see struct erofs_inode_chunk_index in erofs_fs.h for more
+details.)
+
+By the way, chunk-based files are all uncompressed for now.
+
Data compression
----------------
EROFS implements LZ4 fixed-sized output compression which generates fixed-sized
diff --git a/Documentation/filesystems/ext4/globals.rst b/Documentation/filesystems/ext4/globals.rst
index 368bf7662b96..b17418974fd3 100644
--- a/Documentation/filesystems/ext4/globals.rst
+++ b/Documentation/filesystems/ext4/globals.rst
@@ -11,3 +11,4 @@ have static metadata at fixed locations.
.. include:: bitmaps.rst
.. include:: mmp.rst
.. include:: journal.rst
+.. include:: orphan.rst
diff --git a/Documentation/filesystems/ext4/inodes.rst b/Documentation/filesystems/ext4/inodes.rst
index a65baffb4ebf..6c5ce666e63f 100644
--- a/Documentation/filesystems/ext4/inodes.rst
+++ b/Documentation/filesystems/ext4/inodes.rst
@@ -498,11 +498,11 @@ structure -- inode change time (ctime), access time (atime), data
modification time (mtime), and deletion time (dtime). The four fields
are 32-bit signed integers that represent seconds since the Unix epoch
(1970-01-01 00:00:00 GMT), which means that the fields will overflow in
-January 2038. For inodes that are not linked from any directory but are
-still open (orphan inodes), the dtime field is overloaded for use with
-the orphan list. The superblock field ``s_last_orphan`` points to the
-first inode in the orphan list; dtime is then the number of the next
-orphaned inode, or zero if there are no more orphans.
+January 2038. If the filesystem does not have orphan_file feature, inodes
+that are not linked from any directory but are still open (orphan inodes) have
+the dtime field overloaded for use with the orphan list. The superblock field
+``s_last_orphan`` points to the first inode in the orphan list; dtime is then
+the number of the next orphaned inode, or zero if there are no more orphans.
If the inode structure size ``sb->s_inode_size`` is larger than 128
bytes and the ``i_inode_extra`` field is large enough to encompass the
diff --git a/Documentation/filesystems/ext4/orphan.rst b/Documentation/filesystems/ext4/orphan.rst
new file mode 100644
index 000000000000..bb19ecd1b626
--- /dev/null
+++ b/Documentation/filesystems/ext4/orphan.rst
@@ -0,0 +1,52 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Orphan file
+-----------
+
+In unix there can inodes that are unlinked from directory hierarchy but that
+are still alive because they are open. In case of crash the filesystem has to
+clean up these inodes as otherwise they (and the blocks referenced from them)
+would leak. Similarly if we truncate or extend the file, we need not be able
+to perform the operation in a single journalling transaction. In such case we
+track the inode as orphan so that in case of crash extra blocks allocated to
+the file get truncated.
+
+Traditionally ext4 tracks orphan inodes in a form of single linked list where
+superblock contains the inode number of the last orphan inode (s\_last\_orphan
+field) and then each inode contains inode number of the previously orphaned
+inode (we overload i\_dtime inode field for this). However this filesystem
+global single linked list is a scalability bottleneck for workloads that result
+in heavy creation of orphan inodes. When orphan file feature
+(COMPAT\_ORPHAN\_FILE) is enabled, the filesystem has a special inode
+(referenced from the superblock through s\_orphan_file_inum) with several
+blocks. Each of these blocks has a structure:
+
+.. list-table::
+ :widths: 8 8 24 40
+ :header-rows: 1
+
+ * - Offset
+ - Type
+ - Name
+ - Description
+ * - 0x0
+ - Array of \_\_le32 entries
+ - Orphan inode entries
+ - Each \_\_le32 entry is either empty (0) or it contains inode number of
+ an orphan inode.
+ * - blocksize - 8
+ - \_\_le32
+ - ob\_magic
+ - Magic value stored in orphan block tail (0x0b10ca04)
+ * - blocksize - 4
+ - \_\_le32
+ - ob\_checksum
+ - Checksum of the orphan block.
+
+When a filesystem with orphan file feature is writeably mounted, we set
+RO\_COMPAT\_ORPHAN\_PRESENT feature in the superblock to indicate there may
+be valid orphan entries. In case we see this feature when mounting the
+filesystem, we read the whole orphan file and process all orphan inodes found
+there as usual. When cleanly unmounting the filesystem we remove the
+RO\_COMPAT\_ORPHAN\_PRESENT feature to avoid unnecessary scanning of the orphan
+file and also make the filesystem fully compatible with older kernels.
diff --git a/Documentation/filesystems/ext4/special_inodes.rst b/Documentation/filesystems/ext4/special_inodes.rst
index 9061aabba827..94f304e3a0a7 100644
--- a/Documentation/filesystems/ext4/special_inodes.rst
+++ b/Documentation/filesystems/ext4/special_inodes.rst
@@ -36,3 +36,20 @@ ext4 reserves some inode for special features, as follows:
* - 11
- Traditional first non-reserved inode. Usually this is the lost+found directory. See s\_first\_ino in the superblock.
+Note that there are also some inodes allocated from non-reserved inode numbers
+for other filesystem features which are not referenced from standard directory
+hierarchy. These are generally reference from the superblock. They are:
+
+.. list-table::
+ :widths: 20 50
+ :header-rows: 1
+
+ * - Superblock field
+ - Description
+
+ * - s\_lpf\_ino
+ - Inode number of lost+found directory.
+ * - s\_prj\_quota\_inum
+ - Inode number of quota file tracking project quotas
+ * - s\_orphan\_file\_inum
+ - Inode number of file tracking orphan inodes.
diff --git a/Documentation/filesystems/ext4/super.rst b/Documentation/filesystems/ext4/super.rst
index 2eb1ab20498d..f6a548e957bb 100644
--- a/Documentation/filesystems/ext4/super.rst
+++ b/Documentation/filesystems/ext4/super.rst
@@ -479,7 +479,11 @@ The ext4 superblock is laid out as follows in
- Filename charset encoding flags.
* - 0x280
- \_\_le32
- - s\_reserved[95]
+ - s\_orphan\_file\_inum
+ - Orphan file inode number.
+ * - 0x284
+ - \_\_le32
+ - s\_reserved[94]
- Padding to the end of the block.
* - 0x3FC
- \_\_le32
@@ -603,6 +607,11 @@ following:
the journal, JBD2 incompat feature
(JBD2\_FEATURE\_INCOMPAT\_FAST\_COMMIT) gets
set (COMPAT\_FAST\_COMMIT).
+ * - 0x1000
+ - Orphan file allocated. This is the special file for more efficient
+ tracking of unlinked but still open inodes. When there may be any
+ entries in the file, we additionally set proper rocompat feature
+ (RO\_COMPAT\_ORPHAN\_PRESENT).
.. _super_incompat:
@@ -713,6 +722,10 @@ the following:
- Filesystem tracks project quotas. (RO\_COMPAT\_PROJECT)
* - 0x8000
- Verity inodes may be present on the filesystem. (RO\_COMPAT\_VERITY)
+ * - 0x10000
+ - Indicates orphan file may have valid orphan entries and thus we need
+ to clean them up when mounting the filesystem
+ (RO\_COMPAT\_ORPHAN\_PRESENT).
.. _super_def_hash:
diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index ff9e7cc97c65..09de6ebbbdfa 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -185,6 +185,7 @@ fault_type=%d Support configuring fault injection type, should be
FAULT_KVMALLOC 0x000000002
FAULT_PAGE_ALLOC 0x000000004
FAULT_PAGE_GET 0x000000008
+ FAULT_ALLOC_BIO 0x000000010 (obsolete)
FAULT_ALLOC_NID 0x000000020
FAULT_ORPHAN 0x000000040
FAULT_BLOCK 0x000000080
@@ -195,6 +196,7 @@ fault_type=%d Support configuring fault injection type, should be
FAULT_CHECKPOINT 0x000001000
FAULT_DISCARD 0x000002000
FAULT_WRITE_IO 0x000004000
+ FAULT_SLAB_ALLOC 0x000008000
=================== ===========
mode=%s Control block allocation mode which supports "adaptive"
and "lfs". In "lfs" mode, there should be no random
@@ -312,6 +314,14 @@ inlinecrypt When possible, encrypt/decrypt the contents of encrypted
Documentation/block/inline-encryption.rst.
atgc Enable age-threshold garbage collection, it provides high
effectiveness and efficiency on background GC.
+discard_unit=%s Control discard unit, the argument can be "block", "segment"
+ and "section", issued discard command's offset/size will be
+ aligned to the unit, by default, "discard_unit=block" is set,
+ so that small discard functionality is enabled.
+ For blkzoned device, "discard_unit=section" will be set by
+ default, it is helpful for large sized SMR or ZNS devices to
+ reduce memory cost by getting rid of fs metadata supports small
+ discard.
======================== ============================================================
Debugfs Entries
@@ -857,8 +867,11 @@ Compression implementation
directly in order to guarantee potential data updates later to the space.
Instead, the main goal is to reduce data writes to flash disk as much as
possible, resulting in extending disk life time as well as relaxing IO
- congestion. Alternatively, we've added ioctl interface to reclaim compressed
- space and show it to user after putting the immutable bit.
+ congestion. Alternatively, we've added ioctl(F2FS_IOC_RELEASE_COMPRESS_BLOCKS)
+ interface to reclaim compressed space and show it to user after putting the
+ immutable bit. Immutable bit, after release, it doesn't allow writing/mmaping
+ on the file, until reserving compressed space via
+ ioctl(F2FS_IOC_RESERVE_COMPRESS_BLOCKS) or truncating filesize to zero.
Compress metadata layout::
diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst
index 1a2dd4d35717..c0ad233963ae 100644
--- a/Documentation/filesystems/index.rst
+++ b/Documentation/filesystems/index.rst
@@ -101,6 +101,7 @@ Documentation for filesystem implementations.
nilfs2
nfs/index
ntfs
+ ntfs3
ocfs2
ocfs2-online-filecheck
omfs
diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
index 2a75dd5da7b5..d36fe79167b3 100644
--- a/Documentation/filesystems/locking.rst
+++ b/Documentation/filesystems/locking.rst
@@ -70,7 +70,7 @@ prototypes::
const char *(*get_link) (struct dentry *, struct inode *, struct delayed_call *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, unsigned int);
- int (*get_acl)(struct inode *, int);
+ struct posix_acl * (*get_acl)(struct inode *, int, bool);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
diff --git a/Documentation/filesystems/ntfs3.rst b/Documentation/filesystems/ntfs3.rst
new file mode 100644
index 000000000000..ffe9ea0c1499
--- /dev/null
+++ b/Documentation/filesystems/ntfs3.rst
@@ -0,0 +1,106 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====
+NTFS3
+=====
+
+
+Summary and Features
+====================
+
+NTFS3 is fully functional NTFS Read-Write driver. The driver works with
+NTFS versions up to 3.1, normal/compressed/sparse files
+and journal replaying. File system type to use on mount is 'ntfs3'.
+
+- This driver implements NTFS read/write support for normal, sparse and
+ compressed files.
+- Supports native journal replaying;
+- Supports extended attributes
+ Predefined extended attributes:
+ - 'system.ntfs_security' gets/sets security
+ descriptor (SECURITY_DESCRIPTOR_RELATIVE)
+ - 'system.ntfs_attrib' gets/sets ntfs file/dir attributes.
+ Note: applied to empty files, this allows to switch type between
+ sparse(0x200), compressed(0x800) and normal;
+- Supports NFS export of mounted NTFS volumes.
+
+Mount Options
+=============
+
+The list below describes mount options supported by NTFS3 driver in addition to
+generic ones.
+
+===============================================================================
+
+nls=name This option informs the driver how to interpret path
+ strings and translate them to Unicode and back. If
+ this option is not set, the default codepage will be
+ used (CONFIG_NLS_DEFAULT).
+ Examples:
+ 'nls=utf8'
+
+uid=
+gid=
+umask= Controls the default permissions for files/directories created
+ after the NTFS volume is mounted.
+
+fmask=
+dmask= Instead of specifying umask which applies both to
+ files and directories, fmask applies only to files and
+ dmask only to directories.
+
+nohidden Files with the Windows-specific HIDDEN (FILE_ATTRIBUTE_HIDDEN)
+ attribute will not be shown under Linux.
+
+sys_immutable Files with the Windows-specific SYSTEM
+ (FILE_ATTRIBUTE_SYSTEM) attribute will be marked as system
+ immutable files.
+
+discard Enable support of the TRIM command for improved performance
+ on delete operations, which is recommended for use with the
+ solid-state drives (SSD).
+
+force Forces the driver to mount partitions even if 'dirty' flag
+ (volume dirty) is set. Not recommended for use.
+
+sparse Create new files as "sparse".
+
+showmeta Use this parameter to show all meta-files (System Files) on
+ a mounted NTFS partition.
+ By default, all meta-files are hidden.
+
+prealloc Preallocate space for files excessively when file size is
+ increasing on writes. Decreases fragmentation in case of
+ parallel write operations to different files.
+
+no_acs_rules "No access rules" mount option sets access rights for
+ files/folders to 777 and owner/group to root. This mount
+ option absorbs all other permissions:
+ - permissions change for files/folders will be reported
+ as successful, but they will remain 777;
+ - owner/group change will be reported as successful, but
+ they will stay as root
+
+acl Support POSIX ACLs (Access Control Lists). Effective if
+ supported by Kernel. Not to be confused with NTFS ACLs.
+ The option specified as acl enables support for POSIX ACLs.
+
+noatime All files and directories will not update their last access
+ time attribute if a partition is mounted with this parameter.
+ This option can speed up file system operation.
+
+===============================================================================
+
+ToDo list
+=========
+
+- Full journaling support (currently journal replaying is supported) over JBD.
+
+
+References
+==========
+https://www.paragon-software.com/home/ntfs-linux-professional/
+ - Commercial version of the NTFS driver for Linux.
+
+almaz.alexandrovich@paragon-software.com
+ - Direct e-mail address for feedback and requests on the NTFS3 implementation.
diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst
index 455ca86eb4fc..7da6c30ed596 100644
--- a/Documentation/filesystems/overlayfs.rst
+++ b/Documentation/filesystems/overlayfs.rst
@@ -427,6 +427,9 @@ b) If a file residing on a lower layer is opened for read-only and then
memory mapped with MAP_SHARED, then subsequent changes to the file are not
reflected in the memory mapping.
+c) If a file residing on a lower layer is being executed, then opening that
+file for write or truncating the file will not be denied with ETXTBSY.
+
The following options allow overlayfs to act more like a standards
compliant filesystem:
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
index 14c31eced416..bf5c48066fac 100644
--- a/Documentation/filesystems/vfs.rst
+++ b/Documentation/filesystems/vfs.rst
@@ -432,7 +432,7 @@ As of kernel 2.6.22, the following members are defined:
const char *(*get_link) (struct dentry *, struct inode *,
struct delayed_call *);
int (*permission) (struct user_namespace *, struct inode *, int);
- int (*get_acl)(struct inode *, int);
+ struct posix_acl * (*get_acl)(struct inode *, int, bool);
int (*setattr) (struct user_namespace *, struct dentry *, struct iattr *);
int (*getattr) (struct user_namespace *, const struct path *, struct kstat *, u32, unsigned int);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
diff --git a/Documentation/firmware-guide/acpi/dsd/graph.rst b/Documentation/firmware-guide/acpi/dsd/graph.rst
index 4341299aa937..0ced07cb1be3 100644
--- a/Documentation/firmware-guide/acpi/dsd/graph.rst
+++ b/Documentation/firmware-guide/acpi/dsd/graph.rst
@@ -159,7 +159,7 @@ References
[2] Devicetree. https://www.devicetree.org, referenced 2016-10-03.
-[3] Documentation/devicetree/bindings/graph.txt
+[3] Documentation/devicetree/bindings/graph.txt
[4] Device Properties UUID For _DSD.
https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf,
diff --git a/Documentation/fpga/dfl.rst b/Documentation/fpga/dfl.rst
index 75df90d1e54c..ef9eec71f6f3 100644
--- a/Documentation/fpga/dfl.rst
+++ b/Documentation/fpga/dfl.rst
@@ -10,7 +10,7 @@ Authors:
- Xu Yilun <yilun.xu@intel.com>
The Device Feature List (DFL) FPGA framework (and drivers according to
-this framework) hides the very details of low layer hardwares and provides
+this framework) hides the very details of low layer hardware and provides
unified interfaces to userspace. Applications could use these interfaces to
configure, enumerate, open and access FPGA accelerators on platforms which
implement the DFL in the device memory. Besides this, the DFL framework
@@ -205,7 +205,7 @@ given Device Feature Lists and create platform devices for feature devices
also abstracts operations for the private features and exposes common ops to
feature device drivers.
-The FPGA DFL Device could be different hardwares, e.g. PCIe device, platform
+The FPGA DFL Device could be different hardware, e.g. PCIe device, platform
device and etc. Its driver module is always loaded first once the device is
created by the system. This driver plays an infrastructural role in the
driver architecture. It locates the DFLs in the device memory, handles them
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 87e5023e3f55..1ef7951ded5e 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -159,6 +159,8 @@ KMS Core Structures and Functions
.. kernel-doc:: drivers/gpu/drm/drm_mode_config.c
:export:
+.. _kms_base_object_abstraction:
+
Modeset Base Object Abstraction
===============================
@@ -463,6 +465,35 @@ KMS Properties
This section of the documentation is primarily aimed at user-space developers.
For the driver APIs, see the other sections.
+Requirements
+------------
+
+KMS drivers might need to add extra properties to support new features. Each
+new property introduced in a driver needs to meet a few requirements, in
+addition to the one mentioned above:
+
+* It must be standardized, documenting:
+
+ * The full, exact, name string;
+ * If the property is an enum, all the valid value name strings;
+ * What values are accepted, and what these values mean;
+ * What the property does and how it can be used;
+ * How the property might interact with other, existing properties.
+
+* It must provide a generic helper in the core code to register that
+ property on the object it attaches to.
+
+* Its content must be decoded by the core and provided in the object's
+ associated state structure. That includes anything drivers might want
+ to precompute, like struct drm_clip_rect for planes.
+
+* Its initial state must match the behavior prior to the property
+ introduction. This might be a fixed value matching what the hardware
+ does, or it may be inherited from the state the firmware left the
+ system in during boot.
+
+* An IGT test must be submitted where reasonable.
+
Property Types and Blob Property Support
----------------------------------------
@@ -508,8 +539,8 @@ Plane Composition Properties
Damage Tracking Properties
--------------------------
-.. kernel-doc:: drivers/gpu/drm/drm_damage_helper.c
- :doc: overview
+.. kernel-doc:: drivers/gpu/drm/drm_plane.c
+ :doc: damage tracking
Color Management Properties
---------------------------
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 04bdc7a91d53..199afb503ab1 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -37,6 +37,15 @@ Primary Nodes, DRM Master and Authentication
.. kernel-doc:: include/drm/drm_auth.h
:internal:
+
+.. _drm_leasing:
+
+DRM Display Resource Leasing
+============================
+
+.. kernel-doc:: drivers/gpu/drm/drm_lease.c
+ :doc: drm leasing
+
Open-Source Userspace Requirements
==================================
@@ -457,6 +466,19 @@ Userspace API Structures
.. kernel-doc:: include/uapi/drm/drm_mode.h
:doc: overview
+.. _crtc_index:
+
+CRTC index
+----------
+
+CRTC's have both an object ID and an index, and they are not the same thing.
+The index is used in cases where a densely packed identifier for a CRTC is
+needed, for instance a bitmask of CRTC's. The member possible_crtcs of struct
+drm_mode_get_plane is an example.
+
+DRM_IOCTL_MODE_GETRESOURCES populates a structure with an array of CRTC ID's,
+and the CRTC index is its position in this array.
+
.. kernel-doc:: include/uapi/drm/drm.h
:internal:
diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 42ce0196930a..204ebdaadb45 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -422,9 +422,16 @@ Batchbuffer Parsing
User Batchbuffer Execution
--------------------------
+.. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_context_types.h
+
.. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
:doc: User command execution
+Scheduling
+----------
+.. kernel-doc:: drivers/gpu/drm/i915/i915_scheduler_types.h
+ :functions: i915_sched_engine
+
Logical Rings, Logical Ring Contexts and Execlists
--------------------------------------------------
@@ -518,6 +525,14 @@ GuC-based command submission
.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
:doc: GuC-based command submission
+GuC ABI
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h
+.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h
+.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
+.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+
HuC
---
.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_huc.c
diff --git a/Documentation/gpu/rfc/i915_parallel_execbuf.h b/Documentation/gpu/rfc/i915_parallel_execbuf.h
new file mode 100644
index 000000000000..8cbe2c4e0172
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_parallel_execbuf.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#define I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT 2 /* see i915_context_engines_parallel_submit */
+
+/**
+ * struct drm_i915_context_engines_parallel_submit - Configure engine for
+ * parallel submission.
+ *
+ * Setup a slot in the context engine map to allow multiple BBs to be submitted
+ * in a single execbuf IOCTL. Those BBs will then be scheduled to run on the GPU
+ * in parallel. Multiple hardware contexts are created internally in the i915
+ * run these BBs. Once a slot is configured for N BBs only N BBs can be
+ * submitted in each execbuf IOCTL and this is implicit behavior e.g. The user
+ * doesn't tell the execbuf IOCTL there are N BBs, the execbuf IOCTL knows how
+ * many BBs there are based on the slot's configuration. The N BBs are the last
+ * N buffer objects or first N if I915_EXEC_BATCH_FIRST is set.
+ *
+ * The default placement behavior is to create implicit bonds between each
+ * context if each context maps to more than 1 physical engine (e.g. context is
+ * a virtual engine). Also we only allow contexts of same engine class and these
+ * contexts must be in logically contiguous order. Examples of the placement
+ * behavior described below. Lastly, the default is to not allow BBs to
+ * preempted mid BB rather insert coordinated preemption on all hardware
+ * contexts between each set of BBs. Flags may be added in the future to change
+ * both of these default behaviors.
+ *
+ * Returns -EINVAL if hardware context placement configuration is invalid or if
+ * the placement configuration isn't supported on the platform / submission
+ * interface.
+ * Returns -ENODEV if extension isn't supported on the platform / submission
+ * interface.
+ *
+ * .. code-block:: none
+ *
+ * Example 1 pseudo code:
+ * CS[X] = generic engine of same class, logical instance X
+ * INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
+ * set_engines(INVALID)
+ * set_parallel(engine_index=0, width=2, num_siblings=1,
+ * engines=CS[0],CS[1])
+ *
+ * Results in the following valid placement:
+ * CS[0], CS[1]
+ *
+ * Example 2 pseudo code:
+ * CS[X] = generic engine of same class, logical instance X
+ * INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
+ * set_engines(INVALID)
+ * set_parallel(engine_index=0, width=2, num_siblings=2,
+ * engines=CS[0],CS[2],CS[1],CS[3])
+ *
+ * Results in the following valid placements:
+ * CS[0], CS[1]
+ * CS[2], CS[3]
+ *
+ * This can also be thought of as 2 virtual engines described by 2-D array
+ * in the engines the field with bonds placed between each index of the
+ * virtual engines. e.g. CS[0] is bonded to CS[1], CS[2] is bonded to
+ * CS[3].
+ * VE[0] = CS[0], CS[2]
+ * VE[1] = CS[1], CS[3]
+ *
+ * Example 3 pseudo code:
+ * CS[X] = generic engine of same class, logical instance X
+ * INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
+ * set_engines(INVALID)
+ * set_parallel(engine_index=0, width=2, num_siblings=2,
+ * engines=CS[0],CS[1],CS[1],CS[3])
+ *
+ * Results in the following valid and invalid placements:
+ * CS[0], CS[1]
+ * CS[1], CS[3] - Not logical contiguous, return -EINVAL
+ */
+struct drm_i915_context_engines_parallel_submit {
+ /**
+ * @base: base user extension.
+ */
+ struct i915_user_extension base;
+
+ /**
+ * @engine_index: slot for parallel engine
+ */
+ __u16 engine_index;
+
+ /**
+ * @width: number of contexts per parallel engine
+ */
+ __u16 width;
+
+ /**
+ * @num_siblings: number of siblings per context
+ */
+ __u16 num_siblings;
+
+ /**
+ * @mbz16: reserved for future use; must be zero
+ */
+ __u16 mbz16;
+
+ /**
+ * @flags: all undefined flags must be zero, currently not defined flags
+ */
+ __u64 flags;
+
+ /**
+ * @mbz64: reserved for future use; must be zero
+ */
+ __u64 mbz64[3];
+
+ /**
+ * @engines: 2-d array of engine instances to configure parallel engine
+ *
+ * length = width (i) * num_siblings (j)
+ * index = j + i * num_siblings
+ */
+ struct i915_engine_class_instance engines[0];
+
+} __packed;
+
diff --git a/Documentation/gpu/rfc/i915_scheduler.rst b/Documentation/gpu/rfc/i915_scheduler.rst
new file mode 100644
index 000000000000..cbda75065dad
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_scheduler.rst
@@ -0,0 +1,148 @@
+=========================================
+I915 GuC Submission/DRM Scheduler Section
+=========================================
+
+Upstream plan
+=============
+For upstream the overall plan for landing GuC submission and integrating the
+i915 with the DRM scheduler is:
+
+* Merge basic GuC submission
+ * Basic submission support for all gen11+ platforms
+ * Not enabled by default on any current platforms but can be enabled via
+ modparam enable_guc
+ * Lots of rework will need to be done to integrate with DRM scheduler so
+ no need to nit pick everything in the code, it just should be
+ functional, no major coding style / layering errors, and not regress
+ execlists
+ * Update IGTs / selftests as needed to work with GuC submission
+ * Enable CI on supported platforms for a baseline
+ * Rework / get CI heathly for GuC submission in place as needed
+* Merge new parallel submission uAPI
+ * Bonding uAPI completely incompatible with GuC submission, plus it has
+ severe design issues in general, which is why we want to retire it no
+ matter what
+ * New uAPI adds I915_CONTEXT_ENGINES_EXT_PARALLEL context setup step
+ which configures a slot with N contexts
+ * After I915_CONTEXT_ENGINES_EXT_PARALLEL a user can submit N batches to
+ a slot in a single execbuf IOCTL and the batches run on the GPU in
+ paralllel
+ * Initially only for GuC submission but execlists can be supported if
+ needed
+* Convert the i915 to use the DRM scheduler
+ * GuC submission backend fully integrated with DRM scheduler
+ * All request queues removed from backend (e.g. all backpressure
+ handled in DRM scheduler)
+ * Resets / cancels hook in DRM scheduler
+ * Watchdog hooks into DRM scheduler
+ * Lots of complexity of the GuC backend can be pulled out once
+ integrated with DRM scheduler (e.g. state machine gets
+ simplier, locking gets simplier, etc...)
+ * Execlists backend will minimum required to hook in the DRM scheduler
+ * Legacy interface
+ * Features like timeslicing / preemption / virtual engines would
+ be difficult to integrate with the DRM scheduler and these
+ features are not required for GuC submission as the GuC does
+ these things for us
+ * ROI low on fully integrating into DRM scheduler
+ * Fully integrating would add lots of complexity to DRM
+ scheduler
+ * Port i915 priority inheritance / boosting feature in DRM scheduler
+ * Used for i915 page flip, may be useful to other DRM drivers as
+ well
+ * Will be an optional feature in the DRM scheduler
+ * Remove in-order completion assumptions from DRM scheduler
+ * Even when using the DRM scheduler the backends will handle
+ preemption, timeslicing, etc... so it is possible for jobs to
+ finish out of order
+ * Pull out i915 priority levels and use DRM priority levels
+ * Optimize DRM scheduler as needed
+
+TODOs for GuC submission upstream
+=================================
+
+* Need an update to GuC firmware / i915 to enable error state capture
+* Open source tool to decode GuC logs
+* Public GuC spec
+
+New uAPI for basic GuC submission
+=================================
+No major changes are required to the uAPI for basic GuC submission. The only
+change is a new scheduler attribute: I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP.
+This attribute indicates the 2k i915 user priority levels are statically mapped
+into 3 levels as follows:
+
+* -1k to -1 Low priority
+* 0 Medium priority
+* 1 to 1k High priority
+
+This is needed because the GuC only has 4 priority bands. The highest priority
+band is reserved with the kernel. This aligns with the DRM scheduler priority
+levels too.
+
+Spec references:
+----------------
+* https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt
+* https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap5.html#devsandqueues-priority
+* https://spec.oneapi.com/level-zero/latest/core/api.html#ze-command-queue-priority-t
+
+New parallel submission uAPI
+============================
+The existing bonding uAPI is completely broken with GuC submission because
+whether a submission is a single context submit or parallel submit isn't known
+until execbuf time activated via the I915_SUBMIT_FENCE. To submit multiple
+contexts in parallel with the GuC the context must be explicitly registered with
+N contexts and all N contexts must be submitted in a single command to the GuC.
+The GuC interfaces do not support dynamically changing between N contexts as the
+bonding uAPI does. Hence the need for a new parallel submission interface. Also
+the legacy bonding uAPI is quite confusing and not intuitive at all. Furthermore
+I915_SUBMIT_FENCE is by design a future fence, so not really something we should
+continue to support.
+
+The new parallel submission uAPI consists of 3 parts:
+
+* Export engines logical mapping
+* A 'set_parallel' extension to configure contexts for parallel
+ submission
+* Extend execbuf2 IOCTL to support submitting N BBs in a single IOCTL
+
+Export engines logical mapping
+------------------------------
+Certain use cases require BBs to be placed on engine instances in logical order
+(e.g. split-frame on gen11+). The logical mapping of engine instances can change
+based on fusing. Rather than making UMDs be aware of fusing, simply expose the
+logical mapping with the existing query engine info IOCTL. Also the GuC
+submission interface currently only supports submitting multiple contexts to
+engines in logical order which is a new requirement compared to execlists.
+Lastly, all current platforms have at most 2 engine instances and the logical
+order is the same as uAPI order. This will change on platforms with more than 2
+engine instances.
+
+A single bit will be added to drm_i915_engine_info.flags indicating that the
+logical instance has been returned and a new field,
+drm_i915_engine_info.logical_instance, returns the logical instance.
+
+A 'set_parallel' extension to configure contexts for parallel submission
+------------------------------------------------------------------------
+The 'set_parallel' extension configures a slot for parallel submission of N BBs.
+It is a setup step that must be called before using any of the contexts. See
+I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE or I915_CONTEXT_ENGINES_EXT_BOND for
+similar existing examples. Once a slot is configured for parallel submission the
+execbuf2 IOCTL can be called submitting N BBs in a single IOCTL. Initially only
+supports GuC submission. Execlists supports can be added later if needed.
+
+Add I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT and
+drm_i915_context_engines_parallel_submit to the uAPI to implement this
+extension.
+
+.. kernel-doc:: Documentation/gpu/rfc/i915_parallel_execbuf.h
+ :functions: drm_i915_context_engines_parallel_submit
+
+Extend execbuf2 IOCTL to support submitting N BBs in a single IOCTL
+-------------------------------------------------------------------
+Contexts that have been configured with the 'set_parallel' extension can only
+submit N BBs in a single execbuf2 IOCTL. The BBs are either the last N objects
+in the drm_i915_gem_exec_object2 list or the first N if I915_EXEC_BATCH_FIRST is
+set. The number of BBs is implicit based on the slot submitted and how it has
+been configured by 'set_parallel' or other extensions. No uAPI changes are
+required to the execbuf2 IOCTL.
diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/index.rst
index 05670442ca1b..91e93a705230 100644
--- a/Documentation/gpu/rfc/index.rst
+++ b/Documentation/gpu/rfc/index.rst
@@ -19,3 +19,7 @@ host such documentation:
.. toctree::
i915_gem_lmem.rst
+
+.. toctree::
+
+ i915_scheduler.rst
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 2c9b376da5ca..941f0e7e5eef 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -98,9 +98,17 @@ with VKMS maintainers.
IGT better support
------------------
-- Investigate: (1) test cases on kms_plane that are failing due to timeout on
- capturing CRC; (2) when running kms_flip test cases in sequence, some
- successful individual test cases are failing randomly.
+Debugging:
+
+- kms_plane: some test cases are failing due to timeout on capturing CRC;
+
+- kms_flip: when running test cases in sequence, some successful individual
+ test cases are failing randomly; when individually, some successful test
+ cases display in the log the following error::
+
+ [drm:vkms_prepare_fb [vkms]] ERROR vmap failed: -4
+
+Virtual hardware (vblank-less) mode:
- VKMS already has support for vblanks simulated via hrtimers, which can be
tested with kms_flip test; in some way, we can say that VKMS already mimics
@@ -116,7 +124,17 @@ Add Plane Features
There's lots of plane features we could add support for:
-- Real overlay planes, not just cursor.
+- Multiple overlay planes. [Good to get started]
+
+- Clearing primary plane: clear primary plane before plane composition (at the
+ start) for correctness of pixel blend ops. It also guarantees alpha channel
+ is cleared in the target buffer for stable crc. [Good to get started]
+
+- ARGB format on primary plane: blend the primary plane into background with
+ translucent alpha.
+
+- Support when the primary plane isn't exactly matching the output size: blend
+ the primary plane into the black background.
- Full alpha blending on all planes.
@@ -129,13 +147,8 @@ There's lots of plane features we could add support for:
cursor api).
For all of these, we also want to review the igt test coverage and make sure
-all relevant igt testcases work on vkms.
-
-Prime Buffer Sharing
---------------------
-
-- Syzbot report - WARNING in vkms_gem_free_object:
- https://syzkaller.appspot.com/bug?extid=e7ad70d406e74d8fc9d0
+all relevant igt testcases work on vkms. They are good options for internship
+project.
Runtime Configuration
---------------------
@@ -153,7 +166,7 @@ module. Use/Test-cases:
the refresh rate.
The currently proposed solution is to expose vkms configuration through
-configfs. All existing module options should be supported through configfs
+configfs. All existing module options should be supported through configfs
too.
Writeback support
@@ -162,6 +175,7 @@ Writeback support
- The writeback and CRC capture operations share the use of composer_enabled
boolean to ensure vblanks. Probably, when these operations work together,
composer_enabled needs to refcounting the composer state to proper work.
+ [Good to get started]
- Add support for cloned writeback outputs and related test cases using a
cloned output in the IGT kms_writeback.
diff --git a/Documentation/kbuild/llvm.rst b/Documentation/kbuild/llvm.rst
index b18401d2ba82..e87ed5479963 100644
--- a/Documentation/kbuild/llvm.rst
+++ b/Documentation/kbuild/llvm.rst
@@ -38,7 +38,7 @@ Cross Compiling
A single Clang compiler binary will typically contain all supported backends,
which can help simplify cross compiling. ::
- ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make CC=clang
+ make ARCH=arm64 CC=clang CROSS_COMPILE=aarch64-linux-gnu-
``CROSS_COMPILE`` is not used to prefix the Clang compiler binary, instead
``CROSS_COMPILE`` is used to set a command line flag: ``--target=<triple>``. For
@@ -60,8 +60,27 @@ They can be enabled individually. The full list of the parameters: ::
OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump READELF=llvm-readelf \
HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar HOSTLD=ld.lld
-Currently, the integrated assembler is disabled by default. You can pass
-``LLVM_IAS=1`` to enable it.
+The integrated assembler is enabled by default. You can pass ``LLVM_IAS=0`` to
+disable it.
+
+Omitting CROSS_COMPILE
+----------------------
+
+As explained above, ``CROSS_COMPILE`` is used to set ``--target=<triple>``.
+
+If ``CROSS_COMPILE`` is not specified, the ``--target=<triple>`` is inferred
+from ``ARCH``.
+
+That means if you use only LLVM tools, ``CROSS_COMPILE`` becomes unnecessary.
+
+For example, to cross-compile the arm64 kernel::
+
+ make ARCH=arm64 LLVM=1
+
+If ``LLVM_IAS=0`` is specified, ``CROSS_COMPILE`` is also used to derive
+``--prefix=<path>`` to search for the GNU assembler and linker. ::
+
+ make ARCH=arm64 LLVM=1 LLVM_IAS=0 CROSS_COMPILE=aarch64-linux-gnu-
Supported Architectures
-----------------------
diff --git a/Documentation/networking/device_drivers/ethernet/freescale/dpaa2/dpio-driver.rst b/Documentation/networking/device_drivers/ethernet/freescale/dpaa2/dpio-driver.rst
index c50fd46631e0..e4ebfe62a183 100644
--- a/Documentation/networking/device_drivers/ethernet/freescale/dpaa2/dpio-driver.rst
+++ b/Documentation/networking/device_drivers/ethernet/freescale/dpaa2/dpio-driver.rst
@@ -1,5 +1,6 @@
.. include:: <isonum.txt>
+===================================
DPAA2 DPIO (Data Path I/O) Overview
===================================
diff --git a/Documentation/networking/nf_conntrack-sysctl.rst b/Documentation/networking/nf_conntrack-sysctl.rst
index 34ca762ea56f..311128abb768 100644
--- a/Documentation/networking/nf_conntrack-sysctl.rst
+++ b/Documentation/networking/nf_conntrack-sysctl.rst
@@ -17,9 +17,8 @@ nf_conntrack_acct - BOOLEAN
nf_conntrack_buckets - INTEGER
Size of hash table. If not specified as parameter during module
loading, the default size is calculated by dividing total memory
- by 16384 to determine the number of buckets but the hash table will
- never have fewer than 32 and limited to 16384 buckets. For systems
- with more than 4GB of memory it will be 65536 buckets.
+ by 16384 to determine the number of buckets. The hash table will
+ never have fewer than 1024 and never more than 262144 buckets.
This sysctl is only writeable in the initial net namespace.
nf_conntrack_checksum - BOOLEAN
@@ -100,8 +99,12 @@ nf_conntrack_log_invalid - INTEGER
Log invalid packets of a type specified by value.
nf_conntrack_max - INTEGER
- Size of connection tracking table. Default value is
- nf_conntrack_buckets value * 4.
+ Maximum number of allowed connection tracking entries. This value is set
+ to nf_conntrack_buckets by default.
+ Note that connection tracking entries are added to the table twice -- once
+ for the original direction and once for the reply direction (i.e., with
+ the reversed address). This means that with default settings a maxed-out
+ table will have a average hash chain length of 2, not 1.
nf_conntrack_tcp_be_liberal - BOOLEAN
- 0 - disabled (default)
diff --git a/Documentation/powerpc/associativity.rst b/Documentation/powerpc/associativity.rst
new file mode 100644
index 000000000000..4d01c7368561
--- /dev/null
+++ b/Documentation/powerpc/associativity.rst
@@ -0,0 +1,105 @@
+============================
+NUMA resource associativity
+============================
+
+Associativity represents the groupings of the various platform resources into
+domains of substantially similar mean performance relative to resources outside
+of that domain. Resources subsets of a given domain that exhibit better
+performance relative to each other than relative to other resources subsets
+are represented as being members of a sub-grouping domain. This performance
+characteristic is presented in terms of NUMA node distance within the Linux kernel.
+From the platform view, these groups are also referred to as domains.
+
+PAPR interface currently supports different ways of communicating these resource
+grouping details to the OS. These are referred to as Form 0, Form 1 and Form2
+associativity grouping. Form 0 is the oldest format and is now considered deprecated.
+
+Hypervisor indicates the type/form of associativity used via "ibm,architecture-vec-5 property".
+Bit 0 of byte 5 in the "ibm,architecture-vec-5" property indicates usage of Form 0 or Form 1.
+A value of 1 indicates the usage of Form 1 associativity. For Form 2 associativity
+bit 2 of byte 5 in the "ibm,architecture-vec-5" property is used.
+
+Form 0
+------
+Form 0 associativity supports only two NUMA distances (LOCAL and REMOTE).
+
+Form 1
+------
+With Form 1 a combination of ibm,associativity-reference-points, and ibm,associativity
+device tree properties are used to determine the NUMA distance between resource groups/domains.
+
+The “ibm,associativity” property contains a list of one or more numbers (domainID)
+representing the resource’s platform grouping domains.
+
+The “ibm,associativity-reference-points” property contains a list of one or more numbers
+(domainID index) that represents the 1 based ordinal in the associativity lists.
+The list of domainID indexes represents an increasing hierarchy of resource grouping.
+
+ex:
+{ primary domainID index, secondary domainID index, tertiary domainID index.. }
+
+Linux kernel uses the domainID at the primary domainID index as the NUMA node id.
+Linux kernel computes NUMA distance between two domains by recursively comparing
+if they belong to the same higher-level domains. For mismatch at every higher
+level of the resource group, the kernel doubles the NUMA distance between the
+comparing domains.
+
+Form 2
+-------
+Form 2 associativity format adds separate device tree properties representing NUMA node distance
+thereby making the node distance computation flexible. Form 2 also allows flexible primary
+domain numbering. With numa distance computation now detached from the index value in
+"ibm,associativity-reference-points" property, Form 2 allows a large number of primary domain
+ids at the same domainID index representing resource groups of different performance/latency
+characteristics.
+
+Hypervisor indicates the usage of FORM2 associativity using bit 2 of byte 5 in the
+"ibm,architecture-vec-5" property.
+
+"ibm,numa-lookup-index-table" property contains a list of one or more numbers representing
+the domainIDs present in the system. The offset of the domainID in this property is
+used as an index while computing numa distance information via "ibm,numa-distance-table".
+
+prop-encoded-array: The number N of the domainIDs encoded as with encode-int, followed by
+N domainID encoded as with encode-int
+
+For ex:
+"ibm,numa-lookup-index-table" = {4, 0, 8, 250, 252}. The offset of domainID 8 (2) is used when
+computing the distance of domain 8 from other domains present in the system. For the rest of
+this document, this offset will be referred to as domain distance offset.
+
+"ibm,numa-distance-table" property contains a list of one or more numbers representing the NUMA
+distance between resource groups/domains present in the system.
+
+prop-encoded-array: The number N of the distance values encoded as with encode-int, followed by
+N distance values encoded as with encode-bytes. The max distance value we could encode is 255.
+The number N must be equal to the square of m where m is the number of domainIDs in the
+numa-lookup-index-table.
+
+For ex:
+ibm,numa-lookup-index-table = <3 0 8 40>;
+ibm,numa-distace-table = <9>, /bits/ 8 < 10 20 80 20 10 160 80 160 10>;
+
+::
+
+ | 0 8 40
+ --|------------
+ |
+ 0 | 10 20 80
+ |
+ 8 | 20 10 160
+ |
+ 40| 80 160 10
+
+A possible "ibm,associativity" property for resources in node 0, 8 and 40
+
+{ 3, 6, 7, 0 }
+{ 3, 6, 9, 8 }
+{ 3, 6, 7, 40}
+
+With "ibm,associativity-reference-points" { 0x3 }
+
+"ibm,lookup-index-table" helps in having a compact representation of distance matrix.
+Since domainID can be sparse, the matrix of distances can also be effectively sparse.
+With "ibm,lookup-index-table" we can achieve a compact representation of
+distance information.
diff --git a/Documentation/powerpc/index.rst b/Documentation/powerpc/index.rst
index bf5f1a2bdbdf..0f7d3c495693 100644
--- a/Documentation/powerpc/index.rst
+++ b/Documentation/powerpc/index.rst
@@ -7,6 +7,7 @@ powerpc
.. toctree::
:maxdepth: 1
+ associativity
booting
bootwrapper
cpu_families
diff --git a/Documentation/process/deprecated.rst b/Documentation/process/deprecated.rst
index 9d83b8db8874..8ced754a5a0f 100644
--- a/Documentation/process/deprecated.rst
+++ b/Documentation/process/deprecated.rst
@@ -164,7 +164,9 @@ Paraphrasing Linus's current `guidance <https://lore.kernel.org/lkml/CA+55aFwQEd
up to Linus's scrutiny, maybe you can use "%px", along with making sure
you have sensible permissions.
-And finally, know that a toggle for "%p" hashing will `not be accepted <https://lore.kernel.org/lkml/CA+55aFwieC1-nAs+NFq9RTwaR8ef9hWa4MjNBWL41F-8wM49eA@mail.gmail.com/>`_.
+If you are debugging something where "%p" hashing is causing problems,
+you can temporarily boot with the debug flag "`no_hash_pointers
+<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_".
Variable Length Arrays (VLAs)
-----------------------------
diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst
index 0852bcf73630..8ad6b93f91e6 100644
--- a/Documentation/process/submitting-patches.rst
+++ b/Documentation/process/submitting-patches.rst
@@ -216,11 +216,11 @@ cannot find a maintainer for the subsystem you are working on, Andrew
Morton (akpm@linux-foundation.org) serves as a maintainer of last resort.
You should also normally choose at least one mailing list to receive a copy
-of your patch set. linux-kernel@vger.kernel.org functions as a list of
-last resort, but the volume on that list has caused a number of developers
-to tune it out. Look in the MAINTAINERS file for a subsystem-specific
-list; your patch will probably get more attention there. Please do not
-spam unrelated lists, though.
+of your patch set. linux-kernel@vger.kernel.org should be used by default
+for all patches, but the volume on that list has caused a number of
+developers to tune it out. Look in the MAINTAINERS file for a
+subsystem-specific list; your patch will probably get more attention there.
+Please do not spam unrelated lists, though.
Many kernel-related lists are hosted on vger.kernel.org; you can find a
list of them at http://vger.kernel.org/vger-lists.html. There are
diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
index b36af65a08ed..65f61695f561 100644
--- a/Documentation/sound/alsa-configuration.rst
+++ b/Documentation/sound/alsa-configuration.rst
@@ -1059,6 +1059,12 @@ The model name ``generic`` is treated as a special case. When this
model is given, the driver uses the generic codec parser without
"codec-patch". It's sometimes good for testing and debugging.
+The model option can be used also for aliasing to another PCI or codec
+SSID. When it's passed in the form of ``model=XXXX:YYYY`` where XXXX
+and YYYY are the sub-vendor and sub-device IDs in hex numbers,
+respectively, the driver will refer to that SSID as a reference to the
+quirk table.
+
If the default configuration doesn't work and one of the above
matches with your device, report it together with alsa-info.sh
output (with ``--no-upload`` option) to kernel bugzilla or alsa-devel
@@ -2252,6 +2258,27 @@ delayed_register
The driver prints a message like "Found post-registration device
assignment: 1234abcd:04" for such a device, so that user can
notice the need.
+quirk_flags
+ Contains the bit flags for various device specific workarounds.
+ Applied to the corresponding card index.
+
+ * bit 0: Skip reading sample rate for devices
+ * bit 1: Create Media Controller API entries
+ * bit 2: Allow alignment on audio sub-slot at transfer
+ * bit 3: Add length specifier to transfers
+ * bit 4: Start playback stream at first in implement feedback mode
+ * bit 5: Skip clock selector setup
+ * bit 6: Ignore errors from clock source search
+ * bit 7: Indicates ITF-USB DSD based DACs
+ * bit 8: Add a delay of 20ms at each control message handling
+ * bit 9: Add a delay of 1-2ms at each control message handling
+ * bit 10: Add a delay of 5-6ms at each control message handling
+ * bit 11: Add a delay of 50ms at each interface setup
+ * bit 12: Perform sample rate validations at probe
+ * bit 13: Disable runtime PM autosuspend
+ * bit 14: Ignore errors for mixer access
+ * bit 15: Support generic DSD raw U32_BE format
+ * bit 16: Set up the interface at first like UAC1
This module supports multiple devices, autoprobe and hotplugging.
@@ -2261,11 +2288,14 @@ check.
NB: ``ignore_ctl_error=1`` may help when you get an error at accessing
the mixer element such as URB error -22. This happens on some
-buggy USB device or the controller.
+buggy USB device or the controller. This workaround corresponds to
+the ``quirk_flags`` bit 14, too.
-NB: quirk_alias option is provided only for testing / development.
+NB: ``quirk_alias`` option is provided only for testing / development.
If you want to have a proper support, contact to upstream for
adding the matching quirk in the driver code statically.
+Ditto for ``quirk_flags``. If a device is known to require specific
+workarounds, please report to the upstream.
Module snd-usb-caiaq
--------------------
diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst
index cf4d7158af78..d118b6fe269b 100644
--- a/Documentation/sound/hd-audio/notes.rst
+++ b/Documentation/sound/hd-audio/notes.rst
@@ -215,6 +215,17 @@ There are a few special model option values:
* when ``generic`` is passed, the codec-specific parser is skipped and
only the generic parser is used.
+A new style for the model option that was introduced since 5.15 kernel
+is to pass the PCI or codec SSID in the form of ``model=XXXX:YYYY``
+where XXXX and YYYY are the sub-vendor and sub-device IDs in hex
+numbers, respectively. This is a kind of aliasing to another device;
+when this form is given, the driver will refer to that SSID as a
+reference to the quirk table. It'd be useful especially when the
+target quirk isn't listed in the model table. For example, passing
+model=103c:8862 will apply the quirk for HP ProBook 445 G8 (which
+isn't found in the model table as of writing) as long as the device is
+handled equivalently by the same driver.
+
Speaker and Headphone Output
----------------------------
diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
index 01d59b8aea92..176b73583b7a 100644
--- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
+++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
@@ -3368,7 +3368,7 @@ This ensures that the device can be closed and the driver unloaded
without losing data.
This callback is optional. If you do not set ``drain`` in the struct
-snd_rawmidi_ops structure, ALSA will simply wait for 50 milliseconds
+snd_rawmidi_ops structure, ALSA will simply wait for 50 milliseconds
instead.
Miscellaneous Devices
@@ -4172,6 +4172,39 @@ module license as GPL, etc., otherwise the system is shown as “tainted”.
MODULE_LICENSE("GPL");
+Device-Managed Resources
+========================
+
+In the examples above, all resources are allocated and released
+manually. But human beings are lazy in nature, especially developers
+are lazier. So there are some ways to automate the release part; it's
+the (device-)managed resources aka devres or devm family. For
+example, an object allocated via :c:func:`devm_kmalloc()` will be
+freed automatically at unbinding the device.
+
+ALSA core provides also the device-managed helper, namely,
+:c:func:`snd_devm_card_new()` for creating a card object.
+Call this functions instead of the normal :c:func:`snd_card_new()`,
+and you can forget the explicit :c:func:`snd_card_free()` call, as
+it's called automagically at error and removal paths.
+
+One caveat is that the call of :c:func:`snd_card_free()` would be put
+at the beginning of the call chain only after you call
+:c:func:`snd_card_register()`.
+
+Also, the ``private_free`` callback is always called at the card free,
+so be careful to put the hardware clean-up procedure in
+``private_free`` callback. It might be called even before you
+actually set up at an earlier error path. For avoiding such an
+invalid initialization, you can set ``private_free`` callback after
+:c:func:`snd_card_register()` call succeeds.
+
+Another thing to be remarked is that you should use device-managed
+helpers for each component as much as possible once when you manage
+the card in that way. Mixing up with the normal and the managed
+resources may screw up the release order.
+
+
How To Put Your Driver Into ALSA Tree
=====================================
diff --git a/Documentation/sphinx/requirements.txt b/Documentation/sphinx/requirements.txt
index 489f6626de67..9a35f50798a6 100644
--- a/Documentation/sphinx/requirements.txt
+++ b/Documentation/sphinx/requirements.txt
@@ -1,3 +1,2 @@
-docutils
-Sphinx==2.4.4
sphinx_rtd_theme
+Sphinx==2.4.4
diff --git a/Documentation/trace/boottime-trace.rst b/Documentation/trace/boottime-trace.rst
index 8053898cfeb4..6dcfbc64014d 100644
--- a/Documentation/trace/boottime-trace.rst
+++ b/Documentation/trace/boottime-trace.rst
@@ -125,6 +125,71 @@ Note that kprobe and synthetic event definitions can be written under
instance node, but those are also visible from other instances. So please
take care for event name conflict.
+Ftrace Histogram Options
+------------------------
+
+Since it is too long to write a histogram action as a string for per-event
+action option, there are tree-style options under per-event 'hist' subkey
+for the histogram actions. For the detail of the each parameter,
+please read the event histogram document [3]_.
+
+.. [3] See :ref:`Documentation/trace/histogram.rst <histogram>`
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]keys = KEY1[, KEY2[...]]
+ Set histogram key parameters. (Mandatory)
+ The 'N' is a digit string for the multiple histogram. You can omit it
+ if there is one histogram on the event.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]values = VAL1[, VAL2[...]]
+ Set histogram value parameters.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]sort = SORT1[, SORT2[...]]
+ Set histogram sort parameter options.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]size = NR_ENTRIES
+ Set histogram size (number of entries).
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]name = NAME
+ Set histogram name.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]var.VARIABLE = EXPR
+ Define a new VARIABLE by EXPR expression.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]<pause|continue|clear>
+ Set histogram control parameter. You can set one of them.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]onmatch.[M.]event = GROUP.EVENT
+ Set histogram 'onmatch' handler matching event parameter.
+ The 'M' is a digit string for the multiple 'onmatch' handler. You can omit it
+ if there is one 'onmatch' handler on this histogram.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]onmatch.[M.]trace = EVENT[, ARG1[...]]
+ Set histogram 'trace' action for 'onmatch'.
+ EVENT must be a synthetic event name, and ARG1... are parameters
+ for that event. Mandatory if 'onmatch.event' option is set.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]onmax.[M.]var = VAR
+ Set histogram 'onmax' handler variable parameter.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]onchange.[M.]var = VAR
+ Set histogram 'onchange' handler variable parameter.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]<onmax|onchange>.[M.]save = ARG1[, ARG2[...]]
+ Set histogram 'save' action parameters for 'onmax' or 'onchange' handler.
+ This option or below 'snapshot' option is mandatory if 'onmax.var' or
+ 'onchange.var' option is set.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.[N.]<onmax|onchange>.[M.]snapshot
+ Set histogram 'snapshot' action for 'onmax' or 'onchange' handler.
+ This option or above 'save' option is mandatory if 'onmax.var' or
+ 'onchange.var' option is set.
+
+ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist.filter = FILTER_EXPR
+ Set histogram filter expression. You don't need 'if' in the FILTER_EXPR.
+
+Note that this 'hist' option can conflict with the per-event 'actions'
+option if the 'actions' option has a histogram action.
+
When to Start
=============
@@ -159,13 +224,23 @@ below::
}
synthetic.initcall_latency {
fields = "unsigned long func", "u64 lat"
- actions = "hist:keys=func.sym,lat:vals=lat:sort=lat"
+ hist {
+ keys = func.sym, lat
+ values = lat
+ sort = lat
+ }
}
- initcall.initcall_start {
- actions = "hist:keys=func:ts0=common_timestamp.usecs"
+ initcall.initcall_start.hist {
+ keys = func
+ var.ts0 = common_timestamp.usecs
}
- initcall.initcall_finish {
- actions = "hist:keys=func:lat=common_timestamp.usecs-$ts0:onmatch(initcall.initcall_start).initcall_latency(func,$lat)"
+ initcall.initcall_finish.hist {
+ keys = func
+ var.lat = common_timestamp.usecs - $ts0
+ onmatch {
+ event = initcall.initcall_start
+ trace = initcall_latency, func, $lat
+ }
}
}
diff --git a/Documentation/trace/coresight/coresight-config.rst b/Documentation/trace/coresight/coresight-config.rst
new file mode 100644
index 000000000000..a4e3ef295240
--- /dev/null
+++ b/Documentation/trace/coresight/coresight-config.rst
@@ -0,0 +1,244 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================================
+CoreSight System Configuration Manager
+======================================
+
+ :Author: Mike Leach <mike.leach@linaro.org>
+ :Date: October 2020
+
+Introduction
+============
+
+The CoreSight System Configuration manager is an API that allows the
+programming of the CoreSight system with pre-defined configurations that
+can then be easily enabled from sysfs or perf.
+
+Many CoreSight components can be programmed in complex ways - especially ETMs.
+In addition, components can interact across the CoreSight system, often via
+the cross trigger components such as CTI and CTM. These system settings can
+be defined and enabled as named configurations.
+
+
+Basic Concepts
+==============
+
+This section introduces the basic concepts of a CoreSight system configuration.
+
+
+Features
+--------
+
+A feature is a named set of programming for a CoreSight device. The programming
+is device dependent, and can be defined in terms of absolute register values,
+resource usage and parameter values.
+
+The feature is defined using a descriptor. This descriptor is used to load onto
+a matching device, either when the feature is loaded into the system, or when the
+CoreSight device is registered with the configuration manager.
+
+The load process involves interpreting the descriptor into a set of register
+accesses in the driver - the resource usage and parameter descriptions
+translated into appropriate register accesses. This interpretation makes it easy
+and efficient for the feature to be programmed onto the device when required.
+
+The feature will not be active on the device until the feature is enabled, and
+the device itself is enabled. When the device is enabled then enabled features
+will be programmed into the device hardware.
+
+A feature is enabled as part of a configuration being enabled on the system.
+
+
+Parameter Value
+~~~~~~~~~~~~~~~
+
+A parameter value is a named value that may be set by the user prior to the
+feature being enabled that can adjust the behaviour of the operation programmed
+by the feature.
+
+For example, this could be a count value in a programmed operation that repeats
+at a given rate. When the feature is enabled then the current value of the
+parameter is used in programming the device.
+
+The feature descriptor defines a default value for a parameter, which is used
+if the user does not supply a new value.
+
+Users can update parameter values using the configfs API for the CoreSight
+system - which is described below.
+
+The current value of the parameter is loaded into the device when the feature
+is enabled on that device.
+
+
+Configurations
+--------------
+
+A configuration defines a set of features that are to be used in a trace
+session where the configuration is selected. For any trace session only one
+configuration may be selected.
+
+The features defined may be on any type of device that is registered
+to support system configuration. A configuration may select features to be
+enabled on a class of devices - i.e. any ETMv4, or specific devices, e.g. a
+specific CTI on the system.
+
+As with the feature, a descriptor is used to define the configuration.
+This will define the features that must be enabled as part of the configuration
+as well as any preset values that can be used to override default parameter
+values.
+
+
+Preset Values
+~~~~~~~~~~~~~
+
+Preset values are easily selectable sets of parameter values for the features
+that the configuration uses. The number of values in a single preset set, equals
+the sum of parameter values in the features used by the configuration.
+
+e.g. a configuration consists of 3 features, one has 2 parameters, one has
+a single parameter, and another has no parameters. A single preset set will
+therefore have 3 values.
+
+Presets are optionally defined by the configuration, up to 15 can be defined.
+If no preset is selected, then the parameter values defined in the feature
+are used as normal.
+
+
+Operation
+~~~~~~~~~
+
+The following steps take place in the operation of a configuration.
+
+1) In this example, the configuration is 'autofdo', which has an
+ associated feature 'strobing' that works on ETMv4 CoreSight Devices.
+
+2) The configuration is enabled. For example 'perf' may select the
+ configuration as part of its command line::
+
+ perf record -e cs_etm/autofdo/ myapp
+
+ which will enable the 'autofdo' configuration.
+
+3) perf starts tracing on the system. As each ETMv4 that perf uses for
+ trace is enabled, the configuration manager will check if the ETMv4
+ has a feature that relates to the currently active configuration.
+ In this case 'strobing' is enabled & programmed into the ETMv4.
+
+4) When the ETMv4 is disabled, any registers marked as needing to be
+ saved will be read back.
+
+5) At the end of the perf session, the configuration will be disabled.
+
+
+Viewing Configurations and Features
+===================================
+
+The set of configurations and features that are currently loaded into the
+system can be viewed using the configfs API.
+
+Mount configfs as normal and the 'cs-syscfg' subsystem will appear::
+
+ $ ls /config
+ cs-syscfg stp-policy
+
+This has two sub-directories::
+
+ $ cd cs-syscfg/
+ $ ls
+ configurations features
+
+The system has the configuration 'autofdo' built in. It may be examined as
+follows::
+
+ $ cd configurations/
+ $ ls
+ autofdo
+ $ cd autofdo/
+ $ ls
+ description preset1 preset3 preset5 preset7 preset9
+ feature_refs preset2 preset4 preset6 preset8
+ $ cat description
+ Setup ETMs with strobing for autofdo
+ $ cat feature_refs
+ strobing
+
+Each preset declared has a preset<n> subdirectory declared. The values for
+the preset can be examined::
+
+ $ cat preset1/values
+ strobing.window = 0x1388 strobing.period = 0x2
+ $ cat preset2/values
+ strobing.window = 0x1388 strobing.period = 0x4
+
+The features referenced by the configuration can be examined in the features
+directory::
+
+ $ cd ../../features/strobing/
+ $ ls
+ description matches nr_params params
+ $ cat description
+ Generate periodic trace capture windows.
+ parameter 'window': a number of CPU cycles (W)
+ parameter 'period': trace enabled for W cycles every period x W cycles
+ $ cat matches
+ SRC_ETMV4
+ $ cat nr_params
+ 2
+
+Move to the params directory to examine and adjust parameters::
+
+ cd params
+ $ ls
+ period window
+ $ cd period
+ $ ls
+ value
+ $ cat value
+ 0x2710
+ # echo 15000 > value
+ # cat value
+ 0x3a98
+
+Parameters adjusted in this way are reflected in all device instances that have
+loaded the feature.
+
+
+Using Configurations in perf
+============================
+
+The configurations loaded into the CoreSight configuration management are
+also declared in the perf 'cs_etm' event infrastructure so that they can
+be selected when running trace under perf::
+
+ $ ls /sys/devices/cs_etm
+ configurations format perf_event_mux_interval_ms sinks type
+ events nr_addr_filters power
+
+Key directories here are 'configurations' - which lists the loaded
+configurations, and 'events' - a generic perf directory which allows
+selection on the perf command line.::
+
+ $ ls configurations/
+ autofdo
+ $ cat configurations/autofdo
+ 0xa7c3dddd
+
+As with the sinks entries, this provides a hash of the configuration name.
+The entry in the 'events' directory uses perfs built in syntax generator
+to substitute the syntax for the name when evaluating the command::
+
+ $ ls events/
+ autofdo
+ $ cat events/autofdo
+ configid=0xa7c3dddd
+
+The 'autofdo' configuration may be selected on the perf command line::
+
+ $ perf record -e cs_etm/autofdo/u --per-thread <application>
+
+A preset to override the current parameter values can also be selected::
+
+ $ perf record -e cs_etm/autofdo,preset=1/u --per-thread <application>
+
+When configurations are selected in this way, then the trace sink used is
+automatically selected.
diff --git a/Documentation/trace/coresight/coresight.rst b/Documentation/trace/coresight/coresight.rst
index 1ec8dc35b1d8..a15571d96cc8 100644
--- a/Documentation/trace/coresight/coresight.rst
+++ b/Documentation/trace/coresight/coresight.rst
@@ -620,6 +620,19 @@ channels on the CTM (Cross Trigger Matrix).
A separate documentation file is provided to explain the use of these devices.
(Documentation/trace/coresight/coresight-ect.rst) [#fourth]_.
+CoreSight System Configuration
+------------------------------
+
+CoreSight components can be complex devices with many programming options.
+Furthermore, components can be programmed to interact with each other across the
+complete system.
+
+A CoreSight System Configuration manager is provided to allow these complex programming
+configurations to be selected and used easily from perf and sysfs.
+
+See the separate document for further information.
+(Documentation/trace/coresight/coresight-config.rst) [#fifth]_.
+
.. [#first] Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
@@ -628,3 +641,5 @@ A separate documentation file is provided to explain the use of these devices.
.. [#third] https://github.com/Linaro/perf-opencsd
.. [#fourth] Documentation/trace/coresight/coresight-ect.rst
+
+.. [#fifth] Documentation/trace/coresight/coresight-config.rst
diff --git a/Documentation/trace/histogram.rst b/Documentation/trace/histogram.rst
index f99be8062bc8..533415644c54 100644
--- a/Documentation/trace/histogram.rst
+++ b/Documentation/trace/histogram.rst
@@ -70,15 +70,16 @@ Documentation written by Tom Zanussi
modified by appending any of the following modifiers to the field
name:
- =========== ==========================================
- .hex display a number as a hex value
- .sym display an address as a symbol
- .sym-offset display an address as a symbol and offset
- .syscall display a syscall id as a system call name
- .execname display a common_pid as a program name
- .log2 display log2 value rather than raw number
- .usecs display a common_timestamp in microseconds
- =========== ==========================================
+ ============= =================================================
+ .hex display a number as a hex value
+ .sym display an address as a symbol
+ .sym-offset display an address as a symbol and offset
+ .syscall display a syscall id as a system call name
+ .execname display a common_pid as a program name
+ .log2 display log2 value rather than raw number
+ .buckets=size display grouping of values rather than raw number
+ .usecs display a common_timestamp in microseconds
+ ============= =================================================
Note that in general the semantics of a given field aren't
interpreted when applying a modifier to it, but there are some
@@ -228,7 +229,7 @@ Extended error information
that lists the total number of bytes requested for each function in
the kernel that made one or more calls to kmalloc::
- # echo 'hist:key=call_site:val=bytes_req' > \
+ # echo 'hist:key=call_site:val=bytes_req.buckets=32' > \
/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
This tells the tracing system to create a 'hist' trigger using the
@@ -1823,20 +1824,99 @@ 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.
-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
-
The new event is created under the tracing/events/synthetic/ directory
and looks and behaves just like any other event::
# ls /sys/kernel/debug/tracing/events/synthetic/wakeup_latency
enable filter format hist id trigger
+A histogram can now be defined for the new synthetic event::
+
+ # echo 'hist:keys=pid,prio,lat.log2:sort=lat' >> \
+ /sys/kernel/debug/tracing/events/synthetic/wakeup_latency/trigger
+
+The above shows the latency "lat" in a power of 2 grouping.
+
Like any other event, once a histogram is enabled for the event, the
output can be displayed by reading the event's 'hist' file.
+ # cat /sys/kernel/debug/tracing/events/synthetic/wakeup_latency/hist
+
+ # event histogram
+ #
+ # trigger info: hist:keys=pid,prio,lat.log2:vals=hitcount:sort=lat.log2:size=2048 [active]
+ #
+
+ { pid: 2035, prio: 9, lat: ~ 2^2 } hitcount: 43
+ { pid: 2034, prio: 9, lat: ~ 2^2 } hitcount: 60
+ { pid: 2029, prio: 9, lat: ~ 2^2 } hitcount: 965
+ { pid: 2034, prio: 120, lat: ~ 2^2 } hitcount: 9
+ { pid: 2033, prio: 120, lat: ~ 2^2 } hitcount: 5
+ { pid: 2030, prio: 9, lat: ~ 2^2 } hitcount: 335
+ { pid: 2030, prio: 120, lat: ~ 2^2 } hitcount: 10
+ { pid: 2032, prio: 120, lat: ~ 2^2 } hitcount: 1
+ { pid: 2035, prio: 120, lat: ~ 2^2 } hitcount: 2
+ { pid: 2031, prio: 9, lat: ~ 2^2 } hitcount: 176
+ { pid: 2028, prio: 120, lat: ~ 2^2 } hitcount: 15
+ { pid: 2033, prio: 9, lat: ~ 2^2 } hitcount: 91
+ { pid: 2032, prio: 9, lat: ~ 2^2 } hitcount: 125
+ { pid: 2029, prio: 120, lat: ~ 2^2 } hitcount: 4
+ { pid: 2031, prio: 120, lat: ~ 2^2 } hitcount: 3
+ { pid: 2029, prio: 120, lat: ~ 2^3 } hitcount: 2
+ { pid: 2035, prio: 9, lat: ~ 2^3 } hitcount: 41
+ { pid: 2030, prio: 120, lat: ~ 2^3 } hitcount: 1
+ { pid: 2032, prio: 9, lat: ~ 2^3 } hitcount: 32
+ { pid: 2031, prio: 9, lat: ~ 2^3 } hitcount: 44
+ { pid: 2034, prio: 9, lat: ~ 2^3 } hitcount: 40
+ { pid: 2030, prio: 9, lat: ~ 2^3 } hitcount: 29
+ { pid: 2033, prio: 9, lat: ~ 2^3 } hitcount: 31
+ { pid: 2029, prio: 9, lat: ~ 2^3 } hitcount: 31
+ { pid: 2028, prio: 120, lat: ~ 2^3 } hitcount: 18
+ { pid: 2031, prio: 120, lat: ~ 2^3 } hitcount: 2
+ { pid: 2028, prio: 120, lat: ~ 2^4 } hitcount: 1
+ { pid: 2029, prio: 9, lat: ~ 2^4 } hitcount: 4
+ { pid: 2031, prio: 120, lat: ~ 2^7 } hitcount: 1
+ { pid: 2032, prio: 120, lat: ~ 2^7 } hitcount: 1
+
+ Totals:
+ Hits: 2122
+ Entries: 30
+ Dropped: 0
+
+
+The latency values can also be grouped linearly by a given size with
+the ".buckets" modifier and specify a size (in this case groups of 10).
+
+ # echo 'hist:keys=pid,prio,lat.buckets=10:sort=lat' >> \
+ /sys/kernel/debug/tracing/events/synthetic/wakeup_latency/trigger
+
+ # event histogram
+ #
+ # trigger info: hist:keys=pid,prio,lat.buckets=10:vals=hitcount:sort=lat.buckets=10:size=2048 [active]
+ #
+
+ { pid: 2067, prio: 9, lat: ~ 0-9 } hitcount: 220
+ { pid: 2068, prio: 9, lat: ~ 0-9 } hitcount: 157
+ { pid: 2070, prio: 9, lat: ~ 0-9 } hitcount: 100
+ { pid: 2067, prio: 120, lat: ~ 0-9 } hitcount: 6
+ { pid: 2065, prio: 120, lat: ~ 0-9 } hitcount: 2
+ { pid: 2066, prio: 120, lat: ~ 0-9 } hitcount: 2
+ { pid: 2069, prio: 9, lat: ~ 0-9 } hitcount: 122
+ { pid: 2069, prio: 120, lat: ~ 0-9 } hitcount: 8
+ { pid: 2070, prio: 120, lat: ~ 0-9 } hitcount: 1
+ { pid: 2068, prio: 120, lat: ~ 0-9 } hitcount: 7
+ { pid: 2066, prio: 9, lat: ~ 0-9 } hitcount: 365
+ { pid: 2064, prio: 120, lat: ~ 0-9 } hitcount: 35
+ { pid: 2065, prio: 9, lat: ~ 0-9 } hitcount: 998
+ { pid: 2071, prio: 9, lat: ~ 0-9 } hitcount: 85
+ { pid: 2065, prio: 9, lat: ~ 10-19 } hitcount: 2
+ { pid: 2064, prio: 120, lat: ~ 10-19 } hitcount: 2
+
+ Totals:
+ Hits: 2112
+ Entries: 16
+ Dropped: 0
+
2.2.3 Hist trigger 'handlers' and 'actions'
-------------------------------------------
diff --git a/Documentation/translations/conf.py b/Documentation/translations/conf.py
new file mode 100644
index 000000000000..92cdbba74229
--- /dev/null
+++ b/Documentation/translations/conf.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+# SPDX-License-Identifier: GPL-2.0
+
+# -- Additinal options for LaTeX output ----------------------------------
+# font config for ascii-art alignment
+
+latex_elements['preamble'] += '''
+ \\IfFontExistsTF{Noto Sans CJK SC}{
+ % For CJK ascii-art alignment
+ \\setmonofont{Noto Sans Mono CJK SC}[AutoFakeSlant]
+ }{}
+'''
diff --git a/Documentation/translations/index.rst b/Documentation/translations/index.rst
index 556b050884fc..1175a47d07f0 100644
--- a/Documentation/translations/index.rst
+++ b/Documentation/translations/index.rst
@@ -8,6 +8,7 @@ Translations
:maxdepth: 1
zh_CN/index
+ zh_TW/index
it_IT/index
ko_KR/index
ja_JP/index
diff --git a/Documentation/translations/it_IT/core-api/symbol-namespaces.rst b/Documentation/translations/it_IT/core-api/symbol-namespaces.rst
index aa851a57a4b0..42f5d04e38ec 100644
--- a/Documentation/translations/it_IT/core-api/symbol-namespaces.rst
+++ b/Documentation/translations/it_IT/core-api/symbol-namespaces.rst
@@ -42,15 +42,15 @@ nomi: EXPORT_SYMBOL_NS() ed EXPORT_SYMBOL_NS_GPL(). Queste macro richiedono un
argomento aggiuntivo: lo spazio dei nomi.
Tenete presente che per via dell'espansione delle macro questo argomento deve
essere un simbolo di preprocessore. Per esempio per esportare il
-simbolo `usb_stor_suspend` nello spazio dei nomi `USB_STORAGE` usate::
+simbolo ``usb_stor_suspend`` nello spazio dei nomi ``USB_STORAGE`` usate::
EXPORT_SYMBOL_NS(usb_stor_suspend, USB_STORAGE);
Di conseguenza, nella tabella dei simboli del kernel ci sarà una voce
-rappresentata dalla struttura `kernel_symbol` che avrà il campo
-`namespace` (spazio dei nomi) impostato. Un simbolo esportato senza uno spazio
-dei nomi avrà questo campo impostato a `NULL`. Non esiste uno spazio dei nomi
-di base. Il programma `modpost` e il codice in kernel/module.c usano lo spazio
+rappresentata dalla struttura ``kernel_symbol`` che avrà il campo
+``namespace`` (spazio dei nomi) impostato. Un simbolo esportato senza uno spazio
+dei nomi avrà questo campo impostato a ``NULL``. Non esiste uno spazio dei nomi
+di base. Il programma ``modpost`` e il codice in kernel/module.c usano lo spazio
dei nomi, rispettivamente, durante la compilazione e durante il caricamento
di un modulo.
@@ -65,7 +65,7 @@ ed EXPORT_SYMBOL_GPL() che non specificano esplicitamente uno spazio dei nomi.
Ci sono molti modi per specificare questo simbolo di preprocessore e il loro
uso dipende dalle preferenze del manutentore di un sottosistema. La prima
-possibilità è quella di definire il simbolo nel `Makefile` del sottosistema.
+possibilità è quella di definire il simbolo nel ``Makefile`` del sottosistema.
Per esempio per esportare tutti i simboli definiti in usb-common nello spazio
dei nomi USB_COMMON, si può aggiungere la seguente linea in
drivers/usb/common/Makefile::
@@ -97,7 +97,7 @@ USB_STORAGE usando la seguente dichiarazione::
MODULE_IMPORT_NS(USB_STORAGE);
-Questo creerà un'etichetta `modinfo` per ogni spazio dei nomi
+Questo creerà un'etichetta ``modinfo`` per ogni spazio dei nomi
importato. Un risvolto di questo fatto è che gli spazi dei
nomi importati da un modulo possono essere ispezionati tramite
modinfo::
@@ -116,7 +116,7 @@ mancanti.
4. Caricare moduli che usano simboli provenienti da spazi dei nomi
==================================================================
-Quando un modulo viene caricato (per esempio usando `insmod`), il kernel
+Quando un modulo viene caricato (per esempio usando ``insmod``), il kernel
verificherà la disponibilità di ogni simbolo usato e se lo spazio dei nomi
che potrebbe contenerli è stato importato. Il comportamento di base del kernel
è di rifiutarsi di caricare quei moduli che non importano tutti gli spazi dei
@@ -144,22 +144,22 @@ Lo scenario tipico di chi scrive un modulo potrebbe essere::
- scrivere codice che dipende da un simbolo appartenente ad uno spazio
dei nomi non importato
- - eseguire `make`
+ - eseguire ``make``
- aver notato un avviso da modpost che parla di un'importazione
mancante
- - eseguire `make nsdeps` per aggiungere import nel posto giusto
+ - eseguire ``make nsdeps`` per aggiungere import nel posto giusto
Per i manutentori di sottosistemi che vogliono aggiungere uno spazio dei nomi,
-l'approccio è simile. Di nuovo, eseguendo `make nsdeps` aggiungerà le
+l'approccio è simile. Di nuovo, eseguendo ``make nsdeps`` aggiungerà le
importazioni mancanti nei moduli inclusi nel kernel::
- spostare o aggiungere simboli ad uno spazio dei nomi (per esempio
usando EXPORT_SYMBOL_NS())
- - eseguire `make` (preferibilmente con allmodconfig per coprire tutti
+ - eseguire ``make`` (preferibilmente con allmodconfig per coprire tutti
i moduli del kernel)
- aver notato un avviso da modpost che parla di un'importazione
mancante
- - eseguire `make nsdeps` per aggiungere import nel posto giusto
+ - eseguire ``make nsdeps`` per aggiungere import nel posto giusto
Potete anche eseguire nsdeps per moduli esterni. Solitamente si usa così::
diff --git a/Documentation/translations/it_IT/kernel-hacking/hacking.rst b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
index f6beb385b4ac..b4ea00f1b583 100644
--- a/Documentation/translations/it_IT/kernel-hacking/hacking.rst
+++ b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
@@ -634,7 +634,7 @@ Definita in ``include/linux/export.h``
Questa è una variate di `EXPORT_SYMBOL()` che permette di specificare uno
spazio dei nomi. Lo spazio dei nomi è documentato in
-:doc:`../core-api/symbol-namespaces`
+Documentation/translations/it_IT/core-api/symbol-namespaces.rst.
:c:func:`EXPORT_SYMBOL_NS_GPL()`
--------------------------------
@@ -643,7 +643,7 @@ Definita in ``include/linux/export.h``
Questa è una variate di `EXPORT_SYMBOL_GPL()` che permette di specificare uno
spazio dei nomi. Lo spazio dei nomi è documentato in
-:doc:`../core-api/symbol-namespaces`
+Documentation/translations/it_IT/core-api/symbol-namespaces.rst.
Procedure e convenzioni
=======================
diff --git a/Documentation/translations/it_IT/process/deprecated.rst b/Documentation/translations/it_IT/process/deprecated.rst
index 07c79d4bafca..987f45ee1804 100644
--- a/Documentation/translations/it_IT/process/deprecated.rst
+++ b/Documentation/translations/it_IT/process/deprecated.rst
@@ -183,9 +183,11 @@ di Linus:
affrontare il giudizio di Linus, allora forse potrai usare "%px",
assicurandosi anche di averne il permesso.
-Infine, sappi che un cambio in favore di "%p" con hash `non verrà
-accettato
-<https://lore.kernel.org/lkml/CA+55aFwieC1-nAs+NFq9RTwaR8ef9hWa4MjNBWL41F-8wM49eA@mail.gmail.com/>`_.
+Potete disabilitare temporaneamente l'hashing di "%p" nel caso in cui questa
+funzionalità vi sia d'ostacolo durante una sessione di debug. Per farlo
+aggiungete l'opzione di debug "`no_hash_pointers
+<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_" alla
+riga di comando del kernel.
Vettori a dimensione variabile (VLA)
------------------------------------
diff --git a/Documentation/translations/it_IT/process/stable-kernel-rules.rst b/Documentation/translations/it_IT/process/stable-kernel-rules.rst
index 283d62541c4f..83f48afe48b9 100644
--- a/Documentation/translations/it_IT/process/stable-kernel-rules.rst
+++ b/Documentation/translations/it_IT/process/stable-kernel-rules.rst
@@ -41,12 +41,6 @@ Regole sul tipo di patch che vengono o non vengono accettate nei sorgenti
Procedura per sottomettere patch per i sorgenti -stable
-------------------------------------------------------
- - Se la patch contiene modifiche a dei file nelle cartelle net/ o drivers/net,
- allora seguite le linee guida descritte in
- :ref:`Documentation/translations/it_IT/networking/netdev-FAQ.rst <it_netdev-FAQ>`;
- ma solo dopo aver verificato al seguente indirizzo che la patch non sia
- già in coda:
- https://patchwork.kernel.org/bundle/netdev/stable/?state=*
- Una patch di sicurezza non dovrebbero essere gestite (solamente) dal processo
di revisione -stable, ma dovrebbe seguire le procedure descritte in
:ref:`Documentation/translations/it_IT/admin-guide/security-bugs.rst <it_securitybugs>`.
diff --git a/Documentation/translations/it_IT/process/submitting-patches.rst b/Documentation/translations/it_IT/process/submitting-patches.rst
index ded95048b9a8..458d9d24b9c0 100644
--- a/Documentation/translations/it_IT/process/submitting-patches.rst
+++ b/Documentation/translations/it_IT/process/submitting-patches.rst
@@ -14,14 +14,15 @@ una certa familiarità col "sistema". Questo testo è una raccolta di
suggerimenti che aumenteranno significativamente le probabilità di vedere le
vostre patch accettate.
-Questo documento contiene un vasto numero di suggerimenti concisi. Per
-maggiori dettagli su come funziona il processo di sviluppo del kernel leggete
-:doc:`development-process`.
-Leggete anche :doc:`submit-checklist` per una lista di punti da
-verificare prima di inviare del codice. Se state inviando un driver,
-allora leggete anche :doc:`submitting-drivers`; per delle patch
+Questo documento contiene un vasto numero di suggerimenti concisi. Per maggiori
+dettagli su come funziona il processo di sviluppo del kernel leggete
+Documentation/translations/it_IT/process/development-process.rst. Leggete anche
+Documentation/translations/it_IT/process/submit-checklist.rst per una lista di
+punti da verificare prima di inviare del codice. Se state inviando un driver,
+allora leggete anche
+Documentation/translations/it_IT/process/submitting-drivers.rst; per delle patch
relative alle associazioni per Device Tree leggete
-:doc:`submitting-patches`.
+Documentation/translations/it_IT/process/submitting-patches.rst.
Questa documentazione assume che sappiate usare ``git`` per preparare le patch.
Se non siete pratici di ``git``, allora è bene che lo impariate;
@@ -193,7 +194,7 @@ ed integrate.
---------------------------------------------
Controllate che la vostra patch non violi lo stile del codice, maggiori
-dettagli sono disponibili in :ref:`Documentation/translations/it_IT/process/coding-style.rst <it_codingstyle>`.
+dettagli sono disponibili in Documentation/translations/it_IT/process/coding-style.rst.
Non farlo porta semplicemente a una perdita di tempo da parte dei revisori e
voi vedrete la vostra patch rifiutata, probabilmente senza nemmeno essere stata
letta.
@@ -230,13 +231,13 @@ scripts/get_maintainer.pl può esservi d'aiuto. Se non riuscite a trovare un
manutentore per il sottosistema su cui state lavorando, allora Andrew Morton
(akpm@linux-foundation.org) sarà la vostra ultima possibilità.
-Normalmente, dovreste anche scegliere una lista di discussione a cui inviare
-la vostra serie di patch. La lista di discussione linux-kernel@vger.kernel.org
-è proprio l'ultima spiaggia, il volume di email su questa lista fa si che
-diversi sviluppatori non la seguano. Guardate nel file MAINTAINERS per trovare
-la lista di discussione dedicata ad un sottosistema; probabilmente lì la vostra
-patch riceverà molta più attenzione. Tuttavia, per favore, non spammate le
-liste di discussione che non sono interessate al vostro lavoro.
+Normalmente, dovreste anche scegliere una lista di discussione a cui inviare la
+vostra serie di patch. La lista di discussione linux-kernel@vger.kernel.org
+dovrebbe essere usata per inviare tutte le patch, ma il traffico è tale per cui
+diversi sviluppatori la trascurano. Guardate nel file MAINTAINERS per trovare la
+lista di discussione dedicata ad un sottosistema; probabilmente lì la vostra
+patch riceverà molta più attenzione. Tuttavia, per favore, non spammate le liste
+di discussione che non sono interessate al vostro lavoro.
Molte delle liste di discussione relative al kernel vengono ospitate su
vger.kernel.org; potete trovare un loro elenco alla pagina
@@ -257,7 +258,7 @@ embargo potrebbe essere preso in considerazione per dare il tempo alle
distribuzioni di prendere la patch e renderla disponibile ai loro utenti;
in questo caso, ovviamente, la patch non dovrebbe essere inviata su alcuna
lista di discussione pubblica. Leggete anche
-:doc:`/admin-guide/security-bugs`.
+Documentation/admin-guide/security-bugs.rst.
Patch che correggono bachi importanti su un kernel già rilasciato, dovrebbero
essere inviate ai manutentori dei kernel stabili aggiungendo la seguente riga::
@@ -266,12 +267,7 @@ essere inviate ai manutentori dei kernel stabili aggiungendo la seguente riga::
nella vostra patch, nell'area dedicata alle firme (notate, NON come destinatario
delle e-mail). In aggiunta a questo file, dovreste leggere anche
-:ref:`Documentation/translations/it_IT/process/stable-kernel-rules.rst <it_stable_kernel_rules>`
-
-Tuttavia, notate, che alcuni manutentori di sottosistema preferiscono avere
-l'ultima parola su quali patch dovrebbero essere aggiunte ai kernel stabili.
-La rete di manutentori, in particolare, non vorrebbe vedere i singoli
-sviluppatori aggiungere alle loro patch delle righe come quella sopracitata.
+Documentation/translations/it_IT/process/stable-kernel-rules.rst.
Se le modifiche hanno effetti sull'interfaccia con lo spazio utente, per favore
inviate una patch per le pagine man ai manutentori di suddette pagine (elencati
@@ -330,7 +326,7 @@ così la possibilità che il vostro allegato-MIME venga accettato.
Eccezione: se il vostro servizio di posta storpia le patch, allora qualcuno
potrebbe chiedervi di rinviarle come allegato MIME.
-Leggete :doc:`/translations/it_IT/process/email-clients`
+Leggete Documentation/translations/it_IT/process/email-clients.rst
per dei suggerimenti sulla configurazione del programmi di posta elettronica
per l'invio di patch intatte.
@@ -351,7 +347,7 @@ richiede molto tempo, e a volte i revisori diventano burberi. Tuttavia, anche
in questo caso, rispondete con educazione e concentratevi sul problema che
hanno evidenziato.
-Leggete :doc:`/translations/it_IT/process/email-clients` per
+Leggete Documentation/translations/it_IT/process/email-clients.rst per
le raccomandazioni sui programmi di posta elettronica e l'etichetta da usare
sulle liste di discussione.
@@ -369,6 +365,16 @@ aver inviato le patch correttamente. Aspettate almeno una settimana prima di
rinviare le modifiche o sollecitare i revisori - probabilmente anche di più
durante la finestra d'integrazione.
+Potete anche rinviare la patch, o la serie di patch, dopo un paio di settimane
+aggiungendo la parola "RESEND" nel titolo::
+
+ [PATCH Vx RESEND] sub/sys: Condensed patch summary
+
+Ma non aggiungete "RESEND" quando state sottomettendo una versione modificata
+della vostra patch, o serie di patch - "RESEND" si applica solo alla
+sottomissione di patch, o serie di patch, che non hanno subito modifiche
+dall'ultima volta che sono state inviate.
+
Aggiungete PATCH nell'oggetto
-----------------------------
@@ -795,8 +801,7 @@ Greg Kroah-Hartman, "Come scocciare un manutentore di un sottosistema"
No!!!! Basta gigantesche bombe patch alle persone sulla lista linux-kernel@vger.kernel.org!
<https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
-Kernel Documentation/translations/it_IT/process/coding-style.rst:
- :ref:`Documentation/translations/it_IT/process/coding-style.rst <it_codingstyle>`
+Kernel Documentation/translations/it_IT/process/coding-style.rst.
E-mail di Linus Torvalds sul formato canonico di una patch:
<https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
diff --git a/Documentation/translations/ja_JP/howto.rst b/Documentation/translations/ja_JP/howto.rst
index 73ebdab4ced7..d667f9d8a02a 100644
--- a/Documentation/translations/ja_JP/howto.rst
+++ b/Documentation/translations/ja_JP/howto.rst
@@ -1,3 +1,7 @@
+.. raw:: latex
+
+ \kerneldocCJKoff
+
NOTE:
This is a version of Documentation/process/howto.rst translated into Japanese.
This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
@@ -11,6 +15,10 @@ try to update the original English file first.
----------------------------------
+.. raw:: latex
+
+ \kerneldocCJKon
+
この文書は、
Documentation/process/howto.rst
の和訳です。
diff --git a/Documentation/translations/ja_JP/index.rst b/Documentation/translations/ja_JP/index.rst
index f94ba62d41c3..88d4d98eed15 100644
--- a/Documentation/translations/ja_JP/index.rst
+++ b/Documentation/translations/ja_JP/index.rst
@@ -3,6 +3,7 @@
\renewcommand\thesection*
\renewcommand\thesubsection*
\kerneldocCJKon
+ \kerneldocBeginJP
Japanese translations
=====================
@@ -11,3 +12,7 @@ Japanese translations
:maxdepth: 1
howto
+
+.. raw:: latex
+
+ \kerneldocEndJP
diff --git a/Documentation/translations/ko_KR/howto.rst b/Documentation/translations/ko_KR/howto.rst
index a2bdd564c907..e3cdf0c84892 100644
--- a/Documentation/translations/ko_KR/howto.rst
+++ b/Documentation/translations/ko_KR/howto.rst
@@ -1,3 +1,7 @@
+.. raw:: latex
+
+ \kerneldocCJKoff
+
NOTE:
This is a version of Documentation/process/howto.rst translated into korean
This document is maintained by Minchan Kim <minchan@kernel.org>
@@ -11,6 +15,10 @@ try to update the original English file first.
----------------------------------
+.. raw:: latex
+
+ \kerneldocCJKon
+
이 문서는
Documentation/process/howto.rst
의 한글 번역입니다.
diff --git a/Documentation/translations/ko_KR/index.rst b/Documentation/translations/ko_KR/index.rst
index 6ae258118bdf..f636b482fb4c 100644
--- a/Documentation/translations/ko_KR/index.rst
+++ b/Documentation/translations/ko_KR/index.rst
@@ -3,6 +3,7 @@
\renewcommand\thesection*
\renewcommand\thesubsection*
\kerneldocCJKon
+ \kerneldocBeginKR
한국어 번역
===========
@@ -26,3 +27,4 @@
.. raw:: latex
\normalsize
+ \kerneldocEndKR
diff --git a/Documentation/translations/zh_CN/accounting/index.rst b/Documentation/translations/zh_CN/accounting/index.rst
new file mode 100644
index 000000000000..362e907b41f9
--- /dev/null
+++ b/Documentation/translations/zh_CN/accounting/index.rst
@@ -0,0 +1,25 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/accounting/index.rst
+:Translator: Yang Yang <yang.yang29@zte.com.cn>
+
+.. _cn_accounting_index.rst:
+
+
+====
+计数
+====
+
+.. toctree::
+ :maxdepth: 1
+
+ psi
+
+Todolist:
+
+ cgroupstats
+ delay-accounting
+ taskstats
+ taskstats-struct
diff --git a/Documentation/translations/zh_CN/accounting/psi.rst b/Documentation/translations/zh_CN/accounting/psi.rst
new file mode 100644
index 000000000000..a0ddb7bd257c
--- /dev/null
+++ b/Documentation/translations/zh_CN/accounting/psi.rst
@@ -0,0 +1,155 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/accounting/psi.rst
+:Translator: Yang Yang <yang.yang29@zte.com.cn>
+
+.. _cn_psi.rst:
+
+
+=================
+PSI——压力阻塞信息
+=================
+
+:日期: April, 2018
+:作者: Johannes Weiner <hannes@cmpxchg.org>
+
+当CPU、memory或IO设备处于竞争状态,业务负载会遭受时延毛刺、吞吐量降低,
+及面临OOM的风险。
+
+如果没有一种准确的方法度量系统竞争程度,则有两种后果:一种是用户过于节制,
+未充分利用系统资源;另一种是过度使用,经常性面临业务中断的风险。
+
+psi特性能够识别和量化资源竞争导致的业务中断,及其对复杂负载乃至整个系统在
+时间上的影响。
+
+准确度量因资源不足造成的生产力损失,有助于用户基于硬件调整业务负载,或基
+于业务负载配置硬件。
+
+psi能够实时的提供相关信息,因此系统可基于psi实现动态的负载管理。如实施
+卸载、迁移、策略性的停止或杀死低优先级或可重启的批处理任务。
+
+psi帮助用户实现硬件资源利用率的最大化。同时无需牺牲业务负载健康度,也无需
+面临OOM等造成业务中断的风险。
+
+压力接口
+========
+
+压力信息可通过/proc/pressure/ --cpu、memory、io文件分别获取。
+
+CPU相关信息格式如下:
+
+ some avg10=0.00 avg60=0.00 avg300=0.00 total=0
+
+内存和IO相关信息如下:
+
+ some avg10=0.00 avg60=0.00 avg300=0.00 total=0
+ full avg10=0.00 avg60=0.00 avg300=0.00 total=0
+
+some行代表至少有一个任务阻塞于特定资源的时间占比。
+
+full行代表所有非idle任务同时阻塞于特定资源的时间占比。在这种状态下CPU资源
+完全被浪费,相对于正常运行,业务负载由于耗费更多时间等待而受到严重影响。
+
+由于此情况严重影响系统性能,因此清楚的识别本情况并与some行所代表的情况区分开,
+将有助于分析及提升系统性能。这就是full独立于some行的原因。
+
+avg代表阻塞时间占比(百分比),为最近10秒、60秒、300秒内的均值。这样我们
+既可观察到短期事件的影响,也可看到中等及长时间内的趋势。total代表总阻塞
+时间(单位微秒),可用于观察时延毛刺,这种毛刺可能在均值中无法体现。
+
+监控压力门限
+============
+
+用户可注册触发器,通过poll()监控资源压力是否超过门限。
+
+触发器定义:指定时间窗口期内累积阻塞时间的最大值。比如可定义500ms内积累
+100ms阻塞,即触发一次唤醒事件。
+
+触发器注册方法:用户打开代表特定资源的psi接口文件,写入门限、时间窗口的值。
+所打开的文件描述符用于等待事件,可使用select()、poll()、epoll()。
+写入信息的格式如下:
+
+ <some|full> <stall amount in us> <time window in us>
+
+示例:向/proc/pressure/memory写入"some 150000 1000000"将新增触发器,将在
+1秒内至少一个任务阻塞于内存的总时间超过150ms时触发。向/proc/pressure/io写入
+"full 50000 1000000"将新增触发器,将在1秒内所有任务都阻塞于io的总时间超过50ms时触发。
+
+触发器可针对多个psi度量值设置,同一个psi度量值可设置多个触发器。每个触发器需要
+单独的文件描述符用于轮询,以区分于其他触发器。所以即使对于同一个psi接口文件,
+每个触发器也需要单独的调用open()。
+
+监控器在被监控资源进入阻塞状态时启动,在系统退出阻塞状态后停用。系统进入阻塞
+状态后,监控psi增长的频率为每监控窗口刷新10次。
+
+内核接受的窗口为500ms~10s,所以监控间隔为50ms~1s。设置窗口下限目的是为了
+防止过于频繁的轮询。设置窗口上限的目的是因为窗口过长则无意义,此时查看
+psi接口提供的均值即可。
+
+监控器在激活后,至少在跟踪窗口期间将保持活动状态。以避免随着系统进入和退出
+阻塞状态,监控器过于频繁的进入和退出活动状态。
+
+用户态通知在监控窗口内会受到速率限制。当对应的文件描述符关闭,触发器会自动注销。
+
+用户态监控器使用示例
+====================
+
+::
+
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <stdio.h>
+ #include <poll.h>
+ #include <string.h>
+ #include <unistd.h>
+
+ /* 监控内存部分阻塞,监控时间窗口为1秒、阻塞门限为150毫秒。*/
+ int main() {
+ const char trig[] = "some 150000 1000000";
+ struct pollfd fds;
+ int n;
+
+ fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
+ if (fds.fd < 0) {
+ printf("/proc/pressure/memory open error: %s\n",
+ strerror(errno));
+ return 1;
+ }
+ fds.events = POLLPRI;
+
+ if (write(fds.fd, trig, strlen(trig) + 1) < 0) {
+ printf("/proc/pressure/memory write error: %s\n",
+ strerror(errno));
+ return 1;
+ }
+
+ printf("waiting for events...\n");
+ while (1) {
+ n = poll(&fds, 1, -1);
+ if (n < 0) {
+ printf("poll error: %s\n", strerror(errno));
+ return 1;
+ }
+ if (fds.revents & POLLERR) {
+ printf("got POLLERR, event source is gone\n");
+ return 0;
+ }
+ if (fds.revents & POLLPRI) {
+ printf("event triggered!\n");
+ } else {
+ printf("unknown event received: 0x%x\n", fds.revents);
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+Cgroup2接口
+===========
+
+对于CONFIG_CGROUP=y及挂载了cgroup2文件系统的系统,能够获取cgroups内任务的psi。
+此场景下cgroupfs挂载点的子目录包含cpu.pressure、memory.pressure、io.pressure文件,
+内容格式与/proc/pressure/下的文件相同。
+
+可设置基于cgroup的psi监控器,方法与系统级psi监控器相同。
diff --git a/Documentation/translations/zh_CN/core-api/cachetlb.rst b/Documentation/translations/zh_CN/core-api/cachetlb.rst
index 8376485a534d..55827b8a7c53 100644
--- a/Documentation/translations/zh_CN/core-api/cachetlb.rst
+++ b/Documentation/translations/zh_CN/core-api/cachetlb.rst
@@ -298,15 +298,6 @@ HyperSparc cpu就是这样一个具有这种属性的cpu。
用。默认的实现是nop(对于所有相干的架构应该保持这样)。对于不一致性
的架构,它应该刷新vmaddr处的页面缓存。
- ``void flush_kernel_dcache_page(struct page *page)``
-
- 当内核需要修改一个用kmap获得的用户页时,它会在所有修改完成后(但在
- kunmapping之前)调用这个函数,以使底层页面达到最新状态。这里假定用
- 户没有不一致性的缓存副本(即原始页面是从类似get_user_pages()的机制
- 中获得的)。默认的实现是一个nop,在所有相干的架构上都应该如此。在不
- 一致性的架构上,这应该刷新内核缓存中的页面(使用page_address(page))。
-
-
``void flush_icache_range(unsigned long start, unsigned long end)``
当内核存储到它将执行的地址中时(例如在加载模块时),这个函数被调用。
diff --git a/Documentation/translations/zh_CN/core-api/cpu_hotplug.rst b/Documentation/translations/zh_CN/core-api/cpu_hotplug.rst
new file mode 100644
index 000000000000..85a264287426
--- /dev/null
+++ b/Documentation/translations/zh_CN/core-api/cpu_hotplug.rst
@@ -0,0 +1,348 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/cpu_hotplug.rst
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 吴想成 Wu XiangCheng <bobwxc@email.cn>
+
+.. _cn_core_api_cpu_hotplug:
+
+=================
+内核中的CPU热拔插
+=================
+
+:时间: 2016年12月
+:作者: Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
+ Rusty Russell <rusty@rustcorp.com.au>,
+ Srivatsa Vaddagiri <vatsa@in.ibm.com>,
+ Ashok Raj <ashok.raj@intel.com>,
+ Joel Schopp <jschopp@austin.ibm.com>
+
+简介
+====
+
+现代系统架构的演进已经在处理器中引入了先进的错误报告和纠正能力。有一些OEM也支
+持可热拔插的NUMA(Non Uniform Memory Access,非统一内存访问)硬件,其中物理
+节点的插入和移除需要支持CPU热插拔。
+
+这样的进步要求内核可用的CPU被移除,要么是出于配置的原因,要么是出于RAS的目的,
+以保持一个不需要的CPU不在系统执行路径。因此需要在Linux内核中支持CPU热拔插。
+
+CPU热拔插支持的一个更新颖的用途是它在SMP的暂停恢复支持中的应用。双核和超线程支
+持使得即使是笔记本电脑也能运行不支持这些方法的SMP内核。
+
+
+命令行开关
+==========
+
+``maxcpus=n``
+ 限制启动时的CPU为 *n* 个。例如,如果你有四个CPU,使用 ``maxcpus=2`` 将只能启
+ 动两个。你可以选择稍后让其他CPU上线。
+
+``nr_cpus=n``
+ 限制内核将支持的CPU总量。如果这里提供的数量低于实际可用的CPU数量,那么其他CPU
+ 以后就不能上线了。
+
+``additional_cpus=n``
+ 使用它来限制可热插拔的CPU。该选项设置
+ ``cpu_possible_mask = cpu_present_mask + additional_cpus``
+
+ 这个选项只限于IA64架构。
+
+``possible_cpus=n``
+ 这个选项设置 ``cpu_possible_mask`` 中的 ``possible_cpus`` 位。
+
+ 这个选项只限于X86和S390架构。
+
+``cpu0_hotplug``
+ 允许关闭CPU0。
+
+ 这个选项只限于X86架构。
+
+CPU位图
+=======
+
+``cpu_possible_mask``
+ 系统中可能可用CPU的位图。这是用来为per_cpu变量分配一些启动时的内存,这些变量
+ 不会随着CPU的可用或移除而增加/减少。一旦在启动时的发现阶段被设置,该映射就是静态
+ 的,也就是说,任何时候都不会增加或删除任何位。根据你的系统需求提前准确地调整它
+ 可以节省一些启动时的内存。
+
+``cpu_online_mask``
+ 当前在线的所有CPU的位图。在一个CPU可用于内核调度并准备接收设备的中断后,它被
+ 设置在 ``__cpu_up()`` 中。当使用 ``__cpu_disable()`` 关闭一个CPU时,它被清
+ 空,在此之前,所有的操作系统服务包括中断都被迁移到另一个目标CPU。
+
+``cpu_present_mask``
+ 系统中当前存在的CPU的位图。它们并非全部在线。当物理热拔插被相关的子系统
+ (如ACPI)处理时,可以改变和添加新的位或从位图中删除,这取决于事件是
+ hot-add/hot-remove。目前还没有定死规定。典型的用法是在启动时启动拓扑结构,这时
+ 热插拔被禁用。
+
+你真的不需要操作任何系统的CPU映射。在大多数情况下,它们应该是只读的。当设置每个
+CPU资源时,几乎总是使用 ``cpu_possible_mask`` 或 ``for_each_possible_cpu()``
+来进行迭代。宏 ``for_each_cpu()`` 可以用来迭代一个自定义的CPU掩码。
+
+不要使用 ``cpumask_t`` 以外的任何东西来表示CPU的位图。
+
+
+使用CPU热拔插
+=============
+
+内核选项 *CONFIG_HOTPLUG_CPU* 需要被启用。它目前可用于多种架构,包括ARM、MIPS、
+PowerPC和X86。配置是通过sysfs接口完成的::
+
+ $ ls -lh /sys/devices/system/cpu
+ total 0
+ drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu0
+ drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu1
+ drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu2
+ drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu3
+ drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu4
+ drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu5
+ drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu6
+ drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu7
+ drwxr-xr-x 2 root root 0 Dec 21 16:33 hotplug
+ -r--r--r-- 1 root root 4.0K Dec 21 16:33 offline
+ -r--r--r-- 1 root root 4.0K Dec 21 16:33 online
+ -r--r--r-- 1 root root 4.0K Dec 21 16:33 possible
+ -r--r--r-- 1 root root 4.0K Dec 21 16:33 present
+
+文件 *offline* 、 *online* 、*possible* 、*present* 代表CPU掩码。每个CPU文件
+夹包含一个 *online* 文件,控制逻辑上的开(1)和关(0)状态。要在逻辑上关闭CPU4::
+
+ $ echo 0 > /sys/devices/system/cpu/cpu4/online
+ smpboot: CPU 4 is now offline
+
+一旦CPU被关闭,它将从 */proc/interrupts* 、*/proc/cpuinfo* 中被删除,也不应该
+被 *top* 命令显示出来。要让CPU4重新上线::
+
+ $ echo 1 > /sys/devices/system/cpu/cpu4/online
+ smpboot: Booting Node 0 Processor 4 APIC 0x1
+
+CPU又可以使用了。这应该对所有的CPU都有效。CPU0通常比较特殊,被排除在CPU热拔插之外。
+在X86上,内核选项 *CONFIG_BOOTPARAM_HOTPLUG_CPU0* 必须被启用,以便能够关闭CPU0。
+或者,可以使用内核命令选项 *cpu0_hotplug* 。CPU0的一些已知的依赖性:
+
+* 从休眠/暂停中恢复。如果CPU0处于离线状态,休眠/暂停将失败。
+* PIC中断。如果检测到PIC中断,CPU0就不能被移除。
+
+如果你发现CPU0上有任何依赖性,请告知Fenghua Yu <fenghua.yu@intel.com>。
+
+CPU的热拔插协作
+===============
+
+下线情况
+--------
+
+一旦CPU被逻辑关闭,注册的热插拔状态的清除回调将被调用,从 ``CPUHP_ONLINE`` 开始,在
+``CPUHP_OFFLINE`` 状态结束。这包括:
+
+* 如果任务因暂停操作而被冻结,那么 *cpuhp_tasks_frozen* 将被设置为true。
+
+* 所有进程都会从这个将要离线的CPU迁移到新的CPU上。新的CPU是从每个进程的当前cpuset中
+ 选择的,它可能是所有在线CPU的一个子集。
+
+* 所有针对这个CPU的中断都被迁移到新的CPU上。
+
+* 计时器也会被迁移到新的CPU上。
+
+* 一旦所有的服务被迁移,内核会调用一个特定的例程 ``__cpu_disable()`` 来进行特定的清
+ 理。
+
+使用热插拔API
+-------------
+
+一旦一个CPU下线或上线,就有可能收到通知。这对某些需要根据可用CPU数量执行某种设置或清
+理功能的驱动程序来说可能很重要::
+
+ #include <linux/cpuhotplug.h>
+
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "X/Y:online",
+ Y_online, Y_prepare_down);
+
+*X* 是子系统, *Y* 是特定的驱动程序。 *Y_online* 回调将在所有在线CPU的注册过程中被调用。
+如果在线回调期间发生错误, *Y_prepare_down* 回调将在所有之前调用过在线回调的CPU上调
+用。注册完成后,一旦有CPU上线, *Y_online* 回调将被调用,当CPU关闭时, *Y_prepare_down*
+将被调用。所有之前在 *Y_online* 中分配的资源都应该在 *Y_prepare_down* 中释放。如果在
+注册过程中发生错误,返回值 *ret* 为负值。否则会返回一个正值,其中包含动态分配状态
+( *CPUHP_AP_ONLINE_DYN* )的分配热拔插。对于预定义的状态,它将返回0。
+
+该回调可以通过调用 ``cpuhp_remove_state()`` 来删除。如果是动态分配的状态
+( *CPUHP_AP_ONLINE_DYN* ),则使用返回的状态。在移除热插拔状态的过程中,将调用拆解回调。
+
+多个实例
+~~~~~~~~
+
+如果一个驱动程序有多个实例,并且每个实例都需要独立执行回调,那么很可能应该使用
+``multi-state`` 。首先需要注册一个多状态的状态::
+
+ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "X/Y:online,
+ Y_online, Y_prepare_down);
+ Y_hp_online = ret;
+
+``cpuhp_setup_state_multi()`` 的行为与 ``cpuhp_setup_state()`` 类似,只是它
+为多状态准备了回调,但不调用回调。这是一个一次性的设置。
+一旦分配了一个新的实例,你需要注册这个新实例::
+
+ ret = cpuhp_state_add_instance(Y_hp_online, &d->node);
+
+这个函数将把这个实例添加到你先前分配的 ``Y_hp_online`` 状态,并在所有在线的
+CPU上调用先前注册的回调( ``Y_online`` )。 *node* 元素是你的每个实例数据结构
+中的一个 ``struct hlist_node`` 成员。
+
+在移除该实例时::
+
+ cpuhp_state_remove_instance(Y_hp_online, &d->node)
+
+应该被调用,这将在所有在线CPU上调用拆分回调。
+
+手动设置
+~~~~~~~~
+
+通常情况下,在注册或移除状态时调用setup和teamdown回调是很方便的,因为通常在CPU上线
+(下线)和驱动的初始设置(关闭)时需要执行该操作。然而,每个注册和删除功能也有一个
+_nocalls的后缀,如果不希望调用回调,则不调用所提供的回调。在手动设置(或关闭)期间,
+应该使用 ``get_online_cpus()`` 和 ``put_online_cpus()`` 函数来抑制CPU热插拔操作。
+
+
+事件的顺序
+----------
+
+热插拔状态被定义在 ``include/linux/cpuhotplug.h``:
+
+* ``CPUHP_OFFLINE`` ... ``CPUHP_AP_OFFLINE`` 状态是在CPU启动前调用的。
+
+* ``CPUHP_AP_OFFLINE`` ... ``CPUHP_AP_ONLINE`` 状态是在CPU被启动后被调用的。
+ 中断是关闭的,调度程序还没有在这个CPU上活动。从 ``CPUHP_AP_OFFLINE`` 开始,
+ 回调被调用到目标CPU上。
+
+* ``CPUHP_AP_ONLINE_DYN`` 和 ``CPUHP_AP_ONLINE_DYN_END`` 之间的状态被保留
+ 给动态分配。
+
+* 这些状态在CPU关闭时以相反的顺序调用,从 ``CPUHP_ONLINE`` 开始,在 ``CPUHP_OFFLINE``
+ 停止。这里的回调是在将被关闭的CPU上调用的,直到 ``CPUHP_AP_OFFLINE`` 。
+
+通过 ``CPUHP_AP_ONLINE_DYN`` 动态分配的状态通常已经足够了。然而,如果在启动或关闭
+期间需要更早的调用,那么应该获得一个显式状态。如果热拔插事件需要相对于另一个热拔插事
+件的特定排序,也可能需要一个显式状态。
+
+测试热拔插状态
+==============
+
+验证自定义状态是否按预期工作的一个方法是关闭一个CPU,然后再把它上线。也可以把CPU放到某
+些状态(例如 ``CPUHP_AP_ONLINE`` ),然后再回到 ``CPUHP_ONLINE`` 。这将模拟在
+``CPUHP_AP_ONLINE`` 之后的一个状态出现错误,从而导致回滚到在线状态。
+
+所有注册的状态都被列举在 ``/sys/devices/system/cpu/hotplug/states`` ::
+
+ $ tail /sys/devices/system/cpu/hotplug/states
+ 138: mm/vmscan:online
+ 139: mm/vmstat:online
+ 140: lib/percpu_cnt:online
+ 141: acpi/cpu-drv:online
+ 142: base/cacheinfo:online
+ 143: virtio/net:online
+ 144: x86/mce:online
+ 145: printk:online
+ 168: sched:active
+ 169: online
+
+要将CPU4回滚到 ``lib/percpu_cnt:online`` ,再回到在线状态,只需发出::
+
+ $ cat /sys/devices/system/cpu/cpu4/hotplug/state
+ 169
+ $ echo 140 > /sys/devices/system/cpu/cpu4/hotplug/target
+ $ cat /sys/devices/system/cpu/cpu4/hotplug/state
+ 140
+
+需要注意的是,状态140的清除回调已经被调用。现在重新上线::
+
+ $ echo 169 > /sys/devices/system/cpu/cpu4/hotplug/target
+ $ cat /sys/devices/system/cpu/cpu4/hotplug/state
+ 169
+
+启用追踪事件后,单个步骤也是可见的::
+
+ # TASK-PID CPU# TIMESTAMP FUNCTION
+ # | | | | |
+ bash-394 [001] 22.976: cpuhp_enter: cpu: 0004 target: 140 step: 169 (cpuhp_kick_ap_work)
+ cpuhp/4-31 [004] 22.977: cpuhp_enter: cpu: 0004 target: 140 step: 168 (sched_cpu_deactivate)
+ cpuhp/4-31 [004] 22.990: cpuhp_exit: cpu: 0004 state: 168 step: 168 ret: 0
+ cpuhp/4-31 [004] 22.991: cpuhp_enter: cpu: 0004 target: 140 step: 144 (mce_cpu_pre_down)
+ cpuhp/4-31 [004] 22.992: cpuhp_exit: cpu: 0004 state: 144 step: 144 ret: 0
+ cpuhp/4-31 [004] 22.993: cpuhp_multi_enter: cpu: 0004 target: 140 step: 143 (virtnet_cpu_down_prep)
+ cpuhp/4-31 [004] 22.994: cpuhp_exit: cpu: 0004 state: 143 step: 143 ret: 0
+ cpuhp/4-31 [004] 22.995: cpuhp_enter: cpu: 0004 target: 140 step: 142 (cacheinfo_cpu_pre_down)
+ cpuhp/4-31 [004] 22.996: cpuhp_exit: cpu: 0004 state: 142 step: 142 ret: 0
+ bash-394 [001] 22.997: cpuhp_exit: cpu: 0004 state: 140 step: 169 ret: 0
+ bash-394 [005] 95.540: cpuhp_enter: cpu: 0004 target: 169 step: 140 (cpuhp_kick_ap_work)
+ cpuhp/4-31 [004] 95.541: cpuhp_enter: cpu: 0004 target: 169 step: 141 (acpi_soft_cpu_online)
+ cpuhp/4-31 [004] 95.542: cpuhp_exit: cpu: 0004 state: 141 step: 141 ret: 0
+ cpuhp/4-31 [004] 95.543: cpuhp_enter: cpu: 0004 target: 169 step: 142 (cacheinfo_cpu_online)
+ cpuhp/4-31 [004] 95.544: cpuhp_exit: cpu: 0004 state: 142 step: 142 ret: 0
+ cpuhp/4-31 [004] 95.545: cpuhp_multi_enter: cpu: 0004 target: 169 step: 143 (virtnet_cpu_online)
+ cpuhp/4-31 [004] 95.546: cpuhp_exit: cpu: 0004 state: 143 step: 143 ret: 0
+ cpuhp/4-31 [004] 95.547: cpuhp_enter: cpu: 0004 target: 169 step: 144 (mce_cpu_online)
+ cpuhp/4-31 [004] 95.548: cpuhp_exit: cpu: 0004 state: 144 step: 144 ret: 0
+ cpuhp/4-31 [004] 95.549: cpuhp_enter: cpu: 0004 target: 169 step: 145 (console_cpu_notify)
+ cpuhp/4-31 [004] 95.550: cpuhp_exit: cpu: 0004 state: 145 step: 145 ret: 0
+ cpuhp/4-31 [004] 95.551: cpuhp_enter: cpu: 0004 target: 169 step: 168 (sched_cpu_activate)
+ cpuhp/4-31 [004] 95.552: cpuhp_exit: cpu: 0004 state: 168 step: 168 ret: 0
+ bash-394 [005] 95.553: cpuhp_exit: cpu: 0004 state: 169 step: 140 ret: 0
+
+可以看到,CPU4一直下降到时间戳22.996,然后又上升到95.552。所有被调用的回调,
+包括它们的返回代码都可以在跟踪中看到。
+
+架构的要求
+==========
+
+需要具备以下功能和配置:
+
+``CONFIG_HOTPLUG_CPU``
+ 这个配置项需要在Kconfig中启用
+
+``__cpu_up()``
+ 调出一个cpu的架构接口
+
+``__cpu_disable()``
+ 关闭CPU的架构接口,在此程序返回后,内核不能再处理任何中断。这包括定时器的关闭。
+
+``__cpu_die()``
+ 这实际上是为了确保CPU的死亡。实际上,看看其他架构中实现CPU热拔插的一些示例代
+ 码。对于那个特定的架构,处理器被从 ``idle()`` 循环中拿下来。 ``__cpu_die()``
+ 通常会等待一些per_cpu状态的设置,以确保处理器的死亡例程被调用来保持活跃。
+
+用户空间通知
+============
+
+在CPU成功上线或下线后,udev事件被发送。一个udev规则,比如::
+
+ SUBSYSTEM=="cpu", DRIVERS=="processor", DEVPATH=="/devices/system/cpu/*", RUN+="the_hotplug_receiver.sh"
+
+将接收所有事件。一个像这样的脚本::
+
+ #!/bin/sh
+
+ if [ "${ACTION}" = "offline" ]
+ then
+ echo "CPU ${DEVPATH##*/} offline"
+
+ elif [ "${ACTION}" = "online" ]
+ then
+ echo "CPU ${DEVPATH##*/} online"
+
+ fi
+
+可以进一步处理该事件。
+
+内核内联文档参考
+================
+
+该API在以下内核代码中:
+
+include/linux/cpuhotplug.h
diff --git a/Documentation/translations/zh_CN/core-api/genericirq.rst b/Documentation/translations/zh_CN/core-api/genericirq.rst
new file mode 100644
index 000000000000..05ccb954c18d
--- /dev/null
+++ b/Documentation/translations/zh_CN/core-api/genericirq.rst
@@ -0,0 +1,409 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/genericirq.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 吴想成 Wu XiangCheng <bobwxc@email.cn>
+
+.. include:: <isonum.txt>
+
+.. _cn_core-api_genericirq:
+
+================
+Linux通用IRQ处理
+================
+
+:版权: |copy| 2005-2010: Thomas Gleixner
+:版权: |copy| 2005-2006: Ingo Molnar
+
+简介
+====
+
+通用中断处理层是为了给设备驱动程序提供一个完整的中断处理抽象(层)。它能够处
+理所有不同类型的中断控制器硬件。设备驱动程序使用通用API函数来请求、启用、禁
+用和释放中断。驱动程序不需要知道任何关于硬件处理中断的细节,所以它们可以在不同的
+平台上使用而不需要修改代码。
+
+本文档提供给那些希望在通用IRQ处理层的帮助下实现基于其架构的中断子系统的开发
+者。
+
+理论依据
+========
+
+Linux中中断处理的原始实现使用__do_IRQ()超级处理程序,它能够处理每种类型的
+中断逻辑。
+
+最初,Russell King确定了不同类型的处理程序,以便为Linux 2.5/2.6中的ARM中
+断处理程序实现建立一个相当通用的集合。他区分了以下几种类型:
+
+- 电平触发型
+
+- 边沿触发型
+
+- 简单型
+
+在实现过程中,我们发现了另一种类型:
+
+- 响应EOI(end of interrupt)型
+
+在SMP的__do_IRQ()超级处理程序中,还需定义一种类型:
+
+-  每cpu型(针对CPU SMP)
+
+这种高层IRQ处理程序的拆分实现使我们能够为每个特定的中断类型优化中断处理的流
+程。这减少了该特定代码路径的复杂性,并允许对特定类型进行优化处理。
+
+最初的通用IRQ实现使用hw_interrupt_type结构体及其 ``->ack`` ``->end`` 等回
+调来区分超级处理程序中的流控制。这导致了流逻辑和低级硬件逻辑的混合,也导致了
+不必要的代码重复:例如i386中的 ``ioapic_level_irq`` 和 ``ioapic_edge_irq`` ,
+这两个IRQ类型共享许多低级的细节,但有不同的流处理。
+
+一个更自然的抽象是“irq流”和“芯片细节”的干净分离。
+
+分析一些架构的IRQ子系统的实现可以发现,他们中的大多数可以使用一套通用的“irq
+流”方法,只需要添加芯片级的特定代码。这种分离对于那些需要IRQ流本身而不需要芯
+片细节的特定(子)架构也很有价值——以提供了一个更透明的IRQ子系统设计。
+
+每个中断描述符都被分配给它自己的高层流程处理程序,这通常是一个通用的实现。(这
+种高层次的流程处理程序的实现也使得提供解复用处理程序变得简单,这可以在各种架
+构的嵌入式平台上找到。)
+
+这种分离使得通用中断处理层更加灵活和可扩展。例如,一个(子)架构可以使用通用
+的IRQ流实现“电平触发型”中断,并添加一个(子)架构特定的“边沿型”实现。
+
+为了使向新模型的过渡更容易,并防止破坏现有实现,__do_IRQ()超级处理程序仍然
+可用。这导致了一种暂时的双重性。随着时间的推移,新的模型应该在越来越多的架构中
+被使用,因为它能使IRQ子系统更小更干净。它已经被废弃三年了,即将被删除。
+
+已知的缺陷和假设
+================
+
+没有(但愿如此)。
+
+抽象层
+======
+
+中断代码中主要有三个抽象层次:
+
+1. 高级别的驱动API
+
+2. 高级别的IRQ流处理器
+
+3. 芯片级的硬件封装
+
+中断控制流
+----------
+
+每个中断都由一个中断描述符结构体irq_desc来描述。中断是由一个“无符号整型”的数值来
+引用的,它在描述符结构体数组中选择相应的中断描述符结构体。描述符结构体包含状态
+信息和指向中断流方法和中断芯片结构的指针,这些都是分配给这个中断的。
+
+每当中断触发时,低级架构代码通过调用desc->handle_irq()调用到通用中断代码中。
+这个高层IRQ处理函数只使用由分配的芯片描述符结构体引用的desc->irq_data.chip
+基元。
+
+高级驱动程序API
+---------------
+
+高层驱动API由以下函数组成:
+
+- request_irq()
+
+- request_threaded_irq()
+
+- free_irq()
+
+- disable_irq()
+
+- enable_irq()
+
+- disable_irq_nosync() (SMP only)
+
+- synchronize_irq() (SMP only)
+
+- irq_set_irq_type()
+
+- irq_set_irq_wake()
+
+- irq_set_handler_data()
+
+- irq_set_chip()
+
+- irq_set_chip_data()
+
+详见自动生成的函数文档。
+
+.. note::
+
+ 由于文档构建流程所限,中文文档中并没有引入自动生成的函数文档,所以请读者直接
+ 阅读源码注释。
+
+电平触发型IRQ流处理程序
+-----------------------
+
+通用层提供了一套预定义的irq-flow方法:
+
+- handle_level_irq()
+
+- handle_edge_irq()
+
+- handle_fasteoi_irq()
+
+- handle_simple_irq()
+
+- handle_percpu_irq()
+
+- handle_edge_eoi_irq()
+
+- handle_bad_irq()
+
+中断流处理程序(无论是预定义的还是架构特定的)由架构在启动期间或设备初始化期间分配给
+特定中断。
+
+默认流实现
+~~~~~~~~~~
+
+辅助函数
+^^^^^^^^
+
+辅助函数调用芯片基元,并被默认流实现所使用。以下是实现的辅助函数(简化摘录)::
+
+ default_enable(struct irq_data *data)
+ {
+ desc->irq_data.chip->irq_unmask(data);
+ }
+
+ default_disable(struct irq_data *data)
+ {
+ if (!delay_disable(data))
+ desc->irq_data.chip->irq_mask(data);
+ }
+
+ default_ack(struct irq_data *data)
+ {
+ chip->irq_ack(data);
+ }
+
+ default_mask_ack(struct irq_data *data)
+ {
+ if (chip->irq_mask_ack) {
+ chip->irq_mask_ack(data);
+ } else {
+ chip->irq_mask(data);
+ chip->irq_ack(data);
+ }
+ }
+
+ noop(struct irq_data *data))
+ {
+ }
+
+
+
+默认流处理程序的实现
+~~~~~~~~~~~~~~~~~~~~
+
+电平触发型IRQ流处理器
+^^^^^^^^^^^^^^^^^^^^^
+
+handle_level_irq为电平触发型的中断提供了一个通用实现。
+
+实现的控制流如下(简化摘录)::
+
+ desc->irq_data.chip->irq_mask_ack();
+ handle_irq_event(desc->action);
+ desc->irq_data.chip->irq_unmask();
+
+
+默认的需回应IRQ流处理器
+^^^^^^^^^^^^^^^^^^^^^^^
+
+handle_fasteoi_irq为中断提供了一个通用的实现,它只需要在处理程序的末端有一个EOI。
+
+实现的控制流如下(简化摘录)::
+
+ handle_irq_event(desc->action);
+ desc->irq_data.chip->irq_eoi();
+
+
+默认的边沿触发型IRQ流处理器
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+handle_edge_irq为边沿触发型的中断提供了一个通用的实现。
+
+实现的控制流如下(简化摘录)::
+
+ if (desc->status & running) {
+ desc->irq_data.chip->irq_mask_ack();
+ desc->status |= pending | masked;
+ return;
+ }
+ desc->irq_data.chip->irq_ack();
+ desc->status |= running;
+ do {
+ if (desc->status & masked)
+ desc->irq_data.chip->irq_unmask();
+ desc->status &= ~pending;
+ handle_irq_event(desc->action);
+ } while (status & pending);
+ desc->status &= ~running;
+
+
+默认的简单型IRQ流处理器
+^^^^^^^^^^^^^^^^^^^^^^^
+
+handle_simple_irq提供了一个简单型中断的通用实现。
+
+.. note::
+
+ 简单型的流处理程序不调用任何处理程序/芯片基元。
+
+实现的控制流程如下(简化摘录)::
+
+ handle_irq_event(desc->action);
+
+
+默认的每CPU型流处理程序
+^^^^^^^^^^^^^^^^^^^^^^^
+
+handle_percpu_irq为每CPU型中断提供一个通用的实现。
+
+每个CPU中断只在SMP上可用,该处理程序提供了一个没有锁的简化版本。
+
+以下是控制流的实现(简化摘录)::
+
+ if (desc->irq_data.chip->irq_ack)
+ desc->irq_data.chip->irq_ack();
+ handle_irq_event(desc->action);
+ if (desc->irq_data.chip->irq_eoi)
+ desc->irq_data.chip->irq_eoi();
+
+
+EOI边沿型IRQ流处理器
+^^^^^^^^^^^^^^^^^^^^
+
+handle_edge_eoi_irq提供了一个异常的边沿触发型处理程序,它只用于拯救powerpc/cell
+上的一个严重失控的irq控制器。
+
+坏的IRQ流处理器
+^^^^^^^^^^^^^^^
+
+handle_bad_irq用于处理没有真正分配处理程序的假中断。
+
+特殊性和优化
+~~~~~~~~~~~~
+
+通用函数是为“干净”的架构和芯片设计的,它们没有平台特定的IRQ处理特殊性。如果一
+个架构需要在“流”的层面上实现特殊性,那么它可以通过覆盖高层的IRQ-流处理程序来实
+现。
+
+延迟中断禁用
+~~~~~~~~~~~~
+
+每个中断可选择的功能是由Russell King在ARM中断实现中引入的,当调用disable_irq()
+时,不会在硬件层面上屏蔽中断。中断保持启用状态,而在中断事件发生时在流处理器中被
+屏蔽。这可以防止在硬件上丢失边沿中断,因为硬件上不存储边沿中断事件,而中断在硬件
+级被禁用。当一个中断在IRQ_DISABLED标志被设置时到达,那么该中断在硬件层面被屏蔽,
+IRQ_PENDING位被设置。当中断被enable_irq()重新启用时,将检查挂起位,如果它被设置,
+中断将通过硬件或软件重发机制重新发送。(当你想使用延迟中断禁用功能,而你的硬件又不
+能重新触发中断时,有必要启用CONFIG_HARDIRQS_SW_RESEND。) 延迟中断禁止功能是不可
+配置的。
+
+芯片级硬件封装
+--------------
+
+芯片级硬件描述符结构体 :c:type:`irq_chip` 包含了所有与芯片直接相关的功能,这些功
+能可以被irq流实现所利用。
+
+- ``irq_ack``
+
+- ``irq_mask_ack`` - 可选的,建议使用的性能
+
+- ``irq_mask``
+
+- ``irq_unmask``
+
+- ``irq_eoi`` - 可选的,EOI流处理程序需要
+
+- ``irq_retrigger`` - 可选的
+
+- ``irq_set_type`` - 可选的
+
+- ``irq_set_wake`` - 可选的
+
+这些基元的意思是严格意义上的:ack是指ACK,masking是指对IRQ线的屏蔽,等等。这取决
+于流处理器如何使用这些基本的低级功能单元。
+
+__do_IRQ入口点
+==============
+
+最初的实现__do_IRQ()是所有类型中断的替代入口点。它已经不存在了。
+
+这个处理程序被证明不适合所有的中断硬件,因此被重新实现了边沿/级别/简单/超高速中断
+的拆分功能。这不仅是一个功能优化。它也缩短了中断的代码路径。
+
+在SMP上的锁
+===========
+
+芯片寄存器的锁定是由定义芯片基元的架构决定的。每个寄存器的结构通过desc->lock,由
+通用层保护。
+
+通用中断芯片
+============
+
+为了避免复制相同的IRQ芯片实现,核心提供了一个可配置的通用中断芯片实现。开发者在自
+己实现相同的功能之前,应该仔细检查通用芯片是否符合他们的需求,并以稍微不同的方式实
+现相同的功能。
+
+该API在以下内核代码中:
+
+kernel/irq/generic-chip.c
+
+结构体
+======
+
+本章包含自动生成的结构体文档,这些结构体在通用IRQ层中使用。
+
+该API在以下内核代码中:
+
+include/linux/irq.h
+
+include/linux/interrupt.h
+
+提供的通用函数
+==============
+
+这一章包含了自动生成的内核API函数的文档,这些函数被导出。
+
+该API在以下内核代码中:
+
+kernel/irq/manage.c
+
+kernel/irq/chip.c
+
+提供的内部函数
+==============
+
+本章包含自动生成的内部函数的文档。
+
+该API在以下内核代码中:
+
+kernel/irq/irqdesc.c
+
+kernel/irq/handle.c
+
+kernel/irq/chip.c
+
+鸣谢
+====
+
+感谢以下人士对本文档作出的贡献:
+
+1. Thomas Gleixner tglx@linutronix.de
+
+2. Ingo Molnar mingo@elte.hu
diff --git a/Documentation/translations/zh_CN/core-api/index.rst b/Documentation/translations/zh_CN/core-api/index.rst
index b4bde9396339..d5e947d8b6f1 100644
--- a/Documentation/translations/zh_CN/core-api/index.rst
+++ b/Documentation/translations/zh_CN/core-api/index.rst
@@ -80,14 +80,17 @@ Todolist:
:maxdepth: 1
cachetlb
+ cpu_hotplug
+ genericirq
+ memory-hotplug
+ protection-keys
Todolist:
- cpu_hotplug
memory-hotplug
+ cpu_hotplug
genericirq
- protection-keys
内存管理
diff --git a/Documentation/translations/zh_CN/core-api/memory-hotplug.rst b/Documentation/translations/zh_CN/core-api/memory-hotplug.rst
new file mode 100644
index 000000000000..161f4d2c18cc
--- /dev/null
+++ b/Documentation/translations/zh_CN/core-api/memory-hotplug.rst
@@ -0,0 +1,126 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/memory_hotplug.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 吴想成 Wu XiangCheng <bobwxc@email.cn>
+
+.. _cn_core-api_memory-hotplug:
+
+==========
+内存热插拔
+==========
+
+内存热拔插事件通知器
+====================
+
+热插拔事件被发送到一个通知队列中。
+
+在 ``include/linux/memory.h`` 中定义了六种类型的通知:
+
+MEM_GOING_ONLINE
+ 在新内存可用之前生成,以便能够为子系统处理内存做准备。页面分配器仍然无法从新
+ 的内存中进行分配。
+
+MEM_CANCEL_ONLINE
+ 如果MEM_GOING_ONLINE失败,则生成。
+
+MEM_ONLINE
+ 当内存成功上线时产生。回调可以从新的内存中分配页面。
+
+MEM_GOING_OFFLINE
+ 在开始对内存进行下线处理时生成。从内存中的分配不再可能,但是一些要下线的内存
+ 仍然在使用。回调可以用来释放一个子系统在指定内存块中已知的内存。
+
+MEM_CANCEL_OFFLINE
+ 如果MEM_GOING_OFFLINE失败,则生成。来自我们试图离线的内存块中的内存又可以使
+ 用了。
+
+MEM_OFFLINE
+ 在内存下线完成后生成。
+
+可以通过调用如下函数来注册一个回调程序:
+
+ hotplug_memory_notifier(callback_func, priority)
+
+优先级数值较高的回调函数在数值较低的回调函数之前被调用。
+
+一个回调函数必须有以下原型::
+
+ int callback_func(
+ struct notifier_block *self, unsigned long action, void *arg);
+
+回调函数的第一个参数(self)是指向回调函数本身的通知器链块的一个指针。第二个参
+数(action)是上述的事件类型之一。第三个参数(arg)传递一个指向
+memory_notify结构体的指针::
+
+ struct memory_notify {
+ unsigned long start_pfn;
+ unsigned long nr_pages;
+ int status_change_nid_normal;
+ int status_change_nid_high;
+ int status_change_nid;
+ }
+
+- start_pfn是在线/离线内存的start_pfn。
+
+- nr_pages是在线/离线内存的页数。
+
+- status_change_nid_normal是当nodemask的N_NORMAL_MEMORY被设置/清除时设置节
+ 点id,如果是-1,则nodemask状态不改变。
+
+- status_change_nid_high是当nodemask的N_HIGH_MEMORY被设置/清除时设置的节点
+ id,如果这个值为-1,那么nodemask状态不会改变。
+
+- status_change_nid是当nodemask的N_MEMORY被(将)设置/清除时设置的节点id。这
+ 意味着一个新的(没上线的)节点通过联机获得新的内存,而一个节点失去了所有的内
+ 存。如果这个值为-1,那么nodemask的状态就不会改变。
+
+ 如果 status_changed_nid* >= 0,回调应该在必要时为节点创建/丢弃结构体。
+
+回调程序应返回 ``include/linux/notifier.h`` 中定义的NOTIFY_DONE, NOTIFY_OK,
+NOTIFY_BAD, NOTIFY_STOP中的一个值。
+
+NOTIFY_DONE和NOTIFY_OK对进一步处理没有影响。
+
+NOTIFY_BAD是作为对MEM_GOING_ONLINE、MEM_GOING_OFFLINE、MEM_ONLINE或MEM_OFFLINE
+动作的回应,用于取消热插拔。它停止对通知队列的进一步处理。
+
+NOTIFY_STOP停止对通知队列的进一步处理。
+
+内部锁
+======
+
+当添加/删除使用内存块设备(即普通RAM)的内存时,device_hotplug_lock应该被保持
+为:
+
+- 针对在线/离线请求进行同步(例如,通过sysfs)。这样一来,内存块设备只有在内存
+ 被完全添加后才能被用户空间访问(.online/.state属性)。而在删除内存时,我们知
+ 道没有人在临界区。
+
+- 与CPU热拔插或类似操作同步(例如ACPI和PPC相关操作)
+
+特别是,在添加内存和用户空间试图以比预期更快的速度上线该内存时,有可能出现锁反转,
+使用device_hotplug_lock可以避免此情况:
+
+- device_online()将首先接受device_lock(),然后是mem_hotplug_lock。
+
+- add_memory_resource()将首先使用mem_hotplug_lock,然后是device_lock()(在创
+ 建设备时,在bus_add_device()期间)。
+
+由于在使用device_lock()之前,设备对用户空间是可见的,这可能导致锁的反转。
+
+内存的上线/下线应该通过device_online()/device_offline()完成————确保它与通过
+sysfs进行的操作正确同步。建议持有device_hotplug_lock(例如,保护online_type)。
+
+当添加/删除/上线/下线内存或者添加/删除异构或设备内存时,我们应该始终持有写模式的
+mem_hotplug_lock,以序列化内存热插拔(例如访问全局/区域变量)。
+
+此外,mem_hotplug_lock(与device_hotplug_lock相反)在读取模式下允许一个相当
+有效的get_online_mems/put_online_mems实现,所以访问内存的代码可以防止该内存
+消失。
diff --git a/Documentation/translations/zh_CN/core-api/protection-keys.rst b/Documentation/translations/zh_CN/core-api/protection-keys.rst
new file mode 100644
index 000000000000..d07830050153
--- /dev/null
+++ b/Documentation/translations/zh_CN/core-api/protection-keys.rst
@@ -0,0 +1,99 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/protection-keys.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 吴想成 Wu XiangCheng <bobwxc@email.cn>
+
+.. _cn_core-api_protection-keys:
+
+============
+内存保护密钥
+============
+
+用户空间的内存保护密钥(Memory Protection Keys for Userspace,PKU,亦
+即PKEYs)是英特尔Skylake(及以后)“可扩展处理器”服务器CPU上的一项功能。
+它将在未来的非服务器英特尔处理器和未来的AMD处理器中可用。
+
+对于任何希望测试或使用该功能的人来说,它在亚马逊的EC2 C5实例中是可用的,
+并且已知可以在那里使用Ubuntu 17.04镜像运行。
+
+内存保护密钥提供了一种机制来执行基于页面的保护,但在应用程序改变保护域
+时不需要修改页表。它的工作原理是在每个页表项中为“保护密钥”分配4个以
+前被忽略的位,从而提供16个可能的密钥。
+
+还有一个新的用户可访问寄存器(PKRU),为每个密钥提供两个单独的位(访
+问禁止和写入禁止)。作为一个CPU寄存器,PKRU在本质上是线程本地的,可能
+会给每个线程提供一套不同于其他线程的保护措施。
+
+有两条新指令(RDPKRU/WRPKRU)用于读取和写入新的寄存器。该功能仅在64位
+模式下可用,尽管物理地址扩展页表中理论上有空间。这些权限只在数据访问上
+强制执行,对指令获取没有影响。
+
+
+系统调用
+========
+
+有3个系统调用可以直接与pkeys进行交互::
+
+ int pkey_alloc(unsigned long flags, unsigned long init_access_rights)
+ int pkey_free(int pkey);
+ int pkey_mprotect(unsigned long start, size_t len,
+ unsigned long prot, int pkey);
+
+在使用一个pkey之前,必须先用pkey_alloc()分配它。一个应用程序直接调用
+WRPKRU指令,以改变一个密钥覆盖的内存的访问权限。在这个例子中,WRPKRU
+被一个叫做pkey_set()的C函数所封装::
+
+ int real_prot = PROT_READ|PROT_WRITE;
+ pkey = pkey_alloc(0, PKEY_DISABLE_WRITE);
+ ptr = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ ret = pkey_mprotect(ptr, PAGE_SIZE, real_prot, pkey);
+ ... application runs here
+
+现在,如果应用程序需要更新'ptr'处的数据,它可以获得访问权,进行更新,
+然后取消其写访问权::
+
+ pkey_set(pkey, 0); // clear PKEY_DISABLE_WRITE
+ *ptr = foo; // assign something
+ pkey_set(pkey, PKEY_DISABLE_WRITE); // set PKEY_DISABLE_WRITE again
+
+现在,当它释放内存时,它也将释放pkey,因为它不再被使用了::
+
+ munmap(ptr, PAGE_SIZE);
+ pkey_free(pkey);
+
+.. note:: pkey_set()是RDPKRU和WRPKRU指令的一个封装器。在tools/testing/selftests/x86/protection_keys.c中可以找到一个实现实例。
+ tools/testing/selftests/x86/protection_keys.c.
+
+行为
+====
+
+内核试图使保护密钥与普通的mprotect()的行为一致。例如,如果你这样做::
+
+ mprotect(ptr, size, PROT_NONE);
+ something(ptr);
+
+这样做的时候,你可以期待保护密钥的相同效果::
+
+ pkey = pkey_alloc(0, PKEY_DISABLE_WRITE | PKEY_DISABLE_READ);
+ pkey_mprotect(ptr, size, PROT_READ|PROT_WRITE, pkey);
+ something(ptr);
+
+无论something()是否是对'ptr'的直接访问,这都应该为真。
+如::
+
+ *ptr = foo;
+
+或者当内核代表应用程序进行访问时,比如read()::
+
+ read(fd, ptr, 1);
+
+在这两种情况下,内核都会发送一个SIGSEGV,但当违反保护密钥时,si_code
+将被设置为SEGV_PKERR,而当违反普通的mprotect()权限时,则是SEGV_ACCERR。
diff --git a/Documentation/translations/zh_CN/dev-tools/index.rst b/Documentation/translations/zh_CN/dev-tools/index.rst
index e6c99f2f543f..0f770b8664e9 100644
--- a/Documentation/translations/zh_CN/dev-tools/index.rst
+++ b/Documentation/translations/zh_CN/dev-tools/index.rst
@@ -11,6 +11,9 @@
目前这些文档已经整理在一起,不需要再花费额外的精力。
欢迎任何补丁。
+有关测试专用工具的简要概述,参见
+Documentation/translations/zh_CN/dev-tools/testing-overview.rst
+
.. class:: toc-title
目录
@@ -18,6 +21,7 @@
.. toctree::
:maxdepth: 2
+ testing-overview
gcov
kasan
@@ -29,6 +33,7 @@ Todolist:
- ubsan
- kmemleak
- kcsan
+ - kfence
- gdb-kernel-debugging
- kgdb
- kselftest
diff --git a/Documentation/translations/zh_CN/dev-tools/testing-overview.rst b/Documentation/translations/zh_CN/dev-tools/testing-overview.rst
new file mode 100644
index 000000000000..b7a1d13da6c6
--- /dev/null
+++ b/Documentation/translations/zh_CN/dev-tools/testing-overview.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/dev-tools/testing-overview.rst
+:Translator: 胡皓文 Hu Haowen <src.res@email.cn>
+
+============
+内核测试指南
+============
+
+有许多不同的工具可以用于测试Linux内核,因此了解什么时候使用它们可能
+很困难。本文档粗略概述了它们之间的区别,并阐释了它们是怎样糅合在一起
+的。
+
+编写和运行测试
+==============
+
+大多数内核测试都是用kselftest或KUnit框架之一编写的。它们都让运行测试
+更加简化,并为编写新测试提供帮助。
+
+如果你想验证内核的行为——尤其是内核的特定部分——那你就要使用kUnit或
+kselftest。
+
+KUnit和kselftest的区别
+----------------------
+
+.. note::
+ 由于本文段中部分术语尚无较好的对应中文释义,可能导致与原文含义
+ 存在些许差异,因此建议读者结合原文
+ (Documentation/dev-tools/testing-overview.rst)辅助阅读。
+ 如对部分翻译有异议或有更好的翻译意见,欢迎联系译者进行修订。
+
+KUnit(Documentation/dev-tools/kunit/index.rst)是用于“白箱”测
+试的一个完整的内核内部系统:因为测试代码是内核的一部分,所以它能够访
+问用户空间不能访问到的内部结构和功能。
+
+因此,KUnit测试最好针对内核中较小的、自包含的部分,以便能够独立地测
+试。“单元”测试的概念亦是如此。
+
+比如,一个KUnit测试可能测试一个单独的内核功能(甚至通过一个函数测试
+一个单一的代码路径,例如一个错误处理案例),而不是整个地测试一个特性。
+
+这也使得KUnit测试构建和运行非常地快,从而能够作为开发流程的一部分被
+频繁地运行。
+
+有关更详细的介绍,请参阅KUnit测试代码风格指南
+Documentation/dev-tools/kunit/style.rst
+
+kselftest(Documentation/dev-tools/kselftest.rst),相对来说,大量用
+于用户空间,并且通常测试用户空间的脚本或程序。
+
+这使得编写复杂的测试,或者需要操作更多全局系统状态的测试更加容易(诸
+如生成进程之类)。然而,从kselftest直接调用内核函数是不行的。这也就
+意味着只有通过某种方式(如系统调用、驱动设备、文件系统等)导出到了用
+户空间的内核功能才能使用kselftest来测试。为此,有些测试包含了一个伴
+生的内核模块用于导出更多的信息和功能。不过,对于基本上或者完全在内核
+中运行的测试,KUnit可能是更佳工具。
+
+kselftest也因此非常适合于全部功能的测试,因为这些功能会将接口暴露到
+用户空间,从而能够被测试,而不是展现实现细节。“system”测试和
+“end-to-end”测试亦是如此。
+
+比如,一个新的系统调用应该伴随有新的kselftest测试。
+
+代码覆盖率工具
+==============
+
+支持两种不同代码之间的覆盖率测量工具。它们可以用来验证一项测试执行的
+确切函数或代码行。这有助于决定内核被测试了多少,或用来查找合适的测试
+中没有覆盖到的极端情况。
+
+Documentation/translations/zh_CN/dev-tools/gcov.rst 是GCC的覆盖率测试
+工具,能用于获取内核的全局或每个模块的覆盖率。与KCOV不同的是,这个工具
+不记录每个任务的覆盖率。覆盖率数据可以通过debugfs读取,并通过常规的
+gcov工具进行解释。
+
+Documentation/dev-tools/kcov.rst 是能够构建在内核之中,用于在每个任务
+的层面捕捉覆盖率的一个功能。因此,它对于模糊测试和关于代码执行期间信
+息的其它情况非常有用,比如在一个单一系统调用里使用它就很有用。
+
+动态分析工具
+============
+
+内核也支持许多动态分析工具,用以检测正在运行的内核中出现的多种类型的
+问题。这些工具通常每个去寻找一类不同的缺陷,比如非法内存访问,数据竞
+争等并发问题,或整型溢出等其他未定义行为。
+
+如下所示:
+
+* kmemleak检测可能的内存泄漏。参阅
+ Documentation/dev-tools/kmemleak.rst
+* KASAN检测非法内存访问,如数组越界和释放后重用(UAF)。参阅
+ Documentation/dev-tools/kasan.rst
+* UBSAN检测C标准中未定义的行为,如整型溢出。参阅
+ Documentation/dev-tools/ubsan.rst
+* KCSAN检测数据竞争。参阅 Documentation/dev-tools/kcsan.rst
+* KFENCE是一个低开销的内存问题检测器,比KASAN更快且能被用于批量构建。
+ 参阅 Documentation/dev-tools/kfence.rst
+* lockdep是一个锁定正确性检测器。参阅
+ Documentation/locking/lockdep-design.rst
+* 除此以外,在内核中还有一些其它的调试工具,大多数能在
+ lib/Kconfig.debug 中找到。
+
+这些工具倾向于对内核进行整体测试,并且不像kselftest和KUnit一样“传递”。
+它们可以通过在启用这些工具时运行内核测试以与kselftest或KUnit结合起来:
+之后你就能确保这些错误在测试过程中都不会发生了。
+
+一些工具与KUnit和kselftest集成,并且在检测到问题时会自动打断测试。
diff --git a/Documentation/translations/zh_CN/index.rst b/Documentation/translations/zh_CN/index.rst
index 1f953d3439a5..a34e58733ac8 100644
--- a/Documentation/translations/zh_CN/index.rst
+++ b/Documentation/translations/zh_CN/index.rst
@@ -5,6 +5,7 @@
\renewcommand\thesection*
\renewcommand\thesubsection*
\kerneldocCJKon
+ \kerneldocBeginSC
.. _linux_doc_zh:
@@ -17,6 +18,11 @@
**翻译计划:**
内核中文文档欢迎任何翻译投稿,特别是关于内核用户和管理员指南部分。
+这是中文内核文档树的顶级目录。内核文档,就像内核本身一样,在很大程度上是一
+项正在进行的工作;当我们努力将许多分散的文件整合成一个连贯的整体时尤其如此。
+另外,随时欢迎您对内核文档进行改进;如果您想提供帮助,请加入vger.kernel.org
+上的linux-doc邮件列表。
+
许可证文档
----------
@@ -97,12 +103,14 @@ TODOList:
iio/index
sound/index
filesystems/index
+ virt/index
+ infiniband/index
+ accounting/index
TODOList:
* driver-api/index
* locking/index
-* accounting/index
* block/index
* cdrom/index
* ide/index
@@ -111,7 +119,6 @@ TODOList:
* hid/index
* i2c/index
* isdn/index
-* infiniband/index
* leds/index
* netlabel/index
* networking/index
@@ -122,7 +129,6 @@ TODOList:
* spi/index
* w1/index
* watchdog/index
-* virt/index
* input/index
* hwmon/index
* gpu/index
@@ -184,3 +190,7 @@ TODOList:
----------
* :ref:`genindex`
+
+.. raw:: latex
+
+ \kerneldocEndSC
diff --git a/Documentation/translations/zh_CN/infiniband/core_locking.rst b/Documentation/translations/zh_CN/infiniband/core_locking.rst
new file mode 100644
index 000000000000..42f08038d44b
--- /dev/null
+++ b/Documentation/translations/zh_CN/infiniband/core_locking.rst
@@ -0,0 +1,115 @@
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/infiniband/core_locking.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 王普宇 Puyu Wang <realpuyuwang@gmail.com>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_infiniband_core_locking:
+
+==================
+infiniband中间层锁
+==================
+
+ 本指南试图明确infiniband中间层的锁假设。它描述了对位于中间层以下的低
+ 级驱动程序和使用中间层的上层协议的要求。
+
+睡眠和中断环境
+==============
+
+ 除了以下异常情况,ib_device结构体中所有方法的低级驱动实现都可以睡眠。
+ 这些异常情况是列表中的任意的方法:
+
+ - create_ah
+ - modify_ah
+ - query_ah
+ - destroy_ah
+ - post_send
+ - post_recv
+ - poll_cq
+ - req_notify_cq
+
+ 他们可能不可以睡眠,而且必须可以从任何上下文中调用。
+
+ 向上层协议使用者输出的相应函数:
+
+ - rdma_create_ah
+ - rdma_modify_ah
+ - rdma_query_ah
+ - rdma_destroy_ah
+ - ib_post_send
+ - ib_post_recv
+ - ib_req_notify_cq
+
+ 因此,在任何情况下都可以安全调用(它们)。
+
+ 此外,该函数
+
+ - ib_dispatch_event
+
+ 被底层驱动用来通过中间层调度异步事件的“A”,也可以从任何上下文中安全调
+ 用。
+
+可重入性
+--------
+
+ 由低级驱动程序导出的ib_device结构体中的所有方法必须是完全可重入的。
+ 即使使用同一对象的多个函数调用被同时运行,低级驱动程序也需要执行所有
+ 必要的同步以保持一致性。
+
+ IB中间层不执行任何函数调用的序列化。
+
+ 因为低级驱动程序是可重入的,所以不要求上层协议使用者任何顺序执行。然
+ 而,为了得到合理的结果,可能需要一些顺序。例如,一个使用者可以在多个
+ CPU上同时安全地调用ib_poll_cq()。然而,不同的ib_poll_cq()调用之间
+ 的工作完成信息的顺序没有被定义。
+
+回调
+----
+
+ 低级驱动程序不得直接从与ib_device方法调用相同的调用链中执行回调。例
+ 如,低级驱动程序不允许从post_send方法直接调用使用者的完成事件处理程
+ 序。相反,低级驱动程序应该推迟这个回调,例如,调度一个tasklet来执行
+ 这个回调。
+
+ 低层驱动负责确保同一CQ的多个完成事件处理程序不被同时调用。驱动程序必
+ 须保证一个给定的CQ的事件处理程序在同一时间只有一个在运行。换句话说,
+ 以下情况是不允许的::
+
+ CPU1 CPU2
+
+ low-level driver ->
+ consumer CQ event callback:
+ /* ... */
+ ib_req_notify_cq(cq, ...);
+ low-level driver ->
+ /* ... */ consumer CQ event callback:
+ /* ... */
+ return from CQ event handler
+
+ 完成事件和异步事件回调的运行环境没有被定义。 根据低级别的驱动程序,它可能是
+ 进程上下文、softirq上下文或中断上下文。上层协议使用者可能不会在回调中睡眠。
+
+热插拔
+------
+
+ 当一个低级驱动程序调用ib_register_device()时,它宣布一个设备已经
+ 准备好供使用者使用,所有的初始化必须在这个调用之前完成。设备必须保
+ 持可用,直到驱动对ib_unregister_device()的调用返回。
+
+ 低级驱动程序必须从进程上下文调用ib_register_device()和
+ ib_unregister_device()。如果使用者在这些调用中回调到驱动程序,它
+ 不能持有任何可能导致死锁的semaphores。
+
+ 一旦其结构体ib_client的add方法被调用,上层协议使用者就可以开始使用
+ 一个IB设备。使用者必须在从移除方法返回之前完成所有的清理工作并释放
+ 与设备相关的所有资源。
+
+ 使用者被允许在其添加和删除方法中睡眠。
diff --git a/Documentation/translations/zh_CN/infiniband/index.rst b/Documentation/translations/zh_CN/infiniband/index.rst
new file mode 100644
index 000000000000..5634cc48379f
--- /dev/null
+++ b/Documentation/translations/zh_CN/infiniband/index.rst
@@ -0,0 +1,40 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/infiniband/index.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 王普宇 Puyu Wang <realpuyuwang@gmail.com>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_infiniband_index:
+
+==========
+infiniband
+==========
+
+.. toctree::
+ :maxdepth: 1
+
+ core_locking
+ ipoib
+ opa_vnic
+ sysfs
+ tag_matching
+ user_mad
+ user_verbs
+
+
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/infiniband/ipoib.rst b/Documentation/translations/zh_CN/infiniband/ipoib.rst
new file mode 100644
index 000000000000..56517ea5fe9d
--- /dev/null
+++ b/Documentation/translations/zh_CN/infiniband/ipoib.rst
@@ -0,0 +1,111 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/infiniband/ipoib.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 王普宇 Puyu Wang <realpuyuwang@gmail.com>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_infiniband_ipoib:
+
+=========================
+infiniband上的IP(IPoIB)
+=========================
+
+ ib_ipoib驱动是IETF ipoib工作组发布的RFC 4391和4392所规定的
+ infiniband上IP协议的一个实现。它是一个“本地”实现,即把接口类型设置为
+ ARPHRD_INFINIBAND,硬件地址长度为20(早期的专有实现向内核伪装为以太网
+ 接口)。
+
+分区和P_Keys
+============
+
+ 当IPoIB驱动被加载时,它会使用索引为0的P_Key给每个端口创建一个接口。要用
+ 不同的P_Key创建一个接口,将所需的P_Key写入主接口的
+ /sys/class/net/<intf name>/create_child文件里面。比如说::
+
+ echo 0x8001 > /sys/class/net/ib0/create_child
+
+ 这将用P_Key 0x8001创建一个名为ib0.8001的接口。要删除一个子接口,使用
+ ``delete_child`` 文件::
+
+ echo 0x8001 > /sys/class/net/ib0/delete_child
+
+ 任何接口的P_Key都由“pkey”文件给出,而子接口的主接口在“parent”中。
+
+ 子接口的创建/删除也可以使用IPoIB的rtnl_link_ops来完成,使用两种
+ 方式创建的子接口的行为是一样的。
+
+数据报与连接模式
+================
+
+ IPoIB驱动支持两种操作模式:数据报和连接。模式是通过接口的
+ /sys/class/net/<intf name>/mode文件设置和读取的。
+
+ 在数据报模式下,使用IB UD(不可靠数据报)传输,因此接口MTU等于IB L2 MTU
+ 减去IPoIB封装头(4字节)。例如,在一个典型的具有2K MTU的IB结构中,IPoIB
+ MTU将是2048 - 4 = 2044字节。
+
+ 在连接模式下,使用IB RC(可靠的连接)传输。连接模式利用IB传输的连接特性,
+ 允许MTU达到最大的IP包大小64K,这减少了处理大型UDP数据包、TCP段等所需的
+ IP包数量,提高了大型信息的性能。
+
+ 在连接模式下,接口的UD QP仍被用于组播和与不支持连接模式的对等体的通信。
+ 在这种情况下,ICMP PMTU数据包的RX仿真被用来使网络堆栈对这些邻居使用较
+ 小的UD MTU。
+
+无状态卸载
+==========
+
+ 如果IB HW支持IPoIB无状态卸载,IPoIB会向网络堆栈广播TCP/IP校验和/或大量
+ 传送(LSO)负载转移能力。
+
+ 大量传送(LSO)负载转移也已实现,可以使用ethtool调用打开/关闭。目前,LRO
+ 只支持具有校验和卸载能力的设备。
+
+ 无状态卸载只在数据报模式下支持。
+
+中断管理
+========
+
+ 如果底层IB设备支持CQ事件管理,可以使用ethtool来设置中断缓解参数,从而减少
+ 处理中断产生的开销。IPoIB的主要代码路径不使用TX完成信号的事件,所以只支持
+ RX管理。
+
+调试信息
+========
+
+ 通过将CONFIG_INFINIBAND_IPOIB_DEBUG设置为“y”来编译IPoIB驱动,跟踪信
+ 息被编译到驱动中。通过将模块参数debug_level和mcast_debug_level设置为1来
+ 打开它们。这些参数可以在运行时通过/sys/module/ib_ipoib/的文件来控制。
+
+ CONFIG_INFINIBAND_IPOIB_DEBUG也启用debugfs虚拟文件系统中的文件。通过挂
+ 载这个文件系统,例如用::
+
+ mount -t debugfs none /sys/kernel/debug
+
+ 可以从/sys/kernel/debug/ipoib/ib0_mcg等文件中获得关于多播组的统计数据。
+
+ 这个选项对性能的影响可以忽略不计,所以在正常运行时,在debug_level设置为
+ 0的情况下启用这个选项是安全的。
+
+ CONFIG_INFINIBAND_IPOIB_DEBUG_DATA当data_debug_level设置为1时,可以
+ 在数据路径中启用更多的调试输出。 然而,即使禁用输出,启用这个配置选项也
+ 会影响性能,因为它在快速路径中增加了测试。
+
+引用
+====
+
+ 在InfiniBand上传输IP(IPoIB)(RFC 4391)。
+ http://ietf.org/rfc/rfc4391.txt
+
+ infiniband上的IP:上的IP架构(RFC 4392)。
+ http://ietf.org/rfc/rfc4392.txt
+
+ infiniband上的IP: 连接模式 (RFC 4755)
+ http://ietf.org/rfc/rfc4755.txt
diff --git a/Documentation/translations/zh_CN/infiniband/opa_vnic.rst b/Documentation/translations/zh_CN/infiniband/opa_vnic.rst
new file mode 100644
index 000000000000..12b147fbf792
--- /dev/null
+++ b/Documentation/translations/zh_CN/infiniband/opa_vnic.rst
@@ -0,0 +1,156 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/infiniband/opa_vnic.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 王普宇 Puyu Wang <realpuyuwang@gmail.com>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_infiniband_opa_vnic:
+
+=============================================
+英特尔全路径(OPA)虚拟网络接口控制器(VNIC)
+=============================================
+
+英特尔全路径(OPA)虚拟网络接口控制器(VNIC)功能通过封装HFI节点之间的以
+太网数据包,支持Omni-Path结构上的以太网功能。
+
+体系结构
+========
+
+Omni-Path封装的以太网数据包的交换模式涉及Omni-Path结构拓扑上覆盖的一个或
+多个虚拟以太网交换机。Omni-Path结构上的HFI节点的一个子集被允许在特定的虚
+拟以太网交换机上交换封装的以太网数据包。虚拟以太网交换机是通过配置结构上的
+HFI节点实现的逻辑抽象,用于生成和处理报头。在最简单的配置中,整个结构的所有
+HFI节点通过一个虚拟以太网交换机交换封装的以太网数据包。一个虚拟以太网交换机,
+实际上是一个独立的以太网网络。该配置由以太网管理器(EM)执行,它是可信的结
+构管理器(FM)应用程序的一部分。HFI节点可以有多个VNIC,每个连接到不同的虚
+拟以太网交换机。下图介绍了两个虚拟以太网交换机与两个HFI节点的情况::
+
+ +-------------------+
+ | 子网/ |
+ | 以太网 |
+ | 管理 |
+ +-------------------+
+ / /
+ / /
+ / /
+ / /
+ +-----------------------------+ +------------------------------+
+ | 虚拟以太网切换 | | 虚拟以太网切换 |
+ | +---------+ +---------+ | | +---------+ +---------+ |
+ | | VPORT | | VPORT | | | | VPORT | | VPORT | |
+ +--+---------+----+---------+-+ +-+---------+----+---------+---+
+ | \ / |
+ | \ / |
+ | \/ |
+ | / \ |
+ | / \ |
+ +-----------+------------+ +-----------+------------+
+ | VNIC | VNIC | | VNIC | VNIC |
+ +-----------+------------+ +-----------+------------+
+ | HFI | | HFI |
+ +------------------------+ +------------------------+
+
+
+Omni-Path封装的以太网数据包格式如下所述。
+
+==================== ================================
+位 域
+==================== ================================
+Quad Word 0:
+0-19 SLID (低20位)
+20-30 长度 (以四字为单位)
+31 BECN 位
+32-51 DLID (低20位)
+52-56 SC (服务级别)
+57-59 RC (路由控制)
+60 FECN 位
+61-62 L2 (=10, 16B 格式)
+63 LT (=1, 链路传输头 Flit)
+
+Quad Word 1:
+0-7 L4 type (=0x78 ETHERNET)
+8-11 SLID[23:20]
+12-15 DLID[23:20]
+16-31 PKEY
+32-47 熵
+48-63 保留
+
+Quad Word 2:
+0-15 保留
+16-31 L4 头
+32-63 以太网数据包
+
+Quad Words 3 to N-1:
+0-63 以太网数据包 (pad拓展)
+
+Quad Word N (last):
+0-23 以太网数据包 (pad拓展)
+24-55 ICRC
+56-61 尾
+62-63 LT (=01, 链路传输尾 Flit)
+==================== ================================
+
+以太网数据包在传输端被填充,以确保VNIC OPA数据包是四字对齐的。“尾”字段
+包含填充的字节数。在接收端,“尾”字段被读取,在将数据包向上传递到网络堆
+栈之前,填充物被移除(与ICRC、尾和OPA头一起)。
+
+L4头字段包含VNIC端口所属的虚拟以太网交换机ID。在接收端,该字段用于将收
+到的VNIC数据包去多路复用到不同的VNIC端口。
+
+驱动设计
+========
+
+英特尔OPA VNIC的软件设计如下图所示。OPA VNIC功能有一个依赖于硬件的部分
+和一个独立于硬件的部分。
+
+对IB设备分配和释放RDMA netdev设备的支持已经被加入。RDMA netdev支持与
+网络堆栈的对接,从而创建标准的网络接口。OPA_VNIC是一个RDMA netdev设备
+类型。
+
+依赖于HW的VNIC功能是HFI1驱动的一部分。它实现了分配和释放OPA_VNIC RDMA
+netdev的动作。它涉及VNIC功能的HW资源分配/管理。它与网络堆栈接口并实现所
+需的net_device_ops功能。它在传输路径中期待Omni-Path封装的以太网数据包,
+并提供对它们的HW访问。在将数据包向上传递到网络堆栈之前,它把Omni-Path头
+从接收的数据包中剥离。它还实现了RDMA netdev控制操作。
+
+OPA VNIC模块实现了独立于硬件的VNIC功能。它由两部分组成。VNIC以太网管理
+代理(VEMA)作为一个IB客户端向IB核心注册,并与IB MAD栈接口。它与以太网
+管理器(EM)和VNIC netdev交换管理信息。VNIC netdev部分分配和释放OPA_VNIC
+RDMA netdev设备。它在需要时覆盖由依赖HW的VNIC驱动设置的net_device_ops函数,
+以适应任何控制操作。它还处理以太网数据包的封装,在传输路径中使用Omni-Path头。
+对于每个VNIC接口,封装所需的信息是由EM通过VEMA MAD接口配置的。它还通过调用
+RDMA netdev控制操作将任何控制信息传递给依赖于HW的驱动程序::
+
+ +-------------------+ +----------------------+
+ | | | Linux |
+ | IB MAD | | 网络 |
+ | | | 栈 |
+ +-------------------+ +----------------------+
+ | | |
+ | | |
+ +----------------------------+ |
+ | | |
+ | OPA VNIC 模块 | |
+ | (OPA VNIC RDMA Netdev | |
+ | & EMA 函数) | |
+ | | |
+ +----------------------------+ |
+ | |
+ | |
+ +------------------+ |
+ | IB 核心 | |
+ +------------------+ |
+ | |
+ | |
+ +--------------------------------------------+
+ | |
+ | HFI1 驱动和 VNIC 支持 |
+ | |
+ +--------------------------------------------+
diff --git a/Documentation/translations/zh_CN/infiniband/sysfs.rst b/Documentation/translations/zh_CN/infiniband/sysfs.rst
new file mode 100644
index 000000000000..e9a48b0b2ba6
--- /dev/null
+++ b/Documentation/translations/zh_CN/infiniband/sysfs.rst
@@ -0,0 +1,21 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/infiniband/sysfs.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 王普宇 Puyu Wang <realpuyuwang@gmail.com>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_infiniband_sysfs:
+
+=========
+Sysfs文件
+=========
+
+sysfs接口已移至
+Documentation/ABI/stable/sysfs-class-infiniband.
diff --git a/Documentation/translations/zh_CN/infiniband/tag_matching.rst b/Documentation/translations/zh_CN/infiniband/tag_matching.rst
new file mode 100644
index 000000000000..19b99587b862
--- /dev/null
+++ b/Documentation/translations/zh_CN/infiniband/tag_matching.rst
@@ -0,0 +1,63 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/infiniband/tag_matching.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 王普宇 Puyu Wang <realpuyuwang@gmail.com>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_infiniband_tag_matching:
+
+============
+标签匹配逻辑
+============
+
+MPI标准定义了一套规则,称为标签匹配,用于将源发送操作与目的接收匹配。以下参数必
+须与以下源和目的参数相匹配:
+
+* 沟通者
+* 用户标签--通配符(wild card)可由接收方指定
+* 来源等级--通配符可由接收方指定
+* 目的地等级 – wild
+
+排序规则要求,当一对以上的发送和接收消息信封可能匹配时,包括最早发布-发送和最早
+发布-接收的一对是必须用来满足匹配操作的一对。然而,这并不意味着标签是按照它们被
+创建的顺序消耗的,例如,如果早期的标签不能用来满足匹配规则,那么后来生成的标签
+可能被消耗。
+
+当消息从发送方发送到接收方时,通信库可能试图在相应的匹配接收被发布之后或之前处
+理该操作。如果匹配的接收被发布,这就是一个预期的消息,否则就被称为一个意外的消
+息。实现时经常为这两种不同的匹配实例使用不同的匹配方案。
+
+为了减少MPI库的内存占用,MPI实现通常使用两种不同的协议来实现这一目的:
+
+1. Eager协议--当发送方处理完发送时,完整的信息就会被发送。在send_cq中会收到
+一个完成发送的通知,通知缓冲区可以被重新使用。
+
+2. Rendezvous协议--发送方在第一次通知接收方时发送标签匹配头,也许还有一部分
+数据。当相应的缓冲区被发布时,响应者将使用头中的信息,直接向匹配的缓冲区发起
+RDMA读取操作。为了使缓冲区得到重用,需要收到一个fin消息。
+
+标签匹配的实现
+==============
+
+使用的匹配对象有两种类型,即发布的接收列表和意外消息列表。应用程序通过调用发布
+的接收列表中的MPI接收例程发布接收缓冲区,并使用MPI发送例程发布发送消息。发布的
+接收列表的头部可以由硬件来维护,而软件则要对这个列表进行跟踪。
+
+当发送开始并到达接收端时,如果没有为这个到达的消息预先发布接收,它将被传递给软
+件并被放在意外(unexpect)消息列表中。否则,将对该匹配进行处理,包括交会处理,
+如果合适的话,将数据传送到指定的接收缓冲区。这允许接收方MPI标签匹配与计算重叠。
+
+当一个接收信息被发布时,通信库将首先检查软件的意外信息列表,以寻找一个匹配的接
+收信息。如果找到一个匹配的,数据就会被送到用户缓冲区,使用一个软件控制的协议。
+UCX的实现根据数据大小,使用急切或交会协议。如果没有找到匹配,整个预置的接收列
+表由硬件维护,并且有空间在这个列表中增加一个预置的接收,这个接收被传递给硬件。
+软件要对这个列表进行跟踪,以帮助处理MPI取消操作。此外,由于硬件和软件在标签匹
+配操作方面预计不会紧密同步,这个影子列表被用来检测预先发布的接收被传递到硬件的
+情况,因为匹配的意外消息正在从硬件传递到软件。
diff --git a/Documentation/translations/zh_CN/infiniband/user_mad.rst b/Documentation/translations/zh_CN/infiniband/user_mad.rst
new file mode 100644
index 000000000000..d9ab2edfb559
--- /dev/null
+++ b/Documentation/translations/zh_CN/infiniband/user_mad.rst
@@ -0,0 +1,164 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/infiniband/user_mad.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 王普宇 Puyu Wang <realpuyuwang@gmail.com>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_infiniband_user_mad:
+
+===============
+用户空间MAD访问
+===============
+
+设备文件
+========
+
+ 每个InfiniBand设备的每个端口都有一个“umad”设备和一个“issm”设备连接。
+ 例如,一个双端口的HCA将有两个umad设备和两个issm设备,而一个交换机将
+ 有每个类型的一个设备(对于交换机端口0)。
+
+创建MAD代理
+===========
+
+ 一个MAD代理可以通过填写一个结构体ib_user_mad_reg_req来创建,然后在
+ 适当的设备文件的文件描述符上调用IB_USER_MAD_REGISTER_AGENT ioctl。
+ 如果注册请求成功,结构体中会返回一个32位的ID。比如说::
+
+ struct ib_user_mad_reg_req req = { /* ... */ };
+ ret = ioctl(fd, IB_USER_MAD_REGISTER_AGENT, (char *) &req);
+ if (!ret)
+ my_agent = req.id;
+ else
+ perror("agent register");
+
+ 代理可以通过IB_USER_MAD_UNREGISTER_AGENT ioctl取消注册。另外,所有
+ 通过文件描述符注册的代理在描述符关闭时将被取消注册。
+
+ 2014
+ 现在提供了一个新的注册IOctl,允许在注册时提供额外的字段。这个注册
+ 调用的用户隐含了对pkey_index的使用(见下文)。现在提供了一个新的
+ 注册IOctl,允许在注册时提供额外的字段。这个注册调用的用户隐含了对
+ pkey_index的使用(见下文)。
+
+接收MADs
+========
+
+ 使用read()接收MAD。现在接收端支持RMPP。传给read()的缓冲区必须至少是
+ 一个struct ib_user_mad + 256字节。比如说:
+
+ 如果传递的缓冲区不足以容纳收到的MAD(RMPP),errno被设置为ENOSPC,需
+ 要的缓冲区长度被设置在mad.length中。
+
+ 正常MAD(非RMPP)的读取示例::
+
+ struct ib_user_mad *mad;
+ mad = malloc(sizeof *mad + 256);
+ ret = read(fd, mad, sizeof *mad + 256);
+ if (ret != sizeof mad + 256) {
+ perror("read");
+ free(mad);
+ }
+
+ RMPP读取示例::
+
+ struct ib_user_mad *mad;
+ mad = malloc(sizeof *mad + 256);
+ ret = read(fd, mad, sizeof *mad + 256);
+ if (ret == -ENOSPC)) {
+ length = mad.length;
+ free(mad);
+ mad = malloc(sizeof *mad + length);
+ ret = read(fd, mad, sizeof *mad + length);
+ }
+ if (ret < 0) {
+ perror("read");
+ free(mad);
+ }
+
+ 除了实际的MAD内容外,其他结构体ib_user_mad字段将被填入收到的MAD的信
+ 息。例如,远程LID将在mad.lid中。
+
+ 如果发送超时,将产生一个接收,mad.status设置为ETIMEDOUT。否则,当一个
+ MAD被成功接收后,mad.status将是0。
+
+ poll()/select()可以用来等待一个MAD可以被读取。
+
+ poll()/select()可以用来等待,直到可以读取一个MAD。
+
+发送MADs
+========
+
+ MADs是用write()发送的。发送的代理ID应该填入MAD的id字段,目的地LID应该
+ 填入lid字段,以此类推。发送端确实支持RMPP,所以可以发送任意长度的MAD。
+ 比如说::
+
+ struct ib_user_mad *mad;
+
+ mad = malloc(sizeof *mad + mad_length);
+
+ /* fill in mad->data */
+
+ mad->hdr.id = my_agent; /* req.id from agent registration */
+ mad->hdr.lid = my_dest; /* in network byte order... */
+ /* etc. */
+
+ ret = write(fd, &mad, sizeof *mad + mad_length);
+ if (ret != sizeof *mad + mad_length)
+ perror("write");
+
+交换IDs
+=======
+
+ umad设备的用户可以在发送的MAD中使用交换ID字段的低32位(也就是网络字节顺序中
+ 最小有效的一半字段)来匹配请求/响应对。上面的32位是保留给内核使用的,在发送
+ MAD之前会被改写。
+
+P_Key索引处理
+=============
+
+ 旧的ib_umad接口不允许为发送的MAD设置P_Key索引,也没有提供获取接收的MAD的
+ P_Key索引的方法。一个带有pkey_index成员的struct ib_user_mad_hdr的新布局已
+ 经被定义;然而,为了保持与旧的应用程序的二进制兼容性,除非在文件描述符被用于
+ 其他用途之前调用IB_USER_MAD_ENABLE_PKEY或IB_USER_MAD_REGISTER_AGENT2 ioctl
+ 之一,否则不会使用这种新布局。
+
+ 在2008年9月,IB_USER_MAD_ABI_VERSION将被增加到6,默认使用新的ib_user_mad_hdr
+ 结构布局,并且IB_USER_MAD_ENABLE_PKEY ioctl将被删除。
+
+设置IsSM功能位
+==============
+
+ 要为一个端口设置IsSM功能位,只需打开相应的issm设备文件。如果IsSM位已经被设置,那
+ 么打开调用将阻塞,直到该位被清除(或者如果O_NONBLOCK标志被传递给open(),则立即返
+ 回,errno设置为EAGAIN)。当issm文件被关闭时,IsSM位将被清除。在issm文件上不能进
+ 行任何读、写或其他操作。
+
+/dev文件
+========
+
+为了用 udev自动创建相应的字符设备文件,一个类似::
+
+ KERNEL=="umad*", NAME="infiniband/%k"
+ KERNEL=="issm*", NAME="infiniband/%k"
+
+ 的规则可以被使用。它将创建节点的名字::
+
+ /dev/infiniband/umad0
+ /dev/infiniband/issm0
+
+ 为第一个端口,以此类推。与这些设备相关的infiniband设备和端口可以从以下文件中确定::
+
+ /sys/class/infiniband_mad/umad0/ibdev
+ /sys/class/infiniband_mad/umad0/port
+
+ 和::
+
+ /sys/class/infiniband_mad/issm0/ibdev
+ /sys/class/infiniband_mad/issm0/port
diff --git a/Documentation/translations/zh_CN/infiniband/user_verbs.rst b/Documentation/translations/zh_CN/infiniband/user_verbs.rst
new file mode 100644
index 000000000000..970bc1a4e396
--- /dev/null
+++ b/Documentation/translations/zh_CN/infiniband/user_verbs.rst
@@ -0,0 +1,72 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/infiniband/user_verbs.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 王普宇 Puyu Wang <realpuyuwang@gmail.com>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_infiniband_user_verbs:
+
+=================
+用户空间verbs访问
+=================
+
+ ib_uverbs模块,通过启用CONFIG_INFINIBAND_USER_VERBS构建,使用户空间
+ 通过“verbs”直接访问IB硬件,如InfiniBand架构规范第11章所述。
+
+ 要使用verbs,需要libibverbs库,可从https://github.com/linux-rdma/rdma-core。
+ libibverbs包含一个独立于设备的API,用于使用ib_uverbs接口。libibverbs
+ 还需要为你的InfiniBand硬件提供适当的独立于设备的内核和用户空间驱动。例如,
+ 要使用Mellanox HCA,你需要安装ib_mthca内核模块和libmthca用户空间驱动。
+
+用户-内核通信
+=============
+
+ 用户空间通过/dev/infiniband/uverbsN字符设备与内核进行慢速路径、资源管理
+ 操作的通信。快速路径操作通常是通过直接写入硬件寄存器mmap()到用户空间来完成
+ 的,没有系统调用或上下文切换到内核。
+
+ 命令是通过在这些设备文件上的write()s发送给内核的。ABI在
+ drivers/infiniband/include/ib_user_verbs.h中定义。需要内核响应的命令的结
+ 构包含一个64位字段,用来传递一个指向输出缓冲区的指针。状态作为write()系统调
+ 用的返回值被返回到用户空间。
+
+资源管理
+========
+
+ 由于所有IB资源的创建和销毁都是通过文件描述符传递的命令完成的,所以内核可以跟
+ 踪那些被附加到给定用户空间上下文的资源。ib_uverbs模块维护着idr表,用来在
+ 内核指针和不透明的用户空间句柄之间进行转换,这样内核指针就不会暴露给用户空间,
+ 而用户空间也无法欺骗内核去跟踪一个假的指针。
+
+ 这也允许内核在一个进程退出时进行清理,并防止一个进程触及另一个进程的资源。
+
+内存固定
+========
+
+ 直接的用户空间I/O要求与作为潜在I/O目标的内存区域保持在同一物理地址上。ib_uverbs
+ 模块通过get_user_pages()和put_page()调用来管理内存区域的固定和解除固定。它还核
+ 算进程的pinned_vm中被固定的内存量,并检查非特权进程是否超过其RLIMIT_MEMLOCK限制。
+
+ 被多次固定的页面在每次被固定时都会被计数,所以pinned_vm的值可能会高估一个进程所
+ 固定的页面数量。
+
+/dev文件
+========
+
+ 要想用udev自动创建适当的字符设备文件,可以采用如下规则::
+
+ KERNEL=="uverbs*", NAME="infiniband/%k"
+
+ 可以使用。 这将创建设备节点,名为::
+
+ /dev/infiniband/uverbs0
+
+ 等等。由于InfiniBand的用户空间verbs对于非特权进程来说应该是安全的,因此在udev规
+ 则中加入适当的MODE或GROUP可能是有用的。
diff --git a/Documentation/translations/zh_CN/process/coding-style.rst b/Documentation/translations/zh_CN/process/coding-style.rst
index b8c484a84d10..638d714bec83 100644
--- a/Documentation/translations/zh_CN/process/coding-style.rst
+++ b/Documentation/translations/zh_CN/process/coding-style.rst
@@ -268,8 +268,7 @@ C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字
``count_active_users()`` 或者类似的名字,你不应该叫它 ``cntuser()`` 。
在函数名中包含函数类型 (所谓的匈牙利命名法) 是脑子出了问题——编译器知道那些类
-型而且能够检查那些类型,这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题
-的程序。
+型而且能够检查那些类型,这样做只能把程序员弄糊涂了。
本地变量名应该简短,而且能够表达相关的含义。如果你有一些随机的整数型的循环计
数器,它应该被称为 ``i`` 。叫它 ``loop_counter`` 并无益处,如果它没有被误解的
diff --git a/Documentation/translations/zh_CN/virt/acrn/cpuid.rst b/Documentation/translations/zh_CN/virt/acrn/cpuid.rst
new file mode 100644
index 000000000000..6f7be545611b
--- /dev/null
+++ b/Documentation/translations/zh_CN/virt/acrn/cpuid.rst
@@ -0,0 +1,56 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/virt/acrn/cpuid.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_virt_acrn_cpuid:
+
+==============
+ACRN CPUID位域
+==============
+
+在ACRN超级管理器上运行的客户虚拟机可以使用CPUID检查其一些功能。
+
+ACRN的cpuid函数是:
+
+函数: 0x40000000
+
+返回::
+
+ eax = 0x40000010
+ ebx = 0x4e524341
+ ecx = 0x4e524341
+ edx = 0x4e524341
+
+注意,ebx,ecx和edx中的这个值对应于字符串“ACRNACRNACRN”。eax中的值对应于这个叶子
+中存在的最大cpuid函数,如果将来有更多的函数加入,将被更新。
+
+函数: define ACRN_CPUID_FEATURES (0x40000001)
+
+返回::
+
+ ebx, ecx, edx
+ eax = an OR'ed group of (1 << flag)
+
+其中 ``flag`` 的定义如下:
+
+================================= =========== ================================
+标志 值 描述
+================================= =========== ================================
+ACRN_FEATURE_PRIVILEGED_VM 0 客户虚拟机是一个有特权的虚拟机
+================================= =========== ================================
+
+函数: 0x40000010
+
+返回::
+
+ ebx, ecx, edx
+ eax = (Virtual) TSC frequency in kHz.
diff --git a/Documentation/translations/zh_CN/virt/acrn/index.rst b/Documentation/translations/zh_CN/virt/acrn/index.rst
new file mode 100644
index 000000000000..34605d87f103
--- /dev/null
+++ b/Documentation/translations/zh_CN/virt/acrn/index.rst
@@ -0,0 +1,25 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/virt/acrn/index.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_virt_acrn_index:
+
+==============
+ACRN超级管理器
+==============
+
+.. toctree::
+ :maxdepth: 1
+
+ introduction
+ io-request
+ cpuid
diff --git a/Documentation/translations/zh_CN/virt/acrn/introduction.rst b/Documentation/translations/zh_CN/virt/acrn/introduction.rst
new file mode 100644
index 000000000000..7182415cb087
--- /dev/null
+++ b/Documentation/translations/zh_CN/virt/acrn/introduction.rst
@@ -0,0 +1,52 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/virt/acrn/introduction.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_virt_acrn_introduction:
+
+ACRN超级管理器介绍
+==================
+
+ACRN超级管理器是一个第一类超级管理器,直接在裸机硬件上运行。它有一个特权管理虚拟机,称为服
+务虚拟机,用于管理用户虚拟机和进行I/O仿真。
+
+ACRN用户空间是一个运行在服务虚拟机中的应用程序,它根据命令行配置为用户虚拟机仿真设备。
+ACRN管理程序服务模块(HSM)是服务虚拟机中的一个内核模块,为ACRN用户空间提供管理程序服
+务。
+
+下图展示了该架构。
+
+::
+
+ 服务端VM 用户端VM
+ +----------------------------+ | +------------------+
+ | +--------------+ | | | |
+ | |ACRN用户空间 | | | | |
+ | +--------------+ | | | |
+ |-----------------ioctl------| | | | ...
+ |内核空间 +----------+ | | | |
+ | | HSM | | | | 驱动 |
+ | +----------+ | | | |
+ +--------------------|-------+ | +------------------+
+ +---------------------hypercall----------------------------------------+
+ | ACRN超级管理器 |
+ +----------------------------------------------------------------------+
+ | 硬件 |
+ +----------------------------------------------------------------------+
+
+ACRN用户空间为用户虚拟机分配内存,配置和初始化用户虚拟机使用的设备,加载虚拟引导程序,
+初始化虚拟CPU状态,处理来自用户虚拟机的I/O请求访问。它使用ioctls来与HSM通信。HSM通过
+与ACRN超级管理器的hypercalls进行交互来实现管理服务。HSM向用户空间输出一个char设备接口
+(/dev/acrn_hsm)。
+
+ACRN超级管理器是开源的,任何人都可以贡献。源码库在
+https://github.com/projectacrn/acrn-hypervisor。
diff --git a/Documentation/translations/zh_CN/virt/acrn/io-request.rst b/Documentation/translations/zh_CN/virt/acrn/io-request.rst
new file mode 100644
index 000000000000..4b4e7186d9a5
--- /dev/null
+++ b/Documentation/translations/zh_CN/virt/acrn/io-request.rst
@@ -0,0 +1,99 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/virt/acrn/io-request.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_virt_acrn_io-request:
+
+I/O请求处理
+===========
+
+客户虚拟机的I/O请求由超级管理器构建,由ACRN超级管理器服务模块分发到与I/O请求的地址范
+围相对应的I/O客户端。I/O请求处理的细节将在以下章节描述。
+
+1. I/O请求
+----------
+
+对于每个客户虚拟机,有一个共享的4KB字节的内存区域,用于超级管理器和服务虚拟机之间的
+I/O请求通信。一个I/O请求是一个256字节的结构体缓冲区,它是 "acrn_io_request" 结构
+体,当客户虚拟机中发生被困的I/O访问时,由超级管理器的I/O处理器填充。服务虚拟机中的
+ACRN用户空间首先分配一个4KB字节的页面,并将缓冲区的GPA(客户物理地址)传递给管理平
+台。缓冲区被用作16个I/O请求槽的数组,每个I/O请求槽为256字节。这个数组是按vCPU ID
+索引的。
+
+2. I/O客户端
+------------
+
+一个I/O客户端负责处理客户虚拟机的I/O请求,其访问的GPA在一定范围内。每个客户虚拟机
+可以关联多个I/O客户端。每个客户虚拟机都有一个特殊的客户端,称为默认客户端,负责处理
+所有不在其他客户端范围内的I/O请求。ACRN用户空间充当每个客户虚拟机的默认客户端。
+
+下面的图示显示了I/O请求共享缓冲区、I/O请求和I/O客户端之间的关系。
+
+::
+
+ +------------------------------------------------------+
+ | 服务VM |
+ |+--------------------------------------------------+ |
+ || +----------------------------------------+ | |
+ || | 共享页 ACRN用户空间 | | |
+ || | +-----------------+ +------------+ | | |
+ || +----+->| acrn_io_request |<-+ 默认 | | | |
+ || | | | +-----------------+ | I/O客户端 | | | |
+ || | | | | ... | +------------+ | | |
+ || | | | +-----------------+ | | |
+ || | +-|--------------------------------------+ | |
+ ||---|----|-----------------------------------------| |
+ || | | 内核 | |
+ || | | +----------------------+ | |
+ || | | | +-------------+ HSM | | |
+ || | +--------------+ | | | |
+ || | | | I/O客户端 | | | |
+ || | | | | | | |
+ || | | +-------------+ | | |
+ || | +----------------------+ | |
+ |+---|----------------------------------------------+ |
+ +----|-------------------------------------------------+
+ |
+ +----|-------------------------------------------------+
+ | +-+-----------+ |
+ | | I/O处理 | ACRN超级管理器 |
+ | +-------------+ |
+ +------------------------------------------------------+
+
+3. I/O请求状态转换
+------------------
+
+一个ACRN I/O请求的状态转换如下。
+
+::
+
+ FREE -> PENDING -> PROCESSING -> COMPLETE -> FREE -> ...
+
+- FREE: 这个I/O请求槽是空的
+- PENDING: 在这个槽位上有一个有效的I/O请求正在等待
+- PROCESSING: 正在处理I/O请求
+- COMPLETE: 该I/O请求已被处理
+
+处于COMPLETE或FREE状态的I/O请求是由超级管理器拥有的。HSM和ACRN用户空间负责处理其
+他的。
+
+4. I/O请求的处理流程
+--------------------
+
+a. 当客户虚拟机中发生被陷入的I/O访问时,超级管理器的I/O处理程序将把I/O请求填充为
+ PENDING状态。
+b. 超级管理器向服务虚拟机发出一个向上调用,这是一个通知中断。
+c. upcall处理程序会安排一个工作者来调度I/O请求。
+d. 工作者寻找PENDING I/O请求,根据I/O访问的地址将其分配给不同的注册客户,将其
+ 状态更新为PROCESSING,并通知相应的客户进行处理。
+e. 被通知的客户端处理指定的I/O请求。
+f. HSM将I/O请求状态更新为COMPLETE,并通过hypercalls通知超级管理器完成。
diff --git a/Documentation/translations/zh_CN/virt/guest-halt-polling.rst b/Documentation/translations/zh_CN/virt/guest-halt-polling.rst
new file mode 100644
index 000000000000..b798d1cf0b48
--- /dev/null
+++ b/Documentation/translations/zh_CN/virt/guest-halt-polling.rst
@@ -0,0 +1,87 @@
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/virt/guest-halt-polling.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_virt_guest-halt-polling:
+
+========================================
+客户机停机轮询机制(Guest halt polling)
+========================================
+
+cpuidle_haltpoll驱动,与haltpoll管理器一起,允许客户机vcpus在停机前轮询
+一定的时间。
+
+这为物理机侧的轮询提供了以下好处:
+
+ 1) 在执行轮询时,POLL标志被设置,这允许远程vCPU在执行唤醒时避免发送
+ IPI(以及处理IPI的相关成本)。
+
+ 2) 可以避免虚拟机退出的成本。
+
+客户机侧轮询的缺点是,即使在物理机中的其他可运行任务中也会进行轮询。
+
+其基本逻辑如下。一个全局值,即guest_halt_poll_ns,是由用户配置的,表示允
+许轮询的最大时间量。这个值是固定的。
+
+每个vcpu都有一个可调整的guest_halt_poll_ns("per-cpu guest_halt_poll_ns"),
+它由算法响应事件进行调整(解释如下)。
+
+模块参数
+========
+
+haltpoll管理器有5个可调整的模块参数:
+
+1) guest_halt_poll_ns:
+
+轮询停机前执行的最大时间,以纳秒为单位。
+
+默认值: 200000
+
+2) guest_halt_poll_shrink:
+
+当唤醒事件发生在全局的guest_halt_poll_ns之后,用于缩减每个CPU的guest_halt_poll_ns
+的划分系数。
+
+默认值: 2
+
+3) guest_halt_poll_grow:
+
+当事件发生在per-cpu guest_halt_poll_ns之后但在global guest_halt_poll_ns之前,
+用于增长per-cpu guest_halt_poll_ns的乘法系数。
+
+默认值: 2
+
+4) guest_halt_poll_grow_start:
+
+在系统空闲的情况下,每个cpu guest_halt_poll_ns最终达到零。这个值设置了增长时的
+初始每cpu guest_halt_poll_ns。这个值可以从10000开始增加,以避免在最初的增长阶
+段出现失误。:
+
+10k, 20k, 40k, ... (例如,假设guest_halt_poll_grow=2).
+
+默认值: 50000
+
+5) guest_halt_poll_allow_shrink:
+
+允许缩减的Bool参数。设置为N以避免它(一旦达到全局的guest_halt_poll_ns值,每CPU的
+guest_halt_poll_ns将保持高位)。
+
+默认值: Y
+
+模块参数可以从Debugfs文件中设置,在::
+
+ /sys/module/haltpoll/parameters/
+
+进一步说明
+==========
+
+- 在设置guest_halt_poll_ns参数时应该小心,因为一个大的值有可能使几乎是完全空闲机
+ 器上的cpu使用率达到100%。
diff --git a/Documentation/translations/zh_CN/virt/index.rst b/Documentation/translations/zh_CN/virt/index.rst
new file mode 100644
index 000000000000..f8dd13681341
--- /dev/null
+++ b/Documentation/translations/zh_CN/virt/index.rst
@@ -0,0 +1,38 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/virt/index.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_virt_index:
+
+===============
+Linux虚拟化支持
+===============
+
+.. toctree::
+ :maxdepth: 2
+
+ paravirt_ops
+ guest-halt-polling
+ ne_overview
+ acrn/index
+
+TODOLIST:
+
+ kvm/index
+ uml/user_mode_linux_howto_v2
+
+.. only:: html and subproject
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/virt/ne_overview.rst b/Documentation/translations/zh_CN/virt/ne_overview.rst
new file mode 100644
index 000000000000..2455b371abea
--- /dev/null
+++ b/Documentation/translations/zh_CN/virt/ne_overview.rst
@@ -0,0 +1,88 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/virt/ne_overview.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_virt_ne_overview:
+
+==============
+Nitro Enclaves
+==============
+
+概述
+====
+
+Nitro Enclaves(NE)是亚马逊弹性计算云(EC2)的一项新功能,允许客户在EC2实
+例中划分出孤立的计算环境[1]。
+
+例如,一个处理敏感数据并在虚拟机中运行的应用程序,可以与在同一虚拟机中运行的
+其他应用程序分开。然后,这个应用程序在一个独立于主虚拟机的虚拟机中运行,即
+enclave。
+
+一个enclave与催生它的虚拟机一起运行。这种设置符合低延迟应用的需要。为enclave
+分配的资源,如内存和CPU,是从主虚拟机中分割出来的。每个enclave都被映射到一
+个运行在主虚拟机中的进程,该进程通过一个ioctl接口与NE驱动进行通信。
+
+在这个意义上,有两个组成部分。
+
+1. 一个enclave抽象进程——一个运行在主虚拟机客体中的用户空间进程,它使用NE驱动
+提供的ioctl接口来生成一个enclave虚拟机(这就是下面的2)。
+
+有一个NE模拟的PCI设备暴露给主虚拟机。这个新的PCI设备的驱动被包含在NE驱动中。
+
+ioctl逻辑被映射到PCI设备命令,例如,NE_START_ENCLAVE ioctl映射到一个enclave
+启动PCI命令。然后,PCI设备命令被翻译成在管理程序方面采取的行动;也就是在运
+行主虚拟机的主机上运行的Nitro管理程序。Nitro管理程序是基于KVM核心技术的。
+
+2. enclave本身——一个运行在与催生它的主虚拟机相同的主机上的虚拟机。内存和CPU
+从主虚拟机中分割出来,专门用于enclave虚拟机。enclave没有连接持久性存储。
+
+从主虚拟机中分割出来并给enclave的内存区域需要对齐2 MiB/1 GiB物理连续的内存
+区域(或这个大小的倍数,如8 MiB)。该内存可以通过使用hugetlbfs从用户空间分
+配[2][3]。一个enclave的内存大小需要至少64 MiB。enclave内存和CPU需要来自同
+一个NUMA节点。
+
+一个enclave在专用的核心上运行。CPU 0及其同级别的CPU需要保持对主虚拟机的可用
+性。CPU池必须由具有管理能力的用户为NE目的进行设置。关于CPU池的格式,请看内核
+文档[4]中的cpu list部分。
+
+enclave通过本地通信通道与主虚拟机进行通信,使用virtio-vsock[5]。主虚拟机有
+virtio-pci vsock模拟设备,而飞地虚拟机有virtio-mmio vsock模拟设备。vsock
+设备使用eventfd作为信令。enclave虚拟机看到通常的接口——本地APIC和IOAPIC——从
+virtio-vsock设备获得中断。virtio-mmio设备被放置在典型的4 GiB以下的内存中。
+
+在enclave中运行的应用程序需要和将在enclave虚拟机中运行的操作系统(如内核、
+ramdisk、init)一起被打包到enclave镜像中。enclave虚拟机有自己的内核并遵循标
+准的Linux启动协议[6]。
+
+内核bzImage、内核命令行、ramdisk(s)是enclave镜像格式(EIF)的一部分;另外
+还有一个EIF头,包括元数据,如magic number、eif版本、镜像大小和CRC。
+
+哈希值是为整个enclave镜像(EIF)、内核和ramdisk(s)计算的。例如,这被用来检
+查在enclave虚拟机中加载的enclave镜像是否是打算运行的那个。
+
+这些加密测量包括在由Nitro超级管理器成的签名证明文件中,并进一步用来证明enclave
+的身份;KMS是NE集成的服务的一个例子,它检查证明文件。
+
+enclave镜像(EIF)被加载到enclave内存中,偏移量为8 MiB。enclave中的初始进程
+连接到主虚拟机的vsock CID和一个预定义的端口--9000,以发送一个心跳值--0xb7。这
+个机制用于在主虚拟机中检查enclave是否已经启动。主虚拟机的CID是3。
+
+如果enclave虚拟机崩溃或优雅地退出,NE驱动会收到一个中断事件。这个事件会通过轮询
+通知机制进一步发送到运行在主虚拟机中的用户空间enclave进程。然后,用户空间enclave
+进程就可以退出了。
+
+[1] https://aws.amazon.com/ec2/nitro/nitro-enclaves/
+[2] https://www.kernel.org/doc/html/latest/admin-guide/mm/hugetlbpage.html
+[3] https://lwn.net/Articles/807108/
+[4] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
+[5] https://man7.org/linux/man-pages/man7/vsock.7.html
+[6] https://www.kernel.org/doc/html/latest/x86/boot.html
diff --git a/Documentation/translations/zh_CN/virt/paravirt_ops.rst b/Documentation/translations/zh_CN/virt/paravirt_ops.rst
new file mode 100644
index 000000000000..06b122bc915d
--- /dev/null
+++ b/Documentation/translations/zh_CN/virt/paravirt_ops.rst
@@ -0,0 +1,41 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/virt/paravirt_ops.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+ 陈飞杨 Feiyang Chen <chenfeiyang@loongson.cn>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+.. _cn_virt_paravirt_ops:
+
+============
+半虚拟化操作
+============
+
+Linux提供了对不同管理程序虚拟化技术的支持。历史上,为了支持不同的虚拟机超级管理器
+(hypervisor,下文简称超级管理器),需要不同的二进制内核,这个限制已经被pv_ops移
+除了。Linux pv_ops是一个虚拟化API,它能够支持不同的管理程序。它允许每个管理程序
+优先于关键操作,并允许单一的内核二进制文件在所有支持的执行环境中运行,包括本机——没
+有任何管理程序。
+
+pv_ops提供了一组函数指针,代表了与低级关键指令和各领域高级功能相对应的操作。
+pv-ops允许在运行时进行优化,在启动时对低级关键操作进行二进制修补。
+
+pv_ops操作被分为三类:
+
+- 简单的间接调用
+ 这些操作对应于高水平的函数,众所周知,间接调用的开销并不十分重要。
+
+- 间接调用,允许用二进制补丁进行优化
+ 通常情况下,这些操作对应于低级别的关键指令。它们被频繁地调用,并且是对性能关
+ 键。开销是非常重要的。
+
+- 一套用于手写汇编代码的宏程序
+ 手写的汇编代码(.S文件)也需要半虚拟化,因为它们包括敏感指令或其中的一些代
+ 码路径对性能非常关键。
diff --git a/Documentation/translations/zh_TW/IRQ.txt b/Documentation/translations/zh_TW/IRQ.txt
new file mode 100644
index 000000000000..73d435a0d1e7
--- /dev/null
+++ b/Documentation/translations/zh_TW/IRQ.txt
@@ -0,0 +1,41 @@
+Chinese translated version of Documentation/core-api/irq/index.rst
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Eric W. Biederman <ebiederman@xmission.com>
+Traditional Chinese maintainer: Hu Haowen <src.res@email.cn>
+---------------------------------------------------------------------
+Documentation/core-api/irq/index.rst 的繁體中文翻譯
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或
+者翻譯存在問題,請聯繫繁體中文版維護者。
+
+英文版維護者: Eric W. Biederman <ebiederman@xmission.com>
+繁體中文版維護者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版翻譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版校譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+
+
+以下爲正文
+---------------------------------------------------------------------
+何爲 IRQ?
+
+一個 IRQ 是來自某個設備的一個中斷請求。目前,它們可以來自一個硬體引腳,
+或來自一個數據包。多個設備可能連接到同個硬體引腳,從而共享一個 IRQ。
+
+一個 IRQ 編號是用於告知硬體中斷源的內核標識。通常情況下,這是一個
+全局 irq_desc 數組的索引,但是除了在 linux/interrupt.h 中的實現,
+具體的細節是體系結構特定的。
+
+一個 IRQ 編號是設備上某個可能的中斷源的枚舉。通常情況下,枚舉的編號是
+該引腳在系統內中斷控制器的所有輸入引腳中的編號。對於 ISA 總線中的情況,
+枚舉的是在兩個 i8259 中斷控制器中 16 個輸入引腳。
+
+架構可以對 IRQ 編號指定額外的含義,在硬體涉及任何手工配置的情況下,
+是被提倡的。ISA 的 IRQ 是一個分配這類額外含義的典型例子。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/README.rst b/Documentation/translations/zh_TW/admin-guide/README.rst
new file mode 100644
index 000000000000..b752e50359e6
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/README.rst
@@ -0,0 +1,351 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/README.rst
+
+:譯者:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux內核5.x版本 <http://kernel.org/>
+=========================================
+
+以下是Linux版本5的發行註記。仔細閱讀它們,
+它們會告訴你這些都是什麼,解釋如何安裝內核,以及遇到問題時該如何做。
+
+什麼是Linux?
+---------------
+
+ Linux是Unix作業系統的克隆版本,由Linus Torvalds在一個鬆散的網絡黑客
+ (Hacker,無貶義)團隊的幫助下從頭開始編寫。它旨在實現兼容POSIX和
+ 單一UNIX規範。
+
+ 它具有在現代成熟的Unix中應當具有的所有功能,包括真正的多任務處理、虛擬內存、
+ 共享庫、按需加載、共享的寫時拷貝(COW)可執行文件、恰當的內存管理以及包括
+ IPv4和IPv6在內的複合網絡棧。
+
+ Linux在GNU通用公共許可證,版本2(GNU GPLv2)下分發,詳見隨附的COPYING文件。
+
+它能在什麼樣的硬體上運行?
+-----------------------------
+
+ 雖然Linux最初是爲32位的x86 PC機(386或更高版本)開發的,但今天它也能運行在
+ (至少)Compaq Alpha AXP、Sun SPARC與UltraSPARC、Motorola 68000、PowerPC、
+ PowerPC64、ARM、Hitachi SuperH、Cell、IBM S/390、MIPS、HP PA-RISC、Intel
+ IA-64、DEC VAX、AMD x86-64 Xtensa和ARC架構上。
+
+ Linux很容易移植到大多數通用的32位或64位體系架構,只要它們有一個分頁內存管理
+ 單元(PMMU)和一個移植的GNU C編譯器(gcc;GNU Compiler Collection,GCC的一
+ 部分)。Linux也被移植到許多沒有PMMU的體系架構中,儘管功能顯然受到了一定的
+ 限制。
+ Linux也被移植到了其自己上。現在可以將內核作爲用戶空間應用程式運行——這被
+ 稱爲用戶模式Linux(UML)。
+
+文檔
+-----
+網際網路上和書籍上都有大量的電子文檔,既有Linux專屬文檔,也有與一般UNIX問題相關
+的文檔。我建議在任何Linux FTP站點上查找LDP(Linux文檔項目)書籍的文檔子目錄。
+本自述文件並不是關於系統的文檔:有更好的可用資源。
+
+ - 網際網路上和書籍上都有大量的(電子)文檔,既有Linux專屬文檔,也有與普通
+ UNIX問題相關的文檔。我建議在任何有LDP(Linux文檔項目)書籍的Linux FTP
+ 站點上查找文檔子目錄。本自述文件並不是關於系統的文檔:有更好的可用資源。
+
+ - 文檔/子目錄中有各種自述文件:例如,這些文件通常包含一些特定驅動程序的
+ 內核安裝說明。請閱讀
+ :ref:`Documentation/process/changes.rst <changes>` 文件,它包含了升級內核
+ 可能會導致的問題的相關信息。
+
+安裝內核原始碼
+---------------
+
+ - 如果您要安裝完整的原始碼,請把內核tar檔案包放在您有權限的目錄中(例如您
+ 的主目錄)並將其解包::
+
+ xz -cd linux-5.x.tar.xz | tar xvf -
+
+ 將「X」替換成最新內核的版本號。
+
+ 【不要】使用 /usr/src/linux 目錄!這裡有一組庫頭文件使用的內核頭文件
+ (通常是不完整的)。它們應該與庫匹配,而不是被內核的變化搞得一團糟。
+
+ - 您還可以通過打補丁在5.x版本之間升級。補丁以xz格式分發。要通過打補丁進行
+ 安裝,請獲取所有較新的補丁文件,進入內核原始碼(linux-5.x)的目錄並
+ 執行::
+
+ xz -cd ../patch-5.x.xz | patch -p1
+
+ 請【按順序】替換所有大於當前原始碼樹版本的「x」,這樣就可以了。您可能想要
+ 刪除備份文件(文件名類似xxx~ 或 xxx.orig),並確保沒有失敗的補丁(文件名
+ 類似xxx# 或 xxx.rej)。如果有,不是你就是我犯了錯誤。
+
+ 與5.x內核的補丁不同,5.x.y內核(也稱爲穩定版內核)的補丁不是增量的,而是
+ 直接應用於基本的5.x內核。例如,如果您的基本內核是5.0,並且希望應用5.0.3
+ 補丁,則不應先應用5.0.1和5.0.2的補丁。類似地,如果您運行的是5.0.2內核,
+ 並且希望跳轉到5.0.3,那麼在應用5.0.3補丁之前,必須首先撤銷5.0.2補丁
+ (即patch -R)。更多關於這方面的內容,請閱讀
+ :ref:`Documentation/process/applying-patches.rst <applying_patches>` 。
+
+ 或者,腳本 patch-kernel 可以用來自動化這個過程。它能確定當前內核版本並
+ 應用找到的所有補丁::
+
+ linux/scripts/patch-kernel linux
+
+ 上面命令中的第一個參數是內核原始碼的位置。補丁是在當前目錄應用的,但是
+ 可以將另一個目錄指定爲第二個參數。
+
+ - 確保沒有過時的 .o 文件和依賴項::
+
+ cd linux
+ make mrproper
+
+ 現在您應該已經正確安裝了原始碼。
+
+軟體要求
+---------
+
+ 編譯和運行5.x內核需要各種軟體包的最新版本。請參考
+ :ref:`Documentation/process/changes.rst <changes>`
+ 來了解最低版本要求以及如何升級軟體包。請注意,使用過舊版本的這些包可能會
+ 導致很難追蹤的間接錯誤,因此不要以爲在生成或操作過程中出現明顯問題時可以
+ 只更新包。
+
+爲內核建立目錄
+---------------
+
+ 編譯內核時,默認情況下所有輸出文件都將與內核原始碼放在一起。使用
+ ``make O=output/dir`` 選項可以爲輸出文件(包括 .config)指定備用位置。
+ 例如::
+
+ kernel source code: /usr/src/linux-5.x
+ build directory: /home/name/build/kernel
+
+ 要配置和構建內核,請使用::
+
+ cd /usr/src/linux-5.x
+ make O=/home/name/build/kernel menuconfig
+ make O=/home/name/build/kernel
+ sudo make O=/home/name/build/kernel modules_install install
+
+ 請注意:如果使用了 ``O=output/dir`` 選項,那麼它必須用於make的所有調用。
+
+配置內核
+---------
+
+ 即使只升級一個小版本,也不要跳過此步驟。每個版本中都會添加新的配置選項,
+ 如果配置文件沒有按預定設置,就會出現奇怪的問題。如果您想以最少的工作量
+ 將現有配置升級到新版本,請使用 ``makeoldconfig`` ,它只會詢問您新配置
+ 選項的答案。
+
+ - 其他配置命令包括::
+
+ "make config" 純文本界面。
+
+ "make menuconfig" 基於文本的彩色菜單、選項列表和對話框。
+
+ "make nconfig" 增強的基於文本的彩色菜單。
+
+ "make xconfig" 基於Qt的配置工具。
+
+ "make gconfig" 基於GTK+的配置工具。
+
+ "make oldconfig" 基於現有的 ./.config 文件選擇所有選項,並詢問
+ 新配置選項。
+
+ "make olddefconfig"
+ 類似上一個,但不詢問直接將新選項設置爲默認值。
+
+ "make defconfig" 根據體系架構,使用arch/$arch/defconfig或
+ arch/$arch/configs/${PLATFORM}_defconfig中的
+ 默認選項值創建./.config文件。
+
+ "make ${PLATFORM}_defconfig"
+ 使用arch/$arch/configs/${PLATFORM}_defconfig中
+ 的默認選項值創建一個./.config文件。
+ 用「makehelp」來獲取您體系架構中所有可用平台的列表。
+
+ "make allyesconfig"
+ 通過儘可能將選項值設置爲「y」,創建一個
+ ./.config文件。
+
+ "make allmodconfig"
+ 通過儘可能將選項值設置爲「m」,創建一個
+ ./.config文件。
+
+ "make allnoconfig" 通過儘可能將選項值設置爲「n」,創建一個
+ ./.config文件。
+
+ "make randconfig" 通過隨機設置選項值來創建./.config文件。
+
+ "make localmodconfig" 基於當前配置和加載的模塊(lsmod)創建配置。禁用
+ 已加載的模塊不需要的任何模塊選項。
+
+ 要爲另一台計算機創建localmodconfig,請將該計算機
+ 的lsmod存儲到一個文件中,並將其作爲lsmod參數傳入。
+
+ 此外,通過在參數LMC_KEEP中指定模塊的路徑,可以將
+ 模塊保留在某些文件夾或kconfig文件中。
+
+ target$ lsmod > /tmp/mylsmod
+ target$ scp /tmp/mylsmod host:/tmp
+
+ host$ make LSMOD=/tmp/mylsmod \
+ LMC_KEEP="drivers/usb:drivers/gpu:fs" \
+ localmodconfig
+
+ 上述方法在交叉編譯時也適用。
+
+ "make localyesconfig" 與localmodconfig類似,只是它會將所有模塊選項轉換
+ 爲內置(=y)。你可以同時通過LMC_KEEP保留模塊。
+
+ "make kvmconfig" 爲kvm客體內核支持啓用其他選項。
+
+ "make xenconfig" 爲xen dom0客體內核支持啓用其他選項。
+
+ "make tinyconfig" 配置儘可能小的內核。
+
+ 更多關於使用Linux內核配置工具的信息,見文檔
+ Documentation/kbuild/kconfig.rst。
+
+ - ``make config`` 注意事項:
+
+ - 包含不必要的驅動程序會使內核變大,並且在某些情況下會導致問題:
+ 探測不存在的控制器卡可能會混淆其他控制器。
+
+ - 如果存在協處理器,則編譯了數學仿真的內核仍將使用協處理器:在
+ 這種情況下,數學仿真永遠不會被使用。內核會稍微大一點,但不管
+ 是否有數學協處理器,都可以在不同的機器上工作。
+
+ - 「kernel hacking」配置細節通常會導致更大或更慢的內核(或兩者
+ 兼而有之),甚至可以通過配置一些例程來主動嘗試破壞壞代碼以發現
+ 內核問題,從而降低內核的穩定性(kmalloc())。因此,您可能應該
+ 用於研究「開發」、「實驗」或「調試」特性相關問題。
+
+編譯內核
+---------
+
+ - 確保您至少有gcc 4.9可用。
+ 有關更多信息,請參閱 :ref:`Documentation/process/changes.rst <changes>` 。
+
+ 請注意,您仍然可以使用此內核運行a.out用戶程序。
+
+ - 執行 ``make`` 來創建壓縮內核映像。如果您安裝了lilo以適配內核makefile,
+ 那麼也可以進行 ``makeinstall`` ,但是您可能需要先檢查特定的lilo設置。
+
+ 實際安裝必須以root身份執行,但任何正常構建都不需要。
+ 無須徒然使用root身份。
+
+ - 如果您將內核的任何部分配置爲模塊,那麼還必須執行 ``make modules_install`` 。
+
+ - 詳細的內核編譯/生成輸出:
+
+ 通常,內核構建系統在相當安靜的模式下運行(但不是完全安靜)。但是有時您或
+ 其他內核開發人員需要看到編譯、連結或其他命令的執行過程。爲此,可使用
+ 「verbose(詳細)」構建模式。
+ 向 ``make`` 命令傳遞 ``V=1`` 來實現,例如::
+
+ make V=1 all
+
+ 如需構建系統也給出內個目標重建的願意,請使用 ``V=2`` 。默認爲 ``V=0`` 。
+
+ - 準備一個備份內核以防出錯。對於開發版本尤其如此,因爲每個新版本都包含
+ 尚未調試的新代碼。也要確保保留與該內核對應的模塊的備份。如果要安裝
+ 與工作內核版本號相同的新內核,請在進行 ``make modules_install`` 安裝
+ 之前備份modules目錄。
+
+ 或者,在編譯之前,使用內核配置選項「LOCALVERSION」向常規內核版本附加
+ 一個唯一的後綴。LOCALVERSION可以在「General Setup」菜單中設置。
+
+ - 爲了引導新內核,您需要將內核映像(例如編譯後的
+ .../linux/arch/x86/boot/bzImage)複製到常規可引導內核的位置。
+
+ - 不再支持在沒有LILO等啓動裝載程序幫助的情況下直接從軟盤引導內核。
+
+ 如果從硬碟引導Linux,很可能使用LILO,它使用/etc/lilo.conf文件中
+ 指定的內核映像文件。內核映像文件通常是/vmlinuz、/boot/vmlinuz、
+ /bzImage或/boot/bzImage。使用新內核前,請保存舊映像的副本,並複製
+ 新映像覆蓋舊映像。然後您【必須重新運行LILO】來更新加載映射!否則,
+ 將無法啓動新的內核映像。
+
+ 重新安裝LILO通常需要運行/sbin/LILO。您可能希望編輯/etc/lilo.conf
+ 文件爲舊內核映像指定一個條目(例如/vmlinux.old)防止新的不能正常
+ 工作。有關更多信息,請參閱LILO文檔。
+
+ 重新安裝LILO之後,您應該就已經準備好了。關閉系統,重新啓動,盡情
+ 享受吧!
+
+ 如果需要更改內核映像中的默認根設備、視頻模式等,請在適當的地方使用
+ 啓動裝載程序的引導選項。無需重新編譯內核即可更改這些參數。
+
+ - 使用新內核重新啓動並享受它吧。
+
+若遇到問題
+-----------
+
+ - 如果您發現了一些可能由於內核缺陷所導致的問題,請檢查MAINTAINERS(維護者)
+ 文件看看是否有人與令您遇到麻煩的內核部分相關。如果無人在此列出,那麼第二
+ 個最好的方案就是把它們發給我(torvalds@linux-foundation.org),也可能發送
+ 到任何其他相關的郵件列表或新聞組。
+
+ - 在所有的缺陷報告中,【請】告訴我們您在說什麼內核,如何復現問題,以及您的
+ 設置是什麼的(使用您的常識)。如果問題是新的,請告訴我;如果問題是舊的,
+ 請嘗試告訴我您什麼時候首次注意到它。
+
+ - 如果缺陷導致如下消息::
+
+ unable to handle kernel paging request at address C0000010
+ Oops: 0002
+ EIP: 0010:XXXXXXXX
+ eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx
+ esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx
+ ds: xxxx es: xxxx fs: xxxx gs: xxxx
+ Pid: xx, process nr: xx
+ xx xx xx xx xx xx xx xx xx xx
+
+ 或者類似的內核調試信息顯示在屏幕上或在系統日誌里,請【如實】複製它。
+ 可能對你來說轉儲(dump)看起來不可理解,但它確實包含可能有助於調試問題的
+ 信息。轉儲上方的文本也很重要:它說明了內核轉儲代碼的原因(在上面的示例中,
+ 是由於內核指針錯誤)。更多關於如何理解轉儲的信息,請參見
+ Documentation/admin-guide/bug-hunting.rst。
+
+ - 如果使用 CONFIG_KALLSYMS 編譯內核,則可以按原樣發送轉儲,否則必須使用
+ ``ksymoops`` 程序來理解轉儲(但通常首選使用CONFIG_KALLSYMS編譯)。
+ 此實用程序可從
+ https://www.kernel.org/pub/linux/utils/kernel/ksymoops/ 下載。
+ 或者,您可以手動執行轉儲查找:
+
+ - 在調試像上面這樣的轉儲時,如果您可以查找EIP值的含義,這將非常有幫助。
+ 十六進位值本身對我或其他任何人都沒有太大幫助:它會取決於特定的內核設置。
+ 您應該做的是從EIP行獲取十六進位值(忽略 ``0010:`` ),然後在內核名字列表
+ 中查找它,以查看哪個內核函數包含有問題的地址。
+
+ 要找到內核函數名,您需要找到與顯示症狀的內核相關聯的系統二進位文件。就是
+ 文件「linux/vmlinux」。要提取名字列表並將其與內核崩潰中的EIP進行匹配,
+ 請執行::
+
+ nm vmlinux | sort | less
+
+ 這將爲您提供一個按升序排序的內核地址列表,從中很容易找到包含有問題的地址
+ 的函數。請注意,內核調試消息提供的地址不一定與函數地址完全匹配(事實上,
+ 這是不可能的),因此您不能只「grep」列表:不過列表將爲您提供每個內核函數
+ 的起點,因此通過查找起始地址低於你正在搜索的地址,但後一個函數的高於的
+ 函數,你會找到您想要的。實際上,在您的問題報告中加入一些「上下文」可能是
+ 一個好主意,給出相關的上下幾行。
+
+ 如果您由於某些原因無法完成上述操作(如您使用預編譯的內核映像或類似的映像),
+ 請儘可能多地告訴我您的相關設置信息,這會有所幫助。有關詳細信息請閱讀
+ 『Documentation/admin-guide/reporting-issues.rst』。
+
+ - 或者,您可以在正在運行的內核上使用gdb(只讀的;即不能更改值或設置斷點)。
+ 爲此,請首先使用-g編譯內核;適當地編輯arch/x86/Makefile,然後執行 ``make
+ clean`` 。您還需要啓用CONFIG_PROC_FS(通過 ``make config`` )。
+
+ 使用新內核重新啓動後,執行 ``gdb vmlinux /proc/kcore`` 。現在可以使用所有
+ 普通的gdb命令。查找系統崩潰點的命令是 ``l *0xXXXXXXXX`` (將xxx替換爲EIP
+ 值)。
+
+ 用gdb無法調試一個當前未運行的內核是由於gdb(錯誤地)忽略了編譯內核的起始
+ 偏移量。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/bug-bisect.rst b/Documentation/translations/zh_TW/admin-guide/bug-bisect.rst
new file mode 100644
index 000000000000..41a39aebb8d6
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/bug-bisect.rst
@@ -0,0 +1,85 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :doc:`../../../admin-guide/bug-bisect`
+
+:譯者:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+二分(bisect)缺陷
++++++++++++++++++++
+
+(英文版)最後更新:2016年10月28日
+
+引言
+=====
+
+始終嘗試由來自kernel.org的原始碼構建的最新內核。如果您沒有信心這樣做,請將
+錯誤報告給您的發行版供應商,而不是內核開發人員。
+
+找到缺陷(bug)並不總是那麼容易,不過仍然得去找。如果你找不到它,不要放棄。
+儘可能多的向相關維護人員報告您發現的信息。請參閱MAINTAINERS文件以了解您所
+關注的子系統的維護人員。
+
+在提交錯誤報告之前,請閱讀「Documentation/admin-guide/reporting-issues.rst」。
+
+設備未出現(Devices not appearing)
+====================================
+
+這通常是由udev/systemd引起的。在將其歸咎於內核之前先檢查一下。
+
+查找導致缺陷的補丁
+===================
+
+使用 ``git`` 提供的工具可以很容易地找到缺陷,只要缺陷是可復現的。
+
+操作步驟:
+
+- 從git原始碼構建內核
+- 以此開始二分 [#f1]_::
+
+ $ git bisect start
+
+- 標記損壞的變更集::
+
+ $ git bisect bad [commit]
+
+- 標記正常工作的變更集::
+
+ $ git bisect good [commit]
+
+- 重新構建內核並測試
+- 使用以下任一與git bisect進行交互::
+
+ $ git bisect good
+
+ 或::
+
+ $ git bisect bad
+
+ 這取決於您測試的變更集上是否有缺陷
+- 在一些交互之後,git bisect將給出可能導致缺陷的變更集。
+
+- 例如,如果您知道當前版本有問題,而4.8版本是正常的,則可以執行以下操作::
+
+ $ git bisect start
+ $ git bisect bad # Current version is bad
+ $ git bisect good v4.8
+
+
+.. [#f1] 您可以(可選地)在開始git bisect的時候提供good或bad參數
+ ``git bisect start [BAD] [GOOD]``
+
+如需進一步參考,請閱讀:
+
+- ``git-bisect`` 的手冊頁
+- `Fighting regressions with git bisect(用git bisect解決回歸)
+ <https://www.kernel.org/pub/software/scm/git/docs/git-bisect-lk2009.html>`_
+- `Fully automated bisecting with "git bisect run"(使用git bisect run
+ 來全自動二分) <https://lwn.net/Articles/317154>`_
+- `Using Git bisect to figure out when brokenness was introduced
+ (使用Git二分來找出何時引入了錯誤) <http://webchick.net/node/99>`_
+
diff --git a/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst b/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst
new file mode 100644
index 000000000000..4d813aec77d2
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst
@@ -0,0 +1,344 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :doc:`../../../admin-guide/bug-hunting`
+
+:譯者:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+追蹤缺陷
+=========
+
+內核錯誤報告通常附帶如下堆棧轉儲::
+
+ ------------[ cut here ]------------
+ WARNING: CPU: 1 PID: 28102 at kernel/module.c:1108 module_put+0x57/0x70
+ Modules linked in: dvb_usb_gp8psk(-) dvb_usb dvb_core nvidia_drm(PO) nvidia_modeset(PO) snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd soundcore nvidia(PO) [last unloaded: rc_core]
+ CPU: 1 PID: 28102 Comm: rmmod Tainted: P WC O 4.8.4-build.1 #1
+ Hardware name: MSI MS-7309/MS-7309, BIOS V1.12 02/23/2009
+ 00000000 c12ba080 00000000 00000000 c103ed6a c1616014 00000001 00006dc6
+ c1615862 00000454 c109e8a7 c109e8a7 00000009 ffffffff 00000000 f13f6a10
+ f5f5a600 c103ee33 00000009 00000000 00000000 c109e8a7 f80ca4d0 c109f617
+ Call Trace:
+ [<c12ba080>] ? dump_stack+0x44/0x64
+ [<c103ed6a>] ? __warn+0xfa/0x120
+ [<c109e8a7>] ? module_put+0x57/0x70
+ [<c109e8a7>] ? module_put+0x57/0x70
+ [<c103ee33>] ? warn_slowpath_null+0x23/0x30
+ [<c109e8a7>] ? module_put+0x57/0x70
+ [<f80ca4d0>] ? gp8psk_fe_set_frontend+0x460/0x460 [dvb_usb_gp8psk]
+ [<c109f617>] ? symbol_put_addr+0x27/0x50
+ [<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
+ [<f80bb3bf>] ? dvb_usb_exit+0x2f/0xd0 [dvb_usb]
+ [<c13d03bc>] ? usb_disable_endpoint+0x7c/0xb0
+ [<f80bb48a>] ? dvb_usb_device_exit+0x2a/0x50 [dvb_usb]
+ [<c13d2882>] ? usb_unbind_interface+0x62/0x250
+ [<c136b514>] ? __pm_runtime_idle+0x44/0x70
+ [<c13620d8>] ? __device_release_driver+0x78/0x120
+ [<c1362907>] ? driver_detach+0x87/0x90
+ [<c1361c48>] ? bus_remove_driver+0x38/0x90
+ [<c13d1c18>] ? usb_deregister+0x58/0xb0
+ [<c109fbb0>] ? SyS_delete_module+0x130/0x1f0
+ [<c1055654>] ? task_work_run+0x64/0x80
+ [<c1000fa5>] ? exit_to_usermode_loop+0x85/0x90
+ [<c10013f0>] ? do_fast_syscall_32+0x80/0x130
+ [<c1549f43>] ? sysenter_past_esp+0x40/0x6a
+ ---[ end trace 6ebc60ef3981792f ]---
+
+這樣的堆棧跟蹤提供了足夠的信息來識別內核原始碼中發生錯誤的那一行。根據問題的
+嚴重性,它還可能包含 **「Oops」** 一詞,比如::
+
+ BUG: unable to handle kernel NULL pointer dereference at (null)
+ IP: [<c06969d4>] iret_exc+0x7d0/0xa59
+ *pdpt = 000000002258a001 *pde = 0000000000000000
+ Oops: 0002 [#1] PREEMPT SMP
+ ...
+
+儘管有 **Oops** 或其他類型的堆棧跟蹤,但通常需要找到出問題的行來識別和處理缺
+陷。在本章中,我們將參考「Oops」來了解需要分析的各種堆棧跟蹤。
+
+如果內核是用 ``CONFIG_DEBUG_INFO`` 編譯的,那麼可以使用文件:
+`scripts/decode_stacktrace.sh` 。
+
+連結的模塊
+-----------
+
+受到汙染或正在加載/卸載的模塊用「(…)」標記,汙染標誌在
+`Documentation/admin-guide/tainted-kernels.rst` 文件中進行了描述,「正在被加
+載」用「+」標註,「正在被卸載」用「-」標註。
+
+
+Oops消息在哪?
+---------------
+
+通常,Oops文本由klogd從內核緩衝區讀取,然後交給 ``syslogd`` ,後者將其寫入
+syslog文件,通常是 ``/var/log/messages`` (取決於 ``/etc/syslog.conf`` )。
+在使用systemd的系統上,它也可以由 ``journald`` 守護進程存儲,並通過運行
+``journalctl`` 命令進行訪問。
+
+有時 ``klogd`` 會掛掉,這種情況下您可以運行 ``dmesg > file`` 從內核緩衝區
+讀取數據並保存它。或者您可以 ``cat /proc/kmsg > file`` ,但是您必須適時
+中斷以停止傳輸,因爲 ``kmsg`` 是一個「永無止境的文件」。
+
+如果機器嚴重崩潰,無法輸入命令或磁碟不可用,那還有三個選項:
+
+(1) 手動複製屏幕上的文本,並在機器重新啓動後輸入。很難受,但這是突然崩潰下
+ 唯一的選擇。或者你可以用數位相機拍下屏幕——雖然不那麼好,但總比什麼都沒
+ 有好。如果消息滾動超出控制台頂部,使用更高解析度(例如 ``vga=791`` )
+ 引導啓動將允許您閱讀更多文本。(警告:這需要 ``vesafb`` ,因此對「早期」
+ 的Oppses沒有幫助)
+
+(2) 從串口終端啓動(參見
+ :ref:`Documentation/admin-guide/serial-console.rst <serial_console>` ),
+ 在另一台機器上運行數據機然後用你喜歡的通信程序捕獲輸出。
+ Minicom運行良好。
+
+(3) 使用Kdump(參閱 Documentation/admin-guide/kdump/kdump.rst ),使用
+ Documentation/admin-guide/kdump/gdbmacros.txt 中的dmesg gdbmacro從舊內存
+ 中提取內核環形緩衝區。
+
+找到缺陷位置
+-------------
+
+如果你能指出缺陷在內核原始碼中的位置,則報告缺陷的效果會非常好。這有兩種方法。
+通常來說使用 ``gdb`` 會比較容易,不過內核需要用調試信息來預編譯。
+
+gdb
+^^^^
+
+GNU 調試器(GNU debugger, ``gdb`` )是從 ``vmlinux`` 文件中找出OOPS的確切
+文件和行號的最佳方法。
+
+在使用 ``CONFIG_DEBUG_INFO`` 編譯的內核上使用gdb效果最好。可通過運行以下命令
+進行設置::
+
+ $ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
+
+在用 ``CONFIG_DEBUG_INFO`` 編譯的內核上,你可以直接從OOPS複製EIP值::
+
+ EIP: 0060:[<c021e50e>] Not tainted VLI
+
+並使用GDB來將其翻譯成可讀形式::
+
+ $ gdb vmlinux
+ (gdb) l *0xc021e50e
+
+如果沒有啓用 ``CONFIG_DEBUG_INFO`` ,則使用OOPS的函數偏移::
+
+ EIP is at vt_ioctl+0xda8/0x1482
+
+並在啓用 ``CONFIG_DEBUG_INFO`` 的情況下重新編譯內核::
+
+ $ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
+ $ make vmlinux
+ $ gdb vmlinux
+ (gdb) l *vt_ioctl+0xda8
+ 0x1888 is in vt_ioctl (drivers/tty/vt/vt_ioctl.c:293).
+ 288 {
+ 289 struct vc_data *vc = NULL;
+ 290 int ret = 0;
+ 291
+ 292 console_lock();
+ 293 if (VT_BUSY(vc_num))
+ 294 ret = -EBUSY;
+ 295 else if (vc_num)
+ 296 vc = vc_deallocate(vc_num);
+ 297 console_unlock();
+
+或者若您想要更詳細的顯示::
+
+ (gdb) p vt_ioctl
+ $1 = {int (struct tty_struct *, unsigned int, unsigned long)} 0xae0 <vt_ioctl>
+ (gdb) l *0xae0+0xda8
+
+您也可以使用對象文件作爲替代::
+
+ $ make drivers/tty/
+ $ gdb drivers/tty/vt/vt_ioctl.o
+ (gdb) l *vt_ioctl+0xda8
+
+如果你有調用跟蹤,類似::
+
+ Call Trace:
+ [<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
+ [<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
+ [<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
+ ...
+
+這表明問題可能在 :jbd: 模塊中。您可以在gdb中加載該模塊並列出相關代碼::
+
+ $ gdb fs/jbd/jbd.ko
+ (gdb) l *log_wait_commit+0xa3
+
+.. note::
+
+ 您還可以對堆棧跟蹤處的任何函數調用執行相同的操作,例如::
+
+ [<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
+
+ 上述調用發生的位置可以通過以下方式看到::
+
+ $ gdb drivers/media/usb/dvb-usb/dvb-usb.o
+ (gdb) l *dvb_usb_adapter_frontend_exit+0x3a
+
+objdump
+^^^^^^^^
+
+要調試內核,請使用objdump並從崩潰輸出中查找十六進位偏移,以找到有效的代碼/匯
+編行。如果沒有調試符號,您將看到所示例程的彙編程序代碼,但是如果內核有調試
+符號,C代碼也將可見(調試符號可以在內核配置菜單的hacking項中啓用)。例如::
+
+ $ objdump -r -S -l --disassemble net/dccp/ipv4.o
+
+.. note::
+
+ 您需要處於內核樹的頂層以便此獲得您的C文件。
+
+如果您無法訪問原始碼,仍然可以使用以下方法調試一些崩潰轉儲(如Dave Miller的
+示例崩潰轉儲輸出所示)::
+
+ EIP is at +0x14/0x4c0
+ ...
+ Code: 44 24 04 e8 6f 05 00 00 e9 e8 fe ff ff 8d 76 00 8d bc 27 00 00
+ 00 00 55 57 56 53 81 ec bc 00 00 00 8b ac 24 d0 00 00 00 8b 5d 08
+ <8b> 83 3c 01 00 00 89 44 24 14 8b 45 28 85 c0 89 44 24 18 0f 85
+
+ Put the bytes into a "foo.s" file like this:
+
+ .text
+ .globl foo
+ foo:
+ .byte .... /* bytes from Code: part of OOPS dump */
+
+ Compile it with "gcc -c -o foo.o foo.s" then look at the output of
+ "objdump --disassemble foo.o".
+
+ Output:
+
+ ip_queue_xmit:
+ push %ebp
+ push %edi
+ push %esi
+ push %ebx
+ sub $0xbc, %esp
+ mov 0xd0(%esp), %ebp ! %ebp = arg0 (skb)
+ mov 0x8(%ebp), %ebx ! %ebx = skb->sk
+ mov 0x13c(%ebx), %eax ! %eax = inet_sk(sk)->opt
+
+`scripts/decodecode` 文件可以用來自動完成大部分工作,這取決於正在調試的CPU
+體系結構。
+
+報告缺陷
+---------
+
+一旦你通過定位缺陷找到了其發生的地方,你可以嘗試自己修復它或者向上游報告它。
+
+爲了向上游報告,您應該找出用於開發受影響代碼的郵件列表。這可以使用 ``get_maintainer.pl`` 。
+
+
+例如,您在gspca的sonixj.c文件中發現一個缺陷,則可以通過以下方法找到它的維護者::
+
+ $ ./scripts/get_maintainer.pl -f drivers/media/usb/gspca/sonixj.c
+ Hans Verkuil <hverkuil@xs4all.nl> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%)
+ Mauro Carvalho Chehab <mchehab@kernel.org> (maintainer:MEDIA INPUT INFRASTRUCTURE (V4L/DVB),commit_signer:1/1=100%)
+ Tejun Heo <tj@kernel.org> (commit_signer:1/1=100%)
+ Bhaktipriya Shridhar <bhaktipriya96@gmail.com> (commit_signer:1/1=100%,authored:1/1=100%,added_lines:4/4=100%,removed_lines:9/9=100%)
+ linux-media@vger.kernel.org (open list:GSPCA USB WEBCAM DRIVER)
+ linux-kernel@vger.kernel.org (open list)
+
+請注意它將指出:
+
+- 最後接觸原始碼的開發人員(如果這是在git樹中完成的)。在上面的例子中是Tejun
+ 和Bhaktipriya(在這個特定的案例中,沒有人真正參與這個文件的開發);
+- 驅動維護人員(Hans Verkuil);
+- 子系統維護人員(Mauro Carvalho Chehab);
+- 驅動程序和/或子系統郵件列表(linux-media@vger.kernel.org);
+- Linux內核郵件列表(linux-kernel@vger.kernel.org)。
+
+通常,修復缺陷的最快方法是將它報告給用於開發相關代碼的郵件列表(linux-media
+ML),抄送驅動程序維護者(Hans)。
+
+如果你完全不知道該把報告寄給誰,且 ``get_maintainer.pl`` 也沒有提供任何有用
+的信息,請發送到linux-kernel@vger.kernel.org。
+
+感謝您的幫助,這使Linux儘可能穩定:-)
+
+修復缺陷
+---------
+
+如果你懂得編程,你不僅可以通過報告錯誤來幫助我們,還可以提供一個解決方案。
+畢竟,開源就是分享你的工作,你不想因爲你的天才而被認可嗎?
+
+如果你決定這樣做,請在制定解決方案後將其提交到上游。
+
+請務必閱讀
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>` ,
+以幫助您的代碼被接受。
+
+
+---------------------------------------------------------------------------
+
+用 ``klogd`` 進行Oops跟蹤的注意事項
+------------------------------------
+
+爲了幫助Linus和其他內核開發人員, ``klogd`` 對保護故障的處理提供了大量支持。
+爲了完整支持地址解析,至少應該使用 ``sysklogd`` 包的1.3-pl3版本。
+
+當發生保護故障時, ``klogd`` 守護進程會自動將內核日誌消息中的重要地址轉換爲
+它們的等效符號。然後通過 ``klogd`` 使用的任何報告機制來轉發這個已翻譯的內核
+消息。保護錯誤消息可以直接從消息文件中剪切出來並轉發給內核開發人員。
+
+``klogd`` 執行兩種類型的地址解析,靜態翻譯和動態翻譯。靜態翻譯使用System.map
+文件。爲了進行靜態轉換, ``klogd`` 守護進程必須能夠在守護進程初始化時找到系
+統映射文件。有關 ``klogd`` 如何搜索映射文件的信息,請參見klogd手冊頁。
+
+當使用內核可加載模塊時,動態地址轉換非常重要。由於內核模塊的內存是從內核的
+動態內存池中分配的,因此無論是模塊的開頭還是模塊中的函數和符號都沒有固定的
+位置。
+
+內核支持系統調用,允許程序確定加載哪些模塊及其在內存中的位置。klogd守護進程
+使用這些系統調用構建了一個符號表,可用於調試可加載內核模塊中發生的保護錯誤。
+
+klogd至少會提供產生保護故障的模塊的名稱。如果可加載模塊的開發人員選擇從模塊
+導出符號信息,則可能會有其他可用的符號信息。
+
+由於內核模塊環境可以是動態的,因此當模塊環境發生變化時,必須有一種通知
+``klogd`` 守護進程的機制。有一些可用的命令行選項允許klogd向當前正在執行的守
+護進程發出信號示意應該刷新符號信息。有關更多信息,請參閱 ``klogd`` 手冊頁。
+
+sysklogd發行版附帶了一個補丁,它修改了 ``modules-2.0.0`` 包,以便在加載或
+卸載模塊時自動向klogd發送信號。應用此補丁基本上可無縫支持調試內核可加載模塊
+發生的保護故障。
+
+以下是 ``klogd`` 處理的可加載模塊中的保護故障示例::
+
+ Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
+ Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
+ Aug 29 09:51:01 blizard kernel: *pde = 00000000
+ Aug 29 09:51:01 blizard kernel: Oops: 0002
+ Aug 29 09:51:01 blizard kernel: CPU: 0
+ Aug 29 09:51:01 blizard kernel: EIP: 0010:[oops:_oops+16/3868]
+ Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
+ Aug 29 09:51:01 blizard kernel: eax: 315e97cc ebx: 003a6f80 ecx: 001be77b edx: 00237c0c
+ Aug 29 09:51:01 blizard kernel: esi: 00000000 edi: bffffdb3 ebp: 00589f90 esp: 00589f8c
+ Aug 29 09:51:01 blizard kernel: ds: 0018 es: 0018 fs: 002b gs: 002b ss: 0018
+ Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
+ Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
+ Aug 29 09:51:01 blizard kernel: 00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
+ Aug 29 09:51:01 blizard kernel: bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
+ Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
+ Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
+
+---------------------------------------------------------------------------
+
+::
+
+ Dr. G.W. Wettstein Oncology Research Div. Computing Facility
+ Roger Maris Cancer Center INTERNET: greg@wind.rmcc.com
+ 820 4th St. N.
+ Fargo, ND 58122
+ Phone: 701-234-7556
+
diff --git a/Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst b/Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst
new file mode 100644
index 000000000000..bdc1a22046cf
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Translator: 胡皓文 Hu Haowen <src.res@email.cn>
+
+清除 WARN_ONCE
+--------------
+
+WARN_ONCE / WARN_ON_ONCE / printk_once 僅僅列印一次消息.
+
+echo 1 > /sys/kernel/debug/clear_warn_once
+
+可以清除這種狀態並且再次允許列印一次告警信息,這對於運行測試集後重現問題
+很有用。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/cpu-load.rst b/Documentation/translations/zh_TW/admin-guide/cpu-load.rst
new file mode 100644
index 000000000000..be087cef1967
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/cpu-load.rst
@@ -0,0 +1,112 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Translator: 胡皓文 Hu Haowen <src.res@email.cn>
+
+========
+CPU 負載
+========
+
+Linux通過``/proc/stat``和``/proc/uptime``導出各種信息,用戶空間工具
+如top(1)使用這些信息計算系統花費在某個特定狀態的平均時間。
+例如:
+
+ $ iostat
+ Linux 2.6.18.3-exp (linmac) 02/20/2007
+
+ avg-cpu: %user %nice %system %iowait %steal %idle
+ 10.01 0.00 2.92 5.44 0.00 81.63
+
+ ...
+
+這裡系統認爲在默認採樣周期內有10.01%的時間工作在用戶空間,2.92%的時
+間用在系統空間,總體上有81.63%的時間是空閒的。
+
+大多數情況下``/proc/stat``的信息幾乎真實反映了系統信息,然而,由於內
+核採集這些數據的方式/時間的特點,有時這些信息根本不可靠。
+
+那麼這些信息是如何被搜集的呢?每當時間中斷觸發時,內核查看此刻運行的
+進程類型,並增加與此類型/狀態進程對應的計數器的值。這種方法的問題是
+在兩次時間中斷之間系統(進程)能夠在多種狀態之間切換多次,而計數器只
+增加最後一種狀態下的計數。
+
+舉例
+---
+
+假設系統有一個進程以如下方式周期性地占用cpu::
+
+ 兩個時鐘中斷之間的時間線
+ |-----------------------|
+ ^ ^
+ |_ 開始運行 |
+ |_ 開始睡眠
+ (很快會被喚醒)
+
+在上面的情況下,根據``/proc/stat``的信息(由於當系統處於空閒狀態時,
+時間中斷經常會發生)系統的負載將會是0
+
+大家能夠想像內核的這種行爲會發生在許多情況下,這將導致``/proc/stat``
+中存在相當古怪的信息::
+
+ /* gcc -o hog smallhog.c */
+ #include <time.h>
+ #include <limits.h>
+ #include <signal.h>
+ #include <sys/time.h>
+ #define HIST 10
+
+ static volatile sig_atomic_t stop;
+
+ static void sighandler (int signr)
+ {
+ (void) signr;
+ stop = 1;
+ }
+ static unsigned long hog (unsigned long niters)
+ {
+ stop = 0;
+ while (!stop && --niters);
+ return niters;
+ }
+ int main (void)
+ {
+ int i;
+ struct itimerval it = { .it_interval = { .tv_sec = 0, .tv_usec = 1 },
+ .it_value = { .tv_sec = 0, .tv_usec = 1 } };
+ sigset_t set;
+ unsigned long v[HIST];
+ double tmp = 0.0;
+ unsigned long n;
+ signal (SIGALRM, &sighandler);
+ setitimer (ITIMER_REAL, &it, NULL);
+
+ hog (ULONG_MAX);
+ for (i = 0; i < HIST; ++i) v[i] = ULONG_MAX - hog (ULONG_MAX);
+ for (i = 0; i < HIST; ++i) tmp += v[i];
+ tmp /= HIST;
+ n = tmp - (tmp / 3.0);
+
+ sigemptyset (&set);
+ sigaddset (&set, SIGALRM);
+
+ for (;;) {
+ hog (n);
+ sigwait (&set, &i);
+ }
+ return 0;
+ }
+
+
+參考
+---
+
+- https://lore.kernel.org/r/loom.20070212T063225-663@post.gmane.org
+- Documentation/filesystems/proc.rst (1.8)
+
+
+謝謝
+---
+
+Con Kolivas, Pavel Machek
+
diff --git a/Documentation/translations/zh_TW/admin-guide/index.rst b/Documentation/translations/zh_TW/admin-guide/index.rst
new file mode 100644
index 000000000000..293c20245783
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/index.rst
@@ -0,0 +1,135 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :doc:`../../../admin-guide/index`
+:Translator: 胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 內核用戶和管理員指南
+==========================
+
+下面是一組隨時間添加到內核中的面向用戶的文檔的集合。到目前爲止,還沒有一個
+整體的順序或組織 - 這些材料不是一個單一的,連貫的文件!幸運的話,情況會隨著
+時間的推移而迅速改善。
+
+這個初始部分包含總體信息,包括描述內核的README, 關於內核參數的文檔等。
+
+.. toctree::
+ :maxdepth: 1
+
+ README
+
+Todolist:
+
+ kernel-parameters
+ devices
+ sysctl/index
+
+本節介紹CPU漏洞及其緩解措施。
+
+Todolist:
+
+ hw-vuln/index
+
+下面的一組文檔,針對的是試圖跟蹤問題和bug的用戶。
+
+.. toctree::
+ :maxdepth: 1
+
+ reporting-issues
+ security-bugs
+ bug-hunting
+ bug-bisect
+ tainted-kernels
+ init
+
+Todolist:
+
+ reporting-bugs
+ ramoops
+ dynamic-debug-howto
+ kdump/index
+ perf/index
+
+這是應用程式開發人員感興趣的章節的開始。可以在這裡找到涵蓋內核ABI各個
+方面的文檔。
+
+Todolist:
+
+ sysfs-rules
+
+本手冊的其餘部分包括各種指南,介紹如何根據您的喜好配置內核的特定行爲。
+
+
+.. toctree::
+ :maxdepth: 1
+
+ clearing-warn-once
+ cpu-load
+ unicode
+
+Todolist:
+
+ acpi/index
+ aoe/index
+ auxdisplay/index
+ bcache
+ binderfs
+ binfmt-misc
+ blockdev/index
+ bootconfig
+ braille-console
+ btmrvl
+ cgroup-v1/index
+ cgroup-v2
+ cifs/index
+ cputopology
+ dell_rbu
+ device-mapper/index
+ edid
+ efi-stub
+ ext4
+ nfs/index
+ gpio/index
+ highuid
+ hw_random
+ initrd
+ iostats
+ java
+ jfs
+ kernel-per-CPU-kthreads
+ laptops/index
+ lcd-panel-cgram
+ ldm
+ lockup-watchdogs
+ LSM/index
+ md
+ media/index
+ mm/index
+ module-signing
+ mono
+ namespaces/index
+ numastat
+ parport
+ perf-security
+ pm/index
+ pnp
+ rapidio
+ ras
+ rtc
+ serial-console
+ svga
+ sysrq
+ thunderbolt
+ ufs
+ vga-softcursor
+ video-output
+ xfs
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/admin-guide/init.rst b/Documentation/translations/zh_TW/admin-guide/init.rst
new file mode 100644
index 000000000000..32cdf134948f
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/init.rst
@@ -0,0 +1,58 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :doc:`../../../admin-guide/init`
+
+:譯者:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+解釋「No working init found.」啓動掛起消息
+==========================================
+
+:作者:
+
+ Andreas Mohr <andi at lisas period de>
+
+ Cristian Souza <cristianmsbr at gmail period com>
+
+本文檔提供了加載初始化二進位(init binary)失敗的一些高層級原因(大致按執行
+順序列出)。
+
+1) **無法掛載根文件系統Unable to mount root FS** :請設置「debug」內核參數(在
+ 引導加載程序bootloader配置文件或CONFIG_CMDLINE)以獲取更詳細的內核消息。
+
+2) **初始化二進位不存在於根文件系統上init binary doesn't exist on rootfs** :
+ 確保您的根文件系統類型正確(並且 ``root=`` 內核參數指向正確的分區);擁有
+ 所需的驅動程序,例如SCSI或USB等存儲硬體;文件系統(ext3、jffs2等)是內建的
+ (或者作爲模塊由initrd預加載)。
+
+3) **控制台設備損壞Broken console device** : ``console= setup`` 中可能存在
+ 衝突 --> 初始控制台不可用(initial console unavailable)。例如,由於串行
+ IRQ問題(如缺少基於中斷的配置)導致的某些串行控制台不可靠。嘗試使用不同的
+ ``console= device`` 或像 ``netconsole=`` 。
+
+4) **二進位存在但依賴項不可用Binary exists but dependencies not available** :
+ 例如初始化二進位的必需庫依賴項,像 ``/lib/ld-linux.so.2`` 丟失或損壞。使用
+ ``readelf -d <INIT>|grep NEEDED`` 找出需要哪些庫。
+
+5) **無法加載二進位Binary cannot be loaded** :請確保二進位的體系結構與您的
+ 硬體匹配。例如i386不匹配x86_64,或者嘗試在ARM硬體上加載x86。如果您嘗試在
+ 此處加載非二進位文件(shell腳本?),您應該確保腳本在其工作頭(shebang
+ header)行 ``#!/...`` 中指定能正常工作的解釋器(包括其庫依賴項)。在處理
+ 腳本之前,最好先測試一個簡單的非腳本二進位文件,比如 ``/bin/sh`` ,並確認
+ 它能成功執行。要了解更多信息,請將代碼添加到 ``init/main.c`` 以顯示
+ kernel_execve()的返回值。
+
+當您發現新的失敗原因時,請擴展本解釋(畢竟加載初始化二進位是一個 **關鍵** 且
+艱難的過渡步驟,需要儘可能無痛地進行),然後向LKML提交一個補丁。
+
+待辦事項:
+
+- 通過一個可以存儲 ``kernel_execve()`` 結果值的結構體數組實現各種
+ ``run_init_process()`` 調用,並在失敗時通過疊代 **所有** 結果來記錄一切
+ (非常重要的可用性修復)。
+- 試著使實現本身在一般情況下更有幫助,例如在受影響的地方提供額外的錯誤消息。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/reporting-issues.rst b/Documentation/translations/zh_TW/admin-guide/reporting-issues.rst
new file mode 100644
index 000000000000..27638e199f13
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/reporting-issues.rst
@@ -0,0 +1,1337 @@
+.. SPDX-License-Identifier: (GPL-2.0+ OR CC-BY-4.0)
+..
+ If you want to distribute this text under CC-BY-4.0 only, please use 'The
+ Linux kernel developers' for author attribution and link this as source:
+ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/admin-guide/reporting-issues.rst
+..
+ Note: Only the content of this RST file as found in the Linux kernel sources
+ is available under CC-BY-4.0, as versions of this text that were processed
+ (for example by the kernel's build system) might contain content taken from
+ files which use a more restrictive license.
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/reporting-issues.rst
+
+:譯者:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+
+報告問題
++++++++++
+
+
+簡明指南(亦即 太長不看)
+==========================
+
+您面臨的是否爲同系列穩定版或長期支持內核的普通內核的回歸?是否仍然受支持?
+請搜索 `LKML內核郵件列表 <https://lore.kernel.org/lkml/>`_ 和
+`Linux穩定版郵件列表 <https://lore.kernel.org/stable/>`_ 存檔中匹配的報告並
+加入討論。如果找不到匹配的報告,請安裝該系列的最新版本。如果它仍然出現問題,
+報告給穩定版郵件列表(stable@vger.kernel.org)。
+
+在所有其他情況下,請儘可能猜測是哪個內核部分導致了問題。查看MAINTAINERS文件,
+了解開發人員希望如何得知問題,大多數情況下,報告問題都是通過電子郵件和抄送
+相關郵件列表進行的。檢查報告目的地的存檔中是否已有匹配的報告;也請搜索
+`LKML <https://lore.kernel.org/lkml/>`_ 和網絡。如果找不到可加入的討論,請
+安裝 `最新的主線內核 <https://kernel.org/>`_ 。如果仍存在問題,請發送報告。
+
+問題已經解決了,但是您希望看到它在一個仍然支持的穩定版或長期支持系列中得到
+解決?請安裝其最新版本。如果它出現了問題,那麼在主線中搜索修復它的更改,並
+檢查是否正在回傳(backporting)或者已放棄;如果兩者都沒有,那麼可詢問處理
+更改的人員。
+
+**通用提醒** :當安裝和測試上述內核時,請確保它是普通的(即:沒有補丁,也沒
+有使用附加模塊)。還要確保它是在一個正常的環境中構建和運行,並且在問題發生
+之前沒有被汙染(tainted)。
+
+在編寫報告時,要涵蓋與問題相關的所有信息,如使用的內核和發行版。在碰見回歸時,
+嘗試給出引入它的更改的提交ID,二分可以找到它。如果您同時面臨Linux內核的多個
+問題,請分別報告每個問題。
+
+一旦報告發出,請回答任何出現的問題,並儘可能地提供幫助。這包括通過不時重新
+測試新版本並發送狀態更新來推動進展。
+
+
+如何向內核維護人員報告問題的逐步指南
+=====================================
+
+上面的簡明指南概述了如何向Linux內核開發人員報告問題。對於已經熟悉向自由和開
+源軟體(FLOSS)項目報告問題的人來說,這可能是他們所需要的全部內容。對於其他
+人,本部分更爲詳細,並一步一步地描述。爲了便於閱讀,它仍然儘量簡潔,並省略
+了許多細節;這些在逐步指南後的參考章節中進行了描述,該章節更詳細地解釋了每
+個步驟。
+
+注意:本節涉及的方面比簡明指南多,順序也稍有不同。這符合你的利益,以確保您
+儘早意識到看起來像Linux內核毛病的問題可能實際上是由其他原因引起的。這些步驟
+可以確保你最終不會覺得在這一過程中投入的時間是浪費:
+
+ * 您是否面臨硬體或軟體供應商提供的Linux內核的問題?那麼基本上您最好停止閱讀
+ 本文檔,轉而向您的供應商報告問題,除非您願意自己安裝最新的Linux版本。尋找
+ 和解決問題往往需要後者。
+
+ * 使用您喜愛的網絡搜尋引擎對現有報告進行粗略搜索;此外,請檢查
+ `Linux內核郵件列表(LKML) <https://lore.kernel.org/lkml/>`_ 的存檔。如果
+ 找到匹配的報告,請加入討論而不是發送新報告。
+
+ * 看看你正在處理的問題是否爲回歸問題、安全問題或非常嚴重的問題:這些都是需
+ 要在接下來的一些步驟中特別處理的「高優先級問題」。
+
+ * 確保不是內核環境導致了您面臨的問題。
+
+ * 創建一個新的備份,並將系統修復和恢復工具放在手邊。
+
+ * 確保您的系統不會通過動態構建額外的內核模塊來增強其內核,像DKMS這樣的解決
+ 方案可能在您不知情的情況下就在本地進行了這樣的工作。
+
+ * 當問題發生時,檢查您的內核是否被「汙染」,因爲使內核設置這個標誌的事件可能
+ 會導致您面臨的問題。
+
+ * 粗略地寫下如何重現這個問題。如果您同時處理多個問題,請爲每個問題單獨寫注
+ 釋,並確保它們在新啓動的系統上獨立出現。這是必要的,因爲每個問題都需要分
+ 別報告給內核開發人員,除非它們嚴重糾纏在一起。
+
+ * 如果您正面臨穩定版或長期支持版本線的回歸(例如從5.10.4更新到5.10.5時出現
+ 故障),請查看後文「報告穩定版和長期支持內核線的回歸」小節。
+
+ * 定位可能引起問題的驅動程序或內核子系統。找出其開發人員期望的報告的方式和
+ 位置。注意:大多數情況下不會是 bugzilla.kernel.org,因爲問題通常需要通
+ 過郵件發送給維護人員和公共郵件列表。
+
+ * 在缺陷追蹤器或問題相關郵件列表的存檔中徹底搜索可能與您的問題匹配的報告。
+ 如果你發現了一些相關討論,請加入討論而不是發送新的報告。
+
+在完成這些準備之後,你將進入主要部分:
+
+ * 除非您已經在運行最新的「主線」Linux內核,否則最好在報告流程前安裝它。在某些
+ 情況下,使用最新的「穩定版」Linux進行測試和報告也是可以接受的替代方案;在
+ 合併窗口期間,這實際上可能是最好的方法,但在開發階段最好還是暫停幾天。無論
+ 你選擇什麼版本,最好使用「普通」構建。忽略這些建議會大大增加您的報告被拒絕
+ 或忽略的風險。
+
+ * 確保您剛剛安裝的內核在運行時不會「汙染」自己。
+
+ * 在您剛剛安裝的內核中復現這個問題。如果它沒有出現,請查看下方只發生在
+ 穩定版和長期支持內核的問題的說明。
+
+ * 優化你的筆記:試著找到並寫出最直接的復現問題的方法。確保最終結果包含所有
+ 重要的細節,同時讓第一次聽說的人容易閱讀和理解。如果您在此過程中學到了一
+ 些東西,請考慮再次搜索關於該問題的現有報告。
+
+ * 如果失敗涉及「panic」、「Oops」、「warning」或「BUG」,請考慮解碼內核日誌以查找觸
+ 發錯誤的代碼行。
+
+ * 如果您的問題是回歸問題,請儘可能縮小引入問題時的範圍。
+
+ * 通過詳細描述問題來開始編寫報告。記得包括以下條目:您爲復現而安裝的最新內
+ 核版本、使用的Linux發行版以及關於如何復現該問題的說明。如果可能,將內核
+ 構建配置(.config)和 ``dmesg`` 的輸出放在網上的某個地方,並連結到它。包
+ 含或上傳所有其他可能相關的信息,如Oops的輸出/截圖或來自 ``lspci`` 的輸出
+ 。一旦你寫完了這個主要部分,請在上方插入一個正常長度的段落快速概述問題和
+ 影響。再在此之上添加一個簡單描述問題的句子,以得到人們的閱讀。現在給出一
+ 個更短的描述性標題或主題。然後就可以像MAINTAINERS文件告訴你的那樣發送或
+ 提交報告了,除非你在處理一個「高優先級問題」:它們需要按照下面「高優先級問
+ 題的特殊處理」所述特別關照。
+
+ * 等待別人的反應,繼續推進事情,直到你能夠接受這樣或那樣的結果。因此,請公
+ 開和及時地回應任何詢問。測試提出的修復。積極地測試:至少重新測試每個新主
+ 線版本的首個候選版本(RC),並報告你的結果。如果出現拖延,就友好地提醒一
+ 下。如果你沒有得到任何幫助或者未能滿意,請試著自己幫助自己。
+
+
+報告穩定版和長期支持內核線的回歸
+----------------------------------
+
+如果您發現了穩定版或長期支持內核版本線中的回歸問題並按上述流程跳到這裡,那麼
+請閱讀本小節。即例如您在從5.10.4更新到5.10.5時出現了問題(從5.9.15到5.10.5則
+不是)。開發人員希望儘快修復此類回歸,因此有一個簡化流程來報告它們:
+
+ * 檢查內核開發人員是否仍然維護你關心的Linux內核版本線:去 `kernel.org 的首頁
+ <https://kernel.org/>`_ ,確保此特定版本線的最新版沒有「[EOL]」標記。
+
+ * 檢查 `Linux穩定版郵件列表 <https://lore.kernel.org/stable/>`_ 中的現有報告。
+
+ * 從特定的版本線安裝最新版本作爲純淨內核。確保這個內核沒有被汙染,並且仍然
+ 存在問題,因爲問題可能已經在那裡被修復了。如果您第一次發現供應商內核的問題,
+ 請檢查已知最新版本的普通構建是否可以正常運行。
+
+ * 向Linux穩定版郵件列表發送一個簡短的問題報告(stable@vger.kernel.org)。大致
+ 描述問題,並解釋如何復現。講清楚首個出現問題的版本和最後一個工作正常的版本。
+ 然後等待進一步的指示。
+
+下面的參考章節部分詳細解釋了這些步驟中的每一步。
+
+
+報告只發生在較舊內核版本線的問題
+----------------------------------
+
+若您嘗試了上述的最新主線內核,但未能在那裡復現問題,那麼本小節適用於您;以下
+流程有助於使問題在仍然支持的穩定版或長期支持版本線,或者定期基於最新穩定版或
+長期支持內核的供應商內核中得到修復。如果是這種情況,請執行以下步驟:
+
+ * 請做好準備,接下來的幾個步驟可能無法在舊版本中解決問題:修復可能太大或太
+ 冒險,無法移植到那裡。
+
+ * 執行前節「報告穩定版和長期支持內核線的回歸」中的前三個步驟。
+
+ * 在Linux內核版本控制系統中搜索修復主線問題的更改,因爲它的提交消息可能會
+ 告訴你修復是否已經計劃好了支持。如果你沒有找到,搜索適當的郵件列表,尋找
+ 討論此類問題或同行評議可能修復的帖子;然後檢查討論是否認爲修復不適合支持。
+ 如果支持根本不被考慮,加入最新的討論,詢問是否有可能。
+
+ * 前面的步驟之一應該會給出一個解決方案。如果仍未能成功,請向可能引起問題的
+ 子系統的維護人員詢問建議;抄送特定子系統的郵件列表以及穩定版郵件列表
+
+下面的參考章節部分詳細解釋了這些步驟中的每一步。
+
+
+參考章節:向內核維護者報告問題
+===============================
+
+上面的詳細指南簡要地列出了所有主要步驟,這對大多數人來說應該足夠了。但有時,
+即使是有經驗的用戶也可能想知道如何實際執行這些步驟之一。這就是本節的目的,
+因爲它將提供關於上述每個步驟的更多細節。請將此作爲參考文檔:可以從頭到尾
+閱讀它。但它主要是爲了瀏覽和查找如何實際執行這些步驟的詳細信息。
+
+在深入挖掘細節之前,我想先給你一些一般性建議:
+
+ * Linux內核開發人員很清楚這個過程很複雜,比其他的FLOSS項目要求更多。我們很
+ 希望讓它更簡單。但這需要在不同的地方以及一些基礎設施上付諸努力,這些基礎
+ 設施需要持續的維護;尚未有人站出來做這些工作,所以目前情況就是這樣。
+
+ * 與某些供應商簽訂的保證或支持合同並不能使您有權要求上游Linux內核社區的開
+ 發人員進行修復:這樣的合同完全在Linux內核、其開發社區和本文檔的範圍之外。
+ 這就是爲什麼在這種情況下,你不能要求任何契約保證,即使開發人員處理的問
+ 題對供應商有效。如果您想主張您的權利,使用供應商的支持渠道代替。當這樣做
+ 的時候,你可能想提出你希望看到這個問題在上游Linux內核中修復;可以這是確
+ 保最終修復將被納入所有Linux發行版的唯一方法來鼓勵他們。
+
+ * 如果您從未向FLOSS項目報告過任何問題,那麼您應該考慮閱讀 `如何有效地報告
+ 缺陷 <https://www.chiark.greenend.org.uk/~sgtatham/bugs.html>`_ , `如何
+ 以明智的方式提問 <http://www.catb.org/esr/faqs/smart-questions.html>`_ ,
+ 和 `如何提出好問題 <https://jvns.ca/blog/good-questions/>`_ 。
+
+解決這些問題之後,可以在下面找到如何正確地向Linux內核報告問題的詳細信息。
+
+
+確保您使用的是上游Linux內核
+----------------------------
+
+ *您是否面臨硬體或軟體供應商提供的Linux內核的問題?那麼基本上您最好停止閱
+ 讀本文檔,轉而向您的供應商報告問題,除非您願意自己安裝最新的Linux版本。
+ 尋找和解決問題往往需要後者。*
+
+與大多數程式設計師一樣,Linux內核開發人員不喜歡花時間處理他們維護的原始碼中根本
+不會發生的問題的報告。這只會浪費每個人的時間,尤其是你的時間。不幸的是,當
+涉及到內核時,這樣的情況很容易發生,並且常常導致雙方氣餒。這是因爲幾乎所有預
+裝在設備(台式機、筆記本電腦、智慧型手機、路由器等)上的Linux內核,以及大多數
+由Linux發行商提供的內核,都與由kernel.org發行的官方Linux內核相距甚遠:從Linux
+開發的角度來看,這些供應商提供的內核通常是古老的或者經過了大量修改,通常兩點
+兼具。
+
+大多數供應商內核都不適合用來向Linux內核開發人員報告問題:您在其中遇到的問題
+可能已經由Linux內核開發人員在數月或數年前修復;此外,供應商的修改和增強可能
+會導致您面臨的問題,即使它們看起來很小或者完全不相關。這就是爲什麼您應該向
+供應商報告這些內核的問題。它的開發者應該查看報告,如果它是一個上游問題,直接
+於上游修復或將報告轉發到那裡。在實踐中,這有時行不通。因此,您可能需要考慮
+通過自己安裝最新的Linux內核內核來繞過供應商。如果如果您選擇此方法,那麼本指
+南後面的步驟將解釋如何在排除了其他可能導致您的問題的原因後執行此操作。
+
+注意前段使用的詞語是「大多數」,因爲有時候開發人員實際上願意處理供應商內核出現
+的問題報告。他們是否這麼做很大程度上取決於開發人員和相關問題。如果發行版只
+根據最近的Linux版本對內核進行了較小修改,那麼機會就比較大;例如對於Debian
+GNU/Linux Sid或Fedora Rawhide所提供的主線內核。一些開發人員還將接受基於最新
+穩定內核的發行版內核問題報告,只要它改動不大;例如Arch Linux、常規Fedora版本
+和openSUSE Turboweed。但是請記住,您最好使用主線Linux,並避免在此流程中使用
+穩定版內核,如「安裝一個新的內核進行測試」一節中所詳述。
+
+當然,您可以忽略所有這些建議,並向上游Linux開發人員報告舊的或經過大量修改的
+供應商內核的問題。但是注意,這樣的報告經常被拒絕或忽視,所以自行小心考慮一下。
+不過這還是比根本不報告問題要好:有時候這樣的報告會直接或間接地幫助解決之後的
+問題。
+
+
+搜索現有報告(第一部分)
+-------------------------
+
+ *使用您喜愛的網絡搜尋引擎對現有報告進行粗略搜索;此外,請檢查Linux內核
+ 郵件列表(LKML)的存檔。如果找到匹配的報告,請加入討論而不是發送新報告。*
+
+報告一個別人已經提出的問題,對每個人來說都是浪費時間,尤其是作爲報告人的你。
+所以徹底檢查是否有人已經報告了這個問題,這對你自己是有利的。在流程中的這一步,
+可以只執行一個粗略的搜索:一旦您知道您的問題需要報告到哪裡,稍後的步驟將告訴
+您如何詳細搜索。儘管如此,不要倉促完成這一步,它可以節省您的時間和減少麻煩。
+
+只需先用你最喜歡的搜尋引擎在網際網路上搜索。然後再搜索Linux內核郵件列表(LKML)
+存檔。
+
+如果搜索結果實在太多,可以考慮讓你的搜尋引擎將搜索時間範圍限制在過去的一個
+月或一年。而且無論你在哪裡搜索,一定要用恰當的搜索關鍵詞;也要變化幾次關鍵
+詞。同時,試著從別人的角度看問題:這將幫助你想出其他的關鍵詞。另外,一定不
+要同時使用過多的關鍵詞。記住搜索時要同時嘗試包含和不包含內核驅動程序的名稱
+或受影響的硬體組件的名稱等信息。但其確切的品牌名稱(比如說「華碩紅魔 Radeon
+RX 5700 XT Gaming OC」)往往幫助不大,因爲它太具體了。相反,嘗試搜索術語,如
+型號(Radeon 5700 或 Radeon 5000)和核心代號(「Navi」或「Navi10」),以及包含
+和不包含其製造商(「AMD」)。
+
+如果你發現了關於你的問題的現有報告,請加入討論,因爲你可能會提供有價值的額
+外信息。這一點很重要,即使是在修復程序已經準備好或處於最後階段,因爲開發人
+員可能會尋找能夠提供額外信息或測試建議修復程序的人。跳到「發布報告後的責任」
+一節,了解有關如何正確參與的細節。
+
+注意,搜索 `bugzilla.kernel.org <https://bugzilla.kernel.org/>`_ 網站可能
+也是一個好主意,因爲這可能會提供有價值的見解或找到匹配的報告。如果您發現後者,
+請記住:大多數子系統都希望在不同的位置報告,如下面「你需要將問題報告到何處」
+一節中所述。因此本應處理這個問題的開發人員甚至可能不知道bugzilla的工單。所以
+請檢查工單中的問題是否已經按照本文檔所述得到報告,如果沒有,請考慮這樣做。
+
+高優先級的問題?
+-----------------
+
+ *看看你正在處理的問題是否是回歸問題、安全問題或非常嚴重的問題:這些都是
+ 需要在接下來的一些步驟中特別處理的「高優先級問題」。*
+
+Linus Torvalds和主要的Linux內核開發人員希望看到一些問題儘快得到解決,因此在
+報告過程中有一些「高優先級問題」的處理略有不同。有三種情況符合條件:回歸、安全
+問題和非常嚴重的問題。
+
+如果在舊版本的Linux內核中工作的東西不能在新版本的Linux內核中工作,或者某種
+程度上在新版本的Linux內核中工作得更差,那麼你就需要處理「回歸」。因此,當一個
+在Linux 5.7中表現良好的WiFi驅動程序在5.8中表現不佳或根本不能工作時,這是一
+種回歸。如果應用程式在新的內核中出現不穩定的現象,這也是一種回歸,這可能是
+由於內核和用戶空間之間的接口(如procfs和sysfs)發生不兼容的更改造成的。顯著
+的性能降低或功耗增加也可以稱爲回歸。但是請記住:新內核需要使用與舊內核相似的
+配置來構建(參見下面如何實現這一點)。這是因爲內核開發人員在實現新特性時有
+時無法避免不兼容性;但是爲了避免回歸,這些特性必須在構建配置期間顯式地啓用。
+
+什麼是安全問題留給您自己判斷。在繼續之前,請考慮閱讀
+「Documentation/translations/zh_TW/admin-guide/security-bugs.rst」,
+因爲它提供了如何最恰當地處理安全問題的額外細節。
+
+當發生了完全無法接受的糟糕事情時,此問題就是一個「非常嚴重的問題」。例如,
+Linux內核破壞了它處理的數據或損壞了它運行的硬體。當內核突然顯示錯誤消息
+(「kernel panic」)並停止工作,或者根本沒有任何停止信息時,您也在處理一個嚴重
+的問題。注意:不要混淆「panic」(內核停止自身的致命錯誤)和「Oops」(可恢復錯誤),
+因爲顯示後者之後內核仍然在運行。
+
+
+確保環境健康
+--------------
+
+ *確保不是內核所處環境導致了你所面臨的問題。*
+
+看起來很像內核問題的問題有時是由構建或運行時環境引起的。很難完全排除這種問
+題,但你應該儘量減少這種問題:
+
+ * 構建內核時,請使用經過驗證的工具,因爲編譯器或二進位文件中的錯誤可能會導
+ 致內核出現錯誤行爲。
+
+ * 確保您的計算機組件在其設計規範內運行;這對處理器、內存和主板尤爲重要。因
+ 此,當面臨潛在的內核問題時,停止低電壓或超頻。
+
+ * 儘量確保不是硬體故障導致了你的問題。例如,內存損壞會導致大量的問題,這些
+ 問題會表現爲看起來像內核問題。
+
+ * 如果你正在處理一個文件系統問題,你可能需要用 ``fsck`` 檢查一下文件系統,
+ 因爲它可能會以某種方式被損壞,從而導致無法預期的內核行爲。
+
+ * 在處理回歸問題時,要確保沒有在更新內核的同時發生了其他變化。例如,這個問
+ 題可能是由同時更新的其他軟體引起的。也有可能是在你第一次重啓進入新內核時,
+ 某個硬體巧合地壞了。更新系統 BIOS 或改變 BIOS 設置中的某些內容也會導致
+ 一些看起來很像內核回歸的問題。
+
+
+爲緊急情況做好準備
+-------------------
+
+ *創建一個全新的備份,並將系統修復和還原工具放在手邊*
+
+我得提醒您,您正在和計算機打交道,計算機有時會出現意想不到的事情,尤其是當
+您折騰其作業系統的內核等關鍵部件時。而這就是你在這個過程中要做的事情。因此,
+一定要創建一個全新的備份;還要確保你手頭有修復或重裝作業系統的所有工具,
+以及恢復備份所需的一切。
+
+
+確保你的內核不會被增強
+------------------------
+
+ *確保您的系統不會通過動態構建額外的內核模塊來增強其內核,像DKMS這樣的解
+ 決方案可能在您不知情的情況下就在本地進行了這樣的工作。*
+
+如果內核以任何方式得到增強,那麼問題報告被忽略或拒絕的風險就會急劇增加。這就
+是爲什麼您應該刪除或禁用像akmods和DKMS這樣的機制:這些機制會自動構建額外內核
+模塊,例如當您安裝新的Linux內核或第一次引導它時。也要記得同時刪除他們可能安裝
+的任何模塊。然後重新啓動再繼續。
+
+注意,你可能不知道你的系統正在使用這些解決方案之一:當你安裝 Nvidia 專有圖
+形驅動程序、VirtualBox 或其他需要 Linux 內核以外的模塊支持的軟體時,它們通
+常會靜默設置。這就是爲什麼你可能需要卸載這些軟體的軟體包,以擺脫任何第三方
+內核模塊。
+
+
+檢測「汙染」標誌
+----------------
+
+ *當問題發生時,檢查您的內核是否被「汙染」,因爲使內核設置這個標誌的事件可
+ 能會導致您面臨的問題。*
+
+當某些可能會導致看起來完全不相關的後續錯誤的事情發生時,內核會用「汙染
+(taint)」標誌標記自己。如果您的內核受到汙染,那麼您面臨的可能是這樣的錯誤。
+因此在投入更多時間到這個過程中之前,儘早排除此情況可能對你有好處。這是這個
+步驟出現在這裡的唯一原因,因爲這個過程稍後會告訴您安裝最新的主線內核;然後
+您將需要再次檢查汙染標誌,因爲當它出問題的時候內核報告會關注它。
+
+在正在運行的系統上檢查內核是否汙染非常容易:如果 ``cat /proc/sys/kernel/tainted``
+返回「0」,那麼內核沒有被汙染,一切正常。在某些情況下無法檢查該文件;這就是
+爲什麼當內核報告內部問題(「kernel bug」)、可恢復錯誤(「kernel Oops」)或停止
+操作前不可恢復的錯誤(「kernel panic」)時,它也會提到汙染狀態。當其中一個錯
+誤發生時,查看列印的錯誤消息的頂部,搜索以「CPU:」開頭的行。如果發現問題時內
+核未被汙染,那麼它應該以「Not infected」結束;如果你看到「Tainted:」且後跟一些
+空格和字母,那就被汙染了。
+
+如果你的內核被汙染了,請閱讀「Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst」
+以找出原因。設法消除汙染因素。通常是由以下三種因素之一引起的:
+
+ 1. 發生了一個可恢復的錯誤(「kernel Oops」),內核汙染了自己,因爲內核知道在
+ 此之後它可能會出現奇怪的行爲錯亂。在這種情況下,檢查您的內核或系統日誌,
+ 並尋找以下列文字開頭的部分::
+
+ Oops: 0000 [#1] SMP
+
+ 如方括號中的「#1」所示,這是自啓動以來的第一次Oops。每個Oops和此後發生的
+ 任何其他問題都可能是首個Oops的後續問題,即使這兩個問題看起來完全不相關。
+ 通過消除首個Oops的原因並在之後復現該問題,可以排除這種情況。有時僅僅
+ 重新啓動就足夠了,有時更改配置後重新啓動可以消除Oops。但是在這個流程中
+ 不要花費太多時間在這一點上,因爲引起Oops的原因可能已經在您稍後將按流程
+ 安裝的新Linux內核版本中修復了。
+
+ 2. 您的系統使用的軟體安裝了自己的內核模塊,例如Nvidia的專有圖形驅動程序或
+ VirtualBox。當內核從外部源(即使它們是開源的)加載此類模塊時,它會汙染
+ 自己:它們有時會在不相關的內核區域導致錯誤,從而可能導致您面臨的問題。
+ 因此,當您想要向Linux內核開發人員報告問題時,您必須阻止這些模塊加載。
+ 大多數情況下最簡單的方法是:臨時卸載這些軟體,包括它們可能已經安裝的任
+ 何模塊。之後重新啓動。
+
+ 3. 當內核加載駐留在Linux內核原始碼staging樹中的模塊時,它也會汙染自身。這
+ 是一個特殊的區域,代碼(主要是驅動程序)還沒有達到正常Linux內核的質量
+ 標準。當您報告此種模塊的問題時,內核受到汙染顯然是沒有問題的;只需確保
+ 問題模塊是造成汙染的唯一原因。如果問題發生在一個不相關的區域,重新啓動
+ 並通過指定 ``foo.blacklist=1`` 作爲內核參數臨時阻止該模塊被加載(用有
+ 問題的模塊名替換「foo」)。
+
+
+記錄如何重現問題
+------------------
+
+ *粗略地寫下如何重現這個問題。如果您同時處理多個問題,請爲每個問題單獨寫
+ 注釋,並確保它們在新啓動的系統上獨立出現。這是必要的,因爲每個問題都需
+ 要分別報告給內核開發人員,除非它們嚴重糾纏在一起。*
+
+如果你同時處理多個問題,必須分別報告每個問題,因爲它們可能由不同的開發人員
+處理。在一份報告中描述多種問題,也會讓其他人難以將其分開。因此只有在問題嚴
+重糾纏的情況下,才能將問題合併在一份報告中。
+
+此外,在報告過程中,你必須測試該問題是否發生在其他內核版本上。因此,如果您
+知道如何在一個新啓動的系統上快速重現問題,將使您的工作更加輕鬆。
+
+注意:報告只發生過一次的問題往往是沒有結果的,因爲它們可能是由於宇宙輻射導
+致的位翻轉。所以你應該嘗試通過重現問題來排除這種情況,然後再繼續。如果你有
+足夠的經驗來區分由於硬體故障引起的一次性錯誤和難以重現的罕見內核問題,可以
+忽略這個建議。
+
+
+穩定版或長期支持內核的回歸?
+-----------------------------
+
+ *如果您正面臨穩定版或長期支持版本線的回歸(例如從5.10.4更新到5.10.5時出現
+ 故障),請查看後文「報告穩定版和長期支持內核線的回歸」小節。*
+
+穩定版和長期支持內核版本線中的回歸是Linux開發人員非常希望解決的問題,這樣的
+問題甚至比主線開發分支中的回歸更不應出現,因爲它們會很快影響到很多人。開發人員
+希望儘快了解此類問題,因此有一個簡化流程來報告這些問題。注意,使用更新內核版
+本線的回歸(比如從5.9.15切換到5.10.5時出現故障)不符合條件。
+
+
+你需要將問題報告到何處
+------------------------
+
+ *定位可能引起問題的驅動程序或內核子系統。找出其開發人員期望的報告的方式
+ 和位置。注意:大多數情況下不會是bugzilla.kernel.org,因爲問題通常需要通
+ 過郵件發送給維護人員和公共郵件列表。*
+
+將報告發送給合適的人是至關重要的,因爲Linux內核是一個大項目,大多數開發人員
+只熟悉其中的一小部分。例如,相當多的程式設計師只關心一個驅動程序,比如一個WiFi
+晶片驅動程序;它的開發人員可能對疏遠的或不相關的「子系統」(如TCP堆棧、
+PCIe/PCI子系統、內存管理或文件系統)的內部知識了解很少或完全不了解。
+
+問題在於:Linux內核缺少一個,可以簡單地將問題歸檔並讓需要了解它的開發人員了
+解它的,中心化缺陷跟蹤器。這就是爲什麼你必須找到正確的途徑來自己報告問題。
+您可以在腳本的幫助下做到這一點(見下文),但它主要針對的是內核開發人員和專
+家。對於其他人來說,MAINTAINERS(維護人員)文件是更好的選擇。
+
+如何閱讀MAINTAINERS維護者文件
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+爲了說明如何使用 :ref:`MAINTAINERS <maintainers>` 文件,讓我們假設您的筆記
+本電腦中的WiFi在更新內核後突然出現了錯誤行爲。這種情況下可能是WiFi驅動的問
+題。顯然,它也可能由於驅動基於的某些代碼,但除非你懷疑有這樣的東西會附著在
+驅動程序上。如果真的是其他的問題,驅動程序的開發人員會讓合適的人參與進來。
+
+遺憾的是,沒有通用且簡單的辦法來檢查哪個代碼驅動了特定硬體組件。
+
+在WiFi驅動出現問題的情況下,你可能想查看 ``lspci -k`` 的輸出,因爲它列出了
+PCI/PCIe總線上的設備和驅動它的內核模塊::
+
+ [user@something ~]$ lspci -k
+ [...]
+ 3a:00.0 Network controller: Qualcomm Atheros QCA6174 802.11ac Wireless Network Adapter (rev 32)
+ Subsystem: Bigfoot Networks, Inc. Device 1535
+ Kernel driver in use: ath10k_pci
+ Kernel modules: ath10k_pci
+ [...]
+
+但如果你的WiFi晶片通過USB或其他內部總線連接,這種方法就行不通了。在這種情況
+下,您可能需要檢查您的WiFi管理器或 ``ip link`` 的輸出。尋找有問題的網絡接口
+的名稱,它可能類似於「wlp58s0」。此名稱可以用來找到驅動它的模塊::
+
+ [user@something ~]$ realpath --relative-to=/sys/module//sys/class/net/wlp58s0/device/driver/module
+ ath10k_pci
+
+如果這些技巧不能進一步幫助您,請嘗試在網上搜索如何縮小相關驅動程序或子系統
+的範圍。如果你不確定是哪一個:試著猜一下,即使你猜得不好,也會有人會幫助你
+的。
+
+一旦您知道了相應的驅動程序或子系統,您就希望在MAINTAINERS文件中搜索它。如果
+是「ath10k_pci」,您不會找到任何東西,因爲名稱太具體了。有時你需要在網上尋找
+幫助;但在此之前,請嘗試使用一個稍短或修改過的名稱來搜索MAINTAINERS文件,因
+爲這樣你可能會發現類似這樣的東西::
+
+ QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
+ Mail: A. Some Human <shuman@example.com>
+ Mailing list: ath10k@lists.infradead.org
+ Status: Supported
+ Web-page: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
+ SCM: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
+ Files: drivers/net/wireless/ath/ath10k/
+
+注意:如果您閱讀在Linux原始碼樹的根目錄中找到的原始維護者文件,則行描述將是
+縮寫。例如,「Mail:(郵件)」將是「M:」,「Mailing list:(郵件列表)」將是「L」,
+「Status:(狀態)」將是「S:」。此文件頂部有一段解釋了這些和其他縮寫。
+
+首先查看「Status」狀態行。理想情況下,它應該得到「Supported(支持)」或
+「Maintained(維護)」。如果狀態爲「Obsolete(過時的)」,那麼你在使用一些過時的
+方法,需要轉換到新的解決方案上。有時候,只有在感到有動力時,才會有人爲代碼
+提供「Odd Fixes」。如果碰見「Orphan」,你就完全不走運了,因爲再也沒有人關心代碼
+了,只剩下這些選項:準備好與問題共存,自己修復它,或者找一個願意修復它的程式設計師。
+
+檢查狀態後,尋找以「bug:」開頭的一行:它將告訴你在哪裡可以找到子系統特定的缺
+陷跟蹤器來提交你的問題。上面的例子沒有此行。大多數部分都是這樣,因爲 Linux
+內核的開發完全是由郵件驅動的。很少有子系統使用缺陷跟蹤器,且其中只有一部分
+依賴於 bugzilla.kernel.org。
+
+在這種以及其他很多情況下,你必須尋找以「Mail:」開頭的行。這些行提到了特定代碼
+的維護者的名字和電子郵件地址。也可以查找以「Mailing list:」開頭的行,它告訴你
+開發代碼的公共郵件列表。你的報告之後需要通過郵件發到這些地址。另外,對於所有
+通過電子郵件發送的問題報告,一定要抄送 Linux Kernel Mailing List(LKML)
+<linux-kernel@vger.kernel.org>。在以後通過郵件發送問題報告時,不要遺漏任何
+一個郵件列表!維護者都是大忙人,可能會把一些工作留給子系統特定列表上的其他開
+發者;而 LKML 很重要,因爲需要一個可以找到所有問題報告的地方。
+
+
+藉助腳本找到維護者
+~~~~~~~~~~~~~~~~~~~~
+
+對於手頭有Linux源碼的人來說,有第二個可以找到合適的報告地點的選擇:腳本
+「scripts/get_maintainer.pl」,它嘗試找到所有要聯繫的人。它會查詢MAINTAINERS
+文件,並需要用相關原始碼的路徑來調用。對於編譯成模塊的驅動程序,經常可以用
+這樣的命令找到::
+
+ $ modinfo ath10k_pci | grep filename | sed 's!/lib/modules/.*/kernel/!!; s!filename:!!; s!\.ko\(\|\.xz\)!!'
+ drivers/net/wireless/ath/ath10k/ath10k_pci.ko
+
+將其中的部分內容傳遞給腳本::
+
+ $ ./scripts/get_maintainer.pl -f drivers/net/wireless/ath/ath10k*
+ Some Human <shuman@example.com> (supporter:QUALCOMM ATHEROS ATH10K WIRELESS DRIVER)
+ Another S. Human <asomehuman@example.com> (maintainer:NETWORKING DRIVERS)
+ ath10k@lists.infradead.org (open list:QUALCOMM ATHEROS ATH10K WIRELESS DRIVER)
+ linux-wireless@vger.kernel.org (open list:NETWORKING DRIVERS (WIRELESS))
+ netdev@vger.kernel.org (open list:NETWORKING DRIVERS)
+ linux-kernel@vger.kernel.org (open list)
+
+不要把你的報告發給所有的人。發送給維護者,腳本稱之爲「supporter:」;另外抄送
+代碼最相關的郵件列表,以及 Linux 內核郵件列表(LKML)。在此例中,你需要將報
+告發送給 「Some Human <shuman@example.com>」 ,並抄送
+「ath10k@lists.infradead.org」和「linux-kernel@vger.kernel.org」。
+
+注意:如果你用 git 克隆了 Linux 原始碼,你可能需要用--git 再次調用
+get_maintainer.pl。腳本會查看提交歷史,以找到最近哪些人參與了相關代碼的編寫,
+因爲他們可能會提供幫助。但要小心使用這些結果,因爲它很容易讓你誤入歧途。
+例如,這種情況常常會發生在很少被修改的地方(比如老舊的或未維護的驅動程序):
+有時這樣的代碼會在樹級清理期間被根本不關心此驅動程序的開發者修改。
+
+
+搜索現有報告(第二部分)
+--------------------------
+
+ *在缺陷追蹤器或問題相關郵件列表的存檔中徹底搜索可能與您的問題匹配的報告。
+ 如果找到匹配的報告,請加入討論而不是發送新報告。*
+
+如前所述:報告一個別人已經提出的問題,對每個人來說都是浪費時間,尤其是作爲報告
+人的你。這就是爲什麼你應該再次搜索現有的報告。現在你已經知道問題需要報告到哪裡。
+如果是郵件列表,那麼一般在 `lore.kernel.org <https://lore.kernel.org/>`_ 可以
+找到相應存檔。
+
+但有些列表運行在其他地方。例如前面步驟中當例子的ath10k WiFi驅動程序就是這種
+情況。但是你通常可以在網上很容易地找到這些列表的檔案。例如搜索「archive
+ath10k@lists.infradead.org」,將引導您到ath10k郵件列表的信息頁,該頁面頂部連結
+到其 `列表存檔 <https://lists.infradead.org/pipermail/ath10k/>`_ 。遺憾的是,
+這個列表和其他一些列表缺乏搜索其存檔的功能。在這種情況下可以使用常規的網際網路
+搜尋引擎,並添加類似「site:lists.infadead.org/pipermail/ath10k/」這
+樣的搜索條件,這會把結果限制在該連結中的檔案。
+
+也請進一步搜索網絡、LKML和bugzilla.kernel.org網站。
+
+有關如何搜索以及在找到匹配報告時如何操作的詳細信息,請參閱上面的「搜索現有報告
+(第一部分)」。
+
+不要急著完成報告過程的這一步:花30到60分鐘甚至更多的時間可以爲你和其他人節省 /
+減少相當多的時間和麻煩。
+
+
+安裝一個新的內核進行測試
+--------------------------
+
+ *除非您已經在運行最新的「主線」Linux內核,否則最好在報告流程前安裝它。在
+ 某些情況下,使用最新的「穩定版」Linux進行測試和報告也是可以接受的替代方案;
+ 在合併窗口期間,這實際上可能是最好的方法,但在開發階段最好還是暫停幾天。
+ 無論你選擇什麼版本,最好使用「普通」構建。忽略這些建議會大大增加您的報告
+ 被拒絕或忽略的風險。*
+
+正如第一步的詳細解釋中所提到的:與大多數程式設計師一樣,與大多數程式設計師一樣,Linux
+內核開發人員不喜歡花時間處理他們維護的原始碼中根本不會發生的問題的報告。這隻
+會浪費每個人的時間,尤其是你的時間。這就是爲什麼在報告問題之前,您必須先確認
+問題仍然存在於最新的上游代碼中,這符合每個人的利益。您可以忽略此建議,但如前
+所述:這樣做會極大地增加問題報告被拒絕或被忽略的風險。
+
+內核「最新上游」的範圍通常指:
+
+ * 安裝一個主線內核;最新的穩定版內核也可以是一個選擇,但大多數時候都最好避免。
+ 長期支持內核(有時稱爲「LTS內核」)不適合此流程。下一小節將更詳細地解釋所有
+ 這些。
+
+ * 下一小節描述獲取和安裝這樣一個內核的方法。它還指出了使用預編譯內核是可以的,
+ 但普通的內核更好,這意味著:它是直接使用從 `kernel.org <https://kernel.org/>`_
+ 獲得的Linux原始碼構建並且沒有任何方式修改或增強。
+
+
+選擇適合測試的版本
+~~~~~~~~~~~~~~~~~~~~
+
+前往 `kernel.org <https://kernel.org/>`_ 來決定使用哪個版本。忽略那個寫著
+「Latest release最新版本」的巨大黃色按鈕,往下看有一個表格。在表格的頂部,你會
+看到一行以「mainline」開頭的字樣,大多數情況下它會指向一個版本號類似「5.8-rc2」
+的預發布版本。如果是這樣的話,你將需要使用這個主線內核進行測試。不要讓「rc」
+嚇到你,這些「開發版內核」實際上非常可靠——而且你已經按照上面的指示做了備份,
+不是嗎?
+
+大概每九到十周,「mainline」可能會給你指出一個版本號類似「5.7」的正式版本。如果
+碰見這種情況,請考慮暫停報告過程,直到下一個版本的第一個預發布(5.8-rc1)出
+現在 `kernel.org <https://kernel.org/>`_ 上。這是因爲 Linux 的開發周期正在
+兩周的「合併窗口」內。大部分的改動和所有干擾性的改動都會在這段時間內被合併到
+下一個版本中。在此期間使用主線是比較危險的。內核開發者通常也很忙,可能沒有
+多餘的時間來處理問題報告。這也是很有可能在合併窗口中應用了許多修改來修復你
+所面臨的問題;這就是爲什麼你很快就得用一個新的內核版本重新測試,就像下面「發
+布報告後的責任」一節中所述的那樣。
+
+這就是爲什麼要等到合併窗口結束後才去做。但是如果你處理的是一些不應該等待的
+東西,則無需這樣做。在這種情況下,可以考慮通過 git 獲取最新的主線內核(見下
+文),或者使用 kernel.org 上提供的最新穩定版本。如果 mainline 因爲某些原因
+不無法正常工作,那麼使用它也是可以接受的。總的來說:用它來重現問題也比完全
+不報告問題要好。
+
+最好避免在合併窗口外使用最新的穩定版內核,因爲所有修復都必須首先應用於主線。
+這就是爲什麼檢查最新的主線內核是如此重要:你希望看到在舊版本線修復的任何問題
+需要先在主線修復,然後才能得到回傳,這可能需要幾天或幾周。另一個原因是:您
+希望的修復對於回傳來說可能太難或太冒險;因此再次報告問題不太可能改變任何事情。
+
+這些方面也部分表明了爲什麼長期支持內核(有時稱爲「LTS內核」)不適合報告流程:
+它們與當前代碼的距離太遠。因此,先去測試主線,然後再按流程走:如果主線沒有
+出現問題,流程將指導您如何在舊版本線中修復它。
+
+如何獲得新的 Linux 內核
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+你可以使用預編譯或自編譯的內核進行測試;如果你選擇後者,可以使用 git 獲取源
+代碼,或者下載其 tar 存檔包。
+
+**使用預編譯的內核** :這往往是最快速、最簡單、最安全的方法——尤其是在你不熟
+悉 Linux 內核的情況下。問題是:發行商或附加存儲庫提供的大多數版本都是從修改
+過的Linux原始碼構建的。因此它們不是普通的,通常不適合於測試和問題報告:這些
+更改可能會導致您面臨的問題或以某種方式影響問題。
+
+但是如果您使用的是流行的Linux發行版,那麼您就很幸運了:對於大部分的發行版,
+您可以在網上找到包含最新主線或穩定版本Linux內核包的存儲庫。使用這些是完全可
+以的,只要從存儲庫的描述中確認它們是普通的或者至少接近普通。此外,請確保軟體
+包包含kernel.org上提供的最新版本內核。如果這些軟體包的時間超過一周,那麼它們
+可能就不合適了,因爲新的主線和穩定版內核通常至少每周發布一次。
+
+請注意,您以後可能需要手動構建自己的內核:有時這是調試或測試修復程序所必需的,
+如後文所述。還要注意,預編譯的內核可能缺少在出現panic、Oops、warning或BUG時
+解碼內核列印的消息所需的調試符號;如果您計劃解碼這些消息,最好自己編譯內核
+(有關詳細信息,請參閱本小節結尾和「解碼失敗信息」小節)。
+
+**使用git** :熟悉 git 的開發者和有經驗的 Linux 用戶通常最好直接從
+`kernel.org 上的官方開發倉庫
+<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/>`_
+中獲取最新的 Linux 內核原始碼。這些很可能比最新的主線預發布版本更新一些。不
+用擔心:它們和正式的預發布版本一樣可靠,除非內核的開發周期目前正處於合併窗
+口中。不過即便如此,它們也是相當可靠的。
+
+**常規方法** :不熟悉 git 的人通常最好從 `kernel.org <https://kernel.org/>`_
+下載源碼的tar 存檔包。
+
+如何實際構建一個內核並不在這裡描述,因爲許多網站已經解釋了必要的步驟。如果
+你是新手,可以考慮按照那些建議使用 ``make localmodconfig`` 來做,它將嘗試獲
+取你當前內核的配置,然後根據你的系統進行一些調整。這樣做並不能使編譯出來的
+內核更好,但可以更快地編譯。
+
+注意:如果您正在處理來自內核的pannc、Oops、warning或BUG,請在配置內核時嘗試
+啓用 CONFIG_KALLSYMS 選項。此外,還可以啓用 CONFIG_DEBUG_KERNEL 和
+CONFIG_DEBUG_INFO;後者是相關選項,但只有啓用前者才能開啓。請注意,
+CONFIG_DEBUG_INFO 會需要更多儲存空間來構建內核。但這是值得的,因爲這些選項將
+允許您稍後精確定位觸發問題的確切代碼行。下面的「解碼失敗信息」一節對此進行了更
+詳細的解釋。
+
+但請記住:始終記錄遇到的問題,以防難以重現。發送未解碼的報告總比不報告要好。
+
+
+檢查「汙染」標誌
+----------------
+
+ *確保您剛剛安裝的內核在運行時不會「汙染」自己。*
+
+正如上面已經詳細介紹過的:當發生一些可能會導致一些看起來完全不相關的後續錯
+誤的事情時,內核會設置一個「汙染」標誌。這就是爲什麼你需要檢查你剛剛安裝的內
+核是否有設置此標誌。如果有的話,幾乎在任何情況下你都需要在報告問題之前先消
+除它。詳細的操作方法請看上面的章節。
+
+
+用新內核重現問題
+------------------
+
+ *在您剛剛安裝的內核中復現這個問題。如果它沒有出現,請查看下方只發生在
+ 穩定版和長期支持內核的問題的說明。*
+
+檢查這個問題是否發生在你剛剛安裝的新 Linux 內核版本上。如果新內核已經修復了,
+可以考慮使用此版本線,放棄報告問題。但是請記住,只要它沒有在 `kernel.org
+<https://kernel.org/>`_ 的穩定版和長期版(以及由這些版本衍生出來的廠商內核)
+中得到修復,其他用戶可能仍然會受到它的困擾。如果你喜歡使用其中的一個,或
+者只是想幫助它們的用戶,請前往下面的「報告只發生在較舊內核版本線的問題」一節。
+
+
+優化復現問題的描述
+--------------------
+
+ *優化你的筆記:試著找到並寫出最直接的復現問題的方法。確保最終結果包含所
+ 有重要的細節,同時讓第一次聽說的人容易閱讀和理解。如果您在此過程中學到
+ 了一些東西,請考慮再次搜索關於該問題的現有報告。*
+
+過於複雜的報告會讓別人很難理解。因此請儘量找到一個可以直接描述、易於以書面
+形式理解的再現方法。包含所有重要的細節,但同時也要儘量保持簡短。
+
+在這在前面的步驟中,你很可能已經了解了一些關於你所面臨的問題的點。利用這些
+知識,再次搜索可以轉而加入的現有報告。
+
+
+解碼失敗信息
+-------------
+
+ *如果失敗涉及「panic」、「Oops」、「warning」或「BUG」,請考慮解碼內核日誌以查找
+ 觸發錯誤的代碼行。*
+
+當內核檢測到內部問題時,它會記錄一些有關已執行代碼的信息。這使得在原始碼中精
+確定位觸發問題的行並顯示如何調用它成爲可能。但只有在配置內核時啓用了
+CONFIG_DEBUG_INFO 和 CONFIG_KALLSYMS選項時,這種方法才起效。如果已啓用此選項,
+請考慮解碼內核日誌中的信息。這將使我們更容易理解是什麼導致了「panic」、「Oops」、
+「warning」或「BUG」,從而增加了有人提供修復的機率。
+
+解碼可以通過Linux原始碼樹中的腳本來完成。如果您運行的內核是之前自己編譯的,
+這樣這樣調用它::
+
+ [user@something ~]$ sudo dmesg | ./linux-5.10.5/scripts/decode_stacktrace.sh ./linux-5.10.5/vmlinux
+ /usr/lib/debug/lib/modules/5.10.10-4.1.x86_64/vmlinux /usr/src/kernels/5.10.10-4.1.x86_64/
+
+如果您運行的是打包好的普通內核,則可能需要安裝帶有調試符號的相應包。然後按以下
+方式調用腳本(如果發行版未打包,則可能需要從Linux原始碼獲取)::
+
+ [user@something ~]$ sudo dmesg | ./linux-5.10.5/scripts/decode_stacktrace.sh \
+ /usr/lib/debug/lib/modules/5.10.10-4.1.x86_64/vmlinux /usr/src/kernels/5.10.10-4.1.x86_64/
+
+腳本將解碼如下的日誌行,這些日誌行顯示內核在發生錯誤時正在執行的代碼的地址::
+
+ [ 68.387301] RIP: 0010:test_module_init+0x5/0xffa [test_module]
+
+解碼之後,這些行將變成這樣::
+
+ [ 68.387301] RIP: 0010:test_module_init (/home/username/linux-5.10.5/test-module/test-module.c:16) test_module
+
+在本例中,執行的代碼是從文件「~/linux-5.10.5/test-module/test-module.c」構建的,
+錯誤出現在第16行的指令中。
+
+該腳本也會如此解碼以「Call trace」開頭的部分中提到的地址,該部分顯示出現問題的
+函數的路徑。此外,腳本還會顯示內核正在執行的代碼部分的彙編輸出。
+
+注意,如果你沒法做到這一點,只需跳過這一步,並在報告中說明原因。如果你幸運的
+話,可能無需解碼。如果需要的話,也許有人會幫你做這件事情。還要注意,這只是解
+碼內核堆棧跟蹤的幾種方法之一。有時需要採取不同的步驟來檢索相關的詳細信息。
+別擔心,如果您碰到的情況需要這樣做,開發人員會告訴您該怎麼做。
+
+
+對回歸的特別關照
+-----------------
+
+ *如果您的問題是回歸問題,請儘可能縮小引入問題時的範圍。*
+
+Linux 首席開發者 Linus Torvalds 認爲 Linux 內核永遠不應惡化,這就是爲什麼他
+認爲回歸是不可接受的,並希望看到它們被迅速修復。這就是爲什麼引入了回歸的改
+動導致的問題若無法通過其他方式快速解決,通常會被迅速撤銷。因此,報告回歸有
+點像「王炸」,會迅速得到修復。但要做到這一點,需要知道導致回歸的變化。通常情
+況下,要由報告者來追查罪魁禍首,因爲維護者往往沒有時間或手頭設置不便來自行
+重現它。
+
+有一個叫做「二分」的過程可以來尋找變化,這在
+「Documentation/translations/zh_TW/admin-guide/bug-bisect.rst」文檔中進行了詳細
+的描述,這個過程通常需要你構建十到二十個內核鏡像,每次都嘗試在構建下一個鏡像
+之前重現問題。是的,這需要花費一些時間,但不用擔心,它比大多數人想像的要快得多。
+多虧了「binary search二進位搜索」,這將引導你在原始碼管理系統中找到導致回歸的提交。
+一旦你找到它,就在網上搜索其主題、提交ID和縮短的提交ID(提交ID的前12個字符)。
+如果有的話,這將引導您找到關於它的現有報告。
+
+需要注意的是,二分法需要一點竅門,不是每個人都懂得訣竅,也需要相當多的努力,
+不是每個人都願意投入。儘管如此,還是強烈建議自己進行一次二分。如果你真的
+不能或者不想走這條路,至少要找出是哪個主線內核引入的回歸。比如說從 5.5.15
+切換到 5.8.4 的時候出現了一些問題,那麼至少可以嘗試一下相近的所有的主線版本
+(5.6、5.7 和 5.8)來檢查它是什麼時候出現的。除非你想在一個穩定版或長期支持
+內核中找到一個回歸,否則要避免測試那些編號有三段的版本(5.6.12、5.7.8),因
+爲那會使結果難以解釋,可能會讓你的測試變得無用。一旦你找到了引入回歸的主要
+版本,就可以放心地繼續報告了。但請記住:在不知道罪魁禍首的情況下,開發人員
+是否能夠提供幫助取決於手頭的問題。有時他們可能會從報告中確認是什麼出現了問
+題,並能修復它;有時他們可能無法提供幫助,除非你進行二分。
+
+當處理回歸問題時,請確保你所面臨的問題真的是由內核引起的,而不是由其他東西
+引起的,如上文所述。
+
+在整個過程中,請記住:只有當舊內核和新內核的配置相似時,問題才算回歸。最好
+的方法是:把配置文件(``.config``)從舊的工作內核直接複製到你嘗試的每個新內
+核版本。之後運行 ``make oldnoconfig`` 來調整它以適應新版本的需要,而不啓用
+任何新的功能,因爲那些功能也可能導致回歸。
+
+
+撰寫並發送報告
+---------------
+
+ *通過詳細描述問題來開始編寫報告。記得包括以下條目:您爲復現而安裝的最新
+ 內核版本、使用的Linux發行版以及關於如何復現該問題的說明。如果可能,將內
+ 核構建配置(.config)和 ``dmesg`` 的輸出放在網上的某個地方,並連結到它。
+ 包含或上傳所有其他可能相關的信息,如Oops的輸出/截圖或來自 ``lspci``
+ 的輸出。一旦你寫完了這個主要部分,請在上方插入一個正常長度的段落快速概
+ 述問題和影響。再在此之上添加一個簡單描述問題的句子,以得到人們的閱讀。
+ 現在給出一個更短的描述性標題或主題。然後就可以像MAINTAINERS文件告訴你的
+ 那樣發送或提交報告了,除非你在處理一個「高優先級問題」:它們需要按照下面
+ 「高優先級問題的特殊處理」所述特別關照。*
+
+現在你已經準備好了一切,是時候寫你的報告了。上文前言中連結的三篇文檔對如何
+寫報告做了部分解釋。這就是爲什麼本文將只提到一些基本的內容以及 Linux 內核特
+有的東西。
+
+有一點是符合這兩類的:你的報告中最關鍵的部分是標題/主題、第一句話和第一段。
+開發者經常會收到許多郵件。因此,他們往往只是花幾秒鐘的時間瀏覽一下郵件,然
+後再決定繼續下一封或仔細查看。因此,你報告的開頭越好,有人研究並幫助你的機
+會就越大。這就是爲什麼你應該暫時忽略他們,先寫出詳細的報告。;-)
+
+每份報告都應提及的事項
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+詳細描述你的問題是如何發生在你安裝的新純淨內核上的。試著包含你之前寫的和優
+化過的分步說明,概述你和其他人如何重現這個問題;在極少數無法重現的情況下,
+儘量描述你做了什麼來觸發它。
+
+還應包括其他人爲了解該問題及其環境而可能需要的所有相關信息。實際需要的東西
+在很大程度上取決於具體問題,但有些事項你總是應該包括在內:
+
+ * ``cat /proc/version`` 的輸出,其中包含 Linux 內核版本號和構建時的編譯器。
+
+ * 機器正在運行的 Linux 發行版( ``hostnamectl | grep 「Operating System「`` )
+
+ * CPU 和作業系統的架構( ``uname -mi`` )
+
+ * 如果您正在處理回歸,並進行了二分,請提及導致回歸的變更的主題和提交ID。
+
+許多情況下,讓讀你報告的人多了解兩件事也是明智之舉:
+
+ * 用於構建 Linux 內核的配置(「.config」文件)
+
+ * 內核的信息,你從 ``dmesg`` 得到的信息寫到一個文件里。確保它以像「Linux
+ version 5.8-1 (foobar@example.com) (gcc (GCC) 10.2.1, GNU ld version
+ 2.34) #1 SMP Mon Aug 3 14:54:37 UTC 2020」這樣的行開始,如果沒有,那麼第
+ 一次啓動階段的重要信息已經被丟棄了。在這種情況下,可以考慮使用
+ ``journalctl -b 0 -k`` ;或者你也可以重啓,重現這個問題,然後調用
+ ``dmesg`` 。
+
+這兩個文件很大,所以直接把它們放到你的報告中是個壞主意。如果你是在缺陷跟蹤
+器中提交問題,那麼將它們附加到工單中。如果你通過郵件報告問題,不要用附件附
+上它們,因爲那會使郵件變得太大,可以按下列之一做:
+
+ * 將文件上傳到某個公開的地方(你的網站,公共文件粘貼服務,在
+ `bugzilla.kernel.org <https://bugzilla.kernel.org/>`_ 上創建的工單……),
+ 並在你的報告中放上連結。理想情況下請使用允許這些文件保存很多年的地方,因
+ 爲它們可能在很多年後對別人有用;例如 5 年或 10 年後,一個開發者正在修改
+ 一些代碼,而這些代碼正是爲了修復你的問題。
+
+ * 把文件放在一邊,然後說明你會在他人回復時再單獨發送。只要記得報告發出去後,
+ 真正做到這一點就可以了。;-)
+
+提供這些東西可能是明智的
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+根據問題的不同,你可能需要提供更多的背景數據。這裡有一些關於提供什麼比較好
+的建議:
+
+ * 如果你處理的是內核的「warning」、「OOPS」或「panic」,請包含它。如果你不能複製
+ 粘貼它,試著用netconsole網絡終端遠程跟蹤或者至少拍一張屏幕的照片。
+
+ * 如果問題可能與你的電腦硬體有關,請說明你使用的是什麼系統。例如,如果你的
+ 顯卡有問題,請提及它的製造商,顯卡的型號,以及使用的晶片。如果是筆記本電
+ 腦,請提及它的型號名稱,但儘量確保意義明確。例如「戴爾 XPS 13」就不很明確,
+ 因爲它可能是 2012 年的那款,那款除了看起來和現在銷售的沒有什麼不同之外,
+ 兩者沒有任何共同之處。因此,在這種情況下,要加上準確的型號,例如 2019
+ 年內推出的 XPS 13 型號爲「9380」或「7390」。像「聯想 Thinkpad T590」這樣的名字
+ 也有些含糊不清:這款筆記本有帶獨立顯卡和不帶的子型號,所以要儘量找到準確
+ 的型號名稱或註明主要部件。
+
+ * 說明正在使用的相關軟體。如果你在加載模塊時遇到了問題,你要說明正在使用的
+ kmod、systemd 和 udev 的版本。如果其中一個 DRM 驅動出現問題,你要說明
+ libdrm 和 Mesa 的版本;還要說明你的 Wayland 合成器或 X-Server 及其驅動。
+ 如果你有文件系統問題,請註明相應的文件系統實用程序的版本(e2fsprogs,
+ btrfs-progs, xfsprogs……)。
+
+ * 從內核中收集可能有用的額外信息。例如, ``lspci -nn`` 的輸出可以幫助別人
+ 識別你使用的硬體。如果你的硬體有問題,你甚至可以給出 ``sudo lspci -vvv``
+ 的結果,因爲它提供了組件是如何配置的信息。對於一些問題,可能最好包含
+ ``/proc/cpuinfo`` , ``/proc/ioports`` , ``/proc/iomem`` ,
+ ``/proc/modules`` 或 ``/proc/scsi/scsi`` 等文件的內容。一些子系統還提
+ 供了收集相關信息的工具。 ``alsa-info.sh`` `就是這樣一個工具,它是音頻/聲
+ 音子系統開發者提供的 <https://www.alsa-project.org/wiki/AlsaInfo>`_ 。
+
+這些例子應該會給你一些知識點,讓你知道附上什麼數據可能是明智的,但你自己也
+要想一想,哪些數據對別人會有幫助。不要太擔心忘記一些東西,因爲開發人員會要
+求提供他們需要的額外細節。但從一開始就把所有重要的東西都提供出來,會增加別
+人仔細查看的機會。
+
+
+重要部分:報告的開頭
+~~~~~~~~~~~~~~~~~~~~~~
+
+現在你已經準備好了報告的詳細部分,讓我們進入最重要的部分:開頭幾句。現在到
+報告的最前面,在你剛才寫的部分之前加上類似「The detailed description:」(詳細
+描述)這樣的內容,並在最前面插入兩個新行。現在寫一個正常長度的段落,大致概
+述這個問題。去掉所有枯燥的細節,把重點放在讀者需要知道的關鍵部分,以讓人了
+解這是怎麼回事;如果你認爲這個缺陷影響了很多用戶,就提一下這點來吸引大家關
+注。
+
+做好這一點後,在頂部再插入兩行,寫一句話的摘要,快速解釋報告的內容。之後你
+要更加抽象,爲報告寫一個更短的主題/標題。
+
+現在你已經寫好了這部分,請花點時間來優化它,因爲它是你的報告中最重要的部分:
+很多人會先讀這部分,然後才會決定是否值得花時間閱讀其他部分。
+
+現在就像 :ref:`MAINTAINERS <maintainers>` 維護者文件告訴你的那樣發送或提交
+報告,除非它是前面概述的那些「高優先級問題」之一:在這種情況下,請先閱讀下一
+小節,然後再發送報告。
+
+高優先級問題的特殊處理
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+高優先級問題的報告需要特殊處理。
+
+**非常嚴重的缺陷** :確保在主題或工單標題以及第一段中明顯標出 severeness
+(非常嚴重的)。
+
+**回歸** :如果問題是一個回歸,請在郵件的主題或缺陷跟蹤器的標題中添加
+[REGRESSION]。如果您沒有進行二分,請至少註明您測試的最新主線版本(比如 5.7)
+和出現問題的最新版本(比如 5.8)。如果您成功地進行了二分,請註明導致回歸
+的提交ID和主題。也請添加該變更的作者到你的報告中;如果您需要將您的缺陷提交
+到缺陷跟蹤器中,請將報告以私人郵件的形式轉發給他,並註明報告提交地點。
+
+**安全問題** :對於這種問題,你將必須評估:如果細節被公開披露,是否會對其他
+用戶產生短期風險。如果不會,只需按照所述繼續報告問題。如果有此風險,你需要
+稍微調整一下報告流程。
+
+ * 如果 MAINTAINERS 文件指示您通過郵件報告問題,請不要抄送任何公共郵件列表。
+
+ * 如果你應該在缺陷跟蹤器中提交問題,請確保將工單標記爲「私有」或「安全問題」。
+ 如果缺陷跟蹤器沒有提供保持報告私密性的方法,那就別想了,把你的報告以私人
+ 郵件的形式發送給維護者吧。
+
+在這兩種情況下,都一定要將報告發到 MAINTAINERS 文件中「安全聯絡」部分列出的
+地址。理想的情況是在發送報告的時候直接抄送他們。如果您在缺陷跟蹤器中提交了
+報告,請將報告的文本轉發到這些地址;但請在報告的頂部加上注釋,表明您提交了
+報告,並附上工單連結。
+
+更多信息請參見「Documentation/translations/zh_TW/admin-guide/security-bugs.rst」。
+
+
+發布報告後的責任
+------------------
+
+ *等待別人的反應,繼續推進事情,直到你能夠接受這樣或那樣的結果。因此,請
+ 公開和及時地回應任何詢問。測試提出的修復。積極地測試:至少重新測試每個
+ 新主線版本的首個候選版本(RC),並報告你的結果。如果出現拖延,就友好地
+ 提醒一下。如果你沒有得到任何幫助或者未能滿意,請試著自己幫助自己。*
+
+如果你的報告非常優秀,而且你真的很幸運,那麼某個開發者可能會立即發現導致問
+題的原因;然後他們可能會寫一個補丁來修復、測試它,並直接發送給主線集成,同
+時標記它以便以後回溯到需要它的穩定版和長期支持內核。那麼你需要做的就是回復
+一句「Thank you very much」(非常感謝),然後在發布後換上修復好的版本。
+
+但這種理想狀況很少發生。這就是爲什麼你把報告拿出來之後工作才開始。你要做的
+事情要視情況而定,但通常會是下面列出的事情。但在深入研究細節之前,這裡有幾
+件重要的事情,你需要記住這部分的過程。
+
+
+關於進一步互動的一般建議
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**總是公開回復** :當你在缺陷跟蹤器中提交問題時,一定要在那裡回復,不要私下
+聯繫任何開發者。對於郵件報告,在回復您收到的任何郵件時,總是使用「全部回復」
+功能。這包括帶有任何你可能想要添加到你的報告中的額外數據的郵件:進入郵件應
+用程序「已發送」文件夾,並在郵件上使用「全部回復」來回復報告。這種方法可以確保
+公共郵件列表和其他所有參與者都能及時了解情況;它還能保持郵件線程的完整性,
+這對於郵件列表將所有相關郵件歸爲一類是非常重要的。
+
+只有兩種情況不適合在缺陷跟蹤器或「全部回復」中發表評論:
+
+ * 有人讓你私下發東西。
+
+ * 你被告知要發送一些東西,但注意到其中包含需要保密的敏感信息。在這種情況下,
+ 可以私下發送給要求發送的開發者。但要在工單或郵件中註明你是這麼做的,這
+ 樣其他人就知道你尊重了這個要求。
+
+**在請求解釋或幫助之前先研究一下** :在這部分過程中,有人可能會告訴你用尚未
+掌握的技能做一些事情。例如你可能會被要求使用一些你從未聽說過的測試工具;或
+者你可能會被要求在 Linux 內核原始碼上應用一個補丁來測試它是否有幫助。在某些
+情況下,發個回復詢問如何做就可以了。但在走這條路之前,儘量通過在網際網路上搜
+索自行找到答案;或者考慮在其他地方詢問建議。比如詢問朋友,或者到你平時常去
+的聊天室或論壇發帖諮詢。
+
+**要有耐心** :如果你真的很幸運,你可能會在幾個小時內收到對你的報告的答覆。
+但大多數情況下會花費更多的時間,因爲維護者分散在全球各地,因此可能在不同的
+時區——在那裡他們已經享受著遠離鍵盤的夜晚。
+
+一般來說,內核開發者需要一到五個工作日來回復報告。有時會花費更長的時間,因
+爲他們可能正忙於合併窗口、其他工作、參加開發者會議,或者只是在享受一個漫長
+的暑假。
+
+「高優先級的問題」(見上面的解釋)例外:維護者應該儘快解決這些問題;這就是爲
+什麼你應該最多等待一個星期(如果是緊急的事情,則只需兩天),然後再發送友好
+的提醒。
+
+有時維護者可能沒有及時回復;有時候可能會出現分歧,例如一個問題是否符合回歸
+的條件。在這種情況下,在郵件列表上提出你的顧慮,並請求其他人公開或私下回復
+如何繼續推進。如果失敗了,可能應該讓更高級別的維護者介入。如果是 WiFi 驅動,
+那就是無線維護者;如果沒有更高級別的維護者,或者其他一切努力都失敗了,那
+這可能是一種罕見的、可以讓 Linus Torvalds 參與進來的情況。
+
+**主動測試** :每當一個新的主線內核版本的第一個預發布版本(rc1)發布的時候,
+去檢查一下這個問題是否得到了解決,或者是否有什麼重要的變化。在工單中或在
+回復報告的郵件中提及結果(確保所有參與討論的人都被抄送)。這將表明你的承諾
+和你願意幫忙。如果問題持續存在,它也會提醒開發者確保他們不會忘記它。其他一
+些不定期的重新測試(例如用rc3、rc5 和最終版本)也是一個好主意,但只有在相關
+的東西發生變化或者你正在寫什麼東西的時候才報告你的結果。
+
+這些些常規的事情就不說了,我們來談談報告後如何幫助解決問題的細節。
+
+查詢和測試請求
+~~~~~~~~~~~~~~~
+
+如果你的報告得到了回復則需履行以下責任:
+
+**檢查與你打交道的人** :大多數情況下,會是維護者或特定代碼區域的開發人員對
+你的報告做出回應。但由於問題通常是公開報告的,所以回復的可能是任何人——包括
+那些想要幫忙的人,但最後可能會用他們的問題或請求引導你完全偏離軌道。這很少
+發生,但這是快速上網搜搜看你正在與誰互動是明智之舉的許多原因之一。通過這樣
+做,你也可以知道你的報告是否被正確的人聽到,因爲如果討論沒有導致滿意的問題
+解決方案而淡出,之後可能需要提醒維護者(見下文)。
+
+**查詢數據** :通常你會被要求測試一些東西或提供更多細節。儘快提供所要求的信
+息,因爲你已經得到了可能會幫助你的人的注意,你等待的時間越長就有越可能失去
+關注;如果你不在數個工作日內提供信息,甚至可能出現這種結果。
+
+**測試請求** :當你被要求測試一個診斷補丁或可能的修復時,也要儘量及時測試。
+但要做得恰當,一定不要急於求成:混淆事情很容易發生,這會給所有人帶來許多困
+惑。例如一個常見的錯誤是以爲應用了一個帶修復的建議補丁,但事實上並沒有。即
+使是有經驗的測試人員也會偶爾發生這樣的事情,但當有修復的內核和沒有修復的內
+核表現得一樣時,他們大多時候會注意到。
+
+當沒有任何實質性進展時該怎麼辦
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+有些報告不會得到負有相關責任的 Linux 內核開發者的任何反應;或者圍繞這個問題
+的討論有所發展,但漸漸淡出,沒有任何實質內容產出。
+
+在這種情況下,要等兩個星期(最好是三個星期)後再發出友好的提醒:也許當你的
+報告到達時,維護者剛剛離開鍵盤一段時間,或者有更重要的事情要處理。在寫提醒
+信的時候,要善意地問一下,是否還需要你這邊提供什麼來讓事情推進下去。如果報
+告是通過郵件發出來的,那就在郵件的第一行回覆你的初始郵件(見上文),其中包
+括下方的原始報告的完整引用:這是少數幾種情況下,這樣的「TOFU」(Text Over,
+Fullquote Under文字在上,完整引用在下)是正確的做法,因爲這樣所有的收件人都
+會以適當的順序立即讓細節到手頭上來。
+
+在提醒之後,再等三周的回覆。如果你仍然沒有得到適當的反饋,你首先應該重新考
+慮你的方法。你是否可能嘗試接觸了錯誤的人?是不是報告也許令人反感或者太混亂,
+以至於人們決定完全遠離它?排除這些因素的最好方法是:把報告給一兩個熟悉
+FLOSS 問題報告的人看,詢問他們的意見。同時徵求他們關於如何繼續推進的建議。
+這可能意味著:準備一份更好的報告,讓這些人在你發出去之前對它進行審查。這樣
+的方法完全可以;只需說明這是關於這個問題的第二份改進的報告,並附上第一份報
+告的連結。
+
+如果報告是恰當的,你可以發送第二封提醒信;在其中詢問爲什麼報告沒有得到任何
+回復。第二封提醒郵件的好時機是在新 Linux 內核版本的首個預發布版本('rc1')
+發布後不久,因爲無論如何你都應該在那個時候重新測試並提供狀態更新(見上文)。
+
+如果第二次提醒的結果又在一周內沒有任何反應,可以嘗試聯繫上級維護者詢問意見:
+即使再忙的維護者在這時候也至少應該發過某種確認。
+
+記住要做好失望的準備:理想狀況下維護者最好對每一個問題報告做出回應,但他們
+只有義務解決之前列出的「高優先級問題」。所以,如果你得到的回覆是「謝謝你的報告,
+我目前有更重要的問題要處理,在可預見的未來沒有時間去研究這個問題」,那請不
+要太沮喪。
+
+也有可能在缺陷跟蹤器或列表中進行了一些討論之後,什麼都沒有發生,提醒也無助
+於激勵大家進行修復。這種情況可能是毀滅性的,但在 Linux 內核開發中確實會發生。
+這些和其他得不到幫助的原因在本文結尾處的「爲什麼有些問題在被報告後沒有得到
+任何回應或者仍然沒有修復」中進行了解釋。
+
+如果你沒有得到任何幫助或問題最終沒有得到解決,不要沮喪:Linux 內核是 FLOSS,
+因此你仍然可以自己幫助自己。例如,你可以試著找到其他受影響的人,和他們一
+起合作來解決這個問題。這樣的團隊可以一起準備一份新的報告,提到團隊有多少人,
+爲什麼你們認爲這是應該得到解決的事情。也許你們還可以一起縮小確切原因或引
+入回歸的變化,這往往會使修復更容易。而且如果運氣好的話,團隊中可能會有懂點
+編程的人,也許能寫出一個修複方案。
+
+
+
+「報告穩定版和長期支持內核線的回歸」的參考
+------------------------------------------
+
+本小節提供了在穩定版和長期支持內核線中面對回歸時需要執行的步驟的詳細信息。
+
+確保特定版本線仍然受支持
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ *檢查內核開發人員是否仍然維護你關心的Linux內核版本線:去 kernel.org 的
+ 首頁,確保此特定版本線的最新版沒有「[EOL]」標記。*
+
+大多數內核版本線只支持三個月左右,因爲延長維護時間會帶來相當多的工作。因此,
+每年只會選擇一個版本來支持至少兩年(通常是六年)。這就是爲什麼你需要檢查
+內核開發者是否還支持你關心的版本線。
+
+注意,如果 `kernel.org <https://kernel.org/>`_ 在首頁上列出了兩個「穩定」版本,
+你應該考慮切換到較新的版本,而忘掉較舊的版本:對它的支持可能很快就會結束。
+然後,它將被標記爲「生命周期結束」(EOL)。達到這個程度的版本線仍然會在
+`kernel.org <https://kernel.org/>`_ 首頁上被顯示一兩周,但不適合用於測試和
+報告。
+
+搜索穩定版郵件列表
+~~~~~~~~~~~~~~~~~~~
+
+ *檢查Linux穩定版郵件列表中的現有報告。*
+
+也許你所面臨的問題已經被發現,並且已經或即將被修復。因此,請在 `Linux 穩定
+版郵件列表的檔案 <https://lore.kernel.org/stable/>`_ 中搜索類似問題的報告。
+如果你找到任何匹配的問題,可以考慮加入討論,除非修復工作已經完成並計劃很快
+得到應用。
+
+用最新版本復現問題
+~~~~~~~~~~~~~~~~~~~
+
+ *從特定的版本線安裝最新版本作爲純淨內核。確保這個內核沒有被汙染,並且仍
+ 然存在問題,因爲問題可能已經在那裡被修復了。*
+
+在投入更多時間到這個過程中之前,你要檢查這個問題是否在你關注的版本線的最新
+版本中已經得到了修復。這個內核需要是純淨的,在問題發生之前不應該被汙染,正
+如上面已經在測試主線的過程中詳細介紹過的一樣。
+
+您是否是第一次注意到供應商內核的回歸?供應商的更改可能會發生變化。你需要重新
+檢查排除來這個問題。當您從5.10.4-vendor.42更新到5.10.5-vendor.43時,記錄損壞
+的信息。然後在測試了前一段中所述的最新5.10版本之後,檢查Linux 5.10.4的普通版本
+是否也可以正常工作。如果問題在那裡出現,那就不符合上游回歸的條件,您需要切換
+回主逐步指南來報告問題。
+
+報告回歸
+~~~~~~~~~~
+
+ *向Linux穩定版郵件列表發送一個簡短的問題報告(stable@vger.kernel.org)。
+ 大致描述問題,並解釋如何復現。講清楚首個出現問題的版本和最後一個工作正常
+ 的版本。然後等待進一步的指示。*
+
+當報告在穩定版或長期支持內核線內發生的回歸(例如在從5.10.4更新到5.10.5時),
+一份簡短的報告足以快速報告問題。因此只需要粗略的描述。
+
+但是請注意,如果您能夠指明引入問題的確切版本,這將對開發人員有很大幫助。因此
+如果有時間的話,請嘗試使用普通內核找到該版本。讓我們假設發行版發布Linux內核
+5.10.5到5.10.8的更新時發生了故障。那麼按照上面的指示,去檢查該版本線中的最新
+內核,比如5.10.9。如果問題出現,請嘗試普通5.10.5,以確保供應商應用的補丁不會
+干擾。如果問題沒有出現,那麼嘗試5.10.7,然後直到5.10.8或5.10.6(取決於結果)
+找到第一個引入問題的版本。在報告中寫明這一點,並指出5.10.9仍然存在故障。
+
+前一段基本粗略地概述了「二分」方法。一旦報告出來,您可能會被要求做一個正確的
+報告,因爲它允許精確地定位導致問題的確切更改(然後很容易被恢復以快速修復問題)。
+因此如果時間允許,考慮立即進行適當的二分。有關如何詳細信息,請參閱「對回歸的
+特別關照」部分和文檔「Documentation/translations/zh_TW/admin-guide/bug-bisect.rst」。
+
+
+「報告僅在舊內核版本線中發生的問題」的參考
+------------------------------------------
+
+本節詳細介紹了如果無法用主線內核重現問題,但希望在舊版本線(又稱穩定版內核和
+長期支持內核)中修復問題時需要採取的步驟。
+
+有些修復太複雜
+~~~~~~~~~~~~~~~
+
+ *請做好準備,接下來的幾個步驟可能無法在舊版本中解決問題:修復可能太大或
+ 太冒險,無法移植到那裡。*
+
+即使是微小的、看似明顯的代碼變化,有時也會帶來新的、完全意想不到的問題。穩
+定版和長期支持內核的維護者非常清楚這一點,因此他們只對這些內核進行符合
+「Documentation/translations/zh_TW/process/stable-kernel-rules.rst」中所列出的
+規則的修改。
+
+複雜或有風險的修改不符合條件,因此只能應用於主線。其他的修復很容易被回溯到
+最新的穩定版和長期支持內核,但是風險太大,無法集成到舊版內核中。所以要注意
+你所希望的修復可能是那些不會被回溯到你所關心的版本線的修復之一。在這種情況
+下,你將別無選擇,要麼忍受這個問題,要麼切換到一個較新的 Linux 版本,除非你
+想自己把修復補丁應用到你的內核中。
+
+通用準備
+~~~~~~~~~~
+
+ *執行上面「報告僅在舊內核版本線中發生的問題」一節中的前三個步驟。*
+
+您需要執行本指南另一節中已經描述的幾個步驟。這些步驟將讓您:
+
+ * 檢查內核開發人員是否仍然維護您關心的Linux內核版本行。
+
+ * 在Linux穩定郵件列表中搜索退出的報告。
+
+ * 檢查最新版本。
+
+
+檢查代碼歷史和搜索現有的討論
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ *在Linux內核版本控制系統中搜索修復主線問題的更改,因爲它的提交消息可能
+ 會告訴你修復是否已經計劃好了支持。如果你沒有找到,搜索適當的郵件列表,
+ 尋找討論此類問題或同行評議可能修復的帖子;然後檢查討論是否認爲修復不適
+ 合支持。如果支持根本不被考慮,加入最新的討論,詢問是否有可能。*
+
+在許多情況下,你所處理的問題會發生在主線上,但已在主線上得到了解決。修正它
+的提交也需要被回溯才能解決這個問題。這就是爲什麼你要搜索它或任何相關討論。
+
+ * 首先嘗試在存放 Linux 內核原始碼的 Git 倉庫中找到修復。你可以通過
+ `kernel.org 上的網頁
+ <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/>`_
+ 或 `GitHub 上的鏡像 <https://github.com/torvalds/linux>`_ 來實現;如果你
+ 有一個本地克隆,你也可以在命令行用 ``git log --grep=<pattern>`` 來搜索。
+
+ 如果你找到了修復,請查看提交消息的尾部是否包含了類似這樣的「穩定版標籤」:
+
+ Cc: <stable@vger.kernel.org> # 5.4+
+
+ 像上面這行,開發者標記了安全修復可以回傳到 5.4 及以後的版本。大多數情況
+ 下,它會在兩周內被應用到那裡,但有時需要更長的時間。
+
+ * 如果提交沒有告訴你任何東西,或者你找不到修復,請再找找關於這個問題的討論。
+ 用你最喜歡的搜尋引擎搜索網絡,以及 `Linux kernel developers mailing
+ list 內核開發者郵件列表 <https://lore.kernel.org/lkml/>`_ 的檔案。也可以
+ 閱讀上面的 `定位導致問題的內核區域` 一節,然後按照說明找到導致問題的子系
+ 統:它的缺陷跟蹤器或郵件列表存檔中可能有你要找的答案。
+
+ * 如果你看到了一個計劃的修復,請按上所述在版本控制系統中搜索它,因爲提交可
+ 能會告訴你是否可以進行回溯。
+
+ * 檢查討論中是否有任何跡象表明,該修復程序可能風險太大,無法回溯到你關心
+ 的版本線。如果是這樣的話,你必須忍受這個問題,或者切換到應用了修復的內
+ 核版本線。
+
+ * 如果修復的問題未包含穩定版標籤,並且沒有討論過回溯問題,請加入討論:如
+ 果合適的話,請提及你所面對的問題的版本,以及你希望看到它被修復。
+
+
+請求建議
+~~~~~~~~~
+
+ *前面的步驟之一應該會給出一個解決方案。如果仍未能成功,請向可能引起問題
+ 的子系統的維護人員詢問建議;抄送特定子系統的郵件列表以及穩定版郵件列表。*
+
+如果前面的三個步驟都沒有讓你更接近解決方案,那麼只剩下一個選擇:請求建議。
+在你發給可能是問題根源的子系統的維護者的郵件中這樣做;抄送子系統的郵件列表
+以及穩定版郵件列表(stable@vger.kernel.org)。
+
+
+爲什麼有些問題在報告後沒有任何回應或仍未解決?
+===============================================
+
+當向 Linux 開發者報告問題時,要注意只有「高優先級的問題」(回歸、安全問題、嚴
+重問題)才一定會得到解決。如果維護者或其他人都失敗了,Linus Torvalds 他自己
+會確保這一點。他們和其他內核開發者也會解決很多其他問題。但是要知道,有時他
+們也會不能或不願幫忙;有時甚至沒有人發報告給他們。
+
+最好的解釋就是那些內核開發者常常是在業餘時間爲 Linux 內核做出貢獻。內核中的
+不少驅動程序都是由這樣的程式設計師編寫的,往往只是因爲他們想讓自己的硬體可以在
+自己喜歡的作業系統上使用。
+
+這些程式設計師大多數時候會很樂意修復別人報告的問題。但是沒有人可以強迫他們這樣
+做,因爲他們是自願貢獻的。
+
+還有一些情況下,這些開發者真的很想解決一個問題,但卻不能解決:有時他們缺乏
+硬體編程文檔來解決問題。這種情況往往由於公開的文檔太簡陋,或者驅動程序是通
+過逆向工程編寫的。
+
+業餘開發者遲早也會不再關心某驅動。也許他們的測試硬體壞了,被更高級的玩意取
+代了,或者是太老了以至於只能在計算機博物館裡找到。有時開發者根本就不關心他
+們的代碼和 Linux 了,因爲在他們的生活中一些不同的東西變得更重要了。在某些情
+況下,沒有人願意接手維護者的工作——也沒有人可以被強迫,因爲對 Linux 內核的貢
+獻是自願的。然而被遺棄的驅動程序仍然存在於內核中:它們對人們仍然有用,刪除
+它們可能導致回歸。
+
+對於那些爲 Linux 內核工作而獲得報酬的開發者來說,情況並沒有什麼不同。這些人
+現在貢獻了大部分的變更。但是他們的僱主遲早也會停止關注他們的代碼或者讓程序
+員專注於其他事情。例如,硬體廠商主要通過銷售新硬體來賺錢;因此,他們中的不
+少人並沒有投入太多時間和精力來維護他們多年前就停止銷售的東西的 Linux 內核驅
+動。企業級 Linux 發行商往往持續維護的時間比較長,但在新版本中往往會把對老舊
+和稀有硬體的支持放在一邊,以限制範圍。一旦公司拋棄了一些代碼,往往由業餘貢
+獻者接手,但正如上面提到的:他們遲早也會放下代碼。
+
+優先級是一些問題沒有被修復的另一個原因,因爲維護者相當多的時候是被迫設置這
+些優先級的,因爲在 Linux 上工作的時間是有限的。對於業餘時間或者僱主給予他們
+的開發人員用於上游內核維護工作的時間也是如此。有時維護人員也會被報告淹沒,
+即使一個驅動程序幾乎完美地工作。爲了不被完全纏住,程式設計師可能別無選擇,只能
+對問題報告進行優先級排序而拒絕其中的一些報告。
+
+不過這些都不用太過擔心,很多驅動都有積極的維護者,他們對儘可能多的解決問題
+相當感興趣。
+
+
+結束語
+=======
+
+與其他免費/自由&開源軟體(Free/Libre & Open Source Software,FLOSS)相比,
+向 Linux 內核開發者報告問題是很難的:這個文檔的長度和複雜性以及字裡行間的內
+涵都說明了這一點。但目前就是這樣了。這篇文字的主要作者希望通過記錄現狀來爲
+以後改善這種狀況打下一些基礎。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/security-bugs.rst b/Documentation/translations/zh_TW/admin-guide/security-bugs.rst
new file mode 100644
index 000000000000..eed260ef0c37
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/security-bugs.rst
@@ -0,0 +1,78 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :doc:`../../../admin-guide/security-bugs`
+
+:譯者:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+安全缺陷
+=========
+
+Linux內核開發人員非常重視安全性。因此我們想知道何時發現了安全漏洞,以便儘快
+修復和披露。請向Linux內核安全團隊報告安全漏洞。
+
+聯絡
+-----
+
+可以通過電子郵件<security@kernel.org>聯繫Linux內核安全團隊。這是一個安全人員
+的私有列表,他們將幫助驗證錯誤報告並開發和發布修復程序。如果您已經有了一個
+修復,請將其包含在您的報告中,這樣可以大大加快進程。安全團隊可能會從區域維護
+人員那裡獲得額外的幫助,以理解和修復安全漏洞。
+
+與任何缺陷一樣,提供的信息越多,診斷和修復就越容易。如果您不清楚哪些信息有用,
+請查看「Documentation/translations/zh_TW/admin-guide/reporting-issues.rst」中
+概述的步驟。任何利用漏洞的攻擊代碼都非常有用,未經報告者同意不會對外發布,除
+非已經公開。
+
+請儘可能發送無附件的純文本電子郵件。如果所有的細節都藏在附件里,那麼就很難對
+一個複雜的問題進行上下文引用的討論。把它想像成一個
+:doc:`常規的補丁提交 <../process/submitting-patches>` (即使你還沒有補丁):
+描述問題和影響,列出復現步驟,然後給出一個建議的解決方案,所有這些都是純文本的。
+
+披露和限制信息
+---------------
+
+安全列表不是公開渠道。爲此,請參見下面的協作。
+
+一旦開發出了健壯的補丁,發布過程就開始了。對公開的缺陷的修復會立即發布。
+
+儘管我們傾向於在未公開缺陷的修復可用時即發布補丁,但應報告者或受影響方的請求,
+這可能會被推遲到發布過程開始後的7日內,如果根據缺陷的嚴重性需要更多的時間,
+則可額外延長到14天。推遲發布修復的唯一有效原因是爲了適應QA的邏輯和需要發布
+協調的大規模部署。
+
+雖然可能與受信任的個人共享受限信息以開發修復,但未經報告者許可,此類信息不會
+與修復程序一起發布或發布在任何其他披露渠道上。這包括但不限於原始錯誤報告和
+後續討論(如有)、漏洞、CVE信息或報告者的身份。
+
+換句話說,我們唯一感興趣的是修復缺陷。提交給安全列表的所有其他資料以及對報告
+的任何後續討論,即使在解除限制之後,也將永久保密。
+
+協調
+------
+
+對敏感缺陷(例如那些可能導致權限提升的缺陷)的修復可能需要與私有郵件列表
+<linux-distros@vs.openwall.org>進行協調,以便分發供應商做好準備,在公開披露
+上游補丁時發布一個已修復的內核。發行版將需要一些時間來測試建議的補丁,通常
+會要求至少幾天的限制,而供應商更新發布更傾向於周二至周四。若合適,安全團隊
+可以協助這種協調,或者報告者可以從一開始就包括linux發行版。在這種情況下,請
+記住在電子郵件主題行前面加上「[vs]」,如linux發行版wiki中所述:
+<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>。
+
+CVE分配
+--------
+
+安全團隊通常不分配CVE,我們也不需要它們來進行報告或修復,因爲這會使過程不必
+要的複雜化,並可能耽誤缺陷處理。如果報告者希望在公開披露之前分配一個CVE編號,
+他們需要聯繫上述的私有linux-distros列表。當在提供補丁之前已有這樣的CVE編號時,
+如報告者願意,最好在提交消息中提及它。
+
+保密協議
+---------
+
+Linux內核安全團隊不是一個正式的機構實體,因此無法簽訂任何保密協議。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst b/Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst
new file mode 100644
index 000000000000..d7b3c4276417
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst
@@ -0,0 +1,161 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :doc:`../../../admin-guide/tainted-kernels`
+
+:譯者:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+受汙染的內核
+-------------
+
+當發生一些在稍後調查問題時可能相關的事件時,內核會將自己標記爲「受汙染
+(tainted)」的。不用太過擔心,大多數情況下運行受汙染的內核沒有問題;這些信息
+主要在有人想調查某個問題時才有意義的,因爲問題的真正原因可能是導致內核受汙染
+的事件。這就是爲什麼來自受汙染內核的缺陷報告常常被開發人員忽略,因此請嘗試用
+未受汙染的內核重現問題。
+
+請注意,即使在您消除導致汙染的原因(亦即卸載專有內核模塊)之後,內核仍將保持
+汙染狀態,以表示內核仍然不可信。這也是爲什麼內核在注意到內部問題(「kernel
+bug」)、可恢復錯誤(「kernel oops」)或不可恢復錯誤(「kernel panic」)時會列印
+受汙染狀態,並將有關此的調試信息寫入日誌 ``dmesg`` 輸出。也可以通過
+``/proc/`` 中的文件在運行時檢查受汙染的狀態。
+
+
+BUG、Oops或Panics消息中的汙染標誌
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+在頂部以「CPU:」開頭的一行中可以找到受汙染的狀態;內核是否受到汙染和原因會顯示
+在進程ID(「PID:」)和觸發事件命令的縮寫名稱(「Comm:」)之後::
+
+ BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
+ Oops: 0002 [#1] SMP PTI
+ CPU: 0 PID: 4424 Comm: insmod Tainted: P W O 4.20.0-0.rc6.fc30 #1
+ Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
+ RIP: 0010:my_oops_init+0x13/0x1000 [kpanic]
+ [...]
+
+如果內核在事件發生時沒有被汙染,您將在那裡看到「Not-tainted:」;如果被汙染,那
+麼它將是「Tainted:」以及字母或空格。在上面的例子中,它看起來是這樣的::
+
+ Tainted: P W O
+
+下表解釋了這些字符的含義。在本例中,由於加載了專有模塊( ``P`` ),出現了
+警告( ``W`` ),並且加載了外部構建的模塊( ``O`` ),所以內核早些時候受到
+了汙染。要解碼其他字符,請使用下表。
+
+
+解碼運行時的汙染狀態
+~~~~~~~~~~~~~~~~~~~~~
+
+在運行時,您可以通過讀取 ``cat /proc/sys/kernel/tainted`` 來查詢受汙染狀態。
+如果返回 ``0`` ,則內核沒有受到汙染;任何其他數字都表示受到汙染的原因。解碼
+這個數字的最簡單方法是使用腳本 ``tools/debugging/kernel-chktaint`` ,您的
+發行版可能會將其作爲名爲 ``linux-tools`` 或 ``kernel-tools`` 的包的一部分提
+供;如果沒有,您可以從
+`git.kernel.org <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/tools/debugging/kernel-chktaint>`_
+網站下載此腳本並用 ``sh kernel-chktaint`` 執行,它會在上面引用的日誌中有類似
+語句的機器上列印這樣的內容::
+
+ Kernel is Tainted for following reasons:
+ * Proprietary module was loaded (#0)
+ * Kernel issued warning (#9)
+ * Externally-built ('out-of-tree') module was loaded (#12)
+ See Documentation/admin-guide/tainted-kernels.rst in the Linux kernel or
+ https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html for
+ a more details explanation of the various taint flags.
+ Raw taint value as int/string: 4609/'P W O '
+
+你也可以試著自己解碼這個數字。如果內核被汙染的原因只有一個,那麼這很簡單,
+在本例中您可以通過下表找到數字。如果你需要解碼有多個原因的數字,因爲它是一
+個位域(bitfield),其中每個位表示一個特定類型的汙染的存在或不存在,最好讓
+前面提到的腳本來處理。但是如果您需要快速看一下,可以使用這個shell命令來檢查
+設置了哪些位::
+
+ $ for i in $(seq 18); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done
+
+汙染狀態代碼表
+~~~~~~~~~~~~~~~
+
+=== ===== ====== ========================================================
+ 位 日誌 數字 內核被汙染的原因
+=== ===== ====== ========================================================
+ 0 G/P 1 已加載專用模塊
+ 1 _/F 2 模塊被強制加載
+ 2 _/S 4 內核運行在不合規範的系統上
+ 3 _/R 8 模塊被強制卸載
+ 4 _/M 16 處理器報告了機器檢測異常(MCE)
+ 5 _/B 32 引用了錯誤的頁或某些意外的頁標誌
+ 6 _/U 64 用戶空間應用程式請求的汙染
+ 7 _/D 128 內核最近死機了,即曾出現OOPS或BUG
+ 8 _/A 256 ACPI表被用戶覆蓋
+ 9 _/W 512 內核發出警告
+ 10 _/C 1024 已加載staging驅動程序
+ 11 _/I 2048 已應用平台固件缺陷的解決方案
+ 12 _/O 4096 已加載外部構建(「樹外」)模塊
+ 13 _/E 8192 已加載未簽名的模塊
+ 14 _/L 16384 發生軟鎖定
+ 15 _/K 32768 內核已實時打補丁
+ 16 _/X 65536 備用汙染,爲發行版定義並使用
+ 17 _/T 131072 內核是用結構隨機化插件構建的
+=== ===== ====== ========================================================
+
+註:字符 ``_`` 表示空白,以便於閱讀表。
+
+汙染的更詳細解釋
+~~~~~~~~~~~~~~~~~
+
+ 0) ``G`` 加載的所有模塊都有GPL或兼容許可證, ``P`` 加載了任何專有模塊。
+ 沒有MODULE_LICENSE(模塊許可證)或MODULE_LICENSE未被insmod認可爲GPL
+ 兼容的模塊被認爲是專有的。
+
+
+ 1) ``F`` 任何模塊被 ``insmod -f`` 強制加載, ``' '`` 所有模塊正常加載。
+
+ 2) ``S`` 內核運行在不合規範的處理器或系統上:硬體已運行在不受支持的配置中,
+ 因此無法保證正確執行。內核將被汙染,例如:
+
+ - 在x86上:PAE是通過intel CPU(如Pentium M)上的forcepae強制執行的,這些
+ CPU不報告PAE,但可能有功能實現,SMP內核在非官方支持的SMP Athlon CPU上
+ 運行,MSR被暴露到用戶空間中。
+ - 在arm上:在某些CPU(如Keystone 2)上運行的內核,沒有啓用某些內核特性。
+ - 在arm64上:CPU之間存在不匹配的硬體特性,引導加載程序以不同的模式引導CPU。
+ - 某些驅動程序正在被用在不受支持的體系結構上(例如x86_64以外的其他系統
+ 上的scsi/snic,非x86/x86_64/itanium上的scsi/ips,已經損壞了arm64上
+ irqchip/irq-gic的固件設置…)。
+
+ 3) ``R`` 模塊被 ``rmmod -f`` 強制卸載, ``' '`` 所有模塊都正常卸載。
+
+ 4) ``M`` 任何處理器報告了機器檢測異常, ``' '`` 未發生機器檢測異常。
+
+ 5) ``B`` 頁面釋放函數發現錯誤的頁面引用或某些意外的頁面標誌。這表示硬體問題
+ 或內核錯誤;日誌中應該有其他信息指示發生此汙染的原因。
+
+ 6) ``U`` 用戶或用戶應用程式特意請求設置受汙染標誌,否則應爲 ``' '`` 。
+
+ 7) ``D`` 內核最近死機了,即出現了OOPS或BUG。
+
+ 8) ``A`` ACPI表被重寫。
+
+ 9) ``W`` 內核之前已發出過警告(儘管有些警告可能會設置更具體的汙染標誌)。
+
+ 10) ``C`` 已加載staging驅動程序。
+
+ 11) ``I`` 內核正在處理平台固件(BIOS或類似軟體)中的嚴重錯誤。
+
+ 12) ``O`` 已加載外部構建(「樹外」)模塊。
+
+ 13) ``E`` 在支持模塊簽名的內核中加載了未簽名的模塊。
+
+ 14) ``L`` 系統上先前發生過軟鎖定。
+
+ 15) ``K`` 內核已經實時打了補丁。
+
+ 16) ``X`` 備用汙染,由Linux發行版定義和使用。
+
+ 17) ``T`` 內核構建時使用了randstruct插件,它可以有意生成非常不尋常的內核結構
+ 布局(甚至是性能病態的布局),這在調試時非常有用。於構建時設置。
+
diff --git a/Documentation/translations/zh_TW/admin-guide/unicode.rst b/Documentation/translations/zh_TW/admin-guide/unicode.rst
new file mode 100644
index 000000000000..720875be5ef8
--- /dev/null
+++ b/Documentation/translations/zh_TW/admin-guide/unicode.rst
@@ -0,0 +1,174 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: Documentation/admin-guide/unicode.rst
+
+:譯者:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+Unicode(統一碼)支持
+======================
+
+ (英文版)上次更新:2005-01-17,版本號 1.4
+
+此文檔由H. Peter Anvin <unicode@lanana.org>管理,是Linux註冊名稱與編號管理局
+(Linux Assigned Names And Numbers Authority,LANANA)項目的一部分。
+現行版本請見:
+
+ http://www.lanana.org/docs/unicode/admin-guide/unicode.rst
+
+簡介
+-----
+
+Linux內核代碼已被重寫以使用Unicode來將字符映射到字體。下載一個Unicode到字體
+(Unicode-to-font)表,八位字符集與UTF-8模式都將改用此字體來顯示。
+
+這微妙地改變了八位字符表的語義。現在的四個字符表是:
+
+=============== =============================== ================
+映射代號 映射名稱 Escape代碼 (G0)
+=============== =============================== ================
+LAT1_MAP Latin-1 (ISO 8859-1) ESC ( B
+GRAF_MAP DEC VT100 pseudographics ESC ( 0
+IBMPC_MAP IBM code page 437 ESC ( U
+USER_MAP User defined ESC ( K
+=============== =============================== ================
+
+特別是 ESC ( U 不再是「直通字體」,因爲字體可能與IBM字符集完全不同。
+例如,即使加載了一個Latin-1字體,也允許使用塊圖形(block graphics)。
+
+請注意,儘管這些代碼與ISO 2022類似,但這些代碼及其用途都與ISO 2022不匹配;
+Linux有兩個八位代碼(G0和G1),而ISO 2022有四個七位代碼(G0-G3)。
+
+根據Unicode標準/ISO 10646,U+F000到U+F8FF被保留用於作業系統範圍內的分配
+(Unicode標準將其稱爲「團體區域(Corporate Zone)」,因爲這對於Linux是不準確
+的,所以我們稱之爲「Linux區域」)。選擇U+F000作爲起點,因爲它允許直接映射
+區域以2的大倍數開始(以防需要1024或2048個字符的字體)。這就留下U+E000到
+U+EFFF作爲最終用戶區。
+
+[v1.2]:Unicodes範圍從U+F000到U+F7FF已經被硬編碼爲直接映射到加載的字體,
+繞過了翻譯表。用戶定義的映射現在默認爲U+F000到U+F0FF,模擬前述行爲。實際上,
+此範圍可能較短;例如,vgacon只能處理256字符(U+F000..U+F0FF)或512字符
+(U+F000..U+F1FF)字體。
+
+Linux 區域中定義的實際字符
+---------------------------
+
+此外,還定義了Unicode 1.1.4中不存在的以下字符;這些字符由DEC VT圖形映射使用。
+[v1.2]此用法已過時,不應再使用;請參見下文。
+
+====== ======================================
+U+F800 DEC VT GRAPHICS HORIZONTAL LINE SCAN 1
+U+F801 DEC VT GRAPHICS HORIZONTAL LINE SCAN 3
+U+F803 DEC VT GRAPHICS HORIZONTAL LINE SCAN 7
+U+F804 DEC VT GRAPHICS HORIZONTAL LINE SCAN 9
+====== ======================================
+
+DEC VT220使用6x10字符矩陣,這些字符在DEC VT圖形字符集中形成一個平滑的過渡。
+我省略了掃描5行,因爲它也被用作塊圖形字符,因此被編碼爲U+2500 FORMS LIGHT
+HORIZONTAL。
+
+[v1.3]:這些字符已正式添加到Unicode 3.2.0中;它們在U+23BA、U+23BB、U+23BC、
+U+23BD處添加。Linux現在使用新值。
+
+[v1.2]:添加了以下字符來表示常見的鍵盤符號,這些符號不太可能被添加到Unicode
+中,因爲它們非常討厭地取決於特定供應商。當然,這是糟糕設計的一個好例子。
+
+====== ======================================
+U+F810 KEYBOARD SYMBOL FLYING FLAG
+U+F811 KEYBOARD SYMBOL PULLDOWN MENU
+U+F812 KEYBOARD SYMBOL OPEN APPLE
+U+F813 KEYBOARD SYMBOL SOLID APPLE
+====== ======================================
+
+克林貢(Klingon)語支持
+------------------------
+
+1996年,Linux是世界上第一個添加對人工語言克林貢支持的作業系統,克林貢是由
+Marc Okrand爲《星際迷航》電視連續劇創造的。這種編碼後來被徵募Unicode註冊表
+(ConScript Unicode Registry,CSUR)採用,並建議(但最終被拒絕)納入Unicode
+平面一。不過,它仍然是Linux區域中的Linux/CSUR私有分配。
+
+這種編碼已經得到克林貢語言研究所(Klingon Language Institute)的認可。
+有關更多信息,請聯繫他們:
+
+ http://www.kli.org/
+
+由於Linux CZ開頭部分的字符大多是dingbats/symbols/forms類型,而且這是一種
+語言,因此根據標準Unicode慣例,我將它放置在16單元的邊界上。
+
+.. note::
+
+ 這個範圍現在由徵募Unicode註冊表正式管理。規範性引用文件爲:
+
+ https://www.evertype.com/standards/csur/klingon.html
+
+克林貢語有一個26個字符的字母表,一個10位數的位置數字書寫系統,從左到右
+,從上到下書寫。
+
+克林貢字母的幾種字形已經被提出。但是由於這組符號看起來始終是一致的,只有實際
+的形狀不同,因此按照標準Unicode慣例,這些差異被認爲是字體變體。
+
+====== =======================================================
+U+F8D0 KLINGON LETTER A
+U+F8D1 KLINGON LETTER B
+U+F8D2 KLINGON LETTER CH
+U+F8D3 KLINGON LETTER D
+U+F8D4 KLINGON LETTER E
+U+F8D5 KLINGON LETTER GH
+U+F8D6 KLINGON LETTER H
+U+F8D7 KLINGON LETTER I
+U+F8D8 KLINGON LETTER J
+U+F8D9 KLINGON LETTER L
+U+F8DA KLINGON LETTER M
+U+F8DB KLINGON LETTER N
+U+F8DC KLINGON LETTER NG
+U+F8DD KLINGON LETTER O
+U+F8DE KLINGON LETTER P
+U+F8DF KLINGON LETTER Q
+ - Written <q> in standard Okrand Latin transliteration
+U+F8E0 KLINGON LETTER QH
+ - Written <Q> in standard Okrand Latin transliteration
+U+F8E1 KLINGON LETTER R
+U+F8E2 KLINGON LETTER S
+U+F8E3 KLINGON LETTER T
+U+F8E4 KLINGON LETTER TLH
+U+F8E5 KLINGON LETTER U
+U+F8E6 KLINGON LETTER V
+U+F8E7 KLINGON LETTER W
+U+F8E8 KLINGON LETTER Y
+U+F8E9 KLINGON LETTER GLOTTAL STOP
+
+U+F8F0 KLINGON DIGIT ZERO
+U+F8F1 KLINGON DIGIT ONE
+U+F8F2 KLINGON DIGIT TWO
+U+F8F3 KLINGON DIGIT THREE
+U+F8F4 KLINGON DIGIT FOUR
+U+F8F5 KLINGON DIGIT FIVE
+U+F8F6 KLINGON DIGIT SIX
+U+F8F7 KLINGON DIGIT SEVEN
+U+F8F8 KLINGON DIGIT EIGHT
+U+F8F9 KLINGON DIGIT NINE
+
+U+F8FD KLINGON COMMA
+U+F8FE KLINGON FULL STOP
+U+F8FF KLINGON SYMBOL FOR EMPIRE
+====== =======================================================
+
+其他虛構和人工字母
+-------------------
+
+自從分配了克林貢Linux Unicode塊之後,John Cowan <jcowan@reutershealth.com>
+和 Michael Everson <everson@evertype.com> 建立了一個虛構和人工字母的註冊表。
+徵募Unicode註冊表請訪問:
+
+ https://www.evertype.com/standards/csur/
+
+所使用的範圍位於最終用戶區域的低端,因此無法進行規範化分配,但建議希望對虛構
+字母進行編碼的人員使用這些代碼,以實現互操作性。對於克林貢語,CSUR採用了Linux
+編碼。CSUR的人正在推動將Tengwar和Cirth添加到Unicode平面一;將克林貢添加到
+Unicode平面一被拒絕,因此上述編碼仍然是官方的。
+
diff --git a/Documentation/translations/zh_TW/disclaimer-zh_TW.rst b/Documentation/translations/zh_TW/disclaimer-zh_TW.rst
new file mode 100644
index 000000000000..f4cf87d03dc5
--- /dev/null
+++ b/Documentation/translations/zh_TW/disclaimer-zh_TW.rst
@@ -0,0 +1,11 @@
+:orphan:
+
+.. warning::
+ 此文件的目的是爲讓中文讀者更容易閱讀和理解,而不是作爲一個分支。因此,
+ 如果您對此文件有任何意見或改動,請先嘗試更新原始英文文件。如果要更改或
+ 修正某處翻譯文件,請將意見或補丁發送給維護者(聯繫方式見下)。
+
+.. note::
+ 如果您發現本文檔與原始文件有任何不同或者有翻譯問題,請聯繫該文件的譯者,
+ 或者發送電子郵件給胡皓文以獲取幫助:<src.res@email.cn>。
+
diff --git a/Documentation/translations/zh_TW/gpio.txt b/Documentation/translations/zh_TW/gpio.txt
new file mode 100644
index 000000000000..e3c076dd75a5
--- /dev/null
+++ b/Documentation/translations/zh_TW/gpio.txt
@@ -0,0 +1,651 @@
+Chinese translated version of Documentation/admin-guide/gpio
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Grant Likely <grant.likely@secretlab.ca>
+ Linus Walleij <linus.walleij@linaro.org>
+Traditional Chinese maintainer: Hu Haowen <src.res@email.cn>
+---------------------------------------------------------------------
+Documentation/admin-guide/gpio 的繁體中文翻譯
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或
+者翻譯存在問題,請聯繫繁體中文版維護者。
+
+英文版維護者: Grant Likely <grant.likely@secretlab.ca>
+ Linus Walleij <linus.walleij@linaro.org>
+繁體中文版維護者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版翻譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版校譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+
+以下爲正文
+---------------------------------------------------------------------
+GPIO 接口
+
+本文檔提供了一個在Linux下訪問GPIO的公約概述。
+
+這些函數以 gpio_* 作爲前綴。其他的函數不允許使用這樣的前綴或相關的
+__gpio_* 前綴。
+
+
+什麼是GPIO?
+==========
+"通用輸入/輸出口"(GPIO)是一個靈活的由軟體控制的數位訊號。他們可
+由多種晶片提供,且對於從事嵌入式和定製硬體的 Linux 開發者來說是
+比較熟悉。每個GPIO 都代表一個連接到特定引腳或球柵陣列(BGA)封裝中
+「球珠」的一個位。電路板原理圖顯示了 GPIO 與外部硬體的連接關係。
+驅動可以編寫成通用代碼,以使板級啓動代碼可傳遞引腳配置數據給驅動。
+
+片上系統 (SOC) 處理器對 GPIO 有很大的依賴。在某些情況下,每個
+非專用引腳都可配置爲 GPIO,且大多數晶片都最少有一些 GPIO。
+可編程邏輯器件(類似 FPGA) 可以方便地提供 GPIO。像電源管理和
+音頻編解碼器這樣的多功能晶片經常留有一些這樣的引腳來幫助那些引腳
+匱乏的 SOC。同時還有通過 I2C 或 SPI 串行總線連接的「GPIO擴展器」
+晶片。大多數 PC 的南橋有一些擁有 GPIO 能力的引腳 (只有BIOS
+固件才知道如何使用他們)。
+
+GPIO 的實際功能因系統而異。通常用法有:
+
+ - 輸出值可寫 (高電平=1,低電平=0)。一些晶片也有如何驅動這些值的選項,
+ 例如只允許輸出一個值、支持「線與」及其他取值類似的模式(值得注意的是
+ 「開漏」信號)
+
+ - 輸入值可讀(1、0)。一些晶片支持引腳在配置爲「輸出」時回讀,這對於類似
+ 「線與」的情況(以支持雙向信號)是非常有用的。GPIO 控制器可能有輸入
+ 去毛刺/消抖邏輯,這有時需要軟體控制。
+
+ - 輸入通常可作爲 IRQ 信號,一般是沿觸發,但有時是電平觸發。這樣的 IRQ
+ 可能配置爲系統喚醒事件,以將系統從低功耗狀態下喚醒。
+
+ - 通常一個 GPIO 根據不同產品電路板的需求,可以配置爲輸入或輸出,也有僅
+ 支持單向的。
+
+ - 大部分 GPIO 可以在持有自旋鎖時訪問,但是通常由串行總線擴展的 GPIO
+ 不允許持有自旋鎖。但某些系統也支持這種類型。
+
+對於給定的電路板,每個 GPIO 都用於某個特定的目的,如監控 MMC/SD 卡的
+插入/移除、檢測卡的防寫狀態、驅動 LED、配置收發器、模擬串行總線、
+復位硬體看門狗、感知開關狀態等等。
+
+
+GPIO 公約
+=========
+注意,這個叫做「公約」,因爲這不是強制性的,不遵循這個公約是無傷大雅的,
+因爲此時可移植性並不重要。GPIO 常用於板級特定的電路邏輯,甚至可能
+隨著電路板的版本而改變,且不可能在不同走線的電路板上使用。僅有在少數
+功能上才具有可移植性,其他功能是平台特定。這也是由於「膠合」的邏輯造成的。
+
+此外,這不需要任何的執行框架,只是一個接口。某個平台可能通過一個簡單地
+訪問晶片寄存器的內聯函數來實現它,其他平台可能通過委託一系列不同的GPIO
+控制器的抽象函數來實現它。(有一些可選的代碼能支持這種策略的實現,本文檔
+後面會介紹,但作爲 GPIO 接口的客戶端驅動程序必須與它的實現無關。)
+
+也就是說,如果在他們的平台上支持這個公約,驅動應儘可能的使用它。同時,平台
+必須在 Kconfig 中選擇 ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB
+選項。那些調用標準 GPIO 函數的驅動應該在 Kconfig 入口中聲明依賴GENERIC_GPIO。
+當驅動包含文件:
+
+ #include <linux/gpio.h>
+
+則 GPIO 函數是可用,無論是「真實代碼」還是經優化過的語句。如果你遵守
+這個公約,當你的代碼完成後,對其他的開發者來說會更容易看懂和維護。
+
+注意,這些操作包含所用平台的 I/O 屏障代碼,驅動無須顯式地調用他們。
+
+
+標識 GPIO
+---------
+GPIO 是通過無符號整型來標識的,範圍是 0 到 MAX_INT。保留「負」數
+用於其他目的,例如標識信號「在這個板子上不可用」或指示錯誤。未接觸底層
+硬體的代碼會忽略這些整數。
+
+平台會定義這些整數的用法,且通常使用 #define 來定義 GPIO,這樣
+板級特定的啓動代碼可以直接關聯相應的原理圖。相對來說,驅動應該僅使用
+啓動代碼傳遞過來的 GPIO 編號,使用 platform_data 保存板級特定
+引腳配置數據 (同時還有其他須要的板級特定數據),避免可能出現的問題。
+
+例如一個平台使用編號 32-159 來標識 GPIO,而在另一個平台使用編號0-63
+標識一組 GPIO 控制器,64-79標識另一類 GPIO 控制器,且在一個含有
+FPGA 的特定板子上使用 80-95。編號不一定要連續,那些平台中,也可以
+使用編號2000-2063來標識一個 I2C 接口的 GPIO 擴展器中的 GPIO。
+
+如果你要初始化一個帶有無效 GPIO 編號的結構體,可以使用一些負編碼
+(如"-EINVAL"),那將使其永遠不會是有效。來測試這樣一個結構體中的編號
+是否關聯一個 GPIO,你可使用以下斷言:
+
+ int gpio_is_valid(int number);
+
+如果編號不存在,則請求和釋放 GPIO 的函數將拒絕執行相關操作(見下文)。
+其他編號也可能被拒絕,比如一個編號可能存在,但暫時在給定的電路上不可用。
+
+一個平台是否支持多個 GPIO 控制器爲平台特定的實現問題,就像是否可以
+在 GPIO 編號空間中有「空洞」和是否可以在運行時添加新的控制器一樣。
+這些問題會影響其他事情,包括相鄰的 GPIO 編號是否存在等。
+
+使用 GPIO
+---------
+對於一個 GPIO,系統應該做的第一件事情就是通過 gpio_request()
+函數分配它,見下文。
+
+接下來是設置I/O方向,這通常是在板級啓動代碼中爲所使用的 GPIO 設置
+platform_device 時完成。
+
+ /* 設置爲輸入或輸出, 返回 0 或負的錯誤代碼 */
+ int gpio_direction_input(unsigned gpio);
+ int gpio_direction_output(unsigned gpio, int value);
+
+返回值爲零代表成功,否則返回一個負的錯誤代碼。這個返回值需要檢查,因爲
+get/set(獲取/設置)函數調用沒法返回錯誤,且有可能是配置錯誤。通常,
+你應該在進程上下文中調用這些函數。然而,對於自旋鎖安全的 GPIO,在板子
+啓動的早期、進程啓動前使用他們也是可以的。
+
+對於作爲輸出的 GPIO,爲其提供初始輸出值,對於避免在系統啓動期間出現
+信號毛刺是很有幫助的。
+
+爲了與傳統的 GPIO 接口兼容, 在設置一個 GPIO 方向時,如果它還未被申請,
+則隱含了申請那個 GPIO 的操作(見下文)。這種兼容性正在從可選的 gpiolib
+框架中移除。
+
+如果這個 GPIO 編碼不存在,或者特定的 GPIO 不能用於那種模式,則方向
+設置可能失敗。依賴啓動固件來正確地設置方向通常是一個壞主意,因爲它可能
+除了啓動Linux,並沒有做更多的驗證工作。(同理, 板子的啓動代碼可能需要
+將這個復用的引腳設置爲 GPIO,並正確地配置上拉/下拉電阻。)
+
+
+訪問自旋鎖安全的 GPIO
+-------------------
+大多數 GPIO 控制器可以通過內存讀/寫指令來訪問。這些指令不會休眠,可以
+安全地在硬(非線程)中斷例程和類似的上下文中完成。
+
+對於那些用 gpio_cansleep()測試總是返回失敗的 GPIO(見下文),使用
+以下的函數訪問:
+
+ /* GPIO 輸入:返回零或非零 */
+ int gpio_get_value(unsigned gpio);
+
+ /* GPIO 輸出 */
+ void gpio_set_value(unsigned gpio, int value);
+
+GPIO值是布爾值,零表示低電平,非零表示高電平。當讀取一個輸出引腳的值時,
+返回值應該是引腳上的值。這個值不總是和輸出值相符,因爲存在開漏輸出信號和
+輸出延遲問題。
+
+以上的 get/set 函數無錯誤返回值,因爲之前 gpio_direction_*()應已檢查過
+其是否爲「無效GPIO」。此外,還需要注意的是並不是所有平台都可以從輸出引腳
+中讀取數據,對於不能讀取的引腳應總返回零。另外,對那些在原子上下文中無法
+安全訪問的 GPIO (譯者註:因爲訪問可能導致休眠)使用這些函數是不合適的
+(見下文)。
+
+在 GPIO 編號(還有輸出、值)爲常數的情況下,鼓勵通過平台特定的實現來優化
+這兩個函數來訪問 GPIO 值。這種情況(讀寫一個硬體寄存器)下只需要幾條指令
+是很正常的,且無須自旋鎖。這種優化函數比起那些在子程序上花費許多指令的
+函數可以使得模擬接口(譯者注:例如 GPIO 模擬 I2C、1-wire 或 SPI)的
+應用(在空間和時間上都)更具效率。
+
+
+訪問可能休眠的 GPIO
+-----------------
+某些 GPIO 控制器必須通過基於總線(如 I2C 或 SPI)的消息訪問。讀或寫這些
+GPIO 值的命令需要等待其信息排到隊首才發送命令,再獲得其反饋。期間需要
+休眠,這不能在 IRQ 例程(中斷上下文)中執行。
+
+支持此類 GPIO 的平台通過以下函數返回非零值來區分出這種 GPIO。(此函數需要
+一個之前通過 gpio_request 分配到的有效 GPIO 編號):
+
+ int gpio_cansleep(unsigned gpio);
+
+爲了訪問這種 GPIO,內核定義了一套不同的函數:
+
+ /* GPIO 輸入:返回零或非零 ,可能會休眠 */
+ int gpio_get_value_cansleep(unsigned gpio);
+
+ /* GPIO 輸出,可能會休眠 */
+ void gpio_set_value_cansleep(unsigned gpio, int value);
+
+
+訪問這樣的 GPIO 需要一個允許休眠的上下文,例如線程 IRQ 處理例程,並用以上的
+訪問函數替換那些沒有 cansleep()後綴的自旋鎖安全訪問函數。
+
+除了這些訪問函數可能休眠,且它們操作的 GPIO 不能在硬體 IRQ 處理例程中訪問的
+事實,這些處理例程實際上和自旋鎖安全的函數是一樣的。
+
+** 除此之外 ** 調用設置和配置此類 GPIO 的函數也必須在允許休眠的上下文中,
+因爲它們可能也需要訪問 GPIO 控制器晶片: (這些設置函數通常在板級啓動代碼或者
+驅動探測/斷開代碼中,所以這是一個容易滿足的約束條件。)
+
+ gpio_direction_input()
+ gpio_direction_output()
+ gpio_request()
+
+## gpio_request_one()
+## gpio_request_array()
+## gpio_free_array()
+
+ gpio_free()
+ gpio_set_debounce()
+
+
+
+聲明和釋放 GPIO
+----------------------------
+爲了有助於捕獲系統配置錯誤,定義了兩個函數。
+
+ /* 申請 GPIO, 返回 0 或負的錯誤代碼.
+ * 非空標籤可能有助於診斷.
+ */
+ int gpio_request(unsigned gpio, const char *label);
+
+ /* 釋放之前聲明的 GPIO */
+ void gpio_free(unsigned gpio);
+
+將無效的 GPIO 編碼傳遞給 gpio_request()會導致失敗,申請一個已使用這個
+函數聲明過的 GPIO 也會失敗。gpio_request()的返回值必須檢查。你應該在
+進程上下文中調用這些函數。然而,對於自旋鎖安全的 GPIO,在板子啓動的早期、
+進入進程之前是可以申請的。
+
+這個函數完成兩個基本的目標。一是標識那些實際上已作爲 GPIO 使用的信號線,
+這樣便於更好地診斷;系統可能需要服務幾百個可用的 GPIO,但是對於任何一個
+給定的電路板通常只有一些被使用。另一個目的是捕獲衝突,查明錯誤:如兩個或
+更多驅動錯誤地認爲他們已經獨占了某個信號線,或是錯誤地認爲移除一個管理著
+某個已激活信號的驅動是安全的。也就是說,申請 GPIO 的作用類似一種鎖機制。
+
+某些平台可能也使用 GPIO 作爲電源管理激活信號(例如通過關閉未使用晶片區和
+簡單地關閉未使用時鐘)。
+
+對於 GPIO 使用 pinctrl 子系統已知的引腳,子系統應該被告知其使用情況;
+一個 gpiolib 驅動的 .request()操作應調用 pinctrl_gpio_request(),
+而 gpiolib 驅動的 .free()操作應調用 pinctrl_gpio_free()。pinctrl
+子系統允許 pinctrl_gpio_request()在某個引腳或引腳組以復用形式「屬於」
+一個設備時都成功返回。
+
+任何須將 GPIO 信號導向適當引腳的引腳復用硬體的編程應該發生在 GPIO
+驅動的 .direction_input()或 .direction_output()函數中,以及
+任何輸出 GPIO 值的設置之後。這樣可使從引腳特殊功能到 GPIO 的轉換
+不會在引腳產生毛刺波形。有時當用一個 GPIO 實現其信號驅動一個非 GPIO
+硬體模塊的解決方案時,就需要這種機制。
+
+某些平台允許部分或所有 GPIO 信號使用不同的引腳。類似的,GPIO 或引腳的
+其他方面也需要配置,如上拉/下拉。平台軟體應該在對這些 GPIO 調用
+gpio_request()前將這類細節配置好,例如使用 pinctrl 子系統的映射表,
+使得 GPIO 的用戶無須關注這些細節。
+
+還有一個值得注意的是在釋放 GPIO 前,你必須停止使用它。
+
+
+注意:申請一個 GPIO 並沒有以任何方式配置它,只不過標識那個 GPIO 處於使用
+狀態。必須有另外的代碼來處理引腳配置(如控制 GPIO 使用的引腳、上拉/下拉)。
+考慮到大多數情況下聲明 GPIO 之後就會立即配置它們,所以定義了以下三個輔助函數:
+
+ /* 申請一個 GPIO 信號, 同時通過特定的'flags'初始化配置,
+ * 其他和 gpio_request()的參數和返回值相同
+ *
+ */
+ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+
+ /* 在單個函數中申請多個 GPIO
+ */
+ int gpio_request_array(struct gpio *array, size_t num);
+
+ /* 在單個函數中釋放多個 GPIO
+ */
+ void gpio_free_array(struct gpio *array, size_t num);
+
+這裡 'flags' 當前定義可指定以下屬性:
+
+ * GPIOF_DIR_IN - 配置方向爲輸入
+ * GPIOF_DIR_OUT - 配置方向爲輸出
+
+ * GPIOF_INIT_LOW - 在作爲輸出時,初始值爲低電平
+ * GPIOF_INIT_HIGH - 在作爲輸出時,初始值爲高電平
+ * GPIOF_OPEN_DRAIN - gpio引腳爲開漏信號
+ * GPIOF_OPEN_SOURCE - gpio引腳爲源極開路信號
+
+ * GPIOF_EXPORT_DIR_FIXED - 將 gpio 導出到 sysfs,並保持方向
+ * GPIOF_EXPORT_DIR_CHANGEABLE - 同樣是導出, 但允許改變方向
+
+因爲 GPIOF_INIT_* 僅有在配置爲輸出的時候才存在,所以有效的組合爲:
+
+ * GPIOF_IN - 配置爲輸入
+ * GPIOF_OUT_INIT_LOW - 配置爲輸出,並初始化爲低電平
+ * GPIOF_OUT_INIT_HIGH - 配置爲輸出,並初始化爲高電平
+
+當設置 flag 爲 GPIOF_OPEN_DRAIN 時,則假設引腳是開漏信號。這樣的引腳
+將不會在輸出模式下置1。這樣的引腳需要連接上拉電阻。通過使能這個標誌,gpio庫
+將會在被要求輸出模式下置1時將引腳變爲輸入狀態來使引腳置高。引腳在輸出模式下
+通過置0使其輸出低電平。
+
+當設置 flag 爲 GPIOF_OPEN_SOURCE 時,則假設引腳爲源極開路信號。這樣的引腳
+將不會在輸出模式下置0。這樣的引腳需要連接下拉電阻。通過使能這個標誌,gpio庫
+將會在被要求輸出模式下置0時將引腳變爲輸入狀態來使引腳置低。引腳在輸出模式下
+通過置1使其輸出高電平。
+
+將來這些標誌可能擴展到支持更多的屬性。
+
+更進一步,爲了更簡單地聲明/釋放多個 GPIO,'struct gpio'被引進來封裝所有
+這三個領域:
+
+ struct gpio {
+ unsigned gpio;
+ unsigned long flags;
+ const char *label;
+ };
+
+一個典型的用例:
+
+ static struct gpio leds_gpios[] = {
+ { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默認開啓 */
+ { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* 默認關閉 */
+ { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* 默認關閉 */
+ { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* 默認關閉 */
+ { ... },
+ };
+
+ err = gpio_request_one(31, GPIOF_IN, "Reset Button");
+ if (err)
+ ...
+
+ err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+ if (err)
+ ...
+
+ gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+
+
+GPIO 映射到 IRQ
+--------------------
+GPIO 編號是無符號整數;IRQ 編號也是。這些構成了兩個邏輯上不同的命名空間
+(GPIO 0 不一定使用 IRQ 0)。你可以通過以下函數在它們之間實現映射:
+
+ /* 映射 GPIO 編號到 IRQ 編號 */
+ int gpio_to_irq(unsigned gpio);
+
+ /* 映射 IRQ 編號到 GPIO 編號 (儘量避免使用) */
+ int irq_to_gpio(unsigned irq);
+
+它們的返回值爲對應命名空間的相關編號,或是負的錯誤代碼(如果無法映射)。
+(例如,某些 GPIO 無法做爲 IRQ 使用。)以下的編號錯誤是未經檢測的:使用一個
+未通過 gpio_direction_input()配置爲輸入的 GPIO 編號,或者使用一個
+並非來源於gpio_to_irq()的 IRQ 編號。
+
+這兩個映射函數可能會在信號編號的加減計算過程上花些時間。它們不可休眠。
+
+gpio_to_irq()返回的非錯誤值可以傳遞給 request_irq()或者 free_irq()。
+它們通常通過板級特定的初始化代碼存放到平台設備的 IRQ 資源中。注意:IRQ
+觸發選項是 IRQ 接口的一部分,如 IRQF_TRIGGER_FALLING,系統喚醒能力
+也是如此。
+
+irq_to_gpio()返回的非錯誤值大多數通常可以被 gpio_get_value()所使用,
+比如在 IRQ 是沿觸發時初始化或更新驅動狀態。注意某些平台不支持反映射,所以
+你應該儘量避免使用它。
+
+
+模擬開漏信號
+----------------------------
+有時在只有低電平信號作爲實際驅動結果(譯者注:多個輸出連接於一點,邏輯電平
+結果爲所有輸出的邏輯與)的時候,共享的信號線需要使用「開漏」信號。(該術語
+適用於 CMOS 管;而 TTL 用「集電極開路」。)一個上拉電阻使信號爲高電平。這
+有時被稱爲「線與」。實際上,從負邏輯(低電平爲真)的角度來看,這是一個「線或」。
+
+一個開漏信號的常見例子是共享的低電平使能 IRQ 信號線。此外,有時雙向數據總線
+信號也使用漏極開路信號。
+
+某些 GPIO 控制器直接支持開漏輸出,還有許多不支持。當你需要開漏信號,但
+硬體又不直接支持的時候,一個常用的方法是用任何即可作輸入也可作輸出的 GPIO
+引腳來模擬:
+
+ LOW: gpio_direction_output(gpio, 0) ... 這代碼驅動信號並覆蓋
+ 上拉配置。
+
+ HIGH: gpio_direction_input(gpio) ... 這代碼關閉輸出,所以上拉電阻
+ (或其他的一些器件)控制了信號。
+
+如果你將信號線「驅動」爲高電平,但是 gpio_get_value(gpio)報告了一個
+低電平(在適當的上升時間後),你就可以知道是其他的一些組件將共享信號線拉低了。
+這不一定是錯誤的。一個常見的例子就是 I2C 時鐘的延長:一個需要較慢時鐘的
+從設備延遲 SCK 的上升沿,而 I2C 主設備相應地調整其信號傳輸速率。
+
+
+這些公約忽略了什麼?
+================
+這些公約忽略的最大一件事就是引腳復用,因爲這屬於高度晶片特定的屬性且
+沒有可移植性。某個平台可能不需要明確的復用信息;有的對於任意給定的引腳
+可能只有兩個功能選項;有的可能每個引腳有八個功能選項;有的可能可以將
+幾個引腳中的任何一個作爲給定的 GPIO。(是的,這些例子都來自於當前運行
+Linux 的系統。)
+
+在某些系統中,與引腳復用相關的是配置和使能集成的上、下拉模式。並不是所有
+平台都支持這種模式,或者不會以相同的方式來支持這種模式;且任何給定的電路板
+可能使用外置的上拉(或下拉)電阻,這時晶片上的就不應該使用。(當一個電路需要
+5kOhm 的拉動電阻,晶片上的 100 kOhm 電阻就不能做到。)同樣的,驅動能力
+(2 mA vs 20 mA)和電壓(1.8V vs 3.3V)是平台特定問題,就像模型一樣在
+可配置引腳和 GPIO 之間(沒)有一一對應的關係。
+
+還有其他一些系統特定的機制沒有在這裡指出,例如上述的輸入去毛刺和線與輸出
+選項。硬體可能支持批量讀或寫 GPIO,但是那一般是配置相關的:對於處於同一
+塊區(bank)的GPIO。(GPIO 通常以 16 或 32 個組成一個區塊,一個給定的
+片上系統一般有幾個這樣的區塊。)某些系統可以通過輸出 GPIO 觸發 IRQ,
+或者從並非以 GPIO 管理的引腳取值。這些機制的相關代碼沒有必要具有可移植性。
+
+當前,動態定義 GPIO 並不是標準的,例如作爲配置一個帶有某些 GPIO 擴展器的
+附加電路板的副作用。
+
+GPIO 實現者的框架 (可選)
+=====================
+前面提到了,有一個可選的實現框架,讓平台使用相同的編程接口,更加簡單地支持
+不同種類的 GPIO 控制器。這個框架稱爲"gpiolib"。
+
+作爲一個輔助調試功能,如果 debugfs 可用,就會有一個 /sys/kernel/debug/gpio
+文件。通過這個框架,它可以列出所有註冊的控制器,以及當前正在使用中的 GPIO
+的狀態。
+
+
+控制器驅動: gpio_chip
+-------------------
+在框架中每個 GPIO 控制器都包裝爲一個 "struct gpio_chip",他包含了
+該類型的每個控制器的常用信息:
+
+ - 設置 GPIO 方向的方法
+ - 用於訪問 GPIO 值的方法
+ - 告知調用其方法是否可能休眠的標誌
+ - 可選的 debugfs 信息導出方法 (顯示類似上拉配置一樣的額外狀態)
+ - 診斷標籤
+
+也包含了來自 device.platform_data 的每個實例的數據:它第一個 GPIO 的
+編號和它可用的 GPIO 的數量。
+
+實現 gpio_chip 的代碼應支持多控制器實例,這可能使用驅動模型。那些代碼要
+配置每個 gpio_chip,並發起gpiochip_add()。卸載一個 GPIO 控制器很少見,
+但在必要的時候可以使用 gpiochip_remove()。
+
+大部分 gpio_chip 是一個實例特定結構體的一部分,而並不將 GPIO 接口單獨
+暴露出來,比如編址、電源管理等。類似編解碼器這樣的晶片會有複雜的非 GPIO
+狀態。
+
+任何一個 debugfs 信息導出方法通常應該忽略還未申請作爲 GPIO 的信號線。
+他們可以使用 gpiochip_is_requested()測試,當這個 GPIO 已經申請過了
+就返回相關的標籤,否則返回 NULL。
+
+
+平台支持
+-------
+爲了支持這個框架,一個平台的 Kconfig 文件將會 "select"(選擇)
+ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,並讓它的
+<asm/gpio.h> 包含 <asm-generic/gpio.h>,同時定義三個方法:
+gpio_get_value()、gpio_set_value()和 gpio_cansleep()。
+
+它也應提供一個 ARCH_NR_GPIOS 的定義值,這樣可以更好地反映該平台 GPIO
+的實際數量,節省靜態表的空間。(這個定義值應該包含片上系統內建 GPIO 和
+GPIO 擴展器中的數據。)
+
+ARCH_REQUIRE_GPIOLIB 意味著 gpiolib 核心在這個構架中將總是編譯進內核。
+
+ARCH_WANT_OPTIONAL_GPIOLIB 意味著 gpiolib 核心默認關閉,且用戶可以
+使能它,並將其編譯進內核(可選)。
+
+如果這些選項都沒被選擇,該平台就不通過 GPIO-lib 支持 GPIO,且代碼不可以
+被用戶使能。
+
+以下這些方法的實現可以直接使用框架代碼,並總是通過 gpio_chip 調度:
+
+ #define gpio_get_value __gpio_get_value
+ #define gpio_set_value __gpio_set_value
+ #define gpio_cansleep __gpio_cansleep
+
+這些定義可以用更理想的實現方法替代,那就是使用經過邏輯優化的內聯函數來訪問
+基於特定片上系統的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量「12」,
+讀取或設置它可能只需少則兩或三個指令,且不會休眠。當這樣的優化無法實現時,
+那些函數必須使用框架提供的代碼,那就至少要幾十條指令才可以實現。對於用 GPIO
+模擬的 I/O 接口, 如此精簡指令是很有意義的。
+
+對於片上系統,平台特定代碼爲片上 GPIO 每個區(bank)定義並註冊 gpio_chip
+實例。那些 GPIO 應該根據晶片廠商的文檔進行編碼/標籤,並直接和電路板原理圖
+對應。他們應該開始於零並終止於平台特定的限制。這些 GPIO(代碼)通常從
+arch_initcall()或者更早的地方集成進平台初始化代碼,使這些 GPIO 總是可用,
+且他們通常可以作爲 IRQ 使用。
+
+板級支持
+-------
+對於外部 GPIO 控制器(例如 I2C 或 SPI 擴展器、專用晶片、多功能器件、FPGA
+或 CPLD),大多數常用板級特定代碼都可以註冊控制器設備,並保證他們的驅動知道
+gpiochip_add()所使用的 GPIO 編號。他們的起始編號通常跟在平台特定的 GPIO
+編號之後。
+
+例如板級啓動代碼應該創建結構體指明晶片公開的 GPIO 範圍,並使用 platform_data
+將其傳遞給每個 GPIO 擴展器晶片。然後晶片驅動中的 probe()例程可以將這個
+數據傳遞給 gpiochip_add()。
+
+初始化順序很重要。例如,如果一個設備依賴基於 I2C 的(擴展)GPIO,那麼它的
+probe()例程就應該在那個 GPIO 有效以後才可以被調用。這意味著設備應該在
+GPIO 可以工作之後才可被註冊。解決這類依賴的的一種方法是讓這種 gpio_chip
+控制器向板級特定代碼提供 setup()和 teardown()回調函數。一旦所有必須的
+資源可用之後,這些板級特定的回調函數將會註冊設備,並可以在這些 GPIO 控制器
+設備變成無效時移除它們。
+
+
+用戶空間的 Sysfs 接口(可選)
+========================
+使用「gpiolib」實現框架的平台可以選擇配置一個 GPIO 的 sysfs 用戶接口。
+這不同於 debugfs 接口,因爲它提供的是對 GPIO方向和值的控制,而不只顯示
+一個GPIO 的狀態摘要。此外,它可以出現在沒有調試支持的產品級系統中。
+
+例如,通過適當的系統硬體文檔,用戶空間可以知道 GIOP #23 控制 Flash
+存儲器的防寫(用於保護其中 Bootloader 分區)。產品的系統升級可能需要
+臨時解除這個保護:首先導入一個 GPIO,改變其輸出狀態,然後在重新使能防寫
+前升級代碼。通常情況下,GPIO #23 是不會被觸及的,並且內核也不需要知道他。
+
+根據適當的硬體文檔,某些系統的用戶空間 GPIO 可以用於確定系統配置數據,
+這些數據是標準內核不知道的。在某些任務中,簡單的用戶空間 GPIO 驅動可能是
+系統真正需要的。
+
+注意:標準內核驅動中已經存在通用的「LED 和按鍵」GPIO 任務,分別是:
+"leds-gpio" 和 "gpio_keys"。請使用這些來替代直接訪問 GPIO,因爲集成在
+內核框架中的這類驅動比你在用戶空間的代碼更好。
+
+
+Sysfs 中的路徑
+--------------
+在/sys/class/gpio 中有 3 類入口:
+
+ - 用於在用戶空間控制 GPIO 的控制接口;
+
+ - GPIOs 本身;以及
+
+ - GPIO 控制器 ("gpio_chip" 實例)。
+
+除了這些標準的文件,還包含「device」符號連結。
+
+控制接口是只寫的:
+
+ /sys/class/gpio/
+
+ "export" ... 用戶空間可以通過寫其編號到這個文件,要求內核導出
+ 一個 GPIO 的控制到用戶空間。
+
+ 例如: 如果內核代碼沒有申請 GPIO #19,"echo 19 > export"
+ 將會爲 GPIO #19 創建一個 "gpio19" 節點。
+
+ "unexport" ... 導出到用戶空間的逆操作。
+
+ 例如: "echo 19 > unexport" 將會移除使用"export"文件導出的
+ "gpio19" 節點。
+
+GPIO 信號的路徑類似 /sys/class/gpio/gpio42/ (對於 GPIO #42 來說),
+並有如下的讀/寫屬性:
+
+ /sys/class/gpio/gpioN/
+
+ "direction" ... 讀取得到 "in" 或 "out"。這個值通常運行寫入。
+ 寫入"out" 時,其引腳的默認輸出爲低電平。爲了確保無故障運行,
+ "low" 或 "high" 的電平值應該寫入 GPIO 的配置,作爲初始輸出值。
+
+ 注意:如果內核不支持改變 GPIO 的方向,或者在導出時內核代碼沒有
+ 明確允許用戶空間可以重新配置 GPIO 方向,那麼這個屬性將不存在。
+
+ "value" ... 讀取得到 0 (低電平) 或 1 (高電平)。如果 GPIO 配置爲
+ 輸出,這個值允許寫操作。任何非零值都以高電平看待。
+
+ 如果引腳可以配置爲中斷信號,且如果已經配置了產生中斷的模式
+ (見"edge"的描述),你可以對這個文件使用輪詢操作(poll(2)),
+ 且輪詢操作會在任何中斷觸發時返回。如果你使用輪詢操作(poll(2)),
+ 請在 events 中設置 POLLPRI 和 POLLERR。如果你使用輪詢操作
+ (select(2)),請在 exceptfds 設置你期望的文件描述符。在
+ 輪詢操作(poll(2))返回之後,既可以通過 lseek(2)操作讀取
+ sysfs 文件的開始部分,也可以關閉這個文件並重新打開它來讀取數據。
+
+ "edge" ... 讀取得到「none」、「rising」、「falling」或者「both」。
+ 將這些字符串寫入這個文件可以選擇沿觸發模式,會使得輪詢操作
+ (select(2))在"value"文件中返回。
+
+ 這個文件僅有在這個引腳可以配置爲可產生中斷輸入引腳時,才存在。
+
+ "active_low" ... 讀取得到 0 (假) 或 1 (真)。寫入任何非零值可以
+ 翻轉這個屬性的(讀寫)值。已存在或之後通過"edge"屬性設置了"rising"
+ 和 "falling" 沿觸發模式的輪詢操作(poll(2))將會遵循這個設置。
+
+GPIO 控制器的路徑類似 /sys/class/gpio/gpiochip42/ (對於從#42 GPIO
+開始實現控制的控制器),並有著以下只讀屬性:
+
+ /sys/class/gpio/gpiochipN/
+
+ "base" ... 與以上的 N 相同,代表此晶片管理的第一個 GPIO 的編號
+
+ "label" ... 用於診斷 (並不總是只有唯一值)
+
+ "ngpio" ... 此控制器所管理的 GPIO 數量(而 GPIO 編號從 N 到
+ N + ngpio - 1)
+
+大多數情況下,電路板的文檔應當標明每個 GPIO 的使用目的。但是那些編號並不總是
+固定的,例如在擴展卡上的 GPIO會根據所使用的主板或所在堆疊架構中其他的板子而
+有所不同。在這種情況下,你可能需要使用 gpiochip 節點(儘可能地結合電路圖)來
+確定給定信號所用的 GPIO 編號。
+
+
+從內核代碼中導出
+-------------
+內核代碼可以明確地管理那些已通過 gpio_request()申請的 GPIO 的導出:
+
+ /* 導出 GPIO 到用戶空間 */
+ int gpio_export(unsigned gpio, bool direction_may_change);
+
+ /* gpio_export()的逆操作 */
+ void gpio_unexport();
+
+ /* 創建一個 sysfs 連接到已導出的 GPIO 節點 */
+ int gpio_export_link(struct device *dev, const char *name,
+ unsigned gpio)
+
+在一個內核驅動申請一個 GPIO 之後,它可以通過 gpio_export()使其在 sysfs
+接口中可見。該驅動可以控制信號方向是否可修改。這有助於防止用戶空間代碼無意間
+破壞重要的系統狀態。
+
+這個明確的導出有助於(通過使某些實驗更容易來)調試,也可以提供一個始終存在的接口,
+與文檔配合作爲板級支持包的一部分。
+
+在 GPIO 被導出之後,gpio_export_link()允許在 sysfs 文件系統的任何地方
+創建一個到這個 GPIO sysfs 節點的符號連結。這樣驅動就可以通過一個描述性的
+名字,在 sysfs 中他們所擁有的設備下提供一個(到這個 GPIO sysfs 節點的)接口。
+
diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst
new file mode 100644
index 000000000000..c02c4b5281e6
--- /dev/null
+++ b/Documentation/translations/zh_TW/index.rst
@@ -0,0 +1,168 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. raw:: latex
+
+ \renewcommand\thesection*
+ \renewcommand\thesubsection*
+ \kerneldocCJKon
+ \kerneldocBeginTC
+
+.. _linux_doc_zh_tw:
+
+繁體中文翻譯
+============
+
+
+.. note::
+ 內核文檔繁體中文版的翻譯工作正在進行中。如果您願意並且有時間參與這項工
+ 作,歡迎提交補丁給胡皓文 <src.res@email.cn>。
+
+許可證文檔
+----------
+
+下面的文檔介紹了Linux內核原始碼的許可證(GPLv2)、如何在原始碼樹中正確標記
+單個文件的許可證、以及指向完整許可證文本的連結。
+
+Documentation/translations/zh_TW/process/license-rules.rst
+
+用戶文檔
+--------
+
+下面的手冊是爲內核用戶編寫的——即那些試圖讓它在給定系統上以最佳方式工作的
+用戶。
+
+.. toctree::
+ :maxdepth: 2
+
+ admin-guide/index
+
+TODOList:
+
+* kbuild/index
+
+固件相關文檔
+------------
+
+下列文檔描述了內核需要的平台固件相關信息。
+
+TODOList:
+
+* firmware-guide/index
+* devicetree/index
+
+應用程式開發人員文檔
+--------------------
+
+用戶空間API手冊涵蓋了描述應用程式開發人員可見內核接口方面的文檔。
+
+TODOlist:
+
+* userspace-api/index
+
+內核開發簡介
+------------
+
+這些手冊包含有關如何開發內核的整體信息。內核社區非常龐大,一年下來有數千名
+開發人員做出貢獻。與任何大型社區一樣,知道如何完成任務將使得更改合併的過程
+變得更加容易。
+
+.. toctree::
+ :maxdepth: 2
+
+ process/index
+
+TODOList:
+
+* dev-tools/index
+* doc-guide/index
+* kernel-hacking/index
+* trace/index
+* maintainer/index
+* fault-injection/index
+* livepatch/index
+* rust/index
+
+內核API文檔
+-----------
+
+以下手冊從內核開發人員的角度詳細介紹了特定的內核子系統是如何工作的。這裡的
+大部分信息都是直接從內核原始碼獲取的,並根據需要添加補充材料(或者至少是在
+我們設法添加的時候——可能不是所有的都是有需要的)。
+
+TODOList:
+
+* driver-api/index
+* core-api/index
+* locking/index
+* accounting/index
+* block/index
+* cdrom/index
+* cpu-freq/index
+* ide/index
+* fb/index
+* fpga/index
+* hid/index
+* i2c/index
+* iio/index
+* isdn/index
+* infiniband/index
+* leds/index
+* netlabel/index
+* networking/index
+* pcmcia/index
+* power/index
+* target/index
+* timers/index
+* spi/index
+* w1/index
+* watchdog/index
+* virt/index
+* input/index
+* hwmon/index
+* gpu/index
+* security/index
+* sound/index
+* crypto/index
+* filesystems/index
+* vm/index
+* bpf/index
+* usb/index
+* PCI/index
+* scsi/index
+* misc-devices/index
+* scheduler/index
+* mhi/index
+
+體系結構無關文檔
+----------------
+
+TODOList:
+
+* asm-annotations
+
+特定體系結構文檔
+----------------
+
+TODOList:
+
+* arch
+
+其他文檔
+--------
+
+有幾份未排序的文檔似乎不適合放在文檔的其他部分,或者可能需要進行一些調整和/或
+轉換爲reStructureText格式,也有可能太舊。
+
+TODOList:
+
+* staging/index
+* watch_queue
+
+目錄和表格
+----------
+
+* :ref:`genindex`
+
+.. raw:: latex
+
+ \kerneldocEndTC
diff --git a/Documentation/translations/zh_TW/io_ordering.txt b/Documentation/translations/zh_TW/io_ordering.txt
new file mode 100644
index 000000000000..1e99206c8421
--- /dev/null
+++ b/Documentation/translations/zh_TW/io_ordering.txt
@@ -0,0 +1,68 @@
+Chinese translated version of Documentation/driver-api/io_ordering.rst
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Traditional Chinese maintainer: Hu Haowen <src.res@email.cn>
+---------------------------------------------------------------------
+Documentation/driver-api/io_ordering.rst 的繁體中文翻譯
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或
+者翻譯存在問題,請聯繫繁體中文版維護者。
+
+繁體中文版維護者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版翻譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版校譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+
+
+以下爲正文
+---------------------------------------------------------------------
+
+在某些平台上,所謂的內存映射I/O是弱順序。在這些平台上,驅動開發者有責任
+保證I/O內存映射地址的寫操作按程序圖意的順序達到設備。通常讀取一個「安全」
+設備寄存器或橋寄存器,觸發IO晶片清刷未處理的寫操作到達設備後才處理讀操作,
+而達到保證目的。驅動程序通常在spinlock保護的臨界區退出之前使用這種技術。
+這也可以保證後面的寫操作只在前面的寫操作之後到達設備(這非常類似於內存
+屏障操作,mb(),不過僅適用於I/O)。
+
+假設一個設備驅動程的具體例子:
+
+ ...
+CPU A: spin_lock_irqsave(&dev_lock, flags)
+CPU A: val = readl(my_status);
+CPU A: ...
+CPU A: writel(newval, ring_ptr);
+CPU A: spin_unlock_irqrestore(&dev_lock, flags)
+ ...
+CPU B: spin_lock_irqsave(&dev_lock, flags)
+CPU B: val = readl(my_status);
+CPU B: ...
+CPU B: writel(newval2, ring_ptr);
+CPU B: spin_unlock_irqrestore(&dev_lock, flags)
+ ...
+
+上述例子中,設備可能會先接收到newval2的值,然後接收到newval的值,問題就
+發生了。不過很容易通過下面方法來修復:
+
+ ...
+CPU A: spin_lock_irqsave(&dev_lock, flags)
+CPU A: val = readl(my_status);
+CPU A: ...
+CPU A: writel(newval, ring_ptr);
+CPU A: (void)readl(safe_register); /* 配置寄存器?*/
+CPU A: spin_unlock_irqrestore(&dev_lock, flags)
+ ...
+CPU B: spin_lock_irqsave(&dev_lock, flags)
+CPU B: val = readl(my_status);
+CPU B: ...
+CPU B: writel(newval2, ring_ptr);
+CPU B: (void)readl(safe_register); /* 配置寄存器?*/
+CPU B: spin_unlock_irqrestore(&dev_lock, flags)
+
+在解決方案中,讀取safe_register寄存器,觸發IO晶片清刷未處理的寫操作,
+再處理後面的讀操作,防止引發數據不一致問題。
+
diff --git a/Documentation/translations/zh_TW/oops-tracing.txt b/Documentation/translations/zh_TW/oops-tracing.txt
new file mode 100644
index 000000000000..be8e59f2abaf
--- /dev/null
+++ b/Documentation/translations/zh_TW/oops-tracing.txt
@@ -0,0 +1,212 @@
+Chinese translated version of Documentation/admin-guide/bug-hunting.rst
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Traditional Chinese maintainer: Hu Haowen <src.res@email.cn>
+---------------------------------------------------------------------
+Documentation/admin-guide/bug-hunting.rst 的繁體中文版翻譯
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或
+者翻譯存在問題,請聯繫繁體中文版維護者。
+
+繁體中文版維護者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版翻譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版校譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+
+以下爲正文
+---------------------------------------------------------------------
+
+注意: ksymoops 在2.6中是沒有用的。 請以原有格式使用Oops(來自dmesg,等等)。
+忽略任何這樣那樣關於「解碼Oops」或者「通過ksymoops運行」的文檔。 如果你貼出運行過
+ksymoops的來自2.6的Oops,人們只會讓你重貼一次。
+
+快速總結
+-------------
+
+發現Oops並發送給看似相關的內核領域的維護者。別太擔心對不上號。如果你不確定就發給
+和你所做的事情相關的代碼的負責人。 如果可重現試著描述怎樣重構。 那甚至比oops更有
+價值。
+
+如果你對於發送給誰一無所知, 發給linux-kernel@vger.kernel.org。感謝你幫助Linux
+儘可能地穩定。
+
+Oops在哪裡?
+----------------------
+
+通常Oops文本由klogd從內核緩衝區里讀取並傳給syslogd,由syslogd寫到syslog文件中,
+典型地是/var/log/messages(依賴於/etc/syslog.conf)。有時klogd崩潰了,這種情況下你
+能夠運行dmesg > file來從內核緩衝區中讀取數據並保存下來。 否則你可以
+cat /proc/kmsg > file, 然而你必須介入中止傳輸, kmsg是一個「永不結束的文件」。如
+果機器崩潰壞到你不能輸入命令或者磁碟不可用那麼你有三種選擇:-
+
+(1) 手抄屏幕上的文本待機器重啓後再輸入計算機。 麻煩但如果沒有針對崩潰的準備,
+這是僅有的選擇。 另外,你可以用數位相機把屏幕拍下來-不太好,但比沒有強。 如果信
+息滾動到了終端的上面,你會發現以高分辯率啓動(比如,vga=791)會讓你讀到更多的文
+本。(注意:這需要vesafb,所以對『早期』的oops沒有幫助)
+
+(2)用串口終端啓動(請參看Documentation/admin-guide/serial-console.rst),運行一個null
+modem到另一台機器並用你喜歡的通訊工具獲取輸出。Minicom工作地很好。
+
+(3)使用Kdump(請參看Documentation/admin-guide/kdump/kdump.rst),
+使用在Documentation/admin-guide/kdump/gdbmacros.txt中定義的dmesg gdb宏,從舊的內存中提取內核
+環形緩衝區。
+
+完整信息
+----------------
+
+注意:以下來自於Linus的郵件適用於2.4內核。 我因爲歷史原因保留了它,並且因爲其中
+一些信息仍然適用。 特別注意的是,請忽略任何ksymoops的引用。
+
+From: Linus Torvalds <torvalds@osdl.org>
+
+怎樣跟蹤Oops.. [原發到linux-kernel的一封郵件]
+
+主要的竅門是有五年和這些煩人的oops消息打交道的經驗;-)
+
+實際上,你有辦法使它更簡單。我有兩個不同的方法:
+
+ gdb /usr/src/linux/vmlinux
+ gdb> disassemble <offending_function>
+
+那是發現問題的簡單辦法,至少如果bug報告做的好的情況下(象這個一樣-運行ksymoops
+得到oops發生的函數及函數內的偏移)。
+
+哦,如果報告發生的內核以相同的編譯器和相似的配置編譯它會有幫助的。
+
+另一件要做的事是反彙編bug報告的「Code」部分:ksymoops也會用正確的工具來做這件事,
+但如果沒有那些工具你可以寫一個傻程序:
+
+ char str[] = "\xXX\xXX\xXX...";
+ main(){}
+
+並用gcc -g編譯它然後執行「disassemble str」(XX部分是由Oops報告的值-你可以僅剪切
+粘貼並用「\x」替換空格-我就是這麼做的,因爲我懶得寫程序自動做這一切)。
+
+另外,你可以用scripts/decodecode這個shell腳本。它的使用方法是:
+decodecode < oops.txt
+
+「Code」之後的十六進位字節可能(在某些架構上)有一些當前指令之前的指令字節以及
+當前和之後的指令字節
+
+Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
+64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
+7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
+
+最後,如果你想知道代碼來自哪裡,你可以:
+
+ cd /usr/src/linux
+ make fs/buffer.s # 或任何產生BUG的文件
+
+然後你會比gdb反彙編更清楚的知道發生了什麼。
+
+現在,問題是把你所擁有的所有數據結合起來:C源碼(關於它應該怎樣的一般知識),
+彙編代碼及其反彙編得到的代碼(另外還有從「oops」消息得到的寄存器狀態-對了解毀壞的
+指針有用,而且當你有了彙編代碼你也能拿其它的寄存器和任何它們對應的C表達式做匹配
+)。
+
+實際上,你僅需看看哪裡不匹配(這個例子是「Code」反彙編和編譯器生成的代碼不匹配)。
+然後你須要找出爲什麼不匹配。通常很簡單-你看到代碼使用了空指針然後你看代碼想知道
+空指針是怎麼出現的,還有檢查它是否合法..
+
+現在,如果明白這是一項耗時的工作而且需要一丁點兒的專心,沒錯。這就是我爲什麼大多
+只是忽略那些沒有符號表信息的崩潰報告的原因:簡單的說太難查找了(我有一些
+程序用於在內核代碼段中搜索特定的模式,而且有時我也已經能找出那些崩潰的地方,但是
+僅僅是找出正確的序列也確實需要相當紮實的內核知識)
+
+_有時_會發生這種情況,我僅看到崩潰中的反彙編代碼序列, 然後我馬上就明白問題出在
+哪裡。這時我才意識到自己幹這個工作已經太長時間了;-)
+
+ Linus
+
+
+---------------------------------------------------------------------------
+關於Oops跟蹤的註解:
+
+爲了幫助Linus和其它內核開發者,klogd納入了大量的支持來處理保護錯誤。爲了擁有對
+地址解析的完整支持至少應該使用1.3-pl3的sysklogd包。
+
+當保護錯誤發生時,klogd守護進程自動把內核日誌信息中的重要地址翻譯成它們相應的符
+號。
+
+klogd執行兩種類型的地址解析。首先是靜態翻譯其次是動態翻譯。靜態翻譯和ksymoops
+一樣使用System.map文件。爲了做靜態翻譯klogd守護進程必須在初始化時能找到system
+map文件。關於klogd怎樣搜索map文件請參看klogd手冊頁。
+
+動態地址翻譯在使用內核可裝載模塊時很重要。 因爲內核模塊的內存是從內核動態內存池
+里分配的,所以不管是模塊開始位置還是模塊中函數和符號的位置都不是固定的。
+
+內核支持允許程序決定裝載哪些模塊和它們在內存中位置的系統調用。使用這些系統調用
+klogd守護進程生成一張符號表用於調試發生在可裝載模塊中的保護錯誤。
+
+至少klogd會提供產生保護錯誤的模塊名。還可有額外的符號信息供可裝載模塊開發者選擇
+以從模塊中輸出符號信息。
+
+因爲內核模塊環境可能是動態的,所以必須有一種機制當模塊環境發生改變時來通知klogd
+守護進程。 有一些可用的命令行選項允許klogd向當前執行中的守護進程發送信號,告知符
+號信息應該被刷新了。 更多信息請參看klogd手冊頁。
+
+sysklogd發布時包含一個補丁修改了modules-2.0.0包,無論何時一個模塊裝載或者卸載都
+會自動向klogd發送信號。打上這個補丁提供了必要的對調試發生於內核可裝載模塊的保護
+錯誤的無縫支持。
+
+以下是被klogd處理過的發生在可裝載模塊中的一個保護錯誤例子:
+---------------------------------------------------------------------------
+Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
+Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
+Aug 29 09:51:01 blizard kernel: *pde = 00000000
+Aug 29 09:51:01 blizard kernel: Oops: 0002
+Aug 29 09:51:01 blizard kernel: CPU: 0
+Aug 29 09:51:01 blizard kernel: EIP: 0010:[oops:_oops+16/3868]
+Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
+Aug 29 09:51:01 blizard kernel: eax: 315e97cc ebx: 003a6f80 ecx: 001be77b edx: 00237c0c
+Aug 29 09:51:01 blizard kernel: esi: 00000000 edi: bffffdb3 ebp: 00589f90 esp: 00589f8c
+Aug 29 09:51:01 blizard kernel: ds: 0018 es: 0018 fs: 002b gs: 002b ss: 0018
+Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
+Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
+Aug 29 09:51:01 blizard kernel: 00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
+Aug 29 09:51:01 blizard kernel: bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
+Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
+Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
+---------------------------------------------------------------------------
+
+Dr. G.W. Wettstein Oncology Research Div. Computing Facility
+Roger Maris Cancer Center INTERNET: greg@wind.rmcc.com
+820 4th St. N.
+Fargo, ND 58122
+Phone: 701-234-7556
+
+
+---------------------------------------------------------------------------
+受汙染的內核
+
+一些oops報告在程序記數器之後包含字符串'Tainted: '。這表明內核已經被一些東西給汙
+染了。 該字符串之後緊跟著一系列的位置敏感的字符,每個代表一個特定的汙染值。
+
+ 1:'G'如果所有裝載的模塊都有GPL或相容的許可證,'P'如果裝載了任何的專有模塊。
+沒有模塊MODULE_LICENSE或者帶有insmod認爲是與GPL不相容的的MODULE_LICENSE的模塊被
+認定是專有的。
+
+ 2:'F'如果有任何通過「insmod -f」被強制裝載的模塊,' '如果所有模塊都被正常裝載。
+
+ 3:'S'如果oops發生在SMP內核中,運行於沒有證明安全運行多處理器的硬體。 當前這種
+情況僅限於幾種不支持SMP的速龍處理器。
+
+ 4:'R'如果模塊通過「insmod -f」被強制裝載,' '如果所有模塊都被正常裝載。
+
+ 5:'M'如果任何處理器報告了機器檢查異常,' '如果沒有發生機器檢查異常。
+
+ 6:'B'如果頁釋放函數發現了一個錯誤的頁引用或者一些非預期的頁標誌。
+
+ 7:'U'如果用戶或者用戶應用程式特別請求設置汙染標誌,否則' '。
+
+ 8:'D'如果內核剛剛死掉,比如有OOPS或者BUG。
+
+使用'Tainted: '字符串的主要原因是要告訴內核調試者,這是否是一個乾淨的內核亦或發
+生了任何的不正常的事。汙染是永久的:即使出錯的模塊已經被卸載了,汙染值仍然存在,
+以表明內核不再值得信任。
+
diff --git a/Documentation/translations/zh_TW/process/1.Intro.rst b/Documentation/translations/zh_TW/process/1.Intro.rst
new file mode 100644
index 000000000000..ca2b931be6c5
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/1.Intro.rst
@@ -0,0 +1,199 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_intro:
+
+引言
+====
+
+內容提要
+--------
+
+本節的其餘部分涵蓋了內核開發的過程,以及開發人員及其僱主在這方面可能遇到的
+各種問題。有很多原因使內核代碼應被合併到正式的(「主線」)內核中,包括對用戶
+的自動可用性、多種形式的社區支持以及影響內核開發方向的能力。提供給Linux內核
+的代碼必須在與GPL兼容的許可證下可用。
+
+:ref:`tw_development_process` 介紹了開發過程、內核發布周期和合併窗口的機制。
+涵蓋了補丁開發、審查和合併周期中的各個階段。還有一些關於工具和郵件列表的討論?
+鼓勵希望開始內核開發的開發人員跟蹤並修復缺陷以作爲初步練習。
+
+
+:ref:`tw_development_early_stage` 包括項目的早期規劃,重點是儘快讓開發社區
+參與進來。
+
+:ref:`tw_development_coding` 是關於編程過程的;介紹了其他開發人員遇到的幾個
+陷阱。也涵蓋了對補丁的一些要求,並且介紹了一些工具,這些工具有助於確保內核
+補丁是正確的。
+
+:ref:`tw_development_posting` 描述發布補丁以供評審的過程。爲了讓開發社區能
+認真對待,補丁必須被正確格式化和描述,並且必須發送到正確的地方。遵循本節中的
+建議有助於確保您的工作能被較好地接納。
+
+:ref:`tw_development_followthrough` 介紹了發布補丁之後發生的事情;工作在這時
+還遠遠沒有完成。與審閱者一起工作是開發過程中的一個重要部分;本節提供了一些
+關於如何在這個重要階段避免問題的提示。當補丁被合併到主線中時,開發人員要注意
+不要假定任務已經完成。
+
+:ref:`tw_development_advancedtopics` 介紹了兩個「高級」主題:使用Git管理補丁
+和查看其他人發布的補丁。
+
+:ref:`tw_development_conclusion` 總結了有關內核開發的更多信息,附帶有相關資源
+連結。
+
+這個文檔是關於什麼的
+--------------------
+
+Linux內核有超過800萬行代碼,每個版本的貢獻者超過1000人,是現存最大、最活躍的
+免費軟體項目之一。從1991年開始,這個內核已經發展成爲一個最好的作業系統組件,
+運行在袖珍數位音樂播放器、桌上型電腦、現存最大的超級計算機以及所有類型的系統上。
+它是一種適用於幾乎任何情況的健壯、高效和可擴展的解決方案。
+
+隨著Linux的發展,希望參與其開發的開發人員(和公司)的數量也在增加。硬體供應商
+希望確保Linux能夠很好地支持他們的產品,使這些產品對Linux用戶具有吸引力。嵌入
+式系統供應商使用Linux作爲集成產品的組件,希望Linux能夠儘可能地勝任手頭的任務。
+分銷商和其他基於Linux的軟體供應商切實關心Linux內核的功能、性能和可靠性。最終
+用戶也常常希望修改Linux,使之能更好地滿足他們的需求。
+
+Linux最引人注目的特性之一是這些開發人員可以訪問它;任何具備必要技能的人都可以
+改進Linux並影響其開發方向。專有產品不能提供這種開放性,這是自由軟體的一個特點。
+如果有什麼不同的話,那就是內核比大多數其他自由軟體項目更開放。一個典型的三個
+月內核開發周期可以涉及1000多個開發人員,他們爲100多個不同的公司(或者根本不
+隸屬公司)工作。
+
+與內核開發社區合作並不是特別困難。但儘管如此,仍有許多潛在的貢獻者在嘗試做
+內核工作時遇到了困難。內核社區已經發展出自己獨特的操作方式,使其能夠在每天
+都要更改數千行代碼的環境中順利運行(並生成高質量的產品)。因此,Linux內核開發
+過程與專有的開發模式有很大的不同也就不足爲奇了。
+
+對於新開發人員來說,內核的開發過程可能會讓人感到奇怪和恐懼,但這背後有充分的
+理由和堅實的經驗。一個不了解內核社區工作方式的開發人員(或者更糟的是,他們
+試圖拋棄或規避之)會得到令人沮喪的體驗。開發社區在幫助那些試圖學習的人的同時,
+沒有時間幫助那些不願意傾聽或不關心開發過程的人。
+
+希望閱讀本文的人能夠避免這種令人沮喪的經歷。這些材料很長,但閱讀它們時所做的
+努力會在短時間內得到回報。開發社區總是需要能讓內核變更好的開發人員;下面的
+文字應該幫助您或爲您工作的人員加入我們的社區。
+
+致謝
+----
+
+本文檔由Jonathan Corbet <corbet@lwn.net> 撰寫。以下人員的建議使之更爲完善:
+Johannes Berg, James Berry, Alex Chiang, Roland Dreier, Randy Dunlap,
+Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda McPherson,
+Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
+
+這項工作得到了Linux基金會的支持,特別感謝Amanda McPherson,他看到了這項工作
+的價值並將其變成現實。
+
+代碼進入主線的重要性
+--------------------
+
+有些公司和開發人員偶爾會想,爲什麼他們要費心學習如何與內核社區合作,並將代碼
+放入主線內核(「主線」是由Linus Torvalds維護的內核,Linux發行商將其用作基礎)。
+在短期內,貢獻代碼看起來像是一種可以避免的開銷;維護獨立代碼並直接支持用戶
+似乎更容易。事實上,保持代碼獨立(「樹外」)是在經濟上是錯誤的。
+
+爲了說明樹外代碼成本,下面給出內核開發過程的一些相關方面;本文稍後將更詳細地
+討論其中的大部分內容。請考慮:
+
+- 所有Linux用戶都可以使用合併到主線內核中的代碼。它將自動出現在所有啓用它的
+ 發行版上。無需驅動程序磁碟、額外下載,也不需要爲多個發行版的多個版本提供
+ 支持;這一切將方便所有開發人員和用戶。併入主線解決了大量的分發和支持問題。
+
+- 當內核開發人員努力維護一個穩定的用戶空間接口時,內核內部API處於不斷變化之中。
+ 不維持穩定的內部接口是一個慎重的設計決策;它允許在任何時候進行基本的改進,
+ 並產出更高質量的代碼。但該策略導致結果是,若要使用新的內核,任何樹外代碼都
+ 需要持續的維護。維護樹外代碼會需要大量的工作才能使代碼保持正常運行。
+
+ 相反,位於主線中的代碼不需要這樣做,因爲基本規則要求進行API更改的任何開發
+ 人員也必須修復由於該更改而破壞的任何代碼。因此,合併到主線中的代碼大大降低
+ 了維護成本。
+
+- 除此之外,內核中的代碼通常會被其他開發人員改進。您授權的用戶社區和客戶對您
+ 產品的改進可能會令人驚喜。
+
+- 內核代碼在合併到主線之前和之後都要經過審查。無論原始開發人員的技能有多強,
+ 這個審查過程總是能找到改進代碼的方法。審查經常發現嚴重的錯誤和安全問題。
+ 對於在封閉環境中開發的代碼尤其如此;這種代碼從外部開發人員的審查中獲益匪淺。
+ 樹外代碼是低質量代碼。
+
+- 參與開發過程是您影響內核開發方向的方式。旁觀者的抱怨會被聽到,但是活躍的
+ 開發人員有更強的聲音——並且能夠實現使內核更好地滿足其需求的更改。
+
+- 當單獨維護代碼時,總是存在第三方爲類似功能提供不同實現的可能性。如果發生
+ 這種情況,合併代碼將變得更加困難——甚至成爲不可能。之後,您將面臨以下令人
+ 不快的選擇:(1)無限期地維護樹外的非標準特性,或(2)放棄代碼並將用戶遷移
+ 到樹內版本。
+
+- 代碼的貢獻是使整個流程工作的根本。通過貢獻代碼,您可以向內核添加新功能,並
+ 提供其他內核開發人員使用的功能和示例。如果您已經爲Linux開發了代碼(或者正在
+ 考慮這樣做),那麼您顯然對這個平台的持續成功感興趣;貢獻代碼是確保成功的
+ 最好方法之一。
+
+上述所有理由都適用於任何樹外內核代碼,包括以專有的、僅二進位形式分發的代碼。
+然而,在考慮任何類型的純二進位內核代碼分布之前,還需要考慮其他因素。包括:
+
+- 圍繞專有內核模塊分發的法律問題其實較爲模糊;相當多的內核版權所有者認爲,
+ 大多數僅二進位的模塊是內核的派生產品,因此,它們的分發違反了GNU通用公共
+ 許可證(下面將詳細介紹)。本文作者不是律師,本文檔中的任何內容都不可能被
+ 視爲法律建議。封閉原始碼模塊的真實法律地位只能由法院決定。但不管怎樣,困擾
+ 這些模塊的不確定性仍然存在。
+
+- 二進位模塊大大增加了調試內核問題的難度,以至於大多數內核開發人員甚至都不會
+ 嘗試。因此,只分發二進位模塊將使您的用戶更難從社區獲得支持。
+
+- 對於僅二進位的模塊的發行者來說,支持也更加困難,他們必須爲他們希望支持的
+ 每個發行版和每個內核版本提供不同版本的模塊。爲了提供較爲全面的覆蓋範圍,
+ 可能需要一個模塊的幾十個構建,並且每次升級內核時,您的用戶都必須單獨升級
+ 這些模塊。
+
+- 上面提到的關於代碼評審的所有問題都更加存在於封閉原始碼中。由於該代碼根本
+ 不可得,因此社區無法對其進行審查,毫無疑問,它將存在嚴重問題。
+
+尤其是嵌入式系統的製造商,可能會傾向於忽視本節中所說的大部分內容;因爲他們
+相信自己正在商用一種使用凍結內核版本的獨立產品,在發布後不需要再進行開發。
+這個論點忽略了廣泛的代碼審查的價值以及允許用戶向產品添加功能的價值。但這些
+產品的商業壽命有限,之後必須發布新版本的產品。在這一點上,代碼在主線上並得到
+良好維護的供應商將能夠更好地占位,以使新產品快速上市。
+
+許可
+----
+
+代碼是根據一些許可證提供給Linux內核的,但是所有代碼都必須與GNU通用公共許可
+證(GPLV2)的版本2兼容,該版本是覆蓋整個內核分發的許可證。在實踐中,這意味
+著所有代碼貢獻都由GPLv2(可選地,語言允許在更高版本的GPL下分發)或3子句BSD
+許可(New BSD License,譯者注)覆蓋。任何不包含在兼容許可證中的貢獻都不會
+被接受到內核中。
+
+貢獻給內核的代碼不需要(或請求)版權分配。合併到主線內核中的所有代碼都保留
+其原始所有權;因此,內核現在擁有數千個所有者。
+
+這種所有權結構也暗示著,任何改變內核許可的嘗試都註定會失敗。很少有實際情況
+可以獲得所有版權所有者的同意(或者從內核中刪除他們的代碼)。因此,尤其是在
+可預見的將來,許可證不大可能遷移到GPL的版本3。
+
+所有貢獻給內核的代碼都必須是合法的免費軟體。因此,不接受匿名(或化名)貢獻
+者的代碼。所有貢獻者都需要在他們的代碼上「sign off(簽發)」,聲明代碼可以
+在GPL下與內核一起分發。無法提供未被其所有者許可爲免費軟體的代碼,或可能爲
+內核造成版權相關問題的代碼(例如,由缺乏適當保護的反向工程工作派生的代碼)
+不能被接受。
+
+有關版權問題的提問在Linux開發郵件列表中很常見。這樣的問題通常會得到不少答案,
+但請記住,回答這些問題的人不是律師,不能提供法律諮詢。如果您有關於Linux原始碼
+的法律問題,沒有什麼可以代替諮詢了解這一領域的律師。依賴從技術郵件列表中獲得
+的答案是一件冒險的事情。
+
+
diff --git a/Documentation/translations/zh_TW/process/2.Process.rst b/Documentation/translations/zh_TW/process/2.Process.rst
new file mode 100644
index 000000000000..b01cdd3a39ae
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/2.Process.rst
@@ -0,0 +1,369 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/2.Process.rst <development_process>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process:
+
+開發流程如何進行
+================
+
+90年代早期的Linux內核開發是一件相當鬆散的事情,涉及的用戶和開發人員相對較少。
+由於擁有數以百萬計的用戶羣,且每年有大約2000名開發人員參與進來,內核因此必須
+發展出許多既定流程來保證開發的順利進行。要參與到流程中來,需要對此流程的進行
+方式有一個紮實的理解。
+
+總覽
+----
+
+內核開發人員使用一個鬆散的基於時間的發布過程,每兩到三個月發布一次新的主要
+內核版本。最近的發布歷史記錄如下:
+
+ ====== =================
+ 5.0 2019年3月3日
+ 5.1 2019年5月5日
+ 5.2 2019年7月7日
+ 5.3 2019年9月15日
+ 5.4 2019年11月24日
+ 5.5 2020年1月6日
+ ====== =================
+
+每個5.x版本都是一個主要的內核版本,具有新特性、內部API更改等等。一個典型的5.x
+版本包含大約13000個變更集,變更了幾十萬行代碼。因此,5.x是Linux內核開發的前
+沿;內核使用滾動開發模型,不斷集成重大變化。
+
+對於每個版本的補丁合併,遵循一個相對簡單的規則。在每個開發周期的開頭,「合併
+窗口」被打開。這時,被認爲足夠穩定(並且被開發社區接受)的代碼被合併到主線內
+核中。在這段時間內,新開發周期的大部分變更(以及所有主要變更)將以接近每天
+1000次變更(「補丁」或「變更集」)的速度合併。
+
+(順便說一句,值得注意的是,合併窗口期間集成的更改並不是憑空產生的;它們是經
+提前收集、測試和分級的。稍後將詳細描述該過程的工作方式。)
+
+合併窗口持續大約兩周。在這段時間結束時,LinusTorvalds將聲明窗口已關閉,並
+釋放第一個「rc」內核。例如,對於目標爲5.6的內核,在合併窗口結束時發生的釋放
+將被稱爲5.6-rc1。-rc1 版本是一個信號,表示合併新特性的時間已經過去,穩定下一
+個內核的時間已經到來。
+
+在接下來的6到10周內,只有修復問題的補丁才應該提交給主線。有時會允許更大的
+更改,但這種情況很少發生;試圖在合併窗口外合併新功能的開發人員往往受不到
+友好的接待。一般來說,如果您錯過了給定特性的合併窗口,最好的做法是等待下一
+個開發周期。(偶爾會對未支持硬體的驅動程序進行例外;如果它們不改變已有代碼,
+則不會導致回歸,應該可以隨時被安全地加入)。
+
+隨著修復程序進入主線,補丁速度將隨著時間的推移而變慢。Linus大約每周發布一次
+新的-rc內核;在內核被認爲足夠穩定並最終發布前,一般會達到-rc6到-rc9之間。
+然後,整個過程又重新開始了。
+
+例如,這裡是5.4的開發周期進行情況(2019年):
+
+ ============== ==============================
+ 九月 15 5.3 穩定版發布
+ 九月 30 5.4-rc1 合併窗口關閉
+ 十月 6 5.4-rc2
+ 十月 13 5.4-rc3
+ 十月 20 5.4-rc4
+ 十月 27 5.4-rc5
+ 十一月 3 5.4-rc6
+ 十一月 10 5.4-rc7
+ 十一月 17 5.4-rc8
+ 十一月 24 5.4 穩定版發布
+ ============== ==============================
+
+開發人員如何決定何時結束開發周期並創建穩定版本?最重要的指標是以前版本的
+回歸列表。不歡迎出現任何錯誤,但是那些破壞了以前能工作的系統的錯誤被認爲是
+特別嚴重的。因此,導致回歸的補丁是不受歡迎的,很可能在穩定期內刪除。
+
+開發人員的目標是在穩定發布之前修復所有已知的回歸。在現實世界中,這種完美是
+很難實現的;在這種規模的項目中,變數太多了。需要說明的是,延遲最終版本只會
+使問題變得更糟;等待下一個合併窗口的更改將變多,導致下次出現更多的回歸錯誤。
+因此,大多數5.x內核都有一些已知的回歸錯誤,不過,希望沒有一個是嚴重的。
+
+一旦一個穩定的版本發布,它的持續維護工作就被移交給「穩定團隊」,目前由
+Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案不定期地發布穩定版本的
+更新。要合入更新版本,補丁必須(1)修復一個重要的缺陷,且(2)已經合併到
+下一個開發版本主線中。內核通常會在其初始版本後的一個以上的開發周期內收到
+穩定版更新。例如,5.2內核的歷史如下(2019年):
+
+ ============== ===============================
+ 七月 7 5.2 穩定版發布
+ 七月 13 5.2.1
+ 七月 21 5.2.2
+ 七月 26 5.2.3
+ 七月 28 5.2.4
+ 七月 31 5.2.5
+ ... ...
+ 十月 11 5.2.21
+ ============== ===============================
+
+5.2.21是5.2版本的最終穩定更新。
+
+有些內核被指定爲「長期」內核;它們將得到更長時間的支持。在本文中,當前的長期
+內核及其維護者是:
+
+ ====== ================================ ================
+ 3.16 Ben Hutchings (長期穩定內核)
+ 4.4 Greg Kroah-Hartman & Sasha Levin (長期穩定內核)
+ 4.9 Greg Kroah-Hartman & Sasha Levin
+ 4.14 Greg Kroah-Hartman & Sasha Levin
+ 4.19 Greg Kroah-Hartman & Sasha Levin
+ 5.4 Greg Kroah-Hartman & Sasha Levin
+ ====== ================================ ================
+
+長期支持內核的選擇純粹是維護人員是否有需求和時間來維護該版本的問題。
+目前還沒有爲即將發布的任何特定版本提供長期支持的已知計劃。
+
+補丁的生命周期
+--------------
+
+補丁不會直接從開發人員的鍵盤進入主線內核。相反,有一個稍微複雜(如果有些非
+正式)的過程,旨在確保對每個補丁進行質量審查,並確保每個補丁實現了一個在主線
+中需要的更改。對於小的修復,這個過程可能會很快完成,,而對於較大或有爭議的
+變更,可能會持續數年。許多開發人員的沮喪來自於對這個過程缺乏理解或者試圖繞過它。
+
+爲了減少這種挫敗,本文將描述補丁如何進入內核。下面的介紹以一種較爲理想化的
+方式描述了這個過程。更詳細的過程將在後面的章節中介紹。
+
+補丁通常要經歷以下階段:
+
+- 設計。這就是補丁的真正需求——以及滿足這些需求的方式——所在。設計工作通常
+ 是在不涉及社區的情況下完成的,但是如果可能的話,最好是在公開的情況下完成
+ 這項工作;這樣可以節省很多稍後再重新設計的時間。
+
+- 早期評審。補丁被發布到相關的郵件列表中,列表中的開發人員會回復他們可能有
+ 的任何評論。如果一切順利的話,這個過程應該會發現補丁的任何主要問題。
+
+- 更廣泛的評審。當補丁接近準備好納入主線時,它應該被相關的子系統維護人員
+ 接受——儘管這種接受並不能保證補丁會一直延伸到主線。補丁將出現在維護人員的
+ 子系統樹中,並進入 -next 樹(如下所述)。當流程進行時,此步驟將會對補丁
+ 進行更廣泛的審查,並發現由於將此補丁與其他人所做的工作合併而導致的任何
+ 問題。
+
+- 請注意,大多數維護人員也有日常工作,因此合併補丁可能不是他們的最優先工作。
+ 如果您的補丁得到了需要更改的反饋,那麼您應該進行這些更改,或者解釋爲何
+ 不應該進行這些更改。如果您的補丁沒有評審意見,也沒有被其相應的子系統或
+ 驅動程序維護者接受,那麼您應該堅持不懈地將補丁更新到當前內核使其可被正常
+ 應用,並不斷地發送它以供審查和合併。
+
+- 合併到主線。最終,一個成功的補丁將被合併到由LinusTorvalds管理的主線存儲庫
+ 中。此時可能會出現更多的評論和/或問題;對開發人員來說應對這些問題並解決
+ 出現的任何問題仍很重要。
+
+- 穩定版發布。大量用戶可能受此補丁影響,因此可能再次出現新的問題。
+
+- 長期維護。雖然開發人員在合併代碼後可能會忘記代碼,但這種行爲往往會給開發
+ 社區留下不良印象。合併代碼消除了一些維護負擔,因爲其他人將修復由API更改
+ 引起的問題。但是,如果代碼要長期保持可用,原始開發人員應該繼續爲代碼負責。
+
+內核開發人員(或他們的僱主)犯的最大錯誤之一是試圖將流程簡化爲一個「合併到
+主線」步驟。這種方法總是會讓所有相關人員感到沮喪。
+
+補丁如何進入內核
+----------------
+
+只有一個人可以將補丁合併到主線內核存儲庫中:LinusTorvalds。但是,在進入
+2.6.38內核的9500多個補丁中,只有112個(大約1.3%)是由Linus自己直接選擇的。
+內核項目已經發展到一個沒有一個開發人員可以在沒有支持的情況下檢查和選擇每個
+補丁的規模。內核開發人員處理這種增長的方式是使用圍繞信任鏈構建的助理系統。
+
+內核代碼庫在邏輯上被分解爲一組子系統:網絡、特定體系結構支持、內存管理、視
+頻設備等。大多數子系統都有一個指定的維護人員,其總體負責該子系統中的代碼。
+這些子系統維護者(鬆散地)是他們所管理的內核部分的「守門員」;他們(通常)
+會接受一個補丁以包含到主線內核中。
+
+子系統維護人員每個人都管理著自己版本的內核原始碼樹,通常(並非總是)使用Git。
+Git等工具(以及Quilt或Mercurial等相關工具)允許維護人員跟蹤補丁列表,包括作者
+信息和其他元數據。在任何給定的時間,維護人員都可以確定他或她的存儲庫中的哪
+些補丁在主線中找不到。
+
+當合併窗口打開時,頂級維護人員將要求Linus從存儲庫中「拉出」他們爲合併選擇
+的補丁。如果Linus同意,補丁流將流向他的存儲庫,成爲主線內核的一部分。
+Linus對拉取中接收到的特定補丁的關注程度各不相同。很明顯,有時他看起來很
+關注。但是一般來說,Linus相信子系統維護人員不會向上游發送壞補丁。
+
+子系統維護人員反過來也可以從其他維護人員那裡獲取補丁。例如,網絡樹是由首先
+在專用於網絡設備驅動程序、無線網絡等的樹中積累的補丁構建的。此存儲鏈可以
+任意長,但很少超過兩個或三個連結。由於鏈中的每個維護者都信任那些管理較低
+級別樹的維護者,所以這個過程稱爲「信任鏈」。
+
+顯然,在這樣的系統中,獲取內核補丁取決於找到正確的維護者。直接向Linus發送
+補丁通常不是正確的方法。
+
+Next 樹
+-------
+
+子系統樹鏈引導補丁流到內核,但它也提出了一個有趣的問題:如果有人想查看爲
+下一個合併窗口準備的所有補丁怎麼辦?開發人員將感興趣的是,還有什麼其他的
+更改有待解決,以了解是否存在需要擔心的衝突;例如,更改核心內核函數原型的
+修補程序將與使用該函數舊形式的任何其他修補程序衝突。審查人員和測試人員希望
+在所有這些變更到達主線內核之前,能夠訪問它們的集成形式的變更。您可以從所有
+相關的子系統樹中提取更改,但這將是一項複雜且容易出錯的工作。
+
+解決方案以-next樹的形式出現,在這裡子系統樹被收集以供測試和審查。這些樹中
+由Andrew Morton維護的較老的一個,被稱爲「-mm」(用於內存管理,創建時爲此)。
+-mm 樹集成了一長串子系統樹中的補丁;它還包含一些旨在幫助調試的補丁。
+
+除此之外,-mm 還包含大量由Andrew直接選擇的補丁。這些補丁可能已經發布在郵件
+列表上,或者它們可能應用於內核中未指定子系統樹的部分。同時,-mm 作爲最後
+手段的子系統樹;如果沒有其他明顯的路徑可以讓補丁進入主線,那麼它很可能最
+終選擇-mm 樹。累積在-mm 中的各種補丁最終將被轉發到適當的子系統樹,或者直接
+發送到Linus。在典型的開發周期中,大約5-10%的補丁通過-mm 進入主線。
+
+當前-mm 補丁可在「mmotm」(-mm of the moment)目錄中找到:
+
+ https://www.ozlabs.org/~akpm/mmotm/
+
+然而,使用MMOTM樹可能會十分令人頭疼;它甚至可能無法編譯。
+
+下一個周期補丁合併的主要樹是linux-next,由Stephen Rothwell 維護。根據設計
+linux-next 是下一個合併窗口關閉後主線的快照。linux-next樹在Linux-kernel 和
+Linux-next 郵件列表中發布,可從以下位置下載:
+
+ https://www.kernel.org/pub/linux/kernel/next/
+
+Linux-next 已經成爲內核開發過程中不可或缺的一部分;在一個給定的合併窗口中合併
+的所有補丁都應該在合併窗口打開之前的一段時間內找到進入Linux-next 的方法。
+
+Staging 樹
+----------
+
+內核原始碼樹包含drivers/staging/目錄,其中有許多驅動程序或文件系統的子目錄
+正在被添加到內核樹中。它們在仍然需要更多的修正的時候可以保留在driver/staging/
+目錄中;一旦完成,就可以將它們移到內核中。這是一種跟蹤不符合Linux內核編碼或
+質量標準的驅動程序的方法,人們可能希望使用它們並跟蹤開發。
+
+Greg Kroah Hartman 目前負責維護staging 樹。仍需要修正的驅動程序將發送給他,
+每個驅動程序在drivers/staging/中都有自己的子目錄。除了驅動程序源文件之外,
+目錄中還應該有一個TODO文件。TODO文件列出了驅動程序需要接受的暫停的工作,
+以及驅動程序的任何補丁都應該抄送的人員列表。當前的規則要求,staging的驅動
+程序必須至少正確編譯。
+
+Staging 是一種讓新的驅動程序進入主線的相對容易的方法,它們會幸運地引起其他
+開發人員的注意,並迅速改進。然而,進入staging並不是故事的結尾;staging中
+沒有看到常規進展的代碼最終將被刪除。經銷商也傾向於相對不願意使用staging驅動
+程序。因此,在成爲一個合適的主線驅動的路上,staging 僅是一個中轉站。
+
+工具
+----
+
+從上面的文本可以看出,內核開發過程在很大程度上依賴於在不同方向上聚集補丁的
+能力。如果沒有適當強大的工具,整個系統將無法在任何地方正常工作。關於如何使用
+這些工具的教程遠遠超出了本文檔的範圍,但還是用一點篇幅介紹一些關鍵點。
+
+到目前爲止,內核社區使用的主要原始碼管理系統是git。Git是在自由軟體社區中開發
+的許多分布式版本控制系統之一。它非常適合內核開發,因爲它在處理大型存儲庫和
+大量補丁時性能非常好。它也以難以學習和使用而著稱,儘管隨著時間的推移它變得
+更好了。對於內核開發人員來說,對Git的某種熟悉幾乎是一種要求;即使他們不將它
+用於自己的工作,他們也需要Git來跟上其他開發人員(以及主線)正在做的事情。
+
+現在幾乎所有的Linux發行版都打包了Git。Git主頁位於:
+
+ https://git-scm.com/
+
+此頁面包含了文檔和教程的連結。
+
+在不使用git的內核開發人員中,最流行的選擇幾乎肯定是Mercurial:
+
+ http://www.seleric.com/mercurial/
+
+Mercurial與Git共享許多特性,但它提供了一個界面,許多人覺得它更易於使用。
+
+另一個值得了解的工具是Quilt:
+
+ https://savannah.nongnu.org/projects/quilt
+
+Quilt 是一個補丁管理系統,而不是原始碼管理系統。它不會隨著時間的推移跟蹤歷史;
+相反,它面向根據不斷發展的代碼庫跟蹤一組特定的更改。一些主要的子系統維護人員
+使用Quilt來管理打算向上游移動的補丁。對於某些樹的管理(例如-mm),quilt 是
+最好的工具。
+
+郵件列表
+--------
+
+大量的Linux內核開發工作是通過郵件列表完成的。如果不加入至少一個某個列表,
+就很難成爲社區中的一個「全功能」成員。但是,Linux郵件列表對開發人員來說也是
+一個潛在的危險,他們可能會被一堆電子郵件淹沒、違反Linux列表上使用的約定,
+或者兩者兼而有之。
+
+大多數內核郵件列表都在vger.kernel.org上運行;主列表位於:
+
+ http://vger.kernel.org/vger-lists.html
+
+不過,也有一些列表託管在別處;其中一些列表位於
+redhat.com/mailman/listinfo。
+
+當然,內核開發的核心郵件列表是linux-kernel。這個列表是一個令人生畏的地方:
+每天的信息量可以達到500條,噪音很高,談話技術性很強,且參與者並不總是表現出
+高度的禮貌。但是,沒有其他地方可以讓內核開發社區作爲一個整體聚集在一起;
+不使用此列表的開發人員將錯過重要信息。
+
+以下一些提示可以幫助在linux-kernel生存:
+
+- 將郵件轉移到單獨的文件夾,而不是主郵箱文件夾。我們必須能夠持續地忽略洪流。
+
+- 不要試圖跟上每一次談話——沒人會這樣。重要的是要篩選感興趣的主題(但請注意
+ 長時間的對話可能會偏離原來的主題,儘管未改變電子郵件的主題)和參與的人。
+
+- 不要回復挑事的人。如果有人試圖激起憤怒,請忽略他們。
+
+- 當回復Linux內核電子郵件(或其他列表上的電子郵件)時,請爲所有相關人員保留
+ Cc: 抄送頭。如果沒有確實的理由(如明確的請求),則不應刪除收件人。一定要
+ 確保你要回復的人在抄送列表中。這個慣例也使你不必在回覆郵件時明確要求被抄送。
+
+- 在提出問題之前,搜索列表存檔(和整個網絡)。有些開發人員可能會對那些顯然
+ 沒有完成家庭作業的人感到不耐煩。
+
+- 避免頂部回復(把你的答案放在你要回復的引文上面的做法)。這會讓你的回答更難
+ 理解,印象也很差。
+
+- 在正確的郵件列表發問。linux-kernel 可能是通用的討論場所,但它不是尋找所有
+ 子系統開發人員的最佳場所。
+
+最後一點——找到正確的郵件列表——是開發人員常出錯的地方。在linux-kernel上
+提出與網絡相關的問題的人幾乎肯定會收到一個禮貌的建議,轉到netdev列表上提出,
+因爲這是大多數網絡開發人員經常出現的列表。還有其他列表可用於scsi、video4linux、
+ide、filesystem等子系統。查找郵件列表的最佳位置是與內核原始碼一起打包的
+MAINTAINERS文件。
+
+開始內核開發
+------------
+
+關於如何開始內核開發過程的問題很常見——個人和公司皆然。同樣常見的是失誤,這
+使得關係的開始比本應的更困難。
+
+公司通常希望聘請知名的開發人員來啓動開發團隊。實際上,這是一種有效的技術。
+但它也往往是昂貴的,而且對增加有經驗的內核開發人員的數量沒有多大幫助。考
+慮到時間投入,可以讓內部開發人員加快Linux內核的開發速度。利用這段時間可以
+讓僱主擁有一批既了解內核又了解公司的開發人員,還可以幫助培訓其他人。從中期
+來看,這通常是更有利可圖的方法。
+
+可以理解的是,單個開發人員往往對起步感到茫然。從一個大型項目開始可能會很
+嚇人;人們往往想先用一些較小的東西來試試水。由此,一些開發人員開始創建修補
+拼寫錯誤或輕微編碼風格問題的補丁。不幸的是,這樣的補丁會產生一定程度的噪音,
+這會分散整個開發社區的注意力,因此,它們越來越被人不看重。希望向社區介紹
+自己的新開發人員將無法通過這些方式獲得他們期待的反響。
+
+Andrew Morton 爲有抱負的內核開發人員提供了如下建議
+
+::
+
+ 所有內核開發者的第一個項目肯定應該是「確保內核在您可以操作的所有
+ 機器上始終完美運行」。通常的方法是和其他人一起解決問題(這可能需
+ 要堅持!),但就是如此——這是內核開發的一部分。
+
+(http://lwn.net/articles/283982/)
+
+在沒有明顯問題需要解決的情況下,通常建議開發人員查看當前的回歸和開放缺陷
+列表。從來都不缺少需要解決的問題;通過解決這些問題,開發人員將從該過程獲得
+經驗,同時與開發社區的其他成員建立相互尊重。
+
diff --git a/Documentation/translations/zh_TW/process/3.Early-stage.rst b/Documentation/translations/zh_TW/process/3.Early-stage.rst
new file mode 100644
index 000000000000..ab2a45fd65a4
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/3.Early-stage.rst
@@ -0,0 +1,172 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_early_stage:
+
+早期規劃
+========
+
+當考慮一個Linux內核開發項目時,很可能會直接跳進去開始編碼。然而,與任何重要
+的項目一樣,許多成功的基礎最好是在第一行代碼編寫之前就打下。在早期計劃和
+溝通中花費一些時間可以在之後節省更多的時間。
+
+搞清問題
+--------
+
+與任何工程項目一樣,成功的內核改善從清晰描述要解決的問題開始。在某些情況
+下,這個步驟很容易:例如當某個特定硬體需要驅動程序時。不過,在其他情況下,
+很容易將實際問題與建議的解決方案混在一起,這可能會導致麻煩。
+
+舉個例子:幾年前,Linux音頻的開發人員尋求一種方法來運行應用程式,而不會因
+系統延遲過大而導致退出或其他問題。他們得到的解決方案是一個連接到Linux安全
+模塊(LSM)框架中的內核模塊;這個模塊可以配置爲允許特定的應用程式訪問實時
+調度程序。這個模塊被實現並發到linux-kernel郵件列表,在那裡它立即遇到了麻煩。
+
+對於音頻開發人員來說,這個安全模塊足以解決他們當前的問題。但是,對於更廣泛的
+內核社區來說,這被視爲對LSM框架的濫用(LSM框架並不打算授予他們原本不具備的
+進程特權),並對系統穩定性造成風險。他們首選的解決方案包括短期的通過rlimit
+機制進行實時調度訪問,以及長期的減少延遲的工作。
+
+然而,音頻社區無法超越他們實施的特定解決方案來看問題;他們不願意接受替代方案。
+由此產生的分歧使這些開發人員對整個內核開發過程感到失望;其中一個開發人員返回
+到audio列表並發布了以下內容:
+
+ 有很多非常好的Linux內核開發人員,但他們往往會被一羣傲慢的傻瓜所壓倒。
+ 試圖向這些人傳達用戶需求是浪費時間。他們太「聰明」了,根本聽不到少數
+ 人的話。
+
+(http://lwn.net/articles/131776/)
+
+實際情況卻是不同的;與特定模塊相比,內核開發人員更關心系統穩定性、長期維護
+以及找到問題的正確解決方案。這個故事的寓意是把重點放在問題上——而不是具體的
+解決方案上——並在開始編寫代碼之前與開發社區討論這個問題。
+
+因此,在考慮一個內核開發項目時,我們應該得到一組簡短問題的答案:
+
+ - 需要解決的問題究竟是什麼?
+
+ - 受此問題影響的用戶有哪些?解決方案應該解決哪些使用案例?
+
+ - 內核現在爲何沒能解決這個問題?
+
+只有這樣,才能開始考慮可能的解決方案。
+
+
+早期討論
+--------
+
+在計劃內核開發項目時,在開始實施之前與社區進行討論是很有意義的。早期溝通可以
+通過多種方式節省時間和麻煩:
+
+ - 很可能問題是由內核以您不理解的方式解決的。Linux內核很大,具有許多不明顯
+ 的特性和功能。並不是所有的內核功能都像人們所希望的那樣有文檔記錄,而且很
+ 容易遺漏一些東西。某作者發布了一個完整的驅動程序,重複了一個其不
+ 知道的現有驅動程序。重新發明現有輪子的代碼不僅浪費,而且不會被接受到主線
+ 內核中。
+
+ - 建議的解決方案中可能有一些要素不適合併入主線。在編寫代碼之前,最好先了解
+ 這樣的問題。
+
+ - 其他開發人員完全有可能考慮過這個問題;他們可能有更好的解決方案的想法,並且
+ 可能願意幫助創建這個解決方案。
+
+在內核開發社區的多年經驗給了我們一個明確的教訓:閉門設計和開發的內核代碼總是
+有一些問題,這些問題只有在代碼發布到社區中時才會被發現。有時這些問題很嚴重,
+需要數月或數年的努力才能使代碼達到內核社區的標準。例如:
+
+ - 設計並實現了單處理器系統的DeviceScape網絡棧。只有使其適合於多處理器系統,
+ 才能將其合併到主線中。在代碼中修改鎖等等是一項困難的任務;因此,這段代碼
+ (現在稱爲mac80211)的合併被推遲了一年多。
+
+ - Reiser4文件系統包含許多功能,核心內核開發人員認爲這些功能應該在虛擬文件
+ 系統層中實現。它還包括一些特性,這些特性在不將系統暴露於用戶引起的死鎖的
+ 情況下是不容易實現的。這些問題過遲發現——以及拒絕處理其中一些問題——已經
+ 導致Reiser4置身主線內核之外。
+
+ - Apparmor安全模塊以被認爲不安全和不可靠的方式使用內部虛擬文件系統數據結構。
+ 這種擔心(包括其他)使Apparmor多年來無法進入主線。
+
+在這些情況下,與內核開發人員的早期討論,可以避免大量的痛苦和額外的工作。
+
+找誰交流?
+----------
+
+當開發人員決定公開他們的計劃時,下一個問題是:我們從哪裡開始?答案是找到正確
+的郵件列表和正確的維護者。對於郵件列表,最好的方法是在維護者(MAINTAINERS)文件
+中查找要發布的相關位置。如果有一個合適的子系統列表,那麼其上發布通常比在
+linux-kernel上發布更可取;您更有可能接觸到在相關子系統中具有專業知識的開發
+人員,並且環境可能具支持性。
+
+找到維護人員可能會有點困難。同樣,維護者文件是開始的地方。但是,該文件往往不
+是最新的,並且並非所有子系統都在那裡顯示。實際上,維護者文件中列出的人員可能
+不是當前實際擔任該角色的人員。因此,當對聯繫誰有疑問時,一個有用的技巧是使用
+git(尤其是「git-log」)查看感興趣的子系統中當前活動的用戶。看看誰在寫補丁、
+誰會在這些補丁上加上Signed-off-by行簽名(如有)。這些人將是幫助新開發項目的
+最佳人選。
+
+找到合適的維護者有時是非常具有挑戰性的,以至於內核開發人員添加了一個腳本來
+簡化這個過程:
+
+::
+
+ .../scripts/get_maintainer.pl
+
+當給定「-f」選項時,此腳本將返回指定文件或目錄的當前維護者。如果在命令行上
+給出了一個補丁,它將列出可能接收補丁副本的維護人員。有許多選項可以調節
+get_maintainer.pl搜索維護者的嚴格程度;請小心使用更激進的選項,因爲最終結果
+可能會包括對您正在修改的代碼沒有真正興趣的開發人員。
+
+如果所有其他方法都失敗了,那麼與Andrew Morton交流是跟蹤特定代碼段維護人員
+的一種有效方法。
+
+何時郵寄?
+----------
+
+如果可能的話,在早期階段發布你的計劃只會更有幫助。描述正在解決的問題以及已經
+制定的關於如何實施的任何計劃。您可以提供的任何信息都可以幫助開發社區爲項目
+提供有用的輸入。
+
+在這個階段可能發生的一件令人沮喪的事情不是得到反對意見,而是很少或根本沒有
+反饋。令人傷心的事實是:(1)內核開發人員往往很忙;(2)不缺少有宏偉計劃但
+代碼(甚至代碼設想)很少的人去支持他們;(3)沒有人有義務審查或評論別人發表
+的想法。除此之外,高層級的設計常常隱藏著一些問題,這些問題只有在有人真正嘗試
+實現這些設計時才會被發現;因此,內核開發人員寧願看到代碼。
+
+如果發布請求評論(RFC)並沒得到什麼有用的評論,不要以爲這意味著無人對此項目
+有興趣,同時你也不能假設你的想法沒有問題。在這種情況下,最好的做法是繼續進
+行,把你的進展隨時通知社區。
+
+獲得官方認可
+-----------------------
+
+如果您的工作是在公司環境中完成的,就像大多數Linux內核工作一樣;顯然,在您將
+公司的計劃或代碼發布到公共郵件列表之前,必須獲得有適當權利經理的許可。發布
+不確定是否兼容GPL的代碼尤其會帶來問題;公司的管理層和法律人員越早能夠就發布
+內核開發項目達成一致,對參與的每個人都越好。
+
+一些讀者可能會認爲他們的核心工作是爲了支持還沒有正式承認存在的產品。將僱主
+的計劃公布在公共郵件列表上可能不是一個可行的選擇。在這種情況下,有必要考慮
+保密是否真的是必要的;通常不需要把開發計劃關在門內。
+
+的確,有些情況下一家公司在開發過程的早期無法合法地披露其計劃。擁有經驗豐富
+的內核開發人員的公司可能選擇以開環的方式進行開發,前提是他們以後能夠避免
+嚴重的集成問題。對於沒有這種內部專業知識的公司,最好的選擇往往是聘請外部
+開發者根據保密協議審查計劃。Linux基金會運行了一個NDA程序,旨在幫助解決這種
+情況;更多信息參見:
+
+ http://www.linuxfoundation.org/nda/
+
+這種審查通常足以避免以後出現嚴重問題,而無需公開披露項目。
+
diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst
new file mode 100644
index 000000000000..ccc3946227a0
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/4.Coding.rst
@@ -0,0 +1,297 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_coding:
+
+使代碼正確
+======================
+
+雖然一個堅實的、面向社區的設計過程有很多值得說道的,但是任何內核開發項目工作
+的證明都反映在代碼中。它是將由其他開發人員檢查併合並(或不合併)到主線樹中
+的代碼。所以這段代碼的質量決定了項目的最終成功。
+
+本節將檢查編碼過程。我們將從內核開發人員常犯的幾種錯誤開始。然後重點將轉移
+到正確的做法和相關有用的工具上。
+
+陷阱
+----
+
+代碼風格
+********
+
+內核長期以來都有其標準的代碼風格,如
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中所述。在多數時候,該文檔中描述的準則至多被認爲是建議性的。因此,內核中存在
+大量不符合代碼風格準則的代碼。這種代碼的存在會給內核開發人員帶來兩方面的危害。
+
+首先,相信內核代碼標準並不重要,也不強制執行。但事實上,如果沒有按照標準
+編寫代碼,那麼新代碼將很難加入到內核中;許多開發人員甚至會在審查代碼之前要求
+對代碼進行重新格式化。一個像內核這麼大的代碼庫需要一些統一格式的代碼,以使
+開發人員能夠快速理解其中的任何部分。所以再也經不起奇怪格式的代碼的折騰了。
+
+內核的代碼風格偶爾會與僱主的強制風格發生衝突。在這種情況下,必須在代碼合併
+之前遵從內核代碼風格。將代碼放入內核意味著以多種方式放棄一定程度的控制權——
+包括控制代碼樣式。
+
+另一個危害是認爲已經在內核中的代碼迫切需要修復代碼樣式。開發者可能會開始編寫
+重新格式化補丁,作爲熟悉開發過程的一種方式,或者作爲將其名字寫入內核變更日誌
+的一種方式,或者兩者兼而有之。但是純代碼風格的修復被開發社區視爲噪音,它們往
+往受到冷遇。因此,最好避免編寫這種類型的補丁。在由於其他原因處理一段代碼的
+同時順帶修復其樣式是很自然的,但是不應該僅爲了更改代碼樣式而更改之。
+
+代碼風格文檔也不應該被視爲絕對不可違反的規則。如果有一個足夠的理由反對這種
+樣式(例如爲了80列限制拆分行會導致可讀性大大降低),那麼就這樣做吧。
+
+注意您還可以使用 ``clang-format`` 工具來幫助您處理這些規則,快速自動重新格式
+化部分代碼,和審閱完整的文件以發現代碼樣式錯誤、拼寫錯誤和可能的改進。它還
+可以方便地排序 ``#includes`` 、對齊變量/宏、重排文本和其他類似任務。有關詳細
+信息,請參閱文檔 :ref:`Documentation/process/clang-format.rst <clangformat>`
+
+抽象層
+******
+
+計算機科學教授教學生以靈活性和信息隱藏的名義廣泛使用抽象層。當然,內核廣泛
+地使用了抽象;任何涉及數百萬行代碼的項目都必須做到這一點以存續下來。但經驗
+表明,過度或過早的抽象可能和過早的優化一樣有害。抽象應用在適當層級,
+不要過度。
+
+簡單點,先考慮一個調用時始終只有一個參數且總爲零的函數。我們可以保留這個參數,
+以在需要使用它時提供的額外靈活性。不過,在那時實現了這個額外參數的代碼很有
+可能以某種從未被注意到的微妙方式被破壞——因爲它從未被使用過。或者當需要額外
+的靈活性時,它並未以符合程式設計師當初期望的方式來實現。內核開發人員通常會提交
+補丁來刪除未使用的參數;一般來說,一開始就不應該添加這些參數。
+
+隱藏硬體訪問的抽象層——通常爲了允許大量的驅動程序兼容多個作業系統——尤其不受
+歡迎。這樣的層使代碼變得模糊,可能會造成性能損失;它們不屬於Linux內核。
+
+另一方面,如果您發現自己從另一個內核子系統複製了大量的代碼,那麼是時候
+了解一下:是否需要將這些代碼中的部分提取到單獨的庫中,或者在更高的層次上
+實現這些功能。在整個內核中複製相同的代碼沒有價值。
+
+#ifdef 和預處理
+***************
+
+C預處理器似乎給一些C程式設計師帶來了強大的誘惑,他們認爲它是一種將大量靈活性加入
+原始碼中的方法。但是預處理器不是C,大量使用它會導致代碼對其他人來說更難閱讀,
+對編譯器來說更難檢查正確性。使用了大量預處理器幾乎總是代碼需要一些
+清理工作的標誌。
+
+使用#ifdef的條件編譯實際上是一個強大的功能,它在內核中使用。但是很少有人希望
+看到代碼被鋪滿#ifdef塊。一般規定,ifdef的使用應儘可能限制在頭文件中。條件
+編譯代碼可以限制函數,如果代碼不存在,這些函數就直接變成空的。然後編譯器將
+悄悄地優化對空函數的調用。使得代碼更加清晰,更容易理解。
+
+C預處理器宏存在許多危險性,包括可能對具有副作用且沒有類型安全的表達式進行多
+重評估。如果您試圖定義宏,請考慮創建一個內聯函數替代。結果相同的代碼,內聯
+函數更容易閱讀,不會多次計算其參數,並且允許編譯器對參數和返回值執行類型檢查。
+
+內聯函數
+********
+
+不過,內聯函數本身也存在風險。程式設計師可以傾心於避免函數調用和用內聯函數填充源
+文件所固有的效率。然而,這些功能實際上會降低性能。因爲它們的代碼在每個調用站
+點都被複製一遍,所以最終會增加編譯內核的大小。此外,這也對處理器的內存緩存
+造成壓力,從而大大降低執行速度。通常內聯函數應該非常小,而且相對較少。畢竟
+函數調用的成本並不高;大量創建內聯函數是過早優化的典型例子。
+
+一般來說,內核程式設計師會自冒風險忽略緩存效果。在數據結構課程開頭中的經典
+時間/空間權衡通常不適用於當代硬體。空間 *就是* 時間,因爲一個大的程序比一個
+更緊湊的程序運行得慢。
+
+較新的編譯器越來越激進地決定一個給定函數是否應該內聯。因此,隨意放置使用
+「inline」關鍵字可能不僅僅是過度的,也可能是無用的。
+
+鎖
+**
+
+2006年5月,「deviceescape」網絡堆棧在前呼後擁下以GPL發布,並被納入主線內核。
+這是一個受歡迎的消息;Linux中對無線網絡的支持充其量被認爲是不合格的,而
+Deviceescape堆棧承諾修復這種情況。然而直到2007年6月(2.6.22),這段代碼才真
+正進入主線。發生了什麼?
+
+這段代碼出現了許多閉門造車的跡象。但一個大麻煩是,它並不是爲多處理器系統而
+設計。在合併這個網絡堆棧(現在稱爲mac80211)之前,需要對其進行一個鎖方案的
+改造。
+
+曾經,Linux內核代碼可以在不考慮多處理器系統所帶來的並發性問題的情況下進行
+開發。然而現在,這個文檔就是在雙核筆記本電腦上寫的。即使在單處理器系統上,
+爲提高響應能力所做的工作也會提高內核內的並發性水平。編寫內核代碼而不考慮鎖
+的日子早已遠去。
+
+可以由多個線程並發訪問的任何資源(數據結構、硬體寄存器等)必須由鎖保護。新
+的代碼應該謹記這一要求;事後修改鎖是一項相當困難的任務。內核開發人員應該花
+時間充分了解可用的鎖原語,以便爲工作選擇正確的工具。對並發性缺乏關注的代碼
+很難進入主線。
+
+回歸
+****
+
+最後一個值得一提的危險是回歸:它可能會引起導致現有用戶的某些東西中斷的改變
+(這也可能會帶來很大的改進)。這種變化被稱爲「回歸」,回歸已經成爲主線內核
+最不受歡迎的問題。除了少數例外情況,如果回歸不能及時修正,會導致回歸的修改
+將被取消。最好首先避免回歸發生。
+
+人們常常爭論,如果回歸帶來的功能遠超過產生的問題,那麼回歸是否爲可接受的。
+如果它破壞了一個系統卻爲十個系統帶來新的功能,爲何不改改態度呢?2007年7月,
+Linus對這個問題給出了最佳答案:
+
+::
+
+ 所以我們不會通過引入新問題來修復錯誤。這種方式是靠不住的,沒人知道
+ 是否真的有進展。是前進兩步、後退一步,還是前進一步、後退兩步?
+
+(http://lwn.net/articles/243460/)
+
+特別不受歡迎的一種回歸類型是用戶空間ABI的任何變化。一旦接口被導出到用戶空間,
+就必須無限期地支持它。這一事實使得用戶空間接口的創建特別具有挑戰性:因爲它們
+不能以不兼容的方式進行更改,所以必須一次就對。因此,用戶空間接口總是需要大量
+的思考、清晰的文檔和廣泛的審查。
+
+
+代碼檢查工具
+------------
+
+至少目前,編寫無錯誤代碼仍然是我們中很少人能達到的理想狀態。不過,我們希望做
+的是,在代碼進入主線內核之前,儘可能多地捕獲並修復這些錯誤。爲此,內核開發人
+員已經提供了一系列令人印象深刻的工具,可以自動捕獲各種各樣的隱藏問題。計算機
+發現的任何問題都是一個以後不會困擾用戶的問題,因此,只要有可能,就應該使用
+自動化工具。
+
+第一步是注意編譯器產生的警告。當前版本的GCC可以檢測(並警告)大量潛在錯誤。
+通常,這些警告都指向真正的問題。提交以供審閱的代碼一般不會產生任何編譯器警告。
+在消除警告時,注意了解真正的原因,並儘量避免僅「修復」使警告消失而不解決其原因。
+
+請注意,並非所有編譯器警告都默認啓用。使用「make KCFLAGS=-W」構建內核以
+獲得完整集合。
+
+內核提供了幾個配置選項,可以打開調試功能;大多數配置選項位於「kernel hacking」
+子菜單中。對於任何用於開發或測試目的的內核,都應該啓用其中幾個選項。特別是,
+您應該打開:
+
+ - FRAME_WARN 獲取大於給定數量的堆棧幀的警告。
+ 這些警告生成的輸出可能比較冗長,但您不必擔心來自內核其他部分的警告。
+
+ - DEBUG_OBJECTS 將添加代碼以跟蹤內核創建的各種對象的生命周期,並在出現問題
+ 時發出警告。如果你要添加創建(和導出)關於其自己的複雜對象的子系統,請
+ 考慮打開對象調試基礎結構的支持。
+
+ - DEBUG_SLAB 可以發現各種內存分配和使用錯誤;它應該用於大多數開發內核。
+
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP 和 DEBUG_MUTEXES 會發現許多常見的
+ 鎖錯誤。
+
+還有很多其他調試選項,其中一些將在下面討論。其中一些有顯著的性能影響,不應
+一直使用。在學習可用選項上花費一些時間,可能會在短期內得到許多回報。
+
+其中一個較重的調試工具是鎖檢查器或「lockdep」。該工具將跟蹤系統中每個鎖
+(spinlock或mutex)的獲取和釋放、獲取鎖的相對順序、當前中斷環境等等。然後,
+它可以確保總是以相同的順序獲取鎖,相同的中斷假設適用於所有情況等等。換句話
+說,lockdep可以找到許多導致系統死鎖的場景。在部署的系統中,這種問題可能會
+很痛苦(對於開發人員和用戶而言);LockDep允許提前以自動方式發現問題。具有
+任何類型的非普通鎖的代碼在提交合併前應在啓用lockdep的情況下運行測試。
+
+作爲一個勤奮的內核程式設計師,毫無疑問,您將檢查任何可能失敗的操作(如內存分配)
+的返回狀態。然而,事實上,最終的故障復現路徑可能完全沒有經過測試。未測試的
+代碼往往會出問題;如果所有這些錯誤處理路徑都被執行了幾次,那麼您可能對代碼
+更有信心。
+
+內核提供了一個可以做到這一點的錯誤注入框架,特別是在涉及內存分配的情況下。
+啓用故障注入後,內存分配的可配置失敗的百分比;這些失敗可以限定在特定的代碼
+範圍內。在啓用了故障注入的情況下運行,程式設計師可以看到當情況惡化時代碼如何響
+應。有關如何使用此工具的詳細信息,請參閱
+Documentation/fault-injection/fault-injection.rst。
+
+「sparse」靜態分析工具可以發現其他類型的錯誤。sparse可以警告程式設計師用戶空間
+和內核空間地址之間的混淆、大端序與小端序的混淆、在需要一組位標誌的地方傳遞
+整數值等等。sparse必須單獨安裝(如果您的分發伺服器沒有將其打包,
+可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到),
+然後可以通過在make命令中添加「C=1」在代碼上運行它。
+
+「Coccinelle」工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>`
+能夠發現各種潛在的編碼問題;它還可以爲這些問題提出修複方案。在
+scripts/coccinelle目錄下已經打包了相當多的內核「語義補丁」;運行
+「make coccicheck」將運行這些語義補丁並報告發現的任何問題。有關詳細信息,請參閱
+:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
+
+
+其他類型的可移植性錯誤最好通過爲其他體系結構編譯代碼來發現。如果沒有S/390系統
+或Blackfin開發板,您仍然可以執行編譯步驟。可以在以下位置找到一大堆用於x86系統的
+交叉編譯器:
+
+ https://www.kernel.org/pub/tools/crosstool/
+
+花一些時間安裝和使用這些編譯器將有助於避免以後的尷尬。
+
+文檔
+----
+
+文檔通常比內核開發規則更爲例外。即便如此,足夠的文檔將有助於簡化將新代碼合併
+到內核中的過程,使其他開發人員的生活更輕鬆,並對您的用戶有所幫助。在許多情況
+下,添加文檔已基本上是強制性的。
+
+任何補丁的第一個文檔是其關聯的變更日誌。日誌條目應該描述正在解決的問題、解決
+方案的形式、處理補丁的人員、對性能的任何相關影響,以及理解補丁可能需要的任何
+其他內容。確保變更日誌說明了*爲什麼*補丁值得應用;大量開發者未能提供這些信息。
+
+任何添加新用戶空間接口的代碼——包括新的sysfs或/proc文件——都應該包含該接口
+的文檔,該文檔使用戶空間開發人員能夠知道他們在使用什麼。請參閱
+Documentation/ABI/README,了解如何此文檔格式以及需要提供哪些信息。
+
+文檔 :ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>`
+描述了內核的所有引導時間參數。任何添加新參數的補丁都應該向該文檔添加適當的
+條目。
+
+任何新的配置選項都必須附有幫助文本,幫助文本需清楚地解釋這些選項以及用戶可能
+希望何時使用它們。
+
+許多子系統的內部API信息通過專門格式化的注釋進行記錄;這些注釋可以通過
+「kernel-doc」腳本以多種方式提取和格式化。如果您在具有kerneldoc注釋的子系統中
+工作,則應該維護它們,並根據需要爲外部可用的功能添加它們。即使在沒有如此記錄
+的領域中,爲將來添加kerneldoc注釋也沒有壞處;實際上,這對於剛開始開發內核的人
+來說是一個有用的活動。這些注釋的格式以及如何創建kerneldoc模板的一些信息可以在
+:ref:`Documentation/doc-guide/ <doc_guide>` 上找到。
+
+任何閱讀大量現有內核代碼的人都會注意到,注釋的缺失往往是最值得注意的。同時,
+對新代碼的要求比過去更高;合併未注釋的代碼將更加困難。這就是說,人們並不期望
+詳細注釋的代碼。代碼本身應該是自解釋的,注釋闡釋了更微妙的方面。
+
+某些事情應該總是被注釋。使用內存屏障時,應附上一行文字,解釋爲什麼需要設置內存
+屏障。數據結構的鎖規則通常需要在某個地方解釋。一般來說,主要數據結構需要全面
+的文檔。應該指出代碼中分立的位之間不明顯的依賴性。任何可能誘使代碼管理人進行
+錯誤的「清理」的事情都需要一個注釋來說明爲什麼要這樣做。等等。
+
+
+內部API更改
+-----------
+
+內核提供給用戶空間的二進位接口不能被破壞,除非逼不得已。而內核的內部編程接口
+是高度流動的,當需要時可以更改。如果你發現自己不得不處理一個內核API,或者僅
+僅因爲它不滿足你的需求導致無法使用特定的功能,這可能是API需要改變的一個標誌。
+作爲內核開發人員,您有權進行此類更改。
+
+的確可以進行API更改,但更改必須是合理的。因此任何進行內部API更改的補丁都應該
+附帶關於更改內容和必要原因的描述。這種變化也應該拆分成一個單獨的補丁,而不是
+埋在一個更大的補丁中。
+
+另一個要點是,更改內部API的開發人員通常要負責修復內核樹中被更改破壞的任何代碼。
+對於一個廣泛使用的函數,這個責任可以導致成百上千的變化,其中許多變化可能與其他
+開發人員正在做的工作相衝突。不用說,這可能是一項大工程,所以最好確保理由是
+可靠的。請注意,coccinelle工具可以幫助進行廣泛的API更改。
+
+在進行不兼容的API更改時,應儘可能確保編譯器捕獲未更新的代碼。這將幫助您確保找
+到該接口的樹內用處。它還將警告開發人員樹外代碼存在他們需要響應的更改。支持樹外
+代碼不是內核開發人員需要擔心的事情,但是我們也不必使樹外開發人員的生活有不必要
+的困難。
+
diff --git a/Documentation/translations/zh_TW/process/5.Posting.rst b/Documentation/translations/zh_TW/process/5.Posting.rst
new file mode 100644
index 000000000000..5578bca403e6
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/5.Posting.rst
@@ -0,0 +1,251 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_posting:
+
+發布補丁
+========
+
+您的工作遲早會準備好提交給社區進行審查,並最終包含到主線內核中。毫不稀奇,
+內核開發社區已經發展出一套用於發布補丁的約定和過程;遵循這些約定和過程將使
+參與其中的每個人的生活更加輕鬆。本文檔試圖描述這些約定的部分細節;更多信息
+也可在以下文檔中找到
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`,
+:ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+和 :ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`。
+
+何時郵寄
+--------
+
+在補丁完全「準備好」之前,避免發布補丁是一種持續的誘惑。對於簡單的補丁,這
+不是問題。但是如果正在完成的工作很複雜,那麼在工作完成之前從社區獲得反饋就
+可以獲得很多好處。因此,您應該考慮發布正在進行的工作,甚至維護一個可用的Git
+樹,以便感興趣的開發人員可以隨時趕上您的工作。
+
+當發布中有尚未準備好被包含的代碼,最好在發布中說明。還應提及任何有待完成的
+主要工作和任何已知問題。很少有人會願意看那些被認爲是半生不熟的補丁,但是
+那些願意的人會帶著他們的點子來一起幫助你把工作推向正確的方向。
+
+創建補丁之前
+------------
+
+在考慮將補丁發送到開發社區之前,有許多事情應該做。包括:
+
+ - 儘可能地測試代碼。利用內核的調試工具,確保內核使用了所有可能的配置選項組合
+ 進行構建,使用交叉編譯器爲不同的體系結構進行構建等。
+
+ - 確保您的代碼符合內核代碼風格指南。
+
+ - 您的更改是否具有性能影響?如果是這樣,您應該運行基準測試來顯示您的變更的
+ 影響(或好處);結果的摘要應該包含在補丁中。
+
+ - 確保您有權發布代碼。如果這項工作是爲僱主完成的,僱主對這項工作具有所有權,
+ 並且必須同意根據GPL對其進行發布。
+
+一般來說,在發布代碼之前進行一些額外的思考,幾乎總是能在短時間內得到回報。
+
+補丁準備
+--------
+
+準備補丁發布的工作量可能很驚人,但在此嘗試節省時間通常是不明智的,即使在短期
+內亦然。
+
+必須針對內核的特定版本準備補丁。一般來說,補丁應該基於Linus的Git樹中的當前
+主線。當以主線爲基礎時,請從一個衆所周知的發布點開始——如穩定版本或 -rc
+版本發布點——而不是在一個任意的主線分支點。
+
+也可能需要針對-mm、linux-next或子系統樹生成版本,以便於更廣泛的測試和審查。
+根據補丁的區域以及其他地方的情況,針對其他樹建立的補丁可能需要大量的工作來
+解決衝突和處理API更改。
+
+只有最簡單的更改才應格式化爲單個補丁;其他所有更改都應作爲一系列邏輯更改進行。
+分割補丁是一門藝術;一些開發人員花了很長時間來弄清楚如何按照社區期望的方式來
+分割。不過,這些經驗法則也許有幫助:
+
+ - 您發布的補丁系列幾乎肯定不會是開發過程中版本控制系統中的一系列更改。相反,
+ 需要對您所做更改的最終形式加以考慮,然後以有意義的方式進行拆分。開發人員對
+ 離散的、自包含的更改感興趣,而不是您創造這些更改的原始路徑。
+
+ - 每個邏輯上獨立的變更都應該格式化爲單獨的補丁。這些更改可以是小的(如「向
+ 此結構體添加欄位」)或大的(如添加一個重要的新驅動程序),但它們在概念上
+ 應該是小的,並且可以在一行內簡述。每個補丁都應該做一個特定的、可以單獨
+ 檢查並驗證它所做的事情的更改。
+
+ - 換種方式重申上述準則,也就是說:不要在同一補丁中混合不同類型的更改。如果
+ 一個補丁修復了一個關鍵的安全漏洞,又重新排列了一些結構,還重新格式化了代
+ 碼,那麼它很有可能會被忽略,從而導致重要的修復丟失。
+
+ - 每個補丁都應該能創建一個可以正確地構建和運行的內核;如果補丁系列在中間被
+ 斷開,那麼結果仍應是一個正常工作的內核。部分應用一系列補丁是使用
+ 「git bisct」工具查找回歸的一個常見場景;如果結果是一個損壞的內核,那麼將使
+ 那些從事追蹤問題的高尚工作的開發人員和用戶的生活更加艱難。
+
+ - 不要過分分割。一位開發人員曾經將一組針對單個文件的編輯分成500個單獨的補丁
+ 發布,這並沒有使他成爲內核郵件列表中最受歡迎的人。一個補丁可以相當大,
+ 只要它仍然包含一個單一的 *邏輯* 變更。
+
+ - 用一系列補丁添加一個全新的基礎設施,但是該設施在系列中的最後一個補丁啓用
+ 整個變更之前不能使用,這看起來很誘人。如果可能的話,應該避免這種誘惑;
+ 如果這個系列增加了回歸,那麼二分法將指出最後一個補丁是導致問題的補丁,
+ 即使真正的bug在其他地方。只要有可能,添加新代碼的補丁程序應該立即激活該
+ 代碼。
+
+創建完美補丁系列的工作可能是一個令人沮喪的過程,在完成「真正的工作」之後需要
+花費大量的時間和思考。但是如果做得好,花費的時間就是值得的。
+
+補丁格式和更改日誌
+------------------
+
+所以現在你有了一系列完美的補丁可以發布,但是這項工作還沒有完成。每個補丁都
+需要被格式化成一條消息,以快速而清晰地將其目的傳達到世界其他地方。爲此,
+每個補丁將由以下部分組成:
+
+ - 可選的「From」行,表明補丁作者。只有當你通過電子郵件發送別人的補丁時,這一行
+ 才是必須的,但是爲防止疑問加上它也不會有什麼壞處。
+
+ - 一行描述,說明補丁的作用。對於在沒有其他上下文的情況下看到該消息的讀者來說,
+ 該消息應足以確定修補程序的範圍;此行將顯示在「short form(簡短格式)」變更
+ 日誌中。此消息通常需要先加上子系統名稱前綴,然後是補丁的目的。例如:
+
+ ::
+
+ gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - 一行空白,後接補丁內容的詳細描述。此描述可以是任意需要的長度;它應該說明補丁
+ 的作用以及爲什麼它應該應用於內核。
+
+ - 一個或多個標記行,至少有一個由補丁作者的 Signed-off-by 簽名。標記將在下面
+ 詳細描述。
+
+上面的項目一起構成補丁的變更日誌。寫一則好的變更日誌是一門至關重要但常常被
+忽視的藝術;值得花一點時間來討論這個問題。當你編寫變更日誌時,你應該記住有
+很多不同的人會讀你的話。其中包括子系統維護人員和審查人員,他們需要決定是否
+應該合併補丁,分銷商和其他維護人員試圖決定是否應該將補丁反向移植到其他內核,
+缺陷搜尋人員想知道補丁是否導致他們正在追查的問題,以及想知道內核如何變化的
+用戶等等。一個好的變更日誌以最直接和最簡潔的方式向所有這些人傳達所需的信息。
+
+在結尾,總結行應該描述變更的影響和動機,以及在一行約束條件下可能發生的變化。
+然後,詳細的描述可以詳述這些主題,並提供任何需要的附加信息。如果補丁修復了
+一個缺陷,請引用引入該缺陷的提交(如果可能,請在引用提交時同時提供其 id 和
+標題)。如果某個問題與特定的日誌或編譯器輸出相關聯,請包含該輸出以幫助其他
+人搜索同一問題的解決方案。如果更改是爲了支持以後補丁中的其他更改,那麼應當
+說明。如果更改了內部API,請詳細說明這些更改以及其他開發人員應該如何響應。
+一般來說,你越把自己放在每個閱讀你變更日誌的人的位置上,變更日誌(和內核
+作爲一個整體)就越好。
+
+不消說,變更日誌是將變更提交到版本控制系統時使用的文本。接下來將是:
+
+ - 補丁本身,採用統一的(「-u」)補丁格式。使用「-p」選項來diff將使函數名與
+ 更改相關聯,從而使結果補丁更容易被其他人讀取。
+
+您應該避免在補丁中包括與更改不相關文件(例如,構建過程生成的文件或編輯器
+備份文件)。文檔目錄中的「dontdiff」文件在這方面有幫助;使用「-X」選項將
+其傳遞給diff。
+
+上面提到的標籤(tag)用於描述各種開發人員如何與這個補丁的開發相關聯。
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中對它們進行了詳細描述;下面是一個簡短的總結。每一行的格式如下:
+
+::
+
+ tag: Full Name <email address> optional-other-stuff
+
+常用的標籤有:
+
+ - Signed-off-by: 這是一個開發人員的證明,證明他或她有權提交補丁以包含到內核
+ 中。這表明同意開發者來源認證協議,其全文見
+ :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+ 如果沒有合適的簽字,則不能合併到主線中。
+
+ - Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上
+ 工作時,它用於給出共同作者(除了 From: 所給出的作者之外)。由於
+ Co-developed-by: 表示作者身份,所以每個共同開發人,必須緊跟在相關合作作者
+ 的Signed-off-by之後。具體內容和示例見以下文件
+ :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Acked-by: 表示另一個開發人員(通常是相關代碼的維護人員)同意補丁適合包含
+ 在內核中。
+
+ - Tested-by: 聲明某人已經測試了補丁並確認它可以工作。
+
+ - Reviewed-by: 表示某開發人員已經審查了補丁的正確性;有關詳細信息,請參閱
+ :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Reported-by: 指定報告此補丁修復的問題的用戶;此標記用於表示感謝。
+
+ - Cc:指定某人收到了補丁的副本,並有機會對此發表評論。
+
+在補丁中添加標籤時要小心:只有Cc:才適合在沒有指定人員明確許可的情況下添加。
+
+發送補丁
+--------
+
+在寄出補丁之前,您還需要注意以下幾點:
+
+ - 您確定您的郵件發送程序不會損壞補丁嗎?被郵件客戶端更改空白或修飾了行的補丁
+ 無法被另一端接受,並且通常不會進行任何詳細檢查。如果有任何疑問,先把補丁寄
+ 給你自己,讓你自己確定它是完好無損的。
+
+ :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+ 提供了一些有用的提示,可以讓特定的郵件客戶端正常發送補丁。
+
+ - 你確定你的補丁沒有荒唐的錯誤嗎?您應該始終通過scripts/checkpatch.pl檢查
+ 補丁程序,並解決它提出的問題。請記住,checkpatch.pl,雖然體現了對內核補丁
+ 應該是什麼樣的大量思考,但它並不比您聰明。如果修復checkpatch.pl給的問題會
+ 使代碼變得更糟,請不要這樣做。
+
+補丁應始終以純文本形式發送。請不要將它們作爲附件發送;這使得審閱者在答覆中更難
+引用補丁的部分。相反,只需將補丁直接放到您的消息中。
+
+寄出補丁時,重要的是將副本發送給任何可能感興趣的人。與其他一些項目不同,內核
+鼓勵人們甚至錯誤地發送過多的副本;不要假定相關人員會看到您在郵件列表中的發布。
+尤其是,副本應發送至:
+
+ - 受影響子系統的維護人員。如前所述,維護人員文件是查找這些人員的首選地方。
+
+ - 其他在同一領域工作的開發人員,尤其是那些現在可能在那裡工作的開發人員。使用
+ git查看還有誰修改了您正在處理的文件,這很有幫助。
+
+ - 如果您對某錯誤報告或功能請求做出響應,也可以抄送原始發送人。
+
+ - 將副本發送到相關郵件列表,或者若無相關列表,則發送到linux-kernel列表。
+
+ - 如果您正在修復一個缺陷,請考慮該修復是否應進入下一個穩定更新。如果是這樣,
+ 補丁副本也應發到stable@vger.kernel.org 。另外,在補丁本身的標籤中添加一個
+ 「Cc: stable@vger.kernel.org」;這將使穩定版團隊在修復進入主線時收到通知。
+
+當爲一個補丁選擇接收者時,最好清楚你認爲誰最終會接受這個補丁並將其合併。雖然
+可以將補丁直接發給Linus Torvalds並讓他合併,但通常情況下不會這樣做。Linus很
+忙,並且有子系統維護人員負責監視內核的特定部分。通常您會希望維護人員合併您的
+補丁。如果沒有明顯的維護人員,Andrew Morton通常是最後的補丁接收者。
+
+補丁需要好的主題行。補丁主題行的規範格式如下:
+
+::
+
+ [PATCH nn/mm] subsys: one-line description of the patch
+
+其中「nn」是補丁的序號,「mm」是系列中補丁的總數,「subsys」是受影響子系統的
+名稱。當然,一個單獨的補丁可以省略nn/mm。
+
+如果您有一系列重要的補丁,那麼通常發送一個簡介作爲第〇部分。不過,這個約定
+並沒有得到普遍遵循;如果您使用它,請記住簡介中的信息不會進入內核變更日誌。
+因此,請確保補丁本身具有完整的變更日誌信息。
+
+一般來說,多部分補丁的第二部分和後續部分應作爲對第一部分的回覆發送,以便它們
+在接收端都連接在一起。像git和coilt這樣的工具有命令,可以通過適當的線程發送
+一組補丁。但是,如果您有一長串補丁,並正使用git,請不要使用–-chain-reply-to
+選項,以避免創建過深的嵌套。
+
diff --git a/Documentation/translations/zh_TW/process/6.Followthrough.rst b/Documentation/translations/zh_TW/process/6.Followthrough.rst
new file mode 100644
index 000000000000..4af782742db3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/6.Followthrough.rst
@@ -0,0 +1,156 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_followthrough:
+
+跟進
+====
+
+此時,您已經遵循了到目前爲止給出的指導方針,並且,隨著您自己的工程技能的增加,
+已經發布了一系列完美的補丁。即使是經驗豐富的內核開發人員也能犯的最大錯誤之一
+是,認爲他們的工作現在已經完成了。事實上,發布補丁意味著進入流程的下一個階段,
+可能還需要做很多工作。
+
+一個補丁在首次發布時就非常出色、沒有改進的餘地,這是很罕見的。內核開發流程已
+認識到這一事實,因此它非常注重對已發布代碼的改進。作爲代碼的作者,您應該與
+內核社區合作,以確保您的代碼符合內核的質量標準。如果不參與這個過程,很可能會
+無法將補丁合併到主線中。
+
+與審閱者合作
+------------
+
+任何意義上的補丁都會導致其他開發人員在審查代碼時發表大量評論。對於許多開發
+人員來說,與審閱人員合作可能是內核開發過程中最令人生畏的部分。但是如果你
+記住一些事情,生活會變得容易得多:
+
+ - 如果你已經很好地解釋了你的補丁,審閱人員會理解它的價值,以及爲什麼你會
+ 費盡心思去寫它。但是這個並不能阻止他們提出一個基本的問題:在五年或十年後
+ 維護含有此代碼的內核會怎麼樣?你可能被要求做出的許多改變——從編碼風格的
+ 調整到大量的重寫——都來自於對Linux的理解,即從現在起十年後,Linux仍將
+ 在開發中。
+
+ - 代碼審查是一項艱苦的工作,這是一項相對吃力不討好的工作;人們記得誰編寫了
+ 內核代碼,但對於那些審查它的人來說,幾乎沒有什麼長久的名聲。因此,審閱
+ 人員可能會變得暴躁,尤其是當他們看到同樣的錯誤被一遍又一遍地犯下時。如果
+ 你得到了一個看起來憤怒、侮辱或完全冒犯你的評論,請抑制以同樣方式回應的衝動。
+ 代碼審查是關於代碼的,而不是關於人的,代碼審閱人員不會親自攻擊您。
+
+ - 同樣,代碼審閱人員也不想以犧牲你僱主的利益爲代價來宣傳他們僱主的議程。
+ 內核開發人員通常希望今後幾年能在內核上工作,但他們明白他們的僱主可能會改
+ 變。他們真的,幾乎毫無例外地,致力於創造他們所能做到的最好的內核;他們並
+ 沒有試圖給僱主的競爭對手造成不適。
+
+所有這些歸根結底就是,當審閱者向您發送評論時,您需要注意他們正在進行的技術
+評論。不要讓他們的表達方式或你自己的驕傲阻止此事。當你在一個補丁上得到評論
+時,花點時間去理解評論人想說什麼。如果可能的話,請修覆審閱者要求您修復的內
+容。然後回覆審閱者:謝謝他們,並描述你將如何回答他們的問題。
+
+請注意,您不必同意審閱者建議的每個更改。如果您認爲審閱者誤解了您的代碼,請
+解釋到底發生了什麼。如果您對建議的更改有技術上的異議,請描述它並證明您對該
+問題的解決方案是正確的。如果你的解釋有道理,審閱者會接受的。不過,如果你的
+解釋證明缺乏說服力,尤其是當其他人開始同意審稿人的觀點時,請花些時間重新考慮
+一下。你很容易對自己解決問題的方法視而不見,以至於你沒有意識到某些東西完全
+是錯誤的,或者你甚至沒有解決正確的問題。
+
+Andrew Morton建議,每一個不會導致代碼更改的審閱評論都應該產生一個額外的代碼
+注釋;這可以幫助未來的審閱人員避免第一次出現的問題。
+
+一個致命的錯誤是忽視評論,希望它們會消失。它們不會走的。如果您在沒有對之前
+收到的評論做出響應的情況下重新發布代碼,那麼很可能會發現補丁毫無用處。
+
+說到重新發布代碼:請記住,審閱者不會記住您上次發布的代碼的所有細節。因此,
+提醒審閱人員以前提出的問題以及您如何處理這些問題總是一個好主意;補丁變更
+日誌是提供此類信息的好地方。審閱者不必搜索列表檔案來熟悉上次所說的內容;
+如果您幫助他們直接開始,當他們重新查看您的代碼時,心情會更好。
+
+如果你已經試著做正確的事情,但事情仍然沒有進展呢?大多數技術上的分歧都可以
+通過討論來解決,但有時人們仍需要做出決定。如果你真的認爲這個決定對你不利,
+你可以試著向有更高權力的人上訴。對於本文,更高權力的人是 Andrew Morton 。
+Andrew 在內核開發社區中非常受尊敬;他經常爲似乎被絕望阻塞的事情清障。儘管
+如此,不應輕易就直接找 Andrew ,也不應在所有其他替代方案都被嘗試之前找他。
+當然,記住,他也可能不同意你的意見。
+
+接下來會發生什麼
+----------------
+
+如果一個補丁被認爲適合添加到內核中,並且大多數審查問題得到解決,下一步通常
+是進入子系統維護人員的樹中。工作方式因子系統而異;每個維護人員都有自己的
+工作方式。特別是可能有不止一棵樹——也許一棵樹專門用於計劃下一個合併窗口的
+補丁,另一棵樹用於長期工作。
+
+對於應用到不屬於明顯子系統樹(例如內存管理修補程序)的區域的修補程序,默認樹
+通常上溯到-mm。影響多個子系統的補丁也可以最終進入-mm樹。
+
+包含在子系統樹中可以提高補丁的可見性。現在,使用該樹的其他開發人員將默認獲
+得補丁。子系統樹通常也爲Linux提供支持,使其內容對整個開發社區可見。在這一點
+上,您很可能會從一組新的審閱者那裡得到更多的評論;這些評論需要像上一輪那樣
+得到回應。
+
+在這時也會發生點什麼,這取決於你的補丁的性質,是否與其他人正在做的工作發生
+衝突。在最壞的情況下,嚴重的補丁衝突可能會導致一些工作被擱置,以便剩餘的補丁
+可以成形併合並。另一些時候,衝突解決將涉及到與其他開發人員合作,可能還會
+在樹之間移動一些補丁,以確保所有的應用都是乾淨的。這項工作可能是一件痛苦的
+事情,但也需慶幸現在的幸福:在linux-next樹出現之前,這些衝突通常只在合併窗口
+中出現,必須迅速解決。現在可以在合併窗口打開之前的空閒時間解決這些問題。
+
+有朝一日,如果一切順利,您將登錄並看到您的補丁已經合併到主線內核中。祝賀你!
+然而,一旦慶祝完了(並且您已經將自己添加到維護人員文件中),就一定要記住
+一個重要的小事實:工作仍然沒有完成。併入主線也帶來了它的挑戰。
+
+首先,補丁的可見性再次提高。可能會有以前不知道這個補丁的開發者的新一輪評論。
+忽略它們可能很有誘惑力,因爲您的代碼不再存在任何被合併的問題。但是,要抵制
+這種誘惑,您仍然需要對有問題或建議的開發人員作出響應。
+
+不過,更重要的是:將代碼包含在主線中會將代碼交給更多的一些測試人員。即使您
+爲尚未可用的硬體提供了驅動程序,您也會驚訝於有多少人會將您的代碼構建到內核
+中。當然,如果有測試人員,也可能會有錯誤報告。
+
+最糟糕的錯誤報告是回歸。如果你的補丁導致回歸,你會發現多到讓你不舒服的眼睛盯
+著你;回歸需要儘快修復。如果您不願意或無法修復回歸(其他人都不會爲您修復),
+那麼在穩定期內,您的補丁幾乎肯定會被移除。除了否定您爲使補丁進入主線所做的
+所有工作之外,如果由於未能修復回歸而取消補丁,很可能會使將來的工作更難被合併。
+
+在處理完任何回歸之後,可能還有其他普通缺陷需要處理。穩定期是修復這些錯誤並
+確保代碼在主線內核版本中的首次發布儘可能可靠的最好機會。所以,請回應錯誤
+報告,並儘可能解決問題。這就是穩定期的目的;一旦解決了舊補丁的任何問題,就
+可以開始盡情創建新補丁。
+
+別忘了,還有其他節點也可能會創建缺陷報告:下一個主線穩定版本,當著名的發行
+商選擇包含您補丁的內核版本時等等。繼續響應這些報告是您工作的基本素養。但是
+如果這不能提供足夠的動機,那麼也需要考慮:開發社區會記住那些在合併後對代碼
+失去興趣的開發人員。下一次你發布補丁時,他們會以你以後不會持續維護它爲前提
+來評估它。
+
+其他可能發生的事情
+------------------
+
+某天,當你打開你的郵件客戶端時,看到有人給你寄了一個代碼補丁。畢竟,這是
+讓您的代碼公開存在的好處之一。如果您同意這個補丁,您可以將它轉發給子系統
+維護人員(確保包含一個正確的From:行,這樣屬性是正確的,並添加一個您自己的
+signoff ),或者回復一個 Acked-by: 讓原始發送者向上發送它。
+
+如果您不同意補丁,請禮貌地回復,解釋原因。如果可能的話,告訴作者需要做哪些
+更改才能讓您接受補丁。合併代碼的編寫者和維護者所反對的補丁的確存在著一定的
+阻力,但僅此而已。如果你被認爲不必要的阻礙了好的工作,那麼這些補丁最終會
+繞過你並進入主線。在Linux內核中,沒有人對任何代碼擁有絕對的否決權。可能除
+了Linus。
+
+在非常罕見的情況下,您可能會看到完全不同的東西:另一個開發人員發布了針對您
+的問題的不同解決方案。在這時,兩個補丁之一可能不會被合併,「我的補丁首先
+發布」不被認爲是一個令人信服的技術論據。如果有別人的補丁取代了你的補丁而進
+入了主線,那麼只有一種方法可以回應你:很高興你的問題解決了,請繼續工作吧。
+以這種方式把某人的工作推到一邊可能導致傷心和氣餒,但是社區會記住你的反應,
+即使很久以後他們已經忘記了誰的補丁真正被合併。
+
diff --git a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
new file mode 100644
index 000000000000..3de093d0f170
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
@@ -0,0 +1,137 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_advancedtopics:
+
+高級主題
+========
+
+現在,希望您能夠掌握開發流程的工作方式。然而,還有更多的東西要學!本節將介紹
+一些主題,這些主題對希望成爲Linux內核開發過程常規部分的開發人員有幫助。
+
+使用Git管理補丁
+---------------
+
+內核使用分布式版本控制始於2002年初,當時Linus首次開始使用專有的Bitkeeper應用
+程序。雖然BitKeeper存在爭議,但它所體現的軟體版本管理方法卻肯定不是。分布式
+版本控制可以立即加速內核開發項目。現在有好幾種免費的BitKeeper替代品。
+但無論好壞,內核項目都已經選擇了Git作爲其工具。
+
+使用Git管理補丁可以使開發人員的生活更加輕鬆,尤其是隨著補丁數量的增長。Git也
+有其粗糙的邊角和一定的危險性,它是一個年輕和強大的工具,仍然在其開發人員完善
+中。本文檔不會試圖教會讀者如何使用git;這會是個巨長的文檔。相反,這裡的重點
+將是Git如何特別適合內核開發過程。想要加快用Git速度的開發人員可以在以下網站上
+找到更多信息:
+
+ https://git-scm.com/
+
+ https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+同時網上也能找到各種各樣的教程。
+
+在嘗試使用它生成補丁供他人使用之前,第一要務是閱讀上述網頁,對Git的工作方式
+有一個紮實的了解。使用Git的開發人員應能進行拉取主線存儲庫的副本,查詢修訂
+歷史,提交對樹的更改,使用分支等操作。了解Git用於重寫歷史的工具(如rebase)
+也很有用。Git有自己的術語和概念;Git的新用戶應該了解引用、遠程分支、索引、
+快進合併、推拉、游離頭等。一開始可能有點嚇人,但這些概念不難通過一點學習來
+理解。
+
+使用git生成通過電子郵件提交的補丁是提高速度的一個很好的練習。
+
+當您準備好開始建立Git樹供其他人查看時,無疑需要一個可以從中拉取的伺服器。
+如果您有一個可以訪問網際網路的系統,那麼使用git-daemon設置這樣的伺服器相對
+簡單。同時,免費的公共託管網站(例如github)也開始出現在網絡上。成熟的開發
+人員可以在kernel.org上獲得一個帳戶,但這些帳戶並不容易得到;更多有關信息,
+請參閱 https://kernel.org/faq/ 。
+
+正常的Git工作流程涉及到許多分支的使用。每一條開發線都可以分爲單獨的「主題
+分支」,並獨立維護。Git的分支很容易使用,沒有理由不使用它們。而且,在任何
+情況下,您都不應該在任何您打算讓其他人從中拉取的分支中進行開發。應該小心地
+創建公開可用的分支;當開發分支處於完整狀態並已準備好時(而不是之前)才合併
+開發分支的補丁。
+
+Git提供了一些強大的工具,可以讓您重寫開發歷史。一個不方便的補丁(比如說,
+一個打破二分法的補丁,或者有其他一些明顯的缺陷)可以在適當的位置修復,或者
+完全從歷史中消失。一個補丁系列可以被重寫,就好像它是在今天的主線上寫的一樣,
+即使你已經花了幾個月的時間在寫它。可以透明地將更改從一個分支轉移到另一個
+分支。等等。明智地使用git修改歷史的能力可以幫助創建問題更少的乾淨補丁集。
+
+然而,過度使用這種功能可能會導致其他問題,而不僅僅是對創建完美項目歷史的
+簡單癡迷。重寫歷史將重寫該歷史中包含的更改,將經過測試(希望如此)的內核樹
+變爲未經測試的內核樹。除此之外,如果開發人員沒有共享項目歷史,他們就無法
+輕鬆地協作;如果您重寫了其他開發人員拉入他們存儲庫的歷史,您將使這些開發
+人員的生活更加困難。因此,這裡有一個簡單的經驗法則:被導出到其他地方的歷史
+在此後通常被認爲是不可變的。
+
+因此,一旦將一組更改推送到公開可用的伺服器上,就不應該重寫這些更改。如果您
+嘗試強制進行無法快進合併的更改(即不共享同一歷史記錄的更改),Git將嘗試強制
+執行此規則。這可能覆蓋檢查,有時甚至需要重寫導出的樹。在樹之間移動變更集以
+避免linux-next中的衝突就是一個例子。但這種行爲應該是罕見的。這就是爲什麼
+開發應該在私有分支中進行(必要時可以重寫)並且只有在公共分支處於合理的較新
+狀態時才轉移到公共分支中的原因之一。
+
+當主線(或其他一組變更所基於的樹)前進時,很容易與該樹合併以保持領先地位。
+對於一個私有的分支,rebasing 可能是一個很容易跟上另一棵樹的方法,但是一旦
+一棵樹被導出到外界,rebasing就不可取了。一旦發生這種情況,就必須進行完全
+合併(merge)。合併有時是很有意義的,但是過於頻繁的合併會不必要地擾亂歷史。
+在這種情況下建議的做法是不要頻繁合併,通常只在特定的發布點(如主線-rc發布)
+合併。如果您對特定的更改感到緊張,則可以始終在私有分支中執行測試合併。在
+這種情況下,git「rerere」工具很有用;它能記住合併衝突是如何解決的,這樣您
+就不必重複相同的工作。
+
+關於Git這樣的工具的一個最大的反覆抱怨是:補丁從一個存儲庫到另一個存儲庫的
+大量移動使得很容易陷入錯誤建議的變更中,這些變更避開審查雷達進入主線。當內
+核開發人員看到這種情況發生時,他們往往會感到不高興;在Git樹上放置未審閱或
+主題外的補丁可能會影響您將來讓樹被拉取的能力。引用Linus的話:
+
+::
+
+ 你可以給我發補丁,但當我從你那裡拉取一個Git補丁時,我需要知道你清楚
+ 自己在做什麼,我需要能夠相信事情而 *無需* 手動檢查每個單獨的更改。
+
+(http://lwn.net/articles/224135/)。
+
+爲了避免這種情況,請確保給定分支中的所有補丁都與相關主題緊密相關;「驅動程序
+修復」分支不應更改核心內存管理代碼。而且,最重要的是,不要使用Git樹來繞過
+審查過程。不時的將樹的摘要發布到相關的列表中,在合適時候請求linux-next中
+包含該樹。
+
+如果其他人開始發送補丁以包含到您的樹中,不要忘記審閱它們。還要確保您維護正確
+的作者信息; git 「am」工具在這方面做得最好,但是如果補丁通過第三方轉發給您,
+您可能需要在補丁中添加「From:」行。
+
+請求拉取時,請務必提供所有相關信息:樹的位置、要拉取的分支以及拉取將導致的
+更改。在這方面 git request-pull 命令非常有用;它將按照其他開發人員所期望的
+格式化請求,並檢查以確保您已記得將這些更改推送到公共伺服器。
+
+審閱補丁
+--------
+
+一些讀者顯然會反對將本節與「高級主題」放在一起,因爲即使是剛開始的內核開發人員
+也應該審閱補丁。當然,沒有比查看其他人發布的代碼更好的方法來學習如何在內核環境
+中編程了。此外,審閱者永遠供不應求;通過審閱代碼,您可以對整個流程做出重大貢獻。
+
+審查代碼可能是一副令人生畏的圖景,特別是對一個新的內核開發人員來說,他們
+可能會對公開詢問代碼感到緊張,而這些代碼是由那些有更多經驗的人發布的。不過,
+即使是最有經驗的開發人員編寫的代碼也可以得到改進。也許對(所有)審閱者最好
+的建議是:把審閱評論當成問題而不是批評。詢問「在這條路徑中如何釋放鎖?」
+總是比說「這裡的鎖是錯誤的」更好。
+
+不同的開發人員將從不同的角度審查代碼。部分人會主要關注代碼風格以及代碼行是
+否有尾隨空格。其他人會主要關注補丁作爲一個整體實現的變更是否對內核有好處。
+同時也有人會檢查是否存在鎖問題、堆棧使用過度、可能的安全問題、在其他地方
+發現的代碼重複、足夠的文檔、對性能的不利影響、用戶空間ABI更改等。所有類型
+的檢查,只要它們能引導更好的代碼進入內核,都是受歡迎和值得的。
+
diff --git a/Documentation/translations/zh_TW/process/8.Conclusion.rst b/Documentation/translations/zh_TW/process/8.Conclusion.rst
new file mode 100644
index 000000000000..7572b17667d9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/8.Conclusion.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>`
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_conclusion:
+
+更多信息
+========
+
+關於Linux內核開發和相關主題的信息來源很多。首先是在內核原始碼分發中找到的
+文檔目錄。頂級
+:ref:`Documentation/translations/zh_TW/process/howto.rst <tw_process_howto>`
+文件是一個重要的起點;
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和 :ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+也是所有內核開發人員都應該閱讀的內容。許多內部內核API都是使用kerneldoc機制
+記錄的;「make htmldocs」或「make pdfdocs」可用於以HTML或PDF格式生成這些文檔
+(儘管某些發行版提供的tex版本會遇到內部限制,無法正確處理文檔)。
+
+不同的網站在各個細節層次上討論內核開發。本文作者想謙虛地建議用 https://lwn.net/
+作爲來源;有關許多特定內核主題的信息可以通過以下網址的 LWN 內核索引找到:
+
+ http://lwn.net/kernel/index/
+
+除此之外,內核開發人員的一個寶貴資源是:
+
+ https://kernelnewbies.org/
+
+當然,也不應該忘記 https://kernel.org/ ,這是內核發布信息的最終位置。
+
+關於內核開發有很多書:
+
+ 《Linux設備驅動程序》第三版(Jonathan Corbet、Alessandro Rubini和Greg Kroah Hartman)
+ 線上版本在 http://lwn.net/kernel/ldd3/
+
+ 《Linux內核設計與實現》(Robert Love)
+
+ 《深入理解Linux內核》(Daniel Bovet和Marco Cesati)
+
+然而,所有這些書都有一個共同的缺點:它們上架時就往往有些過時,而且已經上架
+一段時間了。不過,在那裡還是可以找到相當多的好信息。
+
+有關git的文檔,請訪問:
+
+ https://www.kernel.org/pub/software/scm/git/docs/
+
+ https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+結論
+====
+
+祝賀所有通過這篇冗長的文檔的人。希望它能夠幫助您理解Linux內核是如何開發的,
+以及您如何參與這個過程。
+
+最後,重要的是參與。任何開源軟體項目都不會超過其貢獻者投入其中的總和。Linux
+內核的發展速度和以前一樣快,因爲它得到了大量開發人員的幫助,他們都在努力使它
+變得更好。內核是一個最成功的例子,說明了當成千上萬的人爲了一個共同的目標一起
+工作時,可以做出什麼。
+
+不過,內核總是可以從更大的開發人員基礎中獲益。總有更多的工作要做。但是同樣
+重要的是,Linux生態系統中的大多數其他參與者可以通過爲內核做出貢獻而受益。使
+代碼進入主線是提高代碼質量、降低維護和分發成本、提高對內核開發方向的影響程度
+等的關鍵。這是一種共贏的局面。啓動你的編輯器,來加入我們吧;你會非常受歡迎的。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
new file mode 100644
index 000000000000..949d831aaf6c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
@@ -0,0 +1,112 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct-interpretation.rst <code_of_conduct_interpretation>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct_interpretation:
+
+Linux內核貢獻者契約行為準則解釋
+===============================
+
+:ref:`tw_code_of_conduct` 準則是一個通用文檔,旨在爲幾乎所有開源社區提供一套規則。
+每個開源社區都是獨一無二的,Linux內核也不例外。因此,本文描述了Linux內核社區中
+如何解釋它。我們也不希望這種解釋隨著時間的推移是靜態的,並將根據需要進行調整。
+
+與開發軟體的「傳統」方法相比,Linux內核開發工作是一個非常個人化的過程。你的貢獻
+和背後的想法將被仔細審查,往往導致批判和批評。審查將幾乎總是需要改進,材料才
+能包括在內核中。要知道這是因爲所有相關人員都希望看到Linux整體成功的最佳解決方
+案。這個開發過程已經被證明可以創建有史以來最健壯的作業系統內核,我們不想做任何
+事情來導致提交質量和最終結果的下降。
+
+維護者
+------
+
+行為準則多次使用「維護者」一詞。在內核社區中,「維護者」是負責子系統、驅動程序或
+文件的任何人,並在內核原始碼樹的維護者文件中列出。
+
+責任
+----
+
+《行為準則》提到了維護人員的權利和責任,這需要進一步澄清。
+
+首先,最重要的是,有一個合理的期望是由維護人員通過實例來領導。
+
+也就是說,我們的社區是廣闊的,對維護者沒有新的要求,他們單方面處理其他人在
+他們活躍的社區的行爲。這一責任由我們所有人承擔,最終《行為準則》記錄了最終的
+上訴路徑,以防有關行爲問題的問題懸而未決。
+
+維護人員應該願意在出現問題時提供幫助,並在需要時與社區中的其他人合作。如果您
+不確定如何處理出現的情況,請不要害怕聯繫技術諮詢委員會(TAB)或其他維護人員。
+除非您願意,否則不會將其視爲違規報告。如果您不確定是否該聯繫TAB 或任何其他維
+護人員,請聯繫我們的衝突調解人 Mishi Choudhary <mishi@linux.com>。
+
+最後,「善待對方」才是每個人的最終目標。我們知道每個人都是人,有時我們都會失敗,
+但我們所有人的首要目標應該是努力友好地解決問題。執行行為準則將是最後的選擇。
+
+我們的目標是創建一個強大的、技術先進的作業系統,以及所涉及的技術複雜性,這自
+然需要專業知識和決策。
+
+所需的專業知識因貢獻領域而異。它主要由上下文和技術複雜性決定,其次由貢獻者和
+維護者的期望決定。
+
+專家的期望和決策都要經過討論,但在最後,爲了取得進展,必須能夠做出決策。這一
+特權掌握在維護人員和項目領導的手中,預計將善意使用。
+
+因此,設定專業知識期望、作出決定和拒絕不適當的貢獻不被視爲違反行為準則。
+
+雖然維護人員一般都歡迎新來者,但他們幫助(新)貢獻者克服障礙的能力有限,因此
+他們必須確定優先事項。這也不應被視爲違反了行為準則。內核社區意識到這一點,並
+以各種形式提供入門級節目,如 kernelnewbies.org 。
+
+範圍
+----
+
+Linux內核社區主要在一組公共電子郵件列表上進行交互,這些列表分布在由多個不同
+公司或個人控制的多個不同伺服器上。所有這些列表都在內核原始碼樹中的
+MAINTAINERS 文件中定義。發送到這些郵件列表的任何電子郵件都被視爲包含在行爲
+準則中。
+
+使用 kernel.org bugzilla和其他子系統bugzilla 或bug跟蹤工具的開發人員應該遵循
+行為準則的指導原則。Linux內核社區沒有「官方」項目電子郵件地址或「官方」社交媒體
+地址。使用kernel.org電子郵件帳戶執行的任何活動必須遵循爲kernel.org發布的行爲
+準則,就像任何使用公司電子郵件帳戶的個人必須遵循該公司的特定規則一樣。
+
+行為準則並不禁止在郵件列表消息、內核更改日誌消息或代碼注釋中繼續包含名稱、
+電子郵件地址和相關注釋。
+
+其他論壇中的互動包括在適用於上述論壇的任何規則中,通常不包括在行為準則中。
+除了在極端情況下可考慮的例外情況。
+
+提交給內核的貢獻應該使用適當的語言。在行為準則之前已經存在的內容現在不會被
+視爲違反。然而,不適當的語言可以被視爲一個bug;如果任何相關方提交補丁,
+這樣的bug將被更快地修復。當前屬於用戶/內核API的一部分的表達式,或者反映已
+發布標準或規範中使用的術語的表達式,不被視爲bug。
+
+執行
+----
+
+行為準則中列出的地址屬於行為準則委員會。https://kernel.org/code-of-conduct.html
+列出了在任何給定時間接收這些電子郵件的確切成員。成員不能訪問在加入委員會之前
+或離開委員會之後所做的報告。
+
+最初的行為準則委員會由TAB的志願者以及作爲中立第三方的專業調解人組成。委員會
+的首要任務是建立文件化的流程,並將其公開。
+
+如果報告人不希望將整個委員會納入投訴或關切,可直接聯繫委員會的任何成員,包括
+調解人。
+
+行為準則委員會根據流程審查案例(見上文),並根據需要和適當與TAB協商,例如請求
+和接收有關內核社區的信息。
+
+委員會做出的任何決定都將提交到表中,以便在必要時與相關維護人員一起執行。行爲
+準則委員會的決定可以通過三分之二的投票推翻。
+
+每季度,行為準則委員會和標籤將提供一份報告,概述行為準則委員會收到的匿名報告
+及其狀態,以及任何否決決定的細節,包括完整和可識別的投票細節。
+
+我們希望在啓動期之後爲行為準則委員會人員配備建立一個不同的流程。發生此情況時,
+將使用該信息更新此文檔。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct.rst b/Documentation/translations/zh_TW/process/code-of-conduct.rst
new file mode 100644
index 000000000000..716e5843b6e9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct.rst <code_of_conduct>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct:
+
+貢獻者契約行為準則
+++++++++++++++++++
+
+我們的誓言
+==========
+
+爲了營造一個開放、友好的環境,我們作爲貢獻者和維護人承諾,讓我們的社區和參
+與者,擁有一個無騷擾的體驗,無論年齡、體型、殘疾、種族、性別特徵、性別認同
+和表達、經驗水平、教育程度、社會狀況,經濟地位、國籍、個人外貌、種族、宗教
+或性身份和取向。
+
+我們的標準
+==========
+
+有助於創造積極環境的行爲包括:
+
+* 使用歡迎和包容的語言
+* 尊重不同的觀點和經驗
+* 優雅地接受建設性的批評
+* 關注什麼對社區最有利
+* 對其他社區成員表示同情
+
+參與者的不可接受行爲包括:
+
+* 使用性意味的語言或意象以及不受歡迎的性注意或者更過分的行爲
+* 煽動、侮辱/貶損評論以及個人或政治攻擊
+* 公開或私下騷擾
+* 未經明確許可,發布他人的私人信息,如物理或電子地址。
+* 在專業場合被合理認爲不適當的其他行爲
+
+我們的責任
+==========
+
+維護人員負責澄清可接受行爲的標準,並應針對任何不可接受行爲採取適當和公平的
+糾正措施。
+
+維護人員有權和責任刪除、編輯或拒絕與本行為準則不一致的評論、承諾、代碼、
+wiki編輯、問題和其他貢獻,或暫時或永久禁止任何貢獻者從事他們認爲不適當、
+威脅、冒犯或有害的其他行爲。
+
+範圍
+====
+
+當個人代表項目或其社區時,本行為準則既適用於項目空間,也適用於公共空間。
+代表一個項目或社區的例子包括使用一個正式的項目電子郵件地址,通過一個正式
+的社交媒體帳戶發布,或者在在線或離線事件中擔任指定的代表。項目維護人員可以
+進一步定義和澄清項目的表示。
+
+執行
+====
+
+如有濫用、騷擾或其他不可接受的行爲,可聯繫行為準則委員會<conduct@kernel.org>。
+所有投訴都將接受審查和調查,並將得到必要和適當的答覆。行為準則委員會有義務
+對事件報告人保密。具體執行政策的進一步細節可單獨公布。
+
+歸屬
+====
+
+本行為準則改編自《貢獻者契約》,版本1.4,可從
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 獲取。
+
+解釋
+====
+
+有關Linux內核社區如何解釋此文檔,請參閱 :ref:`tw_code_of_conduct_interpretation`
+
diff --git a/Documentation/translations/zh_TW/process/coding-style.rst b/Documentation/translations/zh_TW/process/coding-style.rst
new file mode 100644
index 000000000000..61e614aad6a7
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/coding-style.rst
@@ -0,0 +1,958 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
+
+.. _tw_codingstyle:
+
+譯者::
+
+ 中文版維護者: 張樂 Zhang Le <r0bertz@gentoo.org>
+ 中文版翻譯者: 張樂 Zhang Le <r0bertz@gentoo.org>
+ 中文版校譯者: 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+ wheelz <kernel.zeng@gmail.com>
+ 管旭東 Xudong Guan <xudong.guan@gmail.com>
+ Li Zefan <lizf@cn.fujitsu.com>
+ Wang Chen <wangchen@cn.fujitsu.com>
+ Hu Haowen <src.res@email.cn>
+
+Linux 內核代碼風格
+=========================
+
+這是一個簡短的文檔,描述了 linux 內核的首選代碼風格。代碼風格是因人而異的,
+而且我不願意把自己的觀點強加給任何人,但這就像我去做任何事情都必須遵循的原則
+那樣,我也希望在絕大多數事上保持這種的態度。請 (在寫代碼時) 至少考慮一下這裡
+的代碼風格。
+
+首先,我建議你列印一份 GNU 代碼規範,然後不要讀。燒了它,這是一個具有重大象徵
+性意義的動作。
+
+不管怎樣,現在我們開始:
+
+
+1) 縮進
+--------------
+
+制表符是 8 個字符,所以縮進也是 8 個字符。有些異端運動試圖將縮進變爲 4 (甚至
+2!) 字符深,這幾乎相當於嘗試將圓周率的值定義爲 3。
+
+理由:縮進的全部意義就在於清楚的定義一個控制塊起止於何處。尤其是當你盯著你的
+屏幕連續看了 20 小時之後,你將會發現大一點的縮進會使你更容易分辨縮進。
+
+現在,有些人會抱怨 8 個字符的縮進會使代碼向右邊移動的太遠,在 80 個字符的終端
+屏幕上就很難讀這樣的代碼。這個問題的答案是,如果你需要 3 級以上的縮進,不管用
+何種方式你的代碼已經有問題了,應該修正你的程序。
+
+簡而言之,8 個字符的縮進可以讓代碼更容易閱讀,還有一個好處是當你的函數嵌套太
+深的時候可以給你警告。留心這個警告。
+
+在 switch 語句中消除多級縮進的首選的方式是讓 ``switch`` 和從屬於它的 ``case``
+標籤對齊於同一列,而不要 ``兩次縮進`` ``case`` 標籤。比如:
+
+.. code-block:: c
+
+ switch (suffix) {
+ case 'G':
+ case 'g':
+ mem <<= 30;
+ break;
+ case 'M':
+ case 'm':
+ mem <<= 20;
+ break;
+ case 'K':
+ case 'k':
+ mem <<= 10;
+ fallthrough;
+ default:
+ break;
+ }
+
+不要把多個語句放在一行里,除非你有什麼東西要隱藏:
+
+.. code-block:: c
+
+ if (condition) do_this;
+ do_something_everytime;
+
+也不要在一行里放多個賦值語句。內核代碼風格超級簡單。就是避免可能導致別人誤讀
+的表達式。
+
+除了注釋、文檔和 Kconfig 之外,不要使用空格來縮進,前面的例子是例外,是有意爲
+之。
+
+選用一個好的編輯器,不要在行尾留空格。
+
+
+2) 把長的行和字符串打散
+------------------------------
+
+代碼風格的意義就在於使用平常使用的工具來維持代碼的可讀性和可維護性。
+
+每一行的長度的限制是 80 列,我們強烈建議您遵守這個慣例。
+
+長於 80 列的語句要打散成有意義的片段。除非超過 80 列能顯著增加可讀性,並且不
+會隱藏信息。子片段要明顯短於母片段,並明顯靠右。這同樣適用於有著很長參數列表
+的函數頭。然而,絕對不要打散對用戶可見的字符串,例如 printk 信息,因爲這樣就
+很難對它們 grep。
+
+
+3) 大括號和空格的放置
+------------------------------
+
+C 語言風格中另外一個常見問題是大括號的放置。和縮進大小不同,選擇或棄用某种放
+置策略並沒有多少技術上的原因,不過首選的方式,就像 Kernighan 和 Ritchie 展示
+給我們的,是把起始大括號放在行尾,而把結束大括號放在行首,所以:
+
+.. code-block:: c
+
+ if (x is true) {
+ we do y
+ }
+
+這適用於所有的非函數語句塊 (if, switch, for, while, do)。比如:
+
+.. code-block:: c
+
+ switch (action) {
+ case KOBJ_ADD:
+ return "add";
+ case KOBJ_REMOVE:
+ return "remove";
+ case KOBJ_CHANGE:
+ return "change";
+ default:
+ return NULL;
+ }
+
+不過,有一個例外,那就是函數:函數的起始大括號放置於下一行的開頭,所以:
+
+.. code-block:: c
+
+ int function(int x)
+ {
+ body of function
+ }
+
+全世界的異端可能會抱怨這個不一致性是... 呃... 不一致的,不過所有思維健全的人
+都知道 (a) K&R 是 **正確的** 並且 (b) K&R 是正確的。此外,不管怎樣函數都是特
+殊的 (C 函數是不能嵌套的)。
+
+注意結束大括號獨自占據一行,除非它後面跟著同一個語句的剩餘部分,也就是 do 語
+句中的 "while" 或者 if 語句中的 "else",像這樣:
+
+.. code-block:: c
+
+ do {
+ body of do-loop
+ } while (condition);
+
+和
+
+.. code-block:: c
+
+ if (x == y) {
+ ..
+ } else if (x > y) {
+ ...
+ } else {
+ ....
+ }
+
+理由:K&R。
+
+也請注意這種大括號的放置方式也能使空 (或者差不多空的) 行的數量最小化,同時不
+失可讀性。因此,由於你的屏幕上的新行是不可再生資源 (想想 25 行的終端屏幕),你
+將會有更多的空行來放置注釋。
+
+當只有一個單獨的語句的時候,不用加不必要的大括號。
+
+.. code-block:: c
+
+ if (condition)
+ action();
+
+和
+
+.. code-block:: c
+
+ if (condition)
+ do_this();
+ else
+ do_that();
+
+這並不適用於只有一個條件分支是單語句的情況;這時所有分支都要使用大括號:
+
+.. code-block:: c
+
+ if (condition) {
+ do_this();
+ do_that();
+ } else {
+ otherwise();
+ }
+
+3.1) 空格
+********************
+
+Linux 內核的空格使用方式 (主要) 取決於它是用於函數還是關鍵字。(大多數) 關鍵字
+後要加一個空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,這
+些關鍵字某些程度上看起來更像函數 (它們在 Linux 里也常常伴隨小括號而使用,儘管
+在 C 里這樣的小括號不是必需的,就像 ``struct fileinfo info;`` 聲明過後的
+``sizeof info``)。
+
+所以在這些關鍵字之後放一個空格::
+
+ if, switch, case, for, do, while
+
+但是不要在 sizeof, typeof, alignof 或者 __attribute__ 這些關鍵字之後放空格。
+例如,
+
+.. code-block:: c
+
+ s = sizeof(struct file);
+
+不要在小括號里的表達式兩側加空格。這是一個 **反例** :
+
+.. code-block:: c
+
+ s = sizeof( struct file );
+
+當聲明指針類型或者返回指針類型的函數時, ``*`` 的首選使用方式是使之靠近變量名
+或者函數名,而不是靠近類型名。例子:
+
+.. code-block:: c
+
+ char *linux_banner;
+ unsigned long long memparse(char *ptr, char **retptr);
+ char *match_strdup(substring_t *s);
+
+在大多數二元和三元操作符兩側使用一個空格,例如下面所有這些操作符::
+
+ = + - < > * / % | & ^ <= >= == != ? :
+
+但是一元操作符後不要加空格::
+
+ & * + - ~ ! sizeof typeof alignof __attribute__ defined
+
+後綴自加和自減一元操作符前不加空格::
+
+ ++ --
+
+前綴自加和自減一元操作符後不加空格::
+
+ ++ --
+
+``.`` 和 ``->`` 結構體成員操作符前後不加空格。
+
+不要在行尾留空白。有些可以自動縮進的編輯器會在新行的行首加入適量的空白,然後
+你就可以直接在那一行輸入代碼。不過假如你最後沒有在那一行輸入代碼,有些編輯器
+就不會移除已經加入的空白,就像你故意留下一個只有空白的行。包含行尾空白的行就
+這樣產生了。
+
+當 git 發現補丁包含了行尾空白的時候會警告你,並且可以應你的要求去掉行尾空白;
+不過如果你是正在打一系列補丁,這樣做會導致後面的補丁失敗,因爲你改變了補丁的
+上下文。
+
+
+4) 命名
+------------------------------
+
+C 是一個簡樸的語言,你的命名也應該這樣。和 Modula-2 和 Pascal 程式設計師不同,
+C 程式設計師不使用類似 ThisVariableIsATemporaryCounter 這樣華麗的名字。C 程式設計師會
+稱那個變量爲 ``tmp`` ,這樣寫起來會更容易,而且至少不會令其難於理解。
+
+不過,雖然混用大小寫的名字是不提倡使用的,但是全局變量還是需要一個具描述性的
+名字。稱一個全局函數爲 ``foo`` 是一個難以饒恕的錯誤。
+
+全局變量 (只有當你 **真正** 需要它們的時候再用它) 需要有一個具描述性的名字,就
+像全局函數。如果你有一個可以計算活動用戶數量的函數,你應該叫它
+``count_active_users()`` 或者類似的名字,你不應該叫它 ``cntuser()`` 。
+
+在函數名中包含函數類型 (所謂的匈牙利命名法) 是腦子出了問題——編譯器知道那些類
+型而且能夠檢查那些類型,這樣做只能把程式設計師弄糊塗了。難怪微軟總是製造出有問題
+的程序。
+
+本地變量名應該簡短,而且能夠表達相關的含義。如果你有一些隨機的整數型的循環計
+數器,它應該被稱爲 ``i`` 。叫它 ``loop_counter`` 並無益處,如果它沒有被誤解的
+可能的話。類似的, ``tmp`` 可以用來稱呼任意類型的臨時變量。
+
+如果你怕混淆了你的本地變量名,你就遇到另一個問題了,叫做函數增長荷爾蒙失衡綜
+合症。請看第六章 (函數)。
+
+
+5) Typedef
+-----------
+
+不要使用類似 ``vps_t`` 之類的東西。
+
+對結構體和指針使用 typedef 是一個 **錯誤** 。當你在代碼里看到:
+
+.. code-block:: c
+
+ vps_t a;
+
+這代表什麼意思呢?
+
+相反,如果是這樣
+
+.. code-block:: c
+
+ struct virtual_container *a;
+
+你就知道 ``a`` 是什麼了。
+
+很多人認爲 typedef ``能提高可讀性`` 。實際不是這樣的。它們只在下列情況下有用:
+
+ (a) 完全不透明的對象 (這種情況下要主動使用 typedef 來 **隱藏** 這個對象實際上
+ 是什麼)。
+
+ 例如: ``pte_t`` 等不透明對象,你只能用合適的訪問函數來訪問它們。
+
+ .. note::
+
+ 不透明性和 "訪問函數" 本身是不好的。我們使用 pte_t 等類型的原因在於真
+ 的是完全沒有任何共用的可訪問信息。
+
+ (b) 清楚的整數類型,如此,這層抽象就可以 **幫助** 消除到底是 ``int`` 還是
+ ``long`` 的混淆。
+
+ u8/u16/u32 是完全沒有問題的 typedef,不過它們更符合類別 (d) 而不是這裡。
+
+ .. note::
+
+ 要這樣做,必須事出有因。如果某個變量是 ``unsigned long`` ,那麼沒有必要
+
+ typedef unsigned long myflags_t;
+
+ 不過如果有一個明確的原因,比如它在某種情況下可能會是一個 ``unsigned int``
+ 而在其他情況下可能爲 ``unsigned long`` ,那麼就不要猶豫,請務必使用
+ typedef。
+
+ (c) 當你使用 sparse 按字面的創建一個 **新** 類型來做類型檢查的時候。
+
+ (d) 和標準 C99 類型相同的類型,在某些例外的情況下。
+
+ 雖然讓眼睛和腦筋來適應新的標準類型比如 ``uint32_t`` 不需要花很多時間,可
+ 是有些人仍然拒絕使用它們。
+
+ 因此,Linux 特有的等同於標準類型的 ``u8/u16/u32/u64`` 類型和它們的有符號
+ 類型是被允許的——儘管在你自己的新代碼中,它們不是強制要求要使用的。
+
+ 當編輯已經使用了某個類型集的已有代碼時,你應該遵循那些代碼中已經做出的選
+ 擇。
+
+ (e) 可以在用戶空間安全使用的類型。
+
+ 在某些用戶空間可見的結構體裡,我們不能要求 C99 類型而且不能用上面提到的
+ ``u32`` 類型。因此,我們在與用戶空間共享的所有結構體中使用 __u32 和類似
+ 的類型。
+
+可能還有其他的情況,不過基本的規則是 **永遠不要** 使用 typedef,除非你可以明
+確的應用上述某個規則中的一個。
+
+總的來說,如果一個指針或者一個結構體裡的元素可以合理的被直接訪問到,那麼它們
+就不應該是一個 typedef。
+
+
+6) 函數
+------------------------------
+
+函數應該簡短而漂亮,並且只完成一件事情。函數應該可以一屏或者兩屏顯示完 (我們
+都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
+
+一個函數的最大長度是和該函數的複雜度和縮進級數成反比的。所以,如果你有一個理
+論上很簡單的只有一個很長 (但是簡單) 的 case 語句的函數,而且你需要在每個 case
+里做很多很小的事情,這樣的函數儘管很長,但也是可以的。
+
+不過,如果你有一個複雜的函數,而且你懷疑一個天分不是很高的高中一年級學生可能
+甚至搞不清楚這個函數的目的,你應該嚴格遵守前面提到的長度限制。使用輔助函數,
+並爲之取個具描述性的名字 (如果你覺得它們的性能很重要的話,可以讓編譯器內聯它
+們,這樣的效果往往會比你寫一個複雜函數的效果要好。)
+
+函數的另外一個衡量標準是本地變量的數量。此數量不應超過 5-10 個,否則你的函數
+就有問題了。重新考慮一下你的函數,把它分拆成更小的函數。人的大腦一般可以輕鬆
+的同時跟蹤 7 個不同的事物,如果再增多的話,就會糊塗了。即便你聰穎過人,你也可
+能會記不清你 2 個星期前做過的事情。
+
+在源文件里,使用空行隔開不同的函數。如果該函數需要被導出,它的 **EXPORT** 宏
+應該緊貼在它的結束大括號之下。比如:
+
+.. code-block:: c
+
+ int system_is_up(void)
+ {
+ return system_state == SYSTEM_RUNNING;
+ }
+ EXPORT_SYMBOL(system_is_up);
+
+在函數原型中,包含函數名和它們的數據類型。雖然 C 語言裡沒有這樣的要求,在
+Linux 里這是提倡的做法,因爲這樣可以很簡單的給讀者提供更多的有價值的信息。
+
+
+7) 集中的函數退出途徑
+------------------------------
+
+雖然被某些人聲稱已經過時,但是 goto 語句的等價物還是經常被編譯器所使用,具體
+形式是無條件跳轉指令。
+
+當一個函數從多個位置退出,並且需要做一些類似清理的常見操作時,goto 語句就很方
+便了。如果並不需要清理操作,那麼直接 return 即可。
+
+選擇一個能夠說明 goto 行爲或它爲何存在的標籤名。如果 goto 要釋放 ``buffer``,
+一個不錯的名字可以是 ``out_free_buffer:`` 。別去使用像 ``err1:`` 和 ``err2:``
+這樣的GW_BASIC 名稱,因爲一旦你添加或刪除了 (函數的) 退出路徑,你就必須對它們
+重新編號,這樣會難以去檢驗正確性。
+
+使用 goto 的理由是:
+
+- 無條件語句容易理解和跟蹤
+- 嵌套程度減小
+- 可以避免由於修改時忘記更新個別的退出點而導致錯誤
+- 讓編譯器省去刪除冗餘代碼的工作 ;)
+
+.. code-block:: c
+
+ int fun(int a)
+ {
+ int result = 0;
+ char *buffer;
+
+ buffer = kmalloc(SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ if (condition1) {
+ while (loop1) {
+ ...
+ }
+ result = 1;
+ goto out_free_buffer;
+ }
+ ...
+ out_free_buffer:
+ kfree(buffer);
+ return result;
+ }
+
+一個需要注意的常見錯誤是 ``一個 err 錯誤`` ,就像這樣:
+
+.. code-block:: c
+
+ err:
+ kfree(foo->bar);
+ kfree(foo);
+ return ret;
+
+這段代碼的錯誤是,在某些退出路徑上 ``foo`` 是 NULL。通常情況下,通過把它分離
+成兩個錯誤標籤 ``err_free_bar:`` 和 ``err_free_foo:`` 來修復這個錯誤:
+
+.. code-block:: c
+
+ err_free_bar:
+ kfree(foo->bar);
+ err_free_foo:
+ kfree(foo);
+ return ret;
+
+理想情況下,你應該模擬錯誤來測試所有退出路徑。
+
+
+8) 注釋
+------------------------------
+
+注釋是好的,不過有過度注釋的危險。永遠不要在注釋里解釋你的代碼是如何運作的:
+更好的做法是讓別人一看你的代碼就可以明白,解釋寫的很差的代碼是浪費時間。
+
+一般的,你想要你的注釋告訴別人你的代碼做了什麼,而不是怎麼做的。也請你不要把
+注釋放在一個函數體內部:如果函數複雜到你需要獨立的注釋其中的一部分,你很可能
+需要回到第六章看一看。你可以做一些小注釋來註明或警告某些很聰明 (或者槽糕) 的
+做法,但不要加太多。你應該做的,是把注釋放在函數的頭部,告訴人們它做了什麼,
+也可以加上它做這些事情的原因。
+
+當注釋內核 API 函數時,請使用 kernel-doc 格式。請看
+Documentation/doc-guide/ 和 scripts/kernel-doc 以獲得詳細信息。
+
+長 (多行) 注釋的首選風格是:
+
+.. code-block:: c
+
+ /*
+ * This is the preferred style for multi-line
+ * comments in the Linux kernel source code.
+ * Please use it consistently.
+ *
+ * Description: A column of asterisks on the left side,
+ * with beginning and ending almost-blank lines.
+ */
+
+對於在 net/ 和 drivers/net/ 的文件,首選的長 (多行) 注釋風格有些不同。
+
+.. code-block:: c
+
+ /* The preferred comment style for files in net/ and drivers/net
+ * looks like this.
+ *
+ * It is nearly the same as the generally preferred comment style,
+ * but there is no initial almost-blank line.
+ */
+
+注釋數據也是很重要的,不管是基本類型還是衍生類型。爲了方便實現這一點,每一行
+應只聲明一個數據 (不要使用逗號來一次聲明多個數據)。這樣你就有空間來爲每個數據
+寫一段小注釋來解釋它們的用途了。
+
+
+9) 你已經把事情弄糟了
+------------------------------
+
+這沒什麼,我們都是這樣。可能你的使用了很長時間 Unix 的朋友已經告訴你
+``GNU emacs`` 能自動幫你格式化 C 原始碼,而且你也注意到了,確實是這樣,不過它
+所使用的默認值和我們想要的相去甚遠 (實際上,甚至比隨機打的還要差——無數個猴子
+在 GNU emacs 里打字永遠不會創造出一個好程序) (譯註:Infinite Monkey Theorem)
+
+所以你要麼放棄 GNU emacs,要麼改變它讓它使用更合理的設定。要採用後一個方案,
+你可以把下面這段粘貼到你的 .emacs 文件里。
+
+.. code-block:: none
+
+ (defun c-lineup-arglist-tabs-only (ignored)
+ "Line up argument lists by tabs, not spaces"
+ (let* ((anchor (c-langelem-pos c-syntactic-element))
+ (column (c-langelem-2nd-pos c-syntactic-element))
+ (offset (- (1+ column) anchor))
+ (steps (floor offset c-basic-offset)))
+ (* (max steps 1)
+ c-basic-offset)))
+
+ (dir-locals-set-class-variables
+ 'linux-kernel
+ '((c-mode . (
+ (c-basic-offset . 8)
+ (c-label-minimum-indentation . 0)
+ (c-offsets-alist . (
+ (arglist-close . c-lineup-arglist-tabs-only)
+ (arglist-cont-nonempty .
+ (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+ (arglist-intro . +)
+ (brace-list-intro . +)
+ (c . c-lineup-C-comments)
+ (case-label . 0)
+ (comment-intro . c-lineup-comment)
+ (cpp-define-intro . +)
+ (cpp-macro . -1000)
+ (cpp-macro-cont . +)
+ (defun-block-intro . +)
+ (else-clause . 0)
+ (func-decl-cont . +)
+ (inclass . +)
+ (inher-cont . c-lineup-multi-inher)
+ (knr-argdecl-intro . 0)
+ (label . -1000)
+ (statement . 0)
+ (statement-block-intro . +)
+ (statement-case-intro . +)
+ (statement-cont . +)
+ (substatement . +)
+ ))
+ (indent-tabs-mode . t)
+ (show-trailing-whitespace . t)
+ ))))
+
+ (dir-locals-set-directory-class
+ (expand-file-name "~/src/linux-trees")
+ 'linux-kernel)
+
+這會讓 emacs 在 ``~/src/linux-trees`` 下的 C 源文件獲得更好的內核代碼風格。
+
+不過就算你嘗試讓 emacs 正確的格式化代碼失敗了,也並不意味著你失去了一切:還可
+以用 ``indent`` 。
+
+不過,GNU indent 也有和 GNU emacs 一樣有問題的設定,所以你需要給它一些命令選
+項。不過,這還不算太糟糕,因爲就算是 GNU indent 的作者也認同 K&R 的權威性
+(GNU 的人並不是壞人,他們只是在這個問題上被嚴重的誤導了),所以你只要給 indent
+指定選項 ``-kr -i8`` (代表 ``K&R,8 字符縮進``),或使用 ``scripts/Lindent``
+這樣就可以以最時髦的方式縮進原始碼。
+
+``indent`` 有很多選項,特別是重新格式化注釋的時候,你可能需要看一下它的手冊。
+不過記住: ``indent`` 不能修正壞的編程習慣。
+
+
+10) Kconfig 配置文件
+------------------------------
+
+對於遍布源碼樹的所有 Kconfig* 配置文件來說,它們縮進方式有所不同。緊挨著
+``config`` 定義的行,用一個制表符縮進,然而 help 信息的縮進則額外增加 2 個空
+格。舉個例子::
+
+ config AUDIT
+ bool "Auditing support"
+ depends on NET
+ help
+ Enable auditing infrastructure that can be used with another
+ kernel subsystem, such as SELinux (which requires this for
+ logging of avc messages output). Does not do system-call
+ auditing without CONFIG_AUDITSYSCALL.
+
+而那些危險的功能 (比如某些文件系統的寫支持) 應該在它們的提示字符串里顯著的聲
+明這一點::
+
+ config ADFS_FS_RW
+ bool "ADFS write support (DANGEROUS)"
+ depends on ADFS_FS
+ ...
+
+要查看配置文件的完整文檔,請看 Documentation/kbuild/kconfig-language.rst。
+
+
+11) 數據結構
+------------------------------
+
+如果一個數據結構,在創建和銷毀它的單線執行環境之外可見,那麼它必須要有一個引
+用計數器。內核里沒有垃圾收集 (並且內核之外的垃圾收集慢且效率低下),這意味著你
+絕對需要記錄你對這種數據結構的使用情況。
+
+引用計數意味著你能夠避免上鎖,並且允許多個用戶並行訪問這個數據結構——而不需要
+擔心這個數據結構僅僅因爲暫時不被使用就消失了,那些用戶可能不過是沉睡了一陣或
+者做了一些其他事情而已。
+
+注意上鎖 **不能** 取代引用計數。上鎖是爲了保持數據結構的一致性,而引用計數是一
+個內存管理技巧。通常二者都需要,不要把兩個搞混了。
+
+很多數據結構實際上有 2 級引用計數,它們通常有不同 ``類`` 的用戶。子類計數器統
+計子類用戶的數量,每當子類計數器減至零時,全局計數器減一。
+
+這種 ``多級引用計數`` 的例子可以在內存管理 (``struct mm_struct``: mm_users 和
+mm_count),和文件系統 (``struct super_block``: s_count 和 s_active) 中找到。
+
+記住:如果另一個執行線索可以找到你的數據結構,但這個數據結構沒有引用計數器,
+這裡幾乎肯定是一個 bug。
+
+
+12) 宏,枚舉和RTL
+------------------------------
+
+用於定義常量的宏的名字及枚舉里的標籤需要大寫。
+
+.. code-block:: c
+
+ #define CONSTANT 0x12345
+
+在定義幾個相關的常量時,最好用枚舉。
+
+宏的名字請用大寫字母,不過形如函數的宏的名字可以用小寫字母。
+
+一般的,如果能寫成內聯函數就不要寫成像函數的宏。
+
+含有多個語句的宏應該被包含在一個 do-while 代碼塊里:
+
+.. code-block:: c
+
+ #define macrofun(a, b, c) \
+ do { \
+ if (a == 5) \
+ do_this(b, c); \
+ } while (0)
+
+使用宏的時候應避免的事情:
+
+1) 影響控制流程的宏:
+
+.. code-block:: c
+
+ #define FOO(x) \
+ do { \
+ if (blah(x) < 0) \
+ return -EBUGGERED; \
+ } while (0)
+
+**非常** 不好。它看起來像一個函數,不過卻能導致 ``調用`` 它的函數退出;不要打
+亂讀者大腦里的語法分析器。
+
+2) 依賴於一個固定名字的本地變量的宏:
+
+.. code-block:: c
+
+ #define FOO(val) bar(index, val)
+
+可能看起來像是個不錯的東西,不過它非常容易把讀代碼的人搞糊塗,而且容易導致看起
+來不相關的改動帶來錯誤。
+
+3) 作爲左值的帶參數的宏: FOO(x) = y;如果有人把 FOO 變成一個內聯函數的話,這
+ 種用法就會出錯了。
+
+4) 忘記了優先級:使用表達式定義常量的宏必須將表達式置於一對小括號之內。帶參數
+ 的宏也要注意此類問題。
+
+.. code-block:: c
+
+ #define CONSTANT 0x4000
+ #define CONSTEXP (CONSTANT | 3)
+
+5) 在宏里定義類似函數的本地變量時命名衝突:
+
+.. code-block:: c
+
+ #define FOO(x) \
+ ({ \
+ typeof(x) ret; \
+ ret = calc_ret(x); \
+ (ret); \
+ })
+
+ret 是本地變量的通用名字 - __foo_ret 更不容易與一個已存在的變量衝突。
+
+cpp 手冊對宏的講解很詳細。gcc internals 手冊也詳細講解了 RTL,內核里的彙編語
+言經常用到它。
+
+
+13) 列印內核消息
+------------------------------
+
+內核開發者應該是受過良好教育的。請一定注意內核信息的拼寫,以給人以好的印象。
+不要用不規範的單詞比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保證這些信
+息簡單明了,無歧義。
+
+內核信息不必以英文句號結束。
+
+在小括號里列印數字 (%d) 沒有任何價值,應該避免這樣做。
+
+<linux/device.h> 里有一些驅動模型診斷宏,你應該使用它們,以確保信息對應於正確
+的設備和驅動,並且被標記了正確的消息級別。這些宏有:dev_err(), dev_warn(),
+dev_info() 等等。對於那些不和某個特定設備相關連的信息,<linux/printk.h> 定義
+了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
+
+寫出好的調試信息可以是一個很大的挑戰;一旦你寫出後,這些信息在遠程除錯時能提
+供極大的幫助。然而列印調試信息的處理方式同列印非調試信息不同。其他 pr_XXX()
+函數能無條件地列印,pr_debug() 卻不;默認情況下它不會被編譯,除非定義了 DEBUG
+或設定了 CONFIG_DYNAMIC_DEBUG。實際這同樣是爲了 dev_dbg(),一個相關約定是在一
+個已經開啓了 DEBUG 時,使用 VERBOSE_DEBUG 來添加 dev_vdbg()。
+
+許多子系統擁有 Kconfig 調試選項來開啓 -DDEBUG 在對應的 Makefile 裡面;在其他
+情況下,特殊文件使用 #define DEBUG。當一條調試信息需要被無條件列印時,例如,
+如果已經包含一個調試相關的 #ifdef 條件,printk(KERN_DEBUG ...) 就可被使用。
+
+
+14) 分配內存
+------------------------------
+
+內核提供了下面的一般用途的內存分配函數:
+kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
+請參考 API 文檔以獲取有關它們的詳細信息。
+
+傳遞結構體大小的首選形式是這樣的:
+
+.. code-block:: c
+
+ p = kmalloc(sizeof(*p), ...);
+
+另外一種傳遞方式中,sizeof 的操作數是結構體的名字,這樣會降低可讀性,並且可能
+會引入 bug。有可能指針變量類型被改變時,而對應的傳遞給內存分配函數的 sizeof
+的結果不變。
+
+強制轉換一個 void 指針返回值是多餘的。C 語言本身保證了從 void 指針到其他任何
+指針類型的轉換是沒有問題的。
+
+分配一個數組的首選形式是這樣的:
+
+.. code-block:: c
+
+ p = kmalloc_array(n, sizeof(...), ...);
+
+分配一個零長數組的首選形式是這樣的:
+
+.. code-block:: c
+
+ p = kcalloc(n, sizeof(...), ...);
+
+兩種形式檢查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
+
+
+15) 內聯弊病
+------------------------------
+
+有一個常見的誤解是 ``內聯`` 是 gcc 提供的可以讓代碼運行更快的一個選項。雖然使
+用內聯函數有時候是恰當的 (比如作爲一種替代宏的方式,請看第十二章),不過很多情
+況下不是這樣。inline 的過度使用會使內核變大,從而使整個系統運行速度變慢。
+因爲體積大內核會占用更多的指令高速緩存,而且會導致 pagecache 的可用內存減少。
+想像一下,一次 pagecache 未命中就會導致一次磁碟尋址,將耗時 5 毫秒。5 毫秒的
+時間內 CPU 能執行很多很多指令。
+
+一個基本的原則是如果一個函數有 3 行以上,就不要把它變成內聯函數。這個原則的一
+個例外是,如果你知道某個參數是一個編譯時常量,而且因爲這個常量你確定編譯器在
+編譯時能優化掉你的函數的大部分代碼,那仍然可以給它加上 inline 關鍵字。
+kmalloc() 內聯函數就是一個很好的例子。
+
+人們經常主張給 static 的而且只用了一次的函數加上 inline,如此不會有任何損失,
+因爲沒有什麼好權衡的。雖然從技術上說這是正確的,但是實際上這種情況下即使不加
+inline gcc 也可以自動使其內聯。而且其他用戶可能會要求移除 inline,由此而來的
+爭論會抵消 inline 自身的潛在價值,得不償失。
+
+
+16) 函數返回值及命名
+------------------------------
+
+函數可以返回多種不同類型的值,最常見的一種是表明函數執行成功或者失敗的值。這樣
+的一個值可以表示爲一個錯誤代碼整數 (-Exxx=失敗,0=成功) 或者一個 ``成功``
+布爾值 (0=失敗,非0=成功)。
+
+混合使用這兩種表達方式是難於發現的 bug 的來源。如果 C 語言本身嚴格區分整形和
+布爾型變量,那麼編譯器就能夠幫我們發現這些錯誤... 不過 C 語言不區分。爲了避免
+產生這種 bug,請遵循下面的慣例::
+
+ 如果函數的名字是一個動作或者強制性的命令,那麼這個函數應該返回錯誤代
+ 碼整數。如果是一個判斷,那麼函數應該返回一個 "成功" 布爾值。
+
+比如, ``add work`` 是一個命令,所以 add_work() 在成功時返回 0,在失敗時返回
+-EBUSY。類似的,因爲 ``PCI device present`` 是一個判斷,所以 pci_dev_present()
+在成功找到一個匹配的設備時應該返回 1,如果找不到時應該返回 0。
+
+所有 EXPORTed 函數都必須遵守這個慣例,所有的公共函數也都應該如此。私有
+(static) 函數不需要如此,但是我們也推薦這樣做。
+
+返回值是實際計算結果而不是計算是否成功的標誌的函數不受此慣例的限制。一般的,
+他們通過返回一些正常值範圍之外的結果來表示出錯。典型的例子是返回指針的函數,
+他們使用 NULL 或者 ERR_PTR 機制來報告錯誤。
+
+
+17) 不要重新發明內核宏
+------------------------------
+
+頭文件 include/linux/kernel.h 包含了一些宏,你應該使用它們,而不要自己寫一些
+它們的變種。比如,如果你需要計算一個數組的長度,使用這個宏
+
+.. code-block:: c
+
+ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+類似的,如果你要計算某結構體成員的大小,使用
+
+.. code-block:: c
+
+ #define sizeof_field(t, f) (sizeof(((t*)0)->f))
+
+還有可以做嚴格的類型檢查的 min() 和 max() 宏,如果你需要可以使用它們。你可以
+自己看看那個頭文件里還定義了什麼你可以拿來用的東西,如果有定義的話,你就不應
+在你的代碼里自己重新定義。
+
+
+18) 編輯器模式行和其他需要羅嗦的事情
+--------------------------------------------------
+
+有一些編輯器可以解釋嵌入在源文件里的由一些特殊標記標明的配置信息。比如,emacs
+能夠解釋被標記成這樣的行:
+
+.. code-block:: c
+
+ -*- mode: c -*-
+
+或者這樣的:
+
+.. code-block:: c
+
+ /*
+ Local Variables:
+ compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+ End:
+ */
+
+Vim 能夠解釋這樣的標記:
+
+.. code-block:: c
+
+ /* vim:set sw=8 noet */
+
+不要在原始碼中包含任何這樣的內容。每個人都有他自己的編輯器配置,你的源文件不
+應該覆蓋別人的配置。這包括有關縮進和模式配置的標記。人們可以使用他們自己定製
+的模式,或者使用其他可以產生正確的縮進的巧妙方法。
+
+
+19) 內聯彙編
+------------------------------
+
+在特定架構的代碼中,你可能需要內聯彙編與 CPU 和平台相關功能連接。需要這麼做時
+就不要猶豫。然而,當 C 可以完成工作時,不要平白無故地使用內聯彙編。在可能的情
+況下,你可以並且應該用 C 和硬體溝通。
+
+請考慮去寫捆綁通用位元 (wrap common bits) 的內聯彙編的簡單輔助函數,別去重複
+地寫下只有細微差異內聯彙編。記住內聯彙編可以使用 C 參數。
+
+大型,有一定複雜度的彙編函數應該放在 .S 文件內,用相應的 C 原型定義在 C 頭文
+件中。彙編函數的 C 原型應該使用 ``asmlinkage`` 。
+
+你可能需要把彙編語句標記爲 volatile,用來阻止 GCC 在沒發現任何副作用後就把它
+移除了。你不必總是這樣做,儘管,這不必要的舉動會限制優化。
+
+在寫一個包含多條指令的單個內聯彙編語句時,把每條指令用引號分割而且各占一行,
+除了最後一條指令外,在每個指令結尾加上 \n\t,讓彙編輸出時可以正確地縮進下一條
+指令:
+
+.. code-block:: c
+
+ asm ("magic %reg1, #42\n\t"
+ "more_magic %reg2, %reg3"
+ : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+20) 條件編譯
+------------------------------
+
+只要可能,就不要在 .c 文件裡面使用預處理條件 (#if, #ifdef);這樣做讓代碼更難
+閱讀並且更難去跟蹤邏輯。替代方案是,在頭文件中用預處理條件提供給那些 .c 文件
+使用,再給 #else 提供一個空樁 (no-op stub) 版本,然後在 .c 文件內無條件地調用
+那些 (定義在頭文件內的) 函數。這樣做,編譯器會避免爲樁函數 (stub) 的調用生成
+任何代碼,產生的結果是相同的,但邏輯將更加清晰。
+
+最好傾向於編譯整個函數,而不是函數的一部分或表達式的一部分。與其放一個 ifdef
+在表達式內,不如分解出部分或全部表達式,放進一個單獨的輔助函數,並應用預處理
+條件到這個輔助函數內。
+
+如果你有一個在特定配置中,可能變成未使用的函數或變量,編譯器會警告它定義了但
+未使用,把它標記爲 __maybe_unused 而不是將它包含在一個預處理條件中。(然而,如
+果一個函數或變量總是未使用,就直接刪除它。)
+
+在代碼中,儘可能地使用 IS_ENABLED 宏來轉化某個 Kconfig 標記爲 C 的布爾
+表達式,並在一般的 C 條件中使用它:
+
+.. code-block:: c
+
+ if (IS_ENABLED(CONFIG_SOMETHING)) {
+ ...
+ }
+
+編譯器會做常量摺疊,然後就像使用 #ifdef 那樣去包含或排除代碼塊,所以這不會帶
+來任何運行時開銷。然而,這種方法依舊允許 C 編譯器查看塊內的代碼,並檢查它的正
+確性 (語法,類型,符號引用,等等)。因此,如果條件不滿足,代碼塊內的引用符號就
+不存在時,你還是必須去用 #ifdef。
+
+在任何有意義的 #if 或 #ifdef 塊的末尾 (超過幾行的),在 #endif 同一行的後面寫下
+註解,注釋這個條件表達式。例如:
+
+.. code-block:: c
+
+ #ifdef CONFIG_SOMETHING
+ ...
+ #endif /* CONFIG_SOMETHING */
+
+
+附錄 I) 參考
+-------------------
+
+The C Programming Language, 第二版
+作者:Brian W. Kernighan 和 Denni M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (軟皮), 0-13-110370-9 (硬皮).
+
+The Practice of Programming
+作者:Brian W. Kernighan 和 Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU 手冊 - 遵循 K&R 標準和此文本 - cpp, gcc, gcc internals and indent,
+都可以從 https://www.gnu.org/manual/ 找到
+
+WG14 是 C 語言的國際標準化工作組,URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst,作者 greg@kroah.com 發表於 OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
+
diff --git a/Documentation/translations/zh_TW/process/development-process.rst b/Documentation/translations/zh_TW/process/development-process.rst
new file mode 100644
index 000000000000..45e6385647cd
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/development-process.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/development-process.rst <development_process_main>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_main:
+
+內核開發過程指南
+================
+
+內容:
+
+.. toctree::
+ :numbered:
+ :maxdepth: 2
+
+ 1.Intro
+ 2.Process
+ 3.Early-stage
+ 4.Coding
+ 5.Posting
+ 6.Followthrough
+ 7.AdvancedTopics
+ 8.Conclusion
+
+本文檔的目的是幫助開發人員(及其經理)以最小的挫折感與開發社區合作。它試圖記錄這個社區如何以一種不熟悉Linux內核開發(或者實際上是自由軟體開發)的人可以訪問的方式工作。雖然這裡有一些技術資料,但這是一個面向過程的討論,不需要深入了解內核編程就可以理解。
+
diff --git a/Documentation/translations/zh_TW/process/email-clients.rst b/Documentation/translations/zh_TW/process/email-clients.rst
new file mode 100644
index 000000000000..4ba543d06f3b
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/email-clients.rst
@@ -0,0 +1,252 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_email_clients:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
+
+譯者::
+
+ 中文版維護者: 賈威威 Harry Wei <harryxiyou@gmail.com>
+ 中文版翻譯者: 賈威威 Harry Wei <harryxiyou@gmail.com>
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+ 中文版校譯者: Yinglin Luan <synmyth@gmail.com>
+ Xiaochen Wang <wangxiaochen0@gmail.com>
+ yaxinsn <yaxinsn@163.com>
+ Hu Haowen <src.res@email.cn>
+
+Linux郵件客戶端配置信息
+=======================
+
+Git
+---
+
+現在大多數開發人員使用 ``git send-email`` 而不是常規的電子郵件客戶端。這方面
+的手冊非常好。在接收端,維護人員使用 ``git am`` 加載補丁。
+
+如果你是 ``git`` 新手,那麼把你的第一個補丁發送給你自己。將其保存爲包含所有
+標題的原始文本。運行 ``git am raw_email.txt`` ,然後使用 ``git log`` 查看更
+改日誌。如果工作正常,再將補丁發送到相應的郵件列表。
+
+
+普通配置
+--------
+Linux內核補丁是通過郵件被提交的,最好把補丁作爲郵件體的內嵌文本。有些維護者
+接收附件,但是附件的內容格式應該是"text/plain"。然而,附件一般是不贊成的,
+因爲這會使補丁的引用部分在評論過程中變的很困難。
+
+用來發送Linux內核補丁的郵件客戶端在發送補丁時應該處於文本的原始狀態。例如,
+他們不能改變或者刪除制表符或者空格,甚至是在每一行的開頭或者結尾。
+
+不要通過"format=flowed"模式發送補丁。這樣會引起不可預期以及有害的斷行。
+
+不要讓你的郵件客戶端進行自動換行。這樣也會破壞你的補丁。
+
+郵件客戶端不能改變文本的字符集編碼方式。要發送的補丁只能是ASCII或者UTF-8編碼方式,
+如果你使用UTF-8編碼方式發送郵件,那麼你將會避免一些可能發生的字符集問題。
+
+郵件客戶端應該形成並且保持 References: 或者 In-Reply-To: 標題,那麼
+郵件話題就不會中斷。
+
+複製粘帖(或者剪貼粘帖)通常不能用於補丁,因爲制表符會轉換爲空格。使用xclipboard, xclip
+或者xcutsel也許可以,但是最好測試一下或者避免使用複製粘帖。
+
+不要在使用PGP/GPG署名的郵件中包含補丁。這樣會使得很多腳本不能讀取和適用於你的補丁。
+(這個問題應該是可以修復的)
+
+在給內核郵件列表發送補丁之前,給自己發送一個補丁是個不錯的主意,保存接收到的
+郵件,將補丁用'patch'命令打上,如果成功了,再給內核郵件列表發送。
+
+
+一些郵件客戶端提示
+------------------
+這裡給出一些詳細的MUA配置提示,可以用於給Linux內核發送補丁。這些並不意味是
+所有的軟體包配置總結。
+
+說明:
+TUI = 以文本爲基礎的用戶接口
+GUI = 圖形界面用戶接口
+
+Alpine (TUI)
+~~~~~~~~~~~~
+
+配置選項:
+在"Sending Preferences"部分:
+
+- "Do Not Send Flowed Text"必須開啓
+- "Strip Whitespace Before Sending"必須關閉
+
+當寫郵件時,光標應該放在補丁會出現的地方,然後按下CTRL-R組合鍵,使指定的
+補丁文件嵌入到郵件中。
+
+Evolution (GUI)
+~~~~~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁
+
+當選擇郵件選項:Preformat
+ 從Format->Heading->Preformatted (Ctrl-7)或者工具欄
+
+然後使用:
+ Insert->Text File... (Alt-n x)插入補丁文件。
+
+你還可以"diff -Nru old.c new.c | xclip",選擇Preformat,然後使用中間鍵進行粘帖。
+
+Kmail (GUI)
+~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁。
+
+默認設置不爲HTML格式是合適的;不要啓用它。
+
+當書寫一封郵件的時候,在選項下面不要選擇自動換行。唯一的缺點就是你在郵件中輸入的任何文本
+都不會被自動換行,因此你必須在發送補丁之前手動換行。最簡單的方法就是啓用自動換行來書寫郵件,
+然後把它保存爲草稿。一旦你在草稿中再次打開它,它已經全部自動換行了,那麼你的郵件雖然沒有
+選擇自動換行,但是還不會失去已有的自動換行。
+
+在郵件的底部,插入補丁之前,放上常用的補丁定界符:三個連字號(---)。
+
+然後在"Message"菜單條目,選擇插入文件,接著選取你的補丁文件。還有一個額外的選項,你可以
+通過它配置你的郵件建立工具欄菜單,還可以帶上"insert file"圖標。
+
+你可以安全地通過GPG標記附件,但是內嵌補丁最好不要使用GPG標記它們。作爲內嵌文本的簽發補丁,
+當從GPG中提取7位編碼時會使他們變的更加複雜。
+
+如果你非要以附件的形式發送補丁,那麼就右鍵點擊附件,然後選中屬性,突出"Suggest automatic
+display",這樣內嵌附件更容易讓讀者看到。
+
+當你要保存將要發送的內嵌文本補丁,你可以從消息列表窗格選擇包含補丁的郵件,然後右擊選擇
+"save as"。你可以使用一個沒有更改的包含補丁的郵件,如果它是以正確的形式組成。當你正真在它
+自己的窗口之下察看,那時沒有選項可以保存郵件--已經有一個這樣的bug被匯報到了kmail的bugzilla
+並且希望這將會被處理。郵件是以只針對某個用戶可讀寫的權限被保存的,所以如果你想把郵件複製到其他地方,
+你不得不把他們的權限改爲組或者整體可讀。
+
+Lotus Notes (GUI)
+~~~~~~~~~~~~~~~~~
+
+不要使用它。
+
+Mutt (TUI)
+~~~~~~~~~~
+
+很多Linux開發人員使用mutt客戶端,所以證明它肯定工作的非常漂亮。
+
+Mutt不自帶編輯器,所以不管你使用什麼編輯器都不應該帶有自動斷行。大多數編輯器都帶有
+一個"insert file"選項,它可以通過不改變文件內容的方式插入文件。
+
+'vim'作爲mutt的編輯器:
+ set editor="vi"
+
+ 如果使用xclip,敲入以下命令
+ :set paste
+ 按中鍵之前或者shift-insert或者使用
+ :r filename
+
+如果想要把補丁作爲內嵌文本。
+(a)ttach工作的很好,不帶有"set paste"。
+
+你可以通過 ``git format-patch`` 生成補丁,然後用 Mutt發送它們::
+
+ $ mutt -H 0001-some-bug-fix.patch
+
+配置選項:
+它應該以默認設置的形式工作。
+然而,把"send_charset"設置爲"us-ascii::utf-8"也是一個不錯的主意。
+
+Mutt 是高度可配置的。 這裡是個使用mutt通過 Gmail 發送的補丁的最小配置::
+
+ # .muttrc
+ # ================ IMAP ====================
+ set imap_user = 'yourusername@gmail.com'
+ set imap_pass = 'yourpassword'
+ set spoolfile = imaps://imap.gmail.com/INBOX
+ set folder = imaps://imap.gmail.com/
+ set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+ set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+ set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+ # ================ SMTP ====================
+ set smtp_url = "smtp://username@smtp.gmail.com:587/"
+ set smtp_pass = $imap_pass
+ set ssl_force_tls = yes # Require encrypted connection
+
+ # ================ Composition ====================
+ set editor = `echo \$EDITOR`
+ set edit_headers = yes # See the headers when editing
+ set charset = UTF-8 # value of $LANG; also fallback for send_charset
+ # Sender, email address, and sign-off line must match
+ unset use_domain # because joe@localhost is just embarrassing
+ set realname = "YOUR NAME"
+ set from = "username@gmail.com"
+ set use_from = yes
+
+Mutt文檔含有更多信息:
+
+ http://dev.mutt.org/trac/wiki/UseCases/Gmail
+
+ http://dev.mutt.org/doc/manual.html
+
+Pine (TUI)
+~~~~~~~~~~
+
+Pine過去有一些空格刪減問題,但是這些現在應該都被修復了。
+
+如果可以,請使用alpine(pine的繼承者)
+
+配置選項:
+- 最近的版本需要消除流程文本
+- "no-strip-whitespace-before-send"選項也是需要的。
+
+
+Sylpheed (GUI)
+~~~~~~~~~~~~~~
+
+- 內嵌文本可以很好的工作(或者使用附件)。
+- 允許使用外部的編輯器。
+- 對於目錄較多時非常慢。
+- 如果通過non-SSL連接,無法使用TLS SMTP授權。
+- 在組成窗口中有一個很有用的ruler bar。
+- 給地址本中添加地址就不會正確的了解顯示名。
+
+Thunderbird (GUI)
+~~~~~~~~~~~~~~~~~
+
+默認情況下,thunderbird很容易損壞文本,但是還有一些方法可以強制它變得更好。
+
+- 在用戶帳號設置里,組成和尋址,不要選擇"Compose messages in HTML format"。
+
+- 編輯你的Thunderbird配置設置來使它不要拆行使用:user_pref("mailnews.wraplength", 0);
+
+- 編輯你的Thunderbird配置設置,使它不要使用"format=flowed"格式:user_pref("mailnews.
+ send_plaintext_flowed", false);
+
+- 你需要使Thunderbird變爲預先格式方式:
+ 如果默認情況下你書寫的是HTML格式,那不是很難。僅僅從標題欄的下拉框中選擇"Preformat"格式。
+ 如果默認情況下你書寫的是文本格式,你不得把它改爲HTML格式(僅僅作爲一次性的)來書寫新的消息,
+ 然後強制使它回到文本格式,否則它就會拆行。要實現它,在寫信的圖標上使用shift鍵來使它變爲HTML
+ 格式,然後標題欄的下拉框中選擇"Preformat"格式。
+
+- 允許使用外部的編輯器:
+ 針對Thunderbird打補丁最簡單的方法就是使用一個"external editor"擴展,然後使用你最喜歡的
+ $EDITOR來讀取或者合併補丁到文本中。要實現它,可以下載並且安裝這個擴展,然後添加一個使用它的
+ 按鍵View->Toolbars->Customize...最後當你書寫信息的時候僅僅點擊它就可以了。
+
+TkRat (GUI)
+~~~~~~~~~~~
+
+可以使用它。使用"Insert file..."或者外部的編輯器。
+
+Gmail (Web GUI)
+~~~~~~~~~~~~~~~
+
+不要使用它發送補丁。
+
+Gmail網頁客戶端自動地把制表符轉換爲空格。
+
+雖然制表符轉換爲空格問題可以被外部編輯器解決,同時它還會使用回車換行把每行拆分爲78個字符。
+
+另一個問題是Gmail還會把任何不是ASCII的字符的信息改爲base64編碼。它把東西變的像歐洲人的名字。
+
+ ###
+
diff --git a/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
new file mode 100644
index 000000000000..6c76fc96131a
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
@@ -0,0 +1,232 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/embargoed-hardware-issues.rst <embargoed_hardware_issues>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+被限制的硬體問題
+================
+
+範圍
+----
+
+導致安全問題的硬體問題與只影響Linux內核的純軟體錯誤是不同的安全錯誤類別。
+
+必須區別對待諸如熔毀(Meltdown)、Spectre、L1TF等硬體問題,因爲它們通常會影響
+所有作業系統(「OS」),因此需要在不同的OS供應商、發行版、硬體供應商和其他各方
+之間進行協調。對於某些問題,軟體緩解可能依賴於微碼或固件更新,這需要進一步的
+協調。
+
+.. _tw_Contact:
+
+接觸
+----
+
+Linux內核硬體安全小組獨立於普通的Linux內核安全小組。
+
+該小組只負責協調被限制的硬體安全問題。Linux內核中純軟體安全漏洞的報告不由該
+小組處理,報告者將被引導至常規Linux內核安全小組(:ref:`Documentation/admin-guide/
+<securitybugs>`)聯繫。
+
+可以通過電子郵件 <hardware-security@kernel.org> 與小組聯繫。這是一份私密的安全
+官名單,他們將幫助您根據我們的文檔化流程協調問題。
+
+郵件列表是加密的,發送到列表的電子郵件可以通過PGP或S/MIME加密,並且必須使用報告
+者的PGP密鑰或S/MIME證書籤名。該列表的PGP密鑰和S/MIME證書可從
+https://www.kernel.org/.... 獲得。
+
+雖然硬體安全問題通常由受影響的硬體供應商處理,但我們歡迎發現潛在硬體缺陷的研究
+人員或個人與我們聯繫。
+
+硬體安全官
+^^^^^^^^^^
+
+目前的硬體安全官小組:
+
+ - Linus Torvalds(Linux基金會院士)
+ - Greg Kroah Hartman(Linux基金會院士)
+ - Thomas Gleixner(Linux基金會院士)
+
+郵件列表的操作
+^^^^^^^^^^^^^^
+
+處理流程中使用的加密郵件列表託管在Linux Foundation的IT基礎設施上。通過提供這項
+服務,Linux基金會的IT基礎設施安全總監在技術上有能力訪問被限制的信息,但根據他
+的僱傭合同,他必須保密。Linux基金會的IT基礎設施安全總監還負責 kernel.org 基礎
+設施。
+
+Linux基金會目前的IT基礎設施安全總監是 Konstantin Ryabitsev。
+
+保密協議
+--------
+
+Linux內核硬體安全小組不是正式的機構,因此無法簽訂任何保密協議。核心社區意識到
+這些問題的敏感性,並提供了一份諒解備忘錄。
+
+諒解備忘錄
+----------
+
+Linux內核社區深刻理解在不同作業系統供應商、發行商、硬體供應商和其他各方之間
+進行協調時,保持硬體安全問題處於限制狀態的要求。
+
+Linux內核社區在過去已經成功地處理了硬體安全問題,並且有必要的機制允許在限制
+限制下進行符合社區的開發。
+
+Linux內核社區有一個專門的硬體安全小組負責初始聯繫,並監督在限制規則下處理
+此類問題的過程。
+
+硬體安全小組確定開發人員(領域專家),他們將組成特定問題的初始響應小組。最初
+的響應小組可以引入更多的開發人員(領域專家)以最佳的技術方式解決這個問題。
+
+所有相關開發商承諾遵守限制規定,並對收到的信息保密。違反承諾將導致立即從當前
+問題中排除,並從所有相關郵件列表中刪除。此外,硬體安全小組還將把違反者排除在
+未來的問題之外。這一後果的影響在我們社區是一種非常有效的威懾。如果發生違規
+情況,硬體安全小組將立即通知相關方。如果您或任何人發現潛在的違規行爲,請立即
+向硬體安全人員報告。
+
+流程
+^^^^
+
+由於Linux內核開發的全球分布式特性,面對面的會議幾乎不可能解決硬體安全問題。
+由於時區和其他因素,電話會議很難協調,只能在絕對必要時使用。加密電子郵件已被
+證明是解決此類問題的最有效和最安全的通信方法。
+
+開始披露
+""""""""
+
+披露內容首先通過電子郵件聯繫Linux內核硬體安全小組。此初始聯繫人應包含問題的
+描述和任何已知受影響硬體的列表。如果您的組織製造或分發受影響的硬體,我們建議
+您也考慮哪些其他硬體可能會受到影響。
+
+硬體安全小組將提供一個特定於事件的加密郵件列表,用於與報告者進行初步討論、
+進一步披露和協調。
+
+硬體安全小組將向披露方提供一份開發人員(領域專家)名單,在與開發人員確認他們
+將遵守本諒解備忘錄和文件化流程後,應首先告知開發人員有關該問題的信息。這些開發
+人員組成初始響應小組,並在初始接觸後負責處理問題。硬體安全小組支持響應小組,
+但不一定參與緩解開發過程。
+
+雖然個別開發人員可能通過其僱主受到保密協議的保護,但他們不能以Linux內核開發
+人員的身份簽訂個別保密協議。但是,他們將同意遵守這一書面程序和諒解備忘錄。
+
+披露方應提供已經或應該被告知該問題的所有其他實體的聯繫人名單。這有幾個目的:
+
+ - 披露的實體列表允許跨行業通信,例如其他作業系統供應商、硬體供應商等。
+
+ - 可聯繫已披露的實體,指定應參與緩解措施開發的專家。
+
+ - 如果需要處理某一問題的專家受僱於某一上市實體或某一上市實體的成員,則響應
+ 小組可要求該實體披露該專家。這確保專家也是實體反應小組的一部分。
+
+披露
+""""
+
+披露方通過特定的加密郵件列表向初始響應小組提供詳細信息。
+
+根據我們的經驗,這些問題的技術文檔通常是一個足夠的起點,最好通過電子郵件進行
+進一步的技術澄清。
+
+緩解開發
+""""""""
+
+初始響應小組設置加密郵件列表,或在適當的情況下重新修改現有郵件列表。
+
+使用郵件列表接近於正常的Linux開發過程,並且在過去已經成功地用於爲各種硬體安全
+問題開發緩解措施。
+
+郵件列表的操作方式與正常的Linux開發相同。發布、討論和審查修補程序,如果同意,
+則應用於非公共git存儲庫,參與開發人員只能通過安全連接訪問該存儲庫。存儲庫包含
+針對主線內核的主開發分支,並根據需要爲穩定的內核版本提供向後移植分支。
+
+最初的響應小組將根據需要從Linux內核開發人員社區中確定更多的專家。引進專家可以
+在開發過程中的任何時候發生,需要及時處理。
+
+如果專家受僱於披露方提供的披露清單上的實體或其成員,則相關實體將要求其參與。
+
+否則,披露方將被告知專家參與的情況。諒解備忘錄涵蓋了專家,要求披露方確認參與。
+如果披露方有令人信服的理由提出異議,則必須在五個工作日內提出異議,並立即與事件
+小組解決。如果披露方在五個工作日內未作出回應,則視爲默許。
+
+在確認或解決異議後,專家由事件小組披露,並進入開發過程。
+
+協調發布
+""""""""
+
+有關各方將協商限制結束的日期和時間。此時,準備好的緩解措施集成到相關的內核樹中
+並發布。
+
+雖然我們理解硬體安全問題需要協調限制時間,但限制時間應限制在所有有關各方制定、
+測試和準備緩解措施所需的最短時間內。人爲地延長限制時間以滿足會議討論日期或其他
+非技術原因,會給相關的開發人員和響應小組帶來了更多的工作和負擔,因爲補丁需要
+保持最新,以便跟蹤正在進行的上游內核開發,這可能會造成衝突的更改。
+
+CVE分配
+"""""""
+
+硬體安全小組和初始響應小組都不分配CVE,開發過程也不需要CVE。如果CVE是由披露方
+提供的,則可用於文檔中。
+
+流程專使
+--------
+
+爲了協助這一進程,我們在各組織設立了專使,他們可以回答有關報告流程和進一步處理
+的問題或提供指導。專使不參與特定問題的披露,除非響應小組或相關披露方提出要求。
+現任專使名單:
+
+ ============= ========================================================
+ ARM
+ AMD Tom Lendacky <tom.lendacky@amd.com>
+ IBM
+ Intel Tony Luck <tony.luck@intel.com>
+ Qualcomm Trilok Soni <tsoni@codeaurora.org>
+
+ Microsoft Sasha Levin <sashal@kernel.org>
+ VMware
+ Xen Andrew Cooper <andrew.cooper3@citrix.com>
+
+ Canonical John Johansen <john.johansen@canonical.com>
+ Debian Ben Hutchings <ben@decadent.org.uk>
+ Oracle Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+ Red Hat Josh Poimboeuf <jpoimboe@redhat.com>
+ SUSE Jiri Kosina <jkosina@suse.cz>
+
+ Amazon
+ Google Kees Cook <keescook@chromium.org>
+ ============= ========================================================
+
+如果要將您的組織添加到專使名單中,請與硬體安全小組聯繫。被提名的專使必須完全
+理解和支持我們的過程,並且在Linux內核社區中很容易聯繫。
+
+加密郵件列表
+------------
+
+我們使用加密郵件列表進行通信。這些列表的工作原理是,發送到列表的電子郵件使用
+列表的PGP密鑰或列表的/MIME證書進行加密。郵件列表軟體對電子郵件進行解密,並
+使用訂閱者的PGP密鑰或S/MIME證書爲每個訂閱者分別對其進行重新加密。有關郵件列表
+軟體和用於確保列表安全和數據保護的設置的詳細信息,請訪問:
+https://www.kernel.org/....
+
+關鍵點
+^^^^^^
+
+初次接觸見 :ref:`tw_Contact`. 對於特定於事件的郵件列表,密鑰和S/MIME證書通過
+特定列表發送的電子郵件傳遞給訂閱者。
+
+訂閱事件特定列表
+^^^^^^^^^^^^^^^^
+
+訂閱由響應小組處理。希望參與通信的披露方將潛在訂戶的列表發送給響應組,以便
+響應組可以驗證訂閱請求。
+
+每個訂戶都需要通過電子郵件向響應小組發送訂閱請求。電子郵件必須使用訂閱伺服器
+的PGP密鑰或S/MIME證書籤名。如果使用PGP密鑰,則必須從公鑰伺服器獲得該密鑰,
+並且理想情況下該密鑰連接到Linux內核的PGP信任網。另請參見:
+https://www.kernel.org/signature.html.
+
+響應小組驗證訂閱者,並將訂閱者添加到列表中。訂閱後,訂閱者將收到來自郵件列表
+的電子郵件,該郵件列表使用列表的PGP密鑰或列表的/MIME證書籤名。訂閱者的電子郵件
+客戶端可以從簽名中提取PGP密鑰或S/MIME證書,以便訂閱者可以向列表發送加密電子
+郵件。
+
diff --git a/Documentation/translations/zh_TW/process/howto.rst b/Documentation/translations/zh_TW/process/howto.rst
new file mode 100644
index 000000000000..2043691b92e3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/howto.rst
@@ -0,0 +1,500 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_howto:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/howto.rst <process_howto>`
+
+譯者::
+
+ 英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+ 中文版維護者: 李陽 Li Yang <leoyang.li@nxp.com>
+ 中文版翻譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+ 中文版校譯者:
+ 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+ 陳琦 Maggie Chen <chenqi@beyondsoft.com>
+ 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+如何參與Linux內核開發
+=====================
+
+這是一篇將如何參與Linux內核開發的相關問題一網打盡的終極祕笈。它將指導你
+成爲一名Linux內核開發者,並且學會如何同Linux內核開發社區合作。它儘可能不
+包括任何關於內核編程的技術細節,但會給你指引一條獲得這些知識的正確途徑。
+
+如果這篇文章中的任何內容不再適用,請給文末列出的文件維護者發送補丁。
+
+
+入門
+----
+
+你想了解如何成爲一名Linux內核開發者?或者老闆吩咐你「給這個設備寫個Linux
+驅動程序」?這篇文章的目的就是教會你達成這些目標的全部訣竅,它將描述你需
+要經過的流程以及給出如何同內核社區合作的一些提示。它還將試圖解釋內核社區
+爲何這樣運作。
+
+Linux內核大部分是由C語言寫成的,一些體系結構相關的代碼用到了彙編語言。要
+參與內核開發,你必須精通C語言。除非你想爲某個架構開發底層代碼,否則你並
+不需要了解(任何體系結構的)彙編語言。下面列舉的書籍雖然不能替代紮實的C
+語言教育和多年的開發經驗,但如果需要的話,做爲參考還是不錯的:
+
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+ 《C程序設計語言(第2版·新版)》(徐寶文 李志 譯)[機械工業出版社]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+ 《實用C語言編程(第三版)》(郭大海 譯)[中國電力出版社]
+ - "C: A Reference Manual" by Harbison and Steele [Prentice Hall]
+ 《C語言參考手冊(原書第5版)》(邱仲潘 等譯)[機械工業出版社]
+
+Linux內核使用GNU C和GNU工具鏈開發。雖然它遵循ISO C89標準,但也用到了一些
+標準中沒有定義的擴展。內核是自給自足的C環境,不依賴於標準C庫的支持,所以
+並不支持C標準中的部分定義。比如long long類型的大數除法和浮點運算就不允許
+使用。有時候確實很難弄清楚內核對工具鏈的要求和它所使用的擴展,不幸的是目
+前還沒有明確的參考資料可以解釋它們。請查閱gcc信息頁(使用「info gcc」命令
+顯示)獲得一些這方面信息。
+
+請記住你是在學習怎麼和已經存在的開發社區打交道。它由一羣形形色色的人組成,
+他們對代碼、風格和過程有著很高的標準。這些標準是在長期實踐中總結出來的,
+適應於地理上分散的大型開發團隊。它們已經被很好得整理成檔,建議你在開發
+之前儘可能多的學習這些標準,而不要期望別人來適應你或者你公司的行爲方式。
+
+
+法律問題
+--------
+
+Linux內核原始碼都是在GPL(通用公共許可證)的保護下發布的。要了解這種許可
+的細節請查看原始碼主目錄下的COPYING文件。Linux內核許可準則和如何使用
+`SPDX <https://spdx.org/>` 標誌符說明在這個文件中
+:ref:`Documentation/translations/zh_TW/process/license-rules.rst <tw_kernel_licensing>`
+如果你對它還有更深入問題請聯繫律師,而不要在Linux內核郵件組上提問。因爲
+郵件組裡的人並不是律師,不要期望他們的話有法律效力。
+
+對於GPL的常見問題和解答,請訪問以下連結:
+ https://www.gnu.org/licenses/gpl-faq.html
+
+
+文檔
+----
+
+Linux內核代碼中包含有大量的文檔。這些文檔對於學習如何與內核社區互動有著
+不可估量的價值。當一個新的功能被加入內核,最好把解釋如何使用這個功能的文
+檔也放進內核。當內核的改動導致面向用戶空間的接口發生變化時,最好將相關信
+息或手冊頁(manpages)的補丁發到mtk.manpages@gmail.com,以向手冊頁(manpages)
+的維護者解釋這些變化。
+
+以下是內核代碼中需要閱讀的文檔:
+ :ref:`Documentation/admin-guide/README.rst <readme>`
+ 文件簡要介紹了Linux內核的背景,並且描述了如何配置和編譯內核。內核的
+ 新用戶應該從這裡開始。
+
+
+ :ref:`Documentation/process/changes.rst <changes>`
+ 文件給出了用來編譯和使用內核所需要的最小軟體包列表。
+
+ :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+ 描述Linux內核的代碼風格和理由。所有新代碼需要遵守這篇文檔中定義的規
+ 范。大多數維護者只會接收符合規定的補丁,很多人也只會幫忙檢查符合風格
+ 的代碼。
+
+ :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+ :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+ 這兩份文檔明確描述如何創建和發送補丁,其中包括(但不僅限於):
+ - 郵件內容
+ - 郵件格式
+ - 選擇收件人
+
+ 遵守這些規定並不能保證提交成功(因爲所有補丁需要通過嚴格的內容和風格
+ 審查),但是忽視他們幾乎就意味著失敗。
+
+ 其他關於如何正確地生成補丁的優秀文檔包括:
+ "The Perfect Patch"
+
+ https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+ "Linux kernel patch submission format"
+
+ https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
+
+ :ref:`Documentation/translations/zh_TW/process/stable-api-nonsense.rst <tw_stable_api_nonsense>`
+ 論證內核爲什麼特意不包括穩定的內核內部API,也就是說不包括像這樣的特
+ 性:
+
+ - 子系統中間層(爲了兼容性?)
+ - 在不同作業系統間易於移植的驅動程序
+ - 減緩(甚至阻止)內核代碼的快速變化
+
+ 這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
+ 統轉移到Linux的人來說也很重要。
+
+ :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+ 如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
+ 提醒其他內核開發者並幫助解決這個問題。
+
+ :ref:`Documentation/translations/zh_TW/process/management-style.rst <tw_managementstyle>`
+
+ 描述內核維護者的工作方法及其共有特點。這對於剛剛接觸內核開發(或者對
+ 它感到好奇)的人來說很重要,因爲它解釋了很多對於內核維護者獨特行爲的
+ 普遍誤解與迷惑。
+
+ :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+ 解釋了穩定版內核發布的規則,以及如何將改動放入這些版本的步驟。
+
+ :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+ 有助於內核開發的外部文檔列表。如果你在內核自帶的文檔中沒有找到你想找
+ 的內容,可以查看這些文檔。
+
+ :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+ 關於補丁是什麼以及如何將它打在不同內核開發分支上的好介紹
+
+內核還擁有大量從代碼自動生成或者從 ReStructuredText(ReST) 標記生成的文檔,
+比如這個文檔,它包含內核內部API的全面介紹以及如何妥善處理加鎖的規則。所有
+這些文檔都可以通過運行以下命令從內核代碼中生成爲PDF或HTML文檔::
+
+ make pdfdocs
+ make htmldocs
+
+ReST格式的文檔會生成在 Documentation/output. 目錄中。
+它們也可以用下列命令生成 LaTeX 和 ePub 格式文檔::
+
+ make latexdocs
+ make epubdocs
+
+如何成爲內核開發者
+------------------
+如果你對Linux內核開發一無所知,你應該訪問「Linux內核新手」計劃:
+
+ https://kernelnewbies.org
+
+它擁有一個可以問各種最基本的內核開發問題的郵件列表(在提問之前一定要記得
+查找已往的郵件,確認是否有人已經回答過相同的問題)。它還擁有一個可以獲得
+實時反饋的IRC聊天頻道,以及大量對於學習Linux內核開發相當有幫助的文檔。
+
+網站簡要介紹了原始碼組織結構、子系統劃分以及目前正在進行的項目(包括內核
+中的和單獨維護的)。它還提供了一些基本的幫助信息,比如如何編譯內核和打補
+丁。
+
+如果你想加入內核開發社區並協助完成一些任務,卻找不到從哪裡開始,可以訪問
+「Linux內核房管員」計劃:
+
+ https://kernelnewbies.org/KernelJanitors
+
+這是極佳的起點。它提供一個相對簡單的任務列表,列出內核代碼中需要被重新
+整理或者改正的地方。通過和負責這個計劃的開發者們一同工作,你會學到將補丁
+集成進內核的基本原理。如果還沒有決定下一步要做什麼的話,你還可能會得到方
+向性的指點。
+
+在真正動手修改內核代碼之前,理解要修改的代碼如何運作是必需的。要達到這個
+目的,沒什麼辦法比直接讀代碼更有效了(大多數花招都會有相應的注釋),而且
+一些特製的工具還可以提供幫助。例如,「Linux代碼交叉引用」項目就是一個值得
+特別推薦的幫助工具,它將原始碼顯示在有編目和索引的網頁上。其中一個更新及
+時的內核源碼庫,可以通過以下地址訪問:
+
+ https://elixir.bootlin.com/
+
+
+開發流程
+--------
+
+目前Linux內核開發流程包括幾個「主內核分支」和很多子系統相關的內核分支。這
+些分支包括:
+
+ - Linus 的內核源碼樹
+ - 多個主要版本的穩定版內核樹
+ - 子系統相關的內核樹
+ - linux-next 集成測試樹
+
+
+主線樹
+------
+主線樹是由Linus Torvalds 維護的。你可以在https://kernel.org 網站或者代碼
+庫中下找到它。它的開發遵循以下步驟:
+
+ - 每當一個新版本的內核被發布,爲期兩周的集成窗口將被打開。在這段時間裡
+ 維護者可以向Linus提交大段的修改,通常這些修改已經被放到-mm內核中幾個
+ 星期了。提交大量修改的首選方式是使用git工具(內核的代碼版本管理工具
+ ,更多的信息可以在 https://git-scm.com/ 獲取),不過使用普通補丁也是
+ 可以的。
+ - 兩個星期以後-rc1版本內核發布。之後只有不包含可能影響整個內核穩定性的
+ 新功能的補丁才可能被接受。請注意一個全新的驅動程序(或者文件系統)有
+ 可能在-rc1後被接受是因爲這樣的修改完全獨立,不會影響其他的代碼,所以
+ 沒有造成內核退步的風險。在-rc1以後也可以用git向Linus提交補丁,不過所
+ 有的補丁需要同時被發送到相應的公衆郵件列表以徵詢意見。
+ - 當Linus認爲當前的git源碼樹已經達到一個合理健全的狀態足以發布供人測試
+ 時,一個新的-rc版本就會被發布。計劃是每周都發布新的-rc版本。
+ - 這個過程一直持續下去直到內核被認爲達到足夠穩定的狀態,持續時間大概是
+ 6個星期。
+
+關於內核發布,值得一提的是Andrew Morton在linux-kernel郵件列表中如是說:
+ 「沒有人知道新內核何時會被發布,因爲發布是根據已知bug的情況來決定
+ 的,而不是根據一個事先制定好的時間表。」
+
+子系統特定樹
+------------
+
+各種內核子系統的維護者——以及許多內核子系統開發人員——在原始碼庫中公開了他們
+當前的開發狀態。這樣,其他人就可以看到內核的不同區域發生了什麼。在開發速度
+很快的領域,可能會要求開發人員將提交的內容建立在這樣的子系統內核樹上,這樣
+就避免了提交與其他已經進行的工作之間的衝突。
+
+這些存儲庫中的大多數都是Git樹,但是也有其他的scm在使用,或者補丁隊列被發布
+爲Quilt系列。這些子系統存儲庫的地址列在MAINTAINERS文件中。其中許多可以在
+https://git.kernel.org/上瀏覽。
+
+在將一個建議的補丁提交到這樣的子系統樹之前,需要對它進行審查,審查主要發生
+在郵件列表上(請參見下面相應的部分)。對於幾個內核子系統,這個審查過程是通
+過工具補丁跟蹤的。Patchwork提供了一個Web界面,顯示補丁發布、對補丁的任何評
+論或修訂,維護人員可以將補丁標記爲正在審查、接受或拒絕。大多數補丁網站都列
+在 https://patchwork.kernel.org/
+
+Linux-next 集成測試樹
+---------------------
+
+在將子系統樹的更新合併到主線樹之前,需要對它們進行集成測試。爲此,存在一個
+特殊的測試存儲庫,其中幾乎每天都會提取所有子系統樹:
+
+ https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+通過這種方式,Linux-next 對下一個合併階段將進入主線內核的內容給出了一個概要
+展望。非常歡冒險的測試者運行測試Linux-next。
+
+多個主要版本的穩定版內核樹
+-----------------------------------
+由3個數字組成的內核版本號說明此內核是-stable版本。它們包含內核的相對較小且
+至關重要的修補,這些修補針對安全性問題或者嚴重的內核退步。
+
+這種版本的內核適用於那些期望獲得最新的穩定版內核並且不想參與測試開發版或
+者實驗版的用戶。
+
+穩定版內核樹版本由「穩定版」小組(郵件地址<stable@vger.kernel.org>)維護,一般
+隔周發布新版本。
+
+內核源碼中的 :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+文件具體描述了可被穩定版內核接受的修改類型以及發布的流程。
+
+
+報告bug
+-------
+
+bugzilla.kernel.org是Linux內核開發者們用來跟蹤內核Bug的網站。我們鼓勵用
+戶在這個工具中報告找到的所有bug。如何使用內核bugzilla的細節請訪問:
+
+ http://test.kernel.org/bugzilla/faq.html
+
+內核源碼主目錄中的:ref:`admin-guide/reporting-bugs.rst <reportingbugs>`
+文件里有一個很好的模板。它指導用戶如何報告可能的內核bug以及需要提供哪些信息
+來幫助內核開發者們找到問題的根源。
+
+
+利用bug報告
+-----------
+
+練習內核開發技能的最好辦法就是修改其他人報告的bug。你不光可以幫助內核變
+得更加穩定,還可以學會如何解決實際問題從而提高自己的技能,並且讓其他開發
+者感受到你的存在。修改bug是贏得其他開發者讚譽的最好辦法,因爲並不是很多
+人都喜歡浪費時間去修改別人報告的bug。
+
+要嘗試修改已知的bug,請訪問 http://bugzilla.kernel.org 網址。
+
+
+郵件列表
+--------
+
+正如上面的文檔所描述,大多數的骨幹內核開發者都加入了Linux Kernel郵件列
+表。如何訂閱和退訂列表的細節可以在這裡找到:
+
+ http://vger.kernel.org/vger-lists.html#linux-kernel
+
+網上很多地方都有這個郵件列表的存檔(archive)。可以使用搜尋引擎來找到這些
+存檔。比如:
+
+ http://dir.gmane.org/gmane.linux.kernel
+
+在發信之前,我們強烈建議你先在存檔中搜索你想要討論的問題。很多已經被詳細
+討論過的問題只在郵件列表的存檔中可以找到。
+
+大多數內核子系統也有自己獨立的郵件列表來協調各自的開發工作。從
+MAINTAINERS文件中可以找到不同話題對應的郵件列表。
+
+很多郵件列表架設在kernel.org伺服器上。這些列表的信息可以在這裡找到:
+
+ http://vger.kernel.org/vger-lists.html
+
+在使用這些郵件列表時,請記住保持良好的行爲習慣。下面的連結提供了與這些列
+表(或任何其它郵件列表)交流的一些簡單規則,雖然內容有點濫竽充數。
+
+ http://www.albion.com/netiquette/
+
+當有很多人回覆你的郵件時,郵件的抄送列表會變得很長。請不要將任何人從抄送
+列表中刪除,除非你有足夠的理由這麼做。也不要只回復到郵件列表。請習慣於同
+一封郵件接收兩次(一封來自發送者一封來自郵件列表),而不要試圖通過添加一
+些奇特的郵件頭來解決這個問題,人們不會喜歡的。
+
+記住保留你所回復內容的上下文和源頭。在你回覆郵件的頂部保留「某某某說到……」
+這幾行。將你的評論加在被引用的段落之間而不要放在郵件的頂部。
+
+如果你在郵件中附帶補丁,請確認它們是可以直接閱讀的純文本(如
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中所述)。內核開發者們不希望遇到附件或者被壓縮了的補丁。只有這樣才能
+保證他們可以直接評論你的每行代碼。請確保你使用的郵件發送程序不會修改空格
+和制表符。一個防範性的測試方法是先將郵件發送給自己,然後自己嘗試是否可以
+順利地打上收到的補丁。如果測試不成功,請調整或者更換你的郵件發送程序直到
+它正確工作爲止。
+
+總而言之,請尊重其他的郵件列表訂閱者。
+
+
+同內核社區合作
+----------------
+
+內核社區的目標就是提供盡善盡美的內核。所以當你提交補丁期望被接受進內核的
+時候,它的技術價值以及其他方面都將被評審。那麼你可能會得到什麼呢?
+
+ - 批評
+ - 評論
+ - 要求修改
+ - 要求證明修改的必要性
+ - 沉默
+
+要記住,這些是把補丁放進內核的正常情況。你必須學會聽取對補丁的批評和評論,
+從技術層面評估它們,然後要麼重寫你的補丁要麼簡明扼要地論證修改是不必要
+的。如果你發的郵件沒有得到任何回應,請過幾天後再試一次,因爲有時信件會湮
+沒在茫茫信海中。
+
+你不應該做的事情:
+
+ - 期望自己的補丁不受任何質疑就直接被接受
+ - 翻臉
+ - 忽略別人的評論
+ - 沒有按照別人的要求做任何修改就重新提交
+
+在一個努力追尋最好技術方案的社區里,對於一個補丁有多少好處總會有不同的見
+解。你必須要抱著合作的態度,願意改變自己的觀點來適應內核的風格。或者至少
+願意去證明你的想法是有價值的。記住,犯錯誤是允許的,只要你願意朝著正確的
+方案去努力。
+
+如果你的第一個補丁換來的是一堆修改建議,這是很正常的。這並不代表你的補丁
+不會被接受,也不意味著有人和你作對。你只需要改正所有提出的問題然後重新發
+送你的補丁。
+
+內核社區和公司文化的差異
+------------------------
+
+內核社區的工作模式同大多數傳統公司開發隊伍的工作模式並不相同。下面這些例
+子,可以幫助你避免某些可能發生問題:
+用這些話介紹你的修改提案會有好處:
+
+ - 它同時解決了多個問題
+ - 它刪除了2000行代碼
+ - 這是補丁,它已經解釋了我想要說明的
+ - 我在5種不同的體系結構上測試過它……
+ - 這是一系列小補丁用來……
+ - 這個修改提高了普通機器的性能……
+
+應該避免如下的說法:
+
+ - 我們在AIX/ptx/Solaris就是這麼做的,所以這麼做肯定是好的……
+ - 我做這行已經20年了,所以……
+ - 爲了我們公司賺錢考慮必須這麼做
+ - 這是我們的企業產品線所需要的
+ - 這裡是描述我觀點的1000頁設計文檔
+ - 這是一個5000行的補丁用來……
+ - 我重寫了現在亂七八糟的代碼,這就是……
+ - 我被規定了最後期限,所以這個補丁需要立刻被接受
+
+另外一個內核社區與大部分傳統公司的軟體開發隊伍不同的地方是無法面對面地交
+流。使用電子郵件和IRC聊天工具做爲主要溝通工具的一個好處是性別和種族歧視
+將會更少。Linux內核的工作環境更能接受婦女和少數族羣,因爲每個人在別人眼
+里只是一個郵件地址。國際化也幫助了公平的實現,因爲你無法通過姓名來判斷人
+的性別。男人有可能叫李麗,女人也有可能叫王剛。大多數在Linux內核上工作過
+並表達過看法的女性對在linux上工作的經歷都給出了正面的評價。
+
+對於一些不習慣使用英語的人來說,語言可能是一個引起問題的障礙。在郵件列表
+中要正確地表達想法必需良好地掌握語言,所以建議你在發送郵件之前最好檢查一
+下英文寫得是否正確。
+
+
+拆分修改
+--------
+
+Linux內核社區並不喜歡一下接收大段的代碼。修改需要被恰當地介紹、討論並且
+拆分成獨立的小段。這幾乎完全和公司中的習慣背道而馳。你的想法應該在開發最
+開始的階段就讓大家知道,這樣你就可以及時獲得對你正在進行的開發的反饋。這
+樣也會讓社區覺得你是在和他們協作,而不是僅僅把他們當作傾銷新功能的對象。
+無論如何,你不要一次性地向郵件列表發送50封信,你的補丁序列應該永遠用不到
+這麼多。
+
+將補丁拆開的原因如下:
+
+1) 小的補丁更有可能被接受,因爲它們不需要太多的時間和精力去驗證其正確性。
+ 一個5行的補丁,可能在維護者看了一眼以後就會被接受。而500行的補丁則
+ 需要數個小時來審查其正確性(所需時間隨補丁大小增加大約呈指數級增長)。
+
+ 當出了問題的時候,小的補丁也會讓調試變得非常容易。一個一個補丁地回溯
+ 將會比仔細剖析一個被打上的大補丁(這個補丁破壞了其他東西)容易得多。
+
+2)不光發送小的補丁很重要,在提交之前重新編排、化簡(或者僅僅重新排列)
+ 補丁也是很重要的。
+
+這裡有內核開發者Al Viro打的一個比方:
+ 「想像一個老師正在給學生批改數學作業。老師並不希望看到學生爲了得
+ 到正確解法所進行的嘗試和產生的錯誤。他希望看到的是最乾淨最優雅的
+ 解答。好學生了解這點,絕不會把最終解決之前的中間方案提交上去。」
+
+ 內核開發也是這樣。維護者和評審者不希望看到一個人在解決問題時的思
+ 考過程。他們只希望看到簡單和優雅的解決方案。
+
+直接給出一流的解決方案,和社區一起協作討論尚未完成的工作,這兩者之間似乎
+很難找到一個平衡點。所以最好儘早開始收集有利於你進行改進的反饋;同時也要
+保證修改分成很多小塊,這樣在整個項目都準備好被包含進內核之前,其中的一部
+分可能會先被接收。
+
+必須了解這樣做是不可接受的:試圖將未完成的工作提交進內核,然後再找時間修
+復。
+
+
+證明修改的必要性
+----------------
+除了將補丁拆成小塊,很重要的一點是讓Linux社區了解他們爲什麼需要這樣修改。
+你必須證明新功能是有人需要的並且是有用的。
+
+
+記錄修改
+--------
+
+當你發送補丁的時候,需要特別留意郵件正文的內容。因爲這裡的信息將會做爲補
+丁的修改記錄(ChangeLog),會被一直保留以備大家查閱。它需要完全地描述補丁,
+包括:
+
+ - 爲什麼需要這個修改
+ - 補丁的總體設計
+ - 實現細節
+ - 測試結果
+
+想了解它具體應該看起來像什麼,請查閱以下文檔中的「ChangeLog」章節:
+ 「The Perfect Patch」
+ https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+這些事情有時候做起來很難。要在任何方面都做到完美可能需要好幾年時間。這是
+一個持續提高的過程,它需要大量的耐心和決心。只要不放棄,你一定可以做到。
+很多人已經做到了,而他們都曾經和現在的你站在同樣的起點上。
+
+
+感謝
+----
+感謝Paolo Ciarrocchi允許「開發流程」部分基於他所寫的文章
+(http://www.kerneltravel.net/newbie/2.6-development_process),感謝Randy
+Dunlap和Gerrit Huizenga完善了應該說和不該說的列表。感謝Pat Mochel, Hanna
+Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer,
+Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian
+Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael
+Kerrisk和Alex Shepard的評審、建議和貢獻。沒有他們的幫助,這篇文檔是不可
+能完成的。
+
+
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/index.rst b/Documentation/translations/zh_TW/process/index.rst
new file mode 100644
index 000000000000..ec7ad14bfd13
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/index.rst
@@ -0,0 +1,67 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. raw:: latex
+
+ \renewcommand\thesection*
+ \renewcommand\thesubsection*
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/index.rst <process_index>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+.. _tw_process_index:
+
+與Linux 內核社區一起工作
+========================
+
+你想成爲Linux內核開發人員嗎?歡迎之至!在學習許多關於內核的技術知識的同時,
+了解我們社區的工作方式也很重要。閱讀這些文檔可以讓您以更輕鬆的、麻煩更少的
+方式將更改合併到內核。
+
+以下是每位開發人員都應閱讀的基本指南:
+
+.. toctree::
+ :maxdepth: 1
+
+ howto
+ code-of-conduct
+ code-of-conduct-interpretation
+ submitting-patches
+ programming-language
+ coding-style
+ development-process
+ email-clients
+ license-rules
+ kernel-enforcement-statement
+ kernel-driver-statement
+
+其它大多數開發人員感興趣的社區指南:
+
+
+.. toctree::
+ :maxdepth: 1
+
+ submitting-drivers
+ submit-checklist
+ stable-api-nonsense
+ stable-kernel-rules
+ management-style
+ embargoed-hardware-issues
+
+這些是一些總體性技術指南,由於不大好分類而放在這裡:
+
+.. toctree::
+ :maxdepth: 1
+
+ magic-number
+ volatile-considered-harmful
+
+.. only:: subproject and html
+
+ 目錄
+ ====
+
+ * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/process/kernel-driver-statement.rst b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
new file mode 100644
index 000000000000..8f225379b12c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
@@ -0,0 +1,203 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _zh_process_statement_driver:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-driver-statement.rst <process_statement_driver>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+內核驅動聲明
+------------
+
+關於Linux內核模塊的立場聲明
+===========================
+
+我們,以下署名的Linux內核開發人員,認爲任何封閉源Linux內核模塊或驅動程序都是
+有害的和不可取的。我們已經一再發現它們對Linux用戶,企業和更大的Linux生態系統
+有害。這樣的模塊否定了Linux開發模型的開放性,穩定性,靈活性和可維護性,並使
+他們的用戶無法使用Linux社區的專業知識。提供閉源內核模塊的供應商迫使其客戶
+放棄Linux的主要優勢或選擇新的供應商。因此,爲了充分利用開源所提供的成本節省和
+共享支持優勢,我們敦促供應商採取措施,以開源內核代碼在Linux上爲其客戶提供支持。
+
+我們只爲自己說話,而不是我們今天可能會爲之工作,過去或將來會爲之工作的任何公司。
+
+ - Dave Airlie
+ - Nick Andrew
+ - Jens Axboe
+ - Ralf Baechle
+ - Felipe Balbi
+ - Ohad Ben-Cohen
+ - Muli Ben-Yehuda
+ - Jiri Benc
+ - Arnd Bergmann
+ - Thomas Bogendoerfer
+ - Vitaly Bordug
+ - James Bottomley
+ - Josh Boyer
+ - Neil Brown
+ - Mark Brown
+ - David Brownell
+ - Michael Buesch
+ - Franck Bui-Huu
+ - Adrian Bunk
+ - François Cami
+ - Ralph Campbell
+ - Luiz Fernando N. Capitulino
+ - Mauro Carvalho Chehab
+ - Denis Cheng
+ - Jonathan Corbet
+ - Glauber Costa
+ - Alan Cox
+ - Magnus Damm
+ - Ahmed S. Darwish
+ - Robert P. J. Day
+ - Hans de Goede
+ - Arnaldo Carvalho de Melo
+ - Helge Deller
+ - Jean Delvare
+ - Mathieu Desnoyers
+ - Sven-Thorsten Dietrich
+ - Alexey Dobriyan
+ - Daniel Drake
+ - Alex Dubov
+ - Randy Dunlap
+ - Michael Ellerman
+ - Pekka Enberg
+ - Jan Engelhardt
+ - Mark Fasheh
+ - J. Bruce Fields
+ - Larry Finger
+ - Jeremy Fitzhardinge
+ - Mike Frysinger
+ - Kumar Gala
+ - Robin Getz
+ - Liam Girdwood
+ - Jan-Benedict Glaw
+ - Thomas Gleixner
+ - Brice Goglin
+ - Cyrill Gorcunov
+ - Andy Gospodarek
+ - Thomas Graf
+ - Krzysztof Halasa
+ - Harvey Harrison
+ - Stephen Hemminger
+ - Michael Hennerich
+ - Tejun Heo
+ - Benjamin Herrenschmidt
+ - Kristian Høgsberg
+ - Henrique de Moraes Holschuh
+ - Marcel Holtmann
+ - Mike Isely
+ - Takashi Iwai
+ - Olof Johansson
+ - Dave Jones
+ - Jesper Juhl
+ - Matthias Kaehlcke
+ - Kenji Kaneshige
+ - Jan Kara
+ - Jeremy Kerr
+ - Russell King
+ - Olaf Kirch
+ - Roel Kluin
+ - Hans-Jürgen Koch
+ - Auke Kok
+ - Peter Korsgaard
+ - Jiri Kosina
+ - Aaro Koskinen
+ - Mariusz Kozlowski
+ - Greg Kroah-Hartman
+ - Michael Krufky
+ - Aneesh Kumar
+ - Clemens Ladisch
+ - Christoph Lameter
+ - Gunnar Larisch
+ - Anders Larsen
+ - Grant Likely
+ - John W. Linville
+ - Yinghai Lu
+ - Tony Luck
+ - Pavel Machek
+ - Matt Mackall
+ - Paul Mackerras
+ - Roland McGrath
+ - Patrick McHardy
+ - Kyle McMartin
+ - Paul Menage
+ - Thierry Merle
+ - Eric Miao
+ - Akinobu Mita
+ - Ingo Molnar
+ - James Morris
+ - Andrew Morton
+ - Paul Mundt
+ - Oleg Nesterov
+ - Luca Olivetti
+ - S.Çağlar Onur
+ - Pierre Ossman
+ - Keith Owens
+ - Venkatesh Pallipadi
+ - Nick Piggin
+ - Nicolas Pitre
+ - Evgeniy Polyakov
+ - Richard Purdie
+ - Mike Rapoport
+ - Sam Ravnborg
+ - Gerrit Renker
+ - Stefan Richter
+ - David Rientjes
+ - Luis R. Rodriguez
+ - Stefan Roese
+ - Francois Romieu
+ - Rami Rosen
+ - Stephen Rothwell
+ - Maciej W. Rozycki
+ - Mark Salyzyn
+ - Yoshinori Sato
+ - Deepak Saxena
+ - Holger Schurig
+ - Amit Shah
+ - Yoshihiro Shimoda
+ - Sergei Shtylyov
+ - Kay Sievers
+ - Sebastian Siewior
+ - Rik Snel
+ - Jes Sorensen
+ - Alexey Starikovskiy
+ - Alan Stern
+ - Timur Tabi
+ - Hirokazu Takata
+ - Eliezer Tamir
+ - Eugene Teo
+ - Doug Thompson
+ - FUJITA Tomonori
+ - Dmitry Torokhov
+ - Marcelo Tosatti
+ - Steven Toth
+ - Theodore Tso
+ - Matthias Urlichs
+ - Geert Uytterhoeven
+ - Arjan van de Ven
+ - Ivo van Doorn
+ - Rik van Riel
+ - Wim Van Sebroeck
+ - Hans Verkuil
+ - Horst H. von Brand
+ - Dmitri Vorobiev
+ - Anton Vorontsov
+ - Daniel Walker
+ - Johannes Weiner
+ - Harald Welte
+ - Matthew Wilcox
+ - Dan J. Williams
+ - Darrick J. Wong
+ - David Woodhouse
+ - Chris Wright
+ - Bryan Wu
+ - Rafael J. Wysocki
+ - Herbert Xu
+ - Vlad Yasevich
+ - Peter Zijlstra
+ - Bartlomiej Zolnierkiewicz
+
diff --git a/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
new file mode 100644
index 000000000000..99e21d22800d
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
@@ -0,0 +1,155 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_statement_kernel:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst <process_statement_kernel>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+Linux 內核執行聲明
+------------------
+
+作爲Linux內核的開發人員,我們對如何使用我們的軟體以及如何實施軟體許可證有著
+濃厚的興趣。遵守GPL-2.0的互惠共享義務對我們軟體和社區的長期可持續性至關重要。
+
+雖然有權強制執行對我們社區的貢獻中的單獨版權權益,但我們有共同的利益,即確保
+個人強制執行行動的方式有利於我們的社區,不會對我們軟體生態系統的健康和增長
+產生意外的負面影響。爲了阻止無益的執法行動,我們同意代表我們自己和我們版權
+利益的任何繼承人對Linux內核用戶作出以下符合我們開發社區最大利益的承諾:
+
+ 儘管有GPL-2.0的終止條款,我們同意,採用以下GPL-3.0條款作爲我們許可證下的
+ 附加許可,作爲任何對許可證下權利的非防禦性主張,這符合我們開發社區的最佳
+ 利益。
+
+ 但是,如果您停止所有違反本許可證的行爲,則您從特定版權持有人處獲得的
+ 許可證將被恢復:(a)暫時恢復,除非版權持有人明確並最終終止您的許可證;
+ 以及(b)永久恢復, 如果版權持有人未能在你終止違反後60天內以合理方式
+ 通知您違反本許可證的行爲,則永久恢復您的許可證。
+
+ 此外,如果版權所有者以某種合理的方式通知您違反了本許可,這是您第一次
+ 從該版權所有者處收到違反本許可的通知(對於任何作品),並且您在收到通知
+ 後的30天內糾正違規行爲。則您從特定版權所有者處獲得的許可將永久恢復.
+
+我們提供這些保證的目的是鼓勵更多地使用該軟體。我們希望公司和個人使用、修改和
+分發此軟體。我們希望以公開和透明的方式與用戶合作,以消除我們對法規遵從性或強制
+執行的任何不確定性,這些不確定性可能會限制我們軟體的採用。我們將法律行動視爲
+最後手段,只有在其他社區努力未能解決這一問題時才採取行動。
+
+最後,一旦一個不合規問題得到解決,我們希望用戶會感到歡迎,加入我們爲之努力的
+這個項目。共同努力,我們會更強大。
+
+除了下面提到的以外,我們只爲自己說話,而不是爲今天、過去或將來可能爲之工作的
+任何公司說話。
+
+ - Laura Abbott
+ - Bjorn Andersson (Linaro)
+ - Andrea Arcangeli
+ - Neil Armstrong
+ - Jens Axboe
+ - Pablo Neira Ayuso
+ - Khalid Aziz
+ - Ralf Baechle
+ - Felipe Balbi
+ - Arnd Bergmann
+ - Ard Biesheuvel
+ - Tim Bird
+ - Paolo Bonzini
+ - Christian Borntraeger
+ - Mark Brown (Linaro)
+ - Paul Burton
+ - Javier Martinez Canillas
+ - Rob Clark
+ - Kees Cook (Google)
+ - Jonathan Corbet
+ - Dennis Dalessandro
+ - Vivien Didelot (Savoir-faire Linux)
+ - Hans de Goede
+ - Mel Gorman (SUSE)
+ - Sven Eckelmann
+ - Alex Elder (Linaro)
+ - Fabio Estevam
+ - Larry Finger
+ - Bhumika Goyal
+ - Andy Gross
+ - Juergen Gross
+ - Shawn Guo
+ - Ulf Hansson
+ - Stephen Hemminger (Microsoft)
+ - Tejun Heo
+ - Rob Herring
+ - Masami Hiramatsu
+ - Michal Hocko
+ - Simon Horman
+ - Johan Hovold (Hovold Consulting AB)
+ - Christophe JAILLET
+ - Olof Johansson
+ - Lee Jones (Linaro)
+ - Heiner Kallweit
+ - Srinivas Kandagatla
+ - Jan Kara
+ - Shuah Khan (Samsung)
+ - David Kershner
+ - Jaegeuk Kim
+ - Namhyung Kim
+ - Colin Ian King
+ - Jeff Kirsher
+ - Greg Kroah-Hartman (Linux Foundation)
+ - Christian König
+ - Vinod Koul
+ - Krzysztof Kozlowski
+ - Viresh Kumar
+ - Aneesh Kumar K.V
+ - Julia Lawall
+ - Doug Ledford
+ - Chuck Lever (Oracle)
+ - Daniel Lezcano
+ - Shaohua Li
+ - Xin Long
+ - Tony Luck
+ - Catalin Marinas (Arm Ltd)
+ - Mike Marshall
+ - Chris Mason
+ - Paul E. McKenney
+ - Arnaldo Carvalho de Melo
+ - David S. Miller
+ - Ingo Molnar
+ - Kuninori Morimoto
+ - Trond Myklebust
+ - Martin K. Petersen (Oracle)
+ - Borislav Petkov
+ - Jiri Pirko
+ - Josh Poimboeuf
+ - Sebastian Reichel (Collabora)
+ - Guenter Roeck
+ - Joerg Roedel
+ - Leon Romanovsky
+ - Steven Rostedt (VMware)
+ - Frank Rowand
+ - Ivan Safonov
+ - Anna Schumaker
+ - Jes Sorensen
+ - K.Y. Srinivasan
+ - David Sterba (SUSE)
+ - Heiko Stuebner
+ - Jiri Kosina (SUSE)
+ - Willy Tarreau
+ - Dmitry Torokhov
+ - Linus Torvalds
+ - Thierry Reding
+ - Rik van Riel
+ - Luis R. Rodriguez
+ - Geert Uytterhoeven (Glider bvba)
+ - Eduardo Valentin (Amazon.com)
+ - Daniel Vetter
+ - Linus Walleij
+ - Richard Weinberger
+ - Dan Williams
+ - Rafael J. Wysocki
+ - Arvind Yadav
+ - Masahiro Yamada
+ - Wei Yongjun
+ - Lv Zheng
+ - Marc Zyngier (Arm Ltd)
+
diff --git a/Documentation/translations/zh_TW/process/license-rules.rst b/Documentation/translations/zh_TW/process/license-rules.rst
new file mode 100644
index 000000000000..ad2b80f97123
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/license-rules.rst
@@ -0,0 +1,374 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/license-rules.rst <kernel_licensing>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+.. _tw_kernel_licensing:
+
+Linux內核許可規則
+=================
+
+Linux內核根據LICENSES/preferred/GPL-2.0中提供的GNU通用公共許可證版本2
+(GPL-2.0)的條款提供,並在LICENSES/exceptions/Linux-syscall-note中顯式
+描述了例外的系統調用,如COPYING文件中所述。
+
+此文檔文件提供了如何對每個源文件進行注釋以使其許可證清晰明確的說明。
+它不會取代內核的許可證。
+
+內核原始碼作爲一個整體適用於COPYING文件中描述的許可證,但是單個源文件可以
+具有不同的與GPL-20兼容的許可證::
+
+ GPL-1.0+ : GNU通用公共許可證v1.0或更高版本
+ GPL-2.0+ : GNU通用公共許可證v2.0或更高版本
+ LGPL-2.0 : 僅限GNU庫通用公共許可證v2
+ LGPL-2.0+: GNU 庫通用公共許可證v2或更高版本
+ LGPL-2.1 : 僅限GNU寬通用公共許可證v2.1
+ LGPL-2.1+: GNU寬通用公共許可證v2.1或更高版本
+
+除此之外,個人文件可以在雙重許可下提供,例如一個兼容的GPL變體,或者BSD,
+MIT等許可。
+
+用戶空間API(UAPI)頭文件描述了用戶空間程序與內核的接口,這是一種特殊情況。
+根據內核COPYING文件中的注釋,syscall接口是一個明確的邊界,它不會將GPL要求
+擴展到任何使用它與內核通信的軟體。由於UAPI頭文件必須包含在創建在Linux內核
+上運行的可執行文件的任何源文件中,因此此例外必須記錄在特別的許可證表述中。
+
+表達源文件許可證的常用方法是將匹配的樣板文本添加到文件的頂部注釋中。由於
+格式,拼寫錯誤等,這些「樣板」很難通過那些在上下文中使用的驗證許可證合規性
+的工具。
+
+樣板文本的替代方法是在每個源文件中使用軟體包數據交換(SPDX)許可證標識符。
+SPDX許可證標識符是機器可解析的,並且是用於提供文件內容的許可證的精確縮寫。
+SPDX許可證標識符由Linux 基金會的SPDX 工作組管理,並得到了整個行業,工具
+供應商和法律團隊的合作夥伴的一致同意。有關詳細信息,請參閱
+https://spdx.org/
+
+Linux內核需要所有源文件中的精確SPDX標識符。內核中使用的有效標識符在
+`許可標識符`_ 一節中進行了解釋,並且已可以在
+https://spdx.org/licenses/ 上的官方SPDX許可證列表中檢索,並附帶許可證
+文本。
+
+許可標識符語法
+--------------
+
+1.安置:
+
+   內核文件中的SPDX許可證標識符應添加到可包含注釋的文件中的第一行。對於大多
+ 數文件,這是第一行,除了那些在第一行中需要'#!PATH_TO_INTERPRETER'的腳本。
+ 對於這些腳本,SPDX標識符進入第二行。
+
+|
+
+2. 風格:
+
+ SPDX許可證標識符以注釋的形式添加。注釋樣式取決於文件類型::
+
+ C source: // SPDX-License-Identifier: <SPDX License Expression>
+ C header: /* SPDX-License-Identifier: <SPDX License Expression> */
+ ASM: /* SPDX-License-Identifier: <SPDX License Expression> */
+ scripts: # SPDX-License-Identifier: <SPDX License Expression>
+ .rst: .. SPDX-License-Identifier: <SPDX License Expression>
+ .dts{i}: // SPDX-License-Identifier: <SPDX License Expression>
+
+ 如果特定工具無法處理標準注釋樣式,則應使用工具接受的相應注釋機制。這是在
+ C 頭文件中使用「/\*\*/」樣式注釋的原因。過去在使用生成的.lds文件中觀察到
+ 構建被破壞,其中'ld'無法解析C++注釋。現在已經解決了這個問題,但仍然有較
+ 舊的彙編程序工具無法處理C++樣式的注釋。
+
+|
+
+3. 句法:
+
+ <SPDX許可證表達式>是SPDX許可證列表中的SPDX短格式許可證標識符,或者在許可
+ 證例外適用時由「WITH」分隔的兩個SPDX短格式許可證標識符的組合。當應用多個許
+ 可證時,表達式由分隔子表達式的關鍵字「AND」,「OR」組成,並由「(」,「)」包圍。
+
+ 帶有「或更高」選項的[L]GPL等許可證的許可證標識符通過使用「+」來表示「或更高」
+ 選項來構建。::
+
+ // SPDX-License-Identifier: GPL-2.0+
+ // SPDX-License-Identifier: LGPL-2.1+
+
+ 當需要修正的許可證時,應使用WITH。 例如,linux內核UAPI文件使用表達式::
+
+ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ // SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note
+
+ 其它在內核中使用WITH例外的事例如下::
+
+ // SPDX-License-Identifier: GPL-2.0 WITH mif-exception
+ // SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+ 例外只能與特定的許可證標識符一起使用。有效的許可證標識符列在異常文本文件
+ 的標記中。有關詳細信息,請參閱 `許可標識符`_ 一章中的 `例外`_ 。
+
+ 如果文件是雙重許可且只選擇一個許可證,則應使用OR。例如,一些dtsi文件在雙
+ 許可下可用::
+
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+ 內核中雙許可文件中許可表達式的示例::
+
+ // SPDX-License-Identifier: GPL-2.0 OR MIT
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+ // SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
+ // SPDX-License-Identifier: GPL-2.0 OR MPL-1.1
+ // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT
+ // SPDX-License-Identifier: GPL-1.0+ OR BSD-3-Clause OR OpenSSL
+
+ 如果文件具有多個許可證,其條款全部適用於使用該文件,則應使用AND。例如,
+ 如果代碼是從另一個項目繼承的,並且已經授予了將其放入內核的權限,但原始
+ 許可條款需要保持有效::
+
+ // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT
+
+ 另一個需要遵守兩套許可條款的例子是::
+
+ // SPDX-License-Identifier: GPL-1.0+ AND LGPL-2.1+
+
+許可標識符
+----------
+
+當前使用的許可證以及添加到內核的代碼許可證可以分解爲:
+
+1. _`優先許可`:
+
+ 應儘可能使用這些許可證,因爲它們已知完全兼容並廣泛使用。這些許可證在內核
+ 目錄::
+
+ LICENSES/preferred/
+
+ 此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+ 符相同,後者應用於源文件中的許可證。
+
+ 例如::
+
+ LICENSES/preferred/GPL-2.0
+
+ 包含GPLv2許可證文本和所需的元標籤::
+
+ LICENSES/preferred/MIT
+
+ 包含MIT許可證文本和所需的元標記
+
+ _`元標記`:
+
+ 許可證文件中必須包含以下元標記:
+
+ - Valid-License-Identifier:
+
+   一行或多行, 聲明那些許可標識符在項目內有效, 以引用此特定許可的文本。通
+ 常這是一個有效的標識符,但是例如對於帶有'或更高'選項的許可證,兩個標識
+ 符都有效。
+
+ - SPDX-URL:
+
+ SPDX頁面的URL,其中包含與許可證相關的其他信息.
+
+ - Usage-Guidance:
+
+ 使用建議的自由格式文本。該文本必須包含SPDX許可證標識符的正確示例,因爲
+ 它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+ - License-Text:
+
+ 此標記之後的所有文本都被視爲原始許可文本
+
+ 文件格式示例::
+
+ Valid-License-Identifier: GPL-2.0
+ Valid-License-Identifier: GPL-2.0+
+ SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
+ Usage-Guide:
+ To use this license in source code, put one of the following SPDX
+ tag/value pairs into a comment according to the placement
+ guidelines in the licensing rules documentation.
+ For 'GNU General Public License (GPL) version 2 only' use:
+ SPDX-License-Identifier: GPL-2.0
+ For 'GNU General Public License (GPL) version 2 or any later version' use:
+ SPDX-License-Identifier: GPL-2.0+
+ License-Text:
+ Full license text
+
+ ::
+
+ SPDX-License-Identifier: MIT
+ SPDX-URL: https://spdx.org/licenses/MIT.html
+ Usage-Guide:
+ To use this license in source code, put the following SPDX
+ tag/value pair into a comment according to the placement
+ guidelines in the licensing rules documentation.
+ SPDX-License-Identifier: MIT
+ License-Text:
+ Full license text
+
+|
+
+2. 不推薦的許可證:
+
+ 這些許可證只應用於現有代碼或從其他項目導入代碼。這些許可證在內核目錄::
+
+ LICENSES/other/
+
+ 此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+ 符相同,後者應用於源文件中的許可證。
+
+ 例如::
+
+ LICENSES/other/ISC
+
+ 包含國際系統聯合許可文本和所需的元標籤::
+
+ LICENSES/other/ZLib
+
+ 包含ZLIB許可文本和所需的元標籤.
+
+ 元標籤:
+
+ 「其他」許可證的元標籤要求與 `優先許可`_ 的要求相同。
+
+ 文件格式示例::
+
+ Valid-License-Identifier: ISC
+ SPDX-URL: https://spdx.org/licenses/ISC.html
+ Usage-Guide:
+ Usage of this license in the kernel for new code is discouraged
+ and it should solely be used for importing code from an already
+ existing project.
+ To use this license in source code, put the following SPDX
+ tag/value pair into a comment according to the placement
+ guidelines in the licensing rules documentation.
+ SPDX-License-Identifier: ISC
+ License-Text:
+ Full license text
+
+|
+
+3. _`例外`:
+
+ 某些許可證可以修改,並允許原始許可證不具有的某些例外權利。這些例外在
+ 內核目錄::
+
+ LICENSES/exceptions/
+
+ 此目錄中的文件包含完整的例外文本和所需的 `例外元標記`_ 。
+
+ 例如::
+
+ LICENSES/exceptions/Linux-syscall-note
+
+ 包含Linux內核的COPYING文件中記錄的Linux系統調用例外,該文件用於UAPI
+ 頭文件。例如::
+
+ LICENSES/exceptions/GCC-exception-2.0
+
+ 包含GCC'連結例外',它允許獨立於其許可證的任何二進位文件與標記有此例外的
+ 文件的編譯版本連結。這是從GPL不兼容原始碼創建可運行的可執行文件所必需的。
+
+ _`例外元標記`:
+
+ 以下元標記必須在例外文件中可用:
+
+ - SPDX-Exception-Identifier:
+
+   一個可與SPDX許可證標識符一起使用的例外標識符。
+
+ - SPDX-URL:
+
+ SPDX頁面的URL,其中包含與例外相關的其他信息。
+
+ - SPDX-Licenses:
+
+   以逗號分隔的例外可用的SPDX許可證標識符列表。
+
+ - Usage-Guidance:
+
+ 使用建議的自由格式文本。必須在文本後面加上SPDX許可證標識符的正確示例,
+ 因爲它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+ - Exception-Text:
+
+ 此標記之後的所有文本都被視爲原始異常文本
+
+ 文件格式示例::
+
+ SPDX-Exception-Identifier: Linux-syscall-note
+ SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
+ SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+
+ Usage-Guidance:
+ This exception is used together with one of the above SPDX-Licenses
+ to mark user-space API (uapi) header files so they can be included
+ into non GPL compliant user-space application code.
+ To use this exception add it with the keyword WITH to one of the
+ identifiers in the SPDX-Licenses tag:
+ SPDX-License-Identifier: <SPDX-License> WITH Linux-syscall-note
+ Exception-Text:
+ Full exception text
+
+ ::
+
+ SPDX-Exception-Identifier: GCC-exception-2.0
+ SPDX-URL: https://spdx.org/licenses/GCC-exception-2.0.html
+ SPDX-Licenses: GPL-2.0, GPL-2.0+
+ Usage-Guidance:
+ The "GCC Runtime Library exception 2.0" is used together with one
+ of the above SPDX-Licenses for code imported from the GCC runtime
+ library.
+ To use this exception add it with the keyword WITH to one of the
+ identifiers in the SPDX-Licenses tag:
+ SPDX-License-Identifier: <SPDX-License> WITH GCC-exception-2.0
+ Exception-Text:
+ Full exception text
+
+
+所有SPDX許可證標識符和例外都必須在LICENSES子目錄中具有相應的文件。這是允許
+工具驗證(例如checkpatch.pl)以及準備好從源讀取和提取許可證所必需的, 這是
+各種FOSS組織推薦的,例如 `FSFE REUSE initiative <https://reuse.software/>`_.
+
+_`模塊許可`
+-----------------
+
+ 可加載內核模塊還需要MODULE_LICENSE()標記。此標記既不替代正確的原始碼
+ 許可證信息(SPDX-License-Identifier),也不以任何方式表示或確定提供模塊
+ 原始碼的確切許可證。
+
+ 此標記的唯一目的是提供足夠的信息,該模塊是否是自由軟體或者是內核模塊加
+ 載器和用戶空間工具的專有模塊。
+
+ MODULE_LICENSE()的有效許可證字符串是:
+
+ ============================= =============================================
+ "GPL" 模塊是根據GPL版本2許可的。這並不表示僅限於
+ GPL-2.0或GPL-2.0或更高版本之間的任何區別。
+ 最正確許可證信息只能通過相應源文件中的許可證
+ 信息來確定
+
+ "GPL v2" 和"GPL"相同,它的存在是因爲歷史原因。
+
+ "GPL and additional rights" 表示模塊源在GPL v2變體和MIT許可下雙重許可的
+ 歷史變體。請不要在新代碼中使用。
+
+ "Dual MIT/GPL" 表達該模塊在GPL v2變體或MIT許可證選擇下雙重
+ 許可的正確方式。
+
+ "Dual BSD/GPL" 該模塊根據GPL v2變體或BSD許可證選擇進行雙重
+ 許可。 BSD許可證的確切變體只能通過相應源文件
+ 中的許可證信息來確定。
+
+ "Dual MPL/GPL" 該模塊根據GPL v2變體或Mozilla Public License
+ (MPL)選項進行雙重許可。 MPL許可證的確切變體
+ 只能通過相應的源文件中的許可證信息來確定。
+
+ "Proprietary" 該模塊屬於專有許可。此字符串僅用於專有的第三
+ 方模塊,不能用於在內核樹中具有原始碼的模塊。
+ 以這種方式標記的模塊在加載時會使用'P'標記汙
+ 染內核,並且內核模塊加載器拒絕將這些模塊連結
+ 到使用EXPORT_SYMBOL_GPL()導出的符號。
+ ============================= =============================================
+
+
diff --git a/Documentation/translations/zh_TW/process/magic-number.rst b/Documentation/translations/zh_TW/process/magic-number.rst
new file mode 100644
index 000000000000..ae321a9aaece
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/magic-number.rst
@@ -0,0 +1,148 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_magicnumbers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/magic-number.rst <magicnumbers>`
+
+如果想評論或更新本文的內容,請直接發信到LKML。如果你使用英文交流有困難的話,也可
+以向中文版維護者求助。如果本翻譯更新不及時或者翻譯存在問題,請聯繫中文版維護者::
+
+ 中文版維護者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+ 中文版翻譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+ 中文版校譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 魔術數
+============
+
+這個文件是有關當前使用的魔術值註冊表。當你給一個結構添加了一個魔術值,你也應該把這個魔術值添加到這個文件,因爲我們最好把用於各種結構的魔術值統一起來。
+
+使用魔術值來保護內核數據結構是一個非常好的主意。這就允許你在運行期檢查(a)一個結構是否已經被攻擊,或者(b)你已經給一個例行程序通過了一個錯誤的結構。後一種情況特別地有用---特別是當你通過一個空指針指向結構體的時候。tty源碼,例如,經常通過特定驅動使用這種方法並且反覆地排列特定方面的結構。
+
+使用魔術值的方法是在結構的開始處聲明的,如下::
+
+ struct tty_ldisc {
+ int magic;
+ ...
+ };
+
+當你以後給內核添加增強功能的時候,請遵守這條規則!這樣就會節省數不清的調試時間,特別是一些古怪的情況,例如,數組超出範圍並且重新寫了超出部分。遵守這個規則,‪這些情況可以被快速地,安全地避免。
+
+ Theodore Ts'o
+ 31 Mar 94
+
+給當前的Linux 2.1.55添加魔術表。
+
+ Michael Chastain
+ <mailto:mec@shout.net>
+ 22 Sep 1997
+
+現在應該最新的Linux 2.1.112.因爲在特性凍結期間,不能在2.2.x前改變任何東西。這些條目被數域所排序。
+
+ Krzysztof G.Baranowski
+ <mailto: kgb@knm.org.pl>
+ 29 Jul 1998
+
+更新魔術表到Linux 2.5.45。剛好越過特性凍結,但是有可能還會有一些新的魔術值在2.6.x之前融入到內核中。
+
+ Petr Baudis
+ <pasky@ucw.cz>
+ 03 Nov 2002
+
+更新魔術表到Linux 2.5.74。
+
+ Fabian Frederick
+ <ffrederick@users.sourceforge.net>
+ 09 Jul 2003
+
+===================== ================ ======================== ==========================================
+魔術數名 數字 結構 文件
+===================== ================ ======================== ==========================================
+PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/pg.h``
+CMAGIC 0x0111 user ``include/linux/a.out.h``
+MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
+HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
+APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
+DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
+DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
+FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
+FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
+PTY_MAGIC 0x5001 ``drivers/char/pty.c``
+PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
+SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
+SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
+STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
+SIXPACK_MAGIC 0x5304 sixpack ``drivers/net/hamradio/6pack.h``
+AX25_MAGIC 0x5316 ax_disp ``drivers/net/mkiss.h``
+TTY_MAGIC 0x5401 tty_struct ``include/linux/tty.h``
+MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
+TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
+MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
+USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
+FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
+USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
+RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
+USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
+CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
+LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
+GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str ``drivers/scsi/gdth_ioctl.h``
+RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``
+NBD_REQUEST_MAGIC 0x12560953 nbd_request ``include/linux/nbd.h``
+RED_MAGIC2 0x170fc2a5 (any) ``mm/slab.c``
+BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c``
+ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
+ECP_MAGIC 0x21504345 cdkecpsig ``include/linux/cdk.h``
+LSOMAGIC 0x27091997 lso ``drivers/fc4/fc.c``
+LSMAGIC 0x2a3b4d2a ls ``drivers/fc4/fc.c``
+WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} ``include/linux/wanpipe.h``
+CS_CARD_MAGIC 0x43525553 cs_card ``sound/oss/cs46xx.c``
+LABELCL_MAGIC 0x4857434c labelcl_info_s ``include/asm/ia64/sn/labelcl.h``
+ISDN_ASYNC_MAGIC 0x49344C01 modem_info ``include/linux/isdn.h``
+CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info ``drivers/s390/net/ctctty.c``
+ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s ``drivers/isdn/i4l/isdn_net_lib.h``
+SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg ``arch/*/amiga/config.c``
+CS_STATE_MAGIC 0x4c4f4749 cs_state ``sound/oss/cs46xx.c``
+SLAB_C_MAGIC 0x4f17a36d kmem_cache ``mm/slab.c``
+COW_MAGIC 0x4f4f4f4d cow_header_v1 ``arch/um/drivers/ubd_user.c``
+I810_CARD_MAGIC 0x5072696E i810_card ``sound/oss/i810_audio.c``
+TRIDENT_CARD_MAGIC 0x5072696E trident_card ``sound/oss/trident.c``
+ROUTER_MAGIC 0x524d4157 wan_device [in ``wanrouter.h`` pre 3.9]
+SAVEKMSG_MAGIC1 0x53415645 savekmsg ``arch/*/amiga/config.c``
+GDA_MAGIC 0x58464552 gda ``arch/mips/include/asm/sn/gda.h``
+RED_MAGIC1 0x5a2cf071 (any) ``mm/slab.c``
+EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev ``drivers/atm/lanai.c``
+HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h``
+PCXX_MAGIC 0x5c6df104 channel ``drivers/char/pcxx.h``
+KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h``
+I810_STATE_MAGIC 0x63657373 i810_state ``sound/oss/i810_audio.c``
+TRIDENT_STATE_MAGIC 0x63657373 trient_state ``sound/oss/trident.c``
+M3_CARD_MAGIC 0x646e6f50 m3_card ``sound/oss/maestro3.c``
+FW_HEADER_MAGIC 0x65726F66 fw_header ``drivers/atm/fore200e.h``
+SLOT_MAGIC 0x67267321 slot ``drivers/hotplug/cpqphp.h``
+SLOT_MAGIC 0x67267322 slot ``drivers/hotplug/acpiphp.h``
+LO_MAGIC 0x68797548 nbd_device ``include/linux/nbd.h``
+M3_STATE_MAGIC 0x734d724d m3_state ``sound/oss/maestro3.c``
+VMALLOC_MAGIC 0x87654320 snd_alloc_track ``sound/core/memory.c``
+KMALLOC_MAGIC 0x87654321 snd_alloc_track ``sound/core/memory.c``
+PWC_MAGIC 0x89DC10AB pwc_device ``drivers/usb/media/pwc.h``
+NBD_REPLY_MAGIC 0x96744668 nbd_reply ``include/linux/nbd.h``
+ENI155_MAGIC 0xa54b872d midway_eprom ``drivers/atm/eni.h``
+CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``
+DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram ``drivers/scsi/gdth.h``
+YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c``
+CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c``
+QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c``
+QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c``
+HTB_CMAGIC 0xFEFAFEF1 htb_class ``net/sched/sch_htb.c``
+NMI_MAGIC 0x48414d4d455201 nmi_s ``arch/mips/include/asm/sn/nmi.h``
+===================== ================ ======================== ==========================================
+
+
+請注意,在聲音記憶管理中仍然有一些特殊的爲每個驅動定義的魔術值。查看include/sound/sndmagic.h來獲取他們完整的列表信息。很多OSS聲音驅動擁有自己從音效卡PCI ID構建的魔術值-他們也沒有被列在這裡。
+
+IrDA子系統也使用了大量的自己的魔術值,查看include/net/irda/irda.h來獲取他們完整的信息。
+
+HFS是另外一個比較大的使用魔術值的文件系統-你可以在fs/hfs/hfs.h中找到他們。
+
diff --git a/Documentation/translations/zh_TW/process/management-style.rst b/Documentation/translations/zh_TW/process/management-style.rst
new file mode 100644
index 000000000000..dce248470063
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/management-style.rst
@@ -0,0 +1,211 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/management-style.rst <managementstyle>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+.. _tw_managementstyle:
+
+Linux內核管理風格
+=================
+
+這是一個簡短的文檔,描述了Linux內核首選的(或胡編的,取決於您問誰)管理風格。
+它的目的是在某種程度上參照 :ref:`process/coding-style.rst <codingstyle>`
+主要是爲了避免反覆回答 [#cnf1]_ 相同(或類似)的問題。
+
+管理風格是非常個人化的,比簡單的編碼風格規則更難以量化,因此本文檔可能與實
+際情況有關,也可能與實際情況無關。起初它是一個玩笑,但這並不意味著它可能不
+是真的。你得自己決定。
+
+順便說一句,在談到「核心管理者」時,主要是技術負責人,而不是在公司內部進行傳
+統管理的人。如果你簽署了採購訂單或者對你的團隊的預算有任何了解,你幾乎肯定
+不是一個核心管理者。這些建議可能適用於您,也可能不適用於您。
+
+首先,我建議你購買「高效人的七個習慣」,而不是閱讀它。燒了它,這是一個偉大的
+象徵性姿態。
+
+.. [#cnf1] 本文件並不是通過回答問題,而是通過讓提問者痛苦地明白,我們不知道
+ 答案是什麼。
+
+不管怎樣,這裡是:
+
+.. _tw_decisions:
+
+1)決策
+-------
+
+每個人都認爲管理者做決定,而且決策很重要。決定越大越痛苦,管理者就必須越高級。
+這很明顯,但事實並非如此。
+
+遊戲的名字是 **避免** 做出決定。尤其是,如果有人告訴你「選擇(a)或(b),
+我們真的需要你來做決定」,你就是陷入麻煩的管理者。你管理的人比你更了解細節,
+所以如果他們來找你做技術決策,你完蛋了。你顯然沒有能力爲他們做這個決定。
+
+(推論:如果你管理的人不比你更了解細節,你也會被搞砸,儘管原因完全不同。
+也就是說,你的工作是錯的,他們應該管理你的才智)
+
+所以遊戲的名字是 **避免** 做出決定,至少是那些大而痛苦的決定。做一些小的
+和非結果性的決定是很好的,並且使您看起來好像知道自己在做什麼,所以內核管理者
+需要做的是將那些大的和痛苦的決定變成那些沒有人真正關心的小事情。
+
+這有助於認識到一個大的決定和一個小的決定之間的關鍵區別是你是否可以在事後修正
+你的決定。任何決定都可以通過始終確保如果你錯了(而且你一定會錯),你以後總是
+可以通過回溯來彌補損失。突然間,你就要做兩個無關緊要的決定,一個是錯誤的,另
+一個是正確的。
+
+人們甚至會認爲這是真正的領導能力(咳,胡說,咳)。
+
+因此,避免重大決策的關鍵在於避免做那些無法挽回的事情。不要被引導到一個你無法
+逃離的角落。走投無路的老鼠可能很危險——走投無路的管理者真可憐。
+
+事實證明,由於沒有人會愚蠢到讓內核管理者承擔巨大的財政責任,所以通常很容易
+回溯。既然你不可能浪費掉你無法償還的巨額資金,你唯一可以回溯的就是技術決策,
+而回溯很容易:只要告訴大家你是個不稱職的傻瓜,說對不起,然後撤銷你去年讓別
+人所做的毫無價值的工作。突然間,你一年前做的決定不在是一個重大的決定,因爲
+它很容易被推翻。
+
+事實證明,有些人對接受這種方法有困難,原因有兩個:
+
+ - 承認你是個白癡比看起來更難。我們都喜歡保持形象,在公共場合說你錯了有時
+ 確實很難。
+ - 如果有人告訴你,你去年所做的工作終究是不值得的,那麼對那些可憐的低級工
+ 程師來說也是很困難的,雖然實際的 **工作** 很容易刪除,但你可能已經不可
+ 挽回地失去了工程師的信任。記住:「不可撤銷」是我們一開始就試圖避免的,
+ 而你的決定終究是一個重大的決定。
+
+令人欣慰的是,這兩個原因都可以通過預先承認你沒有任何線索,提前告訴人們你的
+決定完全是初步的,而且可能是錯誤的事情來有效地緩解。你應該始終保留改變主意
+的權利,並讓人們 **意識** 到這一點。當你 **還沒有** 做過真正愚蠢的事情的時
+候,承認自己是愚蠢的要容易得多。
+
+然後,當它真的被證明是愚蠢的時候,人們就轉動他們的眼珠說「哎呀,下次不要了」。
+
+這種對不稱職的先發制人的承認,也可能使真正做這項工作的人也會三思是否值得做。
+畢竟,如果他們不確定這是否是一個好主意,你肯定不應該通過向他們保證他們所做
+的工作將會進入(內核)鼓勵他們。在他們開始一項巨大的努力之前,至少讓他們三
+思而後行。
+
+記住:他們最好比你更了解細節,而且他們通常認爲他們對每件事都有答案。作爲一
+個管理者,你能做的最好的事情不是灌輸自信,而是對他們所做的事情進行健康的批
+判性思考。
+
+順便說一句,另一種避免做出決定的方法是看起來很可憐的抱怨 「我們不能兩者兼
+得嗎?」 相信我,它是有效的。如果不清楚哪種方法更好,他們最終會弄清楚的。
+最終的答案可能是兩個團隊都會因爲這種情況而感到沮喪,以至於他們放棄了。
+
+這聽起來像是一個失敗,但這通常是一個跡象,表明兩個項目都有問題,而參與其中
+的人不能做決定的原因是他們都是錯誤的。你最終會聞到玫瑰的味道,你避免了另一
+個你本可以搞砸的決定。
+
+2)人
+-----
+
+大多數人都是白癡,做一名管理者意味著你必須處理好這件事,也許更重要的是,
+**他們** 必須處理好你。
+
+事實證明,雖然很容易糾正技術錯誤,但不容易糾正人格障礙。你只能和他們的和
+你的(人格障礙)共處。
+
+但是,爲了做好作爲內核管理者的準備,最好記住不要燒掉任何橋樑,不要轟炸任何
+無辜的村民,也不要疏遠太多的內核開發人員。事實證明,疏遠人是相當容易的,而
+親近一個疏遠的人是很難的。因此,「疏遠」立即屬於「不可逆」的範疇,並根據
+:ref:`tw_decisions` 成爲絕不可以做的事情。
+
+這裡只有幾個簡單的規則:
+
+ (1) 不要叫人笨蛋(至少不要在公共場合)
+ (2) 學習如何在忘記規則(1)時道歉
+
+問題在於 #1 很容易去做,因爲你可以用數百萬種不同的方式說「你是一個笨蛋」 [#cnf2]_
+有時甚至沒有意識到,而且幾乎總是帶著一種白熱化的信念,認爲你是對的。
+
+你越確信自己是對的(讓我們面對現實吧,你可以把幾乎所有人都稱爲壞人,而且你
+經常是對的),事後道歉就越難。
+
+要解決此問題,您實際上只有兩個選項:
+
+ - 非常擅長道歉
+ - 把「愛」均勻地散開,沒有人會真正感覺到自己被不公平地瞄準了。讓它有足夠的
+ 創造性,他們甚至可能會覺得好笑。
+
+選擇永遠保持禮貌是不存在的。沒有人會相信一個如此明顯地隱藏了他們真實性格的人。
+
+.. [#cnf2] 保羅·西蒙演唱了「離開愛人的50種方法」,因爲坦率地說,「告訴開發者
+ 他們是D*CKHEAD" 的100萬種方法都無法確認。但我確信他已經這麼想了。
+
+3)人2 - 好人
+-------------
+
+雖然大多數人都是白癡,但不幸的是,據此推論你也是白癡,儘管我們都自我感覺良
+好,我們比普通人更好(讓我們面對現實吧,沒有人相信他們是普通人或低於普通人),
+我們也應該承認我們不是最鋒利的刀,而且會有其他人比你更不像白癡。
+
+有些人對聰明人反應不好。其他人利用它們。
+
+作爲內核維護人員,確保您在第二組中。接受他們,因爲他們會讓你的工作更容易。
+特別是,他們能夠爲你做決定,這就是遊戲的全部內容。
+
+所以當你發現一個比你聰明的人時,就順其自然吧。你的管理職責在很大程度上變成
+了「聽起來像是個好主意——去嘗試吧」,或者「聽起來不錯,但是XXX呢?」「。第二個版
+本尤其是一個很好的方法,要麼學習一些關於「XXX」的新東西,要麼通過指出一些聰明
+人沒有想到的東西來顯得更具管理性。無論哪種情況,你都會贏。
+
+要注意的一件事是認識到一個領域的偉大不一定會轉化爲其他領域。所以你可能會向
+特定的方向刺激人們,但讓我們面對現實吧,他們可能擅長他們所做的事情,而且對
+其他事情都很差勁。好消息是,人們往往會自然而然地重拾他們擅長的東西,所以當
+你向某個方向刺激他們時,你並不是在做不可逆轉的事情,只是不要用力推。
+
+4)責備
+-------
+
+事情會出問題的,人們希望去責備人。貼標籤,你就是受責備的人。
+
+事實上,接受責備並不難,尤其是當人們意識到這不 **全是** 你的過錯時。這讓我
+們找到了承擔責任的最佳方式:爲別人承擔這件事。你會感覺很好,他們會感覺很好,
+沒有受到指責. 那誰,失去了他們的全部36GB色情收藏的人,因爲你的無能將勉強承
+認,你至少沒有試圖逃避責任。
+
+然後讓真正搞砸了的開發人員(如果你能找到他們)私下知道他們搞砸了。不僅是爲
+了將來可以避免,而且爲了讓他們知道他們欠你一個人情。而且,也許更重要的是,
+他們也可能是能夠解決問題的人。因爲,讓我們面對現實吧,肯定不是你。
+
+承擔責任也是你首先成爲管理者的原因。這是讓人們信任你,讓你獲得潛在的榮耀的
+一部分,因爲你就是那個會說「我搞砸了」的人。如果你已經遵循了以前的規則,你現
+在已經很擅長說了。
+
+5)應避免的事情
+---------------
+
+有一件事人們甚至比被稱爲「笨蛋」更討厭,那就是在一個神聖的聲音中被稱爲「笨蛋」。
+第一個你可以道歉,第二個你不會真正得到機會。即使你做得很好,他們也可能不再
+傾聽。
+
+我們都認爲自己比別人強,這意味著當別人裝腔作勢時,這會讓我們很惱火。你也許
+在道德和智力上比你周圍的每個人都優越,但不要試圖太明顯,除非你真的打算激怒
+某人 [#cnf3]_
+
+同樣,不要對事情太客氣或太微妙。禮貌很容易落得落花流水,把問題隱藏起來,
+正如他們所說,「在網際網路上,沒人能聽到你的含蓄。」用一個鈍器把這一點錘進去,
+因爲你不能真的依靠別人來獲得你的觀點。
+
+一些幽默可以幫助緩和直率和道德化。過度到荒謬的地步,可以灌輸一個觀點,而不
+會讓接受者感到痛苦,他們只是認爲你是愚蠢的。因此,它可以幫助我們擺脫對批評
+的個人心理障礙。
+
+.. [#cnf3] 提示:與你的工作沒有直接關係的網絡新聞組是消除你對他人不滿的好
+ 方法。偶爾寫些侮辱性的帖子,打個噴嚏,讓你的情緒得到淨化。別把牢騷帶回家
+
+6)爲什麼是我?
+---------------
+
+既然你的主要責任似乎是爲別人的錯誤承擔責任,並且讓別人痛苦地明白你是不稱職
+的,那麼顯而易見的問題之一就變成了爲什麼首先要這樣做。
+
+首先,雖然你可能會或可能不會聽到十幾歲女孩(或男孩,讓我們不要在這裡評判或
+性別歧視)敲你的更衣室門,你會得到一個巨大的個人成就感爲「負責」。別介意你真
+的在領導別人,你要跟上別人,儘可能快地追趕他們。每個人都會認爲你是負責人。
+
+如果你可以做到這個, 這是個偉大的工作!
+
diff --git a/Documentation/translations/zh_TW/process/programming-language.rst b/Documentation/translations/zh_TW/process/programming-language.rst
new file mode 100644
index 000000000000..54e3699eadf8
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/programming-language.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+.. _tw_programming_language:
+
+程序設計語言
+============
+
+內核是用C語言 :ref:`c-language <tw_c-language>` 編寫的。更準確地說,內核通常是用 :ref:`gcc <tw_gcc>`
+在 ``-std=gnu89`` :ref:`gcc-c-dialect-options <tw_gcc-c-dialect-options>` 下編譯的:ISO C90的 GNU 方言(
+包括一些C99特性)
+
+這種方言包含對語言 :ref:`gnu-extensions <tw_gnu-extensions>` 的許多擴展,當然,它們許多都在內核中使用。
+
+對於一些體系結構,有一些使用 :ref:`clang <tw_clang>` 和 :ref:`icc <tw_icc>` 編譯內核
+的支持,儘管在編寫此文檔時還沒有完成,仍需要第三方補丁。
+
+屬性
+----
+
+在整個內核中使用的一個常見擴展是屬性(attributes) :ref:`gcc-attribute-syntax <tw_gcc-attribute-syntax>`
+屬性允許將實現定義的語義引入語言實體(如變量、函數或類型),而無需對語言進行
+重大的語法更改(例如添加新關鍵字) :ref:`n2049 <tw_n2049>`
+
+在某些情況下,屬性是可選的(即不支持這些屬性的編譯器仍然應該生成正確的代碼,
+即使其速度較慢或執行的編譯時檢查/診斷次數不夠)
+
+內核定義了僞關鍵字(例如, ``pure`` ),而不是直接使用GNU屬性語法(例如,
+``__attribute__((__pure__))`` ),以檢測可以使用哪些關鍵字和/或縮短代碼, 具體
+請參閱 ``include/linux/compiler_attributes.h``
+
+.. _tw_c-language:
+
+c-language
+ http://www.open-std.org/jtc1/sc22/wg14/www/standards
+
+.. _tw_gcc:
+
+gcc
+ https://gcc.gnu.org
+
+.. _tw_clang:
+
+clang
+ https://clang.llvm.org
+
+.. _tw_icc:
+
+icc
+ https://software.intel.com/en-us/c-compilers
+
+.. _tw_gcc-c-dialect-options:
+
+c-dialect-options
+ https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+
+.. _tw_gnu-extensions:
+
+gnu-extensions
+ https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+
+.. _tw_gcc-attribute-syntax:
+
+gcc-attribute-syntax
+ https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+
+.. _tw_n2049:
+
+n2049
+ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+
diff --git a/Documentation/translations/zh_TW/process/stable-api-nonsense.rst b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
new file mode 100644
index 000000000000..22caa5b8d422
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
@@ -0,0 +1,159 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_api_nonsense:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-api-nonsense.rst
+ <stable_api_nonsense>`
+
+譯者::
+
+ 中文版維護者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+ 中文版翻譯者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+ 中文版校譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 內核驅動接口
+==================
+
+寫作本文檔的目的,是爲了解釋爲什麼Linux既沒有二進位內核接口,也沒有穩定
+的內核接口。這裡所說的內核接口,是指內核里的接口,而不是內核和用戶空間
+的接口。內核到用戶空間的接口,是提供給應用程式使用的系統調用,系統調用
+在歷史上幾乎沒有過變化,將來也不會有變化。我有一些老應用程式是在0.9版本
+或者更早版本的內核上編譯的,在使用2.6版本內核的Linux發布上依然用得很好
+。用戶和應用程式作者可以將這個接口看成是穩定的。
+
+
+執行綱要
+--------
+
+你也許以爲自己想要穩定的內核接口,但是你不清楚你要的實際上不是它。你需
+要的其實是穩定的驅動程序,而你只有將驅動程序放到公版內核的原始碼樹里,
+才有可能達到這個目的。而且這樣做還有很多其它好處,正是因爲這些好處使得
+Linux能成爲強壯,穩定,成熟的作業系統,這也是你最開始選擇Linux的原因。
+
+
+入門
+-----
+
+只有那些寫驅動程序的「怪人」才會擔心內核接口的改變,對廣大用戶來說,既
+看不到內核接口,也不需要去關心它。
+
+首先,我不打算討論關於任何非GPL許可的內核驅動的法律問題,這些非GPL許可
+的驅動程序包括不公開原始碼,隱藏原始碼,二進位或者是用原始碼包裝,或者
+是其它任何形式的不能以GPL許可公開原始碼的驅動程序。如果有法律問題,請咨
+詢律師,我只是一個程式設計師,所以我只打算探討技術問題(不是小看法律問題,
+法律問題很實際,並且需要一直關注)。
+
+既然只談技術問題,我們就有了下面兩個主題:二進位內核接口和穩定的內核源
+代碼接口。這兩個問題是互相關聯的,讓我們先解決掉二進位接口的問題。
+
+
+二進位內核接口
+--------------
+假如我們有一個穩定的內核原始碼接口,那麼自然而然的,我們就擁有了穩定的
+二進位接口,是這樣的嗎?錯。讓我們看看關於Linux內核的幾點事實:
+
+ - 取決於所用的C編譯器的版本,不同的內核數據結構里的結構體的對齊方
+ 式會有差別,代碼中不同函數的表現形式也不一樣(函數是不是被inline
+ 編譯取決於編譯器行爲)。不同的函數的表現形式並不重要,但是數據
+ 結構內部的對齊方式很關鍵。
+
+ - 取決於內核的配置選項,不同的選項會讓內核的很多東西發生改變:
+
+ - 同一個結構體可能包含不同的成員變量
+ - 有的函數可能根本不會被實現(比如編譯的時候沒有選擇SMP支持
+ 一些鎖函數就會被定義成空函數)。
+ - 內核使用的內存會以不同的方式對齊,這取決於不同的內核配置選
+ 項。
+
+ - Linux可以在很多的不同體系結構的處理器上運行。在某個體系結構上編
+ 譯好的二進位驅動程序,不可能在另外一個體系結構上正確的運行。
+
+對於一個特定的內核,滿足這些條件並不難,使用同一個C編譯器和同樣的內核配
+置選項來編譯驅動程序模塊就可以了。這對於給一個特定Linux發布的特定版本提
+供驅動程序,是完全可以滿足需求的。但是如果你要給不同發布的不同版本都發
+布一個驅動程序,就需要在每個發布上用不同的內核設置參數都編譯一次內核,
+這簡直跟噩夢一樣。而且還要注意到,每個Linux發布還提供不同的Linux內核,
+這些內核都針對不同的硬體類型進行了優化(有很多種不同的處理器,還有不同
+的內核設置選項)。所以每發布一次驅動程序,都需要提供很多不同版本的內核
+模塊。
+
+相信我,如果你真的要採取這種發布方式,一定會慢慢瘋掉,我很久以前就有過
+深刻的教訓...
+
+
+穩定的內核原始碼接口
+--------------------
+
+如果有人不將他的內核驅動程序,放入公版內核的原始碼樹,而又想讓驅動程序
+一直保持在最新的內核中可用,那麼這個話題將會變得沒完沒了。
+內核開發是持續而且快節奏的,從來都不會慢下來。內核開發人員在當前接口中
+找到bug,或者找到更好的實現方式。一旦發現這些,他們就很快會去修改當前的
+接口。修改接口意味著,函數名可能會改變,結構體可能被擴充或者刪減,函數
+的參數也可能發生改變。一旦接口被修改,內核中使用這些接口的地方需要同時
+修正,這樣才能保證所有的東西繼續工作。
+
+舉一個例子,內核的USB驅動程序接口在USB子系統的整個生命周期中,至少經歷
+了三次重寫。這些重寫解決以下問題:
+
+ - 把數據流從同步模式改成非同步模式,這個改動減少了一些驅動程序的
+ 複雜度,提高了所有USB驅動程序的吞吐率,這樣幾乎所有的USB設備都
+ 能以最大速率工作了。
+ - 修改了USB核心代碼中爲USB驅動分配數據包內存的方式,所有的驅動都
+ 需要提供更多的參數給USB核心,以修正了很多已經被記錄在案的死鎖。
+
+這和一些封閉原始碼的作業系統形成鮮明的對比,在那些作業系統上,不得不額
+外的維護舊的USB接口。這導致了一個可能性,新的開發者依然會不小心使用舊的
+接口,以不恰當的方式編寫代碼,進而影響到作業系統的穩定性。
+在上面的例子中,所有的開發者都同意這些重要的改動,在這樣的情況下修改代
+價很低。如果Linux保持一個穩定的內核原始碼接口,那麼就得創建一個新的接口
+;舊的,有問題的接口必須一直維護,給Linux USB開發者帶來額外的工作。既然
+所有的Linux USB驅動的作者都是利用自己的時間工作,那麼要求他們去做毫無意
+義的免費額外工作,是不可能的。
+安全問題對Linux來說十分重要。一個安全問題被發現,就會在短時間內得到修
+正。在很多情況下,這將導致Linux內核中的一些接口被重寫,以從根本上避免安
+全問題。一旦接口被重寫,所有使用這些接口的驅動程序,必須同時得到修正,
+以確定安全問題已經得到修復並且不可能在未來還有同樣的安全問題。如果內核
+內部接口不允許改變,那麼就不可能修復這樣的安全問題,也不可能確認這樣的
+安全問題以後不會發生。
+開發者一直在清理內核接口。如果一個接口沒有人在使用了,它就會被刪除。這
+樣可以確保內核儘可能的小,而且所有潛在的接口都會得到儘可能完整的測試
+(沒有人使用的接口是不可能得到良好的測試的)。
+
+
+要做什麼
+--------
+
+如果你寫了一個Linux內核驅動,但是它還不在Linux原始碼樹里,作爲一個開發
+者,你應該怎麼做?爲每個發布的每個版本提供一個二進位驅動,那簡直是一個
+噩夢,要跟上永遠處於變化之中的內核接口,也是一件辛苦活。
+很簡單,讓你的驅動進入內核原始碼樹(要記得我們在談論的是以GPL許可發行
+的驅動,如果你的代碼不符合GPL,那麼祝你好運,你只能自己解決這個問題了,
+你這個吸血鬼<把Andrew和Linus對吸血鬼的定義連結到這裡>)。當你的代碼加入
+公版內核原始碼樹之後,如果一個內核接口改變,你的驅動會直接被修改接口的
+那個人修改。保證你的驅動永遠都可以編譯通過,並且一直工作,你幾乎不需要
+做什麼事情。
+
+把驅動放到內核原始碼樹里會有很多的好處:
+
+ - 驅動的質量會提升,而維護成本(對原始作者來說)會下降。
+ - 其他人會給驅動添加新特性。
+ - 其他人會找到驅動中的bug並修復。
+ - 其他人會在驅動中找到性能優化的機會。
+ - 當外部的接口的改變需要修改驅動程序的時候,其他人會修改驅動程序
+ - 不需要聯繫任何發行商,這個驅動會自動的隨著所有的Linux發布一起發
+ 布。
+
+和別的作業系統相比,Linux爲更多不同的設備提供現成的驅動,而且能在更多不
+同體系結構的處理器上支持這些設備。這個經過考驗的開發模式,必然是錯不了
+的 :)
+
+感謝
+----
+感謝 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
+Robert Love, and Nishanth Aravamudan 對於本文檔早期版本的評審和建議。
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/stable-kernel-rules.rst b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
new file mode 100644
index 000000000000..9bb0d9b4f3ac
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
@@ -0,0 +1,68 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_kernel_rules:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+ 中文版維護者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+ 中文版翻譯者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+ 中文版校譯者:
+ - 李陽 Li Yang <leoyang.li@nxp.com>
+ - Kangkai Yin <e12051@motorola.com>
+ - 胡皓文 Hu Haowen <src.res@email.cn>
+
+所有你想知道的事情 - 關於linux穩定版發布
+========================================
+
+關於Linux 2.6穩定版發布,所有你想知道的事情。
+
+關於哪些類型的補丁可以被接收進入穩定版代碼樹,哪些不可以的規則:
+----------------------------------------------------------------
+
+ - 必須是顯而易見的正確,並且經過測試的。
+ - 連同上下文,不能大於100行。
+ - 必須只修正一件事情。
+ - 必須修正了一個給大家帶來麻煩的真正的bug(不是「這也許是一個問題...」
+ 那樣的東西)。
+ - 必須修正帶來如下後果的問題:編譯錯誤(對被標記爲CONFIG_BROKEN的例外),
+ 內核崩潰,掛起,數據損壞,真正的安全問題,或者一些類似「哦,這不
+ 好」的問題。簡短的說,就是一些致命的問題。
+ - 沒有「理論上的競爭條件」,除非能給出競爭條件如何被利用的解釋。
+ - 不能存在任何的「瑣碎的」修正(拼寫修正,去掉多餘空格之類的)。
+ - 必須被相關子系統的維護者接受。
+ - 必須遵循Documentation/translations/zh_TW/process/submitting-patches.rst里的規則。
+
+向穩定版代碼樹提交補丁的過程:
+------------------------------
+
+ - 在確認了補丁符合以上的規則後,將補丁發送到stable@vger.kernel.org。
+ - 如果補丁被接受到隊列里,發送者會收到一個ACK回復,如果沒有被接受,收
+ 到的是NAK回復。回復需要幾天的時間,這取決於開發者的時間安排。
+ - 被接受的補丁會被加到穩定版本隊列里,等待其他開發者的審查。
+ - 安全方面的補丁不要發到這個列表,應該發送到security@kernel.org。
+
+審查周期:
+----------
+
+ - 當穩定版的維護者決定開始一個審查周期,補丁將被發送到審查委員會,以
+ 及被補丁影響的領域的維護者(除非提交者就是該領域的維護者)並且抄送
+ 到linux-kernel郵件列表。
+ - 審查委員會有48小時的時間,用來決定給該補丁回復ACK還是NAK。
+ - 如果委員會中有成員拒絕這個補丁,或者linux-kernel列表上有人反對這個
+ 補丁,並提出維護者和審查委員會之前沒有意識到的問題,補丁會從隊列中
+ 丟棄。
+ - 在審查周期結束的時候,那些得到ACK回應的補丁將會被加入到最新的穩定版
+ 發布中,一個新的穩定版發布就此產生。
+ - 安全性補丁將從內核安全小組那裡直接接收到穩定版代碼樹中,而不是通過
+ 通常的審查周期。請聯繫內核安全小組以獲得關於這個過程的更多細節。
+
+審查委員會:
+------------
+ - 由一些自願承擔這項任務的內核開發者,和幾個非志願的組成。
+
diff --git a/Documentation/translations/zh_TW/process/submit-checklist.rst b/Documentation/translations/zh_TW/process/submit-checklist.rst
new file mode 100644
index 000000000000..ff2f89cba83f
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submit-checklist.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+ Hu Haowen <src.res@email.cn>
+
+.. _tw_submitchecklist:
+
+Linux內核補丁提交清單
+~~~~~~~~~~~~~~~~~~~~~
+
+如果開發人員希望看到他們的內核補丁提交更快地被接受,那麼他們應該做一些基本
+的事情。
+
+這些都是在
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和其他有關提交Linux內核補丁的文檔中提供的。
+
+1) 如果使用工具,則包括定義/聲明該工具的文件。不要依賴於其他頭文件拉入您使用
+ 的頭文件。
+
+2) 乾淨的編譯:
+
+ a) 使用適用或修改的 ``CONFIG`` 選項 ``=y``、``=m`` 和 ``=n`` 。沒有GCC
+ 警告/錯誤,沒有連結器警告/錯誤。
+
+ b) 通過allnoconfig、allmodconfig
+
+ c) 使用 ``O=builddir`` 時可以成功編譯
+
+3) 通過使用本地交叉編譯工具或其他一些構建場在多個CPU體系結構上構建。
+
+4) PPC64是一種很好的交叉編譯檢查體系結構,因爲它傾向於對64位的數使用無符號
+ 長整型。
+
+5) 如下所述 :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`.
+ 檢查您的補丁是否爲常規樣式。在提交( ``scripts/check patch.pl`` )之前,
+ 使用補丁樣式檢查器檢查是否有輕微的衝突。您應該能夠處理您的補丁中存在的所有
+ 違規行爲。
+
+6) 任何新的或修改過的 ``CONFIG`` 選項都不會弄髒配置菜單,並默認爲關閉,除非
+ 它們符合 ``Documentation/kbuild/kconfig-language.rst`` 中記錄的異常條件,
+ 菜單屬性:默認值.
+
+7) 所有新的 ``kconfig`` 選項都有幫助文本。
+
+8) 已仔細審查了相關的 ``Kconfig`` 組合。這很難用測試來糾正——腦力在這裡是有
+ 回報的。
+
+9) 用 sparse 檢查乾淨。
+
+10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 並修復他們發現的任何
+ 問題。
+
+ .. note::
+
+ ``checkstack`` 並沒有明確指出問題,但是任何一個在堆棧上使用超過512
+ 字節的函數都可以進行更改。
+
+11) 包括 :ref:`kernel-doc <kernel_doc>` 內核文檔以記錄全局內核API。(靜態函數
+ 不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 檢查
+ :ref:`kernel-doc <kernel_doc>` 並修復任何問題。
+
+12) 通過以下選項同時啓用的測試 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+ ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
+ ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
+ ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``
+
+13) 已經過構建和運行時測試,包括有或沒有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``.
+
+14) 如果補丁程序影響IO/磁碟等:使用或不使用 ``CONFIG_LBDAF`` 進行測試。
+
+15) 所有代碼路徑都已在啓用所有lockdep功能的情況下運行。
+
+16) 所有新的/proc條目都記錄在 ``Documentation/``
+
+17) 所有新的內核引導參數都記錄在
+ Documentation/admin-guide/kernel-parameters.rst 中。
+
+18) 所有新的模塊參數都記錄在 ``MODULE_PARM_DESC()``
+
+19) 所有新的用戶空間接口都記錄在 ``Documentation/ABI/`` 中。有關詳細信息,
+ 請參閱 ``Documentation/ABI/README`` 。更改用戶空間接口的補丁應該抄送
+ linux-api@vger.kernel.org。
+
+20) 已通過至少注入slab和page分配失敗進行檢查。請參閱 ``Documentation/fault-injection/``
+ 如果新代碼是實質性的,那麼添加子系統特定的故障注入可能是合適的。
+
+21) 新添加的代碼已經用 ``gcc -W`` 編譯(使用 ``make EXTRA-CFLAGS=-W`` )。這
+ 將產生大量噪聲,但對於查找諸如「警告:有符號和無符號之間的比較」之類的錯誤
+ 很有用。
+
+22) 在它被合併到-mm補丁集中之後進行測試,以確保它仍然與所有其他排隊的補丁以
+ 及VM、VFS和其他子系統中的各種更改一起工作。
+
+23) 所有內存屏障例如 ``barrier()``, ``rmb()``, ``wmb()`` 都需要原始碼中的注
+ 釋來解釋它們正在執行的操作及其原因的邏輯。
+
+24) 如果補丁添加了任何ioctl,那麼也要更新 ``Documentation/userspace-api/ioctl/ioctl-number.rst``
+
+25) 如果修改後的原始碼依賴或使用與以下 ``Kconfig`` 符號相關的任何內核API或
+ 功能,則在禁用相關 ``Kconfig`` 符號和/或 ``=m`` (如果該選項可用)的情況
+ 下測試以下多個構建[並非所有這些都同時存在,只是它們的各種/隨機組合]:
+
+ ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+ ``CONFIG_NET``, ``CONFIG_INET=n`` (但是後者伴隨 ``CONFIG_NET=y``).
+
diff --git a/Documentation/translations/zh_TW/process/submitting-drivers.rst b/Documentation/translations/zh_TW/process/submitting-drivers.rst
new file mode 100644
index 000000000000..2fdd742318ba
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-drivers.rst
@@ -0,0 +1,164 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingdrivers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-drivers.rst
+ <submittingdrivers>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+ 中文版維護者: 李陽 Li Yang <leoyang.li@nxp.com>
+ 中文版翻譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+ 中文版校譯者: 陳琦 Maggie Chen <chenqi@beyondsoft.com>
+ 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+ 張巍 Zhang Wei <wezhang@outlook.com>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+如何向 Linux 內核提交驅動程序
+=============================
+
+這篇文檔將會解釋如何向不同的內核源碼樹提交設備驅動程序。請注意,如果你感
+興趣的是顯卡驅動程序,你也許應該訪問 XFree86 項目(https://www.xfree86.org/)
+和/或 X.org 項目 (https://x.org)。
+
+另請參閱 Documentation/translations/zh_TW/process/submitting-patches.rst 文檔。
+
+
+分配設備號
+----------
+
+塊設備和字符設備的主設備號與從設備號是由 Linux 命名編號分配權威 LANANA(
+現在是 Torben Mathiasen)負責分配。申請的網址是 https://www.lanana.org/。
+即使不準備提交到主流內核的設備驅動也需要在這裡分配設備號。有關詳細信息,
+請參閱 Documentation/admin-guide/devices.rst。
+
+如果你使用的不是已經分配的設備號,那麼當你提交設備驅動的時候,它將會被強
+制分配一個新的設備號,即便這個設備號和你之前發給客戶的截然不同。
+
+設備驅動的提交對象
+------------------
+
+Linux 2.0:
+ 此內核源碼樹不接受新的驅動程序。
+
+Linux 2.2:
+ 此內核源碼樹不接受新的驅動程序。
+
+Linux 2.4:
+ 如果所屬的代碼領域在內核的 MAINTAINERS 文件中列有一個總維護者,
+ 那麼請將驅動程序提交給他。如果此維護者沒有回應或者你找不到恰當的
+ 維護者,那麼請聯繫 Willy Tarreau <w@1wt.eu>。
+
+Linux 2.6:
+ 除了遵循和 2.4 版內核同樣的規則外,你還需要在 linux-kernel 郵件
+ 列表上跟蹤最新的 API 變化。向 Linux 2.6 內核提交驅動的頂級聯繫人
+ 是 Andrew Morton <akpm@linux-foundation.org>。
+
+決定設備驅動能否被接受的條件
+----------------------------
+
+許可: 代碼必須使用 GNU 通用公開許可證 (GPL) 提交給 Linux,但是
+ 我們並不要求 GPL 是唯一的許可。你或許會希望同時使用多種
+ 許可證發布,如果希望驅動程序可以被其他開源社區(比如BSD)
+ 使用。請參考 include/linux/module.h 文件中所列出的可被
+ 接受共存的許可。
+
+版權: 版權所有者必須同意使用 GPL 許可。最好提交者和版權所有者
+ 是相同個人或實體。否則,必需列出授權使用 GPL 的版權所有
+ 人或實體,以備驗證之需。
+
+接口: 如果你的驅動程序使用現成的接口並且和其他同類的驅動程序行
+ 爲相似,而不是去發明無謂的新接口,那麼它將會更容易被接受。
+ 如果你需要一個 Linux 和 NT 的通用驅動接口,那麼請在用
+ 戶空間實現它。
+
+代碼: 請使用 Documentation/process/coding-style.rst 中所描述的 Linux 代碼風
+ 格。如果你的某些代碼段(例如那些與 Windows 驅動程序包共
+ 享的代碼段)需要使用其他格式,而你卻只希望維護一份代碼,
+ 那麼請將它們很好地區分出來,並且註明原因。
+
+可移植性: 請注意,指針並不永遠是 32 位的,不是所有的計算機都使用小
+ 尾模式 (little endian) 存儲數據,不是所有的人都擁有浮點
+ 單元,不要隨便在你的驅動程序里嵌入 x86 彙編指令。只能在
+ x86 上運行的驅動程序一般是不受歡迎的。雖然你可能只有 x86
+ 硬體,很難測試驅動程序在其他平台上是否可用,但是確保代碼
+ 可以被輕鬆地移植卻是很簡單的。
+
+清晰度: 做到所有人都能修補這個驅動程序將會很有好處,因爲這樣你將
+ 會直接收到修復的補丁而不是 bug 報告。如果你提交一個試圖
+ 隱藏硬體工作機理的驅動程序,那麼它將會被扔進廢紙簍。
+
+電源管理: 因爲 Linux 正在被很多行動裝置和桌面系統使用,所以你的驅
+ 動程序也很有可能被使用在這些設備上。它應該支持最基本的電
+ 源管理,即在需要的情況下實現系統級休眠和喚醒要用到的
+ .suspend 和 .resume 函數。你應該檢查你的驅動程序是否能正
+ 確地處理休眠與喚醒,如果實在無法確認,請至少把 .suspend
+ 函數定義成返回 -ENOSYS(功能未實現)錯誤。你還應該嘗試確
+ 保你的驅動在什麼都不乾的情況下將耗電降到最低。要獲得驅動
+ 程序測試的指導,請參閱
+ Documentation/power/drivers-testing.rst。有關驅動程序電
+ 源管理問題相對全面的概述,請參閱
+ Documentation/driver-api/pm/devices.rst。
+
+管理: 如果一個驅動程序的作者還在進行有效的維護,那麼通常除了那
+ 些明顯正確且不需要任何檢查的補丁以外,其他所有的補丁都會
+ 被轉發給作者。如果你希望成爲驅動程序的聯繫人和更新者,最
+ 好在代碼注釋中寫明並且在 MAINTAINERS 文件中加入這個驅動
+ 程序的條目。
+
+不影響設備驅動能否被接受的條件
+------------------------------
+
+供應商: 由硬體供應商來維護驅動程序通常是一件好事。不過,如果源碼
+ 樹里已經有其他人提供了可穩定工作的驅動程序,那麼請不要期
+ 望「我是供應商」會成爲內核改用你的驅動程序的理由。理想的情
+ 況是:供應商與現有驅動程序的作者合作,構建一個統一完美的
+ 驅動程序。
+
+作者: 驅動程序是由大的 Linux 公司研發還是由你個人編寫,並不影
+ 響其是否能被內核接受。沒有人對內核源碼樹享有特權。只要你
+ 充分了解內核社區,你就會發現這一點。
+
+
+資源列表
+--------
+
+Linux 內核主源碼樹:
+ ftp.??.kernel.org:/pub/linux/kernel/...
+ ?? == 你的國家代碼,例如 "cn"、"us"、"uk"、"fr" 等等
+
+Linux 內核郵件列表:
+ linux-kernel@vger.kernel.org
+ [可通過向majordomo@vger.kernel.org發郵件來訂閱]
+
+Linux 設備驅動程序,第三版(探討 2.6.10 版內核):
+ https://lwn.net/Kernel/LDD3/ (免費版)
+
+LWN.net:
+ 每周內核開發活動摘要 - https://lwn.net/
+
+ 2.6 版中 API 的變更:
+
+ https://lwn.net/Articles/2.6-kernel-api/
+
+ 將舊版內核的驅動程序移植到 2.6 版:
+
+ https://lwn.net/Articles/driver-porting/
+
+內核新手(KernelNewbies):
+ 爲新的內核開發者提供文檔和幫助
+ https://kernelnewbies.org/
+
+Linux USB項目:
+ http://www.linux-usb.org/
+
+寫內核驅動的「不要」(Arjan van de Ven著):
+ http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
+
+內核清潔工 (Kernel Janitor):
+ https://kernelnewbies.org/KernelJanitors
+
diff --git a/Documentation/translations/zh_TW/process/submitting-patches.rst b/Documentation/translations/zh_TW/process/submitting-patches.rst
new file mode 100644
index 000000000000..cdf0b52e4a98
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-patches.rst
@@ -0,0 +1,686 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingpatches:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+
+譯者::
+
+ 中文版維護者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+ 中文版翻譯者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+ 中文版校譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+ 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+
+如何讓你的改動進入內核
+======================
+
+對於想要將改動提交到 Linux 內核的個人或者公司來說,如果不熟悉「規矩」,
+提交的流程會讓人畏懼。本文檔收集了一系列建議,這些建議可以大大的提高你
+的改動被接受的機會.
+
+以下文檔含有大量簡潔的建議, 具體請見:
+:ref:`Documentation/process <development_process_main>`
+同樣,:ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`
+給出在提交代碼前需要檢查的項目的列表。如果你在提交一個驅動程序,那麼
+同時閱讀一下:
+:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+其中許多步驟描述了Git版本控制系統的默認行爲;如果您使用Git來準備補丁,
+您將發現它爲您完成的大部分機械工作,儘管您仍然需要準備和記錄一組合理的
+補丁。一般來說,使用git將使您作爲內核開發人員的生活更輕鬆。
+
+
+0) 獲取當前源碼樹
+-----------------
+
+如果您沒有一個可以使用當前內核原始碼的存儲庫,請使用git獲取一個。您將要
+從主線存儲庫開始,它可以通過以下方式獲取::
+
+ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+但是,請注意,您可能不希望直接針對主線樹進行開發。大多數子系統維護人員運
+行自己的樹,並希望看到針對這些樹準備的補丁。請參見MAINTAINERS文件中子系
+統的 **T:** 項以查找該樹,或者簡單地詢問維護者該樹是否未在其中列出。
+
+仍然可以通過tarballs下載內核版本(如下一節所述),但這是進行內核開發的
+一種困難的方式。
+
+1) "diff -up"
+-------------
+
+使用 "diff -up" 或者 "diff -uprN" 來創建補丁。
+
+所有內核的改動,都是以補丁的形式呈現的,補丁由 diff(1) 生成。創建補丁的
+時候,要確認它是以 "unified diff" 格式創建的,這種格式由 diff(1) 的 '-u'
+參數生成。而且,請使用 '-p' 參數,那樣會顯示每個改動所在的C函數,使得
+產生的補丁容易讀得多。補丁應該基於內核原始碼樹的根目錄,而不是裡邊的任
+何子目錄。
+
+爲一個單獨的文件創建補丁,一般來說這樣做就夠了::
+
+ SRCTREE=linux
+ MYFILE=drivers/net/mydriver.c
+
+ cd $SRCTREE
+ cp $MYFILE $MYFILE.orig
+ vi $MYFILE # make your change
+ cd ..
+ diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+爲多個文件創建補丁,你可以解開一個沒有修改過的內核原始碼樹,然後和你自
+己的代碼樹之間做 diff 。例如::
+
+ MYSRC=/devel/linux
+
+ tar xvfz linux-3.19.tar.gz
+ mv linux-3.19 linux-3.19-vanilla
+ diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
+ linux-3.19-vanilla $MYSRC > /tmp/patch
+
+"dontdiff" 是內核在編譯的時候產生的文件的列表,列表中的文件在 diff(1)
+產生的補丁里會被跳過。
+
+確定你的補丁里沒有包含任何不屬於這次補丁提交的額外文件。記得在用diff(1)
+生成補丁之後,審閱一次補丁,以確保準確。
+
+如果你的改動很散亂,你應該研究一下如何將補丁分割成獨立的部分,將改動分
+割成一系列合乎邏輯的步驟。這樣更容易讓其他內核開發者審核,如果你想你的
+補丁被接受,這是很重要的。請參閱:
+:ref:`tw_split_changes`
+
+如果你用 ``git`` , ``git rebase -i`` 可以幫助你這一點。如果你不用 ``git``,
+``quilt`` <https://savannah.nongnu.org/projects/quilt> 另外一個流行的選擇。
+
+.. _tw_describe_changes:
+
+2) 描述你的改動
+---------------
+
+描述你的問題。無論您的補丁是一行錯誤修復還是5000行新功能,都必須有一個潛在
+的問題激勵您完成這項工作。讓審稿人相信有一個問題值得解決,讓他們讀完第一段
+是有意義的。
+
+描述用戶可見的影響。直接崩潰和鎖定是相當有說服力的,但並不是所有的錯誤都那麼
+明目張胆。即使在代碼審查期間發現了這個問題,也要描述一下您認爲它可能對用戶產
+生的影響。請記住,大多數Linux安裝運行的內核來自二級穩定樹或特定於供應商/產品
+的樹,只從上游精選特定的補丁,因此請包含任何可以幫助您將更改定位到下游的內容:
+觸發的場景、DMESG的摘錄、崩潰描述、性能回歸、延遲尖峯、鎖定等。
+
+量化優化和權衡。如果您聲稱在性能、內存消耗、堆棧占用空間或二進位大小方面有所
+改進,請包括支持它們的數字。但也要描述不明顯的成本。優化通常不是免費的,而是
+在CPU、內存和可讀性之間進行權衡;或者,探索性的工作,在不同的工作負載之間進
+行權衡。請描述優化的預期缺點,以便審閱者可以權衡成本和收益。
+
+一旦問題建立起來,就要詳細地描述一下您實際在做什麼。對於審閱者來說,用簡單的
+英語描述代碼的變化是很重要的,以驗證代碼的行爲是否符合您的意願。
+
+如果您將補丁描述寫在一個表單中,這個表單可以很容易地作爲「提交日誌」放入Linux
+的原始碼管理系統git中,那麼維護人員將非常感謝您。見 :ref:`tw_explicit_in_reply_to`.
+
+每個補丁只解決一個問題。如果你的描述開始變長,這就表明你可能需要拆分你的補丁。
+請見 :ref:`tw_split_changes`
+
+提交或重新提交修補程序或修補程序系列時,請包括完整的修補程序說明和理由。不要
+只說這是補丁(系列)的第幾版。不要期望子系統維護人員引用更早的補丁版本或引用
+URL來查找補丁描述並將其放入補丁中。也就是說,補丁(系列)及其描述應該是獨立的。
+這對維護人員和審查人員都有好處。一些評審者可能甚至沒有收到補丁的早期版本。
+
+描述你在命令語氣中的變化,例如「make xyzzy do frotz」而不是「[這個補丁]make
+xyzzy do frotz」或「[我]changed xyzzy to do frotz」,就好像你在命令代碼庫改變
+它的行爲一樣。
+
+如果修補程序修復了一個記錄的bug條目,請按編號和URL引用該bug條目。如果補丁來
+自郵件列表討論,請給出郵件列表存檔的URL;使用帶有 ``Message-ID`` 的
+https://lkml.kernel.org/ 重定向,以確保連結不會過時。
+
+但是,在沒有外部資源的情況下,儘量讓你的解釋可理解。除了提供郵件列表存檔或
+bug的URL之外,還要總結需要提交補丁的相關討論要點。
+
+如果您想要引用一個特定的提交,不要只引用提交的 SHA-1 ID。還請包括提交的一行
+摘要,以便於審閱者了解它是關於什麼的。例如::
+
+ Commit e21d2170f36602ae2708 ("video: remove unnecessary
+ platform_set_drvdata()") removed the unnecessary
+ platform_set_drvdata(), but left the variable "dev" unused,
+ delete it.
+
+您還應該確保至少使用前12位 SHA-1 ID. 內核存儲庫包含*許多*對象,使與較短的ID
+發生衝突的可能性很大。記住,即使現在不會與您的六個字符ID發生衝突,這種情況
+可能五年後改變。
+
+如果修補程序修復了特定提交中的錯誤,例如,使用 ``git bisct`` ,請使用帶有前
+12個字符SHA-1 ID 的"Fixes:"標記和單行摘要。爲了簡化不要將標記拆分爲多個,
+行、標記不受分析腳本「75列換行」規則的限制。例如::
+
+ Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+
+下列 ``git config`` 設置可以添加讓 ``git log``, ``git show`` 漂亮的顯示格式::
+
+ [core]
+ abbrev = 12
+ [pretty]
+ fixes = Fixes: %h (\"%s\")
+
+.. _tw_split_changes:
+
+3) 拆分你的改動
+---------------
+
+將每個邏輯更改分隔成一個單獨的補丁。
+
+例如,如果你的改動里同時有bug修正和性能優化,那麼把這些改動拆分到兩個或
+者更多的補丁文件中。如果你的改動包含對API的修改,並且修改了驅動程序來適
+應這些新的API,那麼把這些修改分成兩個補丁。
+
+另一方面,如果你將一個單獨的改動做成多個補丁文件,那麼將它們合併成一個
+單獨的補丁文件。這樣一個邏輯上單獨的改動只被包含在一個補丁文件里。
+
+如果有一個補丁依賴另外一個補丁來完成它的改動,那沒問題。簡單的在你的補
+丁描述里指出「這個補丁依賴某補丁」就好了。
+
+在將您的更改劃分爲一系列補丁時,要特別注意確保內核在系列中的每個補丁之後
+都能正常構建和運行。使用 ``git bisect`` 來追蹤問題的開發者可能會在任何時
+候分割你的補丁系列;如果你在中間引入錯誤,他們不會感謝你。
+
+如果你不能將補丁濃縮成更少的文件,那麼每次大約發送出15個,然後等待審查
+和集成。
+
+4) 檢查你的更改風格
+-------------------
+
+檢查您的補丁是否存在基本樣式衝突,詳細信息可在
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中找到。如果不這樣做,只會浪費審稿人的時間,並且會導致你的補丁被拒絕,甚至
+可能沒有被閱讀。
+
+一個重要的例外是在將代碼從一個文件移動到另一個文件時——在這種情況下,您不應
+該在移動代碼的同一個補丁中修改移動的代碼。這清楚地描述了移動代碼和您的更改
+的行爲。這大大有助於審查實際差異,並允許工具更好地跟蹤代碼本身的歷史。
+
+在提交之前,使用補丁樣式檢查程序檢查補丁(scripts/check patch.pl)。不過,
+請注意,樣式檢查程序應該被視爲一個指南,而不是作爲人類判斷的替代品。如果您
+的代碼看起來更好,但有違規行爲,那麼最好不要使用它。
+
+檢查者報告三個級別:
+
+ - ERROR:很可能出錯的事情
+ - WARNING:需要仔細審查的事項
+ - CHECK:需要思考的事情
+
+您應該能夠判斷您的補丁中存在的所有違規行爲。
+
+5) 選擇補丁收件人
+-----------------
+
+您應該總是在任何補丁上複製相應的子系統維護人員,以獲得他們維護的代碼;查看
+維護人員文件和原始碼修訂歷史記錄,以了解這些維護人員是誰。腳本
+scripts/get_Maintainer.pl在這個步驟中非常有用。如果您找不到正在工作的子系統
+的維護人員,那麼Andrew Morton(akpm@linux-foundation.org)將充當最後的維護
+人員。
+
+您通常還應該選擇至少一個郵件列表來接收補丁集的。linux-kernel@vger.kernel.org
+作爲最後一個解決辦法的列表,但是這個列表上的體積已經引起了許多開發人員的拒絕。
+在MAINTAINERS文件中查找子系統特定的列表;您的補丁可能會在那裡得到更多的關注。
+不過,請不要發送垃圾郵件到無關的列表。
+
+許多與內核相關的列表託管在vger.kernel.org上;您可以在
+http://vger.kernel.org/vger-lists.html 上找到它們的列表。不過,也有與內核相關
+的列表託管在其他地方。
+
+不要一次發送超過15個補丁到vger郵件列表!!!!
+
+Linus Torvalds 是決定改動能否進入 Linux 內核的最終裁決者。他的 e-mail
+地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般
+的說,最好別給他發 e-mail。
+
+如果您有修復可利用安全漏洞的補丁,請將該補丁發送到 security@kernel.org。對於
+嚴重的bug,可以考慮短期暫停以允許分銷商向用戶發布補丁;在這種情況下,顯然不應
+將補丁發送到任何公共列表。
+
+修復已發布內核中嚴重錯誤的補丁程序應該指向穩定版維護人員,方法是放這樣的一行::
+
+ Cc: stable@vger.kernel.org
+
+進入補丁的簽准區(注意,不是電子郵件收件人)。除了這個文件之外,您還應該閱讀
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+但是,請注意,一些子系統維護人員希望得出他們自己的結論,即哪些補丁應該被放到
+穩定的樹上。尤其是網絡維護人員,不希望看到單個開發人員在補丁中添加像上面這樣
+的行。
+
+如果更改影響到用戶和內核接口,請向手冊頁維護人員(如維護人員文件中所列)發送
+手冊頁補丁,或至少發送更改通知,以便一些信息進入手冊頁。還應將用戶空間API
+更改複製到 linux-api@vger.kernel.org。
+
+對於小的補丁,你也許會CC到搜集瑣碎補丁的郵件列表(Trivial Patch Monkey)
+trivial@kernel.org,那裡專門收集瑣碎的補丁。下面這樣的補丁會被看作「瑣碎的」
+補丁:
+
+ - 文檔的拼寫修正。
+ - 修正會影響到 grep(1) 的拼寫。
+ - 警告信息修正(頻繁的列印無用的警告是不好的。)
+ - 編譯錯誤修正(代碼邏輯的確是對的,只是編譯有問題。)
+ - 運行時修正(只要真的修正了錯誤。)
+ - 移除使用了被廢棄的函數/宏的代碼(例如 check_region。)
+ - 聯繫方式和文檔修正。
+ - 用可移植的代碼替換不可移植的代碼(即使在體系結構相關的代碼中,既然有
+ - 人拷貝,只要它是瑣碎的)
+ - 任何文件的作者/維護者對該文件的改動(例如 patch monkey 在重傳模式下)
+
+(譯註,關於「瑣碎補丁」的一些說明:因爲原文的這一部分寫得比較簡單,所以不得不
+違例寫一下譯註。"trivial"這個英文單詞的本意是「瑣碎的,不重要的。」但是在這裡
+有稍微有一些變化,例如對一些明顯的NULL指針的修正,屬於運行時修正,會被歸類
+到瑣碎補丁里。雖然NULL指針的修正很重要,但是這樣的修正往往很小而且很容易得到
+檢驗,所以也被歸入瑣碎補丁。瑣碎補丁更精確的歸類應該是
+「simple, localized & easy to verify」,也就是說簡單的,局部的和易於檢驗的。
+trivial@kernel.org郵件列表的目的是針對這樣的補丁,爲提交者提供一個中心,來
+降低提交的門檻。)
+
+6) 沒有 MIME 編碼,沒有連結,沒有壓縮,沒有附件,只有純文本
+-----------------------------------------------------------
+
+Linus 和其他的內核開發者需要閱讀和評論你提交的改動。對於內核開發者來說
+,可以「引用」你的改動很重要,使用一般的 e-mail 工具,他們就可以在你的
+代碼的任何位置添加評論。
+
+因爲這個原因,所有的提交的補丁都是 e-mail 中「內嵌」的。
+
+.. warning::
+ 如果你使用剪切-粘貼你的補丁,小心你的編輯器的自動換行功能破壞你的補丁
+
+不要將補丁作爲 MIME 編碼的附件,不管是否壓縮。很多流行的 e-mail 軟體不
+是任何時候都將 MIME 編碼的附件當作純文本發送的,這會使得別人無法在你的
+代碼中加評論。另外,MIME 編碼的附件會讓 Linus 多花一點時間來處理,這就
+降低了你的改動被接受的可能性。
+
+例外:如果你的郵遞員弄壞了補丁,那麼有人可能會要求你使用mime重新發送補丁
+
+請參閱 :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+以獲取有關配置電子郵件客戶端以使其不受影響地發送修補程序的提示。
+
+7) e-mail 的大小
+----------------
+
+大的改動對郵件列表不合適,對某些維護者也不合適。如果你的補丁,在不壓縮
+的情況下,超過了300kB,那麼你最好將補丁放在一個能通過 internet 訪問的服
+務器上,然後用指向你的補丁的 URL 替代。但是請注意,如果您的補丁超過了
+300kb,那麼它幾乎肯定需要被破壞。
+
+8)回複評審意見
+---------------
+
+你的補丁幾乎肯定會得到評審者對補丁改進方法的評論。您必須對這些評論作出
+回應;讓補丁被忽略的一個好辦法就是忽略審閱者的意見。不會導致代碼更改的
+意見或問題幾乎肯定會帶來注釋或變更日誌的改變,以便下一個評審者更好地了解
+正在發生的事情。
+
+一定要告訴審稿人你在做什麼改變,並感謝他們的時間。代碼審查是一個累人且
+耗時的過程,審查人員有時會變得暴躁。即使在這種情況下,也要禮貌地回應並
+解決他們指出的問題。
+
+9)不要洩氣或不耐煩
+-------------------
+
+提交更改後,請耐心等待。審閱者是忙碌的人,可能無法立即訪問您的修補程序。
+
+曾幾何時,補丁曾在沒有評論的情況下消失在空白中,但開發過程比現在更加順利。
+您應該在一周左右的時間內收到評論;如果沒有收到評論,請確保您已將補丁發送
+到正確的位置。在重新提交或聯繫審閱者之前至少等待一周-在諸如合併窗口之類的
+繁忙時間可能更長。
+
+10)主題中包含 PATCH
+--------------------
+
+由於到linus和linux內核的電子郵件流量很高,通常會在主題行前面加上[PATCH]
+前綴. 這使Linus和其他內核開發人員更容易將補丁與其他電子郵件討論區分開。
+
+11)簽署你的作品-開發者原始認證
+-------------------------------
+
+爲了加強對誰做了何事的追蹤,尤其是對那些透過好幾層的維護者的補丁,我們
+建議在發送出去的補丁上加一個 「sign-off」 的過程。
+
+"sign-off" 是在補丁的注釋的最後的簡單的一行文字,認證你編寫了它或者其他
+人有權力將它作爲開放原始碼的補丁傳遞。規則很簡單:如果你能認證如下信息:
+
+開發者來源證書 1.1
+^^^^^^^^^^^^^^^^^^
+
+對於本項目的貢獻,我認證如下信息:
+
+ (a)這些貢獻是完全或者部分的由我創建,我有權利以文件中指出
+ 的開放原始碼許可證提交它;或者
+ (b)這些貢獻基於以前的工作,據我所知,這些以前的工作受恰當的開放
+ 原始碼許可證保護,而且,根據許可證,我有權提交修改後的貢獻,
+ 無論是完全還是部分由我創造,這些貢獻都使用同一個開放原始碼許可證
+ (除非我被允許用其它的許可證),正如文件中指出的;或者
+ (c)這些貢獻由認證(a),(b)或者(c)的人直接提供給我,而
+ 且我沒有修改它。
+ (d)我理解並同意這個項目和貢獻是公開的,貢獻的記錄(包括我
+ 一起提交的個人記錄,包括 sign-off )被永久維護並且可以和這個項目
+ 或者開放原始碼的許可證同步地再發行。
+
+那麼加入這樣一行::
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+
+使用你的真名(抱歉,不能使用假名或者匿名。)
+
+有人在最後加上標籤。現在這些東西會被忽略,但是你可以這樣做,來標記公司
+內部的過程,或者只是指出關於 sign-off 的一些特殊細節。
+
+如果您是子系統或分支維護人員,有時需要稍微修改收到的補丁,以便合併它們,
+因爲樹和提交者中的代碼不完全相同。如果你嚴格遵守規則(c),你應該要求提交者
+重新發布,但這完全是在浪費時間和精力。規則(b)允許您調整代碼,但是更改一個
+提交者的代碼並讓他認可您的錯誤是非常不禮貌的。要解決此問題,建議在最後一個
+由簽名行和您的行之間添加一行,指示更改的性質。雖然這並不是強制性的,但似乎
+在描述前加上您的郵件和/或姓名(全部用方括號括起來),這足以讓人注意到您對最
+後一分鐘的更改負有責任。例如::
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+ [lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+ Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+如果您維護一個穩定的分支機構,同時希望對作者進行致謝、跟蹤更改、合併修復並
+保護提交者不受投訴,那麼這種做法尤其有用。請注意,在任何情況下都不能更改作者
+的ID(From 頭),因爲它是出現在更改日誌中的標識。
+
+對回合(back-porters)的特別說明:在提交消息的頂部(主題行之後)插入一個補丁
+的起源指示似乎是一種常見且有用的實踐,以便於跟蹤。例如,下面是我們在3.x穩定
+版本中看到的內容::
+
+ Date: Tue Oct 7 07:26:38 2014 -0400
+
+ libata: Un-break ATA blacklist
+
+ commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+
+還有, 這裡是一個舊版內核中的一個回合補丁::
+
+ Date: Tue May 13 22:12:27 2008 +0200
+
+ wireless, airo: waitbusy() won't delay
+
+ [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+12)何時使用Acked-by:,CC:,和Co-Developed by:
+----------------------------------------------
+
+Singed-off-by: 標記表示簽名者參與了補丁的開發,或者他/她在補丁的傳遞路徑中。
+
+如果一個人沒有直接參與補丁的準備或處理,但希望表示並記錄他們對補丁的批准,
+那麼他們可以要求在補丁的變更日誌中添加一個 Acked-by:
+
+Acked-by:通常由受影響代碼的維護者使用,當該維護者既沒有貢獻也沒有轉發補丁時。
+
+Acked-by: 不像簽字人那樣正式。這是一個記錄,確認人至少審查了補丁,並表示接受。
+因此,補丁合併有時會手動將Acker的「Yep,looks good to me」轉換爲 Acked-By:(但
+請注意,通常最好要求一個明確的Ack)。
+
+Acked-by:不一定表示對整個補丁的確認。例如,如果一個補丁影響多個子系統,並且
+有一個:來自一個子系統維護者,那麼這通常表示只確認影響維護者代碼的部分。這裡
+應該仔細判斷。如有疑問,應參考郵件列表檔案中的原始討論。
+
+如果某人有機會對補丁進行評論,但沒有提供此類評論,您可以選擇在補丁中添加 ``Cc:``
+這是唯一一個標籤,它可以在沒有被它命名的人顯式操作的情況下添加,但它應該表明
+這個人是在補丁上抄送的。討論中包含了潛在利益相關方。
+
+Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上工
+作時,它用於將屬性賦予共同作者(除了 From: 所賦予的作者之外)。因爲
+Co-developed-by: 表示作者身份,所以每個共同開發人:必須緊跟在相關合作作者的
+簽名之後。標準的簽核程序要求:標記的簽核順序應儘可能反映補丁的時間歷史,而不
+管作者是通過 From :還是由 Co-developed-by: 共同開發的。值得注意的是,最後一
+個簽字人:必須始終是提交補丁的開發人員。
+
+注意,當作者也是電子郵件標題「發件人:」行中列出的人時,「From: 」 標記是可選的。
+
+作者提交的補丁程序示例::
+
+ <changelog>
+
+ Co-developed-by: First Co-Author <first@coauthor.example.org>
+ Signed-off-by: First Co-Author <first@coauthor.example.org>
+ Co-developed-by: Second Co-Author <second@coauthor.example.org>
+ Signed-off-by: Second Co-Author <second@coauthor.example.org>
+ Signed-off-by: From Author <from@author.example.org>
+
+合作開發者提交的補丁示例::
+
+ From: From Author <from@author.example.org>
+
+ <changelog>
+
+ Co-developed-by: Random Co-Author <random@coauthor.example.org>
+ Signed-off-by: Random Co-Author <random@coauthor.example.org>
+ Signed-off-by: From Author <from@author.example.org>
+ Co-developed-by: Submitting Co-Author <sub@coauthor.example.org>
+ Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>
+
+
+13)使用報告人:、測試人:、審核人:、建議人:、修復人:
+--------------------------------------------------------
+
+Reported-by: 給那些發現錯誤並報告錯誤的人致謝,它希望激勵他們在將來再次幫助
+我們。請注意,如果bug是以私有方式報告的,那麼在使用Reported-by標記之前,請
+先請求權限。
+
+Tested-by: 標記表示補丁已由指定的人(在某些環境中)成功測試。這個標籤通知
+維護人員已經執行了一些測試,爲將來的補丁提供了一種定位測試人員的方法,並確
+保測試人員的信譽。
+
+Reviewed-by:相反,根據審查人的聲明,表明該補丁已被審查並被認爲是可接受的:
+
+
+審查人的監督聲明
+^^^^^^^^^^^^^^^^
+
+通過提供我的 Reviewed-by,我聲明:
+
+ (a) 我已經對這個補丁進行了一次技術審查,以評估它是否適合被包含到
+ 主線內核中。
+
+ (b) 與補丁相關的任何問題、顧慮或問題都已反饋給提交者。我對提交者對
+ 我的評論的回應感到滿意。
+
+ (c) 雖然這一提交可能會改進一些東西,但我相信,此時,(1)對內核
+ 進行了有價值的修改,(2)沒有包含爭論中涉及的已知問題。
+
+ (d) 雖然我已經審查了補丁並認爲它是健全的,但我不會(除非另有明確
+ 說明)作出任何保證或保證它將在任何給定情況下實現其規定的目的
+ 或正常運行。
+
+Reviewed-by 是一種觀點聲明,即補丁是對內核的適當修改,沒有任何遺留的嚴重技術
+問題。任何感興趣的審閱者(完成工作的人)都可以爲一個補丁提供一個 Review-by
+標籤。此標籤用於向審閱者提供致謝,並通知維護者已在修補程序上完成的審閱程度。
+Reviewed-by: 當由已知了解主題區域並執行徹底檢查的審閱者提供時,通常會增加
+補丁進入內核的可能性。
+
+Suggested-by: 表示補丁的想法是由指定的人提出的,並確保將此想法歸功於指定的
+人。請注意,未經許可,不得添加此標籤,特別是如果該想法未在公共論壇上發布。
+這就是說,如果我們勤快地致謝我們的創意者,他們很有希望在未來得到鼓舞,再次
+幫助我們。
+
+Fixes: 指示補丁在以前的提交中修復了一個問題。它可以很容易地確定錯誤的來源,
+這有助於檢查錯誤修復。這個標記還幫助穩定內核團隊確定應該接收修復的穩定內核
+版本。這是指示補丁修復的錯誤的首選方法。請參閱 :ref:`tw_describe_changes`
+描述您的更改以了解更多詳細信息。
+
+.. _tw_the_canonical_patch_format:
+
+12)標準補丁格式
+----------------
+
+本節描述如何格式化補丁本身。請注意,如果您的補丁存儲在 ``Git`` 存儲庫中,則
+可以使用 ``git format-patch`` 進行正確的補丁格式設置。但是,這些工具無法創建
+必要的文本,因此請務必閱讀下面的說明。
+
+標準的補丁,標題行是::
+
+ Subject: [PATCH 001/123] 子系統:一句話概述
+
+標準補丁的信體存在如下部分:
+
+ - 一個 "from" 行指出補丁作者。後跟空行(僅當發送修補程序的人不是作者時才需要)。
+
+ - 解釋的正文,行以75列包裝,這將被複製到永久變更日誌來描述這個補丁。
+
+ - 一個空行
+
+ - 上面描述的「Signed-off-by」 行,也將出現在更改日誌中。
+
+ - 只包含 ``---`` 的標記線。
+
+ - 任何其他不適合放在變更日誌的注釋。
+
+ - 實際補丁( ``diff`` 輸出)。
+
+標題行的格式,使得對標題行按字母序排序非常的容易 - 很多 e-mail 客戶端都
+可以支持 - 因爲序列號是用零填充的,所以按數字排序和按字母排序是一樣的。
+
+e-mail 標題中的「子系統」標識哪個內核子系統將被打補丁。
+
+e-mail 標題中的「一句話概述」扼要的描述 e-mail 中的補丁。「一句話概述」
+不應該是一個文件名。對於一個補丁系列(「補丁系列」指一系列的多個相關補
+丁),不要對每個補丁都使用同樣的「一句話概述」。
+
+記住 e-mail 的「一句話概述」會成爲該補丁的全局唯一標識。它會蔓延到 git
+的改動記錄里。然後「一句話概述」會被用在開發者的討論里,用來指代這個補
+丁。用戶將希望通過 google 來搜索"一句話概述"來找到那些討論這個補丁的文
+章。當人們在兩三個月後使用諸如 ``gitk`` 或 ``git log --oneline`` 之類
+的工具查看數千個補丁時,也會很快看到它。
+
+出於這些原因,概述必須不超過70-75個字符,並且必須描述補丁的更改以及爲
+什麼需要補丁。既要簡潔又要描述性很有挑戰性,但寫得好的概述應該這樣做。
+
+概述的前綴可以用方括號括起來:「Subject: [PATCH <tag>...] <概述>」。標記
+不被視爲概述的一部分,而是描述應該如何處理補丁。如果補丁的多個版本已發
+送出來以響應評審(即「v1,v2,v3」)或「rfc」,以指示評審請求,那麼通用標記
+可能包括版本描述符。如果一個補丁系列中有四個補丁,那麼各個補丁可以這樣
+編號:1/4、2/4、3/4、4/4。這可以確保開發人員了解補丁應用的順序,並且他們
+已經查看或應用了補丁系列中的所有補丁。
+
+一些標題的例子::
+
+ Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+ Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+"From" 行是信體裡的最上面一行,具有如下格式:
+ From: Patch Author <author@example.com>
+
+"From" 行指明在永久改動日誌里,誰會被確認爲作者。如果沒有 "From" 行,那
+麼郵件頭裡的 "From: " 行會被用來決定改動日誌中的作者。
+
+說明的主題將會被提交到永久的原始碼改動日誌里,因此對那些早已經不記得和
+這個補丁相關的討論細節的有能力的讀者來說,是有意義的。包括補丁程序定位
+錯誤的(內核日誌消息、OOPS消息等)症狀,對於搜索提交日誌以尋找適用補丁的人
+尤其有用。如果一個補丁修復了一個編譯失敗,那麼可能不需要包含所有編譯失敗;
+只要足夠讓搜索補丁的人能夠找到它就行了。與概述一樣,既要簡潔又要描述性。
+
+"---" 標記行對於補丁處理工具要找到哪裡是改動日誌信息的結束,是不可缺少
+的。
+
+對於 "---" 標記之後的額外註解,一個好的用途就是用來寫 diffstat,用來顯
+示修改了什麼文件和每個文件都增加和刪除了多少行。diffstat 對於比較大的補
+丁特別有用。其餘那些只是和時刻或者開發者相關的註解,不合適放到永久的改
+動日誌里的,也應該放這裡。
+使用 diffstat的選項 "-p 1 -w 70" 這樣文件名就會從內核原始碼樹的目錄開始
+,不會占用太寬的空間(很容易適合80列的寬度,也許會有一些縮進。)
+
+在後面的參考資料中能看到適當的補丁格式的更多細節。
+
+.. _tw_explicit_in_reply_to:
+
+15) 明確回覆郵件頭(In-Reply-To)
+-------------------------------
+
+手動添加回復補丁的的標題頭(In-Reply_To:) 是有幫助的(例如,使用 ``git send-email`` )
+將補丁與以前的相關討論關聯起來,例如,將bug修復程序連結到電子郵件和bug報告。
+但是,對於多補丁系列,最好避免在回復時使用連結到該系列的舊版本。這樣,
+補丁的多個版本就不會成爲電子郵件客戶端中無法管理的引用序列。如果連結有用,
+可以使用 https://lkml.kernel.org/ 重定向器(例如,在封面電子郵件文本中)
+連結到補丁系列的早期版本。
+
+16) 發送git pull請求
+--------------------
+
+如果您有一系列補丁,那麼讓維護人員通過git pull操作將它們直接拉入子系統存儲
+庫可能是最方便的。但是,請注意,從開發人員那裡獲取補丁比從郵件列表中獲取補
+丁需要更高的信任度。因此,許多子系統維護人員不願意接受請求,特別是來自新的
+未知開發人員的請求。如果有疑問,您可以在封面郵件中使用pull 請求作爲補丁系列
+正常發布的一個選項,讓維護人員可以選擇使用其中之一。
+
+pull 請求的主題行中應該有[Git Pull]。請求本身應該在一行中包含存儲庫名稱和
+感興趣的分支;它應該看起來像::
+
+ Please pull from
+
+ git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+ to get these changes:
+
+
+pull 請求還應該包含一條整體消息,說明請求中將包含什麼,一個補丁本身的 ``Git shortlog``
+以及一個顯示補丁系列整體效果的 ``diffstat`` 。當然,將所有這些信息收集在一起
+的最簡單方法是讓 ``git`` 使用 ``git request-pull`` 命令爲您完成這些工作。
+
+一些維護人員(包括Linus)希望看到來自已簽名提交的請求;這增加了他們對你的
+請求信心。特別是,在沒有簽名標籤的情況下,Linus 不會從像 Github 這樣的公共
+託管站點拉請求。
+
+創建此類簽名的第一步是生成一個 GNRPG 密鑰,並由一個或多個核心內核開發人員對
+其進行簽名。這一步對新開發人員來說可能很困難,但沒有辦法繞過它。參加會議是
+找到可以簽署您的密鑰的開發人員的好方法。
+
+一旦您在Git 中準備了一個您希望有人拉的補丁系列,就用 ``git tag -s`` 創建一
+個簽名標記。這將創建一個新標記,標識該系列中的最後一次提交,並包含用您的私
+鑰創建的簽名。您還可以將changelog樣式的消息添加到標記中;這是一個描述拉請求
+整體效果的理想位置。
+
+如果維護人員將要從中提取的樹不是您正在使用的存儲庫,請不要忘記將已簽名的標記
+顯式推送到公共樹。
+
+生成拉請求時,請使用已簽名的標記作爲目標。這樣的命令可以實現::
+
+ git request-pull master git://my.public.tree/linux.git my-signed-tag
+
+參考文獻
+--------
+
+Andrew Morton, "The perfect patch" (tpp).
+ <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+ <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+ <http://www.kroah.com/log/linux/maintainer.html>
+
+ <http://www.kroah.com/log/linux/maintainer-02.html>
+
+ <http://www.kroah.com/log/linux/maintainer-03.html>
+
+ <http://www.kroah.com/log/linux/maintainer-04.html>
+
+ <http://www.kroah.com/log/linux/maintainer-05.html>
+
+ <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+ <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
+
+Kernel Documentation/process/coding-style.rst:
+ :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+
+Linus Torvalds's mail on the canonical patch format:
+ <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
+
+Andi Kleen, "On submitting kernel patches"
+ Some strategies to get difficult or controversial changes in.
+
+ http://halobates.de/on-submitting-patches.pdf
+
diff --git a/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
new file mode 100644
index 000000000000..097fe80352cb
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
@@ -0,0 +1,110 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_volatile_considered_harmful:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/volatile-considered-harmful.rst
+ <volatile_considered_harmful>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+ 英文版維護者: Jonathan Corbet <corbet@lwn.net>
+ 中文版維護者: 伍鵬 Bryan Wu <bryan.wu@analog.com>
+ 中文版翻譯者: 伍鵬 Bryan Wu <bryan.wu@analog.com>
+ 中文版校譯者: 張漢輝 Eugene Teo <eugeneteo@kernel.sg>
+ 楊瑞 Dave Young <hidave.darkstar@gmail.com>
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+爲什麼不應該使用「volatile」類型
+================================
+
+C程式設計師通常認爲volatile表示某個變量可以在當前執行的線程之外被改變;因此,在內核
+中用到共享數據結構時,常常會有C程式設計師喜歡使用volatile這類變量。換句話說,他們經
+常會把volatile類型看成某種簡易的原子變量,當然它們不是。在內核中使用volatile幾
+乎總是錯誤的;本文檔將解釋爲什麼這樣。
+
+理解volatile的關鍵是知道它的目的是用來消除優化,實際上很少有人真正需要這樣的應
+用。在內核中,程式設計師必須防止意外的並發訪問破壞共享的數據結構,這其實是一個完全
+不同的任務。用來防止意外並發訪問的保護措施,可以更加高效的避免大多數優化相關的
+問題。
+
+像volatile一樣,內核提供了很多原語來保證並發訪問時的數據安全(自旋鎖, 互斥量,內
+存屏障等等),同樣可以防止意外的優化。如果可以正確使用這些內核原語,那麼就沒有
+必要再使用volatile。如果仍然必須使用volatile,那麼幾乎可以肯定在代碼的某處有一
+個bug。在正確設計的內核代碼中,volatile能帶來的僅僅是使事情變慢。
+
+思考一下這段典型的內核代碼::
+
+ spin_lock(&the_lock);
+ do_something_on(&shared_data);
+ do_something_else_with(&shared_data);
+ spin_unlock(&the_lock);
+
+如果所有的代碼都遵循加鎖規則,當持有the_lock的時候,不可能意外的改變shared_data的
+值。任何可能訪問該數據的其他代碼都會在這個鎖上等待。自旋鎖原語跟內存屏障一樣—— 它
+們顯式的用來書寫成這樣 —— 意味著數據訪問不會跨越它們而被優化。所以本來編譯器認爲
+它知道在shared_data裡面將有什麼,但是因爲spin_lock()調用跟內存屏障一樣,會強制編
+譯器忘記它所知道的一切。那麼在訪問這些數據時不會有優化的問題。
+
+如果shared_data被聲名爲volatile,鎖操作將仍然是必須的。就算我們知道沒有其他人正在
+使用它,編譯器也將被阻止優化對臨界區內shared_data的訪問。在鎖有效的同時,
+shared_data不是volatile的。在處理共享數據的時候,適當的鎖操作可以不再需要
+volatile —— 並且是有潛在危害的。
+
+volatile的存儲類型最初是爲那些內存映射的I/O寄存器而定義。在內核里,寄存器訪問也應
+該被鎖保護,但是人們也不希望編譯器「優化」臨界區內的寄存器訪問。內核里I/O的內存訪問
+是通過訪問函數完成的;不贊成通過指針對I/O內存的直接訪問,並且不是在所有體系架構上
+都能工作。那些訪問函數正是爲了防止意外優化而寫的,因此,再說一次,volatile類型不
+是必需的。
+
+另一種引起用戶可能使用volatile的情況是當處理器正忙著等待一個變量的值。正確執行一
+個忙等待的方法是::
+
+ while (my_variable != what_i_want)
+ cpu_relax();
+
+cpu_relax()調用會降低CPU的能量消耗或者讓位於超線程雙處理器;它也作爲內存屏障一樣出
+現,所以,再一次,volatile不是必需的。當然,忙等待一開始就是一種反常規的做法。
+
+在內核中,一些稀少的情況下volatile仍然是有意義的:
+
+ - 在一些體系架構的系統上,允許直接的I/0內存訪問,那麼前面提到的訪問函數可以使用
+ volatile。基本上,每一個訪問函數調用它自己都是一個小的臨界區域並且保證了按照
+ 程式設計師期望的那樣發生訪問操作。
+
+ - 某些會改變內存的內聯彙編代碼雖然沒有什麼其他明顯的附作用,但是有被GCC刪除的可
+ 能性。在彙編聲明中加上volatile關鍵字可以防止這種刪除操作。
+
+ - Jiffies變量是一種特殊情況,雖然每次引用它的時候都可以有不同的值,但讀jiffies
+ 變量時不需要任何特殊的加鎖保護。所以jiffies變量可以使用volatile,但是不贊成
+ 其他跟jiffies相同類型變量使用volatile。Jiffies被認爲是一種「愚蠢的遺留物"
+ (Linus的話)因爲解決這個問題比保持現狀要麻煩的多。
+
+ - 由於某些I/0設備可能會修改連續一致的內存,所以有時,指向連續一致內存的數據結構
+ 的指針需要正確的使用volatile。網絡適配器使用的環狀緩存區正是這類情形的一個例
+ 子,其中適配器用改變指針來表示哪些描述符已經處理過了。
+
+對於大多代碼,上述幾種可以使用volatile的情況都不適用。所以,使用volatile是一種
+bug並且需要對這樣的代碼額外仔細檢查。那些試圖使用volatile的開發人員需要退一步想想
+他們真正想實現的是什麼。
+
+非常歡迎刪除volatile變量的補丁 - 只要證明這些補丁完整的考慮了並發問題。
+
+注釋
+----
+
+[1] https://lwn.net/Articles/233481/
+[2] https://lwn.net/Articles/233482/
+
+致謝
+----
+
+最初由Randy Dunlap推動並作初步研究
+由Jonathan Corbet撰寫
+參考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila,
+H. Peter Anvin,Philipp Hahn和Stefan Richter的意見改善了本檔。
+
diff --git a/Documentation/translations/zh_TW/sparse.txt b/Documentation/translations/zh_TW/sparse.txt
new file mode 100644
index 000000000000..c9acb2c926cb
--- /dev/null
+++ b/Documentation/translations/zh_TW/sparse.txt
@@ -0,0 +1,91 @@
+Chinese translated version of Documentation/dev-tools/sparse.rst
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Traditional Chinese maintainer: Hu Haowen <src.res@email.cn>
+---------------------------------------------------------------------
+Documentation/dev-tools/sparse.rst 的繁體中文翻譯
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或
+者翻譯存在問題,請聯繫繁體中文版維護者。
+
+繁體中文版維護者: 胡皓文 Hu Haowen <src.res@email.cn>
+繁體中文版翻譯者: 胡皓文 Hu Haowen <src.res@email.cn>
+
+以下爲正文
+---------------------------------------------------------------------
+
+Copyright 2004 Linus Torvalds
+Copyright 2004 Pavel Machek <pavel@ucw.cz>
+Copyright 2006 Bob Copeland <me@bobcopeland.com>
+
+使用 sparse 工具做類型檢查
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+"__bitwise" 是一種類型屬性,所以你應該這樣使用它:
+
+ typedef int __bitwise pm_request_t;
+
+ enum pm_request {
+ PM_SUSPEND = (__force pm_request_t) 1,
+ PM_RESUME = (__force pm_request_t) 2
+ };
+
+這樣會使 PM_SUSPEND 和 PM_RESUME 成爲位方式(bitwise)整數(使用"__force"
+是因爲 sparse 會抱怨改變位方式的類型轉換,但是這裡我們確實需要強制進行轉
+換)。而且因爲所有枚舉值都使用了相同的類型,這裡的"enum pm_request"也將
+會使用那個類型做爲底層實現。
+
+而且使用 gcc 編譯的時候,所有的 __bitwise/__force 都會消失,最後在 gcc
+看來它們只不過是普通的整數。
+
+坦白來說,你並不需要使用枚舉類型。上面那些實際都可以濃縮成一個特殊的"int
+__bitwise"類型。
+
+所以更簡單的辦法只要這樣做:
+
+ typedef int __bitwise pm_request_t;
+
+ #define PM_SUSPEND ((__force pm_request_t) 1)
+ #define PM_RESUME ((__force pm_request_t) 2)
+
+現在你就有了嚴格的類型檢查所需要的所有基礎架構。
+
+一個小提醒:常數整數"0"是特殊的。你可以直接把常數零當作位方式整數使用而
+不用擔心 sparse 會抱怨。這是因爲"bitwise"(恰如其名)是用來確保不同位方
+式類型不會被弄混(小尾模式,大尾模式,cpu尾模式,或者其他),對他們來說
+常數"0"確實是特殊的。
+
+獲取 sparse 工具
+~~~~~~~~~~~~~~~~
+
+你可以從 Sparse 的主頁獲取最新的發布版本:
+
+ http://www.kernel.org/pub/linux/kernel/people/josh/sparse/
+
+或者,你也可以使用 git 克隆最新的 sparse 開發版本:
+
+ git://git.kernel.org/pub/scm/linux/kernel/git/josh/sparse.git
+
+一旦你下載了源碼,只要以普通用戶身份運行:
+
+ make
+ make install
+
+它將會被自動安裝到你的 ~/bin 目錄下。
+
+使用 sparse 工具
+~~~~~~~~~~~~~~~~
+
+用"make C=1"命令來編譯內核,會對所有重新編譯的 C 文件使用 sparse 工具。
+或者使用"make C=2"命令,無論文件是否被重新編譯都會對其使用 sparse 工具。
+如果你已經編譯了內核,用後一種方式可以很快地檢查整個源碼樹。
+
+make 的可選變量 CHECKFLAGS 可以用來向 sparse 工具傳遞參數。編譯系統會自
+動向 sparse 工具傳遞 -Wbitwise 參數。
+
diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadget-testing.rst
index 9d6276f82774..c18113077889 100644
--- a/Documentation/usb/gadget-testing.rst
+++ b/Documentation/usb/gadget-testing.rst
@@ -724,18 +724,28 @@ Function-specific configfs interface
The function name to use when creating the function directory is "uac2".
The uac2 function provides these attributes in its function directory:
- =============== ====================================================
- c_chmask capture channel mask
- c_srate capture sampling rate
- c_ssize capture sample size (bytes)
- c_sync capture synchronization type (async/adaptive)
- fb_max maximum extra bandwidth in async mode
- p_chmask playback channel mask
- p_srate playback sampling rate
- p_ssize playback sample size (bytes)
- req_number the number of pre-allocated request for both capture
- and playback
- =============== ====================================================
+ ================ ====================================================
+ c_chmask capture channel mask
+ c_srate capture sampling rate
+ c_ssize capture sample size (bytes)
+ c_sync capture synchronization type (async/adaptive)
+ c_mute_present capture mute control enable
+ c_volume_present capture volume control enable
+ c_volume_min capture volume control min value (in 1/256 dB)
+ c_volume_max capture volume control max value (in 1/256 dB)
+ c_volume_res capture volume control resolution (in 1/256 dB)
+ fb_max maximum extra bandwidth in async mode
+ p_chmask playback channel mask
+ p_srate playback sampling rate
+ p_ssize playback sample size (bytes)
+ p_mute_present playback mute control enable
+ p_volume_present playback volume control enable
+ p_volume_min playback volume control min value (in 1/256 dB)
+ p_volume_max playback volume control max value (in 1/256 dB)
+ p_volume_res playback volume control resolution (in 1/256 dB)
+ req_number the number of pre-allocated request for both capture
+ and playback
+ ================ ====================================================
The attributes have sane default values.
@@ -904,16 +914,26 @@ Function-specific configfs interface
The function name to use when creating the function directory is "uac1".
The uac1 function provides these attributes in its function directory:
- ========== ====================================================
- c_chmask capture channel mask
- c_srate capture sampling rate
- c_ssize capture sample size (bytes)
- p_chmask playback channel mask
- p_srate playback sampling rate
- p_ssize playback sample size (bytes)
- req_number the number of pre-allocated request for both capture
- and playback
- ========== ====================================================
+ ================ ====================================================
+ c_chmask capture channel mask
+ c_srate capture sampling rate
+ c_ssize capture sample size (bytes)
+ c_mute_present capture mute control enable
+ c_volume_present capture volume control enable
+ c_volume_min capture volume control min value (in 1/256 dB)
+ c_volume_max capture volume control max value (in 1/256 dB)
+ c_volume_res capture volume control resolution (in 1/256 dB)
+ p_chmask playback channel mask
+ p_srate playback sampling rate
+ p_ssize playback sample size (bytes)
+ p_mute_present playback mute control enable
+ p_volume_present playback volume control enable
+ p_volume_min playback volume control min value (in 1/256 dB)
+ p_volume_max playback volume control max value (in 1/256 dB)
+ p_volume_res playback volume control resolution (in 1/256 dB)
+ req_number the number of pre-allocated request for both capture
+ and playback
+ ================ ====================================================
The attributes have sane default values.
diff --git a/Documentation/userspace-api/media/cec.h.rst.exceptions b/Documentation/userspace-api/media/cec.h.rst.exceptions
index d83790ccac8e..13de01d9555e 100644
--- a/Documentation/userspace-api/media/cec.h.rst.exceptions
+++ b/Documentation/userspace-api/media/cec.h.rst.exceptions
@@ -140,7 +140,7 @@ ignore define CEC_OP_REC_SEQ_TUESDAY
ignore define CEC_OP_REC_SEQ_WEDNESDAY
ignore define CEC_OP_REC_SEQ_THURSDAY
ignore define CEC_OP_REC_SEQ_FRIDAY
-ignore define CEC_OP_REC_SEQ_SATERDAY
+ignore define CEC_OP_REC_SEQ_SATURDAY
ignore define CEC_OP_REC_SEQ_ONCE_ONLY
ignore define CEC_MSG_CLEAR_DIGITAL_TIMER
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
index 8c6e2a11ed95..976d34445a24 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
@@ -1174,7 +1174,24 @@ enum v4l2_mpeg_video_h264_entropy_mode -
Cyclic intra macroblock refresh. This is the number of continuous
macroblocks refreshed every frame. Each frame a successive set of
macroblocks is refreshed until the cycle completes and starts from
- the top of the frame. Applicable to H264, H263 and MPEG4 encoder.
+ the top of the frame. Setting this control to zero means that
+ macroblocks will not be refreshed. Note that this control will not
+ take effect when ``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD`` control
+ is set to non zero value.
+ Applicable to H264, H263 and MPEG4 encoder.
+
+``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD (integer)``
+ Intra macroblock refresh period. This sets the period to refresh
+ the whole frame. In other words, this defines the number of frames
+ for which the whole frame will be intra-refreshed. An example:
+ setting period to 1 means that the whole frame will be refreshed,
+ setting period to 2 means that the half of macroblocks will be
+ intra-refreshed on frameX and the other half of macroblocks
+ will be refreshed in frameX + 1 and so on. Setting the period to
+ zero means no period is specified.
+ Note that if the client sets this control to non zero value the
+ ``V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB`` control shall be
+ ignored. Applicable to H264 and HEVC encoders.
``V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE (boolean)``
Frame level rate control enable. If this control is disabled then
@@ -3000,6 +3017,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
* - __u8
- ``pic_struct``
-
+ * - __u32
+ - ``slice_segment_addr``
+ -
* - __u8
- ``ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]``
- The list of L0 reference elements as indices in the DPB.
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
index 87698c15c027..b1c2ab2854af 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
@@ -20,25 +20,26 @@ Image Process Control IDs
``V4L2_CID_IMAGE_PROC_CLASS (class)``
The IMAGE_PROC class descriptor.
+.. _v4l2-cid-link-freq:
+
``V4L2_CID_LINK_FREQ (integer menu)``
- Data bus frequency. Together with the media bus pixel code, bus type
- (clock cycles per sample), the data bus frequency defines the pixel
- rate (``V4L2_CID_PIXEL_RATE``) in the pixel array (or possibly
- elsewhere, if the device is not an image sensor). The frame rate can
- be calculated from the pixel clock, image width and height and
- horizontal and vertical blanking. While the pixel rate control may
- be defined elsewhere than in the subdev containing the pixel array,
- the frame rate cannot be obtained from that information. This is
- because only on the pixel array it can be assumed that the vertical
- and horizontal blanking information is exact: no other blanking is
- allowed in the pixel array. The selection of frame rate is performed
- by selecting the desired horizontal and vertical blanking. The unit
- of this control is Hz.
+ The frequency of the data bus (e.g. parallel or CSI-2).
+
+.. _v4l2-cid-pixel-rate:
``V4L2_CID_PIXEL_RATE (64-bit integer)``
- Pixel rate in the source pads of the subdev. This control is
+ Pixel sampling rate in the device's pixel array. This control is
read-only and its unit is pixels / second.
+ Some devices use horizontal and vertical balanking to configure the frame
+ rate. The frame rate can be calculated from the pixel rate, analogue crop
+ rectangle as well as horizontal and vertical blanking. The pixel rate
+ control may be present in a different sub-device than the blanking controls
+ and the analogue crop rectangle configuration.
+
+ The configuration of the frame rate is performed by selecting the desired
+ horizontal and vertical blanking. The unit of this control is Hz.
+
``V4L2_CID_TEST_PATTERN (menu)``
Some capture/display/sensor devices have the capability to generate
test pattern images. These hardware specific test patterns can be
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index dae68e68ca23..a6729c8cf063 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -3357,6 +3357,7 @@ flags which can include the following:
- KVM_GUESTDBG_INJECT_DB: inject DB type exception [x86]
- KVM_GUESTDBG_INJECT_BP: inject BP type exception [x86]
- KVM_GUESTDBG_EXIT_PENDING: trigger an immediate guest exit [s390]
+ - KVM_GUESTDBG_BLOCKIRQ: avoid injecting interrupts/NMI/SMI [x86]
For example KVM_GUESTDBG_USE_SW_BP indicates that software breakpoints
are enabled in memory so we need to ensure breakpoint exceptions are
@@ -5077,7 +5078,7 @@ of bytes successfully copied is returned. If the call completes successfully
then ``length`` is returned.
4.131 KVM_GET_SREGS2
-------------------
+--------------------
:Capability: KVM_CAP_SREGS2
:Architectures: x86
@@ -5090,17 +5091,17 @@ This ioctl (when supported) replaces the KVM_GET_SREGS.
::
-struct kvm_sregs2 {
- /* out (KVM_GET_SREGS2) / in (KVM_SET_SREGS2) */
- struct kvm_segment cs, ds, es, fs, gs, ss;
- struct kvm_segment tr, ldt;
- struct kvm_dtable gdt, idt;
- __u64 cr0, cr2, cr3, cr4, cr8;
- __u64 efer;
- __u64 apic_base;
- __u64 flags;
- __u64 pdptrs[4];
-};
+ struct kvm_sregs2 {
+ /* out (KVM_GET_SREGS2) / in (KVM_SET_SREGS2) */
+ struct kvm_segment cs, ds, es, fs, gs, ss;
+ struct kvm_segment tr, ldt;
+ struct kvm_dtable gdt, idt;
+ __u64 cr0, cr2, cr3, cr4, cr8;
+ __u64 efer;
+ __u64 apic_base;
+ __u64 flags;
+ __u64 pdptrs[4];
+ };
flags values for ``kvm_sregs2``:
@@ -5110,7 +5111,7 @@ flags values for ``kvm_sregs2``:
4.132 KVM_SET_SREGS2
-------------------
+--------------------
:Capability: KVM_CAP_SREGS2
:Architectures: x86
@@ -5201,12 +5202,16 @@ trailing ``'\0'``, is indicated by the ``name_size`` field in the header.
The descriptors block is only needed to be read once for the lifetime of the
file descriptor contains a sequence of ``struct kvm_stats_desc``, each followed
by a string of size ``name_size``.
+::
#define KVM_STATS_TYPE_SHIFT 0
#define KVM_STATS_TYPE_MASK (0xF << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_CUMULATIVE (0x0 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_INSTANT (0x1 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_PEAK (0x2 << KVM_STATS_TYPE_SHIFT)
+ #define KVM_STATS_TYPE_LINEAR_HIST (0x3 << KVM_STATS_TYPE_SHIFT)
+ #define KVM_STATS_TYPE_LOG_HIST (0x4 << KVM_STATS_TYPE_SHIFT)
+ #define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_LOG_HIST
#define KVM_STATS_UNIT_SHIFT 4
#define KVM_STATS_UNIT_MASK (0xF << KVM_STATS_UNIT_SHIFT)
@@ -5214,18 +5219,20 @@ by a string of size ``name_size``.
#define KVM_STATS_UNIT_BYTES (0x1 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_SECONDS (0x2 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_CYCLES (0x3 << KVM_STATS_UNIT_SHIFT)
+ #define KVM_STATS_UNIT_MAX KVM_STATS_UNIT_CYCLES
#define KVM_STATS_BASE_SHIFT 8
#define KVM_STATS_BASE_MASK (0xF << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_POW10 (0x0 << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_POW2 (0x1 << KVM_STATS_BASE_SHIFT)
+ #define KVM_STATS_BASE_MAX KVM_STATS_BASE_POW2
struct kvm_stats_desc {
__u32 flags;
__s16 exponent;
__u16 size;
__u32 offset;
- __u32 unused;
+ __u32 bucket_size;
char name[];
};
@@ -5234,24 +5241,40 @@ by this descriptor. Its endianness is CPU native.
The following flags are supported:
Bits 0-3 of ``flags`` encode the type:
+
* ``KVM_STATS_TYPE_CUMULATIVE``
- The statistics data is cumulative. The value of data can only be increased.
+ The statistics reports a cumulative count. The value of data can only be increased.
Most of the counters used in KVM are of this type.
The corresponding ``size`` field for this type is always 1.
All cumulative statistics data are read/write.
* ``KVM_STATS_TYPE_INSTANT``
- The statistics data is instantaneous. Its value can be increased or
+ The statistics reports an instantaneous value. Its value can be increased or
decreased. This type is usually used as a measurement of some resources,
like the number of dirty pages, the number of large pages, etc.
All instant statistics are read only.
The corresponding ``size`` field for this type is always 1.
* ``KVM_STATS_TYPE_PEAK``
- The statistics data is peak. The value of data can only be increased, and
- represents a peak value for a measurement, for example the maximum number
+ The statistics data reports a peak value, for example the maximum number
of items in a hash table bucket, the longest time waited and so on.
+ The value of data can only be increased.
The corresponding ``size`` field for this type is always 1.
+ * ``KVM_STATS_TYPE_LINEAR_HIST``
+ The statistic is reported as a linear histogram. The number of
+ buckets is specified by the ``size`` field. The size of buckets is specified
+ by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
+ is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
+ bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
+ value.) The bucket value indicates how many samples fell in the bucket's range.
+ * ``KVM_STATS_TYPE_LOG_HIST``
+ The statistic is reported as a logarithmic histogram. The number of
+ buckets is specified by the ``size`` field. The range of the first bucket is
+ [0, 1), while the range of the last bucket is [pow(2, ``size``-2), +INF).
+ Otherwise, The Nth bucket (1 < N < ``size``) covers
+ [pow(2, N-2), pow(2, N-1)). The bucket value indicates how many samples fell
+ in the bucket's range.
Bits 4-7 of ``flags`` encode the unit:
+
* ``KVM_STATS_UNIT_NONE``
There is no unit for the value of statistics data. This usually means that
the value is a simple counter of an event.
@@ -5266,6 +5289,7 @@ Bits 4-7 of ``flags`` encode the unit:
Bits 8-11 of ``flags``, together with ``exponent``, encode the scale of the
unit:
+
* ``KVM_STATS_BASE_POW10``
The scale is based on power of 10. It is used for measurement of time and
CPU clock cycles. For example, an exponent of -9 can be used with
@@ -5282,9 +5306,9 @@ unsigned 64bit data.
The ``offset`` field is the offset from the start of Data Block to the start of
the corresponding statistics data.
-The ``unused`` field is reserved for future support for other types of
-statistics data, like log/linear histogram. Its value is always 0 for the types
-defined above.
+The ``bucket_size`` field is used as a parameter for histogram statistics data.
+It is only used by linear histogram statistics data, specifying the size of a
+bucket.
The ``name`` field is the name string of the statistics data. The name string
starts at the end of ``struct kvm_stats_desc``. The maximum length including
@@ -7213,7 +7237,7 @@ supported in the host. A VMM can check whether the service is
available to the guest on migration.
8.33 KVM_CAP_HYPERV_ENFORCE_CPUID
------------------------------
+---------------------------------
Architectures: x86
diff --git a/Documentation/virt/kvm/locking.rst b/Documentation/virt/kvm/locking.rst
index 88fa495abbac..5d27da356836 100644
--- a/Documentation/virt/kvm/locking.rst
+++ b/Documentation/virt/kvm/locking.rst
@@ -21,6 +21,12 @@ The acquisition orders for mutexes are as follows:
can be taken inside a kvm->srcu read-side critical section,
while kvm->slots_lock cannot.
+- kvm->mn_active_invalidate_count ensures that pairs of
+ invalidate_range_start() and invalidate_range_end() callbacks
+ use the same memslots array. kvm->slots_lock and kvm->slots_arch_lock
+ are taken on the waiting side in install_new_memslots, so MMU notifiers
+ must not take either kvm->slots_lock or kvm->slots_arch_lock.
+
On x86:
- vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock
diff --git a/Documentation/vm/hwpoison.rst b/Documentation/vm/hwpoison.rst
index a5c884293dac..89b5f7a52077 100644
--- a/Documentation/vm/hwpoison.rst
+++ b/Documentation/vm/hwpoison.rst
@@ -180,7 +180,6 @@ Limitations
===========
- Not all page types are supported and never will. Most kernel internal
objects cannot be recovered, only LRU pages for now.
-- Right now hugepage support is missing.
---
Andi Kleen, Oct 2009
diff --git a/MAINTAINERS b/MAINTAINERS
index f3267183e993..a594d5d7edcc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -459,6 +459,12 @@ S: Maintained
W: https://parisc.wiki.kernel.org/index.php/AD1889
F: sound/pci/ad1889.*
+AD5110 ANALOG DEVICES DIGITAL POTENTIOMETERS DRIVER
+M: Mugilraj Dhavachelvan <dmugil2000@gmail.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+F: drivers/iio/potentiometer/ad5110.c
+
AD525X ANALOG DEVICES DIGITAL POTENTIOMETERS DRIVER
M: Michael Hennerich <michael.hennerich@analog.com>
S: Supported
@@ -792,7 +798,7 @@ F: Documentation/devicetree/bindings/i2c/i2c-altera.txt
F: drivers/i2c/busses/i2c-altera.c
ALTERA MAILBOX DRIVER
-M: Ley Foon Tan <ley.foon.tan@intel.com>
+M: Joyce Ooi <joyce.ooi@intel.com>
S: Maintained
F: drivers/mailbox/mailbox-altera.c
@@ -1262,6 +1268,13 @@ L: linux-input@vger.kernel.org
S: Odd fixes
F: drivers/input/mouse/bcm5974.c
+APPLE DART IOMMU DRIVER
+M: Sven Peter <sven@svenpeter.dev>
+L: iommu@lists.linux-foundation.org
+S: Maintained
+F: Documentation/devicetree/bindings/iommu/apple,dart.yaml
+F: drivers/iommu/apple-dart.c
+
APPLE SMC DRIVER
M: Henrik Rydberg <rydberg@bitmath.org>
L: linux-hwmon@vger.kernel.org
@@ -1389,7 +1402,7 @@ F: Documentation/devicetree/bindings/arm/arm,integrator.yaml
F: Documentation/devicetree/bindings/arm/arm,realview.yaml
F: Documentation/devicetree/bindings/arm/arm,versatile.yaml
F: Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml
-F: Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt
+F: Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml
F: Documentation/devicetree/bindings/clock/arm,syscon-icst.yaml
F: Documentation/devicetree/bindings/i2c/i2c-versatile.txt
F: Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
@@ -1483,7 +1496,7 @@ F: drivers/amba/
F: include/linux/amba/bus.h
ARM PRIMECELL PL35X NAND CONTROLLER DRIVER
-M: Miquel Raynal <miquel.raynal@bootlin.com@bootlin.com>
+M: Miquel Raynal <miquel.raynal@bootlin.com>
M: Naga Sureshkumar Relli <nagasure@xilinx.com>
L: linux-mtd@lists.infradead.org
S: Maintained
@@ -1491,11 +1504,11 @@ F: Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
F: drivers/mtd/nand/raw/pl35x-nand-controller.c
ARM PRIMECELL PL35X SMC DRIVER
-M: Miquel Raynal <miquel.raynal@bootlin.com@bootlin.com>
+M: Miquel Raynal <miquel.raynal@bootlin.com>
M: Naga Sureshkumar Relli <nagasure@xilinx.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: Documentation/devicetree/bindings/mtd/arm,pl353-smc.yaml
+F: Documentation/devicetree/bindings/memory-controllers/arm,pl353-smc.yaml
F: drivers/memory/pl353-smc.c
ARM PRIMECELL CLCD PL110 DRIVER
@@ -1697,7 +1710,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
W: https://asahilinux.org
B: https://github.com/AsahiLinux/linux/issues
-C: irc://chat.freenode.net/asahi-dev
+C: irc://irc.oftc.net/asahi-dev
T: git https://github.com/AsahiLinux/linux.git
F: Documentation/devicetree/bindings/arm/apple.yaml
F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
@@ -2017,10 +2030,12 @@ M: Krzysztof Halasa <khalasa@piap.pl>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
+F: Documentation/devicetree/bindings/bus/intel,ixp4xx-expansion-bus-controller.yaml
F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
F: Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
F: arch/arm/mach-ixp4xx/
+F: drivers/bus/intel-ixp4xx-eb.c
F: drivers/clocksource/timer-ixp4xx.c
F: drivers/crypto/ixp4xx_crypto.c
F: drivers/gpio/gpio-ixp4xx.c
@@ -2256,7 +2271,6 @@ F: drivers/iio/adc/ab8500-gpadc.c
F: drivers/mfd/ab8500*
F: drivers/mfd/abx500*
F: drivers/mfd/db8500*
-F: drivers/mfd/dbx500*
F: drivers/pinctrl/nomadik/
F: drivers/rtc/rtc-ab8500.c
F: drivers/rtc/rtc-pl031.c
@@ -3861,7 +3875,7 @@ M: Markus Mayer <mmayer@broadcom.com>
M: bcm-kernel-feedback-list@broadcom.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.txt
+F: Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.yaml
F: drivers/memory/brcmstb_dpfe.c
BROADCOM STB NAND FLASH DRIVER
@@ -4517,6 +4531,7 @@ B: https://github.com/ClangBuiltLinux/linux/issues
C: irc://irc.libera.chat/clangbuiltlinux
F: Documentation/kbuild/llvm.rst
F: include/linux/compiler-clang.h
+F: scripts/Makefile.clang
F: scripts/clang-tools/
K: \b(?i:clang|llvm)\b
@@ -5587,7 +5602,7 @@ M: Lukasz Luba <lukasz.luba@arm.com>
L: linux-pm@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/memory-controllers/exynos5422-dmc.txt
+F: Documentation/devicetree/bindings/memory-controllers/samsung,exynos5422-dmc.yaml
F: drivers/memory/samsung/exynos5422-dmc.c
DME1737 HARDWARE MONITOR DRIVER
@@ -5725,6 +5740,11 @@ F: Documentation/admin-guide/blockdev/
F: drivers/block/drbd/
F: lib/lru_cache.c
+DRIVER COMPONENT FRAMEWORK
+L: dri-devel@lists.freedesktop.org
+F: drivers/base/component.c
+F: include/linux/component.h
+
DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
R: "Rafael J. Wysocki" <rafael@kernel.org>
@@ -5788,7 +5808,7 @@ M: Gerd Hoffmann <kraxel@redhat.com>
L: virtualization@lists.linux-foundation.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
-F: drivers/gpu/drm/bochs/
+F: drivers/gpu/drm/tiny/bochs.c
DRM DRIVER FOR BOE HIMAX8279D PANELS
M: Jerry Han <hanxu5@huaqin.corp-partner.google.com>
@@ -5973,6 +5993,13 @@ S: Maintained
F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml
F: drivers/gpu/drm/panel/panel-raydium-rm67191.c
+DRM DRIVER FOR SAMSUNG DB7430 PANELS
+M: Linus Walleij <linus.walleij@linaro.org>
+S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
+F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
+F: drivers/gpu/drm/panel/panel-samsung-db7430.c
+
DRM DRIVER FOR SITRONIX ST7703 PANELS
M: Guido Günther <agx@sigxcpu.org>
R: Purism Kernel Team <kernel@puri.sm>
@@ -6071,21 +6098,27 @@ F: drivers/gpu/drm/vboxvideo/
DRM DRIVER FOR VMWARE VIRTUAL GPU
M: "VMware Graphics" <linux-graphics-maintainer@vmware.com>
-M: Roland Scheidegger <sroland@vmware.com>
M: Zack Rusin <zackr@vmware.com>
L: dri-devel@lists.freedesktop.org
S: Supported
-T: git git://people.freedesktop.org/~sroland/linux
+T: git git://anongit.freedesktop.org/drm/drm-misc
F: drivers/gpu/drm/vmwgfx/
F: include/uapi/drm/vmwgfx_drm.h
+DRM DRIVER FOR WIDECHIPS WS2401 PANELS
+M: Linus Walleij <linus.walleij@linaro.org>
+S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
+F: Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
+F: drivers/gpu/drm/panel/panel-widechips-ws2401.c
+
DRM DRIVERS
M: David Airlie <airlied@linux.ie>
M: Daniel Vetter <daniel@ffwll.ch>
L: dri-devel@lists.freedesktop.org
S: Maintained
B: https://gitlab.freedesktop.org/drm
-C: irc://chat.freenode.net/dri-devel
+C: irc://irc.oftc.net/dri-devel
T: git git://anongit.freedesktop.org/drm/drm
F: Documentation/devicetree/bindings/display/
F: Documentation/devicetree/bindings/gpu/
@@ -6578,6 +6611,7 @@ EDAC-ARMADA
M: Jan Luebbe <jlu@pengutronix.de>
L: linux-edac@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/memory-controllers/marvell,mvebu-sdram-controller.yaml
F: drivers/edac/armada_xp_*
EDAC-AST2500
@@ -6819,7 +6853,6 @@ F: Documentation/admin-guide/media/em28xx*
F: drivers/media/usb/em28xx/
EMBEDDED LINUX
-M: Paul Gortmaker <paul.gortmaker@windriver.com>
M: Matt Mackall <mpm@selenic.com>
M: David Woodhouse <dwmw2@infradead.org>
L: linux-embedded@vger.kernel.org
@@ -8419,7 +8452,7 @@ F: drivers/crypto/hisilicon/sgl.c
F: drivers/crypto/hisilicon/zip/
HISILICON ROCE DRIVER
-M: Lijun Ou <oulijun@huawei.com>
+M: Wenpeng Liang <liangwenpeng@huawei.com>
M: Weihang Li <liweihang@huawei.com>
L: linux-rdma@vger.kernel.org
S: Maintained
@@ -8457,10 +8490,12 @@ S: Maintained
F: Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
F: drivers/spmi/hisi-spmi-controller.c
-HISILICON STAGING DRIVERS FOR HIKEY 960/970
+HISILICON SPMI PMIC DRIVER FOR HIKEY 6421v600
M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+L: linux-kernel@vger.kernel.org
S: Maintained
-F: drivers/staging/hikey9xx/
+F: Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
+F: drivers/mfd/hi6421-spmi-pmic.c
HISILICON TRUE RANDOM NUMBER GENERATOR V2 SUPPORT
M: Zaibo Xu <xuzaibo@huawei.com>
@@ -8619,6 +8654,9 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
F: Documentation/ABI/stable/sysfs-bus-vmbus
F: Documentation/ABI/testing/debugfs-hyperv
F: Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst
+F: arch/arm64/hyperv
+F: arch/arm64/include/asm/hyperv-tlfs.h
+F: arch/arm64/include/asm/mshyperv.h
F: arch/x86/hyperv
F: arch/x86/include/asm/hyperv-tlfs.h
F: arch/x86/include/asm/mshyperv.h
@@ -9065,7 +9103,7 @@ F: drivers/usb/atm/ueagle-atm.c
IMGTEC ASCII LCD DRIVER
M: Paul Burton <paulburton@kernel.org>
S: Maintained
-F: Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt
+F: Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml
F: drivers/auxdisplay/img-ascii-lcd.c
IMGTEC IR DECODER DRIVER
@@ -9237,13 +9275,20 @@ INTEL ATOMISP2 DUMMY / POWER-MANAGEMENT DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
-F: drivers/platform/x86/intel_atomisp2_pm.c
+F: drivers/platform/x86/intel/atomisp2/pm.c
INTEL ATOMISP2 LED DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
-F: drivers/platform/x86/intel_atomisp2_led.c
+F: drivers/platform/x86/intel/atomisp2/led.c
+
+INTEL BIOS SAR INT1092 DRIVER
+M: Shravan S <s.shravan@intel.com>
+M: Intel Corporation <linuxwwan@intel.com>
+L: platform-driver-x86@vger.kernel.org
+S: Maintained
+F: drivers/platform/x86/intel/int1092/
INTEL BROXTON PMC DRIVER
M: Mika Westerberg <mika.westerberg@linux.intel.com>
@@ -9275,7 +9320,7 @@ S: Supported
W: https://01.org/linuxgraphics/
Q: http://patchwork.freedesktop.org/project/intel-gfx/
B: https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
-C: irc://chat.freenode.net/intel-gfx
+C: irc://irc.oftc.net/intel-gfx
T: git git://anongit.freedesktop.org/drm-intel
F: Documentation/gpu/i915.rst
F: drivers/gpu/drm/i915/
@@ -9339,7 +9384,7 @@ INTEL HID EVENT DRIVER
M: Alex Hung <alex.hung@canonical.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
-F: drivers/platform/x86/intel-hid.c
+F: drivers/platform/x86/intel/hid.c
INTEL I/OAT DMA DRIVER
M: Dave Jiang <dave.jiang@intel.com>
@@ -9483,17 +9528,17 @@ F: include/linux/mfd/intel-m10-bmc.h
INTEL MENLOW THERMAL DRIVER
M: Sujith Thomas <sujith.thomas@intel.com>
-L: platform-driver-x86@vger.kernel.org
+L: linux-pm@vger.kernel.org
S: Supported
W: https://01.org/linux-acpi
-F: drivers/platform/x86/intel_menlow.c
+F: drivers/thermal/intel/intel_menlow.c
INTEL P-Unit IPC DRIVER
M: Zha Qipeng <qipeng.zha@intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: arch/x86/include/asm/intel_punit_ipc.h
-F: drivers/platform/x86/intel_punit_ipc.c
+F: drivers/platform/x86/intel/punit_ipc.c
INTEL PMC CORE DRIVER
M: Rajneesh Bhardwaj <irenic.rajneesh@gmail.com>
@@ -9501,7 +9546,7 @@ M: David E Box <david.e.box@intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-platform-intel-pmc
-F: drivers/platform/x86/intel_pmc_core*
+F: drivers/platform/x86/intel/pmc/
INTEL PMIC GPIO DRIVERS
M: Andy Shevchenko <andy@kernel.org>
@@ -9519,7 +9564,7 @@ INTEL PMT DRIVER
M: "David E. Box" <david.e.box@linux.intel.com>
S: Maintained
F: drivers/mfd/intel_pmt.c
-F: drivers/platform/x86/intel_pmt_*
+F: drivers/platform/x86/intel/pmt/
INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
M: Stanislav Yakovlev <stas.yakovlev@gmail.com>
@@ -9556,7 +9601,7 @@ INTEL SPEED SELECT TECHNOLOGY
M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
-F: drivers/platform/x86/intel_speed_select_if/
+F: drivers/platform/x86/intel/speed_select_if/
F: include/uapi/linux/isst_if.h
F: tools/power/x86/intel-speed-select/
@@ -9577,19 +9622,19 @@ M: "David E. Box" <david.e.box@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: arch/x86/include/asm/intel_telemetry.h
-F: drivers/platform/x86/intel_telemetry*
+F: drivers/platform/x86/intel/telemetry/
INTEL UNCORE FREQUENCY CONTROL
M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
-F: drivers/platform/x86/intel-uncore-frequency.c
+F: drivers/platform/x86/intel/uncore-frequency.c
INTEL VIRTUAL BUTTON DRIVER
M: AceLan Kao <acelan.kao@canonical.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
-F: drivers/platform/x86/intel-vbtn.c
+F: drivers/platform/x86/intel/vbtn.c
INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy)
M: Stanislaw Gruszka <stf_xl@wp.pl>
@@ -9610,12 +9655,12 @@ M: Jithu Joseph <jithu.joseph@intel.com>
R: Maurice Ma <maurice.ma@intel.com>
S: Maintained
W: https://slimbootloader.github.io/security/firmware-update.html
-F: drivers/platform/x86/intel-wmi-sbl-fw-update.c
+F: drivers/platform/x86/intel/wmi/sbl-fw-update.c
INTEL WMI THUNDERBOLT FORCE POWER DRIVER
L: Dell.Client.Kernel@dell.com
S: Maintained
-F: drivers/platform/x86/intel-wmi-thunderbolt.c
+F: drivers/platform/x86/intel/wmi/thunderbolt.c
INTEL WWAN IOSM DRIVER
M: M Chetan Kumar <m.chetan.kumar@intel.com>
@@ -10071,6 +10116,7 @@ F: fs/autofs/
KERNEL BUILD + files below scripts/ (unless maintained elsewhere)
M: Masahiro Yamada <masahiroy@kernel.org>
M: Michal Marek <michal.lkml@markovi.net>
+R: Nick Desaulniers <ndesaulniers@google.com>
L: linux-kbuild@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git
@@ -11074,7 +11120,7 @@ MARDUK (CREATOR CI40) DEVICE TREE SUPPORT
M: Rahul Bedarkar <rahulbedarkar89@gmail.com>
L: linux-mips@vger.kernel.org
S: Maintained
-F: arch/mips/boot/dts/img/pistachio_marduk.dts
+F: arch/mips/boot/dts/img/pistachio*
MARVELL 88E6XXX ETHERNET SWITCH FABRIC DRIVER
M: Andrew Lunn <andrew@lunn.ch>
@@ -13293,6 +13339,15 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs.git
F: Documentation/filesystems/ntfs.rst
F: fs/ntfs/
+NTFS3 FILESYSTEM
+M: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+L: ntfs3@lists.linux.dev
+S: Supported
+W: http://www.paragon-software.com/
+T: git https://github.com/Paragon-Software-Group/linux-ntfs3.git
+F: Documentation/filesystems/ntfs3.rst
+F: fs/ntfs3/
+
NUBUS SUBSYSTEM
M: Finn Thain <fthain@linux-m68k.org>
L: linux-m68k@lists.linux-m68k.org
@@ -13820,6 +13875,15 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ov8856.yaml
F: drivers/media/i2c/ov8856.c
+OMNIVISION OV9282 SENSOR DRIVER
+M: Paul J. Murphy <paul.j.murphy@intel.com>
+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
+F: drivers/media/i2c/ov9282.c
+
OMNIVISION OV9640 SENSOR DRIVER
M: Petr Cvek <petrcvekcz@gmail.com>
L: linux-media@vger.kernel.org
@@ -14241,7 +14305,7 @@ M: Lucas Stach <l.stach@pengutronix.de>
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: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
F: drivers/pci/controller/dwc/*imx6*
PCI DRIVER FOR FU740
@@ -14329,7 +14393,8 @@ M: Jingoo Han <jingoohan1@gmail.com>
M: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
L: linux-pci@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/pci/designware-pcie.txt
+F: Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
+F: Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml
F: drivers/pci/controller/dwc/*designware*
PCI DRIVER FOR TI DRA7XX/J721E
@@ -14466,7 +14531,7 @@ 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/kirin-pcie.txt
+F: Documentation/devicetree/bindings/pci/hisilicon,kirin-pcie.yaml
F: drivers/pci/controller/dwc/pcie-kirin.c
PCIE DRIVER FOR HISILICON STB
@@ -14678,6 +14743,12 @@ F: Documentation/driver-api/pin-control.rst
F: drivers/pinctrl/
F: include/linux/pinctrl/
+PIN CONTROLLER - AMD
+M: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+S: Maintained
+F: drivers/pinctrl/pinctrl-amd.c
+
PIN CONTROLLER - FREESCALE
M: Dong Aisheng <aisheng.dong@nxp.com>
M: Fabio Estevam <festevam@gmail.com>
@@ -14696,12 +14767,19 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel.git
F: drivers/pinctrl/intel/
+PIN CONTROLLER - KEEMBAY
+M: Lakshmi Sowjanya D <lakshmi.sowjanya.d@intel.com>
+S: Supported
+F: drivers/pinctrl/pinctrl-keembay*
+
PIN CONTROLLER - MEDIATEK
M: Sean Wang <sean.wang@kernel.org>
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
-F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml
+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
F: drivers/pinctrl/mediatek/
PIN CONTROLLER - MICROCHIP AT91
@@ -14755,14 +14833,6 @@ S: Maintained
W: http://www.st.com/spear
F: drivers/pinctrl/spear/
-PISTACHIO SOC SUPPORT
-M: James Hartley <james.hartley@sondrel.com>
-L: linux-mips@vger.kernel.org
-S: Odd Fixes
-F: arch/mips/boot/dts/img/pistachio*
-F: arch/mips/configs/pistachio*_defconfig
-F: arch/mips/pistachio/
-
PKTCDVD DRIVER
M: linux-block@vger.kernel.org
S: Orphan
@@ -14979,6 +15049,11 @@ S: Maintained
F: include/linux/printk.h
F: kernel/printk/
+PRINTK INDEXING
+R: Chris Down <chris@chrisdown.name>
+S: Maintained
+F: kernel/printk/index.c
+
PROC FILESYSTEM
L: linux-kernel@vger.kernel.org
L: linux-fsdevel@vger.kernel.org
@@ -15894,6 +15969,14 @@ L: linux-renesas-soc@vger.kernel.org
S: Maintained
F: drivers/phy/renesas/phy-rcar-gen3-usb*.c
+RENESAS RZ/G2L A/D DRIVER
+M: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+L: linux-iio@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml
+F: drivers/iio/adc/rzg2l_adc.c
+
RESET CONTROLLER FRAMEWORK
M: Philipp Zabel <p.zabel@pengutronix.de>
S: Maintained
@@ -16364,7 +16447,7 @@ SAMSUNG EXYNOS TRUE RANDOM NUMBER GENERATOR (TRNG) DRIVER
M: Łukasz Stelmach <l.stelmach@samsung.com>
L: linux-samsung-soc@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
+F: Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.yaml
F: drivers/char/hw_random/exynos-trng.c
SAMSUNG FRAMEBUFFER DRIVER
@@ -16457,10 +16540,14 @@ L: linux-samsung-soc@vger.kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git
F: Documentation/devicetree/bindings/clock/exynos*.txt
+F: Documentation/devicetree/bindings/clock/samsung,*.yaml
F: Documentation/devicetree/bindings/clock/samsung,s3c*
F: Documentation/devicetree/bindings/clock/samsung,s5p*
F: drivers/clk/samsung/
F: include/dt-bindings/clock/exynos*.h
+F: include/dt-bindings/clock/s3c*.h
+F: include/dt-bindings/clock/s5p*.h
+F: include/dt-bindings/clock/samsung,*.h
F: include/linux/clk/samsung.h
F: include/linux/platform_data/clk-s3c2410.h
@@ -16502,6 +16589,12 @@ F: drivers/phy/samsung/phy-s5pv210-usb2.c
F: drivers/phy/samsung/phy-samsung-usb2.c
F: drivers/phy/samsung/phy-samsung-usb2.h
+SANCLOUD BEAGLEBONE ENHANCED DEVICE TREE
+M: Paul Barker <paul.barker@sancloud.com>
+R: Marc Murphy <marc.murphy@sancloud.com>
+S: Supported
+F: arch/arm/boot/dts/am335x-sancloud*
+
SC1200 WDT DRIVER
M: Zwane Mwaikambo <zwanem@gmail.com>
S: Maintained
@@ -16761,6 +16854,12 @@ F: drivers/iio/chemical/scd30_core.c
F: drivers/iio/chemical/scd30_i2c.c
F: drivers/iio/chemical/scd30_serial.c
+SENSIRION SGP40 GAS SENSOR DRIVER
+M: Andreas Klinger <ak@it-klinger.de>
+S: Maintained
+F: Documentation/ABI/testing/sysfs-bus-iio-chemical-sgp40
+F: drivers/iio/chemical/sgp40.c
+
SENSIRION SPS30 AIR POLLUTION SENSOR DRIVER
M: Tomasz Duszynski <tduszyns@gmail.com>
S: Maintained
@@ -17339,6 +17438,15 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
F: drivers/media/i2c/imx334.c
+SONY IMX335 SENSOR DRIVER
+M: Paul J. Murphy <paul.j.murphy@intel.com>
+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
+F: drivers/media/i2c/imx335.c
+
SONY IMX355 SENSOR DRIVER
M: Tianshu Qiu <tian.shu.qiu@intel.com>
L: linux-media@vger.kernel.org
@@ -17346,6 +17454,15 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/imx355.c
+SONY IMX412 SENSOR DRIVER
+M: Paul J. Murphy <paul.j.murphy@intel.com>
+M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
+F: drivers/media/i2c/imx412.c
+
SONY MEMORYSTICK SUBSYSTEM
M: Maxim Levitsky <maximlevitsky@gmail.com>
M: Alex Dubov <oakad@yahoo.com>
@@ -17665,8 +17782,9 @@ F: drivers/staging/olpc_dcon/
STAGING - REALTEK RTL8188EU DRIVERS
M: Larry Finger <Larry.Finger@lwfinger.net>
-S: Odd Fixes
-F: drivers/staging/rtl8188eu/
+M: Phillip Potter <phil@philpotter.co.uk>
+S: Supported
+F: drivers/staging/r8188eu/
STAGING - REALTEK RTL8712U DRIVERS
M: Larry Finger <Larry.Finger@lwfinger.net>
@@ -18003,6 +18121,7 @@ F: drivers/regulator/scmi-regulator.c
F: drivers/reset/reset-scmi.c
F: include/linux/sc[mp]i_protocol.h
F: include/trace/events/scmi.h
+F: include/uapi/linux/virtio_scmi.h
SYSTEM RESET/SHUTDOWN DRIVERS
M: Sebastian Reichel <sre@kernel.org>
@@ -18853,6 +18972,28 @@ F: arch/x86/mm/testmmiotrace.c
F: include/linux/mmiotrace.h
F: kernel/trace/trace_mmiotrace.c
+TRACING OS NOISE / LATENCY TRACERS
+M: Steven Rostedt <rostedt@goodmis.org>
+M: Daniel Bristot de Oliveira <bristot@kernel.org>
+S: Maintained
+F: kernel/trace/trace_osnoise.c
+F: include/trace/events/osnoise.h
+F: kernel/trace/trace_hwlat.c
+F: kernel/trace/trace_irqsoff.c
+F: kernel/trace/trace_sched_wakeup.c
+F: Documentation/trace/osnoise-tracer.rst
+F: Documentation/trace/timerlat-tracer.rst
+F: Documentation/trace/hwlat_detector.rst
+F: arch/*/kernel/trace.c
+
+TRADITIONAL CHINESE DOCUMENTATION
+M: Hu Haowen <src.res@email.cn>
+L: linux-doc-tw-discuss@lists.sourceforge.net
+S: Maintained
+W: https://github.com/srcres258/linux-doc
+T: git git://github.com/srcres258/linux-doc.git doc-zh-tw
+F: Documentation/translations/zh_TW/
+
TRIVIAL PATCHES
M: Jiri Kosina <trivial@kernel.org>
S: Maintained
@@ -19025,9 +19166,8 @@ W: http://dotat.at/prog/unifdef
F: scripts/unifdef.c
UNIFORM CDROM DRIVER
-M: Jens Axboe <axboe@kernel.dk>
+M: Phillip Potter <phil@philpotter.co.uk>
S: Maintained
-W: http://www.kernel.dk
F: Documentation/cdrom/
F: drivers/cdrom/cdrom.c
F: include/linux/cdrom.h
@@ -19512,6 +19652,7 @@ T: git git://github.com/awilliam/linux-vfio.git
F: Documentation/driver-api/vfio.rst
F: drivers/vfio/
F: include/linux/vfio.h
+F: include/linux/vfio_pci_core.h
F: include/uapi/linux/vfio.h
VFIO FSL-MC DRIVER
@@ -19620,18 +19761,11 @@ L: kvm@vger.kernel.org
L: virtualization@lists.linux-foundation.org
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/vsockmon.c
F: drivers/vhost/vsock.c
F: include/linux/virtio_vsock.h
F: include/uapi/linux/virtio_vsock.h
-F: include/uapi/linux/vm_sockets_diag.h
-F: include/uapi/linux/vsockmon.h
-F: net/vmw_vsock/af_vsock_tap.c
-F: net/vmw_vsock/diag.c
F: net/vmw_vsock/virtio_transport.c
F: net/vmw_vsock/virtio_transport_common.c
-F: net/vmw_vsock/vsock_loopback.c
-F: tools/testing/vsock/
VIRTIO BLOCK AND SCSI DRIVERS
M: "Michael S. Tsirkin" <mst@redhat.com>
@@ -19710,6 +19844,15 @@ F: Documentation/filesystems/virtiofs.rst
F: fs/fuse/virtio_fs.c
F: include/uapi/linux/virtio_fs.h
+VIRTIO GPIO DRIVER
+M: Enrico Weigelt, metux IT consult <info@metux.net>
+M: Viresh Kumar <vireshk@kernel.org>
+L: linux-gpio@vger.kernel.org
+L: virtualization@lists.linux-foundation.org
+S: Maintained
+F: drivers/gpio/gpio-virtio.c
+F: include/uapi/linux/virtio_gpio.h
+
VIRTIO GPU DRIVER
M: David Airlie <airlied@linux.ie>
M: Gerd Hoffmann <kraxel@redhat.com>
@@ -19827,6 +19970,19 @@ F: drivers/staging/vme/
F: drivers/vme/
F: include/linux/vme*
+VM SOCKETS (AF_VSOCK)
+M: Stefano Garzarella <sgarzare@redhat.com>
+L: virtualization@lists.linux-foundation.org
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/vsockmon.c
+F: include/net/af_vsock.h
+F: include/uapi/linux/vm_sockets.h
+F: include/uapi/linux/vm_sockets_diag.h
+F: include/uapi/linux/vsockmon.h
+F: net/vmw_vsock/
+F: tools/testing/vsock/
+
VMWARE BALLOON DRIVER
M: Nadav Amit <namit@vmware.com>
M: "VMware, Inc." <pv-drivers@vmware.com>
@@ -20404,7 +20560,7 @@ R: Srinivas Neeli <srinivas.neeli@xilinx.com>
R: Michal Simek <michal.simek@xilinx.com>
S: Maintained
F: Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
-F: Documentation/devicetree/bindings/gpio/gpio-zynq.txt
+F: Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
F: drivers/gpio/gpio-xilinx.c
F: drivers/gpio/gpio-zynq.c
diff --git a/Makefile b/Makefile
index 61741e9d9c6e..d45fc2edf186 100644
--- a/Makefile
+++ b/Makefile
@@ -191,10 +191,9 @@ endif
ifneq ($(abs_srctree),$(abs_objtree))
# Look for make include files relative to root of kernel src
#
-# This does not become effective immediately because MAKEFLAGS is re-parsed
-# once after the Makefile is read. We need to invoke sub-make.
+# --included-dir is added for backward compatibility, but you should not rely on
+# it. Please add $(srctree)/ prefix to include Makefiles in the source tree.
MAKEFLAGS += --include-dir=$(abs_srctree)
-need-sub-make := 1
endif
ifneq ($(filter 3.%,$(MAKE_VERSION)),)
@@ -404,6 +403,11 @@ ifeq ($(ARCH),sparc64)
SRCARCH := sparc
endif
+# Additional ARCH settings for parisc
+ifeq ($(ARCH),parisc64)
+ SRCARCH := parisc
+endif
+
export cross_compiling :=
ifneq ($(SRCARCH),$(SUBARCH))
cross_compiling := 1
@@ -582,23 +586,10 @@ endif
# 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 = $(subst $(pound),,$(shell $(CC) --version 2>/dev/null | head -n 1))
+CC_VERSION_TEXT = $(subst $(pound),,$(shell LC_ALL=C $(CC) --version 2>/dev/null | head -n 1))
ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
-ifneq ($(CROSS_COMPILE),)
-CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))
-endif
-ifeq ($(LLVM_IAS),1)
-CLANG_FLAGS += -integrated-as
-else
-CLANG_FLAGS += -no-integrated-as
-GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
-CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
-endif
-CLANG_FLAGS += -Werror=unknown-warning-option
-KBUILD_CFLAGS += $(CLANG_FLAGS)
-KBUILD_AFLAGS += $(CLANG_FLAGS)
-export CLANG_FLAGS
+include $(srctree)/scripts/Makefile.clang
endif
# Include this also for config targets because some architectures need
@@ -683,9 +674,10 @@ endif # KBUILD_EXTMOD
# 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,)
+CFLAGS_GCOV := -fprofile-arcs -ftest-coverage
+ifdef CONFIG_CC_IS_GCC
+CFLAGS_GCOV += -fno-tree-loop-im
+endif
export CFLAGS_GCOV
# The arch Makefiles can override CC_FLAGS_FTRACE. We may also append it later.
@@ -693,12 +685,14 @@ ifdef CONFIG_FUNCTION_TRACER
CC_FLAGS_FTRACE := -pg
endif
-RETPOLINE_CFLAGS_GCC := -mindirect-branch=thunk-extern -mindirect-branch-register
-RETPOLINE_VDSO_CFLAGS_GCC := -mindirect-branch=thunk-inline -mindirect-branch-register
-RETPOLINE_CFLAGS_CLANG := -mretpoline-external-thunk
-RETPOLINE_VDSO_CFLAGS_CLANG := -mretpoline
-RETPOLINE_CFLAGS := $(call cc-option,$(RETPOLINE_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_CFLAGS_CLANG)))
-RETPOLINE_VDSO_CFLAGS := $(call cc-option,$(RETPOLINE_VDSO_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_VDSO_CFLAGS_CLANG)))
+ifdef CONFIG_CC_IS_GCC
+RETPOLINE_CFLAGS := $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register)
+RETPOLINE_VDSO_CFLAGS := $(call cc-option,-mindirect-branch=thunk-inline -mindirect-branch-register)
+endif
+ifdef CONFIG_CC_IS_CLANG
+RETPOLINE_CFLAGS := -mretpoline-external-thunk
+RETPOLINE_VDSO_CFLAGS := -mretpoline
+endif
export RETPOLINE_CFLAGS
export RETPOLINE_VDSO_CFLAGS
@@ -751,7 +745,7 @@ include/config/auto.conf:
endif # may-sync-config
endif # need-config
-KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,)
+KBUILD_CFLAGS += -fno-delete-null-pointer-checks
KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,)
KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation)
KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
@@ -766,17 +760,19 @@ KBUILD_CFLAGS += -Os
endif
# Tell gcc to never replace conditional load with a non-conditional one
+ifdef CONFIG_CC_IS_GCC
+# gcc-10 renamed --param=allow-store-data-races=0 to
+# -fno-allow-store-data-races.
KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)
KBUILD_CFLAGS += $(call cc-option,-fno-allow-store-data-races)
+endif
ifdef CONFIG_READABLE_ASM
# Disable optimizations that make assembler listings hard to read.
# reorder blocks reorders the control in the function
# ipa clone creates specialized cloned functions
# partial inlining inlines only parts of functions
-KBUILD_CFLAGS += $(call cc-option,-fno-reorder-blocks,) \
- $(call cc-option,-fno-ipa-cp-clone,) \
- $(call cc-option,-fno-partial-inlining)
+KBUILD_CFLAGS += -fno-reorder-blocks -fno-ipa-cp-clone -fno-partial-inlining
endif
ifneq ($(CONFIG_FRAME_WARN),0)
@@ -789,9 +785,12 @@ stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong
KBUILD_CFLAGS += $(stackp-flags-y)
+KBUILD_CFLAGS-$(CONFIG_WERROR) += -Werror
+KBUILD_CFLAGS += $(KBUILD_CFLAGS-y)
+
ifdef CONFIG_CC_IS_CLANG
KBUILD_CPPFLAGS += -Qunused-arguments
-KBUILD_CFLAGS += -Wno-format-invalid-specifier
+# The kernel builds with '-std=gnu89' so use of GNU extensions is acceptable.
KBUILD_CFLAGS += -Wno-gnu
# CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the
# source of a reference will be _MergedGlobals and not on of the whitelisted names.
@@ -808,8 +807,8 @@ endif
# These warnings generated too much noise in a regular build.
# Use make W=1 to enable them (see scripts/Makefile.extrawarn)
KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
-
KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
+
ifdef CONFIG_FRAME_POINTER
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
else
@@ -841,6 +840,11 @@ endif
# for the randomize_kstack_offset feature. Disable it for all compilers.
KBUILD_CFLAGS += $(call cc-option, -fno-stack-clash-protection)
+# Clear used registers at func exit (to reduce data lifetime and ROP gadgets).
+ifdef CONFIG_ZERO_CALL_USED_REGS
+KBUILD_CFLAGS += -fzero-call-used-regs=used-gpr
+endif
+
DEBUG_CFLAGS :=
# Workaround for GCC versions < 5.0
@@ -857,7 +861,7 @@ else
DEBUG_CFLAGS += -g
endif
-ifneq ($(LLVM_IAS),1)
+ifndef CONFIG_AS_IS_LLVM
KBUILD_AFLAGS += -Wa,-gdwarf-2
endif
@@ -868,8 +872,10 @@ DEBUG_CFLAGS += -gdwarf-$(dwarf-version-y)
endif
ifdef CONFIG_DEBUG_INFO_REDUCED
-DEBUG_CFLAGS += $(call cc-option, -femit-struct-debug-baseonly) \
- $(call cc-option,-fno-var-tracking)
+DEBUG_CFLAGS += -fno-var-tracking
+ifdef CONFIG_CC_IS_GCC
+DEBUG_CFLAGS += -femit-struct-debug-baseonly
+endif
endif
ifdef CONFIG_DEBUG_INFO_COMPRESSED
@@ -903,6 +909,7 @@ ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
endif
endif
ifdef CONFIG_HAVE_FENTRY
+ # s390-linux-gnu-gcc did not support -mfentry until gcc-9.
ifeq ($(call cc-option-yn, -mfentry),y)
CC_FLAGS_FTRACE += -mfentry
CC_FLAGS_USING += -DCC_USING_FENTRY
@@ -915,7 +922,7 @@ endif
# We trigger additional mismatches with less inlining
ifdef CONFIG_DEBUG_SECTION_MISMATCH
-KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
+KBUILD_CFLAGS += -fno-inline-functions-called-once
endif
ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
@@ -994,14 +1001,16 @@ KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
# We'll want to enable this eventually, but it's not going away for 5.7 at least
KBUILD_CFLAGS += $(call cc-disable-warning, zero-length-bounds)
-KBUILD_CFLAGS += $(call cc-disable-warning, array-bounds)
+KBUILD_CFLAGS += -Wno-array-bounds
KBUILD_CFLAGS += $(call cc-disable-warning, stringop-overflow)
# Another good warning that we'll want to enable eventually
KBUILD_CFLAGS += $(call cc-disable-warning, restrict)
# Enabled with W=2, disabled by default as noisy
-KBUILD_CFLAGS += $(call cc-disable-warning, maybe-uninitialized)
+ifdef CONFIG_CC_IS_GCC
+KBUILD_CFLAGS += -Wno-maybe-uninitialized
+endif
# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS += -fno-strict-overflow
@@ -1010,7 +1019,9 @@ KBUILD_CFLAGS += -fno-strict-overflow
KBUILD_CFLAGS += -fno-stack-check
# conserve stack if available
-KBUILD_CFLAGS += $(call cc-option,-fconserve-stack)
+ifdef CONFIG_CC_IS_GCC
+KBUILD_CFLAGS += -fconserve-stack
+endif
# Prohibit date/time macros, which would make the build non-deterministic
KBUILD_CFLAGS += -Werror=date-time
@@ -1740,6 +1751,16 @@ clean-dirs := $(KBUILD_EXTMOD)
clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers $(KBUILD_EXTMOD)/modules.nsdeps \
$(KBUILD_EXTMOD)/compile_commands.json $(KBUILD_EXTMOD)/.thinlto-cache
+PHONY += prepare
+# now expand this into a simple variable to reduce the cost of shell evaluations
+prepare: CC_VERSION_TEXT := $(CC_VERSION_TEXT)
+prepare:
+ @if [ "$(CC_VERSION_TEXT)" != $(CONFIG_CC_VERSION_TEXT) ]; then \
+ echo >&2 "warning: the compiler differs from the one used to build the kernel"; \
+ echo >&2 " The kernel was built by: "$(CONFIG_CC_VERSION_TEXT); \
+ echo >&2 " You are using: $(CC_VERSION_TEXT)"; \
+ fi
+
PHONY += help
help:
@echo ' Building external modules.'
@@ -1751,7 +1772,7 @@ help:
@echo ''
# no-op for external module builds
-PHONY += prepare modules_prepare
+PHONY += modules_prepare
endif # KBUILD_EXTMOD
diff --git a/arch/Kconfig b/arch/Kconfig
index 98db63496bab..3743174da870 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -197,6 +197,9 @@ config HAVE_FUNCTION_ERROR_INJECTION
config HAVE_NMI
bool
+config TRACE_IRQFLAGS_SUPPORT
+ bool
+
#
# An arch should select this if it provides all these things:
#
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 6c50877841df..02e5b673bdad 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -28,8 +28,6 @@ config ALPHA
select AUDIT_ARCH
select GENERIC_CPU_VULNERABILITIES
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select HAVE_ARCH_AUDITSYSCALL
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA
diff --git a/arch/alpha/include/uapi/asm/siginfo.h b/arch/alpha/include/uapi/asm/siginfo.h
index 6e1a2af2f962..e08eae88182b 100644
--- a/arch/alpha/include/uapi/asm/siginfo.h
+++ b/arch/alpha/include/uapi/asm/siginfo.h
@@ -2,8 +2,6 @@
#ifndef _ALPHA_SIGINFO_H
#define _ALPHA_SIGINFO_H
-#define __ARCH_SI_TRAPNO
-
#include <asm-generic/siginfo.h>
#endif
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index d31167e3269c..8bbeebb73cf0 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -876,7 +876,7 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
if (fex & IEEE_TRAP_ENABLE_DZE) si_code = FPE_FLTDIV;
if (fex & IEEE_TRAP_ENABLE_INV) si_code = FPE_FLTINV;
- send_sig_fault(SIGFPE, si_code,
+ send_sig_fault_trapno(SIGFPE, si_code,
(void __user *)NULL, /* FIXME */
0, current);
}
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 35d7b3096d6e..21f9ac101324 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -649,7 +649,9 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
sg->dma_address
= pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg),
sg->length, dac_allowed);
- return sg->dma_address != DMA_MAPPING_ERROR;
+ if (sg->dma_address == DMA_MAPPING_ERROR)
+ return -EIO;
+ return 1;
}
start = sg;
@@ -685,8 +687,10 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
if (out < end)
out->dma_length = 0;
- if (out - start == 0)
+ if (out - start == 0) {
printk(KERN_WARNING "pci_map_sg failed: no entries?\n");
+ return -ENOMEM;
+ }
DBGA("pci_map_sg: %ld entries\n", out - start);
return out - start;
@@ -699,7 +703,7 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
entries. Unmap them now. */
if (out > start)
pci_unmap_sg(pdev, start, out - start, dir);
- return 0;
+ return -ENOMEM;
}
/* Unmap a set of streaming mode DMA translations. Again, cpu read
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 948b89789da8..bc077babafab 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -219,7 +219,7 @@ do_sigreturn(struct sigcontext __user *sc)
/* Send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current)) {
- send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc, 0,
+ send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc,
current);
}
return;
@@ -247,7 +247,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame)
/* Send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current)) {
- send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc, 0,
+ send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc,
current);
}
return;
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index fc03471a0b0f..90635ef5dafa 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -204,9 +204,9 @@ srmcons_init(void)
struct tty_driver *driver;
int err;
- driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES);
- if (!driver)
- return -ENOMEM;
+ driver = tty_alloc_driver(MAX_SRM_CONSOLE_DEVICES, 0);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
tty_port_init(&srmcons_singleton.port);
@@ -221,7 +221,7 @@ srmcons_init(void)
tty_port_link_device(&srmcons_singleton.port, driver, 0);
err = tty_register_driver(driver);
if (err) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
tty_port_destroy(&srmcons_singleton.port);
return err;
}
diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
index a17687ed4b51..e4a041cd5715 100644
--- a/arch/alpha/kernel/syscalls/syscall.tbl
+++ b/arch/alpha/kernel/syscalls/syscall.tbl
@@ -230,7 +230,7 @@
259 common osf_swapctl sys_ni_syscall
260 common osf_memcntl sys_ni_syscall
261 common osf_fdatasync sys_ni_syscall
-300 common bdflush sys_bdflush
+300 common bdflush sys_ni_syscall
301 common sethae sys_sethae
302 common mount sys_mount
303 common old_adjtimex sys_old_adjtimex
@@ -486,3 +486,5 @@
554 common landlock_create_ruleset sys_landlock_create_ruleset
555 common landlock_add_rule sys_landlock_add_rule
556 common landlock_restrict_self sys_landlock_restrict_self
+# 557 reserved for memfd_secret
+558 common process_mrelease sys_process_mrelease
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 5398f982bdd1..e805106409f7 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -227,7 +227,7 @@ do_entArith(unsigned long summary, unsigned long write_mask,
}
die_if_kernel("Arithmetic fault", regs, 0, NULL);
- send_sig_fault(SIGFPE, si_code, (void __user *) regs->pc, 0, current);
+ send_sig_fault_trapno(SIGFPE, si_code, (void __user *) regs->pc, 0, current);
}
asmlinkage void
@@ -268,13 +268,13 @@ do_entIF(unsigned long type, struct pt_regs *regs)
regs->pc -= 4; /* make pc point to former bpt */
}
- send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc, 0,
+ send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc,
current);
return;
case 1: /* bugcheck */
- send_sig_fault(SIGTRAP, TRAP_UNK, (void __user *) regs->pc, 0,
- current);
+ send_sig_fault_trapno(SIGTRAP, TRAP_UNK,
+ (void __user *) regs->pc, 0, current);
return;
case 2: /* gentrap */
@@ -335,8 +335,8 @@ do_entIF(unsigned long type, struct pt_regs *regs)
break;
}
- send_sig_fault(signo, code, (void __user *) regs->pc, regs->r16,
- current);
+ send_sig_fault_trapno(signo, code, (void __user *) regs->pc,
+ regs->r16, current);
return;
case 4: /* opDEC */
@@ -360,9 +360,9 @@ do_entIF(unsigned long type, struct pt_regs *regs)
if (si_code == 0)
return;
if (si_code > 0) {
- send_sig_fault(SIGFPE, si_code,
- (void __user *) regs->pc, 0,
- current);
+ send_sig_fault_trapno(SIGFPE, si_code,
+ (void __user *) regs->pc,
+ 0, current);
return;
}
}
@@ -387,7 +387,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)
;
}
- send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, 0, current);
+ send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, current);
}
/* There is an ifdef in the PALcode in MILO that enables a
@@ -402,7 +402,7 @@ do_entDbg(struct pt_regs *regs)
{
die_if_kernel("Instruction fault", regs, 0, NULL);
- force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, 0);
+ force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc);
}
@@ -964,12 +964,12 @@ give_sigsegv:
si_code = SEGV_MAPERR;
mmap_read_unlock(mm);
}
- send_sig_fault(SIGSEGV, si_code, va, 0, current);
+ send_sig_fault(SIGSEGV, si_code, va, current);
return;
give_sigbus:
regs->pc -= 4;
- send_sig_fault(SIGBUS, BUS_ADRALN, va, 0, current);
+ send_sig_fault(SIGBUS, BUS_ADRALN, va, current);
return;
}
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index 09172f017efc..eee5102c3d88 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -219,13 +219,13 @@ retry:
mmap_read_unlock(mm);
/* Send a sigbus, regardless of whether we were in kernel
or user mode. */
- force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *) address, 0);
+ force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *) address);
if (!user_mode(regs))
goto no_context;
return;
do_sigsegv:
- force_sig_fault(SIGSEGV, si_code, (void __user *) address, 0);
+ force_sig_fault(SIGSEGV, si_code, (void __user *) address);
return;
#ifdef CONFIG_ALPHA_LARGE_VMALLOC
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index b5bf68e74732..3a5a80f302e1 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -49,9 +49,7 @@ config ARC
select PERF_USE_VMALLOC if ARC_CACHE_VIPT_ALIASING
select HAVE_ARCH_JUMP_LABEL if ISA_ARCV2 && !CPU_ENDIAN_BE32
select SET_FS
-
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
+ select TRACE_IRQFLAGS_SUPPORT
config LOCKDEP_SUPPORT
def_bool y
@@ -116,16 +114,9 @@ choice
default ARC_CPU_770 if ISA_ARCOMPACT
default ARC_CPU_HS if ISA_ARCV2
-if ISA_ARCOMPACT
-
-config ARC_CPU_750D
- bool "ARC750D"
- select ARC_CANT_LLSC
- help
- Support for ARC750 core
-
config ARC_CPU_770
bool "ARC770"
+ depends on ISA_ARCOMPACT
select ARC_HAS_SWAPE
help
Support for ARC770 core introduced with Rel 4.10 (Summer 2011)
@@ -135,8 +126,6 @@ config ARC_CPU_770
-Caches: New Prog Model, Region Flush
-Insns: endian swap, load-locked/store-conditional, time-stamp-ctr
-endif #ISA_ARCOMPACT
-
config ARC_CPU_HS
bool "ARC-HS"
depends on ISA_ARCV2
@@ -274,33 +263,17 @@ config ARC_DCCM_BASE
choice
prompt "MMU Version"
- default ARC_MMU_V3 if ARC_CPU_770
- default ARC_MMU_V2 if ARC_CPU_750D
- default ARC_MMU_V4 if ARC_CPU_HS
-
-if ISA_ARCOMPACT
-
-config ARC_MMU_V1
- bool "MMU v1"
- help
- Orig ARC700 MMU
-
-config ARC_MMU_V2
- bool "MMU v2"
- help
- Fixed the deficiency of v1 - possible thrashing in memcpy scenario
- when 2 D-TLB and 1 I-TLB entries index into same 2way set.
+ default ARC_MMU_V3 if ISA_ARCOMPACT
+ default ARC_MMU_V4 if ISA_ARCV2
config ARC_MMU_V3
bool "MMU v3"
- depends on ARC_CPU_770
+ depends on ISA_ARCOMPACT
help
Introduced with ARC700 4.10: New Features
Variable Page size (1k-16k), var JTLB size 128 x (2 or 4)
Shared Address Spaces (SASID)
-endif
-
config ARC_MMU_V4
bool "MMU v4"
depends on ISA_ARCV2
@@ -319,7 +292,6 @@ config ARC_PAGE_SIZE_8K
config ARC_PAGE_SIZE_16K
bool "16KB"
- depends on ARC_MMU_V3 || ARC_MMU_V4
config ARC_PAGE_SIZE_4K
bool "4KB"
@@ -340,6 +312,10 @@ config ARC_HUGEPAGE_16M
endchoice
+config PGTABLE_LEVELS
+ int "Number of Page table levels"
+ default 2
+
config ARC_COMPACT_IRQ_LEVELS
depends on ISA_ARCOMPACT
bool "Setup Timer IRQ as high Priority"
@@ -563,9 +539,6 @@ config ARC_DW2_UNWIND
If you don't debug the kernel, you can say N, but we may not be able
to solve problems without frame unwind information
-config ARC_DBG_TLB_PARANOIA
- bool "Paranoia Checks in Low Level TLB Handlers"
-
config ARC_DBG_JUMP_LABEL
bool "Paranoid checks in Static Keys (jump labels) code"
depends on JUMP_LABEL
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index c0d87ac2e221..8782a03f24a8 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -18,8 +18,7 @@ ifeq ($(CONFIG_ARC_TUNE_MCPU),"")
cflags-y += $(tune-mcpu-def-y)
else
tune-mcpu := $(shell echo $(CONFIG_ARC_TUNE_MCPU))
-tune-mcpu-ok := $(call cc-option-yn, $(tune-mcpu))
-ifeq ($(tune-mcpu-ok),y)
+ifneq ($(call cc-option,$(tune-mcpu)),)
cflags-y += $(tune-mcpu)
else
# The flag provided by 'CONFIG_ARC_TUNE_MCPU' option isn't known by this compiler
diff --git a/arch/arc/include/asm/atomic-llsc.h b/arch/arc/include/asm/atomic-llsc.h
new file mode 100644
index 000000000000..088d348781c1
--- /dev/null
+++ b/arch/arc/include/asm/atomic-llsc.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ASM_ARC_ATOMIC_LLSC_H
+#define _ASM_ARC_ATOMIC_LLSC_H
+
+#define arch_atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
+
+#define ATOMIC_OP(op, c_op, asm_op) \
+static inline void arch_atomic_##op(int i, atomic_t *v) \
+{ \
+ unsigned int val; \
+ \
+ __asm__ __volatile__( \
+ "1: llock %[val], [%[ctr]] \n" \
+ " " #asm_op " %[val], %[val], %[i] \n" \
+ " scond %[val], [%[ctr]] \n" \
+ " bnz 1b \n" \
+ : [val] "=&r" (val) /* Early clobber to prevent reg reuse */ \
+ : [ctr] "r" (&v->counter), /* Not "m": llock only supports reg direct addr mode */ \
+ [i] "ir" (i) \
+ : "cc"); \
+} \
+
+#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
+static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \
+{ \
+ unsigned int val; \
+ \
+ __asm__ __volatile__( \
+ "1: llock %[val], [%[ctr]] \n" \
+ " " #asm_op " %[val], %[val], %[i] \n" \
+ " scond %[val], [%[ctr]] \n" \
+ " bnz 1b \n" \
+ : [val] "=&r" (val) \
+ : [ctr] "r" (&v->counter), \
+ [i] "ir" (i) \
+ : "cc"); \
+ \
+ return val; \
+}
+
+#define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed
+#define arch_atomic_sub_return_relaxed arch_atomic_sub_return_relaxed
+
+#define ATOMIC_FETCH_OP(op, c_op, asm_op) \
+static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \
+{ \
+ unsigned int val, orig; \
+ \
+ __asm__ __volatile__( \
+ "1: llock %[orig], [%[ctr]] \n" \
+ " " #asm_op " %[val], %[orig], %[i] \n" \
+ " scond %[val], [%[ctr]] \n" \
+ " bnz 1b \n" \
+ : [val] "=&r" (val), \
+ [orig] "=&r" (orig) \
+ : [ctr] "r" (&v->counter), \
+ [i] "ir" (i) \
+ : "cc"); \
+ \
+ return orig; \
+}
+
+#define arch_atomic_fetch_add_relaxed arch_atomic_fetch_add_relaxed
+#define arch_atomic_fetch_sub_relaxed arch_atomic_fetch_sub_relaxed
+
+#define arch_atomic_fetch_and_relaxed arch_atomic_fetch_and_relaxed
+#define arch_atomic_fetch_andnot_relaxed arch_atomic_fetch_andnot_relaxed
+#define arch_atomic_fetch_or_relaxed arch_atomic_fetch_or_relaxed
+#define arch_atomic_fetch_xor_relaxed arch_atomic_fetch_xor_relaxed
+
+#define ATOMIC_OPS(op, c_op, asm_op) \
+ ATOMIC_OP(op, c_op, asm_op) \
+ ATOMIC_OP_RETURN(op, c_op, asm_op) \
+ ATOMIC_FETCH_OP(op, c_op, asm_op)
+
+ATOMIC_OPS(add, +=, add)
+ATOMIC_OPS(sub, -=, sub)
+
+#undef ATOMIC_OPS
+#define ATOMIC_OPS(op, c_op, asm_op) \
+ ATOMIC_OP(op, c_op, asm_op) \
+ ATOMIC_FETCH_OP(op, c_op, asm_op)
+
+ATOMIC_OPS(and, &=, and)
+ATOMIC_OPS(andnot, &= ~, bic)
+ATOMIC_OPS(or, |=, or)
+ATOMIC_OPS(xor, ^=, xor)
+
+#define arch_atomic_andnot arch_atomic_andnot
+
+#undef ATOMIC_OPS
+#undef ATOMIC_FETCH_OP
+#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP
+
+#endif
diff --git a/arch/arc/include/asm/atomic-spinlock.h b/arch/arc/include/asm/atomic-spinlock.h
new file mode 100644
index 000000000000..2c830347bfb4
--- /dev/null
+++ b/arch/arc/include/asm/atomic-spinlock.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ASM_ARC_ATOMIC_SPLOCK_H
+#define _ASM_ARC_ATOMIC_SPLOCK_H
+
+/*
+ * Non hardware assisted Atomic-R-M-W
+ * Locking would change to irq-disabling only (UP) and spinlocks (SMP)
+ */
+
+static inline void arch_atomic_set(atomic_t *v, int i)
+{
+ /*
+ * Independent of hardware support, all of the atomic_xxx() APIs need
+ * to follow the same locking rules to make sure that a "hardware"
+ * atomic insn (e.g. LD) doesn't clobber an "emulated" atomic insn
+ * sequence
+ *
+ * Thus atomic_set() despite being 1 insn (and seemingly atomic)
+ * requires the locking.
+ */
+ unsigned long flags;
+
+ atomic_ops_lock(flags);
+ WRITE_ONCE(v->counter, i);
+ atomic_ops_unlock(flags);
+}
+
+#define arch_atomic_set_release(v, i) arch_atomic_set((v), (i))
+
+#define ATOMIC_OP(op, c_op, asm_op) \
+static inline void arch_atomic_##op(int i, atomic_t *v) \
+{ \
+ unsigned long flags; \
+ \
+ atomic_ops_lock(flags); \
+ v->counter c_op i; \
+ atomic_ops_unlock(flags); \
+}
+
+#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
+static inline int arch_atomic_##op##_return(int i, atomic_t *v) \
+{ \
+ unsigned long flags; \
+ unsigned int temp; \
+ \
+ /* \
+ * spin lock/unlock provides the needed smp_mb() before/after \
+ */ \
+ atomic_ops_lock(flags); \
+ temp = v->counter; \
+ temp c_op i; \
+ v->counter = temp; \
+ atomic_ops_unlock(flags); \
+ \
+ return temp; \
+}
+
+#define ATOMIC_FETCH_OP(op, c_op, asm_op) \
+static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \
+{ \
+ unsigned long flags; \
+ unsigned int orig; \
+ \
+ /* \
+ * spin lock/unlock provides the needed smp_mb() before/after \
+ */ \
+ atomic_ops_lock(flags); \
+ orig = v->counter; \
+ v->counter c_op i; \
+ atomic_ops_unlock(flags); \
+ \
+ return orig; \
+}
+
+#define ATOMIC_OPS(op, c_op, asm_op) \
+ ATOMIC_OP(op, c_op, asm_op) \
+ ATOMIC_OP_RETURN(op, c_op, asm_op) \
+ ATOMIC_FETCH_OP(op, c_op, asm_op)
+
+ATOMIC_OPS(add, +=, add)
+ATOMIC_OPS(sub, -=, sub)
+
+#undef ATOMIC_OPS
+#define ATOMIC_OPS(op, c_op, asm_op) \
+ ATOMIC_OP(op, c_op, asm_op) \
+ ATOMIC_FETCH_OP(op, c_op, asm_op)
+
+ATOMIC_OPS(and, &=, and)
+ATOMIC_OPS(andnot, &= ~, bic)
+ATOMIC_OPS(or, |=, or)
+ATOMIC_OPS(xor, ^=, xor)
+
+#define arch_atomic_andnot arch_atomic_andnot
+#define arch_atomic_fetch_andnot arch_atomic_fetch_andnot
+
+#undef ATOMIC_OPS
+#undef ATOMIC_FETCH_OP
+#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP
+
+#endif
diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h
index 7a36d79b5b2f..52ee51e1ff7c 100644
--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -17,435 +17,43 @@
#define arch_atomic_read(v) READ_ONCE((v)->counter)
#ifdef CONFIG_ARC_HAS_LLSC
-
-#define arch_atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
-
-#define ATOMIC_OP(op, c_op, asm_op) \
-static inline void arch_atomic_##op(int i, atomic_t *v) \
-{ \
- unsigned int val; \
- \
- __asm__ __volatile__( \
- "1: llock %[val], [%[ctr]] \n" \
- " " #asm_op " %[val], %[val], %[i] \n" \
- " scond %[val], [%[ctr]] \n" \
- " bnz 1b \n" \
- : [val] "=&r" (val) /* Early clobber to prevent reg reuse */ \
- : [ctr] "r" (&v->counter), /* Not "m": llock only supports reg direct addr mode */ \
- [i] "ir" (i) \
- : "cc"); \
-} \
-
-#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
-static inline int arch_atomic_##op##_return(int i, atomic_t *v) \
-{ \
- unsigned int val; \
- \
- /* \
- * Explicit full memory barrier needed before/after as \
- * LLOCK/SCOND themselves don't provide any such semantics \
- */ \
- smp_mb(); \
- \
- __asm__ __volatile__( \
- "1: llock %[val], [%[ctr]] \n" \
- " " #asm_op " %[val], %[val], %[i] \n" \
- " scond %[val], [%[ctr]] \n" \
- " bnz 1b \n" \
- : [val] "=&r" (val) \
- : [ctr] "r" (&v->counter), \
- [i] "ir" (i) \
- : "cc"); \
- \
- smp_mb(); \
- \
- return val; \
-}
-
-#define ATOMIC_FETCH_OP(op, c_op, asm_op) \
-static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \
-{ \
- unsigned int val, orig; \
- \
- /* \
- * Explicit full memory barrier needed before/after as \
- * LLOCK/SCOND themselves don't provide any such semantics \
- */ \
- smp_mb(); \
- \
- __asm__ __volatile__( \
- "1: llock %[orig], [%[ctr]] \n" \
- " " #asm_op " %[val], %[orig], %[i] \n" \
- " scond %[val], [%[ctr]] \n" \
- " bnz 1b \n" \
- : [val] "=&r" (val), \
- [orig] "=&r" (orig) \
- : [ctr] "r" (&v->counter), \
- [i] "ir" (i) \
- : "cc"); \
- \
- smp_mb(); \
- \
- return orig; \
-}
-
-#else /* !CONFIG_ARC_HAS_LLSC */
-
-#ifndef CONFIG_SMP
-
- /* violating atomic_xxx API locking protocol in UP for optimization sake */
-#define arch_atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
-
+#include <asm/atomic-llsc.h>
#else
+#include <asm/atomic-spinlock.h>
+#endif
-static inline void arch_atomic_set(atomic_t *v, int i)
-{
- /*
- * Independent of hardware support, all of the atomic_xxx() APIs need
- * to follow the same locking rules to make sure that a "hardware"
- * atomic insn (e.g. LD) doesn't clobber an "emulated" atomic insn
- * sequence
- *
- * Thus atomic_set() despite being 1 insn (and seemingly atomic)
- * requires the locking.
- */
- unsigned long flags;
+#define arch_atomic_cmpxchg(v, o, n) \
+({ \
+ arch_cmpxchg(&((v)->counter), (o), (n)); \
+})
- atomic_ops_lock(flags);
- WRITE_ONCE(v->counter, i);
- atomic_ops_unlock(flags);
-}
+#ifdef arch_cmpxchg_relaxed
+#define arch_atomic_cmpxchg_relaxed(v, o, n) \
+({ \
+ arch_cmpxchg_relaxed(&((v)->counter), (o), (n)); \
+})
+#endif
-#define arch_atomic_set_release(v, i) arch_atomic_set((v), (i))
+#define arch_atomic_xchg(v, n) \
+({ \
+ arch_xchg(&((v)->counter), (n)); \
+})
+#ifdef arch_xchg_relaxed
+#define arch_atomic_xchg_relaxed(v, n) \
+({ \
+ arch_xchg_relaxed(&((v)->counter), (n)); \
+})
#endif
/*
- * Non hardware assisted Atomic-R-M-W
- * Locking would change to irq-disabling only (UP) and spinlocks (SMP)
+ * 64-bit atomics
*/
-
-#define ATOMIC_OP(op, c_op, asm_op) \
-static inline void arch_atomic_##op(int i, atomic_t *v) \
-{ \
- unsigned long flags; \
- \
- atomic_ops_lock(flags); \
- v->counter c_op i; \
- atomic_ops_unlock(flags); \
-}
-
-#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
-static inline int arch_atomic_##op##_return(int i, atomic_t *v) \
-{ \
- unsigned long flags; \
- unsigned long temp; \
- \
- /* \
- * spin lock/unlock provides the needed smp_mb() before/after \
- */ \
- atomic_ops_lock(flags); \
- temp = v->counter; \
- temp c_op i; \
- v->counter = temp; \
- atomic_ops_unlock(flags); \
- \
- return temp; \
-}
-
-#define ATOMIC_FETCH_OP(op, c_op, asm_op) \
-static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \
-{ \
- unsigned long flags; \
- unsigned long orig; \
- \
- /* \
- * spin lock/unlock provides the needed smp_mb() before/after \
- */ \
- atomic_ops_lock(flags); \
- orig = v->counter; \
- v->counter c_op i; \
- atomic_ops_unlock(flags); \
- \
- return orig; \
-}
-
-#endif /* !CONFIG_ARC_HAS_LLSC */
-
-#define ATOMIC_OPS(op, c_op, asm_op) \
- ATOMIC_OP(op, c_op, asm_op) \
- ATOMIC_OP_RETURN(op, c_op, asm_op) \
- ATOMIC_FETCH_OP(op, c_op, asm_op)
-
-ATOMIC_OPS(add, +=, add)
-ATOMIC_OPS(sub, -=, sub)
-
-#undef ATOMIC_OPS
-#define ATOMIC_OPS(op, c_op, asm_op) \
- ATOMIC_OP(op, c_op, asm_op) \
- ATOMIC_FETCH_OP(op, c_op, asm_op)
-
-ATOMIC_OPS(and, &=, and)
-ATOMIC_OPS(andnot, &= ~, bic)
-ATOMIC_OPS(or, |=, or)
-ATOMIC_OPS(xor, ^=, xor)
-
-#define arch_atomic_andnot arch_atomic_andnot
-#define arch_atomic_fetch_andnot arch_atomic_fetch_andnot
-
-#undef ATOMIC_OPS
-#undef ATOMIC_FETCH_OP
-#undef ATOMIC_OP_RETURN
-#undef ATOMIC_OP
-
#ifdef CONFIG_GENERIC_ATOMIC64
-
#include <asm-generic/atomic64.h>
-
-#else /* Kconfig ensures this is only enabled with needed h/w assist */
-
-/*
- * ARCv2 supports 64-bit exclusive load (LLOCKD) / store (SCONDD)
- * - The address HAS to be 64-bit aligned
- * - There are 2 semantics involved here:
- * = exclusive implies no interim update between load/store to same addr
- * = both words are observed/updated together: this is guaranteed even
- * for regular 64-bit load (LDD) / store (STD). Thus atomic64_set()
- * is NOT required to use LLOCKD+SCONDD, STD suffices
- */
-
-typedef struct {
- s64 __aligned(8) counter;
-} atomic64_t;
-
-#define ATOMIC64_INIT(a) { (a) }
-
-static inline s64 arch_atomic64_read(const atomic64_t *v)
-{
- s64 val;
-
- __asm__ __volatile__(
- " ldd %0, [%1] \n"
- : "=r"(val)
- : "r"(&v->counter));
-
- return val;
-}
-
-static inline void arch_atomic64_set(atomic64_t *v, s64 a)
-{
- /*
- * This could have been a simple assignment in "C" but would need
- * explicit volatile. Otherwise gcc optimizers could elide the store
- * which borked atomic64 self-test
- * In the inline asm version, memory clobber needed for exact same
- * reason, to tell gcc about the store.
- *
- * This however is not needed for sibling atomic64_add() etc since both
- * load/store are explicitly done in inline asm. As long as API is used
- * for each access, gcc has no way to optimize away any load/store
- */
- __asm__ __volatile__(
- " std %0, [%1] \n"
- :
- : "r"(a), "r"(&v->counter)
- : "memory");
-}
-
-#define ATOMIC64_OP(op, op1, op2) \
-static inline void arch_atomic64_##op(s64 a, atomic64_t *v) \
-{ \
- s64 val; \
- \
- __asm__ __volatile__( \
- "1: \n" \
- " llockd %0, [%1] \n" \
- " " #op1 " %L0, %L0, %L2 \n" \
- " " #op2 " %H0, %H0, %H2 \n" \
- " scondd %0, [%1] \n" \
- " bnz 1b \n" \
- : "=&r"(val) \
- : "r"(&v->counter), "ir"(a) \
- : "cc"); \
-} \
-
-#define ATOMIC64_OP_RETURN(op, op1, op2) \
-static inline s64 arch_atomic64_##op##_return(s64 a, atomic64_t *v) \
-{ \
- s64 val; \
- \
- smp_mb(); \
- \
- __asm__ __volatile__( \
- "1: \n" \
- " llockd %0, [%1] \n" \
- " " #op1 " %L0, %L0, %L2 \n" \
- " " #op2 " %H0, %H0, %H2 \n" \
- " scondd %0, [%1] \n" \
- " bnz 1b \n" \
- : [val] "=&r"(val) \
- : "r"(&v->counter), "ir"(a) \
- : "cc"); /* memory clobber comes from smp_mb() */ \
- \
- smp_mb(); \
- \
- return val; \
-}
-
-#define ATOMIC64_FETCH_OP(op, op1, op2) \
-static inline s64 arch_atomic64_fetch_##op(s64 a, atomic64_t *v) \
-{ \
- s64 val, orig; \
- \
- smp_mb(); \
- \
- __asm__ __volatile__( \
- "1: \n" \
- " llockd %0, [%2] \n" \
- " " #op1 " %L1, %L0, %L3 \n" \
- " " #op2 " %H1, %H0, %H3 \n" \
- " scondd %1, [%2] \n" \
- " bnz 1b \n" \
- : "=&r"(orig), "=&r"(val) \
- : "r"(&v->counter), "ir"(a) \
- : "cc"); /* memory clobber comes from smp_mb() */ \
- \
- smp_mb(); \
- \
- return orig; \
-}
-
-#define ATOMIC64_OPS(op, op1, op2) \
- ATOMIC64_OP(op, op1, op2) \
- ATOMIC64_OP_RETURN(op, op1, op2) \
- ATOMIC64_FETCH_OP(op, op1, op2)
-
-ATOMIC64_OPS(add, add.f, adc)
-ATOMIC64_OPS(sub, sub.f, sbc)
-ATOMIC64_OPS(and, and, and)
-ATOMIC64_OPS(andnot, bic, bic)
-ATOMIC64_OPS(or, or, or)
-ATOMIC64_OPS(xor, xor, xor)
-
-#define arch_atomic64_andnot arch_atomic64_andnot
-#define arch_atomic64_fetch_andnot arch_atomic64_fetch_andnot
-
-#undef ATOMIC64_OPS
-#undef ATOMIC64_FETCH_OP
-#undef ATOMIC64_OP_RETURN
-#undef ATOMIC64_OP
-
-static inline s64
-arch_atomic64_cmpxchg(atomic64_t *ptr, s64 expected, s64 new)
-{
- s64 prev;
-
- smp_mb();
-
- __asm__ __volatile__(
- "1: llockd %0, [%1] \n"
- " brne %L0, %L2, 2f \n"
- " brne %H0, %H2, 2f \n"
- " scondd %3, [%1] \n"
- " bnz 1b \n"
- "2: \n"
- : "=&r"(prev)
- : "r"(ptr), "ir"(expected), "r"(new)
- : "cc"); /* memory clobber comes from smp_mb() */
-
- smp_mb();
-
- return prev;
-}
-
-static inline s64 arch_atomic64_xchg(atomic64_t *ptr, s64 new)
-{
- s64 prev;
-
- smp_mb();
-
- __asm__ __volatile__(
- "1: llockd %0, [%1] \n"
- " scondd %2, [%1] \n"
- " bnz 1b \n"
- "2: \n"
- : "=&r"(prev)
- : "r"(ptr), "r"(new)
- : "cc"); /* memory clobber comes from smp_mb() */
-
- smp_mb();
-
- return prev;
-}
-
-/**
- * arch_atomic64_dec_if_positive - decrement by 1 if old value positive
- * @v: pointer of type atomic64_t
- *
- * The function returns the old value of *v minus 1, even if
- * the atomic variable, v, was not decremented.
- */
-
-static inline s64 arch_atomic64_dec_if_positive(atomic64_t *v)
-{
- s64 val;
-
- smp_mb();
-
- __asm__ __volatile__(
- "1: llockd %0, [%1] \n"
- " sub.f %L0, %L0, 1 # w0 - 1, set C on borrow\n"
- " sub.c %H0, %H0, 1 # if C set, w1 - 1\n"
- " brlt %H0, 0, 2f \n"
- " scondd %0, [%1] \n"
- " bnz 1b \n"
- "2: \n"
- : "=&r"(val)
- : "r"(&v->counter)
- : "cc"); /* memory clobber comes from smp_mb() */
-
- smp_mb();
-
- return val;
-}
-#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive
-
-/**
- * arch_atomic64_fetch_add_unless - add unless the number is a given value
- * @v: pointer of type atomic64_t
- * @a: the amount to add to v...
- * @u: ...unless v is equal to u.
- *
- * Atomically adds @a to @v, if it was not @u.
- * Returns the old value of @v
- */
-static inline s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u)
-{
- s64 old, temp;
-
- smp_mb();
-
- __asm__ __volatile__(
- "1: llockd %0, [%2] \n"
- " brne %L0, %L4, 2f # continue to add since v != u \n"
- " breq.d %H0, %H4, 3f # return since v == u \n"
- "2: \n"
- " add.f %L1, %L0, %L3 \n"
- " adc %H1, %H0, %H3 \n"
- " scondd %1, [%2] \n"
- " bnz 1b \n"
- "3: \n"
- : "=&r"(old), "=&r" (temp)
- : "r"(&v->counter), "r"(a), "r"(u)
- : "cc"); /* memory clobber comes from smp_mb() */
-
- smp_mb();
-
- return old;
-}
-#define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless
-
-#endif /* !CONFIG_GENERIC_ATOMIC64 */
+#else
+#include <asm/atomic64-arcv2.h>
+#endif
#endif /* !__ASSEMBLY__ */
diff --git a/arch/arc/include/asm/atomic64-arcv2.h b/arch/arc/include/asm/atomic64-arcv2.h
new file mode 100644
index 000000000000..c5a8010fdc97
--- /dev/null
+++ b/arch/arc/include/asm/atomic64-arcv2.h
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * ARCv2 supports 64-bit exclusive load (LLOCKD) / store (SCONDD)
+ * - The address HAS to be 64-bit aligned
+ */
+
+#ifndef _ASM_ARC_ATOMIC64_ARCV2_H
+#define _ASM_ARC_ATOMIC64_ARCV2_H
+
+typedef struct {
+ s64 __aligned(8) counter;
+} atomic64_t;
+
+#define ATOMIC64_INIT(a) { (a) }
+
+static inline s64 arch_atomic64_read(const atomic64_t *v)
+{
+ s64 val;
+
+ __asm__ __volatile__(
+ " ldd %0, [%1] \n"
+ : "=r"(val)
+ : "r"(&v->counter));
+
+ return val;
+}
+
+static inline void arch_atomic64_set(atomic64_t *v, s64 a)
+{
+ /*
+ * This could have been a simple assignment in "C" but would need
+ * explicit volatile. Otherwise gcc optimizers could elide the store
+ * which borked atomic64 self-test
+ * In the inline asm version, memory clobber needed for exact same
+ * reason, to tell gcc about the store.
+ *
+ * This however is not needed for sibling atomic64_add() etc since both
+ * load/store are explicitly done in inline asm. As long as API is used
+ * for each access, gcc has no way to optimize away any load/store
+ */
+ __asm__ __volatile__(
+ " std %0, [%1] \n"
+ :
+ : "r"(a), "r"(&v->counter)
+ : "memory");
+}
+
+#define ATOMIC64_OP(op, op1, op2) \
+static inline void arch_atomic64_##op(s64 a, atomic64_t *v) \
+{ \
+ s64 val; \
+ \
+ __asm__ __volatile__( \
+ "1: \n" \
+ " llockd %0, [%1] \n" \
+ " " #op1 " %L0, %L0, %L2 \n" \
+ " " #op2 " %H0, %H0, %H2 \n" \
+ " scondd %0, [%1] \n" \
+ " bnz 1b \n" \
+ : "=&r"(val) \
+ : "r"(&v->counter), "ir"(a) \
+ : "cc"); \
+} \
+
+#define ATOMIC64_OP_RETURN(op, op1, op2) \
+static inline s64 arch_atomic64_##op##_return_relaxed(s64 a, atomic64_t *v) \
+{ \
+ s64 val; \
+ \
+ __asm__ __volatile__( \
+ "1: \n" \
+ " llockd %0, [%1] \n" \
+ " " #op1 " %L0, %L0, %L2 \n" \
+ " " #op2 " %H0, %H0, %H2 \n" \
+ " scondd %0, [%1] \n" \
+ " bnz 1b \n" \
+ : [val] "=&r"(val) \
+ : "r"(&v->counter), "ir"(a) \
+ : "cc"); /* memory clobber comes from smp_mb() */ \
+ \
+ return val; \
+}
+
+#define arch_atomic64_add_return_relaxed arch_atomic64_add_return_relaxed
+#define arch_atomic64_sub_return_relaxed arch_atomic64_sub_return_relaxed
+
+#define ATOMIC64_FETCH_OP(op, op1, op2) \
+static inline s64 arch_atomic64_fetch_##op##_relaxed(s64 a, atomic64_t *v) \
+{ \
+ s64 val, orig; \
+ \
+ __asm__ __volatile__( \
+ "1: \n" \
+ " llockd %0, [%2] \n" \
+ " " #op1 " %L1, %L0, %L3 \n" \
+ " " #op2 " %H1, %H0, %H3 \n" \
+ " scondd %1, [%2] \n" \
+ " bnz 1b \n" \
+ : "=&r"(orig), "=&r"(val) \
+ : "r"(&v->counter), "ir"(a) \
+ : "cc"); /* memory clobber comes from smp_mb() */ \
+ \
+ return orig; \
+}
+
+#define arch_atomic64_fetch_add_relaxed arch_atomic64_fetch_add_relaxed
+#define arch_atomic64_fetch_sub_relaxed arch_atomic64_fetch_sub_relaxed
+
+#define arch_atomic64_fetch_and_relaxed arch_atomic64_fetch_and_relaxed
+#define arch_atomic64_fetch_andnot_relaxed arch_atomic64_fetch_andnot_relaxed
+#define arch_atomic64_fetch_or_relaxed arch_atomic64_fetch_or_relaxed
+#define arch_atomic64_fetch_xor_relaxed arch_atomic64_fetch_xor_relaxed
+
+#define ATOMIC64_OPS(op, op1, op2) \
+ ATOMIC64_OP(op, op1, op2) \
+ ATOMIC64_OP_RETURN(op, op1, op2) \
+ ATOMIC64_FETCH_OP(op, op1, op2)
+
+ATOMIC64_OPS(add, add.f, adc)
+ATOMIC64_OPS(sub, sub.f, sbc)
+
+#undef ATOMIC64_OPS
+#define ATOMIC64_OPS(op, op1, op2) \
+ ATOMIC64_OP(op, op1, op2) \
+ ATOMIC64_FETCH_OP(op, op1, op2)
+
+ATOMIC64_OPS(and, and, and)
+ATOMIC64_OPS(andnot, bic, bic)
+ATOMIC64_OPS(or, or, or)
+ATOMIC64_OPS(xor, xor, xor)
+
+#define arch_atomic64_andnot arch_atomic64_andnot
+
+#undef ATOMIC64_OPS
+#undef ATOMIC64_FETCH_OP
+#undef ATOMIC64_OP_RETURN
+#undef ATOMIC64_OP
+
+static inline s64
+arch_atomic64_cmpxchg(atomic64_t *ptr, s64 expected, s64 new)
+{
+ s64 prev;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "1: llockd %0, [%1] \n"
+ " brne %L0, %L2, 2f \n"
+ " brne %H0, %H2, 2f \n"
+ " scondd %3, [%1] \n"
+ " bnz 1b \n"
+ "2: \n"
+ : "=&r"(prev)
+ : "r"(ptr), "ir"(expected), "r"(new)
+ : "cc"); /* memory clobber comes from smp_mb() */
+
+ smp_mb();
+
+ return prev;
+}
+
+static inline s64 arch_atomic64_xchg(atomic64_t *ptr, s64 new)
+{
+ s64 prev;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "1: llockd %0, [%1] \n"
+ " scondd %2, [%1] \n"
+ " bnz 1b \n"
+ "2: \n"
+ : "=&r"(prev)
+ : "r"(ptr), "r"(new)
+ : "cc"); /* memory clobber comes from smp_mb() */
+
+ smp_mb();
+
+ return prev;
+}
+
+/**
+ * arch_atomic64_dec_if_positive - decrement by 1 if old value positive
+ * @v: pointer of type atomic64_t
+ *
+ * The function returns the old value of *v minus 1, even if
+ * the atomic variable, v, was not decremented.
+ */
+
+static inline s64 arch_atomic64_dec_if_positive(atomic64_t *v)
+{
+ s64 val;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "1: llockd %0, [%1] \n"
+ " sub.f %L0, %L0, 1 # w0 - 1, set C on borrow\n"
+ " sub.c %H0, %H0, 1 # if C set, w1 - 1\n"
+ " brlt %H0, 0, 2f \n"
+ " scondd %0, [%1] \n"
+ " bnz 1b \n"
+ "2: \n"
+ : "=&r"(val)
+ : "r"(&v->counter)
+ : "cc"); /* memory clobber comes from smp_mb() */
+
+ smp_mb();
+
+ return val;
+}
+#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive
+
+/**
+ * arch_atomic64_fetch_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, if it was not @u.
+ * Returns the old value of @v
+ */
+static inline s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u)
+{
+ s64 old, temp;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "1: llockd %0, [%2] \n"
+ " brne %L0, %L4, 2f # continue to add since v != u \n"
+ " breq.d %H0, %H4, 3f # return since v == u \n"
+ "2: \n"
+ " add.f %L1, %L0, %L3 \n"
+ " adc %H1, %H0, %H3 \n"
+ " scondd %1, [%2] \n"
+ " bnz 1b \n"
+ "3: \n"
+ : "=&r"(old), "=&r" (temp)
+ : "r"(&v->counter), "r"(a), "r"(u)
+ : "cc"); /* memory clobber comes from smp_mb() */
+
+ smp_mb();
+
+ return old;
+}
+#define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless
+
+#endif
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index fb98440c0bd4..a7daaf64ae34 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -14,188 +14,6 @@
#include <linux/types.h>
#include <linux/compiler.h>
-#include <asm/barrier.h>
-#ifndef CONFIG_ARC_HAS_LLSC
-#include <asm/smp.h>
-#endif
-
-#ifdef CONFIG_ARC_HAS_LLSC
-
-/*
- * Hardware assisted Atomic-R-M-W
- */
-
-#define BIT_OP(op, c_op, asm_op) \
-static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
-{ \
- unsigned int temp; \
- \
- m += nr >> 5; \
- \
- nr &= 0x1f; \
- \
- __asm__ __volatile__( \
- "1: llock %0, [%1] \n" \
- " " #asm_op " %0, %0, %2 \n" \
- " scond %0, [%1] \n" \
- " bnz 1b \n" \
- : "=&r"(temp) /* Early clobber, to prevent reg reuse */ \
- : "r"(m), /* Not "m": llock only supports reg direct addr mode */ \
- "ir"(nr) \
- : "cc"); \
-}
-
-/*
- * Semantically:
- * Test the bit
- * if clear
- * set it and return 0 (old value)
- * else
- * return 1 (old value).
- *
- * Since ARC lacks a equivalent h/w primitive, the bit is set unconditionally
- * and the old value of bit is returned
- */
-#define TEST_N_BIT_OP(op, c_op, asm_op) \
-static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
-{ \
- unsigned long old, temp; \
- \
- m += nr >> 5; \
- \
- nr &= 0x1f; \
- \
- /* \
- * Explicit full memory barrier needed before/after as \
- * LLOCK/SCOND themselves don't provide any such smenatic \
- */ \
- smp_mb(); \
- \
- __asm__ __volatile__( \
- "1: llock %0, [%2] \n" \
- " " #asm_op " %1, %0, %3 \n" \
- " scond %1, [%2] \n" \
- " bnz 1b \n" \
- : "=&r"(old), "=&r"(temp) \
- : "r"(m), "ir"(nr) \
- : "cc"); \
- \
- smp_mb(); \
- \
- return (old & (1 << nr)) != 0; \
-}
-
-#else /* !CONFIG_ARC_HAS_LLSC */
-
-/*
- * Non hardware assisted Atomic-R-M-W
- * Locking would change to irq-disabling only (UP) and spinlocks (SMP)
- *
- * There's "significant" micro-optimization in writing our own variants of
- * bitops (over generic variants)
- *
- * (1) The generic APIs have "signed" @nr while we have it "unsigned"
- * This avoids extra code to be generated for pointer arithmatic, since
- * is "not sure" that index is NOT -ve
- * (2) Utilize the fact that ARCompact bit fidding insn (BSET/BCLR/ASL) etc
- * only consider bottom 5 bits of @nr, so NO need to mask them off.
- * (GCC Quirk: however for constant @nr we still need to do the masking
- * at compile time)
- */
-
-#define BIT_OP(op, c_op, asm_op) \
-static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
-{ \
- unsigned long temp, flags; \
- m += nr >> 5; \
- \
- /* \
- * spin lock/unlock provide the needed smp_mb() before/after \
- */ \
- bitops_lock(flags); \
- \
- temp = *m; \
- *m = temp c_op (1UL << (nr & 0x1f)); \
- \
- bitops_unlock(flags); \
-}
-
-#define TEST_N_BIT_OP(op, c_op, asm_op) \
-static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
-{ \
- unsigned long old, flags; \
- m += nr >> 5; \
- \
- bitops_lock(flags); \
- \
- old = *m; \
- *m = old c_op (1UL << (nr & 0x1f)); \
- \
- bitops_unlock(flags); \
- \
- return (old & (1UL << (nr & 0x1f))) != 0; \
-}
-
-#endif
-
-/***************************************
- * Non atomic variants
- **************************************/
-
-#define __BIT_OP(op, c_op, asm_op) \
-static inline void __##op##_bit(unsigned long nr, volatile unsigned long *m) \
-{ \
- unsigned long temp; \
- m += nr >> 5; \
- \
- temp = *m; \
- *m = temp c_op (1UL << (nr & 0x1f)); \
-}
-
-#define __TEST_N_BIT_OP(op, c_op, asm_op) \
-static inline int __test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
-{ \
- unsigned long old; \
- m += nr >> 5; \
- \
- old = *m; \
- *m = old c_op (1UL << (nr & 0x1f)); \
- \
- return (old & (1UL << (nr & 0x1f))) != 0; \
-}
-
-#define BIT_OPS(op, c_op, asm_op) \
- \
- /* set_bit(), clear_bit(), change_bit() */ \
- BIT_OP(op, c_op, asm_op) \
- \
- /* test_and_set_bit(), test_and_clear_bit(), test_and_change_bit() */\
- TEST_N_BIT_OP(op, c_op, asm_op) \
- \
- /* __set_bit(), __clear_bit(), __change_bit() */ \
- __BIT_OP(op, c_op, asm_op) \
- \
- /* __test_and_set_bit(), __test_and_clear_bit(), __test_and_change_bit() */\
- __TEST_N_BIT_OP(op, c_op, asm_op)
-
-BIT_OPS(set, |, bset)
-BIT_OPS(clear, & ~, bclr)
-BIT_OPS(change, ^, bxor)
-
-/*
- * This routine doesn't need to be atomic.
- */
-static inline int
-test_bit(unsigned int nr, const volatile unsigned long *addr)
-{
- unsigned long mask;
-
- addr += nr >> 5;
-
- mask = 1UL << (nr & 0x1f);
-
- return ((mask & *addr) != 0);
-}
#ifdef CONFIG_ISA_ARCOMPACT
@@ -296,7 +114,7 @@ static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
* @result: [1-32]
* fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
*/
-static inline __attribute__ ((const)) int fls(unsigned long x)
+static inline __attribute__ ((const)) int fls(unsigned int x)
{
int n;
@@ -323,7 +141,7 @@ static inline __attribute__ ((const)) int __fls(unsigned long x)
* ffs = Find First Set in word (LSB to MSB)
* @result: [1-32], 0 if all 0's
*/
-static inline __attribute__ ((const)) int ffs(unsigned long x)
+static inline __attribute__ ((const)) int ffs(unsigned int x)
{
int n;
@@ -368,6 +186,8 @@ static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/atomic.h>
+#include <asm-generic/bitops/non-atomic.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/le.h>
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index d8ece4292388..f0f1fc5d62b6 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -62,10 +62,6 @@
#define ARCH_SLAB_MINALIGN 8
#endif
-extern void arc_cache_init(void);
-extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len);
-extern void read_decode_cache_bcr(void);
-
extern int ioc_enable;
extern unsigned long perip_base, perip_end;
diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h
index d42917e803e1..c5b544a5fe81 100644
--- a/arch/arc/include/asm/cmpxchg.h
+++ b/arch/arc/include/asm/cmpxchg.h
@@ -6,6 +6,7 @@
#ifndef __ASM_ARC_CMPXCHG_H
#define __ASM_ARC_CMPXCHG_H
+#include <linux/build_bug.h>
#include <linux/types.h>
#include <asm/barrier.h>
@@ -13,146 +14,130 @@
#ifdef CONFIG_ARC_HAS_LLSC
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
-{
- unsigned long prev;
-
- /*
- * Explicit full memory barrier needed before/after as
- * LLOCK/SCOND themselves don't provide any such semantics
- */
- smp_mb();
-
- __asm__ __volatile__(
- "1: llock %0, [%1] \n"
- " brne %0, %2, 2f \n"
- " scond %3, [%1] \n"
- " bnz 1b \n"
- "2: \n"
- : "=&r"(prev) /* Early clobber, to prevent reg reuse */
- : "r"(ptr), /* Not "m": llock only supports reg direct addr mode */
- "ir"(expected),
- "r"(new) /* can't be "ir". scond can't take LIMM for "b" */
- : "cc", "memory"); /* so that gcc knows memory is being written here */
-
- smp_mb();
-
- return prev;
-}
-
-#else /* !CONFIG_ARC_HAS_LLSC */
-
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
-{
- unsigned long flags;
- int prev;
- volatile unsigned long *p = ptr;
-
- /*
- * spin lock/unlock provide the needed smp_mb() before/after
- */
- atomic_ops_lock(flags);
- prev = *p;
- if (prev == expected)
- *p = new;
- atomic_ops_unlock(flags);
- return prev;
-}
-
-#endif
+/*
+ * if (*ptr == @old)
+ * *ptr = @new
+ */
+#define __cmpxchg(ptr, old, new) \
+({ \
+ __typeof__(*(ptr)) _prev; \
+ \
+ __asm__ __volatile__( \
+ "1: llock %0, [%1] \n" \
+ " brne %0, %2, 2f \n" \
+ " scond %3, [%1] \n" \
+ " bnz 1b \n" \
+ "2: \n" \
+ : "=&r"(_prev) /* Early clobber prevent reg reuse */ \
+ : "r"(ptr), /* Not "m": llock only supports reg */ \
+ "ir"(old), \
+ "r"(new) /* Not "ir": scond can't take LIMM */ \
+ : "cc", \
+ "memory"); /* gcc knows memory is clobbered */ \
+ \
+ _prev; \
+})
-#define arch_cmpxchg(ptr, o, n) ({ \
- (typeof(*(ptr)))__cmpxchg((ptr), \
- (unsigned long)(o), \
- (unsigned long)(n)); \
+#define arch_cmpxchg_relaxed(ptr, old, new) \
+({ \
+ __typeof__(ptr) _p_ = (ptr); \
+ __typeof__(*(ptr)) _o_ = (old); \
+ __typeof__(*(ptr)) _n_ = (new); \
+ __typeof__(*(ptr)) _prev_; \
+ \
+ switch(sizeof((_p_))) { \
+ case 4: \
+ _prev_ = __cmpxchg(_p_, _o_, _n_); \
+ break; \
+ default: \
+ BUILD_BUG(); \
+ } \
+ _prev_; \
})
-/*
- * atomic_cmpxchg is same as cmpxchg
- * LLSC: only different in data-type, semantics are exactly same
- * !LLSC: cmpxchg() has to use an external lock atomic_ops_lock to guarantee
- * semantics, and this lock also happens to be used by atomic_*()
- */
-#define arch_atomic_cmpxchg(v, o, n) ((int)arch_cmpxchg(&((v)->counter), (o), (n)))
+#else
+#define arch_cmpxchg(ptr, old, new) \
+({ \
+ volatile __typeof__(ptr) _p_ = (ptr); \
+ __typeof__(*(ptr)) _o_ = (old); \
+ __typeof__(*(ptr)) _n_ = (new); \
+ __typeof__(*(ptr)) _prev_; \
+ unsigned long __flags; \
+ \
+ BUILD_BUG_ON(sizeof(_p_) != 4); \
+ \
+ /* \
+ * spin lock/unlock provide the needed smp_mb() before/after \
+ */ \
+ atomic_ops_lock(__flags); \
+ _prev_ = *_p_; \
+ if (_prev_ == _o_) \
+ *_p_ = _n_; \
+ atomic_ops_unlock(__flags); \
+ _prev_; \
+})
+
+#endif
/*
- * xchg (reg with memory) based on "Native atomic" EX insn
+ * xchg
*/
-static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
- int size)
-{
- extern unsigned long __xchg_bad_pointer(void);
-
- switch (size) {
- case 4:
- smp_mb();
-
- __asm__ __volatile__(
- " ex %0, [%1] \n"
- : "+r"(val)
- : "r"(ptr)
- : "memory");
+#ifdef CONFIG_ARC_HAS_LLSC
- smp_mb();
+#define __xchg(ptr, val) \
+({ \
+ __asm__ __volatile__( \
+ " ex %0, [%1] \n" /* set new value */ \
+ : "+r"(val) \
+ : "r"(ptr) \
+ : "memory"); \
+ _val_; /* get old value */ \
+})
- return val;
- }
- return __xchg_bad_pointer();
-}
+#define arch_xchg_relaxed(ptr, val) \
+({ \
+ __typeof__(ptr) _p_ = (ptr); \
+ __typeof__(*(ptr)) _val_ = (val); \
+ \
+ switch(sizeof(*(_p_))) { \
+ case 4: \
+ _val_ = __xchg(_p_, _val_); \
+ break; \
+ default: \
+ BUILD_BUG(); \
+ } \
+ _val_; \
+})
-#define _xchg(ptr, with) ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), \
- sizeof(*(ptr))))
+#else /* !CONFIG_ARC_HAS_LLSC */
/*
- * xchg() maps directly to ARC EX instruction which guarantees atomicity.
- * However in !LLSC config, it also needs to be use @atomic_ops_lock spinlock
- * due to a subtle reason:
- * - For !LLSC, cmpxchg() needs to use that lock (see above) and there is lot
- * of kernel code which calls xchg()/cmpxchg() on same data (see llist.h)
- * Hence xchg() needs to follow same locking rules.
- *
- * Technically the lock is also needed for UP (boils down to irq save/restore)
- * but we can cheat a bit since cmpxchg() atomic_ops_lock() would cause irqs to
- * be disabled thus can't possibly be interrupted/preempted/clobbered by xchg()
- * Other way around, xchg is one instruction anyways, so can't be interrupted
- * as such
+ * EX instructions is baseline and present in !LLSC too. But in this
+ * regime it still needs use @atomic_ops_lock spinlock to allow interop
+ * with cmpxchg() which uses spinlock in !LLSC
+ * (llist.h use xchg and cmpxchg on sama data)
*/
-#if !defined(CONFIG_ARC_HAS_LLSC) && defined(CONFIG_SMP)
-
-#define arch_xchg(ptr, with) \
-({ \
- unsigned long flags; \
- typeof(*(ptr)) old_val; \
- \
- atomic_ops_lock(flags); \
- old_val = _xchg(ptr, with); \
- atomic_ops_unlock(flags); \
- old_val; \
+#define arch_xchg(ptr, val) \
+({ \
+ __typeof__(ptr) _p_ = (ptr); \
+ __typeof__(*(ptr)) _val_ = (val); \
+ \
+ unsigned long __flags; \
+ \
+ atomic_ops_lock(__flags); \
+ \
+ __asm__ __volatile__( \
+ " ex %0, [%1] \n" \
+ : "+r"(_val_) \
+ : "r"(_p_) \
+ : "memory"); \
+ \
+ atomic_ops_unlock(__flags); \
+ _val_; \
})
-#else
-
-#define arch_xchg(ptr, with) _xchg(ptr, with)
-
#endif
-/*
- * "atomic" variant of xchg()
- * REQ: It needs to follow the same serialization rules as other atomic_xxx()
- * Since xchg() doesn't always do that, it would seem that following definition
- * is incorrect. But here's the rationale:
- * SMP : Even xchg() takes the atomic_ops_lock, so OK.
- * LLSC: atomic_ops_lock are not relevant at all (even if SMP, since LLSC
- * is natively "SMP safe", no serialization required).
- * UP : other atomics disable IRQ, so no way a difft ctxt atomic_xchg()
- * could clobber them. atomic_xchg() itself would be 1 insn, so it
- * can't be clobbered by others. Thus no serialization required when
- * atomic_xchg is involved.
- */
-#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new))
-
#endif
diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h
index 6dbf5cecc8cc..5aab4f93ab8a 100644
--- a/arch/arc/include/asm/entry-compact.h
+++ b/arch/arc/include/asm/entry-compact.h
@@ -126,19 +126,11 @@
* to be saved again on kernel mode stack, as part of pt_regs.
*-------------------------------------------------------------*/
.macro PROLOG_FREEUP_REG reg, mem
-#ifndef ARC_USE_SCRATCH_REG
- sr \reg, [ARC_REG_SCRATCH_DATA0]
-#else
st \reg, [\mem]
-#endif
.endm
.macro PROLOG_RESTORE_REG reg, mem
-#ifndef ARC_USE_SCRATCH_REG
- lr \reg, [ARC_REG_SCRATCH_DATA0]
-#else
ld \reg, [\mem]
-#endif
.endm
/*--------------------------------------------------------------
diff --git a/arch/arc/include/asm/hugepage.h b/arch/arc/include/asm/hugepage.h
index 4eef17c5c1da..11b0ff26b97b 100644
--- a/arch/arc/include/asm/hugepage.h
+++ b/arch/arc/include/asm/hugepage.h
@@ -58,14 +58,6 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
pmd_t *pmd);
-/* Generic variants assume pgtable_t is struct page *, hence need for these */
-#define __HAVE_ARCH_PGTABLE_DEPOSIT
-extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
- pgtable_t pgtable);
-
-#define __HAVE_ARCH_PGTABLE_WITHDRAW
-extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
-
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
extern void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
diff --git a/arch/arc/include/asm/mmu-arcv2.h b/arch/arc/include/asm/mmu-arcv2.h
new file mode 100644
index 000000000000..ed9036d4ede3
--- /dev/null
+++ b/arch/arc/include/asm/mmu-arcv2.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2012, 2019-20 Synopsys, Inc. (www.synopsys.com)
+ *
+ * MMUv3 (arc700) / MMUv4 (archs) are software page walked and software managed.
+ * This file contains the TLB access registers and commands
+ */
+
+#ifndef _ASM_ARC_MMU_ARCV2_H
+#define _ASM_ARC_MMU_ARCV2_H
+
+/*
+ * TLB Management regs
+ */
+#define ARC_REG_MMU_BCR 0x06f
+
+#ifdef CONFIG_ARC_MMU_V3
+#define ARC_REG_TLBPD0 0x405
+#define ARC_REG_TLBPD1 0x406
+#define ARC_REG_TLBPD1HI 0 /* Dummy: allows common code */
+#define ARC_REG_TLBINDEX 0x407
+#define ARC_REG_TLBCOMMAND 0x408
+#define ARC_REG_PID 0x409
+#define ARC_REG_SCRATCH_DATA0 0x418
+#else
+#define ARC_REG_TLBPD0 0x460
+#define ARC_REG_TLBPD1 0x461
+#define ARC_REG_TLBPD1HI 0x463
+#define ARC_REG_TLBINDEX 0x464
+#define ARC_REG_TLBCOMMAND 0x465
+#define ARC_REG_PID 0x468
+#define ARC_REG_SCRATCH_DATA0 0x46c
+#endif
+
+/* Bits in MMU PID reg */
+#define __TLB_ENABLE (1 << 31)
+#define __PROG_ENABLE (1 << 30)
+#define MMU_ENABLE (__TLB_ENABLE | __PROG_ENABLE)
+
+/* Bits in TLB Index reg */
+#define TLB_LKUP_ERR 0x80000000
+
+#ifdef CONFIG_ARC_MMU_V3
+#define TLB_DUP_ERR (TLB_LKUP_ERR | 0x00000001)
+#else
+#define TLB_DUP_ERR (TLB_LKUP_ERR | 0x40000000)
+#endif
+
+/*
+ * TLB Commands
+ */
+#define TLBWrite 0x1
+#define TLBRead 0x2
+#define TLBGetIndex 0x3
+#define TLBProbe 0x4
+#define TLBWriteNI 0x5 /* write JTLB without inv uTLBs */
+#define TLBIVUTLB 0x6 /* explicitly inv uTLBs */
+
+#ifdef CONFIG_ARC_MMU_V4
+#define TLBInsertEntry 0x7
+#define TLBDeleteEntry 0x8
+#endif
+
+/* Masks for actual TLB "PD"s */
+#define PTE_BITS_IN_PD0 (_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_HW_SZ)
+#define PTE_BITS_RWX (_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ)
+
+#define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK_PHYS | _PAGE_CACHEABLE)
+
+#ifndef __ASSEMBLY__
+
+struct mm_struct;
+extern int pae40_exist_but_not_enab(void);
+
+static inline int is_pae40_enabled(void)
+{
+ return IS_ENABLED(CONFIG_ARC_HAS_PAE40);
+}
+
+static inline void mmu_setup_asid(struct mm_struct *mm, unsigned long asid)
+{
+ write_aux_reg(ARC_REG_PID, asid | MMU_ENABLE);
+}
+
+static inline void mmu_setup_pgd(struct mm_struct *mm, void *pgd)
+{
+ /* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
+#ifdef CONFIG_ISA_ARCV2
+ write_aux_reg(ARC_REG_SCRATCH_DATA0, (unsigned int)pgd);
+#endif
+}
+
+#else
+
+.macro ARC_MMU_REENABLE reg
+ lr \reg, [ARC_REG_PID]
+ or \reg, \reg, MMU_ENABLE
+ sr \reg, [ARC_REG_PID]
+.endm
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h
index 26b731d32a2b..ca427c30f70e 100644
--- a/arch/arc/include/asm/mmu.h
+++ b/arch/arc/include/asm/mmu.h
@@ -7,98 +7,15 @@
#define _ASM_ARC_MMU_H
#ifndef __ASSEMBLY__
-#include <linux/threads.h> /* NR_CPUS */
-#endif
-
-#if defined(CONFIG_ARC_MMU_V1)
-#define CONFIG_ARC_MMU_VER 1
-#elif defined(CONFIG_ARC_MMU_V2)
-#define CONFIG_ARC_MMU_VER 2
-#elif defined(CONFIG_ARC_MMU_V3)
-#define CONFIG_ARC_MMU_VER 3
-#elif defined(CONFIG_ARC_MMU_V4)
-#define CONFIG_ARC_MMU_VER 4
-#endif
-
-/* MMU Management regs */
-#define ARC_REG_MMU_BCR 0x06f
-#if (CONFIG_ARC_MMU_VER < 4)
-#define ARC_REG_TLBPD0 0x405
-#define ARC_REG_TLBPD1 0x406
-#define ARC_REG_TLBPD1HI 0 /* Dummy: allows code sharing with ARC700 */
-#define ARC_REG_TLBINDEX 0x407
-#define ARC_REG_TLBCOMMAND 0x408
-#define ARC_REG_PID 0x409
-#define ARC_REG_SCRATCH_DATA0 0x418
-#else
-#define ARC_REG_TLBPD0 0x460
-#define ARC_REG_TLBPD1 0x461
-#define ARC_REG_TLBPD1HI 0x463
-#define ARC_REG_TLBINDEX 0x464
-#define ARC_REG_TLBCOMMAND 0x465
-#define ARC_REG_PID 0x468
-#define ARC_REG_SCRATCH_DATA0 0x46c
-#endif
-
-#if defined(CONFIG_ISA_ARCV2) || !defined(CONFIG_SMP)
-#define ARC_USE_SCRATCH_REG
-#endif
-
-/* Bits in MMU PID register */
-#define __TLB_ENABLE (1 << 31)
-#define __PROG_ENABLE (1 << 30)
-#define MMU_ENABLE (__TLB_ENABLE | __PROG_ENABLE)
-
-/* Error code if probe fails */
-#define TLB_LKUP_ERR 0x80000000
-
-#if (CONFIG_ARC_MMU_VER < 4)
-#define TLB_DUP_ERR (TLB_LKUP_ERR | 0x00000001)
-#else
-#define TLB_DUP_ERR (TLB_LKUP_ERR | 0x40000000)
-#endif
-
-/* TLB Commands */
-#define TLBWrite 0x1
-#define TLBRead 0x2
-#define TLBGetIndex 0x3
-#define TLBProbe 0x4
-
-#if (CONFIG_ARC_MMU_VER >= 2)
-#define TLBWriteNI 0x5 /* write JTLB without inv uTLBs */
-#define TLBIVUTLB 0x6 /* explicitly inv uTLBs */
-#else
-#define TLBWriteNI TLBWrite /* Not present in hardware, fallback */
-#endif
-
-#if (CONFIG_ARC_MMU_VER >= 4)
-#define TLBInsertEntry 0x7
-#define TLBDeleteEntry 0x8
-#endif
-#ifndef __ASSEMBLY__
+#include <linux/threads.h> /* NR_CPUS */
typedef struct {
unsigned long asid[NR_CPUS]; /* 8 bit MMU PID + Generation cycle */
} mm_context_t;
-#ifdef CONFIG_ARC_DBG_TLB_PARANOIA
-void tlb_paranoid_check(unsigned int mm_asid, unsigned long address);
-#else
-#define tlb_paranoid_check(a, b)
#endif
-void arc_mmu_init(void);
-extern char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len);
-void read_decode_mmu_bcr(void);
-
-static inline int is_pae40_enabled(void)
-{
- return IS_ENABLED(CONFIG_ARC_HAS_PAE40);
-}
-
-extern int pae40_exist_but_not_enab(void);
-
-#endif /* !__ASSEMBLY__ */
+#include <asm/mmu-arcv2.h>
#endif
diff --git a/arch/arc/include/asm/mmu_context.h b/arch/arc/include/asm/mmu_context.h
index df164066e172..dda471f5f05b 100644
--- a/arch/arc/include/asm/mmu_context.h
+++ b/arch/arc/include/asm/mmu_context.h
@@ -15,22 +15,23 @@
#ifndef _ASM_ARC_MMU_CONTEXT_H
#define _ASM_ARC_MMU_CONTEXT_H
-#include <asm/arcregs.h>
-#include <asm/tlb.h>
#include <linux/sched/mm.h>
+#include <asm/tlb.h>
#include <asm-generic/mm_hooks.h>
-/* ARC700 ASID Management
+/* ARC ASID Management
+ *
+ * MMU tags TLBs with an 8-bit ASID, avoiding need to flush the TLB on
+ * context-switch.
*
- * ARC MMU provides 8-bit ASID (0..255) to TAG TLB entries, allowing entries
- * with same vaddr (different tasks) to co-exit. This provides for
- * "Fast Context Switch" i.e. no TLB flush on ctxt-switch
+ * ASID is managed per cpu, so task threads across CPUs can have different
+ * ASID. Global ASID management is needed if hardware supports TLB shootdown
+ * and/or shared TLB across cores, which ARC doesn't.
*
- * Linux assigns each task a unique ASID. A simple round-robin allocation
- * of H/w ASID is done using software tracker @asid_cpu.
- * When it reaches max 255, the allocation cycle starts afresh by flushing
- * the entire TLB and wrapping ASID back to zero.
+ * Each task is assigned unique ASID, with a simple round-robin allocator
+ * tracked in @asid_cpu. When 8-bit value rolls over,a new cycle is started
+ * over from 0, and TLB is flushed
*
* A new allocation cycle, post rollover, could potentially reassign an ASID
* to a different task. Thus the rule is to refresh the ASID in a new cycle.
@@ -93,7 +94,7 @@ static inline void get_new_mmu_context(struct mm_struct *mm)
asid_mm(mm, cpu) = asid_cpu(cpu);
set_hw:
- write_aux_reg(ARC_REG_PID, hw_pid(mm, cpu) | MMU_ENABLE);
+ mmu_setup_asid(mm, hw_pid(mm, cpu));
local_irq_restore(flags);
}
@@ -146,10 +147,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
*/
cpumask_set_cpu(cpu, mm_cpumask(next));
-#ifdef ARC_USE_SCRATCH_REG
- /* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
- write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
-#endif
+ mmu_setup_pgd(next, next->pgd);
get_new_mmu_context(next);
}
diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
index 4a9d33372fe2..9a62e1d87967 100644
--- a/arch/arc/include/asm/page.h
+++ b/arch/arc/include/asm/page.h
@@ -34,57 +34,55 @@ void copy_user_highpage(struct page *to, struct page *from,
unsigned long u_vaddr, struct vm_area_struct *vma);
void clear_user_page(void *to, unsigned long u_vaddr, struct page *page);
-#undef STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct {
-#ifdef CONFIG_ARC_HAS_PAE40
- unsigned long long pte;
-#else
- unsigned long pte;
-#endif
-} pte_t;
typedef struct {
unsigned long pgd;
} pgd_t;
+
+#define pgd_val(x) ((x).pgd)
+#define __pgd(x) ((pgd_t) { (x) })
+
+#if CONFIG_PGTABLE_LEVELS > 3
+
typedef struct {
- unsigned long pgprot;
-} pgprot_t;
+ unsigned long pud;
+} pud_t;
-#define pte_val(x) ((x).pte)
-#define pgd_val(x) ((x).pgd)
-#define pgprot_val(x) ((x).pgprot)
+#define pud_val(x) ((x).pud)
+#define __pud(x) ((pud_t) { (x) })
-#define __pte(x) ((pte_t) { (x) })
-#define __pgd(x) ((pgd_t) { (x) })
-#define __pgprot(x) ((pgprot_t) { (x) })
+#endif
+
+#if CONFIG_PGTABLE_LEVELS > 2
-#define pte_pgprot(x) __pgprot(pte_val(x))
+typedef struct {
+ unsigned long pmd;
+} pmd_t;
-#else /* !STRICT_MM_TYPECHECKS */
+#define pmd_val(x) ((x).pmd)
+#define __pmd(x) ((pmd_t) { (x) })
+#endif
+
+typedef struct {
#ifdef CONFIG_ARC_HAS_PAE40
-typedef unsigned long long pte_t;
+ unsigned long long pte;
#else
-typedef unsigned long pte_t;
+ unsigned long pte;
#endif
-typedef unsigned long pgd_t;
-typedef unsigned long pgprot_t;
+} pte_t;
-#define pte_val(x) (x)
-#define pgd_val(x) (x)
-#define pgprot_val(x) (x)
-#define __pte(x) (x)
-#define __pgd(x) (x)
-#define __pgprot(x) (x)
-#define pte_pgprot(x) (x)
+#define pte_val(x) ((x).pte)
+#define __pte(x) ((pte_t) { (x) })
-#endif
+typedef struct {
+ unsigned long pgprot;
+} pgprot_t;
+
+#define pgprot_val(x) ((x).pgprot)
+#define __pgprot(x) ((pgprot_t) { (x) })
+#define pte_pgprot(x) __pgprot(pte_val(x))
-typedef pte_t * pgtable_t;
+typedef struct page *pgtable_t;
/*
* Use virt_to_pfn with caution:
@@ -122,8 +120,8 @@ extern int pfn_valid(unsigned long pfn);
* virt here means link-address/program-address as embedded in object code.
* And for ARC, link-addr = physical address
*/
-#define __pa(vaddr) ((unsigned long)(vaddr))
-#define __va(paddr) ((void *)((unsigned long)(paddr)))
+#define __pa(vaddr) ((unsigned long)(vaddr))
+#define __va(paddr) ((void *)((unsigned long)(paddr)))
#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
diff --git a/arch/arc/include/asm/pgalloc.h b/arch/arc/include/asm/pgalloc.h
index a32ca3104ced..096b8ef58edb 100644
--- a/arch/arc/include/asm/pgalloc.h
+++ b/arch/arc/include/asm/pgalloc.h
@@ -31,30 +31,32 @@
#include <linux/mm.h>
#include <linux/log2.h>
+#include <asm-generic/pgalloc.h>
static inline void
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
{
- pmd_set(pmd, pte);
+ /*
+ * The cast to long below is OK in 32-bit PAE40 regime with long long pte
+ * Despite "wider" pte, the pte table needs to be in non-PAE low memory
+ * as all higher levels can only hold long pointers.
+ *
+ * The cast itself is needed given simplistic definition of set_pmd()
+ */
+ set_pmd(pmd, __pmd((unsigned long)pte));
}
-static inline void
-pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t ptep)
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t pte_page)
{
- pmd_set(pmd, (pte_t *) ptep);
-}
-
-static inline int __get_order_pgd(void)
-{
- return get_order(PTRS_PER_PGD * sizeof(pgd_t));
+ set_pmd(pmd, __pmd((unsigned long)page_address(pte_page)));
}
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
- int num, num2;
- pgd_t *ret = (pgd_t *) __get_free_pages(GFP_KERNEL, __get_order_pgd());
+ pgd_t *ret = (pgd_t *) __get_free_page(GFP_KERNEL);
if (ret) {
+ int num, num2;
num = USER_PTRS_PER_PGD + USER_KERNEL_GUTTER / PGDIR_SIZE;
memzero(ret, num * sizeof(pgd_t));
@@ -68,64 +70,27 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
return ret;
}
-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
- free_pages((unsigned long)pgd, __get_order_pgd());
-}
-
-
-/*
- * With software-only page-tables, addr-split for traversal is tweakable and
- * that directly governs how big tables would be at each level.
- * Further, the MMU page size is configurable.
- * Thus we need to programatically assert the size constraint
- * All of this is const math, allowing gcc to do constant folding/propagation.
- */
+#if CONFIG_PGTABLE_LEVELS > 3
-static inline int __get_order_pte(void)
+static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4dp, pud_t *pudp)
{
- return get_order(PTRS_PER_PTE * sizeof(pte_t));
+ set_p4d(p4dp, __p4d((unsigned long)pudp));
}
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
-{
- pte_t *pte;
+#define __pud_free_tlb(tlb, pmd, addr) pud_free((tlb)->mm, pmd)
- pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
- __get_order_pte());
+#endif
- return pte;
-}
+#if CONFIG_PGTABLE_LEVELS > 2
-static inline pgtable_t
-pte_alloc_one(struct mm_struct *mm)
+static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmdp)
{
- pgtable_t pte_pg;
- struct page *page;
-
- pte_pg = (pgtable_t)__get_free_pages(GFP_KERNEL, __get_order_pte());
- if (!pte_pg)
- return 0;
- memzero((void *)pte_pg, PTRS_PER_PTE * sizeof(pte_t));
- page = virt_to_page(pte_pg);
- if (!pgtable_pte_page_ctor(page)) {
- __free_page(page);
- return 0;
- }
-
- return pte_pg;
+ set_pud(pudp, __pud((unsigned long)pmdp));
}
-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
- free_pages((unsigned long)pte, __get_order_pte()); /* takes phy addr */
-}
+#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
-static inline void pte_free(struct mm_struct *mm, pgtable_t ptep)
-{
- pgtable_pte_page_dtor(virt_to_page(ptep));
- free_pages((unsigned long)ptep, __get_order_pte());
-}
+#endif
#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
diff --git a/arch/arc/include/asm/pgtable-bits-arcv2.h b/arch/arc/include/asm/pgtable-bits-arcv2.h
new file mode 100644
index 000000000000..183d23bc1e00
--- /dev/null
+++ b/arch/arc/include/asm/pgtable-bits-arcv2.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ */
+
+/*
+ * page table flags for software walked/managed MMUv3 (ARC700) and MMUv4 (HS)
+ * There correspond to the corresponding bits in the TLB
+ */
+
+#ifndef _ASM_ARC_PGTABLE_BITS_ARCV2_H
+#define _ASM_ARC_PGTABLE_BITS_ARCV2_H
+
+#ifdef CONFIG_ARC_CACHE_PAGES
+#define _PAGE_CACHEABLE (1 << 0) /* Cached (H) */
+#else
+#define _PAGE_CACHEABLE 0
+#endif
+
+#define _PAGE_EXECUTE (1 << 1) /* User Execute (H) */
+#define _PAGE_WRITE (1 << 2) /* User Write (H) */
+#define _PAGE_READ (1 << 3) /* User Read (H) */
+#define _PAGE_ACCESSED (1 << 4) /* Accessed (s) */
+#define _PAGE_DIRTY (1 << 5) /* Modified (s) */
+#define _PAGE_SPECIAL (1 << 6)
+#define _PAGE_GLOBAL (1 << 8) /* ASID agnostic (H) */
+#define _PAGE_PRESENT (1 << 9) /* PTE/TLB Valid (H) */
+
+#ifdef CONFIG_ARC_MMU_V4
+#define _PAGE_HW_SZ (1 << 10) /* Normal/super (H) */
+#else
+#define _PAGE_HW_SZ 0
+#endif
+
+/* Defaults for every user page */
+#define ___DEF (_PAGE_PRESENT | _PAGE_CACHEABLE)
+
+/* Set of bits not changed in pte_modify */
+#define _PAGE_CHG_MASK (PAGE_MASK_PHYS | _PAGE_ACCESSED | _PAGE_DIRTY | \
+ _PAGE_SPECIAL)
+
+/* More Abbrevaited helpers */
+#define PAGE_U_NONE __pgprot(___DEF)
+#define PAGE_U_R __pgprot(___DEF | _PAGE_READ)
+#define PAGE_U_W_R __pgprot(___DEF | _PAGE_READ | _PAGE_WRITE)
+#define PAGE_U_X_R __pgprot(___DEF | _PAGE_READ | _PAGE_EXECUTE)
+#define PAGE_U_X_W_R __pgprot(___DEF \
+ | _PAGE_READ | _PAGE_WRITE | _PAGE_EXECUTE)
+#define PAGE_KERNEL __pgprot(___DEF | _PAGE_GLOBAL \
+ | _PAGE_READ | _PAGE_WRITE | _PAGE_EXECUTE)
+
+#define PAGE_SHARED PAGE_U_W_R
+
+#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) & ~_PAGE_CACHEABLE))
+
+/*
+ * Mapping of vm_flags (Generic VM) to PTE flags (arch specific)
+ *
+ * Certain cases have 1:1 mapping
+ * e.g. __P101 means VM_READ, VM_EXEC and !VM_SHARED
+ * which directly corresponds to PAGE_U_X_R
+ *
+ * Other rules which cause the divergence from 1:1 mapping
+ *
+ * 1. Although ARC700 can do exclusive execute/write protection (meaning R
+ * can be tracked independet of X/W unlike some other CPUs), still to
+ * keep things consistent with other archs:
+ * -Write implies Read: W => R
+ * -Execute implies Read: X => R
+ *
+ * 2. Pvt Writable doesn't have Write Enabled initially: Pvt-W => !W
+ * This is to enable COW mechanism
+ */
+ /* xwr */
+#define __P000 PAGE_U_NONE
+#define __P001 PAGE_U_R
+#define __P010 PAGE_U_R /* Pvt-W => !W */
+#define __P011 PAGE_U_R /* Pvt-W => !W */
+#define __P100 PAGE_U_X_R /* X => R */
+#define __P101 PAGE_U_X_R
+#define __P110 PAGE_U_X_R /* Pvt-W => !W and X => R */
+#define __P111 PAGE_U_X_R /* Pvt-W => !W */
+
+#define __S000 PAGE_U_NONE
+#define __S001 PAGE_U_R
+#define __S010 PAGE_U_W_R /* W => R */
+#define __S011 PAGE_U_W_R
+#define __S100 PAGE_U_X_R /* X => R */
+#define __S101 PAGE_U_X_R
+#define __S110 PAGE_U_X_W_R /* X => R */
+#define __S111 PAGE_U_X_W_R
+
+#ifndef __ASSEMBLY__
+
+#define pte_write(pte) (pte_val(pte) & _PAGE_WRITE)
+#define pte_dirty(pte) (pte_val(pte) & _PAGE_DIRTY)
+#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED)
+#define pte_special(pte) (pte_val(pte) & _PAGE_SPECIAL)
+
+#define PTE_BIT_FUNC(fn, op) \
+ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
+
+PTE_BIT_FUNC(mknotpresent, &= ~(_PAGE_PRESENT));
+PTE_BIT_FUNC(wrprotect, &= ~(_PAGE_WRITE));
+PTE_BIT_FUNC(mkwrite, |= (_PAGE_WRITE));
+PTE_BIT_FUNC(mkclean, &= ~(_PAGE_DIRTY));
+PTE_BIT_FUNC(mkdirty, |= (_PAGE_DIRTY));
+PTE_BIT_FUNC(mkold, &= ~(_PAGE_ACCESSED));
+PTE_BIT_FUNC(mkyoung, |= (_PAGE_ACCESSED));
+PTE_BIT_FUNC(mkspecial, |= (_PAGE_SPECIAL));
+PTE_BIT_FUNC(mkhuge, |= (_PAGE_HW_SZ));
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+ return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+}
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pteval)
+{
+ set_pte(ptep, pteval);
+}
+
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
+ pte_t *ptep);
+
+/* Encode swap {type,off} tuple into PTE
+ * We reserve 13 bits for 5-bit @type, keeping bits 12-5 zero, ensuring that
+ * PAGE_PRESENT is zero in a PTE holding swap "identifier"
+ */
+#define __swp_entry(type, off) ((swp_entry_t) \
+ { ((type) & 0x1f) | ((off) << 13) })
+
+/* Decode a PTE containing swap "identifier "into constituents */
+#define __swp_type(pte_lookalike) (((pte_lookalike).val) & 0x1f)
+#define __swp_offset(pte_lookalike) ((pte_lookalike).val >> 13)
+
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+#define kern_addr_valid(addr) (1)
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#include <asm/hugepage.h>
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/arc/include/asm/pgtable-levels.h b/arch/arc/include/asm/pgtable-levels.h
new file mode 100644
index 000000000000..8084ef2f6491
--- /dev/null
+++ b/arch/arc/include/asm/pgtable-levels.h
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com)
+ */
+
+/*
+ * Helpers for implemenintg paging levels
+ */
+
+#ifndef _ASM_ARC_PGTABLE_LEVELS_H
+#define _ASM_ARC_PGTABLE_LEVELS_H
+
+#if CONFIG_PGTABLE_LEVELS == 2
+
+/*
+ * 2 level paging setup for software walked MMUv3 (ARC700) and MMUv4 (HS)
+ *
+ * [31] 32 bit virtual address [0]
+ * -------------------------------------------------------
+ * | | <---------- PGDIR_SHIFT ----------> |
+ * | | | <-- PAGE_SHIFT --> |
+ * -------------------------------------------------------
+ * | | |
+ * | | --> off in page frame
+ * | ---> index into Page Table
+ * ----> index into Page Directory
+ *
+ * Given software walk, the vaddr split is arbitrary set to 11:8:13
+ * However enabling of super page in a 2 level regime pegs PGDIR_SHIFT to
+ * super page size.
+ */
+
+#if defined(CONFIG_ARC_HUGEPAGE_16M)
+#define PGDIR_SHIFT 24
+#elif defined(CONFIG_ARC_HUGEPAGE_2M)
+#define PGDIR_SHIFT 21
+#else
+/*
+ * No Super page case
+ * Default value provides 11:8:13 (8K), 10:10:12 (4K)
+ * Limits imposed by pgtable_t only PAGE_SIZE long
+ * (so 4K page can only have 1K entries: or 10 bits)
+ */
+#ifdef CONFIG_ARC_PAGE_SIZE_4K
+#define PGDIR_SHIFT 22
+#else
+#define PGDIR_SHIFT 21
+#endif
+
+#endif
+
+#else /* CONFIG_PGTABLE_LEVELS != 2 */
+
+/*
+ * A default 3 level paging testing setup in software walked MMU
+ * MMUv4 (8K page): <4> : <7> : <8> : <13>
+ * A default 4 level paging testing setup in software walked MMU
+ * MMUv4 (8K page): <4> : <3> : <4> : <8> : <13>
+ */
+#define PGDIR_SHIFT 28
+#if CONFIG_PGTABLE_LEVELS > 3
+#define PUD_SHIFT 25
+#endif
+#if CONFIG_PGTABLE_LEVELS > 2
+#define PMD_SHIFT 21
+#endif
+
+#endif /* CONFIG_PGTABLE_LEVELS */
+
+#define PGDIR_SIZE BIT(PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE - 1))
+#define PTRS_PER_PGD BIT(32 - PGDIR_SHIFT)
+
+#if CONFIG_PGTABLE_LEVELS > 3
+#define PUD_SIZE BIT(PUD_SHIFT)
+#define PUD_MASK (~(PUD_SIZE - 1))
+#define PTRS_PER_PUD BIT(PGDIR_SHIFT - PUD_SHIFT)
+#endif
+
+#if CONFIG_PGTABLE_LEVELS > 2
+#define PMD_SIZE BIT(PMD_SHIFT)
+#define PMD_MASK (~(PMD_SIZE - 1))
+#define PTRS_PER_PMD BIT(PUD_SHIFT - PMD_SHIFT)
+#endif
+
+#define PTRS_PER_PTE BIT(PMD_SHIFT - PAGE_SHIFT)
+
+#ifndef __ASSEMBLY__
+
+#if CONFIG_PGTABLE_LEVELS > 3
+#include <asm-generic/pgtable-nop4d.h>
+#elif CONFIG_PGTABLE_LEVELS > 2
+#include <asm-generic/pgtable-nopud.h>
+#else
+#include <asm-generic/pgtable-nopmd.h>
+#endif
+
+/*
+ * 1st level paging: pgd
+ */
+#define pgd_index(addr) ((addr) >> PGDIR_SHIFT)
+#define pgd_offset(mm, addr) (((mm)->pgd) + pgd_index(addr))
+#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
+#define pgd_ERROR(e) \
+ pr_crit("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+#if CONFIG_PGTABLE_LEVELS > 3
+
+/* In 4 level paging, p4d_* macros work on pgd */
+#define p4d_none(x) (!p4d_val(x))
+#define p4d_bad(x) ((p4d_val(x) & ~PAGE_MASK))
+#define p4d_present(x) (p4d_val(x))
+#define p4d_clear(xp) do { p4d_val(*(xp)) = 0; } while (0)
+#define p4d_pgtable(p4d) ((pud_t *)(p4d_val(p4d) & PAGE_MASK))
+#define p4d_page(p4d) virt_to_page(p4d_pgtable(p4d))
+#define set_p4d(p4dp, p4d) (*(p4dp) = p4d)
+
+/*
+ * 2nd level paging: pud
+ */
+#define pud_ERROR(e) \
+ pr_crit("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))
+
+#endif
+
+#if CONFIG_PGTABLE_LEVELS > 2
+
+/*
+ * In 3 level paging, pud_* macros work on pgd
+ * In 4 level paging, pud_* macros work on pud
+ */
+#define pud_none(x) (!pud_val(x))
+#define pud_bad(x) ((pud_val(x) & ~PAGE_MASK))
+#define pud_present(x) (pud_val(x))
+#define pud_clear(xp) do { pud_val(*(xp)) = 0; } while (0)
+#define pud_pgtable(pud) ((pmd_t *)(pud_val(pud) & PAGE_MASK))
+#define pud_page(pud) virt_to_page(pud_pgtable(pud))
+#define set_pud(pudp, pud) (*(pudp) = pud)
+
+/*
+ * 3rd level paging: pmd
+ */
+#define pmd_ERROR(e) \
+ pr_crit("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+
+#define pmd_pfn(pmd) ((pmd_val(pmd) & PMD_MASK) >> PAGE_SHIFT)
+#define pfn_pmd(pfn,prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot)
+
+#endif
+
+/*
+ * Due to the strange way generic pgtable level folding works, the pmd_* macros
+ * - are valid even for 2 levels (which supposedly only has pgd - pte)
+ * - behave differently for 2 vs. 3
+ * In 2 level paging (pgd -> pte), pmd_* macros work on pgd
+ * In 3+ level paging (pgd -> pmd -> pte), pmd_* macros work on pmd
+ */
+#define pmd_none(x) (!pmd_val(x))
+#define pmd_bad(x) ((pmd_val(x) & ~PAGE_MASK))
+#define pmd_present(x) (pmd_val(x))
+#define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0)
+#define pmd_page_vaddr(pmd) (pmd_val(pmd) & PAGE_MASK)
+#define pmd_page(pmd) virt_to_page(pmd_page_vaddr(pmd))
+#define set_pmd(pmdp, pmd) (*(pmdp) = pmd)
+#define pmd_pgtable(pmd) ((pgtable_t) pmd_page_vaddr(pmd))
+
+/*
+ * 4th level paging: pte
+ */
+#define pte_ERROR(e) \
+ pr_crit("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+
+#define pte_none(x) (!pte_val(x))
+#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
+#define pte_clear(mm,addr,ptep) set_pte_at(mm, addr, ptep, __pte(0))
+#define pte_page(pte) pfn_to_page(pte_pfn(pte))
+#define set_pte(ptep, pte) ((*(ptep)) = (pte))
+#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
+#define pfn_pte(pfn, prot) __pte(__pfn_to_phys(pfn) | pgprot_val(prot))
+#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
+
+#ifdef CONFIG_ISA_ARCV2
+#define pmd_leaf(x) (pmd_val(x) & _PAGE_HW_SZ)
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
index 320cc0ae8a08..9320b04c04bf 100644
--- a/arch/arc/include/asm/pgtable.h
+++ b/arch/arc/include/asm/pgtable.h
@@ -1,220 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * vineetg: May 2011
- * -Folded PAGE_PRESENT (used by VM) and PAGE_VALID (used by MMU) into 1.
- * They are semantically the same although in different contexts
- * VALID marks a TLB entry exists and it will only happen if PRESENT
- * - Utilise some unused free bits to confine PTE flags to 12 bits
- * This is a must for 4k pg-sz
- *
- * vineetg: Mar 2011 - changes to accommodate MMU TLB Page Descriptor mods
- * -TLB Locking never really existed, except for initial specs
- * -SILENT_xxx not needed for our port
- * -Per my request, MMU V3 changes the layout of some of the bits
- * to avoid a few shifts in TLB Miss handlers.
- *
- * vineetg: April 2010
- * -PGD entry no longer contains any flags. If empty it is 0, otherwise has
- * Pg-Tbl ptr. Thus pmd_present(), pmd_valid(), pmd_set( ) become simpler
- *
- * vineetg: April 2010
- * -Switched form 8:11:13 split for page table lookup to 11:8:13
- * -this speeds up page table allocation itself as we now have to memset 1K
- * instead of 8k per page table.
- * -TODO: Right now page table alloc is 8K and rest 7K is unused
- * need to optimise it
- *
- * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
*/
#ifndef _ASM_ARC_PGTABLE_H
#define _ASM_ARC_PGTABLE_H
#include <linux/bits.h>
-#include <asm-generic/pgtable-nopmd.h>
-#include <asm/page.h>
-#include <asm/mmu.h> /* to propagate CONFIG_ARC_MMU_VER <n> */
-
-/**************************************************************************
- * Page Table Flags
- *
- * ARC700 MMU only deals with softare managed TLB entries.
- * Page Tables are purely for Linux VM's consumption and the bits below are
- * suited to that (uniqueness). Hence some are not implemented in the TLB and
- * some have different value in TLB.
- * e.g. MMU v2: K_READ bit is 8 and so is GLOBAL (possible because they live in
- * seperate PD0 and PD1, which combined forms a translation entry)
- * while for PTE perspective, they are 8 and 9 respectively
- * with MMU v3: Most bits (except SHARED) represent the exact hardware pos
- * (saves some bit shift ops in TLB Miss hdlrs)
- */
-
-#if (CONFIG_ARC_MMU_VER <= 2)
-
-#define _PAGE_ACCESSED (1<<1) /* Page is accessed (S) */
-#define _PAGE_CACHEABLE (1<<2) /* Page is cached (H) */
-#define _PAGE_EXECUTE (1<<3) /* Page has user execute perm (H) */
-#define _PAGE_WRITE (1<<4) /* Page has user write perm (H) */
-#define _PAGE_READ (1<<5) /* Page has user read perm (H) */
-#define _PAGE_DIRTY (1<<6) /* Page modified (dirty) (S) */
-#define _PAGE_SPECIAL (1<<7)
-#define _PAGE_GLOBAL (1<<8) /* Page is global (H) */
-#define _PAGE_PRESENT (1<<10) /* TLB entry is valid (H) */
-
-#else /* MMU v3 onwards */
-
-#define _PAGE_CACHEABLE (1<<0) /* Page is cached (H) */
-#define _PAGE_EXECUTE (1<<1) /* Page has user execute perm (H) */
-#define _PAGE_WRITE (1<<2) /* Page has user write perm (H) */
-#define _PAGE_READ (1<<3) /* Page has user read perm (H) */
-#define _PAGE_ACCESSED (1<<4) /* Page is accessed (S) */
-#define _PAGE_DIRTY (1<<5) /* Page modified (dirty) (S) */
-#define _PAGE_SPECIAL (1<<6)
-
-#if (CONFIG_ARC_MMU_VER >= 4)
-#define _PAGE_WTHRU (1<<7) /* Page cache mode write-thru (H) */
-#endif
-
-#define _PAGE_GLOBAL (1<<8) /* Page is global (H) */
-#define _PAGE_PRESENT (1<<9) /* TLB entry is valid (H) */
-
-#if (CONFIG_ARC_MMU_VER >= 4)
-#define _PAGE_HW_SZ (1<<10) /* Page Size indicator (H): 0 normal, 1 super */
-#endif
-
-#define _PAGE_SHARED_CODE (1<<11) /* Shared Code page with cmn vaddr
- usable for shared TLB entries (H) */
-
-#define _PAGE_UNUSED_BIT (1<<12)
-#endif
-
-/* vmalloc permissions */
-#define _K_PAGE_PERMS (_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ | \
- _PAGE_GLOBAL | _PAGE_PRESENT)
-
-#ifndef CONFIG_ARC_CACHE_PAGES
-#undef _PAGE_CACHEABLE
-#define _PAGE_CACHEABLE 0
-#endif
-#ifndef _PAGE_HW_SZ
-#define _PAGE_HW_SZ 0
-#endif
-
-/* Defaults for every user page */
-#define ___DEF (_PAGE_PRESENT | _PAGE_CACHEABLE)
-
-/* Set of bits not changed in pte_modify */
-#define _PAGE_CHG_MASK (PAGE_MASK_PHYS | _PAGE_ACCESSED | _PAGE_DIRTY | \
- _PAGE_SPECIAL)
-/* More Abbrevaited helpers */
-#define PAGE_U_NONE __pgprot(___DEF)
-#define PAGE_U_R __pgprot(___DEF | _PAGE_READ)
-#define PAGE_U_W_R __pgprot(___DEF | _PAGE_READ | _PAGE_WRITE)
-#define PAGE_U_X_R __pgprot(___DEF | _PAGE_READ | _PAGE_EXECUTE)
-#define PAGE_U_X_W_R __pgprot(___DEF | _PAGE_READ | _PAGE_WRITE | \
- _PAGE_EXECUTE)
-
-#define PAGE_SHARED PAGE_U_W_R
-
-/* While kernel runs out of unstranslated space, vmalloc/modules use a chunk of
- * user vaddr space - visible in all addr spaces, but kernel mode only
- * Thus Global, all-kernel-access, no-user-access, cached
- */
-#define PAGE_KERNEL __pgprot(_K_PAGE_PERMS | _PAGE_CACHEABLE)
-
-/* ioremap */
-#define PAGE_KERNEL_NO_CACHE __pgprot(_K_PAGE_PERMS)
-
-/* Masks for actual TLB "PD"s */
-#define PTE_BITS_IN_PD0 (_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_HW_SZ)
-#define PTE_BITS_RWX (_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ)
-
-#define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK_PHYS | _PAGE_CACHEABLE)
-
-/**************************************************************************
- * Mapping of vm_flags (Generic VM) to PTE flags (arch specific)
- *
- * Certain cases have 1:1 mapping
- * e.g. __P101 means VM_READ, VM_EXEC and !VM_SHARED
- * which directly corresponds to PAGE_U_X_R
- *
- * Other rules which cause the divergence from 1:1 mapping
- *
- * 1. Although ARC700 can do exclusive execute/write protection (meaning R
- * can be tracked independet of X/W unlike some other CPUs), still to
- * keep things consistent with other archs:
- * -Write implies Read: W => R
- * -Execute implies Read: X => R
- *
- * 2. Pvt Writable doesn't have Write Enabled initially: Pvt-W => !W
- * This is to enable COW mechanism
- */
- /* xwr */
-#define __P000 PAGE_U_NONE
-#define __P001 PAGE_U_R
-#define __P010 PAGE_U_R /* Pvt-W => !W */
-#define __P011 PAGE_U_R /* Pvt-W => !W */
-#define __P100 PAGE_U_X_R /* X => R */
-#define __P101 PAGE_U_X_R
-#define __P110 PAGE_U_X_R /* Pvt-W => !W and X => R */
-#define __P111 PAGE_U_X_R /* Pvt-W => !W */
-
-#define __S000 PAGE_U_NONE
-#define __S001 PAGE_U_R
-#define __S010 PAGE_U_W_R /* W => R */
-#define __S011 PAGE_U_W_R
-#define __S100 PAGE_U_X_R /* X => R */
-#define __S101 PAGE_U_X_R
-#define __S110 PAGE_U_X_W_R /* X => R */
-#define __S111 PAGE_U_X_W_R
-
-/****************************************************************
- * 2 tier (PGD:PTE) software page walker
- *
- * [31] 32 bit virtual address [0]
- * -------------------------------------------------------
- * | | <------------ PGDIR_SHIFT ----------> |
- * | | |
- * | BITS_FOR_PGD | BITS_FOR_PTE | <-- PAGE_SHIFT --> |
- * -------------------------------------------------------
- * | | |
- * | | --> off in page frame
- * | ---> index into Page Table
- * ----> index into Page Directory
- *
- * In a single page size configuration, only PAGE_SHIFT is fixed
- * So both PGD and PTE sizing can be tweaked
- * e.g. 8K page (PAGE_SHIFT 13) can have
- * - PGDIR_SHIFT 21 -> 11:8:13 address split
- * - PGDIR_SHIFT 24 -> 8:11:13 address split
- *
- * If Super Page is configured, PGDIR_SHIFT becomes fixed too,
- * so the sizing flexibility is gone.
- */
-
-#if defined(CONFIG_ARC_HUGEPAGE_16M)
-#define PGDIR_SHIFT 24
-#elif defined(CONFIG_ARC_HUGEPAGE_2M)
-#define PGDIR_SHIFT 21
-#else
-/*
- * Only Normal page support so "hackable" (see comment above)
- * Default value provides 11:8:13 (8K), 11:9:12 (4K)
- */
-#define PGDIR_SHIFT 21
-#endif
-
-#define BITS_FOR_PTE (PGDIR_SHIFT - PAGE_SHIFT)
-#define BITS_FOR_PGD (32 - PGDIR_SHIFT)
-
-#define PGDIR_SIZE BIT(PGDIR_SHIFT) /* vaddr span, not PDG sz */
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-
-#define PTRS_PER_PTE BIT(BITS_FOR_PTE)
-#define PTRS_PER_PGD BIT(BITS_FOR_PGD)
+#include <asm/pgtable-levels.h>
+#include <asm/pgtable-bits-arcv2.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
/*
* Number of entries a user land program use.
@@ -222,143 +19,17 @@
*/
#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
-
-/****************************************************************
- * Bucket load of VM Helpers
- */
-
#ifndef __ASSEMBLY__
-#define pte_ERROR(e) \
- pr_crit("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
-#define pgd_ERROR(e) \
- pr_crit("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
-
-/* the zero page used for uninitialized and anonymous pages */
extern char empty_zero_page[PAGE_SIZE];
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
-
-/* find the page descriptor of the Page Tbl ref by PMD entry */
-#define pmd_page(pmd) virt_to_page(pmd_val(pmd) & PAGE_MASK)
-
-/* find the logical addr (phy for ARC) of the Page Tbl ref by PMD entry */
-#define pmd_page_vaddr(pmd) (pmd_val(pmd) & PAGE_MASK)
-
-/* In a 2 level sys, setup the PGD entry with PTE value */
-static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
-{
- pmd_val(*pmdp) = (unsigned long)ptep;
-}
-
-#define pte_none(x) (!pte_val(x))
-#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(mm, addr, ptep) set_pte_at(mm, addr, ptep, __pte(0))
-
-#define pmd_none(x) (!pmd_val(x))
-#define pmd_bad(x) ((pmd_val(x) & ~PAGE_MASK))
-#define pmd_present(x) (pmd_val(x))
-#define pmd_leaf(x) (pmd_val(x) & _PAGE_HW_SZ)
-#define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0)
-
-#define pte_page(pte) pfn_to_page(pte_pfn(pte))
-#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
-#define pfn_pte(pfn, prot) __pte(__pfn_to_phys(pfn) | pgprot_val(prot))
-
-/* Don't use virt_to_pfn for macros below: could cause truncations for PAE40*/
-#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
-
-/* Zoo of pte_xxx function */
-#define pte_read(pte) (pte_val(pte) & _PAGE_READ)
-#define pte_write(pte) (pte_val(pte) & _PAGE_WRITE)
-#define pte_dirty(pte) (pte_val(pte) & _PAGE_DIRTY)
-#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED)
-#define pte_special(pte) (pte_val(pte) & _PAGE_SPECIAL)
-
-#define PTE_BIT_FUNC(fn, op) \
- static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
-
-PTE_BIT_FUNC(mknotpresent, &= ~(_PAGE_PRESENT));
-PTE_BIT_FUNC(wrprotect, &= ~(_PAGE_WRITE));
-PTE_BIT_FUNC(mkwrite, |= (_PAGE_WRITE));
-PTE_BIT_FUNC(mkclean, &= ~(_PAGE_DIRTY));
-PTE_BIT_FUNC(mkdirty, |= (_PAGE_DIRTY));
-PTE_BIT_FUNC(mkold, &= ~(_PAGE_ACCESSED));
-PTE_BIT_FUNC(mkyoung, |= (_PAGE_ACCESSED));
-PTE_BIT_FUNC(exprotect, &= ~(_PAGE_EXECUTE));
-PTE_BIT_FUNC(mkexec, |= (_PAGE_EXECUTE));
-PTE_BIT_FUNC(mkspecial, |= (_PAGE_SPECIAL));
-PTE_BIT_FUNC(mkhuge, |= (_PAGE_HW_SZ));
-
-static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
- return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
-}
+extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE);
/* Macro to mark a page protection as uncacheable */
#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) & ~_PAGE_CACHEABLE))
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pteval)
-{
- set_pte(ptep, pteval);
-}
-
-/*
- * Macro to quickly access the PGD entry, utlising the fact that some
- * arch may cache the pointer to Page Directory of "current" task
- * in a MMU register
- *
- * Thus task->mm->pgd (3 pointer dereferences, cache misses etc simply
- * becomes read a register
- *
- * ********CAUTION*******:
- * Kernel code might be dealing with some mm_struct of NON "current"
- * Thus use this macro only when you are certain that "current" is current
- * e.g. when dealing with signal frame setup code etc
- */
-#ifdef ARC_USE_SCRATCH_REG
-#define pgd_offset_fast(mm, addr) \
-({ \
- pgd_t *pgd_base = (pgd_t *) read_aux_reg(ARC_REG_SCRATCH_DATA0); \
- pgd_base + pgd_index(addr); \
-})
-#else
-#define pgd_offset_fast(mm, addr) pgd_offset(mm, addr)
-#endif
-
extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE);
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
- pte_t *ptep);
-
-/* Encode swap {type,off} tuple into PTE
- * We reserve 13 bits for 5-bit @type, keeping bits 12-5 zero, ensuring that
- * PAGE_PRESENT is zero in a PTE holding swap "identifier"
- */
-#define __swp_entry(type, off) ((swp_entry_t) { \
- ((type) & 0x1f) | ((off) << 13) })
-
-/* Decode a PTE containing swap "identifier "into constituents */
-#define __swp_type(pte_lookalike) (((pte_lookalike).val) & 0x1f)
-#define __swp_offset(pte_lookalike) ((pte_lookalike).val >> 13)
-
-/* NOPs, to keep generic kernel happy */
-#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
-
-#define kern_addr_valid(addr) (1)
-
-#define pmd_pgtable(pmd) ((pgtable_t) pmd_page_vaddr(pmd))
-
-/*
- * remap a physical page `pfn' of size `size' with page protection `prot'
- * into virtual address `from'
- */
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#include <asm/hugepage.h>
-#endif
/* to cope with aliasing VIPT cache */
#define HAVE_ARCH_UNMAPPED_AREA
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index e4031ecd3c8c..f28afcf5c6d1 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -93,7 +93,7 @@ extern unsigned int get_wchan(struct task_struct *p);
#define VMALLOC_START (PAGE_OFFSET - (CONFIG_ARC_KVADDR_SIZE << 20))
/* 1 PGDIR_SIZE each for fixmap/pkmap, 2 PGDIR_SIZE gutter (see asm/highmem.h) */
-#define VMALLOC_SIZE ((CONFIG_ARC_KVADDR_SIZE << 20) - PGDIR_SIZE * 4)
+#define VMALLOC_SIZE ((CONFIG_ARC_KVADDR_SIZE << 20) - PMD_SIZE * 4)
#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
index 01f85478170d..028a8cf76206 100644
--- a/arch/arc/include/asm/setup.h
+++ b/arch/arc/include/asm/setup.h
@@ -2,8 +2,8 @@
/*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
*/
-#ifndef __ASMARC_SETUP_H
-#define __ASMARC_SETUP_H
+#ifndef __ASM_ARC_SETUP_H
+#define __ASM_ARC_SETUP_H
#include <linux/types.h>
@@ -34,4 +34,12 @@ long __init arc_get_mem_sz(void);
#define IS_AVAIL2(v, s, cfg) IS_AVAIL1(v, s), IS_AVAIL1(v, IS_USED_CFG(cfg))
#define IS_AVAIL3(v, v2, s) IS_AVAIL1(v, s), IS_AVAIL1(v, IS_DISABLED_RUN(v2))
+extern void arc_mmu_init(void);
+extern char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len);
+extern void read_decode_mmu_bcr(void);
+
+extern void arc_cache_init(void);
+extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len);
+extern void read_decode_cache_bcr(void);
+
#endif /* __ASMARC_SETUP_H */
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index c5de4008d19f..d856491606ac 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -105,7 +105,6 @@ static inline const char *arc_platform_smp_cpuinfo(void)
#include <asm/spinlock.h>
extern arch_spinlock_t smp_atomic_ops_lock;
-extern arch_spinlock_t smp_bitops_lock;
#define atomic_ops_lock(flags) do { \
local_irq_save(flags); \
@@ -117,24 +116,11 @@ extern arch_spinlock_t smp_bitops_lock;
local_irq_restore(flags); \
} while (0)
-#define bitops_lock(flags) do { \
- local_irq_save(flags); \
- arch_spin_lock(&smp_bitops_lock); \
-} while (0)
-
-#define bitops_unlock(flags) do { \
- arch_spin_unlock(&smp_bitops_lock); \
- local_irq_restore(flags); \
-} while (0)
-
#else /* !CONFIG_SMP */
#define atomic_ops_lock(flags) local_irq_save(flags)
#define atomic_ops_unlock(flags) local_irq_restore(flags)
-#define bitops_lock(flags) local_irq_save(flags)
-#define bitops_unlock(flags) local_irq_restore(flags)
-
#endif /* !CONFIG_SMP */
#endif /* !CONFIG_ARC_HAS_LLSC */
diff --git a/arch/arc/include/asm/tlb-mmu1.h b/arch/arc/include/asm/tlb-mmu1.h
deleted file mode 100644
index a3083b36f5f4..000000000000
--- a/arch/arc/include/asm/tlb-mmu1.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- */
-
-#ifndef __ASM_TLB_MMU_V1_H__
-#define __ASM_TLB_MMU_V1_H__
-
-#include <asm/mmu.h>
-
-#if defined(__ASSEMBLY__) && (CONFIG_ARC_MMU_VER == 1)
-
-.macro TLB_WRITE_HEURISTICS
-
-#define JH_HACK1
-#undef JH_HACK2
-#undef JH_HACK3
-
-#ifdef JH_HACK3
-; Calculate set index for 2-way MMU
-; -avoiding use of GetIndex from MMU
-; and its unpleasant LFSR pseudo-random sequence
-;
-; r1 = TLBPD0 from TLB_RELOAD above
-;
-; -- jh_ex_way_set not cleared on startup
-; didn't want to change setup.c
-; hence extra instruction to clean
-;
-; -- should be in cache since in same line
-; as r0/r1 saves above
-;
-ld r0,[jh_ex_way_sel] ; victim pointer
-and r0,r0,1 ; clean
-xor.f r0,r0,1 ; flip
-st r0,[jh_ex_way_sel] ; store back
-asr r0,r1,12 ; get set # <<1, note bit 12=R=0
-or.nz r0,r0,1 ; set way bit
-and r0,r0,0xff ; clean
-sr r0,[ARC_REG_TLBINDEX]
-#endif
-
-#ifdef JH_HACK2
-; JH hack #2
-; Faster than hack #1 in non-thrash case, but hard-coded for 2-way MMU
-; Slower in thrash case (where it matters) because more code is executed
-; Inefficient due to two-register paradigm of this miss handler
-;
-/* r1 = data TLBPD0 at this point */
-lr r0,[eret] /* instruction address */
-xor r0,r0,r1 /* compare set # */
-and.f r0,r0,0x000fe000 /* 2-way MMU mask */
-bne 88f /* not in same set - no need to probe */
-
-lr r0,[eret] /* instruction address */
-and r0,r0,PAGE_MASK /* VPN of instruction address */
-; lr r1,[ARC_REG_TLBPD0] /* Data VPN+ASID - already in r1 from TLB_RELOAD*/
-and r1,r1,0xff /* Data ASID */
-or r0,r0,r1 /* Instruction address + Data ASID */
-
-lr r1,[ARC_REG_TLBPD0] /* save TLBPD0 containing data TLB*/
-sr r0,[ARC_REG_TLBPD0] /* write instruction address to TLBPD0 */
-sr TLBProbe, [ARC_REG_TLBCOMMAND] /* Look for instruction */
-lr r0,[ARC_REG_TLBINDEX] /* r0 = index where instruction is, if at all */
-sr r1,[ARC_REG_TLBPD0] /* restore TLBPD0 */
-
-xor r0,r0,1 /* flip bottom bit of data index */
-b.d 89f
-sr r0,[ARC_REG_TLBINDEX] /* and put it back */
-88:
-sr TLBGetIndex, [ARC_REG_TLBCOMMAND]
-89:
-#endif
-
-#ifdef JH_HACK1
-;
-; Always checks whether instruction will be kicked out by dtlb miss
-;
-mov_s r3, r1 ; save PD0 prepared by TLB_RELOAD in r3
-lr r0,[eret] /* instruction address */
-and r0,r0,PAGE_MASK /* VPN of instruction address */
-bmsk r1,r3,7 /* Data ASID, bits 7-0 */
-or_s r0,r0,r1 /* Instruction address + Data ASID */
-
-sr r0,[ARC_REG_TLBPD0] /* write instruction address to TLBPD0 */
-sr TLBProbe, [ARC_REG_TLBCOMMAND] /* Look for instruction */
-lr r0,[ARC_REG_TLBINDEX] /* r0 = index where instruction is, if at all */
-sr r3,[ARC_REG_TLBPD0] /* restore TLBPD0 */
-
-sr TLBGetIndex, [ARC_REG_TLBCOMMAND]
-lr r1,[ARC_REG_TLBINDEX] /* r1 = index where MMU wants to put data */
-cmp r0,r1 /* if no match on indices, go around */
-xor.eq r1,r1,1 /* flip bottom bit of data index */
-sr r1,[ARC_REG_TLBINDEX] /* and put it back */
-#endif
-
-.endm
-
-#endif
-
-#endif
diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
index ea40ec7f6cae..783bfdb3bfa3 100644
--- a/arch/arc/include/asm/uaccess.h
+++ b/arch/arc/include/asm/uaccess.h
@@ -655,88 +655,16 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
return res;
}
-static inline long
-__arc_strncpy_from_user(char *dst, const char __user *src, long count)
-{
- long res = 0;
- char val;
-
- if (count == 0)
- return 0;
-
- __asm__ __volatile__(
- " mov lp_count, %5 \n"
- " lp 3f \n"
- "1: ldb.ab %3, [%2, 1] \n"
- " breq.d %3, 0, 3f \n"
- " stb.ab %3, [%1, 1] \n"
- " add %0, %0, 1 # Num of NON NULL bytes copied \n"
- "3: \n"
- " .section .fixup, \"ax\" \n"
- " .align 4 \n"
- "4: mov %0, %4 # sets @res as -EFAULT \n"
- " j 3b \n"
- " .previous \n"
- " .section __ex_table, \"a\" \n"
- " .align 4 \n"
- " .word 1b, 4b \n"
- " .previous \n"
- : "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
- : "g"(-EFAULT), "r"(count)
- : "lp_count", "memory");
-
- return res;
-}
-
-static inline long __arc_strnlen_user(const char __user *s, long n)
-{
- long res, tmp1, cnt;
- char val;
-
- __asm__ __volatile__(
- " mov %2, %1 \n"
- "1: ldb.ab %3, [%0, 1] \n"
- " breq.d %3, 0, 2f \n"
- " sub.f %2, %2, 1 \n"
- " bnz 1b \n"
- " sub %2, %2, 1 \n"
- "2: sub %0, %1, %2 \n"
- "3: ;nop \n"
- " .section .fixup, \"ax\" \n"
- " .align 4 \n"
- "4: mov %0, 0 \n"
- " j 3b \n"
- " .previous \n"
- " .section __ex_table, \"a\" \n"
- " .align 4 \n"
- " .word 1b, 4b \n"
- " .previous \n"
- : "=r"(res), "=r"(tmp1), "=r"(cnt), "=r"(val)
- : "0"(s), "1"(n)
- : "memory");
-
- return res;
-}
-
#ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
#define INLINE_COPY_TO_USER
#define INLINE_COPY_FROM_USER
#define __clear_user(d, n) __arc_clear_user(d, n)
-#define __strncpy_from_user(d, s, n) __arc_strncpy_from_user(d, s, n)
-#define __strnlen_user(s, n) __arc_strnlen_user(s, n)
#else
extern unsigned long arc_clear_user_noinline(void __user *to,
unsigned long n);
-extern long arc_strncpy_from_user_noinline (char *dst, const char __user *src,
- long count);
-extern long arc_strnlen_user_noinline(const char __user *src, long n);
-
#define __clear_user(d, n) arc_clear_user_noinline(d, n)
-#define __strncpy_from_user(d, s, n) arc_strncpy_from_user_noinline(d, s, n)
-#define __strnlen_user(s, n) arc_strnlen_user_noinline(s, n)
-
#endif
#include <asm/segment.h>
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
index 12d5f12d10d2..a7e6a2174187 100644
--- a/arch/arc/kernel/entry-arcv2.S
+++ b/arch/arc/kernel/entry-arcv2.S
@@ -10,6 +10,7 @@
#include <asm/errno.h>
#include <asm/arcregs.h>
#include <asm/irqflags.h>
+#include <asm/mmu.h>
; A maximum number of supported interrupts in the core interrupt controller.
; This number is not equal to the maximum interrupt number (256) because
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 2cb8dfe866b6..dd77a0c8f740 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -101,11 +101,8 @@ ENTRY(EV_MachineCheck)
lr r0, [efa]
mov r1, sp
- ; hardware auto-disables MMU, re-enable it to allow kernel vaddr
- ; access for say stack unwinding of modules for crash dumps
- lr r3, [ARC_REG_PID]
- or r3, r3, MMU_ENABLE
- sr r3, [ARC_REG_PID]
+ ; MC excpetions disable MMU
+ ARC_MMU_REENABLE r3
lsr r3, r2, 8
bmsk r3, r3, 7
diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c
index a86641b91e65..6885e422870e 100644
--- a/arch/arc/kernel/intc-compact.c
+++ b/arch/arc/kernel/intc-compact.c
@@ -142,7 +142,7 @@ IRQCHIP_DECLARE(arc_intc, "snps,arc700-intc", init_onchip_IRQ);
* Time hard-ISR, timer_interrupt( ) calls spin_unlock_irq several times.
* Here local_irq_enable( ) shd not re-enable lower priority interrupts
* -If called from soft-ISR, it must re-enable all interrupts
- * soft ISR are low prioity jobs which can be very slow, thus all IRQs
+ * soft ISR are low priority jobs which can be very slow, thus all IRQs
* must be enabled while they run.
* Now hardware context wise we may still be in L2 ISR (not done rtie)
* still we must re-enable both L1 and L2 IRQs
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index db0e104d6835..78e6d069b1c1 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -29,10 +29,8 @@
#ifndef CONFIG_ARC_HAS_LLSC
arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
-arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
EXPORT_SYMBOL_GPL(smp_atomic_ops_lock);
-EXPORT_SYMBOL_GPL(smp_bitops_lock);
#endif
struct plat_smp_ops __weak plat_smp_ops;
@@ -283,7 +281,7 @@ static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg)
/*
* Call the platform specific IPI kick function, but avoid if possible:
* Only do so if there's no pending msg from other concurrent sender(s).
- * Otherwise, recevier will see this msg as well when it takes the
+ * Otherwise, receiver will see this msg as well when it takes the
* IPI corresponding to that msg. This is true, even if it is already in
* IPI handler, because !@old means it has not yet dequeued the msg(s)
* so @new msg can be a free-loader
diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c
index 1b9576d21e24..c376ff3147e7 100644
--- a/arch/arc/kernel/stacktrace.c
+++ b/arch/arc/kernel/stacktrace.c
@@ -149,7 +149,7 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
#else
/* On ARC, only Dward based unwinder works. fp based backtracing is
* not possible (-fno-omit-frame-pointer) because of the way function
- * prelogue is setup (callee regs saved and then fp set and not other
+ * prologue is setup (callee regs saved and then fp set and not other
* way around
*/
pr_warn_once("CONFIG_ARC_DW2_UNWIND needs to be enabled\n");
diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c
index a2fbea3ee07c..8aa1231865d1 100644
--- a/arch/arc/mm/cache.c
+++ b/arch/arc/mm/cache.c
@@ -205,93 +205,24 @@ slc_chk:
#define OP_INV_IC 0x4
/*
- * I-Cache Aliasing in ARC700 VIPT caches (MMU v1-v3)
+ * Cache Flush programming model
*
- * ARC VIPT I-cache uses vaddr to index into cache and paddr to match the tag.
- * The orig Cache Management Module "CDU" only required paddr to invalidate a
- * certain line since it sufficed as index in Non-Aliasing VIPT cache-geometry.
- * Infact for distinct V1,V2,P: all of {V1-P},{V2-P},{P-P} would end up fetching
- * the exact same line.
+ * ARC700 MMUv3 I$ and D$ are both VIPT and can potentially alias.
+ * Programming model requires both paddr and vaddr irrespecive of aliasing
+ * considerations:
+ * - vaddr in {I,D}C_IV?L
+ * - paddr in {I,D}C_PTAG
*
- * However for larger Caches (way-size > page-size) - i.e. in Aliasing config,
- * paddr alone could not be used to correctly index the cache.
+ * In HS38x (MMUv4), D$ is PIPT, I$ is VIPT and can still alias.
+ * Programming model is different for aliasing vs. non-aliasing I$
+ * - D$ / Non-aliasing I$: only paddr in {I,D}C_IV?L
+ * - Aliasing I$: same as ARC700 above (so MMUv3 routine used for MMUv4 I$)
*
- * ------------------
- * MMU v1/v2 (Fixed Page Size 8k)
- * ------------------
- * The solution was to provide CDU with these additonal vaddr bits. These
- * would be bits [x:13], x would depend on cache-geometry, 13 comes from
- * standard page size of 8k.
- * H/w folks chose [17:13] to be a future safe range, and moreso these 5 bits
- * of vaddr could easily be "stuffed" in the paddr as bits [4:0] since the
- * orig 5 bits of paddr were anyways ignored by CDU line ops, as they
- * represent the offset within cache-line. The adv of using this "clumsy"
- * interface for additional info was no new reg was needed in CDU programming
- * model.
- *
- * 17:13 represented the max num of bits passable, actual bits needed were
- * fewer, based on the num-of-aliases possible.
- * -for 2 alias possibility, only bit 13 needed (32K cache)
- * -for 4 alias possibility, bits 14:13 needed (64K cache)
- *
- * ------------------
- * MMU v3
- * ------------------
- * This ver of MMU supports variable page sizes (1k-16k): although Linux will
- * only support 8k (default), 16k and 4k.
- * However from hardware perspective, smaller page sizes aggravate aliasing
- * meaning more vaddr bits needed to disambiguate the cache-line-op ;
- * the existing scheme of piggybacking won't work for certain configurations.
- * Two new registers IC_PTAG and DC_PTAG inttoduced.
- * "tag" bits are provided in PTAG, index bits in existing IVIL/IVDL/FLDL regs
+ * - If PAE40 is enabled, independent of aliasing considerations, the higher
+ * bits needs to be written into PTAG_HI
*/
static inline
-void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr,
- unsigned long sz, const int op, const int full_page)
-{
- unsigned int aux_cmd;
- int num_lines;
-
- if (op == OP_INV_IC) {
- aux_cmd = ARC_REG_IC_IVIL;
- } else {
- /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
- aux_cmd = op & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
- }
-
- /* Ensure we properly floor/ceil the non-line aligned/sized requests
- * and have @paddr - aligned to cache line and integral @num_lines.
- * This however can be avoided for page sized since:
- * -@paddr will be cache-line aligned already (being page aligned)
- * -@sz will be integral multiple of line size (being page sized).
- */
- if (!full_page) {
- sz += paddr & ~CACHE_LINE_MASK;
- paddr &= CACHE_LINE_MASK;
- vaddr &= CACHE_LINE_MASK;
- }
-
- num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES);
-
- /* MMUv2 and before: paddr contains stuffed vaddrs bits */
- paddr |= (vaddr >> PAGE_SHIFT) & 0x1F;
-
- while (num_lines-- > 0) {
- write_aux_reg(aux_cmd, paddr);
- paddr += L1_CACHE_BYTES;
- }
-}
-
-/*
- * For ARC700 MMUv3 I-cache and D-cache flushes
- * - ARC700 programming model requires paddr and vaddr be passed in seperate
- * AUX registers (*_IV*L and *_PTAG respectively) irrespective of whether the
- * caches actually alias or not.
- * - For HS38, only the aliasing I-cache configuration uses the PTAG reg
- * (non aliasing I-cache version doesn't; while D-cache can't possibly alias)
- */
-static inline
void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
unsigned long sz, const int op, const int full_page)
{
@@ -350,17 +281,6 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
#ifndef USE_RGN_FLSH
/*
- * In HS38x (MMU v4), I-cache is VIPT (can alias), D-cache is PIPT
- * Here's how cache ops are implemented
- *
- * - D-cache: only paddr needed (in DC_IVDL/DC_FLDL)
- * - I-cache Non Aliasing: Despite VIPT, only paddr needed (in IC_IVIL)
- * - I-cache Aliasing: Both vaddr and paddr needed (in IC_IVIL, IC_PTAG
- * respectively, similar to MMU v3 programming model, hence
- * __cache_line_loop_v3() is used)
- *
- * If PAE40 is enabled, independent of aliasing considerations, the higher bits
- * needs to be written into PTAG_HI
*/
static inline
void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
@@ -460,11 +380,9 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
#endif
-#if (CONFIG_ARC_MMU_VER < 3)
-#define __cache_line_loop __cache_line_loop_v2
-#elif (CONFIG_ARC_MMU_VER == 3)
+#ifdef CONFIG_ARC_MMU_V3
#define __cache_line_loop __cache_line_loop_v3
-#elif (CONFIG_ARC_MMU_VER > 3)
+#else
#define __cache_line_loop __cache_line_loop_v4
#endif
@@ -1123,7 +1041,7 @@ void clear_user_page(void *to, unsigned long u_vaddr, struct page *page)
clear_page(to);
clear_bit(PG_dc_clean, &page->flags);
}
-
+EXPORT_SYMBOL(clear_user_page);
/**********************************************************************
* Explicit Cache flush request from user space via syscall
diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c
index b06b09ddf924..4e14c4244ea2 100644
--- a/arch/arc/mm/extable.c
+++ b/arch/arc/mm/extable.c
@@ -32,16 +32,4 @@ unsigned long arc_clear_user_noinline(void __user *to,
}
EXPORT_SYMBOL(arc_clear_user_noinline);
-long arc_strncpy_from_user_noinline(char *dst, const char __user *src,
- long count)
-{
- return __arc_strncpy_from_user(dst, src, count);
-}
-EXPORT_SYMBOL(arc_strncpy_from_user_noinline);
-
-long arc_strnlen_user_noinline(const char __user *src, long n)
-{
- return __arc_strnlen_user(src, n);
-}
-EXPORT_SYMBOL(arc_strnlen_user_noinline);
#endif
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index f5657cb68e4f..5787c261c9a4 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -33,28 +33,34 @@ noinline static int handle_kernel_vaddr_fault(unsigned long address)
pud_t *pud, *pud_k;
pmd_t *pmd, *pmd_k;
- pgd = pgd_offset_fast(current->active_mm, address);
+ pgd = pgd_offset(current->active_mm, address);
pgd_k = pgd_offset_k(address);
- if (!pgd_present(*pgd_k))
+ if (pgd_none (*pgd_k))
goto bad_area;
+ if (!pgd_present(*pgd))
+ set_pgd(pgd, *pgd_k);
p4d = p4d_offset(pgd, address);
p4d_k = p4d_offset(pgd_k, address);
- if (!p4d_present(*p4d_k))
+ if (p4d_none(*p4d_k))
goto bad_area;
+ if (!p4d_present(*p4d))
+ set_p4d(p4d, *p4d_k);
pud = pud_offset(p4d, address);
pud_k = pud_offset(p4d_k, address);
- if (!pud_present(*pud_k))
+ if (pud_none(*pud_k))
goto bad_area;
+ if (!pud_present(*pud))
+ set_pud(pud, *pud_k);
pmd = pmd_offset(pud, address);
pmd_k = pmd_offset(pud_k, address);
- if (!pmd_present(*pmd_k))
+ if (pmd_none(*pmd_k))
goto bad_area;
-
- set_pmd(pmd, *pmd_k);
+ if (!pmd_present(*pmd))
+ set_pmd(pmd, *pmd_k);
/* XXX: create the TLB entry here */
return 0;
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index c083bf660cec..699ecf119641 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -189,6 +189,11 @@ void __init mem_init(void)
{
memblock_free_all();
highmem_init();
+
+ BUILD_BUG_ON((PTRS_PER_PGD * sizeof(pgd_t)) > PAGE_SIZE);
+ BUILD_BUG_ON((PTRS_PER_PUD * sizeof(pud_t)) > PAGE_SIZE);
+ BUILD_BUG_ON((PTRS_PER_PMD * sizeof(pmd_t)) > PAGE_SIZE);
+ BUILD_BUG_ON((PTRS_PER_PTE * sizeof(pte_t)) > PAGE_SIZE);
}
#ifdef CONFIG_HIGHMEM
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
index 95c649fbc95a..0ee75aca6e10 100644
--- a/arch/arc/mm/ioremap.c
+++ b/arch/arc/mm/ioremap.c
@@ -39,7 +39,8 @@ void __iomem *ioremap(phys_addr_t paddr, unsigned long size)
if (arc_uncached_addr_space(paddr))
return (void __iomem *)(u32)paddr;
- return ioremap_prot(paddr, size, PAGE_KERNEL_NO_CACHE);
+ return ioremap_prot(paddr, size,
+ pgprot_val(pgprot_noncached(PAGE_KERNEL)));
}
EXPORT_SYMBOL(ioremap);
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 9c7c68247289..5f71445f26bd 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -1,51 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * TLB Management (flush/create/diagnostics) for ARC700
+ * TLB Management (flush/create/diagnostics) for MMUv3 and MMUv4
*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
*
- * vineetg: Aug 2011
- * -Reintroduce duplicate PD fixup - some customer chips still have the issue
- *
- * vineetg: May 2011
- * -No need to flush_cache_page( ) for each call to update_mmu_cache()
- * some of the LMBench tests improved amazingly
- * = page-fault thrice as fast (75 usec to 28 usec)
- * = mmap twice as fast (9.6 msec to 4.6 msec),
- * = fork (5.3 msec to 3.7 msec)
- *
- * vineetg: April 2011 :
- * -MMU v3: PD{0,1} bits layout changed: They don't overlap anymore,
- * helps avoid a shift when preparing PD0 from PTE
- *
- * vineetg: April 2011 : Preparing for MMU V3
- * -MMU v2/v3 BCRs decoded differently
- * -Remove TLB_SIZE hardcoding as it's variable now: 256 or 512
- * -tlb_entry_erase( ) can be void
- * -local_flush_tlb_range( ):
- * = need not "ceil" @end
- * = walks MMU only if range spans < 32 entries, as opposed to 256
- *
- * Vineetg: Sept 10th 2008
- * -Changes related to MMU v2 (Rel 4.8)
- *
- * Vineetg: Aug 29th 2008
- * -In TLB Flush operations (Metal Fix MMU) there is a explicit command to
- * flush Micro-TLBS. If TLB Index Reg is invalid prior to TLBIVUTLB cmd,
- * it fails. Thus need to load it with ANY valid value before invoking
- * TLBIVUTLB cmd
- *
- * Vineetg: Aug 21th 2008:
- * -Reduced the duration of IRQ lockouts in TLB Flush routines
- * -Multiple copies of TLB erase code separated into a "single" function
- * -In TLB Flush routines, interrupt disabling moved UP to retrieve ASID
- * in interrupt-safe region.
- *
- * Vineetg: April 23rd Bug #93131
- * Problem: tlb_flush_kernel_range() doesn't do anything if the range to
- * flush is more than the size of TLB itself.
- *
- * Rahul Trivedi : Codito Technologies 2004
*/
#include <linux/module.h>
@@ -57,47 +15,6 @@
#include <asm/mmu_context.h>
#include <asm/mmu.h>
-/* Need for ARC MMU v2
- *
- * ARC700 MMU-v1 had a Joint-TLB for Code and Data and is 2 way set-assoc.
- * For a memcpy operation with 3 players (src/dst/code) such that all 3 pages
- * map into same set, there would be contention for the 2 ways causing severe
- * Thrashing.
- *
- * Although J-TLB is 2 way set assoc, ARC700 caches J-TLB into uTLBS which has
- * much higher associativity. u-D-TLB is 8 ways, u-I-TLB is 4 ways.
- * Given this, the thrashing problem should never happen because once the 3
- * J-TLB entries are created (even though 3rd will knock out one of the prev
- * two), the u-D-TLB and u-I-TLB will have what is required to accomplish memcpy
- *
- * Yet we still see the Thrashing because a J-TLB Write cause flush of u-TLBs.
- * This is a simple design for keeping them in sync. So what do we do?
- * The solution which James came up was pretty neat. It utilised the assoc
- * of uTLBs by not invalidating always but only when absolutely necessary.
- *
- * - Existing TLB commands work as before
- * - New command (TLBWriteNI) for TLB write without clearing uTLBs
- * - New command (TLBIVUTLB) to invalidate uTLBs.
- *
- * The uTLBs need only be invalidated when pages are being removed from the
- * OS page table. If a 'victim' TLB entry is being overwritten in the main TLB
- * as a result of a miss, the removed entry is still allowed to exist in the
- * uTLBs as it is still valid and present in the OS page table. This allows the
- * full associativity of the uTLBs to hide the limited associativity of the main
- * TLB.
- *
- * During a miss handler, the new "TLBWriteNI" command is used to load
- * entries without clearing the uTLBs.
- *
- * When the OS page table is updated, TLB entries that may be associated with a
- * removed page are removed (flushed) from the TLB using TLBWrite. In this
- * circumstance, the uTLBs must also be cleared. This is done by using the
- * existing TLBWrite command. An explicit IVUTLB is also required for those
- * corner cases when TLBWrite was not executed at all because the corresp
- * J-TLB entry got evicted/replaced.
- */
-
-
/* A copy of the ASID from the PID reg is kept in asid_cache */
DEFINE_PER_CPU(unsigned int, asid_cache) = MM_CTXT_FIRST_CYCLE;
@@ -120,32 +37,10 @@ static inline void __tlb_entry_erase(void)
static void utlb_invalidate(void)
{
-#if (CONFIG_ARC_MMU_VER >= 2)
-
-#if (CONFIG_ARC_MMU_VER == 2)
- /* MMU v2 introduced the uTLB Flush command.
- * There was however an obscure hardware bug, where uTLB flush would
- * fail when a prior probe for J-TLB (both totally unrelated) would
- * return lkup err - because the entry didn't exist in MMU.
- * The Workaround was to set Index reg with some valid value, prior to
- * flush. This was fixed in MMU v3
- */
- unsigned int idx;
-
- /* make sure INDEX Reg is valid */
- idx = read_aux_reg(ARC_REG_TLBINDEX);
-
- /* If not write some dummy val */
- if (unlikely(idx & TLB_LKUP_ERR))
- write_aux_reg(ARC_REG_TLBINDEX, 0xa);
-#endif
-
write_aux_reg(ARC_REG_TLBCOMMAND, TLBIVUTLB);
-#endif
-
}
-#if (CONFIG_ARC_MMU_VER < 4)
+#ifdef CONFIG_ARC_MMU_V3
static inline unsigned int tlb_entry_lkup(unsigned long vaddr_n_asid)
{
@@ -176,7 +71,7 @@ static void tlb_entry_erase(unsigned int vaddr_n_asid)
}
}
-static void tlb_entry_insert(unsigned int pd0, pte_t pd1)
+static void tlb_entry_insert(unsigned int pd0, phys_addr_t pd1)
{
unsigned int idx;
@@ -206,7 +101,7 @@ static void tlb_entry_insert(unsigned int pd0, pte_t pd1)
write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
}
-#else /* CONFIG_ARC_MMU_VER >= 4) */
+#else /* MMUv4 */
static void tlb_entry_erase(unsigned int vaddr_n_asid)
{
@@ -214,13 +109,16 @@ static void tlb_entry_erase(unsigned int vaddr_n_asid)
write_aux_reg(ARC_REG_TLBCOMMAND, TLBDeleteEntry);
}
-static void tlb_entry_insert(unsigned int pd0, pte_t pd1)
+static void tlb_entry_insert(unsigned int pd0, phys_addr_t pd1)
{
write_aux_reg(ARC_REG_TLBPD0, pd0);
- write_aux_reg(ARC_REG_TLBPD1, pd1);
- if (is_pae40_enabled())
+ if (!is_pae40_enabled()) {
+ write_aux_reg(ARC_REG_TLBPD1, pd1);
+ } else {
+ write_aux_reg(ARC_REG_TLBPD1, pd1 & 0xFFFFFFFF);
write_aux_reg(ARC_REG_TLBPD1HI, (u64)pd1 >> 32);
+ }
write_aux_reg(ARC_REG_TLBCOMMAND, TLBInsertEntry);
}
@@ -496,7 +394,7 @@ void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *ptep)
unsigned long flags;
unsigned int asid_or_sasid, rwx;
unsigned long pd0;
- pte_t pd1;
+ phys_addr_t pd1;
/*
* create_tlb() assumes that current->mm == vma->mm, since
@@ -505,7 +403,6 @@ void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *ptep)
*
* Removing the assumption involves
* -Using vma->mm->context{ASID,SASID}, as opposed to MMU reg.
- * -Fix the TLB paranoid debug code to not trigger false negatives.
* -More importantly it makes this handler inconsistent with fast-path
* TLB Refill handler which always deals with "current"
*
@@ -528,8 +425,6 @@ void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *ptep)
local_irq_save(flags);
- tlb_paranoid_check(asid_mm(vma->vm_mm, smp_processor_id()), vaddr);
-
vaddr &= PAGE_MASK;
/* update this PTE credentials */
@@ -639,43 +534,6 @@ void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
update_mmu_cache(vma, addr, &pte);
}
-void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
- pgtable_t pgtable)
-{
- struct list_head *lh = (struct list_head *) pgtable;
-
- assert_spin_locked(&mm->page_table_lock);
-
- /* FIFO */
- if (!pmd_huge_pte(mm, pmdp))
- INIT_LIST_HEAD(lh);
- else
- list_add(lh, (struct list_head *) pmd_huge_pte(mm, pmdp));
- pmd_huge_pte(mm, pmdp) = pgtable;
-}
-
-pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
-{
- struct list_head *lh;
- pgtable_t pgtable;
-
- assert_spin_locked(&mm->page_table_lock);
-
- pgtable = pmd_huge_pte(mm, pmdp);
- lh = (struct list_head *) pgtable;
- if (list_empty(lh))
- pmd_huge_pte(mm, pmdp) = NULL;
- else {
- pmd_huge_pte(mm, pmdp) = (pgtable_t) lh->next;
- list_del(lh);
- }
-
- pte_val(pgtable[0]) = 0;
- pte_val(pgtable[1]) = 0;
-
- return pgtable;
-}
-
void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
@@ -706,14 +564,6 @@ void read_decode_mmu_bcr(void)
{
struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
unsigned int tmp;
- struct bcr_mmu_1_2 {
-#ifdef CONFIG_CPU_BIG_ENDIAN
- unsigned int ver:8, ways:4, sets:4, u_itlb:8, u_dtlb:8;
-#else
- unsigned int u_dtlb:8, u_itlb:8, sets:4, ways:4, ver:8;
-#endif
- } *mmu2;
-
struct bcr_mmu_3 {
#ifdef CONFIG_CPU_BIG_ENDIAN
unsigned int ver:8, ways:4, sets:4, res:3, sasid:1, pg_sz:4,
@@ -738,23 +588,14 @@ void read_decode_mmu_bcr(void)
tmp = read_aux_reg(ARC_REG_MMU_BCR);
mmu->ver = (tmp >> 24);
- if (is_isa_arcompact()) {
- if (mmu->ver <= 2) {
- mmu2 = (struct bcr_mmu_1_2 *)&tmp;
- mmu->pg_sz_k = TO_KB(0x2000);
- mmu->sets = 1 << mmu2->sets;
- mmu->ways = 1 << mmu2->ways;
- mmu->u_dtlb = mmu2->u_dtlb;
- mmu->u_itlb = mmu2->u_itlb;
- } else {
- mmu3 = (struct bcr_mmu_3 *)&tmp;
- mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1);
- mmu->sets = 1 << mmu3->sets;
- mmu->ways = 1 << mmu3->ways;
- mmu->u_dtlb = mmu3->u_dtlb;
- mmu->u_itlb = mmu3->u_itlb;
- mmu->sasid = mmu3->sasid;
- }
+ if (is_isa_arcompact() && mmu->ver == 3) {
+ mmu3 = (struct bcr_mmu_3 *)&tmp;
+ mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1);
+ mmu->sets = 1 << mmu3->sets;
+ mmu->ways = 1 << mmu3->ways;
+ mmu->u_dtlb = mmu3->u_dtlb;
+ mmu->u_itlb = mmu3->u_itlb;
+ mmu->sasid = mmu3->sasid;
} else {
mmu4 = (struct bcr_mmu_4 *)&tmp;
mmu->pg_sz_k = 1 << (mmu4->sz0 - 1);
@@ -780,8 +621,8 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
IS_USED_CFG(CONFIG_TRANSPARENT_HUGEPAGE));
n += scnprintf(buf + n, len - n,
- "MMU [v%x]\t: %dk PAGE, %sJTLB %d (%dx%d), uDTLB %d, uITLB %d%s%s\n",
- p_mmu->ver, p_mmu->pg_sz_k, super_pg,
+ "MMU [v%x]\t: %dk PAGE, %s, swalk %d lvl, JTLB %d (%dx%d), uDTLB %d, uITLB %d%s%s\n",
+ p_mmu->ver, p_mmu->pg_sz_k, super_pg, CONFIG_PGTABLE_LEVELS,
p_mmu->sets * p_mmu->ways, p_mmu->sets, p_mmu->ways,
p_mmu->u_dtlb, p_mmu->u_itlb,
IS_AVAIL2(p_mmu->pae, ", PAE40 ", CONFIG_ARC_HAS_PAE40));
@@ -815,22 +656,17 @@ void arc_mmu_init(void)
/*
* Ensure that MMU features assumed by kernel exist in hardware.
- * For older ARC700 cpus, it has to be exact match, since the MMU
- * revisions were not backwards compatible (MMUv3 TLB layout changed
- * so even if kernel for v2 didn't use any new cmds of v3, it would
- * still not work.
- * For HS cpus, MMUv4 was baseline and v5 is backwards compatible
- * (will run older software).
+ * - For older ARC700 cpus, only v3 supported
+ * - For HS cpus, v4 was baseline and v5 is backwards compatible
+ * (will run older software).
*/
- if (is_isa_arcompact() && mmu->ver == CONFIG_ARC_MMU_VER)
+ if (is_isa_arcompact() && mmu->ver == 3)
compat = 1;
- else if (is_isa_arcv2() && mmu->ver >= CONFIG_ARC_MMU_VER)
+ else if (is_isa_arcv2() && mmu->ver >= 4)
compat = 1;
- if (!compat) {
- panic("MMU ver %d doesn't match kernel built for %d...\n",
- mmu->ver, CONFIG_ARC_MMU_VER);
- }
+ if (!compat)
+ panic("MMU ver %d doesn't match kernel built for\n", mmu->ver);
if (mmu->pg_sz_k != TO_KB(PAGE_SIZE))
panic("MMU pg size != PAGE_SIZE (%luk)\n", TO_KB(PAGE_SIZE));
@@ -843,14 +679,11 @@ void arc_mmu_init(void)
if (IS_ENABLED(CONFIG_ARC_HAS_PAE40) && !mmu->pae)
panic("Hardware doesn't support PAE40\n");
- /* Enable the MMU */
- write_aux_reg(ARC_REG_PID, MMU_ENABLE);
+ /* Enable the MMU with ASID 0 */
+ mmu_setup_asid(NULL, 0);
- /* In smp we use this reg for interrupt 1 scratch */
-#ifdef ARC_USE_SCRATCH_REG
- /* swapper_pg_dir is the pgd for the kernel, used by vmalloc */
- write_aux_reg(ARC_REG_SCRATCH_DATA0, swapper_pg_dir);
-#endif
+ /* cache the pgd pointer in MMU SCRATCH reg (ARCv2 only) */
+ mmu_setup_pgd(NULL, swapper_pg_dir);
if (pae40_exist_but_not_enab())
write_aux_reg(ARC_REG_TLBPD1HI, 0);
@@ -945,40 +778,3 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
local_irq_restore(flags);
}
-
-/***********************************************************************
- * Diagnostic Routines
- * -Called from Low Level TLB Handlers if things don;t look good
- **********************************************************************/
-
-#ifdef CONFIG_ARC_DBG_TLB_PARANOIA
-
-/*
- * Low Level ASM TLB handler calls this if it finds that HW and SW ASIDS
- * don't match
- */
-void print_asid_mismatch(int mm_asid, int mmu_asid, int is_fast_path)
-{
- pr_emerg("ASID Mismatch in %s Path Handler: sw-pid=0x%x hw-pid=0x%x\n",
- is_fast_path ? "Fast" : "Slow", mm_asid, mmu_asid);
-
- __asm__ __volatile__("flag 1");
-}
-
-void tlb_paranoid_check(unsigned int mm_asid, unsigned long addr)
-{
- unsigned int mmu_asid;
-
- mmu_asid = read_aux_reg(ARC_REG_PID) & 0xff;
-
- /*
- * At the time of a TLB miss/installation
- * - HW version needs to match SW version
- * - SW needs to have a valid ASID
- */
- if (addr < 0x70000000 &&
- ((mm_asid == MM_CTXT_NO_ASID) ||
- (mmu_asid != (mm_asid & MM_CTXT_ASID_MASK))))
- print_asid_mismatch(mm_asid, mmu_asid, 0);
-}
-#endif
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S
index 062fae46c3f8..e054780a8fe0 100644
--- a/arch/arc/mm/tlbex.S
+++ b/arch/arc/mm/tlbex.S
@@ -39,7 +39,6 @@
#include <asm/arcregs.h>
#include <asm/cache.h>
#include <asm/processor.h>
-#include <asm/tlb-mmu1.h>
#ifdef CONFIG_ISA_ARCOMPACT
;-----------------------------------------------------------------
@@ -94,11 +93,6 @@ ex_saved_reg1:
st_s r1, [r0, 4]
st_s r2, [r0, 8]
st_s r3, [r0, 12]
-
- ; VERIFY if the ASID in MMU-PID Reg is same as
- ; one in Linux data structures
-
- tlb_paranoid_check_asm
.endm
.macro TLBMISS_RESTORE_REGS
@@ -148,53 +142,16 @@ ex_saved_reg1:
#endif
;============================================================================
-; Troubleshooting Stuff
+;TLB Miss handling Code
;============================================================================
-; Linux keeps ASID (Address Space ID) in task->active_mm->context.asid
-; When Creating TLB Entries, instead of doing 3 dependent loads from memory,
-; we use the MMU PID Reg to get current ASID.
-; In bizzare scenrios SW and HW ASID can get out-of-sync which is trouble.
-; So we try to detect this in TLB Mis shandler
-
-.macro tlb_paranoid_check_asm
-
-#ifdef CONFIG_ARC_DBG_TLB_PARANOIA
-
- GET_CURR_TASK_ON_CPU r3
- ld r0, [r3, TASK_ACT_MM]
- ld r0, [r0, MM_CTXT+MM_CTXT_ASID]
- breq r0, 0, 55f ; Error if no ASID allocated
-
- lr r1, [ARC_REG_PID]
- and r1, r1, 0xFF
-
- and r2, r0, 0xFF ; MMU PID bits only for comparison
- breq r1, r2, 5f
-
-55:
- ; Error if H/w and S/w ASID don't match, but NOT if in kernel mode
- lr r2, [erstatus]
- bbit0 r2, STATUS_U_BIT, 5f
-
- ; We sure are in troubled waters, Flag the error, but to do so
- ; need to switch to kernel mode stack to call error routine
- GET_TSK_STACK_BASE r3, sp
-
- ; Call printk to shoutout aloud
- mov r2, 1
- j print_asid_mismatch
-
-5: ; ASIDs match so proceed normally
- nop
-
+#ifndef PMD_SHIFT
+#define PMD_SHIFT PUD_SHIFT
#endif
-.endm
-
-;============================================================================
-;TLB Miss handling Code
-;============================================================================
+#ifndef PUD_SHIFT
+#define PUD_SHIFT PGDIR_SHIFT
+#endif
;-----------------------------------------------------------------------------
; This macro does the page-table lookup for the faulting address.
@@ -203,7 +160,7 @@ ex_saved_reg1:
lr r2, [efa]
-#ifdef ARC_USE_SCRATCH_REG
+#ifdef CONFIG_ISA_ARCV2
lr r1, [ARC_REG_SCRATCH_DATA0] ; current pgd
#else
GET_CURR_TASK_ON_CPU r1
@@ -216,6 +173,24 @@ ex_saved_reg1:
tst r3, r3
bz do_slow_path_pf ; if no Page Table, do page fault
+#if CONFIG_PGTABLE_LEVELS > 3
+ lsr r0, r2, PUD_SHIFT ; Bits for indexing into PUD
+ and r0, r0, (PTRS_PER_PUD - 1)
+ ld.as r1, [r3, r0] ; PMD entry
+ tst r1, r1
+ bz do_slow_path_pf
+ mov r3, r1
+#endif
+
+#if CONFIG_PGTABLE_LEVELS > 2
+ lsr r0, r2, PMD_SHIFT ; Bits for indexing into PMD
+ and r0, r0, (PTRS_PER_PMD - 1)
+ ld.as r1, [r3, r0] ; PMD entry
+ tst r1, r1
+ bz do_slow_path_pf
+ mov r3, r1
+#endif
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
and.f 0, r3, _PAGE_HW_SZ ; Is this Huge PMD (thp)
add2.nz r1, r1, r0
@@ -279,7 +254,7 @@ ex_saved_reg1:
; Commit the TLB entry into MMU
.macro COMMIT_ENTRY_TO_MMU
-#if (CONFIG_ARC_MMU_VER < 4)
+#ifdef CONFIG_ARC_MMU_V3
/* Get free TLB slot: Set = computed from vaddr, way = random */
sr TLBGetIndex, [ARC_REG_TLBCOMMAND]
@@ -375,13 +350,6 @@ ENTRY(EV_TLBMissD)
CONV_PTE_TO_TLB
-#if (CONFIG_ARC_MMU_VER == 1)
- ; MMU with 2 way set assoc J-TLB, needs some help in pathetic case of
- ; memcpy where 3 parties contend for 2 ways, ensuing a livelock.
- ; But only for old MMU or one with Metal Fix
- TLB_WRITE_HEURISTICS
-#endif
-
COMMIT_ENTRY_TO_MMU
TLBMISS_RESTORE_REGS
EV_TLBMissD_fast_ret: ; additional label for VDK OS-kit instrumentation
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2fb7012c3246..99863022436d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -18,8 +18,8 @@ config ARM
select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
select ARCH_HAS_STRICT_MODULE_RWX if MMU
- select ARCH_HAS_SYNC_DMA_FOR_DEVICE if SWIOTLB
- select ARCH_HAS_SYNC_DMA_FOR_CPU if SWIOTLB
+ select ARCH_HAS_SYNC_DMA_FOR_DEVICE if SWIOTLB || !MMU
+ select ARCH_HAS_SYNC_DMA_FOR_CPU if SWIOTLB || !MMU
select ARCH_HAS_TEARDOWN_DMA_OPS if MMU
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAVE_CUSTOM_GPIO_H
@@ -44,6 +44,7 @@ config ARM
select CPU_PM if SUSPEND || CPU_IDLE
select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS
select DMA_DECLARE_COHERENT
+ select DMA_GLOBAL_POOL if !MMU
select DMA_OPS
select DMA_REMAP if MMU
select EDAC_SUPPORT
@@ -63,8 +64,6 @@ config ARM
select GENERIC_PCI_IOMAP
select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND
select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
@@ -127,6 +126,7 @@ config ARM
select RTC_LIB
select SET_FS
select SYS_SUPPORTS_APM_EMULATION
+ select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M
# Above selects are sorted alphabetically; please add new ones
# according to that. Thanks.
help
@@ -190,10 +190,6 @@ config LOCKDEP_SUPPORT
bool
default y
-config TRACE_IRQFLAGS_SUPPORT
- bool
- default !CPU_V7M
-
config ARCH_HAS_ILOG2_U32
bool
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 1c4384db223d..98436702e0c7 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -193,6 +193,14 @@ choice
their output to the USART1 port on SAMV7 based
machines.
+ config DEBUG_AT91_SAMA7G5_FLEXCOM3
+ bool "Kernel low-level debugging on SAMA7G5 FLEXCOM3"
+ select DEBUG_AT91_UART
+ depends on SOC_SAMA7G5
+ help
+ Say Y here if you want kernel low-level debugging support
+ on the FLEXCOM3 port of SAMA7G5.
+
config DEBUG_BCM2835
bool "Kernel low-level debugging on BCM2835 PL011 UART"
depends on ARCH_BCM2835 && ARCH_MULTI_V6
@@ -1668,6 +1676,7 @@ config DEBUG_UART_PHYS
default 0xd4017000 if DEBUG_MMP_UART2
default 0xd4018000 if DEBUG_MMP_UART3
default 0xe0000000 if DEBUG_SPEAR13XX
+ default 0xe1824200 if DEBUG_AT91_SAMA7G5_FLEXCOM3
default 0xe4007000 if DEBUG_HIP04_UART
default 0xe6c40000 if DEBUG_RMOBILE_SCIFA0
default 0xe6c50000 if DEBUG_RMOBILE_SCIFA1
@@ -1729,6 +1738,7 @@ config DEBUG_UART_VIRT
default 0xc8821000 if DEBUG_RV1108_UART1
default 0xc8912000 if DEBUG_RV1108_UART0
default 0xe0010fe0 if ARCH_RPC
+ default 0xe0824200 if DEBUG_AT91_SAMA7G5_FLEXCOM3
default 0xf0010000 if DEBUG_ASM9260_UART
default 0xf0100000 if DEBUG_DIGICOLOR_UA0
default 0xf01fb000 if DEBUG_NOMADIK_UART
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 863347b6b65e..7e0934180724 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -74,6 +74,8 @@ dtb-$(CONFIG_SOC_SAM_V7) += \
at91-sama5d4_xplained.dtb \
at91-sama5d4ek.dtb \
at91-vinco.dtb
+dtb-$(CONFIG_SOC_SAMA7G5) += \
+ at91-sama7g5ek.dtb
dtb-$(CONFIG_ARCH_AXXIA) += \
axm5516-amarillo.dtb
dtb-$(CONFIG_ARCH_BCM2835) += \
@@ -241,8 +243,20 @@ dtb-$(CONFIG_ARCH_INTEGRATOR) += \
integratorcp.dtb
dtb-$(CONFIG_ARCH_IXP4XX) += \
intel-ixp42x-linksys-nslu2.dtb \
+ intel-ixp42x-linksys-wrv54g.dtb \
+ intel-ixp42x-freecom-fsg-3.dtb \
intel-ixp42x-welltech-epbx100.dtb \
- intel-ixp43x-gateworks-gw2358.dtb
+ intel-ixp42x-ixdp425.dtb \
+ intel-ixp43x-kixrp435.dtb \
+ intel-ixp46x-ixdp465.dtb \
+ intel-ixp42x-adi-coyote.dtb \
+ intel-ixp42x-ixdpg425.dtb \
+ intel-ixp42x-iomega-nas100d.dtb \
+ intel-ixp42x-dlink-dsm-g600.dtb \
+ intel-ixp42x-gateworks-gw2348.dtb \
+ intel-ixp43x-gateworks-gw2358.dtb \
+ intel-ixp42x-netgear-wg302v2.dtb \
+ intel-ixp42x-arcom-vulcan.dtb
dtb-$(CONFIG_ARCH_KEYSTONE) += \
keystone-k2hk-evm.dtb \
keystone-k2l-evm.dtb \
@@ -429,6 +443,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-cubox-i-emmc-som-v15.dtb \
imx6dl-cubox-i-som-v15.dtb \
imx6dl-dfi-fs700-m60.dtb \
+ imx6dl-dhcom-picoitx.dtb \
imx6dl-eckelmann-ci4x10.dtb \
imx6dl-emcon-avari.dtb \
imx6dl-gw51xx.dtb \
@@ -475,6 +490,9 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-sabrelite.dtb \
imx6dl-sabresd.dtb \
imx6dl-savageboard.dtb \
+ imx6dl-skov-revc-lt2.dtb \
+ imx6dl-skov-revc-lt6.dtb \
+ imx6dl-solidsense.dtb \
imx6dl-ts4900.dtb \
imx6dl-ts7970.dtb \
imx6dl-tx6dl-comtft.dtb \
@@ -575,6 +593,10 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-sabresd.dtb \
imx6q-savageboard.dtb \
imx6q-sbc6x.dtb \
+ imx6q-skov-revc-lt2.dtb \
+ imx6q-skov-revc-lt6.dtb \
+ imx6q-skov-reve-mi1010ait-1cp1.dtb \
+ imx6q-solidsense.dtb \
imx6q-tbs2910.dtb \
imx6q-ts4900.dtb \
imx6q-ts7970.dtb \
@@ -607,7 +629,8 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6qp-tx6qp-8137-mb7.dtb \
imx6qp-vicutp.dtb \
imx6qp-wandboard-revd1.dtb \
- imx6qp-zii-rdu2.dtb
+ imx6qp-zii-rdu2.dtb \
+ imx6s-dhcom-drc02.dtb
dtb-$(CONFIG_SOC_IMX6SL) += \
imx6sl-evk.dtb \
imx6sl-tolino-shine2hd.dtb \
@@ -843,6 +866,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \
am335x-pocketbeagle.dtb \
am335x-regor-rdk.dtb \
am335x-sancloud-bbe.dtb \
+ am335x-sancloud-bbe-lite.dtb \
am335x-shc.dtb \
am335x-sbc-t335.dtb \
am335x-sl50.dtb \
@@ -933,6 +957,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-ipq4019-ap.dk07.1-c2.dtb \
qcom-ipq8064-ap148.dtb \
qcom-ipq8064-rb3011.dtb \
+ qcom-msm8226-samsung-s3ve3g.dtb \
qcom-msm8660-surf.dtb \
qcom-msm8960-cdp.dtb \
qcom-msm8974-fairphone-fp2.dtb \
@@ -1076,7 +1101,8 @@ dtb-$(CONFIG_ARCH_STI) += \
stih407-b2120.dtb \
stih410-b2120.dtb \
stih410-b2260.dtb \
- stih418-b2199.dtb
+ stih418-b2199.dtb \
+ stih418-b2264.dtb
dtb-$(CONFIG_ARCH_STM32) += \
stm32f429-disco.dtb \
stm32f469-disco.dtb \
@@ -1300,7 +1326,10 @@ dtb-$(CONFIG_ARCH_U8500) += \
ste-href520-tvk.dtb \
ste-ux500-samsung-golden.dtb \
ste-ux500-samsung-janice.dtb \
- ste-ux500-samsung-skomer.dtb
+ ste-ux500-samsung-gavini.dtb \
+ ste-ux500-samsung-codina.dtb \
+ ste-ux500-samsung-skomer.dtb \
+ ste-ux500-samsung-kyle.dtb
dtb-$(CONFIG_ARCH_UNIPHIER) += \
uniphier-ld4-ref.dtb \
uniphier-ld6b-ref.dtb \
@@ -1433,7 +1462,10 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-arm-stardragon4800-rep2.dtb \
aspeed-bmc-asrock-e3c246d4i.dtb \
aspeed-bmc-bytedance-g220a.dtb \
+ aspeed-bmc-facebook-cloudripper.dtb \
aspeed-bmc-facebook-cmm.dtb \
+ aspeed-bmc-facebook-elbert.dtb \
+ aspeed-bmc-facebook-fuji.dtb \
aspeed-bmc-facebook-galaxy100.dtb \
aspeed-bmc-facebook-minipack.dtb \
aspeed-bmc-facebook-tiogapass.dtb \
@@ -1448,6 +1480,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-ibm-rainier-4u.dtb \
aspeed-bmc-intel-s2600wf.dtb \
aspeed-bmc-inspur-fp5280g2.dtb \
+ aspeed-bmc-inspur-nf5280m6.dtb \
aspeed-bmc-lenovo-hr630.dtb \
aspeed-bmc-lenovo-hr855xg2.dtb \
aspeed-bmc-microsoft-olympus.dtb \
diff --git a/arch/arm/boot/dts/am335x-baltos-ir2110.dts b/arch/arm/boot/dts/am335x-baltos-ir2110.dts
index 56915b6d818d..daf4cb398070 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir2110.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir2110.dts
@@ -58,21 +58,21 @@
dr_mode = "host";
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy0: ethernet-phy@0 {
reg = <1>;
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-mode = "rmii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
phy-handle = <&phy0>;
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-mode = "rgmii-id";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
phy-handle = <&phy1>;
};
diff --git a/arch/arm/boot/dts/am335x-baltos-ir3220.dts b/arch/arm/boot/dts/am335x-baltos-ir3220.dts
index d8d60398d803..2123bd589484 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir3220.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir3220.dts
@@ -103,18 +103,18 @@
dr_mode = "host";
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-mode = "rmii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
fixed-link {
speed = <100>;
full-duplex;
};
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-mode = "rgmii-id";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
phy-handle = <&phy1>;
};
diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
index 8096d459b93f..2f3872dbf4f4 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
@@ -120,18 +120,18 @@
dr_mode = "host";
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-mode = "rmii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
fixed-link {
speed = <100>;
full-duplex;
};
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-mode = "rgmii-id";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
phy-handle = <&phy1>;
};
diff --git a/arch/arm/boot/dts/am335x-baltos.dtsi b/arch/arm/boot/dts/am335x-baltos.dtsi
index 1103a2cb836f..366702630290 100644
--- a/arch/arm/boot/dts/am335x-baltos.dtsi
+++ b/arch/arm/boot/dts/am335x-baltos.dtsi
@@ -339,16 +339,15 @@
};
};
-&mac {
+&mac_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
- dual_emac = <1>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
status = "okay";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index 2d51d4bba6d4..0ccdc7cd463b 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -353,24 +353,27 @@
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "mii";
+ ti,dual-emac-pvid = <1>;
};
-&mac {
- slaves = <1>;
+&cpsw_port2 {
+ status = "disabled";
+};
+
+&mac_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
- status = "okay";
ethphy0: ethernet-phy@0 {
reg = <0>;
@@ -397,3 +400,7 @@
clocks = <&clk_32768_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>;
clock-names = "ext-clk", "int-clk";
};
+
+&pruss_tm {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-boneblack-common.dtsi b/arch/arm/boot/dts/am335x-boneblack-common.dtsi
index 64c3e9269f40..10494c4431b9 100644
--- a/arch/arm/boot/dts/am335x-boneblack-common.dtsi
+++ b/arch/arm/boot/dts/am335x-boneblack-common.dtsi
@@ -3,9 +3,6 @@
* Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
*/
-#include <dt-bindings/display/tda998x.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-
&ldo3_reg {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
@@ -25,145 +22,13 @@
non-removable;
};
-&am33xx_pinmux {
- nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
- pinctrl-single,pins = <
- AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
- >;
- };
-
- nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
- pinctrl-single,pins = <
- AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
- >;
- };
-
- mcasp0_pins: mcasp0_pins {
- pinctrl-single,pins = <
- AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
- AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
- AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLUP, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.GPIO1_27 */
- >;
- };
-};
-
-&lcdc {
- status = "okay";
-
- /* If you want to get 24 bit RGB and 16 BGR mode instead of
- * current 16 bit RGB and 24 BGR modes, set the propety
- * below to "crossed" and uncomment the video-ports -property
- * in tda19988 node.
- */
- blue-and-red-wiring = "straight";
-
- port {
- lcdc_0: endpoint@0 {
- remote-endpoint = <&hdmi_0>;
- };
- };
-};
-
-&i2c0 {
- tda19988: tda19988@70 {
- compatible = "nxp,tda998x";
- reg = <0x70>;
- nxp,calib-gpios = <&gpio1 25 0>;
- interrupts-extended = <&gpio1 25 IRQ_TYPE_LEVEL_LOW>;
-
- pinctrl-names = "default", "off";
- pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
- pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
-
- /* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */
- /* video-ports = <0x234501>; */
-
- #sound-dai-cells = <0>;
- audio-ports = < TDA998x_I2S 0x03>;
-
- ports {
- port@0 {
- hdmi_0: endpoint@0 {
- remote-endpoint = <&lcdc_0>;
- };
- };
- };
- };
-};
-
&rtc {
system-power-controller;
};
-&mcasp0 {
- #sound-dai-cells = <0>;
- pinctrl-names = "default";
- pinctrl-0 = <&mcasp0_pins>;
- status = "okay";
- op-mode = <0>; /* MCASP_IIS_MODE */
- tdm-slots = <2>;
- serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
- 0 0 1 0
- >;
- tx-num-evt = <32>;
- rx-num-evt = <32>;
-};
-
/ {
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x20000000>; /* 512 MB */
};
-
- clk_mcasp0_fixed: clk_mcasp0_fixed {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <24576000>;
- };
-
- clk_mcasp0: clk_mcasp0 {
- #clock-cells = <0>;
- compatible = "gpio-gate-clock";
- clocks = <&clk_mcasp0_fixed>;
- enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
- };
-
- sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "TI BeagleBone Black";
- simple-audio-card,format = "i2s";
- simple-audio-card,bitclock-master = <&dailink0_master>;
- simple-audio-card,frame-master = <&dailink0_master>;
-
- dailink0_master: simple-audio-card,cpu {
- sound-dai = <&mcasp0>;
- clocks = <&clk_mcasp0>;
- };
-
- simple-audio-card,codec {
- sound-dai = <&tda19988>;
- };
- };
};
diff --git a/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi b/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi
new file mode 100644
index 000000000000..7cfddada9348
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/display/tda998x.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&am33xx_pinmux {
+ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+ >;
+ };
+
+ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
+ >;
+ };
+
+ mcasp0_pins: mcasp0_pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLUP, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+ >;
+ };
+};
+
+&lcdc {
+ status = "okay";
+
+ /* If you want to get 24 bit RGB and 16 BGR mode instead of
+ * current 16 bit RGB and 24 BGR modes, set the propety
+ * below to "crossed" and uncomment the video-ports -property
+ * in tda19988 node.
+ */
+ blue-and-red-wiring = "straight";
+
+ port {
+ lcdc_0: endpoint@0 {
+ remote-endpoint = <&hdmi_0>;
+ };
+ };
+};
+
+&i2c0 {
+ tda19988: tda19988@70 {
+ compatible = "nxp,tda998x";
+ reg = <0x70>;
+ nxp,calib-gpios = <&gpio1 25 0>;
+ interrupts-extended = <&gpio1 25 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+ /* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */
+ /* video-ports = <0x234501>; */
+
+ #sound-dai-cells = <0>;
+ audio-ports = < TDA998x_I2S 0x03>;
+
+ ports {
+ port@0 {
+ hdmi_0: endpoint@0 {
+ remote-endpoint = <&lcdc_0>;
+ };
+ };
+ };
+ };
+};
+
+&mcasp0 {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcasp0_pins>;
+ status = "okay";
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 0 0 1 0
+ >;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
+};
+
+/ {
+ clk_mcasp0_fixed: clk_mcasp0_fixed {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24576000>;
+ };
+
+ clk_mcasp0: clk_mcasp0 {
+ #clock-cells = <0>;
+ compatible = "gpio-gate-clock";
+ clocks = <&clk_mcasp0_fixed>;
+ enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "TI BeagleBone Black";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&dailink0_master>;
+ simple-audio-card,frame-master = <&dailink0_master>;
+
+ dailink0_master: simple-audio-card,cpu {
+ sound-dai = <&mcasp0>;
+ clocks = <&clk_mcasp0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&tda19988>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/am335x-boneblack-wireless.dts b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
index 80116646a3fe..c72b09ab8da0 100644
--- a/arch/arm/boot/dts/am335x-boneblack-wireless.dts
+++ b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
@@ -7,6 +7,7 @@
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
#include "am335x-boneblack-common.dtsi"
+#include "am335x-boneblack-hdmi.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
@@ -62,7 +63,7 @@
};
};
-&mac {
+&mac_sw {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index e2ee8b8c07bc..9312197316f0 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -7,6 +7,7 @@
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
#include "am335x-boneblack-common.dtsi"
+#include "am335x-boneblack-hdmi.dtsi"
/ {
model = "TI AM335x BeagleBone Black";
diff --git a/arch/arm/boot/dts/am335x-boneblue.dts b/arch/arm/boot/dts/am335x-boneblue.dts
index 0afcc2ee0b63..c6bb325ead33 100644
--- a/arch/arm/boot/dts/am335x-boneblue.dts
+++ b/arch/arm/boot/dts/am335x-boneblue.dts
@@ -435,12 +435,153 @@
status = "okay";
};
+&gpio0 {
+ gpio-line-names =
+ "UART3_CTS", /* M17 */
+ "UART3_RTS", /* M18 */
+ "UART2_RX", /* A17 */
+ "UART2_TX", /* B17 */
+ "I2C1_SDA", /* B16 */
+ "I2C1_SCL", /* A16 */
+ "MMC0_CD", /* C15 */
+ "SPI1_SS2", /* C18 */
+ "EQEP_1A", /* V2 */
+ "EQEP_1B", /* V3 */
+ "MDIR_2B", /* V4 */
+ "BATT_LED_2", /* T5 */
+ "I2C2_SDA", /* D18 */
+ "I2C2_SCL", /* D17 */
+ "UART1_RX", /* D16 */
+ "UART1_TX", /* D15 */
+ "MMC2_DAT1", /* J18 */
+ "MMC2_DAT2", /* K15 */
+ "NC", /* F16 */
+ "WIFI_LED", /* A15 */
+ "MOT_STBY", /* D14 */
+ "WLAN_IRQ", /* K16 */
+ "PWM_2A", /* U10 */
+ "PWM_2B", /* T10 */
+ "",
+ "",
+ "BATT_LED_4", /* T11 */
+ "BATT_LED_1", /* U12 */
+ "BT_EN", /* K17 */
+ "SPI1_SS1", /* H18 */
+ "UART4_RX", /* T17 */
+ "MDIR_1B"; /* U17 */
+};
+
+&gpio1 {
+ gpio-line-names =
+ "MMC1_DAT0", /* U7 */
+ "MMC1_DAT1", /* V7 */
+ "MMC1_DAT2", /* R8 */
+ "MMC1_DAT3", /* T8 */
+ "MMC1_DAT4", /* U8 */
+ "MMC1_DAT5", /* V8 */
+ "MMC1_DAT6", /* R9 */
+ "MMC1_DAT7", /* T9 */
+ "DCAN1_TX", /* E18 */
+ "DCAN1_RX", /* E17 */
+ "UART0_RX", /* E15 */
+ "UART0_TX", /* E16 */
+ "EQEP_2A", /* T12 */
+ "EQEP_2B", /* R12 */
+ "PRU_E_A", /* V13 */
+ "PRU_E_B", /* U13 */
+ "MDIR_2A", /* R13 */
+ "GPIO1_17", /* V14 */
+ "PWM_1A", /* U14 */
+ "PWM_1B", /* T14 */
+ "EMMC_RST", /* R14 */
+ "USR_LED_0", /* V15 */
+ "USR_LED_1", /* U15 */
+ "USR_LED_2", /* T15 */
+ "USR_LED_3", /* V16 */
+ "GPIO1_25", /* U16 */
+ "MCASP0_AXR0", /* T16 */
+ "MCASP0_AXR1", /* V17 */
+ "MCASP0_ACLKR", /* U18 */
+ "BATT_LED_3", /* V6 */
+ "MMC1_CLK", /* U9 */
+ "MMC1_CMD"; /* V9 */
+};
+
+&gpio2 {
+ gpio-line-names =
+ "MDIR_1A", /* T13 */
+ "MCASP0_FSR", /* V12 */
+ "LED_RED", /* R7 */
+ "LED_GREEN", /* T7 */
+ "MODE_BTN", /* U6 */
+ "PAUSE_BTN", /* T6 */
+ "MDIR_4A", /* R1 */
+ "MDIR_4B", /* R2 */
+ "MDIR_3B", /* R3 */
+ "MDIR_3A", /* R4 */
+ "SVO7", /* T1 */
+ "SVO8", /* T2 */
+ "SVO5", /* T3 */
+ "SVO6", /* T4 */
+ "UART5_TX", /* U1 */
+ "UART5_RX", /* U2 */
+ "SERVO_EN", /* U3 */
+ "NC", /* U4 */
+ "UART3_RX", /* L17 */
+ "UART3_TX", /* L16 */
+ "MMC2_CLK", /* L15 */
+ "DCAN1_SILENT", /* M16 */
+ "SVO1", /* U5 */
+ "SVO3", /* R5 */
+ "SVO2", /* V5 */
+ "SVO4", /* R6 */
+ "MMC0_DAT3", /* F17 */
+ "MMC0_DAT2", /* F18 */
+ "MMC0_DAT1", /* G15 */
+ "MMC0_DAT0", /* G16 */
+ "MMC0_CLK", /* G17 */
+ "MMC0_CMD"; /* G18 */
+};
+
&gpio3 {
+ gpio-line-names =
+ "MMC2_DAT3", /* H16 */
+ "GPIO3_1", /* H17 */
+ "GPIO3_2", /* J15 */
+ "MMC2_CMD", /* J16 */
+ "MMC2_DAT0", /* J17 */
+ "I2C0_SDA", /* C17 */
+ "I2C0_SCL", /* C16 */
+ "EMU1", /* C14 */
+ "EMU0", /* B14 */
+ "WL_EN", /* K18 */
+ "WL_BT_OE", /* L18 */
+ "",
+ "",
+ "NC", /* F15 */
+ "SPI1_SCK", /* A13 */
+ "SPI1_MISO", /* B13 */
+ "SPI1_MOSI", /* D12 */
+ "GPIO3_17", /* C12 */
+ "EQEP_0A", /* B12 */
+ "EQEP_0B", /* C13 */
+ "GPIO3_20", /* D13 */
+ "IMU_INT", /* A14 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+
ls-buf-en-hog {
gpio-hog;
gpios = <10 GPIO_ACTIVE_HIGH>;
output-high;
- line-name = "LS_BUF_EN";
};
};
diff --git a/arch/arm/boot/dts/am335x-bonegreen-wireless.dts b/arch/arm/boot/dts/am335x-bonegreen-wireless.dts
index 74db0fc39397..215f279e476b 100644
--- a/arch/arm/boot/dts/am335x-bonegreen-wireless.dts
+++ b/arch/arm/boot/dts/am335x-bonegreen-wireless.dts
@@ -62,7 +62,7 @@
};
};
-&mac {
+&mac_sw {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/am335x-chiliboard.dts b/arch/arm/boot/dts/am335x-chiliboard.dts
index 5660b5f6942d..a223cdd3e30e 100644
--- a/arch/arm/boot/dts/am335x-chiliboard.dts
+++ b/arch/arm/boot/dts/am335x-chiliboard.dts
@@ -128,28 +128,31 @@
};
/* Ethernet */
-&mac {
- slaves = <1>;
+&mac_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
- status = "okay";
ethphy0: ethernet-phy@0 {
reg = <0>;
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "rmii";
+ ti,dual-emac-pvid = <1>;
+};
+
+&cpsw_port2 {
+ status = "disabled";
};
/* USB */
diff --git a/arch/arm/boot/dts/am335x-cm-t335.dts b/arch/arm/boot/dts/am335x-cm-t335.dts
index 688e14e82eba..d9f003d886bf 100644
--- a/arch/arm/boot/dts/am335x-cm-t335.dts
+++ b/arch/arm/boot/dts/am335x-cm-t335.dts
@@ -413,28 +413,31 @@ status = "okay";
status = "okay";
};
-&mac {
+&mac_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
- slaves = <1>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
- status = "okay";
ethphy0: ethernet-phy@0 {
reg = <0>;
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "rgmii-txid";
+ ti,dual-emac-pvid = <1>;
+};
+
+&cpsw_port2 {
+ status = "disabled";
};
&mmc1 {
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 9cf39c93defb..659e99eabe66 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -778,3 +778,7 @@
clocks = <&clk_32768_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>;
clock-names = "ext-clk", "int-clk";
};
+
+&pruss_tm {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index 001657be0381..a2db65538e51 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -715,3 +715,7 @@
clocks = <&clk_32768_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>;
clock-names = "ext-clk", "int-clk";
};
+
+&pruss_tm {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-icev2.dts b/arch/arm/boot/dts/am335x-icev2.dts
index 5e598ac96dcc..e5ce89c8f54d 100644
--- a/arch/arm/boot/dts/am335x-icev2.dts
+++ b/arch/arm/boot/dts/am335x-icev2.dts
@@ -508,3 +508,7 @@
reg = <3>;
};
};
+
+&pruss_tm {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/am335x-igep0033.dtsi
index 7ec23d47a429..cc14415a4eb9 100644
--- a/arch/arm/boot/dts/am335x-igep0033.dtsi
+++ b/arch/arm/boot/dts/am335x-igep0033.dtsi
@@ -93,12 +93,11 @@
};
};
-&mac {
+&mac_sw {
status = "okay";
};
-&davinci_mdio {
- status = "okay";
+&davinci_mdio_sw {
ethphy0: ethernet-phy@0 {
reg = <0>;
@@ -109,15 +108,16 @@
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "rmii";
-
+ ti,dual-emac-pvid = <1>;
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-handle = <&ethphy1>;
phy-mode = "rmii";
+ ti,dual-emac-pvid = <2>;
};
&elm {
diff --git a/arch/arm/boot/dts/am335x-lxm.dts b/arch/arm/boot/dts/am335x-lxm.dts
index 0f078465297a..1282dae144dd 100644
--- a/arch/arm/boot/dts/am335x-lxm.dts
+++ b/arch/arm/boot/dts/am335x-lxm.dts
@@ -295,31 +295,29 @@
dr_mode = "host";
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "rmii";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-handle = <&ethphy1>;
phy-mode = "rmii";
- dual_emac_res_vlan = <3>;
+ ti,dual-emac-pvid = <3>;
};
-&mac {
+&mac_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
- dual_emac = <1>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
- status = "okay";
ethphy0: ethernet-phy@5 {
reg = <5>;
diff --git a/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi b/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi
index 8121a199607c..11e8f64b6606 100644
--- a/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi
+++ b/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi
@@ -122,24 +122,24 @@
regulator-max-microvolt = <5000000>;
};
-&mac {
+&mac_sw {
pinctrl-names = "default";
pinctrl-0 = <&cpsw_default>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default";
pinctrl-0 = <&davinci_mdio_default>;
status = "okay";
};
-&cpsw_emac0 {
- status = "okay";
+&cpsw_port1 {
+ ti,dual-emac-pvid = <1>;
};
-&cpsw_emac1 {
- status = "okay";
+&cpsw_port2 {
+ ti,dual-emac-pvid = <2>;
};
&sham {
diff --git a/arch/arm/boot/dts/am335x-moxa-uc-2101.dts b/arch/arm/boot/dts/am335x-moxa-uc-2101.dts
index 5923b6e7e1cb..1cc513ed92cc 100644
--- a/arch/arm/boot/dts/am335x-moxa-uc-2101.dts
+++ b/arch/arm/boot/dts/am335x-moxa-uc-2101.dts
@@ -52,18 +52,17 @@
};
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy0: ethernet-phy@4 {
reg = <4>;
};
};
-&cpsw_emac0 {
- status = "okay";
+&cpsw_port1 {
phy-handle = <&phy0>;
phy-mode = "rmii";
};
-&cpsw_emac1 {
+&cpsw_port2 {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi b/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi
index 39e5d2ce600a..a7269b90d795 100644
--- a/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi
+++ b/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi
@@ -310,17 +310,15 @@
regulator-max-microvolt = <5000000>;
};
-&mac {
+&mac_sw {
pinctrl-names = "default";
pinctrl-0 = <&cpsw_default>;
- dual_emac = <1>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default";
pinctrl-0 = <&davinci_mdio_default>;
- status = "okay";
ethphy0: ethernet-phy@4 {
reg = <4>;
@@ -331,18 +329,16 @@
};
};
-&cpsw_emac0 {
- status = "okay";
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "rmii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
};
-&cpsw_emac1 {
- status = "okay";
+&cpsw_port2 {
phy-handle = <&ethphy1>;
phy-mode = "rmii";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
};
&sham {
diff --git a/arch/arm/boot/dts/am335x-myirtech-myc.dtsi b/arch/arm/boot/dts/am335x-myirtech-myc.dtsi
index 270a3d5e8f98..245c35f41cdf 100644
--- a/arch/arm/boot/dts/am335x-myirtech-myc.dtsi
+++ b/arch/arm/boot/dts/am335x-myirtech-myc.dtsi
@@ -57,16 +57,27 @@
};
};
-&cpsw_emac0 {
+&mac_sw {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&eth_slave1_pins_default>;
+ pinctrl-1 = <&eth_slave1_pins_sleep>;
+ status = "okay";
+};
+
+&cpsw_port1 {
phy-handle = <&phy0>;
phy-mode = "rgmii-id";
+ ti,dual-emac-pvid = <1>;
+};
+
+&cpsw_port2 {
+ status = "disabled";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mdio_pins_default>;
pinctrl-1 = <&mdio_pins_sleep>;
- status = "okay";
phy0: ethernet-phy@4 {
reg = <4>;
@@ -137,14 +148,6 @@
};
};
-&mac {
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&eth_slave1_pins_default>;
- pinctrl-1 = <&eth_slave1_pins_sleep>;
- slaves = <1>;
- status = "okay";
-};
-
&rtc {
system-power-controller;
};
diff --git a/arch/arm/boot/dts/am335x-myirtech-myd.dts b/arch/arm/boot/dts/am335x-myirtech-myd.dts
index c996639874e6..1479fd95dec2 100644
--- a/arch/arm/boot/dts/am335x-myirtech-myd.dts
+++ b/arch/arm/boot/dts/am335x-myirtech-myd.dts
@@ -86,18 +86,26 @@
};
};
-&cpsw_emac1 {
+&cpsw_port2 {
+ status = "okay";
phy-handle = <&phy1>;
phy-mode = "rgmii-id";
+ ti,dual-emac-pvid = <2>;
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy1: ethernet-phy@6 {
reg = <6>;
eee-broken-1000t;
};
};
+&mac_sw {
+ pinctrl-0 = <&eth_slave1_pins_default>, <&eth_slave2_pins_default>;
+ pinctrl-1 = <&eth_slave1_pins_sleep>, <&eth_slave2_pins_sleep>;
+ slaves = <2>;
+};
+
&dcan0 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&dcan0_pins_default>;
@@ -194,12 +202,6 @@
};
};
-&mac {
- pinctrl-0 = <&eth_slave1_pins_default>, <&eth_slave2_pins_default>;
- pinctrl-1 = <&eth_slave1_pins_sleep>, <&eth_slave2_pins_sleep>;
- slaves = <2>;
-};
-
&mcasp0 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mcasp0_pins_default>;
diff --git a/arch/arm/boot/dts/am335x-nano.dts b/arch/arm/boot/dts/am335x-nano.dts
index 0dbc72d726c9..b6f2567bd65a 100644
--- a/arch/arm/boot/dts/am335x-nano.dts
+++ b/arch/arm/boot/dts/am335x-nano.dts
@@ -369,12 +369,11 @@
};
};
-&mac {
- dual_emac;
+&mac_sw {
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
status = "okay";
ethphy0: ethernet-phy@0 {
@@ -386,16 +385,16 @@
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "mii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-handle = <&ethphy1>;
phy-mode = "mii";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
};
&mmc1 {
diff --git a/arch/arm/boot/dts/am335x-netcan-plus-1xx.dts b/arch/arm/boot/dts/am335x-netcan-plus-1xx.dts
index 8303b832aa50..57e756b0f192 100644
--- a/arch/arm/boot/dts/am335x-netcan-plus-1xx.dts
+++ b/arch/arm/boot/dts/am335x-netcan-plus-1xx.dts
@@ -61,21 +61,21 @@
dr_mode = "host";
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy0: ethernet-phy@0 {
reg = <1>;
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-mode = "rmii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
phy-handle = <&phy0>;
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-mode = "rgmii-id";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
phy-handle = <&phy1>;
};
diff --git a/arch/arm/boot/dts/am335x-netcom-plus-2xx.dts b/arch/arm/boot/dts/am335x-netcom-plus-2xx.dts
index f8e0e95a751f..c6cc1c6218a9 100644
--- a/arch/arm/boot/dts/am335x-netcom-plus-2xx.dts
+++ b/arch/arm/boot/dts/am335x-netcom-plus-2xx.dts
@@ -76,20 +76,20 @@
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy0: ethernet-phy@0 {
reg = <1>;
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-mode = "rmii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
phy-handle = <&phy0>;
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-mode = "rgmii-id";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
phy-handle = <&phy1>;
};
diff --git a/arch/arm/boot/dts/am335x-netcom-plus-8xx.dts b/arch/arm/boot/dts/am335x-netcom-plus-8xx.dts
index a4e137527215..96dffd3ffd85 100644
--- a/arch/arm/boot/dts/am335x-netcom-plus-8xx.dts
+++ b/arch/arm/boot/dts/am335x-netcom-plus-8xx.dts
@@ -96,20 +96,20 @@
};
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy0: ethernet-phy@0 {
reg = <1>;
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-mode = "rmii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
phy-handle = <&phy0>;
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-mode = "rgmii-id";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
phy-handle = <&phy1>;
};
diff --git a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts b/arch/arm/boot/dts/am335x-osd3358-sm-red.dts
index 5403e47c07e2..605b2a436edf 100644
--- a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts
+++ b/arch/arm/boot/dts/am335x-osd3358-sm-red.dts
@@ -391,24 +391,27 @@
clock-frequency = <100000>;
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "rgmii-txid";
+ ti,dual-emac-pvid = <1>;
};
-&mac {
- slaves = <1>;
+&cpsw_port2 {
+ status = "disabled";
+};
+
+&mac_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
- status = "okay";
ethphy0: ethernet-phy@4 {
reg = <4>;
diff --git a/arch/arm/boot/dts/am335x-pcm-953.dtsi b/arch/arm/boot/dts/am335x-pcm-953.dtsi
index 6c547c83e5dd..124026fa0d09 100644
--- a/arch/arm/boot/dts/am335x-pcm-953.dtsi
+++ b/arch/arm/boot/dts/am335x-pcm-953.dtsi
@@ -123,24 +123,22 @@
};
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-handle = <&phy1>;
phy-mode = "rgmii-id";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy1: ethernet-phy@2 {
reg = <2>;
};
};
-&mac {
- slaves = <2>;
+&mac_sw {
pinctrl-names = "default";
pinctrl-0 = <&ethernet0_pins &ethernet1_pins>;
- dual_emac;
};
/* Misc */
diff --git a/arch/arm/boot/dts/am335x-pdu001.dts b/arch/arm/boot/dts/am335x-pdu001.dts
index d41a5ffd83cf..b793beeab245 100644
--- a/arch/arm/boot/dts/am335x-pdu001.dts
+++ b/arch/arm/boot/dts/am335x-pdu001.dts
@@ -494,17 +494,15 @@
};
};
-&mac {
+&mac_sw {
pinctrl-names = "default";
pinctrl-0 = <&cpsw_default>;
- dual_emac; /* no switch, two distinct MACs */
status = "okay";
};
-&davinci_mdio {
+&davinci_mdio_sw {
pinctrl-names = "default";
pinctrl-0 = <&davinci_mdio_default>;
- status = "okay";
ethphy0: ethernet-phy@0 {
reg = <0>;
@@ -515,16 +513,16 @@
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "mii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
};
-&cpsw_emac1 {
+&cpsw_port2 {
phy-handle = <&ethphy1>;
phy-mode = "mii";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
};
&tscadc {
diff --git a/arch/arm/boot/dts/am335x-pepper.dts b/arch/arm/boot/dts/am335x-pepper.dts
index f9a027b47962..b5e88e627bc1 100644
--- a/arch/arm/boot/dts/am335x-pepper.dts
+++ b/arch/arm/boot/dts/am335x-pepper.dts
@@ -260,20 +260,19 @@
};
/* Ethernet */
-&cpsw_emac0 {
- status = "okay";
+&cpsw_port1 {
phy-handle = <&ethphy0>;
phy-mode = "rgmii";
+ ti,dual-emac-pvid = <1>;
};
-&cpsw_emac1 {
- status = "okay";
+&cpsw_port2 {
phy-handle = <&ethphy1>;
phy-mode = "rgmii";
+ ti,dual-emac-pvid = <2>;
};
-&davinci_mdio {
- status = "okay";
+&davinci_mdio_sw {
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
@@ -286,13 +285,12 @@
};
};
-&mac {
+&mac_sw {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ethernet_pins>;
};
-
&am33xx_pinmux {
ethernet_pins: pinmux_ethernet {
pinctrl-single,pins = <
diff --git a/arch/arm/boot/dts/am335x-phycore-som.dtsi b/arch/arm/boot/dts/am335x-phycore-som.dtsi
index 7e46b4c02709..f65cd1331315 100644
--- a/arch/arm/boot/dts/am335x-phycore-som.dtsi
+++ b/arch/arm/boot/dts/am335x-phycore-som.dtsi
@@ -97,24 +97,26 @@
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-handle = <&phy0>;
phy-mode = "rmii";
- dual_emac_res_vlan = <1>;
+ ti,dual-emac-pvid = <1>;
};
-&davinci_mdio {
+&cpsw_port2 {
+ status = "disabled";
+};
+
+&davinci_mdio_sw {
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
- status = "okay";
phy0: ethernet-phy@0 {
reg = <0>;
};
};
-&mac {
- slaves = <1>;
+&mac_sw {
pinctrl-names = "default";
pinctrl-0 = <&ethernet0_pins>;
status = "okay";
diff --git a/arch/arm/boot/dts/am335x-regor.dtsi b/arch/arm/boot/dts/am335x-regor.dtsi
index 6fbf4ac739e7..7b3966ee51b9 100644
--- a/arch/arm/boot/dts/am335x-regor.dtsi
+++ b/arch/arm/boot/dts/am335x-regor.dtsi
@@ -85,23 +85,22 @@
};
};
-&cpsw_emac1 {
+&cpsw_port2 {
+ status = "okay";
phy-handle = <&phy1>;
phy-mode = "mii";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy1: ethernet-phy@1 {
reg = <1>;
};
};
-&mac {
- slaves = <2>;
+&mac_sw {
pinctrl-names = "default";
pinctrl-0 = <&ethernet0_pins &ethernet1_pins>;
- dual_emac = <1>;
};
/* GPIOs */
diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi b/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi
new file mode 100644
index 000000000000..f9b7e774ac48
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+&am33xx_pinmux {
+ cpsw_default: cpsw_default {
+ pinctrl-single,pins = <
+ /* Slave 1 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txen.rgmii1_tctl */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
+ >;
+ };
+
+ cpsw_sleep: cpsw_sleep {
+ pinctrl-single,pins = <
+ /* Slave 1 reset value */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+ >;
+ };
+
+ usb_hub_ctrl: usb_hub_ctrl {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7) /* rmii1_refclk.gpio0_29 */
+ >;
+ };
+};
+
+&mac_sw {
+ pinctrl-0 = <&cpsw_default>;
+ pinctrl-1 = <&cpsw_sleep>;
+};
+
+&cpsw_port1 {
+ phy-mode = "rgmii-id";
+};
+
+&i2c0 {
+ usb2512b: usb-hub@2c {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_hub_ctrl>;
+ compatible = "microchip,usb2512b";
+ reg = <0x2c>;
+ reset-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
+ };
+};
diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts b/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts
new file mode 100644
index 000000000000..d6ef19311a91
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2021 SanCloud Ltd
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include "am335x-boneblack-common.dtsi"
+#include "am335x-sancloud-bbe-common.dtsi"
+
+/ {
+ model = "SanCloud BeagleBone Enhanced Lite";
+ compatible = "sancloud,am335x-boneenhanced",
+ "ti,am335x-bone-black",
+ "ti,am335x-bone",
+ "ti,am33xx";
+};
+
+&am33xx_pinmux {
+ bb_spi0_pins: pinmux_bb_spi0_pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT, MUX_MODE0)
+ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT, MUX_MODE0)
+ >;
+ };
+};
+
+&spi0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bb_spi0_pins>;
+
+ channel@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "micron,spi-authenta";
+
+ reg = <0>;
+ spi-max-frequency = <16000000>;
+ spi-cpha;
+ };
+};
diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe.dts b/arch/arm/boot/dts/am335x-sancloud-bbe.dts
index 275ba339adf4..efbe93135dbe 100644
--- a/arch/arm/boot/dts/am335x-sancloud-bbe.dts
+++ b/arch/arm/boot/dts/am335x-sancloud-bbe.dts
@@ -7,6 +7,8 @@
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
#include "am335x-boneblack-common.dtsi"
+#include "am335x-boneblack-hdmi.dtsi"
+#include "am335x-sancloud-bbe-common.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
@@ -15,66 +17,6 @@
};
&am33xx_pinmux {
- pinctrl-names = "default";
-
- cpsw_default: cpsw_default {
- pinctrl-single,pins = <
- /* Slave 1 */
- AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txen.rgmii1_tctl */
- AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
- AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
- AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
- AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
- AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
- AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
- AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
- AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
- AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
- AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
- AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
- >;
- };
-
- cpsw_sleep: cpsw_sleep {
- pinctrl-single,pins = <
- /* Slave 1 reset value */
- AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
- >;
- };
-
- davinci_mdio_default: davinci_mdio_default {
- pinctrl-single,pins = <
- /* MDIO */
- AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
- AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
- >;
- };
-
- davinci_mdio_sleep: davinci_mdio_sleep {
- pinctrl-single,pins = <
- /* MDIO reset value */
- AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
- AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
- >;
- };
-
- usb_hub_ctrl: usb_hub_ctrl {
- pinctrl-single,pins = <
- AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7) /* rmii1_refclk.gpio0_29 */
- >;
- };
-
mpu6050_pins: pinmux_mpu6050_pins {
pinctrl-single,pins = <
AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT, MUX_MODE7) /* uart0_ctsn.gpio1_8 */
@@ -88,31 +30,10 @@
};
};
-&mac {
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&cpsw_default>;
- pinctrl-1 = <&cpsw_sleep>;
- status = "okay";
-};
-
-&davinci_mdio {
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&davinci_mdio_default>;
- pinctrl-1 = <&davinci_mdio_sleep>;
- status = "okay";
-
- ethphy0: ethernet-phy@0 {
- reg = <0>;
- };
-};
-
-&cpsw_emac0 {
- phy-handle = <&ethphy0>;
- phy-mode = "rgmii-id";
-};
-
&i2c0 {
lps331ap: barometer@5c {
+ pinctrl-names = "default";
+ pinctrl-0 = <&lps3331ap_pins>;
compatible = "st,lps331ap-press";
st,drdy-int-pin = <1>;
reg = <0x5c>;
@@ -121,17 +42,12 @@
};
mpu6050: accelerometer@68 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mpu6050_pins>;
compatible = "invensense,mpu6050";
reg = <0x68>;
interrupt-parent = <&gpio0>;
interrupts = <2 IRQ_TYPE_EDGE_RISING>;
orientation = <0xff 0 0 0 1 0 0 0 0xff>;
};
-
- usb2512b: usb-hub@2c {
- compatible = "microchip,usb2512b";
- reg = <0x2c>;
- reset-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
- /* wifi on port 4 */
- };
};
diff --git a/arch/arm/boot/dts/am335x-shc.dts b/arch/arm/boot/dts/am335x-shc.dts
index 2bfe60d32783..6b9877560741 100644
--- a/arch/arm/boot/dts/am335x-shc.dts
+++ b/arch/arm/boot/dts/am335x-shc.dts
@@ -117,18 +117,6 @@
status = "okay";
};
-&davinci_mdio {
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&davinci_mdio_default>;
- pinctrl-1 = <&davinci_mdio_sleep>;
- status = "okay";
-
- ethernetphy0: ethernet-phy@0 {
- reg = <0>;
- smsc,disable-energy-detect;
- };
-};
-
&epwmss1 {
status = "okay";
@@ -193,15 +181,31 @@
};
};
-&mac {
+&mac_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
status = "okay";
- slaves = <1>;
- cpsw_emac0: slave@200 {
- phy-mode = "mii";
- phy-handle = <&ethernetphy0>;
+};
+
+&cpsw_port1 {
+ phy-mode = "mii";
+ phy-handle = <&ethernetphy0>;
+ ti,dual-emac-pvid = <1>;
+};
+
+&cpsw_port2 {
+ status = "disabled";
+};
+
+&davinci_mdio_sw {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&davinci_mdio_default>;
+ pinctrl-1 = <&davinci_mdio_sleep>;
+
+ ethernetphy0: ethernet-phy@0 {
+ reg = <0>;
+ smsc,disable-energy-detect;
};
};
diff --git a/arch/arm/boot/dts/am335x-sl50.dts b/arch/arm/boot/dts/am335x-sl50.dts
index f4684c8eaffe..6516907ed579 100644
--- a/arch/arm/boot/dts/am335x-sl50.dts
+++ b/arch/arm/boot/dts/am335x-sl50.dts
@@ -661,20 +661,24 @@
};
};
-&cpsw_emac0 {
+&cpsw_port1 {
phy-mode = "mii";
phy-handle = <&ethphy0>;
+ ti,dual-emac-pvid = <1>;
};
-&mac {
+&cpsw_port2 {
+ status = "disabled";
+};
+
+&mac_sw {
status = "okay";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
};
-&davinci_mdio {
- status = "okay";
+&davinci_mdio_sw {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
diff --git a/arch/arm/boot/dts/am335x-wega.dtsi b/arch/arm/boot/dts/am335x-wega.dtsi
index 1359bf8715e6..673159d93a6a 100644
--- a/arch/arm/boot/dts/am335x-wega.dtsi
+++ b/arch/arm/boot/dts/am335x-wega.dtsi
@@ -111,23 +111,22 @@
};
};
-&cpsw_emac1 {
+&cpsw_port2 {
+ status = "okay";
phy-handle = <&phy1>;
phy-mode = "mii";
- dual_emac_res_vlan = <2>;
+ ti,dual-emac-pvid = <2>;
};
-&davinci_mdio {
+&davinci_mdio_sw {
phy1: ethernet-phy@1 {
reg = <1>;
};
};
-&mac {
- slaves = <2>;
+&mac_sw {
pinctrl-names = "default";
pinctrl-0 = <&ethernet0_pins &ethernet1_pins>;
- dual_emac = <1>;
};
/* MMC */
diff --git a/arch/arm/boot/dts/am33xx-l4.dtsi b/arch/arm/boot/dts/am33xx-l4.dtsi
index 859e760df4c8..c9629cb5ccd1 100644
--- a/arch/arm/boot/dts/am33xx-l4.dtsi
+++ b/arch/arm/boot/dts/am33xx-l4.dtsi
@@ -853,6 +853,88 @@
#size-cells = <1>;
ranges = <0x0 0x300000 0x80000>;
status = "disabled";
+
+ pruss: pruss@0 {
+ compatible = "ti,am3356-pruss";
+ reg = <0x0 0x80000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pruss_mem: memories@0 {
+ reg = <0x0 0x2000>,
+ <0x2000 0x2000>,
+ <0x10000 0x3000>;
+ reg-names = "dram0", "dram1",
+ "shrdram2";
+ };
+
+ pruss_cfg: cfg@26000 {
+ compatible = "ti,pruss-cfg", "syscon";
+ reg = <0x26000 0x2000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x26000 0x2000>;
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pruss_iepclk_mux: iepclk-mux@30 {
+ reg = <0x30>;
+ #clock-cells = <0>;
+ clocks = <&l3_gclk>, /* icss_iep_gclk */
+ <&pruss_ocp_gclk>; /* icss_ocp_gclk */
+ };
+ };
+ };
+
+ pruss_mii_rt: mii-rt@32000 {
+ compatible = "ti,pruss-mii", "syscon";
+ reg = <0x32000 0x58>;
+ };
+
+ pruss_intc: interrupt-controller@20000 {
+ compatible = "ti,pruss-intc";
+ reg = <0x20000 0x2000>;
+ interrupts = <20 21 22 23 24 25 26 27>;
+ interrupt-names = "host_intr0", "host_intr1",
+ "host_intr2", "host_intr3",
+ "host_intr4", "host_intr5",
+ "host_intr6", "host_intr7";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ pru0: pru@34000 {
+ compatible = "ti,am3356-pru";
+ reg = <0x34000 0x2000>,
+ <0x22000 0x400>,
+ <0x22400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am335x-pru0-fw";
+ };
+
+ pru1: pru@38000 {
+ compatible = "ti,am3356-pru";
+ reg = <0x38000 0x2000>,
+ <0x24000 0x400>,
+ <0x24400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am335x-pru1-fw";
+ };
+
+ pruss_mdio: mdio@32400 {
+ compatible = "ti,davinci_mdio";
+ reg = <0x32400 0x90>;
+ clocks = <&dpll_core_m4_ck>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ };
};
};
};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 5e33d0e88f5b..f6ec85d58dd1 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -36,8 +36,8 @@
usb1 = &usb1;
phy0 = &usb0_phy;
phy1 = &usb1_phy;
- ethernet0 = &cpsw_emac0;
- ethernet1 = &cpsw_emac1;
+ ethernet0 = &cpsw_port1;
+ ethernet1 = &cpsw_port2;
spi0 = &spi0;
spi1 = &spi1;
mmc0 = &mmc1;
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 57a85a6c34a2..61a1d88f9df6 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -434,6 +434,171 @@
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x54400000 0x80000>;
+
+ pruss1: pruss@0 {
+ compatible = "ti,am4376-pruss1";
+ reg = <0x0 0x40000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pruss1_mem: memories@0 {
+ reg = <0x0 0x2000>,
+ <0x2000 0x2000>,
+ <0x10000 0x8000>;
+ reg-names = "dram0", "dram1",
+ "shrdram2";
+ };
+
+ pruss1_cfg: cfg@26000 {
+ compatible = "ti,pruss-cfg", "syscon";
+ reg = <0x26000 0x2000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x26000 0x2000>;
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pruss1_iepclk_mux: iepclk-mux@30 {
+ reg = <0x30>;
+ #clock-cells = <0>;
+ clocks = <&sysclk_div>, /* icss_iep_gclk */
+ <&pruss_ocp_gclk>; /* icss_ocp_gclk */
+ };
+ };
+ };
+
+ pruss1_mii_rt: mii-rt@32000 {
+ compatible = "ti,pruss-mii", "syscon";
+ reg = <0x32000 0x58>;
+ };
+
+ pruss1_intc: interrupt-controller@20000 {
+ compatible = "ti,pruss-intc";
+ reg = <0x20000 0x2000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host_intr0", "host_intr1",
+ "host_intr2", "host_intr3",
+ "host_intr4",
+ "host_intr6", "host_intr7";
+ ti,irqs-reserved = /bits/ 8 <0x20>; /* BIT(5) */
+ };
+
+ pru1_0: pru@34000 {
+ compatible = "ti,am4376-pru";
+ reg = <0x34000 0x3000>,
+ <0x22000 0x400>,
+ <0x22400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am437x-pru1_0-fw";
+ };
+
+ pru1_1: pru@38000 {
+ compatible = "ti,am4376-pru";
+ reg = <0x38000 0x3000>,
+ <0x24000 0x400>,
+ <0x24400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am437x-pru1_1-fw";
+ };
+
+ pruss1_mdio: mdio@32400 {
+ compatible = "ti,davinci_mdio";
+ reg = <0x32400 0x90>;
+ clocks = <&dpll_core_m4_ck>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ pruss0: pruss@40000 {
+ compatible = "ti,am4376-pruss0";
+ reg = <0x40000 0x40000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pruss0_mem: memories@40000 {
+ reg = <0x40000 0x1000>,
+ <0x42000 0x1000>;
+ reg-names = "dram0", "dram1";
+ };
+
+ pruss0_cfg: cfg@66000 {
+ compatible = "ti,pruss-cfg", "syscon";
+ reg = <0x66000 0x2000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x66000 0x2000>;
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pruss0_iepclk_mux: iepclk-mux@30 {
+ reg = <0x30>;
+ #clock-cells = <0>;
+ clocks = <&sysclk_div>, /* icss_iep_gclk */
+ <&pruss_ocp_gclk>; /* icss_ocp_gclk */
+ };
+ };
+ };
+
+ pruss0_mii_rt: mii-rt@72000 {
+ compatible = "ti,pruss-mii", "syscon";
+ reg = <0x72000 0x58>;
+ status = "disabled";
+ };
+
+ pruss0_intc: interrupt-controller@60000 {
+ compatible = "ti,pruss-intc";
+ reg = <0x60000 0x2000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host_intr0", "host_intr1",
+ "host_intr2", "host_intr3",
+ "host_intr4",
+ "host_intr6", "host_intr7";
+ ti,irqs-reserved = /bits/ 8 <0x20>; /* BIT(5) */
+ };
+
+ pru0_0: pru@74000 {
+ compatible = "ti,am4376-pru";
+ reg = <0x74000 0x1000>,
+ <0x62000 0x400>,
+ <0x62400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am437x-pru0_0-fw";
+ };
+
+ pru0_1: pru@78000 {
+ compatible = "ti,am4376-pru";
+ reg = <0x78000 0x1000>,
+ <0x64000 0x400>,
+ <0x64400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am437x-pru0_1-fw";
+ };
+ };
};
target-module@50000000 {
diff --git a/arch/arm/boot/dts/am437x-cm-t43.dts b/arch/arm/boot/dts/am437x-cm-t43.dts
index a83f46ed0c9a..5ce8e684e7d3 100644
--- a/arch/arm/boot/dts/am437x-cm-t43.dts
+++ b/arch/arm/boot/dts/am437x-cm-t43.dts
@@ -416,3 +416,7 @@
<600000 1100000>,
<300000 950000>;
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index e2677682b540..c2e4896076e7 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -1118,3 +1118,7 @@
&cpu {
cpu0-supply = <&dcdc2>;
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/am437x-idk-evm.dts b/arch/arm/boot/dts/am437x-idk-evm.dts
index 2dc525512266..53f64e3ce735 100644
--- a/arch/arm/boot/dts/am437x-idk-evm.dts
+++ b/arch/arm/boot/dts/am437x-idk-evm.dts
@@ -537,3 +537,7 @@
opp-suspend;
};
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
index 496ed34f7755..20a34d2d85df 100644
--- a/arch/arm/boot/dts/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -892,3 +892,7 @@
};
};
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index 2aa75abf85a9..2f4d2e4e9b3e 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -1018,3 +1018,7 @@
&cpu {
cpu0-supply = <&dcdc2>;
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/am57-pruss.dtsi b/arch/arm/boot/dts/am57-pruss.dtsi
index 032c1acfcda3..46c5383f0eee 100644
--- a/arch/arm/boot/dts/am57-pruss.dtsi
+++ b/arch/arm/boot/dts/am57-pruss.dtsi
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2020-2021 Texas Instruments Incorporated - https://www.ti.com/
*
* Common PRUSS data for TI AM57xx platforms
*/
@@ -25,6 +25,94 @@
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x4b200000 0x80000>;
+
+ pruss1: pruss@0 {
+ compatible = "ti,am5728-pruss";
+ reg = <0x0 0x80000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pruss1_mem: memories@0 {
+ reg = <0x0 0x2000>,
+ <0x2000 0x2000>,
+ <0x10000 0x8000>;
+ reg-names = "dram0", "dram1",
+ "shrdram2";
+ };
+
+ pruss1_cfg: cfg@26000 {
+ compatible = "ti,pruss-cfg", "syscon";
+ reg = <0x26000 0x2000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x26000 0x2000>;
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pruss1_iepclk_mux: iepclk-mux@30 {
+ reg = <0x30>;
+ #clock-cells = <0>;
+ clocks = <&dpll_gmac_m3x2_ck>, /* icss_iep_clk */
+ <&dpll_gmac_h13x2_ck>; /* icss_clk */
+ };
+ };
+ };
+
+ pruss1_mii_rt: mii-rt@32000 {
+ compatible = "ti,pruss-mii", "syscon";
+ reg = <0x32000 0x58>;
+ };
+
+ pruss1_intc: interrupt-controller@20000 {
+ compatible = "ti,pruss-intc";
+ reg = <0x20000 0x2000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host_intr0", "host_intr1",
+ "host_intr2", "host_intr3",
+ "host_intr4", "host_intr5",
+ "host_intr6", "host_intr7";
+ };
+
+ pru1_0: pru@34000 {
+ compatible = "ti,am5728-pru";
+ reg = <0x34000 0x3000>,
+ <0x22000 0x400>,
+ <0x22400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am57xx-pru1_0-fw";
+ };
+
+ pru1_1: pru@38000 {
+ compatible = "ti,am5728-pru";
+ reg = <0x38000 0x3000>,
+ <0x24000 0x400>,
+ <0x24400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am57xx-pru1_1-fw";
+ };
+
+ pruss1_mdio: mdio@32400 {
+ compatible = "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&dpll_gmac_h13x2_ck>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ reg = <0x32400 0x90>;
+ };
+ };
};
pruss2_tm: target-module@4b2a6000 {
@@ -46,5 +134,93 @@
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x4b280000 0x80000>;
+
+ pruss2: pruss@0 {
+ compatible = "ti,am5728-pruss";
+ reg = <0x0 0x80000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pruss2_mem: memories@0 {
+ reg = <0x0 0x2000>,
+ <0x2000 0x2000>,
+ <0x10000 0x8000>;
+ reg-names = "dram0", "dram1",
+ "shrdram2";
+ };
+
+ pruss2_cfg: cfg@26000 {
+ compatible = "ti,pruss-cfg", "syscon";
+ reg = <0x26000 0x2000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x26000 0x2000>;
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pruss2_iepclk_mux: iepclk-mux@30 {
+ reg = <0x30>;
+ #clock-cells = <0>;
+ clocks = <&dpll_gmac_m3x2_ck>, /* icss_iep_clk */
+ <&dpll_gmac_h13x2_ck>; /* icss_clk */
+ };
+ };
+ };
+
+ pruss2_mii_rt: mii-rt@32000 {
+ compatible = "ti,pruss-mii", "syscon";
+ reg = <0x32000 0x58>;
+ };
+
+ pruss2_intc: interrupt-controller@20000 {
+ compatible = "ti,pruss-intc";
+ reg = <0x20000 0x2000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+ <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>;
+ interrupt-names = "host_intr0", "host_intr1",
+ "host_intr2", "host_intr3",
+ "host_intr4", "host_intr5",
+ "host_intr6", "host_intr7";
+ };
+
+ pru2_0: pru@34000 {
+ compatible = "ti,am5728-pru";
+ reg = <0x34000 0x3000>,
+ <0x22000 0x400>,
+ <0x22400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am57xx-pru2_0-fw";
+ };
+
+ pru2_1: pru@38000 {
+ compatible = "ti,am5728-pru";
+ reg = <0x38000 0x3000>,
+ <0x24000 0x400>,
+ <0x24400 0x100>;
+ reg-names = "iram", "control", "debug";
+ firmware-name = "am57xx-pru2_1-fw";
+ };
+
+ pruss2_mdio: mdio@32400 {
+ compatible = "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&dpll_gmac_h13x2_ck>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ reg = <0x32400 0x90>;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/am571x-idk.dts b/arch/arm/boot/dts/am571x-idk.dts
index e81078c2d00d..48425020281a 100644
--- a/arch/arm/boot/dts/am571x-idk.dts
+++ b/arch/arm/boot/dts/am571x-idk.dts
@@ -208,3 +208,11 @@
pinctrl-1 = <&mmc2_pins_hs>;
pinctrl-2 = <&mmc2_pins_ddr_rev20 &mmc2_iodelay_ddr_conf>;
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
+
+&pruss2_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/am572x-idk.dts b/arch/arm/boot/dts/am572x-idk.dts
index 6504265f3f7e..94a738cb0a4d 100644
--- a/arch/arm/boot/dts/am572x-idk.dts
+++ b/arch/arm/boot/dts/am572x-idk.dts
@@ -27,3 +27,11 @@
pinctrl-1 = <&mmc2_pins_hs>;
pinctrl-2 = <&mmc2_pins_ddr_rev20>;
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
+
+&pruss2_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/am5748.dtsi b/arch/arm/boot/dts/am5748.dtsi
index 2cb577432766..c260aa1a85bd 100644
--- a/arch/arm/boot/dts/am5748.dtsi
+++ b/arch/arm/boot/dts/am5748.dtsi
@@ -3,7 +3,7 @@
* Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/
*/
-#include "dra76x.dtsi"
+#include "dra74x-p.dtsi"
#include "am57-pruss.dtsi"
/ {
@@ -25,10 +25,6 @@
status = "disabled";
};
-&usb4_tm {
- status = "disabled";
-};
-
&atl_tm {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/am574x-idk.dts b/arch/arm/boot/dts/am574x-idk.dts
index 1b8f3a28af05..6dff3660bf09 100644
--- a/arch/arm/boot/dts/am574x-idk.dts
+++ b/arch/arm/boot/dts/am574x-idk.dts
@@ -36,10 +36,14 @@
pinctrl-2 = <&mmc2_pins_default>;
};
-&m_can0 {
+&emif1 {
+ status = "okay";
+};
+
+&pruss1_mdio {
status = "disabled";
};
-&emif1 {
- status = "okay";
+&pruss2_mdio {
+ status = "disabled";
};
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
index 6b82ecf803c5..994e69ab38d7 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
@@ -637,3 +637,11 @@
status = "okay";
memory-region = <&dsp2_memory_region>;
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
+
+&pruss2_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
index aed81568a297..2e94f32d9dfc 100644
--- a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
+++ b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
@@ -618,3 +618,11 @@
status = "okay";
ti,no-reset-on-init;
};
+
+&pruss1_mdio {
+ status = "disabled";
+};
+
+&pruss2_mdio {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/aspeed-ast2500-evb.dts b/arch/arm/boot/dts/aspeed-ast2500-evb.dts
index 583a241f1151..1d24b394ea4c 100644
--- a/arch/arm/boot/dts/aspeed-ast2500-evb.dts
+++ b/arch/arm/boot/dts/aspeed-ast2500-evb.dts
@@ -129,3 +129,7 @@
status = "okay";
memory-region = <&gfx_memory>;
};
+
+&rtc {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts
new file mode 100644
index 000000000000..9c6271a17ae8
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts
@@ -0,0 +1,544 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2020 Facebook Inc.
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "ast2600-facebook-netbmc-common.dtsi"
+
+/ {
+ model = "Facebook Cloudripper BMC";
+ compatible = "facebook,cloudripper-bmc", "aspeed,ast2600";
+
+ aliases {
+ /*
+ * PCA9548 (1-0070) provides 8 channels connecting to
+ * SMB (Switch Main Board).
+ */
+ i2c16 = &imux16;
+ i2c17 = &imux17;
+ i2c18 = &imux18;
+ i2c19 = &imux19;
+ i2c20 = &imux20;
+ i2c21 = &imux21;
+ i2c22 = &imux22;
+ i2c23 = &imux23;
+
+ /*
+ * PCA9548 (2-0070) provides 8 channels connecting to
+ * SCM (System Controller Module).
+ */
+ i2c24 = &imux24;
+ i2c25 = &imux25;
+ i2c26 = &imux26;
+ i2c27 = &imux27;
+ i2c28 = &imux28;
+ i2c29 = &imux29;
+ i2c30 = &imux30;
+ i2c31 = &imux31;
+
+ /*
+ * PCA9548 (3-0070) provides 8 channels connecting to
+ * SMB (Switch Main Board).
+ */
+ i2c32 = &imux32;
+ i2c33 = &imux33;
+ i2c34 = &imux34;
+ i2c35 = &imux35;
+ i2c36 = &imux36;
+ i2c37 = &imux37;
+ i2c38 = &imux38;
+ i2c39 = &imux39;
+
+ /*
+ * PCA9548 (8-0070) provides 8 channels connecting to
+ * PDB (Power Delivery Board).
+ */
+ i2c40 = &imux40;
+ i2c41 = &imux41;
+ i2c42 = &imux42;
+ i2c43 = &imux43;
+ i2c44 = &imux44;
+ i2c45 = &imux45;
+ i2c46 = &imux46;
+ i2c47 = &imux47;
+
+ /*
+ * PCA9548 (15-0076) provides 8 channels connecting to
+ * FCM (Fan Controller Module).
+ */
+ i2c48 = &imux48;
+ i2c49 = &imux49;
+ i2c50 = &imux50;
+ i2c51 = &imux51;
+ i2c52 = &imux52;
+ i2c53 = &imux53;
+ i2c54 = &imux54;
+ i2c55 = &imux55;
+ };
+
+ spi_gpio: spi-gpio {
+ num-chipselects = <2>;
+ cs-gpios = <&gpio0 ASPEED_GPIO(X, 0) GPIO_ACTIVE_LOW>,
+ <&gpio0 ASPEED_GPIO(X, 1) GPIO_ACTIVE_HIGH>;
+
+ eeprom@1 {
+ compatible = "atmel,at93c46d";
+ spi-max-frequency = <250000>;
+ data-size = <16>;
+ spi-cs-high;
+ reg = <1>;
+ };
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+/*
+ * "mdio1" is connected to the MDC/MDIO interface of the on-board
+ * management switch (whose ports are connected to BMC, Host and front
+ * panel ethernet port).
+ */
+&mdio1 {
+ status = "okay";
+};
+
+&mdio3 {
+ status = "okay";
+
+ ethphy1: ethernet-phy@13 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x0d>;
+ };
+};
+
+&mac3 {
+ status = "okay";
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii4_default>;
+};
+
+&i2c0 {
+ multi-master;
+ bus-frequency = <1000000>;
+};
+
+&i2c1 {
+ /*
+ * PCA9548 (1-0070) provides 8 channels connecting to SMB (Switch
+ * Main Board).
+ */
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ i2c-mux-idle-disconnect;
+
+ imux16: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux17: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux18: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux19: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux20: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux21: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux22: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux23: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c2 {
+ /*
+ * PCA9548 (2-0070) provides 8 channels connecting to SCM (System
+ * Controller Module).
+ */
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ i2c-mux-idle-disconnect;
+
+ imux24: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux25: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux26: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux27: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux28: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux29: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux30: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux31: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c3 {
+ /*
+ * PCA9548 (3-0070) provides 8 channels connecting to SMB (Switch
+ * Main Board).
+ */
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ i2c-mux-idle-disconnect;
+
+ imux32: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux33: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux34: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux35: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux36: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux37: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux38: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux39: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c6 {
+ lp5012@14 {
+ compatible = "ti,lp5012";
+ reg = <0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi-led@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ color = <LED_COLOR_ID_MULTI>;
+ function = LED_FUNCTION_ACTIVITY;
+ label = "sys";
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+
+ multi-led@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ color = <LED_COLOR_ID_MULTI>;
+ function = LED_FUNCTION_ACTIVITY;
+ label = "fan";
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+
+ multi-led@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ color = <LED_COLOR_ID_MULTI>;
+ function = LED_FUNCTION_ACTIVITY;
+ label = "psu";
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+
+ multi-led@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ color = <LED_COLOR_ID_MULTI>;
+ function = LED_FUNCTION_ACTIVITY;
+ label = "scm";
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+ };
+};
+
+&i2c8 {
+ /*
+ * PCA9548 (8-0070) provides 8 channels connecting to PDB (Power
+ * Delivery Board).
+ */
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ i2c-mux-idle-disconnect;
+
+ imux40: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux41: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux42: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux43: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux44: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux45: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux46: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux47: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+
+ };
+};
+
+&i2c15 {
+ /*
+ * PCA9548 (15-0076) provides 8 channels connecting to FCM (Fan
+ * Controller Module).
+ */
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux48: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux49: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux50: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux51: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux52: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux53: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux54: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux55: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts
new file mode 100644
index 000000000000..27b43fe099f1
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2020 Facebook Inc.
+
+/dts-v1/;
+
+#include "ast2600-facebook-netbmc-common.dtsi"
+
+/ {
+ model = "Facebook Elbert BMC";
+ compatible = "facebook,elbert-bmc", "aspeed,ast2600";
+
+ aliases {
+ serial0 = &uart5;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+
+ /*
+ * 8 child channels of PCA9548 2-0075.
+ */
+ i2c16 = &imux16;
+ i2c17 = &imux17;
+ i2c18 = &imux18;
+ i2c19 = &imux19;
+ i2c20 = &imux20;
+ i2c21 = &imux21;
+ i2c22 = &imux22;
+ i2c23 = &imux23;
+
+ /*
+ * 8 child channels of PCA9548 5-0075.
+ */
+ i2c24 = &imux24;
+ i2c25 = &imux25;
+ i2c26 = &imux26;
+ i2c27 = &imux27;
+ i2c28 = &imux28;
+ i2c29 = &imux29;
+ i2c30 = &imux30;
+ i2c31 = &imux31;
+ };
+
+ chosen {
+ stdout-path = &uart5;
+ };
+
+ spi_gpio: spi-gpio {
+ num-chipselects = <1>;
+ cs-gpios = <&gpio0 ASPEED_GPIO(X, 0) GPIO_ACTIVE_LOW>;
+ };
+};
+
+&lpc_ctrl {
+ status = "okay";
+};
+
+&kcs2 {
+ status = "okay";
+ aspeed,lpc-io-reg = <0xca8>;
+};
+
+&kcs3 {
+ status = "okay";
+ aspeed,lpc-io-reg = <0xca2>;
+};
+
+&i2c2 {
+ i2c-switch@75 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x75>;
+ i2c-mux-idle-disconnect;
+
+ imux16: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux17: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux18: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux19: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux20: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux21: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux22: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux23: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c5 {
+ i2c-switch@75 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x75>;
+ i2c-mux-idle-disconnect;
+
+ imux24: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux25: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux26: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux27: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux28: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux29: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux30: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux31: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c11 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts
new file mode 100644
index 000000000000..af58a73bbc49
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts
@@ -0,0 +1,1251 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2020 Facebook Inc.
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "ast2600-facebook-netbmc-common.dtsi"
+
+/ {
+ model = "Facebook Fuji BMC";
+ compatible = "facebook,fuji-bmc", "aspeed,ast2600";
+
+ aliases {
+ /*
+ * PCA9548 (2-0070) provides 8 channels connecting to
+ * SCM (System Controller Module).
+ */
+ i2c16 = &imux16;
+ i2c17 = &imux17;
+ i2c18 = &imux18;
+ i2c19 = &imux19;
+ i2c20 = &imux20;
+ i2c21 = &imux21;
+ i2c22 = &imux22;
+ i2c23 = &imux23;
+
+ /*
+ * PCA9548 (8-0070) provides 8 channels connecting to
+ * SMB (Switch Main Board).
+ */
+ i2c24 = &imux24;
+ i2c25 = &imux25;
+ i2c26 = &imux26;
+ i2c27 = &imux27;
+ i2c28 = &imux28;
+ i2c29 = &imux29;
+ i2c30 = &imux30;
+ i2c31 = &imux31;
+
+ /*
+ * PCA9548 (11-0077) provides 8 channels connecting to
+ * SMB (Switch Main Board).
+ */
+ i2c40 = &imux40;
+ i2c41 = &imux41;
+ i2c42 = &imux42;
+ i2c43 = &imux43;
+ i2c44 = &imux44;
+ i2c45 = &imux45;
+ i2c46 = &imux46;
+ i2c47 = &imux47;
+
+ /*
+ * PCA9548 (24-0071) provides 8 channels connecting to
+ * PDB-Left.
+ */
+ i2c48 = &imux48;
+ i2c49 = &imux49;
+ i2c50 = &imux50;
+ i2c51 = &imux51;
+ i2c52 = &imux52;
+ i2c53 = &imux53;
+ i2c54 = &imux54;
+ i2c55 = &imux55;
+
+ /*
+ * PCA9548 (25-0072) provides 8 channels connecting to
+ * PDB-Right.
+ */
+ i2c56 = &imux56;
+ i2c57 = &imux57;
+ i2c58 = &imux58;
+ i2c59 = &imux59;
+ i2c60 = &imux60;
+ i2c61 = &imux61;
+ i2c62 = &imux62;
+ i2c63 = &imux63;
+
+ /*
+ * PCA9548 (26-0076) provides 8 channels connecting to
+ * FCM1.
+ */
+ i2c64 = &imux64;
+ i2c65 = &imux65;
+ i2c66 = &imux66;
+ i2c67 = &imux67;
+ i2c68 = &imux68;
+ i2c69 = &imux69;
+ i2c70 = &imux70;
+ i2c71 = &imux71;
+
+ /*
+ * PCA9548 (27-0076) provides 8 channels connecting to
+ * FCM2.
+ */
+ i2c72 = &imux72;
+ i2c73 = &imux73;
+ i2c74 = &imux74;
+ i2c75 = &imux75;
+ i2c76 = &imux76;
+ i2c77 = &imux77;
+ i2c78 = &imux78;
+ i2c79 = &imux79;
+
+ /*
+ * PCA9548 (40-0076) provides 8 channels connecting to
+ * PIM1.
+ */
+ i2c80 = &imux80;
+ i2c81 = &imux81;
+ i2c82 = &imux82;
+ i2c83 = &imux83;
+ i2c84 = &imux84;
+ i2c85 = &imux85;
+ i2c86 = &imux86;
+ i2c87 = &imux87;
+
+ /*
+ * PCA9548 (41-0076) provides 8 channels connecting to
+ * PIM2.
+ */
+ i2c88 = &imux88;
+ i2c89 = &imux89;
+ i2c90 = &imux90;
+ i2c91 = &imux91;
+ i2c92 = &imux92;
+ i2c93 = &imux93;
+ i2c94 = &imux94;
+ i2c95 = &imux95;
+
+ /*
+ * PCA9548 (42-0076) provides 8 channels connecting to
+ * PIM3.
+ */
+ i2c96 = &imux96;
+ i2c97 = &imux97;
+ i2c98 = &imux98;
+ i2c99 = &imux99;
+ i2c100 = &imux100;
+ i2c101 = &imux101;
+ i2c102 = &imux102;
+ i2c103 = &imux103;
+
+ /*
+ * PCA9548 (43-0076) provides 8 channels connecting to
+ * PIM4.
+ */
+ i2c104 = &imux104;
+ i2c105 = &imux105;
+ i2c106 = &imux106;
+ i2c107 = &imux107;
+ i2c108 = &imux108;
+ i2c109 = &imux109;
+ i2c110 = &imux110;
+ i2c111 = &imux111;
+
+ /*
+ * PCA9548 (44-0076) provides 8 channels connecting to
+ * PIM5.
+ */
+ i2c112 = &imux112;
+ i2c113 = &imux113;
+ i2c114 = &imux114;
+ i2c115 = &imux115;
+ i2c116 = &imux116;
+ i2c117 = &imux117;
+ i2c118 = &imux118;
+ i2c119 = &imux119;
+
+ /*
+ * PCA9548 (45-0076) provides 8 channels connecting to
+ * PIM6.
+ */
+ i2c120 = &imux120;
+ i2c121 = &imux121;
+ i2c122 = &imux122;
+ i2c123 = &imux123;
+ i2c124 = &imux124;
+ i2c125 = &imux125;
+ i2c126 = &imux126;
+ i2c127 = &imux127;
+
+ /*
+ * PCA9548 (46-0076) provides 8 channels connecting to
+ * PIM7.
+ */
+ i2c128 = &imux128;
+ i2c129 = &imux129;
+ i2c130 = &imux130;
+ i2c131 = &imux131;
+ i2c132 = &imux132;
+ i2c133 = &imux133;
+ i2c134 = &imux134;
+ i2c135 = &imux135;
+
+ /*
+ * PCA9548 (47-0076) provides 8 channels connecting to
+ * PIM8.
+ */
+ i2c136 = &imux136;
+ i2c137 = &imux137;
+ i2c138 = &imux138;
+ i2c139 = &imux139;
+ i2c140 = &imux140;
+ i2c141 = &imux141;
+ i2c142 = &imux142;
+ i2c143 = &imux143;
+ };
+
+ spi_gpio: spi-gpio {
+ num-chipselects = <3>;
+ cs-gpios = <&gpio0 ASPEED_GPIO(X, 0) GPIO_ACTIVE_LOW>,
+ <0>, /* device reg=<1> does not exist */
+ <&gpio0 ASPEED_GPIO(X, 2) GPIO_ACTIVE_HIGH>;
+
+ eeprom@2 {
+ compatible = "atmel,at93c46d";
+ spi-max-frequency = <250000>;
+ data-size = <16>;
+ spi-cs-high;
+ reg = <2>;
+ };
+ };
+};
+
+&i2c0 {
+ multi-master;
+ bus-frequency = <1000000>;
+};
+
+&i2c2 {
+ /*
+ * PCA9548 (2-0070) provides 8 channels connecting to SCM (System
+ * Controller Module).
+ */
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ i2c-mux-idle-disconnect;
+
+ imux16: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ adm1278@10 {
+ compatible = "adi,adm1278";
+ reg = <0x10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ shunt-resistor-micro-ohms = <1500>;
+ };
+ };
+
+ imux17: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux18: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux19: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux20: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux21: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux22: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux23: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+};
+
+&i2c8 {
+ /*
+ * PCA9548 (8-0070) provides 8 channels connecting to SMB (Switch
+ * Main Board).
+ */
+ i2c-switch@70 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+ i2c-mux-idle-disconnect;
+
+ imux24: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ i2c-switch@71 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x71>;
+ i2c-mux-idle-disconnect;
+
+ imux48: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux49: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux50: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ lp5012@14 {
+ compatible = "ti,lp5012";
+ reg = <0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi-led@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ color = <LED_COLOR_ID_MULTI>;
+ function = LED_FUNCTION_ACTIVITY;
+ label = "sys";
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+
+ multi-led@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ color = <LED_COLOR_ID_MULTI>;
+ function = LED_FUNCTION_ACTIVITY;
+ label = "fan";
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+
+ multi-led@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ color = <LED_COLOR_ID_MULTI>;
+ function = LED_FUNCTION_ACTIVITY;
+ label = "psu";
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+
+ multi-led@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ color = <LED_COLOR_ID_MULTI>;
+ function = LED_FUNCTION_ACTIVITY;
+ label = "smb";
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ };
+ };
+ };
+
+ imux51: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux52: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux53: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux54: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux55: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux25: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ i2c-switch@72 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x72>;
+ i2c-mux-idle-disconnect;
+
+ imux56: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux57: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux58: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux59: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux60: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux61: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux62: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux63: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux26: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux64: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux65: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux66: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux67: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ adm1278@10 {
+ compatible = "adi,adm1278";
+ reg = <0x10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ shunt-resistor-micro-ohms = <250>;
+ };
+ };
+
+ imux68: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux69: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux70: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux71: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux27: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux72: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux73: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux74: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux75: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ adm1278@10 {
+ compatible = "adi,adm1278";
+ reg = <0x10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ shunt-resistor-micro-ohms = <250>;
+ };
+ };
+
+ imux76: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux77: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux78: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux79: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux28: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux29: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux30: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux31: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+
+ };
+};
+
+&i2c11 {
+ status = "okay";
+
+ /*
+ * PCA9548 (11-0077) provides 8 channels connecting to SMB (Switch
+ * Main Board).
+ */
+ i2c-switch@77 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x77>;
+ i2c-mux-idle-disconnect;
+
+ imux40: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux80: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux81: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux82: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux83: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux84: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux85: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux86: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux87: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux41: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux88: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux89: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux90: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux91: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux92: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux93: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux94: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux95: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux42: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux96: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux97: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux98: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux99: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux100: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux101: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux102: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux103: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux43: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux104: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux105: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux106: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux107: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux108: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux109: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux110: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux111: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux44: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux112: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux113: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux114: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux115: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux116: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux117: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux118: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux119: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux45: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux120: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux121: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux122: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux123: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux124: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux125: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux126: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux127: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux46: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux128: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux129: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux130: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux131: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux132: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux133: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux134: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux135: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ imux47: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+
+ i2c-switch@76 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x76>;
+ i2c-mux-idle-disconnect;
+
+ imux136: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ imux137: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ imux138: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ imux139: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+
+ imux140: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ };
+
+ imux141: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ };
+
+ imux142: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ };
+
+ imux143: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ };
+ };
+
+ };
+
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&mdio1 {
+ status = "okay";
+
+ ethphy3: ethernet-phy@13 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x0d>;
+ };
+};
+
+&mac3 {
+ status = "okay";
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii4_default>;
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-galaxy100.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-galaxy100.dts
index dcf213472749..60e875ac2461 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-galaxy100.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-galaxy100.dts
@@ -51,7 +51,3 @@
&vhub {
status = "okay";
};
-
-&adc {
- status = "okay";
-};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts
index 9eb23e874f19..230d16cd9967 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts
@@ -265,19 +265,19 @@
};
/*
- * FIT image: 59.5 MB.
+ * FIT image: 55.5 MB.
*/
fit@80000 {
- reg = <0x80000 0x3b80000>;
+ reg = <0x80000 0x3780000>;
label = "fit";
};
/*
- * "data0" partition (4MB) is reserved for persistent
+ * "data0" partition (8MB) is reserved for persistent
* data store.
*/
data0@3800000 {
- reg = <0x3c00000 0x400000>;
+ reg = <0x3800000 0x800000>;
label = "data0";
};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts
index 39c6be91d53f..584efa528450 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts
@@ -12,6 +12,11 @@
stdout-path = &uart3;
bootargs = "console=ttyS2,9600n8 root=/dev/ram rw";
};
+
+ ast-adc-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 5>, <&adc 6>, <&adc 7>, <&adc 8>, <&adc 9>;
+ };
};
&wdt2 {
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts
index 2dcfeae3c92a..6624855d8ebd 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts
@@ -23,10 +23,6 @@
status = "disabled";
};
-&adc {
- status = "okay";
-};
-
&pwm_tacho {
status = "okay";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts
index 63a3dd548f30..a901c8be49b9 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts
@@ -91,53 +91,7 @@
* Both firmware flashes are 128MB on Wedge400 BMC.
*/
&fmc_flash0 {
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- /*
- * u-boot partition: 384KB.
- */
- u-boot@0 {
- reg = <0x0 0x60000>;
- label = "u-boot";
- };
-
- /*
- * u-boot environment variables: 128KB.
- */
- u-boot-env@60000 {
- reg = <0x60000 0x20000>;
- label = "env";
- };
-
- /*
- * FIT image: 123.5 MB.
- */
- fit@80000 {
- reg = <0x80000 0x7b80000>;
- label = "fit";
- };
-
- /*
- * "data0" partition (4MB) is reserved for persistent
- * data store.
- */
- data0@7c00000 {
- reg = <0x7c00000 0x400000>;
- label = "data0";
- };
-
- /*
- * "flash0" partition (covering the entire flash) is
- * explicitly created to avoid breaking legacy applications.
- */
- flash0@0 {
- reg = <0x0 0x8000000>;
- label = "flash0";
- };
- };
+#include "facebook-bmc-flash-layout-128.dtsi"
};
&fmc_flash1 {
diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
index aa24cac8e5be..2efd70666738 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
@@ -253,7 +253,7 @@
/*O0-O7*/ "","","","","","","","",
/*P0-P7*/ "","","","","led-pcieslot-power","","","",
/*Q0-Q7*/ "","","","","","","","",
- /*R0-R7*/ "","","","","","I2C_FLASH_MICRO_N","","",
+ /*R0-R7*/ "bmc-tpm-reset","power-chassis-control","power-chassis-good","","","I2C_FLASH_MICRO_N","","",
/*S0-S7*/ "","","","","","","","",
/*T0-T7*/ "","","","","","","","",
/*U0-U7*/ "","","","","","","","",
@@ -303,7 +303,7 @@
type = <PCA955X_TYPE_GPIO>;
};
- gpio@01 {
+ gpio@1 {
reg = <1>;
type = <PCA955X_TYPE_GPIO>;
};
@@ -2832,7 +2832,7 @@
&emmc {
status = "okay";
- clk-phase-mmc-hs200 = <180>, <180>;
+ clk-phase-mmc-hs200 = <210>, <228>;
};
&fsim0 {
diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
index 481d0ee1f85f..6419c9762c0b 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
@@ -271,7 +271,7 @@
/*O0-O7*/ "","","","usb-power","","","","",
/*P0-P7*/ "","","","","pcieslot-power","","","",
/*Q0-Q7*/ "cfam-reset","","","","","","","",
- /*R0-R7*/ "","","","","","","","",
+ /*R0-R7*/ "bmc-tpm-reset","power-chassis-control","power-chassis-good","","","","","",
/*S0-S7*/ "presence-ps0","presence-ps1","presence-ps2","presence-ps3",
"","","","",
/*T0-T7*/ "","","","","","","","",
diff --git a/arch/arm/boot/dts/aspeed-bmc-inspur-nf5280m6.dts b/arch/arm/boot/dts/aspeed-bmc-inspur-nf5280m6.dts
new file mode 100644
index 000000000000..b3c1e3ba5831
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-inspur-nf5280m6.dts
@@ -0,0 +1,691 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021 Inspur Corporation
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+#include <dt-bindings/i2c/i2c.h>
+#include <dt-bindings/leds/leds-pca955x.h>
+
+/ {
+ model = "NF5280M6 BMC";
+ compatible = "inspur,nf5280m6-bmc", "aspeed,ast2500";
+
+ chosen {
+ stdout-path = &uart5;
+ bootargs = "console=ttyS4,115200 earlycon";
+ };
+
+ memory@80000000 {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ vga_memory: framebuffer@9f000000 {
+ no-map;
+ reg = <0x9f000000 0x01000000>; /* 16M */
+ };
+
+ video_engine_memory: jpegbuffer {
+ size = <0x02000000>; /* 32M */
+ alignment = <0x01000000>;
+ compatible = "shared-dma-pool";
+ reusable;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ bmc_alive {
+ label = "bmc_alive";
+ gpios = <&gpio ASPEED_GPIO(B, 0) GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "timer";
+ led-pattern = <1000 1000>;
+ };
+
+ front-fan {
+ label = "front-fan";
+ gpios = <&gpio ASPEED_GPIO(F,2) GPIO_ACTIVE_LOW>;
+ };
+
+ front-psu {
+ label = "front-psu";
+ gpios = <&gpio ASPEED_GPIO(F,3) GPIO_ACTIVE_LOW>;
+ };
+
+ front-syshot {
+ label = "front-syshot";
+ gpios = <&gpio ASPEED_GPIO(J, 3) GPIO_ACTIVE_LOW>;
+ };
+
+ front-memory {
+ label = "front-memory";
+ gpios = <&gpio ASPEED_GPIO(S, 7) GPIO_ACTIVE_LOW>;
+ };
+
+ identify {
+ label = "identify";
+ gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>,
+ <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>,
+ <&adc 8>, <&adc 9>, <&adc 10>, <&adc 11>,
+ <&adc 12>, <&adc 13>, <&adc 14>, <&adc 15>;
+ };
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+ spi-max-frequency = <50000000>;
+#include "openbmc-flash-layout.dtsi"
+ };
+};
+
+&spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1_default>;
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bios";
+ spi-max-frequency = <100000000>;
+ };
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&mac0 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii1_default>;
+ clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>,
+ <&syscon ASPEED_CLK_MAC1RCLK>;
+ clock-names = "MACCLK", "RCLK";
+ use-ncsi;
+};
+
+&mac1 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&gpio {
+ status = "okay";
+ /* Enable GPIOE0 and GPIOE2 pass-through by default */
+ pinctrl-names = "pass-through";
+ pinctrl-0 = <&pinctrl_gpie0_default
+ &pinctrl_gpie2_default>;
+ gpio-line-names =
+ /*A0-A7*/ "","MAC2LINK","BMC_RESET_CPLD","","BMC_SCL9","","MAC2MDC_R","",
+ /*B0-B7*/ "BMC_INIT_OK","FM_SKU_ID2","FM_SPD_DDRCPU_LVLSHFT_DIS_R_N",
+ "FM_CPU_MSMI_CATERR_LVT3_BMC_N","","FM_CPU0_PROCHOT_LVT3_N",
+ "FM_CPU_MEM_THERMTRIP_LVT3_N","BIOS_LOAD_DEFAULT_R_N",
+ /*C0-C7*/ "","","","","","","","",
+ /*D0-D7*/ "","BMC_SD2CMD","BMC_SD2DAT0","BMC_SD2DAT1","BMC_SD2DAT2",
+ "BMC_SD2DAT3","BMC_SD2DET","BMC_SD2WPT",
+ /*E0-E7*/ "FM_BOARD_ID0","FM_BOARD_ID1","FM_BOARD_ID2","FM_BOARD_ID3",
+ "FM_BOARD_ID4","FM_BOARD_ID5","","",
+ /*F0-F7*/ "PSU1_PRESENT_N","PSU2_PRESENT_N","FAN_FAULT_LED_N","PSU_FAULT_LED_N",
+ "BIOS_DEBUG_MODE_N","FP_LCD_RESET","FAN_TYPE_SEL",
+ "RST_GLB_RST_WARN_N",
+ /*G0-G7*/ "IRQ_LPTM21L_ALERT_N","IRQ_PLD_ALERT_N","AC_FAIL_N","FP_LCD_PRESENT_BMC",
+ "BMC_JTAG_TCK_MUX_SEL","BMC_BIOS_RESERVED","SYS_NMI_N","BMC_NMI_N",
+ /*H0-H7*/ "JTAG_BMC_TDI","JTAG_BMC_TDO","JTAG_BMC_TCK","JTAG_BMC_TMS","FM_BOARD_ID6",
+ "FM_SKU_ID0","IRQ_SML1_PMBUS_ALERT_N","IRQ_SML0_ALERT_MUX_N",
+ /*I0-I7*/ "FM_CPU_ERR0_LVT3_BMC_N","FM_CPU_ERR1_LVT3_BMC_N","FM_BMC_PCH_SCI_LPC_N",
+ "FM_SYS_THROTTLE_LVC3","SPI2_PCH_CS0_N","","","",
+ /*J0-J7*/ "FM_CPU0_SKTOCC_LVT3_N","FM_CPU1_SKTOCC_LVT3_N","","SYSHOT_FAULT_LED_N",
+ "VGA_HSYNC","VGA_VSYNC","","",
+ /*K0-K7*/ "","","","","","","","",
+ /*L0-L7*/ "","","","","","","SYS_UART_TXD1","SYS_UART_RXD1",
+ /*M0-M7*/ "","","","","","","","",
+ /*N0-N7*/ "","","","","","","","",
+ /*O0-O7*/ "","","","","","","","",
+ /*P0-P7*/ "","","","","","","","",
+ /*Q0-Q7*/ "","","","","","","FM_PCH_BMC_THERMTRIP_N","INTRUDER_N",
+ /*R0-R7*/ "SPI_BMC_BOOT_CS1_R_N","FM_CPU_MEMHOT_LVC3_N",
+ "DBP_CPU_PREQ_N","FM_CPU_ERR2_LVT3_BMC_N",
+ "RISER_NCSI_EN_N","","LOM_NCSI_EN_N","OCP_NCSI_EN_N",
+ /*S0-S7*/ "BMC_XDP_PRDY_N","SIO_POWER_GOOD","BMC_PWR_DEBUG_R_N","BMC_DEBUG_EN_R_N","",
+ "GPIOS5_BMC","","GPIOS7_BMC",
+ /*T0-T7*/ "","","","","","","","",
+ /*U0-U7*/ "","","","","","","","",
+ /*V0-V7*/ "","","","","","","","",
+ /*W0-W7*/ "","","","","","","","",
+ /*X0-X7*/ "","","","","","","","",
+ /*Y0-Y7*/ "","BMC_DET_UID_N","BMC_JTAG_SEL","SIO_ONCONTROL","","","","",
+ /*Z0-Z7*/ "XDP_PRESENT_N","DBP_SYSPWROK","BMC_JTAG_SEL","FM_SMI_ACTIVE_N","",
+ "GPIOZ5","","",
+ /*AA0-AA7*/ "FP_BMC_SYSLED_N","PS_PWROK","RST_PLTRST_BMC_N","HDA_SDO_BMC",
+ "FM_SLPS4_R_N","","POWER_BUTTON","POWER_OUT",
+ /*AB0-AB7*/ "RESET_OUT","RESET_BUTTON","BIOS_REFLASH","POST_COMPLETE","","","","",
+ /*AC0-AC7*/ "","","","","","","","";
+};
+
+&i2c0 {
+ /* FP_LCD */
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ eeprom@50 {
+ compatible = "atmel,24c256";
+ reg = <0x50>;
+ label = "fru";
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ tmp112@48 {
+ compatible = "ti,tmp112";
+ reg = <0x48>;
+ label = "inlet";
+ };
+
+ tmp112@49 {
+ compatible = "ti,tmp112";
+ reg = <0x49>;
+ label = "outlet";
+ };
+
+ pca9548@70 {
+ compatible = "nxp,pca9548";
+ reg = <0x70>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+
+ pca9548@70 {
+ compatible = "nxp,pca9548";
+ reg = <0x70>;
+ };
+
+ pca9548@71 {
+ compatible = "nxp,pca9548";
+ reg = <0x71>;
+ };
+
+ pca9548@72 {
+ compatible = "nxp,pca9548";
+ reg = <0x72>;
+ };
+};
+
+&i2c4 {
+ /* IPMB */
+ status = "okay";
+};
+
+&i2c5 {
+ status = "okay";
+
+ pca9548@70 {
+ compatible = "nxp,pca9548";
+ reg = <0x70>;
+ };
+};
+
+&i2c6 {
+ status = "okay";
+
+ pca9548@70 {
+ compatible = "nxp,pca9548";
+ reg = <0x70>;
+ };
+};
+
+&i2c7 {
+ status = "okay";
+
+ adm1278@33 {
+ compatible = "adi,adm1293";
+ reg = <0x33>;
+ };
+
+ adm1278@32 {
+ compatible = "adi,adm1293";
+ reg = <0x32>;
+ };
+
+ adm1278@20 {
+ compatible = "adi,adm1293";
+ reg = <0x20>;
+ };
+};
+
+&i2c8 {
+ status = "okay";
+
+ pca0: pca9555@23 {
+ compatible = "nxp,pca9555";
+ reg = <0x23>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio@0 {
+ reg = <0>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@1 {
+ reg = <1>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@2 {
+ reg = <2>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@3 {
+ reg = <3>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@4 {
+ reg = <4>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@5 {
+ reg = <5>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@6 {
+ reg = <6>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ };
+
+ pca1: pca9555@22 {
+ compatible = "nxp,pca9555";
+ reg = <0x22>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio@0 {
+ reg = <0>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@1 {
+ reg = <1>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@2 {
+ reg = <2>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@3 {
+ reg = <3>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@4 {
+ reg = <4>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@5 {
+ reg = <5>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@6 {
+ reg = <6>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@7 {
+ reg = <7>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ };
+
+ pca2: pca9555@20 {
+ compatible = "nxp,pca9555";
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio@0 {
+ reg = <0>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@1 {
+ reg = <1>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@2 {
+ reg = <2>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@3 {
+ reg = <3>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@4 {
+ reg = <4>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@5 {
+ reg = <5>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@6 {
+ reg = <6>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@7 {
+ reg = <7>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ };
+
+ pca3: pca9555@21 {
+ compatible = "nxp,pca9555";
+ reg = <0x21>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio@0 {
+ reg = <0>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@1 {
+ reg = <1>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@2 {
+ reg = <2>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@3 {
+ reg = <3>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@4 {
+ reg = <4>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@5 {
+ reg = <5>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@6 {
+ reg = <6>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@7 {
+ reg = <7>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ };
+};
+
+&i2c9 {
+ /* cpld */
+ status = "okay";
+};
+
+&i2c10 {
+ status = "okay";
+
+ pca4: pca9555@24 {
+ compatible = "nxp,pca9555";
+ reg = <0x24>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio@0 {
+ reg = <0>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@1 {
+ reg = <1>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@2 {
+ reg = <2>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@3 {
+ reg = <3>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@4 {
+ reg = <4>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@5 {
+ reg = <5>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@6 {
+ reg = <6>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@7 {
+ reg = <7>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ };
+
+ pca5: pca9555@25 {
+ compatible = "nxp,pca9555";
+ reg = <0x25>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio@0 {
+ reg = <0>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@1 {
+ reg = <1>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@2 {
+ reg = <2>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@3 {
+ reg = <3>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@4 {
+ reg = <4>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@5 {
+ reg = <5>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+
+ gpio@6 {
+ reg = <6>;
+ type = <PCA955X_TYPE_GPIO>;
+ };
+ };
+};
+
+&i2c11 {
+ status = "okay";
+
+ power-supply@58 {
+ compatible = "inspur,ipsps1";
+ reg = <0x58>;
+ };
+
+ power-supply@59 {
+ compatible = "inspur,ipsps1";
+ reg = <0x59>;
+ };
+};
+
+&i2c12 {
+ status = "okay";
+};
+
+&i2c13 {
+ status = "okay";
+};
+
+&pwm_tacho {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
+ &pinctrl_pwm2_default &pinctrl_pwm3_default
+ &pinctrl_pwm4_default &pinctrl_pwm5_default
+ &pinctrl_pwm6_default &pinctrl_pwm7_default>;
+
+ fan@0 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x00 0x01>;
+ };
+
+ fan@1 {
+ reg = <0x01>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x02 0x03>;
+ };
+
+ fan@2 {
+ reg = <0x02>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x04 0x05>;
+ };
+
+ fan@3 {
+ reg = <0x03>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x06 0x07>;
+ };
+
+ fan@4 {
+ reg = <0x04>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x08 0x09>;
+ };
+
+ fan@5 {
+ reg = <0x05>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0a 0x0b>;
+ };
+
+ fan@6 {
+ reg = <0x06>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0c 0x0d>;
+ };
+
+ fan@7 {
+ reg = <0x07>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x0e 0x0f>;
+ };
+};
+
+&kcs3 {
+ status = "okay";
+ aspeed,lpc-io-reg = <0xca2>;
+};
+
+&kcs4 {
+ status = "okay";
+ aspeed,lpc-io-reg = <0xca4>;
+};
+
+&adc {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default
+ &pinctrl_adc2_default &pinctrl_adc3_default &pinctrl_adc4_default
+ &pinctrl_adc5_default &pinctrl_adc6_default &pinctrl_adc7_default
+ &pinctrl_adc8_default &pinctrl_adc9_default &pinctrl_adc10_default
+ &pinctrl_adc11_default &pinctrl_adc12_default &pinctrl_adc13_default
+ &pinctrl_adc14_default &pinctrl_adc15_default>;
+};
+
+&vhub {
+ status = "okay";
+};
+
+&video {
+ status = "okay";
+ memory-region = <&video_engine_memory>;
+};
+
+&vuart {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
index e33153dcaea8..e39f310d55eb 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
@@ -126,7 +126,7 @@
/*M0-M7*/ "","","","","","","","",
/*N0-N7*/ "","","","","","","","",
/*O0-O7*/ "led-rear-power","led-rear-id","","usb-power","","","","",
- /*P0-P7*/ "","","","","","","","",
+ /*P0-P7*/ "","","","","","bmc-tpm-reset","","",
/*Q0-Q7*/ "cfam-reset","","","","","","","fsi-routing",
/*R0-R7*/ "","","","","","","","",
/*S0-S7*/ "","","","","","","","",
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index 329eaeef66fb..73ca1ec6fc24 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -352,7 +352,6 @@
reg = <0x1e780200 0x0100>;
clocks = <&syscon ASPEED_CLK_APB>;
interrupt-controller;
- ngpios = <8>;
bus-frequency = <12000000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sgpm_default>;
diff --git a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
index 7e90d713f5e5..6dde51c2aed3 100644
--- a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
@@ -208,12 +208,12 @@
};
pinctrl_hvi3c3_default: hvi3c3_default {
- function = "HVI3C3";
+ function = "I3C3";
groups = "HVI3C3";
};
pinctrl_hvi3c4_default: hvi3c4_default {
- function = "HVI3C4";
+ function = "I3C4";
groups = "HVI3C4";
};
diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
index f96607b7b4e2..1b47be1704f8 100644
--- a/arch/arm/boot/dts/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
@@ -377,6 +377,34 @@
#interrupt-cells = <2>;
};
+ sgpiom0: sgpiom@1e780500 {
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2600-sgpiom";
+ reg = <0x1e780500 0x100>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ interrupt-controller;
+ bus-frequency = <12000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sgpm1_default>;
+ status = "disabled";
+ };
+
+ sgpiom1: sgpiom@1e780600 {
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2600-sgpiom";
+ reg = <0x1e780600 0x100>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ interrupt-controller;
+ bus-frequency = <12000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sgpm2_default>;
+ status = "disabled";
+ };
+
gpio1: gpio@1e780800 {
#gpio-cells = <2>;
gpio-controller;
diff --git a/arch/arm/boot/dts/ast2400-facebook-netbmc-common.dtsi b/arch/arm/boot/dts/ast2400-facebook-netbmc-common.dtsi
index 73a5503be78c..4e5e786e18b7 100644
--- a/arch/arm/boot/dts/ast2400-facebook-netbmc-common.dtsi
+++ b/arch/arm/boot/dts/ast2400-facebook-netbmc-common.dtsi
@@ -115,3 +115,7 @@
&vhub {
status = "okay";
};
+
+&adc {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi b/arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi
new file mode 100644
index 000000000000..051de5bec345
--- /dev/null
+++ b/arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2020 Facebook Inc.
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+ aliases {
+ mmc0 = &emmc;
+ spi1 = &spi1;
+ spi2 = &spi_gpio;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,9600n8 root=/dev/ram rw vmalloc=640M";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x80000000>;
+ };
+
+ /*
+ * GPIO-based SPI Master is required to access SPI TPM, because
+ * full-duplex SPI transactions are not supported by ASPEED SPI
+ * Controllers.
+ */
+ spi_gpio: spi-gpio {
+ status = "okay";
+ compatible = "spi-gpio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-sck = <&gpio0 ASPEED_GPIO(X, 3) GPIO_ACTIVE_HIGH>;
+ gpio-mosi = <&gpio0 ASPEED_GPIO(X, 4) GPIO_ACTIVE_HIGH>;
+ gpio-miso = <&gpio0 ASPEED_GPIO(X, 5) GPIO_ACTIVE_HIGH>;
+
+ tpmdev@0 {
+ compatible = "tcg,tpm_tis-spi";
+ spi-max-frequency = <33000000>;
+ reg = <0>;
+ };
+ };
+};
+
+&fmc {
+ status = "okay";
+
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "spi0.0";
+
+#include "facebook-bmc-flash-layout-128.dtsi"
+ };
+
+ flash@1 {
+ status = "okay";
+ m25p,fast-read;
+ label = "spi0.1";
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ flash1@0 {
+ reg = <0x0 0x8000000>;
+ label = "flash1";
+ };
+ };
+ };
+};
+
+&spi1 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&wdt1 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&i2c5 {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+};
+
+&i2c7 {
+ status = "okay";
+};
+
+&i2c8 {
+ status = "okay";
+};
+
+&i2c9 {
+ status = "okay";
+};
+
+&i2c10 {
+ status = "okay";
+};
+
+&i2c12 {
+ status = "okay";
+};
+
+&i2c13 {
+ status = "okay";
+};
+
+&i2c15 {
+ status = "okay";
+};
+
+&vhub {
+ status = "okay";
+};
+
+&emmc_controller {
+ status = "okay";
+};
+
+&emmc {
+ status = "okay";
+
+ non-removable;
+ max-frequency = <25000000>;
+ bus-width = <4>;
+};
+
+&rtc {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91-kizbox3_common.dtsi b/arch/arm/boot/dts/at91-kizbox3_common.dtsi
index c4b3750495da..abe27adfa4d6 100644
--- a/arch/arm/boot/dts/at91-kizbox3_common.dtsi
+++ b/arch/arm/boot/dts/at91-kizbox3_common.dtsi
@@ -336,7 +336,7 @@
};
&shutdown_controller {
- atmel,shdwc-debouncer = <976>;
+ debounce-delay-us = <976>;
atmel,wakeup-rtc-timer;
input@0 {
diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts b/arch/arm/boot/dts/at91-sam9x60ek.dts
index edca66c232c1..b1068cca4228 100644
--- a/arch/arm/boot/dts/at91-sam9x60ek.dts
+++ b/arch/arm/boot/dts/at91-sam9x60ek.dts
@@ -92,6 +92,8 @@
leds {
compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
status = "okay"; /* Conflict with pwm0. */
red {
@@ -537,6 +539,10 @@
AT91_PIOA 19 AT91_PERIPH_A (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DRIVE_STRENGTH_HI) /* PA19 DAT2 periph A with pullup */
AT91_PIOA 20 AT91_PERIPH_A (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DRIVE_STRENGTH_HI)>; /* PA20 DAT3 periph A with pullup */
};
+ pinctrl_sdmmc0_cd: sdmmc0_cd {
+ atmel,pins =
+ <AT91_PIOA 23 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
};
sdmmc1 {
@@ -569,6 +575,14 @@
AT91_PIOD 16 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
};
};
+
+ leds {
+ pinctrl_gpio_leds: gpio_leds {
+ atmel,pins = <AT91_PIOB 11 AT91_PERIPH_GPIO AT91_PINCTRL_NONE
+ AT91_PIOB 12 AT91_PERIPH_GPIO AT91_PINCTRL_NONE
+ AT91_PIOB 13 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+ };
}; /* pinctrl */
&pwm0 {
@@ -580,7 +594,7 @@
&sdmmc0 {
bus-width = <4>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_sdmmc0_default>;
+ pinctrl-0 = <&pinctrl_sdmmc0_default &pinctrl_sdmmc0_cd>;
status = "okay";
cd-gpios = <&pioA 23 GPIO_ACTIVE_LOW>;
disable-wp;
@@ -648,7 +662,7 @@
};
&shutdown_controller {
- atmel,shdwc-debouncer = <976>;
+ debounce-delay-us = <976>;
status = "okay";
input@0 {
diff --git a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
index e3251f3e3eaa..b48ac3b62a31 100644
--- a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
+++ b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
@@ -47,32 +47,32 @@
spi-rx-bus-width = <4>;
m25p,fast-read;
- at91bootstrap@00000000 {
+ at91bootstrap@0 {
label = "at91bootstrap";
reg = <0x00000000 0x00040000>;
};
- bootloader@00040000 {
+ bootloader@40000 {
label = "bootloader";
reg = <0x00040000 0x000c0000>;
};
- bootloaderenvred@00100000 {
+ bootloaderenvred@100000 {
label = "bootloader env redundant";
reg = <0x00100000 0x00040000>;
};
- bootloaderenv@00140000 {
+ bootloaderenv@140000 {
label = "bootloader env";
reg = <0x00140000 0x00040000>;
};
- dtb@00180000 {
+ dtb@180000 {
label = "device tree";
reg = <0x00180000 0x00080000>;
};
- kernel@00200000 {
+ kernel@200000 {
label = "kernel";
reg = <0x00200000 0x00600000>;
};
diff --git a/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts b/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
index a9e6fee55a2a..614999dcb990 100644
--- a/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
+++ b/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
@@ -138,7 +138,7 @@
};
shdwc@f8048010 {
- atmel,shdwc-debouncer = <976>;
+ debounce-delay-us = <976>;
atmel,wakeup-rtc-timer;
input@0 {
@@ -224,8 +224,10 @@
adc: adc@fc030000 {
vddana-supply = <&vddana>;
vref-supply = <&advref>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mikrobus1_an &pinctrl_mikrobus2_an>;
- status = "disabled";
+ status = "okay";
};
pinctrl@fc038000 {
diff --git a/arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dts b/arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dts
index ff83967fd008..c145c4e5ef58 100644
--- a/arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dts
+++ b/arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dts
@@ -205,7 +205,7 @@
};
&shutdown_controller {
- atmel,shdwc-debouncer = <976>;
+ debounce-delay-us = <976>;
atmel,wakeup-rtc-timer;
input@0 {
diff --git a/arch/arm/boot/dts/at91-sama5d2_icp.dts b/arch/arm/boot/dts/at91-sama5d2_icp.dts
index bd64721fa23c..e06b58724ca8 100644
--- a/arch/arm/boot/dts/at91-sama5d2_icp.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_icp.dts
@@ -184,6 +184,8 @@
dmas = <0>, <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flx4_default>;
+ i2c-digital-filter;
+ i2c-digital-filter-width-ns = <35>;
status = "okay";
mcp16502@5b {
@@ -307,6 +309,8 @@
&i2c0 { /* mikrobus i2c */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mikrobus_i2c>;
+ i2c-digital-filter;
+ i2c-digital-filter-width-ns = <35>;
status = "okay";
};
@@ -314,6 +318,8 @@
dmas = <0>, <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1_default>;
+ i2c-digital-filter;
+ i2c-digital-filter-width-ns = <35>;
status = "okay";
eeprom@50 {
@@ -693,7 +699,7 @@
};
&shutdown_controller {
- atmel,shdwc-debouncer = <976>;
+ debounce-delay-us = <976>;
atmel,wakeup-rtc-timer;
input@0 {
diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
index dfd150eb0fd8..8ed58af01391 100644
--- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
@@ -93,12 +93,12 @@
reg = <0x40000 0xc0000>;
};
- bootloaderenvred@0x100000 {
+ bootloaderenvred@100000 {
label = "bootloader env redundant";
reg = <0x100000 0x40000>;
};
- bootloaderenv@0x140000 {
+ bootloaderenv@140000 {
label = "bootloader env";
reg = <0x140000 0x40000>;
};
@@ -203,7 +203,7 @@
};
shdwc@f8048010 {
- atmel,shdwc-debouncer = <976>;
+ debounce-delay-us = <976>;
input@0 {
reg = <0>;
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 509c732a0d8b..b1e854f658de 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -95,37 +95,37 @@
spi-rx-bus-width = <4>;
m25p,fast-read;
- at91bootstrap@00000000 {
+ at91bootstrap@0 {
label = "at91bootstrap";
reg = <0x00000000 0x00040000>;
};
- bootloader@00040000 {
+ bootloader@40000 {
label = "bootloader";
reg = <0x00040000 0x000c0000>;
};
- bootloaderenvred@00100000 {
+ bootloaderenvred@100000 {
label = "bootloader env redundant";
reg = <0x00100000 0x00040000>;
};
- bootloaderenv@00140000 {
+ bootloaderenv@140000 {
label = "bootloader env";
reg = <0x00140000 0x00040000>;
};
- dtb@00180000 {
+ dtb@180000 {
label = "device tree";
reg = <0x00180000 0x00080000>;
};
- kernel@00200000 {
+ kernel@200000 {
label = "kernel";
reg = <0x00200000 0x00600000>;
};
- misc@00800000 {
+ misc@800000 {
label = "misc";
reg = <0x00800000 0x00000000>;
};
@@ -347,7 +347,7 @@
};
shdwc@f8048010 {
- atmel,shdwc-debouncer = <976>;
+ debounce-delay-us = <976>;
atmel,wakeup-rtc-timer;
input@0 {
diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
index 9c55a921263b..d72c042f2850 100644
--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -57,6 +57,8 @@
};
spi0: spi@f0004000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi0_cs>;
cs-gpios = <&pioD 13 0>, <0>, <0>, <&pioD 16 0>;
status = "okay";
};
@@ -169,6 +171,8 @@
};
spi1: spi@f8008000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1_cs>;
cs-gpios = <&pioC 25 0>;
status = "okay";
};
@@ -248,6 +252,26 @@
<AT91_PIOE 3 AT91_PERIPH_GPIO AT91_PINCTRL_NONE
AT91_PIOE 4 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
};
+
+ pinctrl_gpio_leds: gpio_leds_default {
+ atmel,pins =
+ <AT91_PIOE 23 AT91_PERIPH_GPIO AT91_PINCTRL_NONE
+ AT91_PIOE 24 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+
+ pinctrl_spi0_cs: spi0_cs_default {
+ atmel,pins =
+ <AT91_PIOD 13 AT91_PERIPH_GPIO AT91_PINCTRL_NONE
+ AT91_PIOD 16 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+
+ pinctrl_spi1_cs: spi1_cs_default {
+ atmel,pins = <AT91_PIOC 25 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+
+ pinctrl_vcc_mmc0_reg_gpio: vcc_mmc0_reg_gpio_default {
+ atmel,pins = <AT91_PIOE 2 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
};
};
};
@@ -339,6 +363,8 @@
vcc_mmc0_reg: fixedregulator_mmc0 {
compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_vcc_mmc0_reg_gpio>;
gpio = <&pioE 2 GPIO_ACTIVE_LOW>;
regulator-name = "mmc0-card-supply";
regulator-min-microvolt = <3300000>;
@@ -362,6 +388,9 @@
leds {
compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
+ status = "okay";
d2 {
label = "d2";
@@ -370,7 +399,7 @@
};
d3 {
- label = "d3";
+ label = "d3"; /* Conflict with EBI CS0, USART2 CTS. */
gpios = <&pioE 24 GPIO_ACTIVE_HIGH>;
};
};
diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
index 0b3ad1b580b8..d241c24f0d83 100644
--- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
@@ -7,6 +7,7 @@
*/
/dts-v1/;
#include "sama5d4.dtsi"
+#include <dt-bindings/input/input.h>
/ {
model = "Atmel SAMA5D4 Xplained";
@@ -38,16 +39,6 @@
status = "okay";
};
- spi0: spi@f8010000 {
- cs-gpios = <&pioC 3 0>, <0>, <0>, <0>;
- status = "okay";
- m25p80@0 {
- compatible = "atmel,at25df321a";
- spi-max-frequency = <50000000>;
- reg = <0>;
- };
- };
-
i2c0: i2c@f8014000 {
i2c-digital-filter;
status = "okay";
@@ -90,6 +81,8 @@
};
spi1: spi@fc018000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi0_cs>;
cs-gpios = <&pioB 21 0>;
status = "okay";
};
@@ -147,6 +140,19 @@
atmel,pins =
<AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
};
+ pinctrl_spi0_cs: spi0_cs_default {
+ atmel,pins =
+ <AT91_PIOB 21 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+ pinctrl_gpio_leds: gpio_leds_default {
+ atmel,pins =
+ <AT91_PIOD 30 AT91_PERIPH_GPIO AT91_PINCTRL_NONE
+ AT91_PIOE 15 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+ pinctrl_vcc_mmc1_reg: vcc_mmc1_reg {
+ atmel,pins =
+ <AT91_PIOE 4 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
};
};
};
@@ -245,13 +251,15 @@
pb_user1 {
label = "pb_user1";
gpios = <&pioE 8 GPIO_ACTIVE_HIGH>;
- linux,code = <0x100>;
+ linux,code = <KEY_PROG1>;
wakeup-source;
};
};
leds {
compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
status = "okay";
d8 {
@@ -278,6 +286,8 @@
vcc_mmc1_reg: fixedregulator_mmc1 {
compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_vcc_mmc1_reg>;
gpio = <&pioE 4 GPIO_ACTIVE_LOW>;
regulator-name = "VDD MCI1";
regulator-min-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/at91-sama7g5ek.dts b/arch/arm/boot/dts/at91-sama7g5ek.dts
new file mode 100644
index 000000000000..4cbed98cc2f4
--- /dev/null
+++ b/arch/arm/boot/dts/at91-sama7g5ek.dts
@@ -0,0 +1,656 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * at91-sama7g5ek.dts - Device Tree file for SAMA7G5-EK board
+ *
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Eugen Hristev <eugen.hristev@microchip.com>
+ * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
+ *
+ */
+/dts-v1/;
+#include "sama7g5-pinfunc.h"
+#include "sama7g5.dtsi"
+#include <dt-bindings/mfd/atmel-flexcom.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Microchip SAMA7G5-EK";
+ compatible = "microchip,sama7g5ek", "microchip,sama7g5", "microchip,sama7";
+
+ chosen {
+ bootargs = "rw root=/dev/mmcblk1p2 rootfstype=ext4 rootwait";
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart3;
+ serial1 = &uart4;
+ serial2 = &uart7;
+ serial3 = &uart0;
+ i2c0 = &i2c1;
+ i2c1 = &i2c8;
+ i2c2 = &i2c9;
+ };
+
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <24000000>;
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_key_gpio_default>;
+
+ bp1 {
+ label = "PB_USER";
+ gpios = <&pioA PIN_PA12 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_PROG1>;
+ wakeup-source;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_led_gpio_default>;
+ status = "okay"; /* Conflict with pwm. */
+
+ red_led {
+ label = "red";
+ gpios = <&pioA PIN_PB8 GPIO_ACTIVE_HIGH>;
+ };
+
+ green_led {
+ label = "green";
+ gpios = <&pioA PIN_PA13 GPIO_ACTIVE_HIGH>;
+ };
+
+ blue_led {
+ label = "blue";
+ gpios = <&pioA PIN_PD20 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ /* 512 M */
+ memory@60000000 {
+ device_type = "memory";
+ reg = <0x60000000 0x20000000>;
+ };
+
+ sound: sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "sama7g5ek audio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ cpu {
+ sound-dai = <&spdiftx>;
+ };
+ codec {
+ sound-dai = <&spdif_out>;
+ };
+ };
+ simple-audio-card,dai-link@1 {
+ reg = <1>;
+ cpu {
+ sound-dai = <&spdifrx>;
+ };
+ codec {
+ sound-dai = <&spdif_in>;
+ };
+ };
+ };
+
+ spdif_in: spdif-in {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dir";
+ };
+
+ spdif_out: spdif-out {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vddcpu>;
+};
+
+&dma0 {
+ status = "okay";
+};
+
+&dma1 {
+ status = "okay";
+};
+
+&dma2 {
+ status = "okay";
+};
+
+&flx0 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+ status = "disabled";
+
+ uart0: serial@200 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flx0_default>;
+ status = "disabled";
+ };
+};
+
+&flx1 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+ status = "okay";
+
+ i2c1: i2c@600 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_default>;
+ i2c-analog-filter;
+ i2c-digital-filter;
+ i2c-digital-filter-width-ns = <35>;
+ status = "okay";
+
+ mcp16502@5b {
+ compatible = "microchip,mcp16502";
+ reg = <0x5b>;
+ status = "okay";
+
+ regulators {
+ vdd_3v3: VDD_IO {
+ regulator-name = "VDD_IO";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3700000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ vddioddr: VDD_DDR {
+ regulator-name = "VDD_DDR";
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1450000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ vddcore: VDD_CORE {
+ regulator-name = "VDD_CORE";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1850000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ vddcpu: VDD_OTHER {
+ regulator-name = "VDD_OTHER";
+ regulator-min-microvolt = <1125000>;
+ regulator-max-microvolt = <1850000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-ramp-delay = <3125>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ vldo1: LDO1 {
+ regulator-name = "LDO1";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3700000>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vldo2: LDO2 {
+ regulator-name = "LDO2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+ };
+};
+
+&flx3 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+ status = "okay";
+
+ uart3: serial@200 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flx3_default>;
+ status = "okay";
+ };
+};
+
+&flx4 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+ status = "okay";
+
+ uart4: serial@200 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flx4_default>;
+ status = "okay";
+ };
+};
+
+&flx7 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+ status = "okay";
+
+ uart7: serial@200 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flx7_default>;
+ status = "okay";
+ };
+};
+
+&flx8 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+ status = "okay";
+
+ i2c8: i2c@600 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c8_default>;
+ i2c-analog-filter;
+ i2c-digital-filter;
+ i2c-digital-filter-width-ns = <35>;
+ status = "okay";
+ };
+};
+
+&flx9 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+ status = "okay";
+
+ i2c9: i2c@600 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c9_default>;
+ i2c-analog-filter;
+ i2c-digital-filter;
+ i2c-digital-filter-width-ns = <35>;
+ status = "okay";
+ };
+};
+
+&flx11 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_SPI>;
+ status = "okay";
+
+ spi11: spi@400 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mikrobus1_spi &pinctrl_mikrobus1_spi_cs>;
+ status = "okay";
+ };
+};
+
+&gmac0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gmac0_default &pinctrl_gmac0_txck_default &pinctrl_gmac0_phy_irq>;
+ phy-mode = "rgmii-id";
+ status = "okay";
+
+ ethernet-phy@7 {
+ reg = <0x7>;
+ interrupt-parent = <&pioA>;
+ interrupts = <PIN_PA31 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&gmac1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gmac1_default &pinctrl_gmac1_phy_irq>;
+ phy-mode = "rmii";
+ status = "okay";
+
+ ethernet-phy@0 {
+ reg = <0x0>;
+ interrupt-parent = <&pioA>;
+ interrupts = <PIN_PA21 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&i2s0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2s0_default>;
+};
+
+&pioA {
+ pinctrl_flx0_default: flx0_default {
+ pinmux = <PIN_PE3__FLEXCOM0_IO0>,
+ <PIN_PE4__FLEXCOM0_IO1>,
+ <PIN_PE6__FLEXCOM0_IO3>,
+ <PIN_PE7__FLEXCOM0_IO4>;
+ bias-disable;
+ };
+
+ pinctrl_flx3_default: flx3_default {
+ pinmux = <PIN_PD16__FLEXCOM3_IO0>,
+ <PIN_PD17__FLEXCOM3_IO1>;
+ bias-disable;
+ };
+
+ pinctrl_flx4_default: flx4_default {
+ pinmux = <PIN_PD18__FLEXCOM4_IO0>,
+ <PIN_PD19__FLEXCOM4_IO1>;
+ bias-disable;
+ };
+
+ pinctrl_flx7_default: flx7_default {
+ pinmux = <PIN_PC23__FLEXCOM7_IO0>,
+ <PIN_PC24__FLEXCOM7_IO1>;
+ bias-disable;
+ };
+
+ pinctrl_gmac0_default: gmac0_default {
+ pinmux = <PIN_PA16__G0_TX0>,
+ <PIN_PA17__G0_TX1>,
+ <PIN_PA26__G0_TX2>,
+ <PIN_PA27__G0_TX3>,
+ <PIN_PA19__G0_RX0>,
+ <PIN_PA20__G0_RX1>,
+ <PIN_PA28__G0_RX2>,
+ <PIN_PA29__G0_RX3>,
+ <PIN_PA15__G0_TXEN>,
+ <PIN_PA30__G0_RXCK>,
+ <PIN_PA18__G0_RXDV>,
+ <PIN_PA22__G0_MDC>,
+ <PIN_PA23__G0_MDIO>,
+ <PIN_PA25__G0_125CK>;
+ bias-disable;
+ };
+
+ pinctrl_gmac0_txck_default: gmac0_txck_default {
+ pinmux = <PIN_PA24__G0_TXCK>;
+ bias-pull-up;
+ };
+
+ pinctrl_gmac0_phy_irq: gmac0_phy_irq {
+ pinmux = <PIN_PA31__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_gmac1_default: gmac1_default {
+ pinmux = <PIN_PD30__G1_TXCK>,
+ <PIN_PD22__G1_TX0>,
+ <PIN_PD23__G1_TX1>,
+ <PIN_PD21__G1_TXEN>,
+ <PIN_PD25__G1_RX0>,
+ <PIN_PD26__G1_RX1>,
+ <PIN_PD27__G1_RXER>,
+ <PIN_PD24__G1_RXDV>,
+ <PIN_PD28__G1_MDC>,
+ <PIN_PD29__G1_MDIO>;
+ bias-disable;
+ };
+
+ pinctrl_gmac1_phy_irq: gmac1_phy_irq {
+ pinmux = <PIN_PA21__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_i2c1_default: i2c1_default {
+ pinmux = <PIN_PC9__FLEXCOM1_IO0>,
+ <PIN_PC10__FLEXCOM1_IO1>;
+ bias-disable;
+ };
+
+ pinctrl_i2c8_default: i2c8_default {
+ pinmux = <PIN_PC14__FLEXCOM8_IO0>,
+ <PIN_PC13__FLEXCOM8_IO1>;
+ bias-disable;
+ };
+
+ pinctrl_i2c9_default: i2c9_default {
+ pinmux = <PIN_PC18__FLEXCOM9_IO0>,
+ <PIN_PC19__FLEXCOM9_IO1>;
+ bias-disable;
+ };
+
+ pinctrl_i2s0_default: i2s0_default {
+ pinmux = <PIN_PB23__I2SMCC0_CK>,
+ <PIN_PB24__I2SMCC0_WS>,
+ <PIN_PB25__I2SMCC0_DOUT1>,
+ <PIN_PB26__I2SMCC0_DOUT0>,
+ <PIN_PB27__I2SMCC0_MCK>;
+ bias-disable;
+ };
+
+ pinctrl_key_gpio_default: key_gpio_default {
+ pinmux = <PIN_PA12__GPIO>;
+ bias-pull-up;
+ };
+
+ pinctrl_led_gpio_default: led_gpio_default {
+ pinmux = <PIN_PA13__GPIO>,
+ <PIN_PB8__GPIO>,
+ <PIN_PD20__GPIO>;
+ bias-pull-up;
+ };
+
+ pinctrl_mikrobus1_an_default: mikrobus1_an_default {
+ pinmux = <PIN_PD0__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_mikrobus2_an_default: mikrobus2_an_default {
+ pinmux = <PIN_PD1__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_mikrobus1_pwm2_default: mikrobus1_pwm2_default {
+ pinmux = <PIN_PA13__PWMH2>;
+ bias-disable;
+ };
+
+ pinctrl_mikrobus2_pwm3_default: mikrobus2_pwm3_default {
+ pinmux = <PIN_PD20__PWMH3>;
+ bias-disable;
+ };
+
+ pinctrl_mikrobus1_spi_cs: mikrobus1_spi_cs {
+ pinmux = <PIN_PB6__FLEXCOM11_IO3>;
+ bias-disable;
+ };
+
+ pinctrl_mikrobus1_spi: mikrobus1_spi {
+ pinmux = <PIN_PB3__FLEXCOM11_IO0>,
+ <PIN_PB4__FLEXCOM11_IO1>,
+ <PIN_PB5__FLEXCOM11_IO2>;
+ bias-disable;
+ };
+
+ pinctrl_sdmmc0_default: sdmmc0_default {
+ cmd_data {
+ pinmux = <PIN_PA1__SDMMC0_CMD>,
+ <PIN_PA3__SDMMC0_DAT0>,
+ <PIN_PA4__SDMMC0_DAT1>,
+ <PIN_PA5__SDMMC0_DAT2>,
+ <PIN_PA6__SDMMC0_DAT3>,
+ <PIN_PA7__SDMMC0_DAT4>,
+ <PIN_PA8__SDMMC0_DAT5>,
+ <PIN_PA9__SDMMC0_DAT6>,
+ <PIN_PA10__SDMMC0_DAT7>;
+ bias-pull-up;
+ };
+
+ ck_cd_rstn_vddsel {
+ pinmux = <PIN_PA0__SDMMC0_CK>,
+ <PIN_PA2__SDMMC0_RSTN>,
+ <PIN_PA11__SDMMC0_DS>;
+ bias-pull-up;
+ };
+ };
+
+ pinctrl_sdmmc1_default: sdmmc1_default {
+ cmd_data {
+ pinmux = <PIN_PB29__SDMMC1_CMD>,
+ <PIN_PB31__SDMMC1_DAT0>,
+ <PIN_PC0__SDMMC1_DAT1>,
+ <PIN_PC1__SDMMC1_DAT2>,
+ <PIN_PC2__SDMMC1_DAT3>;
+ bias-pull-up;
+ };
+
+ ck_cd_rstn_vddsel {
+ pinmux = <PIN_PB30__SDMMC1_CK>,
+ <PIN_PB28__SDMMC1_RSTN>,
+ <PIN_PC5__SDMMC1_1V8SEL>,
+ <PIN_PC4__SDMMC1_CD>;
+ bias-pull-up;
+ };
+ };
+
+ pinctrl_sdmmc2_default: sdmmc2_default {
+ cmd_data {
+ pinmux = <PIN_PD3__SDMMC2_CMD>,
+ <PIN_PD5__SDMMC2_DAT0>,
+ <PIN_PD6__SDMMC2_DAT1>,
+ <PIN_PD7__SDMMC2_DAT2>,
+ <PIN_PD8__SDMMC2_DAT3>;
+ bias-pull-up;
+ };
+
+ ck {
+ pinmux = <PIN_PD4__SDMMC2_CK>;
+ bias-pull-up;
+ };
+ };
+
+ pinctrl_spdifrx_default: spdifrx_default {
+ pinmux = <PIN_PB0__SPDIF_RX>;
+ bias-disable;
+ };
+
+ pinctrl_spdiftx_default: spdiftx_default {
+ pinmux = <PIN_PB1__SPDIF_TX>;
+ bias-disable;
+ };
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mikrobus1_pwm2_default &pinctrl_mikrobus2_pwm3_default>;
+ status = "disabled"; /* Conflict with leds. */
+};
+
+&rtt {
+ atmel,rtt-rtc-time-reg = <&gpbr 0x0>;
+};
+
+&sdmmc0 {
+ bus-width = <8>;
+ non-removable;
+ no-1-8-v;
+ sdhci-caps-mask = <0x0 0x00200000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdmmc0_default>;
+ status = "okay";
+};
+
+&sdmmc1 {
+ bus-width = <4>;
+ no-1-8-v;
+ sdhci-caps-mask = <0x0 0x00200000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdmmc1_default>;
+ status = "okay";
+};
+
+&sdmmc2 {
+ bus-width = <4>;
+ no-1-8-v;
+ sdhci-caps-mask = <0x0 0x00200000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdmmc2_default>;
+};
+
+&spdifrx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdifrx_default>;
+ status = "okay";
+};
+
+&spdiftx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdiftx_default>;
+ status = "okay";
+};
+
+&trng {
+ status = "okay";
+};
+
+&vddout25 {
+ vin-supply = <&vdd_3v3>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/dm8148-evm.dts b/arch/arm/boot/dts/dm8148-evm.dts
index 91d1018ab75f..8ef48c00f98d 100644
--- a/arch/arm/boot/dts/dm8148-evm.dts
+++ b/arch/arm/boot/dts/dm8148-evm.dts
@@ -80,19 +80,19 @@
label = "X-Loader";
reg = <0 0x80000>;
};
- partition@0x80000 {
+ partition@80000 {
label = "U-Boot";
reg = <0x80000 0x1c0000>;
};
- partition@0x1c0000 {
+ partition@1c0000 {
label = "Environment";
reg = <0x240000 0x40000>;
};
- partition@0x280000 {
+ partition@280000 {
label = "Kernel";
reg = <0x280000 0x500000>;
};
- partition@0x780000 {
+ partition@780000 {
label = "Filesystem";
reg = <0x780000 0xf880000>;
};
diff --git a/arch/arm/boot/dts/dm8168-evm.dts b/arch/arm/boot/dts/dm8168-evm.dts
index cf05d532db65..5126e2d72ed7 100644
--- a/arch/arm/boot/dts/dm8168-evm.dts
+++ b/arch/arm/boot/dts/dm8168-evm.dts
@@ -154,19 +154,19 @@
label = "X-Loader";
reg = <0 0x80000>;
};
- partition@0x80000 {
+ partition@80000 {
label = "U-Boot";
reg = <0x80000 0x1c0000>;
};
- partition@0x1c0000 {
+ partition@1c0000 {
label = "Environment";
reg = <0x240000 0x40000>;
};
- partition@0x280000 {
+ partition@280000 {
label = "Kernel";
reg = <0x280000 0x500000>;
};
- partition@0x780000 {
+ partition@780000 {
label = "Filesystem";
reg = <0x780000 0xf880000>;
};
diff --git a/arch/arm/boot/dts/dra74x-p.dtsi b/arch/arm/boot/dts/dra74x-p.dtsi
new file mode 100644
index 000000000000..006189dad7a7
--- /dev/null
+++ b/arch/arm/boot/dts/dra74x-p.dtsi
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "dra74x.dtsi"
+
+/ {
+ compatible = "ti,dra762", "ti,dra7";
+
+ ocp {
+ emif1: emif@4c000000 {
+ compatible = "ti,emif-dra7xx";
+ reg = <0x4c000000 0x200>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+ };
+};
+
+/* MCAN interrupts are hard-wired to irqs 67, 68 */
+&crossbar_mpu {
+ ti,irqs-skip = <10 67 68 133 139 140>;
+};
diff --git a/arch/arm/boot/dts/dra76x.dtsi b/arch/arm/boot/dts/dra76x.dtsi
index a09e7bd77fc7..bc4ae91cba16 100644
--- a/arch/arm/boot/dts/dra76x.dtsi
+++ b/arch/arm/boot/dts/dra76x.dtsi
@@ -9,13 +9,6 @@
compatible = "ti,dra762", "ti,dra7";
ocp {
- emif1: emif@4c000000 {
- compatible = "ti,emif-dra7xx";
- reg = <0x4c000000 0x200>;
- interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
- status = "disabled";
- };
-
target-module@42c01900 {
compatible = "ti,sysc-dra7-mcan", "ti,sysc";
ranges = <0x0 0x42c00000 0x2000>;
@@ -90,11 +83,6 @@
};
};
-/* MCAN interrupts are hard-wired to irqs 67, 68 */
-&crossbar_mpu {
- ti,irqs-skip = <10 67 68 133 139 140>;
-};
-
&scm_conf_clocks {
dpll_gmac_h14x2_ctrl_ck: dpll_gmac_h14x2_ctrl_ck@3fc {
#clock-cells = <0>;
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 77ab7193b903..a10b789d8acf 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -50,6 +50,17 @@
#address-cells = <1>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ };
+ };
+
cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a7";
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 70baad9b11f0..7e7d65ce6585 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -32,6 +32,17 @@
#address-cells = <1>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ };
+ };
+
cpu0: cpu@900 {
device_type = "cpu";
compatible = "arm,cortex-a9";
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index a142fe84010b..d3802046c8b8 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -35,6 +35,23 @@
#address-cells = <1>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ core2 {
+ cpu = <&cpu2>;
+ };
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+ };
+
cpu0: cpu@a00 {
device_type = "cpu";
compatible = "arm,cortex-a9";
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 2ea2caaca4e2..4ffa9253b566 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -50,6 +50,17 @@
#address-cells = <1>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ };
+ };
+
cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a15";
diff --git a/arch/arm/boot/dts/exynos5260.dtsi b/arch/arm/boot/dts/exynos5260.dtsi
index 973448c4ad93..52fa211525ce 100644
--- a/arch/arm/boot/dts/exynos5260.dtsi
+++ b/arch/arm/boot/dts/exynos5260.dtsi
@@ -34,42 +34,68 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu2>;
+ };
+ core1 {
+ cpu = <&cpu3>;
+ };
+ core2 {
+ cpu = <&cpu4>;
+ };
+ core3 {
+ cpu = <&cpu5>;
+ };
+ };
+ };
+
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x0>;
cci-control-port = <&cci_control1>;
};
- cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x1>;
cci-control-port = <&cci_control1>;
};
- cpu@100 {
+ cpu2: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x100>;
cci-control-port = <&cci_control0>;
};
- cpu@101 {
+ cpu3: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x101>;
cci-control-port = <&cci_control0>;
};
- cpu@102 {
+ cpu4: cpu@102 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x102>;
cci-control-port = <&cci_control0>;
};
- cpu@103 {
+ cpu5: cpu@103 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x103>;
diff --git a/arch/arm/boot/dts/exynos5420-cpus.dtsi b/arch/arm/boot/dts/exynos5420-cpus.dtsi
index 58d1c54cf925..e9f4eb75b50f 100644
--- a/arch/arm/boot/dts/exynos5420-cpus.dtsi
+++ b/arch/arm/boot/dts/exynos5420-cpus.dtsi
@@ -22,6 +22,38 @@
#address-cells = <1>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ core2 {
+ cpu = <&cpu2>;
+ };
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu4>;
+ };
+ core1 {
+ cpu = <&cpu5>;
+ };
+ core2 {
+ cpu = <&cpu6>;
+ };
+ core3 {
+ cpu = <&cpu7>;
+ };
+ };
+ };
+
cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a15";
diff --git a/arch/arm/boot/dts/exynos5422-cpus.dtsi b/arch/arm/boot/dts/exynos5422-cpus.dtsi
index 4b641b9b8179..412a0bb4b988 100644
--- a/arch/arm/boot/dts/exynos5422-cpus.dtsi
+++ b/arch/arm/boot/dts/exynos5422-cpus.dtsi
@@ -21,6 +21,38 @@
#address-cells = <1>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ core2 {
+ cpu = <&cpu2>;
+ };
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu4>;
+ };
+ core1 {
+ cpu = <&cpu5>;
+ };
+ core2 {
+ cpu = <&cpu6>;
+ };
+ core3 {
+ cpu = <&cpu7>;
+ };
+ };
+ };
+
cpu0: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a7";
diff --git a/arch/arm/boot/dts/facebook-bmc-flash-layout-128.dtsi b/arch/arm/boot/dts/facebook-bmc-flash-layout-128.dtsi
new file mode 100644
index 000000000000..7f3652dea550
--- /dev/null
+++ b/arch/arm/boot/dts/facebook-bmc-flash-layout-128.dtsi
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2020 Facebook Inc.
+
+partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /*
+ * u-boot partition: 896KB.
+ */
+ u-boot@0 {
+ reg = <0x0 0xe0000>;
+ label = "u-boot";
+ };
+
+ /*
+ * u-boot environment variables: 64KB.
+ */
+ u-boot-env@e0000 {
+ reg = <0xe0000 0x10000>;
+ label = "env";
+ };
+
+ /*
+ * image metadata partition (64KB), used by Facebook internal
+ * tools.
+ */
+ image-meta@f0000 {
+ reg = <0xf0000 0x10000>;
+ label = "meta";
+ };
+
+ /*
+ * FIT image: 119 MB.
+ */
+ fit@100000 {
+ reg = <0x100000 0x7700000>;
+ label = "fit";
+ };
+
+ /*
+ * "data0" partition (8MB) is used by Facebook BMC platforms as
+ * persistent data store.
+ */
+ data0@7800000 {
+ reg = <0x7800000 0x800000>;
+ label = "data0";
+ };
+
+ /*
+ * Although the master partition can be created by enabling
+ * MTD_PARTITIONED_MASTER option, below "flash0" partition is
+ * explicitly created to avoid breaking legacy applications.
+ */
+ flash0@0 {
+ reg = <0x0 0x8000000>;
+ label = "flash0";
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-ppd.dts b/arch/arm/boot/dts/imx53-ppd.dts
index 5a5fa6190a52..37d0cffea99c 100644
--- a/arch/arm/boot/dts/imx53-ppd.dts
+++ b/arch/arm/boot/dts/imx53-ppd.dts
@@ -70,6 +70,12 @@
clock-frequency = <11289600>;
};
+ achc_24M: achc-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ };
+
sgtlsound: sound {
compatible = "fsl,imx53-cpuvo-sgtl5000",
"fsl,imx-audio-sgtl5000";
@@ -314,16 +320,13 @@
&gpio4 12 GPIO_ACTIVE_LOW>;
status = "okay";
- spidev0: spi@0 {
- compatible = "ge,achc";
- reg = <0>;
- spi-max-frequency = <1000000>;
- };
-
- spidev1: spi@1 {
- compatible = "ge,achc";
- reg = <1>;
- spi-max-frequency = <1000000>;
+ spidev0: spi@1 {
+ compatible = "ge,achc", "nxp,kinetis-k20";
+ reg = <1>, <0>;
+ vdd-supply = <&reg_3v3>;
+ vdda-supply = <&reg_3v3>;
+ clocks = <&achc_24M>;
+ reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
};
gpioxra0: gpio@2 {
diff --git a/arch/arm/boot/dts/imx6dl-dhcom-picoitx.dts b/arch/arm/boot/dts/imx6dl-dhcom-picoitx.dts
new file mode 100644
index 000000000000..038bb0025556
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-dhcom-picoitx.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 DH electronics GmbH
+ *
+ * DHCOM iMX6 variant:
+ * DHCM-iMX6DL-C0800-R102-F0819-E-SD-RTC-T-HS-I-01D2
+ * DHCOM PCB number: 493-300 or newer
+ * PicoITX PCB number: 487-600 or newer
+ */
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-dhcom-som.dtsi"
+#include "imx6qdl-dhcom-picoitx.dtsi"
+
+/ {
+ model = "DH electronics i.MX6DL DHCOM on PicoITX";
+ compatible = "dh,imx6dl-dhcom-picoitx", "dh,imx6dl-dhcom-som",
+ "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-skov-revc-lt2.dts b/arch/arm/boot/dts/imx6dl-skov-revc-lt2.dts
new file mode 100644
index 000000000000..667b8faa1807
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-skov-revc-lt2.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Copyright (C) 2020 Pengutronix, Ulrich Oelmann <kernel@pengutronix.de>
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-skov-cpu.dtsi"
+#include "imx6qdl-skov-cpu-revc.dtsi"
+
+/ {
+ model = "SKOV IMX6 CPU SoloCore";
+ compatible = "skov,imx6dl-skov-revc-lt2", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-skov-revc-lt6.dts b/arch/arm/boot/dts/imx6dl-skov-revc-lt6.dts
new file mode 100644
index 000000000000..5dcc433fe2af
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-skov-revc-lt6.dts
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Copyright (C) 2020 Pengutronix, Ulrich Oelmann <kernel@pengutronix.de>
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-skov-cpu.dtsi"
+#include "imx6qdl-skov-cpu-revc.dtsi"
+
+/ {
+ model = "SKOV IMX6 CPU SoloCore";
+ compatible = "skov,imx6dl-skov-revc-lt6", "fsl,imx6dl";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ enable-gpios = <&gpio6 23 GPIO_ACTIVE_LOW>;
+ pwms = <&pwm2 0 20000 0>;
+ brightness-levels = <0 255>;
+ num-interpolated-steps = <17>;
+ default-brightness-level = <8>;
+ power-supply = <&reg_24v0>;
+ };
+
+ display {
+ compatible = "fsl,imx-parallel-display";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ display0_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+
+ panel {
+ compatible = "logictechno,lttd800480070-l6wh-rt";
+ backlight = <&backlight>;
+ power-supply = <&reg_3v3>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&display0_out>;
+ };
+ };
+ };
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
+
+&iomuxc {
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_TD3__GPIO6_IO23 0x58
+ >;
+ };
+
+ 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
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dl-solidsense.dts b/arch/arm/boot/dts/imx6dl-solidsense.dts
new file mode 100644
index 000000000000..2a3699adbed0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-solidsense.dts
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 Rabeeh Khoury <rabeeh@solid-run.com>
+ * Based on dt work by Russell King
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-sr-som.dtsi"
+#include "imx6qdl-sr-som-emmc.dtsi"
+#include "imx6qdl-sr-som-ti.dtsi"
+#include "imx6qdl-hummingboard2.dtsi"
+#include "imx6qdl-solidsense.dtsi"
+
+/ {
+ model = "SolidRun SolidSense Solo/DualLite (1.5som+emmc)";
+ compatible = "solidrun,solidsense/dl", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts b/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts
index a685b1c3208f..d4d57370615d 100644
--- a/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts
+++ b/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts
@@ -1,269 +1,25 @@
-// SPDX-License-Identifier: (GPL-2.0+)
+// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2015 DH electronics GmbH
+ * Copyright (C) 2015-2021 DH electronics GmbH
* Copyright (C) 2018 Marek Vasut <marex@denx.de>
+ *
+ * DHCOM iMX6 variant:
+ * DHCM-iMX6Q-C0800-R102-F0819-E-SD-RTC-T-HS-I-01D2
+ * DHCOM PCB number: 493-300 or newer
+ * PDK2 PCB number: 516-400 or newer
*/
-
/dts-v1/;
-#include "imx6q-dhcom-som.dtsi"
+#include "imx6q.dtsi"
+#include "imx6qdl-dhcom-som.dtsi"
+#include "imx6qdl-dhcom-pdk2.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>;
- };
-
- display_bl: display-bl {
- compatible = "pwm-backlight";
- pwms = <&pwm1 0 50000 PWM_POLARITY_INVERTED>;
- brightness-levels = <0 16 22 30 40 55 75 102 138 188 255>;
- default-brightness-level = <8>;
- enable-gpios = <&gpio3 27 GPIO_ACTIVE_HIGH>;
- status = "okay";
- };
-
- lcd_display: disp0 {
- compatible = "fsl,imx-parallel-display";
- #address-cells = <1>;
- #size-cells = <0>;
- interface-pix-fmt = "rgb24";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ipu1_lcdif>;
- status = "okay";
-
- 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>;
- };
- };
- };
-
- panel {
- compatible = "edt,etm0700g0edh6";
- ddc-i2c-bus = <&i2c2>;
- backlight = <&display_bl>;
-
- port {
- lcd_panel_in: endpoint {
- remote-endpoint = <&lcd_display_out>;
- };
- };
- };
-
- 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";
-};
-
-&can1 {
- status = "okay";
-};
-
-&can2 {
- status = "disabled";
-};
-
-&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 = <&sw2_reg>;
- };
-
- touchscreen@38 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_touchscreen>;
- compatible = "edt,edt-ft5406";
- reg = <0x38>;
- interrupt-parent = <&gpio4>;
- interrupts = <5 IRQ_TYPE_EDGE_FALLING>; /* GPIO E */
- };
-};
-
-&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_DI0_PIN4__GPIO4_IO20 0x400120b0
- 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_ipu1_lcdif: ipu1-lcdif-grp {
- fsl,pins = <
- MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x38
- MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x38
- MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x38
- MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x38
- MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x38
- MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x38
- MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x38
- MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x38
- MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x38
- MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x38
- MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x38
- MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x38
- MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x38
- MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x38
- MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x38
- MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x38
- MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x38
- MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x38
- MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x38
- MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x38
- MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x38
- MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x38
- MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x38
- MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x38
- MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x38
- MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x38
- MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x38
- MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x38
- MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x120b0
- >;
- };
-
- pinctrl_pwm1: pwm1-grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- >;
- };
-
- pinctrl_touchscreen: touchscreen-grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b1
- >;
- };
-
- pinctrl_pcie: pcie-grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b0b1
- >;
- };
-};
-
-&ipu1_di0_disp0 {
- remote-endpoint = <&lcd_display_in>;
-};
-
-&pcie {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pcie>;
- reset-gpio = <&gpio6 14 GPIO_ACTIVE_LOW>;
- status = "okay";
-};
-
-&pwm1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pwm1>;
- status = "okay";
-};
-
-&ssi1 {
- status = "okay";
+ model = "DH electronics i.MX6Q DHCOM on Premium Developer Kit (2)";
+ compatible = "dh,imx6q-dhcom-pdk2", "dh,imx6q-dhcom-som",
+ "fsl,imx6q";
};
&sata {
status = "okay";
};
-
-&usdhc3 {
- status = "okay";
-};
diff --git a/arch/arm/boot/dts/imx6q-skov-revc-lt2.dts b/arch/arm/boot/dts/imx6q-skov-revc-lt2.dts
new file mode 100644
index 000000000000..f00add7b3048
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-skov-revc-lt2.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Copyright (C) 2020 Pengutronix, Ulrich Oelmann <kernel@pengutronix.de>
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-skov-cpu.dtsi"
+#include "imx6qdl-skov-cpu-revc.dtsi"
+
+/ {
+ model = "SKOV IMX6 CPU QuadCore";
+ compatible = "skov,imx6q-skov-revc-lt2", "fsl,imx6q";
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ /* internal 22 k pull up required */
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001f878
+ /* internal 22 k pull up required */
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001f878
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q-skov-revc-lt6.dts b/arch/arm/boot/dts/imx6q-skov-revc-lt6.dts
new file mode 100644
index 000000000000..3e3b36ad362a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-skov-revc-lt6.dts
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Copyright (C) 2020 Pengutronix, Ulrich Oelmann <kernel@pengutronix.de>
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-skov-cpu.dtsi"
+#include "imx6qdl-skov-cpu-revc.dtsi"
+
+/ {
+ model = "SKOV IMX6 CPU QuadCore";
+ compatible = "skov,imx6q-skov-revc-lt6", "fsl,imx6q";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ enable-gpios = <&gpio6 23 GPIO_ACTIVE_LOW>;
+ pwms = <&pwm2 0 20000 0>;
+ brightness-levels = <0 255>;
+ num-interpolated-steps = <17>;
+ default-brightness-level = <8>;
+ power-supply = <&reg_24v0>;
+ };
+
+ display {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "fsl,imx-parallel-display";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1>;
+
+ port@0 {
+ reg = <0>;
+
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ display0_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+
+ panel {
+ compatible = "logictechno,lttd800480070-l6wh-rt";
+ backlight = <&backlight>;
+ power-supply = <&reg_3v3>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&display0_out>;
+ };
+ };
+ };
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
+
+&iomuxc {
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_TD3__GPIO6_IO23 0x58
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ /* internal 22 k pull up required */
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001F878
+ /* internal 22 k pull up required */
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001F878
+ >;
+ };
+
+ 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
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q-skov-reve-mi1010ait-1cp1.dts b/arch/arm/boot/dts/imx6q-skov-reve-mi1010ait-1cp1.dts
new file mode 100644
index 000000000000..7f1f19b74bfa
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-skov-reve-mi1010ait-1cp1.dts
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Copyright (C) 2020 Pengutronix, Ulrich Oelmann <kernel@pengutronix.de>
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-skov-cpu.dtsi"
+
+/ {
+ model = "SKOV IMX6 CPU QuadCore";
+ compatible = "skov,imx6q-skov-reve-mi1010ait-1cp1", "fsl,imx6q";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ enable-gpios = <&gpio6 23 GPIO_ACTIVE_LOW>;
+ pwms = <&pwm2 0 20000 0>;
+ brightness-levels = <0 255>;
+ num-interpolated-steps = <17>;
+ default-brightness-level = <8>;
+ power-supply = <&reg_24v0>;
+ };
+
+ panel {
+ compatible = "multi-inno,mi1010ait-1cp";
+ backlight = <&backlight>;
+ power-supply = <&reg_3v3>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+ assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>,
+ <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>;
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ touchscreen@38 {
+ compatible = "edt,edt-ft5406";
+ reg = <0x38>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_touchscreen>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+ touchscreen-size-x = <1280>;
+ touchscreen-size-y = <800>;
+ wakeup-source;
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+&ldb {
+ status = "okay";
+
+ lvds-channel@0 {
+ status = "okay";
+
+ port@4 {
+ reg = <4>;
+
+ lvds0_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_TD3__GPIO6_IO23 0x58
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ /* external 1 k pull up */
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x40010878
+ /* external 1 k pull up */
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x40010878
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ /* internal 22 k pull up required */
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001F878
+ /* internal 22 k pull up required */
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001F878
+ >;
+ };
+
+ pinctrl_touchscreen: touchscreengrp {
+ fsl,pins = <
+ /* external 10 k pull up */
+ /* CTP_INT */
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0
+ /* CTP_RST */
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x1b0b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q-solidsense.dts b/arch/arm/boot/dts/imx6q-solidsense.dts
new file mode 100644
index 000000000000..0e6a325df363
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-solidsense.dts
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 Rabeeh Khoury <rabeeh@solid-run.com>
+ * Based on dt work by Russell King
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-sr-som.dtsi"
+#include "imx6qdl-sr-som-emmc.dtsi"
+#include "imx6qdl-sr-som-ti.dtsi"
+#include "imx6qdl-hummingboard2.dtsi"
+#include "imx6qdl-solidsense.dtsi"
+
+/ {
+ model = "SolidRun SolidSense Dual/Quad (1.5som+emmc)";
+ compatible = "solidrun,solidsense/q", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 8d209c1b3ca7..9caba4529c71 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -177,7 +177,7 @@
clocks = <&clks IMX6Q_CLK_ECSPI5>,
<&clks IMX6Q_CLK_ECSPI5>;
clock-names = "ipg", "per";
- dmas = <&sdma 11 8 1>, <&sdma 12 8 2>;
+ dmas = <&sdma 11 7 1>, <&sdma 12 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6qdl-dhcom-drc02.dtsi b/arch/arm/boot/dts/imx6qdl-dhcom-drc02.dtsi
new file mode 100644
index 000000000000..3d0a50a9ab21
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-dhcom-drc02.dtsi
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 DH electronics GmbH
+ */
+
+/ {
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+/*
+ * Special SoM hardware required which uses the pins from micro SD card. The
+ * pins SD3_DAT0 and SD3_DAT1 are muxed as can2 Tx and Rx. The signals for can2
+ * Tx and Rx are routed to the DHCOM UART1 rts/cts pins. Therefore the micro SD
+ * card must be disabled and the uart1 rts/cts must be output on other DHCOM
+ * pins, see uart1 and usdhc3 node below.
+ */
+&can2 {
+ status = "okay";
+};
+
+&gpio1 {
+ /*
+ * NOTE: On DRC02, the RS485_RX_En is controlled by a separate
+ * GPIO line, however the i.MX6 UART driver assumes RX happens
+ * during TX anyway and that it only controls drive enable DE
+ * line. Hence, the RX is always enabled here.
+ */
+ rs485-rx-en-hog {
+ gpio-hog;
+ gpios = <18 0>; /* GPIO Q */
+ line-name = "rs485-rx-en";
+ output-low;
+ };
+};
+
+&gpio3 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "DRC02-In1", "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ "", "", "", "", "", "DHCOM-E", "DRC02-In2", "DHCOM-H",
+ "DHCOM-I", "DRC02-HW0", "", "", "", "", "", "",
+ "", "", "", "", "DRC02-Out1", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio6 {
+ gpio-line-names =
+ "", "", "", "DRC02-Out2", "", "", "SOM-HW1", "",
+ "", "", "", "", "", "", "DRC02-HW2", "DRC02-HW1",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&i2c1 {
+ eeprom@50 {
+ compatible = "atmel,24c04";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+};
+
+&uart1 {
+ /*
+ * Due to the use of can2 the signals for can2 Tx and Rx are routed to
+ * DHCOM UART1 rts/cts pins. Therefore this UART have to use DHCOM GPIOs
+ * for rts/cts. So configure DHCOM GPIO I as rts and GPIO M as cts.
+ */
+ /delete-property/ uart-has-rtscts;
+ cts-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>; /* GPIO M */
+ pinctrl-0 = <&pinctrl_uart1 &pinctrl_dhcom_i &pinctrl_dhcom_m>;
+ pinctrl-names = "default";
+ rts-gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; /* GPIO I */
+};
+
+&uart5 {
+ /*
+ * On DRC02 this UART is used as RS485 interface and RS485_TX_En is
+ * controlled by DHCOM GPIO P. So remove rts/cts pins and the property
+ * uart-has-rtscts from this UART and add the DHCOM GPIO P pin via
+ * rts-gpios. The RS485_RX_En is controlled by DHCOM GPIO Q, see gpio1
+ * node above.
+ */
+ /delete-property/ uart-has-rtscts;
+ linux,rs485-enabled-at-boot-time;
+ pinctrl-0 = <&pinctrl_uart5_core &pinctrl_dhcom_p &pinctrl_dhcom_q>;
+ pinctrl-names = "default";
+ rts-gpios = <&gpio7 13 GPIO_ACTIVE_HIGH>; /* GPIO P */
+};
+
+&usdhc2 { /* SD card */
+ status = "okay";
+};
+
+&usdhc3 {
+ /*
+ * Due to the use of can2 the micro SD card on module have to be
+ * disabled, because the pins SD3_DAT0 and SD3_DAT1 are muxed as
+ * can2 Tx and Rx.
+ */
+ status = "disabled";
+};
+
+&iomuxc {
+ pinctrl-0 = <
+ /*
+ * The following DHCOM GPIOs are used on this board.
+ * Therefore, they have been removed from the list below.
+ * I: uart1 rts
+ * M: uart1 cts
+ * P: uart5 rs485-tx-en
+ * Q: uart5 rs485-rx-en
+ */
+ &pinctrl_hog_base
+ &pinctrl_dhcom_a &pinctrl_dhcom_b &pinctrl_dhcom_c
+ &pinctrl_dhcom_d &pinctrl_dhcom_e &pinctrl_dhcom_f
+ &pinctrl_dhcom_g &pinctrl_dhcom_h
+ &pinctrl_dhcom_j &pinctrl_dhcom_k &pinctrl_dhcom_l
+ &pinctrl_dhcom_n &pinctrl_dhcom_o
+ &pinctrl_dhcom_r
+ &pinctrl_dhcom_s &pinctrl_dhcom_t &pinctrl_dhcom_u
+ &pinctrl_dhcom_v &pinctrl_dhcom_w &pinctrl_dhcom_int
+ >;
+ pinctrl-names = "default";
+
+ pinctrl_uart5_core: uart5-core-grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA 0x1b0b1
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6qdl-dhcom-pdk2.dtsi b/arch/arm/boot/dts/imx6qdl-dhcom-pdk2.dtsi
new file mode 100644
index 000000000000..dc21853706a5
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-dhcom-pdk2.dtsi
@@ -0,0 +1,361 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015-2021 DH electronics GmbH
+ * Copyright (C) 2018 Marek Vasut <marex@denx.de>
+ */
+
+#include <dt-bindings/leds/common.h>
+
+/ {
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ clk_ext_audio_codec: clock-codec {
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ compatible = "fixed-clock";
+ };
+
+ display_bl: display-bl {
+ brightness-levels = <0 16 22 30 40 55 75 102 138 188 255>;
+ compatible = "pwm-backlight";
+ default-brightness-level = <8>;
+ enable-gpios = <&gpio3 27 GPIO_ACTIVE_HIGH>; /* GPIO G */
+ pwms = <&pwm1 0 50000 PWM_POLARITY_INVERTED>;
+ status = "okay";
+ };
+
+ lcd_display: disp0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-0 = <&pinctrl_ipu1_lcdif &pinctrl_dhcom_g>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ 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>;
+ };
+ };
+ };
+
+ gpio-keys {
+ #size-cells = <0>;
+ compatible = "gpio-keys";
+
+ button-0 {
+ gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; /* GPIO A */
+ label = "TA1-GPIO-A";
+ linux,code = <KEY_A>;
+ pinctrl-0 = <&pinctrl_dhcom_a>;
+ pinctrl-names = "default";
+ wakeup-source;
+ };
+
+ button-1 {
+ gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; /* GPIO B */
+ label = "TA2-GPIO-B";
+ linux,code = <KEY_B>;
+ pinctrl-0 = <&pinctrl_dhcom_b>;
+ pinctrl-names = "default";
+ wakeup-source;
+ };
+
+ button-2 {
+ gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; /* GPIO C */
+ label = "TA3-GPIO-C";
+ linux,code = <KEY_C>;
+ pinctrl-0 = <&pinctrl_dhcom_c>;
+ pinctrl-names = "default";
+ wakeup-source;
+ };
+
+ button-3 {
+ gpios = <&gpio6 3 GPIO_ACTIVE_LOW>; /* GPIO D */
+ label = "TA4-GPIO-D";
+ linux,code = <KEY_D>;
+ pinctrl-0 = <&pinctrl_dhcom_d>;
+ pinctrl-names = "default";
+ wakeup-source;
+ };
+ };
+
+ led {
+ compatible = "gpio-leds";
+
+ /*
+ * Disable led-5, because GPIO E is
+ * already used as touch interrupt.
+ */
+ led-5 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; /* GPIO E */
+ pinctrl-0 = <&pinctrl_dhcom_e>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ led-6 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio4 20 GPIO_ACTIVE_HIGH>; /* GPIO F */
+ pinctrl-0 = <&pinctrl_dhcom_f>;
+ pinctrl-names = "default";
+ };
+
+ led-7 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* GPIO H */
+ pinctrl-0 = <&pinctrl_dhcom_h>;
+ pinctrl-names = "default";
+ };
+
+ led-8 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; /* GPIO I */
+ pinctrl-0 = <&pinctrl_dhcom_i>;
+ pinctrl-names = "default";
+ };
+ };
+
+ panel {
+ backlight = <&display_bl>;
+ compatible = "edt,etm0700g0edh6";
+
+ port {
+ lcd_panel_in: endpoint {
+ remote-endpoint = <&lcd_display_out>;
+ };
+ };
+ };
+
+ sound {
+ audio-codec = <&sgtl5000>;
+ audio-routing =
+ "MIC_IN", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "LINE_IN", "Line In Jack",
+ "Headphone Jack", "HP_OUT";
+ compatible = "fsl,imx-audio-sgtl5000";
+ model = "imx-sgtl5000";
+ mux-ext-port = <3>;
+ mux-int-port = <1>;
+ ssi-controller = <&ssi1>;
+ };
+};
+
+&audmux {
+ pinctrl-0 = <&pinctrl_audmux_ext>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&can1 {
+ status = "okay";
+};
+
+&can2 {
+ status = "disabled";
+};
+
+/* 1G ethernet */
+/delete-node/ &ethphy0;
+&fec {
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy7>;
+ pinctrl-0 = <&pinctrl_enet_1G>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy7: ethernet-phy@7 { /* KSZ 9021 */
+ compatible = "ethernet-phy-ieee802.3-c22";
+ interrupt-parent = <&gpio1>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&pinctrl_ethphy7>;
+ pinctrl-names = "default";
+ reg = <7>;
+ reset-assert-us = <1000>;
+ reset-deassert-us = <1000>;
+ reset-gpios = <&gpio3 29 GPIO_ACTIVE_LOW>;
+ rxc-skew-ps = <3000>;
+ rxd0-skew-ps = <0>;
+ rxd1-skew-ps = <0>;
+ rxd2-skew-ps = <0>;
+ rxd3-skew-ps = <0>;
+ rxdv-skew-ps = <0>;
+ txc-skew-ps = <3000>;
+ txd0-skew-ps = <0>;
+ txd1-skew-ps = <0>;
+ txd2-skew-ps = <0>;
+ txd3-skew-ps = <0>;
+ txen-skew-ps = <0>;
+ };
+ };
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&i2c2 {
+ sgtl5000: codec@a {
+ #sound-dai-cells = <0>;
+ clocks = <&clk_ext_audio_codec>;
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ VDDA-supply = <&reg_3p3v>;
+ VDDIO-supply = <&sw2_reg>;
+ };
+
+ touchscreen@38 {
+ compatible = "edt,edt-ft5406";
+ interrupt-parent = <&gpio4>;
+ interrupts = <5 IRQ_TYPE_EDGE_FALLING>; /* GPIO E */
+ pinctrl-0 = <&pinctrl_dhcom_e>;
+ pinctrl-names = "default";
+ reg = <0x38>;
+ };
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&lcd_display_in>;
+};
+
+&pcie {
+ pinctrl-0 = <&pinctrl_pcie &pinctrl_dhcom_j>;
+ reset-gpio = <&gpio6 14 GPIO_ACTIVE_LOW>; /* GPIO J */
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&ssi1 {
+ status = "okay";
+};
+
+&usdhc2 { /* SD card */
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-0 = <
+ /*
+ * The following DHCOM GPIOs are used on this board.
+ * Therefore, they have been removed from the list below.
+ * A: key TA1
+ * B: key TA2
+ * C: key TA3
+ * D: key TA4
+ * E: touchscreen
+ * F: led6
+ * G: backlight enable
+ * H: led7
+ * I: led8
+ * J: PCIe reset
+ */
+ &pinctrl_hog_base
+ &pinctrl_dhcom_k &pinctrl_dhcom_l
+ &pinctrl_dhcom_m &pinctrl_dhcom_n &pinctrl_dhcom_o
+ &pinctrl_dhcom_p &pinctrl_dhcom_q &pinctrl_dhcom_r
+ &pinctrl_dhcom_s &pinctrl_dhcom_t &pinctrl_dhcom_u
+ &pinctrl_dhcom_v &pinctrl_dhcom_w &pinctrl_dhcom_int
+ >;
+ pinctrl-names = "default";
+
+ pinctrl_audmux_ext: audmux-ext-grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ >;
+ };
+
+ pinctrl_enet_1G: enet-1G-grp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
+ 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_RGMII_RXC__RGMII_RXC 0x1b0b0
+ 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_RGMII_TXC__RGMII_TXC 0x100b0
+ >;
+ };
+
+ pinctrl_ethphy7: ethphy7-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0xb1 /* WOL */
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0xb0 /* Reset */
+ MX6QDL_PAD_GPIO_0__GPIO1_IO00 0xb1 /* Int */
+ >;
+ };
+
+ pinctrl_ipu1_lcdif: ipu1-lcdif-grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x38
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x38
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x38
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x38
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x38
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x38
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x38
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x38
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x38
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x38
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x38
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x38
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x38
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x38
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x38
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x38
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x38
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x38
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x38
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x38
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x38
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x38
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x38
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x38
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x38
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x38
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x38
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x38
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6qdl-dhcom-picoitx.dtsi b/arch/arm/boot/dts/imx6qdl-dhcom-picoitx.dtsi
new file mode 100644
index 000000000000..4cd4cb9543c8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-dhcom-picoitx.dtsi
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 DH electronics GmbH
+ */
+
+#include <dt-bindings/leds/common.h>
+
+/ {
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ led {
+ compatible = "gpio-leds";
+
+ led-0 {
+ color = <LED_COLOR_ID_YELLOW>;
+ default-state = "off";
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; /* GPIO I */
+ pinctrl-0 = <&pinctrl_dhcom_i>;
+ pinctrl-names = "default";
+ };
+ };
+};
+
+&gpio1 {
+ gpio-line-names =
+ "", "", "DHCOM-A", "", "DHCOM-B", "PicoITX-In2", "", "",
+ "", "", "", "", "", "", "", "",
+ "DHCOM-R", "DHCOM-S", "DHCOM-Q", "DHCOM-T", "DHCOM-U", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ "", "", "", "", "", "PicoITX-In1", "DHCOM-INT", "DHCOM-H",
+ "DHCOM-I", "PicoITX-HW2", "", "", "", "", "", "",
+ "", "", "", "", "PicoITX-Out1", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio6 {
+ gpio-line-names =
+ "", "", "", "PicoITX-Out2", "", "", "SOM-HW1", "",
+ "", "", "", "", "", "", "PicoITX-HW0", "PicoITX-HW1",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&iomuxc {
+ pinctrl-0 = <
+ /*
+ * The following DHCOM GPIOs are used on this board.
+ * Therefore, they have been removed from the list below.
+ * I: yellow led
+ */
+ &pinctrl_hog_base
+ &pinctrl_dhcom_a &pinctrl_dhcom_b &pinctrl_dhcom_c
+ &pinctrl_dhcom_d &pinctrl_dhcom_e &pinctrl_dhcom_f
+ &pinctrl_dhcom_g &pinctrl_dhcom_h
+ &pinctrl_dhcom_j &pinctrl_dhcom_k &pinctrl_dhcom_l
+ &pinctrl_dhcom_m &pinctrl_dhcom_n &pinctrl_dhcom_o
+ &pinctrl_dhcom_p &pinctrl_dhcom_q &pinctrl_dhcom_r
+ &pinctrl_dhcom_s &pinctrl_dhcom_t &pinctrl_dhcom_u
+ &pinctrl_dhcom_v &pinctrl_dhcom_w &pinctrl_dhcom_int
+ >;
+ pinctrl-names = "default";
+};
diff --git a/arch/arm/boot/dts/imx6q-dhcom-som.dtsi b/arch/arm/boot/dts/imx6qdl-dhcom-som.dtsi
index 4bf51f3ce003..5d10c40313cb 100644
--- a/arch/arm/boot/dts/imx6q-dhcom-som.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-dhcom-som.dtsi
@@ -1,10 +1,9 @@
-// SPDX-License-Identifier: (GPL-2.0+)
+// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2015 DH electronics GmbH
+ * Copyright (C) 2015-2021 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>
@@ -28,14 +27,22 @@
serial4 = &uart3;
};
- memory@10000000 {
+ memory@10000000 { /* Appropriate memory size will be filled by U-Boot */
device_type = "memory";
- reg = <0x10000000 0x40000000>;
+ reg = <0x10000000 0x20000000>;
+ };
+
+ reg_3p3v: regulator-3P3V {
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "3P3V";
};
reg_eth_vio: regulator-eth-vio {
compatible = "regulator-fixed";
- gpio = <&gpio1 7 GPIO_ACTIVE_LOW>;
+ gpio = <&gpio1 7 0>;
pinctrl-0 = <&pinctrl_enet_vio>;
pinctrl-names = "default";
regulator-always-on;
@@ -46,225 +53,521 @@
vin-supply = <&sw2_reg>;
};
- reg_usb_otg_vbus: regulator-usb-otg-vbus {
+ /* OE pin of the latch is low active */
+ reg_latch_oe_on: regulator-latch-oe-on {
compatible = "regulator-fixed";
- regulator-name = "usb_otg_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 22 0>;
+ regulator-always-on;
+ regulator-name = "latch_oe_on";
};
reg_usb_h1_vbus: regulator-usb-h1-vbus {
compatible = "regulator-fixed";
- regulator-name = "usb_h1_vbus";
+ enable-active-high;
+ gpio = <&gpio3 31 0>;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
- gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
- enable-active-high;
+ regulator-name = "usb_h1_vbus";
};
- reg_3p3v: regulator-3P3V {
+ reg_usb_otg_vbus: regulator-usb-otg-vbus {
compatible = "regulator-fixed";
- regulator-name = "3P3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "usb_otg_vbus";
};
};
&can1 {
- pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan1>;
+ pinctrl-names = "default";
+ status = "okay";
};
+/*
+ * Special SoM hardware required which uses the pins from micro SD card. The
+ * pins SD3_DAT0 and SD3_DAT1 are muxed as can2 Tx and Rx. The signals for can2
+ * Tx and Rx are routed to the DHCOM UART1 rts/cts pins. So to enable can2 on
+ * the board device tree file, the micro SD card must be disabled and the uart1
+ * rts/cts must be disabled or output on other DHCOM pins.
+ */
&can2 {
- pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan2>;
+ pinctrl-names = "default";
+ status = "disabled";
};
&ecspi1 {
cs-gpios = <&gpio2 30 GPIO_ACTIVE_LOW>, <&gpio4 11 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi1>;
+ pinctrl-names = "default";
status = "okay";
- flash@0 { /* S25FL116K */
+ flash@0 { /* S25FL116K */
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
- spi-max-frequency = <50000000>;
- reg = <0>;
m25p,fast-read;
+ reg = <0>;
+ spi-max-frequency = <50000000>;
};
};
&ecspi2 {
cs-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi2>;
- status = "okay";
+ pinctrl-names = "default";
+ status = "disabled";
};
&fec {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_enet_100M>;
phy-mode = "rmii";
phy-handle = <&ethphy0>;
+ pinctrl-0 = <&pinctrl_enet_100M>;
+ pinctrl-names = "default";
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
- ethphy0: ethernet-phy@0 { /* SMSC LAN8710Ai */
+ ethphy0: ethernet-phy@0 { /* SMSC LAN8710Ai */
+ compatible = "ethernet-phy-ieee802.3-c22";
+ interrupt-parent = <&gpio4>;
+ interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&pinctrl_ethphy0>;
+ pinctrl-names = "default";
reg = <0>;
- max-speed = <100>;
- reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
reset-assert-us = <1000>;
reset-deassert-us = <1000>;
+ reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
smsc,disable-energy-detect; /* Make plugin detection reliable */
};
};
};
+&gpio1 {
+ gpio-line-names =
+ "", "", "DHCOM-A", "", "DHCOM-B", "DHCOM-C", "", "",
+ "", "", "", "", "", "", "", "",
+ "DHCOM-R", "DHCOM-S", "DHCOM-Q", "DHCOM-T", "DHCOM-U", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio2 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "SOM-HW2", "", "", "SOM-HW0", "", "SOM-MEM1", "SOM-MEM0", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio3 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "DHCOM-G", "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ "", "", "", "", "", "DHCOM-E", "DHCOM-INT", "DHCOM-H",
+ "DHCOM-I", "DHCOM-L", "", "", "", "", "", "",
+ "", "", "", "", "DHCOM-F", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio5 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "DHCOM-V", "DHCOM-W", "", "DHCOM-O", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio6 {
+ gpio-line-names =
+ "", "", "", "DHCOM-D", "", "", "SOM-HW1", "",
+ "", "", "", "", "", "", "DHCOM-J", "DHCOM-K",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio7 {
+ gpio-line-names =
+ "DHCOM-M", "DHCOM-N", "", "", "", "", "", "",
+ "", "", "", "", "", "DHCOM-P", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
&i2c1 {
+ /*
+ * Info: According to erratum ERR007805 clock frequency limit is 375000.
+ * The erratum for i.MX6S/DL is here [1] and for i.MX6Q/D is here [2].
+ * [1] https://www.nxp.com/docs/en/errata/IMX6SDLCE.pdf
+ * [2] https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf
+ */
clock-frequency = <100000>;
- pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ pinctrl-names = "default", "gpio";
scl-gpios = <&gpio3 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio3 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
&i2c2 {
+ /* Info: Clock frequency limit is 375000 (for details see i2c1) */
clock-frequency = <100000>;
- pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ pinctrl-names = "default", "gpio";
scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
&i2c3 {
+ /* Info: Clock frequency limit is 375000 (for details see i2c1) */
clock-frequency = <100000>;
- pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ pinctrl-names = "default", "gpio";
scl-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
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>;
+ pinctrl-0 = <&pinctrl_pmic>;
+ pinctrl-names = "default";
+ reg = <0x3c>;
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;
+ regulator-boot-on;
+ regulator-max-microvolt = <1527272>;
+ regulator-min-microvolt = <787500>;
+ regulator-ramp-delay = <7000>;
+ regulator-suspend-mem-microvolt = <1040000>;
};
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;
+ regulator-boot-on;
+ regulator-max-microvolt = <3657142>;
+ regulator-min-microvolt = <1885714>;
+ regulator-ramp-delay = <7000>;
};
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;
+ regulator-boot-on;
+ regulator-max-microvolt = <1527272>;
+ regulator-min-microvolt = <787500>;
+ regulator-ramp-delay = <7000>;
+ regulator-suspend-mem-microvolt = <980000>;
};
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;
+ regulator-boot-on;
+ regulator-max-microvolt = <1659291>;
+ regulator-min-microvolt = <855571>;
+ regulator-ramp-delay = <7000>;
};
ldo1_reg: ldo1 {
- regulator-min-microvolt = <3240306>;
- regulator-max-microvolt = <3240306>;
lltc,fb-voltage-divider = <102000 29400>;
- regulator-boot-on;
regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <3240306>;
+ regulator-min-microvolt = <3240306>;
};
ldo2_reg: ldo2 {
- regulator-min-microvolt = <2484708>;
- regulator-max-microvolt = <2484708>;
lltc,fb-voltage-divider = <100000 41200>;
- regulator-boot-on;
regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <2484708>;
+ regulator-min-microvolt = <2484708>;
};
};
};
- touchscreen@49 { /* TSC2004 */
+ touchscreen@49 { /* TSC2004 */
compatible = "ti,tsc2004";
+ interrupts-extended = <&gpio4 14 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-0 = <&pinctrl_tsc2004>;
+ pinctrl-names = "default";
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>;
+ reg = <0x50>;
};
rtc_i2c: rtc@56 {
compatible = "microcrystal,rv3029";
+ interrupt-parent = <&gpio7>;
+ interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-0 = <&pinctrl_rtc>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_rtc_hw300>;
reg = <0x56>;
- interrupt-parent = <&gpio7>;
- interrupts = <12 2>;
};
};
+&pcie {
+ pinctrl-0 = <&pinctrl_pcie>;
+ pinctrl-names = "default";
+};
+
+&pwm1 {
+ pinctrl-0 = <&pinctrl_pwm1>;
+ pinctrl-names = "default";
+};
+
+&reg_arm {
+ vin-supply = <&sw3_reg>;
+};
+
+&reg_pu {
+ vin-supply = <&sw1_reg>;
+};
+
+&reg_soc {
+ vin-supply = <&sw1_reg>;
+};
+
+&reg_vdd1p1 {
+ vin-supply = <&sw2_reg>;
+};
+
+&reg_vdd2p5 {
+ vin-supply = <&sw2_reg>;
+};
+
+&uart1 { /* DHCOM UART1 */
+ dcd-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+ dsr-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+ dtr-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
+ rng-gpios = <&gpio2 31 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&pinctrl_uart1>;
+ pinctrl-names = "default";
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&uart4 { /* DHCOM UART3 */
+ pinctrl-0 = <&pinctrl_uart4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart5 { /* DHCOM UART2 */
+ pinctrl-0 = <&pinctrl_uart5>;
+ pinctrl-names = "default";
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usbh1 {
+ dr_mode = "host";
+ pinctrl-0 = <&pinctrl_usbh1>;
+ pinctrl-names = "default";
+ vbus-supply = <&reg_usb_h1_vbus>;
+ status = "okay";
+};
+
+&usbotg {
+ disable-over-current;
+ dr_mode = "otg";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ pinctrl-names = "default";
+ vbus-supply = <&reg_usb_otg_vbus>;
+ status = "okay";
+};
+
+&usdhc2 { /* External SD card via DHCOM */
+ cd-gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-names = "default";
+ status = "disabled";
+};
+
+&usdhc3 { /* Micro SD card on module */
+ cd-gpios = <&gpio7 8 GPIO_ACTIVE_LOW>;
+ fsl,wp-controller;
+ keep-power-in-suspend;
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usdhc4 { /* eMMC on module */
+ bus-width = <8>;
+ keep-power-in-suspend;
+ no-1-8-v;
+ non-removable;
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&weim {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ fsl,weim-cs-gpr = <&gpr>;
+ pinctrl-0 = <&pinctrl_weim &pinctrl_weim_cs0 &pinctrl_weim_cs1>;
+ pinctrl-names = "default";
+ /* It is necessary to setup 2x 64MB otherwise setting gpr fails */
+ ranges = <0 0 0x08000000 0x04000000>, /* CS0 */
+ <1 0 0x0c000000 0x04000000>; /* CS1 */
+ status = "disabled";
+};
+
&iomuxc {
+ pinctrl-0 = <
+ &pinctrl_hog_base
+ &pinctrl_dhcom_a &pinctrl_dhcom_b &pinctrl_dhcom_c
+ &pinctrl_dhcom_d &pinctrl_dhcom_e &pinctrl_dhcom_f
+ &pinctrl_dhcom_g &pinctrl_dhcom_h &pinctrl_dhcom_i
+ &pinctrl_dhcom_j &pinctrl_dhcom_k &pinctrl_dhcom_l
+ &pinctrl_dhcom_m &pinctrl_dhcom_n &pinctrl_dhcom_o
+ &pinctrl_dhcom_p &pinctrl_dhcom_q &pinctrl_dhcom_r
+ &pinctrl_dhcom_s &pinctrl_dhcom_t &pinctrl_dhcom_u
+ &pinctrl_dhcom_v &pinctrl_dhcom_w &pinctrl_dhcom_int
+ >;
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
+ /* GPIOs for memory coding */
MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x120b0
MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x120b0
+ /* GPIOs for hardware coding */
+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x120b0
+ MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x120b0
+ MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x120b0
>;
};
+ /* DHCOM GPIOs */
+ pinctrl_dhcom_a: dhcom-a-grp {
+ fsl,pins = <MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x400120b0>;
+ };
+
+ pinctrl_dhcom_b: dhcom-b-grp {
+ fsl,pins = <MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x400120b0>;
+ };
+
+ pinctrl_dhcom_c: dhcom-c-grp {
+ fsl,pins = <MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x400120b0>;
+ };
+
+ pinctrl_dhcom_d: dhcom-d-grp {
+ fsl,pins = <MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03 0x400120b0>;
+ };
+
+ pinctrl_dhcom_e: dhcom-e-grp {
+ fsl,pins = <MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x400120b0>;
+ };
+
+ pinctrl_dhcom_f: dhcom-f-grp {
+ fsl,pins = <MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x400120b0>;
+ };
+
+ pinctrl_dhcom_g: dhcom-g-grp {
+ fsl,pins = <MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x400120b0>;
+ };
+
+ pinctrl_dhcom_h: dhcom-h-grp {
+ fsl,pins = <MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x400120b0>;
+ };
+
+ pinctrl_dhcom_i: dhcom-i-grp {
+ fsl,pins = <MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x400120b0>;
+ };
+
+ pinctrl_dhcom_j: dhcom-j-grp {
+ fsl,pins = <MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x400120b0>;
+ };
+
+ pinctrl_dhcom_k: dhcom-k-grp {
+ fsl,pins = <MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x400120b0>;
+ };
+
+ pinctrl_dhcom_l: dhcom-l-grp {
+ fsl,pins = <MX6QDL_PAD_KEY_ROW1__GPIO4_IO09 0x400120b0>;
+ };
+
+ pinctrl_dhcom_m: dhcom-m-grp {
+ fsl,pins = <MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x400120b0>;
+ };
+
+ pinctrl_dhcom_n: dhcom-n-grp {
+ fsl,pins = <MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x400120b0>;
+ };
+
+ pinctrl_dhcom_o: dhcom-o-grp {
+ fsl,pins = <MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x400120b0>;
+ };
+
+ pinctrl_dhcom_p: dhcom-p-grp {
+ fsl,pins = <MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x400120b0>;
+ };
+
+ pinctrl_dhcom_q: dhcom-q-grp {
+ fsl,pins = <MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x400120b0>;
+ };
+
+ pinctrl_dhcom_r: dhcom-r-grp {
+ fsl,pins = <MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x400120b0>;
+ };
+
+ pinctrl_dhcom_s: dhcom-s-grp {
+ fsl,pins = <MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x400120b0>;
+ };
+
+ pinctrl_dhcom_t: dhcom-t-grp {
+ fsl,pins = <MX6QDL_PAD_SD1_DAT2__GPIO1_IO19 0x400120b0>;
+ };
+
+ pinctrl_dhcom_u: dhcom-u-grp {
+ fsl,pins = <MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x400120b0>;
+ };
+
+ pinctrl_dhcom_v: dhcom-v-grp {
+ fsl,pins = <MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 0x400120b0>;
+ };
+
+ pinctrl_dhcom_w: dhcom-w-grp {
+ fsl,pins = <MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19 0x400120b0>;
+ };
+
+ pinctrl_dhcom_int: dhcom-int-grp {
+ fsl,pins = <MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x400120b0>;
+ };
+
pinctrl_ecspi1: ecspi1-grp {
fsl,pins = <
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
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
>;
@@ -272,18 +575,18 @@
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_DAT9__ECSPI2_MOSI 0x100b1
+ MX6QDL_PAD_CSI0_DAT10__ECSPI2_MISO 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_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 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
@@ -291,8 +594,6 @@
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
>;
};
@@ -302,10 +603,17 @@
>;
};
+ pinctrl_ethphy0: ethphy0-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_WAIT__GPIO5_IO00 0xb0 /* Reset */
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0xb1 /* Int */
+ >;
+ };
+
pinctrl_flexcan1: flexcan1-grp {
fsl,pins = <
- MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
>;
};
@@ -358,34 +666,46 @@
>;
};
- pinctrl_pmic_hw300: pmic-hw300-grp {
+ pinctrl_pcie: pcie-grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b0b1 /* Wake */
+ >;
+ };
+
+ pinctrl_pmic: pmic-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0
+ >;
+ };
+
+ pinctrl_pwm1: pwm1-grp {
fsl,pins = <
- MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1B0B0
+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
>;
};
- pinctrl_rtc_hw300: rtc-hw300-grp {
+ pinctrl_rtc: rtc-grp {
fsl,pins = <
- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x120B0
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x120b0
>;
};
- pinctrl_tsc2004_hw300: tsc2004-hw300-grp {
+ pinctrl_tsc2004: tsc2004-grp {
fsl,pins = <
- MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x120B0
+ 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_D20__UART1_RTS_B 0x1b0b1
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
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
>;
};
@@ -407,7 +727,7 @@
pinctrl_usbh1: usbh1-grp {
fsl,pins = <
- MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x120B0
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x120b0
>;
};
@@ -419,32 +739,32 @@
pinctrl_usdhc2: usdhc2-grp {
fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x120b0
MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
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_CMD__SD3_CMD 0x17059
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
+ 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_CMD__SD4_CMD 0x17059
MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
@@ -455,92 +775,41 @@
MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
>;
};
-};
-
-&reg_arm {
- vin-supply = <&sw3_reg>;
-};
-
-&reg_soc {
- vin-supply = <&sw1_reg>;
-};
-
-&reg_pu {
- vin-supply = <&sw1_reg>;
-};
-
-&reg_vdd1p1 {
- vin-supply = <&sw2_reg>;
-};
-
-&reg_vdd2p5 {
- vin-supply = <&sw2_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";
-};
+ pinctrl_weim: weim-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_DA0__EIM_AD00 0xb0a6
+ MX6QDL_PAD_EIM_DA1__EIM_AD01 0xb0a6
+ MX6QDL_PAD_EIM_DA2__EIM_AD02 0xb0a6
+ MX6QDL_PAD_EIM_DA3__EIM_AD03 0xb0a6
+ MX6QDL_PAD_EIM_DA4__EIM_AD04 0xb0a6
+ MX6QDL_PAD_EIM_DA5__EIM_AD05 0xb0a6
+ MX6QDL_PAD_EIM_DA6__EIM_AD06 0xb0a6
+ MX6QDL_PAD_EIM_DA7__EIM_AD07 0xb0a6
+ MX6QDL_PAD_EIM_DA8__EIM_AD08 0xb0a6
+ MX6QDL_PAD_EIM_DA9__EIM_AD09 0xb0a6
+ MX6QDL_PAD_EIM_DA10__EIM_AD10 0xb0a6
+ MX6QDL_PAD_EIM_DA11__EIM_AD11 0xb0a6
+ MX6QDL_PAD_EIM_DA12__EIM_AD12 0xb0a6
+ MX6QDL_PAD_EIM_DA13__EIM_AD13 0xb0a6
+ MX6QDL_PAD_EIM_DA14__EIM_AD14 0xb0a6
+ MX6QDL_PAD_EIM_DA15__EIM_AD15 0xb0a6
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x130b0
+ MX6QDL_PAD_EIM_LBA__EIM_LBA_B 0xb060 /* LE */
+ MX6QDL_PAD_EIM_OE__EIM_OE_B 0xb0a6
+ MX6QDL_PAD_EIM_RW__EIM_RW 0xb0a6 /* WE */
+ >;
+ };
-&usdhc3 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio7 8 GPIO_ACTIVE_LOW>;
- fsl,wp-controller;
- keep-power-in-suspend;
- status = "disabled";
-};
+ pinctrl_weim_cs0: weim-cs0-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_CS0__EIM_CS0_B 0xb0b1
+ >;
+ };
-&usdhc4 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc4>;
- non-removable;
- bus-width = <8>;
- no-1-8-v;
- keep-power-in-suspend;
- status = "okay";
+ pinctrl_weim_cs1: weim-cs1-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_CS1__EIM_CS1_B 0xb0b1
+ >;
+ };
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
index 3c04b5a4f3cb..069c27fab432 100644
--- a/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
@@ -626,6 +626,7 @@
fsl,pins = <
MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0 /* OTG_PWR_EN */
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x17059
>;
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
index 8e587e17e75d..b1df2beb2832 100644
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -728,6 +728,7 @@
fsl,pins = <
MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0 /* OTG_PWR_EN */
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x17059
>;
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
index 29ba24c273e9..cda48bf2f168 100644
--- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
@@ -812,6 +812,7 @@
fsl,pins = <
MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0 /* PWR_EN */
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x17059
>;
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw553x.dtsi b/arch/arm/boot/dts/imx6qdl-gw553x.dtsi
index c15b9cc63bf8..4662408b225a 100644
--- a/arch/arm/boot/dts/imx6qdl-gw553x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw553x.dtsi
@@ -687,6 +687,7 @@
fsl,pins = <
MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0 /* OTG_PWR_EN */
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x17059
>;
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw5904.dtsi b/arch/arm/boot/dts/imx6qdl-gw5904.dtsi
index 304f3fb88fab..612b6e068e28 100644
--- a/arch/arm/boot/dts/imx6qdl-gw5904.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw5904.dtsi
@@ -467,6 +467,11 @@
};
};
+ crypto@60 {
+ compatible = "atmel,atecc508a";
+ reg = <0x60>;
+ };
+
imu@6a {
compatible = "st,lsm9ds1-imu";
reg = <0x6a>;
diff --git a/arch/arm/boot/dts/imx6qdl-skov-cpu-revc.dtsi b/arch/arm/boot/dts/imx6qdl-skov-cpu-revc.dtsi
new file mode 100644
index 000000000000..69ae430a53bd
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-skov-cpu-revc.dtsi
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Copyright (C) 2020 Pengutronix, Ulrich Oelmann <kernel@pengutronix.de>
+
+&ecspi4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi4>;
+ cs-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ touchscreen@0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_touch>;
+ compatible = "ti,tsc2046";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ interrupts-extended = <&gpio3 19 IRQ_TYPE_LEVEL_LOW>;
+ vcc-supply = <&reg_3v3>;
+ pendown-gpio = <&gpio3 19 GPIO_ACTIVE_LOW>;
+ ti,x-plate-ohms = /bits/ 16 <850>;
+ ti,y-plate-ohms = /bits/ 16 <295>;
+ ti,pressure-min = /bits/ 16 <2>;
+ ti,pressure-max = /bits/ 16 <1500>;
+ ti,vref-mv = /bits/ 16 <3300>;
+ ti,settle-delay-usec = /bits/ 16 <15>;
+ ti,vref-delay-usecs = /bits/ 16 <0>;
+ ti,penirq-recheck-delay-usecs = /bits/ 16 <100>;
+ ti,debounce-max = /bits/ 16 <100>;
+ ti,debounce-tol = /bits/ 16 <(~0)>;
+ ti,debounce-rep = /bits/ 16 <4>;
+ touchscreen-swapped-x-y;
+ touchscreen-inverted-y;
+ wakeup-source;
+ };
+};
+
+&iomuxc {
+ pinctrl_ecspi4: ecspi4grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D28__ECSPI4_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D22__ECSPI4_MISO 0x000b1
+ MX6QDL_PAD_EIM_D21__ECSPI4_SCLK 0x000b1
+ /* *no* external pull up */
+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x40000058
+ >;
+ };
+
+ pinctrl_touch: touchgrp {
+ fsl,pins = <
+ /* external pull up */
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x10040
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi b/arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi
new file mode 100644
index 000000000000..77a91a97e6cf
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi
@@ -0,0 +1,477 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Copyright (C) 2020 Pengutronix, Ulrich Oelmann <kernel@pengutronix.de>
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ aliases {
+ can0 = &can1;
+ can1 = &can2;
+ mdio-gpio0 = &mdio;
+ nand = &gpmi;
+ rtc0 = &i2c_rtc;
+ rtc1 = &snvs;
+ usb0 = &usbh1;
+ usb1 = &usbotg;
+ };
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0>, /* 24V */
+ <&adc 1>; /* temperature */
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ label = "D1";
+ gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_STATUS;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+
+ led-1 {
+ label = "D2";
+ gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ led-2 {
+ label = "D3";
+ gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+ };
+
+ mdio: mdio {
+ compatible = "microchip,mdio-smi0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mdio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>,
+ <&gpio1 22 GPIO_ACTIVE_HIGH>;
+
+ switch@0 {
+ compatible = "microchip,ksz8873";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_switch>;
+ interrupt-parent = <&gpio3>;
+ interrupt = <30 IRQ_TYPE_LEVEL_HIGH>;
+ reset-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
+ reg = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
+ reg = <0>;
+ phy-mode = "internal";
+ label = "lan1";
+ };
+
+ ports@1 {
+ reg = <1>;
+ phy-mode = "internal";
+ label = "lan2";
+ };
+
+ ports@2 {
+ reg = <2>;
+ label = "cpu";
+ ethernet = <&fec>;
+ phy-mode = "rmii";
+
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+ };
+ };
+ };
+
+ };
+
+ clk50m_phy: phy-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ };
+
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ vin-supply = <&reg_5v0>;
+ regulator-name = "3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_24v0: regulator-24v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "24v0";
+ regulator-min-microvolt = <24000000>;
+ regulator-max-microvolt = <24000000>;
+ };
+
+ reg_can1_stby: regulator-can1-stby {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1_stby>;
+ regulator-name = "can1-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 31 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_can2_stby: regulator-can2-stby {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can2_stby>;
+ regulator-name = "can2-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 11 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_vcc_mmc: regulator-vcc-mmc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_vcc_mmc>;
+ vin-supply = <&reg_3v3>;
+ regulator-name = "mmc_vcc_supply";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio7 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <100>;
+ };
+
+ reg_vcc_mmc_io: regulator-vcc-mmc-io {
+ compatible = "regulator-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_vcc_mmc_io>;
+ vin-supply = <&reg_5v0>;
+ regulator-name = "mmc_io_supply";
+ regulator-type = "voltage";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio7 13 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ states = <1800000 0x1>, <3300000 0x0>;
+ startup-delay-us = <100>;
+ };
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1>;
+ xceiver-supply = <&reg_can1_stby>;
+ status = "okay";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can2>;
+ xceiver-supply = <&reg_can2_stby>;
+ status = "okay";
+};
+
+&ecspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ cs-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <54000000>;
+ reg = <0>;
+ };
+};
+
+&ecspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ cs-gpios = <&gpio2 26 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ adc: adc@0 {
+ compatible = "microchip,mcp3002";
+ reg = <0>;
+ vref-supply = <&reg_3v3>;
+ spi-max-frequency = <1000000>;
+ #io-channel-cells = <1>;
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ clocks = <&clks IMX6QDL_CLK_ENET>,
+ <&clks IMX6QDL_CLK_ENET>,
+ <&clk50m_phy>;
+ clock-names = "ipg", "ahb", "ptp";
+ phy-mode = "rmii";
+ phy-supply = <&reg_3v3>;
+ status = "okay";
+
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ i2c_rtc: rtc@51 {
+ compatible = "nxp,pcf85063";
+ reg = <0x51>;
+ quartz-load-femtofarads = <12500>;
+ };
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+ #pwm-cells = <2>;
+ status = "okay";
+};
+
+&pwm3 {
+ /* used for LCD contrast control */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&reg_5v0>;
+ disable-over-current;
+ status = "okay";
+};
+
+/* no usbh2 */
+&usbphynop1 {
+ status = "disabled";
+};
+
+/* no usbh3 */
+&usbphynop2 {
+ status = "disabled";
+};
+
+&usbotg {
+ vbus-supply = <&reg_5v0>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ wp-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+ cap-power-off-card;
+ full-pwr-cycle;
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-ddr50;
+ mmc-ddr-1_8v;
+ vmmc-supply = <&reg_vcc_mmc>;
+ vqmmc-supply = <&reg_vcc_mmc_io>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x3008
+ MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b000
+ >;
+ };
+
+ pinctrl_can1_stby: can1stbygrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x13008
+ >;
+ };
+
+ pinctrl_can2: can2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x3008
+ MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b000
+ >;
+ };
+
+ pinctrl_can2_stby: can2stbygrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__GPIO4_IO11 0x13008
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0xb1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0xb1
+ /* *no* external pull up */
+ MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x58
+ >;
+ };
+
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1
+ MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0xb1
+ MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0xb1
+ /* external pull up */
+ MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x58
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ /* RMII 50 MHz */
+ MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x100f5
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x100f5
+ MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x100c0
+ MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x100c0
+ MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x100f5
+ MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x100f5
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x1b0b0
+ MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x58
+ /* GPIO for "link active" */
+ MX6QDL_PAD_ENET_RX_ER__GPIO1_IO24 0x3038
+ >;
+ };
+
+ pinctrl_gpmi_nand: gpminandgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ /* external 10 k pull up */
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x40010878
+ /* external 10 k pull up */
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x40010878
+ >;
+ };
+
+ pinctrl_mdio: mdiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__GPIO1_IO22 0x100b1
+ MX6QDL_PAD_ENET_MDC__GPIO1_IO31 0xb1
+ >;
+ };
+
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__PWM2_OUT 0x58
+ >;
+ };
+
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x58
+ >;
+ };
+
+ pinctrl_switch: switchgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D30__GPIO3_IO30 0xb0
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ /* SoC internal pull up required */
+ 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
+ /* SoC internal pull up required */
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b040
+ /* SoC internal pull up required */
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b040
+ >;
+ };
+
+ pinctrl_vcc_mmc: vccmmcgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x58
+ >;
+ };
+
+ pinctrl_vcc_mmc_io: vccmmciogrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x58
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6qdl-solidsense.dtsi b/arch/arm/boot/dts/imx6qdl-solidsense.dtsi
new file mode 100644
index 000000000000..234827e554d0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-solidsense.dtsi
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2021 Russell King <rmk@armlinux.org.uk>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <dt-bindings/leds/common.h>
+
+/ {
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_solidsense_leds>;
+
+ /* Red/Green LED1 - next to WiFi SMA */
+ led-11 {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_INDICATOR;
+ function-enumerator = <0>;
+ gpios = <&gpio2 26 GPIO_ACTIVE_LOW>;
+ };
+
+ led-12 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_INDICATOR;
+ function-enumerator = <0>;
+ gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
+ };
+
+ /* Red/Green LED2 - next to GPS SMA */
+ led-21 {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_INDICATOR;
+ function-enumerator = <1>;
+ gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
+ };
+
+ led-22 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_INDICATOR;
+ function-enumerator = <1>;
+ gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&audio {
+ status = "disabled";
+};
+
+&ecspi2 {
+ status = "disabled";
+};
+
+&i2c3 {
+ status = "disabled";
+};
+
+&iomuxc {
+ pinctrl-0 = <&pinctrl_hog>, <&pinctrl_solidsense_hog>;
+
+ solidsense {
+ pinctrl_solidsense_hog: solidsense-hog {
+ fsl,pins = <
+ /* Nordic RESET_N */
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x400130b1
+ /* Nordic Chip 1 SWDIO - GPIO 125 */
+ MX6QDL_PAD_DISP0_DAT8__GPIO4_IO29 0x400130b1
+ /* Nordic Chip 1 SWDCLK - GPIO 59 */
+ /* already claimed in the HB2 hogs */
+ /* MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x400130b1 */
+ /* Nordic Chip 2 SWDIO - GPIO 81 */
+ MX6QDL_PAD_EIM_D17__GPIO3_IO17 0x400130b1
+ /* Nordic Chip 2 SWCLK - GPIO 82 */
+ MX6QDL_PAD_EIM_D18__GPIO3_IO18 0x400130b1
+ >;
+ };
+
+ pinctrl_solidsense_leds: solidsense-leds {
+ fsl,pins = <
+ /* Red LED 1 - GPIO 58 */
+ MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x400130b1
+ /* Green LED 1 - GPIO 55 */
+ MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x400130b1
+ /* Red LED 2 - GPIO 57 */
+ MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x400130b1
+ /* Green LED 2 - GPIO 56 */
+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x400130b1
+ >;
+ };
+
+ pinctrl_solidsense_uart2: solidsense-uart2 {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_solidsense_uart3: solidsense-uart3 {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ >;
+ };
+ };
+};
+
+&pwm1 {
+ status = "disabled";
+};
+
+&sgtl5000 {
+ status = "disabled";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_solidsense_uart2>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_solidsense_uart3>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 82e01ce026ea..89c342f3a7c2 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -334,7 +334,7 @@
clocks = <&clks IMX6QDL_CLK_ECSPI1>,
<&clks IMX6QDL_CLK_ECSPI1>;
clock-names = "ipg", "per";
- dmas = <&sdma 3 8 1>, <&sdma 4 8 2>;
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -348,7 +348,7 @@
clocks = <&clks IMX6QDL_CLK_ECSPI2>,
<&clks IMX6QDL_CLK_ECSPI2>;
clock-names = "ipg", "per";
- dmas = <&sdma 5 8 1>, <&sdma 6 8 2>;
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -362,7 +362,7 @@
clocks = <&clks IMX6QDL_CLK_ECSPI3>,
<&clks IMX6QDL_CLK_ECSPI3>;
clock-names = "ipg", "per";
- dmas = <&sdma 7 8 1>, <&sdma 8 8 2>;
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -376,7 +376,7 @@
clocks = <&clks IMX6QDL_CLK_ECSPI4>,
<&clks IMX6QDL_CLK_ECSPI4>;
clock-names = "ipg", "per";
- dmas = <&sdma 9 8 1>, <&sdma 10 8 2>;
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6qp-prtwd3.dts b/arch/arm/boot/dts/imx6qp-prtwd3.dts
index c42723989bc0..b92e0f2748a5 100644
--- a/arch/arm/boot/dts/imx6qp-prtwd3.dts
+++ b/arch/arm/boot/dts/imx6qp-prtwd3.dts
@@ -208,6 +208,8 @@
&fec {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet>;
+ assigned-clocks = <&clks IMX6QDL_CLK_ENET_REF>;
+ assigned-clock-rates = <125000000>;
status = "okay";
phy-mode = "rgmii";
diff --git a/arch/arm/boot/dts/imx6s-dhcom-drc02.dts b/arch/arm/boot/dts/imx6s-dhcom-drc02.dts
new file mode 100644
index 000000000000..4077b607c29e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6s-dhcom-drc02.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 DH electronics GmbH
+ *
+ * DHCOM iMX6 variant:
+ * DHCM-iMX6S-C0800-R102-F0409-E-CAN2-RTC-I-01D2
+ * DHCOM PCB number: 493-400 or newer
+ * DRC02 PCB number: 568-100 or newer
+ */
+/dts-v1/;
+
+/*
+ * The kernel only distinguishes between i.MX6 Quad and DualLite,
+ * but the Solo is actually a DualLite with only one CPU. So use
+ * DualLite for the Solo and disable one CPU node.
+ */
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-dhcom-som.dtsi"
+#include "imx6qdl-dhcom-drc02.dtsi"
+
+/ {
+ model = "DH electronics i.MX6S DHCOM on DRC02";
+ compatible = "dh,imx6s-dhcom-drc02", "dh,imx6s-dhcom-som",
+ "fsl,imx6dl";
+
+ cpus {
+ /delete-node/ cpu@1;
+ };
+};
diff --git a/arch/arm/boot/dts/imx7d-remarkable2.dts b/arch/arm/boot/dts/imx7d-remarkable2.dts
index 8cbae656395c..89cbf13097a4 100644
--- a/arch/arm/boot/dts/imx7d-remarkable2.dts
+++ b/arch/arm/boot/dts/imx7d-remarkable2.dts
@@ -21,6 +21,27 @@
device_type = "memory";
reg = <0x80000000 0x40000000>;
};
+
+ reg_brcm: regulator-brcm {
+ compatible = "regulator-fixed";
+ regulator-name = "brcm_reg";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_brcm_reg>;
+ gpio = <&gpio6 13 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <150>;
+ };
+
+ wifi_pwrseq: wifi_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+ clocks = <&clks IMX7D_CLKO2_ROOT_DIV>;
+ clock-names = "ext_clock";
+ };
};
&clks {
@@ -56,6 +77,27 @@
status = "okay";
};
+&usdhc2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ vmmc-supply = <&reg_brcm>;
+ bus-width = <4>;
+ non-removable;
+ keep-power-in-suspend;
+ cap-power-off-card;
+ status = "okay";
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
+
&usdhc3 {
pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
pinctrl-0 = <&pinctrl_usdhc3>;
@@ -76,6 +118,13 @@
};
&iomuxc {
+ pinctrl_brcm_reg: brcmreggrp {
+ fsl,pins = <
+ /* WIFI_PWR_EN */
+ MX7D_PAD_SAI1_TX_BCLK__GPIO6_IO13 0x14
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79
@@ -90,6 +139,39 @@
>;
};
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX7D_PAD_SD2_CMD__SD2_CMD 0x59
+ MX7D_PAD_SD2_CLK__SD2_CLK 0x19
+ MX7D_PAD_SD2_DATA0__SD2_DATA0 0x59
+ MX7D_PAD_SD2_DATA1__SD2_DATA1 0x59
+ MX7D_PAD_SD2_DATA2__SD2_DATA2 0x59
+ MX7D_PAD_SD2_DATA3__SD2_DATA3 0x59
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp_100mhz {
+ fsl,pins = <
+ MX7D_PAD_SD2_CMD__SD2_CMD 0x5a
+ MX7D_PAD_SD2_CLK__SD2_CLK 0x1a
+ MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5a
+ MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5a
+ MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5a
+ MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5a
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp_200mhz {
+ fsl,pins = <
+ MX7D_PAD_SD2_CMD__SD2_CMD 0x5b
+ MX7D_PAD_SD2_CLK__SD2_CLK 0x1b
+ MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5b
+ MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5b
+ MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5b
+ MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5b
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX7D_PAD_SD3_CMD__SD3_CMD 0x59
@@ -143,4 +225,13 @@
MX7D_PAD_ENET1_COL__WDOG1_WDOG_ANY 0x74
>;
};
+
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ /* WiFi Reg On */
+ MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x00000014
+ /* WiFi Sleep 32k */
+ MX7D_PAD_SD1_WP__CCM_CLKO2 0x00000014
+ >;
+ };
};
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index a22d41e0cf31..1843fc053870 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -707,6 +707,34 @@
status = "disabled";
};
+ ftm1: pwm@30640000 {
+ compatible = "fsl,vf610-ftm-pwm";
+ reg = <0x30640000 0x10000>;
+ #pwm-cells = <3>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ftm_sys", "ftm_ext",
+ "ftm_fix", "ftm_cnt_clk_en";
+ clocks = <&clks IMX7D_FLEXTIMER1_ROOT_CLK>,
+ <&clks IMX7D_FLEXTIMER1_ROOT_CLK>,
+ <&clks IMX7D_FLEXTIMER1_ROOT_CLK>,
+ <&clks IMX7D_FLEXTIMER1_ROOT_CLK>;
+ status = "disabled";
+ };
+
+ ftm2: pwm@30650000 {
+ compatible = "fsl,vf610-ftm-pwm";
+ reg = <0x30650000 0x10000>;
+ #pwm-cells = <3>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "ftm_sys", "ftm_ext",
+ "ftm_fix", "ftm_cnt_clk_en";
+ clocks = <&clks IMX7D_FLEXTIMER2_ROOT_CLK>,
+ <&clks IMX7D_FLEXTIMER2_ROOT_CLK>,
+ <&clks IMX7D_FLEXTIMER2_ROOT_CLK>,
+ <&clks IMX7D_FLEXTIMER2_ROOT_CLK>;
+ status = "disabled";
+ };
+
pwm1: pwm@30660000 {
compatible = "fsl,imx7d-pwm", "fsl,imx27-pwm";
reg = <0x30660000 0x10000>;
diff --git a/arch/arm/boot/dts/integratorap-im-pd1.dts b/arch/arm/boot/dts/integratorap-im-pd1.dts
index 1412a1a968fc..0614f82b808e 100644
--- a/arch/arm/boot/dts/integratorap-im-pd1.dts
+++ b/arch/arm/boot/dts/integratorap-im-pd1.dts
@@ -29,7 +29,7 @@
compatible = "arm,im-pd1-syscon", "syscon";
reg = <0x00000000 0x1000>;
- vco1: clock@00 {
+ vco1: vco1-clock {
compatible = "arm,impd1-vco1";
#clock-cells = <0>;
lock-offset = <0x08>;
@@ -38,7 +38,7 @@
clock-output-names = "IM-PD1-VCO1";
};
- vco2: clock@04 {
+ vco2: vco2-clock {
compatible = "arm,impd1-vco2";
#clock-cells = <0>;
lock-offset = <0x08>;
diff --git a/arch/arm/boot/dts/intel-ixp42x-adi-coyote.dts b/arch/arm/boot/dts/intel-ixp42x-adi-coyote.dts
new file mode 100644
index 000000000000..44c017b78008
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-adi-coyote.dts
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for ADI Engineering Coyote platform.
+ * Derived from boardfiles written by MontaVista software.
+ * Ethernet set-up from OpenWrt.
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "ADI Engineering Coyote reference design";
+ compatible = "adieng,coyote", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ /* CHECKME: 16 MB SDRAM minimum, maybe the Coyote actually has more */
+ device_type = "memory";
+ reg = <0x00000000 0x01000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 root=/dev/sda1 rw rootwait";
+ stdout-path = "uart1:115200n8";
+ };
+
+ aliases {
+ /* These are switched around */
+ serial0 = &uart1;
+ serial1 = &uart0;
+ };
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /*
+ * 32 MB of Flash in 128 0x20000 sized blocks
+ * mapped in at CS0 and CS1
+ */
+ reg = <0 0x00000000 0x2000000>;
+
+ /* Configure expansion bus to allow writes */
+ intel,ixp4xx-eb-write-enable = <1>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* CHECKME: guess this is Redboot FIS */
+ fis-index-block = <0x1ff>;
+ };
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Taken from Coyote PCI boardfile.
+ * We have slots (IDSEL) 1 and 2 with one assigned IRQ
+ * each handling all IRQs.
+ */
+ interrupt-map =
+ /* IDSEL 1 */
+ <0x0800 0 0 1 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 6 */
+ <0x0800 0 0 2 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 1 is irq 6 */
+ <0x0800 0 0 3 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 1 is irq 6 */
+ <0x0800 0 0 4 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 1 is irq 6 */
+ /* IDSEL 2 */
+ <0x1000 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 11 */
+ <0x1000 0 0 2 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 2 is irq 11 */
+ <0x1000 0 0 3 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 2 is irq 11 */
+ <0x1000 0 0 4 &gpio0 11 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 2 is irq 11 */
+ };
+
+ /* EthB */
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy5>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy4: ethernet-phy@4 {
+ reg = <4>;
+ };
+
+ phy5: ethernet-phy@5 {
+ reg = <5>;
+ };
+ };
+ };
+
+ /* EthC */
+ ethernet@c800a000 {
+ status = "ok";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy4>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-arcom-vulcan.dts b/arch/arm/boot/dts/intel-ixp42x-arcom-vulcan.dts
new file mode 100644
index 000000000000..7200126cb3b5
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-arcom-vulcan.dts
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the Arcom/Eurotech Vulcan board.
+ * This board is a single board computer in the PC/104 form factor based on
+ * IXP425, and was released around 2005. It previously had the name "Mercury".
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Arcom/Eurotech Vulcan";
+ compatible = "arcom,vulcan", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x4000000>;
+ };
+
+ chosen {
+ /* CHECKME: using a harddrive at /dev/sda1 as rootfs by default */
+ bootargs = "console=ttyS0,115200n8 root=/dev/sda1 rw rootfstype=ext4 rootwait";
+ stdout-path = "uart0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ onewire {
+ compatible = "w1-gpio";
+ gpios = <&gpio0 14 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ };
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /*
+ * 32 MB of Flash in 0x20000 byte blocks
+ * mapped in at CS0 and CS1.
+ *
+ * The documentation mentions the existence
+ * of a 16MB version, which we conveniently
+ * ignore. Shout if you own one!
+ */
+ reg = <0 0x00000000 0x2000000>;
+
+ /* Expansion bus settings */
+ intel,ixp4xx-eb-t3 = <3>;
+ intel,ixp4xx-eb-byte-access-on-halfword = <1>;
+ intel,ixp4xx-eb-write-enable = <1>;
+
+ partitions {
+ compatible = "redboot-fis";
+ fis-index-block = <0x1ff>;
+ };
+ };
+ sram@2,0 {
+ /* 256 KB SDRAM memory at CS2 */
+ compatible = "shared-dma-pool";
+ device_type = "memory";
+ reg = <2 0x00000000 0x40000>;
+ no-map;
+ /* Expansion bus settings */
+ intel,ixp4xx-eb-t3 = <1>;
+ intel,ixp4xx-eb-t4 = <2>;
+ intel,ixp4xx-eb-ahb-split-transfers = <1>;
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+ };
+ serial@3,0 {
+ /*
+ * 8250-compatible Exar XR16L2551 2 x UART
+ *
+ * CHECKME: if special tweaks are needed, then fix the
+ * operating system to handle it.
+ */
+ compatible = "exar,xr16l2551", "ns8250";
+ reg = <3 0x00000000 0x10>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ clock-frequency = <1843200>;
+ /* Expansion bus settings */
+ intel,ixp4xx-eb-t3 = <3>;
+ intel,ixp4xx-eb-cycle-type = <1>; /* Motorola cycles */
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+ };
+ gpio1: gpio@4,0 {
+ /*
+ * MMIO GPIO in one byte
+ */
+ compatible = "arcom,vulcan-gpio";
+ reg = <4 0x00000000 0x1>;
+ /* Expansion bus settings */
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+ };
+ watchdog@5,0 {
+ compatible = "maxim,max6369";
+ reg = <5 0x00000000 0x1>;
+ /* Expansion bus settings */
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Taken from Vulcan PCI boardfile.
+ *
+ * We have 2 slots (IDSEL) 1 and 2 with one dedicated interrupt
+ * per slot. This interrupt is shared (OR:ed) by all four pins.
+ */
+ interrupt-map =
+ /* IDSEL 1 */
+ <0x0800 0 0 1 &gpio0 2 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 2 */
+ <0x0800 0 0 2 &gpio0 2 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 1 is irq 2 */
+ <0x0800 0 0 3 &gpio0 2 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 1 is irq 2 */
+ <0x0800 0 0 4 &gpio0 2 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 1 is irq 2 */
+ /* IDSEL 2 */
+ <0x1000 0 0 1 &gpio0 3 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 3 */
+ <0x1000 0 0 2 &gpio0 3 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 2 is irq 3 */
+ <0x1000 0 0 3 &gpio0 3 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 2 is irq 3 */
+ <0x1000 0 0 4 &gpio0 3 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 2 is irq 3 */
+ };
+
+ /* EthB */
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ /* EthC */
+ ethernet@c800a000 {
+ status = "ok";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-dlink-dsm-g600.dts b/arch/arm/boot/dts/intel-ixp42x-dlink-dsm-g600.dts
new file mode 100644
index 000000000000..8b32e9f22d81
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-dlink-dsm-g600.dts
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for D-Link DSM-G600 revision A based on IXP420
+ * NOTE: revision B of this device uses PowerPC and is NOT supported by
+ * this device tree.
+ *
+ * Inspired by the boardfile by Rod Whitby, Tower Technologies, Alessandro Zummo
+ * and Michael Westerhof.
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "D-Link DSM-G600 rev A";
+ compatible = "dlink,dsm-g600-a", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ /* 64 MB SDRAM */
+ device_type = "memory";
+ reg = <0x00000000 0x4000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 root=/dev/sda1 rw rootwait";
+ stdout-path = "uart0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ led-power {
+ label = "dsmg600:green:power";
+ gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+ led-wlan {
+ label = "dsmg600:green:wlan";
+ /* CHECKME: flagged as active low in the old board file */
+ gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ /* We don't have WLAN trigger in the kernel (yet) */
+ linux,default-trigger = "netdev";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ button-reset {
+ wakeup-source;
+ linux,code = <KEY_ESC>;
+ label = "reset";
+ gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio_keys_polled {
+ compatible = "gpio-keys-polled";
+
+ /*
+ * According to the board file this key cannot handle interrupts and
+ * need to be polled. Investigate if this is really the case or if
+ * this can be moved adjacent to the ordinary gpio-keys above.
+ */
+ button-power {
+ wakeup-source;
+ linux,code = <KEY_POWER>;
+ label = "power";
+ gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ i2c {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio0 5 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio0 4 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ gpio-poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
+ timeout-ms = <5000>;
+ };
+
+ soc {
+ bus@c4000000 {
+ /* The first 16MB region at CS0 on the expansion bus */
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /*
+ * 16 MB of Flash in 128 0x20000 sized blocks
+ * mapped in at CS0.
+ */
+ reg = <0 0x00000000 0x1000000>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /*
+ * A boot log says the directory is at 0xfe0000
+ * 0x7f * 0x20000 = 0xfe0000
+ */
+ fis-index-block = <0x7f>;
+ };
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Taken from DSM-G600 PCI boardfile (dsmg600-pci.c)
+ * We have slots (IDSEL) 1, 2, 3, 4 and pins 1, 2 and 3.
+ * Only slot 3 have three IRQs.
+ */
+ interrupt-map =
+ /* IDSEL 1 */
+ <0x0800 0 0 1 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT E on slot 1 is irq 7 */
+ /* IDSEL 2 */
+ <0x1000 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 11 */
+ /* IDSEL 3 */
+ <0x1800 0 0 1 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 10 */
+ <0x1800 0 0 2 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 3 is irq 9 */
+ <0x1800 0 0 3 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 3 is irq 8 */
+ /* IDSEL 4 */
+ <0x2000 0 0 3 &gpio0 6 IRQ_TYPE_LEVEL_LOW>; /* INT F on slot 4 is irq 6 */
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-freecom-fsg-3.dts b/arch/arm/boot/dts/intel-ixp42x-freecom-fsg-3.dts
new file mode 100644
index 000000000000..77e78c6dc2cd
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-freecom-fsg-3.dts
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the Freecom FSG-3 router.
+ * This machine is based on IXP425.
+ * This device tree is inspired by the board file by Rod Whitby.
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Freecom FSG-3";
+ compatible = "freecom,fsg-3", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ /* 64 MB memory */
+ device_type = "memory";
+ reg = <0x00000000 0x4000000>;
+ };
+
+ chosen {
+ /* Boot from the first partition on the hard drive */
+ bootargs = "console=ttyS0,115200n8 root=/dev/sda1 rw rootfstype=ext4 rootwait";
+ stdout-path = "uart0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ button-sync {
+ wakeup-source;
+ /* Closest approximation of what the key should do */
+ linux,code = <KEY_CONNECT>;
+ label = "sync";
+ gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+ };
+ button-reset {
+ wakeup-source;
+ linux,code = <KEY_ESC>;
+ label = "reset";
+ gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
+ };
+ button-usb {
+ wakeup-source;
+ /* Unplug USB, closest approximation of what the key should do */
+ linux,code = <KEY_EJECTCD>;
+ label = "usb";
+ gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ i2c {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio0 12 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio0 13 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hwmon@28 {
+ /*
+ * Temperature sensor and fan control chip.
+ *
+ * TODO: create a proper device tree binding for
+ * the sensor and temperature zone and create a
+ * zone with fan control.
+ */
+ compatible = "winbond,w83781d";
+ reg = <0x28>;
+ };
+ rtc@6f {
+ compatible = "isil,isl1208";
+ reg = <0x6f>;
+ };
+ };
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
+ /* 4 MB of Flash mapped in at CS0 */
+ reg = <0 0x00000000 0x400000>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0x3e0000 */
+ fis-index-block = <0x1f>;
+ };
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Written based on the FSG-3 PCI boardfile.
+ * We have slots 12, 13 & 14 (IDSEL) with one IRQ each.
+ */
+ interrupt-map =
+ /* IDSEL 12 */
+ <0x6000 0 0 1 &gpio0 5 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 12 is irq 5 */
+ <0x6000 0 0 2 &gpio0 5 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 12 is irq 5 */
+ <0x6000 0 0 3 &gpio0 5 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 12 is irq 5 */
+ <0x6000 0 0 4 &gpio0 5 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 12 is irq 5 */
+ /* IDSEL 13 */
+ <0x6800 0 0 1 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 13 is irq 7 */
+ <0x6800 0 0 2 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 13 is irq 7 */
+ <0x6800 0 0 3 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 13 is irq 7 */
+ <0x6800 0 0 4 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 13 is irq 7 */
+ /* IDSEL 14 */
+ <0x7000 0 0 1 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 14 is irq 6 */
+ <0x7000 0 0 2 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 14 is irq 6 */
+ <0x7000 0 0 3 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 14 is irq 6 */
+ <0x7000 0 0 4 &gpio0 6 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 14 is irq 6 */
+ };
+
+ /* EthB */
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy5>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy4: ethernet-phy@4 {
+ reg = <4>;
+ };
+
+ phy5: ethernet-phy@5 {
+ reg = <5>;
+ };
+ };
+ };
+
+ /* EthC */
+ ethernet@c800a000 {
+ status = "ok";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy4>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-gateworks-gw2348.dts b/arch/arm/boot/dts/intel-ixp42x-gateworks-gw2348.dts
new file mode 100644
index 000000000000..a20277ff0420
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-gateworks-gw2348.dts
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the Gateworks Avila GW2348 board.
+ * This machine is based on IXP425.
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Gateworks Avila GW2348";
+ compatible = "gateworks,gw2348", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x4000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8";
+ stdout-path = "uart0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ led-user {
+ label = "gw2348:green:user";
+ gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ i2c {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio0 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hwmon@28 {
+ compatible = "adi,ad7418";
+ reg = <0x28>;
+ };
+ rtc: ds1672@68 {
+ compatible = "dallas,ds1672";
+ reg = <0x68>;
+ };
+ eeprom@51 {
+ compatible = "atmel,24c08";
+ reg = <0x51>;
+ pagesize = <16>;
+ size = <1024>;
+ read-only;
+ };
+ };
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
+ /* 16 MB of Flash mapped in at CS0 */
+ reg = <0 0x00000000 0x1000000>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0x0fe0000 */
+ fis-index-block = <0x7f>;
+ };
+ };
+ ide@1,0 {
+ compatible = "intel,ixp4xx-compact-flash";
+ /*
+ * Set up expansion bus config to a really slow timing.
+ * The CF driver will dynamically reconfigure these timings
+ * depending on selected PIO mode (0-4).
+ */
+ intel,ixp4xx-eb-t1 = <3>; // 3 cycles extra address phase
+ intel,ixp4xx-eb-t2 = <3>; // 3 cycles extra setup phase
+ intel,ixp4xx-eb-t3 = <15>; // 15 cycles extra strobe phase
+ intel,ixp4xx-eb-t4 = <3>; // 3 cycles extra hold phase
+ intel,ixp4xx-eb-t5 = <15>; // 15 cycles extra recovery phase
+ intel,ixp4xx-eb-cycle-type = <0>; // Intel cycle type
+ intel,ixp4xx-eb-byte-access-on-halfword = <1>;
+ intel,ixp4xx-eb-mux-address-and-data = <0>;
+ intel,ixp4xx-eb-ahb-split-transfers = <0>;
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+ /* First register set is CMD second is CTL (notice it uses CS2) */
+ reg = <1 0x00000000 0x1000000>, <2 0x00000000 0x1000000>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <12 IRQ_TYPE_EDGE_RISING>;
+ };
+ /*
+ * FIXME: Latch LEDs or extra UARTs at CS4
+ */
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Taken from Avila PCI boardfile.
+ *
+ * We have up to 4 slots (IDSEL) with 4 swizzled IRQs.
+ */
+ interrupt-map =
+ /* IDSEL 1 */
+ <0x0800 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 11 */
+ <0x0800 0 0 2 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 1 is irq 10 */
+ <0x0800 0 0 3 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 1 is irq 9 */
+ <0x0800 0 0 4 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 1 is irq 8 */
+ /* IDSEL 2 */
+ <0x1000 0 0 1 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 10 */
+ <0x1000 0 0 2 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 2 is irq 9 */
+ <0x1000 0 0 3 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 2 is irq 8 */
+ <0x1000 0 0 4 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 2 is irq 11 */
+ /* IDSEL 3 */
+ <0x1800 0 0 1 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 3 is irq 9 */
+ <0x1800 0 0 2 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 8 */
+ <0x1800 0 0 3 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 3 is irq 11 */
+ <0x1800 0 0 4 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 3 is irq 10 */
+ /* IDSEL 4 */
+ <0x2000 0 0 1 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 4 is irq 8 */
+ <0x2000 0 0 2 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 4 is irq 11 */
+ <0x2000 0 0 3 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 4 is irq 10 */
+ <0x2000 0 0 4 &gpio0 9 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 4 is irq 9 */
+ };
+
+ /* EthB */
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ /* EthC */
+ ethernet@c800a000 {
+ status = "ok";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-iomega-nas100d.dts b/arch/arm/boot/dts/intel-ixp42x-iomega-nas100d.dts
new file mode 100644
index 000000000000..8c18d802c849
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-iomega-nas100d.dts
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for Iomega NAS 100D
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Iomega NAS 100D";
+ compatible = "iom,nas-100d", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ /* 64 MB SDRAM */
+ device_type = "memory";
+ reg = <0x00000000 0x4000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 root=/dev/sda1 rw rootwait";
+ stdout-path = "uart0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ led-wlan {
+ label = "nas100d:red:wlan";
+ gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ /* We don't have WLAN trigger in the kernel (yet) */
+ linux,default-trigger = "netdev";
+ };
+ led-disk {
+ label = "nas100d:red:disk";
+ gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ linux,default-trigger = "disk-activity";
+ };
+ led-power {
+ label = "nas100d:red:power";
+ gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ button-power {
+ wakeup-source;
+ linux,code = <KEY_POWER>;
+ label = "power";
+ gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+ };
+ button-reset {
+ wakeup-source;
+ linux,code = <KEY_ESC>;
+ label = "reset";
+ gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ i2c {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio0 5 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ gpio-poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+ timeout-ms = <5000>;
+ };
+
+ soc {
+ bus@c4000000 {
+ /* The first 16MB region at CS0 on the expansion bus */
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /*
+ * 8 MB of Flash in 0x20000 byte blocks
+ * mapped in at CS0.
+ */
+ reg = <0 0x00000000 0x800000>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0x7e0000 */
+ fis-index-block = <0x3f>;
+ };
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Taken from NAS 100D PCI boardfile (nas100d-pci.c)
+ * We have slots (IDSEL) 1, 2 and 3 and pins 1, 2 and 3.
+ */
+ interrupt-map =
+ /* IDSEL 1 */
+ <0x0800 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 11 */
+ /* IDSEL 2 */
+ <0x1000 0 0 1 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 10 */
+ /* IDSEL 3 */
+ <0x1800 0 0 1 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 3 is irq 9 */
+ <0x1800 0 0 2 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 8 */
+ <0x1800 0 0 3 &gpio0 7 IRQ_TYPE_LEVEL_LOW>; /* INT C on slot 3 is irq 7 */
+ };
+
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-ixdp425.dts b/arch/arm/boot/dts/intel-ixp42x-ixdp425.dts
new file mode 100644
index 000000000000..beaadda4685f
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-ixdp425.dts
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the Intel IXDP425 also known as IXCDP1100 Control Plane
+ * processor reference design.
+ *
+ * This platform has the codename "Richfield".
+ *
+ * This machine is based on a 533 MHz IXP425.
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include "intel-ixp4xx-reference-design.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Intel IXDP425/IXCDP1100 Richfield Reference Design";
+ compatible = "intel,ixdp425", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
+ /* 16 MB of Flash mapped in at CS0 */
+ reg = <0 0x00000000 0x1000000>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0x0fe0000 */
+ fis-index-block = <0x7f>;
+ };
+ };
+ };
+
+ /* EthB */
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ /* EthC */
+ ethernet@c800a000 {
+ status = "ok";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-ixdpg425.dts b/arch/arm/boot/dts/intel-ixp42x-ixdpg425.dts
new file mode 100644
index 000000000000..002a8705abc9
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-ixdpg425.dts
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the Intel IXDPG425 reference design.
+ * Derived from boardfiles written by MontaVista software.
+ * Ethernet set-up from OpenWrt.
+ *
+ * The device has 4 x FXS RJ11 ports for analog phones for
+ * internet telephony. (Not supported yet.)
+ *
+ * The device has 9 status LEDs we do not support yet.
+ *
+ * This device is very similar to ADI engingeering Coyote.
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Intel IXDPG425 reference design";
+ compatible = "intel,ixdpg425", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ /* 32 MB SDRAM */
+ device_type = "memory";
+ reg = <0x00000000 0x02000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 root=/dev/sda1 rw rootwait";
+ stdout-path = "uart0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /*
+ * CHECKME: the product brief says 16MB in a flash
+ * socket.
+ */
+ reg = <0 0x00000000 0x1000000>;
+
+ /* Configure expansion bus to allow writes */
+ intel,ixp4xx-eb-write-enable = <1>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* CHECKME: guess this is Redboot FIS */
+ fis-index-block = <0x7f>;
+ };
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Taken from IXDPG425 PCI boardfile.
+ * We have slots (IDSEL) 12, 13 and 14 with one assigned IRQ
+ * for 12 & 13 and one for 14.
+ */
+ interrupt-map =
+ /* IDSEL 12 */
+ <0x6000 0 0 1 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 12 is irq 7 */
+ <0x6000 0 0 2 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 12 is irq 7 */
+ <0x6000 0 0 3 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 12 is irq 7 */
+ <0x6000 0 0 4 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 12 is irq 7 */
+ /* IDSEL 13 */
+ <0x6800 0 0 1 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 13 is irq 7 */
+ <0x6800 0 0 2 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 13 is irq 7 */
+ <0x6800 0 0 3 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 13 is irq 7 */
+ <0x6800 0 0 4 &gpio0 7 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 13 is irq 7 */
+ /* IDSEL 14 */
+ <0x7000 0 0 1 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 14 is irq 6 */
+ <0x7000 0 0 2 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 14 is irq 6 */
+ <0x7000 0 0 3 &gpio0 6 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 14 is irq 6 */
+ <0x7000 0 0 4 &gpio0 6 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 14 is irq 6 */
+ };
+
+ /*
+ * CHECKME: this ethernet setup seems dubious. Photos of the board shows some kind
+ * of Realtek DSA switch on the board.
+ */
+
+ /* EthB */
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy5>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy4: ethernet-phy@4 {
+ reg = <4>;
+ };
+
+ phy5: ethernet-phy@5 {
+ reg = <5>;
+ };
+ };
+ };
+
+ /* EthC */
+ ethernet@c800a000 {
+ status = "ok";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy4>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts b/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts
index 5b8dcc19deee..e3a32b08d167 100644
--- a/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts
+++ b/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts
@@ -96,16 +96,16 @@
};
soc {
- bus@50000000 {
+ bus@c4000000 {
/* The first 16MB region at CS0 on the expansion bus */
- flash@0 {
+ flash@0,0 {
compatible = "intel,ixp4xx-flash", "cfi-flash";
bank-width = <2>;
/*
* 8 MB of Flash in 0x20000 byte blocks
* mapped in at CS0.
*/
- reg = <0x00000000 0x800000>;
+ reg = <0 0x00000000 0x800000>;
partitions {
compatible = "redboot-fis";
@@ -124,20 +124,20 @@
*/
interrupt-map =
/* IDSEL 1 */
- <0x0800 0 0 1 &gpio0 11 3>, /* INT A on slot 1 is irq 11 */
- <0x0800 0 0 2 &gpio0 10 3>, /* INT B on slot 1 is irq 10 */
- <0x0800 0 0 3 &gpio0 9 3>, /* INT C on slot 1 is irq 9 */
- <0x0800 0 0 4 &gpio0 8 3>, /* INT D on slot 1 is irq 8 */
+ <0x0800 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 11 */
+ <0x0800 0 0 2 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 1 is irq 10 */
+ <0x0800 0 0 3 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 1 is irq 9 */
+ <0x0800 0 0 4 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 1 is irq 8 */
/* IDSEL 2 */
- <0x1000 0 0 1 &gpio0 10 3>, /* INT A on slot 2 is irq 10 */
- <0x1000 0 0 2 &gpio0 9 3>, /* INT B on slot 2 is irq 9 */
- <0x1000 0 0 3 &gpio0 11 3>, /* INT C on slot 2 is irq 11 */
- <0x1000 0 0 4 &gpio0 8 3>, /* INT D on slot 2 is irq 8 */
+ <0x1000 0 0 1 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 10 */
+ <0x1000 0 0 2 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 2 is irq 9 */
+ <0x1000 0 0 3 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 2 is irq 11 */
+ <0x1000 0 0 4 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 2 is irq 8 */
/* IDSEL 3 */
- <0x1800 0 0 1 &gpio0 9 3>, /* INT A on slot 3 is irq 9 */
- <0x1800 0 0 2 &gpio0 11 3>, /* INT B on slot 3 is irq 11 */
- <0x1800 0 0 3 &gpio0 10 3>, /* INT C on slot 3 is irq 10 */
- <0x1800 0 0 4 &gpio0 8 3>; /* INT D on slot 3 is irq 8 */
+ <0x1800 0 0 1 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 3 is irq 9 */
+ <0x1800 0 0 2 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 11 */
+ <0x1800 0 0 3 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 3 is irq 10 */
+ <0x1800 0 0 4 &gpio0 8 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 3 is irq 8 */
};
ethernet@c8009000 {
diff --git a/arch/arm/boot/dts/intel-ixp42x-linksys-wrv54g.dts b/arch/arm/boot/dts/intel-ixp42x-linksys-wrv54g.dts
new file mode 100644
index 000000000000..6b28dda747fd
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-linksys-wrv54g.dts
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the Linksys WRV54G router
+ * Also known as Gemtek GTWX5715
+ * Based on a board file by George T. Joseph and other patches.
+ * This machine is based on IXP425.
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Linksys WRV54G / Gemtek GTWX5715";
+ compatible = "linksys,wrv54g", "gemtek,gtwx5715", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ /* 32 MB memory */
+ device_type = "memory";
+ reg = <0x00000000 0x2000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8";
+ stdout-path = "uart1:115200n8";
+ };
+
+ aliases {
+ /* UART2 is the primary console */
+ serial0 = &uart1;
+ serial1 = &uart0;
+ };
+
+ /* There is an unpopulated LED slot (3) connected to GPIO 8 */
+ leds {
+ compatible = "gpio-leds";
+ led-power {
+ label = "wrv54g:yellow:power";
+ gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+ led-wireless {
+ label = "wrv54g:yellow:wireless";
+ gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ };
+ led-internet {
+ label = "wrv54g:yellow:internet";
+ gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ };
+ led-dmz {
+ label = "wrv54g:green:dmz";
+ gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ };
+ };
+
+ /* This set-up comes from an OpenWrt patch */
+ spi {
+ compatible = "spi-gpio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sck-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+ miso-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+ mosi-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+ num-chipselects = <1>;
+
+ switch@0 {
+ compatible = "micrel,ks8995";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
+ /* 8 MB of Flash mapped in at CS0 */
+ reg = <0 0x00000000 0x00800000>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ /*
+ * Partition info from a boot log
+ * CHECKME: not using redboot? FIS index 0x3f @7e00000?
+ */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@0 {
+ label = "boot";
+ reg = <0x0 0x140000>;
+ read-only;
+ };
+ partition@140000 {
+ label = "linux";
+ reg = <0x140000 0x100000>;
+ read-only;
+ };
+ partition@240000 {
+ label = "root";
+ reg = <0x240000 0x480000>;
+ read-write;
+ };
+ };
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * We have up to 2 slots (IDSEL) with 2 swizzled IRQs.
+ * Derived from the GTWX5715 PCI boardfile.
+ */
+ interrupt-map =
+ /* IDSEL 0 */
+ <0x0000 0 0 1 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 0 is irq 10 */
+ <0x0000 0 0 2 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 0 is irq 11 */
+ /* IDSEL 1 */
+ <0x0800 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 11 */
+ <0x0800 0 0 2 &gpio0 10 IRQ_TYPE_LEVEL_LOW>; /* INT B on slot 1 is irq 10 */
+ };
+
+ /*
+ * EthB - connected to the KS8995 switch ports 1-4
+ * FIXME: the boardfile defines .phy_mask = 0x1e for this port to enable output to
+ * all four switch ports, also using an out of tree multiphy patch.
+ * Do we need a new binding and property for this?
+ */
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy4>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Should be ports 1-4 on the KS8995 switch */
+ phy4: ethernet-phy@4 {
+ reg = <4>;
+ };
+
+ /* Should be port 5 on the KS8995 switch */
+ phy5: ethernet-phy@5 {
+ reg = <5>;
+ };
+ };
+ };
+
+ /* EthC - connected to KS8995 switch port 5 */
+ ethernet@c800a000 {
+ status = "ok";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy5>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-netgear-wg302v2.dts b/arch/arm/boot/dts/intel-ixp42x-netgear-wg302v2.dts
new file mode 100644
index 000000000000..04a0f7138967
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-netgear-wg302v2.dts
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for Netgear WG302v2 based on IXP422BB
+ * Derived from boardfiles written by Imre Kaloz
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Netgear WG302 v2";
+ compatible = "netgear,wg302v2", "intel,ixp42x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@0 {
+ /* 16 MB SDRAM according to OpenWrt database */
+ device_type = "memory";
+ reg = <0x00000000 0x01000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 root=/dev/sda1 rw rootwait";
+ stdout-path = "uart1:115200n8";
+ };
+
+ aliases {
+ /* These are switched around */
+ serial0 = &uart1;
+ serial1 = &uart0;
+ };
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /*
+ * 32 MB of Flash in 128 0x20000 sized blocks
+ * mapped in at CS0 and CS1
+ */
+ reg = <0 0x00000000 0x2000000>;
+
+ /* Configure expansion bus to allow writes */
+ intel,ixp4xx-eb-write-enable = <1>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* CHECKME: guess this is Redboot FIS */
+ fis-index-block = <0xff>;
+ };
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Taken from WG302 v2 PCI boardfile (wg302v2-pci.c)
+ * We have slots (IDSEL) 1 and 2 with one assigned IRQ
+ * each handling all IRQs.
+ */
+ interrupt-map =
+ /* IDSEL 1 */
+ <0x0800 0 0 1 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 8 */
+ <0x0800 0 0 2 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 1 is irq 8 */
+ <0x0800 0 0 3 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 1 is irq 8 */
+ <0x0800 0 0 4 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 1 is irq 8 */
+ /* IDSEL 2 */
+ <0x1000 0 0 1 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 9 */
+ <0x1000 0 0 2 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 2 is irq 9 */
+ <0x1000 0 0 3 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 2 is irq 9 */
+ <0x1000 0 0 4 &gpio0 9 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 2 is irq 9 */
+ };
+
+ ethernet@c8009000 {
+ status = "ok";
+ queue-rx = <&qmgr 3>;
+ queue-txready = <&qmgr 20>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy8>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy8: ethernet-phy@8 {
+ reg = <8>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x-welltech-epbx100.dts b/arch/arm/boot/dts/intel-ixp42x-welltech-epbx100.dts
index 84158503be2a..f5846a50e4d4 100644
--- a/arch/arm/boot/dts/intel-ixp42x-welltech-epbx100.dts
+++ b/arch/arm/boot/dts/intel-ixp42x-welltech-epbx100.dts
@@ -28,48 +28,52 @@
serial0 = &uart0;
};
- flash@50000000 {
- compatible = "intel,ixp4xx-flash", "cfi-flash";
- bank-width = <2>;
- /*
- * 16 MB of Flash
- */
- reg = <0x50000000 0x1000000>;
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /*
+ * 16 MB of Flash
+ */
+ reg = <0 0x00000000 0x1000000>;
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
- partition@0 {
- label = "RedBoot";
- reg = <0x00000000 0x00080000>;
- read-only;
- };
- partition@80000 {
- label = "zImage";
- reg = <0x00080000 0x00100000>;
- read-only;
- };
- partition@180000 {
- label = "ramdisk";
- reg = <0x00180000 0x00300000>;
- read-only;
- };
- partition@480000 {
- label = "User";
- reg = <0x00480000 0x00b60000>;
- read-only;
- };
- partition@fe0000 {
- label = "FIS directory";
- reg = <0x00fe0000 0x001f000>;
- read-only;
- };
- partition@fff000 {
- label = "RedBoot config";
- reg = <0x00fff000 0x0001000>;
- read-only;
+ partition@0 {
+ label = "RedBoot";
+ reg = <0x00000000 0x00080000>;
+ read-only;
+ };
+ partition@80000 {
+ label = "zImage";
+ reg = <0x00080000 0x00100000>;
+ read-only;
+ };
+ partition@180000 {
+ label = "ramdisk";
+ reg = <0x00180000 0x00300000>;
+ read-only;
+ };
+ partition@480000 {
+ label = "User";
+ reg = <0x00480000 0x00b60000>;
+ read-only;
+ };
+ partition@fe0000 {
+ label = "FIS directory";
+ reg = <0x00fe0000 0x001f000>;
+ read-only;
+ };
+ partition@fff000 {
+ label = "RedBoot config";
+ reg = <0x00fff000 0x0001000>;
+ read-only;
+ };
+ };
};
};
};
diff --git a/arch/arm/boot/dts/intel-ixp42x.dtsi b/arch/arm/boot/dts/intel-ixp42x.dtsi
index 5fa063ed396c..d0e0f8afb7c9 100644
--- a/arch/arm/boot/dts/intel-ixp42x.dtsi
+++ b/arch/arm/boot/dts/intel-ixp42x.dtsi
@@ -7,6 +7,11 @@
/ {
soc {
+ bus@c4000000 {
+ compatible = "intel,ixp42x-expansion-bus-controller", "syscon";
+ reg = <0xc4000000 0x28>;
+ };
+
pci@c0000000 {
compatible = "intel,ixp42x-pci";
};
diff --git a/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts b/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts
index 60a1228a970f..84e6aec8e665 100644
--- a/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts
+++ b/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts
@@ -77,15 +77,17 @@
};
soc {
- bus@50000000 {
- flash@0 {
+ bus@c4000000 {
+ flash@0,0 {
compatible = "intel,ixp4xx-flash", "cfi-flash";
bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
/*
* 32 MB of Flash in 0x20000 byte blocks
- * mapped in at CS0.
+ * mapped in at CS0 and CS1
*/
- reg = <0x00000000 0x2000000>;
+ reg = <0 0x00000000 0x2000000>;
partitions {
compatible = "redboot-fis";
@@ -93,6 +95,29 @@
fis-index-block = <0xff>;
};
};
+ ide@3,0 {
+ compatible = "intel,ixp4xx-compact-flash";
+ /*
+ * Set up expansion bus config to a really slow timing.
+ * The CF driver will dynamically reconfigure these timings
+ * depending on selected PIO mode (0-4).
+ */
+ intel,ixp4xx-eb-t1 = <3>; // 3 cycles extra address phase
+ intel,ixp4xx-eb-t2 = <3>; // 3 cycles extra setup phase
+ intel,ixp4xx-eb-t3 = <15>; // 15 cycles extra strobe phase
+ intel,ixp4xx-eb-t4 = <3>; // 3 cycles extra hold phase
+ intel,ixp4xx-eb-t5 = <15>; // 15 cycles extra recovery phase
+ intel,ixp4xx-eb-cycle-type = <0>; // Intel cycle type
+ intel,ixp4xx-eb-byte-access-on-halfword = <1>;
+ intel,ixp4xx-eb-mux-address-and-data = <0>;
+ intel,ixp4xx-eb-ahb-split-transfers = <0>;
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+ /* First register set is CMD second is CTL */
+ reg = <3 0xe00000 0x40000>, <3 0xe40000 0x40000>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <12 IRQ_TYPE_EDGE_RISING>;
+ };
};
pci@c0000000 {
@@ -108,35 +133,35 @@
*/
interrupt-map =
/* IDSEL 1 */
- <0x0800 0 0 1 &gpio0 11 3>, /* INT A on slot 1 is irq 11 */
- <0x0800 0 0 2 &gpio0 10 3>, /* INT B on slot 1 is irq 10 */
- <0x0800 0 0 3 &gpio0 9 3>, /* INT C on slot 1 is irq 9 */
- <0x0800 0 0 4 &gpio0 8 3>, /* INT D on slot 1 is irq 8 */
+ <0x0800 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 11 */
+ <0x0800 0 0 2 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 1 is irq 10 */
+ <0x0800 0 0 3 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 1 is irq 9 */
+ <0x0800 0 0 4 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 1 is irq 8 */
/* IDSEL 2 */
- <0x1000 0 0 1 &gpio0 10 3>, /* INT A on slot 2 is irq 10 */
- <0x1000 0 0 2 &gpio0 9 3>, /* INT B on slot 2 is irq 9 */
- <0x1000 0 0 3 &gpio0 8 3>, /* INT C on slot 2 is irq 8 */
- <0x1000 0 0 4 &gpio0 11 3>, /* INT D on slot 2 is irq 11 */
+ <0x1000 0 0 1 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 10 */
+ <0x1000 0 0 2 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 2 is irq 9 */
+ <0x1000 0 0 3 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 2 is irq 8 */
+ <0x1000 0 0 4 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 2 is irq 11 */
/* IDSEL 3 */
- <0x1800 0 0 1 &gpio0 9 3>, /* INT A on slot 3 is irq 9 */
- <0x1800 0 0 2 &gpio0 8 3>, /* INT B on slot 3 is irq 8 */
- <0x1800 0 0 3 &gpio0 11 3>, /* INT C on slot 3 is irq 11 */
- <0x1800 0 0 4 &gpio0 10 3>, /* INT D on slot 3 is irq 10 */
+ <0x1800 0 0 1 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 3 is irq 9 */
+ <0x1800 0 0 2 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 8 */
+ <0x1800 0 0 3 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 3 is irq 11 */
+ <0x1800 0 0 4 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 3 is irq 10 */
/* IDSEL 4 */
- <0x2000 0 0 1 &gpio0 8 3>, /* INT A on slot 3 is irq 8 */
- <0x2000 0 0 2 &gpio0 11 3>, /* INT B on slot 3 is irq 11 */
- <0x2000 0 0 3 &gpio0 10 3>, /* INT C on slot 3 is irq 10 */
- <0x2000 0 0 4 &gpio0 9 3>, /* INT D on slot 3 is irq 9 */
+ <0x2000 0 0 1 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 3 is irq 8 */
+ <0x2000 0 0 2 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 11 */
+ <0x2000 0 0 3 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 3 is irq 10 */
+ <0x2000 0 0 4 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 3 is irq 9 */
/* IDSEL 6 */
- <0x3000 0 0 1 &gpio0 10 3>, /* INT A on slot 3 is irq 10 */
- <0x3000 0 0 2 &gpio0 9 3>, /* INT B on slot 3 is irq 9 */
- <0x3000 0 0 3 &gpio0 8 3>, /* INT C on slot 3 is irq 8 */
- <0x3000 0 0 4 &gpio0 11 3>, /* INT D on slot 3 is irq 11 */
+ <0x3000 0 0 1 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 3 is irq 10 */
+ <0x3000 0 0 2 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 9 */
+ <0x3000 0 0 3 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 3 is irq 8 */
+ <0x3000 0 0 4 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 3 is irq 11 */
/* IDSEL 15 */
- <0x7800 0 0 1 &gpio0 8 3>, /* INT A on slot 3 is irq 8 */
- <0x7800 0 0 2 &gpio0 11 3>, /* INT B on slot 3 is irq 11 */
- <0x7800 0 0 3 &gpio0 10 3>, /* INT C on slot 3 is irq 10 */
- <0x7800 0 0 4 &gpio0 9 3>; /* INT D on slot 3 is irq 9 */
+ <0x7800 0 0 1 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 3 is irq 8 */
+ <0x7800 0 0 2 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 11 */
+ <0x7800 0 0 3 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 3 is irq 10 */
+ <0x7800 0 0 4 &gpio0 9 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 3 is irq 9 */
};
ethernet@c800a000 {
diff --git a/arch/arm/boot/dts/intel-ixp43x-kixrp435.dts b/arch/arm/boot/dts/intel-ixp43x-kixrp435.dts
new file mode 100644
index 000000000000..3d7cfa1a5ed4
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp43x-kixrp435.dts
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the Intel KIXRP435 Control Plane
+ * processor reference design.
+ */
+
+/dts-v1/;
+
+#include "intel-ixp43x.dtsi"
+#include "intel-ixp4xx-reference-design.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Intel KIXRP435 Reference Design";
+ compatible = "intel,kixrp435", "intel,ixp43x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
+ /* 16 MB of Flash mapped in at CS0 */
+ reg = <0 0x00000000 0x1000000>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0x0fe0000 */
+ fis-index-block = <0x7f>;
+ };
+ };
+ };
+
+ /* CHECKME: ethernet set-up taken from Gateworks Cambria */
+ ethernet@c800a000 {
+ status = "ok";
+ queue-rx = <&qmgr 4>;
+ queue-txready = <&qmgr 21>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy1>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+
+ phy2: ethernet-phy@2 {
+ reg = <2>;
+ };
+ };
+ };
+
+ ethernet@c800c000 {
+ status = "ok";
+ queue-rx = <&qmgr 2>;
+ queue-txready = <&qmgr 19>;
+ phy-mode = "rgmii";
+ phy-handle = <&phy2>;
+ intel,npe-handle = <&npe 0>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp43x.dtsi b/arch/arm/boot/dts/intel-ixp43x.dtsi
index 1d0817c6e3f9..60bf9903e0f8 100644
--- a/arch/arm/boot/dts/intel-ixp43x.dtsi
+++ b/arch/arm/boot/dts/intel-ixp43x.dtsi
@@ -8,6 +8,12 @@
/ {
soc {
+ bus@c4000000 {
+ compatible = "intel,ixp43x-expansion-bus-controller", "syscon";
+ /* Uses at least up to 0x230 */
+ reg = <0xc4000000 0x1000>;
+ };
+
pci@c0000000 {
compatible = "intel,ixp43x-pci";
};
diff --git a/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi b/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi
index cce49e809043..b6ff614dadc6 100644
--- a/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi
+++ b/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi
@@ -9,6 +9,17 @@
/ {
soc {
+ bus@c4000000 {
+ compatible = "intel,ixp46x-expansion-bus-controller", "syscon";
+ /* Uses at least up to 0x124 */
+ reg = <0xc4000000 0x1000>;
+ };
+
+ rng@70002100 {
+ compatible = "intel,ixp46x-rng";
+ reg = <0x70002100 4>;
+ };
+
interrupt-controller@c8003000 {
compatible = "intel,ixp43x-interrupt";
};
diff --git a/arch/arm/boot/dts/intel-ixp46x-ixdp465.dts b/arch/arm/boot/dts/intel-ixp46x-ixdp465.dts
new file mode 100644
index 000000000000..a062cd1a6588
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp46x-ixdp465.dts
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for the Intel IXDP465 Control Plane processor reference
+ * design, codename "BMP".
+ */
+
+/dts-v1/;
+
+#include "intel-ixp45x-ixp46x.dtsi"
+#include "intel-ixp4xx-reference-design.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Intel IXDP465 BMP Reference Design";
+ compatible = "intel,ixdp465", "intel,ixp46x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc {
+ bus@c4000000 {
+ flash@0,0 {
+ compatible = "intel,ixp4xx-flash", "cfi-flash";
+ bank-width = <2>;
+ /* Enable writes on the expansion bus */
+ intel,ixp4xx-eb-write-enable = <1>;
+ /* 32 MB of Flash mapped in at CS0 and CS1 */
+ reg = <0 0x00000000 0x2000000>;
+
+ partitions {
+ compatible = "redboot-fis";
+ /* Eraseblock at 0x1fe0000 */
+ fis-index-block = <0xff>;
+ };
+ };
+ };
+ /* TODO: configure ethernet etc */
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp4xx-reference-design.dtsi b/arch/arm/boot/dts/intel-ixp4xx-reference-design.dtsi
new file mode 100644
index 000000000000..c1d9c49982b3
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp4xx-reference-design.dtsi
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree include file for Intel reference designs for the
+ * XScale Network Processors in the IXP 4xx series. Common device
+ * set-up for IXDP425, IXCDP1100, KIXRP435 and IXDP465.
+ */
+
+/ {
+ memory@0 {
+ /*
+ * The board supports up to 256 MB of memory. Here we put in
+ * 64 MB and this may be modified by the boot loader.
+ */
+ device_type = "memory";
+ reg = <0x00000000 0x4000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8";
+ stdout-path = "uart0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ i2c {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio0 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@50 {
+ /*
+ * Philips PCF8582C-2T/03 512byte I2C EEPROM
+ * should behave like an Atmel 24c04.
+ */
+ compatible = "atmel,24c04";
+ reg = <0x50>;
+ pagesize = <16>;
+ size = <512>;
+ read-only;
+ };
+ };
+
+ soc {
+ bus@c4000000 {
+ /* Flash memory defined per-variant */
+ nand-controller@3,0 {
+ /* Some designs have a NAND on CS3 enable it here if present */
+ status = "disabled";
+
+ /*
+ * gen_nand needs to be extended and documented to get
+ * command byte = 1 and address byte = 2 from the device
+ * tree.
+ */
+ compatible = "gen_nand";
+
+ /* Expansion bus set-up */
+ intel,ixp4xx-eb-t1 = <0>;
+ intel,ixp4xx-eb-t2 = <0>;
+ intel,ixp4xx-eb-t3 = <1>; // 1 cycle extra strobe phase
+ intel,ixp4xx-eb-t4 = <0>;
+ intel,ixp4xx-eb-t5 = <0>;
+ intel,ixp4xx-eb-cycle-type = <0>; // Intel cycle type
+ intel,ixp4xx-eb-byte-access-on-halfword = <0>;
+ intel,ixp4xx-eb-mux-address-and-data = <0>;
+ intel,ixp4xx-eb-ahb-split-transfers = <0>;
+ intel,ixp4xx-eb-write-enable = <1>;
+ intel,ixp4xx-eb-byte-access = <1>;
+
+ /* 512 bytes memory window */
+ reg = <3 0x00000000 0x200>;
+ nand-on-flash-bbt;
+ nand-ecc-mode = "soft_bch";
+ nand-ecc-step-size = <512>;
+ nand-ecc-strength = <4>;
+ nce-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; /* NCE */
+
+ label = "ixp400 NAND";
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ fs@0 {
+ label = "ixp400 NAND FS 0";
+ reg = <0x0 0x800000>;
+ };
+ fs@800000 {
+ label = "ixp400 NAND FS 1";
+ reg = <0x800000 0x0>;
+ };
+ };
+ };
+ };
+
+ pci@c0000000 {
+ status = "ok";
+
+ /*
+ * Taken from IXDP425 PCI boardfile.
+ * PCI slots on the BIXMB425BD base card.
+ * We have up to 4 slots (IDSEL) with 4 swizzled IRQs.
+ */
+ interrupt-map =
+ /* IDSEL 1 */
+ <0x0800 0 0 1 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 1 is irq 11 */
+ <0x0800 0 0 2 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 1 is irq 10 */
+ <0x0800 0 0 3 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 1 is irq 9 */
+ <0x0800 0 0 4 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 1 is irq 8 */
+ /* IDSEL 2 */
+ <0x1000 0 0 1 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 2 is irq 10 */
+ <0x1000 0 0 2 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 2 is irq 9 */
+ <0x1000 0 0 3 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 2 is irq 8 */
+ <0x1000 0 0 4 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 2 is irq 11 */
+ /* IDSEL 3 */
+ <0x1800 0 0 1 &gpio0 9 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 3 is irq 9 */
+ <0x1800 0 0 2 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 3 is irq 8 */
+ <0x1800 0 0 3 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 3 is irq 11 */
+ <0x1800 0 0 4 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT D on slot 3 is irq 10 */
+ /* IDSEL 4 */
+ <0x2000 0 0 1 &gpio0 8 IRQ_TYPE_LEVEL_LOW>, /* INT A on slot 4 is irq 8 */
+ <0x2000 0 0 2 &gpio0 11 IRQ_TYPE_LEVEL_LOW>, /* INT B on slot 4 is irq 11 */
+ <0x2000 0 0 3 &gpio0 10 IRQ_TYPE_LEVEL_LOW>, /* INT C on slot 4 is irq 10 */
+ <0x2000 0 0 4 &gpio0 9 IRQ_TYPE_LEVEL_LOW>; /* INT D on slot 4 is irq 9 */
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/intel-ixp4xx.dtsi b/arch/arm/boot/dts/intel-ixp4xx.dtsi
index a50427ad05e7..e5af2d463074 100644
--- a/arch/arm/boot/dts/intel-ixp4xx.dtsi
+++ b/arch/arm/boot/dts/intel-ixp4xx.dtsi
@@ -15,16 +15,30 @@
interrupt-parent = <&intcon>;
/*
- * The IXP4xx expansion bus is a set of 16 or 32MB
- * windows in the 256MB space from 0x50000000 to
- * 0x5fffffff.
+ * The IXP4xx expansion bus is a set of up to 7 each up to 16MB
+ * windows in the 256MB space from 0x50000000 to 0x5fffffff.
*/
- bus@50000000 {
- compatible = "simple-bus";
- #address-cells = <1>;
+ bus@c4000000 {
+ /* compatible and reg filled in by per-soc device tree */
+ native-endian;
+ #address-cells = <2>;
#size-cells = <1>;
- ranges = <0x00000000 0x50000000 0x10000000>;
- dma-ranges = <0x00000000 0x50000000 0x10000000>;
+ ranges = <0 0x0 0x50000000 0x01000000>,
+ <1 0x0 0x51000000 0x01000000>,
+ <2 0x0 0x52000000 0x01000000>,
+ <3 0x0 0x53000000 0x01000000>,
+ <4 0x0 0x54000000 0x01000000>,
+ <5 0x0 0x55000000 0x01000000>,
+ <6 0x0 0x56000000 0x01000000>,
+ <7 0x0 0x57000000 0x01000000>;
+ dma-ranges = <0 0x0 0x50000000 0x01000000>,
+ <1 0x0 0x51000000 0x01000000>,
+ <2 0x0 0x52000000 0x01000000>,
+ <3 0x0 0x53000000 0x01000000>,
+ <4 0x0 0x54000000 0x01000000>,
+ <5 0x0 0x55000000 0x01000000>,
+ <6 0x0 0x56000000 0x01000000>,
+ <7 0x0 0x57000000 0x01000000>;
};
qmgr: queue-manager@60000000 {
@@ -83,6 +97,20 @@
no-loopback-test;
};
+ uart1: serial@c8001000 {
+ compatible = "intel,xscale-uart";
+ reg = <0xc8001000 0x1000>;
+ /*
+ * The reg-offset and reg-shift is a side effect
+ * of running the platform in big endian mode.
+ */
+ reg-offset = <3>;
+ reg-shift = <2>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <14745600>;
+ no-loopback-test;
+ };
+
gpio0: gpio@c8004000 {
compatible = "intel,ixp4xx-gpio";
reg = <0xc8004000 0x1000>;
diff --git a/arch/arm/boot/dts/keystone-k2e-netcp.dtsi b/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
index ad15e77874b1..71064483d34f 100644
--- a/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
@@ -95,7 +95,7 @@ qmss: qmss@2a40000 {
#address-cells = <1>;
#size-cells = <1>;
ranges;
- pdsp0@0x2a10000 {
+ pdsp0@2a10000 {
reg = <0x2a10000 0x1000 /*iram */
0x2a0f000 0x100 /*reg*/
0x2a0c000 0x3c8 /*intd */
diff --git a/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi b/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
index d5a6c1f5633c..022d93c366c7 100644
--- a/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
@@ -112,7 +112,7 @@ qmss: qmss@2a40000 {
#address-cells = <1>;
#size-cells = <1>;
ranges;
- pdsp0@0x2a10000 {
+ pdsp0@2a10000 {
reg = <0x2a10000 0x1000 /*iram */
0x2a0f000 0x100 /*reg*/
0x2a0c000 0x3c8 /*intd */
diff --git a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
index c1f982604145..e96ca664abc2 100644
--- a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
@@ -94,7 +94,7 @@ qmss: qmss@2a40000 {
#address-cells = <1>;
#size-cells = <1>;
ranges;
- pdsp0@0x2a10000 {
+ pdsp0@2a10000 {
reg = <0x2a10000 0x1000 /*iram */
0x2a0f000 0x100 /*reg*/
0x2a0c000 0x3c8 /*intd */
diff --git a/arch/arm/boot/dts/meson.dtsi b/arch/arm/boot/dts/meson.dtsi
index bd0e864964e9..3be7cba603d5 100644
--- a/arch/arm/boot/dts/meson.dtsi
+++ b/arch/arm/boot/dts/meson.dtsi
@@ -5,6 +5,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/sound/meson-aiu.h>
/ {
#address-cells = <1>;
@@ -36,6 +37,17 @@
reg = <0x4000 0x400>;
};
+ aiu: audio-controller@5400 {
+ compatible = "amlogic,aiu";
+ #sound-dai-cells = <2>;
+ sound-name-prefix = "AIU";
+ reg = <0x5400 0x2ac>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 50 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "i2s", "spdif";
+ status = "disabled";
+ };
+
assist: assist@7c00 {
compatible = "amlogic,meson-mx-assist", "syscon";
reg = <0x7c00 0x200>;
diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/meson8.dtsi
index 157a950a55d3..f80ddc98d3a2 100644
--- a/arch/arm/boot/dts/meson8.dtsi
+++ b/arch/arm/boot/dts/meson8.dtsi
@@ -304,14 +304,42 @@
"pp2", "ppmmu2", "pp4", "ppmmu4",
"pp5", "ppmmu5", "pp6", "ppmmu6";
resets = <&reset RESET_MALI>;
+
clocks = <&clkc CLKID_CLK81>, <&clkc CLKID_MALI>;
clock-names = "bus", "core";
+
+ assigned-clocks = <&clkc CLKID_MALI>;
+ assigned-clock-rates = <318750000>;
+
operating-points-v2 = <&gpu_opp_table>;
#cooling-cells = <2>; /* min followed by max */
};
};
}; /* end of / */
+&aiu {
+ compatible = "amlogic,aiu-meson8", "amlogic,aiu";
+ clocks = <&clkc CLKID_AIU_GLUE>,
+ <&clkc CLKID_I2S_OUT>,
+ <&clkc CLKID_AOCLK_GATE>,
+ <&clkc CLKID_CTS_AMCLK>,
+ <&clkc CLKID_MIXER_IFACE>,
+ <&clkc CLKID_IEC958>,
+ <&clkc CLKID_IEC958_GATE>,
+ <&clkc CLKID_CTS_MCLK_I958>,
+ <&clkc CLKID_CTS_I958>;
+ clock-names = "pclk",
+ "i2s_pclk",
+ "i2s_aoclk",
+ "i2s_mclk",
+ "i2s_mixer",
+ "spdif_pclk",
+ "spdif_aoclk",
+ "spdif_mclk",
+ "spdif_mclk_sel";
+ resets = <&reset RESET_AIU>;
+};
+
&aobus {
pmu: pmu@e0 {
compatible = "amlogic,meson8-pmu", "syscon";
@@ -335,6 +363,38 @@
gpio-ranges = <&pinctrl_aobus 0 0 16>;
};
+ i2s_am_clk_pins: i2s-am-clk-out {
+ mux {
+ groups = "i2s_am_clk_out_ao";
+ function = "i2s_ao";
+ bias-disable;
+ };
+ };
+
+ i2s_out_ao_clk_pins: i2s-ao-clk-out {
+ mux {
+ groups = "i2s_ao_clk_out_ao";
+ function = "i2s_ao";
+ bias-disable;
+ };
+ };
+
+ i2s_out_lr_clk_pins: i2s-lr-clk-out {
+ mux {
+ groups = "i2s_lr_clk_out_ao";
+ function = "i2s_ao";
+ bias-disable;
+ };
+ };
+
+ i2s_out_ch01_ao_pins: i2s-out-ch01 {
+ mux {
+ groups = "i2s_out_ch01_ao";
+ function = "i2s_ao";
+ bias-disable;
+ };
+ };
+
uart_ao_a_pins: uart_ao_a {
mux {
groups = "uart_tx_ao_a", "uart_rx_ao_a";
@@ -455,6 +515,14 @@
};
};
+ spdif_out_pins: spdif-out {
+ mux {
+ groups = "spdif_out";
+ function = "spdif";
+ bias-disable;
+ };
+ };
+
spi_nor_pins: nor {
mux {
groups = "nor_d", "nor_q", "nor_c", "nor_cs";
diff --git a/arch/arm/boot/dts/meson8b-ec100.dts b/arch/arm/boot/dts/meson8b-ec100.dts
index 8e48ccc6b634..77d4beeb8010 100644
--- a/arch/arm/boot/dts/meson8b-ec100.dts
+++ b/arch/arm/boot/dts/meson8b-ec100.dts
@@ -96,6 +96,32 @@
#clock-cells = <0>;
};
+ sound {
+ compatible = "amlogic,gx-sound-card";
+ model = "M8B-EC100";
+
+ assigned-clocks = <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>,
+ <&clkc CLKID_MPLL2>;
+ assigned-clock-rates = <270950400>,
+ <294912000>,
+ <393216000>;
+
+ dai-link-0 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+ dai-format = "i2s";
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&rt5640>;
+ };
+ };
+ };
+
usb_vbus: regulator-usb-vbus {
/*
* Silergy SY6288CCAC-GP 2A Power Distribution Switch.
@@ -148,7 +174,7 @@
regulator-min-microvolt = <860000>;
regulator-max-microvolt = <1140000>;
- vin-supply = <&vcc_5v>;
+ pwm-supply = <&vcc_5v>;
pwms = <&pwm_cd 0 1148 0>;
pwm-dutycycle-range = <100 0>;
@@ -232,7 +258,7 @@
regulator-min-microvolt = <860000>;
regulator-max-microvolt = <1140000>;
- vin-supply = <&vcc_5v>;
+ pwm-supply = <&vcc_5v>;
pwms = <&pwm_cd 1 1148 0>;
pwm-dutycycle-range = <100 0>;
@@ -242,6 +268,14 @@
};
};
+&aiu {
+ status = "okay";
+
+ pinctrl-0 = <&i2s_am_clk_pins>, <&i2s_out_ao_clk_pins>,
+ <&i2s_out_lr_clk_pins>, <&i2s_out_ch01_ao_pins>;
+ pinctrl-names = "default";
+};
+
&cpu0 {
cpu-supply = <&vcck>;
};
@@ -283,9 +317,19 @@
rt5640: codec@1c {
compatible = "realtek,rt5640";
+
reg = <0x1c>;
+
+ #sound-dai-cells = <0>;
+
interrupt-parent = <&gpio_intc>;
interrupts = <13 IRQ_TYPE_EDGE_BOTH>; /* GPIOAO_13 */
+
+ /*
+ * TODO: realtek,ldo1-en-gpios is connected to GPIO_BSD_EN.
+ * We currently cannot configure this pin correctly.
+ * Luckily for us it's in the "right" state by default.
+ */
realtek,in1-differential;
};
};
diff --git a/arch/arm/boot/dts/meson8b-mxq.dts b/arch/arm/boot/dts/meson8b-mxq.dts
index f3937d55472d..7adedd3258c3 100644
--- a/arch/arm/boot/dts/meson8b-mxq.dts
+++ b/arch/arm/boot/dts/meson8b-mxq.dts
@@ -34,6 +34,8 @@
regulator-min-microvolt = <860000>;
regulator-max-microvolt = <1140000>;
+ pwm-supply = <&vcc_5v>;
+
pwms = <&pwm_cd 0 1148 0>;
pwm-dutycycle-range = <100 0>;
@@ -79,7 +81,7 @@
regulator-min-microvolt = <860000>;
regulator-max-microvolt = <1140000>;
- vin-supply = <&vcc_5v>;
+ pwm-supply = <&vcc_5v>;
pwms = <&pwm_cd 1 1148 0>;
pwm-dutycycle-range = <100 0>;
diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts
index c440ef94e082..04356bc639fa 100644
--- a/arch/arm/boot/dts/meson8b-odroidc1.dts
+++ b/arch/arm/boot/dts/meson8b-odroidc1.dts
@@ -131,7 +131,7 @@
regulator-min-microvolt = <860000>;
regulator-max-microvolt = <1140000>;
- vin-supply = <&p5v0>;
+ pwm-supply = <&p5v0>;
pwms = <&pwm_cd 0 12218 0>;
pwm-dutycycle-range = <91 0>;
@@ -163,7 +163,7 @@
regulator-min-microvolt = <860000>;
regulator-max-microvolt = <1140000>;
- vin-supply = <&p5v0>;
+ pwm-supply = <&p5v0>;
pwms = <&pwm_cd 1 12218 0>;
pwm-dutycycle-range = <91 0>;
diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index c02b03cbcdf4..b49b7cbaed4e 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -279,6 +279,29 @@
};
}; /* end of / */
+&aiu {
+ compatible = "amlogic,aiu-meson8b", "amlogic,aiu";
+ clocks = <&clkc CLKID_AIU_GLUE>,
+ <&clkc CLKID_I2S_OUT>,
+ <&clkc CLKID_AOCLK_GATE>,
+ <&clkc CLKID_CTS_AMCLK>,
+ <&clkc CLKID_MIXER_IFACE>,
+ <&clkc CLKID_IEC958>,
+ <&clkc CLKID_IEC958_GATE>,
+ <&clkc CLKID_CTS_MCLK_I958>,
+ <&clkc CLKID_CTS_I958>;
+ clock-names = "pclk",
+ "i2s_pclk",
+ "i2s_aoclk",
+ "i2s_mclk",
+ "i2s_mixer",
+ "spdif_pclk",
+ "spdif_aoclk",
+ "spdif_mclk",
+ "spdif_mclk_sel";
+ resets = <&reset RESET_AIU>;
+};
+
&aobus {
pmu: pmu@e0 {
compatible = "amlogic,meson8b-pmu", "syscon";
@@ -302,6 +325,46 @@
gpio-ranges = <&pinctrl_aobus 0 0 16>;
};
+ i2s_am_clk_pins: i2s-am-clk-out {
+ mux {
+ groups = "i2s_am_clk_out";
+ function = "i2s";
+ bias-disable;
+ };
+ };
+
+ i2s_out_ao_clk_pins: i2s-ao-clk-out {
+ mux {
+ groups = "i2s_ao_clk_out";
+ function = "i2s";
+ bias-disable;
+ };
+ };
+
+ i2s_out_lr_clk_pins: i2s-lr-clk-out {
+ mux {
+ groups = "i2s_lr_clk_out";
+ function = "i2s";
+ bias-disable;
+ };
+ };
+
+ i2s_out_ch01_ao_pins: i2s-out-ch01 {
+ mux {
+ groups = "i2s_out_01";
+ function = "i2s";
+ bias-disable;
+ };
+ };
+
+ spdif_out_1_pins: spdif-out-1 {
+ mux {
+ groups = "spdif_out_1";
+ function = "spdif_1";
+ bias-disable;
+ };
+ };
+
uart_ao_a_pins: uart_ao_a {
mux {
groups = "uart_tx_ao_a", "uart_rx_ao_a";
diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi
index 3c11f7cfcc40..a7d62dbad602 100644
--- a/arch/arm/boot/dts/mt7623.dtsi
+++ b/arch/arm/boot/dts/mt7623.dtsi
@@ -160,7 +160,7 @@
trips {
cpu_passive: cpu-passive {
- temperature = <47000>;
+ temperature = <57000>;
hysteresis = <2000>;
type = "passive";
};
diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index 0e4e835026db..a031b3636318 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -9,7 +9,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/mt8135-resets.h>
-#include "mt8135-pinfunc.h"
+#include <dt-bindings/pinctrl/mt8135-pinfunc.h>
/ {
#address-cells = <2>;
diff --git a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
index dea3dbc4a6a5..0334641f8829 100644
--- a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
+++ b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
@@ -105,11 +105,11 @@
label = "rootfs";
reg = <0x0600000 0x700000>;
};
- spare1@D00000 {
+ spare1@d00000 {
label = "spare1";
reg = <0x0D00000 0x200000>;
};
- spare2@0F00000 {
+ spare2@f00000 {
label = "spare2";
reg = <0x0F00000 0x200000>;
};
diff --git a/arch/arm/boot/dts/omap4-l4-abe.dtsi b/arch/arm/boot/dts/omap4-l4-abe.dtsi
index a9573d441dea..7ae8b620515c 100644
--- a/arch/arm/boot/dts/omap4-l4-abe.dtsi
+++ b/arch/arm/boot/dts/omap4-l4-abe.dtsi
@@ -186,37 +186,39 @@
};
target-module@28000 { /* 0x40128000, ap 8 08.0 */
+ /* 0x4012a000, ap 10 0a.0 */
compatible = "ti,sysc-mcasp", "ti,sysc";
reg = <0x28000 0x4>,
<0x28004 0x4>;
reg-names = "rev", "sysc";
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
- <SYSC_IDLE_SMART>,
- <SYSC_IDLE_SMART_WKUP>;
+ <SYSC_IDLE_SMART>;
/* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
clocks = <&abe_clkctrl OMAP4_MCASP_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x28000 0x1000>,
- <0x49028000 0x49028000 0x1000>;
-
- /*
- * Child device unsupported by davinci-mcasp. At least
- * RX path is disabled for omap4, and only DIT mode
- * works with no I2S. See also old Android kernel
- * omap-mcasp driver for more information.
- */
- };
-
- target-module@2a000 { /* 0x4012a000, ap 10 0a.0 */
- compatible = "ti,sysc";
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x0 0x2a000 0x1000>,
+ <0x49028000 0x49028000 0x1000>,
+ <0x2000 0x2a000 0x1000>,
<0x4902a000 0x4902a000 0x1000>;
+
+ mcasp0: mcasp@0 {
+ compatible = "ti,omap4-mcasp-audio";
+ reg = <0x0 0x2000>,
+ <0x4902a000 0x1000>; /* L3 data port */
+ reg-names = "mpu","dat";
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx";
+ dmas = <&sdma 8>;
+ dma-names = "tx";
+ clocks = <&abe_clkctrl OMAP4_MCASP_CLKCTRL 0>;
+ clock-names = "fck";
+ op-mode = <1>; /* MCASP_DIT_MODE */
+ serial-dir = < 1 >; /* 1 TX serializers */
+ status = "disabled";
+ };
};
target-module@2e000 { /* 0x4012e000, ap 12 0c.0 */
diff --git a/arch/arm/boot/dts/owl-s500-roseapplepi.dts b/arch/arm/boot/dts/owl-s500-roseapplepi.dts
index b8c5db2344aa..eb555f385283 100644
--- a/arch/arm/boot/dts/owl-s500-roseapplepi.dts
+++ b/arch/arm/boot/dts/owl-s500-roseapplepi.dts
@@ -225,6 +225,27 @@
bias-pull-down;
};
};
+
+ ethernet_pins: ethernet-pins {
+ eth_rmii-pinmux {
+ groups = "rmii_txd0_mfp", "rmii_txd1_mfp",
+ "rmii_rxd0_mfp", "rmii_rxd1_mfp",
+ "rmii_txen_mfp", "rmii_rxen_mfp",
+ "rmii_crs_dv_mfp", "rmii_ref_clk_mfp";
+ function = "eth_rmii";
+ };
+
+ phy_clk-pinmux {
+ groups = "clko_25m_mfp";
+ function = "clko_25m";
+ };
+
+ ref_clk-pinconf {
+ groups = "rmii_ref_clk_drv";
+ drive-strength = <2>;
+ };
+
+ };
};
/* uSD */
@@ -241,6 +262,30 @@
vqmmc-supply = <&sd_vcc>;
};
+&ethernet {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ethernet_pins>;
+ phy-mode = "rmii";
+ phy-handle = <&eth_phy>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reset-gpios = <&pinctrl 88 GPIO_ACTIVE_LOW>; /* GPIOC24 */
+ reset-delay-us = <10000>;
+ reset-post-delay-us = <150000>;
+
+ eth_phy: ethernet-phy@3 {
+ reg = <0x3>;
+ max-speed = <100>;
+ interrupt-parent = <&sirq>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+};
+
&twd_timer {
status = "okay";
};
diff --git a/arch/arm/boot/dts/owl-s500.dtsi b/arch/arm/boot/dts/owl-s500.dtsi
index cd635f222d26..739b4b9cec8c 100644
--- a/arch/arm/boot/dts/owl-s500.dtsi
+++ b/arch/arm/boot/dts/owl-s500.dtsi
@@ -324,5 +324,15 @@
dma-names = "mmc";
status = "disabled";
};
+
+ ethernet: ethernet@b0310000 {
+ compatible = "actions,s500-emac", "actions,owl-emac";
+ reg = <0xb0310000 0x10000>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cmu CLK_ETHERNET>, <&cmu CLK_RMII_REF>;
+ clock-names = "eth", "rmii";
+ resets = <&cmu RESET_ETHERNET>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
index 0a4ffd10c484..e1189e929ee6 100644
--- a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
@@ -1,25 +1,4 @@
-/*
- * Copyright 2016 Linaro Ltd
- *
- * 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 BSD-2-Clause)
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 2687c4e890ba..0b2bed6e7adf 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -766,40 +766,40 @@
#size-cells = <0>;
#io-channel-cells = <2>;
- vcoin: adc-channel@00 {
+ vcoin: adc-channel@0 {
reg = <0x00 0x00>;
};
- vbat: adc-channel@01 {
+ vbat: adc-channel@1 {
reg = <0x00 0x01>;
};
- dcin: adc-channel@02 {
+ dcin: adc-channel@2 {
reg = <0x00 0x02>;
};
- vph_pwr: adc-channel@04 {
+ vph_pwr: adc-channel@4 {
reg = <0x00 0x04>;
};
- batt_therm: adc-channel@08 {
+ batt_therm: adc-channel@8 {
reg = <0x00 0x08>;
};
- batt_id: adc-channel@09 {
+ batt_id: adc-channel@9 {
reg = <0x00 0x09>;
};
- usb_vbus: adc-channel@0a {
+ usb_vbus: adc-channel@a {
reg = <0x00 0x0a>;
};
- die_temp: adc-channel@0b {
+ die_temp: adc-channel@b {
reg = <0x00 0x0b>;
};
- ref_625mv: adc-channel@0c {
+ ref_625mv: adc-channel@c {
reg = <0x00 0x0c>;
};
- ref_1250mv: adc-channel@0d {
+ ref_1250mv: adc-channel@d {
reg = <0x00 0x0d>;
};
- chg_temp: adc-channel@0e {
+ chg_temp: adc-channel@e {
reg = <0x00 0x0e>;
};
- ref_muxoff: adc-channel@0f {
+ ref_muxoff: adc-channel@f {
reg = <0x00 0x0f>;
};
};
@@ -1262,9 +1262,9 @@
<&mmcc DSI1_BYTE_CLK>,
<&mmcc DSI_PIXEL_CLK>,
<&mmcc DSI1_ESC_CLK>;
- clock-names = "iface_clk", "bus_clk", "core_mmss_clk",
- "src_clk", "byte_clk", "pixel_clk",
- "core_clk";
+ clock-names = "iface", "bus", "core_mmss",
+ "src", "byte", "pixel",
+ "core";
assigned-clocks = <&mmcc DSI1_BYTE_SRC>,
<&mmcc DSI1_ESC_SRC>,
diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi
index 7bcf5ef92157..4139d3817bd6 100644
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -980,8 +980,9 @@
clocks = <&gcc GMAC_CORE1_CLK>;
clock-names = "stmmaceth";
- resets = <&gcc GMAC_CORE1_RESET>;
- reset-names = "stmmaceth";
+ resets = <&gcc GMAC_CORE1_RESET>,
+ <&gcc GMAC_AHB_RESET>;
+ reset-names = "stmmaceth", "ahb";
status = "disabled";
};
@@ -1003,8 +1004,9 @@
clocks = <&gcc GMAC_CORE2_CLK>;
clock-names = "stmmaceth";
- resets = <&gcc GMAC_CORE2_RESET>;
- reset-names = "stmmaceth";
+ resets = <&gcc GMAC_CORE2_RESET>,
+ <&gcc GMAC_AHB_RESET>;
+ reset-names = "stmmaceth", "ahb";
status = "disabled";
};
@@ -1026,8 +1028,9 @@
clocks = <&gcc GMAC_CORE3_CLK>;
clock-names = "stmmaceth";
- resets = <&gcc GMAC_CORE3_RESET>;
- reset-names = "stmmaceth";
+ resets = <&gcc GMAC_CORE3_RESET>,
+ <&gcc GMAC_AHB_RESET>;
+ reset-names = "stmmaceth", "ahb";
status = "disabled";
};
@@ -1049,8 +1052,9 @@
clocks = <&gcc GMAC_CORE4_CLK>;
clock-names = "stmmaceth";
- resets = <&gcc GMAC_CORE4_RESET>;
- reset-names = "stmmaceth";
+ resets = <&gcc GMAC_CORE4_RESET>,
+ <&gcc GMAC_AHB_RESET>;
+ reset-names = "stmmaceth", "ahb";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts b/arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts
new file mode 100644
index 000000000000..d159188c8b95
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include "qcom-msm8226.dtsi"
+
+/ {
+ model = "Samsung Galaxy S III Neo";
+ compatible = "samsung,s3ve3g", "qcom,msm8226";
+
+ aliases {
+ serial0 = &blsp1_uart3;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&soc {
+ serial@f991f000 {
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-msm8226.dtsi b/arch/arm/boot/dts/qcom-msm8226.dtsi
new file mode 100644
index 000000000000..2de69d56870d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-msm8226.dtsi
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/qcom,gcc-msm8974.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ chosen { };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0>;
+ };
+
+ soc: soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ intc: interrupt-controller@f9000000 {
+ compatible = "qcom,msm-qgic2";
+ reg = <0xf9000000 0x1000>,
+ <0xf9002000 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ gcc: clock-controller@fc400000 {
+ compatible = "qcom,gcc-msm8226";
+ reg = <0xfc400000 0x4000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ tlmm: pinctrl@fd510000 {
+ compatible = "qcom,msm8226-pinctrl";
+ reg = <0xfd510000 0x4000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 117>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ blsp1_uart3: serial@f991f000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0xf991f000 0x1000>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_UART3_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ status = "disabled";
+ };
+
+ restart@fc4ab000 {
+ compatible = "qcom,pshold";
+ reg = <0xfc4ab000 0x4>;
+ };
+
+ rng@f9bff000 {
+ compatible = "qcom,prng";
+ reg = <0xf9bff000 0x200>;
+ clocks = <&gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "core";
+ };
+
+ timer@f9020000 {
+ compatible = "arm,armv7-timer-mem";
+ reg = <0xf9020000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ frame@f9021000 {
+ frame-number = <0>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0xf9021000 0x1000>,
+ <0xf9022000 0x1000>;
+ };
+
+ frame@f9023000 {
+ frame-number = <1>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0xf9023000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9024000 {
+ frame-number = <2>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0xf9024000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9025000 {
+ frame-number = <3>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0xf9025000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9026000 {
+ frame-number = <4>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0xf9026000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9027000 {
+ frame-number = <5>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0xf9027000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9028000 {
+ frame-number = <6>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0xf9028000 0x1000>;
+ status = "disabled";
+ };
+ };
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 2
+ (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3
+ (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 4
+ (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 1
+ (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-msm8974-samsung-klte.dts b/arch/arm/boot/dts/qcom-msm8974-samsung-klte.dts
index d737de7173cf..003f0fa9c857 100644
--- a/arch/arm/boot/dts/qcom-msm8974-samsung-klte.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-samsung-klte.dts
@@ -315,6 +315,10 @@
};
/delete-node/ vreg-boost;
+
+ adsp-pil {
+ cx-supply = <&pma8084_s2>;
+ };
};
&soc {
@@ -831,6 +835,13 @@
vddio-supply = <&pma8084_l12>;
};
};
+
+ remoteproc@fc880000 {
+ cx-supply = <&pma8084_s2>;
+ mss-supply = <&pma8084_s6>;
+ mx-supply = <&pma8084_s1>;
+ pll-supply = <&pma8084_l12>;
+ };
};
&spmi_bus {
diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-castor.dts b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-castor.dts
index f4ec08f13003..b4dd85bd4faf 100644
--- a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-castor.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-castor.dts
@@ -11,6 +11,7 @@
aliases {
serial0 = &blsp1_uart2;
+ serial1 = &blsp2_uart7;
};
chosen {
@@ -336,6 +337,27 @@
pinctrl-0 = <&blsp1_uart2_pin_a>;
};
+ serial@f995d000 {
+ status = "ok";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&blsp2_uart7_pin_a>;
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ max-speed = <3000000>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_host_wake_pin>,
+ <&bt_dev_wake_pin>,
+ <&bt_reg_on_pin>;
+
+ host-wakeup-gpios = <&msmgpio 95 GPIO_ACTIVE_HIGH>;
+ device-wakeup-gpios = <&msmgpio 96 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&pm8941_gpios 16 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
usb@f9a55000 {
status = "okay";
@@ -380,6 +402,40 @@
};
};
+ blsp2_uart7_pin_a: blsp2-uart7-pin-active {
+ tx {
+ pins = "gpio41";
+ function = "blsp_uart7";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio42";
+ function = "blsp_uart7";
+
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cts {
+ pins = "gpio43";
+ function = "blsp_uart7";
+
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ rts {
+ pins = "gpio44";
+ function = "blsp_uart7";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
i2c8_pins: i2c8 {
mux {
pins = "gpio47", "gpio48";
@@ -479,6 +535,23 @@
input-enable;
};
};
+
+ bt_host_wake_pin: bt-host-wake {
+ pins = "gpio95";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+
+ bt_dev_wake_pin: bt-dev-wake {
+ pins = "gpio96";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
};
i2c@f9964000 {
@@ -606,6 +679,14 @@
power-source = <PM8941_GPIO_S3>;
};
+ bt_reg_on_pin: bt-reg-on {
+ pins = "gpio16";
+ function = "normal";
+
+ output-low;
+ power-source = <PM8941_GPIO_S3>;
+ };
+
wlan_sleep_clk_pin: wl-sleep-clk {
pins = "gpio17";
function = "func2";
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index db4c06bf7888..78ec496d5bc3 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -715,6 +715,15 @@
status = "disabled";
};
+ blsp2_uart7: serial@f995d000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0xf995d000 0x1000>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_NONE>;
+ clocks = <&gcc GCC_BLSP2_UART1_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
+ clock-names = "core", "iface";
+ status = "disabled";
+ };
+
blsp2_uart8: serial@f995e000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0xf995e000 0x1000>;
diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom-sdx55.dtsi
index 0057c7c04d31..1e6ce035f76a 100644
--- a/arch/arm/boot/dts/qcom-sdx55.dtsi
+++ b/arch/arm/boot/dts/qcom-sdx55.dtsi
@@ -143,7 +143,7 @@
reg = <0x8ff00000 0x100000>;
};
- tz_apps_mem: memory@0x90000000 {
+ tz_apps_mem: memory@90000000 {
no-map;
reg = <0x90000000 0x500000>;
};
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index 45cf75b5824c..b07b71307f24 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -608,6 +608,8 @@
<GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
clocks = <&mstp9_clks R7S72100_CLK_I2C0>;
clock-frequency = <100000>;
power-domains = <&cpg_clocks>;
@@ -627,6 +629,8 @@
<GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
clocks = <&mstp9_clks R7S72100_CLK_I2C1>;
clock-frequency = <100000>;
power-domains = <&cpg_clocks>;
@@ -646,6 +650,8 @@
<GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
clocks = <&mstp9_clks R7S72100_CLK_I2C2>;
clock-frequency = <100000>;
power-domains = <&cpg_clocks>;
@@ -665,6 +671,8 @@
<GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
clocks = <&mstp9_clks R7S72100_CLK_I2C3>;
clock-frequency = <100000>;
power-domains = <&cpg_clocks>;
diff --git a/arch/arm/boot/dts/r7s9210.dtsi b/arch/arm/boot/dts/r7s9210.dtsi
index 85c0399b1339..fdeb0bc12cb7 100644
--- a/arch/arm/boot/dts/r7s9210.dtsi
+++ b/arch/arm/boot/dts/r7s9210.dtsi
@@ -236,6 +236,8 @@
<GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
clocks = <&cpg CPG_MOD 87>;
power-domains = <&cpg>;
clock-frequency = <100000>;
@@ -255,6 +257,8 @@
<GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
clocks = <&cpg CPG_MOD 86>;
power-domains = <&cpg>;
clock-frequency = <100000>;
@@ -274,6 +278,8 @@
<GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
clocks = <&cpg CPG_MOD 85>;
power-domains = <&cpg>;
clock-frequency = <100000>;
@@ -293,6 +299,8 @@
<GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
clocks = <&cpg CPG_MOD 84>;
power-domains = <&cpg>;
clock-frequency = <100000>;
diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi
index e5fb1ce261f7..c39066967053 100644
--- a/arch/arm/boot/dts/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/r8a73a4.dtsi
@@ -72,50 +72,6 @@
power-domains = <&pd_a3bc>;
};
- dmac: dma-multiplexer {
- compatible = "renesas,shdma-mux";
- #dma-cells = <1>;
- dma-channels = <20>;
- dma-requests = <256>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- dma0: dma-controller@e6700020 {
- compatible = "renesas,shdma-r8a73a4";
- reg = <0 0xe6700020 0 0x89e0>;
- interrupts = <GIC_SPI 220 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>,
- <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>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15",
- "ch16", "ch17", "ch18", "ch19";
- clocks = <&mstp2_clks R8A73A4_CLK_DMAC>;
- power-domains = <&pd_a3sp>;
- };
- };
-
i2c5: i2c@e60b0000 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/r8a7742.dtsi b/arch/arm/boot/dts/r8a7742.dtsi
index a2279686ffcc..420e0b3259d4 100644
--- a/arch/arm/boot/dts/r8a7742.dtsi
+++ b/arch/arm/boot/dts/r8a7742.dtsi
@@ -602,7 +602,9 @@
iic3: i2c@e60b0000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "renesas,iic-r8a7742";
+ compatible = "renesas,iic-r8a7742",
+ "renesas,rcar-gen2-iic",
+ "renesas,rmobile-iic";
reg = <0 0xe60b0000 0 0x425>;
interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 926>;
diff --git a/arch/arm/boot/dts/r8a7743.dtsi b/arch/arm/boot/dts/r8a7743.dtsi
index 7e5e09d210ec..3502b5dcc04f 100644
--- a/arch/arm/boot/dts/r8a7743.dtsi
+++ b/arch/arm/boot/dts/r8a7743.dtsi
@@ -552,7 +552,9 @@
/* doesn't need pinmux */
#address-cells = <1>;
#size-cells = <0>;
- compatible = "renesas,iic-r8a7743";
+ compatible = "renesas,iic-r8a7743",
+ "renesas,rcar-gen2-iic",
+ "renesas,rmobile-iic";
reg = <0 0xe60b0000 0 0x425>;
interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 926>;
diff --git a/arch/arm/boot/dts/r8a7744.dtsi b/arch/arm/boot/dts/r8a7744.dtsi
index 8419683a9d83..f5d4b8b85b6d 100644
--- a/arch/arm/boot/dts/r8a7744.dtsi
+++ b/arch/arm/boot/dts/r8a7744.dtsi
@@ -552,7 +552,9 @@
/* doesn't need pinmux */
#address-cells = <1>;
#size-cells = <0>;
- compatible = "renesas,iic-r8a7744";
+ compatible = "renesas,iic-r8a7744",
+ "renesas,rcar-gen2-iic",
+ "renesas,rmobile-iic";
reg = <0 0xe60b0000 0 0x425>;
interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 926>;
diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index f5a665b5d209..ae4055428c5e 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -218,7 +218,7 @@
};
timer2: timer@2000e000 {
- compatible = "snps,dw-apb-timer-osc";
+ compatible = "snps,dw-apb-timer";
reg = <0x2000e000 0x100>;
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_TIMER2>, <&cru PCLK_TIMER2>;
@@ -239,7 +239,7 @@
};
timer0: timer@20038000 {
- compatible = "snps,dw-apb-timer-osc";
+ compatible = "snps,dw-apb-timer";
reg = <0x20038000 0x100>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_TIMER0>, <&cru PCLK_TIMER0>;
@@ -247,7 +247,7 @@
};
timer1: timer@2003a000 {
- compatible = "snps,dw-apb-timer-osc";
+ compatible = "snps,dw-apb-timer";
reg = <0x2003a000 0x100>;
interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_TIMER1>, <&cru PCLK_TIMER1>;
@@ -351,11 +351,11 @@
#interrupt-cells = <2>;
};
- pcfg_pull_default: pcfg_pull_default {
+ pcfg_pull_default: pcfg-pull-default {
bias-pull-pin-default;
};
- pcfg_pull_none: pcfg_pull_none {
+ pcfg_pull_none: pcfg-pull-none {
bias-disable;
};
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 793a1b9117fe..2c606494b78c 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -275,15 +275,15 @@
#interrupt-cells = <2>;
};
- pcfg_pull_up: pcfg_pull_up {
+ pcfg_pull_up: pcfg-pull-up {
bias-pull-up;
};
- pcfg_pull_down: pcfg_pull_down {
+ pcfg_pull_down: pcfg-pull-down {
bias-pull-down;
};
- pcfg_pull_none: pcfg_pull_none {
+ pcfg_pull_none: pcfg-pull-none {
bias-disable;
};
@@ -638,9 +638,14 @@
power-domains = <&power RK3188_PD_GPU>;
};
-&grf{
+&grf {
compatible = "rockchip,rk3188-grf", "syscon", "simple-mfd";
+ io_domains: io-domains {
+ compatible = "rockchip,rk3188-io-voltage-domain";
+ status = "disabled";
+ };
+
usbphy: usbphy {
compatible = "rockchip,rk3188-usb-phy",
"rockchip,rk3288-usb-phy";
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 9c5a7791a1ab..4dcdcf17c977 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -987,7 +987,6 @@
compatible = "rockchip,iommu";
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>;
@@ -998,7 +997,6 @@
compatible = "rockchip,iommu";
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>;
@@ -1059,7 +1057,6 @@
compatible = "rockchip,iommu";
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>;
@@ -1109,7 +1106,6 @@
compatible = "rockchip,iommu";
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>;
@@ -1252,7 +1248,6 @@
compatible = "rockchip,iommu";
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>;
@@ -1263,7 +1258,6 @@
compatible = "rockchip,iommu";
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>;
diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rv1108.dtsi
index 9bd0acf3b708..24d56849af46 100644
--- a/arch/arm/boot/dts/rv1108.dtsi
+++ b/arch/arm/boot/dts/rv1108.dtsi
@@ -265,6 +265,11 @@
#address-cells = <1>;
#size-cells = <1>;
+ io_domains: io-domains {
+ compatible = "rockchip,rv1108-io-voltage-domain";
+ status = "disabled";
+ };
+
u2phy: usb2phy@100 {
compatible = "rockchip,rv1108-usb2phy";
reg = <0x100 0x0c>;
@@ -434,8 +439,13 @@
};
pmugrf: syscon@20060000 {
- compatible = "rockchip,rv1108-pmugrf", "syscon";
+ compatible = "rockchip,rv1108-pmugrf", "syscon", "simple-mfd";
reg = <0x20060000 0x1000>;
+
+ pmu_io_domains: io-domains {
+ compatible = "rockchip,rv1108-pmu-io-voltage-domain";
+ status = "disabled";
+ };
};
usbgrf: syscon@202a0000 {
@@ -536,6 +546,17 @@
status = "disabled";
};
+ sfc: spi@301c0000 {
+ compatible = "rockchip,sfc";
+ reg = <0x301c0000 0x4000>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
+ clock-names = "clk_sfc", "hclk_sfc";
+ pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus4>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
gmac: eth@30200000 {
compatible = "rockchip,rv1108-gmac";
reg = <0x30200000 0x10000>;
@@ -704,6 +725,32 @@
};
};
+ sfc {
+ sfc_bus4: sfc-bus4 {
+ rockchip,pins =
+ <2 RK_PA0 3 &pcfg_pull_none>,
+ <2 RK_PA1 3 &pcfg_pull_none>,
+ <2 RK_PA2 3 &pcfg_pull_none>,
+ <2 RK_PA3 3 &pcfg_pull_none>;
+ };
+
+ sfc_bus2: sfc-bus2 {
+ rockchip,pins =
+ <2 RK_PA0 3 &pcfg_pull_none>,
+ <2 RK_PA1 3 &pcfg_pull_none>;
+ };
+
+ sfc_cs0: sfc-cs0 {
+ rockchip,pins =
+ <2 RK_PB4 3 &pcfg_pull_none>;
+ };
+
+ sfc_clk: sfc-clk {
+ rockchip,pins =
+ <2 RK_PB7 2 &pcfg_pull_none>;
+ };
+ };
+
gmac {
rmii_pins: rmii-pins {
rockchip,pins = <1 RK_PC5 2 &pcfg_pull_none>,
diff --git a/arch/arm/boot/dts/sama7g5-pinfunc.h b/arch/arm/boot/dts/sama7g5-pinfunc.h
new file mode 100644
index 000000000000..22fe9e522a97
--- /dev/null
+++ b/arch/arm/boot/dts/sama7g5-pinfunc.h
@@ -0,0 +1,923 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+#define PINMUX_PIN(no, func, ioset) \
+(((no) & 0xffff) | (((func) & 0xf) << 16) | (((ioset) & 0xff) << 20))
+
+#define PIN_PA0 0
+#define PIN_PA0__GPIO PINMUX_PIN(PIN_PA0, 0, 0)
+#define PIN_PA0__SDMMC0_CK PINMUX_PIN(PIN_PA0, 1, 1)
+#define PIN_PA0__FLEXCOM0_IO0 PINMUX_PIN(PIN_PA0, 2, 1)
+#define PIN_PA0__CANTX3 PINMUX_PIN(PIN_PA0, 3, 1)
+#define PIN_PA0__PWML0 PINMUX_PIN(PIN_PA0, 5, 2)
+#define PIN_PA1 1
+#define PIN_PA1__GPIO PINMUX_PIN(PIN_PA1, 0, 0)
+#define PIN_PA1__SDMMC0_CMD PINMUX_PIN(PIN_PA1, 1, 1)
+#define PIN_PA1__FLEXCOM0_IO1 PINMUX_PIN(PIN_PA1, 2, 1)
+#define PIN_PA1__CANRX3 PINMUX_PIN(PIN_PA1, 3, 1)
+#define PIN_PA1__D14 PINMUX_PIN(PIN_PA1, 4, 1)
+#define PIN_PA1__PWMH0 PINMUX_PIN(PIN_PA1, 5, 3)
+#define PIN_PA2 2
+#define PIN_PA2__GPIO PINMUX_PIN(PIN_PA2, 0, 0)
+#define PIN_PA2__SDMMC0_RSTN PINMUX_PIN(PIN_PA2, 1, 1)
+#define PIN_PA2__FLEXCOM0_IO2 PINMUX_PIN(PIN_PA2, 2, 1)
+#define PIN_PA2__PDMC1_CLK PINMUX_PIN(PIN_PA2, 3, 1)
+#define PIN_PA2__D15 PINMUX_PIN(PIN_PA2, 4, 1)
+#define PIN_PA2__PWMH1 PINMUX_PIN(PIN_PA2, 5, 3)
+#define PIN_PA2__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA2, 6, 3)
+#define PIN_PA3 3
+#define PIN_PA3__GPIO PINMUX_PIN(PIN_PA3, 0, 0)
+#define PIN_PA3__SDMMC0_DAT0 PINMUX_PIN(PIN_PA3, 1, 1)
+#define PIN_PA3__FLEXCOM0_IO3 PINMUX_PIN(PIN_PA3, 2, 1)
+#define PIN_PA3__PDMC1_DS0 PINMUX_PIN(PIN_PA3, 3, 1)
+#define PIN_PA3__NWR1_NBS1 PINMUX_PIN(PIN_PA3, 4, 1)
+#define PIN_PA3__PWML3 PINMUX_PIN(PIN_PA3, 5, 3)
+#define PIN_PA3__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA3, 6, 3)
+#define PIN_PA4 4
+#define PIN_PA4__GPIO PINMUX_PIN(PIN_PA4, 0, 0)
+#define PIN_PA4__SDMMC0_DAT1 PINMUX_PIN(PIN_PA4, 1, 1)
+#define PIN_PA4__FLEXCOM0_IO4 PINMUX_PIN(PIN_PA4, 2, 1)
+#define PIN_PA4__PDMC1_DS1 PINMUX_PIN(PIN_PA4, 3, 1)
+#define PIN_PA4__NCS2 PINMUX_PIN(PIN_PA4, 4, 1)
+#define PIN_PA4__PWMH3 PINMUX_PIN(PIN_PA4, 5, 3)
+#define PIN_PA4__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA4, 6, 3)
+#define PIN_PA5 5
+#define PIN_PA5__GPIO PINMUX_PIN(PIN_PA5, 0, 0)
+#define PIN_PA5__SDMMC0_DAT2 PINMUX_PIN(PIN_PA5, 1, 1)
+#define PIN_PA5__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA5, 2, 1)
+#define PIN_PA5__CANTX2 PINMUX_PIN(PIN_PA5, 3, 1)
+#define PIN_PA5__A23 PINMUX_PIN(PIN_PA5, 4, 1)
+#define PIN_PA5__PWMEXTRG0 PINMUX_PIN(PIN_PA5, 5, 3)
+#define PIN_PA5__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA5, 6, 3)
+#define PIN_PA6 6
+#define PIN_PA6__GPIO PINMUX_PIN(PIN_PA6, 0, 0)
+#define PIN_PA6__SDMMC0_DAT3 PINMUX_PIN(PIN_PA6, 1, 1)
+#define PIN_PA6__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA6, 2, 1)
+#define PIN_PA6__CANRX2 PINMUX_PIN(PIN_PA6, 3, 1)
+#define PIN_PA6__A24 PINMUX_PIN(PIN_PA6, 4, 1)
+#define PIN_PA6__PWMEXTRG1 PINMUX_PIN(PIN_PA6, 5, 3)
+#define PIN_PA6__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA6, 6, 3)
+#define PIN_PA7 7
+#define PIN_PA7__GPIO PINMUX_PIN(PIN_PA7, 0, 0)
+#define PIN_PA7__SDMMC0_DAT4 PINMUX_PIN(PIN_PA7, 1, 1)
+#define PIN_PA7__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA7, 2, 1)
+#define PIN_PA7__CANTX1 PINMUX_PIN(PIN_PA7, 3, 1)
+#define PIN_PA7__NWAIT PINMUX_PIN(PIN_PA7, 4, 1)
+#define PIN_PA7__PWMFI0 PINMUX_PIN(PIN_PA7, 5, 3)
+#define PIN_PA7__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA7, 6, 3)
+#define PIN_PA8 8
+#define PIN_PA8__GPIO PINMUX_PIN(PIN_PA8, 0, 0)
+#define PIN_PA8__SDMMC0_DAT5 PINMUX_PIN(PIN_PA8, 1, 1)
+#define PIN_PA8__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA8, 2, 1)
+#define PIN_PA8__CANRX1 PINMUX_PIN(PIN_PA8, 3, 1)
+#define PIN_PA8__NCS0 PINMUX_PIN(PIN_PA8, 4, 1)
+#define PIN_PA8__PWMIF1 PINMUX_PIN(PIN_PA8, 5, 3)
+#define PIN_PA8__FLEXCOM4_IO0 PINMUX_PIN(PIN_PA8, 6, 3)
+#define PIN_PA9 9
+#define PIN_PA9__GPIO PINMUX_PIN(PIN_PA9, 0, 0)
+#define PIN_PA9__SDMMC0_DAT6 PINMUX_PIN(PIN_PA9, 1, 1)
+#define PIN_PA9__FLEXCOM2_IO2 PINMUX_PIN(PIN_PA9, 2, 1)
+#define PIN_PA9__CANTX0 PINMUX_PIN(PIN_PA9, 3, 1)
+#define PIN_PA9__SMCK PINMUX_PIN(PIN_PA9, 4, 1)
+#define PIN_PA9__SPDIF_RX PINMUX_PIN(PIN_PA9, 5, 1)
+#define PIN_PA9__FLEXCOM4_IO1 PINMUX_PIN(PIN_PA9, 6, 3)
+#define PIN_PA10 10
+#define PIN_PA10__GPIO PINMUX_PIN(PIN_PA10, 0, 0)
+#define PIN_PA10__SDMMC0_DAT7 PINMUX_PIN(PIN_PA10, 1, 1)
+#define PIN_PA10__FLEXCOM2_IO3 PINMUX_PIN(PIN_PA10, 2, 1)
+#define PIN_PA10__CANRX0 PINMUX_PIN(PIN_PA10, 3, 1)
+#define PIN_PA10__NCS1 PINMUX_PIN(PIN_PA10, 4, 1)
+#define PIN_PA10__SPDIF_TX PINMUX_PIN(PIN_PA10, 5, 1)
+#define PIN_PA10__FLEXCOM5_IO0 PINMUX_PIN(PIN_PA10, 6, 3)
+#define PIN_PA11 11
+#define PIN_PA11__GPIO PINMUX_PIN(PIN_PA11, 0, 0)
+#define PIN_PA11__SDMMC0_DS PINMUX_PIN(PIN_PA11, 1, 1)
+#define PIN_PA11__FLEXCOM2_IO4 PINMUX_PIN(PIN_PA11, 2, 1)
+#define PIN_PA11__A0_NBS0 PINMUX_PIN(PIN_PA11, 4, 1)
+#define PIN_PA11__TIOA0 PINMUX_PIN(PIN_PA11, 5, 1)
+#define PIN_PA11__FLEXCOM5_IO1 PINMUX_PIN(PIN_PA11, 6, 3)
+#define PIN_PA12 12
+#define PIN_PA12__GPIO PINMUX_PIN(PIN_PA12, 0, 0)
+#define PIN_PA12__SDMMC0_WP PINMUX_PIN(PIN_PA12, 1, 1)
+#define PIN_PA12__FLEXCOM1_IO3 PINMUX_PIN(PIN_PA12, 2, 1)
+#define PIN_PA12__FLEXCOM3_IO5 PINMUX_PIN(PIN_PA12, 4, 1)
+#define PIN_PA12__PWML2 PINMUX_PIN(PIN_PA12, 5, 3)
+#define PIN_PA12__FLEXCOM6_IO0 PINMUX_PIN(PIN_PA12, 6, 3)
+#define PIN_PA13 13
+#define PIN_PA13__GPIO PINMUX_PIN(PIN_PA13, 0, 0)
+#define PIN_PA13__SDMMC0_1V8SEL PINMUX_PIN(PIN_PA13, 1, 1)
+#define PIN_PA13__FLEXCOM1_IO2 PINMUX_PIN(PIN_PA13, 2, 1)
+#define PIN_PA13__FLEXCOM3_IO6 PINMUX_PIN(PIN_PA13, 4, 1)
+#define PIN_PA13__PWMH2 PINMUX_PIN(PIN_PA13, 5, 3)
+#define PIN_PA13__FLEXCOM6_IO1 PINMUX_PIN(PIN_PA13, 6, 3)
+#define PIN_PA14 14
+#define PIN_PA14__GPIO PINMUX_PIN(PIN_PA14, 0, 0)
+#define PIN_PA14__SDMMC0_CD PINMUX_PIN(PIN_PA14, 1, 1)
+#define PIN_PA14__FLEXCOM1_IO4 PINMUX_PIN(PIN_PA14, 2, 1)
+#define PIN_PA14__A25 PINMUX_PIN(PIN_PA14, 4, 1)
+#define PIN_PA14__PWML1 PINMUX_PIN(PIN_PA14, 5, 3)
+#define PIN_PA15 15
+#define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0)
+#define PIN_PA15__G0_TXEN PINMUX_PIN(PIN_PA15, 1, 1)
+#define PIN_PA15__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA15, 2, 1)
+#define PIN_PA15__ISC_MCK PINMUX_PIN(PIN_PA15, 3, 1)
+#define PIN_PA15__A1 PINMUX_PIN(PIN_PA15, 4, 1)
+#define PIN_PA15__TIOB0 PINMUX_PIN(PIN_PA15, 5, 1)
+#define PIN_PA16 16
+#define PIN_PA16__GPIO PINMUX_PIN(PIN_PA16, 0, 0)
+#define PIN_PA16__G0_TX0 PINMUX_PIN(PIN_PA16, 1, 1)
+#define PIN_PA16__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA16, 2, 1)
+#define PIN_PA16__ISC_D0 PINMUX_PIN(PIN_PA16, 3, 1)
+#define PIN_PA16__A2 PINMUX_PIN(PIN_PA16, 4, 1)
+#define PIN_PA16__TCLK0 PINMUX_PIN(PIN_PA16, 5, 1)
+#define PIN_PA17 17
+#define PIN_PA17__GPIO PINMUX_PIN(PIN_PA17, 0, 0)
+#define PIN_PA17__G0_TX1 PINMUX_PIN(PIN_PA17, 1, 1)
+#define PIN_PA17__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA17, 2, 1)
+#define PIN_PA17__ISC_D1 PINMUX_PIN(PIN_PA17, 3, 1)
+#define PIN_PA17__A3 PINMUX_PIN(PIN_PA17, 4, 1)
+#define PIN_PA17__TIOA1 PINMUX_PIN(PIN_PA17, 5, 1)
+#define PIN_PA18 18
+#define PIN_PA18__GPIO PINMUX_PIN(PIN_PA18, 0, 0)
+#define PIN_PA18__G0_RXDV PINMUX_PIN(PIN_PA18, 1, 1)
+#define PIN_PA18__FLEXCOM3_IO3 PINMUX_PIN(PIN_PA18, 2, 1)
+#define PIN_PA18__ISC_D2 PINMUX_PIN(PIN_PA18, 3, 1)
+#define PIN_PA18__A4 PINMUX_PIN(PIN_PA18, 4, 1)
+#define PIN_PA18__TIOB1 PINMUX_PIN(PIN_PA18, 5, 1)
+#define PIN_PA19 19
+#define PIN_PA19__GPIO PINMUX_PIN(PIN_PA19, 0, 0)
+#define PIN_PA19__G0_RX0 PINMUX_PIN(PIN_PA19, 1, 1)
+#define PIN_PA19__FLEXCOM3_IO4 PINMUX_PIN(PIN_PA19, 2, 1)
+#define PIN_PA19__ISC_D3 PINMUX_PIN(PIN_PA19, 3, 1)
+#define PIN_PA19__A5 PINMUX_PIN(PIN_PA19, 4, 1)
+#define PIN_PA19__TCLK1 PINMUX_PIN(PIN_PA19, 5, 1)
+#define PIN_PA20 20
+#define PIN_PA20__GPIO PINMUX_PIN(PIN_PA20, 0, 0)
+#define PIN_PA20__G0_RX1 PINMUX_PIN(PIN_PA20, 1, 1)
+#define PIN_PA20__FLEXCOM4_IO0 PINMUX_PIN(PIN_PA20, 2, 1)
+#define PIN_PA20__ISC_D4 PINMUX_PIN(PIN_PA20, 3, 1)
+#define PIN_PA20__A6 PINMUX_PIN(PIN_PA20, 4, 1)
+#define PIN_PA20__TIOA2 PINMUX_PIN(PIN_PA20, 5, 1)
+#define PIN_PA21 21
+#define PIN_PA21__GPIO PINMUX_PIN(PIN_PA21, 0, 0)
+#define PIN_PA21__G0_RXER PINMUX_PIN(PIN_PA21, 1, 1)
+#define PIN_PA21__FLEXCOM4_IO1 PINMUX_PIN(PIN_PA21, 2, 1)
+#define PIN_PA21__ISC_D5 PINMUX_PIN(PIN_PA21, 3, 1)
+#define PIN_PA21__A7 PINMUX_PIN(PIN_PA21, 4, 1)
+#define PIN_PA21__TIOB2 PINMUX_PIN(PIN_PA21, 5, 1)
+#define PIN_PA22 22
+#define PIN_PA22__GPIO PINMUX_PIN(PIN_PA22, 0, 0)
+#define PIN_PA22__G0_MDC PINMUX_PIN(PIN_PA22, 1, 1)
+#define PIN_PA22__FLEXCOM4_IO2 PINMUX_PIN(PIN_PA22, 2, 1)
+#define PIN_PA22__ISC_D6 PINMUX_PIN(PIN_PA22, 3, 1)
+#define PIN_PA22__A8 PINMUX_PIN(PIN_PA22, 4, 1)
+#define PIN_PA22__TCLK2 PINMUX_PIN(PIN_PA22, 5, 1)
+#define PIN_PA23 23
+#define PIN_PA23__GPIO PINMUX_PIN(PIN_PA23, 0, 0)
+#define PIN_PA23__G0_MDIO PINMUX_PIN(PIN_PA23, 1, 1)
+#define PIN_PA23__FLEXCOM4_IO3 PINMUX_PIN(PIN_PA23, 2, 1)
+#define PIN_PA23__ISC_D7 PINMUX_PIN(PIN_PA23, 3, 1)
+#define PIN_PA23__A9 PINMUX_PIN(PIN_PA23, 4, 1)
+#define PIN_PA24 24
+#define PIN_PA24__GPIO PINMUX_PIN(PIN_PA24, 0, 0)
+#define PIN_PA24__G0_TXCK PINMUX_PIN(PIN_PA24, 1, 1)
+#define PIN_PA24__FLEXCOM4_IO4 PINMUX_PIN(PIN_PA24, 2, 1)
+#define PIN_PA24__ISC_HSYNC PINMUX_PIN(PIN_PA24, 3, 1)
+#define PIN_PA24__A10 PINMUX_PIN(PIN_PA24, 4, 1)
+#define PIN_PA24__FLEXCOM0_IO5 PINMUX_PIN(PIN_PA24, 5, 1)
+#define PIN_PA25 25
+#define PIN_PA25__GPIO PINMUX_PIN(PIN_PA25, 0, 0)
+#define PIN_PA25__G0_125CK PINMUX_PIN(PIN_PA25, 1, 1)
+#define PIN_PA25__FLEXCOM5_IO4 PINMUX_PIN(PIN_PA25, 2, 1)
+#define PIN_PA25__ISC_VSYNC PINMUX_PIN(PIN_PA25, 3, 1)
+#define PIN_PA25__A11 PINMUX_PIN(PIN_PA25, 4, 1)
+#define PIN_PA25__FLEXCOM0_IO6 PINMUX_PIN(PIN_PA25, 5, 1)
+#define PIN_PA25__FLEXCOM7_IO0 PINMUX_PIN(PIN_PA25, 6, 3)
+#define PIN_PA26 26
+#define PIN_PA26__GPIO PINMUX_PIN(PIN_PA26, 0, 0)
+#define PIN_PA26__G0_TX2 PINMUX_PIN(PIN_PA26, 1, 1)
+#define PIN_PA26__FLEXCOM5_IO2 PINMUX_PIN(PIN_PA26, 2, 1)
+#define PIN_PA26__ISC_FIELD PINMUX_PIN(PIN_PA26, 3, 1)
+#define PIN_PA26__A12 PINMUX_PIN(PIN_PA26, 4, 1)
+#define PIN_PA26__TF0 PINMUX_PIN(PIN_PA26, 5, 1)
+#define PIN_PA26__FLEXCOM7_IO1 PINMUX_PIN(PIN_PA26, 6, 3)
+#define PIN_PA27 27
+#define PIN_PA27__GPIO PINMUX_PIN(PIN_PA27, 0, 0)
+#define PIN_PA27__G0_TX3 PINMUX_PIN(PIN_PA27, 1, 1)
+#define PIN_PA27__FLEXCOM5_IO3 PINMUX_PIN(PIN_PA27, 2, 1)
+#define PIN_PA27__ISC_PCK PINMUX_PIN(PIN_PA27, 3, 1)
+#define PIN_PA27__A13 PINMUX_PIN(PIN_PA27, 4, 1)
+#define PIN_PA27__TK0 PINMUX_PIN(PIN_PA27, 5, 1)
+#define PIN_PA27__FLEXCOM8_IO0 PINMUX_PIN(PIN_PA27, 6, 3)
+#define PIN_PA28 28
+#define PIN_PA28__GPIO PINMUX_PIN(PIN_PA28, 0, 0)
+#define PIN_PA28__G0_RX2 PINMUX_PIN(PIN_PA28, 1, 1)
+#define PIN_PA28__FLEXCOM5_IO0 PINMUX_PIN(PIN_PA28, 2, 1)
+#define PIN_PA28__ISC_D8 PINMUX_PIN(PIN_PA28, 3, 1)
+#define PIN_PA28__A14 PINMUX_PIN(PIN_PA28, 4, 1)
+#define PIN_PA28__RD0 PINMUX_PIN(PIN_PA28, 5, 1)
+#define PIN_PA28__FLEXCOM8_IO1 PINMUX_PIN(PIN_PA28, 6, 3)
+#define PIN_PA29 29
+#define PIN_PA29__GPIO PINMUX_PIN(PIN_PA29, 0, 0)
+#define PIN_PA29__G0_RX3 PINMUX_PIN(PIN_PA29, 1, 1)
+#define PIN_PA29__FLEXCOM5_IO1 PINMUX_PIN(PIN_PA29, 2, 1)
+#define PIN_PA29__ISC_D9 PINMUX_PIN(PIN_PA29, 3, 1)
+#define PIN_PA29__A15 PINMUX_PIN(PIN_PA29, 4, 1)
+#define PIN_PA29__RF0 PINMUX_PIN(PIN_PA29, 5, 1)
+#define PIN_PA29__FLEXCOM9_IO0 PINMUX_PIN(PIN_PA29, 6, 3)
+#define PIN_PA30 30
+#define PIN_PA30__GPIO PINMUX_PIN(PIN_PA30, 0, 0)
+#define PIN_PA30__G0_RXCK PINMUX_PIN(PIN_PA30, 1, 1)
+#define PIN_PA30__FLEXCOM6_IO4 PINMUX_PIN(PIN_PA30, 2, 1)
+#define PIN_PA30__ISC_D10 PINMUX_PIN(PIN_PA30, 3, 1)
+#define PIN_PA30__A16 PINMUX_PIN(PIN_PA30, 4, 1)
+#define PIN_PA30__RK0 PINMUX_PIN(PIN_PA30, 5, 1)
+#define PIN_PA30__FLEXCOM9_IO1 PINMUX_PIN(PIN_PA30, 6, 3)
+#define PIN_PA31 31
+#define PIN_PA31__GPIO PINMUX_PIN(PIN_PA31, 0, 0)
+#define PIN_PA31__G0_TXER PINMUX_PIN(PIN_PA31, 1, 1)
+#define PIN_PA31__FLEXCOM6_IO2 PINMUX_PIN(PIN_PA31, 2, 1)
+#define PIN_PA31__ISC_D11 PINMUX_PIN(PIN_PA31, 3, 1)
+#define PIN_PA31__A17 PINMUX_PIN(PIN_PA31, 4, 1)
+#define PIN_PA31__TD0 PINMUX_PIN(PIN_PA31, 5, 1)
+#define PIN_PA31__FLEXCOM10_IO0 PINMUX_PIN(PIN_PA31, 6, 3)
+#define PIN_PB0 32
+#define PIN_PB0__GPIO PINMUX_PIN(PIN_PB0, 0, 0)
+#define PIN_PB0__G0_COL PINMUX_PIN(PIN_PB0, 1, 1)
+#define PIN_PB0__FLEXCOM6_IO3 PINMUX_PIN(PIN_PB0, 2, 2)
+#define PIN_PB0__EXT_IRQ0 PINMUX_PIN(PIN_PB0, 3, 1)
+#define PIN_PB0__A18 PINMUX_PIN(PIN_PB0, 4, 1)
+#define PIN_PB0__SPDIF_RX PINMUX_PIN(PIN_PB0, 5, 2)
+#define PIN_PB0__FLEXCOM10_IO1 PINMUX_PIN(PIN_PB0, 6, 3)
+#define PIN_PB1 33
+#define PIN_PB1__GPIO PINMUX_PIN(PIN_PB1, 0, 0)
+#define PIN_PB1__G0_CRS PINMUX_PIN(PIN_PB1, 1, 1)
+#define PIN_PB1__FLEXCOM6_IO1 PINMUX_PIN(PIN_PB1, 2, 2)
+#define PIN_PB1__EXT_IRQ1 PINMUX_PIN(PIN_PB1, 3, 1)
+#define PIN_PB1__A19 PINMUX_PIN(PIN_PB1, 4, 1)
+#define PIN_PB1__SPDIF_TX PINMUX_PIN(PIN_PB1, 5, 2)
+#define PIN_PB1__FLEXCOM11_IO0 PINMUX_PIN(PIN_PB1, 6, 3)
+#define PIN_PB2 34
+#define PIN_PB2__GPIO PINMUX_PIN(PIN_PB2, 0, 0)
+#define PIN_PB2__G0_TSUCOMP PINMUX_PIN(PIN_PB2, 1, 1)
+#define PIN_PB2__FLEXCOM6_IO0 PINMUX_PIN(PIN_PB2, 2, 1)
+#define PIN_PB2__ADTRG PINMUX_PIN(PIN_PB2, 3, 1)
+#define PIN_PB2__A20 PINMUX_PIN(PIN_PB2, 4, 1)
+#define PIN_PB2__FLEXCOM11_IO0 PINMUX_PIN(PIN_PB2, 6, 3)
+#define PIN_PB3 35
+#define PIN_PB3__GPIO PINMUX_PIN(PIN_PB3, 0, 0)
+#define PIN_PB3__RF1 PINMUX_PIN(PIN_PB3, 1, 1)
+#define PIN_PB3__FLEXCOM11_IO0 PINMUX_PIN(PIN_PB3, 2, 1)
+#define PIN_PB3__PCK2 PINMUX_PIN(PIN_PB3, 3, 2)
+#define PIN_PB3__D8 PINMUX_PIN(PIN_PB3, 4, 1)
+#define PIN_PB4 36
+#define PIN_PB4__GPIO PINMUX_PIN(PIN_PB4, 0, 0)
+#define PIN_PB4__TF1 PINMUX_PIN(PIN_PB4, 1, 1)
+#define PIN_PB4__FLEXCOM11_IO1 PINMUX_PIN(PIN_PB4, 2, 1)
+#define PIN_PB4__PCK3 PINMUX_PIN(PIN_PB4, 3, 2)
+#define PIN_PB4__D9 PINMUX_PIN(PIN_PB4, 4, 1)
+#define PIN_PB5 37
+#define PIN_PB5__GPIO PINMUX_PIN(PIN_PB5, 0, 0)
+#define PIN_PB5__TK1 PINMUX_PIN(PIN_PB5, 1, 1)
+#define PIN_PB5__FLEXCOM11_IO2 PINMUX_PIN(PIN_PB5, 2, 1)
+#define PIN_PB5__PCK4 PINMUX_PIN(PIN_PB5, 3, 2)
+#define PIN_PB5__D10 PINMUX_PIN(PIN_PB5, 4, 1)
+#define PIN_PB6 38
+#define PIN_PB6__GPIO PINMUX_PIN(PIN_PB6, 0, 0)
+#define PIN_PB6__RK1 PINMUX_PIN(PIN_PB6, 1, 1)
+#define PIN_PB6__FLEXCOM11_IO3 PINMUX_PIN(PIN_PB6, 2, 1)
+#define PIN_PB6__PCK5 PINMUX_PIN(PIN_PB6, 3, 2)
+#define PIN_PB6__D11 PINMUX_PIN(PIN_PB6, 4, 1)
+#define PIN_PB7 39
+#define PIN_PB7__GPIO PINMUX_PIN(PIN_PB7, 0, 0)
+#define PIN_PB7__TD1 PINMUX_PIN(PIN_PB7, 1, 1)
+#define PIN_PB7__FLEXCOM11_IO4 PINMUX_PIN(PIN_PB7, 2, 1)
+#define PIN_PB7__FLEXCOM3_IO5 PINMUX_PIN(PIN_PB7, 3, 2)
+#define PIN_PB7__D12 PINMUX_PIN(PIN_PB7, 4, 1)
+#define PIN_PB8 40
+#define PIN_PB8__GPIO PINMUX_PIN(PIN_PB8, 0, 0)
+#define PIN_PB8__RD1 PINMUX_PIN(PIN_PB8, 1, 1)
+#define PIN_PB8__FLEXCOM8_IO0 PINMUX_PIN(PIN_PB8, 2, 1)
+#define PIN_PB8__FLEXCOM3_IO6 PINMUX_PIN(PIN_PB8, 3, 2)
+#define PIN_PB8__D13 PINMUX_PIN(PIN_PB8, 4, 1)
+#define PIN_PB9 41
+#define PIN_PB9__GPIO PINMUX_PIN(PIN_PB9, 0, 0)
+#define PIN_PB9__QSPI0_IO3 PINMUX_PIN(PIN_PB9, 1, 1)
+#define PIN_PB9__FLEXCOM8_IO1 PINMUX_PIN(PIN_PB9, 2, 1)
+#define PIN_PB9__PDMC0_CLK PINMUX_PIN(PIN_PB9, 3, 1)
+#define PIN_PB9__NCS3_NANDCS PINMUX_PIN(PIN_PB9, 4, 1)
+#define PIN_PB9__PWML0 PINMUX_PIN(PIN_PB9, 5, 2)
+#define PIN_PB10 42
+#define PIN_PB10__GPIO PINMUX_PIN(PIN_PB10, 0, 0)
+#define PIN_PB10__QSPI0_IO2 PINMUX_PIN(PIN_PB10, 1, 1)
+#define PIN_PB10__FLEXCOM8_IO2 PINMUX_PIN(PIN_PB10, 2, 1)
+#define PIN_PB10__PDMC0_DS0 PINMUX_PIN(PIN_PB10, 3, 1)
+#define PIN_PB10__NWE_NWR0_NANDWE PINMUX_PIN(PIN_PB10, 4, 1)
+#define PIN_PB10__PWMH0 PINMUX_PIN(PIN_PB10, 5, 2)
+#define PIN_PB11 43
+#define PIN_PB11__GPIO PINMUX_PIN(PIN_PB11, 0, 0)
+#define PIN_PB11__QSPI0_IO1 PINMUX_PIN(PIN_PB11, 1, 1)
+#define PIN_PB11__FLEXCOM8_IO3 PINMUX_PIN(PIN_PB11, 2, 1)
+#define PIN_PB11__PDMC0_DS1 PINMUX_PIN(PIN_PB11, 3, 1)
+#define PIN_PB11__NRD_NANDOE PINMUX_PIN(PIN_PB11, 4, 1)
+#define PIN_PB11__PWML1 PINMUX_PIN(PIN_PB11, 5, 2)
+#define PIN_PB12 44
+#define PIN_PB12__GPIO PINMUX_PIN(PIN_PB12, 0, 0)
+#define PIN_PB12__QSPI0_IO0 PINMUX_PIN(PIN_PB12, 1, 1)
+#define PIN_PB12__FLEXCOM8_IO4 PINMUX_PIN(PIN_PB12, 2, 1)
+#define PIN_PB12__FLEXCOM6_IO5 PINMUX_PIN(PIN_PB12, 3, 1)
+#define PIN_PB12__A21_NANDALE PINMUX_PIN(PIN_PB12, 4, 1)
+#define PIN_PB12__PWMH1 PINMUX_PIN(PIN_PB12, 5, 2)
+#define PIN_PB13 45
+#define PIN_PB13__GPIO PINMUX_PIN(PIN_PB13, 0, 0)
+#define PIN_PB13__QSPI0_CS PINMUX_PIN(PIN_PB13, 1, 1)
+#define PIN_PB13__FLEXCOM9_IO0 PINMUX_PIN(PIN_PB13, 2, 1)
+#define PIN_PB13__FLEXCOM6_IO6 PINMUX_PIN(PIN_PB13, 3, 1)
+#define PIN_PB13__A22_NANDCLE PINMUX_PIN(PIN_PB13, 4, 1)
+#define PIN_PB13__PWML2 PINMUX_PIN(PIN_PB13, 5, 2)
+#define PIN_PB14 46
+#define PIN_PB14__GPIO PINMUX_PIN(PIN_PB14, 0, 0)
+#define PIN_PB14__QSPI0_SCK PINMUX_PIN(PIN_PB14, 1, 1)
+#define PIN_PB14__FLEXCOM9_IO1 PINMUX_PIN(PIN_PB14, 2, 1)
+#define PIN_PB14__D0 PINMUX_PIN(PIN_PB14, 4, 1)
+#define PIN_PB14__PWMH2 PINMUX_PIN(PIN_PB14, 5, 2)
+#define PIN_PB15 47
+#define PIN_PB15__GPIO PINMUX_PIN(PIN_PB15, 0, 0)
+#define PIN_PB15__QSPI0_SCKN PINMUX_PIN(PIN_PB15, 1, 1)
+#define PIN_PB15__FLEXCOM9_IO2 PINMUX_PIN(PIN_PB15, 2, 1)
+#define PIN_PB15__D1 PINMUX_PIN(PIN_PB15, 4, 1)
+#define PIN_PB15__PWML3 PINMUX_PIN(PIN_PB15, 5, 2)
+#define PIN_PB16 48
+#define PIN_PB16__GPIO PINMUX_PIN(PIN_PB16, 0, 0)
+#define PIN_PB16__QSPI0_IO4 PINMUX_PIN(PIN_PB16, 1, 1)
+#define PIN_PB16__FLEXCOM9_IO3 PINMUX_PIN(PIN_PB16, 2, 1)
+#define PIN_PB16__PCK0 PINMUX_PIN(PIN_PB16, 3, 1)
+#define PIN_PB16__D2 PINMUX_PIN(PIN_PB16, 4, 1)
+#define PIN_PB16__PWMH3 PINMUX_PIN(PIN_PB16, 5, 2)
+#define PIN_PB16__EXT_IRQ0 PINMUX_PIN(PIN_PB16, 6, 2)
+#define PIN_PB17 49
+#define PIN_PB17__GPIO PINMUX_PIN(PIN_PB17, 0, 0)
+#define PIN_PB17__QSPI0_IO5 PINMUX_PIN(PIN_PB17, 1, 1)
+#define PIN_PB17__FLEXCOM9_IO4 PINMUX_PIN(PIN_PB17, 2, 1)
+#define PIN_PB17__PCK1 PINMUX_PIN(PIN_PB17, 3, 1)
+#define PIN_PB17__D3 PINMUX_PIN(PIN_PB17, 4, 1)
+#define PIN_PB17__PWMEXTRG0 PINMUX_PIN(PIN_PB17, 5, 2)
+#define PIN_PB17__EXT_IRQ1 PINMUX_PIN(PIN_PB17, 6, 2)
+#define PIN_PB18 50
+#define PIN_PB18__GPIO PINMUX_PIN(PIN_PB18, 0, 0)
+#define PIN_PB18__QSPI0_IO6 PINMUX_PIN(PIN_PB18, 1, 1)
+#define PIN_PB18__FLEXCOM10_IO0 PINMUX_PIN(PIN_PB18, 2, 1)
+#define PIN_PB18__PCK2 PINMUX_PIN(PIN_PB18, 3, 1)
+#define PIN_PB18__D4 PINMUX_PIN(PIN_PB18, 4, 1)
+#define PIN_PB18__PWMEXTRG1 PINMUX_PIN(PIN_PB18, 5, 2)
+#define PIN_PB19 51
+#define PIN_PB19__GPIO PINMUX_PIN(PIN_PB19, 0, 0)
+#define PIN_PB19__QSPI0_IO7 PINMUX_PIN(PIN_PB19, 1, 1)
+#define PIN_PB19__FLEXCOM10_IO1 PINMUX_PIN(PIN_PB19, 2, 1)
+#define PIN_PB19__PCK3 PINMUX_PIN(PIN_PB19, 3, 1)
+#define PIN_PB19__D5 PINMUX_PIN(PIN_PB19, 4, 1)
+#define PIN_PB19__PWMFI0 PINMUX_PIN(PIN_PB19, 5, 2)
+#define PIN_PB20 52
+#define PIN_PB20__GPIO PINMUX_PIN(PIN_PB20, 0, 0)
+#define PIN_PB20__QSPI0_DQS PINMUX_PIN(PIN_PB20, 1, 1)
+#define PIN_PB20__FLEXCOM10_IO2 PINMUX_PIN(PIN_PB20, 2, 1)
+#define PIN_PB20__D6 PINMUX_PIN(PIN_PB20, 4, 1)
+#define PIN_PB20__PWMFI1 PINMUX_PIN(PIN_PB20, 5, 2)
+#define PIN_PB21 53
+#define PIN_PB21__GPIO PINMUX_PIN(PIN_PB21, 0, 0)
+#define PIN_PB21__QSPI0_INT PINMUX_PIN(PIN_PB21, 1, 1)
+#define PIN_PB21__FLEXCOM10_IO3 PINMUX_PIN(PIN_PB21, 2, 1)
+#define PIN_PB21__FLEXCOM9_IO5 PINMUX_PIN(PIN_PB21, 3, 1)
+#define PIN_PB21__D7 PINMUX_PIN(PIN_PB21, 4, 1)
+#define PIN_PB22 54
+#define PIN_PB22__GPIO PINMUX_PIN(PIN_PB22, 0, 0)
+#define PIN_PB22__QSPI1_IO3 PINMUX_PIN(PIN_PB22, 1, 1)
+#define PIN_PB22__FLEXCOM10_IO4 PINMUX_PIN(PIN_PB22, 2, 1)
+#define PIN_PB22__FLEXCOM9_IO6 PINMUX_PIN(PIN_PB22, 3, 1)
+#define PIN_PB22__NANDRDY PINMUX_PIN(PIN_PB22, 4, 1)
+#define PIN_PB23 55
+#define PIN_PB23__GPIO PINMUX_PIN(PIN_PB23, 0, 0)
+#define PIN_PB23__QSPI1_IO2 PINMUX_PIN(PIN_PB23, 1, 1)
+#define PIN_PB23__FLEXCOM7_IO0 PINMUX_PIN(PIN_PB23, 2, 1)
+#define PIN_PB23__I2SMCC0_CK PINMUX_PIN(PIN_PB23, 3, 1)
+#define PIN_PB23__PCK4 PINMUX_PIN(PIN_PB23, 6, 1)
+#define PIN_PB24 56
+#define PIN_PB24__GPIO PINMUX_PIN(PIN_PB24, 0, 0)
+#define PIN_PB24__QSPI1_IO1 PINMUX_PIN(PIN_PB24, 1, 1)
+#define PIN_PB24__FLEXCOM7_IO1 PINMUX_PIN(PIN_PB24, 2, 1)
+#define PIN_PB24__I2SMCC0_WS PINMUX_PIN(PIN_PB24, 3, 1)
+#define PIN_PB24__PCK5 PINMUX_PIN(PIN_PB24, 6, 1)
+#define PIN_PB25 57
+#define PIN_PB25__GPIO PINMUX_PIN(PIN_PB25, 0, 0)
+#define PIN_PB25__QSPI1_IO0 PINMUX_PIN(PIN_PB25, 1, 1)
+#define PIN_PB25__FLEXCOM7_IO2 PINMUX_PIN(PIN_PB25, 2, 1)
+#define PIN_PB25__I2SMCC0_DOUT1 PINMUX_PIN(PIN_PB25, 3, 1)
+#define PIN_PB25__PCK6 PINMUX_PIN(PIN_PB25, 6, 1)
+#define PIN_PB26 58
+#define PIN_PB26__GPIO PINMUX_PIN(PIN_PB26, 0, 0)
+#define PIN_PB26__QSPI1_CS PINMUX_PIN(PIN_PB26, 1, 1)
+#define PIN_PB26__FLEXCOM7_IO3 PINMUX_PIN(PIN_PB26, 2, 1)
+#define PIN_PB26__I2SMCC0_DOUT0 PINMUX_PIN(PIN_PB26, 3, 1)
+#define PIN_PB26__PWMEXTRG0 PINMUX_PIN(PIN_PB26, 5, 1)
+#define PIN_PB26__PCK7 PINMUX_PIN(PIN_PB26, 6, 1)
+#define PIN_PB27 59
+#define PIN_PB27__GPIO PINMUX_PIN(PIN_PB27, 0, 0)
+#define PIN_PB27__QSPI1_SCK PINMUX_PIN(PIN_PB27, 1, 1)
+#define PIN_PB27__FLEXCOM7_IO4 PINMUX_PIN(PIN_PB27, 2, 1)
+#define PIN_PB27__I2SMCC0_MCK PINMUX_PIN(PIN_PB27, 3, 1)
+#define PIN_PB27__PWMEXTRG1 PINMUX_PIN(PIN_PB27, 5, 1)
+#define PIN_PB28 60
+#define PIN_PB28__GPIO PINMUX_PIN(PIN_PB28, 0, 0)
+#define PIN_PB28__SDMMC1_RSTN PINMUX_PIN(PIN_PB28, 1, 1)
+#define PIN_PB28__ADTRG PINMUX_PIN(PIN_PB28, 2, 2)
+#define PIN_PB28__PWMFI0 PINMUX_PIN(PIN_PB28, 5, 1)
+#define PIN_PB28__FLEXCOM7_IO0 PINMUX_PIN(PIN_PB28, 6, 4)
+#define PIN_PB29 61
+#define PIN_PB29__GPIO PINMUX_PIN(PIN_PB29, 0, 0)
+#define PIN_PB29__SDMMC1_CMD PINMUX_PIN(PIN_PB29, 1, 1)
+#define PIN_PB29__FLEXCOM3_IO2 PINMUX_PIN(PIN_PB29, 2, 2)
+#define PIN_PB29__FLEXCOM0_IO5 PINMUX_PIN(PIN_PB29, 3, 2)
+#define PIN_PB29__TIOA3 PINMUX_PIN(PIN_PB29, 4, 2)
+#define PIN_PB29__PWMFI1 PINMUX_PIN(PIN_PB29, 5, 1)
+#define PIN_PB29__FLEXCOM7_IO1 PINMUX_PIN(PIN_PB29, 6, 4)
+#define PIN_PB30 62
+#define PIN_PB30__GPIO PINMUX_PIN(PIN_PB30, 0, 0)
+#define PIN_PB30__SDMMC1_CK PINMUX_PIN(PIN_PB30, 1, 1)
+#define PIN_PB30__FLEXCOM3_IO3 PINMUX_PIN(PIN_PB30, 2, 2)
+#define PIN_PB30__FLEXCOM0_IO6 PINMUX_PIN(PIN_PB30, 3, 2)
+#define PIN_PB30__TIOB3 PINMUX_PIN(PIN_PB30, 4, 1)
+#define PIN_PB30__PWMH0 PINMUX_PIN(PIN_PB30, 5, 1)
+#define PIN_PB30__FLEXCOM8_IO0 PINMUX_PIN(PIN_PB30, 6, 4)
+#define PIN_PB31 63
+#define PIN_PB31__GPIO PINMUX_PIN(PIN_PB31, 0, 0)
+#define PIN_PB31__SDMMC1_DAT0 PINMUX_PIN(PIN_PB31, 1, 1)
+#define PIN_PB31__FLEXCOM3_IO4 PINMUX_PIN(PIN_PB31, 2, 2)
+#define PIN_PB31__FLEXCOM9_IO5 PINMUX_PIN(PIN_PB31, 3, 2)
+#define PIN_PB31__TCLK3 PINMUX_PIN(PIN_PB31, 4, 1)
+#define PIN_PB31__PWML0 PINMUX_PIN(PIN_PB31, 5, 1)
+#define PIN_PB31__FLEXCOM8_IO1 PINMUX_PIN(PIN_PB31, 6, 4)
+#define PIN_PC0 64
+#define PIN_PC0__GPIO PINMUX_PIN(PIN_PC0, 0, 0)
+#define PIN_PC0__SDMMC1_DAT1 PINMUX_PIN(PIN_PC0, 1, 1)
+#define PIN_PC0__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC0, 2, 2)
+#define PIN_PC0__TIOA4 PINMUX_PIN(PIN_PC0, 4, 1)
+#define PIN_PC0__PWML1 PINMUX_PIN(PIN_PC0, 5, 1)
+#define PIN_PC0__FLEXCOM9_IO0 PINMUX_PIN(PIN_PC0, 6, 4)
+#define PIN_PC1 65
+#define PIN_PC1__GPIO PINMUX_PIN(PIN_PC1, 0, 0)
+#define PIN_PC1__SDMMC1_DAT2 PINMUX_PIN(PIN_PC1, 1, 1)
+#define PIN_PC1__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC1, 2, 2)
+#define PIN_PC1__TIOB4 PINMUX_PIN(PIN_PC1, 4, 1)
+#define PIN_PC1__PWMH1 PINMUX_PIN(PIN_PC1, 5, 1)
+#define PIN_PC1__FLEXCOM9_IO1 PINMUX_PIN(PIN_PC1, 6, 4)
+#define PIN_PC2 66
+#define PIN_PC2__GPIO PINMUX_PIN(PIN_PC2, 0, 0)
+#define PIN_PC2__SDMMC1_DAT3 PINMUX_PIN(PIN_PC2, 1, 1)
+#define PIN_PC2__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC2, 2, 2)
+#define PIN_PC2__TCLK4 PINMUX_PIN(PIN_PC2, 4, 1)
+#define PIN_PC2__PWML2 PINMUX_PIN(PIN_PC2, 5, 1)
+#define PIN_PC2__FLEXCOM10_IO0 PINMUX_PIN(PIN_PC2, 6, 4)
+#define PIN_PC3 67
+#define PIN_PC3__GPIO PINMUX_PIN(PIN_PC3, 0, 0)
+#define PIN_PC3__SDMMC1_WP PINMUX_PIN(PIN_PC3, 1, 1)
+#define PIN_PC3__FLEXCOM4_IO1 PINMUX_PIN(PIN_PC3, 2, 2)
+#define PIN_PC3__TIOA5 PINMUX_PIN(PIN_PC3, 4, 1)
+#define PIN_PC3__PWMH2 PINMUX_PIN(PIN_PC3, 5, 1)
+#define PIN_PC3__FLEXCOM10_IO1 PINMUX_PIN(PIN_PC3, 6, 4)
+#define PIN_PC4 68
+#define PIN_PC4__GPIO PINMUX_PIN(PIN_PC4, 0, 0)
+#define PIN_PC4__SDMMC1_CD PINMUX_PIN(PIN_PC4, 1, 1)
+#define PIN_PC4__FLEXCOM4_IO2 PINMUX_PIN(PIN_PC4, 2, 2)
+#define PIN_PC4__FLEXCOM9_IO6 PINMUX_PIN(PIN_PC4, 3, 2)
+#define PIN_PC4__TIOB5 PINMUX_PIN(PIN_PC4, 4, 1)
+#define PIN_PC4__PWML3 PINMUX_PIN(PIN_PC4, 5, 1)
+#define PIN_PC4__FLEXCOM11_IO0 PINMUX_PIN(PIN_PC4, 6, 4)
+#define PIN_PC5 69
+#define PIN_PC5__GPIO PINMUX_PIN(PIN_PC5, 0, 0)
+#define PIN_PC5__SDMMC1_1V8SEL PINMUX_PIN(PIN_PC5, 1, 1)
+#define PIN_PC5__FLEXCOM4_IO3 PINMUX_PIN(PIN_PC5, 2, 2)
+#define PIN_PC5__FLEXCOM6_IO5 PINMUX_PIN(PIN_PC5, 3, 2)
+#define PIN_PC5__TCLK5 PINMUX_PIN(PIN_PC5, 4, 1)
+#define PIN_PC5__PWMH3 PINMUX_PIN(PIN_PC5, 5, 1)
+#define PIN_PC5__FLEXCOM11_IO1 PINMUX_PIN(PIN_PC5, 6, 4)
+#define PIN_PC6 70
+#define PIN_PC6__GPIO PINMUX_PIN(PIN_PC6, 0, 0)
+#define PIN_PC6__FLEXCOM4_IO4 PINMUX_PIN(PIN_PC6, 2, 2)
+#define PIN_PC6__FLEXCOM6_IO6 PINMUX_PIN(PIN_PC6, 3, 2)
+#define PIN_PC7 71
+#define PIN_PC7__GPIO PINMUX_PIN(PIN_PC7, 0, 0)
+#define PIN_PC7__I2SMCC0_DIN0 PINMUX_PIN(PIN_PC7, 1, 1)
+#define PIN_PC7__FLEXCOM7_IO0 PINMUX_PIN(PIN_PC7, 2, 2)
+#define PIN_PC8 72
+#define PIN_PC8__GPIO PINMUX_PIN(PIN_PC8, 0, 0)
+#define PIN_PC8__I2SMCC0_DIN1 PINMUX_PIN(PIN_PC8, 1, 1)
+#define PIN_PC8__FLEXCOM7_IO1 PINMUX_PIN(PIN_PC8, 2, 2)
+#define PIN_PC9 73
+#define PIN_PC9__GPIO PINMUX_PIN(PIN_PC9, 0, 0)
+#define PIN_PC9__I2SMCC0_DOUT3 PINMUX_PIN(PIN_PC9, 1, 1)
+#define PIN_PC9__FLEXCOM7_IO2 PINMUX_PIN(PIN_PC9, 2, 2)
+#define PIN_PC9__FLEXCOM1_IO0 PINMUX_PIN(PIN_PC9, 6, 4)
+#define PIN_PC10 74
+#define PIN_PC10__GPIO PINMUX_PIN(PIN_PC10, 0, 0)
+#define PIN_PC10__I2SMCC0_DOUT2 PINMUX_PIN(PIN_PC10, 1, 1)
+#define PIN_PC10__FLEXCOM7_IO3 PINMUX_PIN(PIN_PC10, 2, 2)
+#define PIN_PC10__FLEXCOM1_IO1 PINMUX_PIN(PIN_PC10, 6, 4)
+#define PIN_PC11 75
+#define PIN_PC11__GPIO PINMUX_PIN(PIN_PC11, 0, 0)
+#define PIN_PC11__I2SMCC1_CK PINMUX_PIN(PIN_PC11, 1, 1)
+#define PIN_PC11__FLEXCOM7_IO4 PINMUX_PIN(PIN_PC11, 2, 2)
+#define PIN_PC11__FLEXCOM2_IO0 PINMUX_PIN(PIN_PC11, 6, 4)
+#define PIN_PC12 76
+#define PIN_PC12__GPIO PINMUX_PIN(PIN_PC12, 0, 0)
+#define PIN_PC12__I2SMCC1_WS PINMUX_PIN(PIN_PC12, 1, 1)
+#define PIN_PC12__FLEXCOM8_IO2 PINMUX_PIN(PIN_PC12, 2, 2)
+#define PIN_PC12__FLEXCOM2_IO1 PINMUX_PIN(PIN_PC12, 6, 4)
+#define PIN_PC13 77
+#define PIN_PC13__GPIO PINMUX_PIN(PIN_PC13, 0, 0)
+#define PIN_PC13__I2SMCC1_MCK PINMUX_PIN(PIN_PC13, 1, 1)
+#define PIN_PC13__FLEXCOM8_IO1 PINMUX_PIN(PIN_PC13, 2, 2)
+#define PIN_PC13__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC13, 6, 4)
+#define PIN_PC14 78
+#define PIN_PC14__GPIO PINMUX_PIN(PIN_PC14, 0, 0)
+#define PIN_PC14__I2SMCC1_DOUT0 PINMUX_PIN(PIN_PC14, 1, 1)
+#define PIN_PC14__FLEXCOM8_IO0 PINMUX_PIN(PIN_PC14, 2, 2)
+#define PIN_PC14__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC14, 6, 4)
+#define PIN_PC15 79
+#define PIN_PC15__GPIO PINMUX_PIN(PIN_PC15, 0, 0)
+#define PIN_PC15__I2SMCC1_DOUT1 PINMUX_PIN(PIN_PC15, 1, 1)
+#define PIN_PC15__FLEXCOM8_IO3 PINMUX_PIN(PIN_PC15, 2, 2)
+#define PIN_PC15__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC15, 6, 4)
+#define PIN_PC16 80
+#define PIN_PC16__GPIO PINMUX_PIN(PIN_PC16, 0, 0)
+#define PIN_PC16__I2SMCC1_DOUT2 PINMUX_PIN(PIN_PC16, 1, 1)
+#define PIN_PC16__FLEXCOM8_IO4 PINMUX_PIN(PIN_PC16, 2, 2)
+#define PIN_PC16__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC16, 6, 4)
+#define PIN_PC17 81
+#define PIN_PC17__GPIO PINMUX_PIN(PIN_PC17, 0, 0)
+#define PIN_PC17__I2SMCC1_DOUT3 PINMUX_PIN(PIN_PC17, 1, 1)
+#define PIN_PC17__EXT_IRQ0 PINMUX_PIN(PIN_PC17, 2, 3)
+#define PIN_PC17__FLEXCOM5_IO0 PINMUX_PIN(PIN_PC17, 6, 4)
+#define PIN_PC18 82
+#define PIN_PC18__GPIO PINMUX_PIN(PIN_PC18, 0, 0)
+#define PIN_PC18__I2SMCC1_DIN0 PINMUX_PIN(PIN_PC18, 1, 1)
+#define PIN_PC18__FLEXCOM9_IO0 PINMUX_PIN(PIN_PC18, 2, 2)
+#define PIN_PC18__FLEXCOM5_IO1 PINMUX_PIN(PIN_PC18, 6, 4)
+#define PIN_PC19 83
+#define PIN_PC19__GPIO PINMUX_PIN(PIN_PC19, 0, 0)
+#define PIN_PC19__I2SMCC1_DIN1 PINMUX_PIN(PIN_PC19, 1, 1)
+#define PIN_PC19__FLEXCOM9_IO1 PINMUX_PIN(PIN_PC19, 2, 2)
+#define PIN_PC19__FLEXCOM6_IO0 PINMUX_PIN(PIN_PC19, 6, 4)
+#define PIN_PC20 84
+#define PIN_PC20__GPIO PINMUX_PIN(PIN_PC20, 0, 0)
+#define PIN_PC20__I2SMCC1_DIN2 PINMUX_PIN(PIN_PC20, 1, 1)
+#define PIN_PC20__FLEXCOM9_IO4 PINMUX_PIN(PIN_PC20, 2, 2)
+#define PIN_PC20__FLEXCOM6_IO1 PINMUX_PIN(PIN_PC20, 6, 4)
+#define PIN_PC21 85
+#define PIN_PC21__GPIO PINMUX_PIN(PIN_PC21, 0, 0)
+#define PIN_PC21__I2SMCC1_DIN3 PINMUX_PIN(PIN_PC21, 1, 1)
+#define PIN_PC21__FLEXCOM9_IO2 PINMUX_PIN(PIN_PC21, 2, 2)
+#define PIN_PC21__D3 PINMUX_PIN(PIN_PC21, 4, 2)
+#define PIN_PC21__FLEXCOM6_IO0 PINMUX_PIN(PIN_PC21, 6, 5)
+#define PIN_PC22 86
+#define PIN_PC22__GPIO PINMUX_PIN(PIN_PC22, 0, 0)
+#define PIN_PC22__I2SMCC0_DIN2 PINMUX_PIN(PIN_PC22, 1, 1)
+#define PIN_PC22__FLEXCOM9_IO3 PINMUX_PIN(PIN_PC22, 2, 2)
+#define PIN_PC22__D4 PINMUX_PIN(PIN_PC22, 4, 2)
+#define PIN_PC22__FLEXCOM6_IO1 PINMUX_PIN(PIN_PC22, 6, 5)
+#define PIN_PC23 87
+#define PIN_PC23__GPIO PINMUX_PIN(PIN_PC23, 0, 0)
+#define PIN_PC23__I2SMCC0_DIN3 PINMUX_PIN(PIN_PC23, 1, 1)
+#define PIN_PC23__FLEXCOM0_IO5 PINMUX_PIN(PIN_PC23, 2, 3)
+#define PIN_PC23__D5 PINMUX_PIN(PIN_PC23, 4, 2)
+#define PIN_PC23__FLEXCOM7_IO0 PINMUX_PIN(PIN_PC23, 6, 5)
+#define PIN_PC24 88
+#define PIN_PC24__GPIO PINMUX_PIN(PIN_PC24, 0, 0)
+#define PIN_PC24__FLEXCOM0_IO6 PINMUX_PIN(PIN_PC24, 2, 3)
+#define PIN_PC24__EXT_IRQ1 PINMUX_PIN(PIN_PC24, 3, 3)
+#define PIN_PC24__D6 PINMUX_PIN(PIN_PC24, 4, 2)
+#define PIN_PC24__FLEXCOM7_IO1 PINMUX_PIN(PIN_PC24, 6, 5)
+#define PIN_PC25 89
+#define PIN_PC25__GPIO PINMUX_PIN(PIN_PC25, 0, 0)
+#define PIN_PC25__NTRST PINMUX_PIN(PIN_PC25, 1, 1)
+#define PIN_PC26 90
+#define PIN_PC26__GPIO PINMUX_PIN(PIN_PC26, 0, 0)
+#define PIN_PC26__TCK_SWCLK PINMUX_PIN(PIN_PC26, 1, 1)
+#define PIN_PC27 91
+#define PIN_PC27__GPIO PINMUX_PIN(PIN_PC27, 0, 0)
+#define PIN_PC27__TMS_SWDIO PINMUX_PIN(PIN_PC27, 1, 1)
+#define PIN_PC28 92
+#define PIN_PC28__GPIO PINMUX_PIN(PIN_PC28, 0, 0)
+#define PIN_PC28__TDI PINMUX_PIN(PIN_PC28, 1, 1)
+#define PIN_PC29 93
+#define PIN_PC29__GPIO PINMUX_PIN(PIN_PC29, 0, 0)
+#define PIN_PC29__TDO PINMUX_PIN(PIN_PC29, 1, 1)
+#define PIN_PC30 94
+#define PIN_PC30__GPIO PINMUX_PIN(PIN_PC30, 0, 0)
+#define PIN_PC30__FLEXCOM10_IO0 PINMUX_PIN(PIN_PC30, 2, 2)
+#define PIN_PC31 95
+#define PIN_PC31__GPIO PINMUX_PIN(PIN_PC31, 0, 0)
+#define PIN_PC31__FLEXCOM10_IO1 PINMUX_PIN(PIN_PC31, 2, 2)
+#define PIN_PD0 96
+#define PIN_PD0__GPIO PINMUX_PIN(PIN_PD0, 0, 0)
+#define PIN_PD0__FLEXCOM11_IO0 PINMUX_PIN(PIN_PD0, 2, 2)
+#define PIN_PD1 97
+#define PIN_PD1__GPIO PINMUX_PIN(PIN_PD1, 0, 0)
+#define PIN_PD1__FLEXCOM11_IO1 PINMUX_PIN(PIN_PD1, 2, 2)
+#define PIN_PD2 98
+#define PIN_PD2__GPIO PINMUX_PIN(PIN_PD2, 0, 0)
+#define PIN_PD2__SDMMC2_RSTN PINMUX_PIN(PIN_PD2, 1, 1)
+#define PIN_PD2__PCK0 PINMUX_PIN(PIN_PD2, 2, 2)
+#define PIN_PD2__CANTX4 PINMUX_PIN(PIN_PD2, 3, 1)
+#define PIN_PD2__D7 PINMUX_PIN(PIN_PD2, 4, 2)
+#define PIN_PD2__TIOA0 PINMUX_PIN(PIN_PD2, 5, 2)
+#define PIN_PD2__FLEXCOM8_IO0 PINMUX_PIN(PIN_PD2, 6, 5)
+#define PIN_PD3 99
+#define PIN_PD3__GPIO PINMUX_PIN(PIN_PD3, 0, 0)
+#define PIN_PD3__SDMMC2_CMD PINMUX_PIN(PIN_PD3, 1, 1)
+#define PIN_PD3__FLEXCOM0_IO0 PINMUX_PIN(PIN_PD3, 2, 2)
+#define PIN_PD3__CANRX4 PINMUX_PIN(PIN_PD3, 3, 1)
+#define PIN_PD3__NANDRDY PINMUX_PIN(PIN_PD3, 4, 2)
+#define PIN_PD3__TIOB0 PINMUX_PIN(PIN_PD3, 5, 2)
+#define PIN_PD3__FLEXCOM8_IO1 PINMUX_PIN(PIN_PD3, 6, 5)
+#define PIN_PD4 100
+#define PIN_PD4__GPIO PINMUX_PIN(PIN_PD4, 0, 0)
+#define PIN_PD4__SDMMC2_CK PINMUX_PIN(PIN_PD4, 1, 1)
+#define PIN_PD4__FLEXCOM0_IO1 PINMUX_PIN(PIN_PD4, 2, 2)
+#define PIN_PD4__CANTX5 PINMUX_PIN(PIN_PD4, 3, 1)
+#define PIN_PD4__NCS3_NANDCS PINMUX_PIN(PIN_PD4, 4, 2)
+#define PIN_PD4__TCLK0 PINMUX_PIN(PIN_PD4, 5, 2)
+#define PIN_PD4__FLEXCOM9_IO0 PINMUX_PIN(PIN_PD4, 6, 5)
+#define PIN_PD5 101
+#define PIN_PD5__GPIO PINMUX_PIN(PIN_PD5, 0, 0)
+#define PIN_PD5__SDMMC2_DAT0 PINMUX_PIN(PIN_PD5, 1, 1)
+#define PIN_PD5__FLEXCOM0_IO2 PINMUX_PIN(PIN_PD5, 2, 2)
+#define PIN_PD5__CANRX5 PINMUX_PIN(PIN_PD5, 3, 1)
+#define PIN_PD5__NWE_NWR0_NANDWE PINMUX_PIN(PIN_PD5, 4, 2)
+#define PIN_PD5__TIOA1 PINMUX_PIN(PIN_PD5, 5, 2)
+#define PIN_PD5__FLEXCOM9_IO1 PINMUX_PIN(PIN_PD5, 6, 5)
+#define PIN_PD6 102
+#define PIN_PD6__GPIO PINMUX_PIN(PIN_PD6, 0, 0)
+#define PIN_PD6__SDMMC2_DAT1 PINMUX_PIN(PIN_PD6, 1, 1)
+#define PIN_PD6__FLEXCOM0_IO3 PINMUX_PIN(PIN_PD6, 2, 2)
+#define PIN_PD6__SPDIF_RX PINMUX_PIN(PIN_PD6, 3, 3)
+#define PIN_PD6__NRD_NANDOE PINMUX_PIN(PIN_PD6, 4, 2)
+#define PIN_PD6__TIOB1 PINMUX_PIN(PIN_PD6, 5, 2)
+#define PIN_PD6__FLEXCOM10_IO0 PINMUX_PIN(PIN_PD6, 6, 5)
+#define PIN_PD7 103
+#define PIN_PD7__GPIO PINMUX_PIN(PIN_PD7, 0, 0)
+#define PIN_PD7__SDMMC2_DAT2 PINMUX_PIN(PIN_PD7, 1, 1)
+#define PIN_PD7__FLEXCOM0_IO4 PINMUX_PIN(PIN_PD7, 2, 2)
+#define PIN_PD7__SPDIF_TX PINMUX_PIN(PIN_PD7, 2, 2)
+#define PIN_PD7__A21_NANDALE PINMUX_PIN(PIN_PD7, 4, 2)
+#define PIN_PD7__TCLK1 PINMUX_PIN(PIN_PD7, 5, 2)
+#define PIN_PD7__FLEXCOM10_IO1 PINMUX_PIN(PIN_PD7, 6, 5)
+#define PIN_PD8 104
+#define PIN_PD8__GPIO PINMUX_PIN(PIN_PD8, 0, 0)
+#define PIN_PD8__SDMMC2_DAT3 PINMUX_PIN(PIN_PD8, 1, 1)
+#define PIN_PD8__I2SMCC0_DIN0 PINMUX_PIN(PIN_PD8, 3, 1)
+#define PIN_PD8__A11_NANDCLE PINMUX_PIN(PIN_PD8, 4, 2)
+#define PIN_PD8__TIOA2 PINMUX_PIN(PIN_PD8, 5, 2)
+#define PIN_PD8__FLEXCOM11_IO0 PINMUX_PIN(PIN_PD8, 6, 5)
+#define PIN_PD9 105
+#define PIN_PD9__GPIO PINMUX_PIN(PIN_PD9, 0, 0)
+#define PIN_PD9__SDMMC2_WP PINMUX_PIN(PIN_PD9, 1, 1)
+#define PIN_PD9__I2SMCC0_DIN1 PINMUX_PIN(PIN_PD9, 3, 2)
+#define PIN_PD9__D0 PINMUX_PIN(PIN_PD9, 4, 2)
+#define PIN_PD9__TIOB2 PINMUX_PIN(PIN_PD9, 5, 2)
+#define PIN_PD9__FLEXCOM11_IO1 PINMUX_PIN(PIN_PD9, 6, 5)
+#define PIN_PD10 106
+#define PIN_PD10__GPIO PINMUX_PIN(PIN_PD10, 0, 0)
+#define PIN_PD10__SDMMC2_CD PINMUX_PIN(PIN_PD10, 1, 1)
+#define PIN_PD10__PCK6 PINMUX_PIN(PIN_PD10, 2, 2)
+#define PIN_PD10__I2SMCC0_DIN2 PINMUX_PIN(PIN_PD10, 3, 2)
+#define PIN_PD10__D1 PINMUX_PIN(PIN_PD10, 4, 2)
+#define PIN_PD10__TCLK2 PINMUX_PIN(PIN_PD10, 5, 2)
+#define PIN_PD10__FLEXCOM0_IO0 PINMUX_PIN(PIN_PD10, 6, 3)
+#define PIN_PD11 107
+#define PIN_PD11__GPIO PINMUX_PIN(PIN_PD11, 0, 0)
+#define PIN_PD11__SDMMC2_1V8SEL PINMUX_PIN(PIN_PD11, 1, 1)
+#define PIN_PD11__PCK7 PINMUX_PIN(PIN_PD11, 2, 2)
+#define PIN_PD11__I2SMCC0_DIN3 PINMUX_PIN(PIN_PD11, 3, 2)
+#define PIN_PD11__D2 PINMUX_PIN(PIN_PD11, 4, 2)
+#define PIN_PD11__TIOA3 PINMUX_PIN(PIN_PD11, 5, 2)
+#define PIN_PD11__FLEXCOM0_IO1 PINMUX_PIN(PIN_PD11, 6, 3)
+#define PIN_PD12 108
+#define PIN_PD12__GPIO PINMUX_PIN(PIN_PD12, 0, 0)
+#define PIN_PD12__PCK1 PINMUX_PIN(PIN_PD12, 1, 2)
+#define PIN_PD12__FLEXCOM1_IO0 PINMUX_PIN(PIN_PD12, 2, 2)
+#define PIN_PD12__CANTX0 PINMUX_PIN(PIN_PD12, 4, 2)
+#define PIN_PD12__TIOB3 PINMUX_PIN(PIN_PD12, 5, 2)
+#define PIN_PD13 109
+#define PIN_PD13__GPIO PINMUX_PIN(PIN_PD13, 0, 0)
+#define PIN_PD13__I2SMCC0_CK PINMUX_PIN(PIN_PD13, 1, 2)
+#define PIN_PD13__FLEXCOM1_IO1 PINMUX_PIN(PIN_PD13, 2, 2)
+#define PIN_PD13__PWML0 PINMUX_PIN(PIN_PD13, 3, 4)
+#define PIN_PD13__CANRX0 PINMUX_PIN(PIN_PD13, 4, 2)
+#define PIN_PD13__TCLK3 PINMUX_PIN(PIN_PD13, 5, 2)
+#define PIN_PD14 110
+#define PIN_PD14__GPIO PINMUX_PIN(PIN_PD14, 0, 0)
+#define PIN_PD14__I2SMCC0_MCK PINMUX_PIN(PIN_PD14, 1, 2)
+#define PIN_PD14__FLEXCOM1_IO2 PINMUX_PIN(PIN_PD14, 2, 2)
+#define PIN_PD14__PWMH0 PINMUX_PIN(PIN_PD14, 3, 4)
+#define PIN_PD14__CANTX1 PINMUX_PIN(PIN_PD14, 4, 2)
+#define PIN_PD14__TIOA4 PINMUX_PIN(PIN_PD14, 5, 2)
+#define PIN_PD14__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD14, 6, 5)
+#define PIN_PD15 111
+#define PIN_PD15__GPIO PINMUX_PIN(PIN_PD15, 0, 0)
+#define PIN_PD15__I2SMCC0_WS PINMUX_PIN(PIN_PD15, 1, 2)
+#define PIN_PD15__FLEXCOM1_IO3 PINMUX_PIN(PIN_PD15, 2, 2)
+#define PIN_PD15__PWML1 PINMUX_PIN(PIN_PD15, 3, 4)
+#define PIN_PD15__CANRX1 PINMUX_PIN(PIN_PD15, 4, 2)
+#define PIN_PD15__TIOB4 PINMUX_PIN(PIN_PD15, 5, 2)
+#define PIN_PD15__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD15, 6, 5)
+#define PIN_PD16 112
+#define PIN_PD16__GPIO PINMUX_PIN(PIN_PD16, 0, 0)
+#define PIN_PD16__I2SMCC0_DOUT0 PINMUX_PIN(PIN_PD16, 1, 2)
+#define PIN_PD16__FLEXCOM1_IO4 PINMUX_PIN(PIN_PD16, 2, 2)
+#define PIN_PD16__PWMH1 PINMUX_PIN(PIN_PD16, 3, 4)
+#define PIN_PD16__CANTX2 PINMUX_PIN(PIN_PD16, 4, 2)
+#define PIN_PD16__TCLK4 PINMUX_PIN(PIN_PD16, 5, 2)
+#define PIN_PD16__FLEXCOM3_IO0 PINMUX_PIN(PIN_PD16, 6, 5)
+#define PIN_PD17 113
+#define PIN_PD17__GPIO PINMUX_PIN(PIN_PD17, 0, 0)
+#define PIN_PD17__I2SMCC0_DOUT1 PINMUX_PIN(PIN_PD17, 1, 2)
+#define PIN_PD17__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD17, 2, 2)
+#define PIN_PD17__PWML2 PINMUX_PIN(PIN_PD17, 3, 4)
+#define PIN_PD17__CANRX2 PINMUX_PIN(PIN_PD17, 4, 2)
+#define PIN_PD17__TIOA5 PINMUX_PIN(PIN_PD17, 5, 2)
+#define PIN_PD17__FLEXCOM3_IO1 PINMUX_PIN(PIN_PD17, 6, 5)
+#define PIN_PD18 114
+#define PIN_PD18__GPIO PINMUX_PIN(PIN_PD18, 0, 0)
+#define PIN_PD18__I2SMCC0_DOUT2 PINMUX_PIN(PIN_PD18, 1, 2)
+#define PIN_PD18__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD18, 2, 2)
+#define PIN_PD18__PWMH2 PINMUX_PIN(PIN_PD18, 3, 4)
+#define PIN_PD18__CANTX3 PINMUX_PIN(PIN_PD18, 4, 2)
+#define PIN_PD18__TIOB5 PINMUX_PIN(PIN_PD18, 5, 2)
+#define PIN_PD18__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD18, 6, 5)
+#define PIN_PD19 115
+#define PIN_PD19__GPIO PINMUX_PIN(PIN_PD19, 0, 0)
+#define PIN_PD19__I2SMCC0_DOUT3 PINMUX_PIN(PIN_PD19, 1, 2)
+#define PIN_PD19__FLEXCOM2_IO2 PINMUX_PIN(PIN_PD19, 2, 2)
+#define PIN_PD19__PWML3 PINMUX_PIN(PIN_PD19, 3, 4)
+#define PIN_PD19__CANRX3 PINMUX_PIN(PIN_PD19, 4, 2)
+#define PIN_PD19__TCLK5 PINMUX_PIN(PIN_PD19, 5, 2)
+#define PIN_PD19__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD19, 6, 5)
+#define PIN_PD20 116
+#define PIN_PD20__GPIO PINMUX_PIN(PIN_PD20, 0, 0)
+#define PIN_PD20__PCK0 PINMUX_PIN(PIN_PD20, 1, 3)
+#define PIN_PD20__FLEXCOM2_IO3 PINMUX_PIN(PIN_PD20, 2, 2)
+#define PIN_PD20__PWMH3 PINMUX_PIN(PIN_PD20, 3, 4)
+#define PIN_PD20__CANTX4 PINMUX_PIN(PIN_PD20, 5, 2)
+#define PIN_PD20__FLEXCOM5_IO0 PINMUX_PIN(PIN_PD20, 6, 5)
+#define PIN_PD21 117
+#define PIN_PD21__GPIO PINMUX_PIN(PIN_PD21, 0, 0)
+#define PIN_PD21__PCK1 PINMUX_PIN(PIN_PD21, 1, 3)
+#define PIN_PD21__FLEXCOM2_IO4 PINMUX_PIN(PIN_PD21, 2, 2)
+#define PIN_PD21__CANRX4 PINMUX_PIN(PIN_PD21, 4, 2)
+#define PIN_PD21__FLEXCOM5_IO1 PINMUX_PIN(PIN_PD21, 6, 5)
+#define PIN_PD21__G1_TXEN PINMUX_PIN(PIN_PD21, 7, 1)
+#define PIN_PD22 118
+#define PIN_PD22__GPIO PINMUX_PIN(PIN_PD22, 0, 0)
+#define PIN_PD22__PDMC0_CLK PINMUX_PIN(PIN_PD22, 1, 2)
+#define PIN_PD22__PWMEXTRG0 PINMUX_PIN(PIN_PD22, 3, 4)
+#define PIN_PD22__RD1 PINMUX_PIN(PIN_PD22, 4, 2)
+#define PIN_PD22__CANTX5 PINMUX_PIN(PIN_PD22, 6, 2)
+#define PIN_PD22__G1_TX0 PINMUX_PIN(PIN_PD22, 7, 1)
+#define PIN_PD23 119
+#define PIN_PD23__GPIO PINMUX_PIN(PIN_PD23, 0, 0)
+#define PIN_PD23__PDMC0_DS0 PINMUX_PIN(PIN_PD23, 1, 2)
+#define PIN_PD23__PWMEXTRG1 PINMUX_PIN(PIN_PD23, 3, 4)
+#define PIN_PD23__RF1 PINMUX_PIN(PIN_PD23, 4, 2)
+#define PIN_PD23__ISC_MCK PINMUX_PIN(PIN_PD23, 5, 2)
+#define PIN_PD23__CANRX5 PINMUX_PIN(PIN_PD23, 6, 2)
+#define PIN_PD23__G1_TX1 PINMUX_PIN(PIN_PD23, 7, 1)
+#define PIN_PD24 120
+#define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0)
+#define PIN_PD24__PDMC0_DS1 PINMUX_PIN(PIN_PD24, 1, 2)
+#define PIN_PD24__PWMFI0 PINMUX_PIN(PIN_PD24, 3, 4)
+#define PIN_PD24__RK1 PINMUX_PIN(PIN_PD24, 4, 2)
+#define PIN_PD24__ISC_D0 PINMUX_PIN(PIN_PD24, 5, 2)
+#define PIN_PD24__G1_RXDV PINMUX_PIN(PIN_PD24, 7, 1)
+#define PIN_PD25 121
+#define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0)
+#define PIN_PD25__PDMC1_CLK PINMUX_PIN(PIN_PD25, 1, 2)
+#define PIN_PD25__FLEXCOM5_IO0 PINMUX_PIN(PIN_PD25, 2, 2)
+#define PIN_PD25__PWMFI1 PINMUX_PIN(PIN_PD25, 3, 4)
+#define PIN_PD25__TD1 PINMUX_PIN(PIN_PD25, 4, 2)
+#define PIN_PD25__ISC_D1 PINMUX_PIN(PIN_PD25, 5, 2)
+#define PIN_PD25__G1_RX0 PINMUX_PIN(PIN_PD25, 7, 1)
+#define PIN_PD26 122
+#define PIN_PD26__GPIO PINMUX_PIN(PIN_PD26, 0, 0)
+#define PIN_PD26__PDMC1_DS0 PINMUX_PIN(PIN_PD26, 1, 2)
+#define PIN_PD26__FLEXCOM5_IO1 PINMUX_PIN(PIN_PD26, 2, 2)
+#define PIN_PD26__ADTRG PINMUX_PIN(PIN_PD26, 3, 3)
+#define PIN_PD26__TF1 PINMUX_PIN(PIN_PD26, 4, 2)
+#define PIN_PD26__ISC_D2 PINMUX_PIN(PIN_PD26, 5, 2)
+#define PIN_PD26__G1_RX1 PINMUX_PIN(PIN_PD26, 7, 1)
+#define PIN_PD27 123
+#define PIN_PD27__GPIO PINMUX_PIN(PIN_PD27, 0, 0)
+#define PIN_PD27__PDMC1_DS1 PINMUX_PIN(PIN_PD27, 1, 2)
+#define PIN_PD27__FLEXCOM5_IO2 PINMUX_PIN(PIN_PD27, 2, 2)
+#define PIN_PD27__TIOA0 PINMUX_PIN(PIN_PD27, 3, 3)
+#define PIN_PD27__TK1 PINMUX_PIN(PIN_PD27, 4, 2)
+#define PIN_PD27__ISC_D3 PINMUX_PIN(PIN_PD27, 5, 2)
+#define PIN_PD27__G1_RXER PINMUX_PIN(PIN_PD27, 7, 1)
+#define PIN_PD28 124
+#define PIN_PD28__GPIO PINMUX_PIN(PIN_PD28, 0, 0)
+#define PIN_PD28__RD0 PINMUX_PIN(PIN_PD28, 1, 2)
+#define PIN_PD28__FLEXCOM5_IO3 PINMUX_PIN(PIN_PD28, 2, 2)
+#define PIN_PD28__TIOB0 PINMUX_PIN(PIN_PD28, 3, 3)
+#define PIN_PD28__I2SMCC1_CK PINMUX_PIN(PIN_PD28, 4, 2)
+#define PIN_PD28__ISC_D4 PINMUX_PIN(PIN_PD28, 5, 2)
+#define PIN_PD28__PWML3 PINMUX_PIN(PIN_PD28, 6, 5)
+#define PIN_PD28__G1_MDC PINMUX_PIN(PIN_PD28, 7, 1)
+#define PIN_PD29 125
+#define PIN_PD29__GPIO PINMUX_PIN(PIN_PD29, 0, 0)
+#define PIN_PD29__RF0 PINMUX_PIN(PIN_PD29, 1, 2)
+#define PIN_PD29__FLEXCOM5_IO4 PINMUX_PIN(PIN_PD29, 2, 2)
+#define PIN_PD29__TCLK0 PINMUX_PIN(PIN_PD29, 3, 3)
+#define PIN_PD29__I2SMCC1_WS PINMUX_PIN(PIN_PD29, 4, 2)
+#define PIN_PD29__ISC_D5 PINMUX_PIN(PIN_PD29, 5, 2)
+#define PIN_PD29__PWMH3 PINMUX_PIN(PIN_PD29, 6, 5)
+#define PIN_PD29__G1_MDIO PINMUX_PIN(PIN_PD29, 7, 1)
+#define PIN_PD30 126
+#define PIN_PD30__GPIO PINMUX_PIN(PIN_PD30, 0, 0)
+#define PIN_PD30__RK0 PINMUX_PIN(PIN_PD30, 1, 2)
+#define PIN_PD30__FLEXCOM6_IO0 PINMUX_PIN(PIN_PD30, 2, 2)
+#define PIN_PD30__TIOA1 PINMUX_PIN(PIN_PD30, 3, 3)
+#define PIN_PD30__I2SMCC1_MCK PINMUX_PIN(PIN_PD30, 4, 2)
+#define PIN_PD30__ISC_D6 PINMUX_PIN(PIN_PD30, 5, 2)
+#define PIN_PD30__PWMEXTRG0 PINMUX_PIN(PIN_PD30, 6, 5)
+#define PIN_PD30__G1_TXCK PINMUX_PIN(PIN_PD30, 7, 1)
+#define PIN_PD31 127
+#define PIN_PD31__GPIO PINMUX_PIN(PIN_PD31, 0, 0)
+#define PIN_PD31__TD0 PINMUX_PIN(PIN_PD31, 1, 2)
+#define PIN_PD31__FLEXCOM6_IO1 PINMUX_PIN(PIN_PD31, 2, 2)
+#define PIN_PD31__TIOB1 PINMUX_PIN(PIN_PD31, 3, 3)
+#define PIN_PD31__I2SMCC1_DOUT0 PINMUX_PIN(PIN_PD31, 4, 2)
+#define PIN_PD31__ISC_D7 PINMUX_PIN(PIN_PD31, 5, 2)
+#define PIN_PD31__PWM_EXTRG1 PINMUX_PIN(PIN_PD31, 6, 5)
+#define PIN_PD31__G1_TX2 PINMUX_PIN(PIN_PD31, 7, 1)
+#define PIN_PE0 128
+#define PIN_PE0__GPIO PINMUX_PIN(PIN_PE0, 0, 0)
+#define PIN_PE0__TF0 PINMUX_PIN(PIN_PE0, 1, 2)
+#define PIN_PE0__FLEXCOM6_IO2 PINMUX_PIN(PIN_PE0, 2, 2)
+#define PIN_PE0__TCLK1 PINMUX_PIN(PIN_PE0, 3, 3)
+#define PIN_PE0__I2SMCC1_DOUT1 PINMUX_PIN(PIN_PE0, 4, 2)
+#define PIN_PE0__ISC_HSYNC PINMUX_PIN(PIN_PE0, 5, 2)
+#define PIN_PE0__PWMFI0 PINMUX_PIN(PIN_PE0, 6, 5)
+#define PIN_PE0__G1_TX3 PINMUX_PIN(PIN_PE0, 7, 1)
+#define PIN_PE1 129
+#define PIN_PE1__GPIO PINMUX_PIN(PIN_PE1, 0, 0)
+#define PIN_PE1__TK0 PINMUX_PIN(PIN_PE1, 1, 2)
+#define PIN_PE1__FLEXCOM6_IO3 PINMUX_PIN(PIN_PE1, 2, 2)
+#define PIN_PE1__TIOA2 PINMUX_PIN(PIN_PE1, 3, 3)
+#define PIN_PE1__I2SMCC1_DOUT2 PINMUX_PIN(PIN_PE1, 4, 2)
+#define PIN_PE1__ISC_VSYNC PINMUX_PIN(PIN_PE1, 5, 2)
+#define PIN_PE1__PWMFI1 PINMUX_PIN(PIN_PE1, 6, 5)
+#define PIN_PE1__G1_RX2 PINMUX_PIN(PIN_PE1, 7, 1)
+#define PIN_PE2 130
+#define PIN_PE2__GPIO PINMUX_PIN(PIN_PE2, 0, 0)
+#define PIN_PE2__PWML0 PINMUX_PIN(PIN_PE2, 1, 5)
+#define PIN_PE2__FLEXCOM6_IO4 PINMUX_PIN(PIN_PE2, 2, 2)
+#define PIN_PE2__TIOB2 PINMUX_PIN(PIN_PE2, 3, 3)
+#define PIN_PE2__I2SMCC1_DOUT3 PINMUX_PIN(PIN_PE2, 4, 2)
+#define PIN_PE2__ISC_FIELD PINMUX_PIN(PIN_PE2, 5, 2)
+#define PIN_PE2__G1_RX3 PINMUX_PIN(PIN_PE2, 7, 1)
+#define PIN_PE3 131
+#define PIN_PE3__GPIO PINMUX_PIN(PIN_PE3, 0, 0)
+#define PIN_PE3__PWMH0 PINMUX_PIN(PIN_PE3, 1, 5)
+#define PIN_PE3__FLEXCOM0_IO0 PINMUX_PIN(PIN_PE3, 2, 4)
+#define PIN_PE3__TCLK2 PINMUX_PIN(PIN_PE3, 3, 3)
+#define PIN_PE3__I2SMCC1_DIN0 PINMUX_PIN(PIN_PE3, 4, 2)
+#define PIN_PE3__ISC_PCK PINMUX_PIN(PIN_PE3, 5, 2)
+#define PIN_PE3__G1_RXCK PINMUX_PIN(PIN_PE3, 7, 1)
+#define PIN_PE4 132
+#define PIN_PE4__GPIO PINMUX_PIN(PIN_PE4, 0, 0)
+#define PIN_PE4__PWML1 PINMUX_PIN(PIN_PE4, 1, 5)
+#define PIN_PE4__FLEXCOM0_IO1 PINMUX_PIN(PIN_PE4, 2, 4)
+#define PIN_PE4__TIOA3 PINMUX_PIN(PIN_PE4, 3, 3)
+#define PIN_PE4__I2SMCC1_DIN1 PINMUX_PIN(PIN_PE4, 4, 2)
+#define PIN_PE4__ISC_D8 PINMUX_PIN(PIN_PE4, 5, 2)
+#define PIN_PE4__G1_TXER PINMUX_PIN(PIN_PE4, 7, 1)
+#define PIN_PE5 133
+#define PIN_PE5__GPIO PINMUX_PIN(PIN_PE5, 0, 0)
+#define PIN_PE5__PWMH1 PINMUX_PIN(PIN_PE5, 1, 5)
+#define PIN_PE5__FLEXCOM0_IO2 PINMUX_PIN(PIN_PE5, 2, 4)
+#define PIN_PE5__TIOB3 PINMUX_PIN(PIN_PE5, 3, 3)
+#define PIN_PE5__I2SMCC1_DIN2 PINMUX_PIN(PIN_PE5, 4, 2)
+#define PIN_PE5__ISC_D9 PINMUX_PIN(PIN_PE5, 5, 2)
+#define PIN_PE5__G1_COL PINMUX_PIN(PIN_PE5, 7, 1)
+#define PIN_PE6 134
+#define PIN_PE6__GPIO PINMUX_PIN(PIN_PE6, 0, 0)
+#define PIN_PE6__PWML2 PINMUX_PIN(PIN_PE6, 1, 5)
+#define PIN_PE6__FLEXCOM0_IO3 PINMUX_PIN(PIN_PE6, 2, 4)
+#define PIN_PE6__TCLK3 PINMUX_PIN(PIN_PE6, 3, 3)
+#define PIN_PE6__I2SMCC1_DIN3 PINMUX_PIN(PIN_PE6, 4, 2)
+#define PIN_PE6__ISC_D10 PINMUX_PIN(PIN_PE6, 5, 2)
+#define PIN_PE6__G1_CRS PINMUX_PIN(PIN_PE6, 7, 1)
+#define PIN_PE7 135
+#define PIN_PE7__GPIO PINMUX_PIN(PIN_PE7, 0, 0)
+#define PIN_PE7__PWMH2 PINMUX_PIN(PIN_PE7, 1, 5)
+#define PIN_PE7__FLEXCOM0_IO4 PINMUX_PIN(PIN_PE7, 2, 4)
+#define PIN_PE7__TIOA4 PINMUX_PIN(PIN_PE7, 3, 3)
+#define PIN_PE7__ISC_D11 PINMUX_PIN(PIN_PE7, 5, 2)
+#define PIN_PE7__G1_TSUCOMP PINMUX_PIN(PIN_PE7, 7, 1)
diff --git a/arch/arm/boot/dts/sama7g5.dtsi b/arch/arm/boot/dts/sama7g5.dtsi
new file mode 100644
index 000000000000..cc6be6db7b80
--- /dev/null
+++ b/arch/arm/boot/dts/sama7g5.dtsi
@@ -0,0 +1,528 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * sama7g5.dtsi - Device Tree Include file for SAMA7G5 family SoC
+ *
+ * Copyright (C) 2020 Microchip Technology, Inc. and its subsidiaries
+ *
+ * Author: Eugen Hristev <eugen.hristev@microchip.com>
+ * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/at91.h>
+#include <dt-bindings/dma/at91.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Microchip SAMA7G5 family SoC";
+ compatible = "microchip,sama7g5";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&gic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x0>;
+ };
+ };
+
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ usb_clk: usb_clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <48000000>;
+ };
+ };
+
+ vddout25: fixed-regulator-vddout25 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VDDOUT25";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-boot-on;
+ status = "disabled";
+ };
+
+ ns_sram: sram@100000 {
+ compatible = "mmio-sram";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x100000 0x20000>;
+ ranges;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ secumod: secumod@e0004000 {
+ compatible = "microchip,sama7g5-secumod", "atmel,sama5d2-secumod", "syscon";
+ reg = <0xe0004000 0x4000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ sfrbu: sfr@e0008000 {
+ compatible = "microchip,sama7g5-sfrbu", "atmel,sama5d2-sfrbu", "syscon";
+ reg = <0xe0008000 0x20>;
+ };
+
+ pioA: pinctrl@e0014000 {
+ compatible = "microchip,sama7g5-pinctrl";
+ reg = <0xe0014000 0x800>;
+ 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>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 11>;
+ };
+
+ pmc: pmc@e0018000 {
+ compatible = "microchip,sama7g5-pmc", "syscon";
+ reg = <0xe0018000 0x200>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ #clock-cells = <2>;
+ clocks = <&clk32k 1>, <&clk32k 0>, <&main_xtal>;
+ clock-names = "td_slck", "md_slck", "main_xtal";
+ };
+
+ rtt: rtt@e001d020 {
+ compatible = "microchip,sama7g5-rtt", "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt";
+ reg = <0xe001d020 0x30>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk32k 0>;
+ };
+
+ clk32k: clock-controller@e001d050 {
+ compatible = "microchip,sama7g5-sckc", "microchip,sam9x60-sckc";
+ reg = <0xe001d050 0x4>;
+ clocks = <&slow_xtal>;
+ #clock-cells = <1>;
+ };
+
+ gpbr: gpbr@e001d060 {
+ compatible = "microchip,sama7g5-gpbr", "syscon";
+ reg = <0xe001d060 0x48>;
+ };
+
+ ps_wdt: watchdog@e001d180 {
+ compatible = "microchip,sama7g5-wdt";
+ reg = <0xe001d180 0x24>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk32k 0>;
+ };
+
+ sdmmc0: mmc@e1204000 {
+ compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci";
+ reg = <0xe1204000 0x4000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 80>, <&pmc PMC_TYPE_GCK 80>;
+ clock-names = "hclock", "multclk";
+ assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+ assigned-clocks = <&pmc PMC_TYPE_GCK 80>;
+ assigned-clock-rates = <200000000>;
+ microchip,sdcal-inverted;
+ status = "disabled";
+ };
+
+ sdmmc1: mmc@e1208000 {
+ compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci";
+ reg = <0xe1208000 0x4000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 81>, <&pmc PMC_TYPE_GCK 81>;
+ clock-names = "hclock", "multclk";
+ assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+ assigned-clocks = <&pmc PMC_TYPE_GCK 81>;
+ assigned-clock-rates = <200000000>;
+ microchip,sdcal-inverted;
+ status = "disabled";
+ };
+
+ sdmmc2: mmc@e120c000 {
+ compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci";
+ reg = <0xe120c000 0x4000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 82>, <&pmc PMC_TYPE_GCK 82>;
+ clock-names = "hclock", "multclk";
+ assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+ assigned-clocks = <&pmc PMC_TYPE_GCK 82>;
+ assigned-clock-rates = <200000000>;
+ microchip,sdcal-inverted;
+ status = "disabled";
+ };
+
+ pwm: pwm@e1604000 {
+ compatible = "microchip,sama7g5-pwm", "atmel,sama5d2-pwm";
+ reg = <0xe1604000 0x4000>;
+ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ #pwm-cells = <3>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 77>;
+ status = "disabled";
+ };
+
+ spdifrx: spdifrx@e1614000 {
+ #sound-dai-cells = <0>;
+ compatible = "microchip,sama7g5-spdifrx";
+ reg = <0xe1614000 0x4000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(49)>;
+ dma-names = "rx";
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 84>, <&pmc PMC_TYPE_GCK 84>;
+ clock-names = "pclk", "gclk";
+ status = "disabled";
+ };
+
+ spdiftx: spdiftx@e1618000 {
+ #sound-dai-cells = <0>;
+ compatible = "microchip,sama7g5-spdiftx";
+ reg = <0xe1618000 0x4000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(50)>;
+ dma-names = "tx";
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 85>, <&pmc PMC_TYPE_GCK 85>;
+ clock-names = "pclk", "gclk";
+ };
+
+ i2s0: i2s@e161c000 {
+ compatible = "microchip,sama7g5-i2smcc";
+ #sound-dai-cells = <0>;
+ reg = <0xe161c000 0x4000>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(34)>, <&dma0 AT91_XDMAC_DT_PERID(33)>;
+ dma-names = "tx", "rx";
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 57>, <&pmc PMC_TYPE_GCK 57>;
+ clock-names = "pclk", "gclk";
+ status = "disabled";
+ };
+
+ i2s1: i2s@e1620000 {
+ compatible = "microchip,sama7g5-i2smcc";
+ #sound-dai-cells = <0>;
+ reg = <0xe1620000 0x4000>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(36)>, <&dma0 AT91_XDMAC_DT_PERID(35)>;
+ dma-names = "tx", "rx";
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 58>, <&pmc PMC_TYPE_GCK 58>;
+ clock-names = "pclk", "gclk";
+ status = "disabled";
+ };
+
+ pit64b0: timer@e1800000 {
+ compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b";
+ reg = <0xe1800000 0x4000>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 70>, <&pmc PMC_TYPE_GCK 70>;
+ clock-names = "pclk", "gclk";
+ };
+
+ pit64b1: timer@e1804000 {
+ compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b";
+ reg = <0xe1804000 0x4000>;
+ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 71>, <&pmc PMC_TYPE_GCK 71>;
+ clock-names = "pclk", "gclk";
+ };
+
+ flx0: flexcom@e1818000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xe1818000 0x200>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 38>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xe1818000 0x800>;
+ status = "disabled";
+
+ uart0: serial@200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 38>;
+ clock-names = "usart";
+ dmas = <&dma1 AT91_XDMAC_DT_PERID(6)>,
+ <&dma1 AT91_XDMAC_DT_PERID(5)>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+
+ flx1: flexcom@e181c000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xe181c000 0x200>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 39>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xe181c000 0x800>;
+ status = "disabled";
+
+ i2c1: i2c@600 {
+ compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 39>;
+ atmel,fifo-size = <32>;
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(7)>,
+ <&dma0 AT91_XDMAC_DT_PERID(8)>;
+ dma-names = "rx", "tx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+
+ flx3: flexcom@e1824000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xe1824000 0x200>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 41>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xe1824000 0x800>;
+ status = "disabled";
+
+ uart3: serial@200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 41>;
+ clock-names = "usart";
+ dmas = <&dma1 AT91_XDMAC_DT_PERID(12)>,
+ <&dma1 AT91_XDMAC_DT_PERID(11)>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+
+ trng: rng@e2010000 {
+ compatible = "microchip,sama7g5-trng", "atmel,at91sam9g45-trng";
+ reg = <0xe2010000 0x100>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 97>;
+ status = "disabled";
+ };
+
+ flx4: flexcom@e2018000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xe2018000 0x200>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 42>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xe2018000 0x800>;
+ status = "disabled";
+
+ uart4: serial@200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 42>;
+ clock-names = "usart";
+ dmas = <&dma1 AT91_XDMAC_DT_PERID(14)>,
+ <&dma1 AT91_XDMAC_DT_PERID(13)>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx7: flexcom@e2024000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xe2024000 0x200>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 45>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xe2024000 0x800>;
+ status = "disabled";
+
+ uart7: serial@200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 45>;
+ clock-names = "usart";
+ dmas = <&dma1 AT91_XDMAC_DT_PERID(20)>,
+ <&dma1 AT91_XDMAC_DT_PERID(19)>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ gmac0: ethernet@e2800000 {
+ compatible = "microchip,sama7g5-gem";
+ reg = <0xe2800000 0x1000>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 51>, <&pmc PMC_TYPE_PERIPHERAL 51>, <&pmc PMC_TYPE_GCK 51>, <&pmc PMC_TYPE_GCK 53>;
+ clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
+ assigned-clocks = <&pmc PMC_TYPE_GCK 51>;
+ assigned-clock-rates = <125000000>;
+ status = "disabled";
+ };
+
+ gmac1: ethernet@e2804000 {
+ compatible = "microchip,sama7g5-emac";
+ reg = <0xe2804000 0x1000>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 52>, <&pmc PMC_TYPE_PERIPHERAL 52>;
+ clock-names = "pclk", "hclk";
+ status = "disabled";
+ };
+
+ dma0: dma-controller@e2808000 {
+ compatible = "microchip,sama7g5-dma";
+ reg = <0xe2808000 0x1000>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 22>;
+ clock-names = "dma_clk";
+ status = "disabled";
+ };
+
+ dma1: dma-controller@e280c000 {
+ compatible = "microchip,sama7g5-dma";
+ reg = <0xe280c000 0x1000>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 23>;
+ clock-names = "dma_clk";
+ status = "disabled";
+ };
+
+ /* Place dma2 here despite it's address */
+ dma2: dma-controller@e1200000 {
+ compatible = "microchip,sama7g5-dma";
+ reg = <0xe1200000 0x1000>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 24>;
+ clock-names = "dma_clk";
+ dma-requests = <0>;
+ status = "disabled";
+ };
+
+ flx8: flexcom@e2818000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xe2818000 0x200>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 46>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xe2818000 0x800>;
+ status = "disabled";
+
+ i2c8: i2c@600 {
+ compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 46>;
+ atmel,fifo-size = <32>;
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(21)>,
+ <&dma0 AT91_XDMAC_DT_PERID(22)>;
+ dma-names = "rx", "tx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+
+ flx9: flexcom@e281c000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xe281c000 0x200>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 47>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xe281c000 0x800>;
+ status = "disabled";
+
+ i2c9: i2c@600 {
+ compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 47>;
+ atmel,fifo-size = <32>;
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(23)>,
+ <&dma0 AT91_XDMAC_DT_PERID(24)>;
+ dma-names = "rx", "tx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+
+ flx11: flexcom@e2824000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xe2824000 0x200>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 49>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xe2824000 0x800>;
+ status = "disabled";
+
+ spi11: spi@400 {
+ compatible = "atmel,at91rm9200-spi";
+ reg = <0x400 0x200>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 49>;
+ clock-names = "spi_clk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ atmel,fifo-size = <32>;
+ dmas = <&dma0 AT91_XDMAC_DT_PERID(27)>,
+ <&dma0 AT91_XDMAC_DT_PERID(28)>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+ };
+
+ gic: interrupt-controller@e8c11000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ interrupt-parent;
+ reg = <0xe8c11000 0x1000>,
+ <0xe8c12000 0x2000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/ste-ab8500.dtsi b/arch/arm/boot/dts/ste-ab8500.dtsi
index d0fe3f9aa183..9baf927f9b95 100644
--- a/arch/arm/boot/dts/ste-ab8500.dtsi
+++ b/arch/arm/boot/dts/ste-ab8500.dtsi
@@ -58,46 +58,46 @@
#io-channel-cells = <1>;
/* GPADC channels */
- bat_ctrl: channel@01 {
+ bat_ctrl: channel@1 {
reg = <0x01>;
};
- btemp_ball: channel@02 {
+ btemp_ball: channel@2 {
reg = <0x02>;
};
- main_charger_v: channel@03 {
+ main_charger_v: channel@3 {
reg = <0x03>;
};
- acc_detect1: channel@04 {
+ acc_detect1: channel@4 {
reg = <0x04>;
};
- acc_detect2: channel@05 {
+ acc_detect2: channel@5 {
reg = <0x05>;
};
- adc_aux1: channel@06 {
+ adc_aux1: channel@6 {
reg = <0x06>;
};
- adc_aux2: channel@07 {
+ adc_aux2: channel@7 {
reg = <0x07>;
};
- main_batt_v: channel@08 {
+ main_batt_v: channel@8 {
reg = <0x08>;
};
- vbus_v: channel@09 {
+ vbus_v: channel@9 {
reg = <0x09>;
};
- main_charger_c: channel@0a {
+ main_charger_c: channel@a {
reg = <0x0a>;
};
- usb_charger_c: channel@0b {
+ usb_charger_c: channel@b {
reg = <0x0b>;
};
- bk_bat_v: channel@0c {
+ bk_bat_v: channel@c {
reg = <0x0c>;
};
- die_temp: channel@0d {
+ die_temp: channel@d {
reg = <0x0d>;
};
- usb_id: channel@0e {
+ usb_id: channel@e {
reg = <0x0e>;
};
xtal_temp: channel@12 {
@@ -217,7 +217,7 @@
battery = <&ab8500_battery>;
};
- ab8500_usb {
+ ab8500_usb: ab8500_usb {
compatible = "stericsson,ab8500-usb";
interrupts = <90 IRQ_TYPE_LEVEL_HIGH>,
<96 IRQ_TYPE_LEVEL_HIGH>,
@@ -238,6 +238,7 @@
musb_1v8-supply = <&db8500_vsmps2_reg>;
clocks = <&prcmu_clk PRCMU_SYSCLK>;
clock-names = "sysclk";
+ #phy-cells = <0>;
};
ab8500-ponkey {
@@ -386,5 +387,10 @@
vana-supply = <&ab8500_ldo_ana_reg>;
};
};
+
+ usb_per5@a03e0000 {
+ phys = <&ab8500_usb>;
+ phy-names = "usb";
+ };
};
};
diff --git a/arch/arm/boot/dts/ste-ab8505.dtsi b/arch/arm/boot/dts/ste-ab8505.dtsi
index 0defc15b9bbc..8d018701a680 100644
--- a/arch/arm/boot/dts/ste-ab8505.dtsi
+++ b/arch/arm/boot/dts/ste-ab8505.dtsi
@@ -54,40 +54,40 @@
#io-channel-cells = <1>;
/* GPADC channels */
- bat_ctrl: channel@01 {
+ bat_ctrl: channel@1 {
reg = <0x01>;
};
- btemp_ball: channel@02 {
+ btemp_ball: channel@2 {
reg = <0x02>;
};
- acc_detect1: channel@04 {
+ acc_detect1: channel@4 {
reg = <0x04>;
};
- acc_detect2: channel@05 {
+ acc_detect2: channel@5 {
reg = <0x05>;
};
- adc_aux1: channel@06 {
+ adc_aux1: channel@6 {
reg = <0x06>;
};
- adc_aux2: channel@07 {
+ adc_aux2: channel@7 {
reg = <0x07>;
};
- main_batt_v: channel@08 {
+ main_batt_v: channel@8 {
reg = <0x08>;
};
- vbus_v: channel@09 {
+ vbus_v: channel@9 {
reg = <0x09>;
};
- charger_c: channel@0b {
+ charger_c: channel@b {
reg = <0x0b>;
};
- bk_bat_v: channel@0c {
+ bk_bat_v: channel@c {
reg = <0x0c>;
};
- die_temp: channel@0d {
+ die_temp: channel@d {
reg = <0x0d>;
};
- usb_id: channel@0e {
+ usb_id: channel@e {
reg = <0x0e>;
};
};
@@ -201,6 +201,7 @@
musb_1v8-supply = <&db8500_vsmps2_reg>;
clocks = <&prcmu_clk PRCMU_SYSCLK>;
clock-names = "sysclk";
+ #phy-cells = <0>;
};
ab8500-ponkey {
@@ -322,5 +323,10 @@
vana-supply = <&ab8500_ldo_ana_reg>;
};
};
+
+ usb_per5@a03e0000 {
+ phys = <&ab8500_usb>;
+ phy-names = "usb";
+ };
};
};
diff --git a/arch/arm/boot/dts/ste-db8500.dtsi b/arch/arm/boot/dts/ste-db8500.dtsi
index 344d29853bf7..f1ff3f4835d7 100644
--- a/arch/arm/boot/dts/ste-db8500.dtsi
+++ b/arch/arm/boot/dts/ste-db8500.dtsi
@@ -5,11 +5,10 @@
/ {
cpus {
cpu@300 {
- /* cpufreq controls */
operating-points = <998400 0
- 800000 0
- 400000 0
- 200000 0>;
+ 798720 0
+ 399360 0
+ 199680 0>;
};
};
@@ -19,19 +18,19 @@
ranges;
/* Modem trace memory */
- ram@06000000 {
+ ram@6000000 {
reg = <0x06000000 0x00f00000>;
no-map;
};
/* Modem shared memory */
- ram@06f00000 {
+ ram@6f00000 {
reg = <0x06f00000 0x00100000>;
no-map;
};
/* Modem private memory */
- ram@07000000 {
+ ram@7000000 {
reg = <0x07000000 0x01000000>;
no-map;
};
diff --git a/arch/arm/boot/dts/ste-db8520.dtsi b/arch/arm/boot/dts/ste-db8520.dtsi
index 287804e9e183..e4e8d5fc1f8a 100644
--- a/arch/arm/boot/dts/ste-db8520.dtsi
+++ b/arch/arm/boot/dts/ste-db8520.dtsi
@@ -5,11 +5,10 @@
/ {
cpus {
cpu@300 {
- /* cpufreq controls */
operating-points = <1152000 0
- 800000 0
- 400000 0
- 200000 0>;
+ 798720 0
+ 399360 0
+ 199680 0>;
};
};
@@ -19,19 +18,19 @@
ranges;
/* Modem trace memory */
- ram@06000000 {
+ ram@6000000 {
reg = <0x06000000 0x00f00000>;
no-map;
};
/* Modem shared memory */
- ram@06f00000 {
+ ram@6f00000 {
reg = <0x06f00000 0x00100000>;
no-map;
};
/* Modem private memory */
- ram@07000000 {
+ ram@7000000 {
reg = <0x07000000 0x01000000>;
no-map;
};
diff --git a/arch/arm/boot/dts/ste-db9500.dtsi b/arch/arm/boot/dts/ste-db9500.dtsi
index 0afff703191c..4273d36e881d 100644
--- a/arch/arm/boot/dts/ste-db9500.dtsi
+++ b/arch/arm/boot/dts/ste-db9500.dtsi
@@ -5,11 +5,10 @@
/ {
cpus {
cpu@300 {
- /* cpufreq controls */
- operating-points = <1152000 0
- 800000 0
- 400000 0
- 200000 0>;
+ operating-points = <998400 0
+ 798720 0
+ 399360 0
+ 199680 0>;
};
};
diff --git a/arch/arm/boot/dts/ste-dbx5x0-pinctrl.dtsi b/arch/arm/boot/dts/ste-dbx5x0-pinctrl.dtsi
index 7bf7a2d34cbc..31a86606beda 100644
--- a/arch/arm/boot/dts/ste-dbx5x0-pinctrl.dtsi
+++ b/arch/arm/boot/dts/ste-dbx5x0-pinctrl.dtsi
@@ -163,6 +163,24 @@
};
i2c2 {
+ i2c2_b_1_default: i2c2_b_1_default {
+ default_mux {
+ function = "i2c2";
+ groups = "i2c2_b_1";
+ };
+ default_cfg1 {
+ pins = "GPIO8_AD5", "GPIO9_AE4"; /* SDA/SCL */
+ ste,config = <&in_nopull>;
+ };
+ };
+
+ i2c2_b_1_sleep: i2c2_b_1_sleep {
+ sleep_cfg1 {
+ pins = "GPIO8_AD5", "GPIO9_AE4"; /* SDA/SCL */
+ ste,config = <&slpm_in_wkup_pdis>;
+ };
+ };
+
i2c2_b_2_default: i2c2_b_2_default {
default_mux {
function = "i2c2";
diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi
index c97e8d29004f..961f2c7274ce 100644
--- a/arch/arm/boot/dts/ste-href.dtsi
+++ b/arch/arm/boot/dts/ste-href.dtsi
@@ -163,6 +163,8 @@
bus-width = <8>;
cap-mmc-highspeed;
non-removable;
+ no-sdio;
+ no-sd;
vmmc-supply = <&db8500_vsmps2_reg>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mc2_a_1_default>;
@@ -178,6 +180,8 @@
bus-width = <8>;
cap-mmc-highspeed;
non-removable;
+ no-sdio;
+ no-sd;
vmmc-supply = <&ab8500_ldo_aux2_reg>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mc4_a_1_default>;
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index 40f1d7c9c1d4..934fc788fe1d 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -267,6 +267,8 @@
max-frequency = <100000000>;
bus-width = <8>;
cap-mmc-highspeed;
+ no-sdio;
+ no-sd;
vmmc-supply = <&ab8500_ldo_aux2_reg>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mc4_a_1_default>;
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts b/arch/arm/boot/dts/ste-ux500-samsung-codina.dts
new file mode 100644
index 000000000000..952606e607ed
--- /dev/null
+++ b/arch/arm/boot/dts/ste-ux500-samsung-codina.dts
@@ -0,0 +1,863 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Devicetree for the Samsung Galaxy Ace 2 GT-I8160 also known as Codina.
+ *
+ * NOTE: this is the most common variant according to the vendor tree, known
+ * as "R0.0". There appears to be a "R0.4" variant with backlight on GPIO69,
+ * AB8505 and other changes. There is also talk about some variants having a
+ * Samsung S6D27A1 display, indicated by passing a different command line from
+ * the boot loader.
+ *
+ * The Samsung tree further talks about GT-I8160P and GT-I8160chn (China).
+ * The GT-I8160 plain is knonw as the "europe" variant.
+ * The GT-I8160P appears to not use the ST Microelectronics accelerometer.
+ * The GT-I8160chn appears to be the same as the europe variant.
+ */
+
+/dts-v1/;
+#include "ste-db8500.dtsi"
+#include "ste-ab8500.dtsi"
+#include "ste-dbx5x0-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ model = "Samsung Galaxy Ace 2 (GT-I8160)";
+ compatible = "samsung,codina", "st-ericsson,u8500";
+
+ cpus {
+ cpu@300 {
+ /*
+ * This has a frequency cap at ~800 MHz in the firmware.
+ * (Changing this number here will not overclock it.)
+ */
+ operating-points = <798720 0
+ 399360 0
+ 199680 0>;
+ };
+ };
+
+ chosen {
+ stdout-path = &serial2;
+ };
+
+ /* TI TXS0206 level translator for 2.9 V */
+ sd_level_translator: regulator-gpio {
+ compatible = "regulator-fixed";
+
+ /* GPIO87 EN */
+ gpios = <&gpio2 23 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ regulator-name = "sd-level-translator";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-type = "voltage";
+
+ startup-delay-us = <200>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_level_translator_default>;
+ };
+
+ /* External LDO MIC5366-3.3YMT for eMMC */
+ ldo_3v3_reg: regulator-gpio-ldo-3v3 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VMEM_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio6 31 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_ldo_en_default_mode>;
+ };
+
+ /*
+ * External Ricoh "TSP" regulator for the touchscreen.
+ * One GPIO line controls two voltages of 3.3V and 1.8V
+ * this line is known as "TSP_LDO_ON1" in the schematics.
+ */
+ ldo_tsp_3v3_reg: regulator-gpio-tsp-ldo-3v3 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "LDO_TSP_A3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ /* GPIO94 controls this regulator */
+ gpio = <&gpio2 30 GPIO_ACTIVE_HIGH>;
+ /* 70 ms power-on delay */
+ startup-delay-us = <70000>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_ldo_en_default_mode>;
+ };
+ ldo_tsp_1v8_reg: regulator-gpio-tsp-ldo-1v8 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VREG_TSP_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ /* GPIO94 controls this regulator */
+ gpio = <&gpio2 30 GPIO_ACTIVE_HIGH>;
+ /* 70 ms power-on delay */
+ startup-delay-us = <70000>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_ldo_en_default_mode>;
+ };
+
+ /*
+ * External Ricoh RP152L010B-TR LCD LDO regulator for the display.
+ * LCD_PWR_EN controls both a 3.0V and 1.8V output.
+ */
+ lcd_3v0_reg: regulator-gpio-lcd-3v0 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VREG_LCD_3.0V";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ /* GPIO219 controls this regulator */
+ gpio = <&gpio6 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pwr_en_default_mode>;
+ };
+ lcd_1v8_reg: regulator-gpio-lcd-1v8 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VREG_LCD_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ /* GPIO219 controls this regulator too */
+ gpio = <&gpio6 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pwr_en_default_mode>;
+ };
+
+ /*
+ * This regulator is a GPIO line that drives the Broadcom WLAN
+ * line WL_REG_ON high and enables the internal regulators
+ * inside the chip. Unfortunatley it is erroneously named
+ * WLAN_RST_N on the schematic but it is not a reset line.
+ *
+ * The voltage specified here is only used to determine the OCR mask,
+ * the for the SDIO connector, the chip is actually connected
+ * directly to VBAT.
+ */
+ wl_reg: regulator-gpio-wlan {
+ compatible = "regulator-fixed";
+ regulator-name = "WL_REG_ON";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ startup-delay-us = <100000>;
+ /* GPIO215 (WLAN_RST_N to WL_REG_ON) */
+ gpio = <&gpio6 23 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_ldo_en_default>;
+ };
+
+ vibrator {
+ compatible = "gpio-vibrator";
+ /* GPIO195 "MOT_EN" */
+ enable-gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vibrator_default>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys_default_mode>;
+
+ button-home {
+ linux,code = <KEY_HOME>;
+ label = "HOME";
+ /* GPIO91 */
+ gpios = <&gpio2 27 GPIO_ACTIVE_LOW>;
+ };
+ button-volup {
+ linux,code = <KEY_VOLUMEUP>;
+ label = "VOL+";
+ /* GPIO67 */
+ gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+ };
+ button-voldown {
+ linux,code = <KEY_VOLUMEDOWN>;
+ label = "VOL-";
+ /* GPIO92 */
+ gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_leds_default_mode>;
+ touchkey-led {
+ label = "touchkeys";
+ /*
+ * GPIO194 on R0.0, R0.4 does not use this at all, it
+ * will instead turn LDO AUX4 on/off for key led backlighy.
+ * (Line is pulled down on R0.4)
+ */
+ gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+ };
+
+ ktd253: backlight {
+ compatible = "kinetic,ktd253";
+ /*
+ * GPIO68 is for R0.0, the board file talks about a TMO variant
+ * (R0.4) using GPIO69.
+ */
+ enable-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>;
+ /* Default to 13/32 brightness */
+ default-brightness = <13>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ktd253_backlight_default_mode>;
+ };
+
+ /* Richtek RT8515GQW Flash LED Driver IC */
+ flash {
+ compatible = "richtek,rt8515";
+ /* GPIO 140 */
+ enf-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;
+ /* GPIO 141 */
+ ent-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
+ /*
+ * RFS is 16 kOhm and RTS is 100 kOhm giving
+ * the flash max current 343mA and torch max
+ * current 55 mA.
+ */
+ richtek,rfs-ohms = <16000>;
+ richtek,rts-ohms = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_flash_default_mode>;
+
+ led {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ flash-max-timeout-us = <250000>;
+ flash-max-microamp = <343750>;
+ led-max-microamp = <55000>;
+ };
+ };
+
+ /* Bit-banged I2C on GPIO143 and GPIO144 also called "SUBPMU I2C" */
+ i2c-gpio-0 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio4 16 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio4 15 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_gpio_0_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ magnetometer@c {
+ compatible = "alps,hscdtd008a";
+ reg = <0x0c>;
+ clock-frequency = <400000>;
+
+ avdd-supply = <&ab8500_ldo_aux1_reg>; // 3V
+ dvdd-supply = <&ab8500_ldo_aux2_reg>; // 1.8V
+ };
+ /* TODO: this should also be used by the SM5103 Camera power management unit */
+ };
+
+ /* Bit-banged I2C on GPIO151 and GPIO152 also called "NFC I2C" */
+ i2c-gpio-1 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio4 24 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio4 23 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_gpio_1_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* TODO: add the NFC chip here */
+ };
+
+ spi-gpio-0 {
+ compatible = "spi-gpio";
+ /* Clock on GPIO220, pin SCL */
+ sck-gpios = <&gpio6 28 GPIO_ACTIVE_HIGH>;
+ /* MOSI on GPIO224, pin SDI "slave data in" */
+ mosi-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+ /* MISO on GPIO225, pin SDO "slave data out" */
+ miso-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+ /* Chip select on GPIO201 */
+ cs-gpios = <&gpio6 9 GPIO_ACTIVE_LOW>;
+ num-chipselects = <1>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_gpio_0_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * Some Codinas (90%) have a WideChips WS2401-based LMS380KF01
+ * display mounted and some 10% has a Samsung S6D27A1 instead.
+ * The boot loader needs to modify this compatible to
+ * correspond to whatever is passed from the early Samsung boot.
+ */
+ panel@0 {
+ compatible = "samsung,lms380kf01";
+ spi-max-frequency = <1200000>;
+ /* TYPE 3: inverse clock polarity and phase */
+ spi-cpha;
+ spi-cpol;
+
+ reg = <0>;
+ vci-supply = <&lcd_3v0_reg>;
+ vccio-supply = <&lcd_1v8_reg>;
+
+ /* Reset on GPIO139 */
+ reset-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>;
+ /* LCD_VGH/LCD_DETECT, ESD IRQ on GPIO93 */
+ interrupt-parent = <&gpio2>;
+ interrupts = <29 IRQ_TYPE_EDGE_RISING>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&panel_default_mode>;
+ backlight = <&ktd253>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&display_out>;
+ };
+ };
+ };
+ };
+
+ soc {
+ /* External Micro SD slot */
+ mmc@80126000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <100000000>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ st,sig-pin-fbclk;
+ full-pwr-cycle;
+ /* MMC is powered by AUX3 1.2V .. 2.91V */
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+ /* 2.9 V level translator is using AUX3 at 2.9 V as well */
+ vqmmc-supply = <&sd_level_translator>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mc0_a_2_default>;
+ pinctrl-1 = <&mc0_a_2_sleep>;
+ cd-gpios = <&gpio6 25 GPIO_ACTIVE_LOW>; // GPIO217
+ status = "okay";
+ };
+
+ /* WLAN SDIO channel */
+ mmc@80118000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+ non-removable;
+ cap-sd-highspeed;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mc1_a_2_default>;
+ pinctrl-1 = <&mc1_a_2_sleep>;
+ /*
+ * GPIO-controlled voltage enablement: this drives
+ * the WL_REG_ON line high when we use this device.
+ * Represented as regulator to fill OCR mask.
+ */
+ vmmc-supply = <&wl_reg>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ wifi@1 {
+ /* Actually BRCM4330 */
+ compatible = "brcm,bcm4330-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ /* GPIO216 WL_HOST_WAKE */
+ interrupt-parent = <&gpio6>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-names = "host-wake";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_default_mode>;
+ };
+ };
+
+ /* eMMC */
+ mmc@80005000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <100000000>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ no-sdio;
+ no-sd;
+ vmmc-supply = <&ldo_3v3_reg>;
+ pinctrl-names = "default", "sleep";
+ /*
+ * GPIO130 will be set to input no pull-up resulting in a resistor
+ * pulling the reset high and taking the memory out of reset.
+ */
+ pinctrl-0 = <&mc2_a_1_default>;
+ pinctrl-1 = <&mc2_a_1_sleep>;
+ status = "okay";
+ };
+
+ /* GBF (Bluetooth) UART */
+ uart@80120000 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&u0_a_1_default>;
+ pinctrl-1 = <&u0_a_1_sleep>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4330-bt";
+ /* GPIO222 rail BT_VREG_EN to BT_REG_ON */
+ shutdown-gpios = <&gpio6 30 GPIO_ACTIVE_HIGH>;
+ /* BT_WAKE on GPIO199 */
+ device-wakeup-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+ /* BT_HOST_WAKE on GPIO97 */
+ /* FIXME: convert to interrupt */
+ host-wakeup-gpios = <&gpio3 1 GPIO_ACTIVE_HIGH>;
+ /* BT_RST_N on GPIO209 */
+ reset-gpios = <&gpio6 17 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bluetooth_default_mode>;
+ };
+ };
+
+ /* GPS UART */
+ uart@80121000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ /* CTS/RTS is not used, CTS is repurposed as GPIO */
+ pinctrl-0 = <&u1rxtx_a_1_default>;
+ pinctrl-1 = <&u1rxtx_a_1_sleep>;
+ /* FIXME: add a device for the GPS here */
+ };
+
+ /* Debugging console UART connected to TSU6111RSVR (FSA880) */
+ uart@80007000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&u2rxtx_c_1_default>;
+ pinctrl-1 = <&u2rxtx_c_1_sleep>;
+ };
+
+ prcmu@80157000 {
+ ab8500 {
+ ab8500_usb {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&usb_a_1_default>;
+ pinctrl-1 = <&usb_a_1_sleep>;
+ };
+
+ ab8500-regulators {
+ ab8500_ldo_aux1 {
+ /* Used for VDD for sensors */
+ regulator-name = "V-SENSORS-VDD";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ ab8500_ldo_aux2 {
+ /* Used for VIO for sensors */
+ regulator-name = "V-SENSORS-VIO";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ab8500_ldo_aux3 {
+ /* Used for voltage for external MMC/SD card */
+ regulator-name = "V-MMC-SD";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <2910000>;
+ };
+ };
+ };
+ };
+
+ /* I2C0 also known as "AGC I2C" */
+ i2c@80004000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c0_a_1_default>;
+ pinctrl-1 = <&i2c0_a_1_sleep>;
+
+ /* TODO: write bindings and driver for this proximity sensor */
+ proximity@39 {
+ /* Codina has the Mouser TMD2672 */
+ compatible = "mouser,tmd2672";
+ clock-frequency = <400000>;
+ reg = <0x39>;
+
+ /* IRQ on GPIO146 "PS_INT" */
+ interrupt-parent = <&gpio4>;
+ interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+ /* FIXME: needs a VDDIO supply that is connected to a pull-up resistor */
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tms2672_codina_default>;
+ };
+ };
+
+ /* I2C1 on GPIO16 and GPIO17 also called "MUS I2C" */
+ i2c@80122000 {
+ status = "okay";
+ pinctrl-names = "default","sleep";
+ /* FIXME: If it doesn't work try what we use on Gavini */
+ pinctrl-0 = <&i2c1_b_2_default>;
+ pinctrl-1 = <&i2c1_b_2_sleep>;
+
+ /* Texas Instruments TSU6111 micro USB switch */
+ usb-switch@25 {
+ compatible = "ti,tsu6111";
+ reg = <0x25>;
+ /* Interrupt JACK_INT_N on GPIO95 */
+ interrupt-parent = <&gpio2>;
+ interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsu6111_codina_default>;
+ };
+ };
+
+ /* I2C2 on GPIO10 and GPIO11 also called "SENSORS I2C" */
+ i2c@80128000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c2_b_2_default>;
+ pinctrl-1 = <&i2c2_b_2_sleep>;
+
+ lisd3dh@19 {
+ /* ST Microelectronics Accelerometer */
+ compatible = "st,lis3dh-accel";
+ st,drdy-int-pin = <1>;
+ reg = <0x19>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>; // 3V
+ vddio-supply = <&ab8500_ldo_aux2_reg>; // 1.8V
+ mount-matrix = "0", "-1", "0",
+ "1", "0", "0",
+ "0", "0", "1";
+ };
+ };
+
+ /* I2C3 */
+ i2c@80110000 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c3_c_2_default>;
+ pinctrl-1 = <&i2c3_c_2_sleep>;
+
+ /* TODO: write bindings and driver for this touchscreen */
+
+ /* Zinitix BT404 ISP part */
+ isp@50 {
+ compatible = "zinitix,bt404-isp";
+ reg = <0x50>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_default>;
+ };
+
+ /* Zinitix BT404 touchscreen, also has the touchkeys for menu and back */
+ touchscreen@20 {
+ compatible = "zinitix,bt404";
+ reg = <0x20>;
+ /* GPIO218 (TSP_INT_1V8) */
+ interrupt-parent = <&gpio6>;
+ interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
+ vcca-supply = <&ldo_tsp_3v3_reg>;
+ vdd-supply = <&ldo_tsp_1v8_reg>;
+ zinitix,mode = <2>;
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <800>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_default>;
+ };
+ };
+
+ mcde@a0350000 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dpi_default_mode>;
+
+ port {
+ display_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+ };
+};
+
+&pinctrl {
+ /*
+ * This extends the MC0_A_2 default config to include
+ * the card detect GPIO217 line.
+ */
+ sdi0 {
+ mc0_a_2_default {
+ default_cfg4 {
+ pins = "GPIO217_AH12"; /* card detect */
+ ste,config = <&gpio_in_pd>;
+ };
+ };
+ };
+ sdi2 {
+ /*
+ * This will make the resistor mounted in R0.0 pull up
+ * the reset line and take the eMMC out of reset. On
+ * R0.4 variants, GPIO130 should be set in GPIO mode and
+ * pulled down. (Not connected.)
+ */
+ mc2_a_1_default {
+ default_cfg2 {
+ pins = "GPIO130_C8"; /* FBCLK */
+ ste,config = <&in_nopull>;
+ };
+ };
+ };
+ /* GPIO that enables the 2.9V SD card level translator */
+ sd-level-translator {
+ sd_level_translator_default: sd_level_translator_default {
+ /* level shifter on GPIO87 */
+ codina_cfg1 {
+ pins = "GPIO87_B3";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the eMMC */
+ emmc-ldo {
+ emmc_ldo_en_default_mode: emmc_ldo_default {
+ /* LDO enable on GPIO223 */
+ codina_cfg1 {
+ pins = "GPIO223_AH9";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIOs for panel control */
+ panel {
+ panel_default_mode: panel_default {
+ codina_cfg1 {
+ /* Reset line */
+ pins = "GPIO139_C9";
+ ste,config = <&gpio_out_lo>;
+ };
+ codina_cfg2 {
+ /* ESD IRQ line "LCD detect" */
+ pins = "GPIO93_B7";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the touchscreen */
+ tsp-ldo {
+ tsp_ldo_en_default_mode: tsp_ldo_default {
+ /* LDO enable on GPIO94 */
+ gavini_cfg1 {
+ pins = "GPIO94_D7";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the LCD display */
+ lcd-ldo {
+ lcd_pwr_en_default_mode: lcd_pwr_en_default {
+ /* LCD_PWR_EN on GPIO219 */
+ codina_cfg1 {
+ pins = "GPIO219_AG10";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the key LED */
+ key-led {
+ gpio_leds_default_mode: en_led_ldo_default {
+ /* EN_LED_LDO on GPIO194 */
+ codina_cfg1 {
+ pins = "GPIO194_AF27";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO that enables the WLAN internal LDO regulators */
+ wlan-ldo {
+ wlan_ldo_en_default: wlan_ldo_default {
+ /* GPIO215 named WLAN_RST_N */
+ codina_cfg1 {
+ pins = "GPIO215_AH13";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* Backlight GPIO */
+ backlight {
+ ktd253_backlight_default_mode: backlight_default {
+ skomer_cfg1 {
+ pins = "GPIO68_E1"; /* LCD_BL_CTRL */
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* Flash and torch */
+ flash {
+ gpio_flash_default_mode: flash_default {
+ codina_cfg1 {
+ pins = "GPIO140_B11", "GPIO141_C12";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* GPIO keys */
+ gpio-keys {
+ gpio_keys_default_mode: gpio_keys_default {
+ skomer_cfg1 {
+ pins = "GPIO67_G2", /* VOL UP */
+ "GPIO91_B6", /* HOME */
+ "GPIO92_D6"; /* VOL DOWN */
+ ste,config = <&gpio_in_pu>;
+ };
+ };
+ };
+ /* Interrupt line for the Zinitix BT404 touchscreen */
+ tsp {
+ tsp_default: tsp_default {
+ codina_cfg1 {
+ pins = "GPIO218_AH11"; /* TSP_INT_1V8 */
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* Interrupt line for light/proximity sensor TMS2672 */
+ tms2672 {
+ tms2672_codina_default: tms2672_codina {
+ codina_cfg1 {
+ pins = "GPIO146_D13";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based I2C bus for subpmu */
+ i2c-gpio-0 {
+ i2c_gpio_0_default: i2c_gpio_0 {
+ codina_cfg1 {
+ pins = "GPIO143_D12", "GPIO144_B13";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based I2C bus for the NFC */
+ i2c-gpio-1 {
+ i2c_gpio_1_default: i2c_gpio_1 {
+ codina_cfg1 {
+ pins = "GPIO151_D17", "GPIO152_D16";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based SPI bus for the display */
+ spi-gpio-0 {
+ spi_gpio_0_default: spi_gpio_0_d {
+ codina_cfg1 {
+ pins = "GPIO220_AH10", "GPIO201_AF24", "GPIO224_AG9";
+ ste,config = <&gpio_out_hi>;
+ };
+ codina_cfg2 {
+ pins = "GPIO225_AG8";
+ /* Needs pull down, no pull down resistor on board */
+ ste,config = <&gpio_in_pd>;
+ };
+ };
+ spi_gpio_0_sleep: spi_gpio_0_s {
+ codina_cfg1 {
+ pins = "GPIO220_AH10", "GPIO201_AF24",
+ "GPIO224_AG9", "GPIO225_AG8";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ wlan {
+ wlan_default_mode: wlan_default {
+ /* GPIO216 for WL_HOST_WAKE */
+ codina_cfg2 {
+ pins = "GPIO216_AG12";
+ ste,config = <&gpio_in_pd>;
+ };
+ };
+ };
+ bluetooth {
+ bluetooth_default_mode: bluetooth_default {
+ /* GPIO199 BT_WAKE and GPIO222 BT_VREG_ON */
+ codina_cfg1 {
+ pins = "GPIO199_AH23", "GPIO222_AJ9";
+ ste,config = <&gpio_out_lo>;
+ };
+ /* GPIO97 BT_HOST_WAKE */
+ codina_cfg2 {
+ pins = "GPIO97_D9";
+ ste,config = <&gpio_in_nopull>;
+ };
+ /* GPIO209 BT_RST_N */
+ codina_cfg3 {
+ pins = "GPIO209_AG15";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* Interrupt line for TI TSU6111 Micro USB switch */
+ tsu6111 {
+ tsu6111_codina_default: tsu6111_codina {
+ codina_cfg1 {
+ /* GPIO95 used for IRQ */
+ pins = "GPIO95_E8";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ vibrator {
+ vibrator_default: vibrator_default {
+ codina_cfg1 {
+ pins = "GPIO195_AG28"; /* MOT_EN */
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ mcde {
+ dpi_default_mode: dpi_default {
+ default_mux1 {
+ /* Mux in all the data lines */
+ function = "lcd";
+ groups =
+ /* Data lines D0-D7 GPIO70..GPIO77 */
+ "lcd_d0_d7_a_1",
+ /* Data lines D8-D11 GPIO78..GPIO81 */
+ "lcd_d8_d11_a_1",
+ /* Data lines D12-D15 GPIO82..GPIO85 */
+ "lcd_d12_d15_a_1",
+ /* Data lines D16-D23 GPIO161..GPIO168 */
+ "lcd_d16_d23_b_1";
+ };
+ default_mux2 {
+ function = "lcda";
+ /* Clock line on GPIO150, DE, VSO, HSO on GPIO169..GPIO171 */
+ groups = "lcdaclk_b_1", "lcda_b_1";
+ };
+ /* Input, no pull-up is the default state for pins used for an alt function */
+ default_cfg1 {
+ pins = "GPIO150_C14", "GPIO169_D22", "GPIO170_C23", "GPIO171_D23";
+ ste,config = <&in_nopull>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts b/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
new file mode 100644
index 000000000000..fabc390ccb0c
--- /dev/null
+++ b/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
@@ -0,0 +1,854 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Devicetree for the Samsung Galaxy Beam GT-I8530 also known as Gavini.
+ */
+
+/dts-v1/;
+#include "ste-db8500.dtsi"
+#include "ste-ab8500.dtsi"
+#include "ste-dbx5x0-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ model = "Samsung Galaxy Beam (GT-I8530)";
+ compatible = "samsung,gavini", "st-ericsson,u8500";
+
+ chosen {
+ stdout-path = &serial2;
+ };
+
+ /* TI TXS0206 level translator for 2.9 V */
+ sd_level_translator: regulator-gpio {
+ compatible = "regulator-fixed";
+
+ /* GPIO193 EN */
+ gpios = <&gpio6 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ regulator-name = "sd-level-translator";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-type = "voltage";
+
+ startup-delay-us = <200>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_level_translator_default>;
+ };
+
+ /* External LDO for eMMC LDO VMEM_3V3 controlled by GPIO6 */
+ ldo_3v3_reg: regulator-gpio-ldo-3v3 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VMEM_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>; // FIXME
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_ldo_en_default_mode>;
+ };
+
+ /*
+ * External Ricoh "TSP" regulator for the touchscreen.
+ * One GPIO line controls two voltages of 3.3V and 1.8V
+ * this line is known as "TSP_LDO_ON1" in the schematics.
+ */
+ ldo_tsp_3v3_reg: regulator-gpio-tsp-ldo-3v3 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "LDO_TSP_A3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ /* GPIO94 controls this regulator */
+ gpio = <&gpio2 30 GPIO_ACTIVE_HIGH>;
+ /* 70 ms power-on delay */
+ startup-delay-us = <70000>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_ldo_en_default_mode>;
+ };
+ ldo_tsp_1v8_reg: regulator-gpio-tsp-ldo-1v8 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VREG_TSP_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ /* GPIO94 controls this regulator */
+ gpio = <&gpio2 30 GPIO_ACTIVE_HIGH>;
+ /* 70 ms power-on delay */
+ startup-delay-us = <70000>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_ldo_en_default_mode>;
+ };
+
+ /*
+ * External Ricoh RP152L010B-TR LCD LDO regulator for the display.
+ * LCD_PWR_EN controls both a 3.0V and 1.8V output.
+ */
+ lcd_3v0_reg: regulator-gpio-lcd-3v0 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VREG_LCD_3V0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ /* GPIO219 controls this regulator */
+ gpio = <&gpio6 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pwr_en_default_mode>;
+ };
+ lcd_1v8_reg: regulator-gpio-lcd-1v8 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VREG_LCD_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ /* GPIO219 controls this regulator too */
+ gpio = <&gpio6 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pwr_en_default_mode>;
+ };
+
+ /*
+ * This regulator is a GPIO line that drives the Broadcom WLAN
+ * line WL_REG_ON high and enables the internal regulators
+ * inside the chip. Unfortunatley it is erroneously named
+ * WLAN_RST_N on the schematic but it is not a reset line.
+ *
+ * The voltage specified here is only used to determine the OCR mask,
+ * the for the SDIO connector, the chip is actually connected
+ * directly to VBAT.
+ */
+ wl_reg: regulator-gpio-wlan {
+ compatible = "regulator-fixed";
+ regulator-name = "WL_REG_ON";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ startup-delay-us = <100000>;
+ /* GPIO215 (WLAN_RST_N to WL_REG_ON) */
+ gpio = <&gpio6 23 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_ldo_en_default>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys_default_mode>;
+
+ button-projector {
+ linux,code = <KEY_SWITCHVIDEOMODE>;
+ label = "Projector";
+ /* GPIO32 "Projector On HotKey" */
+ gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+ };
+ button-home {
+ linux,code = <KEY_HOME>;
+ label = "HOME";
+ /* GPIO91 */
+ gpios = <&gpio2 27 GPIO_ACTIVE_LOW>;
+ };
+ button-volup {
+ linux,code = <KEY_VOLUMEUP>;
+ label = "VOL+";
+ /* GPIO67 */
+ gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+ };
+ button-voldown {
+ linux,code = <KEY_VOLUMEDOWN>;
+ label = "VOL-";
+ /* GPIO92 */
+ gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ /* Richtek RT8515GQW Flash LED Driver IC */
+ flash {
+ compatible = "richtek,rt8515";
+ /* GPIO 140 */
+ enf-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;
+ /* GPIO 141 */
+ ent-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
+ /*
+ * RFS is 16 kOhm and RTS is 100 kOhm giving
+ * the flash max current 343mA and torch max
+ * current 55 mA.
+ */
+ richtek,rfs-ohms = <16000>;
+ richtek,rts-ohms = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_flash_default_mode>;
+
+ led {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ flash-max-timeout-us = <250000>;
+ flash-max-microamp = <343750>;
+ led-max-microamp = <55000>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_leds_default_mode>;
+ used-led {
+ label = "touchkeys";
+ /* GPIO68 */
+ gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+ };
+
+ ktd259: backlight {
+ compatible = "kinetic,ktd259";
+ /* GPIO20 */
+ enable-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+ /* Default to 13/32 brightness */
+ default-brightness = <13>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ktd259_backlight_default_mode>;
+ };
+
+ /* Bit-banged I2C on GPIO143 and GPIO144 also called "SUBPMU I2C" */
+ i2c-gpio-0 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio4 16 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio4 15 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_gpio_0_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* TODO: Memsic MMC328 magnetometer */
+ magnetometer@30 {
+ compatible = "memsic,mmc328";
+ reg = <0x30>;
+ /* TODO: if you have the schematic, check if both voltages come from AUX2 */
+ /* VDA 1.8 V */
+ vda-supply = <&ab8500_ldo_aux2_reg>;
+ /* VDD 1.8V */
+ vdd-supply = <&ab8500_ldo_aux2_reg>;
+ /* GPIO204 */
+ reset-gpios = <&gpio6 12 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc328_default>;
+ };
+ /* TODO: this should also be used by the NCP6914 Camera power management unit */
+ };
+
+ /*
+ * TODO: See if we can use the PL023 for this instead.
+ */
+ spi-gpio-0 {
+ compatible = "spi-gpio";
+ /* Clock on GPIO220, pin SCL */
+ sck-gpios = <&gpio6 28 GPIO_ACTIVE_HIGH>;
+ /* MOSI on GPIO224, pin SDI "slave data in" */
+ mosi-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+ /* MISO on GPIO225, pin SDO "slave data out" */
+ miso-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
+ /* Chip select on GPIO223 */
+ cs-gpios = <&gpio6 31 GPIO_ACTIVE_LOW>;
+ num-chipselects = <1>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_gpio_0_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "samsung,lms397kf04";
+ /* 300 ns at read cycle -> 3 MHz max speed */
+ //spi-max-frequency = <3000000>;
+ spi-max-frequency = <1200000>;
+ /* TYPE 3: inverse clock polarity and phase */
+ spi-cpha;
+ spi-cpol;
+
+ reg = <0>;
+ vci-supply = <&lcd_3v0_reg>;
+ vccio-supply = <&lcd_1v8_reg>;
+ /* Reset on GPIO139 */
+ reset-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&panel_default_mode>;
+ backlight = <&ktd259>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&display_out>;
+ };
+ };
+ };
+ };
+
+ /* Bit-banged I2C on GPIO201 and GPIO202 also called "MOT_I2C" */
+ i2c-gpio-2 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio6 10 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio6 9 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_gpio_2_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* TODO: add the Immersion ISA1200 I2C device here */
+ };
+
+ /* Bit-banged I2C on GPIO196 and GPIO197 also called "MPR_I2C" */
+ i2c-gpio-3 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio6 5 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio6 4 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_gpio_3_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* TODO: add the DPP2601 projector I2C device 0x1b here */
+ };
+
+ soc {
+ /* External Micro SD slot */
+ mmc@80126000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ st,sig-pin-fbclk;
+ full-pwr-cycle;
+ /* MMC is powered by AUX3 1.2V .. 2.91V */
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+ /* 2.9 V level translator */
+ vqmmc-supply = <&sd_level_translator>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mc0_a_2_default>;
+ pinctrl-1 = <&mc0_a_2_sleep>;
+ /* "flash detect" actually card detect */
+ cd-gpios = <&gpio6 25 GPIO_ACTIVE_LOW>;
+ status = "okay";
+ };
+
+ /* WLAN SDIO channel */
+ mmc@80118000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+ non-removable;
+ cap-sd-highspeed;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mc1_a_2_default>;
+ pinctrl-1 = <&mc1_a_2_sleep>;
+ /*
+ * GPIO-controlled voltage enablement: this drives
+ * the WL_REG_ON line high when we use this device.
+ * Represented as regulator to fill OCR mask.
+ */
+ vmmc-supply = <&wl_reg>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ wifi@1 {
+ compatible = "brcm,bcm4330-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ /* GPIO216 WL_HOST_WAKE */
+ interrupt-parent = <&gpio6>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-names = "host-wake";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_default_mode>;
+ };
+ };
+
+ /* eMMC */
+ mmc@80005000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ no-sdio;
+ no-sd;
+ vmmc-supply = <&ldo_3v3_reg>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mc2_a_1_default>;
+ pinctrl-1 = <&mc2_a_1_sleep>;
+ status = "okay";
+ };
+
+ /* GBF (Bluetooth) UART */
+ uart@80120000 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&u0_a_1_default>;
+ pinctrl-1 = <&u0_a_1_sleep>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4330-bt";
+ /* GPIO222 rail BT_VREG_EN to BT_REG_ON */
+ shutdown-gpios = <&gpio6 30 GPIO_ACTIVE_HIGH>;
+ /* BT_WAKE on GPIO199 */
+ device-wakeup-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+ /* BT_HOST_WAKE on GPIO97 */
+ host-wakeup-gpios = <&gpio3 1 GPIO_ACTIVE_HIGH>;
+ /* BT_RST_N on GPIO209 */
+ reset-gpios = <&gpio6 17 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bluetooth_default_mode>;
+ };
+ };
+
+ /* GPS UART */
+ uart@80121000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ /* CTS/RTS is not used, CTS is repurposed as GPIO */
+ pinctrl-0 = <&u1rxtx_a_1_default>;
+ pinctrl-1 = <&u1rxtx_a_1_sleep>;
+ /* FIXME: add a device for the GPS here */
+ };
+
+ /* Debugging console UART connected to TSU6111RSVR (FSA880) */
+ uart@80007000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&u2rxtx_c_1_default>;
+ pinctrl-1 = <&u2rxtx_c_1_sleep>;
+ };
+
+ prcmu@80157000 {
+ ab8500 {
+ ab8500_usb {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&usb_a_1_default>;
+ pinctrl-1 = <&usb_a_1_sleep>;
+ };
+
+ ab8500-regulators {
+ ab8500_ldo_aux1 {
+ /* Used for VDD for sensors */
+ regulator-name = "V-SENSORS-VDD";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ ab8500_ldo_aux2 {
+ /* Used for VIO for sensors */
+ regulator-name = "V-SENSORS-VIO";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ab8500_ldo_aux3 {
+ /* Used for voltage for external MMC/SD card */
+ regulator-name = "V-MMC-SD";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <2910000>;
+ };
+ };
+ };
+ };
+
+ /* I2C0 */
+ i2c@80004000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c0_a_1_default>;
+ pinctrl-1 = <&i2c0_a_1_sleep>;
+
+ /* FIXME: fix the proximity sensor bindings and driver */
+ proximity@39 {
+ /* Gavini has the GP2A030S00F proximity sensor */
+ compatible = "sharp,gp2a030s00f";
+ clock-frequency = <400000>;
+ reg = <0x39>;
+ /* FIXME: GPIO146 provides power on, IR LED? */
+ };
+
+ gyroscope@68 {
+ compatible = "invensense,mpu3050";
+ reg = <0x68>;
+ /* GPIO226 interrupt */
+ interrupt-parent = <&gpio7>;
+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+ mount-matrix = "0", "1", "0",
+ "1", "0", "0",
+ "0", "0", "1";
+ vlogic-supply = <&ab8500_ldo_aux2_reg>; // 1.8V
+ vdd-supply = <&ab8500_ldo_aux1_reg>; // 3V
+ pinctrl-names = "default";
+ pinctrl-0 = <&mpu3050_default>;
+
+ /*
+ * The MPU-3050 acts as a hub for the
+ * accelerometer.
+ */
+ i2c-gate {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Bosch BMA222E accelerometer */
+ accelerometer@18 {
+ compatible = "bosch,bma222e";
+ reg = <0x18>;
+ mount-matrix = "0", "1", "0",
+ "-1", "0", "0",
+ "0", "0", "1";
+ vddio-supply = <&ab8500_ldo_aux2_reg>; // 1.8V
+ vdd-supply = <&ab8500_ldo_aux1_reg>; // 3V
+ };
+ };
+ };
+ };
+
+ /* I2C2 "AGC I2C" */
+ i2c@80128000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c2_b_1_default>;
+ pinctrl-1 = <&i2c2_b_1_sleep>;
+
+ /* Texas Instruments TSU6111 micro USB switch */
+ usb-switch@25 {
+ compatible = "ti,tsu6111";
+ reg = <0x25>;
+ /* Interrupt JACK_INT_N on GPIO95 */
+ interrupt-parent = <&gpio2>;
+ interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsu6111_default>;
+ };
+ };
+
+ /* I2C3 */
+ i2c@80110000 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c3_c_2_default>;
+ pinctrl-1 = <&i2c3_c_2_sleep>;
+
+ /* Melfas MMS136 touchscreen */
+ touchscreen@48 {
+ compatible = "melfas,mms136";
+ reg = <0x48>;
+ /* GPIO218 (TSP_INT_1V8) */
+ interrupt-parent = <&gpio6>;
+ interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
+ /* AVDD is "analog supply", 2.57-3.47 V */
+ avdd-supply = <&ldo_tsp_3v3_reg>;
+ /* VDD is "digital supply" 1.71-3.47V */
+ vdd-supply = <&ldo_tsp_1v8_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_default>;
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <800>;
+ };
+ };
+
+ mcde@a0350000 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dpi_default_mode>;
+
+ port {
+ display_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+ };
+};
+
+&pinctrl {
+ /*
+ * This extends the MC0_A_2 default config to include
+ * the card detect GPIO217 line.
+ */
+ sdi0 {
+ mc0_a_2_default {
+ default_cfg4 {
+ pins = "GPIO217_AH12"; /* card detect */
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ mcde {
+ dpi_default_mode: dpi_default {
+ default_mux1 {
+ /* Mux in all the data lines */
+ function = "lcd";
+ groups =
+ /* Data lines D0-D7 GPIO70..GPIO77 */
+ "lcd_d0_d7_a_1",
+ /* Data lines D8-D11 GPIO78..GPIO81 */
+ "lcd_d8_d11_a_1",
+ /* Data lines D12-D15 GPIO82..GPIO85 */
+ "lcd_d12_d15_a_1",
+ /* Data lines D16-D23 GPIO161..GPIO168 */
+ "lcd_d16_d23_b_1";
+ };
+ default_mux2 {
+ function = "lcda";
+ /* Clock line on GPIO150, DE, VSO, HSO on GPIO169..GPIO171 */
+ groups = "lcdaclk_b_1", "lcda_b_1";
+ };
+ /* Input, no pull-up is the default state for pins used for an alt function */
+ default_cfg1 {
+ pins = "GPIO150_C14", "GPIO169_D22", "GPIO170_C23", "GPIO171_D23";
+ ste,config = <&in_nopull>;
+ };
+ };
+ };
+ /* GPIO for panel reset control */
+ panel {
+ panel_default_mode: panel_default {
+ gavini_cfg1 {
+ /* Reset line */
+ pins = "GPIO139_C9";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the eMMC */
+ emmc-ldo {
+ emmc_ldo_en_default_mode: emmc_ldo_default {
+ /* LDO enable on GPIO6 */
+ gavini_cfg1 {
+ pins = "GPIO6_AF6";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the touchscreen */
+ tsp-ldo {
+ tsp_ldo_en_default_mode: tsp_ldo_default {
+ /* LDO enable on GPIO94 */
+ gavini_cfg1 {
+ pins = "GPIO94_D7";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* Flash and torch */
+ flash {
+ gpio_flash_default_mode: flash_default {
+ janice_cfg1 {
+ pins = "GPIO140_B11", "GPIO141_C12";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the key LED */
+ gpio-leds {
+ gpio_leds_default_mode: gpio_leds_default {
+ /* EN_LED_LDO on GPIO68 */
+ gavini_cfg1 {
+ pins = "GPIO68_E1";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ backlight {
+ ktd259_backlight_default_mode: backlight_default {
+ skomer_cfg1 {
+ pins = "GPIO20_AB4"; /* LCD_BL_EN */
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the touchkeys */
+ touchkey-ldo {
+ tsp_ldo_on2_default_mode: tsp_ldo_on2_default {
+ /* TSP_LDO_ON2 on GPIO89 */
+ gavini_cfg1 {
+ pins = "GPIO89_E6";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ touchkey {
+ touchkey_default_mode: touchkey_default {
+ gavini_cfg1 {
+ /* Interrupt */
+ pins = "GPIO198_AG25";
+ ste,config = <&gpio_in_nopull>;
+ };
+ gavini_cfg2 {
+ /* Reset, actually completely unused (not routed) */
+ pins = "GPIO205_AG23";
+ ste,config = <&gpio_in_pd>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the LCD display */
+ lcd-ldo {
+ lcd_pwr_en_default_mode: lcd_pwr_en_default {
+ /* LCD_PWR_EN on GPIO219 */
+ gavini_cfg1 {
+ pins = "GPIO219_AG10";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO that enables the WLAN internal LDO regulators */
+ wlan-ldo {
+ wlan_ldo_en_default: wlan_ldo_default {
+ /* GPIO215 named WLAN_RST_N */
+ gavini_cfg1 {
+ pins = "GPIO215_AH13";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* GPIO that enables the 2.9V SD card level translator */
+ sd-level-translator {
+ sd_level_translator_default: sd_level_translator_default {
+ /* level shifter on GPIO193 */
+ skomer_cfg1 {
+ pins = "GPIO193_AH27";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO keys */
+ gpio-keys {
+ gpio_keys_default_mode: gpio_keys_default {
+ skomer_cfg1 {
+ pins = "GPIO32_V2", /* Projector On HotKey */
+ "GPIO67_G2", /* VOL UP */
+ "GPIO91_B6", /* HOME */
+ "GPIO92_D6"; /* VOL DOWN */
+ ste,config = <&gpio_in_pu>;
+ };
+ };
+ };
+ /* Interrupt line for the Atmel MXT228 touchscreen */
+ tsp {
+ tsp_default: tsp_default {
+ gavini_cfg1 {
+ pins = "GPIO218_AH11"; /* TSP_INT_1V8 */
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* Reset line for the Memsic MMC328 magnetometer */
+ mmc328 {
+ mmc328_default: mmc328_gavini {
+ gavini_cfg1 {
+ pins = "GPIO204_AF23";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* Interrupt line for Invensense MPU3050 gyroscope */
+ mpu3050 {
+ mpu3050_default: mpu3050 {
+ gavini_cfg1 {
+ /* GPIO226 used for IRQ */
+ pins = "GPIO226_AF8";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based I2C bus for magnetometer and NCP6914 */
+ i2c-gpio-0 {
+ i2c_gpio_0_default: i2c_gpio_0 {
+ gavini_cfg1 {
+ pins = "GPIO143_D12", "GPIO144_B13";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based I2C bus for the Immersion ISA1200 */
+ i2c-gpio-2 {
+ i2c_gpio_2_default: i2c_gpio_2 {
+ gavini_cfg1 {
+ pins = "GPIO201_AF24", "GPIO202_AF25";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based I2C bus for the TI DPP2601 */
+ i2c-gpio-3 {
+ i2c_gpio_3_default: i2c_gpio_3 {
+ gavini_cfg1 {
+ pins = "GPIO196_AG26", "GPIO197_AH24";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based SPI bus for the display */
+ spi-gpio-0 {
+ spi_gpio_0_default: spi_gpio_0_d {
+ gavini_cfg1 {
+ pins = "GPIO220_AH10", "GPIO223_AH9", "GPIO224_AG9";
+ ste,config = <&gpio_out_hi>;
+ };
+ gavini_cfg2 {
+ pins = "GPIO225_AG8";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ spi_gpio_0_sleep: spi_gpio_0_s {
+ gavini_cfg1 {
+ pins = "GPIO220_AH10", "GPIO223_AH9",
+ "GPIO224_AG9", "GPIO225_AG8";
+ ste,config = <&gpio_out_hi>;
+ };
+ gavini_cfg2 {
+ pins = "GPIO225_AG8";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ wlan {
+ wlan_default_mode: wlan_default {
+ /* GPIO216 for WL_HOST_WAKE */
+ gavini_cfg2 {
+ pins = "GPIO216_AG12";
+ ste,config = <&gpio_in_pd>;
+ };
+ };
+ };
+ bluetooth {
+ bluetooth_default_mode: bluetooth_default {
+ /* GPIO199 BT_WAKE and GPIO222 BT_VREG_ON */
+ gavini_cfg1 {
+ pins = "GPIO199_AH23", "GPIO222_AJ9";
+ ste,config = <&gpio_out_lo>;
+ };
+ /* GPIO97 BT_HOST_WAKE */
+ gavini_cfg2 {
+ pins = "GPIO97_D9";
+ ste,config = <&gpio_in_nopull>;
+ };
+ /* GPIO209 BT_RST_N */
+ gavini_cfg3 {
+ pins = "GPIO209_AG15";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* Interrupt line for TI TSU6111 Micro USB switch */
+ tsu6111 {
+ tsu6111_default: tsu6111 {
+ gavini_cfg1 {
+ /* GPIO95 used for IRQ */
+ pins = "GPIO95_E8";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-golden.dts b/arch/arm/boot/dts/ste-ux500-samsung-golden.dts
index 40df7c61bf69..ee6379ab688c 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-golden.dts
+++ b/arch/arm/boot/dts/ste-ux500-samsung-golden.dts
@@ -145,6 +145,8 @@
non-removable;
cap-mmc-highspeed;
mmc-ddr-1_8v;
+ no-sdio;
+ no-sd;
vmmc-supply = <&vmem_3v3>;
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-janice.dts b/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
index 25af066f6f3a..f14cf316a70a 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
+++ b/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
@@ -420,6 +420,8 @@
non-removable;
cap-mmc-highspeed;
mmc-ddr-1_8v;
+ no-sdio;
+ no-sd;
vmmc-supply = <&ldo_3v3_reg>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mc2_a_1_default>;
@@ -580,7 +582,7 @@
#size-cells = <0>;
/* Bosch BMA222 accelerometer */
- accelerometer@08 {
+ accelerometer@8 {
compatible = "bosch,bma222";
reg = <0x08>;
mount-matrix = "0", "1", "0",
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts b/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
new file mode 100644
index 000000000000..3b825666d302
--- /dev/null
+++ b/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
@@ -0,0 +1,664 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Devicetree for the Samsung Galaxy Amp SGH-I407 also known as Kyle.
+ *
+ * The code also refers to "Kyle AT&T" reflecting that this mobile phone
+ * was customized for the AT&T subsidiary Aio Wireless (All In One) and
+ * offered by the company in 2013.
+ */
+
+/dts-v1/;
+#include "ste-db8500.dtsi"
+#include "ste-ab8505.dtsi"
+#include "ste-dbx5x0-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ model = "Samsung Galaxy Amp (SGH-I407)";
+ compatible = "samsung,kyle", "st-ericsson,u8500";
+
+ chosen {
+ stdout-path = &serial2;
+ };
+
+ /* TI TXS0206 level translator for 2.9 V */
+ sd_level_translator: regulator-gpio {
+ compatible = "regulator-fixed";
+
+ /* GPIO87 EN */
+ gpios = <&gpio2 23 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ regulator-name = "sd-level-translator";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-type = "voltage";
+
+ startup-delay-us = <200>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_level_translator_default>;
+ };
+
+ /* External LDO MIC5366-3.3YMT for eMMC */
+ ldo_3v3_reg: regulator-gpio-ldo-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "en-3v3-fixed-supply";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio6 31 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_ldo_en_default_mode>;
+ };
+
+ /*
+ * External Ricoh RP152L010B-TR LCD LDO regulator for the display.
+ * LCD_PWR_EN controls both a 3.0V and 1.8V output.
+ */
+ lcd_3v0_reg: regulator-gpio-lcd-3v0 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VREG_LCD_3V0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ /* GPIO219 controls this regulator */
+ gpio = <&gpio6 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pwr_en_default_mode>;
+ };
+ lcd_1v8_reg: regulator-gpio-lcd-1v8 {
+ compatible = "regulator-fixed";
+ /* Supplied in turn by VBAT */
+ regulator-name = "VREG_LCD_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ /* GPIO219 controls this regulator too */
+ gpio = <&gpio6 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pwr_en_default_mode>;
+ };
+
+ wlan_en: regulator-gpio-wlan-en {
+ compatible = "regulator-fixed";
+ regulator-name = "wl-reg-on";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ startup-delay-us = <200000>;
+ /* GPIO215 WLAN_EN */
+ gpio = <&gpio6 23 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_en_default_mode>;
+ };
+
+ vibrator {
+ compatible = "gpio-vibrator";
+ enable-gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vibrator_default>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys_default_mode>;
+
+ button-home {
+ linux,code = <KEY_HOME>;
+ label = "HOME";
+ /* GPIO91 */
+ gpios = <&gpio2 27 GPIO_ACTIVE_LOW>;
+ };
+ button-volup {
+ linux,code = <KEY_VOLUMEUP>;
+ label = "VOL+";
+ /* GPIO67 */
+ gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+ };
+ button-voldown {
+ linux,code = <KEY_VOLUMEDOWN>;
+ label = "VOL-";
+ /* GPIO92 */
+ gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ ktd253: backlight {
+ compatible = "kinetic,ktd253";
+ /* GPIO 69 */
+ enable-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+ /* Default to 13/32 brightness */
+ default-brightness = <13>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_backlight_default_mode>;
+ };
+
+ /* Richtek RT8515GQW Flash LED Driver IC */
+ flash {
+ compatible = "richtek,rt8515";
+ /* GPIO 140 */
+ enf-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;
+ /* GPIO 141 */
+ ent-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
+ /*
+ * RFS is 16 kOhm and RTS is 100 kOhm giving
+ * the flash max current 343mA and torch max
+ * current 55 mA.
+ */
+ richtek,rfs-ohms = <16000>;
+ richtek,rts-ohms = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_flash_default_mode>;
+
+ led {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ flash-max-timeout-us = <250000>;
+ flash-max-microamp = <343750>;
+ led-max-microamp = <55000>;
+ };
+ };
+
+ i2c-gpio-0 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio4 16 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio4 15 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_gpio_0_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* TODO: this should be used by the NCP6914 Camera power management unit */
+ };
+
+ i2c-gpio-1 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&gpio4 24 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&gpio4 23 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c_gpio_1_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ magnetometer@c {
+ compatible = "alps,hscdtd008a";
+ reg = <0x0c>;
+ avdd-supply = <&ab8500_ldo_aux1_reg>;
+ dvdd-supply = <&ab8500_ldo_aux6_reg>;
+ };
+ };
+
+ soc {
+ // External Micro SD slot
+ mmc@80126000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <100000000>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ st,sig-pin-fbclk;
+ full-pwr-cycle;
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+ vqmmc-supply = <&sd_level_translator>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mc0_a_1_default>;
+ pinctrl-1 = <&mc0_a_1_sleep>;
+ cd-gpios = <&gpio6 25 GPIO_ACTIVE_LOW>; // GPIO217
+ status = "okay";
+ };
+
+ // WLAN SDIO channel
+ mmc@80118000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <50000000>;
+ bus-width = <4>;
+ non-removable;
+ cap-sd-highspeed;
+ vmmc-supply = <&wlan_en>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mc1_a_2_default>;
+ pinctrl-1 = <&mc1_a_2_sleep>;
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ wifi@1 {
+ compatible = "brcm,bcm4334-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ /* GPIO216 WL_HOST_WAKE */
+ interrupt-parent = <&gpio6>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-names = "host-wake";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_default_mode>;
+ };
+ };
+
+ /*
+ * eMMC seems to be mostly Samsung KLM4G1YE4C "4YMD1R"
+ */
+ mmc@80005000 {
+ arm,primecell-periphid = <0x10480180>;
+ max-frequency = <100000000>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ no-sdio;
+ no-sd;
+ /* From datasheet page 26 figure 9: 300 ms set-up time for 4GB */
+ post-power-on-delay-ms = <300>;
+ vmmc-supply = <&ldo_3v3_reg>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mc2_a_1_default>;
+ pinctrl-1 = <&mc2_a_1_sleep>;
+
+ status = "okay";
+ };
+
+ /* GBF (Bluetooth) UART */
+ uart@80120000 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&u0_a_1_default>;
+ pinctrl-1 = <&u0_a_1_sleep>;
+ status = "okay";
+
+ bluetooth {
+ /* BCM4334B0 actually */
+ compatible = "brcm,bcm4330-bt";
+ shutdown-gpios = <&gpio6 30 GPIO_ACTIVE_HIGH>;
+ device-wakeup-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio3 1 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bluetooth_default_mode>;
+ };
+ };
+
+ /* GPF UART */
+ uart@80121000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&u1rxtx_a_1_default &u1ctsrts_a_1_default>;
+ pinctrl-1 = <&u1rxtx_a_1_sleep &u1ctsrts_a_1_sleep>;
+ };
+
+ /* Debugging console UART connected to AB8505 USB */
+ uart@80007000 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&u2rxtx_c_1_default>;
+ pinctrl-1 = <&u2rxtx_c_1_sleep>;
+ };
+
+ prcmu@80157000 {
+ ab8505 {
+ ab8500_usb {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&usb_a_1_default>;
+ pinctrl-1 = <&usb_a_1_sleep>;
+ };
+
+ ab8505-regulators {
+ ab8500_ldo_aux1 {
+ /* Used for VDD for sensors */
+ regulator-name = "AUX1";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ab8500_ldo_aux2 {
+ /* Supplies the MMS touchscreen only with 3.3V */
+ regulator-name = "AUX2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ab8500_ldo_aux3 {
+ /* Used for voltage for external MMC/SD card */
+ regulator-name = "AUX3";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ab8500_ldo_aux4 {
+ regulator-name = "AUX4";
+ /* Hammer to 3.3V for the touchscreen */
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ab8500_ldo_aux5 {
+ regulator-name = "AUX5";
+ /* 1.8V for the touchscreen */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ab8500_ldo_aux6 {
+ regulator-name = "AUX6";
+ /* Used by sensors for 1.8 V in R0.1+ */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ab8500_ldo_aux8 {
+ /* Unused */
+ regulator-name = "AUX8";
+ };
+ };
+ };
+ };
+
+ /* I2C0 */
+ i2c@80004000 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c0_a_1_default>;
+ pinctrl-1 = <&i2c0_a_1_sleep>;
+
+ proximity@44 {
+ compatible = "sharp,gp2ap002s00f";
+ clock-frequency = <400000>;
+ reg = <0x44>;
+
+ interrupt-parent = <&gpio4>;
+ interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vio-supply = <&ab8500_ldo_aux6_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gp2ap002_kyle_default>;
+ sharp,proximity-far-hysteresis = /bits/ 8 <0x2f>;
+ sharp,proximity-close-hysteresis = /bits/ 8 <0x0f>;
+ };
+ };
+
+ /* I2C2 */
+ i2c@80128000 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c2_b_2_default>;
+ pinctrl-1 = <&i2c2_b_2_sleep>;
+
+ accel@18 {
+ compatible = "bosch,bma254";
+ clock-frequency = <400000>;
+ reg = <0x18>;
+
+ mount-matrix = "-1", "0", "0",
+ "0", "-1", "0",
+ "0", "0", "-1";
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&ab8500_ldo_aux6_reg>;
+ };
+ };
+
+ /* I2C3 */
+ i2c@80110000 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&i2c3_c_2_default>;
+ pinctrl-1 = <&i2c3_c_2_sleep>;
+
+ /* Melfas MMS134S touchscreen */
+ touchscreen@48 {
+ compatible = "melfas,mms134s";
+ reg = <0x48>;
+ /* GPIO218 for IRQ */
+ interrupt-parent = <&gpio6>;
+ interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
+ /* AVDD is "analog supply", 2.57-3.47 V */
+ avdd-supply = <&ab8500_ldo_aux2_reg>;
+ /* VDD is "digital supply" 1.71-3.47V */
+ vdd-supply = <&ab8500_ldo_aux5_reg>;
+
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <800>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&mms134s_kyle_default>;
+ };
+ };
+
+ mcde@a0350000 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dsi_default_mode>;
+
+ dsi@a0351000 {
+ panel {
+ /*
+ * NT35510-based Hydis HVA40WV1
+ * Apparently some Kyle models can have a NT35512 fitted
+ * here instead. In that case the boot loader needs to
+ * modify this compatible.
+ */
+ compatible = "hydis,hva40wv1", "novatek,nt35510";
+ reg = <0>;
+ /* v_lcd_3v0 2.3-4.8V */
+ vdd-supply = <&lcd_3v0_reg>;
+ /* v_lcd_1v8 1.65-3.3V */
+ vddi-supply = <&lcd_1v8_reg>;
+ /* GPIO 139 */
+ reset-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&display_default_mode>;
+ backlight = <&ktd253>;
+ };
+ };
+ };
+ };
+};
+
+&pinctrl {
+ /*
+ * This extends the MC0_A_1 default config to include
+ * the card detect GPIO217 line.
+ */
+ sdi0 {
+ mc0_a_1_default {
+ default_cfg1 {
+ /* GPIO18, 19 & 20 unused so pull down */
+ ste,config = <&gpio_in_pd>;
+ };
+ default_cfg4 {
+ pins = "GPIO217_AH12"; /* card detect */
+ ste,config = <&gpio_in_pd>;
+ };
+ };
+ };
+
+ mcde {
+ dsi_default_mode: dsi_default {
+ default_mux1 {
+ /* Mux in VSI0 used for DSI TE */
+ function = "lcd";
+ groups = "lcdvsi0_a_1"; /* VSI0 for LCD */
+ };
+ default_cfg1 {
+ pins = "GPIO68_E1"; /* VSI0 */
+ ste,config = <&in_nopull>;
+ };
+ };
+ };
+
+ /* Two GPIO lines used by the display */
+ display {
+ display_default_mode: display_default {
+ kyle_cfg1 {
+ /*
+ * OLED DETECT or check_pba, this appears to be high
+ * on "PBA" which I guess is "prototype board A".
+ */
+ pins = "GPIO93_B7";
+ ste,config = <&gpio_in_nopull>;
+ };
+ kyle_cfg2 {
+ pins = "GPIO139_C9";
+ /*
+ * MIPI_DSI0_RESET_N resets the display, leave high
+ * (de-asserted) so we only assert reset explicitly
+ * from the display driver.
+ */
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+
+ /* GPIO that enables the LDO regulator for the LCD display */
+ lcd-ldo {
+ lcd_pwr_en_default_mode: lcd_pwr_en_default {
+ /* LCD_PWR_EN on GPIO219 */
+ kyle_cfg1 {
+ pins = "GPIO219_AG10";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+
+ backlight {
+ gpio_backlight_default_mode: backlight_default {
+ kyle_cfg1 {
+ pins = "GPIO69_E2"; /* LCD_BL_CTRL */
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ flash {
+ gpio_flash_default_mode: flash_default {
+ kyle_cfg1 {
+ pins = "GPIO140_B11", "GPIO141_C12";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* GPIO that enables the 2.9V SD card level translator */
+ sd-level-translator {
+ sd_level_translator_default: sd_level_translator_default {
+ /* level shifter on GPIO87 */
+ kyle_cfg1 {
+ pins = "GPIO87_B3";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO that enables the LDO regulator for the eMMC */
+ emmc-ldo {
+ emmc_ldo_en_default_mode: emmc_ldo_default {
+ /* LDO enable on GPIO223 */
+ kyle_cfg1 {
+ pins = "GPIO223_AH9";
+ ste,config = <&gpio_out_hi>;
+ };
+ };
+ };
+ /* GPIO keys */
+ gpio-keys {
+ gpio_keys_default_mode: gpio_keys_default {
+ kyle_cfg1 {
+ pins = "GPIO67_G2", /* VOL UP */
+ "GPIO91_B6", /* HOME */
+ "GPIO92_D6"; /* VOL DOWN */
+ ste,config = <&gpio_in_pu>;
+ };
+ };
+ };
+ /* Interrupt line for light/proximity sensor GP2AP002 */
+ gp2ap002 {
+ gp2ap002_kyle_default: gp2ap002_kyle {
+ kyle_cfg1 {
+ pins = "GPIO146_D13";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based I2C bus for NCP6914 */
+ i2c-gpio-0 {
+ i2c_gpio_0_default: i2c_gpio_0 {
+ kyle_cfg1 {
+ pins = "GPIO143_D12", "GPIO144_B13";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ /* GPIO-based I2C bus for ALPS HSCD compass */
+ i2c-gpio-1 {
+ i2c_gpio_1_default: i2c_gpio_1 {
+ kyle_cfg1 {
+ pins = "GPIO151_B17", "GPIO152_D16";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ wlan {
+ wlan_default_mode: wlan_default {
+ kyle_cfg1 {
+ pins = "GPIO216_AG12";
+ ste,config = <&gpio_in_pd>;
+ };
+ };
+ wlan_en_default_mode: wlan_en_default {
+ kyle_cfg2 {
+ pins = "GPIO215_AH13";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ bluetooth {
+ bluetooth_default_mode: bluetooth_default {
+ kyle_cfg1 {
+ pins = "GPIO199_AH23", "GPIO222_AJ9";
+ ste,config = <&gpio_out_lo>;
+ };
+ kyle_cfg2 {
+ pins = "GPIO97_D9";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+ vibrator {
+ vibrator_default: vibrator_default {
+ kyle_cfg1 {
+ pins = "GPIO195_AG28"; /* MOT_EN */
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
+ /* Interrupt line for the Melfas MMS134S touchscreen */
+ touchscreen {
+ mms134s_kyle_default: mms134s_kyle {
+ kyle_cfg1 {
+ pins = "GPIO218_AH11";
+ ste,config = <&gpio_in_nopull>;
+ };
+ };
+ };
+};
+
+&ab8505_gpio {
+ /* Hog a few default settings */
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_default>;
+
+ gpio {
+ gpio_default: gpio_default {
+ kyle_mux {
+ /* Change unused pins to GPIO mode */
+ function = "gpio";
+ groups = "gpio3_a_1", /* default: SysClkReq4 */
+ "gpio14_a_1"; /* default: PWMOut1 */
+ };
+ kyle_cfg1 {
+ pins = "GPIO11_B17", "GPIO13_D17", "GPIO50_L4";
+ bias-disable;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
index 94afd7a0fe1f..264f3e9b5fce 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
+++ b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
@@ -230,6 +230,8 @@
non-removable;
cap-mmc-highspeed;
mmc-ddr-1_8v;
+ no-sdio;
+ no-sd;
vmmc-supply = <&ldo_3v3_reg>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mc2_a_1_default>;
diff --git a/arch/arm/boot/dts/stih407-b2120.dts b/arch/arm/boot/dts/stih407-b2120.dts
index 31c85f945c6b..9c79982ee7ba 100644
--- a/arch/arm/boot/dts/stih407-b2120.dts
+++ b/arch/arm/boot/dts/stih407-b2120.dts
@@ -11,7 +11,6 @@
compatible = "st,stih407-b2120", "st,stih407";
chosen {
- bootargs = "clk_ignore_unused";
stdout-path = &sbc_serial0;
};
diff --git a/arch/arm/boot/dts/stih407-clock.dtsi b/arch/arm/boot/dts/stih407-clock.dtsi
index 1ab40db7c91a..9cce9541e26b 100644
--- a/arch/arm/boot/dts/stih407-clock.dtsi
+++ b/arch/arm/boot/dts/stih407-clock.dtsi
@@ -36,8 +36,6 @@
compatible = "st,stih407-clkgen-plla9";
clocks = <&clk_sysin>;
-
- clock-output-names = "clockgen-a9-pll-odf";
};
};
@@ -74,24 +72,18 @@
clk_s_a0_pll: clk-s-a0-pll {
#clock-cells = <1>;
- compatible = "st,clkgen-pll0";
+ compatible = "st,clkgen-pll0-a0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-a0-pll-ofd-0";
- clock-critical = <0>; /* clk-s-a0-pll-ofd-0 */
};
clk_s_a0_flexgen: clk-s-a0-flexgen {
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih407-a0";
#clock-cells = <1>;
clocks = <&clk_s_a0_pll 0>,
<&clk_sysin>;
-
- clock-output-names = "clk-ic-lmi0";
- clock-critical = <CLK_IC_LMI0>;
};
};
@@ -101,12 +93,6 @@
reg = <0x9103000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-fs0-ch0",
- "clk-s-c0-fs0-ch1",
- "clk-s-c0-fs0-ch2",
- "clk-s-c0-fs0-ch3";
- clock-critical = <0>; /* clk-s-c0-fs0-ch0 */
};
clk_s_c0: clockgen-c@9103000 {
@@ -115,26 +101,21 @@
clk_s_c0_pll0: clk-s-c0-pll0 {
#clock-cells = <1>;
- compatible = "st,clkgen-pll0";
+ compatible = "st,clkgen-pll0-c0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-pll0-odf-0";
- clock-critical = <0>; /* clk-s-c0-pll0-odf-0 */
};
clk_s_c0_pll1: clk-s-c0-pll1 {
#clock-cells = <1>;
- compatible = "st,clkgen-pll1";
+ compatible = "st,clkgen-pll1-c0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-pll1-odf-0";
};
clk_s_c0_flexgen: clk-s-c0-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih407-c0";
clocks = <&clk_s_c0_pll0 0>,
<&clk_s_c0_pll1 0>,
@@ -144,45 +125,6 @@
<&clk_s_c0_quadfs 3>,
<&clk_sysin>;
- clock-output-names = "clk-icn-gpu",
- "clk-fdma",
- "clk-nand",
- "clk-hva",
- "clk-proc-stfe",
- "clk-proc-tp",
- "clk-rx-icn-dmu",
- "clk-rx-icn-hva",
- "clk-icn-cpu",
- "clk-tx-icn-dmu",
- "clk-mmc-0",
- "clk-mmc-1",
- "clk-jpegdec",
- "clk-ext2fa9",
- "clk-ic-bdisp-0",
- "clk-ic-bdisp-1",
- "clk-pp-dmu",
- "clk-vid-dmu",
- "clk-dss-lpc",
- "clk-st231-aud-0",
- "clk-st231-gp-1",
- "clk-st231-dmu",
- "clk-icn-lmi",
- "clk-tx-icn-disp-1",
- "clk-icn-sbc",
- "clk-stfe-frc2",
- "clk-eth-phy",
- "clk-eth-ref-phyclk",
- "clk-flash-promip",
- "clk-main-disp",
- "clk-aux-disp",
- "clk-compo-dvp";
- clock-critical = <CLK_PROC_STFE>,
- <CLK_ICN_CPU>,
- <CLK_TX_ICN_DMU>,
- <CLK_EXT2F_A9>,
- <CLK_ICN_LMI>,
- <CLK_ICN_SBC>;
-
/*
* ARM Peripheral clock for timers
*/
@@ -202,15 +144,10 @@
clk_s_d0_quadfs: clk-s-d0-quadfs@9104000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d0";
reg = <0x9104000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d0-fs0-ch0",
- "clk-s-d0-fs0-ch1",
- "clk-s-d0-fs0-ch2",
- "clk-s-d0-fs0-ch3";
};
clockgen-d0@9104000 {
@@ -219,32 +156,22 @@
clk_s_d0_flexgen: clk-s-d0-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen-audio", "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih407-d0";
clocks = <&clk_s_d0_quadfs 0>,
<&clk_s_d0_quadfs 1>,
<&clk_s_d0_quadfs 2>,
<&clk_s_d0_quadfs 3>,
<&clk_sysin>;
-
- clock-output-names = "clk-pcm-0",
- "clk-pcm-1",
- "clk-pcm-2",
- "clk-spdiff";
};
};
clk_s_d2_quadfs: clk-s-d2-quadfs@9106000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d2";
reg = <0x9106000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d2-fs0-ch0",
- "clk-s-d2-fs0-ch1",
- "clk-s-d2-fs0-ch2",
- "clk-s-d2-fs0-ch3";
};
clockgen-d2@9106000 {
@@ -253,7 +180,7 @@
clk_s_d2_flexgen: clk-s-d2-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen-video", "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih407-d2";
clocks = <&clk_s_d2_quadfs 0>,
<&clk_s_d2_quadfs 1>,
@@ -262,37 +189,15 @@
<&clk_sysin>,
<&clk_sysin>,
<&clk_tmdsout_hdmi>;
-
- clock-output-names = "clk-pix-main-disp",
- "clk-pix-pip",
- "clk-pix-gdp1",
- "clk-pix-gdp2",
- "clk-pix-gdp3",
- "clk-pix-gdp4",
- "clk-pix-aux-disp",
- "clk-denc",
- "clk-pix-hddac",
- "clk-hddac",
- "clk-sddac",
- "clk-pix-dvo",
- "clk-dvo",
- "clk-pix-hdmi",
- "clk-tmds-hdmi",
- "clk-ref-hdmiphy";
- };
+ };
};
clk_s_d3_quadfs: clk-s-d3-quadfs@9107000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d3";
reg = <0x9107000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d3-fs0-ch0",
- "clk-s-d3-fs0-ch1",
- "clk-s-d3-fs0-ch2",
- "clk-s-d3-fs0-ch3";
};
clockgen-d3@9107000 {
@@ -301,22 +206,13 @@
clk_s_d3_flexgen: clk-s-d3-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih407-d3";
clocks = <&clk_s_d3_quadfs 0>,
<&clk_s_d3_quadfs 1>,
<&clk_s_d3_quadfs 2>,
<&clk_s_d3_quadfs 3>,
<&clk_sysin>;
-
- clock-output-names = "clk-stfe-frc1",
- "clk-tsout-0",
- "clk-tsout-1",
- "clk-mchi",
- "clk-vsens-compo",
- "clk-frc1-remote",
- "clk-lpc-0",
- "clk-lpc-1";
};
};
};
diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index 23a1746f3baa..21f3347a91d6 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -616,6 +616,21 @@
st,lpc-mode = <ST_LPC_MODE_CLKSRC>;
};
+ spifsm: spifsm@9022000{
+ compatible = "st,spi-fsm";
+ reg = <0x9022000 0x1000>;
+ reg-names = "spi-fsm";
+ clocks = <&clk_s_c0_flexgen CLK_FLASH_PROMIP>;
+ clock-names = "emi_clk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fsm>;
+ st,syscfg = <&syscfg_core>;
+ st,boot-device-reg = <0x8c4>;
+ st,boot-device-spi = <0x68>;
+
+ status = "disabled";
+ };
+
sata0: sata@9b20000 {
compatible = "st,ahci";
reg = <0x9b20000 0x1000>;
diff --git a/arch/arm/boot/dts/stih410-b2120.dts b/arch/arm/boot/dts/stih410-b2120.dts
index 158b2268748e..9d3b118f5f0f 100644
--- a/arch/arm/boot/dts/stih410-b2120.dts
+++ b/arch/arm/boot/dts/stih410-b2120.dts
@@ -11,7 +11,6 @@
compatible = "st,stih410-b2120", "st,stih410";
chosen {
- bootargs = "clk_ignore_unused";
stdout-path = &sbc_serial0;
};
diff --git a/arch/arm/boot/dts/stih410-b2260.dts b/arch/arm/boot/dts/stih410-b2260.dts
index e2bb59783146..9d579c16c295 100644
--- a/arch/arm/boot/dts/stih410-b2260.dts
+++ b/arch/arm/boot/dts/stih410-b2260.dts
@@ -12,7 +12,6 @@
compatible = "st,stih410-b2260", "st,stih410";
chosen {
- bootargs = "clk_ignore_unused";
stdout-path = &uart1;
};
diff --git a/arch/arm/boot/dts/stih410-clock.dtsi b/arch/arm/boot/dts/stih410-clock.dtsi
index 81a8c25d7ba5..6b0e6d4477a3 100644
--- a/arch/arm/boot/dts/stih410-clock.dtsi
+++ b/arch/arm/boot/dts/stih410-clock.dtsi
@@ -39,8 +39,6 @@
compatible = "st,stih407-clkgen-plla9";
clocks = <&clk_sysin>;
-
- clock-output-names = "clockgen-a9-pll-odf";
};
};
@@ -74,25 +72,18 @@
clk_s_a0_pll: clk-s-a0-pll {
#clock-cells = <1>;
- compatible = "st,clkgen-pll0";
+ compatible = "st,clkgen-pll0-a0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-a0-pll-ofd-0";
- clock-critical = <0>; /* clk-s-a0-pll-ofd-0 */
};
clk_s_a0_flexgen: clk-s-a0-flexgen {
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih410-a0";
#clock-cells = <1>;
clocks = <&clk_s_a0_pll 0>,
<&clk_sysin>;
-
- clock-output-names = "clk-ic-lmi0",
- "clk-ic-lmi1";
- clock-critical = <CLK_IC_LMI0>;
};
};
@@ -102,12 +93,6 @@
reg = <0x9103000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-fs0-ch0",
- "clk-s-c0-fs0-ch1",
- "clk-s-c0-fs0-ch2",
- "clk-s-c0-fs0-ch3";
- clock-critical = <0>; /* clk-s-c0-fs0-ch0 */
};
clk_s_c0: clockgen-c@9103000 {
@@ -116,26 +101,21 @@
clk_s_c0_pll0: clk-s-c0-pll0 {
#clock-cells = <1>;
- compatible = "st,clkgen-pll0";
+ compatible = "st,clkgen-pll0-c0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-pll0-odf-0";
- clock-critical = <0>; /* clk-s-c0-pll0-odf-0 */
};
clk_s_c0_pll1: clk-s-c0-pll1 {
#clock-cells = <1>;
- compatible = "st,clkgen-pll1";
+ compatible = "st,clkgen-pll1-c0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-pll1-odf-0";
};
clk_s_c0_flexgen: clk-s-c0-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih410-c0";
clocks = <&clk_s_c0_pll0 0>,
<&clk_s_c0_pll1 0>,
@@ -145,52 +125,6 @@
<&clk_s_c0_quadfs 3>,
<&clk_sysin>;
- clock-output-names = "clk-icn-gpu",
- "clk-fdma",
- "clk-nand",
- "clk-hva",
- "clk-proc-stfe",
- "clk-proc-tp",
- "clk-rx-icn-dmu",
- "clk-rx-icn-hva",
- "clk-icn-cpu",
- "clk-tx-icn-dmu",
- "clk-mmc-0",
- "clk-mmc-1",
- "clk-jpegdec",
- "clk-ext2fa9",
- "clk-ic-bdisp-0",
- "clk-ic-bdisp-1",
- "clk-pp-dmu",
- "clk-vid-dmu",
- "clk-dss-lpc",
- "clk-st231-aud-0",
- "clk-st231-gp-1",
- "clk-st231-dmu",
- "clk-icn-lmi",
- "clk-tx-icn-disp-1",
- "clk-icn-sbc",
- "clk-stfe-frc2",
- "clk-eth-phy",
- "clk-eth-ref-phyclk",
- "clk-flash-promip",
- "clk-main-disp",
- "clk-aux-disp",
- "clk-compo-dvp",
- "clk-tx-icn-hades",
- "clk-rx-icn-hades",
- "clk-icn-reg-16",
- "clk-pp-hades",
- "clk-clust-hades",
- "clk-hwpe-hades",
- "clk-fc-hades";
- clock-critical = <CLK_PROC_STFE>,
- <CLK_ICN_CPU>,
- <CLK_TX_ICN_DMU>,
- <CLK_EXT2F_A9>,
- <CLK_ICN_LMI>,
- <CLK_ICN_SBC>;
-
/*
* ARM Peripheral clock for timers
*/
@@ -210,15 +144,10 @@
clk_s_d0_quadfs: clk-s-d0-quadfs@9104000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d0";
reg = <0x9104000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d0-fs0-ch0",
- "clk-s-d0-fs0-ch1",
- "clk-s-d0-fs0-ch2",
- "clk-s-d0-fs0-ch3";
};
clockgen-d0@9104000 {
@@ -227,34 +156,22 @@
clk_s_d0_flexgen: clk-s-d0-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen-audio", "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih410-d0";
clocks = <&clk_s_d0_quadfs 0>,
<&clk_s_d0_quadfs 1>,
<&clk_s_d0_quadfs 2>,
<&clk_s_d0_quadfs 3>,
<&clk_sysin>;
-
- clock-output-names = "clk-pcm-0",
- "clk-pcm-1",
- "clk-pcm-2",
- "clk-spdiff",
- "clk-pcmr10-master",
- "clk-usb2-phy";
};
};
clk_s_d2_quadfs: clk-s-d2-quadfs@9106000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d2";
reg = <0x9106000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d2-fs0-ch0",
- "clk-s-d2-fs0-ch1",
- "clk-s-d2-fs0-ch2",
- "clk-s-d2-fs0-ch3";
};
clockgen-d2@9106000 {
@@ -263,7 +180,7 @@
clk_s_d2_flexgen: clk-s-d2-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen-video", "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih407-d2";
clocks = <&clk_s_d2_quadfs 0>,
<&clk_s_d2_quadfs 1>,
@@ -272,37 +189,15 @@
<&clk_sysin>,
<&clk_sysin>,
<&clk_tmdsout_hdmi>;
-
- clock-output-names = "clk-pix-main-disp",
- "clk-pix-pip",
- "clk-pix-gdp1",
- "clk-pix-gdp2",
- "clk-pix-gdp3",
- "clk-pix-gdp4",
- "clk-pix-aux-disp",
- "clk-denc",
- "clk-pix-hddac",
- "clk-hddac",
- "clk-sddac",
- "clk-pix-dvo",
- "clk-dvo",
- "clk-pix-hdmi",
- "clk-tmds-hdmi",
- "clk-ref-hdmiphy";
- };
+ };
};
clk_s_d3_quadfs: clk-s-d3-quadfs@9107000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d3";
reg = <0x9107000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d3-fs0-ch0",
- "clk-s-d3-fs0-ch1",
- "clk-s-d3-fs0-ch2",
- "clk-s-d3-fs0-ch3";
};
clockgen-d3@9107000 {
@@ -311,22 +206,13 @@
clk_s_d3_flexgen: clk-s-d3-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih407-d3";
clocks = <&clk_s_d3_quadfs 0>,
<&clk_s_d3_quadfs 1>,
<&clk_s_d3_quadfs 2>,
<&clk_s_d3_quadfs 3>,
<&clk_sysin>;
-
- clock-output-names = "clk-stfe-frc1",
- "clk-tsout-0",
- "clk-tsout-1",
- "clk-mchi",
- "clk-vsens-compo",
- "clk-frc1-remote",
- "clk-lpc-0",
- "clk-lpc-1";
};
};
};
diff --git a/arch/arm/boot/dts/stih418-b2199.dts b/arch/arm/boot/dts/stih418-b2199.dts
index 48c3c64e4c48..b66e2b29edea 100644
--- a/arch/arm/boot/dts/stih418-b2199.dts
+++ b/arch/arm/boot/dts/stih418-b2199.dts
@@ -11,7 +11,6 @@
compatible = "st,stih418-b2199", "st,stih418";
chosen {
- bootargs = "clk_ignore_unused";
stdout-path = &sbc_serial0;
};
diff --git a/arch/arm/boot/dts/stih418-b2264.dts b/arch/arm/boot/dts/stih418-b2264.dts
new file mode 100644
index 000000000000..a99604bebf8c
--- /dev/null
+++ b/arch/arm/boot/dts/stih418-b2264.dts
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 STMicroelectronics
+ * Author: Alain Volmat <avolmat@me.com>
+ */
+/dts-v1/;
+#include "stih418.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+/ {
+ model = "STiH418 B2264";
+ compatible = "st,stih418-b2264", "st,stih418";
+
+ chosen {
+ stdout-path = &sbc_serial0;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x40000000 0xc0000000>;
+ };
+
+ cpus {
+ cpu@0 {
+ operating-points-v2 = <&cpu_opp_table>;
+ /* u-boot puts hpen in SBC dmem at 0xb8 offset */
+ cpu-release-addr = <0x94100b8>;
+ };
+ cpu@1 {
+ operating-points-v2 = <&cpu_opp_table>;
+ /* u-boot puts hpen in SBC dmem at 0xb8 offset */
+ cpu-release-addr = <0x94100b8>;
+ };
+ cpu@2 {
+ operating-points-v2 = <&cpu_opp_table>;
+ /* u-boot puts hpen in SBC dmem at 0xb8 offset */
+ cpu-release-addr = <0x94100b8>;
+ };
+ cpu@3 {
+ operating-points-v2 = <&cpu_opp_table>;
+ /* u-boot puts hpen in SBC dmem at 0xb8 offset */
+ cpu-release-addr = <0x94100b8>;
+ };
+ };
+
+ cpu_opp_table: opp_table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <784000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <784000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <784000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <784000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <784000>;
+ };
+ };
+
+ aliases {
+ ttyAS0 = &sbc_serial0;
+ ethernet0 = &ethernet0;
+ };
+
+ soc {
+ leds {
+ compatible = "gpio-leds";
+ green {
+ gpios = <&pio1 3 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ pin-controller-sbc@961f080 {
+ gmac1 {
+ rgmii1-0 {
+ st,pins {
+ rxd0 = <&pio1 4 ALT1 IN DE_IO 300 CLK_A>;
+ rxd1 = <&pio1 5 ALT1 IN DE_IO 300 CLK_A>;
+ rxd2 = <&pio1 6 ALT1 IN DE_IO 300 CLK_A>;
+ rxd3 = <&pio1 7 ALT1 IN DE_IO 300 CLK_A>;
+ rxdv = <&pio2 0 ALT1 IN DE_IO 300 CLK_A>;
+ };
+ };
+ };
+ };
+
+ };
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ethernet0 {
+ phy-mode = "rgmii";
+ pinctrl-0 = <&pinctrl_rgmii1 &pinctrl_rgmii1_mdio_1>;
+ st,tx-retime-src = "clkgen";
+
+ snps,reset-gpio = <&pio0 7 0>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 1000000>;
+
+ status = "okay";
+};
+
+&miphy28lp_phy {
+ phy_port0: port@9b22000 {
+ st,sata-gen = <2>; /* SATA GEN3 */
+ st,osc-rdy;
+ };
+};
+
+&mmc0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&sata0 {
+ status = "okay";
+};
+
+&sbc_serial0 {
+ status = "okay";
+};
+
+&spifsm {
+ status = "okay";
+};
+
+&st_dwc3 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/stih418-clock.dtsi b/arch/arm/boot/dts/stih418-clock.dtsi
index 8fa092462102..e84c476b83ed 100644
--- a/arch/arm/boot/dts/stih418-clock.dtsi
+++ b/arch/arm/boot/dts/stih418-clock.dtsi
@@ -39,8 +39,6 @@
compatible = "st,stih418-clkgen-plla9";
clocks = <&clk_sysin>;
-
- clock-output-names = "clockgen-a9-pll-odf";
};
};
@@ -75,23 +73,18 @@
clk_s_a0_pll: clk-s-a0-pll {
#clock-cells = <1>;
- compatible = "st,clkgen-pll0";
+ compatible = "st,clkgen-pll0-a0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-a0-pll-ofd-0";
};
clk_s_a0_flexgen: clk-s-a0-flexgen {
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih410-a0";
#clock-cells = <1>;
clocks = <&clk_s_a0_pll 0>,
<&clk_sysin>;
-
- clock-output-names = "clk-ic-lmi0",
- "clk-ic-lmi1";
};
};
@@ -101,11 +94,6 @@
reg = <0x9103000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-fs0-ch0",
- "clk-s-c0-fs0-ch1",
- "clk-s-c0-fs0-ch2",
- "clk-s-c0-fs0-ch3";
};
clk_s_c0: clockgen-c@9103000 {
@@ -114,25 +102,21 @@
clk_s_c0_pll0: clk-s-c0-pll0 {
#clock-cells = <1>;
- compatible = "st,clkgen-pll0";
+ compatible = "st,clkgen-pll0-c0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-pll0-odf-0";
};
clk_s_c0_pll1: clk-s-c0-pll1 {
#clock-cells = <1>;
- compatible = "st,clkgen-pll1";
+ compatible = "st,clkgen-pll1-c0";
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-c0-pll1-odf-0";
};
clk_s_c0_flexgen: clk-s-c0-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih418-c0";
clocks = <&clk_s_c0_pll0 0>,
<&clk_s_c0_pll1 0>,
@@ -142,49 +126,6 @@
<&clk_s_c0_quadfs 3>,
<&clk_sysin>;
- clock-output-names = "clk-icn-gpu",
- "clk-fdma",
- "clk-nand",
- "clk-hva",
- "clk-proc-stfe",
- "clk-tp",
- "clk-rx-icn-dmu",
- "clk-rx-icn-hva",
- "clk-icn-cpu",
- "clk-tx-icn-dmu",
- "clk-mmc-0",
- "clk-mmc-1",
- "clk-jpegdec",
- "clk-icn-reg",
- "clk-proc-bdisp-0",
- "clk-proc-bdisp-1",
- "clk-pp-dmu",
- "clk-vid-dmu",
- "clk-dss-lpc",
- "clk-st231-aud-0",
- "clk-st231-gp-1",
- "clk-st231-dmu",
- "clk-icn-lmi",
- "clk-tx-icn-1",
- "clk-icn-sbc",
- "clk-stfe-frc2",
- "clk-eth-phyref",
- "clk-eth-ref-phyclk",
- "clk-flash-promip",
- "clk-main-disp",
- "clk-aux-disp",
- "clk-compo-dvp",
- "clk-tx-icn-hades",
- "clk-rx-icn-hades",
- "clk-icn-reg-16",
- "clk-pp-hevc",
- "clk-clust-hevc",
- "clk-hwpe-hevc",
- "clk-fc-hevc",
- "clk-proc-mixer",
- "clk-proc-sc",
- "clk-avsp-hevc";
-
/*
* ARM Peripheral clock for timers
*/
@@ -204,15 +145,10 @@
clk_s_d0_quadfs: clk-s-d0-quadfs@9104000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d0";
reg = <0x9104000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d0-fs0-ch0",
- "clk-s-d0-fs0-ch1",
- "clk-s-d0-fs0-ch2",
- "clk-s-d0-fs0-ch3";
};
clockgen-d0@9104000 {
@@ -221,34 +157,22 @@
clk_s_d0_flexgen: clk-s-d0-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen-audio", "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih410-d0";
clocks = <&clk_s_d0_quadfs 0>,
<&clk_s_d0_quadfs 1>,
<&clk_s_d0_quadfs 2>,
<&clk_s_d0_quadfs 3>,
<&clk_sysin>;
-
- clock-output-names = "clk-pcm-0",
- "clk-pcm-1",
- "clk-pcm-2",
- "clk-spdiff",
- "clk-pcmr10-master",
- "clk-usb2-phy";
};
};
clk_s_d2_quadfs: clk-s-d2-quadfs@9106000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d2";
reg = <0x9106000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d2-fs0-ch0",
- "clk-s-d2-fs0-ch1",
- "clk-s-d2-fs0-ch2",
- "clk-s-d2-fs0-ch3";
};
clockgen-d2@9106000 {
@@ -257,7 +181,7 @@
clk_s_d2_flexgen: clk-s-d2-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen-video", "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih418-d2";
clocks = <&clk_s_d2_quadfs 0>,
<&clk_s_d2_quadfs 1>,
@@ -266,44 +190,15 @@
<&clk_sysin>,
<&clk_sysin>,
<&clk_tmdsout_hdmi>;
-
- clock-output-names = "clk-pix-main-disp",
- "",
- "",
- "",
- "",
- "clk-tmds-hdmi-div2",
- "clk-pix-aux-disp",
- "clk-denc",
- "clk-pix-hddac",
- "clk-hddac",
- "clk-sddac",
- "clk-pix-dvo",
- "clk-dvo",
- "clk-pix-hdmi",
- "clk-tmds-hdmi",
- "clk-ref-hdmiphy",
- "", "", "", "", "",
- "", "", "", "", "",
- "", "", "", "", "",
- "", "", "", "", "",
- "", "", "", "", "",
- "", "", "", "", "",
- "", "clk-vp9";
};
};
clk_s_d3_quadfs: clk-s-d3-quadfs@9107000 {
#clock-cells = <1>;
- compatible = "st,quadfs";
+ compatible = "st,quadfs-d3";
reg = <0x9107000 0x1000>;
clocks = <&clk_sysin>;
-
- clock-output-names = "clk-s-d3-fs0-ch0",
- "clk-s-d3-fs0-ch1",
- "clk-s-d3-fs0-ch2",
- "clk-s-d3-fs0-ch3";
};
clockgen-d3@9107000 {
@@ -312,22 +207,13 @@
clk_s_d3_flexgen: clk-s-d3-flexgen {
#clock-cells = <1>;
- compatible = "st,flexgen";
+ compatible = "st,flexgen", "st,flexgen-stih407-d3";
clocks = <&clk_s_d3_quadfs 0>,
<&clk_s_d3_quadfs 1>,
<&clk_s_d3_quadfs 2>,
<&clk_s_d3_quadfs 3>,
<&clk_sysin>;
-
- clock-output-names = "clk-stfe-frc1",
- "clk-tsout-0",
- "clk-tsout-1",
- "clk-mchi",
- "clk-vsens-compo",
- "clk-frc1-remote",
- "clk-lpc-0",
- "clk-lpc-1";
};
};
};
diff --git a/arch/arm/boot/dts/stih418.dtsi b/arch/arm/boot/dts/stih418.dtsi
index a05e2278b448..97eda4392fbe 100644
--- a/arch/arm/boot/dts/stih418.dtsi
+++ b/arch/arm/boot/dts/stih418.dtsi
@@ -27,6 +27,10 @@
};
soc {
+ rng11: rng@8a8a000 {
+ status = "disabled";
+ };
+
usb2_picophy1: phy2@0 {
compatible = "st,stih407-usb2-phy";
reg = <0 0>;
@@ -104,5 +108,13 @@
assigned-clock-parents = <&clk_s_c0_pll1 0>;
assigned-clock-rates = <200000000>;
};
+
+ thermal@91a0000 {
+ compatible = "st,stih407-thermal";
+ reg = <0x91a0000 0x28>;
+ clock-names = "thermal";
+ clocks = <&clk_sysin>;
+ interrupts = <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>;
+ };
};
};
diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index 9ac1ffe53413..cb46326a8c75 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -60,7 +60,7 @@
stdout-path = "serial0:115200n8";
};
- memory@00000000 {
+ memory@0 {
device_type = "memory";
reg = <0x00000000 0x2000000>;
};
diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
index 8c982ae79f43..30905ce672a0 100644
--- a/arch/arm/boot/dts/stm32f469-disco.dts
+++ b/arch/arm/boot/dts/stm32f469-disco.dts
@@ -60,7 +60,7 @@
stdout-path = "serial0:115200n8";
};
- memory@00000000 {
+ memory@0 {
device_type = "memory";
reg = <0x00000000 0x1000000>;
};
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
index 95b08876b2b3..46b471d09c50 100644
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -313,8 +313,8 @@
&m4_rproc {
memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>,
<&vdev0vring1>, <&vdev0buffer>;
- mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>;
- mbox-names = "vq0", "vq1", "shutdown";
+ mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>;
+ mbox-names = "vq0", "vq1", "shutdown", "detach";
interrupt-parent = <&exti>;
interrupts = <68 1>;
status = "okay";
diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-drc02.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcom-drc02.dtsi
index fb45c5aa878d..4b10b013ffd5 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dhcom-drc02.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dhcom-drc02.dtsi
@@ -159,3 +159,7 @@
&usbphyc_port0 {
phy-supply = <&vdd_usb>;
};
+
+&usbphyc_port1 {
+ phy-supply = <&vdd_usb>;
+};
diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi
index 6cf1c8b4c6e2..fbf3826933e4 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi
@@ -29,6 +29,7 @@
brightness-levels = <0 16 22 30 40 55 75 102 138 188 255>;
default-brightness-level = <8>;
enable-gpios = <&gpioi 0 GPIO_ACTIVE_HIGH>;
+ power-supply = <&reg_panel_bl>;
status = "okay";
};
@@ -110,6 +111,7 @@
panel {
compatible = "edt,etm0700g0edh6";
backlight = <&display_bl>;
+ power-supply = <&reg_panel_bl>;
port {
lcd_panel_in: endpoint {
@@ -118,6 +120,21 @@
};
};
+ reg_panel_bl: regulator-panel-bl {
+ compatible = "regulator-fixed";
+ regulator-name = "panel_backlight";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&reg_panel_supply>;
+ };
+
+ reg_panel_supply: regulator-panel-supply {
+ compatible = "regulator-fixed";
+ regulator-name = "panel_supply";
+ regulator-min-microvolt = <24000000>;
+ regulator-max-microvolt = <24000000>;
+ };
+
sound {
compatible = "audio-graph-card";
routing =
@@ -172,15 +189,15 @@
sgtl5000_tx_endpoint: endpoint@0 {
reg = <0>;
remote-endpoint = <&sai2a_endpoint>;
- frame-master;
- bitclock-master;
+ frame-master = <&sgtl5000_tx_endpoint>;
+ bitclock-master = <&sgtl5000_tx_endpoint>;
};
sgtl5000_rx_endpoint: endpoint@1 {
reg = <1>;
remote-endpoint = <&sai2b_endpoint>;
- frame-master;
- bitclock-master;
+ frame-master = <&sgtl5000_rx_endpoint>;
+ bitclock-master = <&sgtl5000_rx_endpoint>;
};
};
diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi
index 64dca5b7f748..6885948f3024 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi
@@ -220,8 +220,8 @@
&i2c4 {
hdmi-transmitter@3d {
compatible = "adi,adv7513";
- reg = <0x3d>, <0x2d>, <0x4d>, <0x5d>;
- reg-names = "main", "cec", "edid", "packet";
+ reg = <0x3d>, <0x4d>, <0x2d>, <0x5d>;
+ reg-names = "main", "edid", "cec", "packet";
clocks = <&cec_clock>;
clock-names = "cec";
@@ -239,8 +239,6 @@
adi,input-depth = <8>;
adi,input-colorspace = "rgb";
adi,input-clock = "1x";
- adi,input-style = <1>;
- adi,input-justification = "evenly";
ports {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi
index 59f18846cf5d..899bfe04aeb9 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi
@@ -220,15 +220,15 @@
cs42l51_tx_endpoint: endpoint@0 {
reg = <0>;
remote-endpoint = <&sai2a_endpoint>;
- frame-master;
- bitclock-master;
+ frame-master = <&cs42l51_tx_endpoint>;
+ bitclock-master = <&cs42l51_tx_endpoint>;
};
cs42l51_rx_endpoint: endpoint@1 {
reg = <1>;
remote-endpoint = <&sai2b_endpoint>;
- frame-master;
- bitclock-master;
+ frame-master = <&cs42l51_rx_endpoint>;
+ bitclock-master = <&cs42l51_rx_endpoint>;
};
};
};
@@ -470,8 +470,8 @@
&m4_rproc {
memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>,
<&vdev0vring1>, <&vdev0buffer>;
- mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>;
- mbox-names = "vq0", "vq1", "shutdown";
+ mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>;
+ mbox-names = "vq0", "vq1", "shutdown", "detach";
interrupt-parent = <&exti>;
interrupts = <68 1>;
status = "okay";
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
index c04162ddec3c..7fd901f8d39a 100644
--- a/arch/arm/boot/dts/tegra114-dalmore.dts
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -788,7 +788,7 @@
reg = <0x4c>;
vcc-supply = <&palmas_ldo6_reg>;
interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(O, 4) IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <TEGRA_GPIO(O, 4) IRQ_TYPE_EDGE_FALLING>;
};
};
diff --git a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi b/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi
index 1e30fa405fa0..cde9ae8fa04b 100644
--- a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi
+++ b/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi
@@ -1751,7 +1751,7 @@
compatible = "ti,tmp451";
reg = <0x4c>;
interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_EDGE_FALLING>;
#thermal-sensor-cells = <1>;
vcc-supply = <&reg_module_3v3>;
};
diff --git a/arch/arm/boot/dts/tegra124-apalis.dtsi b/arch/arm/boot/dts/tegra124-apalis.dtsi
index 608896f8dd52..a46d9ba9bb7a 100644
--- a/arch/arm/boot/dts/tegra124-apalis.dtsi
+++ b/arch/arm/boot/dts/tegra124-apalis.dtsi
@@ -1744,7 +1744,7 @@
compatible = "ti,tmp451";
reg = <0x4c>;
interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_EDGE_FALLING>;
#thermal-sensor-cells = <1>;
vcc-supply = <&reg_module_3v3>;
};
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index 414cd1cafa7f..35ab296408e1 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1427,7 +1427,7 @@
compatible = "ti,tmp451";
reg = <0x4c>;
interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_EDGE_FALLING>;
};
eeprom@56 {
diff --git a/arch/arm/boot/dts/tegra124-nyan.dtsi b/arch/arm/boot/dts/tegra124-nyan.dtsi
index 5f71add38dfe..63a81270300a 100644
--- a/arch/arm/boot/dts/tegra124-nyan.dtsi
+++ b/arch/arm/boot/dts/tegra124-nyan.dtsi
@@ -91,7 +91,7 @@
compatible = "ti,tmp451";
reg = <0x4c>;
interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_EDGE_FALLING>;
#thermal-sensor-cells = <1>;
};
diff --git a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
index 1976c383912a..2280d75b66ab 100644
--- a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
+++ b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
+#include <dt-bindings/input/atmel-maxtouch.h>
#include <dt-bindings/input/gpio-keys.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/thermal/thermal.h>
@@ -454,7 +455,7 @@
vdda-supply = <&vdd_3v3_sys>;
vdd-supply = <&vdd_3v3_sys>;
- atmel,wakeup-method = <1>;
+ atmel,wakeup-method = <ATMEL_MXT_WAKEUP_I2C_SCL>;
};
gyroscope@68 {
@@ -482,6 +483,9 @@
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(S, 7) IRQ_TYPE_EDGE_RISING>;
+ vdd-supply = <&vdd_1v8_sys>;
+ vddio-supply = <&vdd_1v8_sys>;
+
mount-matrix = "0", "1", "0",
"1", "0", "0",
"0", "0", "-1";
@@ -693,6 +697,10 @@
compatible = "onnn,nct1008";
reg = <0x4c>;
vcc-supply = <&vdd_3v3_sys>;
+
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(N, 6) IRQ_TYPE_EDGE_FALLING>;
+
#thermal-sensor-cells = <1>;
};
};
@@ -719,7 +727,6 @@
nvidia,xcvr-setup-use-fuses;
nvidia,xcvr-lsfslew = <2>;
nvidia,xcvr-lsrslew = <2>;
- vbus-supply = <&vdd_vbus1>;
};
usb@c5008000 {
@@ -731,7 +738,7 @@
nvidia,xcvr-setup-use-fuses;
nvidia,xcvr-lsfslew = <2>;
nvidia,xcvr-lsrslew = <2>;
- vbus-supply = <&vdd_vbus3>;
+ vbus-supply = <&vdd_5v0_sys>;
};
brcm_wifi_pwrseq: wifi-pwrseq {
@@ -991,28 +998,6 @@
vin-supply = <&vdd_5v0_sys>;
};
- vdd_vbus1: regulator@4 {
- compatible = "regulator-fixed";
- regulator-name = "vdd_usb1_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- regulator-always-on;
- gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
- enable-active-high;
- vin-supply = <&vdd_5v0_sys>;
- };
-
- vdd_vbus3: regulator@5 {
- compatible = "regulator-fixed";
- regulator-name = "vdd_usb3_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- regulator-always-on;
- gpio = <&gpio TEGRA_GPIO(D, 3) GPIO_ACTIVE_HIGH>;
- enable-active-high;
- vin-supply = <&vdd_5v0_sys>;
- };
-
sound {
compatible = "nvidia,tegra-audio-wm8903-picasso",
"nvidia,tegra-audio-wm8903";
@@ -1044,11 +1029,48 @@
};
thermal-zones {
+ /*
+ * NCT1008 has two sensors:
+ *
+ * 0: internal that monitors ambient/skin temperature
+ * 1: external that is connected to the CPU's diode
+ *
+ * Ideally we should use userspace thermal governor,
+ * but it's a much more complex solution. The "skin"
+ * zone is a simpler solution which prevents A500 from
+ * getting too hot from a user's tactile perspective.
+ * The CPU zone is intended to protect silicon from damage.
+ */
+
skin-thermal {
polling-delay-passive = <1000>; /* milliseconds */
- polling-delay = <0>; /* milliseconds */
+ polling-delay = <5000>; /* milliseconds */
thermal-sensors = <&nct1008 0>;
+
+ trips {
+ trip0: skin-alert {
+ /* start throttling at 60C */
+ temperature = <60000>;
+ hysteresis = <200>;
+ type = "passive";
+ };
+
+ trip1: skin-crit {
+ /* shut down at 70C */
+ temperature = <70000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&trip0>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
cpu-thermal {
@@ -1058,24 +1080,24 @@
thermal-sensors = <&nct1008 1>;
trips {
- trip0: cpu-alert0 {
- /* start throttling at 60C */
- temperature = <60000>;
+ trip2: cpu-alert {
+ /* throttle at 85C until temperature drops to 84.8C */
+ temperature = <85000>;
hysteresis = <200>;
type = "passive";
};
- trip1: cpu-crit {
- /* shut down at 70C */
- temperature = <70000>;
+ trip3: cpu-crit {
+ /* shut down at 90C */
+ temperature = <90000>;
hysteresis = <2000>;
type = "critical";
};
};
cooling-maps {
- map0 {
- trip = <&trip0>;
+ map1 {
+ trip = <&trip2>;
cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
<&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index 3180bff90756..acc816bfd233 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -503,6 +503,10 @@
adt7461: temperature-sensor@4c {
compatible = "adi,adt7461";
reg = <0x4c>;
+
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(N, 6) IRQ_TYPE_EDGE_FALLING>;
+
#thermal-sensor-cells = <1>;
};
};
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
index 95e6bccdb4f6..dd4d506683de 100644
--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -185,8 +185,9 @@
nvidia,pins = "ata", "atb", "atc", "atd", "ate",
"cdev1", "cdev2", "dap1", "dtb", "gma",
"gmb", "gmc", "gmd", "gme", "gpu7",
- "gpv", "i2cp", "pta", "rm", "slxa",
- "slxk", "spia", "spib", "uac";
+ "gpv", "i2cp", "irrx", "irtx", "pta",
+ "rm", "slxa", "slxk", "spia", "spib",
+ "uac";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
};
@@ -211,7 +212,7 @@
conf_ddc {
nvidia,pins = "ddc", "dta", "dtd", "kbca",
"kbcb", "kbcc", "kbcd", "kbce", "kbcf",
- "sdc";
+ "sdc", "uad", "uca";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
};
@@ -221,10 +222,9 @@
"lvp0", "owc", "sdb";
nvidia,tristate = <TEGRA_PIN_ENABLE>;
};
- conf_irrx {
- nvidia,pins = "irrx", "irtx", "sdd", "spic",
- "spie", "spih", "uaa", "uab", "uad",
- "uca", "ucb";
+ conf_sdd {
+ nvidia,pins = "sdd", "spic", "spie", "spih",
+ "uaa", "uab", "ucb";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
};
diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
index ae8300baa2d4..9732cd6f20b7 100644
--- a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
+++ b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
@@ -920,6 +920,10 @@
compatible = "onnn,nct1008";
reg = <0x4c>;
vcc-supply = <&vdd_3v3_sys>;
+
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(S, 3) IRQ_TYPE_EDGE_FALLING>;
+
#thermal-sensor-cells = <1>;
};
@@ -1251,21 +1255,34 @@
};
thermal-zones {
- cpu-thermal {
+ /*
+ * NCT72 has two sensors:
+ *
+ * 0: internal that monitors ambient/skin temperature
+ * 1: external that is connected to the CPU's diode
+ *
+ * Ideally we should use userspace thermal governor,
+ * but it's a much more complex solution. The "skin"
+ * zone is a simpler solution which prevents Nexus 7
+ * from getting too hot from a user's tactile perspective.
+ * The CPU zone is intended to protect silicon from damage.
+ */
+
+ skin-thermal {
polling-delay-passive = <1000>; /* milliseconds */
polling-delay = <5000>; /* milliseconds */
- thermal-sensors = <&nct72 1>;
+ thermal-sensors = <&nct72 0>;
trips {
- trip0: cpu-alert0 {
+ trip0: skin-alert {
/* throttle at 57C until temperature drops to 56.8C */
temperature = <57000>;
hysteresis = <200>;
type = "passive";
};
- trip1: cpu-crit {
+ trip1: skin-crit {
/* shut down at 65C */
temperature = <65000>;
hysteresis = <2000>;
@@ -1285,5 +1302,40 @@
};
};
};
+
+ cpu-thermal {
+ polling-delay-passive = <1000>; /* milliseconds */
+ polling-delay = <5000>; /* milliseconds */
+
+ thermal-sensors = <&nct72 1>;
+
+ trips {
+ trip2: cpu-alert {
+ /* throttle at 85C until temperature drops to 84.8C */
+ temperature = <85000>;
+ hysteresis = <200>;
+ type = "passive";
+ };
+
+ trip3: cpu-crit {
+ /* shut down at 90C */
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map1 {
+ trip = <&trip2>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&actmon THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>;
+ };
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index d9dd11569d4b..448f1397e64a 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -348,7 +348,7 @@
reg = <0x4c>;
vcc-supply = <&sys_3v3_reg>;
interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(CC, 2) IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <TEGRA_GPIO(CC, 2) IRQ_TYPE_EDGE_FALLING>;
#thermal-sensor-cells = <1>;
};
diff --git a/arch/arm/boot/dts/tegra30-ouya.dts b/arch/arm/boot/dts/tegra30-ouya.dts
index ab8744f3d72d..90db5ff72537 100644
--- a/arch/arm/boot/dts/tegra30-ouya.dts
+++ b/arch/arm/boot/dts/tegra30-ouya.dts
@@ -124,12 +124,11 @@
compatible = "onnn,nct1008";
reg = <0x4c>;
vcc-supply = <&sys_3v3_reg>;
+
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(CC, 2) IRQ_TYPE_EDGE_FALLING>;
+
#thermal-sensor-cells = <1>;
-/*
- * The interrupt is bugged, once triggered it never clears.
- * interrupt-parent = <&gpio>;
- * interrupts = <TEGRA_GPIO(CC, 2) IRQ_TYPE_LEVEL_LOW>;
- */
};
pmic: pmic@2d {
@@ -4376,8 +4375,8 @@
nvidia,pins = "pcc2";
nvidia,function = "i2s4";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- nvidia,tristate = <TEGRA_PIN_ENABLE>;
- nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
sdmmc4_rst_n_pcc3 {
nvidia,pins = "sdmmc4_rst_n_pcc3";
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index c577c191be4b..eaf4951d9ff8 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -5,6 +5,7 @@
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/soc/tegra-pmc.h>
+#include <dt-bindings/thermal/thermal.h>
#include "tegra30-peripherals-opp.dtsi"
@@ -800,6 +801,20 @@
reset-names = "fuse";
};
+ tsensor: tsensor@70014000 {
+ compatible = "nvidia,tegra30-tsensor";
+ reg = <0x70014000 0x500>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA30_CLK_TSENSOR>;
+ resets = <&tegra_car TEGRA30_CLK_TSENSOR>;
+
+ assigned-clocks = <&tegra_car TEGRA30_CLK_TSENSOR>;
+ assigned-clock-parents = <&tegra_car TEGRA30_CLK_CLK_M>;
+ assigned-clock-rates = <500000>;
+
+ #thermal-sensor-cells = <1>;
+ };
+
hda@70030000 {
compatible = "nvidia,tegra30-hda";
reg = <0x70030000 0x10000>;
@@ -1062,32 +1077,36 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
clocks = <&tegra_car TEGRA30_CLK_CCLK_G>;
+ #cooling-cells = <2>;
};
- cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
clocks = <&tegra_car TEGRA30_CLK_CCLK_G>;
+ #cooling-cells = <2>;
};
- cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <2>;
clocks = <&tegra_car TEGRA30_CLK_CCLK_G>;
+ #cooling-cells = <2>;
};
- cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <3>;
clocks = <&tegra_car TEGRA30_CLK_CCLK_G>;
+ #cooling-cells = <2>;
};
};
@@ -1102,4 +1121,64 @@
<&{/cpus/cpu@2}>,
<&{/cpus/cpu@3}>;
};
+
+ thermal-zones {
+ tsensor0-thermal {
+ polling-delay-passive = <1000>; /* milliseconds */
+ polling-delay = <5000>; /* milliseconds */
+
+ thermal-sensors = <&tsensor 0>;
+
+ trips {
+ level1_trip: dvfs-alert {
+ /* throttle at 80C until temperature drops to 79.8C */
+ temperature = <80000>;
+ hysteresis = <200>;
+ type = "passive";
+ };
+
+ level2_trip: cpu-div2-throttle {
+ /* hardware CPU x2 freq throttle at 85C */
+ temperature = <85000>;
+ hysteresis = <200>;
+ type = "hot";
+ };
+
+ level3_trip: soc-critical {
+ /* hardware shut down at 90C */
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&level1_trip>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&actmon THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ tsensor1-thermal {
+ status = "disabled";
+
+ polling-delay-passive = <1000>; /* milliseconds */
+ polling-delay = <0>; /* milliseconds */
+
+ thermal-sensors = <&tsensor 1>;
+
+ trips {
+ dvfs-alert {
+ temperature = <80000>;
+ hysteresis = <200>;
+ type = "passive";
+ };
+ };
+ };
+ };
};
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 6f1e0f0d4f0a..043ddd70372f 100644
--- a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
+++ b/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
@@ -311,8 +311,6 @@
compatible = "atmel,at93c46d";
pinctrl-0 = <&pinctrl_gpio_e6185_eeprom_sel>;
pinctrl-names = "default";
- #address-cells = <0>;
- #size-cells = <0>;
reg = <1>;
spi-max-frequency = <500000>;
spi-cs-high;
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index df9ad831cf05..47c2a4b14c06 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -252,6 +252,27 @@
#size-cells = <0>;
};
+ smcc: memory-controller@e000e000 {
+ compatible = "arm,pl353-smc-r2p1", "arm,primecell";
+ reg = <0xe000e000 0x0001000>;
+ status = "disabled";
+ clock-names = "memclk", "apb_pclk";
+ clocks = <&clkc 11>, <&clkc 44>;
+ ranges = <0x0 0x0 0xe1000000 0x1000000 /* Nand CS region */
+ 0x1 0x0 0xe2000000 0x2000000 /* SRAM/NOR CS0 region */
+ 0x2 0x0 0xe4000000 0x2000000>; /* SRAM/NOR CS1 region */
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ nfc0: nand-controller@0,0 {
+ compatible = "arm,pl353-nand-r2p1";
+ reg = <0 0 0x1000000>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
sdhci0: mmc@e0100000 {
compatible = "arasan,sdhci-8.9a";
status = "disabled";
diff --git a/arch/arm/boot/dts/zynq-ebaz4205.dts b/arch/arm/boot/dts/zynq-ebaz4205.dts
index b0b836aedd76..53fa6dbfd8fd 100644
--- a/arch/arm/boot/dts/zynq-ebaz4205.dts
+++ b/arch/arm/boot/dts/zynq-ebaz4205.dts
@@ -48,6 +48,14 @@
pinctrl-0 = <&pinctrl_gpio0_default>;
};
+&nfc0 {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ };
+};
+
&pinctrl0 {
pinctrl_gpio0_default: gpio0-default {
mux {
@@ -118,6 +126,10 @@
};
};
+&smcc {
+ status = "okay";
+};
+
&sdhci0 {
status = "okay";
disable-wp;
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index e45f4e4e06b6..24d21ba63030 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -834,14 +834,13 @@ static int locomo_bus_probe(struct device *dev)
return ret;
}
-static int locomo_bus_remove(struct device *dev)
+static void locomo_bus_remove(struct device *dev)
{
struct locomo_dev *ldev = LOCOMO_DEV(dev);
struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
if (drv->remove)
drv->remove(ldev);
- return 0;
}
struct bus_type locomo_bus_type = {
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index d17083c3fe2d..5367f03beb46 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -1356,15 +1356,13 @@ static int sa1111_bus_probe(struct device *dev)
return ret;
}
-static int sa1111_bus_remove(struct device *dev)
+static void sa1111_bus_remove(struct device *dev)
{
struct sa1111_dev *sadev = to_sa1111_device(dev);
struct sa1111_driver *drv = SA1111_DRV(dev->driver);
if (drv->remove)
drv->remove(sadev);
-
- return 0;
}
struct bus_type sa1111_bus_type = {
diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig
index a3ee647b1ebb..acaafa351d08 100644
--- a/arch/arm/configs/aspeed_g4_defconfig
+++ b/arch/arm/configs/aspeed_g4_defconfig
@@ -3,6 +3,7 @@ CONFIG_KERNEL_XZ=y
CONFIG_SYSVIPC=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BPF_SYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
@@ -14,22 +15,18 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_UID16 is not set
# CONFIG_SYSFS_SYSCALL is not set
# CONFIG_AIO is not set
-CONFIG_BPF_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_PERF_EVENTS=y
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_ASPEED=y
CONFIG_MACH_ASPEED_G4=y
CONFIG_VMSPLIT_2G=y
CONFIG_AEABI=y
CONFIG_UACCESS_WITH_MEMCPY=y
-CONFIG_SECCOMP=y
# CONFIG_ATAGS is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
CONFIG_KEXEC=y
@@ -76,7 +73,6 @@ CONFIG_NETCONSOLE=y
# CONFIG_NET_VENDOR_AMAZON is not set
# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_VENDOR_AURORA is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CADENCE is not set
# CONFIG_NET_VENDOR_CAVIUM is not set
@@ -132,7 +128,6 @@ CONFIG_ASPEED_BT_IPMI_BMC=y
CONFIG_HW_RANDOM_TIMERIOMEM=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA9541=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_ASPEED=y
@@ -141,6 +136,7 @@ CONFIG_SPI=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_ASPEED=y
+CONFIG_GPIO_ASPEED_SGPIO=y
CONFIG_W1=y
CONFIG_W1_MASTER_GPIO=y
CONFIG_W1_SLAVE_THERM=y
@@ -205,6 +201,7 @@ CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_EDAC=y
+CONFIG_EDAC_ASPEED=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_PCF8523=y
@@ -212,9 +209,6 @@ CONFIG_RTC_DRV_RV8803=y
CONFIG_RTC_DRV_ASPEED=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
-CONFIG_ASPEED_LPC_CTRL=y
-CONFIG_ASPEED_LPC_SNOOP=y
-CONFIG_ASPEED_P2A_CTRL=y
CONFIG_IIO=y
CONFIG_ASPEED_ADC=y
CONFIG_MAX1363=y
@@ -255,6 +249,7 @@ CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_GDB_SCRIPTS=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_WX=y
CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=-1
@@ -263,6 +258,5 @@ CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_WQ_WATCHDOG=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_FUNCTION_TRACER=y
-CONFIG_DEBUG_WX=y
CONFIG_DEBUG_USER=y
# CONFIG_RUNTIME_TESTING_MENU is not set
diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
index 2db48438c5d2..480dbbb4ff91 100644
--- a/arch/arm/configs/aspeed_g5_defconfig
+++ b/arch/arm/configs/aspeed_g5_defconfig
@@ -3,6 +3,7 @@ CONFIG_KERNEL_XZ=y
CONFIG_SYSVIPC=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BPF_SYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
@@ -14,12 +15,11 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_UID16 is not set
# CONFIG_SYSFS_SYSCALL is not set
# CONFIG_AIO is not set
-CONFIG_BPF_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_PERF_EVENTS=y
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
CONFIG_ARCH_MULTI_V6=y
CONFIG_ARCH_ASPEED=y
CONFIG_MACH_ASPEED_G5=y
@@ -31,10 +31,7 @@ CONFIG_VMSPLIT_2G=y
CONFIG_NR_CPUS=2
CONFIG_HIGHMEM=y
CONFIG_UACCESS_WITH_MEMCPY=y
-CONFIG_SECCOMP=y
# CONFIG_ATAGS is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_KEXEC=y
CONFIG_VFP=y
CONFIG_NEON=y
@@ -89,7 +86,6 @@ CONFIG_NETCONSOLE=y
# CONFIG_NET_VENDOR_AMAZON is not set
# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_VENDOR_AURORA is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CADENCE is not set
# CONFIG_NET_VENDOR_CAVIUM is not set
@@ -130,7 +126,7 @@ CONFIG_KEYBOARD_GPIO_POLLED=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_IBM_PANEL=y
-# CONFIG_SERIO is not set
+CONFIG_SERIO_RAW=y
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=y
@@ -144,11 +140,11 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_ASPEED_KCS_IPMI_BMC=y
+CONFIG_IPMI_KCS_BMC_SERIO=y
CONFIG_ASPEED_BT_IPMI_BMC=y
CONFIG_HW_RANDOM_TIMERIOMEM=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_GPIO=y
CONFIG_I2C_MUX_PCA9541=y
CONFIG_I2C_MUX_PCA954x=y
@@ -231,9 +227,6 @@ CONFIG_RTC_DRV_RV8803=y
CONFIG_RTC_DRV_ASPEED=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
-CONFIG_ASPEED_LPC_CTRL=y
-CONFIG_ASPEED_LPC_SNOOP=y
-CONFIG_ASPEED_P2A_CTRL=y
CONFIG_IIO=y
CONFIG_ASPEED_ADC=y
CONFIG_MAX1363=y
@@ -278,14 +271,14 @@ CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_GDB_SCRIPTS=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_WX=y
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_TIMEOUT=-1
CONFIG_SOFTLOCKUP_DETECTOR=y
# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_WQ_WATCHDOG=y
-CONFIG_PANIC_ON_OOPS=y
-CONFIG_PANIC_TIMEOUT=-1
# CONFIG_SCHED_DEBUG is not set
-CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_FUNCTION_TRACER=y
-# CONFIG_RUNTIME_TESTING_MENU is not set
-CONFIG_DEBUG_WX=y
CONFIG_DEBUG_USER=y
+# CONFIG_RUNTIME_TESTING_MENU is not set
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index cd16fb6eb8e6..88d5ecc2121e 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -12,7 +12,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_EP93XX=y
-CONFIG_CRUNCH=y
CONFIG_MACH_ADSSPHERE=y
CONFIG_MACH_EDB9301=y
CONFIG_MACH_EDB9302=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 079fcd8d1d11..ccee86d0045d 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -53,6 +53,7 @@ CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_PM_DEBUG=y
CONFIG_PM_TEST_SUSPEND=y
+CONFIG_KPROBES=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
@@ -119,7 +120,6 @@ CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
-# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_ATA=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_IMX=y
@@ -252,6 +252,7 @@ CONFIG_REGULATOR_DA9052=y
CONFIG_REGULATOR_DA9062=y
CONFIG_REGULATOR_DA9063=y
CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_LTC3676=y
CONFIG_REGULATOR_MC13783=y
CONFIG_REGULATOR_MC13892=y
CONFIG_REGULATOR_PFUZE100=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index d9abaae118dd..ba67c4717dcc 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -16,6 +16,7 @@ CONFIG_ARCH_AT91=y
CONFIG_SOC_SAMA5D2=y
CONFIG_SOC_SAMA5D3=y
CONFIG_SOC_SAMA5D4=y
+CONFIG_SOC_SAMA7G5=y
CONFIG_ARCH_BCM=y
CONFIG_ARCH_BCM_CYGNUS=y
CONFIG_ARCH_BCM_HR2=y
@@ -215,6 +216,7 @@ CONFIG_MTD_NAND_GPMI_NAND=y
CONFIG_MTD_NAND_VF610_NFC=y
CONFIG_MTD_NAND_DAVINCI=y
CONFIG_MTD_NAND_STM32_FMC2=y
+CONFIG_MTD_NAND_PL35X=y
CONFIG_MTD_SPI_NOR=y
CONFIG_SPI_ASPEED_SMC=m
CONFIG_MTD_UBI=y
@@ -492,6 +494,7 @@ CONFIG_BATTERY_ACT8945A=y
CONFIG_BATTERY_CPCAP=m
CONFIG_BATTERY_SBS=y
CONFIG_BATTERY_BQ27XXX=m
+CONFIG_BATTERY_ACER_A500=m
CONFIG_AXP20X_POWER=m
CONFIG_BATTERY_MAX17040=m
CONFIG_BATTERY_MAX17042=m
@@ -523,6 +526,7 @@ CONFIG_BRCMSTB_THERMAL=m
CONFIG_GENERIC_ADC_THERMAL=m
CONFIG_ST_THERMAL_MEMMAP=y
CONFIG_TEGRA_SOCTHERM=m
+CONFIG_TEGRA30_TSENSOR=m
CONFIG_UNIPHIER_THERMAL=y
CONFIG_DA9063_WATCHDOG=m
CONFIG_XILINX_WATCHDOG=y
@@ -550,6 +554,7 @@ CONFIG_BCM7038_WDT=m
CONFIG_BCMA_HOST_SOC=y
CONFIG_BCMA_DRIVER_GMAC_CMN=y
CONFIG_BCMA_DRIVER_GPIO=y
+CONFIG_MFD_ACER_A500_EC=m
CONFIG_MFD_ACT8945A=y
CONFIG_MFD_AS3711=y
CONFIG_MFD_AS3722=y
@@ -870,6 +875,7 @@ CONFIG_MMC_SDHCI_PXAV2=m
CONFIG_MMC_SDHCI_SPEAR=y
CONFIG_MMC_SDHCI_S3C_DMA=y
CONFIG_MMC_SDHCI_BCM_KONA=y
+CONFIG_MMC_MESON_MX_SDHC=y
CONFIG_MMC_MESON_MX_SDIO=y
CONFIG_MMC_SDHCI_ST=y
CONFIG_MMC_OMAP=y
@@ -895,6 +901,7 @@ CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
CONFIG_LEDS_MAX77693=m
CONFIG_LEDS_MAX8997=m
+CONFIG_LEDS_ACER_A500=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
@@ -996,6 +1003,7 @@ CONFIG_APQ_MMCC_8084=y
CONFIG_MSM_GCC_8660=y
CONFIG_MSM_MMCC_8960=y
CONFIG_MSM_MMCC_8974=y
+CONFIG_MICROCHIP_PIT64B=y
CONFIG_BCM2835_MBOX=y
CONFIG_ROCKCHIP_IOMMU=y
CONFIG_TEGRA_IOMMU_GART=y
diff --git a/arch/arm/configs/sama7_defconfig b/arch/arm/configs/sama7_defconfig
new file mode 100644
index 000000000000..938aae4bd80b
--- /dev/null
+++ b/arch/arm/configs/sama7_defconfig
@@ -0,0 +1,209 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_NAMESPACES=y
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_FHANDLE is not set
+# CONFIG_IO_URING is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+CONFIG_ARCH_AT91=y
+CONFIG_SOC_SAMA7G5=y
+CONFIG_ATMEL_CLOCKSOURCE_TCB=y
+# CONFIG_CACHE_L2X0 is not set
+# CONFIG_ARM_PATCH_IDIV is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_FORCE_MAX_ZONEORDER=15
+CONFIG_UACCESS_WITH_MEMCPY=y
+# CONFIG_ATAGS is not set
+CONFIG_CMDLINE="console=ttyS0,115200 earlyprintk ignore_loglevel"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_COREDUMP is not set
+# CONFIG_COMPACTION is not set
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_NET_DSA=m
+CONFIG_VLAN_8021Q=m
+CONFIG_CAN=y
+CONFIG_CAN_M_CAN=y
+CONFIG_CAN_M_CAN_PLATFORM=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIVHCI=y
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_DEFAULT_PS is not set
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_LEDS=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_PCCARD=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_EEPROM_AT24=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+CONFIG_MACB=y
+CONFIG_MICREL_PHY=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_AT91=y
+CONFIG_SPI=y
+CONFIG_SPI_MEM=y
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_GPIO=y
+CONFIG_PINCTRL_AT91=y
+CONFIG_PINCTRL_AT91PIO4=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_AT91_RESET=y
+CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SAMA5D4_WATCHDOG=y
+CONFIG_MFD_ATMEL_FLEXCOM=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MCP16502=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_SUPPORT_FILTER=y
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_PLATFORM_SUPPORT=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_IMX219=m
+CONFIG_VIDEO_IMX274=m
+CONFIG_VIDEO_OV5647=m
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_ATMEL_SOC=y
+CONFIG_SND_SOC_MIKROE_PROTO=m
+CONFIG_SND_MCHP_SOC_I2S_MCC=y
+CONFIG_SND_MCHP_SOC_SPDIFTX=y
+CONFIG_SND_MCHP_SOC_SPDIFRX=y
+CONFIG_SND_SOC_PCM5102A=y
+CONFIG_SND_SOC_SPDIF=y
+CONFIG_SND_SIMPLE_CARD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_UAS=y
+CONFIG_USB_GADGET=y
+CONFIG_U_SERIAL_CONSOLE=y
+CONFIG_USB_ATMEL_USBA=m
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_UVC=y
+CONFIG_USB_G_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_AT91=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_NVMEM is not set
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_DMADEVICES=y
+CONFIG_AT_XDMAC=y
+CONFIG_DMATEST=y
+CONFIG_STAGING=y
+CONFIG_MICROCHIP_PIT64B=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_ATMEL_EBI is not set
+CONFIG_IIO=y
+CONFIG_IIO_SW_TRIGGER=y
+CONFIG_AT91_SAMA5D2_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_LSM="N"
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_ITU_T=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_CMA_ALIGNMENT=9
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_MISC is not set
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_STACKTRACE=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_RUNTIME_TESTING_MENU is not set
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 3d8d8af9524d..0965ed0501dc 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -20,9 +20,6 @@ CONFIG_SLAB=y
CONFIG_ARCH_TEGRA=y
CONFIG_SMP=y
CONFIG_HIGHMEM=y
-CONFIG_SECCOMP=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_KEXEC=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
@@ -49,8 +46,6 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_INET_ESP=y
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -86,7 +81,6 @@ CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TEGRA_GMI=y
CONFIG_MTD=y
-CONFIG_MTD_M25P80=y
CONFIG_MTD_SPI_NOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_AD525X_DPOT=y
@@ -116,8 +110,8 @@ CONFIG_INPUT_JOYDEV=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_TEGRA=y
-CONFIG_KEYBOARD_CAP11XX=y
CONFIG_KEYBOARD_CROS_EC=y
+CONFIG_KEYBOARD_CAP11XX=y
CONFIG_MOUSE_PS2_ELANTECH=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
@@ -162,6 +156,7 @@ CONFIG_BATTERY_BQ27XXX=y
CONFIG_CHARGER_GPIO=y
CONFIG_CHARGER_SMB347=y
CONFIG_CHARGER_TPS65090=y
+CONFIG_BATTERY_ACER_A500=y
CONFIG_SENSORS_LM90=y
CONFIG_SENSORS_LM95245=y
CONFIG_THERMAL=y
@@ -169,11 +164,11 @@ CONFIG_THERMAL_STATISTICS=y
CONFIG_CPU_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_TEGRA_SOCTHERM=m
+CONFIG_TEGRA30_TSENSOR=m
CONFIG_WATCHDOG=y
CONFIG_MAX77620_WATCHDOG=y
CONFIG_TEGRA_WATCHDOG=y
CONFIG_MFD_AS3722=y
-CONFIG_MFD_CROS_EC_DEV=y
CONFIG_MFD_MAX77620=y
CONFIG_MFD_MAX8907=y
CONFIG_MFD_STMPE=y
@@ -181,6 +176,7 @@ CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65090=y
CONFIG_MFD_TPS6586X=y
CONFIG_MFD_TPS65910=y
+CONFIG_MFD_ACER_A500_EC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AS3722=y
@@ -194,7 +190,6 @@ CONFIG_REGULATOR_TPS65090=y
CONFIG_REGULATOR_TPS6586X=y
CONFIG_REGULATOR_TPS65910=y
CONFIG_MEDIA_SUPPORT=y
-CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=y
CONFIG_USB_GSPCA=y
@@ -205,7 +200,7 @@ CONFIG_DRM_TEGRA_STAGING=y
CONFIG_DRM_PANEL_LVDS=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_LVDS_CODEC=y
-# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_FB=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=y
CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -245,18 +240,15 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
-CONFIG_USB_CHIPIDEA_TEGRA=y
CONFIG_USB_GADGET=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=16
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_TEGRA=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
-CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_ACER_A500=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -284,15 +276,15 @@ CONFIG_NVEC_POWER=y
CONFIG_NVEC_PAZ00=y
CONFIG_STAGING_MEDIA=y
CONFIG_TEGRA_VDE=y
+CONFIG_CHROME_PLATFORMS=y
+CONFIG_CROS_EC=y
CONFIG_TEGRA_IOMMU_GART=y
CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_ARCH_TEGRA_2x_SOC=y
CONFIG_ARCH_TEGRA_3x_SOC=y
CONFIG_ARCH_TEGRA_114_SOC=y
CONFIG_ARCH_TEGRA_124_SOC=y
-CONFIG_PM_DEVFREQ=y
CONFIG_ARM_TEGRA_DEVFREQ=y
-CONFIG_ARM_TEGRA20_DEVFREQ=y
CONFIG_MEMORY=y
CONFIG_IIO=y
CONFIG_KXCJK1013=y
@@ -333,7 +325,6 @@ CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRC_CCITT=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=64
CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 2e24e765e6d3..5e56288e343b 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -291,6 +291,7 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
extern void flush_dcache_page(struct page *);
+#define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1
static inline void flush_kernel_vmap_range(void *addr, int size)
{
if ((cache_is_vivt() || cache_is_vipt_aliasing()))
@@ -312,9 +313,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
__flush_anon_page(vma, page, vmaddr);
}
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-extern void flush_kernel_dcache_page(struct page *);
-
#define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages)
#define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages)
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 9de7ab2ce05d..a6f3b179e8a9 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -17,6 +17,7 @@
#ifdef CONFIG_EFI
void efi_init(void);
+extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
@@ -52,10 +53,6 @@ void efi_virtmap_unload(void);
struct screen_info *alloc_screen_info(void);
void free_screen_info(struct screen_info *si);
-static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
-{
-}
-
/*
* A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
* so we will reserve that amount of memory. We have no easy way to tell what
diff --git a/arch/arm/include/asm/fpstate.h b/arch/arm/include/asm/fpstate.h
index 9e2fe9ced084..ca42fd9ae0b3 100644
--- a/arch/arm/include/asm/fpstate.h
+++ b/arch/arm/include/asm/fpstate.h
@@ -77,14 +77,6 @@ union fp_state {
#define FP_SIZE (sizeof(union fp_state) / sizeof(int))
-struct crunch_state {
- unsigned int mvdx[16][2];
- unsigned int mvax[4][3];
- unsigned int dspsc[2];
-};
-
-#define CRUNCH_SIZE sizeof(struct crunch_state)
-
#endif
#endif
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 70d4cbc49ae1..a02799bd0cdf 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -65,9 +65,6 @@ struct thread_info {
__u32 syscall; /* syscall number */
__u8 used_cp[16]; /* thread used copro */
unsigned long tp_value[2]; /* TLS registers */
-#ifdef CONFIG_CRUNCH
- struct crunch_state crunchstate;
-#endif
union fp_state fpstate __attribute__((aligned(8)));
union vfp_state vfpstate;
#ifdef CONFIG_ARM_THUMBEE
@@ -107,11 +104,6 @@ static inline struct thread_info *current_thread_info(void)
((unsigned long)(task_thread_info(tsk)->cpu_context.r7))
#endif
-extern void crunch_task_disable(struct thread_info *);
-extern void crunch_task_copy(struct thread_info *, void *);
-extern void crunch_task_restore(struct thread_info *, void *);
-extern void crunch_task_release(struct thread_info *);
-
extern void iwmmxt_task_disable(struct thread_info *);
extern void iwmmxt_task_copy(struct thread_info *, void *);
extern void iwmmxt_task_restore(struct thread_info *, void *);
diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
index 5c5e62cb304b..4048c92d9c2b 100644
--- a/arch/arm/include/asm/ucontext.h
+++ b/arch/arm/include/asm/ucontext.h
@@ -43,17 +43,6 @@ struct ucontext {
*/
#define DUMMY_MAGIC 0xb0d9ed01
-#ifdef CONFIG_CRUNCH
-#define CRUNCH_MAGIC 0x5065cf03
-#define CRUNCH_STORAGE_SIZE (CRUNCH_SIZE + 8)
-
-struct crunch_sigframe {
- unsigned long magic;
- unsigned long size;
- struct crunch_state storage;
-} __attribute__((__aligned__(8)));
-#endif
-
#ifdef CONFIG_IWMMXT
/* iwmmxt_area is 0x98 bytes long, preceded by 8 bytes of signature */
#define IWMMXT_MAGIC 0x12ef842a
@@ -92,9 +81,6 @@ struct vfp_sigframe
* one of these.
*/
struct aux_sigframe {
-#ifdef CONFIG_CRUNCH
- struct crunch_sigframe crunch;
-#endif
#ifdef CONFIG_IWMMXT
struct iwmmxt_sigframe iwmmxt;
#endif
diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h
index b5971dfa4b8c..990199d8b7c6 100644
--- a/arch/arm/include/uapi/asm/hwcap.h
+++ b/arch/arm/include/uapi/asm/hwcap.h
@@ -15,7 +15,7 @@
#define HWCAP_EDSP (1 << 7)
#define HWCAP_JAVA (1 << 8)
#define HWCAP_IWMMXT (1 << 9)
-#define HWCAP_CRUNCH (1 << 10)
+#define HWCAP_CRUNCH (1 << 10) /* Obsolete */
#define HWCAP_THUMBEE (1 << 11)
#define HWCAP_NEON (1 << 12)
#define HWCAP_VFPv3 (1 << 13)
diff --git a/arch/arm/include/uapi/asm/ptrace.h b/arch/arm/include/uapi/asm/ptrace.h
index e61c65b4018d..8896c23ccba7 100644
--- a/arch/arm/include/uapi/asm/ptrace.h
+++ b/arch/arm/include/uapi/asm/ptrace.h
@@ -26,8 +26,8 @@
#define PTRACE_GET_THREAD_AREA 22
#define PTRACE_SET_SYSCALL 23
/* PTRACE_SYSCALL is 24 */
-#define PTRACE_GETCRUNCHREGS 25
-#define PTRACE_SETCRUNCHREGS 26
+#define PTRACE_GETCRUNCHREGS 25 /* obsolete */
+#define PTRACE_SETCRUNCHREGS 26 /* obsolete */
#define PTRACE_GETVFPREGS 27
#define PTRACE_SETVFPREGS 28
#define PTRACE_GETHBPREGS 29
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 70993af22d80..64944701bf6a 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -63,9 +63,6 @@ int main(void)
#ifdef CONFIG_IWMMXT
DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt));
#endif
-#ifdef CONFIG_CRUNCH
- DEFINE(TI_CRUNCH_STATE, offsetof(struct thread_info, crunchstate));
-#endif
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
DEFINE(TI_STACK_CANARY, offsetof(struct thread_info, stack_canary));
#endif
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 0ea8529a4872..241b73d64df7 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -618,15 +618,9 @@ call_fpe:
W(b) do_fpe @ CP#1 (FPE)
W(b) do_fpe @ CP#2 (FPE)
ret.w lr @ CP#3
-#ifdef CONFIG_CRUNCH
- b crunch_task_enable @ CP#4 (MaverickCrunch)
- b crunch_task_enable @ CP#5 (MaverickCrunch)
- b crunch_task_enable @ CP#6 (MaverickCrunch)
-#else
ret.w lr @ CP#4
ret.w lr @ CP#5
ret.w lr @ CP#6
-#endif
ret.w lr @ CP#7
ret.w lr @ CP#8
ret.w lr @ CP#9
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
index d0e898608d30..7bde93c10962 100644
--- a/arch/arm/kernel/entry-v7m.S
+++ b/arch/arm/kernel/entry-v7m.S
@@ -23,7 +23,7 @@ __invalid_entry:
adr r0, strerr
mrs r1, ipsr
mov r2, lr
- bl printk
+ bl _printk
#endif
mov r0, sp
bl show_regs
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index fc9e8b37eaa8..bb5ad8a6a4c3 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -5,8 +5,6 @@
* Copyright (C) 1996-2000 Russell King - Converted to ARM.
* Original Copyright (C) 1995 Linus Torvalds
*/
-#include <stdarg.h>
-
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 2771e682220b..b008859680bc 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -318,32 +318,6 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
#endif
-#ifdef CONFIG_CRUNCH
-/*
- * Get the child Crunch state.
- */
-static int ptrace_getcrunchregs(struct task_struct *tsk, void __user *ufp)
-{
- struct thread_info *thread = task_thread_info(tsk);
-
- crunch_task_disable(thread); /* force it to ram */
- return copy_to_user(ufp, &thread->crunchstate, CRUNCH_SIZE)
- ? -EFAULT : 0;
-}
-
-/*
- * Set the child Crunch state.
- */
-static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp)
-{
- struct thread_info *thread = task_thread_info(tsk);
-
- crunch_task_release(thread); /* force a reload */
- return copy_from_user(&thread->crunchstate, ufp, CRUNCH_SIZE)
- ? -EFAULT : 0;
-}
-#endif
-
#ifdef CONFIG_HAVE_HW_BREAKPOINT
/*
* Convert a virtual register number into an index for a thread_info
@@ -815,16 +789,6 @@ long arch_ptrace(struct task_struct *child, long request,
ret = 0;
break;
-#ifdef CONFIG_CRUNCH
- case PTRACE_GETCRUNCHREGS:
- ret = ptrace_getcrunchregs(child, datap);
- break;
-
- case PTRACE_SETCRUNCHREGS:
- ret = ptrace_setcrunchregs(child, datap);
- break;
-#endif
-
#ifdef CONFIG_VFP
case PTRACE_GETVFPREGS:
ret = copy_regset_to_user(child,
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index f97eb2371672..284a80c0b6e1 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -1012,31 +1012,25 @@ static void __init reserve_crashkernel(void)
unsigned long long lowmem_max = __pa(high_memory - 1) + 1;
if (crash_max > lowmem_max)
crash_max = lowmem_max;
- crash_base = memblock_find_in_range(CRASH_ALIGN, crash_max,
- crash_size, CRASH_ALIGN);
+
+ crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN,
+ CRASH_ALIGN, crash_max);
if (!crash_base) {
pr_err("crashkernel reservation failed - No suitable area found.\n");
return;
}
} else {
+ unsigned long long crash_max = crash_base + crash_size;
unsigned long long start;
- start = memblock_find_in_range(crash_base,
- crash_base + crash_size,
- crash_size, SECTION_SIZE);
- if (start != crash_base) {
+ start = memblock_phys_alloc_range(crash_size, SECTION_SIZE,
+ crash_base, crash_max);
+ if (!start) {
pr_err("crashkernel reservation failed - memory is in use.\n");
return;
}
}
- ret = memblock_reserve(crash_base, crash_size);
- if (ret < 0) {
- pr_warn("crashkernel reservation failed - memory is in use (0x%lx)\n",
- (unsigned long)crash_base);
- return;
- }
-
pr_info("Reserving %ldMB of memory at %ldMB for crashkernel (System RAM: %ldMB)\n",
(unsigned long)(crash_size >> 20),
(unsigned long)(crash_base >> 20),
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index a3a38d0a4c85..4e0dcff3f5b0 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -25,40 +25,6 @@ extern const unsigned long sigreturn_codes[17];
static unsigned long signal_return_offset;
-#ifdef CONFIG_CRUNCH
-static int preserve_crunch_context(struct crunch_sigframe __user *frame)
-{
- char kbuf[sizeof(*frame) + 8];
- struct crunch_sigframe *kframe;
-
- /* the crunch context must be 64 bit aligned */
- kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7);
- kframe->magic = CRUNCH_MAGIC;
- kframe->size = CRUNCH_STORAGE_SIZE;
- crunch_task_copy(current_thread_info(), &kframe->storage);
- return __copy_to_user(frame, kframe, sizeof(*frame));
-}
-
-static int restore_crunch_context(char __user **auxp)
-{
- struct crunch_sigframe __user *frame =
- (struct crunch_sigframe __user *)*auxp;
- char kbuf[sizeof(*frame) + 8];
- struct crunch_sigframe *kframe;
-
- /* the crunch context must be 64 bit aligned */
- kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7);
- if (__copy_from_user(kframe, frame, sizeof(*frame)))
- return -1;
- if (kframe->magic != CRUNCH_MAGIC ||
- kframe->size != CRUNCH_STORAGE_SIZE)
- return -1;
- *auxp += CRUNCH_STORAGE_SIZE;
- crunch_task_restore(current_thread_info(), &kframe->storage);
- return 0;
-}
-#endif
-
#ifdef CONFIG_IWMMXT
static int preserve_iwmmxt_context(struct iwmmxt_sigframe __user *frame)
@@ -205,10 +171,6 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
err |= !valid_user_regs(regs);
aux = (char __user *) sf->uc.uc_regspace;
-#ifdef CONFIG_CRUNCH
- if (err == 0)
- err |= restore_crunch_context(&aux);
-#endif
#ifdef CONFIG_IWMMXT
if (err == 0)
err |= restore_iwmmxt_context(&aux);
@@ -321,10 +283,6 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
-#ifdef CONFIG_CRUNCH
- if (err == 0)
- err |= preserve_crunch_context(&aux->crunch);
-#endif
#ifdef CONFIG_IWMMXT
if (err == 0)
err |= preserve_iwmmxt_context(&aux->iwmmxt);
@@ -725,3 +683,42 @@ asmlinkage void do_rseq_syscall(struct pt_regs *regs)
rseq_syscall(regs);
}
#endif
+
+/*
+ * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as
+ * changes likely come with new fields that should be added below.
+ */
+static_assert(NSIGILL == 11);
+static_assert(NSIGFPE == 15);
+static_assert(NSIGSEGV == 9);
+static_assert(NSIGBUS == 5);
+static_assert(NSIGTRAP == 6);
+static_assert(NSIGCHLD == 6);
+static_assert(NSIGSYS == 2);
+static_assert(sizeof(siginfo_t) == 128);
+static_assert(__alignof__(siginfo_t) == 4);
+static_assert(offsetof(siginfo_t, si_signo) == 0x00);
+static_assert(offsetof(siginfo_t, si_errno) == 0x04);
+static_assert(offsetof(siginfo_t, si_code) == 0x08);
+static_assert(offsetof(siginfo_t, si_pid) == 0x0c);
+static_assert(offsetof(siginfo_t, si_uid) == 0x10);
+static_assert(offsetof(siginfo_t, si_tid) == 0x0c);
+static_assert(offsetof(siginfo_t, si_overrun) == 0x10);
+static_assert(offsetof(siginfo_t, si_status) == 0x14);
+static_assert(offsetof(siginfo_t, si_utime) == 0x18);
+static_assert(offsetof(siginfo_t, si_stime) == 0x1c);
+static_assert(offsetof(siginfo_t, si_value) == 0x14);
+static_assert(offsetof(siginfo_t, si_int) == 0x14);
+static_assert(offsetof(siginfo_t, si_ptr) == 0x14);
+static_assert(offsetof(siginfo_t, si_addr) == 0x0c);
+static_assert(offsetof(siginfo_t, si_addr_lsb) == 0x10);
+static_assert(offsetof(siginfo_t, si_lower) == 0x14);
+static_assert(offsetof(siginfo_t, si_upper) == 0x18);
+static_assert(offsetof(siginfo_t, si_pkey) == 0x14);
+static_assert(offsetof(siginfo_t, si_perf_data) == 0x10);
+static_assert(offsetof(siginfo_t, si_perf_type) == 0x14);
+static_assert(offsetof(siginfo_t, si_band) == 0x0c);
+static_assert(offsetof(siginfo_t, si_fd) == 0x10);
+static_assert(offsetof(siginfo_t, si_call_addr) == 0x0c);
+static_assert(offsetof(siginfo_t, si_syscall) == 0x10);
+static_assert(offsetof(siginfo_t, si_arch) == 0x14);
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index c7bb168b0d97..842427ff2b3c 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -667,9 +667,9 @@ static void do_handle_IPI(int ipinr)
break;
case IPI_CPU_BACKTRACE:
- printk_nmi_enter();
+ printk_deferred_enter();
nmi_cpu_backtrace(get_irq_regs());
- printk_nmi_exit();
+ printk_deferred_exit();
break;
default:
diff --git a/arch/arm/lib/backtrace-clang.S b/arch/arm/lib/backtrace-clang.S
index 6174c45f53a5..5b2cdb1003e3 100644
--- a/arch/arm/lib/backtrace-clang.S
+++ b/arch/arm/lib/backtrace-clang.S
@@ -202,7 +202,7 @@ finished_setup:
1006: adr r0, .Lbad
mov r1, loglvl
mov r2, frame
- bl printk
+ bl _printk
no_frame: ldmfd sp!, {r4 - r9, fp, pc}
ENDPROC(c_backtrace)
.pushsection __ex_table,"a"
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 872f658638d9..e8408f22d4dc 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -103,7 +103,7 @@ for_each_frame: tst frame, mask @ Check for address exceptions
1006: adr r0, .Lbad
mov r1, loglvl
mov r2, frame
- bl printk
+ bl _printk
no_frame: ldmfd sp!, {r4 - r9, pc}
ENDPROC(c_backtrace)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index ccd7e80ce943..b09bb2279f7f 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -57,6 +57,16 @@ config SOC_SAMA5D4
help
Select this if you are using one of Microchip's SAMA5D4 family SoC.
+config SOC_SAMA7G5
+ bool "SAMA7G5 family"
+ depends on ARCH_MULTI_V7
+ select HAVE_AT91_GENERATED_CLK
+ select HAVE_AT91_SAM9X60_PLL
+ select HAVE_AT91_UTMI
+ select SOC_SAMA7
+ help
+ Select this if you are using one of Microchip's SAMA7G5 family SoC.
+
config SOC_AT91RM9200
bool "AT91RM9200"
depends on ARCH_MULTI_V4T
@@ -191,4 +201,12 @@ config SOC_SAMA5
config ATMEL_PM
bool
+config SOC_SAMA7
+ bool
+ select ARM_GIC
+ select ATMEL_PM if PM
+ select ATMEL_SDRAMC
+ select MEMORY
+ select SOC_SAM_V7
+ select SRAM if PM
endif
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index f565490f1b70..522b680b6446 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o
obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o
obj-$(CONFIG_SOC_SAMA5) += sama5.o
+obj-$(CONFIG_SOC_SAMA7) += sama7.o
obj-$(CONFIG_SOC_SAMV7) += samv7.o
# Power Management
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 0a4cdcb4985b..0c3960a8b3eb 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -14,12 +14,14 @@ extern void __init at91sam9_pm_init(void);
extern void __init sam9x60_pm_init(void);
extern void __init sama5_pm_init(void);
extern void __init sama5d2_pm_init(void);
+extern void __init sama7_pm_init(void);
#else
static inline void __init at91rm9200_pm_init(void) { }
static inline void __init at91sam9_pm_init(void) { }
static inline void __init sam9x60_pm_init(void) { }
static inline void __init sama5_pm_init(void) { }
static inline void __init sama5d2_pm_init(void) { }
+static inline void __init sama7_pm_init(void) { }
#endif
#endif /* _AT91_GENERIC_H */
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 90dcdfe3b3d0..d6cfe7c4bb00 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -10,6 +10,7 @@
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of.h>
+#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/parser.h>
#include <linux/suspend.h>
@@ -27,13 +28,55 @@
#include "generic.h"
#include "pm.h"
+#define BACKUP_DDR_PHY_CALIBRATION (9)
+
+/**
+ * struct at91_pm_bu - AT91 power management backup unit data structure
+ * @suspended: true if suspended to backup mode
+ * @reserved: reserved
+ * @canary: canary data for memory checking after exit from backup mode
+ * @resume: resume API
+ * @ddr_phy_calibration: DDR PHY calibration data: ZQ0CR0, first 8 words
+ * of the memory
+ */
+struct at91_pm_bu {
+ int suspended;
+ unsigned long reserved;
+ phys_addr_t canary;
+ phys_addr_t resume;
+ unsigned long ddr_phy_calibration[BACKUP_DDR_PHY_CALIBRATION];
+};
+
+/**
+ * struct at91_soc_pm - AT91 SoC power management data structure
+ * @config_shdwc_ws: wakeup sources configuration function for SHDWC
+ * @config_pmc_ws: wakeup srouces configuration function for PMC
+ * @ws_ids: wakup sources of_device_id array
+ * @data: PM data to be used on last phase of suspend
+ * @bu: backup unit mapped data (for backup mode)
+ * @memcs: memory chip select
+ */
struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
const struct of_device_id *ws_ids;
+ struct at91_pm_bu *bu;
struct at91_pm_data data;
+ void *memcs;
};
+/**
+ * enum at91_pm_iomaps: IOs that needs to be mapped for different PM modes
+ * @AT91_PM_IOMAP_SHDWC: SHDWC controller
+ * @AT91_PM_IOMAP_SFRBU: SFRBU controller
+ */
+enum at91_pm_iomaps {
+ AT91_PM_IOMAP_SHDWC,
+ AT91_PM_IOMAP_SFRBU,
+};
+
+#define AT91_PM_IOMAP(name) BIT(AT91_PM_IOMAP_##name)
+
static struct at91_soc_pm soc_pm = {
.data = {
.standby_mode = AT91_PM_STANDBY,
@@ -71,13 +114,6 @@ static int at91_pm_valid_state(suspend_state_t state)
static int canary = 0xA5A5A5A5;
-static struct at91_pm_bu {
- int suspended;
- unsigned long reserved;
- phys_addr_t canary;
- phys_addr_t resume;
-} *pm_bu;
-
struct wakeup_source_info {
unsigned int pmc_fsmr_bit;
unsigned int shdwc_mr_bit;
@@ -116,6 +152,17 @@ static const struct of_device_id sam9x60_ws_ids[] = {
{ /* sentinel */ }
};
+static const struct of_device_id sama7g5_ws_ids[] = {
+ { .compatible = "atmel,at91sam9x5-rtc", .data = &ws_info[1] },
+ { .compatible = "microchip,sama7g5-ohci", .data = &ws_info[2] },
+ { .compatible = "usb-ohci", .data = &ws_info[2] },
+ { .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
+ { .compatible = "usb-ehci", .data = &ws_info[2] },
+ { .compatible = "microchip,sama7g5-sdhci", .data = &ws_info[3] },
+ { .compatible = "atmel,at91sam9260-rtt", .data = &ws_info[4] },
+ { /* sentinel */ }
+};
+
static int at91_pm_config_ws(unsigned int pm_mode, bool set)
{
const struct wakeup_source_info *wsi;
@@ -206,6 +253,8 @@ static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity)
*/
static int at91_pm_begin(suspend_state_t state)
{
+ int ret;
+
switch (state) {
case PM_SUSPEND_MEM:
soc_pm.data.mode = soc_pm.data.suspend_mode;
@@ -219,7 +268,16 @@ static int at91_pm_begin(suspend_state_t state)
soc_pm.data.mode = -1;
}
- return at91_pm_config_ws(soc_pm.data.mode, true);
+ ret = at91_pm_config_ws(soc_pm.data.mode, true);
+ if (ret)
+ return ret;
+
+ if (soc_pm.data.mode == AT91_PM_BACKUP)
+ soc_pm.bu->suspended = 1;
+ else if (soc_pm.bu)
+ soc_pm.bu->suspended = 0;
+
+ return 0;
}
/*
@@ -277,6 +335,19 @@ extern u32 at91_pm_suspend_in_sram_sz;
static int at91_suspend_finish(unsigned long val)
{
+ int i;
+
+ if (soc_pm.data.mode == AT91_PM_BACKUP && soc_pm.data.ramc_phy) {
+ /*
+ * The 1st 8 words of memory might get corrupted in the process
+ * of DDR PHY recalibration; it is saved here in securam and it
+ * will be restored later, after recalibration, by bootloader
+ */
+ for (i = 1; i < BACKUP_DDR_PHY_CALIBRATION; i++)
+ soc_pm.bu->ddr_phy_calibration[i] =
+ *((unsigned int *)soc_pm.memcs + (i - 1));
+ }
+
flush_cache_all();
outer_disable();
@@ -288,8 +359,6 @@ static int at91_suspend_finish(unsigned long val)
static void at91_pm_suspend(suspend_state_t state)
{
if (soc_pm.data.mode == AT91_PM_BACKUP) {
- pm_bu->suspended = 1;
-
cpu_suspend(0, at91_suspend_finish);
/* The SRAM is lost between suspend cycles */
@@ -511,10 +580,16 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
{ .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] },
+ { .compatible = "microchip,sama7g5-uddrc", },
{ /*sentinel*/ }
};
-static __init void at91_dt_ramc(void)
+static const struct of_device_id ramc_phy_ids[] __initconst = {
+ { .compatible = "microchip,sama7g5-ddr3phy", },
+ { /* Sentinel. */ },
+};
+
+static __init void at91_dt_ramc(bool phy_mandatory)
{
struct device_node *np;
const struct of_device_id *of_id;
@@ -528,9 +603,11 @@ static __init void at91_dt_ramc(void)
panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
ramc = of_id->data;
- if (!standby)
- standby = ramc->idle;
- soc_pm.data.memctrl = ramc->memctrl;
+ if (ramc) {
+ if (!standby)
+ standby = ramc->idle;
+ soc_pm.data.memctrl = ramc->memctrl;
+ }
idx++;
}
@@ -538,6 +615,16 @@ static __init void at91_dt_ramc(void)
if (!idx)
panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
+ /* Lookup for DDR PHY node, if any. */
+ for_each_matching_node_and_match(np, ramc_phy_ids, &of_id) {
+ soc_pm.data.ramc_phy = of_iomap(np, 0);
+ if (!soc_pm.data.ramc_phy)
+ panic(pr_fmt("unable to map ramc phy cpu registers\n"));
+ }
+
+ if (phy_mandatory && !soc_pm.data.ramc_phy)
+ panic(pr_fmt("DDR PHY is mandatory!\n"));
+
if (!standby) {
pr_warn("ramc no standby function available\n");
return;
@@ -618,37 +705,57 @@ static bool __init at91_is_pm_mode_active(int pm_mode)
soc_pm.data.suspend_mode == pm_mode);
}
+static int __init at91_pm_backup_scan_memcs(unsigned long node,
+ const char *uname, int depth,
+ void *data)
+{
+ const char *type;
+ const __be32 *reg;
+ int *located = data;
+ int size;
+
+ /* Memory node already located. */
+ if (*located)
+ return 0;
+
+ type = of_get_flat_dt_prop(node, "device_type", NULL);
+
+ /* We are scanning "memory" nodes only. */
+ if (!type || strcmp(type, "memory"))
+ return 0;
+
+ reg = of_get_flat_dt_prop(node, "reg", &size);
+ if (reg) {
+ soc_pm.memcs = __va((phys_addr_t)be32_to_cpu(*reg));
+ *located = 1;
+ }
+
+ return 0;
+}
+
static int __init at91_pm_backup_init(void)
{
struct gen_pool *sram_pool;
struct device_node *np;
- struct platform_device *pdev = NULL;
- int ret = -ENODEV;
+ struct platform_device *pdev;
+ int ret = -ENODEV, located = 0;
- if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
+ if (!IS_ENABLED(CONFIG_SOC_SAMA5D2) &&
+ !IS_ENABLED(CONFIG_SOC_SAMA7G5))
return -EPERM;
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
return 0;
- np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
- if (!np) {
- pr_warn("%s: failed to find sfrbu!\n", __func__);
- return ret;
- }
-
- soc_pm.data.sfrbu = of_iomap(np, 0);
- of_node_put(np);
-
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
if (!np)
- goto securam_fail_no_ref_dev;
+ return ret;
pdev = of_find_device_by_node(np);
of_node_put(np);
if (!pdev) {
pr_warn("%s: failed to find securam device!\n", __func__);
- goto securam_fail_no_ref_dev;
+ return ret;
}
sram_pool = gen_pool_get(&pdev->dev, NULL);
@@ -657,79 +764,117 @@ static int __init at91_pm_backup_init(void)
goto securam_fail;
}
- pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
- if (!pm_bu) {
+ soc_pm.bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
+ if (!soc_pm.bu) {
pr_warn("%s: unable to alloc securam!\n", __func__);
ret = -ENOMEM;
goto securam_fail;
}
- pm_bu->suspended = 0;
- pm_bu->canary = __pa_symbol(&canary);
- pm_bu->resume = __pa_symbol(cpu_resume);
+ soc_pm.bu->suspended = 0;
+ soc_pm.bu->canary = __pa_symbol(&canary);
+ soc_pm.bu->resume = __pa_symbol(cpu_resume);
+ if (soc_pm.data.ramc_phy) {
+ of_scan_flat_dt(at91_pm_backup_scan_memcs, &located);
+ if (!located)
+ goto securam_fail;
+
+ /* DDR3PHY_ZQ0SR0 */
+ soc_pm.bu->ddr_phy_calibration[0] = readl(soc_pm.data.ramc_phy +
+ 0x188);
+ }
return 0;
securam_fail:
put_device(&pdev->dev);
-securam_fail_no_ref_dev:
- iounmap(soc_pm.data.sfrbu);
- soc_pm.data.sfrbu = NULL;
return ret;
}
-static void __init at91_pm_use_default_mode(int pm_mode)
-{
- if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
- return;
-
- if (soc_pm.data.standby_mode == pm_mode)
- soc_pm.data.standby_mode = AT91_PM_ULP0;
- if (soc_pm.data.suspend_mode == pm_mode)
- soc_pm.data.suspend_mode = AT91_PM_ULP0;
-}
-
static const struct of_device_id atmel_shdwc_ids[] = {
{ .compatible = "atmel,sama5d2-shdwc" },
{ .compatible = "microchip,sam9x60-shdwc" },
+ { .compatible = "microchip,sama7g5-shdwc" },
{ /* sentinel. */ }
};
-static void __init at91_pm_modes_init(void)
+static void __init at91_pm_modes_init(const u32 *maps, int len)
{
struct device_node *np;
- int ret;
+ int ret, mode;
- if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
- !at91_is_pm_mode_active(AT91_PM_ULP1))
- return;
+ ret = at91_pm_backup_init();
+ if (ret) {
+ if (soc_pm.data.standby_mode == AT91_PM_BACKUP)
+ soc_pm.data.standby_mode = AT91_PM_ULP0;
+ if (soc_pm.data.suspend_mode == AT91_PM_BACKUP)
+ soc_pm.data.suspend_mode = AT91_PM_ULP0;
+ }
- np = of_find_matching_node(NULL, atmel_shdwc_ids);
- if (!np) {
- pr_warn("%s: failed to find shdwc!\n", __func__);
- goto ulp1_default;
+ if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
+ maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC)) {
+ np = of_find_matching_node(NULL, atmel_shdwc_ids);
+ if (!np) {
+ pr_warn("%s: failed to find shdwc!\n", __func__);
+
+ /* Use ULP0 if it doesn't needs SHDWC.*/
+ if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)))
+ mode = AT91_PM_ULP0;
+ else
+ mode = AT91_PM_STANDBY;
+
+ if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC))
+ soc_pm.data.standby_mode = mode;
+ if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))
+ soc_pm.data.suspend_mode = mode;
+ } else {
+ soc_pm.data.shdwc = of_iomap(np, 0);
+ of_node_put(np);
+ }
}
- soc_pm.data.shdwc = of_iomap(np, 0);
- of_node_put(np);
+ if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
+ maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU)) {
+ np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
+ if (!np) {
+ pr_warn("%s: failed to find sfrbu!\n", __func__);
+
+ /*
+ * Use ULP0 if it doesn't need SHDWC or if SHDWC
+ * was already located.
+ */
+ if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)) ||
+ soc_pm.data.shdwc)
+ mode = AT91_PM_ULP0;
+ else
+ mode = AT91_PM_STANDBY;
+
+ if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU))
+ soc_pm.data.standby_mode = mode;
+ if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))
+ soc_pm.data.suspend_mode = mode;
+ } else {
+ soc_pm.data.sfrbu = of_iomap(np, 0);
+ of_node_put(np);
+ }
+ }
- ret = at91_pm_backup_init();
- if (ret) {
- if (!at91_is_pm_mode_active(AT91_PM_ULP1))
- goto unmap;
- else
- goto backup_default;
+ /* Unmap all unnecessary. */
+ if (soc_pm.data.shdwc &&
+ !(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
+ maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))) {
+ iounmap(soc_pm.data.shdwc);
+ soc_pm.data.shdwc = NULL;
}
- return;
+ if (soc_pm.data.sfrbu &&
+ !(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
+ maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))) {
+ iounmap(soc_pm.data.sfrbu);
+ soc_pm.data.sfrbu = NULL;
+ }
-unmap:
- iounmap(soc_pm.data.shdwc);
- soc_pm.data.shdwc = NULL;
-ulp1_default:
- at91_pm_use_default_mode(AT91_PM_ULP1);
-backup_default:
- at91_pm_use_default_mode(AT91_PM_BACKUP);
+ return;
}
struct pmc_info {
@@ -764,6 +909,11 @@ static const struct pmc_info pmc_infos[] __initconst = {
.mckr = 0x28,
.version = AT91_PMC_V2,
},
+ {
+ .mckr = 0x28,
+ .version = AT91_PMC_V2,
+ },
+
};
static const struct of_device_id atmel_pmc_ids[] __initconst = {
@@ -779,6 +929,7 @@ static const struct of_device_id atmel_pmc_ids[] __initconst = {
{ .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] },
{ .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
{ .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] },
+ { .compatible = "microchip,sama7g5-pmc", .data = &pmc_infos[5] },
{ /* sentinel */ },
};
@@ -877,7 +1028,7 @@ void __init at91rm9200_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
- at91_dt_ramc();
+ at91_dt_ramc(false);
/*
* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
@@ -892,13 +1043,16 @@ void __init sam9x60_pm_init(void)
static const int modes[] __initconst = {
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
};
+ static const int iomaps[] __initconst = {
+ [AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
+ };
if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
return;
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
- at91_pm_modes_init();
- at91_dt_ramc();
+ at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
+ at91_dt_ramc(false);
at91_pm_init(NULL);
soc_pm.ws_ids = sam9x60_ws_ids;
@@ -918,7 +1072,7 @@ void __init at91sam9_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
- at91_dt_ramc();
+ at91_dt_ramc(false);
at91_pm_init(at91sam9_idle);
}
@@ -932,7 +1086,7 @@ void __init sama5_pm_init(void)
return;
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
- at91_dt_ramc();
+ at91_dt_ramc(false);
at91_pm_init(NULL);
}
@@ -942,13 +1096,18 @@ void __init sama5d2_pm_init(void)
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
AT91_PM_BACKUP,
};
+ static const u32 iomaps[] __initconst = {
+ [AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
+ [AT91_PM_BACKUP] = AT91_PM_IOMAP(SHDWC) |
+ AT91_PM_IOMAP(SFRBU),
+ };
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
return;
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
- at91_pm_modes_init();
- at91_dt_ramc();
+ at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
+ at91_dt_ramc(false);
at91_pm_init(NULL);
soc_pm.ws_ids = sama5d2_ws_ids;
@@ -956,6 +1115,32 @@ void __init sama5d2_pm_init(void)
soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;
}
+void __init sama7_pm_init(void)
+{
+ static const int modes[] __initconst = {
+ AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP1, AT91_PM_BACKUP,
+ };
+ static const u32 iomaps[] __initconst = {
+ [AT91_PM_ULP0] = AT91_PM_IOMAP(SFRBU),
+ [AT91_PM_ULP1] = AT91_PM_IOMAP(SFRBU) |
+ AT91_PM_IOMAP(SHDWC),
+ [AT91_PM_BACKUP] = AT91_PM_IOMAP(SFRBU) |
+ AT91_PM_IOMAP(SHDWC),
+ };
+
+ if (!IS_ENABLED(CONFIG_SOC_SAMA7))
+ return;
+
+ at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
+
+ at91_dt_ramc(true);
+ at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
+ at91_pm_init(NULL);
+
+ soc_pm.ws_ids = sama7g5_ws_ids;
+ soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
+}
+
static int __init at91_pm_modes_select(char *str)
{
char *s;
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index bfb260be371e..53bdc9000e44 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -12,6 +12,8 @@
#include <linux/mfd/syscon/atmel-mc.h>
#include <soc/at91/at91sam9_ddrsdr.h>
#include <soc/at91/at91sam9_sdramc.h>
+#include <soc/at91/sama7-ddr.h>
+#include <soc/at91/sama7-sfrbu.h>
#define AT91_MEMCTRL_MC 0
#define AT91_MEMCTRL_SDRAMC 1
@@ -27,6 +29,7 @@
struct at91_pm_data {
void __iomem *pmc;
void __iomem *ramc[2];
+ void __iomem *ramc_phy;
unsigned long uhp_udp_mask;
unsigned int memctrl;
unsigned int mode;
diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c
index 82089ff258c0..40bd4e8fe40a 100644
--- a/arch/arm/mach-at91/pm_data-offsets.c
+++ b/arch/arm/mach-at91/pm_data-offsets.c
@@ -8,6 +8,8 @@ int main(void)
DEFINE(PM_DATA_PMC, offsetof(struct at91_pm_data, pmc));
DEFINE(PM_DATA_RAMC0, offsetof(struct at91_pm_data, ramc[0]));
DEFINE(PM_DATA_RAMC1, offsetof(struct at91_pm_data, ramc[1]));
+ DEFINE(PM_DATA_RAMC_PHY, offsetof(struct at91_pm_data,
+ ramc_phy));
DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl));
DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode));
DEFINE(PM_DATA_SHDWC, offsetof(struct at91_pm_data, shdwc));
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index b683c2caa40b..cbd61a3bcab1 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -22,39 +22,57 @@ tmp3 .req r6
/*
* Wait until master clock is ready (after switching master clock source)
+ *
+ * @r_mckid: register holding master clock identifier
+ *
+ * Side effects: overwrites r7, r8
*/
- .macro wait_mckrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_MCKRDY
- beq 1b
+ .macro wait_mckrdy r_mckid
+#ifdef CONFIG_SOC_SAMA7
+ cmp \r_mckid, #0
+ beq 1f
+ mov r7, #AT91_PMC_MCKXRDY
+ b 2f
+#endif
+1: mov r7, #AT91_PMC_MCKRDY
+2: ldr r8, [pmc, #AT91_PMC_SR]
+ and r8, r7
+ cmp r8, r7
+ bne 2b
.endm
/*
* Wait until master oscillator has stabilized.
+ *
+ * Side effects: overwrites r7
*/
.macro wait_moscrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_MOSCS
+1: ldr r7, [pmc, #AT91_PMC_SR]
+ tst r7, #AT91_PMC_MOSCS
beq 1b
.endm
/*
* Wait for main oscillator selection is done
+ *
+ * Side effects: overwrites r7
*/
.macro wait_moscsels
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_MOSCSELS
+1: ldr r7, [pmc, #AT91_PMC_SR]
+ tst r7, #AT91_PMC_MOSCSELS
beq 1b
.endm
/*
* Put the processor to enter the idle state
+ *
+ * Side effects: overwrites r7
*/
.macro at91_cpu_idle
#if defined(CONFIG_CPU_V7)
- mov tmp1, #AT91_PMC_PCK
- str tmp1, [pmc, #AT91_PMC_SCDR]
+ mov r7, #AT91_PMC_PCK
+ str r7, [pmc, #AT91_PMC_SCDR]
dsb
@@ -65,102 +83,375 @@ tmp3 .req r6
.endm
+/**
+ * Set state for 2.5V low power regulator
+ * @ena: 0 - disable regulator
+ * 1 - enable regulator
+ *
+ * Side effects: overwrites r7, r8, r9, r10
+ */
+ .macro at91_2_5V_reg_set_low_power ena
+#ifdef CONFIG_SOC_SAMA7
+ ldr r7, .sfrbu
+ mov r8, #\ena
+ ldr r9, [r7, #AT91_SFRBU_25LDOCR]
+ orr r9, r9, #AT91_SFRBU_25LDOCR_LP
+ cmp r8, #1
+ beq lp_done_\ena
+ bic r9, r9, #AT91_SFRBU_25LDOCR_LP
+lp_done_\ena:
+ ldr r10, =AT91_SFRBU_25LDOCR_LDOANAKEY
+ orr r9, r9, r10
+ str r9, [r7, #AT91_SFRBU_25LDOCR]
+#endif
+ .endm
+
+ .macro at91_backup_set_lpm reg
+#ifdef CONFIG_SOC_SAMA7
+ orr \reg, \reg, #0x200000
+#endif
+ .endm
+
.text
.arm
-/*
- * void at91_suspend_sram_fn(struct at91_pm_data*)
- * @input param:
- * @r0: base address of struct at91_pm_data
+#ifdef CONFIG_SOC_SAMA7
+/**
+ * Enable self-refresh
+ *
+ * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7
*/
-/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
- .align 3
-ENTRY(at91_pm_suspend_in_sram)
- /* Save registers on stack */
- stmfd sp!, {r4 - r12, lr}
+.macro at91_sramc_self_refresh_ena
+ ldr r2, .sramc_base
+ ldr r3, .sramc_phy_base
+ ldr r7, .pm_mode
- /* Drain write buffer */
+ dsb
+
+ /* Disable all AXI ports. */
+ ldr tmp1, [r2, #UDDRC_PCTRL_0]
+ bic tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_0]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_1]
+ bic tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_1]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_2]
+ bic tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_2]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_3]
+ bic tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_3]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_4]
+ bic tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_4]
+
+sr_ena_1:
+ /* Wait for all ports to disable. */
+ ldr tmp1, [r2, #UDDRC_PSTAT]
+ ldr tmp2, =UDDRC_PSTAT_ALL_PORTS
+ tst tmp1, tmp2
+ bne sr_ena_1
+
+ /* Switch to self-refresh. */
+ ldr tmp1, [r2, #UDDRC_PWRCTL]
+ orr tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
+ str tmp1, [r2, #UDDRC_PWRCTL]
+
+sr_ena_2:
+ /* Wait for self-refresh enter. */
+ ldr tmp1, [r2, #UDDRC_STAT]
+ bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
+ cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
+ bne sr_ena_2
+
+ /* Put DDR PHY's DLL in bypass mode for non-backup modes. */
+ cmp r7, #AT91_PM_BACKUP
+ beq sr_ena_3
+ ldr tmp1, [r3, #DDR3PHY_PIR]
+ orr tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
+ str tmp1, [r3, #DDR3PHY_PIR]
+
+sr_ena_3:
+ /* Power down DDR PHY data receivers. */
+ ldr tmp1, [r3, #DDR3PHY_DXCCR]
+ orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+ str tmp1, [r3, #DDR3PHY_DXCCR]
+
+ /* Power down ADDR/CMD IO. */
+ ldr tmp1, [r3, #DDR3PHY_ACIOCR]
+ orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+ orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+ orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+ str tmp1, [r3, #DDR3PHY_ACIOCR]
+
+ /* Power down ODT. */
+ ldr tmp1, [r3, #DDR3PHY_DSGCR]
+ orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
+ str tmp1, [r3, #DDR3PHY_DSGCR]
+.endm
+
+/**
+ * Disable self-refresh
+ *
+ * Side effects: overwrites r2, r3, tmp1, tmp2, tmp3
+ */
+.macro at91_sramc_self_refresh_dis
+ ldr r2, .sramc_base
+ ldr r3, .sramc_phy_base
+
+ /* Power up DDR PHY data receivers. */
+ ldr tmp1, [r3, #DDR3PHY_DXCCR]
+ bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+ str tmp1, [r3, #DDR3PHY_DXCCR]
+
+ /* Power up the output of CK and CS pins. */
+ ldr tmp1, [r3, #DDR3PHY_ACIOCR]
+ bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+ bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+ bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+ str tmp1, [r3, #DDR3PHY_ACIOCR]
+
+ /* Power up ODT. */
+ ldr tmp1, [r3, #DDR3PHY_DSGCR]
+ bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
+ str tmp1, [r3, #DDR3PHY_DSGCR]
+
+ /* Take DDR PHY's DLL out of bypass mode. */
+ ldr tmp1, [r3, #DDR3PHY_PIR]
+ bic tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
+ str tmp1, [r3, #DDR3PHY_PIR]
+
+ /* Enable quasi-dynamic programming. */
mov tmp1, #0
- mcr p15, 0, tmp1, c7, c10, 4
+ str tmp1, [r2, #UDDRC_SWCTRL]
+
+ /* De-assert SDRAM initialization. */
+ ldr tmp1, [r2, #UDDRC_DFIMISC]
+ bic tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
+ str tmp1, [r2, #UDDRC_DFIMISC]
+
+ /* Quasi-dynamic programming done. */
+ mov tmp1, #UDDRC_SWCTRL_SW_DONE
+ str tmp1, [r2, #UDDRC_SWCTRL]
+
+sr_dis_1:
+ ldr tmp1, [r2, #UDDRC_SWSTAT]
+ tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
+ beq sr_dis_1
+
+ /* DLL soft-reset + DLL lock wait + ITM reset */
+ mov tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \
+ DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST)
+ str tmp1, [r3, #DDR3PHY_PIR]
+
+sr_dis_4:
+ /* Wait for it. */
+ ldr tmp1, [r3, #DDR3PHY_PGSR]
+ tst tmp1, #DDR3PHY_PGSR_IDONE
+ beq sr_dis_4
+
+ /* Enable quasi-dynamic programming. */
+ mov tmp1, #0
+ str tmp1, [r2, #UDDRC_SWCTRL]
+
+ /* Assert PHY init complete enable signal. */
+ ldr tmp1, [r2, #UDDRC_DFIMISC]
+ orr tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
+ str tmp1, [r2, #UDDRC_DFIMISC]
+
+ /* Programming is done. Set sw_done. */
+ mov tmp1, #UDDRC_SWCTRL_SW_DONE
+ str tmp1, [r2, #UDDRC_SWCTRL]
+
+sr_dis_5:
+ /* Wait for it. */
+ ldr tmp1, [r2, #UDDRC_SWSTAT]
+ tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
+ beq sr_dis_5
+
+ /* Trigger self-refresh exit. */
+ ldr tmp1, [r2, #UDDRC_PWRCTL]
+ bic tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
+ str tmp1, [r2, #UDDRC_PWRCTL]
+
+sr_dis_6:
+ /* Wait for self-refresh exit done. */
+ ldr tmp1, [r2, #UDDRC_STAT]
+ bic tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK
+ cmp tmp1, #UDDRC_STAT_OPMODE_NORMAL
+ bne sr_dis_6
+
+ /* Enable all AXI ports. */
+ ldr tmp1, [r2, #UDDRC_PCTRL_0]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_0]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_1]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_1]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_2]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_2]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_3]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_3]
+
+ ldr tmp1, [r2, #UDDRC_PCTRL_4]
+ orr tmp1, tmp1, #0x1
+ str tmp1, [r2, #UDDRC_PCTRL_4]
- ldr tmp1, [r0, #PM_DATA_PMC]
- str tmp1, .pmc_base
- ldr tmp1, [r0, #PM_DATA_RAMC0]
- str tmp1, .sramc_base
- ldr tmp1, [r0, #PM_DATA_RAMC1]
- str tmp1, .sramc1_base
- ldr tmp1, [r0, #PM_DATA_MEMCTRL]
- str tmp1, .memtype
- ldr tmp1, [r0, #PM_DATA_MODE]
- str tmp1, .pm_mode
- ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
- str tmp1, .mckr_offset
- ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
- str tmp1, .pmc_version
- /* Both ldrne below are here to preload their address in the TLB */
- ldr tmp1, [r0, #PM_DATA_SHDWC]
- str tmp1, .shdwc
- cmp tmp1, #0
- ldrne tmp2, [tmp1, #0]
- ldr tmp1, [r0, #PM_DATA_SFRBU]
- str tmp1, .sfrbu
- cmp tmp1, #0
- ldrne tmp2, [tmp1, #0x10]
+ dsb
+.endm
+#else
+/**
+ * Enable self-refresh
+ *
+ * register usage:
+ * @r1: memory type
+ * @r2: base address of the sram controller
+ * @r3: temporary
+ */
+.macro at91_sramc_self_refresh_ena
+ ldr r1, .memtype
+ ldr r2, .sramc_base
- /* Active the self-refresh mode */
- mov r0, #SRAMC_SELF_FRESH_ACTIVE
- bl at91_sramc_self_refresh
+ cmp r1, #AT91_MEMCTRL_MC
+ bne sr_ena_ddrc_sf
- ldr r0, .pm_mode
- cmp r0, #AT91_PM_STANDBY
- beq standby
- cmp r0, #AT91_PM_BACKUP
- beq backup_mode
+ /* Active SDRAM self-refresh mode */
+ mov r3, #1
+ str r3, [r2, #AT91_MC_SDRAMC_SRR]
+ b sr_ena_exit
- bl at91_ulp_mode
- b exit_suspend
+sr_ena_ddrc_sf:
+ cmp r1, #AT91_MEMCTRL_DDRSDR
+ bne sr_ena_sdramc_sf
-standby:
- /* Wait for interrupt */
- ldr pmc, .pmc_base
- at91_cpu_idle
- b exit_suspend
+ /*
+ * DDR Memory controller
+ */
-backup_mode:
- bl at91_backup_mode
- b exit_suspend
+ /* LPDDR1 --> force DDR2 mode during self-refresh */
+ ldr r3, [r2, #AT91_DDRSDRC_MDR]
+ str r3, .saved_sam9_mdr
+ bic r3, r3, #~AT91_DDRSDRC_MD
+ cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+ ldreq r3, [r2, #AT91_DDRSDRC_MDR]
+ biceq r3, r3, #AT91_DDRSDRC_MD
+ orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
+ streq r3, [r2, #AT91_DDRSDRC_MDR]
-exit_suspend:
- /* Exit the self-refresh mode */
- mov r0, #SRAMC_SELF_FRESH_EXIT
- bl at91_sramc_self_refresh
+ /* Active DDRC self-refresh mode */
+ ldr r3, [r2, #AT91_DDRSDRC_LPR]
+ str r3, .saved_sam9_lpr
+ bic r3, r3, #AT91_DDRSDRC_LPCB
+ orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+ str r3, [r2, #AT91_DDRSDRC_LPR]
- /* Restore registers, and return */
- ldmfd sp!, {r4 - r12, pc}
-ENDPROC(at91_pm_suspend_in_sram)
+ /* If using the 2nd ddr controller */
+ ldr r2, .sramc1_base
+ cmp r2, #0
+ beq sr_ena_no_2nd_ddrc
-ENTRY(at91_backup_mode)
- /* Switch the master clock source to slow clock. */
- ldr pmc, .pmc_base
- ldr tmp2, .mckr_offset
- ldr tmp1, [pmc, tmp2]
- bic tmp1, tmp1, #AT91_PMC_CSS
- str tmp1, [pmc, tmp2]
+ ldr r3, [r2, #AT91_DDRSDRC_MDR]
+ str r3, .saved_sam9_mdr1
+ bic r3, r3, #~AT91_DDRSDRC_MD
+ cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+ ldreq r3, [r2, #AT91_DDRSDRC_MDR]
+ biceq r3, r3, #AT91_DDRSDRC_MD
+ orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
+ streq r3, [r2, #AT91_DDRSDRC_MDR]
- wait_mckrdy
+ /* Active DDRC self-refresh mode */
+ ldr r3, [r2, #AT91_DDRSDRC_LPR]
+ str r3, .saved_sam9_lpr1
+ bic r3, r3, #AT91_DDRSDRC_LPCB
+ orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+ str r3, [r2, #AT91_DDRSDRC_LPR]
- /*BUMEN*/
- ldr r0, .sfrbu
- mov tmp1, #0x1
- str tmp1, [r0, #0x10]
+sr_ena_no_2nd_ddrc:
+ b sr_ena_exit
- /* Shutdown */
- ldr r0, .shdwc
- mov tmp1, #0xA5000000
- add tmp1, tmp1, #0x1
- str tmp1, [r0, #0]
-ENDPROC(at91_backup_mode)
+ /*
+ * SDRAMC Memory controller
+ */
+sr_ena_sdramc_sf:
+ /* Active SDRAMC self-refresh mode */
+ ldr r3, [r2, #AT91_SDRAMC_LPR]
+ str r3, .saved_sam9_lpr
+ bic r3, r3, #AT91_SDRAMC_LPCB
+ orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
+ str r3, [r2, #AT91_SDRAMC_LPR]
+
+ ldr r3, .saved_sam9_lpr
+ str r3, [r2, #AT91_SDRAMC_LPR]
+
+sr_ena_exit:
+.endm
+
+/**
+ * Disable self-refresh
+ *
+ * register usage:
+ * @r1: memory type
+ * @r2: base address of the sram controller
+ * @r3: temporary
+ */
+.macro at91_sramc_self_refresh_dis
+ ldr r1, .memtype
+ ldr r2, .sramc_base
+
+ cmp r1, #AT91_MEMCTRL_MC
+ bne sr_dis_ddrc_exit_sf
+
+ /*
+ * at91rm9200 Memory controller
+ */
+
+ /*
+ * For exiting the self-refresh mode, do nothing,
+ * automatically exit the self-refresh mode.
+ */
+ b sr_dis_exit
+
+sr_dis_ddrc_exit_sf:
+ cmp r1, #AT91_MEMCTRL_DDRSDR
+ bne sdramc_exit_sf
+
+ /* DDR Memory controller */
+
+ /* Restore MDR in case of LPDDR1 */
+ ldr r3, .saved_sam9_mdr
+ str r3, [r2, #AT91_DDRSDRC_MDR]
+ /* Restore LPR on AT91 with DDRAM */
+ ldr r3, .saved_sam9_lpr
+ str r3, [r2, #AT91_DDRSDRC_LPR]
+
+ /* If using the 2nd ddr controller */
+ ldr r2, .sramc1_base
+ cmp r2, #0
+ ldrne r3, .saved_sam9_mdr1
+ strne r3, [r2, #AT91_DDRSDRC_MDR]
+ ldrne r3, .saved_sam9_lpr1
+ strne r3, [r2, #AT91_DDRSDRC_LPR]
+
+ b sr_dis_exit
+
+sdramc_exit_sf:
+ /* SDRAMC Memory controller */
+ ldr r3, .saved_sam9_lpr
+ str r3, [r2, #AT91_SDRAMC_LPR]
+
+sr_dis_exit:
+.endm
+#endif
.macro at91_pm_ulp0_mode
ldr pmc, .pmc_base
@@ -176,7 +467,9 @@ ENDPROC(at91_backup_mode)
bic tmp1, tmp1, #AT91_PMC_PRES
orr tmp1, tmp1, #AT91_PMC_PRES_64
str tmp1, [pmc, tmp3]
- wait_mckrdy
+
+ mov tmp3, #0
+ wait_mckrdy tmp3
b 1f
0:
@@ -212,10 +505,13 @@ ENDPROC(at91_backup_mode)
bne 5f
/* Set lowest prescaler for fast resume. */
+ ldr tmp3, .mckr_offset
ldr tmp1, [pmc, tmp3]
bic tmp1, tmp1, #AT91_PMC_PRES
str tmp1, [pmc, tmp3]
- wait_mckrdy
+
+ mov tmp3, #0
+ wait_mckrdy tmp3
b 6f
5: /* Restore RC oscillator state */
@@ -252,6 +548,7 @@ ENDPROC(at91_backup_mode)
.macro at91_pm_ulp1_mode
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
+ mov tmp3, #0
/* Save RC oscillator state and check if it is enabled. */
ldr tmp1, [pmc, #AT91_PMC_SR]
@@ -293,7 +590,7 @@ ENDPROC(at91_backup_mode)
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
- wait_mckrdy
+ wait_mckrdy tmp3
/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -306,7 +603,7 @@ ENDPROC(at91_backup_mode)
nop
nop
- wait_mckrdy
+ wait_mckrdy tmp3
/* Enable the crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -322,7 +619,7 @@ ENDPROC(at91_backup_mode)
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
- wait_mckrdy
+ wait_mckrdy tmp3
/* Switch main clock source to crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@@ -339,7 +636,7 @@ ENDPROC(at91_backup_mode)
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
- wait_mckrdy
+ wait_mckrdy tmp3
/* Restore RC oscillator state */
ldr tmp1, .saved_osc_status
@@ -367,7 +664,7 @@ ENDPROC(at91_backup_mode)
cmp tmp1, #AT91_PMC_V1
beq 1f
-#ifdef CONFIG_SOC_SAM9X60
+#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* Save PLLA settings. */
ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
@@ -434,7 +731,7 @@ ENDPROC(at91_backup_mode)
cmp tmp3, #AT91_PMC_V1
beq 4f
-#ifdef CONFIG_SOC_SAM9X60
+#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* step 1. */
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
@@ -497,7 +794,122 @@ ENDPROC(at91_backup_mode)
2:
.endm
-ENTRY(at91_ulp_mode)
+/**
+ * at91_mckx_ps_enable: save MCK1..4 settings and switch it to main clock
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_mckx_ps_enable
+#ifdef CONFIG_SOC_SAMA7
+ ldr pmc, .pmc_base
+
+ /* There are 4 MCKs we need to handle: MCK1..4 */
+ mov tmp1, #1
+e_loop: cmp tmp1, #5
+ beq e_done
+
+ /* Write MCK ID to retrieve the settings. */
+ str tmp1, [pmc, #AT91_PMC_MCR_V2]
+ ldr tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+e_save_mck1:
+ cmp tmp1, #1
+ bne e_save_mck2
+ str tmp2, .saved_mck1
+ b e_ps
+
+e_save_mck2:
+ cmp tmp1, #2
+ bne e_save_mck3
+ str tmp2, .saved_mck2
+ b e_ps
+
+e_save_mck3:
+ cmp tmp1, #3
+ bne e_save_mck4
+ str tmp2, .saved_mck3
+ b e_ps
+
+e_save_mck4:
+ str tmp2, .saved_mck4
+
+e_ps:
+ /* Use CSS=MAINCK and DIV=1. */
+ bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS
+ bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV
+ orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MAINCK
+ orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV1
+ str tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+ wait_mckrdy tmp1
+
+ add tmp1, tmp1, #1
+ b e_loop
+
+e_done:
+#endif
+.endm
+
+/**
+ * at91_mckx_ps_restore: restore MCK1..4 settings
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_mckx_ps_restore
+#ifdef CONFIG_SOC_SAMA7
+ ldr pmc, .pmc_base
+
+ /* There are 4 MCKs we need to handle: MCK1..4 */
+ mov tmp1, #1
+r_loop: cmp tmp1, #5
+ beq r_done
+
+r_save_mck1:
+ cmp tmp1, #1
+ bne r_save_mck2
+ ldr tmp2, .saved_mck1
+ b r_ps
+
+r_save_mck2:
+ cmp tmp1, #2
+ bne r_save_mck3
+ ldr tmp2, .saved_mck2
+ b r_ps
+
+r_save_mck3:
+ cmp tmp1, #3
+ bne r_save_mck4
+ ldr tmp2, .saved_mck3
+ b r_ps
+
+r_save_mck4:
+ ldr tmp2, .saved_mck4
+
+r_ps:
+ /* Write MCK ID to retrieve the settings. */
+ str tmp1, [pmc, #AT91_PMC_MCR_V2]
+ ldr tmp3, [pmc, #AT91_PMC_MCR_V2]
+
+ /* We need to restore CSS and DIV. */
+ bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS
+ bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV
+ orr tmp3, tmp3, tmp2
+ bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MSK
+ orr tmp3, tmp3, tmp1
+ orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
+ str tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+ wait_mckrdy tmp1
+
+ add tmp1, tmp1, #1
+ b r_loop
+r_done:
+#endif
+.endm
+
+.macro at91_ulp_mode
+ at91_mckx_ps_enable
+
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp3, .pm_mode
@@ -518,10 +930,15 @@ ENTRY(at91_ulp_mode)
save_mck:
str tmp1, [pmc, tmp2]
- wait_mckrdy
+ mov tmp3, #0
+ wait_mckrdy tmp3
at91_plla_disable
+ /* Enable low power mode for 2.5V regulator. */
+ at91_2_5V_reg_set_low_power 1
+
+ ldr tmp3, .pm_mode
cmp tmp3, #AT91_PM_ULP1
beq ulp1_mode
@@ -533,6 +950,9 @@ ulp1_mode:
b ulp_exit
ulp_exit:
+ /* Disable low power mode for 2.5V regulator. */
+ at91_2_5V_reg_set_low_power 0
+
ldr pmc, .pmc_base
at91_plla_enable
@@ -544,135 +964,110 @@ ulp_exit:
ldr tmp2, .saved_mckr
str tmp2, [pmc, tmp1]
- wait_mckrdy
-
- mov pc, lr
-ENDPROC(at91_ulp_mode)
+ mov tmp3, #0
+ wait_mckrdy tmp3
-/*
- * void at91_sramc_self_refresh(unsigned int is_active)
- *
- * @input param:
- * @r0: 1 - active self-refresh mode
- * 0 - exit self-refresh mode
- * register usage:
- * @r1: memory type
- * @r2: base address of the sram controller
- */
-
-ENTRY(at91_sramc_self_refresh)
- ldr r1, .memtype
- ldr r2, .sramc_base
-
- cmp r1, #AT91_MEMCTRL_MC
- bne ddrc_sf
-
- /*
- * at91rm9200 Memory controller
- */
-
- /*
- * For exiting the self-refresh mode, do nothing,
- * automatically exit the self-refresh mode.
- */
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq exit_sramc_sf
-
- /* Active SDRAM self-refresh mode */
- mov r3, #1
- str r3, [r2, #AT91_MC_SDRAMC_SRR]
- b exit_sramc_sf
+ at91_mckx_ps_restore
+.endm
-ddrc_sf:
- cmp r1, #AT91_MEMCTRL_DDRSDR
- bne sdramc_sf
+.macro at91_backup_mode
+ /* Switch the master clock source to slow clock. */
+ ldr pmc, .pmc_base
+ ldr tmp2, .mckr_offset
+ ldr tmp1, [pmc, tmp2]
+ bic tmp1, tmp1, #AT91_PMC_CSS
+ str tmp1, [pmc, tmp2]
- /*
- * DDR Memory controller
- */
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq ddrc_exit_sf
+ mov tmp3, #0
+ wait_mckrdy tmp3
- /* LPDDR1 --> force DDR2 mode during self-refresh */
- ldr r3, [r2, #AT91_DDRSDRC_MDR]
- str r3, .saved_sam9_mdr
- bic r3, r3, #~AT91_DDRSDRC_MD
- cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
- ldreq r3, [r2, #AT91_DDRSDRC_MDR]
- biceq r3, r3, #AT91_DDRSDRC_MD
- orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
- streq r3, [r2, #AT91_DDRSDRC_MDR]
+ /*BUMEN*/
+ ldr r0, .sfrbu
+ mov tmp1, #0x1
+ str tmp1, [r0, #0x10]
- /* Active DDRC self-refresh mode */
- ldr r3, [r2, #AT91_DDRSDRC_LPR]
- str r3, .saved_sam9_lpr
- bic r3, r3, #AT91_DDRSDRC_LPCB
- orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
- str r3, [r2, #AT91_DDRSDRC_LPR]
+ /* Wait for it. */
+1: ldr tmp1, [r0, #0x10]
+ tst tmp1, #0x1
+ beq 1b
- /* If using the 2nd ddr controller */
- ldr r2, .sramc1_base
- cmp r2, #0
- beq no_2nd_ddrc
+ /* Shutdown */
+ ldr r0, .shdwc
+ mov tmp1, #0xA5000000
+ add tmp1, tmp1, #0x1
+ at91_backup_set_lpm tmp1
+ str tmp1, [r0, #0]
+.endm
- ldr r3, [r2, #AT91_DDRSDRC_MDR]
- str r3, .saved_sam9_mdr1
- bic r3, r3, #~AT91_DDRSDRC_MD
- cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
- ldreq r3, [r2, #AT91_DDRSDRC_MDR]
- biceq r3, r3, #AT91_DDRSDRC_MD
- orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
- streq r3, [r2, #AT91_DDRSDRC_MDR]
+/*
+ * void at91_suspend_sram_fn(struct at91_pm_data*)
+ * @input param:
+ * @r0: base address of struct at91_pm_data
+ */
+/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
+ .align 3
+ENTRY(at91_pm_suspend_in_sram)
+ /* Save registers on stack */
+ stmfd sp!, {r4 - r12, lr}
- /* Active DDRC self-refresh mode */
- ldr r3, [r2, #AT91_DDRSDRC_LPR]
- str r3, .saved_sam9_lpr1
- bic r3, r3, #AT91_DDRSDRC_LPCB
- orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
- str r3, [r2, #AT91_DDRSDRC_LPR]
+ /* Drain write buffer */
+ mov tmp1, #0
+ mcr p15, 0, tmp1, c7, c10, 4
-no_2nd_ddrc:
- b exit_sramc_sf
+ ldr tmp1, [r0, #PM_DATA_PMC]
+ str tmp1, .pmc_base
+ ldr tmp1, [r0, #PM_DATA_RAMC0]
+ str tmp1, .sramc_base
+ ldr tmp1, [r0, #PM_DATA_RAMC1]
+ str tmp1, .sramc1_base
+ ldr tmp1, [r0, #PM_DATA_RAMC_PHY]
+ str tmp1, .sramc_phy_base
+ ldr tmp1, [r0, #PM_DATA_MEMCTRL]
+ str tmp1, .memtype
+ ldr tmp1, [r0, #PM_DATA_MODE]
+ str tmp1, .pm_mode
+ ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
+ str tmp1, .mckr_offset
+ ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
+ str tmp1, .pmc_version
+ /* Both ldrne below are here to preload their address in the TLB */
+ ldr tmp1, [r0, #PM_DATA_SHDWC]
+ str tmp1, .shdwc
+ cmp tmp1, #0
+ ldrne tmp2, [tmp1, #0]
+ ldr tmp1, [r0, #PM_DATA_SFRBU]
+ str tmp1, .sfrbu
+ cmp tmp1, #0
+ ldrne tmp2, [tmp1, #0x10]
-ddrc_exit_sf:
- /* Restore MDR in case of LPDDR1 */
- ldr r3, .saved_sam9_mdr
- str r3, [r2, #AT91_DDRSDRC_MDR]
- /* Restore LPR on AT91 with DDRAM */
- ldr r3, .saved_sam9_lpr
- str r3, [r2, #AT91_DDRSDRC_LPR]
+ /* Active the self-refresh mode */
+ at91_sramc_self_refresh_ena
- /* If using the 2nd ddr controller */
- ldr r2, .sramc1_base
- cmp r2, #0
- ldrne r3, .saved_sam9_mdr1
- strne r3, [r2, #AT91_DDRSDRC_MDR]
- ldrne r3, .saved_sam9_lpr1
- strne r3, [r2, #AT91_DDRSDRC_LPR]
+ ldr r0, .pm_mode
+ cmp r0, #AT91_PM_STANDBY
+ beq standby
+ cmp r0, #AT91_PM_BACKUP
+ beq backup_mode
- b exit_sramc_sf
+ at91_ulp_mode
+ b exit_suspend
- /*
- * SDRAMC Memory controller
- */
-sdramc_sf:
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq sdramc_exit_sf
+standby:
+ /* Wait for interrupt */
+ ldr pmc, .pmc_base
+ at91_cpu_idle
+ b exit_suspend
- /* Active SDRAMC self-refresh mode */
- ldr r3, [r2, #AT91_SDRAMC_LPR]
- str r3, .saved_sam9_lpr
- bic r3, r3, #AT91_SDRAMC_LPCB
- orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
- str r3, [r2, #AT91_SDRAMC_LPR]
+backup_mode:
+ at91_backup_mode
-sdramc_exit_sf:
- ldr r3, .saved_sam9_lpr
- str r3, [r2, #AT91_SDRAMC_LPR]
+exit_suspend:
+ /* Exit the self-refresh mode */
+ at91_sramc_self_refresh_dis
-exit_sramc_sf:
- mov pc, lr
-ENDPROC(at91_sramc_self_refresh)
+ /* Restore registers, and return */
+ ldmfd sp!, {r4 - r12, pc}
+ENDPROC(at91_pm_suspend_in_sram)
.pmc_base:
.word 0
@@ -680,6 +1075,8 @@ ENDPROC(at91_sramc_self_refresh)
.word 0
.sramc1_base:
.word 0
+.sramc_phy_base:
+ .word 0
.shdwc:
.word 0
.sfrbu:
@@ -706,6 +1103,16 @@ ENDPROC(at91_sramc_self_refresh)
.word 0
.saved_osc_status:
.word 0
+#ifdef CONFIG_SOC_SAMA7
+.saved_mck1:
+ .word 0
+.saved_mck2:
+ .word 0
+.saved_mck3:
+ .word 0
+.saved_mck4:
+ .word 0
+#endif
ENTRY(at91_pm_suspend_in_sram_sz)
.word .-at91_pm_suspend_in_sram
diff --git a/arch/arm/mach-at91/sama7.c b/arch/arm/mach-at91/sama7.c
new file mode 100644
index 000000000000..bd43733ede18
--- /dev/null
+++ b/arch/arm/mach-at91/sama7.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Setup code for SAMA7
+ *
+ * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
+ *
+ */
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/system_misc.h>
+
+#include "generic.h"
+
+static void __init sama7_dt_device_init(void)
+{
+ of_platform_default_populate(NULL, NULL, NULL);
+ sama7_pm_init();
+}
+
+static const char *const sama7_dt_board_compat[] __initconst = {
+ "microchip,sama7",
+ NULL
+};
+
+DT_MACHINE_START(sama7_dt, "Microchip SAMA7")
+ /* Maintainer: Microchip */
+ .init_machine = sama7_dt_device_init,
+ .dt_compat = sama7_dt_board_compat,
+MACHINE_END
+
diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c
index 43a16f922b53..43829e49ad93 100644
--- a/arch/arm/mach-bcm/bcm_kona_smc.c
+++ b/arch/arm/mach-bcm/bcm_kona_smc.c
@@ -10,8 +10,6 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
-#include <stdarg.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <linux/ioport.h>
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index f2db5fd38145..15c68a646d51 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -9,11 +9,6 @@ config EP93XX_SOC_COMMON
select SOC_BUS
select LEDS_GPIO_REGISTER
-config CRUNCH
- bool "Support for MaverickCrunch"
- help
- Enable kernel support for MaverickCrunch.
-
comment "EP93xx Platforms"
config MACH_ADSSPHERE
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 86768495f61d..cfad517fac46 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -6,9 +6,6 @@ obj-y := core.o clock.o timer-ep93xx.o
obj-$(CONFIG_EP93XX_DMA) += dma.o
-obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
-AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
-
obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o
obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o
diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c
index 57cfd8ebe04f..8d5e349a7a6d 100644
--- a/arch/arm/mach-ep93xx/adssphere.c
+++ b/arch/arm/mach-ep93xx/adssphere.c
@@ -36,6 +36,5 @@ MACHINE_START(ADSSPHERE, "ADS Sphere board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = adssphere_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 6fb19a393fd2..4659132a0509 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -1004,8 +1004,3 @@ void ep93xx_restart(enum reboot_mode mode, const char *cmd)
while (1)
;
}
-
-void __init ep93xx_init_late(void)
-{
- crunch_init();
-}
diff --git a/arch/arm/mach-ep93xx/crunch-bits.S b/arch/arm/mach-ep93xx/crunch-bits.S
deleted file mode 100644
index fb2dbf76f09e..000000000000
--- a/arch/arm/mach-ep93xx/crunch-bits.S
+++ /dev/null
@@ -1,310 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/kernel/crunch-bits.S
- * Cirrus MaverickCrunch context switching and handling
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- *
- * Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is
- * Copyright (c) 2003-2004, MontaVista Software, Inc.
- */
-
-#include <linux/linkage.h>
-#include <asm/ptrace.h>
-#include <asm/thread_info.h>
-#include <asm/asm-offsets.h>
-#include <asm/assembler.h>
-#include <mach/ep93xx-regs.h>
-
-/*
- * We can't use hex constants here due to a bug in gas.
- */
-#define CRUNCH_MVDX0 0
-#define CRUNCH_MVDX1 8
-#define CRUNCH_MVDX2 16
-#define CRUNCH_MVDX3 24
-#define CRUNCH_MVDX4 32
-#define CRUNCH_MVDX5 40
-#define CRUNCH_MVDX6 48
-#define CRUNCH_MVDX7 56
-#define CRUNCH_MVDX8 64
-#define CRUNCH_MVDX9 72
-#define CRUNCH_MVDX10 80
-#define CRUNCH_MVDX11 88
-#define CRUNCH_MVDX12 96
-#define CRUNCH_MVDX13 104
-#define CRUNCH_MVDX14 112
-#define CRUNCH_MVDX15 120
-#define CRUNCH_MVAX0L 128
-#define CRUNCH_MVAX0M 132
-#define CRUNCH_MVAX0H 136
-#define CRUNCH_MVAX1L 140
-#define CRUNCH_MVAX1M 144
-#define CRUNCH_MVAX1H 148
-#define CRUNCH_MVAX2L 152
-#define CRUNCH_MVAX2M 156
-#define CRUNCH_MVAX2H 160
-#define CRUNCH_MVAX3L 164
-#define CRUNCH_MVAX3M 168
-#define CRUNCH_MVAX3H 172
-#define CRUNCH_DSPSC 176
-
-#define CRUNCH_SIZE 184
-
- .text
-
-/*
- * Lazy switching of crunch coprocessor context
- *
- * r10 = struct thread_info pointer
- * r9 = ret_from_exception
- * lr = undefined instr exit
- *
- * called from prefetch exception handler with interrupts enabled
- */
-ENTRY(crunch_task_enable)
- inc_preempt_count r10, r3
-
- ldr r8, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr
-
- ldr r1, [r8, #0x80]
- tst r1, #0x00800000 @ access to crunch enabled?
- bne 2f @ if so no business here
- mov r3, #0xaa @ unlock syscon swlock
- str r3, [r8, #0xc0]
- orr r1, r1, #0x00800000 @ enable access to crunch
- str r1, [r8, #0x80]
-
- ldr r3, =crunch_owner
- add r0, r10, #TI_CRUNCH_STATE @ get task crunch save area
- ldr r2, [sp, #60] @ current task pc value
- ldr r1, [r3] @ get current crunch owner
- str r0, [r3] @ this task now owns crunch
- sub r2, r2, #4 @ adjust pc back
- str r2, [sp, #60]
-
- ldr r2, [r8, #0x80]
- mov r2, r2 @ flush out enable (@@@)
-
- teq r1, #0 @ test for last ownership
- mov lr, r9 @ normal exit from exception
- beq crunch_load @ no owner, skip save
-
-crunch_save:
- cfstr64 mvdx0, [r1, #CRUNCH_MVDX0] @ save 64b registers
- cfstr64 mvdx1, [r1, #CRUNCH_MVDX1]
- cfstr64 mvdx2, [r1, #CRUNCH_MVDX2]
- cfstr64 mvdx3, [r1, #CRUNCH_MVDX3]
- cfstr64 mvdx4, [r1, #CRUNCH_MVDX4]
- cfstr64 mvdx5, [r1, #CRUNCH_MVDX5]
- cfstr64 mvdx6, [r1, #CRUNCH_MVDX6]
- cfstr64 mvdx7, [r1, #CRUNCH_MVDX7]
- cfstr64 mvdx8, [r1, #CRUNCH_MVDX8]
- cfstr64 mvdx9, [r1, #CRUNCH_MVDX9]
- cfstr64 mvdx10, [r1, #CRUNCH_MVDX10]
- cfstr64 mvdx11, [r1, #CRUNCH_MVDX11]
- cfstr64 mvdx12, [r1, #CRUNCH_MVDX12]
- cfstr64 mvdx13, [r1, #CRUNCH_MVDX13]
- cfstr64 mvdx14, [r1, #CRUNCH_MVDX14]
- cfstr64 mvdx15, [r1, #CRUNCH_MVDX15]
-
-#ifdef __ARMEB__
-#error fix me for ARMEB
-#endif
-
- cfmv32al mvfx0, mvax0 @ save 72b accumulators
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX0L]
- cfmv32am mvfx0, mvax0
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX0M]
- cfmv32ah mvfx0, mvax0
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX0H]
- cfmv32al mvfx0, mvax1
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX1L]
- cfmv32am mvfx0, mvax1
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX1M]
- cfmv32ah mvfx0, mvax1
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX1H]
- cfmv32al mvfx0, mvax2
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX2L]
- cfmv32am mvfx0, mvax2
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX2M]
- cfmv32ah mvfx0, mvax2
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX2H]
- cfmv32al mvfx0, mvax3
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX3L]
- cfmv32am mvfx0, mvax3
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX3M]
- cfmv32ah mvfx0, mvax3
- cfstr32 mvfx0, [r1, #CRUNCH_MVAX3H]
-
- cfmv32sc mvdx0, dspsc @ save status word
- cfstr64 mvdx0, [r1, #CRUNCH_DSPSC]
-
- teq r0, #0 @ anything to load?
- cfldr64eq mvdx0, [r1, #CRUNCH_MVDX0] @ mvdx0 was clobbered
- beq 1f
-
-crunch_load:
- cfldr64 mvdx0, [r0, #CRUNCH_DSPSC] @ load status word
- cfmvsc32 dspsc, mvdx0
-
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX0L] @ load 72b accumulators
- cfmval32 mvax0, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX0M]
- cfmvam32 mvax0, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX0H]
- cfmvah32 mvax0, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX1L]
- cfmval32 mvax1, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX1M]
- cfmvam32 mvax1, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX1H]
- cfmvah32 mvax1, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX2L]
- cfmval32 mvax2, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX2M]
- cfmvam32 mvax2, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX2H]
- cfmvah32 mvax2, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX3L]
- cfmval32 mvax3, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX3M]
- cfmvam32 mvax3, mvfx0
- cfldr32 mvfx0, [r0, #CRUNCH_MVAX3H]
- cfmvah32 mvax3, mvfx0
-
- cfldr64 mvdx0, [r0, #CRUNCH_MVDX0] @ load 64b registers
- cfldr64 mvdx1, [r0, #CRUNCH_MVDX1]
- cfldr64 mvdx2, [r0, #CRUNCH_MVDX2]
- cfldr64 mvdx3, [r0, #CRUNCH_MVDX3]
- cfldr64 mvdx4, [r0, #CRUNCH_MVDX4]
- cfldr64 mvdx5, [r0, #CRUNCH_MVDX5]
- cfldr64 mvdx6, [r0, #CRUNCH_MVDX6]
- cfldr64 mvdx7, [r0, #CRUNCH_MVDX7]
- cfldr64 mvdx8, [r0, #CRUNCH_MVDX8]
- cfldr64 mvdx9, [r0, #CRUNCH_MVDX9]
- cfldr64 mvdx10, [r0, #CRUNCH_MVDX10]
- cfldr64 mvdx11, [r0, #CRUNCH_MVDX11]
- cfldr64 mvdx12, [r0, #CRUNCH_MVDX12]
- cfldr64 mvdx13, [r0, #CRUNCH_MVDX13]
- cfldr64 mvdx14, [r0, #CRUNCH_MVDX14]
- cfldr64 mvdx15, [r0, #CRUNCH_MVDX15]
-
-1:
-#ifdef CONFIG_PREEMPT_COUNT
- get_thread_info r10
-#endif
-2: dec_preempt_count r10, r3
- ret lr
-
-/*
- * Back up crunch regs to save area and disable access to them
- * (mainly for gdb or sleep mode usage)
- *
- * r0 = struct thread_info pointer of target task or NULL for any
- */
-ENTRY(crunch_task_disable)
- stmfd sp!, {r4, r5, lr}
-
- mrs ip, cpsr
- orr r2, ip, #PSR_I_BIT @ disable interrupts
- msr cpsr_c, r2
-
- ldr r4, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr
-
- ldr r3, =crunch_owner
- add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
- ldr r1, [r3] @ get current crunch owner
- teq r1, #0 @ any current owner?
- beq 1f @ no: quit
- teq r0, #0 @ any owner?
- teqne r1, r2 @ or specified one?
- bne 1f @ no: quit
-
- ldr r5, [r4, #0x80] @ enable access to crunch
- mov r2, #0xaa
- str r2, [r4, #0xc0]
- orr r5, r5, #0x00800000
- str r5, [r4, #0x80]
-
- mov r0, #0 @ nothing to load
- str r0, [r3] @ no more current owner
- ldr r2, [r4, #0x80] @ flush out enable (@@@)
- mov r2, r2
- bl crunch_save
-
- mov r2, #0xaa @ disable access to crunch
- str r2, [r4, #0xc0]
- bic r5, r5, #0x00800000
- str r5, [r4, #0x80]
- ldr r5, [r4, #0x80] @ flush out enable (@@@)
- mov r5, r5
-
-1: msr cpsr_c, ip @ restore interrupt mode
- ldmfd sp!, {r4, r5, pc}
-
-/*
- * Copy crunch state to given memory address
- *
- * r0 = struct thread_info pointer of target task
- * r1 = memory address where to store crunch state
- *
- * this is called mainly in the creation of signal stack frames
- */
-ENTRY(crunch_task_copy)
- mrs ip, cpsr
- orr r2, ip, #PSR_I_BIT @ disable interrupts
- msr cpsr_c, r2
-
- ldr r3, =crunch_owner
- add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
- ldr r3, [r3] @ get current crunch owner
- teq r2, r3 @ does this task own it...
- beq 1f
-
- @ current crunch values are in the task save area
- msr cpsr_c, ip @ restore interrupt mode
- mov r0, r1
- mov r1, r2
- mov r2, #CRUNCH_SIZE
- b memcpy
-
-1: @ this task owns crunch regs -- grab a copy from there
- mov r0, #0 @ nothing to load
- mov r3, lr @ preserve return address
- bl crunch_save
- msr cpsr_c, ip @ restore interrupt mode
- ret r3
-
-/*
- * Restore crunch state from given memory address
- *
- * r0 = struct thread_info pointer of target task
- * r1 = memory address where to get crunch state from
- *
- * this is used to restore crunch state when unwinding a signal stack frame
- */
-ENTRY(crunch_task_restore)
- mrs ip, cpsr
- orr r2, ip, #PSR_I_BIT @ disable interrupts
- msr cpsr_c, r2
-
- ldr r3, =crunch_owner
- add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
- ldr r3, [r3] @ get current crunch owner
- teq r2, r3 @ does this task own it...
- beq 1f
-
- @ this task doesn't own crunch regs -- use its save area
- msr cpsr_c, ip @ restore interrupt mode
- mov r0, r2
- mov r2, #CRUNCH_SIZE
- b memcpy
-
-1: @ this task owns crunch regs -- load them directly
- mov r0, r1
- mov r1, #0 @ nothing to save
- mov r3, lr @ preserve return address
- bl crunch_load
- msr cpsr_c, ip @ restore interrupt mode
- ret r3
diff --git a/arch/arm/mach-ep93xx/crunch.c b/arch/arm/mach-ep93xx/crunch.c
deleted file mode 100644
index 757032d82f63..000000000000
--- a/arch/arm/mach-ep93xx/crunch.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/kernel/crunch.c
- * Cirrus MaverickCrunch context switching and handling
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <asm/thread_notify.h>
-
-#include "soc.h"
-
-struct crunch_state *crunch_owner;
-
-void crunch_task_release(struct thread_info *thread)
-{
- local_irq_disable();
- if (crunch_owner == &thread->crunchstate)
- crunch_owner = NULL;
- local_irq_enable();
-}
-
-static int crunch_enabled(u32 devcfg)
-{
- return !!(devcfg & EP93XX_SYSCON_DEVCFG_CPENA);
-}
-
-static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t)
-{
- struct thread_info *thread = (struct thread_info *)t;
- struct crunch_state *crunch_state;
- u32 devcfg;
-
- crunch_state = &thread->crunchstate;
-
- switch (cmd) {
- case THREAD_NOTIFY_FLUSH:
- memset(crunch_state, 0, sizeof(*crunch_state));
-
- /*
- * FALLTHROUGH: Ensure we don't try to overwrite our newly
- * initialised state information on the first fault.
- */
- fallthrough;
-
- case THREAD_NOTIFY_EXIT:
- crunch_task_release(thread);
- break;
-
- case THREAD_NOTIFY_SWITCH:
- devcfg = __raw_readl(EP93XX_SYSCON_DEVCFG);
- if (crunch_enabled(devcfg) || crunch_owner == crunch_state) {
- /*
- * We don't use ep93xx_syscon_swlocked_write() here
- * because we are on the context switch path and
- * preemption is already disabled.
- */
- devcfg ^= EP93XX_SYSCON_DEVCFG_CPENA;
- __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
- __raw_writel(devcfg, EP93XX_SYSCON_DEVCFG);
- }
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block crunch_notifier_block = {
- .notifier_call = crunch_do,
-};
-
-int __init crunch_init(void)
-{
- thread_register_notifier(&crunch_notifier_block);
- elf_hwcap |= HWCAP_CRUNCH;
-
- return 0;
-}
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 7b7280c21ee0..af0e22471ebd 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -247,7 +247,6 @@ MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = edb93xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -260,7 +259,6 @@ MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = edb93xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -273,7 +271,6 @@ MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = edb93xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -286,7 +283,6 @@ MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = edb93xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -299,7 +295,6 @@ MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = edb93xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -312,7 +307,6 @@ MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = edb93xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -325,7 +319,6 @@ MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = edb93xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -338,7 +331,6 @@ MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = edb93xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
index 8905db1edd5a..d7f9890321eb 100644
--- a/arch/arm/mach-ep93xx/gesbc9312.c
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -36,6 +36,5 @@ MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = gesbc9312_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
index b18ebf26da45..e6ead8ded6ee 100644
--- a/arch/arm/mach-ep93xx/micro9.c
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -80,7 +80,6 @@ MACHINE_START(MICRO9, "Contec Micro9-High")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = micro9_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -93,7 +92,6 @@ MACHINE_START(MICRO9M, "Contec Micro9-Mid")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = micro9_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -106,7 +104,6 @@ MACHINE_START(MICRO9L, "Contec Micro9-Lite")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = micro9_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
@@ -119,7 +116,6 @@ MACHINE_START(MICRO9S, "Contec Micro9-Slim")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = micro9_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
#endif
diff --git a/arch/arm/mach-ep93xx/platform.h b/arch/arm/mach-ep93xx/platform.h
index b4045a186239..5fb1b919133f 100644
--- a/arch/arm/mach-ep93xx/platform.h
+++ b/arch/arm/mach-ep93xx/platform.h
@@ -38,12 +38,5 @@ struct device *ep93xx_init_devices(void);
extern void ep93xx_timer_init(void);
void ep93xx_restart(enum reboot_mode, const char *);
-void ep93xx_init_late(void);
-
-#ifdef CONFIG_CRUNCH
-int crunch_init(void);
-#else
-static inline int crunch_init(void) { return 0; }
-#endif
#endif
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index 8a53b74dc4b2..5291053023b2 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -123,6 +123,5 @@ MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = simone_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index 703f25f19d51..e200d69471e9 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -157,6 +157,5 @@ MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = snappercl15_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index e0e1b11032f1..12eff8c8074d 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -354,7 +354,6 @@ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = ts72xx_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
@@ -418,6 +417,5 @@ MACHINE_START(BK3, "Liebherr controller BK3.1")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = bk3_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
index cbcba3136d74..e46281e60bf7 100644
--- a/arch/arm/mach-ep93xx/vision_ep9307.c
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -306,6 +306,5 @@ MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
.init_irq = ep93xx_init_irq,
.init_time = ep93xx_timer_init,
.init_machine = vision_init_machine,
- .init_late = ep93xx_init_late,
.restart = ep93xx_restart,
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 34a1c7742088..365a5853d310 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -17,39 +17,6 @@ config MACH_IXP4XX_OF
help
Say 'Y' here to support Device Tree-based IXP4xx platforms.
-config MACH_NSLU2
- bool
- prompt "Linksys NSLU2"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support Linksys's
- NSLU2 NAS device. For more information on this platform,
- see http://www.nslu2-linux.org
-
-config MACH_AVILA
- bool "Avila"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support the Gateworks
- Avila Network Platform. For more information on this platform,
- see <file:Documentation/arm/ixp4xx.rst>.
-
-config MACH_LOFT
- bool "Loft"
- depends on MACH_AVILA
- help
- Say 'Y' here if you want your kernel to support the Giant
- Shoulder Inc Loft board (a minor variation on the standard
- Gateworks Avila Network Platform).
-
-config ARCH_ADI_COYOTE
- bool "Coyote"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support the ADI
- Engineering Coyote Gateway Reference Platform. For more
- information on this platform, see <file:Documentation/arm/ixp4xx.rst>.
-
config MACH_GATEWAY7001
bool "Gateway 7001"
depends on IXP4XX_PCI_LEGACY
@@ -58,37 +25,6 @@ config MACH_GATEWAY7001
7001 Access Point. For more information on this platform,
see http://openwrt.org
-config MACH_WG302V2
- bool "Netgear WG302 v2 / WAG302 v2"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support Netgear's
- WG302 v2 or WAG302 v2 Access Points. For more information
- on this platform, see http://openwrt.org
-
-config ARCH_IXDP425
- bool "IXDP425"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support Intel's
- IXDP425 Development Platform (Also known as Richfield).
- For more information on this platform, see <file:Documentation/arm/ixp4xx.rst>.
-
-config MACH_IXDPG425
- bool "IXDPG425"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support Intel's
- IXDPG425 Development Platform (Also known as Montajade).
- For more information on this platform, see <file:Documentation/arm/ixp4xx.rst>.
-
-config MACH_IXDP465
- bool "IXDP465"
- help
- Say 'Y' here if you want your kernel to support Intel's
- IXDP465 Development Platform (Also known as BMP).
- For more information on this platform, see <file:Documentation/arm/ixp4xx.rst>.
-
config MACH_GORAMO_MLR
bool "GORAMO Multi Link Router"
depends on IXP4XX_PCI_LEGACY
@@ -96,23 +32,6 @@ config MACH_GORAMO_MLR
Say 'Y' here if you want your kernel to support GORAMO
MultiLink router.
-config MACH_KIXRP435
- bool "KIXRP435"
- help
- Say 'Y' here if you want your kernel to support Intel's
- KIXRP435 Reference Platform.
- For more information on this platform, see <file:Documentation/arm/ixp4xx.rst>.
-
-#
-# IXCDP1100 is the exact same HW as IXDP425, but with a different machine
-# number from the bootloader due to marketing monkeys, so we just enable it
-# by default if IXDP425 is enabled.
-#
-config ARCH_IXCDP1100
- bool
- depends on ARCH_IXDP425
- default y
-
config ARCH_PRPMC1100
bool "PrPMC1100"
help
@@ -120,46 +39,6 @@ config ARCH_PRPMC1100
PrPCM1100 Processor Mezanine Module. For more information on
this platform, see <file:Documentation/arm/ixp4xx.rst>.
-config MACH_NAS100D
- bool
- prompt "NAS100D"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support Iomega's
- NAS 100d device. For more information on this platform,
- see http://www.nslu2-linux.org/wiki/NAS100d/HomePage
-
-config MACH_DSMG600
- bool
- prompt "D-Link DSM-G600 RevA"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support D-Link's
- DSM-G600 RevA device. For more information on this platform,
- see http://www.nslu2-linux.org/wiki/DSMG600/HomePage
-
-config ARCH_IXDP4XX
- bool
- depends on ARCH_IXDP425 || MACH_IXDP465 || MACH_KIXRP435
- default y
-
-config MACH_FSG
- bool
- prompt "Freecom FSG-3"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support Freecom's
- FSG-3 device. For more information on this platform,
- see http://www.nslu2-linux.org/wiki/FSG3/HomePage
-
-config MACH_ARCOM_VULCAN
- bool
- prompt "Arcom/Eurotech Vulcan"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support Arcom's
- Vulcan board.
-
#
# Certain registers and IRQs are only enabled if supporting IXP465 CPUs
#
@@ -173,43 +52,6 @@ config CPU_IXP43X
depends on MACH_KIXRP435
default y
-config MACH_GTWX5715
- bool "Gemtek WX5715 (Linksys WRV54G)"
- depends on ARCH_IXP4XX
- depends on IXP4XX_PCI_LEGACY
- help
- This board is currently inside the Linksys WRV54G Gateways.
-
- IXP425 - 266mhz
- 32mb SDRAM
- 8mb Flash
- miniPCI slot 0 does not have a card connector soldered to the board
- miniPCI slot 1 has an ISL3880 802.11g card (Prism54)
- npe0 is connected to a Kendin KS8995M Switch (4 ports)
- npe1 is the "wan" port
- "Console" UART is available on J11 as console
- "High Speed" UART is n/c (as far as I can tell)
- 20 Pin ARM/Xscale JTAG interface on J2
-
-config MACH_DEVIXP
- bool "Omicron DEVIXP"
- help
- Say 'Y' here if you want your kernel to support the DEVIXP
- board from OMICRON electronics GmbH.
-
-config MACH_MICCPT
- bool "Omicron MICCPT"
- depends on IXP4XX_PCI_LEGACY
- help
- Say 'Y' here if you want your kernel to support the MICCPT
- board from OMICRON electronics GmbH.
-
-config MACH_MIC256
- bool "Omicron MIC256"
- help
- Say 'Y' here if you want your kernel to support the MIC256
- board from OMICRON electronics GmbH.
-
comment "IXP4xx Options"
config IXP4XX_PCI_LEGACY
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 1fa4e6605782..b241094c9649 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -9,37 +9,11 @@ obj-pci-n :=
# Device tree platform
obj-pci-$(CONFIG_MACH_IXP4XX_OF) += ixp4xx-of.o
-obj-pci-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o
-obj-pci-$(CONFIG_MACH_AVILA) += avila-pci.o
-obj-pci-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o
-obj-pci-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o
-obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o
-obj-pci-$(CONFIG_MACH_MICCPT) += miccpt-pci.o
-obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o
-obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o
-obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o
obj-pci-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o
-obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o
-obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o
-obj-pci-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-pci.o
obj-y += common.o
-obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-setup.o
-obj-$(CONFIG_MACH_AVILA) += avila-setup.o
-obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o
-obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
-obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
-obj-$(CONFIG_MACH_DEVIXP) += omixp-setup.o
-obj-$(CONFIG_MACH_MICCPT) += omixp-setup.o
-obj-$(CONFIG_MACH_MIC256) += omixp-setup.o
-obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o
-obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o
-obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o
obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o
-obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o
-obj-$(CONFIG_MACH_FSG) += fsg-setup.o
obj-$(CONFIG_MACH_GORAMO_MLR) += goramo_mlr.o
-obj-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-setup.o
obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o
diff --git a/arch/arm/mach-ixp4xx/avila-pci.c b/arch/arm/mach-ixp4xx/avila-pci.c
deleted file mode 100644
index 2e5996a96dd3..000000000000
--- a/arch/arm/mach-ixp4xx/avila-pci.c
+++ /dev/null
@@ -1,79 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ixp4xx/avila-pci.c
- *
- * Gateworks Avila board-level PCI initialization
- *
- * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
- *
- * Based on ixdp-pci.c
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <asm/mach/pci.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-#include "irqs.h"
-
-#define AVILA_MAX_DEV 4
-#define LOFT_MAX_DEV 6
-#define IRQ_LINES 4
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define INTA 11
-#define INTB 10
-#define INTC 9
-#define INTD 8
-
-void __init avila_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init avila_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- static int pci_irq_table[IRQ_LINES] = {
- IXP4XX_GPIO_IRQ(INTA),
- IXP4XX_GPIO_IRQ(INTB),
- IXP4XX_GPIO_IRQ(INTC),
- IXP4XX_GPIO_IRQ(INTD)
- };
-
- if (slot >= 1 &&
- slot <= (machine_is_loft() ? LOFT_MAX_DEV : AVILA_MAX_DEV) &&
- pin >= 1 && pin <= IRQ_LINES)
- return pci_irq_table[(slot + pin - 2) % 4];
-
- return -1;
-}
-
-struct hw_pci avila_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = avila_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = avila_map_irq,
-};
-
-int __init avila_pci_init(void)
-{
- if (machine_is_avila() || machine_is_loft())
- pci_common_init(&avila_pci);
- return 0;
-}
-
-subsys_initcall(avila_pci_init);
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
deleted file mode 100644
index ec1d3029f80c..000000000000
--- a/arch/arm/mach-ixp4xx/avila-setup.c
+++ /dev/null
@@ -1,210 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/arm/mach-ixp4xx/avila-setup.c
- *
- * Gateworks Avila board-setup
- *
- * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
- *
- * Based on ixdp-setup.c
- * Copyright (C) 2003-2005 MontaVista Software, Inc.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-#include <linux/gpio/machine.h>
-#include <linux/platform_data/pata_ixp4xx_cf.h>
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#include "irqs.h"
-
-#define AVILA_SDA_PIN 7
-#define AVILA_SCL_PIN 6
-
-static struct flash_platform_data avila_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource avila_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device avila_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &avila_flash_data,
- },
- .num_resources = 1,
- .resource = &avila_flash_resource,
-};
-
-static struct gpiod_lookup_table avila_i2c_gpiod_table = {
- .dev_id = "i2c-gpio.0",
- .table = {
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", AVILA_SDA_PIN,
- NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", AVILA_SCL_PIN,
- NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- },
-};
-
-static struct platform_device avila_i2c_gpio = {
- .name = "i2c-gpio",
- .id = 0,
- .dev = {
- .platform_data = NULL,
- },
-};
-
-static struct resource avila_uart_resources[] = {
- {
- .start = IXP4XX_UART1_BASE_PHYS,
- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM
- },
- {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM
- }
-};
-
-static struct plat_serial8250_port avila_uart_data[] = {
- {
- .mapbase = IXP4XX_UART1_BASE_PHYS,
- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { },
-};
-
-static struct platform_device avila_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev.platform_data = avila_uart_data,
- .num_resources = 2,
- .resource = avila_uart_resources
-};
-
-static struct resource avila_pata_resources[] = {
- {
- .flags = IORESOURCE_MEM
- },
- {
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "intrq",
- .start = IRQ_IXP4XX_GPIO12,
- .end = IRQ_IXP4XX_GPIO12,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct ixp4xx_pata_data avila_pata_data = {
- .cs0_bits = 0xbfff0043,
- .cs1_bits = 0xbfff0043,
-};
-
-static struct platform_device avila_pata = {
- .name = "pata_ixp4xx_cf",
- .id = 0,
- .dev.platform_data = &avila_pata_data,
- .num_resources = ARRAY_SIZE(avila_pata_resources),
- .resource = avila_pata_resources,
-};
-
-static struct platform_device *avila_devices[] __initdata = {
- &avila_i2c_gpio,
- &avila_flash,
- &avila_uart
-};
-
-static void __init avila_init(void)
-{
- ixp4xx_sys_init();
-
- avila_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- avila_flash_resource.end =
- IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
-
- gpiod_add_lookup_table(&avila_i2c_gpiod_table);
-
- platform_add_devices(avila_devices, ARRAY_SIZE(avila_devices));
-
- avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1);
- avila_pata_resources[0].end = IXP4XX_EXP_BUS_END(1);
-
- avila_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
- avila_pata_resources[1].end = IXP4XX_EXP_BUS_END(2);
-
- avila_pata_data.cs0_cfg = IXP4XX_EXP_CS1;
- avila_pata_data.cs1_cfg = IXP4XX_EXP_CS2;
-
- platform_device_register(&avila_pata);
-
-}
-
-MACHINE_START(AVILA, "Gateworks Avila Network Platform")
- /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = avila_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
-
- /*
- * Loft is functionally equivalent to Avila except that it has a
- * different number for the maximum PCI devices. The MACHINE
- * structure below is identical to Avila except for the comment.
- */
-#ifdef CONFIG_MACH_LOFT
-MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
- /* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = avila_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
-#endif
-
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
deleted file mode 100644
index c250b59e8d47..000000000000
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ /dev/null
@@ -1,62 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ixp4xx/coyote-pci.c
- *
- * PCI setup routines for ADI Engineering Coyote platform
- *
- * Copyright (C) 2002 Jungo Software Technologies.
- * Copyright (C) 2003 MontaVista Softwrae, Inc.
- *
- * Maintainer: Deepak Saxena <dsaxena@mvista.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-
-#include "irqs.h"
-
-#define SLOT0_DEVID 14
-#define SLOT1_DEVID 15
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define SLOT0_INTA 6
-#define SLOT1_INTA 11
-
-void __init coyote_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT0_INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT1_INTA), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init coyote_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- if (slot == SLOT0_DEVID)
- return IXP4XX_GPIO_IRQ(SLOT0_INTA);
- else if (slot == SLOT1_DEVID)
- return IXP4XX_GPIO_IRQ(SLOT1_INTA);
- else return -1;
-}
-
-struct hw_pci coyote_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = coyote_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = coyote_map_irq,
-};
-
-int __init coyote_pci_init(void)
-{
- if (machine_is_adi_coyote())
- pci_common_init(&coyote_pci);
- return 0;
-}
-
-subsys_initcall(coyote_pci_init);
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
deleted file mode 100644
index 7ca43ca2816d..000000000000
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ /dev/null
@@ -1,144 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/arm/mach-ixp4xx/coyote-setup.c
- *
- * Board setup for ADI Engineering and IXDGP425 boards
- *
- * Copyright (C) 2003-2005 MontaVista Software, Inc.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#include "irqs.h"
-
-#define COYOTE_IDE_BASE_PHYS IXP4XX_EXP_BUS_BASE(3)
-#define COYOTE_IDE_BASE_VIRT 0xFFFE1000
-#define COYOTE_IDE_REGION_SIZE 0x1000
-
-#define COYOTE_IDE_DATA_PORT 0xFFFE10E0
-#define COYOTE_IDE_CTRL_PORT 0xFFFE10FC
-#define COYOTE_IDE_ERROR_PORT 0xFFFE10E2
-#define IRQ_COYOTE_IDE IRQ_IXP4XX_GPIO5
-
-static struct flash_platform_data coyote_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource coyote_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device coyote_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &coyote_flash_data,
- },
- .num_resources = 1,
- .resource = &coyote_flash_resource,
-};
-
-static struct resource coyote_uart_resource = {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct plat_serial8250_port coyote_uart_data[] = {
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { },
-};
-
-static struct platform_device coyote_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = coyote_uart_data,
- },
- .num_resources = 1,
- .resource = &coyote_uart_resource,
-};
-
-static struct platform_device *coyote_devices[] __initdata = {
- &coyote_flash,
- &coyote_uart
-};
-
-static void __init coyote_init(void)
-{
- ixp4xx_sys_init();
-
- coyote_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- coyote_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
-
- *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
- *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
-
- if (machine_is_ixdpg425()) {
- coyote_uart_data[0].membase =
- (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET);
- coyote_uart_data[0].mapbase = IXP4XX_UART1_BASE_PHYS;
- coyote_uart_data[0].irq = IRQ_IXP4XX_UART1;
- }
-
- platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
-}
-
-#ifdef CONFIG_ARCH_ADI_COYOTE
-MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
- /* Maintainer: MontaVista Software, Inc. */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = coyote_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
-#endif
-
-/*
- * IXDPG425 is identical to Coyote except for which serial port
- * is connected.
- */
-#ifdef CONFIG_MACH_IXDPG425
-MACHINE_START(IXDPG425, "Intel IXDPG425")
- /* Maintainer: MontaVista Software, Inc. */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = coyote_init,
- .restart = ixp4xx_restart,
-MACHINE_END
-#endif
-
diff --git a/arch/arm/mach-ixp4xx/dsmg600-pci.c b/arch/arm/mach-ixp4xx/dsmg600-pci.c
deleted file mode 100644
index e997d97f619e..000000000000
--- a/arch/arm/mach-ixp4xx/dsmg600-pci.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * DSM-G600 board-level PCI initialization
- *
- * Copyright (C) 2006 Tower Technologies
- * Author: Alessandro Zummo <a.zummo@towertech.it>
- *
- * based on ixdp425-pci.c:
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * Maintainer: http://www.nslu2-linux.org/
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-#include "irqs.h"
-
-#define MAX_DEV 4
-#define IRQ_LINES 3
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define INTA 11
-#define INTB 10
-#define INTC 9
-#define INTD 8
-#define INTE 7
-#define INTF 6
-
-void __init dsmg600_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTF), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init dsmg600_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- static int pci_irq_table[MAX_DEV][IRQ_LINES] = {
- { IXP4XX_GPIO_IRQ(INTE), -1, -1 },
- { IXP4XX_GPIO_IRQ(INTA), -1, -1 },
- { IXP4XX_GPIO_IRQ(INTB), IXP4XX_GPIO_IRQ(INTC),
- IXP4XX_GPIO_IRQ(INTD) },
- { IXP4XX_GPIO_IRQ(INTF), -1, -1 },
- };
-
- if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
- return pci_irq_table[slot - 1][pin - 1];
-
- return -1;
-}
-
-struct hw_pci __initdata dsmg600_pci = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = dsmg600_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = dsmg600_map_irq,
-};
-
-int __init dsmg600_pci_init(void)
-{
- if (machine_is_dsmg600())
- pci_common_init(&dsmg600_pci);
-
- return 0;
-}
-
-subsys_initcall(dsmg600_pci_init);
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
deleted file mode 100644
index 4d4c62fced71..000000000000
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ /dev/null
@@ -1,304 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DSM-G600 board-setup
- *
- * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
- * Copyright (C) 2006 Tower Technologies
- *
- * based on ixdp425-setup.c:
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- * based on nslu2-power.c:
- * Copyright (C) 2005 Tower Technologies
- * based on nslu2-io.c:
- * Copyright (C) 2004 Karen Spearel
- *
- * Author: Alessandro Zummo <a.zummo@towertech.it>
- * Author: Michael Westerhof <mwester@dls.net>
- * Author: Rod Whitby <rod@whitby.id.au>
- * Maintainers: http://www.nslu2-linux.org/
- */
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/leds.h>
-#include <linux/reboot.h>
-#include <linux/i2c.h>
-#include <linux/gpio/machine.h>
-
-#include <mach/hardware.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-#include <asm/mach/time.h>
-
-#include "irqs.h"
-
-#define DSMG600_SDA_PIN 5
-#define DSMG600_SCL_PIN 4
-
-/* DSM-G600 Timer Setting */
-#define DSMG600_FREQ 66000000
-
-/* Buttons */
-#define DSMG600_PB_GPIO 15 /* power button */
-#define DSMG600_RB_GPIO 3 /* reset button */
-
-/* Power control */
-#define DSMG600_PO_GPIO 2 /* power off */
-
-/* LEDs */
-#define DSMG600_LED_PWR_GPIO 0
-#define DSMG600_LED_WLAN_GPIO 14
-
-static struct flash_platform_data dsmg600_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource dsmg600_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device dsmg600_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev.platform_data = &dsmg600_flash_data,
- .num_resources = 1,
- .resource = &dsmg600_flash_resource,
-};
-
-static struct gpiod_lookup_table dsmg600_i2c_gpiod_table = {
- .dev_id = "i2c-gpio.0",
- .table = {
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", DSMG600_SDA_PIN,
- NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", DSMG600_SCL_PIN,
- NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- },
-};
-
-static struct platform_device dsmg600_i2c_gpio = {
- .name = "i2c-gpio",
- .id = 0,
- .dev = {
- .platform_data = NULL,
- },
-};
-
-static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
- {
- I2C_BOARD_INFO("pcf8563", 0x51),
- },
-};
-
-static struct gpio_led dsmg600_led_pins[] = {
- {
- .name = "dsmg600:green:power",
- .gpio = DSMG600_LED_PWR_GPIO,
- },
- {
- .name = "dsmg600:green:wlan",
- .gpio = DSMG600_LED_WLAN_GPIO,
- .active_low = true,
- },
-};
-
-static struct gpio_led_platform_data dsmg600_led_data = {
- .num_leds = ARRAY_SIZE(dsmg600_led_pins),
- .leds = dsmg600_led_pins,
-};
-
-static struct platform_device dsmg600_leds = {
- .name = "leds-gpio",
- .id = -1,
- .dev.platform_data = &dsmg600_led_data,
-};
-
-static struct resource dsmg600_uart_resources[] = {
- {
- .start = IXP4XX_UART1_BASE_PHYS,
- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- }
-};
-
-static struct plat_serial8250_port dsmg600_uart_data[] = {
- {
- .mapbase = IXP4XX_UART1_BASE_PHYS,
- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { }
-};
-
-static struct platform_device dsmg600_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev.platform_data = dsmg600_uart_data,
- .num_resources = ARRAY_SIZE(dsmg600_uart_resources),
- .resource = dsmg600_uart_resources,
-};
-
-static struct platform_device *dsmg600_devices[] __initdata = {
- &dsmg600_i2c_gpio,
- &dsmg600_flash,
- &dsmg600_leds,
-};
-
-static void dsmg600_power_off(void)
-{
- /* enable the pwr cntl and drive it high */
- gpio_direction_output(DSMG600_PO_GPIO, 1);
-}
-
-/* This is used to make sure the power-button pusher is serious. The button
- * must be held until the value of this counter reaches zero.
- */
-static int power_button_countdown;
-
-/* Must hold the button down for at least this many counts to be processed */
-#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
-
-static void dsmg600_power_handler(struct timer_list *unused);
-static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler);
-
-static void dsmg600_power_handler(struct timer_list *unused)
-{
- /* This routine is called twice per second to check the
- * state of the power button.
- */
-
- if (gpio_get_value(DSMG600_PB_GPIO)) {
-
- /* IO Pin is 1 (button pushed) */
- if (power_button_countdown > 0)
- power_button_countdown--;
-
- } else {
-
- /* Done on button release, to allow for auto-power-on mods. */
- if (power_button_countdown == 0) {
- /* Signal init to do the ctrlaltdel action,
- * this will bypass init if it hasn't started
- * and do a kernel_restart.
- */
- ctrl_alt_del();
-
- /* Change the state of the power LED to "blink" */
- gpio_set_value(DSMG600_LED_PWR_GPIO, 0);
- } else {
- power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
- }
- }
-
- mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
-}
-
-static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
-{
- /* This is the paper-clip reset, it shuts the machine down directly. */
- machine_power_off();
-
- return IRQ_HANDLED;
-}
-
-static void __init dsmg600_timer_init(void)
-{
- /* The xtal on this machine is non-standard. */
- ixp4xx_timer_freq = DSMG600_FREQ;
-
- /* Call standard timer_init function. */
- ixp4xx_timer_init();
-}
-
-static int __init dsmg600_gpio_init(void)
-{
- if (!machine_is_dsmg600())
- return 0;
-
- gpio_request(DSMG600_RB_GPIO, "reset button");
- if (request_irq(gpio_to_irq(DSMG600_RB_GPIO), &dsmg600_reset_handler,
- IRQF_TRIGGER_LOW, "DSM-G600 reset button", NULL) < 0) {
-
- printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
- gpio_to_irq(DSMG600_RB_GPIO));
- }
-
- /*
- * The power button on the D-Link DSM-G600 is on GPIO 15, but
- * it cannot handle interrupts on that GPIO line. So we'll
- * have to poll it with a kernel timer.
- */
-
- /* Make sure that the power button GPIO is set up as an input */
- gpio_request(DSMG600_PB_GPIO, "power button");
- gpio_direction_input(DSMG600_PB_GPIO);
- /* Request poweroff GPIO line */
- gpio_request(DSMG600_PO_GPIO, "power off button");
-
- /* Set the initial value for the power button IRQ handler */
- power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
-
- mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
- return 0;
-}
-device_initcall(dsmg600_gpio_init);
-
-static void __init dsmg600_init(void)
-{
- ixp4xx_sys_init();
-
- dsmg600_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- dsmg600_flash_resource.end =
- IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
-
- gpiod_add_lookup_table(&dsmg600_i2c_gpiod_table);
- i2c_register_board_info(0, dsmg600_i2c_board_info,
- ARRAY_SIZE(dsmg600_i2c_board_info));
-
- /* The UART is required on the DSM-G600 (Redboot cannot use the
- * NIC) -- do it here so that it does *not* get removed if
- * platform_add_devices fails!
- */
- (void)platform_device_register(&dsmg600_uart);
-
- platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
-
- pm_power_off = dsmg600_power_off;
-}
-
-MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
- /* Maintainer: www.nslu2-linux.org */
- .atag_offset = 0x100,
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = dsmg600_timer_init,
- .init_machine = dsmg600_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/fsg-pci.c b/arch/arm/mach-ixp4xx/fsg-pci.c
deleted file mode 100644
index 4122a61aae70..000000000000
--- a/arch/arm/mach-ixp4xx/fsg-pci.c
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arch/mach-ixp4xx/fsg-pci.c
- *
- * FSG board-level PCI initialization
- *
- * Author: Rod Whitby <rod@whitby.id.au>
- * Maintainer: http://www.nslu2-linux.org/
- *
- * based on ixdp425-pci.c:
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-#include "irqs.h"
-
-#define MAX_DEV 3
-#define IRQ_LINES 3
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define INTA 6
-#define INTB 7
-#define INTC 5
-
-void __init fsg_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init fsg_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- static int pci_irq_table[IRQ_LINES] = {
- IXP4XX_GPIO_IRQ(INTC),
- IXP4XX_GPIO_IRQ(INTB),
- IXP4XX_GPIO_IRQ(INTA),
- };
-
- int irq = -1;
- slot -= 11;
-
- if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
- irq = pci_irq_table[slot - 1];
- printk(KERN_INFO "%s: Mapped slot %d pin %d to IRQ %d\n",
- __func__, slot, pin, irq);
-
- return irq;
-}
-
-struct hw_pci fsg_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = fsg_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = fsg_map_irq,
-};
-
-int __init fsg_pci_init(void)
-{
- if (machine_is_fsg())
- pci_common_init(&fsg_pci);
- return 0;
-}
-
-subsys_initcall(fsg_pci_init);
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
deleted file mode 100644
index 844329c5610d..000000000000
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ /dev/null
@@ -1,311 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/arm/mach-ixp4xx/fsg-setup.c
- *
- * FSG board-setup
- *
- * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
- *
- * based on ixdp425-setup.c:
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- * based on nslu2-power.c
- * Copyright (C) 2005 Tower Technologies
- *
- * Author: Rod Whitby <rod@whitby.id.au>
- * Maintainers: http://www.nslu2-linux.org/
- *
- */
-#include <linux/gpio.h>
-#include <linux/if_ether.h>
-#include <linux/irq.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/leds.h>
-#include <linux/reboot.h>
-#include <linux/i2c.h>
-#include <linux/gpio/machine.h>
-#include <linux/io.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-#include <mach/hardware.h>
-
-#include "irqs.h"
-
-#define FSG_SDA_PIN 12
-#define FSG_SCL_PIN 13
-
-#define FSG_SB_GPIO 4 /* sync button */
-#define FSG_RB_GPIO 9 /* reset button */
-#define FSG_UB_GPIO 10 /* usb button */
-
-static struct flash_platform_data fsg_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource fsg_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device fsg_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &fsg_flash_data,
- },
- .num_resources = 1,
- .resource = &fsg_flash_resource,
-};
-
-static struct gpiod_lookup_table fsg_i2c_gpiod_table = {
- .dev_id = "i2c-gpio.0",
- .table = {
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", FSG_SDA_PIN,
- NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", FSG_SCL_PIN,
- NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- },
-};
-
-static struct platform_device fsg_i2c_gpio = {
- .name = "i2c-gpio",
- .id = 0,
- .dev = {
- .platform_data = NULL,
- },
-};
-
-static struct i2c_board_info __initdata fsg_i2c_board_info [] = {
- {
- I2C_BOARD_INFO("isl1208", 0x6f),
- },
-};
-
-static struct resource fsg_uart_resources[] = {
- {
- .start = IXP4XX_UART1_BASE_PHYS,
- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- }
-};
-
-static struct plat_serial8250_port fsg_uart_data[] = {
- {
- .mapbase = IXP4XX_UART1_BASE_PHYS,
- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { }
-};
-
-static struct platform_device fsg_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = fsg_uart_data,
- },
- .num_resources = ARRAY_SIZE(fsg_uart_resources),
- .resource = fsg_uart_resources,
-};
-
-static struct platform_device fsg_leds = {
- .name = "fsg-led",
- .id = -1,
-};
-
-/* Built-in 10/100 Ethernet MAC interfaces */
-static struct resource fsg_eth_npeb_resources[] = {
- {
- .start = IXP4XX_EthB_BASE_PHYS,
- .end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct resource fsg_eth_npec_resources[] = {
- {
- .start = IXP4XX_EthC_BASE_PHYS,
- .end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct eth_plat_info fsg_plat_eth[] = {
- {
- .phy = 5,
- .rxq = 3,
- .txreadyq = 20,
- }, {
- .phy = 4,
- .rxq = 4,
- .txreadyq = 21,
- }
-};
-
-static struct platform_device fsg_eth[] = {
- {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEB,
- .dev = {
- .platform_data = fsg_plat_eth,
- },
- .num_resources = ARRAY_SIZE(fsg_eth_npeb_resources),
- .resource = fsg_eth_npeb_resources,
- }, {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEC,
- .dev = {
- .platform_data = fsg_plat_eth + 1,
- },
- .num_resources = ARRAY_SIZE(fsg_eth_npec_resources),
- .resource = fsg_eth_npec_resources,
- }
-};
-
-static struct platform_device *fsg_devices[] __initdata = {
- &fsg_i2c_gpio,
- &fsg_flash,
- &fsg_leds,
- &fsg_eth[0],
- &fsg_eth[1],
-};
-
-static irqreturn_t fsg_power_handler(int irq, void *dev_id)
-{
- /* Signal init to do the ctrlaltdel action, this will bypass init if
- * it hasn't started and do a kernel_restart.
- */
- ctrl_alt_del();
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t fsg_reset_handler(int irq, void *dev_id)
-{
- /* This is the paper-clip reset which does an emergency reboot. */
- printk(KERN_INFO "Restarting system.\n");
- machine_restart(NULL);
-
- /* This should never be reached. */
- return IRQ_HANDLED;
-}
-
-static void __init fsg_init(void)
-{
- uint8_t __iomem *f;
-
- ixp4xx_sys_init();
-
- fsg_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- fsg_flash_resource.end =
- IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
-
- *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
- *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
-
- /* Configure CS2 for operation, 8bit and writable */
- *IXP4XX_EXP_CS2 = 0xbfff0002;
-
- gpiod_add_lookup_table(&fsg_i2c_gpiod_table);
- i2c_register_board_info(0, fsg_i2c_board_info,
- ARRAY_SIZE(fsg_i2c_board_info));
-
- /* This is only useful on a modified machine, but it is valuable
- * to have it first in order to see debug messages, and so that
- * it does *not* get removed if platform_add_devices fails!
- */
- (void)platform_device_register(&fsg_uart);
-
- platform_add_devices(fsg_devices, ARRAY_SIZE(fsg_devices));
-
- if (request_irq(gpio_to_irq(FSG_RB_GPIO), &fsg_reset_handler,
- IRQF_TRIGGER_LOW, "FSG reset button", NULL) < 0) {
-
- printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
- gpio_to_irq(FSG_RB_GPIO));
- }
-
- if (request_irq(gpio_to_irq(FSG_SB_GPIO), &fsg_power_handler,
- IRQF_TRIGGER_LOW, "FSG power button", NULL) < 0) {
-
- printk(KERN_DEBUG "Power Button IRQ %d not available\n",
- gpio_to_irq(FSG_SB_GPIO));
- }
-
- /*
- * Map in a portion of the flash and read the MAC addresses.
- * Since it is stored in BE in the flash itself, we need to
- * byteswap it if we're in LE mode.
- */
- f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x400000);
- if (f) {
-#ifdef __ARMEB__
- int i;
- for (i = 0; i < 6; i++) {
- fsg_plat_eth[0].hwaddr[i] = readb(f + 0x3C0422 + i);
- fsg_plat_eth[1].hwaddr[i] = readb(f + 0x3C043B + i);
- }
-#else
-
- /*
- Endian-swapped reads from unaligned addresses are
- required to extract the two MACs from the big-endian
- Redboot config area in flash.
- */
-
- fsg_plat_eth[0].hwaddr[0] = readb(f + 0x3C0421);
- fsg_plat_eth[0].hwaddr[1] = readb(f + 0x3C0420);
- fsg_plat_eth[0].hwaddr[2] = readb(f + 0x3C0427);
- fsg_plat_eth[0].hwaddr[3] = readb(f + 0x3C0426);
- fsg_plat_eth[0].hwaddr[4] = readb(f + 0x3C0425);
- fsg_plat_eth[0].hwaddr[5] = readb(f + 0x3C0424);
-
- fsg_plat_eth[1].hwaddr[0] = readb(f + 0x3C0439);
- fsg_plat_eth[1].hwaddr[1] = readb(f + 0x3C043F);
- fsg_plat_eth[1].hwaddr[2] = readb(f + 0x3C043E);
- fsg_plat_eth[1].hwaddr[3] = readb(f + 0x3C043D);
- fsg_plat_eth[1].hwaddr[4] = readb(f + 0x3C043C);
- fsg_plat_eth[1].hwaddr[5] = readb(f + 0x3C0443);
-#endif
- iounmap(f);
- }
- printk(KERN_INFO "FSG: Using MAC address %pM for port 0\n",
- fsg_plat_eth[0].hwaddr);
- printk(KERN_INFO "FSG: Using MAC address %pM for port 1\n",
- fsg_plat_eth[1].hwaddr);
-
-}
-
-MACHINE_START(FSG, "Freecom FSG-3")
- /* Maintainer: www.nslu2-linux.org */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = fsg_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
-
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
deleted file mode 100644
index 224328dbddb1..000000000000
--- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c
+++ /dev/null
@@ -1,72 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-ixp4xx/gtwx5715-pci.c
- *
- * Gemtek GTWX5715 (Linksys WRV54G) board setup
- *
- * Copyright (C) 2004 George T. Joseph
- * Derived from Coyote
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <asm/mach/pci.h>
-
-#include "irqs.h"
-
-#define SLOT0_DEVID 0
-#define SLOT1_DEVID 1
-#define INTA 10 /* slot 1 has INTA and INTB crossed */
-#define INTB 11
-
-/*
- * Slot 0 isn't actually populated with a card connector but
- * we initialize it anyway in case a future version has the
- * slot populated or someone with good soldering skills has
- * some free time.
- */
-void __init gtwx5715_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-
-static int __init gtwx5715_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- int rc = -1;
-
- if ((slot == SLOT0_DEVID && pin == 1) ||
- (slot == SLOT1_DEVID && pin == 2))
- rc = IXP4XX_GPIO_IRQ(INTA);
- else if ((slot == SLOT0_DEVID && pin == 2) ||
- (slot == SLOT1_DEVID && pin == 1))
- rc = IXP4XX_GPIO_IRQ(INTB);
-
- printk(KERN_INFO "%s: Mapped slot %d pin %d to IRQ %d\n",
- __func__, slot, pin, rc);
- return rc;
-}
-
-struct hw_pci gtwx5715_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = gtwx5715_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = gtwx5715_map_irq,
-};
-
-int __init gtwx5715_pci_init(void)
-{
- if (machine_is_gtwx5715())
- pci_common_init(&gtwx5715_pci);
-
- return 0;
-}
-
-subsys_initcall(gtwx5715_pci_init);
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
deleted file mode 100644
index 28f0d2a8a829..000000000000
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ /dev/null
@@ -1,167 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * arch/arm/mach-ixp4xx/gtwx5715-setup.c
- *
- * Gemtek GTWX5715 (Linksys WRV54G) board setup
- *
- * Copyright (C) 2004 George T. Joseph
- * Derived from Coyote
- */
-
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#include "irqs.h"
-
-/* GPIO 5,6,7 and 12 are hard wired to the Kendin KS8995M Switch
- and operate as an SPI type interface. The details of the interface
- are available on Kendin/Micrel's web site. */
-
-#define GTWX5715_KSSPI_SELECT 5
-#define GTWX5715_KSSPI_TXD 6
-#define GTWX5715_KSSPI_CLOCK 7
-#define GTWX5715_KSSPI_RXD 12
-
-/* The "reset" button is wired to GPIO 3.
- The GPIO is brought "low" when the button is pushed. */
-
-#define GTWX5715_BUTTON_GPIO 3
-
-/* Board Label Front Label
- LED1 Power
- LED2 Wireless-G
- LED3 not populated but could be
- LED4 Internet
- LED5 - LED8 Controlled by KS8995M Switch
- LED9 DMZ */
-
-#define GTWX5715_LED1_GPIO 2
-#define GTWX5715_LED2_GPIO 9
-#define GTWX5715_LED3_GPIO 8
-#define GTWX5715_LED4_GPIO 1
-#define GTWX5715_LED9_GPIO 4
-
-/*
- * Xscale UART registers are 32 bits wide with only the least
- * significant 8 bits having any meaning. From a configuration
- * perspective, this means 2 things...
- *
- * Setting .regshift = 2 so that the standard 16550 registers
- * line up on every 4th byte.
- *
- * Shifting the register start virtual address +3 bytes when
- * compiled big-endian. Since register writes are done on a
- * single byte basis, if the shift isn't done the driver will
- * write the value into the most significant byte of the register,
- * which is ignored, instead of the least significant.
- */
-
-#ifdef __ARMEB__
-#define REG_OFFSET 3
-#else
-#define REG_OFFSET 0
-#endif
-
-/*
- * Only the second or "console" uart is connected on the gtwx5715.
- */
-
-static struct resource gtwx5715_uart_resources[] = {
- {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IRQ_IXP4XX_UART2,
- .end = IRQ_IXP4XX_UART2,
- .flags = IORESOURCE_IRQ,
- },
- { },
-};
-
-
-static struct plat_serial8250_port gtwx5715_uart_platform_data[] = {
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { },
-};
-
-static struct platform_device gtwx5715_uart_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = gtwx5715_uart_platform_data,
- },
- .num_resources = 2,
- .resource = gtwx5715_uart_resources,
-};
-
-static struct flash_platform_data gtwx5715_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource gtwx5715_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device gtwx5715_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &gtwx5715_flash_data,
- },
- .num_resources = 1,
- .resource = &gtwx5715_flash_resource,
-};
-
-static struct platform_device *gtwx5715_devices[] __initdata = {
- &gtwx5715_uart_device,
- &gtwx5715_flash,
-};
-
-static void __init gtwx5715_init(void)
-{
- ixp4xx_sys_init();
-
- gtwx5715_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- gtwx5715_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1;
-
- platform_add_devices(gtwx5715_devices, ARRAY_SIZE(gtwx5715_devices));
-}
-
-
-MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
- /* Maintainer: George Joseph */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = gtwx5715_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
-
-
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
deleted file mode 100644
index c77fe0d52d79..000000000000
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ixp4xx/ixdp425-pci.c
- *
- * IXDP425 board-level PCI initialization
- *
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <asm/mach/pci.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-#include "irqs.h"
-
-#define MAX_DEV 4
-#define IRQ_LINES 4
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define INTA 11
-#define INTB 10
-#define INTC 9
-#define INTD 8
-
-
-void __init ixdp425_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init ixdp425_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- static int pci_irq_table[IRQ_LINES] = {
- IXP4XX_GPIO_IRQ(INTA),
- IXP4XX_GPIO_IRQ(INTB),
- IXP4XX_GPIO_IRQ(INTC),
- IXP4XX_GPIO_IRQ(INTD)
- };
-
- if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
- return pci_irq_table[(slot + pin - 2) % 4];
-
- return -1;
-}
-
-struct hw_pci ixdp425_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = ixdp425_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = ixdp425_map_irq,
-};
-
-int __init ixdp425_pci_init(void)
-{
- if (machine_is_ixdp425() || machine_is_ixcdp1100() ||
- machine_is_ixdp465() || machine_is_kixrp435())
- pci_common_init(&ixdp425_pci);
- return 0;
-}
-
-subsys_initcall(ixdp425_pci_init);
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
deleted file mode 100644
index 45d5b720ded6..000000000000
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ /dev/null
@@ -1,339 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/arm/mach-ixp4xx/ixdp425-setup.c
- *
- * IXDP425/IXCDP1100 board-setup
- *
- * Copyright (C) 2003-2005 MontaVista Software, Inc.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-#include <linux/gpio/machine.h>
-#include <linux/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/platnand.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#include "irqs.h"
-
-#define IXDP425_SDA_PIN 7
-#define IXDP425_SCL_PIN 6
-
-/* NAND Flash pins */
-#define IXDP425_NAND_NCE_PIN 12
-
-#define IXDP425_NAND_CMD_BYTE 0x01
-#define IXDP425_NAND_ADDR_BYTE 0x02
-
-static struct flash_platform_data ixdp425_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource ixdp425_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ixdp425_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &ixdp425_flash_data,
- },
- .num_resources = 1,
- .resource = &ixdp425_flash_resource,
-};
-
-#if defined(CONFIG_MTD_NAND_PLATFORM) || \
- defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
-
-static struct mtd_partition ixdp425_partitions[] = {
- {
- .name = "ixp400 NAND FS 0",
- .offset = 0,
- .size = SZ_8M
- }, {
- .name = "ixp400 NAND FS 1",
- .offset = MTDPART_OFS_APPEND,
- .size = MTDPART_SIZ_FULL
- },
-};
-
-static void
-ixdp425_flash_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl)
-{
- int offset = (int)nand_get_controller_data(this);
-
- if (ctrl & NAND_CTRL_CHANGE) {
- if (ctrl & NAND_NCE) {
- gpio_set_value(IXDP425_NAND_NCE_PIN, 0);
- udelay(5);
- } else
- gpio_set_value(IXDP425_NAND_NCE_PIN, 1);
-
- offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
- offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
- nand_set_controller_data(this, (void *)offset);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->legacy.IO_ADDR_W + offset);
-}
-
-static struct platform_nand_data ixdp425_flash_nand_data = {
- .chip = {
- .nr_chips = 1,
- .chip_delay = 30,
- .partitions = ixdp425_partitions,
- .nr_partitions = ARRAY_SIZE(ixdp425_partitions),
- },
- .ctrl = {
- .cmd_ctrl = ixdp425_flash_nand_cmd_ctrl
- }
-};
-
-static struct resource ixdp425_flash_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device ixdp425_flash_nand = {
- .name = "gen_nand",
- .id = -1,
- .dev = {
- .platform_data = &ixdp425_flash_nand_data,
- },
- .num_resources = 1,
- .resource = &ixdp425_flash_nand_resource,
-};
-#endif /* CONFIG_MTD_NAND_PLATFORM */
-
-static struct gpiod_lookup_table ixdp425_i2c_gpiod_table = {
- .dev_id = "i2c-gpio.0",
- .table = {
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", IXDP425_SDA_PIN,
- NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", IXDP425_SCL_PIN,
- NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- },
-};
-
-static struct platform_device ixdp425_i2c_gpio = {
- .name = "i2c-gpio",
- .id = 0,
- .dev = {
- .platform_data = NULL,
- },
-};
-
-static struct resource ixdp425_uart_resources[] = {
- {
- .start = IXP4XX_UART1_BASE_PHYS,
- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM
- },
- {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM
- }
-};
-
-static struct plat_serial8250_port ixdp425_uart_data[] = {
- {
- .mapbase = IXP4XX_UART1_BASE_PHYS,
- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { },
-};
-
-static struct platform_device ixdp425_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev.platform_data = ixdp425_uart_data,
- .num_resources = 2,
- .resource = ixdp425_uart_resources
-};
-
-/* Built-in 10/100 Ethernet MAC interfaces */
-static struct resource ixp425_npeb_resources[] = {
- {
- .start = IXP4XX_EthB_BASE_PHYS,
- .end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct resource ixp425_npec_resources[] = {
- {
- .start = IXP4XX_EthC_BASE_PHYS,
- .end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct eth_plat_info ixdp425_plat_eth[] = {
- {
- .phy = 0,
- .rxq = 3,
- .txreadyq = 20,
- }, {
- .phy = 1,
- .rxq = 4,
- .txreadyq = 21,
- }
-};
-
-static struct platform_device ixdp425_eth[] = {
- {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEB,
- .dev.platform_data = ixdp425_plat_eth,
- .num_resources = ARRAY_SIZE(ixp425_npeb_resources),
- .resource = ixp425_npeb_resources,
- }, {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEC,
- .dev.platform_data = ixdp425_plat_eth + 1,
- .num_resources = ARRAY_SIZE(ixp425_npec_resources),
- .resource = ixp425_npec_resources,
- }
-};
-
-static struct platform_device *ixdp425_devices[] __initdata = {
- &ixdp425_i2c_gpio,
- &ixdp425_flash,
-#if defined(CONFIG_MTD_NAND_PLATFORM) || \
- defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
- &ixdp425_flash_nand,
-#endif
- &ixdp425_uart,
- &ixdp425_eth[0],
- &ixdp425_eth[1],
-};
-
-static void __init ixdp425_init(void)
-{
- ixp4xx_sys_init();
-
- ixdp425_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- ixdp425_flash_resource.end =
- IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
-
-#if defined(CONFIG_MTD_NAND_PLATFORM) || \
- defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
- ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3),
- ixdp425_flash_nand_resource.end = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1;
-
- gpio_request(IXDP425_NAND_NCE_PIN, "NAND NCE pin");
- gpio_direction_output(IXDP425_NAND_NCE_PIN, 0);
-
- /* Configure expansion bus for NAND Flash */
- *IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
- IXP4XX_EXP_BUS_STROBE_T(1) | /* extend by 1 clock */
- IXP4XX_EXP_BUS_CYCLES(0) | /* Intel cycles */
- IXP4XX_EXP_BUS_SIZE(0) | /* 512bytes addr space*/
- IXP4XX_EXP_BUS_WR_EN |
- IXP4XX_EXP_BUS_BYTE_EN; /* 8 bit data bus */
-#endif
-
- if (cpu_is_ixp43x()) {
- ixdp425_uart.num_resources = 1;
- ixdp425_uart_data[1].flags = 0;
- }
-
- gpiod_add_lookup_table(&ixdp425_i2c_gpiod_table);
- platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
-}
-
-#ifdef CONFIG_ARCH_IXDP425
-MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = ixdp425_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_IXDP465
-MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = ixdp425_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
-MACHINE_END
-#endif
-
-#ifdef CONFIG_ARCH_PRPMC1100
-MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = ixdp425_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_KIXRP435
-MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
- /* Maintainer: MontaVista Software, Inc. */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = ixdp425_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
deleted file mode 100644
index 1cbea65897b2..000000000000
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ixp4xx/ixdpg425-pci.c
- *
- * PCI setup routines for Intel IXDPG425 Platform
- *
- * Copyright (C) 2004 MontaVista Softwrae, Inc.
- *
- * Maintainer: Deepak Saxena <dsaxena@plexity.net>
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-
-#include <asm/mach/pci.h>
-
-#include "irqs.h"
-
-void __init ixdpg425_pci_preinit(void)
-{
- irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
-
- ixp4xx_pci_preinit();
-}
-
-static int __init ixdpg425_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- if (slot == 12 || slot == 13)
- return IRQ_IXP4XX_GPIO7;
- else if (slot == 14)
- return IRQ_IXP4XX_GPIO6;
- else return -1;
-}
-
-struct hw_pci ixdpg425_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = ixdpg425_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = ixdpg425_map_irq,
-};
-
-int __init ixdpg425_pci_init(void)
-{
- if (machine_is_ixdpg425())
- pci_common_init(&ixdpg425_pci);
- return 0;
-}
-
-subsys_initcall(ixdpg425_pci_init);
diff --git a/arch/arm/mach-ixp4xx/miccpt-pci.c b/arch/arm/mach-ixp4xx/miccpt-pci.c
deleted file mode 100644
index 55a36537ee1a..000000000000
--- a/arch/arm/mach-ixp4xx/miccpt-pci.c
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ixp4xx/miccpt-pci.c
- *
- * MICCPT board-level PCI initialization
- *
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- * Copyright (C) 2006 OMICRON electronics GmbH
- *
- * Author: Michael Jochum <michael.jochum@omicron.at>
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-
-#include "irqs.h"
-
-#define MAX_DEV 4
-#define IRQ_LINES 4
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define INTA 1
-#define INTB 2
-#define INTC 3
-#define INTD 4
-
-
-void __init miccpt_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init miccpt_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- static int pci_irq_table[IRQ_LINES] = {
- IXP4XX_GPIO_IRQ(INTA),
- IXP4XX_GPIO_IRQ(INTB),
- IXP4XX_GPIO_IRQ(INTC),
- IXP4XX_GPIO_IRQ(INTD)
- };
-
- if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
- return pci_irq_table[(slot + pin - 2) % 4];
-
- return -1;
-}
-
-struct hw_pci miccpt_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = miccpt_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = miccpt_map_irq,
-};
-
-int __init miccpt_pci_init(void)
-{
- if (machine_is_miccpt())
- pci_common_init(&miccpt_pci);
- return 0;
-}
-
-subsys_initcall(miccpt_pci_init);
diff --git a/arch/arm/mach-ixp4xx/nas100d-pci.c b/arch/arm/mach-ixp4xx/nas100d-pci.c
deleted file mode 100644
index 1176f9cb4865..000000000000
--- a/arch/arm/mach-ixp4xx/nas100d-pci.c
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ixp4xx/nas100d-pci.c
- *
- * NAS 100d board-level PCI initialization
- *
- * based on ixdp425-pci.c:
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * Maintainer: http://www.nslu2-linux.org/
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-#include "irqs.h"
-
-#define MAX_DEV 3
-#define IRQ_LINES 3
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define INTA 11
-#define INTB 10
-#define INTC 9
-#define INTD 8
-#define INTE 7
-
-void __init nas100d_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init nas100d_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- static int pci_irq_table[MAX_DEV][IRQ_LINES] = {
- { IXP4XX_GPIO_IRQ(INTA), -1, -1 },
- { IXP4XX_GPIO_IRQ(INTB), -1, -1 },
- { IXP4XX_GPIO_IRQ(INTC), IXP4XX_GPIO_IRQ(INTD),
- IXP4XX_GPIO_IRQ(INTE) },
- };
-
- if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
- return pci_irq_table[slot - 1][pin - 1];
-
- return -1;
-}
-
-struct hw_pci __initdata nas100d_pci = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = nas100d_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = nas100d_map_irq,
-};
-
-int __init nas100d_pci_init(void)
-{
- if (machine_is_nas100d())
- pci_common_init(&nas100d_pci);
-
- return 0;
-}
-
-subsys_initcall(nas100d_pci_init);
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
deleted file mode 100644
index 6133cf01cbe4..000000000000
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ /dev/null
@@ -1,353 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/arm/mach-ixp4xx/nas100d-setup.c
- *
- * NAS 100d board-setup
- *
- * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
- *
- * based on ixdp425-setup.c:
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- * based on nas100d-power.c:
- * Copyright (C) 2005 Tower Technologies
- * based on nas100d-io.c
- * Copyright (C) 2004 Karen Spearel
- *
- * Author: Alessandro Zummo <a.zummo@towertech.it>
- * Author: Rod Whitby <rod@whitby.id.au>
- * Maintainers: http://www.nslu2-linux.org/
- *
- */
-#include <linux/gpio.h>
-#include <linux/if_ether.h>
-#include <linux/irq.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/leds.h>
-#include <linux/reboot.h>
-#include <linux/i2c.h>
-#include <linux/gpio/machine.h>
-#include <linux/io.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-#include <mach/hardware.h>
-
-#include "irqs.h"
-
-#define NAS100D_SDA_PIN 5
-#define NAS100D_SCL_PIN 6
-
-/* Buttons */
-#define NAS100D_PB_GPIO 14 /* power button */
-#define NAS100D_RB_GPIO 4 /* reset button */
-
-/* Power control */
-#define NAS100D_PO_GPIO 12 /* power off */
-
-/* LEDs */
-#define NAS100D_LED_WLAN_GPIO 0
-#define NAS100D_LED_DISK_GPIO 3
-#define NAS100D_LED_PWR_GPIO 15
-
-static struct flash_platform_data nas100d_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource nas100d_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device nas100d_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev.platform_data = &nas100d_flash_data,
- .num_resources = 1,
- .resource = &nas100d_flash_resource,
-};
-
-static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
- {
- I2C_BOARD_INFO("pcf8563", 0x51),
- },
-};
-
-static struct gpio_led nas100d_led_pins[] = {
- {
- .name = "nas100d:green:wlan",
- .gpio = NAS100D_LED_WLAN_GPIO,
- .active_low = true,
- },
- {
- .name = "nas100d:blue:power", /* (off=flashing) */
- .gpio = NAS100D_LED_PWR_GPIO,
- .active_low = true,
- },
- {
- .name = "nas100d:yellow:disk",
- .gpio = NAS100D_LED_DISK_GPIO,
- .active_low = true,
- },
-};
-
-static struct gpio_led_platform_data nas100d_led_data = {
- .num_leds = ARRAY_SIZE(nas100d_led_pins),
- .leds = nas100d_led_pins,
-};
-
-static struct platform_device nas100d_leds = {
- .name = "leds-gpio",
- .id = -1,
- .dev.platform_data = &nas100d_led_data,
-};
-
-static struct gpiod_lookup_table nas100d_i2c_gpiod_table = {
- .dev_id = "i2c-gpio.0",
- .table = {
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NAS100D_SDA_PIN,
- NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NAS100D_SCL_PIN,
- NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- },
-};
-
-static struct platform_device nas100d_i2c_gpio = {
- .name = "i2c-gpio",
- .id = 0,
- .dev = {
- .platform_data = NULL,
- },
-};
-
-static struct resource nas100d_uart_resources[] = {
- {
- .start = IXP4XX_UART1_BASE_PHYS,
- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- }
-};
-
-static struct plat_serial8250_port nas100d_uart_data[] = {
- {
- .mapbase = IXP4XX_UART1_BASE_PHYS,
- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { }
-};
-
-static struct platform_device nas100d_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev.platform_data = nas100d_uart_data,
- .num_resources = 2,
- .resource = nas100d_uart_resources,
-};
-
-/* Built-in 10/100 Ethernet MAC interfaces */
-static struct resource nas100d_eth_resources[] = {
- {
- .start = IXP4XX_EthB_BASE_PHYS,
- .end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct eth_plat_info nas100d_plat_eth[] = {
- {
- .phy = 0,
- .rxq = 3,
- .txreadyq = 20,
- }
-};
-
-static struct platform_device nas100d_eth[] = {
- {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEB,
- .dev.platform_data = nas100d_plat_eth,
- .num_resources = ARRAY_SIZE(nas100d_eth_resources),
- .resource = nas100d_eth_resources,
- }
-};
-
-static struct platform_device *nas100d_devices[] __initdata = {
- &nas100d_i2c_gpio,
- &nas100d_flash,
- &nas100d_leds,
- &nas100d_eth[0],
-};
-
-static void nas100d_power_off(void)
-{
- /* This causes the box to drop the power and go dead. */
-
- /* enable the pwr cntl gpio and assert power off */
- gpio_direction_output(NAS100D_PO_GPIO, 1);
-}
-
-/* This is used to make sure the power-button pusher is serious. The button
- * must be held until the value of this counter reaches zero.
- */
-static int power_button_countdown;
-
-/* Must hold the button down for at least this many counts to be processed */
-#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
-
-static void nas100d_power_handler(struct timer_list *unused);
-static DEFINE_TIMER(nas100d_power_timer, nas100d_power_handler);
-
-static void nas100d_power_handler(struct timer_list *unused)
-{
- /* This routine is called twice per second to check the
- * state of the power button.
- */
-
- if (gpio_get_value(NAS100D_PB_GPIO)) {
-
- /* IO Pin is 1 (button pushed) */
- if (power_button_countdown > 0)
- power_button_countdown--;
-
- } else {
-
- /* Done on button release, to allow for auto-power-on mods. */
- if (power_button_countdown == 0) {
- /* Signal init to do the ctrlaltdel action,
- * this will bypass init if it hasn't started
- * and do a kernel_restart.
- */
- ctrl_alt_del();
-
- /* Change the state of the power LED to "blink" */
- gpio_set_value(NAS100D_LED_PWR_GPIO, 0);
- } else {
- power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
- }
- }
-
- mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
-}
-
-static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
-{
- /* This is the paper-clip reset, it shuts the machine down directly. */
- machine_power_off();
-
- return IRQ_HANDLED;
-}
-
-static int __init nas100d_gpio_init(void)
-{
- if (!machine_is_nas100d())
- return 0;
-
- /*
- * The power button on the Iomega NAS100d is on GPIO 14, but
- * it cannot handle interrupts on that GPIO line. So we'll
- * have to poll it with a kernel timer.
- */
-
- /* Request the power off GPIO */
- gpio_request(NAS100D_PO_GPIO, "power off");
-
- /* Make sure that the power button GPIO is set up as an input */
- gpio_request(NAS100D_PB_GPIO, "power button");
- gpio_direction_input(NAS100D_PB_GPIO);
-
- /* Set the initial value for the power button IRQ handler */
- power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
-
- mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
-
- return 0;
-}
-device_initcall(nas100d_gpio_init);
-
-static void __init nas100d_init(void)
-{
- uint8_t __iomem *f;
- int i;
-
- ixp4xx_sys_init();
-
- nas100d_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- nas100d_flash_resource.end =
- IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
-
- gpiod_add_lookup_table(&nas100d_i2c_gpiod_table);
- i2c_register_board_info(0, nas100d_i2c_board_info,
- ARRAY_SIZE(nas100d_i2c_board_info));
-
- /*
- * This is only useful on a modified machine, but it is valuable
- * to have it first in order to see debug messages, and so that
- * it does *not* get removed if platform_add_devices fails!
- */
- (void)platform_device_register(&nas100d_uart);
-
- platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
-
- pm_power_off = nas100d_power_off;
-
- if (request_irq(gpio_to_irq(NAS100D_RB_GPIO), &nas100d_reset_handler,
- IRQF_TRIGGER_LOW, "NAS100D reset button", NULL) < 0) {
-
- printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
- gpio_to_irq(NAS100D_RB_GPIO));
- }
-
- /*
- * Map in a portion of the flash and read the MAC address.
- * Since it is stored in BE in the flash itself, we need to
- * byteswap it if we're in LE mode.
- */
- f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x1000000);
- if (f) {
- for (i = 0; i < 6; i++)
-#ifdef __ARMEB__
- nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + i);
-#else
- nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + (i^3));
-#endif
- iounmap(f);
- }
- printk(KERN_INFO "NAS100D: Using MAC address %pM for port 0\n",
- nas100d_plat_eth[0].hwaddr);
-
-}
-
-MACHINE_START(NAS100D, "Iomega NAS 100d")
- /* Maintainer: www.nslu2-linux.org */
- .atag_offset = 0x100,
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .init_machine = nas100d_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c
deleted file mode 100644
index c07936a1d736..000000000000
--- a/arch/arm/mach-ixp4xx/nslu2-pci.c
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ixp4xx/nslu2-pci.c
- *
- * NSLU2 board-level PCI initialization
- *
- * based on ixdp425-pci.c:
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * Maintainer: http://www.nslu2-linux.org/
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-#include "irqs.h"
-
-#define MAX_DEV 3
-#define IRQ_LINES 3
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define INTA 11
-#define INTB 10
-#define INTC 9
-#define INTD 8
-
-void __init nslu2_pci_preinit(void)
-{
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init nslu2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- static int pci_irq_table[IRQ_LINES] = {
- IXP4XX_GPIO_IRQ(INTA),
- IXP4XX_GPIO_IRQ(INTB),
- IXP4XX_GPIO_IRQ(INTC),
- };
-
- if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
- return pci_irq_table[(slot + pin - 2) % IRQ_LINES];
-
- return -1;
-}
-
-struct hw_pci __initdata nslu2_pci = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = nslu2_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = nslu2_map_irq,
-};
-
-int __init nslu2_pci_init(void) /* monkey see, monkey do */
-{
- if (machine_is_nslu2())
- pci_common_init(&nslu2_pci);
-
- return 0;
-}
-
-subsys_initcall(nslu2_pci_init);
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
deleted file mode 100644
index 8526a70e401b..000000000000
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ /dev/null
@@ -1,341 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/arm/mach-ixp4xx/nslu2-setup.c
- *
- * NSLU2 board-setup
- *
- * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
- *
- * based on ixdp425-setup.c:
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- * based on nslu2-power.c:
- * Copyright (C) 2005 Tower Technologies
- *
- * Author: Mark Rakes <mrakes at mac.com>
- * Author: Rod Whitby <rod@whitby.id.au>
- * Author: Alessandro Zummo <a.zummo@towertech.it>
- * Maintainers: http://www.nslu2-linux.org/
- *
- */
-#include <linux/gpio.h>
-#include <linux/if_ether.h>
-#include <linux/irq.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/leds.h>
-#include <linux/reboot.h>
-#include <linux/i2c.h>
-#include <linux/gpio/machine.h>
-#include <linux/io.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-#include <asm/mach/time.h>
-#include <mach/hardware.h>
-
-#include "irqs.h"
-
-#define NSLU2_SDA_PIN 7
-#define NSLU2_SCL_PIN 6
-
-/* NSLU2 Timer */
-#define NSLU2_FREQ 66000000
-
-/* Buttons */
-#define NSLU2_PB_GPIO 5 /* power button */
-#define NSLU2_PO_GPIO 8 /* power off */
-#define NSLU2_RB_GPIO 12 /* reset button */
-
-/* Buzzer */
-#define NSLU2_GPIO_BUZZ 4
-
-/* LEDs */
-#define NSLU2_LED_RED_GPIO 0
-#define NSLU2_LED_GRN_GPIO 1
-#define NSLU2_LED_DISK1_GPIO 3
-#define NSLU2_LED_DISK2_GPIO 2
-
-static struct flash_platform_data nslu2_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource nslu2_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device nslu2_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev.platform_data = &nslu2_flash_data,
- .num_resources = 1,
- .resource = &nslu2_flash_resource,
-};
-
-static struct gpiod_lookup_table nslu2_i2c_gpiod_table = {
- .dev_id = "i2c-gpio.0",
- .table = {
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NSLU2_SDA_PIN,
- NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NSLU2_SCL_PIN,
- NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- },
-};
-
-static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
- {
- I2C_BOARD_INFO("x1205", 0x6f),
- },
-};
-
-static struct gpio_led nslu2_led_pins[] = {
- {
- .name = "nslu2:green:ready",
- .gpio = NSLU2_LED_GRN_GPIO,
- },
- {
- .name = "nslu2:red:status",
- .gpio = NSLU2_LED_RED_GPIO,
- },
- {
- .name = "nslu2:green:disk-1",
- .gpio = NSLU2_LED_DISK1_GPIO,
- .active_low = true,
- },
- {
- .name = "nslu2:green:disk-2",
- .gpio = NSLU2_LED_DISK2_GPIO,
- .active_low = true,
- },
-};
-
-static struct gpio_led_platform_data nslu2_led_data = {
- .num_leds = ARRAY_SIZE(nslu2_led_pins),
- .leds = nslu2_led_pins,
-};
-
-static struct platform_device nslu2_leds = {
- .name = "leds-gpio",
- .id = -1,
- .dev.platform_data = &nslu2_led_data,
-};
-
-static struct platform_device nslu2_i2c_gpio = {
- .name = "i2c-gpio",
- .id = 0,
- .dev = {
- .platform_data = NULL,
- },
-};
-
-static struct resource nslu2_beeper_resources[] = {
- {
- .start = IRQ_IXP4XX_TIMER2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device nslu2_beeper = {
- .name = "ixp4xx-beeper",
- .id = NSLU2_GPIO_BUZZ,
- .resource = nslu2_beeper_resources,
- .num_resources = ARRAY_SIZE(nslu2_beeper_resources),
-};
-
-static struct resource nslu2_uart_resources[] = {
- {
- .start = IXP4XX_UART1_BASE_PHYS,
- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- }
-};
-
-static struct plat_serial8250_port nslu2_uart_data[] = {
- {
- .mapbase = IXP4XX_UART1_BASE_PHYS,
- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { }
-};
-
-static struct platform_device nslu2_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev.platform_data = nslu2_uart_data,
- .num_resources = 2,
- .resource = nslu2_uart_resources,
-};
-
-/* Built-in 10/100 Ethernet MAC interfaces */
-static struct resource nslu2_eth_resources[] = {
- {
- .start = IXP4XX_EthB_BASE_PHYS,
- .end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct eth_plat_info nslu2_plat_eth[] = {
- {
- .phy = 1,
- .rxq = 3,
- .txreadyq = 20,
- }
-};
-
-static struct platform_device nslu2_eth[] = {
- {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEB,
- .dev.platform_data = nslu2_plat_eth,
- .num_resources = ARRAY_SIZE(nslu2_eth_resources),
- .resource = nslu2_eth_resources,
- }
-};
-
-static struct platform_device *nslu2_devices[] __initdata = {
- &nslu2_i2c_gpio,
- &nslu2_flash,
- &nslu2_beeper,
- &nslu2_leds,
- &nslu2_eth[0],
-};
-
-static void nslu2_power_off(void)
-{
- /* This causes the box to drop the power and go dead. */
-
- /* enable the pwr cntl gpio and assert power off */
- gpio_direction_output(NSLU2_PO_GPIO, 1);
-}
-
-static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
-{
- /* Signal init to do the ctrlaltdel action, this will bypass init if
- * it hasn't started and do a kernel_restart.
- */
- ctrl_alt_del();
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
-{
- /* This is the paper-clip reset, it shuts the machine down directly.
- */
- machine_power_off();
-
- return IRQ_HANDLED;
-}
-
-static int __init nslu2_gpio_init(void)
-{
- if (!machine_is_nslu2())
- return 0;
-
- /* Request the power off GPIO */
- return gpio_request(NSLU2_PO_GPIO, "power off");
-}
-device_initcall(nslu2_gpio_init);
-
-static void __init nslu2_timer_init(void)
-{
- /* The xtal on this machine is non-standard. */
- ixp4xx_timer_freq = NSLU2_FREQ;
-
- /* Call standard timer_init function. */
- ixp4xx_timer_init();
-}
-
-static void __init nslu2_init(void)
-{
- uint8_t __iomem *f;
- int i;
-
- ixp4xx_sys_init();
-
- nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- nslu2_flash_resource.end =
- IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
-
- gpiod_add_lookup_table(&nslu2_i2c_gpiod_table);
- i2c_register_board_info(0, nslu2_i2c_board_info,
- ARRAY_SIZE(nslu2_i2c_board_info));
-
- /*
- * This is only useful on a modified machine, but it is valuable
- * to have it first in order to see debug messages, and so that
- * it does *not* get removed if platform_add_devices fails!
- */
- (void)platform_device_register(&nslu2_uart);
-
- platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
-
- pm_power_off = nslu2_power_off;
-
- if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler,
- IRQF_TRIGGER_LOW, "NSLU2 reset button", NULL) < 0) {
-
- printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
- gpio_to_irq(NSLU2_RB_GPIO));
- }
-
- if (request_irq(gpio_to_irq(NSLU2_PB_GPIO), &nslu2_power_handler,
- IRQF_TRIGGER_HIGH, "NSLU2 power button", NULL) < 0) {
-
- printk(KERN_DEBUG "Power Button IRQ %d not available\n",
- gpio_to_irq(NSLU2_PB_GPIO));
- }
-
- /*
- * Map in a portion of the flash and read the MAC address.
- * Since it is stored in BE in the flash itself, we need to
- * byteswap it if we're in LE mode.
- */
- f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x40000);
- if (f) {
- for (i = 0; i < 6; i++)
-#ifdef __ARMEB__
- nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + i);
-#else
- nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + (i^3));
-#endif
- iounmap(f);
- }
- printk(KERN_INFO "NSLU2: Using MAC address %pM for port 0\n",
- nslu2_plat_eth[0].hwaddr);
-
-}
-
-MACHINE_START(NSLU2, "Linksys NSLU2")
- /* Maintainer: www.nslu2-linux.org */
- .atag_offset = 0x100,
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = nslu2_timer_init,
- .init_machine = nslu2_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/omixp-setup.c b/arch/arm/mach-ixp4xx/omixp-setup.c
deleted file mode 100644
index 8f2b8c473d7a..000000000000
--- a/arch/arm/mach-ixp4xx/omixp-setup.c
+++ /dev/null
@@ -1,298 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-ixp4xx/omixp-setup.c
- *
- * omicron ixp4xx board setup
- * Copyright (C) 2009 OMICRON electronics GmbH
- *
- * based nslu2-setup.c, ixdp425-setup.c:
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- */
-
-#include <linux/kernel.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/leds.h>
-
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#include <mach/hardware.h>
-
-#include "irqs.h"
-
-static struct resource omixp_flash_resources[] = {
- {
- .flags = IORESOURCE_MEM,
- }, {
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct mtd_partition omixp_partitions[] = {
- {
- .name = "Recovery Bootloader",
- .size = 0x00020000,
- .offset = 0,
- }, {
- .name = "Calibration Data",
- .size = 0x00020000,
- .offset = 0x00020000,
- }, {
- .name = "Recovery FPGA",
- .size = 0x00020000,
- .offset = 0x00040000,
- }, {
- .name = "Release Bootloader",
- .size = 0x00020000,
- .offset = 0x00060000,
- }, {
- .name = "Release FPGA",
- .size = 0x00020000,
- .offset = 0x00080000,
- }, {
- .name = "Kernel",
- .size = 0x00160000,
- .offset = 0x000a0000,
- }, {
- .name = "Filesystem",
- .size = 0x00C00000,
- .offset = 0x00200000,
- }, {
- .name = "Persistent Storage",
- .size = 0x00200000,
- .offset = 0x00E00000,
- },
-};
-
-static struct flash_platform_data omixp_flash_data[] = {
- {
- .map_name = "cfi_probe",
- .parts = omixp_partitions,
- .nr_parts = ARRAY_SIZE(omixp_partitions),
- }, {
- .map_name = "cfi_probe",
- .parts = NULL,
- .nr_parts = 0,
- },
-};
-
-static struct platform_device omixp_flash_device[] = {
- {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &omixp_flash_data[0],
- },
- .resource = &omixp_flash_resources[0],
- .num_resources = 1,
- }, {
- .name = "IXP4XX-Flash",
- .id = 1,
- .dev = {
- .platform_data = &omixp_flash_data[1],
- },
- .resource = &omixp_flash_resources[1],
- .num_resources = 1,
- },
-};
-
-/* Swap UART's - These boards have the console on UART2. The following
- * configuration is used:
- * ttyS0 .. UART2
- * ttyS1 .. UART1
- * This way standard images can be used with the kernel that expect
- * the console on ttyS0.
- */
-static struct resource omixp_uart_resources[] = {
- {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = IXP4XX_UART1_BASE_PHYS,
- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct plat_serial8250_port omixp_uart_data[] = {
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- }, {
- .mapbase = IXP4XX_UART1_BASE_PHYS,
- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- }, {
- /* list termination */
- }
-};
-
-static struct platform_device omixp_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev.platform_data = omixp_uart_data,
- .num_resources = 2,
- .resource = omixp_uart_resources,
-};
-
-static struct gpio_led mic256_led_pins[] = {
- {
- .name = "LED-A",
- .gpio = 7,
- },
-};
-
-static struct gpio_led_platform_data mic256_led_data = {
- .num_leds = ARRAY_SIZE(mic256_led_pins),
- .leds = mic256_led_pins,
-};
-
-static struct platform_device mic256_leds = {
- .name = "leds-gpio",
- .id = -1,
- .dev.platform_data = &mic256_led_data,
-};
-
-/* Built-in 10/100 Ethernet MAC interfaces */
-static struct resource ixp425_npeb_resources[] = {
- {
- .start = IXP4XX_EthB_BASE_PHYS,
- .end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct resource ixp425_npec_resources[] = {
- {
- .start = IXP4XX_EthC_BASE_PHYS,
- .end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct eth_plat_info ixdp425_plat_eth[] = {
- {
- .phy = 0,
- .rxq = 3,
- .txreadyq = 20,
- }, {
- .phy = 1,
- .rxq = 4,
- .txreadyq = 21,
- },
-};
-
-static struct platform_device ixdp425_eth[] = {
- {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEB,
- .dev.platform_data = ixdp425_plat_eth,
- .num_resources = ARRAY_SIZE(ixp425_npeb_resources),
- .resource = ixp425_npeb_resources,
- }, {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEC,
- .dev.platform_data = ixdp425_plat_eth + 1,
- .num_resources = ARRAY_SIZE(ixp425_npec_resources),
- .resource = ixp425_npec_resources,
- },
-};
-
-
-static struct platform_device *devixp_pldev[] __initdata = {
- &omixp_uart,
- &omixp_flash_device[0],
- &ixdp425_eth[0],
- &ixdp425_eth[1],
-};
-
-static struct platform_device *mic256_pldev[] __initdata = {
- &omixp_uart,
- &omixp_flash_device[0],
- &mic256_leds,
- &ixdp425_eth[0],
- &ixdp425_eth[1],
-};
-
-static struct platform_device *miccpt_pldev[] __initdata = {
- &omixp_uart,
- &omixp_flash_device[0],
- &omixp_flash_device[1],
- &ixdp425_eth[0],
- &ixdp425_eth[1],
-};
-
-static void __init omixp_init(void)
-{
- ixp4xx_sys_init();
-
- /* 16MiB Boot Flash */
- omixp_flash_resources[0].start = IXP4XX_EXP_BUS_BASE(0);
- omixp_flash_resources[0].end = IXP4XX_EXP_BUS_END(0);
-
- /* 32 MiB Data Flash */
- omixp_flash_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
- omixp_flash_resources[1].end = IXP4XX_EXP_BUS_END(2);
-
- if (machine_is_devixp())
- platform_add_devices(devixp_pldev, ARRAY_SIZE(devixp_pldev));
- else if (machine_is_miccpt())
- platform_add_devices(miccpt_pldev, ARRAY_SIZE(miccpt_pldev));
- else if (machine_is_mic256())
- platform_add_devices(mic256_pldev, ARRAY_SIZE(mic256_pldev));
-}
-
-#ifdef CONFIG_MACH_DEVIXP
-MACHINE_START(DEVIXP, "Omicron DEVIXP")
- .atag_offset = 0x100,
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .init_machine = omixp_init,
- .restart = ixp4xx_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_MICCPT
-MACHINE_START(MICCPT, "Omicron MICCPT")
- .atag_offset = 0x100,
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .init_machine = omixp_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_MIC256
-MACHINE_START(MIC256, "Omicron MIC256")
- .atag_offset = 0x100,
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .init_machine = omixp_init,
- .restart = ixp4xx_restart,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-ixp4xx/vulcan-pci.c b/arch/arm/mach-ixp4xx/vulcan-pci.c
deleted file mode 100644
index caf53922dd3f..000000000000
--- a/arch/arm/mach-ixp4xx/vulcan-pci.c
+++ /dev/null
@@ -1,70 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arch/mach-ixp4xx/vulcan-pci.c
- *
- * Vulcan board-level PCI initialization
- *
- * Copyright (C) 2010 Marc Zyngier <maz@misterjones.org>
- *
- * based on ixdp425-pci.c:
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-#include "irqs.h"
-
-/* PCI controller GPIO to IRQ pin mappings */
-#define INTA 2
-#define INTB 3
-
-void __init vulcan_pci_preinit(void)
-{
-#ifndef CONFIG_IXP4XX_INDIRECT_PCI
- /*
- * Cardbus bridge wants way more than the SoC can actually offer,
- * and leaves the whole PCI bus in a mess. Artificially limit it
- * to 8MB per region. Of course indirect mode doesn't have this
- * limitation...
- */
- pci_cardbus_mem_size = SZ_8M;
- pr_info("Vulcan PCI: limiting CardBus memory size to %dMB\n",
- (int)(pci_cardbus_mem_size >> 20));
-#endif
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
- ixp4xx_pci_preinit();
-}
-
-static int __init vulcan_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- if (slot == 1)
- return IXP4XX_GPIO_IRQ(INTA);
-
- if (slot == 2)
- return IXP4XX_GPIO_IRQ(INTB);
-
- return -1;
-}
-
-struct hw_pci vulcan_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = vulcan_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = vulcan_map_irq,
-};
-
-int __init vulcan_pci_init(void)
-{
- if (machine_is_arcom_vulcan())
- pci_common_init(&vulcan_pci);
- return 0;
-}
-
-subsys_initcall(vulcan_pci_init);
diff --git a/arch/arm/mach-ixp4xx/vulcan-setup.c b/arch/arm/mach-ixp4xx/vulcan-setup.c
deleted file mode 100644
index e506d2af98ad..000000000000
--- a/arch/arm/mach-ixp4xx/vulcan-setup.c
+++ /dev/null
@@ -1,282 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/arm/mach-ixp4xx/vulcan-setup.c
- *
- * Arcom/Eurotech Vulcan board-setup
- *
- * Copyright (C) 2010 Marc Zyngier <maz@misterjones.org>
- *
- * based on fsg-setup.c:
- * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
- */
-
-#include <linux/if_ether.h>
-#include <linux/irq.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/io.h>
-#include <linux/w1-gpio.h>
-#include <linux/gpio/machine.h>
-#include <linux/mtd/plat-ram.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#include "irqs.h"
-
-static struct flash_platform_data vulcan_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource vulcan_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device vulcan_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &vulcan_flash_data,
- },
- .resource = &vulcan_flash_resource,
- .num_resources = 1,
-};
-
-static struct platdata_mtd_ram vulcan_sram_data = {
- .mapname = "Vulcan SRAM",
- .bankwidth = 1,
-};
-
-static struct resource vulcan_sram_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device vulcan_sram = {
- .name = "mtd-ram",
- .id = 0,
- .dev = {
- .platform_data = &vulcan_sram_data,
- },
- .resource = &vulcan_sram_resource,
- .num_resources = 1,
-};
-
-static struct resource vulcan_uart_resources[] = {
- [0] = {
- .start = IXP4XX_UART1_BASE_PHYS,
- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct plat_serial8250_port vulcan_uart_data[] = {
- [0] = {
- .mapbase = IXP4XX_UART1_BASE_PHYS,
- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- [1] = {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- [2] = {
- .irq = IXP4XX_GPIO_IRQ(4),
- .irqflags = IRQF_TRIGGER_LOW,
- .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .uartclk = 1843200,
- },
- [3] = {
- .irq = IXP4XX_GPIO_IRQ(4),
- .irqflags = IRQF_TRIGGER_LOW,
- .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .uartclk = 1843200,
- },
- { }
-};
-
-static struct platform_device vulcan_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = vulcan_uart_data,
- },
- .resource = vulcan_uart_resources,
- .num_resources = ARRAY_SIZE(vulcan_uart_resources),
-};
-
-static struct resource vulcan_npeb_resources[] = {
- {
- .start = IXP4XX_EthB_BASE_PHYS,
- .end = IXP4XX_EthB_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct resource vulcan_npec_resources[] = {
- {
- .start = IXP4XX_EthC_BASE_PHYS,
- .end = IXP4XX_EthC_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct eth_plat_info vulcan_plat_eth[] = {
- [0] = {
- .phy = 0,
- .rxq = 3,
- .txreadyq = 20,
- },
- [1] = {
- .phy = 1,
- .rxq = 4,
- .txreadyq = 21,
- },
-};
-
-static struct platform_device vulcan_eth[] = {
- [0] = {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEB,
- .dev = {
- .platform_data = &vulcan_plat_eth[0],
- },
- .num_resources = ARRAY_SIZE(vulcan_npeb_resources),
- .resource = vulcan_npeb_resources,
- },
- [1] = {
- .name = "ixp4xx_eth",
- .id = IXP4XX_ETH_NPEC,
- .dev = {
- .platform_data = &vulcan_plat_eth[1],
- },
- .num_resources = ARRAY_SIZE(vulcan_npec_resources),
- .resource = vulcan_npec_resources,
- },
-};
-
-static struct resource vulcan_max6369_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device vulcan_max6369 = {
- .name = "max6369_wdt",
- .id = -1,
- .resource = &vulcan_max6369_resource,
- .num_resources = 1,
-};
-
-static struct gpiod_lookup_table vulcan_w1_gpiod_table = {
- .dev_id = "w1-gpio",
- .table = {
- GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", 14, NULL, 0,
- GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
- },
-};
-
-static struct w1_gpio_platform_data vulcan_w1_gpio_pdata = {
- /* Intentionally left blank */
-};
-
-static struct platform_device vulcan_w1_gpio = {
- .name = "w1-gpio",
- .id = 0,
- .dev = {
- .platform_data = &vulcan_w1_gpio_pdata,
- },
-};
-
-static struct platform_device *vulcan_devices[] __initdata = {
- &vulcan_uart,
- &vulcan_flash,
- &vulcan_sram,
- &vulcan_max6369,
- &vulcan_eth[0],
- &vulcan_eth[1],
- &vulcan_w1_gpio,
-};
-
-static void __init vulcan_init(void)
-{
- ixp4xx_sys_init();
-
- /* Flash is spread over both CS0 and CS1 */
- vulcan_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- vulcan_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
- *IXP4XX_EXP_CS0 = IXP4XX_EXP_BUS_CS_EN |
- IXP4XX_EXP_BUS_STROBE_T(3) |
- IXP4XX_EXP_BUS_SIZE(0xF) |
- IXP4XX_EXP_BUS_BYTE_RD16 |
- IXP4XX_EXP_BUS_WR_EN;
- *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
-
- /* SRAM on CS2, (256kB, 8bit, writable) */
- vulcan_sram_resource.start = IXP4XX_EXP_BUS_BASE(2);
- vulcan_sram_resource.end = IXP4XX_EXP_BUS_BASE(2) + SZ_256K - 1;
- *IXP4XX_EXP_CS2 = IXP4XX_EXP_BUS_CS_EN |
- IXP4XX_EXP_BUS_STROBE_T(1) |
- IXP4XX_EXP_BUS_HOLD_T(2) |
- IXP4XX_EXP_BUS_SIZE(9) |
- IXP4XX_EXP_BUS_SPLT_EN |
- IXP4XX_EXP_BUS_WR_EN |
- IXP4XX_EXP_BUS_BYTE_EN;
-
- /* XR16L2551 on CS3 (Moto style, 512 bytes, 8bits, writable) */
- vulcan_uart_resources[2].start = IXP4XX_EXP_BUS_BASE(3);
- vulcan_uart_resources[2].end = IXP4XX_EXP_BUS_BASE(3) + 16 - 1;
- vulcan_uart_data[2].mapbase = vulcan_uart_resources[2].start;
- vulcan_uart_data[3].mapbase = vulcan_uart_data[2].mapbase + 8;
- *IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
- IXP4XX_EXP_BUS_STROBE_T(3) |
- IXP4XX_EXP_BUS_CYCLES(IXP4XX_EXP_BUS_CYCLES_MOTOROLA)|
- IXP4XX_EXP_BUS_WR_EN |
- IXP4XX_EXP_BUS_BYTE_EN;
-
- /* GPIOS on CS4 (512 bytes, 8bits, writable) */
- *IXP4XX_EXP_CS4 = IXP4XX_EXP_BUS_CS_EN |
- IXP4XX_EXP_BUS_WR_EN |
- IXP4XX_EXP_BUS_BYTE_EN;
-
- /* max6369 on CS5 (512 bytes, 8bits, writable) */
- vulcan_max6369_resource.start = IXP4XX_EXP_BUS_BASE(5);
- vulcan_max6369_resource.end = IXP4XX_EXP_BUS_BASE(5);
- *IXP4XX_EXP_CS5 = IXP4XX_EXP_BUS_CS_EN |
- IXP4XX_EXP_BUS_WR_EN |
- IXP4XX_EXP_BUS_BYTE_EN;
-
- gpiod_add_lookup_table(&vulcan_w1_gpiod_table);
- platform_add_devices(vulcan_devices, ARRAY_SIZE(vulcan_devices));
-}
-
-MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
- /* Maintainer: Marc Zyngier <maz@misterjones.org> */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = vulcan_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c
deleted file mode 100644
index 1247e7c67bc0..000000000000
--- a/arch/arm/mach-ixp4xx/wg302v2-pci.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arch/mach-ixp4xx/wg302v2-pci.c
- *
- * PCI setup routines for the Netgear WG302 v2 and WAG302 v2
- *
- * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
- *
- * based on coyote-pci.c:
- * Copyright (C) 2002 Jungo Software Technologies.
- * Copyright (C) 2003 MontaVista Software, Inc.
- *
- * Maintainer: Imre Kaloz <kaloz@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-
-#include <asm/mach/pci.h>
-
-#include "irqs.h"
-
-void __init wg302v2_pci_preinit(void)
-{
- irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
- irq_set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
-
- ixp4xx_pci_preinit();
-}
-
-static int __init wg302v2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- if (slot == 1)
- return IRQ_IXP4XX_GPIO8;
- else if (slot == 2)
- return IRQ_IXP4XX_GPIO9;
- else return -1;
-}
-
-struct hw_pci wg302v2_pci __initdata = {
- .nr_controllers = 1,
- .ops = &ixp4xx_ops,
- .preinit = wg302v2_pci_preinit,
- .setup = ixp4xx_setup,
- .map_irq = wg302v2_map_irq,
-};
-
-int __init wg302v2_pci_init(void)
-{
- if (machine_is_wg302v2())
- pci_common_init(&wg302v2_pci);
- return 0;
-}
-
-subsys_initcall(wg302v2_pci_init);
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
deleted file mode 100644
index 8711e299229b..000000000000
--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c
+++ /dev/null
@@ -1,114 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/arm/mach-ixp4xx/wg302-setup.c
- *
- * Board setup for the Netgear WG302 v2 and WAG302 v2
- *
- * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org>
- *
- * based on coyote-setup.c:
- * Copyright (C) 2003-2005 MontaVista Software, Inc.
- *
- * Author: Imre Kaloz <kaloz@openwrt.org>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#include "irqs.h"
-
-static struct flash_platform_data wg302v2_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource wg302v2_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device wg302v2_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &wg302v2_flash_data,
- },
- .num_resources = 1,
- .resource = &wg302v2_flash_resource,
-};
-
-static struct resource wg302v2_uart_resource = {
- .start = IXP4XX_UART2_BASE_PHYS,
- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct plat_serial8250_port wg302v2_uart_data[] = {
- {
- .mapbase = IXP4XX_UART2_BASE_PHYS,
- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- },
- { },
-};
-
-static struct platform_device wg302v2_uart = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = wg302v2_uart_data,
- },
- .num_resources = 1,
- .resource = &wg302v2_uart_resource,
-};
-
-static struct platform_device *wg302v2_devices[] __initdata = {
- &wg302v2_flash,
- &wg302v2_uart,
-};
-
-static void __init wg302v2_init(void)
-{
- ixp4xx_sys_init();
-
- wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
- wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
-
- *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
- *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
-
- platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices));
-}
-
-#ifdef CONFIG_MACH_WG302V2
-MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
- /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
- .map_io = ixp4xx_map_io,
- .init_early = ixp4xx_init_early,
- .init_irq = ixp4xx_init_irq,
- .init_time = ixp4xx_timer_init,
- .atag_offset = 0x100,
- .init_machine = wg302v2_init,
-#if defined(CONFIG_PCI)
- .dma_zone_size = SZ_64M,
-#endif
- .restart = ixp4xx_restart,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 7df8f5276ddf..7f13adf26e61 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -181,18 +181,6 @@ config SOC_TI81XX
depends on ARCH_OMAP3
default y
-config OMAP_PACKAGE_CBC
- bool
-
-config OMAP_PACKAGE_CBB
- bool
-
-config OMAP_PACKAGE_CUS
- bool
-
-config OMAP_PACKAGE_CBP
- bool
-
comment "OMAP Legacy Platform Data Board Type"
depends on ARCH_OMAP2PLUS
@@ -204,17 +192,6 @@ config MACH_OMAP2_TUSB6010
depends on ARCH_OMAP2 && SOC_OMAP2420
default y if MACH_NOKIA_N8X0
-config MACH_OMAP3517EVM
- bool "OMAP3517/ AM3517 EVM board"
- depends on ARCH_OMAP3
- default y
-
-config MACH_OMAP3_PANDORA
- bool "OMAP3 Pandora"
- depends on ARCH_OMAP3
- default y
- select OMAP_PACKAGE_CBB
-
config MACH_NOKIA_N810
bool
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 71c1d18aafbc..d73c7b692116 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -26,7 +26,6 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/omap-gpmc.h>
#include <trace/events/power.h>
@@ -81,8 +80,6 @@ static void omap3_core_save_context(void)
/* Save the Interrupt controller context */
omap_intc_save_context();
- /* Save the GPMC context */
- omap3_gpmc_save_context();
/* Save the system control module context, padconf already save above*/
omap3_control_save_context();
}
@@ -91,8 +88,6 @@ static void omap3_core_restore_context(void)
{
/* Restore the control module context, padconf restored by h/w */
omap3_control_restore_context();
- /* Restore the GPMC context */
- omap3_gpmc_restore_context();
/* Restore the interrupt controller context */
omap_intc_restore_context();
}
diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c
index 827b50f1c73e..53813f9464a2 100644
--- a/arch/arm/mach-rpc/ecard.c
+++ b/arch/arm/mach-rpc/ecard.c
@@ -1052,7 +1052,7 @@ static int ecard_drv_probe(struct device *dev)
return ret;
}
-static int ecard_drv_remove(struct device *dev)
+static void ecard_drv_remove(struct device *dev)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct ecard_driver *drv = ECARD_DRV(dev->driver);
@@ -1067,8 +1067,6 @@ static int ecard_drv_remove(struct device *dev)
ec->ops = &ecard_default_ops;
barrier();
ec->irq_data = NULL;
-
- return 0;
}
/*
diff --git a/arch/arm/mach-rpc/io-acorn.S b/arch/arm/mach-rpc/io-acorn.S
index b9082a2a2a01..aa9bf0d771c0 100644
--- a/arch/arm/mach-rpc/io-acorn.S
+++ b/arch/arm/mach-rpc/io-acorn.S
@@ -25,4 +25,4 @@ ENTRY(insl)
ENTRY(outsl)
adr r0, .Liosl_warning
mov r1, lr
- b printk
+ b _printk
diff --git a/arch/arm/mach-s3c/mach-gta02.c b/arch/arm/mach-s3c/mach-gta02.c
index aec8b451c016..418939ce0fc3 100644
--- a/arch/arm/mach-s3c/mach-gta02.c
+++ b/arch/arm/mach-s3c/mach-gta02.c
@@ -79,13 +79,12 @@ static struct pcf50633 *gta02_pcf;
static long gta02_panic_blink(int state)
{
- long delay = 0;
char led;
led = (state) ? 1 : 0;
gpio_direction_output(GTA02_GPIO_AUX_LED, led);
- return delay;
+ return 0;
}
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index b5c990a7a5af..18d37f90cdfe 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -36,7 +36,7 @@ static struct gpiod_lookup_table wifi_gpio_lookup = {
void __init tegra_paz00_wifikill_init(void)
{
- platform_device_add_properties(&wifi_rfkill_device, wifi_rfkill_prop);
+ device_create_managed_software_node(&wifi_rfkill_device.dev, wifi_rfkill_prop, NULL);
gpiod_add_lookup_table(&wifi_gpio_lookup);
platform_device_register(&wifi_rfkill_device);
}
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 6452ebf68d40..b21f51b8e19e 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -403,7 +403,7 @@ static const struct platform_suspend_ops tegra_suspend_ops = {
.enter = tegra_suspend_enter,
};
-void __init tegra_init_suspend(void)
+void tegra_pm_init_suspend(void)
{
enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 81525f5f4a44..e63f96de2825 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -25,10 +25,4 @@ void tegra30_sleep_core_init(void);
extern void (*tegra_tear_down_cpu)(void);
-#ifdef CONFIG_PM_SLEEP
-void tegra_init_suspend(void);
-#else
-static inline void tegra_init_suspend(void) {}
-#endif
-
#endif /* _MACH_TEGRA_PM_H_ */
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index c011359bcdb4..ab5008f35803 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -84,8 +84,6 @@ static void __init tegra_dt_init(void)
static void __init tegra_dt_init_late(void)
{
- tegra_init_suspend();
-
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
of_machine_is_compatible("compal,paz00"))
tegra_paz00_wifikill_init();
diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c
index 6bfd2b884505..cfd9c933d2f0 100644
--- a/arch/arm/mm/dma-mapping-nommu.c
+++ b/arch/arm/mm/dma-mapping-nommu.c
@@ -5,12 +5,7 @@
* Copyright (C) 2000-2004 Russell King
*/
-#include <linux/export.h>
-#include <linux/mm.h>
-#include <linux/dma-direct.h>
#include <linux/dma-map-ops.h>
-#include <linux/scatterlist.h>
-
#include <asm/cachetype.h>
#include <asm/cacheflush.h>
#include <asm/outercache.h>
@@ -18,65 +13,8 @@
#include "dma.h"
-/*
- * The generic direct mapping code is used if
- * - MMU/MPU is off
- * - cpu is v7m w/o cache support
- * - device is coherent
- * otherwise arm_nommu_dma_ops is used.
- *
- * arm_nommu_dma_ops rely on consistent DMA memory (please, refer to
- * [1] on how to declare such memory).
- *
- * [1] Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
- */
-
-static void *arm_nommu_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp,
- unsigned long attrs)
-
-{
- void *ret = dma_alloc_from_global_coherent(dev, size, dma_handle);
-
- /*
- * dma_alloc_from_global_coherent() may fail because:
- *
- * - no consistent DMA region has been defined, so we can't
- * continue.
- * - there is no space left in consistent DMA region, so we
- * only can fallback to generic allocator if we are
- * advertised that consistency is not required.
- */
-
- WARN_ON_ONCE(ret == NULL);
- return ret;
-}
-
-static void arm_nommu_dma_free(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_addr,
- unsigned long attrs)
-{
- int ret = dma_release_from_global_coherent(get_order(size), cpu_addr);
-
- WARN_ON_ONCE(ret == 0);
-}
-
-static int arm_nommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
- void *cpu_addr, dma_addr_t dma_addr, size_t size,
- unsigned long attrs)
-{
- int ret;
-
- if (dma_mmap_from_global_coherent(vma, cpu_addr, size, &ret))
- return ret;
- if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
- return ret;
- return -ENXIO;
-}
-
-
-static void __dma_page_cpu_to_dev(phys_addr_t paddr, size_t size,
- enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir)
{
dmac_map_area(__va(paddr), size, dir);
@@ -86,8 +24,8 @@ static void __dma_page_cpu_to_dev(phys_addr_t paddr, size_t size,
outer_clean_range(paddr, paddr + size);
}
-static void __dma_page_dev_to_cpu(phys_addr_t paddr, size_t size,
- enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir)
{
if (dir != DMA_TO_DEVICE) {
outer_inv_range(paddr, paddr + size);
@@ -95,102 +33,6 @@ static void __dma_page_dev_to_cpu(phys_addr_t paddr, size_t size,
}
}
-static dma_addr_t arm_nommu_dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- unsigned long attrs)
-{
- dma_addr_t handle = page_to_phys(page) + offset;
-
- __dma_page_cpu_to_dev(handle, size, dir);
-
- return handle;
-}
-
-static void arm_nommu_dma_unmap_page(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir,
- unsigned long attrs)
-{
- __dma_page_dev_to_cpu(handle, size, dir);
-}
-
-
-static int arm_nommu_dma_map_sg(struct device *dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction dir,
- unsigned long attrs)
-{
- int i;
- struct scatterlist *sg;
-
- for_each_sg(sgl, sg, nents, i) {
- sg_dma_address(sg) = sg_phys(sg);
- sg_dma_len(sg) = sg->length;
- __dma_page_cpu_to_dev(sg_dma_address(sg), sg_dma_len(sg), dir);
- }
-
- return nents;
-}
-
-static void arm_nommu_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction dir,
- unsigned long attrs)
-{
- struct scatterlist *sg;
- int i;
-
- for_each_sg(sgl, sg, nents, i)
- __dma_page_dev_to_cpu(sg_dma_address(sg), sg_dma_len(sg), dir);
-}
-
-static void arm_nommu_dma_sync_single_for_device(struct device *dev,
- dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
- __dma_page_cpu_to_dev(handle, size, dir);
-}
-
-static void arm_nommu_dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
- __dma_page_cpu_to_dev(handle, size, dir);
-}
-
-static void arm_nommu_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction dir)
-{
- struct scatterlist *sg;
- int i;
-
- for_each_sg(sgl, sg, nents, i)
- __dma_page_cpu_to_dev(sg_dma_address(sg), sg_dma_len(sg), dir);
-}
-
-static void arm_nommu_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction dir)
-{
- struct scatterlist *sg;
- int i;
-
- for_each_sg(sgl, sg, nents, i)
- __dma_page_dev_to_cpu(sg_dma_address(sg), sg_dma_len(sg), dir);
-}
-
-const struct dma_map_ops arm_nommu_dma_ops = {
- .alloc = arm_nommu_dma_alloc,
- .free = arm_nommu_dma_free,
- .alloc_pages = dma_direct_alloc_pages,
- .free_pages = dma_direct_free_pages,
- .mmap = arm_nommu_dma_mmap,
- .map_page = arm_nommu_dma_map_page,
- .unmap_page = arm_nommu_dma_unmap_page,
- .map_sg = arm_nommu_dma_map_sg,
- .unmap_sg = arm_nommu_dma_unmap_sg,
- .sync_single_for_device = arm_nommu_dma_sync_single_for_device,
- .sync_single_for_cpu = arm_nommu_dma_sync_single_for_cpu,
- .sync_sg_for_device = arm_nommu_dma_sync_sg_for_device,
- .sync_sg_for_cpu = arm_nommu_dma_sync_sg_for_cpu,
-};
-EXPORT_SYMBOL(arm_nommu_dma_ops);
-
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
const struct iommu_ops *iommu, bool coherent)
{
@@ -201,14 +43,11 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
* enough to check if MPU is in use or not since in absense of
* MPU system memory map is used.
*/
- dev->archdata.dma_coherent = (cacheid) ? coherent : true;
+ dev->dma_coherent = cacheid ? coherent : true;
} else {
/*
* Assume coherent DMA in case MMU/MPU has not been set up.
*/
- dev->archdata.dma_coherent = (get_cr() & CR_M) ? coherent : true;
+ dev->dma_coherent = (get_cr() & CR_M) ? coherent : true;
}
-
- if (!dev->archdata.dma_coherent)
- set_dma_ops(dev, &arm_nommu_dma_ops);
}
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index c4b8df2ad328..4b61541853ea 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -980,7 +980,7 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
{
const struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
- int i, j;
+ int i, j, ret;
for_each_sg(sg, s, nents, i) {
#ifdef CONFIG_NEED_SG_DMA_LENGTH
@@ -988,15 +988,17 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
#endif
s->dma_address = ops->map_page(dev, sg_page(s), s->offset,
s->length, dir, attrs);
- if (dma_mapping_error(dev, s->dma_address))
+ if (dma_mapping_error(dev, s->dma_address)) {
+ ret = -EIO;
goto bad_mapping;
+ }
}
return nents;
bad_mapping:
for_each_sg(sg, s, i, j)
ops->unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, attrs);
- return 0;
+ return ret;
}
/**
@@ -1622,7 +1624,7 @@ static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
bool is_coherent)
{
struct scatterlist *s = sg, *dma = sg, *start = sg;
- int i, count = 0;
+ int i, count = 0, ret;
unsigned int offset = s->offset;
unsigned int size = s->offset + s->length;
unsigned int max = dma_get_max_seg_size(dev);
@@ -1630,12 +1632,13 @@ static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
for (i = 1; i < nents; i++) {
s = sg_next(s);
- s->dma_address = DMA_MAPPING_ERROR;
s->dma_length = 0;
if (s->offset || (size & ~PAGE_MASK) || size + s->length > max) {
- if (__map_sg_chunk(dev, start, size, &dma->dma_address,
- dir, attrs, is_coherent) < 0)
+ ret = __map_sg_chunk(dev, start, size,
+ &dma->dma_address, dir, attrs,
+ is_coherent);
+ if (ret < 0)
goto bad_mapping;
dma->dma_address += offset;
@@ -1648,8 +1651,9 @@ static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
}
size += s->length;
}
- if (__map_sg_chunk(dev, start, size, &dma->dma_address, dir, attrs,
- is_coherent) < 0)
+ ret = __map_sg_chunk(dev, start, size, &dma->dma_address, dir, attrs,
+ is_coherent);
+ if (ret < 0)
goto bad_mapping;
dma->dma_address += offset;
@@ -1660,7 +1664,9 @@ static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
bad_mapping:
for_each_sg(sg, s, count, i)
__iommu_remove_mapping(dev, sg_dma_address(s), sg_dma_len(s));
- return 0;
+ if (ret == -ENOMEM)
+ return ret;
+ return -EINVAL;
}
/**
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 6d89db7895d1..7ff9feea13a6 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -346,39 +346,6 @@ void flush_dcache_page(struct page *page)
EXPORT_SYMBOL(flush_dcache_page);
/*
- * Ensure cache coherency for the kernel mapping of this page. We can
- * assume that the page is pinned via kmap.
- *
- * If the page only exists in the page cache and there are no user
- * space mappings, this is a no-op since the page was already marked
- * dirty at creation. Otherwise, we need to flush the dirty kernel
- * cache lines directly.
- */
-void flush_kernel_dcache_page(struct page *page)
-{
- if (cache_is_vivt() || cache_is_vipt_aliasing()) {
- struct address_space *mapping;
-
- mapping = page_mapping_file(page);
-
- if (!mapping || mapping_mapped(mapping)) {
- void *addr;
-
- addr = page_address(page);
- /*
- * kmap_atomic() doesn't set the page virtual
- * address for highmem pages, and
- * kunmap_atomic() takes care of cache
- * flushing already.
- */
- if (!IS_ENABLED(CONFIG_HIGHMEM) || addr)
- __cpuc_flush_dcache_area(addr, PAGE_SIZE);
- }
- }
-}
-EXPORT_SYMBOL(flush_kernel_dcache_page);
-
-/*
* Flush an anonymous page so that users of get_user_pages()
* can safely access the data. The expected sequence is:
*
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 8b3d7191e2b8..2658f52903da 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -166,12 +166,6 @@ void flush_dcache_page(struct page *page)
}
EXPORT_SYMBOL(flush_dcache_page);
-void flush_kernel_dcache_page(struct page *page)
-{
- __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
-}
-EXPORT_SYMBOL(flush_kernel_dcache_page);
-
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long uaddr, void *dst, const void *src,
unsigned long len)
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index c5df1179fc5d..7e0a9b692d87 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -147,7 +147,7 @@
131 common quotactl sys_quotactl
132 common getpgid sys_getpgid
133 common fchdir sys_fchdir
-134 common bdflush sys_bdflush
+134 common bdflush sys_ni_syscall
135 common sysfs sys_sysfs
136 common personality sys_personality
# 137 was sys_afs_syscall
@@ -460,3 +460,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index d5837bf05a9a..6f7926c9c179 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -23,7 +23,7 @@
#ifdef DEBUG
stmfd sp!, {r0-r3, ip, lr}
ldr r0, =1f
- bl printk
+ bl _printk
ldmfd sp!, {r0-r3, ip, lr}
.pushsection .rodata, "a"
@@ -38,7 +38,7 @@
stmfd sp!, {r0-r3, ip, lr}
mov r1, \arg
ldr r0, =1f
- bl printk
+ bl _printk
ldmfd sp!, {r0-r3, ip, lr}
.pushsection .rodata, "a"
@@ -55,7 +55,7 @@
mov r2, \arg2
mov r1, \arg1
ldr r0, =1f
- bl printk
+ bl _printk
ldmfd sp!, {r0-r3, ip, lr}
.pushsection .rodata, "a"
diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild
index 7b393cfec071..ea7ab4ca81f9 100644
--- a/arch/arm64/Kbuild
+++ b/arch/arm64/Kbuild
@@ -2,4 +2,5 @@
obj-y += kernel/ mm/ net/
obj-$(CONFIG_KVM) += kvm/
obj-$(CONFIG_XEN) += xen/
+obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/
obj-$(CONFIG_CRYPTO) += crypto/
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 62c3c1d2190f..077f2ec4eeb2 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -130,8 +130,6 @@ config ARM64
select GENERIC_PTDUMP
select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL
select GENERIC_GETTIMEOFDAY
select GENERIC_VDSO_TIME_NS
@@ -222,6 +220,7 @@ config ARM64
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
select HAVE_ARCH_USERFAULTFD_MINOR if USERFAULTFD
+ select TRACE_IRQFLAGS_SUPPORT
help
ARM 64-bit (AArch64) Linux support.
@@ -289,9 +288,6 @@ config ILLEGAL_POINTER_VALUE
config LOCKDEP_SUPPORT
def_bool y
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config GENERIC_BUG
def_bool y
depends on BUG
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 1110d386f3b4..c744b1e7b356 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -157,8 +157,11 @@ Image: vmlinux
Image.%: Image
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
-zinstall install:
- $(Q)$(MAKE) $(build)=$(boot) $@
+install: install-image := Image
+zinstall: install-image := Image.gz
+install zinstall:
+ $(CONFIG_SHELL) $(srctree)/$(boot)/install.sh $(KERNELRELEASE) \
+ $(boot)/$(install-image) System.map "$(INSTALL_PATH)"
PHONY += vdso_install
vdso_install:
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
index cd3414898d10..ebe80faab883 100644
--- a/arch/arm64/boot/Makefile
+++ b/arch/arm64/boot/Makefile
@@ -35,11 +35,3 @@ $(obj)/Image.lzma: $(obj)/Image FORCE
$(obj)/Image.lzo: $(obj)/Image FORCE
$(call if_changed,lzo)
-
-install:
- $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
- $(obj)/Image System.map "$(INSTALL_PATH)"
-
-zinstall:
- $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
- $(obj)/Image.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts
index be81330db14f..8f2a80f128de 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts
@@ -32,14 +32,21 @@
};
};
- reg_vcc3v3: vcc3v3 {
+ reg_vcc1v8: regulator-vcc1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_vcc3v3: regulator-vcc3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
- reg_vdd_cpu_gpu: vdd-cpu-gpu {
+ reg_vdd_cpu_gpu: regulator-vdd-cpu-gpu {
compatible = "regulator-fixed";
regulator-name = "vdd-cpu-gpu";
regulator-min-microvolt = <1135000>;
@@ -91,6 +98,16 @@
status = "okay";
};
+&mmc2 {
+ vmmc-supply = <&reg_vcc3v3>;
+ vqmmc-supply = <&reg_vcc1v8>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-hw-reset;
+ mmc-hs200-1_8v;
+ status = "okay";
+};
+
&ohci0 {
status = "okay";
};
@@ -99,6 +116,12 @@
status = "okay";
};
+&pio {
+ vcc-pc-supply = <&reg_vcc1v8>;
+ vcc-pd-supply = <&reg_vcc3v3>;
+ vcc-pg-supply = <&reg_vcc1v8>;
+};
+
&r_ir {
linux,rc-map-name = "rc-tanix-tx5max";
status = "okay";
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
index 7273eed5292c..7d94160f5802 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
@@ -385,9 +385,20 @@
/* Bluetooth on AP6212 */
&uart_A {
- status = "disabled";
+ status = "okay";
pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
pinctrl-names = "default";
+ uart-has-rtscts;
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ clocks = <&wifi_32k>;
+ clock-names = "lpo";
+ vbat-supply = <&vddio_ao3v3>;
+ vddio-supply = <&vddio_ao18>;
+ host-wakeup-gpios = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio GPIOX_20 GPIO_ACTIVE_HIGH>;
+ };
};
/* 40-pin CON1 */
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 9b0b81f191f1..66daf3af34c3 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -4,6 +4,7 @@
*/
#include "meson-gxbb.dtsi"
+#include <dt-bindings/sound/meson-aiu.h>
/ {
compatible = "tronsmart,vega-s95", "amlogic,meson-gxbb";
@@ -17,6 +18,13 @@
stdout-path = "serial0:115200n8";
};
+ spdif_dit: audio-codec-0 {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ status = "okay";
+ sound-name-prefix = "DIT";
+ };
+
leds {
compatible = "gpio-leds";
@@ -97,6 +105,59 @@
clocks = <&wifi32k>;
clock-names = "ext_clock";
};
+
+ sound {
+ compatible = "amlogic,gx-sound-card";
+ model = "VEGA-S95";
+ assigned-clocks = <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>,
+ <&clkc CLKID_MPLL2>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+ status = "okay";
+
+ dai-link-0 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+ dai-format = "i2s";
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+ };
+ };
+
+ dai-link-3 {
+ sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>;
+
+ codec-0 {
+ sound-dai = <&spdif_dit>;
+ };
+ };
+
+ dai-link-4 {
+ sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+ codec-0 {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+};
+
+&aiu {
+ status = "okay";
+ pinctrl-0 = <&spdif_out_y_pins>;
+ pinctrl-names = "default";
};
&cec_AO {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
index 60feac0179c0..6ab1cc125b96 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
@@ -218,6 +218,8 @@
};
&sd_emmc_a {
+ max-frequency = <100000000>;
+
brcmf: wifi@1 {
reg = <1>;
compatible = "brcm,bcm4329-fmac";
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
index 18a4b7a6c5df..86bdc0baf032 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
@@ -307,7 +307,8 @@
#size-cells = <0>;
bus-width = <4>;
- max-frequency = <60000000>;
+ cap-sd-highspeed;
+ max-frequency = <100000000>;
non-removable;
disable-wp;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
index dfa7a37a1281..236c0a144142 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
@@ -10,6 +10,7 @@
/dts-v1/;
#include "meson-gxm.dtsi"
+#include <dt-bindings/sound/meson-aiu.h>
/ {
compatible = "nexbox,a1", "amlogic,s912", "amlogic,meson-gxm";
@@ -24,6 +25,13 @@
stdout-path = "serial0:115200n8";
};
+ spdif_dit: audio-codec-0 {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ status = "okay";
+ sound-name-prefix = "DIT";
+ };
+
memory@0 {
device_type = "memory";
reg = <0x0 0x0 0x0 0x80000000>;
@@ -75,6 +83,59 @@
};
};
};
+
+ sound {
+ compatible = "amlogic,gx-sound-card";
+ model = "NEXBOX-A1";
+ assigned-clocks = <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>,
+ <&clkc CLKID_MPLL2>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+ status = "okay";
+
+ dai-link-0 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+ dai-format = "i2s";
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+ };
+ };
+
+ dai-link-3 {
+ sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>;
+
+ codec-0 {
+ sound-dai = <&spdif_dit>;
+ };
+ };
+
+ dai-link-4 {
+ sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+ codec-0 {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+};
+
+&aiu {
+ status = "okay";
+ pinctrl-0 = <&spdif_out_h_pins>;
+ pinctrl-names = "default";
};
&cec_AO {
diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
index 18a912eee360..6a6f7dd1d65c 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
@@ -52,6 +52,38 @@
#address-cells = <1>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ core2 {
+ cpu = <&cpu2>;
+ };
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu4>;
+ };
+ core1 {
+ cpu = <&cpu5>;
+ };
+ core2 {
+ cpu = <&cpu6>;
+ };
+ core3 {
+ cpu = <&cpu7>;
+ };
+ };
+ };
+
cpu0: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a53";
@@ -62,6 +94,13 @@
clock-names = "apolloclk";
operating-points-v2 = <&cluster_a53_opp_table>;
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&cluster_a53_l2>;
};
cpu1: cpu@101 {
@@ -72,6 +111,13 @@
clock-frequency = <1300000000>;
operating-points-v2 = <&cluster_a53_opp_table>;
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&cluster_a53_l2>;
};
cpu2: cpu@102 {
@@ -82,6 +128,13 @@
clock-frequency = <1300000000>;
operating-points-v2 = <&cluster_a53_opp_table>;
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&cluster_a53_l2>;
};
cpu3: cpu@103 {
@@ -92,6 +145,13 @@
clock-frequency = <1300000000>;
operating-points-v2 = <&cluster_a53_opp_table>;
#cooling-cells = <2>;
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&cluster_a53_l2>;
};
cpu4: cpu@0 {
@@ -104,6 +164,13 @@
clock-names = "atlasclk";
operating-points-v2 = <&cluster_a57_opp_table>;
#cooling-cells = <2>;
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&cluster_a57_l2>;
};
cpu5: cpu@1 {
@@ -114,6 +181,13 @@
clock-frequency = <1900000000>;
operating-points-v2 = <&cluster_a57_opp_table>;
#cooling-cells = <2>;
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&cluster_a57_l2>;
};
cpu6: cpu@2 {
@@ -124,6 +198,13 @@
clock-frequency = <1900000000>;
operating-points-v2 = <&cluster_a57_opp_table>;
#cooling-cells = <2>;
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&cluster_a57_l2>;
};
cpu7: cpu@3 {
@@ -134,6 +215,27 @@
clock-frequency = <1900000000>;
operating-points-v2 = <&cluster_a57_opp_table>;
#cooling-cells = <2>;
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&cluster_a57_l2>;
+ };
+
+ cluster_a57_l2: l2-cache0 {
+ compatible = "cache";
+ cache-size = <0x200000>;
+ cache-line-size = <64>;
+ cache-sets = <2048>;
+ };
+
+ cluster_a53_l2: l2-cache1 {
+ compatible = "cache";
+ cache-size = <0x40000>;
+ cache-line-size = <64>;
+ cache-sets = <256>;
};
};
diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi
index 10244e59d56d..c73a597ca66e 100644
--- a/arch/arm64/boot/dts/exynos/exynos7.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi
@@ -54,6 +54,13 @@
compatible = "arm,cortex-a57";
reg = <0x0>;
enable-method = "psci";
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&atlas_l2>;
};
cpu_atlas1: cpu@1 {
@@ -61,6 +68,13 @@
compatible = "arm,cortex-a57";
reg = <0x1>;
enable-method = "psci";
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&atlas_l2>;
};
cpu_atlas2: cpu@2 {
@@ -68,6 +82,13 @@
compatible = "arm,cortex-a57";
reg = <0x2>;
enable-method = "psci";
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&atlas_l2>;
};
cpu_atlas3: cpu@3 {
@@ -75,6 +96,20 @@
compatible = "arm,cortex-a57";
reg = <0x3>;
enable-method = "psci";
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&atlas_l2>;
+ };
+
+ atlas_l2: l2-cache0 {
+ compatible = "cache";
+ cache-size = <0x200000>;
+ cache-line-size = <64>;
+ cache-sets = <2048>;
};
};
@@ -102,7 +137,7 @@
#address-cells = <0>;
interrupt-controller;
reg = <0x11001000 0x1000>,
- <0x11002000 0x1000>,
+ <0x11002000 0x2000>,
<0x11004000 0x2000>,
<0x11006000 0x2000>;
};
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 25806c4924cb..db9e36ebe932 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-rdb.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-ten64.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb
dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb
@@ -42,10 +43,12 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw71xx-0x.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw72xx-0x.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw73xx-0x.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7901.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7902.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-beacon-kit.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-ddr4-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mn-var-som-symphony.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mn-venice-gw7902.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
@@ -55,6 +58,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-r2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-r3.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-r4.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mq-mnt-reform2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-nitrogen.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-phanbell.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-pico-pi.dtb
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts
index db3d303093f6..6d22efbd645c 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts
@@ -83,15 +83,9 @@
};
eeprom@52 {
- compatible = "atmel,24c512";
+ compatible = "onnn,cat24c04", "atmel,24c04";
reg = <0x52>;
};
-
- eeprom@53 {
- compatible = "atmel,24c512";
- reg = <0x53>;
- };
-
};
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
index 60acdf0b689e..7025aad8ae89 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
@@ -59,14 +59,9 @@
};
eeprom@52 {
- compatible = "atmel,24c512";
+ compatible = "onnn,cat24c05", "atmel,24c04";
reg = <0x52>;
};
-
- eeprom@53 {
- compatible = "atmel,24c512";
- reg = <0x53>;
- };
};
&i2c3 {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
index bf7b43ab1293..1bfbce69cc8b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
@@ -83,34 +83,42 @@
status = "okay";
mdio1_phy5: ethernet-phy@c {
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0xc>;
};
mdio1_phy6: ethernet-phy@d {
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0xd>;
};
mdio1_phy7: ethernet-phy@e {
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0xe>;
};
mdio1_phy8: ethernet-phy@f {
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0xf>;
};
mdio1_phy1: ethernet-phy@1c {
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0x1c>;
};
mdio1_phy2: ethernet-phy@1d {
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0x1d>;
};
mdio1_phy3: ethernet-phy@1e {
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0x1e>;
};
mdio1_phy4: ethernet-phy@1f {
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0x1f>;
};
};
@@ -120,6 +128,7 @@
mdio2_aquantia_phy: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c45";
+ interrupts-extended = <&extirq 2 IRQ_TYPE_LEVEL_LOW>;
reg = <0x0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
new file mode 100644
index 000000000000..3063851c2fb9
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree file for Travese Ten64 (LS1088) board
+ * Based on fsl-ls1088a-rdb.dts
+ * Copyright 2017-2020 NXP
+ * Copyright 2019-2021 Traverse Technologies
+ *
+ * Author: Mathew McBride <matt@traverse.com.au>
+ */
+
+/dts-v1/;
+
+#include "fsl-ls1088a.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Traverse Ten64";
+ compatible = "traverse,ten64", "fsl,ls1088a";
+
+ aliases {
+ serial0 = &duart0;
+ serial1 = &duart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ buttons {
+ compatible = "gpio-keys";
+
+ /* Fired by system controller when
+ * external power off (e.g ATX Power Button)
+ * asserted
+ */
+ powerdn {
+ label = "External Power Down";
+ gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
+ interrupts = <&gpio1 17 IRQ_TYPE_EDGE_FALLING>;
+ linux,code = <KEY_POWER>;
+ };
+
+ /* Rear Panel 'ADMIN' button (GPIO_H) */
+ admin {
+ label = "ADMIN button";
+ gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>;
+ interrupts = <&gpio3 8 IRQ_TYPE_EDGE_RISING>;
+ linux,code = <KEY_WPS_BUTTON>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ sfp1down {
+ label = "ten64:green:sfp1:down";
+ gpios = <&gpio3 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp2up {
+ label = "ten64:green:sfp2:up";
+ gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>;
+ };
+
+ admin {
+ label = "ten64:admin";
+ gpios = <&sfpgpio 12 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ sfp_xg0: dpmac2-sfp {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfplower_i2c>;
+ tx-fault-gpios = <&sfpgpio 0 GPIO_ACTIVE_HIGH>;
+ tx-disable-gpios = <&sfpgpio 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sfpgpio 2 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sfpgpio 3 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <2000>;
+ };
+
+ sfp_xg1: dpmac1-sfp {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfpupper_i2c>;
+ tx-fault-gpios = <&sfpgpio 4 GPIO_ACTIVE_HIGH>;
+ tx-disable-gpios = <&sfpgpio 5 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sfpgpio 6 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sfpgpio 7 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <2000>;
+ };
+};
+
+/* XG1 - Upper SFP */
+&dpmac1 {
+ sfp = <&sfp_xg1>;
+ pcs-handle = <&pcs1>;
+ phy-connection-type = "10gbase-r";
+ managed = "in-band-status";
+};
+
+/* XG0 - Lower SFP */
+&dpmac2 {
+ sfp = <&sfp_xg0>;
+ pcs-handle = <&pcs2>;
+ phy-connection-type = "10gbase-r";
+ managed = "in-band-status";
+};
+
+/* DPMAC3..6 is GE4 to GE8 */
+&dpmac3 {
+ phy-handle = <&mdio1_phy5>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ pcs-handle = <&pcs3_0>;
+};
+
+&dpmac4 {
+ phy-handle = <&mdio1_phy6>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ pcs-handle = <&pcs3_1>;
+};
+
+&dpmac5 {
+ phy-handle = <&mdio1_phy7>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ pcs-handle = <&pcs3_2>;
+};
+
+&dpmac6 {
+ phy-handle = <&mdio1_phy8>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ pcs-handle = <&pcs3_3>;
+};
+
+/* DPMAC7..10 is GE0 to GE3 */
+&dpmac7 {
+ phy-handle = <&mdio1_phy1>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ pcs-handle = <&pcs7_0>;
+};
+
+&dpmac8 {
+ phy-handle = <&mdio1_phy2>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ pcs-handle = <&pcs7_1>;
+};
+
+&dpmac9 {
+ phy-handle = <&mdio1_phy3>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ pcs-handle = <&pcs7_2>;
+};
+
+&dpmac10 {
+ phy-handle = <&mdio1_phy4>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ pcs-handle = <&pcs7_3>;
+};
+
+&duart0 {
+ status = "okay";
+};
+
+&duart1 {
+ status = "okay";
+};
+
+&emdio1 {
+ status = "okay";
+
+ mdio1_phy5: ethernet-phy@c {
+ reg = <0xc>;
+ };
+
+ mdio1_phy6: ethernet-phy@d {
+ reg = <0xd>;
+ };
+
+ mdio1_phy7: ethernet-phy@e {
+ reg = <0xe>;
+ };
+
+ mdio1_phy8: ethernet-phy@f {
+ reg = <0xf>;
+ };
+
+ mdio1_phy1: ethernet-phy@1c {
+ reg = <0x1c>;
+ };
+
+ mdio1_phy2: ethernet-phy@1d {
+ reg = <0x1d>;
+ };
+
+ mdio1_phy3: ethernet-phy@1e {
+ reg = <0x1e>;
+ };
+
+ mdio1_phy4: ethernet-phy@1f {
+ reg = <0x1f>;
+ };
+};
+
+&esdhc {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ sfpgpio: gpio@76 {
+ compatible = "ti,tca9539";
+ reg = <0x76>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ admin_led_lower {
+ gpio-hog;
+ gpios = <13 GPIO_ACTIVE_HIGH>;
+ output-low;
+ };
+ };
+
+ at97sc: tpm@29 {
+ compatible = "atmel,at97sc3204t";
+ reg = <0x29>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ rx8035: rtc@32 {
+ compatible = "epson,rx8035";
+ reg = <0x32>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+
+ i2c-switch@70 {
+ compatible = "nxp,pca9540";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ sfpupper_i2c: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ sfplower_i2c: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+};
+
+&pcs_mdio1 {
+ status = "okay";
+};
+
+&pcs_mdio2 {
+ status = "okay";
+};
+
+&pcs_mdio3 {
+ status = "okay";
+};
+
+&pcs_mdio7 {
+ status = "okay";
+};
+
+&qspi {
+ status = "okay";
+
+ en25s64: flash@0 {
+ compatible = "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bl2";
+ reg = <0 0x100000>;
+ };
+
+ partition@100000 {
+ label = "bl3";
+ reg = <0x100000 0x200000>;
+ };
+
+ partition@300000 {
+ label = "mcfirmware";
+ reg = <0x300000 0x200000>;
+ };
+
+ partition@500000 {
+ label = "ubootenv";
+ reg = <0x500000 0x80000>;
+ };
+
+ partition@580000 {
+ label = "dpl";
+ reg = <0x580000 0x40000>;
+ };
+
+ partition@5C0000 {
+ label = "dpc";
+ reg = <0x5C0000 0x40000>;
+ };
+
+ partition@600000 {
+ label = "devicetree";
+ reg = <0x600000 0x40000>;
+ };
+ };
+ };
+
+ nand: flash@1 {
+ compatible = "spi-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <1>;
+ spi-max-frequency = <20000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* reserved for future boot direct from NAND flash
+ * (this would use the same layout as the 8MiB NOR flash)
+ */
+ partition@0 {
+ label = "nand-boot-reserved";
+ reg = <0 0x800000>;
+ };
+
+ /* recovery / install environment */
+ partition@800000 {
+ label = "recovery";
+ reg = <0x800000 0x2000000>;
+ };
+
+ /* ubia (first OpenWrt) - a/b names to prevent confusion with ubi0/1/etc. */
+ partition@2800000 {
+ label = "ubia";
+ reg = <0x2800000 0x6C00000>;
+ };
+
+ /* ubib (second OpenWrt) */
+ partition@9400000 {
+ label = "ubib";
+ reg = <0x9400000 0x6C00000>;
+ };
+ };
+ };
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index 2fa6cfbef01f..f85e437f80b7 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -189,6 +189,11 @@
<1 10 IRQ_TYPE_LEVEL_LOW>;/* Hypervisor PPI */
};
+ pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
psci {
compatible = "arm,psci-0.2";
method = "smc";
@@ -765,6 +770,19 @@
status = "disabled";
};
+ pcs_mdio1: mdio@8c07000 {
+ compatible = "fsl,fman-memac-mdio";
+ reg = <0x0 0x8c07000 0x0 0x1000>;
+ little-endian;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ pcs1: ethernet-phy@0 {
+ reg = <0>;
+ };
+ };
+
pcs_mdio2: mdio@8c0b000 {
compatible = "fsl,fman-memac-mdio";
reg = <0x0 0x8c0b000 0x0 0x1000>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
index 60563917be44..3e4e857db13f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
@@ -92,21 +92,25 @@
mdio2_phy1: ethernet-phy@0 {
compatible = "ethernet-phy-id03a1.b4b0", "ethernet-phy-ieee802.3-c45";
+ interrupts-extended = <&extirq 1 IRQ_TYPE_LEVEL_LOW>;
reg = <0x0>;
};
mdio2_phy2: ethernet-phy@1 {
compatible = "ethernet-phy-id03a1.b4b0", "ethernet-phy-ieee802.3-c45";
+ interrupts-extended = <&extirq 2 IRQ_TYPE_LEVEL_LOW>;
reg = <0x1>;
};
mdio2_phy3: ethernet-phy@2 {
compatible = "ethernet-phy-id03a1.b4b0", "ethernet-phy-ieee802.3-c45";
+ interrupts-extended = <&extirq 4 IRQ_TYPE_LEVEL_LOW>;
reg = <0x2>;
};
mdio2_phy4: ethernet-phy@3 {
compatible = "ethernet-phy-id03a1.b4b0", "ethernet-phy-ieee802.3-c45";
+ interrupts-extended = <&extirq 5 IRQ_TYPE_LEVEL_LOW>;
reg = <0x3>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts
index 5dbf27493e8b..028ff8074b9d 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts
@@ -65,6 +65,7 @@
rgmii_phy1: ethernet-phy@1 {
/* AR8035 PHY */
compatible = "ethernet-phy-id004d.d072";
+ interrupts-extended = <&extirq 4 IRQ_TYPE_LEVEL_LOW>;
reg = <0x1>;
eee-broken-1000t;
};
@@ -72,6 +73,7 @@
rgmii_phy2: ethernet-phy@2 {
/* AR8035 PHY */
compatible = "ethernet-phy-id004d.d072";
+ interrupts-extended = <&extirq 5 IRQ_TYPE_LEVEL_LOW>;
reg = <0x2>;
eee-broken-1000t;
};
@@ -79,12 +81,14 @@
aquantia_phy1: ethernet-phy@4 {
/* AQR107 PHY */
compatible = "ethernet-phy-ieee802.3-c45";
+ interrupts-extended = <&extirq 2 IRQ_TYPE_LEVEL_LOW>;
reg = <0x4>;
};
aquantia_phy2: ethernet-phy@5 {
/* AQR107 PHY */
compatible = "ethernet-phy-ieee802.3-c45";
+ interrupts-extended = <&extirq 3 IRQ_TYPE_LEVEL_LOW>;
reg = <0x5>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi
new file mode 100644
index 000000000000..a90654155a88
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019-2021 NXP
+ * Zhou Guoniu <guoniu.zhou@nxp.com>
+ */
+img_subsys: bus@58000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x58000000 0x0 0x58000000 0x1000000>;
+
+ img_ipg_clk: clock-img-ipg {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <200000000>;
+ clock-output-names = "img_ipg_clk";
+ };
+
+ jpegdec: jpegdec@58400000 {
+ reg = <0x58400000 0x00050000>;
+ interrupts = <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&img_jpeg_dec_lpcg IMX_LPCG_CLK_0>,
+ <&img_jpeg_dec_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&img_jpeg_dec_lpcg IMX_LPCG_CLK_0>,
+ <&img_jpeg_dec_lpcg IMX_LPCG_CLK_4>;
+ assigned-clock-rates = <200000000>, <200000000>;
+ power-domains = <&pd IMX_SC_R_MJPEG_DEC_MP>,
+ <&pd IMX_SC_R_MJPEG_DEC_S0>,
+ <&pd IMX_SC_R_MJPEG_DEC_S1>,
+ <&pd IMX_SC_R_MJPEG_DEC_S2>,
+ <&pd IMX_SC_R_MJPEG_DEC_S3>;
+ };
+
+ jpegenc: jpegenc@58450000 {
+ reg = <0x58450000 0x00050000>;
+ interrupts = <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&img_jpeg_enc_lpcg IMX_LPCG_CLK_0>,
+ <&img_jpeg_enc_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&img_jpeg_enc_lpcg IMX_LPCG_CLK_0>,
+ <&img_jpeg_enc_lpcg IMX_LPCG_CLK_4>;
+ assigned-clock-rates = <200000000>, <200000000>;
+ power-domains = <&pd IMX_SC_R_MJPEG_ENC_MP>,
+ <&pd IMX_SC_R_MJPEG_ENC_S0>,
+ <&pd IMX_SC_R_MJPEG_ENC_S1>,
+ <&pd IMX_SC_R_MJPEG_ENC_S2>,
+ <&pd IMX_SC_R_MJPEG_ENC_S3>;
+ };
+
+ img_jpeg_dec_lpcg: clock-controller@585d0000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x585d0000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&img_ipg_clk>, <&img_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>,
+ <IMX_LPCG_CLK_4>;
+ clock-output-names = "img_jpeg_dec_lpcg_clk",
+ "img_jpeg_dec_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_MJPEG_DEC_MP>;
+ };
+
+ img_jpeg_enc_lpcg: clock-controller@585f0000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x585f0000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&img_ipg_clk>, <&img_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>,
+ <IMX_LPCG_CLK_4>;
+ clock-output-names = "img_jpeg_enc_lpcg_clk",
+ "img_jpeg_enc_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_MJPEG_ENC_MP>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
index c769fadbd008..00f86cada30d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
@@ -278,70 +278,86 @@
pmic@69 {
compatible = "mps,mp5416";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pmic>;
reg = <0x69>;
regulators {
+ /* vdd_0p95: DRAM/GPU/VPU */
buck1 {
- regulator-name = "vdd_0p95";
- regulator-min-microvolt = <805000>;
+ regulator-name = "buck1";
+ regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1000000>;
- regulator-max-microamp = <2500000>;
+ regulator-min-microamp = <3800000>;
+ regulator-max-microamp = <6800000>;
regulator-boot-on;
+ regulator-always-on;
};
+ /* vdd_soc */
buck2 {
- regulator-name = "vdd_soc";
- regulator-min-microvolt = <805000>;
+ regulator-name = "buck2";
+ regulator-min-microvolt = <800000>;
regulator-max-microvolt = <900000>;
- regulator-max-microamp = <1000000>;
+ regulator-min-microamp = <2200000>;
+ regulator-max-microamp = <5200000>;
regulator-boot-on;
+ regulator-always-on;
};
+ /* vdd_arm */
buck3_reg: buck3 {
- regulator-name = "vdd_arm";
- regulator-min-microvolt = <805000>;
+ regulator-name = "buck3";
+ regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1000000>;
- regulator-max-microamp = <2200000>;
- regulator-boot-on;
+ regulator-min-microamp = <3800000>;
+ regulator-max-microamp = <6800000>;
+ regulator-always-on;
};
+ /* vdd_1p8 */
buck4 {
- regulator-name = "vdd_1p8";
+ regulator-name = "buck4";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
- regulator-max-microamp = <500000>;
+ regulator-min-microamp = <2200000>;
+ regulator-max-microamp = <5200000>;
regulator-boot-on;
+ regulator-always-on;
};
+ /* nvcc_snvs_1p8 */
ldo1 {
- regulator-name = "nvcc_snvs_1p8";
+ regulator-name = "ldo1";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
- regulator-max-microamp = <300000>;
regulator-boot-on;
+ regulator-always-on;
};
+ /* vdd_snvs_0p8 */
ldo2 {
- regulator-name = "vdd_snvs_0p8";
+ regulator-name = "ldo2";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <800000>;
regulator-boot-on;
+ regulator-always-on;
};
+ /* vdd_0p9 */
ldo3 {
- regulator-name = "vdd_0p95";
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <800000>;
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
regulator-boot-on;
+ regulator-always-on;
};
+ /* vdd_1p8 */
ldo4 {
- regulator-name = "vdd_1p8";
+ regulator-name = "ldo4";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
+ regulator-always-on;
};
};
};
@@ -426,12 +442,6 @@
>;
};
- pinctrl_pmic: pmicgrp {
- fsl,pins = <
- MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
- >;
- };
-
pinctrl_uart2: uart2grp {
fsl,pins = <
MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
index 905b68a3daa5..8e4a0ce99790 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
@@ -46,7 +46,7 @@
pinctrl-0 = <&pinctrl_reg_usb1_en>;
compatible = "regulator-fixed";
regulator-name = "usb_otg1_vbus";
- gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
@@ -156,7 +156,8 @@
pinctrl_reg_usb1_en: regusb1grp {
fsl,pins = <
- MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x41
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x41
+ MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x141
MX8MM_IOMUXC_GPIO1_IO13_USB1_OTG_OC 0x41
>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
index 5a1e9df39bec..bafd5c8ea4e2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
@@ -216,7 +216,7 @@
pinctrl-0 = <&pinctrl_reg_usb2>;
compatible = "regulator-fixed";
regulator-name = "usb_usb2_vbus";
- gpio = <&gpio4 17 GPIO_ACTIVE_HIGH>;
+ gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
@@ -296,8 +296,6 @@
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
adc {
compatible = "gw,gsc-adc";
@@ -824,8 +822,9 @@
pinctrl_reg_usb2: regusb1grp {
fsl,pins = <
- MX8MM_IOMUXC_SAI1_TXD5_GPIO4_IO17 0x41
- MX8MM_IOMUXC_GPIO1_IO15_USB2_OTG_OC 0x41
+ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x41
+ MX8MM_IOMUXC_SAI1_TXD5_GPIO4_IO17 0x140
+ MX8MM_IOMUXC_GPIO1_IO15_USB2_OTG_OC 0x140
>;
};
@@ -876,9 +875,9 @@
pinctrl_uart3_gpio: uart3gpiogrp {
fsl,pins = <
- MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6 0x40000041 /* RS232# */
- MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x40000041 /* RS422# */
- MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x40000041 /* RS485# */
+ MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6 0x40000110 /* RS232# */
+ MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x40000110 /* RS422# */
+ MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x40000110 /* RS485# */
>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
new file mode 100644
index 000000000000..05cb60991fb9
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
@@ -0,0 +1,911 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2021 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+#include "imx8mm.dtsi"
+
+/ {
+ model = "Gateworks Venice GW7902 i.MX8MM board";
+ compatible = "gw,imx8mm-gw7902", "fsl,imx8mm";
+
+ aliases {
+ usb0 = &usbotg1;
+ usb1 = &usbotg2;
+ };
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x0 0x40000000 0 0x80000000>;
+ };
+
+ can20m: can20m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <20000000>;
+ clock-output-names = "can20m";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ user-pb {
+ label = "user_pb";
+ gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+ linux,code = <BTN_0>;
+ };
+
+ user-pb1x {
+ label = "user_pb1x";
+ linux,code = <BTN_1>;
+ interrupt-parent = <&gsc>;
+ interrupts = <0>;
+ };
+
+ key-erased {
+ label = "key_erased";
+ linux,code = <BTN_2>;
+ interrupt-parent = <&gsc>;
+ interrupts = <1>;
+ };
+
+ eeprom-wp {
+ label = "eeprom_wp";
+ linux,code = <BTN_3>;
+ interrupt-parent = <&gsc>;
+ interrupts = <2>;
+ };
+
+ tamper {
+ label = "tamper";
+ linux,code = <BTN_4>;
+ interrupt-parent = <&gsc>;
+ interrupts = <5>;
+ };
+
+ switch-hold {
+ label = "switch_hold";
+ linux,code = <BTN_5>;
+ interrupt-parent = <&gsc>;
+ interrupts = <7>;
+ };
+ };
+
+ led-controller {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
+
+ led-0 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel1";
+ gpios = <&gpio3 21 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel2";
+ gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led-2 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel3";
+ gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led-3 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel4";
+ gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led-4 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel5";
+ gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ };
+
+ pps {
+ compatible = "pps-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pps>;
+ gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_usb1_vbus: regulator-usb1 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usb1>;
+ regulator-name = "usb_usb1_vbus";
+ gpio = <&gpio2 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_wifi: regulator-wifi {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_wl>;
+ regulator-name = "wifi";
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <100>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&A53_0 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_1 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_2 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_3 {
+ cpu-supply = <&buck2>;
+};
+
+&ddrc {
+ operating-points-v2 = <&ddrc_opp_table>;
+
+ ddrc_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+
+ opp-100M {
+ opp-hz = /bits/ 64 <100000000>;
+ };
+
+ opp-750M {
+ opp-hz = /bits/ 64 <750000000>;
+ };
+ };
+};
+
+&ecspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1>;
+ cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ can@0 {
+ compatible = "microchip,mcp2515";
+ reg = <0>;
+ clocks = <&can20m>;
+ oscillator-frequency = <20000000>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ spi-max-frequency = <10000000>;
+ };
+};
+
+/* off-board header */
+&ecspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi2>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ local-mac-address = [00 00 00 00 00 00];
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ gsc: gsc@20 {
+ compatible = "gw,gsc";
+ reg = <0x20>;
+ pinctrl-0 = <&pinctrl_gsc>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ adc {
+ compatible = "gw,gsc-adc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@6 {
+ gw,mode = <0>;
+ reg = <0x06>;
+ label = "temp";
+ };
+
+ channel@8 {
+ gw,mode = <1>;
+ reg = <0x08>;
+ label = "vdd_bat";
+ };
+
+ channel@82 {
+ gw,mode = <2>;
+ reg = <0x82>;
+ label = "vin";
+ gw,voltage-divider-ohms = <22100 1000>;
+ gw,voltage-offset-microvolt = <700000>;
+ };
+
+ channel@84 {
+ gw,mode = <2>;
+ reg = <0x84>;
+ label = "vin_4p0";
+ gw,voltage-divider-ohms = <10000 10000>;
+ };
+
+ channel@86 {
+ gw,mode = <2>;
+ reg = <0x86>;
+ label = "vdd_3p3";
+ gw,voltage-divider-ohms = <10000 10000>;
+ };
+
+ channel@88 {
+ gw,mode = <2>;
+ reg = <0x88>;
+ label = "vdd_0p9";
+ };
+
+ channel@8c {
+ gw,mode = <2>;
+ reg = <0x8c>;
+ label = "vdd_soc";
+ };
+
+ channel@8e {
+ gw,mode = <2>;
+ reg = <0x8e>;
+ label = "vdd_arm";
+ };
+
+ channel@90 {
+ gw,mode = <2>;
+ reg = <0x90>;
+ label = "vdd_1p8";
+ };
+
+ channel@92 {
+ gw,mode = <2>;
+ reg = <0x92>;
+ label = "vdd_dram";
+ };
+
+ channel@98 {
+ gw,mode = <2>;
+ reg = <0x98>;
+ label = "vdd_1p0";
+ };
+
+ channel@9a {
+ gw,mode = <2>;
+ reg = <0x9a>;
+ label = "vdd_2p5";
+ gw,voltage-divider-ohms = <10000 10000>;
+ };
+
+ channel@a2 {
+ gw,mode = <2>;
+ reg = <0xa2>;
+ label = "vdd_gsc";
+ gw,voltage-divider-ohms = <10000 10000>;
+ };
+ };
+ };
+
+ gpio: gpio@23 {
+ compatible = "nxp,pca9555";
+ reg = <0x23>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&gsc>;
+ interrupts = <4>;
+ };
+
+ pmic@4b {
+ compatible = "rohm,bd71847";
+ reg = <0x4b>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ rohm,reset-snvs-powered;
+ #clock-cells = <0>;
+ clocks = <&osc_32k 0>;
+ clock-output-names = "clk-32k-out";
+
+ regulators {
+ /* vdd_soc: 0.805-0.900V (typ=0.8V) */
+ BUCK1 {
+ regulator-name = "buck1";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ };
+
+ /* vdd_arm: 0.805-1.0V (typ=0.9V) */
+ buck2: BUCK2 {
+ regulator-name = "buck2";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ rohm,dvs-run-voltage = <1000000>;
+ rohm,dvs-idle-voltage = <900000>;
+ };
+
+ /* vdd_0p9: 0.805-1.0V (typ=0.9V) */
+ BUCK3 {
+ regulator-name = "buck3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdd_3p3 */
+ BUCK4 {
+ regulator-name = "buck4";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdd_1p8 */
+ BUCK5 {
+ regulator-name = "buck5";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdd_dram */
+ BUCK6 {
+ regulator-name = "buck6";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* nvcc_snvs_1p8 */
+ LDO1 {
+ regulator-name = "ldo1";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdd_snvs_0p8 */
+ LDO2 {
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdda_1p8 */
+ LDO3 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO4 {
+ regulator-name = "ldo4";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO6 {
+ regulator-name = "ldo6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+
+ eeprom@51 {
+ compatible = "atmel,24c02";
+ reg = <0x51>;
+ pagesize = <16>;
+ };
+
+ eeprom@52 {
+ compatible = "atmel,24c02";
+ reg = <0x52>;
+ pagesize = <16>;
+ };
+
+ eeprom@53 {
+ compatible = "atmel,24c02";
+ reg = <0x53>;
+ pagesize = <16>;
+ };
+
+ rtc@68 {
+ compatible = "dallas,ds1672";
+ reg = <0x68>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ accelerometer@19 {
+ compatible = "st,lis2de12";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_accel>;
+ reg = <0x19>;
+ st,drdy-int-pin = <1>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "INT1";
+ };
+};
+
+/* off-board header */
+&i2c3 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+};
+
+/* off-board header */
+&i2c4 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+};
+
+/* off-board header */
+&sai3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai3>;
+ assigned-clocks = <&clk IMX8MM_CLK_SAI3>;
+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <24576000>;
+ status = "okay";
+};
+
+/* RS232/RS485/RS422 selectable */
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>, <&pinctrl_uart1_gpio>;
+ rts-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;
+ cts-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+/* RS232 console */
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+/* bluetooth HCI */
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_uart3_gpio>;
+ rts-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+ cts-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4330-bt";
+ shutdown-gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+/* LTE Cat M1/NB1/EGPRS modem or GPS (loading option) */
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ rts-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
+ cts-gpios = <&gpio4 1 GPIO_ACTIVE_LOW>;
+ dtr-gpios = <&gpio4 3 GPIO_ACTIVE_LOW>;
+ dsr-gpios = <&gpio4 4 GPIO_ACTIVE_LOW>;
+ dcd-gpios = <&gpio4 6 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "host";
+ vbus-supply = <&reg_usb1_vbus>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+/* SDIO WiFi */
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ non-removable;
+ vmmc-supply = <&reg_wifi>;
+ status = "okay";
+};
+
+/* eMMC */
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_CE0_B_GPIO3_IO1 0x40000159 /* M2_GDIS# */
+ MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x40000041 /* M2_RST# */
+ MX8MM_IOMUXC_NAND_DATA01_GPIO3_IO7 0x40000119 /* M2_OFF# */
+ MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x40000159 /* M2_WDIS# */
+ MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x40000041 /* AMP GPIO1 */
+ MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12 0x40000041 /* AMP GPIO2 */
+ MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11 0x40000041 /* AMP GPIO3 */
+ MX8MM_IOMUXC_SAI1_MCLK_GPIO4_IO20 0x40000041 /* AMP_GPIO4 */
+ MX8MM_IOMUXC_SAI2_RXFS_GPIO4_IO21 0x40000041 /* APP GPIO1 */
+ MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x40000041 /* APP GPIO2 */
+ MX8MM_IOMUXC_SD1_DATA6_GPIO2_IO8 0x40000041 /* UART2_EN# */
+ MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x40000041 /* MIPI_GPIO1 */
+ MX8MM_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5 0x40000041 /* MIPI_GPIO2 */
+ MX8MM_IOMUXC_SPDIF_RX_GPIO5_IO4 0x40000041 /* MIPI_GPIO3/PWM2 */
+ MX8MM_IOMUXC_SPDIF_TX_GPIO5_IO3 0x40000041 /* MIPI_GPIO4/PWM3 */
+ >;
+ };
+
+ pinctrl_accel: accelgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x159
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3
+ MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19 /* RST# */
+ MX8MM_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x19 /* IRQ# */
+ MX8MM_IOMUXC_GPIO1_IO08_ENET1_1588_EVENT0_IN 0x141
+ MX8MM_IOMUXC_GPIO1_IO09_ENET1_1588_EVENT0_OUT 0x141
+ >;
+ };
+
+ pinctrl_gsc: gscgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_DATA4_GPIO2_IO6 0x40
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_gpio_leds: gpioledgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXD0_GPIO3_IO21 0x19
+ MX8MM_IOMUXC_SAI5_RXD2_GPIO3_IO23 0x19
+ MX8MM_IOMUXC_SAI5_RXD1_GPIO3_IO22 0x19
+ MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20 0x19
+ MX8MM_IOMUXC_SAI5_MCLK_GPIO3_IO25 0x19
+ >;
+ };
+
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_DATA02_GPIO3_IO8 0x41
+ >;
+ };
+
+ pinctrl_pps: ppsgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXD3_GPIO3_IO24 0x141 /* PPS */
+ >;
+ };
+
+ pinctrl_reg_wl: regwlgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41 /* WLAN_WLON */
+ >;
+ };
+
+ pinctrl_reg_usb1: regusb1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_DATA5_GPIO2_IO7 0x41
+ >;
+ };
+
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_MCLK_SAI3_MCLK 0xd6
+ MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0xd6
+ MX8MM_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0xd6
+ MX8MM_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0xd6
+ MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0xd6
+ >;
+ };
+
+ pinctrl_spi1: spi1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK 0x82
+ MX8MM_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI 0x82
+ MX8MM_IOMUXC_ECSPI1_MISO_ECSPI1_MISO 0x82
+ MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x40
+ MX8MM_IOMUXC_SD1_DATA1_GPIO2_IO3 0x140 /* CAN_IRQ# */
+ >;
+ };
+
+ pinctrl_spi2: spi2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0x82
+ MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0x82
+ MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0x82
+ MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0x40 /* SS0 */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140
+ MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140
+ MX8MM_IOMUXC_SAI1_TXFS_GPIO4_IO10 0x140 /* RTS */
+ MX8MM_IOMUXC_SAI2_TXFS_GPIO4_IO24 0x140 /* CTS */
+ >;
+ };
+
+ pinctrl_uart1_gpio: uart1gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI2_TXD0_GPIO4_IO26 0x40000110 /* HALF */
+ MX8MM_IOMUXC_SAI2_TXC_GPIO4_IO25 0x40000110 /* TERM */
+ MX8MM_IOMUXC_SAI2_RXD0_GPIO4_IO23 0x40000110 /* RS485 */
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_uart3_gpio: uart3_gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41 /* BT_EN# */
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART3_RXD_UART3_DCE_RX 0x140
+ MX8MM_IOMUXC_UART3_TXD_UART3_DCE_TX 0x140
+ MX8MM_IOMUXC_SD1_CLK_GPIO2_IO0 0x140 /* CTS */
+ MX8MM_IOMUXC_SD1_CMD_GPIO2_IO1 0x140 /* RTS */
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x140
+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x140
+ MX8MM_IOMUXC_SAI1_RXC_GPIO4_IO1 0x140 /* CTS */
+ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x140 /* RTS */
+ MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x140 /* DTR */
+ MX8MM_IOMUXC_SAI1_RXD2_GPIO4_IO4 0x140 /* DSR */
+ MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6 0x140 /* DCD */
+ MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x140 /* RI */
+ MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x140 /* GNSS_PPS */
+ MX8MM_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x141 /* GNSS_GASP */
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x190
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d0
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d0
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d0
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d0
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d0
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d0
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d0
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d0
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d0
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x190
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x194
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d4
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d4
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d4
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d4
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d4
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d4
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d4
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d4
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d4
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x196
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d6
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d6
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d6
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d6
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d6
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d6
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d6
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d6
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d6
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x196
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 1608a48495b6..2f632e8ca388 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -192,10 +192,9 @@
};
pmu {
- compatible = "arm,armv8-pmuv3";
+ compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_PPI 7
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
- interrupt-affinity = <&A53_0>, <&A53_1>, <&A53_2>, <&A53_3>;
};
timer {
@@ -241,6 +240,7 @@
};
usbphynop1: usbphynop1 {
+ #phy-cells = <0>;
compatible = "usb-nop-xceiv";
clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
@@ -249,6 +249,7 @@
};
usbphynop2: usbphynop2 {
+ #phy-cells = <0>;
compatible = "usb-nop-xceiv";
clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
@@ -968,7 +969,7 @@
clock-names = "usb1_ctrl_root_clk";
assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
- fsl,usbphy = <&usbphynop1>;
+ phys = <&usbphynop1>;
fsl,usbmisc = <&usbmisc1 0>;
status = "disabled";
};
@@ -987,7 +988,7 @@
clock-names = "usb1_ctrl_root_clk";
assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
- fsl,usbphy = <&usbphynop2>;
+ phys = <&usbphynop2>;
fsl,usbmisc = <&usbmisc2 0>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
new file mode 100644
index 000000000000..e77db4996e58
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
@@ -0,0 +1,884 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2021 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+#include "imx8mn.dtsi"
+
+/ {
+ model = "Gateworks Venice GW7902 i.MX8MN board";
+ compatible = "gw,imx8mn-gw7902", "fsl,imx8mn";
+
+ aliases {
+ usb0 = &usbotg1;
+ };
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x0 0x40000000 0 0x80000000>;
+ };
+
+ can20m: can20m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <20000000>;
+ clock-output-names = "can20m";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ user-pb {
+ label = "user_pb";
+ gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+ linux,code = <BTN_0>;
+ };
+
+ user-pb1x {
+ label = "user_pb1x";
+ linux,code = <BTN_1>;
+ interrupt-parent = <&gsc>;
+ interrupts = <0>;
+ };
+
+ key-erased {
+ label = "key_erased";
+ linux,code = <BTN_2>;
+ interrupt-parent = <&gsc>;
+ interrupts = <1>;
+ };
+
+ eeprom-wp {
+ label = "eeprom_wp";
+ linux,code = <BTN_3>;
+ interrupt-parent = <&gsc>;
+ interrupts = <2>;
+ };
+
+ tamper {
+ label = "tamper";
+ linux,code = <BTN_4>;
+ interrupt-parent = <&gsc>;
+ interrupts = <5>;
+ };
+
+ switch-hold {
+ label = "switch_hold";
+ linux,code = <BTN_5>;
+ interrupt-parent = <&gsc>;
+ interrupts = <7>;
+ };
+ };
+
+ led-controller {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
+
+ led-0 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel1";
+ gpios = <&gpio3 21 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel2";
+ gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led-2 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel3";
+ gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led-3 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel4";
+ gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led-4 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ label = "panel5";
+ gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ };
+
+ pps {
+ compatible = "pps-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pps>;
+ gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_usb1_vbus: regulator-usb1 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usb1>;
+ regulator-name = "usb_usb1_vbus";
+ gpio = <&gpio2 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_wifi: regulator-wifi {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_wl>;
+ regulator-name = "wifi";
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <100>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&A53_0 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_1 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_2 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_3 {
+ cpu-supply = <&buck2>;
+};
+
+&ddrc {
+ operating-points-v2 = <&ddrc_opp_table>;
+
+ ddrc_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+
+ opp-100M {
+ opp-hz = /bits/ 64 <100000000>;
+ };
+
+ opp-750M {
+ opp-hz = /bits/ 64 <750000000>;
+ };
+ };
+};
+
+&ecspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1>;
+ cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ can@0 {
+ compatible = "microchip,mcp2515";
+ reg = <0>;
+ clocks = <&can20m>;
+ oscillator-frequency = <20000000>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ spi-max-frequency = <10000000>;
+ };
+};
+
+/* off-board header */
+&ecspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi2>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ local-mac-address = [00 00 00 00 00 00];
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ gsc: gsc@20 {
+ compatible = "gw,gsc";
+ reg = <0x20>;
+ pinctrl-0 = <&pinctrl_gsc>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ adc {
+ compatible = "gw,gsc-adc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@6 {
+ gw,mode = <0>;
+ reg = <0x06>;
+ label = "temp";
+ };
+
+ channel@8 {
+ gw,mode = <1>;
+ reg = <0x08>;
+ label = "vdd_bat";
+ };
+
+ channel@82 {
+ gw,mode = <2>;
+ reg = <0x82>;
+ label = "vin";
+ gw,voltage-divider-ohms = <22100 1000>;
+ gw,voltage-offset-microvolt = <700000>;
+ };
+
+ channel@84 {
+ gw,mode = <2>;
+ reg = <0x84>;
+ label = "vin_4p0";
+ gw,voltage-divider-ohms = <10000 10000>;
+ };
+
+ channel@86 {
+ gw,mode = <2>;
+ reg = <0x86>;
+ label = "vdd_3p3";
+ gw,voltage-divider-ohms = <10000 10000>;
+ };
+
+ channel@88 {
+ gw,mode = <2>;
+ reg = <0x88>;
+ label = "vdd_0p9";
+ };
+
+ channel@8c {
+ gw,mode = <2>;
+ reg = <0x8c>;
+ label = "vdd_soc";
+ };
+
+ channel@8e {
+ gw,mode = <2>;
+ reg = <0x8e>;
+ label = "vdd_arm";
+ };
+
+ channel@90 {
+ gw,mode = <2>;
+ reg = <0x90>;
+ label = "vdd_1p8";
+ };
+
+ channel@92 {
+ gw,mode = <2>;
+ reg = <0x92>;
+ label = "vdd_dram";
+ };
+
+ channel@98 {
+ gw,mode = <2>;
+ reg = <0x98>;
+ label = "vdd_1p0";
+ };
+
+ channel@9a {
+ gw,mode = <2>;
+ reg = <0x9a>;
+ label = "vdd_2p5";
+ gw,voltage-divider-ohms = <10000 10000>;
+ };
+
+ channel@a2 {
+ gw,mode = <2>;
+ reg = <0xa2>;
+ label = "vdd_gsc";
+ gw,voltage-divider-ohms = <10000 10000>;
+ };
+ };
+ };
+
+ gpio: gpio@23 {
+ compatible = "nxp,pca9555";
+ reg = <0x23>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&gsc>;
+ interrupts = <4>;
+ };
+
+ pmic@4b {
+ compatible = "rohm,bd71847";
+ reg = <0x4b>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ rohm,reset-snvs-powered;
+ #clock-cells = <0>;
+ clocks = <&osc_32k 0>;
+ clock-output-names = "clk-32k-out";
+
+ regulators {
+ /* vdd_soc: 0.805-0.900V (typ=0.8V) */
+ BUCK1 {
+ regulator-name = "buck1";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ };
+
+ /* vdd_arm: 0.805-1.0V (typ=0.9V) */
+ buck2: BUCK2 {
+ regulator-name = "buck2";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ rohm,dvs-run-voltage = <1000000>;
+ rohm,dvs-idle-voltage = <900000>;
+ };
+
+ /* vdd_0p9: 0.805-1.0V (typ=0.9V) */
+ BUCK3 {
+ regulator-name = "buck3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdd_3p3 */
+ BUCK4 {
+ regulator-name = "buck4";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdd_1p8 */
+ BUCK5 {
+ regulator-name = "buck5";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdd_dram */
+ BUCK6 {
+ regulator-name = "buck6";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* nvcc_snvs_1p8 */
+ LDO1 {
+ regulator-name = "ldo1";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdd_snvs_0p8 */
+ LDO2 {
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* vdda_1p8 */
+ LDO3 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO4 {
+ regulator-name = "ldo4";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO6 {
+ regulator-name = "ldo6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+
+ eeprom@51 {
+ compatible = "atmel,24c02";
+ reg = <0x51>;
+ pagesize = <16>;
+ };
+
+ eeprom@52 {
+ compatible = "atmel,24c02";
+ reg = <0x52>;
+ pagesize = <16>;
+ };
+
+ eeprom@53 {
+ compatible = "atmel,24c02";
+ reg = <0x53>;
+ pagesize = <16>;
+ };
+
+ rtc@68 {
+ compatible = "dallas,ds1672";
+ reg = <0x68>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ accelerometer@19 {
+ compatible = "st,lis2de12";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_accel>;
+ reg = <0x19>;
+ st,drdy-int-pin = <1>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "INT1";
+ };
+};
+
+/* off-board header */
+&i2c3 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+};
+
+/* off-board header */
+&i2c4 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+};
+
+/* off-board header */
+&sai3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai3>;
+ assigned-clocks = <&clk IMX8MN_CLK_SAI3>;
+ assigned-clock-parents = <&clk IMX8MN_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <24576000>;
+ status = "okay";
+};
+
+/* RS232/RS485/RS422 selectable */
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>, <&pinctrl_uart1_gpio>;
+ status = "okay";
+};
+
+/* RS232 console */
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+/* bluetooth HCI */
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_uart3_gpio>;
+ rts-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+ cts-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4330-bt";
+ shutdown-gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+/* LTE Cat M1/NB1/EGPRS modem or GPS (loading option) */
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "host";
+ vbus-supply = <&reg_usb1_vbus>;
+ disable-over-current;
+ status = "okay";
+};
+
+/* SDIO WiFi */
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ non-removable;
+ vmmc-supply = <&reg_wifi>;
+ status = "okay";
+};
+
+/* eMMC */
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_NAND_CE0_B_GPIO3_IO1 0x40000159 /* M2_GDIS# */
+ MX8MN_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x40000041 /* M2_RST# */
+ MX8MN_IOMUXC_NAND_DATA01_GPIO3_IO7 0x40000119 /* M2_OFF# */
+ MX8MN_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x40000159 /* M2_WDIS# */
+ MX8MN_IOMUXC_SAI2_RXFS_GPIO4_IO21 0x40000041 /* APP GPIO1 */
+ MX8MN_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x40000041 /* APP GPIO2 */
+ MX8MN_IOMUXC_SD1_DATA6_GPIO2_IO8 0x40000041 /* UART2_EN# */
+ MX8MN_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x40000041 /* MIPI_GPIO1 */
+ MX8MN_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5 0x40000041 /* MIPI_GPIO2 */
+ MX8MN_IOMUXC_SPDIF_RX_GPIO5_IO4 0x40000041 /* MIPI_GPIO3/PWM2 */
+ MX8MN_IOMUXC_SPDIF_TX_GPIO5_IO3 0x40000041 /* MIPI_GPIO4/PWM3 */
+ >;
+ };
+
+ pinctrl_accel: accelgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x159
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MN_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3
+ MX8MN_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MN_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MN_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MN_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MN_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MN_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MN_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MN_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MN_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MN_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MN_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MN_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MN_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19 /* RST# */
+ MX8MN_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x19 /* IRQ# */
+ MX8MN_IOMUXC_GPIO1_IO08_ENET1_1588_EVENT0_IN 0x141
+ MX8MN_IOMUXC_GPIO1_IO09_ENET1_1588_EVENT0_OUT 0x141
+ >;
+ };
+
+ pinctrl_gsc: gscgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD1_DATA4_GPIO2_IO6 0x40
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
+ MX8MN_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
+ MX8MN_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
+ MX8MN_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
+ MX8MN_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_gpio_leds: gpioledgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SAI5_RXD0_GPIO3_IO21 0x19
+ MX8MN_IOMUXC_SAI5_RXD2_GPIO3_IO23 0x19
+ MX8MN_IOMUXC_SAI5_RXD1_GPIO3_IO22 0x19
+ MX8MN_IOMUXC_SAI5_RXC_GPIO3_IO20 0x19
+ MX8MN_IOMUXC_SAI5_MCLK_GPIO3_IO25 0x19
+ >;
+ };
+
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_NAND_DATA02_GPIO3_IO8 0x41
+ >;
+ };
+
+ pinctrl_pps: ppsgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SAI5_RXD3_GPIO3_IO24 0x141 /* PPS */
+ >;
+ };
+
+ pinctrl_reg_wl: regwlgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41 /* WLAN_WLON */
+ >;
+ };
+
+ pinctrl_reg_usb1: regusb1grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD1_DATA5_GPIO2_IO7 0x41
+ >;
+ };
+
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SAI3_MCLK_SAI3_MCLK 0xd6
+ MX8MN_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0xd6
+ MX8MN_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0xd6
+ MX8MN_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0xd6
+ MX8MN_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0xd6
+ >;
+ };
+
+ pinctrl_spi1: spi1grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK 0x82
+ MX8MN_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI 0x82
+ MX8MN_IOMUXC_ECSPI1_MISO_ECSPI1_MISO 0x82
+ MX8MN_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x40
+ MX8MN_IOMUXC_SD1_DATA1_GPIO2_IO3 0x140 /* CAN_IRQ# */
+ >;
+ };
+
+ pinctrl_spi2: spi2grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0x82
+ MX8MN_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0x82
+ MX8MN_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0x82
+ MX8MN_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0x40 /* SS0 */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140
+ MX8MN_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_uart1_gpio: uart1gpiogrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SAI2_TXD0_GPIO4_IO26 0x40000110 /* HALF */
+ MX8MN_IOMUXC_SAI2_TXC_GPIO4_IO25 0x40000110 /* TERM */
+ MX8MN_IOMUXC_SAI2_RXD0_GPIO4_IO23 0x40000110 /* RS485 */
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
+ MX8MN_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_uart3_gpio: uart3_gpiogrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41 /* BT_EN# */
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_UART3_RXD_UART3_DCE_RX 0x140
+ MX8MN_IOMUXC_UART3_TXD_UART3_DCE_TX 0x140
+ MX8MN_IOMUXC_SD1_CLK_GPIO2_IO0 0x140 /* CTS */
+ MX8MN_IOMUXC_SD1_CMD_GPIO2_IO1 0x140 /* RTS */
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_UART4_RXD_UART4_DCE_RX 0x140
+ MX8MN_IOMUXC_UART4_TXD_UART4_DCE_TX 0x140
+ MX8MN_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x141 /* GNSS_GASP */
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
+ MX8MN_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
+ MX8MN_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
+ MX8MN_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
+ MX8MN_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
+ MX8MN_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_NAND_WE_B_USDHC3_CLK 0x190
+ MX8MN_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d0
+ MX8MN_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d0
+ MX8MN_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d0
+ MX8MN_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d0
+ MX8MN_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d0
+ MX8MN_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d0
+ MX8MN_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d0
+ MX8MN_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d0
+ MX8MN_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d0
+ MX8MN_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x190
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_NAND_WE_B_USDHC3_CLK 0x194
+ MX8MN_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d4
+ MX8MN_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d4
+ MX8MN_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d4
+ MX8MN_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d4
+ MX8MN_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d4
+ MX8MN_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d4
+ MX8MN_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d4
+ MX8MN_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d4
+ MX8MN_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d4
+ MX8MN_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_NAND_WE_B_USDHC3_CLK 0x196
+ MX8MN_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d6
+ MX8MN_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d6
+ MX8MN_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d6
+ MX8MN_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d6
+ MX8MN_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d6
+ MX8MN_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d6
+ MX8MN_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d6
+ MX8MN_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d6
+ MX8MN_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d6
+ MX8MN_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x196
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
index e6de293865b0..da6c942fb7f9 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -190,7 +190,6 @@
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_PPI 7
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
- interrupt-affinity = <&A53_0>, <&A53_1>, <&A53_2>, <&A53_3>;
};
psci {
@@ -971,7 +970,7 @@
clock-names = "usb1_ctrl_root_clk";
assigned-clocks = <&clk IMX8MN_CLK_USB_BUS>;
assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>;
- fsl,usbphy = <&usbphynop1>;
+ phys = <&usbphynop1>;
fsl,usbmisc = <&usbmisc1 0>;
status = "disabled";
};
@@ -1039,6 +1038,7 @@
};
usbphynop1: usbphynop1 {
+ #phy-cells = <0>;
compatible = "usb-nop-xceiv";
clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index f4eaab3ecf03..9b07b26230a1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -135,11 +135,21 @@
clock-output-names = "clk_ext4";
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ dsp_reserved: dsp@92400000 {
+ reg = <0 0x92400000 0 0x2000000>;
+ no-map;
+ };
+ };
+
pmu {
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_PPI 7
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
- interrupt-affinity = <&A53_0>, <&A53_1>, <&A53_2>, <&A53_3>;
};
psci {
@@ -698,6 +708,14 @@
#mbox-cells = <2>;
};
+ mu2: mailbox@30e60000 {
+ compatible = "fsl,imx8mp-mu", "fsl,imx6sx-mu";
+ reg = <0x30e60000 0x10000>;
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <2>;
+ status = "disabled";
+ };
+
i2c5: i2c@30ad0000 {
compatible = "fsl,imx8mp-i2c", "fsl,imx21-i2c";
#address-cells = <1>;
@@ -938,5 +956,16 @@
snps,dis-u2-freeclk-exists-quirk;
};
};
+
+ dsp: dsp@3b6e8000 {
+ compatible = "fsl,imx8mp-dsp";
+ reg = <0x3b6e8000 0x88000>;
+ mbox-names = "txdb0", "txdb1",
+ "rxdb0", "rxdb1";
+ mboxes = <&mu2 2 0>, <&mu2 2 1>,
+ <&mu2 3 0>, <&mu2 3 1>;
+ memory-region = <&dsp_reserved>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
index 4d2035e3dd7c..49f9db971f3b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
@@ -403,9 +403,9 @@
assigned-clocks = <&clk IMX8MQ_CLK_USDHC2>;
assigned-clock-rates = <200000000>;
pinctrl-names = "default", "state_100mhz", "state_200mhz";
- pinctrl-0 = <&pinctrl_usdhc2>;
- pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
- pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
vmmc-supply = <&reg_usdhc2_vmmc>;
status = "okay";
@@ -423,7 +423,6 @@
fsl,pins = <
MX8MQ_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x19
>;
-
};
pinctrl_fec1: fec1grp {
@@ -480,7 +479,6 @@
MX8MQ_IOMUXC_NAND_DATA01_QSPI_A_DATA1 0x82
MX8MQ_IOMUXC_NAND_DATA02_QSPI_A_DATA2 0x82
MX8MQ_IOMUXC_NAND_DATA03_QSPI_A_DATA3 0x82
-
>;
};
@@ -565,6 +563,12 @@
>;
};
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41
+ >;
+ };
+
pinctrl_usdhc2: usdhc2grp {
fsl,pins = <
MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-mnt-reform2.dts b/arch/arm64/boot/dts/freescale/imx8mq-mnt-reform2.dts
new file mode 100644
index 000000000000..2535268f0984
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-mnt-reform2.dts
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/*
+ * Copyright 2019-2021 MNT Research GmbH
+ * Copyright 2021 Lucas Stach <dev@lynxeye.de>
+ */
+
+/dts-v1/;
+
+#include "imx8mq-nitrogen-som.dtsi"
+
+/ {
+ model = "MNT Reform 2";
+ compatible = "mntre,reform2", "boundary,imx8mq-nitrogen8m-som", "fsl,imx8mq";
+
+ pcie1_refclk: clock-pcie1-refclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ };
+
+ reg_main_5v: regulator-main-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_main_3v3: regulator-main-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_main_usb: regulator-main-usb {
+ compatible = "regulator-fixed";
+ regulator-name = "USB_PWR";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&reg_main_5v>;
+ };
+
+ sound {
+ compatible = "fsl,imx-audio-wm8960";
+ audio-cpu = <&sai2>;
+ audio-codec = <&wm8960>;
+ audio-routing =
+ "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Ext Spk", "SPK_LP",
+ "Ext Spk", "SPK_LN",
+ "Ext Spk", "SPK_RP",
+ "Ext Spk", "SPK_RN",
+ "LINPUT1", "Mic Jack",
+ "Mic Jack", "MICB",
+ "LINPUT2", "Line In Jack",
+ "RINPUT2", "Line In Jack";
+ model = "wm8960-audio";
+ };
+};
+
+&fec1 {
+ status = "okay";
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ wm8960: codec@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ clocks = <&clk IMX8MQ_CLK_SAI2_ROOT>;
+ clock-names = "mclk";
+ #sound-dai-cells = <0>;
+ };
+
+ rtc@68 {
+ compatible = "nxp,pcf8523";
+ reg = <0x68>;
+ };
+};
+
+&pcie1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie1>;
+ reset-gpio = <&gpio3 23 GPIO_ACTIVE_LOW>;
+ clocks = <&clk IMX8MQ_CLK_PCIE2_ROOT>,
+ <&clk IMX8MQ_CLK_PCIE2_AUX>,
+ <&clk IMX8MQ_CLK_PCIE2_PHY>,
+ <&pcie1_refclk>;
+ clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus";
+ status = "okay";
+};
+
+&reg_1p8v {
+ vin-supply = <&reg_main_5v>;
+};
+
+&reg_snvs {
+ vin-supply = <&reg_main_5v>;
+};
+
+&reg_arm_dram {
+ vin-supply = <&reg_main_5v>;
+};
+
+&reg_dram_1p1v {
+ vin-supply = <&reg_main_5v>;
+};
+
+&reg_soc_gpu_vpu {
+ vin-supply = <&reg_main_5v>;
+};
+
+&sai2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2>;
+ assigned-clocks = <&clk IMX8MQ_CLK_SAI2>;
+ assigned-clock-parents = <&clk IMX8MQ_CLK_25M>;
+ assigned-clock-rates = <25000000>;
+ fsl,sai-mclk-direction-output;
+ fsl,sai-asynchronous;
+ status = "okay";
+};
+
+&snvs_rtc {
+ status = "disabled";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&usb3_phy0 {
+ vbus-supply = <&reg_main_usb>;
+ status = "okay";
+};
+
+&usb3_phy1 {
+ vbus-supply = <&reg_main_usb>;
+ status = "okay";
+};
+
+&usb_dwc3_0 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usdhc2 {
+ assigned-clocks = <&clk IMX8MQ_CLK_USDHC2>;
+ assigned-clock-rates = <200000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ vqmmc-supply = <&reg_main_3v3>;
+ vmmc-supply = <&reg_main_3v3>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C3_SCL_I2C3_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C3_SDA_I2C3_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_pcie1: pcie1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SAI5_RXD2_GPIO3_IO23 0x16
+ >;
+ };
+
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0 0xd6
+ MX8MQ_IOMUXC_SAI2_RXFS_SAI2_RX_SYNC 0xd6
+ MX8MQ_IOMUXC_SAI2_TXC_SAI2_TX_BCLK 0xd6
+ MX8MQ_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC 0xd6
+ MX8MQ_IOMUXC_SAI2_RXC_SAI2_RX_BCLK 0xd6
+ MX8MQ_IOMUXC_SAI2_MCLK_SAI2_MCLK 0xd6
+ MX8MQ_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0 0xd6
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x45
+ MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x45
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-nitrogen-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen-som.dtsi
new file mode 100644
index 000000000000..36fc428ebe30
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen-som.dtsi
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018 Boundary Devices
+ * Copyright 2021 Lucas Stach <dev@lynxeye.de>
+ */
+
+#include "imx8mq.dtsi"
+
+/ {
+ model = "Boundary Devices i.MX8MQ Nitrogen8M";
+ compatible = "boundary,imx8mq-nitrogen8m-som", "fsl,imx8mq";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ reg_1p8v: regulator-fixed-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "1P8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reg_snvs: regulator-fixed-snvs {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_SNVS";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&{/opp-table/opp-800000000} {
+ opp-microvolt = <1000000>;
+};
+
+&{/opp-table/opp-1000000000} {
+ opp-microvolt = <1000000>;
+};
+
+&A53_0 {
+ cpu-supply = <&reg_arm_dram>;
+};
+
+&A53_1 {
+ cpu-supply = <&reg_arm_dram>;
+};
+
+&A53_2 {
+ cpu-supply = <&reg_arm_dram>;
+};
+
+&A53_3 {
+ cpu-supply = <&reg_arm_dram>;
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@4 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <4>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ i2c-mux@70 {
+ compatible = "nxp,pca9546";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_pca9546>;
+ reg = <0x70>;
+ reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c1a: i2c@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_arm_dram: regulator@60 {
+ compatible = "fcs,fan53555";
+ reg = <0x60>;
+ regulator-name = "VDD_ARM_DRAM_1V";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+ };
+
+ i2c1b: i2c@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_dram_1p1v: regulator@60 {
+ compatible = "fcs,fan53555";
+ reg = <0x60>;
+ regulator-name = "NVCC_DRAM_1P1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+ };
+
+ i2c1c: i2c@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_soc_gpu_vpu: regulator@60 {
+ compatible = "fcs,fan53555";
+ reg = <0x60>;
+ regulator-name = "VDD_SOC_GPU_VPU";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-always-on;
+ };
+ };
+
+ i2c1d: i2c@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&pgc_gpu {
+ power-supply = <&reg_soc_gpu_vpu>;
+};
+
+&pgc_vpu {
+ power-supply = <&reg_soc_gpu_vpu>;
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&usdhc1 {
+ assigned-clocks = <&clk IMX8MQ_CLK_USDHC1>;
+ assigned-clock-rates = <400000000>;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ vqmmc-supply = <&reg_1p8v>;
+ vmmc-supply = <&reg_snvs>;
+ bus-width = <8>;
+ non-removable;
+ no-mmc-hs400;
+ no-sdio;
+ no-sd;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23
+ MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19
+ MX8MQ_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x59
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c1_pca9546: i2c1-pca9546grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x49
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x45
+ MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x45
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3
+ MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x8d
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xcd
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xcd
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xcd
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xcd
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xcd
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xcd
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xcd
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xcd
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xcd
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x9f
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xdf
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xdf
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xdf
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xdf
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xdf
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xdf
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xdf
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xdf
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xdf
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 91df9c5350ae..4066b1612655 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -193,7 +193,6 @@
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
- interrupt-affinity = <&A53_0>, <&A53_1>, <&A53_2>, <&A53_3>;
};
psci {
@@ -1099,6 +1098,110 @@
status = "disabled";
};
+ mipi_csi1: csi@30a70000 {
+ compatible = "fsl,imx8mq-mipi-csi2";
+ reg = <0x30a70000 0x1000>;
+ clocks = <&clk IMX8MQ_CLK_CSI1_CORE>,
+ <&clk IMX8MQ_CLK_CSI1_ESC>,
+ <&clk IMX8MQ_CLK_CSI1_PHY_REF>;
+ clock-names = "core", "esc", "ui";
+ assigned-clocks = <&clk IMX8MQ_CLK_CSI1_CORE>,
+ <&clk IMX8MQ_CLK_CSI1_PHY_REF>,
+ <&clk IMX8MQ_CLK_CSI1_ESC>;
+ assigned-clock-rates = <266000000>, <333000000>, <66000000>;
+ assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_266M>,
+ <&clk IMX8MQ_SYS2_PLL_1000M>,
+ <&clk IMX8MQ_SYS1_PLL_800M>;
+ power-domains = <&pgc_mipi_csi1>;
+ resets = <&src IMX8MQ_RESET_MIPI_CSI1_CORE_RESET>,
+ <&src IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET>,
+ <&src IMX8MQ_RESET_MIPI_CSI1_ESC_RESET>;
+ fsl,mipi-phy-gpr = <&iomuxc_gpr 0x88>;
+ interconnects = <&noc IMX8MQ_ICM_CSI1 &noc IMX8MQ_ICS_DRAM>;
+ interconnect-names = "dram";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ csi1_mipi_ep: endpoint {
+ remote-endpoint = <&csi1_ep>;
+ };
+ };
+ };
+ };
+
+ csi1: csi@30a90000 {
+ compatible = "fsl,imx8mq-csi", "fsl,imx7-csi";
+ reg = <0x30a90000 0x10000>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MQ_CLK_CSI1_ROOT>;
+ clock-names = "mclk";
+ status = "disabled";
+
+ port {
+ csi1_ep: endpoint {
+ remote-endpoint = <&csi1_mipi_ep>;
+ };
+ };
+ };
+
+ mipi_csi2: csi@30b60000 {
+ compatible = "fsl,imx8mq-mipi-csi2";
+ reg = <0x30b60000 0x1000>;
+ clocks = <&clk IMX8MQ_CLK_CSI2_CORE>,
+ <&clk IMX8MQ_CLK_CSI2_ESC>,
+ <&clk IMX8MQ_CLK_CSI2_PHY_REF>;
+ clock-names = "core", "esc", "ui";
+ assigned-clocks = <&clk IMX8MQ_CLK_CSI2_CORE>,
+ <&clk IMX8MQ_CLK_CSI2_PHY_REF>,
+ <&clk IMX8MQ_CLK_CSI2_ESC>;
+ assigned-clock-rates = <266000000>, <333000000>, <66000000>;
+ assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_266M>,
+ <&clk IMX8MQ_SYS2_PLL_1000M>,
+ <&clk IMX8MQ_SYS1_PLL_800M>;
+ power-domains = <&pgc_mipi_csi2>;
+ resets = <&src IMX8MQ_RESET_MIPI_CSI2_CORE_RESET>,
+ <&src IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET>,
+ <&src IMX8MQ_RESET_MIPI_CSI2_ESC_RESET>;
+ fsl,mipi-phy-gpr = <&iomuxc_gpr 0xa4>;
+ interconnects = <&noc IMX8MQ_ICM_CSI2 &noc IMX8MQ_ICS_DRAM>;
+ interconnect-names = "dram";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ csi2_mipi_ep: endpoint {
+ remote-endpoint = <&csi2_ep>;
+ };
+ };
+ };
+ };
+
+ csi2: csi@30b80000 {
+ compatible = "fsl,imx8mq-csi", "fsl,imx7-csi";
+ reg = <0x30b80000 0x10000>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX8MQ_CLK_CSI2_ROOT>;
+ clock-names = "mclk";
+ status = "disabled";
+
+ port {
+ csi2_ep: endpoint {
+ remote-endpoint = <&csi2_mipi_ep>;
+ };
+ };
+ };
+
mu: mailbox@30aa0000 {
compatible = "fsl,imx8mq-mu", "fsl,imx6sx-mu";
reg = <0x30aa0000 0x10000>;
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi
new file mode 100644
index 000000000000..7764b4146e0a
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 NXP
+ */
+
+&jpegdec {
+ compatible = "nxp,imx8qm-jpgdec", "nxp,imx8qxp-jpgdec";
+};
+
+&jpegenc {
+ compatible = "nxp,imx8qm-jpgdec", "nxp,imx8qxp-jpgenc";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm.dtsi b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
index 12cd059b339b..aebbe2b84aa1 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
@@ -166,11 +166,13 @@
};
/* sorted in register address */
+ #include "imx8-ss-img.dtsi"
#include "imx8-ss-dma.dtsi"
#include "imx8-ss-conn.dtsi"
#include "imx8-ss-lsio.dtsi"
};
+#include "imx8qm-ss-img.dtsi"
#include "imx8qm-ss-dma.dtsi"
#include "imx8qm-ss-conn.dtsi"
#include "imx8qm-ss-lsio.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts b/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts
index 47bb68823b24..7d00e17f0447 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts
@@ -195,7 +195,7 @@
fsl,pins = <
IMX8QXP_UART0_RX_ADMA_UART0_RX 0X06000020
IMX8QXP_UART0_TX_ADMA_UART0_TX 0X06000020
- IMX8QXP_FLEXCAN0_TX_ADMA_UART0_CTS_B 0x06000020
+ IMX8QXP_FLEXCAN0_TX_ADMA_UART0_CTS_B 0x06000020
IMX8QXP_FLEXCAN0_RX_ADMA_UART0_RTS_B 0x06000020
>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi
new file mode 100644
index 000000000000..3a087317591d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-ss-img.dtsi
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+&jpegdec {
+ compatible = "nxp,imx8qxp-jpgdec";
+};
+
+&jpegenc {
+ compatible = "nxp,imx8qxp-jpgenc";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
index 1e6b4995091e..617618edf77e 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
@@ -141,7 +141,7 @@
};
pmu {
- compatible = "arm,armv8-pmuv3";
+ compatible = "arm,cortex-a35-pmu";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
};
@@ -258,12 +258,14 @@
};
/* sorted in register address */
+ #include "imx8-ss-img.dtsi"
#include "imx8-ss-adma.dtsi"
#include "imx8-ss-conn.dtsi"
#include "imx8-ss-ddr.dtsi"
#include "imx8-ss-lsio.dtsi"
};
+#include "imx8qxp-ss-img.dtsi"
#include "imx8qxp-ss-adma.dtsi"
#include "imx8qxp-ss-conn.dtsi"
#include "imx8qxp-ss-lsio.dtsi"
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index f1ec87c05842..2d5c1a348716 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -1002,7 +1002,7 @@
<0x0 0xf3f20000 0x0 0x40000>,
<0x0 0xf5000000 0x0 0x2000>;
reg-names = "dbi", "apb", "phy", "config";
- bus-range = <0x0 0x1>;
+ bus-range = <0x0 0xff>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile
index 34efe0fb6f37..c686a8dd3ca5 100644
--- a/arch/arm64/boot/dts/marvell/Makefile
+++ b/arch/arm64/boot/dts/marvell/Makefile
@@ -16,5 +16,10 @@ dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-mcbin-singleshot.dtb
dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-puzzle-m801.dtb
dtb-$(CONFIG_ARCH_MVEBU) += armada-8080-db.dtb
dtb-$(CONFIG_ARCH_MVEBU) += cn9130-db.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9130-db-B.dtb
dtb-$(CONFIG_ARCH_MVEBU) += cn9131-db.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9131-db-B.dtb
dtb-$(CONFIG_ARCH_MVEBU) += cn9132-db.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9132-db-B.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9130-crb-A.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += cn9130-crb-B.dtb
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
index a05b1ab2dd12..04da07ae4420 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
@@ -135,6 +135,23 @@
pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>;
status = "okay";
reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>;
+ /*
+ * U-Boot port for Turris Mox has a bug which always expects that "ranges" DT property
+ * contains exactly 2 ranges with 3 (child) address cells, 2 (parent) address cells and
+ * 2 size cells and also expects that the second range starts at 16 MB offset. If these
+ * conditions are not met then U-Boot crashes during loading kernel DTB file. PCIe address
+ * space is 128 MB long, so the best split between MEM and IO is to use fixed 16 MB window
+ * for IO and the rest 112 MB (64+32+16) for MEM, despite that maximal IO size is just 64 kB.
+ * This bug is not present in U-Boot ports for other Armada 3700 devices and is fixed in
+ * U-Boot version 2021.07. See relevant U-Boot commits (the last one contains fix):
+ * https://source.denx.de/u-boot/u-boot/-/commit/cb2ddb291ee6fcbddd6d8f4ff49089dfe580f5d7
+ * https://source.denx.de/u-boot/u-boot/-/commit/c64ac3b3185aeb3846297ad7391fc6df8ecd73bf
+ * https://source.denx.de/u-boot/u-boot/-/commit/4a82fca8e330157081fc132a591ebd99ba02ee33
+ */
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x81000000 0 0xe8000000 0 0xe8000000 0 0x01000000 /* Port 0 IO */
+ 0x82000000 0 0xe9000000 0 0xe9000000 0 0x07000000>; /* Port 0 MEM */
/* enabled by U-Boot if PCIe module is present */
status = "disabled";
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index 5db81a416cd6..9acc5d2b5a00 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -489,8 +489,15 @@
#interrupt-cells = <1>;
msi-parent = <&pcie0>;
msi-controller;
- ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x1000000 /* Port 0 MEM */
- 0x81000000 0 0xe9000000 0 0xe9000000 0 0x10000>; /* Port 0 IO*/
+ /*
+ * The 128 MiB address range [0xe8000000-0xf0000000] is
+ * dedicated for PCIe and can be assigned to 8 windows
+ * with size a power of two. Use one 64 KiB window for
+ * IO at the end and the remaining seven windows
+ * (totaling 127 MiB) for MEM.
+ */
+ ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x07f00000 /* Port 0 MEM */
+ 0x81000000 0 0xefff0000 0 0xefff0000 0 0x00010000>; /* Port 0 IO */
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc 0>,
<0 0 0 2 &pcie_intc 1>,
diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
index 51f3e2907597..cd326fe224ce 100644
--- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
@@ -282,7 +282,7 @@
&cp0_eth0 {
status = "okay";
/* Network PHY */
- phy-mode = "10gbase-kr";
+ phy-mode = "10gbase-r";
/* Generic PHY, providing serdes lanes */
phys = <&cp0_comphy2 0>;
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
index 0ec0d5625818..8729c6467303 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
@@ -20,7 +20,7 @@
stdout-path = "serial0:115200n8";
};
- memory@00000000 {
+ memory@0 {
device_type = "memory";
reg = <0x0 0x0 0x0 0x80000000>;
};
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-db.dts b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
index e39e1efc95b6..f2e8e0df8865 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
@@ -195,7 +195,7 @@
&cp0_eth0 {
status = "okay";
- phy-mode = "10gbase-kr";
+ phy-mode = "10gbase-r";
fixed-link {
speed = <10000>;
@@ -348,7 +348,7 @@
&cp1_eth0 {
status = "okay";
- phy-mode = "10gbase-kr";
+ phy-mode = "10gbase-r";
fixed-link {
speed = <10000>;
diff --git a/arch/arm64/boot/dts/marvell/cn9130-crb-A.dts b/arch/arm64/boot/dts/marvell/cn9130-crb-A.dts
new file mode 100644
index 000000000000..a7b6dfba8af5
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-crb-A.dts
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Marvell International Ltd.
+ */
+
+#include "cn9130-crb.dtsi"
+
+/ {
+ model = "Marvell Armada CN9130-CRB-A";
+};
+
+&cp0_pcie0 {
+ status = "okay";
+ num-lanes = <4>;
+ num-viewport = <8>;
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp0_comphy0 0
+ &cp0_comphy1 0
+ &cp0_comphy2 0
+ &cp0_comphy3 0>;
+ iommu-map =
+ <0x0 &smmu 0x480 0x20>,
+ <0x100 &smmu 0x4a0 0x20>,
+ <0x200 &smmu 0x4c0 0x20>;
+ iommu-map-mask = <0x031f>;
+};
+
+&cp0_usb3_0 {
+ status = "okay";
+ usb-phy = <&cp0_usb3_0_phy0>;
+ phy-names = "usb";
+};
+
+&cp0_usb3_1 {
+ status = "okay";
+ usb-phy = <&cp0_usb3_0_phy1>;
+ phy-names = "usb";
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9130-crb-B.dts b/arch/arm64/boot/dts/marvell/cn9130-crb-B.dts
new file mode 100644
index 000000000000..0904cb0309ae
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-crb-B.dts
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Marvell International Ltd.
+ */
+
+#include "cn9130-crb.dtsi"
+
+/ {
+ model = "Marvell Armada CN9130-CRB-B";
+};
+
+&cp0_pcie0 {
+ status = "okay";
+ num-lanes = <1>;
+ num-viewport = <8>;
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp0_comphy0 0>;
+ iommu-map =
+ <0x0 &smmu 0x480 0x20>,
+ <0x100 &smmu 0x4a0 0x20>,
+ <0x200 &smmu 0x4c0 0x20>;
+ iommu-map-mask = <0x031f>;
+};
+
+&cp0_sata0 {
+ status = "okay";
+ sata-port@0 {
+ status = "okay";
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp0_comphy2 0>;
+ };
+};
+
+&cp0_usb3_0 {
+ status = "okay";
+ usb-phy = <&cp0_usb3_0_phy0>;
+ phy-names = "usb";
+ phys = <&cp0_comphy1 0>;
+};
+
+&cp0_usb3_1 {
+ status = "okay";
+ usb-phy = <&cp0_usb3_0_phy1>;
+ phy-names = "usb";
+ phys = <&cp0_comphy3 1>;
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi b/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi
new file mode 100644
index 000000000000..505ae69289f6
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Marvell International Ltd.
+ */
+
+#include "cn9130.dtsi" /* include SoC device tree */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ i2c0 = &cp0_i2c0;
+ ethernet0 = &cp0_eth0;
+ ethernet1 = &cp0_eth1;
+ ethernet2 = &cp0_eth2;
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x80000000>;
+ };
+
+ ap0_reg_mmc_vccq: ap0_mmc_vccq@0 {
+ compatible = "regulator-gpio";
+ regulator-name = "ap0_mmc_vccq";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&expander0 5 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x1
+ 3300000 0x0>;
+ };
+
+ cp0_reg_usb3_vbus1: cp0_usb3_vbus@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "cp0-xhci1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&expander0 8 GPIO_ACTIVE_HIGH>;
+ };
+
+ cp0_usb3_0_phy0: cp0_usb3_phy0 {
+ compatible = "usb-nop-xceiv";
+ };
+
+ cp0_usb3_0_phy1: cp0_usb3_phy1 {
+ compatible = "usb-nop-xceiv";
+ vcc-supply = <&cp0_reg_usb3_vbus1>;
+ };
+
+ cp0_reg_sd_vccq: cp0_sd_vccq@0 {
+ compatible = "regulator-gpio";
+ regulator-name = "cp0_sd_vccq";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&cp0_gpio2 18 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x1
+ 3300000 0x0>;
+ };
+
+ cp0_reg_sd_vcc: cp0_sd_vcc@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "cp0_sd_vcc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&cp0_gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+/* on-board eMMC U6 */
+&ap_sdhci0 {
+ pinctrl-names = "default";
+ bus-width = <8>;
+ status = "okay";
+ mmc-ddr-1_8v;
+ vqmmc-supply = <&ap0_reg_mmc_vccq>;
+};
+
+&cp0_syscon0 {
+ cp0_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+
+ cp0_i2c0_pins: cp0-i2c-pins-0 {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "i2c0";
+ };
+ cp0_i2c1_pins: cp0-i2c-pins-1 {
+ marvell,pins = "mpp35", "mpp36";
+ marvell,function = "i2c1";
+ };
+ cp0_sdhci_cd_pins_crb: cp0-sdhci-cd-pins-crb {
+ marvell,pins = "mpp55";
+ marvell,function = "gpio";
+ };
+ cp0_sdhci_pins: cp0-sdhi-pins-0 {
+ marvell,pins = "mpp56", "mpp57", "mpp58",
+ "mpp59", "mpp60", "mpp61";
+ marvell,function = "sdio";
+ };
+ cp0_spi0_pins: cp0-spi-pins-0 {
+ marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
+ marvell,function = "spi1";
+ };
+ };
+};
+
+&cp0_i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_i2c0_pins>;
+ status = "okay";
+ clock-frequency = <100000>;
+ expander0: mcp23x17@20 {
+ compatible = "microchip,mcp23017";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x20>;
+ status = "okay";
+ };
+};
+
+&cp0_i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_i2c1_pins>;
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+
+&cp0_sdhci0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_sdhci_pins
+ &cp0_sdhci_cd_pins_crb>;
+ bus-width = <4>;
+ cd-gpios = <&cp0_gpio2 23 GPIO_ACTIVE_HIGH>;
+ vqmmc-supply = <&cp0_reg_sd_vccq>;
+ vmmc-supply = <&cp0_reg_sd_vcc>;
+ status = "okay";
+};
+
+&cp0_spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_spi0_pins>;
+ reg = <0x700680 0x50>, /* control */
+ <0x2000000 0x1000000>; /* CS0 */
+ status = "okay";
+
+ spi-flash@0 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ /* On-board MUX does not allow higher frequencies */
+ spi-max-frequency = <40000000>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x0 0x200000>;
+ };
+
+ partition@400000 {
+ label = "Filesystem";
+ reg = <0x200000 0xe00000>;
+ };
+ };
+ };
+};
+
+&cp0_mdio {
+ status = "okay";
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
+
+&cp0_xmdio {
+ status = "okay";
+ nbaset_phy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <0>;
+ };
+};
+
+&cp0_ethernet {
+ status = "okay";
+};
+
+&cp0_eth0 {
+ /* This port is connected to 88E6393X switch */
+ status = "okay";
+ phy-mode = "10gbase-r";
+ managed = "in-band-status";
+ phys = <&cp0_comphy4 0>;
+};
+
+&cp0_eth1 {
+ status = "okay";
+ phy = <&phy0>;
+ phy-mode = "rgmii-id";
+};
+
+&cp0_eth2 {
+ /* This port uses "2500base-t" phy-mode */
+ status = "disabled";
+ phy = <&nbaset_phy0>;
+ phys = <&cp0_comphy5 2>;
+};
+
diff --git a/arch/arm64/boot/dts/marvell/cn9130-db-B.dts b/arch/arm64/boot/dts/marvell/cn9130-db-B.dts
new file mode 100644
index 000000000000..57e41cacd483
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-db-B.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2020 Marvell International Ltd.
+ *
+ * Device tree for the CN9130-DB board (setup "B").
+ */
+
+#include "cn9130-db.dtsi"
+
+/ {
+ model = "Marvell Armada CN9130-DB setup B";
+};
+
+/* Setup B has NAND flash as a boot device, while regular setup uses SPI flash.
+ * Since CP0 SPI1 and CP0 NAND are sharing some pins, they cannot be activated
+ * simultaneously. When NAND controller is enabled, SPI1 should be disabled.
+ */
+
+&cp0_nand_controller {
+ status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/marvell/cn9130-db.dts b/arch/arm64/boot/dts/marvell/cn9130-db.dts
index 9758609541c7..994f347f2973 100644
--- a/arch/arm64/boot/dts/marvell/cn9130-db.dts
+++ b/arch/arm64/boot/dts/marvell/cn9130-db.dts
@@ -5,409 +5,18 @@
* Device tree for the CN9130-DB board.
*/
-#include "cn9130.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
+#include "cn9130-db.dtsi"
/ {
- model = "Marvell Armada CN9130-DB";
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- aliases {
- gpio1 = &cp0_gpio1;
- gpio2 = &cp0_gpio2;
- i2c0 = &cp0_i2c0;
- ethernet0 = &cp0_eth0;
- ethernet1 = &cp0_eth1;
- ethernet2 = &cp0_eth2;
- spi1 = &cp0_spi0;
- spi2 = &cp0_spi1;
- };
-
- memory@00000000 {
- device_type = "memory";
- reg = <0x0 0x0 0x0 0x80000000>;
- };
-
- ap0_reg_sd_vccq: ap0_sd_vccq@0 {
- compatible = "regulator-gpio";
- regulator-name = "ap0_sd_vccq";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- gpios = <&expander0 8 GPIO_ACTIVE_HIGH>;
- states = <1800000 0x1 3300000 0x0>;
- };
-
- cp0_reg_usb3_vbus0: cp0_usb3_vbus@0 {
- compatible = "regulator-fixed";
- regulator-name = "cp0-xhci0-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&expander0 0 GPIO_ACTIVE_HIGH>;
- };
-
- cp0_usb3_0_phy0: cp0_usb3_phy@0 {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&cp0_reg_usb3_vbus0>;
- };
-
- cp0_reg_usb3_vbus1: cp0_usb3_vbus@1 {
- compatible = "regulator-fixed";
- regulator-name = "cp0-xhci1-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&expander0 1 GPIO_ACTIVE_HIGH>;
- };
-
- cp0_usb3_0_phy1: cp0_usb3_phy@1 {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&cp0_reg_usb3_vbus1>;
- };
-
- cp0_reg_sd_vccq: cp0_sd_vccq@0 {
- compatible = "regulator-gpio";
- regulator-name = "cp0_sd_vccq";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- gpios = <&expander0 15 GPIO_ACTIVE_HIGH>;
- states = <1800000 0x1
- 3300000 0x0>;
- };
-
- cp0_reg_sd_vcc: cp0_sd_vcc@0 {
- compatible = "regulator-fixed";
- regulator-name = "cp0_sd_vcc";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&expander0 14 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- regulator-always-on;
- };
-
- cp0_sfp_eth0: sfp-eth@0 {
- compatible = "sff,sfp";
- i2c-bus = <&cp0_sfpp0_i2c>;
- los-gpio = <&cp0_module_expander1 11 GPIO_ACTIVE_HIGH>;
- mod-def0-gpio = <&cp0_module_expander1 10 GPIO_ACTIVE_LOW>;
- tx-disable-gpio = <&cp0_module_expander1 9 GPIO_ACTIVE_HIGH>;
- tx-fault-gpio = <&cp0_module_expander1 8 GPIO_ACTIVE_HIGH>;
- /*
- * SFP cages are unconnected on early PCBs because of an the I2C
- * lanes not being connected. Prevent the port for being
- * unusable by disabling the SFP node.
- */
- status = "disabled";
- };
-};
-
-&uart0 {
- status = "okay";
-};
-
-/* on-board eMMC - U9 */
-&ap_sdhci0 {
- pinctrl-names = "default";
- bus-width = <8>;
- mmc-ddr-1_8v;
- mmc-hs400-1_8v;
- vqmmc-supply = <&ap0_reg_sd_vccq>;
- status = "okay";
-};
-
-&cp0_crypto {
- status = "disabled";
-};
-
-&cp0_ethernet {
- status = "okay";
-};
-
-/* SLM-1521-V2, CON9 */
-&cp0_eth0 {
- status = "disabled";
- phy-mode = "10gbase-kr";
- /* Generic PHY, providing serdes lanes */
- phys = <&cp0_comphy4 0>;
- managed = "in-band-status";
- sfp = <&cp0_sfp_eth0>;
-};
-
-/* CON56 */
-&cp0_eth1 {
- status = "okay";
- phy = <&phy0>;
- phy-mode = "rgmii-id";
-};
-
-/* CON57 */
-&cp0_eth2 {
- status = "okay";
- phy = <&phy1>;
- phy-mode = "rgmii-id";
-};
-
-&cp0_gpio1 {
- status = "okay";
-};
-
-&cp0_gpio2 {
- status = "okay";
-};
-
-&cp0_i2c0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&cp0_i2c0_pins>;
- clock-frequency = <100000>;
-
- /* U36 */
- expander0: pca953x@21 {
- compatible = "nxp,pca9555";
- pinctrl-names = "default";
- gpio-controller;
- #gpio-cells = <2>;
- reg = <0x21>;
- status = "okay";
- };
-
- /* U42 */
- eeprom0: eeprom@50 {
- compatible = "atmel,24c64";
- reg = <0x50>;
- pagesize = <0x20>;
- };
-
- /* U38 */
- eeprom1: eeprom@57 {
- compatible = "atmel,24c64";
- reg = <0x57>;
- pagesize = <0x20>;
- };
-};
-
-&cp0_i2c1 {
- status = "okay";
- clock-frequency = <100000>;
-
- /* SLM-1521-V2 - U3 */
- i2c-mux@72 { /* verify address - depends on dpr */
- compatible = "nxp,pca9544";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x72>;
- cp0_sfpp0_i2c: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- /* U12 */
- cp0_module_expander1: pca9555@21 {
- compatible = "nxp,pca9555";
- pinctrl-names = "default";
- gpio-controller;
- #gpio-cells = <2>;
- reg = <0x21>;
- };
-
- };
- };
-};
-
-&cp0_mdio {
- status = "okay";
-
- phy0: ethernet-phy@0 {
- reg = <0>;
- };
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
-};
-
-/* U54 */
-&cp0_nand_controller {
- pinctrl-names = "default";
- pinctrl-0 = <&nand_pins &nand_rb>;
-
- nand@0 {
- reg = <0>;
- label = "main-storage";
- nand-rb = <0>;
- nand-ecc-mode = "hw";
- 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 0x200000>;
- };
- partition@200000 {
- label = "Linux";
- reg = <0x200000 0xe00000>;
- };
- partition@1000000 {
- label = "Filesystem";
- reg = <0x1000000 0x3f000000>;
- };
- };
- };
-};
-
-/* SLM-1521-V2, CON6 */
-&cp0_pcie0 {
- status = "okay";
- num-lanes = <4>;
- num-viewport = <8>;
- /* Generic PHY, providing serdes lanes */
- phys = <&cp0_comphy0 0
- &cp0_comphy1 0
- &cp0_comphy2 0
- &cp0_comphy3 0>;
-};
-
-&cp0_sata0 {
- status = "okay";
-
- /* SLM-1521-V2, CON2 */
- sata-port@1 {
- status = "okay";
- /* Generic PHY, providing serdes lanes */
- phys = <&cp0_comphy5 1>;
- };
+ model = "Marvell Armada CN9130-DB setup A";
};
-/* CON 28 */
-&cp0_sdhci0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&cp0_sdhci_pins
- &cp0_sdhci_cd_pins>;
- bus-width = <4>;
- cd-gpios = <&cp0_gpio2 11 GPIO_ACTIVE_LOW>;
- no-1-8-v;
- vqmmc-supply = <&cp0_reg_sd_vccq>;
- vmmc-supply = <&cp0_reg_sd_vcc>;
-};
+/* Setup A has SPI1 flash as a boot device, while setup B uses NAND flash.
+ * Since CP0 SPI1 and CP0 NAND are sharing some pins, they cannot be activated
+ * simultaneously. When SPI controller is enabled, NAND should be disabled.
+ */
-/* U55 */
&cp0_spi1 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&cp0_spi0_pins>;
- reg = <0x700680 0x50>;
-
- spi-flash@0 {
- #address-cells = <0x1>;
- #size-cells = <0x1>;
- compatible = "jedec,spi-nor";
- reg = <0x0>;
- /* On-board MUX does not allow higher frequencies */
- spi-max-frequency = <40000000>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "U-Boot-0";
- reg = <0x0 0x200000>;
- };
-
- partition@400000 {
- label = "Filesystem-0";
- reg = <0x200000 0xe00000>;
- };
- };
- };
};
-&cp0_syscon0 {
- cp0_pinctrl: pinctrl {
- compatible = "marvell,cp115-standalone-pinctrl";
-
- cp0_i2c0_pins: cp0-i2c-pins-0 {
- marvell,pins = "mpp37", "mpp38";
- marvell,function = "i2c0";
- };
- cp0_i2c1_pins: cp0-i2c-pins-1 {
- marvell,pins = "mpp35", "mpp36";
- marvell,function = "i2c1";
- };
- cp0_ge1_rgmii_pins: cp0-ge-rgmii-pins-0 {
- marvell,pins = "mpp0", "mpp1", "mpp2",
- "mpp3", "mpp4", "mpp5",
- "mpp6", "mpp7", "mpp8",
- "mpp9", "mpp10", "mpp11";
- marvell,function = "ge0";
- };
- cp0_ge2_rgmii_pins: cp0-ge-rgmii-pins-1 {
- marvell,pins = "mpp44", "mpp45", "mpp46",
- "mpp47", "mpp48", "mpp49",
- "mpp50", "mpp51", "mpp52",
- "mpp53", "mpp54", "mpp55";
- marvell,function = "ge1";
- };
- cp0_sdhci_cd_pins: cp0-sdhci-cd-pins-0 {
- marvell,pins = "mpp43";
- marvell,function = "gpio";
- };
- cp0_sdhci_pins: cp0-sdhi-pins-0 {
- marvell,pins = "mpp56", "mpp57", "mpp58",
- "mpp59", "mpp60", "mpp61";
- marvell,function = "sdio";
- };
- cp0_spi0_pins: cp0-spi-pins-0 {
- marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
- marvell,function = "spi1";
- };
- nand_pins: nand-pins {
- marvell,pins = "mpp15", "mpp16", "mpp17", "mpp18",
- "mpp19", "mpp20", "mpp21", "mpp22",
- "mpp23", "mpp24", "mpp25", "mpp26",
- "mpp27";
- marvell,function = "dev";
- };
- nand_rb: nand-rb {
- marvell,pins = "mpp13";
- marvell,function = "nf";
- };
- };
-};
-
-&cp0_utmi {
- status = "okay";
-};
-
-&cp0_usb3_0 {
- status = "okay";
- usb-phy = <&cp0_usb3_0_phy0>;
- phys = <&cp0_utmi0>;
- phy-names = "utmi";
- dr_mode = "host";
-};
-
-&cp0_usb3_1 {
- status = "okay";
- usb-phy = <&cp0_usb3_0_phy1>;
- phys = <&cp0_utmi1>;
- phy-names = "utmi";
- dr_mode = "host";
-};
diff --git a/arch/arm64/boot/dts/marvell/cn9130-db.dtsi b/arch/arm64/boot/dts/marvell/cn9130-db.dtsi
new file mode 100644
index 000000000000..c00b69b88bd2
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9130-db.dtsi
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * Device tree for the CN9130-DB board.
+ */
+
+#include "cn9130.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ gpio1 = &cp0_gpio1;
+ gpio2 = &cp0_gpio2;
+ i2c0 = &cp0_i2c0;
+ ethernet0 = &cp0_eth0;
+ ethernet1 = &cp0_eth1;
+ ethernet2 = &cp0_eth2;
+ spi1 = &cp0_spi0;
+ spi2 = &cp0_spi1;
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x80000000>;
+ };
+
+ ap0_reg_sd_vccq: ap0_sd_vccq@0 {
+ compatible = "regulator-gpio";
+ regulator-name = "ap0_sd_vccq";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&expander0 8 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x1 3300000 0x0>;
+ };
+
+ cp0_reg_usb3_vbus0: cp0_usb3_vbus@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "cp0-xhci0-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&expander0 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ cp0_usb3_0_phy0: cp0_usb3_phy@0 {
+ compatible = "usb-nop-xceiv";
+ vcc-supply = <&cp0_reg_usb3_vbus0>;
+ };
+
+ cp0_reg_usb3_vbus1: cp0_usb3_vbus@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "cp0-xhci1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&expander0 1 GPIO_ACTIVE_HIGH>;
+ };
+
+ cp0_usb3_0_phy1: cp0_usb3_phy@1 {
+ compatible = "usb-nop-xceiv";
+ vcc-supply = <&cp0_reg_usb3_vbus1>;
+ };
+
+ cp0_reg_sd_vccq: cp0_sd_vccq@0 {
+ compatible = "regulator-gpio";
+ regulator-name = "cp0_sd_vccq";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&expander0 15 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x1
+ 3300000 0x0>;
+ };
+
+ cp0_reg_sd_vcc: cp0_sd_vcc@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "cp0_sd_vcc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&expander0 14 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ cp0_sfp_eth0: sfp-eth@0 {
+ compatible = "sff,sfp";
+ i2c-bus = <&cp0_sfpp0_i2c>;
+ los-gpio = <&cp0_module_expander1 11 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpio = <&cp0_module_expander1 10 GPIO_ACTIVE_LOW>;
+ tx-disable-gpio = <&cp0_module_expander1 9 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpio = <&cp0_module_expander1 8 GPIO_ACTIVE_HIGH>;
+ /*
+ * SFP cages are unconnected on early PCBs because of an the I2C
+ * lanes not being connected. Prevent the port for being
+ * unusable by disabling the SFP node.
+ */
+ status = "disabled";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+/* on-board eMMC - U9 */
+&ap_sdhci0 {
+ pinctrl-names = "default";
+ bus-width = <8>;
+ vqmmc-supply = <&ap0_reg_sd_vccq>;
+ status = "okay";
+};
+
+&cp0_crypto {
+ status = "disabled";
+};
+
+&cp0_ethernet {
+ status = "okay";
+};
+
+/* SLM-1521-V2, CON9 */
+&cp0_eth0 {
+ status = "okay";
+ phy-mode = "10gbase-r";
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp0_comphy4 0>;
+ managed = "in-band-status";
+ sfp = <&cp0_sfp_eth0>;
+};
+
+/* CON56 */
+&cp0_eth1 {
+ status = "okay";
+ phy = <&phy0>;
+ phy-mode = "rgmii-id";
+};
+
+/* CON57 */
+&cp0_eth2 {
+ status = "okay";
+ phy = <&phy1>;
+ phy-mode = "rgmii-id";
+};
+
+&cp0_gpio1 {
+ status = "okay";
+};
+
+&cp0_gpio2 {
+ status = "okay";
+};
+
+&cp0_i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_i2c0_pins>;
+ clock-frequency = <100000>;
+
+ /* U36 */
+ expander0: pca953x@21 {
+ compatible = "nxp,pca9555";
+ pinctrl-names = "default";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x21>;
+ status = "okay";
+ };
+
+ /* U42 */
+ eeprom0: eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ pagesize = <0x20>;
+ };
+
+ /* U38 */
+ eeprom1: eeprom@57 {
+ compatible = "atmel,24c64";
+ reg = <0x57>;
+ pagesize = <0x20>;
+ };
+};
+
+&cp0_i2c1 {
+ status = "okay";
+ clock-frequency = <100000>;
+
+ /* SLM-1521-V2 - U3 */
+ i2c-mux@72 { /* verify address - depends on dpr */
+ compatible = "nxp,pca9544";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x72>;
+ cp0_sfpp0_i2c: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ /* U12 */
+ cp0_module_expander1: pca9555@21 {
+ compatible = "nxp,pca9555";
+ pinctrl-names = "default";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x21>;
+ };
+
+ };
+ };
+};
+
+&cp0_mdio {
+ status = "okay";
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+/* U54 */
+&cp0_nand_controller {
+ status = "disabled";
+ pinctrl-names = "default";
+ pinctrl-0 = <&nand_pins &nand_rb>;
+
+ nand@0 {
+ reg = <0>;
+ label = "main-storage";
+ nand-rb = <0>;
+ nand-ecc-mode = "hw";
+ 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 0x200000>;
+ };
+ partition@200000 {
+ label = "Linux";
+ reg = <0x200000 0xe00000>;
+ };
+ partition@1000000 {
+ label = "Filesystem";
+ reg = <0x1000000 0x3f000000>;
+ };
+ };
+ };
+};
+
+/* SLM-1521-V2, CON6 */
+&cp0_pcie0 {
+ status = "okay";
+ num-lanes = <4>;
+ num-viewport = <8>;
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp0_comphy0 0
+ &cp0_comphy1 0
+ &cp0_comphy2 0
+ &cp0_comphy3 0>;
+};
+
+&cp0_sata0 {
+ status = "okay";
+
+ /* SLM-1521-V2, CON2 */
+ sata-port@1 {
+ status = "okay";
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp0_comphy5 1>;
+ };
+};
+
+/* CON 28 */
+&cp0_sdhci0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_sdhci_pins
+ &cp0_sdhci_cd_pins>;
+ bus-width = <4>;
+ cd-gpios = <&cp0_gpio2 11 GPIO_ACTIVE_LOW>;
+ no-1-8-v;
+ vqmmc-supply = <&cp0_reg_sd_vccq>;
+ vmmc-supply = <&cp0_reg_sd_vcc>;
+};
+
+/* U55 */
+&cp0_spi1 {
+ status = "disabled";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_spi0_pins>;
+ reg = <0x700680 0x50>;
+
+ spi-flash@0 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ /* On-board MUX does not allow higher frequencies */
+ spi-max-frequency = <40000000>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot-0";
+ reg = <0x0 0x200000>;
+ };
+
+ partition@400000 {
+ label = "Filesystem-0";
+ reg = <0x200000 0xe00000>;
+ };
+ };
+ };
+};
+
+&cp0_syscon0 {
+ cp0_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+
+ cp0_i2c0_pins: cp0-i2c-pins-0 {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "i2c0";
+ };
+ cp0_i2c1_pins: cp0-i2c-pins-1 {
+ marvell,pins = "mpp35", "mpp36";
+ marvell,function = "i2c1";
+ };
+ cp0_ge1_rgmii_pins: cp0-ge-rgmii-pins-0 {
+ marvell,pins = "mpp0", "mpp1", "mpp2",
+ "mpp3", "mpp4", "mpp5",
+ "mpp6", "mpp7", "mpp8",
+ "mpp9", "mpp10", "mpp11";
+ marvell,function = "ge0";
+ };
+ cp0_ge2_rgmii_pins: cp0-ge-rgmii-pins-1 {
+ marvell,pins = "mpp44", "mpp45", "mpp46",
+ "mpp47", "mpp48", "mpp49",
+ "mpp50", "mpp51", "mpp52",
+ "mpp53", "mpp54", "mpp55";
+ marvell,function = "ge1";
+ };
+ cp0_sdhci_cd_pins: cp0-sdhci-cd-pins-0 {
+ marvell,pins = "mpp43";
+ marvell,function = "gpio";
+ };
+ cp0_sdhci_pins: cp0-sdhi-pins-0 {
+ marvell,pins = "mpp56", "mpp57", "mpp58",
+ "mpp59", "mpp60", "mpp61";
+ marvell,function = "sdio";
+ };
+ cp0_spi0_pins: cp0-spi-pins-0 {
+ marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
+ marvell,function = "spi1";
+ };
+ nand_pins: nand-pins {
+ marvell,pins = "mpp15", "mpp16", "mpp17", "mpp18",
+ "mpp19", "mpp20", "mpp21", "mpp22",
+ "mpp23", "mpp24", "mpp25", "mpp26",
+ "mpp27";
+ marvell,function = "dev";
+ };
+ nand_rb: nand-rb {
+ marvell,pins = "mpp13";
+ marvell,function = "nf";
+ };
+ };
+};
+
+&cp0_utmi {
+ status = "okay";
+};
+
+&cp0_usb3_0 {
+ status = "okay";
+ usb-phy = <&cp0_usb3_0_phy0>;
+ phys = <&cp0_utmi0>;
+ phy-names = "utmi";
+ dr_mode = "host";
+};
+
+&cp0_usb3_1 {
+ status = "okay";
+ usb-phy = <&cp0_usb3_0_phy1>;
+ phys = <&cp0_utmi1>;
+ phy-names = "utmi";
+ dr_mode = "host";
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9131-db-B.dts b/arch/arm64/boot/dts/marvell/cn9131-db-B.dts
new file mode 100644
index 000000000000..183b1ec8b1f0
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9131-db-B.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2020 Marvell International Ltd.
+ *
+ * Device tree for the CN9131-DB board (setup "B").
+ */
+
+#include "cn9131-db.dtsi"
+
+/ {
+ model = "Marvell Armada CN9131-DB setup B";
+};
+
+/* Setup B has NAND flash as a boot device, while regular setup uses SPI flash.
+ * Since CP0 SPI1 and CP0 NAND are sharing some pins, they cannot be activated
+ * simultaneously. When NAND controller is enabled, SPI1 should be disabled.
+ */
+
+&cp0_nand_controller {
+ status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/marvell/cn9131-db.dts b/arch/arm64/boot/dts/marvell/cn9131-db.dts
index ba2d4e1da159..a60fdee79bf8 100644
--- a/arch/arm64/boot/dts/marvell/cn9131-db.dts
+++ b/arch/arm64/boot/dts/marvell/cn9131-db.dts
@@ -5,203 +5,18 @@
* Device tree for the CN9131-DB board.
*/
-#include "cn9130-db.dts"
+#include "cn9131-db.dtsi"
/ {
- model = "Marvell Armada CN9131-DB";
- compatible = "marvell,cn9131", "marvell,cn9130",
- "marvell,armada-ap807-quad", "marvell,armada-ap807";
-
- aliases {
- gpio3 = &cp1_gpio1;
- gpio4 = &cp1_gpio2;
- ethernet3 = &cp1_eth0;
- ethernet4 = &cp1_eth1;
- };
-
- cp1_reg_usb3_vbus0: cp1_usb3_vbus@0 {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&cp1_xhci0_vbus_pins>;
- regulator-name = "cp1-xhci0-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&cp1_gpio1 3 GPIO_ACTIVE_HIGH>;
- };
-
- cp1_usb3_0_phy0: cp1_usb3_phy0 {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&cp1_reg_usb3_vbus0>;
- };
-
- cp1_sfp_eth1: sfp-eth1 {
- compatible = "sff,sfp";
- i2c-bus = <&cp1_i2c0>;
- los-gpio = <&cp1_gpio1 11 GPIO_ACTIVE_HIGH>;
- mod-def0-gpio = <&cp1_gpio1 10 GPIO_ACTIVE_LOW>;
- tx-disable-gpio = <&cp1_gpio1 9 GPIO_ACTIVE_HIGH>;
- tx-fault-gpio = <&cp1_gpio1 8 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&cp1_sfp_pins>;
- /*
- * SFP cages are unconnected on early PCBs because of an the I2C
- * lanes not being connected. Prevent the port for being
- * unusable by disabling the SFP node.
- */
- status = "disabled";
- };
+ model = "Marvell Armada CN9131-DB setup A";
};
-/*
- * Instantiate the first slave CP115
+/* Setup A has SPI1 flash as a boot device, while setup B uses NAND flash.
+ * Since CP0 SPI1 and CP0 NAND are sharing some pins, they cannot be activated
+ * simultaneously. When SPI controller is enabled, NAND should be disabled.
*/
-#define CP11X_NAME cp1
-#define CP11X_BASE f4000000
-#define CP11X_PCIEx_MEM_BASE(iface) (0xe2000000 + (iface * 0x1000000))
-#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
-#define CP11X_PCIE0_BASE f4600000
-#define CP11X_PCIE1_BASE f4620000
-#define CP11X_PCIE2_BASE f4640000
-
-#include "armada-cp115.dtsi"
-
-#undef CP11X_NAME
-#undef CP11X_BASE
-#undef CP11X_PCIEx_MEM_BASE
-#undef CP11X_PCIEx_MEM_SIZE
-#undef CP11X_PCIE0_BASE
-#undef CP11X_PCIE1_BASE
-#undef CP11X_PCIE2_BASE
-
-&cp1_crypto {
- status = "disabled";
-};
-
-&cp1_ethernet {
- status = "okay";
-};
-
-/* CON50 */
-&cp1_eth0 {
- status = "disabled";
- phy-mode = "10gbase-kr";
- /* Generic PHY, providing serdes lanes */
- phys = <&cp1_comphy4 0>;
- managed = "in-band-status";
- sfp = <&cp1_sfp_eth1>;
-};
-
-&cp1_gpio1 {
- status = "okay";
-};
-
-&cp1_gpio2 {
- status = "okay";
-};
-
-&cp1_i2c0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&cp1_i2c0_pins>;
- clock-frequency = <100000>;
-};
-
-/* CON40 */
-&cp1_pcie0 {
- pinctrl-names = "default";
- pinctrl-0 = <&cp1_pcie_reset_pins>;
- num-lanes = <2>;
- num-viewport = <8>;
- marvell,reset-gpio = <&cp1_gpio1 0 GPIO_ACTIVE_HIGH>;
- status = "okay";
- /* Generic PHY, providing serdes lanes */
- phys = <&cp1_comphy0 0
- &cp1_comphy1 0>;
-};
-
-&cp1_sata0 {
- status = "okay";
-
- /* CON32 */
- sata-port@1 {
- /* Generic PHY, providing serdes lanes */
- phys = <&cp1_comphy5 1>;
- };
-};
-
-/* U24 */
-&cp1_spi1 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&cp1_spi0_pins>;
- reg = <0x700680 0x50>;
-
- spi-flash@0 {
- #address-cells = <0x1>;
- #size-cells = <0x1>;
- compatible = "jedec,spi-nor";
- reg = <0x0>;
- /* On-board MUX does not allow higher frequencies */
- spi-max-frequency = <40000000>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "U-Boot-1";
- reg = <0x0 0x200000>;
- };
-
- partition@400000 {
- label = "Filesystem-1";
- reg = <0x200000 0xe00000>;
- };
- };
- };
-
-};
-
-&cp1_syscon0 {
- cp1_pinctrl: pinctrl {
- compatible = "marvell,cp115-standalone-pinctrl";
-
- cp1_i2c0_pins: cp1-i2c-pins-0 {
- marvell,pins = "mpp37", "mpp38";
- marvell,function = "i2c0";
- };
- cp1_spi0_pins: cp1-spi-pins-0 {
- marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
- marvell,function = "spi1";
- };
- cp1_xhci0_vbus_pins: cp1-xhci0-vbus-pins {
- marvell,pins = "mpp3";
- marvell,function = "gpio";
- };
- cp1_sfp_pins: sfp-pins {
- marvell,pins = "mpp8", "mpp9", "mpp10", "mpp11";
- marvell,function = "gpio";
- };
- cp1_pcie_reset_pins: cp1-pcie-reset-pins {
- marvell,pins = "mpp0";
- marvell,function = "gpio";
- };
- };
-};
-
-/* CON58 */
-&cp1_utmi {
+&cp0_spi1 {
status = "okay";
};
-&cp1_usb3_1 {
- status = "okay";
- usb-phy = <&cp1_usb3_0_phy0>;
- /* Generic PHY, providing serdes lanes */
- phys = <&cp1_comphy3 1>, <&cp1_utmi1>;
- phy-names = "usb", "utmi";
- dr_mode = "host";
-};
diff --git a/arch/arm64/boot/dts/marvell/cn9131-db.dtsi b/arch/arm64/boot/dts/marvell/cn9131-db.dtsi
new file mode 100644
index 000000000000..f995b1bcda01
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9131-db.dtsi
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2020 Marvell International Ltd.
+ *
+ * Device tree for the CN9131-DB board.
+ */
+
+#include "cn9130-db.dtsi"
+
+/ {
+ compatible = "marvell,cn9131", "marvell,cn9130",
+ "marvell,armada-ap807-quad", "marvell,armada-ap807";
+
+ aliases {
+ gpio3 = &cp1_gpio1;
+ gpio4 = &cp1_gpio2;
+ ethernet3 = &cp1_eth0;
+ ethernet4 = &cp1_eth1;
+ };
+
+ cp1_reg_usb3_vbus0: cp1_usb3_vbus@0 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_xhci0_vbus_pins>;
+ regulator-name = "cp1-xhci0-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&cp1_gpio1 3 GPIO_ACTIVE_HIGH>;
+ };
+
+ cp1_usb3_0_phy0: cp1_usb3_phy0 {
+ compatible = "usb-nop-xceiv";
+ vcc-supply = <&cp1_reg_usb3_vbus0>;
+ };
+
+ cp1_sfp_eth1: sfp-eth1 {
+ compatible = "sff,sfp";
+ i2c-bus = <&cp1_i2c0>;
+ los-gpio = <&cp1_gpio1 11 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpio = <&cp1_gpio1 10 GPIO_ACTIVE_LOW>;
+ tx-disable-gpio = <&cp1_gpio1 9 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpio = <&cp1_gpio1 8 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_sfp_pins>;
+ /*
+ * SFP cages are unconnected on early PCBs because of an the I2C
+ * lanes not being connected. Prevent the port for being
+ * unusable by disabling the SFP node.
+ */
+ status = "disabled";
+ };
+};
+
+/*
+ * Instantiate the first slave CP115
+ */
+
+#define CP11X_NAME cp1
+#define CP11X_BASE f4000000
+#define CP11X_PCIEx_MEM_BASE(iface) (0xe2000000 + (iface * 0x1000000))
+#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
+#define CP11X_PCIE0_BASE f4600000
+#define CP11X_PCIE1_BASE f4620000
+#define CP11X_PCIE2_BASE f4640000
+
+#include "armada-cp115.dtsi"
+
+#undef CP11X_NAME
+#undef CP11X_BASE
+#undef CP11X_PCIEx_MEM_BASE
+#undef CP11X_PCIEx_MEM_SIZE
+#undef CP11X_PCIE0_BASE
+#undef CP11X_PCIE1_BASE
+#undef CP11X_PCIE2_BASE
+
+&cp1_crypto {
+ status = "disabled";
+};
+
+&cp1_ethernet {
+ status = "okay";
+};
+
+/* CON50 */
+&cp1_eth0 {
+ status = "okay";
+ phy-mode = "10gbase-r";
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp1_comphy4 0>;
+ managed = "in-band-status";
+ sfp = <&cp1_sfp_eth1>;
+};
+
+&cp1_gpio1 {
+ status = "okay";
+};
+
+&cp1_gpio2 {
+ status = "okay";
+};
+
+&cp1_i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_i2c0_pins>;
+ clock-frequency = <100000>;
+};
+
+/* CON40 */
+&cp1_pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_pcie_reset_pins>;
+ num-lanes = <2>;
+ num-viewport = <8>;
+ marvell,reset-gpio = <&cp1_gpio1 0 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp1_comphy0 0
+ &cp1_comphy1 0>;
+};
+
+&cp1_sata0 {
+ status = "okay";
+
+ /* CON32 */
+ sata-port@1 {
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp1_comphy5 1>;
+ };
+};
+
+/* U24 */
+&cp1_spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_spi0_pins>;
+ reg = <0x700680 0x50>;
+
+ spi-flash@0 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ /* On-board MUX does not allow higher frequencies */
+ spi-max-frequency = <40000000>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot-1";
+ reg = <0x0 0x200000>;
+ };
+
+ partition@400000 {
+ label = "Filesystem-1";
+ reg = <0x200000 0xe00000>;
+ };
+ };
+ };
+
+};
+
+&cp1_syscon0 {
+ cp1_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+
+ cp1_i2c0_pins: cp1-i2c-pins-0 {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "i2c0";
+ };
+ cp1_spi0_pins: cp1-spi-pins-0 {
+ marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
+ marvell,function = "spi1";
+ };
+ cp1_xhci0_vbus_pins: cp1-xhci0-vbus-pins {
+ marvell,pins = "mpp3";
+ marvell,function = "gpio";
+ };
+ cp1_sfp_pins: sfp-pins {
+ marvell,pins = "mpp8", "mpp9", "mpp10", "mpp11";
+ marvell,function = "gpio";
+ };
+ cp1_pcie_reset_pins: cp1-pcie-reset-pins {
+ marvell,pins = "mpp0";
+ marvell,function = "gpio";
+ };
+ };
+};
+
+/* CON58 */
+&cp1_utmi {
+ status = "okay";
+};
+
+&cp1_usb3_1 {
+ status = "okay";
+ usb-phy = <&cp1_usb3_0_phy0>;
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp1_comphy3 1>, <&cp1_utmi1>;
+ phy-names = "usb", "utmi";
+ dr_mode = "host";
+};
diff --git a/arch/arm64/boot/dts/marvell/cn9132-db-B.dts b/arch/arm64/boot/dts/marvell/cn9132-db-B.dts
new file mode 100644
index 000000000000..7137a6f22d0f
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9132-db-B.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * Device tree for the CN9132-DB board.
+ */
+
+#include "cn9132-db.dtsi"
+
+/ {
+ model = "Marvell Armada CN9132-DB setup B";
+};
+
+/* Setup B has NAND flash as a boot device, while regular setup uses SPI flash.
+ * Since CP0 SPI1 and CP0 NAND are sharing some pins, they cannot be activated
+ * simultaneously. When NAND controller is enabled, SPI1 should be disabled.
+ */
+
+&cp0_nand_controller {
+ status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/marvell/cn9132-db.dts b/arch/arm64/boot/dts/marvell/cn9132-db.dts
index 81fba024b22d..1f2e6377afc3 100644
--- a/arch/arm64/boot/dts/marvell/cn9132-db.dts
+++ b/arch/arm64/boot/dts/marvell/cn9132-db.dts
@@ -5,224 +5,18 @@
* Device tree for the CN9132-DB board.
*/
-#include "cn9131-db.dts"
+#include "cn9132-db.dtsi"
/ {
- model = "Marvell Armada CN9132-DB";
- compatible = "marvell,cn9132", "marvell,cn9131", "marvell,cn9130",
- "marvell,armada-ap807-quad", "marvell,armada-ap807";
-
- aliases {
- gpio5 = &cp2_gpio1;
- gpio6 = &cp2_gpio2;
- ethernet5 = &cp2_eth0;
- };
-
- cp2_reg_usb3_vbus0: cp2_usb3_vbus@0 {
- compatible = "regulator-fixed";
- regulator-name = "cp2-xhci0-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&cp2_gpio1 2 GPIO_ACTIVE_HIGH>;
- };
-
- cp2_usb3_0_phy0: cp2_usb3_phy0 {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&cp2_reg_usb3_vbus0>;
- };
-
- cp2_reg_usb3_vbus1: cp2_usb3_vbus@1 {
- compatible = "regulator-fixed";
- regulator-name = "cp2-xhci1-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&cp2_gpio1 3 GPIO_ACTIVE_HIGH>;
- };
-
- cp2_usb3_0_phy1: cp2_usb3_phy1 {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&cp2_reg_usb3_vbus1>;
- };
-
- cp2_reg_sd_vccq: cp2_sd_vccq@0 {
- compatible = "regulator-gpio";
- regulator-name = "cp2_sd_vcc";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- gpios = <&cp2_gpio2 17 GPIO_ACTIVE_HIGH>;
- states = <1800000 0x1 3300000 0x0>;
- };
-
- cp2_sfp_eth0: sfp-eth0 {
- compatible = "sff,sfp";
- i2c-bus = <&cp2_sfpp0_i2c>;
- los-gpio = <&cp2_module_expander1 11 GPIO_ACTIVE_HIGH>;
- mod-def0-gpio = <&cp2_module_expander1 10 GPIO_ACTIVE_LOW>;
- tx-disable-gpio = <&cp2_module_expander1 9 GPIO_ACTIVE_HIGH>;
- tx-fault-gpio = <&cp2_module_expander1 8 GPIO_ACTIVE_HIGH>;
- /*
- * SFP cages are unconnected on early PCBs because of an the I2C
- * lanes not being connected. Prevent the port for being
- * unusable by disabling the SFP node.
- */
- status = "disabled";
- };
+ model = "Marvell Armada CN9132-DB setup A";
};
-/*
- * Instantiate the second slave CP115
+/* Setup A has SPI1 flash as a boot device, while setup B uses NAND flash.
+ * Since CP0 SPI1 and CP0 NAND are sharing some pins, they cannot be activated
+ * simultaneously. When SPI controller is enabled, NAND should be disabled.
*/
-#define CP11X_NAME cp2
-#define CP11X_BASE f6000000
-#define CP11X_PCIEx_MEM_BASE(iface) (0xe5000000 + (iface * 0x1000000))
-#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
-#define CP11X_PCIE0_BASE f6600000
-#define CP11X_PCIE1_BASE f6620000
-#define CP11X_PCIE2_BASE f6640000
-
-#include "armada-cp115.dtsi"
-
-#undef CP11X_NAME
-#undef CP11X_BASE
-#undef CP11X_PCIEx_MEM_BASE
-#undef CP11X_PCIEx_MEM_SIZE
-#undef CP11X_PCIE0_BASE
-#undef CP11X_PCIE1_BASE
-#undef CP11X_PCIE2_BASE
-
-&cp2_crypto {
- status = "disabled";
-};
-
-&cp2_ethernet {
+&cp0_spi1 {
status = "okay";
};
-/* SLM-1521-V2, CON9 */
-&cp2_eth0 {
- status = "disabled";
- phy-mode = "10gbase-kr";
- /* Generic PHY, providing serdes lanes */
- phys = <&cp2_comphy4 0>;
- managed = "in-band-status";
- sfp = <&cp2_sfp_eth0>;
-};
-
-&cp2_gpio1 {
- status = "okay";
-};
-
-&cp2_gpio2 {
- status = "okay";
-};
-
-&cp2_i2c0 {
- clock-frequency = <100000>;
-
- /* SLM-1521-V2 - U3 */
- i2c-mux@72 {
- compatible = "nxp,pca9544";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x72>;
- cp2_sfpp0_i2c: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- /* U12 */
- cp2_module_expander1: pca9555@21 {
- compatible = "nxp,pca9555";
- pinctrl-names = "default";
- gpio-controller;
- #gpio-cells = <2>;
- reg = <0x21>;
- };
- };
- };
-};
-
-/* SLM-1521-V2, CON6 */
-&cp2_pcie0 {
- status = "okay";
- num-lanes = <2>;
- num-viewport = <8>;
- /* Generic PHY, providing serdes lanes */
- phys = <&cp2_comphy0 0
- &cp2_comphy1 0>;
-};
-
-/* SLM-1521-V2, CON8 */
-&cp2_pcie2 {
- status = "okay";
- num-lanes = <1>;
- num-viewport = <8>;
- /* Generic PHY, providing serdes lanes */
- phys = <&cp2_comphy5 2>;
-};
-
-&cp2_sata0 {
- status = "okay";
-
- /* SLM-1521-V2, CON4 */
- sata-port@0 {
- /* Generic PHY, providing serdes lanes */
- phys = <&cp2_comphy2 0>;
- };
-};
-
-/* CON 2 on SLM-1683 - microSD */
-&cp2_sdhci0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&cp2_sdhci_pins>;
- bus-width = <4>;
- cd-gpios = <&cp2_gpio2 23 GPIO_ACTIVE_LOW>;
- vqmmc-supply = <&cp2_reg_sd_vccq>;
-};
-
-&cp2_syscon0 {
- cp2_pinctrl: pinctrl {
- compatible = "marvell,cp115-standalone-pinctrl";
-
- cp2_i2c0_pins: cp2-i2c-pins-0 {
- marvell,pins = "mpp37", "mpp38";
- marvell,function = "i2c0";
- };
- cp2_sdhci_pins: cp2-sdhi-pins-0 {
- marvell,pins = "mpp56", "mpp57", "mpp58",
- "mpp59", "mpp60", "mpp61";
- marvell,function = "sdio";
- };
- };
-};
-
-&cp2_utmi {
- status = "okay";
-};
-
-&cp2_usb3_0 {
- status = "okay";
- usb-phy = <&cp2_usb3_0_phy0>;
- phys = <&cp2_utmi0>;
- phy-names = "usb";
- dr_mode = "host";
-};
-
-/* SLM-1521-V2, CON11 */
-&cp2_usb3_1 {
- status = "okay";
- usb-phy = <&cp2_usb3_0_phy1>;
- /* Generic PHY, providing serdes lanes */
- phys = <&cp2_comphy3 1>, <&cp2_utmi1>;
- phy-names = "usb", "utmi";
- dr_mode = "host";
-};
diff --git a/arch/arm64/boot/dts/marvell/cn9132-db.dtsi b/arch/arm64/boot/dts/marvell/cn9132-db.dtsi
new file mode 100644
index 000000000000..3f1795fb4fe7
--- /dev/null
+++ b/arch/arm64/boot/dts/marvell/cn9132-db.dtsi
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2020 Marvell International Ltd.
+ *
+ * Device tree for the CN9132-DB board.
+ */
+
+#include "cn9131-db.dtsi"
+
+/ {
+ compatible = "marvell,cn9132", "marvell,cn9131", "marvell,cn9130",
+ "marvell,armada-ap807-quad", "marvell,armada-ap807";
+
+ aliases {
+ gpio5 = &cp2_gpio1;
+ gpio6 = &cp2_gpio2;
+ ethernet5 = &cp2_eth0;
+ };
+
+ cp2_reg_usb3_vbus0: cp2_usb3_vbus@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "cp2-xhci0-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&cp2_gpio1 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ cp2_usb3_0_phy0: cp2_usb3_phy0 {
+ compatible = "usb-nop-xceiv";
+ vcc-supply = <&cp2_reg_usb3_vbus0>;
+ };
+
+ cp2_reg_usb3_vbus1: cp2_usb3_vbus@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "cp2-xhci1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&cp2_gpio1 3 GPIO_ACTIVE_HIGH>;
+ };
+
+ cp2_usb3_0_phy1: cp2_usb3_phy1 {
+ compatible = "usb-nop-xceiv";
+ vcc-supply = <&cp2_reg_usb3_vbus1>;
+ };
+
+ cp2_reg_sd_vccq: cp2_sd_vccq@0 {
+ compatible = "regulator-gpio";
+ regulator-name = "cp2_sd_vcc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&cp2_gpio2 17 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x1 3300000 0x0>;
+ };
+
+ cp2_sfp_eth0: sfp-eth0 {
+ compatible = "sff,sfp";
+ i2c-bus = <&cp2_sfpp0_i2c>;
+ los-gpio = <&cp2_module_expander1 11 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpio = <&cp2_module_expander1 10 GPIO_ACTIVE_LOW>;
+ tx-disable-gpio = <&cp2_module_expander1 9 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpio = <&cp2_module_expander1 8 GPIO_ACTIVE_HIGH>;
+ /*
+ * SFP cages are unconnected on early PCBs because of an the I2C
+ * lanes not being connected. Prevent the port for being
+ * unusable by disabling the SFP node.
+ */
+ status = "disabled";
+ };
+};
+
+/*
+ * Instantiate the second slave CP115
+ */
+
+#define CP11X_NAME cp2
+#define CP11X_BASE f6000000
+#define CP11X_PCIEx_MEM_BASE(iface) (0xe5000000 + (iface * 0x1000000))
+#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
+#define CP11X_PCIE0_BASE f6600000
+#define CP11X_PCIE1_BASE f6620000
+#define CP11X_PCIE2_BASE f6640000
+
+#include "armada-cp115.dtsi"
+
+#undef CP11X_NAME
+#undef CP11X_BASE
+#undef CP11X_PCIEx_MEM_BASE
+#undef CP11X_PCIEx_MEM_SIZE
+#undef CP11X_PCIE0_BASE
+#undef CP11X_PCIE1_BASE
+#undef CP11X_PCIE2_BASE
+
+&cp2_crypto {
+ status = "disabled";
+};
+
+&cp2_ethernet {
+ status = "okay";
+};
+
+/* SLM-1521-V2, CON9 */
+&cp2_eth0 {
+ status = "disabled";
+ phy-mode = "10gbase-r";
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp2_comphy4 0>;
+ managed = "in-band-status";
+ sfp = <&cp2_sfp_eth0>;
+};
+
+&cp2_gpio1 {
+ status = "okay";
+};
+
+&cp2_gpio2 {
+ status = "okay";
+};
+
+&cp2_i2c0 {
+ clock-frequency = <100000>;
+
+ /* SLM-1521-V2 - U3 */
+ i2c-mux@72 {
+ compatible = "nxp,pca9544";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x72>;
+ cp2_sfpp0_i2c: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ /* U12 */
+ cp2_module_expander1: pca9555@21 {
+ compatible = "nxp,pca9555";
+ pinctrl-names = "default";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x21>;
+ };
+ };
+ };
+};
+
+/* SLM-1521-V2, CON6 */
+&cp2_pcie0 {
+ status = "okay";
+ num-lanes = <2>;
+ num-viewport = <8>;
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp2_comphy0 0
+ &cp2_comphy1 0>;
+};
+
+/* SLM-1521-V2, CON8 */
+&cp2_pcie2 {
+ status = "okay";
+ num-lanes = <1>;
+ num-viewport = <8>;
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp2_comphy5 2>;
+};
+
+&cp2_sata0 {
+ status = "okay";
+
+ /* SLM-1521-V2, CON4 */
+ sata-port@0 {
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp2_comphy2 0>;
+ };
+};
+
+/* CON 2 on SLM-1683 - microSD */
+&cp2_sdhci0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp2_sdhci_pins>;
+ bus-width = <4>;
+ cd-gpios = <&cp2_gpio2 23 GPIO_ACTIVE_LOW>;
+ vqmmc-supply = <&cp2_reg_sd_vccq>;
+};
+
+&cp2_syscon0 {
+ cp2_pinctrl: pinctrl {
+ compatible = "marvell,cp115-standalone-pinctrl";
+
+ cp2_i2c0_pins: cp2-i2c-pins-0 {
+ marvell,pins = "mpp37", "mpp38";
+ marvell,function = "i2c0";
+ };
+ cp2_sdhci_pins: cp2-sdhi-pins-0 {
+ marvell,pins = "mpp56", "mpp57", "mpp58",
+ "mpp59", "mpp60", "mpp61";
+ marvell,function = "sdio";
+ };
+ };
+};
+
+&cp2_utmi {
+ status = "okay";
+};
+
+&cp2_usb3_0 {
+ status = "okay";
+ usb-phy = <&cp2_usb3_0_phy0>;
+ phys = <&cp2_utmi0>;
+ phy-names = "usb";
+ dr_mode = "host";
+};
+
+/* SLM-1521-V2, CON11 */
+&cp2_usb3_1 {
+ status = "okay";
+ usb-phy = <&cp2_usb3_0_phy1>;
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp2_comphy3 1>, <&cp2_utmi1>;
+ phy-names = "usb", "utmi";
+ dr_mode = "host";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
index 21452c51a20a..e666ebb28980 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
@@ -10,6 +10,12 @@
#include "mt8173.dtsi"
/ {
+ aliases {
+ mmc0 = &mmc0;
+ mmc1 = &mmc1;
+ mmc2 = &mmc3;
+ };
+
memory@40000000 {
device_type = "memory";
reg = <0 0x40000000 0 0x80000000>;
@@ -157,6 +163,10 @@
};
};
+&mfg_async {
+ domain-supply = <&da9211_vgpu_reg>;
+};
+
&cec {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
index f6a1738dfbaa..4fa1e93302c7 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -62,6 +62,10 @@
};
};
+&mfg_async {
+ domain-supply = <&da9211_vgpu_reg>;
+};
+
&cec {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 22f271b1f5b0..d9e005ae5bb0 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -504,7 +504,7 @@
reg = <MT8173_POWER_DOMAIN_USB>;
#power-domain-cells = <0>;
};
- power-domain@MT8173_POWER_DOMAIN_MFG_ASYNC {
+ mfg_async: power-domain@MT8173_POWER_DOMAIN_MFG_ASYNC {
reg = <MT8173_POWER_DOMAIN_MFG_ASYNC>;
clocks = <&clk26m>;
clock-names = "mfg";
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
index ae549d55a94f..8e9cf36a9a41 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
@@ -13,6 +13,8 @@
/ {
aliases {
serial0 = &uart0;
+ mmc0 = &mmc0;
+ mmc1 = &mmc1;
};
chosen {
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index f90df6439c08..409cf827970c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -14,7 +14,7 @@
#include <dt-bindings/reset-controller/mt8183-resets.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/thermal/thermal.h>
-#include "mt8183-pinfunc.h"
+#include <dt-bindings/pinctrl/mt8183-pinfunc.h>
/ {
compatible = "mediatek,mt8183";
@@ -1355,6 +1355,8 @@
reg = <0 0x14016000 0 0x1000>;
interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&spm MT8183_POWER_DOMAIN_DISP>;
+ mediatek,gce-events = <CMDQ_EVENT_MUTEX_STREAM_DONE0>,
+ <CMDQ_EVENT_MUTEX_STREAM_DONE1>;
};
larb0: larb@14017000 {
diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile
index e13fb1070472..c80f7dc2935e 100644
--- a/arch/arm64/boot/dts/nvidia/Makefile
+++ b/arch/arm64/boot/dts/nvidia/Makefile
@@ -7,6 +7,7 @@ dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p3450-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2894-0050-a08.dtb
dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb
+dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p3509-0000+p3636-0001.dtb
dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p2972-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p3509-0000+p3668-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p3509-0000+p3668-0001.dtb
diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
index 9928a87f593a..b0bcda8cc51f 100644
--- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
@@ -1227,13 +1227,13 @@
cpu@0 {
device_type = "cpu";
- compatible = "nvidia,denver";
+ compatible = "nvidia,tegra132-denver";
reg = <0>;
};
cpu@1 {
device_type = "cpu";
- compatible = "nvidia,denver";
+ compatible = "nvidia,tegra132-denver";
reg = <1>;
};
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3509-0000+p3636-0001.dts b/arch/arm64/boot/dts/nvidia/tegra186-p3509-0000+p3636-0001.dts
new file mode 100644
index 000000000000..936b106e73db
--- /dev/null
+++ b/arch/arm64/boot/dts/nvidia/tegra186-p3509-0000+p3636-0001.dts
@@ -0,0 +1,718 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/input/gpio-keys.h>
+#include <dt-bindings/mfd/max77620.h>
+
+#include "tegra186.dtsi"
+
+/ {
+ model = "NVIDIA Jetson TX2 NX Developer Kit";
+ compatible = "nvidia,p3509-0000+p3636-0001", "nvidia,tegra186";
+
+ aliases {
+ ethernet0 = "/ethernet@2490000";
+ i2c0 = "/bpmp/i2c";
+ i2c1 = "/i2c@3160000";
+ i2c2 = "/i2c@c240000";
+ i2c3 = "/i2c@3180000";
+ i2c4 = "/i2c@3190000";
+ i2c5 = "/i2c@31c0000";
+ i2c6 = "/i2c@c250000";
+ i2c7 = "/i2c@31e0000";
+ mmc0 = "/mmc@3460000";
+ serial0 = &uarta;
+ };
+
+ chosen {
+ bootargs = "earlycon console=ttyS0,115200n8";
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x70000000>;
+ };
+
+ ethernet@2490000 {
+ status = "okay";
+
+ phy-reset-gpios = <&gpio_aon TEGRA186_AON_GPIO(AA, 6) GPIO_ACTIVE_LOW>;
+ phy-handle = <&phy>;
+ phy-mode = "rgmii-id";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy: phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x0>;
+ interrupt-parent = <&gpio_aon>;
+ interrupts = <TEGRA186_AON_GPIO(AA, 7) IRQ_TYPE_LEVEL_LOW>;
+ #phy-cells = <0>;
+ };
+ };
+ };
+
+ memory-controller@2c00000 {
+ status = "okay";
+ };
+
+ timer@3010000 {
+ status = "okay";
+ };
+
+ serial@3100000 {
+ status = "okay";
+ };
+
+ i2c@3160000 {
+ status = "okay";
+ };
+
+ i2c@3180000 {
+ status = "okay";
+
+ power-monitor@40 {
+ compatible = "ti,ina3221";
+ reg = <0x40>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ reg = <0>;
+ label = "VDD_IN";
+ shunt-resistor-micro-ohms = <5>;
+ };
+
+ channel@1 {
+ reg = <1>;
+ label = "VDD_CPU_GPU";
+ shunt-resistor-micro-ohms = <5>;
+ };
+
+ channel@2 {
+ reg = <2>;
+ label = "VDD_SOC";
+ shunt-resistor-micro-ohms = <>;
+ };
+ };
+ };
+
+ ddc: i2c@3190000 {
+ status = "okay";
+ };
+
+ i2c@31c0000 {
+ status = "okay";
+ };
+
+ i2c@31e0000 {
+ status = "okay";
+ };
+
+ /* SDMMC4 (eMMC) */
+ mmc@3460000 {
+ status = "okay";
+ bus-width = <8>;
+ non-removable;
+
+ vqmmc-supply = <&vdd_1v8_ap>;
+ vmmc-supply = <&vdd_3v3_sys>;
+ };
+
+ hda@3510000 {
+ nvidia,model = "jetson-tx2-hda";
+ status = "okay";
+ };
+
+ padctl@3520000 {
+ status = "okay";
+
+ avdd-pll-erefeut-supply = <&vdd_1v8_pll>;
+ avdd-usb-supply = <&vdd_3v3_sys>;
+ vclamp-usb-supply = <&vdd_1v8>;
+ vddio-hsic-supply = <&gnd>;
+
+ pads {
+ usb2 {
+ status = "okay";
+
+ lanes {
+ micro_b: usb2-0 {
+ nvidia,function = "xusb";
+ status = "okay";
+ };
+
+ usb2-1 {
+ nvidia,function = "xusb";
+ status = "okay";
+ };
+
+ usb2-2 {
+ nvidia,function = "xusb";
+ status = "okay";
+ };
+ };
+ };
+
+ usb3 {
+ status = "okay";
+
+ lanes {
+ usb3-1 {
+ nvidia,function = "xusb";
+ status = "okay";
+ };
+ };
+ };
+ };
+
+ ports {
+ usb2-0 {
+ status = "okay";
+ mode = "otg";
+ vbus-supply = <&vdd_5v0_sys>;
+ usb-role-switch;
+
+ connector {
+ compatible = "gpio-usb-b-connector",
+ "usb-b-connector";
+ label = "micro-USB";
+ type = "micro";
+ vbus-gpios = <&gpio
+ TEGRA186_MAIN_GPIO(L, 4)
+ GPIO_ACTIVE_LOW>;
+ id-gpios = <&pmic 0 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ usb2-1 {
+ status = "okay";
+ mode = "host";
+
+ vbus-supply = <&vdd_5v0_sys>;
+ };
+
+ usb2-2 {
+ status = "okay";
+ mode = "host";
+
+ vbus-supply = <&vdd_5v0_sys>;
+ };
+
+ usb3-1 {
+ nvidia,usb2-companion = <1>;
+ vbus-supply = <&vdd_5v0_sys>;
+ status = "okay";
+ };
+ };
+ };
+
+ usb@3530000 {
+ status = "okay";
+
+ phys = <&{/padctl@3520000/pads/usb2/lanes/usb2-0}>,
+ <&{/padctl@3520000/pads/usb2/lanes/usb2-1}>,
+ <&{/padctl@3520000/pads/usb2/lanes/usb2-2}>,
+ <&{/padctl@3520000/pads/usb3/lanes/usb3-1}>;
+ phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-1";
+ };
+
+ usb@3550000 {
+ status = "okay";
+
+ phys = <&micro_b>;
+ phy-names = "usb2-0";
+ };
+
+ hsp@3c00000 {
+ status = "okay";
+ };
+
+ i2c@c240000 {
+ status = "okay";
+ };
+
+ i2c@c250000 {
+ status = "okay";
+
+ /* module ID EEPROM */
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+
+ label = "module";
+ vcc-supply = <&vdd_1v8>;
+ address-width = <8>;
+ pagesize = <8>;
+ size = <256>;
+ read-only;
+ };
+
+ /* carrier board ID EEPROM */
+ eeprom@57 {
+ compatible = "atmel,24c02";
+ reg = <0x57>;
+
+ label = "system";
+ vcc-supply = <&vdd_1v8>;
+ address-width = <8>;
+ pagesize = <8>;
+ size = <256>;
+ read-only;
+ };
+ };
+
+ rtc@c2a0000 {
+ status = "okay";
+ };
+
+ pwm@c340000 {
+ status = "okay";
+ };
+
+ pmc@c360000 {
+ nvidia,invert-interrupt;
+ };
+
+ pcie@10003000 {
+ status = "okay";
+
+ dvdd-pex-supply = <&vdd_pex>;
+ hvdd-pex-pll-supply = <&vdd_1v8>;
+ hvdd-pex-supply = <&vdd_1v8>;
+ vddio-pexctl-aud-supply = <&vdd_1v8>;
+
+ pci@1,0 {
+ nvidia,num-lanes = <2>;
+ status = "okay";
+ };
+
+ pci@2,0 {
+ nvidia,num-lanes = <1>;
+ status = "disabled";
+ };
+
+ pci@3,0 {
+ nvidia,num-lanes = <1>;
+ status = "okay";
+ };
+ };
+
+ host1x@13e00000 {
+ status = "okay";
+
+ dpaux@15040000 {
+ status = "okay";
+ };
+
+ display-hub@15200000 {
+ status = "okay";
+ };
+
+ dsi@15300000 {
+ status = "disabled";
+ };
+
+ /* DP */
+ sor@15540000 {
+ status = "okay";
+
+ avdd-io-hdmi-dp-supply = <&vdd_hdmi_1v05>;
+ vdd-hdmi-dp-pll-supply = <&vdd_1v8_ap>;
+
+ nvidia,dpaux = <&dpaux>;
+ };
+
+ /* HDMI */
+ sor@15580000 {
+ status = "okay";
+
+ avdd-io-hdmi-dp-supply = <&vdd_hdmi_1v05>;
+ vdd-hdmi-dp-pll-supply = <&vdd_1v8_ap>;
+ hdmi-supply = <&vdd_hdmi>;
+
+ nvidia,ddc-i2c-bus = <&ddc>;
+ nvidia,hpd-gpio = <&gpio TEGRA186_MAIN_GPIO(P, 1)
+ GPIO_ACTIVE_LOW>;
+ };
+
+ dpaux@155c0000 {
+ status = "okay";
+ };
+ };
+
+ gpu@17000000 {
+ status = "okay";
+ };
+
+ fan: fan {
+ compatible = "pwm-fan";
+ pwms = <&pwm4 0 45334>;
+
+ cooling-levels = <0 64 128 255>;
+ #cooling-cells = <2>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "Power";
+ gpios = <&gpio_aon TEGRA186_AON_GPIO(FF, 0)
+ GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_KEY>;
+ linux,code = <KEY_POWER>;
+ debounce-interval = <10>;
+ wakeup-event-action = <EV_ACT_ASSERTED>;
+ wakeup-source;
+ };
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio_aon TEGRA186_AON_GPIO(FF, 1)
+ GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_KEY>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <10>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio_aon TEGRA186_AON_GPIO(FF, 2)
+ GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_KEY>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ debounce-interval = <10>;
+ };
+ };
+
+ cpus {
+ cpu@0 {
+ enable-method = "psci";
+ };
+
+ cpu@1 {
+ enable-method = "psci";
+ };
+
+ cpu@2 {
+ enable-method = "psci";
+ };
+
+ cpu@3 {
+ enable-method = "psci";
+ };
+
+ cpu@4 {
+ enable-method = "psci";
+ };
+
+ cpu@5 {
+ enable-method = "psci";
+ };
+ };
+
+ bpmp {
+ i2c {
+ status = "okay";
+
+ pmic: pmic@3c {
+ compatible = "maxim,max77620";
+ reg = <0x3c>;
+
+ interrupt-parent = <&pmc>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&max77620_default>;
+
+ max77620_default: pinmux {
+ gpio0 {
+ pins = "gpio0";
+ function = "gpio";
+ };
+
+ gpio1 {
+ pins = "gpio1";
+ function = "fps-out";
+ maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
+ };
+
+ gpio2 {
+ pins = "gpio2";
+ function = "fps-out";
+ maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+ };
+
+ gpio3 {
+ pins = "gpio3";
+ function = "fps-out";
+ maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+ };
+
+ gpio4 {
+ pins = "gpio4";
+ function = "32k-out1";
+ drive-push-pull = <1>;
+ };
+
+ gpio5 {
+ pins = "gpio5";
+ function = "gpio";
+ drive-push-pull = <0>;
+ };
+
+ gpio6 {
+ pins = "gpio6";
+ function = "gpio";
+ drive-push-pull = <1>;
+ };
+
+ gpio7 {
+ pins = "gpio7";
+ function = "gpio";
+ drive-push-pull = <1>;
+ };
+ };
+
+ fps {
+ fps0 {
+ maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
+ maxim,shutdown-fps-time-period-us = <640>;
+ };
+
+ fps1 {
+ maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
+ maxim,shutdown-fps-time-period-us = <640>;
+ };
+
+ fps2 {
+ maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
+ maxim,shutdown-fps-time-period-us = <640>;
+ };
+ };
+
+ regulators {
+ in-sd0-supply = <&vdd_5v0_sys>;
+ in-sd1-supply = <&vdd_5v0_sys>;
+ in-sd2-supply = <&vdd_5v0_sys>;
+ in-sd3-supply = <&vdd_5v0_sys>;
+
+ in-ldo0-1-supply = <&vdd_5v0_sys>;
+ in-ldo2-supply = <&vdd_5v0_sys>;
+ in-ldo3-5-supply = <&vdd_5v0_sys>;
+ in-ldo4-6-supply = <&vdd_1v8>;
+ in-ldo7-8-supply = <&avdd_dsi_csi>;
+
+ sd0 {
+ regulator-name = "VDD_DDR_1V1_PMIC";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ avdd_dsi_csi: sd1 {
+ regulator-name = "AVDD_DSI_CSI_1V2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vdd_1v8: sd2 {
+ regulator-name = "VDD_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vdd_3v3_sys: sd3 {
+ regulator-name = "VDD_3V3_SYS";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vdd_1v8_pll: ldo0 {
+ regulator-name = "VDD_1V8_AP_PLL";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo2 {
+ regulator-name = "VDDIO_3V3_AOHV";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vddio_sdmmc1: ldo3 {
+ regulator-name = "VDDIO_SDMMC1_AP";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo4 {
+ regulator-name = "VDD_RTC";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ vddio_sdmmc3: ldo5 {
+ regulator-name = "VDDIO_SDMMC3_AP";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vdd_hdmi_1v05: ldo7 {
+ regulator-name = "VDD_HDMI_1V05";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ vdd_pex: ldo8 {
+ regulator-name = "VDD_PEX_1V05";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ };
+ };
+ };
+ };
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ status = "okay";
+ method = "smc";
+ };
+
+ gnd: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "GND";
+ regulator-min-microvolt = <0>;
+ regulator-max-microvolt = <0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdd_5v0_sys: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_5V0_SYS";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdd_1v8_ap: regulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_1V8_AP";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ vin-supply = <&vdd_1v8>;
+ };
+
+ vdd_hdmi: regulator@3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_5V0_HDMI_CON";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ vin-supply = <&vdd_5v0_sys>;
+ };
+
+ thermal-zones {
+ cpu {
+ polling-delay = <0>;
+ polling-delay-passive = <500>;
+ status = "okay";
+
+ trips {
+ cpu_trip_critical: critical {
+ temperature = <96500>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+
+ cpu_trip_hot: hot {
+ temperature = <79000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ cpu_trip_active: active {
+ temperature = <62000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+
+ cpu_trip_passive: passive {
+ temperature = <45000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ };
+
+ cooling-maps {
+ cpu-critical {
+ cooling-device = <&fan 3 3>;
+ trip = <&cpu_trip_critical>;
+ };
+
+ cpu-hot {
+ cooling-device = <&fan 2 2>;
+ trip = <&cpu_trip_hot>;
+ };
+
+ cpu-active {
+ cooling-device = <&fan 1 1>;
+ trip = <&cpu_trip_active>;
+ };
+
+ cpu-passive {
+ cooling-device = <&fan 0 0>;
+ trip = <&cpu_trip_passive>;
+ };
+ };
+ };
+
+ gpu {
+ polling-delay = <0>;
+ polling-delay-passive = <500>;
+ status = "okay";
+
+ trips {
+ gpu_alert0: critical {
+ temperature = <99000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ aux {
+ polling-delay = <0>;
+ polling-delay-passive = <500>;
+ status = "okay";
+
+ trips {
+ aux_alert0: critical {
+ temperature = <90000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index d02f6bf3e2ca..e94f8add1a40 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -548,6 +548,83 @@
status = "disabled";
};
+ pwm1: pwm@3280000 {
+ compatible = "nvidia,tegra186-pwm";
+ reg = <0x0 0x3280000 0x0 0x10000>;
+ clocks = <&bpmp TEGRA186_CLK_PWM1>;
+ clock-names = "pwm";
+ resets = <&bpmp TEGRA186_RESET_PWM1>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm2: pwm@3290000 {
+ compatible = "nvidia,tegra186-pwm";
+ reg = <0x0 0x3290000 0x0 0x10000>;
+ clocks = <&bpmp TEGRA186_CLK_PWM2>;
+ clock-names = "pwm";
+ resets = <&bpmp TEGRA186_RESET_PWM2>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm3: pwm@32a0000 {
+ compatible = "nvidia,tegra186-pwm";
+ reg = <0x0 0x32a0000 0x0 0x10000>;
+ clocks = <&bpmp TEGRA186_CLK_PWM3>;
+ clock-names = "pwm";
+ resets = <&bpmp TEGRA186_RESET_PWM3>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm5: pwm@32c0000 {
+ compatible = "nvidia,tegra186-pwm";
+ reg = <0x0 0x32c0000 0x0 0x10000>;
+ clocks = <&bpmp TEGRA186_CLK_PWM5>;
+ clock-names = "pwm";
+ resets = <&bpmp TEGRA186_RESET_PWM5>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm6: pwm@32d0000 {
+ compatible = "nvidia,tegra186-pwm";
+ reg = <0x0 0x32d0000 0x0 0x10000>;
+ clocks = <&bpmp TEGRA186_CLK_PWM6>;
+ clock-names = "pwm";
+ resets = <&bpmp TEGRA186_RESET_PWM6>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm7: pwm@32e0000 {
+ compatible = "nvidia,tegra186-pwm";
+ reg = <0x0 0x32e0000 0x0 0x10000>;
+ clocks = <&bpmp TEGRA186_CLK_PWM7>;
+ clock-names = "pwm";
+ resets = <&bpmp TEGRA186_RESET_PWM7>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm8: pwm@32f0000 {
+ compatible = "nvidia,tegra186-pwm";
+ reg = <0x0 0x32f0000 0x0 0x10000>;
+ clocks = <&bpmp TEGRA186_CLK_PWM8>;
+ clock-names = "pwm";
+ resets = <&bpmp TEGRA186_RESET_PWM8>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
sdmmc1: mmc@3400000 {
compatible = "nvidia,tegra186-sdhci";
reg = <0x0 0x03400000 0x0 0x10000>;
@@ -826,6 +903,9 @@
<&bpmp TEGRA186_CLK_XUSB_CORE_SS>,
<&bpmp TEGRA186_CLK_XUSB_FS>;
clock-names = "dev", "ss", "ss_src", "fs_src";
+ interconnects = <&mc TEGRA186_MEMORY_CLIENT_XUSB_DEVR &emc>,
+ <&mc TEGRA186_MEMORY_CLIENT_XUSB_DEVW &emc>;
+ interconnect-names = "dma-mem", "write";
iommus = <&smmu TEGRA186_SID_XUSB_DEV>;
power-domains = <&bpmp TEGRA186_POWER_DOMAIN_XUSBB>,
<&bpmp TEGRA186_POWER_DOMAIN_XUSBA>;
@@ -944,6 +1024,17 @@
#interrupt-cells = <2>;
};
+ pwm4: pwm@c340000 {
+ compatible = "nvidia,tegra186-pwm";
+ reg = <0x0 0xc340000 0x0 0x10000>;
+ clocks = <&bpmp TEGRA186_CLK_PWM4>;
+ clock-names = "pwm";
+ resets = <&bpmp TEGRA186_RESET_PWM4>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
pmc: pmc@c360000 {
compatible = "nvidia,tegra186-pmc";
reg = <0 0x0c360000 0 0x10000>,
diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
index 7e7b0eb90c80..c4058ee36fec 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
@@ -309,7 +309,7 @@
interrupt-parent = <&gpio>;
interrupts = <TEGRA194_MAIN_GPIO(H, 2)
- IRQ_TYPE_LEVEL_LOW>;
+ IRQ_TYPE_EDGE_FALLING>;
vcc-supply = <&vdd_1v8ls>;
#thermal-sensor-cells = <1>;
diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
index 5ba7a4519b95..c8250a3f7891 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -2122,7 +2122,7 @@
};
pcie_ep@14160000 {
- compatible = "nvidia,tegra194-pcie-ep", "snps,dw-pcie-ep";
+ compatible = "nvidia,tegra194-pcie-ep";
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX4A>;
reg = <0x00 0x14160000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x36040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
@@ -2162,7 +2162,7 @@
};
pcie_ep@14180000 {
- compatible = "nvidia,tegra194-pcie-ep", "snps,dw-pcie-ep";
+ compatible = "nvidia,tegra194-pcie-ep";
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8B>;
reg = <0x00 0x14180000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x38040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
@@ -2202,7 +2202,7 @@
};
pcie_ep@141a0000 {
- compatible = "nvidia,tegra194-pcie-ep", "snps,dw-pcie-ep";
+ compatible = "nvidia,tegra194-pcie-ep";
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8A>;
reg = <0x00 0x141a0000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x3a040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 4f0597091976..70516508be56 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -15,6 +15,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-longcheer-l8910.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a3u-eur.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-a5u-eur.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-wingtech-wt88047.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-msft-lumia-octagon-talkman.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-xiaomi-libra.dtb
@@ -26,6 +27,12 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8994-sony-xperia-kitakami-satsuki.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8994-sony-xperia-kitakami-sumire.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8994-sony-xperia-kitakami-suzuran.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996-pmi8996-sony-xperia-tone-dora.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996-pmi8996-sony-xperia-tone-kagura.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996-pmi8996-sony-xperia-tone-keyaki.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-dora.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-kagura.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-keyaki.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-asus-novago-tp370ql.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-hp-envy-x2.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-lenovo-miix-630.dtb
@@ -60,6 +67,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pompom-r3-lte.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-r1-lte.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp2.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-ganges-kirin.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-discovery.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-pioneer.dtb
@@ -75,6 +83,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-oneplus-enchilada.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-oneplus-fajita.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-xiaomi-beryllium.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm850-lenovo-yoga-c630.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm6125-sony-xperia-seine-pdx201.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-microsoft-surface-duo.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-mtp.dtb
diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
index 6aef0c2e4f0a..f8d8f3e3664e 100644
--- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
@@ -414,6 +414,7 @@
&funnel0 { status = "okay"; };
&funnel1 { status = "okay"; };
&replicator { status = "okay"; };
+&stm { status = "okay"; };
&tpiu { status = "okay"; };
&smd_rpm_regulators {
diff --git a/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts b/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts
index 8c7a27e972b7..a57c60070cdc 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts
@@ -92,6 +92,14 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_phy {
+ status = "okay";
+};
+
&mdss {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts
index 99cefe88f6f2..5aec18308712 100644
--- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts
+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts
@@ -78,3 +78,11 @@
nand-bus-width = <8>;
};
};
+
+&qusb_phy_1 {
+ status = "ok";
+};
+
+&usb2 {
+ status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
index 9fa5b028e4f3..d2fe58e0eb7a 100644
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -151,7 +151,7 @@
#size-cells = <2>;
ranges;
- rpm_msg_ram: memory@0x60000 {
+ rpm_msg_ram: memory@60000 {
reg = <0x0 0x60000 0x0 0x6000>;
no-map;
};
@@ -258,9 +258,9 @@
reg = <0x0 0x01905000 0x0 0x8000>;
};
- tcsr_q6: syscon@1945000 {
+ tcsr: syscon@1937000 {
compatible = "syscon";
- reg = <0x0 0x01945000 0x0 0xe000>;
+ reg = <0x0 0x01937000 0x0 0x21000>;
};
blsp_dma: dma-controller@7884000 {
@@ -384,6 +384,105 @@
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
+ pcie_phy: phy@84000 {
+ compatible = "qcom,ipq6018-qmp-pcie-phy";
+ reg = <0x0 0x84000 0x0 0x1bc>; /* Serdes PLL */
+ status = "disabled";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&gcc GCC_PCIE0_AUX_CLK>,
+ <&gcc GCC_PCIE0_AHB_CLK>;
+ clock-names = "aux", "cfg_ahb";
+
+ resets = <&gcc GCC_PCIE0_PHY_BCR>,
+ <&gcc GCC_PCIE0PHY_PHY_BCR>;
+ reset-names = "phy",
+ "common";
+
+ pcie_phy0: lane@84200 {
+ reg = <0x0 0x84200 0x0 0x16c>, /* Serdes Tx */
+ <0x0 0x84400 0x0 0x200>, /* Serdes Rx */
+ <0x0 0x84800 0x0 0x4f4>; /* PCS: Lane0, COM, PCIE */
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_PCIE0_PIPE_CLK>;
+ clock-names = "pipe0";
+ clock-output-names = "gcc_pcie0_pipe_clk_src";
+ #clock-cells = <0>;
+ };
+ };
+
+ pcie0: pci@20000000 {
+ compatible = "qcom,pcie-ipq6018";
+ reg = <0x0 0x20000000 0x0 0xf1d>,
+ <0x0 0x20000f20 0x0 0xa8>,
+ <0x0 0x20001000 0x0 0x1000>,
+ <0x0 0x80000 0x0 0x4000>,
+ <0x0 0x20100000 0x0 0x1000>;
+ reg-names = "dbi", "elbi", "atu", "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 0 0x20200000
+ 0 0x10000>, /* downstream I/O */
+ <0x82000000 0 0x20220000 0 0x20220000
+ 0 0xfde0000>; /* 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_AXI_S_BRIDGE_CLK>,
+ <&gcc PCIE0_RCHNG_CLK>;
+ clock-names = "iface",
+ "axi_m",
+ "axi_s",
+ "axi_bridge",
+ "rchng";
+
+ 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>,
+ <&gcc GCC_PCIE0_AXI_SLAVE_STICKY_ARES>;
+ reset-names = "pipe",
+ "sleep",
+ "sticky",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "axi_m_sticky",
+ "axi_s_sticky";
+
+ status = "disabled";
+ };
+
watchdog@b017000 {
compatible = "qcom,kpss-wdt";
interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
@@ -477,7 +576,7 @@
};
q6v5_wcss: remoteproc@cd00000 {
- compatible = "qcom,ipq8074-wcss-pil";
+ compatible = "qcom,ipq6018-wcss-pil";
reg = <0x0 0x0cd00000 0x0 0x4040>,
<0x0 0x004ab000 0x0 0x20>;
reg-names = "qdsp6",
@@ -504,7 +603,7 @@
clocks = <&gcc GCC_PRNG_AHB_CLK>;
clock-names = "prng";
- qcom,halt-regs = <&tcsr_q6 0xa000 0xd000 0x0>;
+ qcom,halt-regs = <&tcsr 0x18000 0x1b000 0xe000>;
qcom,smem-states = <&wcss_smp2p_out 0>,
<&wcss_smp2p_out 1>;
@@ -524,6 +623,54 @@
};
};
+ qusb_phy_1: qusb@59000 {
+ compatible = "qcom,ipq6018-qusb2-phy";
+ reg = <0x0 0x059000 0x0 0x180>;
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_USB1_PHY_CFG_AHB_CLK>,
+ <&xo>;
+ clock-names = "cfg_ahb", "ref";
+
+ resets = <&gcc GCC_QUSB2_1_PHY_BCR>;
+ status = "disabled";
+ };
+
+ usb2: usb2@7000000 {
+ compatible = "qcom,ipq6018-dwc3", "qcom,dwc3";
+ reg = <0x0 0x070F8800 0x0 0x400>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ clocks = <&gcc GCC_USB1_MASTER_CLK>,
+ <&gcc GCC_USB1_SLEEP_CLK>,
+ <&gcc GCC_USB1_MOCK_UTMI_CLK>;
+ clock-names = "master",
+ "sleep",
+ "mock_utmi";
+
+ assigned-clocks = <&gcc GCC_USB1_MASTER_CLK>,
+ <&gcc GCC_USB1_MOCK_UTMI_CLK>;
+ assigned-clock-rates = <133330000>,
+ <24000000>;
+ resets = <&gcc GCC_USB1_BCR>;
+ status = "disabled";
+
+ dwc_1: usb@7000000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0x7000000 0x0 0xcd00>;
+ interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&qusb_phy_1>;
+ phy-names = "usb2-phy";
+ tx-fifo-resize;
+ snps,is-utmi-l1-suspend;
+ snps,hird-threshold = /bits/ 8 <0x0>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_u3_susphy_quirk;
+ dr_mode = "host";
+ };
+ };
+
};
wcss: wcss-smp2p {
diff --git a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
index e8c37a1693d3..cc08dc4eb56a 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
@@ -20,7 +20,7 @@
stdout-path = "serial0";
};
- memory {
+ memory@40000000 {
device_type = "memory";
reg = <0x0 0x40000000 0x0 0x20000000>;
};
diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
index f39bc10cc5bd..a620ac0d0b19 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -76,6 +76,12 @@
method = "smc";
};
+ firmware {
+ scm {
+ compatible = "qcom,scm-ipq8074", "qcom,scm";
+ };
+ };
+
soc: soc {
#address-cells = <0x1>;
#size-cells = <0x1>;
@@ -198,6 +204,38 @@
status = "disabled";
};
+ prng: rng@e3000 {
+ compatible = "qcom,prng-ee";
+ reg = <0x000e3000 0x1000>;
+ clocks = <&gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "core";
+ status = "disabled";
+ };
+
+ cryptobam: dma@704000 {
+ compatible = "qcom,bam-v1.7.0";
+ reg = <0x00704000 0x20000>;
+ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <1>;
+ qcom,controlled-remotely = <1>;
+ status = "disabled";
+ };
+
+ crypto: crypto@73a000 {
+ compatible = "qcom,crypto-v5.1";
+ reg = <0x0073a000 0x6000>;
+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>,
+ <&gcc GCC_CRYPTO_AXI_CLK>,
+ <&gcc GCC_CRYPTO_CLK>;
+ clock-names = "iface", "bus", "core";
+ dmas = <&cryptobam 2>, <&cryptobam 3>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
tlmm: pinctrl@1000000 {
compatible = "qcom,ipq8074-pinctrl";
reg = <0x01000000 0x300000>;
@@ -583,10 +621,10 @@
pcie1: pci@10000000 {
compatible = "qcom,pcie-ipq8074";
- reg = <0x10000000 0xf1d
- 0x10000f20 0xa8
- 0x00088000 0x2000
- 0x10100000 0x1000>;
+ reg = <0x10000000 0xf1d>,
+ <0x10000f20 0xa8>,
+ <0x00088000 0x2000>,
+ <0x10100000 0x1000>;
reg-names = "dbi", "elbi", "parf", "config";
device_type = "pci";
linux,pci-domain = <1>;
@@ -645,10 +683,10 @@
pcie0: pci@20000000 {
compatible = "qcom,pcie-ipq8074";
- reg = <0x20000000 0xf1d
- 0x20000f20 0xa8
- 0x00080000 0x2000
- 0x20100000 0x1000>;
+ reg = <0x20000000 0xf1d>,
+ <0x20000f20 0xa8>,
+ <0x00080000 0x2000>,
+ <0x20100000 0x1000>;
reg-names = "dbi", "elbi", "parf", "config";
device_type = "pci";
linux,pci-domain = <0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts
index c3f885923127..d66c15538785 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts
@@ -9,6 +9,5 @@
/ {
model = "Qualcomm Technologies, Inc. MSM 8916 MTP";
- compatible = "qcom,msm8916-mtp", "qcom,msm8916-mtp/1",
- "qcom,msm8916", "qcom,mtp";
+ compatible = "qcom,msm8916-mtp", "qcom,msm8916-mtp/1", "qcom,msm8916";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts
new file mode 100644
index 000000000000..4e20cc0008f7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2020 Stephan Gerhold
+
+/dts-v1/;
+
+#include "msm8916-pm8916.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "Xiaomi Redmi 2 (Wingtech WT88047)";
+ compatible = "wingtech,wt88047", "qcom,msm8916";
+
+ aliases {
+ serial0 = &blsp1_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys_default>;
+
+ label = "GPIO Buttons";
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+
+ usb_id: usb-id {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpio = <&msmgpio 110 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_id_default>;
+ };
+};
+
+&blsp_i2c2 {
+ status = "okay";
+
+ imu@68 {
+ compatible = "invensense,mpu6880";
+ reg = <0x68>;
+
+ interrupt-parent = <&msmgpio>;
+ interrupts = <115 IRQ_TYPE_EDGE_RISING>;
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l6>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&imu_default>;
+
+ mount-matrix = "1", "0", "0",
+ "0", "-1", "0",
+ "0", "0", "1";
+ };
+};
+
+&blsp_i2c5 {
+ status = "okay";
+
+ touchscreen@38 {
+ /* Likely some other model but works just fine with this one */
+ compatible = "edt,edt-ft5506";
+ reg = <0x38>;
+
+ interrupt-parent = <&msmgpio>;
+ interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+
+ reset-gpios = <&msmgpio 12 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&pm8916_l17>;
+ iovcc-supply = <&pm8916_l6>;
+
+ touchscreen-size-x = <720>;
+ touchscreen-size-y = <1280>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touchscreen_default>;
+ };
+};
+
+&blsp_i2c6 {
+ status = "okay";
+
+ led-controller@45 {
+ compatible = "awinic,aw2013";
+ reg = <0x45>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vcc-supply = <&pm8916_l16>;
+
+ led@0 {
+ reg = <0>;
+ led-max-microamp = <15000>;
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <1>;
+ led-max-microamp = <15000>;
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+
+ led@2 {
+ reg = <2>;
+ led-max-microamp = <15000>;
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+ };
+};
+
+&blsp1_uart2 {
+ status = "okay";
+};
+
+&pm8916_resin {
+ status = "okay";
+ linux,code = <KEY_VOLUMEDOWN>;
+};
+
+&pm8916_vib {
+ status = "okay";
+};
+
+&pronto {
+ status = "okay";
+};
+
+&sdhc_1 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>;
+};
+
+&sdhc_2 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ non-removable;
+};
+
+&usb {
+ status = "okay";
+ extcon = <&usb_id>, <&usb_id>;
+};
+
+&usb_hs_phy {
+ extcon = <&usb_id>;
+};
+
+&smd_rpm_regulators {
+ vdd_l1_l2_l3-supply = <&pm8916_s3>;
+ vdd_l4_l5_l6-supply = <&pm8916_s4>;
+ vdd_l7-supply = <&pm8916_s4>;
+
+ s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2100000>;
+ };
+
+ l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ l4 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l8 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ l9 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l10 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ l11 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-allow-set-load;
+ regulator-system-load = <200000>;
+ };
+
+ l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ l13 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l16 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ l18 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+};
+
+&msmgpio {
+ gpio_keys_default: gpio-keys-default {
+ pins = "gpio107";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ imu_default: imu-default {
+ pins = "gpio115";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ touchscreen_default: touchscreen-default {
+ pins = "gpio13";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-pull-up;
+
+ reset {
+ pins = "gpio12";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ usb_id_default: usb-id-default {
+ pins = "gpio110";
+ function = "gpio";
+
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 4f06c0a9c425..3f85e34a8ce6 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -489,6 +489,26 @@
<&rpmcc RPM_SMD_SNOC_A_CLK>;
};
+ stm: stm@802000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <0x00802000 0x1000>,
+ <0x09280000 0x180000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ status = "disabled";
+
+ out-ports {
+ port {
+ stm_out: endpoint {
+ remote-endpoint = <&funnel0_in7>;
+ };
+ };
+ };
+ };
+
/* System CTIs */
/* CTI 0 - TMC connections */
cti0: cti@810000 {
@@ -562,6 +582,13 @@
remote-endpoint = <&funnel1_out>;
};
};
+
+ port@7 {
+ reg = <7>;
+ funnel0_in7: endpoint {
+ remote-endpoint = <&stm_out>;
+ };
+ };
};
out-ports {
diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi
index f9f0b5aa6a26..986fe60dec5f 100644
--- a/arch/arm64/boot/dts/qcom/msm8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi
@@ -15,16 +15,18 @@
chosen { };
clocks {
- xo_board: xo_board {
+ xo_board: xo-board {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <19200000>;
+ clock-output-names = "xo_board";
};
- sleep_clk: sleep_clk {
+ sleep_clk: sleep-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
+ clock-output-names = "sleep_clk";
};
};
@@ -430,7 +432,7 @@
power-domains = <&gcc USB30_GDSC>;
qcom,select-utmi-as-pipe-clk;
- dwc3@f9200000 {
+ usb@f9200000 {
compatible = "snps,dwc3";
reg = <0xf9200000 0xcc00>;
interrupts = <0 131 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi
index 1e1514e9158c..ac43a91f1104 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi
@@ -20,3 +20,11 @@
};
};
};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_phy {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-dora.dts b/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-dora.dts
new file mode 100644
index 000000000000..b018693600a5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-dora.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include "msm8996-sony-xperia-tone-dora.dts"
+#include "pmi8996.dtsi"
+
+/ {
+ model = "Sony Xperia X Performance (PMI8996)";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-kagura.dts b/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-kagura.dts
new file mode 100644
index 000000000000..842ea3cf557e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-kagura.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include "msm8996-sony-xperia-tone-kagura.dts"
+#include "pmi8996.dtsi"
+
+/ {
+ model = "Sony Xperia XZ (PMI8996)";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-keyaki.dts b/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-keyaki.dts
new file mode 100644
index 000000000000..b3f9062da4b0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-pmi8996-sony-xperia-tone-keyaki.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include "msm8996-sony-xperia-tone-keyaki.dts"
+#include "pmi8996.dtsi"
+
+/ {
+ model = "Sony Xperia XZs (PMI8996)";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-dora.dts b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-dora.dts
new file mode 100644
index 000000000000..b4cca54dcb68
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-dora.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+/dts-v1/;
+
+#include "msm8996-sony-xperia-tone.dtsi"
+
+/ {
+ model = "Sony Xperia X Performance";
+ compatible = "sony,dora-row", "qcom,msm8996";
+};
+
+/delete-node/ &tof_sensor;
+/delete-node/ &pm8994_l11;
+/delete-node/ &pm8994_l14;
+
+&usb_detect {
+ pins = "gpio24";
+};
+
+&usb3_id {
+ id-gpio = <&tlmm 24 GPIO_ACTIVE_LOW>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-kagura.dts b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-kagura.dts
new file mode 100644
index 000000000000..be6ea855fcce
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-kagura.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+/dts-v1/;
+
+#include "msm8996-sony-xperia-tone.dtsi"
+
+/ {
+ model = "Sony Xperia XZ";
+ compatible = "sony,kagura-row", "qcom,msm8996";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-keyaki.dts b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-keyaki.dts
new file mode 100644
index 000000000000..1eee7d0fc178
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone-keyaki.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+/dts-v1/;
+
+#include "msm8996-sony-xperia-tone.dtsi"
+
+/ {
+ model = "Sony Xperia XZs";
+ compatible = "sony,keyaki-row", "qcom,msm8996";
+};
+
+&pm8994_l19 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+};
+
+&pm8994_l30 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-pull-down;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi
new file mode 100644
index 000000000000..507396c4d23b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi
@@ -0,0 +1,956 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include "msm8996.dtsi"
+#include "pm8994.dtsi"
+#include "pmi8994.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+
+/delete-node/ &slpi_region;
+/delete-node/ &venus_region;
+/delete-node/ &zap_shader_region;
+
+/ {
+ qcom,msm-id = <246 0x30001>; /* MSM8996 V3.1 (Final) */
+ qcom,pmic-id = <0x20009 0x2000a 0 0>; /* PM8994 + PMI8994 */
+ qcom,board-id = <8 0>;
+
+ chosen {
+ /*
+ * Due to an unknown-for-a-few-years regression,
+ * SDHCI only works on MSM8996 in PIO (lame) mode.
+ */
+ bootargs = "sdhci.debug_quirks=0x40 sdhci.debug_quirks2=0x4 maxcpus=2";
+ };
+
+ reserved-memory {
+ ramoops@a7f00000 {
+ compatible = "ramoops";
+ reg = <0 0xa7f00000 0 0x100000>;
+ record-size = <0x20000>;
+ console-size = <0x40000>;
+ ftrace-size = <0x20000>;
+ pmsg-size = <0x20000>;
+ ecc-size = <16>;
+ };
+
+ cont_splash_mem: memory@83401000 {
+ reg = <0 0x83401000 0 0x23ff000>;
+ no-map;
+ };
+
+ zap_shader_region: gpu@90400000 {
+ compatible = "shared-dma-pool";
+ reg = <0x0 0x90400000 0x0 0x2000>;
+ no-map;
+ };
+
+ slpi_region: memory@90500000 {
+ reg = <0 0x90500000 0 0xa00000>;
+ no-map;
+ };
+
+ venus_region: memory@90f00000 {
+ reg = <0 0x90f00000 0 0x500000>;
+ no-map;
+ };
+ };
+
+ panel_tvdd: tvdd-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "panel_tvdd";
+ gpio = <&tlmm 50 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&tp_vddio_en>;
+ pinctrl-names = "default";
+ };
+
+ usb3_id: usb3-id {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpio = <&tlmm 25 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_detect>;
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ regulator-name = "vph_pwr";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ wlan_en: wlan-en-1-8v {
+ compatible = "regulator-fixed";
+ regulator-name = "wlan-en-regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&tlmm 84 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wl_reg_on>;
+
+ /* WLAN card specific delay */
+ startup-delay-us = <70000>;
+ enable-active-high;
+ };
+};
+
+&blsp1_i2c3 {
+ status = "okay";
+ clock-frequency = <355000>;
+
+ tof_sensor: vl53l0x@29 {
+ compatible = "st,vl53l0x";
+ reg = <0x29>;
+ };
+};
+
+&blsp1_uart2 {
+ status = "okay";
+};
+
+&blsp2_i2c5 {
+ status = "okay";
+ clock-frequency = <355000>;
+
+ /* FUSB301 USB-C controller */
+};
+
+&blsp2_i2c6 {
+ status = "okay";
+ clock-frequency = <355000>;
+
+ synaptics@2c {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x2c>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <125 IRQ_TYPE_EDGE_FALLING>;
+ vdd-supply = <&panel_tvdd>;
+
+ syna,reset-delay-ms = <220>;
+ syna,startup-delay-ms = <220>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rmi4-f01@1 {
+ reg = <0x1>;
+ syna,nosleep-mode = <1>;
+ };
+
+ rmi4-f11@11 {
+ reg = <0x11>;
+ syna,sensor-type = <1>;
+ };
+ };
+};
+
+&blsp2_uart2 {
+ status = "okay";
+};
+
+&camera0_mclk {
+ drive-strength = <2>;
+ output-low;
+};
+
+&camera0_pwdn {
+ drive-strength = <2>;
+ output-low;
+};
+
+&camera0_rst {
+ pins = "gpio30";
+ drive-strength = <2>;
+ output-low;
+};
+
+&camera2_mclk {
+ drive-strength = <2>;
+ output-low;
+};
+
+&camera2_rst {
+ drive-strength = <2>;
+ output-low;
+};
+
+&hsusb_phy1 {
+ status = "okay";
+
+ vdda-pll-supply = <&pm8994_l12>;
+ vdda-phy-dpdm-supply = <&pm8994_l24>;
+};
+
+&mmcc {
+ vdd-gfx-supply = <&vdd_gfx>;
+};
+
+&pcie0 {
+ status = "okay";
+ perst-gpio = <&tlmm 35 GPIO_ACTIVE_LOW>;
+ wake-gpio = <&tlmm 37 GPIO_ACTIVE_HIGH>;
+ vddpe-3v3-supply = <&wlan_en>;
+ vdda-supply = <&pm8994_l28>;
+};
+
+&pcie_phy {
+ status = "okay";
+
+ vdda-phy-supply = <&pm8994_l28>;
+ vdda-pll-supply = <&pm8994_l12>;
+};
+
+&pm8994_gpios {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm8994_gpios_defaults>;
+ gpio-line-names =
+ "NC",
+ "VOL_DOWN_N",
+ "VOL_UP_N",
+ "SNAPSHOT_N",
+ "FOCUS_N",
+ "NC",
+ "NFC_VEN",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "EAR_EN",
+ "NC",
+ "PM_DIVCLK1",
+ "PMI_CLK",
+ "NC",
+ "WL_SLEEP_CLK",
+ "NC",
+ "PMIC_SPON",
+ "UIM_BATT_ALARM",
+ "PMK_SLEEP_CLK";
+
+ /*
+ * We don't yet know for sure which GPIOs are of our interest, but what
+ * we do know is that if a vendor sets the pins to a non-default state, there's
+ * probably a reason for it, and just to be on the safe side, we follow suit.
+ */
+ pm8994_gpios_defaults: pm8994-gpios-default-state {
+ pm8994-gpio1-nc {
+ pins = "gpio1";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ bias-high-impedance;
+ };
+
+ vol-down-n {
+ pins = "gpio2";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ input-enable;
+ bias-pull-up;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ vol-up-n {
+ pins = "gpio3";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ input-enable;
+ bias-pull-up;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ camera-snapshot-n {
+ pins = "gpio4";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ input-enable;
+ bias-pull-up;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ camera-focus-n {
+ pins = "gpio5";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ input-enable;
+ bias-pull-up;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pm8994-gpio6-nc {
+ pins = "gpio6";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ bias-high-impedance;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ nfc-download {
+ pins = "gpio7";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ output-low;
+ drive-push-pull;
+ bias-disable;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pm8994-gpio8-nc {
+ pins = "gpio8";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ output-low;
+ drive-push-pull;
+ bias-high-impedance;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ pm8994-gpio9-nc {
+ pins = "gpio9";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ output-high;
+ drive-push-pull;
+ bias-high-impedance;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ nfc-clock {
+ pins = "gpio10";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ input-enable;
+ drive-push-pull;
+ bias-pull-down;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pm8994-gpio11-nc {
+ pins = "gpio11";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ bias-high-impedance;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ pm8994-gpio12-nc {
+ pins = "gpio12";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ bias-high-impedance;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ ear-enable {
+ pins = "gpio13";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ output-high;
+ drive-push-pull;
+ bias-disable;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pm8994-gpio14-nc {
+ pins = "gpio14";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ input-enable;
+ bias-high-impedance;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ pm-divclk1-gpio {
+ pins = "gpio15";
+ function = "func1";
+ output-high;
+ drive-push-pull;
+ bias-high-impedance;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ pmi-clk-gpio {
+ pins = "gpio16";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ };
+
+ pm8994-gpio17-nc {
+ pins = "gpio17";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ bias-high-impedance;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ rome-sleep {
+ pins = "gpio18";
+ function = PMIC_GPIO_FUNC_FUNC2;
+ output-low;
+ drive-push-pull;
+ bias-disable;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_MED>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pm8994-gpio19-nc {
+ pins = "gpio19";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ output-low;
+ drive-push-pull;
+ bias-high-impedance;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ pm8994-gpio22-nc {
+ pins = "gpio22";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ bias-high-impedance;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+ };
+};
+
+&pm8994_mpps {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm8994_mpps_defaults>;
+
+ gpio-line-names =
+ "SDC_UIM_VBIAS",
+ "LCD_ID_ADC",
+ "VREF_DACX",
+ "NC",
+ "FLASH_THERM",
+ "NC",
+ "NC",
+ "RF_ID";
+
+ pm8994_mpps_defaults: pm8994-mpps-default-state {
+ lcd-id_adc-mpp {
+ pins = "mpp2";
+ function = "analog";
+ input-enable;
+ qcom,amux-route = <PMIC_MPP_AMUX_ROUTE_CH6>;
+ };
+
+ pm-mpp4-nc {
+ pins = "mpp4";
+ function = "digital";
+ bias-high-impedance;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ flash-therm-mpp {
+ pins = "mpp5";
+ function = "analog";
+ input-enable;
+ qcom,amux-route = <PMIC_MPP_AMUX_ROUTE_CH5>;
+ };
+
+ mpp6-nc {
+ pins = "mpp6";
+ function = "digital";
+ bias-high-impedance;
+ };
+
+ rf-id-mpp {
+ pins = "mpp8";
+ function = "analog";
+ input-enable;
+ qcom,amux-route = <PMIC_MPP_AMUX_ROUTE_CH8>;
+ };
+ };
+};
+
+&pm8994_resin {
+ status = "okay";
+ linux,code = <KEY_VOLUMEUP>;
+};
+
+&pmi8994_gpios {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmi8994_gpios_defaults>;
+
+ gpio-line-names =
+ "VIB_LDO_EN",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "USB_SWITCH_SEL",
+ "NC";
+
+ pmi8994_gpios_defaults: pmi8994-gpios-default-state {
+ vib-ldo-en-gpio {
+ pins = "gpio1";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ output-low;
+ bias-disable;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pmi-gpio2-nc {
+ pins = "gpio2";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ input-enable;
+ bias-high-impedance;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ pmi-gpio3-nc {
+ pins = "gpio3";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ input-enable;
+ bias-high-impedance;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_VPH>;
+ };
+
+ pmi-gpio4-nc {
+ pins = "gpio4";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ output-high;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pmi-gpio5-nc {
+ pins = "gpio5";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ output-high;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pmi-gpio6-nc {
+ pins = "gpio6";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ output-high;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pmi-gpio7-nc {
+ pins = "gpio7";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ output-high;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ pmi-gpio8-nc {
+ pins = "gpio8";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ output-high;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ usb-switch-sel {
+ pins = "gpio9";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ drive-push-pull;
+ };
+
+ pmi-gpio10-nc {
+ pins = "gpio10";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ output-low;
+ drive-push-pull;
+ bias-disable;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ power-source = <PM8994_GPIO_S4>;
+ };
+ };
+};
+
+&pmi8994_spmi_regulators {
+ qcom,saw-reg = <&saw3>;
+
+ vdd_gfx:
+ pmi8994_s2: s2 {
+ /* Pinned to a high value for now to avoid random crashes. */
+ regulator-min-microvolt = <1015000>;
+ regulator-max-microvolt = <1015000>;
+ regulator-name = "vdd_gfx";
+ regulator-always-on;
+ };
+
+ pmi8994_s9: s9 {
+ qcom,saw-slave;
+ };
+
+ pmi8994_s10: s10 {
+ qcom,saw-slave;
+ };
+
+ pmi8994_s11: s11 {
+ qcom,saw-leader;
+ regulator-always-on;
+ regulator-min-microvolt = <470000>;
+ regulator-max-microvolt = <1140000>;
+ };
+};
+
+&pmi8994_wled {
+ status = "okay";
+ default-brightness = <512>;
+};
+
+&rpm_requests {
+ pm8994-regulators {
+ compatible = "qcom,rpm-pm8994-regulators";
+
+ vdd_s1-supply = <&vph_pwr>;
+ vdd_s2-supply = <&vph_pwr>;
+ vdd_s3-supply = <&vph_pwr>;
+ vdd_s4-supply = <&vph_pwr>;
+ vdd_s5-supply = <&vph_pwr>;
+ vdd_s6-supply = <&vph_pwr>;
+ vdd_s7-supply = <&vph_pwr>;
+ vdd_s8-supply = <&vph_pwr>;
+ vdd_s9-supply = <&vph_pwr>;
+ vdd_s10-supply = <&vph_pwr>;
+ vdd_s11-supply = <&vph_pwr>;
+ vdd_s12-supply = <&vph_pwr>;
+ vdd_l1-supply = <&pm8994_s3>;
+ vdd_l2_l26_l28-supply = <&pm8994_s3>;
+ vdd_l3_l11-supply = <&pm8994_s3>;
+ vdd_l4_l27_l31-supply = <&pm8994_s3>;
+ vdd_l5_l7-supply = <&pm8994_s5>;
+ vdd_l6_l12_l32-supply = <&pm8994_s5>;
+ vdd_l8_l16_l30-supply = <&vph_pwr>;
+ vdd_l14_l15-supply = <&pm8994_s5>;
+ vdd_l20_l21-supply = <&pm8994_s5>;
+ vdd_l25-supply = <&pm8994_s3>;
+ vdd_lvs1_2-supply = <&pm8994_s4>;
+
+ pm8994_s3: s3 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8994_s4: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-system-load = <325000>;
+ regulator-always-on;
+ };
+
+ pm8994_s5: s5 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ };
+
+ pm8994_s7: s7 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ };
+
+ pm8994_l1: l1 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ pm8994_l2: l2 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ };
+
+ pm8994_l3: l3 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ pm8994_l4: l4 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ /* L6 and L7 seem unused. */
+
+ pm8994_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8994_l9: l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8994_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8994_l11: l11 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ pm8994_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allow-set-load;
+ };
+
+ pm8994_l13: l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-system-load = <22000>;
+ regulator-allow-set-load;
+ };
+
+ pm8994_l14: l14 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ };
+
+ pm8994_l15: l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8994_l16: l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ pm8994_l17: l17 {
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2500000>;
+ };
+
+ pm8994_l18: l18 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8994_l19: l19 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8994_l20: l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-system-load = <570000>;
+ regulator-allow-set-load;
+ };
+
+ pm8994_l21: l21 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-system-load = <800000>;
+ regulator-allow-set-load;
+ };
+
+ pm8994_l22: l22 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8994_l23: l23 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ pm8994_l24: l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ regulator-allow-set-load;
+ };
+
+ pm8994_l25: l25 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-allow-set-load;
+ };
+
+ pm8994_l27: l27 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8994_l28: l28 {
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <925000>;
+ regulator-allow-set-load;
+ };
+
+ pm8994_l29: l29 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ pm8994_l30: l30 { };
+
+ pm8994_l32: l32 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+ };
+};
+
+&sdhc1 {
+ /* eMMC doesn't seem to cooperate even in PIO mode.. */
+ status = "disabled";
+
+ vmmc-supply = <&pm8994_l20>;
+ vqmmc-supply = <&pm8994_s4>;
+ mmc-hs400-1_8v;
+ mmc-hs200-1_8v;
+};
+
+&sdhc2 {
+ status = "okay";
+
+ cd-gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&pm8994_l21>;
+ vqmmc-supply = <&pm8994_l13>;
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>;
+ pinctrl-0 = <&sw_service_gpio>;
+ pinctrl-names = "default";
+
+ disp_reset_n_gpio: disp-reset-n {
+ pins = "gpio8";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ mdp_vsync_p_gpio: mdp-vsync-p {
+ pins = "gpio10";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ sw_service_gpio: sw-service-gpio {
+ pins = "gpio16";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ usb_detect: usb-detect {
+ pins = "gpio25";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ uim_detect_en: uim-detect-en {
+ pins = "gpio29";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ tray_det_pin: tray-det {
+ pins = "gpio40";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tp_vddio_en: tp-vddio-en {
+ pins = "gpio50";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ lcd_vddio_en: lcd-vddio-en {
+ pins = "gpio51";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+
+ wl_host_wake: wl-host-wake {
+ pins = "gpio79";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ input-high;
+ };
+
+ wl_reg_on: wl-reg-on {
+ pins = "gpio84";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+
+ ts_reset_n: ts-rst-n {
+ pins = "gpio89";
+ function = "gpio";
+ drive-strength = <2>;
+ };
+
+ touch_int_n: touch-int-n {
+ pins = "gpio125";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ touch_int_sleep: touch-int-sleep {
+ pins = "gpio125";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+};
+
+/*
+ * For reasons that are currently unknown (but probably related to fusb301), USB takes about
+ * 6 minutes to wake up (nothing interesting in kernel logs), but then it works as it should.
+ */
+&usb3 {
+ status = "okay";
+ qcom,select-utmi-as-pipe-clk;
+};
+
+&usb3_dwc3 {
+ extcon = <&usb3_id>;
+ dr_mode = "peripheral";
+ phys = <&hsusb_phy1>;
+ phy-names = "usb2-phy";
+ snps,hird-threshold = /bits/ 8 <0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-v3.0.dtsi b/arch/arm64/boot/dts/qcom/msm8996-v3.0.dtsi
new file mode 100644
index 000000000000..5728583af41e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-v3.0.dtsi
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include "msm8996.dtsi"
+
+/ {
+ qcom,msm-id = <246 0x30000>;
+};
+
+ /*
+ * This revision seems to have differ GPU CPR
+ * parameters, GPU frequencies and some differences
+ * when it comes to voltage delivery to.. once again
+ * the GPU. Funnily enough, it's simpler to make it an
+ * overlay on top of 3.1 (the final one) than vice versa.
+ * The differences will show here as more and more
+ * features get enabled upstream.
+ */
+
+gpu_opp_table_3_0: gpu-opp-table-30 {
+ compatible = "operating-points-v2";
+
+ opp-624000000 {
+ opp-hz = /bits/ 64 <624000000>;
+ opp-level = <7>;
+ };
+
+ opp-560000000 {
+ opp-hz = /bits/ 64 <560000000>;
+ opp-level = <6>;
+ };
+
+ opp-510000000 {
+ opp-hz = /bits/ 64 <510000000>;
+ opp-level = <5>;
+ };
+
+ opp-401800000 {
+ opp-hz = /bits/ 64 <401800000>;
+ opp-level = <4>;
+ };
+
+ opp-315000000 {
+ opp-hz = /bits/ 64 <315000000>;
+ opp-level = <3>;
+ };
+
+ opp-214000000 {
+ opp-hz = /bits/ 64 <214000000>;
+ opp-level = <3>;
+ };
+
+ opp-133000000 {
+ opp-hz = /bits/ 64 <133000000>;
+ opp-level = <3>;
+ };
+};
+
+&gpu {
+ operating-points-v2 = <&gpu_opp_table_3_0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 78c55ca10ba9..52df22ab3f6a 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -19,14 +19,14 @@
chosen { };
clocks {
- xo_board: xo_board {
+ xo_board: xo-board {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <19200000>;
clock-output-names = "xo_board";
};
- sleep_clk: sleep_clk {
+ sleep_clk: sleep-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32764>;
@@ -368,10 +368,10 @@
#hwlock-cells = <1>;
};
- memory {
+ memory@80000000 {
device_type = "memory";
/* We expect the bootloader to fill in the reg */
- reg = <0 0 0 0>;
+ reg = <0x0 0x80000000 0x0 0x0>;
};
psci {
@@ -898,6 +898,8 @@
phy-names = "hdmi_phy";
#sound-dai-cells = <1>;
+ status = "disabled";
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -931,6 +933,8 @@
<&gcc GCC_HDMI_CLKREF_CLK>;
clock-names = "iface",
"ref";
+
+ status = "disabled";
};
};
@@ -968,6 +972,8 @@
status = "disabled";
+ #cooling-cells = <2>;
+
gpu_opp_table: opp-table {
compatible ="operating-points-v2";
@@ -1082,21 +1088,21 @@
camera0_state_on:
camera_rear_default: camera-rear-default {
- mclk0 {
+ camera0_mclk: mclk0 {
pins = "gpio13";
function = "cam_mclk";
drive-strength = <16>;
bias-disable;
};
- rst {
+ camera0_rst: rst {
pins = "gpio25";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- pwdn {
+ camera0_pwdn: pwdn {
pins = "gpio26";
function = "gpio";
drive-strength = <16>;
@@ -1137,14 +1143,14 @@
camera2_state_on:
camera_front_default: camera-front-default {
- mclk2 {
+ camera2_mclk: mclk2 {
pins = "gpio15";
function = "cam_mclk";
drive-strength = <16>;
bias-disable;
};
- rst {
+ camera2_rst: rst {
pins = "gpio23";
function = "gpio";
drive-strength = <16>;
@@ -2566,7 +2572,7 @@
power-domains = <&gcc USB30_GDSC>;
status = "disabled";
- dwc3@6a00000 {
+ usb3_dwc3: dwc3@6a00000 {
compatible = "snps,dwc3";
reg = <0x06a00000 0xcc00>;
interrupts = <0 131 IRQ_TYPE_LEVEL_HIGH>;
@@ -3205,7 +3211,14 @@
gpu1_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
- type = "hot";
+ type = "passive";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&gpu1_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3220,7 +3233,14 @@
gpu2_alert0: trip-point0 {
temperature = <90000>;
hysteresis = <2000>;
- type = "hot";
+ type = "passive";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&gpu2_alert0>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
index e9d3ce29937c..34039b5c8017 100644
--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
@@ -18,10 +18,10 @@
chosen { };
- memory {
+ memory@80000000 {
device_type = "memory";
/* We expect the bootloader to fill in the reg */
- reg = <0 0 0 0>;
+ reg = <0x0 0x80000000 0x0 0x0>;
};
reserved-memory {
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 2e6a6f6c3b66..e847d7209afc 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -3,9 +3,35 @@
* Copyright (c) 2020, Konrad Dybcio
*/
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+ thermal-zones {
+ pm660 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&pm660_temp>;
+
+ trips {
+ pm660_alert0: pm660-alert0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ pm660_crit: pm660-crit {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
&spmi_bus {
@@ -37,6 +63,102 @@
};
+ pm660_temp: temp-alarm@2400 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0x2400>;
+ interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
+ io-channels = <&pm660_adc ADC5_DIE_TEMP>;
+ io-channel-names = "thermal";
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm660_adc: adc@3100 {
+ compatible = "qcom,spmi-adc-rev2";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ ref_gnd: ref_gnd@0 {
+ reg = <ADC5_REF_GND>;
+ qcom,decimation = <1024>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ vref_1p25: vref_1p25@1 {
+ reg = <ADC5_1P25VREF>;
+ qcom,decimation = <1024>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ die_temp: die_temp@6 {
+ reg = <ADC5_DIE_TEMP>;
+ qcom,decimation = <1024>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ xo_therm: xo_therm@4c {
+ reg = <ADC5_XO_THERM_100K_PU>;
+ qcom,pre-scaling = <1 1>;
+ qcom,decimation = <1024>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ msm_therm: msm_therm@4d {
+ reg = <ADC5_AMUX_THM1_100K_PU>;
+ qcom,pre-scaling = <1 1>;
+ qcom,decimation = <1024>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ emmc_therm: emmc_therm@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,pre-scaling = <1 1>;
+ qcom,decimation = <1024>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ pa_therm0: thermistor0@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,pre-scaling = <1 1>;
+ qcom,decimation = <1024>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ pa_therm1: thermistor1@50 {
+ reg = <ADC5_AMUX_THM4_100K_PU>;
+ qcom,pre-scaling = <1 1>;
+ qcom,decimation = <1024>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ quiet_therm: quiet_therm@51 {
+ reg = <ADC5_AMUX_THM5_100K_PU>;
+ qcom,pre-scaling = <1 1>;
+ qcom,decimation = <1024>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ vadc_vph_pwr: vph_pwr@83 {
+ reg = <ADC5_VPH_PWR>;
+ qcom,decimation = <1024>;
+ qcom,pre-scaling = <1 3>;
+ };
+
+ vcoin: vcoin@83 {
+ reg = <ADC5_VCOIN>;
+ qcom,decimation = <1024>;
+ qcom,pre-scaling = <1 3>;
+ };
+ };
+
pm660_gpios: gpios@c000 {
compatible = "qcom,pm660-gpio";
reg = <0xc000>;
@@ -47,4 +169,15 @@
#interrupt-cells = <2>;
};
};
+
+ pmic@1 {
+ compatible = "qcom,pm660", "qcom,spmi-pmic";
+ reg = <0x1 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm660_spmi_regulators: pm660-regulators {
+ compatible = "qcom,pm660-regulators";
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/pm660l.dtsi b/arch/arm64/boot/dts/qcom/pm660l.dtsi
index edba6de02084..05086cbe573b 100644
--- a/arch/arm64/boot/dts/qcom/pm660l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660l.dtsi
@@ -3,9 +3,35 @@
* Copyright (c) 2020, Konrad Dybcio
*/
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+ thermal-zones {
+ pm660l {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&pm660l_temp>;
+
+ trips {
+ pm660l_alert0: pm660l-alert0 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ pm660l_crit: pm660l-crit {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
&spmi_bus {
@@ -15,6 +41,13 @@
#address-cells = <1>;
#size-cells = <0>;
+ pm660l_temp: temp-alarm@2400 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0x2400>;
+ interrupts = <0x2 0x24 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
pm660l_gpios: gpios@c000 {
compatible = "qcom,pm660l-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
@@ -31,6 +64,27 @@
reg = <0x3 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
+
+ pm660l_wled: leds@d800 {
+ compatible = "qcom,pm660l-wled";
+ reg = <0xd800 0xd900>;
+ interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ovp";
+ label = "backlight";
+
+ qcom,switching-freq = <800>;
+ qcom,ovp-millivolt = <29600>;
+ qcom,current-boost-limit = <970>;
+ qcom,current-limit-microamp = <20000>;
+ qcom,num-strings = <2>;
+ qcom,enabled-strings = <0 1>;
+
+ status = "disabled";
+ };
+
+ pm660l_spmi_regulators: pm660l-regulators {
+ compatible = "qcom,pm660l-regulators";
+ };
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm8004.dtsi b/arch/arm64/boot/dts/qcom/pm8004.dtsi
index 0abd1abe12fc..532b79acf0e8 100644
--- a/arch/arm64/boot/dts/qcom/pm8004.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8004.dtsi
@@ -9,7 +9,6 @@
reg = <0x4 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
- status = "disabled";
};
pm8004_lsid5: pmic@5 {
@@ -17,7 +16,6 @@
reg = <0x5 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
- status = "disabled";
pm8004_spmi_regulators: regulators {
compatible = "qcom,pm8004-regulators";
diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index b21e56a46145..058cc5107c75 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -53,6 +53,12 @@
status = "disabled";
};
+ pm8150b_vbus: dcdc@1100 {
+ compatible = "qcom,pm8150b-vbus-reg";
+ status = "disabled";
+ reg = <0x1100>;
+ };
+
pm8150b_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
diff --git a/arch/arm64/boot/dts/qcom/pmi8996.dtsi b/arch/arm64/boot/dts/qcom/pmi8996.dtsi
new file mode 100644
index 000000000000..31b47209e261
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pmi8996.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+ /*
+ * PMI8996 is a slight modification of PMI8994 with
+ * some notable changes, like being the first PMIC
+ * whose the bootloader has to check to continue booting
+ * and a change to a LABIBB parameter.
+ */
+
+/ {
+ qcom,pmic-id = <0x20009 0x10013 0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
index 0da7a3b8d1bf..5ae2ddc65f7e 100644
--- a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
@@ -307,10 +307,6 @@
status = "okay";
};
-&tlmm {
- gpio-reserved-ranges = <0 4>;
-};
-
&uart2 {
status = "okay";
};
@@ -337,6 +333,16 @@
vdda-pll-max-microamp = <18300>;
};
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "host";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2phy_ac_en1_default>;
+};
&usb_1_hsphy {
status = "okay";
@@ -346,15 +352,51 @@
};
&usb_1_qmpphy {
+ status = "disabled";
+};
+
+&usb_2 {
status = "okay";
- vdda-phy-supply = <&vreg_l8c_1p2>;
- vdda-pll-supply = <&vdda_usb_ss_dp_core_1>;
};
-&usb_1 {
+&usb_2_dwc3 {
+ dr_mode = "host";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2phy_ac_en2_default>;
+};
+
+&usb_2_hsphy {
status = "okay";
+ vdda-pll-supply = <&vdd_usb_hs_core>;
+ vdda33-supply = <&vdda_usb_hs_3p1>;
+ vdda18-supply = <&vdda_usb_hs_1p8>;
};
-&usb_1_dwc3 {
- dr_mode = "peripheral";
+&usb_2_qmpphy {
+ status = "okay";
+ vdda-phy-supply = <&vreg_l8c_1p2>;
+ vdda-pll-supply = <&vdda_usb_ss_dp_core_1>;
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>;
+
+ usb2phy_ac_en1_default: usb2phy_ac_en1_default {
+ mux {
+ pins = "gpio113";
+ function = "usb2phy_ac";
+ bias-disable;
+ drive-strength = <2>;
+ };
+ };
+
+ usb2phy_ac_en2_default: usb2phy_ac_en2_default {
+ mux {
+ pins = "gpio123";
+ function = "usb2phy_ac";
+ bias-disable;
+ drive-strength = <2>;
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
index 6f9c07147551..a758e4d22612 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
@@ -23,7 +23,7 @@ ap_h1_spi: &spi0 {};
adau7002: audio-codec-1 {
compatible = "adi,adau7002";
IOVDD-supply = <&pp1800_l15a>;
- wakeup-delay-ms = <15>;
+ wakeup-delay-ms = <80>;
#sound-dai-cells = <0>;
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
index 77ae7561d436..0f2b3c00e434 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
@@ -247,29 +247,14 @@
};
};
- max98357a: audio-codec-0 {
- compatible = "maxim,max98357a";
+ max98360a: audio-codec-0 {
+ compatible = "maxim,max98360a";
pinctrl-names = "default";
pinctrl-0 = <&amp_en>;
sdmode-gpios = <&tlmm 23 GPIO_ACTIVE_HIGH>;
#sound-dai-cells = <0>;
};
- panel: panel {
- /* Compatible will be filled in per-board */
- power-supply = <&pp3300_dx_edp>;
- backlight = <&backlight>;
- hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>;
-
- ports {
- port {
- panel_in_edp: endpoint {
- remote-endpoint = <&sn65dsi86_out>;
- };
- };
- };
- };
-
pwmleds {
compatible = "pwm-leds";
keyboard_backlight: keyboard-backlight {
@@ -288,6 +273,7 @@
"Headphone Jack", "HPOL",
"Headphone Jack", "HPOR";
+ #sound-dai-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@@ -311,7 +297,19 @@
};
sound_multimedia1_codec: codec {
- sound-dai = <&max98357a>;
+ sound-dai = <&max98360a>;
+ };
+ };
+
+ dai-link@2 {
+ link-name = "MultiMedia2";
+ reg = <2>;
+ cpu {
+ sound-dai = <&lpass_cpu 2>;
+ };
+
+ codec {
+ sound-dai = <&mdss_dp>;
};
};
};
@@ -666,6 +664,21 @@ edp_brij_i2c: &i2c2 {
};
};
};
+
+ aux-bus {
+ panel: panel {
+ /* Compatible will be filled in per-board */
+ power-supply = <&pp3300_dx_edp>;
+ backlight = <&backlight>;
+ hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>;
+
+ port {
+ panel_in_edp: endpoint {
+ remote-endpoint = <&sn65dsi86_out>;
+ };
+ };
+ };
+ };
};
};
@@ -768,6 +781,10 @@ hp_i2c: &i2c9 {
reg = <MI2S_SECONDARY>;
qcom,playback-sd-lines = <0>;
};
+
+ hdmi-primary@0 {
+ reg = <LPASS_DP_RX>;
+ };
};
&mdp {
@@ -778,6 +795,15 @@ hp_i2c: &i2c9 {
status = "okay";
};
+&mdss_dp {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp_hot_plug_det>;
+ data-lanes = <0 1>;
+ vdda-1p2-supply = <&vdda_usb_ss_dp_1p2>;
+ vdda-0p9-supply = <&vdda_usb_ss_dp_core>;
+};
+
&pm6150_adc {
charger-thermistor@4f {
reg = <ADC5_AMUX_THM3_100K_PU>;
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index e7f0e5cde424..c8921e2d6480 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -110,6 +110,11 @@
no-map;
};
+ ipa_fw_mem: memory@8b700000 {
+ reg = <0 0x8b700000 0 0x10000>;
+ no-map;
+ };
+
rmtfs_mem: memory@94600000 {
compatible = "qcom,rmtfs-mem";
reg = <0x0 0x94600000 0x0 0x200000>;
@@ -668,7 +673,7 @@
qfprom: efuse@784000 {
compatible = "qcom,sc7180-qfprom", "qcom,qfprom";
- reg = <0 0x00784000 0 0x8ff>,
+ reg = <0 0x00784000 0 0x7a0>,
<0 0x00780000 0 0x7a0>,
<0 0x00782000 0 0x100>,
<0 0x00786000 0 0x1fff>;
@@ -2952,6 +2957,13 @@
remote-endpoint = <&dsi0_in>;
};
};
+
+ port@2 {
+ reg = <2>;
+ dpu_intf0_out: endpoint {
+ remote-endpoint = <&dp_in>;
+ };
+ };
};
mdp_opp_table: mdp-opp-table {
@@ -3001,6 +3013,9 @@
"iface",
"bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi_phy 0>, <&dsi_phy 1>;
+
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd SC7180_CX>;
@@ -3068,6 +3083,75 @@
status = "disabled";
};
+
+ mdss_dp: displayport-controller@ae90000 {
+ compatible = "qcom,sc7180-dp";
+ status = "disabled";
+
+ reg = <0 0x0ae90000 0 0x1400>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <12>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>;
+ clock-names = "core_iface", "core_aux", "ctrl_link",
+ "ctrl_link_iface", "stream_pixel";
+ #clock-cells = <1>;
+ assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+ assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
+ phys = <&dp_phy>;
+ phy-names = "dp";
+
+ operating-points-v2 = <&dp_opp_table>;
+ power-domains = <&rpmhpd SC7180_CX>;
+
+ #sound-dai-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ dp_in: endpoint {
+ remote-endpoint = <&dpu_intf0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dp_out: endpoint { };
+ };
+ };
+
+ dp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-270000000 {
+ opp-hz = /bits/ 64 <270000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
};
dispcc: clock-controller@af00000 {
@@ -3480,17 +3564,20 @@
#power-domain-cells = <1>;
};
- lpass_cpu: lpass@62f00000 {
+ lpass_cpu: lpass@62d87000 {
compatible = "qcom,sc7180-lpass-cpu";
- reg = <0 0x62f00000 0 0x29000>;
- reg-names = "lpass-lpaif";
+ reg = <0 0x62d87000 0 0x68000>, <0 0x62f00000 0 0x29000>;
+ reg-names = "lpass-hdmiif", "lpass-lpaif";
iommus = <&apps_smmu 0x1020 0>,
- <&apps_smmu 0x1021 0>;
+ <&apps_smmu 0x1021 0>,
+ <&apps_smmu 0x1032 0>;
power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>;
+ status = "disabled";
+
clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>,
<&lpasscc LPASS_AUDIO_CORE_CORE_CLK>,
<&lpasscc LPASS_AUDIO_CORE_EXT_MCLK0_CLK>,
@@ -3507,8 +3594,9 @@
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "lpass-irq-lpaif";
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "lpass-irq-lpaif", "lpass-irq-hdmi";
};
lpass_hm: clock-controller@63000000 {
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dts b/arch/arm64/boot/dts/qcom/sc7280-idp.dts
index 3900cfc09562..64fc22aff33d 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dts
@@ -8,17 +8,11 @@
/dts-v1/;
#include <dt-bindings/iio/qcom,spmi-adc7-pmr735a.h>
-#include <dt-bindings/iio/qcom,spmi-adc7-pmr735b.h>
-#include <dt-bindings/iio/qcom,spmi-adc7-pm8350.h>
-#include <dt-bindings/iio/qcom,spmi-adc7-pmk8350.h>
-#include "sc7280.dtsi"
-#include "pm7325.dtsi"
+#include "sc7280-idp.dtsi"
#include "pmr735a.dtsi"
-#include "pm8350c.dtsi"
-#include "pmk8350.dtsi"
/ {
- model = "Qualcomm Technologies, Inc. sc7280 IDP platform";
+ model = "Qualcomm Technologies, Inc. sc7280 IDP SKU1 platform";
compatible = "qcom,sc7280-idp", "google,senor", "qcom,sc7280";
aliases {
@@ -31,186 +25,6 @@
};
&apps_rsc {
- pm7325-regulators {
- compatible = "qcom,pm7325-rpmh-regulators";
- qcom,pmic-id = "b";
-
- vreg_s1b_1p8: smps1 {
- regulator-min-microvolt = <1856000>;
- regulator-max-microvolt = <2040000>;
- };
-
- vreg_s7b_0p9: smps7 {
- regulator-min-microvolt = <535000>;
- regulator-max-microvolt = <1120000>;
- };
-
- vreg_s8b_1p2: smps8 {
- regulator-min-microvolt = <1256000>;
- regulator-max-microvolt = <1500000>;
- };
-
- vreg_l1b_0p8: ldo1 {
- regulator-min-microvolt = <825000>;
- regulator-max-microvolt = <925000>;
- };
-
- vreg_l2b_3p0: ldo2 {
- regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <3544000>;
- };
-
- vreg_l6b_1p2: ldo6 {
- regulator-min-microvolt = <1140000>;
- regulator-max-microvolt = <1260000>;
- };
-
- vreg_l7b_2p9: ldo7 {
- regulator-min-microvolt = <2960000>;
- regulator-max-microvolt = <2960000>;
- };
-
- vreg_l8b_0p9: ldo8 {
- regulator-min-microvolt = <870000>;
- regulator-max-microvolt = <970000>;
- };
-
- vreg_l9b_1p2: ldo9 {
- regulator-min-microvolt = <1080000>;
- regulator-max-microvolt = <1304000>;
- };
-
- vreg_l11b_1p7: ldo11 {
- regulator-min-microvolt = <1504000>;
- regulator-max-microvolt = <2000000>;
- };
-
- vreg_l12b_0p8: ldo12 {
- regulator-min-microvolt = <751000>;
- regulator-max-microvolt = <824000>;
- };
-
- vreg_l13b_0p8: ldo13 {
- regulator-min-microvolt = <530000>;
- regulator-max-microvolt = <824000>;
- };
-
- vreg_l14b_1p2: ldo14 {
- regulator-min-microvolt = <1080000>;
- regulator-max-microvolt = <1304000>;
- };
-
- vreg_l15b_0p8: ldo15 {
- regulator-min-microvolt = <765000>;
- regulator-max-microvolt = <1020000>;
- };
-
- vreg_l16b_1p2: ldo16 {
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1300000>;
- };
-
- vreg_l17b_1p8: ldo17 {
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <1900000>;
- };
-
- vreg_l18b_1p8: ldo18 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2000000>;
- };
-
- vreg_l19b_1p8: ldo19 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- };
- };
-
- pm8350c-regulators {
- compatible = "qcom,pm8350c-rpmh-regulators";
- qcom,pmic-id = "c";
-
- vreg_s1c_2p2: smps1 {
- regulator-min-microvolt = <2190000>;
- regulator-max-microvolt = <2210000>;
- };
-
- vreg_s9c_1p0: smps9 {
- regulator-min-microvolt = <1010000>;
- regulator-max-microvolt = <1170000>;
- };
-
- vreg_l1c_1p8: ldo1 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1980000>;
- };
-
- vreg_l2c_1p8: ldo2 {
- regulator-min-microvolt = <1620000>;
- regulator-max-microvolt = <1980000>;
- };
-
- vreg_l3c_3p0: ldo3 {
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <3540000>;
- };
-
- vreg_l4c_1p8: ldo4 {
- regulator-min-microvolt = <1620000>;
- regulator-max-microvolt = <3300000>;
- };
-
- vreg_l5c_1p8: ldo5 {
- regulator-min-microvolt = <1620000>;
- regulator-max-microvolt = <3300000>;
- };
-
- vreg_l6c_2p9: ldo6 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- };
-
- vreg_l7c_3p0: ldo7 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3544000>;
- };
-
- vreg_l8c_1p8: ldo8 {
- regulator-min-microvolt = <1620000>;
- regulator-max-microvolt = <2000000>;
- };
-
- vreg_l9c_2p9: ldo9 {
- regulator-min-microvolt = <2960000>;
- regulator-max-microvolt = <2960000>;
- };
-
- vreg_l10c_0p8: ldo10 {
- regulator-min-microvolt = <720000>;
- regulator-max-microvolt = <1050000>;
- };
-
- vreg_l11c_2p8: ldo11 {
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <3544000>;
- };
-
- vreg_l12c_1p8: ldo12 {
- regulator-min-microvolt = <1650000>;
- regulator-max-microvolt = <2000000>;
- };
-
- vreg_l13c_3p0: ldo13 {
- regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <3544000>;
- };
-
- vreg_bob: bob {
- regulator-min-microvolt = <3008000>;
- regulator-max-microvolt = <3960000>;
- };
- };
-
pmr735a-regulators {
compatible = "qcom,pmr735a-rpmh-regulators";
qcom,pmic-id = "e";
@@ -242,52 +56,15 @@
};
};
-&pmk8350_vadc {
- pm8350_die_temp {
- reg = <PM8350_ADC7_DIE_TEMP>;
- label = "pm8350_die_temp";
- qcom,pre-scaling = <1 1>;
- };
-
- pmk8350_die_temp {
- reg = <PMK8350_ADC7_DIE_TEMP>;
- label = "pmk8350_die_temp";
- qcom,pre-scaling = <1 1>;
- };
-
- pmr735a_die_temp {
- reg = <PMR735A_ADC7_DIE_TEMP>;
- label = "pmr735a_die_temp";
- qcom,pre-scaling = <1 1>;
- };
-
- pmr735b_die_temp {
- reg = <PMR735B_ADC7_DIE_TEMP>;
- label = "pmr735b_die_temp";
- qcom,pre-scaling = <1 1>;
- };
-};
-
-&qupv3_id_0 {
+&ipa {
status = "okay";
+ modem-init;
};
-&uart5 {
- status = "okay";
-};
-
-/* PINCTRL - additions to nodes defined in sc7280.dtsi */
-
-&qup_uart5_default {
- tx {
- pins = "gpio46";
- drive-strength = <2>;
- bias-disable;
- };
-
- rx {
- pins = "gpio47";
- drive-strength = <2>;
- bias-pull-up;
+&pmk8350_vadc {
+ pmr735a_die_temp {
+ reg = <PMR735A_ADC7_DIE_TEMP>;
+ label = "pmr735a_die_temp";
+ qcom,pre-scaling = <1 1>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
new file mode 100644
index 000000000000..371a2a9dcf7a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
@@ -0,0 +1,341 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * sc7280 IDP board device tree source (common between SKU1 and SKU2)
+ *
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/iio/qcom,spmi-adc7-pmk8350.h>
+#include "sc7280.dtsi"
+#include "pm7325.dtsi"
+#include "pm8350c.dtsi"
+#include "pmk8350.dtsi"
+
+&apps_rsc {
+ pm7325-regulators {
+ compatible = "qcom,pm7325-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vreg_s1b_1p8: smps1 {
+ regulator-min-microvolt = <1856000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vreg_s7b_0p9: smps7 {
+ regulator-min-microvolt = <535000>;
+ regulator-max-microvolt = <1120000>;
+ };
+
+ vreg_s8b_1p2: smps8 {
+ regulator-min-microvolt = <1256000>;
+ regulator-max-microvolt = <1500000>;
+ };
+
+ vreg_l1b_0p8: ldo1 {
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <925000>;
+ };
+
+ vreg_l2b_3p0: ldo2 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ vreg_l6b_1p2: ldo6 {
+ regulator-min-microvolt = <1140000>;
+ regulator-max-microvolt = <1260000>;
+ };
+
+ vreg_l7b_2p9: ldo7 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ };
+
+ vreg_l8b_0p9: ldo8 {
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <970000>;
+ };
+
+ vreg_l9b_1p2: ldo9 {
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ vreg_l11b_1p7: ldo11 {
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ vreg_l12b_0p8: ldo12 {
+ regulator-min-microvolt = <751000>;
+ regulator-max-microvolt = <824000>;
+ };
+
+ vreg_l13b_0p8: ldo13 {
+ regulator-min-microvolt = <530000>;
+ regulator-max-microvolt = <824000>;
+ };
+
+ vreg_l14b_1p2: ldo14 {
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ vreg_l15b_0p8: ldo15 {
+ regulator-min-microvolt = <765000>;
+ regulator-max-microvolt = <1020000>;
+ };
+
+ vreg_l16b_1p2: ldo16 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ vreg_l17b_1p8: ldo17 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ };
+
+ vreg_l18b_1p8: ldo18 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ vreg_l19b_1p8: ldo19 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+ };
+
+ pm8350c-regulators {
+ compatible = "qcom,pm8350c-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vreg_s1c_2p2: smps1 {
+ regulator-min-microvolt = <2190000>;
+ regulator-max-microvolt = <2210000>;
+ };
+
+ vreg_s9c_1p0: smps9 {
+ regulator-min-microvolt = <1010000>;
+ regulator-max-microvolt = <1170000>;
+ };
+
+ vreg_l1c_1p8: ldo1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1980000>;
+ };
+
+ vreg_l2c_1p8: ldo2 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ };
+
+ vreg_l3c_3p0: ldo3 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3540000>;
+ };
+
+ vreg_l4c_1p8: ldo4 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vreg_l5c_1p8: ldo5 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vreg_l6c_2p9: ldo6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ vreg_l7c_3p0: ldo7 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ vreg_l8c_1p8: ldo8 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ vreg_l9c_2p9: ldo9 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ };
+
+ vreg_l10c_0p8: ldo10 {
+ regulator-min-microvolt = <720000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ vreg_l11c_2p8: ldo11 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ vreg_l12c_1p8: ldo12 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ vreg_l13c_3p0: ldo13 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ vreg_bob: bob {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3960000>;
+ };
+ };
+};
+
+&ipa {
+ status = "okay";
+ modem-init;
+};
+
+&pmk8350_vadc {
+ pmk8350_die_temp {
+ reg = <PMK8350_ADC7_DIE_TEMP>;
+ label = "pmk8350_die_temp";
+ qcom,pre-scaling = <1 1>;
+ };
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&sdhc_1 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc1_on>;
+ pinctrl-1 = <&sdc1_off>;
+
+ non-removable;
+ no-sd;
+ no-sdio;
+
+ vmmc-supply = <&vreg_l7b_2p9>;
+ vqmmc-supply = <&vreg_l19b_1p8>;
+};
+
+&sdhc_2 {
+ status = "okay";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_on>;
+ pinctrl-1 = <&sdc2_off>;
+
+ vmmc-supply = <&vreg_l9c_2p9>;
+ vqmmc-supply = <&vreg_l6c_2p9>;
+
+ cd-gpios = <&tlmm 91 GPIO_ACTIVE_LOW>;
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_1_hsphy {
+ status = "okay";
+
+ vdda-pll-supply = <&vreg_l10c_0p8>;
+ vdda33-supply = <&vreg_l2b_3p0>;
+ vdda18-supply = <&vreg_l1c_1p8>;
+};
+
+&usb_1_qmpphy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l6b_1p2>;
+ vdda-pll-supply = <&vreg_l1b_0p8>;
+};
+
+&usb_2 {
+ status = "okay";
+};
+
+&usb_2_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_2_hsphy {
+ status = "okay";
+
+ vdda-pll-supply = <&vreg_l10c_0p8>;
+ vdda33-supply = <&vreg_l2b_3p0>;
+ vdda18-supply = <&vreg_l1c_1p8>;
+};
+
+/* PINCTRL - additions to nodes defined in sc7280.dtsi */
+
+&qup_uart5_default {
+ tx {
+ pins = "gpio46";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio47";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+};
+
+&sdc1_on {
+ clk {
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd {
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data {
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ rclk {
+ bias-pull-down;
+ };
+};
+
+&sdc2_on {
+ clk {
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd {
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data {
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ sd-cd {
+ bias-pull-up;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp2.dts b/arch/arm64/boot/dts/qcom/sc7280-idp2.dts
new file mode 100644
index 000000000000..1fc2addc8ab6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp2.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * sc7280 IDP2 board device tree source
+ *
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include "sc7280-idp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. sc7280 IDP SKU2 platform";
+ compatible = "qcom,sc7280-idp2", "google,piglin", "qcom,sc7280";
+
+ aliases {
+ serial0 = &uart5;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index 188c5768a55a..53a21d086178 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/clock/qcom,gcc-sc7280.h>
#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interconnect/qcom,sc7280.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
#include <dt-bindings/power/qcom-aoss-qmp.h>
@@ -24,6 +25,11 @@
chosen { };
+ aliases {
+ mmc1 = &sdhc_1;
+ mmc2 = &sdhc_2;
+ };
+
clocks {
xo_board: xo-board {
compatible = "fixed-clock";
@@ -63,6 +69,11 @@
no-map;
reg = <0x0 0x80b00000 0x0 0x100000>;
};
+
+ ipa_fw_mem: memory@8b700000 {
+ reg = <0 0x8b700000 0 0x10000>;
+ no-map;
+ };
};
cpus {
@@ -436,6 +447,73 @@
#mbox-cells = <2>;
};
+ qfprom: efuse@784000 {
+ compatible = "qcom,sc7280-qfprom", "qcom,qfprom";
+ reg = <0 0x00784000 0 0xa20>,
+ <0 0x00780000 0 0xa20>,
+ <0 0x00782000 0 0x120>,
+ <0 0x00786000 0 0x1fff>;
+ clocks = <&gcc GCC_SEC_CTRL_CLK_SRC>;
+ clock-names = "core";
+ power-domains = <&rpmhpd SC7280_MX>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ sdhc_1: sdhci@7c4000 {
+ compatible = "qcom,sc7280-sdhci", "qcom,sdhci-msm-v5";
+ status = "disabled";
+
+ reg = <0 0x007c4000 0 0x1000>,
+ <0 0x007c5000 0 0x1000>;
+ reg-names = "hc", "cqhci";
+
+ iommus = <&apps_smmu 0xc0 0x0>;
+ interrupts = <GIC_SPI 652 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 656 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC1_APPS_CLK>,
+ <&gcc GCC_SDCC1_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "core", "iface", "xo";
+ interconnects = <&aggre1_noc MASTER_SDCC_1 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_SDCC_1 0>;
+ interconnect-names = "sdhc-ddr","cpu-sdhc";
+ power-domains = <&rpmhpd SC7280_CX>;
+ operating-points-v2 = <&sdhc1_opp_table>;
+
+ bus-width = <8>;
+ supports-cqe;
+
+ qcom,dll-config = <0x0007642c>;
+ qcom,ddr-config = <0x80040868>;
+
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+
+ sdhc1_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <1800000 400000>;
+ opp-avg-kBps = <100000 0>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <5400000 1600000>;
+ opp-avg-kBps = <390000 0>;
+ };
+ };
+
+ };
+
qupv3_id_0: geniqup@9c0000 {
compatible = "qcom,geni-se-qup";
reg = <0 0x009c0000 0 0x2000>;
@@ -508,6 +586,43 @@
qcom,bcm-voters = <&apps_bcm_voter>;
};
+ ipa: ipa@1e40000 {
+ compatible = "qcom,sc7280-ipa";
+
+ iommus = <&apps_smmu 0x480 0x0>,
+ <&apps_smmu 0x482 0x0>;
+ reg = <0 0x1e40000 0 0x8000>,
+ <0 0x1e50000 0 0x4ad0>,
+ <0 0x1e04000 0 0x23000>;
+ reg-names = "ipa-reg",
+ "ipa-shared",
+ "gsi";
+
+ interrupts-extended = <&intc 0 654 IRQ_TYPE_EDGE_RISING>,
+ <&intc 0 432 IRQ_TYPE_LEVEL_HIGH>,
+ <&ipa_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&ipa_smp2p_in 1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ipa",
+ "gsi",
+ "ipa-clock-query",
+ "ipa-setup-ready";
+
+ clocks = <&rpmhcc RPMH_IPA_CLK>;
+ clock-names = "core";
+
+ interconnects = <&aggre2_noc MASTER_IPA 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_IPA_CFG 0>;
+ interconnect-names = "memory",
+ "config";
+
+ qcom,smem-states = <&ipa_smp2p_out 0>,
+ <&ipa_smp2p_out 1>;
+ qcom,smem-state-names = "ipa-clock-enabled-valid",
+ "ipa-clock-enabled";
+
+ status = "disabled";
+ };
+
tcsr_mutex: hwlock@1f40000 {
compatible = "qcom,tcsr-mutex", "syscon";
reg = <0 0x01f40000 0 0x40000>;
@@ -1035,6 +1150,174 @@
};
};
+ sdhc_2: sdhci@8804000 {
+ compatible = "qcom,sc7280-sdhci", "qcom,sdhci-msm-v5";
+ status = "disabled";
+
+ reg = <0 0x08804000 0 0x1000>;
+
+ iommus = <&apps_smmu 0x100 0x0>;
+ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC2_APPS_CLK>,
+ <&gcc GCC_SDCC2_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "core", "iface", "xo";
+ interconnects = <&aggre1_noc MASTER_SDCC_2 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_SDCC_2 0>;
+ interconnect-names = "sdhc-ddr","cpu-sdhc";
+ power-domains = <&rpmhpd SC7280_CX>;
+ operating-points-v2 = <&sdhc2_opp_table>;
+
+ bus-width = <4>;
+
+ qcom,dll-config = <0x0007642c>;
+
+ sdhc2_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <1800000 400000>;
+ opp-avg-kBps = <100000 0>;
+ };
+
+ opp-202000000 {
+ opp-hz = /bits/ 64 <202000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <5400000 1600000>;
+ opp-avg-kBps = <200000 0>;
+ };
+ };
+
+ };
+
+ usb_1_hsphy: phy@88e3000 {
+ compatible = "qcom,sc7280-usb-hs-phy",
+ "qcom,usb-snps-hs-7nm-phy";
+ reg = <0 0x088e3000 0 0x400>;
+ status = "disabled";
+ #phy-cells = <0>;
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "ref";
+
+ resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+ };
+
+ usb_2_hsphy: phy@88e4000 {
+ compatible = "qcom,sc7280-usb-hs-phy",
+ "qcom,usb-snps-hs-7nm-phy";
+ reg = <0 0x088e4000 0 0x400>;
+ status = "disabled";
+ #phy-cells = <0>;
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "ref";
+
+ resets = <&gcc GCC_QUSB2PHY_SEC_BCR>;
+ };
+
+ usb_1_qmpphy: phy-wrapper@88e9000 {
+ compatible = "qcom,sc7280-qmp-usb3-dp-phy",
+ "qcom,sm8250-qmp-usb3-dp-phy";
+ reg = <0 0x088e9000 0 0x200>,
+ <0 0x088e8000 0 0x40>,
+ <0 0x088ea000 0 0x200>;
+ status = "disabled";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
+ clock-names = "aux", "ref_clk_src", "com_aux";
+
+ resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>,
+ <&gcc GCC_USB3_PHY_PRIM_BCR>;
+ reset-names = "phy", "common";
+
+ usb_1_ssphy: usb3-phy@88e9200 {
+ reg = <0 0x088e9200 0 0x200>,
+ <0 0x088e9400 0 0x200>,
+ <0 0x088e9c00 0 0x400>,
+ <0 0x088e9600 0 0x200>,
+ <0 0x088e9800 0 0x200>,
+ <0 0x088e9a00 0 0x100>;
+ #clock-cells = <0>;
+ #phy-cells = <0>;
+ clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+ clock-names = "pipe0";
+ clock-output-names = "usb3_phy_pipe_clk_src";
+ };
+
+ dp_phy: dp-phy@88ea200 {
+ reg = <0 0x088ea200 0 0x200>,
+ <0 0x088ea400 0 0x200>,
+ <0 0x088eac00 0 0x400>,
+ <0 0x088ea600 0 0x200>,
+ <0 0x088ea800 0 0x200>,
+ <0 0x088eaa00 0 0x100>;
+ #phy-cells = <0>;
+ #clock-cells = <1>;
+ clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+ clock-names = "pipe0";
+ clock-output-names = "usb3_phy_pipe_clk_src";
+ };
+ };
+
+ usb_2: usb@8cf8800 {
+ compatible = "qcom,sc7280-dwc3", "qcom,dwc3";
+ reg = <0 0x08cf8800 0 0x400>;
+ status = "disabled";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ dma-ranges;
+
+ clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>,
+ <&gcc GCC_USB30_SEC_MASTER_CLK>,
+ <&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>,
+ <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_SEC_SLEEP_CLK>;
+ clock-names = "cfg_noc", "core", "iface","mock_utmi",
+ "sleep";
+
+ assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_SEC_MASTER_CLK>;
+ assigned-clock-rates = <19200000>, <200000000>;
+
+ interrupts-extended = <&intc GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 13 IRQ_TYPE_EDGE_RISING>,
+ <&pdc 12 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "hs_phy_irq",
+ "dm_hs_phy_irq", "dp_hs_phy_irq";
+
+ power-domains = <&gcc GCC_USB30_SEC_GDSC>;
+
+ resets = <&gcc GCC_USB30_SEC_BCR>;
+
+ interconnects = <&aggre1_noc MASTER_USB2 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_USB2 0>;
+ interconnect-names = "usb-ddr", "apps-usb";
+
+ usb_2_dwc3: usb@8c00000 {
+ compatible = "snps,dwc3";
+ reg = <0 0x08c00000 0 0xe000>;
+ interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>;
+ iommus = <&apps_smmu 0xa0 0x0>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_enblslpm_quirk;
+ phys = <&usb_2_hsphy>;
+ phy-names = "usb2-phy";
+ maximum-speed = "high-speed";
+ };
+ };
+
dc_noc: interconnect@90e0000 {
reg = <0 0x090e0000 0 0x5080>;
compatible = "qcom,sc7280-dc-noc";
@@ -1063,6 +1346,55 @@
qcom,bcm-voters = <&apps_bcm_voter>;
};
+ usb_1: usb@a6f8800 {
+ compatible = "qcom,sc7280-dwc3", "qcom,dwc3";
+ reg = <0 0x0a6f8800 0 0x400>;
+ status = "disabled";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ dma-ranges;
+
+ clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>,
+ <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_PRIM_SLEEP_CLK>;
+ clock-names = "cfg_noc", "core", "iface", "mock_utmi",
+ "sleep";
+
+ assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+ assigned-clock-rates = <19200000>, <200000000>;
+
+ interrupts-extended = <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 14 IRQ_TYPE_EDGE_BOTH>,
+ <&pdc 15 IRQ_TYPE_EDGE_BOTH>,
+ <&pdc 17 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hs_phy_irq", "dp_hs_phy_irq",
+ "dm_hs_phy_irq", "ss_phy_irq";
+
+ power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
+
+ resets = <&gcc GCC_USB30_PRIM_BCR>;
+
+ interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_USB3_0 0>;
+ interconnect-names = "usb-ddr", "apps-usb";
+
+ usb_1_dwc3: usb@a600000 {
+ compatible = "snps,dwc3";
+ reg = <0 0x0a600000 0 0xe000>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+ iommus = <&apps_smmu 0xe0 0x0>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_enblslpm_quirk;
+ phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
+ phy-names = "usb2-phy", "usb3-phy";
+ maximum-speed = "super-speed";
+ };
+ };
+
videocc: clock-controller@aaf0000 {
compatible = "qcom,sc7280-videocc";
reg = <0 0xaaf0000 0 0x10000>;
@@ -1185,6 +1517,87 @@
pins = "gpio46", "gpio47";
function = "qup13";
};
+
+ sdc1_on: sdc1-on {
+ clk {
+ pins = "sdc1_clk";
+ };
+
+ cmd {
+ pins = "sdc1_cmd";
+ };
+
+ data {
+ pins = "sdc1_data";
+ };
+
+ rclk {
+ pins = "sdc1_rclk";
+ };
+ };
+
+ sdc1_off: sdc1-off {
+ clk {
+ pins = "sdc1_clk";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+
+ cmd {
+ pins = "sdc1_cmd";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+
+ data {
+ pins = "sdc1_data";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+
+ rclk {
+ pins = "sdc1_rclk";
+ bias-bus-hold;
+ };
+ };
+
+ sdc2_on: sdc2-on {
+ clk {
+ pins = "sdc2_clk";
+ };
+
+ cmd {
+ pins = "sdc2_cmd";
+ };
+
+ data {
+ pins = "sdc2_data";
+ };
+
+ sd-cd {
+ pins = "gpio91";
+ };
+ };
+
+ sdc2_off: sdc2-off {
+ clk {
+ pins = "sdc2_clk";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+
+ cmd {
+ pins ="sdc2_cmd";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+
+ data {
+ pins ="sdc2_data";
+ drive-strength = <2>;
+ bias-bus-hold;
+ };
+ };
};
apps_smmu: iommu@15000000 {
@@ -1437,9 +1850,9 @@
cpufreq_hw: cpufreq@18591000 {
compatible = "qcom,cpufreq-epss";
- reg = <0 0x18591000 0 0x1000>,
- <0 0x18592000 0 0x1000>,
- <0 0x18593000 0 0x1000>;
+ reg = <0 0x18591100 0 0x900>,
+ <0 0x18592100 0 0x900>,
+ <0 0x18593100 0 0x900>;
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_GPLL0>;
clock-names = "xo", "alternate";
#freq-domain-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges-kirin.dts b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges-kirin.dts
index 46a7f2b26e6b..a4e1fb8ca52d 100644
--- a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges-kirin.dts
+++ b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges-kirin.dts
@@ -5,9 +5,21 @@
/dts-v1/;
-#include "sdm630-sony-xperia-ganges.dtsi"
+#include "sdm630.dtsi"
+#include "sdm630-sony-xperia-nile.dtsi"
/ {
model = "Sony Xperia 10";
compatible = "sony,kirin-row", "qcom,sdm630";
+
+ chosen {
+ framebuffer@9d400000 {
+ reg = <0 0x9d400000 0 (2520 * 1080 * 4)>;
+ height = <2520>;
+ };
+ };
};
+
+/* Ganges devices feature a Novatek touchscreen instead. */
+/delete-node/ &touchscreen;
+/delete-node/ &vreg_l18a_1v8;
diff --git a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges.dtsi b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges.dtsi
deleted file mode 100644
index cf2e8b5d60e8..000000000000
--- a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-ganges.dtsi
+++ /dev/null
@@ -1,40 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause
-/*
- * Copyright (c) 2020, Martin Botka
- */
-
-/dts-v1/;
-
-/* Ganges is very similar to Nile, but
- * there are some differences that will need
- * to be addresed when more peripherals are
- * enabled upstream. Hence the separate DTSI.
- */
-#include "sdm630-sony-xperia-nile.dtsi"
-
-/ {
- chosen {
- framebuffer@9d400000 {
- reg = <0 0x9d400000 0 (2520 * 1080 * 4)>;
- height = <2520>;
- };
- };
-
- /* Yes, this is intentional.
- * Ganges devices only use gpio-keys for
- * Volume Down, but currently there's an
- * issue with it that has to be resolved.
- * Until then, let's not make the kernel panic
- */
- /delete-node/ gpio-keys;
-
- soc {
-
- i2c@c175000 {
- status = "okay";
-
- /* Novatek touchscreen */
- };
- };
-
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-discovery.dts b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-discovery.dts
index 8fca0b69fa01..c574e430ba67 100644
--- a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-discovery.dts
+++ b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-discovery.dts
@@ -5,6 +5,7 @@
/dts-v1/;
+#include "sdm630.dtsi"
#include "sdm630-sony-xperia-nile.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-pioneer.dts b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-pioneer.dts
index 90dcd4ebaaed..a93ff3ab1b6d 100644
--- a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-pioneer.dts
+++ b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-pioneer.dts
@@ -5,6 +5,7 @@
/dts-v1/;
+#include "sdm630.dtsi"
#include "sdm630-sony-xperia-nile.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-voyager.dts b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-voyager.dts
index fae5f1bb6834..59a679c205e0 100644
--- a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-voyager.dts
+++ b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile-voyager.dts
@@ -5,6 +5,7 @@
/dts-v1/;
+#include "sdm630.dtsi"
#include "sdm630-sony-xperia-nile.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi
index 9ba359c848d0..849900e8b80e 100644
--- a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi
@@ -1,11 +1,10 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
- * Copyright (c) 2020, Konrad Dybcio
+ * Copyright (c) 2020, Konrad Dybcio <konrad.dybcio@somainline.org>
+ * Copyright (c) 2020, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
*/
-/dts-v1/;
-
-#include "sdm630.dtsi"
#include "pm660.dtsi"
#include "pm660l.dtsi"
#include <dt-bindings/gpio/gpio.h>
@@ -39,13 +38,61 @@
};
};
+ board_vbat: vbat-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "VBAT";
+
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ cam_vdig_imx300_219_vreg: cam_vdig_imx300_219_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_vdig_imx300_219_vreg";
+ startup-delay-us = <0>;
+ enable-active-high;
+ gpio = <&tlmm 52 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam_vdig_default>;
+ };
+
+ cam_vana_front_vreg: cam_vana_front_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_vana_front_vreg";
+ startup-delay-us = <0>;
+ enable-active-high;
+ gpio = <&tlmm 51 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&imx219_vana_default>;
+ };
+
+ cam_vana_rear_vreg: cam_vana_rear_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_vana_rear_vreg";
+ startup-delay-us = <0>;
+ enable-active-high;
+ gpio = <&tlmm 50 GPIO_ACTIVE_HIGH>;
+ regulator-always-on;
+ pinctrl-names = "default";
+ pinctrl-0 = <&imx300_vana_default>;
+ };
+
gpio_keys {
status = "okay";
compatible = "gpio-keys";
input-name = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
- autorepeat;
camera_focus {
label = "Camera Focus";
@@ -100,37 +147,471 @@
};
};
- soc {
- sdhci@c0c4000 {
- status = "okay";
+ /*
+ * Until we hook up type-c detection, we
+ * have to stick with this. But it works.
+ */
+ extcon_usb: extcon-usb {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpio = <&tlmm 58 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&adsp_pil {
+ firmware-name = "adsp.mdt";
+};
+
+&blsp_i2c1 {
+ status = "okay";
+
+ touchscreen: synaptics-rmi4-i2c@70 {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x70>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts-extended = <&tlmm 45 0x2008>;
- mmc-ddr-1_8v;
- /* SoMC Nile platform's eMMC doesn't support HS200 mode */
- mmc-hs400-1_8v;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ts_int_active &ts_lcd_id_active>;
+
+ syna,reset-delay-ms = <200>;
+ syna,startup-delay-ms = <220>;
+
+ rmi4-f01@1 {
+ reg = <0x01>;
+ syna,nosleep-mode = <1>;
};
- i2c@c175000 {
- status = "okay";
+ rmi4-f11@11 {
+ reg = <0x11>;
+ syna,sensor-type = <1>;
+ };
+ };
+};
+
+&blsp_i2c2 {
+ status = "okay";
+
+ /* SMB1351 charger */
+};
+
+/* I2C3, 4, 5, 7 and 8 are disabled on this board. */
+
+&blsp_i2c6 {
+ status = "okay";
+
+ /* NXP NFC */
+};
+
+&blsp1_uart2 {
+ status = "okay";
+
+ /* MSM serial console */
+};
+
+&blsp2_uart1 {
+ status = "okay";
- /* Synaptics touchscreen */
+ /* HCI Bluetooth */
+};
+
+&pon {
+ volup {
+ compatible = "qcom,pm8941-resin";
+ interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+};
+
+&qusb2phy {
+ status = "okay";
+
+ vdd-supply = <&vreg_l1b_0p925>;
+ vdda-pll-supply = <&vreg_l10a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l7b_3p125>;
+};
+
+&rpm_requests {
+ pm660l-regulators {
+ compatible = "qcom,rpm-pm660l-regulators";
+
+ vdd_s1-supply = <&vph_pwr>;
+ vdd_s2-supply = <&vph_pwr>;
+ vdd_s3_s4-supply = <&vph_pwr>;
+ vdd_s5-supply = <&vph_pwr>;
+ vdd_s6-supply = <&vph_pwr>;
+
+ vdd_l1_l9_l10-supply = <&vreg_s2b_1p05>;
+ vdd_l2-supply = <&vreg_bob>;
+ vdd_l3_l5_l7_l8-supply = <&vreg_bob>;
+ vdd_l4_l6-supply = <&vreg_bob>;
+ vdd_bob-supply = <&vph_pwr>;
+
+ vreg_s1b_1p125: s1 {
+ regulator-min-microvolt = <1125000>;
+ regulator-max-microvolt = <1125000>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-ramp-delay = <0>;
};
- i2c@c176000 {
- status = "okay";
+ vreg_s2b_1p05: s2 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-ramp-delay = <0>;
+ };
+
+ /*
+ * At least on Nile's configuration, S3B/S4B (VDD_CX) and
+ * S5B (VDD_MX) are managed only through RPM Power Domains.
+ * Trying to set a voltage on the main supply will create
+ * havoc and freeze the SoC.
+ * In any case, reference voltages for these regulators are:
+ * S3B/S4B: 0.870V
+ * S5B: 0.915V
+ */
- /* SMB1351 charger */
+ /* LDOs */
+ vreg_l1b_0p925: l1 {
+ regulator-min-microvolt = <920000>;
+ regulator-max-microvolt = <928000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-allow-set-load;
};
- serial@c1af000 {
- status = "okay";
+ vreg_l2b_2p95: l2 {
+ /*
+ * This regulator supports 1.648 - 3.104V on this board
+ * but we set a max voltage of anything less than 2.7V
+ * to satisfy a condition in sdhci.c that will disable
+ * 3.3V SDHCI signaling, which happens to be not really
+ * supported on the Xperia Nile/Ganges platform.
+ */
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <2696000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-allow-set-load;
};
- /* I2C3, 4, 5, 7 and 8 are disabled on this board. */
+ vreg_l3b_3p0: l3 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-min-microamp = <200>;
+ regulator-max-microamp = <600000>;
+ regulator-system-load = <100000>;
+ regulator-allow-set-load;
+ };
- i2c@c1b6000 {
- status = "okay";
+ vreg_l4b_29p5: l4 {
+ regulator-min-microvolt = <2944000>;
+ regulator-max-microvolt = <2952000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+
+ regulator-min-microamp = <200>;
+ regulator-max-microamp = <600000>;
+ regulator-system-load = <570000>;
+ regulator-allow-set-load;
+ };
+
+ /*
+ * Downstream specifies a range of 1721-3600mV,
+ * but the only assigned consumers are SDHCI2 VMMC
+ * and Coresight QPDI that both request pinned 2.95V.
+ * Tighten the range to 1.8-3.328 (closest to 3.3) to
+ * make the mmc driver happy.
+ */
+ vreg_l5b_29p5: l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3328000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-allow-set-load;
+ regulator-system-load = <800000>;
+ };
+
+ vreg_l6b_3p3: l6 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l7b_3p125: l7 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <3128000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l8b_3p3: l8 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ /* L9B (870mV) is currently unused */
+ /* L10B (915mV) is currently unused */
+
+ vreg_bob: bob {
+ regulator-min-microvolt = <3304000>;
+ regulator-max-microvolt = <3624000>;
+ regulator-enable-ramp-delay = <500>;
+ regulator-ramp-delay = <0>;
+ };
+ };
+
+ pm660-regulators {
+ compatible = "qcom,rpm-pm660-regulators";
+
+ vdd_s1-supply = <&vph_pwr>;
+ vdd_s2-supply = <&vph_pwr>;
+ vdd_s3-supply = <&vph_pwr>;
+ vdd_s4-supply = <&vph_pwr>;
+ vdd_s5-supply = <&vph_pwr>;
+ vdd_s6-supply = <&vph_pwr>;
+
+ vdd_l1_l6_l7-supply = <&vreg_s5a_1p35>;
+ vdd_l2_l3-supply = <&vreg_s2b_1p05>;
+ vdd_l5-supply = <&vreg_s2b_1p05>;
+ vdd_l8_l9_l10_l11_l12_l13_l14-supply = <&vreg_s4a_2p04>;
+ vdd_l15_l16_l17_l18_l19-supply = <&vreg_bob>;
+
+ /*
+ * S1A (FTAPC0), S2A (FTAPC1), S3A (HFAPC1) are managed
+ * by the Core Power Reduction hardened (CPRh) and the
+ * Operating State Manager (OSM) HW automatically.
+ */
+
+ vreg_s4a_2p04: s4 {
+ regulator-min-microvolt = <2040000>;
+ regulator-max-microvolt = <2040000>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-ramp-delay = <0>;
+ regulator-always-on;
+ };
+
+ vreg_s5a_1p35: s5 {
+ regulator-min-microvolt = <1224000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-enable-ramp-delay = <200>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_s6a_0p87: s6 {
+ regulator-min-microvolt = <504000>;
+ regulator-max-microvolt = <992000>;
+ regulator-enable-ramp-delay = <150>;
+ regulator-ramp-delay = <0>;
+ };
+
+ /* LDOs */
+ vreg_l1a_1p225: l1 {
+ regulator-min-microvolt = <1226000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l2a_1p0: l2 {
+ regulator-min-microvolt = <944000>;
+ regulator-max-microvolt = <1008000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l3a_1p0: l3 {
+ regulator-min-microvolt = <944000>;
+ regulator-max-microvolt = <1008000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l5a_0p848: l5 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <952000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l6a_1p3: l6 {
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1368000>;
+ regulator-allow-set-load;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l7a_1p2: l7 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l8a_1p8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-system-load = <325000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l9a_1p8: l9 {
+ regulator-min-microvolt = <1804000>;
+ regulator-max-microvolt = <1896000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l10a_1p8: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1944000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l11a_1p8: l11 {
+ regulator-min-microvolt = <1784000>;
+ regulator-max-microvolt = <1944000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l12a_1p8: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1944000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
- /* NXP NFC */
+ /* This gives power to the LPDDR4: never turn it off! */
+ vreg_l13a_1p8: l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1944000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-boot-on;
+ regulator-always-on;
};
+
+ vreg_l14a_1p8: l14 {
+ regulator-min-microvolt = <1710000>;
+ regulator-max-microvolt = <1904000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l15a_1p8: l15 {
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <2952000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ /* L16A (2.70V) is unused */
+
+ vreg_l17a_1p8: l17 {
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <2952000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ };
+
+ vreg_l18a_1v8: l18 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <10>;
+ regulator-min-microamp = <200>;
+ regulator-max-microamp = <50000>;
+ regulator-system-load = <10000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l19a_3p3: l19 {
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-enable-ramp-delay = <250>;
+ regulator-ramp-delay = <0>;
+ regulator-allow-set-load;
+ };
+ };
+};
+
+&sdhc_1 {
+ status = "okay";
+ supports-cqe;
+
+ /* SoMC Nile platform's eMMC doesn't support HS200 mode */
+ mmc-ddr-1_8v;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+
+ vmmc-supply = <&vreg_l4b_29p5>;
+ vqmmc-supply = <&vreg_l8a_1p8>;
+};
+
+&sdhc_2 {
+ status = "okay";
+
+ vmmc-supply = <&vreg_l5b_29p5>;
+ vqmmc-supply = <&vreg_l2b_2p95>;
+};
+
+&tlmm {
+ gpio-reserved-ranges = <8 4>;
+
+ ts_int_active: ts-int-active {
+ pins = "gpio45";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ ts_lcd_id_active: ts-lcd-id-active {
+ pins = "gpio56";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ imx300_vana_default: imx300-vana-default {
+ pins = "gpio50";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
};
+
+ imx219_vana_default: imx219-vana-default {
+ pins = "gpio51";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cam_vdig_default: cam-vdig-default {
+ pins = "gpio52";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
+ };
+};
+
+&usb3 {
+ status = "okay";
+};
+
+&usb3_dwc3 {
+ dr_mode = "peripheral";
+ extcon = <&extcon_usb>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi
index f91a928466c3..9153e6616ba4 100644
--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
@@ -1,12 +1,17 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
- * Copyright (c) 2020, Konrad Dybcio
+ * Copyright (c) 2020, Konrad Dybcio <konradybcio@gmail.com>
+ * Copyright (c) 2020, AngeloGioacchino Del Regno <kholk11@gmail.com>
*/
#include <dt-bindings/clock/qcom,gcc-sdm660.h>
+#include <dt-bindings/clock/qcom,gpucc-sdm660.h>
+#include <dt-bindings/clock/qcom,mmcc-sdm660.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/qcom,apr.h>
/ {
interrupt-parent = <&intc>;
@@ -17,14 +22,14 @@
chosen { };
clocks {
- xo_board: xo_board {
+ xo_board: xo-board {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <19200000>;
clock-output-names = "xo_board";
};
- sleep_clk: sleep_clk {
+ sleep_clk: sleep-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32764>;
@@ -311,10 +316,10 @@
};
};
- memory {
+ memory@80000000 {
device_type = "memory";
/* We expect the bootloader to fill in the reg */
- reg = <0 0 0 0>;
+ reg = <0x0 0x80000000 0x0 0x0>;
};
pmu {
@@ -343,10 +348,19 @@
};
qhee_code: qhee-code@85800000 {
- reg = <0x0 0x85800000 0x0 0x3700000>;
+ reg = <0x0 0x85800000 0x0 0x600000>;
no-map;
};
+ rmtfs_mem: memory@85e00000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0 0x85e00000 0x0 0x200000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <15>;
+ };
+
smem_region: smem-mem@86000000 {
reg = <0 0x86000000 0 0x200000>;
no-map;
@@ -357,58 +371,44 @@
no-map;
};
- modem_fw_mem: modem-fw-region@8ac00000 {
+ mpss_region: mpss@8ac00000 {
reg = <0x0 0x8ac00000 0x0 0x7e00000>;
no-map;
};
- adsp_fw_mem: adsp-fw-region@92a00000 {
+ adsp_region: adsp@92a00000 {
reg = <0x0 0x92a00000 0x0 0x1e00000>;
no-map;
};
- pil_mba_mem: pil-mba-region@94800000 {
+ mba_region: mba@94800000 {
reg = <0x0 0x94800000 0x0 0x200000>;
no-map;
};
- buffer_mem: buffer-region@94a00000 {
+ buffer_mem: tzbuffer@94a00000 {
reg = <0x0 0x94a00000 0x0 0x100000>;
no-map;
};
- venus_fw_mem: venus-fw-region@9f800000 {
+ venus_region: venus@9f800000 {
reg = <0x0 0x9f800000 0x0 0x800000>;
no-map;
};
- secure_region2: secure-region2@f7c00000 {
- reg = <0x0 0xf7c00000 0x0 0x5c00000>;
- no-map;
- };
-
adsp_mem: adsp-region@f6000000 {
reg = <0x0 0xf6000000 0x0 0x800000>;
no-map;
};
- qseecom_ta_mem: qseecom-ta-region@fec00000 {
- reg = <0x0 0xfec00000 0x0 0x1000000>;
- no-map;
- };
-
qseecom_mem: qseecom-region@f6800000 {
reg = <0x0 0xf6800000 0x0 0x1400000>;
no-map;
};
- secure_display_memory: secure-region@f5c00000 {
- reg = <0x0 0xf5c00000 0x0 0x5c00000>;
- no-map;
- };
-
- cont_splash_mem: cont-splash-region@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x23ff000>;
+ zap_shader_region: gpu@fed00000 {
+ compatible = "shared-dma-pool";
+ reg = <0x0 0xfed00000 0x0 0xa00000>;
no-map;
};
};
@@ -428,6 +428,52 @@
compatible = "qcom,rpmcc-sdm660", "qcom,rpmcc";
#clock-cells = <1>;
};
+
+ rpmpd: power-controller {
+ compatible = "qcom,sdm660-rpmpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmpd_opp_table>;
+
+ rpmpd_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ rpmpd_opp_ret: opp1 {
+ opp-level = <RPM_SMD_LEVEL_RETENTION>;
+ };
+
+ rpmpd_opp_ret_plus: opp2 {
+ opp-level = <RPM_SMD_LEVEL_RETENTION_PLUS>;
+ };
+
+ rpmpd_opp_min_svs: opp3 {
+ opp-level = <RPM_SMD_LEVEL_MIN_SVS>;
+ };
+
+ rpmpd_opp_low_svs: opp4 {
+ opp-level = <RPM_SMD_LEVEL_LOW_SVS>;
+ };
+
+ rpmpd_opp_svs: opp5 {
+ opp-level = <RPM_SMD_LEVEL_SVS>;
+ };
+
+ rpmpd_opp_svs_plus: opp6 {
+ opp-level = <RPM_SMD_LEVEL_SVS_PLUS>;
+ };
+
+ rpmpd_opp_nom: opp7 {
+ opp-level = <RPM_SMD_LEVEL_NOM>;
+ };
+
+ rpmpd_opp_nom_plus: opp8 {
+ opp-level = <RPM_SMD_LEVEL_NOM_PLUS>;
+ };
+
+ rpmpd_opp_turbo: opp9 {
+ opp-level = <RPM_SMD_LEVEL_TURBO>;
+ };
+ };
+ };
};
};
@@ -437,6 +483,46 @@
hwlocks = <&tcsr_mutex 3>;
};
+ smp2p-adsp {
+ compatible = "qcom,smp2p";
+ qcom,smem = <443>, <429>;
+ interrupts = <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&apcs_glb 10>;
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <2>;
+
+ adsp_smp2p_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ adsp_smp2p_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smp2p-mpss {
+ compatible = "qcom,smp2p";
+ qcom,smem = <435>, <428>;
+ interrupts = <GIC_SPI 451 IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&apcs_glb 14>;
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <1>;
+
+ modem_smp2p_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ modem_smp2p_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -465,6 +551,16 @@
reg = <0x00780000 0x621c>;
#address-cells = <1>;
#size-cells = <1>;
+
+ qusb2_hstx_trim: hstx-trim@240 {
+ reg = <0x240 0x1>;
+ bits = <25 3>;
+ };
+
+ gpu_speed_bin: gpu-speed-bin@41a0 {
+ reg = <0x41a0 0x1>;
+ bits = <21 7>;
+ };
};
rng: rng@793000 {
@@ -474,17 +570,49 @@
clock-names = "core";
};
+ bimc: interconnect@1008000 {
+ compatible = "qcom,sdm660-bimc";
+ reg = <0x01008000 0x78000>;
+ #interconnect-cells = <1>;
+ clock-names = "bus", "bus_a";
+ clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
+ <&rpmcc RPM_SMD_BIMC_A_CLK>;
+ };
+
restart@10ac000 {
compatible = "qcom,pshold";
reg = <0x010ac000 0x4>;
};
+ cnoc: interconnect@1500000 {
+ compatible = "qcom,sdm660-cnoc";
+ reg = <0x01500000 0x10000>;
+ #interconnect-cells = <1>;
+ clock-names = "bus", "bus_a";
+ clocks = <&rpmcc RPM_SMD_CNOC_CLK>,
+ <&rpmcc RPM_SMD_CNOC_A_CLK>;
+ };
+
+ snoc: interconnect@1626000 {
+ compatible = "qcom,sdm660-snoc";
+ reg = <0x01626000 0x7090>;
+ #interconnect-cells = <1>;
+ clock-names = "bus", "bus_a";
+ clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
+ <&rpmcc RPM_SMD_SNOC_A_CLK>;
+ };
+
anoc2_smmu: iommu@16c0000 {
compatible = "qcom,sdm630-smmu-v2", "qcom,smmu-v2";
reg = <0x016c0000 0x40000>;
- #iommu-cells = <1>;
+ assigned-clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>;
+ assigned-clock-rates = <1000>;
+ clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>;
+ clock-names = "bus";
#global-interrupts = <2>;
+ #iommu-cells = <1>;
+
interrupts =
<GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
@@ -522,19 +650,53 @@
status = "disabled";
};
+ a2noc: interconnect@1704000 {
+ compatible = "qcom,sdm660-a2noc";
+ reg = <0x01704000 0xc100>;
+ #interconnect-cells = <1>;
+ clock-names = "bus", "bus_a";
+ clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>,
+ <&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>;
+ };
+
+ mnoc: interconnect@1745000 {
+ compatible = "qcom,sdm660-mnoc";
+ reg = <0x01745000 0xA010>;
+ #interconnect-cells = <1>;
+ clock-names = "bus", "bus_a", "iface";
+ clocks = <&rpmcc RPM_SMD_MMSSNOC_AXI_CLK>,
+ <&rpmcc RPM_SMD_MMSSNOC_AXI_CLK_A>,
+ <&mmcc AHB_CLK_SRC>;
+ };
+
+ tsens: thermal-sensor@10ae000 {
+ compatible = "qcom,sdm630-tsens", "qcom,tsens-v2";
+ reg = <0x010ae000 0x1000>, /* TM */
+ <0x010ad000 0x1000>; /* SROT */
+ #qcom,sensors = <12>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uplow", "critical";
+ #thermal-sensor-cells = <1>;
+ };
+
tcsr_mutex_regs: syscon@1f40000 {
compatible = "syscon";
- reg = <0x01f40000 0x20000>;
+ reg = <0x01f40000 0x40000>;
};
- tlmm: pinctrl@3000000 {
+ tlmm: pinctrl@3100000 {
compatible = "qcom,sdm630-pinctrl";
- reg = <0x03000000 0xc00000>;
+ reg = <0x03100000 0x400000>,
+ <0x03500000 0x400000>,
+ <0x03900000 0x400000>;
+ reg-names = "south", "center", "north";
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
- #gpio-cells = <0x2>;
+ gpio-ranges = <&tlmm 0 0 114>;
+ #gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <0x2>;
+ #interrupt-cells = <2>;
blsp1_uart1_default: blsp1-uart1-default {
pins = "gpio0", "gpio1", "gpio2", "gpio3";
@@ -554,191 +716,392 @@
bias-disable;
};
- blsp2_uart1_tx_active: blsp2-uart1-tx-active {
- pins = "gpio16";
- drive-strength = <2>;
- bias-disable;
- };
-
- blsp2_uart1_tx_sleep: blsp2-uart1-tx-sleep {
- pins = "gpio16";
- drive-strength = <2>;
- bias-pull-up;
- };
+ blsp2_uart1_default: blsp2-uart1-active {
+ tx-rts {
+ pins = "gpio16", "gpio19";
+ function = "blsp_uart5";
+ drive-strength = <2>;
+ bias-disable;
+ };
- blsp2_uart1_rxcts_active: blsp2-uart1-rxcts-active {
- pins = "gpio17", "gpio18";
- drive-strength = <2>;
- bias-disable;
- };
+ rx {
+ /*
+ * Avoid garbage data while BT module
+ * is powered off or not driving signal
+ */
+ pins = "gpio17";
+ function = "blsp_uart5";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
- blsp2_uart1_rxcts_sleep: blsp2-uart1-rxcts-sleep {
- pins = "gpio17", "gpio18";
- drive-strength = <2>;
- bias-no-pull;
+ cts {
+ /* Match the pull of the BT module */
+ pins = "gpio18";
+ function = "blsp_uart5";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
};
- blsp2_uart1_rfr_active: blsp2-uart1-rfr-active {
- pins = "gpio19";
- drive-strength = <2>;
- bias-disable;
- };
+ blsp2_uart1_sleep: blsp2-uart1-sleep {
+ tx {
+ pins = "gpio16";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
- blsp2_uart1_rfr_sleep: blsp2-uart1-rfr-sleep {
- pins = "gpio19";
- drive-strength = <2>;
- bias-no-pull;
+ rx-cts-rts {
+ pins = "gpio17", "gpio18", "gpio19";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-no-pull;
+ };
};
i2c1_default: i2c1-default {
pins = "gpio2", "gpio3";
+ function = "blsp_i2c1";
drive-strength = <2>;
bias-disable;
};
i2c1_sleep: i2c1-sleep {
pins = "gpio2", "gpio3";
+ function = "blsp_i2c1";
drive-strength = <2>;
bias-pull-up;
};
i2c2_default: i2c2-default {
pins = "gpio6", "gpio7";
+ function = "blsp_i2c2";
drive-strength = <2>;
bias-disable;
};
i2c2_sleep: i2c2-sleep {
pins = "gpio6", "gpio7";
+ function = "blsp_i2c2";
drive-strength = <2>;
bias-pull-up;
};
i2c3_default: i2c3-default {
pins = "gpio10", "gpio11";
+ function = "blsp_i2c3";
drive-strength = <2>;
bias-disable;
};
i2c3_sleep: i2c3-sleep {
pins = "gpio10", "gpio11";
+ function = "blsp_i2c3";
drive-strength = <2>;
bias-pull-up;
};
i2c4_default: i2c4-default {
pins = "gpio14", "gpio15";
+ function = "blsp_i2c4";
drive-strength = <2>;
bias-disable;
};
i2c4_sleep: i2c4-sleep {
pins = "gpio14", "gpio15";
+ function = "blsp_i2c4";
drive-strength = <2>;
bias-pull-up;
};
i2c5_default: i2c5-default {
pins = "gpio18", "gpio19";
+ function = "blsp_i2c5";
drive-strength = <2>;
bias-disable;
};
i2c5_sleep: i2c5-sleep {
pins = "gpio18", "gpio19";
+ function = "blsp_i2c5";
drive-strength = <2>;
bias-pull-up;
};
i2c6_default: i2c6-default {
pins = "gpio22", "gpio23";
+ function = "blsp_i2c6";
drive-strength = <2>;
bias-disable;
};
i2c6_sleep: i2c6-sleep {
pins = "gpio22", "gpio23";
+ function = "blsp_i2c6";
drive-strength = <2>;
bias-pull-up;
};
i2c7_default: i2c7-default {
pins = "gpio26", "gpio27";
+ function = "blsp_i2c7";
drive-strength = <2>;
bias-disable;
};
i2c7_sleep: i2c7-sleep {
pins = "gpio26", "gpio27";
+ function = "blsp_i2c7";
drive-strength = <2>;
bias-pull-up;
};
i2c8_default: i2c8-default {
pins = "gpio30", "gpio31";
+ function = "blsp_i2c8";
drive-strength = <2>;
bias-disable;
};
i2c8_sleep: i2c8-sleep {
pins = "gpio30", "gpio31";
+ function = "blsp_i2c8";
drive-strength = <2>;
bias-pull-up;
};
- sdc1_clk_on: sdc1-clk-on {
- pins = "sdc1_clk";
- bias-disable;
- drive-strength = <16>;
- };
+ cci0_default: cci0_default {
+ pinmux {
+ pins = "gpio36","gpio37";
+ function = "cci_i2c";
+ };
- sdc1_clk_off: sdc1-clk-off {
- pins = "sdc1_clk";
- bias-disable;
- drive-strength = <2>;
+ pinconf {
+ pins = "gpio36","gpio37";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
};
- sdc1_cmd_on: sdc1-cmd-on {
- pins = "sdc1_cmd";
- bias-pull-up;
- drive-strength = <10>;
+ cci1_default: cci1_default {
+ pinmux {
+ pins = "gpio38","gpio39";
+ function = "cci_i2c";
+ };
+
+ pinconf {
+ pins = "gpio38","gpio39";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
};
- sdc1_cmd_off: sdc1-cmd-off {
- pins = "sdc1_cmd";
- bias-pull-up;
- drive-strength = <2>;
+ sdc1_state_on: sdc1-on {
+ clk {
+ pins = "sdc1_clk";
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ rclk {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
};
- sdc1_data_on: sdc1-data-on {
- pins = "sdc1_data";
- bias-pull-up;
- drive-strength = <8>;
+ sdc1_state_off: sdc1-off {
+ clk {
+ pins = "sdc1_clk";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cmd {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ data {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ rclk {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
};
- sdc1_data_off: sdc1-data-off {
- pins = "sdc1_data";
- bias-pull-up;
- drive-strength = <2>;
+ sdc2_state_on: sdc2-on {
+ clk {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ sd-cd {
+ pins = "gpio54";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
};
- sdc1_rclk_on: sdc1-rclk-on {
- pins = "sdc1_rclk";
- bias-pull-down;
+ sdc2_state_off: sdc2-off {
+ clk {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cmd {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ data {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ sd-cd {
+ pins = "gpio54";
+ bias-disable;
+ drive-strength = <2>;
+ };
};
+ };
+
+ adreno_gpu: gpu@5000000 {
+ compatible = "qcom,adreno-508.0", "qcom,adreno";
+ #stream-id-cells = <16>;
+
+ reg = <0x05000000 0x40000>;
+ reg-names = "kgsl_3d0_reg_memory";
- sdc1_rclk_off: sdc1-rclk-off {
- pins = "sdc1_rclk";
- bias-pull-down;
+ interrupts = <0 300 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_GPU_CFG_AHB_CLK>,
+ <&gpucc GPUCC_RBBMTIMER_CLK>,
+ <&gcc GCC_BIMC_GFX_CLK>,
+ <&gcc GCC_GPU_BIMC_GFX_CLK>,
+ <&gpucc GPUCC_RBCPR_CLK>,
+ <&gpucc GPUCC_GFX3D_CLK>;
+
+ clock-names = "iface",
+ "rbbmtimer",
+ "mem",
+ "mem_iface",
+ "rbcpr",
+ "core";
+
+ power-domains = <&rpmpd SDM660_VDDMX>;
+ iommus = <&kgsl_smmu 0>;
+
+ nvmem-cells = <&gpu_speed_bin>;
+ nvmem-cell-names = "speed_bin";
+
+ interconnects = <&gnoc 1 &bimc 5>;
+ interconnect-names = "gfx-mem";
+
+ operating-points-v2 = <&gpu_sdm630_opp_table>;
+
+ gpu_sdm630_opp_table: opp-table {
+ compatible = "operating-points-v2";
+ opp-775000000 {
+ opp-hz = /bits/ 64 <775000000>;
+ opp-level = <RPM_SMD_LEVEL_TURBO>;
+ opp-peak-kBps = <5412000>;
+ opp-supported-hw = <0xA2>;
+ };
+ opp-647000000 {
+ opp-hz = /bits/ 64 <647000000>;
+ opp-level = <RPM_SMD_LEVEL_NOM_PLUS>;
+ opp-peak-kBps = <4068000>;
+ opp-supported-hw = <0xFF>;
+ };
+ opp-588000000 {
+ opp-hz = /bits/ 64 <588000000>;
+ opp-level = <RPM_SMD_LEVEL_NOM>;
+ opp-peak-kBps = <3072000>;
+ opp-supported-hw = <0xFF>;
+ };
+ opp-465000000 {
+ opp-hz = /bits/ 64 <465000000>;
+ opp-level = <RPM_SMD_LEVEL_SVS_PLUS>;
+ opp-peak-kBps = <2724000>;
+ opp-supported-hw = <0xFF>;
+ };
+ opp-370000000 {
+ opp-hz = /bits/ 64 <370000000>;
+ opp-level = <RPM_SMD_LEVEL_SVS>;
+ opp-peak-kBps = <2188000>;
+ opp-supported-hw = <0xFF>;
+ };
+ opp-240000000 {
+ opp-hz = /bits/ 64 <240000000>;
+ opp-level = <RPM_SMD_LEVEL_LOW_SVS>;
+ opp-peak-kBps = <1648000>;
+ opp-supported-hw = <0xFF>;
+ };
+ opp-160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ opp-level = <RPM_SMD_LEVEL_MIN_SVS>;
+ opp-peak-kBps = <1200000>;
+ opp-supported-hw = <0xFF>;
+ };
};
};
kgsl_smmu: iommu@5040000 {
- compatible = "qcom,sdm630-smmu-v2", "qcom,smmu-v2";
+ compatible = "qcom,sdm630-smmu-v2",
+ "qcom,adreno-smmu", "qcom,smmu-v2";
reg = <0x05040000 0x10000>;
- #iommu-cells = <1>;
+ /*
+ * GX GDSC parent is CX. We need to bring up CX for SMMU
+ * but we need both up for Adreno. On the other hand, we
+ * need to manage the GX rpmpd domain in the adreno driver.
+ * Enable CX/GX GDSCs here so that we can manage just the GX
+ * RPM Power Domain in the Adreno driver.
+ */
+ power-domains = <&gpucc GPU_GX_GDSC>;
+ clocks = <&gcc GCC_GPU_CFG_AHB_CLK>,
+ <&gcc GCC_BIMC_GFX_CLK>,
+ <&gcc GCC_GPU_BIMC_GFX_CLK>;
+ clock-names = "iface", "mem", "mem_iface";
#global-interrupts = <2>;
+ #iommu-cells = <1>;
+
interrupts =
<GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
@@ -755,6 +1118,22 @@
status = "disabled";
};
+ gpucc: clock-controller@5065000 {
+ compatible = "qcom,gpucc-sdm630";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ reg = <0x05065000 0x9038>;
+
+ clocks = <&xo_board>,
+ <&gcc GCC_GPU_GPLL0_CLK>,
+ <&gcc GCC_GPU_GPLL0_DIV_CLK>;
+ clock-names = "xo",
+ "gcc_gpu_gpll0_clk",
+ "gcc_gpu_gpll0_div_clk";
+ status = "disabled";
+ };
+
lpass_smmu: iommu@5100000 {
compatible = "qcom,sdm630-smmu-v2", "qcom,smmu-v2";
reg = <0x05100000 0x40000>;
@@ -805,6 +1184,120 @@
cell-index = <0>;
};
+ usb3: usb@a8f8800 {
+ compatible = "qcom,sdm660-dwc3", "qcom,dwc3";
+ reg = <0x0a8f8800 0x400>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clocks = <&gcc GCC_CFG_NOC_USB3_AXI_CLK>,
+ <&gcc GCC_USB30_MASTER_CLK>,
+ <&gcc GCC_AGGRE2_USB3_AXI_CLK>,
+ <&rpmcc RPM_SMD_AGGR2_NOC_CLK>,
+ <&gcc GCC_USB30_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_SLEEP_CLK>;
+ clock-names = "cfg_noc", "core", "iface", "bus",
+ "mock_utmi", "sleep";
+
+ assigned-clocks = <&gcc GCC_USB30_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_MASTER_CLK>,
+ <&rpmcc RPM_SMD_AGGR2_NOC_CLK>;
+ assigned-clock-rates = <19200000>, <120000000>,
+ <19200000>;
+
+ interrupts = <GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hs_phy_irq", "ss_phy_irq";
+
+ power-domains = <&gcc USB_30_GDSC>;
+ qcom,select-utmi-as-pipe-clk;
+
+ resets = <&gcc GCC_USB_30_BCR>;
+
+ usb3_dwc3: usb@a800000 {
+ compatible = "snps,dwc3";
+ reg = <0x0a800000 0xc8d0>;
+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_enblslpm_quirk;
+
+ /*
+ * SDM630 technically supports USB3 but I
+ * haven't seen any devices making use of it.
+ */
+ maximum-speed = "high-speed";
+ phys = <&qusb2phy>;
+ phy-names = "usb2-phy";
+ snps,hird-threshold = /bits/ 8 <0>;
+ };
+ };
+
+ qusb2phy: phy@c012000 {
+ compatible = "qcom,sdm660-qusb2-phy";
+ reg = <0x0c012000 0x180>;
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+ <&gcc GCC_RX1_USB2_CLKREF_CLK>;
+ clock-names = "cfg_ahb", "ref";
+
+ resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+ nvmem-cells = <&qusb2_hstx_trim>;
+ status = "disabled";
+ };
+
+ sdhc_2: sdhci@c084000 {
+ compatible = "qcom,sdm630-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0x0c084000 0x1000>;
+ reg-names = "hc";
+
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ bus-width = <4>;
+ clocks = <&gcc GCC_SDCC2_APPS_CLK>,
+ <&gcc GCC_SDCC2_AHB_CLK>,
+ <&xo_board>;
+ clock-names = "core", "iface", "xo";
+
+ interconnects = <&a2noc 3 &a2noc 10>,
+ <&gnoc 0 &cnoc 28>;
+ operating-points-v2 = <&sdhc2_opp_table>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_state_on>;
+ pinctrl-1 = <&sdc2_state_off>;
+ power-domains = <&rpmpd SDM660_VDDCX>;
+
+ status = "disabled";
+
+ sdhc2_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-50000000 {
+ opp-hz = /bits/ 64 <50000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <200000 140000>;
+ opp-avg-kBps = <130718 133320>;
+ };
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ opp-peak-kBps = <250000 160000>;
+ opp-avg-kBps = <196078 150000>;
+ };
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ opp-peak-kBps = <4096000 4096000>;
+ opp-avg-kBps = <1338562 1338562>;
+ };
+ };
+ };
+
sdhc_1: sdhci@c0c4000 {
compatible = "qcom,sdm630-sdhci", "qcom,sdhci-msm-v5";
reg = <0x0c0c4000 0x1000>,
@@ -822,14 +1315,264 @@
<&gcc GCC_SDCC1_ICE_CORE_CLK>;
clock-names = "core", "iface", "xo", "ice";
+ interconnects = <&a2noc 2 &a2noc 10>,
+ <&gnoc 0 &cnoc 27>;
+ interconnect-names = "sdhc1-ddr", "cpu-sdhc1";
+ operating-points-v2 = <&sdhc1_opp_table>;
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>;
+ pinctrl-0 = <&sdc1_state_on>;
+ pinctrl-1 = <&sdc1_state_off>;
+ power-domains = <&rpmpd SDM660_VDDCX>;
bus-width = <8>;
non-removable;
status = "disabled";
+
+ sdhc1_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-50000000 {
+ opp-hz = /bits/ 64 <50000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <200000 140000>;
+ opp-avg-kBps = <130718 133320>;
+ };
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ opp-peak-kBps = <250000 160000>;
+ opp-avg-kBps = <196078 150000>;
+ };
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ opp-peak-kBps = <4096000 4096000>;
+ opp-avg-kBps = <1338562 1338562>;
+ };
+ };
+ };
+
+ mmcc: clock-controller@c8c0000 {
+ compatible = "qcom,mmcc-sdm630";
+ reg = <0x0c8c0000 0x40000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ clock-names = "xo",
+ "sleep_clk",
+ "gpll0",
+ "gpll0_div",
+ "dsi0pll",
+ "dsi0pllbyte",
+ "dsi1pll",
+ "dsi1pllbyte",
+ "dp_link_2x_clk_divsel_five",
+ "dp_vco_divided_clk_src_mux";
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&sleep_clk>,
+ <&gcc GCC_MMSS_GPLL0_CLK>,
+ <&gcc GCC_MMSS_GPLL0_DIV_CLK>,
+ <&dsi0_phy 1>,
+ <&dsi0_phy 0>,
+ <0>,
+ <0>,
+ <0>,
+ <0>;
+ };
+
+ dsi_opp_table: dsi-opp-table {
+ compatible = "operating-points-v2";
+
+ opp-131250000 {
+ opp-hz = /bits/ 64 <131250000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp-210000000 {
+ opp-hz = /bits/ 64 <210000000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+
+ opp-262500000 {
+ opp-hz = /bits/ 64 <262500000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+ };
+
+ mdss: mdss@c900000 {
+ compatible = "qcom,mdss";
+ reg = <0x0c900000 0x1000>,
+ <0x0c9b0000 0x1040>;
+ reg-names = "mdss_phys", "vbif_phys";
+
+ power-domains = <&mmcc MDSS_GDSC>;
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MDSS_VSYNC_CLK>,
+ <&mmcc MDSS_MDP_CLK>;
+ clock-names = "iface",
+ "bus",
+ "vsync",
+ "core";
+
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ status = "disabled";
+
+ mdp: mdp@c901000 {
+ compatible = "qcom,mdp5";
+ reg = <0x0c901000 0x89000>;
+ reg-names = "mdp_phys";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+ assigned-clocks = <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_VSYNC_CLK>;
+ assigned-clock-rates = <300000000>,
+ <19200000>;
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_VSYNC_CLK>;
+ clock-names = "iface",
+ "bus",
+ "core",
+ "vsync";
+
+ interconnects = <&mnoc 2 &bimc 5>,
+ <&mnoc 3 &bimc 5>,
+ <&gnoc 0 &mnoc 17>;
+ interconnect-names = "mdp0-mem",
+ "mdp1-mem",
+ "rotator-mem";
+ iommus = <&mmss_smmu 0>;
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd SDM660_VDDCX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ mdp5_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+ };
+
+ mdp_opp_table: mdp-opp {
+ compatible = "operating-points-v2";
+
+ opp-150000000 {
+ opp-hz = /bits/ 64 <150000000>;
+ opp-peak-kBps = <320000 320000 76800>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+ opp-275000000 {
+ opp-hz = /bits/ 64 <275000000>;
+ opp-peak-kBps = <6400000 6400000 160000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-peak-kBps = <6400000 6400000 190000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+ opp-330000000 {
+ opp-hz = /bits/ 64 <330000000>;
+ opp-peak-kBps = <6400000 6400000 240000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+ opp-412500000 {
+ opp-hz = /bits/ 64 <412500000>;
+ opp-peak-kBps = <6400000 6400000 320000>;
+ required-opps = <&rpmpd_opp_turbo>;
+ };
+ };
+ };
+
+ dsi0: dsi@c994000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0c994000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd SDM660_VDDCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+
+ assigned-clocks = <&mmcc BYTE0_CLK_SRC>,
+ <&mmcc PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>,
+ <&dsi0_phy 1>;
+
+ clocks = <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_BYTE0_CLK>,
+ <&mmcc MDSS_BYTE0_INTF_CLK>,
+ <&mmcc MNOC_AHB_CLK>,
+ <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MISC_AHB_CLK>,
+ <&mmcc MDSS_PCLK0_CLK>,
+ <&mmcc MDSS_ESC0_CLK>;
+ clock-names = "mdp_core",
+ "byte",
+ "byte_intf",
+ "mnoc",
+ "iface",
+ "bus",
+ "core_mmss",
+ "pixel",
+ "core";
+
+ phys = <&dsi0_phy>;
+ phy-names = "dsi";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&mdp5_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi0_phy: dsi-phy@c994400 {
+ compatible = "qcom,dsi-phy-14nm-660";
+ reg = <0x0c994400 0x100>,
+ <0x0c994500 0x300>,
+ <0x0c994800 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&mmcc MDSS_AHB_CLK>, <&xo_board>;
+ clock-names = "iface", "ref";
+ };
};
blsp1_dma: dma-controller@c144000 {
@@ -883,6 +1626,8 @@
<&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
+ dmas = <&blsp1_dma 4>, <&blsp1_dma 5>;
+ dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c1_default>;
@@ -901,6 +1646,8 @@
<&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
+ dmas = <&blsp1_dma 6>, <&blsp1_dma 7>;
+ dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c2_default>;
@@ -919,6 +1666,8 @@
<&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
+ dmas = <&blsp1_dma 8>, <&blsp1_dma 9>;
+ dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c3_default>;
@@ -937,6 +1686,8 @@
<&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
+ dmas = <&blsp1_dma 10>, <&blsp1_dma 11>;
+ dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c4_default>;
@@ -969,10 +1720,8 @@
dmas = <&blsp2_dma 0>, <&blsp2_dma 1>;
dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
- pinctrl-0 = <&blsp2_uart1_tx_active &blsp2_uart1_rxcts_active
- &blsp2_uart1_rfr_active>;
- pinctrl-1 = <&blsp2_uart1_tx_sleep &blsp2_uart1_rxcts_sleep
- &blsp2_uart1_rfr_sleep>;
+ pinctrl-0 = <&blsp2_uart1_default>;
+ pinctrl-1 = <&blsp2_uart1_sleep>;
status = "disabled";
};
@@ -985,6 +1734,8 @@
<&gcc GCC_BLSP2_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
+ dmas = <&blsp2_dma 4>, <&blsp2_dma 5>;
+ dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c5_default>;
@@ -1003,6 +1754,8 @@
<&gcc GCC_BLSP2_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
+ dmas = <&blsp2_dma 6>, <&blsp2_dma 7>;
+ dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c6_default>;
@@ -1021,6 +1774,8 @@
<&gcc GCC_BLSP2_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
+ dmas = <&blsp2_dma 8>, <&blsp2_dma 9>;
+ dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c7_default>;
@@ -1039,6 +1794,8 @@
<&gcc GCC_BLSP2_AHB_CLK>;
clock-names = "core", "iface";
clock-frequency = <400000>;
+ dmas = <&blsp2_dma 10>, <&blsp2_dma 11>;
+ dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c8_default>;
@@ -1048,12 +1805,223 @@
status = "disabled";
};
+ imem@146bf000 {
+ compatible = "simple-mfd";
+ reg = <0x146bf000 0x1000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ranges = <0 0x146bf000 0x1000>;
+
+ pil-reloc@94c {
+ compatible = "qcom,pil-reloc-info";
+ reg = <0x94c 0xc8>;
+ };
+ };
+
+ camss: camss@ca00000 {
+ compatible = "qcom,sdm660-camss";
+ reg = <0x0c824000 0x1000>,
+ <0x0ca00120 0x4>,
+ <0x0c825000 0x1000>,
+ <0x0ca00124 0x4>,
+ <0x0c826000 0x1000>,
+ <0x0ca00128 0x4>,
+ <0x0ca30000 0x100>,
+ <0x0ca30400 0x100>,
+ <0x0ca30800 0x100>,
+ <0x0ca30c00 0x100>,
+ <0x0ca31000 0x500>,
+ <0x0ca00020 0x10>,
+ <0x0ca10000 0x1000>,
+ <0x0ca14000 0x1000>;
+ reg-names = "csiphy0",
+ "csiphy0_clk_mux",
+ "csiphy1",
+ "csiphy1_clk_mux",
+ "csiphy2",
+ "csiphy2_clk_mux",
+ "csid0",
+ "csid1",
+ "csid2",
+ "csid3",
+ "ispif",
+ "csi_clk_mux",
+ "vfe0",
+ "vfe1";
+ interrupts = <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 80 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 296 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 297 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 298 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 299 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 309 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 314 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 315 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "csiphy0",
+ "csiphy1",
+ "csiphy2",
+ "csid0",
+ "csid1",
+ "csid2",
+ "csid3",
+ "ispif",
+ "vfe0",
+ "vfe1";
+ clocks = <&mmcc CAMSS_TOP_AHB_CLK>,
+ <&mmcc THROTTLE_CAMSS_AXI_CLK>,
+ <&mmcc CAMSS_ISPIF_AHB_CLK>,
+ <&mmcc CAMSS_CSI0PHYTIMER_CLK>,
+ <&mmcc CAMSS_CSI1PHYTIMER_CLK>,
+ <&mmcc CAMSS_CSI2PHYTIMER_CLK>,
+ <&mmcc CAMSS_CSI0_AHB_CLK>,
+ <&mmcc CAMSS_CSI0_CLK>,
+ <&mmcc CAMSS_CPHY_CSID0_CLK>,
+ <&mmcc CAMSS_CSI0PIX_CLK>,
+ <&mmcc CAMSS_CSI0RDI_CLK>,
+ <&mmcc CAMSS_CSI1_AHB_CLK>,
+ <&mmcc CAMSS_CSI1_CLK>,
+ <&mmcc CAMSS_CPHY_CSID1_CLK>,
+ <&mmcc CAMSS_CSI1PIX_CLK>,
+ <&mmcc CAMSS_CSI1RDI_CLK>,
+ <&mmcc CAMSS_CSI2_AHB_CLK>,
+ <&mmcc CAMSS_CSI2_CLK>,
+ <&mmcc CAMSS_CPHY_CSID2_CLK>,
+ <&mmcc CAMSS_CSI2PIX_CLK>,
+ <&mmcc CAMSS_CSI2RDI_CLK>,
+ <&mmcc CAMSS_CSI3_AHB_CLK>,
+ <&mmcc CAMSS_CSI3_CLK>,
+ <&mmcc CAMSS_CPHY_CSID3_CLK>,
+ <&mmcc CAMSS_CSI3PIX_CLK>,
+ <&mmcc CAMSS_CSI3RDI_CLK>,
+ <&mmcc CAMSS_AHB_CLK>,
+ <&mmcc CAMSS_VFE0_CLK>,
+ <&mmcc CAMSS_CSI_VFE0_CLK>,
+ <&mmcc CAMSS_VFE0_AHB_CLK>,
+ <&mmcc CAMSS_VFE0_STREAM_CLK>,
+ <&mmcc CAMSS_VFE1_CLK>,
+ <&mmcc CAMSS_CSI_VFE1_CLK>,
+ <&mmcc CAMSS_VFE1_AHB_CLK>,
+ <&mmcc CAMSS_VFE1_STREAM_CLK>,
+ <&mmcc CAMSS_VFE_VBIF_AHB_CLK>,
+ <&mmcc CAMSS_VFE_VBIF_AXI_CLK>,
+ <&mmcc CSIPHY_AHB2CRIF_CLK>,
+ <&mmcc CAMSS_CPHY_CSID0_CLK>,
+ <&mmcc CAMSS_CPHY_CSID1_CLK>,
+ <&mmcc CAMSS_CPHY_CSID2_CLK>,
+ <&mmcc CAMSS_CPHY_CSID3_CLK>;
+ clock-names = "top_ahb",
+ "throttle_axi",
+ "ispif_ahb",
+ "csiphy0_timer",
+ "csiphy1_timer",
+ "csiphy2_timer",
+ "csi0_ahb",
+ "csi0",
+ "csi0_phy",
+ "csi0_pix",
+ "csi0_rdi",
+ "csi1_ahb",
+ "csi1",
+ "csi1_phy",
+ "csi1_pix",
+ "csi1_rdi",
+ "csi2_ahb",
+ "csi2",
+ "csi2_phy",
+ "csi2_pix",
+ "csi2_rdi",
+ "csi3_ahb",
+ "csi3",
+ "csi3_phy",
+ "csi3_pix",
+ "csi3_rdi",
+ "ahb",
+ "vfe0",
+ "csi_vfe0",
+ "vfe0_ahb",
+ "vfe0_stream",
+ "vfe1",
+ "csi_vfe1",
+ "vfe1_ahb",
+ "vfe1_stream",
+ "vfe_ahb",
+ "vfe_axi",
+ "csiphy_ahb2crif",
+ "cphy_csid0",
+ "cphy_csid1",
+ "cphy_csid2",
+ "cphy_csid3";
+ interconnects = <&mnoc 5 &bimc 5>;
+ interconnect-names = "vfe-mem";
+ iommus = <&mmss_smmu 0xc00>,
+ <&mmss_smmu 0xc01>,
+ <&mmss_smmu 0xc02>,
+ <&mmss_smmu 0xc03>;
+ power-domains = <&mmcc CAMSS_VFE0_GDSC>,
+ <&mmcc CAMSS_VFE1_GDSC>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ cci: cci@ca0c000 {
+ compatible = "qcom,msm8996-cci";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0ca0c000 0x1000>;
+ interrupts = <GIC_SPI 295 IRQ_TYPE_EDGE_RISING>;
+
+ assigned-clocks = <&mmcc CAMSS_CCI_AHB_CLK>,
+ <&mmcc CAMSS_CCI_CLK>;
+ assigned-clock-rates = <80800000>, <37500000>;
+ clocks = <&mmcc CAMSS_TOP_AHB_CLK>,
+ <&mmcc CAMSS_CCI_AHB_CLK>,
+ <&mmcc CAMSS_CCI_CLK>,
+ <&mmcc CAMSS_AHB_CLK>;
+ clock-names = "camss_top_ahb",
+ "cci_ahb",
+ "cci",
+ "camss_ahb";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&cci0_default &cci1_default>;
+ power-domains = <&mmcc CAMSS_TOP_GDSC>;
+ status = "disabled";
+
+ cci_i2c0: i2c-bus@0 {
+ reg = <0>;
+ clock-frequency = <400000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ cci_i2c1: i2c-bus@1 {
+ reg = <1>;
+ clock-frequency = <400000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
mmss_smmu: iommu@cd00000 {
compatible = "qcom,sdm630-smmu-v2", "qcom,smmu-v2";
reg = <0x0cd00000 0x40000>;
- #iommu-cells = <1>;
+ clocks = <&mmcc MNOC_AHB_CLK>,
+ <&mmcc BIMC_SMMU_AHB_CLK>,
+ <&rpmcc RPM_SMD_MMSSNOC_AXI_CLK>,
+ <&mmcc BIMC_SMMU_AXI_CLK>;
+ clock-names = "iface-mm", "iface-smmu",
+ "bus-mm", "bus-smmu";
#global-interrupts = <2>;
+ #iommu-cells = <1>;
+
interrupts =
<GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
@@ -1086,6 +2054,97 @@
status = "disabled";
};
+ adsp_pil: remoteproc@15700000 {
+ compatible = "qcom,sdm660-adsp-pas";
+ reg = <0x15700000 0x4040>;
+
+ interrupts-extended =
+ <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog", "fatal", "ready",
+ "handover", "stop-ack";
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "xo";
+
+ memory-region = <&adsp_region>;
+ power-domains = <&rpmpd SDM660_VDDCX>;
+ power-domain-names = "cx";
+
+ qcom,smem-states = <&adsp_smp2p_out 0>;
+ qcom,smem-state-names = "stop";
+
+ glink-edge {
+ interrupts = <GIC_SPI 157 IRQ_TYPE_EDGE_RISING>;
+
+ label = "lpass";
+ mboxes = <&apcs_glb 9>;
+ qcom,remote-pid = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ apr {
+ compatible = "qcom,apr-v2";
+ qcom,glink-channels = "apr_audio_svc";
+ qcom,apr-domain = <APR_DOMAIN_ADSP>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ q6core {
+ reg = <APR_SVC_ADSP_CORE>;
+ compatible = "qcom,q6core";
+ };
+
+ q6afe: apr-service@4 {
+ compatible = "qcom,q6afe";
+ reg = <APR_SVC_AFE>;
+ q6afedai: dais {
+ compatible = "qcom,q6afe-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+ };
+
+ q6asm: apr-service@7 {
+ compatible = "qcom,q6asm";
+ reg = <APR_SVC_ASM>;
+ q6asmdai: dais {
+ compatible = "qcom,q6asm-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ iommus = <&lpass_smmu 1>;
+ };
+ };
+
+ q6adm: apr-service@8 {
+ compatible = "qcom,q6adm";
+ reg = <APR_SVC_ADM>;
+ q6routing: routing {
+ compatible = "qcom,q6adm-routing";
+ #sound-dai-cells = <0>;
+ };
+ };
+ };
+ };
+ };
+
+ gnoc: interconnect@17900000 {
+ compatible = "qcom,sdm660-gnoc";
+ reg = <0x17900000 0xe000>;
+ #interconnect-cells = <1>;
+ /*
+ * This one apparently features no clocks,
+ * so let's not mess with the driver needlessly
+ */
+ clock-names = "bus", "bus_a";
+ clocks = <&xo_board>, <&xo_board>;
+ };
+
apcs_glb: mailbox@17911000 {
compatible = "qcom,sdm660-apcs-hmss-global";
reg = <0x17911000 0x1000>;
@@ -1173,6 +2232,182 @@
#hwlock-cells = <1>;
};
+ sound: sound {
+ };
+
+ thermal-zones {
+ aoss-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 0>;
+
+ trips {
+ aoss_alert0: trip-point0 {
+ temperature = <105000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+ };
+ };
+
+ cpuss0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 1>;
+
+ trips {
+ cpuss0_alert0: trip-point0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+ };
+ };
+
+ cpuss1-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 2>;
+
+ trips {
+ cpuss1_alert0: trip-point0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+ };
+ };
+
+ cpu0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 3>;
+
+ trips {
+ cpu0_alert0: trip-point0 {
+ temperature = <70000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ cpu0_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu1-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 4>;
+
+ trips {
+ cpu1_alert0: trip-point0 {
+ temperature = <70000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ cpu1_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu2-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 5>;
+
+ trips {
+ cpu2_alert0: trip-point0 {
+ temperature = <70000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ cpu2_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu3-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 6>;
+
+ trips {
+ cpu3_alert0: trip-point0 {
+ temperature = <70000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ cpu3_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ /*
+ * According to what downstream DTS says,
+ * the entire power efficient cluster has
+ * only a single thermal sensor.
+ */
+
+ pwr-cluster-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 7>;
+
+ trips {
+ pwr_cluster_alert0: trip-point0 {
+ temperature = <70000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ pwr_cluster_crit: cpu_crit {
+ temperature = <110000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpu-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 8>;
+
+ trips {
+ gpu_alert0: trip-point0 {
+ temperature = <90000>;
+ hysteresis = <1000>;
+ type = "hot";
+ };
+ };
+ };
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 1 0xf08>,
diff --git a/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts b/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts
index 7c0830e6a48c..bba1c2bce213 100644
--- a/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts
+++ b/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts
@@ -5,16 +5,20 @@
/dts-v1/;
-/* Mermaid uses sdm636, but it's different ever so slightly
- * that we can ignore it for the time being. Sony also commonizes
- * the Ganges platform as a whole in downstream kernels.
- */
-#include "sdm630-sony-xperia-ganges.dtsi"
+#include "sdm630-sony-xperia-ganges-kirin.dts"
+#include "sdm636.dtsi"
/ {
model = "Sony Xperia 10 Plus";
compatible = "sony,mermaid-row", "qcom,sdm636";
+ /* SDM636 v1 */
qcom,msm-id = <345 0>;
qcom,pmic-id = <0x1001b 0x101011a 0x00 0x00 0x1001b 0x201011a 0x00 0x00 0x1001b 0x102001a 0x00 0x00>;
};
+
+&sdc2_state_on {
+ pinconf-clk {
+ drive-strength = <14>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm636.dtsi b/arch/arm64/boot/dts/qcom/sdm636.dtsi
new file mode 100644
index 000000000000..ae15d81fa3f9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm636.dtsi
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020, AngeloGioacchino Del Regno <kholk11@gmail.com>
+ * Copyright (c) 2020, Konrad Dybcio <konradybcio@gmail.com>
+ * Copyright (c) 2020, Martin Botka <martin.botka1@gmail.com>
+ */
+
+#include "sdm660.dtsi"
+
+/*
+ * According to the downstream DTS,
+ * 636 is basically a 660 except for
+ * different CPU frequencies, Adreno
+ * 509 instead of 512 and lack of
+ * turing IP. These differences will
+ * be addressed when the aforementioned
+ * peripherals will be enabled upstream.
+ */
+
+&adreno_gpu {
+ compatible = "qcom,adreno-509.0", "qcom,adreno";
+ /* Adreno 509 shares the frequency table with 512 */
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts b/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts
index 76533e8b2092..3e677fb7cfea 100644
--- a/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts
+++ b/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts
@@ -37,8 +37,6 @@
&blsp1_uart2 {
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&uart_console_active>;
};
&tlmm {
diff --git a/arch/arm64/boot/dts/qcom/sdm660.dtsi b/arch/arm64/boot/dts/qcom/sdm660.dtsi
index 4abbdd03d1e7..eccf6fde16b4 100644
--- a/arch/arm64/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm660.dtsi
@@ -2,371 +2,250 @@
/*
* Copyright (c) 2018, Craig Tatlor.
* Copyright (c) 2020, Alexey Minnekhanov <alexey.min@gmail.com>
+ * Copyright (c) 2020, AngeloGioacchino Del Regno <kholk11@gmail.com>
+ * Copyright (c) 2020, Konrad Dybcio <konradybcio@gmail.com>
+ * Copyright (c) 2020, Martin Botka <martin.botka1@gmail.com>
*/
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/clock/qcom,gcc-sdm660.h>
+#include "sdm630.dtsi"
-/ {
- interrupt-parent = <&intc>;
+&adreno_gpu {
+ compatible = "qcom,adreno-512.0", "qcom,adreno";
+ operating-points-v2 = <&gpu_sdm660_opp_table>;
- #address-cells = <2>;
- #size-cells = <2>;
+ gpu_sdm660_opp_table: opp-table {
+ compatible = "operating-points-v2";
- chosen { };
+ /*
+ * 775MHz is only available on the highest speed bin
+ * Though it cannot be used for now due to interconnect
+ * framework not supporting multiple frequencies
+ * at the same opp-level
- clocks {
- xo_board: xo_board {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <19200000>;
- clock-output-names = "xo_board";
+ opp-750000000 {
+ opp-hz = /bits/ 64 <750000000>;
+ opp-level = <RPM_SMD_LEVEL_TURBO>;
+ opp-peak-kBps = <5412000>;
+ opp-supported-hw = <0xCHECKME>;
};
- sleep_clk: sleep_clk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32764>;
- clock-output-names = "sleep_clk";
- };
- };
+ * These OPPs are correct, but we are lacking support for the
+ * GPU regulator. Hence, disable them for now to prevent the
+ * platform from hanging on high graphics loads.
- cpus {
- #address-cells = <2>;
- #size-cells = <0>;
-
- CPU0: cpu@100 {
- device_type = "cpu";
- compatible = "qcom,kryo260";
- reg = <0x0 0x100>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_1>;
- L2_1: l2-cache {
- compatible = "cache";
- cache-level = <2>;
- };
- L1_I_100: l1-icache {
- compatible = "cache";
- };
- L1_D_100: l1-dcache {
- compatible = "cache";
- };
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-level = <RPM_SMD_LEVEL_TURBO>;
+ opp-peak-kBps = <5184000>;
+ opp-supported-hw = <0xFF>;
};
- CPU1: cpu@101 {
- device_type = "cpu";
- compatible = "qcom,kryo260";
- reg = <0x0 0x101>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_1>;
- L1_I_101: l1-icache {
- compatible = "cache";
- };
- L1_D_101: l1-dcache {
- compatible = "cache";
- };
+ opp-647000000 {
+ opp-hz = /bits/ 64 <647000000>;
+ opp-level = <RPM_SMD_LEVEL_NOM_PLUS>;
+ opp-peak-kBps = <4068000>;
+ opp-supported-hw = <0xFF>;
};
- CPU2: cpu@102 {
- device_type = "cpu";
- compatible = "qcom,kryo260";
- reg = <0x0 0x102>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_1>;
- L1_I_102: l1-icache {
- compatible = "cache";
- };
- L1_D_102: l1-dcache {
- compatible = "cache";
- };
+ opp-588000000 {
+ opp-hz = /bits/ 64 <588000000>;
+ opp-level = <RPM_SMD_LEVEL_NOM>;
+ opp-peak-kBps = <3072000>;
+ opp-supported-hw = <0xFF>;
};
- CPU3: cpu@103 {
- device_type = "cpu";
- compatible = "qcom,kryo260";
- reg = <0x0 0x103>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_1>;
- L1_I_103: l1-icache {
- compatible = "cache";
- };
- L1_D_103: l1-dcache {
- compatible = "cache";
- };
+ opp-465000000 {
+ opp-hz = /bits/ 64 <465000000>;
+ opp-level = <RPM_SMD_LEVEL_SVS_PLUS>;
+ opp-peak-kBps = <2724000>;
+ opp-supported-hw = <0xFF>;
};
- CPU4: cpu@0 {
- device_type = "cpu";
- compatible = "qcom,kryo260";
- reg = <0x0 0x0>;
- enable-method = "psci";
- capacity-dmips-mhz = <640>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
- compatible = "cache";
- cache-level = <2>;
- };
- L1_I_0: l1-icache {
- compatible = "cache";
- };
- L1_D_0: l1-dcache {
- compatible = "cache";
- };
+ opp-370000000 {
+ opp-hz = /bits/ 64 <370000000>;
+ opp-level = <RPM_SMD_LEVEL_SVS>;
+ opp-peak-kBps = <2188000>;
+ opp-supported-hw = <0xFF>;
};
+ */
- CPU5: cpu@1 {
- device_type = "cpu";
- compatible = "qcom,kryo260";
- reg = <0x0 0x1>;
- enable-method = "psci";
- capacity-dmips-mhz = <640>;
- next-level-cache = <&L2_0>;
- L1_I_1: l1-icache {
- compatible = "cache";
- };
- L1_D_1: l1-dcache {
- compatible = "cache";
- };
+ opp-266000000 {
+ opp-hz = /bits/ 64 <266000000>;
+ opp-level = <RPM_SMD_LEVEL_LOW_SVS>;
+ opp-peak-kBps = <1648000>;
+ opp-supported-hw = <0xFF>;
};
- CPU6: cpu@2 {
- device_type = "cpu";
- compatible = "qcom,kryo260";
- reg = <0x0 0x2>;
- enable-method = "psci";
- capacity-dmips-mhz = <640>;
- next-level-cache = <&L2_0>;
- L1_I_2: l1-icache {
- compatible = "cache";
- };
- L1_D_2: l1-dcache {
- compatible = "cache";
- };
+ opp-160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ opp-level = <RPM_SMD_LEVEL_MIN_SVS>;
+ opp-peak-kBps = <1200000>;
+ opp-supported-hw = <0xFF>;
};
+ };
+};
- CPU7: cpu@3 {
- device_type = "cpu";
- compatible = "qcom,kryo260";
- reg = <0x0 0x3>;
- enable-method = "psci";
- capacity-dmips-mhz = <640>;
- next-level-cache = <&L2_0>;
- L1_I_3: l1-icache {
- compatible = "cache";
- };
- L1_D_3: l1-dcache {
- compatible = "cache";
- };
- };
-
- cpu-map {
- cluster0 {
- core0 {
- cpu = <&CPU4>;
- };
-
- core1 {
- cpu = <&CPU5>;
- };
-
- core2 {
- cpu = <&CPU6>;
- };
-
- core3 {
- cpu = <&CPU7>;
- };
- };
-
- cluster1 {
- core0 {
- cpu = <&CPU0>;
- };
+&CPU0 {
+ compatible = "qcom,kryo260";
+ capacity-dmips-mhz = <1024>;
+ /delete-property/ operating-points-v2;
+};
- core1 {
- cpu = <&CPU1>;
- };
+&CPU1 {
+ compatible = "qcom,kryo260";
+ capacity-dmips-mhz = <1024>;
+ /delete-property/ operating-points-v2;
+};
- core2 {
- cpu = <&CPU2>;
- };
+&CPU2 {
+ compatible = "qcom,kryo260";
+ capacity-dmips-mhz = <1024>;
+ /delete-property/ operating-points-v2;
+};
- core3 {
- cpu = <&CPU3>;
- };
- };
- };
- };
+&CPU3 {
+ compatible = "qcom,kryo260";
+ capacity-dmips-mhz = <1024>;
+ /delete-property/ operating-points-v2;
+};
- firmware {
- scm {
- compatible = "qcom,scm";
- };
- };
+&CPU4 {
+ compatible = "qcom,kryo260";
+ capacity-dmips-mhz = <640>;
+ /delete-property/ operating-points-v2;
+};
- memory {
- device_type = "memory";
- /* We expect the bootloader to fill in the reg */
- reg = <0 0 0 0>;
- };
+&CPU5 {
+ compatible = "qcom,kryo260";
+ capacity-dmips-mhz = <640>;
+ /delete-property/ operating-points-v2;
+};
- psci {
- compatible = "arm,psci-1.0";
- method = "smc";
- };
+&CPU6 {
+ compatible = "qcom,kryo260";
+ capacity-dmips-mhz = <640>;
+ /delete-property/ operating-points-v2;
+};
- 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>;
- };
+&CPU7 {
+ compatible = "qcom,kryo260";
+ capacity-dmips-mhz = <640>;
+ /delete-property/ operating-points-v2;
+};
- soc: soc {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 0 0 0xffffffff>;
- compatible = "simple-bus";
-
- gcc: clock-controller@100000 {
- compatible = "qcom,gcc-sdm660";
- #clock-cells = <1>;
- #reset-cells = <1>;
- #power-domain-cells = <1>;
- reg = <0x00100000 0x94000>;
- };
+&gcc {
+ compatible = "qcom,gcc-sdm660";
+};
- tlmm: pinctrl@3100000 {
- compatible = "qcom,sdm660-pinctrl";
- reg = <0x03100000 0x400000>,
- <0x03500000 0x400000>,
- <0x03900000 0x400000>;
- reg-names = "south", "center", "north";
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- gpio-ranges = <&tlmm 0 0 114>;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- uart_console_active: uart_console_active {
- pinmux {
- pins = "gpio4", "gpio5";
- function = "blsp_uart2";
- };
+&gpucc {
+ compatible = "qcom,gpucc-sdm660";
+};
- pinconf {
- pins = "gpio4", "gpio5";
- drive-strength = <2>;
- bias-disable;
- };
+&mdp {
+ ports {
+ port@1 {
+ reg = <1>;
+ mdp5_intf2_out: endpoint {
+ remote-endpoint = <&dsi1_in>;
};
};
+ };
+};
- spmi_bus: spmi@800f000 {
- compatible = "qcom,spmi-pmic-arb";
- reg = <0x0800f000 0x1000>,
- <0x08400000 0x1000000>,
- <0x09400000 0x1000000>,
- <0x0a400000 0x220000>,
- <0x0800a000 0x3000>;
- reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
- interrupt-names = "periph_irq";
- interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>;
- qcom,ee = <0>;
- qcom,channel = <0>;
- #address-cells = <2>;
+&mdss {
+ dsi1: dsi@c996000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0c996000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ /* DSI1 shares the OPP table with DSI0 */
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd SDM660_VDDCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+
+ assigned-clocks = <&mmcc BYTE1_CLK_SRC>,
+ <&mmcc PCLK1_CLK_SRC>;
+ assigned-clock-parents = <&dsi1_phy 0>,
+ <&dsi1_phy 1>;
+
+ clocks = <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_BYTE1_CLK>,
+ <&mmcc MDSS_BYTE1_INTF_CLK>,
+ <&mmcc MNOC_AHB_CLK>,
+ <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MISC_AHB_CLK>,
+ <&mmcc MDSS_PCLK1_CLK>,
+ <&mmcc MDSS_ESC1_CLK>;
+ clock-names = "mdp_core",
+ "byte",
+ "byte_intf",
+ "mnoc",
+ "iface",
+ "bus",
+ "core_mmss",
+ "pixel",
+ "core";
+
+ phys = <&dsi1_phy>;
+ phy-names = "dsi";
+
+ ports {
+ #address-cells = <1>;
#size-cells = <0>;
- interrupt-controller;
- #interrupt-cells = <4>;
- cell-index = <0>;
- };
- blsp1_uart2: serial@c170000 {
- compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
- reg = <0x0c170000 0x1000>;
- interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>,
- <&gcc GCC_BLSP1_AHB_CLK>;
- clock-names = "core", "iface";
- status = "disabled";
- };
-
- timer@17920000 {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
- compatible = "arm,armv7-timer-mem";
- reg = <0x17920000 0x1000>;
-
- frame@17921000 {
- frame-number = <0>;
- interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
- reg = <0x17921000 0x1000>,
- <0x17922000 0x1000>;
+ port@0 {
+ reg = <0>;
+ dsi1_in: endpoint {
+ remote-endpoint = <&mdp5_intf2_out>;
+ };
};
- frame@17923000 {
- frame-number = <1>;
- interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
- reg = <0x17923000 0x1000>;
- status = "disabled";
+ port@1 {
+ reg = <1>;
+ dsi1_out: endpoint {
+ };
};
+ };
+ };
- frame@17924000 {
- frame-number = <2>;
- interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
- reg = <0x17924000 0x1000>;
- status = "disabled";
- };
+ dsi1_phy: dsi-phy@c996400 {
+ compatible = "qcom,dsi-phy-14nm-660";
+ reg = <0x0c996400 0x100>,
+ <0x0c996500 0x300>,
+ <0x0c996800 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
- frame@17925000 {
- frame-number = <3>;
- interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
- reg = <0x17925000 0x1000>;
- status = "disabled";
- };
+ #clock-cells = <1>;
+ #phy-cells = <0>;
- frame@17926000 {
- frame-number = <4>;
- interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
- reg = <0x17926000 0x1000>;
- status = "disabled";
- };
+ clocks = <&mmcc MDSS_AHB_CLK>, <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "ref";
+ };
+};
- frame@17927000 {
- frame-number = <5>;
- interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
- reg = <0x17927000 0x1000>;
- status = "disabled";
- };
+&mmcc {
+ compatible = "qcom,mmcc-sdm660";
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&sleep_clk>,
+ <&gcc GCC_MMSS_GPLL0_CLK>,
+ <&gcc GCC_MMSS_GPLL0_DIV_CLK>,
+ <&dsi0_phy 1>,
+ <&dsi0_phy 0>,
+ <&dsi1_phy 1>,
+ <&dsi1_phy 0>,
+ <0>,
+ <0>;
+};
- frame@17928000 {
- frame-number = <6>;
- interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
- reg = <0x17928000 0x1000>;
- status = "disabled";
- };
- };
+&tlmm {
+ compatible = "qcom,sdm660-pinctrl";
+};
- intc: interrupt-controller@17a00000 {
- compatible = "arm,gic-v3";
- reg = <0x17a00000 0x10000>,
- <0x17b00000 0x100000>;
- #interrupt-cells = <3>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
- interrupt-controller;
- #redistributor-regions = <1>;
- redistributor-stride = <0x0 0x20000>;
- interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
- };
- };
+&tsens {
+ #qcom,sensors = <14>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
index 91ede9296aff..52dd7a858231 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
@@ -413,6 +413,9 @@
qcom,dual-dsi-mode;
+ /* DSI1 is slave, so use DSI0 clocks */
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
ports {
port@1 {
endpoint {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
index eb6b1d15293d..d4355522374a 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
@@ -19,9 +19,14 @@
/ {
aliases {
+ serial0 = &uart9;
hsuart0 = &uart6;
};
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
gpio-keys {
compatible = "gpio-keys";
label = "Volume keys";
@@ -403,6 +408,7 @@
status = "okay";
memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/sdm845/oneplus6/ipa_fws.mbn";
};
&mdss {
@@ -526,6 +532,11 @@
};
};
+&uart9 {
+ label = "LS-UART1";
+ status = "okay";
+};
+
&ufs_mem_hc {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 0a86fe71a66d..6d7172e6f4c3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -128,28 +128,23 @@
no-map;
};
- ipa_fw_mem: memory@8c400000 {
- reg = <0 0x8c400000 0 0x10000>;
+ wlan_msa_mem: memory@8c400000 {
+ reg = <0 0x8c400000 0 0x100000>;
no-map;
};
- ipa_gsi_mem: memory@8c410000 {
- reg = <0 0x8c410000 0 0x5000>;
+ gpu_mem: memory@8c515000 {
+ reg = <0 0x8c515000 0 0x2000>;
no-map;
};
- gpu_mem: memory@8c415000 {
- reg = <0 0x8c415000 0 0x2000>;
+ ipa_fw_mem: memory@8c517000 {
+ reg = <0 0x8c517000 0 0x5a000>;
no-map;
};
- adsp_mem: memory@8c500000 {
- reg = <0 0x8c500000 0 0x1a00000>;
- no-map;
- };
-
- wlan_msa_mem: memory@8df00000 {
- reg = <0 0x8df00000 0 0x100000>;
+ adsp_mem: memory@8c600000 {
+ reg = <0 0x8c600000 0 0x1a00000>;
no-map;
};
@@ -4148,9 +4143,8 @@
power-domains = <&dispcc MDSS_GDSC>;
clocks = <&gcc GCC_DISP_AHB_CLK>,
- <&gcc GCC_DISP_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>;
- clock-names = "iface", "bus", "core";
+ clock-names = "iface", "core";
assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>;
assigned-clock-rates = <300000000>;
@@ -4178,11 +4172,12 @@
<0 0x0aeb0000 0 0x2008>;
reg-names = "mdp", "vbif";
- clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ clocks = <&gcc GCC_DISP_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- clock-names = "iface", "bus", "core", "vsync";
+ clock-names = "gcc-bus", "iface", "bus", "core", "vsync";
assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
@@ -4260,6 +4255,9 @@
"core",
"iface",
"bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd SDM845_CX>;
@@ -4326,6 +4324,9 @@
"core",
"iface",
"bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>;
+ assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>;
+
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd SDM845_CX>;
diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
index d7591a4621a2..385e5029437d 100644
--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
@@ -415,6 +415,11 @@
};
};
+&ipa {
+ status = "okay";
+ memory-region = <&ipa_fw_mem>;
+};
+
&mdss {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
new file mode 100644
index 000000000000..58b6b2742d3f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Martin Botka <martin.botka@somainline.org>
+ */
+
+/dts-v1/;
+
+#include "sm6125.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/input/gpio-keys.h>
+
+/ {
+ /* required for bootloader to select correct board */
+ qcom,msm-id = <394 0x10000>; /* sm6125 v1 */
+ qcom,board-id = <34 0>;
+
+ model = "Sony Xperia 10 II";
+ compatible = "sony,pdx201", "qcom,sm6125";
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ framebuffer0: framebuffer@5c000000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0x5c000000 0 (2520 * 1080 * 4)>;
+ width = <1080>;
+ height = <2520>;
+ stride = <(1080 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+
+ extcon_usb: extcon-usb {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpio = <&tlmm 102 GPIO_ACTIVE_HIGH>;
+ };
+
+ gpio-keys {
+ status = "okay";
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ autorepeat;
+
+ vol-dn {
+ label = "Volume Down";
+ gpios = <&tlmm 47 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
+
+ reserved_memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ debug_mem: memory@ffb00000 {
+ reg = <0x0 0xffb00000 0x0 0xc0000>;
+ no-map;
+ };
+
+ last_log_mem: memory@ffbc0000 {
+ reg = <0x0 0xffbc0000 0x0 0x80000>;
+ no-map;
+ };
+
+ pstore_mem: ramoops@ffc00000 {
+ compatible = "ramoops";
+ reg = <0x0 0xffc40000 0x0 0xc0000>;
+ record-size = <0x1000>;
+ console-size = <0x40000>;
+ msg-size = <0x20000 0x20000>;
+ };
+
+ cmdline_mem: memory@ffd00000 {
+ reg = <0x0 0xffd40000 0x0 0x1000>;
+ no-map;
+ };
+ };
+};
+
+&hsusb_phy1 {
+ status = "okay";
+};
+
+&sdc2_state_off {
+ sd-cd {
+ pins = "gpio98";
+ bias-disable;
+ drive-strength = <2>;
+ };
+};
+
+&sdhc_1 {
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <22 2>, <28 6>;
+
+ sdc2_state_on: sdc2-on {
+ clk {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ sd-cd {
+ pins = "gpio98";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+};
+
+&usb3 {
+ status = "okay";
+};
+
+&usb3_dwc3 {
+ extcon = <&extcon_usb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi
new file mode 100644
index 000000000000..2b37ce6a9f9c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi
@@ -0,0 +1,566 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Martin Botka <martin.botka@somainline.org>
+ */
+
+#include <dt-bindings/clock/qcom,gcc-sm6125.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+/ {
+ interrupt-parent = <&intc>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ clocks {
+ xo_board: xo-board {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <19200000>;
+ clock-output-names = "xo_board";
+ };
+
+ sleep_clk: sleep-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32000>;
+ clock-output-names = "sleep_clk";
+ };
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ compatible = "cache";
+ };
+ };
+
+ CPU1: cpu@1 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x1>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ next-level-cache = <&L2_0>;
+ };
+
+ CPU2: cpu@2 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x2>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ next-level-cache = <&L2_0>;
+ };
+
+ CPU3: cpu@3 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x3>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ next-level-cache = <&L2_0>;
+ };
+
+ CPU4: cpu@100 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1638>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ compatible = "cache";
+ };
+ };
+
+ CPU5: cpu@101 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x101>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1638>;
+ next-level-cache = <&L2_1>;
+ };
+
+ CPU6: cpu@102 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x102>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1638>;
+ next-level-cache = <&L2_1>;
+ };
+
+ CPU7: cpu@103 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x103>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1638>;
+ next-level-cache = <&L2_1>;
+ };
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+
+ core1 {
+ cpu = <&CPU1>;
+ };
+
+ core2 {
+ cpu = <&CPU2>;
+ };
+
+ core3 {
+ cpu = <&CPU3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&CPU4>;
+ };
+
+ core1 {
+ cpu = <&CPU5>;
+ };
+
+ core2 {
+ cpu = <&CPU6>;
+ };
+
+ core3 {
+ cpu = <&CPU7>;
+ };
+ };
+ };
+ };
+
+ firmware {
+ scm: scm {
+ compatible = "qcom,scm-sm6125", "qcom,scm";
+ #reset-cells = <1>;
+ };
+ };
+
+ memory@40000000 {
+ /* We expect the bootloader to fill in the size */
+ reg = <0x0 0x40000000 0x0 0x0>;
+ device_type = "memory";
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ reserved_memory: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hyp_mem: memory@45700000 {
+ reg = <0x0 0x45700000 0x0 0x600000>;
+ no-map;
+ };
+
+ xbl_aop_mem: memory@45e00000 {
+ reg = <0x0 0x45e00000 0x0 0x140000>;
+ no-map;
+ };
+
+ sec_apps_mem: memory@45fff000 {
+ reg = <0x0 0x45fff000 0x0 0x1000>;
+ no-map;
+ };
+
+ smem_mem: memory@46000000 {
+ reg = <0x0 0x46000000 0x0 0x200000>;
+ no-map;
+ };
+
+ reserved_mem1: memory@46200000 {
+ reg = <0x0 0x46200000 0x0 0x2d00000>;
+ no-map;
+ };
+
+ camera_mem: memory@4ab00000 {
+ reg = <0x0 0x4ab00000 0x0 0x500000>;
+ no-map;
+ };
+
+ modem_mem: memory@4b000000 {
+ reg = <0x0 0x4b000000 0x0 0x7e00000>;
+ no-map;
+ };
+
+ venus_mem: memory@52e00000 {
+ reg = <0x0 0x52e00000 0x0 0x500000>;
+ no-map;
+ };
+
+ wlan_msa_mem: memory@53300000 {
+ reg = <0x0 0x53300000 0x0 0x200000>;
+ no-map;
+ };
+
+ cdsp_mem: memory@53500000 {
+ reg = <0x0 0x53500000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ adsp_pil_mem: memory@55300000 {
+ reg = <0x0 0x55300000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ ipa_fw_mem: memory@57100000 {
+ reg = <0x0 0x57100000 0x0 0x10000>;
+ no-map;
+ };
+
+ ipa_gsi_mem: memory@57110000 {
+ reg = <0x0 0x57110000 0x0 0x5000>;
+ no-map;
+ };
+
+ gpu_mem: memory@57115000 {
+ reg = <0x0 0x57115000 0x0 0x2000>;
+ no-map;
+ };
+
+ cont_splash_mem: memory@5c000000 {
+ reg = <0x0 0x5c000000 0x0 0x00f00000>;
+ no-map;
+ };
+
+ dfps_data_mem: memory@5cf00000 {
+ reg = <0x0 0x5cf00000 0x0 0x0100000>;
+ no-map;
+ };
+
+ cdsp_sec_mem: memory@5f800000 {
+ reg = <0x0 0x5f800000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ qseecom_mem: memory@5e400000 {
+ reg = <0x0 0x5e400000 0x0 0x1400000>;
+ no-map;
+ };
+
+ sdsp_mem: memory@f3000000 {
+ reg = <0x0 0xf3000000 0x0 0x400000>;
+ no-map;
+ };
+
+ adsp_mem: memory@f3400000 {
+ reg = <0x0 0xf3400000 0x0 0x800000>;
+ no-map;
+ };
+
+ qseecom_ta_mem: memory@13fc00000 {
+ reg = <0x1 0x3fc00000 0x0 0x400000>;
+ no-map;
+ };
+ };
+
+ rpm-glink {
+ compatible = "qcom,glink-rpm";
+
+ interrupts = <GIC_SPI 194 IRQ_TYPE_EDGE_RISING>;
+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
+ mboxes = <&apcs_glb 0>;
+
+ rpm_requests: rpm-requests {
+ compatible = "qcom,rpm-sm6125";
+ qcom,glink-channels = "rpm_requests";
+
+ rpmcc: clock-controller {
+ compatible = "qcom,rpmcc-sm6125", "qcom,rpmcc";
+ #clock-cells = <1>;
+ };
+ };
+ };
+
+ smem: smem {
+ compatible = "qcom,smem";
+ memory-region = <&smem_mem>;
+ hwlocks = <&tcsr_mutex 3>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x00 0x00 0x00 0xffffffff>;
+ compatible = "simple-bus";
+
+ tcsr_mutex: hwlock@340000 {
+ compatible = "qcom,tcsr-mutex";
+ reg = <0x00340000 0x20000>;
+ #hwlock-cells = <1>;
+ };
+
+ tlmm: pinctrl@500000 {
+ compatible = "qcom,sm6125-tlmm";
+ reg = <0x00500000 0x400000>,
+ <0x00900000 0x400000>,
+ <0x00d00000 0x400000>;
+ reg-names = "west", "south", "east";
+ interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 134>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ sdc2_state_off: sdc2-off {
+ clk {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cmd {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ data {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+ };
+
+ gcc: clock-controller@1400000 {
+ compatible = "qcom,gcc-sm6125";
+ reg = <0x01400000 0x1f0000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ clock-names = "bi_tcxo", "sleep_clk";
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&sleep_clk>;
+ };
+
+ hsusb_phy1: phy@1613000 {
+ compatible = "qcom,msm8996-qusb2-phy";
+ reg = <0x01613000 0x180>;
+ #phy-cells = <0>;
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GCC_AHB2PHY_USB_CLK>;
+ clock-names = "ref", "cfg_ahb";
+
+ resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+ status = "disabled";
+ };
+
+ rpm_msg_ram: memory@45f0000 {
+ compatible = "qcom,rpm-msg-ram";
+ reg = <0x045f0000 0x7000>;
+ };
+
+ sdhc_1: sdhci@4744000 {
+ compatible = "qcom,sm6125-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0x04744000 0x1000>, <0x04745000 0x1000>;
+ reg-names = "hc", "core";
+
+ interrupts = <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC1_AHB_CLK>,
+ <&gcc GCC_SDCC1_APPS_CLK>,
+ <&xo_board>;
+ clock-names = "iface", "core", "xo";
+ bus-width = <8>;
+ non-removable;
+ status = "disabled";
+ };
+
+ sdhc_2: sdhci@4784000 {
+ compatible = "qcom,sm6125-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0x04784000 0x1000>;
+ reg-names = "hc";
+
+ interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC2_AHB_CLK>,
+ <&gcc GCC_SDCC2_APPS_CLK>,
+ <&xo_board>;
+ clock-names = "iface", "core", "xo";
+
+ pinctrl-0 = <&sdc2_state_on>;
+ pinctrl-1 = <&sdc2_state_off>;
+ pinctrl-names = "default", "sleep";
+
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ usb3: usb@4ef8800 {
+ compatible = "qcom,msm8996-dwc3", "qcom,dwc3";
+ reg = <0x04ef8800 0x400>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clocks = <&gcc GCC_USB30_PRIM_MASTER_CLK>,
+ <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB3_PRIM_CLKREF_CLK>,
+ <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
+ <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
+
+ assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+ assigned-clock-rates = <19200000>, <66666667>;
+
+ power-domains = <&gcc USB30_PRIM_GDSC>;
+ qcom,select-utmi-as-pipe-clk;
+ status = "disabled";
+
+ usb3_dwc3: usb@4e00000 {
+ compatible = "snps,dwc3";
+ reg = <0x04e00000 0xcd00>;
+ interrupts = <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&hsusb_phy1>;
+ phy-names = "usb2-phy";
+ snps,dis_u2_susphy_quirk;
+ snps,dis_enblslpm_quirk;
+ maximum-speed = "high-speed";
+ dr_mode = "peripheral";
+ };
+ };
+
+ spmi_bus: spmi@1c40000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x01c40000 0x1100>,
+ <0x01e00000 0x2000000>,
+ <0x03e00000 0x100000>,
+ <0x03f00000 0xa0000>,
+ <0x01c0a000 0x26000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
+ };
+
+ apcs_glb: mailbox@f111000 {
+ compatible = "qcom,sm6125-apcs-hmss-global";
+ reg = <0x0f111000 0x1000>;
+
+ #mbox-cells = <1>;
+ };
+
+ timer@f120000 {
+ compatible = "arm,armv7-timer-mem";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ reg = <0x0f120000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@0f121000 {
+ frame-number = <0>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0f121000 0x1000>,
+ <0x0f122000 0x1000>;
+ };
+
+ frame@0f123000 {
+ frame-number = <1>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0f123000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@0f124000 {
+ frame-number = <2>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0f124000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f125000 {
+ frame-number = <3>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0f125000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f126000 {
+ frame-number = <4>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0f126000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f127000 {
+ frame-number = <5>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0f127000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f128000 {
+ frame-number = <6>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x0f128000 0x1000>;
+ status = "disabled";
+ };
+ };
+
+ intc: interrupt-controller@f200000 {
+ compatible = "arm,gic-v3";
+ reg = <0x0f200000 0x20000>,
+ <0x0f300000 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 1 0xf08
+ GIC_PPI 2 0xf08
+ GIC_PPI 3 0xf08
+ GIC_PPI 0 0xf08>;
+ clock-frequency = <19200000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
index 53edf7541169..b484371a6044 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
@@ -15,7 +15,7 @@
/ {
model = "Qualcomm Technologies, Inc. SM8150 MTP";
- compatible = "qcom,sm8150-mtp";
+ compatible = "qcom,sm8150-mtp", "qcom,sm8150";
aliases {
serial0 = &uart2;
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index eef9d79157e9..ef0232c2cf45 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -13,6 +13,7 @@
#include <dt-bindings/clock/qcom,gcc-sm8150.h>
#include <dt-bindings/clock/qcom,gpucc-sm8150.h>
#include <dt-bindings/interconnect/qcom,osm-l3.h>
+#include <dt-bindings/interconnect/qcom,sm8150.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -52,6 +53,9 @@
dynamic-power-coefficient = <232>;
next-level-cache = <&L2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
+ operating-points-v2 = <&cpu0_opp_table>;
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>,
+ <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
power-domains = <&CPU_PD0>;
power-domain-names = "psci";
#cooling-cells = <2>;
@@ -73,6 +77,9 @@
dynamic-power-coefficient = <232>;
next-level-cache = <&L2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
+ operating-points-v2 = <&cpu0_opp_table>;
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>,
+ <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
power-domains = <&CPU_PD1>;
power-domain-names = "psci";
#cooling-cells = <2>;
@@ -92,6 +99,9 @@
dynamic-power-coefficient = <232>;
next-level-cache = <&L2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
+ operating-points-v2 = <&cpu0_opp_table>;
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>,
+ <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
power-domains = <&CPU_PD2>;
power-domain-names = "psci";
#cooling-cells = <2>;
@@ -110,6 +120,9 @@
dynamic-power-coefficient = <232>;
next-level-cache = <&L2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
+ operating-points-v2 = <&cpu0_opp_table>;
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>,
+ <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
power-domains = <&CPU_PD3>;
power-domain-names = "psci";
#cooling-cells = <2>;
@@ -128,6 +141,9 @@
dynamic-power-coefficient = <369>;
next-level-cache = <&L2_400>;
qcom,freq-domain = <&cpufreq_hw 1>;
+ operating-points-v2 = <&cpu4_opp_table>;
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>,
+ <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
power-domains = <&CPU_PD4>;
power-domain-names = "psci";
#cooling-cells = <2>;
@@ -146,6 +162,9 @@
dynamic-power-coefficient = <369>;
next-level-cache = <&L2_500>;
qcom,freq-domain = <&cpufreq_hw 1>;
+ operating-points-v2 = <&cpu4_opp_table>;
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>,
+ <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
power-domains = <&CPU_PD5>;
power-domain-names = "psci";
#cooling-cells = <2>;
@@ -164,6 +183,9 @@
dynamic-power-coefficient = <369>;
next-level-cache = <&L2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
+ operating-points-v2 = <&cpu4_opp_table>;
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>,
+ <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
power-domains = <&CPU_PD6>;
power-domain-names = "psci";
#cooling-cells = <2>;
@@ -182,6 +204,9 @@
dynamic-power-coefficient = <421>;
next-level-cache = <&L2_700>;
qcom,freq-domain = <&cpufreq_hw 2>;
+ operating-points-v2 = <&cpu7_opp_table>;
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>,
+ <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
power-domains = <&CPU_PD7>;
power-domain-names = "psci";
#cooling-cells = <2>;
@@ -264,6 +289,296 @@
};
};
+ cpu0_opp_table: cpu0_opp_table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ cpu0_opp1: opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-peak-kBps = <800000 9600000>;
+ };
+
+ cpu0_opp2: opp-403200000 {
+ opp-hz = /bits/ 64 <403200000>;
+ opp-peak-kBps = <800000 9600000>;
+ };
+
+ cpu0_opp3: opp-499200000 {
+ opp-hz = /bits/ 64 <499200000>;
+ opp-peak-kBps = <800000 12902400>;
+ };
+
+ cpu0_opp4: opp-576000000 {
+ opp-hz = /bits/ 64 <576000000>;
+ opp-peak-kBps = <800000 12902400>;
+ };
+
+ cpu0_opp5: opp-672000000 {
+ opp-hz = /bits/ 64 <672000000>;
+ opp-peak-kBps = <800000 15974400>;
+ };
+
+ cpu0_opp6: opp-768000000 {
+ opp-hz = /bits/ 64 <768000000>;
+ opp-peak-kBps = <1804000 19660800>;
+ };
+
+ cpu0_opp7: opp-844800000 {
+ opp-hz = /bits/ 64 <844800000>;
+ opp-peak-kBps = <1804000 19660800>;
+ };
+
+ cpu0_opp8: opp-940800000 {
+ opp-hz = /bits/ 64 <940800000>;
+ opp-peak-kBps = <1804000 22732800>;
+ };
+
+ cpu0_opp9: opp-1036800000 {
+ opp-hz = /bits/ 64 <1036800000>;
+ opp-peak-kBps = <1804000 22732800>;
+ };
+
+ cpu0_opp10: opp-1113600000 {
+ opp-hz = /bits/ 64 <1113600000>;
+ opp-peak-kBps = <2188000 25804800>;
+ };
+
+ cpu0_opp11: opp-1209600000 {
+ opp-hz = /bits/ 64 <1209600000>;
+ opp-peak-kBps = <2188000 31948800>;
+ };
+
+ cpu0_opp12: opp-1305600000 {
+ opp-hz = /bits/ 64 <1305600000>;
+ opp-peak-kBps = <3072000 31948800>;
+ };
+
+ cpu0_opp13: opp-1382400000 {
+ opp-hz = /bits/ 64 <1382400000>;
+ opp-peak-kBps = <3072000 31948800>;
+ };
+
+ cpu0_opp14: opp-1478400000 {
+ opp-hz = /bits/ 64 <1478400000>;
+ opp-peak-kBps = <3072000 31948800>;
+ };
+
+ cpu0_opp15: opp-1555200000 {
+ opp-hz = /bits/ 64 <1555200000>;
+ opp-peak-kBps = <3072000 40550400>;
+ };
+
+ cpu0_opp16: opp-1632000000 {
+ opp-hz = /bits/ 64 <1632000000>;
+ opp-peak-kBps = <3072000 40550400>;
+ };
+
+ cpu0_opp17: opp-1708800000 {
+ opp-hz = /bits/ 64 <1708800000>;
+ opp-peak-kBps = <3072000 43008000>;
+ };
+
+ cpu0_opp18: opp-1785600000 {
+ opp-hz = /bits/ 64 <1785600000>;
+ opp-peak-kBps = <3072000 43008000>;
+ };
+ };
+
+ cpu4_opp_table: cpu4_opp_table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ cpu4_opp1: opp-710400000 {
+ opp-hz = /bits/ 64 <710400000>;
+ opp-peak-kBps = <1804000 15974400>;
+ };
+
+ cpu4_opp2: opp-825600000 {
+ opp-hz = /bits/ 64 <825600000>;
+ opp-peak-kBps = <2188000 19660800>;
+ };
+
+ cpu4_opp3: opp-940800000 {
+ opp-hz = /bits/ 64 <940800000>;
+ opp-peak-kBps = <2188000 22732800>;
+ };
+
+ cpu4_opp4: opp-1056000000 {
+ opp-hz = /bits/ 64 <1056000000>;
+ opp-peak-kBps = <3072000 25804800>;
+ };
+
+ cpu4_opp5: opp-1171200000 {
+ opp-hz = /bits/ 64 <1171200000>;
+ opp-peak-kBps = <3072000 31948800>;
+ };
+
+ cpu4_opp6: opp-1286400000 {
+ opp-hz = /bits/ 64 <1286400000>;
+ opp-peak-kBps = <4068000 31948800>;
+ };
+
+ cpu4_opp7: opp-1401600000 {
+ opp-hz = /bits/ 64 <1401600000>;
+ opp-peak-kBps = <4068000 31948800>;
+ };
+
+ cpu4_opp8: opp-1497600000 {
+ opp-hz = /bits/ 64 <1497600000>;
+ opp-peak-kBps = <4068000 40550400>;
+ };
+
+ cpu4_opp9: opp-1612800000 {
+ opp-hz = /bits/ 64 <1612800000>;
+ opp-peak-kBps = <4068000 40550400>;
+ };
+
+ cpu4_opp10: opp-1708800000 {
+ opp-hz = /bits/ 64 <1708800000>;
+ opp-peak-kBps = <4068000 43008000>;
+ };
+
+ cpu4_opp11: opp-1804800000 {
+ opp-hz = /bits/ 64 <1804800000>;
+ opp-peak-kBps = <6220000 43008000>;
+ };
+
+ cpu4_opp12: opp-1920000000 {
+ opp-hz = /bits/ 64 <1920000000>;
+ opp-peak-kBps = <6220000 49152000>;
+ };
+
+ cpu4_opp13: opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-peak-kBps = <7216000 49152000>;
+ };
+
+ cpu4_opp14: opp-2131200000 {
+ opp-hz = /bits/ 64 <2131200000>;
+ opp-peak-kBps = <8368000 49152000>;
+ };
+
+ cpu4_opp15: opp-2227200000 {
+ opp-hz = /bits/ 64 <2227200000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+
+ cpu4_opp16: opp-2323200000 {
+ opp-hz = /bits/ 64 <2323200000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+
+ cpu4_opp17: opp-2419200000 {
+ opp-hz = /bits/ 64 <2419200000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+ };
+
+ cpu7_opp_table: cpu7_opp_table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ cpu7_opp1: opp-825600000 {
+ opp-hz = /bits/ 64 <825600000>;
+ opp-peak-kBps = <2188000 19660800>;
+ };
+
+ cpu7_opp2: opp-940800000 {
+ opp-hz = /bits/ 64 <940800000>;
+ opp-peak-kBps = <2188000 22732800>;
+ };
+
+ cpu7_opp3: opp-1056000000 {
+ opp-hz = /bits/ 64 <1056000000>;
+ opp-peak-kBps = <3072000 25804800>;
+ };
+
+ cpu7_opp4: opp-1171200000 {
+ opp-hz = /bits/ 64 <1171200000>;
+ opp-peak-kBps = <3072000 31948800>;
+ };
+
+ cpu7_opp5: opp-1286400000 {
+ opp-hz = /bits/ 64 <1286400000>;
+ opp-peak-kBps = <4068000 31948800>;
+ };
+
+ cpu7_opp6: opp-1401600000 {
+ opp-hz = /bits/ 64 <1401600000>;
+ opp-peak-kBps = <4068000 31948800>;
+ };
+
+ cpu7_opp7: opp-1497600000 {
+ opp-hz = /bits/ 64 <1497600000>;
+ opp-peak-kBps = <4068000 40550400>;
+ };
+
+ cpu7_opp8: opp-1612800000 {
+ opp-hz = /bits/ 64 <1612800000>;
+ opp-peak-kBps = <4068000 40550400>;
+ };
+
+ cpu7_opp9: opp-1708800000 {
+ opp-hz = /bits/ 64 <1708800000>;
+ opp-peak-kBps = <4068000 43008000>;
+ };
+
+ cpu7_opp10: opp-1804800000 {
+ opp-hz = /bits/ 64 <1804800000>;
+ opp-peak-kBps = <6220000 43008000>;
+ };
+
+ cpu7_opp11: opp-1920000000 {
+ opp-hz = /bits/ 64 <1920000000>;
+ opp-peak-kBps = <6220000 49152000>;
+ };
+
+ cpu7_opp12: opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-peak-kBps = <7216000 49152000>;
+ };
+
+ cpu7_opp13: opp-2131200000 {
+ opp-hz = /bits/ 64 <2131200000>;
+ opp-peak-kBps = <8368000 49152000>;
+ };
+
+ cpu7_opp14: opp-2227200000 {
+ opp-hz = /bits/ 64 <2227200000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+
+ cpu7_opp15: opp-2323200000 {
+ opp-hz = /bits/ 64 <2323200000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+
+ cpu7_opp16: opp-2419200000 {
+ opp-hz = /bits/ 64 <2419200000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+
+ cpu7_opp17: opp-2534400000 {
+ opp-hz = /bits/ 64 <2534400000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+
+ cpu7_opp18: opp-2649600000 {
+ opp-hz = /bits/ 64 <2649600000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+
+ cpu7_opp19: opp-2745600000 {
+ opp-hz = /bits/ 64 <2745600000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+
+ cpu7_opp20: opp-2841600000 {
+ opp-hz = /bits/ 64 <2841600000>;
+ opp-peak-kBps = <8368000 51609600>;
+ };
+ };
+
firmware {
scm: scm {
compatible = "qcom,scm-sm8150", "qcom,scm";
@@ -626,6 +941,21 @@
status = "disabled";
};
+ spi0: spi@880000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0x880000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi0_default>;
+ interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c1: i2c@884000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00884000 0 0x4000>;
@@ -639,6 +969,21 @@
status = "disabled";
};
+ spi1: spi@884000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0x884000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi1_default>;
+ interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c2: i2c@888000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00888000 0 0x4000>;
@@ -652,6 +997,21 @@
status = "disabled";
};
+ spi2: spi@888000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0x888000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi2_default>;
+ interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c3: i2c@88c000 {
compatible = "qcom,geni-i2c";
reg = <0 0x0088c000 0 0x4000>;
@@ -665,6 +1025,21 @@
status = "disabled";
};
+ spi3: spi@88c000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0x88c000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi3_default>;
+ interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c4: i2c@890000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00890000 0 0x4000>;
@@ -678,6 +1053,21 @@
status = "disabled";
};
+ spi4: spi@890000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0x890000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi4_default>;
+ interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c5: i2c@894000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00894000 0 0x4000>;
@@ -691,6 +1081,21 @@
status = "disabled";
};
+ spi5: spi@894000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0x894000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi5_default>;
+ interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c6: i2c@898000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00898000 0 0x4000>;
@@ -704,6 +1109,21 @@
status = "disabled";
};
+ spi6: spi@898000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0x898000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi6_default>;
+ interrupts = <GIC_SPI 607 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c7: i2c@89c000 {
compatible = "qcom,geni-i2c";
reg = <0 0x0089c000 0 0x4000>;
@@ -717,6 +1137,20 @@
status = "disabled";
};
+ spi7: spi@89c000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0x89c000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi7_default>;
+ interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
gpi_dma1: dma-controller@a00000 {
@@ -767,6 +1201,21 @@
status = "disabled";
};
+ spi8: spi@a80000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xa80000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi8_default>;
+ interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c9: i2c@a84000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00a84000 0 0x4000>;
@@ -780,6 +1229,21 @@
status = "disabled";
};
+ spi9: spi@a84000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xa84000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi9_default>;
+ interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c10: i2c@a88000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00a88000 0 0x4000>;
@@ -793,6 +1257,21 @@
status = "disabled";
};
+ spi10: spi@a88000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xa88000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi10_default>;
+ interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c11: i2c@a8c000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00a8c000 0 0x4000>;
@@ -806,6 +1285,21 @@
status = "disabled";
};
+ spi11: spi@a8c000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xa8c000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi11_default>;
+ interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
uart2: serial@a90000 {
compatible = "qcom,geni-debug-uart";
reg = <0x0 0x00a90000 0x0 0x4000>;
@@ -828,6 +1322,21 @@
status = "disabled";
};
+ spi12: spi@a90000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xa90000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi12_default>;
+ interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c16: i2c@94000 {
compatible = "qcom,geni-i2c";
reg = <0 0x0094000 0 0x4000>;
@@ -840,6 +1349,21 @@
#size-cells = <0>;
status = "disabled";
};
+
+ spi16: spi@a94000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xa94000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi16_default>;
+ interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
gpi_dma2: dma-controller@c00000 {
@@ -891,6 +1415,21 @@
status = "disabled";
};
+ spi17: spi@c80000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xc80000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi17_default>;
+ interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c18: i2c@c84000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00c84000 0 0x4000>;
@@ -904,6 +1443,21 @@
status = "disabled";
};
+ spi18: spi@c84000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xc84000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi18_default>;
+ interrupts = <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c19: i2c@c88000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00c88000 0 0x4000>;
@@ -917,6 +1471,21 @@
status = "disabled";
};
+ spi19: spi@c88000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xc88000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi19_default>;
+ interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c13: i2c@c8c000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00c8c000 0 0x4000>;
@@ -930,6 +1499,21 @@
status = "disabled";
};
+ spi13: spi@c8c000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xc8c000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi13_default>;
+ interrupts = <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c14: i2c@c90000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00c90000 0 0x4000>;
@@ -943,6 +1527,21 @@
status = "disabled";
};
+ spi14: spi@c90000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xc90000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi14_default>;
+ interrupts = <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c15: i2c@c94000 {
compatible = "qcom,geni-i2c";
reg = <0 0x00c94000 0 0x4000>;
@@ -955,6 +1554,21 @@
#size-cells = <0>;
status = "disabled";
};
+
+ spi15: spi@c94000 {
+ compatible = "qcom,geni-spi";
+ reg = <0 0xc94000 0 0x4000>;
+ reg-names = "se";
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP2_S5_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi15_default>;
+ interrupts = <GIC_SPI 587 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
config_noc: interconnect@1500000 {
@@ -1016,7 +1630,9 @@
ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sm8150-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
- reg = <0 0x01d84000 0 0x2500>;
+ reg = <0 0x01d84000 0 0x2500>,
+ <0 0x01d90000 0 0x8000>;
+ reg-names = "std", "ice";
interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
phys = <&ufs_mem_phy_lanes>;
phy-names = "ufsphy";
@@ -1035,7 +1651,8 @@
"ref_clk",
"tx_lane0_sync_clk",
"rx_lane0_sync_clk",
- "rx_lane1_sync_clk";
+ "rx_lane1_sync_clk",
+ "ice_core_clk";
clocks =
<&gcc GCC_UFS_PHY_AXI_CLK>,
<&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>,
@@ -1044,7 +1661,8 @@
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>,
<&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>,
- <&gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>;
+ <&gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>,
+ <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
freq-table-hz =
<37500000 300000000>,
<0 0>,
@@ -1053,7 +1671,8 @@
<0 0>,
<0 0>,
<0 0>,
- <0 0>;
+ <0 0>,
+ <0 300000000>;
status = "disabled";
};
@@ -1296,6 +1915,13 @@
};
};
+ qup_spi0_default: qup-spi0-default {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "qup0";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c1_default: qup-i2c1-default {
mux {
pins = "gpio114", "gpio115";
@@ -1309,6 +1935,13 @@
};
};
+ qup_spi1_default: qup-spi1-default {
+ pins = "gpio114", "gpio115", "gpio116", "gpio117";
+ function = "qup1";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c2_default: qup-i2c2-default {
mux {
pins = "gpio126", "gpio127";
@@ -1322,6 +1955,13 @@
};
};
+ qup_spi2_default: qup-spi2-default {
+ pins = "gpio126", "gpio127", "gpio128", "gpio129";
+ function = "qup2";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c3_default: qup-i2c3-default {
mux {
pins = "gpio144", "gpio145";
@@ -1335,6 +1975,13 @@
};
};
+ qup_spi3_default: qup-spi3-default {
+ pins = "gpio144", "gpio145", "gpio146", "gpio147";
+ function = "qup3";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c4_default: qup-i2c4-default {
mux {
pins = "gpio51", "gpio52";
@@ -1348,6 +1995,13 @@
};
};
+ qup_spi4_default: qup-spi4-default {
+ pins = "gpio51", "gpio52", "gpio53", "gpio54";
+ function = "qup4";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c5_default: qup-i2c5-default {
mux {
pins = "gpio121", "gpio122";
@@ -1361,6 +2015,13 @@
};
};
+ qup_spi5_default: qup-spi5-default {
+ pins = "gpio119", "gpio120", "gpio121", "gpio122";
+ function = "qup5";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c6_default: qup-i2c6-default {
mux {
pins = "gpio6", "gpio7";
@@ -1374,6 +2035,13 @@
};
};
+ qup_spi6_default: qup-spi6_default {
+ pins = "gpio4", "gpio5", "gpio6", "gpio7";
+ function = "qup6";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c7_default: qup-i2c7-default {
mux {
pins = "gpio98", "gpio99";
@@ -1387,6 +2055,13 @@
};
};
+ qup_spi7_default: qup-spi7_default {
+ pins = "gpio98", "gpio99", "gpio100", "gpio101";
+ function = "qup7";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c8_default: qup-i2c8-default {
mux {
pins = "gpio88", "gpio89";
@@ -1400,6 +2075,13 @@
};
};
+ qup_spi8_default: qup-spi8-default {
+ pins = "gpio88", "gpio89", "gpio90", "gpio91";
+ function = "qup8";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c9_default: qup-i2c9-default {
mux {
pins = "gpio39", "gpio40";
@@ -1413,6 +2095,13 @@
};
};
+ qup_spi9_default: qup-spi9-default {
+ pins = "gpio39", "gpio40", "gpio41", "gpio42";
+ function = "qup9";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c10_default: qup-i2c10-default {
mux {
pins = "gpio9", "gpio10";
@@ -1426,6 +2115,13 @@
};
};
+ qup_spi10_default: qup-spi10-default {
+ pins = "gpio9", "gpio10", "gpio11", "gpio12";
+ function = "qup10";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c11_default: qup-i2c11-default {
mux {
pins = "gpio94", "gpio95";
@@ -1439,6 +2135,13 @@
};
};
+ qup_spi11_default: qup-spi11-default {
+ pins = "gpio92", "gpio93", "gpio94", "gpio95";
+ function = "qup11";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c12_default: qup-i2c12-default {
mux {
pins = "gpio83", "gpio84";
@@ -1452,6 +2155,13 @@
};
};
+ qup_spi12_default: qup-spi12-default {
+ pins = "gpio83", "gpio84", "gpio85", "gpio86";
+ function = "qup12";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c13_default: qup-i2c13-default {
mux {
pins = "gpio43", "gpio44";
@@ -1465,6 +2175,13 @@
};
};
+ qup_spi13_default: qup-spi13-default {
+ pins = "gpio43", "gpio44", "gpio45", "gpio46";
+ function = "qup13";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c14_default: qup-i2c14-default {
mux {
pins = "gpio47", "gpio48";
@@ -1478,6 +2195,13 @@
};
};
+ qup_spi14_default: qup-spi14-default {
+ pins = "gpio47", "gpio48", "gpio49", "gpio50";
+ function = "qup14";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c15_default: qup-i2c15-default {
mux {
pins = "gpio27", "gpio28";
@@ -1491,6 +2215,13 @@
};
};
+ qup_spi15_default: qup-spi15-default {
+ pins = "gpio27", "gpio28", "gpio29", "gpio30";
+ function = "qup15";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c16_default: qup-i2c16-default {
mux {
pins = "gpio86", "gpio85";
@@ -1504,6 +2235,13 @@
};
};
+ qup_spi16_default: qup-spi16-default {
+ pins = "gpio83", "gpio84", "gpio85", "gpio86";
+ function = "qup16";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c17_default: qup-i2c17-default {
mux {
pins = "gpio55", "gpio56";
@@ -1517,6 +2255,13 @@
};
};
+ qup_spi17_default: qup-spi17-default {
+ pins = "gpio55", "gpio56", "gpio57", "gpio58";
+ function = "qup17";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c18_default: qup-i2c18-default {
mux {
pins = "gpio23", "gpio24";
@@ -1530,6 +2275,13 @@
};
};
+ qup_spi18_default: qup-spi18-default {
+ pins = "gpio23", "gpio24", "gpio25", "gpio26";
+ function = "qup18";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
qup_i2c19_default: qup-i2c19-default {
mux {
pins = "gpio57", "gpio58";
@@ -1542,6 +2294,13 @@
bias-disable;
};
};
+
+ qup_spi19_default: qup-spi19-default {
+ pins = "gpio55", "gpio56", "gpio57", "gpio58";
+ function = "qup19";
+ drive-strength = <6>;
+ bias-disable;
+ };
};
remoteproc_mpss: remoteproc@4080000 {
@@ -2266,20 +3025,6 @@
};
};
- dc_noc: interconnect@9160000 {
- compatible = "qcom,sm8150-dc-noc";
- reg = <0 0x09160000 0 0x3200>;
- #interconnect-cells = <1>;
- qcom,bcm-voters = <&apps_bcm_voter>;
- };
-
- gem_noc: interconnect@9680000 {
- compatible = "qcom,sm8150-gem-noc";
- reg = <0 0x09680000 0 0x3e200>;
- #interconnect-cells = <1>;
- qcom,bcm-voters = <&apps_bcm_voter>;
- };
-
usb_2_qmpphy: phy@88eb000 {
compatible = "qcom,sm8150-qmp-usb3-uni-phy";
reg = <0 0x088eb000 0 0x200>;
@@ -2311,6 +3056,20 @@
};
};
+ dc_noc: interconnect@9160000 {
+ compatible = "qcom,sm8150-dc-noc";
+ reg = <0 0x09160000 0 0x3200>;
+ #interconnect-cells = <1>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
+ gem_noc: interconnect@9680000 {
+ compatible = "qcom,sm8150-gem-noc";
+ reg = <0 0x09680000 0 0x3e200>;
+ #interconnect-cells = <1>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
usb_1: usb@a6f8800 {
compatible = "qcom,sm8150-dwc3", "qcom,dwc3";
reg = <0 0x0a6f8800 0 0x400>;
@@ -2389,7 +3148,7 @@
resets = <&gcc GCC_USB30_SEC_BCR>;
- usb_2_dwc3: dwc3@a800000 {
+ usb_2_dwc3: usb@a800000 {
compatible = "snps,dwc3";
reg = <0 0x0a800000 0 0xcd00>;
interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index 4798368b02ef..8c15d9fed08f 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -561,6 +561,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c14_default>;
interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma2 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -572,10 +575,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>;
interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma2 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -587,6 +593,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c15_default>;
interrupts = <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma2 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -598,10 +607,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>;
interrupts = <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma2 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -613,6 +625,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c16_default>;
interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma2 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -624,10 +639,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>;
interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma2 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -639,6 +657,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c17_default>;
interrupts = <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma2 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -650,10 +671,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>;
interrupts = <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma2 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -678,6 +702,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c18_default>;
interrupts = <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma2 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -689,10 +716,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>;
interrupts = <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma2 0 4 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 4 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -717,6 +747,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c19_default>;
interrupts = <GIC_SPI 587 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma2 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -728,10 +761,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP2_S5_CLK>;
interrupts = <GIC_SPI 587 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma2 0 5 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 5 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
};
@@ -779,6 +815,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c0_default>;
interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -790,10 +829,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -805,6 +847,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c1_default>;
interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -816,10 +861,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -831,6 +879,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c2_default>;
interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -842,10 +893,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -870,6 +924,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c3_default>;
interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -881,10 +938,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma0 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -896,6 +956,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c4_default>;
interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -907,10 +970,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma0 0 4 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 4 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -922,6 +988,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c5_default>;
interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -933,10 +1002,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 5 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -948,6 +1020,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c6_default>;
interrupts = <GIC_SPI 607 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 6 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 6 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -959,10 +1034,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
interrupts = <GIC_SPI 607 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma0 0 6 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 6 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -987,6 +1065,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c7_default>;
interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 7 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 7 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -998,10 +1079,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma0 0 7 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 7 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
};
@@ -1046,6 +1130,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c8_default>;
interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1057,10 +1144,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma1 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -1072,6 +1162,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c9_default>;
interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1083,10 +1176,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma1 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -1098,6 +1194,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c10_default>;
interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1109,10 +1208,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma1 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -1124,6 +1226,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c11_default>;
interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1135,10 +1240,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma1 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -1150,6 +1258,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c12_default>;
interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1161,10 +1272,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma1 0 4 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 4 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -1189,6 +1303,9 @@
pinctrl-names = "default";
pinctrl-0 = <&qup_i2c13_default>;
interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1200,10 +1317,13 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>;
interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dmas = <&gpi_dma1 0 5 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 5 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
power-domains = <&rpmhpd SM8250_CX>;
operating-points-v2 = <&qup_opp_table>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
};
@@ -2210,7 +2330,7 @@
<&gcc GCC_USB3_PHY_SEC_BCR>;
reset-names = "phy", "common";
- usb_2_ssphy: lane@88eb200 {
+ usb_2_ssphy: lanes@88eb200 {
reg = <0 0x088eb200 0 0x200>,
<0 0x088eb400 0 0x200>,
<0 0x088eb800 0 0x800>;
@@ -2321,7 +2441,7 @@
resets = <&gcc GCC_USB30_PRIM_BCR>;
- usb_1_dwc3: dwc3@a600000 {
+ usb_1_dwc3: usb@a600000 {
compatible = "snps,dwc3";
reg = <0 0x0a600000 0 0xcd00>;
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
@@ -2372,7 +2492,7 @@
resets = <&gcc GCC_USB30_SEC_BCR>;
- usb_2_dwc3: dwc3@a800000 {
+ usb_2_dwc3: usb@a800000 {
compatible = "snps,dwc3";
reg = <0 0x0a800000 0 0xcd00>;
interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
@@ -2470,10 +2590,9 @@
power-domains = <&dispcc MDSS_GDSC>;
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
- <&gcc GCC_DISP_HF_AXI_CLK>,
<&gcc GCC_DISP_SF_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>;
- clock-names = "iface", "bus", "nrt_bus", "core";
+ clock-names = "iface", "nrt_bus", "core";
assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>;
assigned-clock-rates = <460000000>;
@@ -2578,6 +2697,9 @@
"iface",
"bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd SM8250_MMCX>;
@@ -2648,6 +2770,9 @@
"iface",
"bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>;
+ assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>;
+
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd SM8250_MMCX>;
@@ -3955,7 +4080,7 @@
};
};
- epss_l3: interconnect@18591000 {
+ epss_l3: interconnect@18590000 {
compatible = "qcom,sm8250-epss-l3";
reg = <0 0x18590000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
index f23a0cf3f7b7..56093e260ddf 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
@@ -219,7 +219,7 @@
firmware-name = "qcom/sm8350/modem.mbn";
};
-&qupv3_id_1 {
+&qupv3_id_0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8350-mtp.dts b/arch/arm64/boot/dts/qcom/sm8350-mtp.dts
index 93740444dd1e..bd95009c1875 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8350-mtp.dts
@@ -286,7 +286,7 @@
firmware-name = "qcom/sm8350/modem.mbn";
};
-&qupv3_id_1 {
+&qupv3_id_0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi
index 0d16392bb976..e91cd8a5e535 100644
--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
@@ -456,7 +456,7 @@
#mbox-cells = <2>;
};
- qupv3_id_1: geniqup@9c0000 {
+ qupv3_id_0: geniqup@9c0000 {
compatible = "qcom,geni-se-qup";
reg = <0x0 0x009c0000 0x0 0x6000>;
clock-names = "m-ahb", "s-ahb";
@@ -481,6 +481,31 @@
};
};
+ qupv3_id_1: geniqup@ac0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0x0 0x00ac0000 0x0 0x6000>;
+ clock-names = "m-ahb", "s-ahb";
+ clocks = <&gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+ <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ i2c13: i2c@a94000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a94000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c13_default_state>;
+ interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ };
+
apps_smmu: iommu@15000000 {
compatible = "qcom,sm8350-smmu-500", "arm,mmu-500";
reg = <0 0x15000000 0 0x100000>;
@@ -666,12 +691,10 @@
clocks = <&rpmhcc RPMH_IPA_CLK>;
clock-names = "core";
- interconnects = <&aggre2_noc MASTER_IPA &gem_noc SLAVE_LLCC>,
- <&mc_virt MASTER_LLCC &mc_virt SLAVE_EBI1>,
+ interconnects = <&aggre2_noc MASTER_IPA &mc_virt SLAVE_EBI1>,
<&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_IPA_CFG>;
- interconnect-names = "ipa_to_llcc",
- "llcc_to_ebi1",
- "appss_to_ipa";
+ interconnect-names = "memory",
+ "config";
qcom,smem-states = <&ipa_smp2p_out 0>,
<&ipa_smp2p_out 1>;
@@ -801,6 +824,7 @@
interrupt-controller;
#interrupt-cells = <2>;
gpio-ranges = <&tlmm 0 0 204>;
+ wakeup-parent = <&pdc>;
qup_uart3_default_state: qup-uart3-default-state {
rx {
@@ -812,6 +836,19 @@
function = "qup3";
};
};
+
+ qup_i2c13_default_state: qup-i2c13-default-state {
+ mux {
+ pins = "gpio0", "gpio1";
+ function = "qup13";
+ };
+
+ config {
+ pins = "gpio0", "gpio1";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
};
rng: rng@10d3000 {
@@ -1273,7 +1310,7 @@
resets = <&gcc GCC_USB30_PRIM_BCR>;
- usb_1_dwc3: dwc3@a600000 {
+ usb_1_dwc3: usb@a600000 {
compatible = "snps,dwc3";
reg = <0 0x0a600000 0 0xcd00>;
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
@@ -1317,7 +1354,7 @@
resets = <&gcc GCC_USB30_SEC_BCR>;
- usb_2_dwc3: dwc3@a800000 {
+ usb_2_dwc3: usb@a800000 {
compatible = "snps,dwc3";
reg = <0 0x0a800000 0 0xcd00>;
interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
index 68e30e26564b..15a53b513966 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
@@ -63,4 +63,12 @@ dtb-$(CONFIG_ARCH_R8A77995) += r8a77995-draak.dtb
dtb-$(CONFIG_ARCH_R8A779A0) += r8a779a0-falcon.dtb
+dtb-$(CONFIG_ARCH_R8A77951) += r8a779m1-salvator-xs.dtb
+dtb-$(CONFIG_ARCH_R8A77951) += r8a779m1-ulcb.dtb
+dtb-$(CONFIG_ARCH_R8A77951) += r8a779m1-ulcb-kf.dtb
+
+dtb-$(CONFIG_ARCH_R8A77961) += r8a779m3-salvator-xs.dtb
+dtb-$(CONFIG_ARCH_R8A77961) += r8a779m3-ulcb.dtb
+dtb-$(CONFIG_ARCH_R8A77961) += r8a779m3-ulcb-kf.dtb
+
dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044l2-smarc.dtb
diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
index e3c8b2fe143e..2692cc64bff6 100644
--- a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
+++ b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
@@ -197,6 +197,14 @@
compatible = "audio-graph-card";
label = "rcar-sound";
dais = <&rsnd_port0>, <&rsnd_port1>;
+ widgets = "Microphone", "Mic Jack",
+ "Line", "Line In Jack",
+ "Headphone", "Headphone Jack";
+ mic-det-gpio = <&gpio0 2 GPIO_ACTIVE_LOW>;
+ routing = "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "IN3R", "MICBIAS",
+ "Mic Jack", "IN3R";
};
vccq_sdhi0: regulator-vccq-sdhi0 {
diff --git a/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi b/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
index 202c4fc88bd5..dde3a07bc417 100644
--- a/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
+++ b/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
@@ -20,6 +20,7 @@
pinctrl-names = "default";
phy-handle = <&phy0>;
tx-internal-delay-ps = <2000>;
+ rx-internal-delay-ps = <1800>;
status = "okay";
phy0: ethernet-phy@0 {
diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
index 78c121a89f11..6f4fffacfca2 100644
--- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
@@ -25,7 +25,7 @@
i2c4 = &i2c4;
i2c5 = &i2c5;
i2c6 = &i2c6;
- i2c7 = &i2c_dvfs;
+ i2c7 = &iic_pmic;
};
/*
@@ -715,7 +715,7 @@
status = "disabled";
};
- i2c_dvfs: i2c@e60b0000 {
+ iic_pmic: i2c@e60b0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,iic-r8a774a1",
diff --git a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
index 28c612ce49c0..0f7bdfc90a0d 100644
--- a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi
@@ -588,7 +588,7 @@
status = "disabled";
};
- i2c_dvfs: i2c@e60b0000 {
+ iic_pmic: i2c@e60b0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,iic-r8a774b1",
diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
index a5d4dce8476d..d597772c4c37 100644
--- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
@@ -574,11 +574,13 @@
status = "disabled";
};
- i2c_dvfs: i2c@e60b0000 {
+ iic_pmic: i2c@e60b0000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "renesas,iic-r8a774c0";
- reg = <0 0xe60b0000 0 0x15>;
+ compatible = "renesas,iic-r8a774c0",
+ "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 R8A774C0_PD_ALWAYS_ON>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77950-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a77950-salvator-x.dts
index 3e3b954a4a9d..c6ca61a8ed40 100644
--- a/arch/arm64/boot/dts/renesas/r8a77950-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77950-salvator-x.dts
@@ -47,76 +47,3 @@
clock-names = "du.0", "du.1", "du.2", "du.3",
"dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3";
};
-
-&ehci2 {
- status = "okay";
-};
-
-&hdmi1 {
- status = "okay";
-
- ports {
- port@1 {
- reg = <1>;
- rcar_dw_hdmi1_out: endpoint {
- remote-endpoint = <&hdmi1_con>;
- };
- };
- port@2 {
- reg = <2>;
- dw_hdmi1_snd_in: endpoint {
- remote-endpoint = <&rsnd_endpoint2>;
- };
- };
- };
-};
-
-&hdmi1_con {
- remote-endpoint = <&rcar_dw_hdmi1_out>;
-};
-
-&ohci2 {
- status = "okay";
-};
-
-&pfc {
- usb2_pins: usb2 {
- groups = "usb2";
- function = "usb2";
- };
-};
-
-&rcar_sound {
- ports {
- /* rsnd_port0/1 are described in salvator-common.dtsi */
- rsnd_port2: port@2 {
- reg = <2>;
- rsnd_endpoint2: endpoint {
- remote-endpoint = <&dw_hdmi1_snd_in>;
-
- dai-format = "i2s";
- bitclock-master = <&rsnd_endpoint2>;
- frame-master = <&rsnd_endpoint2>;
-
- playback = <&ssi3>;
- };
- };
- };
-};
-
-&sata {
- status = "okay";
-};
-
-&sound_card {
- dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1 /* HDMI0 */
- &rsnd_port2>; /* HDMI1 */
-};
-
-&usb2_phy2 {
- pinctrl-0 = <&usb2_pins>;
- pinctrl-names = "default";
-
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/renesas/r8a77950-ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a77950-ulcb-kf.dts
index dcaaf12cec40..85f008ef63de 100644
--- a/arch/arm64/boot/dts/renesas/r8a77950-ulcb-kf.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77950-ulcb-kf.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the H3ULCB Kingfisher board
+ * Device Tree Source for the H3ULCB Kingfisher board with R-Car H3 ES1.x
*
* Copyright (C) 2017 Renesas Electronics Corp.
* Copyright (C) 2017 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77950-ulcb.dts b/arch/arm64/boot/dts/renesas/r8a77950-ulcb.dts
index 38a6d6a108d4..5340579931e3 100644
--- a/arch/arm64/boot/dts/renesas/r8a77950-ulcb.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77950-ulcb.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) board
+ * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) board with R-Car H3 ES1.x
*
* Copyright (C) 2016 Renesas Electronics Corp.
* Copyright (C) 2016 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77950.dtsi b/arch/arm64/boot/dts/renesas/r8a77950.dtsi
index b643d3079db1..57eb88177e92 100644
--- a/arch/arm64/boot/dts/renesas/r8a77950.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77950.dtsi
@@ -7,6 +7,8 @@
#include "r8a77951.dtsi"
+#undef SOC_HAS_USB2_CH3
+
&audma0 {
iommus = <&ipmmu_mp1 0>, <&ipmmu_mp1 1>,
<&ipmmu_mp1 2>, <&ipmmu_mp1 3>,
diff --git a/arch/arm64/boot/dts/renesas/r8a77951-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a77951-salvator-x.dts
index cf2165bdf625..d8e655ba81bd 100644
--- a/arch/arm64/boot/dts/renesas/r8a77951-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77951-salvator-x.dts
@@ -47,76 +47,3 @@
clock-names = "du.0", "du.1", "du.2", "du.3",
"dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3";
};
-
-&ehci2 {
- status = "okay";
-};
-
-&hdmi1 {
- status = "okay";
-
- ports {
- port@1 {
- reg = <1>;
- rcar_dw_hdmi1_out: endpoint {
- remote-endpoint = <&hdmi1_con>;
- };
- };
- port@2 {
- reg = <2>;
- dw_hdmi1_snd_in: endpoint {
- remote-endpoint = <&rsnd_endpoint2>;
- };
- };
- };
-};
-
-&hdmi1_con {
- remote-endpoint = <&rcar_dw_hdmi1_out>;
-};
-
-&ohci2 {
- status = "okay";
-};
-
-&pfc {
- usb2_pins: usb2 {
- groups = "usb2";
- function = "usb2";
- };
-};
-
-&rcar_sound {
- ports {
- /* rsnd_port0/1 are described in salvator-common.dtsi */
- rsnd_port2: port@2 {
- reg = <2>;
- rsnd_endpoint2: endpoint {
- remote-endpoint = <&dw_hdmi1_snd_in>;
-
- dai-format = "i2s";
- bitclock-master = <&rsnd_endpoint2>;
- frame-master = <&rsnd_endpoint2>;
-
- playback = <&ssi3>;
- };
- };
- };
-};
-
-&sata {
- status = "okay";
-};
-
-&sound_card {
- dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1 /* HDMI0 */
- &rsnd_port2>; /* HDMI1 */
-};
-
-&usb2_phy2 {
- pinctrl-0 = <&usb2_pins>;
- pinctrl-names = "default";
-
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/renesas/r8a77951-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a77951-salvator-xs.dts
index 37202fcdc35b..7f9fa842f01e 100644
--- a/arch/arm64/boot/dts/renesas/r8a77951-salvator-xs.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77951-salvator-xs.dts
@@ -47,125 +47,3 @@
clock-names = "du.0", "du.1", "du.2", "du.3",
"dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3";
};
-
-&ehci2 {
- status = "okay";
-};
-
-&ehci3 {
- dr_mode = "otg";
- status = "okay";
-};
-
-&hdmi1 {
- status = "okay";
-
- ports {
- port@1 {
- reg = <1>;
- rcar_dw_hdmi1_out: endpoint {
- remote-endpoint = <&hdmi1_con>;
- };
- };
- port@2 {
- reg = <2>;
- dw_hdmi1_snd_in: endpoint {
- remote-endpoint = <&rsnd_endpoint2>;
- };
- };
- };
-};
-
-&hdmi1_con {
- remote-endpoint = <&rcar_dw_hdmi1_out>;
-};
-
-&hsusb3 {
- dr_mode = "otg";
- status = "okay";
-};
-
-&ohci2 {
- status = "okay";
-};
-
-&ohci3 {
- dr_mode = "otg";
- status = "okay";
-};
-
-&pca9654 {
- pcie-sata-switch-hog {
- gpio-hog;
- gpios = <7 GPIO_ACTIVE_HIGH>;
- output-low; /* enable SATA by default */
- line-name = "PCIE/SATA switch";
- };
-};
-
-&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
- * r8a77951 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";
- };
-};
-
-&rcar_sound {
- ports {
- /* rsnd_port0/1 are described in salvator-common.dtsi */
- rsnd_port2: port@2 {
- reg = <2>;
- rsnd_endpoint2: endpoint {
- remote-endpoint = <&dw_hdmi1_snd_in>;
-
- dai-format = "i2s";
- bitclock-master = <&rsnd_endpoint2>;
- frame-master = <&rsnd_endpoint2>;
-
- playback = <&ssi3>;
- };
- };
- };
-};
-
-/* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */
-&sata {
- status = "okay";
-};
-
-&sound_card {
- dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1 /* HDMI0 */
- &rsnd_port2>; /* HDMI1 */
-};
-
-&usb2_phy2 {
- pinctrl-0 = <&usb2_pins>;
- pinctrl-names = "default";
-
- status = "okay";
-};
-
-&usb2_phy3 {
- pinctrl-0 = <&usb2_ch3_pins>;
- pinctrl-names = "default";
-
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/renesas/r8a77951-ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a77951-ulcb-kf.dts
index 11f943a67703..2e58a27aa276 100644
--- a/arch/arm64/boot/dts/renesas/r8a77951-ulcb-kf.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77951-ulcb-kf.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the H3ULCB Kingfisher board
+ * Device Tree Source for the H3ULCB Kingfisher board with R-Car H3 ES2.0+
*
* Copyright (C) 2017 Renesas Electronics Corp.
* Copyright (C) 2017 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77951-ulcb.dts b/arch/arm64/boot/dts/renesas/r8a77951-ulcb.dts
index 8ad8f2a53977..06d4e948eb0f 100644
--- a/arch/arm64/boot/dts/renesas/r8a77951-ulcb.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77951-ulcb.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) board
+ * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) board with R-Car H3 ES2.0+
*
* Copyright (C) 2016 Renesas Electronics Corp.
* Copyright (C) 2016 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77951.dtsi b/arch/arm64/boot/dts/renesas/r8a77951.dtsi
index 2e4c18b8eee4..1768a3e6bb8d 100644
--- a/arch/arm64/boot/dts/renesas/r8a77951.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77951.dtsi
@@ -11,6 +11,11 @@
#define CPG_AUDIO_CLK_I R8A7795_CLK_S0D4
+#define SOC_HAS_HDMI1
+#define SOC_HAS_SATA
+#define SOC_HAS_USB2_CH2
+#define SOC_HAS_USB2_CH3
+
/ {
compatible = "renesas,r8a7795";
#address-cells = <2>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77960-ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a77960-ulcb-kf.dts
index 2151c37d77a6..02d61360692c 100644
--- a/arch/arm64/boot/dts/renesas/r8a77960-ulcb-kf.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77960-ulcb-kf.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the M3ULCB Kingfisher board
+ * Device Tree Source for the M3ULCB Kingfisher board with R-Car M3-W
*
* Copyright (C) 2017 Renesas Electronics Corp.
* Copyright (C) 2017 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77960-ulcb.dts b/arch/arm64/boot/dts/renesas/r8a77960-ulcb.dts
index d041042a5619..4bfeb1df0488 100644
--- a/arch/arm64/boot/dts/renesas/r8a77960-ulcb.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77960-ulcb.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the M3ULCB (R-Car Starter Kit Pro) board
+ * Device Tree Source for the M3ULCB (R-Car Starter Kit Pro) board with R-Car M3-W
*
* Copyright (C) 2016 Renesas Electronics Corp.
* Copyright (C) 2016 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77961-ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a77961-ulcb-kf.dts
index 6ec958348eb0..d66eb27ee8c4 100644
--- a/arch/arm64/boot/dts/renesas/r8a77961-ulcb-kf.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77961-ulcb-kf.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the M3ULCB Kingfisher board
+ * Device Tree Source for the M3ULCB Kingfisher board with R-Car M3-W+
*
* Copyright (C) 2020 Eugeniu Rosca <rosca.eugeniu@gmail.com>
*/
diff --git a/arch/arm64/boot/dts/renesas/r8a77961-ulcb.dts b/arch/arm64/boot/dts/renesas/r8a77961-ulcb.dts
index 294a055f117e..70cf926667a6 100644
--- a/arch/arm64/boot/dts/renesas/r8a77961-ulcb.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77961-ulcb.dts
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the M3ULCB (R-Car Starter Kit Pro) board with R-Car
- * M3-W+
+ * Device Tree Source for the M3ULCB (R-Car Starter Kit Pro) board with R-Car M3-W+
*
* Copyright (C) 2020 Renesas Electronics Corp.
*/
diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi b/arch/arm64/boot/dts/renesas/r8a77961.dtsi
index 91b501e0121e..041473aa5cd0 100644
--- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi
@@ -958,6 +958,14 @@
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>;
};
dmac1: dma-controller@e7300000 {
@@ -992,6 +1000,14 @@
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>;
};
dmac2: dma-controller@e7310000 {
@@ -1026,6 +1042,14 @@
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: iommu@e6740000 {
@@ -1160,6 +1184,7 @@
phy-mode = "rgmii";
rx-internal-delay-ps = <0>;
tx-internal-delay-ps = <0>;
+ iommus = <&ipmmu_ds0 16>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -2280,6 +2305,7 @@
max-frequency = <200000000>;
power-domains = <&sysc R8A77961_PD_ALWAYS_ON>;
resets = <&cpg 314>;
+ iommus = <&ipmmu_ds1 32>;
status = "disabled";
};
@@ -2292,6 +2318,7 @@
max-frequency = <200000000>;
power-domains = <&sysc R8A77961_PD_ALWAYS_ON>;
resets = <&cpg 313>;
+ iommus = <&ipmmu_ds1 33>;
status = "disabled";
};
@@ -2304,6 +2331,7 @@
max-frequency = <200000000>;
power-domains = <&sysc R8A77961_PD_ALWAYS_ON>;
resets = <&cpg 312>;
+ iommus = <&ipmmu_ds1 34>;
status = "disabled";
};
@@ -2316,6 +2344,7 @@
max-frequency = <200000000>;
power-domains = <&sysc R8A77961_PD_ALWAYS_ON>;
resets = <&cpg 311>;
+ iommus = <&ipmmu_ds1 35>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
index 729756c24c74..a1d3c8d531cf 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
@@ -30,17 +30,3 @@
clock-names = "du.0", "du.1", "du.3",
"dclkin.0", "dclkin.1", "dclkin.3";
};
-
-&pca9654 {
- pcie-sata-switch-hog {
- gpio-hog;
- gpios = <7 GPIO_ACTIVE_HIGH>;
- output-low; /* enable SATA by default */
- line-name = "PCIE/SATA switch";
- };
-};
-
-/* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */
-&sata {
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/renesas/r8a77965-ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a77965-ulcb-kf.dts
index 12aa08fd6fd8..a601968c5727 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965-ulcb-kf.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77965-ulcb-kf.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the M3NULCB Kingfisher board
+ * Device Tree Source for the M3NULCB Kingfisher board with R-Car M3-N
*
* Copyright (C) 2018 Renesas Electronics Corp.
* Copyright (C) 2018 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77965-ulcb.dts b/arch/arm64/boot/dts/renesas/r8a77965-ulcb.dts
index 964078b6cc49..71704b67a20e 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965-ulcb.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77965-ulcb.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the M3NULCB (R-Car Starter Kit Pro) board
+ * Device Tree Source for the M3NULCB (R-Car Starter Kit Pro) board with R-Car M3-N
*
* Copyright (C) 2018 Renesas Electronics Corp.
* Copyright (C) 2018 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
index ad69da362a72..08df75606430 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
@@ -14,6 +14,8 @@
#define CPG_AUDIO_CLK_I R8A77965_CLK_S0D4
+#define SOC_HAS_SATA
+
/ {
compatible = "renesas,r8a77965";
#address-cells = <2>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
index 5c84681703ed..d24da54f312b 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the Eagle board
+ * Device Tree Source for the Eagle board with R-Car V3M
*
* Copyright (C) 2016-2017 Renesas Electronics Corp.
* Copyright (C) 2017 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
index 7bde0a549c09..edf7f2a2f958 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the Condor board
+ * Device Tree Source for the Condor board with R-Car V3H
*
* Copyright (C) 2018 Renesas Electronics Corp.
* Copyright (C) 2018 Cogent Embedded, Inc.
diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
index 4715e4a4abe0..9c7146084ea1 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the ebisu board
+ * Device Tree Source for the Ebisu board with R-Car E3
*
* Copyright (C) 2018 Renesas Electronics Corp.
*/
@@ -8,6 +8,7 @@
/dts-v1/;
#include "r8a77990.dtsi"
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
/ {
model = "Renesas Ebisu board based on r8a77990";
@@ -80,6 +81,42 @@
};
};
+ keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&keys_pins>;
+ pinctrl-names = "default";
+
+ key-1 {
+ gpios = <&gpio5 10 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_1>;
+ label = "SW4-1";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ key-2 {
+ gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_2>;
+ label = "SW4-2";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ key-3 {
+ gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_3>;
+ label = "SW4-3";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ key-4 {
+ gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_4>;
+ label = "SW4-4";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ };
+
lvds-decoder {
compatible = "thine,thc63lvd1024";
vcc-supply = <&reg_3p3v>;
@@ -473,6 +510,12 @@
rohm,ddr-backup-power = <0x1>;
rohm,rstbmode-level;
};
+
+ eeprom@50 {
+ compatible = "rohm,br24t01", "atmel,24c01";
+ reg = <0x50>;
+ pagesize = <8>;
+ };
};
&lvds0 {
@@ -540,6 +583,11 @@
function = "intc_ex";
};
+ keys_pins: keys {
+ pins = "GP_5_10", "GP_5_11", "GP_5_12", "GP_5_13";
+ bias-pull-up;
+ };
+
pwm3_pins: pwm3 {
groups = "pwm3_b";
function = "pwm3";
diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index 4d0304bc9745..0ea300a8147d 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -290,8 +290,10 @@
i2c_dvfs: i2c@e60b0000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "renesas,iic-r8a77990";
- reg = <0 0xe60b0000 0 0x15>;
+ compatible = "renesas,iic-r8a77990",
+ "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 R8A77990_PD_ALWAYS_ON>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
index 6783c3ad0856..1ac15aa05b82 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the Draak board
+ * Device Tree Source for the Draak board with R-Car D3
*
* Copyright (C) 2016-2018 Renesas Electronics Corp.
* Copyright (C) 2017 Glider bvba
@@ -9,6 +9,7 @@
/dts-v1/;
#include "r8a77995.dtsi"
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
/ {
model = "Renesas Draak board based on r8a77995";
@@ -19,6 +20,16 @@
ethernet0 = &avb;
};
+ audio_clkout: audio-clkout {
+ /*
+ * This is same as <&rcar_sound 0>
+ * but needed to avoid cs2000/rcar_sound probe dead-lock
+ */
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <12288000>;
+ };
+
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm1 0 50000>;
@@ -67,6 +78,42 @@
};
};
+ keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&keys_pins>;
+ pinctrl-names = "default";
+
+ key-1 {
+ gpios = <&gpio4 12 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_1>;
+ label = "SW56-1";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ key-2 {
+ gpios = <&gpio4 13 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_2>;
+ label = "SW56-2";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ key-3 {
+ gpios = <&gpio4 14 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_3>;
+ label = "SW56-3";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ key-4 {
+ gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_4>;
+ label = "SW56-4";
+ wakeup-source;
+ debounce-interval = <20>;
+ };
+ };
+
lvds-decoder {
compatible = "thine,thc63lvd1024";
vcc-supply = <&reg_3p3v>;
@@ -124,6 +171,14 @@
regulator-always-on;
};
+ sound_card: sound {
+ compatible = "audio-graph-card";
+
+ dais = <&rsnd_port0 /* ak4613 */
+ /* HDMI is not yet supported */
+ >;
+ };
+
vga {
compatible = "vga-connector";
@@ -161,6 +216,25 @@
#clock-cells = <0>;
clock-frequency = <74250000>;
};
+
+ x19_clk: x19 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24576000>;
+ };
+};
+
+&audio_clk_b {
+ /*
+ * X11 is connected to VI4_FIELD/SCIF_CLK/AUDIO_CLKB,
+ * and R-Car Sound uses AUDIO_CLKB.
+ * Note is that schematic indicates VI4_FIELD conection only
+ * not AUDIO_CLKB at SoC page.
+ * And this VI4_FIELD/SCIF_CLK/AUDIO_CLKB is connected to SW60.
+ * SW60 should be 1-2.
+ */
+
+ clock-frequency = <22579200>;
};
&avb {
@@ -236,6 +310,28 @@
pinctrl-names = "default";
status = "okay";
+ ak4613: codec@10 {
+ compatible = "asahi-kasei,ak4613";
+ #sound-dai-cells = <0>;
+ reg = <0x10>;
+ clocks = <&rcar_sound 0>; /* audio_clkout */
+
+ asahi-kasei,in1-single-end;
+ asahi-kasei,in2-single-end;
+ asahi-kasei,out1-single-end;
+ asahi-kasei,out2-single-end;
+ asahi-kasei,out3-single-end;
+ asahi-kasei,out4-single-end;
+ asahi-kasei,out5-single-end;
+ asahi-kasei,out6-single-end;
+
+ port {
+ ak4613_endpoint: endpoint {
+ remote-endpoint = <&rsnd_for_ak4613>;
+ };
+ };
+ };
+
composite-in@20 {
compatible = "adi,adv7180cp";
reg = <0x20>;
@@ -277,10 +373,6 @@
interrupt-parent = <&gpio1>;
interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
- /* Depends on LVDS */
- max-clock = <135000000>;
- min-vrefresh = <50>;
-
adi,input-depth = <8>;
adi,input-colorspace = "rgb";
adi,input-clock = "1x";
@@ -342,6 +434,17 @@
};
};
+ cs2000: clk-multiplier@4f {
+ #clock-cells = <0>;
+ compatible = "cirrus,cs2000-cp";
+ reg = <0x4f>;
+ clocks = <&audio_clkout>, <&x19_clk>; /* audio_clkout_1, x19 */
+ clock-names = "clk_in", "ref_clk";
+
+ assigned-clocks = <&cs2000>;
+ assigned-clock-rates = <24576000>; /* 1/1 divide */
+ };
+
eeprom@50 {
compatible = "rohm,br24t01", "atmel,24c01";
reg = <0x50>;
@@ -422,6 +525,11 @@
function = "i2c1";
};
+ keys_pins: keys {
+ pins = "GP_4_12", "GP_4_13", "GP_4_14", "GP_4_15";
+ bias-pull-up;
+ };
+
pwm0_pins: pwm0 {
groups = "pwm0_c";
function = "pwm0";
@@ -449,6 +557,17 @@
power-source = <1800>;
};
+ sound_pins: sound {
+ groups = "ssi34_ctrl", "ssi3_data", "ssi4_data_a";
+ function = "ssi";
+ };
+
+ sound_clk_pins: sound-clk {
+ groups = "audio_clk_a", "audio_clk_b",
+ "audio_clkout", "audio_clkout1";
+ function = "audio_clk";
+ };
+
usb0_pins: usb0 {
groups = "usb0";
function = "usb0";
@@ -474,6 +593,42 @@
status = "okay";
};
+&rcar_sound {
+ pinctrl-0 = <&sound_pins>, <&sound_clk_pins>;
+ pinctrl-names = "default";
+
+ /* Single DAI */
+ #sound-dai-cells = <0>;
+
+ /* audio_clkout0/1 */
+ #clock-cells = <1>;
+ clock-frequency = <12288000 11289600>;
+
+ status = "okay";
+
+ clocks = <&cpg CPG_MOD 1005>,
+ <&cpg CPG_MOD 1011>, <&cpg CPG_MOD 1012>,
+ <&cpg CPG_MOD 1025>, <&cpg CPG_MOD 1026>,
+ <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+ <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+ <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
+ <&cs2000>, <&audio_clk_b>,
+ <&cpg CPG_CORE R8A77995_CLK_ZA2>;
+
+ ports {
+ rsnd_port0: port {
+ rsnd_for_ak4613: endpoint {
+ remote-endpoint = <&ak4613_endpoint>;
+ dai-format = "left_j";
+ bitclock-master = <&rsnd_for_ak4613>;
+ frame-master = <&rsnd_for_ak4613>;
+ playback = <&ssi3>, <&src5>, <&dvc0>;
+ capture = <&ssi4>, <&src6>, <&dvc1>;
+ };
+ };
+ };
+};
+
&rwdt {
timeout-sec = <60>;
status = "okay";
@@ -502,6 +657,10 @@
status = "okay";
};
+&ssi4 {
+ shared-pin;
+};
+
&usb2_phy0 {
pinctrl-0 = <&usb0_pins>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
index 84dba3719381..16ad5fc23a67 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
@@ -15,6 +15,23 @@
#address-cells = <2>;
#size-cells = <2>;
+ /*
+ * 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>;
+ };
+
/* External CAN clock - to be overridden by boards that provide it */
can_clk: can {
compatible = "fixed-clock";
@@ -1016,6 +1033,147 @@
status = "disabled";
};
+ rcar_sound: sound@ec500000 {
+ /*
+ * #sound-dai-cells is required
+ *
+ * Single DAI : #sound-dai-cells = <0>; <&rcar_sound>;
+ * Multi DAI : #sound-dai-cells = <1>; <&rcar_sound N>;
+ */
+ /*
+ * #clock-cells is required for audio_clkout0/1/2/3
+ *
+ * clkout : #clock-cells = <0>; <&rcar_sound>;
+ * clkout0/1/2/3: #clock-cells = <1>; <&rcar_sound N>;
+ */
+ compatible = "renesas,rcar_sound-r8a77995", "renesas,rcar_sound-gen3";
+ 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*/
+ reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
+
+ clocks = <&cpg CPG_MOD 1005>,
+ <&cpg CPG_MOD 1011>, <&cpg CPG_MOD 1012>,
+ <&cpg CPG_MOD 1025>, <&cpg CPG_MOD 1026>,
+ <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+ <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+ <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
+ <&audio_clk_a>, <&audio_clk_b>,
+ <&cpg CPG_CORE R8A77995_CLK_ZA2>;
+ clock-names = "ssi-all",
+ "ssi.4", "ssi.3",
+ "src.6", "src.5",
+ "mix.1", "mix.0",
+ "ctu.1", "ctu.0",
+ "dvc.0", "dvc.1",
+ "clk_a", "clk_b", "clk_i";
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 1005>,
+ <&cpg 1011>, <&cpg 1012>;
+ reset-names = "ssi-all",
+ "ssi.4", "ssi.3";
+ status = "disabled";
+
+ rcar_sound,ctu {
+ ctu00: ctu-0 { };
+ ctu01: ctu-1 { };
+ ctu02: ctu-2 { };
+ ctu03: ctu-3 { };
+ ctu10: ctu-4 { };
+ ctu11: ctu-5 { };
+ ctu12: ctu-6 { };
+ ctu13: ctu-7 { };
+ };
+
+ rcar_sound,dvc {
+ dvc0: dvc-0 {
+ dmas = <&audma0 0xbc>;
+ dma-names = "tx";
+ };
+ dvc1: dvc-1 {
+ dmas = <&audma0 0xbe>;
+ dma-names = "tx";
+ };
+ };
+
+ rcar_sound,mix {
+ mix0: mix-0 { };
+ mix1: mix-1 { };
+ };
+
+ rcar_sound,src {
+ src5: src-5 {
+ interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x8f>, <&audma0 0xb2>;
+ dma-names = "rx", "tx";
+ };
+ src6: src-6 {
+ interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x91>, <&audma0 0xb4>;
+ dma-names = "rx", "tx";
+ };
+ };
+
+ rcar_sound,ssi {
+ ssi3: ssi-3 {
+ interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x07>, <&audma0 0x08>,
+ <&audma0 0x6f>, <&audma0 0x70>;
+ dma-names = "rx", "tx", "rxu", "txu";
+ };
+ ssi4: ssi-4 {
+ interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&audma0 0x09>, <&audma0 0x0a>,
+ <&audma0 0x71>, <&audma0 0x72>;
+ dma-names = "rx", "tx", "rxu", "txu";
+ };
+ };
+ };
+
+ audma0: dma-controller@ec700000 {
+ compatible = "renesas,dmac-r8a77995",
+ "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 R8A77995_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>;
+ };
+
ohci0: usb@ee080000 {
compatible = "generic-ohci";
reg = <0 0xee080000 0 0x100>;
diff --git a/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts b/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts
index 687f019e79f0..dc671ff57ec7 100644
--- a/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts
+++ b/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree Source for the Falcon CPU and BreakOut boards
+ * Device Tree Source for the Falcon CPU and BreakOut boards with R-Car V3U
*
* Copyright (C) 2020 Renesas Electronics Corp.
*/
diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
index 78ca75f619f6..631d520cebee 100644
--- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
@@ -327,6 +327,19 @@
#power-domain-cells = <1>;
};
+ tsc: thermal@e6190000 {
+ compatible = "renesas,r8a779a0-thermal";
+ reg = <0 0xe6190000 0 0x200>,
+ <0 0xe6198000 0 0x200>,
+ <0 0xe61a0000 0 0x200>,
+ <0 0xe61a8000 0 0x200>,
+ <0 0xe61b0000 0 0x200>;
+ clocks = <&cpg CPG_MOD 919>;
+ power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>;
+ resets = <&cpg 919>;
+ #thermal-sensor-cells = <1>;
+ };
+
tmu0: timer@e61e0000 {
compatible = "renesas,tmu-r8a779a0", "renesas,tmu";
reg = <0 0xe61e0000 0 0x30>;
@@ -392,19 +405,6 @@
status = "disabled";
};
- tsc: thermal@e6190000 {
- compatible = "renesas,r8a779a0-thermal";
- reg = <0 0xe6190000 0 0x200>,
- <0 0xe6198000 0 0x200>,
- <0 0xe61a0000 0 0x200>,
- <0 0xe61a8000 0 0x200>,
- <0 0xe61b0000 0 0x200>;
- clocks = <&cpg CPG_MOD 919>;
- power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>;
- resets = <&cpg 919>;
- #thermal-sensor-cells = <1>;
- };
-
i2c0: i2c@e6500000 {
compatible = "renesas,i2c-r8a779a0",
"renesas,rcar-gen3-i2c";
diff --git a/arch/arm64/boot/dts/renesas/r8a779m1-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a779m1-salvator-xs.dts
new file mode 100644
index 000000000000..084b75b04680
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779m1-salvator-xs.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: (GPL-2.0 or MIT)
+/*
+ * Device Tree Source for the Salvator-X 2nd version board with R-Car H3e-2G
+ *
+ * Copyright (C) 2021 Glider bv
+ *
+ * Based on r8a77951-salvator-xs.dts
+ * Copyright (C) 2015-2017 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a779m1.dtsi"
+#include "salvator-xs.dtsi"
+
+/ {
+ model = "Renesas Salvator-X 2nd version board based on r8a779m1";
+ compatible = "renesas,salvator-xs", "renesas,r8a779m1",
+ "renesas,r8a7795";
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x38000000>;
+ };
+
+ memory@500000000 {
+ device_type = "memory";
+ reg = <0x5 0x00000000 0x0 0x40000000>;
+ };
+
+ memory@600000000 {
+ device_type = "memory";
+ reg = <0x6 0x00000000 0x0 0x40000000>;
+ };
+
+ memory@700000000 {
+ device_type = "memory";
+ reg = <0x7 0x00000000 0x0 0x40000000>;
+ };
+};
+
+&du {
+ clocks = <&cpg CPG_MOD 724>,
+ <&cpg CPG_MOD 723>,
+ <&cpg CPG_MOD 722>,
+ <&cpg CPG_MOD 721>,
+ <&versaclock6 1>,
+ <&x21_clk>,
+ <&x22_clk>,
+ <&versaclock6 2>;
+ clock-names = "du.0", "du.1", "du.2", "du.3",
+ "dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779m1-ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a779m1-ulcb-kf.dts
new file mode 100644
index 000000000000..0baebc5c58b0
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779m1-ulcb-kf.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: (GPL-2.0 or MIT)
+/*
+ * Device Tree Source for the H3ULCB Kingfisher board with R-Car H3e-2G
+ *
+ * Copyright (C) 2021 Glider bv
+ *
+ * Based on r8a77951-ulcb-kf.dts
+ * Copyright (C) 2017 Renesas Electronics Corp.
+ * Copyright (C) 2017 Cogent Embedded, Inc.
+ */
+
+#include "r8a779m1-ulcb.dts"
+#include "ulcb-kf.dtsi"
+
+/ {
+ model = "Renesas H3ULCB Kingfisher board based on r8a779m1";
+ compatible = "shimafuji,kingfisher", "renesas,h3ulcb",
+ "renesas,r8a779m1", "renesas,r8a7795";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779m1-ulcb.dts b/arch/arm64/boot/dts/renesas/r8a779m1-ulcb.dts
new file mode 100644
index 000000000000..e294b6bda28c
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779m1-ulcb.dts
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: (GPL-2.0 or MIT)
+/*
+ * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) with R-Car H3e-2G
+ *
+ * Copyright (C) 2021 Glider bv
+ *
+ * Based on r8a77951-ulcb.dts
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ * Copyright (C) 2016 Cogent Embedded, Inc.
+ */
+
+/dts-v1/;
+#include "r8a779m1.dtsi"
+#include "ulcb.dtsi"
+
+/ {
+ model = "Renesas H3ULCB board based on r8a779m1";
+ compatible = "renesas,h3ulcb", "renesas,r8a779m1", "renesas,r8a7795";
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x38000000>;
+ };
+
+ memory@500000000 {
+ device_type = "memory";
+ reg = <0x5 0x00000000 0x0 0x40000000>;
+ };
+
+ memory@600000000 {
+ device_type = "memory";
+ reg = <0x6 0x00000000 0x0 0x40000000>;
+ };
+
+ memory@700000000 {
+ device_type = "memory";
+ reg = <0x7 0x00000000 0x0 0x40000000>;
+ };
+};
+
+&du {
+ clocks = <&cpg CPG_MOD 724>,
+ <&cpg CPG_MOD 723>,
+ <&cpg CPG_MOD 722>,
+ <&cpg CPG_MOD 721>,
+ <&versaclock5 1>,
+ <&versaclock5 3>,
+ <&versaclock5 4>,
+ <&versaclock5 2>;
+ clock-names = "du.0", "du.1", "du.2", "du.3",
+ "dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779m1.dtsi b/arch/arm64/boot/dts/renesas/r8a779m1.dtsi
new file mode 100644
index 000000000000..0e9b04469b83
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779m1.dtsi
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: (GPL-2.0 or MIT)
+/*
+ * Device Tree Source for the R-Car H3e-2G (R8A779M1) SoC
+ *
+ * Copyright (C) 2021 Glider bv
+ */
+
+#include "r8a77951.dtsi"
+
+/ {
+ compatible = "renesas,r8a779m1", "renesas,r8a7795";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779m3-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a779m3-salvator-xs.dts
new file mode 100644
index 000000000000..4ab26fd7233d
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779m3-salvator-xs.dts
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: (GPL-2.0 or MIT)
+/*
+ * Device Tree Source for the Salvator-X 2nd version board with R-Car M3e-2G
+ *
+ * Copyright (C) 2021 Glider bv
+ *
+ * Based on r8a77961-salvator-xs.dts
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a779m3.dtsi"
+#include "salvator-xs.dtsi"
+
+/ {
+ model = "Renesas Salvator-X 2nd version board based on r8a779m3";
+ compatible = "renesas,salvator-xs", "renesas,r8a779m3",
+ "renesas,r8a77961";
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x78000000>;
+ };
+
+ memory@480000000 {
+ device_type = "memory";
+ reg = <0x4 0x80000000 0x0 0x80000000>;
+ };
+
+ memory@600000000 {
+ device_type = "memory";
+ reg = <0x6 0x00000000 0x1 0x00000000>;
+ };
+};
+
+&du {
+ clocks = <&cpg CPG_MOD 724>,
+ <&cpg CPG_MOD 723>,
+ <&cpg CPG_MOD 722>,
+ <&versaclock6 1>,
+ <&x21_clk>,
+ <&versaclock6 2>;
+ clock-names = "du.0", "du.1", "du.2",
+ "dclkin.0", "dclkin.1", "dclkin.2";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779m3-ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a779m3-ulcb-kf.dts
new file mode 100644
index 000000000000..6bacee1d2ef5
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779m3-ulcb-kf.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: (GPL-2.0 or MIT)
+/*
+ * Device Tree Source for the M3ULCB Kingfisher board with R-Car M3e-2G
+ *
+ * Copyright (C) 2021 Glider bv
+ *
+ * Based on r8a77961-ulcb-kf.dts
+ * Copyright (C) 2020 Eugeniu Rosca <rosca.eugeniu@gmail.com>
+ */
+
+#include "r8a779m3-ulcb.dts"
+#include "ulcb-kf.dtsi"
+
+/ {
+ model = "Renesas M3ULCB Kingfisher board based on r8a779m3";
+ compatible = "shimafuji,kingfisher", "renesas,m3ulcb",
+ "renesas,r8a779m3", "renesas,r8a77961";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779m3-ulcb.dts b/arch/arm64/boot/dts/renesas/r8a779m3-ulcb.dts
new file mode 100644
index 000000000000..8f215a0b771b
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779m3-ulcb.dts
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: (GPL-2.0 or MIT)
+/*
+ * Device Tree Source for the M3ULCB (R-Car Starter Kit Pro) with R-Car M3e-2G
+ *
+ * Copyright (C) 2021 Glider bv
+ *
+ * Based on r8a77961-ulcb.dts
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a779m3.dtsi"
+#include "ulcb.dtsi"
+
+/ {
+ model = "Renesas M3ULCB board based on r8a779m3";
+ compatible = "renesas,m3ulcb", "renesas,r8a779m3", "renesas,r8a77961";
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x78000000>;
+ };
+
+ memory@480000000 {
+ device_type = "memory";
+ reg = <0x4 0x80000000 0x0 0x80000000>;
+ };
+
+ memory@600000000 {
+ device_type = "memory";
+ reg = <0x6 0x00000000 0x1 0x00000000>;
+ };
+};
+
+&du {
+ clocks = <&cpg CPG_MOD 724>,
+ <&cpg CPG_MOD 723>,
+ <&cpg CPG_MOD 722>,
+ <&versaclock5 1>,
+ <&versaclock5 3>,
+ <&versaclock5 2>;
+ clock-names = "du.0", "du.1", "du.2",
+ "dclkin.0", "dclkin.1", "dclkin.2";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779m3.dtsi b/arch/arm64/boot/dts/renesas/r8a779m3.dtsi
new file mode 100644
index 000000000000..65bb6188ccf5
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a779m3.dtsi
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: (GPL-2.0 or MIT)
+/*
+ * Device Tree Source for the R-Car M3e-2G (R8A779M3) SoC
+ *
+ * Copyright (C) 2021 Glider bv
+ */
+
+#include "r8a77961.dtsi"
+
+/ {
+ compatible = "renesas,r8a779m3", "renesas,r8a77961";
+};
diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
index 01482d227506..5f3bc2898daf 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
@@ -13,6 +13,13 @@
#address-cells = <2>;
#size-cells = <2>;
+ /* External CAN clock - to be overridden by boards that provide it */
+ can_clk: can {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
/* clock can be either from exclk or crystal oscillator (XIN/XOUT) */
extal_clk: extal {
compatible = "fixed-clock";
@@ -89,6 +96,170 @@
status = "disabled";
};
+ canfd: can@10050000 {
+ compatible = "renesas,r9a07g044-canfd", "renesas,rzg2l-canfd";
+ reg = <0 0x10050000 0 0x8000>;
+ interrupts = <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "g_err", "g_recc",
+ "ch0_err", "ch0_rec", "ch0_trx",
+ "ch1_err", "ch1_rec", "ch1_trx";
+ clocks = <&cpg CPG_MOD R9A07G044_CANFD_PCLK>,
+ <&cpg CPG_CORE R9A07G044_CLK_P0_DIV2>,
+ <&can_clk>;
+ clock-names = "fck", "canfd", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R9A07G044_CLK_P0_DIV2>;
+ assigned-clock-rates = <50000000>;
+ resets = <&cpg R9A07G044_CANFD_RSTP_N>,
+ <&cpg R9A07G044_CANFD_RSTC_N>;
+ reset-names = "rstp_n", "rstc_n";
+ power-domains = <&cpg>;
+ status = "disabled";
+
+ channel0 {
+ status = "disabled";
+ };
+ channel1 {
+ status = "disabled";
+ };
+ };
+
+ i2c0: i2c@10058000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,riic-r9a07g044", "renesas,riic-rz";
+ reg = <0 0x10058000 0 0x400>;
+ interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 348 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 349 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
+ clocks = <&cpg CPG_MOD R9A07G044_I2C0_PCLK>;
+ clock-frequency = <100000>;
+ resets = <&cpg R9A07G044_I2C0_MRST>;
+ power-domains = <&cpg>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@10058400 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,riic-r9a07g044", "renesas,riic-rz";
+ reg = <0 0x10058400 0 0x400>;
+ interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 356 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 357 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 362 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 363 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
+ clocks = <&cpg CPG_MOD R9A07G044_I2C1_PCLK>;
+ clock-frequency = <100000>;
+ resets = <&cpg R9A07G044_I2C1_MRST>;
+ power-domains = <&cpg>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@10058800 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,riic-r9a07g044", "renesas,riic-rz";
+ reg = <0 0x10058800 0 0x400>;
+ interrupts = <GIC_SPI 366 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 364 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 365 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 368 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 369 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 367 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
+ clocks = <&cpg CPG_MOD R9A07G044_I2C2_PCLK>;
+ clock-frequency = <100000>;
+ resets = <&cpg R9A07G044_I2C2_MRST>;
+ power-domains = <&cpg>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@10058c00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,riic-r9a07g044", "renesas,riic-rz";
+ reg = <0 0x10058c00 0 0x400>;
+ interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 372 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tei", "ri", "ti", "spi", "sti",
+ "naki", "ali", "tmoi";
+ clocks = <&cpg CPG_MOD R9A07G044_I2C3_PCLK>;
+ clock-frequency = <100000>;
+ resets = <&cpg R9A07G044_I2C3_MRST>;
+ power-domains = <&cpg>;
+ status = "disabled";
+ };
+
+ adc: adc@10059000 {
+ compatible = "renesas,r9a07g044-adc", "renesas,rzg2l-adc";
+ reg = <0 0x10059000 0 0x400>;
+ interrupts = <GIC_SPI 347 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&cpg CPG_MOD R9A07G044_ADC_ADCLK>,
+ <&cpg CPG_MOD R9A07G044_ADC_PCLK>;
+ clock-names = "adclk", "pclk";
+ resets = <&cpg R9A07G044_ADC_PRESETN>,
+ <&cpg R9A07G044_ADC_ADRST_N>;
+ reset-names = "presetn", "adrst-n";
+ power-domains = <&cpg>;
+ status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ reg = <0>;
+ };
+ channel@1 {
+ reg = <1>;
+ };
+ channel@2 {
+ reg = <2>;
+ };
+ channel@3 {
+ reg = <3>;
+ };
+ channel@4 {
+ reg = <4>;
+ };
+ channel@5 {
+ reg = <5>;
+ };
+ channel@6 {
+ reg = <6>;
+ };
+ channel@7 {
+ reg = <7>;
+ };
+ };
+
cpg: clock-controller@11010000 {
compatible = "renesas,r9a07g044-cpg";
reg = <0 0x11010000 0 0x10000>;
@@ -111,6 +282,19 @@
status = "disabled";
};
+ pinctrl: pin-controller@11030000 {
+ compatible = "renesas,r9a07g044-pinctrl";
+ reg = <0 0x11030000 0 0x10000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 392>;
+ clocks = <&cpg CPG_MOD R9A07G044_GPIO_HCLK>;
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G044_GPIO_RSTN>,
+ <&cpg R9A07G044_GPIO_PORT_RESETN>,
+ <&cpg R9A07G044_GPIO_SPARE_RESETN>;
+ };
+
gic: interrupt-controller@11900000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
index 453ffcef24fa..eb1f3b82300b 100644
--- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
@@ -202,7 +202,11 @@
label = "rcar-sound";
dais = <&rsnd_port0 /* ak4613 */
- &rsnd_port1>; /* HDMI0 */
+ &rsnd_port1 /* HDMI0 */
+#ifdef SOC_HAS_HDMI1
+ &rsnd_port2 /* HDMI1 */
+#endif
+ >;
};
vbus0_usb2: regulator-vbus0-usb2 {
@@ -422,6 +426,31 @@
remote-endpoint = <&rcar_dw_hdmi0_out>;
};
+#ifdef SOC_HAS_HDMI1
+&hdmi1 {
+ status = "okay";
+
+ ports {
+ port@1 {
+ reg = <1>;
+ rcar_dw_hdmi1_out: endpoint {
+ remote-endpoint = <&hdmi1_con>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+ dw_hdmi1_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint2>;
+ };
+ };
+ };
+};
+
+&hdmi1_con {
+ remote-endpoint = <&rcar_dw_hdmi1_out>;
+};
+#endif /* SOC_HAS_HDMI1 */
+
&hscif1 {
pinctrl-0 = <&hscif1_pins>;
pinctrl-names = "default";
@@ -818,6 +847,21 @@
playback = <&ssi2>;
};
};
+
+#ifdef SOC_HAS_HDMI1
+ rsnd_port2: port@2 {
+ reg = <2>;
+ rsnd_endpoint2: endpoint {
+ remote-endpoint = <&dw_hdmi1_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint2>;
+ frame-master = <&rsnd_endpoint2>;
+
+ playback = <&ssi3>;
+ };
+ };
+#endif /* SOC_HAS_HDMI1 */
};
};
@@ -826,6 +870,12 @@
status = "okay";
};
+#ifdef SOC_HAS_SATA
+&sata {
+ status = "okay";
+};
+#endif /* SOC_HAS_SATA */
+
&scif1 {
pinctrl-0 = <&scif1_pins>;
pinctrl-names = "default";
@@ -973,3 +1023,27 @@
status = "okay";
};
+
+#ifdef SOC_HAS_USB2_CH2
+&ehci2 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
+&pfc {
+ usb2_pins: usb2 {
+ groups = "usb2";
+ function = "usb2";
+ };
+};
+
+&usb2_phy2 {
+ pinctrl-0 = <&usb2_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+#endif /* SOC_HAS_USB2_CH2 */
diff --git a/arch/arm64/boot/dts/renesas/salvator-xs.dtsi b/arch/arm64/boot/dts/renesas/salvator-xs.dtsi
index 717d42758cbc..08b925624e12 100644
--- a/arch/arm64/boot/dts/renesas/salvator-xs.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-xs.dtsi
@@ -27,3 +27,59 @@
clock-names = "xin";
};
};
+
+#ifdef SOC_HAS_SATA
+&pca9654 {
+ pcie-sata-switch-hog {
+ gpio-hog;
+ gpios = <7 GPIO_ACTIVE_HIGH>;
+ output-low; /* enable SATA by default */
+ line-name = "PCIE/SATA switch";
+ };
+};
+
+/* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */
+#endif /* SOC_HAS_SATA */
+
+#ifdef SOC_HAS_USB2_CH3
+&ehci3 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&hsusb3 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&ohci3 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&pfc {
+ /*
+ * - 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
+ * r8a77951 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_phy3 {
+ pinctrl-0 = <&usb2_ch3_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+#endif /* SOC_HAS_USB2_CH3 */
diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
index 02c3fdf9cc46..42d1d219a3fd 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
@@ -217,6 +217,12 @@
reg = <0x4044 0x8>;
#phy-cells = <1>;
};
+
+ epwm_tbclk: clock@4140 {
+ compatible = "ti,am64-epwm-tbclk", "syscon";
+ reg = <0x4130 0x4>;
+ #clock-cells = <1>;
+ };
};
main_uart0: serial@2800000 {
@@ -859,4 +865,112 @@
clock-names = "fck";
max-functions = /bits/ 8 <1>;
};
+
+ epwm0: pwm@23000000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23000000 0x0 0x100>;
+ power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ epwm1: pwm@23010000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23010000 0x0 0x100>;
+ power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ epwm2: pwm@23020000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23020000 0x0 0x100>;
+ power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ epwm3: pwm@23030000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23030000 0x0 0x100>;
+ power-domains = <&k3_pds 89 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 3>, <&k3_clks 89 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ epwm4: pwm@23040000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23040000 0x0 0x100>;
+ power-domains = <&k3_pds 90 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 4>, <&k3_clks 90 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ epwm5: pwm@23050000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23050000 0x0 0x100>;
+ power-domains = <&k3_pds 91 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 5>, <&k3_clks 91 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ epwm6: pwm@23060000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23060000 0x0 0x100>;
+ power-domains = <&k3_pds 92 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 6>, <&k3_clks 92 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ epwm7: pwm@23070000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23070000 0x0 0x100>;
+ power-domains = <&k3_pds 93 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 7>, <&k3_clks 93 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ epwm8: pwm@23080000 {
+ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23080000 0x0 0x100>;
+ power-domains = <&k3_pds 94 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&epwm_tbclk 8>, <&k3_clks 94 0>;
+ clock-names = "tbclk", "fck";
+ };
+
+ ecap0: pwm@23100000 {
+ compatible = "ti,am64-ecap", "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23100000 0x0 0x60>;
+ power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 51 0>;
+ clock-names = "fck";
+ };
+
+ ecap1: pwm@23110000 {
+ compatible = "ti,am64-ecap", "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23110000 0x0 0x60>;
+ power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 52 0>;
+ clock-names = "fck";
+ };
+
+ ecap2: pwm@23120000 {
+ compatible = "ti,am64-ecap", "ti,am3352-ecap";
+ #pwm-cells = <3>;
+ reg = <0x0 0x23120000 0x0 0x60>;
+ power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 53 0>;
+ clock-names = "fck";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
index 030712221188..24ce4942618d 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
@@ -288,6 +288,12 @@
AM64X_IOPAD(0x0008, PIN_INPUT, 0) /* (N19) OSPI0_DQS */
>;
};
+
+ main_ecap0_pins_default: main-ecap0-pins-default {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x0270, PIN_INPUT, 0) /* (D18) ECAP0_IN_APWM_OUT */
+ >;
+ };
};
&main_uart0 {
@@ -574,3 +580,53 @@
num-lanes = <1>;
status = "disabled";
};
+
+&ecap0 {
+ /* PWM is available on Pin 1 of header J12 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_ecap0_pins_default>;
+};
+
+&ecap1 {
+ status = "disabled";
+};
+
+&ecap2 {
+ status = "disabled";
+};
+
+&epwm0 {
+ status = "disabled";
+};
+
+&epwm1 {
+ status = "disabled";
+};
+
+&epwm2 {
+ status = "disabled";
+};
+
+&epwm3 {
+ status = "disabled";
+};
+
+&epwm4 {
+ status = "disabled";
+};
+
+&epwm5 {
+ status = "disabled";
+};
+
+&epwm6 {
+ status = "disabled";
+};
+
+&epwm7 {
+ status = "disabled";
+};
+
+&epwm8 {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
index d3aa2901e6fd..6b45cdeeeefa 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
@@ -210,6 +210,12 @@
AM64X_IOPAD(0x0008, PIN_INPUT, 0) /* (N19) OSPI0_DQS */
>;
};
+
+ main_ecap0_pins_default: main-ecap0-pins-default {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x0270, PIN_INPUT, 0) /* (D18) ECAP0_IN_APWM_OUT */
+ >;
+ };
};
&mcu_uart0 {
@@ -453,3 +459,61 @@
&pcie0_ep {
status = "disabled";
};
+
+&ecap0 {
+ /* PWM is available on Pin 1 of header J3 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_ecap0_pins_default>;
+};
+
+&ecap1 {
+ status = "disabled";
+};
+
+&ecap2 {
+ status = "disabled";
+};
+
+&epwm0 {
+ status = "disabled";
+};
+
+&epwm1 {
+ status = "disabled";
+};
+
+&epwm2 {
+ status = "disabled";
+};
+
+&epwm3 {
+ status = "disabled";
+};
+
+&epwm4 {
+ /*
+ * EPWM4_A, EPWM4_B is available on Pin 32 and 33 on J4 (RPi hat)
+ * But RPi Hat will be used for other use cases, so marking epwm4 as disabled.
+ */
+ status = "disabled";
+};
+
+&epwm5 {
+ /*
+ * EPWM5_A, EPWM5_B is available on Pin 29 and 31 on J4 (RPi hat)
+ * But RPi Hat will be used for other use cases, so marking epwm5 as disabled.
+ */
+ status = "disabled";
+};
+
+&epwm6 {
+ status = "disabled";
+};
+
+&epwm7 {
+ status = "disabled";
+};
+
+&epwm8 {
+ status = "disabled";
+};
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f423d08b9a71..156d96afbbfc 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -973,6 +973,7 @@ CONFIG_TI_SCI_CLK=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_A53PLL=y
CONFIG_QCOM_CLK_APCS_MSM8916=y
+CONFIG_QCOM_CLK_APCC_MSM8996=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_QCOM_CLK_RPMH=y
CONFIG_IPQ_GCC_8074=y
diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile
new file mode 100644
index 000000000000..87c31c001da9
--- /dev/null
+++ b/arch/arm64/hyperv/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y := hv_core.o mshyperv.o
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
new file mode 100644
index 000000000000..b54c34793701
--- /dev/null
+++ b/arch/arm64/hyperv/hv_core.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Low level utility routines for interacting with Hyper-V.
+ *
+ * Copyright (C) 2021, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+#include <linux/types.h>
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/hyperv.h>
+#include <linux/arm-smccc.h>
+#include <linux/module.h>
+#include <asm-generic/bug.h>
+#include <asm/hyperv-tlfs.h>
+#include <asm/mshyperv.h>
+
+/*
+ * hv_do_hypercall- Invoke the specified hypercall
+ */
+u64 hv_do_hypercall(u64 control, void *input, void *output)
+{
+ struct arm_smccc_res res;
+ u64 input_address;
+ u64 output_address;
+
+ input_address = input ? virt_to_phys(input) : 0;
+ output_address = output ? virt_to_phys(output) : 0;
+
+ arm_smccc_1_1_hvc(HV_FUNC_ID, control,
+ input_address, output_address, &res);
+ return res.a0;
+}
+EXPORT_SYMBOL_GPL(hv_do_hypercall);
+
+/*
+ * hv_do_fast_hypercall8 -- Invoke the specified hypercall
+ * with arguments in registers instead of physical memory.
+ * Avoids the overhead of virt_to_phys for simple hypercalls.
+ */
+
+u64 hv_do_fast_hypercall8(u16 code, u64 input)
+{
+ struct arm_smccc_res res;
+ u64 control;
+
+ control = (u64)code | HV_HYPERCALL_FAST_BIT;
+
+ arm_smccc_1_1_hvc(HV_FUNC_ID, control, input, &res);
+ return res.a0;
+}
+EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
+
+/*
+ * Set a single VP register to a 64-bit value.
+ */
+void hv_set_vpreg(u32 msr, u64 value)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_hvc(HV_FUNC_ID,
+ HVCALL_SET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
+ HV_HYPERCALL_REP_COMP_1,
+ HV_PARTITION_ID_SELF,
+ HV_VP_INDEX_SELF,
+ msr,
+ 0,
+ value,
+ 0,
+ &res);
+
+ /*
+ * Something is fundamentally broken in the hypervisor if
+ * setting a VP register fails. There's really no way to
+ * continue as a guest VM, so panic.
+ */
+ BUG_ON(!hv_result_success(res.a0));
+}
+EXPORT_SYMBOL_GPL(hv_set_vpreg);
+
+/*
+ * Get the value of a single VP register. One version
+ * returns just 64 bits and another returns the full 128 bits.
+ * The two versions are separate to avoid complicating the
+ * calling sequence for the more frequently used 64 bit version.
+ */
+
+void hv_get_vpreg_128(u32 msr, struct hv_get_vp_registers_output *result)
+{
+ struct arm_smccc_1_2_regs args;
+ struct arm_smccc_1_2_regs res;
+
+ args.a0 = HV_FUNC_ID;
+ args.a1 = HVCALL_GET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
+ HV_HYPERCALL_REP_COMP_1;
+ args.a2 = HV_PARTITION_ID_SELF;
+ args.a3 = HV_VP_INDEX_SELF;
+ args.a4 = msr;
+
+ /*
+ * Use the SMCCC 1.2 interface because the results are in registers
+ * beyond X0-X3.
+ */
+ arm_smccc_1_2_hvc(&args, &res);
+
+ /*
+ * Something is fundamentally broken in the hypervisor if
+ * getting a VP register fails. There's really no way to
+ * continue as a guest VM, so panic.
+ */
+ BUG_ON(!hv_result_success(res.a0));
+
+ result->as64.low = res.a6;
+ result->as64.high = res.a7;
+}
+EXPORT_SYMBOL_GPL(hv_get_vpreg_128);
+
+u64 hv_get_vpreg(u32 msr)
+{
+ struct hv_get_vp_registers_output output;
+
+ hv_get_vpreg_128(msr, &output);
+
+ return output.as64.low;
+}
+EXPORT_SYMBOL_GPL(hv_get_vpreg);
+
+/*
+ * hyperv_report_panic - report a panic to Hyper-V. This function uses
+ * the older version of the Hyper-V interface that admittedly doesn't
+ * pass enough information to be useful beyond just recording the
+ * occurrence of a panic. The parallel hv_kmsg_dump() uses the
+ * new interface that allows reporting 4 Kbytes of data, which is much
+ * more useful. Hyper-V on ARM64 always supports the newer interface, but
+ * we retain support for the older version because the sysadmin is allowed
+ * to disable the newer version via sysctl in case of information security
+ * concerns about the more verbose version.
+ */
+void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
+{
+ static bool panic_reported;
+ u64 guest_id;
+
+ /* Don't report a panic to Hyper-V if we're not going to panic */
+ if (in_die && !panic_on_oops)
+ return;
+
+ /*
+ * We prefer to report panic on 'die' chain as we have proper
+ * registers to report, but if we miss it (e.g. on BUG()) we need
+ * to report it on 'panic'.
+ *
+ * Calling code in the 'die' and 'panic' paths ensures that only
+ * one CPU is running this code, so no atomicity is needed.
+ */
+ if (panic_reported)
+ return;
+ panic_reported = true;
+
+ guest_id = hv_get_vpreg(HV_REGISTER_GUEST_OSID);
+
+ /*
+ * Hyper-V provides the ability to store only 5 values.
+ * Pick the passed in error value, the guest_id, the PC,
+ * and the SP.
+ */
+ hv_set_vpreg(HV_REGISTER_CRASH_P0, err);
+ hv_set_vpreg(HV_REGISTER_CRASH_P1, guest_id);
+ hv_set_vpreg(HV_REGISTER_CRASH_P2, regs->pc);
+ hv_set_vpreg(HV_REGISTER_CRASH_P3, regs->sp);
+ hv_set_vpreg(HV_REGISTER_CRASH_P4, 0);
+
+ /*
+ * Let Hyper-V know there is crash data available
+ */
+ hv_set_vpreg(HV_REGISTER_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
+}
+EXPORT_SYMBOL_GPL(hyperv_report_panic);
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
new file mode 100644
index 000000000000..bbbe351e9045
--- /dev/null
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Core routines for interacting with Microsoft's Hyper-V hypervisor,
+ * including hypervisor initialization.
+ *
+ * Copyright (C) 2021, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+#include <linux/types.h>
+#include <linux/acpi.h>
+#include <linux/export.h>
+#include <linux/errno.h>
+#include <linux/version.h>
+#include <linux/cpuhotplug.h>
+#include <asm/mshyperv.h>
+
+static bool hyperv_initialized;
+
+static int __init hyperv_init(void)
+{
+ struct hv_get_vp_registers_output result;
+ u32 a, b, c, d;
+ u64 guest_id;
+ int ret;
+
+ /*
+ * Allow for a kernel built with CONFIG_HYPERV to be running in
+ * a non-Hyper-V environment, including on DT instead of ACPI.
+ * In such cases, do nothing and return success.
+ */
+ if (acpi_disabled)
+ return 0;
+
+ if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
+ return 0;
+
+ /* Setup the guest ID */
+ guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
+ hv_set_vpreg(HV_REGISTER_GUEST_OSID, guest_id);
+
+ /* Get the features and hints from Hyper-V */
+ hv_get_vpreg_128(HV_REGISTER_FEATURES, &result);
+ ms_hyperv.features = result.as32.a;
+ ms_hyperv.priv_high = result.as32.b;
+ ms_hyperv.misc_features = result.as32.c;
+
+ hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result);
+ ms_hyperv.hints = result.as32.a;
+
+ pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc 0x%x\n",
+ ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints,
+ ms_hyperv.misc_features);
+
+ /* Get information about the Hyper-V host version */
+ hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result);
+ a = result.as32.a;
+ b = result.as32.b;
+ c = result.as32.c;
+ d = result.as32.d;
+ pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n",
+ b >> 16, b & 0xFFFF, a, d & 0xFFFFFF, c, d >> 24);
+
+ ret = hv_common_init();
+ if (ret)
+ return ret;
+
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/hyperv_init:online",
+ hv_common_cpu_init, hv_common_cpu_die);
+ if (ret < 0) {
+ hv_common_free();
+ return ret;
+ }
+
+ hyperv_initialized = true;
+ return 0;
+}
+
+early_initcall(hyperv_init);
+
+bool hv_is_hyperv_initialized(void)
+{
+ return hyperv_initialized;
+}
+EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 9bb9d11750d7..ef6be92b1921 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -552,7 +552,7 @@ cpuid_feature_cap_perfmon_field(u64 features, int field, u64 cap)
u64 mask = GENMASK_ULL(field + 3, field);
/* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
- if (val == 0xf)
+ if (val == ID_AA64DFR0_PMUVER_IMP_DEF)
val = 0;
if (val > cap) {
@@ -602,14 +602,14 @@ static inline bool id_aa64pfr0_32bit_el1(u64 pfr0)
{
u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL1_SHIFT);
- return val == ID_AA64PFR0_EL1_32BIT_64BIT;
+ return val == ID_AA64PFR0_ELx_32BIT_64BIT;
}
static inline bool id_aa64pfr0_32bit_el0(u64 pfr0)
{
u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL0_SHIFT);
- return val == ID_AA64PFR0_EL0_32BIT_64BIT;
+ return val == ID_AA64PFR0_ELx_32BIT_64BIT;
}
static inline bool id_aa64pfr0_sve(u64 pfr0)
@@ -657,7 +657,8 @@ static inline bool system_supports_4kb_granule(void)
val = cpuid_feature_extract_unsigned_field(mmfr0,
ID_AA64MMFR0_TGRAN4_SHIFT);
- return val == ID_AA64MMFR0_TGRAN4_SUPPORTED;
+ return (val >= ID_AA64MMFR0_TGRAN4_SUPPORTED_MIN) &&
+ (val <= ID_AA64MMFR0_TGRAN4_SUPPORTED_MAX);
}
static inline bool system_supports_64kb_granule(void)
@@ -669,7 +670,8 @@ static inline bool system_supports_64kb_granule(void)
val = cpuid_feature_extract_unsigned_field(mmfr0,
ID_AA64MMFR0_TGRAN64_SHIFT);
- return val == ID_AA64MMFR0_TGRAN64_SUPPORTED;
+ return (val >= ID_AA64MMFR0_TGRAN64_SUPPORTED_MIN) &&
+ (val <= ID_AA64MMFR0_TGRAN64_SUPPORTED_MAX);
}
static inline bool system_supports_16kb_granule(void)
@@ -681,7 +683,8 @@ static inline bool system_supports_16kb_granule(void)
val = cpuid_feature_extract_unsigned_field(mmfr0,
ID_AA64MMFR0_TGRAN16_SHIFT);
- return val == ID_AA64MMFR0_TGRAN16_SUPPORTED;
+ return (val >= ID_AA64MMFR0_TGRAN16_SUPPORTED_MIN) &&
+ (val <= ID_AA64MMFR0_TGRAN16_SUPPORTED_MAX);
}
static inline bool system_supports_mixed_endian_el0(void)
@@ -781,13 +784,13 @@ extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
static inline u32 id_aa64mmfr0_parange_to_phys_shift(int parange)
{
switch (parange) {
- case 0: return 32;
- case 1: return 36;
- case 2: return 40;
- case 3: return 42;
- case 4: return 44;
- case 5: return 48;
- case 6: return 52;
+ case ID_AA64MMFR0_PARANGE_32: return 32;
+ case ID_AA64MMFR0_PARANGE_36: return 36;
+ case ID_AA64MMFR0_PARANGE_40: return 40;
+ case ID_AA64MMFR0_PARANGE_42: return 42;
+ case ID_AA64MMFR0_PARANGE_44: return 44;
+ case ID_AA64MMFR0_PARANGE_48: return 48;
+ case ID_AA64MMFR0_PARANGE_52: return 52;
/*
* A future PE could use a value unknown to the kernel.
* However, by the "D10.1.4 Principles of the ID scheme
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 1bed37eb013a..d3e1825337be 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -14,6 +14,7 @@
#ifdef CONFIG_EFI
extern void efi_init(void);
+extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
#else
#define efi_init()
#endif
@@ -85,10 +86,6 @@ static inline void free_screen_info(struct screen_info *si)
{
}
-static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
-{
-}
-
#define EFI_ALLOC_ALIGN SZ_64K
/*
diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h
index b83fb24954b7..3198acb2aad8 100644
--- a/arch/arm64/include/asm/el2_setup.h
+++ b/arch/arm64/include/asm/el2_setup.h
@@ -149,8 +149,17 @@
ubfx x1, x1, #ID_AA64MMFR0_FGT_SHIFT, #4
cbz x1, .Lskip_fgt_\@
- msr_s SYS_HDFGRTR_EL2, xzr
- msr_s SYS_HDFGWTR_EL2, xzr
+ mov x0, xzr
+ mrs x1, id_aa64dfr0_el1
+ ubfx x1, x1, #ID_AA64DFR0_PMSVER_SHIFT, #4
+ cmp x1, #3
+ b.lt .Lset_fgt_\@
+ /* Disable PMSNEVFR_EL1 read and write traps */
+ orr x0, x0, #(1 << 62)
+
+.Lset_fgt_\@:
+ msr_s SYS_HDFGRTR_EL2, x0
+ msr_s SYS_HDFGWTR_EL2, x0
msr_s SYS_HFGRTR_EL2, xzr
msr_s SYS_HFGWTR_EL2, xzr
msr_s SYS_HFGITR_EL2, xzr
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 8d1c8dcb87fd..97932fbf973d 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -213,10 +213,8 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
/* AArch32 EABI. */
#define EF_ARM_EABI_MASK 0xff000000
-#define compat_elf_check_arch(x) (system_supports_32bit_el0() && \
- ((x)->e_machine == EM_ARM) && \
- ((x)->e_flags & EF_ARM_EABI_MASK))
-
+int compat_elf_check_arch(const struct elf32_hdr *);
+#define compat_elf_check_arch compat_elf_check_arch
#define compat_start_thread compat_start_thread
/*
* Unlike the native SET_PERSONALITY macro, the compat version maintains
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index 4afbc45b8bb0..339477dca551 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -55,8 +55,8 @@ asmlinkage void el0t_32_error_handler(struct pt_regs *regs);
asmlinkage void call_on_irq_stack(struct pt_regs *regs,
void (*func)(struct pt_regs *));
-asmlinkage void enter_from_user_mode(void);
-asmlinkage void exit_to_user_mode(void);
+asmlinkage void asm_exit_to_user_mode(struct pt_regs *regs);
+
void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
void do_undefinstr(struct pt_regs *regs);
void do_bti(struct pt_regs *regs);
@@ -73,6 +73,7 @@ void do_el0_svc(struct pt_regs *regs);
void do_el0_svc_compat(struct pt_regs *regs);
void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr);
void do_serror(struct pt_regs *regs, unsigned int esr);
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags);
void panic_bad_stack(struct pt_regs *regs, unsigned int esr, unsigned long far);
#endif /* __ASM_EXCEPTION_H */
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index c072161d5c65..9a62884183e5 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -45,7 +45,6 @@ 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,
void *sve_state, unsigned int sve_vl);
diff --git a/arch/arm64/include/asm/fpsimdmacros.h b/arch/arm64/include/asm/fpsimdmacros.h
index 059204477ce6..00a2c0b69c2b 100644
--- a/arch/arm64/include/asm/fpsimdmacros.h
+++ b/arch/arm64/include/asm/fpsimdmacros.h
@@ -94,6 +94,7 @@
.endm
/* SVE instruction encodings for non-SVE-capable assemblers */
+/* (pre binutils 2.28, all kernel capable clang versions support SVE) */
/* STR (vector): STR Z\nz, [X\nxbase, #\offset, MUL VL] */
.macro _sve_str_v nz, nxbase, offset=0
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 9a5498c2c8ee..8c129db8232a 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -18,7 +18,7 @@
#define COMPAT_HWCAP_EDSP (1 << 7)
#define COMPAT_HWCAP_JAVA (1 << 8)
#define COMPAT_HWCAP_IWMMXT (1 << 9)
-#define COMPAT_HWCAP_CRUNCH (1 << 10)
+#define COMPAT_HWCAP_CRUNCH (1 << 10) /* Obsolete */
#define COMPAT_HWCAP_THUMBEE (1 << 11)
#define COMPAT_HWCAP_NEON (1 << 12)
#define COMPAT_HWCAP_VFPv3 (1 << 13)
diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h
new file mode 100644
index 000000000000..4d964a7f02ee
--- /dev/null
+++ b/arch/arm64/include/asm/hyperv-tlfs.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * This file contains definitions from the Hyper-V Hypervisor Top-Level
+ * Functional Specification (TLFS):
+ * https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
+ *
+ * Copyright (C) 2021, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+#ifndef _ASM_HYPERV_TLFS_H
+#define _ASM_HYPERV_TLFS_H
+
+#include <linux/types.h>
+
+/*
+ * All data structures defined in the TLFS that are shared between Hyper-V
+ * and a guest VM use Little Endian byte ordering. This matches the default
+ * byte ordering of Linux running on ARM64, so no special handling is required.
+ */
+
+/*
+ * These Hyper-V registers provide information equivalent to the CPUID
+ * instruction on x86/x64.
+ */
+#define HV_REGISTER_HYPERVISOR_VERSION 0x00000100 /*CPUID 0x40000002 */
+#define HV_REGISTER_FEATURES 0x00000200 /*CPUID 0x40000003 */
+#define HV_REGISTER_ENLIGHTENMENTS 0x00000201 /*CPUID 0x40000004 */
+
+/*
+ * Group C Features. See the asm-generic version of hyperv-tlfs.h
+ * for a description of Feature Groups.
+ */
+
+/* Crash MSRs available */
+#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(8)
+
+/* STIMER direct mode is available */
+#define HV_STIMER_DIRECT_MODE_AVAILABLE BIT(13)
+
+/*
+ * Synthetic register definitions equivalent to MSRs on x86/x64
+ */
+#define HV_REGISTER_CRASH_P0 0x00000210
+#define HV_REGISTER_CRASH_P1 0x00000211
+#define HV_REGISTER_CRASH_P2 0x00000212
+#define HV_REGISTER_CRASH_P3 0x00000213
+#define HV_REGISTER_CRASH_P4 0x00000214
+#define HV_REGISTER_CRASH_CTL 0x00000215
+
+#define HV_REGISTER_GUEST_OSID 0x00090002
+#define HV_REGISTER_VP_INDEX 0x00090003
+#define HV_REGISTER_TIME_REF_COUNT 0x00090004
+#define HV_REGISTER_REFERENCE_TSC 0x00090017
+
+#define HV_REGISTER_SINT0 0x000A0000
+#define HV_REGISTER_SCONTROL 0x000A0010
+#define HV_REGISTER_SIEFP 0x000A0012
+#define HV_REGISTER_SIMP 0x000A0013
+#define HV_REGISTER_EOM 0x000A0014
+
+#define HV_REGISTER_STIMER0_CONFIG 0x000B0000
+#define HV_REGISTER_STIMER0_COUNT 0x000B0001
+
+#include <asm-generic/hyperv-tlfs.h>
+
+#endif
diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
index 3512184cfec1..96dc0f7da258 100644
--- a/arch/arm64/include/asm/kernel-pgtable.h
+++ b/arch/arm64/include/asm/kernel-pgtable.h
@@ -65,8 +65,8 @@
#define EARLY_KASLR (0)
#endif
-#define EARLY_ENTRIES(vstart, vend, shift) (((vend) >> (shift)) \
- - ((vstart) >> (shift)) + 1 + EARLY_KASLR)
+#define EARLY_ENTRIES(vstart, vend, shift) \
+ ((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + EARLY_KASLR)
#define EARLY_PGDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT))
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index d436831dd706..327120c0089f 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -12,8 +12,13 @@
#include <asm/types.h>
/* Hyp Configuration Register (HCR) bits */
+
+#define HCR_TID5 (UL(1) << 58)
+#define HCR_DCT (UL(1) << 57)
#define HCR_ATA_SHIFT 56
#define HCR_ATA (UL(1) << HCR_ATA_SHIFT)
+#define HCR_AMVOFFEN (UL(1) << 51)
+#define HCR_FIEN (UL(1) << 47)
#define HCR_FWB (UL(1) << 46)
#define HCR_API (UL(1) << 41)
#define HCR_APK (UL(1) << 40)
@@ -32,9 +37,9 @@
#define HCR_TVM (UL(1) << 26)
#define HCR_TTLB (UL(1) << 25)
#define HCR_TPU (UL(1) << 24)
-#define HCR_TPC (UL(1) << 23)
+#define HCR_TPC (UL(1) << 23) /* HCR_TPCP if FEAT_DPB */
#define HCR_TSW (UL(1) << 22)
-#define HCR_TAC (UL(1) << 21)
+#define HCR_TACR (UL(1) << 21)
#define HCR_TIDCP (UL(1) << 20)
#define HCR_TSC (UL(1) << 19)
#define HCR_TID3 (UL(1) << 18)
@@ -56,12 +61,13 @@
#define HCR_PTW (UL(1) << 2)
#define HCR_SWIO (UL(1) << 1)
#define HCR_VM (UL(1) << 0)
+#define HCR_RES0 ((UL(1) << 48) | (UL(1) << 39))
/*
* The bits we set in HCR:
* TLOR: Trap LORegion register accesses
* RW: 64bit by default, can be overridden for 32bit VMs
- * TAC: Trap ACTLR
+ * TACR: Trap ACTLR
* TSC: Trap SMC
* TSW: Trap cache operations by set/way
* TWE: Trap WFE
@@ -76,7 +82,7 @@
* PTW: Take a stage2 fault if a stage1 walk steps in device memory
*/
#define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
- HCR_BSU_IS | HCR_FB | HCR_TAC | \
+ HCR_BSU_IS | HCR_FB | HCR_TACR | \
HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
HCR_FMO | HCR_IMO | HCR_PTW )
#define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
@@ -275,24 +281,40 @@
#define CPTR_EL2_TTA (1 << 20)
#define CPTR_EL2_TFP (1 << CPTR_EL2_TFP_SHIFT)
#define CPTR_EL2_TZ (1 << 8)
-#define CPTR_EL2_RES1 0x000032ff /* known RES1 bits in CPTR_EL2 */
-#define CPTR_EL2_DEFAULT CPTR_EL2_RES1
+#define CPTR_NVHE_EL2_RES1 0x000032ff /* known RES1 bits in CPTR_EL2 (nVHE) */
+#define CPTR_EL2_DEFAULT CPTR_NVHE_EL2_RES1
+#define CPTR_NVHE_EL2_RES0 (GENMASK(63, 32) | \
+ GENMASK(29, 21) | \
+ GENMASK(19, 14) | \
+ BIT(11))
/* Hyp Debug Configuration Register bits */
#define MDCR_EL2_E2TB_MASK (UL(0x3))
#define MDCR_EL2_E2TB_SHIFT (UL(24))
-#define MDCR_EL2_TTRF (1 << 19)
-#define MDCR_EL2_TPMS (1 << 14)
+#define MDCR_EL2_HPMFZS (UL(1) << 36)
+#define MDCR_EL2_HPMFZO (UL(1) << 29)
+#define MDCR_EL2_MTPME (UL(1) << 28)
+#define MDCR_EL2_TDCC (UL(1) << 27)
+#define MDCR_EL2_HCCD (UL(1) << 23)
+#define MDCR_EL2_TTRF (UL(1) << 19)
+#define MDCR_EL2_HPMD (UL(1) << 17)
+#define MDCR_EL2_TPMS (UL(1) << 14)
#define MDCR_EL2_E2PB_MASK (UL(0x3))
#define MDCR_EL2_E2PB_SHIFT (UL(12))
-#define MDCR_EL2_TDRA (1 << 11)
-#define MDCR_EL2_TDOSA (1 << 10)
-#define MDCR_EL2_TDA (1 << 9)
-#define MDCR_EL2_TDE (1 << 8)
-#define MDCR_EL2_HPME (1 << 7)
-#define MDCR_EL2_TPM (1 << 6)
-#define MDCR_EL2_TPMCR (1 << 5)
-#define MDCR_EL2_HPMN_MASK (0x1F)
+#define MDCR_EL2_TDRA (UL(1) << 11)
+#define MDCR_EL2_TDOSA (UL(1) << 10)
+#define MDCR_EL2_TDA (UL(1) << 9)
+#define MDCR_EL2_TDE (UL(1) << 8)
+#define MDCR_EL2_HPME (UL(1) << 7)
+#define MDCR_EL2_TPM (UL(1) << 6)
+#define MDCR_EL2_TPMCR (UL(1) << 5)
+#define MDCR_EL2_HPMN_MASK (UL(0x1F))
+#define MDCR_EL2_RES0 (GENMASK(63, 37) | \
+ GENMASK(35, 30) | \
+ GENMASK(25, 24) | \
+ GENMASK(22, 20) | \
+ BIT(18) | \
+ GENMASK(16, 15))
/* For compatibility with fault code shared with 32-bit */
#define FSC_FAULT ESR_ELx_FSC_FAULT
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 9f0bf2109be7..e86045ac43ba 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -59,12 +59,11 @@
#define __KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs 13
#define __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_aprs 14
#define __KVM_HOST_SMCCC_FUNC___pkvm_init 15
-#define __KVM_HOST_SMCCC_FUNC___pkvm_create_mappings 16
+#define __KVM_HOST_SMCCC_FUNC___pkvm_host_share_hyp 16
#define __KVM_HOST_SMCCC_FUNC___pkvm_create_private_mapping 17
#define __KVM_HOST_SMCCC_FUNC___pkvm_cpu_set_vector 18
#define __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize 19
-#define __KVM_HOST_SMCCC_FUNC___pkvm_mark_hyp 20
-#define __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc 21
+#define __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc 20
#ifndef __ASSEMBLY__
@@ -210,7 +209,7 @@ extern u64 __vgic_v3_read_vmcr(void);
extern void __vgic_v3_write_vmcr(u32 vmcr);
extern void __vgic_v3_init_lrs(void);
-extern u32 __kvm_get_mdcr_el2(void);
+extern u64 __kvm_get_mdcr_el2(void);
#define __KVM_EXTABLE(from, to) \
" .pushsection __kvm_ex_table, \"a\"\n" \
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 41911585ae0c..f8be56d5342b 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -66,7 +66,7 @@ DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
extern unsigned int kvm_sve_max_vl;
int kvm_arm_init_sve(void);
-int __attribute_const__ kvm_target_cpu(void);
+u32 __attribute_const__ kvm_target_cpu(void);
int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu);
@@ -185,7 +185,6 @@ enum vcpu_sysreg {
PMCNTENSET_EL0, /* Count Enable Set Register */
PMINTENSET_EL1, /* Interrupt Enable Set Register */
PMOVSSET_EL0, /* Overflow Flag Status Set Register */
- PMSWINC_EL0, /* Software Increment Register */
PMUSERENR_EL0, /* User Enable Register */
/* Pointer Authentication Registers in a strict increasing order. */
@@ -287,9 +286,13 @@ struct kvm_vcpu_arch {
/* Stage 2 paging state used by the hardware on next switch */
struct kvm_s2_mmu *hw_mmu;
- /* HYP configuration */
+ /* Values of trap registers for the guest. */
u64 hcr_el2;
- u32 mdcr_el2;
+ u64 mdcr_el2;
+ u64 cptr_el2;
+
+ /* Values of trap registers for the host before guest entry. */
+ u64 mdcr_el2_host;
/* Exception Information */
struct kvm_vcpu_fault_info fault;
@@ -576,6 +579,7 @@ struct kvm_vcpu_stat {
u64 wfi_exit_stat;
u64 mmio_exit_user;
u64 mmio_exit_kernel;
+ u64 signal_exits;
u64 exits;
};
@@ -771,6 +775,11 @@ void kvm_arch_free_vm(struct kvm *kvm);
int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
+static inline bool kvm_vm_is_protected(struct kvm *kvm)
+{
+ return false;
+}
+
int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature);
bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 9d60b3006efc..657d0c94cf82 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -95,7 +95,7 @@ void __sve_restore_state(void *sve_pffr, u32 *fpsr);
#ifndef __KVM_NVHE_HYPERVISOR__
void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
-void deactivate_traps_vhe_put(void);
+void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu);
#endif
u64 __guest_enter(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index b52c5c4b9a3d..02d378887743 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -252,6 +252,11 @@ static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
#define kvm_phys_to_vttbr(addr) phys_to_ttbr(addr)
+/*
+ * When this is (directly or indirectly) used on the TLB invalidation
+ * path, we rely on a previously issued DSB so that page table updates
+ * and VMID reads are correctly ordered.
+ */
static __always_inline u64 kvm_get_vttbr(struct kvm_s2_mmu *mmu)
{
struct kvm_vmid *vmid = &mmu->vmid;
@@ -259,7 +264,7 @@ static __always_inline u64 kvm_get_vttbr(struct kvm_s2_mmu *mmu)
u64 cnp = system_supports_cnp() ? VTTBR_CNP_BIT : 0;
baddr = mmu->pgd_phys;
- vmid_field = (u64)vmid->vmid << VTTBR_VMID_SHIFT;
+ vmid_field = (u64)READ_ONCE(vmid->vmid) << VTTBR_VMID_SHIFT;
return kvm_phys_to_vttbr(baddr) | vmid_field | cnp;
}
@@ -267,9 +272,10 @@ static __always_inline u64 kvm_get_vttbr(struct kvm_s2_mmu *mmu)
* Must be called from hyp code running at EL2 with an updated VTTBR
* and interrupts disabled.
*/
-static __always_inline void __load_stage2(struct kvm_s2_mmu *mmu, unsigned long vtcr)
+static __always_inline void __load_stage2(struct kvm_s2_mmu *mmu,
+ struct kvm_arch *arch)
{
- write_sysreg(vtcr, vtcr_el2);
+ write_sysreg(arch->vtcr, vtcr_el2);
write_sysreg(kvm_get_vttbr(mmu), vttbr_el2);
/*
@@ -280,11 +286,6 @@ static __always_inline void __load_stage2(struct kvm_s2_mmu *mmu, unsigned long
asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT));
}
-static __always_inline void __load_guest_stage2(struct kvm_s2_mmu *mmu)
-{
- __load_stage2(mmu, kern_hyp_va(mmu->arch)->vtcr);
-}
-
static inline struct kvm *kvm_s2_mmu_to_kvm(struct kvm_s2_mmu *mmu)
{
return container_of(mmu->arch, struct kvm, arch);
diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index f004c0115d89..027783829584 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -25,6 +25,46 @@ static inline u64 kvm_get_parange(u64 mmfr0)
typedef u64 kvm_pte_t;
+#define KVM_PTE_VALID BIT(0)
+
+#define KVM_PTE_ADDR_MASK GENMASK(47, PAGE_SHIFT)
+#define KVM_PTE_ADDR_51_48 GENMASK(15, 12)
+
+static inline bool kvm_pte_valid(kvm_pte_t pte)
+{
+ return pte & KVM_PTE_VALID;
+}
+
+static inline u64 kvm_pte_to_phys(kvm_pte_t pte)
+{
+ u64 pa = pte & KVM_PTE_ADDR_MASK;
+
+ if (PAGE_SHIFT == 16)
+ pa |= FIELD_GET(KVM_PTE_ADDR_51_48, pte) << 48;
+
+ return pa;
+}
+
+static inline u64 kvm_granule_shift(u32 level)
+{
+ /* Assumes KVM_PGTABLE_MAX_LEVELS is 4 */
+ return ARM64_HW_PGTABLE_LEVEL_SHIFT(level);
+}
+
+static inline u64 kvm_granule_size(u32 level)
+{
+ return BIT(kvm_granule_shift(level));
+}
+
+static inline bool kvm_level_supports_block_mapping(u32 level)
+{
+ /*
+ * Reject invalid block mappings and don't bother with 4TB mappings for
+ * 52-bit PAs.
+ */
+ return !(level == 0 || (PAGE_SIZE != SZ_4K && level == 1));
+}
+
/**
* struct kvm_pgtable_mm_ops - Memory management callbacks.
* @zalloc_page: Allocate a single zeroed memory page.
@@ -76,30 +116,15 @@ enum kvm_pgtable_stage2_flags {
};
/**
- * struct kvm_pgtable - KVM page-table.
- * @ia_bits: Maximum input address size, in bits.
- * @start_level: Level at which the page-table walk starts.
- * @pgd: Pointer to the first top-level entry of the page-table.
- * @mm_ops: Memory management callbacks.
- * @mmu: Stage-2 KVM MMU struct. Unused for stage-1 page-tables.
- */
-struct kvm_pgtable {
- u32 ia_bits;
- u32 start_level;
- kvm_pte_t *pgd;
- struct kvm_pgtable_mm_ops *mm_ops;
-
- /* Stage-2 only */
- struct kvm_s2_mmu *mmu;
- enum kvm_pgtable_stage2_flags flags;
-};
-
-/**
* enum kvm_pgtable_prot - Page-table permissions and attributes.
* @KVM_PGTABLE_PROT_X: Execute permission.
* @KVM_PGTABLE_PROT_W: Write permission.
* @KVM_PGTABLE_PROT_R: Read permission.
* @KVM_PGTABLE_PROT_DEVICE: Device attributes.
+ * @KVM_PGTABLE_PROT_SW0: Software bit 0.
+ * @KVM_PGTABLE_PROT_SW1: Software bit 1.
+ * @KVM_PGTABLE_PROT_SW2: Software bit 2.
+ * @KVM_PGTABLE_PROT_SW3: Software bit 3.
*/
enum kvm_pgtable_prot {
KVM_PGTABLE_PROT_X = BIT(0),
@@ -107,21 +132,48 @@ enum kvm_pgtable_prot {
KVM_PGTABLE_PROT_R = BIT(2),
KVM_PGTABLE_PROT_DEVICE = BIT(3),
+
+ KVM_PGTABLE_PROT_SW0 = BIT(55),
+ KVM_PGTABLE_PROT_SW1 = BIT(56),
+ KVM_PGTABLE_PROT_SW2 = BIT(57),
+ KVM_PGTABLE_PROT_SW3 = BIT(58),
};
-#define PAGE_HYP (KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W)
+#define KVM_PGTABLE_PROT_RW (KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W)
+#define KVM_PGTABLE_PROT_RWX (KVM_PGTABLE_PROT_RW | KVM_PGTABLE_PROT_X)
+
+#define PKVM_HOST_MEM_PROT KVM_PGTABLE_PROT_RWX
+#define PKVM_HOST_MMIO_PROT KVM_PGTABLE_PROT_RW
+
+#define PAGE_HYP KVM_PGTABLE_PROT_RW
#define PAGE_HYP_EXEC (KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_X)
#define PAGE_HYP_RO (KVM_PGTABLE_PROT_R)
#define PAGE_HYP_DEVICE (PAGE_HYP | KVM_PGTABLE_PROT_DEVICE)
+typedef bool (*kvm_pgtable_force_pte_cb_t)(u64 addr, u64 end,
+ enum kvm_pgtable_prot prot);
+
/**
- * struct kvm_mem_range - Range of Intermediate Physical Addresses
- * @start: Start of the range.
- * @end: End of the range.
+ * struct kvm_pgtable - KVM page-table.
+ * @ia_bits: Maximum input address size, in bits.
+ * @start_level: Level at which the page-table walk starts.
+ * @pgd: Pointer to the first top-level entry of the page-table.
+ * @mm_ops: Memory management callbacks.
+ * @mmu: Stage-2 KVM MMU struct. Unused for stage-1 page-tables.
+ * @flags: Stage-2 page-table flags.
+ * @force_pte_cb: Function that returns true if page level mappings must
+ * be used instead of block mappings.
*/
-struct kvm_mem_range {
- u64 start;
- u64 end;
+struct kvm_pgtable {
+ u32 ia_bits;
+ u32 start_level;
+ kvm_pte_t *pgd;
+ struct kvm_pgtable_mm_ops *mm_ops;
+
+ /* Stage-2 only */
+ struct kvm_s2_mmu *mmu;
+ enum kvm_pgtable_stage2_flags flags;
+ kvm_pgtable_force_pte_cb_t force_pte_cb;
};
/**
@@ -216,21 +268,24 @@ int kvm_pgtable_hyp_map(struct kvm_pgtable *pgt, u64 addr, u64 size, u64 phys,
u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift);
/**
- * kvm_pgtable_stage2_init_flags() - Initialise a guest stage-2 page-table.
+ * __kvm_pgtable_stage2_init() - Initialise a guest stage-2 page-table.
* @pgt: Uninitialised page-table structure to initialise.
* @arch: Arch-specific KVM structure representing the guest virtual
* machine.
* @mm_ops: Memory management callbacks.
* @flags: Stage-2 configuration flags.
+ * @force_pte_cb: Function that returns true if page level mappings must
+ * be used instead of block mappings.
*
* Return: 0 on success, negative error code on failure.
*/
-int kvm_pgtable_stage2_init_flags(struct kvm_pgtable *pgt, struct kvm_arch *arch,
- struct kvm_pgtable_mm_ops *mm_ops,
- enum kvm_pgtable_stage2_flags flags);
+int __kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_arch *arch,
+ struct kvm_pgtable_mm_ops *mm_ops,
+ enum kvm_pgtable_stage2_flags flags,
+ kvm_pgtable_force_pte_cb_t force_pte_cb);
#define kvm_pgtable_stage2_init(pgt, arch, mm_ops) \
- kvm_pgtable_stage2_init_flags(pgt, arch, mm_ops, 0)
+ __kvm_pgtable_stage2_init(pgt, arch, mm_ops, 0, NULL)
/**
* kvm_pgtable_stage2_destroy() - Destroy an unused guest stage-2 page-table.
@@ -374,7 +429,8 @@ kvm_pte_t kvm_pgtable_stage2_mkold(struct kvm_pgtable *pgt, u64 addr);
* If there is a valid, leaf page-table entry used to translate @addr, then
* relax the permissions in that entry according to the read, write and
* execute permissions specified by @prot. No permissions are removed, and
- * TLB invalidation is performed after updating the entry.
+ * TLB invalidation is performed after updating the entry. Software bits cannot
+ * be set or cleared using kvm_pgtable_stage2_relax_perms().
*
* Return: 0 on success, negative error code on failure.
*/
@@ -433,22 +489,42 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size,
struct kvm_pgtable_walker *walker);
/**
- * kvm_pgtable_stage2_find_range() - Find a range of Intermediate Physical
- * Addresses with compatible permission
- * attributes.
- * @pgt: Page-table structure initialised by kvm_pgtable_stage2_init*().
- * @addr: Address that must be covered by the range.
- * @prot: Protection attributes that the range must be compatible with.
- * @range: Range structure used to limit the search space at call time and
- * that will hold the result.
+ * kvm_pgtable_get_leaf() - Walk a page-table and retrieve the leaf entry
+ * with its level.
+ * @pgt: Page-table structure initialised by kvm_pgtable_*_init()
+ * or a similar initialiser.
+ * @addr: Input address for the start of the walk.
+ * @ptep: Pointer to storage for the retrieved PTE.
+ * @level: Pointer to storage for the level of the retrieved PTE.
+ *
+ * The offset of @addr within a page is ignored.
*
- * The offset of @addr within a page is ignored. An IPA is compatible with @prot
- * iff its corresponding stage-2 page-table entry has default ownership and, if
- * valid, is mapped with protection attributes identical to @prot.
+ * The walker will walk the page-table entries corresponding to the input
+ * address specified, retrieving the leaf corresponding to this address.
+ * Invalid entries are treated as leaf entries.
*
* Return: 0 on success, negative error code on failure.
*/
-int kvm_pgtable_stage2_find_range(struct kvm_pgtable *pgt, u64 addr,
- enum kvm_pgtable_prot prot,
- struct kvm_mem_range *range);
+int kvm_pgtable_get_leaf(struct kvm_pgtable *pgt, u64 addr,
+ kvm_pte_t *ptep, u32 *level);
+
+/**
+ * kvm_pgtable_stage2_pte_prot() - Retrieve the protection attributes of a
+ * stage-2 Page-Table Entry.
+ * @pte: Page-table entry
+ *
+ * Return: protection attributes of the page-table entry in the enum
+ * kvm_pgtable_prot format.
+ */
+enum kvm_pgtable_prot kvm_pgtable_stage2_pte_prot(kvm_pte_t pte);
+
+/**
+ * kvm_pgtable_hyp_pte_prot() - Retrieve the protection attributes of a stage-1
+ * Page-Table Entry.
+ * @pte: Page-table entry
+ *
+ * Return: protection attributes of the page-table entry in the enum
+ * kvm_pgtable_prot format.
+ */
+enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte);
#endif /* __ARM64_KVM_PGTABLE_H__ */
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 824a3655dd93..f1745a843414 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -243,9 +243,7 @@ static inline const void *__tag_set(const void *addr, u8 tag)
#ifdef CONFIG_KASAN_HW_TAGS
#define arch_enable_tagging_sync() mte_enable_kernel_sync()
#define arch_enable_tagging_async() mte_enable_kernel_async()
-#define arch_set_tagging_report_once(state) mte_set_report_once(state)
#define arch_force_async_tag_fault() mte_check_tfsr_exit()
-#define arch_init_tags(max_tag) mte_init_tags(max_tag)
#define arch_get_random_tag() mte_get_random_tag()
#define arch_get_mem_tag(addr) mte_get_mem_tag(addr)
#define arch_set_mem_tag_range(addr, size, tag, init) \
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 75beffe2ee8a..e9c30859f80c 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -27,11 +27,32 @@ typedef struct {
} mm_context_t;
/*
- * This macro is only used by the TLBI and low-level switch_mm() code,
- * neither of which can race with an ASID change. We therefore don't
- * need to reload the counter using atomic64_read().
+ * We use atomic64_read() here because the ASID for an 'mm_struct' can
+ * be reallocated when scheduling one of its threads following a
+ * rollover event (see new_context() and flush_context()). In this case,
+ * a concurrent TLBI (e.g. via try_to_unmap_one() and ptep_clear_flush())
+ * may use a stale ASID. This is fine in principle as the new ASID is
+ * guaranteed to be clean in the TLB, but the TLBI routines have to take
+ * care to handle the following race:
+ *
+ * CPU 0 CPU 1 CPU 2
+ *
+ * // ptep_clear_flush(mm)
+ * xchg_relaxed(pte, 0)
+ * DSB ISHST
+ * old = ASID(mm)
+ * | <rollover>
+ * | new = new_context(mm)
+ * \-----------------> atomic_set(mm->context.id, new)
+ * cpu_switch_mm(mm)
+ * // Hardware walk of pte using new ASID
+ * TLBI(old)
+ *
+ * In this scenario, the barrier on CPU 0 and the dependency on CPU 1
+ * ensure that the page-table walker on CPU 1 *must* see the invalid PTE
+ * written by CPU 0.
*/
-#define ASID(mm) ((mm)->context.id.counter & 0xffff)
+#define ASID(mm) (atomic64_read(&(mm)->context.id) & 0xffff)
static inline bool arm64_kernel_unmapped_at_el0(void)
{
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index eeb210997149..f4ba93d4ffeb 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -231,6 +231,19 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
update_saved_ttbr0(tsk, next);
}
+static inline const struct cpumask *
+task_cpu_possible_mask(struct task_struct *p)
+{
+ if (!static_branch_unlikely(&arm64_mismatched_32bit_el0))
+ return cpu_possible_mask;
+
+ if (!is_compat_thread(task_thread_info(p)))
+ return cpu_possible_mask;
+
+ return system_32bit_el0_cpumask();
+}
+#define task_cpu_possible_mask task_cpu_possible_mask
+
void verify_cpu_asid_bits(void);
void post_ttbr_update_workaround(void);
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
new file mode 100644
index 000000000000..20070a847304
--- /dev/null
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Linux-specific definitions for managing interactions with Microsoft's
+ * Hyper-V hypervisor. The definitions in this file are specific to
+ * the ARM64 architecture. See include/asm-generic/mshyperv.h for
+ * definitions are that architecture independent.
+ *
+ * Definitions that are specified in the Hyper-V Top Level Functional
+ * Spec (TLFS) should not go in this file, but should instead go in
+ * hyperv-tlfs.h.
+ *
+ * Copyright (C) 2021, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+#ifndef _ASM_MSHYPERV_H
+#define _ASM_MSHYPERV_H
+
+#include <linux/types.h>
+#include <linux/arm-smccc.h>
+#include <asm/hyperv-tlfs.h>
+
+/*
+ * Declare calls to get and set Hyper-V VP register values on ARM64, which
+ * requires a hypercall.
+ */
+
+void hv_set_vpreg(u32 reg, u64 value);
+u64 hv_get_vpreg(u32 reg);
+void hv_get_vpreg_128(u32 reg, struct hv_get_vp_registers_output *result);
+
+static inline void hv_set_register(unsigned int reg, u64 value)
+{
+ hv_set_vpreg(reg, value);
+}
+
+static inline u64 hv_get_register(unsigned int reg)
+{
+ return hv_get_vpreg(reg);
+}
+
+/* SMCCC hypercall parameters */
+#define HV_SMCCC_FUNC_NUMBER 1
+#define HV_FUNC_ID ARM_SMCCC_CALL_VAL( \
+ ARM_SMCCC_STD_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_VENDOR_HYP, \
+ HV_SMCCC_FUNC_NUMBER)
+
+#include <asm-generic/mshyperv.h>
+
+#endif
diff --git a/arch/arm64/include/asm/mte-kasan.h b/arch/arm64/include/asm/mte-kasan.h
index d952352bd008..22420e1f8c03 100644
--- a/arch/arm64/include/asm/mte-kasan.h
+++ b/arch/arm64/include/asm/mte-kasan.h
@@ -130,10 +130,6 @@ static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag,
void mte_enable_kernel_sync(void);
void mte_enable_kernel_async(void);
-void mte_init_tags(u64 max_tag);
-
-void mte_set_report_once(bool state);
-bool mte_report_once(void);
#else /* CONFIG_ARM64_MTE */
@@ -165,19 +161,6 @@ static inline void mte_enable_kernel_async(void)
{
}
-static inline void mte_init_tags(u64 max_tag)
-{
-}
-
-static inline void mte_set_report_once(bool state)
-{
-}
-
-static inline bool mte_report_once(void)
-{
- return false;
-}
-
#endif /* CONFIG_ARM64_MTE */
#endif /* __ASSEMBLY__ */
diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
index 58c7f80f5596..3f93b9e0b339 100644
--- a/arch/arm64/include/asm/mte.h
+++ b/arch/arm64/include/asm/mte.h
@@ -16,8 +16,6 @@
#include <asm/pgtable-types.h>
-extern u64 gcr_kernel_excl;
-
void mte_clear_page_tags(void *addr);
unsigned long mte_copy_tags_from_user(void *to, const void __user *from,
unsigned long n);
@@ -43,7 +41,6 @@ void mte_copy_page_tags(void *kto, const void *kfrom);
void mte_thread_init_user(void);
void mte_thread_switch(struct task_struct *next);
void mte_suspend_enter(void);
-void mte_suspend_exit(void);
long set_mte_ctrl(struct task_struct *task, unsigned long arg);
long get_mte_ctrl(struct task_struct *task);
int mte_ptrace_copy_tags(struct task_struct *child, long request,
@@ -72,9 +69,6 @@ static inline void mte_thread_switch(struct task_struct *next)
static inline void mte_suspend_enter(void)
{
}
-static inline void mte_suspend_exit(void)
-{
-}
static inline long set_mte_ctrl(struct task_struct *task, unsigned long arg)
{
return 0;
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index f09bf5c02891..dfa76afa0ccf 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -715,7 +715,7 @@ static inline pud_t *p4d_pgtable(p4d_t p4d)
return (pud_t *)__va(p4d_page_paddr(p4d));
}
-/* Find an entry in the frst-level page table. */
+/* Find an entry in the first-level page table. */
#define pud_offset_phys(dir, addr) (p4d_page_paddr(READ_ONCE(*(dir))) + pud_index(addr) * sizeof(pud_t))
#define pud_set_fixmap(addr) ((pud_t *)set_fixmap_offset(FIX_PUD, addr))
diff --git a/arch/arm64/include/asm/pointer_auth.h b/arch/arm64/include/asm/pointer_auth.h
index 28a78b67d9b4..efb098de3a84 100644
--- a/arch/arm64/include/asm/pointer_auth.h
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -10,6 +10,9 @@
#include <asm/memory.h>
#include <asm/sysreg.h>
+#define PR_PAC_ENABLED_KEYS_MASK \
+ (PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
+
#ifdef CONFIG_ARM64_PTR_AUTH
/*
* Each key is a 128-bit quantity which is split across a pair of 64-bit
@@ -117,9 +120,9 @@ static __always_inline void ptrauth_enable(void)
\
/* enable all keys */ \
if (system_supports_address_auth()) \
- set_task_sctlr_el1(current->thread.sctlr_user | \
- SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \
- SCTLR_ELx_ENDA | SCTLR_ELx_ENDB); \
+ ptrauth_set_enabled_keys(current, \
+ PR_PAC_ENABLED_KEYS_MASK, \
+ PR_PAC_ENABLED_KEYS_MASK); \
} while (0)
#define ptrauth_thread_switch_user(tsk) \
@@ -146,7 +149,4 @@ static __always_inline void ptrauth_enable(void)
#define ptrauth_thread_switch_kernel(tsk)
#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
-#define PR_PAC_ENABLED_KEYS_MASK \
- (PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
-
#endif /* __ASM_POINTER_AUTH_H */
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index b6517fd03d7b..ee2bdc1b9f5b 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -16,6 +16,12 @@
*/
#define NET_IP_ALIGN 0
+#define MTE_CTRL_GCR_USER_EXCL_SHIFT 0
+#define MTE_CTRL_GCR_USER_EXCL_MASK 0xffff
+
+#define MTE_CTRL_TCF_SYNC (1UL << 16)
+#define MTE_CTRL_TCF_ASYNC (1UL << 17)
+
#ifndef __ASSEMBLY__
#include <linux/build_bug.h>
@@ -153,7 +159,7 @@ struct thread_struct {
#endif
#endif
#ifdef CONFIG_ARM64_MTE
- u64 gcr_user_excl;
+ u64 mte_ctrl;
#endif
u64 sctlr_user;
};
@@ -253,7 +259,7 @@ extern void release_thread(struct task_struct *);
unsigned long get_wchan(struct task_struct *p);
-void set_task_sctlr_el1(u64 sctlr);
+void update_sctlr_el1(u64 sctlr);
/* Thread switching */
extern struct task_struct *cpu_switch_to(struct task_struct *prev,
diff --git a/arch/arm64/include/asm/simd.h b/arch/arm64/include/asm/simd.h
index 89cba2622b79..6a75d7ecdcaa 100644
--- a/arch/arm64/include/asm/simd.h
+++ b/arch/arm64/include/asm/simd.h
@@ -37,7 +37,7 @@ static __must_check inline bool may_use_simd(void)
*/
return !WARN_ON(!system_capabilities_finalized()) &&
system_supports_fpsimd() &&
- !in_irq() && !irqs_disabled() && !in_nmi() &&
+ !in_hardirq() && !irqs_disabled() && !in_nmi() &&
!this_cpu_read(fpsimd_context_busy);
}
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 7b9c3acba684..b268082d67ed 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -11,6 +11,7 @@
#include <linux/bits.h>
#include <linux/stringify.h>
+#include <linux/kasan-tags.h>
/*
* ARMv8 ARM reserves the following encoding for system registers:
@@ -698,8 +699,7 @@
(SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_SA | SCTLR_EL1_SA0 | \
SCTLR_EL1_SED | SCTLR_ELx_I | SCTLR_EL1_DZE | SCTLR_EL1_UCT | \
SCTLR_EL1_NTWE | SCTLR_ELx_IESB | SCTLR_EL1_SPAN | SCTLR_ELx_ITFSB | \
- SCTLR_ELx_ATA | SCTLR_EL1_ATA0 | ENDIAN_SET_EL1 | SCTLR_EL1_UCI | \
- SCTLR_EL1_EPAN | SCTLR_EL1_RES1)
+ ENDIAN_SET_EL1 | SCTLR_EL1_UCI | SCTLR_EL1_EPAN | SCTLR_EL1_RES1)
/* MAIR_ELx memory attributes (used by Linux) */
#define MAIR_ATTR_DEVICE_nGnRnE UL(0x00)
@@ -784,14 +784,13 @@
#define ID_AA64PFR0_AMU 0x1
#define ID_AA64PFR0_SVE 0x1
#define ID_AA64PFR0_RAS_V1 0x1
+#define ID_AA64PFR0_RAS_V1P1 0x2
#define ID_AA64PFR0_FP_NI 0xf
#define ID_AA64PFR0_FP_SUPPORTED 0x0
#define ID_AA64PFR0_ASIMD_NI 0xf
#define ID_AA64PFR0_ASIMD_SUPPORTED 0x0
-#define ID_AA64PFR0_EL1_64BIT_ONLY 0x1
-#define ID_AA64PFR0_EL1_32BIT_64BIT 0x2
-#define ID_AA64PFR0_EL0_64BIT_ONLY 0x1
-#define ID_AA64PFR0_EL0_32BIT_64BIT 0x2
+#define ID_AA64PFR0_ELx_64BIT_ONLY 0x1
+#define ID_AA64PFR0_ELx_32BIT_64BIT 0x2
/* id_aa64pfr1 */
#define ID_AA64PFR1_MPAMFRAC_SHIFT 16
@@ -847,15 +846,29 @@
#define ID_AA64MMFR0_ASID_SHIFT 4
#define ID_AA64MMFR0_PARANGE_SHIFT 0
-#define ID_AA64MMFR0_TGRAN4_NI 0xf
-#define ID_AA64MMFR0_TGRAN4_SUPPORTED 0x0
-#define ID_AA64MMFR0_TGRAN64_NI 0xf
-#define ID_AA64MMFR0_TGRAN64_SUPPORTED 0x0
-#define ID_AA64MMFR0_TGRAN16_NI 0x0
-#define ID_AA64MMFR0_TGRAN16_SUPPORTED 0x1
+#define ID_AA64MMFR0_ASID_8 0x0
+#define ID_AA64MMFR0_ASID_16 0x2
+
+#define ID_AA64MMFR0_TGRAN4_NI 0xf
+#define ID_AA64MMFR0_TGRAN4_SUPPORTED_MIN 0x0
+#define ID_AA64MMFR0_TGRAN4_SUPPORTED_MAX 0x7
+#define ID_AA64MMFR0_TGRAN64_NI 0xf
+#define ID_AA64MMFR0_TGRAN64_SUPPORTED_MIN 0x0
+#define ID_AA64MMFR0_TGRAN64_SUPPORTED_MAX 0x7
+#define ID_AA64MMFR0_TGRAN16_NI 0x0
+#define ID_AA64MMFR0_TGRAN16_SUPPORTED_MIN 0x1
+#define ID_AA64MMFR0_TGRAN16_SUPPORTED_MAX 0xf
+
+#define ID_AA64MMFR0_PARANGE_32 0x0
+#define ID_AA64MMFR0_PARANGE_36 0x1
+#define ID_AA64MMFR0_PARANGE_40 0x2
+#define ID_AA64MMFR0_PARANGE_42 0x3
+#define ID_AA64MMFR0_PARANGE_44 0x4
#define ID_AA64MMFR0_PARANGE_48 0x5
#define ID_AA64MMFR0_PARANGE_52 0x6
+#define ARM64_MIN_PARANGE_BITS 32
+
#define ID_AA64MMFR0_TGRAN_2_SUPPORTED_DEFAULT 0x0
#define ID_AA64MMFR0_TGRAN_2_SUPPORTED_NONE 0x1
#define ID_AA64MMFR0_TGRAN_2_SUPPORTED_MIN 0x2
@@ -900,6 +913,7 @@
#define ID_AA64MMFR2_CNP_SHIFT 0
/* id_aa64dfr0 */
+#define ID_AA64DFR0_MTPMU_SHIFT 48
#define ID_AA64DFR0_TRBE_SHIFT 44
#define ID_AA64DFR0_TRACE_FILT_SHIFT 40
#define ID_AA64DFR0_DOUBLELOCK_SHIFT 36
@@ -1028,16 +1042,19 @@
#if defined(CONFIG_ARM64_4K_PAGES)
#define ID_AA64MMFR0_TGRAN_SHIFT ID_AA64MMFR0_TGRAN4_SHIFT
-#define ID_AA64MMFR0_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_TGRAN4_SUPPORTED
-#define ID_AA64MMFR0_TGRAN_SUPPORTED_MAX 0x7
+#define ID_AA64MMFR0_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_TGRAN4_SUPPORTED_MIN
+#define ID_AA64MMFR0_TGRAN_SUPPORTED_MAX ID_AA64MMFR0_TGRAN4_SUPPORTED_MAX
+#define ID_AA64MMFR0_TGRAN_2_SHIFT ID_AA64MMFR0_TGRAN4_2_SHIFT
#elif defined(CONFIG_ARM64_16K_PAGES)
#define ID_AA64MMFR0_TGRAN_SHIFT ID_AA64MMFR0_TGRAN16_SHIFT
-#define ID_AA64MMFR0_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_TGRAN16_SUPPORTED
-#define ID_AA64MMFR0_TGRAN_SUPPORTED_MAX 0xF
+#define ID_AA64MMFR0_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_TGRAN16_SUPPORTED_MIN
+#define ID_AA64MMFR0_TGRAN_SUPPORTED_MAX ID_AA64MMFR0_TGRAN16_SUPPORTED_MAX
+#define ID_AA64MMFR0_TGRAN_2_SHIFT ID_AA64MMFR0_TGRAN16_2_SHIFT
#elif defined(CONFIG_ARM64_64K_PAGES)
#define ID_AA64MMFR0_TGRAN_SHIFT ID_AA64MMFR0_TGRAN64_SHIFT
-#define ID_AA64MMFR0_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_TGRAN64_SUPPORTED
-#define ID_AA64MMFR0_TGRAN_SUPPORTED_MAX 0x7
+#define ID_AA64MMFR0_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_TGRAN64_SUPPORTED_MIN
+#define ID_AA64MMFR0_TGRAN_SUPPORTED_MAX ID_AA64MMFR0_TGRAN64_SUPPORTED_MAX
+#define ID_AA64MMFR0_TGRAN_2_SHIFT ID_AA64MMFR0_TGRAN64_2_SHIFT
#endif
#define MVFR2_FPMISC_SHIFT 4
@@ -1067,6 +1084,21 @@
#define SYS_GCR_EL1_RRND (BIT(16))
#define SYS_GCR_EL1_EXCL_MASK 0xffffUL
+#ifdef CONFIG_KASAN_HW_TAGS
+/*
+ * KASAN always uses a whole byte for its tags. With CONFIG_KASAN_HW_TAGS it
+ * only uses tags in the range 0xF0-0xFF, which we map to MTE tags 0x0-0xF.
+ */
+#define __MTE_TAG_MIN (KASAN_TAG_MIN & 0xf)
+#define __MTE_TAG_MAX (KASAN_TAG_MAX & 0xf)
+#define __MTE_TAG_INCL GENMASK(__MTE_TAG_MAX, __MTE_TAG_MIN)
+#define KERNEL_GCR_EL1_EXCL (SYS_GCR_EL1_EXCL_MASK & ~__MTE_TAG_INCL)
+#else
+#define KERNEL_GCR_EL1_EXCL SYS_GCR_EL1_EXCL_MASK
+#endif
+
+#define KERNEL_GCR_EL1 (SYS_GCR_EL1_RRND | KERNEL_GCR_EL1_EXCL)
+
/* RGSR_EL1 Definitions */
#define SYS_RGSR_EL1_TAG_MASK 0xfUL
#define SYS_RGSR_EL1_SEED_SHIFT 8
@@ -1153,6 +1185,11 @@
#define ICH_VTR_A3V_SHIFT 21
#define ICH_VTR_A3V_MASK (1 << ICH_VTR_A3V_SHIFT)
+#define ARM64_FEATURE_FIELD_BITS 4
+
+/* Create a mask for the feature bits of the specified feature. */
+#define ARM64_FEATURE_MASK(x) (GENMASK_ULL(x##_SHIFT + ARM64_FEATURE_FIELD_BITS - 1, x##_SHIFT))
+
#ifdef __ASSEMBLY__
.irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index cc3f5a33ff9c..412a3b9a3c25 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -245,9 +245,10 @@ static inline void flush_tlb_all(void)
static inline void flush_tlb_mm(struct mm_struct *mm)
{
- unsigned long asid = __TLBI_VADDR(0, ASID(mm));
+ unsigned long asid;
dsb(ishst);
+ asid = __TLBI_VADDR(0, ASID(mm));
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
dsb(ish);
@@ -256,9 +257,10 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
static inline void flush_tlb_page_nosync(struct vm_area_struct *vma,
unsigned long uaddr)
{
- unsigned long addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm));
+ unsigned long addr;
dsb(ishst);
+ addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm));
__tlbi(vale1is, addr);
__tlbi_user(vale1is, addr);
}
@@ -283,9 +285,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
{
int num = 0;
int scale = 0;
- unsigned long asid = ASID(vma->vm_mm);
- unsigned long addr;
- unsigned long pages;
+ unsigned long asid, addr, pages;
start = round_down(start, stride);
end = round_up(end, stride);
@@ -305,10 +305,11 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
}
dsb(ishst);
+ asid = ASID(vma->vm_mm);
/*
* When the CPU does not support TLB range operations, flush the TLB
- * entries one by one at the granularity of 'stride'. If the the TLB
+ * entries one by one at the granularity of 'stride'. If the TLB
* range ops are supported, then:
*
* 1. If 'pages' is odd, flush the first page through non-range
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 727bfc3be99b..3cb206aea3db 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -38,7 +38,7 @@
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
#define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
-#define __NR_compat_syscalls 447
+#define __NR_compat_syscalls 449
#endif
#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 99ffcafc736c..4e99e4b912ef 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -279,7 +279,7 @@ __SYSCALL(__NR_getpgid, sys_getpgid)
#define __NR_fchdir 133
__SYSCALL(__NR_fchdir, sys_fchdir)
#define __NR_bdflush 134
-__SYSCALL(__NR_bdflush, sys_bdflush)
+__SYSCALL(__NR_bdflush, sys_ni_syscall)
#define __NR_sysfs 135
__SYSCALL(__NR_sysfs, sys_sysfs)
#define __NR_personality 136
@@ -901,6 +901,8 @@ __SYSCALL(__NR_landlock_create_ruleset, sys_landlock_create_ruleset)
__SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule)
#define __NR_landlock_restrict_self 446
__SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self)
+#define __NR_process_mrelease 448
+__SYSCALL(__NR_process_mrelease, sys_process_mrelease)
/*
* Please add new compat syscalls above this comment and update
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index c85670692afa..551427ae8cc5 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -52,7 +52,7 @@ int main(void)
DEFINE(THREAD_KEYS_KERNEL, offsetof(struct task_struct, thread.keys_kernel));
#endif
#ifdef CONFIG_ARM64_MTE
- DEFINE(THREAD_GCR_EL1_USER, offsetof(struct task_struct, thread.gcr_user_excl));
+ DEFINE(THREAD_MTE_CTRL, offsetof(struct task_struct, thread.mte_ctrl));
#endif
BLANK();
DEFINE(S_X0, offsetof(struct pt_regs, regs[0]));
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 0ead8bfedf20..f8a3067d10c6 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -67,6 +67,7 @@
#include <linux/crash_dump.h>
#include <linux/sort.h>
#include <linux/stop_machine.h>
+#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/minmax.h>
#include <linux/mm.h>
@@ -239,8 +240,8 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL3_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL2_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_ELx_64BIT_ONLY),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_ELx_64BIT_ONLY),
ARM64_FTR_END,
};
@@ -1321,6 +1322,31 @@ const struct cpumask *system_32bit_el0_cpumask(void)
return cpu_possible_mask;
}
+static int __init parse_32bit_el0_param(char *str)
+{
+ allow_mismatched_32bit_el0 = true;
+ return 0;
+}
+early_param("allow_mismatched_32bit_el0", parse_32bit_el0_param);
+
+static ssize_t aarch32_el0_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct cpumask *mask = system_32bit_el0_cpumask();
+
+ return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
+}
+static const DEVICE_ATTR_RO(aarch32_el0);
+
+static int __init aarch32_el0_sysfs_init(void)
+{
+ if (!allow_mismatched_32bit_el0)
+ return 0;
+
+ return device_create_file(cpu_subsys.dev_root, &dev_attr_aarch32_el0);
+}
+device_initcall(aarch32_el0_sysfs_init);
+
static bool has_32bit_el0(const struct arm64_cpu_capabilities *entry, int scope)
{
if (!has_cpuid_feature(entry, scope))
@@ -1561,8 +1587,6 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
if (!cpu)
arm64_use_ng_mappings = true;
-
- return;
}
#else
static void
@@ -1734,7 +1758,7 @@ static void cpu_has_fwb(const struct arm64_cpu_capabilities *__unused)
u64 val = read_sysreg_s(SYS_CLIDR_EL1);
/* Check that CLIDR_EL1.LOU{U,IS} are both 0 */
- WARN_ON(val & (7 << 27 | 7 << 21));
+ WARN_ON(CLIDR_LOUU(val) || CLIDR_LOUIS(val));
}
#ifdef CONFIG_ARM64_PAN
@@ -1843,6 +1867,9 @@ static void bti_enable(const struct arm64_cpu_capabilities *__unused)
#ifdef CONFIG_ARM64_MTE
static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)
{
+ sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_ATA | SCTLR_EL1_ATA0);
+ isb();
+
/*
* Clear the tags in the zero page. This needs to be done via the
* linear map which has the Tagged attribute.
@@ -1956,7 +1983,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.sys_reg = SYS_ID_AA64PFR0_EL1,
.sign = FTR_UNSIGNED,
.field_pos = ID_AA64PFR0_EL0_SHIFT,
- .min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT,
+ .min_field_value = ID_AA64PFR0_ELx_32BIT_64BIT,
},
#ifdef CONFIG_KVM
{
@@ -1967,7 +1994,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.sys_reg = SYS_ID_AA64PFR0_EL1,
.sign = FTR_UNSIGNED,
.field_pos = ID_AA64PFR0_EL1_SHIFT,
- .min_field_value = ID_AA64PFR0_EL1_32BIT_64BIT,
+ .min_field_value = ID_AA64PFR0_ELx_32BIT_64BIT,
},
{
.desc = "Protected KVM",
@@ -2901,15 +2928,38 @@ void __init setup_cpu_features(void)
static int enable_mismatched_32bit_el0(unsigned int cpu)
{
+ /*
+ * The first 32-bit-capable CPU we detected and so can no longer
+ * be offlined by userspace. -1 indicates we haven't yet onlined
+ * a 32-bit-capable CPU.
+ */
+ static int lucky_winner = -1;
+
struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
bool cpu_32bit = id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0);
if (cpu_32bit) {
cpumask_set_cpu(cpu, cpu_32bit_el0_mask);
static_branch_enable_cpuslocked(&arm64_mismatched_32bit_el0);
- setup_elf_hwcaps(compat_elf_hwcaps);
}
+ if (cpumask_test_cpu(0, cpu_32bit_el0_mask) == cpu_32bit)
+ return 0;
+
+ if (lucky_winner >= 0)
+ return 0;
+
+ /*
+ * We've detected a mismatch. We need to keep one of our CPUs with
+ * 32-bit EL0 online so that is_cpu_allowed() doesn't end up rejecting
+ * every CPU in the system for a 32-bit task.
+ */
+ lucky_winner = cpu_32bit ? cpu : cpumask_any_and(cpu_32bit_el0_mask,
+ cpu_active_mask);
+ get_cpu_device(lucky_winner)->offline_disabled = true;
+ setup_elf_hwcaps(compat_elf_hwcaps);
+ pr_info("Asymmetric 32-bit EL0 support detected on CPU %u; CPU hot-unplug disabled on CPU %u\n",
+ cpu, lucky_winner);
return 0;
}
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index fa02efb28e88..e1be6c429810 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -55,6 +55,7 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
/* we will fill this structure from the stub, so don't put it in .bss */
struct screen_info screen_info __section(".data");
+EXPORT_SYMBOL(screen_info);
int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
{
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index db8b2e2d02c2..32f9796c4ffe 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -26,10 +26,14 @@
#include <asm/system_misc.h>
/*
+ * Handle IRQ/context state management when entering from kernel mode.
+ * Before this function is called it is not safe to call regular kernel code,
+ * intrumentable code, or any code which may trigger an exception.
+ *
* This is intended to match the logic in irqentry_enter(), handling the kernel
* mode transitions only.
*/
-static void noinstr enter_from_kernel_mode(struct pt_regs *regs)
+static __always_inline void __enter_from_kernel_mode(struct pt_regs *regs)
{
regs->exit_rcu = false;
@@ -45,20 +49,26 @@ static void noinstr enter_from_kernel_mode(struct pt_regs *regs)
lockdep_hardirqs_off(CALLER_ADDR0);
rcu_irq_enter_check_tick();
trace_hardirqs_off_finish();
+}
+static void noinstr enter_from_kernel_mode(struct pt_regs *regs)
+{
+ __enter_from_kernel_mode(regs);
mte_check_tfsr_entry();
}
/*
+ * Handle IRQ/context state management when exiting to kernel mode.
+ * After this function returns it is not safe to call regular kernel code,
+ * intrumentable code, or any code which may trigger an exception.
+ *
* This is intended to match the logic in irqentry_exit(), handling the kernel
* mode transitions only, and with preemption handled elsewhere.
*/
-static void noinstr exit_to_kernel_mode(struct pt_regs *regs)
+static __always_inline void __exit_to_kernel_mode(struct pt_regs *regs)
{
lockdep_assert_irqs_disabled();
- mte_check_tfsr_exit();
-
if (interrupts_enabled(regs)) {
if (regs->exit_rcu) {
trace_hardirqs_on_prepare();
@@ -75,6 +85,71 @@ static void noinstr exit_to_kernel_mode(struct pt_regs *regs)
}
}
+static void noinstr exit_to_kernel_mode(struct pt_regs *regs)
+{
+ mte_check_tfsr_exit();
+ __exit_to_kernel_mode(regs);
+}
+
+/*
+ * Handle IRQ/context state management when entering from user mode.
+ * Before this function is called it is not safe to call regular kernel code,
+ * intrumentable code, or any code which may trigger an exception.
+ */
+static __always_inline void __enter_from_user_mode(void)
+{
+ lockdep_hardirqs_off(CALLER_ADDR0);
+ CT_WARN_ON(ct_state() != CONTEXT_USER);
+ user_exit_irqoff();
+ trace_hardirqs_off_finish();
+}
+
+static __always_inline void enter_from_user_mode(struct pt_regs *regs)
+{
+ __enter_from_user_mode();
+}
+
+/*
+ * Handle IRQ/context state management when exiting to user mode.
+ * After this function returns it is not safe to call regular kernel code,
+ * intrumentable code, or any code which may trigger an exception.
+ */
+static __always_inline void __exit_to_user_mode(void)
+{
+ trace_hardirqs_on_prepare();
+ lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+ user_enter_irqoff();
+ lockdep_hardirqs_on(CALLER_ADDR0);
+}
+
+static __always_inline void prepare_exit_to_user_mode(struct pt_regs *regs)
+{
+ unsigned long flags;
+
+ local_daif_mask();
+
+ flags = READ_ONCE(current_thread_info()->flags);
+ if (unlikely(flags & _TIF_WORK_MASK))
+ do_notify_resume(regs, flags);
+}
+
+static __always_inline void exit_to_user_mode(struct pt_regs *regs)
+{
+ prepare_exit_to_user_mode(regs);
+ mte_check_tfsr_exit();
+ __exit_to_user_mode();
+}
+
+asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
+{
+ exit_to_user_mode(regs);
+}
+
+/*
+ * Handle IRQ/context state management when entering an NMI from user/kernel
+ * mode. Before this function is called it is not safe to call regular kernel
+ * code, intrumentable code, or any code which may trigger an exception.
+ */
static void noinstr arm64_enter_nmi(struct pt_regs *regs)
{
regs->lockdep_hardirqs = lockdep_hardirqs_enabled();
@@ -88,6 +163,11 @@ static void noinstr arm64_enter_nmi(struct pt_regs *regs)
ftrace_nmi_enter();
}
+/*
+ * Handle IRQ/context state management when exiting an NMI from user/kernel
+ * mode. After this function returns it is not safe to call regular kernel
+ * code, intrumentable code, or any code which may trigger an exception.
+ */
static void noinstr arm64_exit_nmi(struct pt_regs *regs)
{
bool restore = regs->lockdep_hardirqs;
@@ -105,6 +185,40 @@ static void noinstr arm64_exit_nmi(struct pt_regs *regs)
__nmi_exit();
}
+/*
+ * Handle IRQ/context state management when entering a debug exception from
+ * kernel mode. Before this function is called it is not safe to call regular
+ * kernel code, intrumentable code, or any code which may trigger an exception.
+ */
+static void noinstr arm64_enter_el1_dbg(struct pt_regs *regs)
+{
+ regs->lockdep_hardirqs = lockdep_hardirqs_enabled();
+
+ lockdep_hardirqs_off(CALLER_ADDR0);
+ rcu_nmi_enter();
+
+ trace_hardirqs_off_finish();
+}
+
+/*
+ * Handle IRQ/context state management when exiting a debug exception from
+ * kernel mode. After this function returns it is not safe to call regular
+ * kernel code, intrumentable code, or any code which may trigger an exception.
+ */
+static void noinstr arm64_exit_el1_dbg(struct pt_regs *regs)
+{
+ bool restore = regs->lockdep_hardirqs;
+
+ if (restore) {
+ trace_hardirqs_on_prepare();
+ lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+ }
+
+ rcu_nmi_exit();
+ if (restore)
+ lockdep_hardirqs_on(CALLER_ADDR0);
+}
+
static void noinstr enter_el1_irq_or_nmi(struct pt_regs *regs)
{
if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && !interrupts_enabled(regs))
@@ -265,30 +379,6 @@ static void noinstr el1_undef(struct pt_regs *regs)
exit_to_kernel_mode(regs);
}
-static void noinstr arm64_enter_el1_dbg(struct pt_regs *regs)
-{
- regs->lockdep_hardirqs = lockdep_hardirqs_enabled();
-
- lockdep_hardirqs_off(CALLER_ADDR0);
- rcu_nmi_enter();
-
- trace_hardirqs_off_finish();
-}
-
-static void noinstr arm64_exit_el1_dbg(struct pt_regs *regs)
-{
- bool restore = regs->lockdep_hardirqs;
-
- if (restore) {
- trace_hardirqs_on_prepare();
- lockdep_hardirqs_on_prepare(CALLER_ADDR0);
- }
-
- rcu_nmi_exit();
- if (restore)
- lockdep_hardirqs_on(CALLER_ADDR0);
-}
-
static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
{
unsigned long far = read_sysreg(far_el1);
@@ -382,31 +472,14 @@ asmlinkage void noinstr el1h_64_error_handler(struct pt_regs *regs)
arm64_exit_nmi(regs);
}
-asmlinkage void noinstr enter_from_user_mode(void)
-{
- lockdep_hardirqs_off(CALLER_ADDR0);
- CT_WARN_ON(ct_state() != CONTEXT_USER);
- user_exit_irqoff();
- trace_hardirqs_off_finish();
-}
-
-asmlinkage void noinstr exit_to_user_mode(void)
-{
- mte_check_tfsr_exit();
-
- trace_hardirqs_on_prepare();
- lockdep_hardirqs_on_prepare(CALLER_ADDR0);
- user_enter_irqoff();
- lockdep_hardirqs_on(CALLER_ADDR0);
-}
-
static void noinstr el0_da(struct pt_regs *regs, unsigned long esr)
{
unsigned long far = read_sysreg(far_el1);
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_mem_abort(far, esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_ia(struct pt_regs *regs, unsigned long esr)
@@ -421,37 +494,42 @@ static void noinstr el0_ia(struct pt_regs *regs, unsigned long esr)
if (!is_ttbr0_addr(far))
arm64_apply_bp_hardening();
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_mem_abort(far, esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_fpsimd_acc(struct pt_regs *regs, unsigned long esr)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_fpsimd_acc(esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_sve_acc(struct pt_regs *regs, unsigned long esr)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_sve_acc(esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_fpsimd_exc(struct pt_regs *regs, unsigned long esr)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_fpsimd_exc(esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_sys(struct pt_regs *regs, unsigned long esr)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_sysinstr(esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_pc(struct pt_regs *regs, unsigned long esr)
@@ -461,37 +539,42 @@ static void noinstr el0_pc(struct pt_regs *regs, unsigned long esr)
if (!is_ttbr0_addr(instruction_pointer(regs)))
arm64_apply_bp_hardening();
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_sp_pc_abort(far, esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_sp(struct pt_regs *regs, unsigned long esr)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_sp_pc_abort(regs->sp, esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_undef(struct pt_regs *regs)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_undefinstr(regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_bti(struct pt_regs *regs)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_bti(regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_inv(struct pt_regs *regs, unsigned long esr)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
bad_el0_sync(regs, 0, esr);
+ exit_to_user_mode(regs);
}
static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
@@ -499,23 +582,26 @@ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
/* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
unsigned long far = read_sysreg(far_el1);
- enter_from_user_mode();
+ enter_from_user_mode(regs);
do_debug_exception(far, esr, regs);
local_daif_restore(DAIF_PROCCTX);
+ exit_to_user_mode(regs);
}
static void noinstr el0_svc(struct pt_regs *regs)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
cortex_a76_erratum_1463225_svc_handler();
do_el0_svc(regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_fpac(struct pt_regs *regs, unsigned long esr)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_ptrauth_fault(regs, esr);
+ exit_to_user_mode(regs);
}
asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
@@ -574,7 +660,7 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
static void noinstr el0_interrupt(struct pt_regs *regs,
void (*handler)(struct pt_regs *))
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
write_sysreg(DAIF_PROCCTX_NOIRQ, daif);
@@ -582,6 +668,8 @@ static void noinstr el0_interrupt(struct pt_regs *regs,
arm64_apply_bp_hardening();
do_interrupt_handler(regs, handler);
+
+ exit_to_user_mode(regs);
}
static void noinstr __el0_irq_handler_common(struct pt_regs *regs)
@@ -608,12 +696,13 @@ static void noinstr __el0_error_handler_common(struct pt_regs *regs)
{
unsigned long esr = read_sysreg(esr_el1);
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_ERRCTX);
arm64_enter_nmi(regs);
do_serror(regs, esr);
arm64_exit_nmi(regs);
local_daif_restore(DAIF_PROCCTX);
+ exit_to_user_mode(regs);
}
asmlinkage void noinstr el0t_64_error_handler(struct pt_regs *regs)
@@ -624,16 +713,18 @@ asmlinkage void noinstr el0t_64_error_handler(struct pt_regs *regs)
#ifdef CONFIG_COMPAT
static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
do_cp15instr(esr, regs);
+ exit_to_user_mode(regs);
}
static void noinstr el0_svc_compat(struct pt_regs *regs)
{
- enter_from_user_mode();
+ enter_from_user_mode(regs);
cortex_a76_erratum_1463225_svc_handler();
do_el0_svc_compat(regs);
+ exit_to_user_mode(regs);
}
asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs)
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S
index 0a7a64753878..196e921f61de 100644
--- a/arch/arm64/kernel/entry-fpsimd.S
+++ b/arch/arm64/kernel/entry-fpsimd.S
@@ -33,11 +33,24 @@ SYM_FUNC_END(fpsimd_load_state)
#ifdef CONFIG_ARM64_SVE
+/*
+ * Save the SVE state
+ *
+ * x0 - pointer to buffer for state
+ * x1 - pointer to storage for FPSR
+ */
SYM_FUNC_START(sve_save_state)
sve_save 0, x1, 2
ret
SYM_FUNC_END(sve_save_state)
+/*
+ * Load the SVE state
+ *
+ * x0 - pointer to buffer for state
+ * x1 - pointer to storage for FPSR
+ * x2 - VQ-1
+ */
SYM_FUNC_START(sve_load_state)
sve_load 0, x1, x2, 3, x4
ret
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 863d44f73028..bc6d5a970a13 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -29,16 +29,6 @@
#include <asm/asm-uaccess.h>
#include <asm/unistd.h>
-/*
- * Context tracking and irqflag tracing need to instrument transitions between
- * user and kernel mode.
- */
- .macro user_enter_irqoff
-#if defined(CONFIG_CONTEXT_TRACKING) || defined(CONFIG_TRACE_IRQFLAGS)
- bl exit_to_user_mode
-#endif
- .endm
-
.macro clear_gp_regs
.irp n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
mov x\n, xzr
@@ -133,42 +123,46 @@ alternative_cb_end
.endm
/* Check for MTE asynchronous tag check faults */
- .macro check_mte_async_tcf, tmp, ti_flags
+ .macro check_mte_async_tcf, tmp, ti_flags, thread_sctlr
#ifdef CONFIG_ARM64_MTE
.arch_extension lse
alternative_if_not ARM64_MTE
b 1f
alternative_else_nop_endif
+ /*
+ * Asynchronous tag check faults are only possible in ASYNC (2) or
+ * ASYM (3) modes. In each of these modes bit 1 of SCTLR_EL1.TCF0 is
+ * set, so skip the check if it is unset.
+ */
+ tbz \thread_sctlr, #(SCTLR_EL1_TCF0_SHIFT + 1), 1f
mrs_s \tmp, SYS_TFSRE0_EL1
tbz \tmp, #SYS_TFSR_EL1_TF0_SHIFT, 1f
/* Asynchronous TCF occurred for TTBR0 access, set the TI flag */
mov \tmp, #_TIF_MTE_ASYNC_FAULT
add \ti_flags, tsk, #TSK_TI_FLAGS
stset \tmp, [\ti_flags]
- msr_s SYS_TFSRE0_EL1, xzr
1:
#endif
.endm
/* Clear the MTE asynchronous tag check faults */
- .macro clear_mte_async_tcf
+ .macro clear_mte_async_tcf thread_sctlr
#ifdef CONFIG_ARM64_MTE
alternative_if ARM64_MTE
+ /* See comment in check_mte_async_tcf above. */
+ tbz \thread_sctlr, #(SCTLR_EL1_TCF0_SHIFT + 1), 1f
dsb ish
msr_s SYS_TFSRE0_EL1, xzr
+1:
alternative_else_nop_endif
#endif
.endm
- .macro mte_set_gcr, tmp, tmp2
+ .macro mte_set_gcr, mte_ctrl, tmp
#ifdef CONFIG_ARM64_MTE
- /*
- * Calculate and set the exclude mask preserving
- * the RRND (bit[16]) setting.
- */
- mrs_s \tmp2, SYS_GCR_EL1
- bfi \tmp2, \tmp, #0, #16
- msr_s SYS_GCR_EL1, \tmp2
+ ubfx \tmp, \mte_ctrl, #MTE_CTRL_GCR_USER_EXCL_SHIFT, #16
+ orr \tmp, \tmp, #SYS_GCR_EL1_RRND
+ msr_s SYS_GCR_EL1, \tmp
#endif
.endm
@@ -177,10 +171,8 @@ alternative_else_nop_endif
alternative_if_not ARM64_MTE
b 1f
alternative_else_nop_endif
- ldr_l \tmp, gcr_kernel_excl
-
- mte_set_gcr \tmp, \tmp2
- isb
+ mov \tmp, KERNEL_GCR_EL1
+ msr_s SYS_GCR_EL1, \tmp
1:
#endif
.endm
@@ -190,7 +182,7 @@ alternative_else_nop_endif
alternative_if_not ARM64_MTE
b 1f
alternative_else_nop_endif
- ldr \tmp, [\tsk, #THREAD_GCR_EL1_USER]
+ ldr \tmp, [\tsk, #THREAD_MTE_CTRL]
mte_set_gcr \tmp, \tmp2
1:
@@ -231,8 +223,8 @@ alternative_else_nop_endif
disable_step_tsk x19, x20
/* Check for asynchronous tag check faults in user space */
- check_mte_async_tcf x22, x23
- apply_ssbd 1, x22, x23
+ ldr x0, [tsk, THREAD_SCTLR_USER]
+ check_mte_async_tcf x22, x23, x0
#ifdef CONFIG_ARM64_PTR_AUTH
alternative_if ARM64_HAS_ADDRESS_AUTH
@@ -245,7 +237,6 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
* was disabled on kernel exit then we would have left the kernel IA
* installed so there is no need to install it again.
*/
- ldr x0, [tsk, THREAD_SCTLR_USER]
tbz x0, SCTLR_ELx_ENIA_SHIFT, 1f
__ptrauth_keys_install_kernel_nosync tsk, x20, x22, x23
b 2f
@@ -254,12 +245,26 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
orr x0, x0, SCTLR_ELx_ENIA
msr sctlr_el1, x0
2:
- isb
alternative_else_nop_endif
#endif
+ apply_ssbd 1, x22, x23
+
mte_set_kernel_gcr x22, x23
+ /*
+ * Any non-self-synchronizing system register updates required for
+ * kernel entry should be placed before this point.
+ */
+alternative_if ARM64_MTE
+ isb
+ b 1f
+alternative_else_nop_endif
+alternative_if ARM64_HAS_ADDRESS_AUTH
+ isb
+alternative_else_nop_endif
+1:
+
scs_load tsk
.else
add x21, sp, #PT_REGS_SIZE
@@ -362,6 +367,10 @@ alternative_else_nop_endif
3:
scs_save tsk
+ /* Ignore asynchronous tag check faults in the uaccess routines */
+ ldr x0, [tsk, THREAD_SCTLR_USER]
+ clear_mte_async_tcf x0
+
#ifdef CONFIG_ARM64_PTR_AUTH
alternative_if ARM64_HAS_ADDRESS_AUTH
/*
@@ -371,7 +380,6 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
*
* No kernel C function calls after this.
*/
- ldr x0, [tsk, THREAD_SCTLR_USER]
tbz x0, SCTLR_ELx_ENIA_SHIFT, 1f
__ptrauth_keys_install_user tsk, x0, x1, x2
b 2f
@@ -474,18 +482,6 @@ SYM_CODE_END(__swpan_exit_el0)
/* GPRs used by entry code */
tsk .req x28 // current thread_info
-/*
- * Interrupt handling.
- */
- .macro gic_prio_kentry_setup, tmp:req
-#ifdef CONFIG_ARM64_PSEUDO_NMI
- alternative_if ARM64_HAS_IRQ_PRIO_MASKING
- mov \tmp, #(GIC_PRIO_PSR_I_SET | GIC_PRIO_IRQON)
- msr_s SYS_ICC_PMR_EL1, \tmp
- alternative_else_nop_endif
-#endif
- .endm
-
.text
/*
@@ -517,12 +513,13 @@ SYM_CODE_START(vectors)
SYM_CODE_END(vectors)
#ifdef CONFIG_VMAP_STACK
+SYM_CODE_START_LOCAL(__bad_stack)
/*
* We detected an overflow in kernel_ventry, which switched to the
* overflow stack. Stash the exception regs, and head to our overflow
* handler.
*/
-__bad_stack:
+
/* Restore the original x0 value */
mrs x0, tpidrro_el0
@@ -542,6 +539,7 @@ __bad_stack:
/* Time to die */
bl handle_bad_stack
ASM_BUG()
+SYM_CODE_END(__bad_stack)
#endif /* CONFIG_VMAP_STACK */
@@ -585,37 +583,13 @@ SYM_CODE_START_LOCAL(ret_to_kernel)
kernel_exit 1
SYM_CODE_END(ret_to_kernel)
-/*
- * "slow" syscall return path.
- */
SYM_CODE_START_LOCAL(ret_to_user)
- disable_daif
- gic_prio_kentry_setup tmp=x3
-#ifdef CONFIG_TRACE_IRQFLAGS
- bl trace_hardirqs_off
-#endif
- ldr x19, [tsk, #TSK_TI_FLAGS]
- and x2, x19, #_TIF_WORK_MASK
- cbnz x2, work_pending
-finish_ret_to_user:
- user_enter_irqoff
- /* Ignore asynchronous tag check faults in the uaccess routines */
- clear_mte_async_tcf
+ ldr x19, [tsk, #TSK_TI_FLAGS] // re-check for single-step
enable_step_tsk x19, x2
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
bl stackleak_erase
#endif
kernel_exit 0
-
-/*
- * Ok, we need to do extra processing, enter the slow path.
- */
-work_pending:
- mov x0, sp // 'regs'
- mov x1, x19
- bl do_notify_resume
- ldr x19, [tsk, #TSK_TI_FLAGS] // re-check for single-step
- b finish_ret_to_user
SYM_CODE_END(ret_to_user)
.popsection // .entry.text
@@ -781,6 +755,8 @@ SYM_CODE_START(ret_from_fork)
mov x0, x20
blr x19
1: get_current_task tsk
+ mov x0, sp
+ bl asm_exit_to_user_mode
b ret_to_user
SYM_CODE_END(ret_from_fork)
NOKPROBE(ret_from_fork)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index e57b23f95284..5a294f20e9de 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -162,6 +162,8 @@ extern void __percpu *efi_sve_state;
DEFINE_PER_CPU(bool, fpsimd_context_busy);
EXPORT_PER_CPU_SYMBOL(fpsimd_context_busy);
+static void fpsimd_bind_task_to_cpu(void);
+
static void __get_cpu_fpsimd_context(void)
{
bool busy = __this_cpu_xchg(fpsimd_context_busy, true);
@@ -518,12 +520,6 @@ void sve_alloc(struct task_struct *task)
/* This is a small allocation (maximum ~8KB) and Should Not Fail. */
task->thread.sve_state =
kzalloc(sve_state_size(task), GFP_KERNEL);
-
- /*
- * If future SVE revisions can have larger vectors though,
- * this may cease to be true:
- */
- BUG_ON(!task->thread.sve_state);
}
@@ -943,6 +939,10 @@ void do_sve_acc(unsigned int esr, struct pt_regs *regs)
}
sve_alloc(current);
+ if (!current->thread.sve_state) {
+ force_sig(SIGKILL);
+ return;
+ }
get_cpu_fpsimd_context();
@@ -1112,7 +1112,7 @@ void fpsimd_signal_preserve_current_state(void)
* The caller must have ownership of the cpu FPSIMD context before calling
* this function.
*/
-void fpsimd_bind_task_to_cpu(void)
+static void fpsimd_bind_task_to_cpu(void)
{
struct fpsimd_last_state_struct *last =
this_cpu_ptr(&fpsimd_last_state);
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index c5c994a73a64..17962452e31d 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -177,7 +177,7 @@ SYM_CODE_END(preserve_boot_args)
* to be composed of multiple pages. (This effectively scales the end index).
*
* vstart: virtual address of start of range
- * vend: virtual address of end of range
+ * vend: virtual address of end of range - we map [vstart, vend]
* shift: shift used to transform virtual address into index
* ptrs: number of entries in page table
* istart: index in table corresponding to vstart
@@ -214,17 +214,18 @@ SYM_CODE_END(preserve_boot_args)
*
* tbl: location of page table
* rtbl: address to be used for first level page table entry (typically tbl + PAGE_SIZE)
- * vstart: start address to map
- * vend: end address to map - we map [vstart, vend]
+ * vstart: virtual address of start of range
+ * vend: virtual address of end of range - we map [vstart, vend - 1]
* flags: flags to use to map last level entries
* phys: physical address corresponding to vstart - physical memory is contiguous
* pgds: the number of pgd entries
*
* Temporaries: istart, iend, tmp, count, sv - these need to be different registers
- * Preserves: vstart, vend, flags
- * Corrupts: tbl, rtbl, istart, iend, tmp, count, sv
+ * Preserves: vstart, flags
+ * Corrupts: tbl, rtbl, vend, istart, iend, tmp, count, sv
*/
.macro map_memory, tbl, rtbl, vstart, vend, flags, phys, pgds, istart, iend, tmp, count, sv
+ sub \vend, \vend, #1
add \rtbl, \tbl, #PAGE_SIZE
mov \sv, \rtbl
mov \count, #0
diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c
index 53a381a7f65d..d8e606fe3c21 100644
--- a/arch/arm64/kernel/idreg-override.c
+++ b/arch/arm64/kernel/idreg-override.c
@@ -54,6 +54,7 @@ static const struct ftr_set_desc pfr1 __initconst = {
.override = &id_aa64pfr1_override,
.fields = {
{ "bt", ID_AA64PFR1_BT_SHIFT },
+ { "mte", ID_AA64PFR1_MTE_SHIFT},
{}
},
};
@@ -100,6 +101,7 @@ static const struct {
{ "arm64.nopauth",
"id_aa64isar1.gpi=0 id_aa64isar1.gpa=0 "
"id_aa64isar1.api=0 id_aa64isar1.apa=0" },
+ { "arm64.nomte", "id_aa64pfr1.mte=0" },
{ "nokaslr", "kaslr.disabled=1" },
};
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 36f51b0e438a..9d314a3bad3b 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -4,6 +4,7 @@
*/
#include <linux/bitops.h>
+#include <linux/cpu.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/prctl.h>
@@ -22,9 +23,7 @@
#include <asm/ptrace.h>
#include <asm/sysreg.h>
-u64 gcr_kernel_excl __ro_after_init;
-
-static bool report_fault_once = true;
+static DEFINE_PER_CPU_READ_MOSTLY(u64, mte_tcf_preferred);
#ifdef CONFIG_KASAN_HW_TAGS
/* Whether the MTE asynchronous mode is enabled. */
@@ -101,26 +100,6 @@ int memcmp_pages(struct page *page1, struct page *page2)
return ret;
}
-void mte_init_tags(u64 max_tag)
-{
- static bool gcr_kernel_excl_initialized;
-
- if (!gcr_kernel_excl_initialized) {
- /*
- * The format of the tags in KASAN is 0xFF and in MTE is 0xF.
- * This conversion extracts an MTE tag from a KASAN tag.
- */
- u64 incl = GENMASK(FIELD_GET(MTE_TAG_MASK >> MTE_TAG_SHIFT,
- max_tag), 0);
-
- gcr_kernel_excl = ~incl & SYS_GCR_EL1_EXCL_MASK;
- gcr_kernel_excl_initialized = true;
- }
-
- /* Enable the kernel exclude mask for random tags generation. */
- write_sysreg_s(SYS_GCR_EL1_RRND | gcr_kernel_excl, SYS_GCR_EL1);
-}
-
static inline void __mte_enable_kernel(const char *mode, unsigned long tcf)
{
/* Enable MTE Sync Mode for EL1. */
@@ -160,16 +139,6 @@ void mte_enable_kernel_async(void)
}
#endif
-void mte_set_report_once(bool state)
-{
- WRITE_ONCE(report_fault_once, state);
-}
-
-bool mte_report_once(void)
-{
- return READ_ONCE(report_fault_once);
-}
-
#ifdef CONFIG_KASAN_HW_TAGS
void mte_check_tfsr_el1(void)
{
@@ -193,14 +162,26 @@ void mte_check_tfsr_el1(void)
}
#endif
-static void set_gcr_el1_excl(u64 excl)
+static void mte_update_sctlr_user(struct task_struct *task)
{
- current->thread.gcr_user_excl = excl;
-
/*
- * SYS_GCR_EL1 will be set to current->thread.gcr_user_excl value
- * by mte_set_user_gcr() in kernel_exit,
+ * This must be called with preemption disabled and can only be called
+ * on the current or next task since the CPU must match where the thread
+ * is going to run. The caller is responsible for calling
+ * update_sctlr_el1() later in the same preemption disabled block.
*/
+ unsigned long sctlr = task->thread.sctlr_user;
+ unsigned long mte_ctrl = task->thread.mte_ctrl;
+ unsigned long pref, resolved_mte_tcf;
+
+ pref = __this_cpu_read(mte_tcf_preferred);
+ resolved_mte_tcf = (mte_ctrl & pref) ? pref : mte_ctrl;
+ sctlr &= ~SCTLR_EL1_TCF0_MASK;
+ if (resolved_mte_tcf & MTE_CTRL_TCF_ASYNC)
+ sctlr |= SCTLR_EL1_TCF0_ASYNC;
+ else if (resolved_mte_tcf & MTE_CTRL_TCF_SYNC)
+ sctlr |= SCTLR_EL1_TCF0_SYNC;
+ task->thread.sctlr_user = sctlr;
}
void mte_thread_init_user(void)
@@ -212,15 +193,14 @@ void mte_thread_init_user(void)
dsb(ish);
write_sysreg_s(0, SYS_TFSRE0_EL1);
clear_thread_flag(TIF_MTE_ASYNC_FAULT);
- /* disable tag checking */
- set_task_sctlr_el1((current->thread.sctlr_user & ~SCTLR_EL1_TCF0_MASK) |
- SCTLR_EL1_TCF0_NONE);
- /* reset tag generation mask */
- set_gcr_el1_excl(SYS_GCR_EL1_EXCL_MASK);
+ /* disable tag checking and reset tag generation mask */
+ set_mte_ctrl(current, 0);
}
void mte_thread_switch(struct task_struct *next)
{
+ mte_update_sctlr_user(next);
+
/*
* Check if an async tag exception occurred at EL1.
*
@@ -248,44 +228,25 @@ void mte_suspend_enter(void)
mte_check_tfsr_el1();
}
-void mte_suspend_exit(void)
-{
- if (!system_supports_mte())
- return;
-
- sysreg_clear_set_s(SYS_GCR_EL1, SYS_GCR_EL1_EXCL_MASK, gcr_kernel_excl);
- isb();
-}
-
long set_mte_ctrl(struct task_struct *task, unsigned long arg)
{
- u64 sctlr = task->thread.sctlr_user & ~SCTLR_EL1_TCF0_MASK;
- u64 gcr_excl = ~((arg & PR_MTE_TAG_MASK) >> PR_MTE_TAG_SHIFT) &
- SYS_GCR_EL1_EXCL_MASK;
+ u64 mte_ctrl = (~((arg & PR_MTE_TAG_MASK) >> PR_MTE_TAG_SHIFT) &
+ SYS_GCR_EL1_EXCL_MASK) << MTE_CTRL_GCR_USER_EXCL_SHIFT;
if (!system_supports_mte())
return 0;
- switch (arg & PR_MTE_TCF_MASK) {
- case PR_MTE_TCF_NONE:
- sctlr |= SCTLR_EL1_TCF0_NONE;
- break;
- case PR_MTE_TCF_SYNC:
- sctlr |= SCTLR_EL1_TCF0_SYNC;
- break;
- case PR_MTE_TCF_ASYNC:
- sctlr |= SCTLR_EL1_TCF0_ASYNC;
- break;
- default:
- return -EINVAL;
- }
-
- if (task != current) {
- task->thread.sctlr_user = sctlr;
- task->thread.gcr_user_excl = gcr_excl;
- } else {
- set_task_sctlr_el1(sctlr);
- set_gcr_el1_excl(gcr_excl);
+ if (arg & PR_MTE_TCF_ASYNC)
+ mte_ctrl |= MTE_CTRL_TCF_ASYNC;
+ if (arg & PR_MTE_TCF_SYNC)
+ mte_ctrl |= MTE_CTRL_TCF_SYNC;
+
+ task->thread.mte_ctrl = mte_ctrl;
+ if (task == current) {
+ preempt_disable();
+ mte_update_sctlr_user(task);
+ update_sctlr_el1(task->thread.sctlr_user);
+ preempt_enable();
}
return 0;
@@ -294,24 +255,18 @@ long set_mte_ctrl(struct task_struct *task, unsigned long arg)
long get_mte_ctrl(struct task_struct *task)
{
unsigned long ret;
- u64 incl = ~task->thread.gcr_user_excl & SYS_GCR_EL1_EXCL_MASK;
+ u64 mte_ctrl = task->thread.mte_ctrl;
+ u64 incl = (~mte_ctrl >> MTE_CTRL_GCR_USER_EXCL_SHIFT) &
+ SYS_GCR_EL1_EXCL_MASK;
if (!system_supports_mte())
return 0;
ret = incl << PR_MTE_TAG_SHIFT;
-
- switch (task->thread.sctlr_user & SCTLR_EL1_TCF0_MASK) {
- case SCTLR_EL1_TCF0_NONE:
- ret |= PR_MTE_TCF_NONE;
- break;
- case SCTLR_EL1_TCF0_SYNC:
- ret |= PR_MTE_TCF_SYNC;
- break;
- case SCTLR_EL1_TCF0_ASYNC:
+ if (mte_ctrl & MTE_CTRL_TCF_ASYNC)
ret |= PR_MTE_TCF_ASYNC;
- break;
- }
+ if (mte_ctrl & MTE_CTRL_TCF_SYNC)
+ ret |= PR_MTE_TCF_SYNC;
return ret;
}
@@ -450,3 +405,54 @@ int mte_ptrace_copy_tags(struct task_struct *child, long request,
return ret;
}
+
+static ssize_t mte_tcf_preferred_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ switch (per_cpu(mte_tcf_preferred, dev->id)) {
+ case MTE_CTRL_TCF_ASYNC:
+ return sysfs_emit(buf, "async\n");
+ case MTE_CTRL_TCF_SYNC:
+ return sysfs_emit(buf, "sync\n");
+ default:
+ return sysfs_emit(buf, "???\n");
+ }
+}
+
+static ssize_t mte_tcf_preferred_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u64 tcf;
+
+ if (sysfs_streq(buf, "async"))
+ tcf = MTE_CTRL_TCF_ASYNC;
+ else if (sysfs_streq(buf, "sync"))
+ tcf = MTE_CTRL_TCF_SYNC;
+ else
+ return -EINVAL;
+
+ device_lock(dev);
+ per_cpu(mte_tcf_preferred, dev->id) = tcf;
+ device_unlock(dev);
+
+ return count;
+}
+static DEVICE_ATTR_RW(mte_tcf_preferred);
+
+static int register_mte_tcf_preferred_sysctl(void)
+{
+ unsigned int cpu;
+
+ if (!system_supports_mte())
+ return 0;
+
+ for_each_possible_cpu(cpu) {
+ per_cpu(mte_tcf_preferred, cpu) = MTE_CTRL_TCF_ASYNC;
+ device_create_file(get_cpu_device(cpu),
+ &dev_attr_mte_tcf_preferred);
+ }
+
+ return 0;
+}
+subsys_initcall(register_mte_tcf_preferred_sysctl);
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index d07788dad388..b4044469527e 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1055,7 +1055,7 @@ static void __armv8pmu_probe_pmu(void *info)
dfr0 = read_sysreg(id_aa64dfr0_el1);
pmuver = cpuid_feature_extract_unsigned_field(dfr0,
ID_AA64DFR0_PMUVER_SHIFT);
- if (pmuver == 0xf || pmuver == 0)
+ if (pmuver == ID_AA64DFR0_PMUVER_IMP_DEF || pmuver == 0)
return;
cpu_pmu->pmuver = pmuver;
diff --git a/arch/arm64/kernel/pointer_auth.c b/arch/arm64/kernel/pointer_auth.c
index 60901ab0a7fe..2708b620b4ae 100644
--- a/arch/arm64/kernel/pointer_auth.c
+++ b/arch/arm64/kernel/pointer_auth.c
@@ -67,7 +67,7 @@ static u64 arg_to_enxx_mask(unsigned long arg)
int ptrauth_set_enabled_keys(struct task_struct *tsk, unsigned long keys,
unsigned long enabled)
{
- u64 sctlr = tsk->thread.sctlr_user;
+ u64 sctlr;
if (!system_supports_address_auth())
return -EINVAL;
@@ -78,12 +78,14 @@ int ptrauth_set_enabled_keys(struct task_struct *tsk, unsigned long keys,
if ((keys & ~PR_PAC_ENABLED_KEYS_MASK) || (enabled & ~keys))
return -EINVAL;
+ preempt_disable();
+ sctlr = tsk->thread.sctlr_user;
sctlr &= ~arg_to_enxx_mask(keys);
sctlr |= arg_to_enxx_mask(enabled);
+ tsk->thread.sctlr_user = sctlr;
if (tsk == current)
- set_task_sctlr_el1(sctlr);
- else
- tsk->thread.sctlr_user = sctlr;
+ update_sctlr_el1(sctlr);
+ preempt_enable();
return 0;
}
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index c8989b999250..19100fe8f7e4 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -6,9 +6,6 @@
* Copyright (C) 1996-2000 Russell King - Converted to ARM.
* Copyright (C) 2012 ARM Ltd.
*/
-
-#include <stdarg.h>
-
#include <linux/compat.h>
#include <linux/efi.h>
#include <linux/elf.h>
@@ -21,6 +18,7 @@
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/nospec.h>
+#include <linux/sched.h>
#include <linux/stddef.h>
#include <linux/sysctl.h>
#include <linux/unistd.h>
@@ -163,7 +161,7 @@ static void print_pstate(struct pt_regs *regs)
u64 pstate = regs->pstate;
if (compat_user_mode(regs)) {
- printk("pstate: %08llx (%c%c%c%c %c %s %s %c%c%c)\n",
+ printk("pstate: %08llx (%c%c%c%c %c %s %s %c%c%c %cDIT %cSSBS)\n",
pstate,
pstate & PSR_AA32_N_BIT ? 'N' : 'n',
pstate & PSR_AA32_Z_BIT ? 'Z' : 'z',
@@ -174,12 +172,14 @@ static void print_pstate(struct pt_regs *regs)
pstate & PSR_AA32_E_BIT ? "BE" : "LE",
pstate & PSR_AA32_A_BIT ? 'A' : 'a',
pstate & PSR_AA32_I_BIT ? 'I' : 'i',
- pstate & PSR_AA32_F_BIT ? 'F' : 'f');
+ pstate & PSR_AA32_F_BIT ? 'F' : 'f',
+ pstate & PSR_AA32_DIT_BIT ? '+' : '-',
+ pstate & PSR_AA32_SSBS_BIT ? '+' : '-');
} else {
const char *btype_str = btypes[(pstate & PSR_BTYPE_MASK) >>
PSR_BTYPE_SHIFT];
- printk("pstate: %08llx (%c%c%c%c %c%c%c%c %cPAN %cUAO %cTCO BTYPE=%s)\n",
+ printk("pstate: %08llx (%c%c%c%c %c%c%c%c %cPAN %cUAO %cTCO %cDIT %cSSBS BTYPE=%s)\n",
pstate,
pstate & PSR_N_BIT ? 'N' : 'n',
pstate & PSR_Z_BIT ? 'Z' : 'z',
@@ -192,6 +192,8 @@ static void print_pstate(struct pt_regs *regs)
pstate & PSR_PAN_BIT ? '+' : '-',
pstate & PSR_UAO_BIT ? '+' : '-',
pstate & PSR_TCO_BIT ? '+' : '-',
+ pstate & PSR_DIT_BIT ? '+' : '-',
+ pstate & PSR_SSBS_BIT ? '+' : '-',
btype_str);
}
}
@@ -468,16 +470,13 @@ static void erratum_1418040_thread_switch(struct task_struct *prev,
write_sysreg(val, cntkctl_el1);
}
-static void compat_thread_switch(struct task_struct *next)
-{
- if (!is_compat_thread(task_thread_info(next)))
- return;
-
- if (static_branch_unlikely(&arm64_mismatched_32bit_el0))
- set_tsk_thread_flag(next, TIF_NOTIFY_RESUME);
-}
-
-static void update_sctlr_el1(u64 sctlr)
+/*
+ * __switch_to() checks current->thread.sctlr_user as an optimisation. Therefore
+ * this function must be called with preemption disabled and the update to
+ * sctlr_user must be made in the same preemption disabled block so that
+ * __switch_to() does not see the variable update before the SCTLR_EL1 one.
+ */
+void update_sctlr_el1(u64 sctlr)
{
/*
* EnIA must not be cleared while in the kernel as this is necessary for
@@ -489,19 +488,6 @@ static void update_sctlr_el1(u64 sctlr)
isb();
}
-void set_task_sctlr_el1(u64 sctlr)
-{
- /*
- * __switch_to() checks current->thread.sctlr as an
- * optimisation. Disable preemption so that it does not see
- * the variable update before the SCTLR_EL1 one.
- */
- preempt_disable();
- current->thread.sctlr_user = sctlr;
- update_sctlr_el1(sctlr);
- preempt_enable();
-}
-
/*
* Thread switching.
*/
@@ -518,7 +504,6 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
ssbs_thread_switch(next);
erratum_1418040_thread_switch(prev, next);
ptrauth_thread_switch_user(next);
- compat_thread_switch(next);
/*
* Complete any pending TLB or cache maintenance on this CPU in case
@@ -579,6 +564,28 @@ unsigned long arch_align_stack(unsigned long sp)
return sp & ~0xf;
}
+#ifdef CONFIG_COMPAT
+int compat_elf_check_arch(const struct elf32_hdr *hdr)
+{
+ if (!system_supports_32bit_el0())
+ return false;
+
+ if ((hdr)->e_machine != EM_ARM)
+ return false;
+
+ if (!((hdr)->e_flags & EF_ARM_EABI_MASK))
+ return false;
+
+ /*
+ * Prevent execve() of a 32-bit program from a deadline task
+ * if the restricted affinity mask would be inadmissible on an
+ * asymmetric system.
+ */
+ return !static_branch_unlikely(&arm64_mismatched_32bit_el0) ||
+ !dl_task_check_affinity(current, system_32bit_el0_cpumask());
+}
+#endif
+
/*
* Called from setup_new_exec() after (COMPAT_)SET_PERSONALITY.
*/
@@ -588,8 +595,20 @@ void arch_setup_new_exec(void)
if (is_compat_task()) {
mmflags = MMCF_AARCH32;
+
+ /*
+ * Restrict the CPU affinity mask for a 32-bit task so that
+ * it contains only 32-bit-capable CPUs.
+ *
+ * From the perspective of the task, this looks similar to
+ * what would happen if the 64-bit-only CPUs were hot-unplugged
+ * at the point of execve(), although we try a bit harder to
+ * honour the cpuset hierarchy.
+ */
if (static_branch_unlikely(&arm64_mismatched_32bit_el0))
- set_tsk_thread_flag(current, TIF_NOTIFY_RESUME);
+ force_compatible_cpus_allowed_ptr(current);
+ } else if (static_branch_unlikely(&arm64_mismatched_32bit_el0)) {
+ relax_compatible_cpus_allowed_ptr(current);
}
current->mm->context.flags = mmflags;
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index b381a1ee9ea7..e26196a33cf4 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -845,6 +845,11 @@ static int sve_set(struct task_struct *target,
}
sve_alloc(target);
+ if (!target->thread.sve_state) {
+ ret = -ENOMEM;
+ clear_tsk_thread_flag(target, TIF_SVE);
+ goto out;
+ }
/*
* Ensure target->thread.sve_state is up to date with target's
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 23036334f4dc..9fe70b12b34f 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -290,6 +290,11 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
sve_alloc(current);
+ if (!current->thread.sve_state) {
+ clear_thread_flag(TIF_SVE);
+ return -ENOMEM;
+ }
+
err = __copy_from_user(current->thread.sve_state,
(char __user const *)user->sve +
SVE_SIG_REGS_OFFSET,
@@ -912,21 +917,7 @@ static void do_signal(struct pt_regs *regs)
restore_saved_sigmask();
}
-static bool cpu_affinity_invalid(struct pt_regs *regs)
-{
- if (!compat_user_mode(regs))
- return false;
-
- /*
- * We're preemptible, but a reschedule will cause us to check the
- * affinity again.
- */
- return !cpumask_test_cpu(raw_smp_processor_id(),
- system_32bit_el0_cpumask());
-}
-
-asmlinkage void do_notify_resume(struct pt_regs *regs,
- unsigned long thread_flags)
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
{
do {
if (thread_flags & _TIF_NEED_RESCHED) {
@@ -952,19 +943,6 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
if (thread_flags & _TIF_NOTIFY_RESUME) {
tracehook_notify_resume(regs);
rseq_handle_notify_resume(NULL, regs);
-
- /*
- * If we reschedule after checking the affinity
- * then we must ensure that TIF_NOTIFY_RESUME
- * is set so that we check the affinity again.
- * Since tracehook_notify_resume() clears the
- * flag, ensure that the compiler doesn't move
- * it after the affinity check.
- */
- barrier();
-
- if (cpu_affinity_invalid(regs))
- force_sig(SIGKILL);
}
if (thread_flags & _TIF_FOREIGN_FPSTATE)
@@ -1000,3 +978,42 @@ void __init minsigstksz_setup(void)
round_up(sizeof(struct frame_record), 16) +
16; /* max alignment padding */
}
+
+/*
+ * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as
+ * changes likely come with new fields that should be added below.
+ */
+static_assert(NSIGILL == 11);
+static_assert(NSIGFPE == 15);
+static_assert(NSIGSEGV == 9);
+static_assert(NSIGBUS == 5);
+static_assert(NSIGTRAP == 6);
+static_assert(NSIGCHLD == 6);
+static_assert(NSIGSYS == 2);
+static_assert(sizeof(siginfo_t) == 128);
+static_assert(__alignof__(siginfo_t) == 8);
+static_assert(offsetof(siginfo_t, si_signo) == 0x00);
+static_assert(offsetof(siginfo_t, si_errno) == 0x04);
+static_assert(offsetof(siginfo_t, si_code) == 0x08);
+static_assert(offsetof(siginfo_t, si_pid) == 0x10);
+static_assert(offsetof(siginfo_t, si_uid) == 0x14);
+static_assert(offsetof(siginfo_t, si_tid) == 0x10);
+static_assert(offsetof(siginfo_t, si_overrun) == 0x14);
+static_assert(offsetof(siginfo_t, si_status) == 0x18);
+static_assert(offsetof(siginfo_t, si_utime) == 0x20);
+static_assert(offsetof(siginfo_t, si_stime) == 0x28);
+static_assert(offsetof(siginfo_t, si_value) == 0x18);
+static_assert(offsetof(siginfo_t, si_int) == 0x18);
+static_assert(offsetof(siginfo_t, si_ptr) == 0x18);
+static_assert(offsetof(siginfo_t, si_addr) == 0x10);
+static_assert(offsetof(siginfo_t, si_addr_lsb) == 0x18);
+static_assert(offsetof(siginfo_t, si_lower) == 0x20);
+static_assert(offsetof(siginfo_t, si_upper) == 0x28);
+static_assert(offsetof(siginfo_t, si_pkey) == 0x20);
+static_assert(offsetof(siginfo_t, si_perf_data) == 0x18);
+static_assert(offsetof(siginfo_t, si_perf_type) == 0x20);
+static_assert(offsetof(siginfo_t, si_band) == 0x10);
+static_assert(offsetof(siginfo_t, si_fd) == 0x18);
+static_assert(offsetof(siginfo_t, si_call_addr) == 0x10);
+static_assert(offsetof(siginfo_t, si_syscall) == 0x18);
+static_assert(offsetof(siginfo_t, si_arch) == 0x1c);
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 2f507f565c48..d984282b979f 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -46,8 +46,6 @@ struct compat_aux_sigframe {
unsigned long end_magic;
} __attribute__((__aligned__(8)));
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
{
compat_sigset_t cset;
@@ -190,10 +188,8 @@ static int compat_restore_sigframe(struct pt_regs *regs,
unsigned long psr;
err = get_sigset_t(&set, &sf->uc.uc_sigmask);
- if (err == 0) {
- sigdelsetmask(&set, ~_BLOCKABLE);
+ if (err == 0)
set_current_blocked(&set);
- }
__get_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err);
__get_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err);
@@ -457,3 +453,42 @@ void compat_setup_restart_syscall(struct pt_regs *regs)
{
regs->regs[7] = __NR_compat_restart_syscall;
}
+
+/*
+ * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as
+ * changes likely come with new fields that should be added below.
+ */
+static_assert(NSIGILL == 11);
+static_assert(NSIGFPE == 15);
+static_assert(NSIGSEGV == 9);
+static_assert(NSIGBUS == 5);
+static_assert(NSIGTRAP == 6);
+static_assert(NSIGCHLD == 6);
+static_assert(NSIGSYS == 2);
+static_assert(sizeof(compat_siginfo_t) == 128);
+static_assert(__alignof__(compat_siginfo_t) == 4);
+static_assert(offsetof(compat_siginfo_t, si_signo) == 0x00);
+static_assert(offsetof(compat_siginfo_t, si_errno) == 0x04);
+static_assert(offsetof(compat_siginfo_t, si_code) == 0x08);
+static_assert(offsetof(compat_siginfo_t, si_pid) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_uid) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_tid) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_overrun) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_status) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_utime) == 0x18);
+static_assert(offsetof(compat_siginfo_t, si_stime) == 0x1c);
+static_assert(offsetof(compat_siginfo_t, si_value) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_int) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_ptr) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_addr) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_addr_lsb) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_lower) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_upper) == 0x18);
+static_assert(offsetof(compat_siginfo_t, si_pkey) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_perf_data) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_perf_type) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_band) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_fd) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_call_addr) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_syscall) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_arch) == 0x14);
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 938ce6fbee8a..19ee7c33769d 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -76,7 +76,6 @@ void notrace __cpu_suspend_exit(void)
spectre_v4_enable_mitigation(NULL);
/* Restore additional feature-specific configuration */
- mte_suspend_exit();
ptrauth_suspend_exit();
}
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 709d2c433c5e..f6b1a88245db 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -181,6 +181,8 @@ SECTIONS
/* everything from this point to __init_begin will be marked RO NX */
RO_DATA(PAGE_SIZE)
+ HYPERVISOR_DATA_SECTIONS
+
idmap_pg_dir = .;
. += IDMAP_DIR_SIZE;
idmap_pg_end = .;
@@ -260,8 +262,6 @@ SECTIONS
_sdata = .;
RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)
- HYPERVISOR_DATA_SECTIONS
-
/*
* Data written with the MMU off but read with the MMU on requires
* cache lines to be invalidated, discarding up to a Cache Writeback
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index a4eba0908bfa..d7eec0b43744 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -26,6 +26,7 @@ menuconfig KVM
select HAVE_KVM_ARCH_TLB_FLUSH_ALL
select KVM_MMIO
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
+ select KVM_XFER_TO_GUEST_WORK
select SRCU
select KVM_VFIO
select HAVE_KVM_EVENTFD
@@ -46,6 +47,15 @@ if KVM
source "virt/kvm/Kconfig"
+config NVHE_EL2_DEBUG
+ bool "Debug mode for non-VHE EL2 object"
+ help
+ Say Y here to enable the debug mode for the non-VHE KVM EL2 object.
+ Failure reports will BUG() in the hypervisor. This is intended for
+ local EL2 hypervisor development.
+
+ If unsure, say N.
+
endif # KVM
endif # VIRTUALIZATION
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 0ca72f5cda41..fe102cd2e518 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -6,6 +6,7 @@
#include <linux/bug.h>
#include <linux/cpu_pm.h>
+#include <linux/entry-kvm.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/kvm_host.h>
@@ -15,6 +16,7 @@
#include <linux/fs.h>
#include <linux/mman.h>
#include <linux/sched.h>
+#include <linux/kmemleak.h>
#include <linux/kvm.h>
#include <linux/kvm_irqfd.h>
#include <linux/irqbypass.h>
@@ -42,10 +44,6 @@
#include <kvm/arm_pmu.h>
#include <kvm/arm_psci.h>
-#ifdef REQUIRES_VIRT
-__asm__(".arch_extension virt");
-#endif
-
static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;
DEFINE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
@@ -575,7 +573,7 @@ static void update_vmid(struct kvm_vmid *vmid)
kvm_call_hyp(__kvm_flush_vm_context);
}
- vmid->vmid = kvm_next_vmid;
+ WRITE_ONCE(vmid->vmid, kvm_next_vmid);
kvm_next_vmid++;
kvm_next_vmid &= (1 << kvm_get_vmid_bits()) - 1;
@@ -719,6 +717,45 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
}
/**
+ * kvm_vcpu_exit_request - returns true if the VCPU should *not* enter the guest
+ * @vcpu: The VCPU pointer
+ * @ret: Pointer to write optional return code
+ *
+ * Returns: true if the VCPU needs to return to a preemptible + interruptible
+ * and skip guest entry.
+ *
+ * This function disambiguates between two different types of exits: exits to a
+ * preemptible + interruptible kernel context and exits to userspace. For an
+ * exit to userspace, this function will write the return code to ret and return
+ * true. For an exit to preemptible + interruptible kernel context (i.e. check
+ * for pending work and re-enter), return true without writing to ret.
+ */
+static bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu, int *ret)
+{
+ struct kvm_run *run = vcpu->run;
+
+ /*
+ * If we're using a userspace irqchip, then check if we need
+ * to tell a userspace irqchip about timer or PMU level
+ * changes and if so, exit to userspace (the actual level
+ * state gets updated in kvm_timer_update_run and
+ * kvm_pmu_update_run below).
+ */
+ if (static_branch_unlikely(&userspace_irqchip_in_use)) {
+ if (kvm_timer_should_notify_user(vcpu) ||
+ kvm_pmu_should_notify_user(vcpu)) {
+ *ret = -EINTR;
+ run->exit_reason = KVM_EXIT_INTR;
+ return true;
+ }
+ }
+
+ return kvm_request_pending(vcpu) ||
+ need_new_vmid_gen(&vcpu->arch.hw_mmu->vmid) ||
+ xfer_to_guest_mode_work_pending();
+}
+
+/**
* kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
* @vcpu: The VCPU pointer
*
@@ -761,7 +798,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
/*
* Check conditions before entering the guest
*/
- cond_resched();
+ ret = xfer_to_guest_mode_handle_work(vcpu);
+ if (!ret)
+ ret = 1;
update_vmid(&vcpu->arch.hw_mmu->vmid);
@@ -781,30 +820,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
kvm_vgic_flush_hwstate(vcpu);
/*
- * Exit if we have a signal pending so that we can deliver the
- * signal to user space.
- */
- if (signal_pending(current)) {
- ret = -EINTR;
- run->exit_reason = KVM_EXIT_INTR;
- }
-
- /*
- * If we're using a userspace irqchip, then check if we need
- * to tell a userspace irqchip about timer or PMU level
- * changes and if so, exit to userspace (the actual level
- * state gets updated in kvm_timer_update_run and
- * kvm_pmu_update_run below).
- */
- if (static_branch_unlikely(&userspace_irqchip_in_use)) {
- if (kvm_timer_should_notify_user(vcpu) ||
- kvm_pmu_should_notify_user(vcpu)) {
- ret = -EINTR;
- run->exit_reason = KVM_EXIT_INTR;
- }
- }
-
- /*
* Ensure we set mode to IN_GUEST_MODE after we disable
* interrupts and before the final VCPU requests check.
* See the comment in kvm_vcpu_exiting_guest_mode() and
@@ -812,8 +827,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
*/
smp_store_mb(vcpu->mode, IN_GUEST_MODE);
- if (ret <= 0 || need_new_vmid_gen(&vcpu->arch.hw_mmu->vmid) ||
- kvm_request_pending(vcpu)) {
+ if (ret <= 0 || kvm_vcpu_exit_request(vcpu, &ret)) {
vcpu->mode = OUTSIDE_GUEST_MODE;
isb(); /* Ensure work in x_flush_hwstate is committed */
kvm_pmu_sync_hwstate(vcpu);
@@ -1039,7 +1053,7 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
const struct kvm_vcpu_init *init)
{
unsigned int i, ret;
- int phys_target = kvm_target_cpu();
+ u32 phys_target = kvm_target_cpu();
if (init->target != phys_target)
return -EINVAL;
@@ -1108,6 +1122,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
}
vcpu_reset_hcr(vcpu);
+ vcpu->arch.cptr_el2 = CPTR_EL2_DEFAULT;
/*
* Handle the "start in power-off" case.
@@ -1219,6 +1234,14 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
if (copy_from_user(&reg, argp, sizeof(reg)))
break;
+ /*
+ * We could owe a reset due to PSCI. Handle the pending reset
+ * here to ensure userspace register accesses are ordered after
+ * the reset.
+ */
+ if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
+ kvm_reset_vcpu(vcpu);
+
if (ioctl == KVM_SET_ONE_REG)
r = kvm_arm_set_reg(vcpu, &reg);
else
@@ -1700,11 +1723,6 @@ static bool init_psci_relay(void)
return true;
}
-static int init_common_resources(void)
-{
- return kvm_set_ipa_limit();
-}
-
static int init_subsystems(void)
{
int err = 0;
@@ -1958,56 +1976,17 @@ static void _kvm_host_prot_finalize(void *discard)
WARN_ON(kvm_call_hyp_nvhe(__pkvm_prot_finalize));
}
-static inline int pkvm_mark_hyp(phys_addr_t start, phys_addr_t end)
-{
- return kvm_call_hyp_nvhe(__pkvm_mark_hyp, start, end);
-}
-
-#define pkvm_mark_hyp_section(__section) \
- pkvm_mark_hyp(__pa_symbol(__section##_start), \
- __pa_symbol(__section##_end))
-
static int finalize_hyp_mode(void)
{
- int cpu, ret;
-
if (!is_protected_kvm_enabled())
return 0;
- ret = pkvm_mark_hyp_section(__hyp_idmap_text);
- if (ret)
- return ret;
-
- ret = pkvm_mark_hyp_section(__hyp_text);
- if (ret)
- return ret;
-
- ret = pkvm_mark_hyp_section(__hyp_rodata);
- if (ret)
- return ret;
-
- ret = pkvm_mark_hyp_section(__hyp_bss);
- if (ret)
- return ret;
-
- ret = pkvm_mark_hyp(hyp_mem_base, hyp_mem_base + hyp_mem_size);
- if (ret)
- return ret;
-
- for_each_possible_cpu(cpu) {
- phys_addr_t start = virt_to_phys((void *)kvm_arm_hyp_percpu_base[cpu]);
- phys_addr_t end = start + (PAGE_SIZE << nvhe_percpu_order());
-
- ret = pkvm_mark_hyp(start, end);
- if (ret)
- return ret;
-
- start = virt_to_phys((void *)per_cpu(kvm_arm_hyp_stack_page, cpu));
- end = start + PAGE_SIZE;
- ret = pkvm_mark_hyp(start, end);
- if (ret)
- return ret;
- }
+ /*
+ * Exclude HYP BSS from kmemleak so that it doesn't get peeked
+ * at, which would end badly once the section is inaccessible.
+ * None of other sections should ever be introspected.
+ */
+ kmemleak_free_part(__hyp_bss_start, __hyp_bss_end - __hyp_bss_start);
/*
* Flip the static key upfront as that may no longer be possible
@@ -2019,11 +1998,6 @@ static int finalize_hyp_mode(void)
return 0;
}
-static void check_kvm_target_cpu(void *ret)
-{
- *(int *)ret = kvm_target_cpu();
-}
-
struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
{
struct kvm_vcpu *vcpu;
@@ -2083,7 +2057,6 @@ void kvm_arch_irq_bypass_start(struct irq_bypass_consumer *cons)
int kvm_arch_init(void *opaque)
{
int err;
- int ret, cpu;
bool in_hyp_mode;
if (!is_hyp_mode_available()) {
@@ -2098,15 +2071,7 @@ int kvm_arch_init(void *opaque)
kvm_info("Guests without required CPU erratum workarounds can deadlock system!\n" \
"Only trusted guests should be used on this system.\n");
- for_each_online_cpu(cpu) {
- smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1);
- if (ret < 0) {
- kvm_err("Error, CPU %d not supported!\n", cpu);
- return -ENODEV;
- }
- }
-
- err = init_common_resources();
+ err = kvm_set_ipa_limit();
if (err)
return err;
diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
index d5e79d7ee6e9..db9361338b2a 100644
--- a/arch/arm64/kvm/debug.c
+++ b/arch/arm64/kvm/debug.c
@@ -21,7 +21,7 @@
DBG_MDSCR_KDE | \
DBG_MDSCR_MDE)
-static DEFINE_PER_CPU(u32, mdcr_el2);
+static DEFINE_PER_CPU(u64, mdcr_el2);
/**
* save/restore_guest_debug_regs
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 1dfb83578277..5ce26bedf23c 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -31,8 +31,6 @@
const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
KVM_GENERIC_VM_STATS()
};
-static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
- sizeof(struct kvm_vm_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vm_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -50,10 +48,9 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, wfi_exit_stat),
STATS_DESC_COUNTER(VCPU, mmio_exit_user),
STATS_DESC_COUNTER(VCPU, mmio_exit_kernel),
+ STATS_DESC_COUNTER(VCPU, signal_exits),
STATS_DESC_COUNTER(VCPU, exits)
};
-static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
- sizeof(struct kvm_vcpu_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vcpu_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -842,7 +839,7 @@ int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
return 0;
}
-int __attribute_const__ kvm_target_cpu(void)
+u32 __attribute_const__ kvm_target_cpu(void)
{
unsigned long implementor = read_cpuid_implementor();
unsigned long part_number = read_cpuid_part_number();
@@ -874,7 +871,7 @@ int __attribute_const__ kvm_target_cpu(void)
int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init)
{
- int target = kvm_target_cpu();
+ u32 target = kvm_target_cpu();
if (target < 0)
return -ENODEV;
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 6f48336b1d86..275a27368a04 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -113,34 +113,20 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu)
* guest and host are using the same debug facilities it will be up to
* userspace to re-inject the correct exception for guest delivery.
*
- * @return: 0 (while setting vcpu->run->exit_reason), -1 for error
+ * @return: 0 (while setting vcpu->run->exit_reason)
*/
static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu)
{
struct kvm_run *run = vcpu->run;
u32 esr = kvm_vcpu_get_esr(vcpu);
- int ret = 0;
run->exit_reason = KVM_EXIT_DEBUG;
run->debug.arch.hsr = esr;
- switch (ESR_ELx_EC(esr)) {
- case ESR_ELx_EC_WATCHPT_LOW:
+ if (ESR_ELx_EC(esr) == ESR_ELx_EC_WATCHPT_LOW)
run->debug.arch.far = vcpu->arch.fault.far_el2;
- fallthrough;
- case ESR_ELx_EC_SOFTSTP_LOW:
- case ESR_ELx_EC_BREAKPT_LOW:
- case ESR_ELx_EC_BKPT32:
- case ESR_ELx_EC_BRK64:
- break;
- default:
- kvm_err("%s: un-handled case esr: %#08x\n",
- __func__, (unsigned int) esr);
- ret = -1;
- break;
- }
- return ret;
+ return 0;
}
static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu)
@@ -292,11 +278,12 @@ void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
}
-void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr,
+void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
+ u64 elr_virt, u64 elr_phys,
u64 par, uintptr_t vcpu,
u64 far, u64 hpfar) {
- u64 elr_in_kimg = __phys_to_kimg(__hyp_pa(elr));
- u64 hyp_offset = elr_in_kimg - kaslr_offset() - elr;
+ u64 elr_in_kimg = __phys_to_kimg(elr_phys);
+ u64 hyp_offset = elr_in_kimg - kaslr_offset() - elr_virt;
u64 mode = spsr & PSR_MODE_MASK;
/*
@@ -309,20 +296,24 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr,
kvm_err("Invalid host exception to nVHE hyp!\n");
} else if (ESR_ELx_EC(esr) == ESR_ELx_EC_BRK64 &&
(esr & ESR_ELx_BRK64_ISS_COMMENT_MASK) == BUG_BRK_IMM) {
- struct bug_entry *bug = find_bug(elr_in_kimg);
const char *file = NULL;
unsigned int line = 0;
/* All hyp bugs, including warnings, are treated as fatal. */
- if (bug)
- bug_get_file_line(bug, &file, &line);
+ if (!is_protected_kvm_enabled() ||
+ IS_ENABLED(CONFIG_NVHE_EL2_DEBUG)) {
+ struct bug_entry *bug = find_bug(elr_in_kimg);
+
+ if (bug)
+ bug_get_file_line(bug, &file, &line);
+ }
if (file)
kvm_err("nVHE hyp BUG at: %s:%u!\n", file, line);
else
- kvm_err("nVHE hyp BUG at: %016llx!\n", elr + hyp_offset);
+ kvm_err("nVHE hyp BUG at: %016llx!\n", elr_virt + hyp_offset);
} else {
- kvm_err("nVHE hyp panic at: %016llx!\n", elr + hyp_offset);
+ kvm_err("nVHE hyp panic at: %016llx!\n", elr_virt + hyp_offset);
}
/*
@@ -334,5 +325,5 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr,
kvm_err("Hyp Offset: 0x%llx\n", hyp_offset);
panic("HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%016lx\n",
- spsr, elr, esr, far, hpfar, par, vcpu);
+ spsr, elr_virt, esr, far, hpfar, par, vcpu);
}
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index e4a2f295a394..a0e78a6027be 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -92,11 +92,15 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
write_sysreg(0, pmselr_el0);
write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
}
+
+ vcpu->arch.mdcr_el2_host = read_sysreg(mdcr_el2);
write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
}
-static inline void __deactivate_traps_common(void)
+static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
{
+ write_sysreg(vcpu->arch.mdcr_el2_host, mdcr_el2);
+
write_sysreg(0, hstr_el2);
if (kvm_arm_support_pmu_v3())
write_sysreg(0, pmuserenr_el0);
diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index 9c227d87c36d..b58c910babaf 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -12,6 +12,32 @@
#include <asm/virt.h>
#include <nvhe/spinlock.h>
+/*
+ * SW bits 0-1 are reserved to track the memory ownership state of each page:
+ * 00: The page is owned exclusively by the page-table owner.
+ * 01: The page is owned by the page-table owner, but is shared
+ * with another entity.
+ * 10: The page is shared with, but not owned by the page-table owner.
+ * 11: Reserved for future use (lending).
+ */
+enum pkvm_page_state {
+ PKVM_PAGE_OWNED = 0ULL,
+ PKVM_PAGE_SHARED_OWNED = KVM_PGTABLE_PROT_SW0,
+ PKVM_PAGE_SHARED_BORROWED = KVM_PGTABLE_PROT_SW1,
+};
+
+#define PKVM_PAGE_STATE_PROT_MASK (KVM_PGTABLE_PROT_SW0 | KVM_PGTABLE_PROT_SW1)
+static inline enum kvm_pgtable_prot pkvm_mkstate(enum kvm_pgtable_prot prot,
+ enum pkvm_page_state state)
+{
+ return (prot & ~PKVM_PAGE_STATE_PROT_MASK) | state;
+}
+
+static inline enum pkvm_page_state pkvm_getstate(enum kvm_pgtable_prot prot)
+{
+ return prot & PKVM_PAGE_STATE_PROT_MASK;
+}
+
struct host_kvm {
struct kvm_arch arch;
struct kvm_pgtable pgt;
@@ -20,16 +46,21 @@ struct host_kvm {
};
extern struct host_kvm host_kvm;
+extern const u8 pkvm_hyp_id;
+
int __pkvm_prot_finalize(void);
-int __pkvm_mark_hyp(phys_addr_t start, phys_addr_t end);
+int __pkvm_host_share_hyp(u64 pfn);
+bool addr_is_memory(phys_addr_t phys);
+int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot prot);
+int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id);
int kvm_host_prepare_stage2(void *pgt_pool_base);
void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt);
static __always_inline void __load_host_stage2(void)
{
if (static_branch_likely(&kvm_protected_mode_initialized))
- __load_stage2(&host_kvm.arch.mmu, host_kvm.arch.vtcr);
+ __load_stage2(&host_kvm.arch.mmu, &host_kvm.arch);
else
write_sysreg(0, vttbr_el2);
}
diff --git a/arch/arm64/kvm/hyp/include/nvhe/mm.h b/arch/arm64/kvm/hyp/include/nvhe/mm.h
index 8ec3a5a7744b..c9a8f535212e 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mm.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mm.h
@@ -23,8 +23,7 @@ int hyp_map_vectors(void);
int hyp_back_vmemmap(phys_addr_t phys, unsigned long size, phys_addr_t back);
int pkvm_cpu_set_vector(enum arm64_hyp_spectre_vector slot);
int pkvm_create_mappings(void *from, void *to, enum kvm_pgtable_prot prot);
-int __pkvm_create_mappings(unsigned long start, unsigned long size,
- unsigned long phys, enum kvm_pgtable_prot prot);
+int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot);
unsigned long __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
enum kvm_pgtable_prot prot);
diff --git a/arch/arm64/kvm/hyp/include/nvhe/spinlock.h b/arch/arm64/kvm/hyp/include/nvhe/spinlock.h
index 76b537f8d1c6..4652fd04bdbe 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/spinlock.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/spinlock.h
@@ -15,6 +15,7 @@
#include <asm/alternative.h>
#include <asm/lse.h>
+#include <asm/rwonce.h>
typedef union hyp_spinlock {
u32 __val;
@@ -89,4 +90,28 @@ static inline void hyp_spin_unlock(hyp_spinlock_t *lock)
: "memory");
}
+static inline bool hyp_spin_is_locked(hyp_spinlock_t *lock)
+{
+ hyp_spinlock_t lockval = READ_ONCE(*lock);
+
+ return lockval.owner != lockval.next;
+}
+
+#ifdef CONFIG_NVHE_EL2_DEBUG
+static inline void hyp_assert_lock_held(hyp_spinlock_t *lock)
+{
+ /*
+ * The __pkvm_init() path accesses protected data-structures without
+ * holding locks as the other CPUs are guaranteed to not enter EL2
+ * concurrently at this point in time. The point by which EL2 is
+ * initialized on all CPUs is reflected in the pkvm static key, so
+ * wait until it is set before checking the lock state.
+ */
+ if (static_branch_likely(&kvm_protected_mode_initialized))
+ BUG_ON(!hyp_spin_is_locked(lock));
+}
+#else
+static inline void hyp_assert_lock_held(hyp_spinlock_t *lock) { }
+#endif
+
#endif /* __ARM64_KVM_NVHE_SPINLOCK_H__ */
diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c
index 7d3f25868cae..df361d839902 100644
--- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c
+++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c
@@ -109,7 +109,7 @@ void __debug_switch_to_host(struct kvm_vcpu *vcpu)
__debug_switch_to_host_common(vcpu);
}
-u32 __kvm_get_mdcr_el2(void)
+u64 __kvm_get_mdcr_el2(void)
{
return read_sysreg(mdcr_el2);
}
diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S
index 2b23400e0fb3..4b652ffb591d 100644
--- a/arch/arm64/kvm/hyp/nvhe/host.S
+++ b/arch/arm64/kvm/hyp/nvhe/host.S
@@ -7,6 +7,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include <asm/kvm_arm.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_mmu.h>
@@ -85,12 +86,24 @@ SYM_FUNC_START(__hyp_do_panic)
mov x29, x0
+#ifdef CONFIG_NVHE_EL2_DEBUG
+ /* Ensure host stage-2 is disabled */
+ mrs x0, hcr_el2
+ bic x0, x0, #HCR_VM
+ msr hcr_el2, x0
+ isb
+ tlbi vmalls12e1
+ dsb nsh
+#endif
+
/* Load the panic arguments into x0-7 */
mrs x0, esr_el2
- get_vcpu_ptr x4, x5
- mrs x5, far_el2
- mrs x6, hpfar_el2
- mov x7, xzr // Unused argument
+ mov x4, x3
+ mov x3, x2
+ hyp_pa x3, x6
+ get_vcpu_ptr x5, x6
+ mrs x6, far_el2
+ mrs x7, hpfar_el2
/* Enter the host, conditionally restoring the host context. */
cbz x29, __host_enter_without_restoring
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 1632f001f4ed..2da6aa8da868 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -140,14 +140,11 @@ static void handle___pkvm_cpu_set_vector(struct kvm_cpu_context *host_ctxt)
cpu_reg(host_ctxt, 1) = pkvm_cpu_set_vector(slot);
}
-static void handle___pkvm_create_mappings(struct kvm_cpu_context *host_ctxt)
+static void handle___pkvm_host_share_hyp(struct kvm_cpu_context *host_ctxt)
{
- DECLARE_REG(unsigned long, start, host_ctxt, 1);
- DECLARE_REG(unsigned long, size, host_ctxt, 2);
- DECLARE_REG(unsigned long, phys, host_ctxt, 3);
- DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 4);
+ DECLARE_REG(u64, pfn, host_ctxt, 1);
- cpu_reg(host_ctxt, 1) = __pkvm_create_mappings(start, size, phys, prot);
+ cpu_reg(host_ctxt, 1) = __pkvm_host_share_hyp(pfn);
}
static void handle___pkvm_create_private_mapping(struct kvm_cpu_context *host_ctxt)
@@ -163,14 +160,6 @@ static void handle___pkvm_prot_finalize(struct kvm_cpu_context *host_ctxt)
{
cpu_reg(host_ctxt, 1) = __pkvm_prot_finalize();
}
-
-static void handle___pkvm_mark_hyp(struct kvm_cpu_context *host_ctxt)
-{
- DECLARE_REG(phys_addr_t, start, host_ctxt, 1);
- DECLARE_REG(phys_addr_t, end, host_ctxt, 2);
-
- cpu_reg(host_ctxt, 1) = __pkvm_mark_hyp(start, end);
-}
typedef void (*hcall_t)(struct kvm_cpu_context *);
#define HANDLE_FUNC(x) [__KVM_HOST_SMCCC_FUNC_##x] = (hcall_t)handle_##x
@@ -193,10 +182,9 @@ static const hcall_t host_hcall[] = {
HANDLE_FUNC(__vgic_v3_restore_aprs),
HANDLE_FUNC(__pkvm_init),
HANDLE_FUNC(__pkvm_cpu_set_vector),
- HANDLE_FUNC(__pkvm_create_mappings),
+ HANDLE_FUNC(__pkvm_host_share_hyp),
HANDLE_FUNC(__pkvm_create_private_mapping),
HANDLE_FUNC(__pkvm_prot_finalize),
- HANDLE_FUNC(__pkvm_mark_hyp),
};
static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index a6ce991b1467..bacd493a4eac 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -31,7 +31,7 @@ static struct hyp_pool host_s2_pool;
u64 id_aa64mmfr0_el1_sys_val;
u64 id_aa64mmfr1_el1_sys_val;
-static const u8 pkvm_hyp_id = 1;
+const u8 pkvm_hyp_id = 1;
static void *host_s2_zalloc_pages_exact(size_t size)
{
@@ -89,6 +89,8 @@ static void prepare_host_vtcr(void)
id_aa64mmfr1_el1_sys_val, phys_shift);
}
+static bool host_stage2_force_pte_cb(u64 addr, u64 end, enum kvm_pgtable_prot prot);
+
int kvm_host_prepare_stage2(void *pgt_pool_base)
{
struct kvm_s2_mmu *mmu = &host_kvm.arch.mmu;
@@ -101,16 +103,17 @@ int kvm_host_prepare_stage2(void *pgt_pool_base)
if (ret)
return ret;
- ret = kvm_pgtable_stage2_init_flags(&host_kvm.pgt, &host_kvm.arch,
- &host_kvm.mm_ops, KVM_HOST_S2_FLAGS);
+ ret = __kvm_pgtable_stage2_init(&host_kvm.pgt, &host_kvm.arch,
+ &host_kvm.mm_ops, KVM_HOST_S2_FLAGS,
+ host_stage2_force_pte_cb);
if (ret)
return ret;
mmu->pgd_phys = __hyp_pa(host_kvm.pgt.pgd);
mmu->arch = &host_kvm.arch;
mmu->pgt = &host_kvm.pgt;
- mmu->vmid.vmid_gen = 0;
- mmu->vmid.vmid = 0;
+ WRITE_ONCE(mmu->vmid.vmid_gen, 0);
+ WRITE_ONCE(mmu->vmid.vmid, 0);
return 0;
}
@@ -126,7 +129,7 @@ int __pkvm_prot_finalize(void)
kvm_flush_dcache_to_poc(params, sizeof(*params));
write_sysreg(params->hcr_el2, hcr_el2);
- __load_stage2(&host_kvm.arch.mmu, host_kvm.arch.vtcr);
+ __load_stage2(&host_kvm.arch.mmu, &host_kvm.arch);
/*
* Make sure to have an ISB before the TLB maintenance below but only
@@ -159,6 +162,11 @@ static int host_stage2_unmap_dev_all(void)
return kvm_pgtable_stage2_unmap(pgt, addr, BIT(pgt->ia_bits) - addr);
}
+struct kvm_mem_range {
+ u64 start;
+ u64 end;
+};
+
static bool find_mem_range(phys_addr_t addr, struct kvm_mem_range *range)
{
int cur, left = 0, right = hyp_memblock_nr;
@@ -189,16 +197,26 @@ static bool find_mem_range(phys_addr_t addr, struct kvm_mem_range *range)
return false;
}
+bool addr_is_memory(phys_addr_t phys)
+{
+ struct kvm_mem_range range;
+
+ return find_mem_range(phys, &range);
+}
+
+static bool is_in_mem_range(u64 addr, struct kvm_mem_range *range)
+{
+ return range->start <= addr && addr < range->end;
+}
+
static bool range_is_memory(u64 start, u64 end)
{
- struct kvm_mem_range r1, r2;
+ struct kvm_mem_range r;
- if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
- return false;
- if (r1.start != r2.start)
+ if (!find_mem_range(start, &r))
return false;
- return true;
+ return is_in_mem_range(end - 1, &r);
}
static inline int __host_stage2_idmap(u64 start, u64 end,
@@ -208,60 +226,208 @@ static inline int __host_stage2_idmap(u64 start, u64 end,
prot, &host_s2_pool);
}
+/*
+ * The pool has been provided with enough pages to cover all of memory with
+ * page granularity, but it is difficult to know how much of the MMIO range
+ * we will need to cover upfront, so we may need to 'recycle' the pages if we
+ * run out.
+ */
+#define host_stage2_try(fn, ...) \
+ ({ \
+ int __ret; \
+ hyp_assert_lock_held(&host_kvm.lock); \
+ __ret = fn(__VA_ARGS__); \
+ if (__ret == -ENOMEM) { \
+ __ret = host_stage2_unmap_dev_all(); \
+ if (!__ret) \
+ __ret = fn(__VA_ARGS__); \
+ } \
+ __ret; \
+ })
+
+static inline bool range_included(struct kvm_mem_range *child,
+ struct kvm_mem_range *parent)
+{
+ return parent->start <= child->start && child->end <= parent->end;
+}
+
+static int host_stage2_adjust_range(u64 addr, struct kvm_mem_range *range)
+{
+ struct kvm_mem_range cur;
+ kvm_pte_t pte;
+ u32 level;
+ int ret;
+
+ hyp_assert_lock_held(&host_kvm.lock);
+ ret = kvm_pgtable_get_leaf(&host_kvm.pgt, addr, &pte, &level);
+ if (ret)
+ return ret;
+
+ if (kvm_pte_valid(pte))
+ return -EAGAIN;
+
+ if (pte)
+ return -EPERM;
+
+ do {
+ u64 granule = kvm_granule_size(level);
+ cur.start = ALIGN_DOWN(addr, granule);
+ cur.end = cur.start + granule;
+ level++;
+ } while ((level < KVM_PGTABLE_MAX_LEVELS) &&
+ !(kvm_level_supports_block_mapping(level) &&
+ range_included(&cur, range)));
+
+ *range = cur;
+
+ return 0;
+}
+
+int host_stage2_idmap_locked(phys_addr_t addr, u64 size,
+ enum kvm_pgtable_prot prot)
+{
+ hyp_assert_lock_held(&host_kvm.lock);
+
+ return host_stage2_try(__host_stage2_idmap, addr, addr + size, prot);
+}
+
+int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id)
+{
+ hyp_assert_lock_held(&host_kvm.lock);
+
+ return host_stage2_try(kvm_pgtable_stage2_set_owner, &host_kvm.pgt,
+ addr, size, &host_s2_pool, owner_id);
+}
+
+static bool host_stage2_force_pte_cb(u64 addr, u64 end, enum kvm_pgtable_prot prot)
+{
+ /*
+ * Block mappings must be used with care in the host stage-2 as a
+ * kvm_pgtable_stage2_map() operation targeting a page in the range of
+ * an existing block will delete the block under the assumption that
+ * mappings in the rest of the block range can always be rebuilt lazily.
+ * That assumption is correct for the host stage-2 with RWX mappings
+ * targeting memory or RW mappings targeting MMIO ranges (see
+ * host_stage2_idmap() below which implements some of the host memory
+ * abort logic). However, this is not safe for any other mappings where
+ * the host stage-2 page-table is in fact the only place where this
+ * state is stored. In all those cases, it is safer to use page-level
+ * mappings, hence avoiding to lose the state because of side-effects in
+ * kvm_pgtable_stage2_map().
+ */
+ if (range_is_memory(addr, end))
+ return prot != PKVM_HOST_MEM_PROT;
+ else
+ return prot != PKVM_HOST_MMIO_PROT;
+}
+
static int host_stage2_idmap(u64 addr)
{
- enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W;
struct kvm_mem_range range;
bool is_memory = find_mem_range(addr, &range);
+ enum kvm_pgtable_prot prot;
int ret;
- if (is_memory)
- prot |= KVM_PGTABLE_PROT_X;
+ prot = is_memory ? PKVM_HOST_MEM_PROT : PKVM_HOST_MMIO_PROT;
hyp_spin_lock(&host_kvm.lock);
- ret = kvm_pgtable_stage2_find_range(&host_kvm.pgt, addr, prot, &range);
+ ret = host_stage2_adjust_range(addr, &range);
if (ret)
goto unlock;
- ret = __host_stage2_idmap(range.start, range.end, prot);
- if (ret != -ENOMEM)
+ ret = host_stage2_idmap_locked(range.start, range.end - range.start, prot);
+unlock:
+ hyp_spin_unlock(&host_kvm.lock);
+
+ return ret;
+}
+
+static inline bool check_prot(enum kvm_pgtable_prot prot,
+ enum kvm_pgtable_prot required,
+ enum kvm_pgtable_prot denied)
+{
+ return (prot & (required | denied)) == required;
+}
+
+int __pkvm_host_share_hyp(u64 pfn)
+{
+ phys_addr_t addr = hyp_pfn_to_phys(pfn);
+ enum kvm_pgtable_prot prot, cur;
+ void *virt = __hyp_va(addr);
+ enum pkvm_page_state state;
+ kvm_pte_t pte;
+ int ret;
+
+ if (!addr_is_memory(addr))
+ return -EINVAL;
+
+ hyp_spin_lock(&host_kvm.lock);
+ hyp_spin_lock(&pkvm_pgd_lock);
+
+ ret = kvm_pgtable_get_leaf(&host_kvm.pgt, addr, &pte, NULL);
+ if (ret)
goto unlock;
+ if (!pte)
+ goto map_shared;
/*
- * The pool has been provided with enough pages to cover all of memory
- * with page granularity, but it is difficult to know how much of the
- * MMIO range we will need to cover upfront, so we may need to 'recycle'
- * the pages if we run out.
+ * Check attributes in the host stage-2 PTE. We need the page to be:
+ * - mapped RWX as we're sharing memory;
+ * - not borrowed, as that implies absence of ownership.
+ * Otherwise, we can't let it got through
*/
- ret = host_stage2_unmap_dev_all();
- if (ret)
+ cur = kvm_pgtable_stage2_pte_prot(pte);
+ prot = pkvm_mkstate(0, PKVM_PAGE_SHARED_BORROWED);
+ if (!check_prot(cur, PKVM_HOST_MEM_PROT, prot)) {
+ ret = -EPERM;
goto unlock;
+ }
- ret = __host_stage2_idmap(range.start, range.end, prot);
+ state = pkvm_getstate(cur);
+ if (state == PKVM_PAGE_OWNED)
+ goto map_shared;
-unlock:
- hyp_spin_unlock(&host_kvm.lock);
+ /*
+ * Tolerate double-sharing the same page, but this requires
+ * cross-checking the hypervisor stage-1.
+ */
+ if (state != PKVM_PAGE_SHARED_OWNED) {
+ ret = -EPERM;
+ goto unlock;
+ }
- return ret;
-}
+ ret = kvm_pgtable_get_leaf(&pkvm_pgtable, (u64)virt, &pte, NULL);
+ if (ret)
+ goto unlock;
-int __pkvm_mark_hyp(phys_addr_t start, phys_addr_t end)
-{
- int ret;
+ /*
+ * If the page has been shared with the hypervisor, it must be
+ * already mapped as SHARED_BORROWED in its stage-1.
+ */
+ cur = kvm_pgtable_hyp_pte_prot(pte);
+ prot = pkvm_mkstate(PAGE_HYP, PKVM_PAGE_SHARED_BORROWED);
+ if (!check_prot(cur, prot, ~prot))
+ ret = -EPERM;
+ goto unlock;
+map_shared:
/*
- * host_stage2_unmap_dev_all() currently relies on MMIO mappings being
- * non-persistent, so don't allow changing page ownership in MMIO range.
+ * If the page is not yet shared, adjust mappings in both page-tables
+ * while both locks are held.
*/
- if (!range_is_memory(start, end))
- return -EINVAL;
+ prot = pkvm_mkstate(PAGE_HYP, PKVM_PAGE_SHARED_BORROWED);
+ ret = pkvm_create_mappings_locked(virt, virt + PAGE_SIZE, prot);
+ BUG_ON(ret);
- hyp_spin_lock(&host_kvm.lock);
- ret = kvm_pgtable_stage2_set_owner(&host_kvm.pgt, start, end - start,
- &host_s2_pool, pkvm_hyp_id);
+ prot = pkvm_mkstate(PKVM_HOST_MEM_PROT, PKVM_PAGE_SHARED_OWNED);
+ ret = host_stage2_idmap_locked(addr, PAGE_SIZE, prot);
+ BUG_ON(ret);
+
+unlock:
+ hyp_spin_unlock(&pkvm_pgd_lock);
hyp_spin_unlock(&host_kvm.lock);
- return ret != -EAGAIN ? ret : 0;
+ return ret;
}
void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt)
diff --git a/arch/arm64/kvm/hyp/nvhe/mm.c b/arch/arm64/kvm/hyp/nvhe/mm.c
index a8efdf0f9003..2fabeceb889a 100644
--- a/arch/arm64/kvm/hyp/nvhe/mm.c
+++ b/arch/arm64/kvm/hyp/nvhe/mm.c
@@ -23,8 +23,8 @@ u64 __io_map_base;
struct memblock_region hyp_memory[HYP_MEMBLOCK_REGIONS];
unsigned int hyp_memblock_nr;
-int __pkvm_create_mappings(unsigned long start, unsigned long size,
- unsigned long phys, enum kvm_pgtable_prot prot)
+static int __pkvm_create_mappings(unsigned long start, unsigned long size,
+ unsigned long phys, enum kvm_pgtable_prot prot)
{
int err;
@@ -67,13 +67,15 @@ out:
return addr;
}
-int pkvm_create_mappings(void *from, void *to, enum kvm_pgtable_prot prot)
+int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot)
{
unsigned long start = (unsigned long)from;
unsigned long end = (unsigned long)to;
unsigned long virt_addr;
phys_addr_t phys;
+ hyp_assert_lock_held(&pkvm_pgd_lock);
+
start = start & PAGE_MASK;
end = PAGE_ALIGN(end);
@@ -81,7 +83,8 @@ int pkvm_create_mappings(void *from, void *to, enum kvm_pgtable_prot prot)
int err;
phys = hyp_virt_to_phys((void *)virt_addr);
- err = __pkvm_create_mappings(virt_addr, PAGE_SIZE, phys, prot);
+ err = kvm_pgtable_hyp_map(&pkvm_pgtable, virt_addr, PAGE_SIZE,
+ phys, prot);
if (err)
return err;
}
@@ -89,6 +92,17 @@ int pkvm_create_mappings(void *from, void *to, enum kvm_pgtable_prot prot)
return 0;
}
+int pkvm_create_mappings(void *from, void *to, enum kvm_pgtable_prot prot)
+{
+ int ret;
+
+ hyp_spin_lock(&pkvm_pgd_lock);
+ ret = pkvm_create_mappings_locked(from, to, prot);
+ hyp_spin_unlock(&pkvm_pgd_lock);
+
+ return ret;
+}
+
int hyp_back_vmemmap(phys_addr_t phys, unsigned long size, phys_addr_t back)
{
unsigned long start, end;
diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index 0b574d106519..57c27846320f 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -58,6 +58,7 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
{
void *start, *end, *virt = hyp_phys_to_virt(phys);
unsigned long pgt_size = hyp_s1_pgtable_pages() << PAGE_SHIFT;
+ enum kvm_pgtable_prot prot;
int ret, i;
/* Recreate the hyp page-table using the early page allocator */
@@ -83,10 +84,6 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
if (ret)
return ret;
- ret = pkvm_create_mappings(__start_rodata, __end_rodata, PAGE_HYP_RO);
- if (ret)
- return ret;
-
ret = pkvm_create_mappings(__hyp_rodata_start, __hyp_rodata_end, PAGE_HYP_RO);
if (ret)
return ret;
@@ -95,10 +92,6 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
if (ret)
return ret;
- ret = pkvm_create_mappings(__hyp_bss_end, __bss_stop, PAGE_HYP_RO);
- if (ret)
- return ret;
-
ret = pkvm_create_mappings(virt, virt + size, PAGE_HYP);
if (ret)
return ret;
@@ -117,6 +110,24 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
return ret;
}
+ /*
+ * Map the host's .bss and .rodata sections RO in the hypervisor, but
+ * transfer the ownership from the host to the hypervisor itself to
+ * make sure it can't be donated or shared with another entity.
+ *
+ * The ownership transition requires matching changes in the host
+ * stage-2. This will be done later (see finalize_host_mappings()) once
+ * the hyp_vmemmap is addressable.
+ */
+ prot = pkvm_mkstate(PAGE_HYP_RO, PKVM_PAGE_SHARED_OWNED);
+ ret = pkvm_create_mappings(__start_rodata, __end_rodata, prot);
+ if (ret)
+ return ret;
+
+ ret = pkvm_create_mappings(__hyp_bss_end, __bss_stop, prot);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -148,6 +159,57 @@ static void hpool_put_page(void *addr)
hyp_put_page(&hpool, addr);
}
+static int finalize_host_mappings_walker(u64 addr, u64 end, u32 level,
+ kvm_pte_t *ptep,
+ enum kvm_pgtable_walk_flags flag,
+ void * const arg)
+{
+ enum kvm_pgtable_prot prot;
+ enum pkvm_page_state state;
+ kvm_pte_t pte = *ptep;
+ phys_addr_t phys;
+
+ if (!kvm_pte_valid(pte))
+ return 0;
+
+ if (level != (KVM_PGTABLE_MAX_LEVELS - 1))
+ return -EINVAL;
+
+ phys = kvm_pte_to_phys(pte);
+ if (!addr_is_memory(phys))
+ return 0;
+
+ /*
+ * Adjust the host stage-2 mappings to match the ownership attributes
+ * configured in the hypervisor stage-1.
+ */
+ state = pkvm_getstate(kvm_pgtable_hyp_pte_prot(pte));
+ switch (state) {
+ case PKVM_PAGE_OWNED:
+ return host_stage2_set_owner_locked(phys, PAGE_SIZE, pkvm_hyp_id);
+ case PKVM_PAGE_SHARED_OWNED:
+ prot = pkvm_mkstate(PKVM_HOST_MEM_PROT, PKVM_PAGE_SHARED_BORROWED);
+ break;
+ case PKVM_PAGE_SHARED_BORROWED:
+ prot = pkvm_mkstate(PKVM_HOST_MEM_PROT, PKVM_PAGE_SHARED_OWNED);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return host_stage2_idmap_locked(phys, PAGE_SIZE, prot);
+}
+
+static int finalize_host_mappings(void)
+{
+ struct kvm_pgtable_walker walker = {
+ .cb = finalize_host_mappings_walker,
+ .flags = KVM_PGTABLE_WALK_LEAF,
+ };
+
+ return kvm_pgtable_walk(&pkvm_pgtable, 0, BIT(pkvm_pgtable.ia_bits), &walker);
+}
+
void __noreturn __pkvm_init_finalise(void)
{
struct kvm_host_data *host_data = this_cpu_ptr(&kvm_host_data);
@@ -167,6 +229,10 @@ void __noreturn __pkvm_init_finalise(void)
if (ret)
goto out;
+ ret = finalize_host_mappings();
+ if (ret)
+ goto out;
+
pkvm_pgtable_mm_ops = (struct kvm_pgtable_mm_ops) {
.zalloc_page = hyp_zalloc_hyp_page,
.phys_to_virt = hyp_phys_to_virt,
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index f7af9688c1f7..a34b01cc8ab9 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -41,7 +41,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
___activate_traps(vcpu);
__activate_traps_common(vcpu);
- val = CPTR_EL2_DEFAULT;
+ val = vcpu->arch.cptr_el2;
val |= CPTR_EL2_TTA | CPTR_EL2_TAM;
if (!update_fp_enabled(vcpu)) {
val |= CPTR_EL2_TFP | CPTR_EL2_TZ;
@@ -69,12 +69,10 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
static void __deactivate_traps(struct kvm_vcpu *vcpu)
{
extern char __kvm_hyp_host_vector[];
- u64 mdcr_el2, cptr;
+ u64 cptr;
___deactivate_traps(vcpu);
- mdcr_el2 = read_sysreg(mdcr_el2);
-
if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
u64 val;
@@ -92,13 +90,8 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
isb();
}
- __deactivate_traps_common();
-
- mdcr_el2 &= MDCR_EL2_HPMN_MASK;
- mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT;
- mdcr_el2 |= MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT;
+ __deactivate_traps_common(vcpu);
- write_sysreg(mdcr_el2, mdcr_el2);
write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
cptr = CPTR_EL2_DEFAULT;
@@ -170,6 +163,7 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
{
struct kvm_cpu_context *host_ctxt;
struct kvm_cpu_context *guest_ctxt;
+ struct kvm_s2_mmu *mmu;
bool pmu_switch_needed;
u64 exit_code;
@@ -213,7 +207,8 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
__sysreg32_restore_state(vcpu);
__sysreg_restore_state_nvhe(guest_ctxt);
- __load_guest_stage2(kern_hyp_va(vcpu->arch.hw_mmu));
+ mmu = kern_hyp_va(vcpu->arch.hw_mmu);
+ __load_stage2(mmu, kern_hyp_va(mmu->arch));
__activate_traps(vcpu);
__hyp_vgic_restore_state(vcpu);
diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c
index 38ed0f6f2703..d296d617f589 100644
--- a/arch/arm64/kvm/hyp/nvhe/tlb.c
+++ b/arch/arm64/kvm/hyp/nvhe/tlb.c
@@ -34,12 +34,12 @@ static void __tlb_switch_to_guest(struct kvm_s2_mmu *mmu,
}
/*
- * __load_guest_stage2() includes an ISB only when the AT
+ * __load_stage2() includes an ISB only when the AT
* workaround is applied. Take care of the opposite condition,
* ensuring that we always have an ISB, but not two ISBs back
* to back.
*/
- __load_guest_stage2(mmu);
+ __load_stage2(mmu, kern_hyp_va(mmu->arch));
asm(ALTERNATIVE("isb", "nop", ARM64_WORKAROUND_SPECULATIVE_AT));
}
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index 05321f4165e3..f8ceebe4982e 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -11,16 +11,12 @@
#include <asm/kvm_pgtable.h>
#include <asm/stage2_pgtable.h>
-#define KVM_PTE_VALID BIT(0)
#define KVM_PTE_TYPE BIT(1)
#define KVM_PTE_TYPE_BLOCK 0
#define KVM_PTE_TYPE_PAGE 1
#define KVM_PTE_TYPE_TABLE 1
-#define KVM_PTE_ADDR_MASK GENMASK(47, PAGE_SHIFT)
-#define KVM_PTE_ADDR_51_48 GENMASK(15, 12)
-
#define KVM_PTE_LEAF_ATTR_LO GENMASK(11, 2)
#define KVM_PTE_LEAF_ATTR_LO_S1_ATTRIDX GENMASK(4, 2)
@@ -40,6 +36,8 @@
#define KVM_PTE_LEAF_ATTR_HI GENMASK(63, 51)
+#define KVM_PTE_LEAF_ATTR_HI_SW GENMASK(58, 55)
+
#define KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54)
#define KVM_PTE_LEAF_ATTR_HI_S2_XN BIT(54)
@@ -48,9 +46,7 @@
KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \
KVM_PTE_LEAF_ATTR_HI_S2_XN)
-#define KVM_PTE_LEAF_ATTR_S2_IGNORED GENMASK(58, 55)
-
-#define KVM_INVALID_PTE_OWNER_MASK GENMASK(63, 56)
+#define KVM_INVALID_PTE_OWNER_MASK GENMASK(9, 2)
#define KVM_MAX_OWNER_ID 1
struct kvm_pgtable_walk_data {
@@ -61,17 +57,6 @@ struct kvm_pgtable_walk_data {
u64 end;
};
-static u64 kvm_granule_shift(u32 level)
-{
- /* Assumes KVM_PGTABLE_MAX_LEVELS is 4 */
- return ARM64_HW_PGTABLE_LEVEL_SHIFT(level);
-}
-
-static u64 kvm_granule_size(u32 level)
-{
- return BIT(kvm_granule_shift(level));
-}
-
#define KVM_PHYS_INVALID (-1ULL)
static bool kvm_phys_is_valid(u64 phys)
@@ -79,15 +64,6 @@ static bool kvm_phys_is_valid(u64 phys)
return phys < BIT(id_aa64mmfr0_parange_to_phys_shift(ID_AA64MMFR0_PARANGE_MAX));
}
-static bool kvm_level_supports_block_mapping(u32 level)
-{
- /*
- * Reject invalid block mappings and don't bother with 4TB mappings for
- * 52-bit PAs.
- */
- return !(level == 0 || (PAGE_SIZE != SZ_4K && level == 1));
-}
-
static bool kvm_block_mapping_supported(u64 addr, u64 end, u64 phys, u32 level)
{
u64 granule = kvm_granule_size(level);
@@ -135,11 +111,6 @@ static u32 kvm_pgd_pages(u32 ia_bits, u32 start_level)
return __kvm_pgd_page_idx(&pgt, -1ULL) + 1;
}
-static bool kvm_pte_valid(kvm_pte_t pte)
-{
- return pte & KVM_PTE_VALID;
-}
-
static bool kvm_pte_table(kvm_pte_t pte, u32 level)
{
if (level == KVM_PGTABLE_MAX_LEVELS - 1)
@@ -151,16 +122,6 @@ static bool kvm_pte_table(kvm_pte_t pte, u32 level)
return FIELD_GET(KVM_PTE_TYPE, pte) == KVM_PTE_TYPE_TABLE;
}
-static u64 kvm_pte_to_phys(kvm_pte_t pte)
-{
- u64 pa = pte & KVM_PTE_ADDR_MASK;
-
- if (PAGE_SHIFT == 16)
- pa |= FIELD_GET(KVM_PTE_ADDR_51_48, pte) << 48;
-
- return pa;
-}
-
static kvm_pte_t kvm_phys_to_pte(u64 pa)
{
kvm_pte_t pte = pa & KVM_PTE_ADDR_MASK;
@@ -326,6 +287,45 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size,
return _kvm_pgtable_walk(&walk_data);
}
+struct leaf_walk_data {
+ kvm_pte_t pte;
+ u32 level;
+};
+
+static int leaf_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
+ enum kvm_pgtable_walk_flags flag, void * const arg)
+{
+ struct leaf_walk_data *data = arg;
+
+ data->pte = *ptep;
+ data->level = level;
+
+ return 0;
+}
+
+int kvm_pgtable_get_leaf(struct kvm_pgtable *pgt, u64 addr,
+ kvm_pte_t *ptep, u32 *level)
+{
+ struct leaf_walk_data data;
+ struct kvm_pgtable_walker walker = {
+ .cb = leaf_walker,
+ .flags = KVM_PGTABLE_WALK_LEAF,
+ .arg = &data,
+ };
+ int ret;
+
+ ret = kvm_pgtable_walk(pgt, ALIGN_DOWN(addr, PAGE_SIZE),
+ PAGE_SIZE, &walker);
+ if (!ret) {
+ if (ptep)
+ *ptep = data.pte;
+ if (level)
+ *level = data.level;
+ }
+
+ return ret;
+}
+
struct hyp_map_data {
u64 phys;
kvm_pte_t attr;
@@ -357,11 +357,47 @@ static int hyp_set_prot_attr(enum kvm_pgtable_prot prot, kvm_pte_t *ptep)
attr |= FIELD_PREP(KVM_PTE_LEAF_ATTR_LO_S1_AP, ap);
attr |= FIELD_PREP(KVM_PTE_LEAF_ATTR_LO_S1_SH, sh);
attr |= KVM_PTE_LEAF_ATTR_LO_S1_AF;
+ attr |= prot & KVM_PTE_LEAF_ATTR_HI_SW;
*ptep = attr;
return 0;
}
+enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte)
+{
+ enum kvm_pgtable_prot prot = pte & KVM_PTE_LEAF_ATTR_HI_SW;
+ u32 ap;
+
+ if (!kvm_pte_valid(pte))
+ return prot;
+
+ if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_XN))
+ prot |= KVM_PGTABLE_PROT_X;
+
+ ap = FIELD_GET(KVM_PTE_LEAF_ATTR_LO_S1_AP, pte);
+ if (ap == KVM_PTE_LEAF_ATTR_LO_S1_AP_RO)
+ prot |= KVM_PGTABLE_PROT_R;
+ else if (ap == KVM_PTE_LEAF_ATTR_LO_S1_AP_RW)
+ prot |= KVM_PGTABLE_PROT_RW;
+
+ return prot;
+}
+
+static bool hyp_pte_needs_update(kvm_pte_t old, kvm_pte_t new)
+{
+ /*
+ * Tolerate KVM recreating the exact same mapping, or changing software
+ * bits if the existing mapping was valid.
+ */
+ if (old == new)
+ return false;
+
+ if (!kvm_pte_valid(old))
+ return true;
+
+ return !WARN_ON((old ^ new) & ~KVM_PTE_LEAF_ATTR_HI_SW);
+}
+
static bool hyp_map_walker_try_leaf(u64 addr, u64 end, u32 level,
kvm_pte_t *ptep, struct hyp_map_data *data)
{
@@ -371,9 +407,8 @@ static bool hyp_map_walker_try_leaf(u64 addr, u64 end, u32 level,
if (!kvm_block_mapping_supported(addr, end, phys, level))
return false;
- /* Tolerate KVM recreating the exact same mapping */
new = kvm_init_valid_leaf_pte(phys, data->attr, level);
- if (old != new && !WARN_ON(kvm_pte_valid(old)))
+ if (hyp_pte_needs_update(old, new))
smp_store_release(ptep, new);
data->phys += granule;
@@ -438,6 +473,8 @@ int kvm_pgtable_hyp_init(struct kvm_pgtable *pgt, u32 va_bits,
pgt->start_level = KVM_PGTABLE_MAX_LEVELS - levels;
pgt->mm_ops = mm_ops;
pgt->mmu = NULL;
+ pgt->force_pte_cb = NULL;
+
return 0;
}
@@ -475,6 +512,9 @@ struct stage2_map_data {
void *memcache;
struct kvm_pgtable_mm_ops *mm_ops;
+
+ /* Force mappings to page granularity */
+ bool force_pte;
};
u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift)
@@ -539,11 +579,29 @@ static int stage2_set_prot_attr(struct kvm_pgtable *pgt, enum kvm_pgtable_prot p
attr |= FIELD_PREP(KVM_PTE_LEAF_ATTR_LO_S2_SH, sh);
attr |= KVM_PTE_LEAF_ATTR_LO_S2_AF;
+ attr |= prot & KVM_PTE_LEAF_ATTR_HI_SW;
*ptep = attr;
return 0;
}
+enum kvm_pgtable_prot kvm_pgtable_stage2_pte_prot(kvm_pte_t pte)
+{
+ enum kvm_pgtable_prot prot = pte & KVM_PTE_LEAF_ATTR_HI_SW;
+
+ if (!kvm_pte_valid(pte))
+ return prot;
+
+ if (pte & KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R)
+ prot |= KVM_PGTABLE_PROT_R;
+ if (pte & KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W)
+ prot |= KVM_PGTABLE_PROT_W;
+ if (!(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN))
+ prot |= KVM_PGTABLE_PROT_X;
+
+ return prot;
+}
+
static bool stage2_pte_needs_update(kvm_pte_t old, kvm_pte_t new)
{
if (!kvm_pte_valid(old) || !kvm_pte_valid(new))
@@ -588,6 +646,15 @@ static bool stage2_pte_executable(kvm_pte_t pte)
return !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN);
}
+static bool stage2_leaf_mapping_allowed(u64 addr, u64 end, u32 level,
+ struct stage2_map_data *data)
+{
+ if (data->force_pte && (level < (KVM_PGTABLE_MAX_LEVELS - 1)))
+ return false;
+
+ return kvm_block_mapping_supported(addr, end, data->phys, level);
+}
+
static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
kvm_pte_t *ptep,
struct stage2_map_data *data)
@@ -597,7 +664,7 @@ static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
struct kvm_pgtable *pgt = data->mmu->pgt;
struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
- if (!kvm_block_mapping_supported(addr, end, phys, level))
+ if (!stage2_leaf_mapping_allowed(addr, end, level, data))
return -E2BIG;
if (kvm_phys_is_valid(phys))
@@ -641,7 +708,7 @@ static int stage2_map_walk_table_pre(u64 addr, u64 end, u32 level,
if (data->anchor)
return 0;
- if (!kvm_block_mapping_supported(addr, end, data->phys, level))
+ if (!stage2_leaf_mapping_allowed(addr, end, level, data))
return 0;
data->childp = kvm_pte_follow(*ptep, data->mm_ops);
@@ -771,6 +838,7 @@ int kvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
.mmu = pgt->mmu,
.memcache = mc,
.mm_ops = pgt->mm_ops,
+ .force_pte = pgt->force_pte_cb && pgt->force_pte_cb(addr, addr + size, prot),
};
struct kvm_pgtable_walker walker = {
.cb = stage2_map_walker,
@@ -802,6 +870,7 @@ int kvm_pgtable_stage2_set_owner(struct kvm_pgtable *pgt, u64 addr, u64 size,
.memcache = mc,
.mm_ops = pgt->mm_ops,
.owner_id = owner_id,
+ .force_pte = true,
};
struct kvm_pgtable_walker walker = {
.cb = stage2_map_walker,
@@ -995,6 +1064,9 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
u32 level;
kvm_pte_t set = 0, clr = 0;
+ if (prot & KVM_PTE_LEAF_ATTR_HI_SW)
+ return -EINVAL;
+
if (prot & KVM_PGTABLE_PROT_R)
set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R;
@@ -1043,9 +1115,11 @@ int kvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size)
return kvm_pgtable_walk(pgt, addr, size, &walker);
}
-int kvm_pgtable_stage2_init_flags(struct kvm_pgtable *pgt, struct kvm_arch *arch,
- struct kvm_pgtable_mm_ops *mm_ops,
- enum kvm_pgtable_stage2_flags flags)
+
+int __kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_arch *arch,
+ struct kvm_pgtable_mm_ops *mm_ops,
+ enum kvm_pgtable_stage2_flags flags,
+ kvm_pgtable_force_pte_cb_t force_pte_cb)
{
size_t pgd_sz;
u64 vtcr = arch->vtcr;
@@ -1063,6 +1137,7 @@ int kvm_pgtable_stage2_init_flags(struct kvm_pgtable *pgt, struct kvm_arch *arch
pgt->mm_ops = mm_ops;
pgt->mmu = &arch->mmu;
pgt->flags = flags;
+ pgt->force_pte_cb = force_pte_cb;
/* Ensure zeroed PGD pages are visible to the hardware walker */
dsb(ishst);
@@ -1102,77 +1177,3 @@ void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt)
pgt->mm_ops->free_pages_exact(pgt->pgd, pgd_sz);
pgt->pgd = NULL;
}
-
-#define KVM_PTE_LEAF_S2_COMPAT_MASK (KVM_PTE_LEAF_ATTR_S2_PERMS | \
- KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR | \
- KVM_PTE_LEAF_ATTR_S2_IGNORED)
-
-static int stage2_check_permission_walker(u64 addr, u64 end, u32 level,
- kvm_pte_t *ptep,
- enum kvm_pgtable_walk_flags flag,
- void * const arg)
-{
- kvm_pte_t old_attr, pte = *ptep, *new_attr = arg;
-
- /*
- * Compatible mappings are either invalid and owned by the page-table
- * owner (whose id is 0), or valid with matching permission attributes.
- */
- if (kvm_pte_valid(pte)) {
- old_attr = pte & KVM_PTE_LEAF_S2_COMPAT_MASK;
- if (old_attr != *new_attr)
- return -EEXIST;
- } else if (pte) {
- return -EEXIST;
- }
-
- return 0;
-}
-
-int kvm_pgtable_stage2_find_range(struct kvm_pgtable *pgt, u64 addr,
- enum kvm_pgtable_prot prot,
- struct kvm_mem_range *range)
-{
- kvm_pte_t attr;
- struct kvm_pgtable_walker check_perm_walker = {
- .cb = stage2_check_permission_walker,
- .flags = KVM_PGTABLE_WALK_LEAF,
- .arg = &attr,
- };
- u64 granule, start, end;
- u32 level;
- int ret;
-
- ret = stage2_set_prot_attr(pgt, prot, &attr);
- if (ret)
- return ret;
- attr &= KVM_PTE_LEAF_S2_COMPAT_MASK;
-
- for (level = pgt->start_level; level < KVM_PGTABLE_MAX_LEVELS; level++) {
- granule = kvm_granule_size(level);
- start = ALIGN_DOWN(addr, granule);
- end = start + granule;
-
- if (!kvm_level_supports_block_mapping(level))
- continue;
-
- if (start < range->start || range->end < end)
- continue;
-
- /*
- * Check the presence of existing mappings with incompatible
- * permissions within the current block range, and try one level
- * deeper if one is found.
- */
- ret = kvm_pgtable_walk(pgt, start, granule, &check_perm_walker);
- if (ret != -EEXIST)
- break;
- }
-
- if (!ret) {
- range->start = start;
- range->end = end;
- }
-
- return ret;
-}
diff --git a/arch/arm64/kvm/hyp/reserved_mem.c b/arch/arm64/kvm/hyp/reserved_mem.c
index d654921dd09b..578670e3f608 100644
--- a/arch/arm64/kvm/hyp/reserved_mem.c
+++ b/arch/arm64/kvm/hyp/reserved_mem.c
@@ -92,12 +92,10 @@ void __init kvm_hyp_reserve(void)
* this is unmapped from the host stage-2, and fallback to PAGE_SIZE.
*/
hyp_mem_size = hyp_mem_pages << PAGE_SHIFT;
- hyp_mem_base = memblock_find_in_range(0, memblock_end_of_DRAM(),
- ALIGN(hyp_mem_size, PMD_SIZE),
- PMD_SIZE);
+ hyp_mem_base = memblock_phys_alloc(ALIGN(hyp_mem_size, PMD_SIZE),
+ PMD_SIZE);
if (!hyp_mem_base)
- hyp_mem_base = memblock_find_in_range(0, memblock_end_of_DRAM(),
- hyp_mem_size, PAGE_SIZE);
+ hyp_mem_base = memblock_phys_alloc(hyp_mem_size, PAGE_SIZE);
else
hyp_mem_size = ALIGN(hyp_mem_size, PMD_SIZE);
@@ -105,7 +103,6 @@ void __init kvm_hyp_reserve(void)
kvm_err("Failed to reserve hyp memory\n");
return;
}
- memblock_reserve(hyp_mem_base, hyp_mem_size);
kvm_info("Reserved %lld MiB at 0x%llx\n", hyp_mem_size >> 20,
hyp_mem_base);
diff --git a/arch/arm64/kvm/hyp/vhe/debug-sr.c b/arch/arm64/kvm/hyp/vhe/debug-sr.c
index f1e2e5a00933..289689b2682d 100644
--- a/arch/arm64/kvm/hyp/vhe/debug-sr.c
+++ b/arch/arm64/kvm/hyp/vhe/debug-sr.c
@@ -20,7 +20,7 @@ void __debug_switch_to_host(struct kvm_vcpu *vcpu)
__debug_switch_to_host_common(vcpu);
}
-u32 __kvm_get_mdcr_el2(void)
+u64 __kvm_get_mdcr_el2(void)
{
return read_sysreg(mdcr_el2);
}
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index b3229924d243..ded2c66675f0 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -91,17 +91,9 @@ void activate_traps_vhe_load(struct kvm_vcpu *vcpu)
__activate_traps_common(vcpu);
}
-void deactivate_traps_vhe_put(void)
+void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu)
{
- u64 mdcr_el2 = read_sysreg(mdcr_el2);
-
- mdcr_el2 &= MDCR_EL2_HPMN_MASK |
- MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT |
- MDCR_EL2_TPMS;
-
- write_sysreg(mdcr_el2, mdcr_el2);
-
- __deactivate_traps_common();
+ __deactivate_traps_common(vcpu);
}
/* Switch to the guest for VHE systems running in EL2 */
@@ -124,11 +116,11 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
*
* We have already configured the guest's stage 1 translation in
* kvm_vcpu_load_sysregs_vhe above. We must now call
- * __load_guest_stage2 before __activate_traps, because
- * __load_guest_stage2 configures stage 2 translation, and
+ * __load_stage2 before __activate_traps, because
+ * __load_stage2 configures stage 2 translation, and
* __activate_traps clear HCR_EL2.TGE (among other things).
*/
- __load_guest_stage2(vcpu->arch.hw_mmu);
+ __load_stage2(vcpu->arch.hw_mmu, vcpu->arch.hw_mmu->arch);
__activate_traps(vcpu);
__kvm_adjust_pc(vcpu);
diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
index 2a0b8c88d74f..007a12dd4351 100644
--- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
+++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
@@ -101,7 +101,7 @@ void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu)
struct kvm_cpu_context *host_ctxt;
host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
- deactivate_traps_vhe_put();
+ deactivate_traps_vhe_put(vcpu);
__sysreg_save_el1_state(guest_ctxt);
__sysreg_save_user_state(guest_ctxt);
diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c
index 66f17349f0c3..24cef9b87f9e 100644
--- a/arch/arm64/kvm/hyp/vhe/tlb.c
+++ b/arch/arm64/kvm/hyp/vhe/tlb.c
@@ -50,10 +50,10 @@ static void __tlb_switch_to_guest(struct kvm_s2_mmu *mmu,
*
* ARM erratum 1165522 requires some special handling (again),
* as we need to make sure both stages of translation are in
- * place before clearing TGE. __load_guest_stage2() already
+ * place before clearing TGE. __load_stage2() already
* has an ISB in order to deal with this.
*/
- __load_guest_stage2(mmu);
+ __load_stage2(mmu, mmu->arch);
val = read_sysreg(hcr_el2);
val &= ~HCR_TGE;
write_sysreg(val, hcr_el2);
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 0625bf2353c2..1a94a7ca48f2 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -80,6 +80,7 @@ static bool memslot_is_logging(struct kvm_memory_slot *memslot)
*/
void kvm_flush_remote_tlbs(struct kvm *kvm)
{
+ ++kvm->stat.generic.remote_tlb_flush_requests;
kvm_call_hyp(__kvm_tlb_flush_vmid, &kvm->arch.mmu);
}
@@ -259,10 +260,8 @@ static int __create_hyp_mappings(unsigned long start, unsigned long size,
{
int err;
- if (!kvm_host_owns_hyp_mappings()) {
- return kvm_call_hyp_nvhe(__pkvm_create_mappings,
- start, size, phys, prot);
- }
+ if (WARN_ON(!kvm_host_owns_hyp_mappings()))
+ return -EINVAL;
mutex_lock(&kvm_hyp_pgd_mutex);
err = kvm_pgtable_hyp_map(hyp_pgtable, start, size, phys, prot);
@@ -282,6 +281,21 @@ static phys_addr_t kvm_kaddr_to_phys(void *kaddr)
}
}
+static int pkvm_share_hyp(phys_addr_t start, phys_addr_t end)
+{
+ phys_addr_t addr;
+ int ret;
+
+ for (addr = ALIGN_DOWN(start, PAGE_SIZE); addr < end; addr += PAGE_SIZE) {
+ ret = kvm_call_hyp_nvhe(__pkvm_host_share_hyp,
+ __phys_to_pfn(addr));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode
* @from: The virtual kernel start address of the range
@@ -302,6 +316,13 @@ int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot)
if (is_kernel_in_hyp_mode())
return 0;
+ if (!kvm_host_owns_hyp_mappings()) {
+ if (WARN_ON(prot != PAGE_HYP))
+ return -EPERM;
+ return pkvm_share_hyp(kvm_kaddr_to_phys(from),
+ kvm_kaddr_to_phys(to));
+ }
+
start = start & PAGE_MASK;
end = PAGE_ALIGN(end);
@@ -433,6 +454,32 @@ int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size,
return 0;
}
+static struct kvm_pgtable_mm_ops kvm_user_mm_ops = {
+ /* We shouldn't need any other callback to walk the PT */
+ .phys_to_virt = kvm_host_va,
+};
+
+static int get_user_mapping_size(struct kvm *kvm, u64 addr)
+{
+ struct kvm_pgtable pgt = {
+ .pgd = (kvm_pte_t *)kvm->mm->pgd,
+ .ia_bits = VA_BITS,
+ .start_level = (KVM_PGTABLE_MAX_LEVELS -
+ CONFIG_PGTABLE_LEVELS),
+ .mm_ops = &kvm_user_mm_ops,
+ };
+ kvm_pte_t pte = 0; /* Keep GCC quiet... */
+ u32 level = ~0;
+ int ret;
+
+ ret = kvm_pgtable_get_leaf(&pgt, addr, &pte, &level);
+ VM_BUG_ON(ret);
+ VM_BUG_ON(level >= KVM_PGTABLE_MAX_LEVELS);
+ VM_BUG_ON(!(pte & PTE_VALID));
+
+ return BIT(ARM64_HW_PGTABLE_LEVEL_SHIFT(level));
+}
+
static struct kvm_pgtable_mm_ops kvm_s2_mm_ops = {
.zalloc_page = stage2_memcache_zalloc_page,
.zalloc_pages_exact = kvm_host_zalloc_pages_exact,
@@ -485,7 +532,7 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu)
mmu->arch = &kvm->arch;
mmu->pgt = pgt;
mmu->pgd_phys = __pa(pgt->pgd);
- mmu->vmid.vmid_gen = 0;
+ WRITE_ONCE(mmu->vmid.vmid_gen, 0);
return 0;
out_destroy_pgtable:
@@ -780,7 +827,7 @@ static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot,
* Returns the size of the mapping.
*/
static unsigned long
-transparent_hugepage_adjust(struct kvm_memory_slot *memslot,
+transparent_hugepage_adjust(struct kvm *kvm, struct kvm_memory_slot *memslot,
unsigned long hva, kvm_pfn_t *pfnp,
phys_addr_t *ipap)
{
@@ -791,8 +838,8 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot,
* sure that the HVA and IPA are sufficiently aligned and that the
* block map is contained within the memslot.
*/
- if (kvm_is_transparent_hugepage(pfn) &&
- fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) {
+ if (fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE) &&
+ get_user_mapping_size(kvm, hva) >= PMD_SIZE) {
/*
* The address we faulted on is backed by a transparent huge
* page. However, because we map the compound huge page and
@@ -814,7 +861,7 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot,
*ipap &= PMD_MASK;
kvm_release_pfn_clean(pfn);
pfn &= ~(PTRS_PER_PMD - 1);
- kvm_get_pfn(pfn);
+ get_page(pfn_to_page(pfn));
*pfnp = pfn;
return PMD_SIZE;
@@ -1050,9 +1097,14 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
* If we are not forced to use page mapping, check if we are
* backed by a THP and thus use block mapping if possible.
*/
- if (vma_pagesize == PAGE_SIZE && !(force_pte || device))
- vma_pagesize = transparent_hugepage_adjust(memslot, hva,
- &pfn, &fault_ipa);
+ if (vma_pagesize == PAGE_SIZE && !(force_pte || device)) {
+ if (fault_status == FSC_PERM && fault_granule > PAGE_SIZE)
+ vma_pagesize = fault_granule;
+ else
+ vma_pagesize = transparent_hugepage_adjust(kvm, memslot,
+ hva, &pfn,
+ &fault_ipa);
+ }
if (fault_status != FSC_PERM && !device && kvm_has_mte(kvm)) {
/* Check the VMM hasn't introduced a new VM_SHARED VMA */
diff --git a/arch/arm64/kvm/perf.c b/arch/arm64/kvm/perf.c
index 151c31fb9860..f9bb3b14130e 100644
--- a/arch/arm64/kvm/perf.c
+++ b/arch/arm64/kvm/perf.c
@@ -50,7 +50,7 @@ static struct perf_guest_info_callbacks kvm_guest_cbs = {
int kvm_perf_init(void)
{
- if (kvm_pmu_probe_pmuver() != 0xf && !is_protected_kvm_enabled())
+ if (kvm_pmu_probe_pmuver() != ID_AA64DFR0_PMUVER_IMP_DEF && !is_protected_kvm_enabled())
static_branch_enable(&kvm_arm_pmu_available);
return perf_register_guest_info_callbacks(&kvm_guest_cbs);
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index f33825c995cb..f5065f23b413 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -373,7 +373,6 @@ static u64 kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
reg &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
- reg &= kvm_pmu_valid_counter_mask(vcpu);
}
return reg;
@@ -564,20 +563,21 @@ void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val)
*/
void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
{
- unsigned long mask = kvm_pmu_valid_counter_mask(vcpu);
int i;
if (val & ARMV8_PMU_PMCR_E) {
kvm_pmu_enable_counter_mask(vcpu,
- __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask);
+ __vcpu_sys_reg(vcpu, PMCNTENSET_EL0));
} else {
- kvm_pmu_disable_counter_mask(vcpu, mask);
+ kvm_pmu_disable_counter_mask(vcpu,
+ __vcpu_sys_reg(vcpu, PMCNTENSET_EL0));
}
if (val & ARMV8_PMU_PMCR_C)
kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0);
if (val & ARMV8_PMU_PMCR_P) {
+ unsigned long mask = kvm_pmu_valid_counter_mask(vcpu);
mask &= ~BIT(ARMV8_PMU_CYCLE_IDX);
for_each_set_bit(i, &mask, 32)
kvm_pmu_set_counter_value(vcpu, i, 0);
@@ -745,7 +745,7 @@ int kvm_pmu_probe_pmuver(void)
struct perf_event_attr attr = { };
struct perf_event *event;
struct arm_pmu *pmu;
- int pmuver = 0xf;
+ int pmuver = ID_AA64DFR0_PMUVER_IMP_DEF;
/*
* Create a dummy event that only counts user cycles. As we'll never
@@ -770,7 +770,7 @@ int kvm_pmu_probe_pmuver(void)
if (IS_ERR(event)) {
pr_err_once("kvm: pmu event creation failed %ld\n",
PTR_ERR(event));
- return 0xf;
+ return ID_AA64DFR0_PMUVER_IMP_DEF;
}
if (event->pmu) {
@@ -923,7 +923,7 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
if (!vcpu->kvm->arch.pmuver)
vcpu->kvm->arch.pmuver = kvm_pmu_probe_pmuver();
- if (vcpu->kvm->arch.pmuver == 0xf)
+ if (vcpu->kvm->arch.pmuver == ID_AA64DFR0_PMUVER_IMP_DEF)
return -ENODEV;
switch (attr->attr) {
diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index db4056ecccfd..74c47d420253 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -59,6 +59,12 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
kvm_vcpu_kick(vcpu);
}
+static inline bool kvm_psci_valid_affinity(struct kvm_vcpu *vcpu,
+ unsigned long affinity)
+{
+ return !(affinity & ~MPIDR_HWID_BITMASK);
+}
+
static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
{
struct vcpu_reset_state *reset_state;
@@ -66,9 +72,9 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
struct kvm_vcpu *vcpu = NULL;
unsigned long cpu_id;
- cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK;
- if (vcpu_mode_is_32bit(source_vcpu))
- cpu_id &= ~((u32) 0);
+ cpu_id = smccc_get_arg1(source_vcpu);
+ if (!kvm_psci_valid_affinity(source_vcpu, cpu_id))
+ return PSCI_RET_INVALID_PARAMS;
vcpu = kvm_mpidr_to_vcpu(kvm, cpu_id);
@@ -126,6 +132,9 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
target_affinity = smccc_get_arg1(vcpu);
lowest_affinity_level = smccc_get_arg2(vcpu);
+ if (!kvm_psci_valid_affinity(vcpu, target_affinity))
+ return PSCI_RET_INVALID_PARAMS;
+
/* Determine target affinity mask */
target_affinity_mask = psci_affinity_mask(lowest_affinity_level);
if (!target_affinity_mask)
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index cba7872d69a8..5ce36b0a3343 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -210,10 +210,16 @@ static bool vcpu_allowed_register_width(struct kvm_vcpu *vcpu)
*/
int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
{
+ struct vcpu_reset_state reset_state;
int ret;
bool loaded;
u32 pstate;
+ mutex_lock(&vcpu->kvm->lock);
+ reset_state = vcpu->arch.reset_state;
+ WRITE_ONCE(vcpu->arch.reset_state.reset, false);
+ mutex_unlock(&vcpu->kvm->lock);
+
/* Reset PMU outside of the non-preemptible section */
kvm_pmu_vcpu_reset(vcpu);
@@ -276,8 +282,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
* Additional reset state handling that PSCI may have imposed on us.
* Must be done after all the sys_reg reset.
*/
- if (vcpu->arch.reset_state.reset) {
- unsigned long target_pc = vcpu->arch.reset_state.pc;
+ if (reset_state.reset) {
+ unsigned long target_pc = reset_state.pc;
/* Gracefully handle Thumb2 entry point */
if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
@@ -286,13 +292,11 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
}
/* Propagate caller endianness */
- if (vcpu->arch.reset_state.be)
+ if (reset_state.be)
kvm_vcpu_set_be(vcpu);
*vcpu_pc(vcpu) = target_pc;
- vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0);
-
- vcpu->arch.reset_state.reset = false;
+ vcpu_set_reg(vcpu, 0, reset_state.r0);
}
/* Reset timer */
@@ -311,31 +315,26 @@ u32 get_kvm_ipa_limit(void)
int kvm_set_ipa_limit(void)
{
- unsigned int parange, tgran_2;
+ unsigned int parange;
u64 mmfr0;
mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
parange = cpuid_feature_extract_unsigned_field(mmfr0,
ID_AA64MMFR0_PARANGE_SHIFT);
+ /*
+ * IPA size beyond 48 bits could not be supported
+ * on either 4K or 16K page size. Hence let's cap
+ * it to 48 bits, in case it's reported as larger
+ * on the system.
+ */
+ if (PAGE_SIZE != SZ_64K)
+ parange = min(parange, (unsigned int)ID_AA64MMFR0_PARANGE_48);
/*
* Check with ARMv8.5-GTG that our PAGE_SIZE is supported at
* Stage-2. If not, things will stop very quickly.
*/
- switch (PAGE_SIZE) {
- default:
- case SZ_4K:
- tgran_2 = ID_AA64MMFR0_TGRAN4_2_SHIFT;
- break;
- case SZ_16K:
- tgran_2 = ID_AA64MMFR0_TGRAN16_2_SHIFT;
- break;
- case SZ_64K:
- tgran_2 = ID_AA64MMFR0_TGRAN64_2_SHIFT;
- break;
- }
-
- switch (cpuid_feature_extract_unsigned_field(mmfr0, tgran_2)) {
+ switch (cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_TGRAN_2_SHIFT)) {
case ID_AA64MMFR0_TGRAN_2_SUPPORTED_NONE:
kvm_err("PAGE_SIZE not supported at Stage-2, giving up\n");
return -EINVAL;
@@ -369,7 +368,7 @@ int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
if (phys_shift) {
if (phys_shift > kvm_ipa_limit ||
- phys_shift < 32)
+ phys_shift < ARM64_MIN_PARANGE_BITS)
return -EINVAL;
} else {
phys_shift = KVM_PHYS_SHIFT;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index f6f126eb6ac1..1d46e185f31e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -44,10 +44,6 @@
* 64bit interface.
*/
-#define reg_to_encoding(x) \
- sys_reg((u32)(x)->Op0, (u32)(x)->Op1, \
- (u32)(x)->CRn, (u32)(x)->CRm, (u32)(x)->Op2)
-
static bool read_from_write_only(struct kvm_vcpu *vcpu,
struct sys_reg_params *params,
const struct sys_reg_desc *r)
@@ -318,14 +314,14 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
/*
* We want to avoid world-switching all the DBG registers all the
* time:
- *
+ *
* - If we've touched any debug register, it is likely that we're
* going to touch more of them. It then makes sense to disable the
* traps and start doing the save/restore dance
* - If debug is active (DBG_MDSCR_KDE or DBG_MDSCR_MDE set), it is
* then mandatory to save/restore the registers, as the guest
* depends on them.
- *
+ *
* For this, we use a DIRTY bit, indicating the guest has modified the
* debug registers, used as follow:
*
@@ -603,6 +599,41 @@ static unsigned int pmu_visibility(const struct kvm_vcpu *vcpu,
return REG_HIDDEN;
}
+static void reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+{
+ u64 n, mask = BIT(ARMV8_PMU_CYCLE_IDX);
+
+ /* No PMU available, any PMU reg may UNDEF... */
+ if (!kvm_arm_support_pmu_v3())
+ return;
+
+ n = read_sysreg(pmcr_el0) >> ARMV8_PMU_PMCR_N_SHIFT;
+ n &= ARMV8_PMU_PMCR_N_MASK;
+ if (n)
+ mask |= GENMASK(n - 1, 0);
+
+ reset_unknown(vcpu, r);
+ __vcpu_sys_reg(vcpu, r->reg) &= mask;
+}
+
+static void reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+{
+ reset_unknown(vcpu, r);
+ __vcpu_sys_reg(vcpu, r->reg) &= GENMASK(31, 0);
+}
+
+static void reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+{
+ reset_unknown(vcpu, r);
+ __vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_EVTYPE_MASK;
+}
+
+static void reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+{
+ reset_unknown(vcpu, r);
+ __vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_COUNTER_MASK;
+}
+
static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
{
u64 pmcr, val;
@@ -845,7 +876,7 @@ static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
kvm_pmu_disable_counter_mask(vcpu, val);
}
} else {
- p->regval = __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask;
+ p->regval = __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
}
return true;
@@ -869,7 +900,7 @@ static bool access_pminten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
/* accessing PMINTENCLR_EL1 */
__vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= ~val;
} else {
- p->regval = __vcpu_sys_reg(vcpu, PMINTENSET_EL1) & mask;
+ p->regval = __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
}
return true;
@@ -891,7 +922,7 @@ static bool access_pmovs(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
/* accessing PMOVSCLR_EL0 */
__vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= ~(p->regval & mask);
} else {
- p->regval = __vcpu_sys_reg(vcpu, PMOVSSET_EL0) & mask;
+ p->regval = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
}
return true;
@@ -944,16 +975,18 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
trap_wcr, reset_wcr, 0, 0, get_wcr, set_wcr }
#define PMU_SYS_REG(r) \
- SYS_DESC(r), .reset = reset_unknown, .visibility = pmu_visibility
+ SYS_DESC(r), .reset = reset_pmu_reg, .visibility = pmu_visibility
/* Macro to expand the PMEVCNTRn_EL0 register */
#define PMU_PMEVCNTR_EL0(n) \
{ PMU_SYS_REG(SYS_PMEVCNTRn_EL0(n)), \
+ .reset = reset_pmevcntr, \
.access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
/* Macro to expand the PMEVTYPERn_EL0 register */
#define PMU_PMEVTYPER_EL0(n) \
{ PMU_SYS_REG(SYS_PMEVTYPERn_EL0(n)), \
+ .reset = reset_pmevtyper, \
.access = access_pmu_evtyper, .reg = (PMEVTYPER0_EL0 + n), }
static bool undef_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
@@ -1026,8 +1059,6 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
return true;
}
-#define FEATURE(x) (GENMASK_ULL(x##_SHIFT + 3, x##_SHIFT))
-
/* Read a sanitised cpufeature ID register by sys_reg_desc */
static u64 read_id_reg(const struct kvm_vcpu *vcpu,
struct sys_reg_desc const *r, bool raz)
@@ -1038,40 +1069,40 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
switch (id) {
case SYS_ID_AA64PFR0_EL1:
if (!vcpu_has_sve(vcpu))
- val &= ~FEATURE(ID_AA64PFR0_SVE);
- val &= ~FEATURE(ID_AA64PFR0_AMU);
- val &= ~FEATURE(ID_AA64PFR0_CSV2);
- val |= FIELD_PREP(FEATURE(ID_AA64PFR0_CSV2), (u64)vcpu->kvm->arch.pfr0_csv2);
- val &= ~FEATURE(ID_AA64PFR0_CSV3);
- val |= FIELD_PREP(FEATURE(ID_AA64PFR0_CSV3), (u64)vcpu->kvm->arch.pfr0_csv3);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_SVE);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_AMU);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_CSV2);
+ val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV2), (u64)vcpu->kvm->arch.pfr0_csv2);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_CSV3);
+ val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV3), (u64)vcpu->kvm->arch.pfr0_csv3);
break;
case SYS_ID_AA64PFR1_EL1:
- val &= ~FEATURE(ID_AA64PFR1_MTE);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_MTE);
if (kvm_has_mte(vcpu->kvm)) {
u64 pfr, mte;
pfr = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1);
mte = cpuid_feature_extract_unsigned_field(pfr, ID_AA64PFR1_MTE_SHIFT);
- val |= FIELD_PREP(FEATURE(ID_AA64PFR1_MTE), mte);
+ val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR1_MTE), mte);
}
break;
case SYS_ID_AA64ISAR1_EL1:
if (!vcpu_has_ptrauth(vcpu))
- val &= ~(FEATURE(ID_AA64ISAR1_APA) |
- FEATURE(ID_AA64ISAR1_API) |
- FEATURE(ID_AA64ISAR1_GPA) |
- FEATURE(ID_AA64ISAR1_GPI));
+ val &= ~(ARM64_FEATURE_MASK(ID_AA64ISAR1_APA) |
+ ARM64_FEATURE_MASK(ID_AA64ISAR1_API) |
+ ARM64_FEATURE_MASK(ID_AA64ISAR1_GPA) |
+ ARM64_FEATURE_MASK(ID_AA64ISAR1_GPI));
break;
case SYS_ID_AA64DFR0_EL1:
/* Limit debug to ARMv8.0 */
- val &= ~FEATURE(ID_AA64DFR0_DEBUGVER);
- val |= FIELD_PREP(FEATURE(ID_AA64DFR0_DEBUGVER), 6);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER);
+ val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER), 6);
/* Limit guests to PMUv3 for ARMv8.4 */
val = cpuid_feature_cap_perfmon_field(val,
ID_AA64DFR0_PMUVER_SHIFT,
kvm_vcpu_has_pmu(vcpu) ? ID_AA64DFR0_PMUVER_8_4 : 0);
/* Hide SPE from guests */
- val &= ~FEATURE(ID_AA64DFR0_PMSVER);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_PMSVER);
break;
case SYS_ID_DFR0_EL1:
/* Limit guests to PMUv3 for ARMv8.4 */
@@ -1249,6 +1280,20 @@ static int set_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
return __set_id_reg(vcpu, rd, uaddr, true);
}
+static int set_wi_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
+ const struct kvm_one_reg *reg, void __user *uaddr)
+{
+ int err;
+ u64 val;
+
+ /* Perform the access even if we are going to ignore the value */
+ err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
+ if (err)
+ return err;
+
+ return 0;
+}
+
static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
@@ -1592,16 +1637,21 @@ static const struct sys_reg_desc sys_reg_descs[] = {
.access = access_pmcnten, .reg = PMCNTENSET_EL0 },
{ PMU_SYS_REG(SYS_PMOVSCLR_EL0),
.access = access_pmovs, .reg = PMOVSSET_EL0 },
+ /*
+ * PM_SWINC_EL0 is exposed to userspace as RAZ/WI, as it was
+ * previously (and pointlessly) advertised in the past...
+ */
{ PMU_SYS_REG(SYS_PMSWINC_EL0),
- .access = access_pmswinc, .reg = PMSWINC_EL0 },
+ .get_user = get_raz_id_reg, .set_user = set_wi_reg,
+ .access = access_pmswinc, .reset = NULL },
{ PMU_SYS_REG(SYS_PMSELR_EL0),
- .access = access_pmselr, .reg = PMSELR_EL0 },
+ .access = access_pmselr, .reset = reset_pmselr, .reg = PMSELR_EL0 },
{ PMU_SYS_REG(SYS_PMCEID0_EL0),
.access = access_pmceid, .reset = NULL },
{ PMU_SYS_REG(SYS_PMCEID1_EL0),
.access = access_pmceid, .reset = NULL },
{ PMU_SYS_REG(SYS_PMCCNTR_EL0),
- .access = access_pmu_evcntr, .reg = PMCCNTR_EL0 },
+ .access = access_pmu_evcntr, .reset = reset_unknown, .reg = PMCCNTR_EL0 },
{ PMU_SYS_REG(SYS_PMXEVTYPER_EL0),
.access = access_pmu_evtyper, .reset = NULL },
{ PMU_SYS_REG(SYS_PMXEVCNTR_EL0),
@@ -2106,23 +2156,6 @@ static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,
return 0;
}
-static int match_sys_reg(const void *key, const void *elt)
-{
- const unsigned long pval = (unsigned long)key;
- const struct sys_reg_desc *r = elt;
-
- return pval - reg_to_encoding(r);
-}
-
-static const struct sys_reg_desc *find_reg(const struct sys_reg_params *params,
- const struct sys_reg_desc table[],
- unsigned int num)
-{
- unsigned long pval = reg_to_encoding(params);
-
- return bsearch((void *)pval, table, num, sizeof(table[0]), match_sys_reg);
-}
-
int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu)
{
kvm_inject_undefined(vcpu);
@@ -2365,13 +2398,8 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu)
trace_kvm_handle_sys_reg(esr);
- params.Op0 = (esr >> 20) & 3;
- params.Op1 = (esr >> 14) & 0x7;
- params.CRn = (esr >> 10) & 0xf;
- params.CRm = (esr >> 1) & 0xf;
- params.Op2 = (esr >> 17) & 0x7;
+ params = esr_sys64_to_params(esr);
params.regval = vcpu_get_reg(vcpu, Rt);
- params.is_write = !(esr & 1);
ret = emulate_sys_reg(vcpu, &params);
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index 9d0621417c2a..cc0cc95a0280 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -11,6 +11,12 @@
#ifndef __ARM64_KVM_SYS_REGS_LOCAL_H__
#define __ARM64_KVM_SYS_REGS_LOCAL_H__
+#include <linux/bsearch.h>
+
+#define reg_to_encoding(x) \
+ sys_reg((u32)(x)->Op0, (u32)(x)->Op1, \
+ (u32)(x)->CRn, (u32)(x)->CRm, (u32)(x)->Op2)
+
struct sys_reg_params {
u8 Op0;
u8 Op1;
@@ -21,6 +27,14 @@ struct sys_reg_params {
bool is_write;
};
+#define esr_sys64_to_params(esr) \
+ ((struct sys_reg_params){ .Op0 = ((esr) >> 20) & 3, \
+ .Op1 = ((esr) >> 14) & 0x7, \
+ .CRn = ((esr) >> 10) & 0xf, \
+ .CRm = ((esr) >> 1) & 0xf, \
+ .Op2 = ((esr) >> 17) & 0x7, \
+ .is_write = !((esr) & 1) })
+
struct sys_reg_desc {
/* Sysreg string for debug */
const char *name;
@@ -152,6 +166,23 @@ static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
return i1->Op2 - i2->Op2;
}
+static inline int match_sys_reg(const void *key, const void *elt)
+{
+ const unsigned long pval = (unsigned long)key;
+ const struct sys_reg_desc *r = elt;
+
+ return pval - reg_to_encoding(r);
+}
+
+static inline const struct sys_reg_desc *
+find_reg(const struct sys_reg_params *params, const struct sys_reg_desc table[],
+ unsigned int num)
+{
+ unsigned long pval = reg_to_encoding(params);
+
+ return __inline_bsearch((void *)pval, table, num, sizeof(table[0]), match_sys_reg);
+}
+
const struct sys_reg_desc *find_reg_by_id(u64 id,
struct sys_reg_params *params,
const struct sys_reg_desc table[],
diff --git a/arch/arm64/kvm/trace_handle_exit.h b/arch/arm64/kvm/trace_handle_exit.h
index 8d78acc4fba7..064a58c19f48 100644
--- a/arch/arm64/kvm/trace_handle_exit.h
+++ b/arch/arm64/kvm/trace_handle_exit.h
@@ -78,13 +78,17 @@ TRACE_EVENT(kvm_arm_clear_debug,
TP_printk("flags: 0x%08x", __entry->guest_debug)
);
+/*
+ * The dreg32 name is a leftover from a distant past. This will really
+ * output a 64bit value...
+ */
TRACE_EVENT(kvm_arm_set_dreg32,
- TP_PROTO(const char *name, __u32 value),
+ TP_PROTO(const char *name, __u64 value),
TP_ARGS(name, value),
TP_STRUCT__entry(
__field(const char *, name)
- __field(__u32, value)
+ __field(__u64, value)
),
TP_fast_assign(
@@ -92,7 +96,7 @@ TRACE_EVENT(kvm_arm_set_dreg32,
__entry->value = value;
),
- TP_printk("%s: 0x%08x", __entry->name, __entry->value)
+ TP_printk("%s: 0x%llx", __entry->name, __entry->value)
);
TRACE_DEFINE_SIZEOF(__u64);
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
index a016f07adc28..5f9014ae595b 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
@@ -282,7 +282,7 @@ static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
case GIC_CPU_PRIMASK:
/*
* Our KVM_DEV_TYPE_ARM_VGIC_V2 device ABI exports the
- * the PMR field as GICH_VMCR.VMPriMask rather than
+ * PMR field as GICH_VMCR.VMPriMask rather than
* GICC_PMR.Priority, so we expose the upper five bits of
* priority mask to userspace using the lower bits in the
* unsigned long.
@@ -329,7 +329,7 @@ static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
case GIC_CPU_PRIMASK:
/*
* Our KVM_DEV_TYPE_ARM_VGIC_V2 device ABI exports the
- * the PMR field as GICH_VMCR.VMPriMask rather than
+ * PMR field as GICH_VMCR.VMPriMask rather than
* GICC_PMR.Priority, so we expose the upper five bits of
* priority mask to userspace using the lower bits in the
* unsigned long.
diff --git a/arch/arm64/kvm/vgic/vgic-v2.c b/arch/arm64/kvm/vgic/vgic-v2.c
index 2c580204f1dc..95a18cec14a3 100644
--- a/arch/arm64/kvm/vgic/vgic-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-v2.c
@@ -60,6 +60,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
u32 val = cpuif->vgic_lr[lr];
u32 cpuid, intid = val & GICH_LR_VIRTUALID;
struct vgic_irq *irq;
+ bool deactivated;
/* Extract the source vCPU id from the LR */
cpuid = val & GICH_LR_PHYSID_CPUID;
@@ -75,7 +76,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
raw_spin_lock(&irq->irq_lock);
- /* Always preserve the active bit */
+ /* Always preserve the active bit, note deactivation */
+ deactivated = irq->active && !(val & GICH_LR_ACTIVE_BIT);
irq->active = !!(val & GICH_LR_ACTIVE_BIT);
if (irq->active && vgic_irq_is_sgi(intid))
@@ -96,36 +98,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
if (irq->config == VGIC_CONFIG_LEVEL && !(val & GICH_LR_STATE))
irq->pending_latch = false;
- /*
- * Level-triggered mapped IRQs are special because we only
- * observe rising edges as input to the VGIC.
- *
- * If the guest never acked the interrupt we have to sample
- * the physical line and set the line level, because the
- * device state could have changed or we simply need to
- * process the still pending interrupt later.
- *
- * If this causes us to lower the level, we have to also clear
- * the physical active state, since we will otherwise never be
- * told when the interrupt becomes asserted again.
- *
- * Another case is when the interrupt requires a helping hand
- * on deactivation (no HW deactivation, for example).
- */
- if (vgic_irq_is_mapped_level(irq)) {
- bool resample = false;
-
- if (val & GICH_LR_PENDING_BIT) {
- irq->line_level = vgic_get_phys_line_level(irq);
- resample = !irq->line_level;
- } else if (vgic_irq_needs_resampling(irq) &&
- !(irq->active || irq->pending_latch)) {
- resample = true;
- }
-
- if (resample)
- vgic_irq_set_phys_active(irq, false);
- }
+ /* Handle resampling for mapped interrupts if required */
+ vgic_irq_handle_resampling(irq, deactivated, val & GICH_LR_PENDING_BIT);
raw_spin_unlock(&irq->irq_lock);
vgic_put_irq(vcpu->kvm, irq);
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index 66004f61cd83..21a6207fb2ee 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -46,6 +46,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
u32 intid, cpuid;
struct vgic_irq *irq;
bool is_v2_sgi = false;
+ bool deactivated;
cpuid = val & GICH_LR_PHYSID_CPUID;
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
@@ -68,7 +69,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
raw_spin_lock(&irq->irq_lock);
- /* Always preserve the active bit */
+ /* Always preserve the active bit, note deactivation */
+ deactivated = irq->active && !(val & ICH_LR_ACTIVE_BIT);
irq->active = !!(val & ICH_LR_ACTIVE_BIT);
if (irq->active && is_v2_sgi)
@@ -89,36 +91,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
if (irq->config == VGIC_CONFIG_LEVEL && !(val & ICH_LR_STATE))
irq->pending_latch = false;
- /*
- * Level-triggered mapped IRQs are special because we only
- * observe rising edges as input to the VGIC.
- *
- * If the guest never acked the interrupt we have to sample
- * the physical line and set the line level, because the
- * device state could have changed or we simply need to
- * process the still pending interrupt later.
- *
- * If this causes us to lower the level, we have to also clear
- * the physical active state, since we will otherwise never be
- * told when the interrupt becomes asserted again.
- *
- * Another case is when the interrupt requires a helping hand
- * on deactivation (no HW deactivation, for example).
- */
- if (vgic_irq_is_mapped_level(irq)) {
- bool resample = false;
-
- if (val & ICH_LR_PENDING_BIT) {
- irq->line_level = vgic_get_phys_line_level(irq);
- resample = !irq->line_level;
- } else if (vgic_irq_needs_resampling(irq) &&
- !(irq->active || irq->pending_latch)) {
- resample = true;
- }
-
- if (resample)
- vgic_irq_set_phys_active(irq, false);
- }
+ /* Handle resampling for mapped interrupts if required */
+ vgic_irq_handle_resampling(irq, deactivated, val & ICH_LR_PENDING_BIT);
raw_spin_unlock(&irq->irq_lock);
vgic_put_irq(vcpu->kvm, irq);
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index 111bff47e471..5dad4996cfb2 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -106,7 +106,6 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
if (intid >= VGIC_MIN_LPI)
return vgic_get_lpi(kvm, intid);
- WARN(1, "Looking up struct vgic_irq for reserved INTID");
return NULL;
}
@@ -1022,3 +1021,41 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
return map_is_active;
}
+
+/*
+ * Level-triggered mapped IRQs are special because we only observe rising
+ * edges as input to the VGIC.
+ *
+ * If the guest never acked the interrupt we have to sample the physical
+ * line and set the line level, because the device state could have changed
+ * or we simply need to process the still pending interrupt later.
+ *
+ * We could also have entered the guest with the interrupt active+pending.
+ * On the next exit, we need to re-evaluate the pending state, as it could
+ * otherwise result in a spurious interrupt by injecting a now potentially
+ * stale pending state.
+ *
+ * If this causes us to lower the level, we have to also clear the physical
+ * active state, since we will otherwise never be told when the interrupt
+ * becomes asserted again.
+ *
+ * Another case is when the interrupt requires a helping hand on
+ * deactivation (no HW deactivation, for example).
+ */
+void vgic_irq_handle_resampling(struct vgic_irq *irq,
+ bool lr_deactivated, bool lr_pending)
+{
+ if (vgic_irq_is_mapped_level(irq)) {
+ bool resample = false;
+
+ if (unlikely(vgic_irq_needs_resampling(irq))) {
+ resample = !(irq->active || irq->pending_latch);
+ } else if (lr_pending || (lr_deactivated && irq->line_level)) {
+ irq->line_level = vgic_get_phys_line_level(irq);
+ resample = !irq->line_level;
+ }
+
+ if (resample)
+ vgic_irq_set_phys_active(irq, false);
+ }
+}
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index dc1f3d1657ee..14a9218641f5 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -169,6 +169,8 @@ void vgic_irq_set_phys_active(struct vgic_irq *irq, bool active);
bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
unsigned long flags);
void vgic_kick_vcpus(struct kvm *kvm);
+void vgic_irq_handle_resampling(struct vgic_irq *irq,
+ bool lr_deactivated, bool lr_pending);
int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
phys_addr_t addr, phys_addr_t alignment);
diff --git a/arch/arm64/lib/insn.c b/arch/arm64/lib/insn.c
index b506a4b1e38c..fccfe363e567 100644
--- a/arch/arm64/lib/insn.c
+++ b/arch/arm64/lib/insn.c
@@ -185,7 +185,7 @@ u64 aarch64_insn_decode_immediate(enum aarch64_insn_imm_type type, u32 insn)
break;
default:
if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) {
- pr_err("aarch64_insn_decode_immediate: unknown immediate encoding %d\n",
+ pr_err("%s: unknown immediate encoding %d\n", __func__,
type);
return 0;
}
@@ -215,7 +215,7 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
break;
default:
if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) {
- pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n",
+ pr_err("%s: unknown immediate encoding %d\n", __func__,
type);
return AARCH64_BREAK_FAULT;
}
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 349c488765ca..9ae24e3b72be 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -309,24 +309,11 @@ static void die_kernel_fault(const char *msg, unsigned long addr,
static void report_tag_fault(unsigned long addr, unsigned int esr,
struct pt_regs *regs)
{
- static bool reported;
- bool is_write;
-
- if (READ_ONCE(reported))
- return;
-
- /*
- * This is used for KASAN tests and assumes that no MTE faults
- * happened before running the tests.
- */
- if (mte_report_once())
- WRITE_ONCE(reported, true);
-
/*
* SAS bits aren't set for all faults reported in EL1, so we can't
* find out access size.
*/
- is_write = !!(esr & ESR_ELx_WNR);
+ bool is_write = !!(esr & ESR_ELx_WNR);
kasan_report(addr, 0, is_write, regs->pc);
}
#else
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 1fdb7bb7c198..b16be52233c6 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -74,6 +74,7 @@ phys_addr_t arm64_dma_phys_limit __ro_after_init;
static void __init reserve_crashkernel(void)
{
unsigned long long crash_base, crash_size;
+ unsigned long long crash_max = arm64_dma_phys_limit;
int ret;
ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
@@ -84,33 +85,18 @@ static void __init reserve_crashkernel(void)
crash_size = PAGE_ALIGN(crash_size);
- if (crash_base == 0) {
- /* Current arm64 boot protocol requires 2MB alignment */
- crash_base = memblock_find_in_range(0, arm64_dma_phys_limit,
- crash_size, SZ_2M);
- if (crash_base == 0) {
- pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
- crash_size);
- return;
- }
- } else {
- /* User specifies base address explicitly. */
- if (!memblock_is_region_memory(crash_base, crash_size)) {
- pr_warn("cannot reserve crashkernel: region is not memory\n");
- return;
- }
+ /* User specifies base address explicitly. */
+ if (crash_base)
+ crash_max = crash_base + crash_size;
- if (memblock_is_region_reserved(crash_base, crash_size)) {
- pr_warn("cannot reserve crashkernel: region overlaps reserved memory\n");
- return;
- }
-
- if (!IS_ALIGNED(crash_base, SZ_2M)) {
- pr_warn("cannot reserve crashkernel: base address is not 2MB aligned\n");
- return;
- }
+ /* Current arm64 boot protocol requires 2MB alignment */
+ crash_base = memblock_phys_alloc_range(crash_size, SZ_2M,
+ crash_base, crash_max);
+ if (!crash_base) {
+ pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
+ crash_size);
+ return;
}
- memblock_reserve(crash_base, crash_size);
pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
crash_base, crash_base + crash_size, crash_size >> 20);
@@ -124,57 +110,6 @@ static void __init reserve_crashkernel(void)
}
#endif /* CONFIG_KEXEC_CORE */
-#ifdef CONFIG_CRASH_DUMP
-static int __init early_init_dt_scan_elfcorehdr(unsigned long node,
- const char *uname, int depth, void *data)
-{
- const __be32 *reg;
- int len;
-
- if (depth != 1 || strcmp(uname, "chosen") != 0)
- return 0;
-
- reg = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len);
- if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells)))
- return 1;
-
- elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, &reg);
- elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, &reg);
-
- return 1;
-}
-
-/*
- * reserve_elfcorehdr() - reserves memory for elf core header
- *
- * This function reserves the memory occupied by an elf core header
- * described in the device tree. This region contains all the
- * information about primary kernel's core image and is used by a dump
- * capture kernel to access the system memory on primary kernel.
- */
-static void __init reserve_elfcorehdr(void)
-{
- of_scan_flat_dt(early_init_dt_scan_elfcorehdr, NULL);
-
- if (!elfcorehdr_size)
- return;
-
- if (memblock_is_region_reserved(elfcorehdr_addr, elfcorehdr_size)) {
- pr_warn("elfcorehdr is overlapped\n");
- return;
- }
-
- memblock_reserve(elfcorehdr_addr, elfcorehdr_size);
-
- pr_info("Reserving %lldKB of memory at 0x%llx for elfcorehdr\n",
- elfcorehdr_size >> 10, elfcorehdr_addr);
-}
-#else
-static void __init reserve_elfcorehdr(void)
-{
-}
-#endif /* CONFIG_CRASH_DUMP */
-
/*
* Return the maximum physical address for a zone accessible by the given bits
* limit. If DRAM starts above 32-bit, expand the zone to the maximum
@@ -285,45 +220,10 @@ static int __init early_mem(char *p)
}
early_param("mem", early_mem);
-static int __init early_init_dt_scan_usablemem(unsigned long node,
- const char *uname, int depth, void *data)
-{
- struct memblock_region *usablemem = data;
- const __be32 *reg;
- int len;
-
- if (depth != 1 || strcmp(uname, "chosen") != 0)
- return 0;
-
- reg = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len);
- if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells)))
- return 1;
-
- usablemem->base = dt_mem_next_cell(dt_root_addr_cells, &reg);
- usablemem->size = dt_mem_next_cell(dt_root_size_cells, &reg);
-
- return 1;
-}
-
-static void __init fdt_enforce_memory_region(void)
-{
- struct memblock_region reg = {
- .size = 0,
- };
-
- of_scan_flat_dt(early_init_dt_scan_usablemem, &reg);
-
- if (reg.size)
- memblock_cap_memory_range(reg.base, reg.size);
-}
-
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual);
- /* Handle linux,usable-memory-range property */
- fdt_enforce_memory_region();
-
/* Remove memory above our supported physical address size */
memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX);
@@ -432,8 +332,6 @@ void __init arm64_memblock_init(void)
early_init_fdt_scan_reserved_mem();
- reserve_elfcorehdr();
-
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
}
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 35936c5ae1ce..d35c90d2e47a 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -437,8 +437,7 @@ SYM_FUNC_START(__cpu_setup)
mov x10, #MAIR_ATTR_NORMAL_TAGGED
bfi mair, x10, #(8 * MT_NORMAL_TAGGED), #8
- /* initialize GCR_EL1: all non-zero tags excluded by default */
- mov x10, #(SYS_GCR_EL1_RRND | SYS_GCR_EL1_EXCL_MASK)
+ mov x10, #KERNEL_GCR_EL1
msr_s SYS_GCR_EL1, x10
/*
diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
index 2716f6395ba7..9d4d898df76b 100644
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -82,6 +82,7 @@ config CSKY
select PCI_SYSCALL if PCI
select PCI_MSI if PCI
select SET_FS
+ select TRACE_IRQFLAGS_SUPPORT
config LOCKDEP_SUPPORT
def_bool y
@@ -139,9 +140,6 @@ config STACKTRACE_SUPPORT
config TIME_LOW_RES
def_bool y
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config CPU_TLB_SIZE
int
default "128" if (CPU_CK610 || CPU_CK807 || CPU_CK810)
diff --git a/arch/csky/abiv1/cacheflush.c b/arch/csky/abiv1/cacheflush.c
index 07ff17ea33de..fb91b069dc69 100644
--- a/arch/csky/abiv1/cacheflush.c
+++ b/arch/csky/abiv1/cacheflush.c
@@ -56,17 +56,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
}
}
-void flush_kernel_dcache_page(struct page *page)
-{
- struct address_space *mapping;
-
- mapping = page_mapping_file(page);
-
- if (!mapping || mapping_mapped(mapping))
- dcache_wbinv_all();
-}
-EXPORT_SYMBOL(flush_kernel_dcache_page);
-
void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
diff --git a/arch/csky/abiv1/inc/abi/cacheflush.h b/arch/csky/abiv1/inc/abi/cacheflush.h
index 6cab7afae962..ed62e2066ba7 100644
--- a/arch/csky/abiv1/inc/abi/cacheflush.h
+++ b/arch/csky/abiv1/inc/abi/cacheflush.h
@@ -14,12 +14,10 @@ extern void flush_dcache_page(struct page *);
#define flush_cache_page(vma, page, pfn) cache_wbinv_all()
#define flush_cache_dup_mm(mm) cache_wbinv_all()
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-extern void flush_kernel_dcache_page(struct page *);
-
#define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages)
#define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages)
+#define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1
static inline void flush_kernel_vmap_range(void *addr, int size)
{
dcache_wbinv_all();
diff --git a/arch/csky/include/asm/uaccess.h b/arch/csky/include/asm/uaccess.h
index ac83823fc437..c40f06ee8d3e 100644
--- a/arch/csky/include/asm/uaccess.h
+++ b/arch/csky/include/asm/uaccess.h
@@ -209,12 +209,6 @@ unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n);
unsigned long __clear_user(void __user *to, unsigned long n);
#define __clear_user __clear_user
-long __strncpy_from_user(char *dst, const char *src, long count);
-#define __strncpy_from_user __strncpy_from_user
-
-long __strnlen_user(const char *s, long n);
-#define __strnlen_user __strnlen_user
-
#include <asm/segment.h>
#include <asm-generic/uaccess.h>
diff --git a/arch/csky/kernel/probes/kprobes.c b/arch/csky/kernel/probes/kprobes.c
index 68b22b499aeb..8fffa34d4e1c 100644
--- a/arch/csky/kernel/probes/kprobes.c
+++ b/arch/csky/kernel/probes/kprobes.c
@@ -283,8 +283,7 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr)
* normal page fault.
*/
regs->pc = (unsigned long) cur->addr;
- if (!instruction_pointer(regs))
- BUG();
+ BUG_ON(!instruction_pointer(regs));
if (kcb->kprobe_status == KPROBE_REENTER)
restore_previous_kprobe(kcb);
diff --git a/arch/csky/lib/usercopy.c b/arch/csky/lib/usercopy.c
index c5d394a0ae78..3c01c54421ca 100644
--- a/arch/csky/lib/usercopy.c
+++ b/arch/csky/lib/usercopy.c
@@ -143,108 +143,6 @@ unsigned long raw_copy_to_user(void *to, const void *from,
EXPORT_SYMBOL(raw_copy_to_user);
/*
- * __strncpy_from_user: - Copy a NUL terminated string from userspace,
- * with less checking.
- * @dst: Destination address, in kernel space. This buffer must be at
- * least @count bytes long.
- * @src: Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- * Caller must check the specified block with access_ok() before calling
- * this function.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-long __strncpy_from_user(char *dst, const char *src, long count)
-{
- long res, faultres;
- int tmp;
-
- __asm__ __volatile__(
- " cmpnei %3, 0 \n"
- " bf 4f \n"
- "1: cmpnei %1, 0 \n"
- " bf 5f \n"
- "2: ldb %4, (%3, 0) \n"
- " stb %4, (%2, 0) \n"
- " cmpnei %4, 0 \n"
- " bf 3f \n"
- " addi %3, 1 \n"
- " addi %2, 1 \n"
- " subi %1, 1 \n"
- " br 1b \n"
- "3: subu %0, %1 \n"
- " br 5f \n"
- "4: mov %0, %5 \n"
- " br 5f \n"
- ".section __ex_table, \"a\" \n"
- ".align 2 \n"
- ".long 2b, 4b \n"
- ".previous \n"
- "5: \n"
- : "=r"(res), "=r"(count), "=r"(dst),
- "=r"(src), "=r"(tmp), "=r"(faultres)
- : "5"(-EFAULT), "0"(count), "1"(count),
- "2"(dst), "3"(src)
- : "memory");
-
- return res;
-}
-EXPORT_SYMBOL(__strncpy_from_user);
-
-/*
- * strnlen_user: - Get the size of a string in user space.
- * @str: The string to measure.
- * @n: The maximum valid length
- *
- * Get the size of a NUL-terminated string in user space.
- *
- * Returns the size of the string INCLUDING the terminating NUL.
- * On exception, returns 0.
- * If the string is too long, returns a value greater than @n.
- */
-long __strnlen_user(const char *s, long n)
-{
- unsigned long res, tmp;
-
- __asm__ __volatile__(
- " cmpnei %1, 0 \n"
- " bf 3f \n"
- "1: cmpnei %0, 0 \n"
- " bf 3f \n"
- "2: ldb %3, (%1, 0) \n"
- " cmpnei %3, 0 \n"
- " bf 3f \n"
- " subi %0, 1 \n"
- " addi %1, 1 \n"
- " br 1b \n"
- "3: subu %2, %0 \n"
- " addi %2, 1 \n"
- " br 5f \n"
- "4: movi %0, 0 \n"
- " br 5f \n"
- ".section __ex_table, \"a\" \n"
- ".align 2 \n"
- ".long 2b, 4b \n"
- ".previous \n"
- "5: \n"
- : "=r"(n), "=r"(s), "=r"(res), "=r"(tmp)
- : "0"(n), "1"(s), "2"(n)
- : "memory");
-
- return res;
-}
-EXPORT_SYMBOL(__strnlen_user);
-
-/*
* __clear_user: - Zero a block of memory in user space, with less checking.
* @to: Destination address, in user space.
* @n: Number of bytes to zero.
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index 1c6f902e82a5..853d6e886477 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -19,7 +19,6 @@ asmlinkage long __mulsi3(long, long);
asmlinkage long __udivsi3(long, long);
asmlinkage void *memcpy(void *, const void *, size_t);
asmlinkage void *memset(void *, int, size_t);
-asmlinkage long strncpy_from_user(void *to, void *from, size_t n);
/* gcc lib functions */
EXPORT_SYMBOL(__ucmpdi2);
@@ -34,4 +33,3 @@ EXPORT_SYMBOL(__mulsi3);
EXPORT_SYMBOL(__udivsi3);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strncpy_from_user);
diff --git a/arch/h8300/lib/Makefile b/arch/h8300/lib/Makefile
index 685fa837c1f7..5911c1fa856d 100644
--- a/arch/h8300/lib/Makefile
+++ b/arch/h8300/lib/Makefile
@@ -3,7 +3,7 @@
# Makefile for H8/300-specific library files..
#
-lib-y = memcpy.o memset.o abs.o strncpy.o \
+lib-y = memcpy.o memset.o abs.o \
mulsi3.o udivsi3.o muldi3.o moddivsi3.o \
ashldi3.o lshrdi3.o ashrdi3.o ucmpdi2.o \
delay.o
diff --git a/arch/h8300/lib/strncpy.S b/arch/h8300/lib/strncpy.S
deleted file mode 100644
index 8b65d7c4727b..000000000000
--- a/arch/h8300/lib/strncpy.S
+++ /dev/null
@@ -1,35 +0,0 @@
-;;; SPDX-License-Identifier: GPL-2.0
-;;; strncpy.S
-
-#include <asm/linkage.h>
-
- .text
-.global strncpy_from_user
-
-;;; long strncpy_from_user(void *to, void *from, size_t n)
-strncpy_from_user:
- mov.l er2,er2
- bne 1f
- sub.l er0,er0
- rts
-1:
- mov.l er4,@-sp
- sub.l er3,er3
-2:
- mov.b @er1+,r4l
- mov.b r4l,@er0
- adds #1,er0
- beq 3f
- inc.l #1,er3
- dec.l #1,er2
- bne 2b
-3:
- dec.l #1,er2
-4:
- mov.b r4l,@er0
- adds #1,er0
- dec.l #1,er2
- bne 4b
- mov.l er3,er0
- mov.l @sp+,er4
- rts
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index e5a852080730..15dd8f38b698 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -7,6 +7,7 @@ config HEXAGON
select ARCH_32BIT_OFF_T
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select ARCH_NO_PREEMPT
+ select DMA_GLOBAL_POOL
# Other pending projects/to-do items.
# select HAVE_REGS_AND_STACK_ACCESS_API
# select HAVE_HW_BREAKPOINT if PERF_EVENTS
@@ -31,6 +32,7 @@ config HEXAGON
select GENERIC_CPU_DEVICES
select SET_FS
select ARCH_WANT_LD_ORPHAN_WARN
+ select TRACE_IRQFLAGS_SUPPORT
help
Qualcomm Hexagon is a processor architecture designed for high
performance and low power across a wide variety of applications.
@@ -52,9 +54,6 @@ config EARLY_PRINTK
config MMU
def_bool y
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config GENERIC_CSUM
def_bool y
diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h
index c1019a736ff1..ef5bfef8d490 100644
--- a/arch/hexagon/include/asm/uaccess.h
+++ b/arch/hexagon/include/asm/uaccess.h
@@ -57,38 +57,7 @@ unsigned long raw_copy_to_user(void __user *to, const void *from,
__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
#define __clear_user(a, s) __clear_user_hexagon((a), (s))
-#define __strncpy_from_user(dst, src, n) hexagon_strncpy_from_user(dst, src, n)
-
-/* get around the ifndef in asm-generic/uaccess.h */
-#define __strnlen_user __strnlen_user
-
-extern long __strnlen_user(const char __user *src, long n);
-
-static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
- long n);
-
#include <asm-generic/uaccess.h>
-/* Todo: an actual accelerated version of this. */
-static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
- long n)
-{
- long res = __strnlen_user(src, n);
-
- if (unlikely(!res))
- return -EFAULT;
-
- if (res > n) {
- long left = raw_copy_from_user(dst, src, n);
- if (unlikely(left))
- memset(dst + (n - left), 0, left);
- return n;
- } else {
- long left = raw_copy_from_user(dst, src, res);
- if (unlikely(left))
- memset(dst + (res - left), 0, left);
- return res-1;
- }
-}
#endif
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index 00b9a81075dd..882680e81a30 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -7,54 +7,8 @@
#include <linux/dma-map-ops.h>
#include <linux/memblock.h>
-#include <linux/genalloc.h>
-#include <linux/module.h>
#include <asm/page.h>
-static struct gen_pool *coherent_pool;
-
-
-/* Allocates from a pool of uncached memory that was reserved at boot time */
-
-void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_addr,
- gfp_t flag, unsigned long attrs)
-{
- void *ret;
-
- /*
- * Our max_low_pfn should have been backed off by 16MB in
- * mm/init.c to create DMA coherent space. Use that as the VA
- * for the pool.
- */
-
- if (coherent_pool == NULL) {
- coherent_pool = gen_pool_create(PAGE_SHIFT, -1);
-
- if (coherent_pool == NULL)
- panic("Can't create %s() memory pool!", __func__);
- else
- gen_pool_add(coherent_pool,
- (unsigned long)pfn_to_virt(max_low_pfn),
- hexagon_coherent_pool_size, -1);
- }
-
- ret = (void *) gen_pool_alloc(coherent_pool, size);
-
- if (ret) {
- memset(ret, 0, size);
- *dma_addr = (dma_addr_t) virt_to_phys(ret);
- } else
- *dma_addr = ~0;
-
- return ret;
-}
-
-void arch_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_addr, unsigned long attrs)
-{
- gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
-}
-
void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
enum dma_data_direction dir)
{
@@ -77,3 +31,14 @@ void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
BUG();
}
}
+
+/*
+ * Our max_low_pfn should have been backed off by 16MB in mm/init.c to create
+ * DMA coherent space. Use that for the pool.
+ */
+static int __init hexagon_dma_init(void)
+{
+ return dma_init_global_coherent(PFN_PHYS(max_low_pfn),
+ hexagon_coherent_pool_size);
+}
+core_initcall(hexagon_dma_init);
diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c
index 35545a7386a0..ec56ce2d92a2 100644
--- a/arch/hexagon/kernel/hexagon_ksyms.c
+++ b/arch/hexagon/kernel/hexagon_ksyms.c
@@ -15,7 +15,6 @@ EXPORT_SYMBOL(__clear_user_hexagon);
EXPORT_SYMBOL(raw_copy_from_user);
EXPORT_SYMBOL(raw_copy_to_user);
EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(__strnlen_user);
EXPORT_SYMBOL(__vmgetie);
EXPORT_SYMBOL(__vmsetie);
EXPORT_SYMBOL(__vmyield);
diff --git a/arch/hexagon/mm/Makefile b/arch/hexagon/mm/Makefile
index 893838499591..49911a906fd0 100644
--- a/arch/hexagon/mm/Makefile
+++ b/arch/hexagon/mm/Makefile
@@ -4,4 +4,4 @@
#
obj-y := init.o ioremap.o uaccess.o vm_fault.o cache.o
-obj-y += copy_to_user.o copy_from_user.o strnlen_user.o vm_tlb.o
+obj-y += copy_to_user.o copy_from_user.o vm_tlb.o
diff --git a/arch/hexagon/mm/strnlen_user.S b/arch/hexagon/mm/strnlen_user.S
deleted file mode 100644
index 4b5574a7cc9c..000000000000
--- a/arch/hexagon/mm/strnlen_user.S
+++ /dev/null
@@ -1,126 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * User string length functions for kernel
- *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
- */
-
-#define isrc r0
-#define max r1 /* Do not change! */
-
-#define end r2
-#define tmp1 r3
-
-#define obo r6 /* off-by-one */
-#define start r7
-#define mod8 r8
-#define dbuf r15:14
-#define dcmp r13:12
-
-/*
- * The vector mask version of this turned out *really* badly.
- * The hardware loop version also turned out *really* badly.
- * Seems straight pointer arithmetic basically wins here.
- */
-
-#define fname __strnlen_user
-
- .text
- .global fname
- .type fname, @function
- .p2align 5 /* why? */
-fname:
- {
- mod8 = and(isrc,#7);
- end = add(isrc,max);
- start = isrc;
- }
- {
- P0 = cmp.eq(mod8,#0);
- mod8 = and(end,#7);
- dcmp = #0;
- if (P0.new) jump:t dw_loop; /* fire up the oven */
- }
-
-alignment_loop:
-fail_1: {
- tmp1 = memb(start++#1);
- }
- {
- P0 = cmp.eq(tmp1,#0);
- if (P0.new) jump:nt exit_found;
- P1 = cmp.gtu(end,start);
- mod8 = and(start,#7);
- }
- {
- if (!P1) jump exit_error; /* hit the end */
- P0 = cmp.eq(mod8,#0);
- }
- {
- if (!P0) jump alignment_loop;
- }
-
-
-
-dw_loop:
-fail_2: {
- dbuf = memd(start);
- obo = add(start,#1);
- }
- {
- P0 = vcmpb.eq(dbuf,dcmp);
- }
- {
- tmp1 = P0;
- P0 = cmp.gtu(end,start);
- }
- {
- tmp1 = ct0(tmp1);
- mod8 = and(end,#7);
- if (!P0) jump end_check;
- }
- {
- P0 = cmp.eq(tmp1,#32);
- if (!P0.new) jump:nt exit_found;
- if (!P0.new) start = add(obo,tmp1);
- }
- {
- start = add(start,#8);
- jump dw_loop;
- } /* might be nice to combine these jumps... */
-
-
-end_check:
- {
- P0 = cmp.gt(tmp1,mod8);
- if (P0.new) jump:nt exit_error; /* neverfound! */
- start = add(obo,tmp1);
- }
-
-exit_found:
- {
- R0 = sub(start,isrc);
- jumpr R31;
- }
-
-exit_error:
- {
- R0 = add(max,#1);
- jumpr R31;
- }
-
- /* Uh, what does the "fixup" return here? */
- .falign
-fix_1:
- {
- R0 = #0;
- jumpr R31;
- }
-
- .size fname,.-fname
-
-
-.section __ex_table,"a"
-.long fail_1,fix_1
-.long fail_2,fix_1
-.previous
diff --git a/arch/ia64/Kbuild b/arch/ia64/Kbuild
index a4e40e534e6a..e77cc76d228c 100644
--- a/arch/ia64/Kbuild
+++ b/arch/ia64/Kbuild
@@ -1 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-y += kernel/ mm/
+obj-$(CONFIG_IA64_SGI_UV) += uv/
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 4993c7ac7ff6..045792cde481 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -9,6 +9,8 @@ menu "Processor type and features"
config IA64
bool
select ARCH_HAS_DMA_MARK_CLEAN
+ select ARCH_HAS_STRNCPY_FROM_USER
+ select ARCH_HAS_STRNLEN_USER
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
select ACPI
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 467b7e7f967c..7e548c654a29 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -47,8 +47,6 @@ KBUILD_CFLAGS += $(cflags-y)
head-y := arch/ia64/kernel/head.o
libs-y += arch/ia64/lib/
-core-y += arch/ia64/kernel/ arch/ia64/mm/
-core-$(CONFIG_IA64_SGI_UV) += arch/ia64/uv/
drivers-y += arch/ia64/pci/ arch/ia64/hp/common/
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 9148ddbf02e5..8ad6946521d8 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1459,7 +1459,7 @@ static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
sglist->dma_address = sba_map_page(dev, sg_page(sglist),
sglist->offset, sglist->length, dir, attrs);
if (dma_mapping_error(dev, sglist->dma_address))
- return 0;
+ return -EIO;
return 1;
}
@@ -1486,7 +1486,7 @@ static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
if (coalesced < 0) {
sba_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
- return 0;
+ return -ENOMEM;
}
/*
diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/meminit.h
index 6c47a239fc26..f1d5bf2ba847 100644
--- a/arch/ia64/include/asm/meminit.h
+++ b/arch/ia64/include/asm/meminit.h
@@ -29,7 +29,6 @@ struct rsvd_region {
};
extern struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
-extern int num_rsvd_regions;
extern void find_memory (void);
extern void reserve_memory (void);
@@ -40,7 +39,6 @@ extern unsigned long efi_memmap_init(u64 *s, u64 *e);
extern int find_max_min_low_pfn (u64, u64, void *);
extern unsigned long vmcore_find_descriptor_size(unsigned long address);
-extern int reserve_elfcorehdr(u64 *start, u64 *end);
/*
* For rounding an address to the next IA64_GRANULE_SIZE or order
diff --git a/arch/ia64/include/uapi/asm/cmpxchg.h b/arch/ia64/include/uapi/asm/cmpxchg.h
index 926c6cb1e029..2c2f3cfeaa77 100644
--- a/arch/ia64/include/uapi/asm/cmpxchg.h
+++ b/arch/ia64/include/uapi/asm/cmpxchg.h
@@ -143,9 +143,9 @@ extern long ia64_cmpxchg_called_with_bad_pointer(void);
do { \
if (_cmpxchg_bugcheck_count-- <= 0) { \
void *ip; \
- extern int printk(const char *fmt, ...); \
+ extern int _printk(const char *fmt, ...); \
ip = (void *) ia64_getreg(_IA64_REG_IP); \
- printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
+ _printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
break; \
} \
} while (0)
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index e2af6b172200..96d13cb7c19f 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -906,6 +906,6 @@ EXPORT_SYMBOL(acpi_unregister_ioapic);
/*
* acpi_suspend_lowlevel() - save kernel state and suspend.
*
- * TBD when when IA64 starts to support suspend...
+ * TBD when IA64 starts to support suspend...
*/
int acpi_suspend_lowlevel(void) { return 0; }
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index dd595fbd8006..31fb84de2d21 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -131,7 +131,7 @@ unsigned long ia64_cache_stride_shift = ~0;
* We use a special marker for the end of memory and it uses the extra (+1) slot
*/
struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1] __initdata;
-int num_rsvd_regions __initdata;
+static int num_rsvd_regions __initdata;
/*
@@ -325,6 +325,31 @@ static inline void __init setup_crashkernel(unsigned long total, int *n)
{}
#endif
+#ifdef CONFIG_CRASH_DUMP
+static int __init reserve_elfcorehdr(u64 *start, u64 *end)
+{
+ u64 length;
+
+ /* We get the address using the kernel command line,
+ * but the size is extracted from the EFI tables.
+ * Both address and size are required for reservation
+ * to work properly.
+ */
+
+ if (!is_vmcore_usable())
+ return -EINVAL;
+
+ if ((length = vmcore_find_descriptor_size(elfcorehdr_addr)) == 0) {
+ vmcore_unusable();
+ return -EINVAL;
+ }
+
+ *start = (unsigned long)__va(elfcorehdr_addr);
+ *end = *start + length;
+ return 0;
+}
+#endif /* CONFIG_CRASH_DUMP */
+
/**
* reserve_memory - setup reserved memory areas
*
@@ -522,32 +547,6 @@ static __init int setup_nomca(char *s)
}
early_param("nomca", setup_nomca);
-#ifdef CONFIG_CRASH_DUMP
-int __init reserve_elfcorehdr(u64 *start, u64 *end)
-{
- u64 length;
-
- /* We get the address using the kernel command line,
- * but the size is extracted from the EFI tables.
- * Both address and size are required for reservation
- * to work properly.
- */
-
- if (!is_vmcore_usable())
- return -EINVAL;
-
- if ((length = vmcore_find_descriptor_size(elfcorehdr_addr)) == 0) {
- vmcore_unusable();
- return -EINVAL;
- }
-
- *start = (unsigned long)__va(elfcorehdr_addr);
- *end = *start + length;
- return 0;
-}
-
-#endif /* CONFIG_PROC_VMCORE */
-
void __init
setup_arch (char **cmdline_p)
{
diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl
index 6d07742c57b8..6fea1844fb95 100644
--- a/arch/ia64/kernel/syscalls/syscall.tbl
+++ b/arch/ia64/kernel/syscalls/syscall.tbl
@@ -123,7 +123,7 @@
# 1135 was get_kernel_syms
# 1136 was query_module
113 common quotactl sys_quotactl
-114 common bdflush sys_bdflush
+114 common bdflush sys_ni_syscall
115 common sysfs sys_sysfs
116 common personality sys_personality
117 common afs_syscall sys_ni_syscall
@@ -367,3 +367,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index d632a1d576f9..774c35f47eea 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -16,8 +16,6 @@ config M68K
select GENERIC_CPU_DEVICES
select GENERIC_IOMAP
select GENERIC_IRQ_SHOW
- select GENERIC_STRNCPY_FROM_USER if MMU
- select GENERIC_STRNLEN_USER if MMU
select HAVE_AOUT if MMU
select HAVE_ASM_MODVERSIONS
select HAVE_DEBUG_BUGVERBOSE
diff --git a/arch/m68k/Kconfig.bus b/arch/m68k/Kconfig.bus
index f1be832e2b74..d1e93a39cd3b 100644
--- a/arch/m68k/Kconfig.bus
+++ b/arch/m68k/Kconfig.bus
@@ -63,7 +63,7 @@ source "drivers/zorro/Kconfig"
endif
-if !MMU
+if COLDFIRE
config ISA_DMA_API
def_bool !M5272
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index 6a07a6817885..36fa0c3ef129 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -465,6 +465,7 @@ config RAMKERNEL
config ROMKERNEL
bool "ROM"
+ depends on ROM
help
The kernel will be resident in FLASH/ROM when running. This is
often referred to as Execute-in-Place (XIP), since the kernel
diff --git a/arch/m68k/coldfire/clk.c b/arch/m68k/coldfire/clk.c
index 2ed841e94111..d03b6c4aa86b 100644
--- a/arch/m68k/coldfire/clk.c
+++ b/arch/m68k/coldfire/clk.c
@@ -78,7 +78,7 @@ int clk_enable(struct clk *clk)
unsigned long flags;
if (!clk)
- return -EINVAL;
+ return 0;
spin_lock_irqsave(&clk_lock, flags);
if ((clk->enabled++ == 0) && clk->clk_ops)
diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c
index 59f7dfe50a4d..0386252e9d04 100644
--- a/arch/m68k/coldfire/device.c
+++ b/arch/m68k/coldfire/device.c
@@ -581,6 +581,47 @@ static struct platform_device mcf_esdhc = {
};
#endif /* MCFSDHC_BASE */
+#if IS_ENABLED(CONFIG_CAN_FLEXCAN)
+
+#include <linux/can/platform/flexcan.h>
+
+static struct flexcan_platform_data mcf5441x_flexcan_info = {
+ .clk_src = 1,
+ .clock_frequency = 120000000,
+};
+
+static struct resource mcf5441x_flexcan0_resource[] = {
+ {
+ .start = MCFFLEXCAN_BASE0,
+ .end = MCFFLEXCAN_BASE0 + MCFFLEXCAN_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MCF_IRQ_IFL0,
+ .end = MCF_IRQ_IFL0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MCF_IRQ_BOFF0,
+ .end = MCF_IRQ_BOFF0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MCF_IRQ_ERR0,
+ .end = MCF_IRQ_ERR0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mcf_flexcan0 = {
+ .name = "flexcan-mcf5441x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mcf5441x_flexcan0_resource),
+ .resource = mcf5441x_flexcan0_resource,
+ .dev.platform_data = &mcf5441x_flexcan_info,
+};
+#endif /* IS_ENABLED(CONFIG_CAN_FLEXCAN) */
+
static struct platform_device *mcf_devices[] __initdata = {
&mcf_uart,
#if IS_ENABLED(CONFIG_FEC)
@@ -616,6 +657,9 @@ static struct platform_device *mcf_devices[] __initdata = {
#ifdef MCFSDHC_BASE
&mcf_esdhc,
#endif
+#if IS_ENABLED(CONFIG_CAN_FLEXCAN)
+ &mcf_flexcan0,
+#endif
};
/*
diff --git a/arch/m68k/coldfire/m5441x.c b/arch/m68k/coldfire/m5441x.c
index ce14693d18b6..39855044090d 100644
--- a/arch/m68k/coldfire/m5441x.c
+++ b/arch/m68k/coldfire/m5441x.c
@@ -19,8 +19,8 @@
#include <asm/mcfclk.h>
DEFINE_CLK(0, "flexbus", 2, MCF_CLK);
-DEFINE_CLK(0, "mcfcan.0", 8, MCF_CLK);
-DEFINE_CLK(0, "mcfcan.1", 9, MCF_CLK);
+DEFINE_CLK(0, "flexcan.0", 8, MCF_CLK);
+DEFINE_CLK(0, "flexcan.1", 9, MCF_CLK);
DEFINE_CLK(0, "imx1-i2c.1", 14, MCF_CLK);
DEFINE_CLK(0, "mcfdspi.1", 15, MCF_CLK);
DEFINE_CLK(0, "edma", 17, MCF_CLK);
@@ -142,6 +142,8 @@ static struct clk_lookup m5411x_clk_lookup[] = {
static struct clk * const enable_clks[] __initconst = {
/* make sure these clocks are enabled */
+ &__clk_0_8, /* flexcan.0 */
+ &__clk_0_9, /* flexcan.1 */
&__clk_0_15, /* dspi.1 */
&__clk_0_17, /* eDMA */
&__clk_0_18, /* intc0 */
@@ -162,8 +164,6 @@ static struct clk * const enable_clks[] __initconst = {
&__clk_1_37, /* gpio */
};
static struct clk * const disable_clks[] __initconst = {
- &__clk_0_8, /* can.0 */
- &__clk_0_9, /* can.1 */
&__clk_0_14, /* i2c.1 */
&__clk_0_22, /* i2c.0 */
&__clk_0_23, /* dspi.0 */
diff --git a/arch/m68k/coldfire/stmark2.c b/arch/m68k/coldfire/stmark2.c
index 8b5af9c83244..036a6ae5f599 100644
--- a/arch/m68k/coldfire/stmark2.c
+++ b/arch/m68k/coldfire/stmark2.c
@@ -111,7 +111,9 @@ static int __init init_stmark2(void)
__raw_writeb(0x00, MCFGPIO_PAR_BE);
__raw_writeb(0x00, MCFGPIO_PAR_FBCTL);
__raw_writeb(0x00, MCFGPIO_PAR_CS);
- __raw_writeb(0x00, MCFGPIO_PAR_CANI2C);
+
+ /* CAN pads */
+ __raw_writeb(0x50, MCFGPIO_PAR_CANI2C);
platform_add_devices(stmark2_devices, ARRAY_SIZE(stmark2_devices));
@@ -121,4 +123,4 @@ static int __init init_stmark2(void)
return 0;
}
-late_initcall(init_stmark2);
+device_initcall(init_stmark2);
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
index 92636c89d65b..557d60867f98 100644
--- a/arch/m68k/emu/nfcon.c
+++ b/arch/m68k/emu/nfcon.c
@@ -120,35 +120,37 @@ early_param("debug", nf_debug_setup);
static int __init nfcon_init(void)
{
+ struct tty_driver *driver;
int res;
stderr_id = nf_get_id("NF_STDERR");
if (!stderr_id)
return -ENODEV;
- nfcon_tty_driver = alloc_tty_driver(1);
- if (!nfcon_tty_driver)
- return -ENOMEM;
+ driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
tty_port_init(&nfcon_tty_port);
- nfcon_tty_driver->driver_name = "nfcon";
- nfcon_tty_driver->name = "nfcon";
- nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
- nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY;
- nfcon_tty_driver->init_termios = tty_std_termios;
- nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
+ driver->driver_name = "nfcon";
+ driver->name = "nfcon";
+ driver->type = TTY_DRIVER_TYPE_SYSTEM;
+ driver->subtype = SYSTEM_TYPE_TTY;
+ driver->init_termios = tty_std_termios;
- tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
- tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0);
- res = tty_register_driver(nfcon_tty_driver);
+ tty_set_operations(driver, &nfcon_tty_ops);
+ tty_port_link_device(&nfcon_tty_port, driver, 0);
+ res = tty_register_driver(driver);
if (res) {
pr_err("failed to register nfcon tty driver\n");
- put_tty_driver(nfcon_tty_driver);
+ tty_driver_kref_put(driver);
tty_port_destroy(&nfcon_tty_port);
return res;
}
+ nfcon_tty_driver = driver;
+
if (!(nf_console.flags & CON_ENABLED))
register_console(&nf_console);
@@ -159,7 +161,7 @@ static void __exit nfcon_exit(void)
{
unregister_console(&nf_console);
tty_unregister_driver(nfcon_tty_driver);
- put_tty_driver(nfcon_tty_driver);
+ tty_driver_kref_put(nfcon_tty_driver);
tty_port_destroy(&nfcon_tty_port);
}
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S
index a8f41615d94a..439395aa6fb4 100644
--- a/arch/m68k/fpsp040/skeleton.S
+++ b/arch/m68k/fpsp040/skeleton.S
@@ -502,7 +502,8 @@ in_ea:
.section .fixup,#alloc,#execinstr
.even
1:
- jbra fpsp040_die
+ jbsr fpsp040_die
+ jbra .Lnotkern
.section __ex_table,#alloc
.align 4
diff --git a/arch/m68k/include/asm/m5441xsim.h b/arch/m68k/include/asm/m5441xsim.h
index e091e36d3464..f48cf63bd782 100644
--- a/arch/m68k/include/asm/m5441xsim.h
+++ b/arch/m68k/include/asm/m5441xsim.h
@@ -73,6 +73,12 @@
#define MCFINT0_FECENTC1 55
/* on interrupt controller 1 */
+#define MCFINT1_FLEXCAN0_IFL 0
+#define MCFINT1_FLEXCAN0_BOFF 1
+#define MCFINT1_FLEXCAN0_ERR 3
+#define MCFINT1_FLEXCAN1_IFL 4
+#define MCFINT1_FLEXCAN1_BOFF 5
+#define MCFINT1_FLEXCAN1_ERR 7
#define MCFINT1_UART4 48
#define MCFINT1_UART5 49
#define MCFINT1_UART6 50
@@ -314,4 +320,17 @@
#define MCF_IRQ_SDHC (MCFINT2_VECBASE + MCFINT2_SDHC)
#define MCFSDHC_CLK (MCFSDHC_BASE + 0x2c)
+/*
+ * Flexcan module
+ */
+#define MCFFLEXCAN_BASE0 0xfc020000
+#define MCFFLEXCAN_BASE1 0xfc024000
+#define MCFFLEXCAN_SIZE 0x4000
+#define MCF_IRQ_IFL0 (MCFINT1_VECBASE + MCFINT1_FLEXCAN0_IFL)
+#define MCF_IRQ_BOFF0 (MCFINT1_VECBASE + MCFINT1_FLEXCAN0_BOFF)
+#define MCF_IRQ_ERR0 (MCFINT1_VECBASE + MCFINT1_FLEXCAN0_ERR)
+#define MCF_IRQ_IFL1 (MCFINT1_VECBASE + MCFINT1_FLEXCAN1_IFL)
+#define MCF_IRQ_BOFF1 (MCFINT1_VECBASE + MCFINT1_FLEXCAN1_BOFF)
+#define MCF_IRQ_ERR1 (MCFINT1_VECBASE + MCFINT1_FLEXCAN1_ERR)
+
#endif /* m5441xsim_h */
diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
index 541bc1b3a8f9..7976dff8f879 100644
--- a/arch/m68k/kernel/syscalls/syscall.tbl
+++ b/arch/m68k/kernel/syscalls/syscall.tbl
@@ -141,7 +141,7 @@
131 common quotactl sys_quotactl
132 common getpgid sys_getpgid
133 common fchdir sys_fchdir
-134 common bdflush sys_bdflush
+134 common bdflush sys_ni_syscall
135 common sysfs sys_sysfs
136 common personality sys_personality
# 137 was afs_syscall
@@ -446,3 +446,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 9e1261462bcc..5b19fcdcd69e 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -1150,7 +1150,7 @@ asmlinkage void set_esp0(unsigned long ssp)
*/
asmlinkage void fpsp040_die(void)
{
- do_exit(SIGSEGV);
+ force_sigsegv(SIGSEGV);
}
#ifdef CONFIG_M68KFPU_EMU
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 14a67a42fcae..59798e43cdb0 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -44,6 +44,7 @@ config MICROBLAZE
select SPARSE_IRQ
select SET_FS
select ZONE_DMA
+ select TRACE_IRQFLAGS_SUPPORT
# Endianness selection
choice
diff --git a/arch/microblaze/Kconfig.debug b/arch/microblaze/Kconfig.debug
index 865527ac332a..a4e40e534e6a 100644
--- a/arch/microblaze/Kconfig.debug
+++ b/arch/microblaze/Kconfig.debug
@@ -1,6 +1 @@
# SPDX-License-Identifier: GPL-2.0-only
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/kconfig-language.rst.
-
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h
index ce550978f4fc..4b8b2fa78fc5 100644
--- a/arch/microblaze/include/asm/page.h
+++ b/arch/microblaze/include/asm/page.h
@@ -112,8 +112,7 @@ extern int page_is_ram(unsigned long pfn);
# define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
# define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT)
-# define pfn_valid(pfn) ((pfn) < (max_mapnr + ARCH_PFN_OFFSET))
-
+# define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < (max_mapnr + ARCH_PFN_OFFSET))
# endif /* __ASSEMBLY__ */
#define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr)))
diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h
index 71cd547655d9..c136a01e467e 100644
--- a/arch/microblaze/include/asm/pgtable.h
+++ b/arch/microblaze/include/asm/pgtable.h
@@ -443,8 +443,6 @@ extern int mem_init_done;
asmlinkage void __init mmu_init(void);
-void __init *early_get_page(void);
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index c44b59470e45..d2a8ef9f8978 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -35,6 +35,7 @@
# define get_fs() (current_thread_info()->addr_limit)
# define set_fs(val) (current_thread_info()->addr_limit = (val))
+# define user_addr_max() get_fs().seg
# define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
@@ -296,28 +297,14 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
/*
* Copy a null terminated string from userspace.
*/
-extern int __strncpy_user(char *to, const char __user *from, int len);
-
-static inline long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
- if (!access_ok(src, 1))
- return -EFAULT;
- return __strncpy_user(dst, src, count);
-}
+__must_check long strncpy_from_user(char *dst, const char __user *src,
+ long count);
/*
* Return the size of a string (including the ending 0)
*
* Return 0 on exception, a value greater than N if too long
*/
-extern int __strnlen_user(const char __user *sstr, int len);
-
-static inline long strnlen_user(const char __user *src, long n)
-{
- if (!access_ok(src, 1))
- return 0;
- return __strnlen_user(src, n);
-}
+__must_check long strnlen_user(const char __user *sstr, long len);
#endif /* _ASM_MICROBLAZE_UACCESS_H */
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
index 303aaf13573b..c892e173ec99 100644
--- a/arch/microblaze/kernel/microblaze_ksyms.c
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
@@ -26,7 +26,6 @@ EXPORT_SYMBOL(_mcount);
* Assembly functions that may be used (directly or indirectly) by modules
*/
EXPORT_SYMBOL(__copy_tofrom_user);
-EXPORT_SYMBOL(__strncpy_user);
#ifdef CONFIG_OPT_LIB_ASM
EXPORT_SYMBOL(memcpy);
diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
index a176faca2927..6b0e11362bd2 100644
--- a/arch/microblaze/kernel/syscalls/syscall.tbl
+++ b/arch/microblaze/kernel/syscalls/syscall.tbl
@@ -141,7 +141,7 @@
131 common quotactl sys_quotactl
132 common getpgid sys_getpgid
133 common fchdir sys_fchdir
-134 common bdflush sys_bdflush
+134 common bdflush sys_ni_syscall
135 common sysfs sys_sysfs
136 common personality sys_personality
137 common afs_syscall sys_ni_syscall
@@ -452,3 +452,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/microblaze/lib/uaccess_old.S b/arch/microblaze/lib/uaccess_old.S
index eca290090038..dd5f3bfbc2c5 100644
--- a/arch/microblaze/lib/uaccess_old.S
+++ b/arch/microblaze/lib/uaccess_old.S
@@ -12,96 +12,6 @@
#include <linux/linkage.h>
#include <asm/page.h>
-/*
- * int __strncpy_user(char *to, char *from, int len);
- *
- * Returns:
- * -EFAULT for an exception
- * len if we hit the buffer limit
- * bytes copied
- */
-
- .text
-.globl __strncpy_user;
-.type __strncpy_user, @function
-.align 4;
-__strncpy_user:
-
- /*
- * r5 - to
- * r6 - from
- * r7 - len
- * r3 - temp count
- * r4 - temp val
- */
- beqid r7,3f
- addik r3,r7,0 /* temp_count = len */
-1:
- lbu r4,r6,r0
- beqid r4,2f
- sb r4,r5,r0
-
- addik r5,r5,1
- addik r6,r6,1 /* delay slot */
-
- addik r3,r3,-1
- bnei r3,1b /* break on len */
-2:
- rsubk r3,r3,r7 /* temp_count = len - temp_count */
-3:
- rtsd r15,8
- nop
- .size __strncpy_user, . - __strncpy_user
-
- .section .fixup, "ax"
- .align 2
-4:
- brid 3b
- addik r3,r0, -EFAULT
-
- .section __ex_table, "a"
- .word 1b,4b
-
-/*
- * int __strnlen_user(char __user *str, int maxlen);
- *
- * Returns:
- * 0 on error
- * maxlen + 1 if no NUL byte found within maxlen bytes
- * size of the string (including NUL byte)
- */
-
- .text
-.globl __strnlen_user;
-.type __strnlen_user, @function
-.align 4;
-__strnlen_user:
- beqid r6,3f
- addik r3,r6,0
-1:
- lbu r4,r5,r0
- beqid r4,2f /* break on NUL */
- addik r3,r3,-1 /* delay slot */
-
- bneid r3,1b
- addik r5,r5,1 /* delay slot */
-
- addik r3,r3,-1 /* for break on len */
-2:
- rsubk r3,r3,r6
-3:
- rtsd r15,8
- nop
- .size __strnlen_user, . - __strnlen_user
-
- .section .fixup,"ax"
-4:
- brid 3b
- addk r3,r0,r0
-
- .section __ex_table,"a"
- .word 1b,4b
-
/* Loop unrolling for __copy_tofrom_user */
#define COPY(offset) \
1: lwi r4 , r6, 0x0000 + offset; \
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
index ab55c70380a5..952f35b335b2 100644
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -265,18 +265,6 @@ asmlinkage void __init mmu_init(void)
dma_contiguous_reserve(memory_start + lowmem_size - 1);
}
-/* This is only called until mem_init is done. */
-void __init *early_get_page(void)
-{
- /*
- * Mem start + kernel_tlb -> here is limit
- * because of mem mapping from head.S
- */
- return memblock_alloc_try_nid_raw(PAGE_SIZE, PAGE_SIZE,
- MEMBLOCK_LOW_LIMIT, memory_start + kernel_tlb,
- NUMA_NO_NODE);
-}
-
void * __ref zalloc_maybe_bootmem(size_t size, gfp_t mask)
{
void *p;
diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c
index 38ccb909bc9d..c1833b159d3b 100644
--- a/arch/microblaze/mm/pgtable.c
+++ b/arch/microblaze/mm/pgtable.c
@@ -33,6 +33,7 @@
#include <linux/init.h>
#include <linux/mm_types.h>
#include <linux/pgtable.h>
+#include <linux/memblock.h>
#include <asm/pgalloc.h>
#include <linux/io.h>
@@ -242,15 +243,13 @@ unsigned long iopa(unsigned long addr)
__ref pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
{
- pte_t *pte;
- if (mem_init_done) {
- pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
- } else {
- pte = (pte_t *)early_get_page();
- if (pte)
- clear_page(pte);
- }
- return pte;
+ if (mem_init_done)
+ return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+ else
+ return memblock_alloc_try_nid(PAGE_SIZE, PAGE_SIZE,
+ MEMBLOCK_LOW_LIMIT,
+ memory_start + kernel_tlb,
+ NUMA_NO_NODE);
}
void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index e4f6e49417a9..584081df89c2 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -21,7 +21,6 @@ platform-$(CONFIG_MIPS_MALTA) += mti-malta/
platform-$(CONFIG_MACH_NINTENDO64) += n64/
platform-$(CONFIG_NLM_COMMON) += netlogic/
platform-$(CONFIG_PIC32MZDA) += pic32/
-platform-$(CONFIG_MACH_PISTACHIO) += pistachio/
platform-$(CONFIG_RALINK) += ralink/
platform-$(CONFIG_MIKROTIK_RB532) += rb532/
platform-$(CONFIG_SGI_IP22) += sgi-ip22/
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 6dfb27d531dd..771ca53af06d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -9,6 +9,8 @@ config MIPS
select ARCH_HAS_KCOV
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if !EVA
select ARCH_HAS_PTE_SPECIAL if !(32BIT && CPU_HAS_RIXI)
+ select ARCH_HAS_STRNCPY_FROM_USER
+ select ARCH_HAS_STRNLEN_USER
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UBSAN_SANITIZE_ALL
select ARCH_HAS_GCOV_PROFILE_ALL
@@ -96,6 +98,7 @@ config MIPS
select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
select RTC_LIB
select SYSCTL_EXCEPTION_TRACE
+ select TRACE_IRQFLAGS_SUPPORT
select VIRT_TO_BUS
select ARCH_HAS_ELFCORE_COMPAT
@@ -512,35 +515,6 @@ config MACH_LOONGSON64
and Loongson-2F which will be removed), developed by the Institute
of Computing Technology (ICT), Chinese Academy of Sciences (CAS).
-config MACH_PISTACHIO
- bool "IMG Pistachio SoC based boards"
- select BOOT_ELF32
- select BOOT_RAW
- select CEVT_R4K
- select CLKSRC_MIPS_GIC
- select COMMON_CLK
- select CSRC_R4K
- select DMA_NONCOHERENT
- select GPIOLIB
- select IRQ_MIPS_CPU
- select MFD_SYSCON
- select MIPS_CPU_SCACHE
- select MIPS_GIC
- select PINCTRL
- select REGULATOR
- select SYS_HAS_CPU_MIPS32_R2
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_LITTLE_ENDIAN
- select SYS_SUPPORTS_MIPS_CPS
- select SYS_SUPPORTS_MULTITHREADING
- select SYS_SUPPORTS_RELOCATABLE
- select SYS_SUPPORTS_ZBOOT
- select SYS_HAS_EARLY_PRINTK
- select USE_GENERIC_EARLY_PRINTK_8250
- select USE_OF
- help
- This enables support for the IMG Pistachio SoC platform.
-
config MIPS_MALTA
bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC
@@ -1087,7 +1061,6 @@ source "arch/mips/ingenic/Kconfig"
source "arch/mips/jazz/Kconfig"
source "arch/mips/lantiq/Kconfig"
source "arch/mips/pic32/Kconfig"
-source "arch/mips/pistachio/Kconfig"
source "arch/mips/ralink/Kconfig"
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 43dbf5930796..f4ae7900fcd3 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -1,9 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-config TRACE_IRQFLAGS_SUPPORT
- bool
- default y
-
config EARLY_PRINTK
bool "Early printk" if EXPERT
depends on SYS_HAS_EARLY_PRINTK
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 653befc1b176..ea3cd080a1c7 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -254,7 +254,7 @@ endif
#
# Board-dependent options and extra files
#
-include arch/mips/Kbuild.platforms
+include $(srctree)/arch/mips/Kbuild.platforms
ifdef CONFIG_PHYSICAL_START
load-y = $(CONFIG_PHYSICAL_START)
@@ -560,6 +560,9 @@ sead3micro_defconfig-y := micro32r2el_defconfig BOARDS=sead-3
legacy_defconfigs += xilfpga_defconfig
xilfpga_defconfig-y := 32r2el_defconfig BOARDS=xilfpga
+legacy_defconfigs += pistachio_defconfig
+pistachio_defconfig-y := 32r2el_defconfig BOARDS=marduk
+
.PHONY: $(legacy_defconfigs)
$(legacy_defconfigs):
$(Q)$(MAKE) -f $(srctree)/Makefile $($@-y)
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
index 421d651433b6..1864eb935ca5 100644
--- a/arch/mips/alchemy/devboards/db1200.c
+++ b/arch/mips/alchemy/devboards/db1200.c
@@ -835,7 +835,7 @@ int __init db1200_dev_setup(void)
if (!IS_ERR(c)) {
pfc = clk_round_rate(c, 50000000);
if ((pfc < 1) || (abs(50000000 - pfc) > 2500000))
- pr_warn("DB1200: cant get I2C close to 50MHz\n");
+ pr_warn("DB1200: can't get I2C close to 50MHz\n");
else
clk_set_rate(c, pfc);
clk_prepare_enable(c);
diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile
index 60bd7d2a9ad8..be96d35eb582 100644
--- a/arch/mips/boot/dts/Makefile
+++ b/arch/mips/boot/dts/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
subdir-$(CONFIG_BMIPS_GENERIC) += brcm
subdir-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon
-subdir-$(CONFIG_MACH_PISTACHIO) += img
+subdir-$(CONFIG_FIT_IMAGE_FDT_MARDUK) += img
subdir-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += img
subdir-$(CONFIG_MACH_INGENIC) += ingenic
subdir-$(CONFIG_LANTIQ) += lantiq
diff --git a/arch/mips/boot/dts/img/Makefile b/arch/mips/boot/dts/img/Makefile
index 441a3c16efb0..ebb47490b04b 100644
--- a/arch/mips/boot/dts/img/Makefile
+++ b/arch/mips/boot/dts/img/Makefile
@@ -1,5 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += boston.dtb
-dtb-$(CONFIG_MACH_PISTACHIO) += pistachio_marduk.dtb
-obj-$(CONFIG_MACH_PISTACHIO) += pistachio_marduk.dtb.o
+dtb-$(CONFIG_FIT_IMAGE_FDT_MARDUK) += pistachio_marduk.dtb
diff --git a/arch/mips/boot/dts/img/pistachio.dtsi b/arch/mips/boot/dts/img/pistachio.dtsi
index dc3b7909de73..b1db8b8f446f 100644
--- a/arch/mips/boot/dts/img/pistachio.dtsi
+++ b/arch/mips/boot/dts/img/pistachio.dtsi
@@ -900,6 +900,16 @@
};
};
+ cpc: cpc@1bde0000 {
+ compatible = "mti,mips-cpc";
+ reg = <0x1bde0000 0x10000>;
+ };
+
+ cdmm: cdmm@1bdf0000 {
+ compatible = "mti,mips-cdmm";
+ reg = <0x1bdf0000 0x10000>;
+ };
+
usb_phy: usb-phy {
compatible = "img,pistachio-usb-phy";
clocks = <&clk_core CLK_USB_PHY>;
diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index 535a98284dcb..e51db651af13 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -150,36 +150,47 @@
port0: port@0 {
reg = <0>;
+ status = "disabled";
};
port1: port@1 {
reg = <1>;
+ status = "disabled";
};
port2: port@2 {
reg = <2>;
+ status = "disabled";
};
port3: port@3 {
reg = <3>;
+ status = "disabled";
};
port4: port@4 {
reg = <4>;
+ status = "disabled";
};
port5: port@5 {
reg = <5>;
+ status = "disabled";
};
port6: port@6 {
reg = <6>;
+ status = "disabled";
};
port7: port@7 {
reg = <7>;
+ status = "disabled";
};
port8: port@8 {
reg = <8>;
+ status = "disabled";
};
port9: port@9 {
reg = <9>;
+ status = "disabled";
};
port10: port@10 {
reg = <10>;
+ status = "disabled";
};
};
};
diff --git a/arch/mips/boot/dts/mscc/ocelot_pcb120.dts b/arch/mips/boot/dts/mscc/ocelot_pcb120.dts
index 897de5025d7f..bd240690cb37 100644
--- a/arch/mips/boot/dts/mscc/ocelot_pcb120.dts
+++ b/arch/mips/boot/dts/mscc/ocelot_pcb120.dts
@@ -69,40 +69,52 @@
};
&port0 {
+ status = "okay";
phy-handle = <&phy0>;
+ phy-mode = "internal";
};
&port1 {
+ status = "okay";
phy-handle = <&phy1>;
+ phy-mode = "internal";
};
&port2 {
+ status = "okay";
phy-handle = <&phy2>;
+ phy-mode = "internal";
};
&port3 {
+ status = "okay";
phy-handle = <&phy3>;
+ phy-mode = "internal";
};
&port4 {
+ status = "okay";
phy-handle = <&phy7>;
phy-mode = "sgmii";
phys = <&serdes 4 SERDES1G(2)>;
};
&port5 {
+ status = "okay";
phy-handle = <&phy4>;
phy-mode = "sgmii";
phys = <&serdes 5 SERDES1G(5)>;
};
&port6 {
+ status = "okay";
phy-handle = <&phy6>;
phy-mode = "sgmii";
phys = <&serdes 6 SERDES1G(3)>;
};
&port9 {
+ status = "okay";
phy-handle = <&phy5>;
phy-mode = "sgmii";
phys = <&serdes 9 SERDES1G(4)>;
diff --git a/arch/mips/boot/dts/mscc/ocelot_pcb123.dts b/arch/mips/boot/dts/mscc/ocelot_pcb123.dts
index ef852f382da8..0185045c7630 100644
--- a/arch/mips/boot/dts/mscc/ocelot_pcb123.dts
+++ b/arch/mips/boot/dts/mscc/ocelot_pcb123.dts
@@ -47,17 +47,25 @@
};
&port0 {
+ status = "okay";
phy-handle = <&phy0>;
+ phy-mode = "internal";
};
&port1 {
+ status = "okay";
phy-handle = <&phy1>;
+ phy-mode = "internal";
};
&port2 {
+ status = "okay";
phy-handle = <&phy2>;
+ phy-mode = "internal";
};
&port3 {
+ status = "okay";
phy-handle = <&phy3>;
+ phy-mode = "internal";
};
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
index e794b2d53adf..b63ad5d42cc7 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
@@ -44,7 +44,7 @@ static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
/* See header file for descriptions of functions */
-/**
+/*
* This macro returns a member of the
* cvmx_bootmem_named_block_desc_t structure. These members can't
* be directly addressed as they might be in memory not directly
@@ -60,7 +60,7 @@ static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
offsetof(struct cvmx_bootmem_named_block_desc, field), \
sizeof_field(struct cvmx_bootmem_named_block_desc, field))
-/**
+/*
* This function is the implementation of the get macros defined
* for individual structure members. The argument are generated
* by the macros inorder to read only the needed memory.
@@ -115,7 +115,7 @@ static uint64_t cvmx_bootmem_phy_get_next(uint64_t addr)
return cvmx_read64_uint64((addr + NEXT_OFFSET) | (1ull << 63));
}
-/**
+/*
* Allocate a block of memory from the free list that was
* passed to the application by the bootloader within a specified
* address range. This is an allocate-only algorithm, so
@@ -550,7 +550,7 @@ bootmem_free_done:
}
-/**
+/*
* Finds a named memory block by name.
* Also used for finding an unused entry in the named block table.
*
@@ -657,7 +657,7 @@ struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name)
}
EXPORT_SYMBOL(cvmx_bootmem_find_named_block);
-/**
+/*
* Frees a named block.
*
* @name: name of block to free
diff --git a/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c b/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c
index 3839feba68f2..20189e9ad94d 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c
@@ -42,14 +42,14 @@
#include <asm/octeon/cvmx-pexp-defs.h>
#include <asm/octeon/cvmx-pko-defs.h>
-/**
+/*
* This application uses this pointer to access the global queue
* state. It points to a bootmem named block.
*/
__cvmx_cmd_queue_all_state_t *__cvmx_cmd_queue_state_ptr;
EXPORT_SYMBOL_GPL(__cvmx_cmd_queue_state_ptr);
-/**
+/*
* Initialize the Global queue state pointer.
*
* Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
@@ -57,27 +57,14 @@ EXPORT_SYMBOL_GPL(__cvmx_cmd_queue_state_ptr);
static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void)
{
char *alloc_name = "cvmx_cmd_queues";
-#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
- extern uint64_t octeon_reserve32_memory;
-#endif
if (likely(__cvmx_cmd_queue_state_ptr))
return CVMX_CMD_QUEUE_SUCCESS;
-#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
- if (octeon_reserve32_memory)
- __cvmx_cmd_queue_state_ptr =
- cvmx_bootmem_alloc_named_range(sizeof(*__cvmx_cmd_queue_state_ptr),
- octeon_reserve32_memory,
- octeon_reserve32_memory +
- (CONFIG_CAVIUM_RESERVE32 <<
- 20) - 1, 128, alloc_name);
- else
-#endif
- __cvmx_cmd_queue_state_ptr =
- cvmx_bootmem_alloc_named(sizeof(*__cvmx_cmd_queue_state_ptr),
- 128,
- alloc_name);
+ __cvmx_cmd_queue_state_ptr =
+ cvmx_bootmem_alloc_named(sizeof(*__cvmx_cmd_queue_state_ptr),
+ 128,
+ alloc_name);
if (__cvmx_cmd_queue_state_ptr)
memset(__cvmx_cmd_queue_state_ptr, 0,
sizeof(*__cvmx_cmd_queue_state_ptr));
@@ -97,7 +84,7 @@ static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void)
return CVMX_CMD_QUEUE_SUCCESS;
}
-/**
+/*
* Initialize a command queue for use. The initial FPA buffer is
* allocated and the hardware unit is configured to point to the
* new command queue.
@@ -195,7 +182,7 @@ cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id,
}
}
-/**
+/*
* Shutdown a queue a free it's command buffers to the FPA. The
* hardware connected to the queue must be stopped before this
* function is called.
@@ -231,7 +218,7 @@ cvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id)
return CVMX_CMD_QUEUE_SUCCESS;
}
-/**
+/*
* Return the number of command words pending in the queue. This
* function may be relatively slow for some hardware units.
*
@@ -287,7 +274,7 @@ int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id)
return CVMX_CMD_QUEUE_INVALID_PARAM;
}
-/**
+/*
* Return the command buffer to be written to. The purpose of this
* function is to allow CVMX routine access t othe low level buffer
* for initial hardware setup. User applications should not call this
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
index abd11b7af22f..1daa0c6b6f4e 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -44,7 +44,7 @@
#include <asm/octeon/cvmx-gmxx-defs.h>
#include <asm/octeon/cvmx-asxx-defs.h>
-/**
+/*
* Return the MII PHY address associated with the given IPD
* port. A result of -1 means there isn't a MII capable PHY
* connected to this port. On chips supporting multiple MII
@@ -189,7 +189,7 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
return -1;
}
-/**
+/*
* This function is the board specific method of determining an
* ethernet ports link speed. Most Octeon boards have Marvell PHYs
* and are handled by the fall through case. This function must be
@@ -274,7 +274,7 @@ union cvmx_helper_link_info __cvmx_helper_board_link_get(int ipd_port)
return result;
}
-/**
+/*
* This function is called by cvmx_helper_interface_probe() after it
* determines the number of ports Octeon can support on a specific
* interface. This function is the per board location to override
@@ -320,7 +320,7 @@ int __cvmx_helper_board_interface_probe(int interface, int supported_ports)
return supported_ports;
}
-/**
+/*
* Get the clock type used for the USB block based on board type.
* Used by the USB code for auto configuration of clock type.
*
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-rgmii.c b/arch/mips/cavium-octeon/executive/cvmx-helper-rgmii.c
index c4b58598aa9d..a8c3be4eb6f0 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-rgmii.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-rgmii.c
@@ -42,7 +42,7 @@
#include <asm/octeon/cvmx-asxx-defs.h>
#include <asm/octeon/cvmx-dbg-defs.h>
-/**
+/*
* Probe RGMII ports and determine the number present
*
* @interface: Interface to probe
@@ -88,7 +88,7 @@ int __cvmx_helper_rgmii_probe(int interface)
return num_ports;
}
-/**
+/*
* Put an RGMII interface in loopback mode. Internal packets sent
* out will be received back again on the same port. Externally
* received packets will echo back out.
@@ -120,7 +120,7 @@ void cvmx_helper_rgmii_internal_loopback(int port)
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
}
-/**
+/*
* Workaround ASX setup errata with CN38XX pass1
*
* @interface: Interface to setup
@@ -148,7 +148,7 @@ static int __cvmx_helper_errata_asx_pass1(int interface, int port,
return 0;
}
-/**
+/*
* Configure all of the ASX, GMX, and PKO registers required
* to get RGMII to function on the supplied interface.
*
@@ -251,7 +251,7 @@ int __cvmx_helper_rgmii_enable(int interface)
return 0;
}
-/**
+/*
* Return the link state of an IPD/PKO port as returned by
* auto negotiation. The result of this function may not match
* Octeon's link config if auto negotiation has changed since
@@ -280,7 +280,7 @@ union cvmx_helper_link_info __cvmx_helper_rgmii_link_get(int ipd_port)
return __cvmx_helper_board_link_get(ipd_port);
}
-/**
+/*
* Configure an IPD/PKO port for the specified link state. This
* function does not influence auto negotiation at the PHY level.
* The passed link state must always match the link state returned
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
index 842990e8404f..fea71a85bb29 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
@@ -54,7 +54,7 @@ int __cvmx_helper_xaui_enumerate(int interface)
return 1;
}
-/**
+/*
* Probe a XAUI interface and determine the number of ports
* connected to it. The XAUI interface should still be down
* after this call.
@@ -102,7 +102,7 @@ int __cvmx_helper_xaui_probe(int interface)
return __cvmx_helper_xaui_enumerate(interface);
}
-/**
+/*
* Bringup and enable a XAUI interface. After this call packet
* I/O should be fully functional. This is called with IPD
* enabled but PKO disabled.
@@ -249,7 +249,7 @@ int __cvmx_helper_xaui_enable(int interface)
return 0;
}
-/**
+/*
* Return the link state of an IPD/PKO port as returned by
* auto negotiation. The result of this function may not match
* Octeon's link config if auto negotiation has changed since
@@ -288,7 +288,7 @@ union cvmx_helper_link_info __cvmx_helper_xaui_link_get(int ipd_port)
return result;
}
-/**
+/*
* Configure an IPD/PKO port for the specified link state. This
* function does not influence auto negotiation at the PHY level.
* The passed link state must always match the link state returned
diff --git a/arch/mips/cavium-octeon/executive/cvmx-interrupt-decodes.c b/arch/mips/cavium-octeon/executive/cvmx-interrupt-decodes.c
index 2f415d9d0f3c..67d6da21d49f 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-interrupt-decodes.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-interrupt-decodes.c
@@ -46,7 +46,9 @@
/**
- * __cvmx_interrupt_gmxx_rxx_int_en_enable enables all interrupt bits in cvmx_gmxx_rxx_int_en_t
+ * __cvmx_interrupt_gmxx_rxx_int_en_enable - enable all interrupt bits in cvmx_gmxx_rxx_int_en_t
+ * @index: interrupt register offset
+ * @block: interrupt register block_id
*/
void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block)
{
@@ -227,7 +229,9 @@ void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block)
cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, block), gmx_rx_int_en.u64);
}
/**
- * __cvmx_interrupt_pcsx_intx_en_reg_enable enables all interrupt bits in cvmx_pcsx_intx_en_reg_t
+ * __cvmx_interrupt_pcsx_intx_en_reg_enable - enable all interrupt bits in cvmx_pcsx_intx_en_reg_t
+ * @index: interrupt register offset
+ * @block: interrupt register block_id
*/
void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block)
{
@@ -268,7 +272,8 @@ void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block)
cvmx_write_csr(CVMX_PCSX_INTX_EN_REG(index, block), pcs_int_en_reg.u64);
}
/**
- * __cvmx_interrupt_pcsxx_int_en_reg_enable enables all interrupt bits in cvmx_pcsxx_int_en_reg_t
+ * __cvmx_interrupt_pcsxx_int_en_reg_enable - enable all interrupt bits in cvmx_pcsxx_int_en_reg_t
+ * @index: interrupt register block_id
*/
void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index)
{
@@ -298,7 +303,8 @@ void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index)
}
/**
- * __cvmx_interrupt_spxx_int_msk_enable enables all interrupt bits in cvmx_spxx_int_msk_t
+ * __cvmx_interrupt_spxx_int_msk_enable - enable all interrupt bits in cvmx_spxx_int_msk_t
+ * @index: interrupt register block_id
*/
void __cvmx_interrupt_spxx_int_msk_enable(int index)
{
@@ -337,7 +343,8 @@ void __cvmx_interrupt_spxx_int_msk_enable(int index)
cvmx_write_csr(CVMX_SPXX_INT_MSK(index), spx_int_msk.u64);
}
/**
- * __cvmx_interrupt_stxx_int_msk_enable enables all interrupt bits in cvmx_stxx_int_msk_t
+ * __cvmx_interrupt_stxx_int_msk_enable - enable all interrupt bits in cvmx_stxx_int_msk_t
+ * @index: interrupt register block_id
*/
void __cvmx_interrupt_stxx_int_msk_enable(int index)
{
diff --git a/arch/mips/cavium-octeon/executive/cvmx-l2c.c b/arch/mips/cavium-octeon/executive/cvmx-l2c.c
index 83df0a963a8b..33b303691bc2 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-l2c.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-l2c.c
@@ -281,7 +281,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter)
}
}
-/**
+/*
* @INTERNAL
* Helper function use to fault in cache lines for L2 cache locking
*
@@ -575,7 +575,7 @@ union __cvmx_l2c_tag {
};
-/**
+/*
* @INTERNAL
* Function to read a L2C tag. This code make the current core
* the 'debug core' for the L2. This code must only be executed by
@@ -764,9 +764,8 @@ int cvmx_l2c_get_cache_size_bytes(void)
CVMX_CACHE_LINE_SIZE;
}
-/**
+/*
* Return log base 2 of the number of sets in the L2 cache
- * Returns
*/
int cvmx_l2c_get_set_bits(void)
{
@@ -857,7 +856,7 @@ int cvmx_l2c_get_num_assoc(void)
return l2_assoc;
}
-/**
+/*
* Flush a line from the L2 cache
* This should only be called from one core at a time, as this routine
* sets the core to the 'debug' core in order to flush the line.
diff --git a/arch/mips/cavium-octeon/executive/cvmx-pko.c b/arch/mips/cavium-octeon/executive/cvmx-pko.c
index b0efc35e95c4..7c4879e74318 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-pko.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-pko.c
@@ -35,7 +35,7 @@
#include <asm/octeon/cvmx-pko.h>
#include <asm/octeon/cvmx-helper.h>
-/**
+/*
* Internal state of packet output
*/
@@ -176,7 +176,7 @@ static void __cvmx_pko_chip_init(void)
}
}
-/**
+/*
* Call before any other calls to initialize the packet
* output system. This does chip global config, and should only be
* done by one core.
@@ -229,7 +229,7 @@ void cvmx_pko_initialize_global(void)
}
}
-/**
+/*
* This function does per-core initialization required by the PKO routines.
* This must be called on all cores that will do packet output, and must
* be called after the FPA has been initialized and filled with pages.
@@ -243,7 +243,7 @@ int cvmx_pko_initialize_local(void)
return 0;
}
-/**
+/*
* Enables the packet output hardware. It must already be
* configured.
*/
@@ -266,7 +266,7 @@ void cvmx_pko_enable(void)
cvmx_write_csr(CVMX_PKO_REG_FLAGS, flags.u64);
}
-/**
+/*
* Disables the packet output. Does not affect any configuration.
*/
void cvmx_pko_disable(void)
@@ -278,7 +278,7 @@ void cvmx_pko_disable(void)
}
EXPORT_SYMBOL_GPL(cvmx_pko_disable);
-/**
+/*
* Reset the packet output.
*/
static void __cvmx_pko_reset(void)
@@ -289,7 +289,7 @@ static void __cvmx_pko_reset(void)
cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64);
}
-/**
+/*
* Shutdown and free resources required by packet output.
*/
void cvmx_pko_shutdown(void)
@@ -320,7 +320,7 @@ void cvmx_pko_shutdown(void)
}
EXPORT_SYMBOL_GPL(cvmx_pko_shutdown);
-/**
+/*
* Configure a output port and the associated queues for use.
*
* @port: Port to configure.
@@ -548,7 +548,7 @@ cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue,
}
#ifdef PKO_DEBUG
-/**
+/*
* Show map of ports -> queues for different cores.
*/
void cvmx_pko_show_queue_map()
@@ -573,7 +573,7 @@ void cvmx_pko_show_queue_map()
}
#endif
-/**
+/*
* Rate limit a PKO port to a max packets/sec. This function is only
* supported on CN51XX and higher, excluding CN58XX.
*
@@ -606,7 +606,7 @@ int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst)
return 0;
}
-/**
+/*
* Rate limit a PKO port to a max bits/sec. This function is only
* supported on CN51XX and higher, excluding CN58XX.
*
diff --git a/arch/mips/cavium-octeon/executive/cvmx-spi.c b/arch/mips/cavium-octeon/executive/cvmx-spi.c
index f51957a3e915..eb9333e84a6b 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-spi.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-spi.c
@@ -66,7 +66,7 @@ static cvmx_spi_callbacks_t cvmx_spi_callbacks = {
.interface_up_cb = cvmx_spi_interface_up_cb
};
-/**
+/*
* Get current SPI4 initialization callbacks
*
* @callbacks: Pointer to the callbacks structure.to fill
@@ -78,7 +78,7 @@ void cvmx_spi_get_callbacks(cvmx_spi_callbacks_t *callbacks)
memcpy(callbacks, &cvmx_spi_callbacks, sizeof(cvmx_spi_callbacks));
}
-/**
+/*
* Set new SPI4 initialization callbacks
*
* @new_callbacks: Pointer to an updated callbacks structure.
@@ -88,7 +88,7 @@ void cvmx_spi_set_callbacks(cvmx_spi_callbacks_t *new_callbacks)
memcpy(&cvmx_spi_callbacks, new_callbacks, sizeof(cvmx_spi_callbacks));
}
-/**
+/*
* Initialize and start the SPI interface.
*
* @interface: The identifier of the packet interface to configure and
@@ -133,7 +133,7 @@ int cvmx_spi_start_interface(int interface, cvmx_spi_mode_t mode, int timeout,
return res;
}
-/**
+/*
* This routine restarts the SPI interface after it has lost synchronization
* with its correspondent system.
*
@@ -179,7 +179,7 @@ int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode, int timeout)
}
EXPORT_SYMBOL_GPL(cvmx_spi_restart_interface);
-/**
+/*
* Callback to perform SPI4 reset
*
* @interface: The identifier of the packet interface to configure and
@@ -294,7 +294,7 @@ int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode)
return 0;
}
-/**
+/*
* Callback to setup calendar and miscellaneous settings before clock detection
*
* @interface: The identifier of the packet interface to configure and
@@ -413,7 +413,7 @@ int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode,
return 0;
}
-/**
+/*
* Callback to perform clock detection
*
* @interface: The identifier of the packet interface to configure and
@@ -491,7 +491,7 @@ int cvmx_spi_clock_detect_cb(int interface, cvmx_spi_mode_t mode, int timeout)
return 0;
}
-/**
+/*
* Callback to perform link training
*
* @interface: The identifier of the packet interface to configure and
@@ -560,7 +560,7 @@ int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, int timeout)
return 0;
}
-/**
+/*
* Callback to perform calendar data synchronization
*
* @interface: The identifier of the packet interface to configure and
@@ -617,7 +617,7 @@ int cvmx_spi_calendar_sync_cb(int interface, cvmx_spi_mode_t mode, int timeout)
return 0;
}
-/**
+/*
* Callback to handle interface up
*
* @interface: The identifier of the packet interface to configure and
diff --git a/arch/mips/cavium-octeon/flash_setup.c b/arch/mips/cavium-octeon/flash_setup.c
index a5e8f4a784af..c8a8c6d359b9 100644
--- a/arch/mips/cavium-octeon/flash_setup.c
+++ b/arch/mips/cavium-octeon/flash_setup.c
@@ -62,7 +62,7 @@ static void octeon_flash_map_copy_to(struct map_info *map, unsigned long to,
up(&octeon_bootbus_sem);
}
-/**
+/*
* Module/ driver initialization.
*
* Returns Zero on success
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index ce4e2806159b..00bf269763cf 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -284,11 +284,6 @@ void octeon_crash_smp_send_stop(void)
#endif /* CONFIG_KEXEC */
-#ifdef CONFIG_CAVIUM_RESERVE32
-uint64_t octeon_reserve32_memory;
-EXPORT_SYMBOL(octeon_reserve32_memory);
-#endif
-
#ifdef CONFIG_KEXEC
/* crashkernel cmdline parameter is parsed _after_ memory setup
* we also parse it here (workaround for EHB5200) */
@@ -300,9 +295,10 @@ static int octeon_uart;
extern asmlinkage void handle_int(void);
/**
- * Return non zero if we are currently running in the Octeon simulator
+ * octeon_is_simulation - Return non-zero if we are currently running
+ * in the Octeon simulator
*
- * Returns
+ * Return: non-0 if running in the Octeon simulator, 0 otherwise
*/
int octeon_is_simulation(void)
{
@@ -311,10 +307,10 @@ int octeon_is_simulation(void)
EXPORT_SYMBOL(octeon_is_simulation);
/**
- * Return true if Octeon is in PCI Host mode. This means
+ * octeon_is_pci_host - Return true if Octeon is in PCI Host mode. This means
* Linux can control the PCI bus.
*
- * Returns Non zero if Octeon in host mode.
+ * Return: Non-zero if Octeon is in host mode.
*/
int octeon_is_pci_host(void)
{
@@ -326,9 +322,9 @@ int octeon_is_pci_host(void)
}
/**
- * Get the clock rate of Octeon
+ * octeon_get_clock_rate - Get the clock rate of Octeon
*
- * Returns Clock rate in HZ
+ * Return: Clock rate in HZ
*/
uint64_t octeon_get_clock_rate(void)
{
@@ -348,11 +344,11 @@ EXPORT_SYMBOL(octeon_get_io_clock_rate);
/**
- * Write to the LCD display connected to the bootbus. This display
- * exists on most Cavium evaluation boards. If it doesn't exist, then
- * this function doesn't do anything.
- *
+ * octeon_write_lcd - Write to the LCD display connected to the bootbus.
* @s: String to write
+ *
+ * This display exists on most Cavium evaluation boards. If it doesn't exist,
+ * then this function doesn't do anything.
*/
static void octeon_write_lcd(const char *s)
{
@@ -372,9 +368,9 @@ static void octeon_write_lcd(const char *s)
}
/**
- * Return the console uart passed by the bootloader
+ * octeon_get_boot_uart - Return the console uart passed by the bootloader
*
- * Returns uart (0 or 1)
+ * Return: uart number (0 or 1)
*/
static int octeon_get_boot_uart(void)
{
@@ -383,9 +379,9 @@ static int octeon_get_boot_uart(void)
}
/**
- * Get the coremask Linux was booted on.
+ * octeon_get_boot_coremask - Get the coremask Linux was booted on.
*
- * Returns Core mask
+ * Return: Core mask
*/
int octeon_get_boot_coremask(void)
{
@@ -393,7 +389,7 @@ int octeon_get_boot_coremask(void)
}
/**
- * Check the hardware BIST results for a CPU
+ * octeon_check_cpu_bist - Check the hardware BIST results for a CPU
*/
void octeon_check_cpu_bist(void)
{
@@ -424,7 +420,7 @@ void octeon_check_cpu_bist(void)
}
/**
- * Reboot Octeon
+ * octeon_restart - Reboot Octeon
*
* @command: Command to pass to the bootloader. Currently ignored.
*/
@@ -449,7 +445,7 @@ static void octeon_restart(char *command)
/**
- * Permanently stop a core.
+ * octeon_kill_core - Permanently stop a core.
*
* @arg: Ignored.
*/
@@ -469,7 +465,7 @@ static void octeon_kill_core(void *arg)
/**
- * Halt the system
+ * octeon_halt - Halt the system
*/
static void octeon_halt(void)
{
@@ -512,9 +508,9 @@ static void __init init_octeon_system_type(void)
}
/**
- * Return a string representing the system type
+ * octeon_board_type_string - Return a string representing the system type
*
- * Returns
+ * Return: system type string
*/
const char *octeon_board_type_string(void)
{
@@ -655,7 +651,7 @@ void octeon_user_io_init(void)
}
/**
- * Early entry point for arch setup
+ * prom_init - Early entry point for arch setup
*/
void __init prom_init(void)
{
@@ -665,9 +661,7 @@ void __init prom_init(void)
int i;
u64 t;
int argc;
-#ifdef CONFIG_CAVIUM_RESERVE32
- int64_t addr = -1;
-#endif
+
/*
* The bootloader passes a pointer to the boot descriptor in
* $a3, this is available as fw_arg3.
@@ -782,25 +776,6 @@ void __init prom_init(void)
cvmx_write_csr(CVMX_LED_UDD_DATX(1), 0);
cvmx_write_csr(CVMX_LED_EN, 1);
}
-#ifdef CONFIG_CAVIUM_RESERVE32
- /*
- * We need to temporarily allocate all memory in the reserve32
- * region. This makes sure the kernel doesn't allocate this
- * memory when it is getting memory from the
- * bootloader. Later, after the memory allocations are
- * complete, the reserve32 will be freed.
- *
- * Allocate memory for RESERVED32 aligned on 2MB boundary. This
- * is in case we later use hugetlb entries with it.
- */
- addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
- 0, 0, 2 << 20,
- "CAVIUM_RESERVE32", 0);
- if (addr < 0)
- pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n");
- else
- octeon_reserve32_memory = addr;
-#endif
#ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2
if (cvmx_read_csr(CVMX_L2D_FUS3) & (3ull << 34)) {
@@ -1078,16 +1053,6 @@ void __init plat_mem_setup(void)
cvmx_bootmem_unlock();
#endif /* CONFIG_CRASH_DUMP */
-#ifdef CONFIG_CAVIUM_RESERVE32
- /*
- * Now that we've allocated the kernel memory it is safe to
- * free the reserved region. We free it here so that builtin
- * drivers can use the memory.
- */
- if (octeon_reserve32_memory)
- cvmx_bootmem_free_named("CAVIUM_RESERVE32");
-#endif /* CONFIG_CAVIUM_RESERVE32 */
-
if (total == 0)
panic("Unable to allocate memory from "
"cvmx_bootmem_phy_alloc");
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index 66ce5527da54..89954f5f87fb 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -91,7 +91,7 @@ static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-/**
+/*
* Cause the function described by call_data to be executed on the passed
* cpu. When the function has finished, increment the finished field of
* call_data.
@@ -115,7 +115,7 @@ static inline void octeon_send_ipi_mask(const struct cpumask *mask,
octeon_send_ipi_single(i, action);
}
-/**
+/*
* Detect available CPUs, populate cpu_possible_mask
*/
static void octeon_smp_hotplug_setup(void)
@@ -202,9 +202,8 @@ int plat_post_relocation(long offset)
}
#endif /* CONFIG_RELOCATABLE */
-/**
+/*
* Firmware CPU startup hook
- *
*/
static int octeon_boot_secondary(int cpu, struct task_struct *idle)
{
@@ -232,7 +231,7 @@ static int octeon_boot_secondary(int cpu, struct task_struct *idle)
return 0;
}
-/**
+/*
* After we've done initial boot, this function is called to allow the
* board code to clean up state, if needed
*/
@@ -250,9 +249,8 @@ static void octeon_init_secondary(void)
octeon_irq_setup_secondary();
}
-/**
+/*
* Callout to firmware before smp_init
- *
*/
static void __init octeon_prepare_cpus(unsigned int max_cpus)
{
@@ -268,7 +266,7 @@ static void __init octeon_prepare_cpus(unsigned int max_cpus)
}
}
-/**
+/*
* Last chance for the board code to finish SMP initialization before
* the CPU is "online".
*/
diff --git a/arch/mips/configs/generic/board-marduk.config b/arch/mips/configs/generic/board-marduk.config
new file mode 100644
index 000000000000..05ca34cd5a73
--- /dev/null
+++ b/arch/mips/configs/generic/board-marduk.config
@@ -0,0 +1,53 @@
+CONFIG_FIT_IMAGE_FDT_MARDUK=y
+
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+
+CONFIG_CLKSRC_PISTACHIO=y
+
+CONFIG_COMMON_CLK_PISTACHIO=y
+
+CONFIG_DMADEVICES=y
+CONFIG_IMG_MDC_DMA=y
+
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_PCH=y
+
+CONFIG_I2C=y
+CONFIG_I2C_IMG=y
+
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_PLTFM=y
+
+CONFIG_NETDEVICES=y
+CONFIG_STMMAC_ETH=y
+CONFIG_STMMAC_PLATFORM=y
+
+CONFIG_PHY_PISTACHIO_USB=y
+
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_PISTACHIO=y
+
+CONFIG_RESET_PISTACHIO=y
+
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_8250_DW=y
+
+CONFIG_SPI=y
+CONFIG_SRAM=y
+
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_DWC2=y
+
+CONFIG_CRYPTO_DEV_IMGTEC_HASH=y
+CONFIG_IMGPDC_WDT=y
+CONFIG_IR_IMG=y
+CONFIG_CC10001_ADC=y
+CONFIG_SND_SOC_IMG=y
diff --git a/arch/mips/configs/pistachio_defconfig b/arch/mips/configs/pistachio_defconfig
deleted file mode 100644
index b9adf15ebbec..000000000000
--- a/arch/mips/configs/pistachio_defconfig
+++ /dev/null
@@ -1,316 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_DEFAULT_HOSTNAME="localhost"
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_IKCONFIG=m
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_CGROUPS=y
-CONFIG_CGROUP_SCHED=y
-CONFIG_CFS_BANDWIDTH=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_NAMESPACES=y
-CONFIG_USER_NS=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_BZIP2 is not set
-# CONFIG_RD_LZMA is not set
-# CONFIG_RD_LZO is not set
-# CONFIG_RD_LZ4 is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_EMBEDDED=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_PROFILING=y
-CONFIG_MACH_PISTACHIO=y
-CONFIG_MIPS_CPS=y
-CONFIG_NR_CPUS=4
-CONFIG_PM_DEBUG=y
-CONFIG_PM_ADVANCED_DEBUG=y
-CONFIG_CPU_IDLE=y
-# CONFIG_MIPS_CPS_CPUIDLE is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_COMPACTION is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
-CONFIG_ZSMALLOC=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-# CONFIG_INET_DIAG is not set
-CONFIG_TCP_CONG_ADVANCED=y
-# CONFIG_TCP_CONG_BIC is not set
-# CONFIG_TCP_CONG_WESTWOOD is not set
-# CONFIG_TCP_CONG_HTCP is not set
-CONFIG_TCP_CONG_LP=m
-CONFIG_TCP_MD5SIG=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_IPV6_SIT=m
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_BRIDGE_NETFILTER is not set
-CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CT_NETLINK=y
-CONFIG_NETFILTER_XT_MARK=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
-CONFIG_NETFILTER_XT_TARGET_DSCP=y
-CONFIG_NETFILTER_XT_TARGET_NFLOG=y
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
-CONFIG_NETFILTER_XT_TARGET_SECMARK=y
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
-CONFIG_NETFILTER_XT_MATCH_DSCP=y
-CONFIG_NETFILTER_XT_MATCH_POLICY=y
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-CONFIG_NF_NAT_IPV4=m
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_MANGLE=y
-CONFIG_NF_NAT_IPV6=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_REJECT=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_CODEL=m
-CONFIG_NET_SCH_FQ_CODEL=m
-CONFIG_NET_CLS_U32=m
-CONFIG_CLS_U32_MARK=y
-CONFIG_BT=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_HCIBTUSB=m
-CONFIG_BT_HCIBFUSB=m
-CONFIG_BT_HCIVHCI=m
-CONFIG_CFG80211=m
-CONFIG_NL80211_TESTMODE=y
-CONFIG_CFG80211_DEBUGFS=y
-CONFIG_CFG80211_WEXT=y
-CONFIG_MAC80211=m
-CONFIG_MAC80211_LEDS=y
-CONFIG_MAC80211_DEBUGFS=y
-CONFIG_MAC80211_DEBUG_MENU=y
-CONFIG_MAC80211_VERBOSE_DEBUG=y
-CONFIG_RFKILL=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_DEBUG_DEVRES=y
-CONFIG_CONNECTOR=y
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_SPI_NOR=y
-CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_BLOCK=y
-CONFIG_ZRAM=m
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_DEV_SR=m
-CONFIG_SCSI_SPI_ATTRS=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
-CONFIG_DM_VERITY=y
-CONFIG_NETDEVICES=y
-CONFIG_TUN=m
-CONFIG_VETH=m
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_MICROCHIP is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SMSC is not set
-CONFIG_STMMAC_ETH=y
-# CONFIG_NET_VENDOR_VIA is not set
-CONFIG_PPP=m
-CONFIG_PPP_ASYNC=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_RTL8152=m
-CONFIG_USB_NET_DM9601=m
-CONFIG_USB_NET_SMSC75XX=m
-CONFIG_USB_NET_SMSC95XX=m
-CONFIG_USB_NET_MCS7830=m
-# CONFIG_USB_NET_CDC_SUBSET is not set
-# CONFIG_USB_NET_ZAURUS is not set
-CONFIG_HOSTAP=m
-CONFIG_HOSTAP_FIRMWARE=y
-CONFIG_HOSTAP_FIRMWARE_NVRAM=y
-CONFIG_LIBERTAS_THINFIRM=m
-CONFIG_RT2X00=m
-CONFIG_RT2800USB=m
-CONFIG_MAC80211_HWSIM=m
-CONFIG_USB_NET_RNDIS_WLAN=m
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_DW=y
-CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_HW_RANDOM=y
-CONFIG_TCG_TPM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_IMG=y
-CONFIG_I2C_STUB=m
-CONFIG_SPI=y
-CONFIG_SPI_BITBANG=m
-CONFIG_SPI_IMG_SPFI=y
-CONFIG_SPI_SPIDEV=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_THERMAL=y
-CONFIG_WATCHDOG=y
-CONFIG_IMGPDC_WDT=y
-CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_REGULATOR_GPIO=y
-CONFIG_RC_CORE=y
-CONFIG_RC_DEVICES=y
-CONFIG_IR_IMG=y
-CONFIG_IR_IMG_NEC=y
-CONFIG_IR_IMG_JVC=y
-CONFIG_IR_IMG_SONY=y
-CONFIG_IR_IMG_SHARP=y
-CONFIG_IR_IMG_SANYO=y
-CONFIG_IR_IMG_RC5=y
-CONFIG_IR_IMG_RC6=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_HRTIMER=m
-CONFIG_SND_DYNAMIC_MINORS=y
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-# CONFIG_SND_SPI is not set
-CONFIG_SND_USB_AUDIO=m
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-# CONFIG_USB_DEFAULT_PERSIST is not set
-CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_ACM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_DWC2=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_CP210X=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_OTI6858=m
-CONFIG_USB_SERIAL_QUALCOMM=m
-CONFIG_USB_SERIAL_SIERRAWIRELESS=m
-CONFIG_USB_SERIAL_OPTION=m
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK_MINORS=16
-CONFIG_MMC_TEST=m
-CONFIG_MMC_DW=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_DMADEVICES=y
-CONFIG_IMG_MDC_DMA=y
-CONFIG_STAGING=y
-CONFIG_ASHMEM=y
-# CONFIG_IOMMU_SUPPORT is not set
-CONFIG_MEMORY=y
-CONFIG_IIO=y
-CONFIG_CC10001_ADC=y
-CONFIG_PWM=y
-CONFIG_PWM_IMG=y
-CONFIG_PHY_PISTACHIO_USB=y
-CONFIG_ANDROID=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-# CONFIG_DNOTIFY is not set
-CONFIG_FUSE_FS=m
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_ECRYPT_FS=y
-CONFIG_HFSPLUS_FS=m
-CONFIG_UBIFS_FS=y
-CONFIG_SQUASHFS=y
-CONFIG_SQUASHFS_FILE_DIRECT=y
-CONFIG_SQUASHFS_LZO=y
-CONFIG_PSTORE=y
-CONFIG_PSTORE_CONSOLE=y
-CONFIG_PSTORE_RAM=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="utf8"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_SECURITY_YAMA=y
-CONFIG_CRYPTO_AUTHENC=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=m
-CONFIG_CRC7=m
-# CONFIG_XZ_DEC_X86 is not set
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_INFO=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0
-# CONFIG_SCHED_DEBUG is not set
-CONFIG_SCHEDSTATS=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_CREDENTIALS=y
-CONFIG_FUNCTION_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_LKDTM=y
-CONFIG_TEST_UDELAY=m
diff --git a/arch/mips/generic/Kconfig b/arch/mips/generic/Kconfig
index 657dd93c5e76..7dc5b3821cc6 100644
--- a/arch/mips/generic/Kconfig
+++ b/arch/mips/generic/Kconfig
@@ -58,6 +58,12 @@ config FIT_IMAGE_FDT_BOSTON
enable this if you wish to boot on a MIPS Boston board, as it is
expected by the bootloader.
+config FIT_IMAGE_FDT_MARDUK
+ bool "Include FDT for IMG Pistachio Marduk (CI40) boards"
+ help
+ Enable this to include the FDT for the IMG Pistachio Marduk (CI40)
+ from Imagination Technologies in the FIT kernel image.
+
config FIT_IMAGE_FDT_NI169445
bool "Include FDT for NI 169445"
help
diff --git a/arch/mips/generic/Platform b/arch/mips/generic/Platform
index b871af16b5b6..e1abc113b409 100644
--- a/arch/mips/generic/Platform
+++ b/arch/mips/generic/Platform
@@ -24,3 +24,4 @@ its-$(CONFIG_FIT_IMAGE_FDT_LUTON) += board-luton.its.S
its-$(CONFIG_FIT_IMAGE_FDT_JAGUAR2) += board-jaguar2.its.S
its-$(CONFIG_FIT_IMAGE_FDT_SERVAL) += board-serval.its.S
its-$(CONFIG_FIT_IMAGE_FDT_XILFPGA) += board-xilfpga.its.S
+its-$(CONFIG_FIT_IMAGE_FDT_MARDUK) += board-marduk.its.S
diff --git a/arch/mips/generic/board-ingenic.c b/arch/mips/generic/board-ingenic.c
index 0cec0bea13d6..3f44f14bdb33 100644
--- a/arch/mips/generic/board-ingenic.c
+++ b/arch/mips/generic/board-ingenic.c
@@ -7,6 +7,8 @@
* Copyright (C) 2020 Paul Cercueil <paul@crapouillou.net>
*/
+#include <linux/clk.h>
+#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#include <linux/pm.h>
@@ -21,6 +23,10 @@
static __init char *ingenic_get_system_type(unsigned long machtype)
{
switch (machtype) {
+ case MACH_INGENIC_X2100:
+ return "X2100";
+ case MACH_INGENIC_X2000H:
+ return "X2000H";
case MACH_INGENIC_X2000E:
return "X2000E";
case MACH_INGENIC_X2000:
@@ -37,8 +43,18 @@ static __init char *ingenic_get_system_type(unsigned long machtype)
return "JZ4775";
case MACH_INGENIC_JZ4770:
return "JZ4770";
+ case MACH_INGENIC_JZ4760B:
+ return "JZ4760B";
+ case MACH_INGENIC_JZ4760:
+ return "JZ4760";
+ case MACH_INGENIC_JZ4755:
+ return "JZ4755";
+ case MACH_INGENIC_JZ4750:
+ return "JZ4750";
case MACH_INGENIC_JZ4725B:
return "JZ4725B";
+ case MACH_INGENIC_JZ4730:
+ return "JZ4730";
default:
return "JZ4740";
}
@@ -61,8 +77,13 @@ static __init const void *ingenic_fixup_fdt(const void *fdt, const void *match_d
}
static const struct of_device_id ingenic_of_match[] __initconst = {
+ { .compatible = "ingenic,jz4730", .data = (void *)MACH_INGENIC_JZ4730 },
{ .compatible = "ingenic,jz4740", .data = (void *)MACH_INGENIC_JZ4740 },
{ .compatible = "ingenic,jz4725b", .data = (void *)MACH_INGENIC_JZ4725B },
+ { .compatible = "ingenic,jz4750", .data = (void *)MACH_INGENIC_JZ4750 },
+ { .compatible = "ingenic,jz4755", .data = (void *)MACH_INGENIC_JZ4755 },
+ { .compatible = "ingenic,jz4760", .data = (void *)MACH_INGENIC_JZ4760 },
+ { .compatible = "ingenic,jz4760b", .data = (void *)MACH_INGENIC_JZ4760B },
{ .compatible = "ingenic,jz4770", .data = (void *)MACH_INGENIC_JZ4770 },
{ .compatible = "ingenic,jz4775", .data = (void *)MACH_INGENIC_JZ4775 },
{ .compatible = "ingenic,jz4780", .data = (void *)MACH_INGENIC_JZ4780 },
@@ -71,6 +92,8 @@ static const struct of_device_id ingenic_of_match[] __initconst = {
{ .compatible = "ingenic,x1830", .data = (void *)MACH_INGENIC_X1830 },
{ .compatible = "ingenic,x2000", .data = (void *)MACH_INGENIC_X2000 },
{ .compatible = "ingenic,x2000e", .data = (void *)MACH_INGENIC_X2000E },
+ { .compatible = "ingenic,x2000h", .data = (void *)MACH_INGENIC_X2000H },
+ { .compatible = "ingenic,x2100", .data = (void *)MACH_INGENIC_X2100 },
{}
};
@@ -108,10 +131,36 @@ static const struct platform_suspend_ops ingenic_pm_ops __maybe_unused = {
static int __init ingenic_pm_init(void)
{
+ struct device_node *cpu_node;
+ struct clk *cpu0_clk;
+ int ret;
+
if (boot_cpu_type() == CPU_XBURST) {
if (IS_ENABLED(CONFIG_PM_SLEEP))
suspend_set_ops(&ingenic_pm_ops);
_machine_halt = ingenic_halt;
+
+ /*
+ * Unconditionally enable the clock for the first CPU.
+ * This makes sure that the PLL that feeds the CPU won't be
+ * stopped while the kernel is running.
+ */
+ cpu_node = of_get_cpu_node(0, NULL);
+ if (!cpu_node) {
+ pr_err("Unable to get CPU node\n");
+ } else {
+ cpu0_clk = of_clk_get(cpu_node, 0);
+ if (IS_ERR(cpu0_clk)) {
+ pr_err("Unable to get CPU0 clock\n");
+ return PTR_ERR(cpu0_clk);
+ }
+
+ ret = clk_prepare_enable(cpu0_clk);
+ if (ret) {
+ pr_err("Unable to enable CPU0 clock\n");
+ return ret;
+ }
+ }
}
return 0;
diff --git a/arch/mips/generic/board-marduk.its.S b/arch/mips/generic/board-marduk.its.S
new file mode 100644
index 000000000000..4f633794db90
--- /dev/null
+++ b/arch/mips/generic/board-marduk.its.S
@@ -0,0 +1,22 @@
+/ {
+ images {
+ fdt-marduk {
+ description = "img,pistachio-marduk Device Tree";
+ data = /incbin/("boot/dts/img/pistachio_marduk.dtb");
+ type = "flat_dt";
+ arch = "mips";
+ compression = "none";
+ hash {
+ algo = "sha1";
+ };
+ };
+ };
+
+ configurations {
+ conf-marduk {
+ description = "Marduk Linux kernel";
+ kernel = "kernel";
+ fdt = "fdt-marduk";
+ };
+ };
+};
diff --git a/arch/mips/generic/board-ocelot.c b/arch/mips/generic/board-ocelot.c
index c238e95190ac..7115410acb4f 100644
--- a/arch/mips/generic/board-ocelot.c
+++ b/arch/mips/generic/board-ocelot.c
@@ -26,13 +26,13 @@ static __init bool ocelot_detect(void)
tlb_probe_hazard();
idx = read_c0_index();
if (idx < 0)
- return 0;
+ return false;
/* A TLB entry exists, lets assume its usable and check the CHIP ID */
rev = __raw_readl((void __iomem *)DEVCPU_GCB_CHIP_REGS_CHIP_ID);
if ((rev & CHIP_ID_PART_ID) != OCELOT_PART_ID)
- return 0;
+ return false;
/* Copy command line from bootloader early for Initrd detection */
if (fw_arg0 < 10 && (fw_arg1 & 0xFFF00000) == 0x80000000) {
@@ -44,7 +44,7 @@ static __init bool ocelot_detect(void)
strcpy(arcs_cmdline, prom_argv[1]);
}
- return 1;
+ return true;
}
static void __init ocelot_earlyprintk_init(void)
diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h
index ea4b62ece336..2f8ce94ebaaf 100644
--- a/arch/mips/include/asm/asm.h
+++ b/arch/mips/include/asm/asm.h
@@ -114,7 +114,7 @@ symbol = value
.set push; \
.set reorder; \
PTR_LA a0, 8f; \
- jal printk; \
+ jal _printk; \
.set pop; \
TEXT(string)
#else
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 95e1f7f3597f..a0b9e7c1e4fc 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -206,7 +206,7 @@ ATOMIC_OPS(atomic64, xor, s64, ^=, xor, lld, scd)
* The function returns the old value of @v minus @i.
*/
#define ATOMIC_SIP_OP(pfx, type, op, ll, sc) \
-static __inline__ int arch_##pfx##_sub_if_positive(type i, pfx##_t * v) \
+static __inline__ type arch_##pfx##_sub_if_positive(type i, pfx##_t * v) \
{ \
type temp, result; \
\
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 4c2e8173e6ec..2128ba903391 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -75,6 +75,7 @@ enum ingenic_machine_type {
MACH_INGENIC_JZ4750,
MACH_INGENIC_JZ4755,
MACH_INGENIC_JZ4760,
+ MACH_INGENIC_JZ4760B,
MACH_INGENIC_JZ4770,
MACH_INGENIC_JZ4775,
MACH_INGENIC_JZ4780,
@@ -83,6 +84,8 @@ enum ingenic_machine_type {
MACH_INGENIC_X1830,
MACH_INGENIC_X2000,
MACH_INGENIC_X2000E,
+ MACH_INGENIC_X2000H,
+ MACH_INGENIC_X2100,
};
extern char *system_type;
diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
index d687b40b9fbb..b3dc9c589442 100644
--- a/arch/mips/include/asm/cacheflush.h
+++ b/arch/mips/include/asm/cacheflush.h
@@ -125,13 +125,7 @@ static inline void kunmap_noncoherent(void)
kunmap_coherent();
}
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-static inline void flush_kernel_dcache_page(struct page *page)
-{
- BUG_ON(cpu_has_dc_aliases && PageHighMem(page));
- flush_dcache_page(page);
-}
-
+#define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1
/*
* For now flush_kernel_vmap_range and invalidate_kernel_vmap_range both do a
* cache writeback and invalidate operation.
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 9e6211e6d76b..d45a52f65b7a 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -46,8 +46,8 @@
#define PRID_COMP_NETLOGIC 0x0c0000
#define PRID_COMP_CAVIUM 0x0d0000
#define PRID_COMP_LOONGSON 0x140000
-#define PRID_COMP_INGENIC_13 0x130000 /* X2000 */
-#define PRID_COMP_INGENIC_D0 0xd00000 /* JZ4740, JZ4750, X1830 */
+#define PRID_COMP_INGENIC_13 0x130000 /* X2000, X2100 */
+#define PRID_COMP_INGENIC_D0 0xd00000 /* JZ4730, JZ4740, JZ4750, JZ4755, JZ4760, X1830 */
#define PRID_COMP_INGENIC_D1 0xd10000 /* JZ4770, JZ4775, X1000 */
#define PRID_COMP_INGENIC_E1 0xe10000 /* JZ4780 */
diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h
index c34c7eef0a1c..8cb8bd061a68 100644
--- a/arch/mips/include/uapi/asm/siginfo.h
+++ b/arch/mips/include/uapi/asm/siginfo.h
@@ -10,9 +10,7 @@
#ifndef _UAPI_ASM_SIGINFO_H
#define _UAPI_ASM_SIGINFO_H
-
#define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(long) + 2*sizeof(int))
-#undef __ARCH_SI_TRAPNO /* exception code needs to fill this ... */
#define __ARCH_HAS_SWAPPED_SIGINFO
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
index 461457b28982..eabddb89d221 100644
--- a/arch/mips/jazz/jazzdma.c
+++ b/arch/mips/jazz/jazzdma.c
@@ -552,7 +552,7 @@ static int jazz_dma_map_sg(struct device *dev, struct scatterlist *sglist,
dir);
sg->dma_address = vdma_alloc(sg_phys(sg), sg->length);
if (sg->dma_address == DMA_MAPPING_ERROR)
- return 0;
+ return -EIO;
sg_dma_len(sg) = sg->length;
}
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 6c590ef27648..67e130d3f038 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -76,13 +76,13 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
return -EFAULT;
- get_online_cpus();
+ cpus_read_lock();
rcu_read_lock();
p = find_process_by_pid(pid);
if (!p) {
rcu_read_unlock();
- put_online_cpus();
+ cpus_read_unlock();
return -ESRCH;
}
@@ -147,7 +147,7 @@ out_free_cpus_allowed:
free_cpumask_var(cpus_allowed);
out_put_task:
put_task_struct(p);
- put_online_cpus();
+ cpus_read_unlock();
return retval;
}
@@ -166,7 +166,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
if (len < real_len)
return -EINVAL;
- get_online_cpus();
+ cpus_read_lock();
rcu_read_lock();
retval = -ESRCH;
@@ -182,7 +182,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
out_unlock:
rcu_read_unlock();
- put_online_cpus();
+ cpus_read_unlock();
if (retval)
return retval;
if (copy_to_user(user_mask_ptr, &mask, real_len))
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 73c8e7990a97..95aa86fa6077 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -859,10 +859,10 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
* scheduled in then it will already have picked up the new FP mode
* whilst doing so.
*/
- get_online_cpus();
+ cpus_read_lock();
for_each_cpu_and(cpu, &process_cpus, cpu_online_mask)
work_on_cpu(cpu, prepare_for_fp_mode_switch, NULL);
- put_online_cpus();
+ cpus_read_unlock();
return 0;
}
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 23a140327a0b..f979adfd4fc2 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -452,8 +452,9 @@ static void __init mips_parse_crashkernel(void)
return;
if (crash_base <= 0) {
- crash_base = memblock_find_in_range(CRASH_ALIGN, CRASH_ADDR_MAX,
- crash_size, CRASH_ALIGN);
+ crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN,
+ CRASH_ALIGN,
+ CRASH_ADDR_MAX);
if (!crash_base) {
pr_warn("crashkernel reservation failed - No suitable area found.\n");
return;
@@ -461,8 +462,9 @@ static void __init mips_parse_crashkernel(void)
} else {
unsigned long long start;
- start = memblock_find_in_range(crash_base, crash_base + crash_size,
- crash_size, 1);
+ start = memblock_phys_alloc_range(crash_size, 1,
+ crash_base,
+ crash_base + crash_size);
if (start != crash_base) {
pr_warn("Invalid memory region reserved for crash kernel\n");
return;
@@ -656,10 +658,6 @@ static void __init arch_mem_init(char **cmdline_p)
mips_reserve_vmcore();
mips_parse_crashkernel();
-#ifdef CONFIG_KEXEC
- if (crashk_res.start != crashk_res.end)
- memblock_reserve(crashk_res.start, resource_size(&crashk_res));
-#endif
device_tree_init();
/*
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
index c2d2e19abea8..56c8d3cf42ed 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -385,3 +385,5 @@
444 n32 landlock_create_ruleset sys_landlock_create_ruleset
445 n32 landlock_add_rule sys_landlock_add_rule
446 n32 landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 n32 process_mrelease sys_process_mrelease
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
index ac653d08b1ea..1ca7bc337932 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
@@ -361,3 +361,5 @@
444 n64 landlock_create_ruleset sys_landlock_create_ruleset
445 n64 landlock_add_rule sys_landlock_add_rule
446 n64 landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 n64 process_mrelease sys_process_mrelease
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index 253f2cd70b6b..201237fd0f43 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -145,7 +145,7 @@
131 o32 quotactl sys_quotactl
132 o32 getpgid sys_getpgid
133 o32 fchdir sys_fchdir
-134 o32 bdflush sys_bdflush
+134 o32 bdflush sys_ni_syscall
135 o32 sysfs sys_sysfs
136 o32 personality sys_personality sys_32_personality
137 o32 afs_syscall sys_ni_syscall
@@ -434,3 +434,5 @@
444 o32 landlock_create_ruleset sys_landlock_create_ruleset
445 o32 landlock_add_rule sys_landlock_add_rule
446 o32 landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 o32 process_mrelease sys_process_mrelease
diff --git a/arch/mips/kernel/uprobes.c b/arch/mips/kernel/uprobes.c
index 6dbe4eab0a0e..9db2a6db5f62 100644
--- a/arch/mips/kernel/uprobes.c
+++ b/arch/mips/kernel/uprobes.c
@@ -75,7 +75,7 @@ bool is_trap_insn(uprobe_opcode_t *insn)
case tlt_op:
case tltu_op:
case tne_op:
- return 1;
+ return true;
}
break;
@@ -87,12 +87,12 @@ bool is_trap_insn(uprobe_opcode_t *insn)
case tlti_op:
case tltiu_op:
case tnei_op:
- return 1;
+ return true;
}
break;
}
- return 0;
+ return false;
}
#define UPROBE_TRAP_NR ULONG_MAX
@@ -254,9 +254,9 @@ unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
* See if the instruction can be emulated.
* Returns true if instruction was emulated, false otherwise.
*
- * For now we always emulate so this function just returns 0.
+ * For now we always emulate so this function just returns false.
*/
bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
{
- return 0;
+ return false;
}
diff --git a/arch/mips/kvm/Makefile b/arch/mips/kvm/Makefile
index c67250a956b8..d3710959da55 100644
--- a/arch/mips/kvm/Makefile
+++ b/arch/mips/kvm/Makefile
@@ -2,21 +2,18 @@
# Makefile for KVM support for MIPS
#
-common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o eventfd.o binary_stats.o)
+ccflags-y += -Ivirt/kvm -Iarch/mips/kvm
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/mips/kvm
+kvm-y := $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o eventfd.o binary_stats.o)
+kvm-$(CONFIG_CPU_HAS_MSA) += msa.o
-common-objs-$(CONFIG_CPU_HAS_MSA) += msa.o
-
-kvm-objs := $(common-objs-y) mips.o emulate.o entry.o \
+kvm-y += mips.o emulate.o entry.o \
interrupt.o stats.o \
fpu.o
-kvm-objs += hypcall.o
-kvm-objs += mmu.o
-ifdef CONFIG_CPU_LOONGSON64
-kvm-objs += loongson_ipi.o
-endif
+kvm-y += hypcall.o
+kvm-y += mmu.o
+kvm-$(CONFIG_CPU_LOONGSON64) += loongson_ipi.o
-kvm-objs += vz.o
+kvm-y += vz.o
obj-$(CONFIG_KVM) += kvm.o
obj-y += callback.o tlb.o
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index af9dd029a4e1..75c6f264c626 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -41,8 +41,6 @@
const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
KVM_GENERIC_VM_STATS()
};
-static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
- sizeof(struct kvm_vm_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vm_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -85,8 +83,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, vz_cpucfg_exits),
#endif
};
-static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
- sizeof(struct kvm_vcpu_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vcpu_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c
index 6d1f68cf4edf..1bfd1b501d82 100644
--- a/arch/mips/kvm/mmu.c
+++ b/arch/mips/kvm/mmu.c
@@ -442,7 +442,7 @@ static int kvm_mips_mkold_gpa_pt(struct kvm *kvm, gfn_t start_gfn,
bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
{
kvm_mips_flush_gpa_pt(kvm, range->start, range->end);
- return 1;
+ return true;
}
bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
@@ -486,7 +486,7 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
pte_t *gpa_pte = kvm_mips_pte_for_gpa(kvm, NULL, gpa);
if (!gpa_pte)
- return 0;
+ return false;
return pte_young(*gpa_pte);
}
diff --git a/arch/mips/kvm/vz.c b/arch/mips/kvm/vz.c
index 43cad10b877d..4adca5abbc72 100644
--- a/arch/mips/kvm/vz.c
+++ b/arch/mips/kvm/vz.c
@@ -388,7 +388,6 @@ static void _kvm_vz_restore_htimer(struct kvm_vcpu *vcpu,
u32 compare, u32 cause)
{
u32 start_count, after_count;
- ktime_t freeze_time;
unsigned long flags;
/*
@@ -396,7 +395,7 @@ static void _kvm_vz_restore_htimer(struct kvm_vcpu *vcpu,
* this with interrupts disabled to avoid latency.
*/
local_irq_save(flags);
- freeze_time = kvm_mips_freeze_hrtimer(vcpu, &start_count);
+ kvm_mips_freeze_hrtimer(vcpu, &start_count);
write_c0_gtoffset(start_count - read_c0_count());
local_irq_restore(flags);
diff --git a/arch/mips/loongson2ef/common/Makefile b/arch/mips/loongson2ef/common/Makefile
index d5ab3e543ea3..30ea8b5ca685 100644
--- a/arch/mips/loongson2ef/common/Makefile
+++ b/arch/mips/loongson2ef/common/Makefile
@@ -4,12 +4,14 @@
#
obj-y += setup.o init.o env.o time.o reset.o irq.o \
- bonito-irq.o mem.o machtype.o platform.o serial.o
+ bonito-irq.o mem.o machtype.o platform.o
obj-$(CONFIG_PCI) += pci.o
#
# Serial port support
#
+obj-$(CONFIG_LOONGSON_UART_BASE) += serial.o
+obj-$(CONFIG_EARLY_PRINTK) += serial.o
obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
obj-$(CONFIG_LOONGSON_MC146818) += rtc.o
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index 8ae181e08311..ec2ae501539a 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -30,7 +30,7 @@
unsigned long long cache_err_dcache[NR_CPUS];
EXPORT_SYMBOL_GPL(cache_err_dcache);
-/**
+/*
* Octeon automatically flushes the dcache on tlb changes, so
* from Linux's viewpoint it acts much like a physically
* tagged cache. No flushing is needed
@@ -56,8 +56,8 @@ static void local_octeon_flush_icache_range(unsigned long start,
}
/**
- * Flush caches as necessary for all cores affected by a
- * vma. If no vma is supplied, all cores are flushed.
+ * octeon_flush_icache_all_cores - Flush caches as necessary for all cores
+ * affected by a vma. If no vma is supplied, all cores are flushed.
*
* @vma: VMA to flush or NULL to flush all icaches.
*/
@@ -92,7 +92,7 @@ static void octeon_flush_icache_all_cores(struct vm_area_struct *vma)
}
-/**
+/*
* Called to flush the icache on all cores
*/
static void octeon_flush_icache_all(void)
@@ -102,8 +102,7 @@ static void octeon_flush_icache_all(void)
/**
- * Called to flush all memory associated with a memory
- * context.
+ * octeon_flush_cache_mm - flush all memory associated with a memory context.
*
* @mm: Memory context to flush
*/
@@ -116,7 +115,7 @@ static void octeon_flush_cache_mm(struct mm_struct *mm)
}
-/**
+/*
* Flush a range of kernel addresses out of the icache
*
*/
@@ -127,11 +126,11 @@ static void octeon_flush_icache_range(unsigned long start, unsigned long end)
/**
- * Flush a range out of a vma
+ * octeon_flush_cache_range - Flush a range out of a vma
*
* @vma: VMA to flush
- * @start:
- * @end:
+ * @start: beginning address for flush
+ * @end: ending address for flush
*/
static void octeon_flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
@@ -142,11 +141,11 @@ static void octeon_flush_cache_range(struct vm_area_struct *vma,
/**
- * Flush a specific page of a vma
+ * octeon_flush_cache_page - Flush a specific page of a vma
*
* @vma: VMA to flush page for
* @page: Page to flush
- * @pfn:
+ * @pfn: Page frame number
*/
static void octeon_flush_cache_page(struct vm_area_struct *vma,
unsigned long page, unsigned long pfn)
@@ -160,7 +159,7 @@ static void octeon_flush_kernel_vmap_range(unsigned long vaddr, int size)
BUG();
}
-/**
+/*
* Probe Octeon's caches
*
*/
@@ -256,7 +255,7 @@ static void octeon_cache_error_setup(void)
set_handler(0x100, &except_vec2_octeon, 0x80);
}
-/**
+/*
* Setup the Octeon cache flush routines
*
*/
@@ -341,7 +340,7 @@ asmlinkage void cache_parity_error_octeon_recoverable(void)
co_cache_error_call_notifiers(0);
}
-/**
+/*
* Called when the the exception is not recoverable
*/
diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c
index 0ddf03df6268..f451268f6c38 100644
--- a/arch/mips/mti-malta/malta-dtshim.c
+++ b/arch/mips/mti-malta/malta-dtshim.c
@@ -22,7 +22,7 @@
#define ROCIT_CONFIG_GEN1_MEMMAP_SHIFT 8
#define ROCIT_CONFIG_GEN1_MEMMAP_MASK (0xf << 8)
-static unsigned char fdt_buf[16 << 10] __initdata;
+static unsigned char fdt_buf[16 << 10] __initdata __aligned(8);
/* determined physical memory size, not overridden by command line args */
extern unsigned long physical_memsize;
diff --git a/arch/mips/netlogic/xlr/fmn-config.c b/arch/mips/netlogic/xlr/fmn-config.c
index c7622c6e5f67..15483537e8cf 100644
--- a/arch/mips/netlogic/xlr/fmn-config.c
+++ b/arch/mips/netlogic/xlr/fmn-config.c
@@ -103,18 +103,19 @@ static void check_credit_distribution(void)
}
/**
- * Configure bucket size and credits for a device. 'size' is the size of
- * the buckets for the device. This size is distributed among all the CPUs
- * so that all of them can send messages to the device.
- *
- * The device is also given 'cpu_credits' to send messages to the CPUs
- *
+ * setup_fmn_cc - Configure bucket size and credits for a device.
* @dev_info: FMN information structure for each devices
* @start_stn_id: Starting station id of dev_info
* @end_stn_id: End station id of dev_info
* @num_buckets: Total number of buckets for den_info
* @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
* @size: Size of the each buckets in the device station
+ *
+ * 'size' is the size of the buckets for the device. This size is
+ * distributed among all the CPUs
+ * so that all of them can send messages to the device.
+ *
+ * The device is also given 'cpu_credits' to send messages to the CPUs
*/
static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
int end_stn_id, int num_buckets, int cpu_credits, int size)
@@ -174,6 +175,8 @@ static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
}
/**
+ * xlr_board_info_setup - Setup FMN details
+ *
* Setup the FMN details for each devices according to the device available
* in each variant of XLR/XLS processor
*/
diff --git a/arch/mips/pistachio/Kconfig b/arch/mips/pistachio/Kconfig
deleted file mode 100644
index 9a0e06c95184..000000000000
--- a/arch/mips/pistachio/Kconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config PISTACHIO_GPTIMER_CLKSRC
- bool "Enable General Purpose Timer based clocksource"
- depends on MACH_PISTACHIO
- select CLKSRC_PISTACHIO
- select MIPS_EXTERNAL_TIMER
- help
- This option enables a clocksource driver based on a Pistachio
- SoC General Purpose external timer.
-
- If you want to enable the CPUFreq, you need to enable
- this option.
-
- If you don't want to enable CPUFreq, you can leave this disabled.
diff --git a/arch/mips/pistachio/Makefile b/arch/mips/pistachio/Makefile
deleted file mode 100644
index 66f4af17fb66..000000000000
--- a/arch/mips/pistachio/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-y += init.o irq.o time.o
diff --git a/arch/mips/pistachio/Platform b/arch/mips/pistachio/Platform
deleted file mode 100644
index c59de86dbddf..000000000000
--- a/arch/mips/pistachio/Platform
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# IMG Pistachio SoC
-#
-load-$(CONFIG_MACH_PISTACHIO) += 0xffffffff80400000
-zload-$(CONFIG_MACH_PISTACHIO) += 0xffffffff81000000
-all-$(CONFIG_MACH_PISTACHIO) := uImage.gz
diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c
deleted file mode 100644
index e0bacfc3c6b4..000000000000
--- a/arch/mips/pistachio/init.c
+++ /dev/null
@@ -1,125 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Pistachio platform setup
- *
- * Copyright (C) 2014 Google, Inc.
- * Copyright (C) 2016 Imagination Technologies
- */
-
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-
-#include <asm/cacheflush.h>
-#include <asm/fw/fw.h>
-#include <asm/mips-boards/generic.h>
-#include <asm/mips-cps.h>
-#include <asm/prom.h>
-#include <asm/smp-ops.h>
-#include <asm/traps.h>
-
-/*
- * Core revision register decoding
- * Bits 23 to 20: Major rev
- * Bits 15 to 8: Minor rev
- * Bits 7 to 0: Maintenance rev
- */
-#define PISTACHIO_CORE_REV_REG 0xB81483D0
-#define PISTACHIO_CORE_REV_A1 0x00100006
-#define PISTACHIO_CORE_REV_B0 0x00100106
-
-const char *get_system_type(void)
-{
- u32 core_rev;
- const char *sys_type;
-
- core_rev = __raw_readl((const void *)PISTACHIO_CORE_REV_REG);
-
- switch (core_rev) {
- case PISTACHIO_CORE_REV_B0:
- sys_type = "IMG Pistachio SoC (B0)";
- break;
-
- case PISTACHIO_CORE_REV_A1:
- sys_type = "IMG Pistachio SoC (A1)";
- break;
-
- default:
- sys_type = "IMG Pistachio SoC";
- break;
- }
-
- return sys_type;
-}
-
-void __init *plat_get_fdt(void)
-{
- if (fw_arg0 != -2)
- panic("Device-tree not present");
- return (void *)fw_arg1;
-}
-
-void __init plat_mem_setup(void)
-{
- __dt_setup_arch(plat_get_fdt());
-}
-
-#define DEFAULT_CPC_BASE_ADDR 0x1bde0000
-#define DEFAULT_CDMM_BASE_ADDR 0x1bdd0000
-
-phys_addr_t mips_cpc_default_phys_base(void)
-{
- return DEFAULT_CPC_BASE_ADDR;
-}
-
-phys_addr_t mips_cdmm_phys_base(void)
-{
- return DEFAULT_CDMM_BASE_ADDR;
-}
-
-static void __init mips_nmi_setup(void)
-{
- void *base;
-
- base = cpu_has_veic ?
- (void *)(CAC_BASE + 0xa80) :
- (void *)(CAC_BASE + 0x380);
- memcpy(base, except_vec_nmi, 0x80);
- flush_icache_range((unsigned long)base,
- (unsigned long)base + 0x80);
-}
-
-static void __init mips_ejtag_setup(void)
-{
- void *base;
- extern char except_vec_ejtag_debug[];
-
- base = cpu_has_veic ?
- (void *)(CAC_BASE + 0xa00) :
- (void *)(CAC_BASE + 0x300);
- memcpy(base, except_vec_ejtag_debug, 0x80);
- flush_icache_range((unsigned long)base,
- (unsigned long)base + 0x80);
-}
-
-void __init prom_init(void)
-{
- board_nmi_handler_setup = mips_nmi_setup;
- board_ejtag_handler_setup = mips_ejtag_setup;
-
- mips_cm_probe();
- mips_cpc_probe();
- register_cps_smp_ops();
-
- pr_info("SoC Type: %s\n", get_system_type());
-}
-
-void __init device_tree_init(void)
-{
- if (!initial_boot_params)
- return;
-
- unflatten_and_copy_device_tree();
-}
diff --git a/arch/mips/pistachio/irq.c b/arch/mips/pistachio/irq.c
deleted file mode 100644
index 437c3101ac45..000000000000
--- a/arch/mips/pistachio/irq.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Pistachio IRQ setup
- *
- * Copyright (C) 2014 Google, Inc.
- */
-
-#include <linux/init.h>
-#include <linux/irqchip.h>
-#include <linux/kernel.h>
-
-#include <asm/cpu-features.h>
-#include <asm/irq_cpu.h>
-
-void __init arch_init_irq(void)
-{
- pr_info("EIC is %s\n", cpu_has_veic ? "on" : "off");
- pr_info("VINT is %s\n", cpu_has_vint ? "on" : "off");
-
- if (!cpu_has_veic)
- mips_cpu_irq_init();
-
- irqchip_init();
-}
diff --git a/arch/mips/pistachio/time.c b/arch/mips/pistachio/time.c
deleted file mode 100644
index de64751dec40..000000000000
--- a/arch/mips/pistachio/time.c
+++ /dev/null
@@ -1,55 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Pistachio clocksource/timer setup
- *
- * Copyright (C) 2014 Google, Inc.
- */
-
-#include <linux/clk.h>
-#include <linux/clocksource.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/of_clk.h>
-
-#include <asm/mips-cps.h>
-#include <asm/time.h>
-
-unsigned int get_c0_compare_int(void)
-{
- return gic_get_c0_compare_int();
-}
-
-int get_c0_perfcount_int(void)
-{
- return gic_get_c0_perfcount_int();
-}
-EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
-
-int get_c0_fdc_int(void)
-{
- return gic_get_c0_fdc_int();
-}
-
-void __init plat_time_init(void)
-{
- struct device_node *np;
- struct clk *clk;
-
- of_clk_init(NULL);
- timer_probe();
-
- np = of_get_cpu_node(0, NULL);
- if (!np) {
- pr_err("Failed to get CPU node\n");
- return;
- }
-
- clk = of_clk_get(np, 0);
- if (IS_ERR(clk)) {
- pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
- return;
- }
-
- mips_hpt_frequency = clk_get_rate(clk) / 2;
- clk_put(clk);
-}
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
index de0768a49ee8..dfc52f661ad0 100644
--- a/arch/mips/sgi-ip22/ip22-gio.c
+++ b/arch/mips/sgi-ip22/ip22-gio.c
@@ -143,14 +143,13 @@ static int gio_device_probe(struct device *dev)
return error;
}
-static int gio_device_remove(struct device *dev)
+static void gio_device_remove(struct device *dev)
{
struct gio_device *gio_dev = to_gio_device(dev);
struct gio_driver *drv = to_gio_driver(dev->driver);
if (dev->driver && drv->remove)
drv->remove(gio_dev);
- return 0;
}
static void gio_device_shutdown(struct device *dev)
diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
index 62313902d75d..aea26e739543 100644
--- a/arch/nds32/Kconfig
+++ b/arch/nds32/Kconfig
@@ -26,8 +26,6 @@ config NDS32
select GENERIC_LIB_LSHRDI3
select GENERIC_LIB_MULDI3
select GENERIC_LIB_UCMPDI2
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL
select HANDLE_DOMAIN_IRQ
select HAVE_ARCH_TRACEHOOK
@@ -48,6 +46,7 @@ config NDS32
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_DYNAMIC_FTRACE
select SET_FS
+ select TRACE_IRQFLAGS_SUPPORT
help
Andes(nds32) Linux support.
@@ -64,9 +63,6 @@ config GENERIC_LOCKBREAK
def_bool y
depends on PREEMPTION
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config STACKTRACE_SUPPORT
def_bool y
diff --git a/arch/nds32/include/asm/cacheflush.h b/arch/nds32/include/asm/cacheflush.h
index 7d6824f7c0e8..c2a222ebfa2a 100644
--- a/arch/nds32/include/asm/cacheflush.h
+++ b/arch/nds32/include/asm/cacheflush.h
@@ -36,8 +36,7 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
void flush_anon_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr);
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-void flush_kernel_dcache_page(struct page *page);
+#define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1
void flush_kernel_vmap_range(void *addr, int size);
void invalidate_kernel_vmap_range(void *addr, int size);
#define flush_dcache_mmap_lock(mapping) xa_lock_irq(&(mapping)->i_pages)
diff --git a/arch/nds32/mm/cacheflush.c b/arch/nds32/mm/cacheflush.c
index ad5344ef5d33..07aac65d1cab 100644
--- a/arch/nds32/mm/cacheflush.c
+++ b/arch/nds32/mm/cacheflush.c
@@ -318,15 +318,6 @@ void flush_anon_page(struct vm_area_struct *vma,
local_irq_restore(flags);
}
-void flush_kernel_dcache_page(struct page *page)
-{
- unsigned long flags;
- local_irq_save(flags);
- cpu_dcache_wbinval_page((unsigned long)page_address(page));
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(flush_kernel_dcache_page);
-
void flush_kernel_vmap_range(void *addr, int size)
{
unsigned long flags;
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index c24955c81c92..33fd06f5fa41 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -13,8 +13,6 @@ config NIOS2
select GENERIC_CPU_DEVICES
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_KGDB
select IRQ_DOMAIN
@@ -43,9 +41,6 @@ config NO_IOPORT_MAP
config FPU
def_bool n
-config TRACE_IRQFLAGS_SUPPORT
- def_bool n
-
menu "Kernel features"
source "kernel/Kconfig.hz"
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 591acc5990dc..e804026b4797 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -25,8 +25,6 @@ config OPENRISC
select HAVE_UID16
select GENERIC_ATOMIC64
select GENERIC_CLOCKEVENTS_BROADCAST
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select GENERIC_SMP_IDLE_THREAD
select MODULES_USE_ELF_RELA
select HAVE_DEBUG_STACKOVERFLOW
@@ -39,6 +37,7 @@ config OPENRISC
select GENERIC_IRQ_MULTI_HANDLER
select MMU_GATHER_NO_RANGE if MMU
select SET_FS
+ select TRACE_IRQFLAGS_SUPPORT
config CPU_BIG_ENDIAN
def_bool y
@@ -52,9 +51,6 @@ config GENERIC_HWEIGHT
config NO_IOPORT_MAP
def_bool y
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
# For now, use generic checksum functions
#These can be reimplemented in assembly later if so inclined
config GENERIC_CSUM
diff --git a/arch/openrisc/boot/dts/or1klitex.dts b/arch/openrisc/boot/dts/or1klitex.dts
index 3f9867aa3844..91c7173c50e6 100644
--- a/arch/openrisc/boot/dts/or1klitex.dts
+++ b/arch/openrisc/boot/dts/or1klitex.dts
@@ -41,10 +41,10 @@
interrupt-controller;
};
- serial0: serial@e0002000 {
+ serial0: serial@e0006800 {
device_type = "serial";
compatible = "litex,liteuart";
- reg = <0xe0002000 0x100>;
+ reg = <0xe0006800 0x100>;
};
soc_ctrl0: soc_controller@e0000000 {
@@ -52,4 +52,13 @@
reg = <0xe0000000 0xc>;
status = "okay";
};
+
+ ethernet@e0001000 {
+ compatible = "litex,liteeth";
+ reg = <0xe0001000 0x7c>,
+ <0xe0001800 0x0a>,
+ <0x80000000 0x2000>;
+ reg-names = "mac", "mdio", "buffer";
+ interrupts = <2>;
+ };
};
diff --git a/arch/openrisc/configs/or1klitex_defconfig b/arch/openrisc/configs/or1klitex_defconfig
index 3c2c70d3d740..d695879a4d26 100644
--- a/arch/openrisc/configs/or1klitex_defconfig
+++ b/arch/openrisc/configs/or1klitex_defconfig
@@ -1,18 +1,24 @@
CONFIG_BLK_DEV_INITRD=y
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
-CONFIG_BUG_ON_DATA_CORRUPTION=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
CONFIG_EMBEDDED=y
+CONFIG_OPENRISC_BUILTIN_DTB="or1klitex"
CONFIG_HZ_100=y
-CONFIG_INITRAMFS_SOURCE="openrisc-rootfs.cpio.gz"
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
CONFIG_OF_OVERLAY=y
-CONFIG_OPENRISC_BUILTIN_DTB="or1klitex"
-CONFIG_PANIC_ON_OOPS=y
-CONFIG_PRINTK_TIME=y
-CONFIG_LITEX_SOC_CONTROLLER=y
+CONFIG_NETDEVICES=y
+CONFIG_LITEX_LITEETH=y
CONFIG_SERIAL_LITEUART=y
CONFIG_SERIAL_LITEUART_CONSOLE=y
-CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_TTY_PRINTK=y
+CONFIG_LITEX_SOC_CONTROLLER=y
+CONFIG_TMPFS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h
index 4ac591c9ca33..cdd657f80bfa 100644
--- a/arch/openrisc/include/asm/pgtable.h
+++ b/arch/openrisc/include/asm/pgtable.h
@@ -12,7 +12,7 @@
* et al.
*/
-/* or32 pgtable.h - macros and functions to manipulate page tables
+/* or1k pgtable.h - macros and functions to manipulate page tables
*
* Based on:
* include/asm-cris/pgtable.h
@@ -29,14 +29,14 @@
/*
* The Linux memory management assumes a three-level page table setup. On
- * or32, we use that, but "fold" the mid level into the top-level page
+ * or1k, we use that, but "fold" the mid level into the top-level page
* table. Since the MMU TLB is software loaded through an interrupt, it
* supports any page table structure, so we could have used a three-level
* setup, but for the amounts of memory we normally use, a two-level is
* probably more efficient.
*
* This file contains the functions and defines necessary to modify and use
- * the or32 page table tree.
+ * the or1k page table tree.
*/
extern void paging_init(void);
diff --git a/arch/openrisc/include/asm/setup.h b/arch/openrisc/include/asm/setup.h
new file mode 100644
index 000000000000..9acbc5deda69
--- /dev/null
+++ b/arch/openrisc/include/asm/setup.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2021 Stafford Horne
+ */
+#ifndef _ASM_OR1K_SETUP_H
+#define _ASM_OR1K_SETUP_H
+
+#include <linux/init.h>
+#include <asm-generic/setup.h>
+
+#ifndef __ASSEMBLY__
+void __init or1k_early_setup(void *fdt);
+#endif
+
+#endif /* _ASM_OR1K_SETUP_H */
diff --git a/arch/openrisc/include/asm/thread_info.h b/arch/openrisc/include/asm/thread_info.h
index 4f9d2a261455..659834ab87fa 100644
--- a/arch/openrisc/include/asm/thread_info.h
+++ b/arch/openrisc/include/asm/thread_info.h
@@ -25,7 +25,7 @@
/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
* normally, the stack is found by doing something like p + THREAD_SIZE
- * in or32, a page is 8192 bytes, which seems like a sane size
+ * in or1k, a page is 8192 bytes, which seems like a sane size
*/
#define THREAD_SIZE_ORDER 0
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index bc657e55c15f..edaa775a648e 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -326,7 +326,7 @@ EXCEPTION_ENTRY(_data_page_fault_handler)
1: l.ori r6,r0,0x0 // !write access
2:
- /* call fault.c handler in or32/mm/fault.c */
+ /* call fault.c handler in openrisc/mm/fault.c */
l.jal do_page_fault
l.nop
l.j _ret_from_exception
@@ -348,7 +348,7 @@ EXCEPTION_ENTRY(_insn_page_fault_handler)
/* r4 set be EXCEPTION_HANDLE */ // effective address of fault
l.ori r6,r0,0x0 // !write access
- /* call fault.c handler in or32/mm/fault.c */
+ /* call fault.c handler in openrisc/mm/fault.c */
l.jal do_page_fault
l.nop
l.j _ret_from_exception
@@ -547,11 +547,12 @@ EXCEPTION_ENTRY(_external_irq_handler)
l.bnf 1f // ext irq enabled, all ok.
l.nop
+#ifdef CONFIG_PRINTK
l.addi r1,r1,-0x8
l.movhi r3,hi(42f)
l.ori r3,r3,lo(42f)
l.sw 0x0(r1),r3
- l.jal printk
+ l.jal _printk
l.sw 0x4(r1),r4
l.addi r1,r1,0x8
@@ -560,6 +561,7 @@ EXCEPTION_ENTRY(_external_irq_handler)
.string "\n\rESR interrupt bug: in _external_irq_handler (ESR %x)\n\r"
.align 4
.previous
+#endif
l.ori r4,r4,SPR_SR_IEE // fix the bug
// l.sw PT_SR(r1),r4
@@ -681,8 +683,8 @@ _syscall_debug:
l.sw -4(r1),r27
l.sw -8(r1),r11
l.addi r1,r1,-8
- l.movhi r27,hi(printk)
- l.ori r27,r27,lo(printk)
+ l.movhi r27,hi(_printk)
+ l.ori r27,r27,lo(_printk)
l.jalr r27
l.nop
l.addi r1,r1,8
diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S
index af355e3f4619..15f1b38dfe03 100644
--- a/arch/openrisc/kernel/head.S
+++ b/arch/openrisc/kernel/head.S
@@ -599,7 +599,7 @@ flush_tlb:
l.jal _flush_tlb
l.nop
-/* The MMU needs to be enabled before or32_early_setup is called */
+/* The MMU needs to be enabled before or1k_early_setup is called */
enable_mmu:
/*
@@ -641,9 +641,9 @@ enable_mmu:
/* magic number mismatch, set fdt pointer to null */
l.or r25,r0,r0
_fdt_found:
- /* pass fdt pointer to or32_early_setup in r3 */
+ /* pass fdt pointer to or1k_early_setup in r3 */
l.or r3,r0,r25
- LOAD_SYMBOL_2_GPR(r24, or32_early_setup)
+ LOAD_SYMBOL_2_GPR(r24, or1k_early_setup)
l.jalr r24
l.nop
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
index eb62429681fc..b0698d9ce14f 100644
--- a/arch/openrisc/kernel/process.c
+++ b/arch/openrisc/kernel/process.c
@@ -14,8 +14,6 @@
*/
#define __KERNEL_SYSCALLS__
-#include <stdarg.h>
-
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c
index 8ae2da6ac097..0cd04d936a7a 100644
--- a/arch/openrisc/kernel/setup.c
+++ b/arch/openrisc/kernel/setup.c
@@ -209,7 +209,8 @@ void __init setup_cpuinfo(void)
}
/**
- * or32_early_setup
+ * or1k_early_setup
+ * @fdt: pointer to the start of the device tree in memory or NULL
*
* Handles the pointer to the device tree that this kernel is to use
* for establishing the available platform devices.
@@ -217,7 +218,7 @@ void __init setup_cpuinfo(void)
* Falls back on built-in device tree in case null pointer is passed.
*/
-void __init or32_early_setup(void *fdt)
+void __init or1k_early_setup(void *fdt)
{
if (fdt)
pr_info("FDT at %p\n", fdt);
@@ -243,21 +244,6 @@ static inline unsigned long extract_value(unsigned long reg, unsigned long mask)
return mask & reg;
}
-void __init detect_unit_config(unsigned long upr, unsigned long mask,
- char *text, void (*func) (void))
-{
- if (text != NULL)
- printk("%s", text);
-
- if (upr & mask) {
- if (func != NULL)
- func();
- else
- printk("present\n");
- } else
- printk("not present\n");
-}
-
/*
* calibrate_delay
*
diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
index 79775aaa6baa..53327406b483 100644
--- a/arch/openrisc/lib/Makefile
+++ b/arch/openrisc/lib/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
#
-# Makefile for or32 specific library files..
+# Makefile for or1k specific library files..
#
obj-y := delay.o string.o memset.o memcpy.o
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
index ca97d9baab51..c730d1a51686 100644
--- a/arch/openrisc/mm/fault.c
+++ b/arch/openrisc/mm/fault.c
@@ -28,7 +28,7 @@ unsigned long pte_misses; /* updated by do_page_fault() */
unsigned long pte_errors; /* updated by do_page_fault() */
/* __PHX__ :: - check the vmalloc_fault in do_page_fault()
- * - also look into include/asm-or32/mmu_context.h
+ * - also look into include/asm/mmu_context.h
*/
volatile pgd_t *current_pgd[NR_CPUS];
diff --git a/arch/parisc/Kbuild b/arch/parisc/Kbuild
index a4e40e534e6a..3c068b700a81 100644
--- a/arch/parisc/Kbuild
+++ b/arch/parisc/Kbuild
@@ -1 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-y += mm/ kernel/ math-emu/
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 4f8c1fbf8f2f..3001a7d8fc76 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -10,6 +10,7 @@ config PARISC
select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_HAS_UBSAN_SANITIZE_ALL
+ select ARCH_HAS_STRNLEN_USER
select ARCH_NO_SG_CHAIN
select ARCH_SUPPORTS_HUGETLBFS if PA20
select ARCH_SUPPORTS_MEMORY_FAILURE
@@ -33,7 +34,6 @@ config PARISC
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select GENERIC_SMP_IDLE_THREAD
select GENERIC_CPU_DEVICES
- select GENERIC_STRNCPY_FROM_USER
select GENERIC_LIB_DEVMEM_IS_ALLOWED
select SYSCTL_ARCH_UNALIGN_ALLOW
select SYSCTL_EXCEPTION_TRACE
@@ -66,6 +66,7 @@ config PARISC
select HAVE_DYNAMIC_FTRACE_WITH_REGS
select HAVE_SOFTIRQ_ON_OWN_STACK if IRQSTACKS
select SET_FS
+ select TRACE_IRQFLAGS_SUPPORT
help
The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
index 1478ded0e247..f66554cd5c45 100644
--- a/arch/parisc/Kconfig.debug
+++ b/arch/parisc/Kconfig.debug
@@ -1,4 +1 @@
# SPDX-License-Identifier: GPL-2.0
-
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index aed8ea29268b..fcde3ffa0221 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -25,18 +25,18 @@ CHECKFLAGS += -D__hppa__=1
ifdef CONFIG_64BIT
UTS_MACHINE := parisc64
CHECKFLAGS += -D__LP64__=1
-CC_ARCHES = hppa64
LD_BFD := elf64-hppa-linux
else # 32-bit
-CC_ARCHES = hppa hppa2.0 hppa1.1
LD_BFD := elf32-hppa-linux
endif
# select defconfig based on actual architecture
-ifeq ($(shell uname -m),parisc64)
+ifeq ($(ARCH),parisc64)
KBUILD_DEFCONFIG := generic-64bit_defconfig
+ CC_ARCHES := hppa64
else
KBUILD_DEFCONFIG := generic-32bit_defconfig
+ CC_ARCHES := hppa hppa2.0 hppa1.1
endif
export LD_BFD
@@ -111,9 +111,6 @@ KBUILD_CFLAGS += $(cflags-y)
LIBGCC := $(shell $(CC) -print-libgcc-file-name)
export LIBGCC
-kernel-y := mm/ kernel/ math-emu/
-
-core-y += $(addprefix arch/parisc/, $(kernel-y))
libs-y += arch/parisc/lib/ $(LIBGCC)
boot := arch/parisc/boot
diff --git a/arch/parisc/boot/Makefile b/arch/parisc/boot/Makefile
index 61f44142cfe1..b873ee4720ca 100644
--- a/arch/parisc/boot/Makefile
+++ b/arch/parisc/boot/Makefile
@@ -15,7 +15,3 @@ $(obj)/bzImage: $(obj)/compressed/vmlinux FORCE
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
-
-install: $(CONFIGURE) $(obj)/bzImage
- sh -x $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/bzImage \
- System.map "$(INSTALL_PATH)"
diff --git a/arch/parisc/boot/compressed/misc.c b/arch/parisc/boot/compressed/misc.c
index 2d395998f524..7ee49f5881d1 100644
--- a/arch/parisc/boot/compressed/misc.c
+++ b/arch/parisc/boot/compressed/misc.c
@@ -26,7 +26,7 @@
extern char input_data[];
extern int input_len;
/* output_len is inserted by the linker possibly at an unaligned address */
-extern __le32 output_len __aligned(1);
+extern char output_len;
extern char _text, _end;
extern char _bss, _ebss;
extern char _startcode_end;
diff --git a/arch/parisc/boot/install.sh b/arch/parisc/boot/install.sh
deleted file mode 100644
index 8f7c365fad83..000000000000
--- a/arch/parisc/boot/install.sh
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/sh
-#
-# arch/parisc/install.sh, derived from arch/i386/boot/install.sh
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1995 by Linus Torvalds
-#
-# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
-#
-# "make install" script for i386 architecture
-#
-# Arguments:
-# $1 - kernel version
-# $2 - kernel image file
-# $3 - kernel map file
-# $4 - default install path (blank if root directory)
-#
-
-verify () {
- if [ ! -f "$1" ]; then
- echo "" 1>&2
- echo " *** Missing file: $1" 1>&2
- echo ' *** You need to run "make" before "make install".' 1>&2
- echo "" 1>&2
- exit 1
- fi
-}
-
-# Make sure the files actually exist
-
-verify "$2"
-verify "$3"
-
-# User may have a custom install script
-
-if [ -n "${INSTALLKERNEL}" ]; then
- if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
- if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
-fi
-
-# Default install
-
-if [ "$(basename $2)" = "zImage" ]; then
-# Compressed install
- echo "Installing compressed kernel"
- base=vmlinuz
-else
-# Normal install
- echo "Installing normal kernel"
- base=vmlinux
-fi
-
-if [ -f $4/$base-$1 ]; then
- mv $4/$base-$1 $4/$base-$1.old
-fi
-cat $2 > $4/$base-$1
-
-# Install system map file
-if [ -f $4/System.map-$1 ]; then
- mv $4/System.map-$1 $4/System.map-$1.old
-fi
-cp $3 $4/System.map-$1
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h
index 99663fc1f997..eef0096db5f8 100644
--- a/arch/parisc/include/asm/cacheflush.h
+++ b/arch/parisc/include/asm/cacheflush.h
@@ -36,16 +36,12 @@ void flush_cache_all_local(void);
void flush_cache_all(void);
void flush_cache_mm(struct mm_struct *mm);
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
void flush_kernel_dcache_page_addr(void *addr);
-static inline void flush_kernel_dcache_page(struct page *page)
-{
- flush_kernel_dcache_page_addr(page_address(page));
-}
#define flush_kernel_dcache_range(start,size) \
flush_kernel_dcache_range_asm((start), (start)+(size));
+#define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1
void flush_kernel_vmap_range(void *vaddr, int size);
void invalidate_kernel_vmap_range(void *vaddr, int size);
@@ -59,7 +55,7 @@ extern void flush_dcache_page(struct page *page);
#define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages)
#define flush_icache_page(vma,page) do { \
- flush_kernel_dcache_page(page); \
+ flush_kernel_dcache_page_addr(page_address(page)); \
flush_kernel_icache_page(page_address(page)); \
} while (0)
diff --git a/arch/parisc/include/asm/parisc-device.h b/arch/parisc/include/asm/parisc-device.h
index d02d144c6012..4de3b391d812 100644
--- a/arch/parisc/include/asm/parisc-device.h
+++ b/arch/parisc/include/asm/parisc-device.h
@@ -34,8 +34,8 @@ struct parisc_driver {
struct parisc_driver *next;
char *name;
const struct parisc_device_id *id_table;
- int (*probe) (struct parisc_device *dev); /* New device discovered */
- int (*remove) (struct parisc_device *dev);
+ int (*probe)(struct parisc_device *dev); /* New device discovered */
+ void (*remove)(struct parisc_device *dev);
struct device_driver drv;
};
diff --git a/arch/parisc/include/asm/pgalloc.h b/arch/parisc/include/asm/pgalloc.h
index 6a7e98e71f1d..54b63374579b 100644
--- a/arch/parisc/include/asm/pgalloc.h
+++ b/arch/parisc/include/asm/pgalloc.h
@@ -48,15 +48,15 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
{
pmd_t *pmd;
- pmd = (pmd_t *)__get_free_pages(GFP_PGTABLE_KERNEL, PMD_ORDER);
+ pmd = (pmd_t *)__get_free_pages(GFP_PGTABLE_KERNEL, PMD_TABLE_ORDER);
if (likely(pmd))
- memset ((void *)pmd, 0, PAGE_SIZE << PMD_ORDER);
+ memset ((void *)pmd, 0, PAGE_SIZE << PMD_TABLE_ORDER);
return pmd;
}
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
{
- free_pages((unsigned long)pmd, PMD_ORDER);
+ free_pages((unsigned long)pmd, PMD_TABLE_ORDER);
}
#endif
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index 43937af127b1..7badd872f05a 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -112,7 +112,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
#define KERNEL_INITIAL_SIZE (1 << KERNEL_INITIAL_ORDER)
#if CONFIG_PGTABLE_LEVELS == 3
-#define PMD_ORDER 1
+#define PMD_TABLE_ORDER 1
#define PGD_ORDER 0
#else
#define PGD_ORDER 1
@@ -131,7 +131,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
#define PMD_SHIFT (PLD_SHIFT + BITS_PER_PTE)
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
-#define BITS_PER_PMD (PAGE_SHIFT + PMD_ORDER - BITS_PER_PMD_ENTRY)
+#define BITS_PER_PMD (PAGE_SHIFT + PMD_TABLE_ORDER - BITS_PER_PMD_ENTRY)
#define PTRS_PER_PMD (1UL << BITS_PER_PMD)
#else
#define BITS_PER_PMD 0
diff --git a/arch/parisc/include/uapi/asm/swab.h b/arch/parisc/include/uapi/asm/swab.h
deleted file mode 100644
index 35fb2d1bfbbd..000000000000
--- a/arch/parisc/include/uapi/asm/swab.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _PARISC_SWAB_H
-#define _PARISC_SWAB_H
-
-#include <asm/bitsperlong.h>
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-#define __SWAB_64_THRU_32__
-
-static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
-{
- __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */
- "shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */
- : "=r" (x)
- : "0" (x));
- return x;
-}
-#define __arch_swab16 __arch_swab16
-
-static inline __attribute_const__ __u32 __arch_swab24(__u32 x)
-{
- __asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */
- "dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */
- "shd %%r0, %0, 8, %0" /* shift 0000cbab -> 0cba */
- : "=r" (x)
- : "0" (x));
- return x;
-}
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
-{
- unsigned int temp;
- __asm__("shd %0, %0, 16, %1\n\t" /* shift abcdabcd -> cdab */
- "dep %1, 15, 8, %1\n\t" /* deposit cdab -> cbab */
- "shd %0, %1, 8, %0" /* shift abcdcbab -> dcba */
- : "=r" (x), "=&r" (temp)
- : "0" (x));
- return x;
-}
-#define __arch_swab32 __arch_swab32
-
-#if __BITS_PER_LONG > 32
-/*
-** From "PA-RISC 2.0 Architecture", HP Professional Books.
-** See Appendix I page 8 , "Endian Byte Swapping".
-**
-** Pretty cool algorithm: (* == zero'd bits)
-** PERMH 01234567 -> 67452301 into %0
-** HSHL 67452301 -> 7*5*3*1* into %1
-** HSHR 67452301 -> *6*4*2*0 into %0
-** OR %0 | %1 -> 76543210 into %0 (all done!)
-*/
-static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
-{
- __u64 temp;
- __asm__("permh,3210 %0, %0\n\t"
- "hshl %0, 8, %1\n\t"
- "hshr,u %0, 8, %0\n\t"
- "or %1, %0, %0"
- : "=r" (x), "=&r" (temp)
- : "0" (x));
- return x;
-}
-#define __arch_swab64 __arch_swab64
-#endif /* __BITS_PER_LONG > 32 */
-
-#endif /* _PARISC_SWAB_H */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 86a1a63563fd..39e02227e231 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -334,7 +334,7 @@ void flush_dcache_page(struct page *page)
return;
}
- flush_kernel_dcache_page(page);
+ flush_kernel_dcache_page_addr(page_address(page));
if (!mapping)
return;
@@ -375,7 +375,6 @@ EXPORT_SYMBOL(flush_dcache_page);
/* Defined in arch/parisc/kernel/pacache.S */
EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
-EXPORT_SYMBOL(flush_kernel_dcache_page_asm);
EXPORT_SYMBOL(flush_data_cache_local);
EXPORT_SYMBOL(flush_kernel_icache_range_asm);
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 80fa0650736b..776d624a7207 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -133,14 +133,13 @@ static int parisc_driver_probe(struct device *dev)
return rc;
}
-static int __exit parisc_driver_remove(struct device *dev)
+static void __exit parisc_driver_remove(struct device *dev)
{
struct parisc_device *pa_dev = to_parisc_device(dev);
struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
+
if (pa_drv->remove)
pa_drv->remove(pa_dev);
-
- return 0;
}
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 665b70086685..7034227dbdf3 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -51,7 +51,7 @@
* prumpf 991016
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 39ccad063533..2661cdd256ae 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -138,6 +138,7 @@ static struct tty_driver *pdc_console_tty_driver;
static int __init pdc_console_tty_driver_init(void)
{
+ struct tty_driver *driver;
int err;
/* Check if the console driver is still registered.
@@ -160,31 +161,32 @@ static int __init pdc_console_tty_driver_init(void)
printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
pdc_cons.flags &= ~CON_BOOT;
- pdc_console_tty_driver = alloc_tty_driver(1);
-
- if (!pdc_console_tty_driver)
- return -ENOMEM;
+ driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_RESET_TERMIOS);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
tty_port_init(&tty_port);
- pdc_console_tty_driver->driver_name = "pdc_cons";
- pdc_console_tty_driver->name = "ttyB";
- pdc_console_tty_driver->major = MUX_MAJOR;
- pdc_console_tty_driver->minor_start = 0;
- pdc_console_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
- pdc_console_tty_driver->init_termios = tty_std_termios;
- pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_RESET_TERMIOS;
- tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops);
- tty_port_link_device(&tty_port, pdc_console_tty_driver, 0);
-
- err = tty_register_driver(pdc_console_tty_driver);
+ driver->driver_name = "pdc_cons";
+ driver->name = "ttyB";
+ driver->major = MUX_MAJOR;
+ driver->minor_start = 0;
+ driver->type = TTY_DRIVER_TYPE_SYSTEM;
+ driver->init_termios = tty_std_termios;
+ tty_set_operations(driver, &pdc_console_tty_ops);
+ tty_port_link_device(&tty_port, driver, 0);
+
+ err = tty_register_driver(driver);
if (err) {
printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
tty_port_destroy(&tty_port);
+ tty_driver_kref_put(driver);
return err;
}
+ pdc_console_tty_driver = driver;
+
return 0;
}
device_initcall(pdc_console_tty_driver_init);
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 184ec3c1eae4..38ec4ae81239 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -17,9 +17,6 @@
* Copyright (C) 2001-2014 Helge Deller <deller@gmx.de>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
*/
-
-#include <stdarg.h>
-
#include <linux/elf.h>
#include <linux/errno.h>
#include <linux/kernel.h>
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index fb1e94a3982b..db1a47cf424d 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -237,6 +237,12 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
#endif
usp = (regs->gr[30] & ~(0x01UL));
+#ifdef CONFIG_64BIT
+ if (is_compat_task()) {
+ /* The gcc alloca implementation leaves garbage in the upper 32 bits of sp */
+ usp = (compat_uint_t)usp;
+ }
+#endif
/*FIXME: frame_size parameter is unused, remove it. */
frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index e26187b9ab87..0bf854b70612 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -147,7 +147,7 @@
131 common quotactl sys_quotactl
132 common getpgid sys_getpgid
133 common fchdir sys_fchdir
-134 common bdflush sys_bdflush
+134 common bdflush sys_ni_syscall
135 common sysfs sys_sysfs
136 32 personality parisc_personality
136 64 personality sys_personality
@@ -444,3 +444,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c
index cd8ffc6ceadf..494ca41df05d 100644
--- a/arch/parisc/math-emu/decode_exc.c
+++ b/arch/parisc/math-emu/decode_exc.c
@@ -46,7 +46,7 @@
#define SIGNALCODE(signal, code) ((signal) << 24 | (code))
#define copropbit 1<<31-2 /* bit position 2 */
#define opclass 9 /* bits 21 & 22 */
-#define fmt 11 /* bits 19 & 20 */
+#define fmtbits 11 /* bits 19 & 20 */
#define df 13 /* bits 17 & 18 */
#define twobits 3 /* mask low-order 2 bits */
#define fivebits 31 /* mask low-order 5 bits */
@@ -57,7 +57,7 @@
#define Excp_instr(index) Instructionfield(Fpu_register[index])
#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
#define Excp_format() \
- (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)
+ (current_ir >> ((current_ir>>opclass & twobits) == 1 ? df : fmtbits) & twobits)
/* Miscellaneous definitions */
#define Fpu_sgl(index) Fpu_register[index*2]
diff --git a/arch/parisc/math-emu/fpudispatch.c b/arch/parisc/math-emu/fpudispatch.c
index 7c46969ead9b..01ed133227c2 100644
--- a/arch/parisc/math-emu/fpudispatch.c
+++ b/arch/parisc/math-emu/fpudispatch.c
@@ -310,12 +310,15 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
r1 &= ~3;
fpregs[t+3] = fpregs[r1+3];
fpregs[t+2] = fpregs[r1+2];
+ fallthrough;
case 1: /* double */
fpregs[t+1] = fpregs[r1+1];
+ fallthrough;
case 0: /* single */
fpregs[t] = fpregs[r1];
return(NOEXCEPTION);
}
+ BUG();
case 3: /* FABS */
switch (fmt) {
case 2: /* illegal */
@@ -325,13 +328,16 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
r1 &= ~3;
fpregs[t+3] = fpregs[r1+3];
fpregs[t+2] = fpregs[r1+2];
+ fallthrough;
case 1: /* double */
fpregs[t+1] = fpregs[r1+1];
+ fallthrough;
case 0: /* single */
/* copy and clear sign bit */
fpregs[t] = fpregs[r1] & 0x7fffffff;
return(NOEXCEPTION);
}
+ BUG();
case 6: /* FNEG */
switch (fmt) {
case 2: /* illegal */
@@ -341,13 +347,16 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
r1 &= ~3;
fpregs[t+3] = fpregs[r1+3];
fpregs[t+2] = fpregs[r1+2];
+ fallthrough;
case 1: /* double */
fpregs[t+1] = fpregs[r1+1];
+ fallthrough;
case 0: /* single */
/* copy and invert sign bit */
fpregs[t] = fpregs[r1] ^ 0x80000000;
return(NOEXCEPTION);
}
+ BUG();
case 7: /* FNEGABS */
switch (fmt) {
case 2: /* illegal */
@@ -357,13 +366,16 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
r1 &= ~3;
fpregs[t+3] = fpregs[r1+3];
fpregs[t+2] = fpregs[r1+2];
+ fallthrough;
case 1: /* double */
fpregs[t+1] = fpregs[r1+1];
+ fallthrough;
case 0: /* single */
/* copy and set sign bit */
fpregs[t] = fpregs[r1] | 0x80000000;
return(NOEXCEPTION);
}
+ BUG();
case 4: /* FSQRT */
switch (fmt) {
case 0:
@@ -376,6 +388,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3: /* quad not implemented */
return(MAJOR_0C_EXCP);
}
+ BUG();
case 5: /* FRND */
switch (fmt) {
case 0:
@@ -389,7 +402,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
return(MAJOR_0C_EXCP);
}
} /* end of switch (subop) */
-
+ BUG();
case 1: /* class 1 */
df = extru(ir,fpdfpos,2); /* get dest format */
if ((df & 2) || (fmt & 2)) {
@@ -419,6 +432,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3: /* dbl/dbl */
return(MAJOR_0C_EXCP);
}
+ BUG();
case 1: /* FCNVXF */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -434,6 +448,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 2: /* FCNVFX */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -449,6 +464,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 3: /* FCNVFXT */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -464,6 +480,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 5: /* FCNVUF (PA2.0 only) */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -479,6 +496,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 6: /* FCNVFU (PA2.0 only) */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -494,6 +512,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 7: /* FCNVFUT (PA2.0 only) */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -509,10 +528,11 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 4: /* undefined */
return(MAJOR_0C_EXCP);
} /* end of switch subop */
-
+ BUG();
case 2: /* class 2 */
fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
@@ -590,6 +610,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3: /* quad not implemented */
return(MAJOR_0C_EXCP);
}
+ BUG();
case 1: /* FTEST */
switch (fmt) {
case 0:
@@ -609,8 +630,10 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3:
return(MAJOR_0C_EXCP);
}
+ BUG();
} /* end of switch subop */
} /* end of else for PA1.0 & PA1.1 */
+ BUG();
case 3: /* class 3 */
r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
if (r2 == 0)
@@ -633,6 +656,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3: /* quad not implemented */
return(MAJOR_0C_EXCP);
}
+ BUG();
case 1: /* FSUB */
switch (fmt) {
case 0:
@@ -645,6 +669,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3: /* quad not implemented */
return(MAJOR_0C_EXCP);
}
+ BUG();
case 2: /* FMPY */
switch (fmt) {
case 0:
@@ -657,6 +682,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3: /* quad not implemented */
return(MAJOR_0C_EXCP);
}
+ BUG();
case 3: /* FDIV */
switch (fmt) {
case 0:
@@ -669,6 +695,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3: /* quad not implemented */
return(MAJOR_0C_EXCP);
}
+ BUG();
case 4: /* FREM */
switch (fmt) {
case 0:
@@ -681,6 +708,7 @@ decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
case 3: /* quad not implemented */
return(MAJOR_0C_EXCP);
}
+ BUG();
} /* end of class 3 switch */
} /* end of switch(class) */
@@ -736,10 +764,12 @@ u_int fpregs[];
return(MAJOR_0E_EXCP);
case 1: /* double */
fpregs[t+1] = fpregs[r1+1];
+ fallthrough;
case 0: /* single */
fpregs[t] = fpregs[r1];
return(NOEXCEPTION);
}
+ BUG();
case 3: /* FABS */
switch (fmt) {
case 2:
@@ -747,10 +777,12 @@ u_int fpregs[];
return(MAJOR_0E_EXCP);
case 1: /* double */
fpregs[t+1] = fpregs[r1+1];
+ fallthrough;
case 0: /* single */
fpregs[t] = fpregs[r1] & 0x7fffffff;
return(NOEXCEPTION);
}
+ BUG();
case 6: /* FNEG */
switch (fmt) {
case 2:
@@ -758,10 +790,12 @@ u_int fpregs[];
return(MAJOR_0E_EXCP);
case 1: /* double */
fpregs[t+1] = fpregs[r1+1];
+ fallthrough;
case 0: /* single */
fpregs[t] = fpregs[r1] ^ 0x80000000;
return(NOEXCEPTION);
}
+ BUG();
case 7: /* FNEGABS */
switch (fmt) {
case 2:
@@ -769,10 +803,12 @@ u_int fpregs[];
return(MAJOR_0E_EXCP);
case 1: /* double */
fpregs[t+1] = fpregs[r1+1];
+ fallthrough;
case 0: /* single */
fpregs[t] = fpregs[r1] | 0x80000000;
return(NOEXCEPTION);
}
+ BUG();
case 4: /* FSQRT */
switch (fmt) {
case 0:
@@ -785,6 +821,7 @@ u_int fpregs[];
case 3:
return(MAJOR_0E_EXCP);
}
+ BUG();
case 5: /* FRMD */
switch (fmt) {
case 0:
@@ -798,7 +835,7 @@ u_int fpregs[];
return(MAJOR_0E_EXCP);
}
} /* end of switch (subop */
-
+ BUG();
case 1: /* class 1 */
df = extru(ir,fpdfpos,2); /* get dest format */
/*
@@ -826,6 +863,7 @@ u_int fpregs[];
case 3: /* dbl/dbl */
return(MAJOR_0E_EXCP);
}
+ BUG();
case 1: /* FCNVXF */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -841,6 +879,7 @@ u_int fpregs[];
return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 2: /* FCNVFX */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -856,6 +895,7 @@ u_int fpregs[];
return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 3: /* FCNVFXT */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -871,6 +911,7 @@ u_int fpregs[];
return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 5: /* FCNVUF (PA2.0 only) */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -886,6 +927,7 @@ u_int fpregs[];
return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 6: /* FCNVFU (PA2.0 only) */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -901,6 +943,7 @@ u_int fpregs[];
return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 7: /* FCNVFUT (PA2.0 only) */
switch(fmt) {
case 0: /* sgl/sgl */
@@ -916,9 +959,11 @@ u_int fpregs[];
return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
&fpregs[t],status));
}
+ BUG();
case 4: /* undefined */
return(MAJOR_0C_EXCP);
} /* end of switch subop */
+ BUG();
case 2: /* class 2 */
/*
* Be careful out there.
@@ -994,6 +1039,7 @@ u_int fpregs[];
}
} /* end of switch subop */
} /* end of else for PA1.0 & PA1.1 */
+ BUG();
case 3: /* class 3 */
/*
* Be careful out there.
@@ -1026,6 +1072,7 @@ u_int fpregs[];
return(dbl_fadd(&fpregs[r1],&fpregs[r2],
&fpregs[t],status));
}
+ BUG();
case 1: /* FSUB */
switch (fmt) {
case 0:
@@ -1035,6 +1082,7 @@ u_int fpregs[];
return(dbl_fsub(&fpregs[r1],&fpregs[r2],
&fpregs[t],status));
}
+ BUG();
case 2: /* FMPY or XMPYU */
/*
* check for integer multiply (x bit set)
@@ -1071,6 +1119,7 @@ u_int fpregs[];
&fpregs[r2],&fpregs[t],status));
}
}
+ BUG();
case 3: /* FDIV */
switch (fmt) {
case 0:
@@ -1080,6 +1129,7 @@ u_int fpregs[];
return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
&fpregs[t],status));
}
+ BUG();
case 4: /* FREM */
switch (fmt) {
case 0:
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 591a4e939415..3f7d6d5b56ac 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -378,8 +378,8 @@ static void __init map_pages(unsigned long start_vaddr,
#if CONFIG_PGTABLE_LEVELS == 3
if (pud_none(*pud)) {
- pmd = memblock_alloc(PAGE_SIZE << PMD_ORDER,
- PAGE_SIZE << PMD_ORDER);
+ pmd = memblock_alloc(PAGE_SIZE << PMD_TABLE_ORDER,
+ PAGE_SIZE << PMD_TABLE_ORDER);
if (!pmd)
panic("pmd allocation failed.\n");
pud_populate(NULL, pud, pmd);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 663766fbf505..ba5b66189358 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -94,10 +94,6 @@ config STACKTRACE_SUPPORT
bool
default y
-config TRACE_IRQFLAGS_SUPPORT
- bool
- default y
-
config LOCKDEP_SUPPORT
bool
default y
@@ -123,6 +119,7 @@ config PPC
select ARCH_HAS_COPY_MC if PPC64
select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE
+ select ARCH_HAS_DEBUG_WX if STRICT_KERNEL_RWX
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_DMA_MAP_DIRECT if PPC_PSERIES
select ARCH_HAS_ELF_RANDOMIZE
@@ -182,9 +179,8 @@ config PPC
select GENERIC_IRQ_SHOW
select GENERIC_IRQ_SHOW_LEVEL
select GENERIC_PCI_IOMAP if PCI
+ select GENERIC_PTDUMP
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_TIME_NS
select HAVE_ARCH_AUDITSYSCALL
@@ -270,6 +266,7 @@ config PPC
select STRICT_KERNEL_RWX if STRICT_MODULE_RWX
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
+ select TRACE_IRQFLAGS_SUPPORT
select VIRT_TO_BUS if !PPC64
#
# Please keep this list sorted alphabetically.
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 205cd77f321f..192f0ed0097f 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -365,36 +365,6 @@ config FAIL_IOMMU
If you are unsure, say N.
-config PPC_PTDUMP
- bool "Export kernel pagetable layout to userspace via debugfs"
- depends on DEBUG_KERNEL && DEBUG_FS
- help
- This option exports the state of the kernel pagetables to a
- debugfs file. This is only useful for kernel developers who are
- working in architecture specific areas of the kernel - probably
- not a good idea to enable this feature in a production kernel.
-
- If you are unsure, say N.
-
-config PPC_DEBUG_WX
- bool "Warn on W+X mappings at boot"
- depends on PPC_PTDUMP && STRICT_KERNEL_RWX
- help
- Generate a warning if any W+X mappings are found at boot.
-
- This is useful for discovering cases where the kernel is leaving
- W+X mappings after applying NX, as such mappings are a security risk.
-
- Note that even if the check fails, your kernel is possibly
- still fine, as W+X mappings are not a security hole in
- themselves, what they do is that they make the exploitation
- of other unfixed kernel bugs easier.
-
- There is no runtime or memory usage effect of this option
- once the kernel has booted up - it's a one time check.
-
- If in doubt, say "Y".
-
config PPC_FAST_ENDIAN_SWITCH
bool "Deprecated fast endian-switch syscall"
depends on DEBUG_KERNEL && PPC_BOOK3S_64
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 6505d66f1193..aa6808e70647 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -122,6 +122,7 @@ endif
LDFLAGS_vmlinux-y := -Bstatic
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
+LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) += -z notext
LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y)
ifdef CONFIG_PPC64
@@ -407,7 +408,8 @@ endef
PHONY += install
install:
- $(Q)$(MAKE) $(build)=$(boot) install
+ sh -x $(srctree)/$(boot)/install.sh "$(KERNELRELEASE)" vmlinux \
+ System.map "$(INSTALL_PATH)"
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index e312ea802aa6..6900d0ac2421 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -341,7 +341,6 @@ image-$(CONFIG_TQM8541) += cuImage.tqm8541
image-$(CONFIG_TQM8548) += cuImage.tqm8548
image-$(CONFIG_TQM8555) += cuImage.tqm8555
image-$(CONFIG_TQM8560) += cuImage.tqm8560
-image-$(CONFIG_SBC8548) += cuImage.sbc8548
image-$(CONFIG_KSI8560) += cuImage.ksi8560
# Board ports in arch/powerpc/platform/86xx/Kconfig
@@ -444,16 +443,6 @@ $(obj)/zImage: $(addprefix $(obj)/, $(image-y))
$(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
$(Q)rm -f $@; ln $< $@
-# Only install the vmlinux
-install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
- sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)"
-
-# Install the vmlinux and other built boot targets.
-zInstall: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
- sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $^
-
-PHONY += install zInstall
-
# anything not in $(targets)
clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \
zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \
diff --git a/arch/powerpc/boot/dts/fsl/sbc8641d.dts b/arch/powerpc/boot/dts/fsl/sbc8641d.dts
deleted file mode 100644
index 3dca10acc161..000000000000
--- a/arch/powerpc/boot/dts/fsl/sbc8641d.dts
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SBC8641D Device Tree Source
- *
- * Copyright 2008 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- *
- * Based largely on the mpc8641_hpcn.dts by Freescale Semiconductor Inc.
- */
-
-/include/ "mpc8641si-pre.dtsi"
-
-/ {
- model = "SBC8641D";
- compatible = "wind,sbc8641";
-
- memory {
- device_type = "memory";
- reg = <0x00000000 0x20000000>; // 512M at 0x0
- };
-
- lbc: localbus@f8005000 {
- reg = <0xf8005000 0x1000>;
-
- ranges = <0 0 0xff000000 0x01000000 // 16MB Boot flash
- 1 0 0xf0000000 0x00010000 // 64KB EEPROM
- 2 0 0xf1000000 0x00100000 // EPLD (1MB)
- 3 0 0xe0000000 0x04000000 // 64MB LB SDRAM (CS3)
- 4 0 0xe4000000 0x04000000 // 64MB LB SDRAM (CS4)
- 6 0 0xf4000000 0x00100000 // LCD display (1MB)
- 7 0 0xe8000000 0x04000000>; // 64MB OneNAND
-
- flash@0,0 {
- compatible = "cfi-flash";
- reg = <0 0 0x01000000>;
- bank-width = <2>;
- device-width = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- partition@0 {
- label = "dtb";
- reg = <0x00000000 0x00100000>;
- read-only;
- };
- partition@300000 {
- label = "kernel";
- reg = <0x00100000 0x00400000>;
- read-only;
- };
- partition@400000 {
- label = "fs";
- reg = <0x00500000 0x00a00000>;
- };
- partition@700000 {
- label = "firmware";
- reg = <0x00f00000 0x00100000>;
- read-only;
- };
- };
-
- epld@2,0 {
- compatible = "wrs,epld-localbus";
- #address-cells = <2>;
- #size-cells = <1>;
- reg = <2 0 0x100000>;
- ranges = <0 0 5 0 1 // User switches
- 1 0 5 1 1 // Board ID/Rev
- 3 0 5 3 1>; // LEDs
- };
- };
-
- soc: soc@f8000000 {
- ranges = <0x00000000 0xf8000000 0x00100000>;
-
- enet0: ethernet@24000 {
- tbi-handle = <&tbi0>;
- phy-handle = <&phy0>;
- phy-connection-type = "rgmii-id";
- };
-
- mdio@24520 {
- phy0: ethernet-phy@1f {
- reg = <0x1f>;
- };
- phy1: ethernet-phy@0 {
- reg = <0>;
- };
- phy2: ethernet-phy@1 {
- reg = <1>;
- };
- phy3: ethernet-phy@2 {
- reg = <2>;
- };
- tbi0: tbi-phy@11 {
- reg = <0x11>;
- device_type = "tbi-phy";
- };
- };
-
- enet1: ethernet@25000 {
- tbi-handle = <&tbi1>;
- phy-handle = <&phy1>;
- phy-connection-type = "rgmii-id";
- };
-
- mdio@25520 {
- tbi1: tbi-phy@11 {
- reg = <0x11>;
- device_type = "tbi-phy";
- };
- };
-
- enet2: ethernet@26000 {
- tbi-handle = <&tbi2>;
- phy-handle = <&phy2>;
- phy-connection-type = "rgmii-id";
- };
-
- mdio@26520 {
- tbi2: tbi-phy@11 {
- reg = <0x11>;
- device_type = "tbi-phy";
- };
- };
-
- enet3: ethernet@27000 {
- tbi-handle = <&tbi3>;
- phy-handle = <&phy3>;
- phy-connection-type = "rgmii-id";
- };
-
- mdio@27520 {
- tbi3: tbi-phy@11 {
- reg = <0x11>;
- device_type = "tbi-phy";
- };
- };
- };
-
- pci0: pcie@f8008000 {
- reg = <0xf8008000 0x1000>;
- ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
- 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
- interrupt-map-mask = <0xff00 0 0 7>;
-
- pcie@0 {
- ranges = <0x02000000 0x0 0x80000000
- 0x02000000 0x0 0x80000000
- 0x0 0x20000000
-
- 0x01000000 0x0 0x00000000
- 0x01000000 0x0 0x00000000
- 0x0 0x00100000>;
- };
-
- };
-
- pci1: pcie@f8009000 {
- reg = <0xf8009000 0x1000>;
- ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
- 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
-
- pcie@0 {
- ranges = <0x02000000 0x0 0xa0000000
- 0x02000000 0x0 0xa0000000
- 0x0 0x20000000
-
- 0x01000000 0x0 0x00000000
- 0x01000000 0x0 0x00000000
- 0x0 0x00100000>;
- };
- };
-};
-
-/include/ "mpc8641si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/microwatt.dts b/arch/powerpc/boot/dts/microwatt.dts
index 974abbdda249..65b270a90f94 100644
--- a/arch/powerpc/boot/dts/microwatt.dts
+++ b/arch/powerpc/boot/dts/microwatt.dts
@@ -127,6 +127,18 @@
fifo-size = <16>;
interrupts = <0x10 0x1>;
};
+
+ ethernet@8020000 {
+ compatible = "litex,liteeth";
+ reg = <0x8021000 0x100
+ 0x8020800 0x100
+ 0x8030000 0x2000>;
+ reg-names = "mac", "mido", "buffer";
+ litex,rx-slots = <2>;
+ litex,tx-slots = <2>;
+ litex,slot-size = <0x800>;
+ interrupts = <0x11 0x1>;
+ };
};
chosen {
diff --git a/arch/powerpc/boot/dts/sbc8548-altflash.dts b/arch/powerpc/boot/dts/sbc8548-altflash.dts
deleted file mode 100644
index bb7a1e712bb7..000000000000
--- a/arch/powerpc/boot/dts/sbc8548-altflash.dts
+++ /dev/null
@@ -1,111 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SBC8548 Device Tree Source
- *
- * Configured for booting off the alternate (64MB SODIMM) flash.
- * Requires switching JP12 jumpers and changing SW2.8 setting.
- *
- * Copyright 2013 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- */
-
-
-/dts-v1/;
-
-/include/ "sbc8548-pre.dtsi"
-
-/{
- localbus@e0000000 {
- #address-cells = <2>;
- #size-cells = <1>;
- compatible = "simple-bus";
- reg = <0xe0000000 0x5000>;
- interrupt-parent = <&mpic>;
-
- ranges = <0x0 0x0 0xfc000000 0x04000000 /*64MB Flash*/
- 0x3 0x0 0xf0000000 0x04000000 /*64MB SDRAM*/
- 0x4 0x0 0xf4000000 0x04000000 /*64MB SDRAM*/
- 0x5 0x0 0xf8000000 0x00b10000 /* EPLD */
- 0x6 0x0 0xef800000 0x00800000>; /*8MB Flash*/
-
- flash@0,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x0 0x0 0x04000000>;
- compatible = "intel,JS28F128", "cfi-flash";
- bank-width = <4>;
- device-width = <1>;
- partition@0 {
- label = "space";
- /* FC000000 -> FFEFFFFF */
- reg = <0x00000000 0x03f00000>;
- };
- partition@3f00000 {
- label = "bootloader";
- /* FFF00000 -> FFFFFFFF */
- reg = <0x03f00000 0x00100000>;
- read-only;
- };
- };
-
-
- epld@5,0 {
- compatible = "wrs,epld-localbus";
- #address-cells = <2>;
- #size-cells = <1>;
- reg = <0x5 0x0 0x00b10000>;
- ranges = <
- 0x0 0x0 0x5 0x000000 0x1fff /* LED */
- 0x1 0x0 0x5 0x100000 0x1fff /* Switches */
- 0x3 0x0 0x5 0x300000 0x1fff /* HW Rev. */
- 0xb 0x0 0x5 0xb00000 0x1fff /* EEPROM */
- >;
-
- led@0,0 {
- compatible = "led";
- reg = <0x0 0x0 0x1fff>;
- };
-
- switches@1,0 {
- compatible = "switches";
- reg = <0x1 0x0 0x1fff>;
- };
-
- hw-rev@3,0 {
- compatible = "hw-rev";
- reg = <0x3 0x0 0x1fff>;
- };
-
- eeprom@b,0 {
- compatible = "eeprom";
- reg = <0xb 0 0x1fff>;
- };
-
- };
-
- alt-flash@6,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "intel,JS28F640", "cfi-flash";
- reg = <0x6 0x0 0x800000>;
- bank-width = <1>;
- device-width = <1>;
- partition@0 {
- label = "space";
- /* EF800000 -> EFF9FFFF */
- reg = <0x00000000 0x007a0000>;
- };
- partition@7a0000 {
- label = "bootloader";
- /* EFFA0000 -> EFFFFFFF */
- reg = <0x007a0000 0x00060000>;
- read-only;
- };
- };
-
-
- };
-};
-
-/include/ "sbc8548-post.dtsi"
diff --git a/arch/powerpc/boot/dts/sbc8548-post.dtsi b/arch/powerpc/boot/dts/sbc8548-post.dtsi
deleted file mode 100644
index 9d848d409408..000000000000
--- a/arch/powerpc/boot/dts/sbc8548-post.dtsi
+++ /dev/null
@@ -1,289 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SBC8548 Device Tree Source
- *
- * Copyright 2007 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- */
-
-/{
- soc8548@e0000000 {
- #address-cells = <1>;
- #size-cells = <1>;
- device_type = "soc";
- ranges = <0x00000000 0xe0000000 0x00100000>;
- bus-frequency = <0>;
- compatible = "simple-bus";
-
- ecm-law@0 {
- compatible = "fsl,ecm-law";
- reg = <0x0 0x1000>;
- fsl,num-laws = <10>;
- };
-
- ecm@1000 {
- compatible = "fsl,mpc8548-ecm", "fsl,ecm";
- reg = <0x1000 0x1000>;
- interrupts = <17 2>;
- interrupt-parent = <&mpic>;
- };
-
- memory-controller@2000 {
- compatible = "fsl,mpc8548-memory-controller";
- reg = <0x2000 0x1000>;
- interrupt-parent = <&mpic>;
- interrupts = <0x12 0x2>;
- };
-
- L2: l2-cache-controller@20000 {
- compatible = "fsl,mpc8548-l2-cache-controller";
- reg = <0x20000 0x1000>;
- cache-line-size = <0x20>; // 32 bytes
- cache-size = <0x80000>; // L2, 512K
- interrupt-parent = <&mpic>;
- interrupts = <0x10 0x2>;
- };
-
- i2c@3000 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
- reg = <0x3000 0x100>;
- interrupts = <0x2b 0x2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-
- i2c@3100 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <1>;
- compatible = "fsl-i2c";
- reg = <0x3100 0x100>;
- interrupts = <0x2b 0x2>;
- interrupt-parent = <&mpic>;
- dfsrr;
- };
-
- dma@21300 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,mpc8548-dma", "fsl,eloplus-dma";
- reg = <0x21300 0x4>;
- ranges = <0x0 0x21100 0x200>;
- cell-index = <0>;
- dma-channel@0 {
- compatible = "fsl,mpc8548-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x0 0x80>;
- cell-index = <0>;
- interrupt-parent = <&mpic>;
- interrupts = <20 2>;
- };
- dma-channel@80 {
- compatible = "fsl,mpc8548-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x80 0x80>;
- cell-index = <1>;
- interrupt-parent = <&mpic>;
- interrupts = <21 2>;
- };
- dma-channel@100 {
- compatible = "fsl,mpc8548-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x100 0x80>;
- cell-index = <2>;
- interrupt-parent = <&mpic>;
- interrupts = <22 2>;
- };
- dma-channel@180 {
- compatible = "fsl,mpc8548-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x180 0x80>;
- cell-index = <3>;
- interrupt-parent = <&mpic>;
- interrupts = <23 2>;
- };
- };
-
- enet0: ethernet@24000 {
- #address-cells = <1>;
- #size-cells = <1>;
- cell-index = <0>;
- device_type = "network";
- model = "eTSEC";
- compatible = "gianfar";
- reg = <0x24000 0x1000>;
- ranges = <0x0 0x24000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
- interrupt-parent = <&mpic>;
- tbi-handle = <&tbi0>;
- phy-handle = <&phy0>;
-
- mdio@520 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
- reg = <0x520 0x20>;
-
- phy0: ethernet-phy@19 {
- interrupt-parent = <&mpic>;
- interrupts = <0x6 0x1>;
- reg = <0x19>;
- };
- phy1: ethernet-phy@1a {
- interrupt-parent = <&mpic>;
- interrupts = <0x7 0x1>;
- reg = <0x1a>;
- };
- tbi0: tbi-phy@11 {
- reg = <0x11>;
- device_type = "tbi-phy";
- };
- };
- };
-
- enet1: ethernet@25000 {
- #address-cells = <1>;
- #size-cells = <1>;
- cell-index = <1>;
- device_type = "network";
- model = "eTSEC";
- compatible = "gianfar";
- reg = <0x25000 0x1000>;
- ranges = <0x0 0x25000 0x1000>;
- local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
- interrupt-parent = <&mpic>;
- tbi-handle = <&tbi1>;
- phy-handle = <&phy1>;
-
- mdio@520 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,gianfar-tbi";
- reg = <0x520 0x20>;
-
- tbi1: tbi-phy@11 {
- reg = <0x11>;
- device_type = "tbi-phy";
- };
- };
- };
-
- serial0: serial@4500 {
- cell-index = <0>;
- device_type = "serial";
- compatible = "fsl,ns16550", "ns16550";
- reg = <0x4500 0x100>; // reg base, size
- clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <0x2a 0x2>;
- interrupt-parent = <&mpic>;
- };
-
- serial1: serial@4600 {
- cell-index = <1>;
- device_type = "serial";
- compatible = "fsl,ns16550", "ns16550";
- reg = <0x4600 0x100>; // reg base, size
- clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <0x2a 0x2>;
- interrupt-parent = <&mpic>;
- };
-
- global-utilities@e0000 { //global utilities reg
- compatible = "fsl,mpc8548-guts";
- reg = <0xe0000 0x1000>;
- fsl,has-rstcr;
- };
-
- crypto@30000 {
- compatible = "fsl,sec2.1", "fsl,sec2.0";
- reg = <0x30000 0x10000>;
- interrupts = <45 2>;
- interrupt-parent = <&mpic>;
- fsl,num-channels = <4>;
- fsl,channel-fifo-len = <24>;
- fsl,exec-units-mask = <0xfe>;
- fsl,descriptor-types-mask = <0x12b0ebf>;
- };
-
- mpic: pic@40000 {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <2>;
- reg = <0x40000 0x40000>;
- compatible = "chrp,open-pic";
- device_type = "open-pic";
- };
- };
-
- pci0: pci@e0008000 {
- interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
- /* IDSEL 0x01 (PCI-X slot) @66MHz */
- 0x0800 0x0 0x0 0x1 &mpic 0x2 0x1
- 0x0800 0x0 0x0 0x2 &mpic 0x3 0x1
- 0x0800 0x0 0x0 0x3 &mpic 0x4 0x1
- 0x0800 0x0 0x0 0x4 &mpic 0x1 0x1
-
- /* IDSEL 0x11 (PCI, 3.3V 32bit) @33MHz */
- 0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
- 0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
- 0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
- 0x8800 0x0 0x0 0x4 &mpic 0x1 0x1>;
-
- interrupt-parent = <&mpic>;
- interrupts = <0x18 0x2>;
- bus-range = <0 0>;
- ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x10000000
- 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00800000>;
- clock-frequency = <66000000>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- reg = <0xe0008000 0x1000>;
- compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
- device_type = "pci";
- };
-
- pci1: pcie@e000a000 {
- interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
-
- /* IDSEL 0x0 (PEX) */
- 0x0000 0x0 0x0 0x1 &mpic 0x0 0x1
- 0x0000 0x0 0x0 0x2 &mpic 0x1 0x1
- 0x0000 0x0 0x0 0x3 &mpic 0x2 0x1
- 0x0000 0x0 0x0 0x4 &mpic 0x3 0x1>;
-
- interrupt-parent = <&mpic>;
- interrupts = <0x1a 0x2>;
- bus-range = <0x0 0xff>;
- ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
- 0x01000000 0x0 0x00000000 0xe2800000 0x0 0x08000000>;
- clock-frequency = <33000000>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- reg = <0xe000a000 0x1000>;
- compatible = "fsl,mpc8548-pcie";
- device_type = "pci";
- pcie@0 {
- reg = <0x0 0x0 0x0 0x0 0x0>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
- ranges = <0x02000000 0x0 0xa0000000
- 0x02000000 0x0 0xa0000000
- 0x0 0x10000000
-
- 0x01000000 0x0 0x00000000
- 0x01000000 0x0 0x00000000
- 0x0 0x00800000>;
- };
- };
-};
diff --git a/arch/powerpc/boot/dts/sbc8548-pre.dtsi b/arch/powerpc/boot/dts/sbc8548-pre.dtsi
deleted file mode 100644
index 0e3665fd15d0..000000000000
--- a/arch/powerpc/boot/dts/sbc8548-pre.dtsi
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SBC8548 Device Tree Source
- *
- * Copyright 2007 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- */
-
-/{
- model = "SBC8548";
- compatible = "SBC8548";
- #address-cells = <1>;
- #size-cells = <1>;
-
- aliases {
- ethernet0 = &enet0;
- ethernet1 = &enet1;
- serial0 = &serial0;
- serial1 = &serial1;
- pci0 = &pci0;
- pci1 = &pci1;
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- PowerPC,8548@0 {
- device_type = "cpu";
- reg = <0>;
- d-cache-line-size = <0x20>; // 32 bytes
- i-cache-line-size = <0x20>; // 32 bytes
- d-cache-size = <0x8000>; // L1, 32K
- i-cache-size = <0x8000>; // L1, 32K
- timebase-frequency = <0>; // From uboot
- bus-frequency = <0>;
- clock-frequency = <0>;
- next-level-cache = <&L2>;
- };
- };
-
- memory {
- device_type = "memory";
- reg = <0x00000000 0x10000000>;
- };
-
-};
diff --git a/arch/powerpc/boot/dts/sbc8548.dts b/arch/powerpc/boot/dts/sbc8548.dts
deleted file mode 100644
index ce0a119f496e..000000000000
--- a/arch/powerpc/boot/dts/sbc8548.dts
+++ /dev/null
@@ -1,106 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SBC8548 Device Tree Source
- *
- * Copyright 2007 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- */
-
-
-/dts-v1/;
-
-/include/ "sbc8548-pre.dtsi"
-
-/{
- localbus@e0000000 {
- #address-cells = <2>;
- #size-cells = <1>;
- compatible = "simple-bus";
- reg = <0xe0000000 0x5000>;
- interrupt-parent = <&mpic>;
-
- ranges = <0x0 0x0 0xff800000 0x00800000 /*8MB Flash*/
- 0x3 0x0 0xf0000000 0x04000000 /*64MB SDRAM*/
- 0x4 0x0 0xf4000000 0x04000000 /*64MB SDRAM*/
- 0x5 0x0 0xf8000000 0x00b10000 /* EPLD */
- 0x6 0x0 0xec000000 0x04000000>; /*64MB Flash*/
-
-
- flash@0,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "intel,JS28F640", "cfi-flash";
- reg = <0x0 0x0 0x800000>;
- bank-width = <1>;
- device-width = <1>;
- partition@0 {
- label = "space";
- /* FF800000 -> FFF9FFFF */
- reg = <0x00000000 0x007a0000>;
- };
- partition@7a0000 {
- label = "bootloader";
- /* FFFA0000 -> FFFFFFFF */
- reg = <0x007a0000 0x00060000>;
- read-only;
- };
- };
-
- epld@5,0 {
- compatible = "wrs,epld-localbus";
- #address-cells = <2>;
- #size-cells = <1>;
- reg = <0x5 0x0 0x00b10000>;
- ranges = <
- 0x0 0x0 0x5 0x000000 0x1fff /* LED */
- 0x1 0x0 0x5 0x100000 0x1fff /* Switches */
- 0x3 0x0 0x5 0x300000 0x1fff /* HW Rev. */
- 0xb 0x0 0x5 0xb00000 0x1fff /* EEPROM */
- >;
-
- led@0,0 {
- compatible = "led";
- reg = <0x0 0x0 0x1fff>;
- };
-
- switches@1,0 {
- compatible = "switches";
- reg = <0x1 0x0 0x1fff>;
- };
-
- hw-rev@3,0 {
- compatible = "hw-rev";
- reg = <0x3 0x0 0x1fff>;
- };
-
- eeprom@b,0 {
- compatible = "eeprom";
- reg = <0xb 0 0x1fff>;
- };
-
- };
-
- alt-flash@6,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x6 0x0 0x04000000>;
- compatible = "intel,JS28F128", "cfi-flash";
- bank-width = <4>;
- device-width = <1>;
- partition@0 {
- label = "space";
- /* EC000000 -> EFEFFFFF */
- reg = <0x00000000 0x03f00000>;
- };
- partition@3f00000 {
- label = "bootloader";
- /* EFF00000 -> EFFFFFFF */
- reg = <0x03f00000 0x00100000>;
- read-only;
- };
- };
- };
-};
-
-/include/ "sbc8548-post.dtsi"
diff --git a/arch/powerpc/boot/dts/wii.dts b/arch/powerpc/boot/dts/wii.dts
index aaa381da1906..e9c945b123c6 100644
--- a/arch/powerpc/boot/dts/wii.dts
+++ b/arch/powerpc/boot/dts/wii.dts
@@ -216,7 +216,18 @@
control@d800100 {
compatible = "nintendo,hollywood-control";
- reg = <0x0d800100 0x300>;
+ /*
+ * Both the address and length are wrong, according to
+ * Wiibrew this should be <0x0d800000 0x400>, but it
+ * requires refactoring the PIC1, GPIO and OTP nodes
+ * before changing that.
+ */
+ reg = <0x0d800100 0xa0>;
+ };
+
+ otp@d8001ec {
+ compatible = "nintendo,hollywood-otp";
+ reg = <0x0d8001ec 0x8>;
};
disk@d806000 {
diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh
index b6a256bc96ee..14473150ddb4 100644
--- a/arch/powerpc/boot/install.sh
+++ b/arch/powerpc/boot/install.sh
@@ -15,12 +15,25 @@
# $2 - kernel image file
# $3 - kernel map file
# $4 - default install path (blank if root directory)
-# $5 and more - kernel boot files; zImage*, uImage, cuImage.*, etc.
#
# Bail with error code if anything goes wrong
set -e
+verify () {
+ if [ ! -f "$1" ]; then
+ echo "" 1>&2
+ echo " *** Missing file: $1" 1>&2
+ echo ' *** You need to run "make" before "make install".' 1>&2
+ echo "" 1>&2
+ exit 1
+ fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
# User may have a custom install script
if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
@@ -41,15 +54,3 @@ fi
cat $2 > $4/$image_name
cp $3 $4/System.map
-
-# Copy all the bootable image files
-path=$4
-shift 4
-while [ $# -ne 0 ]; do
- image_name=`basename $1`
- if [ -f $path/$image_name ]; then
- mv $path/$image_name $path/$image_name.old
- fi
- cat $1 > $path/$image_name
- shift
-done;
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 1f4676bab786..1cd82564c996 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -298,7 +298,7 @@ cuboot*)
*-tqm8541|*-mpc8560*|*-tqm8560|*-tqm8555|*-ksi8560*)
platformo=$object/cuboot-85xx-cpm2.o
;;
- *-mpc85*|*-tqm85*|*-sbc85*)
+ *-mpc85*|*-tqm85*)
platformo=$object/cuboot-85xx.o
;;
*-amigaone)
diff --git a/arch/powerpc/configs/85xx/sbc8548_defconfig b/arch/powerpc/configs/85xx/sbc8548_defconfig
deleted file mode 100644
index 258881727119..000000000000
--- a/arch/powerpc/configs/85xx/sbc8548_defconfig
+++ /dev/null
@@ -1,50 +0,0 @@
-CONFIG_PPC_85xx=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_SBC8548=y
-CONFIG_GEN_RTC=y
-CONFIG_BINFMT_MISC=y
-CONFIG_MATH_EMULATION=y
-# CONFIG_SECCOMP is not set
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_IPV6 is not set
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_CFI_I4=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_NETDEVICES=y
-CONFIG_GIANFAR=y
-CONFIG_BROADCOM_PHY=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
diff --git a/arch/powerpc/configs/microwatt_defconfig b/arch/powerpc/configs/microwatt_defconfig
index a08b739123da..9465209b8c5b 100644
--- a/arch/powerpc/configs/microwatt_defconfig
+++ b/arch/powerpc/configs/microwatt_defconfig
@@ -5,6 +5,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12
+CONFIG_CGROUPS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
@@ -53,10 +54,12 @@ CONFIG_MTD_SPI_NOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_NETDEVICES=y
+CONFIG_LITEX_LITEETH=y
# CONFIG_WLAN is not set
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
CONFIG_SERIAL_8250_CONSOLE=y
@@ -76,8 +79,10 @@ CONFIG_SPI_SPIDEV=y
CONFIG_EXT4_FS=y
# CONFIG_FILE_LOCKING is not set
# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_TMPFS=y
# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_CRYPTO_SHA256=y
# CONFIG_CRYPTO_HW is not set
# CONFIG_XZ_DEC_X86 is not set
# CONFIG_XZ_DEC_IA64 is not set
diff --git a/arch/powerpc/configs/mpc85xx_base.config b/arch/powerpc/configs/mpc85xx_base.config
index b1593fe6f70b..85907b776908 100644
--- a/arch/powerpc/configs/mpc85xx_base.config
+++ b/arch/powerpc/configs/mpc85xx_base.config
@@ -13,7 +13,6 @@ CONFIG_P1022_DS=y
CONFIG_P1022_RDK=y
CONFIG_P1023_RDB=y
CONFIG_TWR_P102x=y
-CONFIG_SBC8548=y
CONFIG_SOCRATES=y
CONFIG_STX_GP3=y
CONFIG_TQM8540=y
diff --git a/arch/powerpc/configs/mpc86xx_base.config b/arch/powerpc/configs/mpc86xx_base.config
index 67bd1fa036ee..588870e6af3b 100644
--- a/arch/powerpc/configs/mpc86xx_base.config
+++ b/arch/powerpc/configs/mpc86xx_base.config
@@ -1,6 +1,5 @@
CONFIG_PPC_86xx=y
CONFIG_MPC8641_HPCN=y
-CONFIG_SBC8641D=y
CONFIG_MPC8610_HPCD=y
CONFIG_GEF_PPC9A=y
CONFIG_GEF_SBC310=y
diff --git a/arch/powerpc/configs/mpc885_ads_defconfig b/arch/powerpc/configs/mpc885_ads_defconfig
index d21f266cea9a..c74dc76b1d0d 100644
--- a/arch/powerpc/configs/mpc885_ads_defconfig
+++ b/arch/powerpc/configs/mpc885_ads_defconfig
@@ -1,19 +1,30 @@
-CONFIG_PPC_8xx=y
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BPF_JIT=y
+CONFIG_VIRT_CPU_ACCOUNTING_NATIVE=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_EXPERT=y
# CONFIG_ELF_CORE is not set
# CONFIG_BASE_FULL is not set
# CONFIG_FUTEX is not set
+CONFIG_PERF_EVENTS=y
# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
+CONFIG_PPC_8xx=y
+CONFIG_8xx_GPIO=y
+CONFIG_SMC_UCODE_PATCH=y
+CONFIG_PIN_TLB=y
CONFIG_GEN_RTC=y
CONFIG_HZ_100=y
+CONFIG_MATH_EMULATION=y
+CONFIG_PPC_16K_PAGES=y
+CONFIG_ADVANCED_OPTIONS=y
# CONFIG_SECCOMP is not set
+CONFIG_STRICT_KERNEL_RWX=y
+CONFIG_MODULES=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -21,7 +32,6 @@ CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_SYN_COOKIES=y
-# CONFIG_IPV6 is not set
# CONFIG_FW_LOADER is not set
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
@@ -34,6 +44,7 @@ CONFIG_MTD_CFI_GEOMETRY=y
# CONFIG_MTD_CFI_I2 is not set
CONFIG_MTD_CFI_I4=y
CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_BLK_DEV is not set
CONFIG_NETDEVICES=y
@@ -46,39 +57,25 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
+CONFIG_SPI=y
+CONFIG_SPI_FSL_SPI=y
# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_8xxx_WDT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_DNOTIFY is not set
CONFIG_TMPFS=y
CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_DEV_TALITOS=y
CONFIG_CRC32_SLICEBY4=y
CONFIG_DEBUG_INFO=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_PPC_16K_PAGES=y
-CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_FS=y
-CONFIG_PPC_PTDUMP=y
-CONFIG_MODULES=y
-CONFIG_SPI=y
-CONFIG_SPI_FSL_SPI=y
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_DEV_TALITOS=y
-CONFIG_8xx_GPIO=y
-CONFIG_WATCHDOG=y
-CONFIG_8xxx_WDT=y
-CONFIG_SMC_UCODE_PATCH=y
-CONFIG_ADVANCED_OPTIONS=y
-CONFIG_PIN_TLB=y
-CONFIG_PERF_EVENTS=y
-CONFIG_MATH_EMULATION=y
-CONFIG_VIRT_CPU_ACCOUNTING_NATIVE=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_IPV6=y
-CONFIG_BPF_JIT=y
CONFIG_DEBUG_VM_PGTABLE=y
+CONFIG_DETECT_HUNG_TASK=y
CONFIG_BDI_SWITCH=y
CONFIG_PPC_EARLY_DEBUG=y
-CONFIG_PPC_EARLY_DEBUG_CPM_ADDR=0xff002008
+CONFIG_PPC_PTDUMP=y
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index ee09f7bb6ea9..6697c5e6682f 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -55,7 +55,6 @@ CONFIG_MPC837x_RDB=y
CONFIG_ASP834x=y
CONFIG_PPC_86xx=y
CONFIG_MPC8641_HPCN=y
-CONFIG_SBC8641D=y
CONFIG_MPC8610_HPCD=y
CONFIG_GEF_SBC610=y
CONFIG_CPU_FREQ=y
diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig
index 379c171f3ddd..a0c45bf2bfb1 100644
--- a/arch/powerpc/configs/wii_defconfig
+++ b/arch/powerpc/configs/wii_defconfig
@@ -99,6 +99,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_GENERIC=y
+CONFIG_NVMEM_NINTENDO_OTP=y
CONFIG_EXT2_FS=y
CONFIG_EXT4_FS=y
CONFIG_FUSE_FS=m
diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h
index 19b70c5b5f18..2b736d9fbb1b 100644
--- a/arch/powerpc/include/asm/asm-compat.h
+++ b/arch/powerpc/include/asm/asm-compat.h
@@ -17,7 +17,7 @@
#define PPC_LONG stringify_in_c(.8byte)
#define PPC_LONG_ALIGN stringify_in_c(.balign 8)
#define PPC_TLNEI stringify_in_c(tdnei)
-#define PPC_LLARX(t, a, b, eh) PPC_LDARX(t, a, b, eh)
+#define PPC_LLARX stringify_in_c(ldarx)
#define PPC_STLCX stringify_in_c(stdcx.)
#define PPC_CNTLZL stringify_in_c(cntlzd)
#define PPC_MTOCRF(FXM, RS) MTOCRF((FXM), RS)
@@ -50,7 +50,7 @@
#define PPC_LONG stringify_in_c(.long)
#define PPC_LONG_ALIGN stringify_in_c(.balign 4)
#define PPC_TLNEI stringify_in_c(twnei)
-#define PPC_LLARX(t, a, b, eh) PPC_LWARX(t, a, b, eh)
+#define PPC_LLARX stringify_in_c(lwarx)
#define PPC_STLCX stringify_in_c(stwcx.)
#define PPC_CNTLZL stringify_in_c(cntlzw)
#define PPC_MTOCRF stringify_in_c(mtcrf)
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index a1732a79e92a..6a53ef178bfd 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -207,7 +207,7 @@ arch_atomic_try_cmpxchg_lock(atomic_t *v, int *old, int new)
int r, o = *old;
__asm__ __volatile__ (
-"1:\t" PPC_LWARX(%0,0,%2,1) " # atomic_try_cmpxchg_acquire \n"
+"1: lwarx %0,0,%2,%5 # atomic_try_cmpxchg_acquire \n"
" cmpw 0,%0,%3 \n"
" bne- 2f \n"
" stwcx. %4,0,%2 \n"
@@ -215,7 +215,7 @@ arch_atomic_try_cmpxchg_lock(atomic_t *v, int *old, int new)
"\t" PPC_ACQUIRE_BARRIER " \n"
"2: \n"
: "=&r" (r), "+m" (v->counter)
- : "r" (&v->counter), "r" (o), "r" (new)
+ : "r" (&v->counter), "r" (o), "r" (new), "i" (IS_ENABLED(CONFIG_PPC64) ? 1 : 0)
: "cr0", "memory");
if (unlikely(r != o))
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index 299ab33505a6..11847b6a244e 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -70,7 +70,7 @@ static inline void fn(unsigned long mask, \
unsigned long *p = (unsigned long *)_p; \
__asm__ __volatile__ ( \
prefix \
-"1:" PPC_LLARX(%0,0,%3,0) "\n" \
+"1:" PPC_LLARX "%0,0,%3,0\n" \
stringify_in_c(op) "%0,%0,%2\n" \
PPC_STLCX "%0,0,%3\n" \
"bne- 1b\n" \
@@ -115,13 +115,13 @@ static inline unsigned long fn( \
unsigned long *p = (unsigned long *)_p; \
__asm__ __volatile__ ( \
prefix \
-"1:" PPC_LLARX(%0,0,%3,eh) "\n" \
+"1:" PPC_LLARX "%0,0,%3,%4\n" \
stringify_in_c(op) "%1,%0,%2\n" \
PPC_STLCX "%1,0,%3\n" \
"bne- 1b\n" \
postfix \
: "=&r" (old), "=&r" (t) \
- : "r" (mask), "r" (p) \
+ : "r" (mask), "r" (p), "i" (IS_ENABLED(CONFIG_PPC64) ? eh : 0) \
: "cc", "memory"); \
return (old & mask); \
}
@@ -170,7 +170,7 @@ clear_bit_unlock_return_word(int nr, volatile unsigned long *addr)
__asm__ __volatile__ (
PPC_RELEASE_BARRIER
-"1:" PPC_LLARX(%0,0,%3,0) "\n"
+"1:" PPC_LLARX "%0,0,%3,0\n"
"andc %1,%0,%2\n"
PPC_STLCX "%1,0,%3\n"
"bne- 1b\n"
diff --git a/arch/powerpc/include/asm/book3s/64/kup.h b/arch/powerpc/include/asm/book3s/64/kup.h
index a1cc73a88710..170339969b7c 100644
--- a/arch/powerpc/include/asm/book3s/64/kup.h
+++ b/arch/powerpc/include/asm/book3s/64/kup.h
@@ -90,7 +90,7 @@
/* Prevent access to userspace using any key values */
LOAD_REG_IMMEDIATE(\gpr2, AMR_KUAP_BLOCKED)
999: tdne \gpr1, \gpr2
- EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE)
+ EMIT_WARN_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE)
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_BOOK3S_KUAP, 67)
#endif
.endm
diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
index 0b2162890d8b..02c08d1492f8 100644
--- a/arch/powerpc/include/asm/bug.h
+++ b/arch/powerpc/include/asm/bug.h
@@ -4,6 +4,7 @@
#ifdef __KERNEL__
#include <asm/asm-compat.h>
+#include <asm/extable.h>
#ifdef CONFIG_BUG
@@ -30,6 +31,11 @@
.endm
#endif /* verbose */
+.macro EMIT_WARN_ENTRY addr,file,line,flags
+ EX_TABLE(\addr,\addr+4)
+ EMIT_BUG_ENTRY \addr,\file,\line,\flags
+.endm
+
#else /* !__ASSEMBLY__ */
/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
sizeof(struct bug_entry), respectively */
@@ -58,6 +64,16 @@
"i" (sizeof(struct bug_entry)), \
##__VA_ARGS__)
+#define WARN_ENTRY(insn, flags, label, ...) \
+ asm_volatile_goto( \
+ "1: " insn "\n" \
+ EX_TABLE(1b, %l[label]) \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (flags), \
+ "i" (sizeof(struct bug_entry)), \
+ ##__VA_ARGS__ : : label)
+
/*
* BUG_ON() and WARN_ON() do their best to cooperate with compile-time
* optimisations. However depending on the complexity of the condition
@@ -68,7 +84,19 @@
BUG_ENTRY("twi 31, 0, 0", 0); \
unreachable(); \
} while (0)
+#define HAVE_ARCH_BUG
+#define __WARN_FLAGS(flags) do { \
+ __label__ __label_warn_on; \
+ \
+ WARN_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags), __label_warn_on); \
+ unreachable(); \
+ \
+__label_warn_on: \
+ break; \
+} while (0)
+
+#ifdef CONFIG_PPC64
#define BUG_ON(x) do { \
if (__builtin_constant_p(x)) { \
if (x) \
@@ -78,31 +106,43 @@
} \
} while (0)
-#define __WARN_FLAGS(flags) BUG_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags))
-
#define WARN_ON(x) ({ \
- int __ret_warn_on = !!(x); \
- if (__builtin_constant_p(__ret_warn_on)) { \
- if (__ret_warn_on) \
+ bool __ret_warn_on = false; \
+ do { \
+ if (__builtin_constant_p((x))) { \
+ if (!(x)) \
+ break; \
__WARN(); \
- } else { \
- BUG_ENTRY(PPC_TLNEI " %4, 0", \
- BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN), \
- "r" (__ret_warn_on)); \
- } \
+ __ret_warn_on = true; \
+ } else { \
+ __label__ __label_warn_on; \
+ \
+ WARN_ENTRY(PPC_TLNEI " %4, 0", \
+ BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN), \
+ __label_warn_on, \
+ "r" ((__force long)(x))); \
+ break; \
+__label_warn_on: \
+ __ret_warn_on = true; \
+ } \
+ } while (0); \
unlikely(__ret_warn_on); \
})
-#define HAVE_ARCH_BUG
#define HAVE_ARCH_BUG_ON
#define HAVE_ARCH_WARN_ON
+#endif
+
#endif /* __ASSEMBLY __ */
#else
#ifdef __ASSEMBLY__
.macro EMIT_BUG_ENTRY addr,file,line,flags
.endm
+.macro EMIT_WARN_ENTRY addr,file,line,flags
+.endm
#else /* !__ASSEMBLY__ */
#define _EMIT_BUG_ENTRY
+#define _EMIT_WARN_ENTRY
#endif
#endif /* CONFIG_BUG */
diff --git a/arch/powerpc/include/asm/debugfs.h b/arch/powerpc/include/asm/debugfs.h
deleted file mode 100644
index 2c5c48571d75..000000000000
--- a/arch/powerpc/include/asm/debugfs.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _ASM_POWERPC_DEBUGFS_H
-#define _ASM_POWERPC_DEBUGFS_H
-
-/*
- * Copyright 2017, Michael Ellerman, IBM Corporation.
- */
-
-#include <linux/debugfs.h>
-
-extern struct dentry *powerpc_debugfs_root;
-
-#endif /* _ASM_POWERPC_DEBUGFS_H */
diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h
index bf2402fed3e0..4265d5e95c2c 100644
--- a/arch/powerpc/include/asm/drmem.h
+++ b/arch/powerpc/include/asm/drmem.h
@@ -111,6 +111,7 @@ int drmem_update_dt(void);
int __init
walk_drmem_lmbs_early(unsigned long node, void *data,
int (*func)(struct drmem_lmb *, const __be32 **, void *));
+void drmem_update_lmbs(struct property *prop);
#endif
static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb)
diff --git a/arch/powerpc/include/asm/extable.h b/arch/powerpc/include/asm/extable.h
index eb91b2d2935a..26ce2e5c0fa8 100644
--- a/arch/powerpc/include/asm/extable.h
+++ b/arch/powerpc/include/asm/extable.h
@@ -17,6 +17,8 @@
#define ARCH_HAS_RELATIVE_EXTABLE
+#ifndef __ASSEMBLY__
+
struct exception_table_entry {
int insn;
int fixup;
@@ -28,3 +30,15 @@ static inline unsigned long extable_fixup(const struct exception_table_entry *x)
}
#endif
+
+/*
+ * Helper macro for exception table entries
+ */
+#define EX_TABLE(_fault, _target) \
+ stringify_in_c(.section __ex_table,"a";)\
+ stringify_in_c(.balign 4;) \
+ stringify_in_c(.long (_fault) - . ;) \
+ stringify_in_c(.long (_target) - . ;) \
+ stringify_in_c(.previous)
+
+#endif
diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
index 7604673787d6..97a3bd9ffeb9 100644
--- a/arch/powerpc/include/asm/firmware.h
+++ b/arch/powerpc/include/asm/firmware.h
@@ -44,7 +44,7 @@
#define FW_FEATURE_OPAL ASM_CONST(0x0000000010000000)
#define FW_FEATURE_SET_MODE ASM_CONST(0x0000000040000000)
#define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000)
-#define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
+#define FW_FEATURE_FORM1_AFFINITY ASM_CONST(0x0000000100000000)
#define FW_FEATURE_PRRN ASM_CONST(0x0000000200000000)
#define FW_FEATURE_DRMEM_V2 ASM_CONST(0x0000000400000000)
#define FW_FEATURE_DRC_INFO ASM_CONST(0x0000000800000000)
@@ -53,6 +53,7 @@
#define FW_FEATURE_ULTRAVISOR ASM_CONST(0x0000004000000000)
#define FW_FEATURE_STUFF_TCE ASM_CONST(0x0000008000000000)
#define FW_FEATURE_RPT_INVALIDATE ASM_CONST(0x0000010000000000)
+#define FW_FEATURE_FORM2_AFFINITY ASM_CONST(0x0000020000000000)
#ifndef __ASSEMBLY__
@@ -69,11 +70,11 @@ enum {
FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO |
FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY |
- FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN |
+ FW_FEATURE_FORM1_AFFINITY | FW_FEATURE_PRRN |
FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRMEM_V2 |
FW_FEATURE_DRC_INFO | FW_FEATURE_BLOCK_REMOVE |
FW_FEATURE_PAPR_SCM | FW_FEATURE_ULTRAVISOR |
- FW_FEATURE_RPT_INVALIDATE,
+ FW_FEATURE_RPT_INVALIDATE | FW_FEATURE_FORM2_AFFINITY,
FW_FEATURE_PSERIES_ALWAYS = 0,
FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_ULTRAVISOR,
FW_FEATURE_POWERNV_ALWAYS = 0,
diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
index deef7c94d7b6..bf3b84128525 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
@@ -154,6 +154,7 @@ extern int iommu_tce_table_put(struct iommu_table *tbl);
*/
extern struct iommu_table *iommu_init_table(struct iommu_table *tbl,
int nid, unsigned long res_start, unsigned long res_end);
+bool iommu_table_in_use(struct iommu_table *tbl);
#define IOMMU_TABLE_GROUP_MAX_TABLES 2
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index eaf3a562bf1e..19b6942c6969 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -39,6 +39,7 @@ struct kvm_nested_guest {
pgd_t *shadow_pgtable; /* our page table for this guest */
u64 l1_gr_to_hr; /* L1's addr of part'n-scoped table */
u64 process_table; /* process table entry for this guest */
+ u64 hfscr; /* HFSCR that the L1 requested for this nested guest */
long refcnt; /* number of pointers to this struct */
struct mutex tlb_lock; /* serialize page faults and tlbies */
struct kvm_nested_guest *next;
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 9f52f282b1aa..080a7feb7731 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
u64 emulated_inst_exits;
u64 dec_exits;
u64 ext_intr_exits;
- u64 halt_wait_ns;
u64 halt_successful_wait;
u64 dbell_exits;
u64 gdbell_exits;
@@ -811,6 +810,8 @@ struct kvm_vcpu_arch {
u32 online;
+ u64 hfscr_permitted; /* A mask of permitted HFSCR facilities */
+
/* For support of nested guests */
struct kvm_nested_guest *nested;
u32 nested_vcpu_id;
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 2d88944f9f34..671fbd1a765e 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -664,9 +664,9 @@ extern int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
struct kvm_vcpu *vcpu, u32 cpu);
extern void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu);
extern int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
- struct irq_desc *host_desc);
+ unsigned long host_irq);
extern int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
- struct irq_desc *host_desc);
+ unsigned long host_irq);
extern u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu);
extern int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
diff --git a/arch/powerpc/include/asm/membarrier.h b/arch/powerpc/include/asm/membarrier.h
index 6e20bb5c74ea..de7f79157918 100644
--- a/arch/powerpc/include/asm/membarrier.h
+++ b/arch/powerpc/include/asm/membarrier.h
@@ -12,7 +12,8 @@ static inline void membarrier_arch_switch_mm(struct mm_struct *prev,
* when switching from userspace to kernel is not needed after
* store to rq->curr.
*/
- if (likely(!(atomic_read(&next->membarrier_state) &
+ if (IS_ENABLED(CONFIG_SMP) &&
+ likely(!(atomic_read(&next->membarrier_state) &
(MEMBARRIER_STATE_PRIVATE_EXPEDITED |
MEMBARRIER_STATE_GLOBAL_EXPEDITED)) || !prev))
return;
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 27016b98ecb2..8abe8e42e045 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -324,7 +324,7 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
}
#endif /* !CONFIG_DEBUG_VM */
-static inline bool radix_enabled(void)
+static __always_inline bool radix_enabled(void)
{
return mmu_has_feature(MMU_FTR_TYPE_RADIX);
}
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 74424c14515c..90f488fa4c17 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -126,6 +126,11 @@ struct pci_controller {
#endif /* CONFIG_PPC64 */
void *private_data;
+
+ /* IRQ domain hierarchy */
+ struct irq_domain *dev_domain;
+ struct irq_domain *msi_domain;
+ struct fwnode_handle *fwnode;
};
/* These are used for config access before all the PCI probing
diff --git a/arch/powerpc/include/asm/pmc.h b/arch/powerpc/include/asm/pmc.h
index c6bbe9778d3c..3c09109e708e 100644
--- a/arch/powerpc/include/asm/pmc.h
+++ b/arch/powerpc/include/asm/pmc.h
@@ -34,6 +34,13 @@ static inline void ppc_set_pmu_inuse(int inuse)
#endif
}
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+static inline int ppc_get_pmu_inuse(void)
+{
+ return get_paca()->pmcregs_in_use;
+}
+#endif
+
extern void power4_enable_pmcs(void);
#else /* CONFIG_PPC64 */
diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h
index d0ee0ede5767..b3f480799352 100644
--- a/arch/powerpc/include/asm/pnv-pci.h
+++ b/arch/powerpc/include/asm/pnv-pci.h
@@ -33,7 +33,7 @@ int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num);
void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num);
int pnv_cxl_get_irq_count(struct pci_dev *dev);
struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev);
-int64_t pnv_opal_pci_msi_eoi(struct irq_chip *chip, unsigned int hw_irq);
+int64_t pnv_opal_pci_msi_eoi(struct irq_data *d);
bool is_pnv_opal_msi(struct irq_chip *chip);
#ifdef CONFIG_CXL_BASE
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index bede76dd3db7..baea657bc868 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -576,8 +576,6 @@
#define PPC_DIVDE(t, a, b) stringify_in_c(.long PPC_RAW_DIVDE(t, a, b))
#define PPC_DIVDEU(t, a, b) stringify_in_c(.long PPC_RAW_DIVDEU(t, a, b))
#define PPC_LQARX(t, a, b, eh) stringify_in_c(.long PPC_RAW_LQARX(t, a, b, eh))
-#define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_RAW_LDARX(t, a, b, eh))
-#define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_RAW_LWARX(t, a, b, eh))
#define PPC_STQCX(t, a, b) stringify_in_c(.long PPC_RAW_STQCX(t, a, b))
#define PPC_MADDHD(t, a, b, c) stringify_in_c(.long PPC_RAW_MADDHD(t, a, b, c))
#define PPC_MADDHDU(t, a, b, c) stringify_in_c(.long PPC_RAW_MADDHDU(t, a, b, c))
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 116c1519728a..1c538a9a11e0 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -10,6 +10,7 @@
#include <asm/ppc-opcode.h>
#include <asm/firmware.h>
#include <asm/feature-fixups.h>
+#include <asm/extable.h>
#ifdef __ASSEMBLY__
@@ -259,7 +260,7 @@ n:
/* Be careful, this will clobber the lr register. */
#define LOAD_REG_ADDR_PIC(reg, name) \
- bl 0f; \
+ bcl 20,31,$+4; \
0: mflr reg; \
addis reg,reg,(name - 0b)@ha; \
addi reg,reg,(name - 0b)@l;
@@ -752,16 +753,6 @@ END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)
#endif /* __ASSEMBLY__ */
-/*
- * Helper macro for exception table entries
- */
-#define EX_TABLE(_fault, _target) \
- stringify_in_c(.section __ex_table,"a";)\
- stringify_in_c(.balign 4;) \
- stringify_in_c(.long (_fault) - . ;) \
- stringify_in_c(.long (_target) - . ;) \
- stringify_in_c(.previous)
-
#define SOFT_MASK_TABLE(_start, _end) \
stringify_in_c(.section __soft_mask_table,"a";)\
stringify_in_c(.balign 8;) \
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index 324a13351749..5c80152e8f18 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -147,8 +147,9 @@ extern int of_read_drc_info_cell(struct property **prop,
#define OV5_MSI 0x0201 /* PCIe/MSI support */
#define OV5_CMO 0x0480 /* Cooperative Memory Overcommitment */
#define OV5_XCMO 0x0440 /* Page Coalescing */
-#define OV5_TYPE1_AFFINITY 0x0580 /* Type 1 NUMA affinity */
+#define OV5_FORM1_AFFINITY 0x0580 /* FORM1 NUMA affinity */
#define OV5_PRRN 0x0540 /* Platform Resource Reassignment */
+#define OV5_FORM2_AFFINITY 0x0520 /* Form2 NUMA affinity */
#define OV5_HP_EVT 0x0604 /* Hot Plug Event support */
#define OV5_RESIZE_HPT 0x0601 /* Hash Page Table resizing */
#define OV5_PFO_HW_RNG 0x1180 /* PFO Random Number Generator */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 14422e851494..6e560f035614 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -22,6 +22,7 @@
#include <linux/err.h>
#include <uapi/asm/ptrace.h>
#include <asm/asm-const.h>
+#include <asm/reg.h>
#ifndef __ASSEMBLY__
struct pt_regs
@@ -43,8 +44,14 @@ struct pt_regs
unsigned long mq;
#endif
unsigned long trap;
- unsigned long dar;
- unsigned long dsisr;
+ union {
+ unsigned long dar;
+ unsigned long dear;
+ };
+ union {
+ unsigned long dsisr;
+ unsigned long esr;
+ };
unsigned long result;
};
};
@@ -197,11 +204,7 @@ static inline unsigned long frame_pointer(struct pt_regs *regs)
return 0;
}
-#ifdef __powerpc64__
-#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
-#else
#define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
-#endif
#define force_successful_syscall_return() \
do { \
@@ -286,6 +289,28 @@ static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
regs->gpr[3] = rc;
}
+static inline bool cpu_has_msr_ri(void)
+{
+ return !IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x);
+}
+
+static inline bool regs_is_unrecoverable(struct pt_regs *regs)
+{
+ return unlikely(cpu_has_msr_ri() && !(regs->msr & MSR_RI));
+}
+
+static inline void regs_set_recoverable(struct pt_regs *regs)
+{
+ if (cpu_has_msr_ri())
+ regs_set_return_msr(regs, regs->msr | MSR_RI);
+}
+
+static inline void regs_set_unrecoverable(struct pt_regs *regs)
+{
+ if (cpu_has_msr_ri())
+ regs_set_return_msr(regs, regs->msr & ~MSR_RI);
+}
+
#define arch_has_single_step() (1)
#define arch_has_block_step() (true)
#define ARCH_HAS_USER_SINGLE_STEP_REPORT
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index be85cf156a1f..e9d27265253b 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -415,6 +415,7 @@
#define FSCR_TAR __MASK(FSCR_TAR_LG)
#define FSCR_EBB __MASK(FSCR_EBB_LG)
#define FSCR_DSCR __MASK(FSCR_DSCR_LG)
+#define FSCR_INTR_CAUSE (ASM_CONST(0xFF) << 56) /* interrupt cause */
#define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */
#define HFSCR_PREFIX __MASK(FSCR_PREFIX_LG)
#define HFSCR_MSGP __MASK(FSCR_MSGP_LG)
@@ -426,7 +427,7 @@
#define HFSCR_DSCR __MASK(FSCR_DSCR_LG)
#define HFSCR_VECVSX __MASK(FSCR_VECVSX_LG)
#define HFSCR_FP __MASK(FSCR_FP_LG)
-#define HFSCR_INTR_CAUSE (ASM_CONST(0xFF) << 56) /* interrupt cause */
+#define HFSCR_INTR_CAUSE FSCR_INTR_CAUSE
#define SPRN_TAR 0x32f /* Target Address Register */
#define SPRN_LPCR 0x13E /* LPAR Control Register */
#define LPCR_VPM0 ASM_CONST(0x8000000000000000)
diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h
index 324d7b298ec3..6e4af4492a14 100644
--- a/arch/powerpc/include/asm/sections.h
+++ b/arch/powerpc/include/asm/sections.h
@@ -38,14 +38,6 @@ extern char start_virt_trampolines[];
extern char end_virt_trampolines[];
#endif
-static inline int in_kernel_text(unsigned long addr)
-{
- if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end)
- return 1;
-
- return 0;
-}
-
static inline unsigned long kernel_toc_addr(void)
{
/* Defined by the linker, see vmlinux.lds.S */
diff --git a/arch/powerpc/include/asm/simple_spinlock.h b/arch/powerpc/include/asm/simple_spinlock.h
index 552f325412cc..8985791a2ba5 100644
--- a/arch/powerpc/include/asm/simple_spinlock.h
+++ b/arch/powerpc/include/asm/simple_spinlock.h
@@ -51,7 +51,7 @@ static inline unsigned long __arch_spin_trylock(arch_spinlock_t *lock)
token = LOCK_TOKEN;
__asm__ __volatile__(
-"1: " PPC_LWARX(%0,0,%2,1) "\n\
+"1: lwarx %0,0,%2,1\n\
cmpwi 0,%0,0\n\
bne- 2f\n\
stwcx. %1,0,%2\n\
@@ -179,7 +179,7 @@ static inline long __arch_read_trylock(arch_rwlock_t *rw)
long tmp;
__asm__ __volatile__(
-"1: " PPC_LWARX(%0,0,%1,1) "\n"
+"1: lwarx %0,0,%1,1\n"
__DO_SIGN_EXTEND
" addic. %0,%0,1\n\
ble- 2f\n"
@@ -203,7 +203,7 @@ static inline long __arch_write_trylock(arch_rwlock_t *rw)
token = WRLOCK_TOKEN;
__asm__ __volatile__(
-"1: " PPC_LWARX(%0,0,%2,1) "\n\
+"1: lwarx %0,0,%2,1\n\
cmpwi 0,%0,0\n\
bne- 2f\n"
" stwcx. %1,0,%2\n\
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 03b3d010cbab..7ef1cd8168a0 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -33,6 +33,10 @@ extern bool coregroup_enabled;
extern int cpu_to_chip_id(int cpu);
extern int *chip_id_lookup_table;
+DECLARE_PER_CPU(cpumask_var_t, thread_group_l1_cache_map);
+DECLARE_PER_CPU(cpumask_var_t, thread_group_l2_cache_map);
+DECLARE_PER_CPU(cpumask_var_t, thread_group_l3_cache_map);
+
#ifdef CONFIG_SMP
struct smp_ops_t {
@@ -141,6 +145,7 @@ extern int cpu_to_core_id(int cpu);
extern bool has_big_cores;
extern bool thread_group_shares_l2;
+extern bool thread_group_shares_l3;
#define cpu_smt_mask cpu_smt_mask
#ifdef CONFIG_SCHED_SMT
@@ -195,6 +200,7 @@ extern void __cpu_die(unsigned int cpu);
#define hard_smp_processor_id() get_hard_smp_processor_id(0)
#define smp_setup_cpu_maps()
#define thread_group_shares_l2 0
+#define thread_group_shares_l3 0
static inline void inhibit_secondary_onlining(void) {}
static inline void uninhibit_secondary_onlining(void) {}
static inline const struct cpumask *cpu_sibling_mask(int cpu)
diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h
index ba0f88f3a30d..c60ebd04b2ed 100644
--- a/arch/powerpc/include/asm/syscall.h
+++ b/arch/powerpc/include/asm/syscall.h
@@ -90,10 +90,9 @@ static inline void syscall_get_arguments(struct task_struct *task,
unsigned long val, mask = -1UL;
unsigned int n = 6;
-#ifdef CONFIG_COMPAT
- if (test_tsk_thread_flag(task, TIF_32BIT))
+ if (is_32bit_task())
mask = 0xffffffff;
-#endif
+
while (n--) {
if (n == 0)
val = regs->orig_gpr3;
@@ -116,16 +115,11 @@ static inline void syscall_set_arguments(struct task_struct *task,
static inline int syscall_get_arch(struct task_struct *task)
{
- int arch;
-
- if (IS_ENABLED(CONFIG_PPC64) && !test_tsk_thread_flag(task, TIF_32BIT))
- arch = AUDIT_ARCH_PPC64;
+ if (is_32bit_task())
+ return AUDIT_ARCH_PPC;
+ else if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
+ return AUDIT_ARCH_PPC64LE;
else
- arch = AUDIT_ARCH_PPC;
-
-#ifdef __LITTLE_ENDIAN__
- arch |= __AUDIT_ARCH_LE;
-#endif
- return arch;
+ return AUDIT_ARCH_PPC64;
}
#endif /* _ASM_SYSCALL_H */
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h
index 398171fdcd9f..7ee66ae5444d 100644
--- a/arch/powerpc/include/asm/syscalls.h
+++ b/arch/powerpc/include/asm/syscalls.h
@@ -6,6 +6,7 @@
#include <linux/compiler.h>
#include <linux/linkage.h>
#include <linux/types.h>
+#include <linux/compat.h>
struct rtas_args;
@@ -18,5 +19,34 @@ asmlinkage long sys_mmap2(unsigned long addr, size_t len,
asmlinkage long ppc64_personality(unsigned long personality);
asmlinkage long sys_rtas(struct rtas_args __user *uargs);
+#ifdef CONFIG_COMPAT
+unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
+
+compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
+ u32 reg6, u32 pos1, u32 pos2);
+
+compat_ssize_t compat_sys_pwrite64(unsigned int fd, const char __user *ubuf, compat_size_t count,
+ u32 reg6, u32 pos1, u32 pos2);
+
+compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offset1, u32 offset2, u32 count);
+
+int compat_sys_truncate64(const char __user *path, u32 reg4,
+ unsigned long len1, unsigned long len2);
+
+long compat_sys_fallocate(int fd, int mode, u32 offset1, u32 offset2, u32 len1, u32 len2);
+
+int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long len1,
+ unsigned long len2);
+
+long ppc32_fadvise64(int fd, u32 unused, u32 offset1, u32 offset2,
+ size_t len, int advice);
+
+long compat_sys_sync_file_range2(int fd, unsigned int flags,
+ unsigned int offset1, unsigned int offset2,
+ unsigned int nbytes1, unsigned int nbytes2);
+#endif
+
#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_SYSCALLS_H */
diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h
index db5fc2f2262d..0c34d2756d92 100644
--- a/arch/powerpc/include/asm/tce.h
+++ b/arch/powerpc/include/asm/tce.h
@@ -19,15 +19,7 @@
#define TCE_VB 0
#define TCE_PCI 1
-/* TCE page size is 4096 bytes (1 << 12) */
-
-#define TCE_SHIFT 12
-#define TCE_PAGE_SIZE (1 << TCE_SHIFT)
-
#define TCE_ENTRY_SIZE 8 /* each TCE is 64 bits */
-
-#define TCE_RPN_MASK 0xfffffffffful /* 40-bit RPN (4K pages) */
-#define TCE_RPN_SHIFT 12
#define TCE_VALID 0x800 /* TCE valid */
#define TCE_ALLIO 0x400 /* TCE valid for all lpars */
#define TCE_PCI_WRITE 0x2 /* write from PCI allowed */
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index e4db64c0e184..36fcafb1fd6d 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -36,7 +36,7 @@ static inline int pcibus_to_node(struct pci_bus *bus)
cpu_all_mask : \
cpumask_of_node(pcibus_to_node(bus)))
-extern int cpu_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc);
+int cpu_relative_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc);
extern int __node_distance(int, int);
#define node_distance(a, b) __node_distance(a, b)
@@ -64,6 +64,12 @@ static inline int early_cpu_to_node(int cpu)
}
int of_drconf_to_nid_single(struct drmem_lmb *lmb);
+void update_numa_distance(struct device_node *node);
+
+extern void map_cpu_to_node(int cpu, int node);
+#ifdef CONFIG_HOTPLUG_CPU
+extern void unmap_cpu_from_node(unsigned long cpu);
+#endif /* CONFIG_HOTPLUG_CPU */
#else
@@ -83,7 +89,7 @@ static inline void sysfs_remove_device_from_node(struct device *dev,
static inline void update_numa_cpu_lookup_table(unsigned int cpu, int node) {}
-static inline int cpu_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
+static inline int cpu_relative_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
{
return 0;
}
@@ -93,6 +99,15 @@ static inline int of_drconf_to_nid_single(struct drmem_lmb *lmb)
return first_online_node;
}
+static inline void update_numa_distance(struct device_node *node) {}
+
+#ifdef CONFIG_SMP
+static inline void map_cpu_to_node(int cpu, int node) {}
+#ifdef CONFIG_HOTPLUG_CPU
+static inline void unmap_cpu_from_node(unsigned long cpu) {}
+#endif /* CONFIG_HOTPLUG_CPU */
+#endif /* CONFIG_SMP */
+
#endif /* CONFIG_NUMA */
#if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR)
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index b541c690a31c..5eb462af6766 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -9,8 +9,6 @@
#define NR_syscalls __NR_syscalls
-#define __NR__exit __NR_exit
-
#ifndef __ASSEMBLY__
#include <linux/types.h>
diff --git a/arch/powerpc/include/asm/vdso/processor.h b/arch/powerpc/include/asm/vdso/processor.h
index e072577bc7c0..8d79f994b4aa 100644
--- a/arch/powerpc/include/asm/vdso/processor.h
+++ b/arch/powerpc/include/asm/vdso/processor.h
@@ -5,12 +5,21 @@
#ifndef __ASSEMBLY__
/* Macros for adjusting thread priority (hardware multi-threading) */
+#ifdef CONFIG_PPC64
#define HMT_very_low() asm volatile("or 31, 31, 31 # very low priority")
#define HMT_low() asm volatile("or 1, 1, 1 # low priority")
#define HMT_medium_low() asm volatile("or 6, 6, 6 # medium low priority")
#define HMT_medium() asm volatile("or 2, 2, 2 # medium priority")
#define HMT_medium_high() asm volatile("or 5, 5, 5 # medium high priority")
#define HMT_high() asm volatile("or 3, 3, 3 # high priority")
+#else
+#define HMT_very_low()
+#define HMT_low()
+#define HMT_medium_low()
+#define HMT_medium()
+#define HMT_medium_high()
+#define HMT_high()
+#endif
#ifdef CONFIG_PPC64
#define cpu_relax() do { HMT_low(); HMT_medium(); barrier(); } while (0)
diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h
index d9cf192368ad..0ac9bfddf704 100644
--- a/arch/powerpc/include/asm/xics.h
+++ b/arch/powerpc/include/asm/xics.h
@@ -89,10 +89,11 @@ static inline int ics_opal_init(void) { return -ENODEV; }
/* ICS instance, hooked up to chip_data of an irq */
struct ics {
struct list_head link;
- int (*map)(struct ics *ics, unsigned int virq);
+ int (*check)(struct ics *ics, unsigned int hwirq);
void (*mask_unknown)(struct ics *ics, unsigned long vec);
long (*get_server)(struct ics *ics, unsigned long vec);
int (*host_match)(struct ics *ics, struct device_node *node);
+ struct irq_chip *chip;
char data[];
};
diff --git a/arch/powerpc/include/asm/xive-regs.h b/arch/powerpc/include/asm/xive-regs.h
index 8b211faa0e42..cf8bb6ac4463 100644
--- a/arch/powerpc/include/asm/xive-regs.h
+++ b/arch/powerpc/include/asm/xive-regs.h
@@ -80,10 +80,13 @@
#define TM_QW0W2_VU PPC_BIT32(0)
#define TM_QW0W2_LOGIC_SERV PPC_BITMASK32(1,31) // XX 2,31 ?
#define TM_QW1W2_VO PPC_BIT32(0)
+#define TM_QW1W2_HO PPC_BIT32(1) /* P10 XIVE2 */
#define TM_QW1W2_OS_CAM PPC_BITMASK32(8,31)
#define TM_QW2W2_VP PPC_BIT32(0)
+#define TM_QW2W2_HP PPC_BIT32(1) /* P10 XIVE2 */
#define TM_QW2W2_POOL_CAM PPC_BITMASK32(8,31)
#define TM_QW3W2_VT PPC_BIT32(0)
+#define TM_QW3W2_HT PPC_BIT32(1) /* P10 XIVE2 */
#define TM_QW3W2_LP PPC_BIT32(6)
#define TM_QW3W2_LE PPC_BIT32(7)
#define TM_QW3W2_T PPC_BIT32(31)
diff --git a/arch/powerpc/include/asm/xive.h b/arch/powerpc/include/asm/xive.h
index aa094a8655b0..92930b0b5d0e 100644
--- a/arch/powerpc/include/asm/xive.h
+++ b/arch/powerpc/include/asm/xive.h
@@ -111,6 +111,7 @@ void xive_native_free_vp_block(u32 vp_base);
int xive_native_populate_irq_data(u32 hw_irq,
struct xive_irq_data *data);
void xive_cleanup_irq_data(struct xive_irq_data *xd);
+void xive_irq_free_data(unsigned int virq);
void xive_native_free_irq(u32 irq);
int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq);
@@ -125,6 +126,7 @@ int xive_native_enable_vp(u32 vp_id, bool single_escalation);
int xive_native_disable_vp(u32 vp_id);
int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id);
bool xive_native_has_single_escalation(void);
+bool xive_native_has_save_restore(void);
int xive_native_get_queue_info(u32 vp_id, uint32_t prio,
u64 *out_qpage,
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index f66b63e81c3b..7be36c1e1db6 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -46,7 +46,8 @@ obj-y := cputable.o syscalls.o \
prom.o traps.o setup-common.o \
udbg.o misc.o io.o misc_$(BITS).o \
of_platform.o prom_parse.o firmware.o \
- hw_breakpoint_constraints.o interrupt.o
+ hw_breakpoint_constraints.o interrupt.o \
+ kdebugfs.o
obj-y += ptrace/
obj-$(CONFIG_PPC64) += setup_64.o \
paca.o nvram_64.o note.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 5bee245d832b..e563d3222d69 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -286,23 +286,16 @@ int main(void)
STACK_PT_REGS_OFFSET(_CCR, ccr);
STACK_PT_REGS_OFFSET(_XER, xer);
STACK_PT_REGS_OFFSET(_DAR, dar);
+ STACK_PT_REGS_OFFSET(_DEAR, dear);
STACK_PT_REGS_OFFSET(_DSISR, dsisr);
+ STACK_PT_REGS_OFFSET(_ESR, esr);
STACK_PT_REGS_OFFSET(ORIG_GPR3, orig_gpr3);
STACK_PT_REGS_OFFSET(RESULT, result);
STACK_PT_REGS_OFFSET(_TRAP, trap);
-#ifndef CONFIG_PPC64
- /*
- * The PowerPC 400-class & Book-E processors have neither the DAR
- * nor the DSISR SPRs. Hence, we overload them to hold the similar
- * DEAR and ESR SPRs for such processors. For critical interrupts
- * we use them to hold SRR0 and SRR1.
- */
- STACK_PT_REGS_OFFSET(_DEAR, dar);
- STACK_PT_REGS_OFFSET(_ESR, dsisr);
-#else /* CONFIG_PPC64 */
+#ifdef CONFIG_PPC64
STACK_PT_REGS_OFFSET(SOFTE, softe);
STACK_PT_REGS_OFFSET(_PPR, ppr);
-#endif /* CONFIG_PPC64 */
+#endif
#ifdef CONFIG_PPC_PKEY
STACK_PT_REGS_OFFSET(STACK_REGS_AMR, amr);
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
index 6f903e9aa20b..cf1be75b7833 100644
--- a/arch/powerpc/kernel/cacheinfo.c
+++ b/arch/powerpc/kernel/cacheinfo.c
@@ -120,6 +120,7 @@ struct cache {
struct cpumask shared_cpu_map; /* online CPUs using this cache */
int type; /* split cache disambiguation */
int level; /* level not explicit in device tree */
+ int group_id; /* id of the group of threads that share this cache */
struct list_head list; /* global list of cache objects */
struct cache *next_local; /* next cache of >= level */
};
@@ -142,22 +143,24 @@ static const char *cache_type_string(const struct cache *cache)
}
static void cache_init(struct cache *cache, int type, int level,
- struct device_node *ofnode)
+ struct device_node *ofnode, int group_id)
{
cache->type = type;
cache->level = level;
cache->ofnode = of_node_get(ofnode);
+ cache->group_id = group_id;
INIT_LIST_HEAD(&cache->list);
list_add(&cache->list, &cache_list);
}
-static struct cache *new_cache(int type, int level, struct device_node *ofnode)
+static struct cache *new_cache(int type, int level,
+ struct device_node *ofnode, int group_id)
{
struct cache *cache;
cache = kzalloc(sizeof(*cache), GFP_KERNEL);
if (cache)
- cache_init(cache, type, level, ofnode);
+ cache_init(cache, type, level, ofnode, group_id);
return cache;
}
@@ -309,20 +312,24 @@ static struct cache *cache_find_first_sibling(struct cache *cache)
return cache;
list_for_each_entry(iter, &cache_list, list)
- if (iter->ofnode == cache->ofnode && iter->next_local == cache)
+ if (iter->ofnode == cache->ofnode &&
+ iter->group_id == cache->group_id &&
+ iter->next_local == cache)
return iter;
return cache;
}
-/* return the first cache on a local list matching node */
-static struct cache *cache_lookup_by_node(const struct device_node *node)
+/* return the first cache on a local list matching node and thread-group id */
+static struct cache *cache_lookup_by_node_group(const struct device_node *node,
+ int group_id)
{
struct cache *cache = NULL;
struct cache *iter;
list_for_each_entry(iter, &cache_list, list) {
- if (iter->ofnode != node)
+ if (iter->ofnode != node ||
+ iter->group_id != group_id)
continue;
cache = cache_find_first_sibling(iter);
break;
@@ -352,14 +359,15 @@ static int cache_is_unified_d(const struct device_node *np)
CACHE_TYPE_UNIFIED_D : CACHE_TYPE_UNIFIED;
}
-static struct cache *cache_do_one_devnode_unified(struct device_node *node, int level)
+static struct cache *cache_do_one_devnode_unified(struct device_node *node, int group_id,
+ int level)
{
pr_debug("creating L%d ucache for %pOFP\n", level, node);
- return new_cache(cache_is_unified_d(node), level, node);
+ return new_cache(cache_is_unified_d(node), level, node, group_id);
}
-static struct cache *cache_do_one_devnode_split(struct device_node *node,
+static struct cache *cache_do_one_devnode_split(struct device_node *node, int group_id,
int level)
{
struct cache *dcache, *icache;
@@ -367,8 +375,8 @@ static struct cache *cache_do_one_devnode_split(struct device_node *node,
pr_debug("creating L%d dcache and icache for %pOFP\n", level,
node);
- dcache = new_cache(CACHE_TYPE_DATA, level, node);
- icache = new_cache(CACHE_TYPE_INSTRUCTION, level, node);
+ dcache = new_cache(CACHE_TYPE_DATA, level, node, group_id);
+ icache = new_cache(CACHE_TYPE_INSTRUCTION, level, node, group_id);
if (!dcache || !icache)
goto err;
@@ -382,31 +390,32 @@ err:
return NULL;
}
-static struct cache *cache_do_one_devnode(struct device_node *node, int level)
+static struct cache *cache_do_one_devnode(struct device_node *node, int group_id, int level)
{
struct cache *cache;
if (cache_node_is_unified(node))
- cache = cache_do_one_devnode_unified(node, level);
+ cache = cache_do_one_devnode_unified(node, group_id, level);
else
- cache = cache_do_one_devnode_split(node, level);
+ cache = cache_do_one_devnode_split(node, group_id, level);
return cache;
}
static struct cache *cache_lookup_or_instantiate(struct device_node *node,
+ int group_id,
int level)
{
struct cache *cache;
- cache = cache_lookup_by_node(node);
+ cache = cache_lookup_by_node_group(node, group_id);
WARN_ONCE(cache && cache->level != level,
"cache level mismatch on lookup (got %d, expected %d)\n",
cache->level, level);
if (!cache)
- cache = cache_do_one_devnode(node, level);
+ cache = cache_do_one_devnode(node, group_id, level);
return cache;
}
@@ -443,7 +452,30 @@ static void do_subsidiary_caches_debugcheck(struct cache *cache)
of_node_get_device_type(cache->ofnode));
}
-static void do_subsidiary_caches(struct cache *cache)
+/*
+ * If sub-groups of threads in a core containing @cpu_id share the
+ * L@level-cache (information obtained via "ibm,thread-groups"
+ * device-tree property), then we identify the group by the first
+ * thread-sibling in the group. We define this to be the group-id.
+ *
+ * In the absence of any thread-group information for L@level-cache,
+ * this function returns -1.
+ */
+static int get_group_id(unsigned int cpu_id, int level)
+{
+ if (has_big_cores && level == 1)
+ return cpumask_first(per_cpu(thread_group_l1_cache_map,
+ cpu_id));
+ else if (thread_group_shares_l2 && level == 2)
+ return cpumask_first(per_cpu(thread_group_l2_cache_map,
+ cpu_id));
+ else if (thread_group_shares_l3 && level == 3)
+ return cpumask_first(per_cpu(thread_group_l3_cache_map,
+ cpu_id));
+ return -1;
+}
+
+static void do_subsidiary_caches(struct cache *cache, unsigned int cpu_id)
{
struct device_node *subcache_node;
int level = cache->level;
@@ -452,9 +484,11 @@ static void do_subsidiary_caches(struct cache *cache)
while ((subcache_node = of_find_next_cache_node(cache->ofnode))) {
struct cache *subcache;
+ int group_id;
level++;
- subcache = cache_lookup_or_instantiate(subcache_node, level);
+ group_id = get_group_id(cpu_id, level);
+ subcache = cache_lookup_or_instantiate(subcache_node, group_id, level);
of_node_put(subcache_node);
if (!subcache)
break;
@@ -468,6 +502,7 @@ static struct cache *cache_chain_instantiate(unsigned int cpu_id)
{
struct device_node *cpu_node;
struct cache *cpu_cache = NULL;
+ int group_id;
pr_debug("creating cache object(s) for CPU %i\n", cpu_id);
@@ -476,11 +511,13 @@ static struct cache *cache_chain_instantiate(unsigned int cpu_id)
if (!cpu_node)
goto out;
- cpu_cache = cache_lookup_or_instantiate(cpu_node, 1);
+ group_id = get_group_id(cpu_id, 1);
+
+ cpu_cache = cache_lookup_or_instantiate(cpu_node, group_id, 1);
if (!cpu_cache)
goto out;
- do_subsidiary_caches(cpu_cache);
+ do_subsidiary_caches(cpu_cache, cpu_id);
cache_cpu_set(cpu_cache, cpu_id);
out:
@@ -641,45 +678,6 @@ static ssize_t level_show(struct kobject *k, struct kobj_attribute *attr, char *
static struct kobj_attribute cache_level_attr =
__ATTR(level, 0444, level_show, NULL);
-static unsigned int index_dir_to_cpu(struct cache_index_dir *index)
-{
- struct kobject *index_dir_kobj = &index->kobj;
- struct kobject *cache_dir_kobj = index_dir_kobj->parent;
- struct kobject *cpu_dev_kobj = cache_dir_kobj->parent;
- struct device *dev = kobj_to_dev(cpu_dev_kobj);
-
- return dev->id;
-}
-
-/*
- * On big-core systems, each core has two groups of CPUs each of which
- * has its own L1-cache. The thread-siblings which share l1-cache with
- * @cpu can be obtained via cpu_smallcore_mask().
- *
- * On some big-core systems, the L2 cache is shared only between some
- * groups of siblings. This is already parsed and encoded in
- * cpu_l2_cache_mask().
- *
- * TODO: cache_lookup_or_instantiate() needs to be made aware of the
- * "ibm,thread-groups" property so that cache->shared_cpu_map
- * reflects the correct siblings on platforms that have this
- * device-tree property. This helper function is only a stop-gap
- * solution so that we report the correct siblings to the
- * userspace via sysfs.
- */
-static const struct cpumask *get_shared_cpu_map(struct cache_index_dir *index, struct cache *cache)
-{
- if (has_big_cores) {
- int cpu = index_dir_to_cpu(index);
- if (cache->level == 1)
- return cpu_smallcore_mask(cpu);
- if (cache->level == 2 && thread_group_shares_l2)
- return cpu_l2_cache_mask(cpu);
- }
-
- return &cache->shared_cpu_map;
-}
-
static ssize_t
show_shared_cpumap(struct kobject *k, struct kobj_attribute *attr, char *buf, bool list)
{
@@ -690,7 +688,7 @@ show_shared_cpumap(struct kobject *k, struct kobj_attribute *attr, char *buf, bo
index = kobj_to_cache_index_dir(k);
cache = index->cache;
- mask = get_shared_cpu_map(index, cache);
+ mask = &cache->shared_cpu_map;
return cpumap_print_to_pagebuf(list, buf, mask);
}
@@ -848,13 +846,15 @@ static struct cache *cache_lookup_by_cpu(unsigned int cpu_id)
{
struct device_node *cpu_node;
struct cache *cache;
+ int group_id;
cpu_node = of_get_cpu_node(cpu_id, NULL);
WARN_ONCE(!cpu_node, "no OF node found for CPU %i\n", cpu_id);
if (!cpu_node)
return NULL;
- cache = cache_lookup_by_node(cpu_node);
+ group_id = get_group_id(cpu_id, 1);
+ cache = cache_lookup_by_node_group(cpu_node, group_id);
of_node_put(cpu_node);
return cache;
diff --git a/arch/powerpc/kernel/dawr.c b/arch/powerpc/kernel/dawr.c
index cdc2dccb987d..64e423d2fe0f 100644
--- a/arch/powerpc/kernel/dawr.c
+++ b/arch/powerpc/kernel/dawr.c
@@ -9,7 +9,6 @@
#include <linux/export.h>
#include <linux/fs.h>
#include <linux/debugfs.h>
-#include <asm/debugfs.h>
#include <asm/machdep.h>
#include <asm/hvcall.h>
@@ -101,7 +100,7 @@ static int __init dawr_force_setup(void)
if (PVR_VER(mfspr(SPRN_PVR)) == PVR_POWER9) {
/* Turn DAWR off by default, but allow admin to turn it on */
debugfs_create_file_unsafe("dawr_enable_dangerous", 0600,
- powerpc_debugfs_root,
+ arch_debugfs_dir,
&dawr_force_enable,
&dawr_enable_fops);
}
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 3bbdcc86d01b..e9b597ed423c 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -21,9 +21,9 @@
#include <linux/spinlock.h>
#include <linux/export.h>
#include <linux/of.h>
+#include <linux/debugfs.h>
#include <linux/atomic.h>
-#include <asm/debugfs.h>
#include <asm/eeh.h>
#include <asm/eeh_event.h>
#include <asm/io.h>
@@ -1901,24 +1901,24 @@ static int __init eeh_init_proc(void)
proc_create_single("powerpc/eeh", 0, NULL, proc_eeh_show);
#ifdef CONFIG_DEBUG_FS
debugfs_create_file_unsafe("eeh_enable", 0600,
- powerpc_debugfs_root, NULL,
+ arch_debugfs_dir, NULL,
&eeh_enable_dbgfs_ops);
debugfs_create_u32("eeh_max_freezes", 0600,
- powerpc_debugfs_root, &eeh_max_freezes);
+ arch_debugfs_dir, &eeh_max_freezes);
debugfs_create_bool("eeh_disable_recovery", 0600,
- powerpc_debugfs_root,
+ arch_debugfs_dir,
&eeh_debugfs_no_recover);
debugfs_create_file_unsafe("eeh_dev_check", 0600,
- powerpc_debugfs_root, NULL,
+ arch_debugfs_dir, NULL,
&eeh_dev_check_fops);
debugfs_create_file_unsafe("eeh_dev_break", 0600,
- powerpc_debugfs_root, NULL,
+ arch_debugfs_dir, NULL,
&eeh_dev_break_fops);
debugfs_create_file_unsafe("eeh_force_recover", 0600,
- powerpc_debugfs_root, NULL,
+ arch_debugfs_dir, NULL,
&eeh_force_recover_fops);
debugfs_create_file_unsafe("eeh_dev_can_recover", 0600,
- powerpc_debugfs_root, NULL,
+ arch_debugfs_dir, NULL,
&eeh_dev_can_recover_fops);
eeh_cache_debugfs_init();
#endif
diff --git a/arch/powerpc/kernel/eeh_cache.c b/arch/powerpc/kernel/eeh_cache.c
index bf3270426d82..9bdaaf7fddc9 100644
--- a/arch/powerpc/kernel/eeh_cache.c
+++ b/arch/powerpc/kernel/eeh_cache.c
@@ -12,8 +12,8 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/atomic.h>
+#include <linux/debugfs.h>
#include <asm/pci-bridge.h>
-#include <asm/debugfs.h>
#include <asm/ppc-pci.h>
@@ -283,6 +283,6 @@ DEFINE_SHOW_ATTRIBUTE(eeh_addr_cache);
void eeh_cache_debugfs_init(void)
{
debugfs_create_file_unsafe("eeh_address_cache", 0400,
- powerpc_debugfs_root, NULL,
+ arch_debugfs_dir, NULL,
&eeh_addr_cache_fops);
}
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 0273a1349006..61fdd53cdd9a 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -161,10 +161,10 @@ ret_from_fork:
ret_from_kernel_thread:
REST_NVGPRS(r1)
bl schedule_tail
- mtlr r14
+ mtctr r14
mr r3,r15
PPC440EP_ERR42
- blrl
+ bctrl
li r3,0
b ret_from_syscall
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 15720f8661a1..70cff7b49e17 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -309,7 +309,7 @@ _GLOBAL(enter_rtas)
*/
lbz r0,PACAIRQSOFTMASK(r13)
1: tdeqi r0,IRQS_ENABLED
- EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING
+ EMIT_WARN_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING
#endif
/* Hard-disable interrupts */
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 1401787b0b93..711c66b76df1 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -545,8 +545,8 @@ __end_interrupts:
PROLOG_ADDITION_2REGS)
mfspr r14,SPRN_DEAR
mfspr r15,SPRN_ESR
- std r14,_DAR(r1)
- std r15,_DSISR(r1)
+ std r14,_DEAR(r1)
+ std r15,_ESR(r1)
ld r14,PACA_EXGEN+EX_R14(r13)
ld r15,PACA_EXGEN+EX_R15(r13)
EXCEPTION_COMMON(0x300)
@@ -558,8 +558,8 @@ __end_interrupts:
PROLOG_ADDITION_2REGS)
li r15,0
mr r14,r10
- std r14,_DAR(r1)
- std r15,_DSISR(r1)
+ std r14,_DEAR(r1)
+ std r15,_ESR(r1)
ld r14,PACA_EXGEN+EX_R14(r13)
ld r15,PACA_EXGEN+EX_R15(r13)
EXCEPTION_COMMON(0x400)
@@ -575,8 +575,8 @@ __end_interrupts:
PROLOG_ADDITION_2REGS)
mfspr r14,SPRN_DEAR
mfspr r15,SPRN_ESR
- std r14,_DAR(r1)
- std r15,_DSISR(r1)
+ std r14,_DEAR(r1)
+ std r15,_ESR(r1)
ld r14,PACA_EXGEN+EX_R14(r13)
ld r15,PACA_EXGEN+EX_R15(r13)
EXCEPTION_COMMON(0x600)
@@ -587,7 +587,7 @@ __end_interrupts:
NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
PROLOG_ADDITION_1REG)
mfspr r14,SPRN_ESR
- std r14,_DSISR(r1)
+ std r14,_ESR(r1)
ld r14,PACA_EXGEN+EX_R14(r13)
EXCEPTION_COMMON(0x700)
addi r3,r1,STACK_FRAME_OVERHEAD
@@ -1057,8 +1057,8 @@ bad_stack_book3e:
std r11,_CCR(r1)
mfspr r10,SPRN_DEAR
mfspr r11,SPRN_ESR
- std r10,_DAR(r1)
- std r11,_DSISR(r1)
+ std r10,_DEAR(r1)
+ std r11,_ESR(r1)
std r0,GPR0(r1); /* save r0 in stackframe */ \
std r2,GPR2(r1); /* save r2 in stackframe */ \
SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \
@@ -1127,7 +1127,7 @@ found_iprot:
* r3 = MAS0_TLBSEL (for the iprot array)
* r4 = SPRN_TLBnCFG
*/
- bl invstr /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
invstr: mflr r6 /* Make it accessible */
mfmsr r7
rlwinm r5,r7,27,31,31 /* extract MSR[IS] */
@@ -1196,7 +1196,7 @@ skpinv: addi r6,r6,1 /* Increment */
mfmsr r6
xori r6,r6,MSR_IS
mtspr SPRN_SRR1,r6
- bl 1f /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
1: mflr r6
addi r6,r6,(2f - 1b)
mtspr SPRN_SRR0,r6
@@ -1256,7 +1256,7 @@ skpinv: addi r6,r6,1 /* Increment */
* r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
*/
/* Now we branch the new virtual address mapped by this entry */
- bl 1f /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
1: mflr r6
addi r6,r6,(2f - 1b)
tovirt(r6,r6)
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index b990075285f5..b7ceb041743c 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -24,8 +24,8 @@
#include <linux/slab.h>
#include <linux/cma.h>
#include <linux/hugetlb.h>
+#include <linux/debugfs.h>
-#include <asm/debugfs.h>
#include <asm/page.h>
#include <asm/prom.h>
#include <asm/fadump.h>
@@ -1557,7 +1557,7 @@ static void fadump_init_files(void)
return;
}
- debugfs_create_file("fadump_region", 0444, powerpc_debugfs_root, NULL,
+ debugfs_create_file("fadump_region", 0444, arch_debugfs_dir, NULL,
&fadump_region_fops);
if (fw_dump.dump_active) {
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 6010adcee16e..ba4afe3b5a9c 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -91,8 +91,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
isync
/* enable use of FP after return */
#ifdef CONFIG_PPC32
- mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */
- tovirt(r5, r5)
+ addi r5,r2,THREAD
lwz r4,THREAD_FPEXC_MODE(r5)
ori r9,r9,MSR_FP /* enable FP for current */
or r9,r9,r4
diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
index 8bccce6544b5..dedc17fac8f8 100644
--- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S
+++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* 1. Find the index of the entry we're executing in */
- bl invstr /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
invstr: mflr r6 /* Make it accessible */
mfmsr r7
rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
@@ -85,7 +85,7 @@ skpinv: addi r6,r6,1 /* Increment */
addi r6,r6,10
slw r6,r8,r6 /* convert to mask */
- bl 1f /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
1: mflr r7
mfspr r8,SPRN_MAS3
@@ -117,7 +117,7 @@ skpinv: addi r6,r6,1 /* Increment */
xori r6,r4,1
slwi r6,r6,5 /* setup new context with other address space */
- bl 1f /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
1: mflr r9
rlwimi r7,r9,0,20,31
addi r7,r7,(2f - 1b)
@@ -207,7 +207,7 @@ next_tlb_setup:
lis r7,MSR_KERNEL@h
ori r7,r7,MSR_KERNEL@l
- bl 1f /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
1: mflr r9
rlwimi r6,r9,0,20,31
addi r6,r6,(2f - 1b)
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index ddc978a2d381..02d2928d1e01 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -70,7 +70,7 @@ _ENTRY(_start);
* address.
* r21 will be loaded with the physical runtime address of _stext
*/
- bl 0f /* Get our runtime address */
+ bcl 20,31,$+4 /* Get our runtime address */
0: mflr r21 /* Make it accessible */
addis r21,r21,(_stext - 0b)@ha
addi r21,r21,(_stext - 0b)@l /* Get our current runtime base */
@@ -853,7 +853,7 @@ _GLOBAL(init_cpu_state)
wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */
sync
- bl invstr /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
invstr: mflr r5 /* Make it accessible */
tlbsx r23,0,r5 /* Find entry we are in */
li r4,0 /* Start at TLB entry 0 */
@@ -1045,7 +1045,7 @@ head_start_47x:
sync
/* Find the entry we are running from */
- bl 1f
+ bcl 20,31,$+4
1: mflr r23
tlbsx r23,0,r23
tlbre r24,r23,0
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 79930b0bc781..f17ae2083733 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -712,6 +712,8 @@ _GLOBAL(copy_and_flush)
isync
blr
+_ASM_NOKPROBE_SYMBOL(copy_and_flush); /* Called in real mode */
+
.align 8
copy_to_here:
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 0f9642f36b49..0a9a0f301474 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -79,7 +79,7 @@ _ENTRY(_start);
mr r23,r3
mr r25,r4
- bl 0f
+ bcl 20,31,$+4
0: mflr r8
addis r3,r8,(is_second_reloc - 0b)@ha
lwz r19,(is_second_reloc - 0b)@l(r3)
@@ -858,7 +858,7 @@ KernelSPE:
ori r3,r3,87f@l
mr r4,r2 /* current */
lwz r5,_NIP(r1)
- bl printk
+ bl _printk
#endif
b interrupt_return
#ifdef CONFIG_PRINTK
@@ -1132,7 +1132,7 @@ _GLOBAL(switch_to_as1)
bne 1b
/* Get the tlb entry used by the current running code */
- bl 0f
+ bcl 20,31,$+4
0: mflr r4
tlbsx 0,r4
@@ -1166,7 +1166,7 @@ _GLOBAL(switch_to_as1)
_GLOBAL(restore_to_as0)
mflr r0
- bl 0f
+ bcl 20,31,$+4
0: mflr r9
addi r9,r9,1f - 0b
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 21a638aff72f..91a3be14808b 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -22,7 +22,6 @@
#include <asm/processor.h>
#include <asm/sstep.h>
#include <asm/debug.h>
-#include <asm/debugfs.h>
#include <asm/hvcall.h>
#include <asm/inst.h>
#include <linux/uaccess.h>
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index 21bbd615ca41..a73f3f70a657 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -8,7 +8,6 @@
#include <asm/asm-prototypes.h>
#include <asm/kup.h>
#include <asm/cputime.h>
-#include <asm/interrupt.h>
#include <asm/hw_irq.h>
#include <asm/interrupt.h>
#include <asm/kprobes.h>
@@ -93,8 +92,7 @@ notrace long system_call_exception(long r3, long r4, long r5,
CT_WARN_ON(ct_state() == CONTEXT_KERNEL);
user_exit_irqoff();
- if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x))
- BUG_ON(!(regs->msr & MSR_RI));
+ BUG_ON(regs_is_unrecoverable(regs));
BUG_ON(!(regs->msr & MSR_PR));
BUG_ON(arch_irq_disabled_regs(regs));
@@ -463,9 +461,7 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
{
unsigned long ret;
- if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x))
- BUG_ON(!(regs->msr & MSR_RI));
- BUG_ON(!(regs->msr & MSR_PR));
+ BUG_ON(regs_is_unrecoverable(regs));
BUG_ON(arch_irq_disabled_regs(regs));
CT_WARN_ON(ct_state() == CONTEXT_USER);
@@ -496,10 +492,8 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
bool stack_store = current_thread_info()->flags &
_TIF_EMULATE_STACK_STORE;
- if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x) &&
- unlikely(!(regs->msr & MSR_RI)))
+ if (regs_is_unrecoverable(regs))
unrecoverable_exception(regs);
- BUG_ON(regs->msr & MSR_PR);
/*
* CT_WARN_ON comes here via program_check_exception,
* so avoid recursion.
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 2af89a5e379f..07093b7cdcb9 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -473,7 +473,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
BUG_ON(direction == DMA_NONE);
if ((nelems == 0) || !tbl)
- return 0;
+ return -EINVAL;
outs = s = segstart = &sglist[0];
outcount = 1;
@@ -575,7 +575,6 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
*/
if (outcount < incount) {
outs = sg_next(outs);
- outs->dma_address = DMA_MAPPING_ERROR;
outs->dma_length = 0;
}
@@ -593,13 +592,12 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
npages = iommu_num_pages(s->dma_address, s->dma_length,
IOMMU_PAGE_SIZE(tbl));
__iommu_free(tbl, vaddr, npages);
- s->dma_address = DMA_MAPPING_ERROR;
s->dma_length = 0;
}
if (s == outs)
break;
}
- return 0;
+ return -EIO;
}
@@ -690,32 +688,24 @@ static void iommu_table_reserve_pages(struct iommu_table *tbl,
if (tbl->it_offset == 0)
set_bit(0, tbl->it_map);
- tbl->it_reserved_start = res_start;
- tbl->it_reserved_end = res_end;
-
- /* Check if res_start..res_end isn't empty and overlaps the table */
- if (res_start && res_end &&
- (tbl->it_offset + tbl->it_size < res_start ||
- res_end < tbl->it_offset))
- return;
+ if (res_start < tbl->it_offset)
+ res_start = tbl->it_offset;
- for (i = tbl->it_reserved_start; i < tbl->it_reserved_end; ++i)
- set_bit(i - tbl->it_offset, tbl->it_map);
-}
+ if (res_end > (tbl->it_offset + tbl->it_size))
+ res_end = tbl->it_offset + tbl->it_size;
-static void iommu_table_release_pages(struct iommu_table *tbl)
-{
- int i;
+ /* Check if res_start..res_end is a valid range in the table */
+ if (res_start >= res_end) {
+ tbl->it_reserved_start = tbl->it_offset;
+ tbl->it_reserved_end = tbl->it_offset;
+ return;
+ }
- /*
- * In case we have reserved the first bit, we should not emit
- * the warning below.
- */
- if (tbl->it_offset == 0)
- clear_bit(0, tbl->it_map);
+ tbl->it_reserved_start = res_start;
+ tbl->it_reserved_end = res_end;
for (i = tbl->it_reserved_start; i < tbl->it_reserved_end; ++i)
- clear_bit(i - tbl->it_offset, tbl->it_map);
+ set_bit(i - tbl->it_offset, tbl->it_map);
}
/*
@@ -779,6 +769,22 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid,
return tbl;
}
+bool iommu_table_in_use(struct iommu_table *tbl)
+{
+ unsigned long start = 0, end;
+
+ /* ignore reserved bit0 */
+ if (tbl->it_offset == 0)
+ start = 1;
+ end = tbl->it_reserved_start - tbl->it_offset;
+ if (find_next_bit(tbl->it_map, end, start) != end)
+ return true;
+
+ start = tbl->it_reserved_end - tbl->it_offset;
+ end = tbl->it_size;
+ return find_next_bit(tbl->it_map, end, start) != end;
+}
+
static void iommu_table_free(struct kref *kref)
{
struct iommu_table *tbl;
@@ -795,10 +801,8 @@ static void iommu_table_free(struct kref *kref)
iommu_debugfs_del(tbl);
- iommu_table_release_pages(tbl);
-
/* verify that table contains no entries */
- if (!bitmap_empty(tbl->it_map, tbl->it_size))
+ if (iommu_table_in_use(tbl))
pr_warn("%s: Unexpected TCEs\n", __func__);
/* free bitmap */
@@ -1099,14 +1103,9 @@ int iommu_take_ownership(struct iommu_table *tbl)
for (i = 0; i < tbl->nr_pools; i++)
spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock);
- iommu_table_release_pages(tbl);
-
- if (!bitmap_empty(tbl->it_map, tbl->it_size)) {
+ if (iommu_table_in_use(tbl)) {
pr_err("iommu_tce: it_map is not empty");
ret = -EBUSY;
- /* Undo iommu_table_release_pages, i.e. restore bit#0, etc */
- iommu_table_reserve_pages(tbl, tbl->it_reserved_start,
- tbl->it_reserved_end);
} else {
memset(tbl->it_map, 0xff, sz);
}
diff --git a/arch/powerpc/kernel/kdebugfs.c b/arch/powerpc/kernel/kdebugfs.c
new file mode 100644
index 000000000000..36d3124d5a8b
--- /dev/null
+++ b/arch/powerpc/kernel/kdebugfs.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/debugfs.h>
+#include <linux/export.h>
+#include <linux/init.h>
+
+struct dentry *arch_debugfs_dir;
+EXPORT_SYMBOL(arch_debugfs_dir);
+
+static int __init arch_kdebugfs_init(void)
+{
+ arch_debugfs_dir = debugfs_create_dir("powerpc", NULL);
+ return 0;
+}
+arch_initcall(arch_kdebugfs_init);
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
index 5be96feccb55..fb7de3543c03 100644
--- a/arch/powerpc/kernel/misc.S
+++ b/arch/powerpc/kernel/misc.S
@@ -29,7 +29,7 @@ _GLOBAL(reloc_offset)
li r3, 0
_GLOBAL(add_reloc_offset)
mflr r0
- bl 1f
+ bcl 20,31,$+4
1: mflr r5
PPC_LL r4,(2f-1b)(r5)
subf r5,r4,r5
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 39ab15419592..e5127b19fec2 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -67,7 +67,7 @@ _GLOBAL(reloc_got2)
srwi. r8,r8,2
beqlr
mtctr r8
- bl 1f
+ bcl 20,31,$+4
1: mflr r0
lis r4,1b@ha
addi r4,r4,1b@l
@@ -237,7 +237,7 @@ _GLOBAL(copy_page)
addi r3,r3,-4
0: twnei r5, 0 /* WARN if r3 is not cache aligned */
- EMIT_BUG_ENTRY 0b,__FILE__,__LINE__, BUGFLAG_WARNING
+ EMIT_WARN_ENTRY 0b,__FILE__,__LINE__, BUGFLAG_WARNING
addi r4,r4,-4
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 4b761a18a74d..d38a019b38e1 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -255,7 +255,7 @@ _GLOBAL(scom970_write)
* Physical (hardware) cpu id should be in r3.
*/
_GLOBAL(kexec_wait)
- bl 1f
+ bcl 20,31,$+4
1: mflr r5
addi r5,r5,kexec_flag-1b
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 001e90cd8948..c3573430919d 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/vgaarb.h>
#include <linux/numa.h>
+#include <linux/msi.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -1060,11 +1061,16 @@ void pcibios_bus_add_device(struct pci_dev *dev)
int pcibios_add_device(struct pci_dev *dev)
{
+ struct irq_domain *d;
+
#ifdef CONFIG_PCI_IOV
if (ppc_md.pcibios_fixup_sriov)
ppc_md.pcibios_fixup_sriov(dev);
#endif /* CONFIG_PCI_IOV */
+ d = dev_get_msi_domain(&dev->bus->dev);
+ if (d)
+ dev_set_msi_domain(&dev->dev, d);
return 0;
}
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 185beb290580..50436b52c213 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1499,7 +1499,7 @@ static void __show_regs(struct pt_regs *regs)
trap == INTERRUPT_DATA_STORAGE ||
trap == INTERRUPT_ALIGNMENT) {
if (IS_ENABLED(CONFIG_4xx) || IS_ENABLED(CONFIG_BOOKE))
- pr_cont("DEAR: "REG" ESR: "REG" ", regs->dar, regs->dsisr);
+ pr_cont("DEAR: "REG" ESR: "REG" ", regs->dear, regs->esr);
else
pr_cont("DAR: "REG" DSISR: %08lx ", regs->dar, regs->dsisr);
}
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f620e04dc9bf..2e67588f6f6e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -11,7 +11,6 @@
#undef DEBUG
-#include <stdarg.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
@@ -640,7 +639,9 @@ static void __init early_reserve_mem(void)
}
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC32
+ if (!IS_ENABLED(CONFIG_PPC32))
+ return;
+
/*
* Handle the case where we might be booting from an old kexec
* image that setup the mem_rsvmap as pairs of 32-bit values
@@ -661,7 +662,6 @@ static void __init early_reserve_mem(void)
}
return;
}
-#endif
}
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index a5bf355ce1d6..18b04b08b983 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -14,7 +14,7 @@
/* we cannot use FORTIFY as it brings in new symbols */
#define __NO_FORTIFY
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
@@ -1096,7 +1096,8 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
#else
0,
#endif
- .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
+ .associativity = OV5_FEAT(OV5_FORM1_AFFINITY) | OV5_FEAT(OV5_PRRN) |
+ OV5_FEAT(OV5_FORM2_AFFINITY),
.bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
.micro_checkpoint = 0,
.reserved0 = 0,
diff --git a/arch/powerpc/kernel/ptrace/ptrace.c b/arch/powerpc/kernel/ptrace/ptrace.c
index 0a0a33eb0d28..7c7093c17c45 100644
--- a/arch/powerpc/kernel/ptrace/ptrace.c
+++ b/arch/powerpc/kernel/ptrace/ptrace.c
@@ -373,8 +373,12 @@ void __init pt_regs_check(void)
offsetof(struct user_pt_regs, trap));
BUILD_BUG_ON(offsetof(struct pt_regs, dar) !=
offsetof(struct user_pt_regs, dar));
+ BUILD_BUG_ON(offsetof(struct pt_regs, dear) !=
+ offsetof(struct user_pt_regs, dar));
BUILD_BUG_ON(offsetof(struct pt_regs, dsisr) !=
offsetof(struct user_pt_regs, dsisr));
+ BUILD_BUG_ON(offsetof(struct pt_regs, esr) !=
+ offsetof(struct user_pt_regs, dsisr));
BUILD_BUG_ON(offsetof(struct pt_regs, result) !=
offsetof(struct user_pt_regs, result));
diff --git a/arch/powerpc/kernel/reloc_32.S b/arch/powerpc/kernel/reloc_32.S
index 10e96f3e22fe..0508c14b4c28 100644
--- a/arch/powerpc/kernel/reloc_32.S
+++ b/arch/powerpc/kernel/reloc_32.S
@@ -30,7 +30,7 @@ R_PPC_RELATIVE = 22
_GLOBAL(relocate)
mflr r0 /* Save our LR */
- bl 0f /* Find our current runtime address */
+ bcl 20,31,$+4 /* Find our current runtime address */
0: mflr r12 /* Make it accessible */
mtlr r0
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 99f2cce635fb..ff80bbad22a5 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -7,7 +7,7 @@
* Copyright (C) 2001 IBM.
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/spinlock.h>
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 8561dfb33f24..32ee17753eb4 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -429,7 +429,7 @@ static void rtas_event_scan(struct work_struct *w)
do_event_scan();
- get_online_cpus();
+ cpus_read_lock();
/* raw_ OK because just using CPU as starting point. */
cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
@@ -451,7 +451,7 @@ static void rtas_event_scan(struct work_struct *w)
schedule_delayed_work_on(cpu, &event_scan_work,
__round_jiffies_relative(event_scan_delay, cpu));
- put_online_cpus();
+ cpus_read_unlock();
}
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
index cc51fa52e783..1a998490fe60 100644
--- a/arch/powerpc/kernel/security.c
+++ b/arch/powerpc/kernel/security.c
@@ -11,10 +11,10 @@
#include <linux/nospec.h>
#include <linux/prctl.h>
#include <linux/seq_buf.h>
+#include <linux/debugfs.h>
#include <asm/asm-prototypes.h>
#include <asm/code-patching.h>
-#include <asm/debugfs.h>
#include <asm/security_features.h>
#include <asm/setup.h>
#include <asm/inst.h>
@@ -106,7 +106,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_barrier_nospec, barrier_nospec_get,
static __init int barrier_nospec_debugfs_init(void)
{
debugfs_create_file_unsafe("barrier_nospec", 0600,
- powerpc_debugfs_root, NULL,
+ arch_debugfs_dir, NULL,
&fops_barrier_nospec);
return 0;
}
@@ -114,7 +114,7 @@ device_initcall(barrier_nospec_debugfs_init);
static __init int security_feature_debugfs_init(void)
{
- debugfs_create_x64("security_features", 0400, powerpc_debugfs_root,
+ debugfs_create_x64("security_features", 0400, arch_debugfs_dir,
&powerpc_security_features);
return 0;
}
@@ -420,7 +420,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set,
static __init int stf_barrier_debugfs_init(void)
{
- debugfs_create_file_unsafe("stf_barrier", 0600, powerpc_debugfs_root,
+ debugfs_create_file_unsafe("stf_barrier", 0600, arch_debugfs_dir,
NULL, &fops_stf_barrier);
return 0;
}
@@ -748,7 +748,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_count_cache_flush, count_cache_flush_get,
static __init int count_cache_flush_debugfs_init(void)
{
debugfs_create_file_unsafe("count_cache_flush", 0600,
- powerpc_debugfs_root, NULL,
+ arch_debugfs_dir, NULL,
&fops_count_cache_flush);
return 0;
}
@@ -834,9 +834,9 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_uaccess_flush, uaccess_flush_get, uaccess_flush_set
static __init int rfi_flush_debugfs_init(void)
{
- debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
- debugfs_create_file("entry_flush", 0600, powerpc_debugfs_root, NULL, &fops_entry_flush);
- debugfs_create_file("uaccess_flush", 0600, powerpc_debugfs_root, NULL, &fops_uaccess_flush);
+ debugfs_create_file("rfi_flush", 0600, arch_debugfs_dir, NULL, &fops_rfi_flush);
+ debugfs_create_file("entry_flush", 0600, arch_debugfs_dir, NULL, &fops_entry_flush);
+ debugfs_create_file("uaccess_flush", 0600, arch_debugfs_dir, NULL, &fops_uaccess_flush);
return 0;
}
device_initcall(rfi_flush_debugfs_init);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index aa9c2d01424a..b1e43b69a559 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -33,7 +33,6 @@
#include <linux/of_platform.h>
#include <linux/hugetlb.h>
#include <linux/pgtable.h>
-#include <asm/debugfs.h>
#include <asm/io.h>
#include <asm/paca.h>
#include <asm/prom.h>
@@ -773,18 +772,6 @@ static int __init check_cache_coherency(void)
late_initcall(check_cache_coherency);
#endif /* CONFIG_CHECK_CACHE_COHERENCY */
-#ifdef CONFIG_DEBUG_FS
-struct dentry *powerpc_debugfs_root;
-EXPORT_SYMBOL(powerpc_debugfs_root);
-
-static int powerpc_debugfs_init(void)
-{
- powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL);
- return 0;
-}
-arch_initcall(powerpc_debugfs_init);
-#endif
-
void ppc_printk_progress(char *s, unsigned short hex)
{
pr_info("%s\n", s);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 1ff258f6c76c..eaa79a0996d1 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -32,7 +32,6 @@
#include <linux/nmi.h>
#include <linux/pgtable.h>
-#include <asm/debugfs.h>
#include <asm/kvm_guest.h>
#include <asm/io.h>
#include <asm/kdump.h>
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 447b78a87c8f..9cc7d3dbf439 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -78,6 +78,7 @@ struct task_struct *secondary_current;
bool has_big_cores;
bool coregroup_enabled;
bool thread_group_shares_l2;
+bool thread_group_shares_l3;
DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map);
DEFINE_PER_CPU(cpumask_var_t, cpu_smallcore_map);
@@ -101,7 +102,7 @@ enum {
#define MAX_THREAD_LIST_SIZE 8
#define THREAD_GROUP_SHARE_L1 1
-#define THREAD_GROUP_SHARE_L2 2
+#define THREAD_GROUP_SHARE_L2_L3 2
struct thread_groups {
unsigned int property;
unsigned int nr_groups;
@@ -122,14 +123,20 @@ static struct thread_groups_list tgl[NR_CPUS] __initdata;
* On big-cores system, thread_group_l1_cache_map for each CPU corresponds to
* the set its siblings that share the L1-cache.
*/
-static DEFINE_PER_CPU(cpumask_var_t, thread_group_l1_cache_map);
+DEFINE_PER_CPU(cpumask_var_t, thread_group_l1_cache_map);
/*
* On some big-cores system, thread_group_l2_cache_map for each CPU
* corresponds to the set its siblings within the core that share the
* L2-cache.
*/
-static DEFINE_PER_CPU(cpumask_var_t, thread_group_l2_cache_map);
+DEFINE_PER_CPU(cpumask_var_t, thread_group_l2_cache_map);
+
+/*
+ * On P10, thread_group_l3_cache_map for each CPU is equal to the
+ * thread_group_l2_cache_map
+ */
+DEFINE_PER_CPU(cpumask_var_t, thread_group_l3_cache_map);
/* SMP operations for this machine */
struct smp_ops_t *smp_ops;
@@ -889,19 +896,41 @@ out:
return tg;
}
+static int update_mask_from_threadgroup(cpumask_var_t *mask, struct thread_groups *tg, int cpu, int cpu_group_start)
+{
+ int first_thread = cpu_first_thread_sibling(cpu);
+ int i;
+
+ zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cpu));
+
+ for (i = first_thread; i < first_thread + threads_per_core; i++) {
+ int i_group_start = get_cpu_thread_group_start(i, tg);
+
+ if (unlikely(i_group_start == -1)) {
+ WARN_ON_ONCE(1);
+ return -ENODATA;
+ }
+
+ if (i_group_start == cpu_group_start)
+ cpumask_set_cpu(i, *mask);
+ }
+
+ return 0;
+}
+
static int __init init_thread_group_cache_map(int cpu, int cache_property)
{
- int first_thread = cpu_first_thread_sibling(cpu);
- int i, cpu_group_start = -1, err = 0;
+ int cpu_group_start = -1, err = 0;
struct thread_groups *tg = NULL;
cpumask_var_t *mask = NULL;
if (cache_property != THREAD_GROUP_SHARE_L1 &&
- cache_property != THREAD_GROUP_SHARE_L2)
+ cache_property != THREAD_GROUP_SHARE_L2_L3)
return -EINVAL;
tg = get_thread_groups(cpu, cache_property, &err);
+
if (!tg)
return err;
@@ -912,25 +941,18 @@ static int __init init_thread_group_cache_map(int cpu, int cache_property)
return -ENODATA;
}
- if (cache_property == THREAD_GROUP_SHARE_L1)
+ if (cache_property == THREAD_GROUP_SHARE_L1) {
mask = &per_cpu(thread_group_l1_cache_map, cpu);
- else if (cache_property == THREAD_GROUP_SHARE_L2)
+ update_mask_from_threadgroup(mask, tg, cpu, cpu_group_start);
+ }
+ else if (cache_property == THREAD_GROUP_SHARE_L2_L3) {
mask = &per_cpu(thread_group_l2_cache_map, cpu);
-
- zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cpu));
-
- for (i = first_thread; i < first_thread + threads_per_core; i++) {
- int i_group_start = get_cpu_thread_group_start(i, tg);
-
- if (unlikely(i_group_start == -1)) {
- WARN_ON_ONCE(1);
- return -ENODATA;
- }
-
- if (i_group_start == cpu_group_start)
- cpumask_set_cpu(i, *mask);
+ update_mask_from_threadgroup(mask, tg, cpu, cpu_group_start);
+ mask = &per_cpu(thread_group_l3_cache_map, cpu);
+ update_mask_from_threadgroup(mask, tg, cpu, cpu_group_start);
}
+
return 0;
}
@@ -1020,14 +1042,16 @@ static int __init init_big_cores(void)
has_big_cores = true;
for_each_possible_cpu(cpu) {
- int err = init_thread_group_cache_map(cpu, THREAD_GROUP_SHARE_L2);
+ int err = init_thread_group_cache_map(cpu, THREAD_GROUP_SHARE_L2_L3);
if (err)
return err;
}
thread_group_shares_l2 = true;
- pr_debug("L2 cache only shared by the threads in the small core\n");
+ thread_group_shares_l3 = true;
+ pr_debug("L2/L3 cache only shared by the threads in the small core\n");
+
return 0;
}
@@ -1085,7 +1109,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
if (cpu_to_chip_id(boot_cpuid) != -1) {
- int idx = num_possible_cpus() / threads_per_core;
+ int idx = DIV_ROUND_UP(num_possible_cpus(), threads_per_core);
/*
* All threads of a core will all belong to the same core,
@@ -1376,7 +1400,7 @@ static bool update_mask_by_l2(int cpu, cpumask_var_t *mask)
l2_cache = cpu_to_l2cache(cpu);
if (!l2_cache || !*mask) {
/* Assume only core siblings share cache with this CPU */
- for_each_cpu(i, submask_fn(cpu))
+ for_each_cpu(i, cpu_sibling_mask(cpu))
set_cpus_related(cpu, i, cpu_l2_cache_mask);
return false;
@@ -1418,6 +1442,8 @@ static void remove_cpu_from_masks(int cpu)
struct cpumask *(*mask_fn)(int) = cpu_sibling_mask;
int i;
+ unmap_cpu_from_node(cpu);
+
if (shared_caches)
mask_fn = cpu_l2_cache_mask;
@@ -1502,7 +1528,9 @@ static void add_cpu_to_masks(int cpu)
* This CPU will not be in the online mask yet so we need to manually
* add it to it's own thread sibling mask.
*/
+ map_cpu_to_node(cpu, cpu_to_node(cpu));
cpumask_set_cpu(cpu, cpu_sibling_mask(cpu));
+ cpumask_set_cpu(cpu, cpu_core_mask(cpu));
for (i = first_thread; i < first_thread + threads_per_core; i++)
if (cpu_online(i))
@@ -1520,11 +1548,6 @@ static void add_cpu_to_masks(int cpu)
if (chip_id_lookup_table && ret)
chip_id = cpu_to_chip_id(cpu);
- if (chip_id == -1) {
- cpumask_copy(per_cpu(cpu_core_map, cpu), cpu_cpu_mask(cpu));
- goto out;
- }
-
if (shared_caches)
submask_fn = cpu_l2_cache_mask;
@@ -1534,6 +1557,10 @@ static void add_cpu_to_masks(int cpu)
/* Skip all CPUs already part of current CPU core mask */
cpumask_andnot(mask, cpu_online_mask, cpu_core_mask(cpu));
+ /* If chip_id is -1; limit the cpu_core_mask to within DIE*/
+ if (chip_id == -1)
+ cpumask_and(mask, mask, cpu_cpu_mask(cpu));
+
for_each_cpu(i, mask) {
if (chip_id == cpu_to_chip_id(i)) {
or_cpumasks_related(cpu, i, submask_fn, cpu_core_mask);
@@ -1543,7 +1570,6 @@ static void add_cpu_to_masks(int cpu)
}
}
-out:
free_cpumask_var(mask);
}
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index 2b0d04a1b7d2..9e4a4a7af380 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -8,6 +8,7 @@
* Copyright 2018 Nick Piggin, Michael Ellerman, IBM Corp.
*/
+#include <linux/delay.h>
#include <linux/export.h>
#include <linux/kallsyms.h>
#include <linux/module.h>
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index bf4ae0f0e36c..825931e400df 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -41,20 +41,13 @@ static inline long do_mmap2(unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long off, int shift)
{
- long ret = -EINVAL;
-
if (!arch_validate_prot(prot, addr))
- goto out;
+ return -EINVAL;
- if (shift) {
- if (off & ((1 << shift) - 1))
- goto out;
- off >>= shift;
- }
+ if (!IS_ALIGNED(off, 1 << shift))
+ return -EINVAL;
- ret = ksys_mmap_pgoff(addr, len, prot, flags, fd, off);
-out:
- return ret;
+ return ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> shift);
}
SYSCALL_DEFINE6(mmap2, unsigned long, addr, size_t, len,
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index aef2a290e71a..29b55e2e035c 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -176,7 +176,7 @@
131 nospu quotactl sys_quotactl
132 common getpgid sys_getpgid
133 common fchdir sys_fchdir
-134 common bdflush sys_bdflush
+134 common bdflush sys_ni_syscall
135 common sysfs sys_sysfs
136 32 personality sys_personality ppc64_personality
136 64 personality ppc64_personality
@@ -526,3 +526,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c
index b9a047d92ec0..8e83d19fe8fa 100644
--- a/arch/powerpc/kernel/tau_6xx.c
+++ b/arch/powerpc/kernel/tau_6xx.c
@@ -164,7 +164,7 @@ static void tau_work_func(struct work_struct *work)
queue_work(tau_workq, work);
}
-DECLARE_WORK(tau_work, tau_work_func);
+static DECLARE_WORK(tau_work, tau_work_func);
/*
* setup the TAU
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index c487ba5a6e11..934d8ae66cc6 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -31,6 +31,7 @@
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/sched/clock.h>
+#include <linux/sched/cputime.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
@@ -52,8 +53,6 @@
#include <linux/irq_work.h>
#include <linux/of_clk.h>
#include <linux/suspend.h>
-#include <linux/sched/cputime.h>
-#include <linux/sched/clock.h>
#include <linux/processor.h>
#include <asm/trace.h>
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index d56254f05e17..4390f8d72126 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -37,10 +37,10 @@
#include <linux/smp.h>
#include <linux/console.h>
#include <linux/kmsg_dump.h>
+#include <linux/debugfs.h>
#include <asm/emulated_ops.h>
#include <linux/uaccess.h>
-#include <asm/debugfs.h>
#include <asm/interrupt.h>
#include <asm/io.h>
#include <asm/machdep.h>
@@ -171,7 +171,6 @@ extern void panic_flush_kmsg_start(void)
extern void panic_flush_kmsg_end(void)
{
- printk_safe_flush_on_panic();
kmsg_dump(KMSG_DUMP_PANIC);
bust_spinlocks(0);
debug_locks_off();
@@ -428,7 +427,7 @@ void hv_nmi_check_nonrecoverable(struct pt_regs *regs)
return;
nonrecoverable:
- regs_set_return_msr(regs, regs->msr & ~MSR_RI);
+ regs_set_unrecoverable(regs);
#endif
}
DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception)
@@ -498,7 +497,7 @@ out:
die("Unrecoverable nested System Reset", regs, SIGABRT);
#endif
/* Must die if the interrupt is not recoverable */
- if (!(regs->msr & MSR_RI)) {
+ if (regs_is_unrecoverable(regs)) {
/* For the reason explained in die_mce, nmi_exit before die */
nmi_exit();
die("Unrecoverable System Reset", regs, SIGABRT);
@@ -550,7 +549,7 @@ static inline int check_io_access(struct pt_regs *regs)
printk(KERN_DEBUG "%s bad port %lx at %p\n",
(*nip & 0x100)? "OUT to": "IN from",
regs->gpr[rb] - _IO_BASE, nip);
- regs_set_return_msr(regs, regs->msr | MSR_RI);
+ regs_set_recoverable(regs);
regs_set_return_ip(regs, extable_fixup(entry));
return 1;
}
@@ -562,7 +561,7 @@ static inline int check_io_access(struct pt_regs *regs)
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
/* On 4xx, the reason for the machine check or program exception
is in the ESR. */
-#define get_reason(regs) ((regs)->dsisr)
+#define get_reason(regs) ((regs)->esr)
#define REASON_FP ESR_FP
#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
#define REASON_PRIVILEGED ESR_PPR
@@ -840,7 +839,7 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception)
bail:
/* Must die if the interrupt is not recoverable */
- if (!(regs->msr & MSR_RI))
+ if (regs_is_unrecoverable(regs))
die_mce("Unrecoverable Machine check", regs, SIGBUS);
#ifdef CONFIG_PPC_BOOK3S_64
@@ -1482,8 +1481,13 @@ static void do_program_check(struct pt_regs *regs)
if (!(regs->msr & MSR_PR) && /* not user-mode */
report_bug(bugaddr, regs) == BUG_TRAP_TYPE_WARN) {
- regs_add_return_ip(regs, 4);
- return;
+ const struct exception_table_entry *entry;
+
+ entry = search_exception_tables(bugaddr);
+ if (entry) {
+ regs_set_return_ip(regs, extable_fixup(entry) + regs->nip - bugaddr);
+ return;
+ }
}
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
return;
@@ -2272,7 +2276,7 @@ static int __init ppc_warn_emulated_init(void)
struct ppc_emulated_entry *entries = (void *)&ppc_emulated;
dir = debugfs_create_dir("emulated_instructions",
- powerpc_debugfs_root);
+ arch_debugfs_dir);
debugfs_create_u32("do_warn", 0644, dir, &ppc_warn_emulated);
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 01595e8cafe7..b1544b2f6321 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -5,7 +5,7 @@
* c 2001 PPC 64 Team, IBM Corp
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/console.h>
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index fc120fac1910..ba03eedfdcd8 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -65,9 +65,8 @@ _GLOBAL(load_up_altivec)
1:
/* enable use of VMX after return */
#ifdef CONFIG_PPC32
- mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */
+ addi r5,r2,THREAD
oris r9,r9,MSR_VEC@h
- tovirt(r5, r5)
#else
ld r4,PACACURRENT(r13)
addi r5,r4,THREAD /* Get THREAD */
@@ -81,7 +80,6 @@ _GLOBAL(load_up_altivec)
li r4,1
stb r4,THREAD_LOAD_VEC(r5)
addi r6,r5,THREAD_VRSTATE
- li r4,1
li r10,VRSTATE_VSCR
stw r4,THREAD_USED_VR(r5)
lvx v0,r10,r6
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c
index a165635fd214..f9ea0e5357f9 100644
--- a/arch/powerpc/kernel/watchdog.c
+++ b/arch/powerpc/kernel/watchdog.c
@@ -184,11 +184,6 @@ static void watchdog_smp_panic(int cpu, u64 tb)
wd_smp_unlock(&flags);
- printk_safe_flush();
- /*
- * printk_safe_flush() seems to require another print
- * before anything actually goes out to console.
- */
if (sysctl_hardlockup_all_cpu_backtrace)
trigger_allbutself_cpu_backtrace();
diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c
index 8a449b2d8715..89c069d664a5 100644
--- a/arch/powerpc/kexec/core_64.c
+++ b/arch/powerpc/kexec/core_64.c
@@ -64,15 +64,18 @@ int default_machine_kexec_prepare(struct kimage *image)
begin = image->segment[i].mem;
end = begin + image->segment[i].memsz;
- if ((begin < high) && (end > low))
+ if ((begin < high) && (end > low)) {
+ of_node_put(node);
return -ETXTBSY;
+ }
}
}
return 0;
}
-static void copy_segments(unsigned long ind)
+/* Called during kexec sequence with MMU off */
+static notrace void copy_segments(unsigned long ind)
{
unsigned long entry;
unsigned long *ptr;
@@ -105,7 +108,8 @@ static void copy_segments(unsigned long ind)
}
}
-void kexec_copy_flush(struct kimage *image)
+/* Called during kexec sequence with MMU off */
+notrace void kexec_copy_flush(struct kimage *image)
{
long i, nr_segments = image->nr_segments;
struct kexec_segment ranges[KEXEC_SEGMENT_MAX];
diff --git a/arch/powerpc/kexec/crash.c b/arch/powerpc/kexec/crash.c
index 10f997e6bb95..22ceeeb705ab 100644
--- a/arch/powerpc/kexec/crash.c
+++ b/arch/powerpc/kexec/crash.c
@@ -313,7 +313,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
int (*old_handler)(struct pt_regs *regs);
/* Avoid hardlocking with irresponsive CPU holding logbuf_lock */
- printk_nmi_enter();
+ printk_deferred_enter();
/*
* This function is only called after the system
diff --git a/arch/powerpc/kexec/relocate_32.S b/arch/powerpc/kexec/relocate_32.S
index 61946c19e07c..cf6e52bdf8d8 100644
--- a/arch/powerpc/kexec/relocate_32.S
+++ b/arch/powerpc/kexec/relocate_32.S
@@ -93,7 +93,7 @@ wmmucr:
* Invalidate all the TLB entries except the current entry
* where we are running from
*/
- bl 0f /* Find our address */
+ bcl 20,31,$+4 /* Find our address */
0: mflr r5 /* Make it accessible */
tlbsx r23,0,r5 /* Find entry we are in */
li r4,0 /* Start at TLB entry 0 */
@@ -158,7 +158,7 @@ write_out:
/* Switch to other address space in MSR */
insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */
- bl 1f
+ bcl 20,31,$+4
1: mflr r8
addi r8, r8, (2f-1b) /* Find the target offset */
@@ -202,7 +202,7 @@ next_tlb:
li r9,0
insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */
- bl 1f
+ bcl 20,31,$+4
1: mflr r8
and r8, r8, r11 /* Get our offset within page */
addi r8, r8, (2f-1b)
@@ -240,7 +240,7 @@ setup_map_47x:
sync
/* Find the entry we are running from */
- bl 2f
+ bcl 20,31,$+4
2: mflr r23
tlbsx r23, 0, r23
tlbre r24, r23, 0 /* TLB Word 0 */
@@ -296,7 +296,7 @@ clear_utlb_entry:
/* Update the msr to the new TS */
insrwi r5, r7, 1, 26
- bl 1f
+ bcl 20,31,$+4
1: mflr r6
addi r6, r6, (2f-1b)
@@ -355,7 +355,7 @@ write_utlb:
/* Defaults to 256M */
lis r10, 0x1000
- bl 1f
+ bcl 20,31,$+4
1: mflr r4
addi r4, r4, (2f-1b) /* virtual address of 2f */
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index e45644657d49..ff581d70f20c 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -38,7 +38,6 @@ config KVM_BOOK3S_32_HANDLER
config KVM_BOOK3S_64_HANDLER
bool
select KVM_BOOK3S_HANDLER
- select PPC_DAWR_FORCE_ENABLE
config KVM_BOOK3S_PR_POSSIBLE
bool
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 79833f78d1da..b785f6772391 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -43,8 +43,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_ICOUNTER(VM, num_2M_pages),
STATS_DESC_ICOUNTER(VM, num_1G_pages)
};
-static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
- sizeof(struct kvm_vm_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vm_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -71,7 +69,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
STATS_DESC_COUNTER(VCPU, dec_exits),
STATS_DESC_COUNTER(VCPU, ext_intr_exits),
- STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
STATS_DESC_COUNTER(VCPU, halt_successful_wait),
STATS_DESC_COUNTER(VCPU, dbell_exits),
STATS_DESC_COUNTER(VCPU, gdbell_exits),
@@ -88,8 +85,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, pthru_host),
STATS_DESC_COUNTER(VCPU, pthru_bad_aff)
};
-static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
- sizeof(struct kvm_vcpu_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vcpu_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
diff --git a/arch/powerpc/kvm/book3s.h b/arch/powerpc/kvm/book3s.h
index 740e51def5a5..58391b4b32ed 100644
--- a/arch/powerpc/kvm/book3s.h
+++ b/arch/powerpc/kvm/book3s.h
@@ -23,7 +23,8 @@ extern int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu,
extern int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu,
int sprn, ulong *spr_val);
extern int kvmppc_book3s_init_pr(void);
-extern void kvmppc_book3s_exit_pr(void);
+void kvmppc_book3s_exit_pr(void);
+extern int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr);
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
extern void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val);
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 26b8b27a3755..feee40cb2ba1 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -196,7 +196,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
hva_t ptegp;
u64 pteg[16];
u64 avpn = 0;
- u64 v, r;
+ u64 r;
u64 v_val, v_mask;
u64 eaddr_mask;
int i;
@@ -285,7 +285,6 @@ do_second:
goto do_second;
}
- v = be64_to_cpu(pteg[i]);
r = be64_to_cpu(pteg[i+1]);
pp = (r & HPTE_R_PP) | key;
if (r & HPTE_R_PP0)
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index b5905ae4377c..16359525a40f 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -44,6 +44,9 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid,
(to != NULL) ? __pa(to): 0,
(from != NULL) ? __pa(from): 0, n);
+ if (eaddr & (0xFFFUL << 52))
+ return ret;
+
quadrant = 1;
if (!pid)
quadrant = 2;
@@ -65,10 +68,12 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid,
}
isync();
+ pagefault_disable();
if (is_load)
- ret = copy_from_user_nofault(to, (const void __user *)from, n);
+ ret = __copy_from_user_inatomic(to, (const void __user *)from, n);
else
- ret = copy_to_user_nofault((void __user *)to, from, n);
+ ret = __copy_to_user_inatomic((void __user *)to, from, n);
+ pagefault_enable();
/* switch the pid first to avoid running host with unallocated pid */
if (quadrant == 1 && pid != old_pid)
@@ -81,7 +86,6 @@ unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid,
return ret;
}
-EXPORT_SYMBOL_GPL(__kvmhv_copy_tofrom_guest_radix);
static long kvmhv_copy_tofrom_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr,
void *to, void *from, unsigned long n)
@@ -117,14 +121,12 @@ long kvmhv_copy_from_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr, void *to,
return ret;
}
-EXPORT_SYMBOL_GPL(kvmhv_copy_from_guest_radix);
long kvmhv_copy_to_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr, void *from,
unsigned long n)
{
return kvmhv_copy_tofrom_guest_radix(vcpu, eaddr, NULL, from, n);
}
-EXPORT_SYMBOL_GPL(kvmhv_copy_to_guest_radix);
int kvmppc_mmu_walk_radix_tree(struct kvm_vcpu *vcpu, gva_t eaddr,
struct kvmppc_pte *gpte, u64 root,
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index 8da93fdfa59e..6365087f3160 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -346,7 +346,7 @@ static long kvmppc_tce_to_ua(struct kvm *kvm, unsigned long tce,
unsigned long gfn = tce >> PAGE_SHIFT;
struct kvm_memory_slot *memslot;
- memslot = search_memslots(kvm_memslots(kvm), gfn);
+ memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
if (!memslot)
return -EINVAL;
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
index dc6591548f0c..870b7f0c7ea5 100644
--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -80,7 +80,7 @@ static long kvmppc_rm_tce_to_ua(struct kvm *kvm,
unsigned long gfn = tce >> PAGE_SHIFT;
struct kvm_memory_slot *memslot;
- memslot = search_memslots(kvm_memslots_raw(kvm), gfn);
+ memslot = __gfn_to_memslot(kvm_memslots_raw(kvm), gfn);
if (!memslot)
return -EINVAL;
@@ -173,10 +173,13 @@ static void kvmppc_rm_tce_put(struct kvmppc_spapr_tce_table *stt,
idx -= stt->offset;
page = stt->pages[idx / TCES_PER_PAGE];
/*
- * page must not be NULL in real mode,
- * kvmppc_rm_ioba_validate() must have taken care of this.
+ * kvmppc_rm_ioba_validate() allows pages not be allocated if TCE is
+ * being cleared, otherwise it returns H_TOO_HARD and we skip this.
*/
- WARN_ON_ONCE_RM(!page);
+ if (!page) {
+ WARN_ON_ONCE_RM(tce != 0);
+ return;
+ }
tbl = kvmppc_page_address(page);
tbl[idx % TCES_PER_PAGE] = tce;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 085fb8ecbf68..2acb1c96cfaf 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -59,6 +59,7 @@
#include <asm/kvm_book3s.h>
#include <asm/mmu_context.h>
#include <asm/lppaca.h>
+#include <asm/pmc.h>
#include <asm/processor.h>
#include <asm/cputhreads.h>
#include <asm/page.h>
@@ -1165,7 +1166,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
break;
#endif
case H_RANDOM:
- if (!powernv_get_random_long(&vcpu->arch.regs.gpr[4]))
+ if (!arch_get_random_seed_long(&vcpu->arch.regs.gpr[4]))
ret = H_HARDWARE;
break;
case H_RPT_INVALIDATE:
@@ -1679,6 +1680,21 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
r = RESUME_GUEST;
}
break;
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ case BOOK3S_INTERRUPT_HV_SOFTPATCH:
+ /*
+ * This occurs for various TM-related instructions that
+ * we need to emulate on POWER9 DD2.2. We have already
+ * handled the cases where the guest was in real-suspend
+ * mode and was transitioning to transactional state.
+ */
+ r = kvmhv_p9_tm_emulation(vcpu);
+ if (r != -1)
+ break;
+ fallthrough; /* go to facility unavailable handler */
+#endif
+
/*
* This occurs if the guest (kernel or userspace), does something that
* is prohibited by HFSCR.
@@ -1697,18 +1713,6 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
}
break;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
- case BOOK3S_INTERRUPT_HV_SOFTPATCH:
- /*
- * This occurs for various TM-related instructions that
- * we need to emulate on POWER9 DD2.2. We have already
- * handled the cases where the guest was in real-suspend
- * mode and was transitioning to transactional state.
- */
- r = kvmhv_p9_tm_emulation(vcpu);
- break;
-#endif
-
case BOOK3S_INTERRUPT_HV_RM_HARD:
r = RESUME_PASSTHROUGH;
break;
@@ -1727,6 +1731,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
{
+ struct kvm_nested_guest *nested = vcpu->arch.nested;
int r;
int srcu_idx;
@@ -1811,9 +1816,41 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
* mode and was transitioning to transactional state.
*/
r = kvmhv_p9_tm_emulation(vcpu);
- break;
+ if (r != -1)
+ break;
+ fallthrough; /* go to facility unavailable handler */
#endif
+ case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: {
+ u64 cause = vcpu->arch.hfscr >> 56;
+
+ /*
+ * Only pass HFU interrupts to the L1 if the facility is
+ * permitted but disabled by the L1's HFSCR, otherwise
+ * the interrupt does not make sense to the L1 so turn
+ * it into a HEAI.
+ */
+ if (!(vcpu->arch.hfscr_permitted & (1UL << cause)) ||
+ (nested->hfscr & (1UL << cause))) {
+ vcpu->arch.trap = BOOK3S_INTERRUPT_H_EMUL_ASSIST;
+
+ /*
+ * If the fetch failed, return to guest and
+ * try executing it again.
+ */
+ r = kvmppc_get_last_inst(vcpu, INST_GENERIC,
+ &vcpu->arch.emul_inst);
+ if (r != EMULATE_DONE)
+ r = RESUME_GUEST;
+ else
+ r = RESUME_HOST;
+ } else {
+ r = RESUME_HOST;
+ }
+
+ break;
+ }
+
case BOOK3S_INTERRUPT_HV_RM_HARD:
vcpu->arch.trap = 0;
r = RESUME_GUEST;
@@ -2684,6 +2721,7 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
spin_lock_init(&vcpu->arch.vpa_update_lock);
spin_lock_init(&vcpu->arch.tbacct_lock);
vcpu->arch.busy_preempt = TB_NIL;
+ vcpu->arch.shregs.msr = MSR_ME;
vcpu->arch.intr_msr = MSR_SF | MSR_ME;
/*
@@ -2705,6 +2743,8 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
if (cpu_has_feature(CPU_FTR_TM_COMP))
vcpu->arch.hfscr |= HFSCR_TM;
+ vcpu->arch.hfscr_permitted = vcpu->arch.hfscr;
+
kvmppc_mmu_book3s_hv_init(vcpu);
vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
@@ -3727,7 +3767,6 @@ static void load_spr_state(struct kvm_vcpu *vcpu)
mtspr(SPRN_EBBHR, vcpu->arch.ebbhr);
mtspr(SPRN_EBBRR, vcpu->arch.ebbrr);
mtspr(SPRN_BESCR, vcpu->arch.bescr);
- mtspr(SPRN_WORT, vcpu->arch.wort);
mtspr(SPRN_TIDR, vcpu->arch.tid);
mtspr(SPRN_AMR, vcpu->arch.amr);
mtspr(SPRN_UAMOR, vcpu->arch.uamor);
@@ -3754,7 +3793,6 @@ static void store_spr_state(struct kvm_vcpu *vcpu)
vcpu->arch.ebbhr = mfspr(SPRN_EBBHR);
vcpu->arch.ebbrr = mfspr(SPRN_EBBRR);
vcpu->arch.bescr = mfspr(SPRN_BESCR);
- vcpu->arch.wort = mfspr(SPRN_WORT);
vcpu->arch.tid = mfspr(SPRN_TIDR);
vcpu->arch.amr = mfspr(SPRN_AMR);
vcpu->arch.uamor = mfspr(SPRN_UAMOR);
@@ -3786,7 +3824,6 @@ static void restore_p9_host_os_sprs(struct kvm_vcpu *vcpu,
struct p9_host_os_sprs *host_os_sprs)
{
mtspr(SPRN_PSPB, 0);
- mtspr(SPRN_WORT, 0);
mtspr(SPRN_UAMOR, 0);
mtspr(SPRN_DSCR, host_os_sprs->dscr);
@@ -3852,6 +3889,18 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST))
kvmppc_restore_tm_hv(vcpu, vcpu->arch.shregs.msr, true);
+#ifdef CONFIG_PPC_PSERIES
+ if (kvmhv_on_pseries()) {
+ barrier();
+ if (vcpu->arch.vpa.pinned_addr) {
+ struct lppaca *lp = vcpu->arch.vpa.pinned_addr;
+ get_lppaca()->pmcregs_in_use = lp->pmcregs_in_use;
+ } else {
+ get_lppaca()->pmcregs_in_use = 1;
+ }
+ barrier();
+ }
+#endif
kvmhv_load_guest_pmu(vcpu);
msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX);
@@ -3986,6 +4035,13 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
save_pmu |= nesting_enabled(vcpu->kvm);
kvmhv_save_guest_pmu(vcpu, save_pmu);
+#ifdef CONFIG_PPC_PSERIES
+ if (kvmhv_on_pseries()) {
+ barrier();
+ get_lppaca()->pmcregs_in_use = ppc_get_pmu_inuse();
+ barrier();
+ }
+#endif
vc->entry_exit_map = 0x101;
vc->in_guest = 0;
@@ -4146,19 +4202,31 @@ out:
/* Attribute wait time */
if (do_sleep) {
- vc->runner->stat.halt_wait_ns +=
+ vc->runner->stat.generic.halt_wait_ns +=
ktime_to_ns(cur) - ktime_to_ns(start_wait);
+ KVM_STATS_LOG_HIST_UPDATE(
+ vc->runner->stat.generic.halt_wait_hist,
+ ktime_to_ns(cur) - ktime_to_ns(start_wait));
/* Attribute failed poll time */
- if (vc->halt_poll_ns)
+ if (vc->halt_poll_ns) {
vc->runner->stat.generic.halt_poll_fail_ns +=
ktime_to_ns(start_wait) -
ktime_to_ns(start_poll);
+ KVM_STATS_LOG_HIST_UPDATE(
+ vc->runner->stat.generic.halt_poll_fail_hist,
+ ktime_to_ns(start_wait) -
+ ktime_to_ns(start_poll));
+ }
} else {
/* Attribute successful poll time */
- if (vc->halt_poll_ns)
+ if (vc->halt_poll_ns) {
vc->runner->stat.generic.halt_poll_success_ns +=
ktime_to_ns(cur) -
ktime_to_ns(start_poll);
+ KVM_STATS_LOG_HIST_UPDATE(
+ vc->runner->stat.generic.halt_poll_success_hist,
+ ktime_to_ns(cur) - ktime_to_ns(start_poll));
+ }
}
/* Adjust poll time */
@@ -5328,6 +5396,7 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
struct kvmppc_passthru_irqmap *pimap;
struct irq_chip *chip;
int i, rc = 0;
+ struct irq_data *host_data;
if (!kvm_irq_bypass)
return 1;
@@ -5355,7 +5424,7 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
* what our real-mode EOI code does, or a XIVE interrupt
*/
chip = irq_data_get_irq_chip(&desc->irq_data);
- if (!chip || !(is_pnv_opal_msi(chip) || is_xive_irq(chip))) {
+ if (!chip || !is_pnv_opal_msi(chip)) {
pr_warn("kvmppc_set_passthru_irq_hv: Could not assign IRQ map for (%d,%d)\n",
host_irq, guest_gsi);
mutex_unlock(&kvm->lock);
@@ -5392,15 +5461,22 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
* the KVM real mode handler.
*/
smp_wmb();
- irq_map->r_hwirq = desc->irq_data.hwirq;
+
+ /*
+ * The 'host_irq' number is mapped in the PCI-MSI domain but
+ * the underlying calls, which will EOI the interrupt in real
+ * mode, need an HW IRQ number mapped in the XICS IRQ domain.
+ */
+ host_data = irq_domain_get_irq_data(irq_get_default_host(), host_irq);
+ irq_map->r_hwirq = (unsigned int)irqd_to_hwirq(host_data);
if (i == pimap->n_mapped)
pimap->n_mapped++;
if (xics_on_xive())
- rc = kvmppc_xive_set_mapped(kvm, guest_gsi, desc);
+ rc = kvmppc_xive_set_mapped(kvm, guest_gsi, host_irq);
else
- kvmppc_xics_set_mapped(kvm, guest_gsi, desc->irq_data.hwirq);
+ kvmppc_xics_set_mapped(kvm, guest_gsi, irq_map->r_hwirq);
if (rc)
irq_map->r_hwirq = 0;
@@ -5439,7 +5515,7 @@ static int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
}
if (xics_on_xive())
- rc = kvmppc_xive_clr_mapped(kvm, guest_gsi, pimap->mapped[i].desc);
+ rc = kvmppc_xive_clr_mapped(kvm, guest_gsi, host_irq);
else
kvmppc_xics_clr_mapped(kvm, guest_gsi, pimap->mapped[i].r_hwirq);
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index be8ef1c5b1bf..fcf4760a3a0e 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -137,23 +137,23 @@ long int kvmppc_rm_h_confer(struct kvm_vcpu *vcpu, int target,
* exist in the system. We use a counter of VMs to track this.
*
* One of the operations we need to block is onlining of secondaries, so we
- * protect hv_vm_count with get/put_online_cpus().
+ * protect hv_vm_count with cpus_read_lock/unlock().
*/
static atomic_t hv_vm_count;
void kvm_hv_vm_activated(void)
{
- get_online_cpus();
+ cpus_read_lock();
atomic_inc(&hv_vm_count);
- put_online_cpus();
+ cpus_read_unlock();
}
EXPORT_SYMBOL_GPL(kvm_hv_vm_activated);
void kvm_hv_vm_deactivated(void)
{
- get_online_cpus();
+ cpus_read_lock();
atomic_dec(&hv_vm_count);
- put_online_cpus();
+ cpus_read_unlock();
}
EXPORT_SYMBOL_GPL(kvm_hv_vm_deactivated);
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index 898f942eb198..ed8a2c9f5629 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -99,13 +99,12 @@ static void byteswap_hv_regs(struct hv_guest_state *hr)
hr->dawrx1 = swab64(hr->dawrx1);
}
-static void save_hv_return_state(struct kvm_vcpu *vcpu, int trap,
+static void save_hv_return_state(struct kvm_vcpu *vcpu,
struct hv_guest_state *hr)
{
struct kvmppc_vcore *vc = vcpu->arch.vcore;
hr->dpdes = vc->dpdes;
- hr->hfscr = vcpu->arch.hfscr;
hr->purr = vcpu->arch.purr;
hr->spurr = vcpu->arch.spurr;
hr->ic = vcpu->arch.ic;
@@ -119,7 +118,7 @@ static void save_hv_return_state(struct kvm_vcpu *vcpu, int trap,
hr->pidr = vcpu->arch.pid;
hr->cfar = vcpu->arch.cfar;
hr->ppr = vcpu->arch.ppr;
- switch (trap) {
+ switch (vcpu->arch.trap) {
case BOOK3S_INTERRUPT_H_DATA_STORAGE:
hr->hdar = vcpu->arch.fault_dar;
hr->hdsisr = vcpu->arch.fault_dsisr;
@@ -128,55 +127,17 @@ static void save_hv_return_state(struct kvm_vcpu *vcpu, int trap,
case BOOK3S_INTERRUPT_H_INST_STORAGE:
hr->asdr = vcpu->arch.fault_gpa;
break;
+ case BOOK3S_INTERRUPT_H_FAC_UNAVAIL:
+ hr->hfscr = ((~HFSCR_INTR_CAUSE & hr->hfscr) |
+ (HFSCR_INTR_CAUSE & vcpu->arch.hfscr));
+ break;
case BOOK3S_INTERRUPT_H_EMUL_ASSIST:
hr->heir = vcpu->arch.emul_inst;
break;
}
}
-/*
- * This can result in some L0 HV register state being leaked to an L1
- * hypervisor when the hv_guest_state is copied back to the guest after
- * being modified here.
- *
- * There is no known problem with such a leak, and in many cases these
- * register settings could be derived by the guest by observing behaviour
- * and timing, interrupts, etc., but it is an issue to consider.
- */
-static void sanitise_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
-{
- struct kvmppc_vcore *vc = vcpu->arch.vcore;
- u64 mask;
-
- /*
- * Don't let L1 change LPCR bits for the L2 except these:
- */
- mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD |
- LPCR_LPES | LPCR_MER;
-
- /*
- * Additional filtering is required depending on hardware
- * and configuration.
- */
- hr->lpcr = kvmppc_filter_lpcr_hv(vcpu->kvm,
- (vc->lpcr & ~mask) | (hr->lpcr & mask));
-
- /*
- * Don't let L1 enable features for L2 which we've disabled for L1,
- * but preserve the interrupt cause field.
- */
- hr->hfscr &= (HFSCR_INTR_CAUSE | vcpu->arch.hfscr);
-
- /* Don't let data address watchpoint match in hypervisor state */
- hr->dawrx0 &= ~DAWRX_HYP;
- hr->dawrx1 &= ~DAWRX_HYP;
-
- /* Don't let completed instruction address breakpt match in HV state */
- if ((hr->ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER)
- hr->ciabr &= ~CIABR_PRIV;
-}
-
-static void restore_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
+static void restore_hv_regs(struct kvm_vcpu *vcpu, const struct hv_guest_state *hr)
{
struct kvmppc_vcore *vc = vcpu->arch.vcore;
@@ -288,6 +249,43 @@ static int kvmhv_write_guest_state_and_regs(struct kvm_vcpu *vcpu,
sizeof(struct pt_regs));
}
+static void load_l2_hv_regs(struct kvm_vcpu *vcpu,
+ const struct hv_guest_state *l2_hv,
+ const struct hv_guest_state *l1_hv, u64 *lpcr)
+{
+ struct kvmppc_vcore *vc = vcpu->arch.vcore;
+ u64 mask;
+
+ restore_hv_regs(vcpu, l2_hv);
+
+ /*
+ * Don't let L1 change LPCR bits for the L2 except these:
+ */
+ mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD |
+ LPCR_LPES | LPCR_MER;
+
+ /*
+ * Additional filtering is required depending on hardware
+ * and configuration.
+ */
+ *lpcr = kvmppc_filter_lpcr_hv(vcpu->kvm,
+ (vc->lpcr & ~mask) | (*lpcr & mask));
+
+ /*
+ * Don't let L1 enable features for L2 which we don't allow for L1,
+ * but preserve the interrupt cause field.
+ */
+ vcpu->arch.hfscr = l2_hv->hfscr & (HFSCR_INTR_CAUSE | vcpu->arch.hfscr_permitted);
+
+ /* Don't let data address watchpoint match in hypervisor state */
+ vcpu->arch.dawrx0 = l2_hv->dawrx0 & ~DAWRX_HYP;
+ vcpu->arch.dawrx1 = l2_hv->dawrx1 & ~DAWRX_HYP;
+
+ /* Don't let completed instruction address breakpt match in HV state */
+ if ((l2_hv->ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER)
+ vcpu->arch.ciabr = l2_hv->ciabr & ~CIABR_PRIV;
+}
+
long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
{
long int err, r;
@@ -296,7 +294,7 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
struct hv_guest_state l2_hv = {0}, saved_l1_hv;
struct kvmppc_vcore *vc = vcpu->arch.vcore;
u64 hv_ptr, regs_ptr;
- u64 hdec_exp;
+ u64 hdec_exp, lpcr;
s64 delta_purr, delta_spurr, delta_ic, delta_vtb;
if (vcpu->kvm->arch.l1_ptcr == 0)
@@ -364,13 +362,14 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
/* set L1 state to L2 state */
vcpu->arch.nested = l2;
vcpu->arch.nested_vcpu_id = l2_hv.vcpu_token;
+ l2->hfscr = l2_hv.hfscr;
vcpu->arch.regs = l2_regs;
/* Guest must always run with ME enabled, HV disabled. */
vcpu->arch.shregs.msr = (vcpu->arch.regs.msr | MSR_ME) & ~MSR_HV;
- sanitise_hv_regs(vcpu, &l2_hv);
- restore_hv_regs(vcpu, &l2_hv);
+ lpcr = l2_hv.lpcr;
+ load_l2_hv_regs(vcpu, &l2_hv, &saved_l1_hv, &lpcr);
vcpu->arch.ret = RESUME_GUEST;
vcpu->arch.trap = 0;
@@ -380,7 +379,7 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
r = RESUME_HOST;
break;
}
- r = kvmhv_run_single_vcpu(vcpu, hdec_exp, l2_hv.lpcr);
+ r = kvmhv_run_single_vcpu(vcpu, hdec_exp, lpcr);
} while (is_kvmppc_resume_guest(r));
/* save L2 state for return */
@@ -390,7 +389,7 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
delta_spurr = vcpu->arch.spurr - l2_hv.spurr;
delta_ic = vcpu->arch.ic - l2_hv.ic;
delta_vtb = vc->vtb - l2_hv.vtb;
- save_hv_return_state(vcpu, vcpu->arch.trap, &l2_hv);
+ save_hv_return_state(vcpu, &l2_hv);
/* restore L1 state */
vcpu->arch.nested = NULL;
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c
index 0a11ec88a0ae..587c33fc4564 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_xics.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c
@@ -706,6 +706,7 @@ static int ics_rm_eoi(struct kvm_vcpu *vcpu, u32 irq)
icp->rm_eoied_irq = irq;
}
+ /* Handle passthrough interrupts */
if (state->host_irq) {
++vcpu->stat.pthru_all;
if (state->intr_cpu != -1) {
@@ -759,12 +760,12 @@ int xics_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
static unsigned long eoi_rc;
-static void icp_eoi(struct irq_chip *c, u32 hwirq, __be32 xirr, bool *again)
+static void icp_eoi(struct irq_data *d, u32 hwirq, __be32 xirr, bool *again)
{
void __iomem *xics_phys;
int64_t rc;
- rc = pnv_opal_pci_msi_eoi(c, hwirq);
+ rc = pnv_opal_pci_msi_eoi(d);
if (rc)
eoi_rc = rc;
@@ -872,8 +873,7 @@ long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu,
icp_rm_deliver_irq(xics, icp, irq, false);
/* EOI the interrupt */
- icp_eoi(irq_desc_get_chip(irq_map->desc), irq_map->r_hwirq, xirr,
- again);
+ icp_eoi(irq_desc_get_irq_data(irq_map->desc), irq_map->r_hwirq, xirr, again);
if (check_too_hard(xics, icp) == H_TOO_HARD)
return 2;
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 8dd437d7a2c6..75079397c2a5 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1088,12 +1088,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
cmpwi r12, BOOK3S_INTERRUPT_H_INST_STORAGE
beq kvmppc_hisi
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
- /* For softpatch interrupt, go off and do TM instruction emulation */
- cmpwi r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
- beq kvmppc_tm_emul
-#endif
-
/* See if this is a leftover HDEC interrupt */
cmpwi r12,BOOK3S_INTERRUPT_HV_DECREMENTER
bne 2f
@@ -1599,42 +1593,6 @@ maybe_reenter_guest:
blt deliver_guest_interrupt
b guest_exit_cont
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-/*
- * Softpatch interrupt for transactional memory emulation cases
- * on POWER9 DD2.2. This is early in the guest exit path - we
- * haven't saved registers or done a treclaim yet.
- */
-kvmppc_tm_emul:
- /* Save instruction image in HEIR */
- mfspr r3, SPRN_HEIR
- stw r3, VCPU_HEIR(r9)
-
- /*
- * The cases we want to handle here are those where the guest
- * is in real suspend mode and is trying to transition to
- * transactional mode.
- */
- lbz r0, HSTATE_FAKE_SUSPEND(r13)
- cmpwi r0, 0 /* keep exiting guest if in fake suspend */
- bne guest_exit_cont
- rldicl r3, r11, 64 - MSR_TS_S_LG, 62
- cmpwi r3, 1 /* or if not in suspend state */
- bne guest_exit_cont
-
- /* Call C code to do the emulation */
- mr r3, r9
- bl kvmhv_p9_tm_emulation_early
- nop
- ld r9, HSTATE_KVM_VCPU(r13)
- li r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
- cmpwi r3, 0
- beq guest_exit_cont /* continue exiting if not handled */
- ld r10, VCPU_PC(r9)
- ld r11, VCPU_MSR(r9)
- b fast_interrupt_c_return /* go back to guest if handled */
-#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
-
/*
* Check whether an HDSI is an HPTE not found fault or something else.
* If it is an HPTE not found fault that is due to the guest accessing
diff --git a/arch/powerpc/kvm/book3s_hv_tm.c b/arch/powerpc/kvm/book3s_hv_tm.c
index cc90b8b82329..866cadd70094 100644
--- a/arch/powerpc/kvm/book3s_hv_tm.c
+++ b/arch/powerpc/kvm/book3s_hv_tm.c
@@ -47,6 +47,15 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
int ra, rs;
/*
+ * The TM softpatch interrupt sets NIP to the instruction following
+ * the faulting instruction, which is not executed. Rewind nip to the
+ * faulting instruction so it looks like a normal synchronous
+ * interrupt, then update nip in the places where the instruction is
+ * emulated.
+ */
+ vcpu->arch.regs.nip -= 4;
+
+ /*
* rfid, rfebb, and mtmsrd encode bit 31 = 0 since it's a reserved bit
* in these instructions, so masking bit 31 out doesn't change these
* instructions. For treclaim., tsr., and trechkpt. instructions if bit
@@ -67,7 +76,7 @@ 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.regs.nip - 4;
+ vcpu->arch.cfar = vcpu->arch.regs.nip;
vcpu->arch.regs.nip = vcpu->arch.shregs.srr0;
return RESUME_GUEST;
@@ -79,14 +88,15 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
}
/* check EBB facility is available */
if (!(vcpu->arch.hfscr & HFSCR_EBB)) {
- /* generate an illegal instruction interrupt */
- kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
- return RESUME_GUEST;
+ vcpu->arch.hfscr &= ~HFSCR_INTR_CAUSE;
+ vcpu->arch.hfscr |= (u64)FSCR_EBB_LG << 56;
+ vcpu->arch.trap = BOOK3S_INTERRUPT_H_FAC_UNAVAIL;
+ return -1; /* rerun host interrupt handler */
}
if ((msr & MSR_PR) && !(vcpu->arch.fscr & FSCR_EBB)) {
/* generate a facility unavailable interrupt */
- vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) |
- ((u64)FSCR_EBB_LG << 56);
+ vcpu->arch.fscr &= ~FSCR_INTR_CAUSE;
+ vcpu->arch.fscr |= (u64)FSCR_EBB_LG << 56;
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FAC_UNAVAIL);
return RESUME_GUEST;
}
@@ -100,7 +110,7 @@ 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.regs.nip - 4;
+ vcpu->arch.cfar = vcpu->arch.regs.nip;
vcpu->arch.regs.nip = vcpu->arch.ebbrr;
return RESUME_GUEST;
@@ -116,6 +126,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
newmsr = (newmsr & ~MSR_LE) | (msr & MSR_LE);
newmsr = sanitize_msr(newmsr);
vcpu->arch.shregs.msr = newmsr;
+ vcpu->arch.regs.nip += 4;
return RESUME_GUEST;
/* ignore bit 31, see comment above */
@@ -128,14 +139,15 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
}
/* check for TM disabled in the HFSCR or MSR */
if (!(vcpu->arch.hfscr & HFSCR_TM)) {
- /* generate an illegal instruction interrupt */
- kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
- return RESUME_GUEST;
+ vcpu->arch.hfscr &= ~HFSCR_INTR_CAUSE;
+ vcpu->arch.hfscr |= (u64)FSCR_TM_LG << 56;
+ vcpu->arch.trap = BOOK3S_INTERRUPT_H_FAC_UNAVAIL;
+ return -1; /* rerun host interrupt handler */
}
if (!(msr & MSR_TM)) {
/* generate a facility unavailable interrupt */
- vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) |
- ((u64)FSCR_TM_LG << 56);
+ vcpu->arch.fscr &= ~FSCR_INTR_CAUSE;
+ vcpu->arch.fscr |= (u64)FSCR_TM_LG << 56;
kvmppc_book3s_queue_irqprio(vcpu,
BOOK3S_INTERRUPT_FAC_UNAVAIL);
return RESUME_GUEST;
@@ -152,20 +164,22 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
msr = (msr & ~MSR_TS_MASK) | MSR_TS_S;
}
vcpu->arch.shregs.msr = msr;
+ vcpu->arch.regs.nip += 4;
return RESUME_GUEST;
/* ignore bit 31, see comment above */
case (PPC_INST_TRECLAIM & PO_XOP_OPCODE_MASK):
/* check for TM disabled in the HFSCR or MSR */
if (!(vcpu->arch.hfscr & HFSCR_TM)) {
- /* generate an illegal instruction interrupt */
- kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
- return RESUME_GUEST;
+ vcpu->arch.hfscr &= ~HFSCR_INTR_CAUSE;
+ vcpu->arch.hfscr |= (u64)FSCR_TM_LG << 56;
+ vcpu->arch.trap = BOOK3S_INTERRUPT_H_FAC_UNAVAIL;
+ return -1; /* rerun host interrupt handler */
}
if (!(msr & MSR_TM)) {
/* generate a facility unavailable interrupt */
- vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) |
- ((u64)FSCR_TM_LG << 56);
+ vcpu->arch.fscr &= ~FSCR_INTR_CAUSE;
+ vcpu->arch.fscr |= (u64)FSCR_TM_LG << 56;
kvmppc_book3s_queue_irqprio(vcpu,
BOOK3S_INTERRUPT_FAC_UNAVAIL);
return RESUME_GUEST;
@@ -189,6 +203,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) |
(((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29);
vcpu->arch.shregs.msr &= ~MSR_TS_MASK;
+ vcpu->arch.regs.nip += 4;
return RESUME_GUEST;
/* ignore bit 31, see comment above */
@@ -196,14 +211,15 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
/* XXX do we need to check for PR=0 here? */
/* check for TM disabled in the HFSCR or MSR */
if (!(vcpu->arch.hfscr & HFSCR_TM)) {
- /* generate an illegal instruction interrupt */
- kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
- return RESUME_GUEST;
+ vcpu->arch.hfscr &= ~HFSCR_INTR_CAUSE;
+ vcpu->arch.hfscr |= (u64)FSCR_TM_LG << 56;
+ vcpu->arch.trap = BOOK3S_INTERRUPT_H_FAC_UNAVAIL;
+ return -1; /* rerun host interrupt handler */
}
if (!(msr & MSR_TM)) {
/* generate a facility unavailable interrupt */
- vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) |
- ((u64)FSCR_TM_LG << 56);
+ vcpu->arch.fscr &= ~FSCR_INTR_CAUSE;
+ vcpu->arch.fscr |= (u64)FSCR_TM_LG << 56;
kvmppc_book3s_queue_irqprio(vcpu,
BOOK3S_INTERRUPT_FAC_UNAVAIL);
return RESUME_GUEST;
@@ -220,6 +236,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) |
(((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29);
vcpu->arch.shregs.msr = msr | MSR_TS_S;
+ vcpu->arch.regs.nip += 4;
return RESUME_GUEST;
}
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index 303e3cb096db..ebd5d920de8c 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -10,13 +10,13 @@
#include <linux/gfp.h>
#include <linux/anon_inodes.h>
#include <linux/spinlock.h>
-
+#include <linux/debugfs.h>
#include <linux/uaccess.h>
+
#include <asm/kvm_book3s.h>
#include <asm/kvm_ppc.h>
#include <asm/hvcall.h>
#include <asm/xics.h>
-#include <asm/debugfs.h>
#include <asm/time.h>
#include <linux/seq_file.h>
@@ -1024,7 +1024,7 @@ static void xics_debugfs_init(struct kvmppc_xics *xics)
return;
}
- xics->dentry = debugfs_create_file(name, 0444, powerpc_debugfs_root,
+ xics->dentry = debugfs_create_file(name, 0444, arch_debugfs_dir,
xics, &xics_debug_fops);
pr_debug("%s: created %s\n", __func__, name);
diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c
index 8cfab3547494..a18db9e16ea4 100644
--- a/arch/powerpc/kvm/book3s_xive.c
+++ b/arch/powerpc/kvm/book3s_xive.c
@@ -22,7 +22,6 @@
#include <asm/xive.h>
#include <asm/xive-regs.h>
#include <asm/debug.h>
-#include <asm/debugfs.h>
#include <asm/time.h>
#include <asm/opal.h>
@@ -59,6 +58,25 @@
*/
#define XIVE_Q_GAP 2
+static bool kvmppc_xive_vcpu_has_save_restore(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+
+ /* Check enablement at VP level */
+ return xc->vp_cam & TM_QW1W2_HO;
+}
+
+bool kvmppc_xive_check_save_restore(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+ struct kvmppc_xive *xive = xc->xive;
+
+ if (xive->flags & KVMPPC_XIVE_FLAG_SAVE_RESTORE)
+ return kvmppc_xive_vcpu_has_save_restore(vcpu);
+
+ return true;
+}
+
/*
* Push a vcpu's context to the XIVE on guest entry.
* This assumes we are in virtual mode (MMU on)
@@ -77,7 +95,8 @@ void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu)
return;
eieio();
- __raw_writeq(vcpu->arch.xive_saved_state.w01, tima + TM_QW1_OS);
+ if (!kvmppc_xive_vcpu_has_save_restore(vcpu))
+ __raw_writeq(vcpu->arch.xive_saved_state.w01, tima + TM_QW1_OS);
__raw_writel(vcpu->arch.xive_cam_word, tima + TM_QW1_OS + TM_WORD2);
vcpu->arch.xive_pushed = 1;
eieio();
@@ -149,7 +168,8 @@ void kvmppc_xive_pull_vcpu(struct kvm_vcpu *vcpu)
/* First load to pull the context, we ignore the value */
__raw_readl(tima + TM_SPC_PULL_OS_CTX);
/* Second load to recover the context state (Words 0 and 1) */
- vcpu->arch.xive_saved_state.w01 = __raw_readq(tima + TM_QW1_OS);
+ if (!kvmppc_xive_vcpu_has_save_restore(vcpu))
+ vcpu->arch.xive_saved_state.w01 = __raw_readq(tima + TM_QW1_OS);
/* Fixup some of the state for the next load */
vcpu->arch.xive_saved_state.lsmfb = 0;
@@ -363,9 +383,9 @@ static int xive_check_provisioning(struct kvm *kvm, u8 prio)
if (!vcpu->arch.xive_vcpu)
continue;
rc = xive_provision_queue(vcpu, prio);
- if (rc == 0 && !xive->single_escalation)
+ if (rc == 0 && !kvmppc_xive_has_single_escalation(xive))
kvmppc_xive_attach_escalation(vcpu, prio,
- xive->single_escalation);
+ kvmppc_xive_has_single_escalation(xive));
if (rc)
return rc;
}
@@ -922,13 +942,13 @@ int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval)
}
int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
- struct irq_desc *host_desc)
+ unsigned long host_irq)
{
struct kvmppc_xive *xive = kvm->arch.xive;
struct kvmppc_xive_src_block *sb;
struct kvmppc_xive_irq_state *state;
- struct irq_data *host_data = irq_desc_get_irq_data(host_desc);
- unsigned int host_irq = irq_desc_get_irq(host_desc);
+ struct irq_data *host_data =
+ irq_domain_get_irq_data(irq_get_default_host(), host_irq);
unsigned int hw_irq = (unsigned int)irqd_to_hwirq(host_data);
u16 idx;
u8 prio;
@@ -937,7 +957,8 @@ int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
if (!xive)
return -ENODEV;
- pr_devel("set_mapped girq 0x%lx host HW irq 0x%x...\n",guest_irq, hw_irq);
+ pr_debug("%s: GIRQ 0x%lx host IRQ %ld XIVE HW IRQ 0x%x\n",
+ __func__, guest_irq, host_irq, hw_irq);
sb = kvmppc_xive_find_source(xive, guest_irq, &idx);
if (!sb)
@@ -959,7 +980,7 @@ int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
*/
rc = irq_set_vcpu_affinity(host_irq, state);
if (rc) {
- pr_err("Failed to set VCPU affinity for irq %d\n", host_irq);
+ pr_err("Failed to set VCPU affinity for host IRQ %ld\n", host_irq);
return rc;
}
@@ -1019,12 +1040,11 @@ int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
EXPORT_SYMBOL_GPL(kvmppc_xive_set_mapped);
int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
- struct irq_desc *host_desc)
+ unsigned long host_irq)
{
struct kvmppc_xive *xive = kvm->arch.xive;
struct kvmppc_xive_src_block *sb;
struct kvmppc_xive_irq_state *state;
- unsigned int host_irq = irq_desc_get_irq(host_desc);
u16 idx;
u8 prio;
int rc;
@@ -1032,7 +1052,7 @@ int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
if (!xive)
return -ENODEV;
- pr_devel("clr_mapped girq 0x%lx...\n", guest_irq);
+ pr_debug("%s: GIRQ 0x%lx host IRQ %ld\n", __func__, guest_irq, host_irq);
sb = kvmppc_xive_find_source(xive, guest_irq, &idx);
if (!sb)
@@ -1059,7 +1079,7 @@ int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
/* Release the passed-through interrupt to the host */
rc = irq_set_vcpu_affinity(host_irq, NULL);
if (rc) {
- pr_err("Failed to clr VCPU affinity for irq %d\n", host_irq);
+ pr_err("Failed to clr VCPU affinity for host IRQ %ld\n", host_irq);
return rc;
}
@@ -1199,7 +1219,7 @@ void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu)
/* Free escalations */
for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
if (xc->esc_virq[i]) {
- if (xc->xive->single_escalation)
+ if (kvmppc_xive_has_single_escalation(xc->xive))
xive_cleanup_single_escalation(vcpu, xc,
xc->esc_virq[i]);
free_irq(xc->esc_virq[i], vcpu);
@@ -1319,6 +1339,12 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
if (r)
goto bail;
+ if (!kvmppc_xive_check_save_restore(vcpu)) {
+ pr_err("inconsistent save-restore setup for VCPU %d\n", cpu);
+ r = -EIO;
+ goto bail;
+ }
+
/* Configure VCPU fields for use by assembly push/pull */
vcpu->arch.xive_saved_state.w01 = cpu_to_be64(0xff000000);
vcpu->arch.xive_cam_word = cpu_to_be32(xc->vp_cam | TM_QW1W2_VO);
@@ -1340,7 +1366,7 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
* Enable the VP first as the single escalation mode will
* affect escalation interrupts numbering
*/
- r = xive_native_enable_vp(xc->vp_id, xive->single_escalation);
+ r = xive_native_enable_vp(xc->vp_id, kvmppc_xive_has_single_escalation(xive));
if (r) {
pr_err("Failed to enable VP in OPAL, err %d\n", r);
goto bail;
@@ -1357,15 +1383,15 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
struct xive_q *q = &xc->queues[i];
/* Single escalation, no queue 7 */
- if (i == 7 && xive->single_escalation)
+ if (i == 7 && kvmppc_xive_has_single_escalation(xive))
break;
/* Is queue already enabled ? Provision it */
if (xive->qmap & (1 << i)) {
r = xive_provision_queue(vcpu, i);
- if (r == 0 && !xive->single_escalation)
+ if (r == 0 && !kvmppc_xive_has_single_escalation(xive))
kvmppc_xive_attach_escalation(
- vcpu, i, xive->single_escalation);
+ vcpu, i, kvmppc_xive_has_single_escalation(xive));
if (r)
goto bail;
} else {
@@ -1380,7 +1406,7 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
}
/* If not done above, attach priority 0 escalation */
- r = kvmppc_xive_attach_escalation(vcpu, 0, xive->single_escalation);
+ r = kvmppc_xive_attach_escalation(vcpu, 0, kvmppc_xive_has_single_escalation(xive));
if (r)
goto bail;
@@ -2135,7 +2161,11 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type)
*/
xive->nr_servers = KVM_MAX_VCPUS;
- xive->single_escalation = xive_native_has_single_escalation();
+ if (xive_native_has_single_escalation())
+ xive->flags |= KVMPPC_XIVE_FLAG_SINGLE_ESCALATION;
+
+ if (xive_native_has_save_restore())
+ xive->flags |= KVMPPC_XIVE_FLAG_SAVE_RESTORE;
kvm->arch.xive = xive;
return 0;
@@ -2329,7 +2359,7 @@ static void xive_debugfs_init(struct kvmppc_xive *xive)
return;
}
- xive->dentry = debugfs_create_file(name, S_IRUGO, powerpc_debugfs_root,
+ xive->dentry = debugfs_create_file(name, S_IRUGO, arch_debugfs_dir,
xive, &xive_debug_fops);
pr_debug("%s: created %s\n", __func__, name);
diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h
index afe9eeac6d56..e6a9651c6f1e 100644
--- a/arch/powerpc/kvm/book3s_xive.h
+++ b/arch/powerpc/kvm/book3s_xive.h
@@ -97,6 +97,9 @@ struct kvmppc_xive_ops {
int (*reset_mapped)(struct kvm *kvm, unsigned long guest_irq);
};
+#define KVMPPC_XIVE_FLAG_SINGLE_ESCALATION 0x1
+#define KVMPPC_XIVE_FLAG_SAVE_RESTORE 0x2
+
struct kvmppc_xive {
struct kvm *kvm;
struct kvm_device *dev;
@@ -133,7 +136,7 @@ struct kvmppc_xive {
u32 q_page_order;
/* Flags */
- u8 single_escalation;
+ u8 flags;
/* Number of entries in the VP block */
u32 nr_servers;
@@ -307,6 +310,12 @@ void xive_cleanup_single_escalation(struct kvm_vcpu *vcpu,
struct kvmppc_xive_vcpu *xc, int irq);
int kvmppc_xive_compute_vp_id(struct kvmppc_xive *xive, u32 cpu, u32 *vp);
int kvmppc_xive_set_nr_servers(struct kvmppc_xive *xive, u64 addr);
+bool kvmppc_xive_check_save_restore(struct kvm_vcpu *vcpu);
+
+static inline bool kvmppc_xive_has_single_escalation(struct kvmppc_xive *xive)
+{
+ return xive->flags & KVMPPC_XIVE_FLAG_SINGLE_ESCALATION;
+}
#endif /* CONFIG_KVM_XICS */
#endif /* _KVM_PPC_BOOK3S_XICS_H */
diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c
index 573ecaab3597..99db9ac49901 100644
--- a/arch/powerpc/kvm/book3s_xive_native.c
+++ b/arch/powerpc/kvm/book3s_xive_native.c
@@ -20,7 +20,6 @@
#include <asm/xive.h>
#include <asm/xive-regs.h>
#include <asm/debug.h>
-#include <asm/debugfs.h>
#include <asm/opal.h>
#include <linux/debugfs.h>
@@ -93,7 +92,7 @@ void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu)
for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
/* Free the escalation irq */
if (xc->esc_virq[i]) {
- if (xc->xive->single_escalation)
+ if (kvmppc_xive_has_single_escalation(xc->xive))
xive_cleanup_single_escalation(vcpu, xc,
xc->esc_virq[i]);
free_irq(xc->esc_virq[i], vcpu);
@@ -168,11 +167,17 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
goto bail;
}
+ if (!kvmppc_xive_check_save_restore(vcpu)) {
+ pr_err("inconsistent save-restore setup for VCPU %d\n", server_num);
+ rc = -EIO;
+ goto bail;
+ }
+
/*
* Enable the VP first as the single escalation mode will
* affect escalation interrupts numbering
*/
- rc = xive_native_enable_vp(xc->vp_id, xive->single_escalation);
+ rc = xive_native_enable_vp(xc->vp_id, kvmppc_xive_has_single_escalation(xive));
if (rc) {
pr_err("Failed to enable VP in OPAL: %d\n", rc);
goto bail;
@@ -693,7 +698,7 @@ static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive,
}
rc = kvmppc_xive_attach_escalation(vcpu, priority,
- xive->single_escalation);
+ kvmppc_xive_has_single_escalation(xive));
error:
if (rc)
kvmppc_xive_native_cleanup_queue(vcpu, priority);
@@ -820,7 +825,7 @@ static int kvmppc_xive_reset(struct kvmppc_xive *xive)
for (prio = 0; prio < KVMPPC_XIVE_Q_COUNT; prio++) {
/* Single escalation, no queue 7 */
- if (prio == 7 && xive->single_escalation)
+ if (prio == 7 && kvmppc_xive_has_single_escalation(xive))
break;
if (xc->esc_virq[prio]) {
@@ -1111,7 +1116,12 @@ static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type)
*/
xive->nr_servers = KVM_MAX_VCPUS;
- xive->single_escalation = xive_native_has_single_escalation();
+ if (xive_native_has_single_escalation())
+ xive->flags |= KVMPPC_XIVE_FLAG_SINGLE_ESCALATION;
+
+ if (xive_native_has_save_restore())
+ xive->flags |= KVMPPC_XIVE_FLAG_SAVE_RESTORE;
+
xive->ops = &kvmppc_xive_native_ops;
kvm->arch.xive = xive;
@@ -1257,7 +1267,7 @@ static void xive_native_debugfs_init(struct kvmppc_xive *xive)
return;
}
- xive->dentry = debugfs_create_file(name, 0444, powerpc_debugfs_root,
+ xive->dentry = debugfs_create_file(name, 0444, arch_debugfs_dir,
xive, &xive_native_debug_fops);
pr_debug("%s: created %s\n", __func__, name);
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 551b30d84aee..977801c83aff 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -41,8 +41,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_ICOUNTER(VM, num_2M_pages),
STATS_DESC_ICOUNTER(VM, num_1G_pages)
};
-static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
- sizeof(struct kvm_vm_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vm_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -69,7 +67,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
STATS_DESC_COUNTER(VCPU, dec_exits),
STATS_DESC_COUNTER(VCPU, ext_intr_exits),
- STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
STATS_DESC_COUNTER(VCPU, halt_successful_wait),
STATS_DESC_COUNTER(VCPU, dbell_exits),
STATS_DESC_COUNTER(VCPU, gdbell_exits),
@@ -79,8 +76,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, pthru_host),
STATS_DESC_COUNTER(VCPU, pthru_bad_aff)
};
-static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
- sizeof(struct kvm_vcpu_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vcpu_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index eae4ec2988fc..df8172da2301 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -18,5 +18,5 @@ obj-$(CONFIG_PPC_MM_SLICES) += slice.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o
-obj-$(CONFIG_PPC_PTDUMP) += ptdump/
+obj-$(CONFIG_PTDUMP_CORE) += ptdump/
obj-$(CONFIG_KASAN) += kasan/
diff --git a/arch/powerpc/mm/book3s64/hash_native.c b/arch/powerpc/mm/book3s64/hash_native.c
index 52e170bd95ae..d8279bfe68ea 100644
--- a/arch/powerpc/mm/book3s64/hash_native.c
+++ b/arch/powerpc/mm/book3s64/hash_native.c
@@ -787,7 +787,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
* TODO: add batching support when enabled. remember, no dynamic memory here,
* although there is the control page available...
*/
-static void native_hpte_clear(void)
+static notrace void native_hpte_clear(void)
{
unsigned long vpn = 0;
unsigned long slot, slots;
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
index ac5720371c0d..c145776d3ae5 100644
--- a/arch/powerpc/mm/book3s64/hash_utils.c
+++ b/arch/powerpc/mm/book3s64/hash_utils.c
@@ -36,8 +36,8 @@
#include <linux/hugetlb.h>
#include <linux/cpu.h>
#include <linux/pgtable.h>
+#include <linux/debugfs.h>
-#include <asm/debugfs.h>
#include <asm/interrupt.h>
#include <asm/processor.h>
#include <asm/mmu.h>
@@ -2072,7 +2072,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_hpt_order, hpt_order_get, hpt_order_set, "%llu\n")
static int __init hash64_debugfs(void)
{
- debugfs_create_file("hpt_order", 0600, powerpc_debugfs_root, NULL,
+ debugfs_create_file("hpt_order", 0600, arch_debugfs_dir, NULL,
&fops_hpt_order);
return 0;
}
diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
index 9ffa65074cb0..9e16c7b1a6c5 100644
--- a/arch/powerpc/mm/book3s64/pgtable.c
+++ b/arch/powerpc/mm/book3s64/pgtable.c
@@ -6,9 +6,9 @@
#include <linux/sched.h>
#include <linux/mm_types.h>
#include <linux/memblock.h>
+#include <linux/debugfs.h>
#include <misc/cxl-base.h>
-#include <asm/debugfs.h>
#include <asm/pgalloc.h>
#include <asm/tlb.h>
#include <asm/trace.h>
@@ -172,8 +172,8 @@ pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
-/* For use by kexec */
-void mmu_cleanup_all(void)
+/* For use by kexec, called with MMU off */
+notrace void mmu_cleanup_all(void)
{
if (radix_enabled())
radix__mmu_cleanup_all();
@@ -520,7 +520,7 @@ static int __init pgtable_debugfs_setup(void)
* invalidated as expected.
*/
debugfs_create_bool("tlbie_enabled", 0600,
- powerpc_debugfs_root,
+ arch_debugfs_dir,
&tlbie_enabled);
return 0;
diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
index e50ddf129c15..ae20add7954a 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -679,7 +679,8 @@ void radix__early_init_mmu_secondary(void)
mtspr(SPRN_UAMOR, 0);
}
-void radix__mmu_cleanup_all(void)
+/* Called during kexec sequence with MMU off */
+notrace void radix__mmu_cleanup_all(void)
{
unsigned long lpcr;
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index aefc100d79a7..7724af19ed7e 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -10,6 +10,7 @@
#include <linux/memblock.h>
#include <linux/mmu_context.h>
#include <linux/sched/mm.h>
+#include <linux/debugfs.h>
#include <asm/ppc-opcode.h>
#include <asm/tlb.h>
@@ -1106,8 +1107,8 @@ EXPORT_SYMBOL(radix__flush_tlb_kernel_range);
* invalidating a full PID, so it has a far lower threshold to change from
* individual page flushes to full-pid flushes.
*/
-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;
+static u32 tlb_single_page_flush_ceiling __read_mostly = 33;
+static u32 tlb_local_single_page_flush_ceiling __read_mostly = POWER9_TLB_SETS_RADIX * 2;
static inline void __radix__flush_tlb_range(struct mm_struct *mm,
unsigned long start, unsigned long end)
@@ -1524,3 +1525,14 @@ void do_h_rpt_invalidate_prt(unsigned long pid, unsigned long lpid,
EXPORT_SYMBOL_GPL(do_h_rpt_invalidate_prt);
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
+
+static int __init create_tlb_single_page_flush_ceiling(void)
+{
+ debugfs_create_u32("tlb_single_page_flush_ceiling", 0600,
+ arch_debugfs_dir, &tlb_single_page_flush_ceiling);
+ debugfs_create_u32("tlb_local_single_page_flush_ceiling", 0600,
+ arch_debugfs_dir, &tlb_local_single_page_flush_ceiling);
+ return 0;
+}
+late_initcall(create_tlb_single_page_flush_ceiling);
+
diff --git a/arch/powerpc/mm/book3s64/slb.c b/arch/powerpc/mm/book3s64/slb.c
index c91bd85eb90e..f0037bcc47a0 100644
--- a/arch/powerpc/mm/book3s64/slb.c
+++ b/arch/powerpc/mm/book3s64/slb.c
@@ -822,7 +822,7 @@ DEFINE_INTERRUPT_HANDLER_RAW(do_slb_fault)
/* IRQs are not reconciled here, so can't check irqs_disabled */
VM_WARN_ON(mfmsr() & MSR_EE);
- if (unlikely(!(regs->msr & MSR_RI)))
+ if (regs_is_unrecoverable(regs))
return -EINVAL;
/*
diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c
index 9af3832c9d8d..22197b18d85e 100644
--- a/arch/powerpc/mm/drmem.c
+++ b/arch/powerpc/mm/drmem.c
@@ -18,6 +18,7 @@ static int n_root_addr_cells, n_root_size_cells;
static struct drmem_lmb_info __drmem_info;
struct drmem_lmb_info *drmem_info = &__drmem_info;
+static bool in_drmem_update;
u64 drmem_lmb_memory_max(void)
{
@@ -178,6 +179,11 @@ int drmem_update_dt(void)
if (!memory)
return -1;
+ /*
+ * Set in_drmem_update to prevent the notifier callback to process the
+ * DT property back since the change is coming from the LMB tree.
+ */
+ in_drmem_update = true;
prop = of_find_property(memory, "ibm,dynamic-memory", NULL);
if (prop) {
rc = drmem_update_dt_v1(memory, prop);
@@ -186,6 +192,7 @@ int drmem_update_dt(void)
if (prop)
rc = drmem_update_dt_v2(memory, prop);
}
+ in_drmem_update = false;
of_node_put(memory);
return rc;
@@ -307,6 +314,45 @@ int __init walk_drmem_lmbs_early(unsigned long node, void *data,
return ret;
}
+/*
+ * Update the LMB associativity index.
+ */
+static int update_lmb(struct drmem_lmb *updated_lmb,
+ __maybe_unused const __be32 **usm,
+ __maybe_unused void *data)
+{
+ struct drmem_lmb *lmb;
+
+ for_each_drmem_lmb(lmb) {
+ if (lmb->drc_index != updated_lmb->drc_index)
+ continue;
+
+ lmb->aa_index = updated_lmb->aa_index;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Update the LMB associativity index.
+ *
+ * This needs to be called when the hypervisor is updating the
+ * dynamic-reconfiguration-memory node property.
+ */
+void drmem_update_lmbs(struct property *prop)
+{
+ /*
+ * Don't update the LMBs if triggered by the update done in
+ * drmem_update_dt(), the LMB values have been used to the update the DT
+ * property in that case.
+ */
+ if (in_drmem_update)
+ return;
+ if (!strcmp(prop->name, "ibm,dynamic-memory"))
+ __walk_drmem_v1_lmbs(prop->value, NULL, NULL, update_lmb);
+ else if (!strcmp(prop->name, "ibm,dynamic-memory-v2"))
+ __walk_drmem_v2_lmbs(prop->value, NULL, NULL, update_lmb);
+}
#endif
static int init_drmem_lmb_size(struct device_node *dn)
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 7dac910c0b21..dd1cabc2ea0f 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -180,7 +180,7 @@ static inline void mmu_mark_rodata_ro(void) { }
void __init mmu_mapin_immr(void);
#endif
-#ifdef CONFIG_PPC_DEBUG_WX
+#ifdef CONFIG_DEBUG_WX
void ptdump_check_wx(void);
#else
static inline void ptdump_check_wx(void) { }
diff --git a/arch/powerpc/mm/nohash/tlb_low.S b/arch/powerpc/mm/nohash/tlb_low.S
index 4613bf8e9aae..5add4a51e51f 100644
--- a/arch/powerpc/mm/nohash/tlb_low.S
+++ b/arch/powerpc/mm/nohash/tlb_low.S
@@ -199,7 +199,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_476_DD2)
* Touch enough instruction cache lines to ensure cache hits
*/
1: mflr r9
- bl 2f
+ bcl 20,31,$+4
2: mflr r6
li r7,32
PPC_ICBT(0,R6,R7) /* touch next cache line */
@@ -414,7 +414,7 @@ _GLOBAL(loadcam_multi)
* Set up temporary TLB entry that is the same as what we're
* running from, but in AS=1.
*/
- bl 1f
+ bcl 20,31,$+4
1: mflr r6
tlbsx 0,r8
mfspr r6,SPRN_MAS1
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index f2bf98bdcea2..6f14c8fb6359 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -40,9 +40,6 @@ static int numa_enabled = 1;
static char *cmdline __initdata;
-static int numa_debug;
-#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
-
int numa_cpu_lookup_table[NR_CPUS];
cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
struct pglist_data *node_data[MAX_NUMNODES];
@@ -51,14 +48,22 @@ EXPORT_SYMBOL(numa_cpu_lookup_table);
EXPORT_SYMBOL(node_to_cpumask_map);
EXPORT_SYMBOL(node_data);
-static int min_common_depth;
+static int primary_domain_index;
static int n_mem_addr_cells, n_mem_size_cells;
-static int form1_affinity;
+
+#define FORM0_AFFINITY 0
+#define FORM1_AFFINITY 1
+#define FORM2_AFFINITY 2
+static int affinity_form;
#define MAX_DISTANCE_REF_POINTS 4
static int distance_ref_points_depth;
static const __be32 *distance_ref_points;
static int distance_lookup_table[MAX_NUMNODES][MAX_DISTANCE_REF_POINTS];
+static int numa_distance_table[MAX_NUMNODES][MAX_NUMNODES] = {
+ [0 ... MAX_NUMNODES - 1] = { [0 ... MAX_NUMNODES - 1] = -1 }
+};
+static int numa_id_index_table[MAX_NUMNODES] = { [0 ... MAX_NUMNODES - 1] = NUMA_NO_NODE };
/*
* Allocate node_to_cpumask_map based on number of available nodes
@@ -79,7 +84,7 @@ static void __init setup_node_to_cpumask_map(void)
alloc_bootmem_cpumask_var(&node_to_cpumask_map[node]);
/* cpumask_of_node() will now work */
- dbg("Node to cpumask map for %u nodes\n", nr_node_ids);
+ pr_debug("Node to cpumask map for %u nodes\n", nr_node_ids);
}
static int __init fake_numa_create_new_node(unsigned long end_pfn,
@@ -123,7 +128,7 @@ static int __init fake_numa_create_new_node(unsigned long end_pfn,
cmdline = p;
fake_nid++;
*nid = fake_nid;
- dbg("created new fake_node with id %d\n", fake_nid);
+ pr_debug("created new fake_node with id %d\n", fake_nid);
return 1;
}
return 0;
@@ -137,33 +142,79 @@ static void reset_numa_cpu_lookup_table(void)
numa_cpu_lookup_table[cpu] = -1;
}
-static void map_cpu_to_node(int cpu, int node)
+void map_cpu_to_node(int cpu, int node)
{
update_numa_cpu_lookup_table(cpu, node);
- dbg("adding cpu %d to node %d\n", cpu, node);
-
- if (!(cpumask_test_cpu(cpu, node_to_cpumask_map[node])))
+ if (!(cpumask_test_cpu(cpu, node_to_cpumask_map[node]))) {
+ pr_debug("adding cpu %d to node %d\n", cpu, node);
cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
+ }
}
#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PPC_SPLPAR)
-static void unmap_cpu_from_node(unsigned long cpu)
+void unmap_cpu_from_node(unsigned long cpu)
{
int node = numa_cpu_lookup_table[cpu];
- dbg("removing cpu %lu from node %d\n", cpu, node);
-
if (cpumask_test_cpu(cpu, node_to_cpumask_map[node])) {
cpumask_clear_cpu(cpu, node_to_cpumask_map[node]);
+ pr_debug("removing cpu %lu from node %d\n", cpu, node);
} else {
- printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n",
- cpu, node);
+ pr_warn("Warning: cpu %lu not found in node %d\n", cpu, node);
}
}
#endif /* CONFIG_HOTPLUG_CPU || CONFIG_PPC_SPLPAR */
-int cpu_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
+static int __associativity_to_nid(const __be32 *associativity,
+ int max_array_sz)
+{
+ int nid;
+ /*
+ * primary_domain_index is 1 based array index.
+ */
+ int index = primary_domain_index - 1;
+
+ if (!numa_enabled || index >= max_array_sz)
+ return NUMA_NO_NODE;
+
+ nid = of_read_number(&associativity[index], 1);
+
+ /* POWER4 LPAR uses 0xffff as invalid node */
+ if (nid == 0xffff || nid >= nr_node_ids)
+ nid = NUMA_NO_NODE;
+ return nid;
+}
+/*
+ * Returns nid in the range [0..nr_node_ids], or -1 if no useful NUMA
+ * info is found.
+ */
+static int associativity_to_nid(const __be32 *associativity)
+{
+ int array_sz = of_read_number(associativity, 1);
+
+ /* Skip the first element in the associativity array */
+ return __associativity_to_nid((associativity + 1), array_sz);
+}
+
+static int __cpu_form2_relative_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
+{
+ int dist;
+ int node1, node2;
+
+ node1 = associativity_to_nid(cpu1_assoc);
+ node2 = associativity_to_nid(cpu2_assoc);
+
+ dist = numa_distance_table[node1][node2];
+ if (dist <= LOCAL_DISTANCE)
+ return 0;
+ else if (dist <= REMOTE_DISTANCE)
+ return 1;
+ else
+ return 2;
+}
+
+static int __cpu_form1_relative_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
{
int dist = 0;
@@ -179,6 +230,15 @@ int cpu_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
return dist;
}
+int cpu_relative_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
+{
+ /* We should not get called with FORM0 */
+ VM_WARN_ON(affinity_form == FORM0_AFFINITY);
+ if (affinity_form == FORM1_AFFINITY)
+ return __cpu_form1_relative_distance(cpu1_assoc, cpu2_assoc);
+ return __cpu_form2_relative_distance(cpu1_assoc, cpu2_assoc);
+}
+
/* must hold reference to node during call */
static const __be32 *of_get_associativity(struct device_node *dev)
{
@@ -190,7 +250,9 @@ int __node_distance(int a, int b)
int i;
int distance = LOCAL_DISTANCE;
- if (!form1_affinity)
+ if (affinity_form == FORM2_AFFINITY)
+ return numa_distance_table[a][b];
+ else if (affinity_form == FORM0_AFFINITY)
return ((a == b) ? LOCAL_DISTANCE : REMOTE_DISTANCE);
for (i = 0; i < distance_ref_points_depth; i++) {
@@ -205,52 +267,6 @@ int __node_distance(int a, int b)
}
EXPORT_SYMBOL(__node_distance);
-static void initialize_distance_lookup_table(int nid,
- const __be32 *associativity)
-{
- int i;
-
- if (!form1_affinity)
- return;
-
- for (i = 0; i < distance_ref_points_depth; i++) {
- const __be32 *entry;
-
- entry = &associativity[be32_to_cpu(distance_ref_points[i]) - 1];
- distance_lookup_table[nid][i] = of_read_number(entry, 1);
- }
-}
-
-/*
- * Returns nid in the range [0..nr_node_ids], or -1 if no useful NUMA
- * info is found.
- */
-static int associativity_to_nid(const __be32 *associativity)
-{
- int nid = NUMA_NO_NODE;
-
- if (!numa_enabled)
- goto out;
-
- if (of_read_number(associativity, 1) >= min_common_depth)
- nid = of_read_number(&associativity[min_common_depth], 1);
-
- /* POWER4 LPAR uses 0xffff as invalid node */
- if (nid == 0xffff || nid >= nr_node_ids)
- nid = NUMA_NO_NODE;
-
- if (nid > 0 &&
- of_read_number(associativity, 1) >= distance_ref_points_depth) {
- /*
- * Skip the length field and send start of associativity array
- */
- initialize_distance_lookup_table(nid, associativity + 1);
- }
-
-out:
- return nid;
-}
-
/* Returns the nid associated with the given device tree node,
* or -1 if not found.
*/
@@ -284,11 +300,159 @@ int of_node_to_nid(struct device_node *device)
}
EXPORT_SYMBOL(of_node_to_nid);
-static int __init find_min_common_depth(void)
+static void __initialize_form1_numa_distance(const __be32 *associativity,
+ int max_array_sz)
+{
+ int i, nid;
+
+ if (affinity_form != FORM1_AFFINITY)
+ return;
+
+ nid = __associativity_to_nid(associativity, max_array_sz);
+ if (nid != NUMA_NO_NODE) {
+ for (i = 0; i < distance_ref_points_depth; i++) {
+ const __be32 *entry;
+ int index = be32_to_cpu(distance_ref_points[i]) - 1;
+
+ /*
+ * broken hierarchy, return with broken distance table
+ */
+ if (WARN(index >= max_array_sz, "Broken ibm,associativity property"))
+ return;
+
+ entry = &associativity[index];
+ distance_lookup_table[nid][i] = of_read_number(entry, 1);
+ }
+ }
+}
+
+static void initialize_form1_numa_distance(const __be32 *associativity)
+{
+ int array_sz;
+
+ array_sz = of_read_number(associativity, 1);
+ /* Skip the first element in the associativity array */
+ __initialize_form1_numa_distance(associativity + 1, array_sz);
+}
+
+/*
+ * Used to update distance information w.r.t newly added node.
+ */
+void update_numa_distance(struct device_node *node)
{
- int depth;
+ int nid;
+
+ if (affinity_form == FORM0_AFFINITY)
+ return;
+ else if (affinity_form == FORM1_AFFINITY) {
+ const __be32 *associativity;
+
+ associativity = of_get_associativity(node);
+ if (!associativity)
+ return;
+
+ initialize_form1_numa_distance(associativity);
+ return;
+ }
+
+ /* FORM2 affinity */
+ nid = of_node_to_nid_single(node);
+ if (nid == NUMA_NO_NODE)
+ return;
+
+ /*
+ * With FORM2 we expect NUMA distance of all possible NUMA
+ * nodes to be provided during boot.
+ */
+ WARN(numa_distance_table[nid][nid] == -1,
+ "NUMA distance details for node %d not provided\n", nid);
+}
+
+/*
+ * ibm,numa-lookup-index-table= {N, domainid1, domainid2, ..... domainidN}
+ * ibm,numa-distance-table = { N, 1, 2, 4, 5, 1, 6, .... N elements}
+ */
+static void initialize_form2_numa_distance_lookup_table(void)
+{
+ int i, j;
+ struct device_node *root;
+ const __u8 *numa_dist_table;
+ const __be32 *numa_lookup_index;
+ int numa_dist_table_length;
+ int max_numa_index, distance_index;
+
+ if (firmware_has_feature(FW_FEATURE_OPAL))
+ root = of_find_node_by_path("/ibm,opal");
+ else
+ root = of_find_node_by_path("/rtas");
+ if (!root)
+ root = of_find_node_by_path("/");
+
+ numa_lookup_index = of_get_property(root, "ibm,numa-lookup-index-table", NULL);
+ max_numa_index = of_read_number(&numa_lookup_index[0], 1);
+
+ /* first element of the array is the size and is encode-int */
+ numa_dist_table = of_get_property(root, "ibm,numa-distance-table", NULL);
+ numa_dist_table_length = of_read_number((const __be32 *)&numa_dist_table[0], 1);
+ /* Skip the size which is encoded int */
+ numa_dist_table += sizeof(__be32);
+
+ pr_debug("numa_dist_table_len = %d, numa_dist_indexes_len = %d\n",
+ numa_dist_table_length, max_numa_index);
+
+ for (i = 0; i < max_numa_index; i++)
+ /* +1 skip the max_numa_index in the property */
+ numa_id_index_table[i] = of_read_number(&numa_lookup_index[i + 1], 1);
+
+
+ if (numa_dist_table_length != max_numa_index * max_numa_index) {
+ WARN(1, "Wrong NUMA distance information\n");
+ /* consider everybody else just remote. */
+ for (i = 0; i < max_numa_index; i++) {
+ for (j = 0; j < max_numa_index; j++) {
+ int nodeA = numa_id_index_table[i];
+ int nodeB = numa_id_index_table[j];
+
+ if (nodeA == nodeB)
+ numa_distance_table[nodeA][nodeB] = LOCAL_DISTANCE;
+ else
+ numa_distance_table[nodeA][nodeB] = REMOTE_DISTANCE;
+ }
+ }
+ }
+
+ distance_index = 0;
+ for (i = 0; i < max_numa_index; i++) {
+ for (j = 0; j < max_numa_index; j++) {
+ int nodeA = numa_id_index_table[i];
+ int nodeB = numa_id_index_table[j];
+
+ numa_distance_table[nodeA][nodeB] = numa_dist_table[distance_index++];
+ pr_debug("dist[%d][%d]=%d ", nodeA, nodeB, numa_distance_table[nodeA][nodeB]);
+ }
+ }
+ of_node_put(root);
+}
+
+static int __init find_primary_domain_index(void)
+{
+ int index;
struct device_node *root;
+ /*
+ * Check for which form of affinity.
+ */
+ if (firmware_has_feature(FW_FEATURE_OPAL)) {
+ affinity_form = FORM1_AFFINITY;
+ } else if (firmware_has_feature(FW_FEATURE_FORM2_AFFINITY)) {
+ pr_debug("Using form 2 affinity\n");
+ affinity_form = FORM2_AFFINITY;
+ } else if (firmware_has_feature(FW_FEATURE_FORM1_AFFINITY)) {
+ pr_debug("Using form 1 affinity\n");
+ affinity_form = FORM1_AFFINITY;
+ } else
+ affinity_form = FORM0_AFFINITY;
+
if (firmware_has_feature(FW_FEATURE_OPAL))
root = of_find_node_by_path("/ibm,opal");
else
@@ -313,42 +477,37 @@ static int __init find_min_common_depth(void)
&distance_ref_points_depth);
if (!distance_ref_points) {
- dbg("NUMA: ibm,associativity-reference-points not found.\n");
+ pr_debug("ibm,associativity-reference-points not found.\n");
goto err;
}
distance_ref_points_depth /= sizeof(int);
-
- if (firmware_has_feature(FW_FEATURE_OPAL) ||
- firmware_has_feature(FW_FEATURE_TYPE1_AFFINITY)) {
- dbg("Using form 1 affinity\n");
- form1_affinity = 1;
- }
-
- if (form1_affinity) {
- depth = of_read_number(distance_ref_points, 1);
- } else {
+ if (affinity_form == FORM0_AFFINITY) {
if (distance_ref_points_depth < 2) {
- printk(KERN_WARNING "NUMA: "
- "short ibm,associativity-reference-points\n");
+ pr_warn("short ibm,associativity-reference-points\n");
goto err;
}
- depth = of_read_number(&distance_ref_points[1], 1);
+ index = of_read_number(&distance_ref_points[1], 1);
+ } else {
+ /*
+ * Both FORM1 and FORM2 affinity find the primary domain details
+ * at the same offset.
+ */
+ index = of_read_number(distance_ref_points, 1);
}
-
/*
* Warn and cap if the hardware supports more than
* MAX_DISTANCE_REF_POINTS domains.
*/
if (distance_ref_points_depth > MAX_DISTANCE_REF_POINTS) {
- printk(KERN_WARNING "NUMA: distance array capped at "
- "%d entries\n", MAX_DISTANCE_REF_POINTS);
+ pr_warn("distance array capped at %d entries\n",
+ MAX_DISTANCE_REF_POINTS);
distance_ref_points_depth = MAX_DISTANCE_REF_POINTS;
}
of_node_put(root);
- return depth;
+ return index;
err:
of_node_put(root);
@@ -426,6 +585,38 @@ static int of_get_assoc_arrays(struct assoc_arrays *aa)
return 0;
}
+static int get_nid_and_numa_distance(struct drmem_lmb *lmb)
+{
+ struct assoc_arrays aa = { .arrays = NULL };
+ int default_nid = NUMA_NO_NODE;
+ int nid = default_nid;
+ int rc, index;
+
+ if ((primary_domain_index < 0) || !numa_enabled)
+ return default_nid;
+
+ rc = of_get_assoc_arrays(&aa);
+ if (rc)
+ return default_nid;
+
+ if (primary_domain_index <= aa.array_sz &&
+ !(lmb->flags & DRCONF_MEM_AI_INVALID) && lmb->aa_index < aa.n_arrays) {
+ const __be32 *associativity;
+
+ index = lmb->aa_index * aa.array_sz;
+ associativity = &aa.arrays[index];
+ nid = __associativity_to_nid(associativity, aa.array_sz);
+ if (nid > 0 && affinity_form == FORM1_AFFINITY) {
+ /*
+ * lookup array associativity entries have
+ * no length of the array as the first element.
+ */
+ __initialize_form1_numa_distance(associativity, aa.array_sz);
+ }
+ }
+ return nid;
+}
+
/*
* This is like of_node_to_nid_single() for memory represented in the
* ibm,dynamic-reconfiguration-memory node.
@@ -437,35 +628,28 @@ int of_drconf_to_nid_single(struct drmem_lmb *lmb)
int nid = default_nid;
int rc, index;
- if ((min_common_depth < 0) || !numa_enabled)
+ if ((primary_domain_index < 0) || !numa_enabled)
return default_nid;
rc = of_get_assoc_arrays(&aa);
if (rc)
return default_nid;
- if (min_common_depth <= aa.array_sz &&
+ if (primary_domain_index <= aa.array_sz &&
!(lmb->flags & DRCONF_MEM_AI_INVALID) && lmb->aa_index < aa.n_arrays) {
- index = lmb->aa_index * aa.array_sz + min_common_depth - 1;
- nid = of_read_number(&aa.arrays[index], 1);
-
- if (nid == 0xffff || nid >= nr_node_ids)
- nid = default_nid;
+ const __be32 *associativity;
- if (nid > 0) {
- index = lmb->aa_index * aa.array_sz;
- initialize_distance_lookup_table(nid,
- &aa.arrays[index]);
- }
+ index = lmb->aa_index * aa.array_sz;
+ associativity = &aa.arrays[index];
+ nid = __associativity_to_nid(associativity, aa.array_sz);
}
-
return nid;
}
#ifdef CONFIG_PPC_SPLPAR
-static int vphn_get_nid(long lcpu)
+
+static int __vphn_get_associativity(long lcpu, __be32 *associativity)
{
- __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
long rc, hwid;
/*
@@ -485,12 +669,30 @@ static int vphn_get_nid(long lcpu)
rc = hcall_vphn(hwid, VPHN_FLAG_VCPU, associativity);
if (rc == H_SUCCESS)
- return associativity_to_nid(associativity);
+ return 0;
}
+ return -1;
+}
+
+static int vphn_get_nid(long lcpu)
+{
+ __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
+
+
+ if (!__vphn_get_associativity(lcpu, associativity))
+ return associativity_to_nid(associativity);
+
return NUMA_NO_NODE;
+
}
#else
+
+static int __vphn_get_associativity(long lcpu, __be32 *associativity)
+{
+ return -1;
+}
+
static int vphn_get_nid(long unused)
{
return NUMA_NO_NODE;
@@ -598,9 +800,6 @@ static int ppc_numa_cpu_prepare(unsigned int cpu)
static int ppc_numa_cpu_dead(unsigned int cpu)
{
-#ifdef CONFIG_HOTPLUG_CPU
- unmap_cpu_from_node(cpu);
-#endif
return 0;
}
@@ -685,7 +884,7 @@ static int __init numa_setup_drmem_lmb(struct drmem_lmb *lmb,
size = read_n_cells(n_mem_size_cells, usm);
}
- nid = of_drconf_to_nid_single(lmb);
+ nid = get_nid_and_numa_distance(lmb);
fake_numa_create_new_node(((base + size) >> PAGE_SHIFT),
&nid);
node_set_online(nid);
@@ -702,24 +901,31 @@ static int __init parse_numa_properties(void)
struct device_node *memory;
int default_nid = 0;
unsigned long i;
+ const __be32 *associativity;
if (numa_enabled == 0) {
- printk(KERN_WARNING "NUMA disabled by user\n");
+ pr_warn("disabled by user\n");
return -1;
}
- min_common_depth = find_min_common_depth();
+ primary_domain_index = find_primary_domain_index();
- if (min_common_depth < 0) {
+ if (primary_domain_index < 0) {
/*
- * if we fail to parse min_common_depth from device tree
+ * if we fail to parse primary_domain_index from device tree
* mark the numa disabled, boot with numa disabled.
*/
numa_enabled = false;
- return min_common_depth;
+ return primary_domain_index;
}
- dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth);
+ pr_debug("associativity depth for CPU/Memory: %d\n", primary_domain_index);
+
+ /*
+ * If it is FORM2 initialize the distance table here.
+ */
+ if (affinity_form == FORM2_AFFINITY)
+ initialize_form2_numa_distance_lookup_table();
/*
* Even though we connect cpus to numa domains later in SMP
@@ -727,18 +933,30 @@ static int __init parse_numa_properties(void)
* each node to be onlined must have NODE_DATA etc backing it.
*/
for_each_present_cpu(i) {
+ __be32 vphn_assoc[VPHN_ASSOC_BUFSIZE];
struct device_node *cpu;
- int nid = vphn_get_nid(i);
+ int nid = NUMA_NO_NODE;
- /*
- * Don't fall back to default_nid yet -- we will plug
- * cpus into nodes once the memory scan has discovered
- * the topology.
- */
- if (nid == NUMA_NO_NODE) {
+ memset(vphn_assoc, 0, VPHN_ASSOC_BUFSIZE * sizeof(__be32));
+
+ if (__vphn_get_associativity(i, vphn_assoc) == 0) {
+ nid = associativity_to_nid(vphn_assoc);
+ initialize_form1_numa_distance(vphn_assoc);
+ } else {
+
+ /*
+ * Don't fall back to default_nid yet -- we will plug
+ * cpus into nodes once the memory scan has discovered
+ * the topology.
+ */
cpu = of_get_cpu_node(i, NULL);
BUG_ON(!cpu);
- nid = of_node_to_nid_single(cpu);
+
+ associativity = of_get_associativity(cpu);
+ if (associativity) {
+ nid = associativity_to_nid(associativity);
+ initialize_form1_numa_distance(associativity);
+ }
of_node_put(cpu);
}
@@ -774,8 +992,11 @@ new_range:
* have associativity properties. If none, then
* everything goes to default_nid.
*/
- nid = of_node_to_nid_single(memory);
- if (nid < 0)
+ associativity = of_get_associativity(memory);
+ if (associativity) {
+ nid = associativity_to_nid(associativity);
+ initialize_form1_numa_distance(associativity);
+ } else
nid = default_nid;
fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid);
@@ -811,10 +1032,8 @@ static void __init setup_nonnuma(void)
unsigned int nid = 0;
int i;
- printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
- top_of_ram, total_ram);
- printk(KERN_DEBUG "Memory hole size: %ldMB\n",
- (top_of_ram - total_ram) >> 20);
+ pr_debug("Top of RAM: 0x%lx, Total RAM: 0x%lx\n", top_of_ram, total_ram);
+ pr_debug("Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20);
for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
fake_numa_create_new_node(end_pfn, &nid);
@@ -893,7 +1112,7 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
static void __init find_possible_nodes(void)
{
struct device_node *rtas;
- const __be32 *domains;
+ const __be32 *domains = NULL;
int prop_length, max_nodes;
u32 i;
@@ -909,9 +1128,14 @@ static void __init find_possible_nodes(void)
* it doesn't exist, then fallback on ibm,max-associativity-domains.
* Current denotes what the platform can support compared to max
* which denotes what the Hypervisor can support.
+ *
+ * If the LPAR is migratable, new nodes might be activated after a LPM,
+ * so we should consider the max number in that case.
*/
- domains = of_get_property(rtas, "ibm,current-associativity-domains",
- &prop_length);
+ if (!of_get_property(of_root, "ibm,migratable-partition", NULL))
+ domains = of_get_property(rtas,
+ "ibm,current-associativity-domains",
+ &prop_length);
if (!domains) {
domains = of_get_property(rtas, "ibm,max-associativity-domains",
&prop_length);
@@ -919,14 +1143,16 @@ static void __init find_possible_nodes(void)
goto out;
}
- max_nodes = of_read_number(&domains[min_common_depth], 1);
+ max_nodes = of_read_number(&domains[primary_domain_index], 1);
+ pr_info("Partition configured for %d NUMA nodes.\n", max_nodes);
+
for (i = 0; i < max_nodes; i++) {
if (!node_possible(i))
node_set(i, node_possible_map);
}
prop_length /= sizeof(int);
- if (prop_length > min_common_depth + 2)
+ if (prop_length > primary_domain_index + 2)
coregroup_enabled = 1;
out:
@@ -1014,9 +1240,6 @@ static int __init early_numa(char *p)
if (strstr(p, "off"))
numa_enabled = 0;
- if (strstr(p, "debug"))
- numa_debug = 1;
-
p = strstr(p, "fake=");
if (p)
cmdline = p + strlen("fake=");
@@ -1179,7 +1402,7 @@ static long vphn_get_associativity(unsigned long cpu,
switch (rc) {
case H_SUCCESS:
- dbg("VPHN hcall succeeded. Reset polling...\n");
+ pr_debug("VPHN hcall succeeded. Reset polling...\n");
goto out;
case H_FUNCTION:
@@ -1259,7 +1482,7 @@ int cpu_to_coregroup_id(int cpu)
goto out;
index = of_read_number(associativity, 1);
- if (index > min_common_depth + 1)
+ if (index > primary_domain_index + 1)
return of_read_number(&associativity[index - 1], 1);
out:
diff --git a/arch/powerpc/mm/ptdump/8xx.c b/arch/powerpc/mm/ptdump/8xx.c
index 86da2a669680..fac932eb8f9a 100644
--- a/arch/powerpc/mm/ptdump/8xx.c
+++ b/arch/powerpc/mm/ptdump/8xx.c
@@ -75,8 +75,10 @@ static const struct flag_info flag_array[] = {
};
struct pgtable_level pg_level[5] = {
- {
- }, { /* pgd */
+ { /* pgd */
+ .flag = flag_array,
+ .num = ARRAY_SIZE(flag_array),
+ }, { /* p4d */
.flag = flag_array,
.num = ARRAY_SIZE(flag_array),
}, { /* pud */
diff --git a/arch/powerpc/mm/ptdump/Makefile b/arch/powerpc/mm/ptdump/Makefile
index 712762be3cb1..4050cbb55acf 100644
--- a/arch/powerpc/mm/ptdump/Makefile
+++ b/arch/powerpc/mm/ptdump/Makefile
@@ -5,5 +5,10 @@ obj-y += ptdump.o
obj-$(CONFIG_4xx) += shared.o
obj-$(CONFIG_PPC_8xx) += 8xx.o
obj-$(CONFIG_PPC_BOOK3E_MMU) += shared.o
-obj-$(CONFIG_PPC_BOOK3S_32) += shared.o bats.o segment_regs.o
-obj-$(CONFIG_PPC_BOOK3S_64) += book3s64.o hashpagetable.o
+obj-$(CONFIG_PPC_BOOK3S_32) += shared.o
+obj-$(CONFIG_PPC_BOOK3S_64) += book3s64.o
+
+ifdef CONFIG_PTDUMP_DEBUGFS
+obj-$(CONFIG_PPC_BOOK3S_32) += bats.o segment_regs.o
+obj-$(CONFIG_PPC_BOOK3S_64) += hashpagetable.o
+endif
diff --git a/arch/powerpc/mm/ptdump/bats.c b/arch/powerpc/mm/ptdump/bats.c
index c4c628b03cf8..820c119013e4 100644
--- a/arch/powerpc/mm/ptdump/bats.c
+++ b/arch/powerpc/mm/ptdump/bats.c
@@ -7,7 +7,7 @@
*/
#include <linux/pgtable.h>
-#include <asm/debugfs.h>
+#include <linux/debugfs.h>
#include <asm/cpu_has_feature.h>
#include "ptdump.h"
@@ -57,7 +57,7 @@ static void bat_show_603(struct seq_file *m, int idx, u32 lower, u32 upper, bool
#define BAT_SHOW_603(_m, _n, _l, _u, _d) bat_show_603(_m, _n, mfspr(_l), mfspr(_u), _d)
-static int bats_show_603(struct seq_file *m, void *v)
+static int bats_show(struct seq_file *m, void *v)
{
seq_puts(m, "---[ Instruction Block Address Translation ]---\n");
@@ -88,22 +88,12 @@ static int bats_show_603(struct seq_file *m, void *v)
return 0;
}
-static int bats_open(struct inode *inode, struct file *file)
-{
- return single_open(file, bats_show_603, NULL);
-}
-
-static const struct file_operations bats_fops = {
- .open = bats_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(bats);
static int __init bats_init(void)
{
debugfs_create_file("block_address_translation", 0400,
- powerpc_debugfs_root, NULL, &bats_fops);
+ arch_debugfs_dir, NULL, &bats_fops);
return 0;
}
device_initcall(bats_init);
diff --git a/arch/powerpc/mm/ptdump/book3s64.c b/arch/powerpc/mm/ptdump/book3s64.c
index 14f73868db66..5ad92d9dc5d1 100644
--- a/arch/powerpc/mm/ptdump/book3s64.c
+++ b/arch/powerpc/mm/ptdump/book3s64.c
@@ -103,8 +103,10 @@ static const struct flag_info flag_array[] = {
};
struct pgtable_level pg_level[5] = {
- {
- }, { /* pgd */
+ { /* pgd */
+ .flag = flag_array,
+ .num = ARRAY_SIZE(flag_array),
+ }, { /* p4d */
.flag = flag_array,
.num = ARRAY_SIZE(flag_array),
}, { /* pud */
diff --git a/arch/powerpc/mm/ptdump/hashpagetable.c b/arch/powerpc/mm/ptdump/hashpagetable.c
index ad6df9a2e7c8..c7f824d294b2 100644
--- a/arch/powerpc/mm/ptdump/hashpagetable.c
+++ b/arch/powerpc/mm/ptdump/hashpagetable.c
@@ -526,17 +526,7 @@ static int ptdump_show(struct seq_file *m, void *v)
return 0;
}
-static int ptdump_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ptdump_show, NULL);
-}
-
-static const struct file_operations ptdump_fops = {
- .open = ptdump_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ptdump);
static int ptdump_init(void)
{
diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
index 5062c58b1e5b..bf251191e78d 100644
--- a/arch/powerpc/mm/ptdump/ptdump.c
+++ b/arch/powerpc/mm/ptdump/ptdump.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/highmem.h>
+#include <linux/ptdump.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <asm/fixmap.h>
@@ -54,11 +55,12 @@
*
*/
struct pg_state {
+ struct ptdump_state ptdump;
struct seq_file *seq;
const struct addr_marker *marker;
unsigned long start_address;
unsigned long start_pa;
- unsigned int level;
+ int level;
u64 current_flags;
bool check_wx;
unsigned long wx_pages;
@@ -102,6 +104,11 @@ static struct addr_marker address_markers[] = {
{ -1, NULL },
};
+static struct ptdump_range ptdump_range[] __ro_after_init = {
+ {TASK_SIZE_MAX, ~0UL},
+ {0, 0}
+};
+
#define pt_dump_seq_printf(m, fmt, args...) \
({ \
if (m) \
@@ -188,10 +195,9 @@ static void note_prot_wx(struct pg_state *st, unsigned long addr)
st->wx_pages += (addr - st->start_address) / PAGE_SIZE;
}
-static void note_page_update_state(struct pg_state *st, unsigned long addr,
- unsigned int level, u64 val, unsigned long page_size)
+static void note_page_update_state(struct pg_state *st, unsigned long addr, int level, u64 val)
{
- u64 flag = val & pg_level[level].mask;
+ u64 flag = level >= 0 ? val & pg_level[level].mask : 0;
u64 pa = val & PTE_RPN_MASK;
st->level = level;
@@ -205,15 +211,15 @@ static void note_page_update_state(struct pg_state *st, unsigned long addr,
}
}
-static void note_page(struct pg_state *st, unsigned long addr,
- unsigned int level, u64 val, unsigned long page_size)
+static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, u64 val)
{
- u64 flag = val & pg_level[level].mask;
+ u64 flag = level >= 0 ? val & pg_level[level].mask : 0;
+ struct pg_state *st = container_of(pt_st, struct pg_state, ptdump);
/* At first no level is set */
- if (!st->level) {
+ if (st->level == -1) {
pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
- note_page_update_state(st, addr, level, val, page_size);
+ note_page_update_state(st, addr, level, val);
/*
* Dump the section of virtual memory when:
* - the PTE flags from one entry to the next differs.
@@ -242,95 +248,7 @@ static void note_page(struct pg_state *st, unsigned long addr,
* Address indicates we have passed the end of the
* current section of virtual memory
*/
- note_page_update_state(st, addr, level, val, page_size);
- }
-}
-
-static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
-{
- pte_t *pte = pte_offset_kernel(pmd, 0);
- unsigned long addr;
- unsigned int i;
-
- for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
- addr = start + i * PAGE_SIZE;
- note_page(st, addr, 4, pte_val(*pte), PAGE_SIZE);
-
- }
-}
-
-static void walk_hugepd(struct pg_state *st, hugepd_t *phpd, unsigned long start,
- int pdshift, int level)
-{
-#ifdef CONFIG_ARCH_HAS_HUGEPD
- unsigned int i;
- int shift = hugepd_shift(*phpd);
- int ptrs_per_hpd = pdshift - shift > 0 ? 1 << (pdshift - shift) : 1;
-
- if (start & ((1 << shift) - 1))
- return;
-
- for (i = 0; i < ptrs_per_hpd; i++) {
- unsigned long addr = start + (i << shift);
- pte_t *pte = hugepte_offset(*phpd, addr, pdshift);
-
- note_page(st, addr, level + 1, pte_val(*pte), 1 << shift);
- }
-#endif
-}
-
-static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
-{
- pmd_t *pmd = pmd_offset(pud, 0);
- unsigned long addr;
- unsigned int i;
-
- for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
- addr = start + i * PMD_SIZE;
- if (!pmd_none(*pmd) && !pmd_is_leaf(*pmd))
- /* pmd exists */
- walk_pte(st, pmd, addr);
- else
- note_page(st, addr, 3, pmd_val(*pmd), PMD_SIZE);
- }
-}
-
-static void walk_pud(struct pg_state *st, p4d_t *p4d, unsigned long start)
-{
- pud_t *pud = pud_offset(p4d, 0);
- unsigned long addr;
- unsigned int i;
-
- for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
- addr = start + i * PUD_SIZE;
- if (!pud_none(*pud) && !pud_is_leaf(*pud))
- /* pud exists */
- walk_pmd(st, pud, addr);
- else
- note_page(st, addr, 2, pud_val(*pud), PUD_SIZE);
- }
-}
-
-static void walk_pagetables(struct pg_state *st)
-{
- unsigned int i;
- unsigned long addr = st->start_address & PGDIR_MASK;
- pgd_t *pgd = pgd_offset_k(addr);
-
- /*
- * Traverse the linux pagetable structure and dump pages that are in
- * the hash pagetable.
- */
- for (i = pgd_index(addr); i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) {
- p4d_t *p4d = p4d_offset(pgd, 0);
-
- if (p4d_none(*p4d) || p4d_is_leaf(*p4d))
- note_page(st, addr, 1, p4d_val(*p4d), PGDIR_SIZE);
- else if (is_hugepd(__hugepd(p4d_val(*p4d))))
- walk_hugepd(st, (hugepd_t *)p4d, addr, PGDIR_SHIFT, 1);
- else
- /* p4d exists */
- walk_pud(st, p4d, addr);
+ note_page_update_state(st, addr, level, val);
}
}
@@ -383,32 +301,19 @@ static int ptdump_show(struct seq_file *m, void *v)
struct pg_state st = {
.seq = m,
.marker = address_markers,
- .start_address = IS_ENABLED(CONFIG_PPC64) ? PAGE_OFFSET : TASK_SIZE,
+ .level = -1,
+ .ptdump = {
+ .note_page = note_page,
+ .range = ptdump_range,
+ }
};
-#ifdef CONFIG_PPC64
- if (!radix_enabled())
- st.start_address = KERN_VIRT_START;
-#endif
-
/* Traverse kernel page tables */
- walk_pagetables(&st);
- note_page(&st, 0, 0, 0, 0);
+ ptdump_walk_pgd(&st.ptdump, &init_mm, NULL);
return 0;
}
-
-static int ptdump_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ptdump_show, NULL);
-}
-
-static const struct file_operations ptdump_fops = {
- .open = ptdump_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ptdump);
static void build_pgtable_complete_mask(void)
{
@@ -420,22 +325,24 @@ static void build_pgtable_complete_mask(void)
pg_level[i].mask |= pg_level[i].flag[j].mask;
}
-#ifdef CONFIG_PPC_DEBUG_WX
+#ifdef CONFIG_DEBUG_WX
void ptdump_check_wx(void)
{
struct pg_state st = {
.seq = NULL,
- .marker = address_markers,
+ .marker = (struct addr_marker[]) {
+ { 0, NULL},
+ { -1, NULL},
+ },
+ .level = -1,
.check_wx = true,
- .start_address = IS_ENABLED(CONFIG_PPC64) ? PAGE_OFFSET : TASK_SIZE,
+ .ptdump = {
+ .note_page = note_page,
+ .range = ptdump_range,
+ }
};
-#ifdef CONFIG_PPC64
- if (!radix_enabled())
- st.start_address = KERN_VIRT_START;
-#endif
-
- walk_pagetables(&st);
+ ptdump_walk_pgd(&st.ptdump, &init_mm, NULL);
if (st.wx_pages)
pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found\n",
@@ -445,12 +352,23 @@ void ptdump_check_wx(void)
}
#endif
-static int ptdump_init(void)
+static int __init ptdump_init(void)
{
+#ifdef CONFIG_PPC64
+ if (!radix_enabled())
+ ptdump_range[0].start = KERN_VIRT_START;
+ else
+ ptdump_range[0].start = PAGE_OFFSET;
+
+ ptdump_range[0].end = PAGE_OFFSET + (PGDIR_SIZE * PTRS_PER_PGD);
+#endif
+
populate_markers();
build_pgtable_complete_mask();
- debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
- &ptdump_fops);
+
+ if (IS_ENABLED(CONFIG_PTDUMP_DEBUGFS))
+ debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops);
+
return 0;
}
device_initcall(ptdump_init);
diff --git a/arch/powerpc/mm/ptdump/segment_regs.c b/arch/powerpc/mm/ptdump/segment_regs.c
index 565048a0c9be..9df3af8d481f 100644
--- a/arch/powerpc/mm/ptdump/segment_regs.c
+++ b/arch/powerpc/mm/ptdump/segment_regs.c
@@ -6,7 +6,7 @@
* This dumps the content of Segment Registers
*/
-#include <asm/debugfs.h>
+#include <linux/debugfs.h>
static void seg_show(struct seq_file *m, int i)
{
@@ -41,21 +41,11 @@ static int sr_show(struct seq_file *m, void *v)
return 0;
}
-static int sr_open(struct inode *inode, struct file *file)
-{
- return single_open(file, sr_show, NULL);
-}
-
-static const struct file_operations sr_fops = {
- .open = sr_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(sr);
static int __init sr_init(void)
{
- debugfs_create_file("segment_registers", 0400, powerpc_debugfs_root,
+ debugfs_create_file("segment_registers", 0400, arch_debugfs_dir,
NULL, &sr_fops);
return 0;
}
diff --git a/arch/powerpc/mm/ptdump/shared.c b/arch/powerpc/mm/ptdump/shared.c
index c005fe041c18..03607ab90c66 100644
--- a/arch/powerpc/mm/ptdump/shared.c
+++ b/arch/powerpc/mm/ptdump/shared.c
@@ -68,8 +68,10 @@ static const struct flag_info flag_array[] = {
};
struct pgtable_level pg_level[5] = {
- {
- }, { /* pgd */
+ { /* pgd */
+ .flag = flag_array,
+ .num = ARRAY_SIZE(flag_array),
+ }, { /* p4d */
.flag = flag_array,
.num = ARRAY_SIZE(flag_array),
}, { /* pud */
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index bb0ee716de91..73e62e9b179b 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -340,6 +340,13 @@ static inline void perf_read_regs(struct pt_regs *regs)
* If the PMU doesn't update the SIAR for non marked events use
* pt_regs.
*
+ * If regs is a kernel interrupt, always use SIAR. Some PMUs have an
+ * issue with regs_sipr not being in synch with SIAR in interrupt entry
+ * and return sequences, which can result in regs_sipr being true for
+ * kernel interrupts and SIAR, which has the effect of causing samples
+ * to pile up at mtmsrd MSR[EE] 0->1 or pending irq replay around
+ * interrupt entry/exit.
+ *
* If the PMU has HV/PR flags then check to see if they
* place the exception in userspace. If so, use pt_regs. In
* continuous sampling mode the SIAR and the PMU exception are
@@ -356,6 +363,8 @@ static inline void perf_read_regs(struct pt_regs *regs)
use_siar = 1;
else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING))
use_siar = 0;
+ else if (!user_mode(regs))
+ use_siar = 1;
else if (!(ppmu->flags & PPMU_NO_SIPR) && regs_sipr(regs))
use_siar = 0;
else
@@ -2251,18 +2260,10 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
*/
unsigned long perf_instruction_pointer(struct pt_regs *regs)
{
- bool use_siar = regs_use_siar(regs);
unsigned long siar = mfspr(SPRN_SIAR);
- if (ppmu && (ppmu->flags & PPMU_P10_DD1)) {
- if (siar)
- return siar;
- else
- return regs->nip;
- } else if (use_siar && siar_valid(regs))
- return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
- else if (use_siar)
- return 0; // no valid instruction pointer
+ if (regs_use_siar(regs) && siar_valid(regs) && siar)
+ return siar + perf_ip_adjust(regs);
else
return regs->nip;
}
diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c
index d48413e28c39..c756228a081f 100644
--- a/arch/powerpc/perf/hv-gpci.c
+++ b/arch/powerpc/perf/hv-gpci.c
@@ -175,7 +175,7 @@ static unsigned long single_gpci_request(u32 req, u32 starting_index,
*/
count = 0;
for (i = offset; i < offset + length; i++)
- count |= arg->bytes[i] << (i - offset);
+ count |= (u64)(arg->bytes[i]) << ((length - 1 - (i - offset)) * 8);
*value = count;
out:
diff --git a/arch/powerpc/platforms/44x/machine_check.c b/arch/powerpc/platforms/44x/machine_check.c
index a5c898bb9bab..5d19daacd78a 100644
--- a/arch/powerpc/platforms/44x/machine_check.c
+++ b/arch/powerpc/platforms/44x/machine_check.c
@@ -11,7 +11,7 @@
int machine_check_440A(struct pt_regs *regs)
{
- unsigned long reason = regs->dsisr;
+ unsigned long reason = regs->esr;
printk("Machine check in kernel mode.\n");
if (reason & ESR_IMCP){
@@ -48,7 +48,7 @@ int machine_check_440A(struct pt_regs *regs)
#ifdef CONFIG_PPC_47x
int machine_check_47x(struct pt_regs *regs)
{
- unsigned long reason = regs->dsisr;
+ unsigned long reason = regs->esr;
u32 mcsr;
printk(KERN_ERR "Machine check in kernel mode.\n");
diff --git a/arch/powerpc/platforms/4xx/machine_check.c b/arch/powerpc/platforms/4xx/machine_check.c
index a71c29892a91..a905da1d6f41 100644
--- a/arch/powerpc/platforms/4xx/machine_check.c
+++ b/arch/powerpc/platforms/4xx/machine_check.c
@@ -10,7 +10,7 @@
int machine_check_4xx(struct pt_regs *regs)
{
- unsigned long reason = regs->dsisr;
+ unsigned long reason = regs->esr;
if (reason & ESR_IMCP) {
printk("Instruction");
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index b77cbb0a50e1..4142ebf01382 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -208,12 +208,6 @@ config TQM8560
select TQM85xx
select CPM2
-config SBC8548
- bool "Wind River SBC8548"
- select DEFAULT_UIMAGE
- help
- This option enables support for the Wind River SBC8548 board
-
config PPA8548
bool "Prodrive PPA8548"
help
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index d1dd0dca5ebf..60e4e97a929d 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -26,7 +26,6 @@ obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o
obj-$(CONFIG_FB_FSL_DIU) += t1042rdb_diu.o
obj-$(CONFIG_STX_GP3) += stx_gp3.o
obj-$(CONFIG_TQM85xx) += tqm85xx.o
-obj-$(CONFIG_SBC8548) += sbc8548.o
obj-$(CONFIG_PPA8548) += ppa8548.o
obj-$(CONFIG_SOCRATES) += socrates.o socrates_fpga_pic.o
obj-$(CONFIG_KSI8560) += ksi8560.o
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
deleted file mode 100644
index e4acf5ce6b07..000000000000
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ /dev/null
@@ -1,134 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Wind River SBC8548 setup and early boot code.
- *
- * Copyright 2007 Wind River Systems Inc.
- *
- * By Paul Gortmaker (see MAINTAINERS for contact information)
- *
- * Based largely on the MPC8548CDS support - Copyright 2005 Freescale Inc.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/initrd.h>
-#include <linux/interrupt.h>
-#include <linux/fsl_devices.h>
-#include <linux/of_platform.h>
-#include <linux/pgtable.h>
-
-#include <asm/page.h>
-#include <linux/atomic.h>
-#include <asm/time.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/ipic.h>
-#include <asm/pci-bridge.h>
-#include <asm/irq.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-
-#include "mpc85xx.h"
-
-static int sbc_rev;
-
-static void __init sbc8548_pic_init(void)
-{
- struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
- 0, 256, " OpenPIC ");
- BUG_ON(mpic == NULL);
- mpic_init(mpic);
-}
-
-/* Extract the HW Rev from the EPLD on the board */
-static int __init sbc8548_hw_rev(void)
-{
- struct device_node *np;
- struct resource res;
- unsigned int *rev;
- int board_rev = 0;
-
- np = of_find_compatible_node(NULL, NULL, "hw-rev");
- if (np == NULL) {
- printk("No HW-REV found in DTB.\n");
- return -ENODEV;
- }
-
- of_address_to_resource(np, 0, &res);
- of_node_put(np);
-
- rev = ioremap(res.start,sizeof(unsigned int));
- board_rev = (*rev) >> 28;
- iounmap(rev);
-
- return board_rev;
-}
-
-/*
- * Setup the architecture
- */
-static void __init sbc8548_setup_arch(void)
-{
- if (ppc_md.progress)
- ppc_md.progress("sbc8548_setup_arch()", 0);
-
- fsl_pci_assign_primary();
-
- sbc_rev = sbc8548_hw_rev();
-}
-
-static void sbc8548_show_cpuinfo(struct seq_file *m)
-{
- uint pvid, svid, phid1;
-
- pvid = mfspr(SPRN_PVR);
- svid = mfspr(SPRN_SVR);
-
- seq_printf(m, "Vendor\t\t: Wind River\n");
- seq_printf(m, "Machine\t\t: SBC8548 v%d\n", sbc_rev);
- seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
- seq_printf(m, "SVR\t\t: 0x%x\n", svid);
-
- /* Display cpu Pll setting */
- phid1 = mfspr(SPRN_HID1);
- seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
-}
-
-machine_arch_initcall(sbc8548, mpc85xx_common_publish_devices);
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init sbc8548_probe(void)
-{
- return of_machine_is_compatible("SBC8548");
-}
-
-define_machine(sbc8548) {
- .name = "SBC8548",
- .probe = sbc8548_probe,
- .setup_arch = sbc8548_setup_arch,
- .init_IRQ = sbc8548_pic_init,
- .show_cpuinfo = sbc8548_show_cpuinfo,
- .get_irq = mpic_get_irq,
-#ifdef CONFIG_PCI
- .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
- .pcibios_fixup_phb = fsl_pcibios_fixup_phb,
-#endif
- .calibrate_decr = generic_calibrate_decr,
- .progress = udbg_progress,
-};
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 07a9d60c618a..be867abebc83 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -20,12 +20,6 @@ config MPC8641_HPCN
help
This option enables support for the MPC8641 HPCN board.
-config SBC8641D
- bool "Wind River SBC8641D"
- select DEFAULT_UIMAGE
- help
- This option enables support for the WRS SBC8641D board.
-
config MPC8610_HPCD
bool "Freescale MPC8610 HPCD"
select DEFAULT_UIMAGE
@@ -74,7 +68,7 @@ config MPC8641
select FSL_PCI if PCI
select PPC_UDBG_16550
select MPIC
- default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A \
+ default y if MPC8641_HPCN || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A \
|| MVME7100
config MPC8610
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 2c04449be107..5bbe1475bf26 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -6,7 +6,6 @@
obj-y := pic.o common.o
obj-$(CONFIG_SMP) += mpc86xx_smp.o
obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o
-obj-$(CONFIG_SBC8641D) += sbc8641d.o
obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o
obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o
obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
deleted file mode 100644
index dc23dd383d6e..000000000000
--- a/arch/powerpc/platforms/86xx/sbc8641d.c
+++ /dev/null
@@ -1,87 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SBC8641D board specific routines
- *
- * Copyright 2008 Wind River Systems Inc.
- *
- * By Paul Gortmaker (see MAINTAINERS for contact information)
- *
- * Based largely on the 8641 HPCN support by Freescale Semiconductor Inc.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/of_platform.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/prom.h>
-#include <mm/mmu_decl.h>
-#include <asm/udbg.h>
-
-#include <asm/mpic.h>
-
-#include <sysdev/fsl_pci.h>
-#include <sysdev/fsl_soc.h>
-
-#include "mpc86xx.h"
-
-static void __init
-sbc8641_setup_arch(void)
-{
- if (ppc_md.progress)
- ppc_md.progress("sbc8641_setup_arch()", 0);
-
- printk("SBC8641 board from Wind River\n");
-
-#ifdef CONFIG_SMP
- mpc86xx_smp_init();
-#endif
-
- fsl_pci_assign_primary();
-}
-
-
-static void
-sbc8641_show_cpuinfo(struct seq_file *m)
-{
- uint svid = mfspr(SPRN_SVR);
-
- seq_printf(m, "Vendor\t\t: Wind River Systems\n");
-
- seq_printf(m, "SVR\t\t: 0x%x\n", svid);
-}
-
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init sbc8641_probe(void)
-{
- if (of_machine_is_compatible("wind,sbc8641"))
- return 1; /* Looks good */
-
- return 0;
-}
-
-machine_arch_initcall(sbc8641, mpc86xx_common_publish_devices);
-
-define_machine(sbc8641) {
- .name = "SBC8641D",
- .probe = sbc8641_probe,
- .setup_arch = sbc8641_setup_arch,
- .init_IRQ = mpc86xx_init_irq,
- .show_cpuinfo = sbc8641_show_cpuinfo,
- .get_irq = mpic_get_irq,
- .time_init = mpc86xx_time_init,
- .calibrate_decr = generic_calibrate_decr,
- .progress = udbg_progress,
-#ifdef CONFIG_PCI
- .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
-#endif
-};
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index ca2555b8a0c2..82335e364c44 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -12,8 +12,8 @@
#include <linux/export.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
+#include <linux/debugfs.h>
-#include <asm/debugfs.h>
#include <asm/dcr.h>
#include <asm/machdep.h>
#include <asm/prom.h>
@@ -480,6 +480,6 @@ void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic)
snprintf(name, sizeof(name), "msic_%d", of_node_to_nid(dn));
- debugfs_create_file(name, 0600, powerpc_debugfs_root, msic, &fops_msic);
+ debugfs_create_file(name, 0600, arch_debugfs_dir, msic, &fops_msic);
}
#endif /* DEBUG */
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index 85521b3e7098..7a85b117f7a4 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -251,7 +251,7 @@ static int ppc750_machine_check_exception(struct pt_regs *regs)
/* Are we prepared to handle this fault */
if ((entry = search_exception_tables(regs->nip)) != NULL) {
tsi108_clear_pci_cfg_error();
- regs_set_return_msr(regs, regs->msr | MSR_RI);
+ regs_set_recoverable(regs);
regs_set_return_ip(regs, extable_fixup(entry));
return 1;
}
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index d8da6a483e59..9eb9abb5bce2 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -173,7 +173,7 @@ static int mpc7448_machine_check_exception(struct pt_regs *regs)
/* Are we prepared to handle this fault */
if ((entry = search_exception_tables(regs->nip)) != NULL) {
tsi108_clear_pci_cfg_error();
- regs_set_return_msr(regs, regs->msr | MSR_RI);
+ regs_set_recoverable(regs);
regs_set_return_ip(regs, extable_fixup(entry));
return 1;
}
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c
index 534b0317fc15..6087c70ed2ef 100644
--- a/arch/powerpc/platforms/pasemi/idle.c
+++ b/arch/powerpc/platforms/pasemi/idle.c
@@ -59,7 +59,7 @@ static int pasemi_system_reset_exception(struct pt_regs *regs)
restore_astate(hard_smp_processor_id());
/* everything handled */
- regs_set_return_msr(regs, regs->msr | MSR_RI);
+ regs_set_recoverable(regs);
return 1;
}
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 528a7e0cf83a..e3ffdc8e8567 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -199,12 +199,12 @@ static ssize_t store_fastsleep_workaround_applyonce(struct device *dev,
*/
power7_fastsleep_workaround_exit = false;
- get_online_cpus();
+ cpus_read_lock();
primary_thread_mask = cpu_online_cores_map();
on_each_cpu_mask(&primary_thread_mask,
pnv_fastsleep_workaround_apply,
&err, 1);
- put_online_cpus();
+ cpus_read_unlock();
if (err) {
pr_err("fastsleep_workaround_applyonce change failed while running pnv_fastsleep_workaround_apply");
goto fail;
@@ -667,7 +667,6 @@ static unsigned long power9_idle_stop(unsigned long psscr)
sprs.purr = mfspr(SPRN_PURR);
sprs.spurr = mfspr(SPRN_SPURR);
sprs.dscr = mfspr(SPRN_DSCR);
- sprs.wort = mfspr(SPRN_WORT);
sprs.ciabr = mfspr(SPRN_CIABR);
sprs.mmcra = mfspr(SPRN_MMCRA);
@@ -785,7 +784,6 @@ core_woken:
mtspr(SPRN_PURR, sprs.purr);
mtspr(SPRN_SPURR, sprs.spurr);
mtspr(SPRN_DSCR, sprs.dscr);
- mtspr(SPRN_WORT, sprs.wort);
mtspr(SPRN_CIABR, sprs.ciabr);
mtspr(SPRN_MMCRA, sprs.mmcra);
diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c
index 537a4daed614..877720c64515 100644
--- a/arch/powerpc/platforms/powernv/memtrace.c
+++ b/arch/powerpc/platforms/powernv/memtrace.c
@@ -18,7 +18,6 @@
#include <linux/memory_hotplug.h>
#include <linux/numa.h>
#include <asm/machdep.h>
-#include <asm/debugfs.h>
#include <asm/cacheflush.h>
/* This enables us to keep track of the memory removed from each node. */
@@ -330,7 +329,7 @@ DEFINE_SIMPLE_ATTRIBUTE(memtrace_init_fops, memtrace_enable_get,
static int memtrace_init(void)
{
memtrace_debugfs_dir = debugfs_create_dir("memtrace",
- powerpc_debugfs_root);
+ arch_debugfs_dir);
debugfs_create_file("enable", 0600, memtrace_debugfs_dir,
NULL, &memtrace_init_fops);
diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c
index 7824cc364bc4..05d3832019b9 100644
--- a/arch/powerpc/platforms/powernv/opal-imc.c
+++ b/arch/powerpc/platforms/powernv/opal-imc.c
@@ -13,11 +13,11 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/crash_dump.h>
+#include <linux/debugfs.h>
#include <asm/opal.h>
#include <asm/io.h>
#include <asm/imc-pmu.h>
#include <asm/cputhreads.h>
-#include <asm/debugfs.h>
static struct dentry *imc_debugfs_parent;
@@ -56,7 +56,7 @@ static void export_imc_mode_and_cmd(struct device_node *node,
u32 cb_offset;
struct imc_mem_info *ptr = pmu_ptr->mem_info;
- imc_debugfs_parent = debugfs_create_dir("imc", powerpc_debugfs_root);
+ imc_debugfs_parent = debugfs_create_dir("imc", arch_debugfs_dir);
if (of_property_read_u32(node, "cb_offset", &cb_offset))
cb_offset = IMC_CNTL_BLK_OFFSET;
@@ -186,7 +186,7 @@ static void disable_nest_pmu_counters(void)
int nid, cpu;
const struct cpumask *l_cpumask;
- get_online_cpus();
+ cpus_read_lock();
for_each_node_with_cpus(nid) {
l_cpumask = cpumask_of_node(nid);
cpu = cpumask_first_and(l_cpumask, cpu_online_mask);
@@ -195,7 +195,7 @@ static void disable_nest_pmu_counters(void)
opal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST,
get_hard_smp_processor_id(cpu));
}
- put_online_cpus();
+ cpus_read_unlock();
}
static void disable_core_pmu_counters(void)
@@ -203,7 +203,7 @@ static void disable_core_pmu_counters(void)
cpumask_t cores_map;
int cpu, rc;
- get_online_cpus();
+ cpus_read_lock();
/* Disable the IMC Core functions */
cores_map = cpu_online_cores_map();
for_each_cpu(cpu, &cores_map) {
@@ -213,7 +213,7 @@ static void disable_core_pmu_counters(void)
pr_err("%s: Failed to stop Core (cpu = %d)\n",
__FUNCTION__, cpu);
}
- put_online_cpus();
+ cpus_read_unlock();
}
int get_max_nest_dev(void)
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c
index 608569082ba0..1e5d51db40f8 100644
--- a/arch/powerpc/platforms/powernv/opal-lpc.c
+++ b/arch/powerpc/platforms/powernv/opal-lpc.c
@@ -10,13 +10,13 @@
#include <linux/bug.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/debugfs.h>
#include <asm/machdep.h>
#include <asm/firmware.h>
#include <asm/opal.h>
#include <asm/prom.h>
#include <linux/uaccess.h>
-#include <asm/debugfs.h>
#include <asm/isa-bridge.h>
static int opal_lpc_chip_id = -1;
@@ -371,7 +371,7 @@ static int opal_lpc_init_debugfs(void)
if (opal_lpc_chip_id < 0)
return -ENODEV;
- root = debugfs_create_dir("lpc", powerpc_debugfs_root);
+ root = debugfs_create_dir("lpc", arch_debugfs_dir);
rc |= opal_lpc_debugfs_create_type(root, "io", OPAL_LPC_IO);
rc |= opal_lpc_debugfs_create_type(root, "mem", OPAL_LPC_MEM);
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c
index fd510d961b8c..6b4eed2ef4fa 100644
--- a/arch/powerpc/platforms/powernv/opal-xscom.c
+++ b/arch/powerpc/platforms/powernv/opal-xscom.c
@@ -14,11 +14,11 @@
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/debugfs.h>
#include <asm/machdep.h>
#include <asm/firmware.h>
#include <asm/opal.h>
-#include <asm/debugfs.h>
#include <asm/prom.h>
static u64 opal_scom_unmangle(u64 addr)
@@ -189,7 +189,7 @@ static int scom_debug_init(void)
if (!firmware_has_feature(FW_FEATURE_OPAL))
return 0;
- root = debugfs_create_dir("scom", powerpc_debugfs_root);
+ root = debugfs_create_dir("scom", arch_debugfs_dir);
if (!root)
return -1;
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 2835376e61a4..e9d18519e650 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -588,7 +588,7 @@ static int opal_recover_mce(struct pt_regs *regs,
{
int recovered = 0;
- if (!(regs->msr & MSR_RI)) {
+ if (regs_is_unrecoverable(regs)) {
/* If MSR_RI isn't set, we cannot recover */
pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n");
recovered = 0;
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 7de464679292..3dd35c327d1c 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -20,6 +20,7 @@
#include <linux/iommu.h>
#include <linux/rculist.h>
#include <linux/sizes.h>
+#include <linux/debugfs.h>
#include <asm/sections.h>
#include <asm/io.h>
@@ -32,10 +33,10 @@
#include <asm/iommu.h>
#include <asm/tce.h>
#include <asm/xics.h>
-#include <asm/debugfs.h>
#include <asm/firmware.h>
#include <asm/pnv-pci.h>
#include <asm/mmzone.h>
+#include <asm/xive.h>
#include <misc/cxl-base.h>
@@ -1962,27 +1963,40 @@ void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
pe->dma_setup_done = true;
}
-int64_t pnv_opal_pci_msi_eoi(struct irq_chip *chip, unsigned int hw_irq)
+/*
+ * Called from KVM in real mode to EOI passthru interrupts. The ICP
+ * EOI is handled directly in KVM in kvmppc_deliver_irq_passthru().
+ *
+ * The IRQ data is mapped in the PCI-MSI domain and the EOI OPAL call
+ * needs an HW IRQ number mapped in the XICS IRQ domain. The HW IRQ
+ * numbers of the in-the-middle MSI domain are vector numbers and it's
+ * good enough for OPAL. Use that.
+ */
+int64_t pnv_opal_pci_msi_eoi(struct irq_data *d)
{
- struct pnv_phb *phb = container_of(chip, struct pnv_phb,
- ioda.irq_chip);
+ struct pci_controller *hose = irq_data_get_irq_chip_data(d->parent_data);
+ struct pnv_phb *phb = hose->private_data;
- return opal_pci_msi_eoi(phb->opal_id, hw_irq);
+ return opal_pci_msi_eoi(phb->opal_id, d->parent_data->hwirq);
}
+/*
+ * The IRQ data is mapped in the XICS domain, with OPAL HW IRQ numbers
+ */
static void pnv_ioda2_msi_eoi(struct irq_data *d)
{
int64_t rc;
unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
- struct irq_chip *chip = irq_data_get_irq_chip(d);
+ struct pci_controller *hose = irq_data_get_irq_chip_data(d);
+ struct pnv_phb *phb = hose->private_data;
- rc = pnv_opal_pci_msi_eoi(chip, hw_irq);
+ rc = opal_pci_msi_eoi(phb->opal_id, hw_irq);
WARN_ON_ONCE(rc);
icp_native_eoi(d);
}
-
+/* P8/CXL only */
void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq)
{
struct irq_data *idata;
@@ -2004,27 +2018,32 @@ void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq)
phb->ioda.irq_chip.irq_eoi = pnv_ioda2_msi_eoi;
}
irq_set_chip(virq, &phb->ioda.irq_chip);
+ irq_set_chip_data(virq, phb->hose);
}
+static struct irq_chip pnv_pci_msi_irq_chip;
+
/*
* Returns true iff chip is something that we could call
* pnv_opal_pci_msi_eoi for.
*/
bool is_pnv_opal_msi(struct irq_chip *chip)
{
- return chip->irq_eoi == pnv_ioda2_msi_eoi;
+ return chip == &pnv_pci_msi_irq_chip;
}
EXPORT_SYMBOL_GPL(is_pnv_opal_msi);
-static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
- unsigned int hwirq, unsigned int virq,
- unsigned int is_64, struct msi_msg *msg)
+static int __pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
+ unsigned int xive_num,
+ unsigned int is_64, struct msi_msg *msg)
{
struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev);
- unsigned int xive_num = hwirq - phb->msi_base;
__be32 data;
int rc;
+ dev_dbg(&dev->dev, "%s: setup %s-bit MSI for vector #%d\n", __func__,
+ is_64 ? "64" : "32", xive_num);
+
/* No PE assigned ? bail out ... no MSI for you ! */
if (pe == NULL)
return -ENXIO;
@@ -2072,12 +2091,209 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
}
msg->data = be32_to_cpu(data);
- pnv_set_msi_irq_chip(phb, virq);
+ return 0;
+}
+
+/*
+ * The msi_free() op is called before irq_domain_free_irqs_top() when
+ * the handler data is still available. Use that to clear the XIVE
+ * controller.
+ */
+static void pnv_msi_ops_msi_free(struct irq_domain *domain,
+ struct msi_domain_info *info,
+ unsigned int irq)
+{
+ if (xive_enabled())
+ xive_irq_free_data(irq);
+}
+
+static struct msi_domain_ops pnv_pci_msi_domain_ops = {
+ .msi_free = pnv_msi_ops_msi_free,
+};
+
+static void pnv_msi_shutdown(struct irq_data *d)
+{
+ d = d->parent_data;
+ if (d->chip->irq_shutdown)
+ d->chip->irq_shutdown(d);
+}
+
+static void pnv_msi_mask(struct irq_data *d)
+{
+ pci_msi_mask_irq(d);
+ irq_chip_mask_parent(d);
+}
+
+static void pnv_msi_unmask(struct irq_data *d)
+{
+ pci_msi_unmask_irq(d);
+ irq_chip_unmask_parent(d);
+}
+
+static struct irq_chip pnv_pci_msi_irq_chip = {
+ .name = "PNV-PCI-MSI",
+ .irq_shutdown = pnv_msi_shutdown,
+ .irq_mask = pnv_msi_mask,
+ .irq_unmask = pnv_msi_unmask,
+ .irq_eoi = irq_chip_eoi_parent,
+};
+
+static struct msi_domain_info pnv_msi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
+ .ops = &pnv_pci_msi_domain_ops,
+ .chip = &pnv_pci_msi_irq_chip,
+};
+
+static void pnv_msi_compose_msg(struct irq_data *d, struct msi_msg *msg)
+{
+ struct msi_desc *entry = irq_data_get_msi_desc(d);
+ struct pci_dev *pdev = msi_desc_to_pci_dev(entry);
+ struct pci_controller *hose = irq_data_get_irq_chip_data(d);
+ struct pnv_phb *phb = hose->private_data;
+ int rc;
+
+ rc = __pnv_pci_ioda_msi_setup(phb, pdev, d->hwirq,
+ entry->msi_attrib.is_64, msg);
+ if (rc)
+ dev_err(&pdev->dev, "Failed to setup %s-bit MSI #%ld : %d\n",
+ entry->msi_attrib.is_64 ? "64" : "32", d->hwirq, rc);
+}
+
+/*
+ * The IRQ data is mapped in the MSI domain in which HW IRQ numbers
+ * correspond to vector numbers.
+ */
+static void pnv_msi_eoi(struct irq_data *d)
+{
+ struct pci_controller *hose = irq_data_get_irq_chip_data(d);
+ struct pnv_phb *phb = hose->private_data;
+
+ if (phb->model == PNV_PHB_MODEL_PHB3) {
+ /*
+ * The EOI OPAL call takes an OPAL HW IRQ number but
+ * since it is translated into a vector number in
+ * OPAL, use that directly.
+ */
+ WARN_ON_ONCE(opal_pci_msi_eoi(phb->opal_id, d->hwirq));
+ }
+
+ irq_chip_eoi_parent(d);
+}
+
+static struct irq_chip pnv_msi_irq_chip = {
+ .name = "PNV-MSI",
+ .irq_shutdown = pnv_msi_shutdown,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = pnv_msi_eoi,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .irq_compose_msi_msg = pnv_msi_compose_msg,
+};
+
+static int pnv_irq_parent_domain_alloc(struct irq_domain *domain,
+ unsigned int virq, int hwirq)
+{
+ struct irq_fwspec parent_fwspec;
+ int ret;
+
+ parent_fwspec.fwnode = domain->parent->fwnode;
+ parent_fwspec.param_count = 2;
+ parent_fwspec.param[0] = hwirq;
+ parent_fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+
+ ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int pnv_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ struct pci_controller *hose = domain->host_data;
+ struct pnv_phb *phb = hose->private_data;
+ msi_alloc_info_t *info = arg;
+ struct pci_dev *pdev = msi_desc_to_pci_dev(info->desc);
+ int hwirq;
+ int i, ret;
+
+ hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, nr_irqs);
+ if (hwirq < 0) {
+ dev_warn(&pdev->dev, "failed to find a free MSI\n");
+ return -ENOSPC;
+ }
+
+ dev_dbg(&pdev->dev, "%s bridge %pOF %d/%x #%d\n", __func__,
+ hose->dn, virq, hwirq, nr_irqs);
+
+ for (i = 0; i < nr_irqs; i++) {
+ ret = pnv_irq_parent_domain_alloc(domain, virq + i,
+ phb->msi_base + hwirq + i);
+ if (ret)
+ goto out;
+
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &pnv_msi_irq_chip, hose);
+ }
+
+ return 0;
+
+out:
+ irq_domain_free_irqs_parent(domain, virq, i - 1);
+ msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq, nr_irqs);
+ return ret;
+}
+
+static void pnv_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+ struct pci_controller *hose = irq_data_get_irq_chip_data(d);
+ struct pnv_phb *phb = hose->private_data;
+
+ pr_debug("%s bridge %pOF %d/%lx #%d\n", __func__, hose->dn,
+ virq, d->hwirq, nr_irqs);
+
+ msi_bitmap_free_hwirqs(&phb->msi_bmp, d->hwirq, nr_irqs);
+ /* XIVE domain is cleared through ->msi_free() */
+}
+
+static const struct irq_domain_ops pnv_irq_domain_ops = {
+ .alloc = pnv_irq_domain_alloc,
+ .free = pnv_irq_domain_free,
+};
+
+static int pnv_msi_allocate_domains(struct pci_controller *hose, unsigned int count)
+{
+ struct pnv_phb *phb = hose->private_data;
+ struct irq_domain *parent = irq_get_default_host();
+
+ hose->fwnode = irq_domain_alloc_named_id_fwnode("PNV-MSI", phb->opal_id);
+ if (!hose->fwnode)
+ return -ENOMEM;
- pr_devel("%s: %s-bit MSI on hwirq %x (xive #%d),"
- " address=%x_%08x data=%x PE# %x\n",
- pci_name(dev), is_64 ? "64" : "32", hwirq, xive_num,
- msg->address_hi, msg->address_lo, data, pe->pe_number);
+ hose->dev_domain = irq_domain_create_hierarchy(parent, 0, count,
+ hose->fwnode,
+ &pnv_irq_domain_ops, hose);
+ if (!hose->dev_domain) {
+ pr_err("PCI: failed to create IRQ domain bridge %pOF (domain %d)\n",
+ hose->dn, hose->global_number);
+ irq_domain_free_fwnode(hose->fwnode);
+ return -ENOMEM;
+ }
+
+ hose->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(hose->dn),
+ &pnv_msi_domain_info,
+ hose->dev_domain);
+ if (!hose->msi_domain) {
+ pr_err("PCI: failed to create MSI IRQ domain bridge %pOF (domain %d)\n",
+ hose->dn, hose->global_number);
+ irq_domain_free_fwnode(hose->fwnode);
+ irq_domain_remove(hose->dev_domain);
+ return -ENOMEM;
+ }
return 0;
}
@@ -2102,10 +2318,10 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb)
return;
}
- phb->msi_setup = pnv_pci_ioda_msi_setup;
- phb->msi32_support = 1;
pr_info(" Allocated bitmap for %d MSIs (base IRQ 0x%x)\n",
count, phb->msi_base);
+
+ pnv_msi_allocate_domains(phb->hose, count);
}
static void pnv_ioda_setup_pe_res(struct pnv_ioda_pe *pe,
@@ -2259,7 +2475,7 @@ static void pnv_pci_ioda_create_dbgfs(void)
phb = hose->private_data;
sprintf(name, "PCI%04x", hose->global_number);
- phb->dbgfs = debugfs_create_dir(name, powerpc_debugfs_root);
+ phb->dbgfs = debugfs_create_dir(name, arch_debugfs_dir);
debugfs_create_file_unsafe("dump_diag_regs", 0200, phb->dbgfs,
phb, &pnv_pci_diag_data_fops);
@@ -2709,8 +2925,6 @@ static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
.dma_dev_setup = pnv_pci_ioda_dma_dev_setup,
.dma_bus_setup = pnv_pci_ioda_dma_bus_setup,
.iommu_bypass_supported = pnv_pci_ioda_iommu_bypass_supported,
- .setup_msi_irqs = pnv_setup_msi_irqs,
- .teardown_msi_irqs = pnv_teardown_msi_irqs,
.enable_device_hook = pnv_pci_enable_device_hook,
.release_device = pnv_pci_release_device,
.window_alignment = pnv_pci_window_alignment,
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 6bb3c52633fb..9a8391b983d1 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -160,73 +160,6 @@ exit:
}
EXPORT_SYMBOL_GPL(pnv_pci_set_power_state);
-int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
-{
- struct pnv_phb *phb = pci_bus_to_pnvhb(pdev->bus);
- struct msi_desc *entry;
- struct msi_msg msg;
- int hwirq;
- unsigned int virq;
- int rc;
-
- if (WARN_ON(!phb) || !phb->msi_bmp.bitmap)
- return -ENODEV;
-
- if (pdev->no_64bit_msi && !phb->msi32_support)
- return -ENODEV;
-
- for_each_pci_msi_entry(entry, pdev) {
- if (!entry->msi_attrib.is_64 && !phb->msi32_support) {
- pr_warn("%s: Supports only 64-bit MSIs\n",
- pci_name(pdev));
- return -ENXIO;
- }
- hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, 1);
- if (hwirq < 0) {
- pr_warn("%s: Failed to find a free MSI\n",
- pci_name(pdev));
- return -ENOSPC;
- }
- virq = irq_create_mapping(NULL, phb->msi_base + hwirq);
- if (!virq) {
- pr_warn("%s: Failed to map MSI to linux irq\n",
- pci_name(pdev));
- msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq, 1);
- return -ENOMEM;
- }
- rc = phb->msi_setup(phb, pdev, phb->msi_base + hwirq,
- virq, entry->msi_attrib.is_64, &msg);
- if (rc) {
- pr_warn("%s: Failed to setup MSI\n", pci_name(pdev));
- irq_dispose_mapping(virq);
- msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq, 1);
- return rc;
- }
- irq_set_msi_desc(virq, entry);
- pci_write_msi_msg(virq, &msg);
- }
- return 0;
-}
-
-void pnv_teardown_msi_irqs(struct pci_dev *pdev)
-{
- struct pnv_phb *phb = pci_bus_to_pnvhb(pdev->bus);
- struct msi_desc *entry;
- irq_hw_number_t hwirq;
-
- if (WARN_ON(!phb))
- return;
-
- for_each_pci_msi_entry(entry, pdev) {
- if (!entry->irq)
- continue;
- hwirq = virq_to_hw(entry->irq);
- irq_set_msi_desc(entry->irq, NULL);
- irq_dispose_mapping(entry->irq);
- msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, 1);
- }
-}
-
/* Nicely print the contents of the PE State Tables (PEST). */
static void pnv_pci_dump_pest(__be64 pestA[], __be64 pestB[], int pest_size)
{
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index c8d4f222a86f..966a9eb64339 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -123,11 +123,7 @@ struct pnv_phb {
#endif
unsigned int msi_base;
- unsigned int msi32_support;
struct msi_bitmap msi_bmp;
- int (*msi_setup)(struct pnv_phb *phb, struct pci_dev *dev,
- unsigned int hwirq, unsigned int virq,
- unsigned int is_64, struct msi_msg *msg);
int (*init_m64)(struct pnv_phb *phb);
int (*get_pe_state)(struct pnv_phb *phb, int pe_no);
void (*freeze_pe)(struct pnv_phb *phb, int pe_no);
@@ -289,8 +285,6 @@ extern void pnv_pci_init_npu2_opencapi_phb(struct device_node *np);
extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option);
-extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type);
-extern void pnv_teardown_msi_irqs(struct pci_dev *pdev);
extern struct pnv_ioda_pe *pnv_pci_bdfn_to_pe(struct pnv_phb *phb, u16 bdfn);
extern struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev);
extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq);
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 7ddc7ec6a7c0..ef710a715903 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -169,7 +169,8 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long vpn,
spin_unlock_irqrestore(&ps3_htab_lock, flags);
}
-static void ps3_hpte_clear(void)
+/* Called during kexec sequence with MMU off */
+static notrace void ps3_hpte_clear(void)
{
unsigned long hpte_count = (1UL << ppc64_pft_size) >> 4;
u64 i;
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index a81eac35d900..9c44f335c0b9 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -195,9 +195,11 @@ fail:
/**
* ps3_mm_vas_destroy -
+ *
+ * called during kexec sequence with MMU off.
*/
-void ps3_mm_vas_destroy(void)
+notrace void ps3_mm_vas_destroy(void)
{
int result;
@@ -1243,9 +1245,11 @@ void __init ps3_mm_init(void)
/**
* ps3_mm_shutdown - final cleanup of address space
+ *
+ * called during kexec sequence with MMU off.
*/
-void ps3_mm_shutdown(void)
+notrace void ps3_mm_shutdown(void)
{
ps3_mm_region_destroy(&map.r1);
}
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 1a5665875165..c8b50fec56bf 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -381,7 +381,7 @@ static int ps3_system_bus_probe(struct device *_dev)
return result;
}
-static int ps3_system_bus_remove(struct device *_dev)
+static void ps3_system_bus_remove(struct device *_dev)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
struct ps3_system_bus_driver *drv;
@@ -399,7 +399,6 @@ static int ps3_system_bus_remove(struct device *_dev)
__func__, __LINE__, drv->core.name);
pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev_name(&dev->core));
- return 0;
}
static void ps3_system_bus_shutdown(struct device *_dev)
@@ -663,7 +662,7 @@ static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
unsigned long attrs)
{
BUG();
- return 0;
+ return -EINVAL;
}
static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index 982f069e4c31..352af5b14a0f 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -11,10 +11,10 @@
#include <linux/spinlock.h>
#include <asm/smp.h>
#include <linux/uaccess.h>
+#include <linux/debugfs.h>
#include <asm/firmware.h>
#include <asm/dtl.h>
#include <asm/lppaca.h>
-#include <asm/debugfs.h>
#include <asm/plpar_wrappers.h>
#include <asm/machdep.h>
@@ -338,7 +338,7 @@ static int dtl_init(void)
/* set up common debugfs structure */
- dtl_dir = debugfs_create_dir("dtl", powerpc_debugfs_root);
+ dtl_dir = debugfs_create_dir("dtl", arch_debugfs_dir);
debugfs_create_x8("dtl_event_mask", 0600, dtl_dir, &dtl_event_mask);
debugfs_create_u32("dtl_buf_entries", 0400, dtl_dir, &dtl_buf_entries);
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 4c7b7f5a2ebc..f162156b7b68 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -119,10 +119,11 @@ struct vec5_fw_feature {
static __initdata struct vec5_fw_feature
vec5_fw_features_table[] = {
- {FW_FEATURE_TYPE1_AFFINITY, OV5_TYPE1_AFFINITY},
+ {FW_FEATURE_FORM1_AFFINITY, OV5_FORM1_AFFINITY},
{FW_FEATURE_PRRN, OV5_PRRN},
{FW_FEATURE_DRMEM_V2, OV5_DRMEM_V2},
{FW_FEATURE_DRC_INFO, OV5_DRC_INFO},
+ {FW_FEATURE_FORM2_AFFINITY, OV5_FORM2_AFFINITY},
};
static void __init fw_vec5_feature_init(const char *vec5, unsigned long len)
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 7e970f81d8ff..d646c22e94ab 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -39,6 +39,12 @@
/* This version can't take the spinlock, because it never returns */
static int rtas_stop_self_token = RTAS_UNKNOWN_SERVICE;
+/*
+ * Record the CPU ids used on each nodes.
+ * Protected by cpu_add_remove_lock.
+ */
+static cpumask_var_t node_recorded_ids_map[MAX_NUMNODES];
+
static void rtas_stop_self(void)
{
static struct rtas_args args;
@@ -139,72 +145,148 @@ static void pseries_cpu_die(unsigned int cpu)
paca_ptrs[cpu]->cpu_start = 0;
}
+/**
+ * find_cpu_id_range - found a linear ranger of @nthreads free CPU ids.
+ * @nthreads : the number of threads (cpu ids)
+ * @assigned_node : the node it belongs to or NUMA_NO_NODE if free ids from any
+ * node can be peek.
+ * @cpu_mask: the returned CPU mask.
+ *
+ * Returns 0 on success.
+ */
+static int find_cpu_id_range(unsigned int nthreads, int assigned_node,
+ cpumask_var_t *cpu_mask)
+{
+ cpumask_var_t candidate_mask;
+ unsigned int cpu, node;
+ int rc = -ENOSPC;
+
+ if (!zalloc_cpumask_var(&candidate_mask, GFP_KERNEL))
+ return -ENOMEM;
+
+ cpumask_clear(*cpu_mask);
+ for (cpu = 0; cpu < nthreads; cpu++)
+ cpumask_set_cpu(cpu, *cpu_mask);
+
+ BUG_ON(!cpumask_subset(cpu_present_mask, cpu_possible_mask));
+
+ /* Get a bitmap of unoccupied slots. */
+ cpumask_xor(candidate_mask, cpu_possible_mask, cpu_present_mask);
+
+ if (assigned_node != NUMA_NO_NODE) {
+ /*
+ * Remove free ids previously assigned on the other nodes. We
+ * can walk only online nodes because once a node became online
+ * it is not turned offlined back.
+ */
+ for_each_online_node(node) {
+ if (node == assigned_node)
+ continue;
+ cpumask_andnot(candidate_mask, candidate_mask,
+ node_recorded_ids_map[node]);
+ }
+ }
+
+ if (cpumask_empty(candidate_mask))
+ goto out;
+
+ while (!cpumask_empty(*cpu_mask)) {
+ if (cpumask_subset(*cpu_mask, candidate_mask))
+ /* Found a range where we can insert the new cpu(s) */
+ break;
+ cpumask_shift_left(*cpu_mask, *cpu_mask, nthreads);
+ }
+
+ if (!cpumask_empty(*cpu_mask))
+ rc = 0;
+
+out:
+ free_cpumask_var(candidate_mask);
+ return rc;
+}
+
/*
* Update cpu_present_mask and paca(s) for a new cpu node. The wrinkle
- * here is that a cpu device node may represent up to two logical cpus
+ * here is that a cpu device node may represent multiple logical cpus
* in the SMT case. We must honor the assumption in other code that
* the logical ids for sibling SMT threads x and y are adjacent, such
* that x^1 == y and y^1 == x.
*/
static int pseries_add_processor(struct device_node *np)
{
- unsigned int cpu;
- cpumask_var_t candidate_mask, tmp;
- int err = -ENOSPC, len, nthreads, i;
+ int len, nthreads, node, cpu, assigned_node;
+ int rc = 0;
+ cpumask_var_t cpu_mask;
const __be32 *intserv;
intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len);
if (!intserv)
return 0;
- zalloc_cpumask_var(&candidate_mask, GFP_KERNEL);
- zalloc_cpumask_var(&tmp, GFP_KERNEL);
-
nthreads = len / sizeof(u32);
- for (i = 0; i < nthreads; i++)
- cpumask_set_cpu(i, tmp);
- cpu_maps_update_begin();
+ if (!alloc_cpumask_var(&cpu_mask, GFP_KERNEL))
+ return -ENOMEM;
- BUG_ON(!cpumask_subset(cpu_present_mask, cpu_possible_mask));
+ /*
+ * Fetch from the DT nodes read by dlpar_configure_connector() the NUMA
+ * node id the added CPU belongs to.
+ */
+ node = of_node_to_nid(np);
+ if (node < 0 || !node_possible(node))
+ node = first_online_node;
- /* Get a bitmap of unoccupied slots. */
- cpumask_xor(candidate_mask, cpu_possible_mask, cpu_present_mask);
- if (cpumask_empty(candidate_mask)) {
- /* If we get here, it most likely means that NR_CPUS is
- * less than the partition's max processors setting.
+ BUG_ON(node == NUMA_NO_NODE);
+ assigned_node = node;
+
+ cpu_maps_update_begin();
+
+ rc = find_cpu_id_range(nthreads, node, &cpu_mask);
+ if (rc && nr_node_ids > 1) {
+ /*
+ * Try again, considering the free CPU ids from the other node.
*/
- printk(KERN_ERR "Cannot add cpu %pOF; this system configuration"
- " supports %d logical cpus.\n", np,
- num_possible_cpus());
- goto out_unlock;
+ node = NUMA_NO_NODE;
+ rc = find_cpu_id_range(nthreads, NUMA_NO_NODE, &cpu_mask);
}
- while (!cpumask_empty(tmp))
- if (cpumask_subset(tmp, candidate_mask))
- /* Found a range where we can insert the new cpu(s) */
- break;
- else
- cpumask_shift_left(tmp, tmp, nthreads);
-
- if (cpumask_empty(tmp)) {
- printk(KERN_ERR "Unable to find space in cpu_present_mask for"
- " processor %pOFn with %d thread(s)\n", np,
- nthreads);
- goto out_unlock;
+ if (rc) {
+ pr_err("Cannot add cpu %pOF; this system configuration"
+ " supports %d logical cpus.\n", np, num_possible_cpus());
+ goto out;
}
- for_each_cpu(cpu, tmp) {
+ for_each_cpu(cpu, cpu_mask) {
BUG_ON(cpu_present(cpu));
set_cpu_present(cpu, true);
set_hard_smp_processor_id(cpu, be32_to_cpu(*intserv++));
}
- err = 0;
-out_unlock:
+
+ /* Record the newly used CPU ids for the associate node. */
+ cpumask_or(node_recorded_ids_map[assigned_node],
+ node_recorded_ids_map[assigned_node], cpu_mask);
+
+ /*
+ * If node is set to NUMA_NO_NODE, CPU ids have be reused from
+ * another node, remove them from its mask.
+ */
+ if (node == NUMA_NO_NODE) {
+ cpu = cpumask_first(cpu_mask);
+ pr_warn("Reusing free CPU ids %d-%d from another node\n",
+ cpu, cpu + nthreads - 1);
+ for_each_online_node(node) {
+ if (node == assigned_node)
+ continue;
+ cpumask_andnot(node_recorded_ids_map[node],
+ node_recorded_ids_map[node],
+ cpu_mask);
+ }
+ }
+
+out:
cpu_maps_update_done();
- free_cpumask_var(candidate_mask);
- free_cpumask_var(tmp);
- return err;
+ free_cpumask_var(cpu_mask);
+ return rc;
}
/*
@@ -498,6 +580,8 @@ static ssize_t dlpar_cpu_add(u32 drc_index)
return saved_rc;
}
+ update_numa_distance(dn);
+
rc = dlpar_online_cpu(dn);
if (rc) {
saved_rc = rc;
@@ -908,6 +992,7 @@ static struct notifier_block pseries_smp_nb = {
static int __init pseries_cpu_hotplug_init(void)
{
int qcss_tok;
+ unsigned int node;
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
ppc_md.cpu_probe = dlpar_cpu_probe;
@@ -929,8 +1014,18 @@ static int __init pseries_cpu_hotplug_init(void)
smp_ops->cpu_die = pseries_cpu_die;
/* Processors can be added/removed only on LPAR */
- if (firmware_has_feature(FW_FEATURE_LPAR))
+ if (firmware_has_feature(FW_FEATURE_LPAR)) {
+ for_each_node(node) {
+ alloc_bootmem_cpumask_var(&node_recorded_ids_map[node]);
+
+ /* Record ids of CPU added at boot time */
+ cpumask_or(node_recorded_ids_map[node],
+ node_recorded_ids_map[node],
+ cpumask_of_node(node));
+ }
+
of_reconfig_notifier_register(&pseries_smp_nb);
+ }
return 0;
}
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 377d852f5a9a..44246ba59768 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -180,6 +180,8 @@ static int update_lmb_associativity_index(struct drmem_lmb *lmb)
return -ENODEV;
}
+ update_numa_distance(lmb_node);
+
dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
if (!dr_node) {
dlpar_free_cc_nodes(lmb_node);
@@ -211,13 +213,11 @@ static int update_lmb_associativity_index(struct drmem_lmb *lmb)
static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb)
{
unsigned long section_nr;
- struct mem_section *mem_sect;
struct memory_block *mem_block;
section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
- mem_sect = __nr_to_section(section_nr);
- mem_block = find_memory_block(mem_sect);
+ mem_block = find_memory_block(section_nr);
return mem_block;
}
@@ -979,6 +979,10 @@ static int pseries_memory_notifier(struct notifier_block *nb,
case OF_RECONFIG_DETACH_NODE:
err = pseries_remove_mem_node(rd->dn);
break;
+ case OF_RECONFIG_UPDATE_PROPERTY:
+ if (!strcmp(rd->dn->name,
+ "ibm,dynamic-reconfiguration-memory"))
+ drmem_update_lmbs(rd->prop);
}
return notifier_from_errno(err);
}
diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c
index c6c79ef55e13..7ee3ed7d6cc2 100644
--- a/arch/powerpc/platforms/pseries/ibmebus.c
+++ b/arch/powerpc/platforms/pseries/ibmebus.c
@@ -366,14 +366,13 @@ static int ibmebus_bus_device_probe(struct device *dev)
return error;
}
-static int ibmebus_bus_device_remove(struct device *dev)
+static void ibmebus_bus_device_remove(struct device *dev)
{
struct platform_device *of_dev = to_platform_device(dev);
struct platform_driver *drv = to_platform_driver(dev->driver);
if (dev->driver && drv->remove)
drv->remove(of_dev);
- return 0;
}
static void ibmebus_bus_device_shutdown(struct device *dev)
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 0c55b991f665..dab5c56ffd0e 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -53,28 +53,31 @@ enum {
DDW_EXT_QUERY_OUT_SIZE = 2
};
-static struct iommu_table_group *iommu_pseries_alloc_group(int node)
+static struct iommu_table *iommu_pseries_alloc_table(int node)
{
- struct iommu_table_group *table_group;
struct iommu_table *tbl;
- table_group = kzalloc_node(sizeof(struct iommu_table_group), GFP_KERNEL,
- node);
- if (!table_group)
- return NULL;
-
tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, node);
if (!tbl)
- goto free_group;
+ return NULL;
INIT_LIST_HEAD_RCU(&tbl->it_group_list);
kref_init(&tbl->it_kref);
+ return tbl;
+}
+
+static struct iommu_table_group *iommu_pseries_alloc_group(int node)
+{
+ struct iommu_table_group *table_group;
- table_group->tables[0] = tbl;
+ table_group = kzalloc_node(sizeof(*table_group), GFP_KERNEL, node);
+ if (!table_group)
+ return NULL;
- return table_group;
+ table_group->tables[0] = iommu_pseries_alloc_table(node);
+ if (table_group->tables[0])
+ return table_group;
-free_group:
kfree(table_group);
return NULL;
}
@@ -107,6 +110,8 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
u64 proto_tce;
__be64 *tcep;
u64 rpn;
+ const unsigned long tceshift = tbl->it_page_shift;
+ const unsigned long pagesize = IOMMU_PAGE_SIZE(tbl);
proto_tce = TCE_PCI_READ; // Read allowed
@@ -117,10 +122,10 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
while (npages--) {
/* can't move this out since we might cross MEMBLOCK boundary */
- rpn = __pa(uaddr) >> TCE_SHIFT;
- *tcep = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT);
+ rpn = __pa(uaddr) >> tceshift;
+ *tcep = cpu_to_be64(proto_tce | rpn << tceshift);
- uaddr += TCE_PAGE_SIZE;
+ uaddr += pagesize;
tcep++;
}
return 0;
@@ -146,7 +151,7 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
return be64_to_cpu(*tcep);
}
-static void tce_free_pSeriesLP(unsigned long liobn, long, long);
+static void tce_free_pSeriesLP(unsigned long liobn, long, long, long);
static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
@@ -166,12 +171,12 @@ static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
proto_tce |= TCE_PCI_WRITE;
while (npages--) {
- tce = proto_tce | (rpn & TCE_RPN_MASK) << tceshift;
+ tce = proto_tce | rpn << tceshift;
rc = plpar_tce_put((u64)liobn, (u64)tcenum << tceshift, tce);
if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
ret = (int)rc;
- tce_free_pSeriesLP(liobn, tcenum_start,
+ tce_free_pSeriesLP(liobn, tcenum_start, tceshift,
(npages_start - (npages + 1)));
break;
}
@@ -205,10 +210,11 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long tcenum_start = tcenum, npages_start = npages;
int ret = 0;
unsigned long flags;
+ const unsigned long tceshift = tbl->it_page_shift;
if ((npages == 1) || !firmware_has_feature(FW_FEATURE_PUT_TCE_IND)) {
return tce_build_pSeriesLP(tbl->it_index, tcenum,
- tbl->it_page_shift, npages, uaddr,
+ tceshift, npages, uaddr,
direction, attrs);
}
@@ -225,13 +231,13 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
if (!tcep) {
local_irq_restore(flags);
return tce_build_pSeriesLP(tbl->it_index, tcenum,
- tbl->it_page_shift,
+ tceshift,
npages, uaddr, direction, attrs);
}
__this_cpu_write(tce_page, tcep);
}
- rpn = __pa(uaddr) >> TCE_SHIFT;
+ rpn = __pa(uaddr) >> tceshift;
proto_tce = TCE_PCI_READ;
if (direction != DMA_TO_DEVICE)
proto_tce |= TCE_PCI_WRITE;
@@ -245,12 +251,12 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
for (l = 0; l < limit; l++) {
- tcep[l] = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT);
+ tcep[l] = cpu_to_be64(proto_tce | rpn << tceshift);
rpn++;
}
rc = plpar_tce_put_indirect((u64)tbl->it_index,
- (u64)tcenum << 12,
+ (u64)tcenum << tceshift,
(u64)__pa(tcep),
limit);
@@ -277,12 +283,13 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
return ret;
}
-static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long npages)
+static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
+ long npages)
{
u64 rc;
while (npages--) {
- rc = plpar_tce_put((u64)liobn, (u64)tcenum << 12, 0);
+ rc = plpar_tce_put((u64)liobn, (u64)tcenum << tceshift, 0);
if (rc && printk_ratelimit()) {
printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
@@ -301,9 +308,11 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
u64 rc;
if (!firmware_has_feature(FW_FEATURE_STUFF_TCE))
- return tce_free_pSeriesLP(tbl->it_index, tcenum, npages);
+ return tce_free_pSeriesLP(tbl->it_index, tcenum,
+ tbl->it_page_shift, npages);
- rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
+ rc = plpar_tce_stuff((u64)tbl->it_index,
+ (u64)tcenum << tbl->it_page_shift, 0, npages);
if (rc && printk_ratelimit()) {
printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
@@ -319,7 +328,8 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
u64 rc;
unsigned long tce_ret;
- rc = plpar_tce_get((u64)tbl->it_index, (u64)tcenum << 12, &tce_ret);
+ rc = plpar_tce_get((u64)tbl->it_index,
+ (u64)tcenum << tbl->it_page_shift, &tce_ret);
if (rc && printk_ratelimit()) {
printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%lld\n", rc);
@@ -339,7 +349,7 @@ struct dynamic_dma_window_prop {
__be32 window_shift; /* ilog2(tce_window_size) */
};
-struct direct_window {
+struct dma_win {
struct device_node *device;
const struct dynamic_dma_window_prop *prop;
struct list_head list;
@@ -359,12 +369,13 @@ struct ddw_create_response {
u32 addr_lo;
};
-static LIST_HEAD(direct_window_list);
+static LIST_HEAD(dma_win_list);
/* prevents races between memory on/offline and window creation */
-static DEFINE_SPINLOCK(direct_window_list_lock);
+static DEFINE_SPINLOCK(dma_win_list_lock);
/* protects initializing window twice for same device */
-static DEFINE_MUTEX(direct_window_init_mutex);
+static DEFINE_MUTEX(dma_win_init_mutex);
#define DIRECT64_PROPNAME "linux,direct64-ddr-window-info"
+#define DMA64_PROPNAME "linux,dma64-ddr-window-info"
static int tce_clearrange_multi_pSeriesLP(unsigned long start_pfn,
unsigned long num_pfn, const void *arg)
@@ -491,6 +502,24 @@ static int tce_setrange_multi_pSeriesLP_walk(unsigned long start_pfn,
return tce_setrange_multi_pSeriesLP(start_pfn, num_pfn, arg);
}
+static void iommu_table_setparms_common(struct iommu_table *tbl, unsigned long busno,
+ unsigned long liobn, unsigned long win_addr,
+ unsigned long window_size, unsigned long page_shift,
+ void *base, struct iommu_table_ops *table_ops)
+{
+ tbl->it_busno = busno;
+ tbl->it_index = liobn;
+ tbl->it_offset = win_addr >> page_shift;
+ tbl->it_size = window_size >> page_shift;
+ tbl->it_page_shift = page_shift;
+ tbl->it_base = (unsigned long)base;
+ tbl->it_blocksize = 16;
+ tbl->it_type = TCE_PCI;
+ tbl->it_ops = table_ops;
+}
+
+struct iommu_table_ops iommu_table_pseries_ops;
+
static void iommu_table_setparms(struct pci_controller *phb,
struct device_node *dn,
struct iommu_table *tbl)
@@ -499,8 +528,13 @@ static void iommu_table_setparms(struct pci_controller *phb,
const unsigned long *basep;
const u32 *sizep;
- node = phb->dn;
+ /* Test if we are going over 2GB of DMA space */
+ if (phb->dma_window_base_cur + phb->dma_window_size > SZ_2G) {
+ udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
+ panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
+ }
+ node = phb->dn;
basep = of_get_property(node, "linux,tce-base", NULL);
sizep = of_get_property(node, "linux,tce-size", NULL);
if (basep == NULL || sizep == NULL) {
@@ -509,33 +543,18 @@ static void iommu_table_setparms(struct pci_controller *phb,
return;
}
- tbl->it_base = (unsigned long)__va(*basep);
+ iommu_table_setparms_common(tbl, phb->bus->number, 0, phb->dma_window_base_cur,
+ phb->dma_window_size, IOMMU_PAGE_SHIFT_4K,
+ __va(*basep), &iommu_table_pseries_ops);
if (!is_kdump_kernel())
memset((void *)tbl->it_base, 0, *sizep);
- tbl->it_busno = phb->bus->number;
- tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
-
- /* Units of tce entries */
- tbl->it_offset = phb->dma_window_base_cur >> tbl->it_page_shift;
-
- /* Test if we are going over 2GB of DMA space */
- if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
- udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
- panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
- }
-
phb->dma_window_base_cur += phb->dma_window_size;
-
- /* Set the tce table size - measured in entries */
- tbl->it_size = phb->dma_window_size >> tbl->it_page_shift;
-
- tbl->it_index = 0;
- tbl->it_blocksize = 16;
- tbl->it_type = TCE_PCI;
}
+struct iommu_table_ops iommu_table_lpar_multi_ops;
+
/*
* iommu_table_setparms_lpar
*
@@ -547,17 +566,13 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
struct iommu_table_group *table_group,
const __be32 *dma_window)
{
- unsigned long offset, size;
+ unsigned long offset, size, liobn;
- of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
+ of_parse_dma_window(dn, dma_window, &liobn, &offset, &size);
+
+ iommu_table_setparms_common(tbl, phb->bus->number, liobn, offset, size, IOMMU_PAGE_SHIFT_4K, NULL,
+ &iommu_table_lpar_multi_ops);
- tbl->it_busno = phb->bus->number;
- tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
- tbl->it_base = 0;
- tbl->it_blocksize = 16;
- tbl->it_type = TCE_PCI;
- tbl->it_offset = offset >> tbl->it_page_shift;
- tbl->it_size = size >> tbl->it_page_shift;
table_group->tce32_start = offset;
table_group->tce32_size = size;
@@ -637,7 +652,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
tbl = pci->table_group->tables[0];
iommu_table_setparms(pci->phb, dn, tbl);
- tbl->it_ops = &iommu_table_pseries_ops;
+
if (!iommu_init_table(tbl, pci->phb->node, 0, 0))
panic("Failed to initialize iommu table");
@@ -698,7 +713,10 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %pOF\n",
dn);
- /* Find nearest ibm,dma-window, walking up the device tree */
+ /*
+ * Find nearest ibm,dma-window (default DMA window), walking up the
+ * device tree
+ */
for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
if (dma_window != NULL)
@@ -720,7 +738,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
tbl = ppci->table_group->tables[0];
iommu_table_setparms_lpar(ppci->phb, pdn, tbl,
ppci->table_group, dma_window);
- tbl->it_ops = &iommu_table_lpar_multi_ops;
+
if (!iommu_init_table(tbl, ppci->phb->node, 0, 0))
panic("Failed to initialize iommu table");
iommu_register_group(ppci->table_group,
@@ -750,7 +768,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
PCI_DN(dn)->table_group = iommu_pseries_alloc_group(phb->node);
tbl = PCI_DN(dn)->table_group->tables[0];
iommu_table_setparms(phb, dn, tbl);
- tbl->it_ops = &iommu_table_pseries_ops;
+
if (!iommu_init_table(tbl, phb->node, 0, 0))
panic("Failed to initialize iommu table");
@@ -785,17 +803,10 @@ static int __init disable_ddw_setup(char *str)
early_param("disable_ddw", disable_ddw_setup);
-static void remove_dma_window(struct device_node *np, u32 *ddw_avail,
- struct property *win)
+static void clean_dma_window(struct device_node *np, struct dynamic_dma_window_prop *dwp)
{
- struct dynamic_dma_window_prop *dwp;
- u64 liobn;
int ret;
- dwp = win->value;
- liobn = (u64)be32_to_cpu(dwp->liobn);
-
- /* clear the whole window, note the arg is in kernel pages */
ret = tce_clearrange_multi_pSeriesLP(0,
1ULL << (be32_to_cpu(dwp->window_shift) - PAGE_SHIFT), dwp);
if (ret)
@@ -804,94 +815,136 @@ static void remove_dma_window(struct device_node *np, u32 *ddw_avail,
else
pr_debug("%pOF successfully cleared tces in window.\n",
np);
+}
+
+/*
+ * Call only if DMA window is clean.
+ */
+static void __remove_dma_window(struct device_node *np, u32 *ddw_avail, u64 liobn)
+{
+ int ret;
ret = rtas_call(ddw_avail[DDW_REMOVE_PE_DMA_WIN], 1, 1, NULL, liobn);
if (ret)
- pr_warn("%pOF: failed to remove direct window: rtas returned "
+ pr_warn("%pOF: failed to remove DMA window: rtas returned "
"%d to ibm,remove-pe-dma-window(%x) %llx\n",
np, ret, ddw_avail[DDW_REMOVE_PE_DMA_WIN], liobn);
else
- pr_debug("%pOF: successfully removed direct window: rtas returned "
+ pr_debug("%pOF: successfully removed DMA window: rtas returned "
"%d to ibm,remove-pe-dma-window(%x) %llx\n",
np, ret, ddw_avail[DDW_REMOVE_PE_DMA_WIN], liobn);
}
-static void remove_ddw(struct device_node *np, bool remove_prop)
+static void remove_dma_window(struct device_node *np, u32 *ddw_avail,
+ struct property *win)
+{
+ struct dynamic_dma_window_prop *dwp;
+ u64 liobn;
+
+ dwp = win->value;
+ liobn = (u64)be32_to_cpu(dwp->liobn);
+
+ clean_dma_window(np, dwp);
+ __remove_dma_window(np, ddw_avail, liobn);
+}
+
+static int remove_ddw(struct device_node *np, bool remove_prop, const char *win_name)
{
struct property *win;
u32 ddw_avail[DDW_APPLICABLE_SIZE];
int ret = 0;
+ win = of_find_property(np, win_name, NULL);
+ if (!win)
+ return -EINVAL;
+
ret = of_property_read_u32_array(np, "ibm,ddw-applicable",
&ddw_avail[0], DDW_APPLICABLE_SIZE);
if (ret)
- return;
+ return 0;
- win = of_find_property(np, DIRECT64_PROPNAME, NULL);
- if (!win)
- return;
if (win->length >= sizeof(struct dynamic_dma_window_prop))
remove_dma_window(np, ddw_avail, win);
if (!remove_prop)
- return;
+ return 0;
ret = of_remove_property(np, win);
if (ret)
- pr_warn("%pOF: failed to remove direct window property: %d\n",
+ pr_warn("%pOF: failed to remove DMA window property: %d\n",
np, ret);
+ return 0;
}
-static u64 find_existing_ddw(struct device_node *pdn, int *window_shift)
+static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift)
{
- struct direct_window *window;
- const struct dynamic_dma_window_prop *direct64;
- u64 dma_addr = 0;
+ struct dma_win *window;
+ const struct dynamic_dma_window_prop *dma64;
+ bool found = false;
- spin_lock(&direct_window_list_lock);
+ spin_lock(&dma_win_list_lock);
/* check if we already created a window and dupe that config if so */
- list_for_each_entry(window, &direct_window_list, list) {
+ list_for_each_entry(window, &dma_win_list, list) {
if (window->device == pdn) {
- direct64 = window->prop;
- dma_addr = be64_to_cpu(direct64->dma_base);
- *window_shift = be32_to_cpu(direct64->window_shift);
+ dma64 = window->prop;
+ *dma_addr = be64_to_cpu(dma64->dma_base);
+ *window_shift = be32_to_cpu(dma64->window_shift);
+ found = true;
break;
}
}
- spin_unlock(&direct_window_list_lock);
+ spin_unlock(&dma_win_list_lock);
- return dma_addr;
+ return found;
}
-static int find_existing_ddw_windows(void)
+static struct dma_win *ddw_list_new_entry(struct device_node *pdn,
+ const struct dynamic_dma_window_prop *dma64)
{
- int len;
- struct device_node *pdn;
- struct direct_window *window;
- const struct dynamic_dma_window_prop *direct64;
+ struct dma_win *window;
- if (!firmware_has_feature(FW_FEATURE_LPAR))
- return 0;
+ window = kzalloc(sizeof(*window), GFP_KERNEL);
+ if (!window)
+ return NULL;
- for_each_node_with_property(pdn, DIRECT64_PROPNAME) {
- direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
- if (!direct64)
- continue;
+ window->device = pdn;
+ window->prop = dma64;
- window = kzalloc(sizeof(*window), GFP_KERNEL);
- if (!window || len < sizeof(struct dynamic_dma_window_prop)) {
- kfree(window);
- remove_ddw(pdn, true);
+ return window;
+}
+
+static void find_existing_ddw_windows_named(const char *name)
+{
+ int len;
+ struct device_node *pdn;
+ struct dma_win *window;
+ const struct dynamic_dma_window_prop *dma64;
+
+ for_each_node_with_property(pdn, name) {
+ dma64 = of_get_property(pdn, name, &len);
+ if (!dma64 || len < sizeof(*dma64)) {
+ remove_ddw(pdn, true, name);
continue;
}
- window->device = pdn;
- window->prop = direct64;
- spin_lock(&direct_window_list_lock);
- list_add(&window->list, &direct_window_list);
- spin_unlock(&direct_window_list_lock);
+ window = ddw_list_new_entry(pdn, dma64);
+ if (!window)
+ break;
+
+ spin_lock(&dma_win_list_lock);
+ list_add(&window->list, &dma_win_list);
+ spin_unlock(&dma_win_list_lock);
}
+}
+
+static int find_existing_ddw_windows(void)
+{
+ if (!firmware_has_feature(FW_FEATURE_LPAR))
+ return 0;
+
+ find_existing_ddw_windows_named(DIRECT64_PROPNAME);
+ find_existing_ddw_windows_named(DMA64_PROPNAME);
return 0;
}
@@ -1130,6 +1183,35 @@ static int iommu_get_page_shift(u32 query_page_size)
return 0;
}
+static struct property *ddw_property_create(const char *propname, u32 liobn, u64 dma_addr,
+ u32 page_shift, u32 window_shift)
+{
+ struct dynamic_dma_window_prop *ddwprop;
+ struct property *win64;
+
+ win64 = kzalloc(sizeof(*win64), GFP_KERNEL);
+ if (!win64)
+ return NULL;
+
+ win64->name = kstrdup(propname, GFP_KERNEL);
+ ddwprop = kzalloc(sizeof(*ddwprop), GFP_KERNEL);
+ win64->value = ddwprop;
+ win64->length = sizeof(*ddwprop);
+ if (!win64->name || !win64->value) {
+ kfree(win64->name);
+ kfree(win64->value);
+ kfree(win64);
+ return NULL;
+ }
+
+ ddwprop->liobn = cpu_to_be32(liobn);
+ ddwprop->dma_base = cpu_to_be64(dma_addr);
+ ddwprop->tce_shift = cpu_to_be32(page_shift);
+ ddwprop->window_shift = cpu_to_be32(window_shift);
+
+ return win64;
+}
+
/*
* If the PE supports dynamic dma windows, and there is space for a table
* that can map all pages in a linear offset, then setup such a table,
@@ -1139,34 +1221,39 @@ static int iommu_get_page_shift(u32 query_page_size)
* pdn: the parent pe node with the ibm,dma_window property
* Future: also check if we can remap the base window for our base page size
*
- * returns the dma offset for use by the direct mapped DMA code.
+ * returns true if can map all pages (direct mapping), false otherwise..
*/
-static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
{
int len = 0, ret;
int max_ram_len = order_base_2(ddw_memory_hotplug_max());
struct ddw_query_response query;
struct ddw_create_response create;
int page_shift;
- u64 dma_addr;
+ u64 win_addr;
+ const char *win_name;
struct device_node *dn;
u32 ddw_avail[DDW_APPLICABLE_SIZE];
- struct direct_window *window;
+ struct dma_win *window;
struct property *win64;
- struct dynamic_dma_window_prop *ddwprop;
+ bool ddw_enabled = false;
struct failed_ddw_pdn *fpdn;
- bool default_win_removed = false;
+ bool default_win_removed = false, direct_mapping = false;
bool pmem_present;
+ struct pci_dn *pci = PCI_DN(pdn);
+ struct iommu_table *tbl = pci->table_group->tables[0];
dn = of_find_node_by_type(NULL, "ibm,pmemory");
pmem_present = dn != NULL;
of_node_put(dn);
- mutex_lock(&direct_window_init_mutex);
+ mutex_lock(&dma_win_init_mutex);
- dma_addr = find_existing_ddw(pdn, &len);
- if (dma_addr != 0)
+ if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len)) {
+ direct_mapping = (len >= max_ram_len);
+ ddw_enabled = true;
goto out_unlock;
+ }
/*
* If we already went through this for a previous function of
@@ -1240,12 +1327,12 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
page_shift = iommu_get_page_shift(query.page_size);
if (!page_shift) {
- dev_dbg(&dev->dev, "no supported direct page size in mask %x",
- query.page_size);
+ dev_dbg(&dev->dev, "no supported page size in mask %x",
+ query.page_size);
goto out_failed;
}
- /* verify the window * number of ptes will map the partition */
- /* check largest block * page size > max memory hotplug addr */
+
+
/*
* The "ibm,pmemory" can appear anywhere in the address space.
* Assuming it is still backed by page structs, try MAX_PHYSMEM_BITS
@@ -1261,81 +1348,127 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
dev_info(&dev->dev, "Skipping ibm,pmemory");
}
+ /* check if the available block * number of ptes will map everything */
if (query.largest_available_block < (1ULL << (len - page_shift))) {
dev_dbg(&dev->dev,
"can't map partition max 0x%llx with %llu %llu-sized pages\n",
1ULL << len,
query.largest_available_block,
1ULL << page_shift);
- goto out_failed;
- }
- win64 = kzalloc(sizeof(struct property), GFP_KERNEL);
- if (!win64) {
- dev_info(&dev->dev,
- "couldn't allocate property for 64bit dma window\n");
- goto out_failed;
- }
- win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
- win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
- win64->length = sizeof(*ddwprop);
- if (!win64->name || !win64->value) {
- dev_info(&dev->dev,
- "couldn't allocate property name and value\n");
- goto out_free_prop;
+
+ /* DDW + IOMMU on single window may fail if there is any allocation */
+ if (default_win_removed && iommu_table_in_use(tbl)) {
+ dev_dbg(&dev->dev, "current IOMMU table in use, can't be replaced.\n");
+ goto out_failed;
+ }
+
+ len = order_base_2(query.largest_available_block << page_shift);
+ win_name = DMA64_PROPNAME;
+ } else {
+ direct_mapping = true;
+ win_name = DIRECT64_PROPNAME;
}
ret = create_ddw(dev, ddw_avail, &create, page_shift, len);
if (ret != 0)
- goto out_free_prop;
-
- ddwprop->liobn = cpu_to_be32(create.liobn);
- ddwprop->dma_base = cpu_to_be64(((u64)create.addr_hi << 32) |
- create.addr_lo);
- ddwprop->tce_shift = cpu_to_be32(page_shift);
- ddwprop->window_shift = cpu_to_be32(len);
+ goto out_failed;
dev_dbg(&dev->dev, "created tce table LIOBN 0x%x for %pOF\n",
create.liobn, dn);
- window = kzalloc(sizeof(*window), GFP_KERNEL);
- if (!window)
- goto out_clear_window;
+ win_addr = ((u64)create.addr_hi << 32) | create.addr_lo;
+ win64 = ddw_property_create(win_name, create.liobn, win_addr, page_shift, len);
- ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT,
- win64->value, tce_setrange_multi_pSeriesLP_walk);
- if (ret) {
- dev_info(&dev->dev, "failed to map direct window for %pOF: %d\n",
- dn, ret);
- goto out_free_window;
+ if (!win64) {
+ dev_info(&dev->dev,
+ "couldn't allocate property, property name, or value\n");
+ goto out_remove_win;
}
ret = of_add_property(pdn, win64);
if (ret) {
- dev_err(&dev->dev, "unable to add dma window property for %pOF: %d",
- pdn, ret);
- goto out_free_window;
+ dev_err(&dev->dev, "unable to add DMA window property for %pOF: %d",
+ pdn, ret);
+ goto out_free_prop;
}
- window->device = pdn;
- window->prop = ddwprop;
- spin_lock(&direct_window_list_lock);
- list_add(&window->list, &direct_window_list);
- spin_unlock(&direct_window_list_lock);
+ window = ddw_list_new_entry(pdn, win64->value);
+ if (!window)
+ goto out_del_prop;
+
+ if (direct_mapping) {
+ /* DDW maps the whole partition, so enable direct DMA mapping */
+ ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT,
+ win64->value, tce_setrange_multi_pSeriesLP_walk);
+ if (ret) {
+ dev_info(&dev->dev, "failed to map DMA window for %pOF: %d\n",
+ dn, ret);
+
+ /* Make sure to clean DDW if any TCE was set*/
+ clean_dma_window(pdn, win64->value);
+ goto out_del_list;
+ }
+ } else {
+ struct iommu_table *newtbl;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pci->phb->mem_resources); i++) {
+ const unsigned long mask = IORESOURCE_MEM_64 | IORESOURCE_MEM;
+
+ /* Look for MMIO32 */
+ if ((pci->phb->mem_resources[i].flags & mask) == IORESOURCE_MEM)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(pci->phb->mem_resources))
+ goto out_del_list;
+
+ /* New table for using DDW instead of the default DMA window */
+ newtbl = iommu_pseries_alloc_table(pci->phb->node);
+ if (!newtbl) {
+ dev_dbg(&dev->dev, "couldn't create new IOMMU table\n");
+ goto out_del_list;
+ }
+
+ iommu_table_setparms_common(newtbl, pci->phb->bus->number, create.liobn, win_addr,
+ 1UL << len, page_shift, NULL, &iommu_table_lpar_multi_ops);
+ iommu_init_table(newtbl, pci->phb->node, pci->phb->mem_resources[i].start,
+ pci->phb->mem_resources[i].end);
- dma_addr = be64_to_cpu(ddwprop->dma_base);
+ pci->table_group->tables[1] = newtbl;
+
+ /* Keep default DMA window stuct if removed */
+ if (default_win_removed) {
+ tbl->it_size = 0;
+ kfree(tbl->it_map);
+ }
+
+ set_iommu_table_base(&dev->dev, newtbl);
+ }
+
+ spin_lock(&dma_win_list_lock);
+ list_add(&window->list, &dma_win_list);
+ spin_unlock(&dma_win_list_lock);
+
+ dev->dev.archdata.dma_offset = win_addr;
+ ddw_enabled = true;
goto out_unlock;
-out_free_window:
+out_del_list:
kfree(window);
-out_clear_window:
- remove_ddw(pdn, true);
+out_del_prop:
+ of_remove_property(pdn, win64);
out_free_prop:
kfree(win64->name);
kfree(win64->value);
kfree(win64);
+out_remove_win:
+ /* DDW is clean, so it's ok to call this directly. */
+ __remove_dma_window(pdn, ddw_avail, create.liobn);
+
out_failed:
if (default_win_removed)
reset_dma_window(dev, pdn);
@@ -1347,17 +1480,17 @@ out_failed:
list_add(&fpdn->list, &failed_ddw_pdn_list);
out_unlock:
- mutex_unlock(&direct_window_init_mutex);
+ mutex_unlock(&dma_win_init_mutex);
/*
* If we have persistent memory and the window size is only as big
* as RAM, then we failed to create a window to cover persistent
* memory and need to set the DMA limit.
*/
- if (pmem_present && dma_addr && (len == max_ram_len))
- dev->dev.bus_dma_limit = dma_addr + (1ULL << len);
+ if (pmem_present && ddw_enabled && direct_mapping && len == max_ram_len)
+ dev->dev.bus_dma_limit = dev->dev.archdata.dma_offset + (1ULL << len);
- return dma_addr;
+ return ddw_enabled && direct_mapping;
}
static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
@@ -1399,7 +1532,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
tbl = pci->table_group->tables[0];
iommu_table_setparms_lpar(pci->phb, pdn, tbl,
pci->table_group, dma_window);
- tbl->it_ops = &iommu_table_lpar_multi_ops;
+
iommu_init_table(tbl, pci->phb->node, 0, 0);
iommu_register_group(pci->table_group,
pci_domain_nr(pci->phb->bus), 0);
@@ -1436,11 +1569,8 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask)
break;
}
- if (pdn && PCI_DN(pdn)) {
- pdev->dev.archdata.dma_offset = enable_ddw(pdev, pdn);
- if (pdev->dev.archdata.dma_offset)
- return true;
- }
+ if (pdn && PCI_DN(pdn))
+ return enable_ddw(pdev, pdn);
return false;
}
@@ -1448,29 +1578,29 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask)
static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
void *data)
{
- struct direct_window *window;
+ struct dma_win *window;
struct memory_notify *arg = data;
int ret = 0;
switch (action) {
case MEM_GOING_ONLINE:
- spin_lock(&direct_window_list_lock);
- list_for_each_entry(window, &direct_window_list, list) {
+ spin_lock(&dma_win_list_lock);
+ list_for_each_entry(window, &dma_win_list, list) {
ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn,
arg->nr_pages, window->prop);
/* XXX log error */
}
- spin_unlock(&direct_window_list_lock);
+ spin_unlock(&dma_win_list_lock);
break;
case MEM_CANCEL_ONLINE:
case MEM_OFFLINE:
- spin_lock(&direct_window_list_lock);
- list_for_each_entry(window, &direct_window_list, list) {
+ spin_lock(&dma_win_list_lock);
+ list_for_each_entry(window, &dma_win_list, list) {
ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn,
arg->nr_pages, window->prop);
/* XXX log error */
}
- spin_unlock(&direct_window_list_lock);
+ spin_unlock(&dma_win_list_lock);
break;
default:
break;
@@ -1491,7 +1621,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
struct of_reconfig_data *rd = data;
struct device_node *np = rd->dn;
struct pci_dn *pci = PCI_DN(np);
- struct direct_window *window;
+ struct dma_win *window;
switch (action) {
case OF_RECONFIG_DETACH_NODE:
@@ -1502,20 +1632,22 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
* we have to remove the property when releasing
* the device node.
*/
- remove_ddw(np, false);
+ if (remove_ddw(np, false, DIRECT64_PROPNAME))
+ remove_ddw(np, false, DMA64_PROPNAME);
+
if (pci && pci->table_group)
iommu_pseries_free_group(pci->table_group,
np->full_name);
- spin_lock(&direct_window_list_lock);
- list_for_each_entry(window, &direct_window_list, list) {
+ spin_lock(&dma_win_list_lock);
+ list_for_each_entry(window, &dma_win_list, list) {
if (window->device == np) {
list_del(&window->list);
kfree(window);
break;
}
}
- spin_unlock(&direct_window_list_lock);
+ spin_unlock(&dma_win_list_lock);
break;
default:
err = NOTIFY_DONE;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index dab356e3ff87..3df6bdfea475 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -22,6 +22,8 @@
#include <linux/workqueue.h>
#include <linux/proc_fs.h>
#include <linux/pgtable.h>
+#include <linux/debugfs.h>
+
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/page.h>
@@ -39,7 +41,6 @@
#include <asm/kexec.h>
#include <asm/fadump.h>
#include <asm/asm-prototypes.h>
-#include <asm/debugfs.h>
#include <asm/dtl.h>
#include "pseries.h"
@@ -261,7 +262,7 @@ static int cpu_relative_dispatch_distance(int last_disp_cpu, int cur_disp_cpu)
if (!last_disp_cpu_assoc || !cur_disp_cpu_assoc)
return -EIO;
- return cpu_distance(last_disp_cpu_assoc, cur_disp_cpu_assoc);
+ return cpu_relative_distance(last_disp_cpu_assoc, cur_disp_cpu_assoc);
}
static int cpu_home_node_dispatch_distance(int disp_cpu)
@@ -281,7 +282,7 @@ static int cpu_home_node_dispatch_distance(int disp_cpu)
if (!disp_cpu_assoc || !vcpu_assoc)
return -EIO;
- return cpu_distance(disp_cpu_assoc, vcpu_assoc);
+ return cpu_relative_distance(disp_cpu_assoc, vcpu_assoc);
}
static void update_vcpu_disp_stat(int disp_cpu)
@@ -801,7 +802,8 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
return -1;
}
-static void manual_hpte_clear_all(void)
+/* Called during kexec sequence with MMU off */
+static notrace void manual_hpte_clear_all(void)
{
unsigned long size_bytes = 1UL << ppc64_pft_size;
unsigned long hpte_count = size_bytes >> 4;
@@ -834,7 +836,8 @@ static void manual_hpte_clear_all(void)
}
}
-static int hcall_hpte_clear_all(void)
+/* Called during kexec sequence with MMU off */
+static notrace int hcall_hpte_clear_all(void)
{
int rc;
@@ -845,7 +848,8 @@ static int hcall_hpte_clear_all(void)
return rc;
}
-static void pseries_hpte_clear_all(void)
+/* Called during kexec sequence with MMU off */
+static notrace void pseries_hpte_clear_all(void)
{
int rc;
@@ -2016,7 +2020,7 @@ static int __init vpa_debugfs_init(void)
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
return 0;
- vpa_dir = debugfs_create_dir("vpa", powerpc_debugfs_root);
+ vpa_dir = debugfs_create_dir("vpa", arch_debugfs_dir);
/* set up the per-cpu vpa file*/
for_each_possible_cpu(i) {
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 637300330507..1b305e411862 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -13,6 +13,7 @@
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
#include <asm/machdep.h>
+#include <asm/xive.h>
#include "pseries.h"
@@ -110,21 +111,6 @@ static int rtas_query_irq_number(struct pci_dn *pdn, int offset)
return rtas_ret[0];
}
-static void rtas_teardown_msi_irqs(struct pci_dev *pdev)
-{
- struct msi_desc *entry;
-
- for_each_pci_msi_entry(entry, pdev) {
- if (!entry->irq)
- continue;
-
- irq_set_msi_desc(entry->irq, NULL);
- irq_dispose_mapping(entry->irq);
- }
-
- rtas_disable_msi(pdev);
-}
-
static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
{
struct device_node *dn;
@@ -164,12 +150,12 @@ static int check_req_msix(struct pci_dev *pdev, int nvec)
/* Quota calculation */
-static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
+static struct device_node *__find_pe_total_msi(struct device_node *node, int *total)
{
struct device_node *dn;
const __be32 *p;
- dn = of_node_get(pci_device_to_OF_node(dev));
+ dn = of_node_get(node);
while (dn) {
p = of_get_property(dn, "ibm,pe-total-#msi", NULL);
if (p) {
@@ -185,6 +171,11 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
return NULL;
}
+static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
+{
+ return __find_pe_total_msi(pci_device_to_OF_node(dev), total);
+}
+
static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
{
struct device_node *dn;
@@ -368,12 +359,11 @@ static void rtas_hack_32bit_msi_gen2(struct pci_dev *pdev)
pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, 0);
}
-static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
+static int rtas_prepare_msi_irqs(struct pci_dev *pdev, int nvec_in, int type,
+ msi_alloc_info_t *arg)
{
struct pci_dn *pdn;
- int hwirq, virq, i, quota, rc;
- struct msi_desc *entry;
- struct msi_msg msg;
+ int quota, rc;
int nvec = nvec_in;
int use_32bit_msi_hack = 0;
@@ -451,53 +441,229 @@ again:
return rc;
}
- i = 0;
- for_each_pci_msi_entry(entry, pdev) {
- hwirq = rtas_query_irq_number(pdn, i++);
- if (hwirq < 0) {
- pr_debug("rtas_msi: error (%d) getting hwirq\n", rc);
- return hwirq;
- }
+ return 0;
+}
- /*
- * Depending on the number of online CPUs in the original
- * kernel, it is likely for CPU #0 to be offline in a kdump
- * kernel. The associated IRQs in the affinity mappings
- * provided by irq_create_affinity_masks() are thus not
- * started by irq_startup(), as per-design for managed IRQs.
- * This can be a problem with multi-queue block devices driven
- * by blk-mq : such a non-started IRQ is very likely paired
- * with the single queue enforced by blk-mq during kdump (see
- * blk_mq_alloc_tag_set()). This causes the device to remain
- * silent and likely hangs the guest at some point.
- *
- * We don't really care for fine-grained affinity when doing
- * kdump actually : simply ignore the pre-computed affinity
- * masks in this case and let the default mask with all CPUs
- * be used when creating the IRQ mappings.
- */
- if (is_kdump_kernel())
- virq = irq_create_mapping(NULL, hwirq);
- else
- virq = irq_create_mapping_affinity(NULL, hwirq,
- entry->affinity);
+static int pseries_msi_ops_prepare(struct irq_domain *domain, struct device *dev,
+ int nvec, msi_alloc_info_t *arg)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct msi_desc *desc = first_pci_msi_entry(pdev);
+ int type = desc->msi_attrib.is_msix ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI;
- if (!virq) {
- pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq);
- return -ENOSPC;
- }
+ return rtas_prepare_msi_irqs(pdev, nvec, type, arg);
+}
+
+/*
+ * ->msi_free() is called before irq_domain_free_irqs_top() when the
+ * handler data is still available. Use that to clear the XIVE
+ * controller data.
+ */
+static void pseries_msi_ops_msi_free(struct irq_domain *domain,
+ struct msi_domain_info *info,
+ unsigned int irq)
+{
+ if (xive_enabled())
+ xive_irq_free_data(irq);
+}
+
+/*
+ * RTAS can not disable one MSI at a time. It's all or nothing. Do it
+ * at the end after all IRQs have been freed.
+ */
+static void pseries_msi_domain_free_irqs(struct irq_domain *domain,
+ struct device *dev)
+{
+ if (WARN_ON_ONCE(!dev_is_pci(dev)))
+ return;
+
+ __msi_domain_free_irqs(domain, dev);
+
+ rtas_disable_msi(to_pci_dev(dev));
+}
+
+static struct msi_domain_ops pseries_pci_msi_domain_ops = {
+ .msi_prepare = pseries_msi_ops_prepare,
+ .msi_free = pseries_msi_ops_msi_free,
+ .domain_free_irqs = pseries_msi_domain_free_irqs,
+};
+
+static void pseries_msi_shutdown(struct irq_data *d)
+{
+ d = d->parent_data;
+ if (d->chip->irq_shutdown)
+ d->chip->irq_shutdown(d);
+}
+
+static void pseries_msi_mask(struct irq_data *d)
+{
+ pci_msi_mask_irq(d);
+ irq_chip_mask_parent(d);
+}
+
+static void pseries_msi_unmask(struct irq_data *d)
+{
+ pci_msi_unmask_irq(d);
+ irq_chip_unmask_parent(d);
+}
- dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq);
- irq_set_msi_desc(virq, entry);
+static struct irq_chip pseries_pci_msi_irq_chip = {
+ .name = "pSeries-PCI-MSI",
+ .irq_shutdown = pseries_msi_shutdown,
+ .irq_mask = pseries_msi_mask,
+ .irq_unmask = pseries_msi_unmask,
+ .irq_eoi = irq_chip_eoi_parent,
+};
+
+static struct msi_domain_info pseries_msi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
+ .ops = &pseries_pci_msi_domain_ops,
+ .chip = &pseries_pci_msi_irq_chip,
+};
+
+static void pseries_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ __pci_read_msi_msg(irq_data_get_msi_desc(data), msg);
+}
+
+static struct irq_chip pseries_msi_irq_chip = {
+ .name = "pSeries-MSI",
+ .irq_shutdown = pseries_msi_shutdown,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .irq_compose_msi_msg = pseries_msi_compose_msg,
+};
+
+static int pseries_irq_parent_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq)
+{
+ struct irq_fwspec parent_fwspec;
+ int ret;
+
+ parent_fwspec.fwnode = domain->parent->fwnode;
+ parent_fwspec.param_count = 2;
+ parent_fwspec.param[0] = hwirq;
+ parent_fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+
+ ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int pseries_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ struct pci_controller *phb = domain->host_data;
+ msi_alloc_info_t *info = arg;
+ struct msi_desc *desc = info->desc;
+ struct pci_dev *pdev = msi_desc_to_pci_dev(desc);
+ int hwirq;
+ int i, ret;
+
+ hwirq = rtas_query_irq_number(pci_get_pdn(pdev), desc->msi_attrib.entry_nr);
+ if (hwirq < 0) {
+ dev_err(&pdev->dev, "Failed to query HW IRQ: %d\n", hwirq);
+ return hwirq;
+ }
+
+ dev_dbg(&pdev->dev, "%s bridge %pOF %d/%x #%d\n", __func__,
+ phb->dn, virq, hwirq, nr_irqs);
+
+ for (i = 0; i < nr_irqs; i++) {
+ ret = pseries_irq_parent_domain_alloc(domain, virq + i, hwirq + i);
+ if (ret)
+ goto out;
+
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &pseries_msi_irq_chip, domain->host_data);
+ }
+
+ return 0;
+
+out:
+ /* TODO: handle RTAS cleanup in ->msi_finish() ? */
+ irq_domain_free_irqs_parent(domain, virq, i - 1);
+ return ret;
+}
+
+static void pseries_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+ struct pci_controller *phb = irq_data_get_irq_chip_data(d);
+
+ pr_debug("%s bridge %pOF %d #%d\n", __func__, phb->dn, virq, nr_irqs);
+
+ /* XIVE domain data is cleared through ->msi_free() */
+}
- /* Read config space back so we can restore after reset */
- __pci_read_msi_msg(entry, &msg);
- entry->msg = msg;
+static const struct irq_domain_ops pseries_irq_domain_ops = {
+ .alloc = pseries_irq_domain_alloc,
+ .free = pseries_irq_domain_free,
+};
+
+static int __pseries_msi_allocate_domains(struct pci_controller *phb,
+ unsigned int count)
+{
+ struct irq_domain *parent = irq_get_default_host();
+
+ phb->fwnode = irq_domain_alloc_named_id_fwnode("pSeries-MSI",
+ phb->global_number);
+ if (!phb->fwnode)
+ return -ENOMEM;
+
+ phb->dev_domain = irq_domain_create_hierarchy(parent, 0, count,
+ phb->fwnode,
+ &pseries_irq_domain_ops, phb);
+ if (!phb->dev_domain) {
+ pr_err("PCI: failed to create IRQ domain bridge %pOF (domain %d)\n",
+ phb->dn, phb->global_number);
+ irq_domain_free_fwnode(phb->fwnode);
+ return -ENOMEM;
+ }
+
+ phb->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(phb->dn),
+ &pseries_msi_domain_info,
+ phb->dev_domain);
+ if (!phb->msi_domain) {
+ pr_err("PCI: failed to create MSI IRQ domain bridge %pOF (domain %d)\n",
+ phb->dn, phb->global_number);
+ irq_domain_free_fwnode(phb->fwnode);
+ irq_domain_remove(phb->dev_domain);
+ return -ENOMEM;
}
return 0;
}
+int pseries_msi_allocate_domains(struct pci_controller *phb)
+{
+ int count;
+
+ if (!__find_pe_total_msi(phb->dn, &count)) {
+ pr_err("PCI: failed to find MSIs for bridge %pOF (domain %d)\n",
+ phb->dn, phb->global_number);
+ return -ENOSPC;
+ }
+
+ return __pseries_msi_allocate_domains(phb, count);
+}
+
+void pseries_msi_free_domains(struct pci_controller *phb)
+{
+ if (phb->msi_domain)
+ irq_domain_remove(phb->msi_domain);
+ if (phb->dev_domain)
+ irq_domain_remove(phb->dev_domain);
+ if (phb->fwnode)
+ irq_domain_free_fwnode(phb->fwnode);
+}
+
static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev)
{
/* No LSI -> leave MSIs (if any) configured */
@@ -518,8 +684,6 @@ static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev)
static int rtas_msi_init(void)
{
- struct pci_controller *phb;
-
query_token = rtas_token("ibm,query-interrupt-source-number");
change_token = rtas_token("ibm,change-msi");
@@ -531,16 +695,6 @@ static int rtas_msi_init(void)
pr_debug("rtas_msi: Registering RTAS MSI callbacks.\n");
- WARN_ON(pseries_pci_controller_ops.setup_msi_irqs);
- pseries_pci_controller_ops.setup_msi_irqs = rtas_setup_msi_irqs;
- pseries_pci_controller_ops.teardown_msi_irqs = rtas_teardown_msi_irqs;
-
- list_for_each_entry(phb, &hose_list, list_node) {
- WARN_ON(phb->controller_ops.setup_msi_irqs);
- phb->controller_ops.setup_msi_irqs = rtas_setup_msi_irqs;
- phb->controller_ops.teardown_msi_irqs = rtas_teardown_msi_irqs;
- }
-
WARN_ON(ppc_md.pci_irq_fixup);
ppc_md.pci_irq_fixup = rtas_msi_pci_irq_fixup;
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index a8f9140a24fa..90c9d3531694 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -33,6 +33,8 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn)
pci_devs_phb_init_dynamic(phb);
+ pseries_msi_allocate_domains(phb);
+
/* Create EEH devices for the PHB */
eeh_phb_pe_create(phb);
@@ -74,6 +76,8 @@ int remove_phb_dynamic(struct pci_controller *phb)
}
}
+ pseries_msi_free_domains(phb);
+
/* Remove the PCI bus and unregister the bridge device from sysfs */
phb->bus = NULL;
pci_remove_bus(b);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 1f051a786fb3..3544778e06d0 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -85,6 +85,8 @@ struct pci_host_bridge;
int pseries_root_bridge_prepare(struct pci_host_bridge *bridge);
extern struct pci_controller_ops pseries_pci_controller_ops;
+int pseries_msi_allocate_domains(struct pci_controller *phb);
+void pseries_msi_free_domains(struct pci_controller *phb);
unsigned long pseries_memory_block_size(void);
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 167f2e1b8d39..56092dccfdb8 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -783,7 +783,7 @@ static int recover_mce(struct pt_regs *regs, struct machine_check_event *evt)
{
int recovered = 0;
- if (!(regs->msr & MSR_RI)) {
+ if (regs_is_unrecoverable(regs)) {
/* If MSR_RI isn't set, we cannot recover */
pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n");
recovered = 0;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 0dfaa6ab44cc..f79126f16258 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -486,6 +486,8 @@ static void __init pSeries_discover_phbs(void)
/* create pci_dn's for DT nodes under this PHB */
pci_devs_phb_init_dynamic(phb);
+
+ pseries_msi_allocate_domains(phb);
}
of_node_put(root);
diff --git a/arch/powerpc/platforms/pseries/svm.c b/arch/powerpc/platforms/pseries/svm.c
index 1d829e257996..87f001b4c4e4 100644
--- a/arch/powerpc/platforms/pseries/svm.c
+++ b/arch/powerpc/platforms/pseries/svm.c
@@ -63,6 +63,9 @@ void __init svm_swiotlb_init(void)
int set_memory_encrypted(unsigned long addr, int numpages)
{
+ if (!mem_encrypt_active())
+ return 0;
+
if (!PAGE_ALIGNED(addr))
return -EINVAL;
@@ -73,6 +76,9 @@ int set_memory_encrypted(unsigned long addr, int numpages)
int set_memory_decrypted(unsigned long addr, int numpages)
{
+ if (!mem_encrypt_active())
+ return 0;
+
if (!PAGE_ALIGNED(addr))
return -EINVAL;
diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index b5c1cf1bc64d..b043e3936d21 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -184,7 +184,7 @@ static int h_get_nx_fault(u32 winid, u64 buffer)
* Note: The hypervisor forwards an interrupt for each fault request.
* So one fault CRB to process for each H_GET_NX_FAULT hcall.
*/
-irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
+static irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
{
struct pseries_vas_window *txwin = data;
struct coprocessor_request_block crb;
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
index e00f3725ec96..feafcb582e1b 100644
--- a/arch/powerpc/platforms/pseries/vio.c
+++ b/arch/powerpc/platforms/pseries/vio.c
@@ -560,7 +560,8 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
for_each_sg(sglist, sgl, nelems, count)
alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE(tbl));
- if (vio_cmo_alloc(viodev, alloc_size))
+ ret = vio_cmo_alloc(viodev, alloc_size);
+ if (ret)
goto out_fail;
ret = ppc_iommu_map_sg(dev, tbl, sglist, nelems, dma_get_mask(dev),
direction, attrs);
@@ -577,7 +578,7 @@ out_deallocate:
vio_cmo_dealloc(viodev, alloc_size);
out_fail:
atomic_inc(&viodev->cmo.allocs_failed);
- return 0;
+ return ret;
}
static void vio_dma_iommu_unmap_sg(struct device *dev,
@@ -1257,7 +1258,7 @@ static int vio_bus_probe(struct device *dev)
}
/* convert from struct device to struct vio_dev and pass to driver. */
-static int vio_bus_remove(struct device *dev)
+static void vio_bus_remove(struct device *dev)
{
struct vio_dev *viodev = to_vio_dev(dev);
struct vio_driver *viodrv = to_vio_driver(dev->driver);
@@ -1276,7 +1277,6 @@ static int vio_bus_remove(struct device *dev)
vio_cmo_bus_remove(viodev);
put_device(devptr);
- return 0;
}
static void vio_bus_shutdown(struct device *dev)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 5a95b8ea23d8..ff7906b48ca1 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -108,7 +108,7 @@ int fsl_rio_mcheck_exception(struct pt_regs *regs)
__func__);
out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
0);
- regs_set_return_msr(regs, regs->msr | MSR_RI);
+ regs_set_recoverable(regs);
regs_set_return_ip(regs, extable_fixup(entry));
return 1;
}
diff --git a/arch/powerpc/sysdev/xics/ics-native.c b/arch/powerpc/sysdev/xics/ics-native.c
index d450502f4053..dec7d93a8ba1 100644
--- a/arch/powerpc/sysdev/xics/ics-native.c
+++ b/arch/powerpc/sysdev/xics/ics-native.c
@@ -131,19 +131,15 @@ static struct irq_chip ics_native_irq_chip = {
.irq_retrigger = xics_retrigger,
};
-static int ics_native_map(struct ics *ics, unsigned int virq)
+static int ics_native_check(struct ics *ics, unsigned int hw_irq)
{
- unsigned int vec = (unsigned int)virq_to_hw(virq);
struct ics_native *in = to_ics_native(ics);
- pr_devel("%s: vec=0x%x\n", __func__, vec);
+ pr_devel("%s: hw_irq=0x%x\n", __func__, hw_irq);
- if (vec < in->ibase || vec >= (in->ibase + in->icount))
+ if (hw_irq < in->ibase || hw_irq >= (in->ibase + in->icount))
return -EINVAL;
- irq_set_chip_and_handler(virq, &ics_native_irq_chip, handle_fasteoi_irq);
- irq_set_chip_data(virq, ics);
-
return 0;
}
@@ -177,10 +173,11 @@ static int ics_native_host_match(struct ics *ics, struct device_node *node)
}
static struct ics ics_native_template = {
- .map = ics_native_map,
+ .check = ics_native_check,
.mask_unknown = ics_native_mask_unknown,
.get_server = ics_native_get_server,
.host_match = ics_native_host_match,
+ .chip = &ics_native_irq_chip,
};
static int __init ics_native_add_one(struct device_node *np)
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c
index 823f6c9664cd..c4d95d8beb6f 100644
--- a/arch/powerpc/sysdev/xics/ics-opal.c
+++ b/arch/powerpc/sysdev/xics/ics-opal.c
@@ -62,17 +62,6 @@ static void ics_opal_unmask_irq(struct irq_data *d)
static unsigned int ics_opal_startup(struct irq_data *d)
{
-#ifdef CONFIG_PCI_MSI
- /*
- * The generic MSI code returns with the interrupt disabled on the
- * card, using the MSI mask bits. Firmware doesn't appear to unmask
- * at that level, so we do it here by hand.
- */
- if (irq_data_get_msi_desc(d))
- pci_msi_unmask_irq(d);
-#endif
-
- /* unmask it */
ics_opal_unmask_irq(d);
return 0;
}
@@ -133,7 +122,7 @@ static int ics_opal_set_affinity(struct irq_data *d,
}
server = ics_opal_mangle_server(wanted_server);
- pr_devel("ics-hal: set-affinity irq %d [hw 0x%x] server: 0x%x/0x%x\n",
+ pr_debug("ics-hal: set-affinity irq %d [hw 0x%x] server: 0x%x/0x%x\n",
d->irq, hw_irq, wanted_server, server);
rc = opal_set_xive(hw_irq, server, priority);
@@ -157,26 +146,13 @@ static struct irq_chip ics_opal_irq_chip = {
.irq_retrigger = xics_retrigger,
};
-static int ics_opal_map(struct ics *ics, unsigned int virq);
-static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec);
-static long ics_opal_get_server(struct ics *ics, unsigned long vec);
-
static int ics_opal_host_match(struct ics *ics, struct device_node *node)
{
return 1;
}
-/* Only one global & state struct ics */
-static struct ics ics_hal = {
- .map = ics_opal_map,
- .mask_unknown = ics_opal_mask_unknown,
- .get_server = ics_opal_get_server,
- .host_match = ics_opal_host_match,
-};
-
-static int ics_opal_map(struct ics *ics, unsigned int virq)
+static int ics_opal_check(struct ics *ics, unsigned int hw_irq)
{
- unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
int64_t rc;
__be16 server;
int8_t priority;
@@ -189,9 +165,6 @@ static int ics_opal_map(struct ics *ics, unsigned int virq)
if (rc != OPAL_SUCCESS)
return -ENXIO;
- irq_set_chip_and_handler(virq, &ics_opal_irq_chip, handle_fasteoi_irq);
- irq_set_chip_data(virq, &ics_hal);
-
return 0;
}
@@ -222,6 +195,15 @@ static long ics_opal_get_server(struct ics *ics, unsigned long vec)
return ics_opal_unmangle_server(be16_to_cpu(server));
}
+/* Only one global & state struct ics */
+static struct ics ics_hal = {
+ .check = ics_opal_check,
+ .mask_unknown = ics_opal_mask_unknown,
+ .get_server = ics_opal_get_server,
+ .host_match = ics_opal_host_match,
+ .chip = &ics_opal_irq_chip,
+};
+
int __init ics_opal_init(void)
{
if (!firmware_has_feature(FW_FEATURE_OPAL))
diff --git a/arch/powerpc/sysdev/xics/ics-rtas.c b/arch/powerpc/sysdev/xics/ics-rtas.c
index 4cf18000f07c..b9da317b7a2d 100644
--- a/arch/powerpc/sysdev/xics/ics-rtas.c
+++ b/arch/powerpc/sysdev/xics/ics-rtas.c
@@ -24,19 +24,6 @@ static int ibm_set_xive;
static int ibm_int_on;
static int ibm_int_off;
-static int ics_rtas_map(struct ics *ics, unsigned int virq);
-static void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec);
-static long ics_rtas_get_server(struct ics *ics, unsigned long vec);
-static int ics_rtas_host_match(struct ics *ics, struct device_node *node);
-
-/* Only one global & state struct ics */
-static struct ics ics_rtas = {
- .map = ics_rtas_map,
- .mask_unknown = ics_rtas_mask_unknown,
- .get_server = ics_rtas_get_server,
- .host_match = ics_rtas_host_match,
-};
-
static void ics_rtas_unmask_irq(struct irq_data *d)
{
unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
@@ -70,15 +57,6 @@ static void ics_rtas_unmask_irq(struct irq_data *d)
static unsigned int ics_rtas_startup(struct irq_data *d)
{
-#ifdef CONFIG_PCI_MSI
- /*
- * The generic MSI code returns with the interrupt disabled on the
- * card, using the MSI mask bits. Firmware doesn't appear to unmask
- * at that level, so we do it here by hand.
- */
- if (irq_data_get_msi_desc(d))
- pci_msi_unmask_irq(d);
-#endif
/* unmask it */
ics_rtas_unmask_irq(d);
return 0;
@@ -146,6 +124,9 @@ static int ics_rtas_set_affinity(struct irq_data *d,
return -1;
}
+ pr_debug("%s: irq %d [hw 0x%x] server: 0x%x\n", __func__, d->irq,
+ hw_irq, irq_server);
+
status = rtas_call_reentrant(ibm_set_xive, 3, 1, NULL,
hw_irq, irq_server, xics_status[1]);
@@ -169,9 +150,8 @@ static struct irq_chip ics_rtas_irq_chip = {
.irq_retrigger = xics_retrigger,
};
-static int ics_rtas_map(struct ics *ics, unsigned int virq)
+static int ics_rtas_check(struct ics *ics, unsigned int hw_irq)
{
- unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
int status[2];
int rc;
@@ -183,9 +163,6 @@ static int ics_rtas_map(struct ics *ics, unsigned int virq)
if (rc)
return -ENXIO;
- irq_set_chip_and_handler(virq, &ics_rtas_irq_chip, handle_fasteoi_irq);
- irq_set_chip_data(virq, &ics_rtas);
-
return 0;
}
@@ -213,6 +190,15 @@ static int ics_rtas_host_match(struct ics *ics, struct device_node *node)
return !of_device_is_compatible(node, "chrp,iic");
}
+/* Only one global & state struct ics */
+static struct ics ics_rtas = {
+ .check = ics_rtas_check,
+ .mask_unknown = ics_rtas_mask_unknown,
+ .get_server = ics_rtas_get_server,
+ .host_match = ics_rtas_host_match,
+ .chip = &ics_rtas_irq_chip,
+};
+
__init int ics_rtas_init(void)
{
ibm_get_xive = rtas_token("ibm,get-xive");
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
index b14c502e56a8..5c1a157a83b8 100644
--- a/arch/powerpc/sysdev/xics/xics-common.c
+++ b/arch/powerpc/sysdev/xics/xics-common.c
@@ -38,7 +38,7 @@ DEFINE_PER_CPU(struct xics_cppr, xics_cppr);
struct irq_domain *xics_host;
-static LIST_HEAD(ics_list);
+static struct ics *xics_ics;
void xics_update_irq_servers(void)
{
@@ -111,12 +111,11 @@ void xics_setup_cpu(void)
void xics_mask_unknown_vec(unsigned int vec)
{
- struct ics *ics;
-
pr_err("Interrupt 0x%x (real) is invalid, disabling it.\n", vec);
- list_for_each_entry(ics, &ics_list, link)
- ics->mask_unknown(ics, vec);
+ if (WARN_ON(!xics_ics))
+ return;
+ xics_ics->mask_unknown(xics_ics, vec);
}
@@ -133,7 +132,7 @@ static void xics_request_ipi(void)
* IPIs are marked IRQF_PERCPU. The handler was set in map.
*/
BUG_ON(request_irq(ipi, icp_ops->ipi_action,
- IRQF_PERCPU | IRQF_NO_THREAD, "IPI", NULL));
+ IRQF_NO_DEBUG | IRQF_PERCPU | IRQF_NO_THREAD, "IPI", NULL));
}
void __init xics_smp_probe(void)
@@ -184,6 +183,8 @@ void xics_migrate_irqs_away(void)
unsigned int irq, virq;
struct irq_desc *desc;
+ pr_debug("%s: CPU %u\n", __func__, cpu);
+
/* If we used to be the default server, move to the new "boot_cpuid" */
if (hw_cpu == xics_default_server)
xics_update_irq_servers();
@@ -198,7 +199,7 @@ void xics_migrate_irqs_away(void)
struct irq_chip *chip;
long server;
unsigned long flags;
- struct ics *ics;
+ struct irq_data *irqd;
/* We can't set affinity on ISA interrupts */
if (virq < NR_IRQS_LEGACY)
@@ -206,9 +207,11 @@ void xics_migrate_irqs_away(void)
/* We only need to migrate enabled IRQS */
if (!desc->action)
continue;
- if (desc->irq_data.domain != xics_host)
+ /* We need a mapping in the XICS IRQ domain */
+ irqd = irq_domain_get_irq_data(xics_host, virq);
+ if (!irqd)
continue;
- irq = desc->irq_data.hwirq;
+ irq = irqd_to_hwirq(irqd);
/* We need to get IPIs still. */
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
continue;
@@ -219,13 +222,10 @@ void xics_migrate_irqs_away(void)
raw_spin_lock_irqsave(&desc->lock, flags);
/* Locate interrupt server */
- server = -1;
- ics = irq_desc_get_chip_data(desc);
- if (ics)
- server = ics->get_server(ics, irq);
+ server = xics_ics->get_server(xics_ics, irq);
if (server < 0) {
- printk(KERN_ERR "%s: Can't find server for irq %d\n",
- __func__, irq);
+ pr_err("%s: Can't find server for irq %d/%x\n",
+ __func__, virq, irq);
goto unlock;
}
@@ -307,13 +307,9 @@ int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
static int xics_host_match(struct irq_domain *h, struct device_node *node,
enum irq_domain_bus_token bus_token)
{
- struct ics *ics;
-
- list_for_each_entry(ics, &ics_list, link)
- if (ics->host_match(ics, node))
- return 1;
-
- return 0;
+ if (WARN_ON(!xics_ics))
+ return 0;
+ return xics_ics->host_match(xics_ics, node) ? 1 : 0;
}
/* Dummies */
@@ -327,12 +323,10 @@ static struct irq_chip xics_ipi_chip = {
.irq_unmask = xics_ipi_unmask,
};
-static int xics_host_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
+static int xics_host_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq)
{
- struct ics *ics;
-
- pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
+ pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hwirq);
/*
* Mark interrupts as edge sensitive by default so that resend
@@ -342,18 +336,23 @@ static int xics_host_map(struct irq_domain *h, unsigned int virq,
irq_clear_status_flags(virq, IRQ_LEVEL);
/* Don't call into ICS for IPIs */
- if (hw == XICS_IPI) {
+ if (hwirq == XICS_IPI) {
irq_set_chip_and_handler(virq, &xics_ipi_chip,
handle_percpu_irq);
return 0;
}
- /* Let the ICS setup the chip data */
- list_for_each_entry(ics, &ics_list, link)
- if (ics->map(ics, virq) == 0)
- return 0;
+ if (WARN_ON(!xics_ics))
+ return -EINVAL;
+
+ if (xics_ics->check(xics_ics, hwirq))
+ return -EINVAL;
+
+ /* No chip data for the XICS domain */
+ irq_domain_set_info(domain, virq, hwirq, xics_ics->chip,
+ NULL, handle_fasteoi_irq, NULL, NULL);
- return -EINVAL;
+ return 0;
}
static int xics_host_xlate(struct irq_domain *h, struct device_node *ct,
@@ -412,22 +411,76 @@ int xics_retrigger(struct irq_data *data)
return 0;
}
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+static int xics_host_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
+ unsigned long *hwirq, unsigned int *type)
+{
+ return xics_host_xlate(d, to_of_node(fwspec->fwnode), fwspec->param,
+ fwspec->param_count, hwirq, type);
+}
+
+static int xics_host_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ struct irq_fwspec *fwspec = arg;
+ irq_hw_number_t hwirq;
+ unsigned int type = IRQ_TYPE_NONE;
+ int i, rc;
+
+ rc = xics_host_domain_translate(domain, fwspec, &hwirq, &type);
+ if (rc)
+ return rc;
+
+ pr_debug("%s %d/%lx #%d\n", __func__, virq, hwirq, nr_irqs);
+
+ for (i = 0; i < nr_irqs; i++)
+ irq_domain_set_info(domain, virq + i, hwirq + i, xics_ics->chip,
+ xics_ics, handle_fasteoi_irq, NULL, NULL);
+
+ return 0;
+}
+
+static void xics_host_domain_free(struct irq_domain *domain,
+ unsigned int virq, unsigned int nr_irqs)
+{
+ pr_debug("%s %d #%d\n", __func__, virq, nr_irqs);
+}
+#endif
+
static const struct irq_domain_ops xics_host_ops = {
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+ .alloc = xics_host_domain_alloc,
+ .free = xics_host_domain_free,
+ .translate = xics_host_domain_translate,
+#endif
.match = xics_host_match,
.map = xics_host_map,
.xlate = xics_host_xlate,
};
-static void __init xics_init_host(void)
+static int __init xics_allocate_domain(void)
{
- xics_host = irq_domain_add_tree(NULL, &xics_host_ops, NULL);
- BUG_ON(xics_host == NULL);
+ struct fwnode_handle *fn;
+
+ fn = irq_domain_alloc_named_fwnode("XICS");
+ if (!fn)
+ return -ENOMEM;
+
+ xics_host = irq_domain_create_tree(fn, &xics_host_ops, NULL);
+ if (!xics_host) {
+ irq_domain_free_fwnode(fn);
+ return -ENOMEM;
+ }
+
irq_set_default_host(xics_host);
+ return 0;
}
void __init xics_register_ics(struct ics *ics)
{
- list_add(&ics->link, &ics_list);
+ if (WARN_ONCE(xics_ics, "XICS: Source Controller is already defined !"))
+ return;
+ xics_ics = ics;
}
static void __init xics_get_server_size(void)
@@ -484,6 +537,8 @@ void __init xics_init(void)
/* Initialize common bits */
xics_get_server_size();
xics_update_irq_servers();
- xics_init_host();
+ rc = xics_allocate_domain();
+ if (rc < 0)
+ pr_err("XICS: Failed to create IRQ domain");
xics_setup_cpu();
}
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c
index 8183ca343675..c732ce5a3e1a 100644
--- a/arch/powerpc/sysdev/xive/common.c
+++ b/arch/powerpc/sysdev/xive/common.c
@@ -21,7 +21,6 @@
#include <linux/msi.h>
#include <linux/vmalloc.h>
-#include <asm/debugfs.h>
#include <asm/prom.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -313,11 +312,10 @@ void xmon_xive_get_irq_all(void)
struct irq_desc *desc;
for_each_irq_desc(i, desc) {
- struct irq_data *d = irq_desc_get_irq_data(desc);
- unsigned int hwirq = (unsigned int)irqd_to_hwirq(d);
+ struct irq_data *d = irq_domain_get_irq_data(xive_irq_domain, i);
- if (d->domain == xive_irq_domain)
- xmon_xive_get_irq_config(hwirq, d);
+ if (d)
+ xmon_xive_get_irq_config(irqd_to_hwirq(d), d);
}
}
@@ -617,16 +615,6 @@ static unsigned int xive_irq_startup(struct irq_data *d)
pr_devel("xive_irq_startup: irq %d [0x%x] data @%p\n",
d->irq, hw_irq, d);
-#ifdef CONFIG_PCI_MSI
- /*
- * The generic MSI code returns with the interrupt disabled on the
- * card, using the MSI mask bits. Firmware doesn't appear to unmask
- * at that level, so we do it here by hand.
- */
- if (irq_data_get_msi_desc(d))
- pci_msi_unmask_irq(d);
-#endif
-
/* Pick a target */
target = xive_pick_irq_target(d, irq_data_get_affinity_mask(d));
if (target == XIVE_INVALID_TARGET) {
@@ -714,16 +702,12 @@ static int xive_irq_set_affinity(struct irq_data *d,
u32 target, old_target;
int rc = 0;
- pr_devel("xive_irq_set_affinity: irq %d\n", d->irq);
+ pr_debug("%s: irq %d/%x\n", __func__, d->irq, hw_irq);
/* Is this valid ? */
if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids)
return -EINVAL;
- /* Don't do anything if the interrupt isn't started */
- if (!irqd_is_started(d))
- return IRQ_SET_MASK_OK;
-
/*
* If existing target is already in the new mask, and is
* online then do nothing.
@@ -759,7 +743,7 @@ static int xive_irq_set_affinity(struct irq_data *d,
return rc;
}
- pr_devel(" target: 0x%x\n", target);
+ pr_debug(" target: 0x%x\n", target);
xd->target = target;
/* Give up previous target */
@@ -990,6 +974,8 @@ EXPORT_SYMBOL_GPL(is_xive_irq);
void xive_cleanup_irq_data(struct xive_irq_data *xd)
{
+ pr_debug("%s for HW %x\n", __func__, xd->hw_irq);
+
if (xd->eoi_mmio) {
iounmap(xd->eoi_mmio);
if (xd->eoi_mmio == xd->trig_mmio)
@@ -1031,7 +1017,7 @@ static int xive_irq_alloc_data(unsigned int virq, irq_hw_number_t hw)
return 0;
}
-static void xive_irq_free_data(unsigned int virq)
+void xive_irq_free_data(unsigned int virq)
{
struct xive_irq_data *xd = irq_get_handler_data(virq);
@@ -1041,6 +1027,7 @@ static void xive_irq_free_data(unsigned int virq)
xive_cleanup_irq_data(xd);
kfree(xd);
}
+EXPORT_SYMBOL_GPL(xive_irq_free_data);
#ifdef CONFIG_SMP
@@ -1179,7 +1166,7 @@ static int xive_request_ipi(unsigned int cpu)
return 0;
ret = request_irq(xid->irq, xive_muxed_ipi_action,
- IRQF_PERCPU | IRQF_NO_THREAD,
+ IRQF_NO_DEBUG | IRQF_PERCPU | IRQF_NO_THREAD,
xid->name, NULL);
WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
@@ -1379,7 +1366,71 @@ static void xive_irq_domain_debug_show(struct seq_file *m, struct irq_domain *d,
}
#endif
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+static int xive_irq_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
+{
+ return xive_irq_domain_xlate(d, to_of_node(fwspec->fwnode),
+ fwspec->param, fwspec->param_count,
+ hwirq, type);
+}
+
+static int xive_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ struct irq_fwspec *fwspec = arg;
+ irq_hw_number_t hwirq;
+ unsigned int type = IRQ_TYPE_NONE;
+ int i, rc;
+
+ rc = xive_irq_domain_translate(domain, fwspec, &hwirq, &type);
+ if (rc)
+ return rc;
+
+ pr_debug("%s %d/%lx #%d\n", __func__, virq, hwirq, nr_irqs);
+
+ for (i = 0; i < nr_irqs; i++) {
+ /* TODO: call xive_irq_domain_map() */
+
+ /*
+ * Mark interrupts as edge sensitive by default so that resend
+ * actually works. Will fix that up below if needed.
+ */
+ irq_clear_status_flags(virq, IRQ_LEVEL);
+
+ /* allocates and sets handler data */
+ rc = xive_irq_alloc_data(virq + i, hwirq + i);
+ if (rc)
+ return rc;
+
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &xive_irq_chip, domain->host_data);
+ irq_set_handler(virq + i, handle_fasteoi_irq);
+ }
+
+ return 0;
+}
+
+static void xive_irq_domain_free(struct irq_domain *domain,
+ unsigned int virq, unsigned int nr_irqs)
+{
+ int i;
+
+ pr_debug("%s %d #%d\n", __func__, virq, nr_irqs);
+
+ for (i = 0; i < nr_irqs; i++)
+ xive_irq_free_data(virq + i);
+}
+#endif
+
static const struct irq_domain_ops xive_irq_domain_ops = {
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+ .alloc = xive_irq_domain_alloc,
+ .free = xive_irq_domain_free,
+ .translate = xive_irq_domain_translate,
+#endif
.match = xive_irq_domain_match,
.map = xive_irq_domain_map,
.unmap = xive_irq_domain_unmap,
@@ -1717,9 +1768,9 @@ static int xive_core_debug_show(struct seq_file *m, void *private)
xive_debug_show_cpu(m, cpu);
for_each_irq_desc(i, desc) {
- struct irq_data *d = irq_desc_get_irq_data(desc);
+ struct irq_data *d = irq_domain_get_irq_data(xive_irq_domain, i);
- if (d->domain == xive_irq_domain)
+ if (d)
xive_debug_show_irq(m, d);
}
return 0;
@@ -1729,7 +1780,7 @@ DEFINE_SHOW_ATTRIBUTE(xive_core_debug);
int xive_core_debug_init(void)
{
if (xive_enabled())
- debugfs_create_file("xive", 0400, powerpc_debugfs_root,
+ debugfs_create_file("xive", 0400, arch_debugfs_dir,
NULL, &xive_core_debug_fops);
return 0;
}
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c
index 57e3f1540435..1aec282cd650 100644
--- a/arch/powerpc/sysdev/xive/native.c
+++ b/arch/powerpc/sysdev/xive/native.c
@@ -41,6 +41,7 @@ static u32 xive_queue_shift;
static u32 xive_pool_vps = XIVE_INVALID_VP;
static struct kmem_cache *xive_provision_cache;
static bool xive_has_single_esc;
+static bool xive_has_save_restore;
int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data)
{
@@ -588,6 +589,9 @@ bool __init xive_native_init(void)
if (of_get_property(np, "single-escalation-support", NULL) != NULL)
xive_has_single_esc = true;
+ if (of_get_property(np, "vp-save-restore", NULL))
+ xive_has_save_restore = true;
+
/* Configure Thread Management areas for KVM */
for_each_possible_cpu(cpu)
kvmppc_set_xive_tima(cpu, r.start, tima);
@@ -752,6 +756,12 @@ bool xive_native_has_single_escalation(void)
}
EXPORT_SYMBOL_GPL(xive_native_has_single_escalation);
+bool xive_native_has_save_restore(void)
+{
+ return xive_has_save_restore;
+}
+EXPORT_SYMBOL_GPL(xive_native_has_save_restore);
+
int xive_native_get_queue_info(u32 vp_id, u32 prio,
u64 *out_qpage,
u64 *out_qsize,
diff --git a/arch/powerpc/tools/head_check.sh b/arch/powerpc/tools/head_check.sh
index e32d3162e5ed..689907cda996 100644
--- a/arch/powerpc/tools/head_check.sh
+++ b/arch/powerpc/tools/head_check.sh
@@ -49,30 +49,30 @@ vmlinux="$2"
$nm "$vmlinux" | grep -e " [TA] _stext$" -e " t start_first_256B$" -e " a text_start$" -e " t start_text$" > .tmp_symbols.txt
-vma=$(cat .tmp_symbols.txt | grep -e " [TA] _stext$" | cut -d' ' -f1)
+vma=$(grep -e " [TA] _stext$" .tmp_symbols.txt | cut -d' ' -f1)
-expected_start_head_addr=$vma
+expected_start_head_addr="$vma"
-start_head_addr=$(cat .tmp_symbols.txt | grep " t start_first_256B$" | cut -d' ' -f1)
+start_head_addr=$(grep " t start_first_256B$" .tmp_symbols.txt | cut -d' ' -f1)
if [ "$start_head_addr" != "$expected_start_head_addr" ]; then
- echo "ERROR: head code starts at $start_head_addr, should be $expected_start_head_addr"
- echo "ERROR: try to enable LD_HEAD_STUB_CATCH config option"
- echo "ERROR: see comments in arch/powerpc/tools/head_check.sh"
+ echo "ERROR: head code starts at $start_head_addr, should be $expected_start_head_addr" 1>&2
+ echo "ERROR: try to enable LD_HEAD_STUB_CATCH config option" 1>&2
+ echo "ERROR: see comments in arch/powerpc/tools/head_check.sh" 1>&2
exit 1
fi
-top_vma=$(echo $vma | cut -d'0' -f1)
+top_vma=$(echo "$vma" | cut -d'0' -f1)
-expected_start_text_addr=$(cat .tmp_symbols.txt | grep " a text_start$" | cut -d' ' -f1 | sed "s/^0/$top_vma/")
+expected_start_text_addr=$(grep " a text_start$" .tmp_symbols.txt | cut -d' ' -f1 | sed "s/^0/$top_vma/")
-start_text_addr=$(cat .tmp_symbols.txt | grep " t start_text$" | cut -d' ' -f1)
+start_text_addr=$(grep " t start_text$" .tmp_symbols.txt | cut -d' ' -f1)
if [ "$start_text_addr" != "$expected_start_text_addr" ]; then
- echo "ERROR: start_text address is $start_text_addr, should be $expected_start_text_addr"
- echo "ERROR: try to enable LD_HEAD_STUB_CATCH config option"
- echo "ERROR: see comments in arch/powerpc/tools/head_check.sh"
+ echo "ERROR: start_text address is $start_text_addr, should be $expected_start_text_addr" 1>&2
+ echo "ERROR: try to enable LD_HEAD_STUB_CATCH config option" 1>&2
+ echo "ERROR: see comments in arch/powerpc/tools/head_check.sh" 1>&2
exit 1
fi
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index da4d7f225a40..dd8241c009e5 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -26,8 +26,8 @@
#include <linux/ctype.h>
#include <linux/highmem.h>
#include <linux/security.h>
+#include <linux/debugfs.h>
-#include <asm/debugfs.h>
#include <asm/ptrace.h>
#include <asm/smp.h>
#include <asm/string.h>
@@ -482,16 +482,6 @@ static inline void get_output_lock(void) {}
static inline void release_output_lock(void) {}
#endif
-static inline int unrecoverable_excp(struct pt_regs *regs)
-{
-#if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
- /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
- return 0;
-#else
- return ((regs->msr & MSR_RI) == 0);
-#endif
-}
-
static void xmon_touch_watchdogs(void)
{
touch_softlockup_watchdog_sync();
@@ -565,7 +555,7 @@ static int xmon_core(struct pt_regs *regs, volatile int fromipi)
bp = NULL;
if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
bp = at_breakpoint(regs->nip);
- if (bp || unrecoverable_excp(regs))
+ if (bp || regs_is_unrecoverable(regs))
fromipi = 0;
if (!fromipi) {
@@ -577,7 +567,7 @@ static int xmon_core(struct pt_regs *regs, volatile int fromipi)
cpu, BP_NUM(bp));
xmon_print_symbol(regs->nip, " ", ")\n");
}
- if (unrecoverable_excp(regs))
+ if (regs_is_unrecoverable(regs))
printf("WARNING: exception is not recoverable, "
"can't continue\n");
release_output_lock();
@@ -693,7 +683,7 @@ static int xmon_core(struct pt_regs *regs, volatile int fromipi)
printf("Stopped at breakpoint %tx (", BP_NUM(bp));
xmon_print_symbol(regs->nip, " ", ")\n");
}
- if (unrecoverable_excp(regs))
+ if (regs_is_unrecoverable(regs))
printf("WARNING: exception is not recoverable, "
"can't continue\n");
remove_bpts();
@@ -4077,8 +4067,8 @@ DEFINE_SIMPLE_ATTRIBUTE(xmon_dbgfs_ops, xmon_dbgfs_get,
static int __init setup_xmon_dbgfs(void)
{
- debugfs_create_file("xmon", 0600, powerpc_debugfs_root, NULL,
- &xmon_dbgfs_ops);
+ debugfs_create_file("xmon", 0600, arch_debugfs_dir, NULL,
+ &xmon_dbgfs_ops);
return 0;
}
device_initcall(setup_xmon_dbgfs);
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 4f7b70ae7c31..aac669a6c3d8 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -13,9 +13,7 @@ config 32BIT
config RISCV
def_bool y
select ARCH_CLOCKSOURCE_INIT
- select ARCH_SUPPORTS_ATOMIC_RMW
- select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
- select ARCH_STACKWALK
+ select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
select ARCH_HAS_BINFMT_FLAT
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_VIRTUAL if MMU
@@ -31,8 +29,12 @@ config RISCV
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
+ select ARCH_HAS_UBSAN_SANITIZE_ALL
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
+ select ARCH_STACKWALK
+ select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
select ARCH_SUPPORTS_HUGETLBFS if MMU
select ARCH_USE_MEMTEST
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
@@ -48,16 +50,16 @@ config RISCV
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_EARLY_IOREMAP
select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
+ select GENERIC_IDLE_POLL_SETUP
select GENERIC_IOREMAP
select GENERIC_IRQ_MULTI_HANDLER
select GENERIC_IRQ_SHOW
+ select GENERIC_IRQ_SHOW_LEVEL
select GENERIC_LIB_DEVMEM_IS_ALLOWED
select GENERIC_PCI_IOMAP
select GENERIC_PTDUMP if MMU
select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_STRNCPY_FROM_USER if MMU
- select GENERIC_STRNLEN_USER if MMU
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
select HANDLE_DOMAIN_IRQ
select HAVE_ARCH_AUDITSYSCALL
@@ -72,6 +74,7 @@ config RISCV
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU
+ select HAVE_ARCH_THREAD_STRUCT_WHITELIST
select HAVE_ARCH_VMAP_STACK if MMU && 64BIT
select HAVE_ASM_MODVERSIONS
select HAVE_CONTEXT_TRACKING
@@ -97,6 +100,7 @@ config RISCV
select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select IRQ_DOMAIN
+ select IRQ_FORCED_THREADING
select MODULES_USE_ELF_RELA if MODULES
select MODULE_SECTIONS if MODULES
select OF
@@ -109,6 +113,7 @@ config RISCV
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
+ select TRACE_IRQFLAGS_SUPPORT
select UACCESS_MEMCPY if !MMU
select ZONE_DMA32 if 64BIT
@@ -178,9 +183,6 @@ config ARCH_SUPPORTS_UPROBES
config STACKTRACE_SUPPORT
def_bool y
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config GENERIC_BUG
def_bool y
depends on BUG
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index bc74afdbf31e..01906a90c501 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -41,7 +41,7 @@ endif
ifeq ($(CONFIG_LD_IS_LLD),y)
KBUILD_CFLAGS += -mno-relax
KBUILD_AFLAGS += -mno-relax
-ifneq ($(LLVM_IAS),1)
+ifndef CONFIG_AS_IS_LLVM
KBUILD_CFLAGS += -Wa,-mno-relax
KBUILD_AFLAGS += -Wa,-mno-relax
endif
@@ -108,6 +108,12 @@ PHONY += vdso_install
vdso_install:
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
+ifeq ($(CONFIG_MMU),y)
+prepare: vdso_prepare
+vdso_prepare: prepare0
+ $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
+endif
+
ifneq ($(CONFIG_XIP_KERNEL),y)
ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy)
KBUILD_IMAGE := $(boot)/loader.bin
diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h
index 7b3483ba2e84..49b398fe99f1 100644
--- a/arch/riscv/include/asm/efi.h
+++ b/arch/riscv/include/asm/efi.h
@@ -13,6 +13,7 @@
#ifdef CONFIG_EFI
extern void efi_init(void);
+extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
#else
#define efi_init()
#endif
@@ -39,10 +40,6 @@ static inline void free_screen_info(struct screen_info *si)
{
}
-static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
-{
-}
-
void efi_virtmap_load(void);
void efi_virtmap_unload(void);
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
index b0ca5058e7ae..109c97e991a6 100644
--- a/arch/riscv/include/asm/page.h
+++ b/arch/riscv/include/asm/page.h
@@ -79,8 +79,8 @@ typedef struct page *pgtable_t;
#endif
#ifdef CONFIG_MMU
-extern unsigned long pfn_base;
-#define ARCH_PFN_OFFSET (pfn_base)
+extern unsigned long riscv_pfn_base;
+#define ARCH_PFN_OFFSET (riscv_pfn_base)
#else
#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#endif /* CONFIG_MMU */
@@ -91,10 +91,8 @@ struct kernel_mapping {
uintptr_t size;
/* Offset between linear mapping virtual address and kernel load address */
unsigned long va_pa_offset;
-#ifdef CONFIG_64BIT
/* Offset between kernel mapping virtual address and kernel load address */
unsigned long va_kernel_pa_offset;
-#endif
unsigned long va_kernel_xip_pa_offset;
#ifdef CONFIG_XIP_KERNEL
uintptr_t xiprom;
@@ -105,11 +103,11 @@ struct kernel_mapping {
extern struct kernel_mapping kernel_map;
extern phys_addr_t phys_ram_base;
-#ifdef CONFIG_64BIT
#define is_kernel_mapping(x) \
((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size))
+
#define is_linear_mapping(x) \
- ((x) >= PAGE_OFFSET && (x) < kernel_map.virt_addr)
+ ((x) >= PAGE_OFFSET && (!IS_ENABLED(CONFIG_64BIT) || (x) < kernel_map.virt_addr))
#define linear_mapping_pa_to_va(x) ((void *)((unsigned long)(x) + kernel_map.va_pa_offset))
#define kernel_mapping_pa_to_va(y) ({ \
@@ -123,7 +121,7 @@ extern phys_addr_t phys_ram_base;
#define linear_mapping_va_to_pa(x) ((unsigned long)(x) - kernel_map.va_pa_offset)
#define kernel_mapping_va_to_pa(y) ({ \
unsigned long _y = y; \
- (_y < kernel_map.virt_addr + XIP_OFFSET) ? \
+ (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \
((unsigned long)(_y) - kernel_map.va_kernel_xip_pa_offset) : \
((unsigned long)(_y) - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \
})
@@ -133,15 +131,6 @@ extern phys_addr_t phys_ram_base;
is_linear_mapping(_x) ? \
linear_mapping_va_to_pa(_x) : kernel_mapping_va_to_pa(_x); \
})
-#else
-#define is_kernel_mapping(x) \
- ((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size))
-#define is_linear_mapping(x) \
- ((x) >= PAGE_OFFSET)
-
-#define __pa_to_va_nodebug(x) ((void *)((unsigned long) (x) + kernel_map.va_pa_offset))
-#define __va_to_pa_nodebug(x) ((unsigned long)(x) - kernel_map.va_pa_offset)
-#endif /* CONFIG_64BIT */
#ifdef CONFIG_DEBUG_VIRTUAL
extern phys_addr_t __virt_to_phys(unsigned long x);
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 021ed64ee608..46b492c78cbb 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -37,6 +37,14 @@ struct thread_struct {
unsigned long bad_cause;
};
+/* Whitelist the fstate from the task_struct for hardened usercopy */
+static inline void arch_thread_struct_whitelist(unsigned long *offset,
+ unsigned long *size)
+{
+ *offset = offsetof(struct thread_struct, fstate);
+ *size = sizeof_field(struct thread_struct, fstate);
+}
+
#define INIT_THREAD { \
.sp = sizeof(init_stack) + (long)&init_stack, \
}
diff --git a/arch/riscv/include/asm/vdso.h b/arch/riscv/include/asm/vdso.h
index 1453a2f563bc..893e47195e30 100644
--- a/arch/riscv/include/asm/vdso.h
+++ b/arch/riscv/include/asm/vdso.h
@@ -8,26 +8,25 @@
#ifndef _ASM_RISCV_VDSO_H
#define _ASM_RISCV_VDSO_H
+
+/*
+ * All systems with an MMU have a VDSO, but systems without an MMU don't
+ * support shared libraries and therefor don't have one.
+ */
+#ifdef CONFIG_MMU
+
#include <linux/types.h>
+#include <generated/vdso-offsets.h>
#ifndef CONFIG_GENERIC_TIME_VSYSCALL
struct vdso_data {
};
#endif
-/*
- * The VDSO symbols are mapped into Linux so we can just use regular symbol
- * addressing to get their offsets in userspace. The symbols are mapped at an
- * offset of 0, but since the linker must support setting weak undefined
- * symbols to the absolute address 0 it also happens to support other low
- * addresses even when the code model suggests those low addresses would not
- * otherwise be availiable.
- */
#define VDSO_SYMBOL(base, name) \
-({ \
- extern const char __vdso_##name[]; \
- (void __user *)((unsigned long)(base) + __vdso_##name); \
-})
+ (void __user *)((unsigned long)(base) + __vdso_##name##_offset)
+
+#endif /* CONFIG_MMU */
asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t);
diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
index 0ed043acc882..64f6183b4717 100644
--- a/arch/riscv/kernel/probes/decode-insn.c
+++ b/arch/riscv/kernel/probes/decode-insn.c
@@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
RISCV_INSN_REJECTED(c_ebreak, insn);
#endif
- RISCV_INSN_REJECTED(auipc, insn);
- RISCV_INSN_REJECTED(branch, insn);
-
RISCV_INSN_SET_SIMULATE(jal, insn);
RISCV_INSN_SET_SIMULATE(jalr, insn);
+ RISCV_INSN_SET_SIMULATE(auipc, insn);
+ RISCV_INSN_SET_SIMULATE(branch, insn);
return INSN_GOOD;
}
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index 2519ce26377d..d73e96f6ed7c 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -83,3 +83,115 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
return ret;
}
+
+#define auipc_rd_idx(opcode) \
+ ((opcode >> 7) & 0x1f)
+
+#define auipc_imm(opcode) \
+ ((((opcode) >> 12) & 0xfffff) << 12)
+
+#if __riscv_xlen == 64
+#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31)
+#elif __riscv_xlen == 32
+#define auipc_offset(opcode) auipc_imm(opcode)
+#else
+#error "Unexpected __riscv_xlen"
+#endif
+
+bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ /*
+ * auipc instruction:
+ * 31 12 11 7 6 0
+ * | imm[31:12] | rd | opcode |
+ * 20 5 7
+ */
+
+ u32 rd_idx = auipc_rd_idx(opcode);
+ unsigned long rd_val = addr + auipc_offset(opcode);
+
+ if (!rv_insn_reg_set_val(regs, rd_idx, rd_val))
+ return false;
+
+ instruction_pointer_set(regs, addr + 4);
+
+ return true;
+}
+
+#define branch_rs1_idx(opcode) \
+ (((opcode) >> 15) & 0x1f)
+
+#define branch_rs2_idx(opcode) \
+ (((opcode) >> 20) & 0x1f)
+
+#define branch_funct3(opcode) \
+ (((opcode) >> 12) & 0x7)
+
+#define branch_imm(opcode) \
+ (((((opcode) >> 8) & 0xf ) << 1) | \
+ ((((opcode) >> 25) & 0x3f) << 5) | \
+ ((((opcode) >> 7) & 0x1 ) << 11) | \
+ ((((opcode) >> 31) & 0x1 ) << 12))
+
+#define branch_offset(opcode) \
+ sign_extend32((branch_imm(opcode)), 12)
+
+#define BRANCH_BEQ 0x0
+#define BRANCH_BNE 0x1
+#define BRANCH_BLT 0x4
+#define BRANCH_BGE 0x5
+#define BRANCH_BLTU 0x6
+#define BRANCH_BGEU 0x7
+
+bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ /*
+ * branch instructions:
+ * 31 30 25 24 20 19 15 14 12 11 8 7 6 0
+ * | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
+ * 1 6 5 5 3 4 1 7
+ * imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 BEQ
+ * imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 BNE
+ * imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 BLT
+ * imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 BGE
+ * imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 BLTU
+ * imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 BGEU
+ */
+
+ s32 offset;
+ s32 offset_tmp;
+ unsigned long rs1_val;
+ unsigned long rs2_val;
+
+ if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
+ !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
+ return false;
+
+ offset_tmp = branch_offset(opcode);
+ switch (branch_funct3(opcode)) {
+ case BRANCH_BEQ:
+ offset = (rs1_val == rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BNE:
+ offset = (rs1_val != rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BLT:
+ offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BGE:
+ offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BLTU:
+ offset = (rs1_val < rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BGEU:
+ offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
+ break;
+ default:
+ return false;
+ }
+
+ instruction_pointer_set(regs, addr + offset);
+
+ return true;
+}
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 120b2f6f71bc..b9620e5f00ba 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -255,7 +255,7 @@ static void __init parse_dtb(void)
pr_err("No DTB passed to the kernel\n");
#ifdef CONFIG_CMDLINE_FORCE
- strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+ strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
pr_info("Forcing kernel command line to: %s\n", boot_command_line);
#endif
}
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
index 24d936c147cd..f2e065671e4d 100644
--- a/arch/riscv/kernel/vdso/Makefile
+++ b/arch/riscv/kernel/vdso/Makefile
@@ -23,10 +23,10 @@ ifneq ($(c-gettimeofday-y),)
endif
# Build rules
-targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-syms.S
+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds
obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
-obj-y += vdso.o vdso-syms.o
+obj-y += vdso.o
CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
# Disable -pg to prevent insert call site
@@ -36,6 +36,7 @@ CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os
GCOV_PROFILE := n
KCOV_INSTRUMENT := n
KASAN_SANITIZE := n
+UBSAN_SANITIZE := n
# Force dependency
$(obj)/vdso.o: $(obj)/vdso.so
@@ -43,20 +44,22 @@ $(obj)/vdso.o: $(obj)/vdso.so
# link rule for the .so file, .lds has to be first
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
$(call if_changed,vdsold)
-LDFLAGS_vdso.so.dbg = -shared -s -soname=linux-vdso.so.1 \
+LDFLAGS_vdso.so.dbg = -shared -S -soname=linux-vdso.so.1 \
--build-id=sha1 --hash-style=both --eh-frame-hdr
-# We also create a special relocatable object that should mirror the symbol
-# table and layout of the linked DSO. With ld --just-symbols we can then
-# refer to these symbols in the kernel code rather than hand-coded addresses.
-$(obj)/vdso-syms.S: $(obj)/vdso.so FORCE
- $(call if_changed,so2s)
-
# strip rule for the .so file
$(obj)/%.so: OBJCOPYFLAGS := -S
$(obj)/%.so: $(obj)/%.so.dbg FORCE
$(call if_changed,objcopy)
+# Generate VDSO offsets using helper script
+gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+ cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
+
+include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
+ $(call if_changed,vdsosym)
+
# actual build commands
# The DSO images are built using a special linker script
# Make sure only to export the intended __vdso_xxx symbol offsets.
@@ -65,11 +68,6 @@ quiet_cmd_vdsold = VDSOLD $@
$(OBJCOPY) $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
rm $@.tmp
-# Extracts symbol offsets from the VDSO, converting them into an assembly file
-# that contains the same symbols at the same offsets.
-quiet_cmd_so2s = SO2S $@
- cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@
-
# install commands for the unstripped file
quiet_cmd_vdso_install = INSTALL $@
cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
diff --git a/arch/riscv/kernel/vdso/gen_vdso_offsets.sh b/arch/riscv/kernel/vdso/gen_vdso_offsets.sh
new file mode 100755
index 000000000000..c2e5613f3495
--- /dev/null
+++ b/arch/riscv/kernel/vdso/gen_vdso_offsets.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+LC_ALL=C
+sed -n -e 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define \2_offset\t0x\1/p'
diff --git a/arch/riscv/kernel/vdso/so2s.sh b/arch/riscv/kernel/vdso/so2s.sh
deleted file mode 100755
index e64cb6d9440e..000000000000
--- a/arch/riscv/kernel/vdso/so2s.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0+
-# Copyright 2020 Palmer Dabbelt <palmerdabbelt@google.com>
-
-sed 's!\([0-9a-f]*\) T \([a-z0-9_]*\)\(@@LINUX_4.15\)*!.global \2\n.set \2,0x\1!' \
-| grep '^\.'
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 7cb4f391d106..c0cddf0fc22d 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -19,6 +19,7 @@
#include <linux/set_memory.h>
#include <linux/dma-map-ops.h>
#include <linux/crash_dump.h>
+#include <linux/hugetlb.h>
#include <asm/fixmap.h>
#include <asm/tlbflush.h>
@@ -222,6 +223,8 @@ static void __init setup_bootmem(void)
early_init_fdt_scan_reserved_mem();
dma_contiguous_reserve(dma32_phys_limit);
+ if (IS_ENABLED(CONFIG_64BIT))
+ hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT);
memblock_allow_resize();
}
@@ -234,14 +237,15 @@ static struct pt_alloc_ops _pt_ops __initdata;
#define pt_ops _pt_ops
#endif
-unsigned long pfn_base __ro_after_init;
-EXPORT_SYMBOL(pfn_base);
+unsigned long riscv_pfn_base __ro_after_init;
+EXPORT_SYMBOL(riscv_pfn_base);
pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
+static pmd_t __maybe_unused early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
#ifdef CONFIG_XIP_KERNEL
#define trampoline_pg_dir ((pgd_t *)XIP_FIXUP(trampoline_pg_dir))
@@ -322,7 +326,6 @@ static void __init create_pte_mapping(pte_t *ptep,
static pmd_t trampoline_pmd[PTRS_PER_PMD] __page_aligned_bss;
static pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss;
static pmd_t early_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
-static pmd_t early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
#ifdef CONFIG_XIP_KERNEL
#define trampoline_pmd ((pmd_t *)XIP_FIXUP(trampoline_pmd))
@@ -408,6 +411,7 @@ static void __init create_pmd_mapping(pmd_t *pmdp,
#define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \
create_pte_mapping(__nextp, __va, __pa, __sz, __prot)
#define fixmap_pgd_next fixmap_pte
+#define create_pmd_mapping(__pmdp, __va, __pa, __sz, __prot)
#endif
void __init create_pgd_mapping(pgd_t *pgdp,
@@ -515,49 +519,80 @@ static __init pgprot_t pgprot_from_va(uintptr_t va)
#endif
#ifdef CONFIG_XIP_KERNEL
-static void __init create_kernel_page_table(pgd_t *pgdir, uintptr_t map_size,
+static void __init create_kernel_page_table(pgd_t *pgdir,
__always_unused bool early)
{
uintptr_t va, end_va;
/* Map the flash resident part */
end_va = kernel_map.virt_addr + kernel_map.xiprom_sz;
- for (va = kernel_map.virt_addr; va < end_va; va += map_size)
+ for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE)
create_pgd_mapping(pgdir, va,
kernel_map.xiprom + (va - kernel_map.virt_addr),
- map_size, PAGE_KERNEL_EXEC);
+ PMD_SIZE, PAGE_KERNEL_EXEC);
/* Map the data in RAM */
end_va = kernel_map.virt_addr + XIP_OFFSET + kernel_map.size;
- for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += map_size)
+ for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += PMD_SIZE)
create_pgd_mapping(pgdir, va,
kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)),
- map_size, PAGE_KERNEL);
+ PMD_SIZE, PAGE_KERNEL);
}
#else
-static void __init create_kernel_page_table(pgd_t *pgdir, uintptr_t map_size,
- bool early)
+static void __init create_kernel_page_table(pgd_t *pgdir, bool early)
{
uintptr_t va, end_va;
end_va = kernel_map.virt_addr + kernel_map.size;
- for (va = kernel_map.virt_addr; va < end_va; va += map_size)
+ for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE)
create_pgd_mapping(pgdir, va,
kernel_map.phys_addr + (va - kernel_map.virt_addr),
- map_size,
+ PMD_SIZE,
early ?
PAGE_KERNEL_EXEC : pgprot_from_va(va));
}
#endif
-asmlinkage void __init setup_vm(uintptr_t dtb_pa)
+/*
+ * Setup a 4MB mapping that encompasses the device tree: for 64-bit kernel,
+ * this means 2 PMD entries whereas for 32-bit kernel, this is only 1 PGDIR
+ * entry.
+ */
+static void __init create_fdt_early_page_table(pgd_t *pgdir, uintptr_t dtb_pa)
{
- uintptr_t __maybe_unused pa;
- uintptr_t map_size;
-#ifndef __PAGETABLE_PMD_FOLDED
- pmd_t fix_bmap_spmd, fix_bmap_epmd;
+#ifndef CONFIG_BUILTIN_DTB
+ uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1);
+
+ create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
+ IS_ENABLED(CONFIG_64BIT) ? (uintptr_t)early_dtb_pmd : pa,
+ PGDIR_SIZE,
+ IS_ENABLED(CONFIG_64BIT) ? PAGE_TABLE : PAGE_KERNEL);
+
+ if (IS_ENABLED(CONFIG_64BIT)) {
+ create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA,
+ pa, PMD_SIZE, PAGE_KERNEL);
+ create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE,
+ pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL);
+ }
+
+ dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1));
+#else
+ /*
+ * For 64-bit kernel, __va can't be used since it would return a linear
+ * mapping address whereas dtb_early_va will be used before
+ * setup_vm_final installs the linear mapping. For 32-bit kernel, as the
+ * kernel is mapped in the linear mapping, that makes no difference.
+ */
+ dtb_early_va = kernel_mapping_pa_to_va(XIP_FIXUP(dtb_pa));
#endif
+ dtb_early_pa = dtb_pa;
+}
+
+asmlinkage void __init setup_vm(uintptr_t dtb_pa)
+{
+ pmd_t __maybe_unused fix_bmap_spmd, fix_bmap_epmd;
+
kernel_map.virt_addr = KERNEL_LINK_ADDR;
#ifdef CONFIG_XIP_KERNEL
@@ -573,23 +608,14 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
kernel_map.phys_addr = (uintptr_t)(&_start);
kernel_map.size = (uintptr_t)(&_end) - kernel_map.phys_addr;
#endif
-
kernel_map.va_pa_offset = PAGE_OFFSET - kernel_map.phys_addr;
-#ifdef CONFIG_64BIT
kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr;
-#endif
-
- pfn_base = PFN_DOWN(kernel_map.phys_addr);
- /*
- * Enforce boot alignment requirements of RV32 and
- * RV64 by only allowing PMD or PGD mappings.
- */
- map_size = PMD_SIZE;
+ riscv_pfn_base = PFN_DOWN(kernel_map.phys_addr);
/* Sanity check alignment and size */
BUG_ON((PAGE_OFFSET % PGDIR_SIZE) != 0);
- BUG_ON((kernel_map.phys_addr % map_size) != 0);
+ BUG_ON((kernel_map.phys_addr % PMD_SIZE) != 0);
#ifdef CONFIG_64BIT
/*
@@ -634,50 +660,10 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
* us to reach paging_init(). We map all memory banks later
* in setup_vm_final() below.
*/
- create_kernel_page_table(early_pg_dir, map_size, true);
+ create_kernel_page_table(early_pg_dir, true);
-#ifndef __PAGETABLE_PMD_FOLDED
- /* Setup early PMD for DTB */
- create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
- (uintptr_t)early_dtb_pmd, PGDIR_SIZE, PAGE_TABLE);
-#ifndef CONFIG_BUILTIN_DTB
- /* Create two consecutive PMD mappings for FDT early scan */
- pa = dtb_pa & ~(PMD_SIZE - 1);
- create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA,
- pa, PMD_SIZE, PAGE_KERNEL);
- create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE,
- pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL);
- dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1));
-#else /* CONFIG_BUILTIN_DTB */
-#ifdef CONFIG_64BIT
- /*
- * __va can't be used since it would return a linear mapping address
- * whereas dtb_early_va will be used before setup_vm_final installs
- * the linear mapping.
- */
- dtb_early_va = kernel_mapping_pa_to_va(XIP_FIXUP(dtb_pa));
-#else
- dtb_early_va = __va(dtb_pa);
-#endif /* CONFIG_64BIT */
-#endif /* CONFIG_BUILTIN_DTB */
-#else
-#ifndef CONFIG_BUILTIN_DTB
- /* Create two consecutive PGD mappings for FDT early scan */
- pa = dtb_pa & ~(PGDIR_SIZE - 1);
- create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
- pa, PGDIR_SIZE, PAGE_KERNEL);
- create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA + PGDIR_SIZE,
- pa + PGDIR_SIZE, PGDIR_SIZE, PAGE_KERNEL);
- dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PGDIR_SIZE - 1));
-#else /* CONFIG_BUILTIN_DTB */
-#ifdef CONFIG_64BIT
- dtb_early_va = kernel_mapping_pa_to_va(XIP_FIXUP(dtb_pa));
-#else
- dtb_early_va = __va(dtb_pa);
-#endif /* CONFIG_64BIT */
-#endif /* CONFIG_BUILTIN_DTB */
-#endif
- dtb_early_pa = dtb_pa;
+ /* Setup early mapping for FDT early scan */
+ create_fdt_early_page_table(early_pg_dir, dtb_pa);
/*
* Bootime fixmap only can handle PMD_SIZE mapping. Thus, boot-ioremap
@@ -752,7 +738,7 @@ static void __init setup_vm_final(void)
#ifdef CONFIG_64BIT
/* Map the kernel */
- create_kernel_page_table(swapper_pg_dir, PMD_SIZE, false);
+ create_kernel_page_table(swapper_pg_dir, false);
#endif
/* Clear fixmap PTE and PMD mappings */
@@ -819,38 +805,22 @@ static void __init reserve_crashkernel(void)
crash_size = PAGE_ALIGN(crash_size);
- if (crash_base == 0) {
- /*
- * Current riscv boot protocol requires 2MB alignment for
- * RV64 and 4MB alignment for RV32 (hugepage size)
- */
- crash_base = memblock_find_in_range(search_start, search_end,
- crash_size, PMD_SIZE);
-
- if (crash_base == 0) {
- pr_warn("crashkernel: couldn't allocate %lldKB\n",
- crash_size >> 10);
- return;
- }
- } else {
- /* User specifies base address explicitly. */
- if (!memblock_is_region_memory(crash_base, crash_size)) {
- pr_warn("crashkernel: requested region is not memory\n");
- return;
- }
-
- if (memblock_is_region_reserved(crash_base, crash_size)) {
- pr_warn("crashkernel: requested region is reserved\n");
- return;
- }
-
+ if (crash_base) {
+ search_start = crash_base;
+ search_end = crash_base + crash_size;
+ }
- if (!IS_ALIGNED(crash_base, PMD_SIZE)) {
- pr_warn("crashkernel: requested region is misaligned\n");
- return;
- }
+ /*
+ * Current riscv boot protocol requires 2MB alignment for
+ * RV64 and 4MB alignment for RV32 (hugepage size)
+ */
+ crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
+ search_start, search_end);
+ if (crash_base == 0) {
+ pr_warn("crashkernel: couldn't allocate %lldKB\n",
+ crash_size >> 10);
+ return;
}
- memblock_reserve(crash_base, crash_size);
pr_info("crashkernel: reserved 0x%016llx - 0x%016llx (%lld MB)\n",
crash_base, crash_base + crash_size, crash_size >> 20);
@@ -860,26 +830,6 @@ static void __init reserve_crashkernel(void)
}
#endif /* CONFIG_KEXEC_CORE */
-#ifdef CONFIG_CRASH_DUMP
-/*
- * We keep track of the ELF core header of the crashed
- * kernel with a reserved-memory region with compatible
- * string "linux,elfcorehdr". Here we register a callback
- * to populate elfcorehdr_addr/size when this region is
- * present. Note that this region will be marked as
- * reserved once we call early_init_fdt_scan_reserved_mem()
- * later on.
- */
-static int __init elfcore_hdr_setup(struct reserved_mem *rmem)
-{
- elfcorehdr_addr = rmem->base;
- elfcorehdr_size = rmem->size;
- return 0;
-}
-
-RESERVEDMEM_OF_DECLARE(elfcorehdr, "linux,elfcorehdr", elfcore_hdr_setup);
-#endif
-
void __init paging_init(void)
{
setup_bootmem();
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 92c0a1b4c528..5af51ace0588 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -209,6 +209,7 @@ config S390
select SWIOTLB
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
+ select TRACE_IRQFLAGS_SUPPORT
select TTY
select VIRT_CPU_ACCOUNTING
select ZONE_DMA
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index 9ea6e61d5858..e94a2a7f6bf4 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -1,8 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config EARLY_PRINTK
def_bool y
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 17dc4f1ac4fa..a3cf33ad009f 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -70,7 +70,7 @@ cflags-y += -Wa,-I$(srctree)/arch/$(ARCH)/include
#
cflags-$(CONFIG_FRAME_POINTER) += -fno-optimize-sibling-calls
-ifeq ($(call cc-option-yn,-mpacked-stack -mbackchain -msoft-float),y)
+ifneq ($(call cc-option,-mpacked-stack -mbackchain -msoft-float),)
cflags-$(CONFIG_PACK_STACK) += -mpacked-stack -D__PACK_STACK
aflags-$(CONFIG_PACK_STACK) += -D__PACK_STACK
endif
@@ -78,22 +78,22 @@ endif
KBUILD_AFLAGS_DECOMPRESSOR += $(aflags-y)
KBUILD_CFLAGS_DECOMPRESSOR += $(cflags-y)
-ifeq ($(call cc-option-yn,-mstack-size=8192 -mstack-guard=128),y)
+ifneq ($(call cc-option,-mstack-size=8192 -mstack-guard=128),)
cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE)
-ifneq ($(call cc-option-yn,-mstack-size=8192),y)
+ifeq ($(call cc-option,-mstack-size=8192),)
cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD)
endif
endif
ifdef CONFIG_WARN_DYNAMIC_STACK
- ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
+ ifneq ($(call cc-option,-mwarn-dynamicstack),)
KBUILD_CFLAGS += -mwarn-dynamicstack
KBUILD_CFLAGS_DECOMPRESSOR += -mwarn-dynamicstack
endif
endif
ifdef CONFIG_EXPOLINE
- ifeq ($(call cc-option-yn,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),y)
+ ifneq ($(call cc-option,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),)
CC_FLAGS_EXPOLINE := -mindirect-branch=thunk
CC_FLAGS_EXPOLINE += -mfunction-return=thunk
CC_FLAGS_EXPOLINE += -mindirect-branch-table
@@ -104,10 +104,10 @@ ifdef CONFIG_EXPOLINE
endif
ifdef CONFIG_FUNCTION_TRACER
- ifeq ($(call cc-option-yn,-mfentry -mnop-mcount),n)
+ ifeq ($(call cc-option,-mfentry -mnop-mcount),)
# make use of hotpatch feature if the compiler supports it
cc_hotpatch := -mhotpatch=0,3
- ifeq ($(call cc-option-yn,$(cc_hotpatch)),y)
+ ifneq ($(call cc-option,$(cc_hotpatch)),)
CC_FLAGS_FTRACE := $(cc_hotpatch)
KBUILD_AFLAGS += -DCC_USING_HOTPATCH
KBUILD_CFLAGS += -DCC_USING_HOTPATCH
diff --git a/arch/s390/boot/pgm_check_info.c b/arch/s390/boot/pgm_check_info.c
index 209f6ae5a197..75bcbfa27941 100644
--- a/arch/s390/boot/pgm_check_info.c
+++ b/arch/s390/boot/pgm_check_info.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
+#include <linux/stdarg.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <asm/stacktrace.h>
@@ -8,7 +9,6 @@
#include <asm/setup.h>
#include <asm/sclp.h>
#include <asm/uv.h>
-#include <stdarg.h>
#include "boot.h"
const char hex_asc[] = "0123456789abcdef";
diff --git a/arch/s390/include/asm/eadm.h b/arch/s390/include/asm/eadm.h
index bb63b2afdf6f..445fe4c8184a 100644
--- a/arch/s390/include/asm/eadm.h
+++ b/arch/s390/include/asm/eadm.h
@@ -105,7 +105,7 @@ enum scm_event {SCM_CHANGE, SCM_AVAIL};
struct scm_driver {
struct device_driver drv;
int (*probe) (struct scm_device *scmdev);
- int (*remove) (struct scm_device *scmdev);
+ void (*remove) (struct scm_device *scmdev);
void (*notify) (struct scm_device *scmdev, enum scm_event event);
void (*handler) (struct scm_device *scmdev, void *data,
blk_status_t error);
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 161a9e12bfb8..a604d51acfc8 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -244,6 +244,7 @@ struct kvm_s390_sie_block {
__u8 fpf; /* 0x0060 */
#define ECB_GS 0x40
#define ECB_TE 0x10
+#define ECB_SPECI 0x08
#define ECB_SRSI 0x04
#define ECB_HOSTPROTINT 0x02
__u8 ecb; /* 0x0061 */
@@ -798,14 +799,12 @@ struct kvm_s390_cpu_model {
unsigned short ibc;
};
-struct kvm_s390_module_hook {
- int (*hook)(struct kvm_vcpu *vcpu);
- struct module *owner;
-};
+typedef int (*crypto_hook)(struct kvm_vcpu *vcpu);
struct kvm_s390_crypto {
struct kvm_s390_crypto_cb *crycb;
- struct kvm_s390_module_hook *pqap_hook;
+ struct rw_semaphore pqap_hook_rwsem;
+ crypto_hook *pqap_hook;
__u32 crycbd;
__u8 aes_kw;
__u8 dea_kw;
@@ -957,6 +956,7 @@ struct kvm_arch{
atomic64_t cmma_dirty_pages;
/* subset of available cpu features enabled by user space */
DECLARE_BITMAP(cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
+ /* indexed by vcpu_idx */
DECLARE_BITMAP(idle_mask, KVM_MAX_VCPUS);
struct kvm_s390_gisa_interrupt gisa_int;
struct kvm_s390_pv pv;
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 2316f2440881..9ed9aa37e836 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -233,23 +233,9 @@ raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
/*
* Copy a null terminated string from userspace.
*/
+long __must_check strncpy_from_user(char *dst, const char __user *src, long count);
-long __strncpy_from_user(char *dst, const char __user *src, long count);
-
-static inline long __must_check
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
- might_fault();
- return __strncpy_from_user(dst, src, count);
-}
-
-unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
-
-static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
-{
- might_fault();
- return __strnlen_user(src, n);
-}
+long __must_check strnlen_user(const char __user *src, long count);
/*
* Zero Userspace
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index fe14beb338e5..5a01872f5984 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -677,8 +677,9 @@ static void __init reserve_crashkernel(void)
return;
}
low = crash_base ?: low;
- crash_base = memblock_find_in_range(low, high, crash_size,
- KEXEC_CRASH_MEM_ALIGN);
+ crash_base = memblock_phys_alloc_range(crash_size,
+ KEXEC_CRASH_MEM_ALIGN,
+ low, high);
}
if (!crash_base) {
@@ -687,8 +688,10 @@ static void __init reserve_crashkernel(void)
return;
}
- if (register_memory_notifier(&kdump_mem_nb))
+ if (register_memory_notifier(&kdump_mem_nb)) {
+ memblock_free(crash_base, crash_size);
return;
+ }
if (!oldmem_data.start && MACHINE_IS_VM)
diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size));
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
index 64d51ab5a8b4..aa9d68b8ee14 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -122,7 +122,7 @@
131 common quotactl sys_quotactl sys_quotactl
132 common getpgid sys_getpgid sys_getpgid
133 common fchdir sys_fchdir sys_fchdir
-134 common bdflush sys_bdflush sys_bdflush
+134 common bdflush sys_ni_syscall sys_ni_syscall
135 common sysfs sys_sysfs sys_sysfs
136 common personality sys_s390_personality sys_s390_personality
137 common afs_syscall - -
@@ -449,3 +449,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease sys_process_mrelease
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index d548d60caed2..16256e17a544 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -419,13 +419,13 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)
static void __set_cpu_idle(struct kvm_vcpu *vcpu)
{
kvm_s390_set_cpuflags(vcpu, CPUSTAT_WAIT);
- set_bit(vcpu->vcpu_id, vcpu->kvm->arch.idle_mask);
+ set_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask);
}
static void __unset_cpu_idle(struct kvm_vcpu *vcpu)
{
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_WAIT);
- clear_bit(vcpu->vcpu_id, vcpu->kvm->arch.idle_mask);
+ clear_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask);
}
static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
@@ -3050,18 +3050,18 @@ int kvm_s390_get_irq_state(struct kvm_vcpu *vcpu, __u8 __user *buf, int len)
static void __airqs_kick_single_vcpu(struct kvm *kvm, u8 deliverable_mask)
{
- int vcpu_id, online_vcpus = atomic_read(&kvm->online_vcpus);
+ int vcpu_idx, online_vcpus = atomic_read(&kvm->online_vcpus);
struct kvm_s390_gisa_interrupt *gi = &kvm->arch.gisa_int;
struct kvm_vcpu *vcpu;
- for_each_set_bit(vcpu_id, kvm->arch.idle_mask, online_vcpus) {
- vcpu = kvm_get_vcpu(kvm, vcpu_id);
+ for_each_set_bit(vcpu_idx, kvm->arch.idle_mask, online_vcpus) {
+ vcpu = kvm_get_vcpu(kvm, vcpu_idx);
if (psw_ioint_disabled(vcpu))
continue;
deliverable_mask &= (u8)(vcpu->arch.sie_block->gcr[6] >> 24);
if (deliverable_mask) {
/* lately kicked but not yet running */
- if (test_and_set_bit(vcpu_id, gi->kicked_mask))
+ if (test_and_set_bit(vcpu_idx, gi->kicked_mask))
return;
kvm_s390_vcpu_wakeup(vcpu);
return;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 4527ac7b5961..752a0ffab9bf 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -66,8 +66,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_COUNTER(VM, inject_service_signal),
STATS_DESC_COUNTER(VM, inject_virtio)
};
-static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
- sizeof(struct kvm_vm_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vm_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -174,8 +172,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, instruction_diagnose_other),
STATS_DESC_COUNTER(VCPU, pfault_sync)
};
-static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
- sizeof(struct kvm_vcpu_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vcpu_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -1953,7 +1949,7 @@ out:
static int gfn_to_memslot_approx(struct kvm_memslots *slots, gfn_t gfn)
{
int start = 0, end = slots->used_slots;
- int slot = atomic_read(&slots->lru_slot);
+ int slot = atomic_read(&slots->last_used_slot);
struct kvm_memory_slot *memslots = slots->memslots;
if (gfn >= memslots[slot].base_gfn &&
@@ -1974,7 +1970,7 @@ static int gfn_to_memslot_approx(struct kvm_memslots *slots, gfn_t gfn)
if (gfn >= memslots[start].base_gfn &&
gfn < memslots[start].base_gfn + memslots[start].npages) {
- atomic_set(&slots->lru_slot, start);
+ atomic_set(&slots->last_used_slot, start);
}
return start;
@@ -2559,12 +2555,26 @@ static void kvm_s390_set_crycb_format(struct kvm *kvm)
kvm->arch.crypto.crycbd |= CRYCB_FORMAT1;
}
+/*
+ * kvm_arch_crypto_set_masks
+ *
+ * @kvm: pointer to the target guest's KVM struct containing the crypto masks
+ * to be set.
+ * @apm: the mask identifying the accessible AP adapters
+ * @aqm: the mask identifying the accessible AP domains
+ * @adm: the mask identifying the accessible AP control domains
+ *
+ * Set the masks that identify the adapters, domains and control domains to
+ * which the KVM guest is granted access.
+ *
+ * Note: The kvm->lock mutex must be locked by the caller before invoking this
+ * function.
+ */
void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm,
unsigned long *aqm, unsigned long *adm)
{
struct kvm_s390_crypto_cb *crycb = kvm->arch.crypto.crycb;
- mutex_lock(&kvm->lock);
kvm_s390_vcpu_block_all(kvm);
switch (kvm->arch.crypto.crycbd & CRYCB_FORMAT_MASK) {
@@ -2595,13 +2605,23 @@ void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm,
/* recreate the shadow crycb for each vcpu */
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_VSIE_RESTART);
kvm_s390_vcpu_unblock_all(kvm);
- mutex_unlock(&kvm->lock);
}
EXPORT_SYMBOL_GPL(kvm_arch_crypto_set_masks);
+/*
+ * kvm_arch_crypto_clear_masks
+ *
+ * @kvm: pointer to the target guest's KVM struct containing the crypto masks
+ * to be cleared.
+ *
+ * Clear the masks that identify the adapters, domains and control domains to
+ * which the KVM guest is granted access.
+ *
+ * Note: The kvm->lock mutex must be locked by the caller before invoking this
+ * function.
+ */
void kvm_arch_crypto_clear_masks(struct kvm *kvm)
{
- mutex_lock(&kvm->lock);
kvm_s390_vcpu_block_all(kvm);
memset(&kvm->arch.crypto.crycb->apcb0, 0,
@@ -2613,7 +2633,6 @@ void kvm_arch_crypto_clear_masks(struct kvm *kvm)
/* recreate the shadow crycb for each vcpu */
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_VSIE_RESTART);
kvm_s390_vcpu_unblock_all(kvm);
- mutex_unlock(&kvm->lock);
}
EXPORT_SYMBOL_GPL(kvm_arch_crypto_clear_masks);
@@ -2630,6 +2649,7 @@ static void kvm_s390_crypto_init(struct kvm *kvm)
{
kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb;
kvm_s390_set_crycb_format(kvm);
+ init_rwsem(&kvm->arch.crypto.pqap_hook_rwsem);
if (!test_kvm_facility(kvm, 76))
return;
@@ -3200,6 +3220,8 @@ static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)
vcpu->arch.sie_block->ecb |= ECB_SRSI;
if (test_kvm_facility(vcpu->kvm, 73))
vcpu->arch.sie_block->ecb |= ECB_TE;
+ if (!kvm_is_ucontrol(vcpu->kvm))
+ vcpu->arch.sie_block->ecb |= ECB_SPECI;
if (test_kvm_facility(vcpu->kvm, 8) && vcpu->kvm->arch.use_pfmfi)
vcpu->arch.sie_block->ecb2 |= ECB2_PFMFI;
@@ -4044,7 +4066,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
kvm_s390_patch_guest_per_regs(vcpu);
}
- clear_bit(vcpu->vcpu_id, vcpu->kvm->arch.gisa_int.kicked_mask);
+ clear_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.gisa_int.kicked_mask);
vcpu->arch.sie_block->icptcode = 0;
cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags);
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 9fad25109b0d..ecd741ee3276 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -79,7 +79,7 @@ static inline int is_vcpu_stopped(struct kvm_vcpu *vcpu)
static inline int is_vcpu_idle(struct kvm_vcpu *vcpu)
{
- return test_bit(vcpu->vcpu_id, vcpu->kvm->arch.idle_mask);
+ return test_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask);
}
static inline int kvm_is_ucontrol(struct kvm *kvm)
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 9928f785c677..53da4ceb16a3 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -610,6 +610,7 @@ static int handle_io_inst(struct kvm_vcpu *vcpu)
static int handle_pqap(struct kvm_vcpu *vcpu)
{
struct ap_queue_status status = {};
+ crypto_hook pqap_hook;
unsigned long reg0;
int ret;
uint8_t fc;
@@ -654,18 +655,20 @@ static int handle_pqap(struct kvm_vcpu *vcpu)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
/*
- * Verify that the hook callback is registered, lock the owner
- * and call the hook.
+ * If the hook callback is registered, there will be a pointer to the
+ * hook function pointer in the kvm_s390_crypto structure. Lock the
+ * owner, retrieve the hook function pointer and call the hook.
*/
+ down_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem);
if (vcpu->kvm->arch.crypto.pqap_hook) {
- if (!try_module_get(vcpu->kvm->arch.crypto.pqap_hook->owner))
- return -EOPNOTSUPP;
- ret = vcpu->kvm->arch.crypto.pqap_hook->hook(vcpu);
- module_put(vcpu->kvm->arch.crypto.pqap_hook->owner);
+ pqap_hook = *vcpu->kvm->arch.crypto.pqap_hook;
+ ret = pqap_hook(vcpu);
if (!ret && vcpu->run->s.regs.gprs[1] & 0x00ff0000)
kvm_s390_set_psw_cc(vcpu, 3);
+ up_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem);
return ret;
}
+ up_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem);
/*
* A vfio_driver must register a hook.
* No hook means no driver to enable the SIE CRYCB and no queues.
diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c
index 4002a24bc43a..acda4b6fc851 100644
--- a/arch/s390/kvm/vsie.c
+++ b/arch/s390/kvm/vsie.c
@@ -510,6 +510,8 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
prefix_unmapped(vsie_page);
scb_s->ecb |= ECB_TE;
}
+ /* specification exception interpretation */
+ scb_s->ecb |= scb_o->ecb & ECB_SPECI;
/* branch prediction */
if (test_kvm_facility(vcpu->kvm, 82))
scb_s->fpf |= scb_o->fpf & FPF_BPBC;
diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c
index 7ec8b1fa0f08..94ca99bde59d 100644
--- a/arch/s390/lib/uaccess.c
+++ b/arch/s390/lib/uaccess.c
@@ -338,55 +338,3 @@ unsigned long __clear_user(void __user *to, unsigned long size)
return clear_user_xc(to, size);
}
EXPORT_SYMBOL(__clear_user);
-
-static inline unsigned long strnlen_user_srst(const char __user *src,
- unsigned long size)
-{
- unsigned long tmp1, tmp2;
-
- asm volatile(
- " lghi 0,0\n"
- " la %2,0(%1)\n"
- " la %3,0(%0,%1)\n"
- " slgr %0,%0\n"
- " sacf 256\n"
- "0: srst %3,%2\n"
- " jo 0b\n"
- " la %0,1(%3)\n" /* strnlen_user results includes \0 */
- " slgr %0,%1\n"
- "1: sacf 768\n"
- EX_TABLE(0b,1b)
- : "+a" (size), "+a" (src), "=a" (tmp1), "=a" (tmp2)
- :
- : "cc", "memory", "0");
- return size;
-}
-
-unsigned long __strnlen_user(const char __user *src, unsigned long size)
-{
- if (unlikely(!size))
- return 0;
- return strnlen_user_srst(src, size);
-}
-EXPORT_SYMBOL(__strnlen_user);
-
-long __strncpy_from_user(char *dst, const char __user *src, long size)
-{
- size_t done, len, offset, len_str;
-
- if (unlikely(size <= 0))
- return 0;
- done = 0;
- do {
- offset = (size_t)src & (L1_CACHE_BYTES - 1);
- len = min(size - done, L1_CACHE_BYTES - offset);
- if (copy_from_user(dst, src, len))
- return -EFAULT;
- len_str = strnlen(dst, len);
- done += len_str;
- src += len_str;
- dst += len_str;
- } while ((len_str == len) && (done < size));
- return done;
-}
-EXPORT_SYMBOL(__strncpy_from_user);
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index f3db3caa8447..f14e7e61cd8e 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -187,9 +187,9 @@ static void pv_init(void)
return;
/* make sure bounce buffers are shared */
+ swiotlb_force = SWIOTLB_FORCE;
swiotlb_init(1);
swiotlb_update_mem_attributes();
- swiotlb_force = SWIOTLB_FORCE;
}
void __init mem_init(void)
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 58f2f7abea96..93223bd110c3 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -487,18 +487,18 @@ static int s390_dma_map_sg(struct device *dev, struct scatterlist *sg,
unsigned int max = dma_get_max_seg_size(dev);
unsigned int size = s->offset + s->length;
unsigned int offset = s->offset;
- int count = 0, i;
+ int count = 0, i, ret;
for (i = 1; i < nr_elements; i++) {
s = sg_next(s);
- s->dma_address = DMA_MAPPING_ERROR;
s->dma_length = 0;
if (s->offset || (size & ~PAGE_MASK) ||
size + s->length > max) {
- if (__s390_dma_map_sg(dev, start, size,
- &dma->dma_address, dir))
+ ret = __s390_dma_map_sg(dev, start, size,
+ &dma->dma_address, dir);
+ if (ret)
goto unmap;
dma->dma_address += offset;
@@ -511,7 +511,8 @@ static int s390_dma_map_sg(struct device *dev, struct scatterlist *sg,
}
size += s->length;
}
- if (__s390_dma_map_sg(dev, start, size, &dma->dma_address, dir))
+ ret = __s390_dma_map_sg(dev, start, size, &dma->dma_address, dir);
+ if (ret)
goto unmap;
dma->dma_address += offset;
@@ -523,7 +524,7 @@ unmap:
s390_dma_unmap_pages(dev, sg_dma_address(s), sg_dma_len(s),
dir, attrs);
- return 0;
+ return ret;
}
static void s390_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index b683b69a4556..6904f4bdbf00 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -22,8 +22,6 @@ config SUPERH
select GENERIC_IRQ_SHOW
select GENERIC_PCI_IOMAP if PCI
select GENERIC_SCHED_CLOCK
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select GENERIC_SMP_IDLE_THREAD
select GUP_GET_PTE_LOW_HIGH if X2TLB
select HAVE_ARCH_AUDITSYSCALL
@@ -71,6 +69,7 @@ config SUPERH
select RTC_LIB
select SET_FS
select SPARSE_IRQ
+ select TRACE_IRQFLAGS_SUPPORT
help
The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 28a43d63bde1..958f790273ab 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -1,8 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config SH_STANDARD_BIOS
bool "Use LinuxSH standard BIOS"
help
diff --git a/arch/sh/boot/compressed/install.sh b/arch/sh/boot/compressed/install.sh
deleted file mode 100644
index f9f41818b17e..000000000000
--- a/arch/sh/boot/compressed/install.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/sh
-#
-# arch/sh/boot/install.sh
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1995 by Linus Torvalds
-#
-# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
-# Adapted from code in arch/i386/boot/install.sh by Russell King
-# Adapted from code in arch/arm/boot/install.sh by Stuart Menefy
-#
-# "make install" script for sh architecture
-#
-# Arguments:
-# $1 - kernel version
-# $2 - kernel image file
-# $3 - kernel map file
-# $4 - default install path (blank if root directory)
-#
-
-# User may have a custom install script
-
-if [ -x /sbin/${INSTALLKERNEL} ]; then
- exec /sbin/${INSTALLKERNEL} "$@"
-fi
-
-if [ "$2" = "zImage" ]; then
-# Compressed install
- echo "Installing compressed kernel"
- if [ -f $4/vmlinuz-$1 ]; then
- mv $4/vmlinuz-$1 $4/vmlinuz.old
- fi
-
- if [ -f $4/System.map-$1 ]; then
- mv $4/System.map-$1 $4/System.old
- fi
-
- cat $2 > $4/vmlinuz-$1
- cp $3 $4/System.map-$1
-else
-# Normal install
- echo "Installing normal kernel"
- if [ -f $4/vmlinux-$1 ]; then
- mv $4/vmlinux-$1 $4/vmlinux.old
- fi
-
- if [ -f $4/System.map ]; then
- mv $4/System.map $4/System.old
- fi
-
- cat $2 > $4/vmlinux-$1
- cp $3 $4/System.map
-fi
diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h
index 4486a865ff62..372afa82fee6 100644
--- a/arch/sh/include/asm/cacheflush.h
+++ b/arch/sh/include/asm/cacheflush.h
@@ -63,6 +63,8 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
if (boot_cpu_data.dcache.n_aliases && PageAnon(page))
__flush_anon_page(page, vmaddr);
}
+
+#define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1
static inline void flush_kernel_vmap_range(void *addr, int size)
{
__flush_wback_region(addr, size);
@@ -72,12 +74,6 @@ static inline void invalidate_kernel_vmap_range(void *addr, int size)
__flush_invalidate_region(addr, size);
}
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-static inline void flush_kernel_dcache_page(struct page *page)
-{
- flush_dcache_page(page);
-}
-
extern void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len);
diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
index e0a70be77d84..208f131659c5 100644
--- a/arch/sh/kernel/syscalls/syscall.tbl
+++ b/arch/sh/kernel/syscalls/syscall.tbl
@@ -141,7 +141,7 @@
131 common quotactl sys_quotactl
132 common getpgid sys_getpgid
133 common fchdir sys_fchdir
-134 common bdflush sys_bdflush
+134 common bdflush sys_ni_syscall
135 common sysfs sys_sysfs
136 common personality sys_personality
# 137 was afs_syscall
@@ -449,3 +449,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index f0c0f955e169..b120ed947f50 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -37,8 +37,6 @@ config SPARC
select HAVE_EBPF_JIT if SPARC64
select HAVE_DEBUG_BUGVERBOSE
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select MODULES_USE_ELF_RELA
select PCI_SYSCALL if PCI
select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
@@ -49,6 +47,7 @@ config SPARC
select NEED_DMA_MAP_STATE
select NEED_SG_DMA_LENGTH
select SET_FS
+ select TRACE_IRQFLAGS_SUPPORT
config SPARC32
def_bool !64BIT
diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug
index 50a918d496c8..6b2bec1888b3 100644
--- a/arch/sparc/Kconfig.debug
+++ b/arch/sparc/Kconfig.debug
@@ -1,9 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-config TRACE_IRQFLAGS_SUPPORT
- bool
- default y
-
config DEBUG_DCFLUSH
bool "D-cache flush debugging"
depends on SPARC64 && DEBUG_KERNEL
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 4e65245bc755..24fb5a99f439 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -72,7 +72,8 @@ image zImage uImage tftpboot.img vmlinux.aout: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
install:
- $(Q)$(MAKE) $(build)=$(boot) $@
+ sh $(srctree)/$(boot)/install.sh $(KERNELRELEASE) $(KBUILD_IMAGE) \
+ System.map "$(INSTALL_PATH)"
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index 380e2b018992..849236d4eca4 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -70,7 +70,3 @@ $(obj)/image: vmlinux FORCE
$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
$(call if_changed,elftoaout)
$(call if_changed,piggy)
-
-install:
- sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/zImage \
- System.map "$(INSTALL_PATH)"
diff --git a/arch/sparc/include/uapi/asm/siginfo.h b/arch/sparc/include/uapi/asm/siginfo.h
index 68bdde4c2a2e..0e7c27522aed 100644
--- a/arch/sparc/include/uapi/asm/siginfo.h
+++ b/arch/sparc/include/uapi/asm/siginfo.h
@@ -8,9 +8,6 @@
#endif /* defined(__sparc__) && defined(__arch64__) */
-
-#define __ARCH_SI_TRAPNO
-
#include <asm-generic/siginfo.h>
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index a034f571d869..da0363692528 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -448,7 +448,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
iommu = dev->archdata.iommu;
strbuf = dev->archdata.stc;
if (nelems == 0 || !iommu)
- return 0;
+ return -EINVAL;
spin_lock_irqsave(&iommu->lock, flags);
@@ -546,7 +546,6 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
if (outcount < incount) {
outs = sg_next(outs);
- outs->dma_address = DMA_MAPPING_ERROR;
outs->dma_length = 0;
}
@@ -572,7 +571,6 @@ iommu_map_failed:
iommu_tbl_range_free(&iommu->tbl, vaddr, npages,
IOMMU_ERROR_CODE);
- s->dma_address = DMA_MAPPING_ERROR;
s->dma_length = 0;
}
if (s == outs)
@@ -580,7 +578,7 @@ iommu_map_failed:
}
spin_unlock_irqrestore(&iommu->lock, flags);
- return 0;
+ return -EINVAL;
}
/* If contexts are being used, they are the same in all of the mappings
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 9de57e88f7a1..384480971805 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -486,7 +486,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
iommu = dev->archdata.iommu;
if (nelems == 0 || !iommu)
- return 0;
+ return -EINVAL;
atu = iommu->atu;
prot = HV_PCI_MAP_ATTR_READ;
@@ -594,7 +594,6 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
if (outcount < incount) {
outs = sg_next(outs);
- outs->dma_address = DMA_MAPPING_ERROR;
outs->dma_length = 0;
}
@@ -611,7 +610,6 @@ iommu_map_failed:
iommu_tbl_range_free(tbl, vaddr, npages,
IOMMU_ERROR_CODE);
/* XXX demap? XXX */
- s->dma_address = DMA_MAPPING_ERROR;
s->dma_length = 0;
}
if (s == outs)
@@ -619,7 +617,7 @@ iommu_map_failed:
}
local_irq_restore(flags);
- return 0;
+ return -EINVAL;
}
static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index 93983d6d431d..bbbe0cfef746 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -8,9 +8,6 @@
/*
* This file handles the architecture-dependent parts of process handling..
*/
-
-#include <stdarg.h>
-
#include <linux/elfcore.h>
#include <linux/errno.h>
#include <linux/module.h>
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index d33c58a58d4f..093849bfda50 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -9,9 +9,6 @@
/*
* This file handles the architecture-dependent parts of process handling..
*/
-
-#include <stdarg.h>
-
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/sched.h>
@@ -518,7 +515,7 @@ void synchronize_user_stack(void)
static void stack_unaligned(unsigned long sp)
{
- force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) sp, 0);
+ force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) sp);
}
static const char uwfault32[] = KERN_INFO \
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index e9695a06492f..4276b9e003ca 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -745,3 +745,40 @@ asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp)
out:
return ret;
}
+
+/*
+ * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as
+ * changes likely come with new fields that should be added below.
+ */
+static_assert(NSIGILL == 11);
+static_assert(NSIGFPE == 15);
+static_assert(NSIGSEGV == 9);
+static_assert(NSIGBUS == 5);
+static_assert(NSIGTRAP == 6);
+static_assert(NSIGCHLD == 6);
+static_assert(NSIGSYS == 2);
+static_assert(sizeof(compat_siginfo_t) == 128);
+static_assert(__alignof__(compat_siginfo_t) == 4);
+static_assert(offsetof(compat_siginfo_t, si_signo) == 0x00);
+static_assert(offsetof(compat_siginfo_t, si_errno) == 0x04);
+static_assert(offsetof(compat_siginfo_t, si_code) == 0x08);
+static_assert(offsetof(compat_siginfo_t, si_pid) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_uid) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_tid) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_overrun) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_status) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_utime) == 0x18);
+static_assert(offsetof(compat_siginfo_t, si_stime) == 0x1c);
+static_assert(offsetof(compat_siginfo_t, si_value) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_int) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_ptr) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_addr) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_trapno) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_addr_lsb) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_lower) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_upper) == 0x18);
+static_assert(offsetof(compat_siginfo_t, si_pkey) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_perf_data) == 0x10);
+static_assert(offsetof(compat_siginfo_t, si_perf_type) == 0x14);
+static_assert(offsetof(compat_siginfo_t, si_band) == 0x0c);
+static_assert(offsetof(compat_siginfo_t, si_fd) == 0x10);
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index a0eec62c825d..cea23cf95600 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -556,3 +556,39 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long
user_enter();
}
+/*
+ * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as
+ * changes likely come with new fields that should be added below.
+ */
+static_assert(NSIGILL == 11);
+static_assert(NSIGFPE == 15);
+static_assert(NSIGSEGV == 9);
+static_assert(NSIGBUS == 5);
+static_assert(NSIGTRAP == 6);
+static_assert(NSIGCHLD == 6);
+static_assert(NSIGSYS == 2);
+static_assert(sizeof(siginfo_t) == 128);
+static_assert(__alignof__(siginfo_t) == 8);
+static_assert(offsetof(siginfo_t, si_signo) == 0x00);
+static_assert(offsetof(siginfo_t, si_errno) == 0x04);
+static_assert(offsetof(siginfo_t, si_code) == 0x08);
+static_assert(offsetof(siginfo_t, si_pid) == 0x10);
+static_assert(offsetof(siginfo_t, si_uid) == 0x14);
+static_assert(offsetof(siginfo_t, si_tid) == 0x10);
+static_assert(offsetof(siginfo_t, si_overrun) == 0x14);
+static_assert(offsetof(siginfo_t, si_status) == 0x18);
+static_assert(offsetof(siginfo_t, si_utime) == 0x20);
+static_assert(offsetof(siginfo_t, si_stime) == 0x28);
+static_assert(offsetof(siginfo_t, si_value) == 0x18);
+static_assert(offsetof(siginfo_t, si_int) == 0x18);
+static_assert(offsetof(siginfo_t, si_ptr) == 0x18);
+static_assert(offsetof(siginfo_t, si_addr) == 0x10);
+static_assert(offsetof(siginfo_t, si_trapno) == 0x18);
+static_assert(offsetof(siginfo_t, si_addr_lsb) == 0x18);
+static_assert(offsetof(siginfo_t, si_lower) == 0x20);
+static_assert(offsetof(siginfo_t, si_upper) == 0x28);
+static_assert(offsetof(siginfo_t, si_pkey) == 0x20);
+static_assert(offsetof(siginfo_t, si_perf_data) == 0x18);
+static_assert(offsetof(siginfo_t, si_perf_type) == 0x20);
+static_assert(offsetof(siginfo_t, si_band) == 0x10);
+static_assert(offsetof(siginfo_t, si_fd) == 0x14);
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index be77538bc038..082a551897ed 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -151,7 +151,7 @@ sparc_breakpoint (struct pt_regs *regs)
#ifdef DEBUG_SPARC_BREAKPOINT
printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc);
#endif
- force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc, 0);
+ force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc);
#ifdef DEBUG_SPARC_BREAKPOINT
printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc);
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 6b92fadb6ec7..1e9a9e016237 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -514,7 +514,7 @@ asmlinkage void sparc_breakpoint(struct pt_regs *regs)
#ifdef DEBUG_SPARC_BREAKPOINT
printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc);
#endif
- force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->tpc, 0);
+ force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->tpc);
#ifdef DEBUG_SPARC_BREAKPOINT
printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc);
#endif
diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
index 603f5a821502..7893104718c2 100644
--- a/arch/sparc/kernel/syscalls/syscall.tbl
+++ b/arch/sparc/kernel/syscalls/syscall.tbl
@@ -270,7 +270,7 @@
222 common delete_module sys_delete_module
223 common get_kernel_syms sys_ni_syscall
224 common getpgid sys_getpgid
-225 common bdflush sys_bdflush
+225 common bdflush sys_ni_syscall
226 common sysfs sys_sysfs
227 common afs_syscall sys_nis_syscall
228 common setfsuid sys_setfsuid16
@@ -492,3 +492,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c
index 247a0d9683b2..5630e5a395e0 100644
--- a/arch/sparc/kernel/traps_32.c
+++ b/arch/sparc/kernel/traps_32.c
@@ -102,8 +102,8 @@ void do_hw_interrupt(struct pt_regs *regs, unsigned long type)
if(regs->psr & PSR_PS)
die_if_kernel("Kernel bad trap", regs);
- force_sig_fault(SIGILL, ILL_ILLTRP,
- (void __user *)regs->pc, type - 0x80);
+ force_sig_fault_trapno(SIGILL, ILL_ILLTRP,
+ (void __user *)regs->pc, type - 0x80);
}
void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -116,7 +116,7 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon
regs->pc, *(unsigned long *)regs->pc);
#endif
- send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)pc, 0, current);
+ send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)pc, current);
}
void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -124,7 +124,7 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long n
{
if(psr & PSR_PS)
die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
- send_sig_fault(SIGILL, ILL_PRVOPC, (void __user *)pc, 0, current);
+ send_sig_fault(SIGILL, ILL_PRVOPC, (void __user *)pc, current);
}
/* XXX User may want to be allowed to do this. XXX */
@@ -145,7 +145,7 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned lon
#endif
send_sig_fault(SIGBUS, BUS_ADRALN,
/* FIXME: Should dig out mna address */ (void *)0,
- 0, current);
+ current);
}
static unsigned long init_fsr = 0x0UL;
@@ -291,7 +291,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
else if (fsr & 0x01)
code = FPE_FLTRES;
}
- send_sig_fault(SIGFPE, code, (void __user *)pc, 0, fpt);
+ send_sig_fault(SIGFPE, code, (void __user *)pc, fpt);
#ifndef CONFIG_SMP
last_task_used_math = NULL;
#endif
@@ -305,7 +305,7 @@ void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long n
{
if(psr & PSR_PS)
die_if_kernel("Penguin overflow trap from kernel mode", regs);
- send_sig_fault(SIGEMT, EMT_TAGOVF, (void __user *)pc, 0, current);
+ send_sig_fault(SIGEMT, EMT_TAGOVF, (void __user *)pc, current);
}
void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -327,13 +327,13 @@ void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc
printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n",
pc, npc, psr);
#endif
- force_sig_fault(SIGBUS, BUS_OBJERR, (void __user *)pc, 0);
+ force_sig_fault(SIGBUS, BUS_OBJERR, (void __user *)pc);
}
void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
- send_sig_fault(SIGILL, ILL_COPROC, (void __user *)pc, 0, current);
+ send_sig_fault(SIGILL, ILL_COPROC, (void __user *)pc, current);
}
void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -343,13 +343,13 @@ void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long n
printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n",
pc, npc, psr);
#endif
- send_sig_fault(SIGILL, ILL_COPROC, (void __user *)pc, 0, current);
+ send_sig_fault(SIGILL, ILL_COPROC, (void __user *)pc, current);
}
void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
- send_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)pc, 0, current);
+ send_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)pc, current);
}
#ifdef CONFIG_DEBUG_BUGVERBOSE
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index a850dccd78ea..6863025ed56d 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -107,8 +107,8 @@ void bad_trap(struct pt_regs *regs, long lvl)
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
}
- force_sig_fault(SIGILL, ILL_ILLTRP,
- (void __user *)regs->tpc, lvl);
+ force_sig_fault_trapno(SIGILL, ILL_ILLTRP,
+ (void __user *)regs->tpc, lvl);
}
void bad_trap_tl1(struct pt_regs *regs, long lvl)
@@ -201,8 +201,7 @@ void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, un
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
}
- force_sig_fault(SIGSEGV, SEGV_MAPERR,
- (void __user *)regs->tpc, 0);
+ force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *)regs->tpc);
out:
exception_exit(prev_state);
}
@@ -237,7 +236,7 @@ void sun4v_insn_access_exception(struct pt_regs *regs, unsigned long addr, unsig
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
}
- force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *) addr, 0);
+ force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *) addr);
}
void sun4v_insn_access_exception_tl1(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
@@ -321,7 +320,7 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un
if (is_no_fault_exception(regs))
return;
- force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *)sfar, 0);
+ force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *)sfar);
out:
exception_exit(prev_state);
}
@@ -385,13 +384,13 @@ void sun4v_data_access_exception(struct pt_regs *regs, unsigned long addr, unsig
*/
switch (type) {
case HV_FAULT_TYPE_INV_ASI:
- force_sig_fault(SIGILL, ILL_ILLADR, (void __user *)addr, 0);
+ force_sig_fault(SIGILL, ILL_ILLADR, (void __user *)addr);
break;
case HV_FAULT_TYPE_MCD_DIS:
- force_sig_fault(SIGSEGV, SEGV_ACCADI, (void __user *)addr, 0);
+ force_sig_fault(SIGSEGV, SEGV_ACCADI, (void __user *)addr);
break;
default:
- force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *)addr, 0);
+ force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *)addr);
break;
}
}
@@ -568,7 +567,7 @@ static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned lon
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
}
- force_sig_fault(SIGBUS, BUS_OBJERR, (void *)0, 0);
+ force_sig_fault(SIGBUS, BUS_OBJERR, (void *)0);
}
void spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar)
@@ -2069,8 +2068,7 @@ void do_mcd_err(struct pt_regs *regs, struct sun4v_error_entry ent)
/* Send SIGSEGV to the userspace process with the right signal
* code
*/
- force_sig_fault(SIGSEGV, SEGV_ADIDERR, (void __user *)ent.err_raddr,
- 0);
+ force_sig_fault(SIGSEGV, SEGV_ADIDERR, (void __user *)ent.err_raddr);
}
/* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate.
@@ -2184,7 +2182,7 @@ bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
}
if (attrs & SUN4V_ERR_ATTRS_PIO) {
force_sig_fault(SIGBUS, BUS_ADRERR,
- (void __user *)sun4v_get_vaddr(regs), 0);
+ (void __user *)sun4v_get_vaddr(regs));
return true;
}
@@ -2340,8 +2338,7 @@ static void do_fpe_common(struct pt_regs *regs)
else if (fsr & 0x01)
code = FPE_FLTRES;
}
- force_sig_fault(SIGFPE, code,
- (void __user *)regs->tpc, 0);
+ force_sig_fault(SIGFPE, code, (void __user *)regs->tpc);
}
}
@@ -2395,8 +2392,7 @@ void do_tof(struct pt_regs *regs)
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
}
- force_sig_fault(SIGEMT, EMT_TAGOVF,
- (void __user *)regs->tpc, 0);
+ force_sig_fault(SIGEMT, EMT_TAGOVF, (void __user *)regs->tpc);
out:
exception_exit(prev_state);
}
@@ -2415,8 +2411,7 @@ void do_div0(struct pt_regs *regs)
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
}
- force_sig_fault(SIGFPE, FPE_INTDIV,
- (void __user *)regs->tpc, 0);
+ force_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)regs->tpc);
out:
exception_exit(prev_state);
}
@@ -2612,7 +2607,7 @@ void do_illegal_instruction(struct pt_regs *regs)
}
}
}
- force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)pc, 0);
+ force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)pc);
out:
exception_exit(prev_state);
}
@@ -2632,7 +2627,7 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
if (is_no_fault_exception(regs))
return;
- force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)sfar, 0);
+ force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)sfar);
out:
exception_exit(prev_state);
}
@@ -2650,7 +2645,7 @@ void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_c
if (is_no_fault_exception(regs))
return;
- force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) addr, 0);
+ force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) addr);
}
/* sun4v_mem_corrupt_detect_precise() - Handle precise exception on an ADI
@@ -2697,7 +2692,7 @@ void sun4v_mem_corrupt_detect_precise(struct pt_regs *regs, unsigned long addr,
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
}
- force_sig_fault(SIGSEGV, SEGV_ADIPERR, (void __user *)addr, 0);
+ force_sig_fault(SIGSEGV, SEGV_ADIPERR, (void __user *)addr);
}
void do_privop(struct pt_regs *regs)
@@ -2712,8 +2707,7 @@ void do_privop(struct pt_regs *regs)
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
}
- force_sig_fault(SIGILL, ILL_PRVOPC,
- (void __user *)regs->tpc, 0);
+ force_sig_fault(SIGILL, ILL_PRVOPC, (void __user *)regs->tpc);
out:
exception_exit(prev_state);
}
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c
index ef5c5207c9ff..455f0258c745 100644
--- a/arch/sparc/kernel/unaligned_32.c
+++ b/arch/sparc/kernel/unaligned_32.c
@@ -278,5 +278,5 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
{
send_sig_fault(SIGBUS, BUS_ADRALN,
(void __user *)safe_compute_effective_address(regs, insn),
- 0, current);
+ current);
}
diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c
index 348a88691219..01122a208f94 100644
--- a/arch/sparc/kernel/vio.c
+++ b/arch/sparc/kernel/vio.c
@@ -93,7 +93,7 @@ static int vio_device_probe(struct device *dev)
return drv->probe(vdev, id);
}
-static int vio_device_remove(struct device *dev)
+static void vio_device_remove(struct device *dev)
{
struct vio_dev *vdev = to_vio_dev(dev);
struct vio_driver *drv = to_vio_driver(dev->driver);
@@ -107,8 +107,6 @@ static int vio_device_remove(struct device *dev)
drv->remove(vdev);
}
-
- return 0;
}
static ssize_t devspec_show(struct device *dev,
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index de2031c2b2d7..fa858626b85b 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -83,7 +83,7 @@ static void __do_fault_siginfo(int code, int sig, struct pt_regs *regs,
show_signal_msg(regs, sig, code,
addr, current);
- force_sig_fault(sig, code, (void __user *) addr, 0);
+ force_sig_fault(sig, code, (void __user *) addr);
}
static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 0a6bcc85fba7..9a9652a15fed 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -176,7 +176,7 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
if (unlikely(show_unhandled_signals))
show_signal_msg(regs, sig, code, addr, current);
- force_sig_fault(sig, code, (void __user *) addr, 0);
+ force_sig_fault(sig, code, (void __user *) addr);
}
static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn)
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 0c0342e5b10d..9e3f6933ca13 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -256,7 +256,7 @@ static int __sbus_iommu_map_sg(struct device *dev, struct scatterlist *sgl,
sg->dma_address =__sbus_iommu_map_page(dev, sg_page(sg),
sg->offset, sg->length, per_page_flush);
if (sg->dma_address == DMA_MAPPING_ERROR)
- return 0;
+ return -EIO;
sg->dma_length = sg->length;
}
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 0561b73cfd9a..8de2646fbdb1 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -7,6 +7,8 @@ config UML
default y
select ARCH_EPHEMERAL_INODES
select ARCH_HAS_KCOV
+ select ARCH_HAS_STRNCPY_FROM_USER
+ select ARCH_HAS_STRNLEN_USER
select ARCH_NO_PREEMPT
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_SECCOMP_FILTER
@@ -20,6 +22,7 @@ config UML
select GENERIC_CPU_DEVICES
select HAVE_GCC_PLUGINS
select SET_FS
+ select TRACE_IRQFLAGS_SUPPORT
select TTY # Needed for line.c
config MMU
@@ -50,10 +53,6 @@ config ISA
config SBUS
bool
-config TRACE_IRQFLAGS_SUPPORT
- bool
- default y
-
config LOCKDEP_SUPPORT
bool
default y
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 12a7acef0357..f2fe63bfd819 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -41,8 +41,8 @@ endif
HOST_DIR := arch/$(HEADER_ARCH)
-include $(ARCH_DIR)/Makefile-skas
-include $(HOST_DIR)/Makefile.um
+include $(srctree)/$(ARCH_DIR)/Makefile-skas
+include $(srctree)/$(HOST_DIR)/Makefile.um
core-y += $(HOST_DIR)/um/
@@ -76,7 +76,7 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
-idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__
#This will adjust *FLAGS accordingly to the platform.
-include $(ARCH_DIR)/Makefile-os-$(OS)
+include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include \
-I$(srctree)/$(HOST_DIR)/include/uapi \
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index fbc623d2cc07..8febf95da96e 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -538,12 +538,14 @@ int register_lines(struct line_driver *line_driver,
const struct tty_operations *ops,
struct line *lines, int nlines)
{
- struct tty_driver *driver = alloc_tty_driver(nlines);
+ struct tty_driver *driver;
int err;
int i;
- if (!driver)
- return -ENOMEM;
+ driver = tty_alloc_driver(nlines, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
driver->driver_name = line_driver->name;
driver->name = line_driver->device_name;
@@ -551,9 +553,8 @@ int register_lines(struct line_driver *line_driver,
driver->minor_start = line_driver->minor_start;
driver->type = line_driver->type;
driver->subtype = line_driver->subtype;
- driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
driver->init_termios = tty_std_termios;
-
+
for (i = 0; i < nlines; i++) {
tty_port_init(&lines[i].port);
lines[i].port.ops = &line_port_ops;
@@ -567,7 +568,7 @@ int register_lines(struct line_driver *line_driver,
if (err) {
printk(KERN_ERR "register_lines : can't register %s driver\n",
line_driver->name);
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
for (i = 0; i < nlines; i++)
tty_port_destroy(&lines[i].port);
return err;
diff --git a/arch/um/drivers/rtc_user.c b/arch/um/drivers/rtc_user.c
index 4016bc1d577e..7c3cec4c68cf 100644
--- a/arch/um/drivers/rtc_user.c
+++ b/arch/um/drivers/rtc_user.c
@@ -3,6 +3,7 @@
* Copyright (C) 2020 Intel Corporation
* Author: Johannes Berg <johannes@sipsolutions.net>
*/
+#include <stdbool.h>
#include <os.h>
#include <errno.h>
#include <sched.h>
diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c
index bae53220ce26..e4ffeb9a1fa4 100644
--- a/arch/um/drivers/vector_user.c
+++ b/arch/um/drivers/vector_user.c
@@ -3,6 +3,7 @@
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
*/
+#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h
index fe66d659acad..191ef36dd543 100644
--- a/arch/um/include/asm/uaccess.h
+++ b/arch/um/include/asm/uaccess.h
@@ -23,16 +23,13 @@
extern unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n);
extern unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n);
-extern long __strncpy_from_user(char *dst, const char __user *src, long count);
-extern long __strnlen_user(const void __user *str, long len);
extern unsigned long __clear_user(void __user *mem, unsigned long len);
static inline int __access_ok(unsigned long addr, unsigned long size);
/* Teach asm-generic/uaccess.h that we have C functions for these. */
#define __access_ok __access_ok
#define __clear_user __clear_user
-#define __strnlen_user __strnlen_user
-#define __strncpy_from_user __strncpy_from_user
+
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
diff --git a/arch/um/include/shared/irq_user.h b/arch/um/include/shared/irq_user.h
index 065829f443ae..86a8a573b65c 100644
--- a/arch/um/include/shared/irq_user.h
+++ b/arch/um/include/shared/irq_user.h
@@ -7,7 +7,6 @@
#define __IRQ_USER_H__
#include <sysdep/ptrace.h>
-#include <stdbool.h>
enum um_irq_type {
IRQ_READ,
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 60b84edc8a68..96d400387c93 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -8,7 +8,6 @@
#ifndef __OS_H__
#define __OS_H__
-#include <stdarg.h>
#include <irq_user.h>
#include <longjmp.h>
#include <mm_id.h>
diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h
index e793e4212f0a..dd4badffdeb3 100644
--- a/arch/um/include/shared/user.h
+++ b/arch/um/include/shared/user.h
@@ -38,7 +38,8 @@ extern void panic(const char *fmt, ...)
#define UM_KERN_CONT KERN_CONT
#ifdef UML_CONFIG_PRINTK
-extern int printk(const char *fmt, ...)
+#define printk(...) _printk(__VA_ARGS__)
+extern int _printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
#else
static inline int printk(const char *fmt, ...)
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 6c76df96e858..a509be911026 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -189,11 +189,14 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
return 0;
}
-long __strncpy_from_user(char *dst, const char __user *src, long count)
+long strncpy_from_user(char *dst, const char __user *src, long count)
{
long n;
char *ptr = dst;
+ if (!access_ok(src, 1))
+ return -EFAULT;
+
if (uaccess_kernel()) {
strncpy(dst, (__force void *) src, count);
return strnlen(dst, count);
@@ -205,7 +208,7 @@ long __strncpy_from_user(char *dst, const char __user *src, long count)
return -EFAULT;
return strnlen(dst, count);
}
-EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(strncpy_from_user);
static int clear_chunk(unsigned long addr, int len, void *unused)
{
@@ -236,10 +239,13 @@ static int strnlen_chunk(unsigned long str, int len, void *arg)
return 0;
}
-long __strnlen_user(const void __user *str, long len)
+long strnlen_user(const char __user *str, long len)
{
int count = 0, n;
+ if (!access_ok(str, 1))
+ return -EFAULT;
+
if (uaccess_kernel())
return strnlen((__force char*)str, len) + 1;
@@ -248,7 +254,7 @@ long __strnlen_user(const void __user *str, long len)
return count + 1;
return 0;
}
-EXPORT_SYMBOL(__strnlen_user);
+EXPORT_SYMBOL(strnlen_user);
/**
* arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 6de99bb16113..6cf098c23a39 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -67,7 +67,7 @@ int signals_enabled;
#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
static int signals_blocked;
#else
-#define signals_blocked false
+#define signals_blocked 0
#endif
static unsigned int signals_pending;
static unsigned int signals_active = 0;
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 07327425d06e..41297ec404bf 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -3,6 +3,7 @@
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
*/
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 421fa9e38c60..4e001bbbb425 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -145,8 +145,6 @@ config X86
select GENERIC_PENDING_IRQ if SMP
select GENERIC_PTDUMP
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL
select GENERIC_GETTIMEOFDAY
select GENERIC_VDSO_TIME_NS
@@ -261,6 +259,7 @@ config X86
select STACK_VALIDATION if HAVE_STACK_VALIDATION && (HAVE_STATIC_CALL_INLINE || RETPOLINE)
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
+ select TRACE_IRQFLAGS_SUPPORT
select USER_STACKTRACE_SUPPORT
select VIRT_TO_BUS
select HAVE_ARCH_KCSAN if X86_64
@@ -2767,32 +2766,6 @@ config AMD_NB
def_bool y
depends on CPU_SUP_AMD && PCI
-config X86_SYSFB
- bool "Mark VGA/VBE/EFI FB as generic system framebuffer"
- help
- Firmwares often provide initial graphics framebuffers so the BIOS,
- bootloader or kernel can show basic video-output during boot for
- user-guidance and debugging. Historically, x86 used the VESA BIOS
- Extensions and EFI-framebuffers for this, which are mostly limited
- to x86.
- This option, if enabled, marks VGA/VBE/EFI framebuffers as generic
- framebuffers so the new generic system-framebuffer drivers can be
- used on x86. If the framebuffer is not compatible with the generic
- modes, it is advertised as fallback platform framebuffer so legacy
- drivers like efifb, vesafb and uvesafb can pick it up.
- If this option is not selected, all system framebuffers are always
- marked as fallback platform framebuffers as usual.
-
- Note: Legacy fbdev drivers, including vesafb, efifb, uvesafb, will
- not be able to pick up generic system framebuffers if this option
- is selected. You are highly encouraged to enable simplefb as
- replacement if you select this option. simplefb can correctly deal
- with generic system framebuffers. But you should still keep vesafb
- and others enabled as fallback if a system framebuffer is
- incompatible with simplefb.
-
- If unsure, say Y.
-
endmenu
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 80b57e7f4947..d3a6f74a94bd 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -1,8 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config TRACE_IRQFLAGS_NMI_SUPPORT
def_bool y
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index d82d01490dd3..7488cfbbd2f6 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -73,7 +73,7 @@ ifeq ($(CONFIG_X86_32),y)
KBUILD_CFLAGS += $(cc_stack_align4)
# CPU-specific tuning. Anything which can be shared with UML should go here.
- include arch/x86/Makefile_32.cpu
+ include $(srctree)/arch/x86/Makefile_32.cpu
KBUILD_CFLAGS += $(cflags-y)
# temporary until string.h is fixed
diff --git a/arch/x86/Makefile_32.cpu b/arch/x86/Makefile_32.cpu
index cd3056759880..e7355f8b51c2 100644
--- a/arch/x86/Makefile_32.cpu
+++ b/arch/x86/Makefile_32.cpu
@@ -2,13 +2,7 @@
# CPU tuning section - shared with UML.
# Must change only cflags-y (or [yn]), not CFLAGS! That makes a difference for UML.
-#-mtune exists since gcc 3.4
-HAS_MTUNE := $(call cc-option-yn, -mtune=i386)
-ifeq ($(HAS_MTUNE),y)
tune = $(call cc-option,-mtune=$(1),$(2))
-else
-tune = $(call cc-option,-mcpu=$(1),$(2))
-endif
cflags-$(CONFIG_M486SX) += -march=i486
cflags-$(CONFIG_M486) += -march=i486
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index ca866f1cca2e..34c9dbb6a47d 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -18,7 +18,7 @@
#ifndef __ASSEMBLY__
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/types.h>
#include <linux/edd.h>
#include <asm/setup.h>
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index ce763a12311c..61f18b72552b 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -145,7 +145,7 @@
131 i386 quotactl sys_quotactl
132 i386 getpgid sys_getpgid
133 i386 fchdir sys_fchdir
-134 i386 bdflush sys_bdflush
+134 i386 bdflush sys_ni_syscall
135 i386 sysfs sys_sysfs
136 i386 personality sys_personality
137 i386 afs_syscall
@@ -452,3 +452,4 @@
445 i386 landlock_add_rule sys_landlock_add_rule
446 i386 landlock_restrict_self sys_landlock_restrict_self
447 i386 memfd_secret sys_memfd_secret
+448 i386 process_mrelease sys_process_mrelease
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index f6b57799c1ea..807b6a1de8e8 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -369,6 +369,7 @@
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
447 common memfd_secret sys_memfd_secret
+448 common process_mrelease sys_process_mrelease
#
# Due to a historical design error, certain syscalls are numbered differently
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index 05c4abc2fdfd..a2dddcc189f6 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -131,7 +131,7 @@ $(obj)/%-x32.o: $(obj)/%.o FORCE
targets += vdsox32.lds $(vobjx32s-y)
$(obj)/%.so: OBJCOPYFLAGS := -S --remove-section __ex_table
-$(obj)/%.so: $(obj)/%.so.dbg
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
$(call if_changed,objcopy)
$(obj)/vdsox32.so.dbg: $(obj)/vdsox32.lds $(vobjx32s) FORCE
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 6952e219cba3..708a2712a516 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -7,10 +7,10 @@
* Author : K. Y. Srinivasan <kys@microsoft.com>
*/
-#include <linux/acpi.h>
#include <linux/efi.h>
#include <linux/types.h>
#include <linux/bitfield.h>
+#include <linux/io.h>
#include <asm/apic.h>
#include <asm/desc.h>
#include <asm/hypervisor.h>
@@ -39,71 +39,50 @@ EXPORT_SYMBOL_GPL(hv_hypercall_pg);
/* Storage to save the hypercall page temporarily for hibernation */
static void *hv_hypercall_pg_saved;
-u32 *hv_vp_index;
-EXPORT_SYMBOL_GPL(hv_vp_index);
-
struct hv_vp_assist_page **hv_vp_assist_page;
EXPORT_SYMBOL_GPL(hv_vp_assist_page);
-void __percpu **hyperv_pcpu_input_arg;
-EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
-
-void __percpu **hyperv_pcpu_output_arg;
-EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg);
-
-u32 hv_max_vp_index;
-EXPORT_SYMBOL_GPL(hv_max_vp_index);
-
static int hv_cpu_init(unsigned int cpu)
{
- u64 msr_vp_index;
+ union hv_vp_assist_msr_contents msr = { 0 };
struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
- void **input_arg;
- struct page *pg;
-
- /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
- pg = alloc_pages(irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL, hv_root_partition ? 1 : 0);
- if (unlikely(!pg))
- return -ENOMEM;
-
- input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
- *input_arg = page_address(pg);
- if (hv_root_partition) {
- void **output_arg;
-
- output_arg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
- *output_arg = page_address(pg + 1);
- }
-
- msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX);
-
- hv_vp_index[smp_processor_id()] = msr_vp_index;
+ int ret;
- if (msr_vp_index > hv_max_vp_index)
- hv_max_vp_index = msr_vp_index;
+ ret = hv_common_cpu_init(cpu);
+ if (ret)
+ return ret;
if (!hv_vp_assist_page)
return 0;
- /*
- * The VP ASSIST PAGE is an "overlay" page (see Hyper-V TLFS's Section
- * 5.2.1 "GPA Overlay Pages"). Here it must be zeroed out to make sure
- * we always write the EOI MSR in hv_apic_eoi_write() *after* the
- * EOI optimization is disabled in hv_cpu_die(), otherwise a CPU may
- * not be stopped in the case of CPU offlining and the VM will hang.
- */
if (!*hvp) {
- *hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL | __GFP_ZERO);
- }
-
- if (*hvp) {
- u64 val;
-
- val = vmalloc_to_pfn(*hvp);
- val = (val << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT) |
- HV_X64_MSR_VP_ASSIST_PAGE_ENABLE;
-
- wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, val);
+ if (hv_root_partition) {
+ /*
+ * For root partition we get the hypervisor provided VP assist
+ * page, instead of allocating a new page.
+ */
+ rdmsrl(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
+ *hvp = memremap(msr.pfn <<
+ HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT,
+ PAGE_SIZE, MEMREMAP_WB);
+ } else {
+ /*
+ * The VP assist page is an "overlay" page (see Hyper-V TLFS's
+ * Section 5.2.1 "GPA Overlay Pages"). Here it must be zeroed
+ * out to make sure we always write the EOI MSR in
+ * hv_apic_eoi_write() *after* the EOI optimization is disabled
+ * in hv_cpu_die(), otherwise a CPU may not be stopped in the
+ * case of CPU offlining and the VM will hang.
+ */
+ *hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL | __GFP_ZERO);
+ if (*hvp)
+ msr.pfn = vmalloc_to_pfn(*hvp);
+ }
+ WARN_ON(!(*hvp));
+ if (*hvp) {
+ msr.enable = 1;
+ wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
+ }
}
return 0;
@@ -198,29 +177,26 @@ static int hv_cpu_die(unsigned int cpu)
{
struct hv_reenlightenment_control re_ctrl;
unsigned int new_cpu;
- unsigned long flags;
- void **input_arg;
- void *pg;
- local_irq_save(flags);
- input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
- pg = *input_arg;
- *input_arg = NULL;
-
- if (hv_root_partition) {
- void **output_arg;
-
- output_arg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
- *output_arg = NULL;
+ hv_common_cpu_die(cpu);
+
+ if (hv_vp_assist_page && hv_vp_assist_page[cpu]) {
+ union hv_vp_assist_msr_contents msr = { 0 };
+ if (hv_root_partition) {
+ /*
+ * For root partition the VP assist page is mapped to
+ * hypervisor provided page, and thus we unmap the
+ * page here and nullify it, so that in future we have
+ * correct page address mapped in hv_cpu_init.
+ */
+ memunmap(hv_vp_assist_page[cpu]);
+ hv_vp_assist_page[cpu] = NULL;
+ rdmsrl(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
+ msr.enable = 0;
+ }
+ wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
}
- local_irq_restore(flags);
-
- free_pages((unsigned long)pg, hv_root_partition ? 1 : 0);
-
- if (hv_vp_assist_page && hv_vp_assist_page[cpu])
- wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, 0);
-
if (hv_reenlightenment_cb == NULL)
return 0;
@@ -368,7 +344,7 @@ void __init hyperv_init(void)
{
u64 guest_id, required_msrs;
union hv_x64_msr_hypercall_contents hypercall_msr;
- int cpuhp, i;
+ int cpuhp;
if (x86_hyper_type != X86_HYPER_MS_HYPERV)
return;
@@ -380,36 +356,14 @@ void __init hyperv_init(void)
if ((ms_hyperv.features & required_msrs) != required_msrs)
return;
- /*
- * Allocate the per-CPU state for the hypercall input arg.
- * If this allocation fails, we will not be able to setup
- * (per-CPU) hypercall input page and thus this failure is
- * fatal on Hyper-V.
- */
- hyperv_pcpu_input_arg = alloc_percpu(void *);
-
- BUG_ON(hyperv_pcpu_input_arg == NULL);
-
- /* Allocate the per-CPU state for output arg for root */
- if (hv_root_partition) {
- hyperv_pcpu_output_arg = alloc_percpu(void *);
- BUG_ON(hyperv_pcpu_output_arg == NULL);
- }
-
- /* Allocate percpu VP index */
- hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
- GFP_KERNEL);
- if (!hv_vp_index)
+ if (hv_common_init())
return;
- for (i = 0; i < num_possible_cpus(); i++)
- hv_vp_index[i] = VP_INVAL;
-
hv_vp_assist_page = kcalloc(num_possible_cpus(),
sizeof(*hv_vp_assist_page), GFP_KERNEL);
if (!hv_vp_assist_page) {
ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
- goto free_vp_index;
+ goto common_free;
}
cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
@@ -507,9 +461,8 @@ remove_cpuhp_state:
free_vp_assist_page:
kfree(hv_vp_assist_page);
hv_vp_assist_page = NULL;
-free_vp_index:
- kfree(hv_vp_index);
- hv_vp_index = NULL;
+common_free:
+ hv_common_free();
}
/*
@@ -539,7 +492,6 @@ void hyperv_cleanup(void)
hypercall_msr.as_uint64 = 0;
wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
}
-EXPORT_SYMBOL_GPL(hyperv_cleanup);
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
{
@@ -595,12 +547,6 @@ bool hv_is_hyperv_initialized(void)
}
EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);
-bool hv_is_hibernation_supported(void)
-{
- return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4);
-}
-EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);
-
enum hv_isolation_type hv_get_isolation_type(void)
{
if (!(ms_hyperv.priv_high & HV_ISOLATION))
@@ -613,4 +559,3 @@ bool hv_is_isolation_supported(void)
{
return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
}
-EXPORT_SYMBOL_GPL(hv_is_isolation_supported);
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 5e5b9fc2747f..9bd15241fadb 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -202,8 +202,7 @@ static int load_aout_binary(struct linux_binprm *bprm)
error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
- MAP_32BIT,
+ MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
fd_offset);
if (error != N_TXTADDR(ex))
@@ -211,8 +210,7 @@ static int load_aout_binary(struct linux_binprm *bprm)
error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
- MAP_32BIT,
+ MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
fd_offset + ex.a_text);
if (error != N_DATADDR(ex))
return error;
@@ -293,7 +291,7 @@ static int load_aout_library(struct file *file)
/* Now use mmap to map the library into memory. */
error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
+ MAP_FIXED | MAP_PRIVATE | MAP_32BIT,
N_TXTOFF(ex));
retval = error;
if (error != start_addr)
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index f1366ce609e3..2322d6bd5883 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -288,6 +288,15 @@ union hv_x64_msr_hypercall_contents {
} __packed;
};
+union hv_vp_assist_msr_contents {
+ u64 as_uint64;
+ struct {
+ u64 enable:1;
+ u64 reserved:11;
+ u64 pfn:52;
+ } __packed;
+};
+
struct hv_reenlightenment_control {
__u64 vector:8;
__u64 reserved1:8;
diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
index a12a4987154e..cefe1d81e2e8 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -72,7 +72,6 @@ KVM_X86_OP(enable_nmi_window)
KVM_X86_OP(enable_irq_window)
KVM_X86_OP(update_cr8_intercept)
KVM_X86_OP(check_apicv_inhibit_reasons)
-KVM_X86_OP_NULL(pre_update_apicv_exec_ctrl)
KVM_X86_OP(refresh_apicv_exec_ctrl)
KVM_X86_OP(hwapic_irr_update)
KVM_X86_OP(hwapic_isr_update)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index af6ce8d4c86a..f8f48a7ec577 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -37,9 +37,21 @@
#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
-#define KVM_MAX_VCPUS 288
-#define KVM_SOFT_MAX_VCPUS 240
-#define KVM_MAX_VCPU_ID 1023
+#define KVM_MAX_VCPUS 1024
+#define KVM_SOFT_MAX_VCPUS 710
+
+/*
+ * In x86, the VCPU ID corresponds to the APIC ID, and APIC IDs
+ * might be larger than the actual number of VCPUs because the
+ * APIC ID encodes CPU topology information.
+ *
+ * In the worst case, we'll need less than one extra bit for the
+ * Core ID, and less than one extra bit for the Package (Die) ID,
+ * so ratio of 4 should be enough.
+ */
+#define KVM_VCPU_ID_RATIO 4
+#define KVM_MAX_VCPU_ID (KVM_MAX_VCPUS * KVM_VCPU_ID_RATIO)
+
/* memory slots that are not exposed to userspace */
#define KVM_PRIVATE_MEM_SLOTS 3
@@ -124,13 +136,6 @@
#define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1))
#define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
-static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level)
-{
- /* KVM_HPAGE_GFN_SHIFT(PG_LEVEL_4K) must be 0. */
- return (gfn >> KVM_HPAGE_GFN_SHIFT(level)) -
- (base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
-}
-
#define KVM_PERMILLE_MMU_PAGES 20
#define KVM_MIN_ALLOC_MMU_PAGES 64UL
#define KVM_MMU_HASH_SHIFT 12
@@ -229,7 +234,8 @@ enum x86_intercept_stage;
KVM_GUESTDBG_USE_HW_BP | \
KVM_GUESTDBG_USE_SW_BP | \
KVM_GUESTDBG_INJECT_BP | \
- KVM_GUESTDBG_INJECT_DB)
+ KVM_GUESTDBG_INJECT_DB | \
+ KVM_GUESTDBG_BLOCKIRQ)
#define PFERR_PRESENT_BIT 0
@@ -447,6 +453,7 @@ struct kvm_mmu {
u64 *pae_root;
u64 *pml4_root;
+ u64 *pml5_root;
/*
* check zero bits on shadow page table entries, these
@@ -482,6 +489,7 @@ struct kvm_pmc {
* ctrl value for fixed counters.
*/
u64 current_config;
+ bool is_paused;
};
struct kvm_pmu {
@@ -522,7 +530,6 @@ struct kvm_pmu_ops;
enum {
KVM_DEBUGREG_BP_ENABLED = 1,
KVM_DEBUGREG_WONT_EXIT = 2,
- KVM_DEBUGREG_RELOAD = 4,
};
struct kvm_mtrr_range {
@@ -723,7 +730,6 @@ struct kvm_vcpu_arch {
u64 reserved_gpa_bits;
int maxphyaddr;
- int max_tdp_level;
/* emulate context */
@@ -988,6 +994,12 @@ struct kvm_hv {
/* How many vCPUs have VP index != vCPU index */
atomic_t num_mismatched_vp_indexes;
+ /*
+ * How many SynICs use 'AutoEOI' feature
+ * (protected by arch.apicv_update_lock)
+ */
+ unsigned int synic_auto_eoi_used;
+
struct hv_partition_assist_pg *hv_pa_pg;
struct kvm_hv_syndbg hv_syndbg;
};
@@ -1002,9 +1014,8 @@ struct msr_bitmap_range {
/* Xen emulation context */
struct kvm_xen {
bool long_mode;
- bool shinfo_set;
u8 upcall_vector;
- struct gfn_to_hva_cache shinfo_cache;
+ gfn_t shinfo_gfn;
};
enum kvm_irqchip_mode {
@@ -1061,6 +1072,9 @@ struct kvm_arch {
struct kvm_apic_map __rcu *apic_map;
atomic_t apic_map_dirty;
+ /* Protects apic_access_memslot_enabled and apicv_inhibit_reasons */
+ struct mutex apicv_update_lock;
+
bool apic_access_memslot_enabled;
unsigned long apicv_inhibit_reasons;
@@ -1213,9 +1227,17 @@ struct kvm_vm_stat {
u64 mmu_recycled;
u64 mmu_cache_miss;
u64 mmu_unsync;
- u64 lpages;
+ union {
+ struct {
+ atomic64_t pages_4k;
+ atomic64_t pages_2m;
+ atomic64_t pages_1g;
+ };
+ atomic64_t pages[KVM_NR_PAGE_SIZES];
+ };
u64 nx_lpage_splits;
u64 max_mmu_page_hash_collisions;
+ u64 max_mmu_rmap_size;
};
struct kvm_vcpu_stat {
@@ -1359,7 +1381,6 @@ struct kvm_x86_ops {
void (*enable_irq_window)(struct kvm_vcpu *vcpu);
void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
bool (*check_apicv_inhibit_reasons)(ulong bit);
- void (*pre_update_apicv_exec_ctrl)(struct kvm *kvm, bool activate);
void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
@@ -1543,12 +1564,12 @@ void kvm_mmu_uninit_vm(struct kvm *kvm);
void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu);
void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
- struct kvm_memory_slot *memslot,
+ const struct kvm_memory_slot *memslot,
int start_level);
void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
const struct kvm_memory_slot *memslot);
void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
- struct kvm_memory_slot *memslot);
+ const struct kvm_memory_slot *memslot);
void kvm_mmu_zap_all(struct kvm *kvm);
void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen);
unsigned long kvm_mmu_calculate_default_mmu_pages(struct kvm *kvm);
@@ -1744,6 +1765,9 @@ void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu);
void kvm_request_apicv_update(struct kvm *kvm, bool activate,
unsigned long bit);
+void __kvm_request_apicv_update(struct kvm *kvm, bool activate,
+ unsigned long bit);
+
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
@@ -1754,8 +1778,8 @@ void kvm_mmu_invalidate_gva(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
void kvm_mmu_invpcid_gva(struct kvm_vcpu *vcpu, gva_t gva, unsigned long pcid);
void kvm_mmu_new_pgd(struct kvm_vcpu *vcpu, gpa_t new_pgd);
-void kvm_configure_mmu(bool enable_tdp, int tdp_max_root_level,
- int tdp_huge_page_level);
+void kvm_configure_mmu(bool enable_tdp, int tdp_forced_root_level,
+ int tdp_max_root_level, int tdp_huge_page_level);
static inline u16 kvm_read_ldt(void)
{
@@ -1779,11 +1803,6 @@ static inline unsigned long read_msr(unsigned long msr)
}
#endif
-static inline u32 get_rdx_init_val(void)
-{
- return 0x600; /* P6 family */
-}
-
static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
{
kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
@@ -1816,31 +1835,6 @@ enum {
#define kvm_arch_vcpu_memslots_id(vcpu) ((vcpu)->arch.hflags & HF_SMM_MASK ? 1 : 0)
#define kvm_memslots_for_spte_role(kvm, role) __kvm_memslots(kvm, (role).smm)
-asmlinkage void kvm_spurious_fault(void);
-
-/*
- * Hardware virtualization extension instructions may fault if a
- * reboot turns off virtualization while processes are running.
- * Usually after catching the fault we just panic; during reboot
- * instead the instruction is ignored.
- */
-#define __kvm_handle_fault_on_reboot(insn) \
- "666: \n\t" \
- insn "\n\t" \
- "jmp 668f \n\t" \
- "667: \n\t" \
- "1: \n\t" \
- ".pushsection .discard.instr_begin \n\t" \
- ".long 1b - . \n\t" \
- ".popsection \n\t" \
- "call kvm_spurious_fault \n\t" \
- "1: \n\t" \
- ".pushsection .discard.instr_end \n\t" \
- ".long 1b - . \n\t" \
- ".popsection \n\t" \
- "668: \n\t" \
- _ASM_EXTABLE(666b, 667b)
-
#define KVM_ARCH_WANT_MMU_NOTIFIER
int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v);
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 67ff0d637e55..adccbc209169 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -36,8 +36,6 @@ void hyperv_vector_handler(struct pt_regs *regs);
extern int hyperv_init_cpuhp;
extern void *hv_hypercall_pg;
-extern void __percpu **hyperv_pcpu_input_arg;
-extern void __percpu **hyperv_pcpu_output_arg;
extern u64 hv_current_partition_id;
@@ -170,8 +168,6 @@ int hyperv_fill_flush_guest_mapping_list(
struct hv_guest_mapping_flush_list *flush,
u64 start_gfn, u64 end_gfn);
-extern bool hv_root_partition;
-
#ifdef CONFIG_X86_64
void hv_apic_init(void);
void __init hv_init_spinlocks(void);
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index a6c327f8ad9e..2ef1f6513c68 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -295,6 +295,7 @@ struct kvm_debug_exit_arch {
#define KVM_GUESTDBG_USE_HW_BP 0x00020000
#define KVM_GUESTDBG_INJECT_DB 0x00040000
#define KVM_GUESTDBG_INJECT_BP 0x00080000
+#define KVM_GUESTDBG_BLOCKIRQ 0x00100000
/* for KVM_SET_GUEST_DEBUG */
struct kvm_guest_debug_arch {
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 3e625c61f008..8f4e8fa6ed75 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -136,9 +136,6 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
obj-$(CONFIG_OF) += devicetree.o
obj-$(CONFIG_UPROBES) += uprobes.o
-obj-y += sysfb.o
-obj-$(CONFIG_X86_SYSFB) += sysfb_simplefb.o
-obj-$(CONFIG_EFI) += sysfb_efi.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
obj-$(CONFIG_TRACING) += tracepoint.o
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index 9ac696487b13..ed837383de5c 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -331,7 +331,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start,
int i;
if (iommu_start == -1)
- return -1;
+ return -ENOMEM;
for_each_sg(start, s, nelems, i) {
unsigned long pages, addr;
@@ -380,13 +380,13 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir, unsigned long attrs)
{
struct scatterlist *s, *ps, *start_sg, *sgmap;
- int need = 0, nextneed, i, out, start;
+ int need = 0, nextneed, i, out, start, ret;
unsigned long pages = 0;
unsigned int seg_size;
unsigned int max_seg_size;
if (nents == 0)
- return 0;
+ return -EINVAL;
out = 0;
start = 0;
@@ -414,8 +414,9 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
if (!iommu_merge || !nextneed || !need || s->offset ||
(s->length + seg_size > max_seg_size) ||
(ps->offset + ps->length) % PAGE_SIZE) {
- if (dma_map_cont(dev, start_sg, i - start,
- sgmap, pages, need) < 0)
+ ret = dma_map_cont(dev, start_sg, i - start,
+ sgmap, pages, need);
+ if (ret < 0)
goto error;
out++;
@@ -432,7 +433,8 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
pages += iommu_num_pages(s->offset, s->length, PAGE_SIZE);
ps = s;
}
- if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
+ ret = dma_map_cont(dev, start_sg, i - start, sgmap, pages, need);
+ if (ret < 0)
goto error;
out++;
flush_gart();
@@ -456,9 +458,7 @@ error:
panic("dma_map_sg: overflow on %lu pages\n", pages);
iommu_full(dev, pages << PAGE_SHIFT, dir);
- for_each_sg(sg, s, nents, i)
- s->dma_address = DMA_MAPPING_ERROR;
- return 0;
+ return ret;
}
/* allocate and map a coherent mapping */
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index 294ed4392a0e..10562885f5fc 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -109,14 +109,13 @@ static u32 __init allocate_aperture(void)
* memory. Unfortunately we cannot move it up because that would
* make the IOMMU useless.
*/
- addr = memblock_find_in_range(GART_MIN_ADDR, GART_MAX_ADDR,
- aper_size, aper_size);
+ addr = memblock_phys_alloc_range(aper_size, aper_size,
+ GART_MIN_ADDR, GART_MAX_ADDR);
if (!addr) {
pr_err("Cannot allocate aperture memory hole [mem %#010lx-%#010lx] (%uKB)\n",
addr, addr + aper_size - 1, aper_size >> 10);
return 0;
}
- memblock_reserve(addr, aper_size);
pr_info("Mapping aperture over RAM [mem %#010lx-%#010lx] (%uKB)\n",
addr, addr + aper_size - 1, aper_size >> 10);
register_nosave_region(addr >> PAGE_SHIFT,
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index c890d67a64ad..e095c28d27ae 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -17,7 +17,6 @@
#include <linux/irq.h>
#include <linux/kexec.h>
#include <linux/i8253.h>
-#include <linux/panic_notifier.h>
#include <linux/random.h>
#include <asm/processor.h>
#include <asm/hypervisor.h>
@@ -36,10 +35,7 @@
/* Is Linux running as the root partition? */
bool hv_root_partition;
-EXPORT_SYMBOL_GPL(hv_root_partition);
-
struct ms_hyperv_info ms_hyperv;
-EXPORT_SYMBOL_GPL(ms_hyperv);
#if IS_ENABLED(CONFIG_HYPERV)
static void (*vmbus_handler)(void);
@@ -65,14 +61,12 @@ void hv_setup_vmbus_handler(void (*handler)(void))
{
vmbus_handler = handler;
}
-EXPORT_SYMBOL_GPL(hv_setup_vmbus_handler);
void hv_remove_vmbus_handler(void)
{
/* We have no way to deallocate the interrupt gate */
vmbus_handler = NULL;
}
-EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
/*
* Routines to do per-architecture handling of stimer0
@@ -107,25 +101,21 @@ void hv_setup_kexec_handler(void (*handler)(void))
{
hv_kexec_handler = handler;
}
-EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
void hv_remove_kexec_handler(void)
{
hv_kexec_handler = NULL;
}
-EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
{
hv_crash_handler = handler;
}
-EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
void hv_remove_crash_handler(void)
{
hv_crash_handler = NULL;
}
-EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
#ifdef CONFIG_KEXEC_CORE
static void hv_machine_shutdown(void)
@@ -335,16 +325,6 @@ static void __init ms_hyperv_init_platform(void)
ms_hyperv.nested_features);
}
- /*
- * Hyper-V expects to get crash register data or kmsg when
- * crash enlightment is available and system crashes. Set
- * crash_kexec_post_notifiers to be true to make sure that
- * calling crash enlightment interface before running kdump
- * kernel.
- */
- if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
- crash_kexec_post_notifiers = true;
-
#ifdef CONFIG_X86_LOCAL_APIC
if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS &&
ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
@@ -373,10 +353,17 @@ static void __init ms_hyperv_init_platform(void)
machine_ops.crash_shutdown = hv_machine_crash_shutdown;
#endif
if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) {
+ /*
+ * Writing to synthetic MSR 0x40000118 updates/changes the
+ * guest visible CPUIDs. Setting bit 0 of this MSR enables
+ * guests to report invariant TSC feature through CPUID
+ * instruction, CPUID 0x800000007/EDX, bit 8. See code in
+ * early_init_intel() where this bit is examined. The
+ * setting of this MSR bit should happen before init_intel()
+ * is called.
+ */
wrmsrl(HV_X64_MSR_TSC_INVARIANT_CONTROL, 0x1);
setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
- } else {
- mark_tsc_unstable("running on Hyper-V");
}
/*
@@ -437,6 +424,13 @@ static void __init ms_hyperv_init_platform(void)
/* Register Hyper-V specific clocksource */
hv_init_clocksource();
#endif
+ /*
+ * TSC should be marked as unstable only after Hyper-V
+ * clocksource has been initialized. This ensures that the
+ * stability of the sched_clock is not altered.
+ */
+ if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT))
+ mark_tsc_unstable("running on Hyper-V");
}
static bool __init ms_hyperv_x2apic_available(void)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 67f590425d90..d8c64dab0efe 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -432,7 +432,7 @@ SYM_FUNC_START(early_ignore_irq)
pushl 32(%esp)
pushl 40(%esp)
pushl $int_msg
- call printk
+ call _printk
call dump_stack
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index a26643dc6bd6..b656456c3a94 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -884,10 +884,11 @@ static void kvm_wait(u8 *ptr, u8 val)
} else {
local_irq_disable();
+ /* safe_halt() will enable IRQ */
if (READ_ONCE(*ptr) == val)
safe_halt();
-
- local_irq_enable();
+ else
+ local_irq_enable();
}
}
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index aa15132228da..525876e7b9f4 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -154,7 +154,7 @@ static struct ldt_struct *alloc_ldt_struct(unsigned int num_entries)
if (num_entries > LDT_ENTRIES)
return NULL;
- new_ldt = kmalloc(sizeof(struct ldt_struct), GFP_KERNEL);
+ new_ldt = kmalloc(sizeof(struct ldt_struct), GFP_KERNEL_ACCOUNT);
if (!new_ldt)
return NULL;
@@ -168,9 +168,9 @@ static struct ldt_struct *alloc_ldt_struct(unsigned int num_entries)
* than PAGE_SIZE.
*/
if (alloc_size > PAGE_SIZE)
- new_ldt->entries = vzalloc(alloc_size);
+ new_ldt->entries = __vmalloc(alloc_size, GFP_KERNEL_ACCOUNT | __GFP_ZERO);
else
- new_ldt->entries = (void *)get_zeroed_page(GFP_KERNEL);
+ new_ldt->entries = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
if (!new_ldt->entries) {
kfree(new_ldt);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 63b20536c8d2..79f164141116 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -5,6 +5,7 @@
* This file contains the setup_arch() code, which handles the architecture-dependent
* parts of early kernel initialization.
*/
+#include <linux/acpi.h>
#include <linux/console.h>
#include <linux/crash_dump.h>
#include <linux/dma-map-ops.h>
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 06743ec054d2..b52407c56000 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -34,7 +34,13 @@ static inline void signal_compat_build_tests(void)
BUILD_BUG_ON(NSIGSYS != 2);
/* This is part of the ABI and can never change in size: */
+ BUILD_BUG_ON(sizeof(siginfo_t) != 128);
BUILD_BUG_ON(sizeof(compat_siginfo_t) != 128);
+
+ /* This is a part of the ABI and can never change in alignment */
+ BUILD_BUG_ON(__alignof__(siginfo_t) != 8);
+ BUILD_BUG_ON(__alignof__(compat_siginfo_t) != 4);
+
/*
* The offsets of all the (unioned) si_fields are fixed
* in the ABI, of course. Make sure none of them ever
diff --git a/arch/x86/kvm/debugfs.c b/arch/x86/kvm/debugfs.c
index 95a98413dc32..54a83a744538 100644
--- a/arch/x86/kvm/debugfs.c
+++ b/arch/x86/kvm/debugfs.c
@@ -7,6 +7,8 @@
#include <linux/kvm_host.h>
#include <linux/debugfs.h>
#include "lapic.h"
+#include "mmu.h"
+#include "mmu/mmu_internal.h"
static int vcpu_get_timer_advance_ns(void *data, u64 *val)
{
@@ -73,3 +75,112 @@ void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu, struct dentry *debugfs_
&vcpu_tsc_scaling_frac_fops);
}
}
+
+/*
+ * This covers statistics <1024 (11=log(1024)+1), which should be enough to
+ * cover RMAP_RECYCLE_THRESHOLD.
+ */
+#define RMAP_LOG_SIZE 11
+
+static const char *kvm_lpage_str[KVM_NR_PAGE_SIZES] = { "4K", "2M", "1G" };
+
+static int kvm_mmu_rmaps_stat_show(struct seq_file *m, void *v)
+{
+ struct kvm_rmap_head *rmap;
+ struct kvm *kvm = m->private;
+ struct kvm_memory_slot *slot;
+ struct kvm_memslots *slots;
+ unsigned int lpage_size, index;
+ /* Still small enough to be on the stack */
+ unsigned int *log[KVM_NR_PAGE_SIZES], *cur;
+ int i, j, k, l, ret;
+
+ ret = -ENOMEM;
+ memset(log, 0, sizeof(log));
+ for (i = 0; i < KVM_NR_PAGE_SIZES; i++) {
+ log[i] = kcalloc(RMAP_LOG_SIZE, sizeof(unsigned int), GFP_KERNEL);
+ if (!log[i])
+ goto out;
+ }
+
+ mutex_lock(&kvm->slots_lock);
+ write_lock(&kvm->mmu_lock);
+
+ for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
+ slots = __kvm_memslots(kvm, i);
+ for (j = 0; j < slots->used_slots; j++) {
+ slot = &slots->memslots[j];
+ for (k = 0; k < KVM_NR_PAGE_SIZES; k++) {
+ rmap = slot->arch.rmap[k];
+ lpage_size = kvm_mmu_slot_lpages(slot, k + 1);
+ cur = log[k];
+ for (l = 0; l < lpage_size; l++) {
+ index = ffs(pte_list_count(&rmap[l]));
+ if (WARN_ON_ONCE(index >= RMAP_LOG_SIZE))
+ index = RMAP_LOG_SIZE - 1;
+ cur[index]++;
+ }
+ }
+ }
+ }
+
+ write_unlock(&kvm->mmu_lock);
+ mutex_unlock(&kvm->slots_lock);
+
+ /* index=0 counts no rmap; index=1 counts 1 rmap */
+ seq_printf(m, "Rmap_Count:\t0\t1\t");
+ for (i = 2; i < RMAP_LOG_SIZE; i++) {
+ j = 1 << (i - 1);
+ k = (1 << i) - 1;
+ seq_printf(m, "%d-%d\t", j, k);
+ }
+ seq_printf(m, "\n");
+
+ for (i = 0; i < KVM_NR_PAGE_SIZES; i++) {
+ seq_printf(m, "Level=%s:\t", kvm_lpage_str[i]);
+ cur = log[i];
+ for (j = 0; j < RMAP_LOG_SIZE; j++)
+ seq_printf(m, "%d\t", cur[j]);
+ seq_printf(m, "\n");
+ }
+
+ ret = 0;
+out:
+ for (i = 0; i < KVM_NR_PAGE_SIZES; i++)
+ kfree(log[i]);
+
+ return ret;
+}
+
+static int kvm_mmu_rmaps_stat_open(struct inode *inode, struct file *file)
+{
+ struct kvm *kvm = inode->i_private;
+
+ if (!kvm_get_kvm_safe(kvm))
+ return -ENOENT;
+
+ return single_open(file, kvm_mmu_rmaps_stat_show, kvm);
+}
+
+static int kvm_mmu_rmaps_stat_release(struct inode *inode, struct file *file)
+{
+ struct kvm *kvm = inode->i_private;
+
+ kvm_put_kvm(kvm);
+
+ return single_release(inode, file);
+}
+
+static const struct file_operations mmu_rmaps_stat_fops = {
+ .open = kvm_mmu_rmaps_stat_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = kvm_mmu_rmaps_stat_release,
+};
+
+int kvm_arch_create_vm_debugfs(struct kvm *kvm)
+{
+ debugfs_create_file("mmu_rmaps_stat", 0644, kvm->debugfs_dentry, kvm,
+ &mmu_rmaps_stat_fops);
+ return 0;
+}
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 41d2a53c5dea..232a86a6faaf 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -88,6 +88,10 @@ static bool synic_has_vector_auto_eoi(struct kvm_vcpu_hv_synic *synic,
static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
int vector)
{
+ struct kvm_vcpu *vcpu = hv_synic_to_vcpu(synic);
+ struct kvm_hv *hv = to_kvm_hv(vcpu->kvm);
+ int auto_eoi_old, auto_eoi_new;
+
if (vector < HV_SYNIC_FIRST_VALID_VECTOR)
return;
@@ -96,10 +100,30 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
else
__clear_bit(vector, synic->vec_bitmap);
+ auto_eoi_old = bitmap_weight(synic->auto_eoi_bitmap, 256);
+
if (synic_has_vector_auto_eoi(synic, vector))
__set_bit(vector, synic->auto_eoi_bitmap);
else
__clear_bit(vector, synic->auto_eoi_bitmap);
+
+ auto_eoi_new = bitmap_weight(synic->auto_eoi_bitmap, 256);
+
+ if (!!auto_eoi_old == !!auto_eoi_new)
+ return;
+
+ mutex_lock(&vcpu->kvm->arch.apicv_update_lock);
+
+ if (auto_eoi_new)
+ hv->synic_auto_eoi_used++;
+ else
+ hv->synic_auto_eoi_used--;
+
+ __kvm_request_apicv_update(vcpu->kvm,
+ !hv->synic_auto_eoi_used,
+ APICV_INHIBIT_REASON_HYPERV);
+
+ mutex_unlock(&vcpu->kvm->arch.apicv_update_lock);
}
static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint,
@@ -933,12 +957,6 @@ int kvm_hv_activate_synic(struct kvm_vcpu *vcpu, bool dont_zero_synic_pages)
synic = to_hv_synic(vcpu);
- /*
- * Hyper-V SynIC auto EOI SINT's are
- * not compatible with APICV, so request
- * to deactivate APICV permanently.
- */
- kvm_request_apicv_update(vcpu->kvm, false, APICV_INHIBIT_REASON_HYPERV);
synic->active = true;
synic->dont_zero_synic_pages = dont_zero_synic_pages;
synic->control = HV_SYNIC_CONTROL_ENABLE;
@@ -2476,6 +2494,8 @@ int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
if (!cpu_smt_possible())
ent->eax |= HV_X64_NO_NONARCH_CORESHARING;
+
+ ent->eax |= HV_DEPRECATING_AEOI_RECOMMENDED;
/*
* Default number of spinlock retry attempts, matches
* HyperV 2016.
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index a6e218c6140d..5a69cce4d72d 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -220,7 +220,8 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
struct kvm_pit *pit = vcpu->kvm->arch.vpit;
struct hrtimer *timer;
- if (!kvm_vcpu_is_bsp(vcpu) || !pit)
+ /* Somewhat arbitrarily make vcpu0 the owner of the PIT. */
+ if (vcpu->vcpu_id || !pit)
return;
timer = &pit->pit_state.timer;
diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h
index 11e4065e1617..bbd4a5d18b5d 100644
--- a/arch/x86/kvm/ioapic.h
+++ b/arch/x86/kvm/ioapic.h
@@ -35,11 +35,7 @@ struct kvm_vcpu;
#define IOAPIC_INIT 0x5
#define IOAPIC_EXTINT 0x7
-#ifdef CONFIG_X86
#define RTC_GSI 8
-#else
-#define RTC_GSI -1U
-#endif
struct dest_map {
/* vcpu bitmap where IRQ has been sent */
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index ba5a27879f1d..76fb00921203 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -192,6 +192,9 @@ void kvm_recalculate_apic_map(struct kvm *kvm)
if (atomic_read_acquire(&kvm->arch.apic_map_dirty) == CLEAN)
return;
+ WARN_ONCE(!irqchip_in_kernel(kvm),
+ "Dirty APIC map without an in-kernel local APIC");
+
mutex_lock(&kvm->arch.apic_map_lock);
/*
* Read kvm->arch.apic_map_dirty before kvm->arch.apic_map
@@ -2265,9 +2268,6 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
u64 old_value = vcpu->arch.apic_base;
struct kvm_lapic *apic = vcpu->arch.apic;
- if (!apic)
- value |= MSR_IA32_APICBASE_BSP;
-
vcpu->arch.apic_base = value;
if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE)
@@ -2323,6 +2323,13 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
struct kvm_lapic *apic = vcpu->arch.apic;
int i;
+ if (!init_event) {
+ vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE |
+ MSR_IA32_APICBASE_ENABLE;
+ if (kvm_vcpu_is_reset_bsp(vcpu))
+ vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP;
+ }
+
if (!apic)
return;
@@ -2330,8 +2337,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
hrtimer_cancel(&apic->lapic_timer.timer);
if (!init_event) {
- kvm_lapic_set_base(vcpu, APIC_DEFAULT_PHYS_BASE |
- MSR_IA32_APICBASE_ENABLE);
+ apic->base_address = APIC_DEFAULT_PHYS_BASE;
+
kvm_apic_set_xapic_id(apic, vcpu->vcpu_id);
}
kvm_apic_set_version(apic->vcpu);
@@ -2364,9 +2371,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
apic->highest_isr_cache = -1;
update_divide_count(apic);
atomic_set(&apic->lapic_timer.pending, 0);
- if (kvm_vcpu_is_bsp(vcpu))
- kvm_lapic_set_base(vcpu,
- vcpu->arch.apic_base | MSR_IA32_APICBASE_BSP);
+
vcpu->arch.pv_eoi.msr_val = 0;
apic_update_ppr(apic);
if (vcpu->arch.apicv_active) {
@@ -2476,11 +2481,6 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu, int timer_advance_ns)
lapic_timer_advance_dynamic = false;
}
- /*
- * APIC is created enabled. This will prevent kvm_lapic_set_base from
- * thinking that APIC state has changed.
- */
- vcpu->arch.apic_base = MSR_IA32_APICBASE_ENABLE;
static_branch_inc(&apic_sw_disabled.key); /* sw disabled at reset */
kvm_iodevice_init(&apic->dev, &apic_mmio_ops);
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 83e6c6965f1e..e9688a9f7b57 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -240,4 +240,29 @@ static inline bool kvm_memslots_have_rmaps(struct kvm *kvm)
return smp_load_acquire(&kvm->arch.memslots_have_rmaps);
}
+static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level)
+{
+ /* KVM_HPAGE_GFN_SHIFT(PG_LEVEL_4K) must be 0. */
+ return (gfn >> KVM_HPAGE_GFN_SHIFT(level)) -
+ (base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
+}
+
+static inline unsigned long
+__kvm_mmu_slot_lpages(struct kvm_memory_slot *slot, unsigned long npages,
+ int level)
+{
+ return gfn_to_index(slot->base_gfn + npages - 1,
+ slot->base_gfn, level) + 1;
+}
+
+static inline unsigned long
+kvm_mmu_slot_lpages(struct kvm_memory_slot *slot, int level)
+{
+ return __kvm_mmu_slot_lpages(slot, slot->npages, level);
+}
+
+static inline void kvm_update_page_stats(struct kvm *kvm, int level, int count)
+{
+ atomic64_add(count, &kvm->stat.pages[level - 1]);
+}
#endif
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 47b765270239..2d7e61122af8 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -97,6 +97,7 @@ module_param_named(flush_on_reuse, force_flush_and_sync_on_reuse, bool, 0644);
bool tdp_enabled = false;
static int max_huge_page_level __read_mostly;
+static int tdp_root_level __read_mostly;
static int max_tdp_level __read_mostly;
enum {
@@ -137,12 +138,22 @@ module_param(dbg, bool, 0644);
#include <trace/events/kvm.h>
-/* make pte_list_desc fit well in cache line */
-#define PTE_LIST_EXT 3
+/* make pte_list_desc fit well in cache lines */
+#define PTE_LIST_EXT 14
+/*
+ * Slight optimization of cacheline layout, by putting `more' and `spte_count'
+ * at the start; then accessing it will only use one single cacheline for
+ * either full (entries==PTE_LIST_EXT) case or entries<=6.
+ */
struct pte_list_desc {
- u64 *sptes[PTE_LIST_EXT];
struct pte_list_desc *more;
+ /*
+ * Stores number of entries stored in the pte_list_desc. No need to be
+ * u64 but just for easier alignment. When PTE_LIST_EXT, means full.
+ */
+ u64 spte_count;
+ u64 *sptes[PTE_LIST_EXT];
};
struct kvm_shadow_walk_iterator {
@@ -193,7 +204,7 @@ struct kvm_mmu_role_regs {
* the single source of truth for the MMU's state.
*/
#define BUILD_MMU_ROLE_REGS_ACCESSOR(reg, name, flag) \
-static inline bool ____is_##reg##_##name(struct kvm_mmu_role_regs *regs)\
+static inline bool __maybe_unused ____is_##reg##_##name(struct kvm_mmu_role_regs *regs)\
{ \
return !!(regs->reg & flag); \
}
@@ -215,7 +226,7 @@ BUILD_MMU_ROLE_REGS_ACCESSOR(efer, lma, EFER_LMA);
* and the vCPU may be incorrect/irrelevant.
*/
#define BUILD_MMU_ROLE_ACCESSOR(base_or_ext, reg, name) \
-static inline bool is_##reg##_##name(struct kvm_mmu *mmu) \
+static inline bool __maybe_unused is_##reg##_##name(struct kvm_mmu *mmu) \
{ \
return !!(mmu->mmu_role. base_or_ext . reg##_##name); \
}
@@ -323,12 +334,6 @@ static bool check_mmio_spte(struct kvm_vcpu *vcpu, u64 spte)
static gpa_t translate_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access,
struct x86_exception *exception)
{
- /* Check if guest physical address doesn't exceed guest maximum */
- if (kvm_vcpu_is_illegal_gpa(vcpu, gpa)) {
- exception->error_code |= PFERR_RSVD_MASK;
- return UNMAPPED_GVA;
- }
-
return gpa;
}
@@ -592,12 +597,13 @@ static bool mmu_spte_update(u64 *sptep, u64 new_spte)
* Rules for using mmu_spte_clear_track_bits:
* It sets the sptep from present to nonpresent, and track the
* state bits, it is used to clear the last level sptep.
- * Returns non-zero if the PTE was previously valid.
+ * Returns the old PTE.
*/
-static int mmu_spte_clear_track_bits(u64 *sptep)
+static int mmu_spte_clear_track_bits(struct kvm *kvm, u64 *sptep)
{
kvm_pfn_t pfn;
u64 old_spte = *sptep;
+ int level = sptep_to_sp(sptep)->role.level;
if (!spte_has_volatile_bits(old_spte))
__update_clear_spte_fast(sptep, 0ull);
@@ -605,7 +611,9 @@ static int mmu_spte_clear_track_bits(u64 *sptep)
old_spte = __update_clear_spte_slow(sptep, 0ull);
if (!is_shadow_present_pte(old_spte))
- return 0;
+ return old_spte;
+
+ kvm_update_page_stats(kvm, level, -1);
pfn = spte_to_pfn(old_spte);
@@ -622,7 +630,7 @@ static int mmu_spte_clear_track_bits(u64 *sptep)
if (is_dirty_spte(old_spte))
kvm_set_pfn_dirty(pfn);
- return 1;
+ return old_spte;
}
/*
@@ -686,28 +694,36 @@ static bool mmu_spte_age(u64 *sptep)
static void walk_shadow_page_lockless_begin(struct kvm_vcpu *vcpu)
{
- /*
- * Prevent page table teardown by making any free-er wait during
- * kvm_flush_remote_tlbs() IPI to all active vcpus.
- */
- local_irq_disable();
+ if (is_tdp_mmu(vcpu->arch.mmu)) {
+ kvm_tdp_mmu_walk_lockless_begin();
+ } else {
+ /*
+ * Prevent page table teardown by making any free-er wait during
+ * kvm_flush_remote_tlbs() IPI to all active vcpus.
+ */
+ local_irq_disable();
- /*
- * Make sure a following spte read is not reordered ahead of the write
- * to vcpu->mode.
- */
- smp_store_mb(vcpu->mode, READING_SHADOW_PAGE_TABLES);
+ /*
+ * Make sure a following spte read is not reordered ahead of the write
+ * to vcpu->mode.
+ */
+ smp_store_mb(vcpu->mode, READING_SHADOW_PAGE_TABLES);
+ }
}
static void walk_shadow_page_lockless_end(struct kvm_vcpu *vcpu)
{
- /*
- * Make sure the write to vcpu->mode is not reordered in front of
- * reads to sptes. If it does, kvm_mmu_commit_zap_page() can see us
- * OUTSIDE_GUEST_MODE and proceed to free the shadow page table.
- */
- smp_store_release(&vcpu->mode, OUTSIDE_GUEST_MODE);
- local_irq_enable();
+ if (is_tdp_mmu(vcpu->arch.mmu)) {
+ kvm_tdp_mmu_walk_lockless_end();
+ } else {
+ /*
+ * Make sure the write to vcpu->mode is not reordered in front of
+ * reads to sptes. If it does, kvm_mmu_commit_zap_page() can see us
+ * OUTSIDE_GUEST_MODE and proceed to free the shadow page table.
+ */
+ smp_store_release(&vcpu->mode, OUTSIDE_GUEST_MODE);
+ local_irq_enable();
+ }
}
static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu, bool maybe_indirect)
@@ -786,7 +802,7 @@ static struct kvm_lpage_info *lpage_info_slot(gfn_t gfn,
return &slot->arch.lpage_info[level - 2][idx];
}
-static void update_gfn_disallow_lpage_count(struct kvm_memory_slot *slot,
+static void update_gfn_disallow_lpage_count(const struct kvm_memory_slot *slot,
gfn_t gfn, int count)
{
struct kvm_lpage_info *linfo;
@@ -799,12 +815,12 @@ static void update_gfn_disallow_lpage_count(struct kvm_memory_slot *slot,
}
}
-void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn)
+void kvm_mmu_gfn_disallow_lpage(const struct kvm_memory_slot *slot, gfn_t gfn)
{
update_gfn_disallow_lpage_count(slot, gfn, 1);
}
-void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn)
+void kvm_mmu_gfn_allow_lpage(const struct kvm_memory_slot *slot, gfn_t gfn)
{
update_gfn_disallow_lpage_count(slot, gfn, -1);
}
@@ -893,7 +909,7 @@ static int pte_list_add(struct kvm_vcpu *vcpu, u64 *spte,
struct kvm_rmap_head *rmap_head)
{
struct pte_list_desc *desc;
- int i, count = 0;
+ int count = 0;
if (!rmap_head->val) {
rmap_printk("%p %llx 0->1\n", spte, *spte);
@@ -903,24 +919,24 @@ static int pte_list_add(struct kvm_vcpu *vcpu, u64 *spte,
desc = mmu_alloc_pte_list_desc(vcpu);
desc->sptes[0] = (u64 *)rmap_head->val;
desc->sptes[1] = spte;
+ desc->spte_count = 2;
rmap_head->val = (unsigned long)desc | 1;
++count;
} else {
rmap_printk("%p %llx many->many\n", spte, *spte);
desc = (struct pte_list_desc *)(rmap_head->val & ~1ul);
- while (desc->sptes[PTE_LIST_EXT-1]) {
+ while (desc->spte_count == PTE_LIST_EXT) {
count += PTE_LIST_EXT;
-
if (!desc->more) {
desc->more = mmu_alloc_pte_list_desc(vcpu);
desc = desc->more;
+ desc->spte_count = 0;
break;
}
desc = desc->more;
}
- for (i = 0; desc->sptes[i]; ++i)
- ++count;
- desc->sptes[i] = spte;
+ count += desc->spte_count;
+ desc->sptes[desc->spte_count++] = spte;
}
return count;
}
@@ -930,13 +946,12 @@ pte_list_desc_remove_entry(struct kvm_rmap_head *rmap_head,
struct pte_list_desc *desc, int i,
struct pte_list_desc *prev_desc)
{
- int j;
+ int j = desc->spte_count - 1;
- for (j = PTE_LIST_EXT - 1; !desc->sptes[j] && j > i; --j)
- ;
desc->sptes[i] = desc->sptes[j];
desc->sptes[j] = NULL;
- if (j != 0)
+ desc->spte_count--;
+ if (desc->spte_count)
return;
if (!prev_desc && !desc->more)
rmap_head->val = 0;
@@ -969,7 +984,7 @@ static void __pte_list_remove(u64 *spte, struct kvm_rmap_head *rmap_head)
desc = (struct pte_list_desc *)(rmap_head->val & ~1ul);
prev_desc = NULL;
while (desc) {
- for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i) {
+ for (i = 0; i < desc->spte_count; ++i) {
if (desc->sptes[i] == spte) {
pte_list_desc_remove_entry(rmap_head,
desc, i, prev_desc);
@@ -984,30 +999,68 @@ static void __pte_list_remove(u64 *spte, struct kvm_rmap_head *rmap_head)
}
}
-static void pte_list_remove(struct kvm_rmap_head *rmap_head, u64 *sptep)
+static void pte_list_remove(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
+ u64 *sptep)
{
- mmu_spte_clear_track_bits(sptep);
+ mmu_spte_clear_track_bits(kvm, sptep);
__pte_list_remove(sptep, rmap_head);
}
-static struct kvm_rmap_head *__gfn_to_rmap(gfn_t gfn, int level,
- struct kvm_memory_slot *slot)
+/* Return true if rmap existed, false otherwise */
+static bool pte_list_destroy(struct kvm *kvm, struct kvm_rmap_head *rmap_head)
{
- unsigned long idx;
+ struct pte_list_desc *desc, *next;
+ int i;
- idx = gfn_to_index(gfn, slot->base_gfn, level);
- return &slot->arch.rmap[level - PG_LEVEL_4K][idx];
+ if (!rmap_head->val)
+ return false;
+
+ if (!(rmap_head->val & 1)) {
+ mmu_spte_clear_track_bits(kvm, (u64 *)rmap_head->val);
+ goto out;
+ }
+
+ desc = (struct pte_list_desc *)(rmap_head->val & ~1ul);
+
+ for (; desc; desc = next) {
+ for (i = 0; i < desc->spte_count; i++)
+ mmu_spte_clear_track_bits(kvm, desc->sptes[i]);
+ next = desc->more;
+ mmu_free_pte_list_desc(desc);
+ }
+out:
+ /* rmap_head is meaningless now, remember to reset it */
+ rmap_head->val = 0;
+ return true;
}
-static struct kvm_rmap_head *gfn_to_rmap(struct kvm *kvm, gfn_t gfn,
- struct kvm_mmu_page *sp)
+unsigned int pte_list_count(struct kvm_rmap_head *rmap_head)
{
- struct kvm_memslots *slots;
- struct kvm_memory_slot *slot;
+ struct pte_list_desc *desc;
+ unsigned int count = 0;
- slots = kvm_memslots_for_spte_role(kvm, sp->role);
- slot = __gfn_to_memslot(slots, gfn);
- return __gfn_to_rmap(gfn, sp->role.level, slot);
+ if (!rmap_head->val)
+ return 0;
+ else if (!(rmap_head->val & 1))
+ return 1;
+
+ desc = (struct pte_list_desc *)(rmap_head->val & ~1ul);
+
+ while (desc) {
+ count += desc->spte_count;
+ desc = desc->more;
+ }
+
+ return count;
+}
+
+static struct kvm_rmap_head *gfn_to_rmap(gfn_t gfn, int level,
+ const struct kvm_memory_slot *slot)
+{
+ unsigned long idx;
+
+ idx = gfn_to_index(gfn, slot->base_gfn, level);
+ return &slot->arch.rmap[level - PG_LEVEL_4K][idx];
}
static bool rmap_can_add(struct kvm_vcpu *vcpu)
@@ -1020,24 +1073,39 @@ static bool rmap_can_add(struct kvm_vcpu *vcpu)
static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
{
+ struct kvm_memory_slot *slot;
struct kvm_mmu_page *sp;
struct kvm_rmap_head *rmap_head;
sp = sptep_to_sp(spte);
kvm_mmu_page_set_gfn(sp, spte - sp->spt, gfn);
- rmap_head = gfn_to_rmap(vcpu->kvm, gfn, sp);
+ slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
+ rmap_head = gfn_to_rmap(gfn, sp->role.level, slot);
return pte_list_add(vcpu, spte, rmap_head);
}
+
static void rmap_remove(struct kvm *kvm, u64 *spte)
{
+ struct kvm_memslots *slots;
+ struct kvm_memory_slot *slot;
struct kvm_mmu_page *sp;
gfn_t gfn;
struct kvm_rmap_head *rmap_head;
sp = sptep_to_sp(spte);
gfn = kvm_mmu_page_get_gfn(sp, spte - sp->spt);
- rmap_head = gfn_to_rmap(kvm, gfn, sp);
+
+ /*
+ * Unlike rmap_add and rmap_recycle, rmap_remove does not run in the
+ * context of a vCPU so have to determine which memslots to use based
+ * on context information in sp->role.
+ */
+ slots = kvm_memslots_for_spte_role(kvm, sp->role);
+
+ slot = __gfn_to_memslot(slots, gfn);
+ rmap_head = gfn_to_rmap(gfn, sp->role.level, slot);
+
__pte_list_remove(spte, rmap_head);
}
@@ -1119,7 +1187,9 @@ out:
static void drop_spte(struct kvm *kvm, u64 *sptep)
{
- if (mmu_spte_clear_track_bits(sptep))
+ u64 old_spte = mmu_spte_clear_track_bits(kvm, sptep);
+
+ if (is_shadow_present_pte(old_spte))
rmap_remove(kvm, sptep);
}
@@ -1129,7 +1199,6 @@ static bool __drop_large_spte(struct kvm *kvm, u64 *sptep)
if (is_large_pte(*sptep)) {
WARN_ON(sptep_to_sp(sptep)->role.level == PG_LEVEL_4K);
drop_spte(kvm, sptep);
- --kvm->stat.lpages;
return true;
}
@@ -1218,7 +1287,7 @@ static bool spte_wrprot_for_clear_dirty(u64 *sptep)
* Returns true iff any D or W bits were cleared.
*/
static bool __rmap_clear_dirty(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
- struct kvm_memory_slot *slot)
+ const struct kvm_memory_slot *slot)
{
u64 *sptep;
struct rmap_iterator iter;
@@ -1256,8 +1325,8 @@ static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm,
return;
while (mask) {
- rmap_head = __gfn_to_rmap(slot->base_gfn + gfn_offset + __ffs(mask),
- PG_LEVEL_4K, slot);
+ rmap_head = gfn_to_rmap(slot->base_gfn + gfn_offset + __ffs(mask),
+ PG_LEVEL_4K, slot);
__rmap_write_protect(kvm, rmap_head, false);
/* clear the first set bit */
@@ -1289,8 +1358,8 @@ static void kvm_mmu_clear_dirty_pt_masked(struct kvm *kvm,
return;
while (mask) {
- rmap_head = __gfn_to_rmap(slot->base_gfn + gfn_offset + __ffs(mask),
- PG_LEVEL_4K, slot);
+ rmap_head = gfn_to_rmap(slot->base_gfn + gfn_offset + __ffs(mask),
+ PG_LEVEL_4K, slot);
__rmap_clear_dirty(kvm, rmap_head, slot);
/* clear the first set bit */
@@ -1356,7 +1425,7 @@ bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
if (kvm_memslots_have_rmaps(kvm)) {
for (i = min_level; i <= KVM_MAX_HUGEPAGE_LEVEL; ++i) {
- rmap_head = __gfn_to_rmap(gfn, i, slot);
+ rmap_head = gfn_to_rmap(gfn, i, slot);
write_protected |= __rmap_write_protect(kvm, rmap_head, true);
}
}
@@ -1377,20 +1446,9 @@ static bool rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
}
static bool kvm_zap_rmapp(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
- struct kvm_memory_slot *slot)
+ const struct kvm_memory_slot *slot)
{
- u64 *sptep;
- struct rmap_iterator iter;
- bool flush = false;
-
- while ((sptep = rmap_get_first(rmap_head, &iter))) {
- rmap_printk("spte %p %llx.\n", sptep, *sptep);
-
- pte_list_remove(rmap_head, sptep);
- flush = true;
- }
-
- return flush;
+ return pte_list_destroy(kvm, rmap_head);
}
static bool kvm_unmap_rmapp(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
@@ -1421,13 +1479,13 @@ restart:
need_flush = 1;
if (pte_write(pte)) {
- pte_list_remove(rmap_head, sptep);
+ pte_list_remove(kvm, rmap_head, sptep);
goto restart;
} else {
new_spte = kvm_mmu_changed_pte_notifier_make_spte(
*sptep, new_pfn);
- mmu_spte_clear_track_bits(sptep);
+ mmu_spte_clear_track_bits(kvm, sptep);
mmu_spte_set(sptep, new_spte);
}
}
@@ -1442,7 +1500,7 @@ restart:
struct slot_rmap_walk_iterator {
/* input fields. */
- struct kvm_memory_slot *slot;
+ const struct kvm_memory_slot *slot;
gfn_t start_gfn;
gfn_t end_gfn;
int start_level;
@@ -1462,14 +1520,13 @@ rmap_walk_init_level(struct slot_rmap_walk_iterator *iterator, int level)
{
iterator->level = level;
iterator->gfn = iterator->start_gfn;
- iterator->rmap = __gfn_to_rmap(iterator->gfn, level, iterator->slot);
- iterator->end_rmap = __gfn_to_rmap(iterator->end_gfn, level,
- iterator->slot);
+ iterator->rmap = gfn_to_rmap(iterator->gfn, level, iterator->slot);
+ iterator->end_rmap = gfn_to_rmap(iterator->end_gfn, level, iterator->slot);
}
static void
slot_rmap_walk_init(struct slot_rmap_walk_iterator *iterator,
- struct kvm_memory_slot *slot, int start_level,
+ const struct kvm_memory_slot *slot, int start_level,
int end_level, gfn_t start_gfn, gfn_t end_gfn)
{
iterator->slot = slot;
@@ -1584,12 +1641,13 @@ static bool kvm_test_age_rmapp(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
static void rmap_recycle(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
{
+ struct kvm_memory_slot *slot;
struct kvm_rmap_head *rmap_head;
struct kvm_mmu_page *sp;
sp = sptep_to_sp(spte);
-
- rmap_head = gfn_to_rmap(vcpu->kvm, gfn, sp);
+ slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
+ rmap_head = gfn_to_rmap(gfn, sp->role.level, slot);
kvm_unmap_rmapp(vcpu->kvm, rmap_head, NULL, gfn, sp->role.level, __pte(0));
kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn,
@@ -2232,8 +2290,6 @@ static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
if (is_shadow_present_pte(pte)) {
if (is_last_spte(pte, sp->role.level)) {
drop_spte(kvm, spte);
- if (is_large_pte(pte))
- --kvm->stat.lpages;
} else {
child = to_shadow_page(pte & PT64_BASE_ADDR_MASK);
drop_parent_pte(child, spte);
@@ -2716,15 +2772,12 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
pgprintk("%s: setting spte %llx\n", __func__, *sptep);
trace_kvm_mmu_set_spte(level, gfn, sptep);
- if (!was_rmapped && is_large_pte(*sptep))
- ++vcpu->kvm->stat.lpages;
- if (is_shadow_present_pte(*sptep)) {
- if (!was_rmapped) {
- rmap_count = rmap_add(vcpu, sptep, gfn);
- if (rmap_count > RMAP_RECYCLE_THRESHOLD)
- rmap_recycle(vcpu, sptep, gfn);
- }
+ if (!was_rmapped) {
+ kvm_update_page_stats(vcpu->kvm, level, 1);
+ rmap_count = rmap_add(vcpu, sptep, gfn);
+ if (rmap_count > RMAP_RECYCLE_THRESHOLD)
+ rmap_recycle(vcpu, sptep, gfn);
}
return ret;
@@ -2852,6 +2905,7 @@ int kvm_mmu_max_mapping_level(struct kvm *kvm,
kvm_pfn_t pfn, int max_level)
{
struct kvm_lpage_info *linfo;
+ int host_level;
max_level = min(max_level, max_huge_page_level);
for ( ; max_level > PG_LEVEL_4K; max_level--) {
@@ -2863,7 +2917,8 @@ int kvm_mmu_max_mapping_level(struct kvm *kvm,
if (max_level == PG_LEVEL_4K)
return PG_LEVEL_4K;
- return host_pfn_mapping_level(kvm, gfn, pfn, slot);
+ host_level = host_pfn_mapping_level(kvm, gfn, pfn, slot);
+ return min(host_level, max_level);
}
int kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, gfn_t gfn,
@@ -2887,17 +2942,12 @@ int kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, gfn_t gfn,
if (!slot)
return PG_LEVEL_4K;
- level = kvm_mmu_max_mapping_level(vcpu->kvm, slot, gfn, pfn, max_level);
- if (level == PG_LEVEL_4K)
- return level;
-
- *req_level = level = min(level, max_level);
-
/*
* Enforce the iTLB multihit workaround after capturing the requested
* level, which will be used to do precise, accurate accounting.
*/
- if (huge_page_disallowed)
+ *req_level = level = kvm_mmu_max_mapping_level(vcpu->kvm, slot, gfn, pfn, max_level);
+ if (level == PG_LEVEL_4K || huge_page_disallowed)
return PG_LEVEL_4K;
/*
@@ -2965,15 +3015,16 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
break;
drop_large_spte(vcpu, it.sptep);
- if (!is_shadow_present_pte(*it.sptep)) {
- sp = kvm_mmu_get_page(vcpu, base_gfn, it.addr,
- it.level - 1, true, ACC_ALL);
-
- link_shadow_page(vcpu, it.sptep, sp);
- if (is_tdp && huge_page_disallowed &&
- req_level >= it.level)
- account_huge_nx_page(vcpu->kvm, sp);
- }
+ if (is_shadow_present_pte(*it.sptep))
+ continue;
+
+ sp = kvm_mmu_get_page(vcpu, base_gfn, it.addr,
+ it.level - 1, true, ACC_ALL);
+
+ link_shadow_page(vcpu, it.sptep, sp);
+ if (is_tdp && huge_page_disallowed &&
+ req_level >= it.level)
+ account_huge_nx_page(vcpu->kvm, sp);
}
ret = mmu_set_spte(vcpu, it.sptep, ACC_ALL,
@@ -3122,15 +3173,40 @@ static bool is_access_allowed(u32 fault_err_code, u64 spte)
}
/*
- * Returns one of RET_PF_INVALID, RET_PF_FIXED or RET_PF_SPURIOUS.
+ * Returns the last level spte pointer of the shadow page walk for the given
+ * gpa, and sets *spte to the spte value. This spte may be non-preset. If no
+ * walk could be performed, returns NULL and *spte does not contain valid data.
+ *
+ * Contract:
+ * - Must be called between walk_shadow_page_lockless_{begin,end}.
+ * - The returned sptep must not be used after walk_shadow_page_lockless_end.
*/
-static int fast_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
- u32 error_code)
+static u64 *fast_pf_get_last_sptep(struct kvm_vcpu *vcpu, gpa_t gpa, u64 *spte)
{
struct kvm_shadow_walk_iterator iterator;
+ u64 old_spte;
+ u64 *sptep = NULL;
+
+ for_each_shadow_entry_lockless(vcpu, gpa, iterator, old_spte) {
+ sptep = iterator.sptep;
+ *spte = old_spte;
+
+ if (!is_shadow_present_pte(old_spte))
+ break;
+ }
+
+ return sptep;
+}
+
+/*
+ * Returns one of RET_PF_INVALID, RET_PF_FIXED or RET_PF_SPURIOUS.
+ */
+static int fast_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code)
+{
struct kvm_mmu_page *sp;
int ret = RET_PF_INVALID;
u64 spte = 0ull;
+ u64 *sptep = NULL;
uint retry_count = 0;
if (!page_fault_can_be_fast(error_code))
@@ -3141,14 +3217,15 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
do {
u64 new_spte;
- for_each_shadow_entry_lockless(vcpu, cr2_or_gpa, iterator, spte)
- if (!is_shadow_present_pte(spte))
- break;
+ if (is_tdp_mmu(vcpu->arch.mmu))
+ sptep = kvm_tdp_mmu_fast_pf_get_last_sptep(vcpu, gpa, &spte);
+ else
+ sptep = fast_pf_get_last_sptep(vcpu, gpa, &spte);
if (!is_shadow_present_pte(spte))
break;
- sp = sptep_to_sp(iterator.sptep);
+ sp = sptep_to_sp(sptep);
if (!is_last_spte(spte, sp->role.level))
break;
@@ -3206,8 +3283,7 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
* since the gfn is not stable for indirect shadow page. See
* Documentation/virt/kvm/locking.rst to get more detail.
*/
- if (fast_pf_fix_direct_spte(vcpu, sp, iterator.sptep, spte,
- new_spte)) {
+ if (fast_pf_fix_direct_spte(vcpu, sp, sptep, spte, new_spte)) {
ret = RET_PF_FIXED;
break;
}
@@ -3220,8 +3296,7 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
} while (true);
- trace_fast_page_fault(vcpu, cr2_or_gpa, error_code, iterator.sptep,
- spte, ret);
+ trace_fast_page_fault(vcpu, gpa, error_code, sptep, spte, ret);
walk_shadow_page_lockless_end(vcpu);
return ret;
@@ -3455,15 +3530,22 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
* the shadow page table may be a PAE or a long mode page table.
*/
pm_mask = PT_PRESENT_MASK | shadow_me_mask;
- if (mmu->shadow_root_level == PT64_ROOT_4LEVEL) {
+ if (mmu->shadow_root_level >= PT64_ROOT_4LEVEL) {
pm_mask |= PT_ACCESSED_MASK | PT_WRITABLE_MASK | PT_USER_MASK;
if (WARN_ON_ONCE(!mmu->pml4_root)) {
r = -EIO;
goto out_unlock;
}
-
mmu->pml4_root[0] = __pa(mmu->pae_root) | pm_mask;
+
+ if (mmu->shadow_root_level == PT64_ROOT_5LEVEL) {
+ if (WARN_ON_ONCE(!mmu->pml5_root)) {
+ r = -EIO;
+ goto out_unlock;
+ }
+ mmu->pml5_root[0] = __pa(mmu->pml4_root) | pm_mask;
+ }
}
for (i = 0; i < 4; ++i) {
@@ -3482,7 +3564,9 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
mmu->pae_root[i] = root | pm_mask;
}
- if (mmu->shadow_root_level == PT64_ROOT_4LEVEL)
+ if (mmu->shadow_root_level == PT64_ROOT_5LEVEL)
+ mmu->root_hpa = __pa(mmu->pml5_root);
+ else if (mmu->shadow_root_level == PT64_ROOT_4LEVEL)
mmu->root_hpa = __pa(mmu->pml4_root);
else
mmu->root_hpa = __pa(mmu->pae_root);
@@ -3498,7 +3582,10 @@ out_unlock:
static int mmu_alloc_special_roots(struct kvm_vcpu *vcpu)
{
struct kvm_mmu *mmu = vcpu->arch.mmu;
- u64 *pml4_root, *pae_root;
+ bool need_pml5 = mmu->shadow_root_level > PT64_ROOT_4LEVEL;
+ u64 *pml5_root = NULL;
+ u64 *pml4_root = NULL;
+ u64 *pae_root;
/*
* When shadowing 32-bit or PAE NPT with 64-bit NPT, the PML4 and PDP
@@ -3511,20 +3598,21 @@ static int mmu_alloc_special_roots(struct kvm_vcpu *vcpu)
return 0;
/*
- * This mess only works with 4-level paging and needs to be updated to
- * work with 5-level paging.
+ * NPT, the only paging mode that uses this horror, uses a fixed number
+ * of levels for the shadow page tables, e.g. all MMUs are 4-level or
+ * all MMus are 5-level. Thus, this can safely require that pml5_root
+ * is allocated if the other roots are valid and pml5 is needed, as any
+ * prior MMU would also have required pml5.
*/
- if (WARN_ON_ONCE(mmu->shadow_root_level != PT64_ROOT_4LEVEL))
- return -EIO;
-
- if (mmu->pae_root && mmu->pml4_root)
+ if (mmu->pae_root && mmu->pml4_root && (!need_pml5 || mmu->pml5_root))
return 0;
/*
* The special roots should always be allocated in concert. Yell and
* bail if KVM ends up in a state where only one of the roots is valid.
*/
- if (WARN_ON_ONCE(!tdp_enabled || mmu->pae_root || mmu->pml4_root))
+ if (WARN_ON_ONCE(!tdp_enabled || mmu->pae_root || mmu->pml4_root ||
+ (need_pml5 && mmu->pml5_root)))
return -EIO;
/*
@@ -3535,16 +3623,31 @@ static int mmu_alloc_special_roots(struct kvm_vcpu *vcpu)
if (!pae_root)
return -ENOMEM;
+#ifdef CONFIG_X86_64
pml4_root = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
- if (!pml4_root) {
- free_page((unsigned long)pae_root);
- return -ENOMEM;
+ if (!pml4_root)
+ goto err_pml4;
+
+ if (need_pml5) {
+ pml5_root = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
+ if (!pml5_root)
+ goto err_pml5;
}
+#endif
mmu->pae_root = pae_root;
mmu->pml4_root = pml4_root;
+ mmu->pml5_root = pml5_root;
return 0;
+
+#ifdef CONFIG_X86_64
+err_pml5:
+ free_page((unsigned long)pml4_root);
+err_pml4:
+ free_page((unsigned long)pae_root);
+ return -ENOMEM;
+#endif
}
void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
@@ -3640,6 +3743,8 @@ static bool mmio_info_in_cache(struct kvm_vcpu *vcpu, u64 addr, bool direct)
/*
* Return the level of the lowest level SPTE added to sptes.
* That SPTE may be non-present.
+ *
+ * Must be called between walk_shadow_page_lockless_{begin,end}.
*/
static int get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes, int *root_level)
{
@@ -3647,8 +3752,6 @@ static int get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes, int *root_level
int leaf = -1;
u64 spte;
- walk_shadow_page_lockless_begin(vcpu);
-
for (shadow_walk_init(&iterator, vcpu, addr),
*root_level = iterator.level;
shadow_walk_okay(&iterator);
@@ -3662,8 +3765,6 @@ static int get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes, int *root_level
break;
}
- walk_shadow_page_lockless_end(vcpu);
-
return leaf;
}
@@ -3675,11 +3776,15 @@ static bool get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
int root, leaf, level;
bool reserved = false;
+ walk_shadow_page_lockless_begin(vcpu);
+
if (is_tdp_mmu(vcpu->arch.mmu))
leaf = kvm_tdp_mmu_get_walk(vcpu, addr, sptes, &root);
else
leaf = get_walk(vcpu, addr, sptes, &root);
+ walk_shadow_page_lockless_end(vcpu);
+
if (unlikely(leaf < 0)) {
*sptep = 0ull;
return reserved;
@@ -3795,9 +3900,9 @@ static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch);
}
-static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
+static bool kvm_faultin_pfn(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
gpa_t cr2_or_gpa, kvm_pfn_t *pfn, hva_t *hva,
- bool write, bool *writable)
+ bool write, bool *writable, int *r)
{
struct kvm_memory_slot *slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
bool async;
@@ -3808,13 +3913,26 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
* be zapped before KVM inserts a new MMIO SPTE for the gfn.
*/
if (slot && (slot->flags & KVM_MEMSLOT_INVALID))
- return true;
-
- /* Don't expose private memslots to L2. */
- if (is_guest_mode(vcpu) && !kvm_is_visible_memslot(slot)) {
- *pfn = KVM_PFN_NOSLOT;
- *writable = false;
- return false;
+ goto out_retry;
+
+ if (!kvm_is_visible_memslot(slot)) {
+ /* Don't expose private memslots to L2. */
+ if (is_guest_mode(vcpu)) {
+ *pfn = KVM_PFN_NOSLOT;
+ *writable = false;
+ return false;
+ }
+ /*
+ * If the APIC access page exists but is disabled, go directly
+ * to emulation without caching the MMIO access or creating a
+ * MMIO SPTE. That way the cache doesn't need to be purged
+ * when the AVIC is re-enabled.
+ */
+ if (slot && slot->id == APIC_ACCESS_PAGE_PRIVATE_MEMSLOT &&
+ !kvm_apicv_activated(vcpu->kvm)) {
+ *r = RET_PF_EMULATE;
+ return true;
+ }
}
async = false;
@@ -3828,14 +3946,17 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
if (kvm_find_async_pf_gfn(vcpu, gfn)) {
trace_kvm_async_pf_doublefault(cr2_or_gpa, gfn);
kvm_make_request(KVM_REQ_APF_HALT, vcpu);
- return true;
+ goto out_retry;
} else if (kvm_arch_setup_async_pf(vcpu, cr2_or_gpa, gfn))
- return true;
+ goto out_retry;
}
*pfn = __gfn_to_pfn_memslot(slot, gfn, false, NULL,
write, writable, hva);
- return false;
+
+out_retry:
+ *r = RET_PF_RETRY;
+ return true;
}
static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
@@ -3854,11 +3975,9 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
if (page_fault_handle_page_track(vcpu, error_code, gfn))
return RET_PF_EMULATE;
- if (!is_tdp_mmu_fault) {
- r = fast_page_fault(vcpu, gpa, error_code);
- if (r != RET_PF_INVALID)
- return r;
- }
+ r = fast_page_fault(vcpu, gpa, error_code);
+ if (r != RET_PF_INVALID)
+ return r;
r = mmu_topup_memory_caches(vcpu, false);
if (r)
@@ -3867,9 +3986,9 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
mmu_seq = vcpu->kvm->mmu_notifier_seq;
smp_rmb();
- if (try_async_pf(vcpu, prefault, gfn, gpa, &pfn, &hva,
- write, &map_writable))
- return RET_PF_RETRY;
+ if (kvm_faultin_pfn(vcpu, prefault, gfn, gpa, &pfn, &hva,
+ write, &map_writable, &r))
+ return r;
if (handle_abnormal_pfn(vcpu, is_tdp ? 0 : gpa, gfn, pfn, ACC_ALL, &r))
return r;
@@ -4588,6 +4707,10 @@ static union kvm_mmu_role kvm_calc_mmu_role_common(struct kvm_vcpu *vcpu,
static inline int kvm_mmu_get_tdp_level(struct kvm_vcpu *vcpu)
{
+ /* tdp_root_level is architecture forced level, use it if nonzero */
+ if (tdp_root_level)
+ return tdp_root_level;
+
/* Use 5-level TDP if and only if it's useful/necessary. */
if (max_tdp_level == 5 && cpuid_maxphyaddr(vcpu) <= 48)
return 4;
@@ -5160,7 +5283,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
if (r == RET_PF_INVALID) {
r = kvm_mmu_do_page_fault(vcpu, cr2_or_gpa,
lower_32_bits(error_code), false);
- if (WARN_ON_ONCE(r == RET_PF_INVALID))
+ if (KVM_BUG_ON(r == RET_PF_INVALID, vcpu->kvm))
return -EIO;
}
@@ -5279,10 +5402,11 @@ void kvm_mmu_invpcid_gva(struct kvm_vcpu *vcpu, gva_t gva, unsigned long pcid)
*/
}
-void kvm_configure_mmu(bool enable_tdp, int tdp_max_root_level,
- int tdp_huge_page_level)
+void kvm_configure_mmu(bool enable_tdp, int tdp_forced_root_level,
+ int tdp_max_root_level, int tdp_huge_page_level)
{
tdp_enabled = enable_tdp;
+ tdp_root_level = tdp_forced_root_level;
max_tdp_level = tdp_max_root_level;
/*
@@ -5302,12 +5426,13 @@ void kvm_configure_mmu(bool enable_tdp, int tdp_max_root_level,
EXPORT_SYMBOL_GPL(kvm_configure_mmu);
/* The return value indicates if tlb flush on all vcpus is needed. */
-typedef bool (*slot_level_handler) (struct kvm *kvm, struct kvm_rmap_head *rmap_head,
- struct kvm_memory_slot *slot);
+typedef bool (*slot_level_handler) (struct kvm *kvm,
+ struct kvm_rmap_head *rmap_head,
+ const struct kvm_memory_slot *slot);
/* The caller should hold mmu-lock before calling this function. */
static __always_inline bool
-slot_handle_level_range(struct kvm *kvm, struct kvm_memory_slot *memslot,
+slot_handle_level_range(struct kvm *kvm, const struct kvm_memory_slot *memslot,
slot_level_handler fn, int start_level, int end_level,
gfn_t start_gfn, gfn_t end_gfn, bool flush_on_yield,
bool flush)
@@ -5334,7 +5459,7 @@ slot_handle_level_range(struct kvm *kvm, struct kvm_memory_slot *memslot,
}
static __always_inline bool
-slot_handle_level(struct kvm *kvm, struct kvm_memory_slot *memslot,
+slot_handle_level(struct kvm *kvm, const struct kvm_memory_slot *memslot,
slot_level_handler fn, int start_level, int end_level,
bool flush_on_yield)
{
@@ -5345,7 +5470,7 @@ slot_handle_level(struct kvm *kvm, struct kvm_memory_slot *memslot,
}
static __always_inline bool
-slot_handle_leaf(struct kvm *kvm, struct kvm_memory_slot *memslot,
+slot_handle_leaf(struct kvm *kvm, const struct kvm_memory_slot *memslot,
slot_level_handler fn, bool flush_on_yield)
{
return slot_handle_level(kvm, memslot, fn, PG_LEVEL_4K,
@@ -5358,6 +5483,7 @@ static void free_mmu_pages(struct kvm_mmu *mmu)
set_memory_encrypted((unsigned long)mmu->pae_root, 1);
free_page((unsigned long)mmu->pae_root);
free_page((unsigned long)mmu->pml4_root);
+ free_page((unsigned long)mmu->pml5_root);
}
static int __kvm_mmu_create(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu)
@@ -5587,6 +5713,10 @@ void kvm_mmu_uninit_vm(struct kvm *kvm)
kvm_mmu_uninit_tdp_mmu(kvm);
}
+/*
+ * Invalidate (zap) SPTEs that cover GFNs from gfn_start and up to gfn_end
+ * (not including it)
+ */
void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
{
struct kvm_memslots *slots;
@@ -5594,8 +5724,11 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
int i;
bool flush = false;
+ write_lock(&kvm->mmu_lock);
+
+ kvm_inc_notifier_count(kvm, gfn_start, gfn_end);
+
if (kvm_memslots_have_rmaps(kvm)) {
- write_lock(&kvm->mmu_lock);
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
slots = __kvm_memslots(kvm, i);
kvm_for_each_memslot(memslot, slots) {
@@ -5606,41 +5739,44 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
if (start >= end)
continue;
- flush = slot_handle_level_range(kvm, memslot,
+ flush = slot_handle_level_range(kvm,
+ (const struct kvm_memory_slot *) memslot,
kvm_zap_rmapp, PG_LEVEL_4K,
KVM_MAX_HUGEPAGE_LEVEL, start,
end - 1, true, flush);
}
}
if (flush)
- kvm_flush_remote_tlbs_with_address(kvm, gfn_start, gfn_end);
- write_unlock(&kvm->mmu_lock);
+ kvm_flush_remote_tlbs_with_address(kvm, gfn_start,
+ gfn_end - gfn_start);
}
if (is_tdp_mmu_enabled(kvm)) {
- flush = false;
-
- read_lock(&kvm->mmu_lock);
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, gfn_start,
- gfn_end, flush, true);
+ gfn_end, flush);
if (flush)
kvm_flush_remote_tlbs_with_address(kvm, gfn_start,
- gfn_end);
-
- read_unlock(&kvm->mmu_lock);
+ gfn_end - gfn_start);
}
+
+ if (flush)
+ kvm_flush_remote_tlbs_with_address(kvm, gfn_start, gfn_end);
+
+ kvm_dec_notifier_count(kvm, gfn_start, gfn_end);
+
+ write_unlock(&kvm->mmu_lock);
}
static bool slot_rmap_write_protect(struct kvm *kvm,
struct kvm_rmap_head *rmap_head,
- struct kvm_memory_slot *slot)
+ const struct kvm_memory_slot *slot)
{
return __rmap_write_protect(kvm, rmap_head, false);
}
void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
- struct kvm_memory_slot *memslot,
+ const struct kvm_memory_slot *memslot,
int start_level)
{
bool flush = false;
@@ -5676,7 +5812,7 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
struct kvm_rmap_head *rmap_head,
- struct kvm_memory_slot *slot)
+ const struct kvm_memory_slot *slot)
{
u64 *sptep;
struct rmap_iterator iter;
@@ -5699,7 +5835,7 @@ restart:
if (sp->role.direct && !kvm_is_reserved_pfn(pfn) &&
sp->role.level < kvm_mmu_max_mapping_level(kvm, slot, sp->gfn,
pfn, PG_LEVEL_NUM)) {
- pte_list_remove(rmap_head, sptep);
+ pte_list_remove(kvm, rmap_head, sptep);
if (kvm_available_flush_tlb_with_range())
kvm_flush_remote_tlbs_with_address(kvm, sp->gfn,
@@ -5715,10 +5851,8 @@ restart:
}
void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
- const struct kvm_memory_slot *memslot)
+ const struct kvm_memory_slot *slot)
{
- /* FIXME: const-ify all uses of struct kvm_memory_slot. */
- struct kvm_memory_slot *slot = (struct kvm_memory_slot *)memslot;
bool flush = false;
if (kvm_memslots_have_rmaps(kvm)) {
@@ -5754,7 +5888,7 @@ void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
}
void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
- struct kvm_memory_slot *memslot)
+ const struct kvm_memory_slot *memslot)
{
bool flush = false;
diff --git a/arch/x86/kvm/mmu/mmu_audit.c b/arch/x86/kvm/mmu/mmu_audit.c
index cedc17b2f60e..9e7dcf999f08 100644
--- a/arch/x86/kvm/mmu/mmu_audit.c
+++ b/arch/x86/kvm/mmu/mmu_audit.c
@@ -147,7 +147,7 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
return;
}
- rmap_head = __gfn_to_rmap(gfn, rev_sp->role.level, slot);
+ rmap_head = gfn_to_rmap(gfn, rev_sp->role.level, slot);
if (!rmap_head->val) {
if (!__ratelimit(&ratelimit_state))
return;
@@ -200,7 +200,7 @@ static void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp)
slots = kvm_memslots_for_spte_role(kvm, sp->role);
slot = __gfn_to_memslot(slots, sp->gfn);
- rmap_head = __gfn_to_rmap(sp->gfn, PG_LEVEL_4K, slot);
+ rmap_head = gfn_to_rmap(sp->gfn, PG_LEVEL_4K, slot);
for_each_rmap_spte(rmap_head, &iter, sptep) {
if (is_writable_pte(*sptep))
diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_internal.h
index 35567293c1fd..bf2bdbf333c2 100644
--- a/arch/x86/kvm/mmu/mmu_internal.h
+++ b/arch/x86/kvm/mmu/mmu_internal.h
@@ -31,13 +31,16 @@ extern bool dbg;
#define IS_VALID_PAE_ROOT(x) (!!(x))
struct kvm_mmu_page {
+ /*
+ * Note, "link" through "spt" fit in a single 64 byte cache line on
+ * 64-bit kernels, keep it that way unless there's a reason not to.
+ */
struct list_head link;
struct hlist_node hash_link;
- struct list_head lpage_disallowed_link;
+ bool tdp_mmu_page;
bool unsync;
u8 mmu_valid_gen;
- bool mmio_cached;
bool lpage_disallowed; /* Can't be replaced by an equiv large page */
/*
@@ -59,6 +62,7 @@ struct kvm_mmu_page {
struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */
DECLARE_BITMAP(unsync_child_bitmap, 512);
+ struct list_head lpage_disallowed_link;
#ifdef CONFIG_X86_32
/*
* Used out of the mmu-lock to avoid reading spte values while an
@@ -71,8 +75,6 @@ struct kvm_mmu_page {
atomic_t write_flooding_count;
#ifdef CONFIG_X86_64
- bool tdp_mmu_page;
-
/* Used for freeing the page asynchronously if it is a TDP MMU page. */
struct rcu_head rcu_head;
#endif
@@ -124,13 +126,14 @@ static inline bool is_nx_huge_page_enabled(void)
int mmu_try_to_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn, bool can_unsync);
-void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
-void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
+void kvm_mmu_gfn_disallow_lpage(const struct kvm_memory_slot *slot, gfn_t gfn);
+void kvm_mmu_gfn_allow_lpage(const struct kvm_memory_slot *slot, gfn_t gfn);
bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
struct kvm_memory_slot *slot, u64 gfn,
int min_level);
void kvm_flush_remote_tlbs_with_address(struct kvm *kvm,
u64 start_gfn, u64 pages);
+unsigned int pte_list_count(struct kvm_rmap_head *rmap_head);
/*
* Return values of handle_mmio_page_fault, mmu.page_fault, and fast_page_fault().
@@ -140,6 +143,9 @@ void kvm_flush_remote_tlbs_with_address(struct kvm *kvm,
* RET_PF_INVALID: the spte is invalid, let the real page fault path update it.
* RET_PF_FIXED: The faulting entry has been fixed.
* RET_PF_SPURIOUS: The faulting entry was already fixed, e.g. by another vCPU.
+ *
+ * Any names added to this enum should be exported to userspace for use in
+ * tracepoints via TRACE_DEFINE_ENUM() in mmutrace.h
*/
enum {
RET_PF_RETRY = 0,
diff --git a/arch/x86/kvm/mmu/mmutrace.h b/arch/x86/kvm/mmu/mmutrace.h
index efbad33a0645..2924a4081a19 100644
--- a/arch/x86/kvm/mmu/mmutrace.h
+++ b/arch/x86/kvm/mmu/mmutrace.h
@@ -54,6 +54,12 @@
{ PFERR_RSVD_MASK, "RSVD" }, \
{ PFERR_FETCH_MASK, "F" }
+TRACE_DEFINE_ENUM(RET_PF_RETRY);
+TRACE_DEFINE_ENUM(RET_PF_EMULATE);
+TRACE_DEFINE_ENUM(RET_PF_INVALID);
+TRACE_DEFINE_ENUM(RET_PF_FIXED);
+TRACE_DEFINE_ENUM(RET_PF_SPURIOUS);
+
/*
* A pagetable walk has started
*/
diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c
index 91a9f7e0fd91..269f11f92fd0 100644
--- a/arch/x86/kvm/mmu/page_track.c
+++ b/arch/x86/kvm/mmu/page_track.c
@@ -16,6 +16,7 @@
#include <asm/kvm_page_track.h>
+#include "mmu.h"
#include "mmu_internal.h"
void kvm_page_track_free_memslot(struct kvm_memory_slot *slot)
diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
index ee044d357b5f..7d03e9b7ccfa 100644
--- a/arch/x86/kvm/mmu/paging_tmpl.h
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
@@ -881,9 +881,9 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gpa_t addr, u32 error_code,
mmu_seq = vcpu->kvm->mmu_notifier_seq;
smp_rmb();
- if (try_async_pf(vcpu, prefault, walker.gfn, addr, &pfn, &hva,
- write_fault, &map_writable))
- return RET_PF_RETRY;
+ if (kvm_faultin_pfn(vcpu, prefault, walker.gfn, addr, &pfn, &hva,
+ write_fault, &map_writable, &r))
+ return r;
if (handle_abnormal_pfn(vcpu, addr, walker.gfn, pfn, walker.pte_access, &r))
return r;
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index d80cb122b5f3..64ccfc1fa553 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -10,7 +10,7 @@
#include <asm/cmpxchg.h>
#include <trace/events/kvm.h>
-static bool __read_mostly tdp_mmu_enabled = false;
+static bool __read_mostly tdp_mmu_enabled = true;
module_param_named(tdp_mmu, tdp_mmu_enabled, bool, 0644);
/* Initializes the TDP MMU for the VM, if enabled. */
@@ -255,26 +255,17 @@ static void handle_changed_spte_dirty_log(struct kvm *kvm, int as_id, gfn_t gfn,
*
* @kvm: kvm instance
* @sp: the new page
- * @shared: This operation may not be running under the exclusive use of
- * the MMU lock and the operation must synchronize with other
- * threads that might be adding or removing pages.
* @account_nx: This page replaces a NX large page and should be marked for
* eventual reclaim.
*/
static void tdp_mmu_link_page(struct kvm *kvm, struct kvm_mmu_page *sp,
- bool shared, bool account_nx)
+ bool account_nx)
{
- if (shared)
- spin_lock(&kvm->arch.tdp_mmu_pages_lock);
- else
- lockdep_assert_held_write(&kvm->mmu_lock);
-
+ spin_lock(&kvm->arch.tdp_mmu_pages_lock);
list_add(&sp->link, &kvm->arch.tdp_mmu_pages);
if (account_nx)
account_huge_nx_page(kvm, sp);
-
- if (shared)
- spin_unlock(&kvm->arch.tdp_mmu_pages_lock);
+ spin_unlock(&kvm->arch.tdp_mmu_pages_lock);
}
/**
@@ -445,13 +436,6 @@ static void __handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn,
trace_kvm_tdp_mmu_spte_changed(as_id, gfn, level, old_spte, new_spte);
- if (is_large_pte(old_spte) != is_large_pte(new_spte)) {
- if (is_large_pte(old_spte))
- atomic64_sub(1, (atomic64_t*)&kvm->stat.lpages);
- else
- atomic64_add(1, (atomic64_t*)&kvm->stat.lpages);
- }
-
/*
* The only times a SPTE should be changed from a non-present to
* non-present state is when an MMIO entry is installed/modified/
@@ -477,6 +461,8 @@ static void __handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn,
return;
}
+ if (is_leaf != was_leaf)
+ kvm_update_page_stats(kvm, level, is_leaf ? 1 : -1);
if (was_leaf && is_dirty_spte(old_spte) &&
(!is_present || !is_dirty_spte(new_spte) || pfn_changed))
@@ -526,6 +512,10 @@ static inline bool tdp_mmu_set_spte_atomic_no_dirty_log(struct kvm *kvm,
if (is_removed_spte(iter->old_spte))
return false;
+ /*
+ * Note, fast_pf_fix_direct_spte() can also modify TDP MMU SPTEs and
+ * does not hold the mmu_lock.
+ */
if (cmpxchg64(rcu_dereference(iter->sptep), iter->old_spte,
new_spte) != iter->old_spte)
return false;
@@ -537,15 +527,40 @@ static inline bool tdp_mmu_set_spte_atomic_no_dirty_log(struct kvm *kvm,
return true;
}
-static inline bool tdp_mmu_set_spte_atomic(struct kvm *kvm,
- struct tdp_iter *iter,
- u64 new_spte)
+/*
+ * tdp_mmu_map_set_spte_atomic - Set a leaf TDP MMU SPTE atomically to resolve a
+ * TDP page fault.
+ *
+ * @vcpu: The vcpu instance that took the TDP page fault.
+ * @iter: a tdp_iter instance currently on the SPTE that should be set
+ * @new_spte: The value the SPTE should be set to
+ *
+ * Returns: true if the SPTE was set, false if it was not. If false is returned,
+ * this function will have no side-effects.
+ */
+static inline bool tdp_mmu_map_set_spte_atomic(struct kvm_vcpu *vcpu,
+ struct tdp_iter *iter,
+ u64 new_spte)
{
+ struct kvm *kvm = vcpu->kvm;
+
if (!tdp_mmu_set_spte_atomic_no_dirty_log(kvm, iter, new_spte))
return false;
- handle_changed_spte_dirty_log(kvm, iter->as_id, iter->gfn,
- iter->old_spte, new_spte, iter->level);
+ /*
+ * Use kvm_vcpu_gfn_to_memslot() instead of going through
+ * handle_changed_spte_dirty_log() to leverage vcpu->last_used_slot.
+ */
+ if (is_writable_pte(new_spte)) {
+ struct kvm_memory_slot *slot = kvm_vcpu_gfn_to_memslot(vcpu, iter->gfn);
+
+ if (slot && kvm_slot_dirty_track_enabled(slot)) {
+ /* Enforced by kvm_mmu_hugepage_adjust. */
+ WARN_ON_ONCE(iter->level > PG_LEVEL_4K);
+ mark_page_dirty_in_slot(kvm, slot, iter->gfn);
+ }
+ }
+
return true;
}
@@ -558,7 +573,7 @@ static inline bool tdp_mmu_zap_spte_atomic(struct kvm *kvm,
* immediately installing a present entry in its place
* before the TLBs are flushed.
*/
- if (!tdp_mmu_set_spte_atomic(kvm, iter, REMOVED_SPTE))
+ if (!tdp_mmu_set_spte_atomic_no_dirty_log(kvm, iter, REMOVED_SPTE))
return false;
kvm_flush_remote_tlbs_with_address(kvm, iter->gfn,
@@ -789,21 +804,15 @@ retry:
* non-root pages mapping GFNs strictly within that range. Returns true if
* SPTEs have been cleared and a TLB flush is needed before releasing the
* MMU lock.
- *
- * If shared is true, this thread holds the MMU lock in read mode and must
- * account for the possibility that other threads are modifying the paging
- * structures concurrently. If shared is false, this thread should hold the
- * MMU in write mode.
*/
bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id, gfn_t start,
- gfn_t end, bool can_yield, bool flush,
- bool shared)
+ gfn_t end, bool can_yield, bool flush)
{
struct kvm_mmu_page *root;
- for_each_tdp_mmu_root_yield_safe(kvm, root, as_id, shared)
+ for_each_tdp_mmu_root_yield_safe(kvm, root, as_id, false)
flush = zap_gfn_range(kvm, root, start, end, can_yield, flush,
- shared);
+ false);
return flush;
}
@@ -814,8 +823,7 @@ void kvm_tdp_mmu_zap_all(struct kvm *kvm)
int i;
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
- flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, 0, -1ull,
- flush, false);
+ flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, 0, -1ull, flush);
if (flush)
kvm_flush_remote_tlbs(kvm);
@@ -940,7 +948,7 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu, int write,
if (new_spte == iter->old_spte)
ret = RET_PF_SPURIOUS;
- else if (!tdp_mmu_set_spte_atomic(vcpu->kvm, iter, new_spte))
+ else if (!tdp_mmu_map_set_spte_atomic(vcpu, iter, new_spte))
return RET_PF_RETRY;
/*
@@ -1044,9 +1052,8 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
new_spte = make_nonleaf_spte(child_pt,
!shadow_accessed_mask);
- if (tdp_mmu_set_spte_atomic(vcpu->kvm, &iter,
- new_spte)) {
- tdp_mmu_link_page(vcpu->kvm, sp, true,
+ if (tdp_mmu_set_spte_atomic_no_dirty_log(vcpu->kvm, &iter, new_spte)) {
+ tdp_mmu_link_page(vcpu->kvm, sp,
huge_page_disallowed &&
req_level >= iter.level);
@@ -1255,8 +1262,8 @@ retry:
* only affect leaf SPTEs down to min_level.
* Returns true if an SPTE has been changed and the TLBs need to be flushed.
*/
-bool kvm_tdp_mmu_wrprot_slot(struct kvm *kvm, struct kvm_memory_slot *slot,
- int min_level)
+bool kvm_tdp_mmu_wrprot_slot(struct kvm *kvm,
+ const struct kvm_memory_slot *slot, int min_level)
{
struct kvm_mmu_page *root;
bool spte_set = false;
@@ -1326,7 +1333,8 @@ retry:
* each SPTE. Returns true if an SPTE has been changed and the TLBs need to
* be flushed.
*/
-bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm, struct kvm_memory_slot *slot)
+bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
+ const struct kvm_memory_slot *slot)
{
struct kvm_mmu_page *root;
bool spte_set = false;
@@ -1529,6 +1537,8 @@ bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm,
/*
* Return the level of the lowest level SPTE added to sptes.
* That SPTE may be non-present.
+ *
+ * Must be called between kvm_tdp_mmu_walk_lockless_{begin,end}.
*/
int kvm_tdp_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes,
int *root_level)
@@ -1540,14 +1550,47 @@ int kvm_tdp_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes,
*root_level = vcpu->arch.mmu->shadow_root_level;
- rcu_read_lock();
-
tdp_mmu_for_each_pte(iter, mmu, gfn, gfn + 1) {
leaf = iter.level;
sptes[leaf] = iter.old_spte;
}
- rcu_read_unlock();
-
return leaf;
}
+
+/*
+ * Returns the last level spte pointer of the shadow page walk for the given
+ * gpa, and sets *spte to the spte value. This spte may be non-preset. If no
+ * walk could be performed, returns NULL and *spte does not contain valid data.
+ *
+ * Contract:
+ * - Must be called between kvm_tdp_mmu_walk_lockless_{begin,end}.
+ * - The returned sptep must not be used after kvm_tdp_mmu_walk_lockless_end.
+ *
+ * WARNING: This function is only intended to be called during fast_page_fault.
+ */
+u64 *kvm_tdp_mmu_fast_pf_get_last_sptep(struct kvm_vcpu *vcpu, u64 addr,
+ u64 *spte)
+{
+ struct tdp_iter iter;
+ struct kvm_mmu *mmu = vcpu->arch.mmu;
+ gfn_t gfn = addr >> PAGE_SHIFT;
+ tdp_ptep_t sptep = NULL;
+
+ tdp_mmu_for_each_pte(iter, mmu, gfn, gfn + 1) {
+ *spte = iter.old_spte;
+ sptep = iter.sptep;
+ }
+
+ /*
+ * Perform the rcu_dereference to get the raw spte pointer value since
+ * we are passing it up to fast_page_fault, which is shared with the
+ * legacy MMU and thus does not retain the TDP MMU-specific __rcu
+ * annotation.
+ *
+ * This is safe since fast_page_fault obeys the contracts of this
+ * function as well as all TDP MMU contracts around modifying SPTEs
+ * outside of mmu_lock.
+ */
+ return rcu_dereference(sptep);
+}
diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h
index 1cae4485b3bc..358f447d4012 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.h
+++ b/arch/x86/kvm/mmu/tdp_mmu.h
@@ -20,14 +20,11 @@ void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
bool shared);
bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id, gfn_t start,
- gfn_t end, bool can_yield, bool flush,
- bool shared);
+ gfn_t end, bool can_yield, bool flush);
static inline bool kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id,
- gfn_t start, gfn_t end, bool flush,
- bool shared)
+ gfn_t start, gfn_t end, bool flush)
{
- return __kvm_tdp_mmu_zap_gfn_range(kvm, as_id, start, end, true, flush,
- shared);
+ return __kvm_tdp_mmu_zap_gfn_range(kvm, as_id, start, end, true, flush);
}
static inline bool kvm_tdp_mmu_zap_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
{
@@ -44,7 +41,7 @@ static inline bool kvm_tdp_mmu_zap_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
*/
lockdep_assert_held_write(&kvm->mmu_lock);
return __kvm_tdp_mmu_zap_gfn_range(kvm, kvm_mmu_page_as_id(sp),
- sp->gfn, end, false, false, false);
+ sp->gfn, end, false, false);
}
void kvm_tdp_mmu_zap_all(struct kvm *kvm);
@@ -61,10 +58,10 @@ bool kvm_tdp_mmu_age_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range);
bool kvm_tdp_mmu_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
bool kvm_tdp_mmu_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
-bool kvm_tdp_mmu_wrprot_slot(struct kvm *kvm, struct kvm_memory_slot *slot,
- int min_level);
+bool kvm_tdp_mmu_wrprot_slot(struct kvm *kvm,
+ const struct kvm_memory_slot *slot, int min_level);
bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
- struct kvm_memory_slot *slot);
+ const struct kvm_memory_slot *slot);
void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
struct kvm_memory_slot *slot,
gfn_t gfn, unsigned long mask,
@@ -77,8 +74,20 @@ bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm,
struct kvm_memory_slot *slot, gfn_t gfn,
int min_level);
+static inline void kvm_tdp_mmu_walk_lockless_begin(void)
+{
+ rcu_read_lock();
+}
+
+static inline void kvm_tdp_mmu_walk_lockless_end(void)
+{
+ rcu_read_unlock();
+}
+
int kvm_tdp_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes,
int *root_level);
+u64 *kvm_tdp_mmu_fast_pf_get_last_sptep(struct kvm_vcpu *vcpu, u64 addr,
+ u64 *spte);
#ifdef CONFIG_X86_64
bool kvm_mmu_init_tdp_mmu(struct kvm *kvm);
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 827886c12c16..0772bad9165c 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -137,18 +137,20 @@ static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
pmc->perf_event = event;
pmc_to_pmu(pmc)->event_count++;
clear_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi);
+ pmc->is_paused = false;
}
static void pmc_pause_counter(struct kvm_pmc *pmc)
{
u64 counter = pmc->counter;
- if (!pmc->perf_event)
+ if (!pmc->perf_event || pmc->is_paused)
return;
/* update counter, reset event value to avoid redundant accumulation */
counter += perf_event_pause(pmc->perf_event, true);
pmc->counter = counter & pmc_bitmask(pmc);
+ pmc->is_paused = true;
}
static bool pmc_resume_counter(struct kvm_pmc *pmc)
@@ -163,6 +165,7 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
/* reuse perf_event to serve as pmc_reprogram_counter() does*/
perf_event_enable(pmc->perf_event);
+ pmc->is_paused = false;
clear_bit(pmc->idx, (unsigned long *)&pmc_to_pmu(pmc)->reprogram_pmi);
return true;
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 67e753edfa22..0e4f2b1fa9fb 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -55,7 +55,7 @@ static inline u64 pmc_read_counter(struct kvm_pmc *pmc)
u64 counter, enabled, running;
counter = pmc->counter;
- if (pmc->perf_event)
+ if (pmc->perf_event && !pmc->is_paused)
counter += perf_event_read_value(pmc->perf_event,
&enabled, &running);
/* FIXME: Scaling needed? */
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index a8ad78a2faa1..8052d92069e0 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -197,6 +197,8 @@ void avic_init_vmcb(struct vcpu_svm *svm)
vmcb->control.avic_logical_id = lpa & AVIC_HPA_MASK;
vmcb->control.avic_physical_id = ppa & AVIC_HPA_MASK;
vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID_COUNT;
+ vmcb->control.avic_vapic_bar = APIC_DEFAULT_PHYS_BASE & VMCB_AVIC_APIC_BAR_MASK;
+
if (kvm_apicv_activated(svm->vcpu.kvm))
vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
else
@@ -225,31 +227,26 @@ static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu,
* field of the VMCB. Therefore, we set up the
* APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (4KB) here.
*/
-static int avic_update_access_page(struct kvm *kvm, bool activate)
+static int avic_alloc_access_page(struct kvm *kvm)
{
void __user *ret;
int r = 0;
mutex_lock(&kvm->slots_lock);
- /*
- * During kvm_destroy_vm(), kvm_pit_set_reinject() could trigger
- * APICv mode change, which update APIC_ACCESS_PAGE_PRIVATE_MEMSLOT
- * memory region. So, we need to ensure that kvm->mm == current->mm.
- */
- if ((kvm->arch.apic_access_memslot_enabled == activate) ||
- (kvm->mm != current->mm))
+
+ if (kvm->arch.apic_access_memslot_enabled)
goto out;
ret = __x86_set_memory_region(kvm,
APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
APIC_DEFAULT_PHYS_BASE,
- activate ? PAGE_SIZE : 0);
+ PAGE_SIZE);
if (IS_ERR(ret)) {
r = PTR_ERR(ret);
goto out;
}
- kvm->arch.apic_access_memslot_enabled = activate;
+ kvm->arch.apic_access_memslot_enabled = true;
out:
mutex_unlock(&kvm->slots_lock);
return r;
@@ -270,7 +267,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
if (kvm_apicv_activated(vcpu->kvm)) {
int ret;
- ret = avic_update_access_page(vcpu->kvm, true);
+ ret = avic_alloc_access_page(vcpu->kvm);
if (ret)
return ret;
}
@@ -587,17 +584,6 @@ void avic_post_state_restore(struct kvm_vcpu *vcpu)
avic_handle_ldr_update(vcpu);
}
-void svm_toggle_avic_for_irq_window(struct kvm_vcpu *vcpu, bool activate)
-{
- if (!enable_apicv || !lapic_in_kernel(vcpu))
- return;
-
- srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
- kvm_request_apicv_update(vcpu->kvm, activate,
- APICV_INHIBIT_REASON_IRQWIN);
- vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
-}
-
void svm_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
{
return;
@@ -667,6 +653,11 @@ void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
}
vmcb_mark_dirty(vmcb, VMCB_AVIC);
+ if (activated)
+ avic_vcpu_load(vcpu, vcpu->cpu);
+ else
+ avic_vcpu_put(vcpu);
+
svm_set_pi_irte_mode(vcpu, activated);
}
@@ -918,10 +909,6 @@ bool svm_check_apicv_inhibit_reasons(ulong bit)
return supported & BIT(bit);
}
-void svm_pre_update_apicv_exec_ctrl(struct kvm *kvm, bool activate)
-{
- avic_update_access_page(kvm, activate);
-}
static inline int
avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu, bool r)
@@ -960,9 +947,6 @@ void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
int h_physical_id = kvm_cpu_get_apicid(cpu);
struct vcpu_svm *svm = to_svm(vcpu);
- if (!kvm_vcpu_apicv_active(vcpu))
- return;
-
/*
* Since the host physical APIC id is 8 bits,
* we can support host APIC ID upto 255.
@@ -990,9 +974,6 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu)
u64 entry;
struct vcpu_svm *svm = to_svm(vcpu);
- if (!kvm_vcpu_apicv_active(vcpu))
- return;
-
entry = READ_ONCE(*(svm->avic_physical_id_cache));
if (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK)
avic_update_iommu_vcpu_affinity(vcpu, -1, 0);
@@ -1009,6 +990,10 @@ static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
struct vcpu_svm *svm = to_svm(vcpu);
svm->avic_is_running = is_run;
+
+ if (!kvm_vcpu_apicv_active(vcpu))
+ return;
+
if (is_run)
avic_vcpu_load(vcpu, vcpu->cpu);
else
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index e5515477c30a..2545d0c61985 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -666,11 +666,6 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu)
goto out;
}
-
- /* Clear internal status */
- kvm_clear_exception_queue(vcpu);
- kvm_clear_interrupt_queue(vcpu);
-
/*
* Since vmcb01 is not in use, we can use it to store some of the L1
* state.
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 7fbce342eec4..75e0b21ad07c 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -28,8 +28,6 @@
#include "cpuid.h"
#include "trace.h"
-#define __ex(x) __kvm_handle_fault_on_reboot(x)
-
#ifndef CONFIG_KVM_AMD_SEV
/*
* When this config is not defined, SEV feature is not supported and APIs in
@@ -584,6 +582,7 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
save->xcr0 = svm->vcpu.arch.xcr0;
save->pkru = svm->vcpu.arch.pkru;
save->xss = svm->vcpu.arch.ia32_xss;
+ save->dr6 = svm->vcpu.arch.dr6;
/*
* SEV-ES will use a VMSA that is pointed to by the VMCB, not
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 69639f9624f5..05e8d4d27969 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -46,8 +46,6 @@
#include "kvm_onhyperv.h"
#include "svm_onhyperv.h"
-#define __ex(x) __kvm_handle_fault_on_reboot(x)
-
MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL");
@@ -261,7 +259,7 @@ u32 svm_msrpm_offset(u32 msr)
static int get_max_npt_level(void)
{
#ifdef CONFIG_X86_64
- return PT64_ROOT_4LEVEL;
+ return pgtable_l5_enabled() ? PT64_ROOT_5LEVEL : PT64_ROOT_4LEVEL;
#else
return PT32E_ROOT_LEVEL;
#endif
@@ -462,11 +460,6 @@ static int has_svm(void)
return 0;
}
- if (pgtable_l5_enabled()) {
- pr_info("KVM doesn't yet support 5-level paging on AMD SVM\n");
- return 0;
- }
-
return 1;
}
@@ -1015,7 +1008,9 @@ static __init int svm_hardware_setup(void)
if (!boot_cpu_has(X86_FEATURE_NPT))
npt_enabled = false;
- kvm_configure_mmu(npt_enabled, get_max_npt_level(), PG_LEVEL_1G);
+ /* Force VM NPT level equal to the host's max NPT level */
+ kvm_configure_mmu(npt_enabled, get_max_npt_level(),
+ get_max_npt_level(), PG_LEVEL_1G);
pr_info("kvm: Nested Paging %sabled\n", npt_enabled ? "en" : "dis");
/* Note, SEV setup consumes npt_enabled. */
@@ -1161,8 +1156,6 @@ static void init_vmcb(struct kvm_vcpu *vcpu)
struct vmcb_control_area *control = &svm->vmcb->control;
struct vmcb_save_area *save = &svm->vmcb->save;
- vcpu->arch.hflags = 0;
-
svm_set_intercept(svm, INTERCEPT_CR0_READ);
svm_set_intercept(svm, INTERCEPT_CR3_READ);
svm_set_intercept(svm, INTERCEPT_CR4_READ);
@@ -1241,29 +1234,14 @@ static void init_vmcb(struct kvm_vcpu *vcpu)
SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
save->cs.limit = 0xffff;
+ save->gdtr.base = 0;
save->gdtr.limit = 0xffff;
+ save->idtr.base = 0;
save->idtr.limit = 0xffff;
init_sys_seg(&save->ldtr, SEG_TYPE_LDT);
init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16);
- svm_set_cr4(vcpu, 0);
- svm_set_efer(vcpu, 0);
- save->dr6 = 0xffff0ff0;
- kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
- save->rip = 0x0000fff0;
- vcpu->arch.regs[VCPU_REGS_RIP] = save->rip;
-
- /*
- * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0.
- * It also updates the guest-visible cr0 value.
- */
- svm_set_cr0(vcpu, X86_CR0_NW | X86_CR0_CD | X86_CR0_ET);
- kvm_mmu_reset_context(vcpu);
-
- save->cr4 = X86_CR4_PAE;
- /* rdx = ?? */
-
if (npt_enabled) {
/* Setup VMCB for Nested Paging */
control->nested_ctl |= SVM_NESTED_CTL_NP_ENABLE;
@@ -1273,14 +1251,12 @@ static void init_vmcb(struct kvm_vcpu *vcpu)
svm_clr_intercept(svm, INTERCEPT_CR3_WRITE);
save->g_pat = vcpu->arch.pat;
save->cr3 = 0;
- save->cr4 = 0;
}
svm->current_vmcb->asid_generation = 0;
svm->asid = 0;
svm->nested.vmcb12_gpa = INVALID_GPA;
svm->nested.last_vmcb12_gpa = INVALID_GPA;
- vcpu->arch.hflags = 0;
if (!kvm_pause_in_guest(vcpu->kvm)) {
control->pause_filter_count = pause_filter_count;
@@ -1330,25 +1306,11 @@ static void init_vmcb(struct kvm_vcpu *vcpu)
static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
{
struct vcpu_svm *svm = to_svm(vcpu);
- u32 dummy;
- u32 eax = 1;
svm->spec_ctrl = 0;
svm->virt_spec_ctrl = 0;
- if (!init_event) {
- vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE |
- MSR_IA32_APICBASE_ENABLE;
- if (kvm_vcpu_is_reset_bsp(vcpu))
- vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP;
- }
init_vmcb(vcpu);
-
- kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy, false);
- kvm_rdx_write(vcpu, eax);
-
- if (kvm_vcpu_apicv_active(vcpu) && !init_event)
- avic_update_vapic_bar(svm, APIC_DEFAULT_PHYS_BASE);
}
void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vmcb)
@@ -1513,12 +1475,15 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
sd->current_vmcb = svm->vmcb;
indirect_branch_prediction_barrier();
}
- avic_vcpu_load(vcpu, cpu);
+ if (kvm_vcpu_apicv_active(vcpu))
+ avic_vcpu_load(vcpu, cpu);
}
static void svm_vcpu_put(struct kvm_vcpu *vcpu)
{
- avic_vcpu_put(vcpu);
+ if (kvm_vcpu_apicv_active(vcpu))
+ avic_vcpu_put(vcpu);
+
svm_prepare_host_switch(vcpu);
++vcpu->stat.host_state_reload;
@@ -1560,7 +1525,7 @@ static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu));
break;
default:
- WARN_ON_ONCE(1);
+ KVM_BUG_ON(1, vcpu->kvm);
}
}
@@ -2078,11 +2043,15 @@ static int shutdown_interception(struct kvm_vcpu *vcpu)
return -EINVAL;
/*
- * VMCB is undefined after a SHUTDOWN intercept
- * so reinitialize it.
+ * VMCB is undefined after a SHUTDOWN intercept. INIT the vCPU to put
+ * the VMCB in a known good state. Unfortuately, KVM doesn't have
+ * KVM_MP_STATE_SHUTDOWN and can't add it without potentially breaking
+ * userspace. At a platform view, INIT is acceptable behavior as
+ * there exist bare metal platforms that automatically INIT the CPU
+ * in response to shutdown.
*/
clear_page(svm->vmcb);
- init_vmcb(vcpu);
+ kvm_vcpu_reset(vcpu, true);
kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
return 0;
@@ -2993,10 +2962,6 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
svm->msr_decfg = data;
break;
}
- case MSR_IA32_APICBASE:
- if (kvm_vcpu_apicv_active(vcpu))
- avic_update_vapic_bar(to_svm(vcpu), data);
- fallthrough;
default:
return kvm_set_msr_common(vcpu, msr);
}
@@ -3021,7 +2986,7 @@ static int interrupt_window_interception(struct kvm_vcpu *vcpu)
* In this case AVIC was temporarily disabled for
* requesting the IRQ window and we have to re-enable it.
*/
- svm_toggle_avic_for_irq_window(vcpu, true);
+ kvm_request_apicv_update(vcpu->kvm, true, APICV_INHIBIT_REASON_IRQWIN);
++vcpu->stat.irq_window_exits;
return 1;
@@ -3269,12 +3234,14 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
"excp_to:", save->last_excp_to);
}
-static int svm_handle_invalid_exit(struct kvm_vcpu *vcpu, u64 exit_code)
+static bool svm_check_exit_valid(struct kvm_vcpu *vcpu, u64 exit_code)
{
- if (exit_code < ARRAY_SIZE(svm_exit_handlers) &&
- svm_exit_handlers[exit_code])
- return 0;
+ return (exit_code < ARRAY_SIZE(svm_exit_handlers) &&
+ svm_exit_handlers[exit_code]);
+}
+static int svm_handle_invalid_exit(struct kvm_vcpu *vcpu, u64 exit_code)
+{
vcpu_unimpl(vcpu, "svm: unexpected exit reason 0x%llx\n", exit_code);
dump_vmcb(vcpu);
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -3282,14 +3249,13 @@ static int svm_handle_invalid_exit(struct kvm_vcpu *vcpu, u64 exit_code)
vcpu->run->internal.ndata = 2;
vcpu->run->internal.data[0] = exit_code;
vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu;
-
- return -EINVAL;
+ return 0;
}
int svm_invoke_exit_handler(struct kvm_vcpu *vcpu, u64 exit_code)
{
- if (svm_handle_invalid_exit(vcpu, exit_code))
- return 0;
+ if (!svm_check_exit_valid(vcpu, exit_code))
+ return svm_handle_invalid_exit(vcpu, exit_code);
#ifdef CONFIG_RETPOLINE
if (exit_code == SVM_EXIT_MSR)
@@ -3573,7 +3539,7 @@ static void svm_enable_irq_window(struct kvm_vcpu *vcpu)
* via AVIC. In such case, we need to temporarily disable AVIC,
* and fallback to injecting IRQ via V_IRQ.
*/
- svm_toggle_avic_for_irq_window(vcpu, false);
+ kvm_request_apicv_update(vcpu->kvm, false, APICV_INHIBIT_REASON_IRQWIN);
svm_set_vintr(svm);
}
}
@@ -3808,6 +3774,8 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
pre_svm_run(vcpu);
+ WARN_ON_ONCE(kvm_apicv_activated(vcpu->kvm) != kvm_vcpu_apicv_active(vcpu));
+
sync_lapic_to_cr8(vcpu);
if (unlikely(svm->asid != svm->vmcb->control.asid)) {
@@ -4610,7 +4578,6 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
.set_virtual_apic_mode = svm_set_virtual_apic_mode,
.refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl,
.check_apicv_inhibit_reasons = svm_check_apicv_inhibit_reasons,
- .pre_update_apicv_exec_ctrl = svm_pre_update_apicv_exec_ctrl,
.load_eoi_exitmap = svm_load_eoi_exitmap,
.hwapic_irr_update = svm_hwapic_irr_update,
.hwapic_isr_update = svm_hwapic_isr_update,
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index bd0fe94c2920..524d943f3efc 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -503,12 +503,6 @@ extern struct kvm_x86_nested_ops svm_nested_ops;
#define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL
-static inline void avic_update_vapic_bar(struct vcpu_svm *svm, u64 data)
-{
- svm->vmcb->control.avic_vapic_bar = data & VMCB_AVIC_APIC_BAR_MASK;
- vmcb_mark_dirty(svm->vmcb, VMCB_AVIC);
-}
-
static inline bool avic_vcpu_is_running(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -524,7 +518,6 @@ int avic_ga_log_notifier(u32 ga_tag);
void avic_vm_destroy(struct kvm *kvm);
int avic_vm_init(struct kvm *kvm);
void avic_init_vmcb(struct vcpu_svm *svm);
-void svm_toggle_avic_for_irq_window(struct kvm_vcpu *vcpu, bool activate);
int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu);
int avic_unaccelerated_access_interception(struct kvm_vcpu *vcpu);
int avic_init_vcpu(struct vcpu_svm *svm);
@@ -534,7 +527,6 @@ void avic_post_state_restore(struct kvm_vcpu *vcpu);
void svm_set_virtual_apic_mode(struct kvm_vcpu *vcpu);
void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu);
bool svm_check_apicv_inhibit_reasons(ulong bit);
-void svm_pre_update_apicv_exec_ctrl(struct kvm *kvm, bool activate);
void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
void svm_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr);
void svm_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr);
diff --git a/arch/x86/kvm/svm/svm_ops.h b/arch/x86/kvm/svm/svm_ops.h
index 8170f2a5a16f..22e2b019de37 100644
--- a/arch/x86/kvm/svm/svm_ops.h
+++ b/arch/x86/kvm/svm/svm_ops.h
@@ -4,7 +4,7 @@
#include <linux/compiler_types.h>
-#include <asm/kvm_host.h>
+#include "x86.h"
#define svm_asm(insn, clobber...) \
do { \
diff --git a/arch/x86/kvm/vmx/evmcs.c b/arch/x86/kvm/vmx/evmcs.c
index 896b2a50b4aa..0dab1b7b529f 100644
--- a/arch/x86/kvm/vmx/evmcs.c
+++ b/arch/x86/kvm/vmx/evmcs.c
@@ -14,7 +14,6 @@ DEFINE_STATIC_KEY_FALSE(enable_evmcs);
#if IS_ENABLED(CONFIG_HYPERV)
-#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
#define EVMCS1_OFFSET(x) offsetof(struct hv_enlightened_vmcs, x)
#define EVMCS1_FIELD(number, name, clean_field)[ROL16(number, 6)] = \
{EVMCS1_OFFSET(name), clean_field}
diff --git a/arch/x86/kvm/vmx/evmcs.h b/arch/x86/kvm/vmx/evmcs.h
index 2ec9b46f0d0c..152ab0aa82cf 100644
--- a/arch/x86/kvm/vmx/evmcs.h
+++ b/arch/x86/kvm/vmx/evmcs.h
@@ -73,8 +73,6 @@ struct evmcs_field {
extern const struct evmcs_field vmcs_field_to_evmcs_1[];
extern const unsigned int nr_evmcs_1_fields;
-#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
-
static __always_inline int get_evmcs_offset(unsigned long field,
u16 *clean_field)
{
@@ -95,8 +93,6 @@ static __always_inline int get_evmcs_offset(unsigned long field,
return evmcs_field->offset;
}
-#undef ROL16
-
static inline void evmcs_write64(unsigned long field, u64 value)
{
u16 clean_field;
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index b3f77d18eb5a..ccb03d69546c 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -2207,7 +2207,8 @@ static void prepare_vmcs02_early_rare(struct vcpu_vmx *vmx,
}
}
-static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
+static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct loaded_vmcs *vmcs01,
+ struct vmcs12 *vmcs12)
{
u32 exec_control;
u64 guest_efer = nested_vmx_calc_efer(vmx, vmcs12);
@@ -2218,23 +2219,22 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
/*
* PIN CONTROLS
*/
- exec_control = vmx_pin_based_exec_ctrl(vmx);
+ exec_control = __pin_controls_get(vmcs01);
exec_control |= (vmcs12->pin_based_vm_exec_control &
~PIN_BASED_VMX_PREEMPTION_TIMER);
/* Posted interrupts setting is only taken from vmcs12. */
- if (nested_cpu_has_posted_intr(vmcs12)) {
+ vmx->nested.pi_pending = false;
+ if (nested_cpu_has_posted_intr(vmcs12))
vmx->nested.posted_intr_nv = vmcs12->posted_intr_nv;
- vmx->nested.pi_pending = false;
- } else {
+ else
exec_control &= ~PIN_BASED_POSTED_INTR;
- }
pin_controls_set(vmx, exec_control);
/*
* EXEC CONTROLS
*/
- exec_control = vmx_exec_control(vmx); /* L0's desires */
+ exec_control = __exec_controls_get(vmcs01); /* L0's desires */
exec_control &= ~CPU_BASED_INTR_WINDOW_EXITING;
exec_control &= ~CPU_BASED_NMI_WINDOW_EXITING;
exec_control &= ~CPU_BASED_TPR_SHADOW;
@@ -2271,10 +2271,11 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
* SECONDARY EXEC CONTROLS
*/
if (cpu_has_secondary_exec_ctrls()) {
- exec_control = vmx->secondary_exec_control;
+ exec_control = __secondary_exec_controls_get(vmcs01);
/* Take the following fields only from vmcs12 */
exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
SECONDARY_EXEC_ENABLE_INVPCID |
SECONDARY_EXEC_ENABLE_RDTSCP |
SECONDARY_EXEC_XSAVES |
@@ -2282,7 +2283,9 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
SECONDARY_EXEC_APIC_REGISTER_VIRT |
SECONDARY_EXEC_ENABLE_VMFUNC |
- SECONDARY_EXEC_TSC_SCALING);
+ SECONDARY_EXEC_TSC_SCALING |
+ SECONDARY_EXEC_DESC);
+
if (nested_cpu_has(vmcs12,
CPU_BASED_ACTIVATE_SECONDARY_CONTROLS))
exec_control |= vmcs12->secondary_vm_exec_control;
@@ -2322,8 +2325,9 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
* on the related bits (if supported by the CPU) in the hope that
* we can avoid VMWrites during vmx_set_efer().
*/
- exec_control = (vmcs12->vm_entry_controls | vmx_vmentry_ctrl()) &
- ~VM_ENTRY_IA32E_MODE & ~VM_ENTRY_LOAD_IA32_EFER;
+ exec_control = __vm_entry_controls_get(vmcs01);
+ exec_control |= vmcs12->vm_entry_controls;
+ exec_control &= ~(VM_ENTRY_IA32E_MODE | VM_ENTRY_LOAD_IA32_EFER);
if (cpu_has_load_ia32_efer()) {
if (guest_efer & EFER_LMA)
exec_control |= VM_ENTRY_IA32E_MODE;
@@ -2339,9 +2343,11 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
* we should use its exit controls. Note that VM_EXIT_LOAD_IA32_EFER
* bits may be modified by vmx_set_efer() in prepare_vmcs02().
*/
- exec_control = vmx_vmexit_ctrl();
+ exec_control = __vm_exit_controls_get(vmcs01);
if (cpu_has_load_ia32_efer() && guest_efer != host_efer)
exec_control |= VM_EXIT_LOAD_IA32_EFER;
+ else
+ exec_control &= ~VM_EXIT_LOAD_IA32_EFER;
vm_exit_controls_set(vmx, exec_control);
/*
@@ -3384,7 +3390,7 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02);
- prepare_vmcs02_early(vmx, vmcs12);
+ prepare_vmcs02_early(vmx, &vmx->vmcs01, vmcs12);
if (from_vmentry) {
if (unlikely(!nested_get_vmcs12_pages(vcpu))) {
@@ -4304,7 +4310,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
seg.l = 1;
else
seg.db = 1;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_CS);
+ __vmx_set_segment(vcpu, &seg, VCPU_SREG_CS);
seg = (struct kvm_segment) {
.base = 0,
.limit = 0xFFFFFFFF,
@@ -4315,17 +4321,17 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
.g = 1
};
seg.selector = vmcs12->host_ds_selector;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_DS);
+ __vmx_set_segment(vcpu, &seg, VCPU_SREG_DS);
seg.selector = vmcs12->host_es_selector;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_ES);
+ __vmx_set_segment(vcpu, &seg, VCPU_SREG_ES);
seg.selector = vmcs12->host_ss_selector;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_SS);
+ __vmx_set_segment(vcpu, &seg, VCPU_SREG_SS);
seg.selector = vmcs12->host_fs_selector;
seg.base = vmcs12->host_fs_base;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_FS);
+ __vmx_set_segment(vcpu, &seg, VCPU_SREG_FS);
seg.selector = vmcs12->host_gs_selector;
seg.base = vmcs12->host_gs_base;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_GS);
+ __vmx_set_segment(vcpu, &seg, VCPU_SREG_GS);
seg = (struct kvm_segment) {
.base = vmcs12->host_tr_base,
.limit = 0x67,
@@ -4333,14 +4339,15 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
.type = 11,
.present = 1
};
- vmx_set_segment(vcpu, &seg, VCPU_SREG_TR);
+ __vmx_set_segment(vcpu, &seg, VCPU_SREG_TR);
+
+ memset(&seg, 0, sizeof(seg));
+ seg.unusable = 1;
+ __vmx_set_segment(vcpu, &seg, VCPU_SREG_LDTR);
kvm_set_dr(vcpu, 7, 0x400);
vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
- if (cpu_has_vmx_msr_bitmap())
- vmx_update_msr_bitmap(vcpu);
-
if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr,
vmcs12->vm_exit_msr_load_count))
nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL);
@@ -4419,9 +4426,6 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
kvm_mmu_reset_context(vcpu);
- if (cpu_has_vmx_msr_bitmap())
- vmx_update_msr_bitmap(vcpu);
-
/*
* This nasty bit of open coding is a compromise between blindly
* loading L1's MSRs using the exit load lists (incorrect emulation
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 9efc1a6b8693..10cc4f65c4ef 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -437,13 +437,13 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
!(msr & MSR_PMC_FULL_WIDTH_BIT))
data = (s64)(s32)data;
pmc->counter += data - pmc_read_counter(pmc);
- if (pmc->perf_event)
+ if (pmc->perf_event && !pmc->is_paused)
perf_event_period(pmc->perf_event,
get_sample_period(pmc, data));
return 0;
} else if ((pmc = get_fixed_pmc(pmu, msr))) {
pmc->counter += data - pmc_read_counter(pmc);
- if (pmc->perf_event)
+ if (pmc->perf_event && !pmc->is_paused)
perf_event_period(pmc->perf_event,
get_sample_period(pmc, data));
return 0;
diff --git a/arch/x86/kvm/vmx/vmcs.h b/arch/x86/kvm/vmx/vmcs.h
index 4b9957e2bf5b..6e5de2e2b0da 100644
--- a/arch/x86/kvm/vmx/vmcs.h
+++ b/arch/x86/kvm/vmx/vmcs.h
@@ -11,6 +11,8 @@
#include "capabilities.h"
+#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
+
struct vmcs_hdr {
u32 revision_id:31;
u32 shadow_vmcs:1;
diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c
index d9f5d7c56ae3..cab6ba7a5005 100644
--- a/arch/x86/kvm/vmx/vmcs12.c
+++ b/arch/x86/kvm/vmx/vmcs12.c
@@ -2,7 +2,6 @@
#include "vmcs12.h"
-#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x)
#define FIELD(number, name) [ROL16(number, 6)] = VMCS12_OFFSET(name)
#define FIELD64(number, name) \
diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h
index 5e0e1b39f495..2a45f026ee11 100644
--- a/arch/x86/kvm/vmx/vmcs12.h
+++ b/arch/x86/kvm/vmx/vmcs12.h
@@ -364,8 +364,6 @@ static inline void vmx_check_vmcs12_offsets(void)
extern const unsigned short vmcs_field_to_offset_table[];
extern const unsigned int nr_vmcs12_fields;
-#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
-
static inline short vmcs_field_to_offset(unsigned long field)
{
unsigned short offset;
@@ -385,8 +383,6 @@ static inline short vmcs_field_to_offset(unsigned long field)
return offset;
}
-#undef ROL16
-
static inline u64 vmcs12_read_any(struct vmcs12 *vmcs12, unsigned long field,
u16 offset)
{
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 927a552393b9..0c2c0d5ae873 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -136,8 +136,7 @@ module_param(allow_smaller_maxphyaddr, bool, S_IRUGO);
#define KVM_VM_CR0_ALWAYS_OFF (X86_CR0_NW | X86_CR0_CD)
#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR0_NE
#define KVM_VM_CR0_ALWAYS_ON \
- (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | \
- X86_CR0_WP | X86_CR0_PG | X86_CR0_PE)
+ (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE)
#define KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR4_VMXE
#define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
@@ -1648,11 +1647,12 @@ static void vmx_setup_uret_msr(struct vcpu_vmx *vmx, unsigned int msr,
}
/*
- * Set up the vmcs to automatically save and restore system
- * msrs. Don't touch the 64-bit msrs if the guest is in legacy
- * mode, as fiddling with msrs is very expensive.
+ * Configuring user return MSRs to automatically save, load, and restore MSRs
+ * that need to be shoved into hardware when running the guest. Note, omitting
+ * an MSR here does _NOT_ mean it's not emulated, only that it will not be
+ * loaded into hardware when running the guest.
*/
-static void setup_msrs(struct vcpu_vmx *vmx)
+static void vmx_setup_uret_msrs(struct vcpu_vmx *vmx)
{
#ifdef CONFIG_X86_64
bool load_syscall_msrs;
@@ -1682,9 +1682,6 @@ static void setup_msrs(struct vcpu_vmx *vmx)
*/
vmx_setup_uret_msr(vmx, MSR_IA32_TSX_CTRL, boot_cpu_has(X86_FEATURE_RTM));
- if (cpu_has_vmx_msr_bitmap())
- vmx_update_msr_bitmap(&vmx->vcpu);
-
/*
* The set of MSRs to load may have changed, reload MSRs before the
* next VM-Enter.
@@ -2263,8 +2260,11 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
vcpu->arch.cr0 |= vmcs_readl(GUEST_CR0) & guest_owned_bits;
break;
case VCPU_EXREG_CR3:
- if (is_unrestricted_guest(vcpu) ||
- (enable_ept && is_paging(vcpu)))
+ /*
+ * When intercepting CR3 loads, e.g. for shadowing paging, KVM's
+ * CR3 is loaded into hardware, not the guest's CR3.
+ */
+ if (!(exec_controls_get(to_vmx(vcpu)) & CPU_BASED_CR3_LOAD_EXITING))
vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
break;
case VCPU_EXREG_CR4:
@@ -2274,7 +2274,7 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
vcpu->arch.cr4 |= vmcs_readl(GUEST_CR4) & guest_owned_bits;
break;
default:
- WARN_ON_ONCE(1);
+ KVM_BUG_ON(1, vcpu->kvm);
break;
}
}
@@ -2733,7 +2733,7 @@ static void fix_pmode_seg(struct kvm_vcpu *vcpu, int seg,
save->dpl = save->selector & SEGMENT_RPL_MASK;
save->s = 1;
}
- vmx_set_segment(vcpu, save, seg);
+ __vmx_set_segment(vcpu, save, seg);
}
static void enter_pmode(struct kvm_vcpu *vcpu)
@@ -2754,7 +2754,7 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
vmx->rmode.vm86_active = 0;
- vmx_set_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
+ __vmx_set_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
flags = vmcs_readl(GUEST_RFLAGS);
flags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
@@ -2852,8 +2852,6 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
fix_rmode_seg(VCPU_SREG_DS, &vmx->rmode.segs[VCPU_SREG_DS]);
fix_rmode_seg(VCPU_SREG_GS, &vmx->rmode.segs[VCPU_SREG_GS]);
fix_rmode_seg(VCPU_SREG_FS, &vmx->rmode.segs[VCPU_SREG_FS]);
-
- kvm_mmu_reset_context(vcpu);
}
int vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
@@ -2874,7 +2872,7 @@ int vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
msr->data = efer & ~EFER_LME;
}
- setup_msrs(vmx);
+ vmx_setup_uret_msrs(vmx);
return 0;
}
@@ -2997,42 +2995,24 @@ void ept_save_pdptrs(struct kvm_vcpu *vcpu)
kvm_register_mark_dirty(vcpu, VCPU_EXREG_PDPTR);
}
-static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
- unsigned long cr0,
- struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (!kvm_register_is_available(vcpu, VCPU_EXREG_CR3))
- vmx_cache_reg(vcpu, VCPU_EXREG_CR3);
- if (!(cr0 & X86_CR0_PG)) {
- /* From paging/starting to nonpaging */
- exec_controls_setbit(vmx, CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_CR3_STORE_EXITING);
- vcpu->arch.cr0 = cr0;
- vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
- } else if (!is_paging(vcpu)) {
- /* From nonpaging to paging */
- exec_controls_clearbit(vmx, CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_CR3_STORE_EXITING);
- vcpu->arch.cr0 = cr0;
- vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
- }
-
- if (!(cr0 & X86_CR0_WP))
- *hw_cr0 &= ~X86_CR0_WP;
-}
+#define CR3_EXITING_BITS (CPU_BASED_CR3_LOAD_EXITING | \
+ CPU_BASED_CR3_STORE_EXITING)
void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned long hw_cr0;
+ unsigned long hw_cr0, old_cr0_pg;
+ u32 tmp;
+
+ old_cr0_pg = kvm_read_cr0_bits(vcpu, X86_CR0_PG);
hw_cr0 = (cr0 & ~KVM_VM_CR0_ALWAYS_OFF);
if (is_unrestricted_guest(vcpu))
hw_cr0 |= KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST;
else {
hw_cr0 |= KVM_VM_CR0_ALWAYS_ON;
+ if (!enable_ept)
+ hw_cr0 |= X86_CR0_WP;
if (vmx->rmode.vm86_active && (cr0 & X86_CR0_PE))
enter_pmode(vcpu);
@@ -3041,22 +3021,60 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
enter_rmode(vcpu);
}
+ vmcs_writel(CR0_READ_SHADOW, cr0);
+ vmcs_writel(GUEST_CR0, hw_cr0);
+ vcpu->arch.cr0 = cr0;
+ kvm_register_mark_available(vcpu, VCPU_EXREG_CR0);
+
#ifdef CONFIG_X86_64
if (vcpu->arch.efer & EFER_LME) {
- if (!is_paging(vcpu) && (cr0 & X86_CR0_PG))
+ if (!old_cr0_pg && (cr0 & X86_CR0_PG))
enter_lmode(vcpu);
- if (is_paging(vcpu) && !(cr0 & X86_CR0_PG))
+ else if (old_cr0_pg && !(cr0 & X86_CR0_PG))
exit_lmode(vcpu);
}
#endif
- if (enable_ept && !is_unrestricted_guest(vcpu))
- ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
+ if (enable_ept && !is_unrestricted_guest(vcpu)) {
+ /*
+ * Ensure KVM has an up-to-date snapshot of the guest's CR3. If
+ * the below code _enables_ CR3 exiting, vmx_cache_reg() will
+ * (correctly) stop reading vmcs.GUEST_CR3 because it thinks
+ * KVM's CR3 is installed.
+ */
+ if (!kvm_register_is_available(vcpu, VCPU_EXREG_CR3))
+ vmx_cache_reg(vcpu, VCPU_EXREG_CR3);
- vmcs_writel(CR0_READ_SHADOW, cr0);
- vmcs_writel(GUEST_CR0, hw_cr0);
- vcpu->arch.cr0 = cr0;
- kvm_register_mark_available(vcpu, VCPU_EXREG_CR0);
+ /*
+ * When running with EPT but not unrestricted guest, KVM must
+ * intercept CR3 accesses when paging is _disabled_. This is
+ * necessary because restricted guests can't actually run with
+ * paging disabled, and so KVM stuffs its own CR3 in order to
+ * run the guest when identity mapped page tables.
+ *
+ * Do _NOT_ check the old CR0.PG, e.g. to optimize away the
+ * update, it may be stale with respect to CR3 interception,
+ * e.g. after nested VM-Enter.
+ *
+ * Lastly, honor L1's desires, i.e. intercept CR3 loads and/or
+ * stores to forward them to L1, even if KVM does not need to
+ * intercept them to preserve its identity mapped page tables.
+ */
+ if (!(cr0 & X86_CR0_PG)) {
+ exec_controls_setbit(vmx, CR3_EXITING_BITS);
+ } else if (!is_guest_mode(vcpu)) {
+ exec_controls_clearbit(vmx, CR3_EXITING_BITS);
+ } else {
+ tmp = exec_controls_get(vmx);
+ tmp &= ~CR3_EXITING_BITS;
+ tmp |= get_vmcs12(vcpu)->cpu_based_vm_exec_control & CR3_EXITING_BITS;
+ exec_controls_set(vmx, tmp);
+ }
+
+ /* Note, vmx_set_cr4() consumes the new vcpu->arch.cr0. */
+ if ((old_cr0_pg ^ cr0) & X86_CR0_PG)
+ vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
+ }
/* depends on vcpu->arch.cr0 to be set to a new value */
vmx->emulation_required = emulation_required(vcpu);
@@ -3271,7 +3289,7 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var)
return ar;
}
-void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
+void __vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -3284,7 +3302,7 @@ void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
vmcs_write16(sf->selector, var->selector);
else if (var->s)
fix_rmode_seg(seg, &vmx->rmode.segs[seg]);
- goto out;
+ return;
}
vmcs_writel(sf->base, var->base);
@@ -3306,9 +3324,13 @@ void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
var->type |= 0x1; /* Accessed */
vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(var));
+}
-out:
- vmx->emulation_required = emulation_required(vcpu);
+static void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
+{
+ __vmx_set_segment(vcpu, var, seg);
+
+ to_vmx(vcpu)->emulation_required = emulation_required(vcpu);
}
static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
@@ -3790,21 +3812,6 @@ void vmx_enable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type)
vmx_set_msr_bitmap_write(msr_bitmap, msr);
}
-static u8 vmx_msr_bitmap_mode(struct kvm_vcpu *vcpu)
-{
- u8 mode = 0;
-
- if (cpu_has_secondary_exec_ctrls() &&
- (secondary_exec_controls_get(to_vmx(vcpu)) &
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
- mode |= MSR_BITMAP_MODE_X2APIC;
- if (enable_apicv && kvm_vcpu_apicv_active(vcpu))
- mode |= MSR_BITMAP_MODE_X2APIC_APICV;
- }
-
- return mode;
-}
-
static void vmx_reset_x2apic_msrs(struct kvm_vcpu *vcpu, u8 mode)
{
unsigned long *msr_bitmap = to_vmx(vcpu)->vmcs01.msr_bitmap;
@@ -3822,11 +3829,29 @@ static void vmx_reset_x2apic_msrs(struct kvm_vcpu *vcpu, u8 mode)
}
}
-static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu, u8 mode)
+static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu)
{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u8 mode;
+
if (!cpu_has_vmx_msr_bitmap())
return;
+ if (cpu_has_secondary_exec_ctrls() &&
+ (secondary_exec_controls_get(vmx) &
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
+ mode = MSR_BITMAP_MODE_X2APIC;
+ if (enable_apicv && kvm_vcpu_apicv_active(vcpu))
+ mode |= MSR_BITMAP_MODE_X2APIC_APICV;
+ } else {
+ mode = 0;
+ }
+
+ if (mode == vmx->x2apic_msr_bitmap_mode)
+ return;
+
+ vmx->x2apic_msr_bitmap_mode = mode;
+
vmx_reset_x2apic_msrs(vcpu, mode);
/*
@@ -3843,21 +3868,6 @@ static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu, u8 mode)
}
}
-void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u8 mode = vmx_msr_bitmap_mode(vcpu);
- u8 changed = mode ^ vmx->msr_bitmap_mode;
-
- if (!changed)
- return;
-
- if (changed & (MSR_BITMAP_MODE_X2APIC | MSR_BITMAP_MODE_X2APIC_APICV))
- vmx_update_msr_bitmap_x2apic(vcpu, mode);
-
- vmx->msr_bitmap_mode = mode;
-}
-
void pt_update_intercept_for_msr(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -3914,7 +3924,6 @@ static void vmx_msr_filter_changed(struct kvm_vcpu *vcpu)
}
pt_update_intercept_for_msr(vcpu);
- vmx_update_msr_bitmap_x2apic(vcpu, vmx_msr_bitmap_mode(vcpu));
}
static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
@@ -4086,7 +4095,7 @@ void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
vmcs_writel(CR4_GUEST_HOST_MASK, ~vcpu->arch.cr4_guest_owned_bits);
}
-u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
+static u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
{
u32 pin_based_exec_ctrl = vmcs_config.pin_based_exec_ctrl;
@@ -4102,6 +4111,30 @@ u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
return pin_based_exec_ctrl;
}
+static u32 vmx_vmentry_ctrl(void)
+{
+ u32 vmentry_ctrl = vmcs_config.vmentry_ctrl;
+
+ if (vmx_pt_mode_is_system())
+ vmentry_ctrl &= ~(VM_ENTRY_PT_CONCEAL_PIP |
+ VM_ENTRY_LOAD_IA32_RTIT_CTL);
+ /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
+ return vmentry_ctrl &
+ ~(VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VM_ENTRY_LOAD_IA32_EFER);
+}
+
+static u32 vmx_vmexit_ctrl(void)
+{
+ u32 vmexit_ctrl = vmcs_config.vmexit_ctrl;
+
+ if (vmx_pt_mode_is_system())
+ vmexit_ctrl &= ~(VM_EXIT_PT_CONCEAL_PIP |
+ VM_EXIT_CLEAR_IA32_RTIT_CTL);
+ /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
+ return vmexit_ctrl &
+ ~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | VM_EXIT_LOAD_IA32_EFER);
+}
+
static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -4118,11 +4151,10 @@ static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
}
- if (cpu_has_vmx_msr_bitmap())
- vmx_update_msr_bitmap(vcpu);
+ vmx_update_msr_bitmap_x2apic(vcpu);
}
-u32 vmx_exec_control(struct vcpu_vmx *vmx)
+static u32 vmx_exec_control(struct vcpu_vmx *vmx)
{
u32 exec_control = vmcs_config.cpu_based_exec_ctrl;
@@ -4204,7 +4236,7 @@ vmx_adjust_secondary_exec_control(struct vcpu_vmx *vmx, u32 *exec_control,
#define vmx_adjust_sec_exec_exiting(vmx, exec_control, lname, uname) \
vmx_adjust_sec_exec_control(vmx, exec_control, lname, uname, uname##_EXITING, true)
-static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
+static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
{
struct kvm_vcpu *vcpu = &vmx->vcpu;
@@ -4290,7 +4322,7 @@ static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
if (!vcpu->kvm->arch.bus_lock_detection_enabled)
exec_control &= ~SECONDARY_EXEC_BUS_LOCK_DETECTION;
- vmx->secondary_exec_control = exec_control;
+ return exec_control;
}
#define VMX_XSS_EXIT_BITMAP 0
@@ -4314,10 +4346,8 @@ static void init_vmcs(struct vcpu_vmx *vmx)
exec_controls_set(vmx, vmx_exec_control(vmx));
- if (cpu_has_secondary_exec_ctrls()) {
- vmx_compute_secondary_exec_control(vmx);
- secondary_exec_controls_set(vmx, vmx->secondary_exec_control);
- }
+ if (cpu_has_secondary_exec_ctrls())
+ secondary_exec_controls_set(vmx, vmx_secondary_exec_control(vmx));
if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
vmcs_write64(EOI_EXIT_BITMAP0, 0);
@@ -4388,32 +4418,35 @@ static void init_vmcs(struct vcpu_vmx *vmx)
vmx->pt_desc.guest.output_mask = 0x7F;
vmcs_write64(GUEST_IA32_RTIT_CTL, 0);
}
+
+ vmcs_write32(GUEST_SYSENTER_CS, 0);
+ vmcs_writel(GUEST_SYSENTER_ESP, 0);
+ vmcs_writel(GUEST_SYSENTER_EIP, 0);
+ vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
+
+ if (cpu_has_vmx_tpr_shadow()) {
+ vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
+ if (cpu_need_tpr_shadow(&vmx->vcpu))
+ vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
+ __pa(vmx->vcpu.arch.apic->regs));
+ vmcs_write32(TPR_THRESHOLD, 0);
+ }
+
+ vmx_setup_uret_msrs(vmx);
}
static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct msr_data apic_base_msr;
- u64 cr0;
vmx->rmode.vm86_active = 0;
vmx->spec_ctrl = 0;
vmx->msr_ia32_umwait_control = 0;
- vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
vmx->hv_deadline_tsc = -1;
kvm_set_cr8(vcpu, 0);
- if (!init_event) {
- apic_base_msr.data = APIC_DEFAULT_PHYS_BASE |
- MSR_IA32_APICBASE_ENABLE;
- if (kvm_vcpu_is_reset_bsp(vcpu))
- apic_base_msr.data |= MSR_IA32_APICBASE_BSP;
- apic_base_msr.host_initiated = true;
- kvm_set_apic_base(vcpu, &apic_base_msr);
- }
-
vmx_segment_cache_clear(vmx);
seg_setup(VCPU_SREG_CS);
@@ -4436,16 +4469,6 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
vmcs_write32(GUEST_LDTR_LIMIT, 0xffff);
vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082);
- if (!init_event) {
- vmcs_write32(GUEST_SYSENTER_CS, 0);
- vmcs_writel(GUEST_SYSENTER_ESP, 0);
- vmcs_writel(GUEST_SYSENTER_EIP, 0);
- vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
- }
-
- kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
- kvm_rip_write(vcpu, 0xfff0);
-
vmcs_writel(GUEST_GDTR_BASE, 0);
vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
@@ -4458,31 +4481,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
if (kvm_mpx_supported())
vmcs_write64(GUEST_BNDCFGS, 0);
- setup_msrs(vmx);
-
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */
- if (cpu_has_vmx_tpr_shadow() && !init_event) {
- vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
- if (cpu_need_tpr_shadow(vcpu))
- vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
- __pa(vcpu->arch.apic->regs));
- vmcs_write32(TPR_THRESHOLD, 0);
- }
-
kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
- cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
- vmx->vcpu.arch.cr0 = cr0;
- vmx_set_cr0(vcpu, cr0); /* enter rmode */
- vmx_set_cr4(vcpu, 0);
- vmx_set_efer(vcpu, 0);
-
- vmx_update_exception_bitmap(vcpu);
-
vpid_sync_context(vmx->vpid);
- if (init_event)
- vmx_clear_hlt(vcpu);
}
static void vmx_enable_irq_window(struct kvm_vcpu *vcpu)
@@ -4996,6 +4999,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
return kvm_complete_insn_gp(vcpu, err);
case 3:
WARN_ON_ONCE(enable_unrestricted_guest);
+
err = kvm_set_cr3(vcpu, val);
return kvm_complete_insn_gp(vcpu, err);
case 4:
@@ -5021,14 +5025,13 @@ static int handle_cr(struct kvm_vcpu *vcpu)
}
break;
case 2: /* clts */
- WARN_ONCE(1, "Guest should always own CR0.TS");
- vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
- trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
- return kvm_skip_emulated_instruction(vcpu);
+ KVM_BUG(1, vcpu->kvm, "Guest always owns CR0.TS");
+ return -EIO;
case 1: /*mov from cr*/
switch (cr) {
case 3:
WARN_ON_ONCE(enable_unrestricted_guest);
+
val = kvm_read_cr3(vcpu);
kvm_register_write(vcpu, reg, val);
trace_kvm_cr_read(cr, val);
@@ -5129,6 +5132,12 @@ static void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_WONT_EXIT;
exec_controls_setbit(to_vmx(vcpu), CPU_BASED_MOV_DR_EXITING);
+
+ /*
+ * exc_debug expects dr6 to be cleared after it runs, avoid that it sees
+ * a stale dr6 from the guest.
+ */
+ set_debugreg(DR6_RESERVED, 6);
}
static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val)
@@ -5338,7 +5347,9 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
static int handle_nmi_window(struct kvm_vcpu *vcpu)
{
- WARN_ON_ONCE(!enable_vnmi);
+ if (KVM_BUG_ON(!enable_vnmi, vcpu->kvm))
+ return -EIO;
+
exec_controls_clearbit(to_vmx(vcpu), CPU_BASED_NMI_WINDOW_EXITING);
++vcpu->stat.nmi_window_exits;
kvm_make_request(KVM_REQ_EVENT, vcpu);
@@ -5896,7 +5907,8 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
* below) should never happen as that means we incorrectly allowed a
* nested VM-Enter with an invalid vmcs12.
*/
- WARN_ON_ONCE(vmx->nested.nested_run_pending);
+ if (KVM_BUG_ON(vmx->nested.nested_run_pending, vcpu->kvm))
+ return -EIO;
/* If guest state is invalid, start emulating */
if (vmx->emulation_required)
@@ -6189,7 +6201,7 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
}
secondary_exec_controls_set(vmx, sec_exec_control);
- vmx_update_msr_bitmap(vcpu);
+ vmx_update_msr_bitmap_x2apic(vcpu);
}
static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu)
@@ -6274,7 +6286,9 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
int max_irr;
bool max_irr_updated;
- WARN_ON(!vcpu->arch.apicv_active);
+ if (KVM_BUG_ON(!vcpu->arch.apicv_active, vcpu->kvm))
+ return -EIO;
+
if (pi_test_on(&vmx->pi_desc)) {
pi_clear_on(&vmx->pi_desc);
/*
@@ -6357,7 +6371,7 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu)
unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
gate_desc *desc = (gate_desc *)host_idt_base + vector;
- if (WARN_ONCE(!is_external_intr(intr_info),
+ if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
"KVM: unexpected VM-Exit interrupt info: 0x%x", intr_info))
return;
@@ -6368,6 +6382,9 @@ static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ if (vmx->emulation_required)
+ return;
+
if (vmx->exit_reason.basic == EXIT_REASON_EXTERNAL_INTERRUPT)
handle_external_interrupt_irqoff(vcpu);
else if (vmx->exit_reason.basic == EXIT_REASON_EXCEPTION_NMI)
@@ -6639,6 +6656,10 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
vmx->loaded_vmcs->host_state.cr4 = cr4;
}
+ /* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */
+ if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
+ set_debugreg(vcpu->arch.dr6, 6);
+
/* When single-stepping over STI and MOV SS, we must clear the
* corresponding interruptibility bits in the guest state. Otherwise
* vmentry fails as it then expects bit 14 (BS) in pending debug
@@ -6838,7 +6859,6 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
vmx_disable_intercept_for_msr(vcpu, MSR_CORE_C6_RESIDENCY, MSR_TYPE_R);
vmx_disable_intercept_for_msr(vcpu, MSR_CORE_C7_RESIDENCY, MSR_TYPE_R);
}
- vmx->msr_bitmap_mode = 0;
vmx->loaded_vmcs = &vmx->vmcs01;
cpu = get_cpu();
@@ -6997,7 +7017,7 @@ exit:
return (cache << VMX_EPT_MT_EPTE_SHIFT) | ipat;
}
-static void vmcs_set_secondary_exec_control(struct vcpu_vmx *vmx)
+static void vmcs_set_secondary_exec_control(struct vcpu_vmx *vmx, u32 new_ctl)
{
/*
* These bits in the secondary execution controls field
@@ -7011,7 +7031,6 @@ static void vmcs_set_secondary_exec_control(struct vcpu_vmx *vmx)
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
SECONDARY_EXEC_DESC;
- u32 new_ctl = vmx->secondary_exec_control;
u32 cur_ctl = secondary_exec_controls_get(vmx);
secondary_exec_controls_set(vmx, (new_ctl & ~mask) | (cur_ctl & mask));
@@ -7154,10 +7173,11 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
/* xsaves_enabled is recomputed in vmx_compute_secondary_exec_control(). */
vcpu->arch.xsaves_enabled = false;
- if (cpu_has_secondary_exec_ctrls()) {
- vmx_compute_secondary_exec_control(vmx);
- vmcs_set_secondary_exec_control(vmx);
- }
+ vmx_setup_uret_msrs(vmx);
+
+ if (cpu_has_secondary_exec_ctrls())
+ vmcs_set_secondary_exec_control(vmx,
+ vmx_secondary_exec_control(vmx));
if (nested_vmx_allowed(vcpu))
to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
@@ -7803,7 +7823,8 @@ static __init int hardware_setup(void)
ept_lpage_level = PG_LEVEL_2M;
else
ept_lpage_level = PG_LEVEL_4K;
- kvm_configure_mmu(enable_ept, vmx_get_max_tdp_level(), ept_lpage_level);
+ kvm_configure_mmu(enable_ept, 0, vmx_get_max_tdp_level(),
+ ept_lpage_level);
/*
* Only enable PML when hardware supports PML feature, and both EPT
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 17a1cb4b059d..4858c5fd95f2 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -227,7 +227,7 @@ struct nested_vmx {
struct vcpu_vmx {
struct kvm_vcpu vcpu;
u8 fail;
- u8 msr_bitmap_mode;
+ u8 x2apic_msr_bitmap_mode;
/*
* If true, host state has been stored in vmx->loaded_vmcs for
@@ -263,8 +263,6 @@ struct vcpu_vmx {
u64 spec_ctrl;
u32 msr_ia32_umwait_control;
- u32 secondary_exec_control;
-
/*
* loaded_vmcs points to the VMCS currently used in this vcpu. For a
* non-nested (L1) guest, it always points to vmcs01. For a nested
@@ -371,12 +369,11 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
void set_cr4_guest_host_mask(struct vcpu_vmx *vmx);
void ept_save_pdptrs(struct kvm_vcpu *vcpu);
void vmx_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
-void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
+void __vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
u64 construct_eptp(struct kvm_vcpu *vcpu, hpa_t root_hpa, int root_level);
bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu);
void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu);
-void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu);
bool vmx_nmi_blocked(struct kvm_vcpu *vcpu);
bool vmx_interrupt_blocked(struct kvm_vcpu *vcpu);
bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu);
@@ -419,9 +416,13 @@ static inline void lname##_controls_set(struct vcpu_vmx *vmx, u32 val) \
vmx->loaded_vmcs->controls_shadow.lname = val; \
} \
} \
+static inline u32 __##lname##_controls_get(struct loaded_vmcs *vmcs) \
+{ \
+ return vmcs->controls_shadow.lname; \
+} \
static inline u32 lname##_controls_get(struct vcpu_vmx *vmx) \
{ \
- return vmx->loaded_vmcs->controls_shadow.lname; \
+ return __##lname##_controls_get(vmx->loaded_vmcs); \
} \
static inline void lname##_controls_setbit(struct vcpu_vmx *vmx, u32 val) \
{ \
@@ -451,31 +452,6 @@ static inline void vmx_register_cache_reset(struct kvm_vcpu *vcpu)
vcpu->arch.regs_dirty = 0;
}
-static inline u32 vmx_vmentry_ctrl(void)
-{
- u32 vmentry_ctrl = vmcs_config.vmentry_ctrl;
- if (vmx_pt_mode_is_system())
- vmentry_ctrl &= ~(VM_ENTRY_PT_CONCEAL_PIP |
- VM_ENTRY_LOAD_IA32_RTIT_CTL);
- /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
- return vmentry_ctrl &
- ~(VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VM_ENTRY_LOAD_IA32_EFER);
-}
-
-static inline u32 vmx_vmexit_ctrl(void)
-{
- u32 vmexit_ctrl = vmcs_config.vmexit_ctrl;
- if (vmx_pt_mode_is_system())
- vmexit_ctrl &= ~(VM_EXIT_PT_CONCEAL_PIP |
- VM_EXIT_CLEAR_IA32_RTIT_CTL);
- /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
- return vmexit_ctrl &
- ~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | VM_EXIT_LOAD_IA32_EFER);
-}
-
-u32 vmx_exec_control(struct vcpu_vmx *vmx);
-u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx);
-
static inline struct kvm_vmx *to_kvm_vmx(struct kvm *kvm)
{
return container_of(kvm, struct kvm_vmx, kvm);
diff --git a/arch/x86/kvm/vmx/vmx_ops.h b/arch/x86/kvm/vmx/vmx_ops.h
index 164b64f65a8f..9e9ef47e988c 100644
--- a/arch/x86/kvm/vmx/vmx_ops.h
+++ b/arch/x86/kvm/vmx/vmx_ops.h
@@ -4,13 +4,11 @@
#include <linux/nospec.h>
-#include <asm/kvm_host.h>
#include <asm/vmx.h>
#include "evmcs.h"
#include "vmcs.h"
-
-#define __ex(x) __kvm_handle_fault_on_reboot(x)
+#include "x86.h"
asmlinkage void vmread_error(unsigned long field, bool fault);
__attribute__((regparm(0))) void vmread_error_trampoline(unsigned long field,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e5d5c5ed7dd4..28ef14155726 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -233,12 +233,13 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_COUNTER(VM, mmu_recycled),
STATS_DESC_COUNTER(VM, mmu_cache_miss),
STATS_DESC_ICOUNTER(VM, mmu_unsync),
- STATS_DESC_ICOUNTER(VM, lpages),
+ STATS_DESC_ICOUNTER(VM, pages_4k),
+ STATS_DESC_ICOUNTER(VM, pages_2m),
+ STATS_DESC_ICOUNTER(VM, pages_1g),
STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
+ STATS_DESC_PCOUNTER(VM, max_mmu_rmap_size),
STATS_DESC_PCOUNTER(VM, max_mmu_page_hash_collisions)
};
-static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
- sizeof(struct kvm_vm_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vm_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -278,8 +279,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
STATS_DESC_COUNTER(VCPU, directed_yield_successful),
STATS_DESC_ICOUNTER(VCPU, guest_mode)
};
-static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
- sizeof(struct kvm_vcpu_stat) / sizeof(u64));
const struct kvm_stats_header kvm_vcpu_stats_header = {
.name_size = KVM_STATS_NAME_SIZE,
@@ -485,7 +484,14 @@ int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
}
EXPORT_SYMBOL_GPL(kvm_set_apic_base);
-asmlinkage __visible noinstr void kvm_spurious_fault(void)
+/*
+ * Handle a fault on a hardware virtualization (VMX or SVM) instruction.
+ *
+ * Hardware virtualization extension instructions may fault if a reboot turns
+ * off virtualization while processes are running. Usually after catching the
+ * fault we just panic; during reboot instead the instruction is ignored.
+ */
+noinstr void kvm_spurious_fault(void)
{
/* Fault while not rebooting. We want the trace. */
BUG_ON(!kvm_rebooting);
@@ -1180,7 +1186,6 @@ static void kvm_update_dr0123(struct kvm_vcpu *vcpu)
if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) {
for (i = 0; i < KVM_NR_DB_REGS; i++)
vcpu->arch.eff_db[i] = vcpu->arch.db[i];
- vcpu->arch.switch_db_regs |= KVM_DEBUGREG_RELOAD;
}
}
@@ -3316,6 +3321,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (!msr_info->host_initiated) {
s64 adj = data - vcpu->arch.ia32_tsc_adjust_msr;
adjust_tsc_offset_guest(vcpu, adj);
+ /* Before back to guest, tsc_timestamp must be adjusted
+ * as well, otherwise guest's percpu pvclock time could jump.
+ */
+ kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
}
vcpu->arch.ia32_tsc_adjust_msr = data;
}
@@ -4310,12 +4319,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
static_call(kvm_x86_vcpu_put)(vcpu);
vcpu->arch.last_host_tsc = rdtsc();
- /*
- * If userspace has set any breakpoints or watchpoints, dr6 is restored
- * on every vmexit, but if not, we might have a stale dr6 from the
- * guest. do_debug expects dr6 to be cleared after it runs, do the same.
- */
- set_debugreg(0, 6);
}
static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
@@ -6567,9 +6570,9 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
* there is no pkey in EPT page table for L1 guest or EPT
* shadow page table for L2 guest.
*/
- if (vcpu_match_mmio_gva(vcpu, gva)
- && !permission_fault(vcpu, vcpu->arch.walk_mmu,
- vcpu->arch.mmio_access, 0, access)) {
+ if (vcpu_match_mmio_gva(vcpu, gva) && (!is_paging(vcpu) ||
+ !permission_fault(vcpu, vcpu->arch.walk_mmu,
+ vcpu->arch.mmio_access, 0, access))) {
*gpa = vcpu->arch.mmio_gfn << PAGE_SHIFT |
(gva & (PAGE_SIZE - 1));
trace_vcpu_match_mmio(gva, *gpa, write, false);
@@ -8578,6 +8581,8 @@ EXPORT_SYMBOL_GPL(kvm_apicv_activated);
static void kvm_apicv_init(struct kvm *kvm)
{
+ mutex_init(&kvm->arch.apicv_update_lock);
+
if (enable_apicv)
clear_bit(APICV_INHIBIT_REASON_DISABLE,
&kvm->arch.apicv_inhibit_reasons);
@@ -8891,6 +8896,10 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool *req_immediate_exit)
can_inject = false;
}
+ /* Don't inject interrupts if the user asked to avoid doing so */
+ if (vcpu->guest_debug & KVM_GUESTDBG_BLOCKIRQ)
+ return 0;
+
/*
* Finally, inject interrupt events. If an event cannot be injected
* due to architectural conditions (e.g. IF=0) a window-open exit
@@ -9236,10 +9245,18 @@ void kvm_make_scan_ioapic_request(struct kvm *kvm)
void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
{
+ bool activate;
+
if (!lapic_in_kernel(vcpu))
return;
- vcpu->arch.apicv_active = kvm_apicv_activated(vcpu->kvm);
+ mutex_lock(&vcpu->kvm->arch.apicv_update_lock);
+
+ activate = kvm_apicv_activated(vcpu->kvm);
+ if (vcpu->arch.apicv_active == activate)
+ goto out;
+
+ vcpu->arch.apicv_active = activate;
kvm_apic_update_apicv(vcpu);
static_call(kvm_x86_refresh_apicv_exec_ctrl)(vcpu);
@@ -9251,54 +9268,45 @@ void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
*/
if (!vcpu->arch.apicv_active)
kvm_make_request(KVM_REQ_EVENT, vcpu);
+
+out:
+ mutex_unlock(&vcpu->kvm->arch.apicv_update_lock);
}
EXPORT_SYMBOL_GPL(kvm_vcpu_update_apicv);
-/*
- * NOTE: Do not hold any lock prior to calling this.
- *
- * In particular, kvm_request_apicv_update() expects kvm->srcu not to be
- * locked, because it calls __x86_set_memory_region() which does
- * synchronize_srcu(&kvm->srcu).
- */
-void kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
+void __kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
{
- struct kvm_vcpu *except;
- unsigned long old, new, expected;
+ unsigned long old, new;
if (!kvm_x86_ops.check_apicv_inhibit_reasons ||
!static_call(kvm_x86_check_apicv_inhibit_reasons)(bit))
return;
- old = READ_ONCE(kvm->arch.apicv_inhibit_reasons);
- do {
- expected = new = old;
- if (activate)
- __clear_bit(bit, &new);
- else
- __set_bit(bit, &new);
- if (new == old)
- break;
- old = cmpxchg(&kvm->arch.apicv_inhibit_reasons, expected, new);
- } while (old != expected);
-
- if (!!old == !!new)
- return;
+ old = new = kvm->arch.apicv_inhibit_reasons;
- trace_kvm_apicv_update_request(activate, bit);
- if (kvm_x86_ops.pre_update_apicv_exec_ctrl)
- static_call(kvm_x86_pre_update_apicv_exec_ctrl)(kvm, activate);
+ if (activate)
+ __clear_bit(bit, &new);
+ else
+ __set_bit(bit, &new);
+
+ if (!!old != !!new) {
+ trace_kvm_apicv_update_request(activate, bit);
+ kvm_make_all_cpus_request(kvm, KVM_REQ_APICV_UPDATE);
+ kvm->arch.apicv_inhibit_reasons = new;
+ if (new) {
+ unsigned long gfn = gpa_to_gfn(APIC_DEFAULT_PHYS_BASE);
+ kvm_zap_gfn_range(kvm, gfn, gfn+1);
+ }
+ } else
+ kvm->arch.apicv_inhibit_reasons = new;
+}
+EXPORT_SYMBOL_GPL(__kvm_request_apicv_update);
- /*
- * Sending request to update APICV for all other vcpus,
- * while update the calling vcpu immediately instead of
- * waiting for another #VMEXIT to handle the request.
- */
- except = kvm_get_running_vcpu();
- kvm_make_all_cpus_request_except(kvm, KVM_REQ_APICV_UPDATE,
- except);
- if (except)
- kvm_vcpu_update_apicv(except);
+void kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
+{
+ mutex_lock(&kvm->arch.apicv_update_lock);
+ __kvm_request_apicv_update(kvm, activate, bit);
+ mutex_unlock(&kvm->arch.apicv_update_lock);
}
EXPORT_SYMBOL_GPL(kvm_request_apicv_update);
@@ -9395,6 +9403,10 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
}
if (kvm_request_pending(vcpu)) {
+ if (kvm_check_request(KVM_REQ_VM_BUGGED, vcpu)) {
+ r = -EIO;
+ goto out;
+ }
if (kvm_check_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu)) {
if (unlikely(!kvm_x86_ops.nested_ops->get_nested_state_pages(vcpu))) {
r = 0;
@@ -9608,8 +9620,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
set_debugreg(vcpu->arch.eff_db[1], 1);
set_debugreg(vcpu->arch.eff_db[2], 2);
set_debugreg(vcpu->arch.eff_db[3], 3);
- set_debugreg(vcpu->arch.dr6, 6);
- vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
} else if (unlikely(hw_breakpoint_active())) {
set_debugreg(0, 7);
}
@@ -9639,7 +9649,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
static_call(kvm_x86_sync_dirty_debug_regs)(vcpu);
kvm_update_dr0123(vcpu);
kvm_update_dr7(vcpu);
- vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
}
/*
@@ -9976,7 +9985,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
goto out;
}
- if (kvm_run->kvm_valid_regs & ~KVM_SYNC_X86_VALID_FIELDS) {
+ if ((kvm_run->kvm_valid_regs & ~KVM_SYNC_X86_VALID_FIELDS) ||
+ (kvm_run->kvm_dirty_regs & ~KVM_SYNC_X86_VALID_FIELDS)) {
r = -EINVAL;
goto out;
}
@@ -10581,9 +10591,6 @@ static void store_regs(struct kvm_vcpu *vcpu)
static int sync_regs(struct kvm_vcpu *vcpu)
{
- if (vcpu->run->kvm_dirty_regs & ~KVM_SYNC_X86_VALID_FIELDS)
- return -EINVAL;
-
if (vcpu->run->kvm_dirty_regs & KVM_SYNC_X86_REGS) {
__set_regs(vcpu, &vcpu->run->s.regs.regs);
vcpu->run->kvm_dirty_regs &= ~KVM_SYNC_X86_REGS;
@@ -10799,6 +10806,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
{
unsigned long old_cr0 = kvm_read_cr0(vcpu);
+ unsigned long new_cr0;
+ u32 eax, dummy;
kvm_lapic_reset(vcpu, init_event);
@@ -10865,10 +10874,41 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
vcpu->arch.regs_avail = ~0;
vcpu->arch.regs_dirty = ~0;
+ /*
+ * Fall back to KVM's default Family/Model/Stepping of 0x600 (P6/Athlon)
+ * if no CPUID match is found. Note, it's impossible to get a match at
+ * RESET since KVM emulates RESET before exposing the vCPU to userspace,
+ * i.e. it'simpossible for kvm_cpuid() to find a valid entry on RESET.
+ * But, go through the motions in case that's ever remedied.
+ */
+ eax = 1;
+ if (!kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy, true))
+ eax = 0x600;
+ kvm_rdx_write(vcpu, eax);
+
vcpu->arch.ia32_xss = 0;
static_call(kvm_x86_vcpu_reset)(vcpu, init_event);
+ kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
+ kvm_rip_write(vcpu, 0xfff0);
+
+ /*
+ * CR0.CD/NW are set on RESET, preserved on INIT. Note, some versions
+ * of Intel's SDM list CD/NW as being set on INIT, but they contradict
+ * (or qualify) that with a footnote stating that CD/NW are preserved.
+ */
+ new_cr0 = X86_CR0_ET;
+ if (init_event)
+ new_cr0 |= (old_cr0 & (X86_CR0_NW | X86_CR0_CD));
+ else
+ new_cr0 |= X86_CR0_NW | X86_CR0_CD;
+
+ static_call(kvm_x86_set_cr0)(vcpu, new_cr0);
+ static_call(kvm_x86_set_cr4)(vcpu, 0);
+ static_call(kvm_x86_set_efer)(vcpu, 0);
+ static_call(kvm_x86_update_exception_bitmap)(vcpu);
+
/*
* Reset the MMU context if paging was enabled prior to INIT (which is
* implied if CR0.PG=1 as CR0 will be '0' prior to RESET). Unlike the
@@ -10879,7 +10919,20 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
*/
if (old_cr0 & X86_CR0_PG)
kvm_mmu_reset_context(vcpu);
+
+ /*
+ * Intel's SDM states that all TLB entries are flushed on INIT. AMD's
+ * APM states the TLBs are untouched by INIT, but it also states that
+ * the TLBs are flushed on "External initialization of the processor."
+ * Flush the guest TLB regardless of vendor, there is no meaningful
+ * benefit in relying on the guest to flush the TLB immediately after
+ * INIT. A spurious TLB flush is benign and likely negligible from a
+ * performance perspective.
+ */
+ if (init_event)
+ kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
}
+EXPORT_SYMBOL_GPL(kvm_vcpu_reset);
void kvm_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector)
{
@@ -11123,6 +11176,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
kvm_hv_init_vm(kvm);
kvm_page_track_init(kvm);
kvm_mmu_init_vm(kvm);
+ kvm_xen_init_vm(kvm);
return static_call(kvm_x86_vm_init)(kvm);
}
@@ -11312,8 +11366,7 @@ static int memslot_rmap_alloc(struct kvm_memory_slot *slot,
for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) {
int level = i + 1;
- int lpages = gfn_to_index(slot->base_gfn + npages - 1,
- slot->base_gfn, level) + 1;
+ int lpages = __kvm_mmu_slot_lpages(slot, npages, level);
WARN_ON(slot->arch.rmap[i]);
@@ -11396,8 +11449,7 @@ static int kvm_alloc_memslot_metadata(struct kvm *kvm,
int lpages;
int level = i + 1;
- lpages = gfn_to_index(slot->base_gfn + npages - 1,
- slot->base_gfn, level) + 1;
+ lpages = __kvm_mmu_slot_lpages(slot, npages, level);
linfo = kvcalloc(lpages, sizeof(*linfo), GFP_KERNEL_ACCOUNT);
if (!linfo)
@@ -11481,7 +11533,7 @@ static void kvm_mmu_update_cpu_dirty_logging(struct kvm *kvm, bool enable)
static void kvm_mmu_slot_apply_flags(struct kvm *kvm,
struct kvm_memory_slot *old,
- struct kvm_memory_slot *new,
+ const struct kvm_memory_slot *new,
enum kvm_mr_change change)
{
bool log_dirty_pages = new->flags & KVM_MEM_LOG_DIRTY_PAGES;
@@ -11561,10 +11613,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
kvm_mmu_change_mmu_pages(kvm,
kvm_mmu_calculate_default_mmu_pages(kvm));
- /*
- * FIXME: const-ify all uses of struct kvm_memory_slot.
- */
- kvm_mmu_slot_apply_flags(kvm, old, (struct kvm_memory_slot *) new, change);
+ kvm_mmu_slot_apply_flags(kvm, old, new, change);
/* Free the arrays associated with the old memslot. */
if (change == KVM_MR_MOVE)
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 44ae10312740..7d66d63dc55a 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -8,6 +8,8 @@
#include "kvm_cache_regs.h"
#include "kvm_emulate.h"
+void kvm_spurious_fault(void);
+
static __always_inline void kvm_guest_enter_irqoff(void)
{
/*
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index ae17250e1efe..9ea9c3dabe37 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -25,15 +25,14 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
{
gpa_t gpa = gfn_to_gpa(gfn);
int wc_ofs, sec_hi_ofs;
- int ret;
+ int ret = 0;
int idx = srcu_read_lock(&kvm->srcu);
- ret = kvm_gfn_to_hva_cache_init(kvm, &kvm->arch.xen.shinfo_cache,
- gpa, PAGE_SIZE);
- if (ret)
+ if (kvm_is_error_hva(gfn_to_hva(kvm, gfn))) {
+ ret = -EFAULT;
goto out;
-
- kvm->arch.xen.shinfo_set = true;
+ }
+ kvm->arch.xen.shinfo_gfn = gfn;
/* Paranoia checks on the 32-bit struct layout */
BUILD_BUG_ON(offsetof(struct compat_shared_info, wc) != 0x900);
@@ -245,7 +244,7 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
case KVM_XEN_ATTR_TYPE_SHARED_INFO:
if (data->u.shared_info.gfn == GPA_INVALID) {
- kvm->arch.xen.shinfo_set = false;
+ kvm->arch.xen.shinfo_gfn = GPA_INVALID;
r = 0;
break;
}
@@ -283,10 +282,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
break;
case KVM_XEN_ATTR_TYPE_SHARED_INFO:
- if (kvm->arch.xen.shinfo_set)
- data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_cache.gpa);
- else
- data->u.shared_info.gfn = GPA_INVALID;
+ data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_gfn);
r = 0;
break;
@@ -646,6 +642,11 @@ int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc)
return 0;
}
+void kvm_xen_init_vm(struct kvm *kvm)
+{
+ kvm->arch.xen.shinfo_gfn = GPA_INVALID;
+}
+
void kvm_xen_destroy_vm(struct kvm *kvm)
{
if (kvm->arch.xen_hvm_config.msr)
diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h
index 463a7844a8ca..cc0cf5f37450 100644
--- a/arch/x86/kvm/xen.h
+++ b/arch/x86/kvm/xen.h
@@ -21,6 +21,7 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data);
int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc);
+void kvm_xen_init_vm(struct kvm *kvm);
void kvm_xen_destroy_vm(struct kvm *kvm);
static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
@@ -50,6 +51,10 @@ static inline int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data)
return 1;
}
+static inline void kvm_xen_init_vm(struct kvm *kvm)
+{
+}
+
static inline void kvm_xen_destroy_vm(struct kvm *kvm)
{
}
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 75ef19aa8903..23a14d82e783 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -127,14 +127,12 @@ __ref void *alloc_low_pages(unsigned int num)
unsigned long ret = 0;
if (min_pfn_mapped < max_pfn_mapped) {
- ret = memblock_find_in_range(
+ ret = memblock_phys_alloc_range(
+ PAGE_SIZE * num, PAGE_SIZE,
min_pfn_mapped << PAGE_SHIFT,
- max_pfn_mapped << PAGE_SHIFT,
- PAGE_SIZE * num , PAGE_SIZE);
+ max_pfn_mapped << PAGE_SHIFT);
}
- if (ret)
- memblock_reserve(ret, PAGE_SIZE * num);
- else if (can_use_brk_pgt)
+ if (!ret && can_use_brk_pgt)
ret = __pa(extend_brk(PAGE_SIZE * num, PAGE_SIZE));
if (!ret)
@@ -610,8 +608,17 @@ static void __init memory_map_top_down(unsigned long map_start,
unsigned long addr;
unsigned long mapped_ram_size = 0;
- /* xen has big range in reserved near end of ram, skip it at first.*/
- addr = memblock_find_in_range(map_start, map_end, PMD_SIZE, PMD_SIZE);
+ /*
+ * Systems that have many reserved areas near top of the memory,
+ * e.g. QEMU with less than 1G RAM and EFI enabled, or Xen, will
+ * require lots of 4K mappings which may exhaust pgt_buf.
+ * Start with top-most PMD_SIZE range aligned at PMD_SIZE to ensure
+ * there is enough mapped memory that can be allocated from
+ * memblock.
+ */
+ addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start,
+ map_end);
+ memblock_free(addr, PMD_SIZE);
real_end = addr + PMD_SIZE;
/* step_size need to be small so pgt_buf from BRK could cover it */
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index e94da744386f..a1b5c71099e6 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -376,15 +376,14 @@ static int __init numa_alloc_distance(void)
cnt++;
size = cnt * cnt * sizeof(numa_distance[0]);
- phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
- size, PAGE_SIZE);
+ phys = memblock_phys_alloc_range(size, PAGE_SIZE, 0,
+ PFN_PHYS(max_pfn_mapped));
if (!phys) {
pr_warn("Warning: can't allocate distance table!\n");
/* don't retry until explicitly reset */
numa_distance = (void *)1LU;
return -ENOMEM;
}
- memblock_reserve(phys, size);
numa_distance = __va(phys);
numa_distance_cnt = cnt;
diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c
index 87d77cc52f86..737491b13728 100644
--- a/arch/x86/mm/numa_emulation.c
+++ b/arch/x86/mm/numa_emulation.c
@@ -447,13 +447,12 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
if (numa_dist_cnt) {
u64 phys;
- phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
- phys_size, PAGE_SIZE);
+ phys = memblock_phys_alloc_range(phys_size, PAGE_SIZE, 0,
+ PFN_PHYS(max_pfn_mapped));
if (!phys) {
pr_warn("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
goto no_emu;
}
- memblock_reserve(phys, phys_size);
phys_dist = __va(phys);
for (i = 0; i < numa_dist_cnt; i++)
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 6534c92d0f83..31b5856010cb 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -28,7 +28,7 @@ void __init reserve_real_mode(void)
WARN_ON(slab_is_available());
/* Has to be under 1M so we can execute real-mode AP code. */
- mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
+ mem = memblock_phys_alloc_range(size, PAGE_SIZE, 0, 1<<20);
if (!mem)
pr_info("No sub-1M memory is available for the trampoline\n");
else
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 03149422dce2..753f63734c13 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -116,9 +116,8 @@ static void __init xen_banner(void)
HYPERVISOR_xen_version(XENVER_extraversion, &extra);
pr_info("Booting paravirtualized kernel on %s\n", pv_info.name);
- printk(KERN_INFO "Xen version: %d.%d%s%s\n",
- version >> 16, version & 0xffff, extra.extraversion,
- xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
+ pr_info("Xen version: %d.%d%s (preserve-AD)\n",
+ version >> 16, version & 0xffff, extra.extraversion);
}
static void __init xen_pv_init_platform(void)
@@ -1302,13 +1301,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
xen_init_apic();
#endif
- if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
- pv_ops.mmu.ptep_modify_prot_start =
- xen_ptep_modify_prot_start;
- pv_ops.mmu.ptep_modify_prot_commit =
- xen_ptep_modify_prot_commit;
- }
-
machine_ops = xen_machine_ops;
/*
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
index ade789e73ee4..1df5f01529e5 100644
--- a/arch/x86/xen/mmu_pv.c
+++ b/arch/x86/xen/mmu_pv.c
@@ -2099,8 +2099,8 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
.set_pte = xen_set_pte_init,
.set_pmd = xen_set_pmd_hyper,
- .ptep_modify_prot_start = __ptep_modify_prot_start,
- .ptep_modify_prot_commit = __ptep_modify_prot_commit,
+ .ptep_modify_prot_start = xen_ptep_modify_prot_start,
+ .ptep_modify_prot_commit = xen_ptep_modify_prot_commit,
.pte_val = PV_CALLEE_SAVE(xen_pte_val),
.pgd_val = PV_CALLEE_SAVE(xen_pgd_val),
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index ac06ca32e9ef..5e6e236977c7 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -618,8 +618,8 @@ int xen_alloc_p2m_entry(unsigned long pfn)
}
/* Expanded the p2m? */
- if (pfn > xen_p2m_last_pfn) {
- xen_p2m_last_pfn = pfn;
+ if (pfn >= xen_p2m_last_pfn) {
+ xen_p2m_last_pfn = ALIGN(pfn + 1, P2M_PER_PAGE);
HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn;
}
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
index 96d7f7d39cb9..62ac4898df1a 100644
--- a/arch/x86/xen/platform-pci-unplug.c
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -7,6 +7,8 @@
* Copyright (c) 2010, Citrix
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h>
#include <linux/io.h>
#include <linux/export.h>
@@ -30,13 +32,13 @@ static int check_platform_magic(void)
magic = inw(XEN_IOPORT_MAGIC);
if (magic != XEN_IOPORT_MAGIC_VAL) {
- printk(KERN_ERR "Xen Platform PCI: unrecognised magic value\n");
+ pr_err("Xen Platform PCI: unrecognised magic value\n");
return XEN_PLATFORM_ERR_MAGIC;
}
protocol = inb(XEN_IOPORT_PROTOVER);
- printk(KERN_DEBUG "Xen Platform PCI: I/O protocol version %d\n",
+ pr_debug("Xen Platform PCI: I/O protocol version %d\n",
protocol);
switch (protocol) {
@@ -44,12 +46,12 @@ static int check_platform_magic(void)
outw(XEN_IOPORT_LINUX_PRODNUM, XEN_IOPORT_PRODNUM);
outl(XEN_IOPORT_LINUX_DRVVER, XEN_IOPORT_DRVVER);
if (inw(XEN_IOPORT_MAGIC) != XEN_IOPORT_MAGIC_VAL) {
- printk(KERN_ERR "Xen Platform: blacklisted by host\n");
+ pr_err("Xen Platform: blacklisted by host\n");
return XEN_PLATFORM_ERR_BLACKLIST;
}
break;
default:
- printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version\n");
+ pr_warn("Xen Platform PCI: unknown I/O protocol version\n");
return XEN_PLATFORM_ERR_PROTOCOL;
}
@@ -155,12 +157,12 @@ void xen_unplug_emulated_devices(void)
* been compiled for this kernel (modules or built-in are both OK). */
if (!xen_emul_unplug) {
if (xen_must_unplug_nics()) {
- printk(KERN_INFO "Netfront and the Xen platform PCI driver have "
+ pr_info("Netfront and the Xen platform PCI driver have "
"been compiled for this kernel: unplug emulated NICs.\n");
xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;
}
if (xen_must_unplug_disks()) {
- printk(KERN_INFO "Blkfront and the Xen platform PCI driver have "
+ pr_info("Blkfront and the Xen platform PCI driver have "
"been compiled for this kernel: unplug emulated disks.\n"
"You might have to change the root device\n"
"from /dev/hd[a-d] to /dev/xvd[a-d]\n"
@@ -200,7 +202,7 @@ static int __init parse_xen_emul_unplug(char *arg)
else if (!strncmp(p, "never", l))
xen_emul_unplug |= XEN_UNPLUG_NEVER;
else
- printk(KERN_WARNING "unrecognised option '%s' "
+ pr_warn("unrecognised option '%s' "
"in parameter 'xen_emul_unplug'\n", p);
}
return 0;
diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c
index c2ac319f11a4..96afadf9878e 100644
--- a/arch/x86/xen/smp_pv.c
+++ b/arch/x86/xen/smp_pv.c
@@ -64,7 +64,6 @@ static void cpu_bringup(void)
cr4_init();
cpu_init();
touch_softlockup_watchdog();
- preempt_disable();
/* PVH runs in ring 0 and allows us to do native syscalls. Yay! */
if (!xen_feature(XENFEAT_supervisor_mode_kernel)) {
diff --git a/arch/xtensa/Kbuild b/arch/xtensa/Kbuild
index a4e40e534e6a..fd12f61745ba 100644
--- a/arch/xtensa/Kbuild
+++ b/arch/xtensa/Kbuild
@@ -1 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-y += kernel/ mm/ platforms/ boot/dts/
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 3878880469d1..0e56bad058fa 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -7,6 +7,8 @@ config XTENSA
select ARCH_HAS_SYNC_DMA_FOR_CPU if MMU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE if MMU
select ARCH_HAS_DMA_SET_UNCACHED if MMU
+ select ARCH_HAS_STRNCPY_FROM_USER if !KASAN
+ select ARCH_HAS_STRNLEN_USER
select ARCH_USE_MEMTEST
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
@@ -20,7 +22,6 @@ config XTENSA
select GENERIC_IRQ_SHOW
select GENERIC_PCI_IOMAP
select GENERIC_SCHED_CLOCK
- select GENERIC_STRNCPY_FROM_USER if KASAN
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL
@@ -30,7 +31,7 @@ config XTENSA
select HAVE_DMA_CONTIGUOUS
select HAVE_EXIT_THREAD
select HAVE_FUNCTION_TRACER
- select HAVE_FUTEX_CMPXCHG if !MMU
+ select HAVE_FUTEX_CMPXCHG if !MMU && FUTEX
select HAVE_HW_BREAKPOINT if PERF_EVENTS
select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_PCI
@@ -41,6 +42,7 @@ config XTENSA
select MODULES_USE_ELF_RELA
select PERF_USE_VMALLOC
select SET_FS
+ select TRACE_IRQFLAGS_SUPPORT
select VIRT_TO_BUS
help
Xtensa processors are 32-bit RISC machines designed by Tensilica
@@ -72,9 +74,6 @@ config LOCKDEP_SUPPORT
config STACKTRACE_SUPPORT
def_bool y
-config TRACE_IRQFLAGS_SUPPORT
- def_bool y
-
config MMU
def_bool n
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index e9c8f064c44d..96714ef7c89e 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -17,7 +17,6 @@
variant-y := $(patsubst "%",%,$(CONFIG_XTENSA_VARIANT_NAME))
VARIANT = $(variant-y)
-export VARIANT
ifneq ($(VARIANT),)
ifdef cross_compiling
@@ -33,9 +32,6 @@ platform-$(CONFIG_XTENSA_PLATFORM_XT2000) := xt2000
platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss
platform-$(CONFIG_XTENSA_PLATFORM_XTFPGA) := xtfpga
-PLATFORM = $(platform-y)
-export PLATFORM
-
# temporarily until string.h is fixed
KBUILD_CFLAGS += -ffreestanding -D__linux__
KBUILD_CFLAGS += -pipe -mlongcalls -mtext-section-literals
@@ -57,19 +53,11 @@ KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(vardirs) $(plfdirs))
KBUILD_DEFCONFIG := iss_defconfig
-# Only build variant and/or platform if it includes a Makefile
-
-buildvar := $(shell test -e $(srctree)/arch/xtensa/variants/$(VARIANT)/Makefile && echo arch/xtensa/variants/$(VARIANT)/)
-buildplf := $(shell test -e $(srctree)/arch/xtensa/platforms/$(PLATFORM)/Makefile && echo arch/xtensa/platforms/$(PLATFORM)/)
-
# Find libgcc.a
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
head-y := arch/xtensa/kernel/head.o
-core-y += arch/xtensa/kernel/ arch/xtensa/mm/
-core-y += $(buildvar) $(buildplf)
-core-y += arch/xtensa/boot/dts/
libs-y += arch/xtensa/lib/ $(LIBGCC)
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h
index 5c9fb8005aa8..75bd8fbf52ba 100644
--- a/arch/xtensa/include/asm/uaccess.h
+++ b/arch/xtensa/include/asm/uaccess.h
@@ -290,8 +290,7 @@ clear_user(void __user *addr, unsigned long size)
#define __clear_user __xtensa_clear_user
-#ifndef CONFIG_GENERIC_STRNCPY_FROM_USER
-
+#ifdef CONFIG_ARCH_HAS_STRNCPY_FROM_USER
extern long __strncpy_user(char *dst, const char __user *src, long count);
static inline long
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
index 235d67d6ceb4..104b327f8ac9 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
@@ -223,7 +223,7 @@
# 205 was old nfsservctl
205 common nfsservctl sys_ni_syscall
206 common _sysctl sys_ni_syscall
-207 common bdflush sys_bdflush
+207 common bdflush sys_ni_syscall
208 common uname sys_newuname
209 common sysinfo sys_sysinfo
210 common init_module sys_init_module
@@ -417,3 +417,5 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self
+# 447 reserved for memfd_secret
+448 common process_mrelease sys_process_mrelease
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index efc3a29cde80..874b6efc6fb3 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -268,6 +268,7 @@ void do_interrupt(struct pt_regs *regs)
XCHAL_INTLEVEL7_MASK,
};
struct pt_regs *old_regs;
+ unsigned unhandled = ~0u;
trace_hardirqs_off();
@@ -283,6 +284,10 @@ void do_interrupt(struct pt_regs *regs)
for (level = LOCKLEVEL; level > 0; --level) {
if (int_at_level & int_level_mask[level]) {
int_at_level &= int_level_mask[level];
+ if (int_at_level & unhandled)
+ int_at_level &= unhandled;
+ else
+ unhandled |= int_level_mask[level];
break;
}
}
@@ -290,6 +295,8 @@ void do_interrupt(struct pt_regs *regs)
if (level == 0)
break;
+ /* clear lowest pending irq in the unhandled mask */
+ unhandled ^= (int_at_level & -int_at_level);
do_IRQ(__ffs(int_at_level), regs);
}
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 415fe7faa37f..d79edbb98d2a 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -43,7 +43,7 @@ EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(__memset);
EXPORT_SYMBOL(__memcpy);
EXPORT_SYMBOL(__memmove);
-#ifndef CONFIG_GENERIC_STRNCPY_FROM_USER
+#ifdef CONFIG_ARCH_HAS_STRNCPY_FROM_USER
EXPORT_SYMBOL(__strncpy_user);
#endif
EXPORT_SYMBOL(clear_page);
diff --git a/arch/xtensa/platforms/Makefile b/arch/xtensa/platforms/Makefile
new file mode 100644
index 000000000000..e2e7e0726979
--- /dev/null
+++ b/arch/xtensa/platforms/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_XTENSA_PLATFORM_XT2000) += xt2000/
+obj-$(CONFIG_XTENSA_PLATFORM_ISS) += iss/
+obj-$(CONFIG_XTENSA_PLATFORM_XTFPGA) += xtfpga/
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
index 21184488c277..81d7c7e8f7e9 100644
--- a/arch/xtensa/platforms/iss/console.c
+++ b/arch/xtensa/platforms/iss/console.c
@@ -136,28 +136,41 @@ static const struct tty_operations serial_ops = {
static int __init rs_init(void)
{
- tty_port_init(&serial_port);
+ struct tty_driver *driver;
+ int ret;
+
+ driver = tty_alloc_driver(SERIAL_MAX_NUM_LINES, TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
- serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES);
+ tty_port_init(&serial_port);
/* Initialize the tty_driver structure */
- serial_driver->driver_name = "iss_serial";
- serial_driver->name = "ttyS";
- serial_driver->major = TTY_MAJOR;
- serial_driver->minor_start = 64;
- serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver->subtype = SERIAL_TYPE_NORMAL;
- serial_driver->init_termios = tty_std_termios;
- serial_driver->init_termios.c_cflag =
+ driver->driver_name = "iss_serial";
+ driver->name = "ttyS";
+ driver->major = TTY_MAJOR;
+ driver->minor_start = 64;
+ driver->type = TTY_DRIVER_TYPE_SERIAL;
+ driver->subtype = SERIAL_TYPE_NORMAL;
+ driver->init_termios = tty_std_termios;
+ driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(serial_driver, &serial_ops);
- tty_port_link_device(&serial_port, serial_driver, 0);
+ tty_set_operations(driver, &serial_ops);
+ tty_port_link_device(&serial_port, driver, 0);
+
+ ret = tty_register_driver(driver);
+ if (ret) {
+ pr_err("Couldn't register serial driver\n");
+ tty_driver_kref_put(driver);
+ tty_port_destroy(&serial_port);
+
+ return ret;
+ }
+
+ serial_driver = driver;
- if (tty_register_driver(serial_driver))
- panic("Couldn't register serial driver\n");
return 0;
}
@@ -165,7 +178,7 @@ static int __init rs_init(void)
static __exit void rs_exit(void)
{
tty_unregister_driver(serial_driver);
- put_tty_driver(serial_driver);
+ tty_driver_kref_put(serial_driver);
tty_port_destroy(&serial_port);
}
@@ -186,10 +199,10 @@ late_initcall(rs_init);
static void iss_console_write(struct console *co, const char *s, unsigned count)
{
- int len = strlen(s);
-
- if (s != 0 && *s != 0)
+ if (s && *s != 0) {
+ int len = strlen(s);
simc_write(1, s, count < len ? count : len);
+ }
}
static struct tty_driver* iss_console_device(struct console *c, int *index)
diff --git a/block/Kconfig b/block/Kconfig
index bac87d773c54..8e28ae7718bd 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -29,35 +29,15 @@ if BLOCK
config BLK_RQ_ALLOC_TIME
bool
-config BLK_SCSI_REQUEST
- bool
-
config BLK_CGROUP_RWSTAT
bool
-config BLK_DEV_BSG
- bool "Block layer SG support v4"
- default y
- select BLK_SCSI_REQUEST
- help
- Saying Y here will enable generic SG (SCSI generic) v4 support
- for any block device.
-
- Unlike SG v3 (aka block/scsi_ioctl.c drivers/scsi/sg.c), SG v4
- can handle complicated SCSI commands: tagged variable length cdbs
- with bidirectional data transfers and generic request/response
- protocols (e.g. Task Management Functions and SMP in Serial
- Attached SCSI).
-
- This option is required by recent UDEV versions to properly
- access device serial numbers, etc.
-
- If unsure, say Y.
+config BLK_DEV_BSG_COMMON
+ tristate
config BLK_DEV_BSGLIB
bool "Block layer SG support v4 helper lib"
- select BLK_DEV_BSG
- select BLK_SCSI_REQUEST
+ select BLK_DEV_BSG_COMMON
help
Subsystems will normally enable this if needed. Users will not
normally need to manually enable this.
diff --git a/block/Makefile b/block/Makefile
index 1d0d466f2182..6cf40276d3cf 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -12,8 +12,7 @@ obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-sysfs.o \
disk-events.o
obj-$(CONFIG_BOUNCE) += bounce.o
-obj-$(CONFIG_BLK_SCSI_REQUEST) += scsi_ioctl.o
-obj-$(CONFIG_BLK_DEV_BSG) += bsg.o
+obj-$(CONFIG_BLK_DEV_BSG_COMMON) += bsg.o
obj-$(CONFIG_BLK_DEV_BSGLIB) += bsg-lib.o
obj-$(CONFIG_BLK_CGROUP) += blk-cgroup.o
obj-$(CONFIG_BLK_CGROUP_RWSTAT) += blk-cgroup-rwstat.o
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 480e1a134859..dd13c2bbc29c 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -2662,6 +2662,15 @@ bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
* are likely to increase the throughput.
*/
bfqq->new_bfqq = new_bfqq;
+ /*
+ * The above assignment schedules the following redirections:
+ * each time some I/O for bfqq arrives, the process that
+ * generated that I/O is disassociated from bfqq and
+ * associated with new_bfqq. Here we increases new_bfqq->ref
+ * in advance, adding the number of processes that are
+ * expected to be associated with new_bfqq as they happen to
+ * issue I/O.
+ */
new_bfqq->ref += process_refs;
return new_bfqq;
}
@@ -2724,6 +2733,10 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
{
struct bfq_queue *in_service_bfqq, *new_bfqq;
+ /* if a merge has already been setup, then proceed with that first */
+ if (bfqq->new_bfqq)
+ return bfqq->new_bfqq;
+
/*
* Check delayed stable merge for rotational or non-queueing
* devs. For this branch to be executed, bfqq must not be
@@ -2825,9 +2838,6 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
if (bfq_too_late_for_merging(bfqq))
return NULL;
- if (bfqq->new_bfqq)
- return bfqq->new_bfqq;
-
if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq))
return NULL;
diff --git a/block/bio.c b/block/bio.c
index e16849f46b0e..5df3dd282e40 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1688,7 +1688,7 @@ EXPORT_SYMBOL(bioset_init_from_src);
/**
* bio_alloc_kiocb - Allocate a bio from bio_set based on kiocb
* @kiocb: kiocb describing the IO
- * @nr_iovecs: number of iovecs to pre-allocate
+ * @nr_vecs: number of iovecs to pre-allocate
* @bs: bio_set to allocate from
*
* Description:
diff --git a/block/blk-map.c b/block/blk-map.c
index d1448aaad980..4526adde0156 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -309,7 +309,7 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
static void bio_invalidate_vmalloc_pages(struct bio *bio)
{
-#ifdef ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+#ifdef ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE
if (bio->bi_private && !op_is_write(bio_op(bio))) {
unsigned long i, len = 0;
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 944049982e6e..65d3a63aecc6 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -3280,8 +3280,6 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
set->map[HCTX_TYPE_POLL].nr_queues)
blk_queue_flag_set(QUEUE_FLAG_POLL, q);
- q->sg_reserved_size = INT_MAX;
-
INIT_DELAYED_WORK(&q->requeue_work, blk_mq_requeue_work);
INIT_LIST_HEAD(&q->requeue_list);
spin_lock_init(&q->requeue_lock);
diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index a89d80102304..ccb98276c964 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -6,6 +6,7 @@
* Copyright (C) 2011 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011 Mike Christie
*/
+#include <linux/bsg.h>
#include <linux/slab.h>
#include <linux/blk-mq.h>
#include <linux/delay.h>
@@ -19,36 +20,44 @@
struct bsg_set {
struct blk_mq_tag_set tag_set;
+ struct bsg_device *bd;
bsg_job_fn *job_fn;
bsg_timeout_fn *timeout_fn;
};
-static int bsg_transport_check_proto(struct sg_io_v4 *hdr)
+static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
+ fmode_t mode, unsigned int timeout)
{
+ struct bsg_job *job;
+ struct request *rq;
+ struct bio *bio;
+ int ret;
+
if (hdr->protocol != BSG_PROTOCOL_SCSI ||
hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_TRANSPORT)
return -EINVAL;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- return 0;
-}
-static int bsg_transport_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
- fmode_t mode)
-{
- struct bsg_job *job = blk_mq_rq_to_pdu(rq);
- int ret;
+ rq = blk_get_request(q, hdr->dout_xfer_len ?
+ REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
+ if (IS_ERR(rq))
+ return PTR_ERR(rq);
+ rq->timeout = timeout;
+ job = blk_mq_rq_to_pdu(rq);
job->request_len = hdr->request_len;
job->request = memdup_user(uptr64(hdr->request), hdr->request_len);
- if (IS_ERR(job->request))
- return PTR_ERR(job->request);
+ if (IS_ERR(job->request)) {
+ ret = PTR_ERR(job->request);
+ goto out_put_request;
+ }
if (hdr->dout_xfer_len && hdr->din_xfer_len) {
job->bidi_rq = blk_get_request(rq->q, REQ_OP_DRV_IN, 0);
if (IS_ERR(job->bidi_rq)) {
ret = PTR_ERR(job->bidi_rq);
- goto out;
+ goto out_free_job_request;
}
ret = blk_rq_map_user(rq->q, job->bidi_rq, NULL,
@@ -63,20 +72,20 @@ static int bsg_transport_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
job->bidi_bio = NULL;
}
- return 0;
+ ret = 0;
+ if (hdr->dout_xfer_len) {
+ ret = blk_rq_map_user(rq->q, rq, NULL, uptr64(hdr->dout_xferp),
+ hdr->dout_xfer_len, GFP_KERNEL);
+ } else if (hdr->din_xfer_len) {
+ ret = blk_rq_map_user(rq->q, rq, NULL, uptr64(hdr->din_xferp),
+ hdr->din_xfer_len, GFP_KERNEL);
+ }
-out_free_bidi_rq:
- if (job->bidi_rq)
- blk_put_request(job->bidi_rq);
-out:
- kfree(job->request);
- return ret;
-}
+ if (ret)
+ goto out_unmap_bidi_rq;
-static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
-{
- struct bsg_job *job = blk_mq_rq_to_pdu(rq);
- int ret = 0;
+ bio = rq->bio;
+ blk_execute_rq(NULL, rq, !(hdr->flags & BSG_FLAG_Q_AT_TAIL));
/*
* The assignments below don't make much sense, but are kept for
@@ -119,28 +128,20 @@ static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
hdr->din_resid = 0;
}
- return ret;
-}
-
-static void bsg_transport_free_rq(struct request *rq)
-{
- struct bsg_job *job = blk_mq_rq_to_pdu(rq);
-
- if (job->bidi_rq) {
+ blk_rq_unmap_user(bio);
+out_unmap_bidi_rq:
+ if (job->bidi_rq)
blk_rq_unmap_user(job->bidi_bio);
+out_free_bidi_rq:
+ if (job->bidi_rq)
blk_put_request(job->bidi_rq);
- }
-
+out_free_job_request:
kfree(job->request);
+out_put_request:
+ blk_put_request(rq);
+ return ret;
}
-static const struct bsg_ops bsg_transport_ops = {
- .check_proto = bsg_transport_check_proto,
- .fill_hdr = bsg_transport_fill_hdr,
- .complete_rq = bsg_transport_complete_rq,
- .free_rq = bsg_transport_free_rq,
-};
-
/**
* bsg_teardown_job - routine to teardown a bsg job
* @kref: kref inside bsg_job that is to be torn down
@@ -327,7 +328,7 @@ void bsg_remove_queue(struct request_queue *q)
struct bsg_set *bset =
container_of(q->tag_set, struct bsg_set, tag_set);
- bsg_unregister_queue(q);
+ bsg_unregister_queue(bset->bd);
blk_cleanup_queue(q);
blk_mq_free_tag_set(&bset->tag_set);
kfree(bset);
@@ -396,10 +397,9 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
q->queuedata = dev;
blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
- ret = bsg_register_queue(q, dev, name, &bsg_transport_ops);
- if (ret) {
- printk(KERN_ERR "%s: bsg interface failed to "
- "initialize - register queue\n", dev->kobj.name);
+ bset->bd = bsg_register_queue(q, dev, name, bsg_transport_sg_io_fn);
+ if (IS_ERR(bset->bd)) {
+ ret = PTR_ERR(bset->bd);
goto out_cleanup_queue;
}
diff --git a/block/bsg.c b/block/bsg.c
index 1f196563ae6c..351095193788 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -15,343 +15,97 @@
#include <scsi/scsi.h>
#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_driver.h>
#include <scsi/sg.h>
#define BSG_DESCRIPTION "Block layer SCSI generic (bsg) driver"
#define BSG_VERSION "0.4"
-#define bsg_dbg(bd, fmt, ...) \
- pr_debug("%s: " fmt, (bd)->name, ##__VA_ARGS__)
-
struct bsg_device {
struct request_queue *queue;
- spinlock_t lock;
- struct hlist_node dev_list;
- refcount_t ref_count;
- char name[20];
+ struct device device;
+ struct cdev cdev;
int max_queue;
+ unsigned int timeout;
+ unsigned int reserved_size;
+ bsg_sg_io_fn *sg_io_fn;
};
+static inline struct bsg_device *to_bsg_device(struct inode *inode)
+{
+ return container_of(inode->i_cdev, struct bsg_device, cdev);
+}
+
#define BSG_DEFAULT_CMDS 64
#define BSG_MAX_DEVS 32768
-static DEFINE_MUTEX(bsg_mutex);
-static DEFINE_IDR(bsg_minor_idr);
-
-#define BSG_LIST_ARRAY_SIZE 8
-static struct hlist_head bsg_device_list[BSG_LIST_ARRAY_SIZE];
-
+static DEFINE_IDA(bsg_minor_ida);
static struct class *bsg_class;
static int bsg_major;
-static inline struct hlist_head *bsg_dev_idx_hash(int index)
-{
- return &bsg_device_list[index & (BSG_LIST_ARRAY_SIZE - 1)];
-}
-
-#define uptr64(val) ((void __user *)(uintptr_t)(val))
-
-static int bsg_scsi_check_proto(struct sg_io_v4 *hdr)
-{
- if (hdr->protocol != BSG_PROTOCOL_SCSI ||
- hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_CMD)
- return -EINVAL;
- return 0;
-}
-
-static int bsg_scsi_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
- fmode_t mode)
-{
- struct scsi_request *sreq = scsi_req(rq);
-
- if (hdr->dout_xfer_len && hdr->din_xfer_len) {
- pr_warn_once("BIDI support in bsg has been removed.\n");
- return -EOPNOTSUPP;
- }
-
- sreq->cmd_len = hdr->request_len;
- if (sreq->cmd_len > BLK_MAX_CDB) {
- sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL);
- if (!sreq->cmd)
- return -ENOMEM;
- }
-
- if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len))
- return -EFAULT;
- if (blk_verify_command(sreq->cmd, mode))
- return -EPERM;
- return 0;
-}
-
-static int bsg_scsi_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
+static unsigned int bsg_timeout(struct bsg_device *bd, struct sg_io_v4 *hdr)
{
- struct scsi_request *sreq = scsi_req(rq);
- int ret = 0;
-
- /*
- * fill in all the output members
- */
- hdr->device_status = sreq->result & 0xff;
- hdr->transport_status = host_byte(sreq->result);
- hdr->driver_status = 0;
- if (scsi_status_is_check_condition(sreq->result))
- hdr->driver_status = DRIVER_SENSE;
- hdr->info = 0;
- if (hdr->device_status || hdr->transport_status || hdr->driver_status)
- hdr->info |= SG_INFO_CHECK;
- hdr->response_len = 0;
-
- if (sreq->sense_len && hdr->response) {
- int len = min_t(unsigned int, hdr->max_response_len,
- sreq->sense_len);
-
- if (copy_to_user(uptr64(hdr->response), sreq->sense, len))
- ret = -EFAULT;
- else
- hdr->response_len = len;
- }
+ unsigned int timeout = BLK_DEFAULT_SG_TIMEOUT;
- if (rq_data_dir(rq) == READ)
- hdr->din_resid = sreq->resid_len;
- else
- hdr->dout_resid = sreq->resid_len;
+ if (hdr->timeout)
+ timeout = msecs_to_jiffies(hdr->timeout);
+ else if (bd->timeout)
+ timeout = bd->timeout;
- return ret;
+ return max_t(unsigned int, timeout, BLK_MIN_SG_TIMEOUT);
}
-static void bsg_scsi_free_rq(struct request *rq)
+static int bsg_sg_io(struct bsg_device *bd, fmode_t mode, void __user *uarg)
{
- scsi_req_free_cmd(scsi_req(rq));
-}
-
-static const struct bsg_ops bsg_scsi_ops = {
- .check_proto = bsg_scsi_check_proto,
- .fill_hdr = bsg_scsi_fill_hdr,
- .complete_rq = bsg_scsi_complete_rq,
- .free_rq = bsg_scsi_free_rq,
-};
-
-static int bsg_sg_io(struct request_queue *q, fmode_t mode, void __user *uarg)
-{
- struct request *rq;
- struct bio *bio;
struct sg_io_v4 hdr;
int ret;
if (copy_from_user(&hdr, uarg, sizeof(hdr)))
return -EFAULT;
-
- if (!q->bsg_dev.class_dev)
- return -ENXIO;
-
if (hdr.guard != 'Q')
return -EINVAL;
- ret = q->bsg_dev.ops->check_proto(&hdr);
- if (ret)
- return ret;
-
- rq = blk_get_request(q, hdr.dout_xfer_len ?
- REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
-
- ret = q->bsg_dev.ops->fill_hdr(rq, &hdr, mode);
- if (ret) {
- blk_put_request(rq);
- return ret;
- }
-
- rq->timeout = msecs_to_jiffies(hdr.timeout);
- if (!rq->timeout)
- rq->timeout = q->sg_timeout;
- if (!rq->timeout)
- rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
- if (rq->timeout < BLK_MIN_SG_TIMEOUT)
- rq->timeout = BLK_MIN_SG_TIMEOUT;
-
- if (hdr.dout_xfer_len) {
- ret = blk_rq_map_user(q, rq, NULL, uptr64(hdr.dout_xferp),
- hdr.dout_xfer_len, GFP_KERNEL);
- } else if (hdr.din_xfer_len) {
- ret = blk_rq_map_user(q, rq, NULL, uptr64(hdr.din_xferp),
- hdr.din_xfer_len, GFP_KERNEL);
- }
-
- if (ret)
- goto out_free_rq;
-
- bio = rq->bio;
-
- blk_execute_rq(NULL, rq, !(hdr.flags & BSG_FLAG_Q_AT_TAIL));
- ret = rq->q->bsg_dev.ops->complete_rq(rq, &hdr);
- blk_rq_unmap_user(bio);
-
-out_free_rq:
- rq->q->bsg_dev.ops->free_rq(rq);
- blk_put_request(rq);
+ ret = bd->sg_io_fn(bd->queue, &hdr, mode, bsg_timeout(bd, &hdr));
if (!ret && copy_to_user(uarg, &hdr, sizeof(hdr)))
return -EFAULT;
return ret;
}
-static struct bsg_device *bsg_alloc_device(void)
-{
- struct bsg_device *bd;
-
- bd = kzalloc(sizeof(struct bsg_device), GFP_KERNEL);
- if (unlikely(!bd))
- return NULL;
-
- spin_lock_init(&bd->lock);
- bd->max_queue = BSG_DEFAULT_CMDS;
- INIT_HLIST_NODE(&bd->dev_list);
- return bd;
-}
-
-static int bsg_put_device(struct bsg_device *bd)
-{
- struct request_queue *q = bd->queue;
-
- mutex_lock(&bsg_mutex);
-
- if (!refcount_dec_and_test(&bd->ref_count)) {
- mutex_unlock(&bsg_mutex);
- return 0;
- }
-
- hlist_del(&bd->dev_list);
- mutex_unlock(&bsg_mutex);
-
- bsg_dbg(bd, "tearing down\n");
-
- /*
- * close can always block
- */
- kfree(bd);
- blk_put_queue(q);
- return 0;
-}
-
-static struct bsg_device *bsg_add_device(struct inode *inode,
- struct request_queue *rq,
- struct file *file)
-{
- struct bsg_device *bd;
- unsigned char buf[32];
-
- lockdep_assert_held(&bsg_mutex);
-
- if (!blk_get_queue(rq))
- return ERR_PTR(-ENXIO);
-
- bd = bsg_alloc_device();
- if (!bd) {
- blk_put_queue(rq);
- return ERR_PTR(-ENOMEM);
- }
-
- bd->queue = rq;
-
- refcount_set(&bd->ref_count, 1);
- 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);
-
- return bd;
-}
-
-static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
-{
- struct bsg_device *bd;
-
- lockdep_assert_held(&bsg_mutex);
-
- hlist_for_each_entry(bd, bsg_dev_idx_hash(minor), dev_list) {
- if (bd->queue == q) {
- refcount_inc(&bd->ref_count);
- goto found;
- }
- }
- bd = NULL;
-found:
- return bd;
-}
-
-static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
-{
- struct bsg_device *bd;
- struct bsg_class_device *bcd;
-
- /*
- * find the class device
- */
- mutex_lock(&bsg_mutex);
- bcd = idr_find(&bsg_minor_idr, iminor(inode));
-
- if (!bcd) {
- bd = ERR_PTR(-ENODEV);
- goto out_unlock;
- }
-
- bd = __bsg_get_device(iminor(inode), bcd->queue);
- if (!bd)
- bd = bsg_add_device(inode, bcd->queue, file);
-
-out_unlock:
- mutex_unlock(&bsg_mutex);
- return bd;
-}
-
static int bsg_open(struct inode *inode, struct file *file)
{
- struct bsg_device *bd;
-
- bd = bsg_get_device(inode, file);
-
- if (IS_ERR(bd))
- return PTR_ERR(bd);
-
- file->private_data = bd;
+ if (!blk_get_queue(to_bsg_device(inode)->queue))
+ return -ENXIO;
return 0;
}
static int bsg_release(struct inode *inode, struct file *file)
{
- struct bsg_device *bd = file->private_data;
-
- file->private_data = NULL;
- return bsg_put_device(bd);
+ blk_put_queue(to_bsg_device(inode)->queue);
+ return 0;
}
static int bsg_get_command_q(struct bsg_device *bd, int __user *uarg)
{
- return put_user(bd->max_queue, uarg);
+ return put_user(READ_ONCE(bd->max_queue), uarg);
}
static int bsg_set_command_q(struct bsg_device *bd, int __user *uarg)
{
- int queue;
+ int max_queue;
- if (get_user(queue, uarg))
+ if (get_user(max_queue, uarg))
return -EFAULT;
- if (queue < 1)
+ if (max_queue < 1)
return -EINVAL;
-
- spin_lock_irq(&bd->lock);
- bd->max_queue = queue;
- spin_unlock_irq(&bd->lock);
+ WRITE_ONCE(bd->max_queue, max_queue);
return 0;
}
static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct bsg_device *bd = file->private_data;
+ struct bsg_device *bd = to_bsg_device(file_inode(file));
+ struct request_queue *q = bd->queue;
void __user *uarg = (void __user *) arg;
+ int __user *intp = uarg;
+ int val;
switch (cmd) {
/*
@@ -366,17 +120,37 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
* SCSI/sg ioctls
*/
case SG_GET_VERSION_NUM:
+ return put_user(30527, intp);
case SCSI_IOCTL_GET_IDLUN:
+ return put_user(0, intp);
case SCSI_IOCTL_GET_BUS_NUMBER:
+ return put_user(0, intp);
case SG_SET_TIMEOUT:
+ if (get_user(val, intp))
+ return -EFAULT;
+ bd->timeout = clock_t_to_jiffies(val);
+ return 0;
case SG_GET_TIMEOUT:
+ return jiffies_to_clock_t(bd->timeout);
case SG_GET_RESERVED_SIZE:
+ return put_user(min(bd->reserved_size, queue_max_bytes(q)),
+ intp);
case SG_SET_RESERVED_SIZE:
+ if (get_user(val, intp))
+ return -EFAULT;
+ if (val < 0)
+ return -EINVAL;
+ bd->reserved_size =
+ min_t(unsigned int, val, queue_max_bytes(q));
+ return 0;
case SG_EMULATED_HOST:
- case SCSI_IOCTL_SEND_COMMAND:
- return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg);
+ return put_user(1, intp);
case SG_IO:
- return bsg_sg_io(bd->queue, file->f_mode, uarg);
+ return bsg_sg_io(bd, file->f_mode, uarg);
+ case SCSI_IOCTL_SEND_COMMAND:
+ pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND\n",
+ current->comm);
+ return -EINVAL;
default:
return -ENOTTY;
}
@@ -391,92 +165,65 @@ static const struct file_operations bsg_fops = {
.llseek = default_llseek,
};
-void bsg_unregister_queue(struct request_queue *q)
+void bsg_unregister_queue(struct bsg_device *bd)
{
- struct bsg_class_device *bcd = &q->bsg_dev;
-
- if (!bcd->class_dev)
- return;
-
- mutex_lock(&bsg_mutex);
- idr_remove(&bsg_minor_idr, bcd->minor);
- if (q->kobj.sd)
- sysfs_remove_link(&q->kobj, "bsg");
- device_unregister(bcd->class_dev);
- bcd->class_dev = NULL;
- mutex_unlock(&bsg_mutex);
+ if (bd->queue->kobj.sd)
+ sysfs_remove_link(&bd->queue->kobj, "bsg");
+ cdev_device_del(&bd->cdev, &bd->device);
+ ida_simple_remove(&bsg_minor_ida, MINOR(bd->device.devt));
+ kfree(bd);
}
EXPORT_SYMBOL_GPL(bsg_unregister_queue);
-int bsg_register_queue(struct request_queue *q, struct device *parent,
- const char *name, const struct bsg_ops *ops)
+struct bsg_device *bsg_register_queue(struct request_queue *q,
+ struct device *parent, const char *name, bsg_sg_io_fn *sg_io_fn)
{
- struct bsg_class_device *bcd;
- dev_t dev;
+ struct bsg_device *bd;
int ret;
- struct device *class_dev = NULL;
- /*
- * we need a proper transport to send commands, not a stacked device
- */
- if (!queue_is_mq(q))
- return 0;
-
- bcd = &q->bsg_dev;
- memset(bcd, 0, sizeof(*bcd));
-
- mutex_lock(&bsg_mutex);
+ bd = kzalloc(sizeof(*bd), GFP_KERNEL);
+ if (!bd)
+ return ERR_PTR(-ENOMEM);
+ bd->max_queue = BSG_DEFAULT_CMDS;
+ bd->reserved_size = INT_MAX;
+ bd->queue = q;
+ bd->sg_io_fn = sg_io_fn;
- ret = idr_alloc(&bsg_minor_idr, bcd, 0, BSG_MAX_DEVS, GFP_KERNEL);
+ ret = ida_simple_get(&bsg_minor_ida, 0, BSG_MAX_DEVS, GFP_KERNEL);
if (ret < 0) {
- if (ret == -ENOSPC) {
- printk(KERN_ERR "bsg: too many bsg devices\n");
- ret = -EINVAL;
- }
- goto unlock;
- }
-
- bcd->minor = ret;
- bcd->queue = q;
- bcd->ops = ops;
- dev = MKDEV(bsg_major, bcd->minor);
- class_dev = device_create(bsg_class, parent, dev, NULL, "%s", name);
- if (IS_ERR(class_dev)) {
- ret = PTR_ERR(class_dev);
- goto idr_remove;
+ if (ret == -ENOSPC)
+ dev_err(parent, "bsg: too many bsg devices\n");
+ goto out_kfree;
}
- bcd->class_dev = class_dev;
+ bd->device.devt = MKDEV(bsg_major, ret);
+ bd->device.class = bsg_class;
+ bd->device.parent = parent;
+ dev_set_name(&bd->device, "%s", name);
+ device_initialize(&bd->device);
+
+ cdev_init(&bd->cdev, &bsg_fops);
+ bd->cdev.owner = THIS_MODULE;
+ ret = cdev_device_add(&bd->cdev, &bd->device);
+ if (ret)
+ goto out_ida_remove;
if (q->kobj.sd) {
- ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg");
+ ret = sysfs_create_link(&q->kobj, &bd->device.kobj, "bsg");
if (ret)
- goto unregister_class_dev;
+ goto out_device_del;
}
- mutex_unlock(&bsg_mutex);
- return 0;
-
-unregister_class_dev:
- device_unregister(class_dev);
-idr_remove:
- idr_remove(&bsg_minor_idr, bcd->minor);
-unlock:
- mutex_unlock(&bsg_mutex);
- return ret;
-}
-
-int bsg_scsi_register_queue(struct request_queue *q, struct device *parent)
-{
- if (!blk_queue_scsi_passthrough(q)) {
- WARN_ONCE(true, "Attempt to register a non-SCSI queue\n");
- return -EINVAL;
- }
+ return bd;
- return bsg_register_queue(q, parent, dev_name(parent), &bsg_scsi_ops);
+out_device_del:
+ cdev_device_del(&bd->cdev, &bd->device);
+out_ida_remove:
+ ida_simple_remove(&bsg_minor_ida, MINOR(bd->device.devt));
+out_kfree:
+ kfree(bd);
+ return ERR_PTR(ret);
}
-EXPORT_SYMBOL_GPL(bsg_scsi_register_queue);
-
-static struct cdev bsg_cdev;
+EXPORT_SYMBOL_GPL(bsg_register_queue);
static char *bsg_devnode(struct device *dev, umode_t *mode)
{
@@ -485,11 +232,8 @@ static char *bsg_devnode(struct device *dev, umode_t *mode)
static int __init bsg_init(void)
{
- int ret, i;
dev_t devid;
-
- for (i = 0; i < BSG_LIST_ARRAY_SIZE; i++)
- INIT_HLIST_HEAD(&bsg_device_list[i]);
+ int ret;
bsg_class = class_create(THIS_MODULE, "bsg");
if (IS_ERR(bsg_class))
@@ -499,19 +243,12 @@ static int __init bsg_init(void)
ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
if (ret)
goto destroy_bsg_class;
-
bsg_major = MAJOR(devid);
- cdev_init(&bsg_cdev, &bsg_fops);
- ret = cdev_add(&bsg_cdev, MKDEV(bsg_major, 0), BSG_MAX_DEVS);
- if (ret)
- goto unregister_chrdev;
-
printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
" loaded (major %d)\n", bsg_major);
return 0;
-unregister_chrdev:
- unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS);
+
destroy_bsg_class:
class_destroy(bsg_class);
return ret;
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index 3c3693c34f06..7f3c3932b723 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -270,12 +270,6 @@ deadline_move_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
deadline_remove_request(rq->q, per_prio, rq);
}
-/* Number of requests queued for a given priority level. */
-static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio)
-{
- return dd_sum(dd, inserted, prio) - dd_sum(dd, completed, prio);
-}
-
/*
* deadline_check_fifo returns 0 if there are no expired requests on the fifo,
* 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
@@ -953,6 +947,12 @@ static int dd_async_depth_show(void *data, struct seq_file *m)
return 0;
}
+/* Number of requests queued for a given priority level. */
+static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio)
+{
+ return dd_sum(dd, inserted, prio) - dd_sum(dd, completed, prio);
+}
+
static int dd_queued_show(void *data, struct seq_file *m)
{
struct request_queue *q = data;
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
deleted file mode 100644
index d247431a6853..000000000000
--- a/block/scsi_ioctl.c
+++ /dev/null
@@ -1,890 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
- */
-#include <linux/compat.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/blkdev.h>
-#include <linux/capability.h>
-#include <linux/completion.h>
-#include <linux/cdrom.h>
-#include <linux/ratelimit.h>
-#include <linux/slab.h>
-#include <linux/times.h>
-#include <linux/uio.h>
-#include <linux/uaccess.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/sg.h>
-
-struct blk_cmd_filter {
- unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
- unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
-};
-
-static struct blk_cmd_filter blk_default_cmd_filter;
-
-/* Command group 3 is reserved and should never be used. */
-const unsigned char scsi_command_size_tbl[8] =
-{
- 6, 10, 10, 12,
- 16, 12, 10, 10
-};
-EXPORT_SYMBOL(scsi_command_size_tbl);
-
-static int sg_get_version(int __user *p)
-{
- static const int sg_version_num = 30527;
- return put_user(sg_version_num, p);
-}
-
-static int scsi_get_idlun(struct request_queue *q, int __user *p)
-{
- return put_user(0, p);
-}
-
-static int scsi_get_bus(struct request_queue *q, int __user *p)
-{
- return put_user(0, p);
-}
-
-static int sg_get_timeout(struct request_queue *q)
-{
- return jiffies_to_clock_t(q->sg_timeout);
-}
-
-static int sg_set_timeout(struct request_queue *q, int __user *p)
-{
- int timeout, err = get_user(timeout, p);
-
- if (!err)
- q->sg_timeout = clock_t_to_jiffies(timeout);
-
- return err;
-}
-
-static int max_sectors_bytes(struct request_queue *q)
-{
- unsigned int max_sectors = queue_max_sectors(q);
-
- max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9);
-
- return max_sectors << 9;
-}
-
-static int sg_get_reserved_size(struct request_queue *q, int __user *p)
-{
- int val = min_t(int, q->sg_reserved_size, max_sectors_bytes(q));
-
- return put_user(val, p);
-}
-
-static int sg_set_reserved_size(struct request_queue *q, int __user *p)
-{
- int size, err = get_user(size, p);
-
- if (err)
- return err;
-
- if (size < 0)
- return -EINVAL;
-
- q->sg_reserved_size = min(size, max_sectors_bytes(q));
- return 0;
-}
-
-/*
- * will always return that we are ATAPI even for a real SCSI drive, I'm not
- * so sure this is worth doing anything about (why would you care??)
- */
-static int sg_emulated_host(struct request_queue *q, int __user *p)
-{
- return put_user(1, p);
-}
-
-static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
-{
- /* Basic read-only commands */
- __set_bit(TEST_UNIT_READY, filter->read_ok);
- __set_bit(REQUEST_SENSE, filter->read_ok);
- __set_bit(READ_6, filter->read_ok);
- __set_bit(READ_10, filter->read_ok);
- __set_bit(READ_12, filter->read_ok);
- __set_bit(READ_16, filter->read_ok);
- __set_bit(READ_BUFFER, filter->read_ok);
- __set_bit(READ_DEFECT_DATA, filter->read_ok);
- __set_bit(READ_CAPACITY, filter->read_ok);
- __set_bit(READ_LONG, filter->read_ok);
- __set_bit(INQUIRY, filter->read_ok);
- __set_bit(MODE_SENSE, filter->read_ok);
- __set_bit(MODE_SENSE_10, filter->read_ok);
- __set_bit(LOG_SENSE, filter->read_ok);
- __set_bit(START_STOP, filter->read_ok);
- __set_bit(GPCMD_VERIFY_10, filter->read_ok);
- __set_bit(VERIFY_16, filter->read_ok);
- __set_bit(REPORT_LUNS, filter->read_ok);
- __set_bit(SERVICE_ACTION_IN_16, filter->read_ok);
- __set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok);
- __set_bit(MAINTENANCE_IN, filter->read_ok);
- __set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok);
-
- /* Audio CD commands */
- __set_bit(GPCMD_PLAY_CD, filter->read_ok);
- __set_bit(GPCMD_PLAY_AUDIO_10, filter->read_ok);
- __set_bit(GPCMD_PLAY_AUDIO_MSF, filter->read_ok);
- __set_bit(GPCMD_PLAY_AUDIO_TI, filter->read_ok);
- __set_bit(GPCMD_PAUSE_RESUME, filter->read_ok);
-
- /* CD/DVD data reading */
- __set_bit(GPCMD_READ_CD, filter->read_ok);
- __set_bit(GPCMD_READ_CD_MSF, filter->read_ok);
- __set_bit(GPCMD_READ_DISC_INFO, filter->read_ok);
- __set_bit(GPCMD_READ_CDVD_CAPACITY, filter->read_ok);
- __set_bit(GPCMD_READ_DVD_STRUCTURE, filter->read_ok);
- __set_bit(GPCMD_READ_HEADER, filter->read_ok);
- __set_bit(GPCMD_READ_TRACK_RZONE_INFO, filter->read_ok);
- __set_bit(GPCMD_READ_SUBCHANNEL, filter->read_ok);
- __set_bit(GPCMD_READ_TOC_PMA_ATIP, filter->read_ok);
- __set_bit(GPCMD_REPORT_KEY, filter->read_ok);
- __set_bit(GPCMD_SCAN, filter->read_ok);
- __set_bit(GPCMD_GET_CONFIGURATION, filter->read_ok);
- __set_bit(GPCMD_READ_FORMAT_CAPACITIES, filter->read_ok);
- __set_bit(GPCMD_GET_EVENT_STATUS_NOTIFICATION, filter->read_ok);
- __set_bit(GPCMD_GET_PERFORMANCE, filter->read_ok);
- __set_bit(GPCMD_SEEK, filter->read_ok);
- __set_bit(GPCMD_STOP_PLAY_SCAN, filter->read_ok);
-
- /* Basic writing commands */
- __set_bit(WRITE_6, filter->write_ok);
- __set_bit(WRITE_10, filter->write_ok);
- __set_bit(WRITE_VERIFY, filter->write_ok);
- __set_bit(WRITE_12, filter->write_ok);
- __set_bit(WRITE_VERIFY_12, filter->write_ok);
- __set_bit(WRITE_16, filter->write_ok);
- __set_bit(WRITE_LONG, filter->write_ok);
- __set_bit(WRITE_LONG_2, filter->write_ok);
- __set_bit(WRITE_SAME, filter->write_ok);
- __set_bit(WRITE_SAME_16, filter->write_ok);
- __set_bit(WRITE_SAME_32, filter->write_ok);
- __set_bit(ERASE, filter->write_ok);
- __set_bit(GPCMD_MODE_SELECT_10, filter->write_ok);
- __set_bit(MODE_SELECT, filter->write_ok);
- __set_bit(LOG_SELECT, filter->write_ok);
- __set_bit(GPCMD_BLANK, filter->write_ok);
- __set_bit(GPCMD_CLOSE_TRACK, filter->write_ok);
- __set_bit(GPCMD_FLUSH_CACHE, filter->write_ok);
- __set_bit(GPCMD_FORMAT_UNIT, filter->write_ok);
- __set_bit(GPCMD_REPAIR_RZONE_TRACK, filter->write_ok);
- __set_bit(GPCMD_RESERVE_RZONE_TRACK, filter->write_ok);
- __set_bit(GPCMD_SEND_DVD_STRUCTURE, filter->write_ok);
- __set_bit(GPCMD_SEND_EVENT, filter->write_ok);
- __set_bit(GPCMD_SEND_KEY, filter->write_ok);
- __set_bit(GPCMD_SEND_OPC, filter->write_ok);
- __set_bit(GPCMD_SEND_CUE_SHEET, filter->write_ok);
- __set_bit(GPCMD_SET_SPEED, filter->write_ok);
- __set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok);
- __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok);
- __set_bit(GPCMD_SET_STREAMING, filter->write_ok);
- __set_bit(GPCMD_SET_READ_AHEAD, filter->write_ok);
-
- /* ZBC Commands */
- __set_bit(ZBC_OUT, filter->write_ok);
- __set_bit(ZBC_IN, filter->read_ok);
-}
-
-int blk_verify_command(unsigned char *cmd, fmode_t mode)
-{
- struct blk_cmd_filter *filter = &blk_default_cmd_filter;
-
- /* root can do any command. */
- if (capable(CAP_SYS_RAWIO))
- return 0;
-
- /* Anybody who can open the device can do a read-safe command */
- if (test_bit(cmd[0], filter->read_ok))
- return 0;
-
- /* Write-safe commands require a writable open */
- if (test_bit(cmd[0], filter->write_ok) && (mode & FMODE_WRITE))
- return 0;
-
- return -EPERM;
-}
-EXPORT_SYMBOL(blk_verify_command);
-
-static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
- struct sg_io_hdr *hdr, fmode_t mode)
-{
- struct scsi_request *req = scsi_req(rq);
-
- if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len))
- return -EFAULT;
- if (blk_verify_command(req->cmd, mode))
- return -EPERM;
-
- /*
- * fill in request structure
- */
- req->cmd_len = hdr->cmd_len;
-
- rq->timeout = msecs_to_jiffies(hdr->timeout);
- if (!rq->timeout)
- rq->timeout = q->sg_timeout;
- if (!rq->timeout)
- rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
- if (rq->timeout < BLK_MIN_SG_TIMEOUT)
- rq->timeout = BLK_MIN_SG_TIMEOUT;
-
- return 0;
-}
-
-static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
- struct bio *bio)
-{
- struct scsi_request *req = scsi_req(rq);
- int r, ret = 0;
-
- /*
- * fill in all the output members
- */
- hdr->status = req->result & 0xff;
- hdr->masked_status = status_byte(req->result);
- hdr->msg_status = COMMAND_COMPLETE;
- hdr->host_status = host_byte(req->result);
- hdr->driver_status = 0;
- if (scsi_status_is_check_condition(hdr->status))
- hdr->driver_status = DRIVER_SENSE;
- hdr->info = 0;
- if (hdr->masked_status || hdr->host_status || hdr->driver_status)
- hdr->info |= SG_INFO_CHECK;
- hdr->resid = req->resid_len;
- hdr->sb_len_wr = 0;
-
- if (req->sense_len && hdr->sbp) {
- int len = min((unsigned int) hdr->mx_sb_len, req->sense_len);
-
- if (!copy_to_user(hdr->sbp, req->sense, len))
- hdr->sb_len_wr = len;
- else
- ret = -EFAULT;
- }
-
- r = blk_rq_unmap_user(bio);
- if (!ret)
- ret = r;
-
- return ret;
-}
-
-static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
- struct sg_io_hdr *hdr, fmode_t mode)
-{
- unsigned long start_time;
- ssize_t ret = 0;
- int writing = 0;
- int at_head = 0;
- struct request *rq;
- struct scsi_request *req;
- struct bio *bio;
-
- if (hdr->interface_id != 'S')
- return -EINVAL;
-
- if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
- return -EIO;
-
- if (hdr->dxfer_len)
- switch (hdr->dxfer_direction) {
- default:
- return -EINVAL;
- case SG_DXFER_TO_DEV:
- writing = 1;
- break;
- case SG_DXFER_TO_FROM_DEV:
- case SG_DXFER_FROM_DEV:
- break;
- }
- if (hdr->flags & SG_FLAG_Q_AT_HEAD)
- at_head = 1;
-
- ret = -ENOMEM;
- rq = blk_get_request(q, writing ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
- req = scsi_req(rq);
-
- if (hdr->cmd_len > BLK_MAX_CDB) {
- req->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
- if (!req->cmd)
- goto out_put_request;
- }
-
- ret = blk_fill_sghdr_rq(q, rq, hdr, mode);
- if (ret < 0)
- goto out_free_cdb;
-
- ret = 0;
- if (hdr->iovec_count) {
- struct iov_iter i;
- struct iovec *iov = NULL;
-
- ret = import_iovec(rq_data_dir(rq), hdr->dxferp,
- hdr->iovec_count, 0, &iov, &i);
- if (ret < 0)
- goto out_free_cdb;
-
- /* SG_IO howto says that the shorter of the two wins */
- iov_iter_truncate(&i, hdr->dxfer_len);
-
- ret = blk_rq_map_user_iov(q, rq, NULL, &i, GFP_KERNEL);
- kfree(iov);
- } else if (hdr->dxfer_len)
- ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
- GFP_KERNEL);
-
- if (ret)
- goto out_free_cdb;
-
- bio = rq->bio;
- req->retries = 0;
-
- start_time = jiffies;
-
- blk_execute_rq(bd_disk, rq, at_head);
-
- hdr->duration = jiffies_to_msecs(jiffies - start_time);
-
- ret = blk_complete_sghdr_rq(rq, hdr, bio);
-
-out_free_cdb:
- scsi_req_free_cmd(req);
-out_put_request:
- blk_put_request(rq);
- return ret;
-}
-
-/**
- * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
- * @q: request queue to send scsi commands down
- * @disk: gendisk to operate on (option)
- * @mode: mode used to open the file through which the ioctl has been
- * submitted
- * @sic: userspace structure describing the command to perform
- *
- * Send down the scsi command described by @sic to the device below
- * the request queue @q. If @file is non-NULL it's used to perform
- * fine-grained permission checks that allow users to send down
- * non-destructive SCSI commands. If the caller has a struct gendisk
- * available it should be passed in as @disk to allow the low level
- * driver to use the information contained in it. A non-NULL @disk
- * is only allowed if the caller knows that the low level driver doesn't
- * need it (e.g. in the scsi subsystem).
- *
- * Notes:
- * - This interface is deprecated - users should use the SG_IO
- * interface instead, as this is a more flexible approach to
- * performing SCSI commands on a device.
- * - The SCSI command length is determined by examining the 1st byte
- * of the given command. There is no way to override this.
- * - Data transfers are limited to PAGE_SIZE
- * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
- * accommodate the sense buffer when an error occurs.
- * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
- * old code will not be surprised.
- * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
- * a negative return and the Unix error code in 'errno'.
- * If the SCSI command succeeds then 0 is returned.
- * Positive numbers returned are the compacted SCSI error codes (4
- * bytes in one int) where the lowest byte is the SCSI status.
- */
-int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
- struct scsi_ioctl_command __user *sic)
-{
- enum { OMAX_SB_LEN = 16 }; /* For backward compatibility */
- struct request *rq;
- struct scsi_request *req;
- int err;
- unsigned int in_len, out_len, bytes, opcode, cmdlen;
- char *buffer = NULL;
-
- if (!sic)
- return -EINVAL;
-
- /*
- * get in an out lengths, verify they don't exceed a page worth of data
- */
- if (get_user(in_len, &sic->inlen))
- return -EFAULT;
- if (get_user(out_len, &sic->outlen))
- return -EFAULT;
- if (in_len > PAGE_SIZE || out_len > PAGE_SIZE)
- return -EINVAL;
- if (get_user(opcode, sic->data))
- return -EFAULT;
-
- bytes = max(in_len, out_len);
- if (bytes) {
- buffer = kzalloc(bytes, GFP_NOIO | GFP_USER | __GFP_NOWARN);
- if (!buffer)
- return -ENOMEM;
-
- }
-
- rq = blk_get_request(q, in_len ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
- if (IS_ERR(rq)) {
- err = PTR_ERR(rq);
- goto error_free_buffer;
- }
- req = scsi_req(rq);
-
- cmdlen = COMMAND_SIZE(opcode);
-
- /*
- * get command and data to send to device, if any
- */
- err = -EFAULT;
- req->cmd_len = cmdlen;
- if (copy_from_user(req->cmd, sic->data, cmdlen))
- goto error;
-
- if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
- goto error;
-
- err = blk_verify_command(req->cmd, mode);
- if (err)
- goto error;
-
- /* default. possible overriden later */
- req->retries = 5;
-
- switch (opcode) {
- case SEND_DIAGNOSTIC:
- case FORMAT_UNIT:
- rq->timeout = FORMAT_UNIT_TIMEOUT;
- req->retries = 1;
- break;
- case START_STOP:
- rq->timeout = START_STOP_TIMEOUT;
- break;
- case MOVE_MEDIUM:
- rq->timeout = MOVE_MEDIUM_TIMEOUT;
- break;
- case READ_ELEMENT_STATUS:
- rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
- break;
- case READ_DEFECT_DATA:
- rq->timeout = READ_DEFECT_DATA_TIMEOUT;
- req->retries = 1;
- break;
- default:
- rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
- break;
- }
-
- if (bytes) {
- err = blk_rq_map_kern(q, rq, buffer, bytes, GFP_NOIO);
- if (err)
- goto error;
- }
-
- blk_execute_rq(disk, rq, 0);
-
- err = req->result & 0xff; /* only 8 bit SCSI status */
- if (err) {
- if (req->sense_len && req->sense) {
- bytes = (OMAX_SB_LEN > req->sense_len) ?
- req->sense_len : OMAX_SB_LEN;
- if (copy_to_user(sic->data, req->sense, bytes))
- err = -EFAULT;
- }
- } else {
- if (copy_to_user(sic->data, buffer, out_len))
- err = -EFAULT;
- }
-
-error:
- blk_put_request(rq);
-
-error_free_buffer:
- kfree(buffer);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
-
-/* Send basic block requests */
-static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
- int cmd, int data)
-{
- struct request *rq;
- int err;
-
- rq = blk_get_request(q, REQ_OP_DRV_OUT, 0);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
- rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
- scsi_req(rq)->cmd[0] = cmd;
- scsi_req(rq)->cmd[4] = data;
- scsi_req(rq)->cmd_len = 6;
- blk_execute_rq(bd_disk, rq, 0);
- err = scsi_req(rq)->result ? -EIO : 0;
- blk_put_request(rq);
-
- return err;
-}
-
-static inline int blk_send_start_stop(struct request_queue *q,
- struct gendisk *bd_disk, int data)
-{
- return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
-}
-
-int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp)
-{
-#ifdef CONFIG_COMPAT
- if (in_compat_syscall()) {
- struct compat_sg_io_hdr hdr32 = {
- .interface_id = hdr->interface_id,
- .dxfer_direction = hdr->dxfer_direction,
- .cmd_len = hdr->cmd_len,
- .mx_sb_len = hdr->mx_sb_len,
- .iovec_count = hdr->iovec_count,
- .dxfer_len = hdr->dxfer_len,
- .dxferp = (uintptr_t)hdr->dxferp,
- .cmdp = (uintptr_t)hdr->cmdp,
- .sbp = (uintptr_t)hdr->sbp,
- .timeout = hdr->timeout,
- .flags = hdr->flags,
- .pack_id = hdr->pack_id,
- .usr_ptr = (uintptr_t)hdr->usr_ptr,
- .status = hdr->status,
- .masked_status = hdr->masked_status,
- .msg_status = hdr->msg_status,
- .sb_len_wr = hdr->sb_len_wr,
- .host_status = hdr->host_status,
- .driver_status = hdr->driver_status,
- .resid = hdr->resid,
- .duration = hdr->duration,
- .info = hdr->info,
- };
-
- if (copy_to_user(argp, &hdr32, sizeof(hdr32)))
- return -EFAULT;
-
- return 0;
- }
-#endif
-
- if (copy_to_user(argp, hdr, sizeof(*hdr)))
- return -EFAULT;
-
- return 0;
-}
-EXPORT_SYMBOL(put_sg_io_hdr);
-
-int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp)
-{
-#ifdef CONFIG_COMPAT
- struct compat_sg_io_hdr hdr32;
-
- if (in_compat_syscall()) {
- if (copy_from_user(&hdr32, argp, sizeof(hdr32)))
- return -EFAULT;
-
- *hdr = (struct sg_io_hdr) {
- .interface_id = hdr32.interface_id,
- .dxfer_direction = hdr32.dxfer_direction,
- .cmd_len = hdr32.cmd_len,
- .mx_sb_len = hdr32.mx_sb_len,
- .iovec_count = hdr32.iovec_count,
- .dxfer_len = hdr32.dxfer_len,
- .dxferp = compat_ptr(hdr32.dxferp),
- .cmdp = compat_ptr(hdr32.cmdp),
- .sbp = compat_ptr(hdr32.sbp),
- .timeout = hdr32.timeout,
- .flags = hdr32.flags,
- .pack_id = hdr32.pack_id,
- .usr_ptr = compat_ptr(hdr32.usr_ptr),
- .status = hdr32.status,
- .masked_status = hdr32.masked_status,
- .msg_status = hdr32.msg_status,
- .sb_len_wr = hdr32.sb_len_wr,
- .host_status = hdr32.host_status,
- .driver_status = hdr32.driver_status,
- .resid = hdr32.resid,
- .duration = hdr32.duration,
- .info = hdr32.info,
- };
-
- return 0;
- }
-#endif
-
- if (copy_from_user(hdr, argp, sizeof(*hdr)))
- return -EFAULT;
-
- return 0;
-}
-EXPORT_SYMBOL(get_sg_io_hdr);
-
-#ifdef CONFIG_COMPAT
-struct compat_cdrom_generic_command {
- unsigned char cmd[CDROM_PACKET_SIZE];
- compat_caddr_t buffer;
- compat_uint_t buflen;
- compat_int_t stat;
- compat_caddr_t sense;
- unsigned char data_direction;
- unsigned char pad[3];
- compat_int_t quiet;
- compat_int_t timeout;
- compat_caddr_t unused;
-};
-#endif
-
-static int scsi_get_cdrom_generic_arg(struct cdrom_generic_command *cgc,
- const void __user *arg)
-{
-#ifdef CONFIG_COMPAT
- if (in_compat_syscall()) {
- struct compat_cdrom_generic_command cgc32;
-
- if (copy_from_user(&cgc32, arg, sizeof(cgc32)))
- return -EFAULT;
-
- *cgc = (struct cdrom_generic_command) {
- .buffer = compat_ptr(cgc32.buffer),
- .buflen = cgc32.buflen,
- .stat = cgc32.stat,
- .sense = compat_ptr(cgc32.sense),
- .data_direction = cgc32.data_direction,
- .quiet = cgc32.quiet,
- .timeout = cgc32.timeout,
- .unused = compat_ptr(cgc32.unused),
- };
- memcpy(&cgc->cmd, &cgc32.cmd, CDROM_PACKET_SIZE);
- return 0;
- }
-#endif
- if (copy_from_user(cgc, arg, sizeof(*cgc)))
- return -EFAULT;
-
- return 0;
-}
-
-static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc,
- void __user *arg)
-{
-#ifdef CONFIG_COMPAT
- if (in_compat_syscall()) {
- struct compat_cdrom_generic_command cgc32 = {
- .buffer = (uintptr_t)(cgc->buffer),
- .buflen = cgc->buflen,
- .stat = cgc->stat,
- .sense = (uintptr_t)(cgc->sense),
- .data_direction = cgc->data_direction,
- .quiet = cgc->quiet,
- .timeout = cgc->timeout,
- .unused = (uintptr_t)(cgc->unused),
- };
- memcpy(&cgc32.cmd, &cgc->cmd, CDROM_PACKET_SIZE);
-
- if (copy_to_user(arg, &cgc32, sizeof(cgc32)))
- return -EFAULT;
-
- return 0;
- }
-#endif
- if (copy_to_user(arg, cgc, sizeof(*cgc)))
- return -EFAULT;
-
- return 0;
-}
-
-static int scsi_cdrom_send_packet(struct request_queue *q,
- struct gendisk *bd_disk,
- fmode_t mode, void __user *arg)
-{
- struct cdrom_generic_command cgc;
- struct sg_io_hdr hdr;
- int err;
-
- err = scsi_get_cdrom_generic_arg(&cgc, arg);
- if (err)
- return err;
-
- cgc.timeout = clock_t_to_jiffies(cgc.timeout);
- memset(&hdr, 0, sizeof(hdr));
- hdr.interface_id = 'S';
- hdr.cmd_len = sizeof(cgc.cmd);
- hdr.dxfer_len = cgc.buflen;
- switch (cgc.data_direction) {
- case CGC_DATA_UNKNOWN:
- hdr.dxfer_direction = SG_DXFER_UNKNOWN;
- break;
- case CGC_DATA_WRITE:
- hdr.dxfer_direction = SG_DXFER_TO_DEV;
- break;
- case CGC_DATA_READ:
- hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- break;
- case CGC_DATA_NONE:
- hdr.dxfer_direction = SG_DXFER_NONE;
- break;
- default:
- return -EINVAL;
- }
-
- hdr.dxferp = cgc.buffer;
- hdr.sbp = cgc.sense;
- if (hdr.sbp)
- hdr.mx_sb_len = sizeof(struct request_sense);
- hdr.timeout = jiffies_to_msecs(cgc.timeout);
- hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd;
- hdr.cmd_len = sizeof(cgc.cmd);
-
- err = sg_io(q, bd_disk, &hdr, mode);
- if (err == -EFAULT)
- return -EFAULT;
-
- if (hdr.status)
- return -EIO;
-
- cgc.stat = err;
- cgc.buflen = hdr.resid;
- if (scsi_put_cdrom_generic_arg(&cgc, arg))
- return -EFAULT;
-
- return err;
-}
-
-int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode,
- unsigned int cmd, void __user *arg)
-{
- int err;
-
- if (!q)
- return -ENXIO;
-
- switch (cmd) {
- /*
- * new sgv3 interface
- */
- case SG_GET_VERSION_NUM:
- err = sg_get_version(arg);
- break;
- case SCSI_IOCTL_GET_IDLUN:
- err = scsi_get_idlun(q, arg);
- break;
- case SCSI_IOCTL_GET_BUS_NUMBER:
- err = scsi_get_bus(q, arg);
- break;
- case SG_SET_TIMEOUT:
- err = sg_set_timeout(q, arg);
- break;
- case SG_GET_TIMEOUT:
- err = sg_get_timeout(q);
- break;
- case SG_GET_RESERVED_SIZE:
- err = sg_get_reserved_size(q, arg);
- break;
- case SG_SET_RESERVED_SIZE:
- err = sg_set_reserved_size(q, arg);
- break;
- case SG_EMULATED_HOST:
- err = sg_emulated_host(q, arg);
- break;
- case SG_IO: {
- struct sg_io_hdr hdr;
-
- err = get_sg_io_hdr(&hdr, arg);
- if (err)
- break;
- err = sg_io(q, bd_disk, &hdr, mode);
- if (err == -EFAULT)
- break;
-
- if (put_sg_io_hdr(&hdr, arg))
- err = -EFAULT;
- break;
- }
- case CDROM_SEND_PACKET:
- err = scsi_cdrom_send_packet(q, bd_disk, mode, arg);
- break;
-
- /*
- * old junk scsi send command ioctl
- */
- case SCSI_IOCTL_SEND_COMMAND:
- printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
- err = -EINVAL;
- if (!arg)
- break;
-
- err = sg_scsi_ioctl(q, bd_disk, mode, arg);
- break;
- case CDROMCLOSETRAY:
- err = blk_send_start_stop(q, bd_disk, 0x03);
- break;
- case CDROMEJECT:
- err = blk_send_start_stop(q, bd_disk, 0x02);
- break;
- default:
- err = -ENOTTY;
- }
-
- return err;
-}
-EXPORT_SYMBOL(scsi_cmd_ioctl);
-
-int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd)
-{
- if (bd && !bdev_is_partition(bd))
- return 0;
-
- if (capable(CAP_SYS_RAWIO))
- return 0;
-
- return -ENOIOCTLCMD;
-}
-EXPORT_SYMBOL(scsi_verify_blk_ioctl);
-
-int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode,
- unsigned int cmd, void __user *arg)
-{
- int ret;
-
- ret = scsi_verify_blk_ioctl(bd, cmd);
- if (ret < 0)
- return ret;
-
- return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg);
-}
-EXPORT_SYMBOL(scsi_cmd_blk_ioctl);
-
-/**
- * scsi_req_init - initialize certain fields of a scsi_request structure
- * @req: Pointer to a scsi_request structure.
- * Initializes .__cmd[], .cmd, .cmd_len and .sense_len but no other members
- * of struct scsi_request.
- */
-void scsi_req_init(struct scsi_request *req)
-{
- memset(req->__cmd, 0, sizeof(req->__cmd));
- req->cmd = req->__cmd;
- req->cmd_len = BLK_MAX_CDB;
- req->sense_len = 0;
-}
-EXPORT_SYMBOL(scsi_req_init);
-
-static int __init blk_scsi_ioctl_init(void)
-{
- blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
- return 0;
-}
-fs_initcall(blk_scsi_ioctl_init);
diff --git a/drivers/accessibility/speakup/i18n.c b/drivers/accessibility/speakup/i18n.c
index bc7b47d1876f..d62079b1661f 100644
--- a/drivers/accessibility/speakup/i18n.c
+++ b/drivers/accessibility/speakup/i18n.c
@@ -90,13 +90,13 @@ static char *speakup_default_msgs[MSG_LAST_INDEX] = {
[MSG_COLOR_YELLOW] = "yellow",
[MSG_COLOR_WHITE] = "white",
[MSG_COLOR_GREY] = "grey",
- [MSG_COLOR_BRIGHTBLUE] "bright blue",
- [MSG_COLOR_BRIGHTGREEN] "bright green",
- [MSG_COLOR_BRIGHTCYAN] "bright cyan",
- [MSG_COLOR_BRIGHTRED] "bright red",
- [MSG_COLOR_BRIGHTMAGENTA] "bright magenta",
- [MSG_COLOR_BRIGHTYELLOW] "bright yellow",
- [MSG_COLOR_BRIGHTWHITE] "bright white",
+ [MSG_COLOR_BRIGHTBLUE] = "bright blue",
+ [MSG_COLOR_BRIGHTGREEN] = "bright green",
+ [MSG_COLOR_BRIGHTCYAN] = "bright cyan",
+ [MSG_COLOR_BRIGHTRED] = "bright red",
+ [MSG_COLOR_BRIGHTMAGENTA] = "bright magenta",
+ [MSG_COLOR_BRIGHTYELLOW] = "bright yellow",
+ [MSG_COLOR_BRIGHTWHITE] = "bright white",
/* Names of key states. */
[MSG_STATE_DOUBLE] = "double",
diff --git a/drivers/accessibility/speakup/speakup_soft.c b/drivers/accessibility/speakup/speakup_soft.c
index c3f97c572fb6..19824e7006fe 100644
--- a/drivers/accessibility/speakup/speakup_soft.c
+++ b/drivers/accessibility/speakup/speakup_soft.c
@@ -153,18 +153,25 @@ static char *get_initstring(void)
static char buf[40];
char *cp;
struct var_t *var;
+ size_t len;
+ size_t n;
memset(buf, 0, sizeof(buf));
cp = buf;
+ len = sizeof(buf);
+
var = synth_soft.vars;
while (var->var_id != MAXVARS) {
if (var->var_id != CAPS_START && var->var_id != CAPS_STOP &&
- var->var_id != PAUSE && var->var_id != DIRECT)
- cp = cp + sprintf(cp, var->u.n.synth_fmt,
- var->u.n.value);
+ var->var_id != PAUSE && var->var_id != DIRECT) {
+ n = scnprintf(cp, len, var->u.n.synth_fmt,
+ var->u.n.value);
+ cp = cp + n;
+ len = len - n;
+ }
var++;
}
- cp = cp + sprintf(cp, "\n");
+ cp = cp + scnprintf(cp, len, "\n");
return buf;
}
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 894b7e6ae144..30b1f511c2af 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -385,7 +385,9 @@ static struct platform_device *lpss_clk_dev;
static inline void lpt_register_clock_device(void)
{
- lpss_clk_dev = platform_device_register_simple("clk-lpt", -1, NULL, 0);
+ lpss_clk_dev = platform_device_register_simple("clk-lpss-atom",
+ PLATFORM_DEVID_NONE,
+ NULL, 0);
}
static int register_device_clock(struct acpi_device *adev,
@@ -434,8 +436,8 @@ static int register_device_clock(struct acpi_device *adev,
if (!clk_name)
return -ENOMEM;
clk = clk_register_fractional_divider(NULL, clk_name, parent,
- 0, prv_base,
- 1, 15, 16, 15, 0, NULL);
+ CLK_FRAC_DIVIDER_POWER_OF_TWO_PS,
+ prv_base, 1, 15, 16, 15, 0, NULL);
parent = clk_name;
clk_name = kasprintf(GFP_KERNEL, "%s-update", devname);
@@ -1337,7 +1339,7 @@ void __init acpi_lpss_init(void)
const struct x86_cpu_id *id;
int ret;
- ret = lpt_clk_init();
+ ret = lpss_atom_clk_init();
if (ret)
return;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 3abb4373d11b..fa923a929224 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1019,7 +1019,7 @@ static int acpi_device_probe(struct device *dev)
return 0;
}
-static int acpi_device_remove(struct device *dev)
+static void acpi_device_remove(struct device *dev)
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
struct acpi_driver *acpi_drv = acpi_dev->driver;
@@ -1034,7 +1034,6 @@ static int acpi_device_remove(struct device *dev)
acpi_dev->driver_data = NULL;
put_device(dev);
- return 0;
}
struct bus_type acpi_bus_type = {
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index a37a1532a575..f9383736fa0f 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -583,8 +583,8 @@ void __init acpi_table_upgrade(void)
}
acpi_tables_addr =
- memblock_find_in_range(0, ACPI_TABLE_UPGRADE_MAX_PHYS,
- all_tables_size, PAGE_SIZE);
+ memblock_phys_alloc_range(all_tables_size, PAGE_SIZE,
+ 0, ACPI_TABLE_UPGRADE_MAX_PHYS);
if (!acpi_tables_addr) {
WARN_ON(1);
return;
@@ -599,7 +599,6 @@ void __init acpi_table_upgrade(void)
* Both memblock_reserve and e820__range_add (via arch_reserve_mem_area)
* works fine.
*/
- memblock_reserve(acpi_tables_addr, all_tables_size);
arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
/*
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 939ca220bf78..962041148482 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -219,7 +219,7 @@ static int amba_probe(struct device *dev)
return ret;
}
-static int amba_remove(struct device *dev)
+static void amba_remove(struct device *dev)
{
struct amba_device *pcdev = to_amba_device(dev);
struct amba_driver *drv = to_amba_driver(dev->driver);
@@ -236,8 +236,6 @@ static int amba_remove(struct device *dev)
amba_put_disable_pclk(pcdev);
dev_pm_domain_detach(dev, true);
-
- return 0;
}
static void amba_shutdown(struct device *dev)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index bcec598b89f2..d9030cb6b1e4 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2547,8 +2547,8 @@ static void binder_transaction(struct binder_proc *proc,
ref->node, &target_proc,
&return_error);
} else {
- binder_user_error("%d:%d got transaction to invalid handle\n",
- proc->pid, thread->pid);
+ binder_user_error("%d:%d got transaction to invalid handle, %u\n",
+ proc->pid, thread->pid, tr->target.handle);
return_error = BR_FAILED_REPLY;
}
binder_proc_unlock(proc);
diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c
index e80ba93c62a9..e3605cdd4335 100644
--- a/drivers/android/binderfs.c
+++ b/drivers/android/binderfs.c
@@ -58,6 +58,10 @@ enum binderfs_stats_mode {
binderfs_stats_mode_global,
};
+struct binder_features {
+ bool oneway_spam_detection;
+};
+
static const struct constant_table binderfs_param_stats[] = {
{ "global", binderfs_stats_mode_global },
{}
@@ -69,6 +73,10 @@ static const struct fs_parameter_spec binderfs_fs_parameters[] = {
{}
};
+static struct binder_features binder_features = {
+ .oneway_spam_detection = true,
+};
+
static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
{
return sb->s_fs_info;
@@ -583,6 +591,33 @@ out:
return dentry;
}
+static int binder_features_show(struct seq_file *m, void *unused)
+{
+ bool *feature = m->private;
+
+ seq_printf(m, "%d\n", *feature);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(binder_features);
+
+static int init_binder_features(struct super_block *sb)
+{
+ struct dentry *dentry, *dir;
+
+ dir = binderfs_create_dir(sb->s_root, "features");
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
+
+ dentry = binderfs_create_file(dir, "oneway_spam_detection",
+ &binder_features_fops,
+ &binder_features.oneway_spam_detection);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ return 0;
+}
+
static int init_binder_logs(struct super_block *sb)
{
struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
@@ -723,6 +758,10 @@ static int binderfs_fill_super(struct super_block *sb, struct fs_context *fc)
name++;
}
+ ret = init_binder_features(sb);
+ if (ret)
+ return ret;
+
if (info->mount_opts.stats_mode == binderfs_stats_mode_global)
return init_binder_logs(sb);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b8459c54f739..eed65311b5d1 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2186,6 +2186,25 @@ not_supported:
dev->flags &= ~ATA_DFLAG_NCQ_PRIO;
}
+static bool ata_dev_check_adapter(struct ata_device *dev,
+ unsigned short vendor_id)
+{
+ struct pci_dev *pcidev = NULL;
+ struct device *parent_dev = NULL;
+
+ for (parent_dev = dev->tdev.parent; parent_dev != NULL;
+ parent_dev = parent_dev->parent) {
+ if (dev_is_pci(parent_dev)) {
+ pcidev = to_pci_dev(parent_dev);
+ if (pcidev->vendor == vendor_id)
+ return true;
+ break;
+ }
+ }
+
+ return false;
+}
+
static int ata_dev_config_ncq(struct ata_device *dev,
char *desc, size_t desc_sz)
{
@@ -2204,6 +2223,13 @@ static int ata_dev_config_ncq(struct ata_device *dev,
snprintf(desc, desc_sz, "NCQ (not used)");
return 0;
}
+
+ if (dev->horkage & ATA_HORKAGE_NO_NCQ_ON_ATI &&
+ ata_dev_check_adapter(dev, PCI_VENDOR_ID_ATI)) {
+ snprintf(desc, desc_sz, "NCQ (not used)");
+ return 0;
+ }
+
if (ap->flags & ATA_FLAG_NCQ) {
hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE);
dev->flags |= ATA_DFLAG_NCQ;
@@ -3970,6 +3996,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Samsung SSD 850*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
+ { "Samsung SSD 860*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
+ ATA_HORKAGE_ZERO_AFTER_TRIM |
+ ATA_HORKAGE_NO_NCQ_ON_ATI, },
+ { "Samsung SSD 870*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
+ ATA_HORKAGE_ZERO_AFTER_TRIM |
+ ATA_HORKAGE_NO_NCQ_ON_ATI, },
{ "FCCT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
@@ -6124,6 +6156,8 @@ static int __init ata_parse_force_one(char **cur,
{ "ncq", .horkage_off = ATA_HORKAGE_NONCQ },
{ "noncqtrim", .horkage_on = ATA_HORKAGE_NO_NCQ_TRIM },
{ "ncqtrim", .horkage_off = ATA_HORKAGE_NO_NCQ_TRIM },
+ { "noncqati", .horkage_on = ATA_HORKAGE_NO_NCQ_ON_ATI },
+ { "ncqati", .horkage_off = ATA_HORKAGE_NO_NCQ_ON_ATI },
{ "dump_id", .horkage_on = ATA_HORKAGE_DUMP_ID },
{ "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) },
{ "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) },
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index bb3637762985..bf9c4b6c5c3d 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -912,7 +912,7 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
* Note that ATA_QCFLAG_FAILED is unconditionally set after
* this function completes.
*/
- blk_abort_request(qc->scsicmd->request);
+ blk_abort_request(scsi_cmd_to_rq(qc->scsicmd));
}
/**
@@ -1893,8 +1893,7 @@ static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc)
*/
static inline bool ata_eh_quiet(struct ata_queued_cmd *qc)
{
- if (qc->scsicmd &&
- qc->scsicmd->request->rq_flags & RQF_QUIET)
+ if (qc->scsicmd && scsi_cmd_to_rq(qc->scsicmd)->rq_flags & RQF_QUIET)
qc->flags |= ATA_QCFLAG_QUIET;
return qc->flags & ATA_QCFLAG_QUIET;
}
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 0b7b4624e4df..1fb4611f7eeb 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -631,7 +631,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
{
struct ata_queued_cmd *qc;
- qc = ata_qc_new_init(dev, cmd->request->tag);
+ qc = ata_qc_new_init(dev, scsi_cmd_to_rq(cmd)->tag);
if (qc) {
qc->scsicmd = cmd;
qc->scsidone = cmd->scsi_done;
@@ -639,7 +639,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
qc->sg = scsi_sglist(cmd);
qc->n_elem = scsi_sg_count(cmd);
- if (cmd->request->rq_flags & RQF_QUIET)
+ if (scsi_cmd_to_rq(cmd)->rq_flags & RQF_QUIET)
qc->flags |= ATA_QCFLAG_QUIET;
} else {
cmd->result = (DID_OK << 16) | SAM_STAT_TASK_SET_FULL;
@@ -1496,7 +1496,7 @@ nothing_to_do:
static bool ata_check_nblocks(struct scsi_cmnd *scmd, u32 n_blocks)
{
- struct request *rq = scmd->request;
+ struct request *rq = scsi_cmd_to_rq(scmd);
u32 req_blocks;
if (!blk_rq_is_passthrough(rq))
@@ -1531,7 +1531,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
const u8 *cdb = scmd->cmnd;
- struct request *rq = scmd->request;
+ struct request *rq = scsi_cmd_to_rq(scmd);
int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
unsigned int tf_flags = 0;
u64 block;
@@ -3139,7 +3139,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
* as it modifies the DATA OUT buffer, which would corrupt user
* memory for SG_IO commands.
*/
- if (unlikely(blk_rq_is_passthrough(scmd->request)))
+ if (unlikely(blk_rq_is_passthrough(scsi_cmd_to_rq(scmd))))
goto invalid_opcode;
if (unlikely(scmd->cmd_len < 16)) {
diff --git a/drivers/ata/pata_falcon.c b/drivers/ata/pata_falcon.c
index 9d0dd8f4c21c..121635aa8c00 100644
--- a/drivers/ata/pata_falcon.c
+++ b/drivers/ata/pata_falcon.c
@@ -48,8 +48,8 @@ static unsigned int pata_falcon_data_xfer(struct ata_queued_cmd *qc,
struct scsi_cmnd *cmd = qc->scsicmd;
bool swap = 1;
- if (dev->class == ATA_DEV_ATA && cmd && cmd->request &&
- !blk_rq_is_passthrough(cmd->request))
+ if (dev->class == ATA_DEV_ATA && cmd &&
+ !blk_rq_is_passthrough(scsi_cmd_to_rq(cmd)))
swap = 0;
/* Transfer multiple of 2 bytes */
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 5881d64af943..99c63087c8ae 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -13,45 +13,134 @@
*/
#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/libata.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
-#include <linux/platform_data/pata_ixp4xx_cf.h>
+#include <linux/regmap.h>
#include <scsi/scsi_host.h>
#define DRV_NAME "pata_ixp4xx_cf"
-#define DRV_VERSION "0.2"
+#define DRV_VERSION "1.0"
-static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
+struct ixp4xx_pata {
+ struct ata_host *host;
+ struct regmap *rmap;
+ u32 cmd_csreg;
+ void __iomem *cmd;
+ void __iomem *ctl;
+};
+
+#define IXP4XX_EXP_TIMING_STRIDE 0x04
+/* The timings for the chipselect is in bits 29..16 */
+#define IXP4XX_EXP_T1_T5_MASK GENMASK(29, 16)
+#define IXP4XX_EXP_PIO_0_8 0x0a470000
+#define IXP4XX_EXP_PIO_1_8 0x06430000
+#define IXP4XX_EXP_PIO_2_8 0x02410000
+#define IXP4XX_EXP_PIO_3_8 0x00820000
+#define IXP4XX_EXP_PIO_4_8 0x00400000
+#define IXP4XX_EXP_PIO_0_16 0x29640000
+#define IXP4XX_EXP_PIO_1_16 0x05030000
+#define IXP4XX_EXP_PIO_2_16 0x00b20000
+#define IXP4XX_EXP_PIO_3_16 0x00820000
+#define IXP4XX_EXP_PIO_4_16 0x00400000
+#define IXP4XX_EXP_BW_MASK (BIT(6)|BIT(0))
+#define IXP4XX_EXP_BYTE_RD16 BIT(6) /* Byte reads on half-word devices */
+#define IXP4XX_EXP_BYTE_EN BIT(0) /* Use 8bit data bus if set */
+
+static void ixp4xx_set_8bit_timing(struct ixp4xx_pata *ixpp, u8 pio_mode)
+{
+ switch (pio_mode) {
+ case XFER_PIO_0:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_0_8);
+ break;
+ case XFER_PIO_1:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_1_8);
+ break;
+ case XFER_PIO_2:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_2_8);
+ break;
+ case XFER_PIO_3:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_3_8);
+ break;
+ case XFER_PIO_4:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_4_8);
+ break;
+ default:
+ break;
+ }
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_BW_MASK, IXP4XX_EXP_BYTE_RD16|IXP4XX_EXP_BYTE_EN);
+}
+
+static void ixp4xx_set_16bit_timing(struct ixp4xx_pata *ixpp, u8 pio_mode)
{
- struct ata_device *dev;
-
- ata_for_each_dev(dev, link, ENABLED) {
- ata_dev_info(dev, "configured for PIO0\n");
- dev->pio_mode = XFER_PIO_0;
- dev->xfer_mode = XFER_PIO_0;
- dev->xfer_shift = ATA_SHIFT_PIO;
- dev->flags |= ATA_DFLAG_PIO;
+ switch (pio_mode){
+ case XFER_PIO_0:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_0_16);
+ break;
+ case XFER_PIO_1:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_1_16);
+ break;
+ case XFER_PIO_2:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_2_16);
+ break;
+ case XFER_PIO_3:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_3_16);
+ break;
+ case XFER_PIO_4:
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_T1_T5_MASK, IXP4XX_EXP_PIO_4_16);
+ break;
+ default:
+ break;
}
- return 0;
+ regmap_update_bits(ixpp->rmap, ixpp->cmd_csreg,
+ IXP4XX_EXP_BW_MASK, IXP4XX_EXP_BYTE_RD16);
+}
+
+/* This sets up the timing on the chipselect CMD accordingly */
+static void ixp4xx_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct ixp4xx_pata *ixpp = ap->host->private_data;
+
+ ata_dev_printk(adev, KERN_INFO, "configured for PIO%d 8bit\n",
+ adev->pio_mode - XFER_PIO_0);
+ ixp4xx_set_8bit_timing(ixpp, adev->pio_mode);
}
+
static unsigned int ixp4xx_mmio_data_xfer(struct ata_queued_cmd *qc,
- unsigned char *buf, unsigned int buflen, int rw)
+ unsigned char *buf, unsigned int buflen, int rw)
{
unsigned int i;
unsigned int words = buflen >> 1;
u16 *buf16 = (u16 *) buf;
+ struct ata_device *adev = qc->dev;
struct ata_port *ap = qc->dev->link->ap;
void __iomem *mmio = ap->ioaddr.data_addr;
- struct ixp4xx_pata_data *data = dev_get_platdata(ap->host->dev);
+ struct ixp4xx_pata *ixpp = ap->host->private_data;
+ unsigned long flags;
+
+ ata_dev_printk(adev, KERN_DEBUG, "%s %d bytes\n", (rw == READ) ? "READ" : "WRITE",
+ buflen);
+ spin_lock_irqsave(ap->lock, flags);
/* set the expansion bus in 16bit mode and restore
* 8 bit mode after the transaction.
*/
- *data->cs0_cfg &= ~(0x01);
- udelay(100);
+ ixp4xx_set_16bit_timing(ixpp, adev->pio_mode);
+ udelay(5);
/* Transfer multiple of 2 bytes */
if (rw == READ)
@@ -76,8 +165,10 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_queued_cmd *qc,
words++;
}
- udelay(100);
- *data->cs0_cfg |= 0x01;
+ ixp4xx_set_8bit_timing(ixpp, adev->pio_mode);
+ udelay(5);
+
+ spin_unlock_irqrestore(ap->lock, flags);
return words << 1;
}
@@ -90,79 +181,98 @@ static struct ata_port_operations ixp4xx_port_ops = {
.inherits = &ata_sff_port_ops,
.sff_data_xfer = ixp4xx_mmio_data_xfer,
.cable_detect = ata_cable_40wire,
- .set_mode = ixp4xx_set_mode,
+ .set_piomode = ixp4xx_set_piomode,
+};
+
+static struct ata_port_info ixp4xx_port_info = {
+ .flags = ATA_FLAG_NO_ATAPI,
+ .pio_mask = ATA_PIO4,
+ .port_ops = &ixp4xx_port_ops,
};
static void ixp4xx_setup_port(struct ata_port *ap,
- struct ixp4xx_pata_data *data,
- unsigned long raw_cs0, unsigned long raw_cs1)
+ struct ixp4xx_pata *ixpp,
+ unsigned long raw_cmd, unsigned long raw_ctl)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
- unsigned long raw_cmd = raw_cs0;
- unsigned long raw_ctl = raw_cs1 + 0x06;
- ioaddr->cmd_addr = data->cs0;
- ioaddr->altstatus_addr = data->cs1 + 0x06;
- ioaddr->ctl_addr = data->cs1 + 0x06;
+ raw_ctl += 0x06;
+ ioaddr->cmd_addr = ixpp->cmd;
+ ioaddr->altstatus_addr = ixpp->ctl + 0x06;
+ ioaddr->ctl_addr = ixpp->ctl + 0x06;
ata_sff_std_ports(ioaddr);
-#ifndef __ARMEB__
-
- /* adjust the addresses to handle the address swizzling of the
- * ixp4xx in little endian mode.
- */
-
- *(unsigned long *)&ioaddr->data_addr ^= 0x02;
- *(unsigned long *)&ioaddr->cmd_addr ^= 0x03;
- *(unsigned long *)&ioaddr->altstatus_addr ^= 0x03;
- *(unsigned long *)&ioaddr->ctl_addr ^= 0x03;
- *(unsigned long *)&ioaddr->error_addr ^= 0x03;
- *(unsigned long *)&ioaddr->feature_addr ^= 0x03;
- *(unsigned long *)&ioaddr->nsect_addr ^= 0x03;
- *(unsigned long *)&ioaddr->lbal_addr ^= 0x03;
- *(unsigned long *)&ioaddr->lbam_addr ^= 0x03;
- *(unsigned long *)&ioaddr->lbah_addr ^= 0x03;
- *(unsigned long *)&ioaddr->device_addr ^= 0x03;
- *(unsigned long *)&ioaddr->status_addr ^= 0x03;
- *(unsigned long *)&ioaddr->command_addr ^= 0x03;
-
- raw_cmd ^= 0x03;
- raw_ctl ^= 0x03;
-#endif
+ if (!IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) {
+ /* adjust the addresses to handle the address swizzling of the
+ * ixp4xx in little endian mode.
+ */
+
+ *(unsigned long *)&ioaddr->data_addr ^= 0x02;
+ *(unsigned long *)&ioaddr->cmd_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->altstatus_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->ctl_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->error_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->feature_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->nsect_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->lbal_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->lbam_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->lbah_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->device_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->status_addr ^= 0x03;
+ *(unsigned long *)&ioaddr->command_addr ^= 0x03;
+
+ raw_cmd ^= 0x03;
+ raw_ctl ^= 0x03;
+ }
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", raw_cmd, raw_ctl);
}
static int ixp4xx_pata_probe(struct platform_device *pdev)
{
- struct resource *cs0, *cs1;
- struct ata_host *host;
- struct ata_port *ap;
- struct ixp4xx_pata_data *data = dev_get_platdata(&pdev->dev);
+ struct resource *cmd, *ctl;
+ struct ata_port_info pi = ixp4xx_port_info;
+ const struct ata_port_info *ppi[] = { &pi, NULL };
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct ixp4xx_pata *ixpp;
+ u32 csindex;
int ret;
int irq;
- cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ cmd = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ctl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!cs0 || !cs1)
+ if (!cmd || !ctl)
return -EINVAL;
- /* allocate host */
- host = ata_host_alloc(&pdev->dev, 1);
- if (!host)
+ ixpp = devm_kzalloc(dev, sizeof(*ixpp), GFP_KERNEL);
+ if (!ixpp)
return -ENOMEM;
- /* acquire resources and fill host */
- ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+ ixpp->rmap = syscon_node_to_regmap(np->parent);
+ if (IS_ERR(ixpp->rmap))
+ return dev_err_probe(dev, PTR_ERR(ixpp->rmap), "no regmap\n");
+ /* Inspect our address to figure out what chipselect the CMD is on */
+ ret = of_property_read_u32_index(np, "reg", 0, &csindex);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "can't inspect CMD address\n");
+ dev_info(dev, "using CS%d for PIO timing configuration\n", csindex);
+ ixpp->cmd_csreg = csindex * IXP4XX_EXP_TIMING_STRIDE;
- data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000);
- data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000);
+ ixpp->host = ata_host_alloc_pinfo(dev, ppi, 1);
+ if (!ixpp->host)
+ return -ENOMEM;
+ ixpp->host->private_data = ixpp;
- if (!data->cs0 || !data->cs1)
+ ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ ixpp->cmd = devm_ioremap_resource(dev, cmd);
+ ixpp->ctl = devm_ioremap_resource(dev, ctl);
+ if (IS_ERR(ixpp->cmd) || IS_ERR(ixpp->ctl))
return -ENOMEM;
irq = platform_get_irq(pdev, 0);
@@ -173,27 +283,23 @@ static int ixp4xx_pata_probe(struct platform_device *pdev)
else
return -EINVAL;
- /* Setup expansion bus chip selects */
- *data->cs0_cfg = data->cs0_bits;
- *data->cs1_cfg = data->cs1_bits;
-
- ap = host->ports[0];
-
- ap->ops = &ixp4xx_port_ops;
- ap->pio_mask = ATA_PIO4;
- ap->flags |= ATA_FLAG_NO_ATAPI;
+ /* Just one port to set up */
+ ixp4xx_setup_port(ixpp->host->ports[0], ixpp, cmd->start, ctl->start);
- ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
+ ata_print_version_once(dev, DRV_VERSION);
- ata_print_version_once(&pdev->dev, DRV_VERSION);
-
- /* activate host */
- return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
+ return ata_host_activate(ixpp->host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
}
+static const struct of_device_id ixp4xx_pata_of_match[] = {
+ { .compatible = "intel,ixp4xx-compact-flash", },
+ { },
+};
+
static struct platform_driver ixp4xx_pata_platform_driver = {
.driver = {
.name = DRV_NAME,
+ .of_match_table = ixp4xx_pata_of_match,
},
.probe = ixp4xx_pata_probe,
.remove = ata_platform_remove_one,
diff --git a/drivers/base/arch_numa.c b/drivers/base/arch_numa.c
index 4cc4e117727d..46c503486e96 100644
--- a/drivers/base/arch_numa.c
+++ b/drivers/base/arch_numa.c
@@ -279,13 +279,10 @@ static int __init numa_alloc_distance(void)
int i, j;
size = nr_node_ids * nr_node_ids * sizeof(numa_distance[0]);
- phys = memblock_find_in_range(0, PFN_PHYS(max_pfn),
- size, PAGE_SIZE);
+ phys = memblock_phys_alloc_range(size, PAGE_SIZE, 0, PFN_PHYS(max_pfn));
if (WARN_ON(!phys))
return -ENOMEM;
- memblock_reserve(phys, size);
-
numa_distance = __va(phys);
numa_distance_cnt = nr_node_ids;
diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c
index 6a30264ab2ba..9230c9472bb0 100644
--- a/drivers/base/auxiliary.c
+++ b/drivers/base/auxiliary.c
@@ -79,7 +79,7 @@ static int auxiliary_bus_probe(struct device *dev)
return ret;
}
-static int auxiliary_bus_remove(struct device *dev)
+static void auxiliary_bus_remove(struct device *dev)
{
struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
@@ -87,8 +87,6 @@ static int auxiliary_bus_remove(struct device *dev)
if (auxdrv->remove)
auxdrv->remove(auxdev);
dev_pm_domain_detach(dev, true);
-
- return 0;
}
static void auxiliary_bus_shutdown(struct device *dev)
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 1f6b4bd61056..bdc98c5713d5 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -195,7 +195,7 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf,
bus_put(bus);
return err;
}
-static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, S_IWUSR, NULL, unbind_store);
+static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, 0200, NULL, unbind_store);
/*
* Manually attach a device to a driver.
@@ -221,7 +221,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
bus_put(bus);
return err;
}
-static DRIVER_ATTR_IGNORE_LOCKDEP(bind, S_IWUSR, NULL, bind_store);
+static DRIVER_ATTR_IGNORE_LOCKDEP(bind, 0200, NULL, bind_store);
static ssize_t drivers_autoprobe_show(struct bus_type *bus, char *buf)
{
@@ -767,7 +767,7 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
* DEVICE_ATTR_WO(uevent), which would cause a clash with the with the store
* function name.
*/
-static struct bus_attribute bus_attr_uevent = __ATTR(uevent, S_IWUSR, NULL,
+static struct bus_attribute bus_attr_uevent = __ATTR(uevent, 0200, NULL,
bus_uevent_store);
/**
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index bfc095956dd1..dad296229161 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -297,6 +297,7 @@ static void free_cache_attributes(unsigned int cpu)
kfree(per_cpu_cacheinfo(cpu));
per_cpu_cacheinfo(cpu) = NULL;
+ cache_leaves(cpu) = 0;
}
int __weak init_cache_level(unsigned int cpu)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 3a72241b87c6..e65dd803a453 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -27,6 +27,7 @@
#include <linux/netdevice.h>
#include <linux/sched/signal.h>
#include <linux/sched/mm.h>
+#include <linux/swiotlb.h>
#include <linux/sysfs.h>
#include <linux/dma-map-ops.h> /* for dma_default_coherent */
@@ -886,6 +887,8 @@ static void device_link_put_kref(struct device_link *link)
{
if (link->flags & DL_FLAG_STATELESS)
kref_put(&link->kref, __device_link_del);
+ else if (!device_is_registered(link->consumer))
+ __device_link_del(&link->kref);
else
WARN(1, "Unable to drop a managed device link reference\n");
}
@@ -2849,6 +2852,9 @@ void device_initialize(struct device *dev)
defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
dev->dma_coherent = dma_default_coherent;
#endif
+#ifdef CONFIG_SWIOTLB
+ dev->dma_io_tlb_mem = &io_tlb_default_mem;
+#endif
}
EXPORT_SYMBOL_GPL(device_initialize);
@@ -4579,8 +4585,8 @@ static void __dev_printk(const char *level, const struct device *dev,
printk("%s(NULL device *): %pV", level, vaf);
}
-void dev_printk(const char *level, const struct device *dev,
- const char *fmt, ...)
+void _dev_printk(const char *level, const struct device *dev,
+ const char *fmt, ...)
{
struct va_format vaf;
va_list args;
@@ -4594,7 +4600,7 @@ void dev_printk(const char *level, const struct device *dev,
va_end(args);
}
-EXPORT_SYMBOL(dev_printk);
+EXPORT_SYMBOL(_dev_printk);
#define define_dev_printk_level(func, kern_level) \
void func(const struct device *dev, const char *fmt, ...) \
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 5ef14db97904..5fc258073bc7 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -388,7 +388,7 @@ int register_cpu(struct cpu *cpu, int num)
return 0;
}
-struct device *get_cpu_device(unsigned cpu)
+struct device *get_cpu_device(unsigned int cpu)
{
if (cpu < nr_cpu_ids && cpu_possible(cpu))
return per_cpu(cpu_sys_devices, cpu);
@@ -484,7 +484,7 @@ static const struct attribute_group *cpu_root_attr_groups[] = {
NULL,
};
-bool cpu_is_hotpluggable(unsigned cpu)
+bool cpu_is_hotpluggable(unsigned int cpu)
{
struct device *dev = get_cpu_device(cpu);
return dev && container_of(dev, struct cpu, dev)->hotpluggable;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 437cd61343b2..68ea1f949daa 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -580,7 +580,8 @@ re_probe:
goto probe_failed;
}
- if (driver_sysfs_add(dev)) {
+ ret = driver_sysfs_add(dev);
+ if (ret) {
pr_err("%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
@@ -602,15 +603,18 @@ re_probe:
goto probe_failed;
}
- if (device_add_groups(dev, drv->dev_groups)) {
+ ret = device_add_groups(dev, drv->dev_groups);
+ if (ret) {
dev_err(dev, "device_add_groups() failed\n");
goto dev_groups_failed;
}
- if (dev_has_sync_state(dev) &&
- device_create_file(dev, &dev_attr_state_synced)) {
- dev_err(dev, "state_synced sysfs add failed\n");
- goto dev_sysfs_state_synced_failed;
+ if (dev_has_sync_state(dev)) {
+ ret = device_create_file(dev, &dev_attr_state_synced);
+ if (ret) {
+ dev_err(dev, "state_synced sysfs add failed\n");
+ goto dev_sysfs_state_synced_failed;
+ }
}
if (test_remove) {
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 68c549d71230..bdbedc6660a8 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -165,7 +165,7 @@ static inline int fw_state_wait(struct fw_priv *fw_priv)
return __fw_state_wait_common(fw_priv, MAX_SCHEDULE_TIMEOUT);
}
-static int fw_cache_piggyback_on_request(const char *name);
+static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv);
static struct fw_priv *__allocate_fw_priv(const char *fw_name,
struct firmware_cache *fwc,
@@ -707,10 +707,8 @@ int assign_fw(struct firmware *fw, struct device *device)
* on request firmware.
*/
if (!(fw_priv->opt_flags & FW_OPT_NOCACHE) &&
- fw_priv->fwc->state == FW_LOADER_START_CACHE) {
- if (fw_cache_piggyback_on_request(fw_priv->fw_name))
- kref_get(&fw_priv->ref);
- }
+ fw_priv->fwc->state == FW_LOADER_START_CACHE)
+ fw_cache_piggyback_on_request(fw_priv);
/* pass the pages buffer to driver at the last minute */
fw_set_page_data(fw_priv, fw);
@@ -1259,11 +1257,11 @@ static int __fw_entry_found(const char *name)
return 0;
}
-static int fw_cache_piggyback_on_request(const char *name)
+static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv)
{
- struct firmware_cache *fwc = &fw_cache;
+ const char *name = fw_priv->fw_name;
+ struct firmware_cache *fwc = fw_priv->fwc;
struct fw_cache_entry *fce;
- int ret = 0;
spin_lock(&fwc->name_lock);
if (__fw_entry_found(name))
@@ -1271,13 +1269,12 @@ static int fw_cache_piggyback_on_request(const char *name)
fce = alloc_fw_cache_entry(name);
if (fce) {
- ret = 1;
list_add(&fce->list, &fwc->fw_names);
+ kref_get(&fw_priv->ref);
pr_debug("%s: fw: %s\n", __func__, name);
}
found:
spin_unlock(&fwc->name_lock);
- return ret;
}
static void free_fw_cache_entry(struct fw_cache_entry *fce)
@@ -1508,9 +1505,8 @@ static inline void unregister_fw_pm_ops(void)
unregister_pm_notifier(&fw_cache.pm_notify);
}
#else
-static int fw_cache_piggyback_on_request(const char *name)
+static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv)
{
- return 0;
}
static inline int register_fw_pm_ops(void)
{
diff --git a/drivers/base/isa.c b/drivers/base/isa.c
index aa4737667026..55e3ee2da98f 100644
--- a/drivers/base/isa.c
+++ b/drivers/base/isa.c
@@ -46,14 +46,12 @@ static int isa_bus_probe(struct device *dev)
return 0;
}
-static int isa_bus_remove(struct device *dev)
+static void isa_bus_remove(struct device *dev)
{
struct isa_driver *isa_driver = dev->platform_data;
if (isa_driver && isa_driver->remove)
isa_driver->remove(dev, to_isa_dev(dev)->id);
-
- return 0;
}
static void isa_bus_shutdown(struct device *dev)
diff --git a/drivers/base/map.c b/drivers/base/map.c
index 5650ab2b247a..83aeb09ca161 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -33,9 +33,9 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
struct module *module, kobj_probe_t *probe,
int (*lock)(dev_t, void *), void *data)
{
- unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
- unsigned index = MAJOR(dev);
- unsigned i;
+ unsigned int n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
+ unsigned int index = MAJOR(dev);
+ unsigned int i;
struct probe *p;
if (n > 255)
@@ -67,9 +67,9 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
{
- unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
- unsigned index = MAJOR(dev);
- unsigned i;
+ unsigned int n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
+ unsigned int index = MAJOR(dev);
+ unsigned int i;
struct probe *found = NULL;
if (n > 255)
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index aa31a21f33d7..e3fd2dbf4eea 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -578,9 +578,9 @@ static struct memory_block *find_memory_block_by_id(unsigned long block_id)
/*
* Called under device_hotplug_lock.
*/
-struct memory_block *find_memory_block(struct mem_section *section)
+struct memory_block *find_memory_block(unsigned long section_nr)
{
- unsigned long block_id = memory_block_id(__section_nr(section));
+ unsigned long block_id = memory_block_id(section_nr);
return find_memory_block_by_id(block_id);
}
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 4a4ae868ad9f..be16bbff11cc 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -26,43 +26,47 @@ static struct bus_type node_subsys = {
.dev_name = "node",
};
-
-static ssize_t node_read_cpumap(struct device *dev, bool list, char *buf)
+static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
{
- ssize_t n;
- cpumask_var_t mask;
+ struct device *dev = kobj_to_dev(kobj);
struct node *node_dev = to_node(dev);
-
- /* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
- BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
+ cpumask_var_t mask;
+ ssize_t n;
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
return 0;
cpumask_and(mask, cpumask_of_node(node_dev->dev.id), cpu_online_mask);
- n = cpumap_print_to_pagebuf(list, buf, mask);
+ n = cpumap_print_bitmask_to_buf(buf, mask, off, count);
free_cpumask_var(mask);
return n;
}
-static inline ssize_t cpumap_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static BIN_ATTR_RO(cpumap, 0);
+
+static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
{
- return node_read_cpumap(dev, false, buf);
-}
+ struct device *dev = kobj_to_dev(kobj);
+ struct node *node_dev = to_node(dev);
+ cpumask_var_t mask;
+ ssize_t n;
+
+ if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+ return 0;
-static DEVICE_ATTR_RO(cpumap);
+ cpumask_and(mask, cpumask_of_node(node_dev->dev.id), cpu_online_mask);
+ n = cpumap_print_list_to_buf(buf, mask, off, count);
+ free_cpumask_var(mask);
-static inline ssize_t cpulist_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return node_read_cpumap(dev, true, buf);
+ return n;
}
-static DEVICE_ATTR_RO(cpulist);
+static BIN_ATTR_RO(cpulist, 0);
/**
* struct node_access_nodes - Access class device to hold user visible
@@ -75,7 +79,7 @@ static DEVICE_ATTR_RO(cpulist);
struct node_access_nodes {
struct device dev;
struct list_head list_node;
- unsigned access;
+ unsigned int access;
#ifdef CONFIG_HMEM_REPORTING
struct node_hmem_attrs hmem_attrs;
#endif
@@ -122,7 +126,7 @@ static void node_access_release(struct device *dev)
}
static struct node_access_nodes *node_init_node_access(struct node *node,
- unsigned access)
+ unsigned int access)
{
struct node_access_nodes *access_node;
struct device *dev;
@@ -187,7 +191,7 @@ static struct attribute *access_attrs[] = {
* @access: The access class the for the given attributes
*/
void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs,
- unsigned access)
+ unsigned int access)
{
struct node_access_nodes *c;
struct node *node;
@@ -557,15 +561,28 @@ static ssize_t node_read_distance(struct device *dev,
static DEVICE_ATTR(distance, 0444, node_read_distance, NULL);
static struct attribute *node_dev_attrs[] = {
- &dev_attr_cpumap.attr,
- &dev_attr_cpulist.attr,
&dev_attr_meminfo.attr,
&dev_attr_numastat.attr,
&dev_attr_distance.attr,
&dev_attr_vmstat.attr,
NULL
};
-ATTRIBUTE_GROUPS(node_dev);
+
+static struct bin_attribute *node_dev_bin_attrs[] = {
+ &bin_attr_cpumap,
+ &bin_attr_cpulist,
+ NULL
+};
+
+static const struct attribute_group node_dev_group = {
+ .attrs = node_dev_attrs,
+ .bin_attrs = node_dev_bin_attrs
+};
+
+static const struct attribute_group *node_dev_groups[] = {
+ &node_dev_group,
+ NULL
+};
#ifdef CONFIG_HUGETLBFS
/*
@@ -711,7 +728,7 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
*/
int register_memory_node_under_compute_node(unsigned int mem_nid,
unsigned int cpu_nid,
- unsigned access)
+ unsigned int access)
{
struct node *init_node, *targ_node;
struct node_access_nodes *initiator, *target;
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 8640578f45e9..652531f67135 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -642,22 +642,6 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
EXPORT_SYMBOL_GPL(platform_device_add_data);
/**
- * platform_device_add_properties - add built-in properties to a platform device
- * @pdev: platform device to add properties to
- * @properties: null terminated array of properties to add
- *
- * The function will take deep copy of @properties and attach the copy to the
- * platform device. The memory associated with properties will be freed when the
- * platform device is released.
- */
-int platform_device_add_properties(struct platform_device *pdev,
- const struct property_entry *properties)
-{
- return device_add_properties(&pdev->dev, properties);
-}
-EXPORT_SYMBOL_GPL(platform_device_add_properties);
-
-/**
* platform_device_add - add a platform device to device hierarchy
* @pdev: platform device we're adding
*
@@ -842,8 +826,8 @@ struct platform_device *platform_device_register_full(
goto err;
if (pdevinfo->properties) {
- ret = platform_device_add_properties(pdev,
- pdevinfo->properties);
+ ret = device_create_managed_software_node(&pdev->dev,
+ pdevinfo->properties, NULL);
if (ret)
goto err;
}
@@ -1438,7 +1422,7 @@ out:
return ret;
}
-static int platform_remove(struct device *_dev)
+static void platform_remove(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
@@ -1450,8 +1434,6 @@ static int platform_remove(struct device *_dev)
dev_warn(_dev, "remove callback returned a non-zero value. This will be ignored.\n");
}
dev_pm_domain_detach(_dev, true);
-
- return 0;
}
static void platform_shutdown(struct device *_dev)
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 0251f3e6e61d..4110c19c08dc 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -519,6 +519,23 @@ void pm_clk_destroy(struct device *dev)
}
EXPORT_SYMBOL_GPL(pm_clk_destroy);
+static void pm_clk_destroy_action(void *data)
+{
+ pm_clk_destroy(data);
+}
+
+int devm_pm_clk_create(struct device *dev)
+{
+ int ret;
+
+ ret = pm_clk_create(dev);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev, pm_clk_destroy_action, dev);
+}
+EXPORT_SYMBOL_GPL(devm_pm_clk_create);
+
/**
* pm_clk_suspend - Disable clocks in a device's PM clock list.
* @dev: Device to disable the clocks for.
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 8a66eaf731e4..ec94049442b9 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1447,6 +1447,23 @@ void pm_runtime_enable(struct device *dev)
}
EXPORT_SYMBOL_GPL(pm_runtime_enable);
+static void pm_runtime_disable_action(void *data)
+{
+ pm_runtime_disable(data);
+}
+
+/**
+ * devm_pm_runtime_enable - devres-enabled version of pm_runtime_enable.
+ * @dev: Device to handle.
+ */
+int devm_pm_runtime_enable(struct device *dev)
+{
+ pm_runtime_enable(dev);
+
+ return devm_add_action_or_reset(dev, pm_runtime_disable_action, dev);
+}
+EXPORT_SYMBOL_GPL(devm_pm_runtime_enable);
+
/**
* pm_runtime_forbid - Block runtime PM of a device.
* @dev: Device to handle.
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index f0b37c188514..99bda0da23a8 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -1180,7 +1180,7 @@ static const struct file_operations wakeup_sources_stats_fops = {
static int __init wakeup_sources_debugfs_init(void)
{
- debugfs_create_file("wakeup_sources", S_IRUGO, NULL, NULL,
+ debugfs_create_file("wakeup_sources", 0444, NULL, NULL,
&wakeup_sources_stats_fops);
return 0;
}
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 4d254fcc93d1..43c0940643f5 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -21,25 +21,27 @@ static ssize_t name##_show(struct device *dev, \
return sysfs_emit(buf, "%d\n", topology_##name(dev->id)); \
}
-#define define_siblings_show_map(name, mask) \
-static ssize_t name##_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- return cpumap_print_to_pagebuf(false, buf, topology_##mask(dev->id));\
+#define define_siblings_read_func(name, mask) \
+static ssize_t name##_read(struct file *file, struct kobject *kobj, \
+ struct bin_attribute *attr, char *buf, \
+ loff_t off, size_t count) \
+{ \
+ struct device *dev = kobj_to_dev(kobj); \
+ \
+ return cpumap_print_bitmask_to_buf(buf, topology_##mask(dev->id), \
+ off, count); \
+} \
+ \
+static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
+ struct bin_attribute *attr, char *buf, \
+ loff_t off, size_t count) \
+{ \
+ struct device *dev = kobj_to_dev(kobj); \
+ \
+ return cpumap_print_list_to_buf(buf, topology_##mask(dev->id), \
+ off, count); \
}
-#define define_siblings_show_list(name, mask) \
-static ssize_t name##_list_show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return cpumap_print_to_pagebuf(true, buf, topology_##mask(dev->id));\
-}
-
-#define define_siblings_show_func(name, mask) \
- define_siblings_show_map(name, mask); \
- define_siblings_show_list(name, mask)
-
define_id_show_func(physical_package_id);
static DEVICE_ATTR_RO(physical_package_id);
@@ -49,71 +51,80 @@ static DEVICE_ATTR_RO(die_id);
define_id_show_func(core_id);
static DEVICE_ATTR_RO(core_id);
-define_siblings_show_func(thread_siblings, sibling_cpumask);
-static DEVICE_ATTR_RO(thread_siblings);
-static DEVICE_ATTR_RO(thread_siblings_list);
+define_siblings_read_func(thread_siblings, sibling_cpumask);
+static BIN_ATTR_RO(thread_siblings, 0);
+static BIN_ATTR_RO(thread_siblings_list, 0);
-define_siblings_show_func(core_cpus, sibling_cpumask);
-static DEVICE_ATTR_RO(core_cpus);
-static DEVICE_ATTR_RO(core_cpus_list);
+define_siblings_read_func(core_cpus, sibling_cpumask);
+static BIN_ATTR_RO(core_cpus, 0);
+static BIN_ATTR_RO(core_cpus_list, 0);
-define_siblings_show_func(core_siblings, core_cpumask);
-static DEVICE_ATTR_RO(core_siblings);
-static DEVICE_ATTR_RO(core_siblings_list);
+define_siblings_read_func(core_siblings, core_cpumask);
+static BIN_ATTR_RO(core_siblings, 0);
+static BIN_ATTR_RO(core_siblings_list, 0);
-define_siblings_show_func(die_cpus, die_cpumask);
-static DEVICE_ATTR_RO(die_cpus);
-static DEVICE_ATTR_RO(die_cpus_list);
+define_siblings_read_func(die_cpus, die_cpumask);
+static BIN_ATTR_RO(die_cpus, 0);
+static BIN_ATTR_RO(die_cpus_list, 0);
-define_siblings_show_func(package_cpus, core_cpumask);
-static DEVICE_ATTR_RO(package_cpus);
-static DEVICE_ATTR_RO(package_cpus_list);
+define_siblings_read_func(package_cpus, core_cpumask);
+static BIN_ATTR_RO(package_cpus, 0);
+static BIN_ATTR_RO(package_cpus_list, 0);
#ifdef CONFIG_SCHED_BOOK
define_id_show_func(book_id);
static DEVICE_ATTR_RO(book_id);
-define_siblings_show_func(book_siblings, book_cpumask);
-static DEVICE_ATTR_RO(book_siblings);
-static DEVICE_ATTR_RO(book_siblings_list);
+define_siblings_read_func(book_siblings, book_cpumask);
+static BIN_ATTR_RO(book_siblings, 0);
+static BIN_ATTR_RO(book_siblings_list, 0);
#endif
#ifdef CONFIG_SCHED_DRAWER
define_id_show_func(drawer_id);
static DEVICE_ATTR_RO(drawer_id);
-define_siblings_show_func(drawer_siblings, drawer_cpumask);
-static DEVICE_ATTR_RO(drawer_siblings);
-static DEVICE_ATTR_RO(drawer_siblings_list);
+define_siblings_read_func(drawer_siblings, drawer_cpumask);
+static BIN_ATTR_RO(drawer_siblings, 0);
+static BIN_ATTR_RO(drawer_siblings_list, 0);
#endif
+static struct bin_attribute *bin_attrs[] = {
+ &bin_attr_core_cpus,
+ &bin_attr_core_cpus_list,
+ &bin_attr_thread_siblings,
+ &bin_attr_thread_siblings_list,
+ &bin_attr_core_siblings,
+ &bin_attr_core_siblings_list,
+ &bin_attr_die_cpus,
+ &bin_attr_die_cpus_list,
+ &bin_attr_package_cpus,
+ &bin_attr_package_cpus_list,
+#ifdef CONFIG_SCHED_BOOK
+ &bin_attr_book_siblings,
+ &bin_attr_book_siblings_list,
+#endif
+#ifdef CONFIG_SCHED_DRAWER
+ &bin_attr_drawer_siblings,
+ &bin_attr_drawer_siblings_list,
+#endif
+ NULL
+};
+
static struct attribute *default_attrs[] = {
&dev_attr_physical_package_id.attr,
&dev_attr_die_id.attr,
&dev_attr_core_id.attr,
- &dev_attr_thread_siblings.attr,
- &dev_attr_thread_siblings_list.attr,
- &dev_attr_core_cpus.attr,
- &dev_attr_core_cpus_list.attr,
- &dev_attr_core_siblings.attr,
- &dev_attr_core_siblings_list.attr,
- &dev_attr_die_cpus.attr,
- &dev_attr_die_cpus_list.attr,
- &dev_attr_package_cpus.attr,
- &dev_attr_package_cpus_list.attr,
#ifdef CONFIG_SCHED_BOOK
&dev_attr_book_id.attr,
- &dev_attr_book_siblings.attr,
- &dev_attr_book_siblings_list.attr,
#endif
#ifdef CONFIG_SCHED_DRAWER
&dev_attr_drawer_id.attr,
- &dev_attr_drawer_siblings.attr,
- &dev_attr_drawer_siblings_list.attr,
#endif
NULL
};
static const struct attribute_group topology_attr_group = {
.attrs = default_attrs,
+ .bin_attrs = bin_attrs,
.name = "topology"
};
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 1df2b5801c3b..c6d6ba0d00b1 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -27,7 +27,7 @@ static DEFINE_MUTEX(bcma_buses_mutex);
static int bcma_bus_match(struct device *dev, struct device_driver *drv);
static int bcma_device_probe(struct device *dev);
-static int bcma_device_remove(struct device *dev);
+static void bcma_device_remove(struct device *dev);
static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -614,7 +614,7 @@ static int bcma_device_probe(struct device *dev)
return err;
}
-static int bcma_device_remove(struct device *dev)
+static void bcma_device_remove(struct device *dev)
{
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
@@ -623,8 +623,6 @@ static int bcma_device_remove(struct device *dev)
if (adrv->remove)
adrv->remove(core);
put_device(dev);
-
- return 0;
}
static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index fbb3a558139f..ab3e37aa1830 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -74,7 +74,6 @@ config N64CART
config CDROM
tristate
- select BLK_SCSI_REQUEST
config GDROM
tristate "SEGA Dreamcast GD-ROM drive"
@@ -306,7 +305,7 @@ config CDROM_PKTCDVD
tristate "Packet writing on CD/DVD media (DEPRECATED)"
depends on !UML
select CDROM
- select BLK_SCSI_REQUEST
+ select SCSI_COMMON
help
Note: This driver is deprecated and will be removed from the
kernel in the near future!
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index fa1c298a8cfb..7bf4686af774 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -2111,18 +2111,6 @@ int loop_register_transfer(struct loop_func_table *funcs)
return 0;
}
-static int unregister_transfer_cb(int id, void *ptr, void *data)
-{
- struct loop_device *lo = ptr;
- struct loop_func_table *xfer = data;
-
- mutex_lock(&lo->lo_mutex);
- if (lo->lo_encryption == xfer)
- loop_release_xfer(lo);
- mutex_unlock(&lo->lo_mutex);
- return 0;
-}
-
int loop_unregister_transfer(int number)
{
unsigned int n = number;
@@ -2130,9 +2118,20 @@ int loop_unregister_transfer(int number)
if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL)
return -EINVAL;
+ /*
+ * This function is called from only cleanup_cryptoloop().
+ * Given that each loop device that has a transfer enabled holds a
+ * reference to the module implementing it we should never get here
+ * with a transfer that is set (unless forced module unloading is
+ * requested). Thus, check module's refcount and warn if this is
+ * not a clean unloading.
+ */
+#ifdef CONFIG_MODULE_UNLOAD
+ if (xfer->owner && module_refcount(xfer->owner) != -1)
+ pr_err("Danger! Unregistering an in use transfer function.\n");
+#endif
xfer_funcs[n] = NULL;
- idr_for_each(&loop_index_idr, &unregister_transfer_cb, xfer);
return 0;
}
@@ -2323,8 +2322,9 @@ static int loop_add(int i)
} else {
err = idr_alloc(&loop_index_idr, lo, 0, 0, GFP_KERNEL);
}
+ mutex_unlock(&loop_ctl_mutex);
if (err < 0)
- goto out_unlock;
+ goto out_free_dev;
i = err;
err = -ENOMEM;
@@ -2393,15 +2393,19 @@ static int loop_add(int i)
disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->event_flags = DISK_EVENT_FLAG_UEVENT;
sprintf(disk->disk_name, "loop%d", i);
+ /* Make this loop device reachable from pathname. */
add_disk(disk);
+ /* Show this loop device. */
+ mutex_lock(&loop_ctl_mutex);
+ lo->idr_visible = true;
mutex_unlock(&loop_ctl_mutex);
return i;
out_cleanup_tags:
blk_mq_free_tag_set(&lo->tag_set);
out_free_idr:
+ mutex_lock(&loop_ctl_mutex);
idr_remove(&loop_index_idr, i);
-out_unlock:
mutex_unlock(&loop_ctl_mutex);
out_free_dev:
kfree(lo);
@@ -2411,9 +2415,14 @@ out:
static void loop_remove(struct loop_device *lo)
{
+ /* Make this loop device unreachable from pathname. */
del_gendisk(lo->lo_disk);
blk_cleanup_disk(lo->lo_disk);
blk_mq_free_tag_set(&lo->tag_set);
+ mutex_lock(&loop_ctl_mutex);
+ idr_remove(&loop_index_idr, lo->lo_number);
+ mutex_unlock(&loop_ctl_mutex);
+ /* There is no route which can find this loop device. */
mutex_destroy(&lo->lo_mutex);
kfree(lo);
}
@@ -2437,31 +2446,40 @@ static int loop_control_remove(int idx)
return -EINVAL;
}
+ /* Hide this loop device for serialization. */
ret = mutex_lock_killable(&loop_ctl_mutex);
if (ret)
return ret;
-
lo = idr_find(&loop_index_idr, idx);
- if (!lo) {
+ if (!lo || !lo->idr_visible)
ret = -ENODEV;
- goto out_unlock_ctrl;
- }
+ else
+ lo->idr_visible = false;
+ mutex_unlock(&loop_ctl_mutex);
+ if (ret)
+ return ret;
+ /* Check whether this loop device can be removed. */
ret = mutex_lock_killable(&lo->lo_mutex);
if (ret)
- goto out_unlock_ctrl;
+ goto mark_visible;
if (lo->lo_state != Lo_unbound ||
atomic_read(&lo->lo_refcnt) > 0) {
mutex_unlock(&lo->lo_mutex);
ret = -EBUSY;
- goto out_unlock_ctrl;
+ goto mark_visible;
}
+ /* Mark this loop device no longer open()-able. */
lo->lo_state = Lo_deleting;
mutex_unlock(&lo->lo_mutex);
- idr_remove(&loop_index_idr, lo->lo_number);
loop_remove(lo);
-out_unlock_ctrl:
+ return 0;
+
+mark_visible:
+ /* Show this loop device again. */
+ mutex_lock(&loop_ctl_mutex);
+ lo->idr_visible = true;
mutex_unlock(&loop_ctl_mutex);
return ret;
}
@@ -2475,7 +2493,8 @@ static int loop_control_get_free(int idx)
if (ret)
return ret;
idr_for_each_entry(&loop_index_idr, lo, id) {
- if (lo->lo_state == Lo_unbound)
+ /* Hitting a race results in creating a new loop device which is harmless. */
+ if (lo->idr_visible && data_race(lo->lo_state) == Lo_unbound)
goto found;
}
mutex_unlock(&loop_ctl_mutex);
@@ -2591,10 +2610,14 @@ static void __exit loop_exit(void)
unregister_blkdev(LOOP_MAJOR, "loop");
misc_deregister(&loop_misc);
- mutex_lock(&loop_ctl_mutex);
+ /*
+ * There is no need to use loop_ctl_mutex here, for nobody else can
+ * access loop_index_idr when this module is unloading (unless forced
+ * module unloading is requested). If this is not a clean unloading,
+ * we have no means to avoid kernel crash.
+ */
idr_for_each_entry(&loop_index_idr, lo, id)
loop_remove(lo);
- mutex_unlock(&loop_ctl_mutex);
idr_destroy(&loop_index_idr);
}
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index 1988899db63a..04c88dd6eabd 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -68,6 +68,7 @@ struct loop_device {
struct blk_mq_tag_set tag_set;
struct gendisk *lo_disk;
struct mutex lo_mutex;
+ bool idr_visible;
};
struct loop_cmd {
diff --git a/drivers/block/paride/Kconfig b/drivers/block/paride/Kconfig
index 7c6ae1036927..a295634597ba 100644
--- a/drivers/block/paride/Kconfig
+++ b/drivers/block/paride/Kconfig
@@ -27,7 +27,6 @@ config PARIDE_PCD
tristate "Parallel port ATAPI CD-ROMs"
depends on PARIDE
select CDROM
- select BLK_SCSI_REQUEST # only for the generic cdrom code
help
This option enables the high-level driver for ATAPI CD-ROM devices
connected through a parallel port. If you chose to build PARIDE
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 125b22205d38..33eba3df4dd9 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -8,7 +8,6 @@
#define pr_fmt(fmt) "xen-blkback: " fmt
-#include <stdarg.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <xen/events.h>
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 715bfa8aca7f..72902104f111 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -80,6 +80,7 @@ enum blkif_state {
BLKIF_STATE_DISCONNECTED,
BLKIF_STATE_CONNECTED,
BLKIF_STATE_SUSPENDED,
+ BLKIF_STATE_ERROR,
};
struct grant {
@@ -89,6 +90,7 @@ struct grant {
};
enum blk_req_status {
+ REQ_PROCESSING,
REQ_WAITING,
REQ_DONE,
REQ_ERROR,
@@ -530,10 +532,10 @@ static unsigned long blkif_ring_get_request(struct blkfront_ring_info *rinfo,
id = get_id_from_freelist(rinfo);
rinfo->shadow[id].request = req;
- rinfo->shadow[id].status = REQ_WAITING;
+ rinfo->shadow[id].status = REQ_PROCESSING;
rinfo->shadow[id].associated_id = NO_ASSOCIATED_ID;
- (*ring_req)->u.rw.id = id;
+ rinfo->shadow[id].req.u.rw.id = id;
return id;
}
@@ -541,11 +543,12 @@ static unsigned long blkif_ring_get_request(struct blkfront_ring_info *rinfo,
static int blkif_queue_discard_req(struct request *req, struct blkfront_ring_info *rinfo)
{
struct blkfront_info *info = rinfo->dev_info;
- struct blkif_request *ring_req;
+ struct blkif_request *ring_req, *final_ring_req;
unsigned long id;
/* Fill out a communications ring structure. */
- id = blkif_ring_get_request(rinfo, req, &ring_req);
+ id = blkif_ring_get_request(rinfo, req, &final_ring_req);
+ ring_req = &rinfo->shadow[id].req;
ring_req->operation = BLKIF_OP_DISCARD;
ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
@@ -556,8 +559,9 @@ static int blkif_queue_discard_req(struct request *req, struct blkfront_ring_inf
else
ring_req->u.discard.flag = 0;
- /* Keep a private copy so we can reissue requests when recovering. */
- rinfo->shadow[id].req = *ring_req;
+ /* Copy the request to the ring page. */
+ *final_ring_req = *ring_req;
+ rinfo->shadow[id].status = REQ_WAITING;
return 0;
}
@@ -690,6 +694,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
{
struct blkfront_info *info = rinfo->dev_info;
struct blkif_request *ring_req, *extra_ring_req = NULL;
+ struct blkif_request *final_ring_req, *final_extra_ring_req = NULL;
unsigned long id, extra_id = NO_ASSOCIATED_ID;
bool require_extra_req = false;
int i;
@@ -734,7 +739,8 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
}
/* Fill out a communications ring structure. */
- id = blkif_ring_get_request(rinfo, req, &ring_req);
+ id = blkif_ring_get_request(rinfo, req, &final_ring_req);
+ ring_req = &rinfo->shadow[id].req;
num_sg = blk_rq_map_sg(req->q, req, rinfo->shadow[id].sg);
num_grant = 0;
@@ -785,7 +791,9 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
ring_req->u.rw.nr_segments = num_grant;
if (unlikely(require_extra_req)) {
extra_id = blkif_ring_get_request(rinfo, req,
- &extra_ring_req);
+ &final_extra_ring_req);
+ extra_ring_req = &rinfo->shadow[extra_id].req;
+
/*
* Only the first request contains the scatter-gather
* list.
@@ -827,10 +835,13 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
if (setup.segments)
kunmap_atomic(setup.segments);
- /* Keep a private copy so we can reissue requests when recovering. */
- rinfo->shadow[id].req = *ring_req;
- if (unlikely(require_extra_req))
- rinfo->shadow[extra_id].req = *extra_ring_req;
+ /* Copy request(s) to the ring page. */
+ *final_ring_req = *ring_req;
+ rinfo->shadow[id].status = REQ_WAITING;
+ if (unlikely(require_extra_req)) {
+ *final_extra_ring_req = *extra_ring_req;
+ rinfo->shadow[extra_id].status = REQ_WAITING;
+ }
if (new_persistent_gnts)
gnttab_free_grant_references(setup.gref_head);
@@ -1353,8 +1364,8 @@ static enum blk_req_status blkif_rsp_to_req_status(int rsp)
static int blkif_get_final_status(enum blk_req_status s1,
enum blk_req_status s2)
{
- BUG_ON(s1 == REQ_WAITING);
- BUG_ON(s2 == REQ_WAITING);
+ BUG_ON(s1 < REQ_DONE);
+ BUG_ON(s2 < REQ_DONE);
if (s1 == REQ_ERROR || s2 == REQ_ERROR)
return BLKIF_RSP_ERROR;
@@ -1387,7 +1398,7 @@ static bool blkif_completion(unsigned long *id,
s->status = blkif_rsp_to_req_status(bret->status);
/* Wait the second response if not yet here. */
- if (s2->status == REQ_WAITING)
+ if (s2->status < REQ_DONE)
return false;
bret->status = blkif_get_final_status(s->status,
@@ -1495,7 +1506,7 @@ static bool blkif_completion(unsigned long *id,
static irqreturn_t blkif_interrupt(int irq, void *dev_id)
{
struct request *req;
- struct blkif_response *bret;
+ struct blkif_response bret;
RING_IDX i, rp;
unsigned long flags;
struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id;
@@ -1506,54 +1517,76 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
spin_lock_irqsave(&rinfo->ring_lock, flags);
again:
- rp = rinfo->ring.sring->rsp_prod;
- rmb(); /* Ensure we see queued responses up to 'rp'. */
+ rp = READ_ONCE(rinfo->ring.sring->rsp_prod);
+ virt_rmb(); /* Ensure we see queued responses up to 'rp'. */
+ if (RING_RESPONSE_PROD_OVERFLOW(&rinfo->ring, rp)) {
+ pr_alert("%s: illegal number of responses %u\n",
+ info->gd->disk_name, rp - rinfo->ring.rsp_cons);
+ goto err;
+ }
for (i = rinfo->ring.rsp_cons; i != rp; i++) {
unsigned long id;
+ unsigned int op;
+
+ RING_COPY_RESPONSE(&rinfo->ring, i, &bret);
+ id = bret.id;
- bret = RING_GET_RESPONSE(&rinfo->ring, i);
- id = bret->id;
/*
* The backend has messed up and given us an id that we would
* never have given to it (we stamp it up to BLK_RING_SIZE -
* look in get_id_from_freelist.
*/
if (id >= BLK_RING_SIZE(info)) {
- WARN(1, "%s: response to %s has incorrect id (%ld)\n",
- info->gd->disk_name, op_name(bret->operation), id);
- /* We can't safely get the 'struct request' as
- * the id is busted. */
- continue;
+ pr_alert("%s: response has incorrect id (%ld)\n",
+ info->gd->disk_name, id);
+ goto err;
}
+ if (rinfo->shadow[id].status != REQ_WAITING) {
+ pr_alert("%s: response references no pending request\n",
+ info->gd->disk_name);
+ goto err;
+ }
+
+ rinfo->shadow[id].status = REQ_PROCESSING;
req = rinfo->shadow[id].request;
- if (bret->operation != BLKIF_OP_DISCARD) {
+ op = rinfo->shadow[id].req.operation;
+ if (op == BLKIF_OP_INDIRECT)
+ op = rinfo->shadow[id].req.u.indirect.indirect_op;
+ if (bret.operation != op) {
+ pr_alert("%s: response has wrong operation (%u instead of %u)\n",
+ info->gd->disk_name, bret.operation, op);
+ goto err;
+ }
+
+ if (bret.operation != BLKIF_OP_DISCARD) {
/*
* We may need to wait for an extra response if the
* I/O request is split in 2
*/
- if (!blkif_completion(&id, rinfo, bret))
+ if (!blkif_completion(&id, rinfo, &bret))
continue;
}
if (add_id_to_freelist(rinfo, id)) {
WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n",
- info->gd->disk_name, op_name(bret->operation), id);
+ info->gd->disk_name, op_name(bret.operation), id);
continue;
}
- if (bret->status == BLKIF_RSP_OKAY)
+ if (bret.status == BLKIF_RSP_OKAY)
blkif_req(req)->error = BLK_STS_OK;
else
blkif_req(req)->error = BLK_STS_IOERR;
- switch (bret->operation) {
+ switch (bret.operation) {
case BLKIF_OP_DISCARD:
- if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+ if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
struct request_queue *rq = info->rq;
- printk(KERN_WARNING "blkfront: %s: %s op failed\n",
- info->gd->disk_name, op_name(bret->operation));
+
+ pr_warn_ratelimited("blkfront: %s: %s op failed\n",
+ info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP;
info->feature_discard = 0;
info->feature_secdiscard = 0;
@@ -1563,15 +1596,15 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
break;
case BLKIF_OP_FLUSH_DISKCACHE:
case BLKIF_OP_WRITE_BARRIER:
- if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
- printk(KERN_WARNING "blkfront: %s: %s op failed\n",
- info->gd->disk_name, op_name(bret->operation));
+ if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
+ pr_warn_ratelimited("blkfront: %s: %s op failed\n",
+ info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP;
}
- if (unlikely(bret->status == BLKIF_RSP_ERROR &&
+ if (unlikely(bret.status == BLKIF_RSP_ERROR &&
rinfo->shadow[id].req.u.rw.nr_segments == 0)) {
- printk(KERN_WARNING "blkfront: %s: empty %s op failed\n",
- info->gd->disk_name, op_name(bret->operation));
+ pr_warn_ratelimited("blkfront: %s: empty %s op failed\n",
+ info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP;
}
if (unlikely(blkif_req(req)->error)) {
@@ -1584,9 +1617,10 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
fallthrough;
case BLKIF_OP_READ:
case BLKIF_OP_WRITE:
- if (unlikely(bret->status != BLKIF_RSP_OKAY))
- dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
- "request: %x\n", bret->status);
+ if (unlikely(bret.status != BLKIF_RSP_OKAY))
+ dev_dbg_ratelimited(&info->xbdev->dev,
+ "Bad return from blkdev data request: %#x\n",
+ bret.status);
break;
default:
@@ -1612,6 +1646,14 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
return IRQ_HANDLED;
+
+ err:
+ info->connected = BLKIF_STATE_ERROR;
+
+ spin_unlock_irqrestore(&rinfo->ring_lock, flags);
+
+ pr_alert("%s disabled for further use\n", info->gd->disk_name);
+ return IRQ_HANDLED;
}
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index e7f7eee6ee9a..a5b96f3aad67 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -95,6 +95,17 @@ config IMX_WEIM
The WEIM(Wireless External Interface Module) works like a bus.
You can attach many different devices on it, such as NOR, onenand.
+config INTEL_IXP4XX_EB
+ bool "Intel IXP4xx expansion bus interface driver"
+ depends on HAS_IOMEM
+ depends on ARCH_IXP4XX || COMPILE_TEST
+ default ARCH_IXP4XX
+ select MFD_SYSCON
+ help
+ Driver for the Intel IXP4xx expansion bus interface. The driver is
+ needed to set up various chip select configuration parameters before
+ devices on the expansion bus can be discovered.
+
config MIPS_CDMM
bool "MIPS Common Device Memory Map (CDMM) Driver"
depends on CPU_MIPSR2 || CPU_MIPSR5
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 397e35392bff..1c29c5e8ffb8 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
obj-$(CONFIG_BT1_APB) += bt1-apb.o
obj-$(CONFIG_BT1_AXI) += bt1-axi.o
obj-$(CONFIG_IMX_WEIM) += imx-weim.o
+obj-$(CONFIG_INTEL_IXP4XX_EB) += intel-ixp4xx-eb.o
obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index b3691de8ac06..8fd4a356a86e 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -63,11 +63,14 @@ struct fsl_mc_addr_translation_range {
#define FSL_MC_GCR1 0x0
#define GCR1_P1_STOP BIT(31)
+#define GCR1_P2_STOP BIT(30)
#define FSL_MC_FAPR 0x28
#define MC_FAPR_PL BIT(18)
#define MC_FAPR_BMT BIT(17)
+static phys_addr_t mc_portal_base_phys_addr;
+
/**
* fsl_mc_bus_match - device to driver matching callback
* @dev: the fsl-mc device to match against
@@ -220,7 +223,7 @@ static int scan_fsl_mc_bus(struct device *dev, void *data)
root_mc_dev = to_fsl_mc_device(dev);
root_mc_bus = to_fsl_mc_bus(root_mc_dev);
mutex_lock(&root_mc_bus->scan_mutex);
- dprc_scan_objects(root_mc_dev, NULL);
+ dprc_scan_objects(root_mc_dev, false);
mutex_unlock(&root_mc_bus->scan_mutex);
exit:
@@ -703,14 +706,30 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
* If base address is in the region_desc use it otherwise
* revert to old mechanism
*/
- if (region_desc.base_address)
+ if (region_desc.base_address) {
regions[i].start = region_desc.base_address +
region_desc.base_offset;
- else
+ } else {
error = translate_mc_addr(mc_dev, mc_region_type,
region_desc.base_offset,
&regions[i].start);
+ /*
+ * Some versions of the MC firmware wrongly report
+ * 0 for register base address of the DPMCP associated
+ * with child DPRC objects thus rendering them unusable.
+ * This is particularly troublesome in ACPI boot
+ * scenarios where the legacy way of extracting this
+ * base address from the device tree does not apply.
+ * Given that DPMCPs share the same base address,
+ * workaround this by using the base address extracted
+ * from the root DPRC container.
+ */
+ if (is_fsl_mc_bus_dprc(mc_dev) &&
+ regions[i].start == region_desc.base_offset)
+ regions[i].start += mc_portal_base_phys_addr;
+ }
+
if (error < 0) {
dev_err(parent_dev,
"Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
@@ -895,6 +914,8 @@ error_cleanup_dev:
}
EXPORT_SYMBOL_GPL(fsl_mc_device_add);
+static struct notifier_block fsl_mc_nb;
+
/**
* fsl_mc_device_remove - Remove an fsl-mc device from being visible to
* Linux
@@ -949,10 +970,28 @@ struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev,
* We know that the device has an endpoint because we verified by
* interrogating the firmware. This is the case when the device was not
* yet discovered by the fsl-mc bus, thus the lookup returned NULL.
- * Differentiate this case by returning EPROBE_DEFER.
+ * Force a rescan of the devices in this container and retry the lookup.
+ */
+ if (!endpoint) {
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
+
+ if (mutex_trylock(&mc_bus->scan_mutex)) {
+ err = dprc_scan_objects(mc_bus_dev, true);
+ mutex_unlock(&mc_bus->scan_mutex);
+ }
+
+ if (err < 0)
+ return ERR_PTR(err);
+ }
+
+ endpoint = fsl_mc_device_lookup(&endpoint_desc, mc_bus_dev);
+ /*
+ * This means that the endpoint might reside in a different isolation
+ * context (DPRC/container). Not much to do, so return a permssion
+ * error.
*/
if (!endpoint)
- return ERR_PTR(-EPROBE_DEFER);
+ return ERR_PTR(-EPERM);
return endpoint;
}
@@ -1091,17 +1130,6 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
}
if (mc->fsl_mc_regs) {
- /*
- * Some bootloaders pause the MC firmware before booting the
- * kernel so that MC will not cause faults as soon as the
- * SMMU probes due to the fact that there's no configuration
- * in place for MC.
- * At this point MC should have all its SMMU setup done so make
- * sure it is resumed.
- */
- writel(readl(mc->fsl_mc_regs + FSL_MC_GCR1) & (~GCR1_P1_STOP),
- mc->fsl_mc_regs + FSL_MC_GCR1);
-
if (IS_ENABLED(CONFIG_ACPI) && !dev_of_node(&pdev->dev)) {
mc_stream_id = readl(mc->fsl_mc_regs + FSL_MC_FAPR);
/*
@@ -1115,11 +1143,25 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
error = acpi_dma_configure_id(&pdev->dev,
DEV_DMA_COHERENT,
&mc_stream_id);
+ if (error == -EPROBE_DEFER)
+ return error;
if (error)
dev_warn(&pdev->dev,
"failed to configure dma: %d.\n",
error);
}
+
+ /*
+ * Some bootloaders pause the MC firmware before booting the
+ * kernel so that MC will not cause faults as soon as the
+ * SMMU probes due to the fact that there's no configuration
+ * in place for MC.
+ * At this point MC should have all its SMMU setup done so make
+ * sure it is resumed.
+ */
+ writel(readl(mc->fsl_mc_regs + FSL_MC_GCR1) &
+ (~(GCR1_P1_STOP | GCR1_P2_STOP)),
+ mc->fsl_mc_regs + FSL_MC_GCR1);
}
/*
@@ -1128,6 +1170,8 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mc_portal_phys_addr = plat_res->start;
mc_portal_size = resource_size(plat_res);
+ mc_portal_base_phys_addr = mc_portal_phys_addr & ~0x3ffffff;
+
error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
mc_portal_size, NULL,
FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
@@ -1201,9 +1245,26 @@ static int fsl_mc_bus_remove(struct platform_device *pdev)
fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
mc->root_mc_bus_dev->mc_io = NULL;
+ bus_unregister_notifier(&fsl_mc_bus_type, &fsl_mc_nb);
+
+ if (mc->fsl_mc_regs) {
+ /*
+ * Pause the MC firmware so that it doesn't crash in certain
+ * scenarios, such as kexec.
+ */
+ writel(readl(mc->fsl_mc_regs + FSL_MC_GCR1) |
+ (GCR1_P1_STOP | GCR1_P2_STOP),
+ mc->fsl_mc_regs + FSL_MC_GCR1);
+ }
+
return 0;
}
+static void fsl_mc_bus_shutdown(struct platform_device *pdev)
+{
+ fsl_mc_bus_remove(pdev);
+}
+
static const struct of_device_id fsl_mc_bus_match_table[] = {
{.compatible = "fsl,qoriq-mc",},
{},
@@ -1226,6 +1287,45 @@ static struct platform_driver fsl_mc_bus_driver = {
},
.probe = fsl_mc_bus_probe,
.remove = fsl_mc_bus_remove,
+ .shutdown = fsl_mc_bus_shutdown,
+};
+
+static int fsl_mc_bus_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct device *dev = data;
+ struct resource *res;
+ void __iomem *fsl_mc_regs;
+
+ if (action != BUS_NOTIFY_ADD_DEVICE)
+ return 0;
+
+ if (!of_match_device(fsl_mc_bus_match_table, dev) &&
+ !acpi_match_device(fsl_mc_bus_acpi_match_table, dev))
+ return 0;
+
+ res = platform_get_resource(to_platform_device(dev), IORESOURCE_MEM, 1);
+ if (!res)
+ return 0;
+
+ fsl_mc_regs = ioremap(res->start, resource_size(res));
+ if (!fsl_mc_regs)
+ return 0;
+
+ /*
+ * Make sure that the MC firmware is paused before the IOMMU setup for
+ * it is done or otherwise the firmware will crash right after the SMMU
+ * gets probed and enabled.
+ */
+ writel(readl(fsl_mc_regs + FSL_MC_GCR1) | (GCR1_P1_STOP | GCR1_P2_STOP),
+ fsl_mc_regs + FSL_MC_GCR1);
+ iounmap(fsl_mc_regs);
+
+ return 0;
+}
+
+static struct notifier_block fsl_mc_nb = {
+ .notifier_call = fsl_mc_bus_notifier,
};
static int __init fsl_mc_bus_driver_init(void)
@@ -1252,7 +1352,7 @@ static int __init fsl_mc_bus_driver_init(void)
if (error < 0)
goto error_cleanup_dprc_driver;
- return 0;
+ return bus_register_notifier(&platform_bus_type, &fsl_mc_nb);
error_cleanup_dprc_driver:
dprc_driver_exit();
diff --git a/drivers/bus/intel-ixp4xx-eb.c b/drivers/bus/intel-ixp4xx-eb.c
new file mode 100644
index 000000000000..a4388440aca7
--- /dev/null
+++ b/drivers/bus/intel-ixp4xx-eb.c
@@ -0,0 +1,429 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel IXP4xx Expansion Bus Controller
+ * Copyright (C) 2021 Linaro Ltd.
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/log2.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define IXP4XX_EXP_NUM_CS 8
+
+#define IXP4XX_EXP_TIMING_CS0 0x00
+#define IXP4XX_EXP_TIMING_CS1 0x04
+#define IXP4XX_EXP_TIMING_CS2 0x08
+#define IXP4XX_EXP_TIMING_CS3 0x0c
+#define IXP4XX_EXP_TIMING_CS4 0x10
+#define IXP4XX_EXP_TIMING_CS5 0x14
+#define IXP4XX_EXP_TIMING_CS6 0x18
+#define IXP4XX_EXP_TIMING_CS7 0x1c
+
+/* Bits inside each CS timing register */
+#define IXP4XX_EXP_TIMING_STRIDE 0x04
+#define IXP4XX_EXP_CS_EN BIT(31)
+#define IXP456_EXP_PAR_EN BIT(30) /* Only on IXP45x and IXP46x */
+#define IXP4XX_EXP_T1_MASK GENMASK(28, 27)
+#define IXP4XX_EXP_T1_SHIFT 28
+#define IXP4XX_EXP_T2_MASK GENMASK(27, 26)
+#define IXP4XX_EXP_T2_SHIFT 26
+#define IXP4XX_EXP_T3_MASK GENMASK(25, 22)
+#define IXP4XX_EXP_T3_SHIFT 22
+#define IXP4XX_EXP_T4_MASK GENMASK(21, 20)
+#define IXP4XX_EXP_T4_SHIFT 20
+#define IXP4XX_EXP_T5_MASK GENMASK(19, 16)
+#define IXP4XX_EXP_T5_SHIFT 16
+#define IXP4XX_EXP_CYC_TYPE_MASK GENMASK(15, 14)
+#define IXP4XX_EXP_CYC_TYPE_SHIFT 14
+#define IXP4XX_EXP_SIZE_MASK GENMASK(13, 10)
+#define IXP4XX_EXP_SIZE_SHIFT 10
+#define IXP4XX_EXP_CNFG_0 BIT(9) /* Always zero */
+#define IXP43X_EXP_SYNC_INTEL BIT(8) /* Only on IXP43x */
+#define IXP43X_EXP_EXP_CHIP BIT(7) /* Only on IXP43x */
+#define IXP4XX_EXP_BYTE_RD16 BIT(6)
+#define IXP4XX_EXP_HRDY_POL BIT(5) /* Only on IXP42x */
+#define IXP4XX_EXP_MUX_EN BIT(4)
+#define IXP4XX_EXP_SPLT_EN BIT(3)
+#define IXP4XX_EXP_WORD BIT(2) /* Always zero */
+#define IXP4XX_EXP_WR_EN BIT(1)
+#define IXP4XX_EXP_BYTE_EN BIT(0)
+#define IXP42X_RESERVED (BIT(30)|IXP4XX_EXP_CNFG_0|BIT(8)|BIT(7)|IXP4XX_EXP_WORD)
+#define IXP43X_RESERVED (BIT(30)|IXP4XX_EXP_CNFG_0|BIT(5)|IXP4XX_EXP_WORD)
+
+#define IXP4XX_EXP_CNFG0 0x20
+#define IXP4XX_EXP_CNFG0_MEM_MAP BIT(31)
+#define IXP4XX_EXP_CNFG1 0x24
+
+#define IXP4XX_EXP_BOOT_BASE 0x00000000
+#define IXP4XX_EXP_NORMAL_BASE 0x50000000
+#define IXP4XX_EXP_STRIDE 0x01000000
+
+/* Fuses on the IXP43x */
+#define IXP43X_EXP_UNIT_FUSE_RESET 0x28
+#define IXP43x_EXP_FUSE_SPEED_MASK GENMASK(23, 22)
+
+/* Number of device tree values in "reg" */
+#define IXP4XX_OF_REG_SIZE 3
+
+struct ixp4xx_eb {
+ struct device *dev;
+ struct regmap *rmap;
+ u32 bus_base;
+ bool is_42x;
+ bool is_43x;
+};
+
+struct ixp4xx_exp_tim_prop {
+ const char *prop;
+ u32 max;
+ u32 mask;
+ u16 shift;
+};
+
+static const struct ixp4xx_exp_tim_prop ixp4xx_exp_tim_props[] = {
+ {
+ .prop = "intel,ixp4xx-eb-t1",
+ .max = 3,
+ .mask = IXP4XX_EXP_T1_MASK,
+ .shift = IXP4XX_EXP_T1_SHIFT,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-t2",
+ .max = 3,
+ .mask = IXP4XX_EXP_T2_MASK,
+ .shift = IXP4XX_EXP_T2_SHIFT,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-t3",
+ .max = 15,
+ .mask = IXP4XX_EXP_T3_MASK,
+ .shift = IXP4XX_EXP_T3_SHIFT,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-t4",
+ .max = 3,
+ .mask = IXP4XX_EXP_T4_MASK,
+ .shift = IXP4XX_EXP_T4_SHIFT,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-t5",
+ .max = 15,
+ .mask = IXP4XX_EXP_T5_MASK,
+ .shift = IXP4XX_EXP_T5_SHIFT,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-byte-access-on-halfword",
+ .max = 1,
+ .mask = IXP4XX_EXP_BYTE_RD16,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-hpi-hrdy-pol-high",
+ .max = 1,
+ .mask = IXP4XX_EXP_HRDY_POL,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-mux-address-and-data",
+ .max = 1,
+ .mask = IXP4XX_EXP_MUX_EN,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-ahb-split-transfers",
+ .max = 1,
+ .mask = IXP4XX_EXP_SPLT_EN,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-write-enable",
+ .max = 1,
+ .mask = IXP4XX_EXP_WR_EN,
+ },
+ {
+ .prop = "intel,ixp4xx-eb-byte-access",
+ .max = 1,
+ .mask = IXP4XX_EXP_BYTE_EN,
+ },
+};
+
+static void ixp4xx_exp_setup_chipselect(struct ixp4xx_eb *eb,
+ struct device_node *np,
+ u32 cs_index,
+ u32 cs_size)
+{
+ u32 cs_cfg;
+ u32 val;
+ u32 cur_cssize;
+ u32 cs_order;
+ int ret;
+ int i;
+
+ if (eb->is_42x && (cs_index > 7)) {
+ dev_err(eb->dev,
+ "invalid chipselect %u, we only support 0-7\n",
+ cs_index);
+ return;
+ }
+ if (eb->is_43x && (cs_index > 3)) {
+ dev_err(eb->dev,
+ "invalid chipselect %u, we only support 0-3\n",
+ cs_index);
+ return;
+ }
+
+ /* Several chip selects can be joined into one device */
+ if (cs_size > IXP4XX_EXP_STRIDE)
+ cur_cssize = IXP4XX_EXP_STRIDE;
+ else
+ cur_cssize = cs_size;
+
+
+ /*
+ * The following will read/modify/write the configuration for one
+ * chipselect, attempting to leave the boot defaults in place unless
+ * something is explicitly defined.
+ */
+ regmap_read(eb->rmap, IXP4XX_EXP_TIMING_CS0 +
+ IXP4XX_EXP_TIMING_STRIDE * cs_index, &cs_cfg);
+ dev_info(eb->dev, "CS%d at %#08x, size %#08x, config before: %#08x\n",
+ cs_index, eb->bus_base + IXP4XX_EXP_STRIDE * cs_index,
+ cur_cssize, cs_cfg);
+
+ /* Size set-up first align to 2^9 .. 2^24 */
+ cur_cssize = roundup_pow_of_two(cur_cssize);
+ if (cur_cssize < 512)
+ cur_cssize = 512;
+ cs_order = ilog2(cur_cssize);
+ if (cs_order < 9 || cs_order > 24) {
+ dev_err(eb->dev, "illegal size order %d\n", cs_order);
+ return;
+ }
+ dev_dbg(eb->dev, "CS%d size order: %d\n", cs_index, cs_order);
+ cs_cfg &= ~(IXP4XX_EXP_SIZE_MASK);
+ cs_cfg |= ((cs_order - 9) << IXP4XX_EXP_SIZE_SHIFT);
+
+ for (i = 0; i < ARRAY_SIZE(ixp4xx_exp_tim_props); i++) {
+ const struct ixp4xx_exp_tim_prop *ip = &ixp4xx_exp_tim_props[i];
+
+ /* All are regular u32 values */
+ ret = of_property_read_u32(np, ip->prop, &val);
+ if (ret)
+ continue;
+
+ /* Handle bools (single bits) first */
+ if (ip->max == 1) {
+ if (val)
+ cs_cfg |= ip->mask;
+ else
+ cs_cfg &= ~ip->mask;
+ dev_info(eb->dev, "CS%d %s %s\n", cs_index,
+ val ? "enabled" : "disabled",
+ ip->prop);
+ continue;
+ }
+
+ if (val > ip->max) {
+ dev_err(eb->dev,
+ "CS%d too high value for %s: %u, capped at %u\n",
+ cs_index, ip->prop, val, ip->max);
+ val = ip->max;
+ }
+ /* This assumes max value fills all the assigned bits (and it does) */
+ cs_cfg &= ~ip->mask;
+ cs_cfg |= (val << ip->shift);
+ dev_info(eb->dev, "CS%d set %s to %u\n", cs_index, ip->prop, val);
+ }
+
+ ret = of_property_read_u32(np, "intel,ixp4xx-eb-cycle-type", &val);
+ if (!ret) {
+ if (val > 3) {
+ dev_err(eb->dev, "illegal cycle type %d\n", val);
+ return;
+ }
+ dev_info(eb->dev, "CS%d set cycle type %d\n", cs_index, val);
+ cs_cfg &= ~IXP4XX_EXP_CYC_TYPE_MASK;
+ cs_cfg |= val << IXP4XX_EXP_CYC_TYPE_SHIFT;
+ }
+
+ if (eb->is_42x)
+ cs_cfg &= ~IXP42X_RESERVED;
+ if (eb->is_43x) {
+ cs_cfg &= ~IXP43X_RESERVED;
+ /*
+ * This bit for Intel strata flash is currently unused, but let's
+ * report it if we find one.
+ */
+ if (cs_cfg & IXP43X_EXP_SYNC_INTEL)
+ dev_info(eb->dev, "claims to be Intel strata flash\n");
+ }
+ cs_cfg |= IXP4XX_EXP_CS_EN;
+
+ regmap_write(eb->rmap,
+ IXP4XX_EXP_TIMING_CS0 + IXP4XX_EXP_TIMING_STRIDE * cs_index,
+ cs_cfg);
+ dev_info(eb->dev, "CS%d wrote %#08x into CS config\n", cs_index, cs_cfg);
+
+ /*
+ * If several chip selects are joined together into one big
+ * device area, we call ourselves recursively for each successive
+ * chip select. For a 32MB flash chip this results in two calls
+ * for example.
+ */
+ if (cs_size > IXP4XX_EXP_STRIDE)
+ ixp4xx_exp_setup_chipselect(eb, np,
+ cs_index + 1,
+ cs_size - IXP4XX_EXP_STRIDE);
+}
+
+static void ixp4xx_exp_setup_child(struct ixp4xx_eb *eb,
+ struct device_node *np)
+{
+ u32 cs_sizes[IXP4XX_EXP_NUM_CS];
+ int num_regs;
+ u32 csindex;
+ u32 cssize;
+ int ret;
+ int i;
+
+ num_regs = of_property_count_elems_of_size(np, "reg", IXP4XX_OF_REG_SIZE);
+ if (num_regs <= 0)
+ return;
+ dev_dbg(eb->dev, "child %s has %d register sets\n",
+ of_node_full_name(np), num_regs);
+
+ for (csindex = 0; csindex < IXP4XX_EXP_NUM_CS; csindex++)
+ cs_sizes[csindex] = 0;
+
+ for (i = 0; i < num_regs; i++) {
+ u32 rbase, rsize;
+
+ ret = of_property_read_u32_index(np, "reg",
+ i * IXP4XX_OF_REG_SIZE, &csindex);
+ if (ret)
+ break;
+ ret = of_property_read_u32_index(np, "reg",
+ i * IXP4XX_OF_REG_SIZE + 1, &rbase);
+ if (ret)
+ break;
+ ret = of_property_read_u32_index(np, "reg",
+ i * IXP4XX_OF_REG_SIZE + 2, &rsize);
+ if (ret)
+ break;
+
+ if (csindex >= IXP4XX_EXP_NUM_CS) {
+ dev_err(eb->dev, "illegal CS %d\n", csindex);
+ continue;
+ }
+ /*
+ * The memory window always starts from CS base so we need to add
+ * the start and size to get to the size from the start of the CS
+ * base. For example if CS0 is at 0x50000000 and the reg is
+ * <0 0xe40000 0x40000> the size is e80000.
+ *
+ * Roof this if we have several regs setting the same CS.
+ */
+ cssize = rbase + rsize;
+ dev_dbg(eb->dev, "CS%d size %#08x\n", csindex, cssize);
+ if (cs_sizes[csindex] < cssize)
+ cs_sizes[csindex] = cssize;
+ }
+
+ for (csindex = 0; csindex < IXP4XX_EXP_NUM_CS; csindex++) {
+ cssize = cs_sizes[csindex];
+ if (!cssize)
+ continue;
+ /* Just this one, so set it up and return */
+ ixp4xx_exp_setup_chipselect(eb, np, csindex, cssize);
+ }
+}
+
+static int ixp4xx_exp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct ixp4xx_eb *eb;
+ struct device_node *child;
+ bool have_children = false;
+ u32 val;
+ int ret;
+
+ eb = devm_kzalloc(dev, sizeof(*eb), GFP_KERNEL);
+ if (!eb)
+ return -ENOMEM;
+
+ eb->dev = dev;
+ eb->is_42x = of_device_is_compatible(np, "intel,ixp42x-expansion-bus-controller");
+ eb->is_43x = of_device_is_compatible(np, "intel,ixp43x-expansion-bus-controller");
+
+ eb->rmap = syscon_node_to_regmap(np);
+ if (IS_ERR(eb->rmap))
+ return dev_err_probe(dev, PTR_ERR(eb->rmap), "no regmap\n");
+
+ /* We check that the regmap work only on first read */
+ ret = regmap_read(eb->rmap, IXP4XX_EXP_CNFG0, &val);
+ if (ret)
+ return dev_err_probe(dev, ret, "cannot read regmap\n");
+ if (val & IXP4XX_EXP_CNFG0_MEM_MAP)
+ eb->bus_base = IXP4XX_EXP_BOOT_BASE;
+ else
+ eb->bus_base = IXP4XX_EXP_NORMAL_BASE;
+ dev_info(dev, "expansion bus at %08x\n", eb->bus_base);
+
+ if (eb->is_43x) {
+ /* Check some fuses */
+ regmap_read(eb->rmap, IXP43X_EXP_UNIT_FUSE_RESET, &val);
+ switch (FIELD_GET(IXP43x_EXP_FUSE_SPEED_MASK, val)) {
+ case 0:
+ dev_info(dev, "IXP43x at 533 MHz\n");
+ break;
+ case 1:
+ dev_info(dev, "IXP43x at 400 MHz\n");
+ break;
+ case 2:
+ dev_info(dev, "IXP43x at 667 MHz\n");
+ break;
+ default:
+ dev_info(dev, "IXP43x unknown speed\n");
+ break;
+ }
+ }
+
+ /* Walk over the child nodes and see what chipselects we use */
+ for_each_available_child_of_node(np, child) {
+ ixp4xx_exp_setup_child(eb, child);
+ /* We have at least one child */
+ have_children = true;
+ }
+
+ if (have_children)
+ return of_platform_default_populate(np, NULL, dev);
+
+ return 0;
+}
+
+static const struct of_device_id ixp4xx_exp_of_match[] = {
+ { .compatible = "intel,ixp42x-expansion-bus-controller", },
+ { .compatible = "intel,ixp43x-expansion-bus-controller", },
+ { .compatible = "intel,ixp45x-expansion-bus-controller", },
+ { .compatible = "intel,ixp46x-expansion-bus-controller", },
+ { }
+};
+
+static struct platform_driver ixp4xx_exp_driver = {
+ .probe = ixp4xx_exp_probe,
+ .driver = {
+ .name = "intel-extbus",
+ .of_match_table = ixp4xx_exp_of_match,
+ },
+};
+module_platform_driver(ixp4xx_exp_driver);
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("Intel IXP4xx external bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/bus/mhi/core/boot.c b/drivers/bus/mhi/core/boot.c
index 8100cf51cd09..0a972620a403 100644
--- a/drivers/bus/mhi/core/boot.c
+++ b/drivers/bus/mhi/core/boot.c
@@ -302,8 +302,8 @@ void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl,
struct mhi_buf *mhi_buf = image_info->mhi_buf;
for (i = 0; i < image_info->entries; i++, mhi_buf++)
- mhi_free_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf,
- mhi_buf->dma_addr);
+ dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len,
+ mhi_buf->buf, mhi_buf->dma_addr);
kfree(image_info->mhi_buf);
kfree(image_info);
@@ -339,8 +339,8 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
vec_size = sizeof(struct bhi_vec_entry) * i;
mhi_buf->len = vec_size;
- mhi_buf->buf = mhi_alloc_coherent(mhi_cntrl, vec_size,
- &mhi_buf->dma_addr,
+ mhi_buf->buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev,
+ vec_size, &mhi_buf->dma_addr,
GFP_KERNEL);
if (!mhi_buf->buf)
goto error_alloc_segment;
@@ -354,8 +354,8 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
error_alloc_segment:
for (--i, --mhi_buf; i >= 0; i--, mhi_buf--)
- mhi_free_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf,
- mhi_buf->dma_addr);
+ dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len,
+ mhi_buf->buf, mhi_buf->dma_addr);
error_alloc_mhi_buf:
kfree(img_info);
@@ -442,7 +442,8 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
if (size > firmware->size)
size = firmware->size;
- buf = mhi_alloc_coherent(mhi_cntrl, size, &dma_addr, GFP_KERNEL);
+ buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev, size, &dma_addr,
+ GFP_KERNEL);
if (!buf) {
release_firmware(firmware);
goto error_fw_load;
@@ -451,7 +452,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
/* Download image using BHI */
memcpy(buf, firmware->data, size);
ret = mhi_fw_load_bhi(mhi_cntrl, dma_addr, size);
- mhi_free_coherent(mhi_cntrl, size, buf, dma_addr);
+ dma_free_coherent(mhi_cntrl->cntrl_dev, size, buf, dma_addr);
/* Error or in EDL mode, we're done */
if (ret) {
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index c81b377fca8f..5aaca6d0f52b 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -129,7 +129,7 @@ static int mhi_alloc_aligned_ring(struct mhi_controller *mhi_cntrl,
u64 len)
{
ring->alloc_size = len + (len - 1);
- ring->pre_aligned = mhi_alloc_coherent(mhi_cntrl, ring->alloc_size,
+ ring->pre_aligned = dma_alloc_coherent(mhi_cntrl->cntrl_dev, ring->alloc_size,
&ring->dma_handle, GFP_KERNEL);
if (!ring->pre_aligned)
return -ENOMEM;
@@ -221,13 +221,13 @@ void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl)
mhi_cmd = mhi_cntrl->mhi_cmd;
for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++) {
ring = &mhi_cmd->ring;
- mhi_free_coherent(mhi_cntrl, ring->alloc_size,
+ dma_free_coherent(mhi_cntrl->cntrl_dev, ring->alloc_size,
ring->pre_aligned, ring->dma_handle);
ring->base = NULL;
ring->iommu_base = 0;
}
- mhi_free_coherent(mhi_cntrl,
+ dma_free_coherent(mhi_cntrl->cntrl_dev,
sizeof(*mhi_ctxt->cmd_ctxt) * NR_OF_CMD_RINGS,
mhi_ctxt->cmd_ctxt, mhi_ctxt->cmd_ctxt_addr);
@@ -237,17 +237,17 @@ void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl)
continue;
ring = &mhi_event->ring;
- mhi_free_coherent(mhi_cntrl, ring->alloc_size,
+ dma_free_coherent(mhi_cntrl->cntrl_dev, ring->alloc_size,
ring->pre_aligned, ring->dma_handle);
ring->base = NULL;
ring->iommu_base = 0;
}
- mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->er_ctxt) *
+ dma_free_coherent(mhi_cntrl->cntrl_dev, sizeof(*mhi_ctxt->er_ctxt) *
mhi_cntrl->total_ev_rings, mhi_ctxt->er_ctxt,
mhi_ctxt->er_ctxt_addr);
- mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->chan_ctxt) *
+ dma_free_coherent(mhi_cntrl->cntrl_dev, sizeof(*mhi_ctxt->chan_ctxt) *
mhi_cntrl->max_chan, mhi_ctxt->chan_ctxt,
mhi_ctxt->chan_ctxt_addr);
@@ -275,7 +275,7 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
return -ENOMEM;
/* Setup channel ctxt */
- mhi_ctxt->chan_ctxt = mhi_alloc_coherent(mhi_cntrl,
+ mhi_ctxt->chan_ctxt = dma_alloc_coherent(mhi_cntrl->cntrl_dev,
sizeof(*mhi_ctxt->chan_ctxt) *
mhi_cntrl->max_chan,
&mhi_ctxt->chan_ctxt_addr,
@@ -307,7 +307,7 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
}
/* Setup event context */
- mhi_ctxt->er_ctxt = mhi_alloc_coherent(mhi_cntrl,
+ mhi_ctxt->er_ctxt = dma_alloc_coherent(mhi_cntrl->cntrl_dev,
sizeof(*mhi_ctxt->er_ctxt) *
mhi_cntrl->total_ev_rings,
&mhi_ctxt->er_ctxt_addr,
@@ -354,7 +354,7 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
/* Setup cmd context */
ret = -ENOMEM;
- mhi_ctxt->cmd_ctxt = mhi_alloc_coherent(mhi_cntrl,
+ mhi_ctxt->cmd_ctxt = dma_alloc_coherent(mhi_cntrl->cntrl_dev,
sizeof(*mhi_ctxt->cmd_ctxt) *
NR_OF_CMD_RINGS,
&mhi_ctxt->cmd_ctxt_addr,
@@ -389,10 +389,10 @@ error_alloc_cmd:
for (--i, --mhi_cmd; i >= 0; i--, mhi_cmd--) {
struct mhi_ring *ring = &mhi_cmd->ring;
- mhi_free_coherent(mhi_cntrl, ring->alloc_size,
+ dma_free_coherent(mhi_cntrl->cntrl_dev, ring->alloc_size,
ring->pre_aligned, ring->dma_handle);
}
- mhi_free_coherent(mhi_cntrl,
+ dma_free_coherent(mhi_cntrl->cntrl_dev,
sizeof(*mhi_ctxt->cmd_ctxt) * NR_OF_CMD_RINGS,
mhi_ctxt->cmd_ctxt, mhi_ctxt->cmd_ctxt_addr);
i = mhi_cntrl->total_ev_rings;
@@ -405,15 +405,15 @@ error_alloc_er:
if (mhi_event->offload_ev)
continue;
- mhi_free_coherent(mhi_cntrl, ring->alloc_size,
+ dma_free_coherent(mhi_cntrl->cntrl_dev, ring->alloc_size,
ring->pre_aligned, ring->dma_handle);
}
- mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->er_ctxt) *
+ dma_free_coherent(mhi_cntrl->cntrl_dev, sizeof(*mhi_ctxt->er_ctxt) *
mhi_cntrl->total_ev_rings, mhi_ctxt->er_ctxt,
mhi_ctxt->er_ctxt_addr);
error_alloc_er_ctxt:
- mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->chan_ctxt) *
+ dma_free_coherent(mhi_cntrl->cntrl_dev, sizeof(*mhi_ctxt->chan_ctxt) *
mhi_cntrl->max_chan, mhi_ctxt->chan_ctxt,
mhi_ctxt->chan_ctxt_addr);
@@ -567,7 +567,7 @@ void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,
if (!chan_ctxt->rbase) /* Already uninitialized */
return;
- mhi_free_coherent(mhi_cntrl, tre_ring->alloc_size,
+ dma_free_coherent(mhi_cntrl->cntrl_dev, tre_ring->alloc_size,
tre_ring->pre_aligned, tre_ring->dma_handle);
vfree(buf_ring->base);
@@ -610,7 +610,7 @@ int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
buf_ring->base = vzalloc(buf_ring->len);
if (!buf_ring->base) {
- mhi_free_coherent(mhi_cntrl, tre_ring->alloc_size,
+ dma_free_coherent(mhi_cntrl->cntrl_dev, tre_ring->alloc_size,
tre_ring->pre_aligned, tre_ring->dma_handle);
return -ENOMEM;
}
@@ -885,7 +885,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
if (!mhi_cntrl || !mhi_cntrl->cntrl_dev || !mhi_cntrl->regs ||
!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put ||
!mhi_cntrl->status_cb || !mhi_cntrl->read_reg ||
- !mhi_cntrl->write_reg || !mhi_cntrl->nr_irqs || !mhi_cntrl->irq)
+ !mhi_cntrl->write_reg || !mhi_cntrl->nr_irqs ||
+ !mhi_cntrl->irq || !mhi_cntrl->reg_len)
return -EINVAL;
ret = parse_config(mhi_cntrl, config);
@@ -1063,7 +1064,7 @@ EXPORT_SYMBOL_GPL(mhi_free_controller);
int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
{
struct device *dev = &mhi_cntrl->mhi_dev->dev;
- u32 bhie_off;
+ u32 bhi_off, bhie_off;
int ret;
mutex_lock(&mhi_cntrl->pm_mutex);
@@ -1072,29 +1073,51 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
if (ret)
goto error_dev_ctxt;
- /*
- * Allocate RDDM table if specified, this table is for debugging purpose
- */
- if (mhi_cntrl->rddm_size) {
- mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image,
- mhi_cntrl->rddm_size);
+ ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIOFF, &bhi_off);
+ if (ret) {
+ dev_err(dev, "Error getting BHI offset\n");
+ goto error_reg_offset;
+ }
- /*
- * This controller supports RDDM, so we need to manually clear
- * BHIE RX registers since POR values are undefined.
- */
+ if (bhi_off >= mhi_cntrl->reg_len) {
+ dev_err(dev, "BHI offset: 0x%x is out of range: 0x%zx\n",
+ bhi_off, mhi_cntrl->reg_len);
+ ret = -EINVAL;
+ goto error_reg_offset;
+ }
+ mhi_cntrl->bhi = mhi_cntrl->regs + bhi_off;
+
+ if (mhi_cntrl->fbc_download || mhi_cntrl->rddm_size) {
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF,
&bhie_off);
if (ret) {
dev_err(dev, "Error getting BHIE offset\n");
- goto bhie_error;
+ goto error_reg_offset;
}
+ if (bhie_off >= mhi_cntrl->reg_len) {
+ dev_err(dev,
+ "BHIe offset: 0x%x is out of range: 0x%zx\n",
+ bhie_off, mhi_cntrl->reg_len);
+ ret = -EINVAL;
+ goto error_reg_offset;
+ }
mhi_cntrl->bhie = mhi_cntrl->regs + bhie_off;
+ }
+
+ if (mhi_cntrl->rddm_size) {
+ /*
+ * This controller supports RDDM, so we need to manually clear
+ * BHIE RX registers since POR values are undefined.
+ */
memset_io(mhi_cntrl->bhie + BHIE_RXVECADDR_LOW_OFFS,
0, BHIE_RXVECSTATUS_OFFS - BHIE_RXVECADDR_LOW_OFFS +
4);
-
+ /*
+ * Allocate RDDM table for debugging purpose if specified
+ */
+ mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image,
+ mhi_cntrl->rddm_size);
if (mhi_cntrl->rddm_image)
mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image);
}
@@ -1103,11 +1126,8 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
return 0;
-bhie_error:
- if (mhi_cntrl->rddm_image) {
- mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image);
- mhi_cntrl->rddm_image = NULL;
- }
+error_reg_offset:
+ mhi_deinit_dev_ctxt(mhi_cntrl);
error_dev_ctxt:
mutex_unlock(&mhi_cntrl->pm_mutex);
@@ -1128,6 +1148,9 @@ void mhi_unprepare_after_power_down(struct mhi_controller *mhi_cntrl)
mhi_cntrl->rddm_image = NULL;
}
+ mhi_cntrl->bhi = NULL;
+ mhi_cntrl->bhie = NULL;
+
mhi_deinit_dev_ctxt(mhi_cntrl);
}
EXPORT_SYMBOL_GPL(mhi_unprepare_after_power_down);
diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/core/internal.h
index 5b9ea66b92dc..3a732afaf73e 100644
--- a/drivers/bus/mhi/core/internal.h
+++ b/drivers/bus/mhi/core/internal.h
@@ -690,26 +690,6 @@ void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,
void mhi_reset_chan(struct mhi_controller *mhi_cntrl,
struct mhi_chan *mhi_chan);
-/* Memory allocation methods */
-static inline void *mhi_alloc_coherent(struct mhi_controller *mhi_cntrl,
- size_t size,
- dma_addr_t *dma_handle,
- gfp_t gfp)
-{
- void *buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev, size, dma_handle,
- gfp);
-
- return buf;
-}
-
-static inline void mhi_free_coherent(struct mhi_controller *mhi_cntrl,
- size_t size,
- void *vaddr,
- dma_addr_t dma_handle)
-{
- dma_free_coherent(mhi_cntrl->cntrl_dev, size, vaddr, dma_handle);
-}
-
/* Event processing methods */
void mhi_ctrl_ev_task(unsigned long data);
void mhi_ev_task(unsigned long data);
diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c
index fc9196f11cb7..b15c5bc37dd4 100644
--- a/drivers/bus/mhi/core/main.c
+++ b/drivers/bus/mhi/core/main.c
@@ -193,7 +193,7 @@ int mhi_map_single_no_bb(struct mhi_controller *mhi_cntrl,
int mhi_map_single_use_bb(struct mhi_controller *mhi_cntrl,
struct mhi_buf_info *buf_info)
{
- void *buf = mhi_alloc_coherent(mhi_cntrl, buf_info->len,
+ void *buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev, buf_info->len,
&buf_info->p_addr, GFP_ATOMIC);
if (!buf)
@@ -220,8 +220,8 @@ void mhi_unmap_single_use_bb(struct mhi_controller *mhi_cntrl,
if (buf_info->dir == DMA_FROM_DEVICE)
memcpy(buf_info->v_addr, buf_info->bb_addr, buf_info->len);
- mhi_free_coherent(mhi_cntrl, buf_info->len, buf_info->bb_addr,
- buf_info->p_addr);
+ dma_free_coherent(mhi_cntrl->cntrl_dev, buf_info->len,
+ buf_info->bb_addr, buf_info->p_addr);
}
static int get_nr_avail_ring_elements(struct mhi_controller *mhi_cntrl,
diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
index bbf6cd04861e..fb99e3727155 100644
--- a/drivers/bus/mhi/core/pm.c
+++ b/drivers/bus/mhi/core/pm.c
@@ -1059,28 +1059,8 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
if (ret)
goto error_setup_irq;
- /* Setup BHI offset & INTVEC */
+ /* Setup BHI INTVEC */
write_lock_irq(&mhi_cntrl->pm_lock);
- ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIOFF, &val);
- if (ret) {
- write_unlock_irq(&mhi_cntrl->pm_lock);
- goto error_bhi_offset;
- }
-
- mhi_cntrl->bhi = mhi_cntrl->regs + val;
-
- /* Setup BHIE offset */
- if (mhi_cntrl->fbc_download) {
- ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF, &val);
- if (ret) {
- write_unlock_irq(&mhi_cntrl->pm_lock);
- dev_err(dev, "Error reading BHIE offset\n");
- goto error_bhi_offset;
- }
-
- mhi_cntrl->bhie = mhi_cntrl->regs + val;
- }
-
mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0);
mhi_cntrl->pm_state = MHI_PM_POR;
mhi_cntrl->ee = MHI_EE_MAX;
@@ -1089,12 +1069,16 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
/* Confirm that the device is in valid exec env */
if (!MHI_IN_PBL(current_ee) && current_ee != MHI_EE_AMSS) {
- dev_err(dev, "Not a valid EE for power on\n");
+ dev_err(dev, "%s is not a valid EE for power on\n",
+ TO_MHI_EXEC_STR(current_ee));
ret = -EIO;
- goto error_bhi_offset;
+ goto error_async_power_up;
}
state = mhi_get_mhi_state(mhi_cntrl);
+ dev_dbg(dev, "Attempting power on with EE: %s, state: %s\n",
+ TO_MHI_EXEC_STR(current_ee), TO_MHI_STATE_STR(state));
+
if (state == MHI_STATE_SYS_ERR) {
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET);
ret = wait_event_timeout(mhi_cntrl->state_event,
@@ -1110,7 +1094,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
if (!ret) {
ret = -EIO;
dev_info(dev, "Failed to reset MHI due to syserr state\n");
- goto error_bhi_offset;
+ goto error_async_power_up;
}
/*
@@ -1132,7 +1116,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
return 0;
-error_bhi_offset:
+error_async_power_up:
mhi_deinit_free_irq(mhi_cntrl);
error_setup_irq:
diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
index b33b9d75e8af..59a4896a8030 100644
--- a/drivers/bus/mhi/pci_generic.c
+++ b/drivers/bus/mhi/pci_generic.c
@@ -369,6 +369,40 @@ static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = {
.sideband_wake = false,
};
+static const struct mhi_channel_config mhi_mv31_channels[] = {
+ MHI_CHANNEL_CONFIG_UL(0, "LOOPBACK", 64, 0),
+ MHI_CHANNEL_CONFIG_DL(1, "LOOPBACK", 64, 0),
+ /* MBIM Control Channel */
+ MHI_CHANNEL_CONFIG_UL(12, "MBIM", 64, 0),
+ MHI_CHANNEL_CONFIG_DL(13, "MBIM", 64, 0),
+ /* MBIM Data Channel */
+ MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0_MBIM", 512, 2),
+ MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0_MBIM", 512, 3),
+};
+
+static struct mhi_event_config mhi_mv31_events[] = {
+ MHI_EVENT_CONFIG_CTRL(0, 256),
+ MHI_EVENT_CONFIG_DATA(1, 256),
+ MHI_EVENT_CONFIG_HW_DATA(2, 1024, 100),
+ MHI_EVENT_CONFIG_HW_DATA(3, 1024, 101),
+};
+
+static const struct mhi_controller_config modem_mv31_config = {
+ .max_channels = 128,
+ .timeout_ms = 20000,
+ .num_channels = ARRAY_SIZE(mhi_mv31_channels),
+ .ch_cfg = mhi_mv31_channels,
+ .num_events = ARRAY_SIZE(mhi_mv31_events),
+ .event_cfg = mhi_mv31_events,
+};
+
+static const struct mhi_pci_dev_info mhi_mv31_info = {
+ .name = "cinterion-mv31",
+ .config = &modem_mv31_config,
+ .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
+ .dma_data_width = 32,
+};
+
static const struct pci_device_id mhi_pci_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0306),
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx55_info },
@@ -389,6 +423,9 @@ static const struct pci_device_id mhi_pci_id_table[] = {
/* DW5930e (sdx55), Non-eSIM, It's also T99W175 */
{ PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0b1),
.driver_data = (kernel_ulong_t) &mhi_foxconn_sdx55_info },
+ /* MV31-W (Cinterion) */
+ { PCI_DEVICE(0x1269, 0x00b3),
+ .driver_data = (kernel_ulong_t) &mhi_mv31_info },
{ }
};
MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);
@@ -490,6 +527,7 @@ static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
return err;
}
mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num];
+ mhi_cntrl->reg_len = pci_resource_len(pdev, bar_num);
err = pci_set_dma_mask(pdev, dma_mask);
if (err) {
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
index d46db132d085..6f225dddc74f 100644
--- a/drivers/bus/sunxi-rsb.c
+++ b/drivers/bus/sunxi-rsb.c
@@ -169,13 +169,11 @@ static int sunxi_rsb_device_probe(struct device *dev)
return drv->probe(rdev);
}
-static int sunxi_rsb_device_remove(struct device *dev)
+static void sunxi_rsb_device_remove(struct device *dev)
{
const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver);
drv->remove(to_sunxi_rsb_device(dev));
-
- return 0;
}
static struct bus_type sunxi_rsb_bus = {
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 148a4dd8cb9a..a51c2a8feed9 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -855,7 +855,7 @@ static int sysc_check_registers(struct sysc *ddata)
}
/**
- * syc_ioremap - ioremap register space for the interconnect target module
+ * sysc_ioremap - ioremap register space for the interconnect target module
* @ddata: device driver data
*
* Note that the interconnect target module registers can be anywhere
@@ -1446,10 +1446,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET),
SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
- SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x24, -ENODEV, 0x00000000, 0xffffffff,
- SYSC_QUIRK_LEGACY_IDLE),
- SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x38, -ENODEV, 0x00000000, 0xffffffff,
- SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff,
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
@@ -1501,6 +1497,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_MODULE_QUIRK_SGX),
SYSC_QUIRK("lcdc", 0, 0, 0x54, -ENODEV, 0x4f201000, 0xffffffff,
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
+ SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44306302, 0xffffffff,
+ SYSC_QUIRK_SWSUP_SIDLE),
SYSC_QUIRK("rtc", 0, 0x74, 0x78, -ENODEV, 0x4eb01908, 0xffff00f0,
SYSC_MODULE_QUIRK_RTC_UNLOCK),
SYSC_QUIRK("tptc", 0, 0, 0x10, -ENODEV, 0x40006c00, 0xffffefff,
@@ -1557,7 +1555,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),
SYSC_QUIRK("iss", 0, 0, 0x10, -ENODEV, 0x40000101, 0xffffffff, 0),
SYSC_QUIRK("keypad", 0x4a31c000, 0, 0x10, 0x14, 0x00000020, 0xffffffff, 0),
- SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44306302, 0xffffffff, 0),
SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44307b02, 0xffffffff, 0),
SYSC_QUIRK("mcbsp", 0, -ENODEV, 0x8c, -ENODEV, 0, 0, 0),
SYSC_QUIRK("mcspi", 0, 0, 0x10, -ENODEV, 0x40300a0b, 0xffff00ff, 0),
@@ -1585,6 +1582,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 0),
SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40000902, 0xffffffff, 0),
SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40002903, 0xffffffff, 0),
+ SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x24, -ENODEV, 0x00000000, 0xffffffff, 0),
+ SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x38, -ENODEV, 0x00000000, 0xffffffff, 0),
SYSC_QUIRK("spinlock", 0, 0, 0x10, -ENODEV, 0x50020000, 0xffffffff, 0),
SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -ENODEV, 0x00000020, 0xffffffff, 0),
SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000013, 0xffffffff, 0),
@@ -3115,9 +3114,8 @@ static int sysc_probe(struct platform_device *pdev)
goto unprepare;
pm_runtime_enable(ddata->dev);
- error = pm_runtime_get_sync(ddata->dev);
+ error = pm_runtime_resume_and_get(ddata->dev);
if (error < 0) {
- pm_runtime_put_noidle(ddata->dev);
pm_runtime_disable(ddata->dev);
goto unprepare;
}
@@ -3175,9 +3173,8 @@ static int sysc_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&ddata->idle_work);
- error = pm_runtime_get_sync(ddata->dev);
+ error = pm_runtime_resume_and_get(ddata->dev);
if (error < 0) {
- pm_runtime_put_noidle(ddata->dev);
pm_runtime_disable(ddata->dev);
goto unprepare;
}
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index feb827eefd1a..bd2e5b1560f5 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -629,7 +629,7 @@ int register_cdrom(struct gendisk *disk, struct cdrom_device_info *cdi)
if (CDROM_CAN(CDC_MRW_W))
cdi->exit = cdrom_mrw_exit;
- if (cdi->disk)
+ if (cdi->ops->read_cdda_bpc)
cdi->cdda_method = CDDA_BPC_FULL;
else
cdi->cdda_method = CDDA_OLD;
@@ -2159,81 +2159,26 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
int lba, int nframes)
{
- struct request_queue *q = cdi->disk->queue;
- struct request *rq;
- struct scsi_request *req;
- struct bio *bio;
- unsigned int len;
+ int max_frames = (queue_max_sectors(cdi->disk->queue) << 9) /
+ CD_FRAMESIZE_RAW;
int nr, ret = 0;
- if (!q)
- return -ENXIO;
-
- if (!blk_queue_scsi_passthrough(q)) {
- WARN_ONCE(true,
- "Attempt read CDDA info through a non-SCSI queue\n");
- return -EINVAL;
- }
-
cdi->last_sense = 0;
while (nframes) {
- nr = nframes;
if (cdi->cdda_method == CDDA_BPC_SINGLE)
nr = 1;
- if (nr * CD_FRAMESIZE_RAW > (queue_max_sectors(q) << 9))
- nr = (queue_max_sectors(q) << 9) / CD_FRAMESIZE_RAW;
-
- len = nr * CD_FRAMESIZE_RAW;
-
- rq = blk_get_request(q, REQ_OP_DRV_IN, 0);
- if (IS_ERR(rq)) {
- ret = PTR_ERR(rq);
- break;
- }
- req = scsi_req(rq);
-
- ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
- if (ret) {
- blk_put_request(rq);
- break;
- }
-
- req->cmd[0] = GPCMD_READ_CD;
- req->cmd[1] = 1 << 2;
- req->cmd[2] = (lba >> 24) & 0xff;
- req->cmd[3] = (lba >> 16) & 0xff;
- req->cmd[4] = (lba >> 8) & 0xff;
- req->cmd[5] = lba & 0xff;
- req->cmd[6] = (nr >> 16) & 0xff;
- req->cmd[7] = (nr >> 8) & 0xff;
- req->cmd[8] = nr & 0xff;
- req->cmd[9] = 0xf8;
-
- req->cmd_len = 12;
- rq->timeout = 60 * HZ;
- bio = rq->bio;
-
- blk_execute_rq(cdi->disk, rq, 0);
- if (scsi_req(rq)->result) {
- struct scsi_sense_hdr sshdr;
-
- ret = -EIO;
- scsi_normalize_sense(req->sense, req->sense_len,
- &sshdr);
- cdi->last_sense = sshdr.sense_key;
- }
-
- if (blk_rq_unmap_user(bio))
- ret = -EFAULT;
- blk_put_request(rq);
+ else
+ nr = min(nframes, max_frames);
+ ret = cdi->ops->read_cdda_bpc(cdi, ubuf, lba, nr,
+ &cdi->last_sense);
if (ret)
break;
nframes -= nr;
lba += nr;
- ubuf += len;
+ ubuf += (nr * CD_FRAMESIZE_RAW);
}
return ret;
@@ -3357,13 +3302,6 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
void __user *argp = (void __user *)arg;
int ret;
- /*
- * Try the generic SCSI command ioctl's first.
- */
- ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
- if (ret != -ENOTTY)
- return ret;
-
switch (cmd) {
case CDROMMULTISESSION:
return cdrom_ioctl_multisession(cdi, argp);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index ea3ead00f30f..740811893c57 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -427,8 +427,6 @@ config ADI
and SSM (Silicon Secured Memory). Intended consumers of this
driver include crash and makedumpfile.
-endmenu
-
config RANDOM_TRUST_CPU
bool "Trust the CPU manufacturer to initialize Linux's CRNG"
depends on ARCH_RANDOM
@@ -452,3 +450,5 @@ config RANDOM_TRUST_BOOTLOADER
booloader is trustworthy so it will be added to the kernel's entropy
pool. Otherwise, say N here so it will be regarded as device input that
only mixes the entropy pool.
+
+endmenu
diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h
index 0a4c69539f24..a7ead2a4c753 100644
--- a/drivers/char/ipmi/ipmi_si.h
+++ b/drivers/char/ipmi/ipmi_si.h
@@ -73,7 +73,7 @@ irqreturn_t ipmi_si_irq_handler(int irq, void *data);
void ipmi_irq_start_cleanup(struct si_sm_io *io);
int ipmi_std_irq_setup(struct si_sm_io *io);
void ipmi_irq_finish_setup(struct si_sm_io *io);
-int ipmi_si_remove_by_dev(struct device *dev);
+void ipmi_si_remove_by_dev(struct device *dev);
struct device *ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
unsigned long addr);
void ipmi_hardcode_init(void);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 62929a3e397e..bb466981dc1b 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2228,22 +2228,18 @@ static void cleanup_one_si(struct smi_info *smi_info)
kfree(smi_info);
}
-int ipmi_si_remove_by_dev(struct device *dev)
+void ipmi_si_remove_by_dev(struct device *dev)
{
struct smi_info *e;
- int rv = -ENOENT;
mutex_lock(&smi_infos_lock);
list_for_each_entry(e, &smi_infos, link) {
if (e->io.dev == dev) {
cleanup_one_si(e);
- rv = 0;
break;
}
}
mutex_unlock(&smi_infos_lock);
-
- return rv;
}
struct device *ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
diff --git a/drivers/char/ipmi/ipmi_si_parisc.c b/drivers/char/ipmi/ipmi_si_parisc.c
index 11c9160275df..2be2967f6b5f 100644
--- a/drivers/char/ipmi/ipmi_si_parisc.c
+++ b/drivers/char/ipmi/ipmi_si_parisc.c
@@ -29,9 +29,9 @@ static int __init ipmi_parisc_probe(struct parisc_device *dev)
return ipmi_si_add_smi(&io);
}
-static int __exit ipmi_parisc_remove(struct parisc_device *dev)
+static void __exit ipmi_parisc_remove(struct parisc_device *dev)
{
- return ipmi_si_remove_by_dev(&dev->dev);
+ ipmi_si_remove_by_dev(&dev->dev);
}
static const struct parisc_device_id ipmi_parisc_tbl[] __initconst = {
diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c
index 380a6a542890..505cc978c97a 100644
--- a/drivers/char/ipmi/ipmi_si_platform.c
+++ b/drivers/char/ipmi/ipmi_si_platform.c
@@ -411,7 +411,9 @@ static int ipmi_probe(struct platform_device *pdev)
static int ipmi_remove(struct platform_device *pdev)
{
- return ipmi_si_remove_by_dev(&pdev->dev);
+ ipmi_si_remove_by_dev(&pdev->dev);
+
+ return 0;
}
static int pdev_match_name(struct device *dev, const void *data)
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
index 8588b51202e5..83eaffeb22c8 100644
--- a/drivers/char/mwave/tp3780i.c
+++ b/drivers/char/mwave/tp3780i.c
@@ -470,8 +470,6 @@ int tp3780I_StartDSP(THINKPAD_BD_DATA * pBDData)
int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities)
{
- int retval = 0;
-
PRINTK_2(TRACE_TP3780I,
"tp3780i::tp3780I_QueryAbilities entry pBDData %p\n", pBDData);
@@ -502,7 +500,7 @@ int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities
PRINTK_1(TRACE_TP3780I,
"tp3780i::tp3780I_QueryAbilities exit retval=SUCCESSFUL\n");
- return retval;
+ return 0;
}
int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 5ac53dcb3a6a..78baba55a8b5 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2841,7 +2841,7 @@ static int __init synclink_cs_init(void)
err_unreg_tty:
tty_unregister_driver(serial_driver);
err_put_tty:
- put_tty_driver(serial_driver);
+ tty_driver_kref_put(serial_driver);
err:
return rc;
}
@@ -2850,7 +2850,7 @@ static void __exit synclink_cs_exit(void)
{
pcmcia_unregister_driver(&mgslpc_driver);
tty_unregister_driver(serial_driver);
- put_tty_driver(serial_driver);
+ tty_driver_kref_put(serial_driver);
}
module_init(synclink_cs_init);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index 230b2c9b3e3c..adf941c47506 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -198,7 +198,7 @@ static int __init ttyprintk_init(void)
return 0;
error:
- put_tty_driver(ttyprintk_driver);
+ tty_driver_kref_put(ttyprintk_driver);
tty_port_destroy(&tpk_port.port);
return ret;
}
@@ -206,7 +206,7 @@ error:
static void __exit ttyprintk_exit(void)
{
tty_unregister_driver(ttyprintk_driver);
- put_tty_driver(ttyprintk_driver);
+ tty_driver_kref_put(ttyprintk_driver);
tty_port_destroy(&tpk_port.port);
}
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e873f9ea2e65..c5b3dc97396a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -403,6 +403,7 @@ source "drivers/clk/mediatek/Kconfig"
source "drivers/clk/meson/Kconfig"
source "drivers/clk/mstar/Kconfig"
source "drivers/clk/mvebu/Kconfig"
+source "drivers/clk/pistachio/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/ralink/Kconfig"
source "drivers/clk/renesas/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 2b91d34c582b..e42312121e51 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -97,7 +97,7 @@ obj-y += mstar/
obj-y += mvebu/
obj-$(CONFIG_ARCH_MXS) += mxs/
obj-$(CONFIG_COMMON_CLK_NXP) += nxp/
-obj-$(CONFIG_MACH_PISTACHIO) += pistachio/
+obj-$(CONFIG_COMMON_CLK_PISTACHIO) += pistachio/
obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
obj-y += ralink/
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index b4fc8d71daf2..b656d25a9767 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -128,6 +128,12 @@ static int clk_generated_determine_rate(struct clk_hw *hw,
int i;
u32 div;
+ /* do not look for a rate that is outside of our range */
+ if (gck->range.max && req->rate > gck->range.max)
+ req->rate = gck->range.max;
+ if (gck->range.min && req->rate < gck->range.min)
+ req->rate = gck->range.min;
+
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
if (gck->chg_pid == i)
continue;
diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c
index 9e1ec48c4474..cf8c079aa086 100644
--- a/drivers/clk/at91/sama7g5.c
+++ b/drivers/clk/at91/sama7g5.c
@@ -35,7 +35,7 @@ static DEFINE_SPINLOCK(pmc_pll_lock);
static DEFINE_SPINLOCK(pmc_mck0_lock);
static DEFINE_SPINLOCK(pmc_mckX_lock);
-/**
+/*
* PLL clocks identifiers
* @PLL_ID_CPU: CPU PLL identifier
* @PLL_ID_SYS: System PLL identifier
@@ -56,7 +56,7 @@ enum pll_ids {
PLL_ID_MAX,
};
-/**
+/*
* PLL type identifiers
* @PLL_TYPE_FRAC: fractional PLL identifier
* @PLL_TYPE_DIV: divider PLL identifier
@@ -118,7 +118,7 @@ static const struct clk_pll_characteristics pll_characteristics = {
.output = pll_outputs,
};
-/**
+/*
* PLL clocks description
* @n: clock name
* @p: clock parent
@@ -285,7 +285,7 @@ static const struct {
},
};
-/**
+/*
* Master clock (MCK[1..4]) description
* @n: clock name
* @ep: extra parents names array
@@ -337,7 +337,7 @@ static const struct {
.c = 1, },
};
-/**
+/*
* System clock description
* @n: clock name
* @p: clock parent name
@@ -361,7 +361,7 @@ static const struct {
/* Mux table for programmable clocks. */
static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };
-/**
+/*
* Peripheral clock description
* @n: clock name
* @p: clock parent name
@@ -449,7 +449,7 @@ static const struct {
{ .n = "uhphs_clk", .p = "mck1", .id = 106, },
};
-/**
+/*
* Generic clock description
* @n: clock name
* @pp: PLL parents
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 1ac803e14fa3..a254512965eb 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -805,11 +805,10 @@ static int bcm2835_pll_divider_is_on(struct clk_hw *hw)
return !(cprman_read(cprman, data->a2w_reg) & A2W_PLL_CHANNEL_DISABLE);
}
-static long bcm2835_pll_divider_round_rate(struct clk_hw *hw,
- unsigned long rate,
- unsigned long *parent_rate)
+static int bcm2835_pll_divider_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- return clk_divider_ops.round_rate(hw, rate, parent_rate);
+ return clk_divider_ops.determine_rate(hw, req);
}
static unsigned long bcm2835_pll_divider_get_rate(struct clk_hw *hw,
@@ -901,7 +900,7 @@ static const struct clk_ops bcm2835_pll_divider_clk_ops = {
.unprepare = bcm2835_pll_divider_off,
.recalc_rate = bcm2835_pll_divider_get_rate,
.set_rate = bcm2835_pll_divider_set_rate,
- .round_rate = bcm2835_pll_divider_round_rate,
+ .determine_rate = bcm2835_pll_divider_determine_rate,
.debug_init = bcm2835_pll_divider_debug_init,
};
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 87ba4966b0e8..f6b2bf558486 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -446,6 +446,27 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
divider->width, divider->flags);
}
+static int clk_divider_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+
+ /* if read only, just return current value */
+ if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+ u32 val;
+
+ val = clk_div_readl(divider) >> divider->shift;
+ val &= clk_div_mask(divider->width);
+
+ return divider_ro_determine_rate(hw, req, divider->table,
+ divider->width,
+ divider->flags, val);
+ }
+
+ return divider_determine_rate(hw, req, divider->table, divider->width,
+ divider->flags);
+}
+
int divider_get_val(unsigned long rate, unsigned long parent_rate,
const struct clk_div_table *table, u8 width,
unsigned long flags)
@@ -501,6 +522,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops clk_divider_ops = {
.recalc_rate = clk_divider_recalc_rate,
.round_rate = clk_divider_round_rate,
+ .determine_rate = clk_divider_determine_rate,
.set_rate = clk_divider_set_rate,
};
EXPORT_SYMBOL_GPL(clk_divider_ops);
@@ -508,6 +530,7 @@ EXPORT_SYMBOL_GPL(clk_divider_ops);
const struct clk_ops clk_divider_ro_ops = {
.recalc_rate = clk_divider_recalc_rate,
.round_rate = clk_divider_round_rate,
+ .determine_rate = clk_divider_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index b1e556f20911..4274540327ce 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -3,8 +3,39 @@
* Copyright (C) 2014 Intel Corporation
*
* Adjustable fractional divider clock implementation.
- * Output rate = (m / n) * parent_rate.
* Uses rational best approximation algorithm.
+ *
+ * Output is calculated as
+ *
+ * rate = (m / n) * parent_rate (1)
+ *
+ * This is useful when we have a prescaler block which asks for
+ * m (numerator) and n (denominator) values to be provided to satisfy
+ * the (1) as much as possible.
+ *
+ * Since m and n have the limitation by a range, e.g.
+ *
+ * n >= 1, n < N_width, where N_width = 2^nwidth (2)
+ *
+ * for some cases the output may be saturated. Hence, from (1) and (2),
+ * assuming the worst case when m = 1, the inequality
+ *
+ * floor(log2(parent_rate / rate)) <= nwidth (3)
+ *
+ * may be derived. Thus, in cases when
+ *
+ * (parent_rate / rate) >> N_width (4)
+ *
+ * we might scale up the rate by 2^scale (see the description of
+ * CLK_FRAC_DIVIDER_POWER_OF_TWO_PS for additional information), where
+ *
+ * scale = floor(log2(parent_rate / rate)) - nwidth (5)
+ *
+ * and assume that the IP, that needs m and n, has also its own
+ * prescaler, which is capable to divide by 2^scale. In this way
+ * we get the denominator to satisfy the desired range (2) and
+ * at the same time much much better result of m and n than simple
+ * saturated values.
*/
#include <linux/clk-provider.h>
@@ -14,6 +45,8 @@
#include <linux/slab.h>
#include <linux/rational.h>
+#include "clk-fractional-divider.h"
+
static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
{
if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
@@ -68,21 +101,26 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
return ret;
}
-static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate,
- unsigned long *m, unsigned long *n)
+void clk_fractional_divider_general_approximation(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate,
+ unsigned long *m, unsigned long *n)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
- unsigned long scale;
/*
* Get rate closer to *parent_rate to guarantee there is no overflow
* for m and n. In the result it will be the nearest rate left shifted
* by (scale - fd->nwidth) bits.
+ *
+ * For the detailed explanation see the top comment in this file.
*/
- scale = fls_long(*parent_rate / rate - 1);
- if (scale > fd->nwidth)
- rate <<= scale - fd->nwidth;
+ if (fd->flags & CLK_FRAC_DIVIDER_POWER_OF_TWO_PS) {
+ unsigned long scale = fls_long(*parent_rate / rate - 1);
+
+ if (scale > fd->nwidth)
+ rate <<= scale - fd->nwidth;
+ }
rational_best_approximation(rate, *parent_rate,
GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
@@ -102,7 +140,7 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
if (fd->approximation)
fd->approximation(hw, rate, parent_rate, &m, &n);
else
- clk_fd_general_approximation(hw, rate, parent_rate, &m, &n);
+ clk_fractional_divider_general_approximation(hw, rate, parent_rate, &m, &n);
ret = (u64)*parent_rate * m;
do_div(ret, n);
diff --git a/drivers/clk/clk-fractional-divider.h b/drivers/clk/clk-fractional-divider.h
new file mode 100644
index 000000000000..f0f71d23797b
--- /dev/null
+++ b/drivers/clk/clk-fractional-divider.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _CLK_FRACTIONAL_DIV_H
+#define _CLK_FRACTIONAL_DIV_H
+
+struct clk_hw;
+
+extern const struct clk_ops clk_fractional_divider_ops;
+
+void clk_fractional_divider_general_approximation(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate,
+ unsigned long *m,
+ unsigned long *n);
+
+#endif
diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c
index c7a3a029fb1e..8f02c0b88000 100644
--- a/drivers/clk/clk-lmk04832.c
+++ b/drivers/clk/clk-lmk04832.c
@@ -269,23 +269,14 @@ static bool lmk04832_regmap_rd_regs(struct device *dev, unsigned int reg)
{
switch (reg) {
case LMK04832_REG_RST3W ... LMK04832_REG_ID_MASKREV:
- fallthrough;
case LMK04832_REG_ID_VNDR_MSB:
- fallthrough;
case LMK04832_REG_ID_VNDR_LSB:
- fallthrough;
case LMK04832_REG_CLKOUT_CTRL0(0) ... LMK04832_REG_PLL2_DLD_CNT_LSB:
- fallthrough;
case LMK04832_REG_PLL2_LD:
- fallthrough;
case LMK04832_REG_PLL2_PD:
- fallthrough;
case LMK04832_REG_PLL1R_RST:
- fallthrough;
case LMK04832_REG_CLR_PLL_LOST ... LMK04832_REG_RB_DAC_VAL_LSB:
- fallthrough;
case LMK04832_REG_RB_HOLDOVER:
- fallthrough;
case LMK04832_REG_SPI_LOCK:
return true;
default:
@@ -297,27 +288,18 @@ static bool lmk04832_regmap_wr_regs(struct device *dev, unsigned int reg)
{
switch (reg) {
case LMK04832_REG_RST3W:
- fallthrough;
case LMK04832_REG_POWERDOWN:
return true;
case LMK04832_REG_ID_DEV_TYPE ... LMK04832_REG_ID_MASKREV:
- fallthrough;
case LMK04832_REG_ID_VNDR_MSB:
- fallthrough;
case LMK04832_REG_ID_VNDR_LSB:
return false;
case LMK04832_REG_CLKOUT_CTRL0(0) ... LMK04832_REG_PLL2_DLD_CNT_LSB:
- fallthrough;
case LMK04832_REG_PLL2_LD:
- fallthrough;
case LMK04832_REG_PLL2_PD:
- fallthrough;
case LMK04832_REG_PLL1R_RST:
- fallthrough;
case LMK04832_REG_CLR_PLL_LOST ... LMK04832_REG_RB_DAC_VAL_LSB:
- fallthrough;
case LMK04832_REG_RB_HOLDOVER:
- fallthrough;
case LMK04832_REG_SPI_LOCK:
return true;
default:
diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
index e41a3a9f7528..b8c3d0da1918 100644
--- a/drivers/clk/clk-palmas.c
+++ b/drivers/clk/clk-palmas.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Clock driver for Palmas device.
*
@@ -6,15 +7,6 @@
*
* Author: Laxman Dewangan <ldewangan@nvidia.com>
* Peter Ujfalusi <peter.ujfalusi@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.
- *
- * 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/clk.h>
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 5c75e3d906c2..af46176ad053 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -709,10 +709,10 @@ static unsigned long stm32f4_pll_div_recalc_rate(struct clk_hw *hw,
return clk_divider_ops.recalc_rate(hw, parent_rate);
}
-static long stm32f4_pll_div_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static int stm32f4_pll_div_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- return clk_divider_ops.round_rate(hw, rate, prate);
+ return clk_divider_ops.determine_rate(hw, req);
}
static int stm32f4_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -738,7 +738,7 @@ static int stm32f4_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops stm32f4_pll_div_ops = {
.recalc_rate = stm32f4_pll_div_recalc_rate,
- .round_rate = stm32f4_pll_div_round_rate,
+ .determine_rate = stm32f4_pll_div_determine_rate,
.set_rate = stm32f4_pll_div_set_rate,
};
diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c
index 0ea7261d15e0..1a701eada0c1 100644
--- a/drivers/clk/clk-stm32h7.c
+++ b/drivers/clk/clk-stm32h7.c
@@ -845,10 +845,10 @@ static unsigned long odf_divider_recalc_rate(struct clk_hw *hw,
return clk_divider_ops.recalc_rate(hw, parent_rate);
}
-static long odf_divider_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static int odf_divider_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- return clk_divider_ops.round_rate(hw, rate, prate);
+ return clk_divider_ops.determine_rate(hw, req);
}
static int odf_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -875,7 +875,7 @@ static int odf_divider_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops odf_divider_ops = {
.recalc_rate = odf_divider_recalc_rate,
- .round_rate = odf_divider_round_rate,
+ .determine_rate = odf_divider_determine_rate,
.set_rate = odf_divider_set_rate,
};
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
index 256575bd29b9..4bd1fe7d8af4 100644
--- a/drivers/clk/clk-stm32mp1.c
+++ b/drivers/clk/clk-stm32mp1.c
@@ -1076,14 +1076,10 @@ static int clk_divider_rtc_set_rate(struct clk_hw *hw, unsigned long rate,
static int clk_divider_rtc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
- unsigned long best_parent_rate = req->best_parent_rate;
+ if (req->best_parent_hw == clk_hw_get_parent_by_index(hw, HSE_RTC))
+ return clk_divider_ops.determine_rate(hw, req);
- if (req->best_parent_hw == clk_hw_get_parent_by_index(hw, HSE_RTC)) {
- req->rate = clk_divider_ops.round_rate(hw, req->rate, &best_parent_rate);
- req->best_parent_rate = best_parent_rate;
- } else {
- req->rate = best_parent_rate;
- }
+ req->rate = req->best_parent_rate;
return 0;
}
diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c
index 3c737742c2a9..c6d3b1ab3d55 100644
--- a/drivers/clk/clk-versaclock5.c
+++ b/drivers/clk/clk-versaclock5.c
@@ -907,6 +907,7 @@ static const struct of_device_id clk_vc5_of_match[];
static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
+ unsigned int oe, sd, src_mask = 0, src_val = 0;
struct vc5_driver_data *vc5;
struct clk_init_data init;
const char *parent_names[2];
@@ -930,11 +931,33 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -EPROBE_DEFER;
vc5->regmap = devm_regmap_init_i2c(client, &vc5_regmap_config);
- if (IS_ERR(vc5->regmap)) {
- dev_err(&client->dev, "failed to allocate register map\n");
- return PTR_ERR(vc5->regmap);
+ if (IS_ERR(vc5->regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(vc5->regmap),
+ "failed to allocate register map\n");
+
+ ret = of_property_read_u32(client->dev.of_node, "idt,shutdown", &sd);
+ if (!ret) {
+ src_mask |= VC5_PRIM_SRC_SHDN_EN_GBL_SHDN;
+ if (sd)
+ src_val |= VC5_PRIM_SRC_SHDN_EN_GBL_SHDN;
+ } else if (ret != -EINVAL) {
+ return dev_err_probe(&client->dev, ret,
+ "could not read idt,shutdown\n");
}
+ ret = of_property_read_u32(client->dev.of_node,
+ "idt,output-enable-active", &oe);
+ if (!ret) {
+ src_mask |= VC5_PRIM_SRC_SHDN_SP;
+ if (oe)
+ src_val |= VC5_PRIM_SRC_SHDN_SP;
+ } else if (ret != -EINVAL) {
+ return dev_err_probe(&client->dev, ret,
+ "could not read idt,output-enable-active\n");
+ }
+
+ regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, src_mask, src_val);
+
/* Register clock input mux */
memset(&init, 0, sizeof(init));
@@ -957,10 +980,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id)
__clk_get_name(vc5->pin_clkin);
}
- if (!init.num_parents) {
- dev_err(&client->dev, "no input clock specified!\n");
- return -EINVAL;
- }
+ if (!init.num_parents)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "no input clock specified!\n");
/* Configure Optional Loading Capacitance for external XTAL */
if (!(vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)) {
@@ -1099,14 +1121,16 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id)
ret = of_clk_add_hw_provider(client->dev.of_node, vc5_of_clk_get, vc5);
if (ret) {
- dev_err(&client->dev, "unable to add clk provider\n");
+ dev_err_probe(&client->dev, ret,
+ "unable to add clk provider\n");
goto err_clk;
}
return 0;
err_clk_register:
- dev_err(&client->dev, "unable to register %s\n", init.name);
+ dev_err_probe(&client->dev, ret,
+ "unable to register %s\n", init.name);
kfree(init.name); /* clock framework made a copy of the name */
err_clk:
if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)
diff --git a/drivers/clk/imx/clk-composite-7ulp.c b/drivers/clk/imx/clk-composite-7ulp.c
index 7c4f31b31eb0..d85ba78abbb1 100644
--- a/drivers/clk/imx/clk-composite-7ulp.c
+++ b/drivers/clk/imx/clk-composite-7ulp.c
@@ -10,6 +10,7 @@
#include <linux/err.h>
#include <linux/slab.h>
+#include "../clk-fractional-divider.h"
#include "clk.h"
#define PCG_PCS_SHIFT 24
diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c
index 2c309e3dc8e3..04e728538cef 100644
--- a/drivers/clk/imx/clk-composite-8m.c
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -216,7 +216,8 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
div->width = PCG_PREDIV_WIDTH;
divider_ops = &imx8m_clk_composite_divider_ops;
mux_ops = &clk_mux_ops;
- flags |= CLK_SET_PARENT_GATE;
+ if (!(composite_flags & IMX_COMPOSITE_FW_MANAGED))
+ flags |= CLK_SET_PARENT_GATE;
}
div->lock = &imx_ccm_lock;
diff --git a/drivers/clk/imx/clk-divider-gate.c b/drivers/clk/imx/clk-divider-gate.c
index 0322a843d245..26b210cba9be 100644
--- a/drivers/clk/imx/clk-divider-gate.c
+++ b/drivers/clk/imx/clk-divider-gate.c
@@ -64,10 +64,10 @@ static unsigned long clk_divider_gate_recalc_rate(struct clk_hw *hw,
div->flags, div->width);
}
-static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static int clk_divider_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- return clk_divider_ops.round_rate(hw, rate, prate);
+ return clk_divider_ops.determine_rate(hw, req);
}
static int clk_divider_gate_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -154,12 +154,12 @@ static int clk_divider_is_enabled(struct clk_hw *hw)
static const struct clk_ops clk_divider_gate_ro_ops = {
.recalc_rate = clk_divider_gate_recalc_rate_ro,
- .round_rate = clk_divider_round_rate,
+ .determine_rate = clk_divider_determine_rate,
};
static const struct clk_ops clk_divider_gate_ops = {
.recalc_rate = clk_divider_gate_recalc_rate,
- .round_rate = clk_divider_round_rate,
+ .determine_rate = clk_divider_determine_rate,
.set_rate = clk_divider_gate_set_rate,
.enable = clk_divider_enable,
.disable = clk_divider_disable,
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index f1919fafb124..e92621fa8b9c 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -407,10 +407,10 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2);
hws[IMX8MM_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
- hws[IMX8MM_CLK_CLKOUT1_SEL] = imx_clk_hw_mux("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
+ hws[IMX8MM_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
hws[IMX8MM_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128, 0, 4);
hws[IMX8MM_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
- hws[IMX8MM_CLK_CLKOUT2_SEL] = imx_clk_hw_mux("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
+ hws[IMX8MM_CLK_CLKOUT2_SEL] = imx_clk_hw_mux2("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
hws[IMX8MM_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128, 16, 4);
hws[IMX8MM_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
@@ -470,10 +470,11 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
/*
* DRAM clocks are manipulated from TF-A outside clock framework.
- * Mark with GET_RATE_NOCACHE to always read div value from hardware
+ * The fw_managed helper sets GET_RATE_NOCACHE and clears SET_PARENT_GATE
+ * as div value should always be read from hardware
*/
- hws[IMX8MM_CLK_DRAM_ALT] = __imx8m_clk_hw_composite("dram_alt", imx8mm_dram_alt_sels, base + 0xa000, CLK_GET_RATE_NOCACHE);
- hws[IMX8MM_CLK_DRAM_APB] = __imx8m_clk_hw_composite("dram_apb", imx8mm_dram_apb_sels, base + 0xa080, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
+ hws[IMX8MM_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mm_dram_alt_sels, base + 0xa000);
+ hws[IMX8MM_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mm_dram_apb_sels, base + 0xa080);
/* IP */
hws[IMX8MM_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mm_vpu_g1_sels, base + 0xa100);
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index 88f6630cd472..c55577604e16 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -40,6 +40,9 @@ static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pl
static const char * const imx8mn_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", };
+static const char * const imx8mn_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "vpu_pll_out",
+ "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+
static const char * const imx8mn_gpu_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
"sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
"video_pll1_out", "audio_pll2_out", };
@@ -402,10 +405,10 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
hws[IMX8MN_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2);
hws[IMX8MN_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
- hws[IMX8MN_CLK_CLKOUT1_SEL] = imx_clk_hw_mux("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
+ hws[IMX8MN_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
hws[IMX8MN_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128, 0, 4);
hws[IMX8MN_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8);
- hws[IMX8MN_CLK_CLKOUT2_SEL] = imx_clk_hw_mux("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
+ hws[IMX8MN_CLK_CLKOUT2_SEL] = imx_clk_hw_mux2("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
hws[IMX8MN_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128, 16, 4);
hws[IMX8MN_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24);
@@ -421,6 +424,8 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
hws[IMX8MN_CLK_A53_SRC] = hws[IMX8MN_CLK_A53_DIV];
hws[IMX8MN_CLK_A53_CG] = hws[IMX8MN_CLK_A53_DIV];
+ hws[IMX8MN_CLK_M7_CORE] = imx8m_clk_hw_composite_core("arm_m7_core", imx8mn_m7_sels, base + 0x8080);
+
hws[IMX8MN_CLK_GPU_CORE] = imx8m_clk_hw_composite_core("gpu_core", imx8mn_gpu_core_sels, base + 0x8180);
hws[IMX8MN_CLK_GPU_SHADER] = imx8m_clk_hw_composite_core("gpu_shader", imx8mn_gpu_shader_sels, base + 0x8200);
@@ -453,10 +458,11 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
/*
* DRAM clocks are manipulated from TF-A outside clock framework.
- * Mark with GET_RATE_NOCACHE to always read div value from hardware
+ * The fw_managed helper sets GET_RATE_NOCACHE and clears SET_PARENT_GATE
+ * as div value should always be read from hardware
*/
- hws[IMX8MN_CLK_DRAM_ALT] = __imx8m_clk_hw_composite("dram_alt", imx8mn_dram_alt_sels, base + 0xa000, CLK_GET_RATE_NOCACHE);
- hws[IMX8MN_CLK_DRAM_APB] = __imx8m_clk_hw_composite("dram_apb", imx8mn_dram_apb_sels, base + 0xa080, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
+ hws[IMX8MN_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mn_dram_alt_sels, base + 0xa000);
+ hws[IMX8MN_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mn_dram_apb_sels, base + 0xa080);
hws[IMX8MN_CLK_DISP_PIXEL] = imx8m_clk_hw_composite("disp_pixel", imx8mn_disp_pixel_sels, base + 0xa500);
hws[IMX8MN_CLK_SAI2] = imx8m_clk_hw_composite("sai2", imx8mn_sai2_sels, base + 0xa600);
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
index c491bc9c61ce..83cc2b1c3294 100644
--- a/drivers/clk/imx/clk-imx8mq.c
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -449,11 +449,12 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
/*
* DRAM clocks are manipulated from TF-A outside clock framework.
- * Mark with GET_RATE_NOCACHE to always read div value from hardware
+ * The fw_managed helper sets GET_RATE_NOCACHE and clears SET_PARENT_GATE
+ * as div value should always be read from hardware
*/
hws[IMX8MQ_CLK_DRAM_CORE] = imx_clk_hw_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mq_dram_core_sels, ARRAY_SIZE(imx8mq_dram_core_sels), CLK_IS_CRITICAL);
- hws[IMX8MQ_CLK_DRAM_ALT] = __imx8m_clk_hw_composite("dram_alt", imx8mq_dram_alt_sels, base + 0xa000, CLK_GET_RATE_NOCACHE);
- hws[IMX8MQ_CLK_DRAM_APB] = __imx8m_clk_hw_composite("dram_apb", imx8mq_dram_apb_sels, base + 0xa080, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
+ hws[IMX8MQ_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mq_dram_alt_sels, base + 0xa000);
+ hws[IMX8MQ_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mq_dram_apb_sels, base + 0xa080);
/* IP */
hws[IMX8MQ_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mq_vpu_g1_sels, base + 0xa100);
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 7571603bee23..e144f983fd8c 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -530,8 +530,9 @@ struct clk_hw *imx_clk_hw_cpu(const char *name, const char *parent_name,
struct clk *div, struct clk *mux, struct clk *pll,
struct clk *step);
-#define IMX_COMPOSITE_CORE BIT(0)
-#define IMX_COMPOSITE_BUS BIT(1)
+#define IMX_COMPOSITE_CORE BIT(0)
+#define IMX_COMPOSITE_BUS BIT(1)
+#define IMX_COMPOSITE_FW_MANAGED BIT(2)
struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
const char * const *parent_names,
@@ -567,6 +568,17 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
ARRAY_SIZE(parent_names), reg, 0, \
flags | CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
+#define __imx8m_clk_hw_fw_managed_composite(name, parent_names, reg, flags) \
+ imx8m_clk_hw_composite_flags(name, parent_names, \
+ ARRAY_SIZE(parent_names), reg, IMX_COMPOSITE_FW_MANAGED, \
+ flags | CLK_GET_RATE_NOCACHE | CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
+
+#define imx8m_clk_hw_fw_managed_composite(name, parent_names, reg) \
+ __imx8m_clk_hw_fw_managed_composite(name, parent_names, reg, 0)
+
+#define imx8m_clk_hw_fw_managed_composite_critical(name, parent_names, reg) \
+ __imx8m_clk_hw_fw_managed_composite(name, parent_names, reg, CLK_IS_CRITICAL)
+
#define __imx8m_clk_composite(name, parent_names, reg, flags) \
to_clk(__imx8m_clk_hw_composite(name, parent_names, reg, flags))
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 886e2d9fced5..439b7c8d0d07 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -362,41 +362,36 @@ config COMMON_CLK_MT8167
config COMMON_CLK_MT8167_AUDSYS
bool "Clock driver for MediaTek MT8167 audsys"
- depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
- select COMMON_CLK_MEDIATEK
- default ARCH_MEDIATEK
+ depends on COMMON_CLK_MT8167
+ default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 audsys clocks.
config COMMON_CLK_MT8167_IMGSYS
bool "Clock driver for MediaTek MT8167 imgsys"
- depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
- select COMMON_CLK_MEDIATEK
- default ARCH_MEDIATEK
+ depends on COMMON_CLK_MT8167
+ default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 imgsys clocks.
config COMMON_CLK_MT8167_MFGCFG
bool "Clock driver for MediaTek MT8167 mfgcfg"
- depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
- select COMMON_CLK_MEDIATEK
- default ARCH_MEDIATEK
+ depends on COMMON_CLK_MT8167
+ default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 mfgcfg clocks.
config COMMON_CLK_MT8167_MMSYS
bool "Clock driver for MediaTek MT8167 mmsys"
- depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
- select COMMON_CLK_MEDIATEK
- default ARCH_MEDIATEK
+ depends on COMMON_CLK_MT8167
+ default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 mmsys clocks.
config COMMON_CLK_MT8167_VDECSYS
bool "Clock driver for MediaTek MT8167 vdecsys"
- depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
- select COMMON_CLK_MEDIATEK
- default ARCH_MEDIATEK
+ depends on COMMON_CLK_MT8167
+ default COMMON_CLK_MT8167
help
This driver supports MediaTek MT8167 vdecsys clocks.
@@ -500,6 +495,86 @@ config COMMON_CLK_MT8183_VENCSYS
help
This driver supports MediaTek MT8183 vencsys clocks.
+config COMMON_CLK_MT8192
+ bool "Clock driver for MediaTek MT8192"
+ depends on ARM64 || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ default ARM64
+ help
+ This driver supports MediaTek MT8192 basic clocks.
+
+config COMMON_CLK_MT8192_AUDSYS
+ bool "Clock driver for MediaTek MT8192 audsys"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 audsys clocks.
+
+config COMMON_CLK_MT8192_CAMSYS
+ bool "Clock driver for MediaTek MT8192 camsys"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 camsys and camsys_raw clocks.
+
+config COMMON_CLK_MT8192_IMGSYS
+ bool "Clock driver for MediaTek MT8192 imgsys"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 imgsys and imgsys2 clocks.
+
+config COMMON_CLK_MT8192_IMP_IIC_WRAP
+ bool "Clock driver for MediaTek MT8192 imp_iic_wrap"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 imp_iic_wrap clocks.
+
+config COMMON_CLK_MT8192_IPESYS
+ bool "Clock driver for MediaTek MT8192 ipesys"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 ipesys clocks.
+
+config COMMON_CLK_MT8192_MDPSYS
+ bool "Clock driver for MediaTek MT8192 mdpsys"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 mdpsys clocks.
+
+config COMMON_CLK_MT8192_MFGCFG
+ bool "Clock driver for MediaTek MT8192 mfgcfg"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 mfgcfg clocks.
+
+config COMMON_CLK_MT8192_MMSYS
+ bool "Clock driver for MediaTek MT8192 mmsys"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 mmsys clocks.
+
+config COMMON_CLK_MT8192_MSDC
+ bool "Clock driver for MediaTek MT8192 msdc"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 msdc and msdc_top clocks.
+
+config COMMON_CLK_MT8192_SCP_ADSP
+ bool "Clock driver for MediaTek MT8192 scp_adsp"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 scp_adsp clocks.
+
+config COMMON_CLK_MT8192_VDECSYS
+ bool "Clock driver for MediaTek MT8192 vdecsys"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 vdecsys and vdecsys_soc clocks.
+
+config COMMON_CLK_MT8192_VENCSYS
+ bool "Clock driver for MediaTek MT8192 vencsys"
+ depends on COMMON_CLK_MT8192
+ help
+ This driver supports MediaTek MT8192 vencsys clocks.
+
config COMMON_CLK_MT8516
bool "Clock driver for MediaTek MT8516"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 3b0c2be73824..15bc045f0b71 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -67,5 +67,18 @@ obj-$(CONFIG_COMMON_CLK_MT8183_MFGCFG) += clk-mt8183-mfgcfg.o
obj-$(CONFIG_COMMON_CLK_MT8183_MMSYS) += clk-mt8183-mm.o
obj-$(CONFIG_COMMON_CLK_MT8183_VDECSYS) += clk-mt8183-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8183_VENCSYS) += clk-mt8183-venc.o
+obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192.o
+obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
+obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
+obj-$(CONFIG_COMMON_CLK_MT8192_IMGSYS) += clk-mt8192-img.o
+obj-$(CONFIG_COMMON_CLK_MT8192_IMP_IIC_WRAP) += clk-mt8192-imp_iic_wrap.o
+obj-$(CONFIG_COMMON_CLK_MT8192_IPESYS) += clk-mt8192-ipe.o
+obj-$(CONFIG_COMMON_CLK_MT8192_MDPSYS) += clk-mt8192-mdp.o
+obj-$(CONFIG_COMMON_CLK_MT8192_MFGCFG) += clk-mt8192-mfg.o
+obj-$(CONFIG_COMMON_CLK_MT8192_MMSYS) += clk-mt8192-mm.o
+obj-$(CONFIG_COMMON_CLK_MT8192_MSDC) += clk-mt8192-msdc.o
+obj-$(CONFIG_COMMON_CLK_MT8192_SCP_ADSP) += clk-mt8192-scp_adsp.o
+obj-$(CONFIG_COMMON_CLK_MT8192_VDECSYS) += clk-mt8192-vdec.o
+obj-$(CONFIG_COMMON_CLK_MT8192_VENCSYS) += clk-mt8192-venc.o
obj-$(CONFIG_COMMON_CLK_MT8516) += clk-mt8516.o
obj-$(CONFIG_COMMON_CLK_MT8516_AUDSYS) += clk-mt8516-aud.o
diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c
index 79fe09028742..61eeae4e60fb 100644
--- a/drivers/clk/mediatek/clk-cpumux.c
+++ b/drivers/clk/mediatek/clk-cpumux.c
@@ -84,7 +84,7 @@ int mtk_clk_register_cpumuxes(struct device_node *node,
struct clk *clk;
struct regmap *regmap;
- regmap = syscon_node_to_regmap(node);
+ regmap = device_node_to_regmap(node);
if (IS_ERR(regmap)) {
pr_err("Cannot find regmap for %pOF: %ld\n", node,
PTR_ERR(regmap));
diff --git a/drivers/clk/mediatek/clk-mt8192-aud.c b/drivers/clk/mediatek/clk-mt8192-aud.c
new file mode 100644
index 000000000000..f28d56628045
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-aud.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs aud0_cg_regs = {
+ .set_ofs = 0x0,
+ .clr_ofs = 0x0,
+ .sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs aud1_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x4,
+};
+
+static const struct mtk_gate_regs aud2_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x8,
+};
+
+#define GATE_AUD0(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &aud0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
+
+#define GATE_AUD1(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &aud1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
+
+#define GATE_AUD2(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &aud2_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
+
+static const struct mtk_gate aud_clks[] = {
+ /* AUD0 */
+ GATE_AUD0(CLK_AUD_AFE, "aud_afe", "audio_sel", 2),
+ GATE_AUD0(CLK_AUD_22M, "aud_22m", "aud_engen1_sel", 8),
+ GATE_AUD0(CLK_AUD_24M, "aud_24m", "aud_engen2_sel", 9),
+ GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "aud_engen2_sel", 18),
+ GATE_AUD0(CLK_AUD_APLL_TUNER, "aud_apll_tuner", "aud_engen1_sel", 19),
+ GATE_AUD0(CLK_AUD_TDM, "aud_tdm", "aud_1_sel", 20),
+ GATE_AUD0(CLK_AUD_ADC, "aud_adc", "audio_sel", 24),
+ GATE_AUD0(CLK_AUD_DAC, "aud_dac", "audio_sel", 25),
+ GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "audio_sel", 26),
+ GATE_AUD0(CLK_AUD_TML, "aud_tml", "audio_sel", 27),
+ GATE_AUD0(CLK_AUD_NLE, "aud_nle", "audio_sel", 28),
+ /* AUD1 */
+ GATE_AUD1(CLK_AUD_I2S1_B, "aud_i2s1_b", "audio_sel", 4),
+ GATE_AUD1(CLK_AUD_I2S2_B, "aud_i2s2_b", "audio_sel", 5),
+ GATE_AUD1(CLK_AUD_I2S3_B, "aud_i2s3_b", "audio_sel", 6),
+ GATE_AUD1(CLK_AUD_I2S4_B, "aud_i2s4_b", "audio_sel", 7),
+ GATE_AUD1(CLK_AUD_CONNSYS_I2S_ASRC, "aud_connsys_i2s_asrc", "audio_sel", 12),
+ GATE_AUD1(CLK_AUD_GENERAL1_ASRC, "aud_general1_asrc", "audio_sel", 13),
+ GATE_AUD1(CLK_AUD_GENERAL2_ASRC, "aud_general2_asrc", "audio_sel", 14),
+ GATE_AUD1(CLK_AUD_DAC_HIRES, "aud_dac_hires", "audio_h_sel", 15),
+ GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires", "audio_h_sel", 16),
+ GATE_AUD1(CLK_AUD_ADC_HIRES_TML, "aud_adc_hires_tml", "audio_h_sel", 17),
+ GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc", "audio_sel", 20),
+ GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", "audio_h_sel", 21),
+ GATE_AUD1(CLK_AUD_3RD_DAC, "aud_3rd_dac", "audio_sel", 28),
+ GATE_AUD1(CLK_AUD_3RD_DAC_PREDIS, "aud_3rd_dac_predis", "audio_sel", 29),
+ GATE_AUD1(CLK_AUD_3RD_DAC_TML, "aud_3rd_dac_tml", "audio_sel", 30),
+ GATE_AUD1(CLK_AUD_3RD_DAC_HIRES, "aud_3rd_dac_hires", "audio_h_sel", 31),
+ /* AUD2 */
+ GATE_AUD2(CLK_AUD_I2S5_B, "aud_i2s5_b", "audio_sel", 0),
+ GATE_AUD2(CLK_AUD_I2S6_B, "aud_i2s6_b", "audio_sel", 1),
+ GATE_AUD2(CLK_AUD_I2S7_B, "aud_i2s7_b", "audio_sel", 2),
+ GATE_AUD2(CLK_AUD_I2S8_B, "aud_i2s8_b", "audio_sel", 3),
+ GATE_AUD2(CLK_AUD_I2S9_B, "aud_i2s9_b", "audio_sel", 4),
+};
+
+static int clk_mt8192_aud_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ struct device_node *node = pdev->dev.of_node;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
+
+ r = mtk_clk_register_gates(node, aud_clks, ARRAY_SIZE(aud_clks), clk_data);
+ if (r)
+ return r;
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ return r;
+
+ r = devm_of_platform_populate(&pdev->dev);
+ if (r)
+ of_clk_del_provider(node);
+
+ return r;
+}
+
+static const struct of_device_id of_match_clk_mt8192_aud[] = {
+ { .compatible = "mediatek,mt8192-audsys", },
+ {}
+};
+
+static struct platform_driver clk_mt8192_aud_drv = {
+ .probe = clk_mt8192_aud_probe,
+ .driver = {
+ .name = "clk-mt8192-aud",
+ .of_match_table = of_match_clk_mt8192_aud,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_aud_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-cam.c b/drivers/clk/mediatek/clk-mt8192-cam.c
new file mode 100644
index 000000000000..fc74cd80b4b0
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-cam.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs cam_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_CAM(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate cam_clks[] = {
+ GATE_CAM(CLK_CAM_LARB13, "cam_larb13", "cam_sel", 0),
+ GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "cam_sel", 1),
+ GATE_CAM(CLK_CAM_LARB14, "cam_larb14", "cam_sel", 2),
+ GATE_CAM(CLK_CAM_CAM, "cam_cam", "cam_sel", 6),
+ GATE_CAM(CLK_CAM_CAMTG, "cam_camtg", "cam_sel", 7),
+ GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "cam_sel", 8),
+ GATE_CAM(CLK_CAM_CAMSV0, "cam_camsv0", "cam_sel", 9),
+ GATE_CAM(CLK_CAM_CAMSV1, "cam_camsv1", "cam_sel", 10),
+ GATE_CAM(CLK_CAM_CAMSV2, "cam_camsv2", "cam_sel", 11),
+ GATE_CAM(CLK_CAM_CAMSV3, "cam_camsv3", "cam_sel", 12),
+ GATE_CAM(CLK_CAM_CCU0, "cam_ccu0", "cam_sel", 13),
+ GATE_CAM(CLK_CAM_CCU1, "cam_ccu1", "cam_sel", 14),
+ GATE_CAM(CLK_CAM_MRAW0, "cam_mraw0", "cam_sel", 15),
+ GATE_CAM(CLK_CAM_FAKE_ENG, "cam_fake_eng", "cam_sel", 17),
+ GATE_CAM(CLK_CAM_CCU_GALS, "cam_ccu_gals", "cam_sel", 18),
+ GATE_CAM(CLK_CAM_CAM2MM_GALS, "cam2mm_gals", "cam_sel", 19),
+};
+
+static const struct mtk_gate cam_rawa_clks[] = {
+ GATE_CAM(CLK_CAM_RAWA_LARBX, "cam_rawa_larbx", "cam_sel", 0),
+ GATE_CAM(CLK_CAM_RAWA_CAM, "cam_rawa_cam", "cam_sel", 1),
+ GATE_CAM(CLK_CAM_RAWA_CAMTG, "cam_rawa_camtg", "cam_sel", 2),
+};
+
+static const struct mtk_gate cam_rawb_clks[] = {
+ GATE_CAM(CLK_CAM_RAWB_LARBX, "cam_rawb_larbx", "cam_sel", 0),
+ GATE_CAM(CLK_CAM_RAWB_CAM, "cam_rawb_cam", "cam_sel", 1),
+ GATE_CAM(CLK_CAM_RAWB_CAMTG, "cam_rawb_camtg", "cam_sel", 2),
+};
+
+static const struct mtk_gate cam_rawc_clks[] = {
+ GATE_CAM(CLK_CAM_RAWC_LARBX, "cam_rawc_larbx", "cam_sel", 0),
+ GATE_CAM(CLK_CAM_RAWC_CAM, "cam_rawc_cam", "cam_sel", 1),
+ GATE_CAM(CLK_CAM_RAWC_CAMTG, "cam_rawc_camtg", "cam_sel", 2),
+};
+
+static const struct mtk_clk_desc cam_desc = {
+ .clks = cam_clks,
+ .num_clks = ARRAY_SIZE(cam_clks),
+};
+
+static const struct mtk_clk_desc cam_rawa_desc = {
+ .clks = cam_rawa_clks,
+ .num_clks = ARRAY_SIZE(cam_rawa_clks),
+};
+
+static const struct mtk_clk_desc cam_rawb_desc = {
+ .clks = cam_rawb_clks,
+ .num_clks = ARRAY_SIZE(cam_rawb_clks),
+};
+
+static const struct mtk_clk_desc cam_rawc_desc = {
+ .clks = cam_rawc_clks,
+ .num_clks = ARRAY_SIZE(cam_rawc_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_cam[] = {
+ {
+ .compatible = "mediatek,mt8192-camsys",
+ .data = &cam_desc,
+ }, {
+ .compatible = "mediatek,mt8192-camsys_rawa",
+ .data = &cam_rawa_desc,
+ }, {
+ .compatible = "mediatek,mt8192-camsys_rawb",
+ .data = &cam_rawb_desc,
+ }, {
+ .compatible = "mediatek,mt8192-camsys_rawc",
+ .data = &cam_rawc_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_cam_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-cam",
+ .of_match_table = of_match_clk_mt8192_cam,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_cam_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-img.c b/drivers/clk/mediatek/clk-mt8192-img.c
new file mode 100644
index 000000000000..7ce3abe42577
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-img.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate img_clks[] = {
+ GATE_IMG(CLK_IMG_LARB9, "img_larb9", "img1_sel", 0),
+ GATE_IMG(CLK_IMG_LARB10, "img_larb10", "img1_sel", 1),
+ GATE_IMG(CLK_IMG_DIP, "img_dip", "img1_sel", 2),
+ GATE_IMG(CLK_IMG_GALS, "img_gals", "img1_sel", 12),
+};
+
+static const struct mtk_gate img2_clks[] = {
+ GATE_IMG(CLK_IMG2_LARB11, "img2_larb11", "img1_sel", 0),
+ GATE_IMG(CLK_IMG2_LARB12, "img2_larb12", "img1_sel", 1),
+ GATE_IMG(CLK_IMG2_MFB, "img2_mfb", "img1_sel", 6),
+ GATE_IMG(CLK_IMG2_WPE, "img2_wpe", "img1_sel", 7),
+ GATE_IMG(CLK_IMG2_MSS, "img2_mss", "img1_sel", 8),
+ GATE_IMG(CLK_IMG2_GALS, "img2_gals", "img1_sel", 12),
+};
+
+static const struct mtk_clk_desc img_desc = {
+ .clks = img_clks,
+ .num_clks = ARRAY_SIZE(img_clks),
+};
+
+static const struct mtk_clk_desc img2_desc = {
+ .clks = img2_clks,
+ .num_clks = ARRAY_SIZE(img2_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_img[] = {
+ {
+ .compatible = "mediatek,mt8192-imgsys",
+ .data = &img_desc,
+ }, {
+ .compatible = "mediatek,mt8192-imgsys2",
+ .data = &img2_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_img_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-img",
+ .of_match_table = of_match_clk_mt8192_img,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c
new file mode 100644
index 000000000000..700356ac6a58
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs imp_iic_wrap_cg_regs = {
+ .set_ofs = 0xe08,
+ .clr_ofs = 0xe04,
+ .sta_ofs = 0xe00,
+};
+
+#define GATE_IMP_IIC_WRAP(_id, _name, _parent, _shift) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &imp_iic_wrap_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, CLK_OPS_PARENT_ENABLE)
+
+static const struct mtk_gate imp_iic_wrap_c_clks[] = {
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_C_I2C10, "imp_iic_wrap_c_i2c10", "infra_i2c0", 0),
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_C_I2C11, "imp_iic_wrap_c_i2c11", "infra_i2c0", 1),
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_C_I2C12, "imp_iic_wrap_c_i2c12", "infra_i2c0", 2),
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_C_I2C13, "imp_iic_wrap_c_i2c13", "infra_i2c0", 3),
+};
+
+static const struct mtk_gate imp_iic_wrap_e_clks[] = {
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_E_I2C3, "imp_iic_wrap_e_i2c3", "infra_i2c0", 0),
+};
+
+static const struct mtk_gate imp_iic_wrap_n_clks[] = {
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_N_I2C0, "imp_iic_wrap_n_i2c0", "infra_i2c0", 0),
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_N_I2C6, "imp_iic_wrap_n_i2c6", "infra_i2c0", 1),
+};
+
+static const struct mtk_gate imp_iic_wrap_s_clks[] = {
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C7, "imp_iic_wrap_s_i2c7", "infra_i2c0", 0),
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C8, "imp_iic_wrap_s_i2c8", "infra_i2c0", 1),
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C9, "imp_iic_wrap_s_i2c9", "infra_i2c0", 2),
+};
+
+static const struct mtk_gate imp_iic_wrap_w_clks[] = {
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_W_I2C5, "imp_iic_wrap_w_i2c5", "infra_i2c0", 0),
+};
+
+static const struct mtk_gate imp_iic_wrap_ws_clks[] = {
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_WS_I2C1, "imp_iic_wrap_ws_i2c1", "infra_i2c0", 0),
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_WS_I2C2, "imp_iic_wrap_ws_i2c2", "infra_i2c0", 1),
+ GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_WS_I2C4, "imp_iic_wrap_ws_i2c4", "infra_i2c0", 2),
+};
+
+static const struct mtk_clk_desc imp_iic_wrap_c_desc = {
+ .clks = imp_iic_wrap_c_clks,
+ .num_clks = ARRAY_SIZE(imp_iic_wrap_c_clks),
+};
+
+static const struct mtk_clk_desc imp_iic_wrap_e_desc = {
+ .clks = imp_iic_wrap_e_clks,
+ .num_clks = ARRAY_SIZE(imp_iic_wrap_e_clks),
+};
+
+static const struct mtk_clk_desc imp_iic_wrap_n_desc = {
+ .clks = imp_iic_wrap_n_clks,
+ .num_clks = ARRAY_SIZE(imp_iic_wrap_n_clks),
+};
+
+static const struct mtk_clk_desc imp_iic_wrap_s_desc = {
+ .clks = imp_iic_wrap_s_clks,
+ .num_clks = ARRAY_SIZE(imp_iic_wrap_s_clks),
+};
+
+static const struct mtk_clk_desc imp_iic_wrap_w_desc = {
+ .clks = imp_iic_wrap_w_clks,
+ .num_clks = ARRAY_SIZE(imp_iic_wrap_w_clks),
+};
+
+static const struct mtk_clk_desc imp_iic_wrap_ws_desc = {
+ .clks = imp_iic_wrap_ws_clks,
+ .num_clks = ARRAY_SIZE(imp_iic_wrap_ws_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_imp_iic_wrap[] = {
+ {
+ .compatible = "mediatek,mt8192-imp_iic_wrap_c",
+ .data = &imp_iic_wrap_c_desc,
+ }, {
+ .compatible = "mediatek,mt8192-imp_iic_wrap_e",
+ .data = &imp_iic_wrap_e_desc,
+ }, {
+ .compatible = "mediatek,mt8192-imp_iic_wrap_n",
+ .data = &imp_iic_wrap_n_desc,
+ }, {
+ .compatible = "mediatek,mt8192-imp_iic_wrap_s",
+ .data = &imp_iic_wrap_s_desc,
+ }, {
+ .compatible = "mediatek,mt8192-imp_iic_wrap_w",
+ .data = &imp_iic_wrap_w_desc,
+ }, {
+ .compatible = "mediatek,mt8192-imp_iic_wrap_ws",
+ .data = &imp_iic_wrap_ws_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_imp_iic_wrap_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-imp_iic_wrap",
+ .of_match_table = of_match_clk_mt8192_imp_iic_wrap,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_imp_iic_wrap_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-ipe.c b/drivers/clk/mediatek/clk-mt8192-ipe.c
new file mode 100644
index 000000000000..730d91b64b3f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-ipe.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs ipe_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_IPE(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &ipe_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate ipe_clks[] = {
+ GATE_IPE(CLK_IPE_LARB19, "ipe_larb19", "ipe_sel", 0),
+ GATE_IPE(CLK_IPE_LARB20, "ipe_larb20", "ipe_sel", 1),
+ GATE_IPE(CLK_IPE_SMI_SUBCOM, "ipe_smi_subcom", "ipe_sel", 2),
+ GATE_IPE(CLK_IPE_FD, "ipe_fd", "ipe_sel", 3),
+ GATE_IPE(CLK_IPE_FE, "ipe_fe", "ipe_sel", 4),
+ GATE_IPE(CLK_IPE_RSC, "ipe_rsc", "ipe_sel", 5),
+ GATE_IPE(CLK_IPE_DPE, "ipe_dpe", "ipe_sel", 6),
+ GATE_IPE(CLK_IPE_GALS, "ipe_gals", "ipe_sel", 8),
+};
+
+static const struct mtk_clk_desc ipe_desc = {
+ .clks = ipe_clks,
+ .num_clks = ARRAY_SIZE(ipe_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_ipe[] = {
+ {
+ .compatible = "mediatek,mt8192-ipesys",
+ .data = &ipe_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_ipe_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-ipe",
+ .of_match_table = of_match_clk_mt8192_ipe,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_ipe_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-mdp.c b/drivers/clk/mediatek/clk-mt8192-mdp.c
new file mode 100644
index 000000000000..93c87ae2f332
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-mdp.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs mdp0_cg_regs = {
+ .set_ofs = 0x104,
+ .clr_ofs = 0x108,
+ .sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mdp1_cg_regs = {
+ .set_ofs = 0x124,
+ .clr_ofs = 0x128,
+ .sta_ofs = 0x120,
+};
+
+#define GATE_MDP0(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &mdp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_MDP1(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &mdp1_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate mdp_clks[] = {
+ /* MDP0 */
+ GATE_MDP0(CLK_MDP_RDMA0, "mdp_mdp_rdma0", "mdp_sel", 0),
+ GATE_MDP0(CLK_MDP_TDSHP0, "mdp_mdp_tdshp0", "mdp_sel", 1),
+ GATE_MDP0(CLK_MDP_IMG_DL_ASYNC0, "mdp_img_dl_async0", "mdp_sel", 2),
+ GATE_MDP0(CLK_MDP_IMG_DL_ASYNC1, "mdp_img_dl_async1", "mdp_sel", 3),
+ GATE_MDP0(CLK_MDP_RDMA1, "mdp_mdp_rdma1", "mdp_sel", 4),
+ GATE_MDP0(CLK_MDP_TDSHP1, "mdp_mdp_tdshp1", "mdp_sel", 5),
+ GATE_MDP0(CLK_MDP_SMI0, "mdp_smi0", "mdp_sel", 6),
+ GATE_MDP0(CLK_MDP_APB_BUS, "mdp_apb_bus", "mdp_sel", 7),
+ GATE_MDP0(CLK_MDP_WROT0, "mdp_mdp_wrot0", "mdp_sel", 8),
+ GATE_MDP0(CLK_MDP_RSZ0, "mdp_mdp_rsz0", "mdp_sel", 9),
+ GATE_MDP0(CLK_MDP_HDR0, "mdp_mdp_hdr0", "mdp_sel", 10),
+ GATE_MDP0(CLK_MDP_MUTEX0, "mdp_mdp_mutex0", "mdp_sel", 11),
+ GATE_MDP0(CLK_MDP_WROT1, "mdp_mdp_wrot1", "mdp_sel", 12),
+ GATE_MDP0(CLK_MDP_RSZ1, "mdp_mdp_rsz1", "mdp_sel", 13),
+ GATE_MDP0(CLK_MDP_HDR1, "mdp_mdp_hdr1", "mdp_sel", 14),
+ GATE_MDP0(CLK_MDP_FAKE_ENG0, "mdp_mdp_fake_eng0", "mdp_sel", 15),
+ GATE_MDP0(CLK_MDP_AAL0, "mdp_mdp_aal0", "mdp_sel", 16),
+ GATE_MDP0(CLK_MDP_AAL1, "mdp_mdp_aal1", "mdp_sel", 17),
+ GATE_MDP0(CLK_MDP_COLOR0, "mdp_mdp_color0", "mdp_sel", 18),
+ GATE_MDP0(CLK_MDP_COLOR1, "mdp_mdp_color1", "mdp_sel", 19),
+ /* MDP1 */
+ GATE_MDP1(CLK_MDP_IMG_DL_RELAY0_ASYNC0, "mdp_img_dl_relay0_async0", "mdp_sel", 0),
+ GATE_MDP1(CLK_MDP_IMG_DL_RELAY1_ASYNC1, "mdp_img_dl_relay1_async1", "mdp_sel", 8),
+};
+
+static const struct mtk_clk_desc mdp_desc = {
+ .clks = mdp_clks,
+ .num_clks = ARRAY_SIZE(mdp_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_mdp[] = {
+ {
+ .compatible = "mediatek,mt8192-mdpsys",
+ .data = &mdp_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_mdp_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-mdp",
+ .of_match_table = of_match_clk_mt8192_mdp,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_mdp_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-mfg.c b/drivers/clk/mediatek/clk-mt8192-mfg.c
new file mode 100644
index 000000000000..3bbc7469f0e4
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-mfg.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs mfg_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_MFG(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate mfg_clks[] = {
+ GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_pll_sel", 0),
+};
+
+static const struct mtk_clk_desc mfg_desc = {
+ .clks = mfg_clks,
+ .num_clks = ARRAY_SIZE(mfg_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_mfg[] = {
+ {
+ .compatible = "mediatek,mt8192-mfgcfg",
+ .data = &mfg_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_mfg_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-mfg",
+ .of_match_table = of_match_clk_mt8192_mfg,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_mfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-mm.c b/drivers/clk/mediatek/clk-mt8192-mm.c
new file mode 100644
index 000000000000..4a0b4c4bc06a
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-mm.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs mm0_cg_regs = {
+ .set_ofs = 0x104,
+ .clr_ofs = 0x108,
+ .sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mm1_cg_regs = {
+ .set_ofs = 0x114,
+ .clr_ofs = 0x118,
+ .sta_ofs = 0x110,
+};
+
+static const struct mtk_gate_regs mm2_cg_regs = {
+ .set_ofs = 0x1a4,
+ .clr_ofs = 0x1a8,
+ .sta_ofs = 0x1a0,
+};
+
+#define GATE_MM0(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_MM1(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_MM2(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &mm2_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate mm_clks[] = {
+ /* MM0 */
+ GATE_MM0(CLK_MM_DISP_MUTEX0, "mm_disp_mutex0", "disp_sel", 0),
+ GATE_MM0(CLK_MM_DISP_CONFIG, "mm_disp_config", "disp_sel", 1),
+ GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "disp_sel", 2),
+ GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "disp_sel", 3),
+ GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "disp_sel", 4),
+ GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "disp_sel", 5),
+ GATE_MM0(CLK_MM_DISP_UFBC_WDMA0, "mm_disp_ufbc_wdma0", "disp_sel", 6),
+ GATE_MM0(CLK_MM_DISP_RSZ0, "mm_disp_rsz0", "disp_sel", 7),
+ GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "disp_sel", 8),
+ GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "disp_sel", 9),
+ GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "disp_sel", 10),
+ GATE_MM0(CLK_MM_SMI_INFRA, "mm_smi_infra", "disp_sel", 11),
+ GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "disp_sel", 12),
+ GATE_MM0(CLK_MM_DISP_POSTMASK0, "mm_disp_postmask0", "disp_sel", 13),
+ GATE_MM0(CLK_MM_DISP_DSC_WRAP0, "mm_disp_dsc_wrap0", "disp_sel", 14),
+ GATE_MM0(CLK_MM_DSI0, "mm_dsi0", "disp_sel", 15),
+ GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "disp_sel", 16),
+ GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "disp_sel", 17),
+ GATE_MM0(CLK_MM_DISP_FAKE_ENG0, "mm_disp_fake_eng0", "disp_sel", 18),
+ GATE_MM0(CLK_MM_DISP_FAKE_ENG1, "mm_disp_fake_eng1", "disp_sel", 19),
+ GATE_MM0(CLK_MM_MDP_TDSHP4, "mm_mdp_tdshp4", "disp_sel", 20),
+ GATE_MM0(CLK_MM_MDP_RSZ4, "mm_mdp_rsz4", "disp_sel", 21),
+ GATE_MM0(CLK_MM_MDP_AAL4, "mm_mdp_aal4", "disp_sel", 22),
+ GATE_MM0(CLK_MM_MDP_HDR4, "mm_mdp_hdr4", "disp_sel", 23),
+ GATE_MM0(CLK_MM_MDP_RDMA4, "mm_mdp_rdma4", "disp_sel", 24),
+ GATE_MM0(CLK_MM_MDP_COLOR4, "mm_mdp_color4", "disp_sel", 25),
+ GATE_MM0(CLK_MM_DISP_Y2R0, "mm_disp_y2r0", "disp_sel", 26),
+ GATE_MM0(CLK_MM_SMI_GALS, "mm_smi_gals", "disp_sel", 27),
+ GATE_MM0(CLK_MM_DISP_OVL2_2L, "mm_disp_ovl2_2l", "disp_sel", 28),
+ GATE_MM0(CLK_MM_DISP_RDMA4, "mm_disp_rdma4", "disp_sel", 29),
+ GATE_MM0(CLK_MM_DISP_DPI0, "mm_disp_dpi0", "disp_sel", 30),
+ /* MM1 */
+ GATE_MM1(CLK_MM_SMI_IOMMU, "mm_smi_iommu", "disp_sel", 0),
+ /* MM2 */
+ GATE_MM2(CLK_MM_DSI_DSI0, "mm_dsi_dsi0", "disp_sel", 0),
+ GATE_MM2(CLK_MM_DPI_DPI0, "mm_dpi_dpi0", "dpi_sel", 8),
+ GATE_MM2(CLK_MM_26MHZ, "mm_26mhz", "clk26m", 24),
+ GATE_MM2(CLK_MM_32KHZ, "mm_32khz", "clk32k", 25),
+};
+
+static int clk_mt8192_mm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->parent->of_node;
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
+
+ r = mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data);
+ if (r)
+ return r;
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static struct platform_driver clk_mt8192_mm_drv = {
+ .probe = clk_mt8192_mm_probe,
+ .driver = {
+ .name = "clk-mt8192-mm",
+ },
+};
+
+builtin_platform_driver(clk_mt8192_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-msdc.c b/drivers/clk/mediatek/clk-mt8192-msdc.c
new file mode 100644
index 000000000000..87c3b79b79cf
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-msdc.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs msdc_cg_regs = {
+ .set_ofs = 0xb4,
+ .clr_ofs = 0xb4,
+ .sta_ofs = 0xb4,
+};
+
+static const struct mtk_gate_regs msdc_top_cg_regs = {
+ .set_ofs = 0x0,
+ .clr_ofs = 0x0,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_MSDC(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &msdc_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+#define GATE_MSDC_TOP(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &msdc_top_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate msdc_clks[] = {
+ GATE_MSDC(CLK_MSDC_AXI_WRAP, "msdc_axi_wrap", "axi_sel", 22),
+};
+
+static const struct mtk_gate msdc_top_clks[] = {
+ GATE_MSDC_TOP(CLK_MSDC_TOP_AES_0P, "msdc_top_aes_0p", "aes_msdcfde_sel", 0),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_SRC_0P, "msdc_top_src_0p", "infra_msdc0_src", 1),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_SRC_1P, "msdc_top_src_1p", "infra_msdc1_src", 2),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_SRC_2P, "msdc_top_src_2p", "infra_msdc2_src", 3),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_P_MSDC0, "msdc_top_p_msdc0", "axi_sel", 4),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_P_MSDC1, "msdc_top_p_msdc1", "axi_sel", 5),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_P_MSDC2, "msdc_top_p_msdc2", "axi_sel", 6),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_P_CFG, "msdc_top_p_cfg", "axi_sel", 7),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_AXI, "msdc_top_axi", "axi_sel", 8),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_H_MST_0P, "msdc_top_h_mst_0p", "infra_msdc0", 9),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_H_MST_1P, "msdc_top_h_mst_1p", "infra_msdc1", 10),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_H_MST_2P, "msdc_top_h_mst_2p", "infra_msdc2", 11),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_MEM_OFF_DLY_26M, "msdc_top_mem_off_dly_26m", "clk26m", 12),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_32K, "msdc_top_32k", "clk32k", 13),
+ GATE_MSDC_TOP(CLK_MSDC_TOP_AHB2AXI_BRG_AXI, "msdc_top_ahb2axi_brg_axi", "axi_sel", 14),
+};
+
+static const struct mtk_clk_desc msdc_desc = {
+ .clks = msdc_clks,
+ .num_clks = ARRAY_SIZE(msdc_clks),
+};
+
+static const struct mtk_clk_desc msdc_top_desc = {
+ .clks = msdc_top_clks,
+ .num_clks = ARRAY_SIZE(msdc_top_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_msdc[] = {
+ {
+ .compatible = "mediatek,mt8192-msdc",
+ .data = &msdc_desc,
+ }, {
+ .compatible = "mediatek,mt8192-msdc_top",
+ .data = &msdc_top_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_msdc_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-msdc",
+ .of_match_table = of_match_clk_mt8192_msdc,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_msdc_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-scp_adsp.c b/drivers/clk/mediatek/clk-mt8192-scp_adsp.c
new file mode 100644
index 000000000000..58725d79dd13
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-scp_adsp.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs scp_adsp_cg_regs = {
+ .set_ofs = 0x180,
+ .clr_ofs = 0x180,
+ .sta_ofs = 0x180,
+};
+
+#define GATE_SCP_ADSP(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &scp_adsp_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
+
+static const struct mtk_gate scp_adsp_clks[] = {
+ GATE_SCP_ADSP(CLK_SCP_ADSP_AUDIODSP, "scp_adsp_audiodsp", "adsp_sel", 0),
+};
+
+static const struct mtk_clk_desc scp_adsp_desc = {
+ .clks = scp_adsp_clks,
+ .num_clks = ARRAY_SIZE(scp_adsp_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_scp_adsp[] = {
+ {
+ .compatible = "mediatek,mt8192-scp_adsp",
+ .data = &scp_adsp_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_scp_adsp_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-scp_adsp",
+ .of_match_table = of_match_clk_mt8192_scp_adsp,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_scp_adsp_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-vdec.c b/drivers/clk/mediatek/clk-mt8192-vdec.c
new file mode 100644
index 000000000000..b1d95cfbf22a
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-vdec.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+ .set_ofs = 0x0,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+ .set_ofs = 0x200,
+ .clr_ofs = 0x204,
+ .sta_ofs = 0x200,
+};
+
+static const struct mtk_gate_regs vdec2_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0xc,
+ .sta_ofs = 0x8,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
+
+#define GATE_VDEC2(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &vdec2_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
+
+static const struct mtk_gate vdec_clks[] = {
+ /* VDEC0 */
+ GATE_VDEC0(CLK_VDEC_VDEC, "vdec_vdec", "vdec_sel", 0),
+ GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "vdec_sel", 4),
+ /* VDEC1 */
+ GATE_VDEC1(CLK_VDEC_LAT, "vdec_lat", "vdec_sel", 0),
+ GATE_VDEC1(CLK_VDEC_LAT_ACTIVE, "vdec_lat_active", "vdec_sel", 4),
+ /* VDEC2 */
+ GATE_VDEC2(CLK_VDEC_LARB1, "vdec_larb1", "vdec_sel", 0),
+};
+
+static const struct mtk_gate vdec_soc_clks[] = {
+ /* VDEC_SOC0 */
+ GATE_VDEC0(CLK_VDEC_SOC_VDEC, "vdec_soc_vdec", "vdec_sel", 0),
+ GATE_VDEC0(CLK_VDEC_SOC_VDEC_ACTIVE, "vdec_soc_vdec_active", "vdec_sel", 4),
+ /* VDEC_SOC1 */
+ GATE_VDEC1(CLK_VDEC_SOC_LAT, "vdec_soc_lat", "vdec_sel", 0),
+ GATE_VDEC1(CLK_VDEC_SOC_LAT_ACTIVE, "vdec_soc_lat_active", "vdec_sel", 4),
+ /* VDEC_SOC2 */
+ GATE_VDEC2(CLK_VDEC_SOC_LARB1, "vdec_soc_larb1", "vdec_sel", 0),
+};
+
+static const struct mtk_clk_desc vdec_desc = {
+ .clks = vdec_clks,
+ .num_clks = ARRAY_SIZE(vdec_clks),
+};
+
+static const struct mtk_clk_desc vdec_soc_desc = {
+ .clks = vdec_soc_clks,
+ .num_clks = ARRAY_SIZE(vdec_soc_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_vdec[] = {
+ {
+ .compatible = "mediatek,mt8192-vdecsys",
+ .data = &vdec_desc,
+ }, {
+ .compatible = "mediatek,mt8192-vdecsys_soc",
+ .data = &vdec_soc_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_vdec_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-vdec",
+ .of_match_table = of_match_clk_mt8192_vdec,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192-venc.c b/drivers/clk/mediatek/clk-mt8192-venc.c
new file mode 100644
index 000000000000..c0d867bff09e
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192-venc.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static const struct mtk_gate_regs venc_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_VENC(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
+
+static const struct mtk_gate venc_clks[] = {
+ GATE_VENC(CLK_VENC_SET0_LARB, "venc_set0_larb", "venc_sel", 0),
+ GATE_VENC(CLK_VENC_SET1_VENC, "venc_set1_venc", "venc_sel", 4),
+ GATE_VENC(CLK_VENC_SET2_JPGENC, "venc_set2_jpgenc", "venc_sel", 8),
+ GATE_VENC(CLK_VENC_SET5_GALS, "venc_set5_gals", "venc_sel", 28),
+};
+
+static const struct mtk_clk_desc venc_desc = {
+ .clks = venc_clks,
+ .num_clks = ARRAY_SIZE(venc_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8192_venc[] = {
+ {
+ .compatible = "mediatek,mt8192-vencsys",
+ .data = &venc_desc,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver clk_mt8192_venc_drv = {
+ .probe = mtk_clk_simple_probe,
+ .driver = {
+ .name = "clk-mt8192-venc",
+ .of_match_table = of_match_clk_mt8192_venc,
+ },
+};
+
+builtin_platform_driver(clk_mt8192_venc_drv);
diff --git a/drivers/clk/mediatek/clk-mt8192.c b/drivers/clk/mediatek/clk-mt8192.c
new file mode 100644
index 000000000000..cbc7c6dbe0f4
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8192.c
@@ -0,0 +1,1326 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8192-clk.h>
+
+static DEFINE_SPINLOCK(mt8192_clk_lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+ FIXED_CLK(CLK_TOP_ULPOSC, "ulposc", NULL, 260000000),
+};
+
+static const struct mtk_fixed_factor top_early_divs[] = {
+ FACTOR(CLK_TOP_CSW_F26M_D2, "csw_f26m_d2", "clk26m", 1, 2),
+};
+
+static const struct mtk_fixed_factor top_divs[] = {
+ FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3),
+ FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4),
+ FACTOR(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll_d4", 1, 2),
+ FACTOR(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll_d4", 1, 4),
+ FACTOR(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll_d4", 1, 8),
+ FACTOR(CLK_TOP_MAINPLL_D4_D16, "mainpll_d4_d16", "mainpll_d4", 1, 16),
+ FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2),
+ FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4),
+ FACTOR(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll_d5", 1, 8),
+ FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6),
+ FACTOR(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll_d6", 1, 2),
+ FACTOR(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll_d6", 1, 4),
+ FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7),
+ FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2),
+ FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4),
+ FACTOR(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll_d7", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+ FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll_d4", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll_d4", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll_d4", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6),
+ FACTOR(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll_d6", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll_d6", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll_d6", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll_d6", 1, 16),
+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+ FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
+ FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2),
+ FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4),
+ FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8),
+ FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
+ FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2),
+ FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4),
+ FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, 8),
+ FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4),
+ FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll_d4", 1, 2),
+ FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+ FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll_d5", 1, 2),
+ FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1, 6),
+ FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll_d6", 1, 2),
+ FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+ FACTOR(CLK_TOP_MMPLL_D9, "mmpll_d9", "mmpll", 1, 9),
+ FACTOR(CLK_TOP_APUPLL, "apupll_ck", "apupll", 1, 2),
+ FACTOR(CLK_TOP_NPUPLL, "npupll_ck", "npupll", 1, 1),
+ FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1),
+ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+ FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1, 8),
+ FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1, 16),
+ FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+ FACTOR(CLK_TOP_OSC_D2, "osc_d2", "ulposc", 1, 2),
+ FACTOR(CLK_TOP_OSC_D4, "osc_d4", "ulposc", 1, 4),
+ FACTOR(CLK_TOP_OSC_D8, "osc_d8", "ulposc", 1, 8),
+ FACTOR(CLK_TOP_OSC_D10, "osc_d10", "ulposc", 1, 10),
+ FACTOR(CLK_TOP_OSC_D16, "osc_d16", "ulposc", 1, 16),
+ FACTOR(CLK_TOP_OSC_D20, "osc_d20", "ulposc", 1, 20),
+ FACTOR(CLK_TOP_ADSPPLL, "adsppll_ck", "adsppll", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D2, "univpll_192m_d2", "univpll_192m", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32),
+};
+
+static const char * const axi_parents[] = {
+ "clk26m",
+ "mainpll_d4_d4",
+ "mainpll_d7_d2",
+ "mainpll_d4_d2",
+ "mainpll_d5_d2",
+ "mainpll_d6_d2",
+ "osc_d4"
+};
+
+static const char * const spm_parents[] = {
+ "clk26m",
+ "osc_d10",
+ "mainpll_d7_d4",
+ "clk32k"
+};
+
+static const char * const scp_parents[] = {
+ "clk26m",
+ "univpll_d5",
+ "mainpll_d6_d2",
+ "mainpll_d6",
+ "univpll_d6",
+ "mainpll_d4_d2",
+ "mainpll_d5_d2",
+ "univpll_d4_d2"
+};
+
+static const char * const bus_aximem_parents[] = {
+ "clk26m",
+ "mainpll_d7_d2",
+ "mainpll_d4_d2",
+ "mainpll_d5_d2",
+ "mainpll_d6"
+};
+
+static const char * const disp_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "mainpll_d5_d2",
+ "mmpll_d6_d2",
+ "univpll_d5_d2",
+ "univpll_d4_d2",
+ "mmpll_d7",
+ "univpll_d6",
+ "mainpll_d4",
+ "mmpll_d5_d2"
+};
+
+static const char * const mdp_parents[] = {
+ "clk26m",
+ "mainpll_d5_d2",
+ "mmpll_d6_d2",
+ "mainpll_d4_d2",
+ "mmpll_d4_d2",
+ "mainpll_d6",
+ "univpll_d6",
+ "mainpll_d4",
+ "tvdpll_ck",
+ "univpll_d4",
+ "mmpll_d5_d2"
+};
+
+static const char * const img1_parents[] = {
+ "clk26m",
+ "univpll_d4",
+ "tvdpll_ck",
+ "mainpll_d4",
+ "univpll_d5",
+ "mmpll_d6",
+ "univpll_d6",
+ "mainpll_d6",
+ "mmpll_d4_d2",
+ "mainpll_d4_d2",
+ "mmpll_d6_d2",
+ "mmpll_d5_d2"
+};
+
+static const char * const img2_parents[] = {
+ "clk26m",
+ "univpll_d4",
+ "tvdpll_ck",
+ "mainpll_d4",
+ "univpll_d5",
+ "mmpll_d6",
+ "univpll_d6",
+ "mainpll_d6",
+ "mmpll_d4_d2",
+ "mainpll_d4_d2",
+ "mmpll_d6_d2",
+ "mmpll_d5_d2"
+};
+
+static const char * const ipe_parents[] = {
+ "clk26m",
+ "mainpll_d4",
+ "mmpll_d6",
+ "univpll_d6",
+ "mainpll_d6",
+ "univpll_d4_d2",
+ "mainpll_d4_d2",
+ "mmpll_d6_d2",
+ "mmpll_d5_d2"
+};
+
+static const char * const dpe_parents[] = {
+ "clk26m",
+ "mainpll_d4",
+ "mmpll_d6",
+ "univpll_d6",
+ "mainpll_d6",
+ "univpll_d4_d2",
+ "univpll_d5_d2",
+ "mmpll_d6_d2"
+};
+
+static const char * const cam_parents[] = {
+ "clk26m",
+ "mainpll_d4",
+ "mmpll_d6",
+ "univpll_d4",
+ "univpll_d5",
+ "univpll_d6",
+ "mmpll_d7",
+ "univpll_d4_d2",
+ "mainpll_d4_d2",
+ "univpll_d6_d2"
+};
+
+static const char * const ccu_parents[] = {
+ "clk26m",
+ "mainpll_d4",
+ "mmpll_d6",
+ "mainpll_d6",
+ "mmpll_d7",
+ "univpll_d4_d2",
+ "mmpll_d6_d2",
+ "mmpll_d5_d2",
+ "univpll_d5",
+ "univpll_d6_d2"
+};
+
+static const char * const dsp7_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "mainpll_d6",
+ "mmpll_d6",
+ "univpll_d5",
+ "mmpll_d5",
+ "univpll_d4",
+ "mmpll_d4"
+};
+
+static const char * const mfg_ref_parents[] = {
+ "clk26m",
+ "clk26m",
+ "univpll_d6",
+ "mainpll_d5_d2"
+};
+
+static const char * const mfg_pll_parents[] = {
+ "mfg_ref_sel",
+ "mfgpll"
+};
+
+static const char * const camtg_parents[] = {
+ "clk26m",
+ "univpll_192m_d8",
+ "univpll_d6_d8",
+ "univpll_192m_d4",
+ "univpll_d6_d16",
+ "csw_f26m_d2",
+ "univpll_192m_d16",
+ "univpll_192m_d32"
+};
+
+static const char * const camtg2_parents[] = {
+ "clk26m",
+ "univpll_192m_d8",
+ "univpll_d6_d8",
+ "univpll_192m_d4",
+ "univpll_d6_d16",
+ "csw_f26m_d2",
+ "univpll_192m_d16",
+ "univpll_192m_d32"
+};
+
+static const char * const camtg3_parents[] = {
+ "clk26m",
+ "univpll_192m_d8",
+ "univpll_d6_d8",
+ "univpll_192m_d4",
+ "univpll_d6_d16",
+ "csw_f26m_d2",
+ "univpll_192m_d16",
+ "univpll_192m_d32"
+};
+
+static const char * const camtg4_parents[] = {
+ "clk26m",
+ "univpll_192m_d8",
+ "univpll_d6_d8",
+ "univpll_192m_d4",
+ "univpll_d6_d16",
+ "csw_f26m_d2",
+ "univpll_192m_d16",
+ "univpll_192m_d32"
+};
+
+static const char * const camtg5_parents[] = {
+ "clk26m",
+ "univpll_192m_d8",
+ "univpll_d6_d8",
+ "univpll_192m_d4",
+ "univpll_d6_d16",
+ "csw_f26m_d2",
+ "univpll_192m_d16",
+ "univpll_192m_d32"
+};
+
+static const char * const camtg6_parents[] = {
+ "clk26m",
+ "univpll_192m_d8",
+ "univpll_d6_d8",
+ "univpll_192m_d4",
+ "univpll_d6_d16",
+ "csw_f26m_d2",
+ "univpll_192m_d16",
+ "univpll_192m_d32"
+};
+
+static const char * const uart_parents[] = {
+ "clk26m",
+ "univpll_d6_d8"
+};
+
+static const char * const spi_parents[] = {
+ "clk26m",
+ "mainpll_d5_d4",
+ "mainpll_d6_d4",
+ "msdcpll_d4"
+};
+
+static const char * const msdc50_0_h_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "mainpll_d6_d2"
+};
+
+static const char * const msdc50_0_parents[] = {
+ "clk26m",
+ "msdcpll_ck",
+ "msdcpll_d2",
+ "univpll_d4_d4",
+ "mainpll_d6_d2",
+ "univpll_d4_d2"
+};
+
+static const char * const msdc30_1_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "mainpll_d6_d2",
+ "mainpll_d7_d2",
+ "msdcpll_d2"
+};
+
+static const char * const msdc30_2_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "mainpll_d6_d2",
+ "mainpll_d7_d2",
+ "msdcpll_d2"
+};
+
+static const char * const audio_parents[] = {
+ "clk26m",
+ "mainpll_d5_d8",
+ "mainpll_d7_d8",
+ "mainpll_d4_d16"
+};
+
+static const char * const aud_intbus_parents[] = {
+ "clk26m",
+ "mainpll_d4_d4",
+ "mainpll_d7_d4"
+};
+
+static const char * const pwrap_ulposc_parents[] = {
+ "osc_d10",
+ "clk26m",
+ "osc_d4",
+ "osc_d8",
+ "osc_d16"
+};
+
+static const char * const atb_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "mainpll_d5_d2"
+};
+
+static const char * const dpi_parents[] = {
+ "clk26m",
+ "tvdpll_d2",
+ "tvdpll_d4",
+ "tvdpll_d8",
+ "tvdpll_d16"
+};
+
+static const char * const scam_parents[] = {
+ "clk26m",
+ "mainpll_d5_d4"
+};
+
+static const char * const disp_pwm_parents[] = {
+ "clk26m",
+ "univpll_d6_d4",
+ "osc_d2",
+ "osc_d4",
+ "osc_d16"
+};
+
+static const char * const usb_top_parents[] = {
+ "clk26m",
+ "univpll_d5_d4",
+ "univpll_d6_d4",
+ "univpll_d5_d2"
+};
+
+static const char * const ssusb_xhci_parents[] = {
+ "clk26m",
+ "univpll_d5_d4",
+ "univpll_d6_d4",
+ "univpll_d5_d2"
+};
+
+static const char * const i2c_parents[] = {
+ "clk26m",
+ "mainpll_d4_d8",
+ "univpll_d5_d4"
+};
+
+static const char * const seninf_parents[] = {
+ "clk26m",
+ "univpll_d4_d4",
+ "univpll_d6_d2",
+ "univpll_d4_d2",
+ "univpll_d7",
+ "univpll_d6",
+ "mmpll_d6",
+ "univpll_d5"
+};
+
+static const char * const seninf1_parents[] = {
+ "clk26m",
+ "univpll_d4_d4",
+ "univpll_d6_d2",
+ "univpll_d4_d2",
+ "univpll_d7",
+ "univpll_d6",
+ "mmpll_d6",
+ "univpll_d5"
+};
+
+static const char * const seninf2_parents[] = {
+ "clk26m",
+ "univpll_d4_d4",
+ "univpll_d6_d2",
+ "univpll_d4_d2",
+ "univpll_d7",
+ "univpll_d6",
+ "mmpll_d6",
+ "univpll_d5"
+};
+
+static const char * const seninf3_parents[] = {
+ "clk26m",
+ "univpll_d4_d4",
+ "univpll_d6_d2",
+ "univpll_d4_d2",
+ "univpll_d7",
+ "univpll_d6",
+ "mmpll_d6",
+ "univpll_d5"
+};
+
+static const char * const tl_parents[] = {
+ "clk26m",
+ "univpll_192m_d2",
+ "mainpll_d6_d4"
+};
+
+static const char * const dxcc_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "mainpll_d4_d4",
+ "mainpll_d4_d8"
+};
+
+static const char * const aud_engen1_parents[] = {
+ "clk26m",
+ "apll1_d2",
+ "apll1_d4",
+ "apll1_d8"
+};
+
+static const char * const aud_engen2_parents[] = {
+ "clk26m",
+ "apll2_d2",
+ "apll2_d4",
+ "apll2_d8"
+};
+
+static const char * const aes_ufsfde_parents[] = {
+ "clk26m",
+ "mainpll_d4",
+ "mainpll_d4_d2",
+ "mainpll_d6",
+ "mainpll_d4_d4",
+ "univpll_d4_d2",
+ "univpll_d6"
+};
+
+static const char * const ufs_parents[] = {
+ "clk26m",
+ "mainpll_d4_d4",
+ "mainpll_d4_d8",
+ "univpll_d4_d4",
+ "mainpll_d6_d2",
+ "mainpll_d5_d2",
+ "msdcpll_d2"
+};
+
+static const char * const aud_1_parents[] = {
+ "clk26m",
+ "apll1_ck"
+};
+
+static const char * const aud_2_parents[] = {
+ "clk26m",
+ "apll2_ck"
+};
+
+static const char * const adsp_parents[] = {
+ "clk26m",
+ "mainpll_d6",
+ "mainpll_d5_d2",
+ "univpll_d4_d4",
+ "univpll_d4",
+ "univpll_d6",
+ "ulposc",
+ "adsppll_ck"
+};
+
+static const char * const dpmaif_main_parents[] = {
+ "clk26m",
+ "univpll_d4_d4",
+ "mainpll_d6",
+ "mainpll_d4_d2",
+ "univpll_d4_d2"
+};
+
+static const char * const venc_parents[] = {
+ "clk26m",
+ "mmpll_d7",
+ "mainpll_d6",
+ "univpll_d4_d2",
+ "mainpll_d4_d2",
+ "univpll_d6",
+ "mmpll_d6",
+ "mainpll_d5_d2",
+ "mainpll_d6_d2",
+ "mmpll_d9",
+ "univpll_d4_d4",
+ "mainpll_d4",
+ "univpll_d4",
+ "univpll_d5",
+ "univpll_d5_d2",
+ "mainpll_d5"
+};
+
+static const char * const vdec_parents[] = {
+ "clk26m",
+ "univpll_192m_d2",
+ "univpll_d5_d4",
+ "mainpll_d5",
+ "mainpll_d5_d2",
+ "mmpll_d6_d2",
+ "univpll_d5_d2",
+ "mainpll_d4_d2",
+ "univpll_d4_d2",
+ "univpll_d7",
+ "mmpll_d7",
+ "mmpll_d6",
+ "univpll_d5",
+ "mainpll_d4",
+ "univpll_d4",
+ "univpll_d6"
+};
+
+static const char * const camtm_parents[] = {
+ "clk26m",
+ "univpll_d7",
+ "univpll_d6_d2",
+ "univpll_d4_d2"
+};
+
+static const char * const pwm_parents[] = {
+ "clk26m",
+ "univpll_d4_d8"
+};
+
+static const char * const audio_h_parents[] = {
+ "clk26m",
+ "univpll_d7",
+ "apll1_ck",
+ "apll2_ck"
+};
+
+static const char * const spmi_mst_parents[] = {
+ "clk26m",
+ "csw_f26m_d2",
+ "osc_d8",
+ "osc_d10",
+ "osc_d16",
+ "osc_d20",
+ "clk32k"
+};
+
+static const char * const aes_msdcfde_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "mainpll_d6",
+ "mainpll_d4_d4",
+ "univpll_d4_d2",
+ "univpll_d6"
+};
+
+static const char * const sflash_parents[] = {
+ "clk26m",
+ "mainpll_d7_d8",
+ "univpll_d6_d8",
+ "univpll_d5_d8"
+};
+
+static const char * const apll_i2s0_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s1_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s2_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s3_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s4_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s5_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s6_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s7_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s8_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const apll_i2s9_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+/*
+ * CRITICAL CLOCK:
+ * axi_sel is the main bus clock of whole SOC.
+ * spm_sel is the clock of the always-on co-processor.
+ * bus_aximem_sel is clock of the bus that access emi.
+ */
+static const struct mtk_mux top_mtk_muxes[] = {
+ /* CLK_CFG_0 */
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel",
+ axi_parents, 0x010, 0x014, 0x018, 0, 3, 7, 0x004, 0,
+ CLK_IS_CRITICAL),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM_SEL, "spm_sel",
+ spm_parents, 0x010, 0x014, 0x018, 8, 2, 15, 0x004, 1,
+ CLK_IS_CRITICAL),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel",
+ scp_parents, 0x010, 0x014, 0x018, 16, 3, 23, 0x004, 2),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM_SEL, "bus_aximem_sel",
+ bus_aximem_parents, 0x010, 0x014, 0x018, 24, 3, 31, 0x004, 3,
+ CLK_IS_CRITICAL),
+ /* CLK_CFG_1 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_SEL, "disp_sel",
+ disp_parents, 0x020, 0x024, 0x028, 0, 4, 7, 0x004, 4),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MDP_SEL, "mdp_sel",
+ mdp_parents, 0x020, 0x024, 0x028, 8, 4, 15, 0x004, 5),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG1_SEL, "img1_sel",
+ img1_parents, 0x020, 0x024, 0x028, 16, 4, 23, 0x004, 6),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG2_SEL, "img2_sel",
+ img2_parents, 0x020, 0x024, 0x028, 24, 4, 31, 0x004, 7),
+ /* CLK_CFG_2 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_IPE_SEL, "ipe_sel",
+ ipe_parents, 0x030, 0x034, 0x038, 0, 4, 7, 0x004, 8),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DPE_SEL, "dpe_sel",
+ dpe_parents, 0x030, 0x034, 0x038, 8, 3, 15, 0x004, 9),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAM_SEL, "cam_sel",
+ cam_parents, 0x030, 0x034, 0x038, 16, 4, 23, 0x004, 10),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CCU_SEL, "ccu_sel",
+ ccu_parents, 0x030, 0x034, 0x038, 24, 4, 31, 0x004, 11),
+ /* CLK_CFG_4 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP7_SEL, "dsp7_sel",
+ dsp7_parents, 0x050, 0x054, 0x058, 0, 3, 7, 0x004, 16),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_REF_SEL, "mfg_ref_sel",
+ mfg_ref_parents, 0x050, 0x054, 0x058, 16, 2, 23, 0x004, 18),
+ MUX_CLR_SET_UPD(CLK_TOP_MFG_PLL_SEL, "mfg_pll_sel",
+ mfg_pll_parents, 0x050, 0x054, 0x058, 18, 1, -1, -1),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG_SEL, "camtg_sel",
+ camtg_parents, 0x050, 0x054, 0x058, 24, 3, 31, 0x004, 19),
+ /* CLK_CFG_5 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG2_SEL, "camtg2_sel",
+ camtg2_parents, 0x060, 0x064, 0x068, 0, 3, 7, 0x004, 20),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG3_SEL, "camtg3_sel",
+ camtg3_parents, 0x060, 0x064, 0x068, 8, 3, 15, 0x004, 21),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG4_SEL, "camtg4_sel",
+ camtg4_parents, 0x060, 0x064, 0x068, 16, 3, 23, 0x004, 22),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG5_SEL, "camtg5_sel",
+ camtg5_parents, 0x060, 0x064, 0x068, 24, 3, 31, 0x004, 23),
+ /* CLK_CFG_6 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG6_SEL, "camtg6_sel",
+ camtg6_parents, 0x070, 0x074, 0x078, 0, 3, 7, 0x004, 24),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel",
+ uart_parents, 0x070, 0x074, 0x078, 8, 1, 15, 0x004, 25),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel",
+ spi_parents, 0x070, 0x074, 0x078, 16, 2, 23, 0x004, 26),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel",
+ msdc50_0_h_parents, 0x070, 0x074, 0x078, 24, 2, 31, 0x004, 27),
+ /* CLK_CFG_7 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
+ msdc50_0_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x004, 28),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
+ msdc30_1_parents, 0x080, 0x084, 0x088, 8, 3, 15, 0x004, 29),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel",
+ msdc30_2_parents, 0x080, 0x084, 0x088, 16, 3, 23, 0x004, 30),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel",
+ audio_parents, 0x080, 0x084, 0x088, 24, 2, 31, 0x008, 0),
+ /* CLK_CFG_8 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel",
+ aud_intbus_parents, 0x090, 0x094, 0x098, 0, 2, 7, 0x008, 1),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PWRAP_ULPOSC_SEL, "pwrap_ulposc_sel",
+ pwrap_ulposc_parents, 0x090, 0x094, 0x098, 8, 3, 15, 0x008, 2),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel",
+ atb_parents, 0x090, 0x094, 0x098, 16, 2, 23, 0x008, 3),
+ /* CLK_CFG_9 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI_SEL, "dpi_sel",
+ dpi_parents, 0x0a0, 0x0a4, 0x0a8, 0, 3, 7, 0x008, 5),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SCAM_SEL, "scam_sel",
+ scam_parents, 0x0a0, 0x0a4, 0x0a8, 8, 1, 15, 0x008, 6),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM_SEL, "disp_pwm_sel",
+ disp_pwm_parents, 0x0a0, 0x0a4, 0x0a8, 16, 3, 23, 0x008, 7),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_SEL, "usb_top_sel",
+ usb_top_parents, 0x0a0, 0x0a4, 0x0a8, 24, 2, 31, 0x008, 8),
+ /* CLK_CFG_10 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI_SEL, "ssusb_xhci_sel",
+ ssusb_xhci_parents, 0x0b0, 0x0b4, 0x0b8, 0, 2, 7, 0x008, 9),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel",
+ i2c_parents, 0x0b0, 0x0b4, 0x0b8, 8, 2, 15, 0x008, 10),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF_SEL, "seninf_sel",
+ seninf_parents, 0x0b0, 0x0b4, 0x0b8, 16, 3, 23, 0x008, 11),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF1_SEL, "seninf1_sel",
+ seninf1_parents, 0x0b0, 0x0b4, 0x0b8, 24, 3, 31, 0x008, 12),
+ /* CLK_CFG_11 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF2_SEL, "seninf2_sel",
+ seninf2_parents, 0x0c0, 0x0c4, 0x0c8, 0, 3, 7, 0x008, 13),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF3_SEL, "seninf3_sel",
+ seninf3_parents, 0x0c0, 0x0c4, 0x0c8, 8, 3, 15, 0x008, 14),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_TL_SEL, "tl_sel",
+ tl_parents, 0x0c0, 0x0c4, 0x0c8, 16, 2, 23, 0x008, 15),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC_SEL, "dxcc_sel",
+ dxcc_parents, 0x0c0, 0x0c4, 0x0c8, 24, 2, 31, 0x008, 16),
+ /* CLK_CFG_12 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel",
+ aud_engen1_parents, 0x0d0, 0x0d4, 0x0d8, 0, 2, 7, 0x008, 17),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel",
+ aud_engen2_parents, 0x0d0, 0x0d4, 0x0d8, 8, 2, 15, 0x008, 18),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_UFSFDE_SEL, "aes_ufsfde_sel",
+ aes_ufsfde_parents, 0x0d0, 0x0d4, 0x0d8, 16, 3, 23, 0x008, 19),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_UFS_SEL, "ufs_sel",
+ ufs_parents, 0x0d0, 0x0d4, 0x0d8, 24, 3, 31, 0x008, 20),
+ /* CLK_CFG_13 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1_SEL, "aud_1_sel",
+ aud_1_parents, 0x0e0, 0x0e4, 0x0e8, 0, 1, 7, 0x008, 21),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_2_SEL, "aud_2_sel",
+ aud_2_parents, 0x0e0, 0x0e4, 0x0e8, 8, 1, 15, 0x008, 22),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ADSP_SEL, "adsp_sel",
+ adsp_parents, 0x0e0, 0x0e4, 0x0e8, 16, 3, 23, 0x008, 23),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DPMAIF_MAIN_SEL, "dpmaif_main_sel",
+ dpmaif_main_parents, 0x0e0, 0x0e4, 0x0e8, 24, 3, 31, 0x008, 24),
+ /* CLK_CFG_14 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_VENC_SEL, "venc_sel",
+ venc_parents, 0x0f0, 0x0f4, 0x0f8, 0, 4, 7, 0x008, 25),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC_SEL, "vdec_sel",
+ vdec_parents, 0x0f0, 0x0f4, 0x0f8, 8, 4, 15, 0x008, 26),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel",
+ camtm_parents, 0x0f0, 0x0f4, 0x0f8, 16, 2, 23, 0x008, 27),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel",
+ pwm_parents, 0x0f0, 0x0f4, 0x0f8, 24, 1, 31, 0x008, 28),
+ /* CLK_CFG_15 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_H_SEL, "audio_h_sel",
+ audio_h_parents, 0x100, 0x104, 0x108, 0, 2, 7, 0x008, 29),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_MST_SEL, "spmi_mst_sel",
+ spmi_mst_parents, 0x100, 0x104, 0x108, 8, 3, 15, 0x008, 30),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE_SEL, "aes_msdcfde_sel",
+ aes_msdcfde_parents, 0x100, 0x104, 0x108, 24, 3, 31, 0x00c, 1),
+ /* CLK_CFG_16 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SFLASH_SEL, "sflash_sel",
+ sflash_parents, 0x110, 0x114, 0x118, 8, 2, 15, 0x00c, 3),
+};
+
+static struct mtk_composite top_muxes[] = {
+ /* CLK_AUDDIV_0 */
+ MUX(CLK_TOP_APLL_I2S0_M_SEL, "apll_i2s0_m_sel", apll_i2s0_m_parents, 0x320, 16, 1),
+ MUX(CLK_TOP_APLL_I2S1_M_SEL, "apll_i2s1_m_sel", apll_i2s1_m_parents, 0x320, 17, 1),
+ MUX(CLK_TOP_APLL_I2S2_M_SEL, "apll_i2s2_m_sel", apll_i2s2_m_parents, 0x320, 18, 1),
+ MUX(CLK_TOP_APLL_I2S3_M_SEL, "apll_i2s3_m_sel", apll_i2s3_m_parents, 0x320, 19, 1),
+ MUX(CLK_TOP_APLL_I2S4_M_SEL, "apll_i2s4_m_sel", apll_i2s4_m_parents, 0x320, 20, 1),
+ MUX(CLK_TOP_APLL_I2S5_M_SEL, "apll_i2s5_m_sel", apll_i2s5_m_parents, 0x320, 21, 1),
+ MUX(CLK_TOP_APLL_I2S6_M_SEL, "apll_i2s6_m_sel", apll_i2s6_m_parents, 0x320, 22, 1),
+ MUX(CLK_TOP_APLL_I2S7_M_SEL, "apll_i2s7_m_sel", apll_i2s7_m_parents, 0x320, 23, 1),
+ MUX(CLK_TOP_APLL_I2S8_M_SEL, "apll_i2s8_m_sel", apll_i2s8_m_parents, 0x320, 24, 1),
+ MUX(CLK_TOP_APLL_I2S9_M_SEL, "apll_i2s9_m_sel", apll_i2s9_m_parents, 0x320, 25, 1),
+};
+
+static const struct mtk_composite top_adj_divs[] = {
+ DIV_GATE(CLK_TOP_APLL12_DIV0, "apll12_div0", "apll_i2s0_m_sel", 0x320, 0, 0x328, 8, 0),
+ DIV_GATE(CLK_TOP_APLL12_DIV1, "apll12_div1", "apll_i2s1_m_sel", 0x320, 1, 0x328, 8, 8),
+ DIV_GATE(CLK_TOP_APLL12_DIV2, "apll12_div2", "apll_i2s2_m_sel", 0x320, 2, 0x328, 8, 16),
+ DIV_GATE(CLK_TOP_APLL12_DIV3, "apll12_div3", "apll_i2s3_m_sel", 0x320, 3, 0x328, 8, 24),
+ DIV_GATE(CLK_TOP_APLL12_DIV4, "apll12_div4", "apll_i2s4_m_sel", 0x320, 4, 0x334, 8, 0),
+ DIV_GATE(CLK_TOP_APLL12_DIVB, "apll12_divb", "apll12_div4", 0x320, 5, 0x334, 8, 8),
+ DIV_GATE(CLK_TOP_APLL12_DIV5, "apll12_div5", "apll_i2s5_m_sel", 0x320, 6, 0x334, 8, 16),
+ DIV_GATE(CLK_TOP_APLL12_DIV6, "apll12_div6", "apll_i2s6_m_sel", 0x320, 7, 0x334, 8, 24),
+ DIV_GATE(CLK_TOP_APLL12_DIV7, "apll12_div7", "apll_i2s7_m_sel", 0x320, 8, 0x338, 8, 0),
+ DIV_GATE(CLK_TOP_APLL12_DIV8, "apll12_div8", "apll_i2s8_m_sel", 0x320, 9, 0x338, 8, 8),
+ DIV_GATE(CLK_TOP_APLL12_DIV9, "apll12_div9", "apll_i2s9_m_sel", 0x320, 10, 0x338, 8, 16),
+};
+
+static const struct mtk_gate_regs apmixed_cg_regs = {
+ .set_ofs = 0x14,
+ .clr_ofs = 0x14,
+ .sta_ofs = 0x14,
+};
+
+#define GATE_APMIXED(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &apmixed_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate apmixed_clks[] = {
+ GATE_APMIXED(CLK_APMIXED_MIPID26M, "mipid26m", "clk26m", 16),
+};
+
+static const struct mtk_gate_regs infra0_cg_regs = {
+ .set_ofs = 0x80,
+ .clr_ofs = 0x84,
+ .sta_ofs = 0x90,
+};
+
+static const struct mtk_gate_regs infra1_cg_regs = {
+ .set_ofs = 0x88,
+ .clr_ofs = 0x8c,
+ .sta_ofs = 0x94,
+};
+
+static const struct mtk_gate_regs infra2_cg_regs = {
+ .set_ofs = 0xa4,
+ .clr_ofs = 0xa8,
+ .sta_ofs = 0xac,
+};
+
+static const struct mtk_gate_regs infra3_cg_regs = {
+ .set_ofs = 0xc0,
+ .clr_ofs = 0xc4,
+ .sta_ofs = 0xc8,
+};
+
+static const struct mtk_gate_regs infra4_cg_regs = {
+ .set_ofs = 0xd0,
+ .clr_ofs = 0xd4,
+ .sta_ofs = 0xd8,
+};
+
+static const struct mtk_gate_regs infra5_cg_regs = {
+ .set_ofs = 0xe0,
+ .clr_ofs = 0xe4,
+ .sta_ofs = 0xe8,
+};
+
+#define GATE_INFRA0(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &infra0_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, _flag) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &infra1_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, _flag)
+
+#define GATE_INFRA1(_id, _name, _parent, _shift) \
+ GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, 0)
+
+#define GATE_INFRA2(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flag) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &infra3_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, _flag)
+
+#define GATE_INFRA3(_id, _name, _parent, _shift) \
+ GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, 0)
+
+#define GATE_INFRA4(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &infra4_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_INFRA5_FLAGS(_id, _name, _parent, _shift, _flag) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &infra5_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, _flag)
+
+#define GATE_INFRA5(_id, _name, _parent, _shift) \
+ GATE_INFRA5_FLAGS(_id, _name, _parent, _shift, 0)
+
+/*
+ * CRITICAL CLOCK:
+ * infra_133m and infra_66m are main peripheral bus clocks of SOC.
+ * infra_device_apc and infra_device_apc_sync are for device access permission control module.
+ */
+static const struct mtk_gate infra_clks[] = {
+ /* INFRA0 */
+ GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "pwrap_ulposc_sel", 0),
+ GATE_INFRA0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", "pwrap_ulposc_sel", 1),
+ GATE_INFRA0(CLK_INFRA_PMIC_MD, "infra_pmic_md", "pwrap_ulposc_sel", 2),
+ GATE_INFRA0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", "pwrap_ulposc_sel", 3),
+ GATE_INFRA0(CLK_INFRA_SCPSYS, "infra_scpsys", "scp_sel", 4),
+ GATE_INFRA0(CLK_INFRA_SEJ, "infra_sej", "axi_sel", 5),
+ GATE_INFRA0(CLK_INFRA_APXGPT, "infra_apxgpt", "axi_sel", 6),
+ GATE_INFRA0(CLK_INFRA_GCE, "infra_gce", "axi_sel", 8),
+ GATE_INFRA0(CLK_INFRA_GCE2, "infra_gce2", "axi_sel", 9),
+ GATE_INFRA0(CLK_INFRA_THERM, "infra_therm", "axi_sel", 10),
+ GATE_INFRA0(CLK_INFRA_I2C0, "infra_i2c0", "i2c_sel", 11),
+ GATE_INFRA0(CLK_INFRA_AP_DMA_PSEUDO, "infra_ap_dma_pseudo", "axi_sel", 12),
+ GATE_INFRA0(CLK_INFRA_I2C2, "infra_i2c2", "i2c_sel", 13),
+ GATE_INFRA0(CLK_INFRA_I2C3, "infra_i2c3", "i2c_sel", 14),
+ GATE_INFRA0(CLK_INFRA_PWM_H, "infra_pwm_h", "axi_sel", 15),
+ GATE_INFRA0(CLK_INFRA_PWM1, "infra_pwm1", "pwm_sel", 16),
+ GATE_INFRA0(CLK_INFRA_PWM2, "infra_pwm2", "pwm_sel", 17),
+ GATE_INFRA0(CLK_INFRA_PWM3, "infra_pwm3", "pwm_sel", 18),
+ GATE_INFRA0(CLK_INFRA_PWM4, "infra_pwm4", "pwm_sel", 19),
+ GATE_INFRA0(CLK_INFRA_PWM, "infra_pwm", "pwm_sel", 21),
+ GATE_INFRA0(CLK_INFRA_UART0, "infra_uart0", "uart_sel", 22),
+ GATE_INFRA0(CLK_INFRA_UART1, "infra_uart1", "uart_sel", 23),
+ GATE_INFRA0(CLK_INFRA_UART2, "infra_uart2", "uart_sel", 24),
+ GATE_INFRA0(CLK_INFRA_UART3, "infra_uart3", "uart_sel", 25),
+ GATE_INFRA0(CLK_INFRA_GCE_26M, "infra_gce_26m", "axi_sel", 27),
+ GATE_INFRA0(CLK_INFRA_CQ_DMA_FPC, "infra_cq_dma_fpc", "axi_sel", 28),
+ GATE_INFRA0(CLK_INFRA_BTIF, "infra_btif", "axi_sel", 31),
+ /* INFRA1 */
+ GATE_INFRA1(CLK_INFRA_SPI0, "infra_spi0", "spi_sel", 1),
+ GATE_INFRA1(CLK_INFRA_MSDC0, "infra_msdc0", "msdc50_0_h_sel", 2),
+ GATE_INFRA1(CLK_INFRA_MSDC1, "infra_msdc1", "msdc50_0_h_sel", 4),
+ GATE_INFRA1(CLK_INFRA_MSDC2, "infra_msdc2", "msdc50_0_h_sel", 5),
+ GATE_INFRA1(CLK_INFRA_MSDC0_SRC, "infra_msdc0_src", "msdc50_0_sel", 6),
+ GATE_INFRA1(CLK_INFRA_GCPU, "infra_gcpu", "axi_sel", 8),
+ GATE_INFRA1(CLK_INFRA_TRNG, "infra_trng", "axi_sel", 9),
+ GATE_INFRA1(CLK_INFRA_AUXADC, "infra_auxadc", "clk26m", 10),
+ GATE_INFRA1(CLK_INFRA_CPUM, "infra_cpum", "axi_sel", 11),
+ GATE_INFRA1(CLK_INFRA_CCIF1_AP, "infra_ccif1_ap", "axi_sel", 12),
+ GATE_INFRA1(CLK_INFRA_CCIF1_MD, "infra_ccif1_md", "axi_sel", 13),
+ GATE_INFRA1(CLK_INFRA_AUXADC_MD, "infra_auxadc_md", "clk26m", 14),
+ GATE_INFRA1(CLK_INFRA_PCIE_TL_26M, "infra_pcie_tl_26m", "axi_sel", 15),
+ GATE_INFRA1(CLK_INFRA_MSDC1_SRC, "infra_msdc1_src", "msdc30_1_sel", 16),
+ GATE_INFRA1(CLK_INFRA_MSDC2_SRC, "infra_msdc2_src", "msdc30_2_sel", 17),
+ GATE_INFRA1(CLK_INFRA_PCIE_TL_96M, "infra_pcie_tl_96m", "tl_sel", 18),
+ GATE_INFRA1(CLK_INFRA_PCIE_PL_P_250M, "infra_pcie_pl_p_250m", "axi_sel", 19),
+ GATE_INFRA1_FLAGS(CLK_INFRA_DEVICE_APC, "infra_device_apc", "axi_sel", 20, CLK_IS_CRITICAL),
+ GATE_INFRA1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", "axi_sel", 23),
+ GATE_INFRA1(CLK_INFRA_DEBUGSYS, "infra_debugsys", "axi_sel", 24),
+ GATE_INFRA1(CLK_INFRA_AUDIO, "infra_audio", "axi_sel", 25),
+ GATE_INFRA1(CLK_INFRA_CCIF_MD, "infra_ccif_md", "axi_sel", 26),
+ GATE_INFRA1(CLK_INFRA_DXCC_SEC_CORE, "infra_dxcc_sec_core", "dxcc_sel", 27),
+ GATE_INFRA1(CLK_INFRA_DXCC_AO, "infra_dxcc_ao", "dxcc_sel", 28),
+ GATE_INFRA1(CLK_INFRA_DBG_TRACE, "infra_dbg_trace", "axi_sel", 29),
+ GATE_INFRA1(CLK_INFRA_DEVMPU_B, "infra_devmpu_b", "axi_sel", 30),
+ GATE_INFRA1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", "clk26m", 31),
+ /* INFRA2 */
+ GATE_INFRA2(CLK_INFRA_IRTX, "infra_irtx", "clk26m", 0),
+ GATE_INFRA2(CLK_INFRA_SSUSB, "infra_ssusb", "usb_top_sel", 1),
+ GATE_INFRA2(CLK_INFRA_DISP_PWM, "infra_disp_pwm", "axi_sel", 2),
+ GATE_INFRA2(CLK_INFRA_CLDMA_B, "infra_cldma_b", "axi_sel", 3),
+ GATE_INFRA2(CLK_INFRA_AUDIO_26M_B, "infra_audio_26m_b", "clk26m", 4),
+ GATE_INFRA2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_modem_temp_share", "clk26m", 5),
+ GATE_INFRA2(CLK_INFRA_SPI1, "infra_spi1", "spi_sel", 6),
+ GATE_INFRA2(CLK_INFRA_I2C4, "infra_i2c4", "i2c_sel", 7),
+ GATE_INFRA2(CLK_INFRA_SPI2, "infra_spi2", "spi_sel", 9),
+ GATE_INFRA2(CLK_INFRA_SPI3, "infra_spi3", "spi_sel", 10),
+ GATE_INFRA2(CLK_INFRA_UNIPRO_SYS, "infra_unipro_sys", "ufs_sel", 11),
+ GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", "clk26m", 12),
+ GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_B, "infra_ufs_mp_sap_b", "clk26m", 13),
+ GATE_INFRA2(CLK_INFRA_MD32_B, "infra_md32_b", "axi_sel", 14),
+ GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist", "axi_sel", 16),
+ GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", "i2c_sel", 18),
+ GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", "i2c_sel", 19),
+ GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm", "i2c_sel", 20),
+ GATE_INFRA2(CLK_INFRA_I2C1_ARBITER, "infra_i2c1_arbiter", "i2c_sel", 21),
+ GATE_INFRA2(CLK_INFRA_I2C1_IMM, "infra_i2c1_imm", "i2c_sel", 22),
+ GATE_INFRA2(CLK_INFRA_I2C2_ARBITER, "infra_i2c2_arbiter", "i2c_sel", 23),
+ GATE_INFRA2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", "i2c_sel", 24),
+ GATE_INFRA2(CLK_INFRA_SPI4, "infra_spi4", "spi_sel", 25),
+ GATE_INFRA2(CLK_INFRA_SPI5, "infra_spi5", "spi_sel", 26),
+ GATE_INFRA2(CLK_INFRA_CQ_DMA, "infra_cq_dma", "axi_sel", 27),
+ GATE_INFRA2(CLK_INFRA_UFS, "infra_ufs", "ufs_sel", 28),
+ GATE_INFRA2(CLK_INFRA_AES_UFSFDE, "infra_aes_ufsfde", "aes_ufsfde_sel", 29),
+ GATE_INFRA2(CLK_INFRA_UFS_TICK, "infra_ufs_tick", "ufs_sel", 30),
+ GATE_INFRA2(CLK_INFRA_SSUSB_XHCI, "infra_ssusb_xhci", "ssusb_xhci_sel", 31),
+ /* INFRA3 */
+ GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", "msdc50_0_sel", 0),
+ GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", "msdc50_0_sel", 1),
+ GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self", "msdc50_0_sel", 2),
+ GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", "axi_sel", 5),
+ GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", "i2c_sel", 6),
+ GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", "msdc50_0_sel", 7),
+ GATE_INFRA3(CLK_INFRA_MD_MSDC0, "infra_md_msdc0", "msdc50_0_sel", 8),
+ GATE_INFRA3(CLK_INFRA_CCIF5_AP, "infra_ccif5_ap", "axi_sel", 9),
+ GATE_INFRA3(CLK_INFRA_CCIF5_MD, "infra_ccif5_md", "axi_sel", 10),
+ GATE_INFRA3(CLK_INFRA_PCIE_TOP_H_133M, "infra_pcie_top_h_133m", "axi_sel", 11),
+ GATE_INFRA3(CLK_INFRA_FLASHIF_TOP_H_133M, "infra_flashif_top_h_133m", "axi_sel", 14),
+ GATE_INFRA3(CLK_INFRA_PCIE_PERI_26M, "infra_pcie_peri_26m", "axi_sel", 15),
+ GATE_INFRA3(CLK_INFRA_CCIF2_AP, "infra_ccif2_ap", "axi_sel", 16),
+ GATE_INFRA3(CLK_INFRA_CCIF2_MD, "infra_ccif2_md", "axi_sel", 17),
+ GATE_INFRA3(CLK_INFRA_CCIF3_AP, "infra_ccif3_ap", "axi_sel", 18),
+ GATE_INFRA3(CLK_INFRA_CCIF3_MD, "infra_ccif3_md", "axi_sel", 19),
+ GATE_INFRA3(CLK_INFRA_SEJ_F13M, "infra_sej_f13m", "clk26m", 20),
+ GATE_INFRA3(CLK_INFRA_AES, "infra_aes", "axi_sel", 21),
+ GATE_INFRA3(CLK_INFRA_I2C7, "infra_i2c7", "i2c_sel", 22),
+ GATE_INFRA3(CLK_INFRA_I2C8, "infra_i2c8", "i2c_sel", 23),
+ GATE_INFRA3(CLK_INFRA_FBIST2FPC, "infra_fbist2fpc", "msdc50_0_sel", 24),
+ GATE_INFRA3_FLAGS(CLK_INFRA_DEVICE_APC_SYNC, "infra_device_apc_sync", "axi_sel", 25,
+ CLK_IS_CRITICAL),
+ GATE_INFRA3(CLK_INFRA_DPMAIF_MAIN, "infra_dpmaif_main", "dpmaif_main_sel", 26),
+ GATE_INFRA3(CLK_INFRA_PCIE_TL_32K, "infra_pcie_tl_32k", "axi_sel", 27),
+ GATE_INFRA3(CLK_INFRA_CCIF4_AP, "infra_ccif4_ap", "axi_sel", 28),
+ GATE_INFRA3(CLK_INFRA_CCIF4_MD, "infra_ccif4_md", "axi_sel", 29),
+ GATE_INFRA3(CLK_INFRA_SPI6, "infra_spi6", "spi_sel", 30),
+ GATE_INFRA3(CLK_INFRA_SPI7, "infra_spi7", "spi_sel", 31),
+ /* INFRA4 */
+ GATE_INFRA4(CLK_INFRA_AP_DMA, "infra_ap_dma", "infra_ap_dma_pseudo", 31),
+ /* INFRA5 */
+ GATE_INFRA5_FLAGS(CLK_INFRA_133M, "infra_133m", "axi_sel", 0, CLK_IS_CRITICAL),
+ GATE_INFRA5_FLAGS(CLK_INFRA_66M, "infra_66m", "axi_sel", 1, CLK_IS_CRITICAL),
+ GATE_INFRA5(CLK_INFRA_66M_PERI_BUS, "infra_66m_peri_bus", "axi_sel", 2),
+ GATE_INFRA5(CLK_INFRA_FREE_DCM_133M, "infra_free_dcm_133m", "axi_sel", 3),
+ GATE_INFRA5(CLK_INFRA_FREE_DCM_66M, "infra_free_dcm_66m", "axi_sel", 4),
+ GATE_INFRA5(CLK_INFRA_PERI_BUS_DCM_133M, "infra_peri_bus_dcm_133m", "axi_sel", 5),
+ GATE_INFRA5(CLK_INFRA_PERI_BUS_DCM_66M, "infra_peri_bus_dcm_66m", "axi_sel", 6),
+ GATE_INFRA5(CLK_INFRA_FLASHIF_PERI_26M, "infra_flashif_peri_26m", "axi_sel", 30),
+ GATE_INFRA5(CLK_INFRA_FLASHIF_SFLASH, "infra_flashif_fsflash", "axi_sel", 31),
+};
+
+static const struct mtk_gate_regs peri_cg_regs = {
+ .set_ofs = 0x20c,
+ .clr_ofs = 0x20c,
+ .sta_ofs = 0x20c,
+};
+
+#define GATE_PERI(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &peri_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate peri_clks[] = {
+ GATE_PERI(CLK_PERI_PERIAXI, "peri_periaxi", "axi_sel", 31),
+};
+
+static const struct mtk_gate_regs top_cg_regs = {
+ .set_ofs = 0x150,
+ .clr_ofs = 0x150,
+ .sta_ofs = 0x150,
+};
+
+#define GATE_TOP(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &top_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate top_clks[] = {
+ GATE_TOP(CLK_TOP_SSUSB_TOP_REF, "ssusb_top_ref", "clk26m", 24),
+ GATE_TOP(CLK_TOP_SSUSB_PHY_REF, "ssusb_phy_ref", "clk26m", 25),
+};
+
+#define MT8192_PLL_FMAX (3800UL * MHZ)
+#define MT8192_PLL_FMIN (1500UL * MHZ)
+#define MT8192_INTEGER_BITS 8
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
+ _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \
+ _tuner_reg, _tuner_en_reg, _tuner_en_bit, \
+ _pcw_reg, _pcw_shift, _pcw_chg_reg, \
+ _en_reg, _pll_en_bit) { \
+ .id = _id, \
+ .name = _name, \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .rst_bar_mask = _rst_bar_mask, \
+ .fmax = MT8192_PLL_FMAX, \
+ .fmin = MT8192_PLL_FMIN, \
+ .pcwbits = _pcwbits, \
+ .pcwibits = MT8192_INTEGER_BITS, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .tuner_en_reg = _tuner_en_reg, \
+ .tuner_en_bit = _tuner_en_bit, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_shift = _pcw_shift, \
+ .pcw_chg_reg = _pcw_chg_reg, \
+ .en_reg = _en_reg, \
+ .pll_en_bit = _pll_en_bit, \
+ }
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
+ _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \
+ _tuner_reg, _tuner_en_reg, _tuner_en_bit, \
+ _pcw_reg, _pcw_shift) \
+ PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
+ _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \
+ _tuner_reg, _tuner_en_reg, _tuner_en_bit, \
+ _pcw_reg, _pcw_shift, 0, 0, 0)
+
+static const struct mtk_pll_data plls[] = {
+ PLL_B(CLK_APMIXED_MAINPLL, "mainpll", 0x0340, 0x034c, 0xff000000,
+ HAVE_RST_BAR, BIT(23), 22, 0x0344, 24, 0, 0, 0, 0x0344, 0),
+ PLL_B(CLK_APMIXED_UNIVPLL, "univpll", 0x0308, 0x0314, 0xff000000,
+ HAVE_RST_BAR, BIT(23), 22, 0x030c, 24, 0, 0, 0, 0x030c, 0),
+ PLL(CLK_APMIXED_USBPLL, "usbpll", 0x03c4, 0x03cc, 0x00000000,
+ 0, 0, 22, 0x03c4, 24, 0, 0, 0, 0x03c4, 0, 0x03c4, 0x03cc, 2),
+ PLL_B(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0350, 0x035c, 0x00000000,
+ 0, 0, 22, 0x0354, 24, 0, 0, 0, 0x0354, 0),
+ PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0360, 0x036c, 0xff000000,
+ HAVE_RST_BAR, BIT(23), 22, 0x0364, 24, 0, 0, 0, 0x0364, 0),
+ PLL_B(CLK_APMIXED_ADSPPLL, "adsppll", 0x0370, 0x037c, 0xff000000,
+ HAVE_RST_BAR, BIT(23), 22, 0x0374, 24, 0, 0, 0, 0x0374, 0),
+ PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0268, 0x0274, 0x00000000,
+ 0, 0, 22, 0x026c, 24, 0, 0, 0, 0x026c, 0),
+ PLL_B(CLK_APMIXED_TVDPLL, "tvdpll", 0x0380, 0x038c, 0x00000000,
+ 0, 0, 22, 0x0384, 24, 0, 0, 0, 0x0384, 0),
+ PLL_B(CLK_APMIXED_APLL1, "apll1", 0x0318, 0x0328, 0x00000000,
+ 0, 0, 32, 0x031c, 24, 0x0040, 0x000c, 0, 0x0320, 0),
+ PLL_B(CLK_APMIXED_APLL2, "apll2", 0x032c, 0x033c, 0x00000000,
+ 0, 0, 32, 0x0330, 24, 0, 0, 0, 0x0334, 0),
+};
+
+static struct clk_onecell_data *top_clk_data;
+
+static void clk_mt8192_top_init_early(struct device_node *node)
+{
+ int i;
+
+ top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+ if (!top_clk_data)
+ return;
+
+ for (i = 0; i < CLK_TOP_NR_CLK; i++)
+ top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+
+ mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), top_clk_data);
+
+ of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data);
+}
+
+CLK_OF_DECLARE_DRIVER(mt8192_topckgen, "mediatek,mt8192-topckgen",
+ clk_mt8192_top_init_early);
+
+static int clk_mt8192_top_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ int r;
+ void __iomem *base;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data);
+ mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), top_clk_data);
+ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data);
+ mtk_clk_register_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), node, &mt8192_clk_lock,
+ top_clk_data);
+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt8192_clk_lock,
+ top_clk_data);
+ mtk_clk_register_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, &mt8192_clk_lock,
+ top_clk_data);
+ r = mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), top_clk_data);
+ if (r)
+ return r;
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data);
+}
+
+static int clk_mt8192_infra_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ struct device_node *node = pdev->dev.of_node;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
+
+ r = mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data);
+ if (r)
+ return r;
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static int clk_mt8192_peri_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ struct device_node *node = pdev->dev.of_node;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
+
+ r = mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), clk_data);
+ if (r)
+ return r;
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static int clk_mt8192_apmixed_probe(struct platform_device *pdev)
+{
+ struct clk_onecell_data *clk_data;
+ struct device_node *node = pdev->dev.of_node;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+ if (!clk_data)
+ return -ENOMEM;
+
+ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+ r = mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data);
+ if (r)
+ return r;
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8192[] = {
+ {
+ .compatible = "mediatek,mt8192-apmixedsys",
+ .data = clk_mt8192_apmixed_probe,
+ }, {
+ .compatible = "mediatek,mt8192-topckgen",
+ .data = clk_mt8192_top_probe,
+ }, {
+ .compatible = "mediatek,mt8192-infracfg",
+ .data = clk_mt8192_infra_probe,
+ }, {
+ .compatible = "mediatek,mt8192-pericfg",
+ .data = clk_mt8192_peri_probe,
+ }, {
+ /* sentinel */
+ }
+};
+
+static int clk_mt8192_probe(struct platform_device *pdev)
+{
+ int (*clk_probe)(struct platform_device *pdev);
+ int r;
+
+ clk_probe = of_device_get_match_data(&pdev->dev);
+ if (!clk_probe)
+ return -EINVAL;
+
+ r = clk_probe(pdev);
+ if (r)
+ dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", pdev->name, r);
+
+ return r;
+}
+
+static struct platform_driver clk_mt8192_drv = {
+ .probe = clk_mt8192_probe,
+ .driver = {
+ .name = "clk-mt8192",
+ .of_match_table = of_match_clk_mt8192,
+ },
+};
+
+static int __init clk_mt8192_init(void)
+{
+ return platform_driver_register(&clk_mt8192_drv);
+}
+
+arch_initcall(clk_mt8192_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index cec1c8a27211..4b6096c44d74 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -13,6 +13,7 @@
#include <linux/clkdev.h>
#include <linux/mfd/syscon.h>
#include <linux/device.h>
+#include <linux/of_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
@@ -106,7 +107,7 @@ int mtk_clk_register_gates_with_dev(struct device_node *node,
if (!clk_data)
return -ENOMEM;
- regmap = syscon_node_to_regmap(node);
+ regmap = device_node_to_regmap(node);
if (IS_ERR(regmap)) {
pr_err("Cannot find regmap for %pOF: %ld\n", node,
PTR_ERR(regmap));
@@ -286,3 +287,25 @@ void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
clk_data->clks[mcd->id] = clk;
}
}
+
+int mtk_clk_simple_probe(struct platform_device *pdev)
+{
+ const struct mtk_clk_desc *mcd;
+ struct clk_onecell_data *clk_data;
+ struct device_node *node = pdev->dev.of_node;
+ int r;
+
+ mcd = of_device_get_match_data(&pdev->dev);
+ if (!mcd)
+ return -EINVAL;
+
+ clk_data = mtk_alloc_clk_data(mcd->num_clks);
+ if (!clk_data)
+ return -ENOMEM;
+
+ r = mtk_clk_register_gates(node, mcd->clks, mcd->num_clks, clk_data);
+ if (r)
+ return r;
+
+ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index c3d6756b0c7e..7de41c3b3206 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -10,6 +10,7 @@
#include <linux/regmap.h>
#include <linux/bitops.h>
#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
struct clk;
struct clk_onecell_data;
@@ -213,13 +214,13 @@ struct mtk_pll_div_table {
struct mtk_pll_data {
int id;
const char *name;
- uint32_t reg;
- uint32_t pwr_reg;
- uint32_t en_mask;
- uint32_t pd_reg;
- uint32_t tuner_reg;
- uint32_t tuner_en_reg;
- uint8_t tuner_en_bit;
+ u32 reg;
+ u32 pwr_reg;
+ u32 en_mask;
+ u32 pd_reg;
+ u32 tuner_reg;
+ u32 tuner_en_reg;
+ u8 tuner_en_bit;
int pd_shift;
unsigned int flags;
const struct clk_ops *ops;
@@ -228,11 +229,13 @@ struct mtk_pll_data {
unsigned long fmax;
int pcwbits;
int pcwibits;
- uint32_t pcw_reg;
+ u32 pcw_reg;
int pcw_shift;
- uint32_t pcw_chg_reg;
+ u32 pcw_chg_reg;
const struct mtk_pll_div_table *div_table;
const char *parent_name;
+ u32 en_reg;
+ u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */
};
void mtk_clk_register_plls(struct device_node *node,
@@ -248,4 +251,11 @@ void mtk_register_reset_controller(struct device_node *np,
void mtk_register_reset_controller_set_clr(struct device_node *np,
unsigned int num_regs, int regofs);
+struct mtk_clk_desc {
+ const struct mtk_gate *clks;
+ size_t num_clks;
+};
+
+int mtk_clk_simple_probe(struct platform_device *pdev);
+
#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
index b0c61709bacc..855b0a1f7eb9 100644
--- a/drivers/clk/mediatek/clk-mux.c
+++ b/drivers/clk/mediatek/clk-mux.c
@@ -116,7 +116,12 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
return 0;
}
-static const struct clk_ops mtk_mux_ops = {
+const struct clk_ops mtk_mux_clr_set_upd_ops = {
+ .get_parent = mtk_clk_mux_get_parent,
+ .set_parent = mtk_clk_mux_set_parent_setclr_lock,
+};
+
+const struct clk_ops mtk_mux_gate_clr_set_upd_ops = {
.enable = mtk_clk_mux_enable_setclr,
.disable = mtk_clk_mux_disable_setclr,
.is_enabled = mtk_clk_mux_is_enabled,
@@ -140,7 +145,7 @@ static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
init.flags = mux->flags | CLK_SET_RATE_PARENT;
init.parent_names = mux->parent_names;
init.num_parents = mux->num_parents;
- init.ops = &mtk_mux_ops;
+ init.ops = mux->ops;
clk_mux->regmap = regmap;
clk_mux->data = mux;
@@ -165,7 +170,7 @@ int mtk_clk_register_muxes(const struct mtk_mux *muxes,
struct clk *clk;
int i;
- regmap = syscon_node_to_regmap(node);
+ regmap = device_node_to_regmap(node);
if (IS_ERR(regmap)) {
pr_err("Cannot find regmap for %pOF: %ld\n", node,
PTR_ERR(regmap));
diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h
index f1946161ade1..27841d649118 100644
--- a/drivers/clk/mediatek/clk-mux.h
+++ b/drivers/clk/mediatek/clk-mux.h
@@ -33,12 +33,13 @@ struct mtk_mux {
u8 gate_shift;
s8 upd_shift;
+ const struct clk_ops *ops;
signed char num_parents;
};
#define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
_mux_set_ofs, _mux_clr_ofs, _shift, _width, \
- _gate, _upd_ofs, _upd, _flags) { \
+ _gate, _upd_ofs, _upd, _flags, _ops) { \
.id = _id, \
.name = _name, \
.mux_ofs = _mux_ofs, \
@@ -52,14 +53,19 @@ struct mtk_mux {
.parent_names = _parents, \
.num_parents = ARRAY_SIZE(_parents), \
.flags = _flags, \
+ .ops = &_ops, \
}
+extern const struct clk_ops mtk_mux_clr_set_upd_ops;
+extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
+
#define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
_mux_set_ofs, _mux_clr_ofs, _shift, _width, \
_gate, _upd_ofs, _upd, _flags) \
GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
_mux_set_ofs, _mux_clr_ofs, _shift, _width, \
- _gate, _upd_ofs, _upd, _flags) \
+ _gate, _upd_ofs, _upd, _flags, \
+ mtk_mux_gate_clr_set_upd_ops)
#define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \
_mux_set_ofs, _mux_clr_ofs, _shift, _width, \
@@ -69,6 +75,14 @@ struct mtk_mux {
_width, _gate, _upd_ofs, _upd, \
CLK_SET_RATE_PARENT)
+#define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \
+ _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
+ _upd_ofs, _upd) \
+ GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
+ _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
+ 0, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \
+ mtk_mux_clr_set_upd_ops)
+
int mtk_clk_register_muxes(const struct mtk_mux *muxes,
int num, struct device_node *node,
spinlock_t *lock,
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index f440f2cd0b69..7fb001a4e7d8 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -44,6 +44,7 @@ struct mtk_clk_pll {
void __iomem *tuner_en_addr;
void __iomem *pcw_addr;
void __iomem *pcw_chg_addr;
+ void __iomem *en_addr;
const struct mtk_pll_data *data;
};
@@ -56,7 +57,7 @@ static int mtk_pll_is_prepared(struct clk_hw *hw)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
- return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
+ return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0;
}
static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
@@ -238,6 +239,7 @@ static int mtk_pll_prepare(struct clk_hw *hw)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
u32 r;
+ u32 div_en_mask;
r = readl(pll->pwr_addr) | CON0_PWR_ON;
writel(r, pll->pwr_addr);
@@ -247,9 +249,14 @@ static int mtk_pll_prepare(struct clk_hw *hw)
writel(r, pll->pwr_addr);
udelay(1);
- r = readl(pll->base_addr + REG_CON0);
- r |= pll->data->en_mask;
- writel(r, pll->base_addr + REG_CON0);
+ r = readl(pll->en_addr) | BIT(pll->data->pll_en_bit);
+ writel(r, pll->en_addr);
+
+ div_en_mask = pll->data->en_mask & ~CON0_BASE_EN;
+ if (div_en_mask) {
+ r = readl(pll->base_addr + REG_CON0) | div_en_mask;
+ writel(r, pll->base_addr + REG_CON0);
+ }
__mtk_pll_tuner_enable(pll);
@@ -268,6 +275,7 @@ static void mtk_pll_unprepare(struct clk_hw *hw)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
u32 r;
+ u32 div_en_mask;
if (pll->data->flags & HAVE_RST_BAR) {
r = readl(pll->base_addr + REG_CON0);
@@ -277,9 +285,14 @@ static void mtk_pll_unprepare(struct clk_hw *hw)
__mtk_pll_tuner_disable(pll);
- r = readl(pll->base_addr + REG_CON0);
- r &= ~CON0_BASE_EN;
- writel(r, pll->base_addr + REG_CON0);
+ div_en_mask = pll->data->en_mask & ~CON0_BASE_EN;
+ if (div_en_mask) {
+ r = readl(pll->base_addr + REG_CON0) & ~div_en_mask;
+ writel(r, pll->base_addr + REG_CON0);
+ }
+
+ r = readl(pll->en_addr) & ~BIT(pll->data->pll_en_bit);
+ writel(r, pll->en_addr);
r = readl(pll->pwr_addr) | CON0_ISO_EN;
writel(r, pll->pwr_addr);
@@ -321,6 +334,10 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
pll->tuner_addr = base + data->tuner_reg;
if (data->tuner_en_reg)
pll->tuner_en_addr = base + data->tuner_en_reg;
+ if (data->en_reg)
+ pll->en_addr = base + data->en_reg;
+ else
+ pll->en_addr = pll->base_addr + REG_CON0;
pll->hw.init = &init;
pll->data = data;
diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c
index cb939c071b0c..e562dc3c10a4 100644
--- a/drivers/clk/mediatek/reset.c
+++ b/drivers/clk/mediatek/reset.c
@@ -98,7 +98,7 @@ static void mtk_register_reset_controller_common(struct device_node *np,
int ret;
struct regmap *regmap;
- regmap = syscon_node_to_regmap(np);
+ regmap = device_node_to_regmap(np);
if (IS_ERR(regmap)) {
pr_err("Cannot find regmap for %pOF: %ld\n", np,
PTR_ERR(regmap));
diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c
index 47680237d0be..8bc893df4736 100644
--- a/drivers/clk/mvebu/kirkwood.c
+++ b/drivers/clk/mvebu/kirkwood.c
@@ -265,6 +265,7 @@ static const char *powersave_parents[] = {
static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = {
{ "powersave", powersave_parents, ARRAY_SIZE(powersave_parents),
11, 1, 0 },
+ { }
};
static struct clk *clk_muxing_get_src(
diff --git a/drivers/clk/pistachio/Kconfig b/drivers/clk/pistachio/Kconfig
new file mode 100644
index 000000000000..d00f7b4a25fc
--- /dev/null
+++ b/drivers/clk/pistachio/Kconfig
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config COMMON_CLK_PISTACHIO
+ bool "Support for IMG Pistachio SoC clock controllers"
+ depends on MIPS || COMPILE_TEST
+ help
+ Support for the IMG Pistachio SoC clock controller.
+ Say Y if you want to include clock support.
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 62e00e15495c..0a5596797b93 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -240,6 +240,14 @@ config MSM_MMCC_8960
Say Y if you want to support multimedia devices such as display,
graphics, video encode/decode, camera, etc.
+config MSM_GCC_8953
+ tristate "MSM8953 Global Clock Controller"
+ select QCOM_GDSC
+ help
+ Support for the global clock controller on msm8953 devices.
+ Say Y if you want to use devices such as UART, SPI i2c, USB,
+ SD/eMMC, display, graphics, camera etc.
+
config MSM_GCC_8974
tristate "MSM8974 Global Clock Controller"
select QCOM_GDSC
@@ -257,6 +265,15 @@ config MSM_MMCC_8974
Say Y if you want to support multimedia devices such as display,
graphics, video encode/decode, camera, etc.
+config MSM_MMCC_8994
+ tristate "MSM8994 Multimedia Clock Controller"
+ select MSM_GCC_8994
+ select QCOM_GDSC
+ help
+ Support for the multimedia clock controller on msm8994 devices.
+ Say Y if you want to support multimedia devices such as display,
+ graphics, video encode/decode, camera, etc.
+
config MSM_GCC_8994
tristate "MSM8994 Global Clock Controller"
help
@@ -332,6 +349,15 @@ config SC_DISPCC_7180
Say Y if you want to support display devices and functionality such as
splash screen.
+config SC_DISPCC_7280
+ tristate "SC7280 Display Clock Controller"
+ select SC_GCC_7280
+ help
+ Support for the display clock controller on Qualcomm Technologies, Inc.
+ SC7280 devices.
+ Say Y if you want to support display devices and functionality such as
+ splash screen.
+
config SC_GCC_7180
tristate "SC7180 Global Clock Controller"
select QCOM_GDSC
@@ -376,6 +402,14 @@ config SC_GPUCC_7180
Say Y if you want to support graphics controller devices and
functionality such as 3D graphics.
+config SC_GPUCC_7280
+ tristate "SC7280 Graphics Clock Controller"
+ select SC_GCC_7280
+ help
+ Support for the graphics clock controller on SC7280 devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
config SC_MSS_7180
tristate "SC7180 Modem Clock Controller"
select SC_GCC_7180
@@ -393,6 +427,14 @@ config SC_VIDEOCC_7180
Say Y if you want to support video devices and functionality such as
video encode and decode.
+config SC_VIDEOCC_7280
+ tristate "SC7280 Video Clock Controller"
+ select SC_GCC_7280
+ help
+ Support for the video clock controller on SC7280 devices.
+ Say Y if you want to support video devices and functionality such as
+ video encode and decode.
+
config SDM_CAMCC_845
tristate "SDM845 Camera Clock Controller"
select SDM_GCC_845
@@ -506,6 +548,13 @@ config SM_DISPCC_8250
Say Y if you want to support display devices and functionality such as
splash screen.
+config SM_GCC_6115
+ tristate "SM6115 and SM4250 Global Clock Controller"
+ help
+ Support for the global clock controller on SM6115 and SM4250 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ i2C, USB, UFS, SDDC, PCIe, etc.
+
config SM_GCC_6125
tristate "SM6125 Global Clock Controller"
help
@@ -513,6 +562,13 @@ config SM_GCC_6125
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
+config SM_GCC_6350
+ tristate "SM6350 Global Clock Controller"
+ help
+ Support for the global clock controller on SM6350 devices.
+ Say Y if you want to use peripheral devices such as UART,
+ SPI, I2C, USB, SD/UFS, PCIe etc.
+
config SM_GCC_8150
tristate "SM8150 Global Clock Controller"
help
@@ -554,7 +610,7 @@ config SM_GPUCC_8250
config SM_VIDEOCC_8150
tristate "SM8150 Video Clock Controller"
- select SDM_GCC_8150
+ select SM_GCC_8150
select QCOM_GDSC
help
Support for the video clock controller on SM8150 devices.
@@ -563,7 +619,7 @@ config SM_VIDEOCC_8150
config SM_VIDEOCC_8250
tristate "SM8250 Video Clock Controller"
- select SDM_GCC_8250
+ select SM_GCC_8250
select QCOM_GDSC
help
Support for the video clock controller on SM8250 devices.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index c2a1cafb31bc..9825ef843f4a 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o
obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
obj-$(CONFIG_MSM_GCC_8939) += gcc-msm8939.o
+obj-$(CONFIG_MSM_GCC_8953) += gcc-msm8953.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
@@ -42,6 +43,7 @@ obj-$(CONFIG_MSM_GCC_8998) += gcc-msm8998.o
obj-$(CONFIG_MSM_GPUCC_8998) += gpucc-msm8998.o
obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
+obj-$(CONFIG_MSM_MMCC_8994) += mmcc-msm8994.o
obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
obj-$(CONFIG_MSM_MMCC_8998) += mmcc-msm8998.o
obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
@@ -57,13 +59,16 @@ obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o
obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o
obj-$(CONFIG_SC_CAMCC_7180) += camcc-sc7180.o
obj-$(CONFIG_SC_DISPCC_7180) += dispcc-sc7180.o
+obj-$(CONFIG_SC_DISPCC_7280) += dispcc-sc7280.o
obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o
obj-$(CONFIG_SC_GCC_7280) += gcc-sc7280.o
obj-$(CONFIG_SC_GCC_8180X) += gcc-sc8180x.o
obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o
+obj-$(CONFIG_SC_GPUCC_7280) += gpucc-sc7280.o
obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o
obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o
obj-$(CONFIG_SC_VIDEOCC_7180) += videocc-sc7180.o
+obj-$(CONFIG_SC_VIDEOCC_7280) += videocc-sc7280.o
obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o
obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
@@ -76,7 +81,9 @@ obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o
obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o
obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
+obj-$(CONFIG_SM_GCC_6115) += gcc-sm6115.o
obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o
+obj-$(CONFIG_SM_GCC_6350) += gcc-sm6350.o
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
obj-$(CONFIG_SM_GCC_8350) += gcc-sm8350.o
diff --git a/drivers/clk/qcom/a53-pll.c b/drivers/clk/qcom/a53-pll.c
index af6ac17c7dae..9e6decb9c26f 100644
--- a/drivers/clk/qcom/a53-pll.c
+++ b/drivers/clk/qcom/a53-pll.c
@@ -6,9 +6,11 @@
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <linux/module.h>
@@ -34,9 +36,59 @@ static const struct regmap_config a53pll_regmap_config = {
.fast_io = true,
};
+static struct pll_freq_tbl *qcom_a53pll_get_freq_tbl(struct device *dev)
+{
+ struct pll_freq_tbl *freq_tbl;
+ unsigned long xo_freq;
+ unsigned long freq;
+ struct clk *xo_clk;
+ int count;
+ int ret;
+ int i;
+
+ xo_clk = devm_clk_get(dev, "xo");
+ if (IS_ERR(xo_clk))
+ return NULL;
+
+ xo_freq = clk_get_rate(xo_clk);
+
+ ret = devm_pm_opp_of_add_table(dev);
+ if (ret)
+ return NULL;
+
+ count = dev_pm_opp_get_opp_count(dev);
+ if (count <= 0)
+ return NULL;
+
+ freq_tbl = devm_kcalloc(dev, count + 1, sizeof(*freq_tbl), GFP_KERNEL);
+ if (!freq_tbl)
+ return NULL;
+
+ for (i = 0, freq = 0; i < count; i++, freq++) {
+ struct dev_pm_opp *opp;
+
+ opp = dev_pm_opp_find_freq_ceil(dev, &freq);
+ if (IS_ERR(opp))
+ return NULL;
+
+ /* Skip the freq that is not divisible */
+ if (freq % xo_freq)
+ continue;
+
+ freq_tbl[i].freq = freq;
+ freq_tbl[i].l = freq / xo_freq;
+ freq_tbl[i].n = 1;
+
+ dev_pm_opp_put(opp);
+ }
+
+ return freq_tbl;
+}
+
static int qcom_a53pll_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
struct regmap *regmap;
struct resource *res;
struct clk_pll *pll;
@@ -64,13 +116,22 @@ static int qcom_a53pll_probe(struct platform_device *pdev)
pll->mode_reg = 0x00;
pll->status_reg = 0x1c;
pll->status_bit = 16;
- pll->freq_tbl = a53pll_freq;
- init.name = "a53pll";
+ pll->freq_tbl = qcom_a53pll_get_freq_tbl(dev);
+ if (!pll->freq_tbl) {
+ /* Fall on a53pll_freq if no freq_tbl is found from OPP */
+ pll->freq_tbl = a53pll_freq;
+ }
+
+ /* Use an unique name by appending @unit-address */
+ init.name = devm_kasprintf(dev, GFP_KERNEL, "a53pll%s",
+ strchrnul(np->full_name, '@'));
+ if (!init.name)
+ return -ENOMEM;
+
init.parent_names = (const char *[]){ "xo" };
init.num_parents = 1;
init.ops = &clk_pll_sr2_ops;
- init.flags = CLK_IS_CRITICAL;
pll->clkr.hw.init = &init;
ret = devm_clk_register_regmap(dev, &pll->clkr);
@@ -91,6 +152,7 @@ static int qcom_a53pll_probe(struct platform_device *pdev)
static const struct of_device_id qcom_a53pll_match_table[] = {
{ .compatible = "qcom,msm8916-a53pll" },
+ { .compatible = "qcom,msm8939-a53pll" },
{ }
};
MODULE_DEVICE_TABLE(of, qcom_a53pll_match_table);
diff --git a/drivers/clk/qcom/apcs-msm8916.c b/drivers/clk/qcom/apcs-msm8916.c
index cf69a97d0439..89e0730810ac 100644
--- a/drivers/clk/qcom/apcs-msm8916.c
+++ b/drivers/clk/qcom/apcs-msm8916.c
@@ -46,6 +46,7 @@ static int qcom_apcs_msm8916_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device *parent = dev->parent;
+ struct device_node *np = parent->of_node;
struct clk_regmap_mux_div *a53cc;
struct regmap *regmap;
struct clk_init_data init = { };
@@ -61,11 +62,16 @@ static int qcom_apcs_msm8916_clk_probe(struct platform_device *pdev)
if (!a53cc)
return -ENOMEM;
- init.name = "a53mux";
+ /* Use an unique name by appending parent's @unit-address */
+ init.name = devm_kasprintf(dev, GFP_KERNEL, "a53mux%s",
+ strchrnul(np->full_name, '@'));
+ if (!init.name)
+ return -ENOMEM;
+
init.parent_data = pdata;
init.num_parents = ARRAY_SIZE(pdata);
init.ops = &clk_regmap_mux_div_ops;
- init.flags = CLK_SET_RATE_PARENT;
+ init.flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT;
a53cc->clkr.hw.init = &init;
a53cc->clkr.regmap = regmap;
diff --git a/drivers/clk/qcom/camcc-sc7180.c b/drivers/clk/qcom/camcc-sc7180.c
index 9bcf2f8ed4de..ce73ee9037cb 100644
--- a/drivers/clk/qcom/camcc-sc7180.c
+++ b/drivers/clk/qcom/camcc-sc7180.c
@@ -1652,32 +1652,35 @@ static int cam_cc_sc7180_probe(struct platform_device *pdev)
struct regmap *regmap;
int ret;
- pm_runtime_enable(&pdev->dev);
- ret = pm_clk_create(&pdev->dev);
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_pm_clk_create(&pdev->dev);
if (ret < 0)
return ret;
ret = pm_clk_add(&pdev->dev, "xo");
if (ret < 0) {
dev_err(&pdev->dev, "Failed to acquire XO clock\n");
- goto disable_pm_runtime;
+ return ret;
}
ret = pm_clk_add(&pdev->dev, "iface");
if (ret < 0) {
dev_err(&pdev->dev, "Failed to acquire iface clock\n");
- goto disable_pm_runtime;
+ return ret;
}
ret = pm_runtime_get(&pdev->dev);
if (ret)
- goto destroy_pm_clk;
+ return ret;
regmap = qcom_cc_map(pdev, &cam_cc_sc7180_desc);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
pm_runtime_put(&pdev->dev);
- goto destroy_pm_clk;
+ return ret;
}
clk_fabia_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
@@ -1689,18 +1692,10 @@ static int cam_cc_sc7180_probe(struct platform_device *pdev)
pm_runtime_put(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register CAM CC clocks\n");
- goto destroy_pm_clk;
+ return ret;
}
return 0;
-
-destroy_pm_clk:
- pm_clk_destroy(&pdev->dev);
-
-disable_pm_runtime:
- pm_runtime_disable(&pdev->dev);
-
- return ret;
}
static const struct dev_pm_ops cam_cc_pm_ops = {
diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c
index 552d1cbfea4c..441d7a20e6f3 100644
--- a/drivers/clk/qcom/clk-rpmh.c
+++ b/drivers/clk/qcom/clk-rpmh.c
@@ -536,6 +536,26 @@ static const struct clk_rpmh_desc clk_rpmh_sc7280 = {
.num_clks = ARRAY_SIZE(sc7280_rpmh_clocks),
};
+DEFINE_CLK_RPMH_VRM(sm6350, ln_bb_clk2, ln_bb_clk2_ao, "lnbclkg2", 4);
+DEFINE_CLK_RPMH_VRM(sm6350, ln_bb_clk3, ln_bb_clk3_ao, "lnbclkg3", 4);
+DEFINE_CLK_RPMH_ARC(sm6350, qlink, qlink_ao, "qphy.lvl", 0x1, 4);
+
+static struct clk_hw *sm6350_rpmh_clocks[] = {
+ [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
+ [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
+ [RPMH_LN_BB_CLK2] = &sm6350_ln_bb_clk2.hw,
+ [RPMH_LN_BB_CLK2_A] = &sm6350_ln_bb_clk2_ao.hw,
+ [RPMH_LN_BB_CLK3] = &sm6350_ln_bb_clk3.hw,
+ [RPMH_LN_BB_CLK3_A] = &sm6350_ln_bb_clk3_ao.hw,
+ [RPMH_QLINK_CLK] = &sm6350_qlink.hw,
+ [RPMH_QLINK_CLK_A] = &sm6350_qlink_ao.hw,
+};
+
+static const struct clk_rpmh_desc clk_rpmh_sm6350 = {
+ .clks = sm6350_rpmh_clocks,
+ .num_clks = ARRAY_SIZE(sm6350_rpmh_clocks),
+};
+
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
void *data)
{
@@ -623,6 +643,7 @@ static const struct of_device_id clk_rpmh_match_table[] = {
{ .compatible = "qcom,sc8180x-rpmh-clk", .data = &clk_rpmh_sc8180x},
{ .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
{ .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55},
+ { .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350},
{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
{ .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
{ .compatible = "qcom,sm8350-rpmh-clk", .data = &clk_rpmh_sm8350},
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index b2c142f3a649..66d7807ee38e 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -913,10 +913,166 @@ static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
.num_clks = ARRAY_SIZE(sdm660_clks),
};
+static struct clk_smd_rpm *mdm9607_clks[] = {
+ [RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
+ [RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
+ [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
+ [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
+ [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
+ [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
+ [RPM_SMD_QPIC_CLK] = &qcs404_qpic_clk,
+ [RPM_SMD_QPIC_CLK_A] = &qcs404_qpic_a_clk,
+ [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk,
+ [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk,
+ [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1,
+ [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a,
+ [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
+ [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
+};
+
+static const struct rpm_smd_clk_desc rpm_clk_mdm9607 = {
+ .clks = mdm9607_clks,
+ .num_clks = ARRAY_SIZE(mdm9607_clks),
+};
+
+static struct clk_smd_rpm *msm8953_clks[] = {
+ [RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
+ [RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
+ [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk,
+ [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk,
+ [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk,
+ [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk,
+ [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
+ [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
+ [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk,
+ [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk,
+ [RPM_SMD_SYSMMNOC_CLK] = &msm8936_sysmmnoc_clk,
+ [RPM_SMD_SYSMMNOC_A_CLK] = &msm8936_sysmmnoc_a_clk,
+ [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk,
+ [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk,
+ [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1,
+ [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a,
+ [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2,
+ [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a,
+ [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,
+ [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,
+ [RPM_SMD_RF_CLK3] = &msm8992_ln_bb_clk,
+ [RPM_SMD_RF_CLK3_A] = &msm8992_ln_bb_a_clk,
+ [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2,
+ [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2,
+ [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin,
+ [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin,
+ [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin,
+ [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin,
+};
+
+static const struct rpm_smd_clk_desc rpm_clk_msm8953 = {
+ .clks = msm8953_clks,
+ .num_clks = ARRAY_SIZE(msm8953_clks),
+};
+
+/* SM6125 */
+DEFINE_CLK_SMD_RPM(sm6125, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
+DEFINE_CLK_SMD_RPM(sm6125, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
+DEFINE_CLK_SMD_RPM_BRANCH(sm6125, qdss_clk, qdss_a_clk,
+ QCOM_SMD_RPM_MISC_CLK, 1, 19200000);
+DEFINE_CLK_SMD_RPM(sm6125, qup_clk, qup_a_clk, QCOM_SMD_RPM_QUP_CLK, 0);
+DEFINE_CLK_SMD_RPM(sm6125, mmnrt_clk, mmnrt_a_clk, QCOM_SMD_RPM_MMAXI_CLK, 0);
+DEFINE_CLK_SMD_RPM(sm6125, mmrt_clk, mmrt_a_clk, QCOM_SMD_RPM_MMAXI_CLK, 1);
+DEFINE_CLK_SMD_RPM(sm6125, snoc_periph_clk, snoc_periph_a_clk,
+ QCOM_SMD_RPM_BUS_CLK, 0);
+DEFINE_CLK_SMD_RPM(sm6125, snoc_lpass_clk, snoc_lpass_a_clk,
+ QCOM_SMD_RPM_BUS_CLK, 5);
+
+static struct clk_smd_rpm *sm6125_clks[] = {
+ [RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
+ [RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
+ [RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
+ [RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
+ [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
+ [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
+ [RPM_SMD_QDSS_CLK] = &sm6125_qdss_clk,
+ [RPM_SMD_QDSS_A_CLK] = &sm6125_qdss_a_clk,
+ [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1,
+ [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a,
+ [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,
+ [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,
+ [RPM_SMD_CNOC_CLK] = &sm6125_cnoc_clk,
+ [RPM_SMD_CNOC_A_CLK] = &sm6125_cnoc_a_clk,
+ [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk,
+ [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk,
+ [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk,
+ [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk,
+ [RPM_SMD_LN_BB_CLK1] = &msm8916_bb_clk1,
+ [RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a,
+ [RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2,
+ [RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a,
+ [RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3,
+ [RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a,
+ [RPM_SMD_QUP_CLK] = &sm6125_qup_clk,
+ [RPM_SMD_QUP_A_CLK] = &sm6125_qup_a_clk,
+ [RPM_SMD_MMRT_CLK] = &sm6125_mmrt_clk,
+ [RPM_SMD_MMRT_A_CLK] = &sm6125_mmrt_a_clk,
+ [RPM_SMD_MMNRT_CLK] = &sm6125_mmnrt_clk,
+ [RPM_SMD_MMNRT_A_CLK] = &sm6125_mmnrt_a_clk,
+ [RPM_SMD_SNOC_PERIPH_CLK] = &sm6125_snoc_periph_clk,
+ [RPM_SMD_SNOC_PERIPH_A_CLK] = &sm6125_snoc_periph_a_clk,
+ [RPM_SMD_SNOC_LPASS_CLK] = &sm6125_snoc_lpass_clk,
+ [RPM_SMD_SNOC_LPASS_A_CLK] = &sm6125_snoc_lpass_a_clk,
+};
+
+static const struct rpm_smd_clk_desc rpm_clk_sm6125 = {
+ .clks = sm6125_clks,
+ .num_clks = ARRAY_SIZE(sm6125_clks),
+};
+
+/* SM6115 */
+static struct clk_smd_rpm *sm6115_clks[] = {
+ [RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo,
+ [RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a,
+ [RPM_SMD_SNOC_CLK] = &sm6125_snoc_clk,
+ [RPM_SMD_SNOC_A_CLK] = &sm6125_snoc_a_clk,
+ [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk,
+ [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk,
+ [RPM_SMD_QDSS_CLK] = &sm6125_qdss_clk,
+ [RPM_SMD_QDSS_A_CLK] = &sm6125_qdss_a_clk,
+ [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1,
+ [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a,
+ [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2,
+ [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a,
+ [RPM_SMD_CNOC_CLK] = &sm6125_cnoc_clk,
+ [RPM_SMD_CNOC_A_CLK] = &sm6125_cnoc_a_clk,
+ [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk,
+ [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk,
+ [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk,
+ [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk,
+ [RPM_SMD_QUP_CLK] = &sm6125_qup_clk,
+ [RPM_SMD_QUP_A_CLK] = &sm6125_qup_a_clk,
+ [RPM_SMD_MMRT_CLK] = &sm6125_mmrt_clk,
+ [RPM_SMD_MMRT_A_CLK] = &sm6125_mmrt_a_clk,
+ [RPM_SMD_MMNRT_CLK] = &sm6125_mmnrt_clk,
+ [RPM_SMD_MMNRT_A_CLK] = &sm6125_mmnrt_a_clk,
+ [RPM_SMD_SNOC_PERIPH_CLK] = &sm6125_snoc_periph_clk,
+ [RPM_SMD_SNOC_PERIPH_A_CLK] = &sm6125_snoc_periph_a_clk,
+ [RPM_SMD_SNOC_LPASS_CLK] = &sm6125_snoc_lpass_clk,
+ [RPM_SMD_SNOC_LPASS_A_CLK] = &sm6125_snoc_lpass_a_clk,
+ [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin,
+ [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin,
+ [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin,
+ [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin,
+};
+
+static const struct rpm_smd_clk_desc rpm_clk_sm6115 = {
+ .clks = sm6115_clks,
+ .num_clks = ARRAY_SIZE(sm6115_clks),
+};
+
static const struct of_device_id rpm_smd_clk_match_table[] = {
+ { .compatible = "qcom,rpmcc-mdm9607", .data = &rpm_clk_mdm9607 },
{ .compatible = "qcom,rpmcc-msm8226", .data = &rpm_clk_msm8974 },
{ .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },
{ .compatible = "qcom,rpmcc-msm8936", .data = &rpm_clk_msm8936 },
+ { .compatible = "qcom,rpmcc-msm8953", .data = &rpm_clk_msm8953 },
{ .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 },
{ .compatible = "qcom,rpmcc-msm8976", .data = &rpm_clk_msm8976 },
{ .compatible = "qcom,rpmcc-msm8992", .data = &rpm_clk_msm8992 },
@@ -925,6 +1081,8 @@ static const struct of_device_id rpm_smd_clk_match_table[] = {
{ .compatible = "qcom,rpmcc-msm8998", .data = &rpm_clk_msm8998 },
{ .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 },
{ .compatible = "qcom,rpmcc-sdm660", .data = &rpm_clk_sdm660 },
+ { .compatible = "qcom,rpmcc-sm6115", .data = &rpm_clk_sm6115 },
+ { .compatible = "qcom,rpmcc-sm6125", .data = &rpm_clk_sm6125 },
{ }
};
MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);
diff --git a/drivers/clk/qcom/dispcc-sc7280.c b/drivers/clk/qcom/dispcc-sc7280.c
new file mode 100644
index 000000000000..4ef4ae231794
--- /dev/null
+++ b/drivers/clk/qcom/dispcc-sc7280.c
@@ -0,0 +1,908 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,dispcc-sc7280.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "gdsc.h"
+
+enum {
+ P_BI_TCXO,
+ P_DISP_CC_PLL0_OUT_EVEN,
+ P_DISP_CC_PLL0_OUT_MAIN,
+ P_DP_PHY_PLL_LINK_CLK,
+ P_DP_PHY_PLL_VCO_DIV_CLK,
+ P_DSI0_PHY_PLL_OUT_BYTECLK,
+ P_DSI0_PHY_PLL_OUT_DSICLK,
+ P_EDP_PHY_PLL_LINK_CLK,
+ P_EDP_PHY_PLL_VCO_DIV_CLK,
+ P_GCC_DISP_GPLL0_CLK,
+};
+
+static const struct pll_vco lucid_vco[] = {
+ { 249600000, 2000000000, 0 },
+};
+
+/* 1520MHz Configuration*/
+static const struct alpha_pll_config disp_cc_pll0_config = {
+ .l = 0x4F,
+ .alpha = 0x2AAA,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00002261,
+ .config_ctl_hi1_val = 0x329A299C,
+ .user_ctl_val = 0x00000001,
+ .user_ctl_hi_val = 0x00000805,
+ .user_ctl_hi1_val = 0x00000000,
+};
+
+static struct clk_alpha_pll disp_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_vco,
+ .num_vco = ARRAY_SIZE(lucid_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_pll0",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_ops,
+ },
+ },
+};
+
+static const struct parent_map disp_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_0[] = {
+ { .fw_name = "bi_tcxo" },
+};
+
+static const struct parent_map disp_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_DP_PHY_PLL_LINK_CLK, 1 },
+ { P_DP_PHY_PLL_VCO_DIV_CLK, 2 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_1[] = {
+ { .fw_name = "bi_tcxo" },
+ { .fw_name = "dp_phy_pll_link_clk" },
+ { .fw_name = "dp_phy_pll_vco_div_clk" },
+};
+
+static const struct parent_map disp_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_DSI0_PHY_PLL_OUT_BYTECLK, 1 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_2[] = {
+ { .fw_name = "bi_tcxo" },
+ { .fw_name = "dsi0_phy_pll_out_byteclk" },
+};
+
+static const struct parent_map disp_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_EDP_PHY_PLL_LINK_CLK, 1 },
+ { P_EDP_PHY_PLL_VCO_DIV_CLK, 2 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_3[] = {
+ { .fw_name = "bi_tcxo" },
+ { .fw_name = "edp_phy_pll_link_clk" },
+ { .fw_name = "edp_phy_pll_vco_div_clk" },
+};
+
+static const struct parent_map disp_cc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_DISP_CC_PLL0_OUT_MAIN, 1 },
+ { P_GCC_DISP_GPLL0_CLK, 4 },
+ { P_DISP_CC_PLL0_OUT_EVEN, 5 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_4[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &disp_cc_pll0.clkr.hw },
+ { .fw_name = "gcc_disp_gpll0_clk" },
+ { .hw = &disp_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map disp_cc_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_DISP_GPLL0_CLK, 4 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_5[] = {
+ { .fw_name = "bi_tcxo" },
+ { .fw_name = "gcc_disp_gpll0_clk" },
+};
+
+static const struct parent_map disp_cc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_DSI0_PHY_PLL_OUT_DSICLK, 1 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_6[] = {
+ { .fw_name = "bi_tcxo" },
+ { .fw_name = "dsi0_phy_pll_out_dsiclk" },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(37500000, P_GCC_DISP_GPLL0_CLK, 16, 0, 0),
+ F(75000000, P_GCC_DISP_GPLL0_CLK, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = {
+ .cmd_rcgr = 0x1170,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_5,
+ .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_ahb_clk_src",
+ .parent_data = disp_cc_parent_data_5,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_5),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {
+ .cmd_rcgr = 0x10d8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_byte0_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_dp_aux_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_aux_clk_src = {
+ .cmd_rcgr = 0x1158,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .freq_tbl = ftbl_disp_cc_mdss_dp_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_aux_clk_src",
+ .parent_data = disp_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = {
+ .cmd_rcgr = 0x1128,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_crypto_clk_src",
+ .parent_data = disp_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = {
+ .cmd_rcgr = 0x110c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_link_clk_src",
+ .parent_data = disp_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = {
+ .cmd_rcgr = 0x1140,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_pixel_clk_src",
+ .parent_data = disp_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_edp_aux_clk_src = {
+ .cmd_rcgr = 0x11d0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .freq_tbl = ftbl_disp_cc_mdss_dp_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_edp_aux_clk_src",
+ .parent_data = disp_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_edp_link_clk_src = {
+ .cmd_rcgr = 0x11a0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_edp_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_edp_pixel_clk_src = {
+ .cmd_rcgr = 0x1188,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_edp_pixel_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {
+ .cmd_rcgr = 0x10f4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_dp_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_esc0_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
+ F(200000000, P_GCC_DISP_GPLL0_CLK, 3, 0, 0),
+ F(300000000, P_GCC_DISP_GPLL0_CLK, 2, 0, 0),
+ F(380000000, P_DISP_CC_PLL0_OUT_MAIN, 4, 0, 0),
+ F(506666667, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(608000000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
+ .cmd_rcgr = 0x1090,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_4,
+ .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_mdp_clk_src",
+ .parent_data = disp_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
+ .cmd_rcgr = 0x1078,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_6,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_pclk0_clk_src",
+ .parent_data = disp_cc_parent_data_6,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {
+ .cmd_rcgr = 0x10a8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_4,
+ .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_rot_clk_src",
+ .parent_data = disp_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {
+ .cmd_rcgr = 0x10c0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .freq_tbl = ftbl_disp_cc_mdss_dp_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_vsync_clk_src",
+ .parent_data = disp_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {
+ .reg = 0x10f0,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_byte0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ops,
+ },
+};
+
+static struct clk_regmap_div disp_cc_mdss_dp_link_div_clk_src = {
+ .reg = 0x1124,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dp_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_dp_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div disp_cc_mdss_edp_link_div_clk_src = {
+ .reg = 0x11b8,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_edp_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_edp_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch disp_cc_mdss_ahb_clk = {
+ .halt_reg = 0x1050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_byte0_clk = {
+ .halt_reg = 0x1030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1030,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_byte0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_byte0_intf_clk = {
+ .halt_reg = 0x1034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_byte0_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_byte0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_dp_aux_clk = {
+ .halt_reg = 0x104c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x104c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_dp_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_dp_crypto_clk = {
+ .halt_reg = 0x1044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1044,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_crypto_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_dp_crypto_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_dp_link_clk = {
+ .halt_reg = 0x103c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x103c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_dp_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_dp_link_intf_clk = {
+ .halt_reg = 0x1040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_dp_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_dp_pixel_clk = {
+ .halt_reg = 0x1048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1048,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_pixel_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_dp_pixel_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_edp_aux_clk = {
+ .halt_reg = 0x1060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1060,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_edp_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_edp_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_edp_link_clk = {
+ .halt_reg = 0x1058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_edp_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_edp_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_edp_link_intf_clk = {
+ .halt_reg = 0x105c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x105c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_edp_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_edp_link_div_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_edp_pixel_clk = {
+ .halt_reg = 0x1054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1054,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_edp_pixel_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_edp_pixel_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_esc0_clk = {
+ .halt_reg = 0x1038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1038,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_esc0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_esc0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_mdp_clk = {
+ .halt_reg = 0x1014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_mdp_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_mdp_lut_clk = {
+ .halt_reg = 0x1024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_mdp_lut_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = {
+ .halt_reg = 0x2004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x2004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_non_gdsc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_pclk0_clk = {
+ .halt_reg = 0x1010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_pclk0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_pclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_rot_clk = {
+ .halt_reg = 0x101c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x101c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_rot_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_rot_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_rscc_ahb_clk = {
+ .halt_reg = 0x200c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_rscc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_rscc_vsync_clk = {
+ .halt_reg = 0x2008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_rscc_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_vsync_clk = {
+ .halt_reg = 0x102c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x102c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_sleep_clk = {
+ .halt_reg = 0x5004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc disp_cc_mdss_core_gdsc = {
+ .gdscr = 0x1004,
+ .pd = {
+ .name = "disp_cc_mdss_core_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *disp_cc_sc7280_clocks[] = {
+ [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,
+ [DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,
+ [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr,
+ [DISP_CC_MDSS_DP_AUX_CLK] = &disp_cc_mdss_dp_aux_clk.clkr,
+ [DISP_CC_MDSS_DP_AUX_CLK_SRC] = &disp_cc_mdss_dp_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DP_CRYPTO_CLK] = &disp_cc_mdss_dp_crypto_clk.clkr,
+ [DISP_CC_MDSS_DP_CRYPTO_CLK_SRC] = &disp_cc_mdss_dp_crypto_clk_src.clkr,
+ [DISP_CC_MDSS_DP_LINK_CLK] = &disp_cc_mdss_dp_link_clk.clkr,
+ [DISP_CC_MDSS_DP_LINK_CLK_SRC] = &disp_cc_mdss_dp_link_clk_src.clkr,
+ [DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC] =
+ &disp_cc_mdss_dp_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DP_LINK_INTF_CLK] = &disp_cc_mdss_dp_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DP_PIXEL_CLK] = &disp_cc_mdss_dp_pixel_clk.clkr,
+ [DISP_CC_MDSS_DP_PIXEL_CLK_SRC] = &disp_cc_mdss_dp_pixel_clk_src.clkr,
+ [DISP_CC_MDSS_EDP_AUX_CLK] = &disp_cc_mdss_edp_aux_clk.clkr,
+ [DISP_CC_MDSS_EDP_AUX_CLK_SRC] = &disp_cc_mdss_edp_aux_clk_src.clkr,
+ [DISP_CC_MDSS_EDP_LINK_CLK] = &disp_cc_mdss_edp_link_clk.clkr,
+ [DISP_CC_MDSS_EDP_LINK_CLK_SRC] = &disp_cc_mdss_edp_link_clk_src.clkr,
+ [DISP_CC_MDSS_EDP_LINK_DIV_CLK_SRC] =
+ &disp_cc_mdss_edp_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_EDP_LINK_INTF_CLK] = &disp_cc_mdss_edp_link_intf_clk.clkr,
+ [DISP_CC_MDSS_EDP_PIXEL_CLK] = &disp_cc_mdss_edp_pixel_clk.clkr,
+ [DISP_CC_MDSS_EDP_PIXEL_CLK_SRC] = &disp_cc_mdss_edp_pixel_clk_src.clkr,
+ [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr,
+ [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr,
+ [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,
+ [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,
+ [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,
+ [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,
+ [DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr,
+ [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr,
+ [DISP_CC_MDSS_ROT_CLK] = &disp_cc_mdss_rot_clk.clkr,
+ [DISP_CC_MDSS_ROT_CLK_SRC] = &disp_cc_mdss_rot_clk_src.clkr,
+ [DISP_CC_MDSS_RSCC_AHB_CLK] = &disp_cc_mdss_rscc_ahb_clk.clkr,
+ [DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp_cc_mdss_rscc_vsync_clk.clkr,
+ [DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr,
+ [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr,
+ [DISP_CC_PLL0] = &disp_cc_pll0.clkr,
+ [DISP_CC_SLEEP_CLK] = &disp_cc_sleep_clk.clkr,
+};
+
+static struct gdsc *disp_cc_sc7280_gdscs[] = {
+ [DISP_CC_MDSS_CORE_GDSC] = &disp_cc_mdss_core_gdsc,
+};
+
+static const struct regmap_config disp_cc_sc7280_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x10000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc disp_cc_sc7280_desc = {
+ .config = &disp_cc_sc7280_regmap_config,
+ .clks = disp_cc_sc7280_clocks,
+ .num_clks = ARRAY_SIZE(disp_cc_sc7280_clocks),
+ .gdscs = disp_cc_sc7280_gdscs,
+ .num_gdscs = ARRAY_SIZE(disp_cc_sc7280_gdscs),
+};
+
+static const struct of_device_id disp_cc_sc7280_match_table[] = {
+ { .compatible = "qcom,sc7280-dispcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, disp_cc_sc7280_match_table);
+
+static int disp_cc_sc7280_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &disp_cc_sc7280_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_lucid_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
+
+ /*
+ * Keep the clocks always-ON
+ * DISP_CC_XO_CLK
+ */
+ regmap_update_bits(regmap, 0x5008, BIT(0), BIT(0));
+
+ return qcom_cc_really_probe(pdev, &disp_cc_sc7280_desc, regmap);
+}
+
+static struct platform_driver disp_cc_sc7280_driver = {
+ .probe = disp_cc_sc7280_probe,
+ .driver = {
+ .name = "disp_cc-sc7280",
+ .of_match_table = disp_cc_sc7280_match_table,
+ },
+};
+
+static int __init disp_cc_sc7280_init(void)
+{
+ return platform_driver_register(&disp_cc_sc7280_driver);
+}
+subsys_initcall(disp_cc_sc7280_init);
+
+static void __exit disp_cc_sc7280_exit(void)
+{
+ platform_driver_unregister(&disp_cc_sc7280_driver);
+}
+module_exit(disp_cc_sc7280_exit);
+
+MODULE_DESCRIPTION("QTI DISP_CC sc7280 Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c
index 601c7c0ba483..bf9ffe1a1cf4 100644
--- a/drivers/clk/qcom/dispcc-sm8250.c
+++ b/drivers/clk/qcom/dispcc-sm8250.c
@@ -26,6 +26,10 @@ enum {
P_DISP_CC_PLL1_OUT_MAIN,
P_DP_PHY_PLL_LINK_CLK,
P_DP_PHY_PLL_VCO_DIV_CLK,
+ P_DPTX1_PHY_PLL_LINK_CLK,
+ P_DPTX1_PHY_PLL_VCO_DIV_CLK,
+ P_DPTX2_PHY_PLL_LINK_CLK,
+ P_DPTX2_PHY_PLL_VCO_DIV_CLK,
P_EDP_PHY_PLL_LINK_CLK,
P_EDP_PHY_PLL_VCO_DIV_CLK,
P_DSI0_PHY_PLL_OUT_BYTECLK,
@@ -98,12 +102,20 @@ static const struct parent_map disp_cc_parent_map_0[] = {
{ P_BI_TCXO, 0 },
{ P_DP_PHY_PLL_LINK_CLK, 1 },
{ P_DP_PHY_PLL_VCO_DIV_CLK, 2 },
+ { P_DPTX1_PHY_PLL_LINK_CLK, 3 },
+ { P_DPTX1_PHY_PLL_VCO_DIV_CLK, 4 },
+ { P_DPTX2_PHY_PLL_LINK_CLK, 5 },
+ { P_DPTX2_PHY_PLL_VCO_DIV_CLK, 6 },
};
static const struct clk_parent_data disp_cc_parent_data_0[] = {
{ .fw_name = "bi_tcxo" },
{ .fw_name = "dp_phy_pll_link_clk" },
{ .fw_name = "dp_phy_pll_vco_div_clk" },
+ { .fw_name = "dptx1_phy_pll_link_clk" },
+ { .fw_name = "dptx1_phy_pll_vco_div_clk" },
+ { .fw_name = "dptx2_phy_pll_link_clk" },
+ { .fw_name = "dptx2_phy_pll_vco_div_clk" },
};
static const struct parent_map disp_cc_parent_map_1[] = {
@@ -269,20 +281,11 @@ static struct clk_rcg2 disp_cc_mdss_dp_aux_clk_src = {
},
};
-static const struct freq_tbl ftbl_disp_cc_mdss_dp_link1_clk_src[] = {
- F(162000000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0),
- F(270000000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0),
- F(540000000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0),
- F(810000000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0),
- { }
-};
-
static struct clk_rcg2 disp_cc_mdss_dp_link1_clk_src = {
.cmd_rcgr = 0x220c,
.mnd_width = 0,
.hid_width = 5,
.parent_map = disp_cc_parent_map_0,
- .freq_tbl = ftbl_disp_cc_mdss_dp_link1_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "disp_cc_mdss_dp_link1_clk_src",
.parent_data = disp_cc_parent_data_0,
@@ -296,7 +299,6 @@ static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = {
.mnd_width = 0,
.hid_width = 5,
.parent_map = disp_cc_parent_map_0,
- .freq_tbl = ftbl_disp_cc_mdss_dp_link1_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "disp_cc_mdss_dp_link_clk_src",
.parent_data = disp_cc_parent_data_0,
diff --git a/drivers/clk/qcom/gcc-msm8953.c b/drivers/clk/qcom/gcc-msm8953.c
new file mode 100644
index 000000000000..49513f1366ff
--- /dev/null
+++ b/drivers/clk/qcom/gcc-msm8953.c
@@ -0,0 +1,4250 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021, The Linux Foundation. All rights reserved.
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8953.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ P_XO,
+ P_SLEEP_CLK,
+ P_GPLL0,
+ P_GPLL0_DIV2,
+ P_GPLL2,
+ P_GPLL3,
+ P_GPLL4,
+ P_GPLL6,
+ P_GPLL6_DIV2,
+ P_DSI0PLL,
+ P_DSI0PLL_BYTE,
+ P_DSI1PLL,
+ P_DSI1PLL_BYTE,
+};
+
+static struct clk_alpha_pll gpll0_early = {
+ .offset = 0x21000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x45000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gpll0_early",
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll0_early_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early_div",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0_early.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+ .offset = 0x21000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0_early.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll2_early = {
+ .offset = 0x4a000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x45000,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll2_early",
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll2 = {
+ .offset = 0x4a000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll2",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll2_early.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+static const struct pll_vco gpll3_p_vco[] = {
+ { 1000000000, 2000000000, 0 },
+};
+
+static const struct alpha_pll_config gpll3_early_config = {
+ .l = 63,
+ .config_ctl_val = 0x4001055b,
+ .early_output_mask = 0,
+ .post_div_mask = GENMASK(11, 8),
+ .post_div_val = BIT(8),
+};
+
+static struct clk_alpha_pll gpll3_early = {
+ .offset = 0x22000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .vco_table = gpll3_p_vco,
+ .num_vco = ARRAY_SIZE(gpll3_p_vco),
+ .flags = SUPPORTS_DYNAMIC_UPDATE,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll3_early",
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll3 = {
+ .offset = 0x22000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll3",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll3_early.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_alpha_pll gpll4_early = {
+ .offset = 0x24000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x45000,
+ .enable_mask = BIT(5),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll4_early",
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll4 = {
+ .offset = 0x24000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll4",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll4_early.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll6_early = {
+ .offset = 0x37000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x45000,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll6_early",
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll6_early_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll6_early_div",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll6_early.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll6 = {
+ .offset = 0x37000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll6",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll6_early.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll0div2_2_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_DIV2, 2 },
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll0div2_4_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_DIV2, 4 },
+};
+
+static const struct clk_parent_data gcc_xo_gpll0_gpll0div2_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct parent_map gcc_apc_droop_detector_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 2 },
+};
+
+static const struct clk_parent_data gcc_apc_droop_detector_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_apc_droop_detector_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(400000000, P_GPLL0, 2, 0, 0),
+ F(576000000, P_GPLL4, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 apc0_droop_detector_clk_src = {
+ .cmd_rcgr = 0x78008,
+ .hid_width = 5,
+ .freq_tbl = ftbl_apc_droop_detector_clk_src,
+ .parent_map = gcc_apc_droop_detector_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "apc0_droop_detector_clk_src",
+ .parent_data = gcc_apc_droop_detector_data,
+ .num_parents = ARRAY_SIZE(gcc_apc_droop_detector_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+static struct clk_rcg2 apc1_droop_detector_clk_src = {
+ .cmd_rcgr = 0x79008,
+ .hid_width = 5,
+ .freq_tbl = ftbl_apc_droop_detector_clk_src,
+ .parent_map = gcc_apc_droop_detector_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "apc1_droop_detector_clk_src",
+ .parent_data = gcc_apc_droop_detector_data,
+ .num_parents = ARRAY_SIZE(gcc_apc_droop_detector_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_apss_ahb_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0_DIV2, 16, 0, 0),
+ F(50000000, P_GPLL0, 16, 0, 0),
+ F(100000000, P_GPLL0, 8, 0, 0),
+ F(133330000, P_GPLL0, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 apss_ahb_clk_src = {
+ .cmd_rcgr = 0x46000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_apss_ahb_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_4_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "apss_ahb_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_blsp_i2c_apps_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0_DIV2, 16, 0, 0),
+ F(50000000, P_GPLL0, 16, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0200c,
+ .hid_width = 5,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_qup1_i2c_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x03000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_qup2_i2c_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x04000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_qup3_i2c_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x05000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_qup4_i2c_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0c00c,
+ .hid_width = 5,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_qup1_i2c_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0d000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_qup2_i2c_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0f000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_qup3_i2c_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x18000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_qup4_i2c_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_blsp_spi_apps_clk_src[] = {
+ F(960000, P_XO, 10, 1, 2),
+ F(4800000, P_XO, 4, 0, 0),
+ F(9600000, P_XO, 2, 0, 0),
+ F(12500000, P_GPLL0_DIV2, 16, 1, 2),
+ F(16000000, P_GPLL0, 10, 1, 5),
+ F(19200000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0, 16, 1, 2),
+ F(50000000, P_GPLL0, 16, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x02024,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_blsp_spi_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_qup1_spi_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x03014,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_blsp_spi_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_qup2_spi_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x04024,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_blsp_spi_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_qup3_spi_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x05024,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_blsp_spi_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_qup4_spi_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0c024,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_blsp_spi_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_qup1_spi_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0d014,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_blsp_spi_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_qup2_spi_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0f024,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_blsp_spi_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_qup3_spi_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x18024,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_blsp_spi_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_qup4_spi_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_blsp_uart_apps_clk_src[] = {
+ F(3686400, P_GPLL0_DIV2, 1, 144, 15625),
+ F(7372800, P_GPLL0_DIV2, 1, 288, 15625),
+ F(14745600, P_GPLL0_DIV2, 1, 576, 15625),
+ F(16000000, P_GPLL0_DIV2, 5, 1, 5),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 1, 3, 100),
+ F(25000000, P_GPLL0, 16, 1, 2),
+ F(32000000, P_GPLL0, 1, 1, 25),
+ F(40000000, P_GPLL0, 1, 1, 20),
+ F(46400000, P_GPLL0, 1, 29, 500),
+ F(48000000, P_GPLL0, 1, 3, 50),
+ F(51200000, P_GPLL0, 1, 8, 125),
+ F(56000000, P_GPLL0, 1, 7, 100),
+ F(58982400, P_GPLL0, 1, 1152, 15625),
+ F(60000000, P_GPLL0, 1, 3, 40),
+ F(64000000, P_GPLL0, 1, 2, 25),
+ { }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x02044,
+ .hid_width = 5,
+ .mnd_width = 16,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_4_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_uart1_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x03034,
+ .hid_width = 5,
+ .mnd_width = 16,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_4_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp1_uart2_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x0c044,
+ .hid_width = 5,
+ .mnd_width = 16,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_4_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_uart1_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x0d034,
+ .hid_width = 5,
+ .mnd_width = 16,
+ .freq_tbl = ftbl_blsp_uart_apps_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_4_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "blsp2_uart2_apps_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_byte0_map[] = {
+ { P_XO, 0 },
+ { P_DSI0PLL_BYTE, 1 },
+ { P_DSI1PLL_BYTE, 3 },
+};
+
+static const struct parent_map gcc_byte1_map[] = {
+ { P_XO, 0 },
+ { P_DSI0PLL_BYTE, 3 },
+ { P_DSI1PLL_BYTE, 1 },
+};
+
+static const struct clk_parent_data gcc_byte_data[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "dsi0pllbyte", .name = "dsi0pllbyte" },
+ { .fw_name = "dsi1pllbyte", .name = "dsi1pllbyte" },
+};
+
+static struct clk_rcg2 byte0_clk_src = {
+ .cmd_rcgr = 0x4d044,
+ .hid_width = 5,
+ .parent_map = gcc_byte0_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "byte0_clk_src",
+ .parent_data = gcc_byte_data,
+ .num_parents = ARRAY_SIZE(gcc_byte_data),
+ .ops = &clk_byte2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+};
+
+static struct clk_rcg2 byte1_clk_src = {
+ .cmd_rcgr = 0x4d0b0,
+ .hid_width = 5,
+ .parent_map = gcc_byte1_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "byte1_clk_src",
+ .parent_data = gcc_byte_data,
+ .num_parents = ARRAY_SIZE(gcc_byte_data),
+ .ops = &clk_byte2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+};
+
+static const struct parent_map gcc_gp_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL0_DIV2, 4 },
+ { P_SLEEP_CLK, 6 },
+};
+
+static const struct clk_parent_data gcc_gp_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+ { .fw_name = "sleep", .name = "sleep" },
+};
+
+static const struct freq_tbl ftbl_camss_gp_clk_src[] = {
+ F(50000000, P_GPLL0_DIV2, 8, 0, 0),
+ F(100000000, P_GPLL0, 8, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(266670000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 camss_gp0_clk_src = {
+ .cmd_rcgr = 0x54000,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_camss_gp_clk_src,
+ .parent_map = gcc_gp_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "camss_gp0_clk_src",
+ .parent_data = gcc_gp_data,
+ .num_parents = ARRAY_SIZE(gcc_gp_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 camss_gp1_clk_src = {
+ .cmd_rcgr = 0x55000,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_camss_gp_clk_src,
+ .parent_map = gcc_gp_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "camss_gp1_clk_src",
+ .parent_data = gcc_gp_data,
+ .num_parents = ARRAY_SIZE(gcc_gp_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_camss_top_ahb_clk_src[] = {
+ F(40000000, P_GPLL0_DIV2, 10, 0, 0),
+ F(80000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 camss_top_ahb_clk_src = {
+ .cmd_rcgr = 0x5a000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_camss_top_ahb_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "camss_top_ahb_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_cci_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 2 },
+ { P_GPLL0_DIV2, 3 },
+ { P_SLEEP_CLK, 6 },
+};
+
+static const struct clk_parent_data gcc_cci_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+ { .fw_name = "sleep", .name = "sleep" },
+};
+
+static const struct freq_tbl ftbl_cci_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(37500000, P_GPLL0_DIV2, 1, 3, 32),
+ { }
+};
+
+static struct clk_rcg2 cci_clk_src = {
+ .cmd_rcgr = 0x51000,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_cci_clk_src,
+ .parent_map = gcc_cci_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "cci_clk_src",
+ .parent_data = gcc_cci_data,
+ .num_parents = ARRAY_SIZE(gcc_cci_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_cpp_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 3 },
+ { P_GPLL2, 4 },
+ { P_GPLL0_DIV2, 5 },
+};
+
+static const struct clk_parent_data gcc_cpp_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_cpp_clk_src[] = {
+ F(100000000, P_GPLL0_DIV2, 4, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(266670000, P_GPLL0, 3, 0, 0),
+ F(320000000, P_GPLL0, 2.5, 0, 0),
+ F(400000000, P_GPLL0, 2, 0, 0),
+ F(465000000, P_GPLL2, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cpp_clk_src = {
+ .cmd_rcgr = 0x58018,
+ .hid_width = 5,
+ .freq_tbl = ftbl_cpp_clk_src,
+ .parent_map = gcc_cpp_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "cpp_clk_src",
+ .parent_data = gcc_cpp_data,
+ .num_parents = ARRAY_SIZE(gcc_cpp_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_crypto_clk_src[] = {
+ F(40000000, P_GPLL0_DIV2, 10, 0, 0),
+ F(80000000, P_GPLL0, 10, 0, 0),
+ F(100000000, P_GPLL0, 8, 0, 0),
+ F(160000000, P_GPLL0, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 crypto_clk_src = {
+ .cmd_rcgr = 0x16004,
+ .hid_width = 5,
+ .freq_tbl = ftbl_crypto_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_4_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "crypto_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_csi0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL2, 4 },
+ { P_GPLL0_DIV2, 5 },
+};
+
+static const struct parent_map gcc_csi12_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL2, 5 },
+ { P_GPLL0_DIV2, 4 },
+};
+
+static const struct clk_parent_data gcc_csi_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_csi_clk_src[] = {
+ F(100000000, P_GPLL0_DIV2, 4, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(310000000, P_GPLL2, 3, 0, 0),
+ F(400000000, P_GPLL0, 2, 0, 0),
+ F(465000000, P_GPLL2, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 csi0_clk_src = {
+ .cmd_rcgr = 0x4e020,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_clk_src,
+ .parent_map = gcc_csi0_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi0_clk_src",
+ .parent_data = gcc_csi_data,
+ .num_parents = ARRAY_SIZE(gcc_csi_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 csi1_clk_src = {
+ .cmd_rcgr = 0x4f020,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_clk_src,
+ .parent_map = gcc_csi12_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi1_clk_src",
+ .parent_data = gcc_csi_data,
+ .num_parents = ARRAY_SIZE(gcc_csi_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 csi2_clk_src = {
+ .cmd_rcgr = 0x3c020,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_clk_src,
+ .parent_map = gcc_csi12_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi2_clk_src",
+ .parent_data = gcc_csi_data,
+ .num_parents = ARRAY_SIZE(gcc_csi_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_csip_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 3 },
+ { P_GPLL2, 4 },
+ { P_GPLL0_DIV2, 5 },
+};
+
+static const struct clk_parent_data gcc_csip_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_csi_p_clk_src[] = {
+ F(66670000, P_GPLL0_DIV2, 6, 0, 0),
+ F(133330000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(266670000, P_GPLL0, 3, 0, 0),
+ F(310000000, P_GPLL2, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 csi0p_clk_src = {
+ .cmd_rcgr = 0x58084,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_p_clk_src,
+ .parent_map = gcc_csip_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi0p_clk_src",
+ .parent_data = gcc_csip_data,
+ .num_parents = ARRAY_SIZE(gcc_csip_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 csi1p_clk_src = {
+ .cmd_rcgr = 0x58094,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_p_clk_src,
+ .parent_map = gcc_csip_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi1p_clk_src",
+ .parent_data = gcc_csip_data,
+ .num_parents = ARRAY_SIZE(gcc_csip_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 csi2p_clk_src = {
+ .cmd_rcgr = 0x580a4,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_p_clk_src,
+ .parent_map = gcc_csip_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi2p_clk_src",
+ .parent_data = gcc_csip_data,
+ .num_parents = ARRAY_SIZE(gcc_csip_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_csi_phytimer_clk_src[] = {
+ F(100000000, P_GPLL0_DIV2, 4, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(266670000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 csi0phytimer_clk_src = {
+ .cmd_rcgr = 0x4e000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_phytimer_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi0phytimer_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 csi1phytimer_clk_src = {
+ .cmd_rcgr = 0x4f000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_phytimer_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi1phytimer_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 csi2phytimer_clk_src = {
+ .cmd_rcgr = 0x4f05c,
+ .hid_width = 5,
+ .freq_tbl = ftbl_csi_phytimer_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "csi2phytimer_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_esc_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 3 },
+};
+
+static const struct clk_parent_data gcc_esc_vsync_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_esc0_1_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 esc0_clk_src = {
+ .cmd_rcgr = 0x4d05c,
+ .hid_width = 5,
+ .freq_tbl = ftbl_esc0_1_clk_src,
+ .parent_map = gcc_esc_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "esc0_clk_src",
+ .parent_data = gcc_esc_vsync_data,
+ .num_parents = ARRAY_SIZE(gcc_esc_vsync_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 esc1_clk_src = {
+ .cmd_rcgr = 0x4d0a8,
+ .hid_width = 5,
+ .freq_tbl = ftbl_esc0_1_clk_src,
+ .parent_map = gcc_esc_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "esc1_clk_src",
+ .parent_data = gcc_esc_vsync_data,
+ .num_parents = ARRAY_SIZE(gcc_esc_vsync_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_gfx3d_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL3, 2 },
+ { P_GPLL6, 3 },
+ { P_GPLL4, 4 },
+ { P_GPLL0_DIV2, 5 },
+ { P_GPLL6_DIV2, 6 },
+};
+
+static const struct clk_parent_data gcc_gfx3d_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll3.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+ { .hw = &gpll6_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_gfx3d_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0_DIV2, 8, 0, 0),
+ F(80000000, P_GPLL0_DIV2, 5, 0, 0),
+ F(100000000, P_GPLL0_DIV2, 4, 0, 0),
+ F(133330000, P_GPLL0_DIV2, 3, 0, 0),
+ F(160000000, P_GPLL0_DIV2, 2.5, 0, 0),
+ F(200000000, P_GPLL0_DIV2, 2, 0, 0),
+ F(266670000, P_GPLL0, 3.0, 0, 0),
+ F(320000000, P_GPLL0, 2.5, 0, 0),
+ F(400000000, P_GPLL0, 2, 0, 0),
+ F(460800000, P_GPLL4, 2.5, 0, 0),
+ F(510000000, P_GPLL3, 2, 0, 0),
+ F(560000000, P_GPLL3, 2, 0, 0),
+ F(600000000, P_GPLL3, 2, 0, 0),
+ F(650000000, P_GPLL3, 2, 0, 0),
+ F(685000000, P_GPLL3, 2, 0, 0),
+ F(725000000, P_GPLL3, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gfx3d_clk_src = {
+ .cmd_rcgr = 0x59000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_gfx3d_clk_src,
+ .parent_map = gcc_gfx3d_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gfx3d_clk_src",
+ .parent_data = gcc_gfx3d_data,
+ .num_parents = ARRAY_SIZE(gcc_gfx3d_data),
+ .ops = &clk_rcg2_floor_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+};
+
+static const struct freq_tbl ftbl_gp_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+ .cmd_rcgr = 0x08004,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_gp_clk_src,
+ .parent_map = gcc_gp_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gp1_clk_src",
+ .parent_data = gcc_gp_data,
+ .num_parents = ARRAY_SIZE(gcc_gp_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+ .cmd_rcgr = 0x09004,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_gp_clk_src,
+ .parent_map = gcc_gp_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gp2_clk_src",
+ .parent_data = gcc_gp_data,
+ .num_parents = ARRAY_SIZE(gcc_gp_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+ .cmd_rcgr = 0x0a004,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_gp_clk_src,
+ .parent_map = gcc_gp_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gp3_clk_src",
+ .parent_data = gcc_gp_data,
+ .num_parents = ARRAY_SIZE(gcc_gp_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_jpeg0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL0_DIV2, 4 },
+ { P_GPLL2, 5 },
+};
+
+static const struct clk_parent_data gcc_jpeg0_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+ { .hw = &gpll2.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_jpeg0_clk_src[] = {
+ F(66670000, P_GPLL0_DIV2, 6, 0, 0),
+ F(133330000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(266670000, P_GPLL0, 3, 0, 0),
+ F(310000000, P_GPLL2, 3, 0, 0),
+ F(320000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 jpeg0_clk_src = {
+ .cmd_rcgr = 0x57000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_jpeg0_clk_src,
+ .parent_map = gcc_jpeg0_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "jpeg0_clk_src",
+ .parent_data = gcc_jpeg0_data,
+ .num_parents = ARRAY_SIZE(gcc_jpeg0_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_mclk_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL0_DIV2, 4 },
+ { P_GPLL6_DIV2, 5 },
+ { P_SLEEP_CLK, 6 },
+};
+
+static const struct clk_parent_data gcc_mclk_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+ { .hw = &gpll6_early_div.hw },
+ { .fw_name = "sleep", .name = "sleep" },
+};
+
+static const struct freq_tbl ftbl_mclk_clk_src[] = {
+ F(19200000, P_GPLL6, 5, 4, 45),
+ F(24000000, P_GPLL6_DIV2, 1, 2, 45),
+ F(26000000, P_GPLL0, 1, 4, 123),
+ F(33330000, P_GPLL0_DIV2, 12, 0, 0),
+ F(36610000, P_GPLL6, 1, 2, 59),
+ F(66667000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mclk0_clk_src = {
+ .cmd_rcgr = 0x52000,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_mclk_clk_src,
+ .parent_map = gcc_mclk_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "mclk0_clk_src",
+ .parent_data = gcc_mclk_data,
+ .num_parents = ARRAY_SIZE(gcc_mclk_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 mclk1_clk_src = {
+ .cmd_rcgr = 0x53000,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_mclk_clk_src,
+ .parent_map = gcc_mclk_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "mclk1_clk_src",
+ .parent_data = gcc_mclk_data,
+ .num_parents = ARRAY_SIZE(gcc_mclk_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 mclk2_clk_src = {
+ .cmd_rcgr = 0x5c000,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_mclk_clk_src,
+ .parent_map = gcc_mclk_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "mclk2_clk_src",
+ .parent_data = gcc_mclk_data,
+ .num_parents = ARRAY_SIZE(gcc_mclk_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 mclk3_clk_src = {
+ .cmd_rcgr = 0x5e000,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_mclk_clk_src,
+ .parent_map = gcc_mclk_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "mclk3_clk_src",
+ .parent_data = gcc_mclk_data,
+ .num_parents = ARRAY_SIZE(gcc_mclk_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_mdp_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 3 },
+ { P_GPLL0_DIV2, 4 },
+};
+
+static const struct clk_parent_data gcc_mdp_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_mdp_clk_src[] = {
+ F(50000000, P_GPLL0_DIV2, 8, 0, 0),
+ F(80000000, P_GPLL0_DIV2, 5, 0, 0),
+ F(160000000, P_GPLL0_DIV2, 2.5, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(266670000, P_GPLL0, 3, 0, 0),
+ F(320000000, P_GPLL0, 2.5, 0, 0),
+ F(400000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdp_clk_src = {
+ .cmd_rcgr = 0x4d014,
+ .hid_width = 5,
+ .freq_tbl = ftbl_mdp_clk_src,
+ .parent_map = gcc_mdp_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "mdp_clk_src",
+ .parent_data = gcc_mdp_data,
+ .num_parents = ARRAY_SIZE(gcc_mdp_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_pclk0_map[] = {
+ { P_XO, 0 },
+ { P_DSI0PLL, 1 },
+ { P_DSI1PLL, 3 },
+};
+
+static const struct parent_map gcc_pclk1_map[] = {
+ { P_XO, 0 },
+ { P_DSI0PLL, 3 },
+ { P_DSI1PLL, 1 },
+};
+
+static const struct clk_parent_data gcc_pclk_data[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "dsi0pll", .name = "dsi0pll" },
+ { .fw_name = "dsi1pll", .name = "dsi1pll" },
+};
+
+static struct clk_rcg2 pclk0_clk_src = {
+ .cmd_rcgr = 0x4d000,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .parent_map = gcc_pclk0_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pclk0_clk_src",
+ .parent_data = gcc_pclk_data,
+ .num_parents = ARRAY_SIZE(gcc_pclk_data),
+ .ops = &clk_pixel_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+};
+
+static struct clk_rcg2 pclk1_clk_src = {
+ .cmd_rcgr = 0x4d0b8,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .parent_map = gcc_pclk1_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pclk1_clk_src",
+ .parent_data = gcc_pclk_data,
+ .num_parents = ARRAY_SIZE(gcc_pclk_data),
+ .ops = &clk_pixel_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+};
+
+static const struct freq_tbl ftbl_pdm2_clk_src[] = {
+ F(32000000, P_GPLL0_DIV2, 12.5, 0, 0),
+ F(64000000, P_GPLL0, 12.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+ .cmd_rcgr = 0x44010,
+ .hid_width = 5,
+ .freq_tbl = ftbl_pdm2_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "pdm2_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_rbcpr_gfx_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0, 16, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 rbcpr_gfx_clk_src = {
+ .cmd_rcgr = 0x3a00c,
+ .hid_width = 5,
+ .freq_tbl = ftbl_rbcpr_gfx_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_4_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "rbcpr_gfx_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_sdcc1_ice_core_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL0_DIV2, 4 },
+};
+
+static const struct clk_parent_data gcc_sdcc1_ice_core_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
+ F(80000000, P_GPLL0_DIV2, 5, 0, 0),
+ F(160000000, P_GPLL0, 5, 0, 0),
+ F(270000000, P_GPLL6, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x5d000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
+ .parent_map = gcc_sdcc1_ice_core_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "sdcc1_ice_core_clk_src",
+ .parent_data = gcc_sdcc1_ice_core_data,
+ .num_parents = ARRAY_SIZE(gcc_sdcc1_ice_core_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_sdcc_apps_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 2 },
+ { P_GPLL0_DIV2, 4 },
+};
+
+static const struct clk_parent_data gcc_sdcc_apss_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0_DIV2, 5, 1, 4),
+ F(25000000, P_GPLL0_DIV2, 16, 0, 0),
+ F(50000000, P_GPLL0, 16, 0, 0),
+ F(100000000, P_GPLL0, 8, 0, 0),
+ F(177770000, P_GPLL0, 4.5, 0, 0),
+ F(192000000, P_GPLL4, 6, 0, 0),
+ F(384000000, P_GPLL4, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x42004,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_sdcc1_apps_clk_src,
+ .parent_map = gcc_sdcc_apps_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "sdcc1_apps_clk_src",
+ .parent_data = gcc_sdcc_apss_data,
+ .num_parents = ARRAY_SIZE(gcc_sdcc_apss_data),
+ .ops = &clk_rcg2_floor_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0_DIV2, 5, 1, 4),
+ F(25000000, P_GPLL0_DIV2, 16, 0, 0),
+ F(50000000, P_GPLL0, 16, 0, 0),
+ F(100000000, P_GPLL0, 8, 0, 0),
+ F(177770000, P_GPLL0, 4.5, 0, 0),
+ F(192000000, P_GPLL4, 6, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x43004,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_sdcc2_apps_clk_src,
+ .parent_map = gcc_sdcc_apps_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "sdcc2_apps_clk_src",
+ .parent_data = gcc_sdcc_apss_data,
+ .num_parents = ARRAY_SIZE(gcc_sdcc_apss_data),
+ .ops = &clk_rcg2_floor_ops,
+ }
+};
+
+static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
+ F(80000000, P_GPLL0_DIV2, 5, 0, 0),
+ F(100000000, P_GPLL0, 8, 0, 0),
+ F(133330000, P_GPLL0, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+ .cmd_rcgr = 0x3f00c,
+ .hid_width = 5,
+ .freq_tbl = ftbl_usb30_master_clk_src,
+ .parent_map = gcc_xo_gpll0_gpll0div2_2_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "usb30_master_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0div2_data,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0div2_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_usb30_mock_utmi_map[] = {
+ { P_XO, 0 },
+ { P_GPLL6, 1 },
+ { P_GPLL6_DIV2, 2 },
+ { P_GPLL0, 3 },
+ { P_GPLL0_DIV2, 4 },
+};
+
+static const struct clk_parent_data gcc_usb30_mock_utmi_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll6_early_div.hw },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL6_DIV2, 9, 1, 1),
+ { }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x3f020,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+ .parent_map = gcc_usb30_mock_utmi_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "usb30_mock_utmi_clk_src",
+ .parent_data = gcc_usb30_mock_utmi_data,
+ .num_parents = ARRAY_SIZE(gcc_usb30_mock_utmi_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_usb3_aux_map[] = {
+ { P_XO, 0 },
+ { P_SLEEP_CLK, 6 },
+};
+
+static const struct clk_parent_data gcc_usb3_aux_data[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "sleep", .name = "sleep" },
+};
+
+static const struct freq_tbl ftbl_usb3_aux_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb3_aux_clk_src = {
+ .cmd_rcgr = 0x3f05c,
+ .hid_width = 5,
+ .mnd_width = 8,
+ .freq_tbl = ftbl_usb3_aux_clk_src,
+ .parent_map = gcc_usb3_aux_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "usb3_aux_clk_src",
+ .parent_data = gcc_usb3_aux_data,
+ .num_parents = ARRAY_SIZE(gcc_usb3_aux_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_vcodec0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL2, 3 },
+ { P_GPLL0_DIV2, 4 },
+};
+
+static const struct clk_parent_data gcc_vcodec0_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_vcodec0_clk_src[] = {
+ F(114290000, P_GPLL0_DIV2, 3.5, 0, 0),
+ F(228570000, P_GPLL0, 3.5, 0, 0),
+ F(310000000, P_GPLL2, 3, 0, 0),
+ F(360000000, P_GPLL6, 3, 0, 0),
+ F(400000000, P_GPLL0, 2, 0, 0),
+ F(465000000, P_GPLL2, 2, 0, 0),
+ F(540000000, P_GPLL6, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vcodec0_clk_src = {
+ .cmd_rcgr = 0x4c000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_vcodec0_clk_src,
+ .parent_map = gcc_vcodec0_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "vcodec0_clk_src",
+ .parent_data = gcc_vcodec0_data,
+ .num_parents = ARRAY_SIZE(gcc_vcodec0_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_vfe_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL4, 3 },
+ { P_GPLL2, 4 },
+ { P_GPLL0_DIV2, 5 },
+};
+
+static const struct clk_parent_data gcc_vfe_data[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct freq_tbl ftbl_vfe_clk_src[] = {
+ F(50000000, P_GPLL0_DIV2, 8, 0, 0),
+ F(100000000, P_GPLL0_DIV2, 4, 0, 0),
+ F(133330000, P_GPLL0, 6, 0, 0),
+ F(160000000, P_GPLL0, 5, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(266670000, P_GPLL0, 3, 0, 0),
+ F(310000000, P_GPLL2, 3, 0, 0),
+ F(400000000, P_GPLL0, 2, 0, 0),
+ F(465000000, P_GPLL2, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vfe0_clk_src = {
+ .cmd_rcgr = 0x58000,
+ .hid_width = 5,
+ .freq_tbl = ftbl_vfe_clk_src,
+ .parent_map = gcc_vfe_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "vfe0_clk_src",
+ .parent_data = gcc_vfe_data,
+ .num_parents = ARRAY_SIZE(gcc_vfe_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_rcg2 vfe1_clk_src = {
+ .cmd_rcgr = 0x58054,
+ .hid_width = 5,
+ .freq_tbl = ftbl_vfe_clk_src,
+ .parent_map = gcc_vfe_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "vfe1_clk_src",
+ .parent_data = gcc_vfe_data,
+ .num_parents = ARRAY_SIZE(gcc_vfe_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static const struct parent_map gcc_vsync_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 2 },
+};
+
+static const struct freq_tbl ftbl_vsync_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vsync_clk_src = {
+ .cmd_rcgr = 0x4d02c,
+ .hid_width = 5,
+ .freq_tbl = ftbl_vsync_clk_src,
+ .parent_map = gcc_vsync_map,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "vsync_clk_src",
+ .parent_data = gcc_esc_vsync_data,
+ .num_parents = ARRAY_SIZE(gcc_esc_vsync_data),
+ .ops = &clk_rcg2_ops,
+ }
+};
+
+static struct clk_branch gcc_apc0_droop_detector_gpll0_clk = {
+ .halt_reg = 0x78004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x78004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_apc0_droop_detector_gpll0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &apc0_droop_detector_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_apc1_droop_detector_gpll0_clk = {
+ .halt_reg = 0x79004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_apc1_droop_detector_gpll0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &apc1_droop_detector_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_apss_ahb_clk = {
+ .halt_reg = 0x4601c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_apss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &apss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_apss_axi_clk = {
+ .halt_reg = 0x46020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_apss_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_apss_tcu_async_clk = {
+ .halt_reg = 0x12018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_apss_tcu_async_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_bimc_gfx_clk = {
+ .halt_reg = 0x59034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_bimc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_bimc_gpu_clk = {
+ .halt_reg = 0x59030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59030,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_bimc_gpu_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+ .halt_reg = 0x01008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+ .halt_reg = 0x0b008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(20),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+ .halt_reg = 0x02008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x02008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_qup1_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup1_i2c_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+ .halt_reg = 0x03010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x03010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_qup2_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup2_i2c_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+ .halt_reg = 0x04020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x04020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_qup3_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup3_i2c_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+ .halt_reg = 0x05020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x05020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_qup4_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup4_i2c_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+ .halt_reg = 0x0c008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0c008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_qup1_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup1_i2c_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+ .halt_reg = 0x0d010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0d010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_qup2_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup2_i2c_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+ .halt_reg = 0x0f020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0f020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_qup3_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup3_i2c_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+ .halt_reg = 0x18020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x18020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_qup4_i2c_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup4_i2c_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+ .halt_reg = 0x02004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x02004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_qup1_spi_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup1_spi_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+ .halt_reg = 0x0300c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_qup2_spi_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup2_spi_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+ .halt_reg = 0x0401c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0401c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_qup3_spi_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup3_spi_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+ .halt_reg = 0x0501c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0501c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_qup4_spi_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup4_spi_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+ .halt_reg = 0x0c004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_qup1_spi_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup1_spi_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+ .halt_reg = 0x0d00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0d00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_qup2_spi_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup2_spi_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+ .halt_reg = 0x0f01c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0f01c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_qup3_spi_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup3_spi_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+ .halt_reg = 0x1801c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1801c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_qup4_spi_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup4_spi_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+ .halt_reg = 0x0203c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0203c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_uart1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_uart1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+ .halt_reg = 0x0302c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0302c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp1_uart2_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_uart2_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+ .halt_reg = 0x0c03c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0c03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_uart1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_uart1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+ .halt_reg = 0x0d02c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0d02c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_blsp2_uart2_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_uart2_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x1300c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_ahb_clk = {
+ .halt_reg = 0x56004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x56004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_cci_ahb_clk = {
+ .halt_reg = 0x5101c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5101c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_cci_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_cci_clk = {
+ .halt_reg = 0x51018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x51018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_cci_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &cci_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_cpp_ahb_clk = {
+ .halt_reg = 0x58040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_cpp_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_cpp_axi_clk = {
+ .halt_reg = 0x58064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58064,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_cpp_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_cpp_clk = {
+ .halt_reg = 0x5803c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5803c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_cpp_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &cpp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi0_ahb_clk = {
+ .halt_reg = 0x4e040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4e040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi0_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi1_ahb_clk = {
+ .halt_reg = 0x4f040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4f040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi1_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi2_ahb_clk = {
+ .halt_reg = 0x3c040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3c040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi2_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi0_clk = {
+ .halt_reg = 0x4e03c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4e03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi1_clk = {
+ .halt_reg = 0x4f03c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4f03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi2_clk = {
+ .halt_reg = 0x3c03c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3c03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi0_csiphy_3p_clk = {
+ .halt_reg = 0x58090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58090,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi0_csiphy_3p_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0p_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi1_csiphy_3p_clk = {
+ .halt_reg = 0x580a0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x580a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi1_csiphy_3p_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1p_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi2_csiphy_3p_clk = {
+ .halt_reg = 0x580b0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x580b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi2_csiphy_3p_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2p_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi0phy_clk = {
+ .halt_reg = 0x4e048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4e048,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi0phy_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi1phy_clk = {
+ .halt_reg = 0x4f048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4f048,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi1phy_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi2phy_clk = {
+ .halt_reg = 0x3c048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3c048,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi2phy_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi0phytimer_clk = {
+ .halt_reg = 0x4e01c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4e01c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi0phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi1phytimer_clk = {
+ .halt_reg = 0x4f01c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4f01c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi1phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi2phytimer_clk = {
+ .halt_reg = 0x4f068,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4f068,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi2phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi0pix_clk = {
+ .halt_reg = 0x4e058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4e058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi0pix_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi1pix_clk = {
+ .halt_reg = 0x4f058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4f058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi1pix_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi2pix_clk = {
+ .halt_reg = 0x3c058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3c058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi2pix_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi0rdi_clk = {
+ .halt_reg = 0x4e050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4e050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi0rdi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi1rdi_clk = {
+ .halt_reg = 0x4f050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4f050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi1rdi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi2rdi_clk = {
+ .halt_reg = 0x3c050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3c050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi2rdi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi_vfe0_clk = {
+ .halt_reg = 0x58050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi_vfe0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &vfe0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_csi_vfe1_clk = {
+ .halt_reg = 0x58074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58074,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_csi_vfe1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &vfe1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_gp0_clk = {
+ .halt_reg = 0x54018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x54018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_gp0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_gp0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_gp1_clk = {
+ .halt_reg = 0x55018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x55018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_gp1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_gp1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_ispif_ahb_clk = {
+ .halt_reg = 0x50004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x50004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_ispif_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_jpeg0_clk = {
+ .halt_reg = 0x57020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x57020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_jpeg0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &jpeg0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_jpeg_ahb_clk = {
+ .halt_reg = 0x57024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x57024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_jpeg_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_jpeg_axi_clk = {
+ .halt_reg = 0x57028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x57028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_jpeg_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_mclk0_clk = {
+ .halt_reg = 0x52018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x52018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_mclk0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &mclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_mclk1_clk = {
+ .halt_reg = 0x53018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x53018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_mclk1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &mclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_mclk2_clk = {
+ .halt_reg = 0x5c018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5c018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_mclk2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &mclk2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_mclk3_clk = {
+ .halt_reg = 0x5e018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5e018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_mclk3_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &mclk3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_micro_ahb_clk = {
+ .halt_reg = 0x5600c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_micro_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_top_ahb_clk = {
+ .halt_reg = 0x5a014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5a014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_top_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_vfe0_ahb_clk = {
+ .halt_reg = 0x58044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58044,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_vfe0_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_vfe0_axi_clk = {
+ .halt_reg = 0x58048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58048,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_vfe0_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_vfe0_clk = {
+ .halt_reg = 0x58038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58038,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_vfe0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &vfe0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_vfe1_ahb_clk = {
+ .halt_reg = 0x58060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58060,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_vfe1_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_vfe1_axi_clk = {
+ .halt_reg = 0x58068,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58068,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_vfe1_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_camss_vfe1_clk = {
+ .halt_reg = 0x5805c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5805c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_camss_vfe1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &vfe1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_cpp_tbu_clk = {
+ .halt_reg = 0x12040,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_cpp_tbu_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_crypto_ahb_clk = {
+ .halt_reg = 0x16024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_crypto_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_crypto_axi_clk = {
+ .halt_reg = 0x16020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_crypto_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_crypto_clk = {
+ .halt_reg = 0x1601c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_crypto_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &crypto_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_dcc_clk = {
+ .halt_reg = 0x77004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x77004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_dcc_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x08000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x08000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_gp1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gp1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x09000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x09000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_gp2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gp2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x0a000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x0a000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_gp3_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gp3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_jpeg_tbu_clk = {
+ .halt_reg = 0x12034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_jpeg_tbu_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdp_tbu_clk = {
+ .halt_reg = 0x1201c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdp_tbu_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_ahb_clk = {
+ .halt_reg = 0x4d07c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d07c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_axi_clk = {
+ .halt_reg = 0x4d080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d080,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_byte0_clk = {
+ .halt_reg = 0x4d094,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d094,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_byte0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_byte1_clk = {
+ .halt_reg = 0x4d0a0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d0a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_byte1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &byte1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_esc0_clk = {
+ .halt_reg = 0x4d098,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d098,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_esc0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &esc0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_esc1_clk = {
+ .halt_reg = 0x4d09c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d09c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_esc1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &esc1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_mdp_clk = {
+ .halt_reg = 0x4d088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d088,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_mdp_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_pclk0_clk = {
+ .halt_reg = 0x4d084,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d084,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_pclk0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &pclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_pclk1_clk = {
+ .halt_reg = 0x4d0a4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d0a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_pclk1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &pclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_mdss_vsync_clk = {
+ .halt_reg = 0x4d090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d090,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mdss_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_mss_cfg_ahb_clk = {
+ .halt_reg = 0x49000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mss_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
+ .halt_reg = 0x49004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_mss_q6_bimc_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_oxili_ahb_clk = {
+ .halt_reg = 0x59028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_oxili_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_oxili_aon_clk = {
+ .halt_reg = 0x59044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59044,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_oxili_aon_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gfx3d_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_oxili_gfx3d_clk = {
+ .halt_reg = 0x59020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_oxili_gfx3d_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gfx3d_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_oxili_timer_clk = {
+ .halt_reg = 0x59040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_oxili_timer_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_pcnoc_usb3_axi_clk = {
+ .halt_reg = 0x3f038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3f038,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_pcnoc_usb3_axi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb30_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x4400c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4400c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_pdm2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &pdm2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x44004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x44004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+ .halt_reg = 0x13004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_prng_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_qdss_dap_clk = {
+ .halt_reg = 0x29084,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_qdss_dap_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_qusb_ref_clk = {
+ .halt_reg = 0,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x41030,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_qusb_ref_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_rbcpr_gfx_clk = {
+ .halt_reg = 0x3a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_rbcpr_gfx_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &rbcpr_gfx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x5d014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5d014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &sdcc1_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x4201c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4201c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x4301c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4301c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x42018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x42018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &sdcc1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x43018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x43018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &sdcc2_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_smmu_cfg_clk = {
+ .halt_reg = 0x12038,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_smmu_cfg_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+ .halt_reg = 0x3f000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3f000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb30_master_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb30_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+ .halt_reg = 0x3f008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3f008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb30_mock_utmi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb30_mock_utmi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+ .halt_reg = 0x3f004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3f004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb30_sleep_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_usb3_aux_clk = {
+ .halt_reg = 0x3f044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3f044,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb3_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb3_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_usb3_pipe_clk = {
+ .halt_reg = 0,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x3f040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb3_pipe_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_usb_phy_cfg_ahb_clk = {
+ .halt_reg = 0x3f080,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x3f080,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb_phy_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_usb_ss_ref_clk = {
+ .halt_reg = 0,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x3f07c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb_ss_ref_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_venus0_ahb_clk = {
+ .halt_reg = 0x4c020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4c020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_venus0_ahb_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_venus0_axi_clk = {
+ .halt_reg = 0x4c024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4c024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_venus0_axi_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_venus0_core0_vcodec0_clk = {
+ .halt_reg = 0x4c02c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4c02c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_venus0_core0_vcodec0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &vcodec0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_venus0_vcodec0_clk = {
+ .halt_reg = 0x4c01c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4c01c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_venus0_vcodec0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &vcodec0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+ }
+};
+
+static struct clk_branch gcc_venus_tbu_clk = {
+ .halt_reg = 0x12014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(5),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_venus_tbu_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_vfe1_tbu_clk = {
+ .halt_reg = 0x12090,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_vfe1_tbu_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct clk_branch gcc_vfe_tbu_clk = {
+ .halt_reg = 0x1203c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_vfe_tbu_clk",
+ .ops = &clk_branch2_ops,
+ }
+ }
+};
+
+static struct gdsc usb30_gdsc = {
+ .gdscr = 0x3f078,
+ .pd = {
+ .name = "usb30_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ /*
+ * FIXME: dwc3 usb gadget cannot resume after GDSC power off
+ * dwc3 7000000.dwc3: failed to enable ep0out
+ */
+ .flags = ALWAYS_ON,
+};
+
+static struct gdsc venus_gdsc = {
+ .gdscr = 0x4c018,
+ .cxcs = (unsigned int []){ 0x4c024, 0x4c01c },
+ .cxc_count = 2,
+ .pd = {
+ .name = "venus_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc venus_core0_gdsc = {
+ .gdscr = 0x4c028,
+ .cxcs = (unsigned int []){ 0x4c02c },
+ .cxc_count = 1,
+ .pd = {
+ .name = "venus_core0",
+ },
+ .flags = HW_CTRL,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc mdss_gdsc = {
+ .gdscr = 0x4d078,
+ .cxcs = (unsigned int []){ 0x4d080, 0x4d088 },
+ .cxc_count = 2,
+ .pd = {
+ .name = "mdss_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc jpeg_gdsc = {
+ .gdscr = 0x5701c,
+ .cxcs = (unsigned int []){ 0x57020, 0x57028 },
+ .cxc_count = 2,
+ .pd = {
+ .name = "jpeg_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc vfe0_gdsc = {
+ .gdscr = 0x58034,
+ .cxcs = (unsigned int []){ 0x58038, 0x58048, 0x5600c, 0x58050 },
+ .cxc_count = 4,
+ .pd = {
+ .name = "vfe0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc vfe1_gdsc = {
+ .gdscr = 0x5806c,
+ .cxcs = (unsigned int []){ 0x5805c, 0x58068, 0x5600c, 0x58074 },
+ .cxc_count = 4,
+ .pd = {
+ .name = "vfe1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc oxili_gx_gdsc = {
+ .gdscr = 0x5901c,
+ .clamp_io_ctrl = 0x5b00c,
+ .cxcs = (unsigned int []){ 0x59000, 0x59024 },
+ .cxc_count = 2,
+ .pd = {
+ .name = "oxili_gx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = CLAMP_IO,
+};
+
+static struct gdsc oxili_cx_gdsc = {
+ .gdscr = 0x5904c,
+ .cxcs = (unsigned int []){ 0x59020 },
+ .cxc_count = 1,
+ .pd = {
+ .name = "oxili_cx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc cpp_gdsc = {
+ .gdscr = 0x58078,
+ .cxcs = (unsigned int []){ 0x5803c, 0x58064 },
+ .cxc_count = 2,
+ .pd = {
+ .name = "cpp_gdsc",
+ },
+ .flags = ALWAYS_ON,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct clk_hw *gcc_msm8953_hws[] = {
+ &gpll0_early_div.hw,
+ &gpll6_early_div.hw,
+};
+
+static struct clk_regmap *gcc_msm8953_clocks[] = {
+ [GPLL0] = &gpll0.clkr,
+ [GPLL0_EARLY] = &gpll0_early.clkr,
+ [GPLL2] = &gpll2.clkr,
+ [GPLL2_EARLY] = &gpll2_early.clkr,
+ [GPLL3] = &gpll3.clkr,
+ [GPLL3_EARLY] = &gpll3_early.clkr,
+ [GPLL4] = &gpll4.clkr,
+ [GPLL4_EARLY] = &gpll4_early.clkr,
+ [GPLL6] = &gpll6.clkr,
+ [GPLL6_EARLY] = &gpll6_early.clkr,
+ [GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr,
+ [GCC_APSS_AXI_CLK] = &gcc_apss_axi_clk.clkr,
+ [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+ [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr,
+ [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr,
+ [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr,
+ [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+ [GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr,
+ [GCC_APSS_TCU_ASYNC_CLK] = &gcc_apss_tcu_async_clk.clkr,
+ [GCC_CPP_TBU_CLK] = &gcc_cpp_tbu_clk.clkr,
+ [GCC_JPEG_TBU_CLK] = &gcc_jpeg_tbu_clk.clkr,
+ [GCC_MDP_TBU_CLK] = &gcc_mdp_tbu_clk.clkr,
+ [GCC_SMMU_CFG_CLK] = &gcc_smmu_cfg_clk.clkr,
+ [GCC_VENUS_TBU_CLK] = &gcc_venus_tbu_clk.clkr,
+ [GCC_VFE1_TBU_CLK] = &gcc_vfe1_tbu_clk.clkr,
+ [GCC_VFE_TBU_CLK] = &gcc_vfe_tbu_clk.clkr,
+ [CAMSS_TOP_AHB_CLK_SRC] = &camss_top_ahb_clk_src.clkr,
+ [CSI0_CLK_SRC] = &csi0_clk_src.clkr,
+ [APSS_AHB_CLK_SRC] = &apss_ahb_clk_src.clkr,
+ [CSI1_CLK_SRC] = &csi1_clk_src.clkr,
+ [CSI2_CLK_SRC] = &csi2_clk_src.clkr,
+ [VFE0_CLK_SRC] = &vfe0_clk_src.clkr,
+ [VCODEC0_CLK_SRC] = &vcodec0_clk_src.clkr,
+ [CPP_CLK_SRC] = &cpp_clk_src.clkr,
+ [JPEG0_CLK_SRC] = &jpeg0_clk_src.clkr,
+ [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+ [VFE1_CLK_SRC] = &vfe1_clk_src.clkr,
+ [APC0_DROOP_DETECTOR_CLK_SRC] = &apc0_droop_detector_clk_src.clkr,
+ [APC1_DROOP_DETECTOR_CLK_SRC] = &apc1_droop_detector_clk_src.clkr,
+ [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+ [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+ [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+ [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+ [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+ [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+ [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+ [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+ [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+ [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+ [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+ [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+ [CCI_CLK_SRC] = &cci_clk_src.clkr,
+ [CSI0P_CLK_SRC] = &csi0p_clk_src.clkr,
+ [CSI1P_CLK_SRC] = &csi1p_clk_src.clkr,
+ [CSI2P_CLK_SRC] = &csi2p_clk_src.clkr,
+ [CAMSS_GP0_CLK_SRC] = &camss_gp0_clk_src.clkr,
+ [CAMSS_GP1_CLK_SRC] = &camss_gp1_clk_src.clkr,
+ [MCLK0_CLK_SRC] = &mclk0_clk_src.clkr,
+ [MCLK1_CLK_SRC] = &mclk1_clk_src.clkr,
+ [MCLK2_CLK_SRC] = &mclk2_clk_src.clkr,
+ [MCLK3_CLK_SRC] = &mclk3_clk_src.clkr,
+ [CSI0PHYTIMER_CLK_SRC] = &csi0phytimer_clk_src.clkr,
+ [CSI1PHYTIMER_CLK_SRC] = &csi1phytimer_clk_src.clkr,
+ [CSI2PHYTIMER_CLK_SRC] = &csi2phytimer_clk_src.clkr,
+ [CRYPTO_CLK_SRC] = &crypto_clk_src.clkr,
+ [GP1_CLK_SRC] = &gp1_clk_src.clkr,
+ [GP2_CLK_SRC] = &gp2_clk_src.clkr,
+ [GP3_CLK_SRC] = &gp3_clk_src.clkr,
+ [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+ [RBCPR_GFX_CLK_SRC] = &rbcpr_gfx_clk_src.clkr,
+ [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+ [SDCC1_ICE_CORE_CLK_SRC] = &sdcc1_ice_core_clk_src.clkr,
+ [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+ [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+ [USB3_AUX_CLK_SRC] = &usb3_aux_clk_src.clkr,
+ [GCC_APC0_DROOP_DETECTOR_GPLL0_CLK] = &gcc_apc0_droop_detector_gpll0_clk.clkr,
+ [GCC_APC1_DROOP_DETECTOR_GPLL0_CLK] = &gcc_apc1_droop_detector_gpll0_clk.clkr,
+ [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+ [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+ [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+ [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+ [GCC_CAMSS_CCI_AHB_CLK] = &gcc_camss_cci_ahb_clk.clkr,
+ [GCC_CAMSS_CCI_CLK] = &gcc_camss_cci_clk.clkr,
+ [GCC_CAMSS_CPP_AHB_CLK] = &gcc_camss_cpp_ahb_clk.clkr,
+ [GCC_CAMSS_CPP_AXI_CLK] = &gcc_camss_cpp_axi_clk.clkr,
+ [GCC_CAMSS_CPP_CLK] = &gcc_camss_cpp_clk.clkr,
+ [GCC_CAMSS_CSI0_AHB_CLK] = &gcc_camss_csi0_ahb_clk.clkr,
+ [GCC_CAMSS_CSI0_CLK] = &gcc_camss_csi0_clk.clkr,
+ [GCC_CAMSS_CSI0_CSIPHY_3P_CLK] = &gcc_camss_csi0_csiphy_3p_clk.clkr,
+ [GCC_CAMSS_CSI0PHY_CLK] = &gcc_camss_csi0phy_clk.clkr,
+ [GCC_CAMSS_CSI0PIX_CLK] = &gcc_camss_csi0pix_clk.clkr,
+ [GCC_CAMSS_CSI0RDI_CLK] = &gcc_camss_csi0rdi_clk.clkr,
+ [GCC_CAMSS_CSI1_AHB_CLK] = &gcc_camss_csi1_ahb_clk.clkr,
+ [GCC_CAMSS_CSI1_CLK] = &gcc_camss_csi1_clk.clkr,
+ [GCC_CAMSS_CSI1_CSIPHY_3P_CLK] = &gcc_camss_csi1_csiphy_3p_clk.clkr,
+ [GCC_CAMSS_CSI1PHY_CLK] = &gcc_camss_csi1phy_clk.clkr,
+ [GCC_CAMSS_CSI1PIX_CLK] = &gcc_camss_csi1pix_clk.clkr,
+ [GCC_CAMSS_CSI1RDI_CLK] = &gcc_camss_csi1rdi_clk.clkr,
+ [GCC_CAMSS_CSI2_AHB_CLK] = &gcc_camss_csi2_ahb_clk.clkr,
+ [GCC_CAMSS_CSI2_CLK] = &gcc_camss_csi2_clk.clkr,
+ [GCC_CAMSS_CSI2_CSIPHY_3P_CLK] = &gcc_camss_csi2_csiphy_3p_clk.clkr,
+ [GCC_CAMSS_CSI2PHY_CLK] = &gcc_camss_csi2phy_clk.clkr,
+ [GCC_CAMSS_CSI2PIX_CLK] = &gcc_camss_csi2pix_clk.clkr,
+ [GCC_CAMSS_CSI2RDI_CLK] = &gcc_camss_csi2rdi_clk.clkr,
+ [GCC_CAMSS_CSI_VFE0_CLK] = &gcc_camss_csi_vfe0_clk.clkr,
+ [GCC_CAMSS_CSI_VFE1_CLK] = &gcc_camss_csi_vfe1_clk.clkr,
+ [GCC_CAMSS_GP0_CLK] = &gcc_camss_gp0_clk.clkr,
+ [GCC_CAMSS_GP1_CLK] = &gcc_camss_gp1_clk.clkr,
+ [GCC_CAMSS_ISPIF_AHB_CLK] = &gcc_camss_ispif_ahb_clk.clkr,
+ [GCC_CAMSS_JPEG0_CLK] = &gcc_camss_jpeg0_clk.clkr,
+ [GCC_CAMSS_JPEG_AHB_CLK] = &gcc_camss_jpeg_ahb_clk.clkr,
+ [GCC_CAMSS_JPEG_AXI_CLK] = &gcc_camss_jpeg_axi_clk.clkr,
+ [GCC_CAMSS_MCLK0_CLK] = &gcc_camss_mclk0_clk.clkr,
+ [GCC_CAMSS_MCLK1_CLK] = &gcc_camss_mclk1_clk.clkr,
+ [GCC_CAMSS_MCLK2_CLK] = &gcc_camss_mclk2_clk.clkr,
+ [GCC_CAMSS_MCLK3_CLK] = &gcc_camss_mclk3_clk.clkr,
+ [GCC_CAMSS_MICRO_AHB_CLK] = &gcc_camss_micro_ahb_clk.clkr,
+ [GCC_CAMSS_CSI0PHYTIMER_CLK] = &gcc_camss_csi0phytimer_clk.clkr,
+ [GCC_CAMSS_CSI1PHYTIMER_CLK] = &gcc_camss_csi1phytimer_clk.clkr,
+ [GCC_CAMSS_CSI2PHYTIMER_CLK] = &gcc_camss_csi2phytimer_clk.clkr,
+ [GCC_CAMSS_AHB_CLK] = &gcc_camss_ahb_clk.clkr,
+ [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr,
+ [GCC_CAMSS_VFE0_CLK] = &gcc_camss_vfe0_clk.clkr,
+ [GCC_CAMSS_VFE0_AHB_CLK] = &gcc_camss_vfe0_ahb_clk.clkr,
+ [GCC_CAMSS_VFE0_AXI_CLK] = &gcc_camss_vfe0_axi_clk.clkr,
+ [GCC_CAMSS_VFE1_AHB_CLK] = &gcc_camss_vfe1_ahb_clk.clkr,
+ [GCC_CAMSS_VFE1_AXI_CLK] = &gcc_camss_vfe1_axi_clk.clkr,
+ [GCC_CAMSS_VFE1_CLK] = &gcc_camss_vfe1_clk.clkr,
+ [GCC_DCC_CLK] = &gcc_dcc_clk.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr,
+ [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
+ [GCC_PCNOC_USB3_AXI_CLK] = &gcc_pcnoc_usb3_axi_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_RBCPR_GFX_CLK] = &gcc_rbcpr_gfx_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+ [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+ [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+ [GCC_USB3_AUX_CLK] = &gcc_usb3_aux_clk.clkr,
+ [GCC_USB_PHY_CFG_AHB_CLK] = &gcc_usb_phy_cfg_ahb_clk.clkr,
+ [GCC_VENUS0_AHB_CLK] = &gcc_venus0_ahb_clk.clkr,
+ [GCC_VENUS0_AXI_CLK] = &gcc_venus0_axi_clk.clkr,
+ [GCC_VENUS0_CORE0_VCODEC0_CLK] = &gcc_venus0_core0_vcodec0_clk.clkr,
+ [GCC_VENUS0_VCODEC0_CLK] = &gcc_venus0_vcodec0_clk.clkr,
+ [GCC_QUSB_REF_CLK] = &gcc_qusb_ref_clk.clkr,
+ [GCC_USB_SS_REF_CLK] = &gcc_usb_ss_ref_clk.clkr,
+ [GCC_USB3_PIPE_CLK] = &gcc_usb3_pipe_clk.clkr,
+ [MDP_CLK_SRC] = &mdp_clk_src.clkr,
+ [PCLK0_CLK_SRC] = &pclk0_clk_src.clkr,
+ [BYTE0_CLK_SRC] = &byte0_clk_src.clkr,
+ [ESC0_CLK_SRC] = &esc0_clk_src.clkr,
+ [PCLK1_CLK_SRC] = &pclk1_clk_src.clkr,
+ [BYTE1_CLK_SRC] = &byte1_clk_src.clkr,
+ [ESC1_CLK_SRC] = &esc1_clk_src.clkr,
+ [VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
+ [GCC_MDSS_AHB_CLK] = &gcc_mdss_ahb_clk.clkr,
+ [GCC_MDSS_AXI_CLK] = &gcc_mdss_axi_clk.clkr,
+ [GCC_MDSS_PCLK0_CLK] = &gcc_mdss_pclk0_clk.clkr,
+ [GCC_MDSS_BYTE0_CLK] = &gcc_mdss_byte0_clk.clkr,
+ [GCC_MDSS_ESC0_CLK] = &gcc_mdss_esc0_clk.clkr,
+ [GCC_MDSS_PCLK1_CLK] = &gcc_mdss_pclk1_clk.clkr,
+ [GCC_MDSS_BYTE1_CLK] = &gcc_mdss_byte1_clk.clkr,
+ [GCC_MDSS_ESC1_CLK] = &gcc_mdss_esc1_clk.clkr,
+ [GCC_MDSS_MDP_CLK] = &gcc_mdss_mdp_clk.clkr,
+ [GCC_MDSS_VSYNC_CLK] = &gcc_mdss_vsync_clk.clkr,
+ [GCC_OXILI_TIMER_CLK] = &gcc_oxili_timer_clk.clkr,
+ [GCC_OXILI_GFX3D_CLK] = &gcc_oxili_gfx3d_clk.clkr,
+ [GCC_OXILI_AON_CLK] = &gcc_oxili_aon_clk.clkr,
+ [GCC_OXILI_AHB_CLK] = &gcc_oxili_ahb_clk.clkr,
+ [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
+ [GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr,
+ [GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr,
+};
+
+static const struct qcom_reset_map gcc_msm8953_resets[] = {
+ [GCC_CAMSS_MICRO_BCR] = { 0x56008 },
+ [GCC_MSS_BCR] = { 0x71000 },
+ [GCC_QUSB2_PHY_BCR] = { 0x4103c },
+ [GCC_USB3PHY_PHY_BCR] = { 0x3f03c },
+ [GCC_USB3_PHY_BCR] = { 0x3f034 },
+ [GCC_USB_30_BCR] = { 0x3f070 },
+};
+
+static const struct regmap_config gcc_msm8953_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x80000,
+ .fast_io = true,
+};
+
+static struct gdsc *gcc_msm8953_gdscs[] = {
+ [CPP_GDSC] = &cpp_gdsc,
+ [JPEG_GDSC] = &jpeg_gdsc,
+ [MDSS_GDSC] = &mdss_gdsc,
+ [OXILI_CX_GDSC] = &oxili_cx_gdsc,
+ [OXILI_GX_GDSC] = &oxili_gx_gdsc,
+ [USB30_GDSC] = &usb30_gdsc,
+ [VENUS_CORE0_GDSC] = &venus_core0_gdsc,
+ [VENUS_GDSC] = &venus_gdsc,
+ [VFE0_GDSC] = &vfe0_gdsc,
+ [VFE1_GDSC] = &vfe1_gdsc,
+};
+
+static const struct qcom_cc_desc gcc_msm8953_desc = {
+ .config = &gcc_msm8953_regmap_config,
+ .clks = gcc_msm8953_clocks,
+ .num_clks = ARRAY_SIZE(gcc_msm8953_clocks),
+ .resets = gcc_msm8953_resets,
+ .num_resets = ARRAY_SIZE(gcc_msm8953_resets),
+ .gdscs = gcc_msm8953_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_msm8953_gdscs),
+ .clk_hws = gcc_msm8953_hws,
+ .num_clk_hws = ARRAY_SIZE(gcc_msm8953_hws),
+};
+
+static int gcc_msm8953_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &gcc_msm8953_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_alpha_pll_configure(&gpll3_early, regmap, &gpll3_early_config);
+
+ return qcom_cc_really_probe(pdev, &gcc_msm8953_desc, regmap);
+}
+
+static const struct of_device_id gcc_msm8953_match_table[] = {
+ { .compatible = "qcom,gcc-msm8953" },
+ {},
+};
+
+static struct platform_driver gcc_msm8953_driver = {
+ .probe = gcc_msm8953_probe,
+ .driver = {
+ .name = "gcc-msm8953",
+ .of_match_table = gcc_msm8953_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init gcc_msm8953_init(void)
+{
+ return platform_driver_register(&gcc_msm8953_driver);
+}
+core_initcall(gcc_msm8953_init);
+
+static void __exit gcc_msm8953_exit(void)
+{
+ platform_driver_unregister(&gcc_msm8953_driver);
+}
+module_exit(gcc_msm8953_exit);
+
+MODULE_DESCRIPTION("Qualcomm GCC MSM8953 Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
index 6394257ca8c0..4d36f96e9ae2 100644
--- a/drivers/clk/qcom/gcc-sdm660.c
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -37,114 +37,14 @@ enum {
P_GPLL1_EARLY_DIV,
};
-static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL0_EARLY_DIV, 6 },
-};
-
-static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div[] = {
- "xo",
- "gpll0",
- "gpll0_early_div",
-};
-
-static const struct parent_map gcc_parent_map_xo_gpll0[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
-};
-
-static const char * const gcc_parent_names_xo_gpll0[] = {
- "xo",
- "gpll0",
-};
-
-static const struct parent_map gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_SLEEP_CLK, 5 },
- { P_GPLL0_EARLY_DIV, 6 },
-};
-
-static const char * const gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div[] = {
- "xo",
- "gpll0",
- "sleep_clk",
- "gpll0_early_div",
-};
-
-static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
- { P_XO, 0 },
- { P_SLEEP_CLK, 5 },
-};
-
-static const char * const gcc_parent_names_xo_sleep_clk[] = {
- "xo",
- "sleep_clk",
-};
-
-static const struct parent_map gcc_parent_map_xo_gpll4[] = {
- { P_XO, 0 },
- { P_GPLL4, 5 },
-};
-
-static const char * const gcc_parent_names_xo_gpll4[] = {
- "xo",
- "gpll4",
-};
-
-static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL0_EARLY_DIV, 3 },
- { P_GPLL1, 4 },
- { P_GPLL4, 5 },
- { P_GPLL1_EARLY_DIV, 6 },
-};
-
-static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
- "xo",
- "gpll0",
- "gpll0_early_div",
- "gpll1",
- "gpll4",
- "gpll1_early_div",
-};
-
-static const struct parent_map gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL4, 5 },
- { P_GPLL0_EARLY_DIV, 6 },
-};
-
-static const char * const gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div[] = {
- "xo",
- "gpll0",
- "gpll4",
- "gpll0_early_div",
-};
-
-static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL0_EARLY_DIV, 2 },
- { P_GPLL4, 5 },
-};
-
-static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4[] = {
- "xo",
- "gpll0",
- "gpll0_early_div",
- "gpll4",
-};
-
static struct clk_fixed_factor xo = {
.mult = 1,
.div = 1,
.hw.init = &(struct clk_init_data){
.name = "xo",
- .parent_names = (const char *[]){ "xo_board" },
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xo"
+ },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
},
@@ -158,7 +58,9 @@ static struct clk_alpha_pll gpll0_early = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpll0_early",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ },
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
},
@@ -170,7 +72,9 @@ static struct clk_fixed_factor gpll0_early_div = {
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "gpll0_early_div",
- .parent_names = (const char *[]){ "gpll0_early" },
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0_early.clkr.hw,
+ },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
},
@@ -181,7 +85,9 @@ static struct clk_alpha_pll_postdiv gpll0 = {
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll0",
- .parent_names = (const char *[]){ "gpll0_early" },
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0_early.clkr.hw,
+ },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ops,
},
@@ -195,7 +101,9 @@ static struct clk_alpha_pll gpll1_early = {
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "gpll1_early",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ },
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
},
@@ -207,7 +115,9 @@ static struct clk_fixed_factor gpll1_early_div = {
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "gpll1_early_div",
- .parent_names = (const char *[]){ "gpll1_early" },
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll1_early.clkr.hw,
+ },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
},
@@ -218,7 +128,9 @@ static struct clk_alpha_pll_postdiv gpll1 = {
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll1",
- .parent_names = (const char *[]){ "gpll1_early" },
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll1_early.clkr.hw,
+ },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ops,
},
@@ -232,7 +144,9 @@ static struct clk_alpha_pll gpll4_early = {
.enable_mask = BIT(4),
.hw.init = &(struct clk_init_data){
.name = "gpll4_early",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ },
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
},
@@ -245,12 +159,116 @@ static struct clk_alpha_pll_postdiv gpll4 = {
.clkr.hw.init = &(struct clk_init_data)
{
.name = "gpll4",
- .parent_names = (const char *[]) { "gpll4_early" },
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll4_early.clkr.hw,
+ },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ops,
},
};
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_xo_gpll0_gpll0_early_div[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+};
+
+static const struct clk_parent_data gcc_parent_data_xo_gpll0[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_SLEEP_CLK, 5 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .fw_name = "sleep_clk" },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
+ { P_XO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_xo_sleep_clk[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "sleep_clk" },
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll4[] = {
+ { P_XO, 0 },
+ { P_GPLL4, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_xo_gpll4[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll4.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 3 },
+ { P_GPLL1, 4 },
+ { P_GPLL4, 5 },
+ { P_GPLL1_EARLY_DIV, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+ { .hw = &gpll1.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll1_early_div.hw },
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 5 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_xo_gpll0_gpll4_gpll0_early_div[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 2 },
+ { P_GPLL4, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_xo_gpll0_gpll0_early_div_gpll4[] = {
+ { .fw_name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_early_div.hw },
+ { .hw = &gpll4.clkr.hw },
+};
+
static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
F(19200000, P_XO, 1, 0, 0),
F(50000000, P_GPLL0, 12, 0, 0),
@@ -265,7 +283,7 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup1_i2c_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -290,7 +308,7 @@ static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup1_spi_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -304,7 +322,7 @@ static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup2_i2c_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -318,7 +336,7 @@ static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup2_spi_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -332,7 +350,7 @@ static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup3_i2c_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -346,7 +364,7 @@ static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup3_spi_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -360,7 +378,7 @@ static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup4_i2c_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -374,7 +392,7 @@ static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup4_spi_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -407,7 +425,7 @@ static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart1_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -421,7 +439,7 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart2_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -435,7 +453,7 @@ static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup1_i2c_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -449,7 +467,7 @@ static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup1_spi_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -463,7 +481,7 @@ static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup2_i2c_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -477,7 +495,7 @@ static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup2_spi_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -491,7 +509,7 @@ static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup3_i2c_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -505,7 +523,7 @@ static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup3_spi_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -519,7 +537,7 @@ static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup4_i2c_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -533,7 +551,7 @@ static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup4_spi_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -547,7 +565,7 @@ static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_uart1_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -561,7 +579,7 @@ static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
.freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_uart2_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -582,7 +600,7 @@ static struct clk_rcg2 gp1_clk_src = {
.freq_tbl = ftbl_gp1_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp1_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_sleep_clk_gpll0_early_div,
.num_parents = 4,
.ops = &clk_rcg2_ops,
},
@@ -596,7 +614,7 @@ static struct clk_rcg2 gp2_clk_src = {
.freq_tbl = ftbl_gp1_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp2_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_sleep_clk_gpll0_early_div,
.num_parents = 4,
.ops = &clk_rcg2_ops,
},
@@ -610,7 +628,7 @@ static struct clk_rcg2 gp3_clk_src = {
.freq_tbl = ftbl_gp1_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp3_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_sleep_clk_gpll0_early_div,
.num_parents = 4,
.ops = &clk_rcg2_ops,
},
@@ -630,7 +648,7 @@ static struct clk_rcg2 hmss_gpll0_clk_src = {
.freq_tbl = ftbl_hmss_gpll0_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "hmss_gpll0_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -651,7 +669,7 @@ static struct clk_rcg2 hmss_gpll4_clk_src = {
.freq_tbl = ftbl_hmss_gpll4_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "hmss_gpll4_clk_src",
- .parent_names = gcc_parent_names_xo_gpll4,
+ .parent_data = gcc_parent_data_xo_gpll4,
.num_parents = 2,
.ops = &clk_rcg2_ops,
},
@@ -670,7 +688,7 @@ static struct clk_rcg2 hmss_rbcpr_clk_src = {
.freq_tbl = ftbl_hmss_rbcpr_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "hmss_rbcpr_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0,
+ .parent_data = gcc_parent_data_xo_gpll0,
.num_parents = 2,
.ops = &clk_rcg2_ops,
},
@@ -689,7 +707,7 @@ static struct clk_rcg2 pdm2_clk_src = {
.freq_tbl = ftbl_pdm2_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "pdm2_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -711,7 +729,7 @@ static struct clk_rcg2 qspi_ser_clk_src = {
.freq_tbl = ftbl_qspi_ser_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "qspi_ser_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
.num_parents = 6,
.ops = &clk_rcg2_ops,
},
@@ -737,7 +755,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.freq_tbl = ftbl_sdcc1_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc1_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll4_gpll0_early_div,
.num_parents = 4,
.ops = &clk_rcg2_ops,
},
@@ -759,7 +777,7 @@ static struct clk_rcg2 sdcc1_ice_core_clk_src = {
.freq_tbl = ftbl_sdcc1_ice_core_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc1_ice_core_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -785,7 +803,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.freq_tbl = ftbl_sdcc2_apps_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc2_apps_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div_gpll4,
.num_parents = 4,
.ops = &clk_rcg2_floor_ops,
},
@@ -808,7 +826,7 @@ static struct clk_rcg2 ufs_axi_clk_src = {
.freq_tbl = ftbl_ufs_axi_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "ufs_axi_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -829,7 +847,7 @@ static struct clk_rcg2 ufs_ice_core_clk_src = {
.freq_tbl = ftbl_ufs_ice_core_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "ufs_ice_core_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -843,7 +861,7 @@ static struct clk_rcg2 ufs_phy_aux_clk_src = {
.freq_tbl = ftbl_hmss_rbcpr_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "ufs_phy_aux_clk_src",
- .parent_names = gcc_parent_names_xo_sleep_clk,
+ .parent_data = gcc_parent_data_xo_sleep_clk,
.num_parents = 2,
.ops = &clk_rcg2_ops,
},
@@ -864,7 +882,7 @@ static struct clk_rcg2 ufs_unipro_core_clk_src = {
.freq_tbl = ftbl_ufs_unipro_core_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "ufs_unipro_core_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -885,7 +903,7 @@ static struct clk_rcg2 usb20_master_clk_src = {
.freq_tbl = ftbl_usb20_master_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb20_master_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -905,7 +923,7 @@ static struct clk_rcg2 usb20_mock_utmi_clk_src = {
.freq_tbl = ftbl_usb20_mock_utmi_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb20_mock_utmi_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -930,7 +948,7 @@ static struct clk_rcg2 usb30_master_clk_src = {
.freq_tbl = ftbl_usb30_master_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb30_master_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -951,7 +969,7 @@ static struct clk_rcg2 usb30_mock_utmi_clk_src = {
.freq_tbl = ftbl_usb30_mock_utmi_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb30_mock_utmi_clk_src",
- .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .parent_data = gcc_parent_data_xo_gpll0_gpll0_early_div,
.num_parents = 3,
.ops = &clk_rcg2_ops,
},
@@ -971,7 +989,7 @@ static struct clk_rcg2 usb3_phy_aux_clk_src = {
.freq_tbl = ftbl_usb3_phy_aux_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb3_phy_aux_clk_src",
- .parent_names = gcc_parent_names_xo_sleep_clk,
+ .parent_data = gcc_parent_data_xo_sleep_clk,
.num_parents = 2,
.ops = &clk_rcg2_ops,
},
@@ -985,8 +1003,8 @@ static struct clk_branch gcc_aggre2_ufs_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_aggre2_ufs_axi_clk",
- .parent_names = (const char *[]){
- "ufs_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &ufs_axi_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1002,8 +1020,8 @@ static struct clk_branch gcc_aggre2_usb3_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_aggre2_usb3_axi_clk",
- .parent_names = (const char *[]){
- "usb30_master_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &usb30_master_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1071,8 +1089,8 @@ static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup1_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup1_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_qup1_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1089,8 +1107,8 @@ static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup1_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup1_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_qup1_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1107,8 +1125,8 @@ static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup2_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup2_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_qup2_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1125,8 +1143,8 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup2_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup2_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_qup2_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1143,8 +1161,8 @@ static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup3_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup3_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_qup3_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1161,8 +1179,8 @@ static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup3_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup3_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_qup3_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1179,8 +1197,8 @@ static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup4_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup4_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_qup4_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1197,8 +1215,8 @@ static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup4_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup4_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_qup4_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1215,8 +1233,8 @@ static struct clk_branch gcc_blsp1_uart1_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart1_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart1_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_uart1_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1233,8 +1251,8 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart2_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart2_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp1_uart2_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1264,8 +1282,8 @@ static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup1_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup1_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_qup1_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1282,8 +1300,8 @@ static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup1_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup1_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_qup1_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1300,8 +1318,8 @@ static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup2_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup2_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_qup2_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1318,8 +1336,8 @@ static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup2_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup2_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_qup2_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1336,8 +1354,8 @@ static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup3_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup3_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_qup3_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1354,8 +1372,8 @@ static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup3_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup3_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_qup3_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1372,8 +1390,8 @@ static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup4_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup4_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_qup4_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1390,8 +1408,8 @@ static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup4_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup4_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_qup4_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1408,8 +1426,8 @@ static struct clk_branch gcc_blsp2_uart1_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_uart1_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_uart1_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_uart1_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1426,8 +1444,8 @@ static struct clk_branch gcc_blsp2_uart2_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_uart2_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_uart2_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &blsp2_uart2_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1457,8 +1475,8 @@ static struct clk_branch gcc_cfg_noc_usb2_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_cfg_noc_usb2_axi_clk",
- .parent_names = (const char *[]){
- "usb20_master_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &usb20_master_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1474,8 +1492,8 @@ static struct clk_branch gcc_cfg_noc_usb3_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_cfg_noc_usb3_axi_clk",
- .parent_names = (const char *[]){
- "usb30_master_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &usb30_master_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1503,8 +1521,8 @@ static struct clk_branch gcc_gp1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp1_clk",
- .parent_names = (const char *[]){
- "gp1_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gp1_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1521,8 +1539,8 @@ static struct clk_branch gcc_gp2_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp2_clk",
- .parent_names = (const char *[]){
- "gp2_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gp2_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1539,8 +1557,8 @@ static struct clk_branch gcc_gp3_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp3_clk",
- .parent_names = (const char *[]){
- "gp3_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gp3_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1584,8 +1602,8 @@ static struct clk_branch gcc_gpu_gpll0_clk = {
.enable_mask = BIT(4),
.hw.init = &(struct clk_init_data){
.name = "gcc_gpu_gpll0_clk",
- .parent_names = (const char *[]){
- "gpll0",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpll0.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1601,8 +1619,8 @@ static struct clk_branch gcc_gpu_gpll0_div_clk = {
.enable_mask = BIT(3),
.hw.init = &(struct clk_init_data){
.name = "gcc_gpu_gpll0_div_clk",
- .parent_names = (const char *[]){
- "gpll0_early_div",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpll0_early_div.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1632,8 +1650,8 @@ static struct clk_branch gcc_hmss_rbcpr_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_hmss_rbcpr_clk",
- .parent_names = (const char *[]){
- "hmss_rbcpr_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &hmss_rbcpr_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1650,8 +1668,8 @@ static struct clk_branch gcc_mmss_gpll0_clk = {
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "gcc_mmss_gpll0_clk",
- .parent_names = (const char *[]){
- "gpll0",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpll0.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1667,8 +1685,8 @@ static struct clk_branch gcc_mmss_gpll0_div_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mmss_gpll0_div_clk",
- .parent_names = (const char *[]){
- "gpll0_early_div",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpll0_early_div.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1767,8 +1785,8 @@ static struct clk_branch gcc_pdm2_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pdm2_clk",
- .parent_names = (const char *[]){
- "pdm2_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &pdm2_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1824,8 +1842,8 @@ static struct clk_branch gcc_qspi_ser_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_qspi_ser_clk",
- .parent_names = (const char *[]){
- "qspi_ser_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &qspi_ser_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1881,8 +1899,8 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_apps_clk",
- .parent_names = (const char *[]){
- "sdcc1_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &sdcc1_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1899,8 +1917,8 @@ static struct clk_branch gcc_sdcc1_ice_core_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_ice_core_clk",
- .parent_names = (const char *[]){
- "sdcc1_ice_core_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &sdcc1_ice_core_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1930,8 +1948,8 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc2_apps_clk",
- .parent_names = (const char *[]){
- "sdcc2_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &sdcc2_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1961,8 +1979,8 @@ static struct clk_branch gcc_ufs_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_axi_clk",
- .parent_names = (const char *[]){
- "ufs_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &ufs_axi_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1992,8 +2010,8 @@ static struct clk_branch gcc_ufs_ice_core_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_ice_core_clk",
- .parent_names = (const char *[]){
- "ufs_ice_core_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &ufs_ice_core_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2010,8 +2028,8 @@ static struct clk_branch gcc_ufs_phy_aux_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_aux_clk",
- .parent_names = (const char *[]){
- "ufs_phy_aux_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &ufs_phy_aux_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2067,8 +2085,8 @@ static struct clk_branch gcc_ufs_unipro_core_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_unipro_core_clk",
- .parent_names = (const char *[]){
- "ufs_unipro_core_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &ufs_unipro_core_clk_src.clkr.hw,
},
.flags = CLK_SET_RATE_PARENT,
.num_parents = 1,
@@ -2085,8 +2103,8 @@ static struct clk_branch gcc_usb20_master_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb20_master_clk",
- .parent_names = (const char *[]){
- "usb20_master_clk_src"
+ .parent_hws = (const struct clk_hw*[]) {
+ &usb20_master_clk_src.clkr.hw,
},
.flags = CLK_SET_RATE_PARENT,
.num_parents = 1,
@@ -2103,8 +2121,8 @@ static struct clk_branch gcc_usb20_mock_utmi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb20_mock_utmi_clk",
- .parent_names = (const char *[]){
- "usb20_mock_utmi_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &usb20_mock_utmi_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2134,8 +2152,8 @@ static struct clk_branch gcc_usb30_master_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb30_master_clk",
- .parent_names = (const char *[]){
- "usb30_master_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &usb30_master_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2152,8 +2170,8 @@ static struct clk_branch gcc_usb30_mock_utmi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb30_mock_utmi_clk",
- .parent_names = (const char *[]){
- "usb30_mock_utmi_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &usb30_mock_utmi_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2196,8 +2214,8 @@ static struct clk_branch gcc_usb3_phy_aux_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb3_phy_aux_clk",
- .parent_names = (const char *[]){
- "usb3_phy_aux_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &usb3_phy_aux_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
diff --git a/drivers/clk/qcom/gcc-sm6115.c b/drivers/clk/qcom/gcc-sm6115.c
new file mode 100644
index 000000000000..bc09736ece76
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sm6115.c
@@ -0,0 +1,3544 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-sm6115.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ P_BI_TCXO,
+ P_GPLL0_OUT_AUX2,
+ P_GPLL0_OUT_EARLY,
+ P_GPLL10_OUT_MAIN,
+ P_GPLL11_OUT_MAIN,
+ P_GPLL3_OUT_EARLY,
+ P_GPLL4_OUT_MAIN,
+ P_GPLL6_OUT_EARLY,
+ P_GPLL6_OUT_MAIN,
+ P_GPLL7_OUT_MAIN,
+ P_GPLL8_OUT_EARLY,
+ P_GPLL8_OUT_MAIN,
+ P_GPLL9_OUT_EARLY,
+ P_GPLL9_OUT_MAIN,
+ P_SLEEP_CLK,
+};
+
+static struct pll_vco default_vco[] = {
+ { 500000000, 1000000000, 2 },
+};
+
+static struct pll_vco gpll9_vco[] = {
+ { 500000000, 1250000000, 0 },
+};
+
+static struct pll_vco gpll10_vco[] = {
+ { 750000000, 1500000000, 1 },
+};
+
+static struct clk_alpha_pll gpll0 = {
+ .offset = 0x0,
+ .vco_table = default_vco,
+ .num_vco = ARRAY_SIZE(default_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll0_out_aux2[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll0_out_aux2 = {
+ .offset = 0x0,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll0_out_aux2,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_aux2),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0_out_aux2",
+ .parent_hws = (const struct clk_hw *[]){ &gpll0.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+/* listed as BRAMMO, but it doesn't really match */
+static const u8 clk_gpll9_regs[PLL_OFF_MAX_REGS] = {
+ [PLL_OFF_L_VAL] = 0x04,
+ [PLL_OFF_ALPHA_VAL] = 0x08,
+ [PLL_OFF_ALPHA_VAL_U] = 0x0c,
+ [PLL_OFF_TEST_CTL] = 0x10,
+ [PLL_OFF_TEST_CTL_U] = 0x14,
+ [PLL_OFF_USER_CTL] = 0x18,
+ [PLL_OFF_CONFIG_CTL] = 0x1C,
+ [PLL_OFF_STATUS] = 0x20,
+};
+
+static const struct clk_div_table post_div_table_gpll0_out_main[] = {
+ { 0x0, 1 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll0_out_main = {
+ .offset = 0x0,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll0_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_main),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0_out_main",
+ .parent_hws = (const struct clk_hw *[]){ &gpll0.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+/* 1152MHz configuration */
+static const struct alpha_pll_config gpll10_config = {
+ .l = 0x3c,
+ .vco_val = 0x1 << 20,
+ .vco_mask = GENMASK(21, 20),
+ .main_output_mask = BIT(0),
+ .config_ctl_val = 0x4001055b,
+};
+
+static struct clk_alpha_pll gpll10 = {
+ .offset = 0xa000,
+ .vco_table = gpll10_vco,
+ .num_vco = ARRAY_SIZE(gpll10_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll10",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll10_out_main[] = {
+ { 0x0, 1 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll10_out_main = {
+ .offset = 0xa000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll10_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll10_out_main),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll10_out_main",
+ .parent_hws = (const struct clk_hw *[]){ &gpll10.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+/* 600MHz configuration */
+static const struct alpha_pll_config gpll11_config = {
+ .l = 0x1F,
+ .alpha = 0x0,
+ .alpha_hi = 0x40,
+ .alpha_en_mask = BIT(24),
+ .vco_val = 0x2 << 20,
+ .vco_mask = GENMASK(21, 20),
+ .config_ctl_val = 0x4001055b,
+};
+
+static struct clk_alpha_pll gpll11 = {
+ .offset = 0xb000,
+ .vco_table = default_vco,
+ .num_vco = ARRAY_SIZE(default_vco),
+ .flags = SUPPORTS_DYNAMIC_UPDATE,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll11",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll11_out_main[] = {
+ { 0x0, 1 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll11_out_main = {
+ .offset = 0xb000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll11_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll11_out_main),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll11_out_main",
+ .parent_hws = (const struct clk_hw *[]){ &gpll11.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll3 = {
+ .offset = 0x3000,
+ .vco_table = default_vco,
+ .num_vco = ARRAY_SIZE(default_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll3",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gpll4 = {
+ .offset = 0x4000,
+ .vco_table = default_vco,
+ .num_vco = ARRAY_SIZE(default_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll4",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll4_out_main[] = {
+ { 0x0, 1 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll4_out_main = {
+ .offset = 0x4000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll4_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll4_out_main),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll4_out_main",
+ .parent_hws = (const struct clk_hw *[]){ &gpll4.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll6 = {
+ .offset = 0x6000,
+ .vco_table = default_vco,
+ .num_vco = ARRAY_SIZE(default_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(6),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll6",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll6_out_main[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll6_out_main = {
+ .offset = 0x6000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll6_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll6_out_main),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll6_out_main",
+ .parent_hws = (const struct clk_hw *[]){ &gpll6.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll7 = {
+ .offset = 0x7000,
+ .vco_table = default_vco,
+ .num_vco = ARRAY_SIZE(default_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll7",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll7_out_main[] = {
+ { 0x0, 1 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll7_out_main = {
+ .offset = 0x7000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll7_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll7_out_main),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll7_out_main",
+ .parent_hws = (const struct clk_hw *[]){ &gpll7.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+/* 800MHz configuration */
+static const struct alpha_pll_config gpll8_config = {
+ .l = 0x29,
+ .alpha = 0xAAAAAAAA,
+ .alpha_hi = 0xAA,
+ .alpha_en_mask = BIT(24),
+ .vco_val = 0x2 << 20,
+ .vco_mask = GENMASK(21, 20),
+ .main_output_mask = BIT(0),
+ .early_output_mask = BIT(3),
+ .post_div_val = 0x1 << 8,
+ .post_div_mask = GENMASK(11, 8),
+ .config_ctl_val = 0x4001055b,
+};
+
+static struct clk_alpha_pll gpll8 = {
+ .offset = 0x8000,
+ .vco_table = default_vco,
+ .num_vco = ARRAY_SIZE(default_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .flags = SUPPORTS_DYNAMIC_UPDATE,
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll8",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll8_out_main[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll8_out_main = {
+ .offset = 0x8000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll8_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll8_out_main),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll8_out_main",
+ .parent_hws = (const struct clk_hw *[]){ &gpll8.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+/* 1152MHz configuration */
+static const struct alpha_pll_config gpll9_config = {
+ .l = 0x3C,
+ .alpha = 0x0,
+ .post_div_val = 0x1 << 8,
+ .post_div_mask = GENMASK(9, 8),
+ .main_output_mask = BIT(0),
+ .config_ctl_val = 0x00004289,
+};
+
+static struct clk_alpha_pll gpll9 = {
+ .offset = 0x9000,
+ .vco_table = gpll9_vco,
+ .num_vco = ARRAY_SIZE(gpll9_vco),
+ .regs = clk_gpll9_regs,
+ .clkr = {
+ .enable_reg = 0x79000,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll9",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll9_out_main[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll9_out_main = {
+ .offset = 0x9000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll9_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll9_out_main),
+ .width = 2,
+ .regs = clk_gpll9_regs,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll9_out_main",
+ .parent_hws = (const struct clk_hw *[]){ &gpll9.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static const struct parent_map gcc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL0_OUT_AUX2, 2 },
+};
+
+static const struct clk_parent_data gcc_parents_0[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_aux2.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL0_OUT_AUX2, 2 },
+ { P_GPLL6_OUT_MAIN, 4 },
+};
+
+static const struct clk_parent_data gcc_parents_1[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_aux2.clkr.hw },
+ { .hw = &gpll6_out_main.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL0_OUT_AUX2, 2 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parents_2[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_aux2.clkr.hw },
+ { .fw_name = "sleep_clk" },
+};
+
+static const struct parent_map gcc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL9_OUT_EARLY, 2 },
+ { P_GPLL10_OUT_MAIN, 3 },
+ { P_GPLL9_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data gcc_parents_3[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll9.clkr.hw },
+ { .hw = &gpll10_out_main.clkr.hw },
+ { .hw = &gpll9_out_main.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL0_OUT_AUX2, 2 },
+ { P_GPLL4_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data gcc_parents_4[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_aux2.clkr.hw },
+ { .hw = &gpll4_out_main.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL8_OUT_EARLY, 2 },
+ { P_GPLL10_OUT_MAIN, 3 },
+ { P_GPLL8_OUT_MAIN, 4 },
+ { P_GPLL9_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data gcc_parents_5[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll8.clkr.hw },
+ { .hw = &gpll10_out_main.clkr.hw },
+ { .hw = &gpll8_out_main.clkr.hw },
+ { .hw = &gpll9_out_main.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL8_OUT_EARLY, 2 },
+ { P_GPLL10_OUT_MAIN, 3 },
+ { P_GPLL6_OUT_MAIN, 4 },
+ { P_GPLL9_OUT_MAIN, 5 },
+ { P_GPLL3_OUT_EARLY, 6 },
+};
+
+static const struct clk_parent_data gcc_parents_6[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll8.clkr.hw },
+ { .hw = &gpll10_out_main.clkr.hw },
+ { .hw = &gpll6_out_main.clkr.hw },
+ { .hw = &gpll9_out_main.clkr.hw },
+ { .hw = &gpll3.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_7[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL0_OUT_AUX2, 2 },
+ { P_GPLL10_OUT_MAIN, 3 },
+ { P_GPLL4_OUT_MAIN, 5 },
+ { P_GPLL3_OUT_EARLY, 6 },
+};
+
+static const struct clk_parent_data gcc_parents_7[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_aux2.clkr.hw },
+ { .hw = &gpll10_out_main.clkr.hw },
+ { .hw = &gpll4_out_main.clkr.hw },
+ { .hw = &gpll3.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_8[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL8_OUT_EARLY, 2 },
+ { P_GPLL10_OUT_MAIN, 3 },
+ { P_GPLL8_OUT_MAIN, 4 },
+ { P_GPLL9_OUT_MAIN, 5 },
+ { P_GPLL3_OUT_EARLY, 6 },
+};
+
+static const struct clk_parent_data gcc_parents_8[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll8.clkr.hw },
+ { .hw = &gpll10_out_main.clkr.hw },
+ { .hw = &gpll8_out_main.clkr.hw },
+ { .hw = &gpll9_out_main.clkr.hw },
+ { .hw = &gpll3.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_9[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL0_OUT_AUX2, 2 },
+ { P_GPLL10_OUT_MAIN, 3 },
+ { P_GPLL8_OUT_MAIN, 4 },
+ { P_GPLL9_OUT_MAIN, 5 },
+ { P_GPLL3_OUT_EARLY, 6 },
+};
+
+static const struct clk_parent_data gcc_parents_9[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_aux2.clkr.hw },
+ { .hw = &gpll10_out_main.clkr.hw },
+ { .hw = &gpll8_out_main.clkr.hw },
+ { .hw = &gpll9_out_main.clkr.hw },
+ { .hw = &gpll3.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_10[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL8_OUT_EARLY, 2 },
+ { P_GPLL10_OUT_MAIN, 3 },
+ { P_GPLL6_OUT_EARLY, 4 },
+ { P_GPLL9_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data gcc_parents_10[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll8.clkr.hw },
+ { .hw = &gpll10_out_main.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll9_out_main.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_11[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EARLY, 1 },
+ { P_GPLL0_OUT_AUX2, 2 },
+ { P_GPLL7_OUT_MAIN, 3 },
+ { P_GPLL4_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data gcc_parents_11[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_aux2.clkr.hw },
+ { .hw = &gpll7_out_main.clkr.hw },
+ { .hw = &gpll4_out_main.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_12[] = {
+ { P_BI_TCXO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parents_12[] = {
+ { .fw_name = "bi_tcxo" },
+ { .fw_name = "sleep_clk" },
+};
+
+static const struct parent_map gcc_parent_map_13[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL11_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data gcc_parents_13[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll11_out_main.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_axi_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0),
+ F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0),
+ F(300000000, P_GPLL0_OUT_AUX2, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_axi_clk_src = {
+ .cmd_rcgr = 0x5802c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_7,
+ .freq_tbl = ftbl_gcc_camss_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_axi_clk_src",
+ .parent_data = gcc_parents_7,
+ .num_parents = ARRAY_SIZE(gcc_parents_7),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_cci_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_cci_clk_src = {
+ .cmd_rcgr = 0x56000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_9,
+ .freq_tbl = ftbl_gcc_camss_cci_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_cci_clk_src",
+ .parent_data = gcc_parents_9,
+ .num_parents = ARRAY_SIZE(gcc_parents_9),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_csi0phytimer_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0),
+ F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0),
+ F(268800000, P_GPLL4_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_csi0phytimer_clk_src = {
+ .cmd_rcgr = 0x59000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_csi0phytimer_clk_src",
+ .parent_data = gcc_parents_4,
+ .num_parents = ARRAY_SIZE(gcc_parents_4),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_csi1phytimer_clk_src = {
+ .cmd_rcgr = 0x5901c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_csi1phytimer_clk_src",
+ .parent_data = gcc_parents_4,
+ .num_parents = ARRAY_SIZE(gcc_parents_4),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_csi2phytimer_clk_src = {
+ .cmd_rcgr = 0x59038,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_csi2phytimer_clk_src",
+ .parent_data = gcc_parents_4,
+ .num_parents = ARRAY_SIZE(gcc_parents_4),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_mclk0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(24000000, P_GPLL9_OUT_MAIN, 1, 1, 24),
+ F(64000000, P_GPLL9_OUT_MAIN, 1, 1, 9),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_mclk0_clk_src = {
+ .cmd_rcgr = 0x51000,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_camss_mclk0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_mclk0_clk_src",
+ .parent_data = gcc_parents_3,
+ .num_parents = ARRAY_SIZE(gcc_parents_3),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_mclk1_clk_src = {
+ .cmd_rcgr = 0x5101c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_camss_mclk0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_mclk1_clk_src",
+ .parent_data = gcc_parents_3,
+ .num_parents = ARRAY_SIZE(gcc_parents_3),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_mclk2_clk_src = {
+ .cmd_rcgr = 0x51038,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_camss_mclk0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_mclk2_clk_src",
+ .parent_data = gcc_parents_3,
+ .num_parents = ARRAY_SIZE(gcc_parents_3),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_mclk3_clk_src = {
+ .cmd_rcgr = 0x51054,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_camss_mclk0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_mclk3_clk_src",
+ .parent_data = gcc_parents_3,
+ .num_parents = ARRAY_SIZE(gcc_parents_3),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_ope_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(171428571, P_GPLL0_OUT_EARLY, 3.5, 0, 0),
+ F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_ope_ahb_clk_src = {
+ .cmd_rcgr = 0x55024,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_8,
+ .freq_tbl = ftbl_gcc_camss_ope_ahb_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_ope_ahb_clk_src",
+ .parent_data = gcc_parents_8,
+ .num_parents = ARRAY_SIZE(gcc_parents_8),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_ope_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_GPLL8_OUT_MAIN, 2, 0, 0),
+ F(266600000, P_GPLL8_OUT_MAIN, 1, 0, 0),
+ F(465000000, P_GPLL8_OUT_MAIN, 1, 0, 0),
+ F(576000000, P_GPLL9_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_ope_clk_src = {
+ .cmd_rcgr = 0x55004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_8,
+ .freq_tbl = ftbl_gcc_camss_ope_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_ope_clk_src",
+ .parent_data = gcc_parents_8,
+ .num_parents = ARRAY_SIZE(gcc_parents_8),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_tfe_0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(128000000, P_GPLL10_OUT_MAIN, 9, 0, 0),
+ F(135529412, P_GPLL10_OUT_MAIN, 8.5, 0, 0),
+ F(144000000, P_GPLL10_OUT_MAIN, 8, 0, 0),
+ F(153600000, P_GPLL10_OUT_MAIN, 7.5, 0, 0),
+ F(164571429, P_GPLL10_OUT_MAIN, 7, 0, 0),
+ F(177230769, P_GPLL10_OUT_MAIN, 6.5, 0, 0),
+ F(192000000, P_GPLL10_OUT_MAIN, 6, 0, 0),
+ F(209454545, P_GPLL10_OUT_MAIN, 5.5, 0, 0),
+ F(230400000, P_GPLL10_OUT_MAIN, 5, 0, 0),
+ F(256000000, P_GPLL10_OUT_MAIN, 4.5, 0, 0),
+ F(288000000, P_GPLL10_OUT_MAIN, 4, 0, 0),
+ F(329142857, P_GPLL10_OUT_MAIN, 3.5, 0, 0),
+ F(384000000, P_GPLL10_OUT_MAIN, 3, 0, 0),
+ F(460800000, P_GPLL10_OUT_MAIN, 2.5, 0, 0),
+ F(576000000, P_GPLL10_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_tfe_0_clk_src = {
+ .cmd_rcgr = 0x52004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_camss_tfe_0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_0_clk_src",
+ .parent_data = gcc_parents_5,
+ .num_parents = ARRAY_SIZE(gcc_parents_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_tfe_0_csid_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(120000000, P_GPLL0_OUT_EARLY, 5, 0, 0),
+ F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0),
+ F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0),
+ F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0),
+ F(426400000, P_GPLL3_OUT_EARLY, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_tfe_0_csid_clk_src = {
+ .cmd_rcgr = 0x52094,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_6,
+ .freq_tbl = ftbl_gcc_camss_tfe_0_csid_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_0_csid_clk_src",
+ .parent_data = gcc_parents_6,
+ .num_parents = ARRAY_SIZE(gcc_parents_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_tfe_1_clk_src = {
+ .cmd_rcgr = 0x52024,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_camss_tfe_0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_1_clk_src",
+ .parent_data = gcc_parents_5,
+ .num_parents = ARRAY_SIZE(gcc_parents_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_tfe_1_csid_clk_src = {
+ .cmd_rcgr = 0x520b4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_6,
+ .freq_tbl = ftbl_gcc_camss_tfe_0_csid_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_1_csid_clk_src",
+ .parent_data = gcc_parents_6,
+ .num_parents = ARRAY_SIZE(gcc_parents_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_tfe_2_clk_src = {
+ .cmd_rcgr = 0x52044,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_camss_tfe_0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_2_clk_src",
+ .parent_data = gcc_parents_5,
+ .num_parents = ARRAY_SIZE(gcc_parents_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_camss_tfe_2_csid_clk_src = {
+ .cmd_rcgr = 0x520d4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_6,
+ .freq_tbl = ftbl_gcc_camss_tfe_0_csid_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_2_csid_clk_src",
+ .parent_data = gcc_parents_6,
+ .num_parents = ARRAY_SIZE(gcc_parents_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_tfe_cphy_rx_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0),
+ F(341333333, P_GPLL6_OUT_EARLY, 1, 4, 9),
+ F(384000000, P_GPLL6_OUT_EARLY, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_tfe_cphy_rx_clk_src = {
+ .cmd_rcgr = 0x52064,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_10,
+ .freq_tbl = ftbl_gcc_camss_tfe_cphy_rx_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_cphy_rx_clk_src",
+ .parent_data = gcc_parents_10,
+ .num_parents = ARRAY_SIZE(gcc_parents_10),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_top_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(40000000, P_GPLL0_OUT_AUX2, 7.5, 0, 0),
+ F(80000000, P_GPLL0_OUT_EARLY, 7.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_camss_top_ahb_clk_src = {
+ .cmd_rcgr = 0x58010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_7,
+ .freq_tbl = ftbl_gcc_camss_top_ahb_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_top_ahb_clk_src",
+ .parent_data = gcc_parents_7,
+ .num_parents = ARRAY_SIZE(gcc_parents_7),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
+ F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0),
+ F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0),
+ F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0),
+ F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_gp1_clk_src = {
+ .cmd_rcgr = 0x4d004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk_src",
+ .parent_data = gcc_parents_2,
+ .num_parents = ARRAY_SIZE(gcc_parents_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp2_clk_src = {
+ .cmd_rcgr = 0x4e004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk_src",
+ .parent_data = gcc_parents_2,
+ .num_parents = ARRAY_SIZE(gcc_parents_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp3_clk_src = {
+ .cmd_rcgr = 0x4f004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk_src",
+ .parent_data = gcc_parents_2,
+ .num_parents = ARRAY_SIZE(gcc_parents_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(60000000, P_GPLL0_OUT_AUX2, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pdm2_clk_src = {
+ .cmd_rcgr = 0x20010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pdm2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk_src",
+ .parent_data = gcc_parents_0,
+ .num_parents = ARRAY_SIZE(gcc_parents_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
+ F(7372800, P_GPLL0_OUT_AUX2, 1, 384, 15625),
+ F(14745600, P_GPLL0_OUT_AUX2, 1, 768, 15625),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(29491200, P_GPLL0_OUT_AUX2, 1, 1536, 15625),
+ F(32000000, P_GPLL0_OUT_AUX2, 1, 8, 75),
+ F(48000000, P_GPLL0_OUT_AUX2, 1, 4, 25),
+ F(64000000, P_GPLL0_OUT_AUX2, 1, 16, 75),
+ F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0),
+ F(80000000, P_GPLL0_OUT_AUX2, 1, 4, 15),
+ F(96000000, P_GPLL0_OUT_AUX2, 1, 8, 25),
+ F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0),
+ F(102400000, P_GPLL0_OUT_AUX2, 1, 128, 375),
+ F(112000000, P_GPLL0_OUT_AUX2, 1, 28, 75),
+ F(117964800, P_GPLL0_OUT_AUX2, 1, 6144, 15625),
+ F(120000000, P_GPLL0_OUT_AUX2, 2.5, 0, 0),
+ F(128000000, P_GPLL6_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s0_clk_src",
+ .parent_data = gcc_parents_1,
+ .num_parents = ARRAY_SIZE(gcc_parents_1),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
+ .cmd_rcgr = 0x1f148,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s1_clk_src",
+ .parent_data = gcc_parents_1,
+ .num_parents = ARRAY_SIZE(gcc_parents_1),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
+ .cmd_rcgr = 0x1f278,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s2_clk_src",
+ .parent_data = gcc_parents_1,
+ .num_parents = ARRAY_SIZE(gcc_parents_1),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
+ .cmd_rcgr = 0x1f3a8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s3_clk_src",
+ .parent_data = gcc_parents_1,
+ .num_parents = ARRAY_SIZE(gcc_parents_1),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
+ .cmd_rcgr = 0x1f4d8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s4_clk_src",
+ .parent_data = gcc_parents_1,
+ .num_parents = ARRAY_SIZE(gcc_parents_1),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
+ .cmd_rcgr = 0x1f608,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s5_clk_src",
+ .parent_data = gcc_parents_1,
+ .num_parents = ARRAY_SIZE(gcc_parents_1),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
+ .cmd_rcgr = 0x1f738,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
+ F(144000, P_BI_TCXO, 16, 3, 25),
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(20000000, P_GPLL0_OUT_AUX2, 5, 1, 3),
+ F(25000000, P_GPLL0_OUT_AUX2, 6, 1, 2),
+ F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0),
+ F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0),
+ F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0),
+ F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x38028,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk_src",
+ .parent_data = gcc_parents_1,
+ .num_parents = ARRAY_SIZE(gcc_parents_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = {
+ F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0),
+ F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0),
+ F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0),
+ F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0),
+ F(300000000, P_GPLL0_OUT_AUX2, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x38010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ice_core_clk_src",
+ .parent_data = gcc_parents_0,
+ .num_parents = ARRAY_SIZE(gcc_parents_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0),
+ F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0),
+ F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0),
+ F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x1e00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_11,
+ .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk_src",
+ .parent_data = gcc_parents_11,
+ .num_parents = ARRAY_SIZE(gcc_parents_11),
+ .ops = &clk_rcg2_ops,
+ .flags = CLK_OPS_PARENT_ENABLE,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = {
+ F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0),
+ F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0),
+ F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0),
+ F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0),
+ F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = {
+ .cmd_rcgr = 0x45020,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_axi_clk_src",
+ .parent_data = gcc_parents_0,
+ .num_parents = ARRAY_SIZE(gcc_parents_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = {
+ F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0),
+ F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0),
+ F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0),
+ F(300000000, P_GPLL0_OUT_AUX2, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = {
+ .cmd_rcgr = 0x45048,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ice_core_clk_src",
+ .parent_data = gcc_parents_0,
+ .num_parents = ARRAY_SIZE(gcc_parents_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_phy_aux_clk_src[] = {
+ F(9600000, P_BI_TCXO, 2, 0, 0),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = {
+ .cmd_rcgr = 0x4507c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_phy_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_phy_aux_clk_src",
+ .parent_data = gcc_parents_0,
+ .num_parents = ARRAY_SIZE(gcc_parents_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = {
+ F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0),
+ F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0),
+ F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = {
+ .cmd_rcgr = 0x45060,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_unipro_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_unipro_core_clk_src",
+ .parent_data = gcc_parents_0,
+ .num_parents = ARRAY_SIZE(gcc_parents_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = {
+ F(66666667, P_GPLL0_OUT_AUX2, 4.5, 0, 0),
+ F(133333333, P_GPLL0_OUT_EARLY, 4.5, 0, 0),
+ F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0),
+ F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_prim_master_clk_src = {
+ .cmd_rcgr = 0x1a01c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_master_clk_src",
+ .parent_data = gcc_parents_0,
+ .num_parents = ARRAY_SIZE(gcc_parents_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x1a034,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_mock_utmi_clk_src",
+ .parent_data = gcc_parents_0,
+ .num_parents = ARRAY_SIZE(gcc_parents_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = {
+ .reg = 0x1a04c,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
+ .cmd_rcgr = 0x1a060,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_12,
+ .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_aux_clk_src",
+ .parent_data = gcc_parents_12,
+ .num_parents = ARRAY_SIZE(gcc_parents_12),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_video_venus_clk_src[] = {
+ F(133333333, P_GPLL11_OUT_MAIN, 4.5, 0, 0),
+ F(240000000, P_GPLL11_OUT_MAIN, 2.5, 0, 0),
+ F(300000000, P_GPLL11_OUT_MAIN, 2, 0, 0),
+ F(384000000, P_GPLL11_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_video_venus_clk_src = {
+ .cmd_rcgr = 0x58060,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_13,
+ .freq_tbl = ftbl_gcc_video_venus_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_video_venus_clk_src",
+ .parent_data = gcc_parents_13,
+ .num_parents = ARRAY_SIZE(gcc_parents_13),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_ahb2phy_csi_clk = {
+ .halt_reg = 0x1d004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1d004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ahb2phy_csi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ahb2phy_usb_clk = {
+ .halt_reg = 0x1d008,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1d008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ahb2phy_usb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_gpu_axi_clk = {
+ .halt_reg = 0x71154,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x71154,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x71154,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_gpu_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x23004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x23004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cam_throttle_nrt_clk = {
+ .halt_reg = 0x17070,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x17070,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(27),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cam_throttle_nrt_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cam_throttle_rt_clk = {
+ .halt_reg = 0x1706c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x1706c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(26),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cam_throttle_rt_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_ahb_clk = {
+ .halt_reg = 0x17008,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x17008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_xo_clk = {
+ .halt_reg = 0x17028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_xo_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_axi_clk = {
+ .halt_reg = 0x58044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58044,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_camnoc_atb_clk = {
+ .halt_reg = 0x5804c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x5804c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x5804c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_camnoc_atb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_camnoc_nts_xo_clk = {
+ .halt_reg = 0x58050,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x58050,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x58050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_camnoc_nts_xo_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_cci_0_clk = {
+ .halt_reg = 0x56018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x56018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_cci_0_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_cci_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_cphy_0_clk = {
+ .halt_reg = 0x52088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x52088,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_cphy_0_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_cphy_1_clk = {
+ .halt_reg = 0x5208c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5208c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_cphy_1_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_cphy_2_clk = {
+ .halt_reg = 0x52090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x52090,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_cphy_2_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_csi0phytimer_clk = {
+ .halt_reg = 0x59018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_csi0phytimer_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_csi0phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_csi1phytimer_clk = {
+ .halt_reg = 0x59034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_csi1phytimer_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_csi1phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_csi2phytimer_clk = {
+ .halt_reg = 0x59050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x59050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_csi2phytimer_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_csi2phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_mclk0_clk = {
+ .halt_reg = 0x51018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x51018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_mclk0_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_mclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_mclk1_clk = {
+ .halt_reg = 0x51034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x51034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_mclk1_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_mclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_mclk2_clk = {
+ .halt_reg = 0x51050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x51050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_mclk2_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_mclk2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_mclk3_clk = {
+ .halt_reg = 0x5106c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5106c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_mclk3_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_mclk3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_nrt_axi_clk = {
+ .halt_reg = 0x58054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58054,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_nrt_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_ope_ahb_clk = {
+ .halt_reg = 0x5503c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5503c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_ope_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_ope_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_ope_clk = {
+ .halt_reg = 0x5501c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5501c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_ope_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_ope_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_rt_axi_clk = {
+ .halt_reg = 0x5805c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5805c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_rt_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_0_clk = {
+ .halt_reg = 0x5201c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5201c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_0_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_0_cphy_rx_clk = {
+ .halt_reg = 0x5207c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5207c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_0_cphy_rx_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_0_csid_clk = {
+ .halt_reg = 0x520ac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x520ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_0_csid_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_0_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_1_clk = {
+ .halt_reg = 0x5203c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5203c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_1_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_1_cphy_rx_clk = {
+ .halt_reg = 0x52080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x52080,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_1_cphy_rx_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_1_csid_clk = {
+ .halt_reg = 0x520cc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x520cc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_1_csid_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_1_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_2_clk = {
+ .halt_reg = 0x5205c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5205c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_2_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_2_cphy_rx_clk = {
+ .halt_reg = 0x52084,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x52084,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_2_cphy_rx_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_tfe_2_csid_clk = {
+ .halt_reg = 0x520ec,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x520ec,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_tfe_2_csid_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_tfe_2_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camss_top_ahb_clk = {
+ .halt_reg = 0x58028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x58028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camss_top_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_camss_top_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = {
+ .halt_reg = 0x1a084,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1a084,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1a084,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cpuss_gnoc_clk = {
+ .halt_reg = 0x2b004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2b004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(22),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cpuss_gnoc_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_ahb_clk = {
+ .halt_reg = 0x1700c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1700c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1700c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap_div gcc_disp_gpll0_clk_src = {
+ .reg = 0x17058,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gcc_disp_gpll0_clk_src",
+ .parent_hws = (const struct clk_hw *[]){ &gpll0.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ops,
+ },
+};
+
+static struct clk_branch gcc_disp_gpll0_div_clk_src = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(20),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_gpll0_div_clk_src",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_disp_gpll0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_hf_axi_clk = {
+ .halt_reg = 0x17020,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_hf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_throttle_core_clk = {
+ .halt_reg = 0x17064,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x17064,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(5),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_throttle_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_xo_clk = {
+ .halt_reg = 0x1702c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1702c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_xo_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x4d000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_gp1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x4e000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4e000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_gp2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x4f000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4f000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_gp3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_cfg_ahb_clk = {
+ .halt_reg = 0x36004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x36004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x36004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_cfg_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_clk_src = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_clk_src",
+ .parent_hws = (const struct clk_hw *[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_div_clk_src = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(16),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_div_clk_src",
+ .parent_hws = (const struct clk_hw *[]){
+ &gpll0_out_aux2.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_iref_clk = {
+ .halt_reg = 0x36100,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x36100,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_iref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_memnoc_gfx_clk = {
+ .halt_reg = 0x3600c,
+ .halt_check = BRANCH_VOTED,
+ .hwcg_reg = 0x3600c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_memnoc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = {
+ .halt_reg = 0x36018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x36018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_snoc_dvm_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_throttle_core_clk = {
+ .halt_reg = 0x36048,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x36048,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(31),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_throttle_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x2000c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2000c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_pdm2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x20004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x20004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x20004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_xo4_clk = {
+ .halt_reg = 0x20008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_xo4_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+ .halt_reg = 0x21004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x21004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_prng_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = {
+ .halt_reg = 0x17014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x17014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_camera_nrt_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_camera_rt_ahb_clk = {
+ .halt_reg = 0x17060,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x17060,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_camera_rt_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_disp_ahb_clk = {
+ .halt_reg = 0x17018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x17018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_disp_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_gpu_cfg_ahb_clk = {
+ .halt_reg = 0x36040,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x36040,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_gpu_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = {
+ .halt_reg = 0x17010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x17010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(25),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_video_vcodec_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = {
+ .halt_reg = 0x1f014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_clk = {
+ .halt_reg = 0x1f00c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s0_clk = {
+ .halt_reg = 0x1f144,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s0_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_qupv3_wrap0_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s1_clk = {
+ .halt_reg = 0x1f274,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s1_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_qupv3_wrap0_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s2_clk = {
+ .halt_reg = 0x1f3a4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s2_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_qupv3_wrap0_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s3_clk = {
+ .halt_reg = 0x1f4d4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s3_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_qupv3_wrap0_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s4_clk = {
+ .halt_reg = 0x1f604,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s4_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_qupv3_wrap0_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s5_clk = {
+ .halt_reg = 0x1f734,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s5_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_qupv3_wrap0_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = {
+ .halt_reg = 0x1f004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x1f004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(6),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_0_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = {
+ .halt_reg = 0x1f008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x1f008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7900c,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_0_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x38008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x38008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x38004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x38004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_sdcc1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT /* | CLK_ENABLE_HAND_OFF */,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x3800c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3800c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3800c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_sdcc1_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x1e008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1e008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x1e004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1e004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_sdcc2_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = {
+ .halt_reg = 0x2b06c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2b06c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_cpuss_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_ufs_phy_axi_clk = {
+ .halt_reg = 0x45098,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x45098,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_ufs_phy_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_usb3_prim_axi_clk = {
+ .halt_reg = 0x1a080,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1a080,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1a080,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_clkref_clk = {
+ .halt_reg = 0x8c000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8c000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ahb_clk = {
+ .halt_reg = 0x45014,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x45014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x45014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_axi_clk = {
+ .halt_reg = 0x45010,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x45010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x45010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ice_core_clk = {
+ .halt_reg = 0x45044,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x45044,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x45044,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ice_core_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_ufs_phy_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_phy_aux_clk = {
+ .halt_reg = 0x45078,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x45078,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x45078,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_phy_aux_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_ufs_phy_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = {
+ .halt_reg = 0x4501c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x4501c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_rx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = {
+ .halt_reg = 0x45018,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x45018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_tx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_unipro_core_clk = {
+ .halt_reg = 0x45040,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x45040,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x45040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_unipro_core_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_ufs_phy_unipro_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_master_clk = {
+ .halt_reg = 0x1a010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_master_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_mock_utmi_clk = {
+ .halt_reg = 0x1a018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_mock_utmi_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_sleep_clk = {
+ .halt_reg = 0x1a014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_clkref_clk = {
+ .halt_reg = 0x9f000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9f000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = {
+ .halt_reg = 0x1a054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a054,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_com_aux_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_usb3_prim_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_pipe_clk = {
+ .halt_reg = 0x1a058,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x1a058,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1a058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_pipe_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_vcodec0_axi_clk = {
+ .halt_reg = 0x6e008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6e008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_vcodec0_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_venus_ahb_clk = {
+ .halt_reg = 0x6e010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6e010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_venus_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_venus_ctl_axi_clk = {
+ .halt_reg = 0x6e004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6e004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_venus_ctl_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_ahb_clk = {
+ .halt_reg = 0x17004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_axi0_clk = {
+ .halt_reg = 0x1701c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1701c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1701c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_axi0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_throttle_core_clk = {
+ .halt_reg = 0x17068,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x17068,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x79004,
+ .enable_mask = BIT(28),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_throttle_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_vcodec0_sys_clk = {
+ .halt_reg = 0x580a4,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x580a4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x580a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_vcodec0_sys_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_video_venus_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_venus_ctl_clk = {
+ .halt_reg = 0x5808c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5808c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_venus_ctl_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_video_venus_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_xo_clk = {
+ .halt_reg = 0x17024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_xo_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc gcc_camss_top_gdsc = {
+ .gdscr = 0x58004,
+ .pd = {
+ .name = "gcc_camss_top",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc gcc_ufs_phy_gdsc = {
+ .gdscr = 0x45004,
+ .pd = {
+ .name = "gcc_ufs_phy",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc gcc_usb30_prim_gdsc = {
+ .gdscr = 0x1a004,
+ .pd = {
+ .name = "gcc_usb30_prim",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc gcc_vcodec0_gdsc = {
+ .gdscr = 0x58098,
+ .pd = {
+ .name = "gcc_vcodec0",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc gcc_venus_gdsc = {
+ .gdscr = 0x5807c,
+ .pd = {
+ .name = "gcc_venus",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc hlos1_vote_turing_mmu_tbu1_gdsc = {
+ .gdscr = 0x7d060,
+ .pd = {
+ .name = "hlos1_vote_turing_mmu_tbu1",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc hlos1_vote_turing_mmu_tbu0_gdsc = {
+ .gdscr = 0x7d060,
+ .pd = {
+ .name = "hlos1_vote_turing_mmu_tbu0",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc hlos1_vote_mm_snoc_mmu_tbu_rt_gdsc = {
+ .gdscr = 0x7d074,
+ .pd = {
+ .name = "hlos1_vote_mm_snoc_mmu_tbu_rt",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc = {
+ .gdscr = 0x7d078,
+ .pd = {
+ .name = "hlos1_vote_mm_snoc_mmu_tbu_nrt",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct clk_regmap *gcc_sm6115_clocks[] = {
+ [GCC_AHB2PHY_CSI_CLK] = &gcc_ahb2phy_csi_clk.clkr,
+ [GCC_AHB2PHY_USB_CLK] = &gcc_ahb2phy_usb_clk.clkr,
+ [GCC_BIMC_GPU_AXI_CLK] = &gcc_bimc_gpu_axi_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CAM_THROTTLE_NRT_CLK] = &gcc_cam_throttle_nrt_clk.clkr,
+ [GCC_CAM_THROTTLE_RT_CLK] = &gcc_cam_throttle_rt_clk.clkr,
+ [GCC_CAMERA_AHB_CLK] = &gcc_camera_ahb_clk.clkr,
+ [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr,
+ [GCC_CAMSS_AXI_CLK] = &gcc_camss_axi_clk.clkr,
+ [GCC_CAMSS_AXI_CLK_SRC] = &gcc_camss_axi_clk_src.clkr,
+ [GCC_CAMSS_CAMNOC_ATB_CLK] = &gcc_camss_camnoc_atb_clk.clkr,
+ [GCC_CAMSS_CAMNOC_NTS_XO_CLK] = &gcc_camss_camnoc_nts_xo_clk.clkr,
+ [GCC_CAMSS_CCI_0_CLK] = &gcc_camss_cci_0_clk.clkr,
+ [GCC_CAMSS_CCI_CLK_SRC] = &gcc_camss_cci_clk_src.clkr,
+ [GCC_CAMSS_CPHY_0_CLK] = &gcc_camss_cphy_0_clk.clkr,
+ [GCC_CAMSS_CPHY_1_CLK] = &gcc_camss_cphy_1_clk.clkr,
+ [GCC_CAMSS_CPHY_2_CLK] = &gcc_camss_cphy_2_clk.clkr,
+ [GCC_CAMSS_CSI0PHYTIMER_CLK] = &gcc_camss_csi0phytimer_clk.clkr,
+ [GCC_CAMSS_CSI0PHYTIMER_CLK_SRC] = &gcc_camss_csi0phytimer_clk_src.clkr,
+ [GCC_CAMSS_CSI1PHYTIMER_CLK] = &gcc_camss_csi1phytimer_clk.clkr,
+ [GCC_CAMSS_CSI1PHYTIMER_CLK_SRC] = &gcc_camss_csi1phytimer_clk_src.clkr,
+ [GCC_CAMSS_CSI2PHYTIMER_CLK] = &gcc_camss_csi2phytimer_clk.clkr,
+ [GCC_CAMSS_CSI2PHYTIMER_CLK_SRC] = &gcc_camss_csi2phytimer_clk_src.clkr,
+ [GCC_CAMSS_MCLK0_CLK] = &gcc_camss_mclk0_clk.clkr,
+ [GCC_CAMSS_MCLK0_CLK_SRC] = &gcc_camss_mclk0_clk_src.clkr,
+ [GCC_CAMSS_MCLK1_CLK] = &gcc_camss_mclk1_clk.clkr,
+ [GCC_CAMSS_MCLK1_CLK_SRC] = &gcc_camss_mclk1_clk_src.clkr,
+ [GCC_CAMSS_MCLK2_CLK] = &gcc_camss_mclk2_clk.clkr,
+ [GCC_CAMSS_MCLK2_CLK_SRC] = &gcc_camss_mclk2_clk_src.clkr,
+ [GCC_CAMSS_MCLK3_CLK] = &gcc_camss_mclk3_clk.clkr,
+ [GCC_CAMSS_MCLK3_CLK_SRC] = &gcc_camss_mclk3_clk_src.clkr,
+ [GCC_CAMSS_NRT_AXI_CLK] = &gcc_camss_nrt_axi_clk.clkr,
+ [GCC_CAMSS_OPE_AHB_CLK] = &gcc_camss_ope_ahb_clk.clkr,
+ [GCC_CAMSS_OPE_AHB_CLK_SRC] = &gcc_camss_ope_ahb_clk_src.clkr,
+ [GCC_CAMSS_OPE_CLK] = &gcc_camss_ope_clk.clkr,
+ [GCC_CAMSS_OPE_CLK_SRC] = &gcc_camss_ope_clk_src.clkr,
+ [GCC_CAMSS_RT_AXI_CLK] = &gcc_camss_rt_axi_clk.clkr,
+ [GCC_CAMSS_TFE_0_CLK] = &gcc_camss_tfe_0_clk.clkr,
+ [GCC_CAMSS_TFE_0_CLK_SRC] = &gcc_camss_tfe_0_clk_src.clkr,
+ [GCC_CAMSS_TFE_0_CPHY_RX_CLK] = &gcc_camss_tfe_0_cphy_rx_clk.clkr,
+ [GCC_CAMSS_TFE_0_CSID_CLK] = &gcc_camss_tfe_0_csid_clk.clkr,
+ [GCC_CAMSS_TFE_0_CSID_CLK_SRC] = &gcc_camss_tfe_0_csid_clk_src.clkr,
+ [GCC_CAMSS_TFE_1_CLK] = &gcc_camss_tfe_1_clk.clkr,
+ [GCC_CAMSS_TFE_1_CLK_SRC] = &gcc_camss_tfe_1_clk_src.clkr,
+ [GCC_CAMSS_TFE_1_CPHY_RX_CLK] = &gcc_camss_tfe_1_cphy_rx_clk.clkr,
+ [GCC_CAMSS_TFE_1_CSID_CLK] = &gcc_camss_tfe_1_csid_clk.clkr,
+ [GCC_CAMSS_TFE_1_CSID_CLK_SRC] = &gcc_camss_tfe_1_csid_clk_src.clkr,
+ [GCC_CAMSS_TFE_2_CLK] = &gcc_camss_tfe_2_clk.clkr,
+ [GCC_CAMSS_TFE_2_CLK_SRC] = &gcc_camss_tfe_2_clk_src.clkr,
+ [GCC_CAMSS_TFE_2_CPHY_RX_CLK] = &gcc_camss_tfe_2_cphy_rx_clk.clkr,
+ [GCC_CAMSS_TFE_2_CSID_CLK] = &gcc_camss_tfe_2_csid_clk.clkr,
+ [GCC_CAMSS_TFE_2_CSID_CLK_SRC] = &gcc_camss_tfe_2_csid_clk_src.clkr,
+ [GCC_CAMSS_TFE_CPHY_RX_CLK_SRC] = &gcc_camss_tfe_cphy_rx_clk_src.clkr,
+ [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr,
+ [GCC_CAMSS_TOP_AHB_CLK_SRC] = &gcc_camss_top_ahb_clk_src.clkr,
+ [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr,
+ [GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr,
+ [GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr,
+ [GCC_DISP_GPLL0_CLK_SRC] = &gcc_disp_gpll0_clk_src.clkr,
+ [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr,
+ [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr,
+ [GCC_DISP_THROTTLE_CORE_CLK] = &gcc_disp_throttle_core_clk.clkr,
+ [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr,
+ [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
+ [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr,
+ [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr,
+ [GCC_GPU_IREF_CLK] = &gcc_gpu_iref_clk.clkr,
+ [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr,
+ [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr,
+ [GCC_GPU_THROTTLE_CORE_CLK] = &gcc_gpu_throttle_core_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr,
+ [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+ [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr,
+ [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr,
+ [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr,
+ [GCC_QMIP_GPU_CFG_AHB_CLK] = &gcc_qmip_gpu_cfg_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr,
+ [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr,
+ [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr,
+ [GCC_SYS_NOC_UFS_PHY_AXI_CLK] = &gcc_sys_noc_ufs_phy_axi_clk.clkr,
+ [GCC_SYS_NOC_USB3_PRIM_AXI_CLK] = &gcc_sys_noc_usb3_prim_axi_clk.clkr,
+ [GCC_UFS_CLKREF_CLK] = &gcc_ufs_clkref_clk.clkr,
+ [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr,
+ [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr,
+ [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr,
+ [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr,
+ [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr,
+ [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr,
+ [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr,
+ [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] =
+ &gcc_ufs_phy_unipro_core_clk_src.clkr,
+ [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr,
+ [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] =
+ &gcc_usb30_prim_mock_utmi_clk_src.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC] =
+ &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr,
+ [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr,
+ [GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr,
+ [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr,
+ [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr,
+ [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr,
+ [GCC_VCODEC0_AXI_CLK] = &gcc_vcodec0_axi_clk.clkr,
+ [GCC_VENUS_AHB_CLK] = &gcc_venus_ahb_clk.clkr,
+ [GCC_VENUS_CTL_AXI_CLK] = &gcc_venus_ctl_axi_clk.clkr,
+ [GCC_VIDEO_AHB_CLK] = &gcc_video_ahb_clk.clkr,
+ [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr,
+ [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr,
+ [GCC_VIDEO_VCODEC0_SYS_CLK] = &gcc_video_vcodec0_sys_clk.clkr,
+ [GCC_VIDEO_VENUS_CLK_SRC] = &gcc_video_venus_clk_src.clkr,
+ [GCC_VIDEO_VENUS_CTL_CLK] = &gcc_video_venus_ctl_clk.clkr,
+ [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr,
+ [GPLL0] = &gpll0.clkr,
+ [GPLL0_OUT_AUX2] = &gpll0_out_aux2.clkr,
+ [GPLL0_OUT_MAIN] = &gpll0_out_main.clkr,
+ [GPLL10] = &gpll10.clkr,
+ [GPLL10_OUT_MAIN] = &gpll10_out_main.clkr,
+ [GPLL11] = &gpll11.clkr,
+ [GPLL11_OUT_MAIN] = &gpll11_out_main.clkr,
+ [GPLL3] = &gpll3.clkr,
+ [GPLL4] = &gpll4.clkr,
+ [GPLL4_OUT_MAIN] = &gpll4_out_main.clkr,
+ [GPLL6] = &gpll6.clkr,
+ [GPLL6_OUT_MAIN] = &gpll6_out_main.clkr,
+ [GPLL7] = &gpll7.clkr,
+ [GPLL7_OUT_MAIN] = &gpll7_out_main.clkr,
+ [GPLL8] = &gpll8.clkr,
+ [GPLL8_OUT_MAIN] = &gpll8_out_main.clkr,
+ [GPLL9] = &gpll9.clkr,
+ [GPLL9_OUT_MAIN] = &gpll9_out_main.clkr,
+};
+
+static const struct qcom_reset_map gcc_sm6115_resets[] = {
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0x1c000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0x1c004 },
+ [GCC_SDCC1_BCR] = { 0x38000 },
+ [GCC_SDCC2_BCR] = { 0x1e000 },
+ [GCC_UFS_PHY_BCR] = { 0x45000 },
+ [GCC_USB30_PRIM_BCR] = { 0x1a000 },
+ [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x1d000 },
+ [GCC_USB3PHY_PHY_PRIM_SP0_BCR] = { 0x1b008 },
+ [GCC_USB3_PHY_PRIM_SP0_BCR] = { 0x1b000 },
+ [GCC_VCODEC0_BCR] = { 0x58094 },
+ [GCC_VENUS_BCR] = { 0x58078 },
+ [GCC_VIDEO_INTERFACE_BCR] = { 0x6e000 },
+};
+
+static struct gdsc *gcc_sm6115_gdscs[] = {
+ [GCC_CAMSS_TOP_GDSC] = &gcc_camss_top_gdsc,
+ [GCC_UFS_PHY_GDSC] = &gcc_ufs_phy_gdsc,
+ [GCC_USB30_PRIM_GDSC] = &gcc_usb30_prim_gdsc,
+ [GCC_VCODEC0_GDSC] = &gcc_vcodec0_gdsc,
+ [GCC_VENUS_GDSC] = &gcc_venus_gdsc,
+ [HLOS1_VOTE_TURING_MMU_TBU1_GDSC] = &hlos1_vote_turing_mmu_tbu1_gdsc,
+ [HLOS1_VOTE_TURING_MMU_TBU0_GDSC] = &hlos1_vote_turing_mmu_tbu0_gdsc,
+ [HLOS1_VOTE_MM_SNOC_MMU_TBU_RT_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_rt_gdsc,
+ [HLOS1_VOTE_MM_SNOC_MMU_TBU_NRT_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc,
+};
+
+static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src),
+};
+
+static const struct regmap_config gcc_sm6115_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xc7000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_sm6115_desc = {
+ .config = &gcc_sm6115_regmap_config,
+ .clks = gcc_sm6115_clocks,
+ .num_clks = ARRAY_SIZE(gcc_sm6115_clocks),
+ .resets = gcc_sm6115_resets,
+ .num_resets = ARRAY_SIZE(gcc_sm6115_resets),
+ .gdscs = gcc_sm6115_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_sm6115_gdscs),
+};
+
+static const struct of_device_id gcc_sm6115_match_table[] = {
+ { .compatible = "qcom,gcc-sm6115" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_sm6115_match_table);
+
+static int gcc_sm6115_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ regmap = qcom_cc_map(pdev, &gcc_sm6115_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
+ ARRAY_SIZE(gcc_dfs_clocks));
+ if (ret)
+ return ret;
+
+ clk_alpha_pll_configure(&gpll8, regmap, &gpll8_config);
+ clk_alpha_pll_configure(&gpll9, regmap, &gpll9_config);
+ clk_alpha_pll_configure(&gpll10, regmap, &gpll10_config);
+ clk_alpha_pll_configure(&gpll11, regmap, &gpll11_config);
+
+ return qcom_cc_really_probe(pdev, &gcc_sm6115_desc, regmap);
+}
+
+static struct platform_driver gcc_sm6115_driver = {
+ .probe = gcc_sm6115_probe,
+ .driver = {
+ .name = "gcc-sm6115",
+ .of_match_table = gcc_sm6115_match_table,
+ },
+};
+
+static int __init gcc_sm6115_init(void)
+{
+ return platform_driver_register(&gcc_sm6115_driver);
+}
+subsys_initcall(gcc_sm6115_init);
+
+static void __exit gcc_sm6115_exit(void)
+{
+ platform_driver_unregister(&gcc_sm6115_driver);
+}
+module_exit(gcc_sm6115_exit);
+
+MODULE_DESCRIPTION("QTI GCC SM6115 and SM4250 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-sm6115");
diff --git a/drivers/clk/qcom/gcc-sm6350.c b/drivers/clk/qcom/gcc-sm6350.c
new file mode 100644
index 000000000000..053089f83677
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sm6350.c
@@ -0,0 +1,2588 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,gcc-sm6350.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ P_BI_TCXO,
+ P_GPLL0_OUT_EVEN,
+ P_GPLL0_OUT_MAIN,
+ P_GPLL0_OUT_ODD,
+ P_GPLL6_OUT_EVEN,
+ P_GPLL7_OUT_MAIN,
+ P_SLEEP_CLK,
+};
+
+static struct clk_alpha_pll gpll0 = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_fabia_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll0_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll0_out_even = {
+ .offset = 0x0,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll0_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0_out_even",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_fabia_ops,
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll0_out_odd[] = {
+ { 0x3, 3 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll0_out_odd = {
+ .offset = 0x0,
+ .post_div_shift = 12,
+ .post_div_table = post_div_table_gpll0_out_odd,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_odd),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0_out_odd",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_fabia_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll6 = {
+ .offset = 0x6000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(6),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll6",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_fabia_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll6_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll6_out_even = {
+ .offset = 0x6000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_gpll6_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll6_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll6_out_even",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_fabia_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll7 = {
+ .offset = 0x7000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll7",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_fabia_ops,
+ },
+ },
+};
+
+static const struct parent_map gcc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL6_OUT_EVEN, 2 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_0[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6_out_even.clkr.hw },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_1[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_ODD, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_2[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0_out_odd.clkr.hw },
+};
+static const struct clk_parent_data gcc_parent_data_2_ao[] = {
+ { .fw_name = "bi_tcxo_ao" },
+ { .hw = &gpll0_out_odd.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL0_OUT_ODD, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_4[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_odd.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_ODD, 2 },
+ { P_SLEEP_CLK, 5 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_5[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0_out_odd.clkr.hw },
+ { .fw_name = "sleep_clk" },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_6[] = {
+ { .fw_name = "bi_tcxo" },
+ { .fw_name = "sleep_clk" }
+};
+
+static const struct parent_map gcc_parent_map_7[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL6_OUT_EVEN, 2 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_7[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll6_out_even.clkr.hw },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_8[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_ODD, 2 },
+ { P_GPLL7_OUT_MAIN, 3 },
+};
+
+static const struct clk_parent_data gcc_parent_data_8[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpll0_out_odd.clkr.hw },
+ { .hw = &gpll7.clkr.hw },
+};
+
+static struct clk_regmap_div gcc_gpu_gpll0_main_div_clk_src = {
+ .reg = 0x4514C,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gcc_gpu_gpll0_main_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_npu_pll0_main_div_clk_src = {
+ .reg = 0x4ce00,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gcc_npu_pll0_main_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_cpuss_ahb_clk_src = {
+ .cmd_rcgr = 0x30014,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_cpuss_ahb_clk_src",
+ .parent_data = gcc_parent_data_2_ao,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2_ao),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(50000000, P_GPLL0_OUT_ODD, 4, 0, 0),
+ F(100000000, P_GPLL0_OUT_ODD, 2, 0, 0),
+ F(200000000, P_GPLL0_OUT_ODD, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_gp1_clk_src = {
+ .cmd_rcgr = 0x37004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk_src",
+ .parent_data = gcc_parent_data_5,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_5),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp2_clk_src = {
+ .cmd_rcgr = 0x38004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk_src",
+ .parent_data = gcc_parent_data_5,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_5),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp3_clk_src = {
+ .cmd_rcgr = 0x39004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk_src",
+ .parent_data = gcc_parent_data_5,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_5),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(60000000, P_GPLL0_OUT_EVEN, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pdm2_clk_src = {
+ .cmd_rcgr = 0x23010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_pdm2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
+ F(7372800, P_GPLL0_OUT_EVEN, 1, 384, 15625),
+ F(14745600, P_GPLL0_OUT_EVEN, 1, 768, 15625),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(29491200, P_GPLL0_OUT_EVEN, 1, 1536, 15625),
+ F(32000000, P_GPLL0_OUT_EVEN, 1, 8, 75),
+ F(48000000, P_GPLL0_OUT_EVEN, 1, 4, 25),
+ F(64000000, P_GPLL0_OUT_EVEN, 1, 16, 75),
+ F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(80000000, P_GPLL0_OUT_EVEN, 1, 4, 15),
+ F(96000000, P_GPLL0_OUT_EVEN, 1, 8, 25),
+ F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(102400000, P_GPLL0_OUT_EVEN, 1, 128, 375),
+ F(112000000, P_GPLL0_OUT_EVEN, 1, 28, 75),
+ F(117964800, P_GPLL0_OUT_EVEN, 1, 6144, 15625),
+ F(120000000, P_GPLL0_OUT_EVEN, 2.5, 0, 0),
+ F(128000000, P_GPLL6_OUT_EVEN, 3, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
+ .cmd_rcgr = 0x21148,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
+ .cmd_rcgr = 0x21278,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
+ .cmd_rcgr = 0x213a8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
+ .cmd_rcgr = 0x214d8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
+ .cmd_rcgr = 0x21608,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s5_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
+ .cmd_rcgr = 0x21738,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = {
+ .cmd_rcgr = 0x22018,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = {
+ .cmd_rcgr = 0x22148,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = {
+ .cmd_rcgr = 0x22278,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = {
+ .cmd_rcgr = 0x223a8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = {
+ .cmd_rcgr = 0x224d8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s5_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = {
+ .cmd_rcgr = 0x22608,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
+ F(144000, P_BI_TCXO, 16, 3, 25),
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(20000000, P_GPLL0_OUT_EVEN, 5, 1, 3),
+ F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(192000000, P_GPLL6_OUT_EVEN, 2, 0, 0),
+ F(384000000, P_GPLL6_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x4b024,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_7,
+ .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk_src",
+ .parent_data = gcc_parent_data_7,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_7),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = {
+ F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(150000000, P_GPLL0_OUT_EVEN, 2, 0, 0),
+ F(300000000, P_GPLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x4b00c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ice_core_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(9600000, P_BI_TCXO, 2, 0, 0),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(25000000, P_GPLL0_OUT_ODD, 8, 0, 0),
+ F(50000000, P_GPLL0_OUT_ODD, 4, 0, 0),
+ F(100000000, P_GPLL0_OUT_ODD, 2, 0, 0),
+ F(202000000, P_GPLL7_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x2000c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_8,
+ .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk_src",
+ .parent_data = gcc_parent_data_8,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_8),
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = {
+ F(25000000, P_GPLL0_OUT_ODD, 8, 0, 0),
+ F(50000000, P_GPLL0_OUT_ODD, 4, 0, 0),
+ F(100000000, P_GPLL0_OUT_ODD, 2, 0, 0),
+ F(200000000, P_GPLL0_OUT_ODD, 1, 0, 0),
+ F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = {
+ .cmd_rcgr = 0x3a01c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_axi_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = {
+ F(37500000, P_GPLL0_OUT_EVEN, 8, 0, 0),
+ F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(150000000, P_GPLL0_OUT_EVEN, 2, 0, 0),
+ F(300000000, P_GPLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = {
+ .cmd_rcgr = 0x3a048,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ice_core_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_phy_aux_clk_src[] = {
+ F(9600000, P_BI_TCXO, 2, 0, 0),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = {
+ .cmd_rcgr = 0x3a0b0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .freq_tbl = ftbl_gcc_ufs_phy_phy_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_phy_aux_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = {
+ F(37500000, P_GPLL0_OUT_EVEN, 8, 0, 0),
+ F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(150000000, P_GPLL0_OUT_EVEN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = {
+ .cmd_rcgr = 0x3a060,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_ufs_phy_unipro_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_unipro_core_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = {
+ F(66666667, P_GPLL0_OUT_ODD, 3, 0, 0),
+ F(133333333, P_GPLL0_OUT_MAIN, 4.5, 0, 0),
+ F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+ F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_prim_master_clk_src = {
+ .cmd_rcgr = 0x1a01c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_master_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x1a034,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_mock_utmi_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
+ .cmd_rcgr = 0x1a060,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_6,
+ .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_6,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_6),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_aggre_ufs_phy_axi_clk = {
+ .halt_reg = 0x3e014,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x3e014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3e014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre_ufs_phy_axi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_ufs_phy_axi_hw_ctl_clk = {
+ .halt_reg = 0x3e014,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3e014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3e014,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre_ufs_phy_axi_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_axi_hw_ctl_clk = {
+ .halt_reg = 0x3e014,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3e014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3e014,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_axi_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_usb3_prim_axi_clk = {
+ .halt_reg = 0x3e010,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3e010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3e010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x26004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x26004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(28),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_ahb_clk = {
+ .halt_reg = 0x17008,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_axi_clk = {
+ .halt_reg = 0x17018,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_throttle_nrt_axi_clk = {
+ .halt_reg = 0x17078,
+ .halt_check = BRANCH_VOTED,
+ .hwcg_reg = 0x17078,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17078,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_throttle_nrt_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_throttle_rt_axi_clk = {
+ .halt_reg = 0x17024,
+ .halt_check = BRANCH_VOTED,
+ .hwcg_reg = 0x17024,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_throttle_rt_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_xo_clk = {
+ .halt_reg = 0x17030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17030,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_xo_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce1_ahb_clk = {
+ .halt_reg = 0x2b00c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2b00c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce1_axi_clk = {
+ .halt_reg = 0x2b008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce1_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce1_clk = {
+ .halt_reg = 0x2b004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = {
+ .halt_reg = 0x1101c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1101c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1101c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cpuss_ahb_clk = {
+ .halt_reg = 0x30000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x30000,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cpuss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_cpuss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cpuss_gnoc_clk = {
+ .halt_reg = 0x30004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x30004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(5),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cpuss_gnoc_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cpuss_rbcpr_clk = {
+ .halt_reg = 0x30008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x30008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cpuss_rbcpr_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ddrss_gpu_axi_clk = {
+ .halt_reg = 0x2d038,
+ .halt_check = BRANCH_VOTED,
+ .hwcg_reg = 0x2d038,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x2d038,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ddrss_gpu_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_ahb_clk = {
+ .halt_reg = 0x1700c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1700c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1700c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_axi_clk = {
+ .halt_reg = 0x1701c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x1701c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1701c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_cc_sleep_clk = {
+ .halt_reg = 0x17074,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x17074,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17074,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_cc_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_cc_xo_clk = {
+ .halt_reg = 0x17070,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17070,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17070,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_cc_xo_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_gpll0_clk = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_gpll0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_throttle_axi_clk = {
+ .halt_reg = 0x17028,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17028,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_throttle_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_xo_clk = {
+ .halt_reg = 0x17034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_xo_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x37000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x37000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_gp1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x38000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x38000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_gp2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x39000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x39000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_gp3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_cfg_ahb_clk = {
+ .halt_reg = 0x45004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x45004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x45004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_cfg_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_clk = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_div_clk = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_div_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_gpu_gpll0_main_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_memnoc_gfx_clk = {
+ .halt_reg = 0x4500c,
+ .halt_check = BRANCH_VOTED,
+ .hwcg_reg = 0x4500c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4500c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_memnoc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = {
+ .halt_reg = 0x45014,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x45014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x45014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_snoc_dvm_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_npu_axi_clk = {
+ .halt_reg = 0x4c008,
+ .halt_check = BRANCH_VOTED,
+ .hwcg_reg = 0x4c008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4c008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_npu_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_npu_bwmon_axi_clk = {
+ .halt_reg = 0x4d004,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x4d004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_npu_bwmon_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_npu_bwmon_dma_cfg_ahb_clk = {
+ .halt_reg = 0x4d008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_npu_bwmon_dma_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_npu_bwmon_dsp_cfg_ahb_clk = {
+ .halt_reg = 0x4d00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_npu_bwmon_dsp_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_npu_cfg_ahb_clk = {
+ .halt_reg = 0x4c004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x4c004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_npu_cfg_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_npu_dma_clk = {
+ .halt_reg = 0x4c140,
+ .halt_check = BRANCH_VOTED,
+ .hwcg_reg = 0x4c140,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4c140,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_npu_dma_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_npu_gpll0_clk = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_npu_gpll0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_npu_gpll0_div_clk = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_npu_gpll0_div_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_npu_pll0_main_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x2300c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_pdm2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x23004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x23004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x23004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_xo4_clk = {
+ .halt_reg = 0x23008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x23008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_xo4_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+ .halt_reg = 0x24004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x24004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(26),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_prng_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = {
+ .halt_reg = 0x21014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_clk = {
+ .halt_reg = 0x2100c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s0_clk = {
+ .halt_reg = 0x21144,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap0_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s1_clk = {
+ .halt_reg = 0x21274,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap0_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s2_clk = {
+ .halt_reg = 0x213a4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap0_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s3_clk = {
+ .halt_reg = 0x214d4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s3_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap0_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s4_clk = {
+ .halt_reg = 0x21604,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s4_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap0_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s5_clk = {
+ .halt_reg = 0x21734,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap0_s5_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap0_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = {
+ .halt_reg = 0x22004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(16),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_core_clk = {
+ .halt_reg = 0x22008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s0_clk = {
+ .halt_reg = 0x22014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(20),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap1_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s1_clk = {
+ .halt_reg = 0x22144,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(21),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap1_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s2_clk = {
+ .halt_reg = 0x22274,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(22),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap1_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s3_clk = {
+ .halt_reg = 0x223a4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(23),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s3_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap1_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s4_clk = {
+ .halt_reg = 0x224d4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(24),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s4_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap1_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s5_clk = {
+ .halt_reg = 0x22604,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(25),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s5_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_qupv3_wrap1_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = {
+ .halt_reg = 0x21004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x21004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(6),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_0_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = {
+ .halt_reg = 0x21008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x21008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_0_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = {
+ .halt_reg = 0x2200c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2200c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(18),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_1_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = {
+ .halt_reg = 0x22010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x22010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(19),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_1_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x4b004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4b004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x4b008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_sdcc1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x4b03c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x4b03c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_sdcc1_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x20008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x20004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_sdcc2_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = {
+ .halt_reg = 0x10140,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x10140,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_cpuss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_cpuss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_mem_clkref_clk = {
+ .halt_reg = 0x8c000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8c000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_mem_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ahb_clk = {
+ .halt_reg = 0x3a00c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3a00c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3a00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_axi_clk = {
+ .halt_reg = 0x3a034,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3a034,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3a034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_axi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ice_core_clk = {
+ .halt_reg = 0x3a0a4,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3a0a4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3a0a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ice_core_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ice_core_hw_ctl_clk = {
+ .halt_reg = 0x3a0a4,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3a0a4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3a0a4,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ice_core_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_phy_aux_clk = {
+ .halt_reg = 0x3a0ac,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3a0ac,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3a0ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_phy_aux_hw_ctl_clk = {
+ .halt_reg = 0x3a0ac,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3a0ac,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3a0ac,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_phy_aux_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = {
+ .halt_reg = 0x3a014,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x3a014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_rx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_rx_symbol_1_clk = {
+ .halt_reg = 0x3a018,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x3a018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_rx_symbol_1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = {
+ .halt_reg = 0x3a010,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x3a010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_tx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_unipro_core_clk = {
+ .halt_reg = 0x3a09c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3a09c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3a09c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_unipro_core_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_unipro_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_unipro_core_hw_ctl_clk = {
+ .halt_reg = 0x3a09c,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x3a09c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3a09c,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_unipro_core_hw_ctl_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_ufs_phy_unipro_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_master_clk = {
+ .halt_reg = 0x1a00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_master_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_mock_utmi_clk = {
+ .halt_reg = 0x1a018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_mock_utmi_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_sleep_clk = {
+ .halt_reg = 0x1a014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_clkref_clk = {
+ .halt_reg = 0x8c010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8c010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_aux_clk = {
+ .halt_reg = 0x1a050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a050,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_usb3_prim_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = {
+ .halt_reg = 0x1a054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a054,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_com_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gcc_usb3_prim_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_pipe_clk = {
+ .halt_reg = 0x1a058,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x1a058,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1a058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_pipe_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_ahb_clk = {
+ .halt_reg = 0x17004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_ahb_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_axi_clk = {
+ .halt_reg = 0x17014,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_throttle_axi_clk = {
+ .halt_reg = 0x17020,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x17020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x17020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_throttle_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_xo_clk = {
+ .halt_reg = 0x1702c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1702c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_xo_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc usb30_prim_gdsc = {
+ .gdscr = 0x1a004,
+ .pd = {
+ .name = "usb30_prim_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc ufs_phy_gdsc = {
+ .gdscr = 0x3a004,
+ .pd = {
+ .name = "ufs_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = {
+ .gdscr = 0xb7040,
+ .pd = {
+ .name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc = {
+ .gdscr = 0xb7044,
+ .pd = {
+ .name = "hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct clk_regmap *gcc_sm6350_clocks[] = {
+ [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr,
+ [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CAMERA_AHB_CLK] = &gcc_camera_ahb_clk.clkr,
+ [GCC_CAMERA_AXI_CLK] = &gcc_camera_axi_clk.clkr,
+ [GCC_CAMERA_THROTTLE_NRT_AXI_CLK] =
+ &gcc_camera_throttle_nrt_axi_clk.clkr,
+ [GCC_CAMERA_THROTTLE_RT_AXI_CLK] = &gcc_camera_throttle_rt_axi_clk.clkr,
+ [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr,
+ [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr,
+ [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr,
+ [GCC_CE1_CLK] = &gcc_ce1_clk.clkr,
+ [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr,
+ [GCC_CPUSS_AHB_CLK] = &gcc_cpuss_ahb_clk.clkr,
+ [GCC_CPUSS_AHB_CLK_SRC] = &gcc_cpuss_ahb_clk_src.clkr,
+ [GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr,
+ [GCC_CPUSS_RBCPR_CLK] = &gcc_cpuss_rbcpr_clk.clkr,
+ [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr,
+ [GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr,
+ [GCC_DISP_AXI_CLK] = &gcc_disp_axi_clk.clkr,
+ [GCC_DISP_CC_SLEEP_CLK] = &gcc_disp_cc_sleep_clk.clkr,
+ [GCC_DISP_CC_XO_CLK] = &gcc_disp_cc_xo_clk.clkr,
+ [GCC_DISP_GPLL0_CLK] = &gcc_disp_gpll0_clk.clkr,
+ [GCC_DISP_THROTTLE_AXI_CLK] = &gcc_disp_throttle_axi_clk.clkr,
+ [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr,
+ [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
+ [GCC_GPU_GPLL0_CLK] = &gcc_gpu_gpll0_clk.clkr,
+ [GCC_GPU_GPLL0_DIV_CLK] = &gcc_gpu_gpll0_div_clk.clkr,
+ [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr,
+ [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr,
+ [GCC_NPU_AXI_CLK] = &gcc_npu_axi_clk.clkr,
+ [GCC_NPU_BWMON_AXI_CLK] = &gcc_npu_bwmon_axi_clk.clkr,
+ [GCC_NPU_BWMON_DMA_CFG_AHB_CLK] = &gcc_npu_bwmon_dma_cfg_ahb_clk.clkr,
+ [GCC_NPU_BWMON_DSP_CFG_AHB_CLK] = &gcc_npu_bwmon_dsp_cfg_ahb_clk.clkr,
+ [GCC_NPU_CFG_AHB_CLK] = &gcc_npu_cfg_ahb_clk.clkr,
+ [GCC_NPU_DMA_CLK] = &gcc_npu_dma_clk.clkr,
+ [GCC_NPU_GPLL0_CLK] = &gcc_npu_gpll0_clk.clkr,
+ [GCC_NPU_GPLL0_DIV_CLK] = &gcc_npu_gpll0_div_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr,
+ [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr,
+ [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr,
+ [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr,
+ [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr,
+ [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr,
+ [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr,
+ [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr,
+ [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr,
+ [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr,
+ [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr,
+ [GCC_UFS_MEM_CLKREF_CLK] = &gcc_ufs_mem_clkref_clk.clkr,
+ [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr,
+ [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr,
+ [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr,
+ [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr,
+ [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr,
+ [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr,
+ [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr,
+ [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] =
+ &gcc_ufs_phy_unipro_core_clk_src.clkr,
+ [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr,
+ [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] =
+ &gcc_usb30_prim_mock_utmi_clk_src.clkr,
+ [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr,
+ [GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr,
+ [GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.clkr,
+ [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr,
+ [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr,
+ [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr,
+ [GCC_VIDEO_AHB_CLK] = &gcc_video_ahb_clk.clkr,
+ [GCC_VIDEO_AXI_CLK] = &gcc_video_axi_clk.clkr,
+ [GCC_VIDEO_THROTTLE_AXI_CLK] = &gcc_video_throttle_axi_clk.clkr,
+ [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr,
+ [GPLL0] = &gpll0.clkr,
+ [GPLL0_OUT_EVEN] = &gpll0_out_even.clkr,
+ [GPLL0_OUT_ODD] = &gpll0_out_odd.clkr,
+ [GPLL6] = &gpll6.clkr,
+ [GPLL6_OUT_EVEN] = &gpll6_out_even.clkr,
+ [GPLL7] = &gpll7.clkr,
+ [GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_ufs_phy_axi_hw_ctl_clk.clkr,
+ [GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK] =
+ &gcc_aggre_ufs_phy_axi_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK] =
+ &gcc_ufs_phy_unipro_core_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK] =
+ &gcc_ufs_phy_ice_core_hw_ctl_clk.clkr,
+ [GCC_GPU_GPLL0_MAIN_DIV_CLK_SRC] = &gcc_gpu_gpll0_main_div_clk_src.clkr,
+ [GCC_NPU_PLL0_MAIN_DIV_CLK_SRC] = &gcc_npu_pll0_main_div_clk_src.clkr,
+};
+
+static struct gdsc *gcc_sm6350_gdscs[] = {
+ [USB30_PRIM_GDSC] = &usb30_prim_gdsc,
+ [UFS_PHY_GDSC] = &ufs_phy_gdsc,
+ [HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC] = &hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc,
+ [HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC] = &hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc,
+};
+
+static const struct qcom_reset_map gcc_sm6350_resets[] = {
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0x1d000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0x1e000 },
+ [GCC_SDCC1_BCR] = { 0x4b000 },
+ [GCC_SDCC2_BCR] = { 0x20000 },
+ [GCC_UFS_PHY_BCR] = { 0x3a000 },
+ [GCC_USB30_PRIM_BCR] = { 0x1a000 },
+ [GCC_USB3_PHY_PRIM_BCR] = { 0x1c000 },
+ [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x1c008 },
+};
+
+static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk_src),
+};
+
+static const struct regmap_config gcc_sm6350_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xbf030,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_sm6350_desc = {
+ .config = &gcc_sm6350_regmap_config,
+ .clks = gcc_sm6350_clocks,
+ .num_clks = ARRAY_SIZE(gcc_sm6350_clocks),
+ .resets = gcc_sm6350_resets,
+ .num_resets = ARRAY_SIZE(gcc_sm6350_resets),
+ .gdscs = gcc_sm6350_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_sm6350_gdscs),
+};
+
+static const struct of_device_id gcc_sm6350_match_table[] = {
+ { .compatible = "qcom,gcc-sm6350" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_sm6350_match_table);
+
+static int gcc_sm6350_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ regmap = qcom_cc_map(pdev, &gcc_sm6350_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /* Disable the GPLL0 active input to NPU and GPU via MISC registers */
+ regmap_update_bits(regmap, 0x4cf00, 0x3, 0x3);
+ regmap_update_bits(regmap, 0x45f00, 0x3, 0x3);
+
+ ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
+ ARRAY_SIZE(gcc_dfs_clocks));
+ if (ret)
+ return ret;
+
+ return qcom_cc_really_probe(pdev, &gcc_sm6350_desc, regmap);;
+}
+
+static struct platform_driver gcc_sm6350_driver = {
+ .probe = gcc_sm6350_probe,
+ .driver = {
+ .name = "gcc-sm6350",
+ .of_match_table = gcc_sm6350_match_table,
+ },
+};
+
+static int __init gcc_sm6350_init(void)
+{
+ return platform_driver_register(&gcc_sm6350_driver);
+}
+core_initcall(gcc_sm6350_init);
+
+static void __exit gcc_sm6350_exit(void)
+{
+ platform_driver_unregister(&gcc_sm6350_driver);
+}
+module_exit(gcc_sm6350_exit);
+
+MODULE_DESCRIPTION("QTI GCC SM6350 Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/gpucc-sc7280.c b/drivers/clk/qcom/gpucc-sc7280.c
new file mode 100644
index 000000000000..9a832f2bcf49
--- /dev/null
+++ b/drivers/clk/qcom/gpucc-sc7280.c
@@ -0,0 +1,491 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,gpucc-sc7280.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "reset.h"
+#include "gdsc.h"
+
+enum {
+ P_BI_TCXO,
+ P_GCC_GPU_GPLL0_CLK_SRC,
+ P_GCC_GPU_GPLL0_DIV_CLK_SRC,
+ P_GPU_CC_PLL0_OUT_MAIN,
+ P_GPU_CC_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_vco[] = {
+ { 249600000, 2000000000, 0 },
+};
+
+static struct clk_alpha_pll gpu_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_vco,
+ .num_vco = ARRAY_SIZE(lucid_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_pll0",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_ops,
+ },
+ },
+};
+
+/* 500MHz Configuration */
+static const struct alpha_pll_config gpu_cc_pll1_config = {
+ .l = 0x1A,
+ .alpha = 0xAAA,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00002261,
+ .config_ctl_hi1_val = 0x329A299C,
+ .user_ctl_val = 0x00000001,
+ .user_ctl_hi_val = 0x00000805,
+ .user_ctl_hi1_val = 0x00000000,
+};
+
+static struct clk_alpha_pll gpu_cc_pll1 = {
+ .offset = 0x100,
+ .vco_table = lucid_vco,
+ .num_vco = ARRAY_SIZE(lucid_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_pll1",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_ops,
+ },
+ },
+};
+
+static const struct parent_map gpu_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL0_OUT_MAIN, 1 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GCC_GPU_GPLL0_CLK_SRC, 5 },
+ { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_0[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gpu_cc_pll0.clkr.hw },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .fw_name = "gcc_gpu_gpll0_clk_src" },
+ { .fw_name = "gcc_gpu_gpll0_div_clk_src" },
+};
+
+static const struct parent_map gpu_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GCC_GPU_GPLL0_CLK_SRC, 5 },
+ { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_1[] = {
+ { .fw_name = "bi_tcxo", },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .fw_name = "gcc_gpu_gpll0_clk_src", },
+ { .fw_name = "gcc_gpu_gpll0_div_clk_src", },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 1.5, 0, 0),
+ F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_gmu_clk_src = {
+ .cmd_rcgr = 0x1120,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_0,
+ .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_gmu_clk_src",
+ .parent_data = gpu_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = {
+ F(150000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 2, 0, 0),
+ F(240000000, P_GCC_GPU_GPLL0_CLK_SRC, 2.5, 0, 0),
+ F(300000000, P_GCC_GPU_GPLL0_CLK_SRC, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_hub_clk_src = {
+ .cmd_rcgr = 0x117c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_1,
+ .freq_tbl = ftbl_gpu_cc_hub_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_hub_clk_src",
+ .parent_data = gpu_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_hub_ahb_div_clk_src = {
+ .reg = 0x11c0,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gpu_cc_hub_ahb_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_hub_cx_int_div_clk_src = {
+ .reg = 0x11bc,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gpu_cc_hub_cx_int_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch gpu_cc_ahb_clk = {
+ .halt_reg = 0x1078,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x1078,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_hub_ahb_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_crc_ahb_clk = {
+ .halt_reg = 0x107c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x107c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_crc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_hub_ahb_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_gmu_clk = {
+ .halt_reg = 0x1098,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1098,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cx_gmu_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_gmu_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
+ .halt_reg = 0x108c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x108c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cx_snoc_dvm_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cxo_aon_clk = {
+ .halt_reg = 0x1004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cxo_aon_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cxo_clk = {
+ .halt_reg = 0x109c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x109c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cxo_clk",
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_gx_gmu_clk = {
+ .halt_reg = 0x1064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1064,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_gx_gmu_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_gmu_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
+ .halt_reg = 0x5000,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x5000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_aon_clk = {
+ .halt_reg = 0x1178,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1178,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_hub_aon_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_cx_int_clk = {
+ .halt_reg = 0x1204,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1204,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_hub_cx_int_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_hub_cx_int_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = {
+ .halt_reg = 0x802c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x802c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_mnd1x_0_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = {
+ .halt_reg = 0x8030,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x8030,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_mnd1x_1_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_sleep_clk = {
+ .halt_reg = 0x1090,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1090,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc cx_gdsc = {
+ .gdscr = 0x106c,
+ .gds_hw_ctrl = 0x1540,
+ .pd = {
+ .name = "cx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gx_gdsc = {
+ .gdscr = 0x100c,
+ .clamp_io_ctrl = 0x1508,
+ .pd = {
+ .name = "gx_gdsc",
+ .power_on = gdsc_gx_do_nothing_enable,
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = CLAMP_IO | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc *gpu_cc_sc7180_gdscs[] = {
+ [GPU_CC_CX_GDSC] = &cx_gdsc,
+ [GPU_CC_GX_GDSC] = &gx_gdsc,
+};
+
+static struct clk_regmap *gpu_cc_sc7280_clocks[] = {
+ [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
+ [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
+ [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
+ [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
+ [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
+ [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
+ [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
+ [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
+ [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
+ [GPU_CC_HUB_AHB_DIV_CLK_SRC] = &gpu_cc_hub_ahb_div_clk_src.clkr,
+ [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
+ [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
+ [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
+ [GPU_CC_HUB_CX_INT_DIV_CLK_SRC] = &gpu_cc_hub_cx_int_div_clk_src.clkr,
+ [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr,
+ [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr,
+ [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
+ [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
+ [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
+};
+
+static const struct regmap_config gpu_cc_sc7280_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x8030,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gpu_cc_sc7280_desc = {
+ .config = &gpu_cc_sc7280_regmap_config,
+ .clks = gpu_cc_sc7280_clocks,
+ .num_clks = ARRAY_SIZE(gpu_cc_sc7280_clocks),
+ .gdscs = gpu_cc_sc7180_gdscs,
+ .num_gdscs = ARRAY_SIZE(gpu_cc_sc7180_gdscs),
+};
+
+static const struct of_device_id gpu_cc_sc7280_match_table[] = {
+ { .compatible = "qcom,sc7280-gpucc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpu_cc_sc7280_match_table);
+
+static int gpu_cc_sc7280_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &gpu_cc_sc7280_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+
+ /*
+ * Keep the clocks always-ON
+ * GPU_CC_CB_CLK, GPUCC_CX_GMU_CLK
+ */
+ regmap_update_bits(regmap, 0x1170, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x1098, BIT(0), BIT(0));
+
+ return qcom_cc_really_probe(pdev, &gpu_cc_sc7280_desc, regmap);
+}
+
+static struct platform_driver gpu_cc_sc7280_driver = {
+ .probe = gpu_cc_sc7280_probe,
+ .driver = {
+ .name = "gpu_cc-sc7280",
+ .of_match_table = gpu_cc_sc7280_match_table,
+ },
+};
+
+static int __init gpu_cc_sc7280_init(void)
+{
+ return platform_driver_register(&gpu_cc_sc7280_driver);
+}
+subsys_initcall(gpu_cc_sc7280_init);
+
+static void __exit gpu_cc_sc7280_exit(void)
+{
+ platform_driver_unregister(&gpu_cc_sc7280_driver);
+}
+module_exit(gpu_cc_sc7280_exit);
+
+MODULE_DESCRIPTION("QTI GPU_CC SC7280 Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/gpucc-sm8150.c b/drivers/clk/qcom/gpucc-sm8150.c
index 80fb6f73601d..8422fd047493 100644
--- a/drivers/clk/qcom/gpucc-sm8150.c
+++ b/drivers/clk/qcom/gpucc-sm8150.c
@@ -82,6 +82,14 @@ static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
{ }
};
+static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src_sc8180x[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
+ F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0),
+ F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
static struct clk_rcg2 gpu_cc_gmu_clk_src = {
.cmd_rcgr = 0x1120,
.mnd_width = 0,
@@ -277,6 +285,7 @@ static const struct qcom_cc_desc gpu_cc_sm8150_desc = {
};
static const struct of_device_id gpu_cc_sm8150_match_table[] = {
+ { .compatible = "qcom,sc8180x-gpucc" },
{ .compatible = "qcom,sm8150-gpucc" },
{ }
};
@@ -290,6 +299,9 @@ static int gpu_cc_sm8150_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,sc8180x-gpucc"))
+ gpu_cc_gmu_clk_src.freq_tbl = ftbl_gpu_cc_gmu_clk_src_sc8180x;
+
clk_trion_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
return qcom_cc_really_probe(pdev, &gpu_cc_sm8150_desc, regmap);
diff --git a/drivers/clk/qcom/lpass-gfm-sm8250.c b/drivers/clk/qcom/lpass-gfm-sm8250.c
index f5e31e692b9b..96f476f24eb2 100644
--- a/drivers/clk/qcom/lpass-gfm-sm8250.c
+++ b/drivers/clk/qcom/lpass-gfm-sm8250.c
@@ -251,15 +251,18 @@ static int lpass_gfm_clk_driver_probe(struct platform_device *pdev)
if (IS_ERR(cc->base))
return PTR_ERR(cc->base);
- pm_runtime_enable(dev);
- err = pm_clk_create(dev);
+ err = devm_pm_runtime_enable(dev);
if (err)
- goto pm_clk_err;
+ return err;
+
+ err = devm_pm_clk_create(dev);
+ if (err)
+ return err;
err = of_pm_clk_add_clks(dev);
if (err < 0) {
dev_dbg(dev, "Failed to get lpass core voting clocks\n");
- goto clk_reg_err;
+ return err;
}
for (i = 0; i < data->onecell_data->num; i++) {
@@ -273,22 +276,16 @@ static int lpass_gfm_clk_driver_probe(struct platform_device *pdev)
err = devm_clk_hw_register(dev, &data->gfm_clks[i]->hw);
if (err)
- goto clk_reg_err;
+ return err;
}
err = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
data->onecell_data);
if (err)
- goto clk_reg_err;
+ return err;
return 0;
-
-clk_reg_err:
- pm_clk_destroy(dev);
-pm_clk_err:
- pm_runtime_disable(dev);
- return err;
}
static const struct of_device_id lpass_gfm_clk_match_table[] = {
diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c
index 2e0ecc38efdd..ac09b7b840ab 100644
--- a/drivers/clk/qcom/lpasscorecc-sc7180.c
+++ b/drivers/clk/qcom/lpasscorecc-sc7180.c
@@ -356,32 +356,18 @@ static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = {
.num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs),
};
-static void lpass_pm_runtime_disable(void *data)
-{
- pm_runtime_disable(data);
-}
-
-static void lpass_pm_clk_destroy(void *data)
-{
- pm_clk_destroy(data);
-}
-
static int lpass_create_pm_clks(struct platform_device *pdev)
{
int ret;
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
- pm_runtime_enable(&pdev->dev);
- ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_runtime_disable, &pdev->dev);
+ ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
return ret;
- ret = pm_clk_create(&pdev->dev);
- if (ret)
- return ret;
- ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_clk_destroy, &pdev->dev);
+ ret = devm_pm_clk_create(&pdev->dev);
if (ret)
return ret;
diff --git a/drivers/clk/qcom/mmcc-msm8994.c b/drivers/clk/qcom/mmcc-msm8994.c
new file mode 100644
index 000000000000..89c5f5fa7d9a
--- /dev/null
+++ b/drivers/clk/qcom/mmcc-msm8994.c
@@ -0,0 +1,2620 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/clk.h>
+
+#include <dt-bindings/clock/qcom,mmcc-msm8994.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+#include "gdsc.h"
+
+
+enum {
+ P_XO,
+ P_GPLL0,
+ P_MMPLL0,
+ P_MMPLL1,
+ P_MMPLL3,
+ P_MMPLL4,
+ P_MMPLL5, /* Is this one even used by anything? Downstream doesn't tell. */
+ P_DSI0PLL,
+ P_DSI1PLL,
+ P_DSI0PLL_BYTE,
+ P_DSI1PLL_BYTE,
+ P_HDMIPLL,
+};
+static const struct parent_map mmcc_xo_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 5 }
+};
+
+static const struct clk_parent_data mmcc_xo_gpll0[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "gpll0" },
+};
+
+static const struct parent_map mmss_xo_hdmi_map[] = {
+ { P_XO, 0 },
+ { P_HDMIPLL, 3 }
+};
+
+static const struct clk_parent_data mmss_xo_hdmi[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "hdmipll" },
+};
+
+static const struct parent_map mmcc_xo_dsi0pll_dsi1pll_map[] = {
+ { P_XO, 0 },
+ { P_DSI0PLL, 1 },
+ { P_DSI1PLL, 2 }
+};
+
+static const struct clk_parent_data mmcc_xo_dsi0pll_dsi1pll[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "dsi0pll" },
+ { .fw_name = "dsi1pll" },
+};
+
+static const struct parent_map mmcc_xo_dsibyte_map[] = {
+ { P_XO, 0 },
+ { P_DSI0PLL_BYTE, 1 },
+ { P_DSI1PLL_BYTE, 2 }
+};
+
+static const struct clk_parent_data mmcc_xo_dsibyte[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "dsi0pllbyte" },
+ { .fw_name = "dsi1pllbyte" },
+};
+
+static struct pll_vco mmpll_p_vco[] = {
+ { 250000000, 500000000, 3 },
+ { 500000000, 1000000000, 2 },
+ { 1000000000, 1500000000, 1 },
+ { 1500000000, 2000000000, 0 },
+};
+
+static struct pll_vco mmpll_t_vco[] = {
+ { 500000000, 1500000000, 0 },
+};
+
+static const struct alpha_pll_config mmpll_p_config = {
+ .post_div_mask = 0xf00,
+};
+
+static struct clk_alpha_pll mmpll0_early = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .vco_table = mmpll_p_vco,
+ .num_vco = ARRAY_SIZE(mmpll_p_vco),
+ .clkr = {
+ .enable_reg = 0x100,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmpll0_early",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv mmpll0 = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll0",
+ .parent_hws = (const struct clk_hw *[]){ &mmpll0_early.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_alpha_pll mmpll1_early = {
+ .offset = 0x30,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .vco_table = mmpll_p_vco,
+ .num_vco = ARRAY_SIZE(mmpll_p_vco),
+ .clkr = {
+ .enable_reg = 0x100,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmpll1_early",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ }
+ },
+};
+
+static struct clk_alpha_pll_postdiv mmpll1 = {
+ .offset = 0x30,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll1",
+ .parent_hws = (const struct clk_hw *[]){ &mmpll1_early.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_alpha_pll mmpll3_early = {
+ .offset = 0x60,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .vco_table = mmpll_p_vco,
+ .num_vco = ARRAY_SIZE(mmpll_p_vco),
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll3_early",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv mmpll3 = {
+ .offset = 0x60,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll3",
+ .parent_hws = (const struct clk_hw *[]){ &mmpll3_early.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_alpha_pll mmpll4_early = {
+ .offset = 0x90,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .vco_table = mmpll_t_vco,
+ .num_vco = ARRAY_SIZE(mmpll_t_vco),
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll4_early",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv mmpll4 = {
+ .offset = 0x90,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .width = 2,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll4",
+ .parent_hws = (const struct clk_hw *[]){ &mmpll4_early.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct parent_map mmcc_xo_gpll0_mmpll1_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 5 },
+ { P_MMPLL1, 2 }
+};
+
+static const struct clk_parent_data mmcc_xo_gpll0_mmpll1[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "gpll0" },
+ { .hw = &mmpll1.clkr.hw },
+};
+
+static const struct parent_map mmcc_xo_gpll0_mmpll0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 5 },
+ { P_MMPLL0, 1 }
+};
+
+static const struct clk_parent_data mmcc_xo_gpll0_mmpll0[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "gpll0" },
+ { .hw = &mmpll0.clkr.hw },
+};
+
+static const struct parent_map mmcc_xo_gpll0_mmpll0_mmpll3_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 5 },
+ { P_MMPLL0, 1 },
+ { P_MMPLL3, 3 }
+};
+
+static const struct clk_parent_data mmcc_xo_gpll0_mmpll0_mmpll3[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "gpll0" },
+ { .hw = &mmpll0.clkr.hw },
+ { .hw = &mmpll3.clkr.hw },
+};
+
+static const struct parent_map mmcc_xo_gpll0_mmpll0_mmpll4_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 5 },
+ { P_MMPLL0, 1 },
+ { P_MMPLL4, 3 }
+};
+
+static const struct clk_parent_data mmcc_xo_gpll0_mmpll0_mmpll4[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "gpll0" },
+ { .hw = &mmpll0.clkr.hw },
+ { .hw = &mmpll4.clkr.hw },
+};
+
+static struct clk_alpha_pll mmpll5_early = {
+ .offset = 0xc0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .vco_table = mmpll_p_vco,
+ .num_vco = ARRAY_SIZE(mmpll_p_vco),
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll5_early",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv mmpll5 = {
+ .offset = 0xc0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll5",
+ .parent_hws = (const struct clk_hw *[]){ &mmpll5_early.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct freq_tbl ftbl_ahb_clk_src[] = {
+ /* Note: There might be more frequencies desired here. */
+ F(19200000, P_XO, 1, 0, 0),
+ F(40000000, P_GPLL0, 15, 0, 0),
+ F(80000000, P_MMPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ahb_clk_src = {
+ .cmd_rcgr = 0x5000,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_ahb_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ahb_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_axi_clk_src[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(333430000, P_MMPLL1, 3.5, 0, 0),
+ F(466800000, P_MMPLL1, 2.5, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_axi_clk_src_8992[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ F(404000000, P_MMPLL1, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 axi_clk_src = {
+ .cmd_rcgr = 0x5040,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll1_map,
+ .freq_tbl = ftbl_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "axi_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll1,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_csi0_1_2_3_clk_src[] = {
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_csi0_1_2_3_clk_src_8992[] = {
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 csi0_clk_src = {
+ .cmd_rcgr = 0x3090,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_csi0_1_2_3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi0_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_vcodec0_clk_src[] = {
+ F(66670000, P_GPLL0, 9, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(133330000, P_GPLL0, 4.5, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(510000000, P_MMPLL3, 2, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_vcodec0_clk_src_8992[] = {
+ F(66670000, P_GPLL0, 9, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(133330000, P_GPLL0, 4.5, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(510000000, P_MMPLL3, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vcodec0_clk_src = {
+ .cmd_rcgr = 0x1000,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_mmpll3_map,
+ .freq_tbl = ftbl_vcodec0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vcodec0_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0_mmpll3,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0_mmpll3),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi1_clk_src = {
+ .cmd_rcgr = 0x3100,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_csi0_1_2_3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi1_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi2_clk_src = {
+ .cmd_rcgr = 0x3160,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_csi0_1_2_3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi2_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi3_clk_src = {
+ .cmd_rcgr = 0x31c0,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_csi0_1_2_3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi3_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_vfe0_clk_src[] = {
+ F(80000000, P_GPLL0, 7.5, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ F(480000000, P_MMPLL4, 2, 0, 0),
+ F(533330000, P_MMPLL0, 1.5, 0, 0),
+ F(600000000, P_GPLL0, 1, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_vfe0_1_clk_src_8992[] = {
+ F(80000000, P_GPLL0, 7.5, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(480000000, P_MMPLL4, 2, 0, 0),
+ F(600000000, P_GPLL0, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vfe0_clk_src = {
+ .cmd_rcgr = 0x3600,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_mmpll4_map,
+ .freq_tbl = ftbl_vfe0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vfe0_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0_mmpll4,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0_mmpll4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_vfe1_clk_src[] = {
+ F(80000000, P_GPLL0, 7.5, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ F(533330000, P_MMPLL0, 1.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vfe1_clk_src = {
+ .cmd_rcgr = 0x3620,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_mmpll4_map,
+ .freq_tbl = ftbl_vfe1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vfe1_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0_mmpll4,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0_mmpll4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cpp_clk_src[] = {
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(480000000, P_MMPLL4, 2, 0, 0),
+ F(600000000, P_GPLL0, 1, 0, 0),
+ F(640000000, P_MMPLL4, 1.5, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_cpp_clk_src_8992[] = {
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(480000000, P_MMPLL4, 2, 0, 0),
+ F(640000000, P_MMPLL4, 1.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cpp_clk_src = {
+ .cmd_rcgr = 0x3640,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_mmpll4_map,
+ .freq_tbl = ftbl_cpp_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "cpp_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0_mmpll4,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0_mmpll4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_jpeg0_1_clk_src[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(228570000, P_MMPLL0, 3.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(480000000, P_MMPLL4, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 jpeg1_clk_src = {
+ .cmd_rcgr = 0x3520,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_mmpll4_map,
+ .freq_tbl = ftbl_jpeg0_1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "jpeg1_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0_mmpll4,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0_mmpll4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_jpeg2_clk_src[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(133330000, P_GPLL0, 4.5, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(228570000, P_MMPLL0, 3.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 jpeg2_clk_src = {
+ .cmd_rcgr = 0x3540,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_jpeg2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "jpeg2_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_csi2phytimer_clk_src[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 csi2phytimer_clk_src = {
+ .cmd_rcgr = 0x3060,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_csi2phytimer_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi2phytimer_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_fd_core_clk_src[] = {
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 fd_core_clk_src = {
+ .cmd_rcgr = 0x3b00,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_fd_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "fd_core_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mdp_clk_src[] = {
+ F(85710000, P_GPLL0, 7, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(120000000, P_GPLL0, 5, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(171430000, P_GPLL0, 3.5, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_mdp_clk_src_8992[] = {
+ F(85710000, P_GPLL0, 7, 0, 0),
+ F(171430000, P_GPLL0, 3.5, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdp_clk_src = {
+ .cmd_rcgr = 0x2040,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_mdp_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mdp_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 pclk0_clk_src = {
+ .cmd_rcgr = 0x2000,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsi0pll_dsi1pll_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pclk0_clk_src",
+ .parent_data = mmcc_xo_dsi0pll_dsi1pll,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsi0pll_dsi1pll),
+ .ops = &clk_pixel_ops,
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_rcg2 pclk1_clk_src = {
+ .cmd_rcgr = 0x2020,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsi0pll_dsi1pll_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pclk1_clk_src",
+ .parent_data = mmcc_xo_dsi0pll_dsi1pll,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsi0pll_dsi1pll),
+ .ops = &clk_pixel_ops,
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static const struct freq_tbl ftbl_ocmemnoc_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(228570000, P_MMPLL0, 3.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_ocmemnoc_clk_src_8992[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ocmemnoc_clk_src = {
+ .cmd_rcgr = 0x5090,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_ocmemnoc_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ocmemnoc_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cci_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(37500000, P_GPLL0, 16, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cci_clk_src = {
+ .cmd_rcgr = 0x3300,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_map,
+ .freq_tbl = ftbl_cci_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "cci_clk_src",
+ .parent_data = mmcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mmss_gp0_1_clk_src[] = {
+ F(10000, P_XO, 16, 10, 120),
+ F(24000, P_GPLL0, 16, 1, 50),
+ F(6000000, P_GPLL0, 10, 1, 10),
+ F(12000000, P_GPLL0, 10, 1, 5),
+ F(13000000, P_GPLL0, 4, 13, 150),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ { }
+};
+
+static struct clk_rcg2 mmss_gp0_clk_src = {
+ .cmd_rcgr = 0x3420,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_map,
+ .freq_tbl = ftbl_mmss_gp0_1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmss_gp0_clk_src",
+ .parent_data = mmcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 mmss_gp1_clk_src = {
+ .cmd_rcgr = 0x3450,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_map,
+ .freq_tbl = ftbl_mmss_gp0_1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmss_gp1_clk_src",
+ .parent_data = mmcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 jpeg0_clk_src = {
+ .cmd_rcgr = 0x3500,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_mmpll4_map,
+ .freq_tbl = ftbl_jpeg0_1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "jpeg0_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0_mmpll4,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0_mmpll4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 jpeg_dma_clk_src = {
+ .cmd_rcgr = 0x3560,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_mmpll4_map,
+ .freq_tbl = ftbl_jpeg0_1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "jpeg_dma_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0_mmpll4,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0_mmpll4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mclk0_1_2_3_clk_src[] = {
+ F(4800000, P_XO, 4, 0, 0),
+ F(6000000, P_GPLL0, 10, 1, 10),
+ F(8000000, P_GPLL0, 15, 1, 5),
+ F(9600000, P_XO, 2, 0, 0),
+ F(16000000, P_MMPLL0, 10, 1, 5),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ F(32000000, P_MMPLL0, 5, 1, 5),
+ F(48000000, P_GPLL0, 12.5, 0, 0),
+ F(64000000, P_MMPLL0, 12.5, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_mclk0_clk_src_8992[] = {
+ F(4800000, P_XO, 4, 0, 0),
+ F(6000000, P_MMPLL4, 10, 1, 16),
+ F(8000000, P_MMPLL4, 10, 1, 12),
+ F(9600000, P_XO, 2, 0, 0),
+ F(12000000, P_MMPLL4, 10, 1, 8),
+ F(16000000, P_MMPLL4, 10, 1, 6),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_MMPLL4, 10, 1, 4),
+ F(32000000, P_MMPLL4, 10, 1, 3),
+ F(48000000, P_MMPLL4, 10, 1, 2),
+ F(64000000, P_MMPLL4, 15, 0, 0),
+ { }
+};
+
+static const struct freq_tbl ftbl_mclk1_2_3_clk_src_8992[] = {
+ F(4800000, P_XO, 4, 0, 0),
+ F(6000000, P_MMPLL4, 10, 1, 16),
+ F(8000000, P_MMPLL4, 10, 1, 12),
+ F(9600000, P_XO, 2, 0, 0),
+ F(16000000, P_MMPLL4, 10, 1, 6),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_MMPLL4, 10, 1, 4),
+ F(32000000, P_MMPLL4, 10, 1, 3),
+ F(48000000, P_MMPLL4, 10, 1, 2),
+ F(64000000, P_MMPLL4, 15, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mclk0_clk_src = {
+ .cmd_rcgr = 0x3360,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_mclk0_1_2_3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mclk0_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 mclk1_clk_src = {
+ .cmd_rcgr = 0x3390,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_mclk0_1_2_3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mclk1_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 mclk2_clk_src = {
+ .cmd_rcgr = 0x33c0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_mclk0_1_2_3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mclk2_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 mclk3_clk_src = {
+ .cmd_rcgr = 0x33f0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_mclk0_1_2_3_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mclk3_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_csi0_1phytimer_clk_src[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 csi0phytimer_clk_src = {
+ .cmd_rcgr = 0x3000,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_csi0_1phytimer_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi0phytimer_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi1phytimer_clk_src = {
+ .cmd_rcgr = 0x3030,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_mmpll0_map,
+ .freq_tbl = ftbl_csi0_1phytimer_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi1phytimer_clk_src",
+ .parent_data = mmcc_xo_gpll0_mmpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0_mmpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 byte0_clk_src = {
+ .cmd_rcgr = 0x2120,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsibyte_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "byte0_clk_src",
+ .parent_data = mmcc_xo_dsibyte,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsibyte),
+ .ops = &clk_byte2_ops,
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_rcg2 byte1_clk_src = {
+ .cmd_rcgr = 0x2140,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsibyte_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "byte1_clk_src",
+ .parent_data = mmcc_xo_dsibyte,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsibyte),
+ .ops = &clk_byte2_ops,
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct freq_tbl ftbl_mdss_esc0_1_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 esc0_clk_src = {
+ .cmd_rcgr = 0x2160,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsibyte_map,
+ .freq_tbl = ftbl_mdss_esc0_1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "esc0_clk_src",
+ .parent_data = mmcc_xo_dsibyte,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsibyte),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 esc1_clk_src = {
+ .cmd_rcgr = 0x2180,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsibyte_map,
+ .freq_tbl = ftbl_mdss_esc0_1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "esc1_clk_src",
+ .parent_data = mmcc_xo_dsibyte,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsibyte),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl extpclk_freq_tbl[] = {
+ { .src = P_HDMIPLL },
+ { }
+};
+
+static struct clk_rcg2 extpclk_clk_src = {
+ .cmd_rcgr = 0x2060,
+ .hid_width = 5,
+ .parent_map = mmss_xo_hdmi_map,
+ .freq_tbl = extpclk_freq_tbl,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "extpclk_clk_src",
+ .parent_data = mmss_xo_hdmi,
+ .num_parents = ARRAY_SIZE(mmss_xo_hdmi),
+ .ops = &clk_rcg2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct freq_tbl ftbl_hdmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hdmi_clk_src = {
+ .cmd_rcgr = 0x2100,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_map,
+ .freq_tbl = ftbl_hdmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hdmi_clk_src",
+ .parent_data = mmcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_mdss_vsync_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vsync_clk_src = {
+ .cmd_rcgr = 0x2080,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_map,
+ .freq_tbl = ftbl_mdss_vsync_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vsync_clk_src",
+ .parent_data = mmcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_rbbmtimer_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 rbbmtimer_clk_src = {
+ .cmd_rcgr = 0x4090,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_gpll0_map,
+ .freq_tbl = ftbl_rbbmtimer_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "rbbmtimer_clk_src",
+ .parent_data = mmcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch camss_ahb_clk = {
+ .halt_reg = 0x348c,
+ .clkr = {
+ .enable_reg = 0x348c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_cci_cci_ahb_clk = {
+ .halt_reg = 0x3348,
+ .clkr = {
+ .enable_reg = 0x3348,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_cci_cci_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_cci_cci_clk = {
+ .halt_reg = 0x3344,
+ .clkr = {
+ .enable_reg = 0x3344,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_cci_cci_clk",
+ .parent_hws = (const struct clk_hw *[]){ &cci_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_cpp_ahb_clk = {
+ .halt_reg = 0x36b4,
+ .clkr = {
+ .enable_reg = 0x36b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_cpp_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_cpp_axi_clk = {
+ .halt_reg = 0x36c4,
+ .clkr = {
+ .enable_reg = 0x36c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_cpp_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &axi_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_cpp_clk = {
+ .halt_reg = 0x36b0,
+ .clkr = {
+ .enable_reg = 0x36b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_cpp_clk",
+ .parent_hws = (const struct clk_hw *[]){ &cpp_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0_ahb_clk = {
+ .halt_reg = 0x30bc,
+ .clkr = {
+ .enable_reg = 0x30bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0_clk = {
+ .halt_reg = 0x30b4,
+ .clkr = {
+ .enable_reg = 0x30b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0phy_clk = {
+ .halt_reg = 0x30c4,
+ .clkr = {
+ .enable_reg = 0x30c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0phy_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0pix_clk = {
+ .halt_reg = 0x30e4,
+ .clkr = {
+ .enable_reg = 0x30e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0pix_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0rdi_clk = {
+ .halt_reg = 0x30d4,
+ .clkr = {
+ .enable_reg = 0x30d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0rdi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1_ahb_clk = {
+ .halt_reg = 0x3128,
+ .clkr = {
+ .enable_reg = 0x3128,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1_clk = {
+ .halt_reg = 0x3124,
+ .clkr = {
+ .enable_reg = 0x3124,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1phy_clk = {
+ .halt_reg = 0x3134,
+ .clkr = {
+ .enable_reg = 0x3134,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1phy_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1pix_clk = {
+ .halt_reg = 0x3154,
+ .clkr = {
+ .enable_reg = 0x3154,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1pix_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1rdi_clk = {
+ .halt_reg = 0x3144,
+ .clkr = {
+ .enable_reg = 0x3144,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1rdi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2_ahb_clk = {
+ .halt_reg = 0x3188,
+ .clkr = {
+ .enable_reg = 0x3188,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2_clk = {
+ .halt_reg = 0x3184,
+ .clkr = {
+ .enable_reg = 0x3184,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2phy_clk = {
+ .halt_reg = 0x3194,
+ .clkr = {
+ .enable_reg = 0x3194,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2phy_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2pix_clk = {
+ .halt_reg = 0x31b4,
+ .clkr = {
+ .enable_reg = 0x31b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2pix_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2rdi_clk = {
+ .halt_reg = 0x31a4,
+ .clkr = {
+ .enable_reg = 0x31a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2rdi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3_ahb_clk = {
+ .halt_reg = 0x31e8,
+ .clkr = {
+ .enable_reg = 0x31e8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3_clk = {
+ .halt_reg = 0x31e4,
+ .clkr = {
+ .enable_reg = 0x31e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3phy_clk = {
+ .halt_reg = 0x31f4,
+ .clkr = {
+ .enable_reg = 0x31f4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3phy_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3pix_clk = {
+ .halt_reg = 0x3214,
+ .clkr = {
+ .enable_reg = 0x3214,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3pix_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3rdi_clk = {
+ .halt_reg = 0x3204,
+ .clkr = {
+ .enable_reg = 0x3204,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3rdi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi_vfe0_clk = {
+ .halt_reg = 0x3704,
+ .clkr = {
+ .enable_reg = 0x3704,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi_vfe0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vfe0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi_vfe1_clk = {
+ .halt_reg = 0x3714,
+ .clkr = {
+ .enable_reg = 0x3714,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi_vfe1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vfe1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_gp0_clk = {
+ .halt_reg = 0x3444,
+ .clkr = {
+ .enable_reg = 0x3444,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_gp0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &mmss_gp0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_gp1_clk = {
+ .halt_reg = 0x3474,
+ .clkr = {
+ .enable_reg = 0x3474,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_gp1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &mmss_gp1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_ispif_ahb_clk = {
+ .halt_reg = 0x3224,
+ .clkr = {
+ .enable_reg = 0x3224,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_ispif_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_dma_clk = {
+ .halt_reg = 0x35c0,
+ .clkr = {
+ .enable_reg = 0x35c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_dma_clk",
+ .parent_hws = (const struct clk_hw *[]){ &jpeg_dma_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg0_clk = {
+ .halt_reg = 0x35a8,
+ .clkr = {
+ .enable_reg = 0x35a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &jpeg0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg1_clk = {
+ .halt_reg = 0x35ac,
+ .clkr = {
+ .enable_reg = 0x35ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &jpeg1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg2_clk = {
+ .halt_reg = 0x35b0,
+ .clkr = {
+ .enable_reg = 0x35b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg2_clk",
+ .parent_hws = (const struct clk_hw *[]){ &jpeg2_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg_ahb_clk = {
+ .halt_reg = 0x35b4,
+ .clkr = {
+ .enable_reg = 0x35b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg_axi_clk = {
+ .halt_reg = 0x35b8,
+ .clkr = {
+ .enable_reg = 0x35b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &axi_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_mclk0_clk = {
+ .halt_reg = 0x3384,
+ .clkr = {
+ .enable_reg = 0x3384,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_mclk0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &mclk0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_mclk1_clk = {
+ .halt_reg = 0x33b4,
+ .clkr = {
+ .enable_reg = 0x33b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_mclk1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &mclk1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_mclk2_clk = {
+ .halt_reg = 0x33e4,
+ .clkr = {
+ .enable_reg = 0x33e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_mclk2_clk",
+ .parent_hws = (const struct clk_hw *[]){ &mclk2_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_mclk3_clk = {
+ .halt_reg = 0x3414,
+ .clkr = {
+ .enable_reg = 0x3414,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_mclk3_clk",
+ .parent_hws = (const struct clk_hw *[]){ &mclk3_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_micro_ahb_clk = {
+ .halt_reg = 0x3494,
+ .clkr = {
+ .enable_reg = 0x3494,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_micro_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_phy0_csi0phytimer_clk = {
+ .halt_reg = 0x3024,
+ .clkr = {
+ .enable_reg = 0x3024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_phy0_csi0phytimer_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi0phytimer_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_phy1_csi1phytimer_clk = {
+ .halt_reg = 0x3054,
+ .clkr = {
+ .enable_reg = 0x3054,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_phy1_csi1phytimer_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi1phytimer_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_phy2_csi2phytimer_clk = {
+ .halt_reg = 0x3084,
+ .clkr = {
+ .enable_reg = 0x3084,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_phy2_csi2phytimer_clk",
+ .parent_hws = (const struct clk_hw *[]){ &csi2phytimer_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_top_ahb_clk = {
+ .halt_reg = 0x3484,
+ .clkr = {
+ .enable_reg = 0x3484,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_top_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_vfe0_clk = {
+ .halt_reg = 0x36a8,
+ .clkr = {
+ .enable_reg = 0x36a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_vfe0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vfe0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_vfe1_clk = {
+ .halt_reg = 0x36ac,
+ .clkr = {
+ .enable_reg = 0x36ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_vfe1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vfe1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_vfe_ahb_clk = {
+ .halt_reg = 0x36b8,
+ .clkr = {
+ .enable_reg = 0x36b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_vfe_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_vfe_axi_clk = {
+ .halt_reg = 0x36bc,
+ .clkr = {
+ .enable_reg = 0x36bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_vfe_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &axi_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch fd_ahb_clk = {
+ .halt_reg = 0x3b74,
+ .clkr = {
+ .enable_reg = 0x3b74,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "fd_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch fd_axi_clk = {
+ .halt_reg = 0x3b70,
+ .clkr = {
+ .enable_reg = 0x3b70,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "fd_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &axi_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch fd_core_clk = {
+ .halt_reg = 0x3b68,
+ .clkr = {
+ .enable_reg = 0x3b68,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "fd_core_clk",
+ .parent_hws = (const struct clk_hw *[]){ &fd_core_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch fd_core_uar_clk = {
+ .halt_reg = 0x3b6c,
+ .clkr = {
+ .enable_reg = 0x3b6c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "fd_core_uar_clk",
+ .parent_hws = (const struct clk_hw *[]){ &fd_core_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_ahb_clk = {
+ .halt_reg = 0x2308,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2308,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_axi_clk = {
+ .halt_reg = 0x2310,
+ .clkr = {
+ .enable_reg = 0x2310,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &axi_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_byte0_clk = {
+ .halt_reg = 0x233c,
+ .clkr = {
+ .enable_reg = 0x233c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_byte0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &byte0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_byte1_clk = {
+ .halt_reg = 0x2340,
+ .clkr = {
+ .enable_reg = 0x2340,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_byte1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &byte1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_esc0_clk = {
+ .halt_reg = 0x2344,
+ .clkr = {
+ .enable_reg = 0x2344,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_esc0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &esc0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_esc1_clk = {
+ .halt_reg = 0x2348,
+ .clkr = {
+ .enable_reg = 0x2348,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_esc1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &esc1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_extpclk_clk = {
+ .halt_reg = 0x2324,
+ .clkr = {
+ .enable_reg = 0x2324,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_extpclk_clk",
+ .parent_hws = (const struct clk_hw *[]){ &extpclk_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_hdmi_ahb_clk = {
+ .halt_reg = 0x230c,
+ .clkr = {
+ .enable_reg = 0x230c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_hdmi_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_hdmi_clk = {
+ .halt_reg = 0x2338,
+ .clkr = {
+ .enable_reg = 0x2338,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_hdmi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &hdmi_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_mdp_clk = {
+ .halt_reg = 0x231c,
+ .clkr = {
+ .enable_reg = 0x231c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_mdp_clk",
+ .parent_hws = (const struct clk_hw *[]){ &mdp_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_pclk0_clk = {
+ .halt_reg = 0x2314,
+ .clkr = {
+ .enable_reg = 0x2314,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_pclk0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &pclk0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_pclk1_clk = {
+ .halt_reg = 0x2318,
+ .clkr = {
+ .enable_reg = 0x2318,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_pclk1_clk",
+ .parent_hws = (const struct clk_hw *[]){ &pclk1_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_vsync_clk = {
+ .halt_reg = 0x2328,
+ .clkr = {
+ .enable_reg = 0x2328,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_vsync_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vsync_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_misc_ahb_clk = {
+ .halt_reg = 0x502c,
+ .clkr = {
+ .enable_reg = 0x502c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_misc_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_mmssnoc_axi_clk = {
+ .halt_reg = 0x506c,
+ .clkr = {
+ .enable_reg = 0x506c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_mmssnoc_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &axi_clk_src.clkr.hw },
+ .num_parents = 1,
+ /* Gating this clock will wreck havoc among MMSS! */
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_s0_axi_clk = {
+ .halt_reg = 0x5064,
+ .clkr = {
+ .enable_reg = 0x5064,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_s0_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &axi_clk_src.clkr.hw, },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch ocmemcx_ocmemnoc_clk = {
+ .halt_reg = 0x4058,
+ .clkr = {
+ .enable_reg = 0x4058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "ocmemcx_ocmemnoc_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ocmemnoc_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch oxili_gfx3d_clk = {
+ .halt_reg = 0x4028,
+ .clkr = {
+ .enable_reg = 0x4028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "oxili_gfx3d_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "oxili_gfx3d_clk_src",
+ .name = "oxili_gfx3d_clk_src"
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch oxili_rbbmtimer_clk = {
+ .halt_reg = 0x40b0,
+ .clkr = {
+ .enable_reg = 0x40b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "oxili_rbbmtimer_clk",
+ .parent_hws = (const struct clk_hw *[]){ &rbbmtimer_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch oxilicx_ahb_clk = {
+ .halt_reg = 0x403c,
+ .clkr = {
+ .enable_reg = 0x403c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "oxilicx_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_ahb_clk = {
+ .halt_reg = 0x1030,
+ .clkr = {
+ .enable_reg = 0x1030,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ahb_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_axi_clk = {
+ .halt_reg = 0x1034,
+ .clkr = {
+ .enable_reg = 0x1034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_axi_clk",
+ .parent_hws = (const struct clk_hw *[]){ &axi_clk_src.clkr.hw },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_ocmemnoc_clk = {
+ .halt_reg = 0x1038,
+ .clkr = {
+ .enable_reg = 0x1038,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_ocmemnoc_clk",
+ .parent_hws = (const struct clk_hw *[]){ &ocmemnoc_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_vcodec0_clk = {
+ .halt_reg = 0x1028,
+ .clkr = {
+ .enable_reg = 0x1028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_vcodec0_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vcodec0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_core0_vcodec_clk = {
+ .halt_reg = 0x1048,
+ .clkr = {
+ .enable_reg = 0x1048,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_core0_vcodec_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vcodec0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_core1_vcodec_clk = {
+ .halt_reg = 0x104c,
+ .clkr = {
+ .enable_reg = 0x104c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_core1_vcodec_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vcodec0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_core2_vcodec_clk = {
+ .halt_reg = 0x1054,
+ .clkr = {
+ .enable_reg = 0x1054,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_core2_vcodec_clk",
+ .parent_hws = (const struct clk_hw *[]){ &vcodec0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc venus_gdsc = {
+ .gdscr = 0x1024,
+ .cxcs = (unsigned int []){ 0x1038, 0x1034, 0x1048 },
+ .cxc_count = 3,
+ .pd = {
+ .name = "venus_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc venus_core0_gdsc = {
+ .gdscr = 0x1040,
+ .cxcs = (unsigned int []){ 0x1048 },
+ .cxc_count = 1,
+ .pd = {
+ .name = "venus_core0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
+};
+
+static struct gdsc venus_core1_gdsc = {
+ .gdscr = 0x1044,
+ .cxcs = (unsigned int []){ 0x104c },
+ .cxc_count = 1,
+ .pd = {
+ .name = "venus_core1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
+};
+
+static struct gdsc venus_core2_gdsc = {
+ .gdscr = 0x1050,
+ .cxcs = (unsigned int []){ 0x1054 },
+ .cxc_count = 1,
+ .pd = {
+ .name = "venus_core2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
+};
+
+static struct gdsc mdss_gdsc = {
+ .gdscr = 0x2304,
+ .cxcs = (unsigned int []){ 0x2310, 0x231c },
+ .cxc_count = 2,
+ .pd = {
+ .name = "mdss_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc camss_top_gdsc = {
+ .gdscr = 0x34a0,
+ .cxcs = (unsigned int []){ 0x3704, 0x3714, 0x3494 },
+ .cxc_count = 3,
+ .pd = {
+ .name = "camss_top_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc jpeg_gdsc = {
+ .gdscr = 0x35a4,
+ .cxcs = (unsigned int []){ 0x35a8 },
+ .cxc_count = 1,
+ .pd = {
+ .name = "jpeg_gdsc",
+ },
+ .parent = &camss_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc vfe_gdsc = {
+ .gdscr = 0x36a4,
+ .cxcs = (unsigned int []){ 0x36bc },
+ .cxc_count = 1,
+ .pd = {
+ .name = "vfe_gdsc",
+ },
+ .parent = &camss_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc cpp_gdsc = {
+ .gdscr = 0x36d4,
+ .cxcs = (unsigned int []){ 0x36c4, 0x36b0 },
+ .cxc_count = 2,
+ .pd = {
+ .name = "cpp_gdsc",
+ },
+ .parent = &camss_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc fd_gdsc = {
+ .gdscr = 0x3b64,
+ .cxcs = (unsigned int []){ 0x3b70, 0x3b68 },
+ .pd = {
+ .name = "fd_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc oxili_cx_gdsc = {
+ .gdscr = 0x4034,
+ .pd = {
+ .name = "oxili_cx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc oxili_gx_gdsc = {
+ .gdscr = 0x4024,
+ .cxcs = (unsigned int []){ 0x4028 },
+ .cxc_count = 1,
+ .pd = {
+ .name = "oxili_gx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &oxili_cx_gdsc.pd,
+ .flags = CLAMP_IO,
+ .supply = "VDD_GFX",
+};
+
+static struct clk_regmap *mmcc_msm8994_clocks[] = {
+ [MMPLL0_EARLY] = &mmpll0_early.clkr,
+ [MMPLL0_PLL] = &mmpll0.clkr,
+ [MMPLL1_EARLY] = &mmpll1_early.clkr,
+ [MMPLL1_PLL] = &mmpll1.clkr,
+ [MMPLL3_EARLY] = &mmpll3_early.clkr,
+ [MMPLL3_PLL] = &mmpll3.clkr,
+ [MMPLL4_EARLY] = &mmpll4_early.clkr,
+ [MMPLL4_PLL] = &mmpll4.clkr,
+ [MMPLL5_EARLY] = &mmpll5_early.clkr,
+ [MMPLL5_PLL] = &mmpll5.clkr,
+ [AHB_CLK_SRC] = &ahb_clk_src.clkr,
+ [AXI_CLK_SRC] = &axi_clk_src.clkr,
+ [CSI0_CLK_SRC] = &csi0_clk_src.clkr,
+ [CSI1_CLK_SRC] = &csi1_clk_src.clkr,
+ [CSI2_CLK_SRC] = &csi2_clk_src.clkr,
+ [CSI3_CLK_SRC] = &csi3_clk_src.clkr,
+ [VFE0_CLK_SRC] = &vfe0_clk_src.clkr,
+ [VFE1_CLK_SRC] = &vfe1_clk_src.clkr,
+ [CPP_CLK_SRC] = &cpp_clk_src.clkr,
+ [JPEG0_CLK_SRC] = &jpeg0_clk_src.clkr,
+ [JPEG1_CLK_SRC] = &jpeg1_clk_src.clkr,
+ [JPEG2_CLK_SRC] = &jpeg2_clk_src.clkr,
+ [CSI2PHYTIMER_CLK_SRC] = &csi2phytimer_clk_src.clkr,
+ [FD_CORE_CLK_SRC] = &fd_core_clk_src.clkr,
+ [MDP_CLK_SRC] = &mdp_clk_src.clkr,
+ [PCLK0_CLK_SRC] = &pclk0_clk_src.clkr,
+ [PCLK1_CLK_SRC] = &pclk1_clk_src.clkr,
+ [OCMEMNOC_CLK_SRC] = &ocmemnoc_clk_src.clkr,
+ [CCI_CLK_SRC] = &cci_clk_src.clkr,
+ [MMSS_GP0_CLK_SRC] = &mmss_gp0_clk_src.clkr,
+ [MMSS_GP1_CLK_SRC] = &mmss_gp1_clk_src.clkr,
+ [JPEG_DMA_CLK_SRC] = &jpeg_dma_clk_src.clkr,
+ [MCLK0_CLK_SRC] = &mclk0_clk_src.clkr,
+ [MCLK1_CLK_SRC] = &mclk1_clk_src.clkr,
+ [MCLK2_CLK_SRC] = &mclk2_clk_src.clkr,
+ [MCLK3_CLK_SRC] = &mclk3_clk_src.clkr,
+ [CSI0PHYTIMER_CLK_SRC] = &csi0phytimer_clk_src.clkr,
+ [CSI1PHYTIMER_CLK_SRC] = &csi1phytimer_clk_src.clkr,
+ [BYTE0_CLK_SRC] = &byte0_clk_src.clkr,
+ [BYTE1_CLK_SRC] = &byte1_clk_src.clkr,
+ [ESC0_CLK_SRC] = &esc0_clk_src.clkr,
+ [ESC1_CLK_SRC] = &esc1_clk_src.clkr,
+ [MDSS_ESC0_CLK] = &mdss_esc0_clk.clkr,
+ [MDSS_ESC1_CLK] = &mdss_esc1_clk.clkr,
+ [EXTPCLK_CLK_SRC] = &extpclk_clk_src.clkr,
+ [HDMI_CLK_SRC] = &hdmi_clk_src.clkr,
+ [VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
+ [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,
+ [CAMSS_AHB_CLK] = &camss_ahb_clk.clkr,
+ [CAMSS_CCI_CCI_AHB_CLK] = &camss_cci_cci_ahb_clk.clkr,
+ [CAMSS_CCI_CCI_CLK] = &camss_cci_cci_clk.clkr,
+ [CAMSS_VFE_CPP_AHB_CLK] = &camss_vfe_cpp_ahb_clk.clkr,
+ [CAMSS_VFE_CPP_AXI_CLK] = &camss_vfe_cpp_axi_clk.clkr,
+ [CAMSS_VFE_CPP_CLK] = &camss_vfe_cpp_clk.clkr,
+ [CAMSS_CSI0_AHB_CLK] = &camss_csi0_ahb_clk.clkr,
+ [CAMSS_CSI0_CLK] = &camss_csi0_clk.clkr,
+ [CAMSS_CSI0PHY_CLK] = &camss_csi0phy_clk.clkr,
+ [CAMSS_CSI0PIX_CLK] = &camss_csi0pix_clk.clkr,
+ [CAMSS_CSI0RDI_CLK] = &camss_csi0rdi_clk.clkr,
+ [CAMSS_CSI1_AHB_CLK] = &camss_csi1_ahb_clk.clkr,
+ [CAMSS_CSI1_CLK] = &camss_csi1_clk.clkr,
+ [CAMSS_CSI1PHY_CLK] = &camss_csi1phy_clk.clkr,
+ [CAMSS_CSI1PIX_CLK] = &camss_csi1pix_clk.clkr,
+ [CAMSS_CSI1RDI_CLK] = &camss_csi1rdi_clk.clkr,
+ [CAMSS_CSI2_AHB_CLK] = &camss_csi2_ahb_clk.clkr,
+ [CAMSS_CSI2_CLK] = &camss_csi2_clk.clkr,
+ [CAMSS_CSI2PHY_CLK] = &camss_csi2phy_clk.clkr,
+ [CAMSS_CSI2PIX_CLK] = &camss_csi2pix_clk.clkr,
+ [CAMSS_CSI2RDI_CLK] = &camss_csi2rdi_clk.clkr,
+ [CAMSS_CSI3_AHB_CLK] = &camss_csi3_ahb_clk.clkr,
+ [CAMSS_CSI3_CLK] = &camss_csi3_clk.clkr,
+ [CAMSS_CSI3PHY_CLK] = &camss_csi3phy_clk.clkr,
+ [CAMSS_CSI3PIX_CLK] = &camss_csi3pix_clk.clkr,
+ [CAMSS_CSI3RDI_CLK] = &camss_csi3rdi_clk.clkr,
+ [CAMSS_CSI_VFE0_CLK] = &camss_csi_vfe0_clk.clkr,
+ [CAMSS_CSI_VFE1_CLK] = &camss_csi_vfe1_clk.clkr,
+ [CAMSS_GP0_CLK] = &camss_gp0_clk.clkr,
+ [CAMSS_GP1_CLK] = &camss_gp1_clk.clkr,
+ [CAMSS_ISPIF_AHB_CLK] = &camss_ispif_ahb_clk.clkr,
+ [CAMSS_JPEG_DMA_CLK] = &camss_jpeg_dma_clk.clkr,
+ [CAMSS_JPEG_JPEG0_CLK] = &camss_jpeg_jpeg0_clk.clkr,
+ [CAMSS_JPEG_JPEG1_CLK] = &camss_jpeg_jpeg1_clk.clkr,
+ [CAMSS_JPEG_JPEG2_CLK] = &camss_jpeg_jpeg2_clk.clkr,
+ [CAMSS_JPEG_JPEG_AHB_CLK] = &camss_jpeg_jpeg_ahb_clk.clkr,
+ [CAMSS_JPEG_JPEG_AXI_CLK] = &camss_jpeg_jpeg_axi_clk.clkr,
+ [CAMSS_MCLK0_CLK] = &camss_mclk0_clk.clkr,
+ [CAMSS_MCLK1_CLK] = &camss_mclk1_clk.clkr,
+ [CAMSS_MCLK2_CLK] = &camss_mclk2_clk.clkr,
+ [CAMSS_MCLK3_CLK] = &camss_mclk3_clk.clkr,
+ [CAMSS_MICRO_AHB_CLK] = &camss_micro_ahb_clk.clkr,
+ [CAMSS_PHY0_CSI0PHYTIMER_CLK] = &camss_phy0_csi0phytimer_clk.clkr,
+ [CAMSS_PHY1_CSI1PHYTIMER_CLK] = &camss_phy1_csi1phytimer_clk.clkr,
+ [CAMSS_PHY2_CSI2PHYTIMER_CLK] = &camss_phy2_csi2phytimer_clk.clkr,
+ [CAMSS_TOP_AHB_CLK] = &camss_top_ahb_clk.clkr,
+ [CAMSS_VFE_VFE0_CLK] = &camss_vfe_vfe0_clk.clkr,
+ [CAMSS_VFE_VFE1_CLK] = &camss_vfe_vfe1_clk.clkr,
+ [CAMSS_VFE_VFE_AHB_CLK] = &camss_vfe_vfe_ahb_clk.clkr,
+ [CAMSS_VFE_VFE_AXI_CLK] = &camss_vfe_vfe_axi_clk.clkr,
+ [FD_AHB_CLK] = &fd_ahb_clk.clkr,
+ [FD_AXI_CLK] = &fd_axi_clk.clkr,
+ [FD_CORE_CLK] = &fd_core_clk.clkr,
+ [FD_CORE_UAR_CLK] = &fd_core_uar_clk.clkr,
+ [MDSS_AHB_CLK] = &mdss_ahb_clk.clkr,
+ [MDSS_AXI_CLK] = &mdss_axi_clk.clkr,
+ [MDSS_BYTE0_CLK] = &mdss_byte0_clk.clkr,
+ [MDSS_BYTE1_CLK] = &mdss_byte1_clk.clkr,
+ [MDSS_EXTPCLK_CLK] = &mdss_extpclk_clk.clkr,
+ [MDSS_HDMI_AHB_CLK] = &mdss_hdmi_ahb_clk.clkr,
+ [MDSS_HDMI_CLK] = &mdss_hdmi_clk.clkr,
+ [MDSS_MDP_CLK] = &mdss_mdp_clk.clkr,
+ [MDSS_PCLK0_CLK] = &mdss_pclk0_clk.clkr,
+ [MDSS_PCLK1_CLK] = &mdss_pclk1_clk.clkr,
+ [MDSS_VSYNC_CLK] = &mdss_vsync_clk.clkr,
+ [MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr,
+ [MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr,
+ [MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr,
+ [OCMEMCX_OCMEMNOC_CLK] = &ocmemcx_ocmemnoc_clk.clkr,
+ [OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr,
+ [OXILI_RBBMTIMER_CLK] = &oxili_rbbmtimer_clk.clkr,
+ [OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr,
+ [VENUS0_AHB_CLK] = &venus0_ahb_clk.clkr,
+ [VENUS0_AXI_CLK] = &venus0_axi_clk.clkr,
+ [VENUS0_OCMEMNOC_CLK] = &venus0_ocmemnoc_clk.clkr,
+ [VENUS0_VCODEC0_CLK] = &venus0_vcodec0_clk.clkr,
+ [VENUS0_CORE0_VCODEC_CLK] = &venus0_core0_vcodec_clk.clkr,
+ [VENUS0_CORE1_VCODEC_CLK] = &venus0_core1_vcodec_clk.clkr,
+ [VENUS0_CORE2_VCODEC_CLK] = &venus0_core2_vcodec_clk.clkr,
+};
+
+static struct gdsc *mmcc_msm8994_gdscs[] = {
+ [VENUS_GDSC] = &venus_gdsc,
+ [VENUS_CORE0_GDSC] = &venus_core0_gdsc,
+ [VENUS_CORE1_GDSC] = &venus_core1_gdsc,
+ [VENUS_CORE2_GDSC] = &venus_core2_gdsc,
+ [CAMSS_TOP_GDSC] = &camss_top_gdsc,
+ [MDSS_GDSC] = &mdss_gdsc,
+ [JPEG_GDSC] = &jpeg_gdsc,
+ [VFE_GDSC] = &vfe_gdsc,
+ [CPP_GDSC] = &cpp_gdsc,
+ [OXILI_GX_GDSC] = &oxili_gx_gdsc,
+ [OXILI_CX_GDSC] = &oxili_cx_gdsc,
+ [FD_GDSC] = &fd_gdsc,
+};
+
+static const struct qcom_reset_map mmcc_msm8994_resets[] = {
+ [CAMSS_MICRO_BCR] = { 0x3490 },
+};
+
+static const struct regmap_config mmcc_msm8994_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x5200,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc mmcc_msm8994_desc = {
+ .config = &mmcc_msm8994_regmap_config,
+ .clks = mmcc_msm8994_clocks,
+ .num_clks = ARRAY_SIZE(mmcc_msm8994_clocks),
+ .resets = mmcc_msm8994_resets,
+ .num_resets = ARRAY_SIZE(mmcc_msm8994_resets),
+ .gdscs = mmcc_msm8994_gdscs,
+ .num_gdscs = ARRAY_SIZE(mmcc_msm8994_gdscs),
+};
+
+static const struct of_device_id mmcc_msm8994_match_table[] = {
+ { .compatible = "qcom,mmcc-msm8992" },
+ { .compatible = "qcom,mmcc-msm8994" }, /* V2 and V2.1 */
+ { }
+};
+MODULE_DEVICE_TABLE(of, mmcc_msm8994_match_table);
+
+static int mmcc_msm8994_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,mmcc-msm8992")) {
+ /* MSM8992 features less clocks and some have different freq tables */
+ mmcc_msm8994_desc.clks[CAMSS_JPEG_JPEG1_CLK] = NULL;
+ mmcc_msm8994_desc.clks[CAMSS_JPEG_JPEG2_CLK] = NULL;
+ mmcc_msm8994_desc.clks[FD_CORE_CLK_SRC] = NULL;
+ mmcc_msm8994_desc.clks[FD_CORE_CLK] = NULL;
+ mmcc_msm8994_desc.clks[FD_CORE_UAR_CLK] = NULL;
+ mmcc_msm8994_desc.clks[FD_AXI_CLK] = NULL;
+ mmcc_msm8994_desc.clks[FD_AHB_CLK] = NULL;
+ mmcc_msm8994_desc.clks[JPEG1_CLK_SRC] = NULL;
+ mmcc_msm8994_desc.clks[JPEG2_CLK_SRC] = NULL;
+ mmcc_msm8994_desc.clks[VENUS0_CORE2_VCODEC_CLK] = NULL;
+
+ mmcc_msm8994_desc.gdscs[FD_GDSC] = NULL;
+ mmcc_msm8994_desc.gdscs[VENUS_CORE2_GDSC] = NULL;
+
+ axi_clk_src.freq_tbl = ftbl_axi_clk_src_8992;
+ cpp_clk_src.freq_tbl = ftbl_cpp_clk_src_8992;
+ csi0_clk_src.freq_tbl = ftbl_csi0_1_2_3_clk_src_8992;
+ csi1_clk_src.freq_tbl = ftbl_csi0_1_2_3_clk_src_8992;
+ csi2_clk_src.freq_tbl = ftbl_csi0_1_2_3_clk_src_8992;
+ csi3_clk_src.freq_tbl = ftbl_csi0_1_2_3_clk_src_8992;
+ mclk0_clk_src.freq_tbl = ftbl_mclk0_clk_src_8992;
+ mclk1_clk_src.freq_tbl = ftbl_mclk1_2_3_clk_src_8992;
+ mclk2_clk_src.freq_tbl = ftbl_mclk1_2_3_clk_src_8992;
+ mclk3_clk_src.freq_tbl = ftbl_mclk1_2_3_clk_src_8992;
+ mdp_clk_src.freq_tbl = ftbl_mdp_clk_src_8992;
+ ocmemnoc_clk_src.freq_tbl = ftbl_ocmemnoc_clk_src_8992;
+ vcodec0_clk_src.freq_tbl = ftbl_vcodec0_clk_src_8992;
+ vfe0_clk_src.freq_tbl = ftbl_vfe0_1_clk_src_8992;
+ vfe1_clk_src.freq_tbl = ftbl_vfe0_1_clk_src_8992;
+ }
+
+ regmap = qcom_cc_map(pdev, &mmcc_msm8994_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_alpha_pll_configure(&mmpll0_early, regmap, &mmpll_p_config);
+ clk_alpha_pll_configure(&mmpll1_early, regmap, &mmpll_p_config);
+ clk_alpha_pll_configure(&mmpll3_early, regmap, &mmpll_p_config);
+ clk_alpha_pll_configure(&mmpll5_early, regmap, &mmpll_p_config);
+
+ return qcom_cc_really_probe(pdev, &mmcc_msm8994_desc, regmap);
+}
+
+static struct platform_driver mmcc_msm8994_driver = {
+ .probe = mmcc_msm8994_probe,
+ .driver = {
+ .name = "mmcc-msm8994",
+ .of_match_table = mmcc_msm8994_match_table,
+ },
+};
+module_platform_driver(mmcc_msm8994_driver);
+
+MODULE_DESCRIPTION("QCOM MMCC MSM8994 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mmcc-msm8994");
diff --git a/drivers/clk/qcom/mss-sc7180.c b/drivers/clk/qcom/mss-sc7180.c
index 673fa1a4f734..5a1407440662 100644
--- a/drivers/clk/qcom/mss-sc7180.c
+++ b/drivers/clk/qcom/mss-sc7180.c
@@ -73,36 +73,23 @@ static int mss_sc7180_probe(struct platform_device *pdev)
{
int ret;
- pm_runtime_enable(&pdev->dev);
- ret = pm_clk_create(&pdev->dev);
+ ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
- goto disable_pm_runtime;
+ return ret;
+
+ ret = devm_pm_clk_create(&pdev->dev);
+ if (ret)
+ return ret;
ret = pm_clk_add(&pdev->dev, "cfg_ahb");
if (ret < 0) {
dev_err(&pdev->dev, "failed to acquire iface clock\n");
- goto destroy_pm_clk;
+ return ret;
}
ret = qcom_cc_probe(pdev, &mss_sc7180_desc);
if (ret < 0)
- goto destroy_pm_clk;
-
- return 0;
-
-destroy_pm_clk:
- pm_clk_destroy(&pdev->dev);
-
-disable_pm_runtime:
- pm_runtime_disable(&pdev->dev);
-
- return ret;
-}
-
-static int mss_sc7180_remove(struct platform_device *pdev)
-{
- pm_clk_destroy(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
+ return ret;
return 0;
}
@@ -119,7 +106,6 @@ MODULE_DEVICE_TABLE(of, mss_sc7180_match_table);
static struct platform_driver mss_sc7180_driver = {
.probe = mss_sc7180_probe,
- .remove = mss_sc7180_remove,
.driver = {
.name = "sc7180-mss",
.of_match_table = mss_sc7180_match_table,
diff --git a/drivers/clk/qcom/q6sstop-qcs404.c b/drivers/clk/qcom/q6sstop-qcs404.c
index 723f932fbf7d..507386bee07d 100644
--- a/drivers/clk/qcom/q6sstop-qcs404.c
+++ b/drivers/clk/qcom/q6sstop-qcs404.c
@@ -159,15 +159,18 @@ static int q6sstopcc_qcs404_probe(struct platform_device *pdev)
const struct qcom_cc_desc *desc;
int ret;
- pm_runtime_enable(&pdev->dev);
- ret = pm_clk_create(&pdev->dev);
+ ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
- goto disable_pm_runtime;
+ return ret;
+
+ ret = devm_pm_clk_create(&pdev->dev);
+ if (ret)
+ return ret;
ret = pm_clk_add(&pdev->dev, NULL);
if (ret < 0) {
dev_err(&pdev->dev, "failed to acquire iface clock\n");
- goto destroy_pm_clk;
+ return ret;
}
q6sstop_regmap_config.name = "q6sstop_tcsr";
@@ -175,30 +178,14 @@ static int q6sstopcc_qcs404_probe(struct platform_device *pdev)
ret = qcom_cc_probe_by_index(pdev, 1, desc);
if (ret)
- goto destroy_pm_clk;
+ return ret;
q6sstop_regmap_config.name = "q6sstop_cc";
desc = &q6sstop_qcs404_desc;
ret = qcom_cc_probe_by_index(pdev, 0, desc);
if (ret)
- goto destroy_pm_clk;
-
- return 0;
-
-destroy_pm_clk:
- pm_clk_destroy(&pdev->dev);
-
-disable_pm_runtime:
- pm_runtime_disable(&pdev->dev);
-
- return ret;
-}
-
-static int q6sstopcc_qcs404_remove(struct platform_device *pdev)
-{
- pm_clk_destroy(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
+ return ret;
return 0;
}
@@ -209,7 +196,6 @@ static const struct dev_pm_ops q6sstopcc_pm_ops = {
static struct platform_driver q6sstopcc_qcs404_driver = {
.probe = q6sstopcc_qcs404_probe,
- .remove = q6sstopcc_qcs404_remove,
.driver = {
.name = "qcs404-q6sstopcc",
.of_match_table = q6sstopcc_qcs404_match_table,
diff --git a/drivers/clk/qcom/turingcc-qcs404.c b/drivers/clk/qcom/turingcc-qcs404.c
index 4cfbbf5bf4d9..4543bda793f4 100644
--- a/drivers/clk/qcom/turingcc-qcs404.c
+++ b/drivers/clk/qcom/turingcc-qcs404.c
@@ -110,36 +110,23 @@ static int turingcc_probe(struct platform_device *pdev)
{
int ret;
- pm_runtime_enable(&pdev->dev);
- ret = pm_clk_create(&pdev->dev);
+ ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
- goto disable_pm_runtime;
+ return ret;
+
+ ret = devm_pm_clk_create(&pdev->dev);
+ if (ret)
+ return ret;
ret = pm_clk_add(&pdev->dev, NULL);
if (ret < 0) {
dev_err(&pdev->dev, "failed to acquire iface clock\n");
- goto destroy_pm_clk;
+ return ret;
}
ret = qcom_cc_probe(pdev, &turingcc_desc);
if (ret < 0)
- goto destroy_pm_clk;
-
- return 0;
-
-destroy_pm_clk:
- pm_clk_destroy(&pdev->dev);
-
-disable_pm_runtime:
- pm_runtime_disable(&pdev->dev);
-
- return ret;
-}
-
-static int turingcc_remove(struct platform_device *pdev)
-{
- pm_clk_destroy(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
+ return ret;
return 0;
}
@@ -156,7 +143,6 @@ MODULE_DEVICE_TABLE(of, turingcc_match_table);
static struct platform_driver turingcc_driver = {
.probe = turingcc_probe,
- .remove = turingcc_remove,
.driver = {
.name = "qcs404-turingcc",
.of_match_table = turingcc_match_table,
diff --git a/drivers/clk/qcom/videocc-sc7280.c b/drivers/clk/qcom/videocc-sc7280.c
new file mode 100644
index 000000000000..615695d82319
--- /dev/null
+++ b/drivers/clk/qcom/videocc-sc7280.c
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,videocc-sc7280.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "common.h"
+#include "reset.h"
+#include "gdsc.h"
+
+enum {
+ P_BI_TCXO,
+ P_SLEEP_CLK,
+ P_VIDEO_PLL0_OUT_EVEN,
+};
+
+static const struct pll_vco lucid_vco[] = {
+ { 249600000, 2000000000, 0 },
+};
+
+/* 400MHz Configuration */
+static const struct alpha_pll_config video_pll0_config = {
+ .l = 0x14,
+ .alpha = 0xD555,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00002261,
+ .config_ctl_hi1_val = 0x329A299C,
+ .user_ctl_val = 0x00000001,
+ .user_ctl_hi_val = 0x00000805,
+ .user_ctl_hi1_val = 0x00000000,
+};
+
+static struct clk_alpha_pll video_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_vco,
+ .num_vco = ARRAY_SIZE(lucid_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "video_pll0",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_ops,
+ },
+ },
+};
+
+static const struct parent_map video_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_PLL0_OUT_EVEN, 3 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_0[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &video_pll0.clkr.hw },
+};
+
+static const struct parent_map video_cc_parent_map_1[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_1[] = {
+ { .fw_name = "sleep_clk" },
+};
+
+static const struct freq_tbl ftbl_video_cc_iris_clk_src[] = {
+ F(133333333, P_VIDEO_PLL0_OUT_EVEN, 3, 0, 0),
+ F(240000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),
+ F(335000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),
+ F(424000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),
+ F(460000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_iris_clk_src = {
+ .cmd_rcgr = 0x1000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0,
+ .freq_tbl = ftbl_video_cc_iris_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "video_cc_iris_clk_src",
+ .parent_data = video_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x701c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_1,
+ .freq_tbl = ftbl_video_cc_sleep_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "video_cc_sleep_clk_src",
+ .parent_data = video_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch video_cc_iris_ahb_clk = {
+ .halt_reg = 0x5004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x5004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "video_cc_iris_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_iris_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0_axi_clk = {
+ .halt_reg = 0x800c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x800c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "video_cc_mvs0_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0_core_clk = {
+ .halt_reg = 0x3010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x3010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "video_cc_mvs0_core_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_iris_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvsc_core_clk = {
+ .halt_reg = 0x2014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "video_cc_mvsc_core_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_iris_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvsc_ctl_axi_clk = {
+ .halt_reg = 0x8004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "video_cc_mvsc_ctl_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_sleep_clk = {
+ .halt_reg = 0x7034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x7034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "video_cc_sleep_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_sleep_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_venus_ahb_clk = {
+ .halt_reg = 0x801c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x801c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "video_cc_venus_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc mvs0_gdsc = {
+ .gdscr = 0x3004,
+ .pd = {
+ .name = "mvs0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc mvsc_gdsc = {
+ .gdscr = 0x2004,
+ .pd = {
+ .name = "mvsc_gdsc",
+ },
+ .flags = RETAIN_FF_ENABLE,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct clk_regmap *video_cc_sc7280_clocks[] = {
+ [VIDEO_CC_IRIS_AHB_CLK] = &video_cc_iris_ahb_clk.clkr,
+ [VIDEO_CC_IRIS_CLK_SRC] = &video_cc_iris_clk_src.clkr,
+ [VIDEO_CC_MVS0_AXI_CLK] = &video_cc_mvs0_axi_clk.clkr,
+ [VIDEO_CC_MVS0_CORE_CLK] = &video_cc_mvs0_core_clk.clkr,
+ [VIDEO_CC_MVSC_CORE_CLK] = &video_cc_mvsc_core_clk.clkr,
+ [VIDEO_CC_MVSC_CTL_AXI_CLK] = &video_cc_mvsc_ctl_axi_clk.clkr,
+ [VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr,
+ [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
+ [VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr,
+ [VIDEO_PLL0] = &video_pll0.clkr,
+};
+
+static struct gdsc *video_cc_sc7280_gdscs[] = {
+ [MVS0_GDSC] = &mvs0_gdsc,
+ [MVSC_GDSC] = &mvsc_gdsc,
+};
+
+static const struct regmap_config video_cc_sc7280_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xb000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc video_cc_sc7280_desc = {
+ .config = &video_cc_sc7280_regmap_config,
+ .clks = video_cc_sc7280_clocks,
+ .num_clks = ARRAY_SIZE(video_cc_sc7280_clocks),
+ .gdscs = video_cc_sc7280_gdscs,
+ .num_gdscs = ARRAY_SIZE(video_cc_sc7280_gdscs),
+};
+
+static const struct of_device_id video_cc_sc7280_match_table[] = {
+ { .compatible = "qcom,sc7280-videocc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, video_cc_sc7280_match_table);
+
+static int video_cc_sc7280_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &video_cc_sc7280_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_lucid_pll_configure(&video_pll0, regmap, &video_pll0_config);
+
+ return qcom_cc_really_probe(pdev, &video_cc_sc7280_desc, regmap);
+}
+
+static struct platform_driver video_cc_sc7280_driver = {
+ .probe = video_cc_sc7280_probe,
+ .driver = {
+ .name = "video_cc-sc7280",
+ .of_match_table = video_cc_sc7280_match_table,
+ },
+};
+
+static int __init video_cc_sc7280_init(void)
+{
+ return platform_driver_register(&video_cc_sc7280_driver);
+}
+subsys_initcall(video_cc_sc7280_init);
+
+static void __exit video_cc_sc7280_exit(void)
+{
+ platform_driver_unregister(&video_cc_sc7280_driver);
+}
+module_exit(video_cc_sc7280_exit);
+
+MODULE_DESCRIPTION("QTI VIDEO_CC sc7280 Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/ralink/clk-mt7621.c b/drivers/clk/ralink/clk-mt7621.c
index 857da1e274be..a2c045390f00 100644
--- a/drivers/clk/ralink/clk-mt7621.c
+++ b/drivers/clk/ralink/clk-mt7621.c
@@ -131,14 +131,7 @@ static int mt7621_gate_ops_init(struct device *dev,
struct mt7621_gate *sclk)
{
struct clk_init_data init = {
- /*
- * Until now no clock driver existed so
- * these SoC drivers are not prepared
- * yet for the clock. We don't want kernel to
- * disable anything so we add CLK_IS_CRITICAL
- * flag here.
- */
- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .flags = CLK_SET_RATE_PARENT,
.num_parents = 1,
.parent_names = &sclk->parent_name,
.ops = &mt7621_gate_ops,
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index 7b450650bcae..6d0280751bb1 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -153,9 +153,7 @@ config CLK_R8A779A0
select CLK_RENESAS_CPG_MSSR
config CLK_R9A06G032
- bool "Renesas R9A06G032 clock driver"
- help
- This is a driver for R9A06G032 clocks
+ bool "RZ/N1D clock support" if COMPILE_TEST
config CLK_R9A07G044
bool "RZ/G2L clock support" if COMPILE_TEST
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index 5c6c5c721d98..7d018700d08b 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o
obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o
obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o
obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o
-obj-$(CONFIG_CLK_RZG2L) += renesas-rzg2l-cpg.o
+obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o
# Generic
obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o
diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
index 4a43ebec7d5e..39b185d8e957 100644
--- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
@@ -210,7 +210,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
DEF_MOD("rpc-if", 917, R8A774A1_CLK_RPCD2),
DEF_MOD("i2c6", 918, R8A774A1_CLK_S0D6),
DEF_MOD("i2c5", 919, R8A774A1_CLK_S0D6),
- DEF_MOD("i2c-dvfs", 926, R8A774A1_CLK_CP),
+ DEF_MOD("iic-pmic", 926, R8A774A1_CLK_CP),
DEF_MOD("i2c4", 927, R8A774A1_CLK_S0D6),
DEF_MOD("i2c3", 928, R8A774A1_CLK_S0D6),
DEF_MOD("i2c2", 929, R8A774A1_CLK_S3D2),
diff --git a/drivers/clk/renesas/r8a774b1-cpg-mssr.c b/drivers/clk/renesas/r8a774b1-cpg-mssr.c
index 6f04c40fe237..af602d83c8ce 100644
--- a/drivers/clk/renesas/r8a774b1-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a774b1-cpg-mssr.c
@@ -206,7 +206,7 @@ static const struct mssr_mod_clk r8a774b1_mod_clks[] __initconst = {
DEF_MOD("rpc-if", 917, R8A774B1_CLK_RPCD2),
DEF_MOD("i2c6", 918, R8A774B1_CLK_S0D6),
DEF_MOD("i2c5", 919, R8A774B1_CLK_S0D6),
- DEF_MOD("i2c-dvfs", 926, R8A774B1_CLK_CP),
+ DEF_MOD("iic-pmic", 926, R8A774B1_CLK_CP),
DEF_MOD("i2c4", 927, R8A774B1_CLK_S0D6),
DEF_MOD("i2c3", 928, R8A774B1_CLK_S0D6),
DEF_MOD("i2c2", 929, R8A774B1_CLK_S3D2),
diff --git a/drivers/clk/renesas/r8a774c0-cpg-mssr.c b/drivers/clk/renesas/r8a774c0-cpg-mssr.c
index ed3a2cf0e0bb..5b938eb2df25 100644
--- a/drivers/clk/renesas/r8a774c0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c
@@ -210,7 +210,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
DEF_MOD("rpc-if", 917, R8A774C0_CLK_RPCD2),
DEF_MOD("i2c6", 918, R8A774C0_CLK_S3D2),
DEF_MOD("i2c5", 919, R8A774C0_CLK_S3D2),
- DEF_MOD("i2c-dvfs", 926, R8A774C0_CLK_CP),
+ DEF_MOD("iic-pmic", 926, R8A774C0_CLK_CP),
DEF_MOD("i2c4", 927, R8A774C0_CLK_S3D2),
DEF_MOD("i2c3", 928, R8A774C0_CLK_S3D2),
DEF_MOD("i2c2", 929, R8A774C0_CLK_S3D2),
diff --git a/drivers/clk/renesas/r8a774e1-cpg-mssr.c b/drivers/clk/renesas/r8a774e1-cpg-mssr.c
index b96c486abb44..40c71466df37 100644
--- a/drivers/clk/renesas/r8a774e1-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a774e1-cpg-mssr.c
@@ -219,7 +219,7 @@ static const struct mssr_mod_clk r8a774e1_mod_clks[] __initconst = {
DEF_MOD("i2c6", 918, R8A774E1_CLK_S0D6),
DEF_MOD("i2c5", 919, R8A774E1_CLK_S0D6),
DEF_MOD("adg", 922, R8A774E1_CLK_S0D1),
- DEF_MOD("i2c-dvfs", 926, R8A774E1_CLK_CP),
+ DEF_MOD("iic-pmic", 926, R8A774E1_CLK_CP),
DEF_MOD("i2c4", 927, R8A774E1_CLK_S0D6),
DEF_MOD("i2c3", 928, R8A774E1_CLK_S0D6),
DEF_MOD("i2c2", 929, R8A774E1_CLK_S3D2),
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
index acaf5a93f1d3..f16d125ca009 100644
--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
@@ -135,7 +135,6 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
DEF_FIXED("zt", R8A779A0_CLK_ZT, CLK_PLL1_DIV2, 2, 1),
DEF_FIXED("ztr", R8A779A0_CLK_ZTR, CLK_PLL1_DIV2, 2, 1),
DEF_FIXED("zr", R8A779A0_CLK_ZR, CLK_PLL1_DIV2, 1, 1),
- DEF_FIXED("dsi", R8A779A0_CLK_DSI, CLK_PLL5_DIV4, 1, 1),
DEF_FIXED("cnndsp", R8A779A0_CLK_CNNDSP, CLK_PLL5_DIV4, 1, 1),
DEF_FIXED("vip", R8A779A0_CLK_VIP, CLK_PLL5, 5, 1),
DEF_FIXED("adgh", R8A779A0_CLK_ADGH, CLK_PLL5_DIV4, 1, 1),
@@ -151,6 +150,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c),
DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878),
DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, 0x880),
+ DEF_DIV6P1("dsi", R8A779A0_CLK_DSI, CLK_PLL5_DIV4, 0x884),
DEF_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8),
DEF_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
@@ -167,6 +167,9 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0),
DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0),
DEF_MOD("csi43", 402, R8A779A0_CLK_CSI0),
+ DEF_MOD("du", 411, R8A779A0_CLK_S3D1),
+ DEF_MOD("dsi0", 415, R8A779A0_CLK_DSI),
+ DEF_MOD("dsi1", 416, R8A779A0_CLK_DSI),
DEF_MOD("fcpvd0", 508, R8A779A0_CLK_S3D1),
DEF_MOD("fcpvd1", 509, R8A779A0_CLK_S3D1),
DEF_MOD("hscif0", 514, R8A779A0_CLK_S1D2),
diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
index ae24e0397d3c..4c94b94c4125 100644
--- a/drivers/clk/renesas/r9a07g044-cpg.c
+++ b/drivers/clk/renesas/r9a07g044-cpg.c
@@ -12,11 +12,11 @@
#include <dt-bindings/clock/r9a07g044-cpg.h>
-#include "renesas-rzg2l-cpg.h"
+#include "rzg2l-cpg.h"
enum clk_ids {
/* Core Clock Outputs exported to DT */
- LAST_DT_CORE_CLK = R9A07G044_OSCCLK,
+ LAST_DT_CORE_CLK = R9A07G044_CLK_P0_DIV2,
/* External Input Clocks */
CLK_EXTAL,
@@ -37,6 +37,7 @@ enum clk_ids {
CLK_PLL5,
CLK_PLL5_DIV2,
CLK_PLL6,
+ CLK_P1_DIV2,
/* Module Clocks */
MOD_CLK_BASE,
@@ -76,9 +77,11 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
DEF_FIXED("I", R9A07G044_CLK_I, CLK_PLL1, 1, 1),
DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV16, DIVPL2A,
dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
+ DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2),
DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV20, 1, 1),
DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4,
DIVPL3B, dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
+ DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2),
DEF_DIV("P2", R9A07G044_CLK_P2, CLK_PLL3_DIV2_4_2,
DIVPL3A, dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
};
@@ -90,6 +93,42 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
0x518, 0),
DEF_MOD("ia55_clk", R9A07G044_IA55_CLK, R9A07G044_CLK_P1,
0x518, 1),
+ DEF_MOD("dmac_aclk", R9A07G044_DMAC_ACLK, R9A07G044_CLK_P1,
+ 0x52c, 0),
+ DEF_MOD("dmac_pclk", R9A07G044_DMAC_PCLK, CLK_P1_DIV2,
+ 0x52c, 1),
+ DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 0),
+ DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 1),
+ DEF_MOD("ssi1_pclk", R9A07G044_SSI1_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 2),
+ DEF_MOD("ssi1_sfr", R9A07G044_SSI1_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 3),
+ DEF_MOD("ssi2_pclk", R9A07G044_SSI2_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 4),
+ DEF_MOD("ssi2_sfr", R9A07G044_SSI2_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 5),
+ DEF_MOD("ssi3_pclk", R9A07G044_SSI3_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 6),
+ DEF_MOD("ssi3_sfr", R9A07G044_SSI3_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 7),
+ DEF_MOD("usb0_host", R9A07G044_USB_U2H0_HCLK, R9A07G044_CLK_P1,
+ 0x578, 0),
+ DEF_MOD("usb1_host", R9A07G044_USB_U2H1_HCLK, R9A07G044_CLK_P1,
+ 0x578, 1),
+ DEF_MOD("usb0_func", R9A07G044_USB_U2P_EXR_CPUCLK, R9A07G044_CLK_P1,
+ 0x578, 2),
+ DEF_MOD("usb_pclk", R9A07G044_USB_PCLK, R9A07G044_CLK_P1,
+ 0x578, 3),
+ DEF_MOD("i2c0", R9A07G044_I2C0_PCLK, R9A07G044_CLK_P0,
+ 0x580, 0),
+ DEF_MOD("i2c1", R9A07G044_I2C1_PCLK, R9A07G044_CLK_P0,
+ 0x580, 1),
+ DEF_MOD("i2c2", R9A07G044_I2C2_PCLK, R9A07G044_CLK_P0,
+ 0x580, 2),
+ DEF_MOD("i2c3", R9A07G044_I2C3_PCLK, R9A07G044_CLK_P0,
+ 0x580, 3),
DEF_MOD("scif0", R9A07G044_SCIF0_CLK_PCK, R9A07G044_CLK_P0,
0x584, 0),
DEF_MOD("scif1", R9A07G044_SCIF1_CLK_PCK, R9A07G044_CLK_P0,
@@ -102,18 +141,47 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
0x584, 4),
DEF_MOD("sci0", R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0,
0x588, 0),
+ DEF_MOD("canfd", R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0,
+ 0x594, 0),
+ DEF_MOD("gpio", R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK,
+ 0x598, 0),
+ DEF_MOD("adc_adclk", R9A07G044_ADC_ADCLK, R9A07G044_CLK_TSU,
+ 0x5a8, 0),
+ DEF_MOD("adc_pclk", R9A07G044_ADC_PCLK, R9A07G044_CLK_P0,
+ 0x5a8, 1),
};
static struct rzg2l_reset r9a07g044_resets[] = {
DEF_RST(R9A07G044_GIC600_GICRESET_N, 0x814, 0),
DEF_RST(R9A07G044_GIC600_DBG_GICRESET_N, 0x814, 1),
DEF_RST(R9A07G044_IA55_RESETN, 0x818, 0),
+ DEF_RST(R9A07G044_DMAC_ARESETN, 0x82c, 0),
+ DEF_RST(R9A07G044_DMAC_RST_ASYNC, 0x82c, 1),
+ DEF_RST(R9A07G044_SSI0_RST_M2_REG, 0x870, 0),
+ DEF_RST(R9A07G044_SSI1_RST_M2_REG, 0x870, 1),
+ DEF_RST(R9A07G044_SSI2_RST_M2_REG, 0x870, 2),
+ DEF_RST(R9A07G044_SSI3_RST_M2_REG, 0x870, 3),
+ DEF_RST(R9A07G044_USB_U2H0_HRESETN, 0x878, 0),
+ DEF_RST(R9A07G044_USB_U2H1_HRESETN, 0x878, 1),
+ DEF_RST(R9A07G044_USB_U2P_EXL_SYSRST, 0x878, 2),
+ DEF_RST(R9A07G044_USB_PRESETN, 0x878, 3),
+ DEF_RST(R9A07G044_I2C0_MRST, 0x880, 0),
+ DEF_RST(R9A07G044_I2C1_MRST, 0x880, 1),
+ DEF_RST(R9A07G044_I2C2_MRST, 0x880, 2),
+ DEF_RST(R9A07G044_I2C3_MRST, 0x880, 3),
DEF_RST(R9A07G044_SCIF0_RST_SYSTEM_N, 0x884, 0),
DEF_RST(R9A07G044_SCIF1_RST_SYSTEM_N, 0x884, 1),
DEF_RST(R9A07G044_SCIF2_RST_SYSTEM_N, 0x884, 2),
DEF_RST(R9A07G044_SCIF3_RST_SYSTEM_N, 0x884, 3),
DEF_RST(R9A07G044_SCIF4_RST_SYSTEM_N, 0x884, 4),
DEF_RST(R9A07G044_SCI0_RST, 0x888, 0),
+ DEF_RST(R9A07G044_CANFD_RSTP_N, 0x894, 0),
+ DEF_RST(R9A07G044_CANFD_RSTC_N, 0x894, 1),
+ DEF_RST(R9A07G044_GPIO_RSTN, 0x898, 0),
+ DEF_RST(R9A07G044_GPIO_PORT_RESETN, 0x898, 1),
+ DEF_RST(R9A07G044_GPIO_SPARE_RESETN, 0x898, 2),
+ DEF_RST(R9A07G044_ADC_PRESETN, 0x8a8, 0),
+ DEF_RST(R9A07G044_ADC_ADRST_N, 0x8a8, 1),
};
static const unsigned int r9a07g044_crit_mod_clks[] __initconst = {
diff --git a/drivers/clk/renesas/renesas-rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index e7c59af2a1d8..3b3b2c3347f3 100644
--- a/drivers/clk/renesas/renesas-rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -29,7 +29,7 @@
#include <dt-bindings/clock/renesas-cpg-mssr.h>
-#include "renesas-rzg2l-cpg.h"
+#include "rzg2l-cpg.h"
#ifdef DEBUG
#define WARN_DEBUG(x) WARN_ON(x)
@@ -125,7 +125,7 @@ rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core,
core->flag, &priv->rmw_lock);
if (IS_ERR(clk_hw))
- return NULL;
+ return ERR_CAST(clk_hw);
return clk_hw->clk;
}
@@ -175,17 +175,14 @@ rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core,
struct clk_init_data init;
const char *parent_name;
struct pll_clk *pll_clk;
- struct clk *clk;
parent = clks[core->parent & 0xffff];
if (IS_ERR(parent))
return ERR_CAST(parent);
pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL);
- if (!pll_clk) {
- clk = ERR_PTR(-ENOMEM);
- return NULL;
- }
+ if (!pll_clk)
+ return ERR_PTR(-ENOMEM);
parent_name = __clk_get_name(parent);
init.name = core->name;
@@ -200,11 +197,7 @@ rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core,
pll_clk->priv = priv;
pll_clk->type = core->type;
- clk = clk_register(NULL, &pll_clk->hw);
- if (IS_ERR(clk))
- kfree(pll_clk);
-
- return clk;
+ return clk_register(NULL, &pll_clk->hw);
}
static struct clk
@@ -229,7 +222,7 @@ static struct clk
case CPG_MOD:
type = "module";
- if (clkidx > priv->num_mod_clks) {
+ if (clkidx >= priv->num_mod_clks) {
dev_err(dev, "Invalid %s clock index %u\n", type,
clkidx);
return ERR_PTR(-EINVAL);
@@ -297,7 +290,7 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
break;
default:
goto fail;
- };
+ }
if (IS_ERR_OR_NULL(clk))
goto fail;
@@ -473,7 +466,6 @@ rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod,
fail:
dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
mod->name, PTR_ERR(clk));
- kfree(clock);
}
#define rcdev_to_priv(x) container_of(x, struct rzg2l_cpg_priv, rcdev)
diff --git a/drivers/clk/renesas/renesas-rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
index 63695280ce8b..63695280ce8b 100644
--- a/drivers/clk/renesas/renesas-rzg2l-cpg.h
+++ b/drivers/clk/renesas/rzg2l-cpg.h
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index fe937bcdb487..f7827b3b7fc1 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -940,7 +940,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
switch (pll_type) {
case pll_rk3036:
case pll_rk3328:
- if (!pll->rate_table || IS_ERR(ctx->grf))
+ if (!pll->rate_table)
init.ops = &rockchip_rk3036_pll_clk_norate_ops;
else
init.ops = &rockchip_rk3036_pll_clk_ops;
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c
index 614845cc5b4a..d644bc155ec6 100644
--- a/drivers/clk/rockchip/clk-rk3036.c
+++ b/drivers/clk/rockchip/clk-rk3036.c
@@ -121,6 +121,7 @@ PNAME(mux_pll_src_3plls_p) = { "apll", "dpll", "gpll" };
PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" };
PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" };
+PNAME(mux_pll_src_dmyapll_dpll_gpll_xin24_p) = { "dummy_apll", "dpll", "gpll", "xin24m" };
PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" };
PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
@@ -340,7 +341,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS,
RK2928_CLKGATE_CON(10), 4, GFLAGS),
- COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_dpll_gpll_usb480m_p, 0,
+ COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_dmyapll_dpll_gpll_xin24_p, 0,
RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS,
RK2928_CLKGATE_CON(10), 5, GFLAGS),
@@ -403,7 +404,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS),
GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS),
GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
- GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS),
+ GATE(HCLK_SFC, "hclk_sfc", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS),
GATE(HCLK_MAC, "hclk_mac", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS),
/* pclk_peri gates */
diff --git a/drivers/clk/rockchip/clk-rk3308.c b/drivers/clk/rockchip/clk-rk3308.c
index 2c3bd0c749f2..db3396c3e6e9 100644
--- a/drivers/clk/rockchip/clk-rk3308.c
+++ b/drivers/clk/rockchip/clk-rk3308.c
@@ -911,6 +911,7 @@ static const char *const rk3308_critical_clocks[] __initconst = {
"hclk_audio",
"pclk_audio",
"sclk_ddrc",
+ "clk_ddrphy4x",
};
static void __init rk3308_clk_init(struct device_node *np)
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 049e5e0b64f6..b7be7e11b0df 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -22,6 +22,8 @@
#include <linux/regmap.h>
#include <linux/reboot.h>
#include <linux/rational.h>
+
+#include "../clk-fractional-divider.h"
#include "clk.h"
/*
@@ -178,10 +180,8 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
unsigned long rate, unsigned long *parent_rate,
unsigned long *m, unsigned long *n)
{
- struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long p_rate, p_parent_rate;
struct clk_hw *p_parent;
- unsigned long scale;
p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
@@ -190,18 +190,7 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
*parent_rate = p_parent_rate;
}
- /*
- * Get rate closer to *parent_rate to guarantee there is no overflow
- * for m and n. In the result it will be the nearest rate left shifted
- * by (scale - fd->nwidth) bits.
- */
- scale = fls_long(*parent_rate / rate - 1);
- if (scale > fd->nwidth)
- rate <<= scale - fd->nwidth;
-
- rational_best_approximation(rate, *parent_rate,
- GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
- m, n);
+ clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
}
static struct clk *rockchip_clk_register_frac_branch(
diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c
index 1cb21ea79c64..242e94c0cf8a 100644
--- a/drivers/clk/socfpga/clk-agilex.c
+++ b/drivers/clk/socfpga/clk-agilex.c
@@ -107,10 +107,10 @@ static const struct clk_parent_data gpio_db_free_mux[] = {
};
static const struct clk_parent_data psi_ref_free_mux[] = {
- { .fw_name = "main_pll_c3",
- .name = "main_pll_c3", },
- { .fw_name = "peri_pll_c3",
- .name = "peri_pll_c3", },
+ { .fw_name = "main_pll_c2",
+ .name = "main_pll_c2", },
+ { .fw_name = "peri_pll_c2",
+ .name = "peri_pll_c2", },
{ .fw_name = "osc1",
.name = "osc1", },
{ .fw_name = "cb-intosc-hs-div2-clk",
@@ -195,6 +195,13 @@ static const struct clk_parent_data sdmmc_mux[] = {
.name = "boot_clk", },
};
+static const struct clk_parent_data s2f_user0_mux[] = {
+ { .fw_name = "s2f_user0_free_clk",
+ .name = "s2f_user0_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
static const struct clk_parent_data s2f_user1_mux[] = {
{ .fw_name = "s2f_user1_free_clk",
.name = "s2f_user1_free_clk", },
@@ -273,7 +280,7 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = {
{ AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0, 0},
{ AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux,
- ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0, 0},
+ ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0x30, 2},
{ AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
ARRAY_SIZE(s2f_usr1_free_mux), 0, 0xEC, 0, 0x88, 5},
{ AGILEX_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
@@ -319,6 +326,8 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = {
4, 0x98, 0, 16, 0x88, 3, 0},
{ AGILEX_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0x7C,
5, 0, 0, 0, 0x88, 4, 4},
+ { AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_user0_mux, ARRAY_SIZE(s2f_user0_mux), 0, 0x24,
+ 6, 0, 0, 0, 0x30, 2, 0},
{ AGILEX_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0x7C,
6, 0, 0, 0, 0x88, 5, 0},
{ AGILEX_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0x7C,
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
index a5f526bb0483..6144447f86c6 100644
--- a/drivers/clk/tegra/clk-dfll.c
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -1377,7 +1377,7 @@ static void dfll_debug_init(struct tegra_dfll *td)
}
#else
-static void inline dfll_debug_init(struct tegra_dfll *td) { }
+static inline void dfll_debug_init(struct tegra_dfll *td) { }
#endif /* CONFIG_DEBUG_FS */
/*
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index 292d6269daf1..4dcf7f7cb8a0 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -777,11 +777,7 @@ static struct tegra_periph_init_data gate_clks[] = {
GATE("ahbdma", "hclk", 33, 0, tegra_clk_ahbdma, 0),
GATE("apbdma", "pclk", 34, 0, tegra_clk_apbdma, 0),
GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0),
- /*
- * Critical for RAM re-repair operation, which must occur on resume
- * from LP1 system suspend and as part of CCPLEX cluster switching.
- */
- GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, CLK_IS_CRITICAL),
+ GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0),
GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0),
GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0),
GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0),
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
index 0aedd42fad52..528c5bb397cc 100644
--- a/drivers/clk/ux500/u8500_of_clk.c
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -99,10 +99,11 @@ static void u8500_clk_init(struct device_node *np)
if (fw_version != NULL) {
switch (fw_version->project) {
case PRCMU_FW_PROJECT_U8500_C2:
- case PRCMU_FW_PROJECT_U8500_MBL:
+ case PRCMU_FW_PROJECT_U8500_SSG1:
case PRCMU_FW_PROJECT_U8520:
case PRCMU_FW_PROJECT_U8420:
case PRCMU_FW_PROJECT_U8420_SYSCLK:
+ case PRCMU_FW_PROJECT_U8500_SSG2:
sgaclk_parent = "soc0_pll";
break;
default:
diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
index 18564efdc651..1244c4e568ff 100644
--- a/drivers/clk/x86/Makefile
+++ b/drivers/clk/x86/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE) += clk-fch.o
-clk-x86-lpss-objs := clk-lpt.o
+clk-x86-lpss-y := clk-lpss-atom.o
obj-$(CONFIG_X86_INTEL_LPSS) += clk-x86-lpss.o
obj-$(CONFIG_CLK_LGM_CGU) += clk-cgu.o clk-cgu-pll.o clk-lgm.o
diff --git a/drivers/clk/x86/clk-lpt.c b/drivers/clk/x86/clk-lpss-atom.c
index fbe9fd3ed948..aa9d0bb98f8b 100644
--- a/drivers/clk/x86/clk-lpt.c
+++ b/drivers/clk/x86/clk-lpss-atom.c
@@ -13,7 +13,7 @@
#include <linux/platform_data/x86/clk-lpss.h>
#include <linux/platform_device.h>
-static int lpt_clk_probe(struct platform_device *pdev)
+static int lpss_atom_clk_probe(struct platform_device *pdev)
{
struct lpss_clk_data *drvdata;
struct clk *clk;
@@ -34,14 +34,14 @@ static int lpt_clk_probe(struct platform_device *pdev)
return 0;
}
-static struct platform_driver lpt_clk_driver = {
+static struct platform_driver lpss_atom_clk_driver = {
.driver = {
- .name = "clk-lpt",
+ .name = "clk-lpss-atom",
},
- .probe = lpt_clk_probe,
+ .probe = lpss_atom_clk_probe,
};
-int __init lpt_clk_init(void)
+int __init lpss_atom_clk_init(void)
{
- return platform_driver_register(&lpt_clk_driver);
+ return platform_driver_register(&lpss_atom_clk_driver);
}
diff --git a/drivers/clk/zynqmp/clk-gate-zynqmp.c b/drivers/clk/zynqmp/clk-gate-zynqmp.c
index 695feaa82da5..565ed67a0430 100644
--- a/drivers/clk/zynqmp/clk-gate-zynqmp.c
+++ b/drivers/clk/zynqmp/clk-gate-zynqmp.c
@@ -12,7 +12,7 @@
#include "clk-zynqmp.h"
/**
- * struct clk_gate - gating clock
+ * struct zynqmp_clk_gate - gating clock
* @hw: handle between common and hardware-specific interfaces
* @flags: hardware-specific flags
* @clk_id: Id of clock
@@ -66,7 +66,7 @@ static void zynqmp_clk_gate_disable(struct clk_hw *hw)
}
/**
- * zynqmp_clk_gate_is_enable() - Check clock state
+ * zynqmp_clk_gate_is_enabled() - Check clock state
* @hw: handle between common and hardware-specific interfaces
*
* Return: 1 if enabled, 0 if disabled else error code
diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c
index 157d4a960bf4..17afce594f28 100644
--- a/drivers/clk/zynqmp/clk-mux-zynqmp.c
+++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c
@@ -159,7 +159,7 @@ struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id,
hw = &mux->hw;
ret = clk_hw_register(NULL, hw);
if (ret) {
- kfree(hw);
+ kfree(mux);
hw = ERR_PTR(ret);
}
diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h
index 84fa80a969a9..60cbc0674a9e 100644
--- a/drivers/clk/zynqmp/clk-zynqmp.h
+++ b/drivers/clk/zynqmp/clk-zynqmp.h
@@ -56,6 +56,7 @@ enum topology_type {
* @type: Type of topology
* @flag: Topology flags
* @type_flag: Topology type specific flag
+ * @custom_type_flag: Topology type specific custom flag
*/
struct clock_topology {
u32 type;
diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c
index 871184e406e1..eb25303eefed 100644
--- a/drivers/clk/zynqmp/clkc.c
+++ b/drivers/clk/zynqmp/clkc.c
@@ -762,9 +762,7 @@ static int zynqmp_clk_setup(struct device_node *np)
zynqmp_register_clocks(np);
zynqmp_data->num = clock_max_idx;
- of_clk_add_hw_provider(np, of_clk_hw_onecell_get, zynqmp_data);
-
- return 0;
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, zynqmp_data);
}
static int zynqmp_clock_probe(struct platform_device *pdev)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index eb661b539a3e..0f5e3983951a 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -234,8 +234,9 @@ config CLKSRC_LPC32XX
Support for the LPC32XX clocksource.
config CLKSRC_PISTACHIO
- bool "Clocksource for Pistachio SoC" if COMPILE_TEST
+ bool "Clocksource for Pistachio SoC"
depends on HAS_IOMEM
+ depends on MIPS || COMPILE_TEST
select TIMER_OF
help
Enables the clocksource for the Pistachio SoC.
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
index d6ece7bbce89..ff188ab68496 100644
--- a/drivers/clocksource/hyperv_timer.c
+++ b/drivers/clocksource/hyperv_timer.c
@@ -361,9 +361,6 @@ EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup);
* Hyper-V and 32-bit x86. The TSC reference page version is preferred.
*/
-u64 (*hv_read_reference_counter)(void);
-EXPORT_SYMBOL_GPL(hv_read_reference_counter);
-
static union {
struct ms_hyperv_tsc_page page;
u8 reserved[PAGE_SIZE];
diff --git a/drivers/clocksource/timer-ixp4xx.c b/drivers/clocksource/timer-ixp4xx.c
index 9396745e1c17..cbb184953510 100644
--- a/drivers/clocksource/timer-ixp4xx.c
+++ b/drivers/clocksource/timer-ixp4xx.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/platform_device.h>
/* Goes away with OF conversion */
#include <linux/platform_data/timer-ixp4xx.h>
@@ -29,9 +30,6 @@
#define IXP4XX_OSRT1_OFFSET 0x08 /* Timer 1 Reload */
#define IXP4XX_OST2_OFFSET 0x0C /* Timer 2 Timestamp */
#define IXP4XX_OSRT2_OFFSET 0x10 /* Timer 2 Reload */
-#define IXP4XX_OSWT_OFFSET 0x14 /* Watchdog Timer */
-#define IXP4XX_OSWE_OFFSET 0x18 /* Watchdog Enable */
-#define IXP4XX_OSWK_OFFSET 0x1C /* Watchdog Key */
#define IXP4XX_OSST_OFFSET 0x20 /* Timer Status */
/*
@@ -45,17 +43,10 @@
#define IXP4XX_OSST_TIMER_1_PEND 0x00000001
#define IXP4XX_OSST_TIMER_2_PEND 0x00000002
#define IXP4XX_OSST_TIMER_TS_PEND 0x00000004
-#define IXP4XX_OSST_TIMER_WDOG_PEND 0x00000008
-#define IXP4XX_OSST_TIMER_WARM_RESET 0x00000010
-
-#define IXP4XX_WDT_KEY 0x0000482E
-#define IXP4XX_WDT_RESET_ENABLE 0x00000001
-#define IXP4XX_WDT_IRQ_ENABLE 0x00000002
-#define IXP4XX_WDT_COUNT_ENABLE 0x00000004
+/* Remaining registers are for the watchdog and defined in the watchdog driver */
struct ixp4xx_timer {
void __iomem *base;
- unsigned int tick_rate;
u32 latch;
struct clock_event_device clkevt;
#ifdef CONFIG_ARM
@@ -181,7 +172,6 @@ static __init int ixp4xx_timer_register(void __iomem *base,
if (!tmr)
return -ENOMEM;
tmr->base = base;
- tmr->tick_rate = timer_freq;
/*
* The timer register doesn't allow to specify the two least
@@ -239,6 +229,40 @@ static __init int ixp4xx_timer_register(void __iomem *base,
return 0;
}
+static struct platform_device ixp4xx_watchdog_device = {
+ .name = "ixp4xx-watchdog",
+ .id = -1,
+};
+
+/*
+ * This probe gets called after the timer is already up and running. The main
+ * function on this platform is to spawn the watchdog device as a child.
+ */
+static int ixp4xx_timer_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+
+ /* Pass the base address as platform data and nothing else */
+ ixp4xx_watchdog_device.dev.platform_data = local_ixp4xx_timer->base;
+ ixp4xx_watchdog_device.dev.parent = dev;
+ return platform_device_register(&ixp4xx_watchdog_device);
+}
+
+static const struct of_device_id ixp4xx_timer_dt_id[] = {
+ { .compatible = "intel,ixp4xx-timer", },
+ { /* sentinel */ },
+};
+
+static struct platform_driver ixp4xx_timer_driver = {
+ .probe = ixp4xx_timer_probe,
+ .driver = {
+ .name = "ixp4xx-timer",
+ .of_match_table = ixp4xx_timer_dt_id,
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver(ixp4xx_timer_driver);
+
/**
* ixp4xx_timer_setup() - Timer setup function to be called from boardfiles
* @timerbase: physical base of timer block
diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
index 09a9a77cce06..0caa60537b14 100644
--- a/drivers/counter/104-quad-8.c
+++ b/drivers/counter/104-quad-8.c
@@ -28,6 +28,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
/**
* struct quad8 - device private data structure
+ * @lock: lock to prevent clobbering device states during R/W ops
* @counter: instance of the counter_device
* @fck_prescaler: array of filter clock prescaler configurations
* @preset: array of preset values
@@ -97,7 +98,8 @@ struct quad8 {
#define QUAD8_CMR_QUADRATURE_X4 0x18
static int quad8_signal_read(struct counter_device *counter,
- struct counter_signal *signal, enum counter_signal_value *val)
+ struct counter_signal *signal,
+ enum counter_signal_level *level)
{
const struct quad8 *const priv = counter->priv;
unsigned int state;
@@ -109,7 +111,7 @@ static int quad8_signal_read(struct counter_device *counter,
state = inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS)
& BIT(signal->id - 16);
- *val = (state) ? COUNTER_SIGNAL_HIGH : COUNTER_SIGNAL_LOW;
+ *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
return 0;
}
@@ -154,7 +156,7 @@ static int quad8_count_write(struct counter_device *counter,
/* Only 24-bit values are supported */
if (val > 0xFFFFFF)
- return -EINVAL;
+ return -ERANGE;
mutex_lock(&priv->lock);
@@ -193,11 +195,11 @@ enum quad8_count_function {
QUAD8_COUNT_FUNCTION_QUADRATURE_X4
};
-static const enum counter_count_function quad8_count_functions_list[] = {
- [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION] = COUNTER_COUNT_FUNCTION_PULSE_DIRECTION,
- [QUAD8_COUNT_FUNCTION_QUADRATURE_X1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A,
- [QUAD8_COUNT_FUNCTION_QUADRATURE_X2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
- [QUAD8_COUNT_FUNCTION_QUADRATURE_X4] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4
+static const enum counter_function quad8_count_functions_list[] = {
+ [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION] = COUNTER_FUNCTION_PULSE_DIRECTION,
+ [QUAD8_COUNT_FUNCTION_QUADRATURE_X1] = COUNTER_FUNCTION_QUADRATURE_X1_A,
+ [QUAD8_COUNT_FUNCTION_QUADRATURE_X2] = COUNTER_FUNCTION_QUADRATURE_X2_A,
+ [QUAD8_COUNT_FUNCTION_QUADRATURE_X4] = COUNTER_FUNCTION_QUADRATURE_X4
};
static int quad8_function_get(struct counter_device *counter,
@@ -273,6 +275,10 @@ static int quad8_function_set(struct counter_device *counter,
*scale = 2;
mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
break;
+ default:
+ /* should never reach this path */
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
}
}
@@ -349,7 +355,7 @@ static int quad8_action_get(struct counter_device *counter,
case QUAD8_COUNT_FUNCTION_PULSE_DIRECTION:
if (synapse->signal->id == signal_a_id)
*action = QUAD8_SYNAPSE_ACTION_RISING_EDGE;
- break;
+ return 0;
case QUAD8_COUNT_FUNCTION_QUADRATURE_X1:
if (synapse->signal->id == signal_a_id) {
quad8_direction_get(counter, count, &direction);
@@ -359,17 +365,18 @@ static int quad8_action_get(struct counter_device *counter,
else
*action = QUAD8_SYNAPSE_ACTION_FALLING_EDGE;
}
- break;
+ return 0;
case QUAD8_COUNT_FUNCTION_QUADRATURE_X2:
if (synapse->signal->id == signal_a_id)
*action = QUAD8_SYNAPSE_ACTION_BOTH_EDGES;
- break;
+ return 0;
case QUAD8_COUNT_FUNCTION_QUADRATURE_X4:
*action = QUAD8_SYNAPSE_ACTION_BOTH_EDGES;
- break;
+ return 0;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
-
- return 0;
}
static const struct counter_ops quad8_ops = {
@@ -529,6 +536,9 @@ static int quad8_count_mode_set(struct counter_device *counter,
case COUNTER_COUNT_MODE_MODULO_N:
cnt_mode = 3;
break;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
mutex_lock(&priv->lock);
@@ -661,7 +671,7 @@ static ssize_t quad8_count_preset_write(struct counter_device *counter,
/* Only 24-bit values are supported */
if (preset > 0xFFFFFF)
- return -EINVAL;
+ return -ERANGE;
mutex_lock(&priv->lock);
@@ -706,7 +716,7 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter,
/* Only 24-bit values are supported */
if (ceiling > 0xFFFFFF)
- return -EINVAL;
+ return -ERANGE;
mutex_lock(&priv->lock);
@@ -715,12 +725,13 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter,
case 1:
case 3:
quad8_preset_register_set(priv, count->id, ceiling);
- break;
+ mutex_unlock(&priv->lock);
+ return len;
}
mutex_unlock(&priv->lock);
- return len;
+ return -EINVAL;
}
static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,
diff --git a/drivers/counter/counter.c b/drivers/counter/counter.c
index 6a683d086008..de921e8a3f72 100644
--- a/drivers/counter/counter.c
+++ b/drivers/counter/counter.c
@@ -289,9 +289,9 @@ struct counter_signal_unit {
struct counter_signal *signal;
};
-static const char *const counter_signal_value_str[] = {
- [COUNTER_SIGNAL_LOW] = "low",
- [COUNTER_SIGNAL_HIGH] = "high"
+static const char *const counter_signal_level_str[] = {
+ [COUNTER_SIGNAL_LEVEL_LOW] = "low",
+ [COUNTER_SIGNAL_LEVEL_HIGH] = "high"
};
static ssize_t counter_signal_show(struct device *dev,
@@ -302,13 +302,13 @@ static ssize_t counter_signal_show(struct device *dev,
const struct counter_signal_unit *const component = devattr->component;
struct counter_signal *const signal = component->signal;
int err;
- enum counter_signal_value val;
+ enum counter_signal_level level;
- err = counter->ops->signal_read(counter, signal, &val);
+ err = counter->ops->signal_read(counter, signal, &level);
if (err)
return err;
- return sprintf(buf, "%s\n", counter_signal_value_str[val]);
+ return sprintf(buf, "%s\n", counter_signal_level_str[level]);
}
struct counter_name_unit {
@@ -744,15 +744,15 @@ static ssize_t counter_count_store(struct device *dev,
return len;
}
-static const char *const counter_count_function_str[] = {
- [COUNTER_COUNT_FUNCTION_INCREASE] = "increase",
- [COUNTER_COUNT_FUNCTION_DECREASE] = "decrease",
- [COUNTER_COUNT_FUNCTION_PULSE_DIRECTION] = "pulse-direction",
- [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a",
- [COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b",
- [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a",
- [COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b",
- [COUNTER_COUNT_FUNCTION_QUADRATURE_X4] = "quadrature x4"
+static const char *const counter_function_str[] = {
+ [COUNTER_FUNCTION_INCREASE] = "increase",
+ [COUNTER_FUNCTION_DECREASE] = "decrease",
+ [COUNTER_FUNCTION_PULSE_DIRECTION] = "pulse-direction",
+ [COUNTER_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a",
+ [COUNTER_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b",
+ [COUNTER_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a",
+ [COUNTER_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b",
+ [COUNTER_FUNCTION_QUADRATURE_X4] = "quadrature x4"
};
static ssize_t counter_function_show(struct device *dev,
@@ -764,7 +764,7 @@ static ssize_t counter_function_show(struct device *dev,
const struct counter_count_unit *const component = devattr->component;
struct counter_count *const count = component->count;
size_t func_index;
- enum counter_count_function function;
+ enum counter_function function;
err = counter->ops->function_get(counter, count, &func_index);
if (err)
@@ -773,7 +773,7 @@ static ssize_t counter_function_show(struct device *dev,
count->function = func_index;
function = count->functions_list[func_index];
- return sprintf(buf, "%s\n", counter_count_function_str[function]);
+ return sprintf(buf, "%s\n", counter_function_str[function]);
}
static ssize_t counter_function_store(struct device *dev,
@@ -785,14 +785,14 @@ static ssize_t counter_function_store(struct device *dev,
struct counter_count *const count = component->count;
const size_t num_functions = count->num_functions;
size_t func_index;
- enum counter_count_function function;
+ enum counter_function function;
int err;
struct counter_device *const counter = dev_get_drvdata(dev);
/* Find requested Count function mode */
for (func_index = 0; func_index < num_functions; func_index++) {
function = count->functions_list[func_index];
- if (sysfs_streq(buf, counter_count_function_str[function]))
+ if (sysfs_streq(buf, counter_function_str[function]))
break;
}
/* Return error if requested Count function mode not found */
@@ -880,25 +880,25 @@ err_free_attr_list:
}
struct counter_func_avail_unit {
- const enum counter_count_function *functions_list;
+ const enum counter_function *functions_list;
size_t num_functions;
};
-static ssize_t counter_count_function_available_show(struct device *dev,
+static ssize_t counter_function_available_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct counter_device_attr *const devattr = to_counter_attr(attr);
const struct counter_func_avail_unit *const component = devattr->component;
- const enum counter_count_function *const func_list = component->functions_list;
+ const enum counter_function *const func_list = component->functions_list;
const size_t num_functions = component->num_functions;
size_t i;
- enum counter_count_function function;
+ enum counter_function function;
ssize_t len = 0;
for (i = 0; i < num_functions; i++) {
function = func_list[i];
len += sprintf(buf + len, "%s\n",
- counter_count_function_str[function]);
+ counter_function_str[function]);
}
return len;
@@ -968,7 +968,7 @@ static int counter_count_attributes_create(
parm.group = group;
parm.prefix = "";
parm.name = "function_available";
- parm.show = counter_count_function_available_show;
+ parm.show = counter_function_available_show;
parm.store = NULL;
parm.component = avail_comp;
err = counter_attribute_create(&parm);
diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c
index 9371532406ca..53c15f84909b 100644
--- a/drivers/counter/ftm-quaddec.c
+++ b/drivers/counter/ftm-quaddec.c
@@ -171,9 +171,8 @@ enum ftm_quaddec_count_function {
FTM_QUADDEC_COUNT_ENCODER_MODE_1,
};
-static const enum counter_count_function ftm_quaddec_count_functions[] = {
- [FTM_QUADDEC_COUNT_ENCODER_MODE_1] =
- COUNTER_COUNT_FUNCTION_QUADRATURE_X4
+static const enum counter_function ftm_quaddec_count_functions[] = {
+ [FTM_QUADDEC_COUNT_ENCODER_MODE_1] = COUNTER_FUNCTION_QUADRATURE_X4
};
static int ftm_quaddec_count_read(struct counter_device *counter,
diff --git a/drivers/counter/intel-qep.c b/drivers/counter/intel-qep.c
index 8d7ae28fbd67..8a6847d5fb2b 100644
--- a/drivers/counter/intel-qep.c
+++ b/drivers/counter/intel-qep.c
@@ -8,7 +8,6 @@
* Author: Jarkko Nikula <jarkko.nikula@linux.intel.com>
* Author: Raymond Tan <raymond.tan@intel.com>
*/
-#include <linux/bitops.h>
#include <linux/counter.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -127,8 +126,8 @@ static int intel_qep_count_read(struct counter_device *counter,
return 0;
}
-static const enum counter_count_function intel_qep_count_functions[] = {
- COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
+static const enum counter_function intel_qep_count_functions[] = {
+ COUNTER_FUNCTION_QUADRATURE_X4,
};
static int intel_qep_function_get(struct counter_device *counter,
@@ -320,7 +319,7 @@ static ssize_t spike_filter_ns_write(struct counter_device *counter,
}
if (length > INTEL_QEPFLT_MAX_COUNT(length))
- return -EINVAL;
+ return -ERANGE;
mutex_lock(&qep->lock);
if (qep->enabled) {
diff --git a/drivers/counter/interrupt-cnt.c b/drivers/counter/interrupt-cnt.c
index 5df7cd13d4c7..1de4243db488 100644
--- a/drivers/counter/interrupt-cnt.c
+++ b/drivers/counter/interrupt-cnt.c
@@ -107,13 +107,16 @@ static int interrupt_cnt_write(struct counter_device *counter,
{
struct interrupt_cnt_priv *priv = counter->priv;
+ if (val != (typeof(priv->count.counter))val)
+ return -ERANGE;
+
atomic_set(&priv->count, val);
return 0;
}
-static const enum counter_count_function interrupt_cnt_functions[] = {
- COUNTER_COUNT_FUNCTION_INCREASE,
+static const enum counter_function interrupt_cnt_functions[] = {
+ COUNTER_FUNCTION_INCREASE,
};
static int interrupt_cnt_function_get(struct counter_device *counter,
@@ -127,7 +130,7 @@ static int interrupt_cnt_function_get(struct counter_device *counter,
static int interrupt_cnt_signal_read(struct counter_device *counter,
struct counter_signal *signal,
- enum counter_signal_value *val)
+ enum counter_signal_level *level)
{
struct interrupt_cnt_priv *priv = counter->priv;
int ret;
@@ -139,7 +142,7 @@ static int interrupt_cnt_signal_read(struct counter_device *counter,
if (ret < 0)
return ret;
- *val = ret ? COUNTER_SIGNAL_HIGH : COUNTER_SIGNAL_LOW;
+ *level = ret ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
return 0;
}
diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index 51b8af80f98b..1aa70b9c4833 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -37,9 +37,9 @@ enum mchp_tc_count_function {
MCHP_TC_FUNCTION_QUADRATURE,
};
-static const enum counter_count_function mchp_tc_count_functions[] = {
- [MCHP_TC_FUNCTION_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE,
- [MCHP_TC_FUNCTION_QUADRATURE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
+static const enum counter_function mchp_tc_count_functions[] = {
+ [MCHP_TC_FUNCTION_INCREASE] = COUNTER_FUNCTION_INCREASE,
+ [MCHP_TC_FUNCTION_QUADRATURE] = COUNTER_FUNCTION_QUADRATURE_X4,
};
enum mchp_tc_synapse_action {
@@ -133,6 +133,9 @@ static int mchp_tc_count_function_set(struct counter_device *counter,
bmr |= ATMEL_TC_QDEN | ATMEL_TC_POSEN;
cmr |= ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_ABETRG | ATMEL_TC_XC0;
break;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
regmap_write(priv->regmap, ATMEL_TC_BMR, bmr);
@@ -155,7 +158,7 @@ static int mchp_tc_count_function_set(struct counter_device *counter,
static int mchp_tc_count_signal_read(struct counter_device *counter,
struct counter_signal *signal,
- enum counter_signal_value *val)
+ enum counter_signal_level *lvl)
{
struct mchp_tc_data *const priv = counter->priv;
bool sigstatus;
@@ -168,7 +171,7 @@ static int mchp_tc_count_signal_read(struct counter_device *counter,
else
sigstatus = (sr & ATMEL_TC_MTIOA);
- *val = sigstatus ? COUNTER_SIGNAL_HIGH : COUNTER_SIGNAL_LOW;
+ *lvl = sigstatus ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
return 0;
}
@@ -226,6 +229,9 @@ static int mchp_tc_count_action_set(struct counter_device *counter,
case MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE:
edge = ATMEL_TC_ETRGEDG_BOTH;
break;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
return regmap_write_bits(priv->regmap,
diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c
index c19d998df5ba..13656957c45f 100644
--- a/drivers/counter/stm32-lptimer-cnt.c
+++ b/drivers/counter/stm32-lptimer-cnt.c
@@ -134,9 +134,9 @@ enum stm32_lptim_cnt_function {
STM32_LPTIM_ENCODER_BOTH_EDGE,
};
-static const enum counter_count_function stm32_lptim_cnt_functions[] = {
- [STM32_LPTIM_COUNTER_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE,
- [STM32_LPTIM_ENCODER_BOTH_EDGE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
+static const enum counter_function stm32_lptim_cnt_functions[] = {
+ [STM32_LPTIM_COUNTER_INCREASE] = COUNTER_FUNCTION_INCREASE,
+ [STM32_LPTIM_ENCODER_BOTH_EDGE] = COUNTER_FUNCTION_QUADRATURE_X4,
};
enum stm32_lptim_synapse_action {
@@ -206,9 +206,10 @@ static int stm32_lptim_cnt_function_set(struct counter_device *counter,
priv->quadrature_mode = 1;
priv->polarity = STM32_LPTIM_SYNAPSE_ACTION_BOTH_EDGES;
return 0;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
-
- return -EINVAL;
}
static ssize_t stm32_lptim_cnt_enable_read(struct counter_device *counter,
@@ -282,7 +283,7 @@ static ssize_t stm32_lptim_cnt_ceiling_write(struct counter_device *counter,
return ret;
if (ceiling > STM32_LPTIM_MAX_ARR)
- return -EINVAL;
+ return -ERANGE;
priv->ceiling = ceiling;
@@ -326,9 +327,10 @@ static int stm32_lptim_cnt_action_get(struct counter_device *counter,
case STM32_LPTIM_ENCODER_BOTH_EDGE:
*action = priv->polarity;
return 0;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
-
- return -EINVAL;
}
static int stm32_lptim_cnt_action_set(struct counter_device *counter,
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 603b30ada839..3fb0debd7425 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -50,11 +50,11 @@ enum stm32_count_function {
STM32_COUNT_ENCODER_MODE_3,
};
-static const enum counter_count_function stm32_count_functions[] = {
- [STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE,
- [STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
- [STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,
- [STM32_COUNT_ENCODER_MODE_3] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
+static const enum counter_function stm32_count_functions[] = {
+ [STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_FUNCTION_INCREASE,
+ [STM32_COUNT_ENCODER_MODE_1] = COUNTER_FUNCTION_QUADRATURE_X2_A,
+ [STM32_COUNT_ENCODER_MODE_2] = COUNTER_FUNCTION_QUADRATURE_X2_B,
+ [STM32_COUNT_ENCODER_MODE_3] = COUNTER_FUNCTION_QUADRATURE_X4,
};
static int stm32_count_read(struct counter_device *counter,
diff --git a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c
index 65df9ef5b5bc..94fe58bb3eab 100644
--- a/drivers/counter/ti-eqep.c
+++ b/drivers/counter/ti-eqep.c
@@ -157,7 +157,7 @@ static int ti_eqep_action_get(struct counter_device *counter,
* QEPA and QEPB trigger QCLK.
*/
*action = TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES;
- break;
+ return 0;
case TI_EQEP_COUNT_FUNC_DIR_COUNT:
/* In direction-count mode only rising edge of QEPA is counted
* and QEPB gives direction.
@@ -165,12 +165,14 @@ static int ti_eqep_action_get(struct counter_device *counter,
switch (synapse->signal->id) {
case TI_EQEP_SIGNAL_QEPA:
*action = TI_EQEP_SYNAPSE_ACTION_RISING_EDGE;
- break;
- default:
+ return 0;
+ case TI_EQEP_SIGNAL_QEPB:
*action = TI_EQEP_SYNAPSE_ACTION_NONE;
- break;
+ return 0;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
- break;
case TI_EQEP_COUNT_FUNC_UP_COUNT:
case TI_EQEP_COUNT_FUNC_DOWN_COUNT:
/* In up/down-count modes only QEPA is counted and QEPB is not
@@ -186,15 +188,18 @@ static int ti_eqep_action_get(struct counter_device *counter,
*action = TI_EQEP_SYNAPSE_ACTION_BOTH_EDGES;
else
*action = TI_EQEP_SYNAPSE_ACTION_RISING_EDGE;
- break;
- default:
+ return 0;
+ case TI_EQEP_SIGNAL_QEPB:
*action = TI_EQEP_SYNAPSE_ACTION_NONE;
- break;
+ return 0;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
- break;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
}
-
- return 0;
}
static const struct counter_ops ti_eqep_counter_ops = {
@@ -289,11 +294,11 @@ static struct counter_signal ti_eqep_signals[] = {
},
};
-static const enum counter_count_function ti_eqep_position_functions[] = {
- [TI_EQEP_COUNT_FUNC_QUAD_COUNT] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
- [TI_EQEP_COUNT_FUNC_DIR_COUNT] = COUNTER_COUNT_FUNCTION_PULSE_DIRECTION,
- [TI_EQEP_COUNT_FUNC_UP_COUNT] = COUNTER_COUNT_FUNCTION_INCREASE,
- [TI_EQEP_COUNT_FUNC_DOWN_COUNT] = COUNTER_COUNT_FUNCTION_DECREASE,
+static const enum counter_function ti_eqep_position_functions[] = {
+ [TI_EQEP_COUNT_FUNC_QUAD_COUNT] = COUNTER_FUNCTION_QUADRATURE_X4,
+ [TI_EQEP_COUNT_FUNC_DIR_COUNT] = COUNTER_FUNCTION_PULSE_DIRECTION,
+ [TI_EQEP_COUNT_FUNC_UP_COUNT] = COUNTER_FUNCTION_INCREASE,
+ [TI_EQEP_COUNT_FUNC_DOWN_COUNT] = COUNTER_FUNCTION_DECREASE,
};
static const enum counter_synapse_action ti_eqep_position_synapse_actions[] = {
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 23a06cba392c..5a2cf5f91ccb 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -36,6 +36,7 @@
#define MAX_PSTATE_SHIFT 32
#define LPSTATE_SHIFT 48
#define GPSTATE_SHIFT 56
+#define MAX_NR_CHIPS 32
#define MAX_RAMP_DOWN_TIME 5120
/*
@@ -1046,12 +1047,20 @@ static int init_chip_info(void)
unsigned int *chip;
unsigned int cpu, i;
unsigned int prev_chip_id = UINT_MAX;
+ cpumask_t *chip_cpu_mask;
int ret = 0;
chip = kcalloc(num_possible_cpus(), sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
+ /* Allocate a chip cpu mask large enough to fit mask for all chips */
+ chip_cpu_mask = kcalloc(MAX_NR_CHIPS, sizeof(cpumask_t), GFP_KERNEL);
+ if (!chip_cpu_mask) {
+ ret = -ENOMEM;
+ goto free_and_return;
+ }
+
for_each_possible_cpu(cpu) {
unsigned int id = cpu_to_chip_id(cpu);
@@ -1059,22 +1068,25 @@ static int init_chip_info(void)
prev_chip_id = id;
chip[nr_chips++] = id;
}
+ cpumask_set_cpu(cpu, &chip_cpu_mask[nr_chips-1]);
}
chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL);
if (!chips) {
ret = -ENOMEM;
- goto free_and_return;
+ goto out_free_chip_cpu_mask;
}
for (i = 0; i < nr_chips; i++) {
chips[i].id = chip[i];
- cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i]));
+ cpumask_copy(&chips[i].mask, &chip_cpu_mask[i]);
INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn);
for_each_cpu(cpu, &chips[i].mask)
per_cpu(chip_info, cpu) = &chips[i];
}
+out_free_chip_cpu_mask:
+ kfree(chip_cpu_mask);
free_and_return:
kfree(chip);
return ret;
diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
index a2b5c6f60cf0..7e7ab5597d7a 100644
--- a/drivers/cpuidle/cpuidle-pseries.c
+++ b/drivers/cpuidle/cpuidle-pseries.c
@@ -346,11 +346,9 @@ static int pseries_cpuidle_driver_init(void)
static void __init fixup_cede0_latency(void)
{
struct xcede_latency_payload *payload;
- u64 min_latency_us;
+ u64 min_xcede_latency_us = UINT_MAX;
int i;
- min_latency_us = dedicated_states[1].exit_latency; // CEDE latency
-
if (parse_cede_parameters())
return;
@@ -358,42 +356,45 @@ static void __init fixup_cede0_latency(void)
nr_xcede_records);
payload = &xcede_latency_parameter.payload;
+
+ /*
+ * The CEDE idle state maps to CEDE(0). While the hypervisor
+ * does not advertise CEDE(0) exit latency values, it does
+ * advertise the latency values of the extended CEDE states.
+ * We use the lowest advertised exit latency value as a proxy
+ * for the exit latency of CEDE(0).
+ */
for (i = 0; i < nr_xcede_records; i++) {
struct xcede_latency_record *record = &payload->records[i];
+ u8 hint = record->hint;
u64 latency_tb = be64_to_cpu(record->latency_ticks);
u64 latency_us = DIV_ROUND_UP_ULL(tb_to_ns(latency_tb), NSEC_PER_USEC);
- if (latency_us == 0)
- pr_warn("cpuidle: xcede record %d has an unrealistic latency of 0us.\n", i);
-
- if (latency_us < min_latency_us)
- min_latency_us = latency_us;
- }
-
- /*
- * By default, we assume that CEDE(0) has exit latency 10us,
- * since there is no way for us to query from the platform.
- *
- * However, if the wakeup latency of an Extended CEDE state is
- * smaller than 10us, then we can be sure that CEDE(0)
- * requires no more than that.
- *
- * Perform the fix-up.
- */
- if (min_latency_us < dedicated_states[1].exit_latency) {
/*
- * We set a minimum of 1us wakeup latency for cede0 to
- * distinguish it from snooze
+ * We expect the exit latency of an extended CEDE
+ * state to be non-zero, it to since it takes at least
+ * a few nanoseconds to wakeup the idle CPU and
+ * dispatch the virtual processor into the Linux
+ * Guest.
+ *
+ * So we consider only non-zero value for performing
+ * the fixup of CEDE(0) latency.
*/
- u64 cede0_latency = 1;
+ if (latency_us == 0) {
+ pr_warn("cpuidle: Skipping xcede record %d [hint=%d]. Exit latency = 0us\n",
+ i, hint);
+ continue;
+ }
- if (min_latency_us > cede0_latency)
- cede0_latency = min_latency_us - 1;
+ if (latency_us < min_xcede_latency_us)
+ min_xcede_latency_us = latency_us;
+ }
- dedicated_states[1].exit_latency = cede0_latency;
- dedicated_states[1].target_residency = 10 * (cede0_latency);
+ if (min_xcede_latency_us != UINT_MAX) {
+ dedicated_states[1].exit_latency = min_xcede_latency_us;
+ dedicated_states[1].target_residency = 10 * (min_xcede_latency_us);
pr_info("cpuidle: Fixed up CEDE exit latency to %llu us\n",
- cede0_latency);
+ min_xcede_latency_us);
}
}
@@ -402,7 +403,7 @@ static void __init fixup_cede0_latency(void)
* pseries_idle_probe()
* Choose state table for shared versus dedicated partition
*/
-static int pseries_idle_probe(void)
+static int __init pseries_idle_probe(void)
{
if (cpuidle_disable != IDLE_NO_OVERRIDE)
@@ -419,7 +420,21 @@ static int pseries_idle_probe(void)
cpuidle_state_table = shared_states;
max_idle_state = ARRAY_SIZE(shared_states);
} else {
- fixup_cede0_latency();
+ /*
+ * Use firmware provided latency values
+ * starting with POWER10 platforms. In the
+ * case that we are running on a POWER10
+ * platform but in an earlier compat mode, we
+ * can still use the firmware provided values.
+ *
+ * However, on platforms prior to POWER10, we
+ * cannot rely on the accuracy of the firmware
+ * provided latency values. On such platforms,
+ * go with the conservative default estimate
+ * of 10us.
+ */
+ if (cpu_has_feature(CPU_FTR_ARCH_31) || pvr_version_is(PVR_POWER10))
+ fixup_cede0_latency();
cpuidle_state_table = dedicated_states;
max_idle_state = NR_DEDICATED_STATES;
}
diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c
index a2d34be17a09..f7d778580e9b 100644
--- a/drivers/cpuidle/cpuidle-ux500.c
+++ b/drivers/cpuidle/cpuidle-ux500.c
@@ -117,7 +117,7 @@ static int dbx500_cpuidle_probe(struct platform_device *pdev)
static struct platform_driver dbx500_cpuidle_plat_driver = {
.driver = {
- .name = "cpuidle-dbx500",
+ .name = "db8500-cpuidle",
},
.probe = dbx500_cpuidle_probe,
};
diff --git a/drivers/cxl/core.c b/drivers/cxl/core.c
index a2e4d54fc7bc..2b90b7c3b9d7 100644
--- a/drivers/cxl/core.c
+++ b/drivers/cxl/core.c
@@ -1034,13 +1034,12 @@ static int cxl_bus_probe(struct device *dev)
return to_cxl_drv(dev->driver)->probe(dev);
}
-static int cxl_bus_remove(struct device *dev)
+static void cxl_bus_remove(struct device *dev)
{
struct cxl_driver *cxl_drv = to_cxl_drv(dev->driver);
if (cxl_drv->remove)
cxl_drv->remove(dev);
- return 0;
}
struct bus_type cxl_bus_type = {
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index 5aee26e1bbd6..6cc4da4c713d 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -172,15 +172,13 @@ static int dax_bus_probe(struct device *dev)
return 0;
}
-static int dax_bus_remove(struct device *dev)
+static void dax_bus_remove(struct device *dev)
{
struct dax_device_driver *dax_drv = to_dax_drv(dev->driver);
struct dev_dax *dev_dax = to_dev_dax(dev);
if (dax_drv->remove)
dax_drv->remove(dev_dax);
-
- return 0;
}
static struct bus_type dax_bus_type = {
diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c
index 193b40e7aec0..4c06c93c93d3 100644
--- a/drivers/dio/dio.c
+++ b/drivers/dio/dio.c
@@ -219,7 +219,7 @@ static int __init dio_init(void)
/* Found a board, allocate it an entry in the list */
dev = kzalloc(sizeof(struct dio_dev), GFP_KERNEL);
if (!dev)
- return 0;
+ return -ENOMEM;
dev->bus = &dio_bus;
dev->dev.parent = &dio_bus.dev;
diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig
index 4e16c71c24b7..9561e3d2d428 100644
--- a/drivers/dma-buf/Kconfig
+++ b/drivers/dma-buf/Kconfig
@@ -72,6 +72,17 @@ menuconfig DMABUF_HEAPS
allows userspace to allocate dma-bufs that can be shared
between drivers.
+menuconfig DMABUF_SYSFS_STATS
+ bool "DMA-BUF sysfs statistics"
+ select DMA_SHARED_BUFFER
+ help
+ Choose this option to enable DMA-BUF sysfs statistics
+ in location /sys/kernel/dmabuf/buffers.
+
+ /sys/kernel/dmabuf/buffers/<inode_number> will contain
+ statistics for the DMA-BUF with the unique inode number
+ <inode_number>.
+
source "drivers/dma-buf/heaps/Kconfig"
endmenu
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 995e05f609ff..40d81f23cacf 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_DMABUF_HEAPS) += heaps/
obj-$(CONFIG_SYNC_FILE) += sync_file.o
obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o
obj-$(CONFIG_UDMABUF) += udmabuf.o
+obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o
dmabuf_selftests-y := \
selftest.o \
diff --git a/drivers/dma-buf/dma-buf-sysfs-stats.c b/drivers/dma-buf/dma-buf-sysfs-stats.c
new file mode 100644
index 000000000000..053baadcada9
--- /dev/null
+++ b/drivers/dma-buf/dma-buf-sysfs-stats.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DMA-BUF sysfs statistics.
+ *
+ * Copyright (C) 2021 Google LLC.
+ */
+
+#include <linux/dma-buf.h>
+#include <linux/dma-resv.h>
+#include <linux/kobject.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include "dma-buf-sysfs-stats.h"
+
+#define to_dma_buf_entry_from_kobj(x) container_of(x, struct dma_buf_sysfs_entry, kobj)
+
+/**
+ * DOC: overview
+ *
+ * ``/sys/kernel/debug/dma_buf/bufinfo`` provides an overview of every DMA-BUF
+ * in the system. However, since debugfs is not safe to be mounted in
+ * production, procfs and sysfs can be used to gather DMA-BUF statistics on
+ * production systems.
+ *
+ * The ``/proc/<pid>/fdinfo/<fd>`` files in procfs can be used to gather
+ * information about DMA-BUF fds. Detailed documentation about the interface
+ * is present in Documentation/filesystems/proc.rst.
+ *
+ * Unfortunately, the existing procfs interfaces can only provide information
+ * about the DMA-BUFs for which processes hold fds or have the buffers mmapped
+ * into their address space. This necessitated the creation of the DMA-BUF sysfs
+ * statistics interface to provide per-buffer information on production systems.
+ *
+ * The interface at ``/sys/kernel/dma-buf/buffers`` exposes information about
+ * every DMA-BUF when ``CONFIG_DMABUF_SYSFS_STATS`` is enabled.
+ *
+ * The following stats are exposed by the interface:
+ *
+ * * ``/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name``
+ * * ``/sys/kernel/dmabuf/buffers/<inode_number>/size``
+ *
+ * The information in the interface can also be used to derive per-exporter
+ * statistics. The data from the interface can be gathered on error conditions
+ * or other important events to provide a snapshot of DMA-BUF usage.
+ * It can also be collected periodically by telemetry to monitor various metrics.
+ *
+ * Detailed documentation about the interface is present in
+ * Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers.
+ */
+
+struct dma_buf_stats_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct dma_buf *dmabuf,
+ struct dma_buf_stats_attribute *attr, char *buf);
+};
+#define to_dma_buf_stats_attr(x) container_of(x, struct dma_buf_stats_attribute, attr)
+
+static ssize_t dma_buf_stats_attribute_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct dma_buf_stats_attribute *attribute;
+ struct dma_buf_sysfs_entry *sysfs_entry;
+ struct dma_buf *dmabuf;
+
+ attribute = to_dma_buf_stats_attr(attr);
+ sysfs_entry = to_dma_buf_entry_from_kobj(kobj);
+ dmabuf = sysfs_entry->dmabuf;
+
+ if (!dmabuf || !attribute->show)
+ return -EIO;
+
+ return attribute->show(dmabuf, attribute, buf);
+}
+
+static const struct sysfs_ops dma_buf_stats_sysfs_ops = {
+ .show = dma_buf_stats_attribute_show,
+};
+
+static ssize_t exporter_name_show(struct dma_buf *dmabuf,
+ struct dma_buf_stats_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%s\n", dmabuf->exp_name);
+}
+
+static ssize_t size_show(struct dma_buf *dmabuf,
+ struct dma_buf_stats_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%zu\n", dmabuf->size);
+}
+
+static struct dma_buf_stats_attribute exporter_name_attribute =
+ __ATTR_RO(exporter_name);
+static struct dma_buf_stats_attribute size_attribute = __ATTR_RO(size);
+
+static struct attribute *dma_buf_stats_default_attrs[] = {
+ &exporter_name_attribute.attr,
+ &size_attribute.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(dma_buf_stats_default);
+
+static void dma_buf_sysfs_release(struct kobject *kobj)
+{
+ struct dma_buf_sysfs_entry *sysfs_entry;
+
+ sysfs_entry = to_dma_buf_entry_from_kobj(kobj);
+ kfree(sysfs_entry);
+}
+
+static struct kobj_type dma_buf_ktype = {
+ .sysfs_ops = &dma_buf_stats_sysfs_ops,
+ .release = dma_buf_sysfs_release,
+ .default_groups = dma_buf_stats_default_groups,
+};
+
+void dma_buf_stats_teardown(struct dma_buf *dmabuf)
+{
+ struct dma_buf_sysfs_entry *sysfs_entry;
+
+ sysfs_entry = dmabuf->sysfs_entry;
+ if (!sysfs_entry)
+ return;
+
+ kobject_del(&sysfs_entry->kobj);
+ kobject_put(&sysfs_entry->kobj);
+}
+
+
+/* Statistics files do not need to send uevents. */
+static int dmabuf_sysfs_uevent_filter(struct kset *kset, struct kobject *kobj)
+{
+ return 0;
+}
+
+static const struct kset_uevent_ops dmabuf_sysfs_no_uevent_ops = {
+ .filter = dmabuf_sysfs_uevent_filter,
+};
+
+static struct kset *dma_buf_stats_kset;
+static struct kset *dma_buf_per_buffer_stats_kset;
+int dma_buf_init_sysfs_statistics(void)
+{
+ dma_buf_stats_kset = kset_create_and_add("dmabuf",
+ &dmabuf_sysfs_no_uevent_ops,
+ kernel_kobj);
+ if (!dma_buf_stats_kset)
+ return -ENOMEM;
+
+ dma_buf_per_buffer_stats_kset = kset_create_and_add("buffers",
+ &dmabuf_sysfs_no_uevent_ops,
+ &dma_buf_stats_kset->kobj);
+ if (!dma_buf_per_buffer_stats_kset) {
+ kset_unregister(dma_buf_stats_kset);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void dma_buf_uninit_sysfs_statistics(void)
+{
+ kset_unregister(dma_buf_per_buffer_stats_kset);
+ kset_unregister(dma_buf_stats_kset);
+}
+
+int dma_buf_stats_setup(struct dma_buf *dmabuf)
+{
+ struct dma_buf_sysfs_entry *sysfs_entry;
+ int ret;
+
+ if (!dmabuf || !dmabuf->file)
+ return -EINVAL;
+
+ if (!dmabuf->exp_name) {
+ pr_err("exporter name must not be empty if stats needed\n");
+ return -EINVAL;
+ }
+
+ sysfs_entry = kzalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL);
+ if (!sysfs_entry)
+ return -ENOMEM;
+
+ sysfs_entry->kobj.kset = dma_buf_per_buffer_stats_kset;
+ sysfs_entry->dmabuf = dmabuf;
+
+ dmabuf->sysfs_entry = sysfs_entry;
+
+ /* create the directory for buffer stats */
+ ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype, NULL,
+ "%lu", file_inode(dmabuf->file)->i_ino);
+ if (ret)
+ goto err_sysfs_dmabuf;
+
+ return 0;
+
+err_sysfs_dmabuf:
+ kobject_put(&sysfs_entry->kobj);
+ dmabuf->sysfs_entry = NULL;
+ return ret;
+}
diff --git a/drivers/dma-buf/dma-buf-sysfs-stats.h b/drivers/dma-buf/dma-buf-sysfs-stats.h
new file mode 100644
index 000000000000..a49c6e2650cc
--- /dev/null
+++ b/drivers/dma-buf/dma-buf-sysfs-stats.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * DMA-BUF sysfs statistics.
+ *
+ * Copyright (C) 2021 Google LLC.
+ */
+
+#ifndef _DMA_BUF_SYSFS_STATS_H
+#define _DMA_BUF_SYSFS_STATS_H
+
+#ifdef CONFIG_DMABUF_SYSFS_STATS
+
+int dma_buf_init_sysfs_statistics(void);
+void dma_buf_uninit_sysfs_statistics(void);
+
+int dma_buf_stats_setup(struct dma_buf *dmabuf);
+
+void dma_buf_stats_teardown(struct dma_buf *dmabuf);
+#else
+
+static inline int dma_buf_init_sysfs_statistics(void)
+{
+ return 0;
+}
+
+static inline void dma_buf_uninit_sysfs_statistics(void) {}
+
+static inline int dma_buf_stats_setup(struct dma_buf *dmabuf)
+{
+ return 0;
+}
+
+static inline void dma_buf_stats_teardown(struct dma_buf *dmabuf) {}
+#endif
+#endif // _DMA_BUF_SYSFS_STATS_H
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 511fe0d217a0..63d32261b63f 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -29,6 +29,8 @@
#include <uapi/linux/dma-buf.h>
#include <uapi/linux/magic.h>
+#include "dma-buf-sysfs-stats.h"
+
static inline int is_dma_buf_file(struct file *);
struct dma_buf_list {
@@ -74,6 +76,7 @@ static void dma_buf_release(struct dentry *dentry)
*/
BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active);
+ dma_buf_stats_teardown(dmabuf);
dmabuf->ops->release(dmabuf);
if (dmabuf->resv == (struct dma_resv *)&dmabuf[1])
@@ -580,6 +583,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
file->f_mode |= FMODE_LSEEK;
dmabuf->file = file;
+ ret = dma_buf_stats_setup(dmabuf);
+ if (ret)
+ goto err_sysfs;
+
mutex_init(&dmabuf->lock);
INIT_LIST_HEAD(&dmabuf->attachments);
@@ -589,6 +596,14 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
return dmabuf;
+err_sysfs:
+ /*
+ * Set file->f_path.dentry->d_fsdata to NULL so that when
+ * dma_buf_release() gets invoked by dentry_ops, it exits
+ * early before calling the release() dma_buf op.
+ */
+ file->f_path.dentry->d_fsdata = NULL;
+ fput(file);
err_dmabuf:
kfree(dmabuf);
err_module:
@@ -926,6 +941,9 @@ EXPORT_SYMBOL_GPL(dma_buf_unpin);
* the underlying backing storage is pinned for as long as a mapping exists,
* therefore users/importers should not hold onto a mapping for undue amounts of
* time.
+ *
+ * Important: Dynamic importers must wait for the exclusive fence of the struct
+ * dma_resv attached to the DMA-BUF first.
*/
struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
@@ -992,7 +1010,6 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
}
}
#endif /* CONFIG_DMA_API_DEBUG */
-
return sg_table;
}
EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
@@ -1469,6 +1486,12 @@ static inline void dma_buf_uninit_debugfs(void)
static int __init dma_buf_init(void)
{
+ int ret;
+
+ ret = dma_buf_init_sysfs_statistics();
+ if (ret)
+ return ret;
+
dma_buf_mnt = kern_mount(&dma_buf_fs_type);
if (IS_ERR(dma_buf_mnt))
return PTR_ERR(dma_buf_mnt);
@@ -1484,5 +1507,6 @@ static void __exit dma_buf_deinit(void)
{
dma_buf_uninit_debugfs();
kern_unmount(dma_buf_mnt);
+ dma_buf_uninit_sysfs_statistics();
}
__exitcall(dma_buf_deinit);
diff --git a/drivers/dma-buf/dma-fence-chain.c b/drivers/dma-buf/dma-fence-chain.c
index 7d129e68ac70..1b4cb3e5cec9 100644
--- a/drivers/dma-buf/dma-fence-chain.c
+++ b/drivers/dma-buf/dma-fence-chain.c
@@ -137,6 +137,7 @@ static void dma_fence_chain_cb(struct dma_fence *f, struct dma_fence_cb *cb)
struct dma_fence_chain *chain;
chain = container_of(cb, typeof(*chain), cb);
+ init_irq_work(&chain->work, dma_fence_chain_irq_work);
irq_work_queue(&chain->work);
dma_fence_put(f);
}
@@ -239,7 +240,6 @@ void dma_fence_chain_init(struct dma_fence_chain *chain,
rcu_assign_pointer(chain->prev, prev);
chain->fence = fence;
chain->prev_seqno = 0;
- init_irq_work(&chain->work, dma_fence_chain_irq_work);
/* Try to reuse the context of the previous chain node. */
if (prev_chain && __dma_fence_is_later(seqno, prev->seqno, prev->ops)) {
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index f26c71747d43..e744fd87c63c 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -615,25 +615,21 @@ static inline int dma_resv_test_signaled_single(struct dma_fence *passed_fence)
*/
bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all)
{
- unsigned int seq, shared_count;
+ struct dma_fence *fence;
+ unsigned int seq;
int ret;
rcu_read_lock();
retry:
ret = true;
- shared_count = 0;
seq = read_seqcount_begin(&obj->seq);
if (test_all) {
struct dma_resv_list *fobj = dma_resv_shared_list(obj);
- unsigned int i;
-
- if (fobj)
- shared_count = fobj->shared_count;
+ unsigned int i, shared_count;
+ shared_count = fobj ? fobj->shared_count : 0;
for (i = 0; i < shared_count; ++i) {
- struct dma_fence *fence;
-
fence = rcu_dereference(fobj->shared[i]);
ret = dma_resv_test_signaled_single(fence);
if (ret < 0)
@@ -641,24 +637,19 @@ retry:
else if (!ret)
break;
}
-
- if (read_seqcount_retry(&obj->seq, seq))
- goto retry;
}
- if (!shared_count) {
- struct dma_fence *fence_excl = dma_resv_excl_fence(obj);
-
- if (fence_excl) {
- ret = dma_resv_test_signaled_single(fence_excl);
- if (ret < 0)
- goto retry;
+ fence = dma_resv_excl_fence(obj);
+ if (ret && fence) {
+ ret = dma_resv_test_signaled_single(fence);
+ if (ret < 0)
+ goto retry;
- if (read_seqcount_retry(&obj->seq, seq))
- goto retry;
- }
}
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto retry;
+
rcu_read_unlock();
return ret;
}
diff --git a/drivers/dma-buf/st-dma-fence-chain.c b/drivers/dma-buf/st-dma-fence-chain.c
index 9525f7f56119..8ce1ea59d31b 100644
--- a/drivers/dma-buf/st-dma-fence-chain.c
+++ b/drivers/dma-buf/st-dma-fence-chain.c
@@ -58,28 +58,20 @@ static struct dma_fence *mock_fence(void)
return &f->base;
}
-static inline struct mock_chain {
- struct dma_fence_chain base;
-} *to_mock_chain(struct dma_fence *f) {
- return container_of(f, struct mock_chain, base.base);
-}
-
static struct dma_fence *mock_chain(struct dma_fence *prev,
struct dma_fence *fence,
u64 seqno)
{
- struct mock_chain *f;
+ struct dma_fence_chain *f;
- f = kmalloc(sizeof(*f), GFP_KERNEL);
+ f = dma_fence_chain_alloc();
if (!f)
return NULL;
- dma_fence_chain_init(&f->base,
- dma_fence_get(prev),
- dma_fence_get(fence),
+ dma_fence_chain_init(f, dma_fence_get(prev), dma_fence_get(fence),
seqno);
- return &f->base.base;
+ return &f->base;
}
static int sanitycheck(void *arg)
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index db732f71e59a..c57a609db75b 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -11,9 +11,15 @@
#include <linux/shmem_fs.h>
#include <linux/slab.h>
#include <linux/udmabuf.h>
+#include <linux/hugetlb.h>
-static const u32 list_limit = 1024; /* udmabuf_create_list->count limit */
-static const size_t size_limit_mb = 64; /* total dmabuf size, in megabytes */
+static int list_limit = 1024;
+module_param(list_limit, int, 0644);
+MODULE_PARM_DESC(list_limit, "udmabuf_create_list->count limit. Default is 1024.");
+
+static int size_limit_mb = 64;
+module_param(size_limit_mb, int, 0644);
+MODULE_PARM_DESC(size_limit_mb, "Max size of a dmabuf, in megabytes. Default is 64.");
struct udmabuf {
pgoff_t pagecount;
@@ -160,10 +166,13 @@ static long udmabuf_create(struct miscdevice *device,
{
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct file *memfd = NULL;
+ struct address_space *mapping = NULL;
struct udmabuf *ubuf;
struct dma_buf *buf;
pgoff_t pgoff, pgcnt, pgidx, pgbuf = 0, pglimit;
- struct page *page;
+ struct page *page, *hpage = NULL;
+ pgoff_t subpgoff, maxsubpgs;
+ struct hstate *hpstate;
int seals, ret = -EINVAL;
u32 i, flags;
@@ -194,7 +203,8 @@ static long udmabuf_create(struct miscdevice *device,
memfd = fget(list[i].memfd);
if (!memfd)
goto err;
- if (!shmem_mapping(file_inode(memfd)->i_mapping))
+ mapping = file_inode(memfd)->i_mapping;
+ if (!shmem_mapping(mapping) && !is_file_hugepages(memfd))
goto err;
seals = memfd_fcntl(memfd, F_GET_SEALS, 0);
if (seals == -EINVAL)
@@ -205,17 +215,48 @@ static long udmabuf_create(struct miscdevice *device,
goto err;
pgoff = list[i].offset >> PAGE_SHIFT;
pgcnt = list[i].size >> PAGE_SHIFT;
+ if (is_file_hugepages(memfd)) {
+ hpstate = hstate_file(memfd);
+ pgoff = list[i].offset >> huge_page_shift(hpstate);
+ subpgoff = (list[i].offset &
+ ~huge_page_mask(hpstate)) >> PAGE_SHIFT;
+ maxsubpgs = huge_page_size(hpstate) >> PAGE_SHIFT;
+ }
for (pgidx = 0; pgidx < pgcnt; pgidx++) {
- page = shmem_read_mapping_page(
- file_inode(memfd)->i_mapping, pgoff + pgidx);
- if (IS_ERR(page)) {
- ret = PTR_ERR(page);
- goto err;
+ if (is_file_hugepages(memfd)) {
+ if (!hpage) {
+ hpage = find_get_page_flags(mapping, pgoff,
+ FGP_ACCESSED);
+ if (!hpage) {
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+ page = hpage + subpgoff;
+ get_page(page);
+ subpgoff++;
+ if (subpgoff == maxsubpgs) {
+ put_page(hpage);
+ hpage = NULL;
+ subpgoff = 0;
+ pgoff++;
+ }
+ } else {
+ page = shmem_read_mapping_page(mapping,
+ pgoff + pgidx);
+ if (IS_ERR(page)) {
+ ret = PTR_ERR(page);
+ goto err;
+ }
}
ubuf->pages[pgbuf++] = page;
}
fput(memfd);
memfd = NULL;
+ if (hpage) {
+ put_page(hpage);
+ hpage = NULL;
+ }
}
exp_info.ops = &udmabuf_ops;
diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
index bb4df63906a7..26d8ff97d13d 100644
--- a/drivers/dma/idxd/sysfs.c
+++ b/drivers/dma/idxd/sysfs.c
@@ -260,7 +260,7 @@ static void disable_wq(struct idxd_wq *wq)
dev_info(dev, "wq %s disabled\n", dev_name(&wq->conf_dev));
}
-static int idxd_config_bus_remove(struct device *dev)
+static void idxd_config_bus_remove(struct device *dev)
{
int rc;
@@ -305,8 +305,6 @@ static int idxd_config_bus_remove(struct device *dev)
dev_info(dev, "Device %s disabled\n", dev_name(dev));
}
-
- return 0;
}
static void idxd_config_bus_shutdown(struct device *dev)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 8070fd664bfc..cacc725ca545 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -198,12 +198,12 @@ struct sdma_script_start_addrs {
s32 per_2_firi_addr;
s32 mcu_2_firi_addr;
s32 uart_2_per_addr;
- s32 uart_2_mcu_addr;
+ s32 uart_2_mcu_ram_addr;
s32 per_2_app_addr;
s32 mcu_2_app_addr;
s32 per_2_per_addr;
s32 uartsh_2_per_addr;
- s32 uartsh_2_mcu_addr;
+ s32 uartsh_2_mcu_ram_addr;
s32 per_2_shp_addr;
s32 mcu_2_shp_addr;
s32 ata_2_mcu_addr;
@@ -230,6 +230,10 @@ struct sdma_script_start_addrs {
s32 zcanfd_2_mcu_addr;
s32 zqspi_2_mcu_addr;
s32 mcu_2_ecspi_addr;
+ s32 mcu_2_sai_addr;
+ s32 sai_2_mcu_addr;
+ s32 uart_2_mcu_addr;
+ s32 uartsh_2_mcu_addr;
/* End of v3 array */
s32 mcu_2_zqspi_addr;
/* End of v4 array */
@@ -433,9 +437,10 @@ struct sdma_channel {
unsigned long watermark_level;
u32 shp_addr, per_addr;
enum dma_status status;
- bool context_loaded;
struct imx_dma_data data;
struct work_struct terminate_worker;
+ struct list_head terminated;
+ bool is_ram_script;
};
#define IMX_DMA_SG_LOOP BIT(0)
@@ -476,6 +481,13 @@ struct sdma_driver_data {
int num_events;
struct sdma_script_start_addrs *script_addrs;
bool check_ratio;
+ /*
+ * ecspi ERR009165 fixed should be done in sdma script
+ * and it has been fixed in soc from i.mx6ul.
+ * please get more information from the below link:
+ * https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf
+ */
+ bool ecspi_fixed;
};
struct sdma_engine {
@@ -499,6 +511,7 @@ struct sdma_engine {
struct sdma_buffer_descriptor *bd0;
/* clock ratio for AHB:SDMA core. 1:1 is 1, 2:1 is 0*/
bool clk_ratio;
+ bool fw_loaded;
};
static int sdma_config_write(struct dma_chan *chan,
@@ -595,6 +608,13 @@ static struct sdma_driver_data sdma_imx6q = {
.script_addrs = &sdma_script_imx6q,
};
+static struct sdma_driver_data sdma_imx6ul = {
+ .chnenbl0 = SDMA_CHNENBL0_IMX35,
+ .num_events = 48,
+ .script_addrs = &sdma_script_imx6q,
+ .ecspi_fixed = true,
+};
+
static struct sdma_script_start_addrs sdma_script_imx7d = {
.ap_2_ap_addr = 644,
.uart_2_mcu_addr = 819,
@@ -628,6 +648,7 @@ static const struct of_device_id sdma_dt_ids[] = {
{ .compatible = "fsl,imx31-sdma", .data = &sdma_imx31, },
{ .compatible = "fsl,imx25-sdma", .data = &sdma_imx25, },
{ .compatible = "fsl,imx7d-sdma", .data = &sdma_imx7d, },
+ { .compatible = "fsl,imx6ul-sdma", .data = &sdma_imx6ul, },
{ .compatible = "fsl,imx8mq-sdma", .data = &sdma_imx8mq, },
{ /* sentinel */ }
};
@@ -919,6 +940,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
sdmac->pc_to_device = 0;
sdmac->device_to_device = 0;
sdmac->pc_to_pc = 0;
+ sdmac->is_ram_script = false;
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
@@ -945,6 +967,17 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
emi_2_per = sdma->script_addrs->mcu_2_ata_addr;
break;
case IMX_DMATYPE_CSPI:
+ per_2_emi = sdma->script_addrs->app_2_mcu_addr;
+
+ /* Use rom script mcu_2_app if ERR009165 fixed */
+ if (sdmac->sdma->drvdata->ecspi_fixed) {
+ emi_2_per = sdma->script_addrs->mcu_2_app_addr;
+ } else {
+ emi_2_per = sdma->script_addrs->mcu_2_ecspi_addr;
+ sdmac->is_ram_script = true;
+ }
+
+ break;
case IMX_DMATYPE_EXT:
case IMX_DMATYPE_SSI:
case IMX_DMATYPE_SAI:
@@ -954,6 +987,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
case IMX_DMATYPE_SSI_DUAL:
per_2_emi = sdma->script_addrs->ssish_2_mcu_addr;
emi_2_per = sdma->script_addrs->mcu_2_ssish_addr;
+ sdmac->is_ram_script = true;
break;
case IMX_DMATYPE_SSI_SP:
case IMX_DMATYPE_MMC:
@@ -968,6 +1002,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
per_2_emi = sdma->script_addrs->asrc_2_mcu_addr;
emi_2_per = sdma->script_addrs->asrc_2_mcu_addr;
per_2_per = sdma->script_addrs->per_2_per_addr;
+ sdmac->is_ram_script = true;
break;
case IMX_DMATYPE_ASRC_SP:
per_2_emi = sdma->script_addrs->shp_2_mcu_addr;
@@ -1008,9 +1043,6 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int ret;
unsigned long flags;
- if (sdmac->context_loaded)
- return 0;
-
if (sdmac->direction == DMA_DEV_TO_MEM)
load_address = sdmac->pc_from_device;
else if (sdmac->direction == DMA_DEV_TO_DEV)
@@ -1053,8 +1085,6 @@ static int sdma_load_context(struct sdma_channel *sdmac)
spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
- sdmac->context_loaded = true;
-
return ret;
}
@@ -1078,9 +1108,6 @@ static void sdma_channel_terminate_work(struct work_struct *work)
{
struct sdma_channel *sdmac = container_of(work, struct sdma_channel,
terminate_worker);
- unsigned long flags;
- LIST_HEAD(head);
-
/*
* According to NXP R&D team a delay of one BD SDMA cost time
* (maximum is 1ms) should be added after disable of the channel
@@ -1089,11 +1116,7 @@ static void sdma_channel_terminate_work(struct work_struct *work)
*/
usleep_range(1000, 2000);
- spin_lock_irqsave(&sdmac->vc.lock, flags);
- vchan_get_all_descriptors(&sdmac->vc, &head);
- spin_unlock_irqrestore(&sdmac->vc.lock, flags);
- vchan_dma_desc_free_list(&sdmac->vc, &head);
- sdmac->context_loaded = false;
+ vchan_dma_desc_free_list(&sdmac->vc, &sdmac->terminated);
}
static int sdma_terminate_all(struct dma_chan *chan)
@@ -1107,6 +1130,13 @@ static int sdma_terminate_all(struct dma_chan *chan)
if (sdmac->desc) {
vchan_terminate_vdesc(&sdmac->desc->vd);
+ /*
+ * move out current descriptor into terminated list so that
+ * it could be free in sdma_channel_terminate_work alone
+ * later without potential involving next descriptor raised
+ * up before the last descriptor terminated.
+ */
+ vchan_get_all_descriptors(&sdmac->vc, &sdmac->terminated);
sdmac->desc = NULL;
schedule_work(&sdmac->terminate_worker);
}
@@ -1168,7 +1198,6 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
static int sdma_config_channel(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
- int ret;
sdma_disable_channel(chan);
@@ -1208,9 +1237,7 @@ static int sdma_config_channel(struct dma_chan *chan)
sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */
}
- ret = sdma_load_context(sdmac);
-
- return ret;
+ return 0;
}
static int sdma_set_channel_priority(struct sdma_channel *sdmac,
@@ -1361,7 +1388,6 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
sdmac->event_id0 = 0;
sdmac->event_id1 = 0;
- sdmac->context_loaded = false;
sdma_set_channel_priority(sdmac, 0);
@@ -1374,6 +1400,11 @@ static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
{
struct sdma_desc *desc;
+ if (!sdmac->sdma->fw_loaded && sdmac->is_ram_script) {
+ dev_warn_once(sdmac->sdma->dev, "sdma firmware not ready!\n");
+ goto err_out;
+ }
+
desc = kzalloc((sizeof(*desc)), GFP_NOWAIT);
if (!desc)
goto err_out;
@@ -1722,8 +1753,8 @@ static void sdma_issue_pending(struct dma_chan *chan)
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2 38
-#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3 41
-#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V4 42
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3 45
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V4 46
static void sdma_add_scripts(struct sdma_engine *sdma,
const struct sdma_script_start_addrs *addr)
@@ -1747,6 +1778,19 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
for (i = 0; i < sdma->script_number; i++)
if (addr_arr[i] > 0)
saddr_arr[i] = addr_arr[i];
+
+ /*
+ * get uart_2_mcu_addr/uartsh_2_mcu_addr rom script specially because
+ * they are now replaced by uart_2_mcu_ram_addr/uartsh_2_mcu_ram_addr
+ * to be compatible with legacy freescale/nxp sdma firmware, and they
+ * are located in the bottom part of sdma_script_start_addrs which are
+ * beyond the SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1.
+ */
+ if (addr->uart_2_mcu_addr)
+ sdma->script_addrs->uart_2_mcu_addr = addr->uart_2_mcu_addr;
+ if (addr->uartsh_2_mcu_addr)
+ sdma->script_addrs->uartsh_2_mcu_addr = addr->uartsh_2_mcu_addr;
+
}
static void sdma_load_firmware(const struct firmware *fw, void *context)
@@ -1803,6 +1847,8 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
sdma_add_scripts(sdma, addr);
+ sdma->fw_loaded = true;
+
dev_info(sdma->dev, "loaded firmware %d.%d\n",
header->version_major,
header->version_minor);
@@ -2086,6 +2132,7 @@ static int sdma_probe(struct platform_device *pdev)
sdmac->channel = i;
sdmac->vc.desc_free = sdma_desc_free;
+ INIT_LIST_HEAD(&sdmac->terminated);
INIT_WORK(&sdmac->terminate_worker,
sdma_channel_terminate_work);
/*
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 68216988391f..90ed8fdaba75 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -187,14 +187,12 @@ static int fw_unit_probe(struct device *dev)
return driver->probe(fw_unit(dev), unit_match(dev, dev->driver));
}
-static int fw_unit_remove(struct device *dev)
+static void fw_unit_remove(struct device *dev)
{
struct fw_driver *driver =
container_of(dev->driver, struct fw_driver, driver);
driver->remove(fw_unit(dev));
-
- return 0;
}
static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 1db738d5b301..220a58cf0a44 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -6,39 +6,7 @@
menu "Firmware Drivers"
-config ARM_SCMI_PROTOCOL
- tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
- depends on ARM || ARM64 || COMPILE_TEST
- depends on MAILBOX || HAVE_ARM_SMCCC_DISCOVERY
- help
- ARM System Control and Management Interface (SCMI) protocol is a
- set of operating system-independent software interfaces that are
- used in system management. SCMI is extensible and currently provides
- interfaces for: Discovery and self-description of the interfaces
- it supports, Power domain management which is the ability to place
- a given device or domain into the various power-saving states that
- it supports, Performance management which is the ability to control
- the performance of a domain that is composed of compute engines
- such as application processors and other accelerators, Clock
- management which is the ability to set and inquire rates on platform
- managed clocks and Sensor management which is the ability to read
- sensor data, and be notified of sensor value.
-
- This protocol library provides interface for all the client drivers
- making use of the features offered by the SCMI.
-
-config ARM_SCMI_POWER_DOMAIN
- tristate "SCMI power domain driver"
- depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
- default y
- select PM_GENERIC_DOMAINS if PM
- help
- This enables support for the SCMI power domains which can be
- enabled or disabled via the SCP firmware
-
- This driver can also be built as a module. If so, the module
- will be called scmi_pm_domain. Note this may needed early in boot
- before rootfs may be available.
+source "drivers/firmware/arm_scmi/Kconfig"
config ARM_SCPI_PROTOCOL
tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
@@ -235,7 +203,7 @@ config INTEL_STRATIX10_RSU
Say Y here if you want Intel RSU support.
config QCOM_SCM
- bool
+ tristate "Qcom SCM driver"
depends on ARM || ARM64
depends on HAVE_ARM_SMCCC
select RESET_CONTROLLER
@@ -251,6 +219,38 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
Say Y here to enable "download mode" by default.
+config SYSFB
+ bool
+ default y
+ depends on X86 || EFI
+
+config SYSFB_SIMPLEFB
+ bool "Mark VGA/VBE/EFI FB as generic system framebuffer"
+ depends on SYSFB
+ help
+ Firmwares often provide initial graphics framebuffers so the BIOS,
+ bootloader or kernel can show basic video-output during boot for
+ user-guidance and debugging. Historically, x86 used the VESA BIOS
+ Extensions and EFI-framebuffers for this, which are mostly limited
+ to x86 BIOS or EFI systems.
+ This option, if enabled, marks VGA/VBE/EFI framebuffers as generic
+ framebuffers so the new generic system-framebuffer drivers can be
+ used instead. If the framebuffer is not compatible with the generic
+ modes, it is advertised as fallback platform framebuffer so legacy
+ drivers like efifb, vesafb and uvesafb can pick it up.
+ If this option is not selected, all system framebuffers are always
+ marked as fallback platform framebuffers as usual.
+
+ Note: Legacy fbdev drivers, including vesafb, efifb, uvesafb, will
+ not be able to pick up generic system framebuffers if this option
+ is selected. You are highly encouraged to enable simplefb as
+ replacement if you select this option. simplefb can correctly deal
+ with generic system framebuffers. But you should still keep vesafb
+ and others enabled as fallback if a system framebuffer is
+ incompatible with simplefb.
+
+ If unsure, say Y.
+
config TI_SCI_PROTOCOL
tristate "TI System Control Interface (TISCI) Message Protocol"
depends on TI_MESSAGE_MANAGER
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 546ac8e7f6d0..5ced0673d94b 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -17,7 +17,10 @@ obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o
-obj-$(CONFIG_QCOM_SCM) += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
+obj-$(CONFIG_QCOM_SCM) += qcom-scm.o
+qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
+obj-$(CONFIG_SYSFB) += sysfb.o
+obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
new file mode 100644
index 000000000000..7f4d2435503b
--- /dev/null
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menu "ARM System Control and Management Interface Protocol"
+
+config ARM_SCMI_PROTOCOL
+ tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
+ depends on ARM || ARM64 || COMPILE_TEST
+ help
+ ARM System Control and Management Interface (SCMI) protocol is a
+ set of operating system-independent software interfaces that are
+ used in system management. SCMI is extensible and currently provides
+ interfaces for: Discovery and self-description of the interfaces
+ it supports, Power domain management which is the ability to place
+ a given device or domain into the various power-saving states that
+ it supports, Performance management which is the ability to control
+ the performance of a domain that is composed of compute engines
+ such as application processors and other accelerators, Clock
+ management which is the ability to set and inquire rates on platform
+ managed clocks and Sensor management which is the ability to read
+ sensor data, and be notified of sensor value.
+
+ This protocol library provides interface for all the client drivers
+ making use of the features offered by the SCMI.
+
+if ARM_SCMI_PROTOCOL
+
+config ARM_SCMI_HAVE_TRANSPORT
+ bool
+ help
+ This declares whether at least one SCMI transport has been configured.
+ Used to trigger a build bug when trying to build SCMI without any
+ configured transport.
+
+config ARM_SCMI_HAVE_SHMEM
+ bool
+ help
+ This declares whether a shared memory based transport for SCMI is
+ available.
+
+config ARM_SCMI_HAVE_MSG
+ bool
+ help
+ This declares whether a message passing based transport for SCMI is
+ available.
+
+config ARM_SCMI_TRANSPORT_MAILBOX
+ bool "SCMI transport based on Mailbox"
+ depends on MAILBOX
+ select ARM_SCMI_HAVE_TRANSPORT
+ select ARM_SCMI_HAVE_SHMEM
+ default y
+ help
+ Enable mailbox based transport for SCMI.
+
+ If you want the ARM SCMI PROTOCOL stack to include support for a
+ transport based on mailboxes, answer Y.
+
+config ARM_SCMI_TRANSPORT_SMC
+ bool "SCMI transport based on SMC"
+ depends on HAVE_ARM_SMCCC_DISCOVERY
+ select ARM_SCMI_HAVE_TRANSPORT
+ select ARM_SCMI_HAVE_SHMEM
+ default y
+ help
+ Enable SMC based transport for SCMI.
+
+ If you want the ARM SCMI PROTOCOL stack to include support for a
+ transport based on SMC, answer Y.
+
+config ARM_SCMI_TRANSPORT_VIRTIO
+ bool "SCMI transport based on VirtIO"
+ depends on VIRTIO
+ select ARM_SCMI_HAVE_TRANSPORT
+ select ARM_SCMI_HAVE_MSG
+ help
+ This enables the virtio based transport for SCMI.
+
+ If you want the ARM SCMI PROTOCOL stack to include support for a
+ transport based on VirtIO, answer Y.
+
+endif #ARM_SCMI_PROTOCOL
+
+config ARM_SCMI_POWER_DOMAIN
+ tristate "SCMI power domain driver"
+ depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+ default y
+ select PM_GENERIC_DOMAINS if PM
+ help
+ This enables support for the SCMI power domains which can be
+ enabled or disabled via the SCP firmware
+
+ This driver can also be built as a module. If so, the module
+ will be called scmi_pm_domain. Note this may needed early in boot
+ before rootfs may be available.
+
+endmenu
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 6a2ef63306d6..1dcf123d64ab 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,9 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
scmi-bus-y = bus.o
scmi-driver-y = driver.o notify.o
-scmi-transport-y = shmem.o
-scmi-transport-$(CONFIG_MAILBOX) += mailbox.o
-scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o
+scmi-transport-$(CONFIG_ARM_SCMI_HAVE_SHMEM) = shmem.o
+scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += mailbox.o
+scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += smc.o
+scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o
+scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += virtio.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o
scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \
$(scmi-transport-y)
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 6c7e24935eca..f6fe723ab869 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -111,15 +111,13 @@ static int scmi_dev_probe(struct device *dev)
return scmi_drv->probe(scmi_dev);
}
-static int scmi_dev_remove(struct device *dev)
+static void scmi_dev_remove(struct device *dev)
{
struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
struct scmi_device *scmi_dev = to_scmi_dev(dev);
if (scmi_drv->remove)
scmi_drv->remove(scmi_dev);
-
- return 0;
}
static struct bus_type scmi_bus_type = {
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 8685619d38f9..dea1bfbe1052 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -14,8 +14,12 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <linux/hashtable.h>
+#include <linux/list.h>
#include <linux/module.h>
+#include <linux/refcount.h>
#include <linux/scmi_protocol.h>
+#include <linux/spinlock.h>
#include <linux/types.h>
#include <asm/unaligned.h>
@@ -65,11 +69,22 @@ struct scmi_msg_resp_prot_version {
#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr))
#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1)
+/*
+ * Size of @pending_xfers hashtable included in @scmi_xfers_info; ideally, in
+ * order to minimize space and collisions, this should equal max_msg, i.e. the
+ * maximum number of in-flight messages on a specific platform, but such value
+ * is only available at runtime while kernel hashtables are statically sized:
+ * pick instead as a fixed static size the maximum number of entries that can
+ * fit the whole table into one 4k page.
+ */
+#define SCMI_PENDING_XFERS_HT_ORDER_SZ 9
+
/**
* struct scmi_msg_hdr - Message(Tx/Rx) header
*
* @id: The identifier of the message being sent
* @protocol_id: The identifier of the protocol used to send @id message
+ * @type: The SCMI type for this message
* @seq: The token to identify the message. When a message returns, the
* platform returns the whole message header unmodified including the
* token
@@ -80,6 +95,7 @@ struct scmi_msg_resp_prot_version {
struct scmi_msg_hdr {
u8 id;
u8 protocol_id;
+ u8 type;
u16 seq;
u32 status;
bool poll_completion;
@@ -89,13 +105,14 @@ struct scmi_msg_hdr {
* pack_scmi_header() - packs and returns 32-bit header
*
* @hdr: pointer to header containing all the information on message id,
- * protocol id and sequence id.
+ * protocol id, sequence id and type.
*
* Return: 32-bit packed message header to be sent to the platform.
*/
static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
{
return FIELD_PREP(MSG_ID_MASK, hdr->id) |
+ FIELD_PREP(MSG_TYPE_MASK, hdr->type) |
FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) |
FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id);
}
@@ -110,6 +127,7 @@ static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr)
{
hdr->id = MSG_XTRACT_ID(msg_hdr);
hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr);
+ hdr->type = MSG_XTRACT_TYPE(msg_hdr);
}
/**
@@ -134,6 +152,27 @@ struct scmi_msg {
* buffer for the rx path as we use for the tx path.
* @done: command message transmit completion event
* @async_done: pointer to delayed response message received event completion
+ * @pending: True for xfers added to @pending_xfers hashtable
+ * @node: An hlist_node reference used to store this xfer, alternatively, on
+ * the free list @free_xfers or in the @pending_xfers hashtable
+ * @users: A refcount to track the active users for this xfer.
+ * This is meant to protect against the possibility that, when a command
+ * transaction times out concurrently with the reception of a valid
+ * response message, the xfer could be finally put on the TX path, and
+ * so vanish, while on the RX path scmi_rx_callback() is still
+ * processing it: in such a case this refcounting will ensure that, even
+ * though the timed-out transaction will anyway cause the command
+ * request to be reported as failed by time-out, the underlying xfer
+ * cannot be discarded and possibly reused until the last one user on
+ * the RX path has released it.
+ * @busy: An atomic flag to ensure exclusive write access to this xfer
+ * @state: The current state of this transfer, with states transitions deemed
+ * valid being:
+ * - SCMI_XFER_SENT_OK -> SCMI_XFER_RESP_OK [ -> SCMI_XFER_DRESP_OK ]
+ * - SCMI_XFER_SENT_OK -> SCMI_XFER_DRESP_OK
+ * (Missing synchronous response is assumed OK and ignored)
+ * @lock: A spinlock to protect state and busy fields.
+ * @priv: A pointer for transport private usage.
*/
struct scmi_xfer {
int transfer_id;
@@ -142,8 +181,36 @@ struct scmi_xfer {
struct scmi_msg rx;
struct completion done;
struct completion *async_done;
+ bool pending;
+ struct hlist_node node;
+ refcount_t users;
+#define SCMI_XFER_FREE 0
+#define SCMI_XFER_BUSY 1
+ atomic_t busy;
+#define SCMI_XFER_SENT_OK 0
+#define SCMI_XFER_RESP_OK 1
+#define SCMI_XFER_DRESP_OK 2
+ int state;
+ /* A lock to protect state and busy fields */
+ spinlock_t lock;
+ void *priv;
};
+/*
+ * An helper macro to lookup an xfer from the @pending_xfers hashtable
+ * using the message sequence number token as a key.
+ */
+#define XFER_FIND(__ht, __k) \
+({ \
+ typeof(__k) k_ = __k; \
+ struct scmi_xfer *xfer_ = NULL; \
+ \
+ hash_for_each_possible((__ht), xfer_, node, k_) \
+ if (xfer_->hdr.seq == k_) \
+ break; \
+ xfer_; \
+})
+
struct scmi_xfer_ops;
/**
@@ -283,9 +350,13 @@ struct scmi_chan_info {
/**
* struct scmi_transport_ops - Structure representing a SCMI transport ops
*
+ * @link_supplier: Optional callback to add link to a supplier device
* @chan_available: Callback to check if channel is available or not
* @chan_setup: Callback to allocate and setup a channel
* @chan_free: Callback to free a channel
+ * @get_max_msg: Optional callback to provide max_msg dynamically
+ * Returns the maximum number of messages for the channel type
+ * (tx or rx) that can be pending simultaneously in the system
* @send_message: Callback to send a message
* @mark_txdone: Callback to mark tx as done
* @fetch_response: Callback to fetch response
@@ -294,10 +365,12 @@ struct scmi_chan_info {
* @poll_done: Callback to poll transfer status
*/
struct scmi_transport_ops {
+ int (*link_supplier)(struct device *dev);
bool (*chan_available)(struct device *dev, int idx);
int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev,
bool tx);
int (*chan_free)(int id, void *p, void *data);
+ unsigned int (*get_max_msg)(struct scmi_chan_info *base_cinfo);
int (*send_message)(struct scmi_chan_info *cinfo,
struct scmi_xfer *xfer);
void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret);
@@ -317,25 +390,39 @@ struct scmi_device *scmi_child_dev_find(struct device *parent,
/**
* struct scmi_desc - Description of SoC integration
*
+ * @transport_init: An optional function that a transport can provide to
+ * initialize some transport-specific setup during SCMI core
+ * initialization, so ahead of SCMI core probing.
+ * @transport_exit: An optional function that a transport can provide to
+ * de-initialize some transport-specific setup during SCMI core
+ * de-initialization, so after SCMI core removal.
* @ops: Pointer to the transport specific ops structure
* @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
- * @max_msg: Maximum number of messages that can be pending
- * simultaneously in the system
+ * @max_msg: Maximum number of messages for a channel type (tx or rx) that can
+ * be pending simultaneously in the system. May be overridden by the
+ * get_max_msg op.
* @max_msg_size: Maximum size of data per message that can be handled.
*/
struct scmi_desc {
+ int (*transport_init)(void);
+ void (*transport_exit)(void);
const struct scmi_transport_ops *ops;
int max_rx_timeout_ms;
int max_msg;
int max_msg_size;
};
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_MAILBOX
extern const struct scmi_desc scmi_mailbox_desc;
-#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY
+#endif
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
extern const struct scmi_desc scmi_smc_desc;
#endif
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
+extern const struct scmi_desc scmi_virtio_desc;
+#endif
-void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr);
+void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, void *priv);
void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id);
/* shmem related declarations */
@@ -352,8 +439,22 @@ void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem);
bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer);
+/* declarations for message passing transports */
+struct scmi_msg_payld;
+
+/* Maximum overhead of message w.r.t. struct scmi_desc.max_msg_size */
+#define SCMI_MSG_MAX_PROT_OVERHEAD (2 * sizeof(__le32))
+
+size_t msg_response_size(struct scmi_xfer *xfer);
+size_t msg_command_size(struct scmi_xfer *xfer);
+void msg_tx_prepare(struct scmi_msg_payld *msg, struct scmi_xfer *xfer);
+u32 msg_read_header(struct scmi_msg_payld *msg);
+void msg_fetch_response(struct scmi_msg_payld *msg, size_t len,
+ struct scmi_xfer *xfer);
+void msg_fetch_notification(struct scmi_msg_payld *msg, size_t len,
+ size_t max_len, struct scmi_xfer *xfer);
+
void scmi_notification_instance_data_set(const struct scmi_handle *handle,
void *priv);
void *scmi_notification_instance_data_get(const struct scmi_handle *handle);
-
#endif /* _SCMI_COMMON_H */
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 9b2e8d42a992..b406b3f78f46 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/ktime.h>
+#include <linux/hashtable.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of_address.h>
@@ -67,16 +68,23 @@ struct scmi_requested_dev {
/**
* struct scmi_xfers_info - Structure to manage transfer information
*
- * @xfer_block: Preallocated Message array
* @xfer_alloc_table: Bitmap table for allocated messages.
* Index of this bitmap table is also used for message
* sequence identifier.
* @xfer_lock: Protection for message allocation
+ * @max_msg: Maximum number of messages that can be pending
+ * @free_xfers: A free list for available to use xfers. It is initialized with
+ * a number of xfers equal to the maximum allowed in-flight
+ * messages.
+ * @pending_xfers: An hashtable, indexed by msg_hdr.seq, used to keep all the
+ * currently in-flight messages.
*/
struct scmi_xfers_info {
- struct scmi_xfer *xfer_block;
unsigned long *xfer_alloc_table;
spinlock_t xfer_lock;
+ int max_msg;
+ struct hlist_head free_xfers;
+ DECLARE_HASHTABLE(pending_xfers, SCMI_PENDING_XFERS_HT_ORDER_SZ);
};
/**
@@ -172,19 +180,6 @@ static inline int scmi_to_linux_errno(int errno)
return -EIO;
}
-/**
- * scmi_dump_header_dbg() - Helper to dump a message header.
- *
- * @dev: Device pointer corresponding to the SCMI entity
- * @hdr: pointer to header.
- */
-static inline void scmi_dump_header_dbg(struct device *dev,
- struct scmi_msg_hdr *hdr)
-{
- dev_dbg(dev, "Message ID: %x Sequence ID: %x Protocol: %x\n",
- hdr->id, hdr->seq, hdr->protocol_id);
-}
-
void scmi_notification_instance_data_set(const struct scmi_handle *handle,
void *priv)
{
@@ -205,45 +200,189 @@ void *scmi_notification_instance_data_get(const struct scmi_handle *handle)
}
/**
+ * scmi_xfer_token_set - Reserve and set new token for the xfer at hand
+ *
+ * @minfo: Pointer to Tx/Rx Message management info based on channel type
+ * @xfer: The xfer to act upon
+ *
+ * Pick the next unused monotonically increasing token and set it into
+ * xfer->hdr.seq: picking a monotonically increasing value avoids immediate
+ * reuse of freshly completed or timed-out xfers, thus mitigating the risk
+ * of incorrect association of a late and expired xfer with a live in-flight
+ * transaction, both happening to re-use the same token identifier.
+ *
+ * Since platform is NOT required to answer our request in-order we should
+ * account for a few rare but possible scenarios:
+ *
+ * - exactly 'next_token' may be NOT available so pick xfer_id >= next_token
+ * using find_next_zero_bit() starting from candidate next_token bit
+ *
+ * - all tokens ahead upto (MSG_TOKEN_ID_MASK - 1) are used in-flight but we
+ * are plenty of free tokens at start, so try a second pass using
+ * find_next_zero_bit() and starting from 0.
+ *
+ * X = used in-flight
+ *
+ * Normal
+ * ------
+ *
+ * |- xfer_id picked
+ * -----------+----------------------------------------------------------
+ * | | |X|X|X| | | | | | ... ... ... ... ... ... ... ... ... ... ...|X|X|
+ * ----------------------------------------------------------------------
+ * ^
+ * |- next_token
+ *
+ * Out-of-order pending at start
+ * -----------------------------
+ *
+ * |- xfer_id picked, last_token fixed
+ * -----+----------------------------------------------------------------
+ * |X|X| | | | |X|X| ... ... ... ... ... ... ... ... ... ... ... ...|X| |
+ * ----------------------------------------------------------------------
+ * ^
+ * |- next_token
+ *
+ *
+ * Out-of-order pending at end
+ * ---------------------------
+ *
+ * |- xfer_id picked, last_token fixed
+ * -----+----------------------------------------------------------------
+ * |X|X| | | | |X|X| ... ... ... ... ... ... ... ... ... ... |X|X|X||X|X|
+ * ----------------------------------------------------------------------
+ * ^
+ * |- next_token
+ *
+ * Context: Assumes to be called with @xfer_lock already acquired.
+ *
+ * Return: 0 on Success or error
+ */
+static int scmi_xfer_token_set(struct scmi_xfers_info *minfo,
+ struct scmi_xfer *xfer)
+{
+ unsigned long xfer_id, next_token;
+
+ /*
+ * Pick a candidate monotonic token in range [0, MSG_TOKEN_MAX - 1]
+ * using the pre-allocated transfer_id as a base.
+ * Note that the global transfer_id is shared across all message types
+ * so there could be holes in the allocated set of monotonic sequence
+ * numbers, but that is going to limit the effectiveness of the
+ * mitigation only in very rare limit conditions.
+ */
+ next_token = (xfer->transfer_id & (MSG_TOKEN_MAX - 1));
+
+ /* Pick the next available xfer_id >= next_token */
+ xfer_id = find_next_zero_bit(minfo->xfer_alloc_table,
+ MSG_TOKEN_MAX, next_token);
+ if (xfer_id == MSG_TOKEN_MAX) {
+ /*
+ * After heavily out-of-order responses, there are no free
+ * tokens ahead, but only at start of xfer_alloc_table so
+ * try again from the beginning.
+ */
+ xfer_id = find_next_zero_bit(minfo->xfer_alloc_table,
+ MSG_TOKEN_MAX, 0);
+ /*
+ * Something is wrong if we got here since there can be a
+ * maximum number of (MSG_TOKEN_MAX - 1) in-flight messages
+ * but we have not found any free token [0, MSG_TOKEN_MAX - 1].
+ */
+ if (WARN_ON_ONCE(xfer_id == MSG_TOKEN_MAX))
+ return -ENOMEM;
+ }
+
+ /* Update +/- last_token accordingly if we skipped some hole */
+ if (xfer_id != next_token)
+ atomic_add((int)(xfer_id - next_token), &transfer_last_id);
+
+ /* Set in-flight */
+ set_bit(xfer_id, minfo->xfer_alloc_table);
+ xfer->hdr.seq = (u16)xfer_id;
+
+ return 0;
+}
+
+/**
+ * scmi_xfer_token_clear - Release the token
+ *
+ * @minfo: Pointer to Tx/Rx Message management info based on channel type
+ * @xfer: The xfer to act upon
+ */
+static inline void scmi_xfer_token_clear(struct scmi_xfers_info *minfo,
+ struct scmi_xfer *xfer)
+{
+ clear_bit(xfer->hdr.seq, minfo->xfer_alloc_table);
+}
+
+/**
* scmi_xfer_get() - Allocate one message
*
* @handle: Pointer to SCMI entity handle
* @minfo: Pointer to Tx/Rx Message management info based on channel type
+ * @set_pending: If true a monotonic token is picked and the xfer is added to
+ * the pending hash table.
*
* Helper function which is used by various message functions that are
* exposed to clients of this driver for allocating a message traffic event.
*
- * This function can sleep depending on pending requests already in the system
- * for the SCMI entity. Further, this also holds a spinlock to maintain
- * integrity of internal data structures.
+ * Picks an xfer from the free list @free_xfers (if any available) and, if
+ * required, sets a monotonically increasing token and stores the inflight xfer
+ * into the @pending_xfers hashtable for later retrieval.
+ *
+ * The successfully initialized xfer is refcounted.
+ *
+ * Context: Holds @xfer_lock while manipulating @xfer_alloc_table and
+ * @free_xfers.
*
* Return: 0 if all went fine, else corresponding error.
*/
static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle,
- struct scmi_xfers_info *minfo)
+ struct scmi_xfers_info *minfo,
+ bool set_pending)
{
- u16 xfer_id;
+ int ret;
+ unsigned long flags;
struct scmi_xfer *xfer;
- unsigned long flags, bit_pos;
- struct scmi_info *info = handle_to_scmi_info(handle);
- /* Keep the locked section as small as possible */
spin_lock_irqsave(&minfo->xfer_lock, flags);
- bit_pos = find_first_zero_bit(minfo->xfer_alloc_table,
- info->desc->max_msg);
- if (bit_pos == info->desc->max_msg) {
+ if (hlist_empty(&minfo->free_xfers)) {
spin_unlock_irqrestore(&minfo->xfer_lock, flags);
return ERR_PTR(-ENOMEM);
}
- set_bit(bit_pos, minfo->xfer_alloc_table);
- spin_unlock_irqrestore(&minfo->xfer_lock, flags);
- xfer_id = bit_pos;
+ /* grab an xfer from the free_list */
+ xfer = hlist_entry(minfo->free_xfers.first, struct scmi_xfer, node);
+ hlist_del_init(&xfer->node);
- xfer = &minfo->xfer_block[xfer_id];
- xfer->hdr.seq = xfer_id;
+ /*
+ * Allocate transfer_id early so that can be used also as base for
+ * monotonic sequence number generation if needed.
+ */
xfer->transfer_id = atomic_inc_return(&transfer_last_id);
+ if (set_pending) {
+ /* Pick and set monotonic token */
+ ret = scmi_xfer_token_set(minfo, xfer);
+ if (!ret) {
+ hash_add(minfo->pending_xfers, &xfer->node,
+ xfer->hdr.seq);
+ xfer->pending = true;
+ } else {
+ dev_err(handle->dev,
+ "Failed to get monotonic token %d\n", ret);
+ hlist_add_head(&xfer->node, &minfo->free_xfers);
+ xfer = ERR_PTR(ret);
+ }
+ }
+
+ if (!IS_ERR(xfer)) {
+ refcount_set(&xfer->users, 1);
+ atomic_set(&xfer->busy, SCMI_XFER_FREE);
+ }
+ spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
return xfer;
}
@@ -253,6 +392,9 @@ static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle,
* @minfo: Pointer to Tx/Rx Message management info based on channel type
* @xfer: message that was reserved by scmi_xfer_get
*
+ * After refcount check, possibly release an xfer, clearing the token slot,
+ * removing xfer from @pending_xfers and putting it back into free_xfers.
+ *
* This holds a spinlock to maintain integrity of internal data structures.
*/
static void
@@ -260,17 +402,215 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer)
{
unsigned long flags;
+ spin_lock_irqsave(&minfo->xfer_lock, flags);
+ if (refcount_dec_and_test(&xfer->users)) {
+ if (xfer->pending) {
+ scmi_xfer_token_clear(minfo, xfer);
+ hash_del(&xfer->node);
+ xfer->pending = false;
+ }
+ hlist_add_head(&xfer->node, &minfo->free_xfers);
+ }
+ spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+}
+
+/**
+ * scmi_xfer_lookup_unlocked - Helper to lookup an xfer_id
+ *
+ * @minfo: Pointer to Tx/Rx Message management info based on channel type
+ * @xfer_id: Token ID to lookup in @pending_xfers
+ *
+ * Refcounting is untouched.
+ *
+ * Context: Assumes to be called with @xfer_lock already acquired.
+ *
+ * Return: A valid xfer on Success or error otherwise
+ */
+static struct scmi_xfer *
+scmi_xfer_lookup_unlocked(struct scmi_xfers_info *minfo, u16 xfer_id)
+{
+ struct scmi_xfer *xfer = NULL;
+
+ if (test_bit(xfer_id, minfo->xfer_alloc_table))
+ xfer = XFER_FIND(minfo->pending_xfers, xfer_id);
+
+ return xfer ?: ERR_PTR(-EINVAL);
+}
+
+/**
+ * scmi_msg_response_validate - Validate message type against state of related
+ * xfer
+ *
+ * @cinfo: A reference to the channel descriptor.
+ * @msg_type: Message type to check
+ * @xfer: A reference to the xfer to validate against @msg_type
+ *
+ * This function checks if @msg_type is congruent with the current state of
+ * a pending @xfer; if an asynchronous delayed response is received before the
+ * related synchronous response (Out-of-Order Delayed Response) the missing
+ * synchronous response is assumed to be OK and completed, carrying on with the
+ * Delayed Response: this is done to address the case in which the underlying
+ * SCMI transport can deliver such out-of-order responses.
+ *
+ * Context: Assumes to be called with xfer->lock already acquired.
+ *
+ * Return: 0 on Success, error otherwise
+ */
+static inline int scmi_msg_response_validate(struct scmi_chan_info *cinfo,
+ u8 msg_type,
+ struct scmi_xfer *xfer)
+{
/*
- * Keep the locked section as small as possible
- * NOTE: we might escape with smp_mb and no lock here..
- * but just be conservative and symmetric.
+ * Even if a response was indeed expected on this slot at this point,
+ * a buggy platform could wrongly reply feeding us an unexpected
+ * delayed response we're not prepared to handle: bail-out safely
+ * blaming firmware.
*/
+ if (msg_type == MSG_TYPE_DELAYED_RESP && !xfer->async_done) {
+ dev_err(cinfo->dev,
+ "Delayed Response for %d not expected! Buggy F/W ?\n",
+ xfer->hdr.seq);
+ return -EINVAL;
+ }
+
+ switch (xfer->state) {
+ case SCMI_XFER_SENT_OK:
+ if (msg_type == MSG_TYPE_DELAYED_RESP) {
+ /*
+ * Delayed Response expected but delivered earlier.
+ * Assume message RESPONSE was OK and skip state.
+ */
+ xfer->hdr.status = SCMI_SUCCESS;
+ xfer->state = SCMI_XFER_RESP_OK;
+ complete(&xfer->done);
+ dev_warn(cinfo->dev,
+ "Received valid OoO Delayed Response for %d\n",
+ xfer->hdr.seq);
+ }
+ break;
+ case SCMI_XFER_RESP_OK:
+ if (msg_type != MSG_TYPE_DELAYED_RESP)
+ return -EINVAL;
+ break;
+ case SCMI_XFER_DRESP_OK:
+ /* No further message expected once in SCMI_XFER_DRESP_OK */
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * scmi_xfer_state_update - Update xfer state
+ *
+ * @xfer: A reference to the xfer to update
+ * @msg_type: Type of message being processed.
+ *
+ * Note that this message is assumed to have been already successfully validated
+ * by @scmi_msg_response_validate(), so here we just update the state.
+ *
+ * Context: Assumes to be called on an xfer exclusively acquired using the
+ * busy flag.
+ */
+static inline void scmi_xfer_state_update(struct scmi_xfer *xfer, u8 msg_type)
+{
+ xfer->hdr.type = msg_type;
+
+ /* Unknown command types were already discarded earlier */
+ if (xfer->hdr.type == MSG_TYPE_COMMAND)
+ xfer->state = SCMI_XFER_RESP_OK;
+ else
+ xfer->state = SCMI_XFER_DRESP_OK;
+}
+
+static bool scmi_xfer_acquired(struct scmi_xfer *xfer)
+{
+ int ret;
+
+ ret = atomic_cmpxchg(&xfer->busy, SCMI_XFER_FREE, SCMI_XFER_BUSY);
+
+ return ret == SCMI_XFER_FREE;
+}
+
+/**
+ * scmi_xfer_command_acquire - Helper to lookup and acquire a command xfer
+ *
+ * @cinfo: A reference to the channel descriptor.
+ * @msg_hdr: A message header to use as lookup key
+ *
+ * When a valid xfer is found for the sequence number embedded in the provided
+ * msg_hdr, reference counting is properly updated and exclusive access to this
+ * xfer is granted till released with @scmi_xfer_command_release.
+ *
+ * Return: A valid @xfer on Success or error otherwise.
+ */
+static inline struct scmi_xfer *
+scmi_xfer_command_acquire(struct scmi_chan_info *cinfo, u32 msg_hdr)
+{
+ int ret;
+ unsigned long flags;
+ struct scmi_xfer *xfer;
+ struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
+ struct scmi_xfers_info *minfo = &info->tx_minfo;
+ u8 msg_type = MSG_XTRACT_TYPE(msg_hdr);
+ u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
+
+ /* Are we even expecting this? */
spin_lock_irqsave(&minfo->xfer_lock, flags);
- clear_bit(xfer->hdr.seq, minfo->xfer_alloc_table);
+ xfer = scmi_xfer_lookup_unlocked(minfo, xfer_id);
+ if (IS_ERR(xfer)) {
+ dev_err(cinfo->dev,
+ "Message for %d type %d is not expected!\n",
+ xfer_id, msg_type);
+ spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+ return xfer;
+ }
+ refcount_inc(&xfer->users);
spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+ spin_lock_irqsave(&xfer->lock, flags);
+ ret = scmi_msg_response_validate(cinfo, msg_type, xfer);
+ /*
+ * If a pending xfer was found which was also in a congruent state with
+ * the received message, acquire exclusive access to it setting the busy
+ * flag.
+ * Spins only on the rare limit condition of concurrent reception of
+ * RESP and DRESP for the same xfer.
+ */
+ if (!ret) {
+ spin_until_cond(scmi_xfer_acquired(xfer));
+ scmi_xfer_state_update(xfer, msg_type);
+ }
+ spin_unlock_irqrestore(&xfer->lock, flags);
+
+ if (ret) {
+ dev_err(cinfo->dev,
+ "Invalid message type:%d for %d - HDR:0x%X state:%d\n",
+ msg_type, xfer_id, msg_hdr, xfer->state);
+ /* On error the refcount incremented above has to be dropped */
+ __scmi_xfer_put(minfo, xfer);
+ xfer = ERR_PTR(-EINVAL);
+ }
+
+ return xfer;
+}
+
+static inline void scmi_xfer_command_release(struct scmi_info *info,
+ struct scmi_xfer *xfer)
+{
+ atomic_set(&xfer->busy, SCMI_XFER_FREE);
+ __scmi_xfer_put(&info->tx_minfo, xfer);
+}
+
+static inline void scmi_clear_channel(struct scmi_info *info,
+ struct scmi_chan_info *cinfo)
+{
+ if (info->desc->ops->clear_channel)
+ info->desc->ops->clear_channel(cinfo);
}
-static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr)
+static void scmi_handle_notification(struct scmi_chan_info *cinfo,
+ u32 msg_hdr, void *priv)
{
struct scmi_xfer *xfer;
struct device *dev = cinfo->dev;
@@ -279,16 +619,17 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr)
ktime_t ts;
ts = ktime_get_boottime();
- xfer = scmi_xfer_get(cinfo->handle, minfo);
+ xfer = scmi_xfer_get(cinfo->handle, minfo, false);
if (IS_ERR(xfer)) {
dev_err(dev, "failed to get free message slot (%ld)\n",
PTR_ERR(xfer));
- info->desc->ops->clear_channel(cinfo);
+ scmi_clear_channel(info, cinfo);
return;
}
unpack_scmi_header(msg_hdr, &xfer->hdr);
- scmi_dump_header_dbg(dev, &xfer->hdr);
+ if (priv)
+ xfer->priv = priv;
info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size,
xfer);
scmi_notify(cinfo->handle, xfer->hdr.protocol_id,
@@ -300,59 +641,41 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr)
__scmi_xfer_put(minfo, xfer);
- info->desc->ops->clear_channel(cinfo);
+ scmi_clear_channel(info, cinfo);
}
static void scmi_handle_response(struct scmi_chan_info *cinfo,
- u16 xfer_id, u8 msg_type)
+ u32 msg_hdr, void *priv)
{
struct scmi_xfer *xfer;
- struct device *dev = cinfo->dev;
struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
- struct scmi_xfers_info *minfo = &info->tx_minfo;
- /* 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);
- info->desc->ops->clear_channel(cinfo);
- return;
- }
-
- xfer = &minfo->xfer_block[xfer_id];
- /*
- * Even if a response was indeed expected on this slot at this point,
- * a buggy platform could wrongly reply feeding us an unexpected
- * delayed response we're not prepared to handle: bail-out safely
- * blaming firmware.
- */
- if (unlikely(msg_type == MSG_TYPE_DELAYED_RESP && !xfer->async_done)) {
- dev_err(dev,
- "Delayed Response for %d not expected! Buggy F/W ?\n",
- xfer_id);
- info->desc->ops->clear_channel(cinfo);
- /* It was unexpected, so nobody will clear the xfer if not us */
- __scmi_xfer_put(minfo, xfer);
+ xfer = scmi_xfer_command_acquire(cinfo, msg_hdr);
+ if (IS_ERR(xfer)) {
+ scmi_clear_channel(info, cinfo);
return;
}
/* rx.len could be shrunk in the sync do_xfer, so reset to maxsz */
- if (msg_type == MSG_TYPE_DELAYED_RESP)
+ if (xfer->hdr.type == MSG_TYPE_DELAYED_RESP)
xfer->rx.len = info->desc->max_msg_size;
- scmi_dump_header_dbg(dev, &xfer->hdr);
-
+ if (priv)
+ xfer->priv = priv;
info->desc->ops->fetch_response(cinfo, xfer);
trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id,
xfer->hdr.protocol_id, xfer->hdr.seq,
- msg_type);
+ xfer->hdr.type);
- if (msg_type == MSG_TYPE_DELAYED_RESP) {
- info->desc->ops->clear_channel(cinfo);
+ if (xfer->hdr.type == MSG_TYPE_DELAYED_RESP) {
+ scmi_clear_channel(info, cinfo);
complete(xfer->async_done);
} else {
complete(&xfer->done);
}
+
+ scmi_xfer_command_release(info, xfer);
}
/**
@@ -360,6 +683,7 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo,
*
* @cinfo: SCMI channel info
* @msg_hdr: Message header
+ * @priv: Transport specific private data.
*
* Processes one received message to appropriate transfer information and
* signals completion of the transfer.
@@ -367,18 +691,17 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo,
* NOTE: This function will be invoked in IRQ context, hence should be
* as optimal as possible.
*/
-void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
+void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, void *priv)
{
- u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
u8 msg_type = MSG_XTRACT_TYPE(msg_hdr);
switch (msg_type) {
case MSG_TYPE_NOTIFICATION:
- scmi_handle_notification(cinfo, msg_hdr);
+ scmi_handle_notification(cinfo, msg_hdr, priv);
break;
case MSG_TYPE_COMMAND:
case MSG_TYPE_DELAYED_RESP:
- scmi_handle_response(cinfo, xfer_id, msg_type);
+ scmi_handle_response(cinfo, msg_hdr, priv);
break;
default:
WARN_ONCE(1, "received unknown msg_type:%d\n", msg_type);
@@ -390,7 +713,7 @@ void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
* xfer_put() - Release a transmit message
*
* @ph: Pointer to SCMI protocol handle
- * @xfer: message that was reserved by scmi_xfer_get
+ * @xfer: message that was reserved by xfer_get_init
*/
static void xfer_put(const struct scmi_protocol_handle *ph,
struct scmi_xfer *xfer)
@@ -408,7 +731,12 @@ static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
{
struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
+ /*
+ * Poll also on xfer->done so that polling can be forcibly terminated
+ * in case of out-of-order receptions of delayed responses
+ */
return info->desc->ops->poll_done(cinfo, xfer) ||
+ try_wait_for_completion(&xfer->done) ||
ktime_after(ktime_get(), stop);
}
@@ -432,6 +760,12 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
struct device *dev = info->dev;
struct scmi_chan_info *cinfo;
+ if (xfer->hdr.poll_completion && !info->desc->ops->poll_done) {
+ dev_warn_once(dev,
+ "Polling mode is not supported by transport.\n");
+ return -EINVAL;
+ }
+
/*
* Initialise protocol id now from protocol handle to avoid it being
* overridden by mistake (or malice) by the protocol code mangling with
@@ -448,6 +782,16 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
xfer->hdr.protocol_id, xfer->hdr.seq,
xfer->hdr.poll_completion);
+ xfer->state = SCMI_XFER_SENT_OK;
+ /*
+ * Even though spinlocking is not needed here since no race is possible
+ * on xfer->state due to the monotonically increasing tokens allocation,
+ * we must anyway ensure xfer->state initialization is not re-ordered
+ * after the .send_message() to be sure that on the RX path an early
+ * ISR calling scmi_rx_callback() cannot see an old stale xfer->state.
+ */
+ smp_mb();
+
ret = info->desc->ops->send_message(cinfo, xfer);
if (ret < 0) {
dev_dbg(dev, "Failed to send message %d\n", ret);
@@ -458,11 +802,22 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
ktime_t stop = ktime_add_ns(ktime_get(), SCMI_MAX_POLL_TO_NS);
spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop));
-
- if (ktime_before(ktime_get(), stop))
- info->desc->ops->fetch_response(cinfo, xfer);
- else
+ if (ktime_before(ktime_get(), stop)) {
+ unsigned long flags;
+
+ /*
+ * Do not fetch_response if an out-of-order delayed
+ * response is being processed.
+ */
+ spin_lock_irqsave(&xfer->lock, flags);
+ if (xfer->state == SCMI_XFER_SENT_OK) {
+ info->desc->ops->fetch_response(cinfo, xfer);
+ xfer->state = SCMI_XFER_RESP_OK;
+ }
+ spin_unlock_irqrestore(&xfer->lock, flags);
+ } else {
ret = -ETIMEDOUT;
+ }
} else {
/* And we wait for the response. */
timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
@@ -557,7 +912,7 @@ static int xfer_get_init(const struct scmi_protocol_handle *ph,
tx_size > info->desc->max_msg_size)
return -ERANGE;
- xfer = scmi_xfer_get(pi->handle, minfo);
+ xfer = scmi_xfer_get(pi->handle, minfo, true);
if (IS_ERR(xfer)) {
ret = PTR_ERR(xfer);
dev_err(dev, "failed to get free message slot(%d)\n", ret);
@@ -566,6 +921,7 @@ static int xfer_get_init(const struct scmi_protocol_handle *ph,
xfer->tx.len = tx_size;
xfer->rx.len = rx_size ? : info->desc->max_msg_size;
+ xfer->hdr.type = MSG_TYPE_COMMAND;
xfer->hdr.id = msg_id;
xfer->hdr.poll_completion = false;
@@ -1026,25 +1382,32 @@ static int __scmi_xfer_info_init(struct scmi_info *sinfo,
const struct scmi_desc *desc = sinfo->desc;
/* Pre-allocated messages, no more than what hdr.seq can support */
- if (WARN_ON(!desc->max_msg || desc->max_msg > MSG_TOKEN_MAX)) {
+ if (WARN_ON(!info->max_msg || info->max_msg > MSG_TOKEN_MAX)) {
dev_err(dev,
"Invalid maximum messages %d, not in range [1 - %lu]\n",
- desc->max_msg, MSG_TOKEN_MAX);
+ info->max_msg, MSG_TOKEN_MAX);
return -EINVAL;
}
- info->xfer_block = devm_kcalloc(dev, desc->max_msg,
- sizeof(*info->xfer_block), GFP_KERNEL);
- if (!info->xfer_block)
- return -ENOMEM;
+ hash_init(info->pending_xfers);
- info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(desc->max_msg),
+ /* Allocate a bitmask sized to hold MSG_TOKEN_MAX tokens */
+ info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(MSG_TOKEN_MAX),
sizeof(long), GFP_KERNEL);
if (!info->xfer_alloc_table)
return -ENOMEM;
- /* Pre-initialize the buffer pointer to pre-allocated buffers */
- for (i = 0, xfer = info->xfer_block; i < desc->max_msg; i++, xfer++) {
+ /*
+ * Preallocate a number of xfers equal to max inflight messages,
+ * pre-initialize the buffer pointer to pre-allocated buffers and
+ * attach all of them to the free list
+ */
+ INIT_HLIST_HEAD(&info->free_xfers);
+ for (i = 0; i < info->max_msg; i++) {
+ xfer = devm_kzalloc(dev, sizeof(*xfer), GFP_KERNEL);
+ if (!xfer)
+ return -ENOMEM;
+
xfer->rx.buf = devm_kcalloc(dev, sizeof(u8), desc->max_msg_size,
GFP_KERNEL);
if (!xfer->rx.buf)
@@ -1052,6 +1415,10 @@ static int __scmi_xfer_info_init(struct scmi_info *sinfo,
xfer->tx.buf = xfer->rx.buf;
init_completion(&xfer->done);
+ spin_lock_init(&xfer->lock);
+
+ /* Add initialized xfer to the free list */
+ hlist_add_head(&xfer->node, &info->free_xfers);
}
spin_lock_init(&info->xfer_lock);
@@ -1059,10 +1426,40 @@ static int __scmi_xfer_info_init(struct scmi_info *sinfo,
return 0;
}
+static int scmi_channels_max_msg_configure(struct scmi_info *sinfo)
+{
+ const struct scmi_desc *desc = sinfo->desc;
+
+ if (!desc->ops->get_max_msg) {
+ sinfo->tx_minfo.max_msg = desc->max_msg;
+ sinfo->rx_minfo.max_msg = desc->max_msg;
+ } else {
+ struct scmi_chan_info *base_cinfo;
+
+ base_cinfo = idr_find(&sinfo->tx_idr, SCMI_PROTOCOL_BASE);
+ if (!base_cinfo)
+ return -EINVAL;
+ sinfo->tx_minfo.max_msg = desc->ops->get_max_msg(base_cinfo);
+
+ /* RX channel is optional so can be skipped */
+ base_cinfo = idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE);
+ if (base_cinfo)
+ sinfo->rx_minfo.max_msg =
+ desc->ops->get_max_msg(base_cinfo);
+ }
+
+ return 0;
+}
+
static int scmi_xfer_info_init(struct scmi_info *sinfo)
{
- int ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo);
+ int ret;
+
+ ret = scmi_channels_max_msg_configure(sinfo);
+ if (ret)
+ return ret;
+ ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo);
if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE))
ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo);
@@ -1390,6 +1787,21 @@ void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
mutex_unlock(&scmi_requested_devices_mtx);
}
+static int scmi_cleanup_txrx_channels(struct scmi_info *info)
+{
+ int ret;
+ struct idr *idr = &info->tx_idr;
+
+ ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
+ idr_destroy(&info->tx_idr);
+
+ idr = &info->rx_idr;
+ ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
+ idr_destroy(&info->rx_idr);
+
+ return ret;
+}
+
static int scmi_probe(struct platform_device *pdev)
{
int ret;
@@ -1424,13 +1836,19 @@ static int scmi_probe(struct platform_device *pdev)
handle->devm_protocol_get = scmi_devm_protocol_get;
handle->devm_protocol_put = scmi_devm_protocol_put;
+ if (desc->ops->link_supplier) {
+ ret = desc->ops->link_supplier(dev);
+ if (ret)
+ return ret;
+ }
+
ret = scmi_txrx_setup(info, dev, SCMI_PROTOCOL_BASE);
if (ret)
return ret;
ret = scmi_xfer_info_init(info);
if (ret)
- return ret;
+ goto clear_txrx_setup;
if (scmi_notification_init(handle))
dev_err(dev, "SCMI Notifications NOT available.\n");
@@ -1443,7 +1861,7 @@ static int scmi_probe(struct platform_device *pdev)
ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE);
if (ret) {
dev_err(dev, "unable to communicate with SCMI\n");
- return ret;
+ goto notification_exit;
}
mutex_lock(&scmi_list_mutex);
@@ -1482,6 +1900,12 @@ static int scmi_probe(struct platform_device *pdev)
}
return 0;
+
+notification_exit:
+ scmi_notification_exit(&info->handle);
+clear_txrx_setup:
+ scmi_cleanup_txrx_channels(info);
+ return ret;
}
void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id)
@@ -1493,7 +1917,6 @@ static int scmi_remove(struct platform_device *pdev)
{
int ret = 0, id;
struct scmi_info *info = platform_get_drvdata(pdev);
- struct idr *idr = &info->tx_idr;
struct device_node *child;
mutex_lock(&scmi_list_mutex);
@@ -1517,14 +1940,7 @@ static int scmi_remove(struct platform_device *pdev)
idr_destroy(&info->active_protocols);
/* Safe to free channels since no more users */
- ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
- idr_destroy(&info->tx_idr);
-
- idr = &info->rx_idr;
- ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
- idr_destroy(&info->rx_idr);
-
- return ret;
+ return scmi_cleanup_txrx_channels(info);
}
static ssize_t protocol_version_show(struct device *dev,
@@ -1575,12 +1991,15 @@ ATTRIBUTE_GROUPS(versions);
/* Each compatible listed below must have descriptor associated with it */
static const struct of_device_id scmi_of_match[] = {
-#ifdef CONFIG_MAILBOX
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_MAILBOX
{ .compatible = "arm,scmi", .data = &scmi_mailbox_desc },
#endif
-#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
{ .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
#endif
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
+ { .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc},
+#endif
{ /* Sentinel */ },
};
@@ -1596,10 +2015,69 @@ static struct platform_driver scmi_driver = {
.remove = scmi_remove,
};
+/**
+ * __scmi_transports_setup - Common helper to call transport-specific
+ * .init/.exit code if provided.
+ *
+ * @init: A flag to distinguish between init and exit.
+ *
+ * Note that, if provided, we invoke .init/.exit functions for all the
+ * transports currently compiled in.
+ *
+ * Return: 0 on Success.
+ */
+static inline int __scmi_transports_setup(bool init)
+{
+ int ret = 0;
+ const struct of_device_id *trans;
+
+ for (trans = scmi_of_match; trans->data; trans++) {
+ const struct scmi_desc *tdesc = trans->data;
+
+ if ((init && !tdesc->transport_init) ||
+ (!init && !tdesc->transport_exit))
+ continue;
+
+ if (init)
+ ret = tdesc->transport_init();
+ else
+ tdesc->transport_exit();
+
+ if (ret) {
+ pr_err("SCMI transport %s FAILED initialization!\n",
+ trans->compatible);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int __init scmi_transports_init(void)
+{
+ return __scmi_transports_setup(true);
+}
+
+static void __exit scmi_transports_exit(void)
+{
+ __scmi_transports_setup(false);
+}
+
static int __init scmi_driver_init(void)
{
+ int ret;
+
+ /* Bail out if no SCMI transport was configured */
+ if (WARN_ON(!IS_ENABLED(CONFIG_ARM_SCMI_HAVE_TRANSPORT)))
+ return -EINVAL;
+
scmi_bus_init();
+ /* Initialize any compiled-in transport which provided an init/exit */
+ ret = scmi_transports_init();
+ if (ret)
+ return ret;
+
scmi_base_register();
scmi_clock_register();
@@ -1628,6 +2106,8 @@ static void __exit scmi_driver_exit(void)
scmi_bus_exit();
+ scmi_transports_exit();
+
platform_driver_unregister(&scmi_driver);
}
module_exit(scmi_driver_exit);
diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c
index e3dcb58314ae..e09eb12bf421 100644
--- a/drivers/firmware/arm_scmi/mailbox.c
+++ b/drivers/firmware/arm_scmi/mailbox.c
@@ -43,7 +43,7 @@ static void rx_callback(struct mbox_client *cl, void *m)
{
struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
- scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem));
+ scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem), NULL);
}
static bool mailbox_chan_available(struct device *dev, int idx)
diff --git a/drivers/firmware/arm_scmi/msg.c b/drivers/firmware/arm_scmi/msg.c
new file mode 100644
index 000000000000..d33a704e5814
--- /dev/null
+++ b/drivers/firmware/arm_scmi/msg.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * For transports using message passing.
+ *
+ * Derived from shm.c.
+ *
+ * Copyright (C) 2019-2021 ARM Ltd.
+ * Copyright (C) 2020-2021 OpenSynergy GmbH
+ */
+
+#include <linux/types.h>
+
+#include "common.h"
+
+/*
+ * struct scmi_msg_payld - Transport SDU layout
+ *
+ * The SCMI specification requires all parameters, message headers, return
+ * arguments or any protocol data to be expressed in little endian format only.
+ */
+struct scmi_msg_payld {
+ __le32 msg_header;
+ __le32 msg_payload[];
+};
+
+/**
+ * msg_command_size() - Actual size of transport SDU for command.
+ *
+ * @xfer: message which core has prepared for sending
+ *
+ * Return: transport SDU size.
+ */
+size_t msg_command_size(struct scmi_xfer *xfer)
+{
+ return sizeof(struct scmi_msg_payld) + xfer->tx.len;
+}
+
+/**
+ * msg_response_size() - Maximum size of transport SDU for response.
+ *
+ * @xfer: message which core has prepared for sending
+ *
+ * Return: transport SDU size.
+ */
+size_t msg_response_size(struct scmi_xfer *xfer)
+{
+ return sizeof(struct scmi_msg_payld) + sizeof(__le32) + xfer->rx.len;
+}
+
+/**
+ * msg_tx_prepare() - Set up transport SDU for command.
+ *
+ * @msg: transport SDU for command
+ * @xfer: message which is being sent
+ */
+void msg_tx_prepare(struct scmi_msg_payld *msg, struct scmi_xfer *xfer)
+{
+ msg->msg_header = cpu_to_le32(pack_scmi_header(&xfer->hdr));
+ if (xfer->tx.buf)
+ memcpy(msg->msg_payload, xfer->tx.buf, xfer->tx.len);
+}
+
+/**
+ * msg_read_header() - Read SCMI header from transport SDU.
+ *
+ * @msg: transport SDU
+ *
+ * Return: SCMI header
+ */
+u32 msg_read_header(struct scmi_msg_payld *msg)
+{
+ return le32_to_cpu(msg->msg_header);
+}
+
+/**
+ * msg_fetch_response() - Fetch response SCMI payload from transport SDU.
+ *
+ * @msg: transport SDU with response
+ * @len: transport SDU size
+ * @xfer: message being responded to
+ */
+void msg_fetch_response(struct scmi_msg_payld *msg, size_t len,
+ struct scmi_xfer *xfer)
+{
+ size_t prefix_len = sizeof(*msg) + sizeof(msg->msg_payload[0]);
+
+ xfer->hdr.status = le32_to_cpu(msg->msg_payload[0]);
+ xfer->rx.len = min_t(size_t, xfer->rx.len,
+ len >= prefix_len ? len - prefix_len : 0);
+
+ /* Take a copy to the rx buffer.. */
+ memcpy(xfer->rx.buf, &msg->msg_payload[1], xfer->rx.len);
+}
+
+/**
+ * msg_fetch_notification() - Fetch notification payload from transport SDU.
+ *
+ * @msg: transport SDU with notification
+ * @len: transport SDU size
+ * @max_len: maximum SCMI payload size to fetch
+ * @xfer: notification message
+ */
+void msg_fetch_notification(struct scmi_msg_payld *msg, size_t len,
+ size_t max_len, struct scmi_xfer *xfer)
+{
+ xfer->rx.len = min_t(size_t, max_len,
+ len >= sizeof(*msg) ? len - sizeof(*msg) : 0);
+
+ /* Take a copy to the rx buffer.. */
+ memcpy(xfer->rx.buf, msg->msg_payload, xfer->rx.len);
+}
diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c
index bed5596c7209..4effecc3bb46 100644
--- a/drivers/firmware/arm_scmi/smc.c
+++ b/drivers/firmware/arm_scmi/smc.c
@@ -154,7 +154,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
if (scmi_info->irq)
wait_for_completion(&scmi_info->tx_complete);
- scmi_rx_callback(scmi_info->cinfo, shmem_read_header(scmi_info->shmem));
+ scmi_rx_callback(scmi_info->cinfo,
+ shmem_read_header(scmi_info->shmem), NULL);
mutex_unlock(&scmi_info->shmem_lock);
diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c
new file mode 100644
index 000000000000..224577f86928
--- /dev/null
+++ b/drivers/firmware/arm_scmi/virtio.c
@@ -0,0 +1,491 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Virtio Transport driver for Arm System Control and Management Interface
+ * (SCMI).
+ *
+ * Copyright (C) 2020-2021 OpenSynergy.
+ * Copyright (C) 2021 ARM Ltd.
+ */
+
+/**
+ * DOC: Theory of Operation
+ *
+ * The scmi-virtio transport implements a driver for the virtio SCMI device.
+ *
+ * There is one Tx channel (virtio cmdq, A2P channel) and at most one Rx
+ * channel (virtio eventq, P2A channel). Each channel is implemented through a
+ * virtqueue. Access to each virtqueue is protected by spinlocks.
+ */
+
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+
+#include <uapi/linux/virtio_ids.h>
+#include <uapi/linux/virtio_scmi.h>
+
+#include "common.h"
+
+#define VIRTIO_SCMI_MAX_MSG_SIZE 128 /* Value may be increased. */
+#define VIRTIO_SCMI_MAX_PDU_SIZE \
+ (VIRTIO_SCMI_MAX_MSG_SIZE + SCMI_MSG_MAX_PROT_OVERHEAD)
+#define DESCRIPTORS_PER_TX_MSG 2
+
+/**
+ * struct scmi_vio_channel - Transport channel information
+ *
+ * @vqueue: Associated virtqueue
+ * @cinfo: SCMI Tx or Rx channel
+ * @free_list: List of unused scmi_vio_msg, maintained for Tx channels only
+ * @is_rx: Whether channel is an Rx channel
+ * @ready: Whether transport user is ready to hear about channel
+ * @max_msg: Maximum number of pending messages for this channel.
+ * @lock: Protects access to all members except ready.
+ * @ready_lock: Protects access to ready. If required, it must be taken before
+ * lock.
+ */
+struct scmi_vio_channel {
+ struct virtqueue *vqueue;
+ struct scmi_chan_info *cinfo;
+ struct list_head free_list;
+ bool is_rx;
+ bool ready;
+ unsigned int max_msg;
+ /* lock to protect access to all members except ready. */
+ spinlock_t lock;
+ /* lock to rotects access to ready flag. */
+ spinlock_t ready_lock;
+};
+
+/**
+ * struct scmi_vio_msg - Transport PDU information
+ *
+ * @request: SDU used for commands
+ * @input: SDU used for (delayed) responses and notifications
+ * @list: List which scmi_vio_msg may be part of
+ * @rx_len: Input SDU size in bytes, once input has been received
+ */
+struct scmi_vio_msg {
+ struct scmi_msg_payld *request;
+ struct scmi_msg_payld *input;
+ struct list_head list;
+ unsigned int rx_len;
+};
+
+/* Only one SCMI VirtIO device can possibly exist */
+static struct virtio_device *scmi_vdev;
+
+static bool scmi_vio_have_vq_rx(struct virtio_device *vdev)
+{
+ return virtio_has_feature(vdev, VIRTIO_SCMI_F_P2A_CHANNELS);
+}
+
+static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch,
+ struct scmi_vio_msg *msg)
+{
+ struct scatterlist sg_in;
+ int rc;
+ unsigned long flags;
+
+ sg_init_one(&sg_in, msg->input, VIRTIO_SCMI_MAX_PDU_SIZE);
+
+ spin_lock_irqsave(&vioch->lock, flags);
+
+ rc = virtqueue_add_inbuf(vioch->vqueue, &sg_in, 1, msg, GFP_ATOMIC);
+ if (rc)
+ dev_err_once(vioch->cinfo->dev,
+ "failed to add to virtqueue (%d)\n", rc);
+ else
+ virtqueue_kick(vioch->vqueue);
+
+ spin_unlock_irqrestore(&vioch->lock, flags);
+
+ return rc;
+}
+
+static void scmi_finalize_message(struct scmi_vio_channel *vioch,
+ struct scmi_vio_msg *msg)
+{
+ if (vioch->is_rx) {
+ scmi_vio_feed_vq_rx(vioch, msg);
+ } else {
+ unsigned long flags;
+
+ spin_lock_irqsave(&vioch->lock, flags);
+ list_add(&msg->list, &vioch->free_list);
+ spin_unlock_irqrestore(&vioch->lock, flags);
+ }
+}
+
+static void scmi_vio_complete_cb(struct virtqueue *vqueue)
+{
+ unsigned long ready_flags;
+ unsigned long flags;
+ unsigned int length;
+ struct scmi_vio_channel *vioch;
+ struct scmi_vio_msg *msg;
+ bool cb_enabled = true;
+
+ if (WARN_ON_ONCE(!vqueue->vdev->priv))
+ return;
+ vioch = &((struct scmi_vio_channel *)vqueue->vdev->priv)[vqueue->index];
+
+ for (;;) {
+ spin_lock_irqsave(&vioch->ready_lock, ready_flags);
+
+ if (!vioch->ready) {
+ if (!cb_enabled)
+ (void)virtqueue_enable_cb(vqueue);
+ goto unlock_ready_out;
+ }
+
+ spin_lock_irqsave(&vioch->lock, flags);
+ if (cb_enabled) {
+ virtqueue_disable_cb(vqueue);
+ cb_enabled = false;
+ }
+ msg = virtqueue_get_buf(vqueue, &length);
+ if (!msg) {
+ if (virtqueue_enable_cb(vqueue))
+ goto unlock_out;
+ cb_enabled = true;
+ }
+ spin_unlock_irqrestore(&vioch->lock, flags);
+
+ if (msg) {
+ msg->rx_len = length;
+ scmi_rx_callback(vioch->cinfo,
+ msg_read_header(msg->input), msg);
+
+ scmi_finalize_message(vioch, msg);
+ }
+
+ spin_unlock_irqrestore(&vioch->ready_lock, ready_flags);
+ }
+
+unlock_out:
+ spin_unlock_irqrestore(&vioch->lock, flags);
+unlock_ready_out:
+ spin_unlock_irqrestore(&vioch->ready_lock, ready_flags);
+}
+
+static const char *const scmi_vio_vqueue_names[] = { "tx", "rx" };
+
+static vq_callback_t *scmi_vio_complete_callbacks[] = {
+ scmi_vio_complete_cb,
+ scmi_vio_complete_cb
+};
+
+static unsigned int virtio_get_max_msg(struct scmi_chan_info *base_cinfo)
+{
+ struct scmi_vio_channel *vioch = base_cinfo->transport_info;
+
+ return vioch->max_msg;
+}
+
+static int virtio_link_supplier(struct device *dev)
+{
+ if (!scmi_vdev) {
+ dev_notice_once(dev,
+ "Deferring probe after not finding a bound scmi-virtio device\n");
+ return -EPROBE_DEFER;
+ }
+
+ if (!device_link_add(dev, &scmi_vdev->dev,
+ DL_FLAG_AUTOREMOVE_CONSUMER)) {
+ dev_err(dev, "Adding link to supplier virtio device failed\n");
+ return -ECANCELED;
+ }
+
+ return 0;
+}
+
+static bool virtio_chan_available(struct device *dev, int idx)
+{
+ struct scmi_vio_channel *channels, *vioch = NULL;
+
+ if (WARN_ON_ONCE(!scmi_vdev))
+ return false;
+
+ channels = (struct scmi_vio_channel *)scmi_vdev->priv;
+
+ switch (idx) {
+ case VIRTIO_SCMI_VQ_TX:
+ vioch = &channels[VIRTIO_SCMI_VQ_TX];
+ break;
+ case VIRTIO_SCMI_VQ_RX:
+ if (scmi_vio_have_vq_rx(scmi_vdev))
+ vioch = &channels[VIRTIO_SCMI_VQ_RX];
+ break;
+ default:
+ return false;
+ }
+
+ return vioch && !vioch->cinfo;
+}
+
+static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
+ bool tx)
+{
+ unsigned long flags;
+ struct scmi_vio_channel *vioch;
+ int index = tx ? VIRTIO_SCMI_VQ_TX : VIRTIO_SCMI_VQ_RX;
+ int i;
+
+ if (!scmi_vdev)
+ return -EPROBE_DEFER;
+
+ vioch = &((struct scmi_vio_channel *)scmi_vdev->priv)[index];
+
+ for (i = 0; i < vioch->max_msg; i++) {
+ struct scmi_vio_msg *msg;
+
+ msg = devm_kzalloc(cinfo->dev, sizeof(*msg), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ if (tx) {
+ msg->request = devm_kzalloc(cinfo->dev,
+ VIRTIO_SCMI_MAX_PDU_SIZE,
+ GFP_KERNEL);
+ if (!msg->request)
+ return -ENOMEM;
+ }
+
+ msg->input = devm_kzalloc(cinfo->dev, VIRTIO_SCMI_MAX_PDU_SIZE,
+ GFP_KERNEL);
+ if (!msg->input)
+ return -ENOMEM;
+
+ if (tx) {
+ spin_lock_irqsave(&vioch->lock, flags);
+ list_add_tail(&msg->list, &vioch->free_list);
+ spin_unlock_irqrestore(&vioch->lock, flags);
+ } else {
+ scmi_vio_feed_vq_rx(vioch, msg);
+ }
+ }
+
+ spin_lock_irqsave(&vioch->lock, flags);
+ cinfo->transport_info = vioch;
+ /* Indirectly setting channel not available any more */
+ vioch->cinfo = cinfo;
+ spin_unlock_irqrestore(&vioch->lock, flags);
+
+ spin_lock_irqsave(&vioch->ready_lock, flags);
+ vioch->ready = true;
+ spin_unlock_irqrestore(&vioch->ready_lock, flags);
+
+ return 0;
+}
+
+static int virtio_chan_free(int id, void *p, void *data)
+{
+ unsigned long flags;
+ struct scmi_chan_info *cinfo = p;
+ struct scmi_vio_channel *vioch = cinfo->transport_info;
+
+ spin_lock_irqsave(&vioch->ready_lock, flags);
+ vioch->ready = false;
+ spin_unlock_irqrestore(&vioch->ready_lock, flags);
+
+ scmi_free_channel(cinfo, data, id);
+
+ spin_lock_irqsave(&vioch->lock, flags);
+ vioch->cinfo = NULL;
+ spin_unlock_irqrestore(&vioch->lock, flags);
+
+ return 0;
+}
+
+static int virtio_send_message(struct scmi_chan_info *cinfo,
+ struct scmi_xfer *xfer)
+{
+ struct scmi_vio_channel *vioch = cinfo->transport_info;
+ struct scatterlist sg_out;
+ struct scatterlist sg_in;
+ struct scatterlist *sgs[DESCRIPTORS_PER_TX_MSG] = { &sg_out, &sg_in };
+ unsigned long flags;
+ int rc;
+ struct scmi_vio_msg *msg;
+
+ spin_lock_irqsave(&vioch->lock, flags);
+
+ if (list_empty(&vioch->free_list)) {
+ spin_unlock_irqrestore(&vioch->lock, flags);
+ return -EBUSY;
+ }
+
+ msg = list_first_entry(&vioch->free_list, typeof(*msg), list);
+ list_del(&msg->list);
+
+ msg_tx_prepare(msg->request, xfer);
+
+ sg_init_one(&sg_out, msg->request, msg_command_size(xfer));
+ sg_init_one(&sg_in, msg->input, msg_response_size(xfer));
+
+ rc = virtqueue_add_sgs(vioch->vqueue, sgs, 1, 1, msg, GFP_ATOMIC);
+ if (rc) {
+ list_add(&msg->list, &vioch->free_list);
+ dev_err_once(vioch->cinfo->dev,
+ "%s() failed to add to virtqueue (%d)\n", __func__,
+ rc);
+ } else {
+ virtqueue_kick(vioch->vqueue);
+ }
+
+ spin_unlock_irqrestore(&vioch->lock, flags);
+
+ return rc;
+}
+
+static void virtio_fetch_response(struct scmi_chan_info *cinfo,
+ struct scmi_xfer *xfer)
+{
+ struct scmi_vio_msg *msg = xfer->priv;
+
+ if (msg) {
+ msg_fetch_response(msg->input, msg->rx_len, xfer);
+ xfer->priv = NULL;
+ }
+}
+
+static void virtio_fetch_notification(struct scmi_chan_info *cinfo,
+ size_t max_len, struct scmi_xfer *xfer)
+{
+ struct scmi_vio_msg *msg = xfer->priv;
+
+ if (msg) {
+ msg_fetch_notification(msg->input, msg->rx_len, max_len, xfer);
+ xfer->priv = NULL;
+ }
+}
+
+static const struct scmi_transport_ops scmi_virtio_ops = {
+ .link_supplier = virtio_link_supplier,
+ .chan_available = virtio_chan_available,
+ .chan_setup = virtio_chan_setup,
+ .chan_free = virtio_chan_free,
+ .get_max_msg = virtio_get_max_msg,
+ .send_message = virtio_send_message,
+ .fetch_response = virtio_fetch_response,
+ .fetch_notification = virtio_fetch_notification,
+};
+
+static int scmi_vio_probe(struct virtio_device *vdev)
+{
+ struct device *dev = &vdev->dev;
+ struct scmi_vio_channel *channels;
+ bool have_vq_rx;
+ int vq_cnt;
+ int i;
+ int ret;
+ struct virtqueue *vqs[VIRTIO_SCMI_VQ_MAX_CNT];
+
+ /* Only one SCMI VirtiO device allowed */
+ if (scmi_vdev)
+ return -EINVAL;
+
+ have_vq_rx = scmi_vio_have_vq_rx(vdev);
+ vq_cnt = have_vq_rx ? VIRTIO_SCMI_VQ_MAX_CNT : 1;
+
+ channels = devm_kcalloc(dev, vq_cnt, sizeof(*channels), GFP_KERNEL);
+ if (!channels)
+ return -ENOMEM;
+
+ if (have_vq_rx)
+ channels[VIRTIO_SCMI_VQ_RX].is_rx = true;
+
+ ret = virtio_find_vqs(vdev, vq_cnt, vqs, scmi_vio_complete_callbacks,
+ scmi_vio_vqueue_names, NULL);
+ if (ret) {
+ dev_err(dev, "Failed to get %d virtqueue(s)\n", vq_cnt);
+ return ret;
+ }
+
+ for (i = 0; i < vq_cnt; i++) {
+ unsigned int sz;
+
+ spin_lock_init(&channels[i].lock);
+ spin_lock_init(&channels[i].ready_lock);
+ INIT_LIST_HEAD(&channels[i].free_list);
+ channels[i].vqueue = vqs[i];
+
+ sz = virtqueue_get_vring_size(channels[i].vqueue);
+ /* Tx messages need multiple descriptors. */
+ if (!channels[i].is_rx)
+ sz /= DESCRIPTORS_PER_TX_MSG;
+
+ if (sz > MSG_TOKEN_MAX) {
+ dev_info_once(dev,
+ "%s virtqueue could hold %d messages. Only %ld allowed to be pending.\n",
+ channels[i].is_rx ? "rx" : "tx",
+ sz, MSG_TOKEN_MAX);
+ sz = MSG_TOKEN_MAX;
+ }
+ channels[i].max_msg = sz;
+ }
+
+ vdev->priv = channels;
+ scmi_vdev = vdev;
+
+ return 0;
+}
+
+static void scmi_vio_remove(struct virtio_device *vdev)
+{
+ vdev->config->reset(vdev);
+ vdev->config->del_vqs(vdev);
+ scmi_vdev = NULL;
+}
+
+static int scmi_vio_validate(struct virtio_device *vdev)
+{
+ if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+ dev_err(&vdev->dev,
+ "device does not comply with spec version 1.x\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static unsigned int features[] = {
+ VIRTIO_SCMI_F_P2A_CHANNELS,
+};
+
+static const struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_SCMI, VIRTIO_DEV_ANY_ID },
+ { 0 }
+};
+
+static struct virtio_driver virtio_scmi_driver = {
+ .driver.name = "scmi-virtio",
+ .driver.owner = THIS_MODULE,
+ .feature_table = features,
+ .feature_table_size = ARRAY_SIZE(features),
+ .id_table = id_table,
+ .probe = scmi_vio_probe,
+ .remove = scmi_vio_remove,
+ .validate = scmi_vio_validate,
+};
+
+static int __init virtio_scmi_init(void)
+{
+ return register_virtio_driver(&virtio_scmi_driver);
+}
+
+static void __exit virtio_scmi_exit(void)
+{
+ unregister_virtio_driver(&virtio_scmi_driver);
+}
+
+const struct scmi_desc scmi_virtio_desc = {
+ .transport_init = virtio_scmi_init,
+ .transport_exit = virtio_scmi_exit,
+ .ops = &scmi_virtio_ops,
+ .max_rx_timeout_ms = 60000, /* for non-realtime virtio devices */
+ .max_msg = 0, /* overridden by virtio_get_max_msg() */
+ .max_msg_size = VIRTIO_SCMI_MAX_MSG_SIZE,
+};
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
index 4d5421d14a41..940ddf916202 100644
--- a/drivers/firmware/dmi-id.c
+++ b/drivers/firmware/dmi-id.c
@@ -73,6 +73,10 @@ static void ascii_filter(char *d, const char *s)
static ssize_t get_modalias(char *buffer, size_t buffer_size)
{
+ /*
+ * Note new fields need to be added at the end to keep compatibility
+ * with udev's hwdb which does matches on "`cat dmi/id/modalias`*".
+ */
static const struct mafield {
const char *prefix;
int field;
@@ -85,13 +89,13 @@ static ssize_t get_modalias(char *buffer, size_t buffer_size)
{ "svn", DMI_SYS_VENDOR },
{ "pn", DMI_PRODUCT_NAME },
{ "pvr", DMI_PRODUCT_VERSION },
- { "sku", DMI_PRODUCT_SKU },
{ "rvn", DMI_BOARD_VENDOR },
{ "rn", DMI_BOARD_NAME },
{ "rvr", DMI_BOARD_VERSION },
{ "cvn", DMI_CHASSIS_VENDOR },
{ "ct", DMI_CHASSIS_TYPE },
{ "cvr", DMI_CHASSIS_VERSION },
+ { "sku", DMI_PRODUCT_SKU },
{ NULL, DMI_NONE }
};
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 467e94259679..c02ff25dd477 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -36,6 +36,8 @@ obj-$(CONFIG_LOAD_UEFI_KEYS) += mokvar-table.o
fake_map-y += fake_mem.o
fake_map-$(CONFIG_X86) += x86_fake_mem.o
+obj-$(CONFIG_SYSFB) += sysfb_efi.o
+
arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o
obj-$(CONFIG_ARM) += $(arm-obj-y)
obj-$(CONFIG_ARM64) += $(arm-obj-y)
diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
index a552a08a1741..b19ce1a83f91 100644
--- a/drivers/firmware/efi/efi-init.c
+++ b/drivers/firmware/efi/efi-init.c
@@ -275,93 +275,3 @@ void __init efi_init(void)
}
#endif
}
-
-static bool efifb_overlaps_pci_range(const struct of_pci_range *range)
-{
- u64 fb_base = screen_info.lfb_base;
-
- if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
- fb_base |= (u64)(unsigned long)screen_info.ext_lfb_base << 32;
-
- return fb_base >= range->cpu_addr &&
- fb_base < (range->cpu_addr + range->size);
-}
-
-static struct device_node *find_pci_overlap_node(void)
-{
- struct device_node *np;
-
- for_each_node_by_type(np, "pci") {
- struct of_pci_range_parser parser;
- struct of_pci_range range;
- int err;
-
- err = of_pci_range_parser_init(&parser, np);
- if (err) {
- pr_warn("of_pci_range_parser_init() failed: %d\n", err);
- continue;
- }
-
- for_each_of_pci_range(&parser, &range)
- if (efifb_overlaps_pci_range(&range))
- return np;
- }
- return NULL;
-}
-
-/*
- * If the efifb framebuffer is backed by a PCI graphics controller, we have
- * to ensure that this relation is expressed using a device link when
- * running in DT mode, or the probe order may be reversed, resulting in a
- * resource reservation conflict on the memory window that the efifb
- * framebuffer steals from the PCIe host bridge.
- */
-static int efifb_add_links(struct fwnode_handle *fwnode)
-{
- struct device_node *sup_np;
-
- sup_np = find_pci_overlap_node();
-
- /*
- * If there's no PCI graphics controller backing the efifb, we are
- * done here.
- */
- if (!sup_np)
- return 0;
-
- fwnode_link_add(fwnode, of_fwnode_handle(sup_np));
- of_node_put(sup_np);
-
- return 0;
-}
-
-static const struct fwnode_operations efifb_fwnode_ops = {
- .add_links = efifb_add_links,
-};
-
-static struct fwnode_handle efifb_fwnode;
-
-static int __init register_gop_device(void)
-{
- struct platform_device *pd;
- int err;
-
- if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
- return 0;
-
- pd = platform_device_alloc("efi-framebuffer", 0);
- if (!pd)
- return -ENOMEM;
-
- if (IS_ENABLED(CONFIG_PCI)) {
- fwnode_init(&efifb_fwnode, &efifb_fwnode_ops);
- pd->dev.fwnode = &efifb_fwnode;
- }
-
- err = platform_device_add_data(pd, &screen_info, sizeof(screen_info));
- if (err)
- return err;
-
- return platform_device_add(pd);
-}
-subsys_initcall(register_gop_device);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index ae87dded989d..d489bdc645fe 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -7,7 +7,7 @@
* Copyright 2011 Intel Corporation; author Matt Fleming
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/ctype.h>
#include <linux/efi.h>
diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
index 1088e288c04d..71c71c222346 100644
--- a/drivers/firmware/efi/libstub/vsprintf.c
+++ b/drivers/firmware/efi/libstub/vsprintf.c
@@ -10,7 +10,7 @@
* Oh, it's a waste of space, but oh-so-yummy for debugging.
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/compiler.h>
#include <linux/ctype.h>
diff --git a/arch/x86/kernel/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c
index 8a56a6d80098..4c7c9dd7733f 100644
--- a/arch/x86/kernel/sysfb_efi.c
+++ b/drivers/firmware/efi/sysfb_efi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Generic System Framebuffers on x86
+ * Generic System Framebuffers
* Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
*
* EFI Quirks Copyright (c) 2006 Edgar Hucek <gimli@dark-green.com>
@@ -19,12 +19,14 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/of_address.h>
#include <linux/pci.h>
+#include <linux/platform_device.h>
#include <linux/screen_info.h>
+#include <linux/sysfb.h>
#include <video/vga.h>
#include <asm/efi.h>
-#include <asm/sysfb.h>
enum {
OVERRIDE_NONE = 0x0,
@@ -267,7 +269,73 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
{},
};
-__init void sysfb_apply_efi_quirks(void)
+static bool efifb_overlaps_pci_range(const struct of_pci_range *range)
+{
+ u64 fb_base = screen_info.lfb_base;
+
+ if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+ fb_base |= (u64)(unsigned long)screen_info.ext_lfb_base << 32;
+
+ return fb_base >= range->cpu_addr &&
+ fb_base < (range->cpu_addr + range->size);
+}
+
+static struct device_node *find_pci_overlap_node(void)
+{
+ struct device_node *np;
+
+ for_each_node_by_type(np, "pci") {
+ struct of_pci_range_parser parser;
+ struct of_pci_range range;
+ int err;
+
+ err = of_pci_range_parser_init(&parser, np);
+ if (err) {
+ pr_warn("of_pci_range_parser_init() failed: %d\n", err);
+ continue;
+ }
+
+ for_each_of_pci_range(&parser, &range)
+ if (efifb_overlaps_pci_range(&range))
+ return np;
+ }
+ return NULL;
+}
+
+/*
+ * If the efifb framebuffer is backed by a PCI graphics controller, we have
+ * to ensure that this relation is expressed using a device link when
+ * running in DT mode, or the probe order may be reversed, resulting in a
+ * resource reservation conflict on the memory window that the efifb
+ * framebuffer steals from the PCIe host bridge.
+ */
+static int efifb_add_links(struct fwnode_handle *fwnode)
+{
+ struct device_node *sup_np;
+
+ sup_np = find_pci_overlap_node();
+
+ /*
+ * If there's no PCI graphics controller backing the efifb, we are
+ * done here.
+ */
+ if (!sup_np)
+ return 0;
+
+ fwnode_link_add(fwnode, of_fwnode_handle(sup_np));
+ of_node_put(sup_np);
+
+ return 0;
+}
+
+static const struct fwnode_operations efifb_fwnode_ops = {
+ .add_links = efifb_add_links,
+};
+
+#ifdef CONFIG_EFI
+static struct fwnode_handle efifb_fwnode;
+
+__init void sysfb_apply_efi_quirks(struct platform_device *pd)
{
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
!(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
@@ -281,4 +349,10 @@ __init void sysfb_apply_efi_quirks(void)
screen_info.lfb_height = temp;
screen_info.lfb_linelength = 4 * screen_info.lfb_width;
}
+
+ if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) {
+ fwnode_init(&efifb_fwnode, &efifb_fwnode_ops);
+ pd->dev.fwnode = &efifb_fwnode;
+ }
}
+#endif
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c
index dc83ea118c67..c52bcaa9def6 100644
--- a/drivers/firmware/google/coreboot_table.c
+++ b/drivers/firmware/google/coreboot_table.c
@@ -44,15 +44,13 @@ static int coreboot_bus_probe(struct device *dev)
return ret;
}
-static int coreboot_bus_remove(struct device *dev)
+static void coreboot_bus_remove(struct device *dev)
{
struct coreboot_device *device = CB_DEV(dev);
struct coreboot_driver *driver = CB_DRV(dev->driver);
if (driver->remove)
driver->remove(device);
-
- return 0;
}
static struct bus_type coreboot_bus_type = {
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index 612a59e213df..6e9788324fea 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -86,10 +86,6 @@ MODULE_VERSION(IBFT_ISCSI_VERSION);
static struct acpi_table_ibft *ibft_addr;
-#ifndef CONFIG_ISCSI_IBFT_FIND
-phys_addr_t ibft_phys_addr;
-#endif
-
struct ibft_hdr {
u8 id;
u8 version;
@@ -851,7 +847,21 @@ static void __init acpi_find_ibft_region(void)
{
}
#endif
-
+#ifdef CONFIG_ISCSI_IBFT_FIND
+static int __init acpi_find_isa_region(void)
+{
+ if (ibft_phys_addr) {
+ ibft_addr = isa_bus_to_virt(ibft_phys_addr);
+ return 0;
+ }
+ return -ENODEV;
+}
+#else
+static int __init acpi_find_isa_region(void)
+{
+ return -ENODEV;
+}
+#endif
/*
* ibft_init() - creates sysfs tree entries for the iBFT data.
*/
@@ -864,9 +874,7 @@ static int __init ibft_init(void)
is called before ACPI tables are parsed and it only does
legacy finding.
*/
- if (ibft_phys_addr)
- ibft_addr = isa_bus_to_virt(ibft_phys_addr);
- else
+ if (acpi_find_isa_region())
acpi_find_ibft_region();
if (ibft_addr) {
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 47ea2bd42b10..ced1964faf42 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -71,7 +71,7 @@ static struct qcom_scm_wb_entry qcom_scm_wb[] = {
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
};
-static const char *qcom_scm_convention_names[] = {
+static const char * const qcom_scm_convention_names[] = {
[SMC_CONVENTION_UNKNOWN] = "unknown",
[SMC_CONVENTION_ARM_32] = "smc arm 32",
[SMC_CONVENTION_ARM_64] = "smc arm 64",
@@ -331,7 +331,7 @@ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
.owner = ARM_SMCCC_OWNER_SIP,
};
- if (!cpus || (cpus && cpumask_empty(cpus)))
+ if (!cpus || cpumask_empty(cpus))
return -EINVAL;
for_each_cpu(cpu, cpus) {
@@ -1299,6 +1299,7 @@ static const struct of_device_id qcom_scm_dt_match[] = {
{ .compatible = "qcom,scm" },
{}
};
+MODULE_DEVICE_TABLE(of, qcom_scm_dt_match);
static struct platform_driver qcom_scm_driver = {
.driver = {
@@ -1315,3 +1316,6 @@ static int __init qcom_scm_init(void)
return platform_driver_register(&qcom_scm_driver);
}
subsys_initcall(qcom_scm_init);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. SCM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 250e01680742..4b8978b254f9 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -329,12 +329,18 @@ struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node)
fw = platform_get_drvdata(pdev);
if (!fw)
- return NULL;
+ goto err_put_device;
if (!kref_get_unless_zero(&fw->consumers))
- return NULL;
+ goto err_put_device;
+
+ put_device(&pdev->dev);
return fw;
+
+err_put_device:
+ put_device(&pdev->dev);
+ return NULL;
}
EXPORT_SYMBOL_GPL(rpi_firmware_get);
diff --git a/arch/x86/kernel/sysfb.c b/drivers/firmware/sysfb.c
index 014ebd8ca869..2bfbb05f7d89 100644
--- a/arch/x86/kernel/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Generic System Framebuffers on x86
+ * Generic System Framebuffers
* Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
*/
/*
- * Simple-Framebuffer support for x86 systems
+ * Simple-Framebuffer support
* Create a platform-device for any available boot framebuffer. The
* simple-framebuffer platform device is already available on DT systems, so
* this module parses the global "screen_info" object and creates a suitable
@@ -16,12 +16,12 @@
* to pick these devices up without messing with simple-framebuffer drivers.
* The global "screen_info" is still valid at all times.
*
- * If CONFIG_X86_SYSFB is not selected, we never register "simple-framebuffer"
+ * If CONFIG_SYSFB_SIMPLEFB is not selected, never register "simple-framebuffer"
* platform devices, but only use legacy framebuffer devices for
* backwards compatibility.
*
* TODO: We set the dev_id field of all platform-devices to 0. This allows
- * other x86 OF/DT parsers to create such devices, too. However, they must
+ * other OF/DT parsers to create such devices, too. However, they must
* start at offset 1 for this to work.
*/
@@ -32,7 +32,7 @@
#include <linux/platform_data/simplefb.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>
-#include <asm/sysfb.h>
+#include <linux/sysfb.h>
static __init int sysfb_init(void)
{
@@ -43,12 +43,10 @@ static __init int sysfb_init(void)
bool compatible;
int ret;
- sysfb_apply_efi_quirks();
-
/* try to create a simple-framebuffer device */
- compatible = parse_mode(si, &mode);
+ compatible = sysfb_parse_mode(si, &mode);
if (compatible) {
- ret = create_simplefb(si, &mode);
+ ret = sysfb_create_simplefb(si, &mode);
if (!ret)
return 0;
}
@@ -61,9 +59,24 @@ static __init int sysfb_init(void)
else
name = "platform-framebuffer";
- pd = platform_device_register_resndata(NULL, name, 0,
- NULL, 0, si, sizeof(*si));
- return PTR_ERR_OR_ZERO(pd);
+ pd = platform_device_alloc(name, 0);
+ if (!pd)
+ return -ENOMEM;
+
+ sysfb_apply_efi_quirks(pd);
+
+ ret = platform_device_add_data(pd, si, sizeof(*si));
+ if (ret)
+ goto err;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ platform_device_put(pd);
+ return ret;
}
/* must execute after PCI subsystem for EFI quirks */
diff --git a/arch/x86/kernel/sysfb_simplefb.c b/drivers/firmware/sysfb_simplefb.c
index 298fc1edd9c9..b86761904949 100644
--- a/arch/x86/kernel/sysfb_simplefb.c
+++ b/drivers/firmware/sysfb_simplefb.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Generic System Framebuffers on x86
+ * Generic System Framebuffers
* Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
*/
@@ -18,14 +18,14 @@
#include <linux/platform_data/simplefb.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>
-#include <asm/sysfb.h>
+#include <linux/sysfb.h>
static const char simplefb_resname[] = "BOOTFB";
static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
-/* try parsing x86 screen_info into a simple-framebuffer mode struct */
-__init bool parse_mode(const struct screen_info *si,
- struct simplefb_platform_data *mode)
+/* try parsing screen_info into a simple-framebuffer mode struct */
+__init bool sysfb_parse_mode(const struct screen_info *si,
+ struct simplefb_platform_data *mode)
{
const struct simplefb_format *f;
__u8 type;
@@ -57,13 +57,14 @@ __init bool parse_mode(const struct screen_info *si,
return false;
}
-__init int create_simplefb(const struct screen_info *si,
- const struct simplefb_platform_data *mode)
+__init int sysfb_create_simplefb(const struct screen_info *si,
+ const struct simplefb_platform_data *mode)
{
struct platform_device *pd;
struct resource res;
u64 base, size;
u32 length;
+ int ret;
/*
* If the 64BIT_BASE capability is set, ext_lfb_base will contain the
@@ -105,7 +106,19 @@ __init int create_simplefb(const struct screen_info *si,
if (res.end <= res.start)
return -EINVAL;
- pd = platform_device_register_resndata(NULL, "simple-framebuffer", 0,
- &res, 1, mode, sizeof(*mode));
- return PTR_ERR_OR_ZERO(pd);
+ pd = platform_device_alloc("simple-framebuffer", 0);
+ if (!pd)
+ return -ENOMEM;
+
+ sysfb_apply_efi_quirks(pd);
+
+ ret = platform_device_add_resources(pd, &res, 1);
+ if (ret)
+ return ret;
+
+ ret = platform_device_add_data(pd, mode, sizeof(*mode));
+ if (ret)
+ return ret;
+
+ return platform_device_add(pd);
}
diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c
index 440d99c63638..3e9fa4b54358 100644
--- a/drivers/firmware/tegra/bpmp-debugfs.c
+++ b/drivers/firmware/tegra/bpmp-debugfs.c
@@ -296,25 +296,61 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
struct file *file = m->private;
struct inode *inode = file_inode(file);
struct tegra_bpmp *bpmp = inode->i_private;
- char *databuf = NULL;
char fnamebuf[256];
const char *filename;
- uint32_t nbytes = 0;
- size_t len;
- int err;
-
- len = seq_get_buf(m, &databuf);
- if (!databuf)
- return -ENOMEM;
+ struct mrq_debug_request req = {
+ .cmd = cpu_to_le32(CMD_DEBUG_READ),
+ };
+ struct mrq_debug_response resp;
+ struct tegra_bpmp_message msg = {
+ .mrq = MRQ_DEBUG,
+ .tx = {
+ .data = &req,
+ .size = sizeof(req),
+ },
+ .rx = {
+ .data = &resp,
+ .size = sizeof(resp),
+ },
+ };
+ uint32_t fd = 0, len = 0;
+ int remaining, err;
filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
if (!filename)
return -ENOENT;
- err = mrq_debug_read(bpmp, filename, databuf, len, &nbytes);
- if (!err)
- seq_commit(m, nbytes);
+ mutex_lock(&bpmp_debug_lock);
+ err = mrq_debug_open(bpmp, filename, &fd, &len, 0);
+ if (err)
+ goto out;
+
+ req.frd.fd = fd;
+ remaining = len;
+
+ while (remaining > 0) {
+ err = tegra_bpmp_transfer(bpmp, &msg);
+ if (err < 0) {
+ goto close;
+ } else if (msg.rx.ret < 0) {
+ err = -EINVAL;
+ goto close;
+ }
+ if (resp.frd.readlen > remaining) {
+ pr_err("%s: read data length invalid\n", __func__);
+ err = -EINVAL;
+ goto close;
+ }
+
+ seq_write(m, resp.frd.data, resp.frd.readlen);
+ remaining -= resp.frd.readlen;
+ }
+
+close:
+ err = mrq_debug_close(bpmp, fd);
+out:
+ mutex_unlock(&bpmp_debug_lock);
return err;
}
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 15b138326ecc..a3cadbaf3cba 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -664,7 +664,7 @@ int zynqmp_pm_write_ggs(u32 index, u32 value)
EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
/**
- * zynqmp_pm_write_ggs() - PM API for reading global general storage (ggs)
+ * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
* @index: GGS register index
* @value: Register value to be written
*
@@ -697,7 +697,7 @@ int zynqmp_pm_write_pggs(u32 index, u32 value)
EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
/**
- * zynqmp_pm_write_pggs() - PM API for reading persistent global general
+ * zynqmp_pm_read_pggs() - PM API for reading persistent global general
* storage (pggs)
* @index: PGGS register index
* @value: Register value to be written
@@ -1012,7 +1012,24 @@ int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
/**
- * zynqmp_pm_aes - Access AES hardware to encrypt/decrypt the data using
+ * zynqmp_pm_load_pdi - Load and process PDI
+ * @src: Source device where PDI is located
+ * @address: PDI src address
+ *
+ * This function provides support to load PDI from linux
+ *
+ * Return: Returns status, either success or error+reason
+ */
+int zynqmp_pm_load_pdi(const u32 src, const u64 address)
+{
+ return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src,
+ lower_32_bits(address),
+ upper_32_bits(address), 0, NULL);
+}
+EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
+
+/**
+ * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
* AES-GCM core.
* @address: Address of the AesParams structure.
* @out: Returned output value
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 8cd454ee20c0..991b3f361ec9 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -119,7 +119,7 @@ config XILINX_PR_DECOUPLER
depends on HAS_IOMEM
help
Say Y to enable drivers for Xilinx LogiCORE PR Decoupler
- or Xilinx Dynamic Function eXchnage AIX Shutdown Manager.
+ or Xilinx Dynamic Function eXchange AIX Shutdown Manager.
The PR Decoupler exists in the FPGA fabric to isolate one
region of the FPGA from the busses while that region is
being reprogrammed during partial reconfig.
@@ -234,4 +234,13 @@ config FPGA_MGR_ZYNQMP_FPGA
to configure the programmable logic(PL) through PS
on ZynqMP SoC.
+config FPGA_MGR_VERSAL_FPGA
+ tristate "Xilinx Versal FPGA"
+ depends on ARCH_ZYNQMP || COMPILE_TEST
+ help
+ Select this option to enable FPGA manager driver support for
+ Xilinx Versal SoC. This driver uses the firmware interface to
+ configure the programmable logic(PL).
+
+ To compile this as a module, choose M here.
endif # FPGA
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 18dc9885883a..0bff783d1b61 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o
obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o
obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA) += zynqmp-fpga.o
+obj-$(CONFIG_FPGA_MGR_VERSAL_FPGA) += versal-fpga.o
obj-$(CONFIG_ALTERA_PR_IP_CORE) += altera-pr-ip-core.o
obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT) += altera-pr-ip-core-plat.o
diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c
index 4e0edb60bfba..ccf4546eff29 100644
--- a/drivers/fpga/altera-cvp.c
+++ b/drivers/fpga/altera-cvp.c
@@ -346,7 +346,7 @@ static int altera_cvp_write_init(struct fpga_manager *mgr,
}
if (val & VSE_CVP_STATUS_CFG_RDY) {
- dev_warn(&mgr->dev, "CvP already started, teardown first\n");
+ dev_warn(&mgr->dev, "CvP already started, tear down first\n");
ret = altera_cvp_teardown(mgr, info);
if (ret)
return ret;
diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c
index dd58c4aea92e..7d22a44d652e 100644
--- a/drivers/fpga/altera-freeze-bridge.c
+++ b/drivers/fpga/altera-freeze-bridge.c
@@ -198,11 +198,13 @@ static const struct fpga_bridge_ops altera_freeze_br_br_ops = {
.enable_show = altera_freeze_br_enable_show,
};
+#ifdef CONFIG_OF
static const struct of_device_id altera_freeze_br_of_match[] = {
{ .compatible = "altr,freeze-bridge-controller", },
{},
};
MODULE_DEVICE_TABLE(of, altera_freeze_br_of_match);
+#endif
static int altera_freeze_br_probe(struct platform_device *pdev)
{
diff --git a/drivers/fpga/dfl-fme-mgr.c b/drivers/fpga/dfl-fme-mgr.c
index d5861d13b306..313420405d5e 100644
--- a/drivers/fpga/dfl-fme-mgr.c
+++ b/drivers/fpga/dfl-fme-mgr.c
@@ -252,11 +252,6 @@ static int fme_mgr_write_complete(struct fpga_manager *mgr,
return 0;
}
-static enum fpga_mgr_states fme_mgr_state(struct fpga_manager *mgr)
-{
- return FPGA_MGR_STATE_UNKNOWN;
-}
-
static u64 fme_mgr_status(struct fpga_manager *mgr)
{
struct fme_mgr_priv *priv = mgr->priv;
@@ -268,7 +263,6 @@ static const struct fpga_manager_ops fme_mgr_ops = {
.write_init = fme_mgr_write_init,
.write = fme_mgr_write,
.write_complete = fme_mgr_write_complete,
- .state = fme_mgr_state,
.status = fme_mgr_status,
};
diff --git a/drivers/fpga/dfl-fme-pr.c b/drivers/fpga/dfl-fme-pr.c
index 1194c0e850e0..d61ce9a18879 100644
--- a/drivers/fpga/dfl-fme-pr.c
+++ b/drivers/fpga/dfl-fme-pr.c
@@ -148,7 +148,7 @@ static int fme_pr(struct platform_device *pdev, unsigned long arg)
/*
* it allows userspace to reset the PR region's logic by disabling and
- * reenabling the bridge to clear things out between accleration runs.
+ * reenabling the bridge to clear things out between acceleration runs.
* so no need to hold the bridges after partial reconfiguration.
*/
if (region->get_bridges)
diff --git a/drivers/fpga/dfl-n3000-nios.c b/drivers/fpga/dfl-n3000-nios.c
index 7a95366f6516..9ddf1d1d392f 100644
--- a/drivers/fpga/dfl-n3000-nios.c
+++ b/drivers/fpga/dfl-n3000-nios.c
@@ -461,7 +461,7 @@ static int n3000_nios_poll_stat_timeout(void __iomem *base, u64 *v)
* We don't use the time based timeout here for performance.
*
* The regbus read/write is on the critical path of Intel PAC N3000
- * image programing. The time based timeout checking will add too much
+ * image programming. The time based timeout checking will add too much
* overhead on it. Usually the state changes in 1 or 2 loops on the
* test server, and we set 10000 times loop here for safety.
*/
diff --git a/drivers/fpga/dfl-pci.c b/drivers/fpga/dfl-pci.c
index b44523ea8c91..4d68719e608f 100644
--- a/drivers/fpga/dfl-pci.c
+++ b/drivers/fpga/dfl-pci.c
@@ -74,6 +74,9 @@ static void cci_pci_free_irq(struct pci_dev *pcidev)
#define PCIE_DEVICE_ID_PF_DSC_1_X 0x09C4
#define PCIE_DEVICE_ID_INTEL_PAC_N3000 0x0B30
#define PCIE_DEVICE_ID_INTEL_PAC_D5005 0x0B2B
+#define PCIE_DEVICE_ID_SILICOM_PAC_N5010 0x1000
+#define PCIE_DEVICE_ID_SILICOM_PAC_N5011 0x1001
+
/* VF Device */
#define PCIE_DEVICE_ID_VF_INT_5_X 0xBCBF
#define PCIE_DEVICE_ID_VF_INT_6_X 0xBCC1
@@ -90,6 +93,8 @@ static struct pci_device_id cci_pcie_id_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_N3000),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005_VF),},
+ {PCI_DEVICE(PCI_VENDOR_ID_SILICOM_DENMARK, PCIE_DEVICE_ID_SILICOM_PAC_N5010),},
+ {PCI_DEVICE(PCI_VENDOR_ID_SILICOM_DENMARK, PCIE_DEVICE_ID_SILICOM_PAC_N5011),},
{0,}
};
MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index 511b20ff35a3..c99b78ee008a 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -284,15 +284,13 @@ static int dfl_bus_probe(struct device *dev)
return ddrv->probe(ddev);
}
-static int dfl_bus_remove(struct device *dev)
+static void dfl_bus_remove(struct device *dev)
{
struct dfl_driver *ddrv = to_dfl_drv(dev->driver);
struct dfl_device *ddev = to_dfl_dev(dev);
if (ddrv->remove)
ddrv->remove(ddev);
-
- return 0;
}
static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -381,6 +379,7 @@ dfl_dev_add(struct dfl_feature_platform_data *pdata,
ddev->type = feature_dev_id_type(pdev);
ddev->feature_id = feature->id;
+ ddev->revision = feature->revision;
ddev->cdev = pdata->dfl_cdev;
/* add mmio resource */
@@ -717,6 +716,7 @@ struct build_feature_devs_info {
*/
struct dfl_feature_info {
u16 fid;
+ u8 revision;
struct resource mmio_res;
void __iomem *ioaddr;
struct list_head node;
@@ -796,6 +796,7 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
/* save resource information for each feature */
feature->dev = fdev;
feature->id = finfo->fid;
+ feature->revision = finfo->revision;
/*
* the FIU header feature has some fundamental functions (sriov
@@ -910,19 +911,17 @@ static void build_info_free(struct build_feature_devs_info *binfo)
devm_kfree(binfo->dev, binfo);
}
-static inline u32 feature_size(void __iomem *start)
+static inline u32 feature_size(u64 value)
{
- u64 v = readq(start + DFH);
- u32 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, v);
+ u32 ofst = FIELD_GET(DFH_NEXT_HDR_OFST, value);
/* workaround for private features with invalid size, use 4K instead */
return ofst ? ofst : 4096;
}
-static u16 feature_id(void __iomem *start)
+static u16 feature_id(u64 value)
{
- u64 v = readq(start + DFH);
- u16 id = FIELD_GET(DFH_ID, v);
- u8 type = FIELD_GET(DFH_TYPE, v);
+ u16 id = FIELD_GET(DFH_ID, value);
+ u8 type = FIELD_GET(DFH_TYPE, value);
if (type == DFH_TYPE_FIU)
return FEATURE_ID_FIU_HEADER;
@@ -1021,10 +1020,15 @@ create_feature_instance(struct build_feature_devs_info *binfo,
unsigned int irq_base, nr_irqs;
struct dfl_feature_info *finfo;
int ret;
+ u8 revision;
+ u64 v;
+
+ v = readq(binfo->ioaddr + ofst);
+ revision = FIELD_GET(DFH_REVISION, v);
/* read feature size and id if inputs are invalid */
- size = size ? size : feature_size(binfo->ioaddr + ofst);
- fid = fid ? fid : feature_id(binfo->ioaddr + ofst);
+ size = size ? size : feature_size(v);
+ fid = fid ? fid : feature_id(v);
if (binfo->len - ofst < size)
return -EINVAL;
@@ -1038,6 +1042,7 @@ create_feature_instance(struct build_feature_devs_info *binfo,
return -ENOMEM;
finfo->fid = fid;
+ finfo->revision = revision;
finfo->mmio_res.start = binfo->start + ofst;
finfo->mmio_res.end = finfo->mmio_res.start + size - 1;
finfo->mmio_res.flags = IORESOURCE_MEM;
@@ -1166,7 +1171,7 @@ static int parse_feature_private(struct build_feature_devs_info *binfo,
{
if (!is_feature_dev_detected(binfo)) {
dev_err(binfo->dev, "the private feature 0x%x does not belong to any AFU.\n",
- feature_id(binfo->ioaddr + ofst));
+ feature_id(readq(binfo->ioaddr + ofst)));
return -EINVAL;
}
diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h
index 2b82c96ba56c..53572c7aced0 100644
--- a/drivers/fpga/dfl.h
+++ b/drivers/fpga/dfl.h
@@ -232,7 +232,7 @@ struct dfl_feature_irq_ctx {
* @id: sub feature id.
* @resource_index: each sub feature has one mmio resource for its registers.
* this index is used to find its mmio resource from the
- * feature dev (platform device)'s reources.
+ * feature dev (platform device)'s resources.
* @ioaddr: mapped mmio resource address.
* @irq_ctx: interrupt context list.
* @nr_irqs: number of interrupt contexts.
@@ -243,6 +243,7 @@ struct dfl_feature_irq_ctx {
struct dfl_feature {
struct platform_device *dev;
u16 id;
+ u8 revision;
int resource_index;
void __iomem *ioaddr;
struct dfl_feature_irq_ctx *irq_ctx;
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
index 2bfb2ff86930..798f55670646 100644
--- a/drivers/fpga/fpga-bridge.c
+++ b/drivers/fpga/fpga-bridge.c
@@ -228,9 +228,9 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put);
* @info: fpga image specific information
* @bridge_list: list of FPGA bridges
*
- * Get an exclusive reference to the bridge and and it to the list.
+ * Get an exclusive reference to the bridge and it to the list.
*
- * Return 0 for success, error code from of_fpga_bridge_get() othewise.
+ * Return 0 for success, error code from of_fpga_bridge_get() otherwise.
*/
int of_fpga_bridge_get_to_list(struct device_node *np,
struct fpga_image_info *info,
@@ -258,9 +258,9 @@ EXPORT_SYMBOL_GPL(of_fpga_bridge_get_to_list);
* @info: fpga image specific information
* @bridge_list: list of FPGA bridges
*
- * Get an exclusive reference to the bridge and and it to the list.
+ * Get an exclusive reference to the bridge and it to the list.
*
- * Return 0 for success, error code from fpga_bridge_get() othewise.
+ * Return 0 for success, error code from fpga_bridge_get() otherwise.
*/
int fpga_bridge_get_to_list(struct device *dev,
struct fpga_image_info *info,
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
index ecb4c3c795fa..aa30889e2320 100644
--- a/drivers/fpga/fpga-mgr.c
+++ b/drivers/fpga/fpga-mgr.c
@@ -25,6 +25,72 @@ struct fpga_mgr_devres {
struct fpga_manager *mgr;
};
+static inline void fpga_mgr_fpga_remove(struct fpga_manager *mgr)
+{
+ if (mgr->mops->fpga_remove)
+ mgr->mops->fpga_remove(mgr);
+}
+
+static inline enum fpga_mgr_states fpga_mgr_state(struct fpga_manager *mgr)
+{
+ if (mgr->mops->state)
+ return mgr->mops->state(mgr);
+ return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static inline u64 fpga_mgr_status(struct fpga_manager *mgr)
+{
+ if (mgr->mops->status)
+ return mgr->mops->status(mgr);
+ return 0;
+}
+
+static inline int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count)
+{
+ if (mgr->mops->write)
+ return mgr->mops->write(mgr, buf, count);
+ return -EOPNOTSUPP;
+}
+
+/*
+ * After all the FPGA image has been written, do the device specific steps to
+ * finish and set the FPGA into operating mode.
+ */
+static inline int fpga_mgr_write_complete(struct fpga_manager *mgr,
+ struct fpga_image_info *info)
+{
+ int ret = 0;
+
+ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
+ if (mgr->mops->write_complete)
+ ret = mgr->mops->write_complete(mgr, info);
+ if (ret) {
+ dev_err(&mgr->dev, "Error after writing image data to FPGA\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+ return ret;
+ }
+ mgr->state = FPGA_MGR_STATE_OPERATING;
+
+ return 0;
+}
+
+static inline int fpga_mgr_write_init(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+ const char *buf, size_t count)
+{
+ if (mgr->mops->write_init)
+ return mgr->mops->write_init(mgr, info, buf, count);
+ return 0;
+}
+
+static inline int fpga_mgr_write_sg(struct fpga_manager *mgr,
+ struct sg_table *sgt)
+{
+ if (mgr->mops->write_sg)
+ return mgr->mops->write_sg(mgr, sgt);
+ return -EOPNOTSUPP;
+}
+
/**
* fpga_image_info_alloc - Allocate an FPGA image info struct
* @dev: owning device
@@ -83,9 +149,9 @@ static int fpga_mgr_write_init_buf(struct fpga_manager *mgr,
mgr->state = FPGA_MGR_STATE_WRITE_INIT;
if (!mgr->mops->initial_header_size)
- ret = mgr->mops->write_init(mgr, info, NULL, 0);
+ ret = fpga_mgr_write_init(mgr, info, NULL, 0);
else
- ret = mgr->mops->write_init(
+ ret = fpga_mgr_write_init(
mgr, info, buf, min(mgr->mops->initial_header_size, count));
if (ret) {
@@ -137,27 +203,6 @@ static int fpga_mgr_write_init_sg(struct fpga_manager *mgr,
return ret;
}
-/*
- * After all the FPGA image has been written, do the device specific steps to
- * finish and set the FPGA into operating mode.
- */
-static int fpga_mgr_write_complete(struct fpga_manager *mgr,
- struct fpga_image_info *info)
-{
- int ret;
-
- mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
- ret = mgr->mops->write_complete(mgr, info);
- if (ret) {
- dev_err(&mgr->dev, "Error after writing image data to FPGA\n");
- mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
- return ret;
- }
- mgr->state = FPGA_MGR_STATE_OPERATING;
-
- return 0;
-}
-
/**
* fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list
* @mgr: fpga manager
@@ -188,13 +233,13 @@ static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr,
/* Write the FPGA image to the FPGA. */
mgr->state = FPGA_MGR_STATE_WRITE;
if (mgr->mops->write_sg) {
- ret = mgr->mops->write_sg(mgr, sgt);
+ ret = fpga_mgr_write_sg(mgr, sgt);
} else {
struct sg_mapping_iter miter;
sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
while (sg_miter_next(&miter)) {
- ret = mgr->mops->write(mgr, miter.addr, miter.length);
+ ret = fpga_mgr_write(mgr, miter.addr, miter.length);
if (ret)
break;
}
@@ -224,7 +269,7 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr,
* Write the FPGA image to the FPGA.
*/
mgr->state = FPGA_MGR_STATE_WRITE;
- ret = mgr->mops->write(mgr, buf, count);
+ ret = fpga_mgr_write(mgr, buf, count);
if (ret) {
dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
mgr->state = FPGA_MGR_STATE_WRITE_ERR;
@@ -417,10 +462,7 @@ static ssize_t status_show(struct device *dev,
u64 status;
int len = 0;
- if (!mgr->mops->status)
- return -ENOENT;
-
- status = mgr->mops->status(mgr);
+ status = fpga_mgr_status(mgr);
if (status & FPGA_MGR_STATUS_OPERATION_ERR)
len += sprintf(buf + len, "reconfig operation error\n");
@@ -568,9 +610,7 @@ struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name,
struct fpga_manager *mgr;
int id, ret;
- if (!mops || !mops->write_complete || !mops->state ||
- !mops->write_init || (!mops->write && !mops->write_sg) ||
- (mops->write && mops->write_sg)) {
+ if (!mops) {
dev_err(parent, "Attempt to register without fpga_manager_ops\n");
return NULL;
}
@@ -688,7 +728,7 @@ int fpga_mgr_register(struct fpga_manager *mgr)
* from device. FPGA may be in reset mode or may have been programmed
* by bootloader or EEPROM.
*/
- mgr->state = mgr->mops->state(mgr);
+ mgr->state = fpga_mgr_state(mgr);
ret = device_add(&mgr->dev);
if (ret)
@@ -719,8 +759,7 @@ void fpga_mgr_unregister(struct fpga_manager *mgr)
* If the low level driver provides a method for putting fpga into
* a desired state upon unregister, do it.
*/
- if (mgr->mops->fpga_remove)
- mgr->mops->fpga_remove(mgr);
+ fpga_mgr_fpga_remove(mgr);
device_unregister(&mgr->dev);
}
diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c
index a2cea500f7cc..047fd7f23706 100644
--- a/drivers/fpga/stratix10-soc.c
+++ b/drivers/fpga/stratix10-soc.c
@@ -388,13 +388,7 @@ static int s10_ops_write_complete(struct fpga_manager *mgr,
return ret;
}
-static enum fpga_mgr_states s10_ops_state(struct fpga_manager *mgr)
-{
- return FPGA_MGR_STATE_UNKNOWN;
-}
-
static const struct fpga_manager_ops s10_ops = {
- .state = s10_ops_state,
.write_init = s10_ops_write_init,
.write = s10_ops_write,
.write_complete = s10_ops_write_complete,
diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c
index 101f016c6ed8..167abb0b08d4 100644
--- a/drivers/fpga/ts73xx-fpga.c
+++ b/drivers/fpga/ts73xx-fpga.c
@@ -32,11 +32,6 @@ struct ts73xx_fpga_priv {
struct device *dev;
};
-static enum fpga_mgr_states ts73xx_fpga_state(struct fpga_manager *mgr)
-{
- return FPGA_MGR_STATE_UNKNOWN;
-}
-
static int ts73xx_fpga_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count)
@@ -98,7 +93,6 @@ static int ts73xx_fpga_write_complete(struct fpga_manager *mgr,
}
static const struct fpga_manager_ops ts73xx_fpga_ops = {
- .state = ts73xx_fpga_state,
.write_init = ts73xx_fpga_write_init,
.write = ts73xx_fpga_write,
.write_complete = ts73xx_fpga_write_complete,
diff --git a/drivers/fpga/versal-fpga.c b/drivers/fpga/versal-fpga.c
new file mode 100644
index 000000000000..5b0dda304bd2
--- /dev/null
+++ b/drivers/fpga/versal-fpga.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2021 Xilinx, Inc.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/string.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+static int versal_fpga_ops_write_init(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+ const char *buf, size_t size)
+{
+ return 0;
+}
+
+static int versal_fpga_ops_write(struct fpga_manager *mgr,
+ const char *buf, size_t size)
+{
+ dma_addr_t dma_addr = 0;
+ char *kbuf;
+ int ret;
+
+ kbuf = dma_alloc_coherent(mgr->dev.parent, size, &dma_addr, GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+
+ memcpy(kbuf, buf, size);
+ ret = zynqmp_pm_load_pdi(PDI_SRC_DDR, dma_addr);
+ dma_free_coherent(mgr->dev.parent, size, kbuf, dma_addr);
+
+ return ret;
+}
+
+static const struct fpga_manager_ops versal_fpga_ops = {
+ .write_init = versal_fpga_ops_write_init,
+ .write = versal_fpga_ops_write,
+};
+
+static int versal_fpga_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct fpga_manager *mgr;
+ int ret;
+
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret < 0) {
+ dev_err(dev, "no usable DMA configuration\n");
+ return ret;
+ }
+
+ mgr = devm_fpga_mgr_create(dev, "Xilinx Versal FPGA Manager",
+ &versal_fpga_ops, NULL);
+ if (!mgr)
+ return -ENOMEM;
+
+ return devm_fpga_mgr_register(dev, mgr);
+}
+
+static const struct of_device_id versal_fpga_of_match[] = {
+ { .compatible = "xlnx,versal-fpga", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, versal_fpga_of_match);
+
+static struct platform_driver versal_fpga_driver = {
+ .probe = versal_fpga_probe,
+ .driver = {
+ .name = "versal_fpga_manager",
+ .of_match_table = of_match_ptr(versal_fpga_of_match),
+ },
+};
+module_platform_driver(versal_fpga_driver);
+
+MODULE_AUTHOR("Nava kishore Manne <nava.manne@xilinx.com>");
+MODULE_AUTHOR("Appana Durga Kedareswara rao <appanad.durga.rao@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx Versal FPGA Manager");
+MODULE_LICENSE("GPL");
diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c
index ea2bde6e5bc4..e986ed47c4ed 100644
--- a/drivers/fpga/xilinx-pr-decoupler.c
+++ b/drivers/fpga/xilinx-pr-decoupler.c
@@ -81,6 +81,7 @@ static const struct fpga_bridge_ops xlnx_pr_decoupler_br_ops = {
.enable_show = xlnx_pr_decoupler_enable_show,
};
+#ifdef CONFIG_OF
static const struct xlnx_config_data decoupler_config = {
.name = "Xilinx PR Decoupler",
};
@@ -99,6 +100,7 @@ static const struct of_device_id xlnx_pr_decoupler_of_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match);
+#endif
static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
{
diff --git a/drivers/fpga/xilinx-spi.c b/drivers/fpga/xilinx-spi.c
index fee4d0abf6bf..b6bcf1d9233d 100644
--- a/drivers/fpga/xilinx-spi.c
+++ b/drivers/fpga/xilinx-spi.c
@@ -256,11 +256,13 @@ static int xilinx_spi_probe(struct spi_device *spi)
return devm_fpga_mgr_register(&spi->dev, mgr);
}
+#ifdef CONFIG_OF
static const struct of_device_id xlnx_spi_of_match[] = {
{ .compatible = "xlnx,fpga-slave-serial", },
{}
};
MODULE_DEVICE_TABLE(of, xlnx_spi_of_match);
+#endif
static struct spi_driver xilinx_slave_spi_driver = {
.driver = {
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 07fa8d9ec675..9b75bd4f93d8 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -192,7 +192,7 @@ static void zynq_step_dma(struct zynq_fpga_priv *priv)
/* Once the first transfer is queued we can turn on the ISR, future
* calls to zynq_step_dma will happen from the ISR context. The
- * dma_lock spinlock guarentees this handover is done coherently, the
+ * dma_lock spinlock guarantees this handover is done coherently, the
* ISR enable is put at the end to avoid another CPU spinning in the
* ISR on this lock.
*/
@@ -267,7 +267,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
if (!(ctrl & CTRL_SEC_EN_MASK)) {
dev_err(&mgr->dev,
- "System not secure, can't use crypted bitstreams\n");
+ "System not secure, can't use encrypted bitstreams\n");
err = -EINVAL;
goto out_err;
}
@@ -344,7 +344,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
/* set configuration register with following options:
* - enable PCAP interface
- * - set throughput for maximum speed (if bistream not crypted)
+ * - set throughput for maximum speed (if bistream not encrypted)
* - set CPU in user mode
*/
ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
diff --git a/drivers/fpga/zynqmp-fpga.c b/drivers/fpga/zynqmp-fpga.c
index 125743c9797f..7d3d5650c322 100644
--- a/drivers/fpga/zynqmp-fpga.c
+++ b/drivers/fpga/zynqmp-fpga.c
@@ -66,12 +66,6 @@ static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
return ret;
}
-static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr,
- struct fpga_image_info *info)
-{
- return 0;
-}
-
static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
{
u32 status = 0;
@@ -87,7 +81,6 @@ static const struct fpga_manager_ops zynqmp_fpga_ops = {
.state = zynqmp_fpga_ops_state,
.write_init = zynqmp_fpga_ops_write_init,
.write = zynqmp_fpga_ops_write,
- .write_complete = zynqmp_fpga_ops_write_complete,
};
static int zynqmp_fpga_probe(struct platform_device *pdev)
@@ -110,12 +103,13 @@ static int zynqmp_fpga_probe(struct platform_device *pdev)
return devm_fpga_mgr_register(dev, mgr);
}
+#ifdef CONFIG_OF
static const struct of_device_id zynqmp_fpga_of_match[] = {
{ .compatible = "xlnx,zynqmp-pcap-fpga", },
{},
};
-
MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match);
+#endif
static struct platform_driver zynqmp_fpga_driver = {
.probe = zynqmp_fpga_probe,
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 81abd890b364..fae5141251e5 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1018,12 +1018,6 @@ config GPIO_MAX732X_IRQ
Say yes here to enable the max732x to be used as an interrupt
controller. It requires the driver to be built in the kernel.
-config GPIO_MC9S08DZ60
- bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
- depends on I2C=y && MACH_MX35_3DS
- help
- Select this to enable the MC9S08DZ60 GPIO driver
-
config GPIO_PCA953X
tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"
select REGMAP_I2C
@@ -1677,6 +1671,15 @@ config GPIO_MOCKUP
tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
it.
+config GPIO_VIRTIO
+ tristate "VirtIO GPIO support"
+ depends on VIRTIO
+ help
+ Say Y here to enable guest support for virtio-based GPIO controllers.
+
+ These virtual GPIOs can be routed to real GPIOs or attached to
+ simulators on the host (like QEMU).
+
endmenu
endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 5243e2d1c207..fbcda637d5e1 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -92,7 +92,6 @@ obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o
obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o
obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
-obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o
obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
@@ -166,6 +165,7 @@ obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
+obj-$(CONFIG_GPIO_VIRTIO) += gpio-virtio.o
obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
index a99ece15db95..10f303d15225 100644
--- a/drivers/gpio/gpio-aspeed-sgpio.c
+++ b/drivers/gpio/gpio-aspeed-sgpio.c
@@ -17,37 +17,30 @@
#include <linux/spinlock.h>
#include <linux/string.h>
-/*
- * MAX_NR_HW_GPIO represents the number of actual hardware-supported GPIOs (ie,
- * slots within the clocked serial GPIO data). Since each HW GPIO is both an
- * input and an output, we provide MAX_NR_HW_GPIO * 2 lines on our gpiochip
- * device.
- *
- * We use SGPIO_OUTPUT_OFFSET to define the split between the inputs and
- * outputs; the inputs start at line 0, the outputs start at OUTPUT_OFFSET.
- */
-#define MAX_NR_HW_SGPIO 80
-#define SGPIO_OUTPUT_OFFSET MAX_NR_HW_SGPIO
-
#define ASPEED_SGPIO_CTRL 0x54
-#define ASPEED_SGPIO_PINS_MASK GENMASK(9, 6)
#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16)
#define ASPEED_SGPIO_ENABLE BIT(0)
+#define ASPEED_SGPIO_PINS_SHIFT 6
+
+struct aspeed_sgpio_pdata {
+ const u32 pin_mask;
+};
struct aspeed_sgpio {
struct gpio_chip chip;
+ struct irq_chip intc;
struct clk *pclk;
spinlock_t lock;
void __iomem *base;
int irq;
- int n_sgpio;
};
struct aspeed_sgpio_bank {
- uint16_t val_regs;
- uint16_t rdata_reg;
- uint16_t irq_regs;
+ u16 val_regs;
+ u16 rdata_reg;
+ u16 irq_regs;
+ u16 tolerance_regs;
const char names[4][3];
};
@@ -63,19 +56,29 @@ static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = {
.val_regs = 0x0000,
.rdata_reg = 0x0070,
.irq_regs = 0x0004,
+ .tolerance_regs = 0x0018,
.names = { "A", "B", "C", "D" },
},
{
.val_regs = 0x001C,
.rdata_reg = 0x0074,
.irq_regs = 0x0020,
+ .tolerance_regs = 0x0034,
.names = { "E", "F", "G", "H" },
},
{
.val_regs = 0x0038,
.rdata_reg = 0x0078,
.irq_regs = 0x003C,
- .names = { "I", "J" },
+ .tolerance_regs = 0x0050,
+ .names = { "I", "J", "K", "L" },
+ },
+ {
+ .val_regs = 0x0090,
+ .rdata_reg = 0x007C,
+ .irq_regs = 0x0094,
+ .tolerance_regs = 0x00A8,
+ .names = { "M", "N", "O", "P" },
},
};
@@ -87,6 +90,7 @@ enum aspeed_sgpio_reg {
reg_irq_type1,
reg_irq_type2,
reg_irq_status,
+ reg_tolerance,
};
#define GPIO_VAL_VALUE 0x00
@@ -115,15 +119,17 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2;
case reg_irq_status:
return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
+ case reg_tolerance:
+ return gpio->base + bank->tolerance_regs;
default:
/* acturally if code runs to here, it's an error case */
BUG();
}
}
-#define GPIO_BANK(x) ((x % SGPIO_OUTPUT_OFFSET) >> 5)
-#define GPIO_OFFSET(x) ((x % SGPIO_OUTPUT_OFFSET) & 0x1f)
-#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
+#define GPIO_BANK(x) ((x) >> 6)
+#define GPIO_OFFSET(x) ((x) & GENMASK(5, 0))
+#define GPIO_BIT(x) BIT(GPIO_OFFSET(x) >> 1)
static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
{
@@ -138,39 +144,25 @@ static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc,
unsigned long *valid_mask, unsigned int ngpios)
{
- struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
- int n = sgpio->n_sgpio;
- int c = SGPIO_OUTPUT_OFFSET - n;
-
- WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
-
- /* input GPIOs in the lower range */
- bitmap_set(valid_mask, 0, n);
- bitmap_clear(valid_mask, n, c);
-
- /* output GPIOS above SGPIO_OUTPUT_OFFSET */
- bitmap_set(valid_mask, SGPIO_OUTPUT_OFFSET, n);
- bitmap_clear(valid_mask, SGPIO_OUTPUT_OFFSET + n, c);
-
+ bitmap_set(valid_mask, 0, ngpios);
return 0;
}
static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
unsigned long *valid_mask, unsigned int ngpios)
{
- struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
- int n = sgpio->n_sgpio;
+ unsigned int i;
- WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
-
- /* input GPIOs in the lower range */
- bitmap_set(valid_mask, 0, n);
- bitmap_clear(valid_mask, n, ngpios - n);
+ /* input GPIOs are even bits */
+ for (i = 0; i < ngpios; i++) {
+ if (i % 2)
+ clear_bit(i, valid_mask);
+ }
}
static bool aspeed_sgpio_is_input(unsigned int offset)
{
- return offset < SGPIO_OUTPUT_OFFSET;
+ return !(offset % 2);
}
static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
@@ -409,14 +401,6 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(ic, desc);
}
-static struct irq_chip aspeed_sgpio_irqchip = {
- .name = "aspeed-sgpio",
- .irq_ack = aspeed_sgpio_irq_ack,
- .irq_mask = aspeed_sgpio_irq_mask,
- .irq_unmask = aspeed_sgpio_irq_unmask,
- .irq_set_type = aspeed_sgpio_set_type,
-};
-
static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
struct platform_device *pdev)
{
@@ -439,8 +423,14 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status));
}
+ gpio->intc.name = dev_name(&pdev->dev);
+ gpio->intc.irq_ack = aspeed_sgpio_irq_ack;
+ gpio->intc.irq_mask = aspeed_sgpio_irq_mask;
+ gpio->intc.irq_unmask = aspeed_sgpio_irq_unmask;
+ gpio->intc.irq_set_type = aspeed_sgpio_set_type;
+
irq = &gpio->chip.irq;
- irq->chip = &aspeed_sgpio_irqchip;
+ irq->chip = &gpio->intc;
irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask;
irq->handler = handle_bad_irq;
irq->default_type = IRQ_TYPE_NONE;
@@ -463,9 +453,56 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
return 0;
}
+static const struct aspeed_sgpio_pdata ast2400_sgpio_pdata = {
+ .pin_mask = GENMASK(9, 6),
+};
+
+static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
+ unsigned int offset, bool enable)
+{
+ struct aspeed_sgpio *gpio = gpiochip_get_data(chip);
+ unsigned long flags;
+ void __iomem *reg;
+ u32 val;
+
+ reg = bank_reg(gpio, to_bank(offset), reg_tolerance);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ val = readl(reg);
+
+ if (enable)
+ val |= GPIO_BIT(offset);
+ else
+ val &= ~GPIO_BIT(offset);
+
+ writel(val, reg);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static int aspeed_sgpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
+{
+ unsigned long param = pinconf_to_config_param(config);
+ u32 arg = pinconf_to_config_argument(config);
+
+ if (param == PIN_CONFIG_PERSIST_STATE)
+ return aspeed_sgpio_reset_tolerance(chip, offset, arg);
+
+ return -ENOTSUPP;
+}
+
+static const struct aspeed_sgpio_pdata ast2600_sgpiom_pdata = {
+ .pin_mask = GENMASK(10, 6),
+};
+
static const struct of_device_id aspeed_sgpio_of_table[] = {
- { .compatible = "aspeed,ast2400-sgpio" },
- { .compatible = "aspeed,ast2500-sgpio" },
+ { .compatible = "aspeed,ast2400-sgpio", .data = &ast2400_sgpio_pdata, },
+ { .compatible = "aspeed,ast2500-sgpio", .data = &ast2400_sgpio_pdata, },
+ { .compatible = "aspeed,ast2600-sgpiom", .data = &ast2600_sgpiom_pdata, },
{}
};
@@ -473,10 +510,11 @@ MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table);
static int __init aspeed_sgpio_probe(struct platform_device *pdev)
{
+ u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask;
+ const struct aspeed_sgpio_pdata *pdata;
struct aspeed_sgpio *gpio;
- u32 nr_gpios, sgpio_freq, sgpio_clk_div;
- int rc;
unsigned long apb_freq;
+ int rc;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
@@ -486,18 +524,23 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio->base))
return PTR_ERR(gpio->base);
- rc = of_property_read_u32(pdev->dev.of_node, "ngpios", &nr_gpios);
+ pdata = device_get_match_data(&pdev->dev);
+ if (!pdata)
+ return -EINVAL;
+
+ pin_mask = pdata->pin_mask;
+
+ rc = device_property_read_u32(&pdev->dev, "ngpios", &nr_gpios);
if (rc < 0) {
dev_err(&pdev->dev, "Could not read ngpios property\n");
return -EINVAL;
- } else if (nr_gpios > MAX_NR_HW_SGPIO) {
- dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n",
- MAX_NR_HW_SGPIO, nr_gpios);
+ } else if (nr_gpios % 8) {
+ dev_err(&pdev->dev, "Number of GPIOs not multiple of 8: %d\n",
+ nr_gpios);
return -EINVAL;
}
- gpio->n_sgpio = nr_gpios;
- rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq);
+ rc = device_property_read_u32(&pdev->dev, "bus-frequency", &sgpio_freq);
if (rc < 0) {
dev_err(&pdev->dev, "Could not read bus-frequency property\n");
return -EINVAL;
@@ -528,15 +571,14 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
if (sgpio_clk_div > (1 << 16) - 1)
return -EINVAL;
- iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) |
- FIELD_PREP(ASPEED_SGPIO_PINS_MASK, (nr_gpios / 8)) |
- ASPEED_SGPIO_ENABLE,
- gpio->base + ASPEED_SGPIO_CTRL);
+ gpio_cnt_regval = ((nr_gpios / 8) << ASPEED_SGPIO_PINS_SHIFT) & pin_mask;
+ iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval |
+ ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL);
spin_lock_init(&gpio->lock);
gpio->chip.parent = &pdev->dev;
- gpio->chip.ngpio = MAX_NR_HW_SGPIO * 2;
+ gpio->chip.ngpio = nr_gpios * 2;
gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask;
gpio->chip.direction_input = aspeed_sgpio_dir_in;
gpio->chip.direction_output = aspeed_sgpio_dir_out;
@@ -545,7 +587,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
gpio->chip.free = NULL;
gpio->chip.get = aspeed_sgpio_get;
gpio->chip.set = aspeed_sgpio_set;
- gpio->chip.set_config = NULL;
+ gpio->chip.set_config = aspeed_sgpio_set_config;
gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.base = -1;
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index 74b7c91c3d1a..895a79936248 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -602,49 +602,6 @@ static const struct dev_pm_ops brcmstb_gpio_pm_ops = {
.resume_noirq = brcmstb_gpio_resume,
};
-static void brcmstb_gpio_set_names(struct device *dev,
- struct brcmstb_gpio_bank *bank)
-{
- struct device_node *np = dev->of_node;
- const char **names;
- int nstrings, base;
- unsigned int i;
-
- base = bank->id * MAX_GPIO_PER_BANK;
-
- nstrings = of_property_count_strings(np, "gpio-line-names");
- if (nstrings <= base)
- /* Line names not present */
- return;
-
- names = devm_kcalloc(dev, MAX_GPIO_PER_BANK, sizeof(*names),
- GFP_KERNEL);
- if (!names)
- return;
-
- /*
- * Make sure to not index beyond the end of the number of descriptors
- * of the GPIO device.
- */
- for (i = 0; i < bank->width; i++) {
- const char *name;
- int ret;
-
- ret = of_property_read_string_index(np, "gpio-line-names",
- base + i, &name);
- if (ret) {
- if (ret != -ENODATA)
- dev_err(dev, "unable to name line %d: %d\n",
- base + i, ret);
- break;
- }
- if (*name)
- names[i] = name;
- }
-
- bank->gc.names = names;
-}
-
static int brcmstb_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -758,6 +715,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
gc->of_xlate = brcmstb_gpio_of_xlate;
/* not all ngpio lines are valid, will use bank width later */
gc->ngpio = MAX_GPIO_PER_BANK;
+ gc->offset = bank->id * MAX_GPIO_PER_BANK;
if (priv->parent_irq > 0)
gc->to_irq = brcmstb_gpio_to_irq;
@@ -768,7 +726,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank);
gc->write_reg(reg_base + GIO_MASK(bank->id), 0);
- brcmstb_gpio_set_names(dev, bank);
err = gpiochip_add_data(gc, bank);
if (err) {
dev_err(dev, "Could not add gpiochip for bank %d\n",
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 3eb13d6d31ef..f98fa33e1679 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -16,7 +16,6 @@
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/platform_data/gpio-dwapb.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/reset.h>
@@ -48,6 +47,7 @@
#define DWAPB_DRIVER_NAME "gpio-dwapb"
#define DWAPB_MAX_PORTS 4
+#define DWAPB_MAX_GPIOS 32
#define GPIO_EXT_PORT_STRIDE 0x04 /* register stride 32 bits */
#define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */
@@ -65,6 +65,19 @@
struct dwapb_gpio;
+struct dwapb_port_property {
+ struct fwnode_handle *fwnode;
+ unsigned int idx;
+ unsigned int ngpio;
+ unsigned int gpio_base;
+ int irq[DWAPB_MAX_GPIOS];
+};
+
+struct dwapb_platform_data {
+ struct dwapb_port_property *properties;
+ unsigned int nports;
+};
+
#ifdef CONFIG_PM_SLEEP
/* Store GPIO context across system-wide suspend/resume transitions */
struct dwapb_context {
@@ -436,21 +449,17 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
pirq->irqchip.irq_set_wake = dwapb_irq_set_wake;
#endif
- if (!pp->irq_shared) {
- girq->num_parents = pirq->nr_irqs;
- girq->parents = pirq->irq;
- girq->parent_handler_data = gpio;
- girq->parent_handler = dwapb_irq_handler;
- } else {
- /* This will let us handle the parent IRQ in the driver */
+ /*
+ * Intel ACPI-based platforms mostly have the DesignWare APB GPIO
+ * IRQ lane shared between several devices. In that case the parental
+ * IRQ has to be handled in the shared way so to be properly delivered
+ * to all the connected devices.
+ */
+ if (has_acpi_companion(gpio->dev)) {
girq->num_parents = 0;
girq->parents = NULL;
girq->parent_handler = NULL;
- /*
- * Request a shared IRQ since where MFD would have devices
- * using the same irq pin
- */
err = devm_request_irq(gpio->dev, pp->irq[0],
dwapb_irq_handler_mfd,
IRQF_SHARED, DWAPB_DRIVER_NAME, gpio);
@@ -458,6 +467,11 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
dev_err(gpio->dev, "error requesting IRQ\n");
goto err_kfree_pirq;
}
+ } else {
+ girq->num_parents = pirq->nr_irqs;
+ girq->parents = pirq->irq;
+ girq->parent_handler_data = gpio;
+ girq->parent_handler = dwapb_irq_handler;
}
girq->chip = &pirq->irqchip;
@@ -581,9 +595,12 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
pp->ngpio = DWAPB_MAX_GPIOS;
}
- pp->irq_shared = false;
pp->gpio_base = -1;
+ /* For internal use only, new platforms mustn't exercise this */
+ if (is_software_node(fwnode))
+ fwnode_property_read_u32(fwnode, "gpio-base", &pp->gpio_base);
+
/*
* Only port A can provide interrupts in all configurations of
* the IP.
@@ -670,17 +687,12 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
unsigned int i;
struct dwapb_gpio *gpio;
int err;
+ struct dwapb_platform_data *pdata;
struct device *dev = &pdev->dev;
- struct dwapb_platform_data *pdata = dev_get_platdata(dev);
-
- if (!pdata) {
- pdata = dwapb_gpio_get_pdata(dev);
- if (IS_ERR(pdata))
- return PTR_ERR(pdata);
- }
- if (!pdata->nports)
- return -ENODEV;
+ pdata = dwapb_gpio_get_pdata(dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c
deleted file mode 100644
index a9f17cebd5ed..000000000000
--- a/drivers/gpio/gpio-mc9s08dz60.c
+++ /dev/null
@@ -1,112 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Author: Wu Guoxing <b39297@freescale.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/gpio/driver.h>
-
-#define GPIO_GROUP_NUM 2
-#define GPIO_NUM_PER_GROUP 8
-#define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP)
-
-struct mc9s08dz60 {
- struct i2c_client *client;
- struct gpio_chip chip;
-};
-
-static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit)
-{
- *reg = 0x20 + offset / GPIO_NUM_PER_GROUP;
- *bit = offset % GPIO_NUM_PER_GROUP;
-}
-
-static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset)
-{
- u8 reg, bit;
- s32 value;
- struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
-
- mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
- value = i2c_smbus_read_byte_data(mc9s->client, reg);
-
- return (value >= 0) ? (value >> bit) & 0x1 : 0;
-}
-
-static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val)
-{
- u8 reg, bit;
- s32 value;
-
- mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
- value = i2c_smbus_read_byte_data(mc9s->client, reg);
- if (value >= 0) {
- if (val)
- value |= 1 << bit;
- else
- value &= ~(1 << bit);
-
- return i2c_smbus_write_byte_data(mc9s->client, reg, value);
- } else
- return value;
-
-}
-
-
-static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val)
-{
- struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
-
- mc9s08dz60_set(mc9s, offset, val);
-}
-
-static int mc9s08dz60_direction_output(struct gpio_chip *gc,
- unsigned offset, int val)
-{
- struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
-
- return mc9s08dz60_set(mc9s, offset, val);
-}
-
-static int mc9s08dz60_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct mc9s08dz60 *mc9s;
-
- mc9s = devm_kzalloc(&client->dev, sizeof(*mc9s), GFP_KERNEL);
- if (!mc9s)
- return -ENOMEM;
-
- mc9s->chip.label = client->name;
- mc9s->chip.base = -1;
- mc9s->chip.parent = &client->dev;
- mc9s->chip.owner = THIS_MODULE;
- mc9s->chip.ngpio = GPIO_NUM;
- mc9s->chip.can_sleep = true;
- mc9s->chip.get = mc9s08dz60_get_value;
- mc9s->chip.set = mc9s08dz60_set_value;
- mc9s->chip.direction_output = mc9s08dz60_direction_output;
- mc9s->client = client;
- i2c_set_clientdata(client, mc9s);
-
- return devm_gpiochip_add_data(&client->dev, &mc9s->chip, mc9s);
-}
-
-static const struct i2c_device_id mc9s08dz60_id[] = {
- {"mc9s08dz60", 0},
- {},
-};
-
-static struct i2c_driver mc9s08dz60_i2c_driver = {
- .driver = {
- .name = "mc9s08dz60",
- },
- .probe = mc9s08dz60_probe,
- .id_table = mc9s08dz60_id,
-};
-builtin_i2c_driver(mc9s08dz60_i2c_driver);
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 53d4abefa6ff..efa9acdc320a 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -155,11 +155,10 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
return 0;
}
-#ifdef CONFIG_PM
/*
* Save register configuration and disable interrupts.
*/
-static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
+static void __maybe_unused ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
{
int i;
@@ -185,7 +184,7 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
/*
* This function restores the register configuration of the GPIO device.
*/
-static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
+static void __maybe_unused ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
{
int i;
@@ -207,7 +206,6 @@ static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
&chip->reg->ioh_sel_reg[i]);
}
}
-#endif
static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
{
@@ -522,47 +520,23 @@ static void ioh_gpio_remove(struct pci_dev *pdev)
kfree(chip);
}
-#ifdef CONFIG_PM
-static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
+static int __maybe_unused ioh_gpio_suspend(struct device *dev)
{
- s32 ret;
- struct ioh_gpio *chip = pci_get_drvdata(pdev);
+ struct ioh_gpio *chip = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
ioh_gpio_save_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags);
- ret = pci_save_state(pdev);
- if (ret) {
- dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
- return ret;
- }
- pci_disable_device(pdev);
- pci_set_power_state(pdev, PCI_D0);
- ret = pci_enable_wake(pdev, PCI_D0, 1);
- if (ret)
- dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
-
return 0;
}
-static int ioh_gpio_resume(struct pci_dev *pdev)
+static int __maybe_unused ioh_gpio_resume(struct device *dev)
{
- s32 ret;
- struct ioh_gpio *chip = pci_get_drvdata(pdev);
+ struct ioh_gpio *chip = dev_get_drvdata(dev);
unsigned long flags;
- ret = pci_enable_wake(pdev, PCI_D0, 0);
-
- pci_set_power_state(pdev, PCI_D0);
- ret = pci_enable_device(pdev);
- if (ret) {
- dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
- return ret;
- }
- pci_restore_state(pdev);
-
spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->srst);
iowrite32(0x00, &chip->reg->srst);
@@ -571,10 +545,8 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
return 0;
}
-#else
-#define ioh_gpio_suspend NULL
-#define ioh_gpio_resume NULL
-#endif
+
+static SIMPLE_DEV_PM_OPS(ioh_gpio_pm_ops, ioh_gpio_suspend, ioh_gpio_resume);
static const struct pci_device_id ioh_gpio_pcidev_id[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
@@ -587,8 +559,9 @@ static struct pci_driver ioh_gpio_driver = {
.id_table = ioh_gpio_pcidev_id,
.probe = ioh_gpio_probe,
.remove = ioh_gpio_remove,
- .suspend = ioh_gpio_suspend,
- .resume = ioh_gpio_resume
+ .driver = {
+ .pm = &ioh_gpio_pm_ops,
+ },
};
module_pci_driver(ioh_gpio_driver);
diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c
index befa5e109943..177d03ef4529 100644
--- a/drivers/gpio/gpio-mlxbf2.c
+++ b/drivers/gpio/gpio-mlxbf2.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/device.h>
@@ -8,6 +7,7 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
@@ -47,12 +47,10 @@
#define YU_GPIO_MODE0_SET 0x54
#define YU_GPIO_MODE0_CLEAR 0x58
-#ifdef CONFIG_PM
struct mlxbf2_gpio_context_save_regs {
u32 gpio_mode0;
u32 gpio_mode1;
};
-#endif
/* BlueField-2 gpio block context structure. */
struct mlxbf2_gpio_context {
@@ -61,9 +59,7 @@ struct mlxbf2_gpio_context {
/* YU GPIO blocks address */
void __iomem *gpio_io;
-#ifdef CONFIG_PM
struct mlxbf2_gpio_context_save_regs *csave_regs;
-#endif
};
/* BlueField-2 gpio shared structure. */
@@ -73,11 +69,8 @@ struct mlxbf2_gpio_param {
struct mutex *lock;
};
-static struct resource yu_arm_gpio_lock_res = {
- .start = YU_ARM_GPIO_LOCK_ADDR,
- .end = YU_ARM_GPIO_LOCK_ADDR + YU_ARM_GPIO_LOCK_SIZE - 1,
- .name = "YU_ARM_GPIO_LOCK",
-};
+static struct resource yu_arm_gpio_lock_res =
+ DEFINE_RES_MEM_NAMED(YU_ARM_GPIO_LOCK_ADDR, YU_ARM_GPIO_LOCK_SIZE, "YU_ARM_GPIO_LOCK");
static DEFINE_MUTEX(yu_arm_gpio_lock_mutex);
@@ -232,7 +225,6 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
struct mlxbf2_gpio_context *gs;
struct device *dev = &pdev->dev;
struct gpio_chip *gc;
- struct resource *res;
unsigned int npins;
int ret;
@@ -241,13 +233,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
/* YU GPIO block address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- gs->gpio_io = devm_ioremap(dev, res->start, resource_size(res));
- if (!gs->gpio_io)
- return -ENOMEM;
+ gs->gpio_io = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(gs->gpio_io))
+ return PTR_ERR(gs->gpio_io);
ret = mlxbf2_gpio_get_lock_res(pdev);
if (ret) {
@@ -284,11 +272,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int mlxbf2_gpio_suspend(struct platform_device *pdev,
- pm_message_t state)
+static int __maybe_unused mlxbf2_gpio_suspend(struct device *dev)
{
- struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev);
+ struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev);
gs->csave_regs->gpio_mode0 = readl(gs->gpio_io +
YU_GPIO_MODE0);
@@ -298,9 +284,9 @@ static int mlxbf2_gpio_suspend(struct platform_device *pdev,
return 0;
}
-static int mlxbf2_gpio_resume(struct platform_device *pdev)
+static int __maybe_unused mlxbf2_gpio_resume(struct device *dev)
{
- struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev);
+ struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev);
writel(gs->csave_regs->gpio_mode0, gs->gpio_io +
YU_GPIO_MODE0);
@@ -309,7 +295,7 @@ static int mlxbf2_gpio_resume(struct platform_device *pdev)
return 0;
}
-#endif
+static SIMPLE_DEV_PM_OPS(mlxbf2_pm_ops, mlxbf2_gpio_suspend, mlxbf2_gpio_resume);
static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = {
{ "MLNXBF22", 0 },
@@ -320,13 +306,10 @@ MODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match);
static struct platform_driver mlxbf2_gpio_driver = {
.driver = {
.name = "mlxbf2_gpio",
- .acpi_match_table = ACPI_PTR(mlxbf2_gpio_acpi_match),
+ .acpi_match_table = mlxbf2_gpio_acpi_match,
+ .pm = &mlxbf2_pm_ops,
},
.probe = mlxbf2_gpio_probe,
-#ifdef CONFIG_PM
- .suspend = mlxbf2_gpio_suspend,
- .resume = mlxbf2_gpio_resume,
-#endif
};
module_platform_driver(mlxbf2_gpio_driver);
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index 67dc38976ab6..70d6ae20b1da 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -332,7 +332,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
mpc8xxx_gc->regs + GPIO_DIR, NULL,
BGPIOF_BIG_ENDIAN);
if (ret)
- goto err;
+ return ret;
dev_dbg(&pdev->dev, "GPIO registers are LITTLE endian\n");
} else {
ret = bgpio_init(gc, &pdev->dev, 4,
@@ -342,7 +342,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
BGPIOF_BIG_ENDIAN
| BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (ret)
- goto err;
+ return ret;
dev_dbg(&pdev->dev, "GPIO registers are BIG endian\n");
}
@@ -380,11 +380,11 @@ static int mpc8xxx_probe(struct platform_device *pdev)
is_acpi_node(fwnode))
gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
- ret = gpiochip_add_data(gc, mpc8xxx_gc);
+ ret = devm_gpiochip_add_data(&pdev->dev, gc, mpc8xxx_gc);
if (ret) {
dev_err(&pdev->dev,
"GPIO chip registration failed with status %d\n", ret);
- goto err;
+ return ret;
}
mpc8xxx_gc->irqn = platform_get_irq(pdev, 0);
@@ -416,7 +416,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
return 0;
err:
- iounmap(mpc8xxx_gc->regs);
+ irq_domain_remove(mpc8xxx_gc->irq);
return ret;
}
@@ -429,9 +429,6 @@ static int mpc8xxx_remove(struct platform_device *pdev)
irq_domain_remove(mpc8xxx_gc->irq);
}
- gpiochip_remove(&mpc8xxx_gc->gc);
- iounmap(mpc8xxx_gc->regs);
-
return 0;
}
diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c
index 10c0a9bc5ea1..c3658a597a80 100644
--- a/drivers/gpio/gpio-mt7621.c
+++ b/drivers/gpio/gpio-mt7621.c
@@ -239,6 +239,7 @@ mediatek_gpio_bank_probe(struct device *dev,
if (!rg->chip.label)
return -ENOMEM;
+ rg->chip.offset = bank * MTK_BANK_WIDTH;
rg->irq_chip.name = dev_name(dev);
rg->irq_chip.parent_device = dev;
rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask;
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index b378aba32602..f7b653314e7e 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -564,9 +564,9 @@ static int gpio_rcar_probe(struct platform_device *pdev)
}
if (p->info.has_inen) {
- pm_runtime_get_sync(p->dev);
+ pm_runtime_get_sync(dev);
gpio_rcar_enable_inputs(p);
- pm_runtime_put(p->dev);
+ pm_runtime_put(dev);
}
dev_info(dev, "driving %d GPIOs\n", npins);
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 05c90d76cb22..c99858f40a27 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -607,15 +607,21 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
if (!gpio)
return -ENOMEM;
- gpio->soc = of_device_get_match_data(&pdev->dev);
+ gpio->soc = device_get_match_data(&pdev->dev);
gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security");
- if (IS_ERR(gpio->secure))
- return PTR_ERR(gpio->secure);
+ if (IS_ERR(gpio->secure)) {
+ gpio->secure = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(gpio->secure))
+ return PTR_ERR(gpio->secure);
+ }
gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio");
- if (IS_ERR(gpio->base))
- return PTR_ERR(gpio->base);
+ if (IS_ERR(gpio->base)) {
+ gpio->base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(gpio->base))
+ return PTR_ERR(gpio->base);
+ }
err = platform_irq_count(pdev);
if (err < 0)
@@ -677,11 +683,13 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
gpio->gpio.names = (const char * const *)names;
+#if defined(CONFIG_OF_GPIO)
gpio->gpio.of_node = pdev->dev.of_node;
gpio->gpio.of_gpio_n_cells = 2;
gpio->gpio.of_xlate = tegra186_gpio_of_xlate;
+#endif /* CONFIG_OF_GPIO */
- gpio->intc.name = pdev->dev.of_node->name;
+ gpio->intc.name = dev_name(&pdev->dev);
gpio->intc.irq_ack = tegra186_irq_ack;
gpio->intc.irq_mask = tegra186_irq_mask;
gpio->intc.irq_unmask = tegra186_irq_unmask;
@@ -893,10 +901,20 @@ static const struct of_device_id tegra186_gpio_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra186_gpio_of_match);
+static const struct acpi_device_id tegra186_gpio_acpi_match[] = {
+ { .id = "NVDA0108", .driver_data = (kernel_ulong_t)&tegra186_main_soc },
+ { .id = "NVDA0208", .driver_data = (kernel_ulong_t)&tegra186_aon_soc },
+ { .id = "NVDA0308", .driver_data = (kernel_ulong_t)&tegra194_main_soc },
+ { .id = "NVDA0408", .driver_data = (kernel_ulong_t)&tegra194_aon_soc },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, tegra186_gpio_acpi_match);
+
static struct platform_driver tegra186_gpio_driver = {
.driver = {
.name = "tegra186-gpio",
.of_match_table = tegra186_gpio_of_match,
+ .acpi_match_table = tegra186_gpio_acpi_match,
},
.probe = tegra186_gpio_probe,
};
diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c
index c301c1d56dd2..e55d28a8a66f 100644
--- a/drivers/gpio/gpio-viperboard.c
+++ b/drivers/gpio/gpio-viperboard.c
@@ -404,11 +404,10 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
vb_gpio->gpioa.get = vprbrd_gpioa_get;
vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input;
vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output;
+
ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpioa, vb_gpio);
- if (ret < 0) {
- dev_err(vb_gpio->gpioa.parent, "could not add gpio a");
+ if (ret < 0)
return ret;
- }
/* registering gpio b */
vb_gpio->gpiob.label = "viperboard gpio b";
@@ -421,15 +420,8 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
vb_gpio->gpiob.get = vprbrd_gpiob_get;
vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input;
vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output;
- ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
- if (ret < 0) {
- dev_err(vb_gpio->gpiob.parent, "could not add gpio b");
- return ret;
- }
-
- platform_set_drvdata(pdev, vb_gpio);
- return ret;
+ return devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
}
static struct platform_driver vprbrd_gpio_driver = {
diff --git a/drivers/gpio/gpio-virtio.c b/drivers/gpio/gpio-virtio.c
new file mode 100644
index 000000000000..d24f1c9264bc
--- /dev/null
+++ b/drivers/gpio/gpio-virtio.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * GPIO driver for virtio-based virtual GPIO controllers
+ *
+ * Copyright (C) 2021 metux IT consult
+ * Enrico Weigelt, metux IT consult <info@metux.net>
+ *
+ * Copyright (C) 2021 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ */
+
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/virtio_config.h>
+#include <uapi/linux/virtio_gpio.h>
+#include <uapi/linux/virtio_ids.h>
+
+struct virtio_gpio_line {
+ struct mutex lock; /* Protects line operation */
+ struct completion completion;
+ struct virtio_gpio_request req ____cacheline_aligned;
+ struct virtio_gpio_response res ____cacheline_aligned;
+ unsigned int rxlen;
+};
+
+struct virtio_gpio {
+ struct virtio_device *vdev;
+ struct mutex lock; /* Protects virtqueue operation */
+ struct gpio_chip gc;
+ struct virtio_gpio_line *lines;
+ struct virtqueue *request_vq;
+};
+
+static int _virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio,
+ u8 txvalue, u8 *rxvalue, void *response, u32 rxlen)
+{
+ struct virtio_gpio_line *line = &vgpio->lines[gpio];
+ struct virtio_gpio_request *req = &line->req;
+ struct virtio_gpio_response *res = response;
+ struct scatterlist *sgs[2], req_sg, res_sg;
+ struct device *dev = &vgpio->vdev->dev;
+ int ret;
+
+ /*
+ * Prevent concurrent requests for the same line since we have
+ * pre-allocated request/response buffers for each GPIO line. Moreover
+ * Linux always accesses a GPIO line sequentially, so this locking shall
+ * always go through without any delays.
+ */
+ mutex_lock(&line->lock);
+
+ req->type = cpu_to_le16(type);
+ req->gpio = cpu_to_le16(gpio);
+ req->value = cpu_to_le32(txvalue);
+
+ sg_init_one(&req_sg, req, sizeof(*req));
+ sg_init_one(&res_sg, res, rxlen);
+ sgs[0] = &req_sg;
+ sgs[1] = &res_sg;
+
+ line->rxlen = 0;
+ reinit_completion(&line->completion);
+
+ /*
+ * Virtqueue callers need to ensure they don't call its APIs with other
+ * virtqueue operations at the same time.
+ */
+ mutex_lock(&vgpio->lock);
+ ret = virtqueue_add_sgs(vgpio->request_vq, sgs, 1, 1, line, GFP_KERNEL);
+ if (ret) {
+ dev_err(dev, "failed to add request to vq\n");
+ mutex_unlock(&vgpio->lock);
+ goto out;
+ }
+
+ virtqueue_kick(vgpio->request_vq);
+ mutex_unlock(&vgpio->lock);
+
+ if (!wait_for_completion_timeout(&line->completion, HZ)) {
+ dev_err(dev, "GPIO operation timed out\n");
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ if (unlikely(res->status != VIRTIO_GPIO_STATUS_OK)) {
+ dev_err(dev, "GPIO request failed: %d\n", gpio);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (unlikely(line->rxlen != rxlen)) {
+ dev_err(dev, "GPIO operation returned incorrect len (%u : %u)\n",
+ rxlen, line->rxlen);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (rxvalue)
+ *rxvalue = res->value;
+
+out:
+ mutex_unlock(&line->lock);
+ return ret;
+}
+
+static int virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio,
+ u8 txvalue, u8 *rxvalue)
+{
+ struct virtio_gpio_line *line = &vgpio->lines[gpio];
+ struct virtio_gpio_response *res = &line->res;
+
+ return _virtio_gpio_req(vgpio, type, gpio, txvalue, rxvalue, res,
+ sizeof(*res));
+}
+
+static void virtio_gpio_free(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct virtio_gpio *vgpio = gpiochip_get_data(gc);
+
+ virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
+ VIRTIO_GPIO_DIRECTION_NONE, NULL);
+}
+
+static int virtio_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct virtio_gpio *vgpio = gpiochip_get_data(gc);
+ u8 direction;
+ int ret;
+
+ ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_DIRECTION, gpio, 0,
+ &direction);
+ if (ret)
+ return ret;
+
+ switch (direction) {
+ case VIRTIO_GPIO_DIRECTION_IN:
+ return GPIO_LINE_DIRECTION_IN;
+ case VIRTIO_GPIO_DIRECTION_OUT:
+ return GPIO_LINE_DIRECTION_OUT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int virtio_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct virtio_gpio *vgpio = gpiochip_get_data(gc);
+
+ return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
+ VIRTIO_GPIO_DIRECTION_IN, NULL);
+}
+
+static int virtio_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
+ int value)
+{
+ struct virtio_gpio *vgpio = gpiochip_get_data(gc);
+ int ret;
+
+ ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL);
+ if (ret)
+ return ret;
+
+ return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
+ VIRTIO_GPIO_DIRECTION_OUT, NULL);
+}
+
+static int virtio_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct virtio_gpio *vgpio = gpiochip_get_data(gc);
+ u8 value;
+ int ret;
+
+ ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_VALUE, gpio, 0, &value);
+ return ret ? ret : value;
+}
+
+static void virtio_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
+{
+ struct virtio_gpio *vgpio = gpiochip_get_data(gc);
+
+ virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL);
+}
+
+static void virtio_gpio_request_vq(struct virtqueue *vq)
+{
+ struct virtio_gpio_line *line;
+ unsigned int len;
+
+ do {
+ line = virtqueue_get_buf(vq, &len);
+ if (!line)
+ return;
+
+ line->rxlen = len;
+ complete(&line->completion);
+ } while (1);
+}
+
+static void virtio_gpio_free_vqs(struct virtio_device *vdev)
+{
+ vdev->config->reset(vdev);
+ vdev->config->del_vqs(vdev);
+}
+
+static int virtio_gpio_alloc_vqs(struct virtio_gpio *vgpio,
+ struct virtio_device *vdev)
+{
+ const char * const names[] = { "requestq" };
+ vq_callback_t *cbs[] = {
+ virtio_gpio_request_vq,
+ };
+ struct virtqueue *vqs[1] = { NULL };
+ int ret;
+
+ ret = virtio_find_vqs(vdev, 1, vqs, cbs, names, NULL);
+ if (ret) {
+ dev_err(&vdev->dev, "failed to find vqs: %d\n", ret);
+ return ret;
+ }
+
+ if (!vqs[0]) {
+ dev_err(&vdev->dev, "failed to find requestq vq\n");
+ return -ENODEV;
+ }
+ vgpio->request_vq = vqs[0];
+
+ return 0;
+}
+
+static const char **virtio_gpio_get_names(struct virtio_gpio *vgpio,
+ u32 gpio_names_size, u16 ngpio)
+{
+ struct virtio_gpio_response_get_names *res;
+ struct device *dev = &vgpio->vdev->dev;
+ u8 *gpio_names, *str;
+ const char **names;
+ int i, ret, len;
+
+ if (!gpio_names_size)
+ return NULL;
+
+ len = sizeof(*res) + gpio_names_size;
+ res = devm_kzalloc(dev, len, GFP_KERNEL);
+ if (!res)
+ return NULL;
+ gpio_names = res->value;
+
+ ret = _virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_NAMES, 0, 0, NULL,
+ res, len);
+ if (ret) {
+ dev_err(dev, "Failed to get GPIO names: %d\n", ret);
+ return NULL;
+ }
+
+ names = devm_kcalloc(dev, ngpio, sizeof(*names), GFP_KERNEL);
+ if (!names)
+ return NULL;
+
+ /* NULL terminate the string instead of checking it */
+ gpio_names[gpio_names_size - 1] = '\0';
+
+ for (i = 0, str = gpio_names; i < ngpio; i++) {
+ names[i] = str;
+ str += strlen(str) + 1; /* zero-length strings are allowed */
+
+ if (str > gpio_names + gpio_names_size) {
+ dev_err(dev, "gpio_names block is too short (%d)\n", i);
+ return NULL;
+ }
+ }
+
+ return names;
+}
+
+static int virtio_gpio_probe(struct virtio_device *vdev)
+{
+ struct virtio_gpio_config config;
+ struct device *dev = &vdev->dev;
+ struct virtio_gpio *vgpio;
+ u32 gpio_names_size;
+ u16 ngpio;
+ int ret, i;
+
+ vgpio = devm_kzalloc(dev, sizeof(*vgpio), GFP_KERNEL);
+ if (!vgpio)
+ return -ENOMEM;
+
+ /* Read configuration */
+ virtio_cread_bytes(vdev, 0, &config, sizeof(config));
+ gpio_names_size = le32_to_cpu(config.gpio_names_size);
+ ngpio = le16_to_cpu(config.ngpio);
+ if (!ngpio) {
+ dev_err(dev, "Number of GPIOs can't be zero\n");
+ return -EINVAL;
+ }
+
+ vgpio->lines = devm_kcalloc(dev, ngpio, sizeof(*vgpio->lines), GFP_KERNEL);
+ if (!vgpio->lines)
+ return -ENOMEM;
+
+ for (i = 0; i < ngpio; i++) {
+ mutex_init(&vgpio->lines[i].lock);
+ init_completion(&vgpio->lines[i].completion);
+ }
+
+ mutex_init(&vgpio->lock);
+ vdev->priv = vgpio;
+
+ vgpio->vdev = vdev;
+ vgpio->gc.free = virtio_gpio_free;
+ vgpio->gc.get_direction = virtio_gpio_get_direction;
+ vgpio->gc.direction_input = virtio_gpio_direction_input;
+ vgpio->gc.direction_output = virtio_gpio_direction_output;
+ vgpio->gc.get = virtio_gpio_get;
+ vgpio->gc.set = virtio_gpio_set;
+ vgpio->gc.ngpio = ngpio;
+ vgpio->gc.base = -1; /* Allocate base dynamically */
+ vgpio->gc.label = dev_name(dev);
+ vgpio->gc.parent = dev;
+ vgpio->gc.owner = THIS_MODULE;
+ vgpio->gc.can_sleep = true;
+
+ ret = virtio_gpio_alloc_vqs(vgpio, vdev);
+ if (ret)
+ return ret;
+
+ /* Mark the device ready to perform operations from within probe() */
+ virtio_device_ready(vdev);
+
+ vgpio->gc.names = virtio_gpio_get_names(vgpio, gpio_names_size, ngpio);
+
+ ret = gpiochip_add_data(&vgpio->gc, vgpio);
+ if (ret) {
+ virtio_gpio_free_vqs(vdev);
+ dev_err(dev, "Failed to add virtio-gpio controller\n");
+ }
+
+ return ret;
+}
+
+static void virtio_gpio_remove(struct virtio_device *vdev)
+{
+ struct virtio_gpio *vgpio = vdev->priv;
+
+ gpiochip_remove(&vgpio->gc);
+ virtio_gpio_free_vqs(vdev);
+}
+
+static const struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_GPIO, VIRTIO_DEV_ANY_ID },
+ {},
+};
+MODULE_DEVICE_TABLE(virtio, id_table);
+
+static struct virtio_driver virtio_gpio_driver = {
+ .id_table = id_table,
+ .probe = virtio_gpio_probe,
+ .remove = virtio_gpio_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ },
+};
+module_virtio_driver(virtio_gpio_driver);
+
+MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("VirtIO GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c
index 4a517e5dedf0..79da85d17b71 100644
--- a/drivers/gpio/gpiolib-devres.c
+++ b/drivers/gpio/gpiolib-devres.c
@@ -145,7 +145,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_index);
* In case of error an ERR_PTR() is returned.
*/
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
- struct device_node *node,
+ const struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label)
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index bbcc7c073f63..0ad288ab6262 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -122,7 +122,7 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
{
int size;
- struct device_node *np = gc->of_node;
+ const struct device_node *np = gc->of_node;
size = of_property_count_u32_elems(np, "gpio-reserved-ranges");
if (size > 0 && size % 2 == 0)
@@ -130,7 +130,7 @@ bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
return false;
}
-static void of_gpio_flags_quirks(struct device_node *np,
+static void of_gpio_flags_quirks(const struct device_node *np,
const char *propname,
enum of_gpio_flags *flags,
int index)
@@ -236,7 +236,7 @@ static void of_gpio_flags_quirks(struct device_node *np,
* value on the error condition. If @flags is not NULL the function also fills
* in flags for the GPIO.
*/
-static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np,
const char *propname, int index, enum of_gpio_flags *flags)
{
struct of_phandle_args gpiospec;
@@ -275,7 +275,7 @@ out:
return desc;
}
-int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
+int of_get_named_gpio_flags(const struct device_node *np, const char *list_name,
int index, enum of_gpio_flags *flags)
{
struct gpio_desc *desc;
@@ -303,7 +303,7 @@ EXPORT_SYMBOL_GPL(of_get_named_gpio_flags);
*
* In case of error an ERR_PTR() is returned.
*/
-struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
+struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label)
@@ -373,7 +373,7 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id
enum of_gpio_flags *of_flags)
{
char prop_name[32]; /* 32 is max size of property name */
- struct device_node *np = dev->of_node;
+ const struct device_node *np = dev->of_node;
struct gpio_desc *desc;
/*
@@ -404,7 +404,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
unsigned int idx,
unsigned long *flags)
{
- struct device_node *np = dev->of_node;
+ const struct device_node *np = dev->of_node;
if (!IS_ENABLED(CONFIG_SPI_MASTER))
return ERR_PTR(-ENOENT);
@@ -440,7 +440,7 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *
"wlf,ldo1ena", /* WM8994 */
"wlf,ldo2ena", /* WM8994 */
};
- struct device_node *np = dev->of_node;
+ const struct device_node *np = dev->of_node;
struct gpio_desc *desc;
int i;
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 27c07108496d..d1b9b721218f 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -382,10 +382,18 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
if (count < 0)
return 0;
- if (count > gdev->ngpio) {
- dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d",
- count, gdev->ngpio);
- count = gdev->ngpio;
+ /*
+ * When offset is set in the driver side we assume the driver internally
+ * is using more than one gpiochip per the same device. We have to stop
+ * setting friendly names if the specified ones with 'gpio-line-names'
+ * are less than the offset in the device itself. This means all the
+ * lines are not present for every single pin within all the internal
+ * gpiochips.
+ */
+ if (count <= chip->offset) {
+ dev_warn(&gdev->dev, "gpio-line-names too short (length %d), cannot map names for the gpiochip at offset %u\n",
+ count, chip->offset);
+ return 0;
}
names = kcalloc(count, sizeof(*names), GFP_KERNEL);
@@ -400,8 +408,22 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
return ret;
}
+ /*
+ * When more that one gpiochip per device is used, 'count' can
+ * contain at most number gpiochips x chip->ngpio. We have to
+ * correctly distribute all defined lines taking into account
+ * chip->offset as starting point from where we will assign
+ * the names to pins from the 'names' array. Since property
+ * 'gpio-line-names' cannot contains gaps, we have to be sure
+ * we only assign those pins that really exists since chip->ngpio
+ * can be different of the chip->offset.
+ */
+ count = (count > chip->offset) ? count - chip->offset : count;
+ if (count > chip->ngpio)
+ count = chip->ngpio;
+
for (i = 0; i < count; i++)
- gdev->descs[i].name = names[i];
+ gdev->descs[i].name = names[chip->offset + i];
kfree(names);
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 7ff89690a976..cea777ae7fb9 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -35,6 +35,11 @@ config DRM_MIPI_DSI
bool
depends on DRM
+config DRM_DP_AUX_BUS
+ tristate
+ depends on DRM
+ depends on OF
+
config DRM_DP_AUX_CHARDEV
bool "DRM DP AUX Interface"
depends on DRM
@@ -251,7 +256,6 @@ config DRM_AMDGPU
select HWMON
select BACKLIGHT_CLASS_DEVICE
select INTERVAL_TREE
- select CHASH
help
Choose this option if you have a recent AMD Radeon graphics card.
@@ -317,8 +321,6 @@ source "drivers/gpu/drm/tilcdc/Kconfig"
source "drivers/gpu/drm/qxl/Kconfig"
-source "drivers/gpu/drm/bochs/Kconfig"
-
source "drivers/gpu/drm/virtio/Kconfig"
source "drivers/gpu/drm/msm/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a118692a6df7..ad1112154898 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -33,6 +33,8 @@ drm-$(CONFIG_PCI) += drm_pci.o
drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
+obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
+
drm_vram_helper-y := drm_gem_vram_helper.o
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
@@ -96,7 +98,6 @@ obj-y += omapdrm/
obj-$(CONFIG_DRM_SUN4I) += sun4i/
obj-y += tilcdc/
obj-$(CONFIG_DRM_QXL) += qxl/
-obj-$(CONFIG_DRM_BOCHS) += bochs/
obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio/
obj-$(CONFIG_DRM_MSM) += msm/
obj-$(CONFIG_DRM_TEGRA) += tegra/
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index c56320e78c0e..8d0748184a14 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -57,7 +57,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
- amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o
+ amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o \
+ amdgpu_eeprom.o amdgpu_mca.o
amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
@@ -75,7 +76,7 @@ amdgpu-y += \
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \
arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o vangogh_reg_init.o \
nbio_v7_2.o dimgrey_cavefish_reg_init.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o \
- beige_goby_reg_init.o yellow_carp_reg_init.o
+ beige_goby_reg_init.o yellow_carp_reg_init.o cyan_skillfish_reg_init.o
# add DF block
amdgpu-y += \
@@ -111,6 +112,7 @@ amdgpu-y += \
psp_v3_1.o \
psp_v10_0.o \
psp_v11_0.o \
+ psp_v11_0_8.o \
psp_v12_0.o \
psp_v13_0.o
@@ -118,7 +120,7 @@ amdgpu-y += \
amdgpu-y += \
dce_v10_0.o \
dce_v11_0.o \
- dce_virtual.o
+ amdgpu_vkms.o
# add GFX block
amdgpu-y += \
@@ -187,6 +189,10 @@ amdgpu-y += \
amdgpu-y += \
amdgpu_reset.o
+# add MCA block
+amdgpu-y += \
+ mca_v3_0.o
+
# add amdkfd interfaces
amdgpu-y += amdgpu_amdkfd.o
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 8ac6eb9f1fdb..dc3c6b3a00e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -108,6 +108,7 @@
#include "amdgpu_df.h"
#include "amdgpu_smuio.h"
#include "amdgpu_fdinfo.h"
+#include "amdgpu_mca.h"
#define MAX_GPU_INSTANCE 16
@@ -916,6 +917,7 @@ struct amdgpu_device {
/* display */
bool enable_virtual_display;
+ struct amdgpu_vkms_output *amdgpu_vkms_output;
struct amdgpu_mode_info mode_info;
/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
struct work_struct hotplug_work;
@@ -1008,6 +1010,9 @@ struct amdgpu_device {
/* df */
struct amdgpu_df df;
+ /* MCA */
+ struct amdgpu_mca mca;
+
struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM];
uint32_t harvest_ip_mask;
int num_ip_blocks;
@@ -1108,8 +1113,13 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev);
int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev);
+void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
+ void *buf, size_t size, bool write);
+size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
+ void *buf, size_t size, bool write);
+
void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
- uint32_t *buf, size_t size, bool write);
+ void *buf, size_t size, bool write);
uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
uint32_t reg, uint32_t acc_flags);
void amdgpu_device_wreg(struct amdgpu_device *adev,
@@ -1265,6 +1275,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter));
+#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+
/* Common functions */
bool amdgpu_device_has_job_running(struct amdgpu_device *adev);
bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev);
@@ -1385,12 +1397,12 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta
int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps);
-bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev);
+bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
void amdgpu_acpi_detect(void);
#else
static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
-static inline bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev) { return false; }
+static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
static inline void amdgpu_acpi_detect(void) { }
static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }
static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
index b8655ff73a65..cc9c9f8b23b2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
@@ -160,17 +160,28 @@ static int acp_poweron(struct generic_pm_domain *genpd)
return 0;
}
-static struct device *get_mfd_cell_dev(const char *device_name, int r)
+static int acp_genpd_add_device(struct device *dev, void *data)
{
- char auto_dev_name[25];
- struct device *dev;
+ struct generic_pm_domain *gpd = data;
+ int ret;
- snprintf(auto_dev_name, sizeof(auto_dev_name),
- "%s.%d.auto", device_name, r);
- dev = bus_find_device_by_name(&platform_bus_type, NULL, auto_dev_name);
- dev_info(dev, "device %s added to pm domain\n", auto_dev_name);
+ ret = pm_genpd_add_device(gpd, dev);
+ if (ret)
+ dev_err(dev, "Failed to add dev to genpd %d\n", ret);
- return dev;
+ return ret;
+}
+
+static int acp_genpd_remove_device(struct device *dev, void *data)
+{
+ int ret;
+
+ ret = pm_genpd_remove_device(dev);
+ if (ret)
+ dev_err(dev, "Failed to remove dev from genpd %d\n", ret);
+
+ /* Continue to remove */
+ return 0;
}
/**
@@ -181,11 +192,10 @@ static struct device *get_mfd_cell_dev(const char *device_name, int r)
*/
static int acp_hw_init(void *handle)
{
- int r, i;
+ int r;
uint64_t acp_base;
u32 val = 0;
u32 count = 0;
- struct device *dev;
struct i2s_platform_data *i2s_pdata = NULL;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -341,15 +351,10 @@ static int acp_hw_init(void *handle)
if (r)
goto failure;
- for (i = 0; i < ACP_DEVS ; i++) {
- dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
- r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev);
- if (r) {
- dev_err(dev, "Failed to add dev to genpd\n");
- goto failure;
- }
- }
-
+ r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
+ acp_genpd_add_device);
+ if (r)
+ goto failure;
/* Assert Soft reset of ACP */
val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
@@ -410,10 +415,8 @@ failure:
*/
static int acp_hw_fini(void *handle)
{
- int i, ret;
u32 val = 0;
u32 count = 0;
- struct device *dev;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* return early if no ACP */
@@ -458,13 +461,8 @@ static int acp_hw_fini(void *handle)
udelay(100);
}
- for (i = 0; i < ACP_DEVS ; i++) {
- dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
- ret = pm_genpd_remove_device(dev);
- /* If removal fails, dont giveup and try rest */
- if (ret)
- dev_err(dev, "remove dev from genpd failed\n");
- }
+ device_for_each_child(adev->acp.parent, NULL,
+ acp_genpd_remove_device);
mfd_remove_devices(adev->acp.parent);
kfree(adev->acp.acp_res);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index a9ce3b20d371..4811b0faafd9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -854,8 +854,8 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
if (amdgpu_device_has_dc_support(adev)) {
#if defined(CONFIG_DRM_AMD_DC)
struct amdgpu_display_manager *dm = &adev->dm;
- if (dm->backlight_dev)
- atif->bd = dm->backlight_dev;
+ if (dm->backlight_dev[0])
+ atif->bd = dm->backlight_dev[0];
#endif
} else {
struct drm_encoder *tmp;
@@ -1032,13 +1032,13 @@ void amdgpu_acpi_detect(void)
}
/**
- * amdgpu_acpi_is_s0ix_supported
+ * amdgpu_acpi_is_s0ix_active
*
* @adev: amdgpu_device_pointer
*
* returns true if supported, false if not.
*/
-bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev)
+bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
{
#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND)
if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index f9c01bdc3d4c..3003ee1c9487 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -21,6 +21,7 @@
*/
#include "amdgpu_amdkfd.h"
+#include "amd_pcie.h"
#include "amd_shared.h"
#include "amdgpu.h"
@@ -553,6 +554,88 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *s
return (uint8_t)ret;
}
+int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)dst, *peer_adev;
+ int num_links;
+
+ if (adev->asic_type != CHIP_ALDEBARAN)
+ return 0;
+
+ if (src)
+ peer_adev = (struct amdgpu_device *)src;
+
+ /* num links returns 0 for indirect peers since indirect route is unknown. */
+ num_links = is_min ? 1 : amdgpu_xgmi_get_num_links(adev, peer_adev);
+ if (num_links < 0) {
+ DRM_ERROR("amdgpu: failed to get xgmi num links between node %d and %d. ret = %d\n",
+ adev->gmc.xgmi.physical_node_id,
+ peer_adev->gmc.xgmi.physical_node_id, num_links);
+ num_links = 0;
+ }
+
+ /* Aldebaran xGMI DPM is defeatured so assume x16 x 25Gbps for bandwidth. */
+ return (num_links * 16 * 25000)/BITS_PER_BYTE;
+}
+
+int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)dev;
+ int num_lanes_shift = (is_min ? ffs(adev->pm.pcie_mlw_mask) :
+ fls(adev->pm.pcie_mlw_mask)) - 1;
+ int gen_speed_shift = (is_min ? ffs(adev->pm.pcie_gen_mask &
+ CAIL_PCIE_LINK_SPEED_SUPPORT_MASK) :
+ fls(adev->pm.pcie_gen_mask &
+ CAIL_PCIE_LINK_SPEED_SUPPORT_MASK)) - 1;
+ uint32_t num_lanes_mask = 1 << num_lanes_shift;
+ uint32_t gen_speed_mask = 1 << gen_speed_shift;
+ int num_lanes_factor = 0, gen_speed_mbits_factor = 0;
+
+ switch (num_lanes_mask) {
+ case CAIL_PCIE_LINK_WIDTH_SUPPORT_X1:
+ num_lanes_factor = 1;
+ break;
+ case CAIL_PCIE_LINK_WIDTH_SUPPORT_X2:
+ num_lanes_factor = 2;
+ break;
+ case CAIL_PCIE_LINK_WIDTH_SUPPORT_X4:
+ num_lanes_factor = 4;
+ break;
+ case CAIL_PCIE_LINK_WIDTH_SUPPORT_X8:
+ num_lanes_factor = 8;
+ break;
+ case CAIL_PCIE_LINK_WIDTH_SUPPORT_X12:
+ num_lanes_factor = 12;
+ break;
+ case CAIL_PCIE_LINK_WIDTH_SUPPORT_X16:
+ num_lanes_factor = 16;
+ break;
+ case CAIL_PCIE_LINK_WIDTH_SUPPORT_X32:
+ num_lanes_factor = 32;
+ break;
+ }
+
+ switch (gen_speed_mask) {
+ case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1:
+ gen_speed_mbits_factor = 2500;
+ break;
+ case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2:
+ gen_speed_mbits_factor = 5000;
+ break;
+ case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3:
+ gen_speed_mbits_factor = 8000;
+ break;
+ case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4:
+ gen_speed_mbits_factor = 16000;
+ break;
+ case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5:
+ gen_speed_mbits_factor = 32000;
+ break;
+ }
+
+ return (num_lanes_factor * gen_speed_mbits_factor)/BITS_PER_BYTE;
+}
+
uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd)
{
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
@@ -631,7 +714,6 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
ret = dma_fence_wait(f, false);
err_ib_sched:
- dma_fence_put(f);
amdgpu_job_free(job);
err:
return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index cf62f43a03da..ec028cf963f5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -226,6 +226,8 @@ uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd);
uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd);
int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd);
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src);
+int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min);
+int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min);
/* Read user wptr from a specified user address space with page fault
* disabled. The memory must be pinned and mapped to the hardware when
@@ -269,7 +271,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv,
uint64_t *size);
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
- struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv);
+ struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv, bool *table_freed);
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv);
int amdgpu_amdkfd_gpuvm_sync_memory(
@@ -330,7 +332,7 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd);
int kgd2kfd_post_reset(struct kfd_dev *kfd);
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd);
-void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask);
+void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask);
#else
static inline int kgd2kfd_init(void)
{
@@ -389,7 +391,7 @@ void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd)
}
static inline
-void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
+void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
{
}
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c
index a5434b713856..46cd4ee6bafb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c
@@ -44,4 +44,5 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = {
.get_atc_vmid_pasid_mapping_info =
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
.set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base,
+ .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c
index 6409d6b1b2df..5a7f680bcb3f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c
@@ -305,5 +305,6 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = {
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
.set_vm_context_page_table_base =
kgd_gfx_v9_set_vm_context_page_table_base,
- .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy
+ .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
+ .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
index 491acdf92f73..960acf68150a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
@@ -560,6 +560,9 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
case KFD_PREEMPT_TYPE_WAVEFRONT_RESET:
type = RESET_WAVES;
break;
+ case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE:
+ type = SAVE_WAVES;
+ break;
default:
type = DRAIN_PIPE;
break;
@@ -754,6 +757,33 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
}
+static void program_trap_handler_settings(struct kgd_dev *kgd,
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
+{
+ struct amdgpu_device *adev = get_amdgpu_device(kgd);
+
+ lock_srbm(kgd, 0, 0, 0, vmid);
+
+ /*
+ * Program TBA registers
+ */
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_LO),
+ lower_32_bits(tba_addr >> 8));
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_HI),
+ upper_32_bits(tba_addr >> 8) |
+ (1 << SQ_SHADER_TBA_HI__TRAP_EN__SHIFT));
+
+ /*
+ * Program TMA registers
+ */
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_LO),
+ lower_32_bits(tma_addr >> 8));
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
+ upper_32_bits(tma_addr >> 8));
+
+ unlock_srbm(kgd);
+}
+
const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
.program_sh_mem_settings = kgd_program_sh_mem_settings,
.set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
@@ -774,4 +804,5 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
.get_atc_vmid_pasid_mapping_info =
get_atc_vmid_pasid_mapping_info,
.set_vm_context_page_table_base = set_vm_context_page_table_base,
+ .program_trap_handler_settings = program_trap_handler_settings,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
index 1f5620cc3570..dac0d751d5af 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
@@ -537,6 +537,9 @@ static int hqd_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
case KFD_PREEMPT_TYPE_WAVEFRONT_RESET:
type = RESET_WAVES;
break;
+ case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE:
+ type = SAVE_WAVES;
+ break;
default:
type = DRAIN_PIPE;
break;
@@ -658,6 +661,33 @@ static void set_vm_context_page_table_base_v10_3(struct kgd_dev *kgd, uint32_t v
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
}
+static void program_trap_handler_settings_v10_3(struct kgd_dev *kgd,
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
+{
+ struct amdgpu_device *adev = get_amdgpu_device(kgd);
+
+ lock_srbm(kgd, 0, 0, 0, vmid);
+
+ /*
+ * Program TBA registers
+ */
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_LO),
+ lower_32_bits(tba_addr >> 8));
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_HI),
+ upper_32_bits(tba_addr >> 8) |
+ (1 << SQ_SHADER_TBA_HI__TRAP_EN__SHIFT));
+
+ /*
+ * Program TMA registers
+ */
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_LO),
+ lower_32_bits(tma_addr >> 8));
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
+ upper_32_bits(tma_addr >> 8));
+
+ unlock_srbm(kgd);
+}
+
#if 0
uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd,
uint32_t trap_debug_wave_launch_mode,
@@ -820,6 +850,7 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
.address_watch_get_offset = address_watch_get_offset_v10_3,
.get_atc_vmid_pasid_mapping_info = NULL,
.set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3,
+ .program_trap_handler_settings = program_trap_handler_settings_v10_3,
#if 0
.enable_debug_trap = enable_debug_trap_v10_3,
.disable_debug_trap = disable_debug_trap_v10_3,
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 ed3014fbb563..bcc1cbeb8799 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
@@ -42,7 +42,8 @@
enum hqd_dequeue_request_type {
NO_ACTION = 0,
DRAIN_PIPE,
- RESET_WAVES
+ RESET_WAVES,
+ SAVE_WAVES
};
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
@@ -566,6 +567,9 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
case KFD_PREEMPT_TYPE_WAVEFRONT_RESET:
type = RESET_WAVES;
break;
+ case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE:
+ type = SAVE_WAVES;
+ break;
default:
type = DRAIN_PIPE;
break;
@@ -878,6 +882,32 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
adev->gfx.cu_info.max_waves_per_simd;
}
+void kgd_gfx_v9_program_trap_handler_settings(struct kgd_dev *kgd,
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
+{
+ struct amdgpu_device *adev = get_amdgpu_device(kgd);
+
+ lock_srbm(kgd, 0, 0, 0, vmid);
+
+ /*
+ * Program TBA registers
+ */
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_LO),
+ lower_32_bits(tba_addr >> 8));
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_HI),
+ upper_32_bits(tba_addr >> 8));
+
+ /*
+ * Program TMA registers
+ */
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_LO),
+ lower_32_bits(tma_addr >> 8));
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
+ upper_32_bits(tma_addr >> 8));
+
+ unlock_srbm(kgd);
+}
+
const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
.program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
.set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping,
@@ -899,4 +929,5 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
.set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base,
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
+ .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h
index e64deba8900f..c63591106879 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h
@@ -65,3 +65,5 @@ void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd,
uint32_t vmid, uint64_t page_table_base);
void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
int *pasid_wave_cnt, int *max_waves_per_cu);
+void kgd_gfx_v9_program_trap_handler_settings(struct kgd_dev *kgd,
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 4fb15750b9bb..2d6b2d77b738 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1057,7 +1057,8 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem,
static int update_gpuvm_pte(struct kgd_mem *mem,
struct kfd_mem_attachment *entry,
- struct amdgpu_sync *sync)
+ struct amdgpu_sync *sync,
+ bool *table_freed)
{
struct amdgpu_bo_va *bo_va = entry->bo_va;
struct amdgpu_device *adev = entry->adev;
@@ -1068,7 +1069,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem,
return ret;
/* Update the page tables */
- ret = amdgpu_vm_bo_update(adev, bo_va, false);
+ ret = amdgpu_vm_bo_update(adev, bo_va, false, table_freed);
if (ret) {
pr_err("amdgpu_vm_bo_update failed\n");
return ret;
@@ -1080,7 +1081,8 @@ static int update_gpuvm_pte(struct kgd_mem *mem,
static int map_bo_to_gpuvm(struct kgd_mem *mem,
struct kfd_mem_attachment *entry,
struct amdgpu_sync *sync,
- bool no_update_pte)
+ bool no_update_pte,
+ bool *table_freed)
{
int ret;
@@ -1097,7 +1099,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem,
if (no_update_pte)
return 0;
- ret = update_gpuvm_pte(mem, entry, sync);
+ ret = update_gpuvm_pte(mem, entry, sync, table_freed);
if (ret) {
pr_err("update_gpuvm_pte() failed\n");
goto update_gpuvm_pte_failed;
@@ -1285,11 +1287,22 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
if (avm->process_info)
return -EINVAL;
+ /* Free the original amdgpu allocated pasid,
+ * will be replaced with kfd allocated pasid.
+ */
+ if (avm->pasid) {
+ amdgpu_pasid_free(avm->pasid);
+ amdgpu_vm_set_pasid(adev, avm, 0);
+ }
+
/* Convert VM into a compute VM */
- ret = amdgpu_vm_make_compute(adev, avm, pasid);
+ ret = amdgpu_vm_make_compute(adev, avm);
if (ret)
return ret;
+ ret = amdgpu_vm_set_pasid(adev, avm, pasid);
+ if (ret)
+ return ret;
/* Initialize KFD part of the VM and process info */
ret = init_kfd_vm(avm, process_info, ef);
if (ret)
@@ -1594,7 +1607,8 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
}
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
- struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv)
+ struct kgd_dev *kgd, struct kgd_mem *mem,
+ void *drm_priv, bool *table_freed)
{
struct amdgpu_device *adev = get_amdgpu_device(kgd);
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
@@ -1682,7 +1696,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
entry->va, entry->va + bo_size, entry);
ret = map_bo_to_gpuvm(mem, entry, ctx.sync,
- is_invalid_userptr);
+ is_invalid_userptr, table_freed);
if (ret) {
pr_err("Failed to map bo to gpuvm\n");
goto out_unreserve;
@@ -1706,6 +1720,12 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
true);
ret = unreserve_bo_and_vms(&ctx, false, false);
+ /* Only apply no TLB flush on Aldebaran to
+ * workaround regressions on other Asics.
+ */
+ if (table_freed && (adev->asic_type != CHIP_ALDEBARAN))
+ *table_freed = true;
+
goto out;
out_unreserve:
@@ -2132,7 +2152,7 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info)
continue;
kfd_mem_dmaunmap_attachment(mem, attachment);
- ret = update_gpuvm_pte(mem, attachment, &sync);
+ ret = update_gpuvm_pte(mem, attachment, &sync, NULL);
if (ret) {
pr_err("%s: update PTE failed\n", __func__);
/* make sure this gets validated again */
@@ -2338,7 +2358,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
continue;
kfd_mem_dmaunmap_attachment(mem, attachment);
- ret = update_gpuvm_pte(mem, attachment, &sync_obj);
+ ret = update_gpuvm_pte(mem, attachment, &sync_obj, NULL);
if (ret) {
pr_debug("Memory eviction: update PTE failed. Try again\n");
goto validate_map_fail;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
index a130e766cbdb..c905a4cfc173 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
@@ -34,6 +34,7 @@ struct amdgpu_fpriv;
struct amdgpu_bo_list_entry {
struct ttm_validate_buffer tv;
struct amdgpu_bo_va *bo_va;
+ struct dma_fence_chain *chain;
uint32_t priority;
struct page **user_pages;
bool user_invalidated;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 30fa1f61e0e5..913f9eaa9cd6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -572,6 +572,20 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
goto out;
}
+ amdgpu_bo_list_for_each_entry(e, p->bo_list) {
+ struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo);
+
+ e->bo_va = amdgpu_vm_bo_find(vm, bo);
+
+ if (bo->tbo.base.dma_buf && !amdgpu_bo_explicit_sync(bo)) {
+ e->chain = dma_fence_chain_alloc();
+ if (!e->chain) {
+ r = -ENOMEM;
+ goto error_validate;
+ }
+ }
+ }
+
amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold,
&p->bytes_moved_vis_threshold);
p->bytes_moved = 0;
@@ -599,15 +613,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
gws = p->bo_list->gws_obj;
oa = p->bo_list->oa_obj;
- amdgpu_bo_list_for_each_entry(e, p->bo_list) {
- struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo);
-
- /* Make sure we use the exclusive slot for shared BOs */
- if (bo->prime_shared_count)
- e->tv.num_shared = 0;
- e->bo_va = amdgpu_vm_bo_find(vm, bo);
- }
-
if (gds) {
p->job->gds_base = amdgpu_bo_gpu_offset(gds) >> PAGE_SHIFT;
p->job->gds_size = amdgpu_bo_size(gds) >> PAGE_SHIFT;
@@ -629,8 +634,13 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
}
error_validate:
- if (r)
+ if (r) {
+ amdgpu_bo_list_for_each_entry(e, p->bo_list) {
+ dma_fence_chain_free(e->chain);
+ e->chain = NULL;
+ }
ttm_eu_backoff_reservation(&p->ticket, &p->validated);
+ }
out:
return r;
}
@@ -670,9 +680,17 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error,
{
unsigned i;
- if (error && backoff)
+ if (error && backoff) {
+ struct amdgpu_bo_list_entry *e;
+
+ amdgpu_bo_list_for_each_entry(e, parser->bo_list) {
+ dma_fence_chain_free(e->chain);
+ e->chain = NULL;
+ }
+
ttm_eu_backoff_reservation(&parser->ticket,
&parser->validated);
+ }
for (i = 0; i < parser->num_post_deps; i++) {
drm_syncobj_put(parser->post_deps[i].syncobj);
@@ -781,7 +799,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (r)
return r;
- r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false);
+ r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false, NULL);
if (r)
return r;
@@ -792,7 +810,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
bo_va = fpriv->csa_va;
BUG_ON(!bo_va);
- r = amdgpu_vm_bo_update(adev, bo_va, false);
+ r = amdgpu_vm_bo_update(adev, bo_va, false, NULL);
if (r)
return r;
@@ -811,7 +829,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (bo_va == NULL)
continue;
- r = amdgpu_vm_bo_update(adev, bo_va, false);
+ r = amdgpu_vm_bo_update(adev, bo_va, false, NULL);
if (r)
return r;
@@ -1109,7 +1127,7 @@ static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p
dep->chain = NULL;
if (syncobj_deps[i].point) {
- dep->chain = kmalloc(sizeof(*dep->chain), GFP_KERNEL);
+ dep->chain = dma_fence_chain_alloc();
if (!dep->chain)
return -ENOMEM;
}
@@ -1117,7 +1135,7 @@ static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p
dep->syncobj = drm_syncobj_find(p->filp,
syncobj_deps[i].handle);
if (!dep->syncobj) {
- kfree(dep->chain);
+ dma_fence_chain_free(dep->chain);
return -EINVAL;
}
dep->point = syncobj_deps[i].point;
@@ -1245,6 +1263,28 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
amdgpu_vm_move_to_lru_tail(p->adev, &fpriv->vm);
+ amdgpu_bo_list_for_each_entry(e, p->bo_list) {
+ struct dma_resv *resv = e->tv.bo->base.resv;
+ struct dma_fence_chain *chain = e->chain;
+
+ if (!chain)
+ continue;
+
+ /*
+ * Work around dma_resv shortcommings by wrapping up the
+ * submission in a dma_fence_chain and add it as exclusive
+ * fence, but first add the submission as shared fence to make
+ * sure that shared fences never signal before the exclusive
+ * one.
+ */
+ dma_fence_chain_init(chain, dma_resv_excl_fence(resv),
+ dma_fence_get(p->fence), 1);
+
+ dma_resv_add_shared_fence(resv, p->fence);
+ rcu_assign_pointer(resv->fence_excl, &chain->base);
+ e->chain = NULL;
+ }
+
ttm_eu_fence_buffer_objects(&p->ticket, &p->validated, p->fence);
mutex_unlock(&p->adev->notifier_lock);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index 536005bff24a..277128846dd1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -1414,7 +1414,7 @@ no_preempt:
continue;
}
job = to_amdgpu_job(s_job);
- if (preempted && job->fence == fence)
+ if (preempted && (&job->hw_fence) == fence)
/* mark the job as preempted */
job->preemption_status |= AMDGPU_IB_PREEMPTED;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index f944ed858f3e..41c6b3aacd37 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -116,6 +116,7 @@ const char *amdgpu_asic_name[] = {
"RENOIR",
"ALDEBARAN",
"NAVI10",
+ "CYAN_SKILLFISH",
"NAVI14",
"NAVI12",
"SIENNA_CICHLID",
@@ -287,7 +288,7 @@ bool amdgpu_device_supports_smart_shift(struct drm_device *dev)
*/
/**
- * amdgpu_device_vram_access - read/write a buffer in vram
+ * amdgpu_device_mm_access - access vram by MM_INDEX/MM_DATA
*
* @adev: amdgpu_device pointer
* @pos: offset of the buffer in vram
@@ -295,22 +296,65 @@ bool amdgpu_device_supports_smart_shift(struct drm_device *dev)
* @size: read/write size, sizeof(@buf) must > @size
* @write: true - write to vram, otherwise - read from vram
*/
-void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
- uint32_t *buf, size_t size, bool write)
+void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
+ void *buf, size_t size, bool write)
{
unsigned long flags;
- uint32_t hi = ~0;
+ uint32_t hi = ~0, tmp = 0;
+ uint32_t *data = buf;
uint64_t last;
int idx;
if (!drm_dev_enter(&adev->ddev, &idx))
return;
+ BUG_ON(!IS_ALIGNED(pos, 4) || !IS_ALIGNED(size, 4));
+
+ spin_lock_irqsave(&adev->mmio_idx_lock, flags);
+ for (last = pos + size; pos < last; pos += 4) {
+ tmp = pos >> 31;
+
+ WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
+ if (tmp != hi) {
+ WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
+ hi = tmp;
+ }
+ if (write)
+ WREG32_NO_KIQ(mmMM_DATA, *data++);
+ else
+ *data++ = RREG32_NO_KIQ(mmMM_DATA);
+ }
+
+ spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
+ drm_dev_exit(idx);
+}
+
+/**
+ * amdgpu_device_vram_access - access vram by vram aperature
+ *
+ * @adev: amdgpu_device pointer
+ * @pos: offset of the buffer in vram
+ * @buf: virtual address of the buffer in system memory
+ * @size: read/write size, sizeof(@buf) must > @size
+ * @write: true - write to vram, otherwise - read from vram
+ *
+ * The return value means how many bytes have been transferred.
+ */
+size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
+ void *buf, size_t size, bool write)
+{
#ifdef CONFIG_64BIT
+ void __iomem *addr;
+ size_t count = 0;
+ uint64_t last;
+
+ if (!adev->mman.aper_base_kaddr)
+ return 0;
+
last = min(pos + size, adev->gmc.visible_vram_size);
if (last > pos) {
- void __iomem *addr = adev->mman.aper_base_kaddr + pos;
- size_t count = last - pos;
+ addr = adev->mman.aper_base_kaddr + pos;
+ count = last - pos;
if (write) {
memcpy_toio(addr, buf, count);
@@ -322,35 +366,37 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
memcpy_fromio(buf, addr, count);
}
- if (count == size)
- goto exit;
-
- pos += count;
- buf += count / 4;
- size -= count;
}
+
+ return count;
+#else
+ return 0;
#endif
+}
- spin_lock_irqsave(&adev->mmio_idx_lock, flags);
- for (last = pos + size; pos < last; pos += 4) {
- uint32_t tmp = pos >> 31;
+/**
+ * amdgpu_device_vram_access - read/write a buffer in vram
+ *
+ * @adev: amdgpu_device pointer
+ * @pos: offset of the buffer in vram
+ * @buf: virtual address of the buffer in system memory
+ * @size: read/write size, sizeof(@buf) must > @size
+ * @write: true - write to vram, otherwise - read from vram
+ */
+void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
+ void *buf, size_t size, bool write)
+{
+ size_t count;
- WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
- if (tmp != hi) {
- WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
- hi = tmp;
- }
- if (write)
- WREG32_NO_KIQ(mmMM_DATA, *buf++);
- else
- *buf++ = RREG32_NO_KIQ(mmMM_DATA);
+ /* try to using vram apreature to access vram first */
+ count = amdgpu_device_aper_access(adev, pos, buf, size, write);
+ size -= count;
+ if (size) {
+ /* using MM to access rest vram */
+ pos += count;
+ buf += count;
+ amdgpu_device_mm_access(adev, pos, buf, size, write);
}
- spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
-
-#ifdef CONFIG_64BIT
-exit:
-#endif
- drm_dev_exit(idx);
}
/*
@@ -518,7 +564,7 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
adev->gfx.rlc.funcs &&
adev->gfx.rlc.funcs->is_rlcg_access_range) {
if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg))
- return adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, v, 0, 0);
+ return adev->gfx.rlc.funcs->sriov_wreg(adev, reg, v, 0, 0);
} else {
writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
}
@@ -1266,15 +1312,16 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
/**
* amdgpu_device_vga_set_decode - enable/disable vga decode
*
- * @cookie: amdgpu_device pointer
+ * @pdev: PCI device pointer
* @state: enable/disable vga decode
*
* Enable/disable vga decode (all asics).
* Returns VGA resource flags.
*/
-static unsigned int amdgpu_device_vga_set_decode(void *cookie, bool state)
+static unsigned int amdgpu_device_vga_set_decode(struct pci_dev *pdev,
+ bool state)
{
- struct amdgpu_device *adev = cookie;
+ struct amdgpu_device *adev = drm_to_adev(pci_get_drvdata(pdev));
amdgpu_asic_set_vga_state(adev, state);
if (state)
return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
@@ -1394,6 +1441,10 @@ static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev)
break;
case CHIP_YELLOW_CARP:
break;
+ case CHIP_CYAN_SKILLFISH:
+ if (adev->pdev->device == 0x13FE)
+ adev->apu_flags |= AMD_APU_IS_CYAN_SKILLFISH2;
+ break;
default:
return -EINVAL;
}
@@ -2100,6 +2151,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
case CHIP_BEIGE_GOBY:
case CHIP_VANGOGH:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
if (adev->asic_type == CHIP_VANGOGH)
adev->family = AMDGPU_FAMILY_VGH;
else if (adev->asic_type == CHIP_YELLOW_CARP)
@@ -3594,9 +3646,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
fence_driver_init:
/* Fence driver */
- r = amdgpu_fence_driver_init(adev);
+ r = amdgpu_fence_driver_sw_init(adev);
if (r) {
- dev_err(adev->dev, "amdgpu_fence_driver_init failed\n");
+ dev_err(adev->dev, "amdgpu_fence_driver_sw_init failed\n");
amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0);
goto failed;
}
@@ -3623,6 +3675,8 @@ fence_driver_init:
goto release_ras_con;
}
+ amdgpu_fence_driver_hw_init(adev);
+
dev_info(adev->dev,
"SE %d, SH per SE %d, CU per SH %d, active_cu_number %d\n",
adev->gfx.config.max_shader_engines,
@@ -3714,7 +3768,7 @@ fence_driver_init:
/* this will fail for cards that aren't VGA class devices, just
* ignore it */
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- vga_client_register(adev->pdev, adev, NULL, amdgpu_device_vga_set_decode);
+ vga_client_register(adev->pdev, amdgpu_device_vga_set_decode);
if (amdgpu_device_supports_px(ddev)) {
px = true;
@@ -3771,7 +3825,10 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
{
dev_info(adev->dev, "amdgpu: finishing device.\n");
flush_delayed_work(&adev->delayed_init_work);
- ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
+ if (adev->mman.initialized) {
+ flush_delayed_work(&adev->mman.bdev.wq);
+ ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
+ }
adev->shutdown = true;
/* make sure IB test finished before entering exclusive mode
@@ -3790,7 +3847,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
else
drm_atomic_helper_shutdown(adev_to_drm(adev));
}
- amdgpu_fence_driver_fini_hw(adev);
+ amdgpu_fence_driver_hw_fini(adev);
if (adev->pm_sysfs_en)
amdgpu_pm_sysfs_fini(adev);
@@ -3812,7 +3869,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
{
amdgpu_device_ip_fini(adev);
- amdgpu_fence_driver_fini_sw(adev);
+ amdgpu_fence_driver_sw_fini(adev);
release_firmware(adev->firmware.gpu_info_fw);
adev->firmware.gpu_info_fw = NULL;
adev->accel_working = false;
@@ -3833,7 +3890,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
vga_switcheroo_fini_domain_pm_ops(adev->dev);
}
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- vga_client_register(adev->pdev, NULL, NULL, NULL);
+ vga_client_unregister(adev->pdev);
if (IS_ENABLED(CONFIG_PERF_EVENTS))
amdgpu_pmu_fini(adev);
@@ -3887,7 +3944,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
/* evict vram memory */
amdgpu_bo_evict_vram(adev);
- amdgpu_fence_driver_suspend(adev);
+ amdgpu_fence_driver_hw_fini(adev);
amdgpu_device_ip_suspend_phase2(adev);
/* evict remaining vram memory
@@ -3932,8 +3989,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
return r;
}
- amdgpu_fence_driver_resume(adev);
-
+ amdgpu_fence_driver_hw_init(adev);
r = amdgpu_device_ip_late_init(adev);
if (r)
@@ -4394,7 +4450,7 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev)
int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
struct amdgpu_reset_context *reset_context)
{
- int i, r = 0;
+ int i, j, r = 0;
struct amdgpu_job *job = NULL;
bool need_full_reset =
test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
@@ -4418,11 +4474,22 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
if (!ring || !ring->sched.thread)
continue;
+ /*clear job fence from fence drv to avoid force_completion
+ *leave NULL and vm flush fence in fence drv */
+ for (j = 0; j <= ring->fence_drv.num_fences_mask; j++) {
+ struct dma_fence *old, **ptr;
+
+ ptr = &ring->fence_drv.fences[j];
+ old = rcu_dereference_protected(*ptr, 1);
+ if (old && test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &old->flags)) {
+ RCU_INIT_POINTER(*ptr, NULL);
+ }
+ }
/* after all hw jobs are reset, hw fence is meaningless, so force_completion */
amdgpu_fence_driver_force_completion(ring);
}
- if(job)
+ if (job && job->vm)
drm_sched_increase_karma(&job->base);
r = amdgpu_reset_prepare_hwcontext(adev, reset_context);
@@ -4886,7 +4953,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
job ? job->base.id : -1, hive->hive_id);
amdgpu_put_xgmi_hive(hive);
- if (job)
+ if (job && job->vm)
drm_sched_increase_karma(&job->base);
return 0;
}
@@ -4910,7 +4977,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
job ? job->base.id : -1);
/* even we skipped this reset, still need to set the job to guilty */
- if (job)
+ if (job && job->vm)
drm_sched_increase_karma(&job->base);
goto skip_recovery;
}
@@ -5277,6 +5344,10 @@ int amdgpu_device_baco_exit(struct drm_device *dev)
adev->nbio.funcs->enable_doorbell_interrupt)
adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
+ if (amdgpu_passthrough(adev) &&
+ adev->nbio.funcs->clear_doorbell_interrupt)
+ adev->nbio.funcs->clear_doorbell_interrupt(adev);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index a9475b207510..ae6ab93c868b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -42,48 +42,6 @@
#include <linux/pci-p2pdma.h>
#include <linux/pm_runtime.h>
-static int
-__dma_resv_make_exclusive(struct dma_resv *obj)
-{
- struct dma_fence **fences;
- unsigned int count;
- int r;
-
- if (!dma_resv_shared_list(obj)) /* no shared fences to convert */
- return 0;
-
- r = dma_resv_get_fences(obj, NULL, &count, &fences);
- if (r)
- return r;
-
- if (count == 0) {
- /* Now that was unexpected. */
- } else if (count == 1) {
- dma_resv_add_excl_fence(obj, fences[0]);
- dma_fence_put(fences[0]);
- kfree(fences);
- } else {
- struct dma_fence_array *array;
-
- array = dma_fence_array_create(count, fences,
- dma_fence_context_alloc(1), 0,
- false);
- if (!array)
- goto err_fences_put;
-
- dma_resv_add_excl_fence(obj, &array->base);
- dma_fence_put(&array->base);
- }
-
- return 0;
-
-err_fences_put:
- while (count--)
- dma_fence_put(fences[count]);
- kfree(fences);
- return -ENOMEM;
-}
-
/**
* amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation
*
@@ -110,24 +68,6 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
if (r < 0)
goto out;
- r = amdgpu_bo_reserve(bo, false);
- if (unlikely(r != 0))
- goto out;
-
- /*
- * We only create shared fences for internal use, but importers
- * of the dmabuf rely on exclusive fences for implicitly
- * tracking write hazards. As any of the current fences may
- * correspond to a write, we need to convert all existing
- * fences on the reservation object into a single exclusive
- * fence.
- */
- r = __dma_resv_make_exclusive(bo->tbo.base.resv);
- if (r)
- goto out;
-
- bo->prime_shared_count++;
- amdgpu_bo_unreserve(bo);
return 0;
out:
@@ -150,9 +90,6 @@ static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
- if (attach->dev->driver != adev->dev->driver && bo->prime_shared_count)
- bo->prime_shared_count--;
-
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
}
@@ -418,8 +355,6 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
bo = gem_to_amdgpu_bo(gobj);
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
- if (dma_buf->ops != &amdgpu_dmabuf_ops)
- bo->prime_shared_count = 1;
dma_resv_unlock(resv);
return gobj;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 971c5b8e75dc..b6640291f980 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -870,11 +870,10 @@ MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legac
module_param_named(reset_method, amdgpu_reset_method, int, 0444);
/**
- * DOC: bad_page_threshold (int)
- * Bad page threshold is to specify the threshold value of faulty pages
- * detected by RAS ECC, that may result in GPU entering bad status if total
- * faulty pages by ECC exceed threshold value and leave it for user's further
- * check.
+ * DOC: bad_page_threshold (int) Bad page threshold is specifies the
+ * threshold value of faulty pages detected by RAS ECC, which may
+ * result in the GPU entering bad status when the number of total
+ * faulty pages by ECC exceeds the threshold value.
*/
MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)");
module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444);
@@ -1213,6 +1212,9 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
{0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
+ /* CYAN_SKILLFISH */
+ {0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
+
/* BEIGE_GOBY */
{0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
@@ -1236,7 +1238,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
int ret, retry = 0;
bool supports_atomic = false;
- if (!amdgpu_virtual_display &&
+ if (amdgpu_virtual_display ||
amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
supports_atomic = true;
@@ -1292,7 +1294,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
#endif
/* Get rid of things like offb */
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "amdgpudrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver);
if (ret)
return ret;
@@ -1474,7 +1476,7 @@ static int amdgpu_pmops_suspend(struct device *dev)
struct amdgpu_device *adev = drm_to_adev(drm_dev);
int r;
- if (amdgpu_acpi_is_s0ix_supported(adev))
+ if (amdgpu_acpi_is_s0ix_active(adev))
adev->in_s0ix = true;
adev->in_s3 = true;
r = amdgpu_device_suspend(drm_dev, true);
@@ -1490,7 +1492,7 @@ static int amdgpu_pmops_resume(struct device *dev)
int r;
r = amdgpu_device_resume(drm_dev, true);
- if (amdgpu_acpi_is_s0ix_supported(adev))
+ if (amdgpu_acpi_is_s0ix_active(adev))
adev->in_s0ix = false;
return r;
}
@@ -1784,7 +1786,6 @@ static const struct drm_driver amdgpu_kms_driver = {
.open = amdgpu_driver_open_kms,
.postclose = amdgpu_driver_postclose_kms,
.lastclose = amdgpu_driver_lastclose_kms,
- .irq_handler = amdgpu_irq_handler,
.ioctls = amdgpu_ioctls_kms,
.num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms),
.dumb_create = amdgpu_mode_dumb_create,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
new file mode 100644
index 000000000000..4d9eb0137f8c
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu_eeprom.h"
+#include "amdgpu.h"
+
+/* AT24CM02 and M24M02-R have a 256-byte write page size.
+ */
+#define EEPROM_PAGE_BITS 8
+#define EEPROM_PAGE_SIZE (1U << EEPROM_PAGE_BITS)
+#define EEPROM_PAGE_MASK (EEPROM_PAGE_SIZE - 1)
+
+#define EEPROM_OFFSET_SIZE 2
+
+/* EEPROM memory addresses are 19-bits long, which can
+ * be partitioned into 3, 8, 8 bits, for a total of 19.
+ * The upper 3 bits are sent as part of the 7-bit
+ * "Device Type Identifier"--an I2C concept, which for EEPROM devices
+ * is hard-coded as 1010b, indicating that it is an EEPROM
+ * device--this is the wire format, followed by the upper
+ * 3 bits of the 19-bit address, followed by the direction,
+ * followed by two bytes holding the rest of the 16-bits of
+ * the EEPROM memory address. The format on the wire for EEPROM
+ * devices is: 1010XYZD, A15:A8, A7:A0,
+ * Where D is the direction and sequenced out by the hardware.
+ * Bits XYZ are memory address bits 18, 17 and 16.
+ * These bits are compared to how pins 1-3 of the part are connected,
+ * depending on the size of the part, more on that later.
+ *
+ * Note that of this wire format, a client is in control
+ * of, and needs to specify only XYZ, A15:A8, A7:0, bits,
+ * which is exactly the EEPROM memory address, or offset,
+ * in order to address up to 8 EEPROM devices on the I2C bus.
+ *
+ * For instance, a 2-Mbit I2C EEPROM part, addresses all its bytes,
+ * using an 18-bit address, bit 17 to 0 and thus would use all but one bit of
+ * the 19 bits previously mentioned. The designer would then not connect
+ * pins 1 and 2, and pin 3 usually named "A_2" or "E2", would be connected to
+ * either Vcc or GND. This would allow for up to two 2-Mbit parts on
+ * the same bus, where one would be addressable with bit 18 as 1, and
+ * the other with bit 18 of the address as 0.
+ *
+ * For a 2-Mbit part, bit 18 is usually known as the "Chip Enable" or
+ * "Hardware Address Bit". This bit is compared to the load on pin 3
+ * of the device, described above, and if there is a match, then this
+ * device responds to the command. This way, you can connect two
+ * 2-Mbit EEPROM devices on the same bus, but see one contiguous
+ * memory from 0 to 7FFFFh, where address 0 to 3FFFF is in the device
+ * whose pin 3 is connected to GND, and address 40000 to 7FFFFh is in
+ * the 2nd device, whose pin 3 is connected to Vcc.
+ *
+ * This addressing you encode in the 32-bit "eeprom_addr" below,
+ * namely the 19-bits "XYZ,A15:A0", as a single 19-bit address. For
+ * instance, eeprom_addr = 0x6DA01, is 110_1101_1010_0000_0001, where
+ * XYZ=110b, and A15:A0=DA01h. The XYZ bits become part of the device
+ * address, and the rest of the address bits are sent as the memory
+ * address bytes.
+ *
+ * That is, for an I2C EEPROM driver everything is controlled by
+ * the "eeprom_addr".
+ *
+ * P.S. If you need to write, lock and read the Identification Page,
+ * (M24M02-DR device only, which we do not use), change the "7" to
+ * "0xF" in the macro below, and let the client set bit 20 to 1 in
+ * "eeprom_addr", and set A10 to 0 to write into it, and A10 and A1 to
+ * 1 to lock it permanently.
+ */
+#define MAKE_I2C_ADDR(_aa) ((0xA << 3) | (((_aa) >> 16) & 7))
+
+static int __amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
+ u8 *eeprom_buf, u16 buf_size, bool read)
+{
+ u8 eeprom_offset_buf[EEPROM_OFFSET_SIZE];
+ struct i2c_msg msgs[] = {
+ {
+ .flags = 0,
+ .len = EEPROM_OFFSET_SIZE,
+ .buf = eeprom_offset_buf,
+ },
+ {
+ .flags = read ? I2C_M_RD : 0,
+ },
+ };
+ const u8 *p = eeprom_buf;
+ int r;
+ u16 len;
+
+ for (r = 0; buf_size > 0;
+ buf_size -= len, eeprom_addr += len, eeprom_buf += len) {
+ /* Set the EEPROM address we want to write to/read from.
+ */
+ msgs[0].addr = MAKE_I2C_ADDR(eeprom_addr);
+ msgs[1].addr = msgs[0].addr;
+ msgs[0].buf[0] = (eeprom_addr >> 8) & 0xff;
+ msgs[0].buf[1] = eeprom_addr & 0xff;
+
+ if (!read) {
+ /* Write the maximum amount of data, without
+ * crossing the device's page boundary, as per
+ * its spec. Partial page writes are allowed,
+ * starting at any location within the page,
+ * so long as the page boundary isn't crossed
+ * over (actually the page pointer rolls
+ * over).
+ *
+ * As per the AT24CM02 EEPROM spec, after
+ * writing into a page, the I2C driver should
+ * terminate the transfer, i.e. in
+ * "i2c_transfer()" below, with a STOP
+ * condition, so that the self-timed write
+ * cycle begins. This is implied for the
+ * "i2c_transfer()" abstraction.
+ */
+ len = min(EEPROM_PAGE_SIZE - (eeprom_addr &
+ EEPROM_PAGE_MASK),
+ (u32)buf_size);
+ } else {
+ /* Reading from the EEPROM has no limitation
+ * on the number of bytes read from the EEPROM
+ * device--they are simply sequenced out.
+ */
+ len = buf_size;
+ }
+ msgs[1].len = len;
+ msgs[1].buf = eeprom_buf;
+
+ /* This constitutes a START-STOP transaction.
+ */
+ r = i2c_transfer(i2c_adap, msgs, ARRAY_SIZE(msgs));
+ if (r != ARRAY_SIZE(msgs))
+ break;
+
+ if (!read) {
+ /* According to EEPROM specs the length of the
+ * self-writing cycle, tWR (tW), is 10 ms.
+ *
+ * TODO: Use polling on ACK, aka Acknowledge
+ * Polling, to minimize waiting for the
+ * internal write cycle to complete, as it is
+ * usually smaller than tWR (tW).
+ */
+ msleep(10);
+ }
+ }
+
+ return r < 0 ? r : eeprom_buf - p;
+}
+
+/**
+ * amdgpu_eeprom_xfer -- Read/write from/to an I2C EEPROM device
+ * @i2c_adap: pointer to the I2C adapter to use
+ * @eeprom_addr: EEPROM address from which to read/write
+ * @eeprom_buf: pointer to data buffer to read into/write from
+ * @buf_size: the size of @eeprom_buf
+ * @read: True if reading from the EEPROM, false if writing
+ *
+ * Returns the number of bytes read/written; -errno on error.
+ */
+static int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
+ u8 *eeprom_buf, u16 buf_size, bool read)
+{
+ const struct i2c_adapter_quirks *quirks = i2c_adap->quirks;
+ u16 limit;
+
+ if (!quirks)
+ limit = 0;
+ else if (read)
+ limit = quirks->max_read_len;
+ else
+ limit = quirks->max_write_len;
+
+ if (limit == 0) {
+ return __amdgpu_eeprom_xfer(i2c_adap, eeprom_addr,
+ eeprom_buf, buf_size, read);
+ } else if (limit <= EEPROM_OFFSET_SIZE) {
+ dev_err_ratelimited(&i2c_adap->dev,
+ "maddr:0x%04X size:0x%02X:quirk max_%s_len must be > %d",
+ eeprom_addr, buf_size,
+ read ? "read" : "write", EEPROM_OFFSET_SIZE);
+ return -EINVAL;
+ } else {
+ u16 ps; /* Partial size */
+ int res = 0, r;
+
+ /* The "limit" includes all data bytes sent/received,
+ * which would include the EEPROM_OFFSET_SIZE bytes.
+ * Account for them here.
+ */
+ limit -= EEPROM_OFFSET_SIZE;
+ for ( ; buf_size > 0;
+ buf_size -= ps, eeprom_addr += ps, eeprom_buf += ps) {
+ ps = min(limit, buf_size);
+
+ r = __amdgpu_eeprom_xfer(i2c_adap, eeprom_addr,
+ eeprom_buf, ps, read);
+ if (r < 0)
+ return r;
+ res += r;
+ }
+
+ return res;
+ }
+}
+
+int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap,
+ u32 eeprom_addr, u8 *eeprom_buf,
+ u16 bytes)
+{
+ return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
+ true);
+}
+
+int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap,
+ u32 eeprom_addr, u8 *eeprom_buf,
+ u16 bytes)
+{
+ return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
+ false);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
new file mode 100644
index 000000000000..6935adb2be1f
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _AMDGPU_EEPROM_H
+#define _AMDGPU_EEPROM_H
+
+#include <linux/i2c.h>
+
+int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap,
+ u32 eeprom_addr, u8 *eeprom_buf,
+ u16 bytes);
+
+int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap,
+ u32 eeprom_addr, u8 *eeprom_buf,
+ u16 bytes);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 09b048647523..cd0acbea75da 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -273,9 +273,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
return 0;
out:
- if (abo) {
-
- }
if (fb && ret) {
drm_gem_object_put(gobj);
drm_framebuffer_unregister_private(fb);
@@ -344,7 +341,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
}
/* disable all the possible outputs/crtcs before entering KMS mode */
- if (!amdgpu_device_has_dc_support(adev))
+ if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display)
drm_helper_disable_unused_functions(adev_to_drm(adev));
drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 72d9b92b1754..14499f0de32d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -129,30 +129,50 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
*
* @ring: ring the fence is associated with
* @f: resulting fence object
+ * @job: job the fence is embedded in
* @flags: flags to pass into the subordinate .emit_fence() call
*
* Emits a fence command on the requested ring (all asics).
* Returns 0 on success, -ENOMEM on failure.
*/
-int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
+int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amdgpu_job *job,
unsigned flags)
{
struct amdgpu_device *adev = ring->adev;
- struct amdgpu_fence *fence;
+ struct dma_fence *fence;
+ struct amdgpu_fence *am_fence;
struct dma_fence __rcu **ptr;
uint32_t seq;
int r;
- fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL);
- if (fence == NULL)
- return -ENOMEM;
+ if (job == NULL) {
+ /* create a sperate hw fence */
+ am_fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_ATOMIC);
+ if (am_fence == NULL)
+ return -ENOMEM;
+ fence = &am_fence->base;
+ am_fence->ring = ring;
+ } else {
+ /* take use of job-embedded fence */
+ fence = &job->hw_fence;
+ }
seq = ++ring->fence_drv.sync_seq;
- fence->ring = ring;
- dma_fence_init(&fence->base, &amdgpu_fence_ops,
- &ring->fence_drv.lock,
- adev->fence_context + ring->idx,
- seq);
+ if (job != NULL && job->job_run_counter) {
+ /* reinit seq for resubmitted jobs */
+ fence->seqno = seq;
+ } else {
+ dma_fence_init(fence, &amdgpu_fence_ops,
+ &ring->fence_drv.lock,
+ adev->fence_context + ring->idx,
+ seq);
+ }
+
+ if (job != NULL) {
+ /* mark this fence has a parent job */
+ set_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &fence->flags);
+ }
+
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
seq, flags | AMDGPU_FENCE_FLAG_INT);
pm_runtime_get_noresume(adev_to_drm(adev)->dev);
@@ -175,9 +195,9 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
/* This function can't be called concurrently anyway, otherwise
* emitting the fence would mess up the hardware ring buffer.
*/
- rcu_assign_pointer(*ptr, dma_fence_get(&fence->base));
+ rcu_assign_pointer(*ptr, dma_fence_get(fence));
- *f = &fence->base;
+ *f = fence;
return 0;
}
@@ -417,9 +437,6 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
}
amdgpu_fence_write(ring, atomic_read(&ring->fence_drv.last_seq));
- if (irq_src)
- amdgpu_irq_get(adev, irq_src, irq_type);
-
ring->fence_drv.irq_src = irq_src;
ring->fence_drv.irq_type = irq_type;
ring->fence_drv.initialized = true;
@@ -490,7 +507,7 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
r = drm_sched_init(&ring->sched, &amdgpu_sched_ops,
num_hw_submission, amdgpu_job_hang_limit,
- timeout, sched_score, ring->name);
+ timeout, NULL, sched_score, ring->name);
if (r) {
DRM_ERROR("Failed to create scheduler on ring %s.\n",
ring->name);
@@ -501,7 +518,7 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
}
/**
- * amdgpu_fence_driver_init - init the fence driver
+ * amdgpu_fence_driver_sw_init - init the fence driver
* for all possible rings.
*
* @adev: amdgpu device pointer
@@ -512,20 +529,20 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
* amdgpu_fence_driver_start_ring().
* Returns 0 for success.
*/
-int amdgpu_fence_driver_init(struct amdgpu_device *adev)
+int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev)
{
return 0;
}
/**
- * amdgpu_fence_driver_fini - tear down the fence driver
+ * amdgpu_fence_driver_hw_fini - tear down the fence driver
* for all possible rings.
*
* @adev: amdgpu device pointer
*
* Tear down the fence driver for all possible rings (all asics).
*/
-void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev)
+void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev)
{
int i, r;
@@ -534,8 +551,7 @@ void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev)
if (!ring || !ring->fence_drv.initialized)
continue;
- if (!ring->no_scheduler)
- drm_sched_fini(&ring->sched);
+
/* You can't wait for HW to signal if it's gone */
if (!drm_dev_is_unplugged(&adev->ddev))
r = amdgpu_fence_wait_empty(ring);
@@ -553,7 +569,7 @@ void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev)
}
}
-void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev)
+void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev)
{
unsigned int i, j;
@@ -563,6 +579,9 @@ void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev)
if (!ring || !ring->fence_drv.initialized)
continue;
+ if (!ring->no_scheduler)
+ drm_sched_fini(&ring->sched);
+
for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j)
dma_fence_put(ring->fence_drv.fences[j]);
kfree(ring->fence_drv.fences);
@@ -572,49 +591,18 @@ void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev)
}
/**
- * amdgpu_fence_driver_suspend - suspend the fence driver
- * for all possible rings.
- *
- * @adev: amdgpu device pointer
- *
- * Suspend the fence driver for all possible rings (all asics).
- */
-void amdgpu_fence_driver_suspend(struct amdgpu_device *adev)
-{
- int i, r;
-
- for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
- struct amdgpu_ring *ring = adev->rings[i];
- if (!ring || !ring->fence_drv.initialized)
- continue;
-
- /* wait for gpu to finish processing current batch */
- r = amdgpu_fence_wait_empty(ring);
- if (r) {
- /* delay GPU reset to resume */
- amdgpu_fence_driver_force_completion(ring);
- }
-
- /* disable the interrupt */
- if (ring->fence_drv.irq_src)
- amdgpu_irq_put(adev, ring->fence_drv.irq_src,
- ring->fence_drv.irq_type);
- }
-}
-
-/**
- * amdgpu_fence_driver_resume - resume the fence driver
+ * amdgpu_fence_driver_hw_init - enable the fence driver
* for all possible rings.
*
* @adev: amdgpu device pointer
*
- * Resume the fence driver for all possible rings (all asics).
+ * Enable the fence driver for all possible rings (all asics).
* Not all asics have all rings, so each asic will only
* start the fence driver on the rings it has using
* amdgpu_fence_driver_start_ring().
* Returns 0 for success.
*/
-void amdgpu_fence_driver_resume(struct amdgpu_device *adev)
+void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev)
{
int i;
@@ -653,8 +641,16 @@ static const char *amdgpu_fence_get_driver_name(struct dma_fence *fence)
static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f)
{
- struct amdgpu_fence *fence = to_amdgpu_fence(f);
- return (const char *)fence->ring->name;
+ struct amdgpu_ring *ring;
+
+ if (test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &f->flags)) {
+ struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence);
+
+ ring = to_amdgpu_ring(job->base.sched);
+ } else {
+ ring = to_amdgpu_fence(f)->ring;
+ }
+ return (const char *)ring->name;
}
/**
@@ -667,13 +663,20 @@ static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f)
*/
static bool amdgpu_fence_enable_signaling(struct dma_fence *f)
{
- struct amdgpu_fence *fence = to_amdgpu_fence(f);
- struct amdgpu_ring *ring = fence->ring;
+ struct amdgpu_ring *ring;
+
+ if (test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &f->flags)) {
+ struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence);
+
+ ring = to_amdgpu_ring(job->base.sched);
+ } else {
+ ring = to_amdgpu_fence(f)->ring;
+ }
if (!timer_pending(&ring->fence_drv.fallback_timer))
amdgpu_fence_schedule_fallback(ring);
- DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
+ DMA_FENCE_TRACE(f, "armed on ring %i!\n", ring->idx);
return true;
}
@@ -688,8 +691,20 @@ static bool amdgpu_fence_enable_signaling(struct dma_fence *f)
static void amdgpu_fence_free(struct rcu_head *rcu)
{
struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
- struct amdgpu_fence *fence = to_amdgpu_fence(f);
- kmem_cache_free(amdgpu_fence_slab, fence);
+
+ if (test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &f->flags)) {
+ /* free job if fence has a parent job */
+ struct amdgpu_job *job;
+
+ job = container_of(f, struct amdgpu_job, hw_fence);
+ kfree(job);
+ } else {
+ /* free fence_slab if it's separated fence*/
+ struct amdgpu_fence *fence;
+
+ fence = to_amdgpu_fence(f);
+ kmem_cache_free(amdgpu_fence_slab, fence);
+ }
}
/**
@@ -712,6 +727,7 @@ static const struct dma_fence_ops amdgpu_fence_ops = {
.release = amdgpu_fence_release,
};
+
/*
* Fence debugfs
*/
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index 39b6c6bfab45..7709caeb233d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -27,10 +27,10 @@
#include "smu_v11_0_i2c.h"
#include "atom.h"
#include "amdgpu_fru_eeprom.h"
+#include "amdgpu_eeprom.h"
-#define I2C_PRODUCT_INFO_ADDR 0xAC
-#define I2C_PRODUCT_INFO_ADDR_SIZE 0x2
-#define I2C_PRODUCT_INFO_OFFSET 0xC0
+#define FRU_EEPROM_MADDR 0x60000
+#define I2C_PRODUCT_INFO_OFFSET 0xC0
static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
{
@@ -62,19 +62,11 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
}
static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
- unsigned char *buff)
+ unsigned char *buff)
{
int ret, size;
- struct i2c_msg msg = {
- .addr = I2C_PRODUCT_INFO_ADDR,
- .flags = I2C_M_RD,
- .buf = buff,
- };
- buff[0] = 0;
- buff[1] = addrptr;
- msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + 1;
- ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
+ ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr, buff, 1);
if (ret < 1) {
DRM_WARN("FRU: Failed to get size field");
return ret;
@@ -83,13 +75,9 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
/* The size returned by the i2c requires subtraction of 0xC0 since the
* size apparently always reports as 0xC0+actual size.
*/
- size = buff[2] - I2C_PRODUCT_INFO_OFFSET;
- /* Add 1 since address field was 1 byte */
- buff[1] = addrptr + 1;
-
- msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + size;
- ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
+ size = buff[0] - I2C_PRODUCT_INFO_OFFSET;
+ ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr + 1, buff, size);
if (ret < 1) {
DRM_WARN("FRU: Failed to get data field");
return ret;
@@ -101,8 +89,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
{
unsigned char buff[34];
- int addrptr, size;
- int len;
+ u32 addrptr;
+ int size, len;
if (!is_fru_eeprom_supported(adev))
return 0;
@@ -125,7 +113,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
* Bytes 8-a are all 1-byte and refer to the size of the entire struct,
* and the language field, so just start from 0xb, manufacturer size
*/
- addrptr = 0xb;
+ addrptr = FRU_EEPROM_MADDR + 0xb;
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
if (size < 1) {
DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index b36405170ff3..76efd5f8950f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -76,7 +76,7 @@ static int amdgpu_gart_dummy_page_init(struct amdgpu_device *adev)
if (adev->dummy_page_addr)
return 0;
adev->dummy_page_addr = dma_map_page(&adev->pdev->dev, dummy_page, 0,
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
if (dma_mapping_error(&adev->pdev->dev, adev->dummy_page_addr)) {
dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n");
adev->dummy_page_addr = 0;
@@ -96,8 +96,8 @@ void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
{
if (!adev->dummy_page_addr)
return;
- pci_unmap_page(adev->pdev, adev->dummy_page_addr,
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_page(&adev->pdev->dev, adev->dummy_page_addr, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
adev->dummy_page_addr = 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 854fc497844b..cb07cc3b06ed 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -621,7 +621,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
if (operation == AMDGPU_VA_OP_MAP ||
operation == AMDGPU_VA_OP_REPLACE) {
- r = amdgpu_vm_bo_update(adev, bo_va, false);
+ r = amdgpu_vm_bo_update(adev, bo_va, false, NULL);
if (r)
goto error;
}
@@ -838,7 +838,8 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
break;
}
case AMDGPU_GEM_OP_SET_PLACEMENT:
- if (robj->prime_shared_count && (args->value & AMDGPU_GEM_DOMAIN_VRAM)) {
+ if (robj->tbo.base.import_attach &&
+ args->value & AMDGPU_GEM_DOMAIN_VRAM) {
r = -EINVAL;
amdgpu_bo_unreserve(robj);
break;
@@ -903,7 +904,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
DIV_ROUND_UP(args->bpp, 8), 0);
args->size = (u64)args->pitch * args->height;
args->size = ALIGN(args->size, PAGE_SIZE);
- domain = amdgpu_bo_get_preferred_pin_domain(adev,
+ domain = amdgpu_bo_get_preferred_domain(adev,
amdgpu_display_supported_domains(adev, flags));
r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags,
ttm_bo_type_device, NULL, &gobj);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index b4ced45301be..e7f06bd0f0cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -629,7 +629,6 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev)
adev->gfx.ras_if->block = AMDGPU_RAS_BLOCK__GFX;
adev->gfx.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->gfx.ras_if->sub_block_index = 0;
- strcpy(adev->gfx.ras_if->name, "gfx");
}
fs_info.head = ih_info.head = *adev->gfx.ras_if;
r = amdgpu_ras_late_init(adev, adev->gfx.ras_if,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index d0b8d415b63b..c7797eac83c3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -471,6 +471,27 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev)
return r;
}
+ if (adev->mca.mp0.ras_funcs &&
+ adev->mca.mp0.ras_funcs->ras_late_init) {
+ r = adev->mca.mp0.ras_funcs->ras_late_init(adev);
+ if (r)
+ return r;
+ }
+
+ if (adev->mca.mp1.ras_funcs &&
+ adev->mca.mp1.ras_funcs->ras_late_init) {
+ r = adev->mca.mp1.ras_funcs->ras_late_init(adev);
+ if (r)
+ return r;
+ }
+
+ if (adev->mca.mpio.ras_funcs &&
+ adev->mca.mpio.ras_funcs->ras_late_init) {
+ r = adev->mca.mpio.ras_funcs->ras_late_init(adev);
+ if (r)
+ return r;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index ec96e0b26b11..543000304a1c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@ -132,14 +132,11 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man,
struct amdgpu_gtt_node *node;
int r;
- spin_lock(&mgr->lock);
- if (tbo->resource && tbo->resource->mem_type != TTM_PL_TT &&
- atomic64_read(&mgr->available) < num_pages) {
- spin_unlock(&mgr->lock);
+ if (!(place->flags & TTM_PL_FLAG_TEMPORARY) &&
+ atomic64_add_return(num_pages, &mgr->used) > man->size) {
+ atomic64_sub(num_pages, &mgr->used);
return -ENOSPC;
}
- atomic64_sub(num_pages, &mgr->available);
- spin_unlock(&mgr->lock);
node = kzalloc(struct_size(node, base.mm_nodes, 1), GFP_KERNEL);
if (!node) {
@@ -175,7 +172,8 @@ err_free:
kfree(node);
err_out:
- atomic64_add(num_pages, &mgr->available);
+ if (!(place->flags & TTM_PL_FLAG_TEMPORARY))
+ atomic64_sub(num_pages, &mgr->used);
return r;
}
@@ -198,7 +196,9 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man,
if (drm_mm_node_allocated(&node->base.mm_nodes[0]))
drm_mm_remove_node(&node->base.mm_nodes[0]);
spin_unlock(&mgr->lock);
- atomic64_add(res->num_pages, &mgr->available);
+
+ if (!(res->placement & TTM_PL_FLAG_TEMPORARY))
+ atomic64_sub(res->num_pages, &mgr->used);
kfree(node);
}
@@ -213,9 +213,8 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man,
uint64_t amdgpu_gtt_mgr_usage(struct ttm_resource_manager *man)
{
struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man);
- s64 result = man->size - atomic64_read(&mgr->available);
- return (result > 0 ? result : 0) * PAGE_SIZE;
+ return atomic64_read(&mgr->used) * PAGE_SIZE;
}
/**
@@ -265,9 +264,8 @@ static void amdgpu_gtt_mgr_debug(struct ttm_resource_manager *man,
drm_mm_print(&mgr->mm, printer);
spin_unlock(&mgr->lock);
- drm_printf(printer, "man size:%llu pages, gtt available:%lld pages, usage:%lluMB\n",
- man->size, (u64)atomic64_read(&mgr->available),
- amdgpu_gtt_mgr_usage(man) >> 20);
+ drm_printf(printer, "man size:%llu pages, gtt used:%llu pages\n",
+ man->size, atomic64_read(&mgr->used));
}
static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = {
@@ -299,7 +297,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size)
size = (adev->gmc.gart_size >> PAGE_SHIFT) - start;
drm_mm_init(&mgr->mm, start, size);
spin_lock_init(&mgr->lock);
- atomic64_set(&mgr->available, gtt_size >> PAGE_SHIFT);
+ atomic64_set(&mgr->used, 0);
ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager);
ttm_resource_manager_set_used(man, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c
index 1d50d534d77c..a766e1aad2b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c
@@ -41,7 +41,6 @@ int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev)
adev->hdp.ras_if->block = AMDGPU_RAS_BLOCK__HDP;
adev->hdp.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->hdp.ras_if->sub_block_index = 0;
- strcpy(adev->hdp.ras_if->name, "hdp");
}
ih_info.head = fs_info.head = *adev->hdp.ras_if;
r = amdgpu_ras_late_init(adev, adev->hdp.ras_if,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c
index bca4dddd5a15..82608df43396 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c
@@ -339,7 +339,7 @@ static void amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus,
void
amdgpu_i2c_router_select_ddc_port(const struct amdgpu_connector *amdgpu_connector)
{
- u8 val;
+ u8 val = 0;
if (!amdgpu_connector->router.ddc_valid)
return;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index ec65ab0ddf89..c076a6b9a5a2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -262,7 +262,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
fence_flags | AMDGPU_FENCE_FLAG_64BIT);
}
- r = amdgpu_fence_emit(ring, f, fence_flags);
+ r = amdgpu_fence_emit(ring, f, job, fence_flags);
if (r) {
dev_err(adev->dev, "failed to emit fence (%d)\n", r);
if (job && job->vmid)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index cd2e18f072fc..cc2e0c9cfe0a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -46,7 +46,6 @@
#include <linux/pci.h>
#include <drm/drm_crtc_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_vblank.h>
#include <drm/amdgpu_drm.h>
#include <drm/drm_drv.h>
@@ -184,7 +183,7 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev)
* Returns:
* result of handling the IRQ, as defined by &irqreturn_t
*/
-irqreturn_t amdgpu_irq_handler(int irq, void *arg)
+static irqreturn_t amdgpu_irq_handler(int irq, void *arg)
{
struct drm_device *dev = (struct drm_device *) arg;
struct amdgpu_device *adev = drm_to_adev(dev);
@@ -307,6 +306,7 @@ static void amdgpu_restore_msix(struct amdgpu_device *adev)
int amdgpu_irq_init(struct amdgpu_device *adev)
{
int r = 0;
+ unsigned int irq;
spin_lock_init(&adev->irq.lock);
@@ -349,15 +349,22 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft);
- adev->irq.installed = true;
- /* Use vector 0 for MSI-X */
- r = drm_irq_install(adev_to_drm(adev), pci_irq_vector(adev->pdev, 0));
+ /* Use vector 0 for MSI-X. */
+ r = pci_irq_vector(adev->pdev, 0);
+ if (r < 0)
+ return r;
+ irq = r;
+
+ /* PCI devices require shared interrupts. */
+ r = request_irq(irq, amdgpu_irq_handler, IRQF_SHARED, adev_to_drm(adev)->driver->name,
+ adev_to_drm(adev));
if (r) {
- adev->irq.installed = false;
if (!amdgpu_device_has_dc_support(adev))
flush_work(&adev->hotplug_work);
return r;
}
+ adev->irq.installed = true;
+ adev->irq.irq = irq;
adev_to_drm(adev)->max_vblank_count = 0x00ffffff;
DRM_DEBUG("amdgpu: irq initialized.\n");
@@ -368,7 +375,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
{
if (adev->irq.installed) {
- drm_irq_uninstall(&adev->ddev);
+ free_irq(adev->irq.irq, adev_to_drm(adev));
adev->irq.installed = false;
if (adev->irq.msi_enabled)
pci_free_irq_vectors(adev->pdev);
@@ -584,7 +591,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev)
{
int i, j, k;
- if (amdgpu_sriov_vf(adev))
+ if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev))
amdgpu_restore_msix(adev);
for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
@@ -617,7 +624,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev)
int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
unsigned type)
{
- if (!adev_to_drm(adev)->irq_enabled)
+ if (!adev->irq.installed)
return -ENOENT;
if (type >= src->num_types)
@@ -647,7 +654,7 @@ int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
unsigned type)
{
- if (!adev_to_drm(adev)->irq_enabled)
+ if (!adev->irq.installed)
return -ENOENT;
if (type >= src->num_types)
@@ -678,7 +685,7 @@ int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
unsigned type)
{
- if (!adev_to_drm(adev)->irq_enabled)
+ if (!adev->irq.installed)
return false;
if (type >= src->num_types)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
index 78ad4784cc74..e9f2c11ea416 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
@@ -80,6 +80,7 @@ struct amdgpu_irq_src_funcs {
struct amdgpu_irq {
bool installed;
+ unsigned int irq;
spinlock_t lock;
/* interrupt sources */
struct amdgpu_irq_client client[AMDGPU_IRQ_CLIENTID_MAX];
@@ -100,7 +101,6 @@ struct amdgpu_irq {
};
void amdgpu_irq_disable_all(struct amdgpu_device *adev);
-irqreturn_t amdgpu_irq_handler(int irq, void *arg);
int amdgpu_irq_init(struct amdgpu_device *adev);
void amdgpu_irq_fini_sw(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index d33e6d97cc89..de29518673dd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -127,11 +127,16 @@ void amdgpu_job_free_resources(struct amdgpu_job *job)
{
struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched);
struct dma_fence *f;
+ struct dma_fence *hw_fence;
unsigned i;
- /* use sched fence if available */
- f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;
+ if (job->hw_fence.ops == NULL)
+ hw_fence = job->external_hw_fence;
+ else
+ hw_fence = &job->hw_fence;
+ /* use sched fence if available */
+ f = job->base.s_fence ? &job->base.s_fence->finished : hw_fence;
for (i = 0; i < job->num_ibs; ++i)
amdgpu_ib_free(ring->adev, &job->ibs[i], f);
}
@@ -142,20 +147,27 @@ static void amdgpu_job_free_cb(struct drm_sched_job *s_job)
drm_sched_job_cleanup(s_job);
- dma_fence_put(job->fence);
amdgpu_sync_free(&job->sync);
amdgpu_sync_free(&job->sched_sync);
- kfree(job);
+
+ /* only put the hw fence if has embedded fence */
+ if (job->hw_fence.ops != NULL)
+ dma_fence_put(&job->hw_fence);
+ else
+ kfree(job);
}
void amdgpu_job_free(struct amdgpu_job *job)
{
amdgpu_job_free_resources(job);
-
- dma_fence_put(job->fence);
amdgpu_sync_free(&job->sync);
amdgpu_sync_free(&job->sched_sync);
- kfree(job);
+
+ /* only put the hw fence if has embedded fence */
+ if (job->hw_fence.ops != NULL)
+ dma_fence_put(&job->hw_fence);
+ else
+ kfree(job);
}
int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity,
@@ -184,11 +196,14 @@ int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring,
job->base.sched = &ring->sched;
r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, NULL, fence);
- job->fence = dma_fence_get(*fence);
+ /* record external_hw_fence for direct submit */
+ job->external_hw_fence = dma_fence_get(*fence);
if (r)
return r;
amdgpu_job_free(job);
+ dma_fence_put(*fence);
+
return 0;
}
@@ -246,10 +261,12 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
if (r)
DRM_ERROR("Error scheduling IBs (%d)\n", r);
}
- /* if gpu reset, hw fence will be replaced here */
- dma_fence_put(job->fence);
- job->fence = dma_fence_get(fence);
+ if (!job->job_run_counter)
+ dma_fence_get(fence);
+ else if (finished->error < 0)
+ dma_fence_put(&job->hw_fence);
+ job->job_run_counter++;
amdgpu_job_free_resources(job);
fence = r ? ERR_PTR(r) : fence;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
index 81caac9b958a..9e65730193b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
@@ -46,7 +46,8 @@ struct amdgpu_job {
struct amdgpu_sync sync;
struct amdgpu_sync sched_sync;
struct amdgpu_ib *ibs;
- struct dma_fence *fence; /* the hw fence */
+ struct dma_fence hw_fence;
+ struct dma_fence *external_hw_fence;
uint32_t preamble_status;
uint32_t preemption_status;
uint32_t num_ibs;
@@ -62,6 +63,9 @@ struct amdgpu_job {
/* user fence handling */
uint64_t uf_addr;
uint64_t uf_sequence;
+
+ /* job_run_counter >= 1 means a resubmit job */
+ uint32_t job_run_counter;
};
int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
index 8996cb4ed57a..9342aa23ebd2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
@@ -47,8 +47,6 @@ int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev)
{
int i;
- cancel_delayed_work_sync(&adev->jpeg.idle_work);
-
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
continue;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 96ef3f1051d8..7e45640fbee0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -341,27 +341,27 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
switch (query_fw->index) {
case TA_FW_TYPE_PSP_XGMI:
fw_info->ver = adev->psp.ta_fw_version;
- fw_info->feature = adev->psp.ta_xgmi_ucode_version;
+ fw_info->feature = adev->psp.xgmi.feature_version;
break;
case TA_FW_TYPE_PSP_RAS:
fw_info->ver = adev->psp.ta_fw_version;
- fw_info->feature = adev->psp.ta_ras_ucode_version;
+ fw_info->feature = adev->psp.ras.feature_version;
break;
case TA_FW_TYPE_PSP_HDCP:
fw_info->ver = adev->psp.ta_fw_version;
- fw_info->feature = adev->psp.ta_hdcp_ucode_version;
+ fw_info->feature = adev->psp.hdcp.feature_version;
break;
case TA_FW_TYPE_PSP_DTM:
fw_info->ver = adev->psp.ta_fw_version;
- fw_info->feature = adev->psp.ta_dtm_ucode_version;
+ fw_info->feature = adev->psp.dtm.feature_version;
break;
case TA_FW_TYPE_PSP_RAP:
fw_info->ver = adev->psp.ta_fw_version;
- fw_info->feature = adev->psp.ta_rap_ucode_version;
+ fw_info->feature = adev->psp.rap.feature_version;
break;
case TA_FW_TYPE_PSP_SECUREDISPLAY:
fw_info->ver = adev->psp.ta_fw_version;
- fw_info->feature = adev->psp.ta_securedisplay_ucode_version;
+ fw_info->feature = adev->psp.securedisplay.feature_version;
break;
default:
return -EINVAL;
@@ -374,12 +374,12 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
fw_info->feature = adev->sdma.instance[query_fw->index].feature_version;
break;
case AMDGPU_INFO_FW_SOS:
- fw_info->ver = adev->psp.sos_fw_version;
- fw_info->feature = adev->psp.sos_feature_version;
+ fw_info->ver = adev->psp.sos.fw_version;
+ fw_info->feature = adev->psp.sos.feature_version;
break;
case AMDGPU_INFO_FW_ASD:
- fw_info->ver = adev->psp.asd_fw_version;
- fw_info->feature = adev->psp.asd_feature_version;
+ fw_info->ver = adev->psp.asd.fw_version;
+ fw_info->feature = adev->psp.asd.feature_version;
break;
case AMDGPU_INFO_FW_DMCU:
fw_info->ver = adev->dm.dmcu_fw_version;
@@ -390,8 +390,8 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
fw_info->feature = 0;
break;
case AMDGPU_INFO_FW_TOC:
- fw_info->ver = adev->psp.toc_fw_version;
- fw_info->feature = adev->psp.toc_feature_version;
+ fw_info->ver = adev->psp.toc.fw_version;
+ fw_info->feature = adev->psp.toc.feature_version;
break;
default:
return -EINVAL;
@@ -1179,10 +1179,14 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
pasid = 0;
}
- r = amdgpu_vm_init(adev, &fpriv->vm, pasid);
+ r = amdgpu_vm_init(adev, &fpriv->vm);
if (r)
goto error_pasid;
+ r = amdgpu_vm_set_pasid(adev, &fpriv->vm, pasid);
+ if (r)
+ goto error_vm;
+
fpriv->prt_va = amdgpu_vm_bo_add(adev, &fpriv->vm, NULL);
if (!fpriv->prt_va) {
r = -ENOMEM;
@@ -1210,8 +1214,10 @@ error_vm:
amdgpu_vm_fini(adev, &fpriv->vm);
error_pasid:
- if (pasid)
+ if (pasid) {
amdgpu_pasid_free(pasid);
+ amdgpu_vm_set_pasid(adev, &fpriv->vm, 0);
+ }
kfree(fpriv);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
new file mode 100644
index 000000000000..a2d3dbbf7d25
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu_ras.h"
+#include "amdgpu.h"
+#include "amdgpu_mca.h"
+
+#include "umc/umc_6_7_0_offset.h"
+#include "umc/umc_6_7_0_sh_mask.h"
+
+void amdgpu_mca_query_correctable_error_count(struct amdgpu_device *adev,
+ uint64_t mc_status_addr,
+ unsigned long *error_count)
+{
+ uint64_t mc_status = RREG64_PCIE(mc_status_addr * 4);
+
+ if (REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
+ REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)
+ *error_count += 1;
+}
+
+void amdgpu_mca_query_uncorrectable_error_count(struct amdgpu_device *adev,
+ uint64_t mc_status_addr,
+ unsigned long *error_count)
+{
+ uint64_t mc_status = RREG64_PCIE(mc_status_addr * 4);
+
+ if ((REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
+ (REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
+ REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
+ REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
+ REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
+ REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1))
+ *error_count += 1;
+}
+
+void amdgpu_mca_reset_error_count(struct amdgpu_device *adev,
+ uint64_t mc_status_addr)
+{
+ WREG64_PCIE(mc_status_addr * 4, 0x0ULL);
+}
+
+void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
+ uint64_t mc_status_addr,
+ void *ras_error_status)
+{
+ struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
+
+ amdgpu_mca_query_correctable_error_count(adev, mc_status_addr, &(err_data->ce_count));
+ amdgpu_mca_query_uncorrectable_error_count(adev, mc_status_addr, &(err_data->ue_count));
+
+ amdgpu_mca_reset_error_count(adev, mc_status_addr);
+}
+
+int amdgpu_mca_ras_late_init(struct amdgpu_device *adev,
+ struct amdgpu_mca_ras *mca_dev)
+{
+ int r;
+ struct ras_ih_if ih_info = {
+ .cb = NULL,
+ };
+ struct ras_fs_if fs_info = {
+ .sysfs_name = mca_dev->ras_funcs->sysfs_name,
+ };
+
+ if (!mca_dev->ras_if) {
+ mca_dev->ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+ if (!mca_dev->ras_if)
+ return -ENOMEM;
+ mca_dev->ras_if->block = mca_dev->ras_funcs->ras_block;
+ mca_dev->ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
+ mca_dev->ras_if->sub_block_index = 0;
+ }
+ ih_info.head = fs_info.head = *mca_dev->ras_if;
+ r = amdgpu_ras_late_init(adev, mca_dev->ras_if,
+ &fs_info, &ih_info);
+ if (r || !amdgpu_ras_is_supported(adev, mca_dev->ras_if->block)) {
+ kfree(mca_dev->ras_if);
+ mca_dev->ras_if = NULL;
+ }
+
+ return r;
+}
+
+void amdgpu_mca_ras_fini(struct amdgpu_device *adev,
+ struct amdgpu_mca_ras *mca_dev)
+{
+ struct ras_ih_if ih_info = {
+ .cb = NULL,
+ };
+
+ if (!mca_dev->ras_if)
+ return;
+
+ amdgpu_ras_late_fini(adev, mca_dev->ras_if, &ih_info);
+ kfree(mca_dev->ras_if);
+ mca_dev->ras_if = NULL;
+} \ No newline at end of file
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
new file mode 100644
index 000000000000..f860f2f0e296
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __AMDGPU_MCA_H__
+#define __AMDGPU_MCA_H__
+
+struct amdgpu_mca_ras_funcs {
+ int (*ras_late_init)(struct amdgpu_device *adev);
+ void (*ras_fini)(struct amdgpu_device *adev);
+ void (*query_ras_error_count)(struct amdgpu_device *adev,
+ void *ras_error_status);
+ void (*query_ras_error_address)(struct amdgpu_device *adev,
+ void *ras_error_status);
+ uint32_t ras_block;
+ const char* sysfs_name;
+};
+
+struct amdgpu_mca_ras {
+ struct ras_common_if *ras_if;
+ const struct amdgpu_mca_ras_funcs *ras_funcs;
+};
+
+struct amdgpu_mca_funcs {
+ void (*init)(struct amdgpu_device *adev);
+};
+
+struct amdgpu_mca {
+ const struct amdgpu_mca_funcs *funcs;
+ struct amdgpu_mca_ras mp0;
+ struct amdgpu_mca_ras mp1;
+ struct amdgpu_mca_ras mpio;
+};
+
+void amdgpu_mca_query_correctable_error_count(struct amdgpu_device *adev,
+ uint64_t mc_status_addr,
+ unsigned long *error_count);
+
+void amdgpu_mca_query_uncorrectable_error_count(struct amdgpu_device *adev,
+ uint64_t mc_status_addr,
+ unsigned long *error_count);
+
+void amdgpu_mca_reset_error_count(struct amdgpu_device *adev,
+ uint64_t mc_status_addr);
+
+void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
+ uint64_t mc_status_addr,
+ void *ras_error_status);
+
+int amdgpu_mca_ras_late_init(struct amdgpu_device *adev,
+ struct amdgpu_mca_ras *mca_dev);
+
+void amdgpu_mca_ras_fini(struct amdgpu_device *adev,
+ struct amdgpu_mca_ras *mca_dev);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c
index ead3dc572ec5..24297dc51434 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c
@@ -41,7 +41,6 @@ int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev)
adev->mmhub.ras_if->block = AMDGPU_RAS_BLOCK__MMHUB;
adev->mmhub.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->mmhub.ras_if->sub_block_index = 0;
- strcpy(adev->mmhub.ras_if->name, "mmhub");
}
ih_info.head = fs_info.head = *adev->mmhub.ras_if;
r = amdgpu_ras_late_init(adev, adev->mmhub.ras_if,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c
index 6201a5f4b4fa..6afb02fef8cf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c
@@ -39,7 +39,6 @@ int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev)
adev->nbio.ras_if->block = AMDGPU_RAS_BLOCK__PCIE_BIF;
adev->nbio.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->nbio.ras_if->sub_block_index = 0;
- strcpy(adev->nbio.ras_if->name, "pcie_bif");
}
ih_info.head = fs_info.head = *adev->nbio.ras_if;
r = amdgpu_ras_late_init(adev, adev->nbio.ras_if,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
index 45295dce5c3e..843052205bd5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
@@ -95,6 +95,7 @@ struct amdgpu_nbio_funcs {
void (*program_aspm)(struct amdgpu_device *adev);
void (*apply_lc_spc_mode_wa)(struct amdgpu_device *adev);
void (*apply_l1_link_width_reconfig_wa)(struct amdgpu_device *adev);
+ void (*clear_doorbell_interrupt)(struct amdgpu_device *adev);
};
struct amdgpu_nbio {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 92c8e6e7f346..01a78c786536 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -196,7 +196,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
c++;
}
- BUG_ON(c >= AMDGPU_BO_MAX_PLACEMENTS);
+ BUG_ON(c > AMDGPU_BO_MAX_PLACEMENTS);
placement->num_placement = c;
placement->placement = places;
@@ -731,7 +731,7 @@ retry:
/**
* amdgpu_bo_add_to_shadow_list - add a BO to the shadow list
*
- * @bo: BO that will be inserted into the shadow list
+ * @vmbo: BO that will be inserted into the shadow list
*
* Insert a BO to the shadow list.
*/
@@ -913,7 +913,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
return -EINVAL;
/* A shared bo cannot be migrated to VRAM */
- if (bo->prime_shared_count || bo->tbo.base.import_attach) {
+ if (bo->tbo.base.import_attach) {
if (domain & AMDGPU_GEM_DOMAIN_GTT)
domain = AMDGPU_GEM_DOMAIN_GTT;
else
@@ -947,7 +947,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()
*/
- domain = amdgpu_bo_get_preferred_pin_domain(adev, domain);
+ domain = amdgpu_bo_get_preferred_domain(adev, domain);
if (bo->tbo.base.import_attach)
dma_buf_pin(bo->tbo.base.import_attach);
@@ -1518,14 +1518,14 @@ u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo)
}
/**
- * amdgpu_bo_get_preferred_pin_domain - get preferred domain for scanout
+ * amdgpu_bo_get_preferred_domain - get preferred domain
* @adev: amdgpu device object
* @domain: allowed :ref:`memory domains <amdgpu_memory_domains>`
*
* Returns:
- * Which of the allowed domains is preferred for pinning the BO for scanout.
+ * Which of the allowed domains is preferred for allocating the BO.
*/
-uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev,
+uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev,
uint32_t domain)
{
if (domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 38c834d0f930..9d6c001c15f8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -100,7 +100,6 @@ struct amdgpu_bo {
struct ttm_buffer_object tbo;
struct ttm_bo_kmap_obj kmap;
u64 flags;
- unsigned prime_shared_count;
/* per VM structure for page tables and with virtual addresses */
struct amdgpu_vm_bo_base *vm_bo;
/* Constant after initialization */
@@ -334,7 +333,7 @@ void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem,
void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo);
int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow,
struct dma_fence **fence);
-uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev,
+uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev,
uint32_t domain);
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c
index f2e20666c9c1..4eaec446b49d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c
@@ -80,12 +80,17 @@ static void amdgpu_pll_reduce_ratio(unsigned *nom, unsigned *den,
* Calculate feedback and reference divider for a given post divider. Makes
* sure we stay within the limits.
*/
-static void amdgpu_pll_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div,
- unsigned fb_div_max, unsigned ref_div_max,
- unsigned *fb_div, unsigned *ref_div)
+static void amdgpu_pll_get_fb_ref_div(struct amdgpu_device *adev, unsigned int nom,
+ unsigned int den, unsigned int post_div,
+ unsigned int fb_div_max, unsigned int ref_div_max,
+ unsigned int *fb_div, unsigned int *ref_div)
{
+
/* limit reference * post divider to a maximum */
- ref_div_max = min(128 / post_div, ref_div_max);
+ if (adev->family == AMDGPU_FAMILY_SI)
+ ref_div_max = min(100 / post_div, ref_div_max);
+ else
+ ref_div_max = min(128 / post_div, ref_div_max);
/* get matching reference and feedback divider */
*ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max);
@@ -112,7 +117,8 @@ static void amdgpu_pll_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_
* Try to calculate the PLL parameters to generate the given frequency:
* dot_clock = (ref_freq * feedback_div) / (ref_div * post_div)
*/
-void amdgpu_pll_compute(struct amdgpu_pll *pll,
+void amdgpu_pll_compute(struct amdgpu_device *adev,
+ struct amdgpu_pll *pll,
u32 freq,
u32 *dot_clock_p,
u32 *fb_div_p,
@@ -199,7 +205,7 @@ void amdgpu_pll_compute(struct amdgpu_pll *pll,
for (post_div = post_div_min; post_div <= post_div_max; ++post_div) {
unsigned diff;
- amdgpu_pll_get_fb_ref_div(nom, den, post_div, fb_div_max,
+ amdgpu_pll_get_fb_ref_div(adev, nom, den, post_div, fb_div_max,
ref_div_max, &fb_div, &ref_div);
diff = abs(target_clock - (pll->reference_freq * fb_div) /
(ref_div * post_div));
@@ -214,7 +220,7 @@ void amdgpu_pll_compute(struct amdgpu_pll *pll,
post_div = post_div_best;
/* get the feedback and reference divider for the optimal value */
- amdgpu_pll_get_fb_ref_div(nom, den, post_div, fb_div_max, ref_div_max,
+ amdgpu_pll_get_fb_ref_div(adev, nom, den, post_div, fb_div_max, ref_div_max,
&fb_div, &ref_div);
/* reduce the numbers to a simpler ratio once more */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.h
index db6136f68b82..44a583d6c9b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.h
@@ -24,7 +24,8 @@
#ifndef __AMDGPU_PLL_H__
#define __AMDGPU_PLL_H__
-void amdgpu_pll_compute(struct amdgpu_pll *pll,
+void amdgpu_pll_compute(struct amdgpu_device *adev,
+ struct amdgpu_pll *pll,
u32 freq,
u32 *dot_clock_p,
u32 *fb_div_p,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 3ec5099ffeb6..23efdc672502 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -24,16 +24,17 @@
*/
#include <linux/firmware.h>
-#include <linux/dma-mapping.h>
#include <drm/drm_drv.h>
#include "amdgpu.h"
#include "amdgpu_psp.h"
#include "amdgpu_ucode.h"
+#include "amdgpu_xgmi.h"
#include "soc15_common.h"
#include "psp_v3_1.h"
#include "psp_v10_0.h"
#include "psp_v11_0.h"
+#include "psp_v11_0_8.h"
#include "psp_v12_0.h"
#include "psp_v13_0.h"
@@ -41,8 +42,6 @@
#include "amdgpu_securedisplay.h"
#include "amdgpu_atomfirmware.h"
-#include <drm/drm_drv.h>
-
static int psp_sysfs_init(struct amdgpu_device *adev);
static void psp_sysfs_fini(struct amdgpu_device *adev);
@@ -122,6 +121,12 @@ static int psp_early_init(void *handle)
psp_v13_0_set_psp_funcs(psp);
psp->autoload_supported = true;
break;
+ case CHIP_CYAN_SKILLFISH:
+ if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) {
+ psp_v11_0_8_set_psp_funcs(psp);
+ psp->autoload_supported = false;
+ }
+ break;
default:
return -EINVAL;
}
@@ -247,6 +252,12 @@ static int psp_sw_init(void *handle)
struct psp_runtime_boot_cfg_entry boot_cfg_entry;
struct psp_memory_training_context *mem_training_ctx = &psp->mem_train_ctx;
+ psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+ if (!psp->cmd) {
+ DRM_ERROR("Failed to allocate memory to command buffer!\n");
+ ret = -ENOMEM;
+ }
+
if (!amdgpu_sriov_vf(adev)) {
ret = psp_init_microcode(psp);
if (ret) {
@@ -309,25 +320,30 @@ static int psp_sw_init(void *handle)
static int psp_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct psp_context *psp = &adev->psp;
+ struct psp_gfx_cmd_resp *cmd = psp->cmd;
- psp_memory_training_fini(&adev->psp);
- if (adev->psp.sos_fw) {
- release_firmware(adev->psp.sos_fw);
- adev->psp.sos_fw = NULL;
+ psp_memory_training_fini(psp);
+ if (psp->sos_fw) {
+ release_firmware(psp->sos_fw);
+ psp->sos_fw = NULL;
}
- if (adev->psp.asd_fw) {
- release_firmware(adev->psp.asd_fw);
- adev->psp.asd_fw = NULL;
+ if (psp->asd_fw) {
+ release_firmware(psp->asd_fw);
+ psp->asd_fw = NULL;
}
- if (adev->psp.ta_fw) {
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
+ if (psp->ta_fw) {
+ release_firmware(psp->ta_fw);
+ psp->ta_fw = NULL;
}
if (adev->asic_type == CHIP_NAVI10 ||
adev->asic_type == CHIP_SIENNA_CICHLID)
psp_sysfs_fini(adev);
+ kfree(cmd);
+ cmd = NULL;
+
return 0;
}
@@ -356,6 +372,44 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
return -ETIME;
}
+static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id)
+{
+ switch (cmd_id) {
+ case GFX_CMD_ID_LOAD_TA:
+ return "LOAD_TA";
+ case GFX_CMD_ID_UNLOAD_TA:
+ return "UNLOAD_TA";
+ case GFX_CMD_ID_INVOKE_CMD:
+ return "INVOKE_CMD";
+ case GFX_CMD_ID_LOAD_ASD:
+ return "LOAD_ASD";
+ case GFX_CMD_ID_SETUP_TMR:
+ return "SETUP_TMR";
+ case GFX_CMD_ID_LOAD_IP_FW:
+ return "LOAD_IP_FW";
+ case GFX_CMD_ID_DESTROY_TMR:
+ return "DESTROY_TMR";
+ case GFX_CMD_ID_SAVE_RESTORE:
+ return "SAVE_RESTORE_IP_FW";
+ case GFX_CMD_ID_SETUP_VMR:
+ return "SETUP_VMR";
+ case GFX_CMD_ID_DESTROY_VMR:
+ return "DESTROY_VMR";
+ case GFX_CMD_ID_PROG_REG:
+ return "PROG_REG";
+ case GFX_CMD_ID_GET_FW_ATTESTATION:
+ return "GET_FW_ATTESTATION";
+ case GFX_CMD_ID_LOAD_TOC:
+ return "ID_LOAD_TOC";
+ case GFX_CMD_ID_AUTOLOAD_RLC:
+ return "AUTOLOAD_RLC";
+ case GFX_CMD_ID_BOOT_CFG:
+ return "BOOT_CFG";
+ default:
+ return "UNKNOWN CMD";
+ }
+}
+
static int
psp_cmd_submit_buf(struct psp_context *psp,
struct amdgpu_firmware_info *ucode,
@@ -373,8 +427,6 @@ psp_cmd_submit_buf(struct psp_context *psp,
if (!drm_dev_enter(&psp->adev->ddev, &idx))
return 0;
- mutex_lock(&psp->mutex);
-
memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE);
memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp));
@@ -417,10 +469,10 @@ psp_cmd_submit_buf(struct psp_context *psp,
*/
if (!skip_unsupport && (psp->cmd_buf_mem->resp.status || !timeout) && !ras_intr) {
if (ucode)
- DRM_WARN("failed to load ucode id (%d) ",
- ucode->ucode_id);
- DRM_WARN("psp command (0x%X) failed and response status is (0x%X)\n",
- psp->cmd_buf_mem->cmd_id,
+ DRM_WARN("failed to load ucode (%s) ",
+ amdgpu_ucode_name(ucode->ucode_id));
+ DRM_WARN("psp gfx command (%s) failed and response status is (0x%X)\n",
+ psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id),
psp->cmd_buf_mem->resp.status);
if (!timeout) {
ret = -EINVAL;
@@ -434,11 +486,26 @@ psp_cmd_submit_buf(struct psp_context *psp,
}
exit:
- mutex_unlock(&psp->mutex);
drm_dev_exit(idx);
return ret;
}
+static struct psp_gfx_cmd_resp *acquire_psp_cmd_buf(struct psp_context *psp)
+{
+ struct psp_gfx_cmd_resp *cmd = psp->cmd;
+
+ mutex_lock(&psp->mutex);
+
+ memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
+
+ return cmd;
+}
+
+void release_psp_cmd_buf(struct psp_context *psp)
+{
+ mutex_unlock(&psp->mutex);
+}
+
static void psp_prep_tmr_cmd_buf(struct psp_context *psp,
struct psp_gfx_cmd_resp *cmd,
uint64_t tmr_mc, struct amdgpu_bo *tmr_bo)
@@ -473,21 +540,20 @@ static int psp_load_toc(struct psp_context *psp,
uint32_t *tmr_size)
{
int ret;
- struct psp_gfx_cmd_resp *cmd;
+ struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
/* Copy toc to psp firmware private buffer */
- psp_copy_fw(psp, psp->toc_start_addr, psp->toc_bin_size);
+ psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes);
- psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc_bin_size);
+ psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc.size_bytes);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
if (!ret)
*tmr_size = psp->cmd_buf_mem->resp.tmr_size;
- kfree(cmd);
+
+ release_psp_cmd_buf(psp);
+
return ret;
}
@@ -511,8 +577,8 @@ static int psp_tmr_init(struct psp_context *psp)
/* For ASICs support RLC autoload, psp will parse the toc
* and calculate the total size of TMR needed */
if (!amdgpu_sriov_vf(psp->adev) &&
- psp->toc_start_addr &&
- psp->toc_bin_size &&
+ psp->toc.start_addr &&
+ psp->toc.size_bytes &&
psp->fw_pri_buf) {
ret = psp_load_toc(psp, &tmr_size);
if (ret) {
@@ -552,9 +618,7 @@ static int psp_tmr_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp))
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo);
DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n",
@@ -563,13 +627,13 @@ static int psp_tmr_load(struct psp_context *psp)
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp,
- struct psp_gfx_cmd_resp *cmd)
+ struct psp_gfx_cmd_resp *cmd)
{
if (amdgpu_sriov_vf(psp->adev))
cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR;
@@ -580,11 +644,7 @@ static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp,
static int psp_tmr_unload(struct psp_context *psp)
{
int ret;
- struct psp_gfx_cmd_resp *cmd;
-
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_tmr_unload_cmd_buf(psp, cmd);
DRM_INFO("free PSP TMR buffer\n");
@@ -592,7 +652,7 @@ static int psp_tmr_unload(struct psp_context *psp)
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -626,9 +686,7 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
if (amdgpu_sriov_vf(psp->adev))
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION;
@@ -640,7 +698,7 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32);
}
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -648,13 +706,13 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg)
{
struct psp_context *psp = &adev->psp;
- struct psp_gfx_cmd_resp *cmd = psp->cmd;
+ struct psp_gfx_cmd_resp *cmd;
int ret;
if (amdgpu_sriov_vf(adev))
return 0;
- memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
+ cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_BOOT_CFG;
cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_GET;
@@ -665,47 +723,59 @@ static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg)
(cmd->resp.uresp.boot_cfg.boot_cfg & BOOT_CONFIG_GECC) ? 1 : 0;
}
+ release_psp_cmd_buf(psp);
+
return ret;
}
static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg)
{
+ int ret;
struct psp_context *psp = &adev->psp;
- struct psp_gfx_cmd_resp *cmd = psp->cmd;
+ struct psp_gfx_cmd_resp *cmd;
if (amdgpu_sriov_vf(adev))
return 0;
- memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
+ cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_BOOT_CFG;
cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET;
cmd->cmd.boot_cfg.boot_config = boot_cfg;
cmd->cmd.boot_cfg.boot_config_valid = boot_cfg;
- return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+ ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+ release_psp_cmd_buf(psp);
+
+ return ret;
}
static int psp_rl_load(struct amdgpu_device *adev)
{
+ int ret;
struct psp_context *psp = &adev->psp;
- struct psp_gfx_cmd_resp *cmd = psp->cmd;
+ struct psp_gfx_cmd_resp *cmd;
- if (psp->rl_bin_size == 0)
+ if (!is_psp_fw_valid(psp->rl))
return 0;
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
- memcpy(psp->fw_pri_buf, psp->rl_start_addr, psp->rl_bin_size);
+ cmd = acquire_psp_cmd_buf(psp);
- memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
+ memset(psp->fw_pri_buf, 0, PSP_1_MEG);
+ memcpy(psp->fw_pri_buf, psp->rl.start_addr, psp->rl.size_bytes);
cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr);
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(psp->fw_pri_mc_addr);
- cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl_bin_size;
+ cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl.size_bytes;
cmd->cmd.cmd_load_ip_fw.fw_type = GFX_FW_TYPE_REG_LIST;
- return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+ ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+ release_psp_cmd_buf(psp);
+
+ return ret;
}
static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
@@ -730,17 +800,15 @@ static int psp_asd_load(struct psp_context *psp)
* add workaround to bypass it for sriov now.
* TODO: add version check to make it common
*/
- if (amdgpu_sriov_vf(psp->adev) || !psp->asd_ucode_size)
+ if (amdgpu_sriov_vf(psp->adev) || !psp->asd.size_bytes)
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
- psp_copy_fw(psp, psp->asd_start_addr, psp->asd_ucode_size);
+ psp_copy_fw(psp, psp->asd.start_addr, psp->asd.size_bytes);
psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr,
- psp->asd_ucode_size);
+ psp->asd.size_bytes);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
@@ -749,7 +817,7 @@ static int psp_asd_load(struct psp_context *psp)
psp->asd_context.session_id = cmd->resp.session_id;
}
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -772,9 +840,7 @@ static int psp_asd_unload(struct psp_context *psp)
if (!psp->asd_context.asd_initialized)
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_unload_cmd_buf(cmd, psp->asd_context.session_id);
@@ -783,7 +849,7 @@ static int psp_asd_unload(struct psp_context *psp)
if (!ret)
psp->asd_context.asd_initialized = false;
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -799,22 +865,21 @@ static void psp_prep_reg_prog_cmd_buf(struct psp_gfx_cmd_resp *cmd,
int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg,
uint32_t value)
{
- struct psp_gfx_cmd_resp *cmd = NULL;
+ struct psp_gfx_cmd_resp *cmd;
int ret = 0;
if (reg >= PSP_REG_LAST)
return -EINVAL;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
psp_prep_reg_prog_cmd_buf(cmd, reg, value);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
if (ret)
DRM_ERROR("PSP failed to program reg id %d", reg);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
+
return ret;
}
@@ -834,23 +899,37 @@ static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
cmd->cmd.cmd_load_ta.cmd_buf_len = ta_shared_size;
}
-static int psp_xgmi_init_shared_buf(struct psp_context *psp)
+static int psp_ta_init_shared_buf(struct psp_context *psp,
+ struct ta_mem_context *mem_ctx,
+ uint32_t shared_mem_size)
{
int ret;
/*
- * Allocate 16k memory aligned to 4k from Frame Buffer (local
- * physical) for xgmi ta <-> Driver
- */
- ret = amdgpu_bo_create_kernel(psp->adev, PSP_XGMI_SHARED_MEM_SIZE,
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
- &psp->xgmi_context.xgmi_shared_bo,
- &psp->xgmi_context.xgmi_shared_mc_addr,
- &psp->xgmi_context.xgmi_shared_buf);
+ * Allocate 16k memory aligned to 4k from Frame Buffer (local
+ * physical) for ta to host memory
+ */
+ ret = amdgpu_bo_create_kernel(psp->adev, shared_mem_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &mem_ctx->shared_bo,
+ &mem_ctx->shared_mc_addr,
+ &mem_ctx->shared_buf);
return ret;
}
+static void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx)
+{
+ amdgpu_bo_free_kernel(&mem_ctx->shared_bo, &mem_ctx->shared_mc_addr,
+ &mem_ctx->shared_buf);
+}
+
+static int psp_xgmi_init_shared_buf(struct psp_context *psp)
+{
+ return psp_ta_init_shared_buf(psp, &psp->xgmi_context.context.mem_context,
+ PSP_XGMI_SHARED_MEM_SIZE);
+}
+
static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd,
uint32_t ta_cmd_id,
uint32_t session_id)
@@ -865,18 +944,14 @@ static int psp_ta_invoke(struct psp_context *psp,
uint32_t session_id)
{
int ret;
- struct psp_gfx_cmd_resp *cmd;
-
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_invoke_cmd_buf(cmd, ta_cmd_id, session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -890,27 +965,25 @@ static int psp_xgmi_load(struct psp_context *psp)
* TODO: bypass the loading in sriov for now
*/
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
- psp_copy_fw(psp, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size);
+ psp_copy_fw(psp, psp->xgmi.start_addr, psp->xgmi.size_bytes);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
- psp->ta_xgmi_ucode_size,
- psp->xgmi_context.xgmi_shared_mc_addr,
+ psp->xgmi.size_bytes,
+ psp->xgmi_context.context.mem_context.shared_mc_addr,
PSP_XGMI_SHARED_MEM_SIZE);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
if (!ret) {
- psp->xgmi_context.initialized = 1;
- psp->xgmi_context.session_id = cmd->resp.session_id;
+ psp->xgmi_context.context.initialized = true;
+ psp->xgmi_context.context.session_id = cmd->resp.session_id;
}
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -930,57 +1003,56 @@ static int psp_xgmi_unload(struct psp_context *psp)
* TODO: bypass the unloading in sriov for now
*/
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
- psp_prep_ta_unload_cmd_buf(cmd, psp->xgmi_context.session_id);
+ psp_prep_ta_unload_cmd_buf(cmd, psp->xgmi_context.context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
{
- return psp_ta_invoke(psp, ta_cmd_id, psp->xgmi_context.session_id);
+ return psp_ta_invoke(psp, ta_cmd_id, psp->xgmi_context.context.session_id);
}
int psp_xgmi_terminate(struct psp_context *psp)
{
int ret;
- if (!psp->xgmi_context.initialized)
+ if (!psp->xgmi_context.context.initialized)
return 0;
ret = psp_xgmi_unload(psp);
if (ret)
return ret;
- psp->xgmi_context.initialized = 0;
+ psp->xgmi_context.context.initialized = false;
/* free xgmi shared memory */
- amdgpu_bo_free_kernel(&psp->xgmi_context.xgmi_shared_bo,
- &psp->xgmi_context.xgmi_shared_mc_addr,
- &psp->xgmi_context.xgmi_shared_buf);
+ psp_ta_free_shared_buf(&psp->xgmi_context.context.mem_context);
return 0;
}
-int psp_xgmi_initialize(struct psp_context *psp)
+int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta)
{
struct ta_xgmi_shared_memory *xgmi_cmd;
int ret;
- if (!psp->adev->psp.ta_fw ||
- !psp->adev->psp.ta_xgmi_ucode_size ||
- !psp->adev->psp.ta_xgmi_start_addr)
+ if (!psp->ta_fw ||
+ !psp->xgmi.size_bytes ||
+ !psp->xgmi.start_addr)
return -ENOENT;
- if (!psp->xgmi_context.initialized) {
+ if (!load_ta)
+ goto invoke;
+
+ if (!psp->xgmi_context.context.initialized) {
ret = psp_xgmi_init_shared_buf(psp);
if (ret)
return ret;
@@ -991,9 +1063,11 @@ int psp_xgmi_initialize(struct psp_context *psp)
if (ret)
return ret;
+invoke:
/* Initialize XGMI session */
- xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.xgmi_shared_buf);
+ xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.context.mem_context.shared_buf);
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
+ xgmi_cmd->flag_extend_link_record = set_extended_data;
xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE;
ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id);
@@ -1006,7 +1080,7 @@ int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id)
struct ta_xgmi_shared_memory *xgmi_cmd;
int ret;
- xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf;
+ xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf;
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_HIVE_ID;
@@ -1026,7 +1100,7 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
struct ta_xgmi_shared_memory *xgmi_cmd;
int ret;
- xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf;
+ xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf;
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_NODE_ID;
@@ -1041,9 +1115,62 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
return 0;
}
+static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp)
+{
+ return psp->adev->asic_type == CHIP_ALDEBARAN &&
+ psp->xgmi.feature_version >= 0x2000000b;
+}
+
+/*
+ * Chips that support extended topology information require the driver to
+ * reflect topology information in the opposite direction. This is
+ * because the TA has already exceeded its link record limit and if the
+ * TA holds bi-directional information, the driver would have to do
+ * multiple fetches instead of just two.
+ */
+static void psp_xgmi_reflect_topology_info(struct psp_context *psp,
+ struct psp_xgmi_node_info node_info)
+{
+ struct amdgpu_device *mirror_adev;
+ struct amdgpu_hive_info *hive;
+ uint64_t src_node_id = psp->adev->gmc.xgmi.node_id;
+ uint64_t dst_node_id = node_info.node_id;
+ uint8_t dst_num_hops = node_info.num_hops;
+ uint8_t dst_num_links = node_info.num_links;
+
+ hive = amdgpu_get_xgmi_hive(psp->adev);
+ list_for_each_entry(mirror_adev, &hive->device_list, gmc.xgmi.head) {
+ struct psp_xgmi_topology_info *mirror_top_info;
+ int j;
+
+ if (mirror_adev->gmc.xgmi.node_id != dst_node_id)
+ continue;
+
+ mirror_top_info = &mirror_adev->psp.xgmi_context.top_info;
+ for (j = 0; j < mirror_top_info->num_nodes; j++) {
+ if (mirror_top_info->nodes[j].node_id != src_node_id)
+ continue;
+
+ mirror_top_info->nodes[j].num_hops = dst_num_hops;
+ /*
+ * prevent 0 num_links value re-reflection since reflection
+ * criteria is based on num_hops (direct or indirect).
+ *
+ */
+ if (dst_num_links)
+ mirror_top_info->nodes[j].num_links = dst_num_links;
+
+ break;
+ }
+
+ break;
+ }
+}
+
int psp_xgmi_get_topology_info(struct psp_context *psp,
int number_devices,
- struct psp_xgmi_topology_info *topology)
+ struct psp_xgmi_topology_info *topology,
+ bool get_extended_data)
{
struct ta_xgmi_shared_memory *xgmi_cmd;
struct ta_xgmi_cmd_get_topology_info_input *topology_info_input;
@@ -1054,8 +1181,9 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES)
return -EINVAL;
- xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf;
+ xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf;
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
+ xgmi_cmd->flag_extend_link_record = get_extended_data;
/* Fill in the shared memory with topology information as input */
topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info;
@@ -1078,10 +1206,45 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
topology_info_output = &xgmi_cmd->xgmi_out_message.get_topology_info;
topology->num_nodes = xgmi_cmd->xgmi_out_message.get_topology_info.num_nodes;
for (i = 0; i < topology->num_nodes; i++) {
- topology->nodes[i].node_id = topology_info_output->nodes[i].node_id;
- topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops;
- topology->nodes[i].is_sharing_enabled = topology_info_output->nodes[i].is_sharing_enabled;
- topology->nodes[i].sdma_engine = topology_info_output->nodes[i].sdma_engine;
+ /* extended data will either be 0 or equal to non-extended data */
+ if (topology_info_output->nodes[i].num_hops)
+ topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops;
+
+ /* non-extended data gets everything here so no need to update */
+ if (!get_extended_data) {
+ topology->nodes[i].node_id = topology_info_output->nodes[i].node_id;
+ topology->nodes[i].is_sharing_enabled =
+ topology_info_output->nodes[i].is_sharing_enabled;
+ topology->nodes[i].sdma_engine =
+ topology_info_output->nodes[i].sdma_engine;
+ }
+
+ }
+
+ /* Invoke xgmi ta again to get the link information */
+ if (psp_xgmi_peer_link_info_supported(psp)) {
+ struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output;
+
+ xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS;
+
+ ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_PEER_LINKS);
+
+ if (ret)
+ return ret;
+
+ link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info;
+ for (i = 0; i < topology->num_nodes; i++) {
+ /* accumulate num_links on extended data */
+ topology->nodes[i].num_links = get_extended_data ?
+ topology->nodes[i].num_links +
+ link_info_output->nodes[i].num_links :
+ link_info_output->nodes[i].num_links;
+
+ /* reflect the topology information for bi-directionality */
+ if (psp->xgmi_context.supports_extended_data &&
+ get_extended_data && topology->nodes[i].num_hops)
+ psp_xgmi_reflect_topology_info(psp, topology->nodes[i]);
+ }
}
return 0;
@@ -1098,7 +1261,7 @@ int psp_xgmi_set_topology_info(struct psp_context *psp,
if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES)
return -EINVAL;
- xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf;
+ xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf;
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info;
@@ -1119,19 +1282,8 @@ int psp_xgmi_set_topology_info(struct psp_context *psp,
// ras begin
static int psp_ras_init_shared_buf(struct psp_context *psp)
{
- int ret;
-
- /*
- * Allocate 16k memory aligned to 4k from Frame Buffer (local
- * physical) for ras ta <-> Driver
- */
- ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAS_SHARED_MEM_SIZE,
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
- &psp->ras.ras_shared_bo,
- &psp->ras.ras_shared_mc_addr,
- &psp->ras.ras_shared_buf);
-
- return ret;
+ return psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context,
+ PSP_RAS_SHARED_MEM_SIZE);
}
static int psp_ras_load(struct psp_context *psp)
@@ -1146,42 +1298,40 @@ static int psp_ras_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- psp_copy_fw(psp, psp->ta_ras_start_addr, psp->ta_ras_ucode_size);
+ psp_copy_fw(psp, psp->ras.start_addr, psp->ras.size_bytes);
- ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf;
+ ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
if (psp->adev->gmc.xgmi.connected_to_cpu)
ras_cmd->ras_in_message.init_flags.poison_mode_en = 1;
else
ras_cmd->ras_in_message.init_flags.dgpu_mode = 1;
+ cmd = acquire_psp_cmd_buf(psp);
+
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
- psp->ta_ras_ucode_size,
- psp->ras.ras_shared_mc_addr,
+ psp->ras.size_bytes,
+ psp->ras_context.context.mem_context.shared_mc_addr,
PSP_RAS_SHARED_MEM_SIZE);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
if (!ret) {
- psp->ras.session_id = cmd->resp.session_id;
+ psp->ras_context.context.session_id = cmd->resp.session_id;
if (!ras_cmd->ras_status)
- psp->ras.ras_initialized = true;
+ psp->ras_context.context.initialized = true;
else
dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status);
}
+ release_psp_cmd_buf(psp);
+
if (ret || ras_cmd->ras_status)
amdgpu_ras_fini(psp->adev);
- kfree(cmd);
-
return ret;
}
@@ -1196,16 +1346,14 @@ static int psp_ras_unload(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
- psp_prep_ta_unload_cmd_buf(cmd, psp->ras.session_id);
+ psp_prep_ta_unload_cmd_buf(cmd, psp->ras_context.context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -1215,7 +1363,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
struct ta_ras_shared_memory *ras_cmd;
int ret;
- ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf;
+ ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
/*
* TODO: bypass the loading in sriov for now
@@ -1223,7 +1371,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- ret = psp_ta_invoke(psp, ta_cmd_id, psp->ras.session_id);
+ ret = psp_ta_invoke(psp, ta_cmd_id, psp->ras_context.context.session_id);
if (amdgpu_ras_intr_triggered())
return ret;
@@ -1279,10 +1427,10 @@ int psp_ras_enable_features(struct psp_context *psp,
struct ta_ras_shared_memory *ras_cmd;
int ret;
- if (!psp->ras.ras_initialized)
+ if (!psp->ras_context.context.initialized)
return -EINVAL;
- ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf;
+ ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
if (enable)
@@ -1309,19 +1457,17 @@ static int psp_ras_terminate(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- if (!psp->ras.ras_initialized)
+ if (!psp->ras_context.context.initialized)
return 0;
ret = psp_ras_unload(psp);
if (ret)
return ret;
- psp->ras.ras_initialized = false;
+ psp->ras_context.context.initialized = false;
/* free ras shared memory */
- amdgpu_bo_free_kernel(&psp->ras.ras_shared_bo,
- &psp->ras.ras_shared_mc_addr,
- &psp->ras.ras_shared_buf);
+ psp_ta_free_shared_buf(&psp->ras_context.context.mem_context);
return 0;
}
@@ -1338,8 +1484,8 @@ static int psp_ras_initialize(struct psp_context *psp)
if (amdgpu_sriov_vf(adev))
return 0;
- if (!adev->psp.ta_ras_ucode_size ||
- !adev->psp.ta_ras_start_addr) {
+ if (!adev->psp.ras.size_bytes ||
+ !adev->psp.ras.start_addr) {
dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n");
return 0;
}
@@ -1385,7 +1531,7 @@ static int psp_ras_initialize(struct psp_context *psp)
}
}
- if (!psp->ras.ras_initialized) {
+ if (!psp->ras_context.context.initialized) {
ret = psp_ras_init_shared_buf(psp);
if (ret)
return ret;
@@ -1404,10 +1550,10 @@ int psp_ras_trigger_error(struct psp_context *psp,
struct ta_ras_shared_memory *ras_cmd;
int ret;
- if (!psp->ras.ras_initialized)
+ if (!psp->ras_context.context.initialized)
return -EINVAL;
- ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf;
+ ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
ras_cmd->cmd_id = TA_RAS_COMMAND__TRIGGER_ERROR;
@@ -1429,19 +1575,8 @@ int psp_ras_trigger_error(struct psp_context *psp,
// HDCP start
static int psp_hdcp_init_shared_buf(struct psp_context *psp)
{
- int ret;
-
- /*
- * Allocate 16k memory aligned to 4k from Frame Buffer (local
- * physical) for hdcp ta <-> Driver
- */
- ret = amdgpu_bo_create_kernel(psp->adev, PSP_HDCP_SHARED_MEM_SIZE,
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
- &psp->hdcp_context.hdcp_shared_bo,
- &psp->hdcp_context.hdcp_shared_mc_addr,
- &psp->hdcp_context.hdcp_shared_buf);
-
- return ret;
+ return psp_ta_init_shared_buf(psp, &psp->hdcp_context.context.mem_context,
+ PSP_HDCP_SHARED_MEM_SIZE);
}
static int psp_hdcp_load(struct psp_context *psp)
@@ -1455,28 +1590,26 @@ static int psp_hdcp_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ psp_copy_fw(psp, psp->hdcp.start_addr,
+ psp->hdcp.size_bytes);
- psp_copy_fw(psp, psp->ta_hdcp_start_addr,
- psp->ta_hdcp_ucode_size);
+ cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
- psp->ta_hdcp_ucode_size,
- psp->hdcp_context.hdcp_shared_mc_addr,
+ psp->hdcp.size_bytes,
+ psp->hdcp_context.context.mem_context.shared_mc_addr,
PSP_HDCP_SHARED_MEM_SIZE);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
if (!ret) {
- psp->hdcp_context.hdcp_initialized = true;
- psp->hdcp_context.session_id = cmd->resp.session_id;
+ psp->hdcp_context.context.initialized = true;
+ psp->hdcp_context.context.session_id = cmd->resp.session_id;
mutex_init(&psp->hdcp_context.mutex);
}
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -1490,13 +1623,13 @@ static int psp_hdcp_initialize(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- if (!psp->adev->psp.ta_hdcp_ucode_size ||
- !psp->adev->psp.ta_hdcp_start_addr) {
+ if (!psp->hdcp.size_bytes ||
+ !psp->hdcp.start_addr) {
dev_info(psp->adev->dev, "HDCP: optional hdcp ta ucode is not available\n");
return 0;
}
- if (!psp->hdcp_context.hdcp_initialized) {
+ if (!psp->hdcp_context.context.initialized) {
ret = psp_hdcp_init_shared_buf(psp);
if (ret)
return ret;
@@ -1520,15 +1653,13 @@ static int psp_hdcp_unload(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
- psp_prep_ta_unload_cmd_buf(cmd, psp->hdcp_context.session_id);
+ psp_prep_ta_unload_cmd_buf(cmd, psp->hdcp_context.context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -1541,7 +1672,7 @@ int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- return psp_ta_invoke(psp, ta_cmd_id, psp->hdcp_context.session_id);
+ return psp_ta_invoke(psp, ta_cmd_id, psp->hdcp_context.context.session_id);
}
static int psp_hdcp_terminate(struct psp_context *psp)
@@ -1554,8 +1685,8 @@ static int psp_hdcp_terminate(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- if (!psp->hdcp_context.hdcp_initialized) {
- if (psp->hdcp_context.hdcp_shared_buf)
+ if (!psp->hdcp_context.context.initialized) {
+ if (psp->hdcp_context.context.mem_context.shared_buf)
goto out;
else
return 0;
@@ -1565,13 +1696,11 @@ static int psp_hdcp_terminate(struct psp_context *psp)
if (ret)
return ret;
- psp->hdcp_context.hdcp_initialized = false;
+ psp->hdcp_context.context.initialized = false;
out:
/* free hdcp shared memory */
- amdgpu_bo_free_kernel(&psp->hdcp_context.hdcp_shared_bo,
- &psp->hdcp_context.hdcp_shared_mc_addr,
- &psp->hdcp_context.hdcp_shared_buf);
+ psp_ta_free_shared_buf(&psp->hdcp_context.context.mem_context);
return 0;
}
@@ -1580,19 +1709,8 @@ out:
// DTM start
static int psp_dtm_init_shared_buf(struct psp_context *psp)
{
- int ret;
-
- /*
- * Allocate 16k memory aligned to 4k from Frame Buffer (local
- * physical) for dtm ta <-> Driver
- */
- ret = amdgpu_bo_create_kernel(psp->adev, PSP_DTM_SHARED_MEM_SIZE,
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
- &psp->dtm_context.dtm_shared_bo,
- &psp->dtm_context.dtm_shared_mc_addr,
- &psp->dtm_context.dtm_shared_buf);
-
- return ret;
+ return psp_ta_init_shared_buf(psp, &psp->dtm_context.context.mem_context,
+ PSP_DTM_SHARED_MEM_SIZE);
}
static int psp_dtm_load(struct psp_context *psp)
@@ -1606,27 +1724,25 @@ static int psp_dtm_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ psp_copy_fw(psp, psp->dtm.start_addr, psp->dtm.size_bytes);
- psp_copy_fw(psp, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size);
+ cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
- psp->ta_dtm_ucode_size,
- psp->dtm_context.dtm_shared_mc_addr,
+ psp->dtm.size_bytes,
+ psp->dtm_context.context.mem_context.shared_mc_addr,
PSP_DTM_SHARED_MEM_SIZE);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
if (!ret) {
- psp->dtm_context.dtm_initialized = true;
- psp->dtm_context.session_id = cmd->resp.session_id;
+ psp->dtm_context.context.initialized = true;
+ psp->dtm_context.context.session_id = cmd->resp.session_id;
mutex_init(&psp->dtm_context.mutex);
}
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -1641,13 +1757,13 @@ static int psp_dtm_initialize(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- if (!psp->adev->psp.ta_dtm_ucode_size ||
- !psp->adev->psp.ta_dtm_start_addr) {
+ if (!psp->dtm.size_bytes ||
+ !psp->dtm.start_addr) {
dev_info(psp->adev->dev, "DTM: optional dtm ta ucode is not available\n");
return 0;
}
- if (!psp->dtm_context.dtm_initialized) {
+ if (!psp->dtm_context.context.initialized) {
ret = psp_dtm_init_shared_buf(psp);
if (ret)
return ret;
@@ -1671,15 +1787,13 @@ static int psp_dtm_unload(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ cmd = acquire_psp_cmd_buf(psp);
- psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.session_id);
+ psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -1692,7 +1806,7 @@ int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- return psp_ta_invoke(psp, ta_cmd_id, psp->dtm_context.session_id);
+ return psp_ta_invoke(psp, ta_cmd_id, psp->dtm_context.context.session_id);
}
static int psp_dtm_terminate(struct psp_context *psp)
@@ -1705,8 +1819,8 @@ static int psp_dtm_terminate(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- if (!psp->dtm_context.dtm_initialized) {
- if (psp->dtm_context.dtm_shared_buf)
+ if (!psp->dtm_context.context.initialized) {
+ if (psp->dtm_context.context.mem_context.shared_buf)
goto out;
else
return 0;
@@ -1716,13 +1830,11 @@ static int psp_dtm_terminate(struct psp_context *psp)
if (ret)
return ret;
- psp->dtm_context.dtm_initialized = false;
+ psp->dtm_context.context.initialized = false;
out:
- /* free hdcp shared memory */
- amdgpu_bo_free_kernel(&psp->dtm_context.dtm_shared_bo,
- &psp->dtm_context.dtm_shared_mc_addr,
- &psp->dtm_context.dtm_shared_buf);
+ /* free dtm shared memory */
+ psp_ta_free_shared_buf(&psp->dtm_context.context.mem_context);
return 0;
}
@@ -1731,19 +1843,8 @@ out:
// RAP start
static int psp_rap_init_shared_buf(struct psp_context *psp)
{
- int ret;
-
- /*
- * Allocate 16k memory aligned to 4k from Frame Buffer (local
- * physical) for rap ta <-> Driver
- */
- ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAP_SHARED_MEM_SIZE,
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
- &psp->rap_context.rap_shared_bo,
- &psp->rap_context.rap_shared_mc_addr,
- &psp->rap_context.rap_shared_buf);
-
- return ret;
+ return psp_ta_init_shared_buf(psp, &psp->rap_context.context.mem_context,
+ PSP_RAP_SHARED_MEM_SIZE);
}
static int psp_rap_load(struct psp_context *psp)
@@ -1751,27 +1852,25 @@ static int psp_rap_load(struct psp_context *psp)
int ret;
struct psp_gfx_cmd_resp *cmd;
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ psp_copy_fw(psp, psp->rap.start_addr, psp->rap.size_bytes);
- psp_copy_fw(psp, psp->ta_rap_start_addr, psp->ta_rap_ucode_size);
+ cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
- psp->ta_rap_ucode_size,
- psp->rap_context.rap_shared_mc_addr,
+ psp->rap.size_bytes,
+ psp->rap_context.context.mem_context.shared_mc_addr,
PSP_RAP_SHARED_MEM_SIZE);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
if (!ret) {
- psp->rap_context.rap_initialized = true;
- psp->rap_context.session_id = cmd->resp.session_id;
+ psp->rap_context.context.initialized = true;
+ psp->rap_context.context.session_id = cmd->resp.session_id;
mutex_init(&psp->rap_context.mutex);
}
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -1779,17 +1878,13 @@ static int psp_rap_load(struct psp_context *psp)
static int psp_rap_unload(struct psp_context *psp)
{
int ret;
- struct psp_gfx_cmd_resp *cmd;
+ struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.session_id);
+ psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -1805,13 +1900,13 @@ static int psp_rap_initialize(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- if (!psp->adev->psp.ta_rap_ucode_size ||
- !psp->adev->psp.ta_rap_start_addr) {
+ if (!psp->rap.size_bytes ||
+ !psp->rap.start_addr) {
dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n");
return 0;
}
- if (!psp->rap_context.rap_initialized) {
+ if (!psp->rap_context.context.initialized) {
ret = psp_rap_init_shared_buf(psp);
if (ret)
return ret;
@@ -1825,11 +1920,9 @@ static int psp_rap_initialize(struct psp_context *psp)
if (ret || status != TA_RAP_STATUS__SUCCESS) {
psp_rap_unload(psp);
- amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo,
- &psp->rap_context.rap_shared_mc_addr,
- &psp->rap_context.rap_shared_buf);
+ psp_ta_free_shared_buf(&psp->rap_context.context.mem_context);
- psp->rap_context.rap_initialized = false;
+ psp->rap_context.context.initialized = false;
dev_warn(psp->adev->dev, "RAP TA initialize fail (%d) status %d.\n",
ret, status);
@@ -1844,17 +1937,15 @@ static int psp_rap_terminate(struct psp_context *psp)
{
int ret;
- if (!psp->rap_context.rap_initialized)
+ if (!psp->rap_context.context.initialized)
return 0;
ret = psp_rap_unload(psp);
- psp->rap_context.rap_initialized = false;
+ psp->rap_context.context.initialized = false;
/* free rap shared memory */
- amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo,
- &psp->rap_context.rap_shared_mc_addr,
- &psp->rap_context.rap_shared_buf);
+ psp_ta_free_shared_buf(&psp->rap_context.context.mem_context);
return ret;
}
@@ -1864,7 +1955,7 @@ int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_stat
struct ta_rap_shared_memory *rap_cmd;
int ret = 0;
- if (!psp->rap_context.rap_initialized)
+ if (!psp->rap_context.context.initialized)
return 0;
if (ta_cmd_id != TA_CMD_RAP__INITIALIZE &&
@@ -1874,13 +1965,13 @@ int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_stat
mutex_lock(&psp->rap_context.mutex);
rap_cmd = (struct ta_rap_shared_memory *)
- psp->rap_context.rap_shared_buf;
+ psp->rap_context.context.mem_context.shared_buf;
memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory));
rap_cmd->cmd_id = ta_cmd_id;
rap_cmd->validation_method_id = METHOD_A;
- ret = psp_ta_invoke(psp, rap_cmd->cmd_id, psp->rap_context.session_id);
+ ret = psp_ta_invoke(psp, rap_cmd->cmd_id, psp->rap_context.context.session_id);
if (ret)
goto out_unlock;
@@ -1897,67 +1988,48 @@ out_unlock:
/* securedisplay start */
static int psp_securedisplay_init_shared_buf(struct psp_context *psp)
{
- int ret;
-
- /*
- * Allocate 16k memory aligned to 4k from Frame Buffer (local
- * physical) for sa ta <-> Driver
- */
- ret = amdgpu_bo_create_kernel(psp->adev, PSP_SECUREDISPLAY_SHARED_MEM_SIZE,
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
- &psp->securedisplay_context.securedisplay_shared_bo,
- &psp->securedisplay_context.securedisplay_shared_mc_addr,
- &psp->securedisplay_context.securedisplay_shared_buf);
-
- return ret;
+ return psp_ta_init_shared_buf(
+ psp, &psp->securedisplay_context.context.mem_context,
+ PSP_SECUREDISPLAY_SHARED_MEM_SIZE);
}
static int psp_securedisplay_load(struct psp_context *psp)
{
int ret;
- struct psp_gfx_cmd_resp *cmd;
-
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
- memcpy(psp->fw_pri_buf, psp->ta_securedisplay_start_addr, psp->ta_securedisplay_ucode_size);
+ memcpy(psp->fw_pri_buf, psp->securedisplay.start_addr, psp->securedisplay.size_bytes);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
- psp->ta_securedisplay_ucode_size,
- psp->securedisplay_context.securedisplay_shared_mc_addr,
+ psp->securedisplay.size_bytes,
+ psp->securedisplay_context.context.mem_context.shared_mc_addr,
PSP_SECUREDISPLAY_SHARED_MEM_SIZE);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
- if (ret)
- goto failed;
+ if (!ret) {
+ psp->securedisplay_context.context.initialized = true;
+ psp->securedisplay_context.context.session_id = cmd->resp.session_id;
+ mutex_init(&psp->securedisplay_context.mutex);
+ }
- psp->securedisplay_context.securedisplay_initialized = true;
- psp->securedisplay_context.session_id = cmd->resp.session_id;
- mutex_init(&psp->securedisplay_context.mutex);
+ release_psp_cmd_buf(psp);
-failed:
- kfree(cmd);
return ret;
}
static int psp_securedisplay_unload(struct psp_context *psp)
{
int ret;
- struct psp_gfx_cmd_resp *cmd;
-
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
- psp_prep_ta_unload_cmd_buf(cmd, psp->securedisplay_context.session_id);
+ psp_prep_ta_unload_cmd_buf(cmd, psp->securedisplay_context.context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
- kfree(cmd);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -1973,13 +2045,13 @@ static int psp_securedisplay_initialize(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- if (!psp->adev->psp.ta_securedisplay_ucode_size ||
- !psp->adev->psp.ta_securedisplay_start_addr) {
+ if (!psp->securedisplay.size_bytes ||
+ !psp->securedisplay.start_addr) {
dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n");
return 0;
}
- if (!psp->securedisplay_context.securedisplay_initialized) {
+ if (!psp->securedisplay_context.context.initialized) {
ret = psp_securedisplay_init_shared_buf(psp);
if (ret)
return ret;
@@ -1996,11 +2068,9 @@ static int psp_securedisplay_initialize(struct psp_context *psp)
if (ret) {
psp_securedisplay_unload(psp);
- amdgpu_bo_free_kernel(&psp->securedisplay_context.securedisplay_shared_bo,
- &psp->securedisplay_context.securedisplay_shared_mc_addr,
- &psp->securedisplay_context.securedisplay_shared_buf);
+ psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context);
- psp->securedisplay_context.securedisplay_initialized = false;
+ psp->securedisplay_context.context.initialized = false;
dev_err(psp->adev->dev, "SECUREDISPLAY TA initialize fail.\n");
return -EINVAL;
@@ -2025,19 +2095,17 @@ static int psp_securedisplay_terminate(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
- if (!psp->securedisplay_context.securedisplay_initialized)
+ if (!psp->securedisplay_context.context.initialized)
return 0;
ret = psp_securedisplay_unload(psp);
if (ret)
return ret;
- psp->securedisplay_context.securedisplay_initialized = false;
+ psp->securedisplay_context.context.initialized = false;
/* free securedisplay shared memory */
- amdgpu_bo_free_kernel(&psp->securedisplay_context.securedisplay_shared_bo,
- &psp->securedisplay_context.securedisplay_shared_mc_addr,
- &psp->securedisplay_context.securedisplay_shared_buf);
+ psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context);
return ret;
}
@@ -2046,7 +2114,7 @@ int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
{
int ret;
- if (!psp->securedisplay_context.securedisplay_initialized)
+ if (!psp->securedisplay_context.context.initialized)
return -EINVAL;
if (ta_cmd_id != TA_SECUREDISPLAY_COMMAND__QUERY_TA &&
@@ -2055,7 +2123,7 @@ int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
mutex_lock(&psp->securedisplay_context.mutex);
- ret = psp_ta_invoke(psp, ta_cmd_id, psp->securedisplay_context.session_id);
+ ret = psp_ta_invoke(psp, ta_cmd_id, psp->securedisplay_context.context.session_id);
mutex_unlock(&psp->securedisplay_context.mutex);
@@ -2069,7 +2137,7 @@ static int psp_hw_start(struct psp_context *psp)
int ret;
if (!amdgpu_sriov_vf(adev)) {
- if (psp->kdb_bin_size &&
+ if ((is_psp_fw_valid(psp->kdb)) &&
(psp->funcs->bootloader_load_kdb != NULL)) {
ret = psp_bootloader_load_kdb(psp);
if (ret) {
@@ -2078,7 +2146,8 @@ static int psp_hw_start(struct psp_context *psp)
}
}
- if (psp->spl_bin_size) {
+ if ((is_psp_fw_valid(psp->spl)) &&
+ (psp->funcs->bootloader_load_spl != NULL)) {
ret = psp_bootloader_load_spl(psp);
if (ret) {
DRM_ERROR("PSP load spl failed!\n");
@@ -2086,16 +2155,49 @@ static int psp_hw_start(struct psp_context *psp)
}
}
- ret = psp_bootloader_load_sysdrv(psp);
- if (ret) {
- DRM_ERROR("PSP load sysdrv failed!\n");
- return ret;
+ if ((is_psp_fw_valid(psp->sys)) &&
+ (psp->funcs->bootloader_load_sysdrv != NULL)) {
+ ret = psp_bootloader_load_sysdrv(psp);
+ if (ret) {
+ DRM_ERROR("PSP load sys drv failed!\n");
+ return ret;
+ }
}
- ret = psp_bootloader_load_sos(psp);
- if (ret) {
- DRM_ERROR("PSP load sos failed!\n");
- return ret;
+ if ((is_psp_fw_valid(psp->soc_drv)) &&
+ (psp->funcs->bootloader_load_soc_drv != NULL)) {
+ ret = psp_bootloader_load_soc_drv(psp);
+ if (ret) {
+ DRM_ERROR("PSP load soc drv failed!\n");
+ return ret;
+ }
+ }
+
+ if ((is_psp_fw_valid(psp->intf_drv)) &&
+ (psp->funcs->bootloader_load_intf_drv != NULL)) {
+ ret = psp_bootloader_load_intf_drv(psp);
+ if (ret) {
+ DRM_ERROR("PSP load intf drv failed!\n");
+ return ret;
+ }
+ }
+
+ if ((is_psp_fw_valid(psp->dbg_drv)) &&
+ (psp->funcs->bootloader_load_dbg_drv != NULL)) {
+ ret = psp_bootloader_load_dbg_drv(psp);
+ if (ret) {
+ DRM_ERROR("PSP load dbg drv failed!\n");
+ return ret;
+ }
+ }
+
+ if ((is_psp_fw_valid(psp->sos)) &&
+ (psp->funcs->bootloader_load_sos != NULL)) {
+ ret = psp_bootloader_load_sos(psp);
+ if (ret) {
+ DRM_ERROR("PSP load sos failed!\n");
+ return ret;
+ }
}
}
@@ -2299,8 +2401,6 @@ static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
int ret;
uint64_t fw_mem_mc_addr = ucode->mc_addr;
- memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
-
cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
@@ -2313,17 +2413,19 @@ static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
return ret;
}
-static int psp_execute_np_fw_load(struct psp_context *psp,
+static int psp_execute_non_psp_fw_load(struct psp_context *psp,
struct amdgpu_firmware_info *ucode)
{
int ret = 0;
+ struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
- ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd);
- if (ret)
- return ret;
+ ret = psp_prep_load_ip_fw_cmd_buf(ucode, cmd);
+ if (!ret) {
+ ret = psp_cmd_submit_buf(psp, ucode, cmd,
+ psp->fence_buf_mc_addr);
+ }
- ret = psp_cmd_submit_buf(psp, ucode, psp->cmd,
- psp->fence_buf_mc_addr);
+ release_psp_cmd_buf(psp);
return ret;
}
@@ -2334,7 +2436,7 @@ static int psp_load_smu_fw(struct psp_context *psp)
struct amdgpu_device *adev = psp->adev;
struct amdgpu_firmware_info *ucode =
&adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
- struct amdgpu_ras *ras = psp->ras.ras;
+ struct amdgpu_ras *ras = psp->ras_context.ras;
if (!ucode->fw || amdgpu_sriov_vf(psp->adev))
return 0;
@@ -2349,7 +2451,7 @@ static int psp_load_smu_fw(struct psp_context *psp)
}
}
- ret = psp_execute_np_fw_load(psp, ucode);
+ ret = psp_execute_non_psp_fw_load(psp, ucode);
if (ret)
DRM_ERROR("PSP load smu failed!\n");
@@ -2404,14 +2506,14 @@ int psp_load_fw_list(struct psp_context *psp,
for (i = 0; i < ucode_count; ++i) {
ucode = ucode_list[i];
psp_print_fw_hdr(psp, ucode);
- ret = psp_execute_np_fw_load(psp, ucode);
+ ret = psp_execute_non_psp_fw_load(psp, ucode);
if (ret)
return ret;
}
return ret;
}
-static int psp_np_fw_load(struct psp_context *psp)
+static int psp_load_non_psp_fw(struct psp_context *psp)
{
int i, ret;
struct amdgpu_firmware_info *ucode;
@@ -2450,7 +2552,7 @@ static int psp_np_fw_load(struct psp_context *psp)
psp_print_fw_hdr(psp, ucode);
- ret = psp_execute_np_fw_load(psp, ucode);
+ ret = psp_execute_non_psp_fw_load(psp, ucode);
if (ret)
return ret;
@@ -2478,10 +2580,6 @@ static int psp_load_fw(struct amdgpu_device *adev)
goto skip_memalloc;
}
- psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!psp->cmd)
- return -ENOMEM;
-
if (amdgpu_sriov_vf(adev)) {
ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG,
AMDGPU_GEM_DOMAIN_VRAM,
@@ -2527,7 +2625,7 @@ skip_memalloc:
if (ret)
goto failed;
- ret = psp_np_fw_load(psp);
+ ret = psp_load_non_psp_fw(psp);
if (ret)
goto failed;
@@ -2543,7 +2641,7 @@ skip_memalloc:
return ret;
}
- if (psp->adev->psp.ta_fw) {
+ if (psp->ta_fw) {
ret = psp_ras_initialize(psp);
if (ret)
dev_err(psp->adev->dev,
@@ -2615,7 +2713,7 @@ static int psp_hw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct psp_context *psp = &adev->psp;
- if (psp->adev->psp.ta_fw) {
+ if (psp->ta_fw) {
psp_ras_terminate(psp);
psp_securedisplay_terminate(psp);
psp_rap_terminate(psp);
@@ -2635,9 +2733,6 @@ static int psp_hw_fini(void *handle)
amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr,
(void **)&psp->cmd_buf_mem);
- kfree(psp->cmd);
- psp->cmd = NULL;
-
return 0;
}
@@ -2648,7 +2743,7 @@ static int psp_suspend(void *handle)
struct psp_context *psp = &adev->psp;
if (adev->gmc.xgmi.num_physical_nodes > 1 &&
- psp->xgmi_context.initialized == 1) {
+ psp->xgmi_context.context.initialized) {
ret = psp_xgmi_terminate(psp);
if (ret) {
DRM_ERROR("Failed to terminate xgmi ta\n");
@@ -2656,7 +2751,7 @@ static int psp_suspend(void *handle)
}
}
- if (psp->adev->psp.ta_fw) {
+ if (psp->ta_fw) {
ret = psp_ras_terminate(psp);
if (ret) {
DRM_ERROR("Failed to terminate ras ta\n");
@@ -2727,7 +2822,7 @@ static int psp_resume(void *handle)
if (ret)
goto failed;
- ret = psp_np_fw_load(psp);
+ ret = psp_load_non_psp_fw(psp);
if (ret)
goto failed;
@@ -2738,7 +2833,7 @@ static int psp_resume(void *handle)
}
if (adev->gmc.xgmi.num_physical_nodes > 1) {
- ret = psp_xgmi_initialize(psp);
+ ret = psp_xgmi_initialize(psp, false, true);
/* Warning the XGMI seesion initialize failure
* Instead of stop driver initialization
*/
@@ -2747,7 +2842,7 @@ static int psp_resume(void *handle)
"XGMI: Failed to initialize XGMI session\n");
}
- if (psp->adev->psp.ta_fw) {
+ if (psp->ta_fw) {
ret = psp_ras_initialize(psp);
if (ret)
dev_err(psp->adev->dev,
@@ -2801,17 +2896,15 @@ int psp_gpu_reset(struct amdgpu_device *adev)
int psp_rlc_autoload_start(struct psp_context *psp)
{
int ret;
- struct psp_gfx_cmd_resp *cmd;
-
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC;
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
- kfree(cmd);
+
+ release_psp_cmd_buf(psp);
+
return ret;
}
@@ -2825,7 +2918,7 @@ int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx,
ucode.mc_addr = cmd_gpu_addr;
ucode.ucode_size = cmd_size;
- return psp_execute_np_fw_load(&adev->psp, &ucode);
+ return psp_execute_non_psp_fw_load(&adev->psp, &ucode);
}
int psp_ring_cmd_submit(struct psp_context *psp,
@@ -2901,10 +2994,10 @@ int psp_init_asd_microcode(struct psp_context *psp,
goto out;
asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data;
- adev->psp.asd_fw_version = le32_to_cpu(asd_hdr->header.ucode_version);
- adev->psp.asd_feature_version = le32_to_cpu(asd_hdr->sos.fw_version);
- adev->psp.asd_ucode_size = le32_to_cpu(asd_hdr->header.ucode_size_bytes);
- adev->psp.asd_start_addr = (uint8_t *)asd_hdr +
+ adev->psp.asd.fw_version = le32_to_cpu(asd_hdr->header.ucode_version);
+ adev->psp.asd.feature_version = le32_to_cpu(asd_hdr->sos.fw_version);
+ adev->psp.asd.size_bytes = le32_to_cpu(asd_hdr->header.ucode_size_bytes);
+ adev->psp.asd.start_addr = (uint8_t *)asd_hdr +
le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes);
return 0;
out:
@@ -2918,7 +3011,7 @@ int psp_init_toc_microcode(struct psp_context *psp,
const char *chip_name)
{
struct amdgpu_device *adev = psp->adev;
- char fw_name[30];
+ char fw_name[PSP_FW_NAME_LEN];
const struct psp_firmware_header_v1_0 *toc_hdr;
int err = 0;
@@ -2937,10 +3030,10 @@ int psp_init_toc_microcode(struct psp_context *psp,
goto out;
toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data;
- adev->psp.toc_fw_version = le32_to_cpu(toc_hdr->header.ucode_version);
- adev->psp.toc_feature_version = le32_to_cpu(toc_hdr->sos.fw_version);
- adev->psp.toc_bin_size = le32_to_cpu(toc_hdr->header.ucode_size_bytes);
- adev->psp.toc_start_addr = (uint8_t *)toc_hdr +
+ adev->psp.toc.fw_version = le32_to_cpu(toc_hdr->header.ucode_version);
+ adev->psp.toc.feature_version = le32_to_cpu(toc_hdr->sos.fw_version);
+ adev->psp.toc.size_bytes = le32_to_cpu(toc_hdr->header.ucode_size_bytes);
+ adev->psp.toc.start_addr = (uint8_t *)toc_hdr +
le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes);
return 0;
out:
@@ -2950,6 +3043,82 @@ out:
return err;
}
+static int parse_sos_bin_descriptor(struct psp_context *psp,
+ const struct psp_fw_bin_desc *desc,
+ const struct psp_firmware_header_v2_0 *sos_hdr)
+{
+ uint8_t *ucode_start_addr = NULL;
+
+ if (!psp || !desc || !sos_hdr)
+ return -EINVAL;
+
+ ucode_start_addr = (uint8_t *)sos_hdr +
+ le32_to_cpu(desc->offset_bytes) +
+ le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
+
+ switch (desc->fw_type) {
+ case PSP_FW_TYPE_PSP_SOS:
+ psp->sos.fw_version = le32_to_cpu(desc->fw_version);
+ psp->sos.feature_version = le32_to_cpu(desc->fw_version);
+ psp->sos.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->sos.start_addr = ucode_start_addr;
+ break;
+ case PSP_FW_TYPE_PSP_SYS_DRV:
+ psp->sys.fw_version = le32_to_cpu(desc->fw_version);
+ psp->sys.feature_version = le32_to_cpu(desc->fw_version);
+ psp->sys.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->sys.start_addr = ucode_start_addr;
+ break;
+ case PSP_FW_TYPE_PSP_KDB:
+ psp->kdb.fw_version = le32_to_cpu(desc->fw_version);
+ psp->kdb.feature_version = le32_to_cpu(desc->fw_version);
+ psp->kdb.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->kdb.start_addr = ucode_start_addr;
+ break;
+ case PSP_FW_TYPE_PSP_TOC:
+ psp->toc.fw_version = le32_to_cpu(desc->fw_version);
+ psp->toc.feature_version = le32_to_cpu(desc->fw_version);
+ psp->toc.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->toc.start_addr = ucode_start_addr;
+ break;
+ case PSP_FW_TYPE_PSP_SPL:
+ psp->spl.fw_version = le32_to_cpu(desc->fw_version);
+ psp->spl.feature_version = le32_to_cpu(desc->fw_version);
+ psp->spl.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->spl.start_addr = ucode_start_addr;
+ break;
+ case PSP_FW_TYPE_PSP_RL:
+ psp->rl.fw_version = le32_to_cpu(desc->fw_version);
+ psp->rl.feature_version = le32_to_cpu(desc->fw_version);
+ psp->rl.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->rl.start_addr = ucode_start_addr;
+ break;
+ case PSP_FW_TYPE_PSP_SOC_DRV:
+ psp->soc_drv.fw_version = le32_to_cpu(desc->fw_version);
+ psp->soc_drv.feature_version = le32_to_cpu(desc->fw_version);
+ psp->soc_drv.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->soc_drv.start_addr = ucode_start_addr;
+ break;
+ case PSP_FW_TYPE_PSP_INTF_DRV:
+ psp->intf_drv.fw_version = le32_to_cpu(desc->fw_version);
+ psp->intf_drv.feature_version = le32_to_cpu(desc->fw_version);
+ psp->intf_drv.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->intf_drv.start_addr = ucode_start_addr;
+ break;
+ case PSP_FW_TYPE_PSP_DBG_DRV:
+ psp->dbg_drv.fw_version = le32_to_cpu(desc->fw_version);
+ psp->dbg_drv.feature_version = le32_to_cpu(desc->fw_version);
+ psp->dbg_drv.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->dbg_drv.start_addr = ucode_start_addr;
+ break;
+ default:
+ dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type);
+ break;
+ }
+
+ return 0;
+}
+
static int psp_init_sos_base_fw(struct amdgpu_device *adev)
{
const struct psp_firmware_header_v1_0 *sos_hdr;
@@ -2961,32 +3130,34 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev)
le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
if (adev->gmc.xgmi.connected_to_cpu || (adev->asic_type != CHIP_ALDEBARAN)) {
- adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
- adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->sos.fw_version);
+ adev->psp.sos.fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
+ adev->psp.sos.feature_version = le32_to_cpu(sos_hdr->sos.fw_version);
- adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos.offset_bytes);
- adev->psp.sys_start_addr = ucode_array_start_addr;
+ adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr->sos.offset_bytes);
+ adev->psp.sys.start_addr = ucode_array_start_addr;
- adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos.size_bytes);
- adev->psp.sos_start_addr = ucode_array_start_addr +
+ adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes);
+ adev->psp.sos.start_addr = ucode_array_start_addr +
le32_to_cpu(sos_hdr->sos.offset_bytes);
+ adev->psp.xgmi_context.supports_extended_data = false;
} else {
/* Load alternate PSP SOS FW */
sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data;
- adev->psp.sos_fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
- adev->psp.sos_feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
+ adev->psp.sos.fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
+ adev->psp.sos.feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
- adev->psp.sys_bin_size = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes);
- adev->psp.sys_start_addr = ucode_array_start_addr +
+ adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes);
+ adev->psp.sys.start_addr = ucode_array_start_addr +
le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes);
- adev->psp.sos_bin_size = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes);
- adev->psp.sos_start_addr = ucode_array_start_addr +
+ adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes);
+ adev->psp.sos.start_addr = ucode_array_start_addr +
le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes);
+ adev->psp.xgmi_context.supports_extended_data = true;
}
- if ((adev->psp.sys_bin_size == 0) || (adev->psp.sos_bin_size == 0)) {
+ if ((adev->psp.sys.size_bytes == 0) || (adev->psp.sos.size_bytes == 0)) {
dev_warn(adev->dev, "PSP SOS FW not available");
return -EINVAL;
}
@@ -3003,8 +3174,10 @@ int psp_init_sos_microcode(struct psp_context *psp,
const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
const struct psp_firmware_header_v1_2 *sos_hdr_v1_2;
const struct psp_firmware_header_v1_3 *sos_hdr_v1_3;
+ const struct psp_firmware_header_v2_0 *sos_hdr_v2_0;
int err = 0;
uint8_t *ucode_array_start_addr;
+ int fw_index = 0;
if (!chip_name) {
dev_err(adev->dev, "invalid chip name for sos microcode\n");
@@ -3033,35 +3206,52 @@ int psp_init_sos_microcode(struct psp_context *psp,
if (sos_hdr->header.header_version_minor == 1) {
sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data;
- adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes);
- adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+ adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes);
+ adev->psp.toc.start_addr = (uint8_t *)adev->psp.sys.start_addr +
le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes);
- adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes);
- adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+ adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes);
+ adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr +
le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes);
}
if (sos_hdr->header.header_version_minor == 2) {
sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data;
- adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes);
- adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+ adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes);
+ adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr +
le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes);
}
if (sos_hdr->header.header_version_minor == 3) {
sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data;
- adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes);
- adev->psp.toc_start_addr = ucode_array_start_addr +
+ adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes);
+ adev->psp.toc.start_addr = ucode_array_start_addr +
le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes);
- adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes);
- adev->psp.kdb_start_addr = ucode_array_start_addr +
+ adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes);
+ adev->psp.kdb.start_addr = ucode_array_start_addr +
le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes);
- adev->psp.spl_bin_size = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes);
- adev->psp.spl_start_addr = ucode_array_start_addr +
+ adev->psp.spl.size_bytes = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes);
+ adev->psp.spl.start_addr = ucode_array_start_addr +
le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes);
- adev->psp.rl_bin_size = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes);
- adev->psp.rl_start_addr = ucode_array_start_addr +
+ adev->psp.rl.size_bytes = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes);
+ adev->psp.rl.start_addr = ucode_array_start_addr +
le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes);
}
break;
+ case 2:
+ sos_hdr_v2_0 = (const struct psp_firmware_header_v2_0 *)adev->psp.sos_fw->data;
+
+ if (le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
+ dev_err(adev->dev, "packed SOS count exceeds maximum limit\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ for (fw_index = 0; fw_index < le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count); fw_index++) {
+ err = parse_sos_bin_descriptor(psp,
+ &sos_hdr_v2_0->psp_fw_bin[fw_index],
+ sos_hdr_v2_0);
+ if (err)
+ goto out;
+ }
+ break;
default:
dev_err(adev->dev,
"unsupported psp sos firmware\n");
@@ -3080,7 +3270,7 @@ out:
}
static int parse_ta_bin_descriptor(struct psp_context *psp,
- const struct ta_fw_bin_desc *desc,
+ const struct psp_fw_bin_desc *desc,
const struct ta_firmware_header_v2_0 *ta_hdr)
{
uint8_t *ucode_start_addr = NULL;
@@ -3094,40 +3284,40 @@ static int parse_ta_bin_descriptor(struct psp_context *psp,
switch (desc->fw_type) {
case TA_FW_TYPE_PSP_ASD:
- psp->asd_fw_version = le32_to_cpu(desc->fw_version);
- psp->asd_feature_version = le32_to_cpu(desc->fw_version);
- psp->asd_ucode_size = le32_to_cpu(desc->size_bytes);
- psp->asd_start_addr = ucode_start_addr;
+ psp->asd.fw_version = le32_to_cpu(desc->fw_version);
+ psp->asd.feature_version = le32_to_cpu(desc->fw_version);
+ psp->asd.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->asd.start_addr = ucode_start_addr;
break;
case TA_FW_TYPE_PSP_XGMI:
- psp->ta_xgmi_ucode_version = le32_to_cpu(desc->fw_version);
- psp->ta_xgmi_ucode_size = le32_to_cpu(desc->size_bytes);
- psp->ta_xgmi_start_addr = ucode_start_addr;
+ psp->xgmi.feature_version = le32_to_cpu(desc->fw_version);
+ psp->xgmi.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->xgmi.start_addr = ucode_start_addr;
break;
case TA_FW_TYPE_PSP_RAS:
- psp->ta_ras_ucode_version = le32_to_cpu(desc->fw_version);
- psp->ta_ras_ucode_size = le32_to_cpu(desc->size_bytes);
- psp->ta_ras_start_addr = ucode_start_addr;
+ psp->ras.feature_version = le32_to_cpu(desc->fw_version);
+ psp->ras.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->ras.start_addr = ucode_start_addr;
break;
case TA_FW_TYPE_PSP_HDCP:
- psp->ta_hdcp_ucode_version = le32_to_cpu(desc->fw_version);
- psp->ta_hdcp_ucode_size = le32_to_cpu(desc->size_bytes);
- psp->ta_hdcp_start_addr = ucode_start_addr;
+ psp->hdcp.feature_version = le32_to_cpu(desc->fw_version);
+ psp->hdcp.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->hdcp.start_addr = ucode_start_addr;
break;
case TA_FW_TYPE_PSP_DTM:
- psp->ta_dtm_ucode_version = le32_to_cpu(desc->fw_version);
- psp->ta_dtm_ucode_size = le32_to_cpu(desc->size_bytes);
- psp->ta_dtm_start_addr = ucode_start_addr;
+ psp->dtm.feature_version = le32_to_cpu(desc->fw_version);
+ psp->dtm.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->dtm.start_addr = ucode_start_addr;
break;
case TA_FW_TYPE_PSP_RAP:
- psp->ta_rap_ucode_version = le32_to_cpu(desc->fw_version);
- psp->ta_rap_ucode_size = le32_to_cpu(desc->size_bytes);
- psp->ta_rap_start_addr = ucode_start_addr;
+ psp->rap.feature_version = le32_to_cpu(desc->fw_version);
+ psp->rap.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->rap.start_addr = ucode_start_addr;
break;
case TA_FW_TYPE_PSP_SECUREDISPLAY:
- psp->ta_securedisplay_ucode_version = le32_to_cpu(desc->fw_version);
- psp->ta_securedisplay_ucode_size = le32_to_cpu(desc->size_bytes);
- psp->ta_securedisplay_start_addr = ucode_start_addr;
+ psp->securedisplay.feature_version = le32_to_cpu(desc->fw_version);
+ psp->securedisplay.size_bytes = le32_to_cpu(desc->size_bytes);
+ psp->securedisplay.start_addr = ucode_start_addr;
break;
default:
dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type);
@@ -3168,7 +3358,7 @@ int psp_init_ta_microcode(struct psp_context *psp,
goto out;
}
- if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_TA_PACKAGING) {
+ if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
err = -EINVAL;
goto out;
@@ -3235,11 +3425,12 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
- void *cpu_addr;
- dma_addr_t dma_addr;
int ret, idx;
char fw_name[100];
const struct firmware *usbc_pd_fw;
+ struct amdgpu_bo *fw_buf_bo = NULL;
+ uint64_t fw_pri_mc_addr;
+ void *fw_pri_cpu_addr;
if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) {
DRM_INFO("PSP block is not ready yet.");
@@ -3254,31 +3445,24 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
if (ret)
goto fail;
- /* We need contiguous physical mem to place the FW for psp to access */
- cpu_addr = dma_alloc_coherent(adev->dev, usbc_pd_fw->size, &dma_addr, GFP_KERNEL);
-
- ret = dma_mapping_error(adev->dev, dma_addr);
+ /* LFB address which is aligned to 1MB boundary per PSP request */
+ ret = amdgpu_bo_create_kernel(adev, usbc_pd_fw->size, 0x100000,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &fw_buf_bo,
+ &fw_pri_mc_addr,
+ &fw_pri_cpu_addr);
if (ret)
goto rel_buf;
- memcpy_toio(cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size);
-
- /*
- * x86 specific workaround.
- * Without it the buffer is invisible in PSP.
- *
- * TODO Remove once PSP starts snooping CPU cache
- */
-#ifdef CONFIG_X86
- clflush_cache_range(cpu_addr, (usbc_pd_fw->size & ~(L1_CACHE_BYTES - 1)));
-#endif
+ memcpy_toio(fw_pri_cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size);
mutex_lock(&adev->psp.mutex);
- ret = psp_load_usbc_pd_fw(&adev->psp, dma_addr);
+ ret = psp_load_usbc_pd_fw(&adev->psp, fw_pri_mc_addr);
mutex_unlock(&adev->psp.mutex);
+ amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr);
+
rel_buf:
- dma_free_coherent(adev->dev, usbc_pd_fw->size, cpu_addr, dma_addr);
release_firmware(usbc_pd_fw);
fail:
if (ret) {
@@ -3307,7 +3491,10 @@ static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR,
psp_usbc_pd_fw_sysfs_read,
psp_usbc_pd_fw_sysfs_write);
-
+int is_psp_fw_valid(struct psp_bin_desc bin)
+{
+ return bin.size_bytes;
+}
const struct amd_ip_funcs psp_ip_funcs = {
.name = "psp",
@@ -3369,6 +3556,14 @@ const struct amdgpu_ip_block_version psp_v11_0_ip_block =
.funcs = &psp_ip_funcs,
};
+const struct amdgpu_ip_block_version psp_v11_0_8_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_PSP,
+ .major = 11,
+ .minor = 0,
+ .rev = 8,
+ .funcs = &psp_ip_funcs,
+};
+
const struct amdgpu_ip_block_version psp_v12_0_ip_block =
{
.type = AMD_IP_BLOCK_TYPE_PSP,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 3030ec24eb3b..8ef2d28af92a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -48,11 +48,15 @@
struct psp_context;
struct psp_xgmi_node_info;
struct psp_xgmi_topology_info;
+struct psp_bin_desc;
enum psp_bootloader_cmd {
PSP_BL__LOAD_SYSDRV = 0x10000,
PSP_BL__LOAD_SOSDRV = 0x20000,
PSP_BL__LOAD_KEY_DATABASE = 0x80000,
+ PSP_BL__LOAD_SOCDRV = 0xB0000,
+ PSP_BL__LOAD_INTFDRV = 0xC0000,
+ PSP_BL__LOAD_DBGDRV = 0xD0000,
PSP_BL__DRAM_LONG_TRAIN = 0x100000,
PSP_BL__DRAM_SHORT_TRAIN = 0x200000,
PSP_BL__LOAD_TOS_SPL_TABLE = 0x10000000,
@@ -93,6 +97,9 @@ struct psp_funcs
int (*bootloader_load_kdb)(struct psp_context *psp);
int (*bootloader_load_spl)(struct psp_context *psp);
int (*bootloader_load_sysdrv)(struct psp_context *psp);
+ int (*bootloader_load_soc_drv)(struct psp_context *psp);
+ int (*bootloader_load_intf_drv)(struct psp_context *psp);
+ int (*bootloader_load_dbg_drv)(struct psp_context *psp);
int (*bootloader_load_sos)(struct psp_context *psp);
int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type);
int (*ring_create)(struct psp_context *psp,
@@ -106,7 +113,7 @@ struct psp_funcs
int (*mem_training)(struct psp_context *psp, uint32_t ops);
uint32_t (*ring_get_wptr)(struct psp_context *psp);
void (*ring_set_wptr)(struct psp_context *psp, uint32_t value);
- int (*load_usbc_pd_fw)(struct psp_context *psp, dma_addr_t dma_addr);
+ int (*load_usbc_pd_fw)(struct psp_context *psp, uint64_t fw_pri_mc_addr);
int (*read_usbc_pd_fw)(struct psp_context *psp, uint32_t *fw_ver);
};
@@ -116,6 +123,7 @@ struct psp_xgmi_node_info {
uint8_t num_hops;
uint8_t is_sharing_enabled;
enum ta_xgmi_assigned_sdma_engine sdma_engine;
+ uint8_t num_links;
};
struct psp_xgmi_topology_info {
@@ -128,59 +136,32 @@ struct psp_asd_context {
uint32_t session_id;
};
-struct psp_xgmi_context {
- uint8_t initialized;
- uint32_t session_id;
- struct amdgpu_bo *xgmi_shared_bo;
- uint64_t xgmi_shared_mc_addr;
- void *xgmi_shared_buf;
- struct psp_xgmi_topology_info top_info;
-};
-
-struct psp_ras_context {
- /*ras fw*/
- bool ras_initialized;
- uint32_t session_id;
- struct amdgpu_bo *ras_shared_bo;
- uint64_t ras_shared_mc_addr;
- void *ras_shared_buf;
- struct amdgpu_ras *ras;
+struct ta_mem_context {
+ struct amdgpu_bo *shared_bo;
+ uint64_t shared_mc_addr;
+ void *shared_buf;
};
-struct psp_hdcp_context {
- bool hdcp_initialized;
+struct ta_context {
+ bool initialized;
uint32_t session_id;
- struct amdgpu_bo *hdcp_shared_bo;
- uint64_t hdcp_shared_mc_addr;
- void *hdcp_shared_buf;
- struct mutex mutex;
+ struct ta_mem_context mem_context;
};
-struct psp_dtm_context {
- bool dtm_initialized;
- uint32_t session_id;
- struct amdgpu_bo *dtm_shared_bo;
- uint64_t dtm_shared_mc_addr;
- void *dtm_shared_buf;
- struct mutex mutex;
+struct ta_cp_context {
+ struct ta_context context;
+ struct mutex mutex;
};
-struct psp_rap_context {
- bool rap_initialized;
- uint32_t session_id;
- struct amdgpu_bo *rap_shared_bo;
- uint64_t rap_shared_mc_addr;
- void *rap_shared_buf;
- struct mutex mutex;
+struct psp_xgmi_context {
+ struct ta_context context;
+ struct psp_xgmi_topology_info top_info;
+ bool supports_extended_data;
};
-struct psp_securedisplay_context {
- bool securedisplay_initialized;
- uint32_t session_id;
- struct amdgpu_bo *securedisplay_shared_bo;
- uint64_t securedisplay_shared_mc_addr;
- void *securedisplay_shared_buf;
- struct mutex mutex;
+struct psp_ras_context {
+ struct ta_context context;
+ struct amdgpu_ras *ras;
};
#define MEM_TRAIN_SYSTEM_SIGNATURE 0x54534942
@@ -282,6 +263,13 @@ struct psp_runtime_boot_cfg_entry {
uint32_t reserved;
};
+struct psp_bin_desc {
+ uint32_t fw_version;
+ uint32_t feature_version;
+ uint32_t size_bytes;
+ uint8_t *start_addr;
+};
+
struct psp_context
{
struct amdgpu_device *adev;
@@ -297,36 +285,26 @@ struct psp_context
/* sos firmware */
const struct firmware *sos_fw;
- uint32_t sos_fw_version;
- uint32_t sos_feature_version;
- uint32_t sys_bin_size;
- uint32_t sos_bin_size;
- uint32_t toc_bin_size;
- uint32_t kdb_bin_size;
- uint32_t spl_bin_size;
- uint32_t rl_bin_size;
- uint8_t *sys_start_addr;
- uint8_t *sos_start_addr;
- uint8_t *toc_start_addr;
- uint8_t *kdb_start_addr;
- uint8_t *spl_start_addr;
- uint8_t *rl_start_addr;
+ struct psp_bin_desc sys;
+ struct psp_bin_desc sos;
+ struct psp_bin_desc toc;
+ struct psp_bin_desc kdb;
+ struct psp_bin_desc spl;
+ struct psp_bin_desc rl;
+ struct psp_bin_desc soc_drv;
+ struct psp_bin_desc intf_drv;
+ struct psp_bin_desc dbg_drv;
/* tmr buffer */
struct amdgpu_bo *tmr_bo;
uint64_t tmr_mc_addr;
/* asd firmware */
- const struct firmware *asd_fw;
- uint32_t asd_fw_version;
- uint32_t asd_feature_version;
- uint32_t asd_ucode_size;
- uint8_t *asd_start_addr;
+ const struct firmware *asd_fw;
+ struct psp_bin_desc asd;
/* toc firmware */
const struct firmware *toc_fw;
- uint32_t toc_fw_version;
- uint32_t toc_feature_version;
/* fence buffer */
struct amdgpu_bo *fence_buf_bo;
@@ -348,36 +326,20 @@ struct psp_context
/* xgmi ta firmware and buffer */
const struct firmware *ta_fw;
uint32_t ta_fw_version;
- uint32_t ta_xgmi_ucode_version;
- uint32_t ta_xgmi_ucode_size;
- uint8_t *ta_xgmi_start_addr;
- uint32_t ta_ras_ucode_version;
- uint32_t ta_ras_ucode_size;
- uint8_t *ta_ras_start_addr;
-
- uint32_t ta_hdcp_ucode_version;
- uint32_t ta_hdcp_ucode_size;
- uint8_t *ta_hdcp_start_addr;
-
- uint32_t ta_dtm_ucode_version;
- uint32_t ta_dtm_ucode_size;
- uint8_t *ta_dtm_start_addr;
-
- uint32_t ta_rap_ucode_version;
- uint32_t ta_rap_ucode_size;
- uint8_t *ta_rap_start_addr;
-
- uint32_t ta_securedisplay_ucode_version;
- uint32_t ta_securedisplay_ucode_size;
- uint8_t *ta_securedisplay_start_addr;
+ struct psp_bin_desc xgmi;
+ struct psp_bin_desc ras;
+ struct psp_bin_desc hdcp;
+ struct psp_bin_desc dtm;
+ struct psp_bin_desc rap;
+ struct psp_bin_desc securedisplay;
struct psp_asd_context asd_context;
struct psp_xgmi_context xgmi_context;
- struct psp_ras_context ras;
- struct psp_hdcp_context hdcp_context;
- struct psp_dtm_context dtm_context;
- struct psp_rap_context rap_context;
- struct psp_securedisplay_context securedisplay_context;
+ struct psp_ras_context ras_context;
+ struct ta_cp_context hdcp_context;
+ struct ta_cp_context dtm_context;
+ struct ta_cp_context rap_context;
+ struct ta_cp_context securedisplay_context;
struct mutex mutex;
struct psp_memory_training_context mem_train_ctx;
@@ -402,6 +364,12 @@ struct amdgpu_psp_funcs {
((psp)->funcs->bootloader_load_spl ? (psp)->funcs->bootloader_load_spl((psp)) : 0)
#define psp_bootloader_load_sysdrv(psp) \
((psp)->funcs->bootloader_load_sysdrv ? (psp)->funcs->bootloader_load_sysdrv((psp)) : 0)
+#define psp_bootloader_load_soc_drv(psp) \
+ ((psp)->funcs->bootloader_load_soc_drv ? (psp)->funcs->bootloader_load_soc_drv((psp)) : 0)
+#define psp_bootloader_load_intf_drv(psp) \
+ ((psp)->funcs->bootloader_load_intf_drv ? (psp)->funcs->bootloader_load_intf_drv((psp)) : 0)
+#define psp_bootloader_load_dbg_drv(psp) \
+ ((psp)->funcs->bootloader_load_dbg_drv ? (psp)->funcs->bootloader_load_dbg_drv((psp)) : 0)
#define psp_bootloader_load_sos(psp) \
((psp)->funcs->bootloader_load_sos ? (psp)->funcs->bootloader_load_sos((psp)) : 0)
#define psp_smu_reload_quirk(psp) \
@@ -414,9 +382,9 @@ struct amdgpu_psp_funcs {
#define psp_ring_get_wptr(psp) (psp)->funcs->ring_get_wptr((psp))
#define psp_ring_set_wptr(psp, value) (psp)->funcs->ring_set_wptr((psp), (value))
-#define psp_load_usbc_pd_fw(psp, dma_addr) \
+#define psp_load_usbc_pd_fw(psp, fw_pri_mc_addr) \
((psp)->funcs->load_usbc_pd_fw ? \
- (psp)->funcs->load_usbc_pd_fw((psp), (dma_addr)) : -EINVAL)
+ (psp)->funcs->load_usbc_pd_fw((psp), (fw_pri_mc_addr)) : -EINVAL)
#define psp_read_usbc_pd_fw(psp, fw_ver) \
((psp)->funcs->read_usbc_pd_fw ? \
@@ -427,6 +395,7 @@ extern const struct amd_ip_funcs psp_ip_funcs;
extern const struct amdgpu_ip_block_version psp_v3_1_ip_block;
extern const struct amdgpu_ip_block_version psp_v10_0_ip_block;
extern const struct amdgpu_ip_block_version psp_v11_0_ip_block;
+extern const struct amdgpu_ip_block_version psp_v11_0_8_ip_block;
extern const struct amdgpu_ip_block_version psp_v12_0_ip_block;
extern const struct amdgpu_ip_block_version psp_v13_0_ip_block;
@@ -437,14 +406,15 @@ int psp_gpu_reset(struct amdgpu_device *adev);
int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx,
uint64_t cmd_gpu_addr, int cmd_size);
-int psp_xgmi_initialize(struct psp_context *psp);
+int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta);
int psp_xgmi_terminate(struct psp_context *psp);
int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id);
int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id);
int psp_xgmi_get_topology_info(struct psp_context *psp,
int number_devices,
- struct psp_xgmi_topology_info *topology);
+ struct psp_xgmi_topology_info *topology,
+ bool get_extended_data);
int psp_xgmi_set_topology_info(struct psp_context *psp,
int number_devices,
struct psp_xgmi_topology_info *topology);
@@ -483,4 +453,5 @@ int psp_load_fw_list(struct psp_context *psp,
struct amdgpu_firmware_info **ucode_list, int ucode_count);
void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
+int is_psp_fw_valid(struct psp_bin_desc bin);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c
index 51909bf8798c..12010c988c8b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c
@@ -76,7 +76,7 @@ static ssize_t amdgpu_rap_debugfs_write(struct file *f, const char __user *buf,
dev_info(adev->dev, "RAP L0 validate test success.\n");
} else {
rap_shared_mem = (struct ta_rap_shared_memory *)
- adev->psp.rap_context.rap_shared_buf;
+ adev->psp.rap_context.context.mem_context.shared_buf;
rap_cmd_output = &(rap_shared_mem->rap_out_message.output);
dev_info(adev->dev, "RAP test failed, the output is:\n");
@@ -119,7 +119,7 @@ void amdgpu_rap_debugfs_init(struct amdgpu_device *adev)
#if defined(CONFIG_DEBUG_FS)
struct drm_minor *minor = adev_to_drm(adev)->primary;
- if (!adev->psp.rap_context.rap_initialized)
+ if (!adev->psp.rap_context.context.initialized)
return;
debugfs_create_file("rap_test", S_IWUSR, minor->debugfs_root,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index fc66aca28594..96a8fd0ca1df 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -64,15 +64,14 @@ const char *ras_block_string[] = {
};
#define ras_err_str(i) (ras_error_string[ffs(i)])
-#define ras_block_str(i) (ras_block_string[i])
#define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS)
/* inject address is 52 bits */
#define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52)
-/* typical ECC bad page rate(1 bad page per 100MB VRAM) */
-#define RAS_BAD_PAGE_RATE (100 * 1024 * 1024ULL)
+/* typical ECC bad page rate is 1 bad page per 100MB VRAM */
+#define RAS_BAD_PAGE_COVER (100 * 1024 * 1024ULL)
enum amdgpu_ras_retire_page_reservation {
AMDGPU_RAS_RETIRE_PAGE_RESERVED,
@@ -355,8 +354,9 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
* to see which blocks support RAS on a particular asic.
*
*/
-static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *buf,
- size_t size, loff_t *pos)
+static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f,
+ const char __user *buf,
+ size_t size, loff_t *pos)
{
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
struct ras_debug_if data;
@@ -370,7 +370,7 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
ret = amdgpu_ras_debugfs_ctrl_parse_data(f, buf, size, pos, &data);
if (ret)
- return -EINVAL;
+ return ret;
if (data.op == 3) {
ret = amdgpu_reserve_page_direct(adev, data.inject.address);
@@ -403,9 +403,9 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
/* umc ce/ue error injection for a bad page is not allowed */
if ((data.head.block == AMDGPU_RAS_BLOCK__UMC) &&
amdgpu_ras_check_bad_page(adev, data.inject.address)) {
- dev_warn(adev->dev, "RAS WARN: 0x%llx has been marked "
- "as bad before error injection!\n",
- data.inject.address);
+ dev_warn(adev->dev, "RAS WARN: inject: 0x%llx has "
+ "already been marked as bad!\n",
+ data.inject.address);
break;
}
@@ -439,21 +439,24 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
* will reset EEPROM table to 0 entries.
*
*/
-static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, const char __user *buf,
- size_t size, loff_t *pos)
+static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f,
+ const char __user *buf,
+ size_t size, loff_t *pos)
{
struct amdgpu_device *adev =
(struct amdgpu_device *)file_inode(f)->i_private;
int ret;
ret = amdgpu_ras_eeprom_reset_table(
- &(amdgpu_ras_get_context(adev)->eeprom_control));
+ &(amdgpu_ras_get_context(adev)->eeprom_control));
- if (ret == 1) {
+ if (!ret) {
+ /* Something was written to EEPROM.
+ */
amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS;
return size;
} else {
- return -EIO;
+ return ret;
}
}
@@ -526,7 +529,7 @@ static inline void put_obj(struct ras_manager *obj)
if (obj && (--obj->use == 0))
list_del(&obj->node);
if (obj && (obj->use < 0))
- DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", obj->head.name);
+ DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", ras_block_str(obj->head.block));
}
/* make one obj and return it. */
@@ -789,7 +792,6 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev,
.type = default_ras_type,
.sub_block_index = 0,
};
- strcpy(head.name, ras_block_str(i));
if (bypass) {
/*
* bypass psp. vbios enable ras for us.
@@ -1316,6 +1318,12 @@ static struct dentry *amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *
&con->bad_page_cnt_threshold);
debugfs_create_x32("ras_hw_enabled", 0444, dir, &adev->ras_hw_enabled);
debugfs_create_x32("ras_enabled", 0444, dir, &adev->ras_enabled);
+ debugfs_create_file("ras_eeprom_size", S_IRUGO, dir, adev,
+ &amdgpu_ras_debugfs_eeprom_size_ops);
+ con->de_ras_eeprom_table = debugfs_create_file("ras_eeprom_table",
+ S_IRUGO, dir, adev,
+ &amdgpu_ras_debugfs_eeprom_table_ops);
+ amdgpu_ras_debugfs_set_ret_size(&con->eeprom_control);
/*
* After one uncorrectable error happens, usually GPU recovery will
@@ -1833,13 +1841,12 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
control = &con->eeprom_control;
data = con->eh_data;
- save_count = data->count - control->num_recs;
+ save_count = data->count - control->ras_num_recs;
/* only new entries are saved */
if (save_count > 0) {
- if (amdgpu_ras_eeprom_process_recods(control,
- &data->bps[control->num_recs],
- true,
- save_count)) {
+ if (amdgpu_ras_eeprom_append(control,
+ &data->bps[control->ras_num_recs],
+ save_count)) {
dev_err(adev->dev, "Failed to save EEPROM table data!");
return -EIO;
}
@@ -1857,28 +1864,24 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev)
{
struct amdgpu_ras_eeprom_control *control =
- &adev->psp.ras.ras->eeprom_control;
- struct eeprom_table_record *bps = NULL;
- int ret = 0;
+ &adev->psp.ras_context.ras->eeprom_control;
+ struct eeprom_table_record *bps;
+ int ret;
/* no bad page record, skip eeprom access */
- if (!control->num_recs || (amdgpu_bad_page_threshold == 0))
- return ret;
+ if (control->ras_num_recs == 0 || amdgpu_bad_page_threshold == 0)
+ return 0;
- bps = kcalloc(control->num_recs, sizeof(*bps), GFP_KERNEL);
+ bps = kcalloc(control->ras_num_recs, sizeof(*bps), GFP_KERNEL);
if (!bps)
return -ENOMEM;
- if (amdgpu_ras_eeprom_process_recods(control, bps, false,
- control->num_recs)) {
+ ret = amdgpu_ras_eeprom_read(control, bps, control->ras_num_recs);
+ if (ret)
dev_err(adev->dev, "Failed to load EEPROM table records!");
- ret = -EIO;
- goto out;
- }
-
- ret = amdgpu_ras_add_bad_pages(adev, bps, control->num_recs);
+ else
+ ret = amdgpu_ras_add_bad_pages(adev, bps, control->ras_num_recs);
-out:
kfree(bps);
return ret;
}
@@ -1918,11 +1921,9 @@ static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev,
}
static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev,
- uint32_t max_length)
+ uint32_t max_count)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
- int tmp_threshold = amdgpu_bad_page_threshold;
- u64 val;
/*
* Justification of value bad_page_cnt_threshold in ras structure
@@ -1943,18 +1944,15 @@ static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev,
* take no effect.
*/
- if (tmp_threshold < -1)
- tmp_threshold = -1;
- else if (tmp_threshold > max_length)
- tmp_threshold = max_length;
+ if (amdgpu_bad_page_threshold < 0) {
+ u64 val = adev->gmc.mc_vram_size;
- if (tmp_threshold == -1) {
- val = adev->gmc.mc_vram_size;
- do_div(val, RAS_BAD_PAGE_RATE);
+ do_div(val, RAS_BAD_PAGE_COVER);
con->bad_page_cnt_threshold = min(lower_32_bits(val),
- max_length);
+ max_count);
} else {
- con->bad_page_cnt_threshold = tmp_threshold;
+ con->bad_page_cnt_threshold = min_t(int, max_count,
+ amdgpu_bad_page_threshold);
}
}
@@ -1962,15 +1960,24 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
struct ras_err_handler_data **data;
- uint32_t max_eeprom_records_len = 0;
+ u32 max_eeprom_records_count = 0;
bool exc_err_limit = false;
int ret;
- if (adev->ras_enabled && con)
- data = &con->eh_data;
- else
+ if (!con)
return 0;
+ /* Allow access to RAS EEPROM via debugfs, when the ASIC
+ * supports RAS and debugfs is enabled, but when
+ * adev->ras_enabled is unset, i.e. when "ras_enable"
+ * module parameter is set to 0.
+ */
+ con->adev = adev;
+
+ if (!adev->ras_enabled)
+ return 0;
+
+ data = &con->eh_data;
*data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO);
if (!*data) {
ret = -ENOMEM;
@@ -1980,10 +1987,9 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
mutex_init(&con->recovery_lock);
INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery);
atomic_set(&con->in_recovery, 0);
- con->adev = adev;
- max_eeprom_records_len = amdgpu_ras_eeprom_get_record_max_length();
- amdgpu_ras_validate_threshold(adev, max_eeprom_records_len);
+ max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count();
+ amdgpu_ras_validate_threshold(adev, max_eeprom_records_count);
/* Todo: During test the SMU might fail to read the eeprom through I2C
* when the GPU is pending on XGMI reset during probe time
@@ -1999,13 +2005,13 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
if (exc_err_limit || ret)
goto free;
- if (con->eeprom_control.num_recs) {
+ if (con->eeprom_control.ras_num_recs) {
ret = amdgpu_ras_load_bad_pages(adev);
if (ret)
goto free;
if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num)
- adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.num_recs);
+ adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs);
}
return 0;
@@ -2015,7 +2021,7 @@ free:
kfree(*data);
con->eh_data = NULL;
out:
- dev_warn(adev->dev, "Failed to initialize ras recovery!\n");
+ dev_warn(adev->dev, "Failed to initialize ras recovery! (%d)\n", ret);
/*
* Except error threshold exceeding case, other failure cases in this
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
index b504ed8c9b50..eae604fd90b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
@@ -49,10 +49,14 @@ enum amdgpu_ras_block {
AMDGPU_RAS_BLOCK__MP0,
AMDGPU_RAS_BLOCK__MP1,
AMDGPU_RAS_BLOCK__FUSE,
+ AMDGPU_RAS_BLOCK__MPIO,
AMDGPU_RAS_BLOCK__LAST
};
+extern const char *ras_block_string[];
+
+#define ras_block_str(i) (ras_block_string[i])
#define AMDGPU_RAS_BLOCK_COUNT AMDGPU_RAS_BLOCK__LAST
#define AMDGPU_RAS_BLOCK_MASK ((1ULL << AMDGPU_RAS_BLOCK_COUNT) - 1)
@@ -306,7 +310,6 @@ struct ras_common_if {
enum amdgpu_ras_block block;
enum amdgpu_ras_error_type type;
uint32_t sub_block_index;
- /* block name */
char name[32];
};
@@ -318,6 +321,7 @@ struct amdgpu_ras {
/* sysfs */
struct device_attribute features_attr;
struct bin_attribute badpages_attr;
+ struct dentry *de_ras_eeprom_table;
/* block array */
struct ras_manager *objs;
@@ -417,7 +421,7 @@ struct ras_badpage {
/* interfaces for IP */
struct ras_fs_if {
struct ras_common_if head;
- char sysfs_name[32];
+ const char* sysfs_name;
char debugfs_name[32];
};
@@ -469,8 +473,8 @@ struct ras_debug_if {
* 8: feature disable
*/
-#define amdgpu_ras_get_context(adev) ((adev)->psp.ras.ras)
-#define amdgpu_ras_set_context(adev, ras_con) ((adev)->psp.ras.ras = (ras_con))
+#define amdgpu_ras_get_context(adev) ((adev)->psp.ras_context.ras)
+#define amdgpu_ras_set_context(adev, ras_con) ((adev)->psp.ras_context.ras = (ras_con))
/* check if ras is supported on block, say, sdma, gfx */
static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 38222de921d1..9dc3b2d88176 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -26,94 +26,131 @@
#include "amdgpu_ras.h"
#include <linux/bits.h>
#include "atom.h"
+#include "amdgpu_eeprom.h"
#include "amdgpu_atomfirmware.h"
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
-#define EEPROM_I2C_TARGET_ADDR_VEGA20 0xA0
-#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8
-#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342 0xA0
-#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID 0xA0
-#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN 0xA0
+#define EEPROM_I2C_MADDR_VEGA20 0x0
+#define EEPROM_I2C_MADDR_ARCTURUS 0x40000
+#define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0
+#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0
+#define EEPROM_I2C_MADDR_ALDEBARAN 0x0
/*
* The 2 macros bellow represent the actual size in bytes that
* those entities occupy in the EEPROM memory.
- * EEPROM_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which
+ * RAS_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which
* uses uint64 to store 6b fields such as retired_page.
*/
-#define EEPROM_TABLE_HEADER_SIZE 20
-#define EEPROM_TABLE_RECORD_SIZE 24
-
-#define EEPROM_ADDRESS_SIZE 0x2
+#define RAS_TABLE_HEADER_SIZE 20
+#define RAS_TABLE_RECORD_SIZE 24
/* Table hdr is 'AMDR' */
-#define EEPROM_TABLE_HDR_VAL 0x414d4452
-#define EEPROM_TABLE_VER 0x00010000
+#define RAS_TABLE_HDR_VAL 0x414d4452
+#define RAS_TABLE_VER 0x00010000
/* Bad GPU tag ‘BADG’ */
-#define EEPROM_TABLE_HDR_BAD 0x42414447
+#define RAS_TABLE_HDR_BAD 0x42414447
+
+/* Assume 2-Mbit size EEPROM and take up the whole space. */
+#define RAS_TBL_SIZE_BYTES (256 * 1024)
+#define RAS_TABLE_START 0
+#define RAS_HDR_START RAS_TABLE_START
+#define RAS_RECORD_START (RAS_HDR_START + RAS_TABLE_HEADER_SIZE)
+#define RAS_MAX_RECORD_COUNT ((RAS_TBL_SIZE_BYTES - RAS_TABLE_HEADER_SIZE) \
+ / RAS_TABLE_RECORD_SIZE)
+
+/* Given a zero-based index of an EEPROM RAS record, yields the EEPROM
+ * offset off of RAS_TABLE_START. That is, this is something you can
+ * add to control->i2c_address, and then tell I2C layer to read
+ * from/write to there. _N is the so called absolute index,
+ * because it starts right after the table header.
+ */
+#define RAS_INDEX_TO_OFFSET(_C, _N) ((_C)->ras_record_offset + \
+ (_N) * RAS_TABLE_RECORD_SIZE)
+
+#define RAS_OFFSET_TO_INDEX(_C, _O) (((_O) - \
+ (_C)->ras_record_offset) / RAS_TABLE_RECORD_SIZE)
+
+/* Given a 0-based relative record index, 0, 1, 2, ..., etc., off
+ * of "fri", return the absolute record index off of the end of
+ * the table header.
+ */
+#define RAS_RI_TO_AI(_C, _I) (((_I) + (_C)->ras_fri) % \
+ (_C)->ras_max_record_count)
-/* Assume 2 Mbit size */
-#define EEPROM_SIZE_BYTES 256000
-#define EEPROM_PAGE__SIZE_BYTES 256
-#define EEPROM_HDR_START 0
-#define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE)
-#define EEPROM_MAX_RECORD_NUM ((EEPROM_SIZE_BYTES - EEPROM_TABLE_HEADER_SIZE) / EEPROM_TABLE_RECORD_SIZE)
-#define EEPROM_ADDR_MSB_MASK GENMASK(17, 8)
+#define RAS_NUM_RECS(_tbl_hdr) (((_tbl_hdr)->tbl_size - \
+ RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE)
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev
static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
{
- if ((adev->asic_type == CHIP_VEGA20) ||
- (adev->asic_type == CHIP_ARCTURUS) ||
- (adev->asic_type == CHIP_SIENNA_CICHLID) ||
- (adev->asic_type == CHIP_ALDEBARAN))
- return true;
-
- return false;
+ return adev->asic_type == CHIP_VEGA20 ||
+ adev->asic_type == CHIP_ARCTURUS ||
+ adev->asic_type == CHIP_SIENNA_CICHLID ||
+ adev->asic_type == CHIP_ALDEBARAN;
}
static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev,
- uint16_t *i2c_addr)
+ struct amdgpu_ras_eeprom_control *control)
{
struct atom_context *atom_ctx = adev->mode_info.atom_context;
- if (!i2c_addr || !atom_ctx)
+ if (!control || !atom_ctx)
return false;
if (strnstr(atom_ctx->vbios_version,
"D342",
sizeof(atom_ctx->vbios_version)))
- *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342;
+ control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS_D342;
else
- *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS;
+ control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS;
return true;
}
static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
- uint16_t *i2c_addr)
+ struct amdgpu_ras_eeprom_control *control)
{
- if (!i2c_addr)
+ uint8_t ras_rom_i2c_slave_addr;
+
+ if (!control)
return false;
- if (amdgpu_atomfirmware_ras_rom_addr(adev, (uint8_t*)i2c_addr))
- return true;
+ control->i2c_address = 0;
+
+ if (amdgpu_atomfirmware_ras_rom_addr(adev, &ras_rom_i2c_slave_addr))
+ {
+ switch (ras_rom_i2c_slave_addr) {
+ case 0xA0:
+ control->i2c_address = 0;
+ return true;
+ case 0xA8:
+ control->i2c_address = 0x40000;
+ return true;
+ default:
+ dev_warn(adev->dev, "RAS EEPROM I2C slave address %02x not supported",
+ ras_rom_i2c_slave_addr);
+ return false;
+ }
+ }
switch (adev->asic_type) {
case CHIP_VEGA20:
- *i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20;
+ control->i2c_address = EEPROM_I2C_MADDR_VEGA20;
break;
case CHIP_ARCTURUS:
- return __get_eeprom_i2c_addr_arct(adev, i2c_addr);
+ return __get_eeprom_i2c_addr_arct(adev, control);
case CHIP_SIENNA_CICHLID:
- *i2c_addr = EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID;
+ control->i2c_address = EEPROM_I2C_MADDR_SIENNA_CICHLID;
break;
case CHIP_ALDEBARAN:
- *i2c_addr = EEPROM_I2C_TARGET_ADDR_ALDEBARAN;
+ control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN;
break;
default:
@@ -123,10 +160,11 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
return true;
}
-static void __encode_table_header_to_buff(struct amdgpu_ras_eeprom_table_header *hdr,
- unsigned char *buff)
+static void
+__encode_table_header_to_buf(struct amdgpu_ras_eeprom_table_header *hdr,
+ unsigned char *buf)
{
- uint32_t *pp = (uint32_t *) buff;
+ u32 *pp = (uint32_t *)buf;
pp[0] = cpu_to_le32(hdr->header);
pp[1] = cpu_to_le32(hdr->version);
@@ -135,10 +173,11 @@ static void __encode_table_header_to_buff(struct amdgpu_ras_eeprom_table_header
pp[4] = cpu_to_le32(hdr->checksum);
}
-static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_header *hdr,
- unsigned char *buff)
+static void
+__decode_table_header_from_buf(struct amdgpu_ras_eeprom_table_header *hdr,
+ unsigned char *buf)
{
- uint32_t *pp = (uint32_t *)buff;
+ u32 *pp = (uint32_t *)buf;
hdr->header = le32_to_cpu(pp[0]);
hdr->version = le32_to_cpu(pp[1]);
@@ -147,303 +186,168 @@ static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_heade
hdr->checksum = le32_to_cpu(pp[4]);
}
-static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
- unsigned char *buff)
+static int __write_table_header(struct amdgpu_ras_eeprom_control *control)
{
- int ret = 0;
+ u8 buf[RAS_TABLE_HEADER_SIZE];
struct amdgpu_device *adev = to_amdgpu_device(control);
- struct i2c_msg msg = {
- .addr = 0,
- .flags = 0,
- .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE,
- .buf = buff,
- };
-
+ int res;
- *(uint16_t *)buff = EEPROM_HDR_START;
- __encode_table_header_to_buff(&control->tbl_hdr, buff + EEPROM_ADDRESS_SIZE);
-
- msg.addr = control->i2c_address;
+ memset(buf, 0, sizeof(buf));
+ __encode_table_header_to_buf(&control->tbl_hdr, buf);
/* i2c may be unstable in gpu reset */
down_read(&adev->reset_sem);
- ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
+ res = amdgpu_eeprom_write(&adev->pm.smu_i2c,
+ control->i2c_address +
+ control->ras_header_offset,
+ buf, RAS_TABLE_HEADER_SIZE);
up_read(&adev->reset_sem);
- if (ret < 1)
- DRM_ERROR("Failed to write EEPROM table header, ret:%d", ret);
-
- return ret;
-}
-
-static uint32_t __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control)
-{
- int i;
- uint32_t tbl_sum = 0;
-
- /* Header checksum, skip checksum field in the calculation */
- for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++)
- tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i);
-
- return tbl_sum;
-}
-
-static uint32_t __calc_recs_byte_sum(struct eeprom_table_record *records,
- int num)
-{
- int i, j;
- uint32_t tbl_sum = 0;
-
- /* Records checksum */
- for (i = 0; i < num; i++) {
- struct eeprom_table_record *record = &records[i];
-
- for (j = 0; j < sizeof(*record); j++) {
- tbl_sum += *(((unsigned char *)record) + j);
- }
+ if (res < 0) {
+ DRM_ERROR("Failed to write EEPROM table header:%d", res);
+ } else if (res < RAS_TABLE_HEADER_SIZE) {
+ DRM_ERROR("Short write:%d out of %d\n",
+ res, RAS_TABLE_HEADER_SIZE);
+ res = -EIO;
+ } else {
+ res = 0;
}
- return tbl_sum;
-}
-
-static inline uint32_t __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *records, int num)
-{
- return __calc_hdr_byte_sum(control) + __calc_recs_byte_sum(records, num);
-}
-
-/* Checksum = 256 -((sum of all table entries) mod 256) */
-static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *records, int num,
- uint32_t old_hdr_byte_sum)
-{
- /*
- * This will update the table sum with new records.
- *
- * TODO: What happens when the EEPROM table is to be wrapped around
- * and old records from start will get overridden.
- */
-
- /* need to recalculate updated header byte sum */
- control->tbl_byte_sum -= old_hdr_byte_sum;
- control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num);
-
- control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256);
+ return res;
}
-/* table sum mod 256 + checksum must equals 256 */
-static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *records, int num)
+static u8 __calc_hdr_byte_sum(const struct amdgpu_ras_eeprom_control *control)
{
- control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
+ int ii;
+ u8 *pp, csum;
+ size_t sz;
- if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) {
- DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum);
- return false;
- }
+ /* Header checksum, skip checksum field in the calculation */
+ sz = sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum);
+ pp = (u8 *) &control->tbl_hdr;
+ csum = 0;
+ for (ii = 0; ii < sz; ii++, pp++)
+ csum += *pp;
- return true;
+ return csum;
}
static int amdgpu_ras_eeprom_correct_header_tag(
- struct amdgpu_ras_eeprom_control *control,
- uint32_t header)
+ struct amdgpu_ras_eeprom_control *control,
+ uint32_t header)
{
- unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE];
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
- int ret = 0;
-
- memset(buff, 0, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE);
-
- mutex_lock(&control->tbl_mutex);
+ u8 *hh;
+ int res;
+ u8 csum;
+
+ csum = -hdr->checksum;
+
+ hh = (void *) &hdr->header;
+ csum -= (hh[0] + hh[1] + hh[2] + hh[3]);
+ hh = (void *) &header;
+ csum += hh[0] + hh[1] + hh[2] + hh[3];
+ csum = -csum;
+ mutex_lock(&control->ras_tbl_mutex);
hdr->header = header;
- ret = __update_table_header(control, buff);
- mutex_unlock(&control->tbl_mutex);
+ hdr->checksum = csum;
+ res = __write_table_header(control);
+ mutex_unlock(&control->ras_tbl_mutex);
- return ret;
+ return res;
}
+/**
+ * amdgpu_ras_eeprom_reset_table -- Reset the RAS EEPROM table
+ * @control: pointer to control structure
+ *
+ * Reset the contents of the header of the RAS EEPROM table.
+ * Return 0 on success, -errno on error.
+ */
int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
{
- unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 };
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
- int ret = 0;
-
- mutex_lock(&control->tbl_mutex);
-
- hdr->header = EEPROM_TABLE_HDR_VAL;
- hdr->version = EEPROM_TABLE_VER;
- hdr->first_rec_offset = EEPROM_RECORD_START;
- hdr->tbl_size = EEPROM_TABLE_HEADER_SIZE;
-
- control->tbl_byte_sum = 0;
- __update_tbl_checksum(control, NULL, 0, 0);
- control->next_addr = EEPROM_RECORD_START;
-
- ret = __update_table_header(control, buff);
-
- mutex_unlock(&control->tbl_mutex);
-
- return ret;
-
-}
-
-int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
- bool *exceed_err_limit)
-{
- int ret = 0;
- struct amdgpu_device *adev = to_amdgpu_device(control);
- unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 };
- struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
- struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
- struct i2c_msg msg = {
- .addr = 0,
- .flags = I2C_M_RD,
- .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE,
- .buf = buff,
- };
-
- *exceed_err_limit = false;
-
- if (!__is_ras_eeprom_supported(adev))
- return 0;
-
- /* Verify i2c adapter is initialized */
- if (!adev->pm.smu_i2c.algo)
- return -ENOENT;
+ u8 csum;
+ int res;
- if (!__get_eeprom_i2c_addr(adev, &control->i2c_address))
- return -EINVAL;
+ mutex_lock(&control->ras_tbl_mutex);
- mutex_init(&control->tbl_mutex);
+ hdr->header = RAS_TABLE_HDR_VAL;
+ hdr->version = RAS_TABLE_VER;
+ hdr->first_rec_offset = RAS_RECORD_START;
+ hdr->tbl_size = RAS_TABLE_HEADER_SIZE;
- msg.addr = control->i2c_address;
- /* Read/Create table header from EEPROM address 0 */
- ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
- if (ret < 1) {
- DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret);
- return ret;
- }
+ csum = __calc_hdr_byte_sum(control);
+ csum = -csum;
+ hdr->checksum = csum;
+ res = __write_table_header(control);
- __decode_table_header_from_buff(hdr, &buff[2]);
+ control->ras_num_recs = 0;
+ control->ras_fri = 0;
- if (hdr->header == EEPROM_TABLE_HDR_VAL) {
- control->num_recs = (hdr->tbl_size - EEPROM_TABLE_HEADER_SIZE) /
- EEPROM_TABLE_RECORD_SIZE;
- control->tbl_byte_sum = __calc_hdr_byte_sum(control);
- control->next_addr = EEPROM_RECORD_START;
+ amdgpu_ras_debugfs_set_ret_size(control);
- DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records",
- control->num_recs);
-
- } else if ((hdr->header == EEPROM_TABLE_HDR_BAD) &&
- (amdgpu_bad_page_threshold != 0)) {
- if (ras->bad_page_cnt_threshold > control->num_recs) {
- dev_info(adev->dev, "Using one valid bigger bad page "
- "threshold and correcting eeprom header tag.\n");
- ret = amdgpu_ras_eeprom_correct_header_tag(control,
- EEPROM_TABLE_HDR_VAL);
- } else {
- *exceed_err_limit = true;
- dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, "
- "disabling the GPU.\n");
- }
- } else {
- DRM_INFO("Creating new EEPROM table");
+ mutex_unlock(&control->ras_tbl_mutex);
- ret = amdgpu_ras_eeprom_reset_table(control);
- }
-
- return ret == 1 ? 0 : -EIO;
+ return res;
}
-static void __encode_table_record_to_buff(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *record,
- unsigned char *buff)
+static void
+__encode_table_record_to_buf(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *record,
+ unsigned char *buf)
{
__le64 tmp = 0;
int i = 0;
/* Next are all record fields according to EEPROM page spec in LE foramt */
- buff[i++] = record->err_type;
+ buf[i++] = record->err_type;
- buff[i++] = record->bank;
+ buf[i++] = record->bank;
tmp = cpu_to_le64(record->ts);
- memcpy(buff + i, &tmp, 8);
+ memcpy(buf + i, &tmp, 8);
i += 8;
tmp = cpu_to_le64((record->offset & 0xffffffffffff));
- memcpy(buff + i, &tmp, 6);
+ memcpy(buf + i, &tmp, 6);
i += 6;
- buff[i++] = record->mem_channel;
- buff[i++] = record->mcumc_id;
+ buf[i++] = record->mem_channel;
+ buf[i++] = record->mcumc_id;
tmp = cpu_to_le64((record->retired_page & 0xffffffffffff));
- memcpy(buff + i, &tmp, 6);
+ memcpy(buf + i, &tmp, 6);
}
-static void __decode_table_record_from_buff(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *record,
- unsigned char *buff)
+static void
+__decode_table_record_from_buf(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *record,
+ unsigned char *buf)
{
__le64 tmp = 0;
int i = 0;
/* Next are all record fields according to EEPROM page spec in LE foramt */
- record->err_type = buff[i++];
+ record->err_type = buf[i++];
- record->bank = buff[i++];
+ record->bank = buf[i++];
- memcpy(&tmp, buff + i, 8);
+ memcpy(&tmp, buf + i, 8);
record->ts = le64_to_cpu(tmp);
i += 8;
- memcpy(&tmp, buff + i, 6);
+ memcpy(&tmp, buf + i, 6);
record->offset = (le64_to_cpu(tmp) & 0xffffffffffff);
i += 6;
- record->mem_channel = buff[i++];
- record->mcumc_id = buff[i++];
+ record->mem_channel = buf[i++];
+ record->mcumc_id = buf[i++];
- memcpy(&tmp, buff + i, 6);
+ memcpy(&tmp, buf + i, 6);
record->retired_page = (le64_to_cpu(tmp) & 0xffffffffffff);
}
-/*
- * When reaching end of EEPROM memory jump back to 0 record address
- * When next record access will go beyond EEPROM page boundary modify bits A17/A8
- * in I2C selector to go to next page
- */
-static uint32_t __correct_eeprom_dest_address(uint32_t curr_address)
-{
- uint32_t next_address = curr_address + EEPROM_TABLE_RECORD_SIZE;
-
- /* When all EEPROM memory used jump back to 0 address */
- if (next_address > EEPROM_SIZE_BYTES) {
- DRM_INFO("Reached end of EEPROM memory, jumping to 0 "
- "and overriding old record");
- return EEPROM_RECORD_START;
- }
-
- /*
- * To check if we overflow page boundary compare next address with
- * current and see if bits 17/8 of the EEPROM address will change
- * If they do start from the next 256b page
- *
- * https://www.st.com/resource/en/datasheet/m24m02-dr.pdf sec. 5.1.2
- */
- if ((curr_address & EEPROM_ADDR_MSB_MASK) != (next_address & EEPROM_ADDR_MSB_MASK)) {
- DRM_DEBUG_DRIVER("Reached end of EEPROM memory page, jumping to next: %lx",
- (next_address & EEPROM_ADDR_MSB_MASK));
-
- return (next_address & EEPROM_ADDR_MSB_MASK);
- }
-
- return curr_address;
-}
-
bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
@@ -458,197 +362,756 @@ bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev)
if (!(con->features & BIT(AMDGPU_RAS_BLOCK__UMC)))
return false;
- if (con->eeprom_control.tbl_hdr.header == EEPROM_TABLE_HDR_BAD) {
+ if (con->eeprom_control.tbl_hdr.header == RAS_TABLE_HDR_BAD) {
dev_warn(adev->dev, "This GPU is in BAD status.");
- dev_warn(adev->dev, "Please retire it or setting one bigger "
- "threshold value when reloading driver.\n");
+ dev_warn(adev->dev, "Please retire it or set a larger "
+ "threshold value when reloading driver.\n");
return true;
}
return false;
}
-int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *records,
- bool write,
- int num)
+/**
+ * __amdgpu_ras_eeprom_write -- write indexed from buffer to EEPROM
+ * @control: pointer to control structure
+ * @buf: pointer to buffer containing data to write
+ * @fri: start writing at this index
+ * @num: number of records to write
+ *
+ * The caller must hold the table mutex in @control.
+ * Return 0 on success, -errno otherwise.
+ */
+static int __amdgpu_ras_eeprom_write(struct amdgpu_ras_eeprom_control *control,
+ u8 *buf, const u32 fri, const u32 num)
{
- int i, ret = 0;
- struct i2c_msg *msgs, *msg;
- unsigned char *buffs, *buff;
- struct eeprom_table_record *record;
struct amdgpu_device *adev = to_amdgpu_device(control);
- struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ u32 buf_size;
+ int res;
- if (!__is_ras_eeprom_supported(adev))
- return 0;
+ /* i2c may be unstable in gpu reset */
+ down_read(&adev->reset_sem);
+ buf_size = num * RAS_TABLE_RECORD_SIZE;
+ res = amdgpu_eeprom_write(&adev->pm.smu_i2c,
+ control->i2c_address +
+ RAS_INDEX_TO_OFFSET(control, fri),
+ buf, buf_size);
+ up_read(&adev->reset_sem);
+ if (res < 0) {
+ DRM_ERROR("Writing %d EEPROM table records error:%d",
+ num, res);
+ } else if (res < buf_size) {
+ /* Short write, return error.
+ */
+ DRM_ERROR("Wrote %d records out of %d",
+ res / RAS_TABLE_RECORD_SIZE, num);
+ res = -EIO;
+ } else {
+ res = 0;
+ }
- buffs = kcalloc(num, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE,
- GFP_KERNEL);
- if (!buffs)
- return -ENOMEM;
+ return res;
+}
- mutex_lock(&control->tbl_mutex);
+static int
+amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *record,
+ const u32 num)
+{
+ u32 a, b, i;
+ u8 *buf, *pp;
+ int res;
+
+ buf = kcalloc(num, RAS_TABLE_RECORD_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- msgs = kcalloc(num, sizeof(*msgs), GFP_KERNEL);
- if (!msgs) {
- ret = -ENOMEM;
- goto free_buff;
+ /* Encode all of them in one go.
+ */
+ pp = buf;
+ for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE)
+ __encode_table_record_to_buf(control, &record[i], pp);
+
+ /* a, first record index to write into.
+ * b, last record index to write into.
+ * a = first index to read (fri) + number of records in the table,
+ * b = a + @num - 1.
+ * Let N = control->ras_max_num_record_count, then we have,
+ * case 0: 0 <= a <= b < N,
+ * just append @num records starting at a;
+ * case 1: 0 <= a < N <= b,
+ * append (N - a) records starting at a, and
+ * append the remainder, b % N + 1, starting at 0.
+ * case 2: 0 <= fri < N <= a <= b, then modulo N we get two subcases,
+ * case 2a: 0 <= a <= b < N
+ * append num records starting at a; and fix fri if b overwrote it,
+ * and since a <= b, if b overwrote it then a must've also,
+ * and if b didn't overwrite it, then a didn't also.
+ * case 2b: 0 <= b < a < N
+ * write num records starting at a, which wraps around 0=N
+ * and overwrite fri unconditionally. Now from case 2a,
+ * this means that b eclipsed fri to overwrite it and wrap
+ * around 0 again, i.e. b = 2N+r pre modulo N, so we unconditionally
+ * set fri = b + 1 (mod N).
+ * Now, since fri is updated in every case, except the trivial case 0,
+ * the number of records present in the table after writing, is,
+ * num_recs - 1 = b - fri (mod N), and we take the positive value,
+ * by adding an arbitrary multiple of N before taking the modulo N
+ * as shown below.
+ */
+ a = control->ras_fri + control->ras_num_recs;
+ b = a + num - 1;
+ if (b < control->ras_max_record_count) {
+ res = __amdgpu_ras_eeprom_write(control, buf, a, num);
+ } else if (a < control->ras_max_record_count) {
+ u32 g0, g1;
+
+ g0 = control->ras_max_record_count - a;
+ g1 = b % control->ras_max_record_count + 1;
+ res = __amdgpu_ras_eeprom_write(control, buf, a, g0);
+ if (res)
+ goto Out;
+ res = __amdgpu_ras_eeprom_write(control,
+ buf + g0 * RAS_TABLE_RECORD_SIZE,
+ 0, g1);
+ if (res)
+ goto Out;
+ if (g1 > control->ras_fri)
+ control->ras_fri = g1 % control->ras_max_record_count;
+ } else {
+ a %= control->ras_max_record_count;
+ b %= control->ras_max_record_count;
+
+ if (a <= b) {
+ /* Note that, b - a + 1 = num. */
+ res = __amdgpu_ras_eeprom_write(control, buf, a, num);
+ if (res)
+ goto Out;
+ if (b >= control->ras_fri)
+ control->ras_fri = (b + 1) % control->ras_max_record_count;
+ } else {
+ u32 g0, g1;
+
+ /* b < a, which means, we write from
+ * a to the end of the table, and from
+ * the start of the table to b.
+ */
+ g0 = control->ras_max_record_count - a;
+ g1 = b + 1;
+ res = __amdgpu_ras_eeprom_write(control, buf, a, g0);
+ if (res)
+ goto Out;
+ res = __amdgpu_ras_eeprom_write(control,
+ buf + g0 * RAS_TABLE_RECORD_SIZE,
+ 0, g1);
+ if (res)
+ goto Out;
+ control->ras_fri = g1 % control->ras_max_record_count;
+ }
}
+ control->ras_num_recs = 1 + (control->ras_max_record_count + b
+ - control->ras_fri)
+ % control->ras_max_record_count;
+Out:
+ kfree(buf);
+ return res;
+}
- /*
- * If saved bad pages number exceeds the bad page threshold for
- * the whole VRAM, update table header to mark the BAD GPU tag
- * and schedule one ras recovery after eeprom write is done,
- * this can avoid the missing for latest records.
- *
- * This new header will be picked up and checked in the bootup
- * by ras recovery, which may break bootup process to notify
- * user this GPU is in bad state and to retire such GPU for
- * further check.
+static int
+amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
+{
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ u8 *buf, *pp, csum;
+ u32 buf_size;
+ int res;
+
+ /* Modify the header if it exceeds.
*/
- if (write && (amdgpu_bad_page_threshold != 0) &&
- ((control->num_recs + num) >= ras->bad_page_cnt_threshold)) {
+ if (amdgpu_bad_page_threshold != 0 &&
+ control->ras_num_recs >= ras->bad_page_cnt_threshold) {
dev_warn(adev->dev,
- "Saved bad pages(%d) reaches threshold value(%d).\n",
- control->num_recs + num, ras->bad_page_cnt_threshold);
- control->tbl_hdr.header = EEPROM_TABLE_HDR_BAD;
+ "Saved bad pages %d reaches threshold value %d\n",
+ control->ras_num_recs, ras->bad_page_cnt_threshold);
+ control->tbl_hdr.header = RAS_TABLE_HDR_BAD;
+ }
+
+ control->tbl_hdr.version = RAS_TABLE_VER;
+ control->tbl_hdr.first_rec_offset = RAS_INDEX_TO_OFFSET(control, control->ras_fri);
+ control->tbl_hdr.tbl_size = RAS_TABLE_HEADER_SIZE + control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+ control->tbl_hdr.checksum = 0;
+
+ buf_size = control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+ buf = kcalloc(control->ras_num_recs, RAS_TABLE_RECORD_SIZE, GFP_KERNEL);
+ if (!buf) {
+ DRM_ERROR("allocating memory for table of size %d bytes failed\n",
+ control->tbl_hdr.tbl_size);
+ res = -ENOMEM;
+ goto Out;
}
- /* In case of overflow just start from beginning to not lose newest records */
- if (write && (control->next_addr + EEPROM_TABLE_RECORD_SIZE * num > EEPROM_SIZE_BYTES))
- control->next_addr = EEPROM_RECORD_START;
+ down_read(&adev->reset_sem);
+ res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
+ control->i2c_address +
+ control->ras_record_offset,
+ buf, buf_size);
+ up_read(&adev->reset_sem);
+ if (res < 0) {
+ DRM_ERROR("EEPROM failed reading records:%d\n",
+ res);
+ goto Out;
+ } else if (res < buf_size) {
+ DRM_ERROR("EEPROM read %d out of %d bytes\n",
+ res, buf_size);
+ res = -EIO;
+ goto Out;
+ }
- /*
- * TODO Currently makes EEPROM writes for each record, this creates
- * internal fragmentation. Optimized the code to do full page write of
- * 256b
+ /* Recalc the checksum.
*/
- for (i = 0; i < num; i++) {
- buff = &buffs[i * (EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)];
- record = &records[i];
- msg = &msgs[i];
+ csum = 0;
+ for (pp = buf; pp < buf + buf_size; pp++)
+ csum += *pp;
+
+ csum += __calc_hdr_byte_sum(control);
+ /* avoid sign extension when assigning to "checksum" */
+ csum = -csum;
+ control->tbl_hdr.checksum = csum;
+ res = __write_table_header(control);
+Out:
+ kfree(buf);
+ return res;
+}
- control->next_addr = __correct_eeprom_dest_address(control->next_addr);
+/**
+ * amdgpu_ras_eeprom_append -- append records to the EEPROM RAS table
+ * @control: pointer to control structure
+ * @record: array of records to append
+ * @num: number of records in @record array
+ *
+ * Append @num records to the table, calculate the checksum and write
+ * the table back to EEPROM. The maximum number of records that
+ * can be appended is between 1 and control->ras_max_record_count,
+ * regardless of how many records are already stored in the table.
+ *
+ * Return 0 on success or if EEPROM is not supported, -errno on error.
+ */
+int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *record,
+ const u32 num)
+{
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ int res;
- /*
- * Update bits 16,17 of EEPROM address in I2C address by setting them
- * to bits 1,2 of Device address byte
- */
- msg->addr = control->i2c_address |
- ((control->next_addr & EEPROM_ADDR_MSB_MASK) >> 15);
- msg->flags = write ? 0 : I2C_M_RD;
- msg->len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE;
- msg->buf = buff;
-
- /* Insert the EEPROM dest addess, bits 0-15 */
- buff[0] = ((control->next_addr >> 8) & 0xff);
- buff[1] = (control->next_addr & 0xff);
-
- /* EEPROM table content is stored in LE format */
- if (write)
- __encode_table_record_to_buff(control, record, buff + EEPROM_ADDRESS_SIZE);
-
- /*
- * The destination EEPROM address might need to be corrected to account
- * for page or entire memory wrapping
- */
- control->next_addr += EEPROM_TABLE_RECORD_SIZE;
+ if (!__is_ras_eeprom_supported(adev))
+ return 0;
+
+ if (num == 0) {
+ DRM_ERROR("will not append 0 records\n");
+ return -EINVAL;
+ } else if (num > control->ras_max_record_count) {
+ DRM_ERROR("cannot append %d records than the size of table %d\n",
+ num, control->ras_max_record_count);
+ return -EINVAL;
}
+ mutex_lock(&control->ras_tbl_mutex);
+
+ res = amdgpu_ras_eeprom_append_table(control, record, num);
+ if (!res)
+ res = amdgpu_ras_eeprom_update_header(control);
+ if (!res)
+ amdgpu_ras_debugfs_set_ret_size(control);
+
+ mutex_unlock(&control->ras_tbl_mutex);
+ return res;
+}
+
+/**
+ * __amdgpu_ras_eeprom_read -- read indexed from EEPROM into buffer
+ * @control: pointer to control structure
+ * @buf: pointer to buffer to read into
+ * @fri: first record index, start reading at this index, absolute index
+ * @num: number of records to read
+ *
+ * The caller must hold the table mutex in @control.
+ * Return 0 on success, -errno otherwise.
+ */
+static int __amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
+ u8 *buf, const u32 fri, const u32 num)
+{
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ u32 buf_size;
+ int res;
+
/* i2c may be unstable in gpu reset */
down_read(&adev->reset_sem);
- ret = i2c_transfer(&adev->pm.smu_i2c, msgs, num);
+ buf_size = num * RAS_TABLE_RECORD_SIZE;
+ res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
+ control->i2c_address +
+ RAS_INDEX_TO_OFFSET(control, fri),
+ buf, buf_size);
up_read(&adev->reset_sem);
+ if (res < 0) {
+ DRM_ERROR("Reading %d EEPROM table records error:%d",
+ num, res);
+ } else if (res < buf_size) {
+ /* Short read, return error.
+ */
+ DRM_ERROR("Read %d records out of %d",
+ res / RAS_TABLE_RECORD_SIZE, num);
+ res = -EIO;
+ } else {
+ res = 0;
+ }
+
+ return res;
+}
+
+/**
+ * amdgpu_ras_eeprom_read -- read EEPROM
+ * @control: pointer to control structure
+ * @record: array of records to read into
+ * @num: number of records in @record
+ *
+ * Reads num records from the RAS table in EEPROM and
+ * writes the data into @record array.
+ *
+ * Returns 0 on success, -errno on error.
+ */
+int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *record,
+ const u32 num)
+{
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ int i, res;
+ u8 *buf, *pp;
+ u32 g0, g1;
- if (ret < 1) {
- DRM_ERROR("Failed to process EEPROM table records, ret:%d", ret);
+ if (!__is_ras_eeprom_supported(adev))
+ return 0;
- /* TODO Restore prev next EEPROM address ? */
- goto free_msgs;
+ if (num == 0) {
+ DRM_ERROR("will not read 0 records\n");
+ return -EINVAL;
+ } else if (num > control->ras_num_recs) {
+ DRM_ERROR("too many records to read:%d available:%d\n",
+ num, control->ras_num_recs);
+ return -EINVAL;
}
+ buf = kcalloc(num, RAS_TABLE_RECORD_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- if (!write) {
- for (i = 0; i < num; i++) {
- buff = &buffs[i*(EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)];
- record = &records[i];
+ /* Determine how many records to read, from the first record
+ * index, fri, to the end of the table, and from the beginning
+ * of the table, such that the total number of records is
+ * @num, and we handle wrap around when fri > 0 and
+ * fri + num > RAS_MAX_RECORD_COUNT.
+ *
+ * First we compute the index of the last element
+ * which would be fetched from each region,
+ * g0 is in [fri, fri + num - 1], and
+ * g1 is in [0, RAS_MAX_RECORD_COUNT - 1].
+ * Then, if g0 < RAS_MAX_RECORD_COUNT, the index of
+ * the last element to fetch, we set g0 to _the number_
+ * of elements to fetch, @num, since we know that the last
+ * indexed to be fetched does not exceed the table.
+ *
+ * If, however, g0 >= RAS_MAX_RECORD_COUNT, then
+ * we set g0 to the number of elements to read
+ * until the end of the table, and g1 to the number of
+ * elements to read from the beginning of the table.
+ */
+ g0 = control->ras_fri + num - 1;
+ g1 = g0 % control->ras_max_record_count;
+ if (g0 < control->ras_max_record_count) {
+ g0 = num;
+ g1 = 0;
+ } else {
+ g0 = control->ras_max_record_count - control->ras_fri;
+ g1 += 1;
+ }
- __decode_table_record_from_buff(control, record, buff + EEPROM_ADDRESS_SIZE);
- }
+ mutex_lock(&control->ras_tbl_mutex);
+ res = __amdgpu_ras_eeprom_read(control, buf, control->ras_fri, g0);
+ if (res)
+ goto Out;
+ if (g1) {
+ res = __amdgpu_ras_eeprom_read(control,
+ buf + g0 * RAS_TABLE_RECORD_SIZE,
+ 0, g1);
+ if (res)
+ goto Out;
}
- if (write) {
- uint32_t old_hdr_byte_sum = __calc_hdr_byte_sum(control);
+ res = 0;
+
+ /* Read up everything? Then transform.
+ */
+ pp = buf;
+ for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE)
+ __decode_table_record_from_buf(control, &record[i], pp);
+Out:
+ kfree(buf);
+ mutex_unlock(&control->ras_tbl_mutex);
+
+ return res;
+}
+
+inline uint32_t amdgpu_ras_eeprom_max_record_count(void)
+{
+ return RAS_MAX_RECORD_COUNT;
+}
+
+static ssize_t
+amdgpu_ras_debugfs_eeprom_size_read(struct file *f, char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ struct amdgpu_ras_eeprom_control *control = ras ? &ras->eeprom_control : NULL;
+ u8 data[50];
+ int res;
+
+ if (!size)
+ return size;
+
+ if (!ras || !control) {
+ res = snprintf(data, sizeof(data), "Not supported\n");
+ } else {
+ res = snprintf(data, sizeof(data), "%d bytes or %d records\n",
+ RAS_TBL_SIZE_BYTES, control->ras_max_record_count);
+ }
+
+ if (*pos >= res)
+ return 0;
+
+ res -= *pos;
+ res = min_t(size_t, res, size);
+
+ if (copy_to_user(buf, &data[*pos], res))
+ return -EFAULT;
+
+ *pos += res;
- /*
- * Update table header with size and CRC and account for table
- * wrap around where the assumption is that we treat it as empty
- * table
- *
- * TODO - Check the assumption is correct
+ return res;
+}
+
+const struct file_operations amdgpu_ras_debugfs_eeprom_size_ops = {
+ .owner = THIS_MODULE,
+ .read = amdgpu_ras_debugfs_eeprom_size_read,
+ .write = NULL,
+ .llseek = default_llseek,
+};
+
+static const char *tbl_hdr_str = " Signature Version FirstOffs Size Checksum\n";
+static const char *tbl_hdr_fmt = "0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n";
+#define tbl_hdr_fmt_size (5 * (2+8) + 4 + 1)
+static const char *rec_hdr_str = "Index Offset ErrType Bank/CU TimeStamp Offs/Addr MemChl MCUMCID RetiredPage\n";
+static const char *rec_hdr_fmt = "%5d 0x%05X %7s 0x%02X 0x%016llX 0x%012llX 0x%02X 0x%02X 0x%012llX\n";
+#define rec_hdr_fmt_size (5 + 1 + 7 + 1 + 7 + 1 + 7 + 1 + 18 + 1 + 14 + 1 + 6 + 1 + 7 + 1 + 14 + 1)
+
+static const char *record_err_type_str[AMDGPU_RAS_EEPROM_ERR_COUNT] = {
+ "ignore",
+ "re",
+ "ue",
+};
+
+static loff_t amdgpu_ras_debugfs_table_size(struct amdgpu_ras_eeprom_control *control)
+{
+ return strlen(tbl_hdr_str) + tbl_hdr_fmt_size +
+ strlen(rec_hdr_str) + rec_hdr_fmt_size * control->ras_num_recs;
+}
+
+void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control)
+{
+ struct amdgpu_ras *ras = container_of(control, struct amdgpu_ras,
+ eeprom_control);
+ struct dentry *de = ras->de_ras_eeprom_table;
+
+ if (de)
+ d_inode(de)->i_size = amdgpu_ras_debugfs_table_size(control);
+}
+
+static ssize_t amdgpu_ras_debugfs_table_read(struct file *f, char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ struct amdgpu_ras_eeprom_control *control = &ras->eeprom_control;
+ const size_t orig_size = size;
+ int res = -EFAULT;
+ size_t data_len;
+
+ mutex_lock(&control->ras_tbl_mutex);
+
+ /* We want *pos - data_len > 0, which means there's
+ * bytes to be printed from data.
+ */
+ data_len = strlen(tbl_hdr_str);
+ if (*pos < data_len) {
+ data_len -= *pos;
+ data_len = min_t(size_t, data_len, size);
+ if (copy_to_user(buf, &tbl_hdr_str[*pos], data_len))
+ goto Out;
+ buf += data_len;
+ size -= data_len;
+ *pos += data_len;
+ }
+
+ data_len = strlen(tbl_hdr_str) + tbl_hdr_fmt_size;
+ if (*pos < data_len && size > 0) {
+ u8 data[tbl_hdr_fmt_size + 1];
+ loff_t lpos;
+
+ snprintf(data, sizeof(data), tbl_hdr_fmt,
+ control->tbl_hdr.header,
+ control->tbl_hdr.version,
+ control->tbl_hdr.first_rec_offset,
+ control->tbl_hdr.tbl_size,
+ control->tbl_hdr.checksum);
+
+ data_len -= *pos;
+ data_len = min_t(size_t, data_len, size);
+ lpos = *pos - strlen(tbl_hdr_str);
+ if (copy_to_user(buf, &data[lpos], data_len))
+ goto Out;
+ buf += data_len;
+ size -= data_len;
+ *pos += data_len;
+ }
+
+ data_len = strlen(tbl_hdr_str) + tbl_hdr_fmt_size + strlen(rec_hdr_str);
+ if (*pos < data_len && size > 0) {
+ loff_t lpos;
+
+ data_len -= *pos;
+ data_len = min_t(size_t, data_len, size);
+ lpos = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size;
+ if (copy_to_user(buf, &rec_hdr_str[lpos], data_len))
+ goto Out;
+ buf += data_len;
+ size -= data_len;
+ *pos += data_len;
+ }
+
+ data_len = amdgpu_ras_debugfs_table_size(control);
+ if (*pos < data_len && size > 0) {
+ u8 dare[RAS_TABLE_RECORD_SIZE];
+ u8 data[rec_hdr_fmt_size + 1];
+ struct eeprom_table_record record;
+ int s, r;
+
+ /* Find the starting record index
*/
- control->num_recs += num;
- control->num_recs %= EEPROM_MAX_RECORD_NUM;
- control->tbl_hdr.tbl_size += EEPROM_TABLE_RECORD_SIZE * num;
- if (control->tbl_hdr.tbl_size > EEPROM_SIZE_BYTES)
- control->tbl_hdr.tbl_size = EEPROM_TABLE_HEADER_SIZE +
- control->num_recs * EEPROM_TABLE_RECORD_SIZE;
-
- __update_tbl_checksum(control, records, num, old_hdr_byte_sum);
-
- __update_table_header(control, buffs);
- } else if (!__validate_tbl_checksum(control, records, num)) {
- DRM_WARN("EEPROM Table checksum mismatch!");
- /* TODO Uncomment when EEPROM read/write is relliable */
- /* ret = -EIO; */
+ s = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size -
+ strlen(rec_hdr_str);
+ s = s / rec_hdr_fmt_size;
+ r = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size -
+ strlen(rec_hdr_str);
+ r = r % rec_hdr_fmt_size;
+
+ for ( ; size > 0 && s < control->ras_num_recs; s++) {
+ u32 ai = RAS_RI_TO_AI(control, s);
+ /* Read a single record
+ */
+ res = __amdgpu_ras_eeprom_read(control, dare, ai, 1);
+ if (res)
+ goto Out;
+ __decode_table_record_from_buf(control, &record, dare);
+ snprintf(data, sizeof(data), rec_hdr_fmt,
+ s,
+ RAS_INDEX_TO_OFFSET(control, ai),
+ record_err_type_str[record.err_type],
+ record.bank,
+ record.ts,
+ record.offset,
+ record.mem_channel,
+ record.mcumc_id,
+ record.retired_page);
+
+ data_len = min_t(size_t, rec_hdr_fmt_size - r, size);
+ if (copy_to_user(buf, &data[r], data_len)) {
+ res = -EFAULT;
+ goto Out;
+ }
+ buf += data_len;
+ size -= data_len;
+ *pos += data_len;
+ r = 0;
+ }
}
+ res = 0;
+Out:
+ mutex_unlock(&control->ras_tbl_mutex);
+ return res < 0 ? res : orig_size - size;
+}
-free_msgs:
- kfree(msgs);
+static ssize_t
+amdgpu_ras_debugfs_eeprom_table_read(struct file *f, char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ struct amdgpu_ras_eeprom_control *control = ras ? &ras->eeprom_control : NULL;
+ u8 data[81];
+ int res;
+
+ if (!size)
+ return size;
+
+ if (!ras || !control) {
+ res = snprintf(data, sizeof(data), "Not supported\n");
+ if (*pos >= res)
+ return 0;
+
+ res -= *pos;
+ res = min_t(size_t, res, size);
-free_buff:
- kfree(buffs);
+ if (copy_to_user(buf, &data[*pos], res))
+ return -EFAULT;
- mutex_unlock(&control->tbl_mutex);
+ *pos += res;
- return ret == num ? 0 : -EIO;
+ return res;
+ } else {
+ return amdgpu_ras_debugfs_table_read(f, buf, size, pos);
+ }
}
-inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void)
+const struct file_operations amdgpu_ras_debugfs_eeprom_table_ops = {
+ .owner = THIS_MODULE,
+ .read = amdgpu_ras_debugfs_eeprom_table_read,
+ .write = NULL,
+ .llseek = default_llseek,
+};
+
+/**
+ * __verify_ras_table_checksum -- verify the RAS EEPROM table checksum
+ * @control: pointer to control structure
+ *
+ * Check the checksum of the stored in EEPROM RAS table.
+ *
+ * Return 0 if the checksum is correct,
+ * positive if it is not correct, and
+ * -errno on I/O error.
+ */
+static int __verify_ras_table_checksum(struct amdgpu_ras_eeprom_control *control)
{
- return EEPROM_MAX_RECORD_NUM;
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ int buf_size, res;
+ u8 csum, *buf, *pp;
+
+ buf_size = RAS_TABLE_HEADER_SIZE +
+ control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+ buf = kzalloc(buf_size, GFP_KERNEL);
+ if (!buf) {
+ DRM_ERROR("Out of memory checking RAS table checksum.\n");
+ return -ENOMEM;
+ }
+
+ res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
+ control->i2c_address +
+ control->ras_header_offset,
+ buf, buf_size);
+ if (res < buf_size) {
+ DRM_ERROR("Partial read for checksum, res:%d\n", res);
+ /* On partial reads, return -EIO.
+ */
+ if (res >= 0)
+ res = -EIO;
+ goto Out;
+ }
+
+ csum = 0;
+ for (pp = buf; pp < buf + buf_size; pp++)
+ csum += *pp;
+Out:
+ kfree(buf);
+ return res < 0 ? res : csum;
}
-/* Used for testing if bugs encountered */
-#if 0
-void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control)
+int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
+ bool *exceed_err_limit)
{
- int i;
- struct eeprom_table_record *recs = kcalloc(1, sizeof(*recs), GFP_KERNEL);
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 };
+ struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+ int res;
+
+ *exceed_err_limit = false;
+
+ if (!__is_ras_eeprom_supported(adev))
+ return 0;
- if (!recs)
- return;
+ /* Verify i2c adapter is initialized */
+ if (!adev->pm.smu_i2c.algo)
+ return -ENOENT;
- for (i = 0; i < 1 ; i++) {
- recs[i].address = 0xdeadbeef;
- recs[i].retired_page = i;
+ if (!__get_eeprom_i2c_addr(adev, control))
+ return -EINVAL;
+
+ control->ras_header_offset = RAS_HDR_START;
+ control->ras_record_offset = RAS_RECORD_START;
+ control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
+ mutex_init(&control->ras_tbl_mutex);
+
+ /* Read the table header from EEPROM address */
+ res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
+ control->i2c_address + control->ras_header_offset,
+ buf, RAS_TABLE_HEADER_SIZE);
+ if (res < RAS_TABLE_HEADER_SIZE) {
+ DRM_ERROR("Failed to read EEPROM table header, res:%d", res);
+ return res >= 0 ? -EIO : res;
}
- if (!amdgpu_ras_eeprom_process_recods(control, recs, true, 1)) {
+ __decode_table_header_from_buf(hdr, buf);
- memset(recs, 0, sizeof(*recs) * 1);
+ control->ras_num_recs = RAS_NUM_RECS(hdr);
+ control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset);
- control->next_addr = EEPROM_RECORD_START;
+ if (hdr->header == RAS_TABLE_HDR_VAL) {
+ DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records",
+ control->ras_num_recs);
+ res = __verify_ras_table_checksum(control);
+ if (res)
+ DRM_ERROR("RAS table incorrect checksum or error:%d\n",
+ res);
+ } else if (hdr->header == RAS_TABLE_HDR_BAD &&
+ amdgpu_bad_page_threshold != 0) {
+ res = __verify_ras_table_checksum(control);
+ if (res)
+ DRM_ERROR("RAS Table incorrect checksum or error:%d\n",
+ res);
+ if (ras->bad_page_cnt_threshold > control->ras_num_recs) {
+ /* This means that, the threshold was increased since
+ * the last time the system was booted, and now,
+ * ras->bad_page_cnt_threshold - control->num_recs > 0,
+ * so that at least one more record can be saved,
+ * before the page count threshold is reached.
+ */
+ dev_info(adev->dev,
+ "records:%d threshold:%d, resetting "
+ "RAS table header signature",
+ control->ras_num_recs,
+ ras->bad_page_cnt_threshold);
+ res = amdgpu_ras_eeprom_correct_header_tag(control,
+ RAS_TABLE_HDR_VAL);
+ } else {
+ *exceed_err_limit = true;
+ dev_err(adev->dev,
+ "RAS records:%d exceed threshold:%d, "
+ "maybe retire this GPU?",
+ control->ras_num_recs, ras->bad_page_cnt_threshold);
+ }
+ } else {
+ DRM_INFO("Creating a new EEPROM table");
- if (!amdgpu_ras_eeprom_process_recods(control, recs, false, 1)) {
- for (i = 0; i < 1; i++)
- DRM_INFO("rec.address :0x%llx, rec.retired_page :%llu",
- recs[i].address, recs[i].retired_page);
- } else
- DRM_ERROR("Failed in reading from table");
+ res = amdgpu_ras_eeprom_reset_table(control);
+ }
- } else
- DRM_ERROR("Failed in writing to table");
+ return res < 0 ? res : 0;
}
-#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
index 178721170974..f95fc61b3021 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
@@ -28,10 +28,11 @@
struct amdgpu_device;
-enum amdgpu_ras_eeprom_err_type{
- AMDGPU_RAS_EEPROM_ERR_PLACE_HOLDER,
+enum amdgpu_ras_eeprom_err_type {
+ AMDGPU_RAS_EEPROM_ERR_NA,
AMDGPU_RAS_EEPROM_ERR_RECOVERABLE,
- AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE
+ AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE,
+ AMDGPU_RAS_EEPROM_ERR_COUNT,
};
struct amdgpu_ras_eeprom_table_header {
@@ -40,15 +41,45 @@ struct amdgpu_ras_eeprom_table_header {
uint32_t first_rec_offset;
uint32_t tbl_size;
uint32_t checksum;
-}__attribute__((__packed__));
+} __packed;
struct amdgpu_ras_eeprom_control {
struct amdgpu_ras_eeprom_table_header tbl_hdr;
- uint32_t next_addr;
- unsigned int num_recs;
- struct mutex tbl_mutex;
- uint32_t tbl_byte_sum;
- uint16_t i2c_address; // 8-bit represented address
+
+ /* Base I2C EEPPROM 19-bit memory address,
+ * where the table is located. For more information,
+ * see top of amdgpu_eeprom.c.
+ */
+ u32 i2c_address;
+
+ /* The byte offset off of @i2c_address
+ * where the table header is found,
+ * and where the records start--always
+ * right after the header.
+ */
+ u32 ras_header_offset;
+ u32 ras_record_offset;
+
+ /* Number of records in the table.
+ */
+ u32 ras_num_recs;
+
+ /* First record index to read, 0-based.
+ * Range is [0, num_recs-1]. This is
+ * an absolute index, starting right after
+ * the table header.
+ */
+ u32 ras_fri;
+
+ /* Maximum possible number of records
+ * we could store, i.e. the maximum capacity
+ * of the table.
+ */
+ u32 ras_max_record_count;
+
+ /* Protect table access via this mutex.
+ */
+ struct mutex ras_tbl_mutex;
};
/*
@@ -74,21 +105,26 @@ struct eeprom_table_record {
unsigned char mem_channel;
unsigned char mcumc_id;
-}__attribute__((__packed__));
+} __packed;
int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
- bool *exceed_err_limit);
+ bool *exceed_err_limit);
+
int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control);
bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev);
-int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *records,
- bool write,
- int num);
+int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *records, const u32 num);
+
+int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *records, const u32 num);
+
+inline uint32_t amdgpu_ras_eeprom_max_record_count(void);
-inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void);
+void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control);
-void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control);
+extern const struct file_operations amdgpu_ras_debugfs_eeprom_size_ops;
+extern const struct file_operations amdgpu_ras_debugfs_eeprom_table_ops;
#endif // _AMDGPU_RAS_EEPROM_H
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index e7d3d0dbdd96..e713d31619fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -48,6 +48,9 @@
#define AMDGPU_FENCE_FLAG_INT (1 << 1)
#define AMDGPU_FENCE_FLAG_TC_WB_ONLY (1 << 2)
+/* fence flag bit to indicate the face is embedded in job*/
+#define AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT (DMA_FENCE_FLAG_USER_BITS + 1)
+
#define to_amdgpu_ring(s) container_of((s), struct amdgpu_ring, sched)
#define AMDGPU_IB_POOL_SIZE (1024 * 1024)
@@ -106,9 +109,6 @@ struct amdgpu_fence_driver {
struct dma_fence **fences;
};
-int amdgpu_fence_driver_init(struct amdgpu_device *adev);
-void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev);
-void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev);
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
@@ -117,9 +117,11 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
struct amdgpu_irq_src *irq_src,
unsigned irq_type);
-void amdgpu_fence_driver_suspend(struct amdgpu_device *adev);
-void amdgpu_fence_driver_resume(struct amdgpu_device *adev);
-int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence,
+void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev);
+void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev);
+int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev);
+void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev);
+int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence, struct amdgpu_job *job,
unsigned flags);
int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s,
uint32_t timeout);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h
index 7a4775ab6804..00afd0dcae86 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h
@@ -127,8 +127,8 @@ struct amdgpu_rlc_funcs {
void (*reset)(struct amdgpu_device *adev);
void (*start)(struct amdgpu_device *adev);
void (*update_spm_vmid)(struct amdgpu_device *adev, unsigned vmid);
- void (*rlcg_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 acc_flags, u32 hwip);
- u32 (*rlcg_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip);
+ void (*sriov_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 acc_flags, u32 hwip);
+ u32 (*sriov_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip);
bool (*is_rlcg_access_range)(struct amdgpu_device *adev, uint32_t reg);
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index de91d29c9d96..65debb65a5df 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -105,7 +105,6 @@ int amdgpu_sdma_ras_late_init(struct amdgpu_device *adev,
adev->sdma.ras_if->block = AMDGPU_RAS_BLOCK__SDMA;
adev->sdma.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->sdma.ras_if->sub_block_index = 0;
- strcpy(adev->sdma.ras_if->name, "sdma");
}
fs_info.head = ih_info->head = *adev->sdma.ras_if;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c
index 123453999093..cc7597a15fe9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c
@@ -80,7 +80,7 @@ void psp_securedisplay_parse_resp_status(struct psp_context *psp,
void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct securedisplay_cmd **cmd,
enum ta_securedisplay_command command_id)
{
- *cmd = (struct securedisplay_cmd *)psp->securedisplay_context.securedisplay_shared_buf;
+ *cmd = (struct securedisplay_cmd *)psp->securedisplay_context.context.mem_context.shared_buf;
memset(*cmd, 0, sizeof(struct securedisplay_cmd));
(*cmd)->status = TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE;
(*cmd)->cmd_id = command_id;
@@ -170,7 +170,7 @@ void amdgpu_securedisplay_debugfs_init(struct amdgpu_device *adev)
{
#if defined(CONFIG_DEBUG_FS)
- if (!adev->psp.securedisplay_context.securedisplay_initialized)
+ if (!adev->psp.securedisplay_context.context.initialized)
return;
debugfs_create_file("securedisplay_test", S_IWUSR, adev_to_drm(adev)->primary->debugfs_root,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index 1b2ceccaf5b0..862eb3c1c4c5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -28,6 +28,8 @@
* Christian König <christian.koenig@amd.com>
*/
+#include <linux/dma-fence-chain.h>
+
#include "amdgpu.h"
#include "amdgpu_trace.h"
#include "amdgpu_amdkfd.h"
@@ -186,6 +188,55 @@ int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence)
return amdgpu_sync_fence(sync, fence);
}
+/* Determine based on the owner and mode if we should sync to a fence or not */
+static bool amdgpu_sync_test_fence(struct amdgpu_device *adev,
+ enum amdgpu_sync_mode mode,
+ void *owner, struct dma_fence *f)
+{
+ void *fence_owner = amdgpu_sync_get_owner(f);
+
+ /* Always sync to moves, no matter what */
+ if (fence_owner == AMDGPU_FENCE_OWNER_UNDEFINED)
+ return true;
+
+ /* We only want to trigger KFD eviction fences on
+ * evict or move jobs. Skip KFD fences otherwise.
+ */
+ if (fence_owner == AMDGPU_FENCE_OWNER_KFD &&
+ owner != AMDGPU_FENCE_OWNER_UNDEFINED)
+ return false;
+
+ /* Never sync to VM updates either. */
+ if (fence_owner == AMDGPU_FENCE_OWNER_VM &&
+ owner != AMDGPU_FENCE_OWNER_UNDEFINED)
+ return false;
+
+ /* Ignore fences depending on the sync mode */
+ switch (mode) {
+ case AMDGPU_SYNC_ALWAYS:
+ return true;
+
+ case AMDGPU_SYNC_NE_OWNER:
+ if (amdgpu_sync_same_dev(adev, f) &&
+ fence_owner == owner)
+ return false;
+ break;
+
+ case AMDGPU_SYNC_EQ_OWNER:
+ if (amdgpu_sync_same_dev(adev, f) &&
+ fence_owner != owner)
+ return false;
+ break;
+
+ case AMDGPU_SYNC_EXPLICIT:
+ return false;
+ }
+
+ WARN(debug_evictions && fence_owner == AMDGPU_FENCE_OWNER_KFD,
+ "Adding eviction fence to sync obj");
+ return true;
+}
+
/**
* amdgpu_sync_resv - sync to a reservation object
*
@@ -211,67 +262,34 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
/* always sync to the exclusive fence */
f = dma_resv_excl_fence(resv);
- r = amdgpu_sync_fence(sync, f);
+ dma_fence_chain_for_each(f, f) {
+ struct dma_fence_chain *chain = to_dma_fence_chain(f);
+
+ if (amdgpu_sync_test_fence(adev, mode, owner, chain ?
+ chain->fence : f)) {
+ r = amdgpu_sync_fence(sync, f);
+ dma_fence_put(f);
+ if (r)
+ return r;
+ break;
+ }
+ }
flist = dma_resv_shared_list(resv);
- if (!flist || r)
- return r;
+ if (!flist)
+ return 0;
for (i = 0; i < flist->shared_count; ++i) {
- void *fence_owner;
-
f = rcu_dereference_protected(flist->shared[i],
dma_resv_held(resv));
- fence_owner = amdgpu_sync_get_owner(f);
-
- /* Always sync to moves, no matter what */
- if (fence_owner == AMDGPU_FENCE_OWNER_UNDEFINED) {
+ if (amdgpu_sync_test_fence(adev, mode, owner, f)) {
r = amdgpu_sync_fence(sync, f);
if (r)
- break;
- }
-
- /* We only want to trigger KFD eviction fences on
- * evict or move jobs. Skip KFD fences otherwise.
- */
- if (fence_owner == AMDGPU_FENCE_OWNER_KFD &&
- owner != AMDGPU_FENCE_OWNER_UNDEFINED)
- continue;
-
- /* Never sync to VM updates either. */
- if (fence_owner == AMDGPU_FENCE_OWNER_VM &&
- owner != AMDGPU_FENCE_OWNER_UNDEFINED)
- continue;
-
- /* Ignore fences depending on the sync mode */
- switch (mode) {
- case AMDGPU_SYNC_ALWAYS:
- break;
-
- case AMDGPU_SYNC_NE_OWNER:
- if (amdgpu_sync_same_dev(adev, f) &&
- fence_owner == owner)
- continue;
- break;
-
- case AMDGPU_SYNC_EQ_OWNER:
- if (amdgpu_sync_same_dev(adev, f) &&
- fence_owner != owner)
- continue;
- break;
-
- case AMDGPU_SYNC_EXPLICIT:
- continue;
+ return r;
}
-
- WARN(debug_evictions && fence_owner == AMDGPU_FENCE_OWNER_KFD,
- "Adding eviction fence to sync obj");
- r = amdgpu_sync_fence(sync, f);
- if (r)
- break;
}
- return r;
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 3a55f08e00e1..38dade421d46 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -149,14 +149,16 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
* BOs to be evicted from VRAM
*/
amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM |
- AMDGPU_GEM_DOMAIN_GTT);
+ AMDGPU_GEM_DOMAIN_GTT |
+ AMDGPU_GEM_DOMAIN_CPU);
abo->placements[0].fpfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
abo->placements[0].lpfn = 0;
abo->placement.busy_placement = &abo->placements[1];
abo->placement.num_busy_placement = 1;
} else {
/* Move to GTT memory */
- amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT);
+ amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT |
+ AMDGPU_GEM_DOMAIN_CPU);
}
break;
case TTM_PL_TT:
@@ -521,7 +523,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
hop->fpfn = 0;
hop->lpfn = 0;
hop->mem_type = TTM_PL_TT;
- hop->flags = 0;
+ hop->flags = TTM_PL_FLAG_TEMPORARY;
return -EMULTIHOP;
}
@@ -1121,7 +1123,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev,
struct amdgpu_ttm_tt *gtt = (void *)ttm;
/* user pages are bound by amdgpu_ttm_tt_pin_userptr() */
- if (gtt && gtt->userptr) {
+ if (gtt->userptr) {
ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
if (!ttm->sg)
return -ENOMEM;
@@ -1146,7 +1148,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev,
struct amdgpu_ttm_tt *gtt = (void *)ttm;
struct amdgpu_device *adev;
- if (gtt && gtt->userptr) {
+ if (gtt->userptr) {
amdgpu_ttm_tt_set_user_pages(ttm, NULL);
kfree(ttm->sg);
ttm->sg = NULL;
@@ -1394,6 +1396,41 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
return ttm_bo_eviction_valuable(bo, place);
}
+static void amdgpu_ttm_vram_mm_access(struct amdgpu_device *adev, loff_t pos,
+ void *buf, size_t size, bool write)
+{
+ while (size) {
+ uint64_t aligned_pos = ALIGN_DOWN(pos, 4);
+ uint64_t bytes = 4 - (pos & 0x3);
+ uint32_t shift = (pos & 0x3) * 8;
+ uint32_t mask = 0xffffffff << shift;
+ uint32_t value = 0;
+
+ if (size < bytes) {
+ mask &= 0xffffffff >> (bytes - size) * 8;
+ bytes = size;
+ }
+
+ if (mask != 0xffffffff) {
+ amdgpu_device_mm_access(adev, aligned_pos, &value, 4, false);
+ if (write) {
+ value &= ~mask;
+ value |= (*(uint32_t *)buf << shift) & mask;
+ amdgpu_device_mm_access(adev, aligned_pos, &value, 4, true);
+ } else {
+ value = (value & mask) >> shift;
+ memcpy(buf, &value, bytes);
+ }
+ } else {
+ amdgpu_device_mm_access(adev, aligned_pos, buf, 4, write);
+ }
+
+ pos += bytes;
+ buf += bytes;
+ size -= bytes;
+ }
+}
+
/**
* amdgpu_ttm_access_memory - Read or Write memory that backs a buffer object.
*
@@ -1413,8 +1450,6 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
struct amdgpu_res_cursor cursor;
- unsigned long flags;
- uint32_t value = 0;
int ret = 0;
if (bo->resource->mem_type != TTM_PL_VRAM)
@@ -1422,41 +1457,21 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
amdgpu_res_first(bo->resource, offset, len, &cursor);
while (cursor.remaining) {
- uint64_t aligned_pos = cursor.start & ~(uint64_t)3;
- uint64_t bytes = 4 - (cursor.start & 3);
- uint32_t shift = (cursor.start & 3) * 8;
- uint32_t mask = 0xffffffff << shift;
-
- if (cursor.size < bytes) {
- mask &= 0xffffffff >> (bytes - cursor.size) * 8;
- bytes = cursor.size;
- }
-
- if (mask != 0xffffffff) {
- spin_lock_irqsave(&adev->mmio_idx_lock, flags);
- WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)aligned_pos) | 0x80000000);
- WREG32_NO_KIQ(mmMM_INDEX_HI, aligned_pos >> 31);
- value = RREG32_NO_KIQ(mmMM_DATA);
- if (write) {
- value &= ~mask;
- value |= (*(uint32_t *)buf << shift) & mask;
- WREG32_NO_KIQ(mmMM_DATA, value);
- }
- spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
- if (!write) {
- value = (value & mask) >> shift;
- memcpy(buf, &value, bytes);
- }
- } else {
- bytes = cursor.size & ~0x3ULL;
- amdgpu_device_vram_access(adev, cursor.start,
- (uint32_t *)buf, bytes,
- write);
+ size_t count, size = cursor.size;
+ loff_t pos = cursor.start;
+
+ count = amdgpu_device_aper_access(adev, pos, buf, size, write);
+ size -= count;
+ if (size) {
+ /* using MM to access rest vram and handle un-aligned address */
+ pos += count;
+ buf += count;
+ amdgpu_ttm_vram_mm_access(adev, pos, buf, size, write);
}
- ret += bytes;
- buf = (uint8_t *)buf + bytes;
- amdgpu_res_next(&cursor, bytes);
+ ret += cursor.size;
+ buf += cursor.size;
+ amdgpu_res_next(&cursor, cursor.size);
}
return ret;
@@ -2146,7 +2161,6 @@ static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf,
return -ENXIO;
while (size) {
- unsigned long flags;
uint32_t value;
if (*pos >= adev->gmc.mc_vram_size)
@@ -2156,11 +2170,7 @@ static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf,
if (r)
return r;
- spin_lock_irqsave(&adev->mmio_idx_lock, flags);
- WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)*pos) | 0x80000000);
- WREG32_NO_KIQ(mmMM_INDEX_HI, *pos >> 31);
- WREG32_NO_KIQ(mmMM_DATA, value);
- spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
+ amdgpu_device_mm_access(adev, *pos, &value, 4, true);
result += 4;
buf += 4;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index e69f3e8e06e5..3205fd520060 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -52,7 +52,7 @@ struct amdgpu_gtt_mgr {
struct ttm_resource_manager manager;
struct drm_mm mm;
spinlock_t lock;
- atomic64_t available;
+ atomic64_t used;
};
struct amdgpu_preempt_mgr {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 2834981f8c08..abd8469380e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -409,6 +409,12 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
return AMDGPU_FW_LOAD_DIRECT;
else
return AMDGPU_FW_LOAD_PSP;
+ case CHIP_CYAN_SKILLFISH:
+ if (!(load_type &&
+ adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2))
+ return AMDGPU_FW_LOAD_DIRECT;
+ else
+ return AMDGPU_FW_LOAD_PSP;
default:
DRM_ERROR("Unknown firmware load type\n");
}
@@ -416,6 +422,84 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
return AMDGPU_FW_LOAD_DIRECT;
}
+const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id)
+{
+ switch (ucode_id) {
+ case AMDGPU_UCODE_ID_SDMA0:
+ return "SDMA0";
+ case AMDGPU_UCODE_ID_SDMA1:
+ return "SDMA1";
+ case AMDGPU_UCODE_ID_SDMA2:
+ return "SDMA2";
+ case AMDGPU_UCODE_ID_SDMA3:
+ return "SDMA3";
+ case AMDGPU_UCODE_ID_SDMA4:
+ return "SDMA4";
+ case AMDGPU_UCODE_ID_SDMA5:
+ return "SDMA5";
+ case AMDGPU_UCODE_ID_SDMA6:
+ return "SDMA6";
+ case AMDGPU_UCODE_ID_SDMA7:
+ return "SDMA7";
+ case AMDGPU_UCODE_ID_CP_CE:
+ return "CP_CE";
+ case AMDGPU_UCODE_ID_CP_PFP:
+ return "CP_PFP";
+ case AMDGPU_UCODE_ID_CP_ME:
+ return "CP_ME";
+ case AMDGPU_UCODE_ID_CP_MEC1:
+ return "CP_MEC1";
+ case AMDGPU_UCODE_ID_CP_MEC1_JT:
+ return "CP_MEC1_JT";
+ case AMDGPU_UCODE_ID_CP_MEC2:
+ return "CP_MEC2";
+ case AMDGPU_UCODE_ID_CP_MEC2_JT:
+ return "CP_MEC2_JT";
+ case AMDGPU_UCODE_ID_CP_MES:
+ return "CP_MES";
+ case AMDGPU_UCODE_ID_CP_MES_DATA:
+ return "CP_MES_DATA";
+ case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
+ return "RLC_RESTORE_LIST_CNTL";
+ case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
+ return "RLC_RESTORE_LIST_GPM_MEM";
+ case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
+ return "RLC_RESTORE_LIST_SRM_MEM";
+ case AMDGPU_UCODE_ID_RLC_IRAM:
+ return "RLC_IRAM";
+ case AMDGPU_UCODE_ID_RLC_DRAM:
+ return "RLC_DRAM";
+ case AMDGPU_UCODE_ID_RLC_G:
+ return "RLC_G";
+ case AMDGPU_UCODE_ID_STORAGE:
+ return "STORAGE";
+ case AMDGPU_UCODE_ID_SMC:
+ return "SMC";
+ case AMDGPU_UCODE_ID_UVD:
+ return "UVD";
+ case AMDGPU_UCODE_ID_UVD1:
+ return "UVD1";
+ case AMDGPU_UCODE_ID_VCE:
+ return "VCE";
+ case AMDGPU_UCODE_ID_VCN:
+ return "VCN";
+ case AMDGPU_UCODE_ID_VCN1:
+ return "VCN1";
+ case AMDGPU_UCODE_ID_DMCU_ERAM:
+ return "DMCU_ERAM";
+ case AMDGPU_UCODE_ID_DMCU_INTV:
+ return "DMCU_INTV";
+ case AMDGPU_UCODE_ID_VCN0_RAM:
+ return "VCN0_RAM";
+ case AMDGPU_UCODE_ID_VCN1_RAM:
+ return "VCN1_RAM";
+ case AMDGPU_UCODE_ID_DMCUB:
+ return "DMCUB";
+ default:
+ return "UNKNOWN UCODE";
+ }
+}
+
#define FW_VERSION_ATTR(name, mode, field) \
static ssize_t show_##name(struct device *dev, \
struct device_attribute *attr, \
@@ -440,10 +524,10 @@ FW_VERSION_ATTR(rlc_srlg_fw_version, 0444, gfx.rlc_srlg_fw_version);
FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version);
FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version);
FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version);
-FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos_fw_version);
-FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_fw_version);
-FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ta_ras_ucode_version);
-FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.ta_xgmi_ucode_version);
+FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version);
+FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd.fw_version);
+FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras.feature_version);
+FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi.feature_version);
FW_VERSION_ATTR(smc_fw_version, 0444, pm.fw_version);
FW_VERSION_ATTR(sdma_fw_version, 0444, sdma.instance[0].fw_version);
FW_VERSION_ATTR(sdma2_fw_version, 0444, sdma.instance[1].fw_version);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 270309e7f5f5..7c2538db3cd5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -71,7 +71,7 @@ struct smc_firmware_header_v2_1 {
uint32_t pptable_entry_offset;
};
-struct psp_fw_bin_desc {
+struct psp_fw_legacy_bin_desc {
uint32_t fw_version;
uint32_t offset_bytes;
uint32_t size_bytes;
@@ -80,50 +80,67 @@ struct psp_fw_bin_desc {
/* version_major=1, version_minor=0 */
struct psp_firmware_header_v1_0 {
struct common_firmware_header header;
- struct psp_fw_bin_desc sos;
+ struct psp_fw_legacy_bin_desc sos;
};
/* version_major=1, version_minor=1 */
struct psp_firmware_header_v1_1 {
struct psp_firmware_header_v1_0 v1_0;
- struct psp_fw_bin_desc toc;
- struct psp_fw_bin_desc kdb;
+ struct psp_fw_legacy_bin_desc toc;
+ struct psp_fw_legacy_bin_desc kdb;
};
/* version_major=1, version_minor=2 */
struct psp_firmware_header_v1_2 {
struct psp_firmware_header_v1_0 v1_0;
- struct psp_fw_bin_desc res;
- struct psp_fw_bin_desc kdb;
+ struct psp_fw_legacy_bin_desc res;
+ struct psp_fw_legacy_bin_desc kdb;
};
/* version_major=1, version_minor=3 */
struct psp_firmware_header_v1_3 {
struct psp_firmware_header_v1_1 v1_1;
- struct psp_fw_bin_desc spl;
- struct psp_fw_bin_desc rl;
- struct psp_fw_bin_desc sys_drv_aux;
- struct psp_fw_bin_desc sos_aux;
+ struct psp_fw_legacy_bin_desc spl;
+ struct psp_fw_legacy_bin_desc rl;
+ struct psp_fw_legacy_bin_desc sys_drv_aux;
+ struct psp_fw_legacy_bin_desc sos_aux;
+};
+
+struct psp_fw_bin_desc {
+ uint32_t fw_type;
+ uint32_t fw_version;
+ uint32_t offset_bytes;
+ uint32_t size_bytes;
+};
+
+enum psp_fw_type {
+ PSP_FW_TYPE_UNKOWN,
+ PSP_FW_TYPE_PSP_SOS,
+ PSP_FW_TYPE_PSP_SYS_DRV,
+ PSP_FW_TYPE_PSP_KDB,
+ PSP_FW_TYPE_PSP_TOC,
+ PSP_FW_TYPE_PSP_SPL,
+ PSP_FW_TYPE_PSP_RL,
+ PSP_FW_TYPE_PSP_SOC_DRV,
+ PSP_FW_TYPE_PSP_INTF_DRV,
+ PSP_FW_TYPE_PSP_DBG_DRV,
+};
+
+/* version_major=2, version_minor=0 */
+struct psp_firmware_header_v2_0 {
+ struct common_firmware_header header;
+ uint32_t psp_fw_bin_count;
+ struct psp_fw_bin_desc psp_fw_bin[];
};
/* version_major=1, version_minor=0 */
struct ta_firmware_header_v1_0 {
struct common_firmware_header header;
- uint32_t ta_xgmi_ucode_version;
- uint32_t ta_xgmi_offset_bytes;
- uint32_t ta_xgmi_size_bytes;
- uint32_t ta_ras_ucode_version;
- uint32_t ta_ras_offset_bytes;
- uint32_t ta_ras_size_bytes;
- uint32_t ta_hdcp_ucode_version;
- uint32_t ta_hdcp_offset_bytes;
- uint32_t ta_hdcp_size_bytes;
- uint32_t ta_dtm_ucode_version;
- uint32_t ta_dtm_offset_bytes;
- uint32_t ta_dtm_size_bytes;
- uint32_t ta_securedisplay_ucode_version;
- uint32_t ta_securedisplay_offset_bytes;
- uint32_t ta_securedisplay_size_bytes;
+ struct psp_fw_legacy_bin_desc xgmi;
+ struct psp_fw_legacy_bin_desc ras;
+ struct psp_fw_legacy_bin_desc hdcp;
+ struct psp_fw_legacy_bin_desc dtm;
+ struct psp_fw_legacy_bin_desc securedisplay;
};
enum ta_fw_type {
@@ -138,18 +155,11 @@ enum ta_fw_type {
TA_FW_TYPE_MAX_INDEX,
};
-struct ta_fw_bin_desc {
- uint32_t fw_type;
- uint32_t fw_version;
- uint32_t offset_bytes;
- uint32_t size_bytes;
-};
-
/* version_major=2, version_minor=0 */
struct ta_firmware_header_v2_0 {
struct common_firmware_header header;
uint32_t ta_fw_bin_count;
- struct ta_fw_bin_desc ta_fw_bin[];
+ struct psp_fw_bin_desc ta_fw_bin[];
};
/* version_major=1, version_minor=0 */
@@ -312,6 +322,7 @@ union amdgpu_firmware_header {
struct psp_firmware_header_v1_0 psp;
struct psp_firmware_header_v1_1 psp_v1_1;
struct psp_firmware_header_v1_3 psp_v1_3;
+ struct psp_firmware_header_v2_0 psp_v2_0;
struct ta_firmware_header_v1_0 ta;
struct ta_firmware_header_v2_0 ta_v2_0;
struct gfx_firmware_header_v1_0 gfx;
@@ -326,7 +337,7 @@ union amdgpu_firmware_header {
uint8_t raw[0x100];
};
-#define UCODE_MAX_TA_PACKAGING ((sizeof(union amdgpu_firmware_header) - sizeof(struct common_firmware_header) - 4) / sizeof(struct ta_fw_bin_desc))
+#define UCODE_MAX_PSP_PACKAGING ((sizeof(union amdgpu_firmware_header) - sizeof(struct common_firmware_header) - 4) / sizeof(struct psp_fw_bin_desc))
/*
* fw loading support
@@ -449,4 +460,6 @@ void amdgpu_ucode_sysfs_fini(struct amdgpu_device *adev);
enum amdgpu_firmware_load_type
amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type);
+const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
index f4489773715e..a90029ee9733 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
@@ -41,7 +41,6 @@ int amdgpu_umc_ras_late_init(struct amdgpu_device *adev)
adev->umc.ras_if->block = AMDGPU_RAS_BLOCK__UMC;
adev->umc.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->umc.ras_if->sub_block_index = 0;
- strcpy(adev->umc.ras_if->name, "umc");
}
ih_info.head = fs_info.head = *adev->umc.ras_if;
@@ -134,7 +133,7 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
amdgpu_ras_save_bad_pages(adev);
if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num)
- adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.num_recs);
+ adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs);
}
amdgpu_ras_reset_gpu(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 0f576f294d8a..d451c359606a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -326,7 +326,6 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
{
int i, j;
- cancel_delayed_work_sync(&adev->uvd.idle_work);
drm_sched_entity_destroy(&adev->uvd.entity);
for (j = 0; j < adev->uvd.num_uvd_inst; ++j) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 1ae7f824adc7..8e8dee9fac9f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -218,7 +218,6 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
if (adev->vce.vcpu_bo == NULL)
return 0;
- cancel_delayed_work_sync(&adev->vce.idle_work);
drm_sched_entity_destroy(&adev->vce.entity);
amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 6780df0fb265..008a308a4eca 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -258,8 +258,6 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
{
int i, j;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
-
for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
if (adev->vcn.harvest_config & (1 << j))
continue;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index b71dd1deeb2d..ca058fbcccd4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -531,10 +531,10 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev)
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version);
- POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos_fw_version);
- POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd_fw_version);
- POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS, adev->psp.ta_ras_ucode_version);
- POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, adev->psp.ta_xgmi_ucode_version);
+ POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version);
+ POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd.fw_version);
+ POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS, adev->psp.ras.feature_version);
+ POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, adev->psp.xgmi.feature_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SMC, adev->pm.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA, adev->sdma.instance[0].fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA2, adev->sdma.instance[1].fw_version);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
new file mode 100644
index 000000000000..ce982afeff91
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -0,0 +1,643 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_vblank.h>
+
+#include "amdgpu.h"
+#ifdef CONFIG_DRM_AMDGPU_SI
+#include "dce_v6_0.h"
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
+#include "dce_v8_0.h"
+#endif
+#include "dce_v10_0.h"
+#include "dce_v11_0.h"
+#include "ivsrcid/ivsrcid_vislands30.h"
+#include "amdgpu_vkms.h"
+#include "amdgpu_display.h"
+
+/**
+ * DOC: amdgpu_vkms
+ *
+ * The amdgpu vkms interface provides a virtual KMS interface for several use
+ * cases: devices without display hardware, platforms where the actual display
+ * hardware is not useful (e.g., servers), SR-IOV virtual functions, device
+ * emulation/simulation, and device bring up prior to display hardware being
+ * usable. We previously emulated a legacy KMS interface, but there was a desire
+ * to move to the atomic KMS interface. The vkms driver did everything we
+ * needed, but we wanted KMS support natively in the driver without buffer
+ * sharing and the ability to support an instance of VKMS per device. We first
+ * looked at splitting vkms into a stub driver and a helper module that other
+ * drivers could use to implement a virtual display, but this strategy ended up
+ * being messy due to driver specific callbacks needed for buffer management.
+ * Ultimately, it proved easier to import the vkms code as it mostly used core
+ * drm helpers anyway.
+ */
+
+static const u32 amdgpu_vkms_formats[] = {
+ DRM_FORMAT_XRGB8888,
+};
+
+static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
+{
+ struct amdgpu_vkms_output *output = container_of(timer,
+ struct amdgpu_vkms_output,
+ vblank_hrtimer);
+ struct drm_crtc *crtc = &output->crtc;
+ u64 ret_overrun;
+ bool ret;
+
+ ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
+ output->period_ns);
+ WARN_ON(ret_overrun != 1);
+
+ ret = drm_crtc_handle_vblank(crtc);
+ if (!ret)
+ DRM_ERROR("amdgpu_vkms failure on handling vblank");
+
+ return HRTIMER_RESTART;
+}
+
+static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ unsigned int pipe = drm_crtc_index(crtc);
+ struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+ struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
+
+ drm_calc_timestamping_constants(crtc, &crtc->mode);
+
+ hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
+ out->period_ns = ktime_set(0, vblank->framedur_ns);
+ hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL);
+
+ return 0;
+}
+
+static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
+{
+ struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
+
+ hrtimer_cancel(&out->vblank_hrtimer);
+}
+
+static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
+ int *max_error,
+ ktime_t *vblank_time,
+ bool in_vblank_irq)
+{
+ struct drm_device *dev = crtc->dev;
+ unsigned int pipe = crtc->index;
+ struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
+ struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+ if (!READ_ONCE(vblank->enabled)) {
+ *vblank_time = ktime_get();
+ return true;
+ }
+
+ *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
+
+ if (WARN_ON(*vblank_time == vblank->time))
+ return true;
+
+ /*
+ * To prevent races we roll the hrtimer forward before we do any
+ * interrupt processing - this is how real hw works (the interrupt is
+ * only generated after all the vblank registers are updated) and what
+ * the vblank core expects. Therefore we need to always correct the
+ * timestampe by one frame.
+ */
+ *vblank_time -= output->period_ns;
+
+ return true;
+}
+
+static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
+ .set_config = drm_atomic_helper_set_config,
+ .destroy = drm_crtc_cleanup,
+ .page_flip = drm_atomic_helper_page_flip,
+ .reset = drm_atomic_helper_crtc_reset,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+ .enable_vblank = amdgpu_vkms_enable_vblank,
+ .disable_vblank = amdgpu_vkms_disable_vblank,
+ .get_vblank_timestamp = amdgpu_vkms_get_vblank_timestamp,
+};
+
+static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ drm_crtc_vblank_on(crtc);
+}
+
+static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ drm_crtc_vblank_off(crtc);
+}
+
+static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ if (crtc->state->event) {
+ spin_lock(&crtc->dev->event_lock);
+
+ if (drm_crtc_vblank_get(crtc) != 0)
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ else
+ drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+
+ spin_unlock(&crtc->dev->event_lock);
+
+ crtc->state->event = NULL;
+ }
+}
+
+static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
+ .atomic_flush = amdgpu_vkms_crtc_atomic_flush,
+ .atomic_enable = amdgpu_vkms_crtc_atomic_enable,
+ .atomic_disable = amdgpu_vkms_crtc_atomic_disable,
+};
+
+static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+ struct drm_plane *primary, struct drm_plane *cursor)
+{
+ int ret;
+
+ ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
+ &amdgpu_vkms_crtc_funcs, NULL);
+ if (ret) {
+ DRM_ERROR("Failed to init CRTC\n");
+ return ret;
+ }
+
+ drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
+
+ return ret;
+}
+
+static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *mode = NULL;
+ unsigned i;
+ static const struct mode_size {
+ int w;
+ int h;
+ } common_modes[] = {
+ { 640, 480},
+ { 720, 480},
+ { 800, 600},
+ { 848, 480},
+ {1024, 768},
+ {1152, 768},
+ {1280, 720},
+ {1280, 800},
+ {1280, 854},
+ {1280, 960},
+ {1280, 1024},
+ {1440, 900},
+ {1400, 1050},
+ {1680, 1050},
+ {1600, 1200},
+ {1920, 1080},
+ {1920, 1200},
+ {2560, 1440},
+ {4096, 3112},
+ {3656, 2664},
+ {3840, 2160},
+ {4096, 2160},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
+ mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
+ drm_mode_probed_add(connector, mode);
+ }
+
+ drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
+
+ return ARRAY_SIZE(common_modes);
+}
+
+static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
+ .get_modes = amdgpu_vkms_conn_get_modes,
+};
+
+static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *old_state)
+{
+ return;
+}
+
+static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
+ struct drm_atomic_state *state)
+{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
+ plane);
+ struct drm_crtc_state *crtc_state;
+ int ret;
+
+ if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))
+ return 0;
+
+ crtc_state = drm_atomic_get_crtc_state(state,
+ new_plane_state->crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ false, true);
+ if (ret != 0)
+ return ret;
+
+ /* for now primary plane must be visible and full screen */
+ if (!new_plane_state->visible)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
+{
+ struct amdgpu_framebuffer *afb;
+ struct drm_gem_object *obj;
+ struct amdgpu_device *adev;
+ struct amdgpu_bo *rbo;
+ struct list_head list;
+ struct ttm_validate_buffer tv;
+ struct ww_acquire_ctx ticket;
+ uint32_t domain;
+ int r;
+
+ if (!new_state->fb) {
+ DRM_DEBUG_KMS("No FB bound\n");
+ return 0;
+ }
+ afb = to_amdgpu_framebuffer(new_state->fb);
+ obj = new_state->fb->obj[0];
+ rbo = gem_to_amdgpu_bo(obj);
+ adev = amdgpu_ttm_adev(rbo->tbo.bdev);
+ INIT_LIST_HEAD(&list);
+
+ tv.bo = &rbo->tbo;
+ tv.num_shared = 1;
+ list_add(&tv.head, &list);
+
+ r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
+ if (r) {
+ dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
+ return r;
+ }
+
+ if (plane->type != DRM_PLANE_TYPE_CURSOR)
+ domain = amdgpu_display_supported_domains(adev, rbo->flags);
+ else
+ domain = AMDGPU_GEM_DOMAIN_VRAM;
+
+ r = amdgpu_bo_pin(rbo, domain);
+ if (unlikely(r != 0)) {
+ if (r != -ERESTARTSYS)
+ DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
+ ttm_eu_backoff_reservation(&ticket, &list);
+ return r;
+ }
+
+ r = amdgpu_ttm_alloc_gart(&rbo->tbo);
+ if (unlikely(r != 0)) {
+ amdgpu_bo_unpin(rbo);
+ ttm_eu_backoff_reservation(&ticket, &list);
+ DRM_ERROR("%p bind failed\n", rbo);
+ return r;
+ }
+
+ ttm_eu_backoff_reservation(&ticket, &list);
+
+ afb->address = amdgpu_bo_gpu_offset(rbo);
+
+ amdgpu_bo_ref(rbo);
+
+ return 0;
+}
+
+static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct amdgpu_bo *rbo;
+ int r;
+
+ if (!old_state->fb)
+ return;
+
+ rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
+ r = amdgpu_bo_reserve(rbo, false);
+ if (unlikely(r)) {
+ DRM_ERROR("failed to reserve rbo before unpin\n");
+ return;
+ }
+
+ amdgpu_bo_unpin(rbo);
+ amdgpu_bo_unreserve(rbo);
+ amdgpu_bo_unref(&rbo);
+}
+
+static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
+ .atomic_update = amdgpu_vkms_plane_atomic_update,
+ .atomic_check = amdgpu_vkms_plane_atomic_check,
+ .prepare_fb = amdgpu_vkms_prepare_fb,
+ .cleanup_fb = amdgpu_vkms_cleanup_fb,
+};
+
+static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
+ enum drm_plane_type type,
+ int index)
+{
+ struct drm_plane *plane;
+ int ret;
+
+ plane = kzalloc(sizeof(*plane), GFP_KERNEL);
+ if (!plane)
+ return ERR_PTR(-ENOMEM);
+
+ ret = drm_universal_plane_init(dev, plane, 1 << index,
+ &amdgpu_vkms_plane_funcs,
+ amdgpu_vkms_formats,
+ ARRAY_SIZE(amdgpu_vkms_formats),
+ NULL, type, NULL);
+ if (ret) {
+ kfree(plane);
+ return ERR_PTR(ret);
+ }
+
+ drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs);
+
+ return plane;
+}
+
+int amdgpu_vkms_output_init(struct drm_device *dev,
+ struct amdgpu_vkms_output *output, int index)
+{
+ struct drm_connector *connector = &output->connector;
+ struct drm_encoder *encoder = &output->encoder;
+ struct drm_crtc *crtc = &output->crtc;
+ struct drm_plane *primary, *cursor = NULL;
+ int ret;
+
+ primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
+ if (IS_ERR(primary))
+ return PTR_ERR(primary);
+
+ ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
+ if (ret)
+ goto err_crtc;
+
+ ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL);
+ if (ret) {
+ DRM_ERROR("Failed to init connector\n");
+ goto err_connector;
+ }
+
+ drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs);
+
+ ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
+ if (ret) {
+ DRM_ERROR("Failed to init encoder\n");
+ goto err_encoder;
+ }
+ encoder->possible_crtcs = 1 << index;
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret) {
+ DRM_ERROR("Failed to attach connector to encoder\n");
+ goto err_attach;
+ }
+
+ drm_mode_config_reset(dev);
+
+ return 0;
+
+err_attach:
+ drm_encoder_cleanup(encoder);
+
+err_encoder:
+ drm_connector_cleanup(connector);
+
+err_connector:
+ drm_crtc_cleanup(crtc);
+
+err_crtc:
+ drm_plane_cleanup(primary);
+
+ return ret;
+}
+
+const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
+ .fb_create = amdgpu_display_user_framebuffer_create,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+static int amdgpu_vkms_sw_init(void *handle)
+{
+ int r, i;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ adev_to_drm(adev)->max_vblank_count = 0;
+
+ adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
+
+ adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
+ adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
+
+ adev_to_drm(adev)->mode_config.preferred_depth = 24;
+ adev_to_drm(adev)->mode_config.prefer_shadow = 1;
+
+ adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
+
+ r = amdgpu_display_modeset_create_props(adev);
+ if (r)
+ return r;
+
+ adev->amdgpu_vkms_output = kcalloc(adev->mode_info.num_crtc, sizeof(struct amdgpu_vkms_output), GFP_KERNEL);
+ if (!adev->amdgpu_vkms_output)
+ return -ENOMEM;
+
+ /* allocate crtcs, encoders, connectors */
+ for (i = 0; i < adev->mode_info.num_crtc; i++) {
+ r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
+ if (r)
+ return r;
+ }
+
+ drm_kms_helper_poll_init(adev_to_drm(adev));
+
+ adev->mode_info.mode_config_initialized = true;
+ return 0;
+}
+
+static int amdgpu_vkms_sw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i = 0;
+
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ if (adev->mode_info.crtcs[i])
+ hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
+
+ kfree(adev->mode_info.bios_hardcoded_edid);
+ kfree(adev->amdgpu_vkms_output);
+
+ drm_kms_helper_poll_fini(adev_to_drm(adev));
+
+ adev->mode_info.mode_config_initialized = false;
+ return 0;
+}
+
+static int amdgpu_vkms_hw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ switch (adev->asic_type) {
+#ifdef CONFIG_DRM_AMDGPU_SI
+ case CHIP_TAHITI:
+ case CHIP_PITCAIRN:
+ case CHIP_VERDE:
+ case CHIP_OLAND:
+ dce_v6_0_disable_dce(adev);
+ break;
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
+ case CHIP_BONAIRE:
+ case CHIP_HAWAII:
+ case CHIP_KAVERI:
+ case CHIP_KABINI:
+ case CHIP_MULLINS:
+ dce_v8_0_disable_dce(adev);
+ break;
+#endif
+ case CHIP_FIJI:
+ case CHIP_TONGA:
+ dce_v10_0_disable_dce(adev);
+ break;
+ case CHIP_CARRIZO:
+ case CHIP_STONEY:
+ case CHIP_POLARIS10:
+ case CHIP_POLARIS11:
+ case CHIP_VEGAM:
+ dce_v11_0_disable_dce(adev);
+ break;
+ case CHIP_TOPAZ:
+#ifdef CONFIG_DRM_AMDGPU_SI
+ case CHIP_HAINAN:
+#endif
+ /* no DCE */
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int amdgpu_vkms_hw_fini(void *handle)
+{
+ return 0;
+}
+
+static int amdgpu_vkms_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = drm_mode_config_helper_suspend(adev_to_drm(adev));
+ if (r)
+ return r;
+ return amdgpu_vkms_hw_fini(handle);
+}
+
+static int amdgpu_vkms_resume(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_vkms_hw_init(handle);
+ if (r)
+ return r;
+ return drm_mode_config_helper_resume(adev_to_drm(adev));
+}
+
+static bool amdgpu_vkms_is_idle(void *handle)
+{
+ return true;
+}
+
+static int amdgpu_vkms_wait_for_idle(void *handle)
+{
+ return 0;
+}
+
+static int amdgpu_vkms_soft_reset(void *handle)
+{
+ return 0;
+}
+
+static int amdgpu_vkms_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state)
+{
+ return 0;
+}
+
+static int amdgpu_vkms_set_powergating_state(void *handle,
+ enum amd_powergating_state state)
+{
+ return 0;
+}
+
+static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
+ .name = "amdgpu_vkms",
+ .early_init = NULL,
+ .late_init = NULL,
+ .sw_init = amdgpu_vkms_sw_init,
+ .sw_fini = amdgpu_vkms_sw_fini,
+ .hw_init = amdgpu_vkms_hw_init,
+ .hw_fini = amdgpu_vkms_hw_fini,
+ .suspend = amdgpu_vkms_suspend,
+ .resume = amdgpu_vkms_resume,
+ .is_idle = amdgpu_vkms_is_idle,
+ .wait_for_idle = amdgpu_vkms_wait_for_idle,
+ .soft_reset = amdgpu_vkms_soft_reset,
+ .set_clockgating_state = amdgpu_vkms_set_clockgating_state,
+ .set_powergating_state = amdgpu_vkms_set_powergating_state,
+};
+
+const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
+{
+ .type = AMD_IP_BLOCK_TYPE_DCE,
+ .major = 1,
+ .minor = 0,
+ .rev = 0,
+ .funcs = &amdgpu_vkms_ip_funcs,
+};
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
new file mode 100644
index 000000000000..97f1b79c0724
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _AMDGPU_VKMS_H_
+#define _AMDGPU_VKMS_H_
+
+#define XRES_DEF 1024
+#define YRES_DEF 768
+
+#define XRES_MAX 16384
+#define YRES_MAX 16384
+
+#define drm_crtc_to_amdgpu_vkms_output(target) \
+ container_of(target, struct amdgpu_vkms_output, crtc)
+
+extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
+
+struct amdgpu_vkms_output {
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+ struct hrtimer vblank_hrtimer;
+ ktime_t period_ns;
+ struct drm_pending_vblank_event *event;
+};
+
+#endif /* _AMDGPU_VKMS_H_ */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 078c068937fe..6b15cad78de9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -88,6 +88,46 @@ struct amdgpu_prt_cb {
struct dma_fence_cb cb;
};
+/**
+ * amdgpu_vm_set_pasid - manage pasid and vm ptr mapping
+ *
+ * @adev: amdgpu_device pointer
+ * @vm: amdgpu_vm pointer
+ * @pasid: the pasid the VM is using on this GPU
+ *
+ * Set the pasid this VM is using on this GPU, can also be used to remove the
+ * pasid by passing in zero.
+ *
+ */
+int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ u32 pasid)
+{
+ int r;
+
+ if (vm->pasid == pasid)
+ return 0;
+
+ if (vm->pasid) {
+ r = xa_err(xa_erase_irq(&adev->vm_manager.pasids, vm->pasid));
+ if (r < 0)
+ return r;
+
+ vm->pasid = 0;
+ }
+
+ if (pasid) {
+ r = xa_err(xa_store_irq(&adev->vm_manager.pasids, pasid, vm,
+ GFP_KERNEL));
+ if (r < 0)
+ return r;
+
+ vm->pasid = pasid;
+ }
+
+
+ return 0;
+}
+
/*
* vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS
* happens while holding this lock anywhere to prevent deadlocks when
@@ -886,7 +926,7 @@ static int amdgpu_vm_pt_create(struct amdgpu_device *adev,
bp.size = amdgpu_vm_bo_size(adev, level);
bp.byte_align = AMDGPU_GPU_PAGE_SIZE;
bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
- bp.domain = amdgpu_bo_get_preferred_pin_domain(adev, bp.domain);
+ bp.domain = amdgpu_bo_get_preferred_domain(adev, bp.domain);
bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
@@ -1178,7 +1218,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
amdgpu_gmc_emit_pasid_mapping(ring, job->vmid, job->pasid);
if (vm_flush_needed || pasid_mapping_needed) {
- r = amdgpu_fence_emit(ring, &fence, 0);
+ r = amdgpu_fence_emit(ring, &fence, NULL, 0);
if (r)
return r;
}
@@ -1758,7 +1798,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
r = vm->update_funcs->commit(&params, fence);
if (table_freed)
- *table_freed = params.table_freed;
+ *table_freed = *table_freed || params.table_freed;
error_unlock:
amdgpu_vm_eviction_unlock(vm);
@@ -1816,6 +1856,7 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem,
* @adev: amdgpu_device pointer
* @bo_va: requested BO and VM object
* @clear: if true clear the entries
+ * @table_freed: return true if page table is freed
*
* Fill in the page table entries for @bo_va.
*
@@ -1823,7 +1864,7 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem,
* 0 for success, -EINVAL for failure.
*/
int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
- bool clear)
+ bool clear, bool *table_freed)
{
struct amdgpu_bo *bo = bo_va->base.bo;
struct amdgpu_vm *vm = bo_va->base.vm;
@@ -1902,7 +1943,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
resv, mapping->start,
mapping->last, update_flags,
mapping->offset, mem,
- pages_addr, last_update, NULL);
+ pages_addr, last_update, table_freed);
if (r)
return r;
}
@@ -2154,7 +2195,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) {
/* Per VM BOs never need to bo cleared in the page tables */
- r = amdgpu_vm_bo_update(adev, bo_va, false);
+ r = amdgpu_vm_bo_update(adev, bo_va, false, NULL);
if (r)
return r;
}
@@ -2173,7 +2214,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
else
clear = true;
- r = amdgpu_vm_bo_update(adev, bo_va, clear);
+ r = amdgpu_vm_bo_update(adev, bo_va, clear, NULL);
if (r)
return r;
@@ -2863,14 +2904,13 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
*
* @adev: amdgpu_device pointer
* @vm: requested vm
- * @pasid: Process address space identifier
*
* Init @vm fields.
*
* Returns:
* 0 for success, error for failure.
*/
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid)
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
{
struct amdgpu_bo *root_bo;
struct amdgpu_bo_vm *root;
@@ -2944,19 +2984,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid)
amdgpu_bo_unreserve(vm->root.bo);
- if (pasid) {
- unsigned long flags;
-
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
- r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1,
- GFP_ATOMIC);
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
- if (r < 0)
- goto error_free_root;
-
- vm->pasid = pasid;
- }
-
INIT_KFIFO(vm->faults);
return 0;
@@ -3012,7 +3039,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
*
* @adev: amdgpu_device pointer
* @vm: requested vm
- * @pasid: pasid to use
*
* This only works on GFX VMs that don't have any BOs added and no
* page tables allocated yet.
@@ -3020,7 +3046,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
* Changes the following VM parameters:
* - use_cpu_for_update
* - pte_supports_ats
- * - pasid (old PASID is released, because compute manages its own PASIDs)
*
* Reinitializes the page directory to reflect the changed ATS
* setting.
@@ -3028,8 +3053,7 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
* Returns:
* 0 for success, -errno for errors.
*/
-int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
- u32 pasid)
+int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
{
bool pte_support_ats = (adev->asic_type == CHIP_RAVEN);
int r;
@@ -3043,19 +3067,6 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
if (r)
goto unreserve_bo;
- if (pasid) {
- unsigned long flags;
-
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
- r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1,
- GFP_ATOMIC);
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
-
- if (r == -ENOSPC)
- goto unreserve_bo;
- r = 0;
- }
-
/* Check if PD needs to be reinitialized and do it before
* changing any other state, in case it fails.
*/
@@ -3065,7 +3076,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
to_amdgpu_bo_vm(vm->root.bo),
false);
if (r)
- goto free_idr;
+ goto unreserve_bo;
}
/* Update VM state */
@@ -3082,7 +3093,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
r = amdgpu_bo_sync_wait(vm->root.bo,
AMDGPU_FENCE_OWNER_UNDEFINED, true);
if (r)
- goto free_idr;
+ goto unreserve_bo;
vm->update_funcs = &amdgpu_vm_cpu_funcs;
} else {
@@ -3092,36 +3103,11 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
vm->last_update = NULL;
vm->is_compute_context = true;
- if (vm->pasid) {
- unsigned long flags;
-
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
- idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
-
- /* Free the original amdgpu allocated pasid
- * Will be replaced with kfd allocated pasid
- */
- amdgpu_pasid_free(vm->pasid);
- vm->pasid = 0;
- }
-
/* Free the shadow bo for compute VM */
amdgpu_bo_unref(&to_amdgpu_bo_vm(vm->root.bo)->shadow);
- if (pasid)
- vm->pasid = pasid;
-
goto unreserve_bo;
-free_idr:
- if (pasid) {
- unsigned long flags;
-
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
- idr_remove(&adev->vm_manager.pasid_idr, pasid);
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
- }
unreserve_bo:
amdgpu_bo_unreserve(vm->root.bo);
return r;
@@ -3137,14 +3123,7 @@ unreserve_bo:
*/
void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
{
- if (vm->pasid) {
- unsigned long flags;
-
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
- idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
- }
- vm->pasid = 0;
+ amdgpu_vm_set_pasid(adev, vm, 0);
vm->is_compute_context = false;
}
@@ -3168,15 +3147,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
root = amdgpu_bo_ref(vm->root.bo);
amdgpu_bo_reserve(root, true);
- if (vm->pasid) {
- unsigned long flags;
-
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
- idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
- vm->pasid = 0;
- }
-
+ amdgpu_vm_set_pasid(adev, vm, 0);
dma_fence_wait(vm->last_unlocked, false);
dma_fence_put(vm->last_unlocked);
@@ -3258,8 +3229,7 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
adev->vm_manager.vm_update_mode = 0;
#endif
- idr_init(&adev->vm_manager.pasid_idr);
- spin_lock_init(&adev->vm_manager.pasid_lock);
+ xa_init_flags(&adev->vm_manager.pasids, XA_FLAGS_LOCK_IRQ);
}
/**
@@ -3271,8 +3241,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
*/
void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
{
- WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr));
- idr_destroy(&adev->vm_manager.pasid_idr);
+ WARN_ON(!xa_empty(&adev->vm_manager.pasids));
+ xa_destroy(&adev->vm_manager.pasids);
amdgpu_vmid_mgr_fini(adev);
}
@@ -3341,13 +3311,13 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid,
struct amdgpu_vm *vm;
unsigned long flags;
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
+ xa_lock_irqsave(&adev->vm_manager.pasids, flags);
- vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+ vm = xa_load(&adev->vm_manager.pasids, pasid);
if (vm)
*task_info = vm->task_info;
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
+ xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
}
/**
@@ -3375,12 +3345,13 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
* @adev: amdgpu device pointer
* @pasid: PASID of the VM
* @addr: Address of the fault
+ * @write_fault: true is write fault, false is read fault
*
* Try to gracefully handle a VM fault. Return true if the fault was handled and
* shouldn't be reported any more.
*/
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
- uint64_t addr)
+ uint64_t addr, bool write_fault)
{
bool is_compute_context = false;
struct amdgpu_bo *root;
@@ -3389,15 +3360,15 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
struct amdgpu_vm *vm;
int r;
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags);
- vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+ xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
+ vm = xa_load(&adev->vm_manager.pasids, pasid);
if (vm) {
root = amdgpu_bo_ref(vm->root.bo);
is_compute_context = vm->is_compute_context;
} else {
root = NULL;
}
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags);
+ xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
if (!root)
return false;
@@ -3405,7 +3376,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
addr /= AMDGPU_GPU_PAGE_SIZE;
if (is_compute_context &&
- !svm_range_restore_pages(adev, pasid, addr)) {
+ !svm_range_restore_pages(adev, pasid, addr, write_fault)) {
amdgpu_bo_unref(&root);
return true;
}
@@ -3415,11 +3386,11 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
goto error_unref;
/* Double check that the VM still exists */
- spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags);
- vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+ xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
+ vm = xa_load(&adev->vm_manager.pasids, pasid);
if (vm && vm->root.bo != root)
vm = NULL;
- spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags);
+ xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
if (!vm)
goto error_unlock;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index f8fa653d4da7..85fcfb8c5efd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -359,8 +359,7 @@ struct amdgpu_vm_manager {
/* PASID to VM mapping, will be used in interrupt context to
* look up VM of a page fault
*/
- struct idr pasid_idr;
- spinlock_t pasid_lock;
+ struct xarray pasids;
};
struct amdgpu_bo_va_mapping;
@@ -375,9 +374,12 @@ extern const struct amdgpu_vm_update_funcs amdgpu_vm_sdma_funcs;
void amdgpu_vm_manager_init(struct amdgpu_device *adev);
void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
+int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ u32 pasid);
+
long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid);
-int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
@@ -406,7 +408,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
struct dma_fence **fence, bool *free_table);
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
- bool clear);
+ bool clear, bool *table_freed);
bool amdgpu_vm_evictable(struct amdgpu_bo *bo);
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
struct amdgpu_bo *bo, bool evicted);
@@ -446,7 +448,7 @@ void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev);
void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid,
struct amdgpu_task_info *task_info);
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
- uint64_t addr);
+ uint64_t addr, bool write_fault);
void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index 8567d5d77346..978ac927ac11 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -32,6 +32,10 @@
#include "wafl/wafl2_4_0_0_smn.h"
#include "wafl/wafl2_4_0_0_sh_mask.h"
+#define smnPCS_XGMI23_PCS_ERROR_STATUS 0x11a01210
+#define smnPCS_XGMI3X16_PCS_ERROR_STATUS 0x11a0020c
+#define smnPCS_GOPX1_PCS_ERROR_STATUS 0x12200210
+
static DEFINE_MUTEX(xgmi_mutex);
#define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4
@@ -63,6 +67,33 @@ static const int wafl_pcs_err_status_reg_arct[] = {
smnPCS_GOPX1_0_PCS_GOPX1_PCS_ERROR_STATUS + 0x100000,
};
+static const int xgmi23_pcs_err_status_reg_aldebaran[] = {
+ smnPCS_XGMI23_PCS_ERROR_STATUS,
+ smnPCS_XGMI23_PCS_ERROR_STATUS + 0x100000,
+ smnPCS_XGMI23_PCS_ERROR_STATUS + 0x200000,
+ smnPCS_XGMI23_PCS_ERROR_STATUS + 0x300000,
+ smnPCS_XGMI23_PCS_ERROR_STATUS + 0x400000,
+ smnPCS_XGMI23_PCS_ERROR_STATUS + 0x500000,
+ smnPCS_XGMI23_PCS_ERROR_STATUS + 0x600000,
+ smnPCS_XGMI23_PCS_ERROR_STATUS + 0x700000
+};
+
+static const int xgmi3x16_pcs_err_status_reg_aldebaran[] = {
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS,
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x100000,
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x200000,
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x300000,
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x400000,
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x500000,
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x600000,
+ smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x700000
+};
+
+static const int walf_pcs_err_status_reg_aldebaran[] = {
+ smnPCS_GOPX1_PCS_ERROR_STATUS,
+ smnPCS_GOPX1_PCS_ERROR_STATUS + 0x100000
+};
+
static const struct amdgpu_pcs_ras_field xgmi_pcs_ras_fields[] = {
{"XGMI PCS DataLossErr",
SOC15_REG_FIELD(XGMI0_PCS_GOPX16_PCS_ERROR_STATUS, DataLossErr)},
@@ -486,6 +517,44 @@ int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
return -EINVAL;
}
+int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev,
+ struct amdgpu_device *peer_adev)
+{
+ struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
+ int i;
+
+ for (i = 0 ; i < top->num_nodes; ++i)
+ if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id)
+ return top->nodes[i].num_links;
+ return -EINVAL;
+}
+
+/*
+ * Devices that support extended data require the entire hive to initialize with
+ * the shared memory buffer flag set.
+ *
+ * Hive locks and conditions apply - see amdgpu_xgmi_add_device
+ */
+static int amdgpu_xgmi_initialize_hive_get_data_partition(struct amdgpu_hive_info *hive,
+ bool set_extended_data)
+{
+ struct amdgpu_device *tmp_adev;
+ int ret;
+
+ list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
+ ret = psp_xgmi_initialize(&tmp_adev->psp, set_extended_data, false);
+ if (ret) {
+ dev_err(tmp_adev->dev,
+ "XGMI: Failed to initialize xgmi session for data partition %i\n",
+ set_extended_data);
+ return ret;
+ }
+
+ }
+
+ return 0;
+}
+
int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
{
struct psp_xgmi_topology_info *top_info;
@@ -500,7 +569,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
if (!adev->gmc.xgmi.pending_reset &&
amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP)) {
- ret = psp_xgmi_initialize(&adev->psp);
+ ret = psp_xgmi_initialize(&adev->psp, false, true);
if (ret) {
dev_err(adev->dev,
"XGMI: Failed to initialize xgmi session\n");
@@ -563,7 +632,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
/* get latest topology info for each device from psp */
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count,
- &tmp_adev->psp.xgmi_context.top_info);
+ &tmp_adev->psp.xgmi_context.top_info, false);
if (ret) {
dev_err(tmp_adev->dev,
"XGMI: Get topology failure on device %llx, hive %llx, ret %d",
@@ -573,6 +642,34 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
goto exit_unlock;
}
}
+
+ /* get topology again for hives that support extended data */
+ if (adev->psp.xgmi_context.supports_extended_data) {
+
+ /* initialize the hive to get extended data. */
+ ret = amdgpu_xgmi_initialize_hive_get_data_partition(hive, true);
+ if (ret)
+ goto exit_unlock;
+
+ /* get the extended data. */
+ list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
+ ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count,
+ &tmp_adev->psp.xgmi_context.top_info, true);
+ if (ret) {
+ dev_err(tmp_adev->dev,
+ "XGMI: Get topology for extended data failure on device %llx, hive %llx, ret %d",
+ tmp_adev->gmc.xgmi.node_id,
+ tmp_adev->gmc.xgmi.hive_id, ret);
+ goto exit_unlock;
+ }
+ }
+
+ /* initialize the hive to get non-extended data for the next round. */
+ ret = amdgpu_xgmi_initialize_hive_get_data_partition(hive, false);
+ if (ret)
+ goto exit_unlock;
+
+ }
}
if (!ret && !adev->gmc.xgmi.pending_reset)
@@ -651,7 +748,6 @@ static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev)
adev->gmc.xgmi.ras_if->block = AMDGPU_RAS_BLOCK__XGMI_WAFL;
adev->gmc.xgmi.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->gmc.xgmi.ras_if->sub_block_index = 0;
- strcpy(adev->gmc.xgmi.ras_if->name, "xgmi_wafl");
}
ih_info.head = fs_info.head = *adev->gmc.xgmi.ras_if;
r = amdgpu_ras_late_init(adev, adev->gmc.xgmi.ras_if,
@@ -706,6 +802,17 @@ static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
pcs_clear_status(adev,
xgmi_pcs_err_status_reg_vg20[i]);
break;
+ case CHIP_ALDEBARAN:
+ for (i = 0; i < ARRAY_SIZE(xgmi23_pcs_err_status_reg_aldebaran); i++)
+ pcs_clear_status(adev,
+ xgmi23_pcs_err_status_reg_aldebaran[i]);
+ for (i = 0; i < ARRAY_SIZE(xgmi23_pcs_err_status_reg_aldebaran); i++)
+ pcs_clear_status(adev,
+ xgmi23_pcs_err_status_reg_aldebaran[i]);
+ for (i = 0; i < ARRAY_SIZE(walf_pcs_err_status_reg_aldebaran); i++)
+ pcs_clear_status(adev,
+ walf_pcs_err_status_reg_aldebaran[i]);
+ break;
default:
break;
}
@@ -783,7 +890,6 @@ static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
}
break;
case CHIP_VEGA20:
- default:
/* check xgmi pcs error */
for (i = 0; i < ARRAY_SIZE(xgmi_pcs_err_status_reg_vg20); i++) {
data = RREG32_PCIE(xgmi_pcs_err_status_reg_vg20[i]);
@@ -799,6 +905,32 @@ static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
data, &ue_cnt, &ce_cnt, false);
}
break;
+ case CHIP_ALDEBARAN:
+ /* check xgmi23 pcs error */
+ for (i = 0; i < ARRAY_SIZE(xgmi23_pcs_err_status_reg_aldebaran); i++) {
+ data = RREG32_PCIE(xgmi23_pcs_err_status_reg_aldebaran[i]);
+ if (data)
+ amdgpu_xgmi_query_pcs_error_status(adev,
+ data, &ue_cnt, &ce_cnt, true);
+ }
+ /* check xgmi3x16 pcs error */
+ for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_aldebaran); i++) {
+ data = RREG32_PCIE(xgmi3x16_pcs_err_status_reg_aldebaran[i]);
+ if (data)
+ amdgpu_xgmi_query_pcs_error_status(adev,
+ data, &ue_cnt, &ce_cnt, true);
+ }
+ /* check wafl pcs error */
+ for (i = 0; i < ARRAY_SIZE(walf_pcs_err_status_reg_aldebaran); i++) {
+ data = RREG32_PCIE(walf_pcs_err_status_reg_aldebaran[i]);
+ if (data)
+ amdgpu_xgmi_query_pcs_error_status(adev,
+ data, &ue_cnt, &ce_cnt, false);
+ }
+ break;
+ default:
+ dev_warn(adev->dev, "XGMI RAS error query not supported");
+ break;
}
adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
index 12969c0830d5..d2189bf7d428 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
@@ -59,6 +59,8 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate);
int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
struct amdgpu_device *peer_adev);
+int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev,
+ struct amdgpu_device *peer_adev);
uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev,
uint64_t addr);
static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
index 159a2a4385a1..afad094f84c2 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
@@ -851,7 +851,7 @@ void amdgpu_atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
pll->reference_div = amdgpu_crtc->pll_reference_div;
pll->post_div = amdgpu_crtc->pll_post_div;
- amdgpu_pll_compute(pll, amdgpu_crtc->adjusted_clock, &pll_clock,
+ amdgpu_pll_compute(adev, pll, amdgpu_crtc->adjusted_clock, &pll_clock,
&fb_div, &frac_fb_div, &ref_div, &post_div);
amdgpu_atombios_crtc_program_ss(adev, ATOM_DISABLE, amdgpu_crtc->pll_id,
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index c0fcc41ee574..54f28c075f21 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -70,7 +70,7 @@
#include "amdgpu_dm.h"
#include "amdgpu_amdkfd.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] =
{
@@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
diff --git a/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c b/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c
new file mode 100644
index 000000000000..58808814d8fb
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "nv.h"
+
+#include "soc15_common.h"
+#include "soc15_hw_ip.h"
+#include "cyan_skillfish_ip_offset.h"
+
+int cyan_skillfish_reg_base_init(struct amdgpu_device *adev)
+{
+ /* HW has more IP blocks, only initialized the blocke needed by driver */
+ uint32_t i;
+ for (i = 0 ; i < MAX_INSTANCE ; ++i) {
+ adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
+ adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
+ adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
+ adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
+ adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
+ adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
+ adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
+ adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(UVD0_BASE.instance[i]));
+ adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
+ adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DMU_BASE.instance[i]));
+ adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
+ adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
+ adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
+ adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
+ }
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
deleted file mode 100644
index 7e0d8c092c7e..000000000000
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- * Copyright 2014 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include <drm/drm_vblank.h>
-
-#include "amdgpu.h"
-#include "amdgpu_pm.h"
-#include "amdgpu_i2c.h"
-#include "atom.h"
-#include "amdgpu_pll.h"
-#include "amdgpu_connectors.h"
-#ifdef CONFIG_DRM_AMDGPU_SI
-#include "dce_v6_0.h"
-#endif
-#ifdef CONFIG_DRM_AMDGPU_CIK
-#include "dce_v8_0.h"
-#endif
-#include "dce_v10_0.h"
-#include "dce_v11_0.h"
-#include "dce_virtual.h"
-#include "ivsrcid/ivsrcid_vislands30.h"
-#include "amdgpu_display.h"
-
-#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
-
-
-static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
-static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
-static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
- int index);
-static int dce_virtual_pageflip(struct amdgpu_device *adev,
- unsigned crtc_id);
-static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer);
-static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
- int crtc,
- enum amdgpu_interrupt_state state);
-
-static u32 dce_virtual_vblank_get_counter(struct amdgpu_device *adev, int crtc)
-{
- return 0;
-}
-
-static void dce_virtual_page_flip(struct amdgpu_device *adev,
- int crtc_id, u64 crtc_base, bool async)
-{
- return;
-}
-
-static int dce_virtual_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
- u32 *vbl, u32 *position)
-{
- *vbl = 0;
- *position = 0;
-
- return -EINVAL;
-}
-
-static bool dce_virtual_hpd_sense(struct amdgpu_device *adev,
- enum amdgpu_hpd_id hpd)
-{
- return true;
-}
-
-static void dce_virtual_hpd_set_polarity(struct amdgpu_device *adev,
- enum amdgpu_hpd_id hpd)
-{
- return;
-}
-
-static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev)
-{
- return 0;
-}
-
-/**
- * dce_virtual_bandwidth_update - program display watermarks
- *
- * @adev: amdgpu_device pointer
- *
- * Calculate and program the display watermarks and line
- * buffer allocation (CIK).
- */
-static void dce_virtual_bandwidth_update(struct amdgpu_device *adev)
-{
- return;
-}
-
-static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
- u16 *green, u16 *blue, uint32_t size,
- struct drm_modeset_acquire_ctx *ctx)
-{
- return 0;
-}
-
-static void dce_virtual_crtc_destroy(struct drm_crtc *crtc)
-{
- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-
- drm_crtc_cleanup(crtc);
- kfree(amdgpu_crtc);
-}
-
-static const struct drm_crtc_funcs dce_virtual_crtc_funcs = {
- .cursor_set2 = NULL,
- .cursor_move = NULL,
- .gamma_set = dce_virtual_crtc_gamma_set,
- .set_config = amdgpu_display_crtc_set_config,
- .destroy = dce_virtual_crtc_destroy,
- .page_flip_target = amdgpu_display_crtc_page_flip_target,
- .get_vblank_counter = amdgpu_get_vblank_counter_kms,
- .enable_vblank = amdgpu_enable_vblank_kms,
- .disable_vblank = amdgpu_disable_vblank_kms,
- .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
-};
-
-static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
- unsigned type;
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- amdgpu_crtc->enabled = true;
- /* Make sure VBLANK interrupts are still enabled */
- type = amdgpu_display_crtc_idx_to_irq_type(adev,
- amdgpu_crtc->crtc_id);
- amdgpu_irq_update(adev, &adev->crtc_irq, type);
- drm_crtc_vblank_on(crtc);
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- drm_crtc_vblank_off(crtc);
- amdgpu_crtc->enabled = false;
- break;
- }
-}
-
-
-static void dce_virtual_crtc_prepare(struct drm_crtc *crtc)
-{
- dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void dce_virtual_crtc_commit(struct drm_crtc *crtc)
-{
- dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
-{
- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
- struct drm_device *dev = crtc->dev;
-
- if (dev->num_crtcs)
- drm_crtc_vblank_off(crtc);
-
- amdgpu_crtc->enabled = false;
- amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
- amdgpu_crtc->encoder = NULL;
- amdgpu_crtc->connector = NULL;
-}
-
-static int dce_virtual_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y, struct drm_framebuffer *old_fb)
-{
- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-
- /* update the hw version fpr dpm */
- amdgpu_crtc->hw_mode = *adjusted_mode;
-
- return 0;
-}
-
-static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-
-static int dce_virtual_crtc_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- return 0;
-}
-
-static int dce_virtual_crtc_set_base_atomic(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- int x, int y, enum mode_set_atomic state)
-{
- return 0;
-}
-
-static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = {
- .dpms = dce_virtual_crtc_dpms,
- .mode_fixup = dce_virtual_crtc_mode_fixup,
- .mode_set = dce_virtual_crtc_mode_set,
- .mode_set_base = dce_virtual_crtc_set_base,
- .mode_set_base_atomic = dce_virtual_crtc_set_base_atomic,
- .prepare = dce_virtual_crtc_prepare,
- .commit = dce_virtual_crtc_commit,
- .disable = dce_virtual_crtc_disable,
- .get_scanout_position = amdgpu_crtc_get_scanout_position,
-};
-
-static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
-{
- struct amdgpu_crtc *amdgpu_crtc;
-
- amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) +
- (AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
- if (amdgpu_crtc == NULL)
- return -ENOMEM;
-
- drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_virtual_crtc_funcs);
-
- drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256);
- amdgpu_crtc->crtc_id = index;
- adev->mode_info.crtcs[index] = amdgpu_crtc;
-
- amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
- amdgpu_crtc->encoder = NULL;
- amdgpu_crtc->connector = NULL;
- amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
- drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
-
- hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hrtimer_set_expires(&amdgpu_crtc->vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD);
- amdgpu_crtc->vblank_timer.function = dce_virtual_vblank_timer_handle;
- hrtimer_start(&amdgpu_crtc->vblank_timer,
- DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
- return 0;
-}
-
-static int dce_virtual_early_init(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- dce_virtual_set_display_funcs(adev);
- dce_virtual_set_irq_funcs(adev);
-
- adev->mode_info.num_hpd = 1;
- adev->mode_info.num_dig = 1;
- return 0;
-}
-
-static struct drm_encoder *
-dce_virtual_encoder(struct drm_connector *connector)
-{
- struct drm_encoder *encoder;
-
- drm_connector_for_each_possible_encoder(connector, encoder) {
- if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
- return encoder;
- }
-
- /* pick the first one */
- drm_connector_for_each_possible_encoder(connector, encoder)
- return encoder;
-
- return NULL;
-}
-
-static int dce_virtual_get_modes(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode = NULL;
- unsigned i;
- static const struct mode_size {
- int w;
- int h;
- } common_modes[] = {
- { 640, 480},
- { 720, 480},
- { 800, 600},
- { 848, 480},
- {1024, 768},
- {1152, 768},
- {1280, 720},
- {1280, 800},
- {1280, 854},
- {1280, 960},
- {1280, 1024},
- {1440, 900},
- {1400, 1050},
- {1680, 1050},
- {1600, 1200},
- {1920, 1080},
- {1920, 1200},
- {2560, 1440},
- {4096, 3112},
- {3656, 2664},
- {3840, 2160},
- {4096, 2160},
- };
-
- for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
- mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
- drm_mode_probed_add(connector, mode);
- }
-
- return 0;
-}
-
-static enum drm_mode_status dce_virtual_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- return MODE_OK;
-}
-
-static int
-dce_virtual_dpms(struct drm_connector *connector, int mode)
-{
- return 0;
-}
-
-static int
-dce_virtual_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t val)
-{
- return 0;
-}
-
-static void dce_virtual_destroy(struct drm_connector *connector)
-{
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
-
-static void dce_virtual_force(struct drm_connector *connector)
-{
- return;
-}
-
-static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
- .get_modes = dce_virtual_get_modes,
- .mode_valid = dce_virtual_mode_valid,
- .best_encoder = dce_virtual_encoder,
-};
-
-static const struct drm_connector_funcs dce_virtual_connector_funcs = {
- .dpms = dce_virtual_dpms,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = dce_virtual_set_property,
- .destroy = dce_virtual_destroy,
- .force = dce_virtual_force,
-};
-
-static int dce_virtual_sw_init(void *handle)
-{
- int r, i;
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq);
- if (r)
- return r;
-
- adev_to_drm(adev)->max_vblank_count = 0;
-
- adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
-
- adev_to_drm(adev)->mode_config.max_width = 16384;
- adev_to_drm(adev)->mode_config.max_height = 16384;
-
- adev_to_drm(adev)->mode_config.preferred_depth = 24;
- adev_to_drm(adev)->mode_config.prefer_shadow = 1;
-
- adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
-
- r = amdgpu_display_modeset_create_props(adev);
- if (r)
- return r;
-
- adev_to_drm(adev)->mode_config.max_width = 16384;
- adev_to_drm(adev)->mode_config.max_height = 16384;
-
- /* allocate crtcs, encoders, connectors */
- for (i = 0; i < adev->mode_info.num_crtc; i++) {
- r = dce_virtual_crtc_init(adev, i);
- if (r)
- return r;
- r = dce_virtual_connector_encoder_init(adev, i);
- if (r)
- return r;
- }
-
- drm_kms_helper_poll_init(adev_to_drm(adev));
-
- adev->mode_info.mode_config_initialized = true;
- return 0;
-}
-
-static int dce_virtual_sw_fini(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int i = 0;
-
- for (i = 0; i < adev->mode_info.num_crtc; i++)
- if (adev->mode_info.crtcs[i])
- hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
-
- kfree(adev->mode_info.bios_hardcoded_edid);
-
- drm_kms_helper_poll_fini(adev_to_drm(adev));
-
- drm_mode_config_cleanup(adev_to_drm(adev));
- /* clear crtcs pointer to avoid dce irq finish routine access freed data */
- memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS);
- adev->mode_info.mode_config_initialized = false;
- return 0;
-}
-
-static int dce_virtual_hw_init(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- switch (adev->asic_type) {
-#ifdef CONFIG_DRM_AMDGPU_SI
- case CHIP_TAHITI:
- case CHIP_PITCAIRN:
- case CHIP_VERDE:
- case CHIP_OLAND:
- dce_v6_0_disable_dce(adev);
- break;
-#endif
-#ifdef CONFIG_DRM_AMDGPU_CIK
- case CHIP_BONAIRE:
- case CHIP_HAWAII:
- case CHIP_KAVERI:
- case CHIP_KABINI:
- case CHIP_MULLINS:
- dce_v8_0_disable_dce(adev);
- break;
-#endif
- case CHIP_FIJI:
- case CHIP_TONGA:
- dce_v10_0_disable_dce(adev);
- break;
- case CHIP_CARRIZO:
- case CHIP_STONEY:
- case CHIP_POLARIS10:
- case CHIP_POLARIS11:
- case CHIP_VEGAM:
- dce_v11_0_disable_dce(adev);
- break;
- case CHIP_TOPAZ:
-#ifdef CONFIG_DRM_AMDGPU_SI
- case CHIP_HAINAN:
-#endif
- /* no DCE */
- break;
- default:
- break;
- }
- return 0;
-}
-
-static int dce_virtual_hw_fini(void *handle)
-{
- return 0;
-}
-
-static int dce_virtual_suspend(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int r;
-
- r = amdgpu_display_suspend_helper(adev);
- if (r)
- return r;
- return dce_virtual_hw_fini(handle);
-}
-
-static int dce_virtual_resume(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int r;
-
- r = dce_virtual_hw_init(handle);
- if (r)
- return r;
- return amdgpu_display_resume_helper(adev);
-}
-
-static bool dce_virtual_is_idle(void *handle)
-{
- return true;
-}
-
-static int dce_virtual_wait_for_idle(void *handle)
-{
- return 0;
-}
-
-static int dce_virtual_soft_reset(void *handle)
-{
- return 0;
-}
-
-static int dce_virtual_set_clockgating_state(void *handle,
- enum amd_clockgating_state state)
-{
- return 0;
-}
-
-static int dce_virtual_set_powergating_state(void *handle,
- enum amd_powergating_state state)
-{
- return 0;
-}
-
-static const struct amd_ip_funcs dce_virtual_ip_funcs = {
- .name = "dce_virtual",
- .early_init = dce_virtual_early_init,
- .late_init = NULL,
- .sw_init = dce_virtual_sw_init,
- .sw_fini = dce_virtual_sw_fini,
- .hw_init = dce_virtual_hw_init,
- .hw_fini = dce_virtual_hw_fini,
- .suspend = dce_virtual_suspend,
- .resume = dce_virtual_resume,
- .is_idle = dce_virtual_is_idle,
- .wait_for_idle = dce_virtual_wait_for_idle,
- .soft_reset = dce_virtual_soft_reset,
- .set_clockgating_state = dce_virtual_set_clockgating_state,
- .set_powergating_state = dce_virtual_set_powergating_state,
-};
-
-/* these are handled by the primary encoders */
-static void dce_virtual_encoder_prepare(struct drm_encoder *encoder)
-{
- return;
-}
-
-static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
-{
- return;
-}
-
-static void
-dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return;
-}
-
-static void dce_virtual_encoder_disable(struct drm_encoder *encoder)
-{
- return;
-}
-
-static void
-dce_virtual_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- return;
-}
-
-static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs = {
- .dpms = dce_virtual_encoder_dpms,
- .mode_fixup = dce_virtual_encoder_mode_fixup,
- .prepare = dce_virtual_encoder_prepare,
- .mode_set = dce_virtual_encoder_mode_set,
- .commit = dce_virtual_encoder_commit,
- .disable = dce_virtual_encoder_disable,
-};
-
-static void dce_virtual_encoder_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
- kfree(encoder);
-}
-
-static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
- .destroy = dce_virtual_encoder_destroy,
-};
-
-static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
- int index)
-{
- struct drm_encoder *encoder;
- struct drm_connector *connector;
-
- /* add a new encoder */
- encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
- if (!encoder)
- return -ENOMEM;
- encoder->possible_crtcs = 1 << index;
- drm_encoder_init(adev_to_drm(adev), encoder, &dce_virtual_encoder_funcs,
- DRM_MODE_ENCODER_VIRTUAL, NULL);
- drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
-
- connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
- if (!connector) {
- kfree(encoder);
- return -ENOMEM;
- }
-
- /* add a new connector */
- drm_connector_init(adev_to_drm(adev), connector, &dce_virtual_connector_funcs,
- DRM_MODE_CONNECTOR_VIRTUAL);
- drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
-
- /* link them */
- drm_connector_attach_encoder(connector, encoder);
-
- return 0;
-}
-
-static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
- .bandwidth_update = &dce_virtual_bandwidth_update,
- .vblank_get_counter = &dce_virtual_vblank_get_counter,
- .backlight_set_level = NULL,
- .backlight_get_level = NULL,
- .hpd_sense = &dce_virtual_hpd_sense,
- .hpd_set_polarity = &dce_virtual_hpd_set_polarity,
- .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
- .page_flip = &dce_virtual_page_flip,
- .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
- .add_encoder = NULL,
- .add_connector = NULL,
-};
-
-static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
-{
- adev->mode_info.funcs = &dce_virtual_display_funcs;
-}
-
-static int dce_virtual_pageflip(struct amdgpu_device *adev,
- unsigned crtc_id)
-{
- unsigned long flags;
- struct amdgpu_crtc *amdgpu_crtc;
- struct amdgpu_flip_work *works;
-
- amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
-
- if (crtc_id >= adev->mode_info.num_crtc) {
- DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
- return -EINVAL;
- }
-
- /* IRQ could occur when in initial stage */
- if (amdgpu_crtc == NULL)
- return 0;
-
- spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
- works = amdgpu_crtc->pflip_works;
- if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
- DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
- "AMDGPU_FLIP_SUBMITTED(%d)\n",
- amdgpu_crtc->pflip_status,
- AMDGPU_FLIP_SUBMITTED);
- spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
- return 0;
- }
-
- /* page flip completed. clean up */
- amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
- amdgpu_crtc->pflip_works = NULL;
-
- /* wakeup usersapce */
- if (works->event)
- drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);
-
- spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-
- drm_crtc_vblank_put(&amdgpu_crtc->base);
- amdgpu_bo_unref(&works->old_abo);
- kfree(works->shared);
- kfree(works);
-
- return 0;
-}
-
-static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
-{
- struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
- struct amdgpu_crtc, vblank_timer);
- struct drm_device *ddev = amdgpu_crtc->base.dev;
- struct amdgpu_device *adev = drm_to_adev(ddev);
- struct amdgpu_irq_src *source = adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources
- [VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER];
- int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev,
- amdgpu_crtc->crtc_id);
-
- if (amdgpu_irq_enabled(adev, source, irq_type)) {
- drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
- dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
- }
- hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
- HRTIMER_MODE_REL);
-
- return HRTIMER_NORESTART;
-}
-
-static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
- int crtc,
- enum amdgpu_interrupt_state state)
-{
- if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) {
- DRM_DEBUG("invalid crtc %d\n", crtc);
- return;
- }
-
- adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
- DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
-}
-
-
-static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
- struct amdgpu_irq_src *source,
- unsigned type,
- enum amdgpu_interrupt_state state)
-{
- if (type > AMDGPU_CRTC_IRQ_VBLANK6)
- return -EINVAL;
-
- dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);
-
- return 0;
-}
-
-static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
- .set = dce_virtual_set_crtc_irq_state,
- .process = NULL,
-};
-
-static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
-{
- adev->crtc_irq.num_types = adev->mode_info.num_crtc;
- adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
-}
-
-const struct amdgpu_ip_block_version dce_virtual_ip_block =
-{
- .type = AMD_IP_BLOCK_TYPE_DCE,
- .major = 1,
- .minor = 0,
- .rev = 0,
- .funcs = &dce_virtual_ip_funcs,
-};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index a64b2c706090..16dbe593cba2 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -56,6 +56,10 @@
#define GFX10_NUM_GFX_RINGS_Sienna_Cichlid 1
#define GFX10_MEC_HPD_SIZE 2048
+#define RLCG_VFGATE_DISABLED 0x4000000
+#define RLCG_WRONG_OPERATION_TYPE 0x2000000
+#define RLCG_NOT_IN_RANGE 0x1000000
+
#define F32_CE_PROGRAM_RAM_SIZE 65536
#define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
@@ -181,6 +185,9 @@
#define GFX_RLCG_GC_READ (0x1 << 28)
#define GFX_RLCG_MMHUB_WRITE (0x2 << 28)
+#define RLCG_ERROR_REPORT_ENABLED(adev) \
+ (amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev))
+
MODULE_FIRMWARE("amdgpu/navi10_ce.bin");
MODULE_FIRMWARE("amdgpu/navi10_pfp.bin");
MODULE_FIRMWARE("amdgpu/navi10_me.bin");
@@ -249,6 +256,39 @@ MODULE_FIRMWARE("amdgpu/yellow_carp_mec.bin");
MODULE_FIRMWARE("amdgpu/yellow_carp_mec2.bin");
MODULE_FIRMWARE("amdgpu/yellow_carp_rlc.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_ce.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_pfp.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_me.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_mec.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_mec2.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_rlc.bin");
+
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_ce.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_pfp.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_me.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec2.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_rlc.bin");
+
+static const struct soc15_reg_golden golden_settings_gc_10_0[] =
+{
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_INDEX, 0xffffffff, 0x00000000),
+ /* TA_GRAD_ADJ_UCONFIG -> TA_GRAD_ADJ */
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2544c382),
+ /* VGT_TF_RING_SIZE_UMD -> VGT_TF_RING_SIZE */
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2262c24e),
+ /* VGT_HS_OFFCHIP_PARAM_UMD -> VGT_HS_OFFCHIP_PARAM */
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226cc24f),
+ /* VGT_TF_MEMORY_BASE_UMD -> VGT_TF_MEMORY_BASE */
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226ec250),
+ /* VGT_TF_MEMORY_BASE_HI_UMD -> VGT_TF_MEMORY_BASE_HI */
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2278c261),
+ /* VGT_ESGS_RING_SIZE_UMD -> VGT_ESGS_RING_SIZE */
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2232c240),
+ /* VGT_GSVS_RING_SIZE_UMD -> VGT_GSVS_RING_SIZE */
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2233c241),
+};
+
static const struct soc15_reg_golden golden_settings_gc_10_1[] =
{
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014),
@@ -1486,6 +1526,7 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32
uint32_t i = 0;
uint32_t retries = 50000;
u32 ret = 0;
+ u32 tmp;
scratch_reg0 = adev->rmmio +
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0) * 4;
@@ -1519,9 +1560,8 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32
writel(v, scratch_reg0);
writel(offset | flag, scratch_reg1);
writel(1, spare_int);
- for (i = 0; i < retries; i++) {
- u32 tmp;
+ for (i = 0; i < retries; i++) {
tmp = readl(scratch_reg1);
if (!(tmp & flag))
break;
@@ -1529,8 +1569,19 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32
udelay(10);
}
- if (i >= retries)
- pr_err("timeout: rlcg program reg:0x%05x failed !\n", offset);
+ if (i >= retries) {
+ if (RLCG_ERROR_REPORT_ENABLED(adev)) {
+ if (tmp & RLCG_VFGATE_DISABLED)
+ pr_err("The vfgate is disabled, program reg:0x%05x failed!\n", offset);
+ else if (tmp & RLCG_WRONG_OPERATION_TYPE)
+ pr_err("Wrong operation type, program reg:0x%05x failed!\n", offset);
+ else if (tmp & RLCG_NOT_IN_RANGE)
+ pr_err("The register is not in range, program reg:0x%05x failed!\n", offset);
+ else
+ pr_err("Unknown error type, program reg:0x%05x failed!\n", offset);
+ } else
+ pr_err("timeout: rlcg program reg:0x%05x failed!\n", offset);
+ }
}
ret = readl(scratch_reg0);
@@ -1538,7 +1589,7 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32
return ret;
}
-static void gfx_v10_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip)
+static void gfx_v10_sriov_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip)
{
u32 rlcg_flag;
@@ -1554,7 +1605,7 @@ static void gfx_v10_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 value,
WREG32(offset, value);
}
-static u32 gfx_v10_rlcg_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip)
+static u32 gfx_v10_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip)
{
u32 rlcg_flag;
@@ -3488,12 +3539,51 @@ static const struct soc15_reg_golden golden_settings_gc_10_3_5[] = {
SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffbfffff, 0x00a00000)
};
+static const struct soc15_reg_golden golden_settings_gc_10_0_cyan_skillfish[] = {
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGE_FAST_CLKS, 0x3fffffff, 0x0000493e),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_CPF_CLK_CTRL, 0xfcff8fff, 0xf8000100),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xff7f0fff, 0x3c000100),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_3, 0xa0000000, 0xa0000000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0x00008000, 0x003c8014),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_DRAM_BURST_CTRL, 0x00000010, 0x00000017),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_PIPE_STEER, 0xffffffff, 0xd8d8d8d8),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_VC5_ENABLE, 0x00000003, 0x00000003),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_SD_CNTL, 0x800007ff, 0x000005ff),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG, 0xffffffff, 0x20000000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000200),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x04800000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_LAST_OF_BURST_CONFIG, 0xffffffff, 0x03860210),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0x0c1800ff, 0x00000044),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL, 0x00009d00, 0x00008500),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCMC_VM_CACHEABLE_DRAM_ADDRESS_END, 0xffffffff, 0x000fffff),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_DRAM_BURST_CTRL, 0x00000010, 0x00000017),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_PIPE_STEER, 0xfcfcfcfc, 0xd8d8d8d8),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_0, 0x77707770, 0x21302130),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_1, 0x77707770, 0x21302130),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0x10000000, 0x10000100),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xfc02002f, 0x9402002f),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0x00002188, 0x00000188),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x08000009, 0x08000009),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_EVENT_CNTL_0, 0xcc3fcc03, 0x842a4c02),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000000f, 0x00000000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffff3109, 0xffff3101),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000100, 0x00000130),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0x00030008, 0x01030000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0x00800000, 0x00800000)
+};
+
#define DEFAULT_SH_MEM_CONFIG \
((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \
(SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \
(SH_MEM_RETRY_MODE_ALL << SH_MEM_CONFIG__RETRY_MODE__SHIFT) | \
(3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT))
+/* TODO: pending on golden setting value of gb address config */
+#define CYAN_SKILLFISH_GB_ADDR_CONFIG_GOLDEN 0x00100044
static void gfx_v10_0_set_ring_funcs(struct amdgpu_device *adev);
static void gfx_v10_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -3718,6 +3808,14 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev)
golden_settings_gc_10_3_5,
(const u32)ARRAY_SIZE(golden_settings_gc_10_3_5));
break;
+ case CHIP_CYAN_SKILLFISH:
+ soc15_program_register_sequence(adev,
+ golden_settings_gc_10_0,
+ (const u32)ARRAY_SIZE(golden_settings_gc_10_0));
+ soc15_program_register_sequence(adev,
+ golden_settings_gc_10_0_cyan_skillfish,
+ (const u32)ARRAY_SIZE(golden_settings_gc_10_0_cyan_skillfish));
+ break;
default:
break;
}
@@ -3891,6 +3989,7 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev)
case CHIP_NAVI10:
case CHIP_NAVI12:
case CHIP_NAVI14:
+ case CHIP_CYAN_SKILLFISH:
if ((adev->gfx.me_fw_version >= 0x00000046) &&
(adev->gfx.me_feature_version >= 27) &&
(adev->gfx.pfp_fw_version >= 0x00000068) &&
@@ -4025,6 +4124,12 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
case CHIP_YELLOW_CARP:
chip_name = "yellow_carp";
break;
+ case CHIP_CYAN_SKILLFISH:
+ if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
+ chip_name = "cyan_skillfish2";
+ else
+ chip_name = "cyan_skillfish";
+ break;
default:
BUG();
}
@@ -4516,6 +4621,7 @@ static void gfx_v10_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd,
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_STS2);
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_DBG1);
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_M0);
+ dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_MODE);
}
static void gfx_v10_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
@@ -4604,6 +4710,14 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
adev->gfx.config.gb_addr_config_fields.num_pkrs =
1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS);
break;
+ case CHIP_CYAN_SKILLFISH:
+ adev->gfx.config.max_hw_contexts = 8;
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0;
+ gb_addr_config = CYAN_SKILLFISH_GB_ADDR_CONFIG_GOLDEN;
+ break;
default:
BUG();
break;
@@ -4708,6 +4822,7 @@ static int gfx_v10_0_sw_init(void *handle)
case CHIP_NAVI10:
case CHIP_NAVI14:
case CHIP_NAVI12:
+ case CHIP_CYAN_SKILLFISH:
adev->gfx.me.num_me = 1;
adev->gfx.me.num_pipe_per_me = 1;
adev->gfx.me.num_queue_per_pipe = 1;
@@ -5319,7 +5434,8 @@ static int gfx_v10_0_rlc_resume(struct amdgpu_device *adev)
{
int r;
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
+ adev->psp.autoload_supported) {
r = gfx_v10_0_wait_for_rlc_autoload_complete(adev);
if (r)
@@ -5379,7 +5495,7 @@ static int gfx_v10_0_parse_rlc_toc(struct amdgpu_device *adev)
int ret;
RLC_TABLE_OF_CONTENT *rlc_toc;
- ret = amdgpu_bo_create_reserved(adev, adev->psp.toc_bin_size, PAGE_SIZE,
+ ret = amdgpu_bo_create_reserved(adev, adev->psp.toc.size_bytes, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT,
&adev->gfx.rlc.rlc_toc_bo,
&adev->gfx.rlc.rlc_toc_gpu_addr,
@@ -5390,7 +5506,7 @@ static int gfx_v10_0_parse_rlc_toc(struct amdgpu_device *adev)
}
/* Copy toc from psp sos fw to rlc toc buffer */
- memcpy(adev->gfx.rlc.rlc_toc_buf, adev->psp.toc_start_addr, adev->psp.toc_bin_size);
+ memcpy(adev->gfx.rlc.rlc_toc_buf, adev->psp.toc.start_addr, adev->psp.toc.size_bytes);
rlc_toc = (RLC_TABLE_OF_CONTENT *)adev->gfx.rlc.rlc_toc_buf;
while (rlc_toc && (rlc_toc->id > FIRMWARE_ID_INVALID) &&
@@ -7608,10 +7724,8 @@ static int gfx_v10_0_soft_reset(void *handle)
static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
{
- uint64_t clock;
+ uint64_t clock, clock_lo, clock_hi, hi_check;
- amdgpu_gfx_off_ctrl(adev, false);
- mutex_lock(&adev->gfx.gpu_clock_mutex);
switch (adev->asic_type) {
case CHIP_VANGOGH:
case CHIP_YELLOW_CARP:
@@ -7619,12 +7733,21 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL);
break;
default:
- clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER) |
- ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER) << 32ULL);
+ preempt_disable();
+ clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER);
+ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER);
+ hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER);
+ /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over
+ * roughly every 42 seconds.
+ */
+ if (hi_check != clock_hi) {
+ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER);
+ clock_hi = hi_check;
+ }
+ preempt_enable();
+ clock = clock_lo | (clock_hi << 32ULL);
break;
}
- mutex_unlock(&adev->gfx.gpu_clock_mutex);
- amdgpu_gfx_off_ctrl(adev, true);
return clock;
}
@@ -7665,6 +7788,7 @@ static int gfx_v10_0_early_init(void *handle)
case CHIP_NAVI10:
case CHIP_NAVI14:
case CHIP_NAVI12:
+ case CHIP_CYAN_SKILLFISH:
adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X;
break;
case CHIP_SIENNA_CICHLID:
@@ -8261,8 +8385,8 @@ static const struct amdgpu_rlc_funcs gfx_v10_0_rlc_funcs_sriov = {
.reset = gfx_v10_0_rlc_reset,
.start = gfx_v10_0_rlc_start,
.update_spm_vmid = gfx_v10_0_update_spm_vmid,
- .rlcg_wreg = gfx_v10_rlcg_wreg,
- .rlcg_rreg = gfx_v10_rlcg_rreg,
+ .sriov_wreg = gfx_v10_sriov_wreg,
+ .sriov_rreg = gfx_v10_sriov_rreg,
.is_rlcg_access_range = gfx_v10_0_is_rlcg_access_range,
};
@@ -9425,6 +9549,7 @@ static void gfx_v10_0_set_rlc_funcs(struct amdgpu_device *adev)
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
adev->gfx.rlc.funcs = &gfx_v10_0_rlc_funcs;
break;
case CHIP_NAVI12:
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 3a8d52a54873..6a8dadea40f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -3027,6 +3027,7 @@ static void gfx_v6_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 685212c3ddae..37b4a3db6360 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -4198,6 +4198,7 @@ static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index c26e06059466..e0302c23e9a7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -5279,6 +5279,7 @@ static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 6a23c6826e12..603c259b073b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -787,7 +787,7 @@ static void gfx_v9_0_rlcg_w(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
}
-static void gfx_v9_0_rlcg_wreg(struct amdgpu_device *adev, u32 offset,
+static void gfx_v9_0_sriov_wreg(struct amdgpu_device *adev, u32 offset,
u32 v, u32 acc_flags, u32 hwip)
{
if ((acc_flags & AMDGPU_REGS_RLC) &&
@@ -2090,6 +2090,7 @@ static void gfx_v9_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
+ dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
static void gfx_v9_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
@@ -5150,7 +5151,7 @@ static const struct amdgpu_rlc_funcs gfx_v9_0_rlc_funcs = {
.reset = gfx_v9_0_rlc_reset,
.start = gfx_v9_0_rlc_start,
.update_spm_vmid = gfx_v9_0_update_spm_vmid,
- .rlcg_wreg = gfx_v9_0_rlcg_wreg,
+ .sriov_wreg = gfx_v9_0_sriov_wreg,
.is_rlcg_access_range = gfx_v9_0_is_rlcg_access_range,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
index 1769c4cba2ad..00a2b36a24b3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
@@ -85,7 +85,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_4_2_alde[] = {
SOC15_REG_GOLDEN_VALUE(GC, 0, regTCI_CNTL_3, 0xff, 0x20),
};
-/**
+/*
* This shader is used to clear VGPRS and LDS, and also write the input
* pattern into the write back buffer, which will be used by driver to
* check whether all SIMDs have been covered.
@@ -206,7 +206,7 @@ const struct soc15_reg_entry vgpr_init_regs_aldebaran[] = {
{ SOC15_REG_ENTRY(GC, 0, regCOMPUTE_STATIC_THREAD_MGMT_SE7), 0xffffffff },
};
-/**
+/*
* The below shaders are used to clear SGPRS, and also write the input
* pattern into the write back buffer. The first two dispatch should be
* scheduled simultaneously which make sure that all SGPRS could be
@@ -302,7 +302,7 @@ const struct soc15_reg_entry sgpr96_init_regs_aldebaran[] = {
{ SOC15_REG_ENTRY(GC, 0, regCOMPUTE_STATIC_THREAD_MGMT_SE7), 0xffffffff },
};
-/**
+/*
* This shader is used to clear the uninitiated sgprs after the above
* two dispatches, because of hardware feature, dispath 0 couldn't clear
* top hole sgprs. Therefore need 4 waves per SIMD to cover these sgprs
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c
index 8fca72ebd11c..497b86c376c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c
@@ -75,9 +75,8 @@ int gfxhub_v1_1_get_xgmi_info(struct amdgpu_device *adev)
max_physical_node_id = 7;
break;
case CHIP_ALDEBARAN:
- /* just using duplicates for Aldebaran support, revisit later */
- max_num_physical_nodes = 8;
- max_physical_node_id = 7;
+ max_num_physical_nodes = 16;
+ max_physical_node_id = 15;
break;
default:
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index 4523df2785d6..41c3a0d70b7c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -93,6 +93,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry)
{
bool retry_fault = !!(entry->src_data[1] & 0x80);
+ bool write_fault = !!(entry->src_data[1] & 0x20);
struct amdgpu_vmhub *hub = &adev->vmhub[entry->vmid_src];
struct amdgpu_task_info task_info;
uint32_t status = 0;
@@ -121,7 +122,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev,
/* Try to handle the recoverable page faults by filling page
* tables
*/
- if (amdgpu_vm_handle_fault(adev, entry->pasid, addr))
+ if (amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault))
return 1;
}
@@ -810,6 +811,7 @@ static int gmc_v10_0_mc_init(struct amdgpu_device *adev)
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
default:
adev->gmc.gart_size = 512ULL << 20;
break;
@@ -879,6 +881,7 @@ static int gmc_v10_0_sw_init(void *handle)
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
adev->num_vmhubs = 2;
/*
* To fulfill 4-level page support,
@@ -996,6 +999,7 @@ static void gmc_v10_0_init_golden_registers(struct amdgpu_device *adev)
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
break;
default:
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 7eb70d69f760..d90c16a6b2b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -53,7 +53,9 @@
#include "mmhub_v1_7.h"
#include "umc_v6_1.h"
#include "umc_v6_0.h"
+#include "umc_v6_7.h"
#include "hdp_v4_0.h"
+#include "mca_v3_0.h"
#include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
@@ -505,6 +507,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry)
{
bool retry_fault = !!(entry->src_data[1] & 0x80);
+ bool write_fault = !!(entry->src_data[1] & 0x20);
uint32_t status = 0, cid = 0, rw = 0;
struct amdgpu_task_info task_info;
struct amdgpu_vmhub *hub;
@@ -535,7 +538,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
/* Try to handle the recoverable page faults by filling page
* tables
*/
- if (amdgpu_vm_handle_fault(adev, entry->pasid, addr))
+ if (amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault))
return 1;
}
@@ -1168,6 +1171,18 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
adev->umc.ras_funcs = &umc_v6_1_ras_funcs;
break;
+ case CHIP_ALDEBARAN:
+ adev->umc.max_ras_err_cnt_per_query = UMC_V6_7_TOTAL_CHANNEL_NUM;
+ adev->umc.channel_inst_num = UMC_V6_7_CHANNEL_INSTANCE_NUM;
+ adev->umc.umc_inst_num = UMC_V6_7_UMC_INSTANCE_NUM;
+ adev->umc.channel_offs = UMC_V6_7_PER_CHANNEL_OFFSET;
+ if (!adev->gmc.xgmi.connected_to_cpu)
+ adev->umc.ras_funcs = &umc_v6_7_ras_funcs;
+ if (1 & adev->smuio.funcs->get_die_id(adev))
+ adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_first[0][0];
+ else
+ adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_second[0][0];
+ break;
default:
break;
}
@@ -1216,6 +1231,18 @@ static void gmc_v9_0_set_hdp_ras_funcs(struct amdgpu_device *adev)
adev->hdp.ras_funcs = &hdp_v4_0_ras_funcs;
}
+static void gmc_v9_0_set_mca_funcs(struct amdgpu_device *adev)
+{
+ switch (adev->asic_type) {
+ case CHIP_ALDEBARAN:
+ if (!adev->gmc.xgmi.connected_to_cpu)
+ adev->mca.funcs = &mca_v3_0_funcs;
+ break;
+ default:
+ break;
+ }
+}
+
static int gmc_v9_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1237,6 +1264,7 @@ static int gmc_v9_0_early_init(void *handle)
gmc_v9_0_set_mmhub_ras_funcs(adev);
gmc_v9_0_set_gfxhub_funcs(adev);
gmc_v9_0_set_hdp_ras_funcs(adev);
+ gmc_v9_0_set_mca_funcs(adev);
adev->gmc.shared_aperture_start = 0x2000000000000000ULL;
adev->gmc.shared_aperture_end =
@@ -1448,6 +1476,8 @@ static int gmc_v9_0_sw_init(void *handle)
adev->gfxhub.funcs->init(adev);
adev->mmhub.funcs->init(adev);
+ if (adev->mca.funcs)
+ adev->mca.funcs->init(adev);
spin_lock_init(&adev->gmc.invalidate_lock);
diff --git a/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c
new file mode 100644
index 000000000000..058b65730a84
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu_ras.h"
+#include "amdgpu.h"
+#include "amdgpu_mca.h"
+
+#define smnMCMP0_STATUST0 0x03830408
+#define smnMCMP1_STATUST0 0x03b30408
+#define smnMCMPIO_STATUST0 0x0c930408
+
+
+static void mca_v3_0_mp0_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_error_status)
+{
+ amdgpu_mca_query_ras_error_count(adev,
+ smnMCMP0_STATUST0,
+ ras_error_status);
+}
+
+static int mca_v3_0_mp0_ras_late_init(struct amdgpu_device *adev)
+{
+ return amdgpu_mca_ras_late_init(adev, &adev->mca.mp0);
+}
+
+static void mca_v3_0_mp0_ras_fini(struct amdgpu_device *adev)
+{
+ amdgpu_mca_ras_fini(adev, &adev->mca.mp0);
+}
+
+const struct amdgpu_mca_ras_funcs mca_v3_0_mp0_ras_funcs = {
+ .ras_late_init = mca_v3_0_mp0_ras_late_init,
+ .ras_fini = mca_v3_0_mp0_ras_fini,
+ .query_ras_error_count = mca_v3_0_mp0_query_ras_error_count,
+ .query_ras_error_address = NULL,
+ .ras_block = AMDGPU_RAS_BLOCK__MP0,
+ .sysfs_name = "mp0_err_count",
+};
+
+static void mca_v3_0_mp1_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_error_status)
+{
+ amdgpu_mca_query_ras_error_count(adev,
+ smnMCMP1_STATUST0,
+ ras_error_status);
+}
+
+static int mca_v3_0_mp1_ras_late_init(struct amdgpu_device *adev)
+{
+ return amdgpu_mca_ras_late_init(adev, &adev->mca.mp1);
+}
+
+static void mca_v3_0_mp1_ras_fini(struct amdgpu_device *adev)
+{
+ amdgpu_mca_ras_fini(adev, &adev->mca.mp1);
+}
+
+const struct amdgpu_mca_ras_funcs mca_v3_0_mp1_ras_funcs = {
+ .ras_late_init = mca_v3_0_mp1_ras_late_init,
+ .ras_fini = mca_v3_0_mp1_ras_fini,
+ .query_ras_error_count = mca_v3_0_mp1_query_ras_error_count,
+ .query_ras_error_address = NULL,
+ .ras_block = AMDGPU_RAS_BLOCK__MP1,
+ .sysfs_name = "mp1_err_count",
+};
+
+static void mca_v3_0_mpio_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_error_status)
+{
+ amdgpu_mca_query_ras_error_count(adev,
+ smnMCMPIO_STATUST0,
+ ras_error_status);
+}
+
+static int mca_v3_0_mpio_ras_late_init(struct amdgpu_device *adev)
+{
+ return amdgpu_mca_ras_late_init(adev, &adev->mca.mpio);
+}
+
+static void mca_v3_0_mpio_ras_fini(struct amdgpu_device *adev)
+{
+ amdgpu_mca_ras_fini(adev, &adev->mca.mpio);
+}
+
+const struct amdgpu_mca_ras_funcs mca_v3_0_mpio_ras_funcs = {
+ .ras_late_init = mca_v3_0_mpio_ras_late_init,
+ .ras_fini = mca_v3_0_mpio_ras_fini,
+ .query_ras_error_count = mca_v3_0_mpio_query_ras_error_count,
+ .query_ras_error_address = NULL,
+ .ras_block = AMDGPU_RAS_BLOCK__MPIO,
+ .sysfs_name = "mpio_err_count",
+};
+
+
+static void mca_v3_0_init(struct amdgpu_device *adev)
+{
+ struct amdgpu_mca *mca = &adev->mca;
+
+ mca->mp0.ras_funcs = &mca_v3_0_mp0_ras_funcs;
+ mca->mp1.ras_funcs = &mca_v3_0_mp1_ras_funcs;
+ mca->mpio.ras_funcs = &mca_v3_0_mpio_ras_funcs;
+}
+
+const struct amdgpu_mca_funcs mca_v3_0_funcs = {
+ .init = mca_v3_0_init,
+}; \ No newline at end of file
diff --git a/drivers/gpu/drm/amd/amdgpu/mca_v3_0.h b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.h
new file mode 100644
index 000000000000..b899b86194c2
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __MCA_V3_0_H__
+#define __MCA_V3_0_H__
+
+extern const struct amdgpu_mca_funcs mca_v3_0_funcs;
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h b/drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h
index 20958639b601..2cdab8062c86 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h
@@ -24,9 +24,7 @@
#ifndef __MMSCH_V1_0_H__
#define __MMSCH_V1_0_H__
-#define MMSCH_VERSION_MAJOR 1
-#define MMSCH_VERSION_MINOR 0
-#define MMSCH_VERSION (MMSCH_VERSION_MAJOR << 16 | MMSCH_VERSION_MINOR)
+#define MMSCH_VERSION 0x1
enum mmsch_v1_0_command_type {
MMSCH_COMMAND__DIRECT_REG_WRITE = 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
index 9f7aac435d69..a35e6d87e537 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
@@ -96,7 +96,11 @@ static int xgpu_nv_poll_ack(struct amdgpu_device *adev)
static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event)
{
- int r, timeout = NV_MAILBOX_POLL_MSG_TIMEDOUT;
+ int r;
+ uint64_t timeout, now;
+
+ now = (uint64_t)ktime_to_ms(ktime_get());
+ timeout = now + NV_MAILBOX_POLL_MSG_TIMEDOUT;
do {
r = xgpu_nv_mailbox_rcv_msg(adev, event);
@@ -104,8 +108,8 @@ static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event)
return 0;
msleep(10);
- timeout -= 10;
- } while (timeout > 1);
+ now = (uint64_t)ktime_to_ms(ktime_get());
+ } while (timeout > now);
return -ETIME;
@@ -149,9 +153,10 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev,
static int xgpu_nv_send_access_requests(struct amdgpu_device *adev,
enum idh_request req)
{
- int r;
+ int r, retry = 1;
enum idh_event event = -1;
+send_request:
xgpu_nv_mailbox_trans_msg(adev, req, 0, 0, 0);
switch (req) {
@@ -170,6 +175,9 @@ static int xgpu_nv_send_access_requests(struct amdgpu_device *adev,
if (event != -1) {
r = xgpu_nv_poll_msg(adev, event);
if (r) {
+ if (retry++ < 2)
+ goto send_request;
+
if (req != IDH_REQ_GPU_INIT_DATA) {
pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r);
return r;
@@ -279,6 +287,8 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work)
amdgpu_virt_fini_data_exchange(adev);
atomic_set(&adev->in_gpu_reset, 1);
+ xgpu_nv_mailbox_trans_msg(adev, IDH_READY_TO_RESET, 0, 0, 0);
+
do {
if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
goto flr_done;
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
index 9f5808616174..73887b0aa1d6 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
@@ -37,7 +37,8 @@ enum idh_request {
IDH_REQ_GPU_RESET_ACCESS,
IDH_REQ_GPU_INIT_DATA,
- IDH_LOG_VF_ERROR = 200,
+ IDH_LOG_VF_ERROR = 200,
+ IDH_READY_TO_RESET = 201,
};
enum idh_event {
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
index 7b79eeaa88aa..b184b656b9b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
@@ -508,6 +508,26 @@ static void nbio_v2_3_apply_l1_link_width_reconfig_wa(struct amdgpu_device *adev
WREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL, reg_data);
}
+static void nbio_v2_3_clear_doorbell_interrupt(struct amdgpu_device *adev)
+{
+ uint32_t reg, reg_data;
+
+ if (adev->asic_type != CHIP_SIENNA_CICHLID)
+ return;
+
+ reg = RREG32_SOC15(NBIO, 0, mmBIF_RB_CNTL);
+
+ /* Clear Interrupt Status
+ */
+ if ((reg & BIF_RB_CNTL__RB_ENABLE_MASK) == 0) {
+ reg = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
+ if (reg & BIF_DOORBELL_INT_CNTL__DOORBELL_INTERRUPT_STATUS_MASK) {
+ reg_data = 1 << BIF_DOORBELL_INT_CNTL__DOORBELL_INTERRUPT_CLEAR__SHIFT;
+ WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, reg_data);
+ }
+ }
+}
+
const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
.get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset,
.get_hdp_flush_done_offset = nbio_v2_3_get_hdp_flush_done_offset,
@@ -531,4 +551,5 @@ const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
.program_aspm = nbio_v2_3_program_aspm,
.apply_lc_spc_mode_wa = nbio_v2_3_apply_lc_spc_mode_wa,
.apply_l1_link_width_reconfig_wa = nbio_v2_3_apply_l1_link_width_reconfig_wa,
+ .clear_doorbell_interrupt = nbio_v2_3_clear_doorbell_interrupt,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
index cef929746739..ba1d3ab869c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
@@ -85,6 +85,11 @@
#define mmRCC_DEV0_EPF0_STRAP0_ALDE 0x0015
#define mmRCC_DEV0_EPF0_STRAP0_ALDE_BASE_IDX 2
+#define mmBIF_DOORBELL_INT_CNTL_ALDE 0x3878
+#define mmBIF_DOORBELL_INT_CNTL_ALDE_BASE_IDX 2
+#define BIF_DOORBELL_INT_CNTL_ALDE__DOORBELL_INTERRUPT_DISABLE__SHIFT 0x18
+#define BIF_DOORBELL_INT_CNTL_ALDE__DOORBELL_INTERRUPT_DISABLE_MASK 0x01000000L
+
static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev,
void *ras_error_status);
@@ -346,14 +351,21 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device
struct ras_err_data err_data = {0, 0, 0, NULL};
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
- bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
+ if (adev->asic_type == CHIP_ALDEBARAN)
+ bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE);
+ else
+ bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
+
if (REG_GET_FIELD(bif_doorbell_intr_cntl,
BIF_DOORBELL_INT_CNTL, RAS_CNTLR_INTERRUPT_STATUS)) {
/* driver has to clear the interrupt status when bif ring is disabled */
bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl,
BIF_DOORBELL_INT_CNTL,
RAS_CNTLR_INTERRUPT_CLEAR, 1);
- WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
+ if (adev->asic_type == CHIP_ALDEBARAN)
+ WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE, bif_doorbell_intr_cntl);
+ else
+ WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
if (!ras->disable_ras_err_cnt_harvest) {
/*
@@ -372,13 +384,13 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device
"errors detected in %s block, "
"no user action is needed.\n",
obj->err_data.ce_count,
- adev->nbio.ras_if->name);
+ ras_block_str(adev->nbio.ras_if->block));
if (err_data.ue_count)
dev_info(adev->dev, "%ld uncorrectable hardware "
"errors detected in %s block\n",
obj->err_data.ue_count,
- adev->nbio.ras_if->name);
+ ras_block_str(adev->nbio.ras_if->block));
}
dev_info(adev->dev, "RAS controller interrupt triggered "
@@ -395,14 +407,22 @@ static void nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring(struct amdgpu_d
{
uint32_t bif_doorbell_intr_cntl;
- bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
+ if (adev->asic_type == CHIP_ALDEBARAN)
+ bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE);
+ else
+ bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
+
if (REG_GET_FIELD(bif_doorbell_intr_cntl,
BIF_DOORBELL_INT_CNTL, RAS_ATHUB_ERR_EVENT_INTERRUPT_STATUS)) {
/* driver has to clear the interrupt status when bif ring is disabled */
bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl,
BIF_DOORBELL_INT_CNTL,
RAS_ATHUB_ERR_EVENT_INTERRUPT_CLEAR, 1);
- WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
+
+ if (adev->asic_type == CHIP_ALDEBARAN)
+ WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE, bif_doorbell_intr_cntl);
+ else
+ WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
amdgpu_ras_global_ras_isr(adev);
}
@@ -572,7 +592,11 @@ static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev,
static void nbio_v7_4_enable_doorbell_interrupt(struct amdgpu_device *adev,
bool enable)
{
- WREG32_FIELD15(NBIO, 0, BIF_DOORBELL_INT_CNTL,
+ if (adev->asic_type == CHIP_ALDEBARAN)
+ WREG32_FIELD15(NBIO, 0, BIF_DOORBELL_INT_CNTL_ALDE,
+ DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1);
+ else
+ WREG32_FIELD15(NBIO, 0, BIF_DOORBELL_INT_CNTL,
DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index 94d029dbf30d..ff80786e3918 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -58,7 +58,7 @@
#include "jpeg_v2_0.h"
#include "vcn_v3_0.h"
#include "jpeg_v3_0.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
#include "mes_v10_1.h"
#include "mxgpu_nv.h"
#include "smuio_v11_0.h"
@@ -666,6 +666,9 @@ legacy_init:
case CHIP_YELLOW_CARP:
yellow_carp_reg_base_init(adev);
break;
+ case CHIP_CYAN_SKILLFISH:
+ cyan_skillfish_reg_base_init(adev);
+ break;
default:
return -EINVAL;
}
@@ -682,7 +685,10 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
{
int r;
- if (adev->flags & AMD_IS_APU) {
+ if (adev->asic_type == CHIP_CYAN_SKILLFISH) {
+ adev->nbio.funcs = &nbio_v2_3_funcs;
+ adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
+ } else if (adev->flags & AMD_IS_APU) {
adev->nbio.funcs = &nbio_v7_2_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg;
} else {
@@ -715,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -743,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -773,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -796,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -817,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -837,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -859,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -877,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -889,6 +895,20 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
break;
+ case CHIP_CYAN_SKILLFISH:
+ amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
+ amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
+ if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) {
+ if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
+ amdgpu_device_ip_block_add(adev, &psp_v11_0_8_ip_block);
+ amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
+ }
+ if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
+ break;
default:
return -EINVAL;
}
@@ -1241,6 +1261,11 @@ static int nv_common_early_init(void *handle)
else
adev->external_rev_id = adev->rev_id + 0x01;
break;
+ case CHIP_CYAN_SKILLFISH:
+ adev->cg_flags = 0;
+ adev->pg_flags = 0;
+ adev->external_rev_id = adev->rev_id + 0x82;
+ break;
default:
/* FIXME: not supported yet */
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.h b/drivers/gpu/drm/amd/amdgpu/nv.h
index eb9aff1e7253..1f40ba3b0460 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.h
+++ b/drivers/gpu/drm/amd/amdgpu/nv.h
@@ -38,5 +38,6 @@ void vangogh_reg_base_init(struct amdgpu_device *adev);
int dimgrey_cavefish_reg_base_init(struct amdgpu_device *adev);
int beige_goby_reg_base_init(struct amdgpu_device *adev);
int yellow_carp_reg_base_init(struct amdgpu_device *adev);
+int cyan_skillfish_reg_base_init(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 4b1cc5e9ee92..5872d68ed13d 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -84,29 +84,29 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
ta_hdr = (const struct ta_firmware_header_v1_0 *)
adev->psp.ta_fw->data;
- adev->psp.ta_hdcp_ucode_version =
- le32_to_cpu(ta_hdr->ta_hdcp_ucode_version);
- adev->psp.ta_hdcp_ucode_size =
- le32_to_cpu(ta_hdr->ta_hdcp_size_bytes);
- adev->psp.ta_hdcp_start_addr =
+ adev->psp.hdcp.feature_version =
+ le32_to_cpu(ta_hdr->hdcp.fw_version);
+ adev->psp.hdcp.size_bytes =
+ le32_to_cpu(ta_hdr->hdcp.size_bytes);
+ adev->psp.hdcp.start_addr =
(uint8_t *)ta_hdr +
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
- adev->psp.ta_dtm_ucode_version =
- le32_to_cpu(ta_hdr->ta_dtm_ucode_version);
- adev->psp.ta_dtm_ucode_size =
- le32_to_cpu(ta_hdr->ta_dtm_size_bytes);
- adev->psp.ta_dtm_start_addr =
- (uint8_t *)adev->psp.ta_hdcp_start_addr +
- le32_to_cpu(ta_hdr->ta_dtm_offset_bytes);
-
- adev->psp.ta_securedisplay_ucode_version =
- le32_to_cpu(ta_hdr->ta_securedisplay_ucode_version);
- adev->psp.ta_securedisplay_ucode_size =
- le32_to_cpu(ta_hdr->ta_securedisplay_size_bytes);
- adev->psp.ta_securedisplay_start_addr =
- (uint8_t *)adev->psp.ta_hdcp_start_addr +
- le32_to_cpu(ta_hdr->ta_securedisplay_offset_bytes);
+ adev->psp.dtm.feature_version =
+ le32_to_cpu(ta_hdr->dtm.fw_version);
+ adev->psp.dtm.size_bytes =
+ le32_to_cpu(ta_hdr->dtm.size_bytes);
+ adev->psp.dtm.start_addr =
+ (uint8_t *)adev->psp.hdcp.start_addr +
+ le32_to_cpu(ta_hdr->dtm.offset_bytes);
+
+ adev->psp.securedisplay.feature_version =
+ le32_to_cpu(ta_hdr->securedisplay.fw_version);
+ adev->psp.securedisplay.size_bytes =
+ le32_to_cpu(ta_hdr->securedisplay.size_bytes);
+ adev->psp.securedisplay.start_addr =
+ (uint8_t *)adev->psp.hdcp.start_addr +
+ le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index bc133db2d538..29bf9f09944b 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -80,6 +80,9 @@ MODULE_FIRMWARE("amdgpu/beige_goby_ta.bin");
/* For large FW files the time to complete can be very long */
#define USBC_PD_POLLING_LIMIT_S 240
+/* Read USB-PD from LFB */
+#define GFX_CMD_USB_PD_USE_LFB 0x480
+
static int psp_v11_0_init_microcode(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
@@ -148,15 +151,15 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
goto out2;
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
- adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
- adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
- adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
+ adev->psp.xgmi.feature_version = le32_to_cpu(ta_hdr->xgmi.fw_version);
+ adev->psp.xgmi.size_bytes = le32_to_cpu(ta_hdr->xgmi.size_bytes);
+ adev->psp.xgmi.start_addr = (uint8_t *)ta_hdr +
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
- adev->psp.ta_ras_ucode_version = le32_to_cpu(ta_hdr->ta_ras_ucode_version);
- adev->psp.ta_ras_ucode_size = le32_to_cpu(ta_hdr->ta_ras_size_bytes);
- adev->psp.ta_ras_start_addr = (uint8_t *)adev->psp.ta_xgmi_start_addr +
- le32_to_cpu(ta_hdr->ta_ras_offset_bytes);
+ adev->psp.ras.feature_version = le32_to_cpu(ta_hdr->ras.fw_version);
+ adev->psp.ras.size_bytes = le32_to_cpu(ta_hdr->ras.size_bytes);
+ adev->psp.ras.start_addr = (uint8_t *)adev->psp.xgmi.start_addr +
+ le32_to_cpu(ta_hdr->ras.offset_bytes);
}
break;
case CHIP_NAVI10:
@@ -183,17 +186,17 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
goto out2;
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
- adev->psp.ta_hdcp_ucode_version = le32_to_cpu(ta_hdr->ta_hdcp_ucode_version);
- adev->psp.ta_hdcp_ucode_size = le32_to_cpu(ta_hdr->ta_hdcp_size_bytes);
- adev->psp.ta_hdcp_start_addr = (uint8_t *)ta_hdr +
+ adev->psp.hdcp.feature_version = le32_to_cpu(ta_hdr->hdcp.fw_version);
+ adev->psp.hdcp.size_bytes = le32_to_cpu(ta_hdr->hdcp.size_bytes);
+ adev->psp.hdcp.start_addr = (uint8_t *)ta_hdr +
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
- adev->psp.ta_dtm_ucode_version = le32_to_cpu(ta_hdr->ta_dtm_ucode_version);
- adev->psp.ta_dtm_ucode_size = le32_to_cpu(ta_hdr->ta_dtm_size_bytes);
- adev->psp.ta_dtm_start_addr = (uint8_t *)adev->psp.ta_hdcp_start_addr +
- le32_to_cpu(ta_hdr->ta_dtm_offset_bytes);
+ adev->psp.dtm.feature_version = le32_to_cpu(ta_hdr->dtm.fw_version);
+ adev->psp.dtm.size_bytes = le32_to_cpu(ta_hdr->dtm.size_bytes);
+ adev->psp.dtm.start_addr = (uint8_t *)adev->psp.hdcp.start_addr +
+ le32_to_cpu(ta_hdr->dtm.offset_bytes);
}
break;
case CHIP_SIENNA_CICHLID:
@@ -284,7 +287,7 @@ static int psp_v11_0_bootloader_load_kdb(struct psp_context *psp)
return ret;
/* Copy PSP KDB binary to memory */
- psp_copy_fw(psp, psp->kdb_start_addr, psp->kdb_bin_size);
+ psp_copy_fw(psp, psp->kdb.start_addr, psp->kdb.size_bytes);
/* Provide the PSP KDB to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -315,7 +318,7 @@ static int psp_v11_0_bootloader_load_spl(struct psp_context *psp)
return ret;
/* Copy PSP SPL binary to memory */
- psp_copy_fw(psp, psp->spl_start_addr, psp->spl_bin_size);
+ psp_copy_fw(psp, psp->spl.start_addr, psp->spl.size_bytes);
/* Provide the PSP SPL to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -346,7 +349,7 @@ static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp)
return ret;
/* Copy PSP System Driver binary to memory */
- psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
+ psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
/* Provide the sys driver to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -380,7 +383,7 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
return ret;
/* Copy Secure OS binary to PSP memory */
- psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
+ psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -753,44 +756,26 @@ static void psp_v11_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
}
-static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, dma_addr_t dma_addr)
+static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc_addr)
{
struct amdgpu_device *adev = psp->adev;
uint32_t reg_status;
int ret, i = 0;
- /* Write lower 32-bit address of the PD Controller FW */
- WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, lower_32_bits(dma_addr));
- ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
- 0x80000000, 0x80000000, false);
- if (ret)
- return ret;
-
- /* Fireup interrupt so PSP can pick up the lower address */
- WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x800000);
- ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
- 0x80000000, 0x80000000, false);
- if (ret)
- return ret;
-
- reg_status = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35);
-
- if ((reg_status & 0xFFFF) != 0) {
- DRM_ERROR("Lower address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = %02x...\n",
- reg_status & 0xFFFF);
- return -EIO;
- }
-
- /* Write upper 32-bit address of the PD Controller FW */
- WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, upper_32_bits(dma_addr));
+ /*
+ * LFB address which is aligned to 1MB address and has to be
+ * right-shifted by 20 so that LFB address can be passed on a 32-bit C2P
+ * register
+ */
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20));
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
if (ret)
return ret;
- /* Fireup interrupt so PSP can pick up the upper address */
- WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x4000000);
+ /* Fireup interrupt so PSP can pick up the address */
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, (GFX_CMD_USB_PD_USE_LFB << 16));
/* FW load takes very long time */
do {
@@ -806,7 +791,7 @@ static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, dma_addr_t dma_add
done:
if ((reg_status & 0xFFFF) != 0) {
- DRM_ERROR("Upper address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = x%04x\n",
+ DRM_ERROR("Address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = 0x%04x\n",
reg_status & 0xFFFF);
return -EIO;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c
new file mode 100644
index 000000000000..ff13e1beb49b
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "amdgpu_psp.h"
+#include "amdgpu_ucode.h"
+#include "soc15_common.h"
+#include "psp_v11_0_8.h"
+
+#include "mp/mp_11_0_8_offset.h"
+
+static int psp_v11_0_8_ring_init(struct psp_context *psp,
+ enum psp_ring_type ring_type)
+{
+ int ret = 0;
+ struct psp_ring *ring;
+ struct amdgpu_device *adev = psp->adev;
+
+ ring = &psp->km_ring;
+
+ ring->ring_type = ring_type;
+
+ /* allocate 4k Page of Local Frame Buffer memory for ring */
+ ring->ring_size = 0x1000;
+ ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &adev->firmware.rbuf,
+ &ring->ring_mem_mc_addr,
+ (void **)&ring->ring_mem);
+ if (ret) {
+ ring->ring_size = 0;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int psp_v11_0_8_ring_stop(struct psp_context *psp,
+ enum psp_ring_type ring_type)
+{
+ int ret = 0;
+ struct amdgpu_device *adev = psp->adev;
+
+ if (amdgpu_sriov_vf(adev)) {
+ /* Write the ring destroy command*/
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
+ GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING);
+ /* there might be handshake issue with hardware which needs delay */
+ mdelay(20);
+ /* Wait for response flag (bit 31) */
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
+ 0x80000000, 0x80000000, false);
+ } else {
+ /* Write the ring destroy command*/
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64,
+ GFX_CTRL_CMD_ID_DESTROY_RINGS);
+ /* there might be handshake issue with hardware which needs delay */
+ mdelay(20);
+ /* Wait for response flag (bit 31) */
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+ 0x80000000, 0x80000000, false);
+ }
+
+ return ret;
+}
+
+static int psp_v11_0_8_ring_create(struct psp_context *psp,
+ enum psp_ring_type ring_type)
+{
+ int ret = 0;
+ unsigned int psp_ring_reg = 0;
+ struct psp_ring *ring = &psp->km_ring;
+ struct amdgpu_device *adev = psp->adev;
+
+ if (amdgpu_sriov_vf(adev)) {
+ ret = psp_v11_0_8_ring_stop(psp, ring_type);
+ if (ret) {
+ DRM_ERROR("psp_v11_0_8_ring_stop_sriov failed!\n");
+ return ret;
+ }
+
+ /* Write low address of the ring to C2PMSG_102 */
+ psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg);
+ /* Write high address of the ring to C2PMSG_103 */
+ psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr);
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_103, psp_ring_reg);
+
+ /* Write the ring initialization command to C2PMSG_101 */
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
+ GFX_CTRL_CMD_ID_INIT_GPCOM_RING);
+
+ /* there might be handshake issue with hardware which needs delay */
+ mdelay(20);
+
+ /* Wait for response flag (bit 31) in C2PMSG_101 */
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
+ 0x80000000, 0x8000FFFF, false);
+
+ } else {
+ /* Wait for sOS ready for ring creation */
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+ 0x80000000, 0x80000000, false);
+ if (ret) {
+ DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
+ return ret;
+ }
+
+ /* Write low address of the ring to C2PMSG_69 */
+ psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg);
+ /* Write high address of the ring to C2PMSG_70 */
+ psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr);
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg);
+ /* Write size of ring to C2PMSG_71 */
+ psp_ring_reg = ring->ring_size;
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg);
+ /* Write the ring initialization command to C2PMSG_64 */
+ psp_ring_reg = ring_type;
+ psp_ring_reg = psp_ring_reg << 16;
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg);
+
+ /* there might be handshake issue with hardware which needs delay */
+ mdelay(20);
+
+ /* Wait for response flag (bit 31) in C2PMSG_64 */
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+ 0x80000000, 0x8000FFFF, false);
+ }
+
+ return ret;
+}
+
+static int psp_v11_0_8_ring_destroy(struct psp_context *psp,
+ enum psp_ring_type ring_type)
+{
+ int ret = 0;
+ struct psp_ring *ring = &psp->km_ring;
+ struct amdgpu_device *adev = psp->adev;
+
+ ret = psp_v11_0_8_ring_stop(psp, ring_type);
+ if (ret)
+ DRM_ERROR("Fail to stop psp ring\n");
+
+ amdgpu_bo_free_kernel(&adev->firmware.rbuf,
+ &ring->ring_mem_mc_addr,
+ (void **)&ring->ring_mem);
+
+ return ret;
+}
+
+static uint32_t psp_v11_0_8_ring_get_wptr(struct psp_context *psp)
+{
+ uint32_t data;
+ struct amdgpu_device *adev = psp->adev;
+
+ if (amdgpu_sriov_vf(adev))
+ data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
+ else
+ data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
+
+ return data;
+}
+
+static void psp_v11_0_8_ring_set_wptr(struct psp_context *psp, uint32_t value)
+{
+ struct amdgpu_device *adev = psp->adev;
+
+ if (amdgpu_sriov_vf(adev)) {
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, value);
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
+ GFX_CTRL_CMD_ID_CONSUME_CMD);
+ } else
+ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
+}
+
+static const struct psp_funcs psp_v11_0_8_funcs = {
+ .ring_init = psp_v11_0_8_ring_init,
+ .ring_create = psp_v11_0_8_ring_create,
+ .ring_stop = psp_v11_0_8_ring_stop,
+ .ring_destroy = psp_v11_0_8_ring_destroy,
+ .ring_get_wptr = psp_v11_0_8_ring_get_wptr,
+ .ring_set_wptr = psp_v11_0_8_ring_set_wptr,
+};
+
+void psp_v11_0_8_set_psp_funcs(struct psp_context *psp)
+{
+ psp->funcs = &psp_v11_0_8_funcs;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.h
index ed422012c8c6..890377a5afe0 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Advanced Micro Devices, Inc.
+ * Copyright 2021 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -20,11 +20,11 @@
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
+#ifndef __PSP_V11_0_8_H__
+#define __PSP_V11_0_8_H__
-#ifndef __DCE_VIRTUAL_H__
-#define __DCE_VIRTUAL_H__
+#include "amdgpu_psp.h"
-extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
+void psp_v11_0_8_set_psp_funcs(struct psp_context *psp);
#endif
-
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
index 536d41f327c1..cc649406234b 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
@@ -84,23 +84,23 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
ta_hdr = (const struct ta_firmware_header_v1_0 *)
adev->psp.ta_fw->data;
- adev->psp.ta_hdcp_ucode_version =
- le32_to_cpu(ta_hdr->ta_hdcp_ucode_version);
- adev->psp.ta_hdcp_ucode_size =
- le32_to_cpu(ta_hdr->ta_hdcp_size_bytes);
- adev->psp.ta_hdcp_start_addr =
+ adev->psp.hdcp.feature_version =
+ le32_to_cpu(ta_hdr->hdcp.fw_version);
+ adev->psp.hdcp.size_bytes =
+ le32_to_cpu(ta_hdr->hdcp.size_bytes);
+ adev->psp.hdcp.start_addr =
(uint8_t *)ta_hdr +
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
- adev->psp.ta_dtm_ucode_version =
- le32_to_cpu(ta_hdr->ta_dtm_ucode_version);
- adev->psp.ta_dtm_ucode_size =
- le32_to_cpu(ta_hdr->ta_dtm_size_bytes);
- adev->psp.ta_dtm_start_addr =
- (uint8_t *)adev->psp.ta_hdcp_start_addr +
- le32_to_cpu(ta_hdr->ta_dtm_offset_bytes);
+ adev->psp.dtm.feature_version =
+ le32_to_cpu(ta_hdr->dtm.fw_version);
+ adev->psp.dtm.size_bytes =
+ le32_to_cpu(ta_hdr->dtm.size_bytes);
+ adev->psp.dtm.start_addr =
+ (uint8_t *)adev->psp.hdcp.start_addr +
+ le32_to_cpu(ta_hdr->dtm.offset_bytes);
}
return 0;
@@ -138,7 +138,7 @@ static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)
return ret;
/* Copy PSP System Driver binary to memory */
- psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
+ psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
/* Provide the sys driver to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -177,7 +177,7 @@ static int psp_v12_0_bootloader_load_sos(struct psp_context *psp)
return ret;
/* Copy Secure OS binary to PSP memory */
- psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
+ psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
index c8949add88f3..47a500f64db2 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -35,6 +35,12 @@ MODULE_FIRMWARE("amdgpu/yellow_carp_asd.bin");
MODULE_FIRMWARE("amdgpu/yellow_carp_toc.bin");
MODULE_FIRMWARE("amdgpu/yellow_carp_ta.bin");
+/* For large FW files the time to complete can be very long */
+#define USBC_PD_POLLING_LIMIT_S 240
+
+/* Read USB-PD from LFB */
+#define GFX_CMD_USB_PD_USE_LFB 0x480
+
static int psp_v13_0_init_microcode(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
@@ -111,7 +117,9 @@ static int psp_v13_0_wait_for_bootloader(struct psp_context *psp)
return ret;
}
-static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp)
+static int psp_v13_0_bootloader_load_component(struct psp_context *psp,
+ struct psp_bin_desc *bin_desc,
+ enum psp_bootloader_cmd bl_cmd)
{
int ret;
uint32_t psp_gfxdrv_command_reg = 0;
@@ -130,12 +138,12 @@ static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp)
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
/* Copy PSP KDB binary to memory */
- memcpy(psp->fw_pri_buf, psp->kdb_start_addr, psp->kdb_bin_size);
+ memcpy(psp->fw_pri_buf, bin_desc->start_addr, bin_desc->size_bytes);
/* Provide the PSP KDB to bootloader */
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
(uint32_t)(psp->fw_pri_mc_addr >> 20));
- psp_gfxdrv_command_reg = PSP_BL__LOAD_KEY_DATABASE;
+ psp_gfxdrv_command_reg = bl_cmd;
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35,
psp_gfxdrv_command_reg);
@@ -144,40 +152,29 @@ static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp)
return ret;
}
-static int psp_v13_0_bootloader_load_sysdrv(struct psp_context *psp)
+static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp)
{
- int ret;
- uint32_t psp_gfxdrv_command_reg = 0;
- struct amdgpu_device *adev = psp->adev;
-
- /* Check sOS sign of life register to confirm sys driver and sOS
- * are already been loaded.
- */
- if (psp_v13_0_is_sos_alive(psp))
- return 0;
-
- ret = psp_v13_0_wait_for_bootloader(psp);
- if (ret)
- return ret;
-
- memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
- /* Copy PSP System Driver binary to memory */
- memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size);
+ return psp_v13_0_bootloader_load_component(psp, &psp->kdb, PSP_BL__LOAD_KEY_DATABASE);
+}
- /* Provide the sys driver to bootloader */
- WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
- (uint32_t)(psp->fw_pri_mc_addr >> 20));
- psp_gfxdrv_command_reg = PSP_BL__LOAD_SYSDRV;
- WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35,
- psp_gfxdrv_command_reg);
+static int psp_v13_0_bootloader_load_sysdrv(struct psp_context *psp)
+{
+ return psp_v13_0_bootloader_load_component(psp, &psp->sys, PSP_BL__LOAD_SYSDRV);
+}
- /* there might be handshake issue with hardware which needs delay */
- mdelay(20);
+static int psp_v13_0_bootloader_load_soc_drv(struct psp_context *psp)
+{
+ return psp_v13_0_bootloader_load_component(psp, &psp->soc_drv, PSP_BL__LOAD_SOCDRV);
+}
- ret = psp_v13_0_wait_for_bootloader(psp);
+static int psp_v13_0_bootloader_load_intf_drv(struct psp_context *psp)
+{
+ return psp_v13_0_bootloader_load_component(psp, &psp->intf_drv, PSP_BL__LOAD_INTFDRV);
+}
- return ret;
+static int psp_v13_0_bootloader_load_dbg_drv(struct psp_context *psp)
+{
+ return psp_v13_0_bootloader_load_component(psp, &psp->dbg_drv, PSP_BL__LOAD_DBGDRV);
}
static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
@@ -199,7 +196,7 @@ static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
/* Copy Secure OS binary to PSP memory */
- memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size);
+ memcpy(psp->fw_pri_buf, psp->sos.start_addr, psp->sos.size_bytes);
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36,
@@ -382,10 +379,71 @@ static void psp_v13_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_67, value);
}
+static int psp_v13_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc_addr)
+{
+ struct amdgpu_device *adev = psp->adev;
+ uint32_t reg_status;
+ int ret, i = 0;
+
+ /*
+ * LFB address which is aligned to 1MB address and has to be
+ * right-shifted by 20 so that LFB address can be passed on a 32-bit C2P
+ * register
+ */
+ WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20));
+
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
+ 0x80000000, 0x80000000, false);
+ if (ret)
+ return ret;
+
+ /* Fireup interrupt so PSP can pick up the address */
+ WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, (GFX_CMD_USB_PD_USE_LFB << 16));
+
+ /* FW load takes very long time */
+ do {
+ msleep(1000);
+ reg_status = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35);
+
+ if (reg_status & 0x80000000)
+ goto done;
+
+ } while (++i < USBC_PD_POLLING_LIMIT_S);
+
+ return -ETIME;
+done:
+
+ if ((reg_status & 0xFFFF) != 0) {
+ DRM_ERROR("Address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = %04x\n",
+ reg_status & 0xFFFF);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int psp_v13_0_read_usbc_pd_fw(struct psp_context *psp, uint32_t *fw_ver)
+{
+ struct amdgpu_device *adev = psp->adev;
+ int ret;
+
+ WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, C2PMSG_CMD_GFX_USB_PD_FW_VER);
+
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
+ 0x80000000, 0x80000000, false);
+ if (!ret)
+ *fw_ver = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36);
+
+ return ret;
+}
+
static const struct psp_funcs psp_v13_0_funcs = {
.init_microcode = psp_v13_0_init_microcode,
.bootloader_load_kdb = psp_v13_0_bootloader_load_kdb,
.bootloader_load_sysdrv = psp_v13_0_bootloader_load_sysdrv,
+ .bootloader_load_soc_drv = psp_v13_0_bootloader_load_soc_drv,
+ .bootloader_load_intf_drv = psp_v13_0_bootloader_load_intf_drv,
+ .bootloader_load_dbg_drv = psp_v13_0_bootloader_load_dbg_drv,
.bootloader_load_sos = psp_v13_0_bootloader_load_sos,
.ring_init = psp_v13_0_ring_init,
.ring_create = psp_v13_0_ring_create,
@@ -393,6 +451,8 @@ static const struct psp_funcs psp_v13_0_funcs = {
.ring_destroy = psp_v13_0_ring_destroy,
.ring_get_wptr = psp_v13_0_ring_get_wptr,
.ring_set_wptr = psp_v13_0_ring_set_wptr,
+ .load_usbc_pd_fw = psp_v13_0_load_usbc_pd_fw,
+ .read_usbc_pd_fw = psp_v13_0_read_usbc_pd_fw
};
void psp_v13_0_set_psp_funcs(struct psp_context *psp)
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
index b86dcbabb635..1ed357cb0f49 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
@@ -103,7 +103,7 @@ static int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
return ret;
/* Copy PSP System Driver binary to memory */
- psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
+ psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes);
/* Provide the sys driver to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -142,7 +142,7 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
return ret;
/* Copy Secure OS binary to PSP memory */
- psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
+ psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes);
/* Provide the PSP secure OS to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
index 6117ba8a4c3f..50bf3b71bc93 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -51,6 +51,12 @@ MODULE_FIRMWARE("amdgpu/navi14_sdma1.bin");
MODULE_FIRMWARE("amdgpu/navi12_sdma.bin");
MODULE_FIRMWARE("amdgpu/navi12_sdma1.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_sdma.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish_sdma1.bin");
+
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_sdma.bin");
+MODULE_FIRMWARE("amdgpu/cyan_skillfish2_sdma1.bin");
+
#define SDMA1_REG_OFFSET 0x600
#define SDMA0_HYP_DEC_REG_START 0x5880
#define SDMA0_HYP_DEC_REG_END 0x5893
@@ -130,6 +136,37 @@ static const struct soc15_reg_golden golden_settings_sdma_nv12[] = {
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
};
+static const struct soc15_reg_golden golden_settings_sdma_cyan_skillfish[] = {
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_CHICKEN_BITS, 0xffbf1f0f, 0x03ab0107),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG, 0x001877ff, 0x00000044),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_PAGE_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC2_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC4_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC5_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC6_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC7_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_UTCL1_PAGE, 0x007fffff, 0x004c5c00),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_CHICKEN_BITS, 0xffbf1f0f, 0x03ab0107),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG, 0x001877ff, 0x00000044),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_PAGE_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC2_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC4_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC5_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC6_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC7_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_UTCL1_PAGE, 0x007fffff, 0x004c5c00)
+};
+
static u32 sdma_v5_0_get_reg_offset(struct amdgpu_device *adev, u32 instance, u32 internal_offset)
{
u32 base;
@@ -180,6 +217,11 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev)
golden_settings_sdma_nv12,
(const u32)ARRAY_SIZE(golden_settings_sdma_nv12));
break;
+ case CHIP_CYAN_SKILLFISH:
+ soc15_program_register_sequence(adev,
+ golden_settings_sdma_cyan_skillfish,
+ (const u32)ARRAY_SIZE(golden_settings_sdma_cyan_skillfish));
+ break;
default:
break;
}
@@ -200,7 +242,7 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev)
static int sdma_v5_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
- char fw_name[30];
+ char fw_name[40];
int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
@@ -221,6 +263,12 @@ static int sdma_v5_0_init_microcode(struct amdgpu_device *adev)
case CHIP_NAVI12:
chip_name = "navi12";
break;
+ case CHIP_CYAN_SKILLFISH:
+ if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
+ chip_name = "cyan_skillfish2";
+ else
+ chip_name = "cyan_skillfish";
+ break;
default:
BUG();
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index 7486e5306786..779f5c911e11 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -87,21 +87,6 @@ static u32 sdma_v5_2_get_reg_offset(struct amdgpu_device *adev, u32 instance, u3
return base + internal_offset;
}
-static void sdma_v5_2_init_golden_registers(struct amdgpu_device *adev)
-{
- switch (adev->asic_type) {
- case CHIP_SIENNA_CICHLID:
- case CHIP_NAVY_FLOUNDER:
- case CHIP_VANGOGH:
- case CHIP_DIMGREY_CAVEFISH:
- case CHIP_BEIGE_GOBY:
- case CHIP_YELLOW_CARP:
- break;
- default:
- break;
- }
-}
-
static int sdma_v5_2_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst)
{
int err = 0;
@@ -1345,8 +1330,6 @@ static int sdma_v5_2_hw_init(void *handle)
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- sdma_v5_2_init_golden_registers(adev);
-
r = sdma_v5_2_start(adev);
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 7cbc2bb03bc6..e6d2f74a7976 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -44,7 +44,7 @@
#include "dce_v6_0.h"
#include "si.h"
#include "uvd_v3_1.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
#include "gca/gfx_6_0_d.h"
#include "oss/oss_1_0_d.h"
#include "oss/oss_1_0_sh_mask.h"
@@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
break;
default:
BUG();
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 5c7d769aee3f..73ffa8fde3df 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -41,9 +41,7 @@
#define I2C_SW_TIMEOUT 8
#define I2C_ABORT 0x10
-/* I2C transaction flags */
-#define I2C_NO_STOP 1
-#define I2C_RESTART 2
+#define I2C_X_RESTART BIT(31)
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
@@ -56,12 +54,48 @@ static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool en)
WREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT, reg);
}
+/* The T_I2C_POLL_US is defined as follows:
+ *
+ * "Define a timer interval (t_i2c_poll) equal to 10 times the
+ * signalling period for the highest I2C transfer speed used in the
+ * system and supported by DW_apb_i2c. For instance, if the highest
+ * I2C data transfer mode is 400 kb/s, then t_i2c_poll is 25 us." --
+ * DesignWare DW_apb_i2c Databook, Version 1.21a, section 3.8.3.1,
+ * page 56, with grammar and syntax corrections.
+ *
+ * Vcc for our device is at 1.8V which puts it at 400 kHz,
+ * see Atmel AT24CM02 datasheet, section 8.3 DC Characteristics table, page 14.
+ *
+ * The procedure to disable the IP block is described in section
+ * 3.8.3 Disabling DW_apb_i2c on page 56.
+ */
+#define I2C_SPEED_MODE_FAST 2
+#define T_I2C_POLL_US 25
+#define I2C_MAX_T_POLL_COUNT 1000
-static void smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable)
+static int smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0);
+
+ if (!enable) {
+ int ii;
+
+ for (ii = I2C_MAX_T_POLL_COUNT; ii > 0; ii--) {
+ u32 en_stat = RREG32_SOC15(SMUIO,
+ 0,
+ mmCKSVII2C_IC_ENABLE_STATUS);
+ if (REG_GET_FIELD(en_stat, CKSVII2C_IC_ENABLE_STATUS, IC_EN))
+ udelay(T_I2C_POLL_US);
+ else
+ return I2C_OK;
+ }
+
+ return I2C_ABORT;
+ }
+
+ return I2C_OK;
}
static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control)
@@ -83,8 +117,13 @@ static void smu_v11_0_i2c_configure(struct i2c_adapter *control)
reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_RESTART_EN, 1);
reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_MASTER, 0);
reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_SLAVE, 0);
- /* Standard mode */
- reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE, 2);
+ /* The values of IC_MAX_SPEED_MODE are,
+ * 1: standard mode, 0 - 100 Kb/s,
+ * 2: fast mode, <= 400 Kb/s, or fast mode plus, <= 1000 Kb/s,
+ * 3: high speed mode, <= 3.4 Mb/s.
+ */
+ reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE,
+ I2C_SPEED_MODE_FAST);
reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MASTER_MODE, 1);
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CON, reg);
@@ -113,13 +152,15 @@ static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control)
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SDA_HOLD, 20);
}
-static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, uint8_t address)
+static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, u16 address)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
- /* Convert fromr 8-bit to 7-bit address */
- address >>= 1;
- WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, (address & 0xFF));
+ /* The IC_TAR::IC_TAR field is 10-bits wide.
+ * It takes a 7-bit or 10-bit addresses as an address,
+ * i.e. no read/write bit--no wire format, just the address.
+ */
+ WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, address & 0x3FF);
}
static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control)
@@ -206,9 +247,6 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control)
return ret;
}
-
-
-
/**
* smu_v11_0_i2c_transmit - Send a block of data over the I2C bus to a slave device.
*
@@ -221,17 +259,17 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control)
* Returns 0 on success or error.
*/
static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control,
- uint8_t address, uint8_t *data,
- uint32_t numbytes, uint32_t i2c_flag)
+ u16 address, u8 *data,
+ u32 numbytes, u32 i2c_flag)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
- uint32_t bytes_sent, reg, ret = 0;
+ u32 bytes_sent, reg, ret = I2C_OK;
unsigned long timeout_counter;
bytes_sent = 0;
DRM_DEBUG_DRIVER("I2C_Transmit(), address = %x, bytes = %d , data: ",
- (uint16_t)address, numbytes);
+ address, numbytes);
if (drm_debug_enabled(DRM_UT_DRIVER)) {
print_hex_dump(KERN_INFO, "data: ", DUMP_PREFIX_NONE,
@@ -246,53 +284,49 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control,
/* Clear status bits */
smu_v11_0_i2c_clear_status(control);
-
timeout_counter = jiffies + msecs_to_jiffies(20);
while (numbytes > 0) {
reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
- if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
- do {
- reg = 0;
- /*
- * Prepare transaction, no need to set RESTART. I2C engine will send
- * START as soon as it sees data in TXFIFO
- */
- if (bytes_sent == 0)
- reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
- (i2c_flag & I2C_RESTART) ? 1 : 0);
- reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, data[bytes_sent]);
-
- /* determine if we need to send STOP bit or not */
- if (numbytes == 1)
- /* Final transaction, so send stop unless I2C_NO_STOP */
- reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,
- (i2c_flag & I2C_NO_STOP) ? 0 : 1);
- /* Write */
- reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0);
- WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
-
- /* Record that the bytes were transmitted */
- bytes_sent++;
- numbytes--;
-
- reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
-
- } while (numbytes && REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF));
- }
-
- /*
- * We waited too long for the transmission FIFO to become not-full.
- * Exit the loop with error.
- */
- if (time_after(jiffies, timeout_counter)) {
- ret |= I2C_SW_TIMEOUT;
- goto Err;
+ if (!REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
+ /*
+ * We waited for too long for the transmission
+ * FIFO to become not-full. Exit the loop
+ * with error.
+ */
+ if (time_after(jiffies, timeout_counter)) {
+ ret |= I2C_SW_TIMEOUT;
+ goto Err;
+ }
+ } else {
+ reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT,
+ data[bytes_sent]);
+
+ /* Final message, final byte, must generate a
+ * STOP to release the bus, i.e. don't hold
+ * SCL low.
+ */
+ if (numbytes == 1 && i2c_flag & I2C_M_STOP)
+ reg = REG_SET_FIELD(reg,
+ CKSVII2C_IC_DATA_CMD,
+ STOP, 1);
+
+ if (bytes_sent == 0 && i2c_flag & I2C_X_RESTART)
+ reg = REG_SET_FIELD(reg,
+ CKSVII2C_IC_DATA_CMD,
+ RESTART, 1);
+
+ /* Write */
+ reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0);
+ WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
+
+ /* Record that the bytes were transmitted */
+ bytes_sent++;
+ numbytes--;
}
}
ret = smu_v11_0_i2c_poll_tx_status(control);
-
Err:
/* Any error, no point in proceeding */
if (ret != I2C_OK) {
@@ -323,8 +357,8 @@ Err:
* Returns 0 on success or error.
*/
static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control,
- uint8_t address, uint8_t *data,
- uint32_t numbytes, uint8_t i2c_flag)
+ u16 address, u8 *data,
+ u32 numbytes, u32 i2c_flag)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
uint32_t bytes_received, ret = I2C_OK;
@@ -342,23 +376,21 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control,
smu_v11_0_i2c_clear_status(control);
-
/* Prepare transaction */
-
- /* Each time we disable I2C, so this is not a restart */
- if (bytes_received == 0)
- reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
- (i2c_flag & I2C_RESTART) ? 1 : 0);
-
reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0);
/* Read */
reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 1);
- /* Transmitting last byte */
- if (numbytes == 1)
- /* Final transaction, so send stop if requested */
- reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,
- (i2c_flag & I2C_NO_STOP) ? 0 : 1);
+ /* Final message, final byte, must generate a STOP
+ * to release the bus, i.e. don't hold SCL low.
+ */
+ if (numbytes == 1 && i2c_flag & I2C_M_STOP)
+ reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD,
+ STOP, 1);
+
+ if (bytes_received == 0 && i2c_flag & I2C_X_RESTART)
+ reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD,
+ RESTART, 1);
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
@@ -413,7 +445,6 @@ static void smu_v11_0_i2c_abort(struct i2c_adapter *control)
DRM_DEBUG_DRIVER("I2C_Abort() Done.");
}
-
static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -425,7 +456,6 @@ static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control)
reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS);
reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
-
if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) &&
(REG_GET_FIELD(reg_ic_enable_status, CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) {
/*
@@ -455,6 +485,8 @@ static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control)
static void smu_v11_0_i2c_init(struct i2c_adapter *control)
{
+ int res;
+
/* Disable clock gating */
smu_v11_0_i2c_set_clock_gating(control, false);
@@ -462,7 +494,9 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control)
DRM_WARN("I2C busy !");
/* Disable I2C */
- smu_v11_0_i2c_enable(control, false);
+ res = smu_v11_0_i2c_enable(control, false);
+ if (res != I2C_OK)
+ smu_v11_0_i2c_abort(control);
/* Configure I2C to operate as master and in standard mode */
smu_v11_0_i2c_configure(control);
@@ -475,21 +509,22 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control)
static void smu_v11_0_i2c_fini(struct i2c_adapter *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
- uint32_t reg_ic_enable_status, reg_ic_enable;
+ u32 status, enable, en_stat;
+ int res;
- smu_v11_0_i2c_enable(control, false);
+ res = smu_v11_0_i2c_enable(control, false);
+ if (res != I2C_OK) {
+ status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
+ enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
+ en_stat = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS);
- /* Double check if disabled, else force abort */
- reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS);
- reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
-
- if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) &&
- (REG_GET_FIELD(reg_ic_enable_status,
- CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) {
- /*
- * Nobody is using I2C engine, but engine remains active because
- * someone missed to send STOP
+ /* Nobody is using the I2C engine, yet it remains
+ * active, possibly because someone missed to send
+ * STOP.
*/
+ DRM_DEBUG_DRIVER("Aborting from fini: status:0x%08x "
+ "enable:0x%08x enable_stat:0x%08x",
+ status, enable, en_stat);
smu_v11_0_i2c_abort(control);
}
@@ -531,22 +566,12 @@ static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control)
/***************************** I2C GLUE ****************************/
static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
+ struct i2c_msg *msg, uint32_t i2c_flag)
{
- uint32_t ret = 0;
-
- /* First 2 bytes are dummy write to set EEPROM address */
- ret = smu_v11_0_i2c_transmit(control, address, data, 2, I2C_NO_STOP);
- if (ret != I2C_OK)
- goto Fail;
+ uint32_t ret;
- /* Now read data starting with that address */
- ret = smu_v11_0_i2c_receive(control, address, data + 2, numbytes - 2,
- I2C_RESTART);
+ ret = smu_v11_0_i2c_receive(control, msg->addr, msg->buf, msg->len, i2c_flag);
-Fail:
if (ret != I2C_OK)
DRM_ERROR("ReadData() - I2C error occurred :%x", ret);
@@ -554,28 +579,15 @@ Fail:
}
static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
+ struct i2c_msg *msg, uint32_t i2c_flag)
{
uint32_t ret;
- ret = smu_v11_0_i2c_transmit(control, address, data, numbytes, 0);
+ ret = smu_v11_0_i2c_transmit(control, msg->addr, msg->buf, msg->len, i2c_flag);
if (ret != I2C_OK)
DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret);
- else
- /*
- * According to EEPROM spec there is a MAX of 10 ms required for
- * EEPROM to flush internal RX buffer after STOP was issued at the
- * end of write transaction. During this time the EEPROM will not be
- * responsive to any more commands - so wait a bit more.
- *
- * TODO Improve to wait for first ACK for slave address after
- * internal write cycle done.
- */
- msleep(10);
-
+
return ret;
}
@@ -584,12 +596,11 @@ static void lock_bus(struct i2c_adapter *i2c, unsigned int flags)
{
struct amdgpu_device *adev = to_amdgpu_device(i2c);
- if (!smu_v11_0_i2c_bus_lock(i2c)) {
+ mutex_lock(&adev->pm.smu_i2c_mutex);
+ if (!smu_v11_0_i2c_bus_lock(i2c))
DRM_ERROR("Failed to lock the bus from SMU");
- return;
- }
-
- adev->pm.bus_locked = true;
+ else
+ adev->pm.bus_locked = true;
}
static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags)
@@ -602,12 +613,11 @@ static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags)
{
struct amdgpu_device *adev = to_amdgpu_device(i2c);
- if (!smu_v11_0_i2c_bus_unlock(i2c)) {
+ if (!smu_v11_0_i2c_bus_unlock(i2c))
DRM_ERROR("Failed to unlock the bus from SMU");
- return;
- }
-
- adev->pm.bus_locked = false;
+ else
+ adev->pm.bus_locked = false;
+ mutex_unlock(&adev->pm.smu_i2c_mutex);
}
static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
@@ -617,27 +627,60 @@ static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
};
static int smu_v11_0_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs, int num)
+ struct i2c_msg *msg, int num)
{
int i, ret;
- struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
-
- if (!adev->pm.bus_locked) {
- DRM_ERROR("I2C bus unlocked, stopping transaction!");
- return -EIO;
- }
+ u16 addr, dir;
smu_v11_0_i2c_init(i2c_adap);
+ /* From the client's point of view, this sequence of
+ * messages-- the array i2c_msg *msg, is a single transaction
+ * on the bus, starting with START and ending with STOP.
+ *
+ * The client is welcome to send any sequence of messages in
+ * this array, as processing under this function here is
+ * striving to be agnostic.
+ *
+ * Record the first address and direction we see. If either
+ * changes for a subsequent message, generate ReSTART. The
+ * DW_apb_i2c databook, v1.21a, specifies that ReSTART is
+ * generated when the direction changes, with the default IP
+ * block parameter settings, but it doesn't specify if ReSTART
+ * is generated when the address changes (possibly...). We
+ * don't rely on the default IP block parameter settings as
+ * the block is shared and they may change.
+ */
+ if (num > 0) {
+ addr = msg[0].addr;
+ dir = msg[0].flags & I2C_M_RD;
+ }
+
for (i = 0; i < num; i++) {
- if (msgs[i].flags & I2C_M_RD)
+ u32 i2c_flag = 0;
+
+ if (msg[i].addr != addr || (msg[i].flags ^ dir) & I2C_M_RD) {
+ addr = msg[i].addr;
+ dir = msg[i].flags & I2C_M_RD;
+ i2c_flag |= I2C_X_RESTART;
+ }
+
+ if (i == num - 1) {
+ /* Set the STOP bit on the last message, so
+ * that the IP block generates a STOP after
+ * the last byte of the message.
+ */
+ i2c_flag |= I2C_M_STOP;
+ }
+
+ if (msg[i].flags & I2C_M_RD)
ret = smu_v11_0_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- msgs[i].buf, msgs[i].len);
+ msg + i,
+ i2c_flag);
else
ret = smu_v11_0_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- msgs[i].buf, msgs[i].len);
+ msg + i,
+ i2c_flag);
if (ret != I2C_OK) {
num = -EIO;
@@ -654,23 +697,28 @@ static u32 smu_v11_0_i2c_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
-
static const struct i2c_algorithm smu_v11_0_i2c_algo = {
.master_xfer = smu_v11_0_i2c_xfer,
.functionality = smu_v11_0_i2c_func,
};
+static const struct i2c_adapter_quirks smu_v11_0_i2c_control_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
int smu_v11_0_i2c_control_init(struct i2c_adapter *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
int res;
+ mutex_init(&adev->pm.smu_i2c_mutex);
control->owner = THIS_MODULE;
- control->class = I2C_CLASS_SPD;
+ control->class = I2C_CLASS_HWMON;
control->dev.parent = &adev->pdev->dev;
control->algo = &smu_v11_0_i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops;
+ control->quirks = &smu_v11_0_i2c_control_quirks;
res = i2c_add_adapter(control);
if (res)
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index b7d350be8050..0fc97c364fd7 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -74,7 +74,7 @@
#include "smuio_v9_0.h"
#include "smuio_v11_0.h"
#include "smuio_v13_0.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
#include "mxgpu_ai.h"
#include "amdgpu_ras.h"
#include "amdgpu_xgmi.h"
@@ -575,7 +575,7 @@ soc15_asic_reset_method(struct amdgpu_device *adev)
baco_reset = amdgpu_dpm_is_baco_supported(adev);
break;
case CHIP_VEGA20:
- if (adev->psp.sos_fw_version >= 0x80067)
+ if (adev->psp.sos.fw_version >= 0x80067)
baco_reset = amdgpu_dpm_is_baco_supported(adev);
/*
@@ -635,7 +635,7 @@ static bool soc15_supports_baco(struct amdgpu_device *adev)
case CHIP_ARCTURUS:
return amdgpu_dpm_is_baco_supported(adev);
case CHIP_VEGA20:
- if (adev->psp.sos_fw_version >= 0x80067)
+ if (adev->psp.sos.fw_version >= 0x80067)
return amdgpu_dpm_is_baco_supported(adev);
return false;
default:
@@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
}
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
}
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
@@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -1353,8 +1353,6 @@ static int soc15_common_early_init(void *handle)
adev->asic_funcs = &vega20_asic_funcs;
adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
AMD_CG_SUPPORT_GFX_MGLS |
- AMD_CG_SUPPORT_GFX_CGCG |
- AMD_CG_SUPPORT_GFX_CGLS |
AMD_CG_SUPPORT_GFX_CP_LS |
AMD_CG_SUPPORT_HDP_LS |
AMD_CG_SUPPORT_SDMA_MGCG |
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15_common.h b/drivers/gpu/drm/amd/amdgpu/soc15_common.h
index 0eeb5e073be8..8a9ca87d8663 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15_common.h
+++ b/drivers/gpu/drm/amd/amdgpu/soc15_common.h
@@ -28,13 +28,13 @@
#define SOC15_REG_OFFSET(ip, inst, reg) (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg)
#define __WREG32_SOC15_RLC__(reg, value, flag, hwip) \
- ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->rlcg_wreg) ? \
- adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, value, flag, hwip) : \
+ ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_wreg) ? \
+ adev->gfx.rlc.funcs->sriov_wreg(adev, reg, value, flag, hwip) : \
WREG32(reg, value))
#define __RREG32_SOC15_RLC__(reg, flag, hwip) \
- ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->rlcg_rreg) ? \
- adev->gfx.rlc.funcs->rlcg_rreg(adev, reg, flag, hwip) : \
+ ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_rreg) ? \
+ adev->gfx.rlc.funcs->sriov_rreg(adev, reg, flag, hwip) : \
RREG32(reg))
#define WREG32_FIELD15(ip, idx, reg, field, val) \
diff --git a/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h b/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
index ac2c27b7630c..da815a93d46e 100644
--- a/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
+++ b/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
@@ -33,7 +33,8 @@ enum ta_command_xgmi {
TA_COMMAND_XGMI__GET_NODE_ID = 0x01,
TA_COMMAND_XGMI__GET_HIVE_ID = 0x02,
TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO = 0x03,
- TA_COMMAND_XGMI__SET_TOPOLOGY_INFO = 0x04
+ TA_COMMAND_XGMI__SET_TOPOLOGY_INFO = 0x04,
+ TA_COMMAND_XGMI__GET_PEER_LINKS = 0x0B
};
/* XGMI related enumerations */
@@ -75,6 +76,11 @@ struct ta_xgmi_node_info {
enum ta_xgmi_assigned_sdma_engine sdma_engine;
};
+struct ta_xgmi_peer_link_info {
+ uint64_t node_id;
+ uint8_t num_links;
+};
+
struct ta_xgmi_cmd_initialize_output {
uint32_t status;
};
@@ -97,6 +103,11 @@ struct ta_xgmi_cmd_get_topology_info_output {
struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
};
+struct ta_xgmi_cmd_get_peer_link_info_output {
+ uint32_t num_nodes;
+ struct ta_xgmi_peer_link_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
+};
+
struct ta_xgmi_cmd_set_topology_info_input {
uint32_t num_nodes;
struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES];
@@ -115,6 +126,7 @@ union ta_xgmi_cmd_output {
struct ta_xgmi_cmd_get_node_id_output get_node_id;
struct ta_xgmi_cmd_get_hive_id_output get_hive_id;
struct ta_xgmi_cmd_get_topology_info_output get_topology_info;
+ struct ta_xgmi_cmd_get_peer_link_info_output get_link_info;
};
/**********************************************************/
@@ -122,7 +134,8 @@ struct ta_xgmi_shared_memory {
uint32_t cmd_id;
uint32_t resp_id;
enum ta_xgmi_status xgmi_status;
- uint32_t reserved;
+ uint8_t flag_extend_link_record;
+ uint8_t reserved0[3];
union ta_xgmi_cmd_input xgmi_in_message;
union ta_xgmi_cmd_output xgmi_out_message;
};
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
index 3a8f787374c0..bb30336b1e8d 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
@@ -28,6 +28,21 @@
#include "umc/umc_6_7_0_offset.h"
#include "umc/umc_6_7_0_sh_mask.h"
+const uint32_t
+ umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = {
+ {28, 20, 24, 16, 12, 4, 8, 0},
+ {6, 30, 2, 26, 22, 14, 18, 10},
+ {19, 11, 15, 7, 3, 27, 31, 23},
+ {9, 1, 5, 29, 25, 17, 21, 13}
+};
+const uint32_t
+ umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = {
+ {19, 11, 15, 7, 3, 27, 31, 23},
+ {9, 1, 5, 29, 25, 17, 21, 13},
+ {28, 20, 24, 16, 12, 4, 8, 0},
+ {6, 30, 2, 26, 22, 14, 18, 10},
+};
+
static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev,
uint32_t umc_inst,
uint32_t ch_inst)
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
index 4eb85f247e96..57f2557e7aca 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
@@ -23,6 +23,9 @@
#ifndef __UMC_V6_7_H__
#define __UMC_V6_7_H__
+#include "soc15_common.h"
+#include "amdgpu.h"
+
/* EccErrCnt max value */
#define UMC_V6_7_CE_CNT_MAX 0xffff
/* umc ce interrupt threshold */
@@ -32,6 +35,18 @@
#define UMC_V6_7_INST_DIST 0x40000
+/* number of umc channel instance with memory map register access */
+#define UMC_V6_7_UMC_INSTANCE_NUM 4
+/* number of umc instance with memory map register access */
+#define UMC_V6_7_CHANNEL_INSTANCE_NUM 8
+/* total channel instances in one umc block */
+#define UMC_V6_7_TOTAL_CHANNEL_NUM (UMC_V6_7_CHANNEL_INSTANCE_NUM * UMC_V6_7_UMC_INSTANCE_NUM)
+/* UMC regiser per channel offset */
+#define UMC_V6_7_PER_CHANNEL_OFFSET 0x400
extern const struct amdgpu_umc_ras_funcs umc_v6_7_ras_funcs;
+extern const uint32_t
+ umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM];
+extern const uint32_t
+ umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM];
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
index 6c0e91495365..7232241e3bfb 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
@@ -698,6 +698,30 @@ static int uvd_v3_1_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ /*
+ * Proper cleanups before halting the HW engine:
+ * - cancel the delayed idle work
+ * - enable powergating
+ * - enable clockgating
+ * - disable dpm
+ *
+ * TODO: to align with the VCN implementation, move the
+ * jobs for clockgating/powergating/dpm setting to
+ * ->set_powergating_state().
+ */
+ cancel_delayed_work_sync(&adev->uvd.idle_work);
+
+ if (adev->pm.dpm_enabled) {
+ amdgpu_dpm_enable_uvd(adev, false);
+ } else {
+ amdgpu_asic_set_uvd_clocks(adev, 0, 0);
+ /* shutdown the UVD block */
+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_GATE);
+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_CG_STATE_GATE);
+ }
+
if (RREG32(mmUVD_STATUS) != 0)
uvd_v3_1_stop(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
index a301518e4957..52d6de969f46 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
@@ -212,6 +212,30 @@ static int uvd_v4_2_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ /*
+ * Proper cleanups before halting the HW engine:
+ * - cancel the delayed idle work
+ * - enable powergating
+ * - enable clockgating
+ * - disable dpm
+ *
+ * TODO: to align with the VCN implementation, move the
+ * jobs for clockgating/powergating/dpm setting to
+ * ->set_powergating_state().
+ */
+ cancel_delayed_work_sync(&adev->uvd.idle_work);
+
+ if (adev->pm.dpm_enabled) {
+ amdgpu_dpm_enable_uvd(adev, false);
+ } else {
+ amdgpu_asic_set_uvd_clocks(adev, 0, 0);
+ /* shutdown the UVD block */
+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_GATE);
+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_CG_STATE_GATE);
+ }
+
if (RREG32(mmUVD_STATUS) != 0)
uvd_v4_2_stop(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
index a4d5bd21c83c..db6d06758e4d 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
@@ -210,6 +210,30 @@ static int uvd_v5_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ /*
+ * Proper cleanups before halting the HW engine:
+ * - cancel the delayed idle work
+ * - enable powergating
+ * - enable clockgating
+ * - disable dpm
+ *
+ * TODO: to align with the VCN implementation, move the
+ * jobs for clockgating/powergating/dpm setting to
+ * ->set_powergating_state().
+ */
+ cancel_delayed_work_sync(&adev->uvd.idle_work);
+
+ if (adev->pm.dpm_enabled) {
+ amdgpu_dpm_enable_uvd(adev, false);
+ } else {
+ amdgpu_asic_set_uvd_clocks(adev, 0, 0);
+ /* shutdown the UVD block */
+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_GATE);
+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_CG_STATE_GATE);
+ }
+
if (RREG32(mmUVD_STATUS) != 0)
uvd_v5_0_stop(adev);
@@ -224,7 +248,6 @@ static int uvd_v5_0_suspend(void *handle)
r = uvd_v5_0_hw_fini(adev);
if (r)
return r;
- uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_GATE);
return amdgpu_uvd_suspend(adev);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index cf3803f8f075..bc571833632e 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -543,6 +543,30 @@ static int uvd_v6_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ /*
+ * Proper cleanups before halting the HW engine:
+ * - cancel the delayed idle work
+ * - enable powergating
+ * - enable clockgating
+ * - disable dpm
+ *
+ * TODO: to align with the VCN implementation, move the
+ * jobs for clockgating/powergating/dpm setting to
+ * ->set_powergating_state().
+ */
+ cancel_delayed_work_sync(&adev->uvd.idle_work);
+
+ if (adev->pm.dpm_enabled) {
+ amdgpu_dpm_enable_uvd(adev, false);
+ } else {
+ amdgpu_asic_set_uvd_clocks(adev, 0, 0);
+ /* shutdown the UVD block */
+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_GATE);
+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_CG_STATE_GATE);
+ }
+
if (RREG32(mmUVD_STATUS) != 0)
uvd_v6_0_stop(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
index 939bcfa2a4ec..b6e82d75561f 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
@@ -606,6 +606,30 @@ static int uvd_v7_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ /*
+ * Proper cleanups before halting the HW engine:
+ * - cancel the delayed idle work
+ * - enable powergating
+ * - enable clockgating
+ * - disable dpm
+ *
+ * TODO: to align with the VCN implementation, move the
+ * jobs for clockgating/powergating/dpm setting to
+ * ->set_powergating_state().
+ */
+ cancel_delayed_work_sync(&adev->uvd.idle_work);
+
+ if (adev->pm.dpm_enabled) {
+ amdgpu_dpm_enable_uvd(adev, false);
+ } else {
+ amdgpu_asic_set_uvd_clocks(adev, 0, 0);
+ /* shutdown the UVD block */
+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_GATE);
+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_CG_STATE_GATE);
+ }
+
if (!amdgpu_sriov_vf(adev))
uvd_v7_0_stop(adev);
else {
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
index c7d28c169be5..b70c17f0c52e 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
@@ -477,6 +477,31 @@ static int vce_v2_0_hw_init(void *handle)
static int vce_v2_0_hw_fini(void *handle)
{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ /*
+ * Proper cleanups before halting the HW engine:
+ * - cancel the delayed idle work
+ * - enable powergating
+ * - enable clockgating
+ * - disable dpm
+ *
+ * TODO: to align with the VCN implementation, move the
+ * jobs for clockgating/powergating/dpm setting to
+ * ->set_powergating_state().
+ */
+ cancel_delayed_work_sync(&adev->vce.idle_work);
+
+ if (adev->pm.dpm_enabled) {
+ amdgpu_dpm_enable_vce(adev, false);
+ } else {
+ amdgpu_asic_set_vce_clocks(adev, 0, 0);
+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_PG_STATE_GATE);
+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_CG_STATE_GATE);
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index 3b82fb289ef6..9de66893ccd6 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -490,6 +490,29 @@ static int vce_v3_0_hw_fini(void *handle)
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ /*
+ * Proper cleanups before halting the HW engine:
+ * - cancel the delayed idle work
+ * - enable powergating
+ * - enable clockgating
+ * - disable dpm
+ *
+ * TODO: to align with the VCN implementation, move the
+ * jobs for clockgating/powergating/dpm setting to
+ * ->set_powergating_state().
+ */
+ cancel_delayed_work_sync(&adev->vce.idle_work);
+
+ if (adev->pm.dpm_enabled) {
+ amdgpu_dpm_enable_vce(adev, false);
+ } else {
+ amdgpu_asic_set_vce_clocks(adev, 0, 0);
+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_PG_STATE_GATE);
+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_CG_STATE_GATE);
+ }
+
r = vce_v3_0_wait_for_idle(handle);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
index 90910d19db12..fec902b800c2 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
@@ -542,6 +542,29 @@ static int vce_v4_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ /*
+ * Proper cleanups before halting the HW engine:
+ * - cancel the delayed idle work
+ * - enable powergating
+ * - enable clockgating
+ * - disable dpm
+ *
+ * TODO: to align with the VCN implementation, move the
+ * jobs for clockgating/powergating/dpm setting to
+ * ->set_powergating_state().
+ */
+ cancel_delayed_work_sync(&adev->vce.idle_work);
+
+ if (adev->pm.dpm_enabled) {
+ amdgpu_dpm_enable_vce(adev, false);
+ } else {
+ amdgpu_asic_set_vce_clocks(adev, 0, 0);
+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_PG_STATE_GATE);
+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_CG_STATE_GATE);
+ }
+
if (!amdgpu_sriov_vf(adev)) {
/* vce_v4_0_wait_for_idle(handle); */
vce_v4_0_stop(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index 284bb42d6c86..121ee9f2b8d1 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -119,7 +119,7 @@ static int vcn_v1_0_sw_init(void *handle)
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
- DRM_INFO("PSP loading VCN firmware\n");
+ dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
r = amdgpu_vcn_resume(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index 8af567c546db..f4686e918e0d 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -122,7 +122,7 @@ static int vcn_v2_0_sw_init(void *handle)
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
- DRM_INFO("PSP loading VCN firmware\n");
+ dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
r = amdgpu_vcn_resume(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 888b17d84691..e0c0c3734432 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -152,7 +152,7 @@ static int vcn_v2_5_sw_init(void *handle)
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
}
- DRM_INFO("PSP loading VCN firmware\n");
+ dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
r = amdgpu_vcn_resume(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 47d4f04cbd69..3d18aab88b4e 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -90,9 +90,7 @@ static int vcn_v3_0_early_init(void *handle)
int i;
if (amdgpu_sriov_vf(adev)) {
- for (i = 0; i < VCN_INSTANCES_SIENNA_CICHLID; i++)
- if (amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, i))
- adev->vcn.num_vcn_inst++;
+ adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID;
adev->vcn.harvest_config = 0;
adev->vcn.num_enc_rings = 1;
@@ -153,14 +151,13 @@ static int vcn_v3_0_sw_init(void *handle)
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
- if ((adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) ||
- (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID)) {
+ if (adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) {
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
}
- DRM_INFO("PSP loading VCN firmware\n");
+ dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
r = amdgpu_vcn_resume(adev);
@@ -328,18 +325,28 @@ static int vcn_v3_0_hw_init(void *handle)
continue;
ring = &adev->vcn.inst[i].ring_dec;
- ring->wptr = 0;
- ring->wptr_old = 0;
- vcn_v3_0_dec_ring_set_wptr(ring);
- ring->sched.ready = true;
-
- for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
- ring = &adev->vcn.inst[i].ring_enc[j];
+ if (amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, i)) {
+ ring->sched.ready = false;
+ dev_info(adev->dev, "ring %s is disabled by hypervisor\n", ring->name);
+ } else {
ring->wptr = 0;
ring->wptr_old = 0;
- vcn_v3_0_enc_ring_set_wptr(ring);
+ vcn_v3_0_dec_ring_set_wptr(ring);
ring->sched.ready = true;
}
+
+ for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
+ ring = &adev->vcn.inst[i].ring_enc[j];
+ if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) {
+ ring->sched.ready = false;
+ dev_info(adev->dev, "ring %s is disabled by hypervisor\n", ring->name);
+ } else {
+ ring->wptr = 0;
+ ring->wptr_old = 0;
+ vcn_v3_0_enc_ring_set_wptr(ring);
+ ring->sched.ready = true;
+ }
+ }
}
} else {
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 3d21c0799037..42a35d9520f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -77,7 +77,7 @@
#if defined(CONFIG_DRM_AMD_ACP)
#include "amdgpu_acp.h"
#endif
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
#include "mxgpu_vi.h"
#include "amdgpu_dm.h"
@@ -904,7 +904,14 @@ static bool vi_asic_supports_baco(struct amdgpu_device *adev)
case CHIP_POLARIS11:
case CHIP_POLARIS12:
case CHIP_TOPAZ:
- return amdgpu_dpm_is_baco_supported(adev);
+ /* Disable BACO support for the specific polaris12 SKU temporarily */
+ if ((adev->pdev->device == 0x699F) &&
+ (adev->pdev->revision == 0xC7) &&
+ (adev->pdev->subsystem_vendor == 0x1028) &&
+ (adev->pdev->subsystem_device == 0x0039))
+ return false;
+ else
+ return amdgpu_dpm_is_baco_supported(adev);
default:
return false;
}
@@ -2102,7 +2109,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
break;
case CHIP_FIJI:
amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
@@ -2112,7 +2119,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2132,7 +2139,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2155,7 +2162,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2173,7 +2180,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2194,7 +2201,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
- amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index e48acdd03c1a..86afd37b098d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1393,6 +1393,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
long err = 0;
int i;
uint32_t *devices_arr = NULL;
+ bool table_freed = false;
dev = kfd_device_by_id(GET_GPU_ID(args->handle));
if (!dev)
@@ -1450,7 +1451,8 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
goto get_mem_obj_from_handle_failed;
}
err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
- peer->kgd, (struct kgd_mem *)mem, peer_pdd->drm_priv);
+ peer->kgd, (struct kgd_mem *)mem,
+ peer_pdd->drm_priv, &table_freed);
if (err) {
pr_err("Failed to map to gpu %d/%d\n",
i, args->n_devices);
@@ -1468,16 +1470,17 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
}
/* Flush TLBs after waiting for the page table updates to complete */
- for (i = 0; i < args->n_devices; i++) {
- peer = kfd_device_by_id(devices_arr[i]);
- if (WARN_ON_ONCE(!peer))
- continue;
- peer_pdd = kfd_get_process_device_data(peer, p);
- if (WARN_ON_ONCE(!peer_pdd))
- continue;
- kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY);
+ if (table_freed) {
+ for (i = 0; i < args->n_devices; i++) {
+ peer = kfd_device_by_id(devices_arr[i]);
+ if (WARN_ON_ONCE(!peer))
+ continue;
+ peer_pdd = kfd_get_process_device_data(peer, p);
+ if (WARN_ON_ONCE(!peer_pdd))
+ continue;
+ kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY);
+ }
}
-
kfree(devices_arr);
return err;
@@ -1565,10 +1568,29 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
}
args->n_success = i+1;
}
- kfree(devices_arr);
-
mutex_unlock(&p->mutex);
+ if (dev->device_info->asic_family == CHIP_ALDEBARAN) {
+ err = amdgpu_amdkfd_gpuvm_sync_memory(dev->kgd,
+ (struct kgd_mem *) mem, true);
+ if (err) {
+ pr_debug("Sync memory failed, wait interrupted by user signal\n");
+ goto sync_memory_failed;
+ }
+
+ /* Flush TLBs after waiting for the page table updates to complete */
+ for (i = 0; i < args->n_devices; i++) {
+ peer = kfd_device_by_id(devices_arr[i]);
+ if (WARN_ON_ONCE(!peer))
+ continue;
+ peer_pdd = kfd_get_process_device_data(peer, p);
+ if (WARN_ON_ONCE(!peer_pdd))
+ continue;
+ kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
+ }
+ }
+ kfree(devices_arr);
+
return 0;
bind_process_to_device_failed:
@@ -1576,6 +1598,7 @@ get_mem_obj_from_handle_failed:
unmap_memory_from_gpu_failed:
mutex_unlock(&p->mutex);
copy_from_user_failed:
+sync_memory_failed:
kfree(devices_arr);
return err;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index c6b02aee4993..cfedfb1e8596 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1404,6 +1404,7 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev,
break;
case CHIP_NAVI10:
case CHIP_NAVI12:
+ case CHIP_CYAN_SKILLFISH:
pcache_info = navi10_cache_info;
num_of_cache_types = ARRAY_SIZE(navi10_cache_info);
break;
@@ -1989,8 +1990,19 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,
sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL;
sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI;
sub_type_hdr->num_hops_xgmi = 1;
+ if (adev->asic_type == CHIP_ALDEBARAN) {
+ sub_type_hdr->minimum_bandwidth_mbs =
+ amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(
+ kdev->kgd, NULL, true);
+ sub_type_hdr->maximum_bandwidth_mbs =
+ sub_type_hdr->minimum_bandwidth_mbs;
+ }
} else {
sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_PCIEXPRESS;
+ sub_type_hdr->minimum_bandwidth_mbs =
+ amdgpu_amdkfd_get_pcie_bandwidth_mbytes(kdev->kgd, true);
+ sub_type_hdr->maximum_bandwidth_mbs =
+ amdgpu_amdkfd_get_pcie_bandwidth_mbytes(kdev->kgd, false);
}
sub_type_hdr->proximity_domain_from = proximity_domain;
@@ -2033,6 +2045,11 @@ static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,
sub_type_hdr->proximity_domain_to = proximity_domain_to;
sub_type_hdr->num_hops_xgmi =
amdgpu_amdkfd_get_xgmi_hops_count(kdev->kgd, peer_kdev->kgd);
+ sub_type_hdr->maximum_bandwidth_mbs =
+ amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->kgd, peer_kdev->kgd, false);
+ sub_type_hdr->minimum_bandwidth_mbs = sub_type_hdr->maximum_bandwidth_mbs ?
+ amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->kgd, NULL, true) : 0;
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 6b57dfd2cd2a..16a57b70cc1a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -84,12 +84,14 @@ static const struct kfd2kgd_calls *kfd2kgd_funcs[] = {
[CHIP_DIMGREY_CAVEFISH] = &gfx_v10_3_kfd2kgd,
[CHIP_BEIGE_GOBY] = &gfx_v10_3_kfd2kgd,
[CHIP_YELLOW_CARP] = &gfx_v10_3_kfd2kgd,
+ [CHIP_CYAN_SKILLFISH] = &gfx_v10_kfd2kgd,
};
#ifdef KFD_SUPPORT_IOMMU_V2
static const struct kfd_device_info kaveri_device_info = {
.asic_family = CHIP_KAVERI,
.asic_name = "kaveri",
+ .gfx_target_version = 70000,
.max_pasid_bits = 16,
/* max num of queues for KV.TODO should be a dynamic value */
.max_no_of_hqd = 24,
@@ -109,6 +111,7 @@ static const struct kfd_device_info kaveri_device_info = {
static const struct kfd_device_info carrizo_device_info = {
.asic_family = CHIP_CARRIZO,
.asic_name = "carrizo",
+ .gfx_target_version = 80001,
.max_pasid_bits = 16,
/* max num of queues for CZ.TODO should be a dynamic value */
.max_no_of_hqd = 24,
@@ -129,6 +132,7 @@ static const struct kfd_device_info carrizo_device_info = {
static const struct kfd_device_info raven_device_info = {
.asic_family = CHIP_RAVEN,
.asic_name = "raven",
+ .gfx_target_version = 90002,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -147,6 +151,7 @@ static const struct kfd_device_info raven_device_info = {
static const struct kfd_device_info hawaii_device_info = {
.asic_family = CHIP_HAWAII,
.asic_name = "hawaii",
+ .gfx_target_version = 70001,
.max_pasid_bits = 16,
/* max num of queues for KV.TODO should be a dynamic value */
.max_no_of_hqd = 24,
@@ -166,6 +171,7 @@ static const struct kfd_device_info hawaii_device_info = {
static const struct kfd_device_info tonga_device_info = {
.asic_family = CHIP_TONGA,
.asic_name = "tonga",
+ .gfx_target_version = 80002,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@@ -184,6 +190,7 @@ static const struct kfd_device_info tonga_device_info = {
static const struct kfd_device_info fiji_device_info = {
.asic_family = CHIP_FIJI,
.asic_name = "fiji",
+ .gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@@ -202,6 +209,7 @@ static const struct kfd_device_info fiji_device_info = {
static const struct kfd_device_info fiji_vf_device_info = {
.asic_family = CHIP_FIJI,
.asic_name = "fiji",
+ .gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@@ -221,6 +229,7 @@ static const struct kfd_device_info fiji_vf_device_info = {
static const struct kfd_device_info polaris10_device_info = {
.asic_family = CHIP_POLARIS10,
.asic_name = "polaris10",
+ .gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@@ -239,6 +248,7 @@ static const struct kfd_device_info polaris10_device_info = {
static const struct kfd_device_info polaris10_vf_device_info = {
.asic_family = CHIP_POLARIS10,
.asic_name = "polaris10",
+ .gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@@ -257,6 +267,7 @@ static const struct kfd_device_info polaris10_vf_device_info = {
static const struct kfd_device_info polaris11_device_info = {
.asic_family = CHIP_POLARIS11,
.asic_name = "polaris11",
+ .gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@@ -275,6 +286,7 @@ static const struct kfd_device_info polaris11_device_info = {
static const struct kfd_device_info polaris12_device_info = {
.asic_family = CHIP_POLARIS12,
.asic_name = "polaris12",
+ .gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@@ -293,6 +305,7 @@ static const struct kfd_device_info polaris12_device_info = {
static const struct kfd_device_info vegam_device_info = {
.asic_family = CHIP_VEGAM,
.asic_name = "vegam",
+ .gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@@ -311,6 +324,7 @@ static const struct kfd_device_info vegam_device_info = {
static const struct kfd_device_info vega10_device_info = {
.asic_family = CHIP_VEGA10,
.asic_name = "vega10",
+ .gfx_target_version = 90000,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -329,6 +343,7 @@ static const struct kfd_device_info vega10_device_info = {
static const struct kfd_device_info vega10_vf_device_info = {
.asic_family = CHIP_VEGA10,
.asic_name = "vega10",
+ .gfx_target_version = 90000,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -347,6 +362,7 @@ static const struct kfd_device_info vega10_vf_device_info = {
static const struct kfd_device_info vega12_device_info = {
.asic_family = CHIP_VEGA12,
.asic_name = "vega12",
+ .gfx_target_version = 90004,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -365,6 +381,7 @@ static const struct kfd_device_info vega12_device_info = {
static const struct kfd_device_info vega20_device_info = {
.asic_family = CHIP_VEGA20,
.asic_name = "vega20",
+ .gfx_target_version = 90006,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -383,6 +400,7 @@ static const struct kfd_device_info vega20_device_info = {
static const struct kfd_device_info arcturus_device_info = {
.asic_family = CHIP_ARCTURUS,
.asic_name = "arcturus",
+ .gfx_target_version = 90008,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -401,6 +419,7 @@ static const struct kfd_device_info arcturus_device_info = {
static const struct kfd_device_info aldebaran_device_info = {
.asic_family = CHIP_ALDEBARAN,
.asic_name = "aldebaran",
+ .gfx_target_version = 90010,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -419,6 +438,7 @@ static const struct kfd_device_info aldebaran_device_info = {
static const struct kfd_device_info renoir_device_info = {
.asic_family = CHIP_RENOIR,
.asic_name = "renoir",
+ .gfx_target_version = 90002,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -437,6 +457,7 @@ static const struct kfd_device_info renoir_device_info = {
static const struct kfd_device_info navi10_device_info = {
.asic_family = CHIP_NAVI10,
.asic_name = "navi10",
+ .gfx_target_version = 100100,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -455,6 +476,7 @@ static const struct kfd_device_info navi10_device_info = {
static const struct kfd_device_info navi12_device_info = {
.asic_family = CHIP_NAVI12,
.asic_name = "navi12",
+ .gfx_target_version = 100101,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -473,6 +495,7 @@ static const struct kfd_device_info navi12_device_info = {
static const struct kfd_device_info navi14_device_info = {
.asic_family = CHIP_NAVI14,
.asic_name = "navi14",
+ .gfx_target_version = 100102,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -491,6 +514,7 @@ static const struct kfd_device_info navi14_device_info = {
static const struct kfd_device_info sienna_cichlid_device_info = {
.asic_family = CHIP_SIENNA_CICHLID,
.asic_name = "sienna_cichlid",
+ .gfx_target_version = 100300,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -509,6 +533,7 @@ static const struct kfd_device_info sienna_cichlid_device_info = {
static const struct kfd_device_info navy_flounder_device_info = {
.asic_family = CHIP_NAVY_FLOUNDER,
.asic_name = "navy_flounder",
+ .gfx_target_version = 100301,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -527,6 +552,7 @@ static const struct kfd_device_info navy_flounder_device_info = {
static const struct kfd_device_info vangogh_device_info = {
.asic_family = CHIP_VANGOGH,
.asic_name = "vangogh",
+ .gfx_target_version = 100303,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -545,6 +571,7 @@ static const struct kfd_device_info vangogh_device_info = {
static const struct kfd_device_info dimgrey_cavefish_device_info = {
.asic_family = CHIP_DIMGREY_CAVEFISH,
.asic_name = "dimgrey_cavefish",
+ .gfx_target_version = 100302,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -563,6 +590,7 @@ static const struct kfd_device_info dimgrey_cavefish_device_info = {
static const struct kfd_device_info beige_goby_device_info = {
.asic_family = CHIP_BEIGE_GOBY,
.asic_name = "beige_goby",
+ .gfx_target_version = 100304,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -581,6 +609,7 @@ static const struct kfd_device_info beige_goby_device_info = {
static const struct kfd_device_info yellow_carp_device_info = {
.asic_family = CHIP_YELLOW_CARP,
.asic_name = "yellow_carp",
+ .gfx_target_version = 100305,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@@ -596,6 +625,25 @@ static const struct kfd_device_info yellow_carp_device_info = {
.num_sdma_queues_per_engine = 2,
};
+static const struct kfd_device_info cyan_skillfish_device_info = {
+ .asic_family = CHIP_CYAN_SKILLFISH,
+ .asic_name = "cyan_skillfish",
+ .gfx_target_version = 100103,
+ .max_pasid_bits = 16,
+ .max_no_of_hqd = 24,
+ .doorbell_size = 8,
+ .ih_ring_entry_size = 8 * sizeof(uint32_t),
+ .event_interrupt_class = &event_interrupt_class_v9,
+ .num_of_watch_points = 4,
+ .mqd_size_aligned = MQD_SIZE_ALIGNED,
+ .needs_iommu_device = false,
+ .supports_cwsr = true,
+ .needs_pci_atomics = true,
+ .num_sdma_engines = 2,
+ .num_xgmi_sdma_engines = 0,
+ .num_sdma_queues_per_engine = 8,
+};
+
/* For each entry, [0] is regular and [1] is virtualisation device. */
static const struct kfd_device_info *kfd_supported_devices[][2] = {
#ifdef KFD_SUPPORT_IOMMU_V2
@@ -625,6 +673,7 @@ static const struct kfd_device_info *kfd_supported_devices[][2] = {
[CHIP_DIMGREY_CAVEFISH] = {&dimgrey_cavefish_device_info, &dimgrey_cavefish_device_info},
[CHIP_BEIGE_GOBY] = {&beige_goby_device_info, &beige_goby_device_info},
[CHIP_YELLOW_CARP] = {&yellow_carp_device_info, NULL},
+ [CHIP_CYAN_SKILLFISH] = {&cyan_skillfish_device_info, NULL},
};
static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
@@ -1369,7 +1418,7 @@ void kfd_dec_compute_active(struct kfd_dev *kfd)
WARN_ONCE(count < 0, "Compute profile ref. count error");
}
-void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
+void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
{
if (kfd && kfd->init_complete)
kfd_smi_event_update_thermal_throttling(kfd, throttle_bitmask);
@@ -1382,18 +1431,12 @@ void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
*/
int kfd_debugfs_hang_hws(struct kfd_dev *dev)
{
- int r = 0;
-
if (dev->dqm->sched_policy != KFD_SCHED_POLICY_HWS) {
pr_err("HWS is not enabled");
return -EINVAL;
}
- r = pm_debugfs_hang_hws(&dev->dqm->packets);
- if (!r)
- r = dqm_debugfs_execute_queues(dev->dqm);
-
- return r;
+ return dqm_debugfs_hang_hws(dev->dqm);
}
#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index 16a1713808c2..f8fce9d05f50 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -211,6 +211,15 @@ static void deallocate_doorbell(struct qcm_process_device *qpd,
WARN_ON(!old);
}
+static void program_trap_handler_settings(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd)
+{
+ if (dqm->dev->kfd2kgd->program_trap_handler_settings)
+ dqm->dev->kfd2kgd->program_trap_handler_settings(
+ dqm->dev->kgd, qpd->vmid,
+ qpd->tba_addr, qpd->tma_addr);
+}
+
static int allocate_vmid(struct device_queue_manager *dqm,
struct qcm_process_device *qpd,
struct queue *q)
@@ -241,6 +250,10 @@ static int allocate_vmid(struct device_queue_manager *dqm,
program_sh_mem_settings(dqm, qpd);
+ if (dqm->dev->device_info->asic_family >= CHIP_VEGA10 &&
+ dqm->dev->cwsr_enabled)
+ program_trap_handler_settings(dqm, qpd);
+
/* qpd->page_table_base is set earlier when register_process()
* is called, i.e. when the first queue is created.
*/
@@ -260,7 +273,7 @@ static int allocate_vmid(struct device_queue_manager *dqm,
static int flush_texture_cache_nocpsch(struct kfd_dev *kdev,
struct qcm_process_device *qpd)
{
- const struct packet_manager_funcs *pmf = qpd->dqm->packets.pmf;
+ const struct packet_manager_funcs *pmf = qpd->dqm->packet_mgr.pmf;
int ret;
if (!qpd->ib_kaddr)
@@ -582,7 +595,9 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
}
retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd,
- KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN,
+ (dqm->dev->cwsr_enabled?
+ KFD_PREEMPT_TYPE_WAVEFRONT_SAVE:
+ KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN),
KFD_UNMAP_LATENCY_MS, q->pipe, q->queue);
if (retval) {
pr_err("destroy mqd failed\n");
@@ -675,7 +690,9 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm,
continue;
retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd,
- KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN,
+ (dqm->dev->cwsr_enabled?
+ KFD_PREEMPT_TYPE_WAVEFRONT_SAVE:
+ KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN),
KFD_UNMAP_LATENCY_MS, q->pipe, q->queue);
if (retval && !ret)
/* Return the first error, but keep going to
@@ -1000,7 +1017,7 @@ static int start_nocpsch(struct device_queue_manager *dqm)
init_interrupts(dqm);
if (dqm->dev->device_info->asic_family == CHIP_HAWAII)
- return pm_init(&dqm->packets, dqm);
+ return pm_init(&dqm->packet_mgr, dqm);
dqm->sched_running = true;
return 0;
@@ -1009,7 +1026,7 @@ static int start_nocpsch(struct device_queue_manager *dqm)
static int stop_nocpsch(struct device_queue_manager *dqm)
{
if (dqm->dev->device_info->asic_family == CHIP_HAWAII)
- pm_uninit(&dqm->packets, false);
+ pm_uninit(&dqm->packet_mgr, false);
dqm->sched_running = false;
return 0;
@@ -1124,7 +1141,7 @@ static int set_sched_resources(struct device_queue_manager *dqm)
"queue mask: 0x%8llX\n",
res.vmid_mask, res.queue_mask);
- return pm_send_set_resources(&dqm->packets, &res);
+ return pm_send_set_resources(&dqm->packet_mgr, &res);
}
static int initialize_cpsch(struct device_queue_manager *dqm)
@@ -1164,7 +1181,8 @@ static int start_cpsch(struct device_queue_manager *dqm)
retval = 0;
- retval = pm_init(&dqm->packets, dqm);
+ dqm_lock(dqm);
+ retval = pm_init(&dqm->packet_mgr, dqm);
if (retval)
goto fail_packet_manager_init;
@@ -1186,7 +1204,6 @@ static int start_cpsch(struct device_queue_manager *dqm)
init_interrupts(dqm);
- dqm_lock(dqm);
/* clear hang status when driver try to start the hw scheduler */
dqm->is_hws_hang = false;
dqm->is_resetting = false;
@@ -1197,8 +1214,9 @@ static int start_cpsch(struct device_queue_manager *dqm)
return 0;
fail_allocate_vidmem:
fail_set_sched_resources:
- pm_uninit(&dqm->packets, false);
+ pm_uninit(&dqm->packet_mgr, false);
fail_packet_manager_init:
+ dqm_unlock(dqm);
return retval;
}
@@ -1211,12 +1229,12 @@ static int stop_cpsch(struct device_queue_manager *dqm)
unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
hanging = dqm->is_hws_hang || dqm->is_resetting;
dqm->sched_running = false;
- dqm_unlock(dqm);
- pm_release_ib(&dqm->packets);
+ pm_release_ib(&dqm->packet_mgr);
kfd_gtt_sa_free(dqm->dev, dqm->fence_mem);
- pm_uninit(&dqm->packets, hanging);
+ pm_uninit(&dqm->packet_mgr, hanging);
+ dqm_unlock(dqm);
return 0;
}
@@ -1390,7 +1408,7 @@ static int map_queues_cpsch(struct device_queue_manager *dqm)
if (dqm->active_runlist)
return 0;
- retval = pm_send_runlist(&dqm->packets, &dqm->queues);
+ retval = pm_send_runlist(&dqm->packet_mgr, &dqm->queues);
pr_debug("%s sent runlist\n", __func__);
if (retval) {
pr_err("failed to execute runlist\n");
@@ -1416,13 +1434,13 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
if (!dqm->active_runlist)
return retval;
- retval = pm_send_unmap_queue(&dqm->packets, KFD_QUEUE_TYPE_COMPUTE,
+ retval = pm_send_unmap_queue(&dqm->packet_mgr, KFD_QUEUE_TYPE_COMPUTE,
filter, filter_param, false, 0);
if (retval)
return retval;
*dqm->fence_addr = KFD_FENCE_INIT;
- pm_send_query_status(&dqm->packets, dqm->fence_gpu_addr,
+ pm_send_query_status(&dqm->packet_mgr, dqm->fence_gpu_addr,
KFD_FENCE_COMPLETED);
/* should be timed out */
retval = amdkfd_fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED,
@@ -1448,14 +1466,14 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
* check those fields
*/
mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ];
- if (mqd_mgr->read_doorbell_id(dqm->packets.priv_queue->queue->mqd)) {
+ if (mqd_mgr->read_doorbell_id(dqm->packet_mgr.priv_queue->queue->mqd)) {
pr_err("HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n");
while (halt_if_hws_hang)
schedule();
return -ETIME;
}
- pm_release_ib(&dqm->packets);
+ pm_release_ib(&dqm->packet_mgr);
dqm->active_runlist = false;
return retval;
@@ -1946,6 +1964,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev)
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
device_queue_manager_init_v10_navi10(&dqm->asic_ops);
break;
default:
@@ -2099,11 +2118,16 @@ int dqm_debugfs_hqds(struct seq_file *m, void *data)
return r;
}
-int dqm_debugfs_execute_queues(struct device_queue_manager *dqm)
+int dqm_debugfs_hang_hws(struct device_queue_manager *dqm)
{
int r = 0;
dqm_lock(dqm);
+ r = pm_debugfs_hang_hws(&dqm->packet_mgr);
+ if (r) {
+ dqm_unlock(dqm);
+ return r;
+ }
dqm->active_runlist = true;
r = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
dqm_unlock(dqm);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
index 71e2fde56b2b..c8719682c4da 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
@@ -169,7 +169,7 @@ struct device_queue_manager {
struct device_queue_manager_asic_ops asic_ops;
struct mqd_manager *mqd_mgrs[KFD_MQD_TYPE_MAX];
- struct packet_manager packets;
+ struct packet_manager packet_mgr;
struct kfd_dev *dev;
struct mutex lock_hidden; /* use dqm_lock/unlock(dqm) */
struct list_head queues;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
index a9b329f0f862..2e86692def19 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
@@ -422,6 +422,7 @@ int kfd_init_apertures(struct kfd_process *process)
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
kfd_init_apertures_v9(pdd, id);
break;
default:
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
index 88813dad731f..c021519af810 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
@@ -98,36 +98,78 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
uint32_t *se_mask)
{
struct kfd_cu_info cu_info;
- uint32_t cu_per_se[KFD_MAX_NUM_SE] = {0};
- int i, se, sh, cu = 0;
-
+ uint32_t cu_per_sh[KFD_MAX_NUM_SE][KFD_MAX_NUM_SH_PER_SE] = {0};
+ int i, se, sh, cu;
amdgpu_amdkfd_get_cu_info(mm->dev->kgd, &cu_info);
if (cu_mask_count > cu_info.cu_active_number)
cu_mask_count = cu_info.cu_active_number;
+ /* Exceeding these bounds corrupts the stack and indicates a coding error.
+ * Returning with no CU's enabled will hang the queue, which should be
+ * attention grabbing.
+ */
+ if (cu_info.num_shader_engines > KFD_MAX_NUM_SE) {
+ pr_err("Exceeded KFD_MAX_NUM_SE, chip reports %d\n", cu_info.num_shader_engines);
+ return;
+ }
+ if (cu_info.num_shader_arrays_per_engine > KFD_MAX_NUM_SH_PER_SE) {
+ pr_err("Exceeded KFD_MAX_NUM_SH, chip reports %d\n",
+ cu_info.num_shader_arrays_per_engine * cu_info.num_shader_engines);
+ return;
+ }
+ /* Count active CUs per SH.
+ *
+ * Some CUs in an SH may be disabled. HW expects disabled CUs to be
+ * represented in the high bits of each SH's enable mask (the upper and lower
+ * 16 bits of se_mask) and will take care of the actual distribution of
+ * disabled CUs within each SH automatically.
+ * Each half of se_mask must be filled only on bits 0-cu_per_sh[se][sh]-1.
+ *
+ * See note on Arcturus cu_bitmap layout in gfx_v9_0_get_cu_info.
+ */
for (se = 0; se < cu_info.num_shader_engines; se++)
for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++)
- cu_per_se[se] += hweight32(cu_info.cu_bitmap[se % 4][sh + (se / 4)]);
-
- /* Symmetrically map cu_mask to all SEs:
- * cu_mask[0] bit0 -> se_mask[0] bit0;
- * cu_mask[0] bit1 -> se_mask[1] bit0;
- * ... (if # SE is 4)
- * cu_mask[0] bit4 -> se_mask[0] bit1;
+ cu_per_sh[se][sh] = hweight32(cu_info.cu_bitmap[se % 4][sh + (se / 4)]);
+
+ /* Symmetrically map cu_mask to all SEs & SHs:
+ * se_mask programs up to 2 SH in the upper and lower 16 bits.
+ *
+ * Examples
+ * Assuming 1 SH/SE, 4 SEs:
+ * cu_mask[0] bit0 -> se_mask[0] bit0
+ * cu_mask[0] bit1 -> se_mask[1] bit0
+ * ...
+ * cu_mask[0] bit4 -> se_mask[0] bit1
+ * ...
+ *
+ * Assuming 2 SH/SE, 4 SEs
+ * cu_mask[0] bit0 -> se_mask[0] bit0 (SE0,SH0,CU0)
+ * cu_mask[0] bit1 -> se_mask[1] bit0 (SE1,SH0,CU0)
+ * ...
+ * cu_mask[0] bit4 -> se_mask[0] bit16 (SE0,SH1,CU0)
+ * cu_mask[0] bit5 -> se_mask[1] bit16 (SE1,SH1,CU0)
+ * ...
+ * cu_mask[0] bit8 -> se_mask[0] bit1 (SE0,SH0,CU1)
* ...
+ *
+ * First ensure all CUs are disabled, then enable user specified CUs.
*/
- se = 0;
- for (i = 0; i < cu_mask_count; i++) {
- if (cu_mask[i / 32] & (1 << (i % 32)))
- se_mask[se] |= 1 << cu;
-
- do {
- se++;
- if (se == cu_info.num_shader_engines) {
- se = 0;
- cu++;
+ for (i = 0; i < cu_info.num_shader_engines; i++)
+ se_mask[i] = 0;
+
+ i = 0;
+ for (cu = 0; cu < 16; cu++) {
+ for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) {
+ for (se = 0; se < cu_info.num_shader_engines; se++) {
+ if (cu_per_sh[se][sh] > cu) {
+ if (cu_mask[i / 32] & (1 << (i % 32)))
+ se_mask[se] |= 1 << (cu + sh * 16);
+ i++;
+ if (i == cu_mask_count)
+ return;
+ }
}
- } while (cu >= cu_per_se[se] && cu < 32);
+ }
}
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
index b5e2ea7550d4..6e6918ccedfd 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
@@ -27,6 +27,7 @@
#include "kfd_priv.h"
#define KFD_MAX_NUM_SE 8
+#define KFD_MAX_NUM_SH_PER_SE 2
/**
* struct mqd_manager
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
index d8e940f03102..e547f1f8c49f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
@@ -251,6 +251,7 @@ int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm)
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
pm->pmf = &kfd_v9_pm_funcs;
break;
case CHIP_ALDEBARAN:
@@ -278,6 +279,7 @@ void pm_uninit(struct packet_manager *pm, bool hanging)
{
mutex_destroy(&pm->lock);
kernel_queue_uninit(pm->priv_queue, hanging);
+ pm->priv_queue = NULL;
}
int pm_send_set_resources(struct packet_manager *pm,
@@ -447,6 +449,9 @@ int pm_debugfs_hang_hws(struct packet_manager *pm)
uint32_t *buffer, size;
int r = 0;
+ if (!pm->priv_queue)
+ return -EAGAIN;
+
size = pm->pmf->query_status_size;
mutex_lock(&pm->lock);
kq_acquire_packet_buffer(pm->priv_queue,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index 3426743ed228..ab83b0de6b22 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -196,6 +196,7 @@ struct kfd_event_interrupt_class {
struct kfd_device_info {
enum amd_asic_type asic_family;
const char *asic_name;
+ uint32_t gfx_target_version;
const struct kfd_event_interrupt_class *event_interrupt_class;
unsigned int max_pasid_bits;
unsigned int max_no_of_hqd;
@@ -1194,7 +1195,7 @@ int pm_debugfs_runlist(struct seq_file *m, void *data);
int kfd_debugfs_hang_hws(struct kfd_dev *dev);
int pm_debugfs_hang_hws(struct packet_manager *pm);
-int dqm_debugfs_execute_queues(struct device_queue_manager *dqm);
+int dqm_debugfs_hang_hws(struct device_queue_manager *dqm);
#else
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 8a2c6fc438c0..21ec8a18cad2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -714,7 +714,8 @@ static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
if (err)
goto err_alloc_mem;
- err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, mem, pdd->drm_priv);
+ err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, mem,
+ pdd->drm_priv, NULL);
if (err)
goto err_map_mem;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
index 246522423559..ed4bc5f844ce 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
@@ -205,23 +205,23 @@ void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset)
}
void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev,
- uint32_t throttle_bitmask)
+ uint64_t throttle_bitmask)
{
struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd;
/*
* ThermalThrottle msg = throttle_bitmask(8):
* thermal_interrupt_count(16):
- * 1 byte event + 1 byte space + 8 byte throttle_bitmask +
+ * 1 byte event + 1 byte space + 16 byte throttle_bitmask +
* 1 byte : + 16 byte thermal_interupt_counter + 1 byte \n +
- * 1 byte \0 = 29
+ * 1 byte \0 = 37
*/
- char fifo_in[29];
+ char fifo_in[37];
int len;
if (list_empty(&dev->smi_clients))
return;
- len = snprintf(fifo_in, sizeof(fifo_in), "%x %x:%llx\n",
+ len = snprintf(fifo_in, sizeof(fifo_in), "%x %llx:%llx\n",
KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask,
atomic64_read(&adev->smu.throttle_int_counter));
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
index b9b0438202e2..bffd0c32b060 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
@@ -26,7 +26,7 @@
int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd);
void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid);
void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev,
- uint32_t throttle_bitmask);
+ uint64_t throttle_bitmask);
void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset);
#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index e883731c3f8f..491373fcdb38 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -120,6 +120,7 @@ static void svm_range_remove_notifier(struct svm_range *prange)
static int
svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
+ unsigned long offset, unsigned long npages,
unsigned long *hmm_pfns, uint32_t gpuidx)
{
enum dma_data_direction dir = DMA_BIDIRECTIONAL;
@@ -136,7 +137,8 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
prange->dma_addr[gpuidx] = addr;
}
- for (i = 0; i < prange->npages; i++) {
+ addr += offset;
+ for (i = 0; i < npages; i++) {
if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]),
"leaking dma mapping\n"))
dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
@@ -167,6 +169,7 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
static int
svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
+ unsigned long offset, unsigned long npages,
unsigned long *hmm_pfns)
{
struct kfd_process *p;
@@ -187,7 +190,8 @@ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
}
adev = (struct amdgpu_device *)pdd->dev->kgd;
- r = svm_range_dma_map_dev(adev, prange, hmm_pfns, gpuidx);
+ r = svm_range_dma_map_dev(adev, prange, offset, npages,
+ hmm_pfns, gpuidx);
if (r)
break;
}
@@ -1088,11 +1092,6 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags);
-
- pr_debug("svms 0x%p [0x%lx 0x%lx] vram %d PTE 0x%llx mapping 0x%x\n",
- prange->svms, prange->start, prange->last,
- (domain == SVM_RANGE_VRAM_DOMAIN) ? 1:0, pte_flags, mapping_flags);
-
return pte_flags;
}
@@ -1156,7 +1155,8 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
static int
svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
- struct svm_range *prange, dma_addr_t *dma_addr,
+ struct svm_range *prange, unsigned long offset,
+ unsigned long npages, bool readonly, dma_addr_t *dma_addr,
struct amdgpu_device *bo_adev, struct dma_fence **fence)
{
struct amdgpu_bo_va bo_va;
@@ -1167,14 +1167,15 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
int r = 0;
int64_t i;
- pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start,
- prange->last);
+ last_start = prange->start + offset;
+
+ pr_debug("svms 0x%p [0x%lx 0x%lx] readonly %d\n", prange->svms,
+ last_start, last_start + npages - 1, readonly);
if (prange->svm_bo && prange->ttm_res)
bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev);
- last_start = prange->start;
- for (i = 0; i < prange->npages; i++) {
+ for (i = offset; i < offset + npages; i++) {
last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN;
dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN;
if ((prange->start + i) < prange->last &&
@@ -1183,13 +1184,21 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n",
last_start, prange->start + i, last_domain ? "GPU" : "CPU");
+
pte_flags = svm_range_get_pte_flags(adev, prange, last_domain);
- r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, NULL,
- last_start,
+ if (readonly)
+ pte_flags &= ~AMDGPU_PTE_WRITEABLE;
+
+ pr_debug("svms 0x%p map [0x%lx 0x%llx] vram %d PTE 0x%llx\n",
+ prange->svms, last_start, prange->start + i,
+ (last_domain == SVM_RANGE_VRAM_DOMAIN) ? 1 : 0,
+ pte_flags);
+
+ r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false,
+ NULL, last_start,
prange->start + i, pte_flags,
last_start - prange->start,
- NULL,
- dma_addr,
+ NULL, dma_addr,
&vm->last_update,
&table_freed);
if (r) {
@@ -1220,8 +1229,10 @@ out:
return r;
}
-static int svm_range_map_to_gpus(struct svm_range *prange,
- unsigned long *bitmap, bool wait)
+static int
+svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
+ unsigned long npages, bool readonly,
+ unsigned long *bitmap, bool wait)
{
struct kfd_process_device *pdd;
struct amdgpu_device *bo_adev;
@@ -1257,7 +1268,8 @@ static int svm_range_map_to_gpus(struct svm_range *prange,
}
r = svm_range_map_to_gpu(adev, drm_priv_to_vm(pdd->drm_priv),
- prange, prange->dma_addr[gpuidx],
+ prange, offset, npages, readonly,
+ prange->dma_addr[gpuidx],
bo_adev, wait ? &fence : NULL);
if (r)
break;
@@ -1390,7 +1402,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
int32_t gpuidx, bool intr, bool wait)
{
struct svm_validate_context ctx;
- struct hmm_range *hmm_range;
+ unsigned long start, end, addr;
struct kfd_process *p;
void *owner;
int32_t idx;
@@ -1448,40 +1460,66 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
break;
}
}
- r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
- prange->start << PAGE_SHIFT,
- prange->npages, &hmm_range,
- false, true, owner);
- if (r) {
- pr_debug("failed %d to get svm range pages\n", r);
- goto unreserve_out;
- }
- r = svm_range_dma_map(prange, ctx.bitmap,
- hmm_range->hmm_pfns);
- if (r) {
- pr_debug("failed %d to dma map range\n", r);
- goto unreserve_out;
- }
+ start = prange->start << PAGE_SHIFT;
+ end = (prange->last + 1) << PAGE_SHIFT;
+ for (addr = start; addr < end && !r; ) {
+ struct hmm_range *hmm_range;
+ struct vm_area_struct *vma;
+ unsigned long next;
+ unsigned long offset;
+ unsigned long npages;
+ bool readonly;
- prange->validated_once = true;
+ vma = find_vma(mm, addr);
+ if (!vma || addr < vma->vm_start) {
+ r = -EFAULT;
+ goto unreserve_out;
+ }
+ readonly = !(vma->vm_flags & VM_WRITE);
- svm_range_lock(prange);
- if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
- pr_debug("hmm update the range, need validate again\n");
- r = -EAGAIN;
- goto unlock_out;
- }
- if (!list_empty(&prange->child_list)) {
- pr_debug("range split by unmap in parallel, validate again\n");
- r = -EAGAIN;
- goto unlock_out;
- }
+ next = min(vma->vm_end, end);
+ npages = (next - addr) >> PAGE_SHIFT;
+ r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
+ addr, npages, &hmm_range,
+ readonly, true, owner);
+ if (r) {
+ pr_debug("failed %d to get svm range pages\n", r);
+ goto unreserve_out;
+ }
- r = svm_range_map_to_gpus(prange, ctx.bitmap, wait);
+ offset = (addr - start) >> PAGE_SHIFT;
+ r = svm_range_dma_map(prange, ctx.bitmap, offset, npages,
+ hmm_range->hmm_pfns);
+ if (r) {
+ pr_debug("failed %d to dma map range\n", r);
+ goto unreserve_out;
+ }
+
+ svm_range_lock(prange);
+ if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
+ pr_debug("hmm update the range, need validate again\n");
+ r = -EAGAIN;
+ goto unlock_out;
+ }
+ if (!list_empty(&prange->child_list)) {
+ pr_debug("range split by unmap in parallel, validate again\n");
+ r = -EAGAIN;
+ goto unlock_out;
+ }
+
+ r = svm_range_map_to_gpus(prange, offset, npages, readonly,
+ ctx.bitmap, wait);
unlock_out:
- svm_range_unlock(prange);
+ svm_range_unlock(prange);
+
+ addr = next;
+ }
+
+ if (addr == end)
+ prange->validated_once = true;
+
unreserve_out:
svm_range_unreserve_bos(&ctx);
@@ -2400,9 +2438,29 @@ svm_range_count_fault(struct amdgpu_device *adev, struct kfd_process *p,
WRITE_ONCE(pdd->faults, pdd->faults + 1);
}
+static bool
+svm_fault_allowed(struct mm_struct *mm, uint64_t addr, bool write_fault)
+{
+ unsigned long requested = VM_READ;
+ struct vm_area_struct *vma;
+
+ if (write_fault)
+ requested |= VM_WRITE;
+
+ vma = find_vma(mm, addr << PAGE_SHIFT);
+ if (!vma || (addr << PAGE_SHIFT) < vma->vm_start) {
+ pr_debug("address 0x%llx VMA is removed\n", addr);
+ return true;
+ }
+
+ pr_debug("requested 0x%lx, vma permission flags 0x%lx\n", requested,
+ vma->vm_flags);
+ return (vma->vm_flags & requested) == requested;
+}
+
int
svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
- uint64_t addr)
+ uint64_t addr, bool write_fault)
{
struct mm_struct *mm = NULL;
struct svm_range_list *svms;
@@ -2484,6 +2542,13 @@ retry_write_locked:
goto out_unlock_range;
}
+ if (!svm_fault_allowed(mm, addr, write_fault)) {
+ pr_debug("fault addr 0x%llx no %s permission\n", addr,
+ write_fault ? "write" : "read");
+ r = -EPERM;
+ goto out_unlock_range;
+ }
+
best_loc = svm_range_best_restore_location(prange, adev, &gpuidx);
if (best_loc == -1) {
pr_debug("svms %p failed get best restore loc [0x%lx 0x%lx]\n",
@@ -2675,22 +2740,26 @@ svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size,
return 0;
}
-/* svm_range_best_prefetch_location - decide the best prefetch location
+/**
+ * svm_range_best_prefetch_location - decide the best prefetch location
* @prange: svm range structure
*
* For xnack off:
- * If range map to single GPU, the best acutal location is prefetch loc, which
+ * If range map to single GPU, the best prefetch location is prefetch_loc, which
* can be CPU or GPU.
*
- * If range map to multiple GPUs, only if mGPU connection on xgmi same hive,
- * the best actual location could be prefetch_loc GPU. If mGPU connection on
- * PCIe, the best actual location is always CPU, because GPU cannot access vram
- * of other GPUs, assuming PCIe small bar (large bar support is not upstream).
+ * If range is ACCESS or ACCESS_IN_PLACE by mGPUs, only if mGPU connection on
+ * XGMI same hive, the best prefetch location is prefetch_loc GPU, othervise
+ * the best prefetch location is always CPU, because GPU can not have coherent
+ * mapping VRAM of other GPUs even with large-BAR PCIe connection.
*
* For xnack on:
- * The best actual location is prefetch location. If mGPU connection on xgmi
- * same hive, range map to multiple GPUs. Otherwise, the range only map to
- * actual location GPU. Other GPU access vm fault will trigger migration.
+ * If range is not ACCESS_IN_PLACE by mGPUs, the best prefetch location is
+ * prefetch_loc, other GPU access will generate vm fault and trigger migration.
+ *
+ * If range is ACCESS_IN_PLACE by mGPUs, only if mGPU connection on XGMI same
+ * hive, the best prefetch location is prefetch_loc GPU, otherwise the best
+ * prefetch location is always CPU.
*
* Context: Process context
*
@@ -2710,11 +2779,6 @@ svm_range_best_prefetch_location(struct svm_range *prange)
p = container_of(prange->svms, struct kfd_process, svms);
- /* xnack on */
- if (p->xnack_enabled)
- goto out;
-
- /* xnack off */
if (!best_loc || best_loc == KFD_IOCTL_SVM_LOCATION_UNDEFINED)
goto out;
@@ -2724,8 +2788,12 @@ svm_range_best_prefetch_location(struct svm_range *prange)
best_loc = 0;
goto out;
}
- bitmap_or(bitmap, prange->bitmap_access, prange->bitmap_aip,
- MAX_GPU_INSTANCE);
+
+ if (p->xnack_enabled)
+ bitmap_copy(bitmap, prange->bitmap_aip, MAX_GPU_INSTANCE);
+ else
+ bitmap_or(bitmap, prange->bitmap_access, prange->bitmap_aip,
+ MAX_GPU_INSTANCE);
for_each_set_bit(gpuidx, bitmap, MAX_GPU_INSTANCE) {
pdd = kfd_process_device_from_gpuidx(p, gpuidx);
@@ -3019,7 +3087,8 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
struct svm_range *prange;
uint32_t prefetch_loc = KFD_IOCTL_SVM_LOCATION_UNDEFINED;
uint32_t location = KFD_IOCTL_SVM_LOCATION_UNDEFINED;
- uint32_t flags = 0xffffffff;
+ uint32_t flags_and = 0xffffffff;
+ uint32_t flags_or = 0;
int gpuidx;
uint32_t i;
@@ -3054,12 +3123,12 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
get_accessible = true;
break;
case KFD_IOCTL_SVM_ATTR_SET_FLAGS:
+ case KFD_IOCTL_SVM_ATTR_CLR_FLAGS:
get_flags = true;
break;
case KFD_IOCTL_SVM_ATTR_GRANULARITY:
get_granularity = true;
break;
- case KFD_IOCTL_SVM_ATTR_CLR_FLAGS:
case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE:
case KFD_IOCTL_SVM_ATTR_NO_ACCESS:
fallthrough;
@@ -3077,7 +3146,8 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
if (!node) {
pr_debug("range attrs not found return default values\n");
svm_range_set_default_attributes(&location, &prefetch_loc,
- &granularity, &flags);
+ &granularity, &flags_and);
+ flags_or = flags_and;
if (p->xnack_enabled)
bitmap_copy(bitmap_access, svms->bitmap_supported,
MAX_GPU_INSTANCE);
@@ -3123,8 +3193,10 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
bitmap_and(bitmap_aip, bitmap_aip,
prange->bitmap_aip, MAX_GPU_INSTANCE);
}
- if (get_flags)
- flags &= prange->flags;
+ if (get_flags) {
+ flags_and &= prange->flags;
+ flags_or |= prange->flags;
+ }
if (get_granularity && prange->granularity < granularity)
granularity = prange->granularity;
@@ -3158,7 +3230,10 @@ fill_values:
attrs[i].type = KFD_IOCTL_SVM_ATTR_NO_ACCESS;
break;
case KFD_IOCTL_SVM_ATTR_SET_FLAGS:
- attrs[i].value = flags;
+ attrs[i].value = flags_and;
+ break;
+ case KFD_IOCTL_SVM_ATTR_CLR_FLAGS:
+ attrs[i].value = ~flags_or;
break;
case KFD_IOCTL_SVM_ATTR_GRANULARITY:
attrs[i].value = (uint32_t)granularity;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 3fc1fd8b4fbc..c6ec55354c7b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -175,7 +175,7 @@ int svm_range_split_by_granularity(struct kfd_process *p, struct mm_struct *mm,
unsigned long addr, struct svm_range *parent,
struct svm_range *prange);
int svm_range_restore_pages(struct amdgpu_device *adev,
- unsigned int pasid, uint64_t addr);
+ unsigned int pasid, uint64_t addr, bool write_fault);
int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence);
void svm_range_add_list_work(struct svm_range_list *svms,
struct svm_range *prange, struct mm_struct *mm,
@@ -209,7 +209,8 @@ static inline void svm_range_list_fini(struct kfd_process *p)
}
static inline int svm_range_restore_pages(struct amdgpu_device *adev,
- unsigned int pasid, uint64_t addr)
+ unsigned int pasid, uint64_t addr,
+ bool write_fault)
{
return -EFAULT;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index b1ce072aa20b..98cca5f2b27f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -478,6 +478,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
dev->node_props.simd_per_cu);
sysfs_show_32bit_prop(buffer, offs, "max_slots_scratch_cu",
dev->node_props.max_slots_scratch_cu);
+ sysfs_show_32bit_prop(buffer, offs, "gfx_target_version",
+ dev->node_props.gfx_target_version);
sysfs_show_32bit_prop(buffer, offs, "vendor_id",
dev->node_props.vendor_id);
sysfs_show_32bit_prop(buffer, offs, "device_id",
@@ -1360,6 +1362,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
dev->node_props.simd_arrays_per_engine =
cu_info.num_shader_arrays_per_engine;
+ dev->node_props.gfx_target_version = gpu->device_info->gfx_target_version;
dev->node_props.vendor_id = gpu->pdev->vendor;
dev->node_props.device_id = gpu->pdev->device;
dev->node_props.capability |=
@@ -1424,6 +1427,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_YELLOW_CARP:
+ case CHIP_CYAN_SKILLFISH:
dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 <<
HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) &
HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK);
@@ -1630,7 +1634,7 @@ int kfd_debugfs_rls_by_device(struct seq_file *m, void *data)
}
seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id);
- r = pm_debugfs_runlist(m, &dev->gpu->dqm->packets);
+ r = pm_debugfs_runlist(m, &dev->gpu->dqm->packet_mgr);
if (r)
break;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
index 8b48c6692007..a8db017c9b8e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
@@ -78,6 +78,7 @@ struct kfd_node_properties {
uint32_t simd_per_cu;
uint32_t max_slots_scratch_cu;
uint32_t engine_id;
+ uint32_t gfx_target_version;
uint32_t vendor_id;
uint32_t device_id;
uint32_t location_id;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index 91fb72c96545..718e123a3230 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -27,6 +27,10 @@
AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o
+ifdef CONFIG_DRM_AMD_DC_DCN
+AMDGPUDM += dc_fpu.o
+endif
+
ifneq ($(CONFIG_DRM_AMD_DC),)
AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o amdgpu_dm_psr.o
endif
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 afa96c8f721b..816723691d51 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -618,6 +618,7 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params)
}
#endif
+#define DMUB_TRACE_MAX_READ 64
/**
* dm_dmub_outbox1_low_irq() - Handles Outbox interrupt
* @interrupt_params: used for determining the Outbox instance
@@ -625,7 +626,6 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params)
* Handles the Outbox Interrupt
* event handler.
*/
-#define DMUB_TRACE_MAX_READ 64
static void dm_dmub_outbox1_low_irq(void *interrupt_params)
{
struct dmub_notification notify;
@@ -1044,10 +1044,10 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
}
#endif
#if defined(CONFIG_DRM_AMD_DC_DCN)
-static void event_mall_stutter(struct work_struct *work)
+static void vblank_control_worker(struct work_struct *work)
{
-
- struct vblank_workqueue *vblank_work = container_of(work, struct vblank_workqueue, mall_work);
+ struct vblank_control_work *vblank_work =
+ container_of(work, struct vblank_control_work, work);
struct amdgpu_display_manager *dm = vblank_work->dm;
mutex_lock(&dm->dc_lock);
@@ -1061,27 +1061,25 @@ static void event_mall_stutter(struct work_struct *work)
DRM_DEBUG_KMS("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0);
- mutex_unlock(&dm->dc_lock);
-}
-
-static struct vblank_workqueue *vblank_create_workqueue(struct amdgpu_device *adev, struct dc *dc)
-{
-
- int max_caps = dc->caps.max_links;
- struct vblank_workqueue *vblank_work;
- int i = 0;
-
- vblank_work = kcalloc(max_caps, sizeof(*vblank_work), GFP_KERNEL);
- if (ZERO_OR_NULL_PTR(vblank_work)) {
- kfree(vblank_work);
- return NULL;
+ /* Control PSR based on vblank requirements from OS */
+ if (vblank_work->stream && vblank_work->stream->link) {
+ if (vblank_work->enable) {
+ if (vblank_work->stream->link->psr_settings.psr_allow_active)
+ amdgpu_dm_psr_disable(vblank_work->stream);
+ } else if (vblank_work->stream->link->psr_settings.psr_feature_enabled &&
+ !vblank_work->stream->link->psr_settings.psr_allow_active &&
+ vblank_work->acrtc->dm_irq_params.allow_psr_entry) {
+ amdgpu_dm_psr_enable(vblank_work->stream);
+ }
}
- for (i = 0; i < max_caps; i++)
- INIT_WORK(&vblank_work[i].mall_work, event_mall_stutter);
+ mutex_unlock(&dm->dc_lock);
+
+ dc_stream_release(vblank_work->stream);
- return vblank_work;
+ kfree(vblank_work);
}
+
#endif
static int amdgpu_dm_init(struct amdgpu_device *adev)
{
@@ -1224,12 +1222,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (adev->dm.dc->caps.max_links > 0) {
- adev->dm.vblank_workqueue = vblank_create_workqueue(adev, adev->dm.dc);
-
- if (!adev->dm.vblank_workqueue)
+ adev->dm.vblank_control_workqueue =
+ create_singlethread_workqueue("dm_vblank_control_workqueue");
+ if (!adev->dm.vblank_control_workqueue)
DRM_ERROR("amdgpu: failed to initialize vblank_workqueue.\n");
- else
- DRM_DEBUG_DRIVER("amdgpu: vblank_workqueue init done %p.\n", adev->dm.vblank_workqueue);
}
#endif
@@ -1302,6 +1298,13 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
{
int i;
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+ if (adev->dm.vblank_control_workqueue) {
+ destroy_workqueue(adev->dm.vblank_control_workqueue);
+ adev->dm.vblank_control_workqueue = NULL;
+ }
+#endif
+
for (i = 0; i < adev->dm.display_indexes_num; i++) {
drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
}
@@ -1325,14 +1328,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
dc_deinit_callbacks(adev->dm.dc);
#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN)
- if (adev->dm.vblank_workqueue) {
- adev->dm.vblank_workqueue->dm = NULL;
- kfree(adev->dm.vblank_workqueue);
- adev->dm.vblank_workqueue = NULL;
- }
-#endif
-
dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv);
if (dc_enable_dmub_notifications(adev->dm.dc)) {
@@ -2412,6 +2407,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
static const u8 pre_computed_values[] = {
50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
+ int i;
if (!aconnector || !aconnector->dc_link)
return;
@@ -2423,7 +2419,13 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
conn_base = &aconnector->base;
adev = drm_to_adev(conn_base->dev);
dm = &adev->dm;
- caps = &dm->backlight_caps;
+ for (i = 0; i < dm->num_of_edps; i++) {
+ if (link == dm->backlight_link[i])
+ break;
+ }
+ if (i >= dm->num_of_edps)
+ return;
+ caps = &dm->backlight_caps[i];
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
caps->aux_support = false;
max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll;
@@ -3423,35 +3425,36 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
-static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)
+static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
+ int bl_idx)
{
#if defined(CONFIG_ACPI)
struct amdgpu_dm_backlight_caps caps;
memset(&caps, 0, sizeof(caps));
- if (dm->backlight_caps.caps_valid)
+ if (dm->backlight_caps[bl_idx].caps_valid)
return;
amdgpu_acpi_get_backlight_caps(&caps);
if (caps.caps_valid) {
- dm->backlight_caps.caps_valid = true;
+ dm->backlight_caps[bl_idx].caps_valid = true;
if (caps.aux_support)
return;
- dm->backlight_caps.min_input_signal = caps.min_input_signal;
- dm->backlight_caps.max_input_signal = caps.max_input_signal;
+ dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal;
+ dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal;
} else {
- dm->backlight_caps.min_input_signal =
+ dm->backlight_caps[bl_idx].min_input_signal =
AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
- dm->backlight_caps.max_input_signal =
+ dm->backlight_caps[bl_idx].max_input_signal =
AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
}
#else
- if (dm->backlight_caps.aux_support)
+ if (dm->backlight_caps[bl_idx].aux_support)
return;
- dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
- dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
+ dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
+ dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
#endif
}
@@ -3502,41 +3505,31 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap
}
static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
+ int bl_idx,
u32 user_brightness)
{
struct amdgpu_dm_backlight_caps caps;
- struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP];
- u32 brightness[AMDGPU_DM_MAX_NUM_EDP];
+ struct dc_link *link;
+ u32 brightness;
bool rc;
- int i;
- amdgpu_dm_update_backlight_caps(dm);
- caps = dm->backlight_caps;
+ amdgpu_dm_update_backlight_caps(dm, bl_idx);
+ caps = dm->backlight_caps[bl_idx];
- for (i = 0; i < dm->num_of_edps; i++) {
- dm->brightness[i] = user_brightness;
- brightness[i] = convert_brightness_from_user(&caps, dm->brightness[i]);
- link[i] = (struct dc_link *)dm->backlight_link[i];
- }
+ dm->brightness[bl_idx] = user_brightness;
+ brightness = convert_brightness_from_user(&caps, dm->brightness[bl_idx]);
+ link = (struct dc_link *)dm->backlight_link[bl_idx];
/* Change brightness based on AUX property */
if (caps.aux_support) {
- for (i = 0; i < dm->num_of_edps; i++) {
- rc = dc_link_set_backlight_level_nits(link[i], true, brightness[i],
- AUX_BL_DEFAULT_TRANSITION_TIME_MS);
- if (!rc) {
- DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", i);
- break;
- }
- }
+ rc = dc_link_set_backlight_level_nits(link, true, brightness,
+ AUX_BL_DEFAULT_TRANSITION_TIME_MS);
+ if (!rc)
+ DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", bl_idx);
} else {
- for (i = 0; i < dm->num_of_edps; i++) {
- rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness[i], 0);
- if (!rc) {
- DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", i);
- break;
- }
- }
+ rc = dc_link_set_backlight_level(link, brightness, 0);
+ if (!rc)
+ DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx);
}
return rc ? 0 : 1;
@@ -3545,33 +3538,41 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
{
struct amdgpu_display_manager *dm = bl_get_data(bd);
+ int i;
- amdgpu_dm_backlight_set_level(dm, bd->props.brightness);
+ for (i = 0; i < dm->num_of_edps; i++) {
+ if (bd == dm->backlight_dev[i])
+ break;
+ }
+ if (i >= AMDGPU_DM_MAX_NUM_EDP)
+ i = 0;
+ amdgpu_dm_backlight_set_level(dm, i, bd->props.brightness);
return 0;
}
-static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
+static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm,
+ int bl_idx)
{
struct amdgpu_dm_backlight_caps caps;
+ struct dc_link *link = (struct dc_link *)dm->backlight_link[bl_idx];
- amdgpu_dm_update_backlight_caps(dm);
- caps = dm->backlight_caps;
+ amdgpu_dm_update_backlight_caps(dm, bl_idx);
+ caps = dm->backlight_caps[bl_idx];
if (caps.aux_support) {
- struct dc_link *link = (struct dc_link *)dm->backlight_link[0];
u32 avg, peak;
bool rc;
rc = dc_link_get_backlight_level_nits(link, &avg, &peak);
if (!rc)
- return dm->brightness[0];
+ return dm->brightness[bl_idx];
return convert_brightness_to_user(&caps, avg);
} else {
- int ret = dc_link_get_backlight_level(dm->backlight_link[0]);
+ int ret = dc_link_get_backlight_level(link);
if (ret == DC_ERROR_UNEXPECTED)
- return dm->brightness[0];
+ return dm->brightness[bl_idx];
return convert_brightness_to_user(&caps, ret);
}
}
@@ -3579,8 +3580,15 @@ static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
{
struct amdgpu_display_manager *dm = bl_get_data(bd);
+ int i;
- return amdgpu_dm_backlight_get_level(dm);
+ for (i = 0; i < dm->num_of_edps; i++) {
+ if (bd == dm->backlight_dev[i])
+ break;
+ }
+ if (i >= AMDGPU_DM_MAX_NUM_EDP)
+ i = 0;
+ return amdgpu_dm_backlight_get_level(dm, i);
}
static const struct backlight_ops amdgpu_dm_backlight_ops = {
@@ -3594,31 +3602,28 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
{
char bl_name[16];
struct backlight_properties props = { 0 };
- int i;
- amdgpu_dm_update_backlight_caps(dm);
- for (i = 0; i < dm->num_of_edps; i++)
- dm->brightness[i] = AMDGPU_MAX_BL_LEVEL;
+ amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps);
+ dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL;
props.max_brightness = AMDGPU_MAX_BL_LEVEL;
props.brightness = AMDGPU_MAX_BL_LEVEL;
props.type = BACKLIGHT_RAW;
snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
- adev_to_drm(dm->adev)->primary->index);
+ adev_to_drm(dm->adev)->primary->index + dm->num_of_edps);
- dm->backlight_dev = backlight_device_register(bl_name,
- adev_to_drm(dm->adev)->dev,
- dm,
- &amdgpu_dm_backlight_ops,
- &props);
+ dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name,
+ adev_to_drm(dm->adev)->dev,
+ dm,
+ &amdgpu_dm_backlight_ops,
+ &props);
- if (IS_ERR(dm->backlight_dev))
+ if (IS_ERR(dm->backlight_dev[dm->num_of_edps]))
DRM_ERROR("DM: Backlight registration failed!\n");
else
DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name);
}
-
#endif
static int initialize_plane(struct amdgpu_display_manager *dm,
@@ -3675,10 +3680,10 @@ static void register_backlight_device(struct amdgpu_display_manager *dm,
* DM initialization because not having a backlight control
* is better then a black screen.
*/
- if (!dm->backlight_dev)
+ if (!dm->backlight_dev[dm->num_of_edps])
amdgpu_dm_register_backlight_device(dm);
- if (dm->backlight_dev) {
+ if (dm->backlight_dev[dm->num_of_edps]) {
dm->backlight_link[dm->num_of_edps] = link;
dm->num_of_edps++;
}
@@ -4747,7 +4752,7 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
const bool force_disable_dcc)
{
const uint64_t modifier = afb->base.modifier;
- int ret;
+ int ret = 0;
fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier);
@@ -4765,9 +4770,9 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
if (ret)
- return ret;
+ drm_dbg_kms(adev_to_drm(adev), "validate_dcc: returned error: %d\n", ret);
- return 0;
+ return ret;
}
static int
@@ -5994,7 +5999,7 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct amdgpu_display_manager *dm = &adev->dm;
- unsigned long flags;
+ struct vblank_control_work *work;
#endif
int rc = 0;
@@ -6019,12 +6024,21 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
return 0;
#if defined(CONFIG_DRM_AMD_DC_DCN)
- spin_lock_irqsave(&dm->vblank_lock, flags);
- dm->vblank_workqueue->dm = dm;
- dm->vblank_workqueue->otg_inst = acrtc->otg_inst;
- dm->vblank_workqueue->enable = enable;
- spin_unlock_irqrestore(&dm->vblank_lock, flags);
- schedule_work(&dm->vblank_workqueue->mall_work);
+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
+ if (!work)
+ return -ENOMEM;
+
+ INIT_WORK(&work->work, vblank_control_worker);
+ work->dm = dm;
+ work->acrtc = acrtc;
+ work->enable = enable;
+
+ if (acrtc_state->stream) {
+ dc_stream_retain(acrtc_state->stream);
+ work->stream = acrtc_state->stream;
+ }
+
+ queue_work(dm->vblank_control_workqueue, &work->work);
#endif
return 0;
@@ -6198,6 +6212,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
const struct dc_link *link = aconnector->dc_link;
struct amdgpu_device *adev = drm_to_adev(connector->dev);
struct amdgpu_display_manager *dm = &adev->dm;
+ int i;
/*
* Call only if mst_mgr was iniitalized before since it's not done
@@ -6208,12 +6223,11 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
-
- if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) &&
- link->type != dc_connection_none &&
- dm->backlight_dev) {
- backlight_device_unregister(dm->backlight_dev);
- dm->backlight_dev = NULL;
+ for (i = 0; i < dm->num_of_edps; i++) {
+ if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) {
+ backlight_device_unregister(dm->backlight_dev[i]);
+ dm->backlight_dev[i] = NULL;
+ }
}
#endif
@@ -7570,8 +7584,10 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
* 60 - Commonly used
* 48,72,96 - Multiples of 24
*/
- const uint32_t common_rates[] = { 23976, 24000, 25000, 29970, 30000,
- 48000, 50000, 60000, 72000, 96000 };
+ static const uint32_t common_rates[] = {
+ 23976, 24000, 25000, 29970, 30000,
+ 48000, 50000, 60000, 72000, 96000
+ };
/*
* Find mode with highest refresh rate with the same resolution
@@ -8627,6 +8643,14 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
/* Update the planes if changed or disable if we don't have any. */
if ((planes_count || acrtc_state->active_planes == 0) &&
acrtc_state->stream) {
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+ /*
+ * If PSR or idle optimizations are enabled then flush out
+ * any pending work before hardware programming.
+ */
+ flush_workqueue(dm->vblank_control_workqueue);
+#endif
+
bundle->stream_update.stream = acrtc_state->stream;
if (new_pcrtc_state->mode_changed) {
bundle->stream_update.src = acrtc_state->stream->src;
@@ -8695,16 +8719,20 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED &&
!acrtc_state->stream->link->psr_settings.psr_feature_enabled)
amdgpu_dm_link_setup_psr(acrtc_state->stream);
- else if ((acrtc_state->update_type == UPDATE_TYPE_FAST) &&
- acrtc_state->stream->link->psr_settings.psr_feature_enabled &&
- !acrtc_state->stream->link->psr_settings.psr_allow_active) {
- struct amdgpu_dm_connector *aconn = (struct amdgpu_dm_connector *)
- acrtc_state->stream->dm_stream_context;
+
+ /* Decrement skip count when PSR is enabled and we're doing fast updates. */
+ if (acrtc_state->update_type == UPDATE_TYPE_FAST &&
+ acrtc_state->stream->link->psr_settings.psr_feature_enabled) {
+ struct amdgpu_dm_connector *aconn =
+ (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context;
if (aconn->psr_skip_count > 0)
aconn->psr_skip_count--;
- else
- amdgpu_dm_psr_enable(acrtc_state->stream);
+
+ /* Allow PSR when skip count is 0. */
+ acrtc_attach->dm_irq_params.allow_psr_entry = !aconn->psr_skip_count;
+ } else {
+ acrtc_attach->dm_irq_params.allow_psr_entry = false;
}
mutex_unlock(&dm->dc_lock);
@@ -8953,8 +8981,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
if (dc_state) {
/* if there mode set or reset, disable eDP PSR */
- if (mode_set_reset_required)
+ if (mode_set_reset_required) {
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+ flush_workqueue(dm->vblank_control_workqueue);
+#endif
amdgpu_dm_psr_disable_all(dm);
+ }
dm_enable_per_frame_crtc_master_sync(dc_state);
mutex_lock(&dm->dc_lock);
@@ -9191,8 +9223,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
/* restore the backlight level */
- if (dm->backlight_dev && (amdgpu_dm_backlight_get_level(dm) != dm->brightness[0]))
- amdgpu_dm_backlight_set_level(dm, dm->brightness[0]);
+ for (i = 0; i < dm->num_of_edps; i++) {
+ if (dm->backlight_dev[i] &&
+ (amdgpu_dm_backlight_get_level(dm, i) != dm->brightness[i]))
+ amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
+ }
#endif
/*
* send vblank event on all events not handled in flip and
@@ -10554,13 +10589,68 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc,
return capable;
}
-static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
+static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
+ unsigned int offset,
+ unsigned int total_length,
+ uint8_t *data,
+ unsigned int length,
+ struct amdgpu_hdmi_vsdb_info *vsdb)
+{
+ bool res;
+ union dmub_rb_cmd cmd;
+ struct dmub_cmd_send_edid_cea *input;
+ struct dmub_cmd_edid_cea_output *output;
+
+ if (length > DMUB_EDID_CEA_DATA_CHUNK_BYTES)
+ return false;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ input = &cmd.edid_cea.data.input;
+
+ cmd.edid_cea.header.type = DMUB_CMD__EDID_CEA;
+ cmd.edid_cea.header.sub_type = 0;
+ cmd.edid_cea.header.payload_bytes =
+ sizeof(cmd.edid_cea) - sizeof(cmd.edid_cea.header);
+ input->offset = offset;
+ input->length = length;
+ input->total_length = total_length;
+ memcpy(input->payload, data, length);
+
+ res = dc_dmub_srv_cmd_with_reply_data(dm->dc->ctx->dmub_srv, &cmd);
+ if (!res) {
+ DRM_ERROR("EDID CEA parser failed\n");
+ return false;
+ }
+
+ output = &cmd.edid_cea.data.output;
+
+ if (output->type == DMUB_CMD__EDID_CEA_ACK) {
+ if (!output->ack.success) {
+ DRM_ERROR("EDID CEA ack failed at offset %d\n",
+ output->ack.offset);
+ }
+ } else if (output->type == DMUB_CMD__EDID_CEA_AMD_VSDB) {
+ if (!output->amd_vsdb.vsdb_found)
+ return false;
+
+ vsdb->freesync_supported = output->amd_vsdb.freesync_supported;
+ vsdb->amd_vsdb_version = output->amd_vsdb.amd_vsdb_version;
+ vsdb->min_refresh_rate_hz = output->amd_vsdb.min_frame_rate;
+ vsdb->max_refresh_rate_hz = output->amd_vsdb.max_frame_rate;
+ } else {
+ DRM_WARN("Unknown EDID CEA parser results\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
uint8_t *edid_ext, int len,
struct amdgpu_hdmi_vsdb_info *vsdb_info)
{
int i;
- struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
- struct dc *dc = adev->dm.dc;
/* send extension block to DMCU for parsing */
for (i = 0; i < len; i += 8) {
@@ -10568,14 +10658,14 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
int offset;
/* send 8 bytes a time */
- if (!dc_edid_parser_send_cea(dc, i, len, &edid_ext[i], 8))
+ if (!dc_edid_parser_send_cea(dm->dc, i, len, &edid_ext[i], 8))
return false;
if (i+8 == len) {
/* EDID block sent completed, expect result */
int version, min_rate, max_rate;
- res = dc_edid_parser_recv_amd_vsdb(dc, &version, &min_rate, &max_rate);
+ res = dc_edid_parser_recv_amd_vsdb(dm->dc, &version, &min_rate, &max_rate);
if (res) {
/* amd vsdb found */
vsdb_info->freesync_supported = 1;
@@ -10589,7 +10679,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
}
/* check for ack*/
- res = dc_edid_parser_recv_cea_ack(dc, &offset);
+ res = dc_edid_parser_recv_cea_ack(dm->dc, &offset);
if (!res)
return false;
}
@@ -10597,6 +10687,34 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
return false;
}
+static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
+ uint8_t *edid_ext, int len,
+ struct amdgpu_hdmi_vsdb_info *vsdb_info)
+{
+ int i;
+
+ /* send extension block to DMCU for parsing */
+ for (i = 0; i < len; i += 8) {
+ /* send 8 bytes a time */
+ if (!dm_edid_parser_send_cea(dm, i, len, &edid_ext[i], 8, vsdb_info))
+ return false;
+ }
+
+ return vsdb_info->freesync_supported;
+}
+
+static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
+ uint8_t *edid_ext, int len,
+ struct amdgpu_hdmi_vsdb_info *vsdb_info)
+{
+ struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
+
+ if (adev->dm.dmub_srv)
+ return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
+ else
+ return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+}
+
static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
{
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 9522d4ca299e..d1d353a7c77d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -60,6 +60,7 @@ enum aux_return_code_type;
/* Forward declarations */
struct amdgpu_device;
+struct amdgpu_crtc;
struct drm_device;
struct dc;
struct amdgpu_bo;
@@ -86,16 +87,18 @@ struct dm_compressor_info {
};
/**
- * struct vblank_workqueue - Works to be executed in a separate thread during vblank
- * @mall_work: work for mall stutter
+ * struct vblank_control_work - Work data for vblank control
+ * @work: Kernel work data for the work event
* @dm: amdgpu display manager device
- * @otg_inst: otg instance of which vblank is being set
- * @enable: true if enable vblank
+ * @acrtc: amdgpu CRTC instance for which the event has occurred
+ * @stream: DC stream for which the event has occurred
+ * @enable: true if enabling vblank
*/
-struct vblank_workqueue {
- struct work_struct mall_work;
+struct vblank_control_work {
+ struct work_struct work;
struct amdgpu_display_manager *dm;
- int otg_inst;
+ struct amdgpu_crtc *acrtc;
+ struct dc_stream_state *stream;
bool enable;
};
@@ -365,13 +368,13 @@ struct amdgpu_display_manager {
spinlock_t irq_handler_list_table_lock;
- struct backlight_device *backlight_dev;
+ struct backlight_device *backlight_dev[AMDGPU_DM_MAX_NUM_EDP];
const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP];
uint8_t num_of_edps;
- struct amdgpu_dm_backlight_caps backlight_caps;
+ struct amdgpu_dm_backlight_caps backlight_caps[AMDGPU_DM_MAX_NUM_EDP];
struct mod_freesync *freesync_module;
#ifdef CONFIG_DRM_AMD_DC_HDCP
@@ -380,11 +383,11 @@ struct amdgpu_display_manager {
#if defined(CONFIG_DRM_AMD_DC_DCN)
/**
- * @vblank_workqueue:
+ * @vblank_control_workqueue:
*
- * amdgpu workqueue during vblank
+ * Deferred work for vblank control events.
*/
- struct vblank_workqueue *vblank_workqueue;
+ struct workqueue_struct *vblank_control_workqueue;
#endif
struct drm_atomic_state *cached_state;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index f1145086a468..87daa78a32b8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -197,29 +197,29 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
rd_buf_ptr = rd_buf;
- str_len = strlen("Current: %d %d %d ");
- snprintf(rd_buf_ptr, str_len, "Current: %d %d %d ",
+ str_len = strlen("Current: %d 0x%x %d ");
+ snprintf(rd_buf_ptr, str_len, "Current: %d 0x%x %d ",
link->cur_link_settings.lane_count,
link->cur_link_settings.link_rate,
link->cur_link_settings.link_spread);
rd_buf_ptr += str_len;
- str_len = strlen("Verified: %d %d %d ");
- snprintf(rd_buf_ptr, str_len, "Verified: %d %d %d ",
+ str_len = strlen("Verified: %d 0x%x %d ");
+ snprintf(rd_buf_ptr, str_len, "Verified: %d 0x%x %d ",
link->verified_link_cap.lane_count,
link->verified_link_cap.link_rate,
link->verified_link_cap.link_spread);
rd_buf_ptr += str_len;
- str_len = strlen("Reported: %d %d %d ");
- snprintf(rd_buf_ptr, str_len, "Reported: %d %d %d ",
+ str_len = strlen("Reported: %d 0x%x %d ");
+ snprintf(rd_buf_ptr, str_len, "Reported: %d 0x%x %d ",
link->reported_link_cap.lane_count,
link->reported_link_cap.link_rate,
link->reported_link_cap.link_spread);
rd_buf_ptr += str_len;
- str_len = strlen("Preferred: %d %d %d ");
- snprintf(rd_buf_ptr, str_len, "Preferred: %d %d %d\n",
+ str_len = strlen("Preferred: %d 0x%x %d ");
+ snprintf(rd_buf_ptr, str_len, "Preferred: %d 0x%x %d\n",
link->preferred_link_setting.lane_count,
link->preferred_link_setting.link_rate,
link->preferred_link_setting.link_spread);
@@ -377,7 +377,7 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf,
if (!rd_buf)
return -EINVAL;
- snprintf(rd_buf, rd_buf_size, " %d %d %d ",
+ snprintf(rd_buf, rd_buf_size, " %d %d %d\n",
link->cur_lane_setting.VOLTAGE_SWING,
link->cur_lane_setting.PRE_EMPHASIS,
link->cur_lane_setting.POST_CURSOR2);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
index e63c6885c757..c5f1dc3b5961 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
@@ -79,12 +79,12 @@ static uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint
struct ta_hdcp_shared_memory *hdcp_cmd;
- if (!psp->hdcp_context.hdcp_initialized) {
+ if (!psp->hdcp_context.context.initialized) {
DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized.");
return NULL;
}
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP_GET_SRM;
@@ -105,12 +105,12 @@ static int psp_set_srm(struct psp_context *psp, uint8_t *srm, uint32_t srm_size,
struct ta_hdcp_shared_memory *hdcp_cmd;
- if (!psp->hdcp_context.hdcp_initialized) {
+ if (!psp->hdcp_context.context.initialized) {
DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized.");
return -EINVAL;
}
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
memcpy(hdcp_cmd->in_msg.hdcp_set_srm.srm_buf, srm, srm_size);
@@ -414,12 +414,12 @@ static bool enable_assr(void *handle, struct dc_link *link)
struct ta_dtm_shared_memory *dtm_cmd;
bool res = true;
- if (!psp->dtm_context.dtm_initialized) {
+ if (!psp->dtm_context.context.initialized) {
DRM_INFO("Failed to enable ASSR, DTM TA is not initialized.");
return false;
}
- dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
+ dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.context.mem_context.shared_buf;
mutex_lock(&psp->dtm_context.mutex);
memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory));
@@ -655,10 +655,8 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate);
hdcp_work[i].hdcp.config.psp.handle = &adev->psp;
- if (dc->ctx->dce_version == DCN_VERSION_3_1) {
+ if (dc->ctx->dce_version == DCN_VERSION_3_1)
hdcp_work[i].hdcp.config.psp.caps.dtm_v3_supported = 1;
- hdcp_work[i].hdcp.config.psp.caps.opm_state_query_supported = false;
- }
hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i);
hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c;
hdcp_work[i].hdcp.config.ddc.funcs.read_i2c = lp_read_i2c;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h
index f3b93ba69a27..79b5f9999fec 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h
@@ -33,6 +33,7 @@ struct dm_irq_params {
struct mod_vrr_params vrr_params;
struct dc_stream_state *stream;
int active_planes;
+ bool allow_psr_entry;
struct mod_freesync_config freesync_config;
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 5568d4e518e6..1bcba6943fd7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -213,6 +213,29 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
drm_connector_update_edid_property(
&aconnector->base,
NULL);
+
+ DRM_DEBUG_KMS("Can't get EDID of %s. Add default remote sink.", connector->name);
+ if (!aconnector->dc_sink) {
+ struct dc_sink *dc_sink;
+ struct dc_sink_init_data init_params = {
+ .link = aconnector->dc_link,
+ .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
+
+ dc_sink = dc_link_add_remote_sink(
+ aconnector->dc_link,
+ NULL,
+ 0,
+ &init_params);
+
+ if (!dc_sink) {
+ DRM_ERROR("Unable to add a remote sink\n");
+ return 0;
+ }
+
+ dc_sink->priv = aconnector;
+ aconnector->dc_sink = dc_sink;
+ }
+
return ret;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index 46a33f64cf8e..fdcaea22b456 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -637,6 +637,30 @@ TRACE_EVENT(amdgpu_refresh_rate_track,
__entry->refresh_rate_ns)
);
+TRACE_EVENT(dcn_fpu,
+ TP_PROTO(bool begin, const char *function, const int line, const int recursion_depth),
+ TP_ARGS(begin, function, line, recursion_depth),
+
+ TP_STRUCT__entry(
+ __field(bool, begin)
+ __field(const char *, function)
+ __field(int, line)
+ __field(int, recursion_depth)
+ ),
+ TP_fast_assign(
+ __entry->begin = begin;
+ __entry->function = function;
+ __entry->line = line;
+ __entry->recursion_depth = recursion_depth;
+ ),
+ TP_printk("%s: recursion_depth: %d: %s()+%d:",
+ __entry->begin ? "begin" : "end",
+ __entry->recursion_depth,
+ __entry->function,
+ __entry->line
+ )
+);
+
#endif /* _AMDGPU_DM_TRACE_H_ */
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
new file mode 100644
index 000000000000..c9f47d167472
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dc_trace.h"
+
+#if defined(CONFIG_X86)
+#include <asm/fpu/api.h>
+#elif defined(CONFIG_PPC64)
+#include <asm/switch_to.h>
+#include <asm/cputable.h>
+#endif
+
+/**
+ * DOC: DC FPU manipulation overview
+ *
+ * DC core uses FPU operations in multiple parts of the code, which requires a
+ * more specialized way to manage these areas' entrance. To fulfill this
+ * requirement, we created some wrapper functions that encapsulate
+ * kernel_fpu_begin/end to better fit our need in the display component. In
+ * summary, in this file, you can find functions related to FPU operation
+ * management.
+ */
+
+static DEFINE_PER_CPU(int, fpu_recursion_depth);
+
+/**
+ * dc_assert_fp_enabled - Check if FPU protection is enabled
+ *
+ * This function tells if the code is already under FPU protection or not. A
+ * function that works as an API for a set of FPU operations can use this
+ * function for checking if the caller invoked it after DC_FP_START(). For
+ * example, take a look at dcn2x.c file.
+ */
+inline void dc_assert_fp_enabled(void)
+{
+ int *pcpu, depth = 0;
+
+ pcpu = get_cpu_ptr(&fpu_recursion_depth);
+ depth = *pcpu;
+ put_cpu_ptr(&fpu_recursion_depth);
+
+ ASSERT(depth > 1);
+}
+
+/**
+ * dc_fpu_begin - Enables FPU protection
+ * @function_name: A string containing the function name for debug purposes
+ * (usually __func__)
+ *
+ * @line: A line number where DC_FP_START was invoked for debug purpose
+ * (usually __LINE__)
+ *
+ * This function is responsible for managing the use of kernel_fpu_begin() with
+ * the advantage of providing an event trace for debugging.
+ *
+ * Note: Do not call this function directly; always use DC_FP_START().
+ */
+void dc_fpu_begin(const char *function_name, const int line)
+{
+ int *pcpu;
+
+ pcpu = get_cpu_ptr(&fpu_recursion_depth);
+ *pcpu += 1;
+
+ if (*pcpu == 1) {
+#if defined(CONFIG_X86)
+ kernel_fpu_begin();
+#elif defined(CONFIG_PPC64)
+ if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
+ preempt_disable();
+ enable_kernel_vsx();
+ } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
+ preempt_disable();
+ enable_kernel_altivec();
+ } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
+ preempt_disable();
+ enable_kernel_fp();
+ }
+#endif
+ }
+
+ TRACE_DCN_FPU(true, function_name, line, *pcpu);
+ put_cpu_ptr(&fpu_recursion_depth);
+}
+
+/**
+ * dc_fpu_end - Disable FPU protection
+ * @function_name: A string containing the function name for debug purposes
+ * @line: A-line number where DC_FP_END was invoked for debug purpose
+ *
+ * This function is responsible for managing the use of kernel_fpu_end() with
+ * the advantage of providing an event trace for debugging.
+ *
+ * Note: Do not call this function directly; always use DC_FP_END().
+ */
+void dc_fpu_end(const char *function_name, const int line)
+{
+ int *pcpu;
+
+ pcpu = get_cpu_ptr(&fpu_recursion_depth);
+ *pcpu -= 1;
+ if (*pcpu <= 0) {
+#if defined(CONFIG_X86)
+ kernel_fpu_end();
+#elif defined(CONFIG_PPC64)
+ if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
+ disable_kernel_vsx();
+ preempt_enable();
+ } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
+ disable_kernel_altivec();
+ preempt_enable();
+ } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
+ disable_kernel_fp();
+ preempt_enable();
+ }
+#endif
+ }
+
+ TRACE_DCN_FPU(false, function_name, line, *pcpu);
+ put_cpu_ptr(&fpu_recursion_depth);
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
new file mode 100644
index 000000000000..b8275b397920
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_FPU_H__
+#define __DC_FPU_H__
+
+void dc_assert_fp_enabled(void);
+void dc_fpu_begin(const char *function_name, const int line);
+void dc_fpu_end(const char *function_name, const int line);
+
+#endif /* __DC_FPU_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
index e133edc587d3..76ec8ec92efd 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
@@ -264,9 +264,9 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base,
if (pp_smu->set_hard_min_fclk_by_freq &&
pp_smu->set_hard_min_dcfclk_by_freq &&
pp_smu->set_min_deep_sleep_dcfclk) {
- pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, new_clocks->fclk_khz / 1000);
- pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, new_clocks->dcfclk_khz / 1000);
- pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000);
+ pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->fclk_khz));
+ pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_khz));
+ pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_deep_sleep_khz));
}
}
@@ -284,9 +284,9 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base,
if (pp_smu->set_hard_min_fclk_by_freq &&
pp_smu->set_hard_min_dcfclk_by_freq &&
pp_smu->set_min_deep_sleep_dcfclk) {
- pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, new_clocks->fclk_khz / 1000);
- pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, new_clocks->dcfclk_khz / 1000);
- pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000);
+ pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->fclk_khz));
+ pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_khz));
+ pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_deep_sleep_khz));
}
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c
index dbc7cde00433..fe18bb9e19aa 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c
@@ -130,7 +130,7 @@ int rv1_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_di
actual_dispclk_set_mhz = rv1_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDispclkFreq,
- requested_dispclk_khz / 1000);
+ khz_to_mhz_ceil(requested_dispclk_khz));
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
@@ -150,7 +150,7 @@ int rv1_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
actual_dprefclk_set_mhz = rv1_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDprefclkFreq,
- clk_mgr->base.dprefclk_khz / 1000);
+ khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
/* TODO: add code for programing DP DTO, currently this is down by command table */
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
index a5331b96f551..0d01aa9f15a6 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
@@ -253,20 +253,20 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
if (pp_smu && pp_smu->set_hard_min_dcfclk_by_freq)
- pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.dcfclk_khz / 1000);
+ pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz));
}
if (should_set_clock(safe_to_lower,
new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
if (pp_smu && pp_smu->set_min_deep_sleep_dcfclk)
- pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, clk_mgr_base->clks.dcfclk_deep_sleep_khz / 1000);
+ pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz));
}
if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) {
clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz;
if (pp_smu && pp_smu->set_hard_min_socclk_by_freq)
- pp_smu->set_hard_min_socclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.socclk_khz / 1000);
+ pp_smu->set_hard_min_socclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.socclk_khz));
}
total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context);
@@ -281,7 +281,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) {
clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz;
if (pp_smu && pp_smu->set_hard_min_uclk_by_freq)
- pp_smu->set_hard_min_uclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.dramclk_khz / 1000);
+ pp_smu->set_hard_min_uclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
}
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
@@ -306,7 +306,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
clk_mgr_base->clks.disp_dpp_voltage_level_khz = new_clocks->disp_dpp_voltage_level_khz;
if (pp_smu && pp_smu->set_voltage_by_freq)
- pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, clk_mgr_base->clks.disp_dpp_voltage_level_khz / 1000);
+ pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.disp_dpp_voltage_level_khz));
}
if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) {
@@ -502,7 +502,7 @@ static void dcn2_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc
if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) {
clk_mgr_base->clks.phyclk_khz = max_phyclk_req;
- pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000);
+ pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PHYCLK, khz_to_mhz_ceil(clk_mgr_base->clks.phyclk_khz));
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
index 7deeec9d1c7c..9f7eed6688c4 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
@@ -126,7 +126,7 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis
actual_dispclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDispclkFreq,
- requested_dispclk_khz / 1000);
+ khz_to_mhz_ceil(requested_dispclk_khz));
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
@@ -138,7 +138,7 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis
// pmfw always set clock more than or equal requested clock
if (!IS_DIAG_DC(dc->ctx->dce_environment))
- ASSERT(actual_dispclk_set_mhz >= requested_dispclk_khz / 1000);
+ ASSERT(actual_dispclk_set_mhz >= khz_to_mhz_ceil(requested_dispclk_khz));
return actual_dispclk_set_mhz * 1000;
}
@@ -150,7 +150,7 @@ int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
actual_dprefclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDprefclkFreq,
- clk_mgr->base.dprefclk_khz / 1000);
+ khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
/* TODO: add code for programing DP DTO, currently this is down by command table */
@@ -167,7 +167,7 @@ int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int reque
actual_dcfclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
- requested_dcfclk_khz / 1000);
+ khz_to_mhz_ceil(requested_dcfclk_khz));
return actual_dcfclk_set_mhz * 1000;
}
@@ -182,7 +182,7 @@ int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int
actual_min_ds_dcfclk_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
- requested_min_ds_dcfclk_khz / 1000);
+ khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
return actual_min_ds_dcfclk_mhz * 1000;
}
@@ -192,7 +192,7 @@ void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phy
rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetPhyclkVoltageByFreq,
- requested_phyclk_khz / 1000);
+ khz_to_mhz_ceil(requested_phyclk_khz));
}
int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
@@ -203,10 +203,10 @@ int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_
actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDppclkFreq,
- requested_dpp_khz / 1000);
+ khz_to_mhz_ceil(requested_dpp_khz));
if (!IS_DIAG_DC(dc->ctx->dce_environment))
- ASSERT(actual_dppclk_set_mhz >= requested_dpp_khz / 1000);
+ ASSERT(actual_dppclk_set_mhz >= khz_to_mhz_ceil(requested_dpp_khz));
return actual_dppclk_set_mhz * 1000;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
index af7004b770ae..1861a147a7fa 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
@@ -284,12 +284,12 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
- dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCEFCLK, clk_mgr_base->clks.dcfclk_khz / 1000);
+ dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCEFCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz));
}
if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
- dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz / 1000);
+ dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz));
}
if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz))
@@ -317,20 +317,20 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
/* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
if (clk_mgr_base->clks.p_state_change_support &&
(update_uclk || !clk_mgr_base->clks.prev_p_state_change_support))
- dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, clk_mgr_base->clks.dramclk_khz / 1000);
+ dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) {
if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz)
dpp_clock_lowered = true;
clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
- dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PIXCLK, clk_mgr_base->clks.dppclk_khz / 1000);
+ dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PIXCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz));
update_dppclk = true;
}
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
- dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, clk_mgr_base->clks.dispclk_khz / 1000);
+ dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dispclk_khz));
update_dispclk = true;
}
@@ -396,12 +396,17 @@ static void dcn3_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool current_
if (!clk_mgr->smu_present)
return;
- if (current_mode)
- dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
- clk_mgr_base->clks.dramclk_khz / 1000);
- else
+ if (current_mode) {
+ if (clk_mgr_base->clks.p_state_change_support)
+ dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+ khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
+ else
+ dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+ clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries - 1].memclk_mhz);
+ } else {
dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz);
+ }
}
/* Set max memclk to highest DPM value */
@@ -489,7 +494,7 @@ static void dcn30_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct d
if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) {
clk_mgr_base->clks.phyclk_khz = max_phyclk_req;
- dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000);
+ dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PHYCLK, khz_to_mhz_ceil(clk_mgr_base->clks.phyclk_khz));
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c
index 07774fa2c2cf..6ea642615854 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c
@@ -133,7 +133,7 @@ int dcn301_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispc
actual_dispclk_set_mhz = dcn301_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDispclkFreq,
- requested_dispclk_khz / 1000);
+ khz_to_mhz_ceil(requested_dispclk_khz));
return actual_dispclk_set_mhz * 1000;
}
@@ -147,7 +147,7 @@ int dcn301_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
actual_dprefclk_set_mhz = dcn301_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDprefclkFreq,
- clk_mgr->base.dprefclk_khz / 1000);
+ khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
/* TODO: add code for programing DP DTO, currently this is down by command table */
@@ -163,7 +163,7 @@ int dcn301_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int request
actual_dcfclk_set_mhz = dcn301_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
- requested_dcfclk_khz / 1000);
+ khz_to_mhz_ceil(requested_dcfclk_khz));
return actual_dcfclk_set_mhz * 1000;
}
@@ -177,7 +177,7 @@ int dcn301_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int r
actual_min_ds_dcfclk_mhz = dcn301_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
- requested_min_ds_dcfclk_khz / 1000);
+ khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
return actual_min_ds_dcfclk_mhz * 1000;
}
@@ -191,7 +191,7 @@ int dcn301_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_kh
actual_dppclk_set_mhz = dcn301_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDppclkFreq,
- requested_dpp_khz / 1000);
+ khz_to_mhz_ceil(requested_dpp_khz));
return actual_dppclk_set_mhz * 1000;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
index c636b589d69d..7046da14bb2a 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
@@ -114,7 +114,7 @@ void vg_update_clocks(struct clk_mgr *clk_mgr_base,
display_count = vg_get_active_display_cnt_wa(dc, context);
/* if we can go lower, go lower */
- if (display_count == 0) {
+ if (display_count == 0 && !IS_DIAG_DC(dc->ctx->dce_environment)) {
union display_idle_optimization_u idle_info = { 0 };
idle_info.idle_info.df_request_disabled = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c
index dad4a4c18bcf..8c2b77eb9459 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c
@@ -147,7 +147,7 @@ int dcn31_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispcl
actual_dispclk_set_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDispclkFreq,
- (requested_dispclk_khz + 999) / 1000);
+ khz_to_mhz_ceil(requested_dispclk_khz));
return actual_dispclk_set_mhz * 1000;
}
@@ -162,7 +162,7 @@ int dcn31_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
actual_dprefclk_set_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDprefclkFreq,
- (clk_mgr->base.dprefclk_khz + 999) / 1000);
+ khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
/* TODO: add code for programing DP DTO, currently this is down by command table */
@@ -182,7 +182,7 @@ int dcn31_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requeste
actual_dcfclk_set_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
- (requested_dcfclk_khz + 999) / 1000);
+ khz_to_mhz_ceil(requested_dcfclk_khz));
return actual_dcfclk_set_mhz * 1000;
}
@@ -200,7 +200,7 @@ int dcn31_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int re
actual_min_ds_dcfclk_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
- (requested_min_ds_dcfclk_khz + 999) / 1000);
+ khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
return actual_min_ds_dcfclk_mhz * 1000;
}
@@ -215,7 +215,7 @@ int dcn31_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz
actual_dppclk_set_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDppclkFreq,
- (requested_dpp_khz + 999) / 1000);
+ khz_to_mhz_ceil(requested_dpp_khz));
return actual_dppclk_set_mhz * 1000;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index a30283fa5173..c798c65d4276 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1481,6 +1481,22 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
return true;
}
+static inline bool should_update_pipe_for_stream(
+ struct dc_state *context,
+ struct pipe_ctx *pipe_ctx,
+ struct dc_stream_state *stream)
+{
+ return (pipe_ctx->stream && pipe_ctx->stream == stream);
+}
+
+static inline bool should_update_pipe_for_plane(
+ struct dc_state *context,
+ struct pipe_ctx *pipe_ctx,
+ struct dc_plane_state *plane_state)
+{
+ return (pipe_ctx->plane_state == plane_state);
+}
+
void dc_enable_stereo(
struct dc *dc,
struct dc_state *context,
@@ -1491,12 +1507,15 @@ void dc_enable_stereo(
struct pipe_ctx *pipe;
for (i = 0; i < MAX_PIPES; i++) {
- if (context != NULL)
+ if (context != NULL) {
pipe = &context->res_ctx.pipe_ctx[i];
- else
+ } else {
+ context = dc->current_state;
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- for (j = 0 ; pipe && j < stream_count; j++) {
- if (streams[j] && streams[j] == pipe->stream &&
+ }
+
+ for (j = 0; pipe && j < stream_count; j++) {
+ if (should_update_pipe_for_stream(context, pipe, streams[j]) &&
dc->hwss.setup_stereo)
dc->hwss.setup_stereo(pipe, dc);
}
@@ -2629,6 +2648,7 @@ static void commit_planes_for_stream(struct dc *dc,
{
int i, j;
struct pipe_ctx *top_pipe_to_program = NULL;
+ bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST);
#if defined(CONFIG_DRM_AMD_DC_DCN)
dc_z10_restore(dc);
@@ -2700,7 +2720,7 @@ static void commit_planes_for_stream(struct dc *dc,
top_pipe_to_program->stream_res.tg);
}
- if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
+ if (should_lock_all_pipes && dc->hwss.interdependent_update_lock)
dc->hwss.interdependent_update_lock(dc, context, true);
else
/* Lock the top pipe while updating plane addrs, since freesync requires
@@ -2723,7 +2743,7 @@ static void commit_planes_for_stream(struct dc *dc,
if (dc->hwss.program_front_end_for_ctx)
dc->hwss.program_front_end_for_ctx(dc, context);
- if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
+ if (should_lock_all_pipes && dc->hwss.interdependent_update_lock)
dc->hwss.interdependent_update_lock(dc, context, false);
else
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
@@ -2739,14 +2759,14 @@ static void commit_planes_for_stream(struct dc *dc,
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
if (!pipe_ctx->plane_state)
continue;
- if (pipe_ctx->plane_state != plane_state)
+ if (should_update_pipe_for_plane(context, pipe_ctx, plane_state))
continue;
- plane_state->triplebuffer_flips = false;
+ pipe_ctx->plane_state->triplebuffer_flips = false;
if (update_type == UPDATE_TYPE_FAST &&
dc->hwss.program_triplebuffer != NULL &&
- !plane_state->flip_immediate && dc->debug.enable_tri_buf) {
+ !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
/*triple buffer for VUpdate only*/
- plane_state->triplebuffer_flips = true;
+ pipe_ctx->plane_state->triplebuffer_flips = true;
}
}
if (update_type == UPDATE_TYPE_FULL) {
@@ -2762,8 +2782,7 @@ static void commit_planes_for_stream(struct dc *dc,
if (!pipe_ctx->top_pipe &&
!pipe_ctx->prev_odm_pipe &&
- pipe_ctx->stream &&
- pipe_ctx->stream == stream) {
+ should_update_pipe_for_stream(context, pipe_ctx, stream)) {
struct dc_stream_status *stream_status = NULL;
if (!pipe_ctx->plane_state)
@@ -2816,15 +2835,15 @@ static void commit_planes_for_stream(struct dc *dc,
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
- if (pipe_ctx->stream != stream)
+ if (!should_update_pipe_for_stream(context, pipe_ctx, stream))
continue;
- if (pipe_ctx->plane_state != plane_state)
+ if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
continue;
// GSL has to be used for flip immediate
dc->hwss.set_flip_control_gsl(pipe_ctx,
- plane_state->flip_immediate);
+ pipe_ctx->plane_state->flip_immediate);
}
}
@@ -2835,25 +2854,26 @@ static void commit_planes_for_stream(struct dc *dc,
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
- if (pipe_ctx->stream != stream)
+ if (!should_update_pipe_for_stream(context, pipe_ctx, stream))
continue;
- if (pipe_ctx->plane_state != plane_state)
+ if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
continue;
+
/*program triple buffer after lock based on flip type*/
if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
/*only enable triplebuffer for fast_update*/
dc->hwss.program_triplebuffer(
- dc, pipe_ctx, plane_state->triplebuffer_flips);
+ dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
}
- if (srf_updates[i].flip_addr)
+ if (pipe_ctx->plane_state->update_flags.bits.addr_update)
dc->hwss.update_plane_addr(dc, pipe_ctx);
}
}
}
- if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
+ if (should_lock_all_pipes && dc->hwss.interdependent_update_lock)
dc->hwss.interdependent_update_lock(dc, context, false);
else
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
@@ -2897,7 +2917,7 @@ static void commit_planes_for_stream(struct dc *dc,
continue;
if (pipe_ctx->bottom_pipe || pipe_ctx->next_odm_pipe ||
- !pipe_ctx->stream || pipe_ctx->stream != stream ||
+ !pipe_ctx->stream || !should_update_pipe_for_stream(context, pipe_ctx, stream) ||
!pipe_ctx->plane_state->update_flags.bits.addr_update ||
pipe_ctx->plane_state->skip_manual_trigger)
continue;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 6132b645bfd1..8bd7f42a8053 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -541,6 +541,7 @@ static void link_disconnect_sink(struct dc_link *link)
}
link->dpcd_sink_count = 0;
+ //link->dpcd_caps.dpcd_rev.raw = 0;
}
static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *link)
@@ -742,6 +743,7 @@ static bool detect_dp(struct dc_link *link,
sink_caps,
audio_support);
link->dpcd_caps.dongle_type = sink_caps->dongle_type;
+ link->dpcd_caps.dpcd_rev.raw = 0;
}
return true;
@@ -1663,6 +1665,12 @@ struct dc_link *link_create(const struct link_init_data *init_params)
if (false == dc_link_construct(link, init_params))
goto construct_fail;
+ /*
+ * Must use preferred_link_setting, not reported_link_cap or verified_link_cap,
+ * since struct preferred_link_setting won't be reset after S3.
+ */
+ link->preferred_link_setting.dpcd_source_device_specific_field_support = true;
+
return link;
construct_fail:
@@ -3509,61 +3517,6 @@ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
}
}
-uint32_t dc_bandwidth_in_kbps_from_timing(
- const struct dc_crtc_timing *timing)
-{
- uint32_t bits_per_channel = 0;
- uint32_t kbps;
-
-#if defined(CONFIG_DRM_AMD_DC_DCN)
- if (timing->flags.DSC)
- return dc_dsc_stream_bandwidth_in_kbps(timing,
- timing->dsc_cfg.bits_per_pixel,
- timing->dsc_cfg.num_slices_h,
- timing->dsc_cfg.is_dp);
-#endif
-
- switch (timing->display_color_depth) {
- case COLOR_DEPTH_666:
- bits_per_channel = 6;
- break;
- case COLOR_DEPTH_888:
- bits_per_channel = 8;
- break;
- case COLOR_DEPTH_101010:
- bits_per_channel = 10;
- break;
- case COLOR_DEPTH_121212:
- bits_per_channel = 12;
- break;
- case COLOR_DEPTH_141414:
- bits_per_channel = 14;
- break;
- case COLOR_DEPTH_161616:
- bits_per_channel = 16;
- break;
- default:
- ASSERT(bits_per_channel != 0);
- bits_per_channel = 8;
- break;
- }
-
- kbps = timing->pix_clk_100hz / 10;
- kbps *= bits_per_channel;
-
- if (timing->flags.Y_ONLY != 1) {
- /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
- kbps *= 3;
- if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
- kbps /= 2;
- else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
- kbps = kbps * 2 / 3;
- }
-
- return kbps;
-
-}
-
void dc_link_set_drive_settings(struct dc *dc,
struct link_training_settings *lt_settings,
const struct dc_link *link)
@@ -3769,3 +3722,58 @@ bool dc_link_should_enable_fec(const struct dc_link *link)
return ret;
}
+
+uint32_t dc_bandwidth_in_kbps_from_timing(
+ const struct dc_crtc_timing *timing)
+{
+ uint32_t bits_per_channel = 0;
+ uint32_t kbps;
+
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+ if (timing->flags.DSC)
+ return dc_dsc_stream_bandwidth_in_kbps(timing,
+ timing->dsc_cfg.bits_per_pixel,
+ timing->dsc_cfg.num_slices_h,
+ timing->dsc_cfg.is_dp);
+#endif
+
+ switch (timing->display_color_depth) {
+ case COLOR_DEPTH_666:
+ bits_per_channel = 6;
+ break;
+ case COLOR_DEPTH_888:
+ bits_per_channel = 8;
+ break;
+ case COLOR_DEPTH_101010:
+ bits_per_channel = 10;
+ break;
+ case COLOR_DEPTH_121212:
+ bits_per_channel = 12;
+ break;
+ case COLOR_DEPTH_141414:
+ bits_per_channel = 14;
+ break;
+ case COLOR_DEPTH_161616:
+ bits_per_channel = 16;
+ break;
+ default:
+ ASSERT(bits_per_channel != 0);
+ bits_per_channel = 8;
+ break;
+ }
+
+ kbps = timing->pix_clk_100hz / 10;
+ kbps *= bits_per_channel;
+
+ if (timing->flags.Y_ONLY != 1) {
+ /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
+ kbps *= 3;
+ if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
+ kbps /= 2;
+ else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
+ kbps = kbps * 2 / 3;
+ }
+
+ return kbps;
+
+}
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 a6d0fd24fd02..cd025c12f17b 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
@@ -1241,29 +1241,15 @@ enum link_training_result dp_check_link_loss_status(
static inline void decide_8b_10b_training_settings(
struct dc_link *link,
const struct dc_link_settings *link_setting,
- const struct dc_link_training_overrides *overrides,
struct link_training_settings *lt_settings)
{
- uint32_t lane;
-
memset(lt_settings, '\0', sizeof(struct link_training_settings));
/* Initialize link settings */
lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
-
- if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
- lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate;
- else
- lt_settings->link_settings.link_rate = link_setting->link_rate;
-
- if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN)
- lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count;
- else
- lt_settings->link_settings.lane_count = link_setting->lane_count;
-
- /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
-
+ lt_settings->link_settings.link_rate = link_setting->link_rate;
+ lt_settings->link_settings.lane_count = link_setting->lane_count;
/* TODO hard coded to SS for now
* lt_settings.link_settings.link_spread =
* dal_display_path_is_ss_supported(
@@ -1271,30 +1257,52 @@ static inline void decide_8b_10b_training_settings(
* LINK_SPREAD_05_DOWNSPREAD_30KHZ :
* LINK_SPREAD_DISABLED;
*/
- /* Initialize link spread */
- if (link->dp_ss_off)
- lt_settings->link_settings.link_spread = LINK_SPREAD_DISABLED;
- else if (overrides->downspread != NULL)
- lt_settings->link_settings.link_spread
- = *overrides->downspread
- ? LINK_SPREAD_05_DOWNSPREAD_30KHZ
- : LINK_SPREAD_DISABLED;
- else
- lt_settings->link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
-
+ lt_settings->link_settings.link_spread = link->dp_ss_off ?
+ LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
lt_settings->lttpr_mode = link->lttpr_mode;
+ lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
+ lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
+ lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
+ lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
+ lt_settings->enhanced_framing = 1;
+ lt_settings->should_set_fec_ready = true;
+}
+
+void dp_decide_training_settings(
+ struct dc_link *link,
+ const struct dc_link_settings *link_settings,
+ struct link_training_settings *lt_settings)
+{
+ if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
+ decide_8b_10b_training_settings(link, link_settings, lt_settings);
+}
+
+static void override_training_settings(
+ struct dc_link *link,
+ const struct dc_link_training_overrides *overrides,
+ struct link_training_settings *lt_settings)
+{
+ uint32_t lane;
+
+ /* Override link settings */
+ if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
+ lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate;
+ if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN)
+ lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count;
+
+ /* Override link spread */
+ if (!link->dp_ss_off && overrides->downspread != NULL)
+ lt_settings->link_settings.link_spread = *overrides->downspread ?
+ LINK_SPREAD_05_DOWNSPREAD_30KHZ
+ : LINK_SPREAD_DISABLED;
- /* Initialize lane settings overrides */
+ /* Override lane settings */
if (overrides->voltage_swing != NULL)
lt_settings->voltage_swing = overrides->voltage_swing;
-
if (overrides->pre_emphasis != NULL)
lt_settings->pre_emphasis = overrides->pre_emphasis;
-
if (overrides->post_cursor2 != NULL)
lt_settings->post_cursor2 = overrides->post_cursor2;
-
- /* Initialize lane settings (VS/PE/PC2) */
for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
lt_settings->lane_settings[lane].VOLTAGE_SWING =
lt_settings->voltage_swing != NULL ?
@@ -1313,45 +1321,22 @@ static inline void decide_8b_10b_training_settings(
/* Initialize training timings */
if (overrides->cr_pattern_time != NULL)
lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
- else
- lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
if (overrides->eq_pattern_time != NULL)
lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
- else
- lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
if (overrides->pattern_for_cr != NULL)
lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
- else
- lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
if (overrides->pattern_for_eq != NULL)
lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
- else
- lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
if (overrides->enhanced_framing != NULL)
lt_settings->enhanced_framing = *overrides->enhanced_framing;
- else
- lt_settings->enhanced_framing = 1;
if (link->preferred_training_settings.fec_enable != NULL)
lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
- else
- lt_settings->should_set_fec_ready = true;
-}
-
-void dp_decide_training_settings(
- struct dc_link *link,
- const struct dc_link_settings *link_settings,
- const struct dc_link_training_overrides *overrides,
- struct link_training_settings *lt_settings)
-{
- if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
- decide_8b_10b_training_settings(link, link_settings, overrides, lt_settings);
}
-
uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
{
switch (lttpr_repeater_count) {
@@ -1581,6 +1566,9 @@ bool dc_link_dp_perform_link_training_skip_aux(
dp_decide_training_settings(
link,
link_setting,
+ &lt_settings);
+ override_training_settings(
+ link,
&link->preferred_training_settings,
&lt_settings);
@@ -1727,6 +1715,9 @@ enum link_training_result dc_link_dp_perform_link_training(
dp_decide_training_settings(
link,
link_settings,
+ &lt_settings);
+ override_training_settings(
+ link,
&link->preferred_training_settings,
&lt_settings);
@@ -1939,11 +1930,13 @@ enum link_training_result dc_link_dp_sync_lt_attempt(
bool fec_enable = false;
dp_decide_training_settings(
- link,
- link_settings,
- lt_overrides,
- &lt_settings);
-
+ link,
+ link_settings,
+ &lt_settings);
+ override_training_settings(
+ link,
+ lt_overrides,
+ &lt_settings);
/* Setup MST Mode */
if (lt_overrides->mst_enable)
set_dp_mst_mode(link, *lt_overrides->mst_enable);
@@ -4776,10 +4769,18 @@ void dpcd_set_source_specific_data(struct dc_link *link)
uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period;
- result_write_min_hblank = core_link_write_dpcd(link,
- DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
- sizeof(hblank_size));
+ if (link->preferred_link_setting.dpcd_source_device_specific_field_support) {
+ result_write_min_hblank = core_link_write_dpcd(link,
+ DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size),
+ sizeof(hblank_size));
+
+ if (result_write_min_hblank == DC_ERROR_UNEXPECTED)
+ link->preferred_link_setting.dpcd_source_device_specific_field_support = false;
+ } else {
+ DC_LOG_DC("Sink device does not support 00340h DPCD write. Skipping on purpose.\n");
+ }
}
+
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
WPP_BIT_FLAG_DC_DETECTION_DP_CAPS,
"result=%u link_index=%u enum dce_version=%d DPCD=0x%04X min_hblank=%u branch_dev_id=0x%x branch_dev_name='%c%c%c%c%c%c'",
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c
index fe234760a0f5..72970e49800a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c
@@ -1,3 +1,28 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
#include <inc/core_status.h>
#include <dc_link.h>
#include <inc/link_hwss.h>
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
index 1a89d565c92e..de80a9ea4cfa 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
@@ -305,7 +305,7 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc(
const struct dc_state *state)
{
struct link_encoder *link_enc = NULL;
- enum engine_id eng_id = ENGINE_ID_UNKNOWN;
+ enum engine_id eng_id;
eng_id = find_first_avail_link_enc(dc->ctx, state);
if (eng_id != ENGINE_ID_UNKNOWN)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 1596f6b7fed7..a60396d5be44 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1030,7 +1030,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
/* Timing borders are part of vactive that we are also supposed to skip in addition
* to any stream dst offset. Since dm logic assumes dst is in addressable
- * space we need to add the the left and top borders to dst offsets temporarily.
+ * space we need to add the left and top borders to dst offsets temporarily.
* TODO: fix in DM, stream dst is supposed to be in vactive
*/
pipe_ctx->stream->dst.x += timing->h_border_left;
@@ -1051,6 +1051,11 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
/* depends on scaling ratios and recout, does not calculate offset yet */
calculate_viewport_size(pipe_ctx);
+ /* Stopgap for validation of ODM + MPO on one side of screen case */
+ if (pipe_ctx->plane_res.scl_data.viewport.height < 1 ||
+ pipe_ctx->plane_res.scl_data.viewport.width < 1)
+ return false;
+
/*
* LB calculations depend on vp size, h/v_active and scaling ratios
* Setting line buffer pixel depth to 24bpp yields banding
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stat.c b/drivers/gpu/drm/amd/display/dc/core/dc_stat.c
index 31761f3595a6..28ef9760fa34 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stat.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stat.c
@@ -62,3 +62,27 @@ void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification
status = dmub_srv_stat_get_notification(dmub, notify);
ASSERT(status == DMUB_STATUS_OK);
}
+
+/**
+ *****************************************************************************
+ * Function: dc_stat_get_dmub_dataout
+ *
+ * @brief
+ * Calls dmub layer to retrieve dmub gpint dataout
+ *
+ * @param
+ * [in] dc: dc structure
+ * [in] dataout: dmub gpint dataout
+ *
+ * @return
+ * None
+ *****************************************************************************
+ */
+void dc_stat_get_dmub_dataout(const struct dc *dc, uint32_t *dataout)
+{
+ struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub;
+ enum dmub_status status;
+
+ status = dmub_srv_get_gpint_dataout(dmub, dataout);
+ ASSERT(status == DMUB_STATUS_OK);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 45931ee14a6e..f0f54f4d3d9b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -221,6 +221,9 @@ struct dc_stream_status *dc_stream_get_status_from_state(
{
uint8_t i;
+ if (state == NULL)
+ return NULL;
+
for (i = 0; i < state->stream_count; i++) {
if (stream == state->streams[i])
return &state->stream_status[i];
@@ -243,6 +246,40 @@ struct dc_stream_status *dc_stream_get_status(
return dc_stream_get_status_from_state(dc->current_state, stream);
}
+static void program_cursor_attributes(
+ struct dc *dc,
+ struct dc_stream_state *stream,
+ const struct dc_cursor_attributes *attributes)
+{
+ int i;
+ struct resource_context *res_ctx;
+ struct pipe_ctx *pipe_to_program = NULL;
+
+ if (!stream)
+ return;
+
+ res_ctx = &dc->current_state->res_ctx;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
+
+ if (pipe_ctx->stream != stream)
+ continue;
+
+ if (!pipe_to_program) {
+ pipe_to_program = pipe_ctx;
+ dc->hwss.cursor_lock(dc, pipe_to_program, true);
+ }
+
+ dc->hwss.set_cursor_attribute(pipe_ctx);
+ if (dc->hwss.set_cursor_sdr_white_level)
+ dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
+ }
+
+ if (pipe_to_program)
+ dc->hwss.cursor_lock(dc, pipe_to_program, false);
+}
+
#ifndef TRIM_FSFT
/*
* dc_optimize_timing_for_fsft() - dc to optimize timing
@@ -267,10 +304,7 @@ bool dc_stream_set_cursor_attributes(
struct dc_stream_state *stream,
const struct dc_cursor_attributes *attributes)
{
- int i;
struct dc *dc;
- struct resource_context *res_ctx;
- struct pipe_ctx *pipe_to_program = NULL;
#if defined(CONFIG_DRM_AMD_DC_DCN)
bool reset_idle_optimizations = false;
#endif
@@ -290,7 +324,6 @@ bool dc_stream_set_cursor_attributes(
}
dc = stream->ctx->dc;
- res_ctx = &dc->current_state->res_ctx;
stream->cursor_attributes = *attributes;
#if defined(CONFIG_DRM_AMD_DC_DCN)
@@ -302,11 +335,39 @@ bool dc_stream_set_cursor_attributes(
}
#endif
+ program_cursor_attributes(dc, stream, attributes);
+
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+ /* re-enable idle optimizations if necessary */
+ if (reset_idle_optimizations)
+ dc_allow_idle_optimizations(dc, true);
+
+#endif
+ return true;
+}
+
+static void program_cursor_position(
+ struct dc *dc,
+ struct dc_stream_state *stream,
+ const struct dc_cursor_position *position)
+{
+ int i;
+ struct resource_context *res_ctx;
+ struct pipe_ctx *pipe_to_program = NULL;
+
+ if (!stream)
+ return;
+
+ res_ctx = &dc->current_state->res_ctx;
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
- if (pipe_ctx->stream != stream)
+ if (pipe_ctx->stream != stream ||
+ (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) ||
+ !pipe_ctx->plane_state ||
+ (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) ||
+ (!pipe_ctx->plane_res.ipp && !pipe_ctx->plane_res.dpp))
continue;
if (!pipe_to_program) {
@@ -314,31 +375,18 @@ bool dc_stream_set_cursor_attributes(
dc->hwss.cursor_lock(dc, pipe_to_program, true);
}
- dc->hwss.set_cursor_attribute(pipe_ctx);
- if (dc->hwss.set_cursor_sdr_white_level)
- dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
+ dc->hwss.set_cursor_position(pipe_ctx);
}
if (pipe_to_program)
dc->hwss.cursor_lock(dc, pipe_to_program, false);
-
-#if defined(CONFIG_DRM_AMD_DC_DCN)
- /* re-enable idle optimizations if necessary */
- if (reset_idle_optimizations)
- dc_allow_idle_optimizations(dc, true);
-
-#endif
- return true;
}
bool dc_stream_set_cursor_position(
struct dc_stream_state *stream,
const struct dc_cursor_position *position)
{
- int i;
struct dc *dc;
- struct resource_context *res_ctx;
- struct pipe_ctx *pipe_to_program = NULL;
#if defined(CONFIG_DRM_AMD_DC_DCN)
bool reset_idle_optimizations = false;
#endif
@@ -354,7 +402,6 @@ bool dc_stream_set_cursor_position(
}
dc = stream->ctx->dc;
- res_ctx = &dc->current_state->res_ctx;
#if defined(CONFIG_DRM_AMD_DC_DCN)
dc_z10_restore(dc);
@@ -367,27 +414,7 @@ bool dc_stream_set_cursor_position(
#endif
stream->cursor_position = *position;
- for (i = 0; i < MAX_PIPES; i++) {
- struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
-
- if (pipe_ctx->stream != stream ||
- (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) ||
- !pipe_ctx->plane_state ||
- (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) ||
- (!pipe_ctx->plane_res.ipp && !pipe_ctx->plane_res.dpp))
- continue;
-
- if (!pipe_to_program) {
- pipe_to_program = pipe_ctx;
- dc->hwss.cursor_lock(dc, pipe_to_program, true);
- }
-
- dc->hwss.set_cursor_position(pipe_ctx);
- }
-
- if (pipe_to_program)
- dc->hwss.cursor_lock(dc, pipe_to_program, false);
-
+ program_cursor_position(dc, stream, position);
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* re-enable idle optimizations if necessary */
if (reset_idle_optimizations)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 21d78289b048..3ab52d9a82cf 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -45,7 +45,7 @@
/* forward declaration */
struct aux_payload;
-#define DC_VER "3.2.141"
+#define DC_VER "3.2.149"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@@ -460,7 +460,65 @@ union mem_low_power_enable_options {
uint32_t u32All;
};
+struct dc_debug_data {
+ uint32_t ltFailCount;
+ uint32_t i2cErrorCount;
+ uint32_t auxErrorCount;
+};
+
+struct dc_phy_addr_space_config {
+ struct {
+ uint64_t start_addr;
+ uint64_t end_addr;
+ uint64_t fb_top;
+ uint64_t fb_offset;
+ uint64_t fb_base;
+ uint64_t agp_top;
+ uint64_t agp_bot;
+ uint64_t agp_base;
+ } system_aperture;
+
+ struct {
+ uint64_t page_table_start_addr;
+ uint64_t page_table_end_addr;
+ uint64_t page_table_base_addr;
+ bool base_addr_is_mc_addr;
+ } gart_config;
+
+ bool valid;
+ bool is_hvm_enabled;
+ uint64_t page_table_default_page_addr;
+};
+
+struct dc_virtual_addr_space_config {
+ uint64_t page_table_base_addr;
+ uint64_t page_table_start_addr;
+ uint64_t page_table_end_addr;
+ uint32_t page_table_block_size_in_bytes;
+ uint8_t page_table_depth; // 1 = 1 level, 2 = 2 level, etc. 0 = invalid
+};
+
+struct dc_bounding_box_overrides {
+ int sr_exit_time_ns;
+ int sr_enter_plus_exit_time_ns;
+ int urgent_latency_ns;
+ int percent_of_ideal_drambw;
+ int dram_clock_change_latency_ns;
+ int dummy_clock_change_latency_ns;
+ /* This forces a hard min on the DCFCLK we use
+ * for DML. Unlike the debug option for forcing
+ * DCFCLK, this override affects watermark calculations
+ */
+ int min_dcfclk_mhz;
+};
+
+struct dc_state;
+struct resource_pool;
+struct dce_hwseq;
+
struct dc_debug_options {
+ bool native422_support;
+ bool disable_dsc;
enum visual_confirm visual_confirm;
bool sanity_checks;
bool max_disp_clk;
@@ -486,7 +544,6 @@ struct dc_debug_options {
bool disable_dsc_power_gate;
int dsc_min_slice_height_override;
int dsc_bpp_increment_div;
- bool native422_support;
bool disable_pplib_wm_range;
enum wm_report_mode pplib_wm_report_mode;
unsigned int min_disp_clk_khz;
@@ -556,7 +613,6 @@ struct dc_debug_options {
bool validate_dml_output;
bool enable_dmcub_surface_flip;
bool usbc_combo_phy_reset_wa;
- bool disable_dsc;
bool enable_dram_clock_change_one_display_vactive;
union mem_low_power_enable_options enable_mem_low_power;
bool force_vblank_alignment;
@@ -574,69 +630,13 @@ struct dc_debug_options {
#endif
};
-struct dc_debug_data {
- uint32_t ltFailCount;
- uint32_t i2cErrorCount;
- uint32_t auxErrorCount;
-};
-
-struct dc_phy_addr_space_config {
- struct {
- uint64_t start_addr;
- uint64_t end_addr;
- uint64_t fb_top;
- uint64_t fb_offset;
- uint64_t fb_base;
- uint64_t agp_top;
- uint64_t agp_bot;
- uint64_t agp_base;
- } system_aperture;
-
- struct {
- uint64_t page_table_start_addr;
- uint64_t page_table_end_addr;
- uint64_t page_table_base_addr;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
- bool base_addr_is_mc_addr;
-#endif
- } gart_config;
-
- bool valid;
- bool is_hvm_enabled;
- uint64_t page_table_default_page_addr;
-};
-
-struct dc_virtual_addr_space_config {
- uint64_t page_table_base_addr;
- uint64_t page_table_start_addr;
- uint64_t page_table_end_addr;
- uint32_t page_table_block_size_in_bytes;
- uint8_t page_table_depth; // 1 = 1 level, 2 = 2 level, etc. 0 = invalid
-};
-
-struct dc_bounding_box_overrides {
- int sr_exit_time_ns;
- int sr_enter_plus_exit_time_ns;
- int urgent_latency_ns;
- int percent_of_ideal_drambw;
- int dram_clock_change_latency_ns;
- int dummy_clock_change_latency_ns;
- /* This forces a hard min on the DCFCLK we use
- * for DML. Unlike the debug option for forcing
- * DCFCLK, this override affects watermark calculations
- */
- int min_dcfclk_mhz;
-};
-
-struct resource_pool;
-struct dce_hwseq;
struct gpu_info_soc_bounding_box_v1_0;
struct dc {
+ struct dc_debug_options debug;
struct dc_versions versions;
struct dc_caps caps;
struct dc_cap_funcs cap_funcs;
struct dc_config config;
- struct dc_debug_options debug;
struct dc_bounding_box_overrides bb_overrides;
struct dc_bug_wa work_arounds;
struct dc_context *ctx;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
index 1948cd9427d7..4f54bde1bb1c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
@@ -109,6 +109,7 @@ struct dc_link_settings {
enum dc_link_spread link_spread;
bool use_link_rate_set;
uint8_t link_rate_set;
+ bool dpcd_source_device_specific_field_support;
};
struct dc_lane_settings {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
index a612ba6dc389..ab6bc5d79012 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
@@ -28,9 +28,9 @@
*/
#include <linux/delay.h>
+#include <linux/stdarg.h>
#include "dm_services.h"
-#include <stdarg.h>
#include "dc.h"
#include "dc_dmub_srv.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stat.h b/drivers/gpu/drm/amd/display/dc/dc_stat.h
index 2a000ba54ddb..aacbfd786c6c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stat.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stat.h
@@ -38,5 +38,6 @@
#include "dmub/dmub_srv.h"
void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification *notify);
+void dc_stat_get_dmub_dataout(const struct dc *dc, uint32_t *dataout);
#endif /* _DC_STAT_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_trace.h b/drivers/gpu/drm/amd/display/dc/dc_trace.h
index d2615357269b..c711797e5c9e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_trace.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_trace.h
@@ -37,3 +37,6 @@
#define TRACE_DCN_CLOCK_STATE(dcn_clocks) \
trace_amdgpu_dm_dc_clocks_state(dcn_clocks)
+
+#define TRACE_DCN_FPU(begin, function, line, ref_count) \
+ trace_dcn_fpu(begin, function, line, ref_count)
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 8016e22114ce..c1532930169b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -75,18 +75,6 @@ enum dce_environment {
#define IS_DIAG_DC(dce_environment) \
(IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG))
-struct hw_asic_id {
- uint32_t chip_id;
- uint32_t chip_family;
- uint32_t pci_revision_id;
- uint32_t hw_internal_rev;
- uint32_t vram_type;
- uint32_t vram_width;
- uint32_t feature_flags;
- uint32_t fake_paths_num;
- void *atombios_base_address;
-};
-
struct dc_perf_trace {
unsigned long read_count;
unsigned long write_count;
@@ -94,36 +82,7 @@ struct dc_perf_trace {
unsigned long last_entry_write;
};
-struct dc_context {
- struct dc *dc;
-
- void *driver_context; /* e.g. amdgpu_device */
- struct dc_perf_trace *perf_trace;
- void *cgs_device;
-
- enum dce_environment dce_environment;
- struct hw_asic_id asic_id;
-
- /* todo: below should probably move to dc. to facilitate removal
- * of AS we will store these here
- */
- enum dce_version dce_version;
- struct dc_bios *dc_bios;
- bool created_bios;
- struct gpio_service *gpio_service;
- uint32_t dc_sink_id_count;
- uint32_t dc_stream_id_count;
- uint32_t dc_edp_id_count;
- uint64_t fbc_gpu_addr;
- struct dc_dmub_srv *dmub_srv;
-
-#ifdef CONFIG_DRM_AMD_DC_HDCP
- struct cp_psp cp_psp;
-#endif
-};
-
-
-#define DC_MAX_EDID_BUFFER_SIZE 1280
+#define DC_MAX_EDID_BUFFER_SIZE 2048
#define DC_EDID_BLOCK_SIZE 128
#define MAX_SURFACE_NUM 4
#define NUM_PIXEL_FORMATS 10
@@ -836,6 +795,46 @@ struct dc_clock_config {
uint32_t current_clock_khz;/*current clock in use*/
};
+struct hw_asic_id {
+ uint32_t chip_id;
+ uint32_t chip_family;
+ uint32_t pci_revision_id;
+ uint32_t hw_internal_rev;
+ uint32_t vram_type;
+ uint32_t vram_width;
+ uint32_t feature_flags;
+ uint32_t fake_paths_num;
+ void *atombios_base_address;
+};
+
+struct dc_context {
+ struct dc *dc;
+
+ void *driver_context; /* e.g. amdgpu_device */
+ struct dc_perf_trace *perf_trace;
+ void *cgs_device;
+
+ enum dce_environment dce_environment;
+ struct hw_asic_id asic_id;
+
+ /* todo: below should probably move to dc. to facilitate removal
+ * of AS we will store these here
+ */
+ enum dce_version dce_version;
+ struct dc_bios *dc_bios;
+ bool created_bios;
+ struct gpio_service *gpio_service;
+ uint32_t dc_sink_id_count;
+ uint32_t dc_stream_id_count;
+ uint32_t dc_edp_id_count;
+ uint64_t fbc_gpu_addr;
+ struct dc_dmub_srv *dmub_srv;
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+ struct cp_psp cp_psp;
+#endif
+
+};
+
/* DSC DPCD capabilities */
union dsc_slice_caps1 {
struct {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
index 2fb88e54a4bf..e14f99b4b0c3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
@@ -42,6 +42,11 @@
#define DC_LOGGER \
engine->ctx->logger
+#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
+#define IS_DC_I2CAUX_LOGGING_ENABLED() (false)
+#define LOG_FLAG_Error_I2cAux LOG_ERROR
+#define LOG_FLAG_I2cAux_DceAux LOG_I2C_AUX
+
#include "reg_helper.h"
#undef FN
@@ -71,6 +76,8 @@ enum {
#define DEFAULT_AUX_ENGINE_MULT 0
#define DEFAULT_AUX_ENGINE_LENGTH 69
+#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
+
static void release_engine(
struct dce_aux *engine)
{
@@ -621,6 +628,58 @@ int dce_aux_transfer_dmub_raw(struct ddc_service *ddc,
#define AUX_MAX_INVALID_REPLY_RETRIES 2
#define AUX_MAX_TIMEOUT_RETRIES 3
+static void dce_aux_log_payload(const char *payload_name,
+ unsigned char *payload, uint32_t length, uint32_t max_length_to_log)
+{
+ if (!IS_DC_I2CAUX_LOGGING_ENABLED())
+ return;
+
+ if (payload && length) {
+ char hex_str[128] = {0};
+ char *hex_str_ptr = &hex_str[0];
+ uint32_t hex_str_remaining = sizeof(hex_str);
+ unsigned char *payload_ptr = payload;
+ unsigned char *payload_max_to_log_ptr = payload_ptr + min(max_length_to_log, length);
+ unsigned int count;
+ char *padding = "";
+
+ while (payload_ptr < payload_max_to_log_ptr) {
+ count = snprintf_count(hex_str_ptr, hex_str_remaining, "%s%02X", padding, *payload_ptr);
+ padding = " ";
+ hex_str_remaining -= count;
+ hex_str_ptr += count;
+ payload_ptr++;
+ }
+
+ count = snprintf_count(hex_str_ptr, hex_str_remaining, " ");
+ hex_str_remaining -= count;
+ hex_str_ptr += count;
+
+ payload_ptr = payload;
+ while (payload_ptr < payload_max_to_log_ptr) {
+ count = snprintf_count(hex_str_ptr, hex_str_remaining, "%c",
+ *payload_ptr >= ' ' ? *payload_ptr : '.');
+ hex_str_remaining -= count;
+ hex_str_ptr += count;
+ payload_ptr++;
+ }
+
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_log_payload: %s: length=%u: data: %s%s",
+ payload_name,
+ length,
+ hex_str,
+ (length > max_length_to_log ? " (...)" : " "));
+ } else {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_log_payload: %s: length=%u: data: <empty payload>",
+ payload_name,
+ length);
+ }
+}
+
bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
struct aux_payload *payload)
{
@@ -646,7 +705,34 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
}
for (i = 0; i < AUX_MAX_RETRIES; i++) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: link_index=%u: START: retry %d of %d: address=0x%04x length=%u write=%d mot=%d",
+ ddc && ddc->link ? ddc->link->link_index : UINT_MAX,
+ i + 1,
+ (int)AUX_MAX_RETRIES,
+ payload->address,
+ payload->length,
+ (unsigned int) payload->write,
+ (unsigned int) payload->mot);
+ if (payload->write)
+ dce_aux_log_payload(" write", payload->data, payload->length, 16);
ret = dce_aux_transfer_raw(ddc, payload, &operation_result);
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: link_index=%u: END: retry %d of %d: address=0x%04x length=%u write=%d mot=%d: ret=%d operation_result=%d payload->reply=%u",
+ ddc && ddc->link ? ddc->link->link_index : UINT_MAX,
+ i + 1,
+ (int)AUX_MAX_RETRIES,
+ payload->address,
+ payload->length,
+ (unsigned int) payload->write,
+ (unsigned int) payload->mot,
+ ret,
+ (int)operation_result,
+ (unsigned int) *payload->reply);
+ if (!payload->write)
+ dce_aux_log_payload(" read", payload->data, ret > 0 ? ret : 0, 16);
switch (operation_result) {
case AUX_RET_SUCCESS:
@@ -655,30 +741,64 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
switch (*payload->reply) {
case AUX_TRANSACTION_REPLY_AUX_ACK:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_ACK");
if (!payload->write && payload->length != ret) {
- if (++aux_ack_retries >= AUX_MAX_RETRIES)
+ if (++aux_ack_retries >= AUX_MAX_RETRIES) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ LOG_FLAG_Error_I2cAux,
+ "dce_aux_transfer_with_retries: FAILURE: aux_ack_retries=%d >= AUX_MAX_RETRIES=%d",
+ aux_defer_retries,
+ AUX_MAX_RETRIES);
goto fail;
- else
+ } else {
udelay(300);
+ }
} else
return true;
break;
case AUX_TRANSACTION_REPLY_AUX_DEFER:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_DEFER");
+
/* polling_timeout_period is in us */
defer_time_in_ms += aux110->polling_timeout_period / 1000;
++aux_defer_retries;
fallthrough;
case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
+ if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER");
+
retry_on_defer = true;
fallthrough;
case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
+ if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK)
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK");
+
if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES
&& defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ LOG_FLAG_Error_I2cAux,
+ "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d && defer_time_in_ms=%d >= AUX_MAX_DEFER_TIMEOUT_MS=%d",
+ aux_defer_retries,
+ AUX_MIN_DEFER_RETRIES,
+ defer_time_in_ms,
+ AUX_MAX_DEFER_TIMEOUT_MS);
goto fail;
} else {
if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) ||
(*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: payload->defer_delay=%u",
+ payload->defer_delay);
if (payload->defer_delay > 1) {
msleep(payload->defer_delay);
defer_time_in_ms += payload->defer_delay;
@@ -691,37 +811,86 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
break;
case AUX_TRANSACTION_REPLY_I2C_DEFER:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_DEFER");
+
aux_defer_retries = 0;
- if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES)
+ if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ LOG_FLAG_Error_I2cAux,
+ "dce_aux_transfer_with_retries: FAILURE: aux_i2c_defer_retries=%d >= AUX_MAX_I2C_DEFER_RETRIES=%d",
+ aux_i2c_defer_retries,
+ AUX_MAX_I2C_DEFER_RETRIES);
goto fail;
+ }
break;
case AUX_TRANSACTION_REPLY_AUX_NACK:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_NACK");
+ goto fail;
+
case AUX_TRANSACTION_REPLY_HPD_DISCON:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_HPD_DISCON");
+ goto fail;
+
default:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ LOG_FLAG_Error_I2cAux,
+ "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: FAILURE: AUX_TRANSACTION_REPLY_* unknown, default case.");
goto fail;
}
break;
case AUX_RET_ERROR_INVALID_REPLY:
- if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES)
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_ERROR_INVALID_REPLY");
+ if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ LOG_FLAG_Error_I2cAux,
+ "dce_aux_transfer_with_retries: FAILURE: aux_invalid_reply_retries=%d >= AUX_MAX_INVALID_REPLY_RETRIES=%d",
+ aux_invalid_reply_retries,
+ AUX_MAX_INVALID_REPLY_RETRIES);
goto fail;
- else
+ } else
udelay(400);
break;
case AUX_RET_ERROR_TIMEOUT:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: AUX_RET_ERROR_TIMEOUT");
// Check whether a DEFER had occurred before the timeout.
// If so, treat timeout as a DEFER.
if (retry_on_defer) {
- if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES)
+ if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ LOG_FLAG_Error_I2cAux,
+ "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d",
+ aux_defer_retries,
+ AUX_MIN_DEFER_RETRIES);
goto fail;
- else if (payload->defer_delay > 0)
+ } else if (payload->defer_delay > 0) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: payload->defer_delay=%u",
+ payload->defer_delay);
msleep(payload->defer_delay);
+ }
} else {
- if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
+ if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) {
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ LOG_FLAG_Error_I2cAux,
+ "dce_aux_transfer_with_retries: FAILURE: aux_timeout_retries=%d >= AUX_MAX_TIMEOUT_RETRIES=%d",
+ aux_timeout_retries,
+ AUX_MAX_TIMEOUT_RETRIES);
goto fail;
- else {
+ } else {
/*
* DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts
* According to the DP spec there should be 3 retries total
@@ -736,12 +905,25 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
case AUX_RET_ERROR_ENGINE_ACQUIRE:
case AUX_RET_ERROR_UNKNOWN:
default:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
+ LOG_FLAG_I2cAux_DceAux,
+ "dce_aux_transfer_with_retries: Failure: operation_result=%d",
+ (int)operation_result);
goto fail;
}
}
fail:
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ LOG_FLAG_Error_I2cAux,
+ "dce_aux_transfer_with_retries: FAILURE");
if (!payload_reply)
payload->reply = NULL;
+
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ WPP_BIT_FLAG_DC_ERROR,
+ "AUX transaction failed. Result: %d",
+ operation_result);
+
return false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
index 10d42ae0cffe..aa8403bc4c83 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
@@ -29,6 +29,8 @@
#include "dmub/dmub_srv.h"
#include "core_types.h"
+#define DC_TRACE_LEVEL_MESSAGE(...) do {} while (0) /* do nothing */
+
#define MAX_PIPES 6
/*
@@ -96,10 +98,19 @@ static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state,
// Return invalid state when GPINT times out
*state = PSR_STATE_INVALID;
- // Assert if max retry hit
- if (retry_count >= 1000)
- ASSERT(0);
} while (++retry_count <= 1000 && *state == PSR_STATE_INVALID);
+
+ // Assert if max retry hit
+ if (retry_count >= 1000 && *state == PSR_STATE_INVALID) {
+ ASSERT(0);
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
+ WPP_BIT_FLAG_Firmware_PsrState,
+ "Unable to get PSR state from FW.");
+ } else
+ DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
+ WPP_BIT_FLAG_Firmware_PsrState,
+ "Got PSR state from FW. PSR state: %d, Retry count: %d",
+ *state, retry_count);
}
/*
@@ -207,7 +218,7 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_
cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL;
cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data);
cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;
- cmd.psr_set_level.psr_set_level_data.cmd_version = PSR_VERSION_1;
+ cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst;
dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
dc_dmub_srv_cmd_execute(dc->dmub_srv);
@@ -293,7 +304,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1;
copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled);
copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us;
- copy_settings_data->cmd_version = PSR_VERSION_1;
+ copy_settings_data->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
copy_settings_data->panel_inst = panel_inst;
dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
index 8d7e92d5d3e4..39485bdeb90e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
@@ -121,6 +121,10 @@ struct dcn_hubbub_registers {
uint32_t DCN_VM_AGP_BASE;
uint32_t DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB;
uint32_t DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB;
+ uint32_t DCN_VM_FAULT_ADDR_MSB;
+ uint32_t DCN_VM_FAULT_ADDR_LSB;
+ uint32_t DCN_VM_FAULT_CNTL;
+ uint32_t DCN_VM_FAULT_STATUS;
uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_A;
uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_B;
uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_C;
@@ -233,7 +237,19 @@ struct dcn_hubbub_registers {
type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C;\
type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D;\
type DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\
- type DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB
+ type DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\
+ type DCN_VM_FAULT_ADDR_MSB;\
+ type DCN_VM_FAULT_ADDR_LSB;\
+ type DCN_VM_ERROR_STATUS_CLEAR;\
+ type DCN_VM_ERROR_STATUS_MODE;\
+ type DCN_VM_ERROR_INTERRUPT_ENABLE;\
+ type DCN_VM_RANGE_FAULT_DISABLE;\
+ type DCN_VM_PRQ_FAULT_DISABLE;\
+ type DCN_VM_ERROR_STATUS;\
+ type DCN_VM_ERROR_VMID;\
+ type DCN_VM_ERROR_TABLE_LEVEL;\
+ type DCN_VM_ERROR_PIPE;\
+ type DCN_VM_ERROR_INTERRUPT_STATUS
#define HUBBUB_STUTTER_REG_FIELD_LIST(type) \
type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A;\
@@ -303,6 +319,7 @@ struct dcn_hubbub_registers {
type DET3_SIZE_CURRENT;\
type COMPBUF_SIZE;\
type COMPBUF_SIZE_CURRENT;\
+ type CONFIG_ERROR;\
type COMPBUF_RESERVED_SPACE_64B;\
type COMPBUF_RESERVED_SPACE_ZS;\
type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A;\
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 04303fe9c659..ea185c877323 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
@@ -871,6 +871,8 @@ void hubp1_read_state_common(struct hubp *hubp)
struct _vcs_dpi_display_dlg_regs_st *dlg_attr = &s->dlg_attr;
struct _vcs_dpi_display_ttu_regs_st *ttu_attr = &s->ttu_attr;
struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
+ uint32_t aperture_low_msb, aperture_low_lsb;
+ uint32_t aperture_high_msb, aperture_high_lsb;
/* Requester */
REG_GET(HUBPRET_CONTROL,
@@ -881,6 +883,22 @@ void hubp1_read_state_common(struct hubp *hubp)
MRQ_EXPANSION_MODE, &rq_regs->mrq_expansion_mode,
CRQ_EXPANSION_MODE, &rq_regs->crq_expansion_mode);
+ REG_GET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB,
+ MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, &aperture_low_msb);
+
+ REG_GET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB,
+ MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, &aperture_low_lsb);
+
+ REG_GET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB,
+ MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, &aperture_high_msb);
+
+ REG_GET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB,
+ MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, &aperture_high_lsb);
+
+ // On DCN1, aperture is broken down into MSB and LSB; only keep bits [47:18] to match later DCN format
+ rq_regs->aperture_low_addr = (aperture_low_msb << 26) | (aperture_low_lsb >> 6);
+ rq_regs->aperture_high_addr = (aperture_high_msb << 26) | (aperture_high_lsb >> 6);
+
/* DLG - Per hubp */
REG_GET_2(BLANK_OFFSET_0,
REFCYC_H_BLANK_END, &dlg_attr->refcyc_h_blank_end,
@@ -1037,6 +1055,17 @@ void hubp1_read_state_common(struct hubp *hubp)
QoS_LEVEL_LOW_WM, &s->qos_level_low_wm,
QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm);
+ REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS,
+ PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_lo);
+
+ REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH,
+ PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_hi);
+
+ REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS,
+ PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_lo);
+
+ REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH,
+ PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_hi);
}
void hubp1_read_state(struct hubp *hubp)
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 e2f2f6995935..9cb8c383d673 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
@@ -682,6 +682,10 @@ struct dcn_hubp_state {
uint32_t min_ttu_vblank;
uint32_t qos_level_low_wm;
uint32_t qos_level_high_wm;
+ uint32_t primary_surface_addr_lo;
+ uint32_t primary_surface_addr_hi;
+ uint32_t primary_meta_addr_lo;
+ uint32_t primary_meta_addr_hi;
};
struct dcn10_hubp {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index c545eddabdcc..df8a7718a85f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1502,25 +1502,22 @@ void dcn10_init_hw(struct dc *dc)
void dcn10_power_down_on_boot(struct dc *dc)
{
struct dc_link *edp_links[MAX_NUM_EDP];
- struct dc_link *edp_link;
+ struct dc_link *edp_link = NULL;
int edp_num;
int i = 0;
get_edp_links(dc, edp_links, &edp_num);
-
- if (edp_num) {
- for (i = 0; i < edp_num; i++) {
- edp_link = edp_links[i];
- if (edp_link->link_enc->funcs->is_dig_enabled &&
- edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
- dc->hwseq->funcs.edp_backlight_control &&
- dc->hwss.power_down &&
- dc->hwss.edp_power_control) {
- dc->hwseq->funcs.edp_backlight_control(edp_link, false);
- dc->hwss.power_down(dc);
- dc->hwss.edp_power_control(edp_link, false);
- }
- }
+ if (edp_num)
+ edp_link = edp_links[0];
+
+ if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
+ edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
+ dc->hwseq->funcs.edp_backlight_control &&
+ dc->hwss.power_down &&
+ dc->hwss.edp_power_control) {
+ dc->hwseq->funcs.edp_backlight_control(edp_link, false);
+ dc->hwss.power_down(dc);
+ dc->hwss.edp_power_control(edp_link, false);
} else {
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
@@ -3180,8 +3177,12 @@ void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
{
struct pipe_ctx *test_pipe;
- const struct rect *r1 = &pipe_ctx->plane_res.scl_data.recout, *r2;
+ const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data;
+ const struct rect *r1 = &scl_data->recout, *r2;
int r1_r = r1->x + r1->width, r1_b = r1->y + r1->height, r2_r, r2_b;
+ int cur_layer = pipe_ctx->plane_state->layer_index;
+ bool upper_pipe_exists = false;
+ struct fixed31_32 one = dc_fixpt_from_int(1);
/**
* Disable the cursor if there's another pipe above this with a
@@ -3199,8 +3200,17 @@ static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
if (r1->x >= r2->x && r1->y >= r2->y && r1_r <= r2_r && r1_b <= r2_b)
return true;
+
+ if (test_pipe->plane_state->layer_index < cur_layer)
+ upper_pipe_exists = true;
}
+ // if plane scaled, assume an upper plane can handle cursor if it exists.
+ if (upper_pipe_exists &&
+ (scl_data->ratios.horz.value != one.value ||
+ scl_data->ratios.vert.value != one.value))
+ return true;
+
return false;
}
@@ -3631,13 +3641,12 @@ enum dc_status dcn10_set_clock(struct dc *dc,
struct dc_clock_config clock_cfg = {0};
struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk;
- if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock)
- dc->clk_mgr->funcs->get_clock(dc->clk_mgr,
- context, clock_type, &clock_cfg);
-
- if (!dc->clk_mgr->funcs->get_clock)
+ if (!dc->clk_mgr || !dc->clk_mgr->funcs->get_clock)
return DC_FAIL_UNSUPPORTED_1;
+ dc->clk_mgr->funcs->get_clock(dc->clk_mgr,
+ context, clock_type, &clock_cfg);
+
if (clk_khz > clock_cfg.max_clock_khz)
return DC_FAIL_CLK_EXCEED_MAX;
@@ -3655,7 +3664,7 @@ enum dc_status dcn10_set_clock(struct dc *dc,
else
return DC_ERROR_UNEXPECTED;
- if (dc->clk_mgr && dc->clk_mgr->funcs->update_clocks)
+ if (dc->clk_mgr->funcs->update_clocks)
dc->clk_mgr->funcs->update_clocks(dc->clk_mgr,
context, true);
return DC_OK;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
index 3696faf12d86..37848f4577b1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
@@ -1388,6 +1388,12 @@ void optc1_read_otg_state(struct optc *optc1,
REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status);
+
+ REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL,
+ OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &s->vertical_interrupt2_en);
+
+ REG_GET(OTG_VERTICAL_INTERRUPT2_POSITION,
+ OTG_VERTICAL_INTERRUPT2_LINE_START, &s->vertical_interrupt2_line);
}
bool optc1_get_otg_active_size(struct timing_generator *optc,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
index 29d6fbe0093a..c50c29984d51 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
@@ -578,6 +578,8 @@ struct dcn_otg_state {
uint32_t underflow_occurred_status;
uint32_t otg_enabled;
uint32_t blank_enabled;
+ uint32_t vertical_interrupt2_en;
+ uint32_t vertical_interrupt2_line;
};
void optc1_read_otg_state(struct optc *optc1,
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 f1a08a7736ac..cf364ae93138 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
@@ -522,16 +522,21 @@ void enc1_stream_encoder_hdmi_set_stream_attribute(
switch (crtc_timing->display_color_depth) {
case COLOR_DEPTH_888:
REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0);
+ DC_LOG_DEBUG("HDMI source set to 24BPP deep color depth\n");
break;
case COLOR_DEPTH_101010:
if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
REG_UPDATE_2(HDMI_CONTROL,
HDMI_DEEP_COLOR_DEPTH, 1,
HDMI_DEEP_COLOR_ENABLE, 0);
+ DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \
+ "disabled for YCBCR422 pixel encoding\n");
} else {
REG_UPDATE_2(HDMI_CONTROL,
HDMI_DEEP_COLOR_DEPTH, 1,
HDMI_DEEP_COLOR_ENABLE, 1);
+ DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \
+ "enabled for YCBCR422 non-pixel encoding\n");
}
break;
case COLOR_DEPTH_121212:
@@ -539,16 +544,22 @@ void enc1_stream_encoder_hdmi_set_stream_attribute(
REG_UPDATE_2(HDMI_CONTROL,
HDMI_DEEP_COLOR_DEPTH, 2,
HDMI_DEEP_COLOR_ENABLE, 0);
+ DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \
+ "disabled for YCBCR422 pixel encoding\n");
} else {
REG_UPDATE_2(HDMI_CONTROL,
HDMI_DEEP_COLOR_DEPTH, 2,
HDMI_DEEP_COLOR_ENABLE, 1);
+ DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \
+ "enabled for non-pixel YCBCR422 encoding\n");
}
break;
case COLOR_DEPTH_161616:
REG_UPDATE_2(HDMI_CONTROL,
HDMI_DEEP_COLOR_DEPTH, 3,
HDMI_DEEP_COLOR_ENABLE, 1);
+ DC_LOG_DEBUG("HDMI source deep color depth enabled in" \
+ "reserved mode\n");
break;
default:
break;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
index 91a9305d42e8..aacb1fb5c73e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
@@ -605,6 +605,26 @@ static bool hubbub2_program_watermarks(
return wm_pending;
}
+void hubbub2_read_state(struct hubbub *hubbub, struct dcn_hubbub_state *hubbub_state)
+{
+ struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+
+ if (REG(DCN_VM_FAULT_ADDR_MSB))
+ hubbub_state->vm_fault_addr_msb = REG_READ(DCN_VM_FAULT_ADDR_MSB);
+
+ if (REG(DCN_VM_FAULT_ADDR_LSB))
+ hubbub_state->vm_fault_addr_msb = REG_READ(DCN_VM_FAULT_ADDR_LSB);
+
+ if (REG(DCN_VM_FAULT_CNTL))
+ REG_GET(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, &hubbub_state->vm_error_mode);
+
+ if (REG(DCN_VM_FAULT_STATUS)) {
+ REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, &hubbub_state->vm_error_status);
+ REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, &hubbub_state->vm_error_vmid);
+ REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, &hubbub_state->vm_error_pipe);
+ }
+}
+
static const struct hubbub_funcs hubbub2_funcs = {
.update_dchub = hubbub2_update_dchub,
.init_dchub_sys_ctx = hubbub2_init_dchub_sys_ctx,
@@ -617,6 +637,7 @@ static const struct hubbub_funcs hubbub2_funcs = {
.program_watermarks = hubbub2_program_watermarks,
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
.allow_self_refresh_control = hubbub1_allow_self_refresh_control,
+ .hubbub_read_state = hubbub2_read_state,
};
void hubbub2_construct(struct dcn20_hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h
index 10af257d90ef..2f6146bf1d32 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h
@@ -29,16 +29,6 @@
#include "dcn10/dcn10_hubbub.h"
#include "dcn20_vmid.h"
-#define HUBBUB_REG_LIST_DCN20_COMMON()\
- HUBBUB_REG_LIST_DCN_COMMON(), \
- SR(DCHUBBUB_CRC_CTRL), \
- SR(DCN_VM_FB_LOCATION_BASE),\
- SR(DCN_VM_FB_LOCATION_TOP),\
- SR(DCN_VM_FB_OFFSET),\
- SR(DCN_VM_AGP_BOT),\
- SR(DCN_VM_AGP_TOP),\
- SR(DCN_VM_AGP_BASE)
-
#define TO_DCN20_HUBBUB(hubbub)\
container_of(hubbub, struct dcn20_hubbub, base)
@@ -50,7 +40,11 @@
SR(DCN_VM_FB_OFFSET),\
SR(DCN_VM_AGP_BOT),\
SR(DCN_VM_AGP_TOP),\
- SR(DCN_VM_AGP_BASE)
+ SR(DCN_VM_AGP_BASE),\
+ SR(DCN_VM_FAULT_ADDR_MSB), \
+ SR(DCN_VM_FAULT_ADDR_LSB), \
+ SR(DCN_VM_FAULT_CNTL), \
+ SR(DCN_VM_FAULT_STATUS)
#define HUBBUB_REG_LIST_DCN20(id)\
HUBBUB_REG_LIST_DCN20_COMMON(), \
@@ -71,7 +65,19 @@
HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \
HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \
HUBBUB_SF(DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB, DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh), \
- HUBBUB_SF(DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh)
+ HUBBUB_SF(DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
struct dcn20_hubbub {
struct hubbub base;
@@ -131,4 +137,7 @@ void hubbub2_get_dchub_ref_freq(struct hubbub *hubbub,
void hubbub2_wm_read_state(struct hubbub *hubbub,
struct dcn_hubbub_wm *wm);
+void hubbub2_read_state(struct hubbub *hubbub,
+ struct dcn_hubbub_state *hubbub_state);
+
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
index 7e54058715aa..5adf42a7cc27 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
@@ -1080,6 +1080,12 @@ void hubp2_read_state_common(struct hubp *hubp)
MRQ_EXPANSION_MODE, &rq_regs->mrq_expansion_mode,
CRQ_EXPANSION_MODE, &rq_regs->crq_expansion_mode);
+ REG_GET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR,
+ MC_VM_SYSTEM_APERTURE_HIGH_ADDR, &rq_regs->aperture_high_addr);
+
+ REG_GET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR,
+ MC_VM_SYSTEM_APERTURE_LOW_ADDR, &rq_regs->aperture_low_addr);
+
/* DLG - Per hubp */
REG_GET_2(BLANK_OFFSET_0,
REFCYC_H_BLANK_END, &dlg_attr->refcyc_h_blank_end,
@@ -1236,6 +1242,17 @@ void hubp2_read_state_common(struct hubp *hubp)
QoS_LEVEL_LOW_WM, &s->qos_level_low_wm,
QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm);
+ REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS,
+ PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_lo);
+
+ REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH,
+ PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_hi);
+
+ REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS,
+ PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_lo);
+
+ REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH,
+ PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_hi);
}
void hubp2_read_state(struct hubp *hubp)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 5c2853654cca..a47ba1d45be9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1723,13 +1723,15 @@ void dcn20_program_front_end_for_ctx(
pipe = pipe->bottom_pipe;
}
- /* Program secondary blending tree and writeback pipes */
- pipe = &context->res_ctx.pipe_ctx[i];
- if (!pipe->prev_odm_pipe && pipe->stream->num_wb_info > 0
- && (pipe->update_flags.raw || pipe->plane_state->update_flags.raw || pipe->stream->update_flags.raw)
- && hws->funcs.program_all_writeback_pipes_in_tree)
- hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
}
+ /* Program secondary blending tree and writeback pipes */
+ pipe = &context->res_ctx.pipe_ctx[i];
+ if (!pipe->top_pipe && !pipe->prev_odm_pipe
+ && pipe->stream && pipe->stream->num_wb_info > 0
+ && (pipe->update_flags.raw || (pipe->plane_state && pipe->plane_state->update_flags.raw)
+ || pipe->stream->update_flags.raw)
+ && hws->funcs.program_all_writeback_pipes_in_tree)
+ hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index b173fa3653b5..e3e01b17c164 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -35,6 +35,8 @@
#include "include/irq_service_interface.h"
#include "dcn20/dcn20_resource.h"
+#include "dml/dcn2x/dcn2x.h"
+
#include "dcn10/dcn10_hubp.h"
#include "dcn10/dcn10_ipp.h"
#include "dcn20_hubbub.h"
@@ -1974,43 +1976,6 @@ void dcn20_split_stream_for_mpc(
ASSERT(primary_pipe->plane_state);
}
-void dcn20_populate_dml_writeback_from_context(
- struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes)
-{
- int pipe_cnt, i;
-
- for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
- struct dc_writeback_info *wb_info = &res_ctx->pipe_ctx[i].stream->writeback_info[0];
-
- if (!res_ctx->pipe_ctx[i].stream)
- continue;
-
- /* Set writeback information */
- pipes[pipe_cnt].dout.wb_enable = (wb_info->wb_enabled == true) ? 1 : 0;
- pipes[pipe_cnt].dout.num_active_wb++;
- pipes[pipe_cnt].dout.wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_height;
- pipes[pipe_cnt].dout.wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_width;
- pipes[pipe_cnt].dout.wb.wb_dst_width = wb_info->dwb_params.dest_width;
- pipes[pipe_cnt].dout.wb.wb_dst_height = wb_info->dwb_params.dest_height;
- pipes[pipe_cnt].dout.wb.wb_htaps_luma = 1;
- pipes[pipe_cnt].dout.wb.wb_vtaps_luma = 1;
- pipes[pipe_cnt].dout.wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
- pipes[pipe_cnt].dout.wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
- pipes[pipe_cnt].dout.wb.wb_hratio = 1.0;
- pipes[pipe_cnt].dout.wb.wb_vratio = 1.0;
- if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
- if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
- pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_8;
- else
- pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_10;
- } else
- pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_444_32;
-
- pipe_cnt++;
- }
-
-}
-
int dcn20_populate_dml_pipes_from_context(
struct dc *dc,
struct dc_state *context,
@@ -2392,7 +2357,9 @@ int dcn20_populate_dml_pipes_from_context(
}
/* populate writeback information */
+ DC_FP_START();
dc->res_pool->funcs->populate_dml_writeback_from_context(dc, res_ctx, pipes);
+ DC_FP_END();
return pipe_cnt;
}
@@ -2462,7 +2429,7 @@ void dcn20_set_mcif_arb_params(
wb_arb_params->cli_watermark[k] = get_wm_writeback_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
wb_arb_params->pstate_watermark[k] = get_wm_writeback_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
}
- wb_arb_params->time_per_pixel = 16.0 / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; /* 4 bit fraction, ms */
+ wb_arb_params->time_per_pixel = 16.0 * 1000 / (context->res_ctx.pipe_ctx[i].stream->phy_pix_clk / 1000); /* 4 bit fraction, ms */
wb_arb_params->slice_lines = 32;
wb_arb_params->arbitration_slice = 2;
wb_arb_params->max_scaled_time = dcn20_calc_max_scaled_time(wb_arb_params->time_per_pixel,
@@ -2531,16 +2498,16 @@ struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
* pick that pipe as secondary
* Same logic applies for ODM pipes
*/
- if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
- preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
+ if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
+ preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
secondary_pipe->pipe_idx = preferred_pipe_idx;
}
}
if (secondary_pipe == NULL &&
- dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
- preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
+ dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
+ preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
secondary_pipe->pipe_idx = preferred_pipe_idx;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
index c8f3127bbcdf..6ec8ff45f0f7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
@@ -58,8 +58,6 @@ struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer(
struct dc_state *state,
const struct resource_pool *pool,
struct dc_stream_state *stream);
-void dcn20_populate_dml_writeback_from_context(
- struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes);
struct stream_encoder *dcn20_stream_encoder_create(
enum engine_id eng_id,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
index 42fbb5e6d505..36044cb8ec83 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
@@ -701,6 +701,7 @@ static const struct hubbub_funcs hubbub21_funcs = {
.program_watermarks = hubbub21_program_watermarks,
.allow_self_refresh_control = hubbub1_allow_self_refresh_control,
.apply_DEDCN21_147_wa = hubbub21_apply_DEDCN21_147_wa,
+ .hubbub_read_state = hubbub2_read_state,
};
void hubbub21_construct(struct dcn20_hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h
index ef3ef28509ed..d8eb2bb7282c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h
@@ -108,7 +108,19 @@
HUBBUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET, mask_sh), \
HUBBUB_SF(DCN_VM_AGP_BOT, AGP_BOT, mask_sh), \
HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \
- HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh)
+ HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
void dcn21_dchvm_init(struct hubbub *hubbub);
int hubbub21_init_dchub(struct hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
index b0c9180b808f..3de1bcf9b3d8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
@@ -833,7 +833,7 @@ static struct hubp_funcs dcn21_hubp_funcs = {
.dmdata_set_attributes = hubp2_dmdata_set_attributes,
.dmdata_load = hubp2_dmdata_load,
.dmdata_status_done = hubp2_dmdata_status_done,
- .hubp_read_state = hubp1_read_state,
+ .hubp_read_state = hubp2_read_state,
.hubp_clear_underflow = hubp1_clear_underflow,
.hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl,
.hubp_init = hubp21_init,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index bf0a198eae15..fbbdf9976183 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -35,6 +35,8 @@
#include "include/irq_service_interface.h"
#include "dcn20/dcn20_resource.h"
+#include "dml/dcn2x/dcn2x.h"
+
#include "clk_mgr.h"
#include "dcn10/dcn10_hubp.h"
#include "dcn10/dcn10_ipp.h"
@@ -884,7 +886,8 @@ static const struct dc_debug_options debug_defaults_drv = {
.disable_48mhz_pwrdwn = false,
.usbc_combo_phy_reset_wa = true,
.dmub_command_table = true,
- .use_max_lb = true
+ .use_max_lb = true,
+ .optimize_edp_link_rate = true
};
static const struct dc_debug_options debug_defaults_diags = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
index 3fe9e41e4dbd..6a3d3a0ec0a3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
@@ -49,6 +49,11 @@
static void dwb3_get_reg_field_ogam(struct dcn30_dwbc *dwbc30,
struct dcn3_xfer_func_reg *reg)
{
+ reg->shifts.field_region_start_base = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_BASE_B;
+ reg->masks.field_region_start_base = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_BASE_B;
+ reg->shifts.field_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_OFFSET_B;
+ reg->masks.field_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_OFFSET_B;
+
reg->shifts.exp_region0_lut_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
reg->masks.exp_region0_lut_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
reg->shifts.exp_region0_num_segments = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
@@ -66,8 +71,6 @@ static void dwb3_get_reg_field_ogam(struct dcn30_dwbc *dwbc30,
reg->masks.field_region_end_base = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_BASE_B;
reg->shifts.field_region_linear_slope = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
reg->masks.field_region_linear_slope = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
- reg->masks.field_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_OFFSET_B;
- reg->shifts.field_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_OFFSET_B;
reg->shifts.exp_region_start = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_B;
reg->masks.exp_region_start = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_B;
reg->shifts.exp_resion_start_segment = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
@@ -147,18 +150,19 @@ static enum dc_lut_mode dwb3_get_ogam_current(
uint32_t state_mode;
uint32_t ram_select;
- REG_GET(DWB_OGAM_CONTROL,
- DWB_OGAM_MODE, &state_mode);
- REG_GET(DWB_OGAM_CONTROL,
- DWB_OGAM_SELECT, &ram_select);
+ REG_GET_2(DWB_OGAM_CONTROL,
+ DWB_OGAM_MODE_CURRENT, &state_mode,
+ DWB_OGAM_SELECT_CURRENT, &ram_select);
if (state_mode == 0) {
mode = LUT_BYPASS;
} else if (state_mode == 2) {
if (ram_select == 0)
mode = LUT_RAM_A;
- else
+ else if (ram_select == 1)
mode = LUT_RAM_B;
+ else
+ mode = LUT_BYPASS;
} else {
// Reserved value
mode = LUT_BYPASS;
@@ -172,10 +176,10 @@ static void dwb3_configure_ogam_lut(
struct dcn30_dwbc *dwbc30,
bool is_ram_a)
{
- REG_UPDATE(DWB_OGAM_LUT_CONTROL,
- DWB_OGAM_LUT_READ_COLOR_SEL, 7);
- REG_UPDATE(DWB_OGAM_CONTROL,
- DWB_OGAM_SELECT, is_ram_a == true ? 0 : 1);
+ REG_UPDATE_2(DWB_OGAM_LUT_CONTROL,
+ DWB_OGAM_LUT_WRITE_COLOR_MASK, 7,
+ DWB_OGAM_LUT_HOST_SEL, (is_ram_a == true) ? 0 : 1);
+
REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0);
}
@@ -185,17 +189,45 @@ static void dwb3_program_ogam_pwl(struct dcn30_dwbc *dwbc30,
{
uint32_t i;
- // triple base implementation
- for (i = 0; i < num/2; i++) {
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].red_reg);
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].green_reg);
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].blue_reg);
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].red_reg);
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].green_reg);
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].blue_reg);
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].red_reg);
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].green_reg);
- REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].blue_reg);
+ uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
+ uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg;
+ uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg;
+
+ if (is_rgb_equal(rgb, num)) {
+ for (i = 0 ; i < num; i++)
+ REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].red_reg);
+
+ REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_red);
+
+ } else {
+
+ REG_UPDATE(DWB_OGAM_LUT_CONTROL,
+ DWB_OGAM_LUT_WRITE_COLOR_MASK, 4);
+
+ for (i = 0 ; i < num; i++)
+ REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].red_reg);
+
+ REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_red);
+
+ REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0);
+
+ REG_UPDATE(DWB_OGAM_LUT_CONTROL,
+ DWB_OGAM_LUT_WRITE_COLOR_MASK, 2);
+
+ for (i = 0 ; i < num; i++)
+ REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].green_reg);
+
+ REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_green);
+
+ REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0);
+
+ REG_UPDATE(DWB_OGAM_LUT_CONTROL,
+ DWB_OGAM_LUT_WRITE_COLOR_MASK, 1);
+
+ for (i = 0 ; i < num; i++)
+ REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].blue_reg);
+
+ REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_blue);
}
}
@@ -211,6 +243,8 @@ static bool dwb3_program_ogam_lut(
return false;
}
+ REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 2);
+
current_mode = dwb3_get_ogam_current(dwbc30);
if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
next_mode = LUT_RAM_B;
@@ -227,8 +261,7 @@ static bool dwb3_program_ogam_lut(
dwb3_program_ogam_pwl(
dwbc30, params->rgb_resulted, params->hw_points_num);
- REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 2);
- REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_SELECT, next_mode == LUT_RAM_A ? 0 : 1);
+ REG_UPDATE(DWB_OGAM_CONTROL, DWB_OGAM_SELECT, next_mode == LUT_RAM_A ? 0 : 1);
return true;
}
@@ -271,14 +304,19 @@ static void dwb3_program_gamut_remap(
struct color_matrices_reg gam_regs;
- REG_UPDATE(DWB_GAMUT_REMAP_COEF_FORMAT, DWB_GAMUT_REMAP_COEF_FORMAT, coef_format);
-
if (regval == NULL || select == CM_GAMUT_REMAP_MODE_BYPASS) {
REG_SET(DWB_GAMUT_REMAP_MODE, 0,
DWB_GAMUT_REMAP_MODE, 0);
return;
}
+ REG_UPDATE(DWB_GAMUT_REMAP_COEF_FORMAT, DWB_GAMUT_REMAP_COEF_FORMAT, coef_format);
+
+ gam_regs.shifts.csc_c11 = dwbc30->dwbc_shift->DWB_GAMUT_REMAPA_C11;
+ gam_regs.masks.csc_c11 = dwbc30->dwbc_mask->DWB_GAMUT_REMAPA_C11;
+ gam_regs.shifts.csc_c12 = dwbc30->dwbc_shift->DWB_GAMUT_REMAPA_C12;
+ gam_regs.masks.csc_c12 = dwbc30->dwbc_mask->DWB_GAMUT_REMAPA_C12;
+
switch (select) {
case CM_GAMUT_REMAP_MODE_RAMA_COEFF:
gam_regs.csc_c11_c12 = REG(DWB_GAMUT_REMAPA_C11_C12);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
index c0980da6dc49..f4414de96acc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c
@@ -451,6 +451,7 @@ static const struct hubbub_funcs hubbub30_funcs = {
.force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
.force_pstate_change_control = hubbub3_force_pstate_change_control,
.init_watermarks = hubbub3_init_watermarks,
+ .hubbub_read_state = hubbub2_read_state,
};
void hubbub3_construct(struct dcn20_hubbub *hubbub3,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h
index c0bd0fb09455..7b597908b937 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h
@@ -87,7 +87,19 @@
HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, mask_sh), \
HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, mask_sh), \
HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, mask_sh), \
- HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, mask_sh)
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
void hubbub3_construct(struct dcn20_hubbub *hubbub3,
struct dc_context *ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
index c68e3a708a33..fafed1e4a998 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
@@ -398,12 +398,22 @@ void dcn30_program_all_writeback_pipes_in_tree(
for (i_pipe = 0; i_pipe < dc->res_pool->pipe_count; i_pipe++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i_pipe];
+ if (!pipe_ctx->plane_state)
+ continue;
+
if (pipe_ctx->plane_state == wb_info.writeback_source_plane) {
wb_info.mpcc_inst = pipe_ctx->plane_res.mpcc_inst;
break;
}
}
- ASSERT(wb_info.mpcc_inst != -1);
+
+ if (wb_info.mpcc_inst == -1) {
+ /* Disable writeback pipe and disconnect from MPCC
+ * if source plane has been removed
+ */
+ dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst);
+ continue;
+ }
ASSERT(wb_info.dwb_pipe_inst < dc->res_pool->res_cap->num_dwb);
dwb = dc->res_pool->dwbc[wb_info.dwb_pipe_inst];
@@ -580,22 +590,19 @@ void dcn30_init_hw(struct dc *dc)
*/
if (dc->config.power_down_display_on_boot) {
struct dc_link *edp_links[MAX_NUM_EDP];
- struct dc_link *edp_link;
+ struct dc_link *edp_link = NULL;
get_edp_links(dc, edp_links, &edp_num);
- if (edp_num) {
- for (i = 0; i < edp_num; i++) {
- edp_link = edp_links[i];
- if (edp_link->link_enc->funcs->is_dig_enabled &&
- edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
- dc->hwss.edp_backlight_control &&
- dc->hwss.power_down &&
- dc->hwss.edp_power_control) {
- dc->hwss.edp_backlight_control(edp_link, false);
- dc->hwss.power_down(dc);
- dc->hwss.edp_power_control(edp_link, false);
- }
- }
+ if (edp_num)
+ edp_link = edp_links[0];
+ if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
+ edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
+ dc->hwss.edp_backlight_control &&
+ dc->hwss.power_down &&
+ dc->hwss.edp_power_control) {
+ dc->hwss.edp_backlight_control(edp_link, false);
+ dc->hwss.power_down(dc);
+ dc->hwss.edp_power_control(edp_link, false);
} else {
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
index f37e8254df21..089be7347591 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
@@ -109,11 +109,9 @@ void optc3_lock(struct timing_generator *optc)
REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
OTG_MASTER_UPDATE_LOCK, 1);
- /* Should be fast, status does not update on maximus */
- if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
- REG_WAIT(OTG_MASTER_UPDATE_LOCK,
- UPDATE_LOCK_STATUS, 1,
- 1, 10);
+ REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+ UPDATE_LOCK_STATUS, 1,
+ 1, 10);
}
void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
index 28e15ebf2f43..a0de309475a9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -92,7 +92,7 @@
#define DC_LOGGER_INIT(logger)
struct _vcs_dpi_ip_params_st dcn3_0_ip = {
- .use_min_dcfclk = 1,
+ .use_min_dcfclk = 0,
.clamp_min_dcfclk = 0,
.odm_capable = 1,
.gpuvm_enable = 0,
@@ -2398,16 +2398,37 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
if (bw_params->clk_table.entries[0].memclk_mhz) {
+ int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0;
+
+ for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
+ if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
+ max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
+ if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
+ max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
+ if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
+ max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
+ if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
+ max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
+ }
+
+ if (!max_dcfclk_mhz)
+ max_dcfclk_mhz = dcn3_0_soc.clock_limits[0].dcfclk_mhz;
+ if (!max_dispclk_mhz)
+ max_dispclk_mhz = dcn3_0_soc.clock_limits[0].dispclk_mhz;
+ if (!max_dppclk_mhz)
+ max_dppclk_mhz = dcn3_0_soc.clock_limits[0].dppclk_mhz;
+ if (!max_phyclk_mhz)
+ max_phyclk_mhz = dcn3_0_soc.clock_limits[0].phyclk_mhz;
- if (bw_params->clk_table.entries[1].dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
+ if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
// If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array
- dcfclk_sta_targets[num_dcfclk_sta_targets] = bw_params->clk_table.entries[1].dcfclk_mhz;
+ dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz;
num_dcfclk_sta_targets++;
- } else if (bw_params->clk_table.entries[1].dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
+ } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
// If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates
for (i = 0; i < num_dcfclk_sta_targets; i++) {
- if (dcfclk_sta_targets[i] > bw_params->clk_table.entries[1].dcfclk_mhz) {
- dcfclk_sta_targets[i] = bw_params->clk_table.entries[1].dcfclk_mhz;
+ if (dcfclk_sta_targets[i] > max_dcfclk_mhz) {
+ dcfclk_sta_targets[i] = max_dcfclk_mhz;
break;
}
}
@@ -2447,7 +2468,7 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
} else {
- if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= bw_params->clk_table.entries[1].dcfclk_mhz) {
+ if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
} else {
@@ -2462,11 +2483,12 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
}
while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES &&
- optimal_dcfclk_for_uclk[j] <= bw_params->clk_table.entries[1].dcfclk_mhz) {
+ optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
}
+ dcn3_0_soc.num_states = num_states;
for (i = 0; i < dcn3_0_soc.num_states; i++) {
dcn3_0_soc.clock_limits[i].state = i;
dcn3_0_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i];
@@ -2474,9 +2496,9 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
dcn3_0_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i];
/* Fill all states with max values of all other clocks */
- dcn3_0_soc.clock_limits[i].dispclk_mhz = bw_params->clk_table.entries[1].dispclk_mhz;
- dcn3_0_soc.clock_limits[i].dppclk_mhz = bw_params->clk_table.entries[1].dppclk_mhz;
- dcn3_0_soc.clock_limits[i].phyclk_mhz = bw_params->clk_table.entries[1].phyclk_mhz;
+ dcn3_0_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz;
+ dcn3_0_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz;
+ dcn3_0_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz;
dcn3_0_soc.clock_limits[i].dtbclk_mhz = dcn3_0_soc.clock_limits[0].dtbclk_mhz;
/* These clocks cannot come from bw_params, always fill from dcn3_0_soc[1] */
/* FCLK, PHYCLK_D18, SOCCLK, DSCCLK */
@@ -2489,11 +2511,6 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
if (dc->current_state)
dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30);
}
-
- /* re-init DML with updated bb */
- dml_init_instance(&dc->dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30);
- if (dc->current_state)
- dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30);
}
static const struct resource_funcs dcn30_res_pool_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
index a0b96b3c083f..1e3bd2e9cdcc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c
@@ -62,6 +62,7 @@ static const struct hubbub_funcs hubbub301_funcs = {
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
.force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
.force_pstate_change_control = hubbub3_force_pstate_change_control,
+ .hubbub_read_state = hubbub2_read_state,
};
void hubbub301_construct(struct dcn20_hubbub *hubbub3,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
index bb9648488900..90c73a1cb986 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
@@ -124,8 +124,8 @@ static void dcn31_program_compbuf_size(struct hubbub *hubbub, unsigned int compb
ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
+ hubbub2->det3_size + compbuf_size_segments <= hubbub2->crb_size_segs);
REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_segments);
- REG_WAIT(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, compbuf_size_segments, 1, 100);
hubbub2->compbuf_size_segments = compbuf_size_segments;
+ ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &compbuf_size_segments) && !compbuf_size_segments);
}
}
@@ -876,7 +876,33 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub,
static int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub,
struct dcn_hubbub_phys_addr_config *pa_config)
{
- hubbub3_init_dchub_sys_ctx(hubbub, pa_config);
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ struct dcn_vmid_page_table_config phys_config;
+
+ REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
+ FB_BASE, pa_config->system_aperture.fb_base >> 24);
+ REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
+ FB_TOP, pa_config->system_aperture.fb_top >> 24);
+ REG_SET(DCN_VM_FB_OFFSET, 0,
+ FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);
+ REG_SET(DCN_VM_AGP_BOT, 0,
+ AGP_BOT, pa_config->system_aperture.agp_bot >> 24);
+ REG_SET(DCN_VM_AGP_TOP, 0,
+ AGP_TOP, pa_config->system_aperture.agp_top >> 24);
+ REG_SET(DCN_VM_AGP_BASE, 0,
+ AGP_BASE, pa_config->system_aperture.agp_base >> 24);
+
+ if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
+ phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
+ phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
+ phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
+ phys_config.depth = 0;
+ phys_config.block_size = 0;
+ // Init VMID 0 based on PA config
+ dcn20_vmid_setup(&hubbub2->vmid[0], &phys_config);
+
+ dcn20_vmid_setup(&hubbub2->vmid[15], &phys_config);
+ }
dcn21_dchvm_init(hubbub);
@@ -934,7 +960,8 @@ static const struct hubbub_funcs hubbub31_funcs = {
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
.program_det_size = dcn31_program_det_size,
.program_compbuf_size = dcn31_program_compbuf_size,
- .init_crb = dcn31_init_crb
+ .init_crb = dcn31_init_crb,
+ .hubbub_read_state = hubbub2_read_state,
};
void hubbub31_construct(struct dcn20_hubbub *hubbub31,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h
index 8ec98cbcbd47..e3a654bf04e8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h
@@ -98,6 +98,7 @@
HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, mask_sh),\
HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\
HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\
HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\
HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_ZS, mask_sh),\
HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, mask_sh), \
@@ -107,7 +108,19 @@
HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, mask_sh), \
HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, mask_sh), \
HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, mask_sh), \
- HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh)
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
void hubbub31_construct(struct dcn20_hubbub *hubbub3,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
index 8a2119d8ca0d..3f2333ec67e2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
@@ -226,6 +226,7 @@ void dcn31_init_hw(struct dc *dc)
if (dc->config.power_down_display_on_boot) {
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link;
+ bool power_down = false;
get_edp_links(dc, edp_links, &edp_num);
if (edp_num) {
@@ -239,9 +240,11 @@ void dcn31_init_hw(struct dc *dc)
dc->hwss.edp_backlight_control(edp_link, false);
dc->hwss.power_down(dc);
dc->hwss.edp_power_control(edp_link, false);
+ power_down = true;
}
}
- } else {
+ }
+ if (!power_down) {
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
@@ -607,20 +610,3 @@ bool dcn31_is_abm_supported(struct dc *dc,
}
return false;
}
-
-static void apply_riommu_invalidation_wa(struct dc *dc)
-{
- struct dce_hwseq *hws = dc->hwseq;
-
- if (!hws->wa.early_riommu_invalidation)
- return;
-
- REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, 0);
-}
-
-void dcn31_init_pipes(struct dc *dc, struct dc_state *context)
-{
- dcn10_init_pipes(dc, context);
- apply_riommu_invalidation_wa(dc);
-
-}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
index b30d923471cb..40011cd3c8ef 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
@@ -104,7 +104,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
};
static const struct hwseq_private_funcs dcn31_private_funcs = {
- .init_pipes = dcn31_init_pipes,
+ .init_pipes = dcn10_init_pipes,
.update_plane_addr = dcn20_update_plane_addr,
.plane_atomic_disconnect = dcn10_plane_atomic_disconnect,
.update_mpcc = dcn20_update_mpcc,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
index cd3248dc31d8..a7702d3c75cd 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
@@ -1302,7 +1302,6 @@ static struct dce_hwseq *dcn31_hwseq_create(
hws->regs = &hwseq_reg;
hws->shifts = &hwseq_shift;
hws->masks = &hwseq_mask;
- hws->wa.early_riommu_invalidation = true;
}
return hws;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
index 45862167e6ce..56055df2e8d2 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
@@ -58,6 +58,8 @@ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
ifdef CONFIG_DRM_AMD_DC_DCN
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags)
@@ -70,6 +72,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(fram
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_rcflags)
@@ -91,6 +94,7 @@ DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \
ifdef CONFIG_DRM_AMD_DC_DCN
DML += display_mode_vba.o dcn20/display_rq_dlg_calc_20.o dcn20/display_mode_vba_20.o
+DML += dcn2x/dcn2x.o
DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o
DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
index 799bae229e67..2091dd8c252d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
@@ -488,7 +488,7 @@ static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib,
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
- // a meta element covers one 256b block of the the data surface.
+ // a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
- log2_meta_req_height;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
index 6a6d5970d1d5..1a0c14e465fa 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
@@ -488,7 +488,7 @@ static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib,
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
- // a meta element covers one 256b block of the the data surface.
+ // a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
- log2_meta_req_height;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
index 6655bb99fdfd..4136eb8256cb 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
@@ -2270,7 +2270,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
&locals->UrgentBurstFactorLumaPre[k],
&locals->UrgentBurstFactorChroma[k],
&locals->UrgentBurstFactorChromaPre[k],
- &locals->NotEnoughUrgentLatencyHiding,
+ &locals->NotEnoughUrgentLatencyHiding[0][0],
&locals->NotEnoughUrgentLatencyHidingPre);
if (mode_lib->vba.UseUrgentBurstBandwidth == false) {
@@ -2303,7 +2303,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
}
mode_lib->vba.FractionOfUrgentBandwidth = MaxTotalRDBandwidthNoUrgentBurst / mode_lib->vba.ReturnBW;
- if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && locals->NotEnoughUrgentLatencyHiding == 0 && locals->NotEnoughUrgentLatencyHidingPre == 0 && !VRatioPrefetchMoreThan4
+ if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && locals->NotEnoughUrgentLatencyHiding[0][0] == 0 &&
+ locals->NotEnoughUrgentLatencyHidingPre == 0 && !VRatioPrefetchMoreThan4
&& !DestinationLineTimesForPrefetchLessThan2)
mode_lib->vba.PrefetchModeSupported = true;
else {
@@ -4824,7 +4825,7 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
&locals->UrgentBurstFactorLumaPre[k],
&locals->UrgentBurstFactorChroma[k],
&locals->UrgentBurstFactorChromaPre[k],
- &locals->NotEnoughUrgentLatencyHiding,
+ &locals->NotEnoughUrgentLatencyHiding[0][0],
&locals->NotEnoughUrgentLatencyHidingPre);
if (mode_lib->vba.UseUrgentBurstBandwidth == false) {
@@ -4851,13 +4852,13 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
}
locals->BandwidthWithoutPrefetchSupported[i][0] = true;
if (mode_lib->vba.MaximumReadBandwidthWithoutPrefetch > locals->ReturnBWPerState[i][0]
- || locals->NotEnoughUrgentLatencyHiding == 1) {
+ || locals->NotEnoughUrgentLatencyHiding[0][0] == 1) {
locals->BandwidthWithoutPrefetchSupported[i][0] = false;
}
locals->PrefetchSupported[i][j] = true;
if (mode_lib->vba.MaximumReadBandwidthWithPrefetch > locals->ReturnBWPerState[i][0]
- || locals->NotEnoughUrgentLatencyHiding == 1
+ || locals->NotEnoughUrgentLatencyHiding[0][0] == 1
|| locals->NotEnoughUrgentLatencyHidingPre == 1) {
locals->PrefetchSupported[i][j] = false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
index dc1c81a6e377..287e31052b30 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
@@ -482,7 +482,7 @@ static void get_meta_and_pte_attr(
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
- // a meta element covers one 256b block of the the data surface.
+ // a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
- log2_meta_req_height;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c b/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c
new file mode 100644
index 000000000000..c58522436291
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "resource.h"
+
+#include "dcn2x.h"
+
+/**
+ * DOC: DCN2x FPU manipulation Overview
+ *
+ * The DCN architecture relies on FPU operations, which require special
+ * compilation flags and the use of kernel_fpu_begin/end functions; ideally, we
+ * want to avoid spreading FPU access across multiple files. With this idea in
+ * mind, this file aims to centralize all DCN20 and DCN2.1 (DCN2x) functions
+ * that require FPU access in a single place. Code in this file follows the
+ * following code pattern:
+ *
+ * 1. Functions that use FPU operations should be isolated in static functions.
+ * 2. The FPU functions should have the noinline attribute to ensure anything
+ * that deals with FP register is contained within this call.
+ * 3. All function that needs to be accessed outside this file requires a
+ * public interface that not uses any FPU reference.
+ * 4. Developers **must not** use DC_FP_START/END in this file, but they need
+ * to ensure that the caller invokes it before access any function available
+ * in this file. For this reason, public functions in this file must invoke
+ * dc_assert_fp_enabled();
+ *
+ * Let's expand a little bit more the idea in the code pattern. To fully
+ * isolate FPU operations in a single place, we must avoid situations where
+ * compilers spill FP values to registers due to FP enable in a specific C
+ * file. Note that even if we isolate all FPU functions in a single file and
+ * call its interface from other files, the compiler might enable the use of
+ * FPU before we call DC_FP_START. Nevertheless, it is the programmer's
+ * responsibility to invoke DC_FP_START/END in the correct place. To highlight
+ * situations where developers forgot to use the FP protection before calling
+ * the DC FPU interface functions, we introduce a helper that checks if the
+ * function is invoked under FP protection. If not, it will trigger a kernel
+ * warning.
+ */
+
+void dcn20_populate_dml_writeback_from_context(struct dc *dc,
+ struct resource_context *res_ctx,
+ display_e2e_pipe_params_st *pipes)
+{
+ int pipe_cnt, i;
+
+ dc_assert_fp_enabled();
+
+ for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
+ struct dc_writeback_info *wb_info = &res_ctx->pipe_ctx[i].stream->writeback_info[0];
+
+ if (!res_ctx->pipe_ctx[i].stream)
+ continue;
+
+ /* Set writeback information */
+ pipes[pipe_cnt].dout.wb_enable = (wb_info->wb_enabled == true) ? 1 : 0;
+ pipes[pipe_cnt].dout.num_active_wb++;
+ pipes[pipe_cnt].dout.wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_height;
+ pipes[pipe_cnt].dout.wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_width;
+ pipes[pipe_cnt].dout.wb.wb_dst_width = wb_info->dwb_params.dest_width;
+ pipes[pipe_cnt].dout.wb.wb_dst_height = wb_info->dwb_params.dest_height;
+ pipes[pipe_cnt].dout.wb.wb_htaps_luma = 1;
+ pipes[pipe_cnt].dout.wb.wb_vtaps_luma = 1;
+ pipes[pipe_cnt].dout.wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
+ pipes[pipe_cnt].dout.wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
+ pipes[pipe_cnt].dout.wb.wb_hratio = 1.0;
+ pipes[pipe_cnt].dout.wb.wb_vratio = 1.0;
+ if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
+ if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
+ pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_8;
+ else
+ pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_10;
+ } else {
+ pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_444_32;
+ }
+
+ pipe_cnt++;
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h b/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h
new file mode 100644
index 000000000000..331547ba0713
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN2X_H__
+#define __DCN2X_H__
+
+void dcn20_populate_dml_writeback_from_context(struct dc *dc,
+ struct resource_context *res_ctx,
+ display_e2e_pipe_params_st *pipes);
+
+#endif /* __DCN2X_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
index 9d2016d8fafe..e3d9f1decdfc 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
@@ -2596,7 +2596,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
}
}
- v->NotEnoughUrgentLatencyHiding = false;
+ v->NotEnoughUrgentLatencyHiding[0][0] = false;
v->NotEnoughUrgentLatencyHidingPre = false;
for (k = 0; k < v->NumberOfActivePlanes; ++k) {
@@ -2681,7 +2681,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
if (v->VRatioPrefetchY[k] > 4 || v->VRatioPrefetchC[k] > 4)
VRatioPrefetchMoreThan4 = true;
if (v->NoUrgentLatencyHiding[k] == true)
- v->NotEnoughUrgentLatencyHiding = true;
+ v->NotEnoughUrgentLatencyHiding[0][0] = true;
if (v->NoUrgentLatencyHidingPre[k] == true)
v->NotEnoughUrgentLatencyHidingPre = true;
@@ -2689,7 +2689,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
v->FractionOfUrgentBandwidth = MaxTotalRDBandwidthNoUrgentBurst / v->ReturnBW;
- if (MaxTotalRDBandwidth <= v->ReturnBW && v->NotEnoughUrgentLatencyHiding == 0 && v->NotEnoughUrgentLatencyHidingPre == 0 && !VRatioPrefetchMoreThan4
+ if (MaxTotalRDBandwidth <= v->ReturnBW && v->NotEnoughUrgentLatencyHiding[0][0] == 0
+ && v->NotEnoughUrgentLatencyHidingPre == 0 && !VRatioPrefetchMoreThan4
&& !DestinationLineTimesForPrefetchLessThan2)
v->PrefetchModeSupported = true;
else {
@@ -2794,8 +2795,9 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
}
v->VStartupLines = v->VStartupLines + 1;
- v->PrefetchAndImmediateFlipSupported = (v->PrefetchModeSupported == true && ((!v->ImmediateFlipSupport && !v->HostVMEnable && v->ImmediateFlipRequirement != dm_immediate_flip_required) || v->ImmediateFlipSupported)) ? true : false;
-
+ v->PrefetchModeSupported = (v->PrefetchModeSupported == true && ((!v->ImmediateFlipSupport &&
+ !v->HostVMEnable && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required) ||
+ v->ImmediateFlipSupported)) ? true : false;
} while (!v->PrefetchModeSupported && v->VStartupLines <= v->MaximumMaxVStartupLines);
ASSERT(v->PrefetchModeSupported);
@@ -3642,8 +3644,7 @@ static double TruncToValidBPP(
void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib)
{
struct vba_vars_st *v = &mode_lib->vba;
- int MinPrefetchMode = 0;
- int MaxPrefetchMode = 2;
+ int MinPrefetchMode, MaxPrefetchMode;
int i;
unsigned int j, k, m;
bool EnoughWritebackUnits = true;
@@ -3655,6 +3656,10 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
/*MODE SUPPORT, VOLTAGE STATE AND SOC CONFIGURATION*/
+ CalculateMinAndMaxPrefetchMode(
+ mode_lib->vba.AllowDRAMSelfRefreshOrDRAMClockChangeInVblank,
+ &MinPrefetchMode, &MaxPrefetchMode);
+
/*Scale Ratio, taps Support Check*/
v->ScaleRatioAndTapsSupport = true;
@@ -4753,7 +4758,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->HostVMMinPageSize,
v->HostVMMaxNonCachedPageTableLevels,
v->DynamicMetadataVMEnabled,
- v->ImmediateFlipRequirement,
+ v->ImmediateFlipRequirement[0],
v->ProgressiveToInterlaceUnitInOPP,
v->MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation,
v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
@@ -5164,7 +5169,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->NextMaxVStartup = v->NextMaxVStartup - 1;
}
} while (!((v->PrefetchSupported[i][j] == true && v->DynamicMetadataSupported[i][j] == true && v->VRatioInPrefetchSupported[i][j] == true
- && ((v->HostVMEnable == false && v->ImmediateFlipRequirement != dm_immediate_flip_required)
+ && ((v->HostVMEnable == false && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
|| v->ImmediateFlipSupportedForState[i][j] == true))
|| (v->NextMaxVStartup == v->MaxMaxVStartup[i][j] && NextPrefetchModeState > MaxPrefetchMode)));
@@ -5305,7 +5310,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
&& ViewportExceedsSurface == 0 && v->PrefetchSupported[i][j] == 1 && v->DynamicMetadataSupported[i][j] == 1
&& v->TotalVerticalActiveBandwidthSupport[i][j] == 1 && v->VRatioInPrefetchSupported[i][j] == 1
&& v->PTEBufferSizeNotExceeded[i][j] == 1 && v->NonsupportedDSCInputBPC == 0
- && ((v->HostVMEnable == 0 && v->ImmediateFlipRequirement != dm_immediate_flip_required)
+ && ((v->HostVMEnable == 0 && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
|| v->ImmediateFlipSupportedForState[i][j] == true)) {
v->ModeSupport[i][j] = true;
} else {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
index 04601a767a8f..0d934fae1c3a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
@@ -549,7 +549,7 @@ static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib,
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
- // a meta element covers one 256b block of the the data surface.
+ // a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
- log2_meta_req_height;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
index a9667068c690..ce55c9caf9a2 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
@@ -3036,10 +3036,9 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
}
v->PrefetchAndImmediateFlipSupported =
- (v->PrefetchModeSupported == true
- && ((!v->ImmediateFlipSupport && !v->HostVMEnable
- && v->ImmediateFlipRequirement != dm_immediate_flip_required) || v->ImmediateFlipSupported)) ?
- true : false;
+ (v->PrefetchModeSupported == true && ((!v->ImmediateFlipSupport && !v->HostVMEnable
+ && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required) ||
+ v->ImmediateFlipSupported)) ? true : false;
#ifdef __DML_VBA_DEBUG__
dml_print("DML::%s: PrefetchModeSupported %d\n", __func__, v->PrefetchModeSupported);
dml_print("DML::%s: ImmediateFlipRequirement %d\n", __func__, v->ImmediateFlipRequirement == dm_immediate_flip_required);
@@ -5103,7 +5102,7 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->HostVMMinPageSize,
v->HostVMMaxNonCachedPageTableLevels,
v->DynamicMetadataVMEnabled,
- v->ImmediateFlipRequirement,
+ v->ImmediateFlipRequirement[0],
v->ProgressiveToInterlaceUnitInOPP,
v->MaxAveragePercentOfIdealFabricAndSDPPortBWDisplayCanUseInNormalSystemOperation,
v->PercentOfIdealFabricAndSDPPortBWReceivedAfterUrgLatency,
@@ -5542,7 +5541,8 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
}
v->NextPrefetchMode = v->NextPrefetchMode + 1;
} while (!((v->PrefetchSupported[i][j] == true && v->DynamicMetadataSupported[i][j] == true && v->VRatioInPrefetchSupported[i][j] == true
- && ((v->HostVMEnable == false && v->ImmediateFlipRequirement != dm_immediate_flip_required)
+ && ((v->HostVMEnable == false &&
+ v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
|| v->ImmediateFlipSupportedForState[i][j] == true))
|| (v->NextMaxVStartup == v->MaxMaxVStartup[i][j] && NextPrefetchModeState > MaxPrefetchMode)));
@@ -5702,7 +5702,8 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
&& v->PrefetchSupported[i][j] == true && v->DynamicMetadataSupported[i][j] == true
&& v->TotalVerticalActiveBandwidthSupport[i][j] == true && v->VRatioInPrefetchSupported[i][j] == true
&& v->PTEBufferSizeNotExceeded[i][j] == true && v->NonsupportedDSCInputBPC == false
- && ((v->HostVMEnable == false && v->ImmediateFlipRequirement != dm_immediate_flip_required)
+ && ((v->HostVMEnable == false
+ && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
|| v->ImmediateFlipSupportedForState[i][j] == true)
&& FMTBufferExceeded == false) {
v->ModeSupport[i][j] = true;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
index 3def093ef88e..c23905bc733a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
@@ -563,7 +563,7 @@ static void get_meta_and_pte_attr(
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
- // a meta element covers one 256b block of the the data surface.
+ // a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element - log2_meta_req_height;
meta_req_width = 1 << log2_meta_req_width;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h
index 64f9c735f74d..1051ca1a23b8 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h
@@ -109,7 +109,9 @@ enum clock_change_support {
};
enum output_standard {
- dm_std_uninitialized = 0, dm_std_cvtr2, dm_std_cvt
+ dm_std_uninitialized = 0,
+ dm_std_cvtr2,
+ dm_std_cvt
};
enum mpc_combine_affinity {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
index 64daa0507393..d46a2733024c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
@@ -536,6 +536,8 @@ struct _vcs_dpi_display_rq_regs_st {
unsigned int mrq_expansion_mode;
unsigned int crq_expansion_mode;
unsigned int plane1_base_address;
+ unsigned int aperture_low_addr; // bits [47:18]
+ unsigned int aperture_high_addr; // bits [47:18]
};
struct _vcs_dpi_display_dlg_sys_params_st {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
index d3b1b6d4ce2f..0fad15020c74 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
@@ -244,6 +244,8 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib)
mode_lib->vba.DRAMClockChangeSupportsVActive = !soc->disable_dram_clock_change_vactive_support ||
mode_lib->vba.DummyPStateCheck;
mode_lib->vba.AllowDramClockChangeOneDisplayVactive = soc->allow_dram_clock_one_display_vactive;
+ mode_lib->vba.AllowDRAMSelfRefreshOrDRAMClockChangeInVblank =
+ soc->allow_dram_self_refresh_or_dram_clock_change_in_vblank;
mode_lib->vba.Downspreading = soc->downspread_percent;
mode_lib->vba.DRAMChannelWidth = soc->dram_channel_width_bytes; // new!
@@ -396,7 +398,6 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
mode_lib->vba.NumberOfActivePlanes = 0;
mode_lib->vba.ImmediateFlipSupport = false;
- mode_lib->vba.ImmediateFlipRequirement = dm_immediate_flip_not_required;
for (j = 0; j < mode_lib->vba.cache_num_pipes; ++j) {
display_pipe_source_params_st *src = &pipes[j].pipe.src;
display_pipe_dest_params_st *dst = &pipes[j].pipe.dest;
@@ -409,6 +410,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
continue;
visited[j] = true;
+ mode_lib->vba.ImmediateFlipRequirement[j] = dm_immediate_flip_not_required;
mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes;
mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1;
mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] =
@@ -667,9 +669,9 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max / vdiv_c;
}
- if (pipes[k].pipe.src.immediate_flip) {
+ if (pipes[j].pipe.src.immediate_flip) {
mode_lib->vba.ImmediateFlipSupport = true;
- mode_lib->vba.ImmediateFlipRequirement = dm_immediate_flip_required;
+ mode_lib->vba.ImmediateFlipRequirement[j] = dm_immediate_flip_required;
}
mode_lib->vba.NumberOfActivePlanes++;
@@ -733,8 +735,6 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
mode_lib->vba.OverrideHostVMPageTableLevels;
}
- mode_lib->vba.AllowDRAMSelfRefreshOrDRAMClockChangeInVblank = dm_try_to_allow_self_refresh_and_mclk_switch;
-
if (mode_lib->vba.OverrideGPUVMPageTableLevels)
mode_lib->vba.GPUVMMaxPageTableLevels = mode_lib->vba.OverrideGPUVMPageTableLevels;
@@ -845,9 +845,10 @@ void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *
//Progressive To Interlace Unit Effect
for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
+ mode_lib->vba.PixelClockBackEnd[k] = mode_lib->vba.PixelClock[k];
if (mode_lib->vba.Interlace[k] == 1
&& mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) {
- mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClockBackEnd[k];
+ mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClock[k];
}
}
}
@@ -890,8 +891,9 @@ void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib)
mode_lib->vba.DISPCLK = soc->clock_limits[mode_lib->vba.VoltageLevel].dispclk_mhz;
// Total Available Pipes Support Check
- for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
+ for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
total_pipes += mode_lib->vba.DPPPerPlane[k];
+ }
ASSERT(total_pipes <= DC__NUM_DPP__MAX);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h
index d18a021d4d32..90e87961fe3e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h
@@ -676,7 +676,7 @@ struct vba_vars_st {
double AlignedDCCMetaPitchY[DC__NUM_DPP__MAX];
double AlignedDCCMetaPitchC[DC__NUM_DPP__MAX];
- unsigned int NotEnoughUrgentLatencyHiding;
+ unsigned int NotEnoughUrgentLatencyHiding[DC__VOLTAGE_STATES][2];
unsigned int NotEnoughUrgentLatencyHidingPre;
int PTEBufferSizeInRequestsForLuma;
int PTEBufferSizeInRequestsForChroma;
@@ -877,7 +877,7 @@ struct vba_vars_st {
int PercentMarginOverMinimumRequiredDCFCLK;
bool DynamicMetadataSupported[DC__VOLTAGE_STATES][2];
- enum immediate_flip_requirement ImmediateFlipRequirement;
+ enum immediate_flip_requirement ImmediateFlipRequirement[DC__NUM_DPP__MAX];
unsigned int DETBufferSizeYThisState[DC__NUM_DPP__MAX];
unsigned int DETBufferSizeCThisState[DC__NUM_DPP__MAX];
bool NoUrgentLatencyHiding[DC__NUM_DPP__MAX];
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
index 414da64f5734..8f2b1684c231 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
@@ -456,7 +456,7 @@ static void dml1_rq_dlg_get_row_heights(
log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */
/* each 64b meta request for dcn is 8x8 meta elements and
- * a meta element covers one 256b block of the the data surface.
+ * a meta element covers one 256b block of the data surface.
*/
log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
@@ -718,7 +718,7 @@ static void get_surf_rq_param(
log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */
/* each 64b meta request for dcn is 8x8 meta elements and
- * a meta element covers one 256b block of the the data surface.
+ * a meta element covers one 256b block of the data surface.
*/
log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index f403d8e84a8c..f5b7da0e64c0 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -28,6 +28,7 @@
#include <drm/drm_dp_helper.h>
#include "dc.h"
#include "rc_calc.h"
+#include "fixed31_32.h"
/* This module's internal functions */
@@ -39,6 +40,47 @@ static bool dsc_policy_enable_dsc_when_not_needed;
static bool dsc_policy_disable_dsc_stream_overhead;
+/* Forward Declerations */
+static void get_dsc_bandwidth_range(
+ const uint32_t min_bpp_x16,
+ const uint32_t max_bpp_x16,
+ const uint32_t num_slices_h,
+ const struct dsc_enc_caps *dsc_caps,
+ const struct dc_crtc_timing *timing,
+ struct dc_dsc_bw_range *range);
+
+static uint32_t compute_bpp_x16_from_target_bandwidth(
+ const uint32_t bandwidth_in_kbps,
+ const struct dc_crtc_timing *timing,
+ const uint32_t num_slices_h,
+ const uint32_t bpp_increment_div,
+ const bool is_dp);
+
+static void get_dsc_enc_caps(
+ const struct display_stream_compressor *dsc,
+ struct dsc_enc_caps *dsc_enc_caps,
+ int pixel_clock_100Hz);
+
+static bool intersect_dsc_caps(
+ const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+ const struct dsc_enc_caps *dsc_enc_caps,
+ enum dc_pixel_encoding pixel_encoding,
+ struct dsc_enc_caps *dsc_common_caps);
+
+static bool setup_dsc_config(
+ const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+ const struct dsc_enc_caps *dsc_enc_caps,
+ int target_bandwidth_kbps,
+ const struct dc_crtc_timing *timing,
+ int min_slice_height_override,
+ int max_dsc_target_bpp_limit_override_x16,
+ struct dc_dsc_config *dsc_cfg);
+
+static struct fixed31_32 compute_dsc_max_bandwidth_overhead(
+ const struct dc_crtc_timing *timing,
+ const int num_slices_h,
+ const bool is_dp);
+
static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)
{
@@ -171,10 +213,164 @@ static bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t
return true;
}
+
+
+bool dc_dsc_parse_dsc_dpcd(const struct dc *dc,
+ const uint8_t *dpcd_dsc_basic_data,
+ const uint8_t *dpcd_dsc_branch_decoder_caps,
+ struct dsc_dec_dpcd_caps *dsc_sink_caps)
+{
+ if (!dpcd_dsc_basic_data)
+ return false;
+
+ dsc_sink_caps->is_dsc_supported =
+ (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
+ if (!dsc_sink_caps->is_dsc_supported)
+ return false;
+
+ dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];
+
+ {
+ int buff_block_size;
+ int buff_size;
+
+ if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT],
+ &buff_block_size))
+ return false;
+
+ buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
+ dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
+ }
+
+ dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
+ if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT],
+ &dsc_sink_caps->lb_bit_depth))
+ return false;
+
+ dsc_sink_caps->is_block_pred_supported =
+ (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &
+ DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
+
+ dsc_sink_caps->edp_max_bits_per_pixel =
+ dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
+ dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
+
+ dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
+ dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
+
+ {
+ int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
+
+ if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK,
+ &dsc_sink_caps->throughput_mode_0_mps))
+ return false;
+
+ dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;
+ if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))
+ return false;
+ }
+
+ dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
+ dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
+
+ if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT],
+ &dsc_sink_caps->bpp_increment_div))
+ return false;
+
+ if (dc->debug.dsc_bpp_increment_div) {
+ /* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values,
+ * we'll accept all and get it into range. This also makes the above check against 0 redundant,
+ * but that one stresses out the override will be only used if it's not 0.
+ */
+ if (dc->debug.dsc_bpp_increment_div >= 1)
+ dsc_sink_caps->bpp_increment_div = 1;
+ if (dc->debug.dsc_bpp_increment_div >= 2)
+ dsc_sink_caps->bpp_increment_div = 2;
+ if (dc->debug.dsc_bpp_increment_div >= 4)
+ dsc_sink_caps->bpp_increment_div = 4;
+ if (dc->debug.dsc_bpp_increment_div >= 8)
+ dsc_sink_caps->bpp_increment_div = 8;
+ if (dc->debug.dsc_bpp_increment_div >= 16)
+ dsc_sink_caps->bpp_increment_div = 16;
+ }
+
+ /* Extended caps */
+ if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device
+ dsc_sink_caps->branch_overall_throughput_0_mps = 0;
+ dsc_sink_caps->branch_overall_throughput_1_mps = 0;
+ dsc_sink_caps->branch_max_line_width = 0;
+ return true;
+ }
+
+ dsc_sink_caps->branch_overall_throughput_0_mps =
+ dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
+ if (dsc_sink_caps->branch_overall_throughput_0_mps == 0)
+ dsc_sink_caps->branch_overall_throughput_0_mps = 0;
+ else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1)
+ dsc_sink_caps->branch_overall_throughput_0_mps = 680;
+ else {
+ dsc_sink_caps->branch_overall_throughput_0_mps *= 50;
+ dsc_sink_caps->branch_overall_throughput_0_mps += 600;
+ }
+
+ dsc_sink_caps->branch_overall_throughput_1_mps =
+ dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
+ if (dsc_sink_caps->branch_overall_throughput_1_mps == 0)
+ dsc_sink_caps->branch_overall_throughput_1_mps = 0;
+ else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1)
+ dsc_sink_caps->branch_overall_throughput_1_mps = 680;
+ else {
+ dsc_sink_caps->branch_overall_throughput_1_mps *= 50;
+ dsc_sink_caps->branch_overall_throughput_1_mps += 600;
+ }
+
+ dsc_sink_caps->branch_max_line_width =
+ dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320;
+ ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120);
+
+ dsc_sink_caps->is_dp = true;
+ return true;
+}
+
+
+/* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and
+ * timing's pixel clock and uncompressed bandwidth.
+ * If DSC is not possible, leave '*range' untouched.
+ */
+bool dc_dsc_compute_bandwidth_range(
+ const struct display_stream_compressor *dsc,
+ uint32_t dsc_min_slice_height_override,
+ uint32_t min_bpp_x16,
+ uint32_t max_bpp_x16,
+ const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+ const struct dc_crtc_timing *timing,
+ struct dc_dsc_bw_range *range)
+{
+ bool is_dsc_possible = false;
+ struct dsc_enc_caps dsc_enc_caps;
+ struct dsc_enc_caps dsc_common_caps;
+ struct dc_dsc_config config;
+
+ get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
+
+ is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,
+ timing->pixel_encoding, &dsc_common_caps);
+
+ if (is_dsc_possible)
+ is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing,
+ dsc_min_slice_height_override, max_bpp_x16, &config);
+
+ if (is_dsc_possible)
+ get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16,
+ config.num_slices_h, &dsc_common_caps, timing, range);
+
+ return is_dsc_possible;
+}
+
static void get_dsc_enc_caps(
- const struct display_stream_compressor *dsc,
- struct dsc_enc_caps *dsc_enc_caps,
- int pixel_clock_100Hz)
+ const struct display_stream_compressor *dsc,
+ struct dsc_enc_caps *dsc_enc_caps,
+ int pixel_clock_100Hz)
{
// This is a static HW query, so we can use any DSC
@@ -187,14 +383,14 @@ static void get_dsc_enc_caps(
}
}
-/* Returns 'false' if no intersection was found for at least one capablity.
+/* Returns 'false' if no intersection was found for at least one capability.
* It also implicitly validates some sink caps against invalid value of zero.
*/
static bool intersect_dsc_caps(
- const struct dsc_dec_dpcd_caps *dsc_sink_caps,
- const struct dsc_enc_caps *dsc_enc_caps,
- enum dc_pixel_encoding pixel_encoding,
- struct dsc_enc_caps *dsc_common_caps)
+ const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+ const struct dsc_enc_caps *dsc_enc_caps,
+ enum dc_pixel_encoding pixel_encoding,
+ struct dsc_enc_caps *dsc_common_caps)
{
int32_t max_slices;
int32_t total_sink_throughput;
@@ -205,10 +401,14 @@ static bool intersect_dsc_caps(
if (!dsc_common_caps->dsc_version)
return false;
- dsc_common_caps->slice_caps.bits.NUM_SLICES_1 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1;
- dsc_common_caps->slice_caps.bits.NUM_SLICES_2 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2;
- dsc_common_caps->slice_caps.bits.NUM_SLICES_4 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;
- dsc_common_caps->slice_caps.bits.NUM_SLICES_8 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;
+ dsc_common_caps->slice_caps.bits.NUM_SLICES_1 =
+ dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1;
+ dsc_common_caps->slice_caps.bits.NUM_SLICES_2 =
+ dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2;
+ dsc_common_caps->slice_caps.bits.NUM_SLICES_4 =
+ dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;
+ dsc_common_caps->slice_caps.bits.NUM_SLICES_8 =
+ dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;
if (!dsc_common_caps->slice_caps.raw)
return false;
@@ -216,7 +416,8 @@ static bool intersect_dsc_caps(
if (!dsc_common_caps->lb_bit_depth)
return false;
- dsc_common_caps->is_block_pred_supported = dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported;
+ dsc_common_caps->is_block_pred_supported =
+ dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported;
dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw;
if (!dsc_common_caps->color_formats.raw)
@@ -288,11 +489,11 @@ static struct fixed31_32 compute_dsc_max_bandwidth_overhead(
}
static uint32_t compute_bpp_x16_from_target_bandwidth(
- const uint32_t bandwidth_in_kbps,
- const struct dc_crtc_timing *timing,
- const uint32_t num_slices_h,
- const uint32_t bpp_increment_div,
- const bool is_dp)
+ const uint32_t bandwidth_in_kbps,
+ const struct dc_crtc_timing *timing,
+ const uint32_t num_slices_h,
+ const uint32_t bpp_increment_div,
+ const bool is_dp)
{
struct fixed31_32 overhead_in_kbps;
struct fixed31_32 effective_bandwidth_in_kbps;
@@ -769,146 +970,6 @@ done:
return is_dsc_possible;
}
-bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_data, const uint8_t *dpcd_dsc_branch_decoder_caps, struct dsc_dec_dpcd_caps *dsc_sink_caps)
-{
- if (!dpcd_dsc_basic_data)
- return false;
-
- dsc_sink_caps->is_dsc_supported = (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
- if (!dsc_sink_caps->is_dsc_supported)
- return false;
-
- dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];
-
- {
- int buff_block_size;
- int buff_size;
-
- if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], &buff_block_size))
- return false;
-
- buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
- dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
- }
-
- dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
- if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], &dsc_sink_caps->lb_bit_depth))
- return false;
-
- dsc_sink_caps->is_block_pred_supported =
- (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
-
- dsc_sink_caps->edp_max_bits_per_pixel =
- dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
- dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
-
- dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
- dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
-
- {
- int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
-
- if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, &dsc_sink_caps->throughput_mode_0_mps))
- return false;
-
- dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;
- if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))
- return false;
- }
-
- dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
- dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
-
- if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT], &dsc_sink_caps->bpp_increment_div))
- return false;
-
- if (dc->debug.dsc_bpp_increment_div) {
- /* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values,
- * we'll accept all and get it into range. This also makes the above check against 0 redundant,
- * but that one stresses out the override will be only used if it's not 0.
- */
- if (dc->debug.dsc_bpp_increment_div >= 1)
- dsc_sink_caps->bpp_increment_div = 1;
- if (dc->debug.dsc_bpp_increment_div >= 2)
- dsc_sink_caps->bpp_increment_div = 2;
- if (dc->debug.dsc_bpp_increment_div >= 4)
- dsc_sink_caps->bpp_increment_div = 4;
- if (dc->debug.dsc_bpp_increment_div >= 8)
- dsc_sink_caps->bpp_increment_div = 8;
- if (dc->debug.dsc_bpp_increment_div >= 16)
- dsc_sink_caps->bpp_increment_div = 16;
- }
-
- /* Extended caps */
- if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device
- dsc_sink_caps->branch_overall_throughput_0_mps = 0;
- dsc_sink_caps->branch_overall_throughput_1_mps = 0;
- dsc_sink_caps->branch_max_line_width = 0;
- return true;
- }
-
- dsc_sink_caps->branch_overall_throughput_0_mps = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
- if (dsc_sink_caps->branch_overall_throughput_0_mps == 0)
- dsc_sink_caps->branch_overall_throughput_0_mps = 0;
- else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1)
- dsc_sink_caps->branch_overall_throughput_0_mps = 680;
- else {
- dsc_sink_caps->branch_overall_throughput_0_mps *= 50;
- dsc_sink_caps->branch_overall_throughput_0_mps += 600;
- }
-
- dsc_sink_caps->branch_overall_throughput_1_mps = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
- if (dsc_sink_caps->branch_overall_throughput_1_mps == 0)
- dsc_sink_caps->branch_overall_throughput_1_mps = 0;
- else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1)
- dsc_sink_caps->branch_overall_throughput_1_mps = 680;
- else {
- dsc_sink_caps->branch_overall_throughput_1_mps *= 50;
- dsc_sink_caps->branch_overall_throughput_1_mps += 600;
- }
-
- dsc_sink_caps->branch_max_line_width = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320;
- ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120);
-
- dsc_sink_caps->is_dp = true;
- return true;
-}
-
-
-/* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and
- * timing's pixel clock and uncompressed bandwidth.
- * If DSC is not possible, leave '*range' untouched.
- */
-bool dc_dsc_compute_bandwidth_range(
- const struct display_stream_compressor *dsc,
- uint32_t dsc_min_slice_height_override,
- uint32_t min_bpp_x16,
- uint32_t max_bpp_x16,
- const struct dsc_dec_dpcd_caps *dsc_sink_caps,
- const struct dc_crtc_timing *timing,
- struct dc_dsc_bw_range *range)
-{
- bool is_dsc_possible = false;
- struct dsc_enc_caps dsc_enc_caps;
- struct dsc_enc_caps dsc_common_caps;
- struct dc_dsc_config config;
-
- get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
-
- is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,
- timing->pixel_encoding, &dsc_common_caps);
-
- if (is_dsc_possible)
- is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing,
- dsc_min_slice_height_override, max_bpp_x16, &config);
-
- if (is_dsc_possible)
- get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16,
- config.num_slices_h, &dsc_common_caps, timing, range);
-
- return is_dsc_possible;
-}
-
bool dc_dsc_compute_config(
const struct display_stream_compressor *dsc,
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
@@ -923,22 +984,22 @@ bool dc_dsc_compute_config(
get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
is_dsc_possible = setup_dsc_config(dsc_sink_caps,
- &dsc_enc_caps,
- target_bandwidth_kbps,
- timing, dsc_min_slice_height_override,
- max_target_bpp_limit_override * 16, dsc_cfg);
+ &dsc_enc_caps,
+ target_bandwidth_kbps,
+ timing, dsc_min_slice_height_override,
+ max_target_bpp_limit_override * 16, dsc_cfg);
return is_dsc_possible;
}
uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing,
- uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp)
+ uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp)
{
struct fixed31_32 overhead_in_kbps;
struct fixed31_32 bpp;
struct fixed31_32 actual_bandwidth_in_kbps;
overhead_in_kbps = compute_dsc_max_bandwidth_overhead(
- timing, num_slices_h, is_dp);
+ timing, num_slices_h, is_dp);
bpp = dc_fixpt_from_fraction(bpp_x16, 16);
actual_bandwidth_in_kbps = dc_fixpt_from_fraction(timing->pix_clk_100hz, 10);
actual_bandwidth_in_kbps = dc_fixpt_mul(actual_bandwidth_in_kbps, bpp);
@@ -946,7 +1007,9 @@ uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing,
return dc_fixpt_ceil(actual_bandwidth_in_kbps);
}
-void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, struct dc_dsc_policy *policy)
+void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing,
+ uint32_t max_target_bpp_limit_override_x16,
+ struct dc_dsc_policy *policy)
{
uint32_t bpc = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
index e2b58ec9912d..01c3a31be191 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
@@ -174,7 +174,6 @@ bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable);
void dp_decide_training_settings(
struct dc_link *link,
const struct dc_link_settings *link_setting,
- const struct dc_link_training_overrides *overrides,
struct link_training_settings *lt_settings);
/* Convert PHY repeater count read from DPCD uint8_t. */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
index 316301fc1e30..a262f3278c21 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
@@ -318,6 +318,11 @@ static inline bool should_update_pstate_support(bool safe_to_lower, bool calc_su
return false;
}
+static inline int khz_to_mhz_ceil(int khz)
+{
+ return (khz + 999) / 1000;
+}
+
int clk_mgr_helper_get_active_display_cnt(
struct dc *dc,
struct dc_state *context);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index 0638b337f143..713f5558f5e1 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -102,6 +102,15 @@ struct hubbub_addr_config {
} default_addrs;
};
+struct dcn_hubbub_state {
+ uint32_t vm_fault_addr_msb;
+ uint32_t vm_fault_addr_lsb;
+ uint32_t vm_error_status;
+ uint32_t vm_error_vmid;
+ uint32_t vm_error_pipe;
+ uint32_t vm_error_mode;
+};
+
struct hubbub_funcs {
void (*update_dchub)(
struct hubbub *hubbub,
@@ -149,6 +158,8 @@ struct hubbub_funcs {
void (*force_wm_propagate_to_pipes)(struct hubbub *hubbub);
+ void (*hubbub_read_state)(struct hubbub *hubbub, struct dcn_hubbub_state *hubbub_state);
+
void (*force_pstate_change_control)(struct hubbub *hubbub, bool force, bool allow);
void (*init_watermarks)(struct hubbub *hubbub);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
index 082549f75978..f7f7e4fff0c2 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
@@ -41,7 +41,6 @@ struct dce_hwseq_wa {
bool DEGVIDCN10_254;
bool DEGVIDCN21;
bool disallow_self_refresh_during_multi_plane_transition;
- bool early_riommu_invalidation;
};
struct hwseq_wa_state {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h b/drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h
index d4d52ef1b165..3f12b1600d2a 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h
@@ -1,3 +1,28 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
#ifndef __LINK_DPCD_H__
#define __LINK_DPCD_H__
#include <inc/core_status.h>
diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h
index 1139b9eb9f6f..530c2578db40 100644
--- a/drivers/gpu/drm/amd/display/dc/irq_types.h
+++ b/drivers/gpu/drm/amd/display/dc/irq_types.h
@@ -152,7 +152,7 @@ enum dc_irq_source {
DC_IRQ_SOURCE_DC6_VLINE1,
DC_IRQ_SOURCE_DMCUB_OUTBOX,
DC_IRQ_SOURCE_DMCUB_OUTBOX0,
-
+ DC_IRQ_SOURCE_DMCUB_GENERAL_DATAOUT,
DAL_IRQ_SOURCES_NUMBER
};
diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h
index 126c2f3a4dd3..f50cae252de4 100644
--- a/drivers/gpu/drm/amd/display/dc/os_types.h
+++ b/drivers/gpu/drm/amd/display/dc/os_types.h
@@ -51,38 +51,9 @@
#define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
#if defined(CONFIG_DRM_AMD_DC_DCN)
-#if defined(CONFIG_X86)
-#include <asm/fpu/api.h>
-#define DC_FP_START() kernel_fpu_begin()
-#define DC_FP_END() kernel_fpu_end()
-#elif defined(CONFIG_PPC64)
-#include <asm/switch_to.h>
-#include <asm/cputable.h>
-#define DC_FP_START() { \
- if (cpu_has_feature(CPU_FTR_VSX_COMP)) { \
- preempt_disable(); \
- enable_kernel_vsx(); \
- } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { \
- preempt_disable(); \
- enable_kernel_altivec(); \
- } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { \
- preempt_disable(); \
- enable_kernel_fp(); \
- } \
-}
-#define DC_FP_END() { \
- if (cpu_has_feature(CPU_FTR_VSX_COMP)) { \
- disable_kernel_vsx(); \
- preempt_enable(); \
- } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { \
- disable_kernel_altivec(); \
- preempt_enable(); \
- } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { \
- disable_kernel_fp(); \
- preempt_enable(); \
- } \
-}
-#endif
+#include "amdgpu_dm/dc_fpu.h"
+#define DC_FP_START() dc_fpu_begin(__func__, __LINE__)
+#define DC_FP_END() dc_fpu_end(__func__, __LINE__)
#endif
/*
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index abbf7ae584c9..caf961bb633f 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -352,6 +352,8 @@ struct dmub_srv_hw_funcs {
uint32_t (*get_gpint_response)(struct dmub_srv *dmub);
+ uint32_t (*get_gpint_dataout)(struct dmub_srv *dmub);
+
void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data);
uint32_t (*get_current_time)(struct dmub_srv *dmub);
@@ -677,6 +679,22 @@ enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub,
uint32_t *response);
/**
+ * dmub_srv_get_gpint_dataout() - Queries the GPINT DATAOUT.
+ * @dmub: the dmub service
+ * @dataout: the data for the GPINT DATAOUT
+ *
+ * Returns the response code for the last GPINT DATAOUT interrupt.
+ *
+ * Can be called after software initialization.
+ *
+ * Return:
+ * DMUB_STATUS_OK - success
+ * DMUB_STATUS_INVALID - unspecified error
+ */
+enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub,
+ uint32_t *dataout);
+
+/**
* dmub_flush_buffer_mem() - Read back entire frame buffer region.
* This ensures that the write from x86 has been flushed and will not
* hang the DMCUB.
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index 7fafb8d6c1da..7efe9ba8706e 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -23,8 +23,8 @@
*
*/
-#ifndef _DMUB_CMD_H_
-#define _DMUB_CMD_H_
+#ifndef DMUB_CMD_H
+#define DMUB_CMD_H
#if defined(_TEST_HARNESS) || defined(FPGA_USB4)
#include "dmub_fw_types.h"
@@ -39,7 +39,6 @@
#include <linux/types.h>
#include <linux/string.h>
#include <linux/delay.h>
-#include <stdarg.h>
#include "atomfirmware.h"
@@ -47,10 +46,10 @@
/* Firmware versioning. */
#ifdef DMUB_EXPOSE_VERSION
-#define DMUB_FW_VERSION_GIT_HASH 0xf3da2b656
+#define DMUB_FW_VERSION_GIT_HASH 0x7383caadc
#define DMUB_FW_VERSION_MAJOR 0
#define DMUB_FW_VERSION_MINOR 0
-#define DMUB_FW_VERSION_REVISION 71
+#define DMUB_FW_VERSION_REVISION 79
#define DMUB_FW_VERSION_TEST 0
#define DMUB_FW_VERSION_VBIOS 0
#define DMUB_FW_VERSION_HOTFIX 0
@@ -322,6 +321,10 @@ union dmub_fw_boot_status {
uint32_t mailbox_rdy : 1; /**< 1 if mailbox ready */
uint32_t optimized_init_done : 1; /**< 1 if optimized init done */
uint32_t restore_required : 1; /**< 1 if driver should call restore */
+ uint32_t defer_load : 1; /**< 1 if VBIOS data is deferred programmed */
+ uint32_t reserved : 1;
+ uint32_t detection_required: 1; /**< if detection need to be triggered by driver */
+
} bits; /**< status bits */
uint32_t all; /**< 32-bit access to status bits */
};
@@ -334,6 +337,8 @@ enum dmub_fw_boot_status_bit {
DMUB_FW_BOOT_STATUS_BIT_MAILBOX_READY = (1 << 1), /**< 1 if mailbox ready */
DMUB_FW_BOOT_STATUS_BIT_OPTIMIZED_INIT_DONE = (1 << 2), /**< 1 if init done */
DMUB_FW_BOOT_STATUS_BIT_RESTORE_REQUIRED = (1 << 3), /**< 1 if driver should call restore */
+ DMUB_FW_BOOT_STATUS_BIT_DEFERRED_LOADED = (1 << 4), /**< 1 if VBIOS data is deferred programmed */
+ DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED = (1 << 6), /**< 1 if detection need to be triggered by driver*/
};
/* Register bit definition for SCRATCH5 */
@@ -352,7 +357,7 @@ enum dmub_lvtma_status_bit {
};
/**
- * union dmub_fw_boot_options - Boot option definitions for SCRATCH15
+ * union dmub_fw_boot_options - Boot option definitions for SCRATCH14
*/
union dmub_fw_boot_options {
struct {
@@ -363,7 +368,10 @@ union dmub_fw_boot_options {
uint32_t disable_clk_gate: 1; /**< 1 if clock gating should be disabled */
uint32_t skip_phy_init_panel_sequence: 1; /**< 1 to skip panel init seq */
uint32_t z10_disable: 1; /**< 1 to disable z10 */
- uint32_t reserved : 25; /**< reserved */
+ uint32_t reserved2: 1; /**< reserved for an unreleased feature */
+ uint32_t reserved_unreleased1: 1; /**< reserved for an unreleased feature */
+ uint32_t invalid_vbios_data: 1; /**< 1 if VBIOS data table is invalid */
+ uint32_t reserved : 23; /**< reserved */
} bits; /**< boot bits */
uint32_t all; /**< 32-bit access to bits */
};
@@ -485,6 +493,11 @@ enum dmub_gpint_command {
* RETURN: PSR residency in milli-percent.
*/
DMUB_GPINT__PSR_RESIDENCY = 9,
+
+ /**
+ * DESC: Notifies DMCUB detection is done so detection required can be cleared.
+ */
+ DMUB_GPINT__NOTIFY_DETECTION_DONE = 12,
};
/**
@@ -1411,6 +1424,10 @@ struct dmub_cmd_psr_copy_settings_data {
* Currently the support is only for 0 or 1
*/
uint8_t panel_inst;
+ /**
+ * Explicit padding to 4 byte boundary.
+ */
+ uint8_t pad3[4];
};
/**
@@ -1435,7 +1452,7 @@ struct dmub_cmd_psr_set_level_data {
* 16-bit value dicated by driver that will enable/disable different functionality.
*/
uint16_t psr_level;
- /**
+ /**
* PSR control version.
*/
uint8_t cmd_version;
@@ -2467,16 +2484,14 @@ static inline bool dmub_rb_full(struct dmub_rb *rb)
static inline bool dmub_rb_push_front(struct dmub_rb *rb,
const union dmub_rb_cmd *cmd)
{
- uint64_t volatile *dst = (uint64_t volatile *)(rb->base_address) + rb->wrpt / sizeof(uint64_t);
- const uint64_t *src = (const uint64_t *)cmd;
- uint8_t i;
+ uint8_t *dst = (uint8_t *)(rb->base_address) + rb->wrpt;
+ const uint8_t *src = (const uint8_t *)cmd;
if (dmub_rb_full(rb))
return false;
// copying data
- for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
- *dst++ = *src++;
+ dmub_memcpy(dst, src, DMUB_RB_CMD_SIZE);
rb->wrpt += DMUB_RB_CMD_SIZE;
@@ -2498,7 +2513,7 @@ static inline bool dmub_rb_out_push_front(struct dmub_rb *rb,
const union dmub_rb_out_cmd *cmd)
{
uint8_t *dst = (uint8_t *)(rb->base_address) + rb->wrpt;
- const uint8_t *src = (uint8_t *)cmd;
+ const uint8_t *src = (const uint8_t *)cmd;
if (dmub_rb_full(rb))
return false;
@@ -2583,18 +2598,16 @@ static inline bool dmub_rb_peek_offset(struct dmub_rb *rb,
* @return false otherwise
*/
static inline bool dmub_rb_out_front(struct dmub_rb *rb,
- union dmub_rb_out_cmd *cmd)
+ union dmub_rb_out_cmd *cmd)
{
- const uint64_t volatile *src = (const uint64_t volatile *)(rb->base_address) + rb->rptr / sizeof(uint64_t);
- uint64_t *dst = (uint64_t *)cmd;
- uint8_t i;
+ const uint8_t *src = (const uint8_t *)(rb->base_address) + rb->rptr;
+ uint8_t *dst = (uint8_t *)cmd;
if (dmub_rb_empty(rb))
return false;
// copying data
- for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
- *dst++ = *src++;
+ dmub_memcpy(dst, src, DMUB_RB_CMD_SIZE);
return true;
}
@@ -2629,15 +2642,14 @@ static inline bool dmub_rb_pop_front(struct dmub_rb *rb)
*/
static inline void dmub_rb_flush_pending(const struct dmub_rb *rb)
{
+ uint8_t buf[DMUB_RB_CMD_SIZE];
uint32_t rptr = rb->rptr;
uint32_t wptr = rb->wrpt;
while (rptr != wptr) {
- uint64_t volatile *data = (uint64_t volatile *)rb->base_address + rptr / sizeof(uint64_t);
- uint8_t i;
+ const uint8_t *data = (const uint8_t *)rb->base_address + rptr;
- for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
- *data++;
+ dmub_memcpy(buf, data, DMUB_RB_CMD_SIZE);
rptr += DMUB_RB_CMD_SIZE;
if (rptr >= rb->capacity)
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
index 27c7fa3110c8..fc667cb17eb0 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
@@ -38,7 +38,10 @@
const struct dmub_srv_dcn31_regs dmub_srv_dcn31_regs = {
#define DMUB_SR(reg) REG_OFFSET_EXP(reg),
- { DMUB_DCN31_REGS() },
+ {
+ DMUB_DCN31_REGS()
+ DMCUB_INTERNAL_REGS()
+ },
#undef DMUB_SR
#define DMUB_SF(reg, field) FD_MASK(reg, field),
@@ -80,7 +83,7 @@ static inline void dmub_dcn31_translate_addr(const union dmub_addr *addr_in,
void dmub_dcn31_reset(struct dmub_srv *dmub)
{
union dmub_gpint_data_register cmd;
- const uint32_t timeout = 30;
+ const uint32_t timeout = 100;
uint32_t in_reset, scratch, i;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset);
@@ -95,26 +98,22 @@ void dmub_dcn31_reset(struct dmub_srv *dmub)
/**
* Timeout covers both the ACK and the wait
* for remaining work to finish.
- *
- * This is mostly bound by the PHY disable sequence.
- * Each register check will be greater than 1us, so
- * don't bother using udelay.
*/
for (i = 0; i < timeout; ++i) {
if (dmub->hw_funcs.is_gpint_acked(dmub, cmd))
break;
+
+ udelay(1);
}
for (i = 0; i < timeout; ++i) {
scratch = dmub->hw_funcs.get_gpint_response(dmub);
if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
break;
- }
- /* Clear the GPINT command manually so we don't reset again. */
- cmd.all = 0;
- dmub->hw_funcs.set_gpint(dmub, cmd);
+ udelay(1);
+ }
/* Force reset in case we timed out, DMCUB is likely hung. */
}
@@ -127,6 +126,10 @@ void dmub_dcn31_reset(struct dmub_srv *dmub)
REG_WRITE(DMCUB_OUTBOX1_RPTR, 0);
REG_WRITE(DMCUB_OUTBOX1_WPTR, 0);
REG_WRITE(DMCUB_SCRATCH0, 0);
+
+ /* Clear the GPINT command manually so we don't send anything during boot. */
+ cmd.all = 0;
+ dmub->hw_funcs.set_gpint(dmub, cmd);
}
void dmub_dcn31_reset_release(struct dmub_srv *dmub)
@@ -307,6 +310,21 @@ uint32_t dmub_dcn31_get_gpint_response(struct dmub_srv *dmub)
return REG_READ(DMCUB_SCRATCH7);
}
+uint32_t dmub_dcn31_get_gpint_dataout(struct dmub_srv *dmub)
+{
+ uint32_t dataout = REG_READ(DMCUB_GPINT_DATAOUT);
+
+ REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 0);
+
+ REG_WRITE(DMCUB_GPINT_DATAOUT, 0);
+ REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 1);
+ REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 0);
+
+ REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 1);
+
+ return dataout;
+}
+
union dmub_fw_boot_status dmub_dcn31_get_fw_boot_status(struct dmub_srv *dmub)
{
union dmub_fw_boot_status status;
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
index 9456a6a2d518..bb62605d2ac8 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
@@ -114,7 +114,9 @@ struct dmub_srv;
DMUB_SR(DMCUB_TIMER_CURRENT) \
DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \
DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \
- DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR)
+ DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) \
+ DMUB_SR(DMCUB_INTERRUPT_ENABLE) \
+ DMUB_SR(DMCUB_INTERRUPT_ACK)
#define DMUB_DCN31_FIELDS() \
DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
@@ -147,7 +149,9 @@ struct dmub_srv;
DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
- DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR)
+ DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \
+ DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \
+ DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK)
struct dmub_srv_dcn31_reg_offset {
#define DMUB_SR(reg) uint32_t reg;
@@ -222,6 +226,8 @@ bool dmub_dcn31_is_gpint_acked(struct dmub_srv *dmub,
uint32_t dmub_dcn31_get_gpint_response(struct dmub_srv *dmub);
+uint32_t dmub_dcn31_get_gpint_dataout(struct dmub_srv *dmub);
+
void dmub_dcn31_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params);
void dmub_dcn31_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index 2bdbd7406f56..75a91cfaf036 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -224,6 +224,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->set_gpint = dmub_dcn31_set_gpint;
funcs->is_gpint_acked = dmub_dcn31_is_gpint_acked;
funcs->get_gpint_response = dmub_dcn31_get_gpint_response;
+ funcs->get_gpint_dataout = dmub_dcn31_get_gpint_dataout;
funcs->get_fw_status = dmub_dcn31_get_fw_boot_status;
funcs->enable_dmub_boot_options = dmub_dcn31_enable_dmub_boot_options;
funcs->skip_dmub_panel_power_sequence = dmub_dcn31_skip_dmub_panel_power_sequence;
@@ -719,6 +720,22 @@ enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub,
return DMUB_STATUS_OK;
}
+enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub,
+ uint32_t *dataout)
+{
+ *dataout = 0;
+
+ if (!dmub->sw_init)
+ return DMUB_STATUS_INVALID;
+
+ if (!dmub->hw_funcs.get_gpint_dataout)
+ return DMUB_STATUS_INVALID;
+
+ *dataout = dmub->hw_funcs.get_gpint_dataout(dmub);
+
+ return DMUB_STATUS_OK;
+}
+
enum dmub_status dmub_srv_get_fw_boot_status(struct dmub_srv *dmub,
union dmub_fw_boot_status *status)
{
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c
index b963226e8af4..3e81850a7ffe 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c
@@ -39,8 +39,12 @@ static void push_error_status(struct mod_hdcp *hdcp,
if (is_hdcp1(hdcp)) {
hdcp->connection.hdcp1_retry_count++;
+ if (hdcp->connection.hdcp1_retry_count == MAX_NUM_OF_ATTEMPTS)
+ hdcp->connection.link.adjust.hdcp1.disable = 1;
} else if (is_hdcp2(hdcp)) {
hdcp->connection.hdcp2_retry_count++;
+ if (hdcp->connection.hdcp2_retry_count == MAX_NUM_OF_ATTEMPTS)
+ hdcp->connection.link.adjust.hdcp2.disable = 1;
}
}
@@ -59,8 +63,7 @@ static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp)
}
}
- return (hdcp->connection.hdcp1_retry_count < MAX_NUM_OF_ATTEMPTS) &&
- is_auth_needed &&
+ return is_auth_needed &&
!hdcp->connection.link.adjust.hdcp1.disable &&
!hdcp->connection.is_hdcp1_revoked;
}
@@ -80,8 +83,7 @@ static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp)
}
}
- return (hdcp->connection.hdcp2_retry_count < MAX_NUM_OF_ATTEMPTS) &&
- is_auth_needed &&
+ return is_auth_needed &&
!hdcp->connection.link.adjust.hdcp2.disable &&
!hdcp->connection.is_hdcp2_revoked;
}
@@ -143,6 +145,7 @@ static enum mod_hdcp_status transition(struct mod_hdcp *hdcp,
} else {
callback_in_ms(0, output);
set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
+ set_auth_complete(hdcp, output);
}
else if (is_hdmi_dvi_sl_hdcp(hdcp))
if (is_cp_desired_hdcp2(hdcp)) {
@@ -154,10 +157,12 @@ static enum mod_hdcp_status transition(struct mod_hdcp *hdcp,
} else {
callback_in_ms(0, output);
set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
+ set_auth_complete(hdcp, output);
}
else {
callback_in_ms(0, output);
set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
+ set_auth_complete(hdcp, output);
}
} else if (is_in_cp_not_desired_state(hdcp)) {
increment_stay_counter(hdcp);
@@ -313,9 +318,6 @@ enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
goto out;
}
- /* save current encryption states to restore after next authentication */
- mod_hdcp_save_current_encryption_states(hdcp);
-
/* reset existing authentication status */
status = reset_authentication(hdcp, output);
if (status != MOD_HDCP_STATUS_SUCCESS)
@@ -362,9 +364,6 @@ enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
goto out;
}
- /* save current encryption states to restore after next authentication */
- mod_hdcp_save_current_encryption_states(hdcp);
-
/* stop current authentication */
status = reset_authentication(hdcp, output);
if (status != MOD_HDCP_STATUS_SUCCESS)
@@ -392,6 +391,60 @@ out:
return status;
}
+enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp,
+ uint8_t index,
+ struct mod_hdcp_link_adjustment *link_adjust,
+ struct mod_hdcp_display_adjustment *display_adjust,
+ struct mod_hdcp_output *output)
+{
+ enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+ struct mod_hdcp_display *display = NULL;
+
+ HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
+ memset(output, 0, sizeof(struct mod_hdcp_output));
+
+ /* find display in connection */
+ display = get_active_display_at_index(hdcp, index);
+ if (!display) {
+ status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
+ goto out;
+ }
+
+ /* skip if no changes */
+ if (memcmp(link_adjust, &hdcp->connection.link.adjust,
+ sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
+ memcmp(display_adjust, &display->adjust,
+ sizeof(struct mod_hdcp_display_adjustment)) == 0) {
+ status = MOD_HDCP_STATUS_SUCCESS;
+ goto out;
+ }
+
+ /* stop current authentication */
+ status = reset_authentication(hdcp, output);
+ if (status != MOD_HDCP_STATUS_SUCCESS)
+ goto out;
+
+ /* clear retry counters */
+ reset_retry_counts(hdcp);
+
+ /* reset error trace */
+ memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
+
+ /* set new adjustment */
+ hdcp->connection.link.adjust = *link_adjust;
+ display->adjust = *display_adjust;
+
+ /* request authentication when connection is not reset */
+ if (current_state(hdcp) != HDCP_UNINITIALIZED)
+ /* wait 100ms to debounce simultaneous updates for different indices */
+ callback_in_ms(100, output);
+
+out:
+ if (status != MOD_HDCP_STATUS_SUCCESS)
+ push_error_status(hdcp, status);
+ return status;
+}
+
enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
uint8_t index, struct mod_hdcp_display_query *query)
{
@@ -470,7 +523,7 @@ enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp,
/* reset authentication if needed */
if (trans_status == MOD_HDCP_STATUS_RESET_NEEDED) {
- HDCP_FULL_DDC_TRACE(hdcp);
+ mod_hdcp_log_ddc_trace(hdcp);
reset_status = reset_authentication(hdcp, output);
if (reset_status != MOD_HDCP_STATUS_SUCCESS)
push_error_status(hdcp, reset_status);
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
index 3ce91db560d1..399fbca8947b 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
@@ -324,6 +324,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_dp_transition(struct mod_hdcp *hdcp,
/* log functions */
void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size,
uint8_t *buf, uint32_t buf_size);
+void mod_hdcp_log_ddc_trace(struct mod_hdcp *hdcp);
/* TODO: add adjustment log */
/* psp functions */
@@ -331,8 +332,6 @@ enum mod_hdcp_status mod_hdcp_add_display_to_topology(
struct mod_hdcp *hdcp, struct mod_hdcp_display *display);
enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
struct mod_hdcp *hdcp, uint8_t index);
-bool mod_hdcp_is_link_encryption_enabled(struct mod_hdcp *hdcp);
-void mod_hdcp_save_current_encryption_states(struct mod_hdcp *hdcp);
enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp);
enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp);
enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp);
@@ -496,6 +495,13 @@ static inline void set_watchdog_in_ms(struct mod_hdcp *hdcp, uint16_t time,
output->watchdog_timer_delay = time;
}
+static inline void set_auth_complete(struct mod_hdcp *hdcp,
+ struct mod_hdcp_output *output)
+{
+ output->auth_complete = 1;
+ mod_hdcp_log_ddc_trace(hdcp);
+}
+
/* connection topology helpers */
static inline uint8_t is_display_active(struct mod_hdcp_display *display)
{
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
index de872e7958b0..6ec918af3bff 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
@@ -266,9 +266,6 @@ static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp,
mod_hdcp_execute_and_set(mod_hdcp_hdcp1_link_maintenance,
&input->link_maintenance, &status,
hdcp, "link_maintenance");
-
- if (status != MOD_HDCP_STATUS_SUCCESS)
- mod_hdcp_save_current_encryption_states(hdcp);
out:
return status;
}
@@ -447,9 +444,6 @@ static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp,
mod_hdcp_execute_and_set(check_no_reauthentication_request_dp,
&input->reauth_request_check, &status,
hdcp, "reauth_request_check");
-
- if (status != MOD_HDCP_STATUS_SUCCESS)
- mod_hdcp_save_current_encryption_states(hdcp);
out:
return status;
}
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c
index 3dda8c1d83fc..7f011196ce98 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c
@@ -89,7 +89,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp,
} else {
callback_in_ms(0, output);
set_state_id(hdcp, output, H1_A45_AUTHENTICATED);
- HDCP_FULL_DDC_TRACE(hdcp);
+ set_auth_complete(hdcp, output);
}
break;
case H1_A45_AUTHENTICATED:
@@ -137,7 +137,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp,
}
callback_in_ms(0, output);
set_state_id(hdcp, output, H1_A45_AUTHENTICATED);
- HDCP_FULL_DDC_TRACE(hdcp);
+ set_auth_complete(hdcp, output);
break;
default:
status = MOD_HDCP_STATUS_INVALID_STATE;
@@ -239,7 +239,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp,
set_state_id(hdcp, output, D1_A6_WAIT_FOR_READY);
} else {
set_state_id(hdcp, output, D1_A4_AUTHENTICATED);
- HDCP_FULL_DDC_TRACE(hdcp);
+ set_auth_complete(hdcp, output);
}
break;
case D1_A4_AUTHENTICATED:
@@ -311,7 +311,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp,
break;
}
set_state_id(hdcp, output, D1_A4_AUTHENTICATED);
- HDCP_FULL_DDC_TRACE(hdcp);
+ set_auth_complete(hdcp, output);
break;
default:
fail_and_restart_in_ms(0, &status, output);
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
index 117c6b45f718..91c22b96ebde 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
@@ -571,9 +571,6 @@ static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp,
}
process_rxstatus(hdcp, event_ctx, input, &status);
-
- if (status != MOD_HDCP_STATUS_SUCCESS)
- mod_hdcp_save_current_encryption_states(hdcp);
out:
return status;
}
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c
index 70cb230d8f56..1f4095b26409 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c
@@ -242,7 +242,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_transition(struct mod_hdcp *hdcp,
}
callback_in_ms(0, output);
set_state_id(hdcp, output, H2_A5_AUTHENTICATED);
- HDCP_FULL_DDC_TRACE(hdcp);
+ set_auth_complete(hdcp, output);
break;
case H2_A5_AUTHENTICATED:
if (input->rxstatus_read == FAIL ||
@@ -559,7 +559,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_dp_transition(struct mod_hdcp *hdcp,
break;
}
set_state_id(hdcp, output, D2_A5_AUTHENTICATED);
- HDCP_FULL_DDC_TRACE(hdcp);
+ set_auth_complete(hdcp, output);
break;
case D2_A5_AUTHENTICATED:
if (input->rxstatus_read == FAIL ||
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c
index 1a0f7c3dc964..6b3b5f610907 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c
@@ -51,6 +51,80 @@ void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size,
}
}
+void mod_hdcp_log_ddc_trace(struct mod_hdcp *hdcp)
+{
+ if (is_hdcp1(hdcp)) {
+ HDCP_DDC_READ_TRACE(hdcp, "BKSV", hdcp->auth.msg.hdcp1.bksv,
+ sizeof(hdcp->auth.msg.hdcp1.bksv));
+ HDCP_DDC_READ_TRACE(hdcp, "BCAPS", &hdcp->auth.msg.hdcp1.bcaps,
+ sizeof(hdcp->auth.msg.hdcp1.bcaps));
+ HDCP_DDC_READ_TRACE(hdcp, "BSTATUS",
+ (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
+ sizeof(hdcp->auth.msg.hdcp1.bstatus));
+ HDCP_DDC_WRITE_TRACE(hdcp, "AN", hdcp->auth.msg.hdcp1.an,
+ sizeof(hdcp->auth.msg.hdcp1.an));
+ HDCP_DDC_WRITE_TRACE(hdcp, "AKSV", hdcp->auth.msg.hdcp1.aksv,
+ sizeof(hdcp->auth.msg.hdcp1.aksv));
+ HDCP_DDC_WRITE_TRACE(hdcp, "AINFO", &hdcp->auth.msg.hdcp1.ainfo,
+ sizeof(hdcp->auth.msg.hdcp1.ainfo));
+ HDCP_DDC_READ_TRACE(hdcp, "RI' / R0'",
+ (uint8_t *)&hdcp->auth.msg.hdcp1.r0p,
+ sizeof(hdcp->auth.msg.hdcp1.r0p));
+ HDCP_DDC_READ_TRACE(hdcp, "BINFO",
+ (uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp,
+ sizeof(hdcp->auth.msg.hdcp1.binfo_dp));
+ HDCP_DDC_READ_TRACE(hdcp, "KSVLIST", hdcp->auth.msg.hdcp1.ksvlist,
+ hdcp->auth.msg.hdcp1.ksvlist_size);
+ HDCP_DDC_READ_TRACE(hdcp, "V'", hdcp->auth.msg.hdcp1.vp,
+ sizeof(hdcp->auth.msg.hdcp1.vp));
+ } else if (is_hdcp2(hdcp)) {
+ HDCP_DDC_READ_TRACE(hdcp, "HDCP2Version",
+ &hdcp->auth.msg.hdcp2.hdcp2version_hdmi,
+ sizeof(hdcp->auth.msg.hdcp2.hdcp2version_hdmi));
+ HDCP_DDC_READ_TRACE(hdcp, "Rx Caps", hdcp->auth.msg.hdcp2.rxcaps_dp,
+ sizeof(hdcp->auth.msg.hdcp2.rxcaps_dp));
+ HDCP_DDC_WRITE_TRACE(hdcp, "AKE Init", hdcp->auth.msg.hdcp2.ake_init,
+ sizeof(hdcp->auth.msg.hdcp2.ake_init));
+ HDCP_DDC_READ_TRACE(hdcp, "AKE Cert", hdcp->auth.msg.hdcp2.ake_cert,
+ sizeof(hdcp->auth.msg.hdcp2.ake_cert));
+ HDCP_DDC_WRITE_TRACE(hdcp, "Stored KM",
+ hdcp->auth.msg.hdcp2.ake_stored_km,
+ sizeof(hdcp->auth.msg.hdcp2.ake_stored_km));
+ HDCP_DDC_WRITE_TRACE(hdcp, "No Stored KM",
+ hdcp->auth.msg.hdcp2.ake_no_stored_km,
+ sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km));
+ HDCP_DDC_READ_TRACE(hdcp, "H'", hdcp->auth.msg.hdcp2.ake_h_prime,
+ sizeof(hdcp->auth.msg.hdcp2.ake_h_prime));
+ HDCP_DDC_READ_TRACE(hdcp, "Pairing Info",
+ hdcp->auth.msg.hdcp2.ake_pairing_info,
+ sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info));
+ HDCP_DDC_WRITE_TRACE(hdcp, "LC Init", hdcp->auth.msg.hdcp2.lc_init,
+ sizeof(hdcp->auth.msg.hdcp2.lc_init));
+ HDCP_DDC_READ_TRACE(hdcp, "L'", hdcp->auth.msg.hdcp2.lc_l_prime,
+ sizeof(hdcp->auth.msg.hdcp2.lc_l_prime));
+ HDCP_DDC_WRITE_TRACE(hdcp, "Exchange KS", hdcp->auth.msg.hdcp2.ske_eks,
+ sizeof(hdcp->auth.msg.hdcp2.ske_eks));
+ HDCP_DDC_READ_TRACE(hdcp, "Rx Status",
+ (uint8_t *)&hdcp->auth.msg.hdcp2.rxstatus,
+ sizeof(hdcp->auth.msg.hdcp2.rxstatus));
+ HDCP_DDC_READ_TRACE(hdcp, "Rx Id List",
+ hdcp->auth.msg.hdcp2.rx_id_list,
+ hdcp->auth.msg.hdcp2.rx_id_list_size);
+ HDCP_DDC_WRITE_TRACE(hdcp, "Rx Id List Ack",
+ hdcp->auth.msg.hdcp2.repeater_auth_ack,
+ sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack));
+ HDCP_DDC_WRITE_TRACE(hdcp, "Content Stream Management",
+ hdcp->auth.msg.hdcp2.repeater_auth_stream_manage,
+ hdcp->auth.msg.hdcp2.stream_manage_size);
+ HDCP_DDC_READ_TRACE(hdcp, "Stream Ready",
+ hdcp->auth.msg.hdcp2.repeater_auth_stream_ready,
+ sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready));
+ HDCP_DDC_WRITE_TRACE(hdcp, "Content Stream Type",
+ hdcp->auth.msg.hdcp2.content_stream_type_dp,
+ sizeof(hdcp->auth.msg.hdcp2.content_stream_type_dp));
+ }
+}
+
char *mod_hdcp_status_to_str(int32_t status)
{
switch (status) {
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h
index 47f8ee2832ff..eb6f9b9c504a 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h
@@ -106,78 +106,6 @@
hdcp->config.index, msg_name,\
hdcp->buf); \
} while (0)
-#define HDCP_FULL_DDC_TRACE(hdcp) do { \
- if (is_hdcp1(hdcp)) { \
- HDCP_DDC_READ_TRACE(hdcp, "BKSV", hdcp->auth.msg.hdcp1.bksv, \
- sizeof(hdcp->auth.msg.hdcp1.bksv)); \
- HDCP_DDC_READ_TRACE(hdcp, "BCAPS", &hdcp->auth.msg.hdcp1.bcaps, \
- sizeof(hdcp->auth.msg.hdcp1.bcaps)); \
- HDCP_DDC_READ_TRACE(hdcp, "BSTATUS", \
- (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus, \
- sizeof(hdcp->auth.msg.hdcp1.bstatus)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "AN", hdcp->auth.msg.hdcp1.an, \
- sizeof(hdcp->auth.msg.hdcp1.an)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "AKSV", hdcp->auth.msg.hdcp1.aksv, \
- sizeof(hdcp->auth.msg.hdcp1.aksv)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "AINFO", &hdcp->auth.msg.hdcp1.ainfo, \
- sizeof(hdcp->auth.msg.hdcp1.ainfo)); \
- HDCP_DDC_READ_TRACE(hdcp, "RI' / R0'", \
- (uint8_t *)&hdcp->auth.msg.hdcp1.r0p, \
- sizeof(hdcp->auth.msg.hdcp1.r0p)); \
- HDCP_DDC_READ_TRACE(hdcp, "BINFO", \
- (uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp, \
- sizeof(hdcp->auth.msg.hdcp1.binfo_dp)); \
- HDCP_DDC_READ_TRACE(hdcp, "KSVLIST", hdcp->auth.msg.hdcp1.ksvlist, \
- hdcp->auth.msg.hdcp1.ksvlist_size); \
- HDCP_DDC_READ_TRACE(hdcp, "V'", hdcp->auth.msg.hdcp1.vp, \
- sizeof(hdcp->auth.msg.hdcp1.vp)); \
- } else { \
- HDCP_DDC_READ_TRACE(hdcp, "HDCP2Version", \
- &hdcp->auth.msg.hdcp2.hdcp2version_hdmi, \
- sizeof(hdcp->auth.msg.hdcp2.hdcp2version_hdmi)); \
- HDCP_DDC_READ_TRACE(hdcp, "Rx Caps", hdcp->auth.msg.hdcp2.rxcaps_dp, \
- sizeof(hdcp->auth.msg.hdcp2.rxcaps_dp)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "AKE Init", hdcp->auth.msg.hdcp2.ake_init, \
- sizeof(hdcp->auth.msg.hdcp2.ake_init)); \
- HDCP_DDC_READ_TRACE(hdcp, "AKE Cert", hdcp->auth.msg.hdcp2.ake_cert, \
- sizeof(hdcp->auth.msg.hdcp2.ake_cert)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "Stored KM", \
- hdcp->auth.msg.hdcp2.ake_stored_km, \
- sizeof(hdcp->auth.msg.hdcp2.ake_stored_km)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "No Stored KM", \
- hdcp->auth.msg.hdcp2.ake_no_stored_km, \
- sizeof(hdcp->auth.msg.hdcp2.ake_no_stored_km)); \
- HDCP_DDC_READ_TRACE(hdcp, "H'", hdcp->auth.msg.hdcp2.ake_h_prime, \
- sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)); \
- HDCP_DDC_READ_TRACE(hdcp, "Pairing Info", \
- hdcp->auth.msg.hdcp2.ake_pairing_info, \
- sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "LC Init", hdcp->auth.msg.hdcp2.lc_init, \
- sizeof(hdcp->auth.msg.hdcp2.lc_init)); \
- HDCP_DDC_READ_TRACE(hdcp, "L'", hdcp->auth.msg.hdcp2.lc_l_prime, \
- sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "Exchange KS", hdcp->auth.msg.hdcp2.ske_eks, \
- sizeof(hdcp->auth.msg.hdcp2.ske_eks)); \
- HDCP_DDC_READ_TRACE(hdcp, "Rx Status", \
- (uint8_t *)&hdcp->auth.msg.hdcp2.rxstatus, \
- sizeof(hdcp->auth.msg.hdcp2.rxstatus)); \
- HDCP_DDC_READ_TRACE(hdcp, "Rx Id List", \
- hdcp->auth.msg.hdcp2.rx_id_list, \
- hdcp->auth.msg.hdcp2.rx_id_list_size); \
- HDCP_DDC_WRITE_TRACE(hdcp, "Rx Id List Ack", \
- hdcp->auth.msg.hdcp2.repeater_auth_ack, \
- sizeof(hdcp->auth.msg.hdcp2.repeater_auth_ack)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "Content Stream Management", \
- hdcp->auth.msg.hdcp2.repeater_auth_stream_manage, \
- hdcp->auth.msg.hdcp2.stream_manage_size); \
- HDCP_DDC_READ_TRACE(hdcp, "Stream Ready", \
- hdcp->auth.msg.hdcp2.repeater_auth_stream_ready, \
- sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)); \
- HDCP_DDC_WRITE_TRACE(hdcp, "Content Stream Type", \
- hdcp->auth.msg.hdcp2.content_stream_type_dp, \
- sizeof(hdcp->auth.msg.hdcp2.content_stream_type_dp)); \
- } \
-} while (0)
#define HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, i) \
HDCP_LOG_TOP(hdcp, "[Link %d]\tadd display %d", \
hdcp->config.index, i)
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
index 1b02056bc8bd..e9bd84ec027d 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
@@ -45,7 +45,7 @@ static void hdcp2_message_init(struct mod_hdcp *hdcp,
in->process.msg3_desc.msg_size = 0;
}
-static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v2(
+static enum mod_hdcp_status remove_display_from_topology_v2(
struct mod_hdcp *hdcp, uint8_t index)
{
struct psp_context *psp = hdcp->config.psp.handle;
@@ -54,7 +54,7 @@ static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v2(
get_active_display_at_index(hdcp, index);
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
- dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
+ dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.context.mem_context.shared_buf;
if (!display || !is_display_active(display))
return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
@@ -81,7 +81,7 @@ static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v2(
return status;
}
-static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v3(
+static enum mod_hdcp_status remove_display_from_topology_v3(
struct mod_hdcp *hdcp, uint8_t index)
{
struct psp_context *psp = hdcp->config.psp.handle;
@@ -90,7 +90,7 @@ static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v3(
get_active_display_at_index(hdcp, index);
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
- dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
+ dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.context.mem_context.shared_buf;
if (!display || !is_display_active(display))
return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
@@ -107,7 +107,7 @@ static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v3(
psp_dtm_invoke(psp, dtm_cmd->cmd_id);
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
- status = mod_hdcp_remove_display_from_topology_v2(hdcp, index);
+ status = remove_display_from_topology_v2(hdcp, index);
if (status != MOD_HDCP_STATUS_SUCCESS)
display->state = MOD_HDCP_DISPLAY_INACTIVE;
} else {
@@ -120,20 +120,7 @@ static enum mod_hdcp_status mod_hdcp_remove_display_from_topology_v3(
return status;
}
-enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
- struct mod_hdcp *hdcp, uint8_t index)
-{
- enum mod_hdcp_status status = MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE;
-
- if (hdcp->config.psp.caps.dtm_v3_supported)
- status = mod_hdcp_remove_display_from_topology_v3(hdcp, index);
- else
- status = mod_hdcp_remove_display_from_topology_v2(hdcp, index);
-
- return status;
-}
-
-static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v2(
+static enum mod_hdcp_status add_display_to_topology_v2(
struct mod_hdcp *hdcp, struct mod_hdcp_display *display)
{
struct psp_context *psp = hdcp->config.psp.handle;
@@ -141,13 +128,13 @@ static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v2(
struct mod_hdcp_link *link = &hdcp->connection.link;
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
- if (!psp->dtm_context.dtm_initialized) {
+ if (!psp->dtm_context.context.initialized) {
DRM_INFO("Failed to add display topology, DTM TA is not initialized.");
display->state = MOD_HDCP_DISPLAY_INACTIVE;
return MOD_HDCP_STATUS_FAILURE;
}
- dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
+ dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.context.mem_context.shared_buf;
mutex_lock(&psp->dtm_context.mutex);
memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory));
@@ -180,7 +167,7 @@ static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v2(
return status;
}
-static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v3(
+static enum mod_hdcp_status add_display_to_topology_v3(
struct mod_hdcp *hdcp, struct mod_hdcp_display *display)
{
struct psp_context *psp = hdcp->config.psp.handle;
@@ -188,13 +175,13 @@ static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v3(
struct mod_hdcp_link *link = &hdcp->connection.link;
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
- if (!psp->dtm_context.dtm_initialized) {
+ if (!psp->dtm_context.context.initialized) {
DRM_INFO("Failed to add display topology, DTM TA is not initialized.");
display->state = MOD_HDCP_DISPLAY_INACTIVE;
return MOD_HDCP_STATUS_FAILURE;
}
- dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
+ dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.context.mem_context.shared_buf;
mutex_lock(&psp->dtm_context.mutex);
memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory));
@@ -220,7 +207,7 @@ static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v3(
psp_dtm_invoke(psp, dtm_cmd->cmd_id);
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
- status = mod_hdcp_add_display_to_topology_v2(hdcp, display);
+ status = add_display_to_topology_v2(hdcp, display);
if (status != MOD_HDCP_STATUS_SUCCESS)
display->state = MOD_HDCP_DISPLAY_INACTIVE;
} else {
@@ -232,15 +219,28 @@ static enum mod_hdcp_status mod_hdcp_add_display_to_topology_v3(
return status;
}
+enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
+ struct mod_hdcp *hdcp, uint8_t index)
+{
+ enum mod_hdcp_status status = MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE;
+
+ if (hdcp->config.psp.caps.dtm_v3_supported)
+ status = remove_display_from_topology_v3(hdcp, index);
+ else
+ status = remove_display_from_topology_v2(hdcp, index);
+
+ return status;
+}
+
enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp,
struct mod_hdcp_display *display)
{
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
if (hdcp->config.psp.caps.dtm_v3_supported)
- status = mod_hdcp_add_display_to_topology_v3(hdcp, display);
+ status = add_display_to_topology_v3(hdcp, display);
else
- status = mod_hdcp_add_display_to_topology_v2(hdcp, display);
+ status = add_display_to_topology_v2(hdcp, display);
return status;
}
@@ -253,12 +253,12 @@ enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp)
struct ta_hdcp_shared_memory *hdcp_cmd;
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
- if (!psp->hdcp_context.hdcp_initialized) {
+ if (!psp->hdcp_context.context.initialized) {
DRM_ERROR("Failed to create hdcp session. HDCP TA is not initialized.");
return MOD_HDCP_STATUS_FAILURE;
}
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
mutex_lock(&psp->hdcp_context.mutex);
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
@@ -293,7 +293,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
hdcp_cmd->in_msg.hdcp1_destroy_session.session_handle = hdcp->auth.id;
@@ -325,7 +325,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
hdcp_cmd->in_msg.hdcp1_first_part_authentication.session_handle = hdcp->auth.id;
@@ -367,7 +367,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_enable_encryption(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
hdcp_cmd->in_msg.hdcp1_enable_encryption.session_handle = hdcp->auth.id;
@@ -393,7 +393,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
hdcp_cmd->in_msg.hdcp1_second_part_authentication.session_handle = hdcp->auth.id;
@@ -436,7 +436,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(struct mod_hdcp
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
@@ -471,7 +471,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_link_maintenance(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
@@ -498,7 +498,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_create_session(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
- if (!psp->hdcp_context.hdcp_initialized) {
+ if (!psp->hdcp_context.context.initialized) {
DRM_ERROR("Failed to create hdcp session, HDCP TA is not initialized");
return MOD_HDCP_STATUS_FAILURE;
}
@@ -508,7 +508,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_create_session(struct mod_hdcp *hdcp)
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
hdcp_cmd->in_msg.hdcp2_create_session_v2.display_handle = display->index;
@@ -545,7 +545,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_destroy_session(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
hdcp_cmd->in_msg.hdcp2_destroy_session.session_handle = hdcp->auth.id;
@@ -579,7 +579,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_prepare_ake_init(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -611,7 +611,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_ake_cert(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -671,7 +671,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_h_prime(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -717,7 +717,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_prepare_lc_init(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -750,7 +750,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_l_prime(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -785,7 +785,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_prepare_eks(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -833,7 +833,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_enable_encryption(struct mod_hdcp *hdcp)
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
hdcp_cmd->in_msg.hdcp2_set_encryption.session_handle = hdcp->auth.id;
@@ -862,7 +862,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_rx_id_list(struct mod_hdcp *hdcp)
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -914,7 +914,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_enable_dp_stream_encryption(struct mod_hdcp
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -958,7 +958,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_prepare_stream_management(struct mod_hdcp *h
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -994,7 +994,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_stream_ready(struct mod_hdcp *hdcp)
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
mutex_lock(&psp->hdcp_context.mutex);
- hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
msg_in = &hdcp_cmd->in_msg.hdcp2_prepare_process_authentication_message_v2;
@@ -1021,14 +1021,3 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_stream_ready(struct mod_hdcp *hdcp)
mutex_unlock(&psp->hdcp_context.mutex);
return status;
}
-
-bool mod_hdcp_is_link_encryption_enabled(struct mod_hdcp *hdcp)
-{
- /* unsupported */
- return true;
-}
-
-void mod_hdcp_save_current_encryption_states(struct mod_hdcp *hdcp)
-{
- /* unsupported */
-}
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
index c590493fd293..f37101f5a777 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
@@ -123,7 +123,6 @@ enum mod_hdcp_display_state {
struct mod_hdcp_psp_caps {
uint8_t dtm_v3_supported;
- uint8_t opm_state_query_supported;
};
enum mod_hdcp_display_disable_option {
@@ -226,6 +225,7 @@ struct mod_hdcp_output {
uint8_t watchdog_timer_stop;
uint16_t callback_delay;
uint16_t watchdog_timer_delay;
+ uint8_t auth_complete;
};
/* used to represent per display info */
@@ -282,15 +282,22 @@ enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp,
/* called per link on link destroy */
enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp);
-/* called per display on cp_desired set to true */
+/* called per display after stream is enabled */
enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
struct mod_hdcp_link *link, struct mod_hdcp_display *display,
struct mod_hdcp_output *output);
-/* called per display on cp_desired set to false */
+/* called per display before stream is disabled */
enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
uint8_t index, struct mod_hdcp_output *output);
+/* called per display to apply new authentication adjustment */
+enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp,
+ uint8_t index,
+ struct mod_hdcp_link_adjustment *link_adjust,
+ struct mod_hdcp_display_adjustment *display_adjust,
+ struct mod_hdcp_output *output);
+
/* called to query hdcp information on a specific index */
enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
uint8_t index, struct mod_hdcp_display_query *query);
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index ff1d3d4a6488..257f280d3d53 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -47,6 +47,7 @@ enum amd_apu_flags {
AMD_APU_IS_RENOIR = 0x00000008UL,
AMD_APU_IS_GREEN_SARDINE = 0x00000010UL,
AMD_APU_IS_VANGOGH = 0x00000020UL,
+ AMD_APU_IS_CYAN_SKILLFISH2 = 0x00000040UL,
};
/**
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h
index e5fd0121ceff..a9d553ef26c0 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h
@@ -5971,6 +5971,7 @@
#define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT1_INT_EN__SHIFT 0xb
#define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT2_INT_EN__SHIFT 0xc
#define DMCUB_INTERRUPT_ENABLE__DMCUB_UNDEFINED_ADDRESS_FAULT_INT_EN__SHIFT 0xd
+#define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT_IH_INT_EN__SHIFT 0x11
#define DMCUB_INTERRUPT_ENABLE__DMCUB_TIMER0_INT_EN_MASK 0x00000001L
#define DMCUB_INTERRUPT_ENABLE__DMCUB_TIMER1_INT_EN_MASK 0x00000002L
#define DMCUB_INTERRUPT_ENABLE__DMCUB_INBOX0_READY_INT_EN_MASK 0x00000004L
@@ -5985,6 +5986,7 @@
#define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT1_INT_EN_MASK 0x00000800L
#define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT2_INT_EN_MASK 0x00001000L
#define DMCUB_INTERRUPT_ENABLE__DMCUB_UNDEFINED_ADDRESS_FAULT_INT_EN_MASK 0x00002000L
+#define DMCUB_INTERRUPT_ENABLE__DMCUB_GPINT_IH_INT_EN_MASK 0x00020000L
//DMCUB_INTERRUPT_ACK
#define DMCUB_INTERRUPT_ACK__DMCUB_TIMER0_INT_ACK__SHIFT 0x0
#define DMCUB_INTERRUPT_ACK__DMCUB_TIMER1_INT_ACK__SHIFT 0x1
@@ -6000,6 +6002,7 @@
#define DMCUB_INTERRUPT_ACK__DMCUB_GPINT1_INT_ACK__SHIFT 0xb
#define DMCUB_INTERRUPT_ACK__DMCUB_GPINT2_INT_ACK__SHIFT 0xc
#define DMCUB_INTERRUPT_ACK__DMCUB_UNDEFINED_ADDRESS_FAULT_ACK__SHIFT 0xd
+#define DMCUB_INTERRUPT_ACK__DMCUB_GPINT_IH_INT_ACK__SHIFT 0x11
#define DMCUB_INTERRUPT_ACK__DMCUB_TIMER0_INT_ACK_MASK 0x00000001L
#define DMCUB_INTERRUPT_ACK__DMCUB_TIMER1_INT_ACK_MASK 0x00000002L
#define DMCUB_INTERRUPT_ACK__DMCUB_INBOX0_READY_INT_ACK_MASK 0x00000004L
@@ -6014,6 +6017,7 @@
#define DMCUB_INTERRUPT_ACK__DMCUB_GPINT1_INT_ACK_MASK 0x00000800L
#define DMCUB_INTERRUPT_ACK__DMCUB_GPINT2_INT_ACK_MASK 0x00001000L
#define DMCUB_INTERRUPT_ACK__DMCUB_UNDEFINED_ADDRESS_FAULT_ACK_MASK 0x00002000L
+#define DMCUB_INTERRUPT_ACK__DMCUB_GPINT_IH_INT_ACK_MASK 0x00020000L
//DMCUB_INTERRUPT_STATUS
#define DMCUB_INTERRUPT_STATUS__DMCUB_TIMER0_INT_STAT__SHIFT 0x0
#define DMCUB_INTERRUPT_STATUS__DMCUB_TIMER1_INT_STAT__SHIFT 0x1
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_offset.h
index a9ad00e017a5..1a8a6a350789 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_offset.h
@@ -508,6 +508,10 @@
#define regCP_ME2_PIPE2_INT_STATUS_BASE_IDX 0
#define regCP_ME2_PIPE3_INT_STATUS 0x1094
#define regCP_ME2_PIPE3_INT_STATUS_BASE_IDX 0
+#define regCP_ME1_INT_STAT_DEBUG 0x1095
+#define regCP_ME1_INT_STAT_DEBUG_BASE_IDX 0
+#define regCP_ME2_INT_STAT_DEBUG 0x1096
+#define regCP_ME2_INT_STAT_DEBUG_BASE_IDX 0
#define regCC_GC_EDC_CONFIG 0x1098
#define regCC_GC_EDC_CONFIG_BASE_IDX 0
#define regCP_ME1_PIPE_PRIORITY_CNTS 0x1099
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_sh_mask.h
index bc4d2997cb51..049221262e5c 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_2_sh_mask.h
@@ -2989,6 +2989,60 @@
#define CP_ME1_PIPE3_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000L
#define CP_ME1_PIPE3_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000L
#define CP_ME1_PIPE3_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000L
+//CP_ME1_INT_STAT_DEBUG
+#define CP_ME1_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED__SHIFT 0xc
+#define CP_ME1_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED__SHIFT 0xd
+#define CP_ME1_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0xe
+#define CP_ME1_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME1_INT_STAT_DEBUG__GPF_INT_ASSERTED__SHIFT 0x10
+#define CP_ME1_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x11
+#define CP_ME1_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x17
+#define CP_ME1_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x18
+#define CP_ME1_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x1a
+#define CP_ME1_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x1b
+#define CP_ME1_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x1d
+#define CP_ME1_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x1e
+#define CP_ME1_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x1f
+#define CP_ME1_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED_MASK 0x00001000L
+#define CP_ME1_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED_MASK 0x00002000L
+#define CP_ME1_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x00004000L
+#define CP_ME1_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS_MASK 0x00008000L
+#define CP_ME1_INT_STAT_DEBUG__GPF_INT_ASSERTED_MASK 0x00010000L
+#define CP_ME1_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x00020000L
+#define CP_ME1_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x00800000L
+#define CP_ME1_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x01000000L
+#define CP_ME1_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x04000000L
+#define CP_ME1_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x08000000L
+#define CP_ME1_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000L
+#define CP_ME1_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000L
+#define CP_ME1_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000L
+//CP_ME2_INT_STAT_DEBUG
+#define CP_ME2_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED__SHIFT 0xc
+#define CP_ME2_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED__SHIFT 0xd
+#define CP_ME2_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0xe
+#define CP_ME2_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
+#define CP_ME2_INT_STAT_DEBUG__GPF_INT_ASSERTED__SHIFT 0x10
+#define CP_ME2_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x11
+#define CP_ME2_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x17
+#define CP_ME2_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x18
+#define CP_ME2_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x1a
+#define CP_ME2_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x1b
+#define CP_ME2_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x1d
+#define CP_ME2_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x1e
+#define CP_ME2_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x1f
+#define CP_ME2_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED_MASK 0x00001000L
+#define CP_ME2_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED_MASK 0x00002000L
+#define CP_ME2_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x00004000L
+#define CP_ME2_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS_MASK 0x00008000L
+#define CP_ME2_INT_STAT_DEBUG__GPF_INT_ASSERTED_MASK 0x00010000L
+#define CP_ME2_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x00020000L
+#define CP_ME2_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x00800000L
+#define CP_ME2_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x01000000L
+#define CP_ME2_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x04000000L
+#define CP_ME2_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x08000000L
+#define CP_ME2_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000L
+#define CP_ME2_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000L
+#define CP_ME2_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000L
//CP_ME2_PIPE0_INT_STATUS
#define CP_ME2_PIPE0_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
#define CP_ME2_PIPE0_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd
diff --git a/drivers/gpu/drm/amd/include/asic_reg/mp/mp_11_0_8_offset.h b/drivers/gpu/drm/amd/include/asic_reg/mp/mp_11_0_8_offset.h
new file mode 100644
index 000000000000..19293ccaec23
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/mp/mp_11_0_8_offset.h
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _mp_11_0_8_OFFSET_HEADER
+#define _mp_11_0_8_OFFSET_HEADER
+
+
+
+// addressBlock: mp_SmuMp0_SmnDec
+// base address: 0x0
+#define mmMP0_SMN_C2PMSG_32 0x0060
+#define mmMP0_SMN_C2PMSG_32_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_33 0x0061
+#define mmMP0_SMN_C2PMSG_33_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_34 0x0062
+#define mmMP0_SMN_C2PMSG_34_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_35 0x0063
+#define mmMP0_SMN_C2PMSG_35_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_36 0x0064
+#define mmMP0_SMN_C2PMSG_36_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_37 0x0065
+#define mmMP0_SMN_C2PMSG_37_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_38 0x0066
+#define mmMP0_SMN_C2PMSG_38_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_39 0x0067
+#define mmMP0_SMN_C2PMSG_39_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_40 0x0068
+#define mmMP0_SMN_C2PMSG_40_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_41 0x0069
+#define mmMP0_SMN_C2PMSG_41_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_42 0x006a
+#define mmMP0_SMN_C2PMSG_42_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_43 0x006b
+#define mmMP0_SMN_C2PMSG_43_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_44 0x006c
+#define mmMP0_SMN_C2PMSG_44_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_45 0x006d
+#define mmMP0_SMN_C2PMSG_45_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_46 0x006e
+#define mmMP0_SMN_C2PMSG_46_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_47 0x006f
+#define mmMP0_SMN_C2PMSG_47_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_48 0x0070
+#define mmMP0_SMN_C2PMSG_48_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_49 0x0071
+#define mmMP0_SMN_C2PMSG_49_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_50 0x0072
+#define mmMP0_SMN_C2PMSG_50_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_51 0x0073
+#define mmMP0_SMN_C2PMSG_51_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_52 0x0074
+#define mmMP0_SMN_C2PMSG_52_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_53 0x0075
+#define mmMP0_SMN_C2PMSG_53_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_54 0x0076
+#define mmMP0_SMN_C2PMSG_54_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_55 0x0077
+#define mmMP0_SMN_C2PMSG_55_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_56 0x0078
+#define mmMP0_SMN_C2PMSG_56_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_57 0x0079
+#define mmMP0_SMN_C2PMSG_57_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_58 0x007a
+#define mmMP0_SMN_C2PMSG_58_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_59 0x007b
+#define mmMP0_SMN_C2PMSG_59_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_60 0x007c
+#define mmMP0_SMN_C2PMSG_60_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_61 0x007d
+#define mmMP0_SMN_C2PMSG_61_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_62 0x007e
+#define mmMP0_SMN_C2PMSG_62_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_63 0x007f
+#define mmMP0_SMN_C2PMSG_63_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_64 0x0080
+#define mmMP0_SMN_C2PMSG_64_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_65 0x0081
+#define mmMP0_SMN_C2PMSG_65_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_66 0x0082
+#define mmMP0_SMN_C2PMSG_66_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_67 0x0083
+#define mmMP0_SMN_C2PMSG_67_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_68 0x0084
+#define mmMP0_SMN_C2PMSG_68_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_69 0x0085
+#define mmMP0_SMN_C2PMSG_69_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_70 0x0086
+#define mmMP0_SMN_C2PMSG_70_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_71 0x0087
+#define mmMP0_SMN_C2PMSG_71_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_72 0x0088
+#define mmMP0_SMN_C2PMSG_72_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_73 0x0089
+#define mmMP0_SMN_C2PMSG_73_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_74 0x008a
+#define mmMP0_SMN_C2PMSG_74_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_75 0x008b
+#define mmMP0_SMN_C2PMSG_75_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_76 0x008c
+#define mmMP0_SMN_C2PMSG_76_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_77 0x008d
+#define mmMP0_SMN_C2PMSG_77_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_78 0x008e
+#define mmMP0_SMN_C2PMSG_78_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_79 0x008f
+#define mmMP0_SMN_C2PMSG_79_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_80 0x0090
+#define mmMP0_SMN_C2PMSG_80_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_81 0x0091
+#define mmMP0_SMN_C2PMSG_81_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_82 0x0092
+#define mmMP0_SMN_C2PMSG_82_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_83 0x0093
+#define mmMP0_SMN_C2PMSG_83_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_84 0x0094
+#define mmMP0_SMN_C2PMSG_84_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_85 0x0095
+#define mmMP0_SMN_C2PMSG_85_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_86 0x0096
+#define mmMP0_SMN_C2PMSG_86_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_87 0x0097
+#define mmMP0_SMN_C2PMSG_87_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_88 0x0098
+#define mmMP0_SMN_C2PMSG_88_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_89 0x0099
+#define mmMP0_SMN_C2PMSG_89_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_90 0x009a
+#define mmMP0_SMN_C2PMSG_90_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_91 0x009b
+#define mmMP0_SMN_C2PMSG_91_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_92 0x009c
+#define mmMP0_SMN_C2PMSG_92_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_93 0x009d
+#define mmMP0_SMN_C2PMSG_93_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_94 0x009e
+#define mmMP0_SMN_C2PMSG_94_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_95 0x009f
+#define mmMP0_SMN_C2PMSG_95_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_96 0x00a0
+#define mmMP0_SMN_C2PMSG_96_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_97 0x00a1
+#define mmMP0_SMN_C2PMSG_97_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_98 0x00a2
+#define mmMP0_SMN_C2PMSG_98_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_99 0x00a3
+#define mmMP0_SMN_C2PMSG_99_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_100 0x00a4
+#define mmMP0_SMN_C2PMSG_100_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_101 0x00a5
+#define mmMP0_SMN_C2PMSG_101_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_102 0x00a6
+#define mmMP0_SMN_C2PMSG_102_BASE_IDX 0
+#define mmMP0_SMN_C2PMSG_103 0x00a7
+#define mmMP0_SMN_C2PMSG_103_BASE_IDX 0
+#define mmMP0_SMN_IH_CREDIT 0x00c1
+#define mmMP0_SMN_IH_CREDIT_BASE_IDX 0
+#define mmMP0_SMN_IH_SW_INT 0x00c2
+#define mmMP0_SMN_IH_SW_INT_BASE_IDX 0
+#define mmMP0_SMN_IH_SW_INT_CTRL 0x00c3
+#define mmMP0_SMN_IH_SW_INT_CTRL_BASE_IDX 0
+
+
+// addressBlock: mp_SmuMp1_SmnDec
+// base address: 0x0
+#define mmMP1_SMN_C2PMSG_32 0x0260
+#define mmMP1_SMN_C2PMSG_32_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_33 0x0261
+#define mmMP1_SMN_C2PMSG_33_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_34 0x0262
+#define mmMP1_SMN_C2PMSG_34_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_35 0x0263
+#define mmMP1_SMN_C2PMSG_35_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_36 0x0264
+#define mmMP1_SMN_C2PMSG_36_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_37 0x0265
+#define mmMP1_SMN_C2PMSG_37_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_38 0x0266
+#define mmMP1_SMN_C2PMSG_38_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_39 0x0267
+#define mmMP1_SMN_C2PMSG_39_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_40 0x0268
+#define mmMP1_SMN_C2PMSG_40_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_41 0x0269
+#define mmMP1_SMN_C2PMSG_41_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_42 0x026a
+#define mmMP1_SMN_C2PMSG_42_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_43 0x026b
+#define mmMP1_SMN_C2PMSG_43_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_44 0x026c
+#define mmMP1_SMN_C2PMSG_44_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_45 0x026d
+#define mmMP1_SMN_C2PMSG_45_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_46 0x026e
+#define mmMP1_SMN_C2PMSG_46_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_47 0x026f
+#define mmMP1_SMN_C2PMSG_47_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_48 0x0270
+#define mmMP1_SMN_C2PMSG_48_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_49 0x0271
+#define mmMP1_SMN_C2PMSG_49_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_50 0x0272
+#define mmMP1_SMN_C2PMSG_50_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_51 0x0273
+#define mmMP1_SMN_C2PMSG_51_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_52 0x0274
+#define mmMP1_SMN_C2PMSG_52_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_53 0x0275
+#define mmMP1_SMN_C2PMSG_53_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_54 0x0276
+#define mmMP1_SMN_C2PMSG_54_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_55 0x0277
+#define mmMP1_SMN_C2PMSG_55_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_56 0x0278
+#define mmMP1_SMN_C2PMSG_56_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_57 0x0279
+#define mmMP1_SMN_C2PMSG_57_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_58 0x027a
+#define mmMP1_SMN_C2PMSG_58_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_59 0x027b
+#define mmMP1_SMN_C2PMSG_59_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_60 0x027c
+#define mmMP1_SMN_C2PMSG_60_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_61 0x027d
+#define mmMP1_SMN_C2PMSG_61_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_62 0x027e
+#define mmMP1_SMN_C2PMSG_62_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_63 0x027f
+#define mmMP1_SMN_C2PMSG_63_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_64 0x0280
+#define mmMP1_SMN_C2PMSG_64_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_65 0x0281
+#define mmMP1_SMN_C2PMSG_65_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_66 0x0282
+#define mmMP1_SMN_C2PMSG_66_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_67 0x0283
+#define mmMP1_SMN_C2PMSG_67_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_68 0x0284
+#define mmMP1_SMN_C2PMSG_68_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_69 0x0285
+#define mmMP1_SMN_C2PMSG_69_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_70 0x0286
+#define mmMP1_SMN_C2PMSG_70_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_71 0x0287
+#define mmMP1_SMN_C2PMSG_71_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_72 0x0288
+#define mmMP1_SMN_C2PMSG_72_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_73 0x0289
+#define mmMP1_SMN_C2PMSG_73_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_74 0x028a
+#define mmMP1_SMN_C2PMSG_74_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_75 0x028b
+#define mmMP1_SMN_C2PMSG_75_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_76 0x028c
+#define mmMP1_SMN_C2PMSG_76_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_77 0x028d
+#define mmMP1_SMN_C2PMSG_77_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_78 0x028e
+#define mmMP1_SMN_C2PMSG_78_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_79 0x028f
+#define mmMP1_SMN_C2PMSG_79_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_80 0x0290
+#define mmMP1_SMN_C2PMSG_80_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_81 0x0291
+#define mmMP1_SMN_C2PMSG_81_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_82 0x0292
+#define mmMP1_SMN_C2PMSG_82_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_83 0x0293
+#define mmMP1_SMN_C2PMSG_83_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_84 0x0294
+#define mmMP1_SMN_C2PMSG_84_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_85 0x0295
+#define mmMP1_SMN_C2PMSG_85_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_86 0x0296
+#define mmMP1_SMN_C2PMSG_86_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_87 0x0297
+#define mmMP1_SMN_C2PMSG_87_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_88 0x0298
+#define mmMP1_SMN_C2PMSG_88_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_89 0x0299
+#define mmMP1_SMN_C2PMSG_89_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_90 0x029a
+#define mmMP1_SMN_C2PMSG_90_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_91 0x029b
+#define mmMP1_SMN_C2PMSG_91_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_92 0x029c
+#define mmMP1_SMN_C2PMSG_92_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_93 0x029d
+#define mmMP1_SMN_C2PMSG_93_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_94 0x029e
+#define mmMP1_SMN_C2PMSG_94_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_95 0x029f
+#define mmMP1_SMN_C2PMSG_95_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_96 0x02a0
+#define mmMP1_SMN_C2PMSG_96_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_97 0x02a1
+#define mmMP1_SMN_C2PMSG_97_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_98 0x02a2
+#define mmMP1_SMN_C2PMSG_98_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_99 0x02a3
+#define mmMP1_SMN_C2PMSG_99_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_100 0x02a4
+#define mmMP1_SMN_C2PMSG_100_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_101 0x02a5
+#define mmMP1_SMN_C2PMSG_101_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_102 0x02a6
+#define mmMP1_SMN_C2PMSG_102_BASE_IDX 0
+#define mmMP1_SMN_C2PMSG_103 0x02a7
+#define mmMP1_SMN_C2PMSG_103_BASE_IDX 0
+#define mmMP1_SMN_IH_CREDIT 0x02c1
+#define mmMP1_SMN_IH_CREDIT_BASE_IDX 0
+#define mmMP1_SMN_IH_SW_INT 0x02c2
+#define mmMP1_SMN_IH_SW_INT_BASE_IDX 0
+#define mmMP1_SMN_IH_SW_INT_CTRL 0x02c3
+#define mmMP1_SMN_IH_SW_INT_CTRL_BASE_IDX 0
+#define mmMP1_SMN_FPS_CNT 0x02c4
+#define mmMP1_SMN_FPS_CNT_BASE_IDX 0
+#define mmMP1_SMN_EXT_SCRATCH0 0x03c0
+#define mmMP1_SMN_EXT_SCRATCH0_BASE_IDX 0
+#define mmMP1_SMN_EXT_SCRATCH1 0x03c1
+#define mmMP1_SMN_EXT_SCRATCH1_BASE_IDX 0
+#define mmMP1_SMN_EXT_SCRATCH2 0x03c2
+#define mmMP1_SMN_EXT_SCRATCH2_BASE_IDX 0
+#define mmMP1_SMN_EXT_SCRATCH3 0x03c3
+#define mmMP1_SMN_EXT_SCRATCH3_BASE_IDX 0
+#define mmMP1_SMN_EXT_SCRATCH4 0x03c4
+#define mmMP1_SMN_EXT_SCRATCH4_BASE_IDX 0
+#define mmMP1_SMN_EXT_SCRATCH5 0x03c5
+#define mmMP1_SMN_EXT_SCRATCH5_BASE_IDX 0
+#define mmMP1_SMN_EXT_SCRATCH6 0x03c6
+#define mmMP1_SMN_EXT_SCRATCH6_BASE_IDX 0
+#define mmMP1_SMN_EXT_SCRATCH7 0x03c7
+#define mmMP1_SMN_EXT_SCRATCH7_BASE_IDX 0
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
index a485526f3a51..8474f419caa5 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
@@ -38,6 +38,9 @@
#define mmCG_TACH_CTRL 0x006a
#define mmCG_TACH_CTRL_BASE_IDX 0
+#define mmCG_TACH_STATUS 0x006b
+#define mmCG_TACH_STATUS_BASE_IDX 0
+
#define mmTHM_THERMAL_INT_ENA 0x000a
#define mmTHM_THERMAL_INT_ENA_BASE_IDX 0
#define mmTHM_THERMAL_INT_CTRL 0x000b
@@ -49,4 +52,7 @@
#define mmTHM_BACO_CNTL 0x0081
#define mmTHM_BACO_CNTL_BASE_IDX 0
+#define mmCG_THERMAL_STATUS 0x006C
+#define mmCG_THERMAL_STATUS_BASE_IDX 0
+
#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h
index d130d92aee19..f2f9eae9a68f 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h
@@ -92,5 +92,8 @@
#define THM_TCON_THERM_TRIP__RSVD3_MASK 0x7FFFC000L
#define THM_TCON_THERM_TRIP__SW_THERM_TP_MASK 0x80000000L
+#define CG_THERMAL_STATUS__FDO_PWM_DUTY__SHIFT 0x9
+#define CG_THERMAL_STATUS__FDO_PWM_DUTY_MASK 0x0001FE00L
+
#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h
index 4c5097fa0c09..20329da53b0a 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h
@@ -1,79 +1,100 @@
-#ifndef _umc_8_7_0_SH_MASK_HEADER
-#define _umc_8_7_0_SH_MASK_HEADER
-
-//UMCCH0_0_GeccErrCntSel
-#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel__SHIFT 0x0
-#define UMCCH0_0_GeccErrCntSel__GeccErrInt__SHIFT 0xc
-#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn__SHIFT 0xf
-#define UMCCH0_0_GeccErrCntSel__PoisonCntEn__SHIFT 0x10
-#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel_MASK 0x0000000FL
-#define UMCCH0_0_GeccErrCntSel__GeccErrInt_MASK 0x00003000L
-#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn_MASK 0x00008000L
-#define UMCCH0_0_GeccErrCntSel__PoisonCntEn_MASK 0x00030000L
-//UMCCH0_0_GeccErrCnt
-#define UMCCH0_0_GeccErrCnt__GeccErrCnt__SHIFT 0x0
-#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt__SHIFT 0x10
-#define UMCCH0_0_GeccErrCnt__GeccErrCnt_MASK 0x0000FFFFL
-#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt_MASK 0xFFFF0000L
-//MCA_UMC_UMC0_MCUMC_STATUST0
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode__SHIFT 0x0
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt__SHIFT 0x10
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22__SHIFT 0x16
-#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb__SHIFT 0x18
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30__SHIFT 0x1e
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId__SHIFT 0x20
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38__SHIFT 0x26
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub__SHIFT 0x28
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41__SHIFT 0x29
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison__SHIFT 0x2b
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred__SHIFT 0x2c
-#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC__SHIFT 0x2d
-#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC__SHIFT 0x2e
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47__SHIFT 0x2f
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent__SHIFT 0x34
-#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV__SHIFT 0x35
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54__SHIFT 0x36
-#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC__SHIFT 0x37
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal__SHIFT 0x38
-#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC__SHIFT 0x39
-#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV__SHIFT 0x3a
-#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV__SHIFT 0x3b
-#define MCA_UMC_UMC0_MCUMC_STATUST0__En__SHIFT 0x3c
-#define MCA_UMC_UMC0_MCUMC_STATUST0__UC__SHIFT 0x3d
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow__SHIFT 0x3e
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Val__SHIFT 0x3f
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode_MASK 0x000000000000FFFFL
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt_MASK 0x00000000003F0000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22_MASK 0x0000000000C00000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb_MASK 0x000000003F000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30_MASK 0x00000000C0000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId_MASK 0x0000003F00000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38_MASK 0x000000C000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub_MASK 0x0000010000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41_MASK 0x0000060000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison_MASK 0x0000080000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred_MASK 0x0000100000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC_MASK 0x0000200000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC_MASK 0x0000400000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47_MASK 0x000F800000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent_MASK 0x0010000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV_MASK 0x0020000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54_MASK 0x0040000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC_MASK 0x0080000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal_MASK 0x0100000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC_MASK 0x0200000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV_MASK 0x0400000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV_MASK 0x0800000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__En_MASK 0x1000000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__UC_MASK 0x2000000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow_MASK 0x4000000000000000L
-#define MCA_UMC_UMC0_MCUMC_STATUST0__Val_MASK 0x8000000000000000L
-//MCA_UMC_UMC0_MCUMC_ADDRT0
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT 0x0
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB__SHIFT 0x38
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT 0x3e
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr_MASK 0x00FFFFFFFFFFFFFFL
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB_MASK 0x3F00000000000000L
-#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved_MASK 0xC000000000000000L
-
-#endif
+/*
+ * Copyright (C) 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _umc_8_7_0_SH_MASK_HEADER
+#define _umc_8_7_0_SH_MASK_HEADER
+
+//UMCCH0_0_GeccErrCntSel
+#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel__SHIFT 0x0
+#define UMCCH0_0_GeccErrCntSel__GeccErrInt__SHIFT 0xc
+#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn__SHIFT 0xf
+#define UMCCH0_0_GeccErrCntSel__PoisonCntEn__SHIFT 0x10
+#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel_MASK 0x0000000FL
+#define UMCCH0_0_GeccErrCntSel__GeccErrInt_MASK 0x00003000L
+#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn_MASK 0x00008000L
+#define UMCCH0_0_GeccErrCntSel__PoisonCntEn_MASK 0x00030000L
+//UMCCH0_0_GeccErrCnt
+#define UMCCH0_0_GeccErrCnt__GeccErrCnt__SHIFT 0x0
+#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt__SHIFT 0x10
+#define UMCCH0_0_GeccErrCnt__GeccErrCnt_MASK 0x0000FFFFL
+#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt_MASK 0xFFFF0000L
+//MCA_UMC_UMC0_MCUMC_STATUST0
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode__SHIFT 0x0
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt__SHIFT 0x10
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22__SHIFT 0x16
+#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb__SHIFT 0x18
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30__SHIFT 0x1e
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId__SHIFT 0x20
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38__SHIFT 0x26
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub__SHIFT 0x28
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41__SHIFT 0x29
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison__SHIFT 0x2b
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred__SHIFT 0x2c
+#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC__SHIFT 0x2d
+#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC__SHIFT 0x2e
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47__SHIFT 0x2f
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent__SHIFT 0x34
+#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV__SHIFT 0x35
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54__SHIFT 0x36
+#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC__SHIFT 0x37
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal__SHIFT 0x38
+#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC__SHIFT 0x39
+#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV__SHIFT 0x3a
+#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV__SHIFT 0x3b
+#define MCA_UMC_UMC0_MCUMC_STATUST0__En__SHIFT 0x3c
+#define MCA_UMC_UMC0_MCUMC_STATUST0__UC__SHIFT 0x3d
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow__SHIFT 0x3e
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Val__SHIFT 0x3f
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode_MASK 0x000000000000FFFFL
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt_MASK 0x00000000003F0000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22_MASK 0x0000000000C00000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb_MASK 0x000000003F000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30_MASK 0x00000000C0000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId_MASK 0x0000003F00000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38_MASK 0x000000C000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub_MASK 0x0000010000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41_MASK 0x0000060000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison_MASK 0x0000080000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred_MASK 0x0000100000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC_MASK 0x0000200000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC_MASK 0x0000400000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47_MASK 0x000F800000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent_MASK 0x0010000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV_MASK 0x0020000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54_MASK 0x0040000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC_MASK 0x0080000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal_MASK 0x0100000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC_MASK 0x0200000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV_MASK 0x0400000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV_MASK 0x0800000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__En_MASK 0x1000000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__UC_MASK 0x2000000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow_MASK 0x4000000000000000L
+#define MCA_UMC_UMC0_MCUMC_STATUST0__Val_MASK 0x8000000000000000L
+//MCA_UMC_UMC0_MCUMC_ADDRT0
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT 0x0
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB__SHIFT 0x38
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT 0x3e
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr_MASK 0x00FFFFFFFFFFFFFFL
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB_MASK 0x3F00000000000000L
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved_MASK 0xC000000000000000L
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/cyan_skillfish_ip_offset.h b/drivers/gpu/drm/amd/include/cyan_skillfish_ip_offset.h
new file mode 100644
index 000000000000..9cb5f3631c60
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/cyan_skillfish_ip_offset.h
@@ -0,0 +1,714 @@
+/*
+ * Copyright (C) 2018 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _cyan_skillfish_ip_offset_HEADER
+#define _cyan_skillfish_ip_offset_HEADER
+
+#define MAX_INSTANCE 6
+#define MAX_SEGMENT 5
+
+
+struct IP_BASE_INSTANCE
+{
+ unsigned int segment[MAX_SEGMENT];
+};
+
+struct IP_BASE
+{
+ struct IP_BASE_INSTANCE instance[MAX_INSTANCE];
+};
+
+
+static const struct IP_BASE ATHUB_BASE ={ { { { 0x00000C00, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE CLK_BASE ={ { { { 0x00016C00, 0, 0, 0, 0 } },
+ { { 0x00016E00, 0, 0, 0, 0 } },
+ { { 0x00017000, 0, 0, 0, 0 } },
+ { { 0x00017200, 0, 0, 0, 0 } },
+ { { 0x00017E00, 0, 0, 0, 0 } },
+ { { 0x0001B000, 0, 0, 0, 0 } } } };
+static const struct IP_BASE DF_BASE ={ { { { 0x00007000, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE DMU_BASE ={ { { { 0x00000012, 0x000000C0, 0x000034C0, 0x00009000, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE FUSE_BASE ={ { { { 0x00017400, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE GC_BASE ={ { { { 0x00001260, 0x0000A000, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE HDP_BASE ={ { { { 0x00000F20, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE MMHUB_BASE ={ { { { 0x0001A000, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE MP0_BASE ={ { { { 0x00016000, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE MP1_BASE ={ { { { 0x00016000, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE NBIO_BASE ={ { { { 0x00000000, 0x00000014, 0x00000D20, 0x00010400, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE OSSSYS_BASE ={ { { { 0x000010A0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE SMUIO_BASE ={ { { { 0x00016800, 0x00016A00, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE THM_BASE ={ { { { 0x00016600, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE UMC0_BASE ={ { { { 0x00014000, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE UVD0_BASE ={ { { { 0x00007800, 0x00007E00, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } },
+ { { 0, 0, 0, 0, 0 } } } };
+
+
+#define ATHUB_BASE__INST0_SEG0 0x00000C00
+#define ATHUB_BASE__INST0_SEG1 0
+#define ATHUB_BASE__INST0_SEG2 0
+#define ATHUB_BASE__INST0_SEG3 0
+#define ATHUB_BASE__INST0_SEG4 0
+
+#define ATHUB_BASE__INST1_SEG0 0
+#define ATHUB_BASE__INST1_SEG1 0
+#define ATHUB_BASE__INST1_SEG2 0
+#define ATHUB_BASE__INST1_SEG3 0
+#define ATHUB_BASE__INST1_SEG4 0
+
+#define ATHUB_BASE__INST2_SEG0 0
+#define ATHUB_BASE__INST2_SEG1 0
+#define ATHUB_BASE__INST2_SEG2 0
+#define ATHUB_BASE__INST2_SEG3 0
+#define ATHUB_BASE__INST2_SEG4 0
+
+#define ATHUB_BASE__INST3_SEG0 0
+#define ATHUB_BASE__INST3_SEG1 0
+#define ATHUB_BASE__INST3_SEG2 0
+#define ATHUB_BASE__INST3_SEG3 0
+#define ATHUB_BASE__INST3_SEG4 0
+
+#define ATHUB_BASE__INST4_SEG0 0
+#define ATHUB_BASE__INST4_SEG1 0
+#define ATHUB_BASE__INST4_SEG2 0
+#define ATHUB_BASE__INST4_SEG3 0
+#define ATHUB_BASE__INST4_SEG4 0
+
+#define ATHUB_BASE__INST5_SEG0 0
+#define ATHUB_BASE__INST5_SEG1 0
+#define ATHUB_BASE__INST5_SEG2 0
+#define ATHUB_BASE__INST5_SEG3 0
+#define ATHUB_BASE__INST5_SEG4 0
+
+#define CLK_BASE__INST0_SEG0 0x00016C00
+#define CLK_BASE__INST0_SEG1 0
+#define CLK_BASE__INST0_SEG2 0
+#define CLK_BASE__INST0_SEG3 0
+#define CLK_BASE__INST0_SEG4 0
+
+#define CLK_BASE__INST1_SEG0 0x00016E00
+#define CLK_BASE__INST1_SEG1 0
+#define CLK_BASE__INST1_SEG2 0
+#define CLK_BASE__INST1_SEG3 0
+#define CLK_BASE__INST1_SEG4 0
+
+#define CLK_BASE__INST2_SEG0 0x00017000
+#define CLK_BASE__INST2_SEG1 0
+#define CLK_BASE__INST2_SEG2 0
+#define CLK_BASE__INST2_SEG3 0
+#define CLK_BASE__INST2_SEG4 0
+
+#define CLK_BASE__INST3_SEG0 0x00017200
+#define CLK_BASE__INST3_SEG1 0
+#define CLK_BASE__INST3_SEG2 0
+#define CLK_BASE__INST3_SEG3 0
+#define CLK_BASE__INST3_SEG4 0
+
+#define CLK_BASE__INST4_SEG0 0x00017E00
+#define CLK_BASE__INST4_SEG1 0
+#define CLK_BASE__INST4_SEG2 0
+#define CLK_BASE__INST4_SEG3 0
+#define CLK_BASE__INST4_SEG4 0
+
+#define CLK_BASE__INST5_SEG0 0x0001B000
+#define CLK_BASE__INST5_SEG1 0
+#define CLK_BASE__INST5_SEG2 0
+#define CLK_BASE__INST5_SEG3 0
+#define CLK_BASE__INST5_SEG4 0
+
+#define DF_BASE__INST0_SEG0 0x00007000
+#define DF_BASE__INST0_SEG1 0
+#define DF_BASE__INST0_SEG2 0
+#define DF_BASE__INST0_SEG3 0
+#define DF_BASE__INST0_SEG4 0
+
+#define DF_BASE__INST1_SEG0 0
+#define DF_BASE__INST1_SEG1 0
+#define DF_BASE__INST1_SEG2 0
+#define DF_BASE__INST1_SEG3 0
+#define DF_BASE__INST1_SEG4 0
+
+#define DF_BASE__INST2_SEG0 0
+#define DF_BASE__INST2_SEG1 0
+#define DF_BASE__INST2_SEG2 0
+#define DF_BASE__INST2_SEG3 0
+#define DF_BASE__INST2_SEG4 0
+
+#define DF_BASE__INST3_SEG0 0
+#define DF_BASE__INST3_SEG1 0
+#define DF_BASE__INST3_SEG2 0
+#define DF_BASE__INST3_SEG3 0
+#define DF_BASE__INST3_SEG4 0
+
+#define DF_BASE__INST4_SEG0 0
+#define DF_BASE__INST4_SEG1 0
+#define DF_BASE__INST4_SEG2 0
+#define DF_BASE__INST4_SEG3 0
+#define DF_BASE__INST4_SEG4 0
+
+#define DF_BASE__INST5_SEG0 0
+#define DF_BASE__INST5_SEG1 0
+#define DF_BASE__INST5_SEG2 0
+#define DF_BASE__INST5_SEG3 0
+#define DF_BASE__INST5_SEG4 0
+
+#define DMU_BASE__INST0_SEG0 0x00000012
+#define DMU_BASE__INST0_SEG1 0x000000C0
+#define DMU_BASE__INST0_SEG2 0x000034C0
+#define DMU_BASE__INST0_SEG3 0x00009000
+#define DMU_BASE__INST0_SEG4 0
+
+#define DMU_BASE__INST1_SEG0 0
+#define DMU_BASE__INST1_SEG1 0
+#define DMU_BASE__INST1_SEG2 0
+#define DMU_BASE__INST1_SEG3 0
+#define DMU_BASE__INST1_SEG4 0
+
+#define DMU_BASE__INST2_SEG0 0
+#define DMU_BASE__INST2_SEG1 0
+#define DMU_BASE__INST2_SEG2 0
+#define DMU_BASE__INST2_SEG3 0
+#define DMU_BASE__INST2_SEG4 0
+
+#define DMU_BASE__INST3_SEG0 0
+#define DMU_BASE__INST3_SEG1 0
+#define DMU_BASE__INST3_SEG2 0
+#define DMU_BASE__INST3_SEG3 0
+#define DMU_BASE__INST3_SEG4 0
+
+#define DMU_BASE__INST4_SEG0 0
+#define DMU_BASE__INST4_SEG1 0
+#define DMU_BASE__INST4_SEG2 0
+#define DMU_BASE__INST4_SEG3 0
+#define DMU_BASE__INST4_SEG4 0
+
+#define DMU_BASE__INST5_SEG0 0
+#define DMU_BASE__INST5_SEG1 0
+#define DMU_BASE__INST5_SEG2 0
+#define DMU_BASE__INST5_SEG3 0
+#define DMU_BASE__INST5_SEG4 0
+
+#define FUSE_BASE__INST0_SEG0 0x00017400
+#define FUSE_BASE__INST0_SEG1 0
+#define FUSE_BASE__INST0_SEG2 0
+#define FUSE_BASE__INST0_SEG3 0
+#define FUSE_BASE__INST0_SEG4 0
+
+#define FUSE_BASE__INST1_SEG0 0
+#define FUSE_BASE__INST1_SEG1 0
+#define FUSE_BASE__INST1_SEG2 0
+#define FUSE_BASE__INST1_SEG3 0
+#define FUSE_BASE__INST1_SEG4 0
+
+#define FUSE_BASE__INST2_SEG0 0
+#define FUSE_BASE__INST2_SEG1 0
+#define FUSE_BASE__INST2_SEG2 0
+#define FUSE_BASE__INST2_SEG3 0
+#define FUSE_BASE__INST2_SEG4 0
+
+#define FUSE_BASE__INST3_SEG0 0
+#define FUSE_BASE__INST3_SEG1 0
+#define FUSE_BASE__INST3_SEG2 0
+#define FUSE_BASE__INST3_SEG3 0
+#define FUSE_BASE__INST3_SEG4 0
+
+#define FUSE_BASE__INST4_SEG0 0
+#define FUSE_BASE__INST4_SEG1 0
+#define FUSE_BASE__INST4_SEG2 0
+#define FUSE_BASE__INST4_SEG3 0
+#define FUSE_BASE__INST4_SEG4 0
+
+#define FUSE_BASE__INST5_SEG0 0
+#define FUSE_BASE__INST5_SEG1 0
+#define FUSE_BASE__INST5_SEG2 0
+#define FUSE_BASE__INST5_SEG3 0
+#define FUSE_BASE__INST5_SEG4 0
+
+#define GC_BASE__INST0_SEG0 0x00001260
+#define GC_BASE__INST0_SEG1 0x0000A000
+#define GC_BASE__INST0_SEG2 0
+#define GC_BASE__INST0_SEG3 0
+#define GC_BASE__INST0_SEG4 0
+
+#define GC_BASE__INST1_SEG0 0
+#define GC_BASE__INST1_SEG1 0
+#define GC_BASE__INST1_SEG2 0
+#define GC_BASE__INST1_SEG3 0
+#define GC_BASE__INST1_SEG4 0
+
+#define GC_BASE__INST2_SEG0 0
+#define GC_BASE__INST2_SEG1 0
+#define GC_BASE__INST2_SEG2 0
+#define GC_BASE__INST2_SEG3 0
+#define GC_BASE__INST2_SEG4 0
+
+#define GC_BASE__INST3_SEG0 0
+#define GC_BASE__INST3_SEG1 0
+#define GC_BASE__INST3_SEG2 0
+#define GC_BASE__INST3_SEG3 0
+#define GC_BASE__INST3_SEG4 0
+
+#define GC_BASE__INST4_SEG0 0
+#define GC_BASE__INST4_SEG1 0
+#define GC_BASE__INST4_SEG2 0
+#define GC_BASE__INST4_SEG3 0
+#define GC_BASE__INST4_SEG4 0
+
+#define GC_BASE__INST5_SEG0 0
+#define GC_BASE__INST5_SEG1 0
+#define GC_BASE__INST5_SEG2 0
+#define GC_BASE__INST5_SEG3 0
+#define GC_BASE__INST5_SEG4 0
+
+#define HDP_BASE__INST0_SEG0 0x00000F20
+#define HDP_BASE__INST0_SEG1 0
+#define HDP_BASE__INST0_SEG2 0
+#define HDP_BASE__INST0_SEG3 0
+#define HDP_BASE__INST0_SEG4 0
+
+#define HDP_BASE__INST1_SEG0 0
+#define HDP_BASE__INST1_SEG1 0
+#define HDP_BASE__INST1_SEG2 0
+#define HDP_BASE__INST1_SEG3 0
+#define HDP_BASE__INST1_SEG4 0
+
+#define HDP_BASE__INST2_SEG0 0
+#define HDP_BASE__INST2_SEG1 0
+#define HDP_BASE__INST2_SEG2 0
+#define HDP_BASE__INST2_SEG3 0
+#define HDP_BASE__INST2_SEG4 0
+
+#define HDP_BASE__INST3_SEG0 0
+#define HDP_BASE__INST3_SEG1 0
+#define HDP_BASE__INST3_SEG2 0
+#define HDP_BASE__INST3_SEG3 0
+#define HDP_BASE__INST3_SEG4 0
+
+#define HDP_BASE__INST4_SEG0 0
+#define HDP_BASE__INST4_SEG1 0
+#define HDP_BASE__INST4_SEG2 0
+#define HDP_BASE__INST4_SEG3 0
+#define HDP_BASE__INST4_SEG4 0
+
+#define HDP_BASE__INST5_SEG0 0
+#define HDP_BASE__INST5_SEG1 0
+#define HDP_BASE__INST5_SEG2 0
+#define HDP_BASE__INST5_SEG3 0
+#define HDP_BASE__INST5_SEG4 0
+
+#define MMHUB_BASE__INST0_SEG0 0x0001A000
+#define MMHUB_BASE__INST0_SEG1 0
+#define MMHUB_BASE__INST0_SEG2 0
+#define MMHUB_BASE__INST0_SEG3 0
+#define MMHUB_BASE__INST0_SEG4 0
+
+#define MMHUB_BASE__INST1_SEG0 0
+#define MMHUB_BASE__INST1_SEG1 0
+#define MMHUB_BASE__INST1_SEG2 0
+#define MMHUB_BASE__INST1_SEG3 0
+#define MMHUB_BASE__INST1_SEG4 0
+
+#define MMHUB_BASE__INST2_SEG0 0
+#define MMHUB_BASE__INST2_SEG1 0
+#define MMHUB_BASE__INST2_SEG2 0
+#define MMHUB_BASE__INST2_SEG3 0
+#define MMHUB_BASE__INST2_SEG4 0
+
+#define MMHUB_BASE__INST3_SEG0 0
+#define MMHUB_BASE__INST3_SEG1 0
+#define MMHUB_BASE__INST3_SEG2 0
+#define MMHUB_BASE__INST3_SEG3 0
+#define MMHUB_BASE__INST3_SEG4 0
+
+#define MMHUB_BASE__INST4_SEG0 0
+#define MMHUB_BASE__INST4_SEG1 0
+#define MMHUB_BASE__INST4_SEG2 0
+#define MMHUB_BASE__INST4_SEG3 0
+#define MMHUB_BASE__INST4_SEG4 0
+
+#define MMHUB_BASE__INST5_SEG0 0
+#define MMHUB_BASE__INST5_SEG1 0
+#define MMHUB_BASE__INST5_SEG2 0
+#define MMHUB_BASE__INST5_SEG3 0
+#define MMHUB_BASE__INST5_SEG4 0
+
+#define MP0_BASE__INST0_SEG0 0x00016000
+#define MP0_BASE__INST0_SEG1 0
+#define MP0_BASE__INST0_SEG2 0
+#define MP0_BASE__INST0_SEG3 0
+#define MP0_BASE__INST0_SEG4 0
+
+#define MP0_BASE__INST1_SEG0 0
+#define MP0_BASE__INST1_SEG1 0
+#define MP0_BASE__INST1_SEG2 0
+#define MP0_BASE__INST1_SEG3 0
+#define MP0_BASE__INST1_SEG4 0
+
+#define MP0_BASE__INST2_SEG0 0
+#define MP0_BASE__INST2_SEG1 0
+#define MP0_BASE__INST2_SEG2 0
+#define MP0_BASE__INST2_SEG3 0
+#define MP0_BASE__INST2_SEG4 0
+
+#define MP0_BASE__INST3_SEG0 0
+#define MP0_BASE__INST3_SEG1 0
+#define MP0_BASE__INST3_SEG2 0
+#define MP0_BASE__INST3_SEG3 0
+#define MP0_BASE__INST3_SEG4 0
+
+#define MP0_BASE__INST4_SEG0 0
+#define MP0_BASE__INST4_SEG1 0
+#define MP0_BASE__INST4_SEG2 0
+#define MP0_BASE__INST4_SEG3 0
+#define MP0_BASE__INST4_SEG4 0
+
+#define MP0_BASE__INST5_SEG0 0
+#define MP0_BASE__INST5_SEG1 0
+#define MP0_BASE__INST5_SEG2 0
+#define MP0_BASE__INST5_SEG3 0
+#define MP0_BASE__INST5_SEG4 0
+
+#define MP1_BASE__INST0_SEG0 0x00016000
+#define MP1_BASE__INST0_SEG1 0
+#define MP1_BASE__INST0_SEG2 0
+#define MP1_BASE__INST0_SEG3 0
+#define MP1_BASE__INST0_SEG4 0
+
+#define MP1_BASE__INST1_SEG0 0
+#define MP1_BASE__INST1_SEG1 0
+#define MP1_BASE__INST1_SEG2 0
+#define MP1_BASE__INST1_SEG3 0
+#define MP1_BASE__INST1_SEG4 0
+
+#define MP1_BASE__INST2_SEG0 0
+#define MP1_BASE__INST2_SEG1 0
+#define MP1_BASE__INST2_SEG2 0
+#define MP1_BASE__INST2_SEG3 0
+#define MP1_BASE__INST2_SEG4 0
+
+#define MP1_BASE__INST3_SEG0 0
+#define MP1_BASE__INST3_SEG1 0
+#define MP1_BASE__INST3_SEG2 0
+#define MP1_BASE__INST3_SEG3 0
+#define MP1_BASE__INST3_SEG4 0
+
+#define MP1_BASE__INST4_SEG0 0
+#define MP1_BASE__INST4_SEG1 0
+#define MP1_BASE__INST4_SEG2 0
+#define MP1_BASE__INST4_SEG3 0
+#define MP1_BASE__INST4_SEG4 0
+
+#define MP1_BASE__INST5_SEG0 0
+#define MP1_BASE__INST5_SEG1 0
+#define MP1_BASE__INST5_SEG2 0
+#define MP1_BASE__INST5_SEG3 0
+#define MP1_BASE__INST5_SEG4 0
+
+#define NBIO_BASE__INST0_SEG0 0x00000000
+#define NBIO_BASE__INST0_SEG1 0x00000014
+#define NBIO_BASE__INST0_SEG2 0x00000D20
+#define NBIO_BASE__INST0_SEG3 0x00010400
+#define NBIO_BASE__INST0_SEG4 0
+
+#define NBIO_BASE__INST1_SEG0 0
+#define NBIO_BASE__INST1_SEG1 0
+#define NBIO_BASE__INST1_SEG2 0
+#define NBIO_BASE__INST1_SEG3 0
+#define NBIO_BASE__INST1_SEG4 0
+
+#define NBIO_BASE__INST2_SEG0 0
+#define NBIO_BASE__INST2_SEG1 0
+#define NBIO_BASE__INST2_SEG2 0
+#define NBIO_BASE__INST2_SEG3 0
+#define NBIO_BASE__INST2_SEG4 0
+
+#define NBIO_BASE__INST3_SEG0 0
+#define NBIO_BASE__INST3_SEG1 0
+#define NBIO_BASE__INST3_SEG2 0
+#define NBIO_BASE__INST3_SEG3 0
+#define NBIO_BASE__INST3_SEG4 0
+
+#define NBIO_BASE__INST4_SEG0 0
+#define NBIO_BASE__INST4_SEG1 0
+#define NBIO_BASE__INST4_SEG2 0
+#define NBIO_BASE__INST4_SEG3 0
+#define NBIO_BASE__INST4_SEG4 0
+
+#define NBIO_BASE__INST5_SEG0 0
+#define NBIO_BASE__INST5_SEG1 0
+#define NBIO_BASE__INST5_SEG2 0
+#define NBIO_BASE__INST5_SEG3 0
+#define NBIO_BASE__INST5_SEG4 0
+
+#define OSSSYS_BASE__INST0_SEG0 0x000010A0
+#define OSSSYS_BASE__INST0_SEG1 0
+#define OSSSYS_BASE__INST0_SEG2 0
+#define OSSSYS_BASE__INST0_SEG3 0
+#define OSSSYS_BASE__INST0_SEG4 0
+
+#define OSSSYS_BASE__INST1_SEG0 0
+#define OSSSYS_BASE__INST1_SEG1 0
+#define OSSSYS_BASE__INST1_SEG2 0
+#define OSSSYS_BASE__INST1_SEG3 0
+#define OSSSYS_BASE__INST1_SEG4 0
+
+#define OSSSYS_BASE__INST2_SEG0 0
+#define OSSSYS_BASE__INST2_SEG1 0
+#define OSSSYS_BASE__INST2_SEG2 0
+#define OSSSYS_BASE__INST2_SEG3 0
+#define OSSSYS_BASE__INST2_SEG4 0
+
+#define OSSSYS_BASE__INST3_SEG0 0
+#define OSSSYS_BASE__INST3_SEG1 0
+#define OSSSYS_BASE__INST3_SEG2 0
+#define OSSSYS_BASE__INST3_SEG3 0
+#define OSSSYS_BASE__INST3_SEG4 0
+
+#define OSSSYS_BASE__INST4_SEG0 0
+#define OSSSYS_BASE__INST4_SEG1 0
+#define OSSSYS_BASE__INST4_SEG2 0
+#define OSSSYS_BASE__INST4_SEG3 0
+#define OSSSYS_BASE__INST4_SEG4 0
+
+#define OSSSYS_BASE__INST5_SEG0 0
+#define OSSSYS_BASE__INST5_SEG1 0
+#define OSSSYS_BASE__INST5_SEG2 0
+#define OSSSYS_BASE__INST5_SEG3 0
+#define OSSSYS_BASE__INST5_SEG4 0
+
+#define SMUIO_BASE__INST0_SEG0 0x00016800
+#define SMUIO_BASE__INST0_SEG1 0x00016A00
+#define SMUIO_BASE__INST0_SEG2 0
+#define SMUIO_BASE__INST0_SEG3 0
+#define SMUIO_BASE__INST0_SEG4 0
+
+#define SMUIO_BASE__INST1_SEG0 0
+#define SMUIO_BASE__INST1_SEG1 0
+#define SMUIO_BASE__INST1_SEG2 0
+#define SMUIO_BASE__INST1_SEG3 0
+#define SMUIO_BASE__INST1_SEG4 0
+
+#define SMUIO_BASE__INST2_SEG0 0
+#define SMUIO_BASE__INST2_SEG1 0
+#define SMUIO_BASE__INST2_SEG2 0
+#define SMUIO_BASE__INST2_SEG3 0
+#define SMUIO_BASE__INST2_SEG4 0
+
+#define SMUIO_BASE__INST3_SEG0 0
+#define SMUIO_BASE__INST3_SEG1 0
+#define SMUIO_BASE__INST3_SEG2 0
+#define SMUIO_BASE__INST3_SEG3 0
+#define SMUIO_BASE__INST3_SEG4 0
+
+#define SMUIO_BASE__INST4_SEG0 0
+#define SMUIO_BASE__INST4_SEG1 0
+#define SMUIO_BASE__INST4_SEG2 0
+#define SMUIO_BASE__INST4_SEG3 0
+#define SMUIO_BASE__INST4_SEG4 0
+
+#define SMUIO_BASE__INST5_SEG0 0
+#define SMUIO_BASE__INST5_SEG1 0
+#define SMUIO_BASE__INST5_SEG2 0
+#define SMUIO_BASE__INST5_SEG3 0
+#define SMUIO_BASE__INST5_SEG4 0
+
+#define THM_BASE__INST0_SEG0 0x00016600
+#define THM_BASE__INST0_SEG1 0
+#define THM_BASE__INST0_SEG2 0
+#define THM_BASE__INST0_SEG3 0
+#define THM_BASE__INST0_SEG4 0
+
+#define THM_BASE__INST1_SEG0 0
+#define THM_BASE__INST1_SEG1 0
+#define THM_BASE__INST1_SEG2 0
+#define THM_BASE__INST1_SEG3 0
+#define THM_BASE__INST1_SEG4 0
+
+#define THM_BASE__INST2_SEG0 0
+#define THM_BASE__INST2_SEG1 0
+#define THM_BASE__INST2_SEG2 0
+#define THM_BASE__INST2_SEG3 0
+#define THM_BASE__INST2_SEG4 0
+
+#define THM_BASE__INST3_SEG0 0
+#define THM_BASE__INST3_SEG1 0
+#define THM_BASE__INST3_SEG2 0
+#define THM_BASE__INST3_SEG3 0
+#define THM_BASE__INST3_SEG4 0
+
+#define THM_BASE__INST4_SEG0 0
+#define THM_BASE__INST4_SEG1 0
+#define THM_BASE__INST4_SEG2 0
+#define THM_BASE__INST4_SEG3 0
+#define THM_BASE__INST4_SEG4 0
+
+#define THM_BASE__INST5_SEG0 0
+#define THM_BASE__INST5_SEG1 0
+#define THM_BASE__INST5_SEG2 0
+#define THM_BASE__INST5_SEG3 0
+#define THM_BASE__INST5_SEG4 0
+
+#define UMC0_BASE__INST0_SEG0 0x00014000
+#define UMC0_BASE__INST0_SEG1 0
+#define UMC0_BASE__INST0_SEG2 0
+#define UMC0_BASE__INST0_SEG3 0
+#define UMC0_BASE__INST0_SEG4 0
+
+#define UMC0_BASE__INST1_SEG0 0
+#define UMC0_BASE__INST1_SEG1 0
+#define UMC0_BASE__INST1_SEG2 0
+#define UMC0_BASE__INST1_SEG3 0
+#define UMC0_BASE__INST1_SEG4 0
+
+#define UMC0_BASE__INST2_SEG0 0
+#define UMC0_BASE__INST2_SEG1 0
+#define UMC0_BASE__INST2_SEG2 0
+#define UMC0_BASE__INST2_SEG3 0
+#define UMC0_BASE__INST2_SEG4 0
+
+#define UMC0_BASE__INST3_SEG0 0
+#define UMC0_BASE__INST3_SEG1 0
+#define UMC0_BASE__INST3_SEG2 0
+#define UMC0_BASE__INST3_SEG3 0
+#define UMC0_BASE__INST3_SEG4 0
+
+#define UMC0_BASE__INST4_SEG0 0
+#define UMC0_BASE__INST4_SEG1 0
+#define UMC0_BASE__INST4_SEG2 0
+#define UMC0_BASE__INST4_SEG3 0
+#define UMC0_BASE__INST4_SEG4 0
+
+#define UMC0_BASE__INST5_SEG0 0
+#define UMC0_BASE__INST5_SEG1 0
+#define UMC0_BASE__INST5_SEG2 0
+#define UMC0_BASE__INST5_SEG3 0
+#define UMC0_BASE__INST5_SEG4 0
+
+#define UVD0_BASE__INST0_SEG0 0x00007800
+#define UVD0_BASE__INST0_SEG1 0x00007E00
+#define UVD0_BASE__INST0_SEG2 0
+#define UVD0_BASE__INST0_SEG3 0
+#define UVD0_BASE__INST0_SEG4 0
+
+#define UVD0_BASE__INST1_SEG0 0
+#define UVD0_BASE__INST1_SEG1 0
+#define UVD0_BASE__INST1_SEG2 0
+#define UVD0_BASE__INST1_SEG3 0
+#define UVD0_BASE__INST1_SEG4 0
+
+#define UVD0_BASE__INST2_SEG0 0
+#define UVD0_BASE__INST2_SEG1 0
+#define UVD0_BASE__INST2_SEG2 0
+#define UVD0_BASE__INST2_SEG3 0
+#define UVD0_BASE__INST2_SEG4 0
+
+#define UVD0_BASE__INST3_SEG0 0
+#define UVD0_BASE__INST3_SEG1 0
+#define UVD0_BASE__INST3_SEG2 0
+#define UVD0_BASE__INST3_SEG3 0
+#define UVD0_BASE__INST3_SEG4 0
+
+#define UVD0_BASE__INST4_SEG0 0
+#define UVD0_BASE__INST4_SEG1 0
+#define UVD0_BASE__INST4_SEG2 0
+#define UVD0_BASE__INST4_SEG3 0
+#define UVD0_BASE__INST4_SEG4 0
+
+#define UVD0_BASE__INST5_SEG0 0
+#define UVD0_BASE__INST5_SEG1 0
+#define UVD0_BASE__INST5_SEG2 0
+#define UVD0_BASE__INST5_SEG3 0
+#define UVD0_BASE__INST5_SEG4 0
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
index 95c656d205ed..c84bd7b2cf59 100644
--- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
@@ -44,6 +44,7 @@ struct kgd_mem;
enum kfd_preempt_type {
KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN = 0,
KFD_PREEMPT_TYPE_WAVEFRONT_RESET,
+ KFD_PREEMPT_TYPE_WAVEFRONT_SAVE
};
struct kfd_vm_fault_info {
@@ -298,6 +299,8 @@ struct kfd2kgd_calls {
void (*get_cu_occupancy)(struct kgd_dev *kgd, int pasid, int *wave_cnt,
int *max_waves_per_cu);
+ void (*program_trap_handler_settings)(struct kgd_dev *kgd,
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr);
};
#endif /* KGD_KFD_INTERFACE_H_INCLUDED */
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index e38b191c7b7c..bac15c466733 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -306,8 +306,8 @@ struct amd_pm_funcs {
/* export for sysfs */
void (*set_fan_control_mode)(void *handle, u32 mode);
u32 (*get_fan_control_mode)(void *handle);
- int (*set_fan_speed_percent)(void *handle, u32 speed);
- int (*get_fan_speed_percent)(void *handle, u32 *speed);
+ int (*set_fan_speed_pwm)(void *handle, u32 speed);
+ int (*get_fan_speed_pwm)(void *handle, u32 *speed);
int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask);
int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf);
int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level);
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 769f58d5ae1a..2d55627b05b1 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -2094,14 +2094,19 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
*states = ATTR_STATE_UNSUPPORTED;
}
- if (asic_type == CHIP_ARCTURUS) {
- /* Arcturus does not support standalone mclk/socclk/fclk level setting */
+ switch (asic_type) {
+ case CHIP_ARCTURUS:
+ case CHIP_ALDEBARAN:
+ /* the Mi series card does not support standalone mclk/socclk/fclk level setting */
if (DEVICE_ATTR_IS(pp_dpm_mclk) ||
DEVICE_ATTR_IS(pp_dpm_socclk) ||
DEVICE_ATTR_IS(pp_dpm_fclk)) {
dev_attr->attr.mode &= ~S_IWUGO;
dev_attr->store = NULL;
}
+ break;
+ default:
+ break;
}
if (DEVICE_ATTR_IS(pp_dpm_dcefclk)) {
@@ -2379,7 +2384,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev,
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
- return sprintf(buf, "%u\n", pwm_mode);
+ return sysfs_emit(buf, "%u\n", pwm_mode);
}
static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev,
@@ -2424,14 +2429,14 @@ static ssize_t amdgpu_hwmon_get_pwm1_min(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%i\n", 0);
+ return sysfs_emit(buf, "%i\n", 0);
}
static ssize_t amdgpu_hwmon_get_pwm1_max(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%i\n", 255);
+ return sysfs_emit(buf, "%i\n", 255);
}
static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev,
@@ -2469,10 +2474,8 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev,
return err;
}
- value = (value * 100) / 255;
-
- if (adev->powerplay.pp_funcs->set_fan_speed_percent)
- err = amdgpu_dpm_set_fan_speed_percent(adev, value);
+ if (adev->powerplay.pp_funcs->set_fan_speed_pwm)
+ err = amdgpu_dpm_set_fan_speed_pwm(adev, value);
else
err = -EINVAL;
@@ -2504,8 +2507,8 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev,
return err;
}
- if (adev->powerplay.pp_funcs->get_fan_speed_percent)
- err = amdgpu_dpm_get_fan_speed_percent(adev, &speed);
+ if (adev->powerplay.pp_funcs->get_fan_speed_pwm)
+ err = amdgpu_dpm_get_fan_speed_pwm(adev, &speed);
else
err = -EINVAL;
@@ -2515,9 +2518,7 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev,
if (err)
return err;
- speed = (speed * 255) / 100;
-
- return sprintf(buf, "%i\n", speed);
+ return sysfs_emit(buf, "%i\n", speed);
}
static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev,
@@ -2550,7 +2551,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev,
if (err)
return err;
- return sprintf(buf, "%i\n", speed);
+ return sysfs_emit(buf, "%i\n", speed);
}
static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev,
@@ -2647,7 +2648,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev,
if (err)
return err;
- return sprintf(buf, "%i\n", rpm);
+ return sysfs_emit(buf, "%i\n", rpm);
}
static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev,
@@ -2729,7 +2730,7 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev,
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
- return sprintf(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1);
+ return sysfs_emit(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1);
}
static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev,
@@ -2899,7 +2900,7 @@ static ssize_t amdgpu_hwmon_show_power_cap_min(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%i\n", 0);
+ return sysfs_emit(buf, "%i\n", 0);
}
@@ -3174,6 +3175,9 @@ static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev,
*
* - fan[1-\*]_enable: Enable or disable the sensors.1: Enable 0: Disable
*
+ * NOTE: DO NOT set the fan speed via "pwm1" and "fan[1-\*]_target" interfaces at the same time.
+ * That will get the former one overridden.
+ *
* hwmon interfaces for GPU clocks:
*
* - freq1_input: the gfx/compute clock in hertz
@@ -3349,13 +3353,13 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
if (!is_support_sw_smu(adev)) {
/* mask fan attributes if we have no bindings for this asic to expose */
- if ((!adev->powerplay.pp_funcs->get_fan_speed_percent &&
+ if ((!adev->powerplay.pp_funcs->get_fan_speed_pwm &&
attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */
(!adev->powerplay.pp_funcs->get_fan_control_mode &&
attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */
effective_mode &= ~S_IRUGO;
- if ((!adev->powerplay.pp_funcs->set_fan_speed_percent &&
+ if ((!adev->powerplay.pp_funcs->set_fan_speed_pwm &&
attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */
(!adev->powerplay.pp_funcs->set_fan_control_mode &&
attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */
@@ -3379,8 +3383,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
if (!is_support_sw_smu(adev)) {
/* hide max/min values if we can't both query and manage the fan */
- if ((!adev->powerplay.pp_funcs->set_fan_speed_percent &&
- !adev->powerplay.pp_funcs->get_fan_speed_percent) &&
+ if ((!adev->powerplay.pp_funcs->set_fan_speed_pwm &&
+ !adev->powerplay.pp_funcs->get_fan_speed_pwm) &&
(!adev->powerplay.pp_funcs->set_fan_speed_rpm &&
!adev->powerplay.pp_funcs->get_fan_speed_rpm) &&
(attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
index f6e0e7d8a007..98f1b3d8c1d5 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
@@ -280,11 +280,11 @@ enum amdgpu_pcie_gen {
#define amdgpu_dpm_get_fan_control_mode(adev) \
((adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle))
-#define amdgpu_dpm_set_fan_speed_percent(adev, s) \
- ((adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)))
+#define amdgpu_dpm_set_fan_speed_pwm(adev, s) \
+ ((adev)->powerplay.pp_funcs->set_fan_speed_pwm((adev)->powerplay.pp_handle, (s)))
-#define amdgpu_dpm_get_fan_speed_percent(adev, s) \
- ((adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)))
+#define amdgpu_dpm_get_fan_speed_pwm(adev, s) \
+ ((adev)->powerplay.pp_funcs->get_fan_speed_pwm((adev)->powerplay.pp_handle, (s)))
#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \
((adev)->powerplay.pp_funcs->get_fan_speed_rpm)((adev)->powerplay.pp_handle, (s))
@@ -450,6 +450,7 @@ struct amdgpu_pm {
/* Used for I2C access to various EEPROMs on relevant ASICs */
struct i2c_adapter smu_i2c;
+ struct mutex smu_i2c_mutex;
struct list_head pm_attr_list;
};
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
index 3e89852e4820..715b4225f5ee 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
@@ -34,6 +34,8 @@
#define SMU_FW_NAME_LEN 0x24
#define SMU_DPM_USER_PROFILE_RESTORE (1 << 0)
+#define SMU_CUSTOM_FAN_SPEED_RPM (1 << 1)
+#define SMU_CUSTOM_FAN_SPEED_PWM (1 << 2)
// Power Throttlers
#define SMU_THROTTLER_PPT0_BIT 0
@@ -229,8 +231,10 @@ enum smu_memory_pool_size
struct smu_user_dpm_profile {
uint32_t fan_mode;
uint32_t power_limit;
- uint32_t fan_speed_percent;
+ uint32_t fan_speed_pwm;
+ uint32_t fan_speed_rpm;
uint32_t flags;
+ uint32_t user_od;
/* user clock state information */
uint32_t clk_mask[SMU_CLK_COUNT];
@@ -352,6 +356,7 @@ struct smu_table_context
void *overdrive_table;
void *boot_overdrive_table;
+ void *user_overdrive_table;
uint32_t gpu_metrics_table_size;
void *gpu_metrics_table;
@@ -538,7 +543,7 @@ struct smu_context
struct work_struct interrupt_work;
unsigned fan_max_rpm;
- unsigned manual_fan_speed_percent;
+ unsigned manual_fan_speed_pwm;
uint32_t gfx_default_hard_min_freq;
uint32_t gfx_default_soft_max_freq;
@@ -624,6 +629,12 @@ struct pptable_funcs {
long *input, uint32_t size);
/**
+ * @restore_user_od_settings: Restore the user customized
+ * OD settings on S3/S4/Runpm resume.
+ */
+ int (*restore_user_od_settings)(struct smu_context *smu);
+
+ /**
* @get_clock_by_type_with_latency: Get the speed and latency of a clock
* domain.
*/
@@ -714,9 +725,14 @@ struct pptable_funcs {
bool (*is_dpm_running)(struct smu_context *smu);
/**
- * @get_fan_speed_percent: Get the current fan speed in percent.
+ * @get_fan_speed_pwm: Get the current fan speed in PWM.
*/
- int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed);
+ int (*get_fan_speed_pwm)(struct smu_context *smu, uint32_t *speed);
+
+ /**
+ * @get_fan_speed_rpm: Get the current fan speed in rpm.
+ */
+ int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed);
/**
* @set_watermarks_table: Configure and upload the watermarks tables to
@@ -1035,9 +1051,14 @@ struct pptable_funcs {
int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
/**
- * @set_fan_speed_percent: Set a static fan speed in percent.
+ * @set_fan_speed_pwm: Set a static fan speed in PWM.
+ */
+ int (*set_fan_speed_pwm)(struct smu_context *smu, uint32_t speed);
+
+ /**
+ * @set_fan_speed_rpm: Set a static fan speed in rpm.
*/
- int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed);
+ int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed);
/**
* @set_xgmi_pstate: Set inter-chip global memory interconnect pstate.
diff --git a/drivers/gpu/drm/amd/pm/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/inc/hwmgr.h
index 490371bd2520..8ed01071fe5a 100644
--- a/drivers/gpu/drm/amd/pm/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/inc/hwmgr.h
@@ -278,9 +278,9 @@ struct pp_hwmgr_func {
int (*get_fan_speed_info)(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info);
void (*set_fan_control_mode)(struct pp_hwmgr *hwmgr, uint32_t mode);
uint32_t (*get_fan_control_mode)(struct pp_hwmgr *hwmgr);
- int (*set_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t percent);
- int (*get_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t *speed);
- int (*set_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t percent);
+ int (*set_fan_speed_pwm)(struct pp_hwmgr *hwmgr, uint32_t speed);
+ int (*get_fan_speed_pwm)(struct pp_hwmgr *hwmgr, uint32_t *speed);
+ int (*set_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t speed);
int (*get_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t *speed);
int (*reset_fan_speed_to_default)(struct pp_hwmgr *hwmgr);
int (*uninitialize_thermal_controller)(struct pp_hwmgr *hwmgr);
diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h
new file mode 100644
index 000000000000..8a08ecc34c69
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SMU11_DRIVER_IF_CYAN_SKILLFISH_H__
+#define __SMU11_DRIVER_IF_CYAN_SKILLFISH_H__
+
+// *** IMPORTANT ***
+// Always increment the interface version if
+// any structure is changed in this file
+#define MP1_DRIVER_IF_VERSION 0x8
+
+#define TABLE_BIOS_IF 0 // Called by BIOS
+#define TABLE_WATERMARKS 1 // Called by Driver; defined here, but not used, for backward compatible
+#define TABLE_PMSTATUSLOG 3 // Called by Tools for Agm logging
+#define TABLE_DPMCLOCKS 4 // Called by Driver; defined here, but not used, for backward compatible
+#define TABLE_MOMENTARY_PM 5 // Called by Tools; defined here, but not used, for backward compatible
+#define TABLE_COUNT 6
+
+#define NUM_DSPCLK_LEVELS 8
+#define NUM_SOCCLK_DPM_LEVELS 8
+#define NUM_DCEFCLK_DPM_LEVELS 4
+#define NUM_FCLK_DPM_LEVELS 4
+#define NUM_MEMCLK_DPM_LEVELS 4
+
+#define NUMBER_OF_PSTATES 8
+#define NUMBER_OF_CORES 8
+
+typedef enum {
+ S3_TYPE_ENTRY,
+ S5_TYPE_ENTRY,
+} Sleep_Type_e;
+
+typedef enum {
+ GFX_OFF = 0,
+ GFX_ON = 1,
+} GFX_Mode_e;
+
+typedef enum {
+ CPU_P0 = 0,
+ CPU_P1,
+ CPU_P2,
+ CPU_P3,
+ CPU_P4,
+ CPU_P5,
+ CPU_P6,
+ CPU_P7
+} CPU_PState_e;
+
+typedef enum {
+ CPU_CORE0 = 0,
+ CPU_CORE1,
+ CPU_CORE2,
+ CPU_CORE3,
+ CPU_CORE4,
+ CPU_CORE5,
+ CPU_CORE6,
+ CPU_CORE7
+} CORE_ID_e;
+
+typedef enum {
+ DF_DPM0 = 0,
+ DF_DPM1,
+ DF_DPM2,
+ DF_DPM3,
+ DF_PState_Count
+} DF_PState_e;
+
+typedef enum {
+ GFX_DPM0 = 0,
+ GFX_DPM1,
+ GFX_DPM2,
+ GFX_DPM3,
+ GFX_PState_Count
+} GFX_PState_e;
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h
index 61c87c39be80..63b8701fd466 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h
@@ -131,7 +131,7 @@
#define FEATURE_GFX_EDC_BIT 49
#define FEATURE_GFX_PER_PART_VMIN_BIT 50
#define FEATURE_SMART_SHIFT_BIT 51
-#define FEATURE_SPARE_52_BIT 52
+#define FEATURE_APT_BIT 52
#define FEATURE_SPARE_53_BIT 53
#define FEATURE_SPARE_54_BIT 54
#define FEATURE_SPARE_55_BIT 55
@@ -211,6 +211,7 @@ typedef enum {
#define THROTTLER_FIT_BIT 17
#define THROTTLER_PPM_BIT 18
#define THROTTLER_APCC_BIT 19
+#define THROTTLER_COUNT 20
// FW DState Features Control Bits
// FW DState Features Control Bits
@@ -1406,7 +1407,67 @@ typedef struct {
} SmuMetrics_t;
typedef struct {
- SmuMetrics_t SmuMetrics;
+ uint32_t CurrClock[PPCLK_COUNT];
+
+ uint16_t AverageGfxclkFrequencyPreDs;
+ uint16_t AverageGfxclkFrequencyPostDs;
+ uint16_t AverageFclkFrequencyPreDs;
+ uint16_t AverageFclkFrequencyPostDs;
+ uint16_t AverageUclkFrequencyPreDs ;
+ uint16_t AverageUclkFrequencyPostDs ;
+
+
+ uint16_t AverageGfxActivity ;
+ uint16_t AverageUclkActivity ;
+ uint8_t CurrSocVoltageOffset ;
+ uint8_t CurrGfxVoltageOffset ;
+ uint8_t CurrMemVidOffset ;
+ uint8_t Padding8 ;
+ uint16_t AverageSocketPower ;
+ uint16_t TemperatureEdge ;
+ uint16_t TemperatureHotspot ;
+ uint16_t TemperatureMem ;
+ uint16_t TemperatureVrGfx ;
+ uint16_t TemperatureVrMem0 ;
+ uint16_t TemperatureVrMem1 ;
+ uint16_t TemperatureVrSoc ;
+ uint16_t TemperatureLiquid0 ;
+ uint16_t TemperatureLiquid1 ;
+ uint16_t TemperaturePlx ;
+ uint16_t Padding16 ;
+ uint32_t AccCnt ;
+ uint8_t ThrottlingPercentage[THROTTLER_COUNT];
+
+
+ uint8_t LinkDpmLevel;
+ uint8_t CurrFanPwm;
+ uint16_t CurrFanSpeed;
+
+ //BACO metrics, PMFW-1721
+ //metrics for D3hot entry/exit and driver ARM msgs
+ uint8_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT];
+ uint8_t D3HotExitCountPerMode[D3HOT_SEQUENCE_COUNT];
+ uint8_t ArmMsgReceivedCountPerMode[D3HOT_SEQUENCE_COUNT];
+
+ //PMFW-4362
+ uint32_t EnergyAccumulator;
+ uint16_t AverageVclk0Frequency ;
+ uint16_t AverageDclk0Frequency ;
+ uint16_t AverageVclk1Frequency ;
+ uint16_t AverageDclk1Frequency ;
+ uint16_t VcnActivityPercentage ; //place holder, David N. to provide full sequence
+ uint8_t PcieRate ;
+ uint8_t PcieWidth ;
+ uint16_t AverageGfxclkFrequencyTarget;
+ uint16_t Padding16_2;
+
+} SmuMetrics_V2_t;
+
+typedef struct {
+ union {
+ SmuMetrics_t SmuMetrics;
+ SmuMetrics_V2_t SmuMetrics_V2;
+ };
uint32_t Spare[1];
// Padding - ignore
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_types.h b/drivers/gpu/drm/amd/pm/inc/smu_types.h
index 1d3765b873df..6f1b1b50d527 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_types.h
@@ -282,6 +282,7 @@ enum smu_clk_type {
__SMU_DUMMY_MAP(TDC), \
__SMU_DUMMY_MAP(THERMAL), \
__SMU_DUMMY_MAP(GFX_PER_CU_CG), \
+ __SMU_DUMMY_MAP(DATA_CALCULATIONS), \
__SMU_DUMMY_MAP(RM), \
__SMU_DUMMY_MAP(DS_DCEFCLK), \
__SMU_DUMMY_MAP(ACDC), \
@@ -297,7 +298,6 @@ enum smu_clk_type {
__SMU_DUMMY_MAP(DS_FCLK), \
__SMU_DUMMY_MAP(DS_MP1CLK), \
__SMU_DUMMY_MAP(DS_MP0CLK), \
- __SMU_DUMMY_MAP(XGMI), \
__SMU_DUMMY_MAP(XGMI_PER_LINK_PWR_DWN), \
__SMU_DUMMY_MAP(DPM_GFX_PACE), \
__SMU_DUMMY_MAP(MEM_VDDCI_SCALING), \
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
index f61b5c914a3d..cbdae8a2c698 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
@@ -30,11 +30,12 @@
#define SMU11_DRIVER_IF_VERSION_NV10 0x37
#define SMU11_DRIVER_IF_VERSION_NV12 0x38
#define SMU11_DRIVER_IF_VERSION_NV14 0x38
-#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x3D
+#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x40
#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0xE
#define SMU11_DRIVER_IF_VERSION_VANGOGH 0x03
#define SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish 0xF
#define SMU11_DRIVER_IF_VERSION_Beige_Goby 0xD
+#define SMU11_DRIVER_IF_VERSION_Cyan_Skillfish 0x8
/* MP Apertures */
#define MP0_Public 0x03800000
@@ -220,9 +221,18 @@ int
smu_v11_0_set_fan_control_mode(struct smu_context *smu,
uint32_t mode);
-int smu_v11_0_set_fan_speed_percent(struct smu_context *smu,
+int smu_v11_0_set_fan_speed_pwm(struct smu_context *smu,
uint32_t speed);
+int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
+ uint32_t speed);
+
+int smu_v11_0_get_fan_speed_pwm(struct smu_context *smu,
+ uint32_t *speed);
+
+int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed);
+
int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
uint32_t pstate);
@@ -302,5 +312,7 @@ void smu_v11_0_interrupt_work(struct smu_context *smu);
int smu_v11_0_set_light_sbr(struct smu_context *smu, bool enable);
+int smu_v11_0_restore_user_od_settings(struct smu_context *smu);
+
#endif
#endif
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h
new file mode 100644
index 000000000000..bd4fcb6b9610
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __SMU_V11_8_0_PMFW_H__
+#define __SMU_V11_8_0_PMFW_H__
+
+#pragma pack(push, 1)
+
+#define ENABLE_DEBUG_FEATURES
+
+// Feature Control Defines
+#define FEATURE_CCLK_CONTROLLER_BIT 0
+#define FEATURE_GFXCLK_EFFT_FREQ_BIT 1
+#define FEATURE_DATA_CALCULATION_BIT 2
+#define FEATURE_THERMAL_BIT 3
+#define FEATURE_PLL_POWER_DOWN_BIT 4
+#define FEATURE_FCLK_DPM_BIT 5
+#define FEATURE_GFX_DPM_BIT 6
+#define FEATURE_DS_GFXCLK_BIT 7
+#define FEATURE_DS_SOCCLK_BIT 8
+#define FEATURE_DS_LCLK_BIT 9
+#define FEATURE_CORE_CSTATES_BIT 10
+#define FEATURE_G6_SSC_BIT 11 //G6 memory UCLK and UCLK_DIV SS
+#define FEATURE_RM_BIT 12
+#define FEATURE_SOC_DPM_BIT 13
+#define FEATURE_DS_SMNCLK_BIT 14
+#define FEATURE_DS_MP1CLK_BIT 15
+#define FEATURE_DS_MP0CLK_BIT 16
+#define FEATURE_MGCG_BIT 17
+#define FEATURE_DS_FUSE_SRAM_BIT 18
+#define FEATURE_GFX_CKS_BIT 19
+#define FEATURE_FP_THROTTLING_BIT 20
+#define FEATURE_PROCHOT_BIT 21
+#define FEATURE_CPUOFF_BIT 22
+#define FEATURE_UMC_THROTTLE_BIT 23
+#define FEATURE_DF_THROTTLE_BIT 24
+#define FEATURE_DS_MP3CLK_BIT 25
+#define FEATURE_DS_SHUBCLK_BIT 26
+#define FEATURE_TDC_BIT 27 //Legacy APM_BIT
+#define FEATURE_UMC_CAL_SHARING_BIT 28
+#define FEATURE_DFLL_BTC_CALIBRATION_BIT 29
+#define FEATURE_EDC_BIT 30
+#define FEATURE_DLDO_BIT 31
+#define FEATURE_MEAS_DRAM_BLACKOUT_BIT 32
+#define FEATURE_CC1_BIT 33
+#define FEATURE_PPT_BIT 34
+#define FEATURE_STAPM_BIT 35
+#define FEATURE_CSTATE_BOOST_BIT 36
+#define FEATURE_SPARE_37_BIT 37
+#define FEATURE_SPARE_38_BIT 38
+#define FEATURE_SPARE_39_BIT 39
+#define FEATURE_SPARE_40_BIT 40
+#define FEATURE_SPARE_41_BIT 41
+#define FEATURE_SPARE_42_BIT 42
+#define FEATURE_SPARE_43_BIT 43
+#define FEATURE_SPARE_44_BIT 44
+#define FEATURE_SPARE_45_BIT 45
+#define FEATURE_SPARE_46_BIT 46
+#define FEATURE_SPARE_47_BIT 47
+#define FEATURE_SPARE_48_BIT 48
+#define FEATURE_SPARE_49_BIT 49
+#define FEATURE_SPARE_50_BIT 50
+#define FEATURE_SPARE_51_BIT 51
+#define FEATURE_SPARE_52_BIT 52
+#define FEATURE_SPARE_53_BIT 53
+#define FEATURE_SPARE_54_BIT 54
+#define FEATURE_SPARE_55_BIT 55
+#define FEATURE_SPARE_56_BIT 56
+#define FEATURE_SPARE_57_BIT 57
+#define FEATURE_SPARE_58_BIT 58
+#define FEATURE_SPARE_59_BIT 59
+#define FEATURE_SPARE_60_BIT 60
+#define FEATURE_SPARE_61_BIT 61
+#define FEATURE_SPARE_62_BIT 62
+#define FEATURE_SPARE_63_BIT 63
+
+#define NUM_FEATURES 64
+
+#define FEATURE_CCLK_CONTROLLER_MASK (1 << FEATURE_CCLK_CONTROLLER_BIT)
+#define FEATURE_DATA_CALCULATION_MASK (1 << FEATURE_DATA_CALCULATION_BIT)
+#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT)
+#define FEATURE_PLL_POWER_DOWN_MASK (1 << FEATURE_PLL_POWER_DOWN_BIT)
+#define FEATURE_FCLK_DPM_MASK (1 << FEATURE_FCLK_DPM_BIT)
+#define FEATURE_GFX_DPM_MASK (1 << FEATURE_GFX_DPM_BIT)
+#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT)
+#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT)
+#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT)
+#define FEATURE_RM_MASK (1 << FEATURE_RM_BIT)
+#define FEATURE_DS_SMNCLK_MASK (1 << FEATURE_DS_SMNCLK_BIT)
+#define FEATURE_DS_MP1CLK_MASK (1 << FEATURE_DS_MP1CLK_BIT)
+#define FEATURE_DS_MP0CLK_MASK (1 << FEATURE_DS_MP0CLK_BIT)
+#define FEATURE_MGCG_MASK (1 << FEATURE_MGCG_BIT)
+#define FEATURE_DS_FUSE_SRAM_MASK (1 << FEATURE_DS_FUSE_SRAM_BIT)
+#define FEATURE_PROCHOT_MASK (1 << FEATURE_PROCHOT_BIT)
+#define FEATURE_CPUOFF_MASK (1 << FEATURE_CPUOFF_BIT)
+#define FEATURE_GFX_CKS_MASK (1 << FEATURE_GFX_CKS_BIT)
+#define FEATURE_UMC_THROTTLE_MASK (1 << FEATURE_UMC_THROTTLE_BIT)
+#define FEATURE_DF_THROTTLE_MASK (1 << FEATURE_DF_THROTTLE_BIT)
+#define FEATURE_SOC_DPM_MASK (1 << FEATURE_SOC_DPM_BIT)
+
+typedef struct {
+ // MP1_EXT_SCRATCH0
+ uint32_t SPARE1 : 4;
+ uint32_t SPARE2 : 4;
+ uint32_t SPARE3 : 4;
+ uint32_t CurrLevel_LCLK : 4;
+ uint32_t CurrLevel_MP0CLK : 4;
+ uint32_t CurrLevel_FCLK : 4;
+ uint32_t CurrLevel_SOCCLK : 4;
+ uint32_t CurrLevel_DCEFCLK : 4;
+ // MP1_EXT_SCRATCH1
+ uint32_t SPARE4 : 4;
+ uint32_t SPARE5 : 4;
+ uint32_t SPARE6 : 4;
+ uint32_t TargLevel_LCLK : 4;
+ uint32_t TargLevel_MP0CLK : 4;
+ uint32_t TargLevel_FCLK : 4;
+ uint32_t TargLevel_SOCCLK : 4;
+ uint32_t TargLevel_DCEFCLK : 4;
+ // MP1_EXT_SCRATCH2
+ uint32_t CurrLevel_SHUBCLK : 4;
+ uint32_t TargLevel_SHUBCLK : 4;
+ uint32_t Reserved : 24;
+ // MP1_EXT_SCRATCH3-4
+ uint32_t Reserved2[2];
+ // MP1_EXT_SCRATCH5
+ uint32_t FeatureStatus[NUM_FEATURES / 32];
+} FwStatus_t;
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h
new file mode 100644
index 000000000000..6e6088760b18
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef SMU_11_8_0_PPSMC_H
+#define SMU_11_8_0_PPSMC_H
+
+// SMU Response Codes:
+#define PPSMC_Result_OK 0x1
+#define PPSMC_Result_Failed 0xFF
+#define PPSMC_Result_UnknownCmd 0xFE
+#define PPSMC_Result_CmdRejectedPrereq 0xFD
+#define PPSMC_Result_CmdRejectedBusy 0xFC
+
+// Message Definitions:
+#define PPSMC_MSG_TestMessage 0x1
+#define PPSMC_MSG_GetSmuVersion 0x2
+#define PPSMC_MSG_GetDriverIfVersion 0x3
+#define PPSMC_MSG_SetDriverTableDramAddrHigh 0x4
+#define PPSMC_MSG_SetDriverTableDramAddrLow 0x5
+#define PPSMC_MSG_TransferTableSmu2Dram 0x6
+#define PPSMC_MSG_TransferTableDram2Smu 0x7
+#define PPSMC_MSG_Rsvd1 0xA
+#define PPSMC_MSG_RequestCorePstate 0xB
+#define PPSMC_MSG_QueryCorePstate 0xC
+#define PPSMC_MSG_Rsvd2 0xD
+#define PPSMC_MSG_RequestGfxclk 0xE
+#define PPSMC_MSG_QueryGfxclk 0xF
+#define PPSMC_MSG_QueryVddcrSocClock 0x11
+#define PPSMC_MSG_QueryDfPstate 0x13
+#define PPSMC_MSG_Rsvd3 0x14
+#define PPSMC_MSG_ConfigureS3PwrOffRegisterAddressHigh 0x16
+#define PPSMC_MSG_ConfigureS3PwrOffRegisterAddressLow 0x17
+#define PPSMC_MSG_RequestActiveWgp 0x18
+#define PPSMC_MSG_SetMinDeepSleepGfxclkFreq 0x19
+#define PPSMC_MSG_SetMaxDeepSleepDfllGfxDiv 0x1A
+#define PPSMC_MSG_StartTelemetryReporting 0x1B
+#define PPSMC_MSG_StopTelemetryReporting 0x1C
+#define PPSMC_MSG_ClearTelemetryMax 0x1D
+#define PPSMC_MSG_QueryActiveWgp 0x1E
+#define PPSMC_MSG_SetCoreEnableMask 0x2C
+#define PPSMC_MSG_InitiateGcRsmuSoftReset 0x2E
+#define PPSMC_MSG_GfxCacWeightOperation 0x2F
+#define PPSMC_MSG_L3CacWeightOperation 0x30
+#define PPSMC_MSG_PackCoreCacWeight 0x31
+#define PPSMC_MSG_SetDriverTableVMID 0x34
+#define PPSMC_MSG_SetSoftMinCclk 0x35
+#define PPSMC_MSG_SetSoftMaxCclk 0x36
+#define PPSMC_Message_Count 0x37
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
index d2a38246a78a..321215003643 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
@@ -533,7 +533,7 @@ static uint32_t pp_dpm_get_fan_control_mode(void *handle)
return mode;
}
-static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
+static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed)
{
struct pp_hwmgr *hwmgr = handle;
int ret = 0;
@@ -541,17 +541,17 @@ static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
if (!hwmgr || !hwmgr->pm_en)
return -EINVAL;
- if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
+ if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL) {
pr_info_ratelimited("%s was not implemented.\n", __func__);
return 0;
}
mutex_lock(&hwmgr->smu_lock);
- ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
+ ret = hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed);
mutex_unlock(&hwmgr->smu_lock);
return ret;
}
-static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
+static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed)
{
struct pp_hwmgr *hwmgr = handle;
int ret = 0;
@@ -559,13 +559,13 @@ static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
if (!hwmgr || !hwmgr->pm_en)
return -EINVAL;
- if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
+ if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL) {
pr_info_ratelimited("%s was not implemented.\n", __func__);
return 0;
}
mutex_lock(&hwmgr->smu_lock);
- ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
+ ret = hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed);
mutex_unlock(&hwmgr->smu_lock);
return ret;
}
@@ -1691,8 +1691,8 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
.dispatch_tasks = pp_dpm_dispatch_tasks,
.set_fan_control_mode = pp_dpm_set_fan_control_mode,
.get_fan_control_mode = pp_dpm_get_fan_control_mode,
- .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
- .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
+ .set_fan_speed_pwm = pp_dpm_set_fan_speed_pwm,
+ .get_fan_speed_pwm = pp_dpm_get_fan_speed_pwm,
.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
.set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm,
.get_pp_num_states = pp_dpm_get_pp_num_states,
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
index 43c3f6e755e7..1de3ae77e03e 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
@@ -1036,13 +1036,13 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr,
else
i = 1;
- size += sprintf(buf + size, "0: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "0: %uMhz %s\n",
data->gfx_min_freq_limit/100,
i == 0 ? "*" : "");
- size += sprintf(buf + size, "1: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK,
i == 1 ? "*" : "");
- size += sprintf(buf + size, "2: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "2: %uMhz %s\n",
data->gfx_max_freq_limit/100,
i == 2 ? "*" : "");
break;
@@ -1050,7 +1050,7 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr,
smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &now);
for (i = 0; i < mclk_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i,
mclk_table->entries[i].clk / 100,
((mclk_table->entries[i].clk / 100)
@@ -1065,10 +1065,10 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr,
if (ret)
return ret;
- size = sprintf(buf, "%s:\n", "OD_SCLK");
- size += sprintf(buf + size, "0: %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_SCLK");
+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
(data->gfx_actual_soft_min_freq > 0) ? data->gfx_actual_soft_min_freq : min_freq);
- size += sprintf(buf + size, "1: %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
(data->gfx_actual_soft_max_freq > 0) ? data->gfx_actual_soft_max_freq : max_freq);
}
break;
@@ -1081,8 +1081,8 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr,
if (ret)
return ret;
- size = sprintf(buf, "%s:\n", "OD_RANGE");
- size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n",
min_freq, max_freq);
}
break;
@@ -1456,11 +1456,11 @@ static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
if (!buf)
return -EINVAL;
- size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0],
+ size += sysfs_emit_at(buf, size, "%s %16s %s %s %s %s\n",title[0],
title[1], title[2], title[3], title[4], title[5]);
for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++)
- size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n",
+ size += sysfs_emit_at(buf, size, "%3d %14s%s: %14d %3d %10d %14d\n",
i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
profile_mode_setting[i][0], profile_mode_setting[i][1],
profile_mode_setting[i][2], profile_mode_setting[i][3]);
@@ -1580,7 +1580,7 @@ static int smu10_set_fine_grain_clk_vol(struct pp_hwmgr *hwmgr,
}
if (smu10_data->gfx_actual_soft_min_freq > smu10_data->gfx_actual_soft_max_freq) {
- pr_err("The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
+ pr_err("The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
smu10_data->gfx_actual_soft_min_freq, smu10_data->gfx_actual_soft_max_freq);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
index 0541bfc81c1b..465ff8d2a01a 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -3212,7 +3212,7 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr,
if (!ret) {
if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
- smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
+ smu7_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr);
}
@@ -4896,8 +4896,8 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels);
struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels);
- int i, now, size = 0;
- uint32_t clock, pcie_speed;
+ int size = 0;
+ uint32_t i, now, clock, pcie_speed;
switch (type) {
case PP_SCLK:
@@ -4911,7 +4911,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
now = i;
for (i = 0; i < sclk_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, sclk_table->dpm_levels[i].value / 100,
(i == now) ? "*" : "");
break;
@@ -4926,7 +4926,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
now = i;
for (i = 0; i < mclk_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, mclk_table->dpm_levels[i].value / 100,
(i == now) ? "*" : "");
break;
@@ -4940,7 +4940,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
now = i;
for (i = 0; i < pcie_table->count; i++)
- size += sprintf(buf + size, "%d: %s %s\n", i,
+ size += sysfs_emit_at(buf, size, "%d: %s %s\n", i,
(pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" :
(pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" :
(pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "",
@@ -4948,32 +4948,32 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
break;
case OD_SCLK:
if (hwmgr->od_enabled) {
- size = sprintf(buf, "%s:\n", "OD_SCLK");
+ size = sysfs_emit(buf, "%s:\n", "OD_SCLK");
for (i = 0; i < odn_sclk_table->num_of_pl; i++)
- size += sprintf(buf + size, "%d: %10uMHz %10umV\n",
+ size += sysfs_emit_at(buf, size, "%d: %10uMHz %10umV\n",
i, odn_sclk_table->entries[i].clock/100,
odn_sclk_table->entries[i].vddc);
}
break;
case OD_MCLK:
if (hwmgr->od_enabled) {
- size = sprintf(buf, "%s:\n", "OD_MCLK");
+ size = sysfs_emit(buf, "%s:\n", "OD_MCLK");
for (i = 0; i < odn_mclk_table->num_of_pl; i++)
- size += sprintf(buf + size, "%d: %10uMHz %10umV\n",
+ size += sysfs_emit_at(buf, size, "%d: %10uMHz %10umV\n",
i, odn_mclk_table->entries[i].clock/100,
odn_mclk_table->entries[i].vddc);
}
break;
case OD_RANGE:
if (hwmgr->od_enabled) {
- size = sprintf(buf, "%s:\n", "OD_RANGE");
- size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n",
data->golden_dpm_table.sclk_table.dpm_levels[0].value/100,
hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
- size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n",
+ size += sysfs_emit_at(buf, size, "MCLK: %7uMHz %10uMHz\n",
data->golden_dpm_table.mclk_table.dpm_levels[0].value/100,
hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
- size += sprintf(buf + size, "VDDC: %7umV %11umV\n",
+ size += sysfs_emit_at(buf, size, "VDDC: %7umV %11umV\n",
data->odn_dpm_table.min_vddc,
data->odn_dpm_table.max_vddc);
}
@@ -4988,7 +4988,7 @@ static void smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
{
switch (mode) {
case AMD_FAN_CTRL_NONE:
- smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
+ smu7_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
break;
case AMD_FAN_CTRL_MANUAL:
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
@@ -5503,7 +5503,7 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
if (!buf)
return -EINVAL;
- size += sprintf(buf + size, "%s %16s %16s %16s %16s %16s %16s %16s\n",
+ size += sysfs_emit_at(buf, size, "%s %16s %16s %16s %16s %16s %16s %16s\n",
title[0], title[1], title[2], title[3],
title[4], title[5], title[6], title[7]);
@@ -5511,7 +5511,7 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
for (i = 0; i < len; i++) {
if (i == hwmgr->power_profile_mode) {
- size += sprintf(buf + size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n",
+ size += sysfs_emit_at(buf, size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n",
i, profile_name[i], "*",
data->current_profile_setting.sclk_up_hyst,
data->current_profile_setting.sclk_down_hyst,
@@ -5522,21 +5522,21 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
continue;
}
if (smu7_profiling[i].bupdate_sclk)
- size += sprintf(buf + size, "%3d %16s: %8d %16d %16d ",
+ size += sysfs_emit_at(buf, size, "%3d %16s: %8d %16d %16d ",
i, profile_name[i], smu7_profiling[i].sclk_up_hyst,
smu7_profiling[i].sclk_down_hyst,
smu7_profiling[i].sclk_activity);
else
- size += sprintf(buf + size, "%3d %16s: %8s %16s %16s ",
+ size += sysfs_emit_at(buf, size, "%3d %16s: %8s %16s %16s ",
i, profile_name[i], "-", "-", "-");
if (smu7_profiling[i].bupdate_mclk)
- size += sprintf(buf + size, "%16d %16d %16d\n",
+ size += sysfs_emit_at(buf, size, "%16d %16d %16d\n",
smu7_profiling[i].mclk_up_hyst,
smu7_profiling[i].mclk_down_hyst,
smu7_profiling[i].mclk_activity);
else
- size += sprintf(buf + size, "%16s %16s %16s\n",
+ size += sysfs_emit_at(buf, size, "%16s %16s %16s\n",
"-", "-", "-");
}
@@ -5692,8 +5692,8 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
.set_max_fan_rpm_output = smu7_set_max_fan_rpm_output,
.stop_thermal_controller = smu7_thermal_stop_thermal_controller,
.get_fan_speed_info = smu7_fan_ctrl_get_fan_speed_info,
- .get_fan_speed_percent = smu7_fan_ctrl_get_fan_speed_percent,
- .set_fan_speed_percent = smu7_fan_ctrl_set_fan_speed_percent,
+ .get_fan_speed_pwm = smu7_fan_ctrl_get_fan_speed_pwm,
+ .set_fan_speed_pwm = smu7_fan_ctrl_set_fan_speed_pwm,
.reset_fan_speed_to_default = smu7_fan_ctrl_reset_fan_speed_to_default,
.get_fan_speed_rpm = smu7_fan_ctrl_get_fan_speed_rpm,
.set_fan_speed_rpm = smu7_fan_ctrl_set_fan_speed_rpm,
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c
index 6cfe148ed45b..a6c3610db23e 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c
@@ -51,7 +51,7 @@ int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
return 0;
}
-int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+int smu7_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t *speed)
{
uint32_t duty100;
@@ -70,12 +70,9 @@ int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
return -EINVAL;
- tmp64 = (uint64_t)duty * 100;
+ tmp64 = (uint64_t)duty * 255;
do_div(tmp64, duty100);
- *speed = (uint32_t)tmp64;
-
- if (*speed > 100)
- *speed = 100;
+ *speed = MIN((uint32_t)tmp64, 255);
return 0;
}
@@ -199,12 +196,11 @@ int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
}
/**
- * smu7_fan_ctrl_set_fan_speed_percent - Set Fan Speed in percent.
+ * smu7_fan_ctrl_set_fan_speed_pwm - Set Fan Speed in PWM.
* @hwmgr: the address of the powerplay hardware manager.
- * @speed: is the percentage value (0% - 100%) to be set.
- * Exception: Fails is the 100% setting appears to be 0.
+ * @speed: is the pwm value (0 - 255) to be set.
*/
-int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+int smu7_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t speed)
{
uint32_t duty100;
@@ -214,8 +210,7 @@ int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return 0;
- if (speed > 100)
- speed = 100;
+ speed = MIN(speed, 255);
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
@@ -227,7 +222,7 @@ int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
- do_div(tmp64, 100);
+ do_div(tmp64, 255);
duty = (uint32_t)tmp64;
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h
index 42c1ba0fad78..a386a437e1f0 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h
@@ -41,10 +41,10 @@
extern int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr);
extern int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
extern int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info);
-extern int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed);
+extern int smu7_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr, uint32_t *speed);
extern int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr);
extern int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode);
-extern int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed);
+extern int smu7_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr, uint32_t speed);
extern int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
extern int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr);
extern int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
index d425b02b1418..b94a77e4e714 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
@@ -1547,7 +1547,8 @@ static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr,
struct smu8_hwmgr *data = hwmgr->backend;
struct phm_clock_voltage_dependency_table *sclk_table =
hwmgr->dyn_state.vddc_dependency_on_sclk;
- int i, now, size = 0;
+ uint32_t i, now;
+ int size = 0;
switch (type) {
case PP_SCLK:
@@ -1558,7 +1559,7 @@ static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr,
CURR_SCLK_INDEX);
for (i = 0; i < sclk_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, sclk_table->entries[i].clk / 100,
(i == now) ? "*" : "");
break;
@@ -1570,7 +1571,7 @@ static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr,
CURR_MCLK_INDEX);
for (i = SMU8_NUM_NBPMEMORYCLOCK; i > 0; i--)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
SMU8_NUM_NBPMEMORYCLOCK-i, data->sys_info.nbp_memory_clock[i-1] / 100,
(SMU8_NUM_NBPMEMORYCLOCK-i == now) ? "*" : "");
break;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
index 02e8c6e5448d..c152a61ddd2c 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
@@ -4199,7 +4199,7 @@ static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
switch (mode) {
case AMD_FAN_CTRL_NONE:
- vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
+ vega10_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
break;
case AMD_FAN_CTRL_MANUAL:
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
@@ -4553,13 +4553,13 @@ static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
"[EnableAllSmuFeatures] Failed to get enabled smc features!",
return ret);
- size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
- size += sprintf(buf + size, "%-19s %-22s %s\n",
+ size += sysfs_emit_at(buf, size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+ size += sysfs_emit_at(buf, size, "%-19s %-22s %s\n",
output_title[0],
output_title[1],
output_title[2]);
for (i = 0; i < GNLD_FEATURES_MAX; i++) {
- size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+ size += sysfs_emit_at(buf, size, "%-19s 0x%016llx %6s\n",
ppfeature_name[i],
1ULL << i,
(features_enabled & (1ULL << i)) ? "Y" : "N");
@@ -4650,7 +4650,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
else
count = sclk_table->count;
for (i = 0; i < count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, sclk_table->dpm_levels[i].value / 100,
(i == now) ? "*" : "");
break;
@@ -4661,7 +4661,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now);
for (i = 0; i < mclk_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, mclk_table->dpm_levels[i].value / 100,
(i == now) ? "*" : "");
break;
@@ -4672,7 +4672,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now);
for (i = 0; i < soc_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, soc_table->dpm_levels[i].value / 100,
(i == now) ? "*" : "");
break;
@@ -4684,7 +4684,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK, &now);
for (i = 0; i < dcef_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, dcef_table->dpm_levels[i].value / 100,
(dcef_table->dpm_levels[i].value / 100 == now) ?
"*" : "");
@@ -4698,7 +4698,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
gen_speed = pptable->PcieGenSpeed[i];
lane_width = pptable->PcieLaneCount[i];
- size += sprintf(buf + size, "%d: %s %s %s\n", i,
+ size += sysfs_emit_at(buf, size, "%d: %s %s %s\n", i,
(gen_speed == 0) ? "2.5GT/s," :
(gen_speed == 1) ? "5.0GT/s," :
(gen_speed == 2) ? "8.0GT/s," :
@@ -4717,34 +4717,34 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
case OD_SCLK:
if (hwmgr->od_enabled) {
- size = sprintf(buf, "%s:\n", "OD_SCLK");
+ size = sysfs_emit(buf, "%s:\n", "OD_SCLK");
podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
for (i = 0; i < podn_vdd_dep->count; i++)
- size += sprintf(buf + size, "%d: %10uMhz %10umV\n",
+ size += sysfs_emit_at(buf, size, "%d: %10uMhz %10umV\n",
i, podn_vdd_dep->entries[i].clk / 100,
podn_vdd_dep->entries[i].vddc);
}
break;
case OD_MCLK:
if (hwmgr->od_enabled) {
- size = sprintf(buf, "%s:\n", "OD_MCLK");
+ size = sysfs_emit(buf, "%s:\n", "OD_MCLK");
podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
for (i = 0; i < podn_vdd_dep->count; i++)
- size += sprintf(buf + size, "%d: %10uMhz %10umV\n",
+ size += sysfs_emit_at(buf, size, "%d: %10uMhz %10umV\n",
i, podn_vdd_dep->entries[i].clk/100,
podn_vdd_dep->entries[i].vddc);
}
break;
case OD_RANGE:
if (hwmgr->od_enabled) {
- size = sprintf(buf, "%s:\n", "OD_RANGE");
- size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n",
data->golden_dpm_table.gfx_table.dpm_levels[0].value/100,
hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
- size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n",
+ size += sysfs_emit_at(buf, size, "MCLK: %7uMHz %10uMHz\n",
data->golden_dpm_table.mem_table.dpm_levels[0].value/100,
hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
- size += sprintf(buf + size, "VDDC: %7umV %11umV\n",
+ size += sysfs_emit_at(buf, size, "VDDC: %7umV %11umV\n",
data->odn_dpm_table.min_vddc,
data->odn_dpm_table.max_vddc);
}
@@ -5112,15 +5112,15 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
if (!buf)
return -EINVAL;
- size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0],
+ size += sysfs_emit_at(buf, size, "%s %16s %s %s %s %s\n",title[0],
title[1], title[2], title[3], title[4], title[5]);
for (i = 0; i < PP_SMC_POWER_PROFILE_CUSTOM; i++)
- size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n",
+ size += sysfs_emit_at(buf, size, "%3d %14s%s: %14d %3d %10d %14d\n",
i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
profile_mode_setting[i][0], profile_mode_setting[i][1],
profile_mode_setting[i][2], profile_mode_setting[i][3]);
- size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", i,
+ size += sysfs_emit_at(buf, size, "%3d %14s%s: %14d %3d %10d %14d\n", i,
profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
data->custom_profile_mode[0], data->custom_profile_mode[1],
data->custom_profile_mode[2], data->custom_profile_mode[3]);
@@ -5536,8 +5536,8 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
.force_dpm_level = vega10_dpm_force_dpm_level,
.stop_thermal_controller = vega10_thermal_stop_thermal_controller,
.get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info,
- .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent,
- .set_fan_speed_percent = vega10_fan_ctrl_set_fan_speed_percent,
+ .get_fan_speed_pwm = vega10_fan_ctrl_get_fan_speed_pwm,
+ .set_fan_speed_pwm = vega10_fan_ctrl_set_fan_speed_pwm,
.reset_fan_speed_to_default =
vega10_fan_ctrl_reset_fan_speed_to_default,
.get_fan_speed_rpm = vega10_fan_ctrl_get_fan_speed_rpm,
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c
index 9b46b27bd30c..dad3e3741a4e 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c
@@ -64,7 +64,7 @@ int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
return 0;
}
-int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+int vega10_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t *speed)
{
uint32_t current_rpm;
@@ -78,11 +78,11 @@ int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
if (hwmgr->thermal_controller.
advanceFanControlParameters.usMaxFanRPM != 0)
- percent = current_rpm * 100 /
+ percent = current_rpm * 255 /
hwmgr->thermal_controller.
advanceFanControlParameters.usMaxFanRPM;
- *speed = percent > 100 ? 100 : percent;
+ *speed = MIN(percent, 255);
return 0;
}
@@ -241,12 +241,11 @@ int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
}
/**
- * vega10_fan_ctrl_set_fan_speed_percent - Set Fan Speed in percent.
+ * vega10_fan_ctrl_set_fan_speed_pwm - Set Fan Speed in PWM.
* @hwmgr: the address of the powerplay hardware manager.
- * @speed: is the percentage value (0% - 100%) to be set.
- * Exception: Fails is the 100% setting appears to be 0.
+ * @speed: is the percentage value (0 - 255) to be set.
*/
-int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+int vega10_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t speed)
{
struct amdgpu_device *adev = hwmgr->adev;
@@ -257,8 +256,7 @@ int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return 0;
- if (speed > 100)
- speed = 100;
+ speed = MIN(speed, 255);
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
@@ -270,7 +268,7 @@ int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
- do_div(tmp64, 100);
+ do_div(tmp64, 255);
duty = (uint32_t)tmp64;
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h
index 4a0ede7c1f07..6850a21a2991 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h
@@ -54,12 +54,12 @@ extern int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr);
extern int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
extern int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info);
-extern int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+extern int vega10_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t *speed);
extern int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr);
extern int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr,
uint32_t mode);
-extern int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+extern int vega10_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t speed);
extern int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
extern int vega10_thermal_ctrl_uninitialize_thermal_controller(
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
index 29e0d1d4035a..8558718e15a8 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
@@ -2146,13 +2146,13 @@ static int vega12_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
"[EnableAllSmuFeatures] Failed to get enabled smc features!",
return ret);
- size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
- size += sprintf(buf + size, "%-19s %-22s %s\n",
+ size += sysfs_emit_at(buf, size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+ size += sysfs_emit_at(buf, size, "%-19s %-22s %s\n",
output_title[0],
output_title[1],
output_title[2]);
for (i = 0; i < GNLD_FEATURES_MAX; i++) {
- size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+ size += sysfs_emit_at(buf, size, "%-19s 0x%016llx %6s\n",
ppfeature_name[i],
1ULL << i,
(features_enabled & (1ULL << i)) ? "Y" : "N");
@@ -2256,7 +2256,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr,
"Attempt to get gfx clk levels Failed!",
return -1);
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : "");
break;
@@ -2272,7 +2272,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr,
"Attempt to get memory clk levels Failed!",
return -1);
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : "");
break;
@@ -2290,7 +2290,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr,
"Attempt to get soc clk levels Failed!",
return -1);
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : "");
break;
@@ -2308,7 +2308,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr,
"Attempt to get dcef clk levels Failed!",
return -1);
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : "");
break;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
index 0791309586c5..0cf39c1244b1 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
@@ -2769,7 +2769,7 @@ static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
{
switch (mode) {
case AMD_FAN_CTRL_NONE:
- vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
+ vega20_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
break;
case AMD_FAN_CTRL_MANUAL:
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
@@ -3243,13 +3243,13 @@ static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
"[EnableAllSmuFeatures] Failed to get enabled smc features!",
return ret);
- size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
- size += sprintf(buf + size, "%-19s %-22s %s\n",
+ size += sysfs_emit_at(buf, size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+ size += sysfs_emit_at(buf, size, "%-19s %-22s %s\n",
output_title[0],
output_title[1],
output_title[2]);
for (i = 0; i < GNLD_FEATURES_MAX; i++) {
- size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+ size += sysfs_emit_at(buf, size, "%-19s 0x%016llx %6s\n",
ppfeature_name[i],
1ULL << i,
(features_enabled & (1ULL << i)) ? "Y" : "N");
@@ -3372,13 +3372,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
return ret);
if (vega20_get_sclks(hwmgr, &clocks)) {
- size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
+ size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n",
now / 100);
break;
}
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
break;
@@ -3390,13 +3390,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
return ret);
if (vega20_get_memclocks(hwmgr, &clocks)) {
- size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
+ size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n",
now / 100);
break;
}
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
break;
@@ -3408,13 +3408,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
return ret);
if (vega20_get_socclocks(hwmgr, &clocks)) {
- size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
+ size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n",
now / 100);
break;
}
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
break;
@@ -3426,7 +3426,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
return ret);
for (i = 0; i < fclk_dpm_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, fclk_dpm_table->dpm_levels[i].value,
fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
break;
@@ -3438,13 +3438,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
return ret);
if (vega20_get_dcefclocks(hwmgr, &clocks)) {
- size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
+ size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n",
now / 100);
break;
}
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
break;
@@ -3458,7 +3458,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
gen_speed = pptable->PcieGenSpeed[i];
lane_width = pptable->PcieLaneCount[i];
- size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
+ size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
(gen_speed == 0) ? "2.5GT/s," :
(gen_speed == 1) ? "5.0GT/s," :
(gen_speed == 2) ? "8.0GT/s," :
@@ -3479,18 +3479,18 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
case OD_SCLK:
if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
- size = sprintf(buf, "%s:\n", "OD_SCLK");
- size += sprintf(buf + size, "0: %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_SCLK");
+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
od_table->GfxclkFmin);
- size += sprintf(buf + size, "1: %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
od_table->GfxclkFmax);
}
break;
case OD_MCLK:
if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
- size = sprintf(buf, "%s:\n", "OD_MCLK");
- size += sprintf(buf + size, "1: %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_MCLK");
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
od_table->UclkFmax);
}
@@ -3503,14 +3503,14 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
- size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
- size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_VDDC_CURVE");
+ size += sysfs_emit_at(buf, size, "0: %10uMhz %10dmV\n",
od_table->GfxclkFreq1,
od_table->GfxclkVolt1 / VOLTAGE_SCALE);
- size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
+ size += sysfs_emit_at(buf, size, "1: %10uMhz %10dmV\n",
od_table->GfxclkFreq2,
od_table->GfxclkVolt2 / VOLTAGE_SCALE);
- size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
+ size += sysfs_emit_at(buf, size, "2: %10uMhz %10dmV\n",
od_table->GfxclkFreq3,
od_table->GfxclkVolt3 / VOLTAGE_SCALE);
}
@@ -3518,17 +3518,17 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
break;
case OD_RANGE:
- size = sprintf(buf, "%s:\n", "OD_RANGE");
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
- size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
}
if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
- size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
}
@@ -3539,22 +3539,22 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
- size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value,
od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value);
- size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
- size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value,
od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value);
- size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
- size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value,
od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value);
- size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
}
@@ -4003,7 +4003,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
if (!buf)
return -EINVAL;
- size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
+ size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
title[0], title[1], title[2], title[3], title[4], title[5],
title[6], title[7], title[8], title[9], title[10]);
@@ -4016,10 +4016,10 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
"[GetPowerProfile] Failed to get activity monitor!",
return result);
- size += sprintf(buf + size, "%2d %14s%s:\n",
+ size += sysfs_emit_at(buf, size, "%2d %14s%s:\n",
i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ");
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
0,
"GFXCLK",
@@ -4033,7 +4033,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
activity_monitor.Gfx_PD_Data_error_coeff,
activity_monitor.Gfx_PD_Data_error_rate_coeff);
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
1,
"SOCCLK",
@@ -4047,7 +4047,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
activity_monitor.Soc_PD_Data_error_coeff,
activity_monitor.Soc_PD_Data_error_rate_coeff);
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
2,
"UCLK",
@@ -4061,7 +4061,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
activity_monitor.Mem_PD_Data_error_coeff,
activity_monitor.Mem_PD_Data_error_rate_coeff);
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
3,
"FCLK",
@@ -4409,8 +4409,8 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
.register_irq_handlers = smu9_register_irq_handlers,
.disable_smc_firmware_ctf = vega20_thermal_disable_alert,
/* fan control related */
- .get_fan_speed_percent = vega20_fan_ctrl_get_fan_speed_percent,
- .set_fan_speed_percent = vega20_fan_ctrl_set_fan_speed_percent,
+ .get_fan_speed_pwm = vega20_fan_ctrl_get_fan_speed_pwm,
+ .set_fan_speed_pwm = vega20_fan_ctrl_set_fan_speed_pwm,
.get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info,
.get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm,
.set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm,
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c
index 269dd7e95a44..f4f4efdbda79 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c
@@ -114,26 +114,29 @@ static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
return 0;
}
-int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+int vega20_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t *speed)
{
- struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
- PPTable_t *pp_table = &(data->smc_state_table.pp_table);
- uint32_t current_rpm, percent = 0;
- int ret = 0;
+ struct amdgpu_device *adev = hwmgr->adev;
+ uint32_t duty100, duty;
+ uint64_t tmp64;
- ret = vega20_get_current_rpm(hwmgr, &current_rpm);
- if (ret)
- return ret;
+ duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
+ CG_FDO_CTRL1, FMAX_DUTY100);
+ duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS),
+ CG_THERMAL_STATUS, FDO_PWM_DUTY);
- percent = current_rpm * 100 / pp_table->FanMaximumRpm;
+ if (!duty100)
+ return -EINVAL;
- *speed = percent > 100 ? 100 : percent;
+ tmp64 = (uint64_t)duty * 255;
+ do_div(tmp64, duty100);
+ *speed = MIN((uint32_t)tmp64, 255);
return 0;
}
-int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+int vega20_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t speed)
{
struct amdgpu_device *adev = hwmgr->adev;
@@ -141,8 +144,7 @@ int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t duty;
uint64_t tmp64;
- if (speed > 100)
- speed = 100;
+ speed = MIN(speed, 255);
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
@@ -154,7 +156,7 @@ int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
- do_div(tmp64, 100);
+ do_div(tmp64, 255);
duty = (uint32_t)tmp64;
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h
index 2d1769bbd24e..b18d09cf761e 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h
@@ -56,9 +56,9 @@ extern int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr,
uint32_t *speed);
extern int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr,
uint32_t speed);
-extern int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+extern int vega20_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t *speed);
-extern int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+extern int vega20_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr,
uint32_t speed);
extern int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c
index 15c0b8af376f..bdbbeb959c68 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c
@@ -6539,7 +6539,7 @@ static int si_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev)
}
}
-static int si_dpm_get_fan_speed_percent(void *handle,
+static int si_dpm_get_fan_speed_pwm(void *handle,
u32 *speed)
{
u32 duty, duty100;
@@ -6555,17 +6555,14 @@ static int si_dpm_get_fan_speed_percent(void *handle,
if (duty100 == 0)
return -EINVAL;
- tmp64 = (u64)duty * 100;
+ tmp64 = (u64)duty * 255;
do_div(tmp64, duty100);
- *speed = (u32)tmp64;
-
- if (*speed > 100)
- *speed = 100;
+ *speed = MIN((u32)tmp64, 255);
return 0;
}
-static int si_dpm_set_fan_speed_percent(void *handle,
+static int si_dpm_set_fan_speed_pwm(void *handle,
u32 speed)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -6580,7 +6577,7 @@ static int si_dpm_set_fan_speed_percent(void *handle,
if (si_pi->fan_is_controlled_by_smc)
return -EINVAL;
- if (speed > 100)
+ if (speed > 255)
return -EINVAL;
duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
@@ -6589,7 +6586,7 @@ static int si_dpm_set_fan_speed_percent(void *handle,
return -EINVAL;
tmp64 = (u64)speed * duty100;
- do_div(tmp64, 100);
+ do_div(tmp64, 255);
duty = (u32)tmp64;
tmp = RREG32(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK;
@@ -8059,8 +8056,8 @@ static const struct amd_pm_funcs si_dpm_funcs = {
.vblank_too_short = &si_dpm_vblank_too_short,
.set_fan_control_mode = &si_dpm_set_fan_control_mode,
.get_fan_control_mode = &si_dpm_get_fan_control_mode,
- .set_fan_speed_percent = &si_dpm_set_fan_speed_percent,
- .get_fan_speed_percent = &si_dpm_get_fan_speed_percent,
+ .set_fan_speed_pwm = &si_dpm_set_fan_speed_pwm,
+ .get_fan_speed_pwm = &si_dpm_get_fan_speed_pwm,
.check_state_equal = &si_check_state_equal,
.get_vce_clock_state = amdgpu_get_vce_clock_state,
.read_sensor = &si_dpm_read_sensor,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index ebe672142808..3ab1ce4d3419 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -36,6 +36,7 @@
#include "vangogh_ppt.h"
#include "aldebaran_ppt.h"
#include "yellow_carp_ppt.h"
+#include "cyan_skillfish_ppt.h"
#include "amd_pcie.h"
/*
@@ -57,7 +58,7 @@ static int smu_handle_task(struct smu_context *smu,
enum amd_pp_task task_id,
bool lock_needed);
static int smu_reset(struct smu_context *smu);
-static int smu_set_fan_speed_percent(void *handle, u32 speed);
+static int smu_set_fan_speed_pwm(void *handle, u32 speed);
static int smu_set_fan_control_mode(struct smu_context *smu, int value);
static int smu_set_power_limit(void *handle, uint32_t limit);
static int smu_set_fan_speed_rpm(void *handle, uint32_t speed);
@@ -402,17 +403,35 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu)
}
/* set the user dpm fan configurations */
- if (smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_MANUAL) {
+ if (smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_MANUAL ||
+ smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_NONE) {
ret = smu_set_fan_control_mode(smu, smu->user_dpm_profile.fan_mode);
if (ret) {
+ smu->user_dpm_profile.fan_speed_pwm = 0;
+ smu->user_dpm_profile.fan_speed_rpm = 0;
+ smu->user_dpm_profile.fan_mode = AMD_FAN_CTRL_AUTO;
dev_err(smu->adev->dev, "Failed to set manual fan control mode\n");
- return;
}
- if (!ret && smu->user_dpm_profile.fan_speed_percent) {
- ret = smu_set_fan_speed_percent(smu, smu->user_dpm_profile.fan_speed_percent);
+ if (smu->user_dpm_profile.fan_speed_pwm) {
+ ret = smu_set_fan_speed_pwm(smu, smu->user_dpm_profile.fan_speed_pwm);
+ if (ret)
+ dev_err(smu->adev->dev, "Failed to set manual fan speed in pwm\n");
+ }
+
+ if (smu->user_dpm_profile.fan_speed_rpm) {
+ ret = smu_set_fan_speed_rpm(smu, smu->user_dpm_profile.fan_speed_rpm);
if (ret)
- dev_err(smu->adev->dev, "Failed to set manual fan speed\n");
+ dev_err(smu->adev->dev, "Failed to set manual fan speed in rpm\n");
+ }
+ }
+
+ /* Restore user customized OD settings */
+ if (smu->user_dpm_profile.user_od) {
+ if (smu->ppt_funcs->restore_user_od_settings) {
+ ret = smu->ppt_funcs->restore_user_od_settings(smu);
+ if (ret)
+ dev_err(smu->adev->dev, "Failed to upload customized OD settings\n");
}
}
@@ -588,6 +607,9 @@ static int smu_set_funcs(struct amdgpu_device *adev)
case CHIP_YELLOW_CARP:
yellow_carp_set_ppt_funcs(smu);
break;
+ case CHIP_CYAN_SKILLFISH:
+ cyan_skillfish_set_ppt_funcs(smu);
+ break;
default:
return -EINVAL;
}
@@ -607,6 +629,7 @@ static int smu_early_init(void *handle)
mutex_init(&smu->smu_baco.mutex);
smu->smu_baco.state = SMU_BACO_STATE_EXIT;
smu->smu_baco.platform_support = false;
+ smu->user_dpm_profile.fan_mode = -1;
adev->powerplay.pp_handle = smu;
adev->powerplay.pp_funcs = &swsmu_pm_funcs;
@@ -2166,7 +2189,6 @@ static int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled)
static int smu_set_fan_speed_rpm(void *handle, uint32_t speed)
{
struct smu_context *smu = handle;
- u32 percent;
int ret = 0;
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
@@ -2174,11 +2196,16 @@ static int smu_set_fan_speed_rpm(void *handle, uint32_t speed)
mutex_lock(&smu->mutex);
- if (smu->ppt_funcs->set_fan_speed_percent) {
- percent = speed * 100 / smu->fan_max_rpm;
- ret = smu->ppt_funcs->set_fan_speed_percent(smu, percent);
- if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE))
- smu->user_dpm_profile.fan_speed_percent = percent;
+ if (smu->ppt_funcs->set_fan_speed_rpm) {
+ ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed);
+ if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) {
+ smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_RPM;
+ smu->user_dpm_profile.fan_speed_rpm = speed;
+
+ /* Override custom PWM setting as they cannot co-exist */
+ smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_PWM;
+ smu->user_dpm_profile.fan_speed_pwm = 0;
+ }
}
mutex_unlock(&smu->mutex);
@@ -2538,8 +2565,11 @@ static int smu_set_fan_control_mode(struct smu_context *smu, int value)
/* reset user dpm fan speed */
if (!ret && value != AMD_FAN_CTRL_MANUAL &&
- !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE))
- smu->user_dpm_profile.fan_speed_percent = 0;
+ !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) {
+ smu->user_dpm_profile.fan_speed_pwm = 0;
+ smu->user_dpm_profile.fan_speed_rpm = 0;
+ smu->user_dpm_profile.flags &= ~(SMU_CUSTOM_FAN_SPEED_RPM | SMU_CUSTOM_FAN_SPEED_PWM);
+ }
return ret;
}
@@ -2552,31 +2582,25 @@ static void smu_pp_set_fan_control_mode(void *handle, u32 value)
}
-static int smu_get_fan_speed_percent(void *handle, u32 *speed)
+static int smu_get_fan_speed_pwm(void *handle, u32 *speed)
{
struct smu_context *smu = handle;
int ret = 0;
- uint32_t percent;
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
return -EOPNOTSUPP;
mutex_lock(&smu->mutex);
- if (smu->ppt_funcs->get_fan_speed_percent) {
- ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
- if (!ret) {
- *speed = percent > 100 ? 100 : percent;
- }
- }
+ if (smu->ppt_funcs->get_fan_speed_pwm)
+ ret = smu->ppt_funcs->get_fan_speed_pwm(smu, speed);
mutex_unlock(&smu->mutex);
-
return ret;
}
-static int smu_set_fan_speed_percent(void *handle, u32 speed)
+static int smu_set_fan_speed_pwm(void *handle, u32 speed)
{
struct smu_context *smu = handle;
int ret = 0;
@@ -2586,12 +2610,16 @@ static int smu_set_fan_speed_percent(void *handle, u32 speed)
mutex_lock(&smu->mutex);
- if (smu->ppt_funcs->set_fan_speed_percent) {
- if (speed > 100)
- speed = 100;
- ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed);
- if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE))
- smu->user_dpm_profile.fan_speed_percent = speed;
+ if (smu->ppt_funcs->set_fan_speed_pwm) {
+ ret = smu->ppt_funcs->set_fan_speed_pwm(smu, speed);
+ if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) {
+ smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_PWM;
+ smu->user_dpm_profile.fan_speed_pwm = speed;
+
+ /* Override custom RPM setting as they cannot co-exist */
+ smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_RPM;
+ smu->user_dpm_profile.fan_speed_rpm = 0;
+ }
}
mutex_unlock(&smu->mutex);
@@ -2603,17 +2631,14 @@ static int smu_get_fan_speed_rpm(void *handle, uint32_t *speed)
{
struct smu_context *smu = handle;
int ret = 0;
- u32 percent;
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
return -EOPNOTSUPP;
mutex_lock(&smu->mutex);
- if (smu->ppt_funcs->get_fan_speed_percent) {
- ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
- *speed = percent * smu->fan_max_rpm / 100;
- }
+ if (smu->ppt_funcs->get_fan_speed_rpm)
+ ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed);
mutex_unlock(&smu->mutex);
@@ -3030,8 +3055,8 @@ static const struct amd_pm_funcs swsmu_pm_funcs = {
/* export for sysfs */
.set_fan_control_mode = smu_pp_set_fan_control_mode,
.get_fan_control_mode = smu_get_fan_control_mode,
- .set_fan_speed_percent = smu_set_fan_speed_percent,
- .get_fan_speed_percent = smu_get_fan_speed_percent,
+ .set_fan_speed_pwm = smu_set_fan_speed_pwm,
+ .get_fan_speed_pwm = smu_get_fan_speed_pwm,
.force_clock_level = smu_force_ppclk_levels,
.print_clock_levels = smu_print_ppclk_levels,
.force_performance_level = smu_force_performance_level,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile
index 0138c982dfd3..f9b2e16f6431 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile
@@ -27,6 +27,7 @@ SMU11_MGR = arcturus_ppt.o \
navi10_ppt.o \
sienna_cichlid_ppt.o \
vangogh_ppt.o \
+ cyan_skillfish_ppt.o \
smu_v11_0.o
AMD_SWSMU_SMU11MGR = $(addprefix $(AMD_SWSMU_PATH)/smu11/,$(SMU11_MGR))
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 094df6f87cfc..273df66cac14 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -81,6 +81,24 @@
#define smnPCIE_ESM_CTRL 0x111003D0
+#define mmCG_FDO_CTRL0_ARCT 0x8B
+#define mmCG_FDO_CTRL0_ARCT_BASE_IDX 0
+
+#define mmCG_FDO_CTRL1_ARCT 0x8C
+#define mmCG_FDO_CTRL1_ARCT_BASE_IDX 0
+
+#define mmCG_FDO_CTRL2_ARCT 0x8D
+#define mmCG_FDO_CTRL2_ARCT_BASE_IDX 0
+
+#define mmCG_TACH_CTRL_ARCT 0x8E
+#define mmCG_TACH_CTRL_ARCT_BASE_IDX 0
+
+#define mmCG_TACH_STATUS_ARCT 0x8F
+#define mmCG_TACH_STATUS_ARCT_BASE_IDX 0
+
+#define mmCG_THERMAL_STATUS_ARCT 0x90
+#define mmCG_THERMAL_STATUS_ARCT_BASE_IDX 0
+
static const struct cmn2asic_msg_mapping arcturus_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0),
MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
@@ -163,14 +181,14 @@ static const struct cmn2asic_mapping arcturus_feature_mask_map[SMU_FEATURE_COUNT
FEA_MAP(DPM_SOCCLK),
FEA_MAP(DPM_FCLK),
FEA_MAP(DPM_MP0CLK),
- ARCTURUS_FEA_MAP(SMU_FEATURE_XGMI_BIT, FEATURE_DPM_XGMI_BIT),
+ FEA_MAP(DPM_XGMI),
FEA_MAP(DS_GFXCLK),
FEA_MAP(DS_SOCCLK),
FEA_MAP(DS_LCLK),
FEA_MAP(DS_FCLK),
FEA_MAP(DS_UCLK),
FEA_MAP(GFX_ULV),
- ARCTURUS_FEA_MAP(SMU_FEATURE_VCN_PG_BIT, FEATURE_DPM_VCN_BIT),
+ ARCTURUS_FEA_MAP(SMU_FEATURE_VCN_DPM_BIT, FEATURE_DPM_VCN_BIT),
FEA_MAP(RSMU_SMN_CG),
FEA_MAP(WAFL_CG),
FEA_MAP(PPT),
@@ -721,13 +739,13 @@ static int arcturus_get_current_clk_freq_by_table(struct smu_context *smu,
member_type = METRICS_AVERAGE_SOCCLK;
break;
case PPCLK_VCLK:
- if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT))
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_DPM_BIT))
member_type = METRICS_CURR_VCLK;
else
member_type = METRICS_AVERAGE_VCLK;
break;
case PPCLK_DCLK:
- if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT))
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_DPM_BIT))
member_type = METRICS_CURR_DCLK;
else
member_type = METRICS_AVERAGE_DCLK;
@@ -756,7 +774,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
uint32_t gen_speed, lane_width;
if (amdgpu_ras_intr_triggered())
- return snprintf(buf, PAGE_SIZE, "unavailable\n");
+ return sysfs_emit(buf, "unavailable\n");
dpm_context = smu_dpm->dpm_context;
@@ -780,7 +798,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
* And it's safe to assume that is always the current clock.
*/
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n", i,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i,
clocks.data[i].clocks_in_khz / 1000,
(clocks.num_levels == 1) ? "*" :
(arcturus_freqs_in_same_level(
@@ -803,7 +821,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.num_levels == 1) ? "*" :
(arcturus_freqs_in_same_level(
@@ -826,7 +844,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.num_levels == 1) ? "*" :
(arcturus_freqs_in_same_level(
@@ -849,7 +867,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < single_dpm_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, single_dpm_table->dpm_levels[i].value,
(clocks.num_levels == 1) ? "*" :
(arcturus_freqs_in_same_level(
@@ -872,7 +890,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < single_dpm_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, single_dpm_table->dpm_levels[i].value,
(clocks.num_levels == 1) ? "*" :
(arcturus_freqs_in_same_level(
@@ -895,7 +913,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < single_dpm_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, single_dpm_table->dpm_levels[i].value,
(clocks.num_levels == 1) ? "*" :
(arcturus_freqs_in_same_level(
@@ -906,7 +924,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
case SMU_PCIE:
gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu);
lane_width = smu_v11_0_get_current_pcie_link_width_level(smu);
- size += sprintf(buf + size, "0: %s %s %dMhz *\n",
+ size += sysfs_emit_at(buf, size, "0: %s %s %dMhz *\n",
(gen_speed == 0) ? "2.5GT/s," :
(gen_speed == 1) ? "5.0GT/s," :
(gen_speed == 2) ? "8.0GT/s," :
@@ -1162,11 +1180,29 @@ static int arcturus_read_sensor(struct smu_context *smu,
return ret;
}
-static int arcturus_get_fan_speed_percent(struct smu_context *smu,
- uint32_t *speed)
+static int arcturus_set_fan_static_mode(struct smu_context *smu,
+ uint32_t mode)
{
- int ret;
- u32 rpm;
+ struct amdgpu_device *adev = smu->adev;
+
+ WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2_ARCT,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2_ARCT),
+ CG_FDO_CTRL2, TMIN, 0));
+ WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2_ARCT,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2_ARCT),
+ CG_FDO_CTRL2, FDO_PWM_MODE, mode));
+
+ return 0;
+}
+
+static int arcturus_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t crystal_clock_freq = 2500;
+ uint32_t tach_status;
+ uint64_t tmp64;
+ int ret = 0;
if (!speed)
return -EINVAL;
@@ -1175,14 +1211,112 @@ static int arcturus_get_fan_speed_percent(struct smu_context *smu,
case AMD_FAN_CTRL_AUTO:
ret = arcturus_get_smu_metrics_data(smu,
METRICS_CURR_FANSPEED,
- &rpm);
- if (!ret && smu->fan_max_rpm)
- *speed = rpm * 100 / smu->fan_max_rpm;
- return ret;
+ speed);
+ break;
default:
- *speed = smu->user_dpm_profile.fan_speed_percent;
+ /*
+ * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
+ * detected via register retrieving. To workaround this, we will
+ * report the fan speed as 0 RPM if user just requested such.
+ */
+ if ((smu->user_dpm_profile.flags & SMU_CUSTOM_FAN_SPEED_RPM)
+ && !smu->user_dpm_profile.fan_speed_rpm) {
+ *speed = 0;
+ return 0;
+ }
+
+ tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
+ tach_status = RREG32_SOC15(THM, 0, mmCG_TACH_STATUS_ARCT);
+ if (tach_status) {
+ do_div(tmp64, tach_status);
+ *speed = (uint32_t)tmp64;
+ } else {
+ *speed = 0;
+ }
+
+ break;
+ }
+
+ return ret;
+}
+
+static int arcturus_set_fan_speed_pwm(struct smu_context *smu,
+ uint32_t speed)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t duty100, duty;
+ uint64_t tmp64;
+
+ speed = MIN(speed, 255);
+
+ duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1_ARCT),
+ CG_FDO_CTRL1, FMAX_DUTY100);
+ if (!duty100)
+ return -EINVAL;
+
+ tmp64 = (uint64_t)speed * duty100;
+ do_div(tmp64, 255);
+ duty = (uint32_t)tmp64;
+
+ WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0_ARCT,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0_ARCT),
+ CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
+
+ return arcturus_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC);
+}
+
+static int arcturus_set_fan_speed_rpm(struct smu_context *smu,
+ uint32_t speed)
+{
+ struct amdgpu_device *adev = smu->adev;
+ /*
+ * crystal_clock_freq used for fan speed rpm calculation is
+ * always 25Mhz. So, hardcode it as 2500(in 10K unit).
+ */
+ uint32_t crystal_clock_freq = 2500;
+ uint32_t tach_period;
+
+ tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
+ WREG32_SOC15(THM, 0, mmCG_TACH_CTRL_ARCT,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL_ARCT),
+ CG_TACH_CTRL, TARGET_PERIOD,
+ tach_period));
+
+ return arcturus_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
+}
+
+static int arcturus_get_fan_speed_pwm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t duty100, duty;
+ uint64_t tmp64;
+
+ /*
+ * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
+ * detected via register retrieving. To workaround this, we will
+ * report the fan speed as 0 PWM if user just requested such.
+ */
+ if ((smu->user_dpm_profile.flags & SMU_CUSTOM_FAN_SPEED_PWM)
+ && !smu->user_dpm_profile.fan_speed_pwm) {
+ *speed = 0;
return 0;
}
+
+ duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1_ARCT),
+ CG_FDO_CTRL1, FMAX_DUTY100);
+ duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS_ARCT),
+ CG_THERMAL_STATUS, FDO_PWM_DUTY);
+
+ if (duty100) {
+ tmp64 = (uint64_t)duty * 255;
+ do_div(tmp64, duty100);
+ *speed = MIN((uint32_t)tmp64, 255);
+ } else {
+ *speed = 0;
+ }
+
+ return 0;
}
static int arcturus_get_fan_parameters(struct smu_context *smu)
@@ -1272,11 +1406,11 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
return result;
if (smu_version >= 0x360d00)
- size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
+ size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
title[0], title[1], title[2], title[3], title[4], title[5],
title[6], title[7], title[8], title[9], title[10]);
else
- size += sprintf(buf + size, "%16s\n",
+ size += sysfs_emit_at(buf, size, "%16s\n",
title[0]);
for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
@@ -1302,11 +1436,11 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
}
}
- size += sprintf(buf + size, "%2d %14s%s\n",
+ size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
if (smu_version >= 0x360d00) {
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
0,
"GFXCLK",
@@ -1320,7 +1454,7 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
activity_monitor.Gfx_PD_Data_error_coeff,
activity_monitor.Gfx_PD_Data_error_rate_coeff);
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
1,
"UCLK",
@@ -1916,16 +2050,16 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
int ret = 0;
if (enable) {
- if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
- ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 1);
+ if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_DPM_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_DPM_BIT, 1);
if (ret) {
dev_err(smu->adev->dev, "[EnableVCNDPM] failed!\n");
return ret;
}
}
} else {
- if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
- ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 0);
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_DPM_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_DPM_BIT, 0);
if (ret) {
dev_err(smu->adev->dev, "[DisableVCNDPM] failed!\n");
return ret;
@@ -1936,197 +2070,77 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
return ret;
}
-static void arcturus_fill_i2c_req(SwI2cRequest_t *req, bool write,
- uint8_t address, uint32_t numbytes,
- uint8_t *data)
-{
- int i;
-
- req->I2CcontrollerPort = 0;
- req->I2CSpeed = 2;
- req->SlaveAddress = address;
- req->NumCmds = numbytes;
-
- for (i = 0; i < numbytes; i++) {
- SwI2cCmd_t *cmd = &req->SwI2cCmds[i];
-
- /* First 2 bytes are always write for lower 2b EEPROM address */
- if (i < 2)
- cmd->Cmd = 1;
- else
- cmd->Cmd = write;
-
-
- /* Add RESTART for read after address filled */
- cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
-
- /* Add STOP in the end */
- cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
-
- /* Fill with data regardless if read or write to simplify code */
- cmd->RegisterAddr = data[i];
- }
-}
-
-static int arcturus_i2c_read_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
+static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msg, int num_msgs)
{
- uint32_t i, ret = 0;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
+ struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
struct smu_table_context *smu_table = &adev->smu.smu_table;
struct smu_table *table = &smu_table->driver_table;
+ SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+ int i, j, r, c;
+ u16 dir;
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
- }
-
- memset(&req, 0, sizeof(req));
- arcturus_fill_i2c_req(&req, false, address, numbytes, data);
-
- mutex_lock(&adev->smu.mutex);
- /* Now read data starting with that address */
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
- true);
- mutex_unlock(&adev->smu.mutex);
-
- if (!ret) {
- SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
- /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */
- for (i = 0; i < numbytes; i++)
- data[i] = res->SwI2cCmds[i].Data;
-
- dev_dbg(adev->dev, "arcturus_i2c_read_data, address = %x, bytes = %d, data :",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- } else
- dev_err(adev->dev, "arcturus_i2c_read_data - error occurred :%x", ret);
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
- return ret;
-}
+ req->I2CcontrollerPort = 0;
+ req->I2CSpeed = I2C_SPEED_FAST_400K;
+ req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+ dir = msg[0].flags & I2C_M_RD;
+
+ for (c = i = 0; i < num_msgs; i++) {
+ for (j = 0; j < msg[i].len; j++, c++) {
+ SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+ if (!(msg[i].flags & I2C_M_RD)) {
+ /* write */
+ cmd->Cmd = I2C_CMD_WRITE;
+ cmd->RegisterAddr = msg[i].buf[j];
+ }
-static int arcturus_i2c_write_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
-{
- uint32_t ret;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
+ if ((dir ^ msg[i].flags) & I2C_M_RD) {
+ /* The direction changes.
+ */
+ dir = msg[i].flags & I2C_M_RD;
+ cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+ }
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
+ req->NumCmds++;
+
+ /*
+ * Insert STOP if we are at the last byte of either last
+ * message for the transaction or the client explicitly
+ * requires a STOP at this particular message.
+ */
+ if ((j == msg[i].len - 1) &&
+ ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
+ cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+ cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+ }
+ }
}
-
- memset(&req, 0, sizeof(req));
- arcturus_fill_i2c_req(&req, true, address, numbytes, data);
-
mutex_lock(&adev->smu.mutex);
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
+ r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
mutex_unlock(&adev->smu.mutex);
+ if (r)
+ goto fail;
- if (!ret) {
- dev_dbg(adev->dev, "arcturus_i2c_write(), address = %x, bytes = %d , data: ",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- /*
- * According to EEPROM spec there is a MAX of 10 ms required for
- * EEPROM to flush internal RX buffer after STOP was issued at the
- * end of write transaction. During this time the EEPROM will not be
- * responsive to any more commands - so wait a bit more.
- */
- msleep(10);
-
- } else
- dev_err(adev->dev, "arcturus_i2c_write- error occurred :%x", ret);
-
- return ret;
-}
-
-static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs, int num)
-{
- uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
- uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
-
- for (i = 0; i < num; i++) {
- /*
- * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
- * once and hence the data needs to be spliced into chunks and sent each
- * chunk separately
- */
- data_size = msgs[i].len - 2;
- data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
- next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
- data_ptr = msgs[i].buf + 2;
-
- for (j = 0; j < data_size / data_chunk_size; j++) {
- /* Insert the EEPROM dest addess, bits 0-15 */
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = arcturus_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
-
- memcpy(data_ptr, data_chunk + 2, data_chunk_size);
- } else {
-
- memcpy(data_chunk + 2, data_ptr, data_chunk_size);
-
- ret = arcturus_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
-
- next_eeprom_addr += data_chunk_size;
- data_ptr += data_chunk_size;
+ for (c = i = 0; i < num_msgs; i++) {
+ if (!(msg[i].flags & I2C_M_RD)) {
+ c += msg[i].len;
+ continue;
}
+ for (j = 0; j < msg[i].len; j++, c++) {
+ SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
- if (data_size % data_chunk_size) {
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = arcturus_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
-
- memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
- } else {
- memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
-
- ret = arcturus_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
+ msg[i].buf[j] = cmd->Data;
}
}
-
+ r = num_msgs;
fail:
- return num;
+ kfree(req);
+ return r;
}
static u32 arcturus_i2c_func(struct i2c_adapter *adap)
@@ -2140,15 +2154,25 @@ static const struct i2c_algorithm arcturus_i2c_algo = {
.functionality = arcturus_i2c_func,
};
+
+static const struct i2c_adapter_quirks arcturus_i2c_control_quirks = {
+ .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+ .max_read_len = MAX_SW_I2C_COMMANDS,
+ .max_write_len = MAX_SW_I2C_COMMANDS,
+ .max_comb_1st_msg_len = 2,
+ .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
+};
+
static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
int res;
control->owner = THIS_MODULE;
- control->class = I2C_CLASS_SPD;
+ control->class = I2C_CLASS_HWMON;
control->dev.parent = &adev->pdev->dev;
control->algo = &arcturus_i2c_algo;
+ control->quirks = &arcturus_i2c_control_quirks;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
res = i2c_add_adapter(control);
@@ -2288,7 +2312,9 @@ static void arcturus_log_thermal_throttling_event(struct smu_context *smu)
dev_warn(adev->dev, "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n",
log_buf);
- kgd2kfd_smi_event_throttle(smu->adev->kfd.dev, throttler_status);
+ kgd2kfd_smi_event_throttle(smu->adev->kfd.dev,
+ smu_cmn_get_indep_throttler_status(throttler_status,
+ arcturus_throttler_map));
}
static uint16_t arcturus_get_current_pcie_link_speed(struct smu_context *smu)
@@ -2378,7 +2404,8 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
.print_clk_levels = arcturus_print_clk_levels,
.force_clk_levels = arcturus_force_clk_levels,
.read_sensor = arcturus_read_sensor,
- .get_fan_speed_percent = arcturus_get_fan_speed_percent,
+ .get_fan_speed_pwm = arcturus_get_fan_speed_pwm,
+ .get_fan_speed_rpm = arcturus_get_fan_speed_rpm,
.get_power_profile_mode = arcturus_get_power_profile_mode,
.set_power_profile_mode = arcturus_set_power_profile_mode,
.set_performance_level = arcturus_set_performance_level,
@@ -2423,7 +2450,8 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
.display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
.get_fan_control_mode = smu_v11_0_get_fan_control_mode,
.set_fan_control_mode = smu_v11_0_set_fan_control_mode,
- .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
+ .set_fan_speed_pwm = arcturus_set_fan_speed_pwm,
+ .set_fan_speed_rpm = arcturus_set_fan_speed_rpm,
.set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
.gfx_off_control = smu_v11_0_gfx_off_control,
.register_irq_handler = smu_v11_0_register_irq_handler,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c
new file mode 100644
index 000000000000..b05f9541accc
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define SWSMU_CODE_LAYER_L2
+
+#include "amdgpu.h"
+#include "amdgpu_smu.h"
+#include "smu_v11_0.h"
+#include "smu11_driver_if_cyan_skillfish.h"
+#include "cyan_skillfish_ppt.h"
+#include "smu_v11_8_ppsmc.h"
+#include "smu_v11_8_pmfw.h"
+#include "smu_cmn.h"
+#include "soc15_common.h"
+
+/*
+ * DO NOT use these for err/warn/info/debug messages.
+ * Use dev_err, dev_warn, dev_info and dev_dbg instead.
+ * They are more MGPU friendly.
+ */
+
+#undef pr_err
+#undef pr_warn
+#undef pr_info
+#undef pr_debug
+
+static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = {
+ MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0),
+ MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0),
+ MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 0),
+ MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverTableDramAddrHigh, 0),
+ MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverTableDramAddrLow, 0),
+ MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0),
+ MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
+};
+
+static const struct pptable_funcs cyan_skillfish_ppt_funcs = {
+
+ .check_fw_status = smu_v11_0_check_fw_status,
+ .check_fw_version = smu_v11_0_check_fw_version,
+ .init_power = smu_v11_0_init_power,
+ .fini_power = smu_v11_0_fini_power,
+ .register_irq_handler = smu_v11_0_register_irq_handler,
+ .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
+ .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
+ .send_smc_msg = smu_cmn_send_smc_msg,
+ .set_driver_table_location = smu_v11_0_set_driver_table_location,
+ .interrupt_work = smu_v11_0_interrupt_work,
+};
+
+void cyan_skillfish_set_ppt_funcs(struct smu_context *smu)
+{
+ smu->ppt_funcs = &cyan_skillfish_ppt_funcs;
+ smu->message_map = cyan_skillfish_message_map;
+ smu->is_apu = true;
+}
diff --git a/include/drm/drm_irq.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.h
index 631b22f9757d..76cd7229e383 100644
--- a/include/drm/drm_irq.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Intel Corp.
+ * Copyright 2021 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -8,25 +8,22 @@
* 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 (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
+ * 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
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
+ *
*/
-#ifndef _DRM_IRQ_H_
-#define _DRM_IRQ_H_
+#ifndef __CYAN_SKILLFISH_PPT_H__
+#define __CYAN_SKILLFISH_PPT_H__
-struct drm_device;
+extern void cyan_skillfish_set_ppt_funcs(struct smu_context *smu);
-int drm_irq_install(struct drm_device *dev, int irq);
-int drm_irq_uninstall(struct drm_device *dev);
-int devm_drm_irq_install(struct drm_device *dev, int irq);
#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 1ba42b69ce74..f96681700c41 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -1303,7 +1303,7 @@ static int navi10_print_clk_levels(struct smu_context *smu,
if (ret)
return size;
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
cur_value == value ? "*" : "");
}
} else {
@@ -1321,7 +1321,7 @@ static int navi10_print_clk_levels(struct smu_context *smu,
freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
for (i = 0; i < 3; i++) {
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, freq_values[i],
i == mark_index ? "*" : "");
}
@@ -1331,7 +1331,7 @@ static int navi10_print_clk_levels(struct smu_context *smu,
gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu);
lane_width = smu_v11_0_get_current_pcie_link_width_level(smu);
for (i = 0; i < NUM_LINK_LEVELS; i++)
- size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
+ size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
(dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," :
(dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," :
(dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," :
@@ -1352,23 +1352,24 @@ static int navi10_print_clk_levels(struct smu_context *smu,
break;
if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS))
break;
- size += sprintf(buf + size, "OD_SCLK:\n");
- size += sprintf(buf + size, "0: %uMhz\n1: %uMhz\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
+ size += sysfs_emit_at(buf, size, "OD_SCLK:\n");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ od_table->GfxclkFmin, od_table->GfxclkFmax);
break;
case SMU_OD_MCLK:
if (!smu->od_enabled || !od_table || !od_settings)
break;
if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX))
break;
- size += sprintf(buf + size, "OD_MCLK:\n");
- size += sprintf(buf + size, "1: %uMHz\n", od_table->UclkFmax);
+ size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
+ size += sysfs_emit_at(buf, size, "1: %uMHz\n", od_table->UclkFmax);
break;
case SMU_OD_VDDC_CURVE:
if (!smu->od_enabled || !od_table || !od_settings)
break;
if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE))
break;
- size += sprintf(buf + size, "OD_VDDC_CURVE:\n");
+ size += sysfs_emit_at(buf, size, "OD_VDDC_CURVE:\n");
for (i = 0; i < 3; i++) {
switch (i) {
case 0:
@@ -1383,55 +1384,57 @@ static int navi10_print_clk_levels(struct smu_context *smu,
default:
break;
}
- size += sprintf(buf + size, "%d: %uMHz %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE);
+ size += sysfs_emit_at(buf, size, "%d: %uMHz %umV\n",
+ i, curve_settings[0],
+ curve_settings[1] / NAVI10_VOLTAGE_SCALE);
}
break;
case SMU_OD_RANGE:
if (!smu->od_enabled || !od_table || !od_settings)
break;
- size = sprintf(buf, "%s:\n", "OD_RANGE");
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN,
&min_value, NULL);
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMAX,
NULL, &max_value);
- size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
min_value, max_value);
}
if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) {
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX,
&min_value, &max_value);
- size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
min_value, max_value);
}
if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) {
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1,
&min_value, &max_value);
- size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
- min_value, max_value);
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
+ min_value, max_value);
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1,
&min_value, &max_value);
- size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
- min_value, max_value);
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
+ min_value, max_value);
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2,
&min_value, &max_value);
- size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
- min_value, max_value);
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
+ min_value, max_value);
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2,
&min_value, &max_value);
- size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
- min_value, max_value);
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
+ min_value, max_value);
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3,
&min_value, &max_value);
- size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
- min_value, max_value);
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
+ min_value, max_value);
navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3,
&min_value, &max_value);
- size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
- min_value, max_value);
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
+ min_value, max_value);
}
break;
@@ -1668,27 +1671,27 @@ static bool navi10_is_dpm_running(struct smu_context *smu)
return !!(feature_enabled & SMC_DPM_FEATURE);
}
-static int navi10_get_fan_speed_percent(struct smu_context *smu,
- uint32_t *speed)
+static int navi10_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed)
{
- int ret;
- u32 rpm;
+ int ret = 0;
if (!speed)
return -EINVAL;
switch (smu_v11_0_get_fan_control_mode(smu)) {
case AMD_FAN_CTRL_AUTO:
- ret = navi1x_get_smu_metrics_data(smu,
+ ret = navi10_get_smu_metrics_data(smu,
METRICS_CURR_FANSPEED,
- &rpm);
- if (!ret && smu->fan_max_rpm)
- *speed = rpm * 100 / smu->fan_max_rpm;
- return ret;
+ speed);
+ break;
default:
- *speed = smu->user_dpm_profile.fan_speed_percent;
- return 0;
+ ret = smu_v11_0_get_fan_speed_rpm(smu,
+ speed);
+ break;
}
+
+ return ret;
}
static int navi10_get_fan_parameters(struct smu_context *smu)
@@ -1730,7 +1733,7 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
if (!buf)
return -EINVAL;
- size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
+ size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
title[0], title[1], title[2], title[3], title[4], title[5],
title[6], title[7], title[8], title[9], title[10]);
@@ -1750,10 +1753,10 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
return result;
}
- size += sprintf(buf + size, "%2d %14s%s:\n",
+ size += sysfs_emit_at(buf, size, "%2d %14s%s:\n",
i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
0,
"GFXCLK",
@@ -1767,7 +1770,7 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
activity_monitor.Gfx_PD_Data_error_coeff,
activity_monitor.Gfx_PD_Data_error_rate_coeff);
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
1,
"SOCCLK",
@@ -1781,7 +1784,7 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
activity_monitor.Soc_PD_Data_error_coeff,
activity_monitor.Soc_PD_Data_error_rate_coeff);
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
2,
"MEMLK",
@@ -2294,41 +2297,52 @@ static int navi10_set_default_od_settings(struct smu_context *smu)
(OverDriveTable_t *)smu->smu_table.overdrive_table;
OverDriveTable_t *boot_od_table =
(OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
+ OverDriveTable_t *user_od_table =
+ (OverDriveTable_t *)smu->smu_table.user_overdrive_table;
int ret = 0;
- ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, false);
+ /*
+ * For S3/S4/Runpm resume, no need to setup those overdrive tables again as
+ * - either they already have the default OD settings got during cold bootup
+ * - or they have some user customized OD settings which cannot be overwritten
+ */
+ if (smu->adev->in_suspend)
+ return 0;
+
+ ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)boot_od_table, false);
if (ret) {
dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
return ret;
}
- if (!od_table->GfxclkVolt1) {
+ if (!boot_od_table->GfxclkVolt1) {
ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
- &od_table->GfxclkVolt1,
- od_table->GfxclkFreq1);
+ &boot_od_table->GfxclkVolt1,
+ boot_od_table->GfxclkFreq1);
if (ret)
return ret;
}
- if (!od_table->GfxclkVolt2) {
+ if (!boot_od_table->GfxclkVolt2) {
ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
- &od_table->GfxclkVolt2,
- od_table->GfxclkFreq2);
+ &boot_od_table->GfxclkVolt2,
+ boot_od_table->GfxclkFreq2);
if (ret)
return ret;
}
- if (!od_table->GfxclkVolt3) {
+ if (!boot_od_table->GfxclkVolt3) {
ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
- &od_table->GfxclkVolt3,
- od_table->GfxclkFreq3);
+ &boot_od_table->GfxclkVolt3,
+ boot_od_table->GfxclkFreq3);
if (ret)
return ret;
}
- memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t));
+ navi10_dump_od_table(smu, boot_od_table);
- navi10_dump_od_table(smu, od_table);
+ memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t));
+ memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
return 0;
}
@@ -2429,11 +2443,20 @@ static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABL
memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t));
break;
case PP_OD_COMMIT_DPM_TABLE:
- navi10_dump_od_table(smu, od_table);
- ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
- if (ret) {
- dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
- return ret;
+ if (memcmp(od_table, table_context->user_overdrive_table, sizeof(OverDriveTable_t))) {
+ navi10_dump_od_table(smu, od_table);
+ ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
+ return ret;
+ }
+ memcpy(table_context->user_overdrive_table, od_table, sizeof(OverDriveTable_t));
+ smu->user_dpm_profile.user_od = true;
+
+ if (!memcmp(table_context->user_overdrive_table,
+ table_context->boot_overdrive_table,
+ sizeof(OverDriveTable_t)))
+ smu->user_dpm_profile.user_od = false;
}
break;
case PP_OD_EDIT_VDDC_CURVE:
@@ -2735,6 +2758,122 @@ static ssize_t navi10_get_legacy_gpu_metrics(struct smu_context *smu,
return sizeof(struct gpu_metrics_v1_3);
}
+static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msg, int num_msgs)
+{
+ struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
+ struct smu_table_context *smu_table = &adev->smu.smu_table;
+ struct smu_table *table = &smu_table->driver_table;
+ SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+ int i, j, r, c;
+ u16 dir;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->I2CcontrollerPort = 0;
+ req->I2CSpeed = I2C_SPEED_FAST_400K;
+ req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+ dir = msg[0].flags & I2C_M_RD;
+
+ for (c = i = 0; i < num_msgs; i++) {
+ for (j = 0; j < msg[i].len; j++, c++) {
+ SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+ if (!(msg[i].flags & I2C_M_RD)) {
+ /* write */
+ cmd->Cmd = I2C_CMD_WRITE;
+ cmd->RegisterAddr = msg[i].buf[j];
+ }
+
+ if ((dir ^ msg[i].flags) & I2C_M_RD) {
+ /* The direction changes.
+ */
+ dir = msg[i].flags & I2C_M_RD;
+ cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+ }
+
+ req->NumCmds++;
+
+ /*
+ * Insert STOP if we are at the last byte of either last
+ * message for the transaction or the client explicitly
+ * requires a STOP at this particular message.
+ */
+ if ((j == msg[i].len - 1) &&
+ ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
+ cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+ cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+ }
+ }
+ }
+ mutex_lock(&adev->smu.mutex);
+ r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
+ mutex_unlock(&adev->smu.mutex);
+ if (r)
+ goto fail;
+
+ for (c = i = 0; i < num_msgs; i++) {
+ if (!(msg[i].flags & I2C_M_RD)) {
+ c += msg[i].len;
+ continue;
+ }
+ for (j = 0; j < msg[i].len; j++, c++) {
+ SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
+
+ msg[i].buf[j] = cmd->Data;
+ }
+ }
+ r = num_msgs;
+fail:
+ kfree(req);
+ return r;
+}
+
+static u32 navi10_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+
+static const struct i2c_algorithm navi10_i2c_algo = {
+ .master_xfer = navi10_i2c_xfer,
+ .functionality = navi10_i2c_func,
+};
+
+static const struct i2c_adapter_quirks navi10_i2c_control_quirks = {
+ .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+ .max_read_len = MAX_SW_I2C_COMMANDS,
+ .max_write_len = MAX_SW_I2C_COMMANDS,
+ .max_comb_1st_msg_len = 2,
+ .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
+};
+
+static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
+{
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ int res;
+
+ control->owner = THIS_MODULE;
+ control->class = I2C_CLASS_HWMON;
+ control->dev.parent = &adev->pdev->dev;
+ control->algo = &navi10_i2c_algo;
+ snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+ control->quirks = &navi10_i2c_control_quirks;
+
+ res = i2c_add_adapter(control);
+ if (res)
+ DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+
+ return res;
+}
+
+static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
+{
+ i2c_del_adapter(control);
+}
+
static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
void **table)
{
@@ -3078,6 +3217,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.set_default_dpm_table = navi10_set_default_dpm_table,
.dpm_set_vcn_enable = navi10_dpm_set_vcn_enable,
.dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable,
+ .i2c_init = navi10_i2c_control_init,
+ .i2c_fini = navi10_i2c_control_fini,
.print_clk_levels = navi10_print_clk_levels,
.force_clk_levels = navi10_force_clk_levels,
.populate_umd_state_clk = navi10_populate_umd_state_clk,
@@ -3086,7 +3227,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.display_config_changed = navi10_display_config_changed,
.notify_smc_display_config = navi10_notify_smc_display_config,
.is_dpm_running = navi10_is_dpm_running,
- .get_fan_speed_percent = navi10_get_fan_speed_percent,
+ .get_fan_speed_pwm = smu_v11_0_get_fan_speed_pwm,
+ .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
.get_power_profile_mode = navi10_get_power_profile_mode,
.set_power_profile_mode = navi10_set_power_profile_mode,
.set_watermarks_table = navi10_set_watermarks_table,
@@ -3129,7 +3271,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
.get_fan_control_mode = smu_v11_0_get_fan_control_mode,
.set_fan_control_mode = smu_v11_0_set_fan_control_mode,
- .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
+ .set_fan_speed_pwm = smu_v11_0_set_fan_speed_pwm,
+ .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
.set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
.gfx_off_control = smu_v11_0_gfx_off_control,
.register_irq_handler = smu_v11_0_register_irq_handler,
@@ -3144,6 +3287,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
.set_default_od_settings = navi10_set_default_od_settings,
.od_edit_dpm_table = navi10_od_edit_dpm_table,
+ .restore_user_od_settings = smu_v11_0_restore_user_od_settings,
.run_btc = navi10_run_btc,
.set_power_source = smu_v11_0_set_power_source,
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index d92dd2c7448e..5e292c3f5050 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -488,6 +488,26 @@ err0_out:
return -ENOMEM;
}
+static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table= &smu->smu_table;
+ SmuMetricsExternal_t *metrics_ext =
+ (SmuMetricsExternal_t *)(smu_table->metrics_table);
+ uint32_t throttler_status = 0;
+ int i;
+
+ if ((smu->adev->asic_type == CHIP_SIENNA_CICHLID) &&
+ (smu->smc_fw_version >= 0x3A4300)) {
+ for (i = 0; i < THROTTLER_COUNT; i++)
+ throttler_status |=
+ (metrics_ext->SmuMetrics_V2.ThrottlingPercentage[i] ? 1U << i : 0);
+ } else {
+ throttler_status = metrics_ext->SmuMetrics.ThrottlerStatus;
+ }
+
+ return throttler_status;
+}
+
static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
@@ -495,6 +515,11 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
struct smu_table_context *smu_table= &smu->smu_table;
SmuMetrics_t *metrics =
&(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
+ SmuMetrics_V2_t *metrics_v2 =
+ &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics_V2);
+ bool use_metrics_v2 = ((smu->adev->asic_type == CHIP_SIENNA_CICHLID) &&
+ (smu->smc_fw_version >= 0x3A4300)) ? true : false;
+ uint16_t average_gfx_activity;
int ret = 0;
mutex_lock(&smu->metrics_lock);
@@ -509,78 +534,96 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
switch (member) {
case METRICS_CURR_GFXCLK:
- *value = metrics->CurrClock[PPCLK_GFXCLK];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_GFXCLK] :
+ metrics->CurrClock[PPCLK_GFXCLK];
break;
case METRICS_CURR_SOCCLK:
- *value = metrics->CurrClock[PPCLK_SOCCLK];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_SOCCLK] :
+ metrics->CurrClock[PPCLK_SOCCLK];
break;
case METRICS_CURR_UCLK:
- *value = metrics->CurrClock[PPCLK_UCLK];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_UCLK] :
+ metrics->CurrClock[PPCLK_UCLK];
break;
case METRICS_CURR_VCLK:
- *value = metrics->CurrClock[PPCLK_VCLK_0];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_VCLK_0] :
+ metrics->CurrClock[PPCLK_VCLK_0];
break;
case METRICS_CURR_VCLK1:
- *value = metrics->CurrClock[PPCLK_VCLK_1];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_VCLK_1] :
+ metrics->CurrClock[PPCLK_VCLK_1];
break;
case METRICS_CURR_DCLK:
- *value = metrics->CurrClock[PPCLK_DCLK_0];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_0] :
+ metrics->CurrClock[PPCLK_DCLK_0];
break;
case METRICS_CURR_DCLK1:
- *value = metrics->CurrClock[PPCLK_DCLK_1];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_1] :
+ metrics->CurrClock[PPCLK_DCLK_1];
break;
case METRICS_CURR_DCEFCLK:
- *value = metrics->CurrClock[PPCLK_DCEFCLK];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCEFCLK] :
+ metrics->CurrClock[PPCLK_DCEFCLK];
break;
case METRICS_CURR_FCLK:
- *value = metrics->CurrClock[PPCLK_FCLK];
+ *value = use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_FCLK] :
+ metrics->CurrClock[PPCLK_FCLK];
break;
case METRICS_AVERAGE_GFXCLK:
- if (metrics->AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
- *value = metrics->AverageGfxclkFrequencyPostDs;
+ average_gfx_activity = use_metrics_v2 ? metrics_v2->AverageGfxActivity :
+ metrics->AverageGfxActivity;
+ if (average_gfx_activity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
+ *value = use_metrics_v2 ? metrics_v2->AverageGfxclkFrequencyPostDs :
+ metrics->AverageGfxclkFrequencyPostDs;
else
- *value = metrics->AverageGfxclkFrequencyPreDs;
+ *value = use_metrics_v2 ? metrics_v2->AverageGfxclkFrequencyPreDs :
+ metrics->AverageGfxclkFrequencyPreDs;
break;
case METRICS_AVERAGE_FCLK:
- *value = metrics->AverageFclkFrequencyPostDs;
+ *value = use_metrics_v2 ? metrics_v2->AverageFclkFrequencyPostDs :
+ metrics->AverageFclkFrequencyPostDs;
break;
case METRICS_AVERAGE_UCLK:
- *value = metrics->AverageUclkFrequencyPostDs;
+ *value = use_metrics_v2 ? metrics_v2->AverageUclkFrequencyPostDs :
+ metrics->AverageUclkFrequencyPostDs;
break;
case METRICS_AVERAGE_GFXACTIVITY:
- *value = metrics->AverageGfxActivity;
+ *value = use_metrics_v2 ? metrics_v2->AverageGfxActivity :
+ metrics->AverageGfxActivity;
break;
case METRICS_AVERAGE_MEMACTIVITY:
- *value = metrics->AverageUclkActivity;
+ *value = use_metrics_v2 ? metrics_v2->AverageUclkActivity :
+ metrics->AverageUclkActivity;
break;
case METRICS_AVERAGE_SOCKETPOWER:
- *value = metrics->AverageSocketPower << 8;
+ *value = use_metrics_v2 ? metrics_v2->AverageSocketPower << 8 :
+ metrics->AverageSocketPower << 8;
break;
case METRICS_TEMPERATURE_EDGE:
- *value = metrics->TemperatureEdge *
+ *value = (use_metrics_v2 ? metrics_v2->TemperatureEdge : metrics->TemperatureEdge) *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_TEMPERATURE_HOTSPOT:
- *value = metrics->TemperatureHotspot *
+ *value = (use_metrics_v2 ? metrics_v2->TemperatureHotspot : metrics->TemperatureHotspot) *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_TEMPERATURE_MEM:
- *value = metrics->TemperatureMem *
+ *value = (use_metrics_v2 ? metrics_v2->TemperatureMem : metrics->TemperatureMem) *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_TEMPERATURE_VRGFX:
- *value = metrics->TemperatureVrGfx *
+ *value = (use_metrics_v2 ? metrics_v2->TemperatureVrGfx : metrics->TemperatureVrGfx) *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_TEMPERATURE_VRSOC:
- *value = metrics->TemperatureVrSoc *
+ *value = (use_metrics_v2 ? metrics_v2->TemperatureVrSoc : metrics->TemperatureVrSoc) *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_THROTTLER_STATUS:
- *value = metrics->ThrottlerStatus;
+ *value = sienna_cichlid_get_throttler_status_locked(smu);
break;
case METRICS_CURR_FANSPEED:
- *value = metrics->CurrFanSpeed;
+ *value = use_metrics_v2 ? metrics_v2->CurrFanSpeed : metrics->CurrFanSpeed;
break;
default:
*value = UINT_MAX;
@@ -1045,7 +1088,7 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,
if (ret)
goto print_clk_out;
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
cur_value == value ? "*" : "");
}
} else {
@@ -1067,7 +1110,7 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < count; i++) {
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, freq_values[i],
cur_value == freq_values[i] ? "*" : "");
}
@@ -1078,7 +1121,7 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,
lane_width = smu_v11_0_get_current_pcie_link_width_level(smu);
GET_PPTABLE_MEMBER(LclkFreq, &table_member);
for (i = 0; i < NUM_LINK_LEVELS; i++)
- size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
+ size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
(dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," :
(dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," :
(dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," :
@@ -1101,8 +1144,8 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,
if (!sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_GFXCLK_LIMITS))
break;
- size += sprintf(buf + size, "OD_SCLK:\n");
- size += sprintf(buf + size, "0: %uMhz\n1: %uMhz\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
+ size += sysfs_emit_at(buf, size, "OD_SCLK:\n");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
break;
case SMU_OD_MCLK:
@@ -1112,8 +1155,8 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,
if (!sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_UCLK_LIMITS))
break;
- size += sprintf(buf + size, "OD_MCLK:\n");
- size += sprintf(buf + size, "0: %uMhz\n1: %uMHz\n", od_table->UclkFmin, od_table->UclkFmax);
+ size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMHz\n", od_table->UclkFmin, od_table->UclkFmax);
break;
case SMU_OD_VDDGFX_OFFSET:
@@ -1129,22 +1172,22 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,
(smu_version < 0x003a2900))
break;
- size += sprintf(buf + size, "OD_VDDGFX_OFFSET:\n");
- size += sprintf(buf + size, "%dmV\n", od_table->VddGfxOffset);
+ size += sysfs_emit_at(buf, size, "OD_VDDGFX_OFFSET:\n");
+ size += sysfs_emit_at(buf, size, "%dmV\n", od_table->VddGfxOffset);
break;
case SMU_OD_RANGE:
if (!smu->od_enabled || !od_table || !od_settings)
break;
- size = sprintf(buf, "%s:\n", "OD_RANGE");
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
if (sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_GFXCLK_LIMITS)) {
sienna_cichlid_get_od_setting_range(od_settings, SMU_11_0_7_ODSETTING_GFXCLKFMIN,
&min_value, NULL);
sienna_cichlid_get_od_setting_range(od_settings, SMU_11_0_7_ODSETTING_GFXCLKFMAX,
NULL, &max_value);
- size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
min_value, max_value);
}
@@ -1153,7 +1196,7 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,
&min_value, NULL);
sienna_cichlid_get_od_setting_range(od_settings, SMU_11_0_7_ODSETTING_UCLKFMAX,
NULL, &max_value);
- size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
min_value, max_value);
}
break;
@@ -1311,27 +1354,20 @@ static bool sienna_cichlid_is_dpm_running(struct smu_context *smu)
return !!(feature_enabled & SMC_DPM_FEATURE);
}
-static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu,
- uint32_t *speed)
+static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed)
{
- int ret;
- u32 rpm;
-
if (!speed)
return -EINVAL;
- switch (smu_v11_0_get_fan_control_mode(smu)) {
- case AMD_FAN_CTRL_AUTO:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_CURR_FANSPEED,
- &rpm);
- if (!ret && smu->fan_max_rpm)
- *speed = rpm * 100 / smu->fan_max_rpm;
- return ret;
- default:
- *speed = smu->user_dpm_profile.fan_speed_percent;
- return 0;
- }
+ /*
+ * For Sienna_Cichlid and later, the fan speed(rpm) reported
+ * by pmfw is always trustable(even when the fan control feature
+ * disabled or 0 RPM kicked in).
+ */
+ return sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_CURR_FANSPEED,
+ speed);
}
static int sienna_cichlid_get_fan_parameters(struct smu_context *smu)
@@ -1376,7 +1412,7 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
if (!buf)
return -EINVAL;
- size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
+ size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
title[0], title[1], title[2], title[3], title[4], title[5],
title[6], title[7], title[8], title[9], title[10]);
@@ -1396,10 +1432,10 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
return result;
}
- size += sprintf(buf + size, "%2d %14s%s:\n",
+ size += sysfs_emit_at(buf, size, "%2d %14s%s:\n",
i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
0,
"GFXCLK",
@@ -1413,7 +1449,7 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
activity_monitor->Gfx_PD_Data_error_coeff,
activity_monitor->Gfx_PD_Data_error_rate_coeff);
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
1,
"SOCCLK",
@@ -1427,7 +1463,7 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
activity_monitor->Fclk_PD_Data_error_coeff,
activity_monitor->Fclk_PD_Data_error_rate_coeff);
- size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
2,
"MEMLK",
@@ -1910,18 +1946,29 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu)
(OverDriveTable_t *)smu->smu_table.overdrive_table;
OverDriveTable_t *boot_od_table =
(OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
+ OverDriveTable_t *user_od_table =
+ (OverDriveTable_t *)smu->smu_table.user_overdrive_table;
int ret = 0;
+ /*
+ * For S3/S4/Runpm resume, no need to setup those overdrive tables again as
+ * - either they already have the default OD settings got during cold bootup
+ * - or they have some user customized OD settings which cannot be overwritten
+ */
+ if (smu->adev->in_suspend)
+ return 0;
+
ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE,
- 0, (void *)od_table, false);
+ 0, (void *)boot_od_table, false);
if (ret) {
dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
return ret;
}
- memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t));
+ sienna_cichlid_dump_od_table(smu, boot_od_table);
- sienna_cichlid_dump_od_table(smu, od_table);
+ memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t));
+ memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
return 0;
}
@@ -2084,13 +2131,20 @@ static int sienna_cichlid_od_edit_dpm_table(struct smu_context *smu,
fallthrough;
case PP_OD_COMMIT_DPM_TABLE:
- sienna_cichlid_dump_od_table(smu, od_table);
+ if (memcmp(od_table, table_context->user_overdrive_table, sizeof(OverDriveTable_t))) {
+ sienna_cichlid_dump_od_table(smu, od_table);
+ ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
+ return ret;
+ }
+ memcpy(table_context->user_overdrive_table, od_table, sizeof(OverDriveTable_t));
+ smu->user_dpm_profile.user_od = true;
- ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE,
- 0, (void *)od_table, true);
- if (ret) {
- dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
- return ret;
+ if (!memcmp(table_context->user_overdrive_table,
+ table_context->boot_overdrive_table,
+ sizeof(OverDriveTable_t)))
+ smu->user_dpm_profile.user_od = false;
}
break;
@@ -3441,197 +3495,77 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", pptable->MmHubPadding[7]);
}
-static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t *req, bool write,
- uint8_t address, uint32_t numbytes,
- uint8_t *data)
-{
- int i;
-
- req->I2CcontrollerPort = 1;
- req->I2CSpeed = 2;
- req->SlaveAddress = address;
- req->NumCmds = numbytes;
-
- for (i = 0; i < numbytes; i++) {
- SwI2cCmd_t *cmd = &req->SwI2cCmds[i];
-
- /* First 2 bytes are always write for lower 2b EEPROM address */
- if (i < 2)
- cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
- else
- cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
-
-
- /* Add RESTART for read after address filled */
- cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
-
- /* Add STOP in the end */
- cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
-
- /* Fill with data regardless if read or write to simplify code */
- cmd->ReadWriteData = data[i];
- }
-}
-
-static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
+static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msg, int num_msgs)
{
- uint32_t i, ret = 0;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
+ struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
struct smu_table_context *smu_table = &adev->smu.smu_table;
struct smu_table *table = &smu_table->driver_table;
+ SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+ int i, j, r, c;
+ u16 dir;
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
- }
-
- memset(&req, 0, sizeof(req));
- sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data);
-
- mutex_lock(&adev->smu.mutex);
- /* Now read data starting with that address */
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
- true);
- mutex_unlock(&adev->smu.mutex);
-
- if (!ret) {
- SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
- /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */
- for (i = 0; i < numbytes; i++)
- data[i] = res->SwI2cCmds[i].ReadWriteData;
-
- dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, bytes = %d, data :",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- } else
- dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error occurred :%x", ret);
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
- return ret;
-}
+ req->I2CcontrollerPort = 1;
+ req->I2CSpeed = I2C_SPEED_FAST_400K;
+ req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+ dir = msg[0].flags & I2C_M_RD;
+
+ for (c = i = 0; i < num_msgs; i++) {
+ for (j = 0; j < msg[i].len; j++, c++) {
+ SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+ if (!(msg[i].flags & I2C_M_RD)) {
+ /* write */
+ cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
+ cmd->ReadWriteData = msg[i].buf[j];
+ }
-static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
-{
- uint32_t ret;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
+ if ((dir ^ msg[i].flags) & I2C_M_RD) {
+ /* The direction changes.
+ */
+ dir = msg[i].flags & I2C_M_RD;
+ cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+ }
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
+ req->NumCmds++;
+
+ /*
+ * Insert STOP if we are at the last byte of either last
+ * message for the transaction or the client explicitly
+ * requires a STOP at this particular message.
+ */
+ if ((j == msg[i].len - 1) &&
+ ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
+ cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+ cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+ }
+ }
}
-
- memset(&req, 0, sizeof(req));
- sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data);
-
mutex_lock(&adev->smu.mutex);
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
+ r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
mutex_unlock(&adev->smu.mutex);
+ if (r)
+ goto fail;
- if (!ret) {
- dev_dbg(adev->dev, "sienna_cichlid_i2c_write(), address = %x, bytes = %d , data: ",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- /*
- * According to EEPROM spec there is a MAX of 10 ms required for
- * EEPROM to flush internal RX buffer after STOP was issued at the
- * end of write transaction. During this time the EEPROM will not be
- * responsive to any more commands - so wait a bit more.
- */
- msleep(10);
-
- } else
- dev_err(adev->dev, "sienna_cichlid_i2c_write- error occurred :%x", ret);
-
- return ret;
-}
-
-static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs, int num)
-{
- uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
- uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
-
- for (i = 0; i < num; i++) {
- /*
- * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
- * once and hence the data needs to be spliced into chunks and sent each
- * chunk separately
- */
- data_size = msgs[i].len - 2;
- data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
- next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
- data_ptr = msgs[i].buf + 2;
-
- for (j = 0; j < data_size / data_chunk_size; j++) {
- /* Insert the EEPROM dest addess, bits 0-15 */
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = sienna_cichlid_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
-
- memcpy(data_ptr, data_chunk + 2, data_chunk_size);
- } else {
-
- memcpy(data_chunk + 2, data_ptr, data_chunk_size);
-
- ret = sienna_cichlid_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
-
- next_eeprom_addr += data_chunk_size;
- data_ptr += data_chunk_size;
+ for (c = i = 0; i < num_msgs; i++) {
+ if (!(msg[i].flags & I2C_M_RD)) {
+ c += msg[i].len;
+ continue;
}
+ for (j = 0; j < msg[i].len; j++, c++) {
+ SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
- if (data_size % data_chunk_size) {
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = sienna_cichlid_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
-
- memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
- } else {
- memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
-
- ret = sienna_cichlid_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
+ msg[i].buf[j] = cmd->ReadWriteData;
}
}
-
+ r = num_msgs;
fail:
- return num;
+ kfree(req);
+ return r;
}
static u32 sienna_cichlid_i2c_func(struct i2c_adapter *adap)
@@ -3645,16 +3579,25 @@ static const struct i2c_algorithm sienna_cichlid_i2c_algo = {
.functionality = sienna_cichlid_i2c_func,
};
+static const struct i2c_adapter_quirks sienna_cichlid_i2c_control_quirks = {
+ .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+ .max_read_len = MAX_SW_I2C_COMMANDS,
+ .max_write_len = MAX_SW_I2C_COMMANDS,
+ .max_comb_1st_msg_len = 2,
+ .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
+};
+
static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
int res;
control->owner = THIS_MODULE;
- control->class = I2C_CLASS_SPD;
+ control->class = I2C_CLASS_HWMON;
control->dev.parent = &adev->pdev->dev;
control->algo = &sienna_cichlid_i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+ control->quirks = &sienna_cichlid_i2c_control_quirks;
res = i2c_add_adapter(control);
if (res)
@@ -3677,65 +3620,94 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
SmuMetricsExternal_t metrics_external;
SmuMetrics_t *metrics =
&(metrics_external.SmuMetrics);
+ SmuMetrics_V2_t *metrics_v2 =
+ &(metrics_external.SmuMetrics_V2);
struct amdgpu_device *adev = smu->adev;
- uint32_t smu_version;
+ bool use_metrics_v2 = ((adev->asic_type == CHIP_SIENNA_CICHLID) &&
+ (smu->smc_fw_version >= 0x3A4300)) ? true : false;
+ uint16_t average_gfx_activity;
int ret = 0;
- ret = smu_cmn_get_metrics_table(smu,
- &metrics_external,
- true);
- if (ret)
+ mutex_lock(&smu->metrics_lock);
+ ret = smu_cmn_get_metrics_table_locked(smu,
+ &metrics_external,
+ true);
+ if (ret) {
+ mutex_unlock(&smu->metrics_lock);
return ret;
+ }
smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
- gpu_metrics->temperature_edge = metrics->TemperatureEdge;
- gpu_metrics->temperature_hotspot = metrics->TemperatureHotspot;
- gpu_metrics->temperature_mem = metrics->TemperatureMem;
- gpu_metrics->temperature_vrgfx = metrics->TemperatureVrGfx;
- gpu_metrics->temperature_vrsoc = metrics->TemperatureVrSoc;
- gpu_metrics->temperature_vrmem = metrics->TemperatureVrMem0;
-
- gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
- gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
- gpu_metrics->average_mm_activity = metrics->VcnActivityPercentage;
-
- gpu_metrics->average_socket_power = metrics->AverageSocketPower;
- gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
-
- if (metrics->AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
- gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
+ gpu_metrics->temperature_edge =
+ use_metrics_v2 ? metrics_v2->TemperatureEdge : metrics->TemperatureEdge;
+ gpu_metrics->temperature_hotspot =
+ use_metrics_v2 ? metrics_v2->TemperatureHotspot : metrics->TemperatureHotspot;
+ gpu_metrics->temperature_mem =
+ use_metrics_v2 ? metrics_v2->TemperatureMem : metrics->TemperatureMem;
+ gpu_metrics->temperature_vrgfx =
+ use_metrics_v2 ? metrics_v2->TemperatureVrGfx : metrics->TemperatureVrGfx;
+ gpu_metrics->temperature_vrsoc =
+ use_metrics_v2 ? metrics_v2->TemperatureVrSoc : metrics->TemperatureVrSoc;
+ gpu_metrics->temperature_vrmem =
+ use_metrics_v2 ? metrics_v2->TemperatureVrMem0 : metrics->TemperatureVrMem0;
+
+ gpu_metrics->average_gfx_activity =
+ use_metrics_v2 ? metrics_v2->AverageGfxActivity : metrics->AverageGfxActivity;
+ gpu_metrics->average_umc_activity =
+ use_metrics_v2 ? metrics_v2->AverageUclkActivity : metrics->AverageUclkActivity;
+ gpu_metrics->average_mm_activity =
+ use_metrics_v2 ? metrics_v2->VcnActivityPercentage : metrics->VcnActivityPercentage;
+
+ gpu_metrics->average_socket_power =
+ use_metrics_v2 ? metrics_v2->AverageSocketPower : metrics->AverageSocketPower;
+ gpu_metrics->energy_accumulator =
+ use_metrics_v2 ? metrics_v2->EnergyAccumulator : metrics->EnergyAccumulator;
+
+ average_gfx_activity = use_metrics_v2 ? metrics_v2->AverageGfxActivity : metrics->AverageGfxActivity;
+ if (average_gfx_activity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
+ gpu_metrics->average_gfxclk_frequency =
+ use_metrics_v2 ? metrics_v2->AverageGfxclkFrequencyPostDs : metrics->AverageGfxclkFrequencyPostDs;
else
- gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
- gpu_metrics->average_uclk_frequency = metrics->AverageUclkFrequencyPostDs;
- gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency;
- gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency;
- gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
- gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
-
- gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
- gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
- gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
- gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
- gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
- gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
- gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1];
-
- gpu_metrics->throttle_status = metrics->ThrottlerStatus;
+ gpu_metrics->average_gfxclk_frequency =
+ use_metrics_v2 ? metrics_v2->AverageGfxclkFrequencyPreDs : metrics->AverageGfxclkFrequencyPreDs;
+ gpu_metrics->average_uclk_frequency =
+ use_metrics_v2 ? metrics_v2->AverageUclkFrequencyPostDs : metrics->AverageUclkFrequencyPostDs;
+ gpu_metrics->average_vclk0_frequency =
+ use_metrics_v2 ? metrics_v2->AverageVclk0Frequency : metrics->AverageVclk0Frequency;
+ gpu_metrics->average_dclk0_frequency =
+ use_metrics_v2 ? metrics_v2->AverageDclk0Frequency : metrics->AverageDclk0Frequency;
+ gpu_metrics->average_vclk1_frequency =
+ use_metrics_v2 ? metrics_v2->AverageVclk1Frequency : metrics->AverageVclk1Frequency;
+ gpu_metrics->average_dclk1_frequency =
+ use_metrics_v2 ? metrics_v2->AverageDclk1Frequency : metrics->AverageDclk1Frequency;
+
+ gpu_metrics->current_gfxclk =
+ use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_GFXCLK] : metrics->CurrClock[PPCLK_GFXCLK];
+ gpu_metrics->current_socclk =
+ use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_SOCCLK] : metrics->CurrClock[PPCLK_SOCCLK];
+ gpu_metrics->current_uclk =
+ use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_UCLK] : metrics->CurrClock[PPCLK_UCLK];
+ gpu_metrics->current_vclk0 =
+ use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_VCLK_0] : metrics->CurrClock[PPCLK_VCLK_0];
+ gpu_metrics->current_dclk0 =
+ use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_0] : metrics->CurrClock[PPCLK_DCLK_0];
+ gpu_metrics->current_vclk1 =
+ use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_VCLK_1] : metrics->CurrClock[PPCLK_VCLK_1];
+ gpu_metrics->current_dclk1 =
+ use_metrics_v2 ? metrics_v2->CurrClock[PPCLK_DCLK_1] : metrics->CurrClock[PPCLK_DCLK_1];
+
+ gpu_metrics->throttle_status = sienna_cichlid_get_throttler_status_locked(smu);
gpu_metrics->indep_throttle_status =
- smu_cmn_get_indep_throttler_status(metrics->ThrottlerStatus,
+ smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
sienna_cichlid_throttler_map);
- gpu_metrics->current_fan_speed = metrics->CurrFanSpeed;
+ gpu_metrics->current_fan_speed = use_metrics_v2 ? metrics_v2->CurrFanSpeed : metrics->CurrFanSpeed;
- ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
- if (ret)
- return ret;
-
- if (((adev->asic_type == CHIP_SIENNA_CICHLID) && smu_version > 0x003A1E00) ||
- ((adev->asic_type == CHIP_NAVY_FLOUNDER) && smu_version > 0x00410400)) {
- gpu_metrics->pcie_link_width = metrics->PcieWidth;
- gpu_metrics->pcie_link_speed = link_speed[metrics->PcieRate];
+ if (((adev->asic_type == CHIP_SIENNA_CICHLID) && smu->smc_fw_version > 0x003A1E00) ||
+ ((adev->asic_type == CHIP_NAVY_FLOUNDER) && smu->smc_fw_version > 0x00410400)) {
+ gpu_metrics->pcie_link_width = use_metrics_v2 ? metrics_v2->PcieWidth : metrics->PcieWidth;
+ gpu_metrics->pcie_link_speed = link_speed[use_metrics_v2 ? metrics_v2->PcieRate : metrics->PcieRate];
} else {
gpu_metrics->pcie_link_width =
smu_v11_0_get_current_pcie_link_width(smu);
@@ -3743,6 +3715,8 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
smu_v11_0_get_current_pcie_link_speed(smu);
}
+ mutex_unlock(&smu->metrics_lock);
+
gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
*table = (void *)gpu_metrics;
@@ -3878,7 +3852,8 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.display_config_changed = sienna_cichlid_display_config_changed,
.notify_smc_display_config = sienna_cichlid_notify_smc_display_config,
.is_dpm_running = sienna_cichlid_is_dpm_running,
- .get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent,
+ .get_fan_speed_pwm = smu_v11_0_get_fan_speed_pwm,
+ .get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm,
.get_power_profile_mode = sienna_cichlid_get_power_profile_mode,
.set_power_profile_mode = sienna_cichlid_set_power_profile_mode,
.set_watermarks_table = sienna_cichlid_set_watermarks_table,
@@ -3921,7 +3896,8 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
.get_fan_control_mode = smu_v11_0_get_fan_control_mode,
.set_fan_control_mode = smu_v11_0_set_fan_control_mode,
- .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
+ .set_fan_speed_pwm = smu_v11_0_set_fan_speed_pwm,
+ .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
.set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
.gfx_off_control = smu_v11_0_gfx_off_control,
.register_irq_handler = smu_v11_0_register_irq_handler,
@@ -3938,6 +3914,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
.set_default_od_settings = sienna_cichlid_set_default_od_settings,
.od_edit_dpm_table = sienna_cichlid_od_edit_dpm_table,
+ .restore_user_od_settings = smu_v11_0_restore_user_od_settings,
.run_btc = sienna_cichlid_run_btc,
.set_power_source = smu_v11_0_set_power_source,
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index 0a5d46ac9ccd..87b055466a33 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -266,6 +266,9 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
case CHIP_BEIGE_GOBY:
smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Beige_Goby;
break;
+ case CHIP_CYAN_SKILLFISH:
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Cyan_Skillfish;
+ break;
default:
dev_err(smu->adev->dev, "smu unsupported asic type:%d.\n", smu->adev->asic_type);
smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV;
@@ -422,10 +425,20 @@ int smu_v11_0_init_smc_tables(struct smu_context *smu)
ret = -ENOMEM;
goto err3_out;
}
+
+ smu_table->user_overdrive_table =
+ kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
+ if (!smu_table->user_overdrive_table) {
+ ret = -ENOMEM;
+ goto err4_out;
+ }
+
}
return 0;
+err4_out:
+ kfree(smu_table->boot_overdrive_table);
err3_out:
kfree(smu_table->overdrive_table);
err2_out:
@@ -442,12 +455,14 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu)
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
kfree(smu_table->gpu_metrics_table);
+ kfree(smu_table->user_overdrive_table);
kfree(smu_table->boot_overdrive_table);
kfree(smu_table->overdrive_table);
kfree(smu_table->max_sustainable_clocks);
kfree(smu_table->driver_pptable);
kfree(smu_table->clocks_table);
smu_table->gpu_metrics_table = NULL;
+ smu_table->user_overdrive_table = NULL;
smu_table->boot_overdrive_table = NULL;
smu_table->overdrive_table = NULL;
smu_table->max_sustainable_clocks = NULL;
@@ -1185,17 +1200,13 @@ smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
}
int
-smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
+smu_v11_0_set_fan_speed_pwm(struct smu_context *smu, uint32_t speed)
{
struct amdgpu_device *adev = smu->adev;
uint32_t duty100, duty;
uint64_t tmp64;
- if (speed > 100)
- speed = 100;
-
- if (smu_v11_0_auto_fan_control(smu, 0))
- return -EINVAL;
+ speed = MIN(speed, 255);
duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
CG_FDO_CTRL1, FMAX_DUTY100);
@@ -1203,7 +1214,7 @@ smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
- do_div(tmp64, 100);
+ do_div(tmp64, 255);
duty = (uint32_t)tmp64;
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
@@ -1213,6 +1224,99 @@ smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC);
}
+int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
+ uint32_t speed)
+{
+ struct amdgpu_device *adev = smu->adev;
+ /*
+ * crystal_clock_freq used for fan speed rpm calculation is
+ * always 25Mhz. So, hardcode it as 2500(in 10K unit).
+ */
+ uint32_t crystal_clock_freq = 2500;
+ uint32_t tach_period;
+
+ /*
+ * To prevent from possible overheat, some ASICs may have requirement
+ * for minimum fan speed:
+ * - For some NV10 SKU, the fan speed cannot be set lower than
+ * 700 RPM.
+ * - For some Sienna Cichlid SKU, the fan speed cannot be set
+ * lower than 500 RPM.
+ */
+ tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
+ WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
+ CG_TACH_CTRL, TARGET_PERIOD,
+ tach_period));
+
+ return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
+}
+
+int smu_v11_0_get_fan_speed_pwm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t duty100, duty;
+ uint64_t tmp64;
+
+ /*
+ * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
+ * detected via register retrieving. To workaround this, we will
+ * report the fan speed as 0 PWM if user just requested such.
+ */
+ if ((smu->user_dpm_profile.flags & SMU_CUSTOM_FAN_SPEED_PWM)
+ && !smu->user_dpm_profile.fan_speed_pwm) {
+ *speed = 0;
+ return 0;
+ }
+
+ duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
+ CG_FDO_CTRL1, FMAX_DUTY100);
+ duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS),
+ CG_THERMAL_STATUS, FDO_PWM_DUTY);
+ if (!duty100)
+ return -EINVAL;
+
+ tmp64 = (uint64_t)duty * 255;
+ do_div(tmp64, duty100);
+ *speed = MIN((uint32_t)tmp64, 255);
+
+ return 0;
+}
+
+int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t crystal_clock_freq = 2500;
+ uint32_t tach_status;
+ uint64_t tmp64;
+
+ /*
+ * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
+ * detected via register retrieving. To workaround this, we will
+ * report the fan speed as 0 RPM if user just requested such.
+ */
+ if ((smu->user_dpm_profile.flags & SMU_CUSTOM_FAN_SPEED_RPM)
+ && !smu->user_dpm_profile.fan_speed_rpm) {
+ *speed = 0;
+ return 0;
+ }
+
+ tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
+
+ tach_status = RREG32_SOC15(THM, 0, mmCG_TACH_STATUS);
+ if (tach_status) {
+ do_div(tmp64, tach_status);
+ *speed = (uint32_t)tmp64;
+ } else {
+ dev_warn_once(adev->dev, "Got zero output on CG_TACH_STATUS reading!\n");
+ *speed = 0;
+ }
+
+ return 0;
+}
+
int
smu_v11_0_set_fan_control_mode(struct smu_context *smu,
uint32_t mode)
@@ -1221,7 +1325,9 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
switch (mode) {
case AMD_FAN_CTRL_NONE:
- ret = smu_v11_0_set_fan_speed_percent(smu, 100);
+ ret = smu_v11_0_auto_fan_control(smu, 0);
+ if (!ret)
+ ret = smu_v11_0_set_fan_speed_pwm(smu, 255);
break;
case AMD_FAN_CTRL_MANUAL:
ret = smu_v11_0_auto_fan_control(smu, 0);
@@ -2101,3 +2207,16 @@ int smu_v11_0_deep_sleep_control(struct smu_context *smu,
return ret;
}
+
+int smu_v11_0_restore_user_od_settings(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ void *user_od_table = table_context->user_overdrive_table;
+ int ret = 0;
+
+ ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)user_od_table, true);
+ if (ret)
+ dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
index bcaaa086fc2f..6eb50b05a33c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -592,28 +592,28 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu,
switch (clk_type) {
case SMU_OD_SCLK:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
- size = sprintf(buf, "%s:\n", "OD_SCLK");
- size += sprintf(buf + size, "0: %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_SCLK");
+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
- size += sprintf(buf + size, "1: %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
}
break;
case SMU_OD_CCLK:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
- size = sprintf(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select);
- size += sprintf(buf + size, "0: %10uMhz\n",
+ size = sysfs_emit(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select);
+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
(smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);
- size += sprintf(buf + size, "1: %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
(smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq);
}
break;
case SMU_OD_RANGE:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
- size = sprintf(buf, "%s:\n", "OD_RANGE");
- size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
- size += sprintf(buf + size, "CCLK: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n",
smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq);
}
break;
@@ -656,14 +656,14 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu,
return ret;
if (!value)
continue;
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
cur_value == value ? "*" : "");
if (cur_value == value)
cur_value_match_level = true;
}
if (!cur_value_match_level)
- size += sprintf(buf + size, " %uMhz *\n", cur_value);
+ size += sysfs_emit_at(buf, size, " %uMhz *\n", cur_value);
break;
default:
break;
@@ -691,28 +691,28 @@ static int vangogh_print_clk_levels(struct smu_context *smu,
switch (clk_type) {
case SMU_OD_SCLK:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
- size = sprintf(buf, "%s:\n", "OD_SCLK");
- size += sprintf(buf + size, "0: %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_SCLK");
+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
- size += sprintf(buf + size, "1: %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
}
break;
case SMU_OD_CCLK:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
- size = sprintf(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select);
- size += sprintf(buf + size, "0: %10uMhz\n",
+ size = sysfs_emit(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select);
+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
(smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);
- size += sprintf(buf + size, "1: %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
(smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq);
}
break;
case SMU_OD_RANGE:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
- size = sprintf(buf, "%s:\n", "OD_RANGE");
- size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
- size += sprintf(buf + size, "CCLK: %7uMhz %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n",
smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq);
}
break;
@@ -755,14 +755,14 @@ static int vangogh_print_clk_levels(struct smu_context *smu,
return ret;
if (!value)
continue;
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
cur_value == value ? "*" : "");
if (cur_value == value)
cur_value_match_level = true;
}
if (!cur_value_match_level)
- size += sprintf(buf + size, " %uMhz *\n", cur_value);
+ size += sysfs_emit_at(buf, size, " %uMhz *\n", cur_value);
break;
default:
break;
@@ -1035,7 +1035,7 @@ static int vangogh_get_power_profile_mode(struct smu_context *smu,
if (workload_type < 0)
continue;
- size += sprintf(buf + size, "%2d %14s%s\n",
+ size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
index 9a9c24a6ec35..b39138041141 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
@@ -510,16 +510,16 @@ static int renoir_print_clk_levels(struct smu_context *smu,
0, &max);
if (ret)
return ret;
- size += sprintf(buf + size, "OD_RANGE\nSCLK: %10uMhz %10uMhz\n", min, max);
+ size += sysfs_emit_at(buf, size, "OD_RANGE\nSCLK: %10uMhz %10uMhz\n", min, max);
}
break;
case SMU_OD_SCLK:
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
- size += sprintf(buf + size, "OD_SCLK\n");
- size += sprintf(buf + size, "0:%10uMhz\n", min);
- size += sprintf(buf + size, "1:%10uMhz\n", max);
+ size += sysfs_emit_at(buf, size, "OD_SCLK\n");
+ size += sysfs_emit_at(buf, size, "0:%10uMhz\n", min);
+ size += sysfs_emit_at(buf, size, "1:%10uMhz\n", max);
}
break;
case SMU_GFXCLK:
@@ -536,12 +536,12 @@ static int renoir_print_clk_levels(struct smu_context *smu,
else
i = 1;
- size += sprintf(buf + size, "0: %uMhz %s\n", min,
+ size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
i == 0 ? "*" : "");
- size += sprintf(buf + size, "1: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
i == 1 ? cur_value : RENOIR_UMD_PSTATE_GFXCLK,
i == 1 ? "*" : "");
- size += sprintf(buf + size, "2: %uMhz %s\n", max,
+ size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
i == 2 ? "*" : "");
}
return size;
@@ -588,14 +588,14 @@ static int renoir_print_clk_levels(struct smu_context *smu,
return ret;
if (!value)
continue;
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
cur_value == value ? "*" : "");
if (cur_value == value)
cur_value_match_level = true;
}
if (!cur_value_match_level)
- size += sprintf(buf + size, " %uMhz *\n", cur_value);
+ size += sysfs_emit_at(buf, size, " %uMhz *\n", cur_value);
break;
default:
@@ -1118,7 +1118,7 @@ static int renoir_get_power_profile_mode(struct smu_context *smu,
if (workload_type < 0)
continue;
- size += sprintf(buf + size, "%2d %14s%s\n",
+ size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
index cb5485cf243f..ec8c30daf31c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
@@ -90,8 +90,8 @@ static const struct cmn2asic_msg_mapping aldebaran_message_map[SMU_MSG_MAX_COUNT
MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0),
- MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 0),
- MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 0),
+ MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1),
+ MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1),
MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1),
MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1),
MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0),
@@ -150,20 +150,20 @@ static const struct cmn2asic_mapping aldebaran_clk_map[SMU_CLK_COUNT] = {
};
static const struct cmn2asic_mapping aldebaran_feature_mask_map[SMU_FEATURE_COUNT] = {
- ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_PREFETCHER_BIT, FEATURE_DATA_CALCULATIONS),
+ ALDEBARAN_FEA_MAP(SMU_FEATURE_DATA_CALCULATIONS_BIT, FEATURE_DATA_CALCULATIONS),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_GFXCLK_BIT, FEATURE_DPM_GFXCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_UCLK_BIT, FEATURE_DPM_UCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_SOCCLK_BIT, FEATURE_DPM_SOCCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_FCLK_BIT, FEATURE_DPM_FCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_LCLK_BIT, FEATURE_DPM_LCLK_BIT),
- ALDEBARAN_FEA_MAP(SMU_FEATURE_XGMI_BIT, FEATURE_DPM_XGMI_BIT),
+ ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_XGMI_BIT, FEATURE_DPM_XGMI_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_GFXCLK_BIT, FEATURE_DS_GFXCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_SOCCLK_BIT, FEATURE_DS_SOCCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_LCLK_BIT, FEATURE_DS_LCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_FCLK_BIT, FEATURE_DS_FCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_UCLK_BIT, FEATURE_DS_UCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_GFX_SS_BIT, FEATURE_GFX_SS_BIT),
- ALDEBARAN_FEA_MAP(SMU_FEATURE_VCN_PG_BIT, FEATURE_DPM_VCN_BIT),
+ ALDEBARAN_FEA_MAP(SMU_FEATURE_VCN_DPM_BIT, FEATURE_DPM_VCN_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_RSMU_SMN_CG_BIT, FEATURE_RSMU_SMN_CG_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_WAFL_CG_BIT, FEATURE_WAFL_CG_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_PPT_BIT, FEATURE_PPT_BIT),
@@ -735,14 +735,14 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
uint32_t min_clk, max_clk;
if (amdgpu_ras_intr_triggered())
- return snprintf(buf, PAGE_SIZE, "unavailable\n");
+ return sysfs_emit(buf, "unavailable\n");
dpm_context = smu_dpm->dpm_context;
switch (type) {
case SMU_OD_SCLK:
- size = sprintf(buf, "%s:\n", "GFXCLK");
+ size = sysfs_emit(buf, "%s:\n", "GFXCLK");
fallthrough;
case SMU_SCLK:
ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now);
@@ -779,8 +779,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
*/
if (display_levels == clocks.num_levels) {
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(
- buf + size, "%d: %uMhz %s\n", i,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i,
freq_values[i],
(clocks.num_levels == 1) ?
"*" :
@@ -790,14 +789,14 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
""));
} else {
for (i = 0; i < display_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n", i,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i,
freq_values[i], i == 1 ? "*" : "");
}
break;
case SMU_OD_MCLK:
- size = sprintf(buf, "%s:\n", "MCLK");
+ size = sysfs_emit(buf, "%s:\n", "MCLK");
fallthrough;
case SMU_MCLK:
ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, &now);
@@ -814,7 +813,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.num_levels == 1) ? "*" :
(aldebaran_freqs_in_same_level(
@@ -837,7 +836,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < clocks.num_levels; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, clocks.data[i].clocks_in_khz / 1000,
(clocks.num_levels == 1) ? "*" :
(aldebaran_freqs_in_same_level(
@@ -860,7 +859,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < single_dpm_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, single_dpm_table->dpm_levels[i].value,
(clocks.num_levels == 1) ? "*" :
(aldebaran_freqs_in_same_level(
@@ -883,7 +882,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < single_dpm_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, single_dpm_table->dpm_levels[i].value,
(clocks.num_levels == 1) ? "*" :
(aldebaran_freqs_in_same_level(
@@ -906,7 +905,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
}
for (i = 0; i < single_dpm_table->count; i++)
- size += sprintf(buf + size, "%d: %uMhz %s\n",
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
i, single_dpm_table->dpm_levels[i].value,
(clocks.num_levels == 1) ? "*" :
(aldebaran_freqs_in_same_level(
@@ -1194,8 +1193,19 @@ static int aldebaran_get_power_limit(struct smu_context *smu,
uint32_t power_limit = 0;
int ret;
- if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
- return -EINVAL;
+ if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
+ if (current_power_limit)
+ *current_power_limit = 0;
+ if (default_power_limit)
+ *default_power_limit = 0;
+ if (max_power_limit)
+ *max_power_limit = 0;
+
+ dev_warn(smu->adev->dev,
+ "PPT feature is not enabled, power values can't be fetched.");
+
+ return 0;
+ }
/* Valid power data is available only from primary die.
* For secondary die show the value as 0.
@@ -1451,197 +1461,77 @@ static bool aldebaran_is_dpm_running(struct smu_context *smu)
return !!(feature_enabled & SMC_DPM_FEATURE);
}
-static void aldebaran_fill_i2c_req(SwI2cRequest_t *req, bool write,
- uint8_t address, uint32_t numbytes,
- uint8_t *data)
-{
- int i;
-
- req->I2CcontrollerPort = 0;
- req->I2CSpeed = 2;
- req->SlaveAddress = address;
- req->NumCmds = numbytes;
-
- for (i = 0; i < numbytes; i++) {
- SwI2cCmd_t *cmd = &req->SwI2cCmds[i];
-
- /* First 2 bytes are always write for lower 2b EEPROM address */
- if (i < 2)
- cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
- else
- cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
-
-
- /* Add RESTART for read after address filled */
- cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
-
- /* Add STOP in the end */
- cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
-
- /* Fill with data regardless if read or write to simplify code */
- cmd->ReadWriteData = data[i];
- }
-}
-
-static int aldebaran_i2c_read_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
+static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msg, int num_msgs)
{
- uint32_t i, ret = 0;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
+ struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
struct smu_table_context *smu_table = &adev->smu.smu_table;
struct smu_table *table = &smu_table->driver_table;
+ SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+ int i, j, r, c;
+ u16 dir;
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
- }
-
- memset(&req, 0, sizeof(req));
- aldebaran_fill_i2c_req(&req, false, address, numbytes, data);
-
- mutex_lock(&adev->smu.mutex);
- /* Now read data starting with that address */
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
- true);
- mutex_unlock(&adev->smu.mutex);
-
- if (!ret) {
- SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
- /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */
- for (i = 0; i < numbytes; i++)
- data[i] = res->SwI2cCmds[i].ReadWriteData;
-
- dev_dbg(adev->dev, "aldebaran_i2c_read_data, address = %x, bytes = %d, data :",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- } else
- dev_err(adev->dev, "aldebaran_i2c_read_data - error occurred :%x", ret);
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
- return ret;
-}
+ req->I2CcontrollerPort = 0;
+ req->I2CSpeed = I2C_SPEED_FAST_400K;
+ req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+ dir = msg[0].flags & I2C_M_RD;
+
+ for (c = i = 0; i < num_msgs; i++) {
+ for (j = 0; j < msg[i].len; j++, c++) {
+ SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+ if (!(msg[i].flags & I2C_M_RD)) {
+ /* write */
+ cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
+ cmd->ReadWriteData = msg[i].buf[j];
+ }
-static int aldebaran_i2c_write_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
-{
- uint32_t ret;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
+ if ((dir ^ msg[i].flags) & I2C_M_RD) {
+ /* The direction changes.
+ */
+ dir = msg[i].flags & I2C_M_RD;
+ cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+ }
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
+ req->NumCmds++;
+
+ /*
+ * Insert STOP if we are at the last byte of either last
+ * message for the transaction or the client explicitly
+ * requires a STOP at this particular message.
+ */
+ if ((j == msg[i].len - 1) &&
+ ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
+ cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+ cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+ }
+ }
}
-
- memset(&req, 0, sizeof(req));
- aldebaran_fill_i2c_req(&req, true, address, numbytes, data);
-
mutex_lock(&adev->smu.mutex);
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
+ r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
mutex_unlock(&adev->smu.mutex);
+ if (r)
+ goto fail;
- if (!ret) {
- dev_dbg(adev->dev, "aldebaran_i2c_write(), address = %x, bytes = %d , data: ",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- /*
- * According to EEPROM spec there is a MAX of 10 ms required for
- * EEPROM to flush internal RX buffer after STOP was issued at the
- * end of write transaction. During this time the EEPROM will not be
- * responsive to any more commands - so wait a bit more.
- */
- msleep(10);
-
- } else
- dev_err(adev->dev, "aldebaran_i2c_write- error occurred :%x", ret);
-
- return ret;
-}
-
-static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs, int num)
-{
- uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
- uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
-
- for (i = 0; i < num; i++) {
- /*
- * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
- * once and hence the data needs to be spliced into chunks and sent each
- * chunk separately
- */
- data_size = msgs[i].len - 2;
- data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
- next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
- data_ptr = msgs[i].buf + 2;
-
- for (j = 0; j < data_size / data_chunk_size; j++) {
- /* Insert the EEPROM dest addess, bits 0-15 */
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = aldebaran_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
-
- memcpy(data_ptr, data_chunk + 2, data_chunk_size);
- } else {
-
- memcpy(data_chunk + 2, data_ptr, data_chunk_size);
-
- ret = aldebaran_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
-
- next_eeprom_addr += data_chunk_size;
- data_ptr += data_chunk_size;
+ for (c = i = 0; i < num_msgs; i++) {
+ if (!(msg[i].flags & I2C_M_RD)) {
+ c += msg[i].len;
+ continue;
}
+ for (j = 0; j < msg[i].len; j++, c++) {
+ SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
- if (data_size % data_chunk_size) {
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = aldebaran_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
-
- memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
- } else {
- memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
-
- ret = aldebaran_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
+ msg[i].buf[j] = cmd->ReadWriteData;
}
}
-
+ r = num_msgs;
fail:
- return num;
+ kfree(req);
+ return r;
}
static u32 aldebaran_i2c_func(struct i2c_adapter *adap)
@@ -1655,6 +1545,14 @@ static const struct i2c_algorithm aldebaran_i2c_algo = {
.functionality = aldebaran_i2c_func,
};
+static const struct i2c_adapter_quirks aldebaran_i2c_control_quirks = {
+ .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+ .max_read_len = MAX_SW_I2C_COMMANDS,
+ .max_write_len = MAX_SW_I2C_COMMANDS,
+ .max_comb_1st_msg_len = 2,
+ .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
+};
+
static int aldebaran_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -1665,6 +1563,7 @@ static int aldebaran_i2c_control_init(struct smu_context *smu, struct i2c_adapte
control->dev.parent = &adev->pdev->dev;
control->algo = &aldebaran_i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+ control->quirks = &aldebaran_i2c_control_quirks;
res = i2c_add_adapter(control);
if (res)
@@ -1764,7 +1663,9 @@ static void aldebaran_log_thermal_throttling_event(struct smu_context *smu)
dev_warn(adev->dev, "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n",
log_buf);
- kgd2kfd_smi_event_throttle(smu->adev->kfd.dev, throttler_status);
+ kgd2kfd_smi_event_throttle(smu->adev->kfd.dev,
+ smu_cmn_get_indep_throttler_status(throttler_status,
+ aldebaran_throttler_map));
}
static int aldebaran_get_current_pcie_link_speed(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
index a421ba85bd6d..a0e50f23b1dd 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -85,6 +85,10 @@ int smu_v13_0_init_microcode(struct smu_context *smu)
const struct common_firmware_header *header;
struct amdgpu_firmware_info *ucode = NULL;
+ /* doesn't need to load smu firmware in IOV mode */
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
switch (adev->asic_type) {
case CHIP_ALDEBARAN:
chip_name = "aldebaran";
@@ -268,52 +272,86 @@ static int smu_v13_0_set_pptable_v2_1(struct smu_context *smu, void **table,
return 0;
}
-int smu_v13_0_setup_pptable(struct smu_context *smu)
+static int smu_v13_0_get_pptable_from_vbios(struct smu_context *smu, void **table, uint32_t *size)
{
struct amdgpu_device *adev = smu->adev;
- const struct smc_firmware_header_v1_0 *hdr;
- int ret, index;
- uint32_t size = 0;
uint16_t atom_table_size;
uint8_t frev, crev;
- void *table;
- uint16_t version_major, version_minor;
+ int ret, index;
+ dev_info(adev->dev, "use vbios provided pptable\n");
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+ powerplayinfo);
- if (amdgpu_smu_pptable_id >= 0) {
- smu->smu_table.boot_values.pp_table_id = amdgpu_smu_pptable_id;
- dev_info(adev->dev, "override pptable id %d\n", amdgpu_smu_pptable_id);
- }
+ ret = amdgpu_atombios_get_data_table(adev, index, &atom_table_size, &frev, &crev,
+ (uint8_t **)table);
+ if (ret)
+ return ret;
+
+ if (size)
+ *size = atom_table_size;
+
+ return 0;
+}
+
+static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **table, uint32_t *size,
+ uint32_t pptable_id)
+{
+ const struct smc_firmware_header_v1_0 *hdr;
+ struct amdgpu_device *adev = smu->adev;
+ uint16_t version_major, version_minor;
+ int ret;
hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
+ if (!hdr)
+ return -EINVAL;
+
+ dev_info(adev->dev, "use driver provided pptable %d\n", pptable_id);
+
version_major = le16_to_cpu(hdr->header.header_version_major);
version_minor = le16_to_cpu(hdr->header.header_version_minor);
- if (version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) {
- dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id);
- switch (version_minor) {
- case 1:
- ret = smu_v13_0_set_pptable_v2_1(smu, &table, &size,
- smu->smu_table.boot_values.pp_table_id);
- break;
- default:
- ret = -EINVAL;
- break;
- }
- if (ret)
- return ret;
+ if (version_major != 2) {
+ dev_err(adev->dev, "Unsupported smu firmware version %d.%d\n",
+ version_major, version_minor);
+ return -EINVAL;
+ }
- } else {
- dev_info(adev->dev, "use vbios provided pptable\n");
- index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
- powerplayinfo);
+ switch (version_minor) {
+ case 1:
+ ret = smu_v13_0_set_pptable_v2_1(smu, table, size, pptable_id);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
- ret = amdgpu_atombios_get_data_table(adev, index, &atom_table_size, &frev, &crev,
- (uint8_t **)&table);
- if (ret)
- return ret;
- size = atom_table_size;
+ return ret;
+}
+
+int smu_v13_0_setup_pptable(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t size = 0, pptable_id = 0;
+ void *table;
+ int ret = 0;
+
+ /* override pptable_id from driver parameter */
+ if (amdgpu_smu_pptable_id >= 0) {
+ pptable_id = amdgpu_smu_pptable_id;
+ dev_info(adev->dev, "override pptable id %d\n", pptable_id);
+ } else {
+ pptable_id = smu->smu_table.boot_values.pp_table_id;
}
+ /* force using vbios pptable in sriov mode */
+ if (amdgpu_sriov_vf(adev) || !pptable_id)
+ ret = smu_v13_0_get_pptable_from_vbios(smu, &table, &size);
+ else
+ ret = smu_v13_0_get_pptable_from_firmware(smu, &table, &size, pptable_id);
+
+ if (ret)
+ return ret;
+
if (!smu->smu_table.power_play_table)
smu->smu_table.power_play_table = table;
if (!smu->smu_table.power_play_table_size)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
index 0cfeb9fc7c03..0f17c2522c85 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
@@ -572,7 +572,7 @@ static int yellow_carp_get_power_profile_mode(struct smu_context *smu,
if (workload_type < 0)
continue;
- size += sprintf(buf + size, "%2d %14s%s\n",
+ size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
}
@@ -1054,15 +1054,15 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
switch (clk_type) {
case SMU_OD_SCLK:
- size = sprintf(buf, "%s:\n", "OD_SCLK");
- size += sprintf(buf + size, "0: %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_SCLK");
+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
- size += sprintf(buf + size, "1: %10uMhz\n",
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
break;
case SMU_OD_RANGE:
- size = sprintf(buf, "%s:\n", "OD_RANGE");
- size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+ size = sysfs_emit(buf, "%s:\n", "OD_RANGE");
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
break;
case SMU_SOCCLK:
@@ -1083,7 +1083,7 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
if (ret)
goto print_clk_out;
- size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
cur_value == value ? "*" : "");
}
break;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index e802f9a95f08..66711ab24c15 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -55,7 +55,7 @@
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) #type
-static const char* __smu_message_names[] = {
+static const char * const __smu_message_names[] = {
SMU_MESSAGE_TYPES
};
@@ -76,55 +76,256 @@ static void smu_cmn_read_arg(struct smu_context *smu,
*arg = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
}
-int smu_cmn_wait_for_response(struct smu_context *smu)
+/* Redefine the SMU error codes here.
+ *
+ * Note that these definitions are redundant and should be removed
+ * when the SMU has exported a unified header file containing these
+ * macros, which header file we can just include and use the SMU's
+ * macros. At the moment, these error codes are defined by the SMU
+ * per-ASIC unfortunately, yet we're a one driver for all ASICs.
+ */
+#define SMU_RESP_NONE 0
+#define SMU_RESP_OK 1
+#define SMU_RESP_CMD_FAIL 0xFF
+#define SMU_RESP_CMD_UNKNOWN 0xFE
+#define SMU_RESP_CMD_BAD_PREREQ 0xFD
+#define SMU_RESP_BUSY_OTHER 0xFC
+#define SMU_RESP_DEBUG_END 0xFB
+
+/**
+ * __smu_cmn_poll_stat -- poll for a status from the SMU
+ * smu: a pointer to SMU context
+ *
+ * Returns the status of the SMU, which could be,
+ * 0, the SMU is busy with your previous command;
+ * 1, execution status: success, execution result: success;
+ * 0xFF, execution status: success, execution result: failure;
+ * 0xFE, unknown command;
+ * 0xFD, valid command, but bad (command) prerequisites;
+ * 0xFC, the command was rejected as the SMU is busy;
+ * 0xFB, "SMC_Result_DebugDataDumpEnd".
+ *
+ * The values here are not defined by macros, because I'd rather we
+ * include a single header file which defines them, which is
+ * maintained by the SMU FW team, so that we're impervious to firmware
+ * changes. At the moment those values are defined in various header
+ * files, one for each ASIC, yet here we're a single ASIC-agnostic
+ * interface. Such a change can be followed-up by a subsequent patch.
+ */
+static u32 __smu_cmn_poll_stat(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- uint32_t cur_value, i, timeout = adev->usec_timeout * 20;
+ int timeout = adev->usec_timeout * 20;
+ u32 reg;
- for (i = 0; i < timeout; i++) {
- cur_value = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
- if ((cur_value & MP1_C2PMSG_90__CONTENT_MASK) != 0)
- return cur_value;
+ for ( ; timeout > 0; timeout--) {
+ reg = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
+ if ((reg & MP1_C2PMSG_90__CONTENT_MASK) != 0)
+ break;
udelay(1);
}
- /* timeout means wrong logic */
- if (i == timeout)
- return -ETIME;
-
- return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
+ return reg;
}
-int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
- uint16_t msg, uint32_t param)
+static void __smu_cmn_reg_print_error(struct smu_context *smu,
+ u32 reg_c2pmsg_90,
+ int msg_index,
+ u32 param,
+ enum smu_message_type msg)
{
struct amdgpu_device *adev = smu->adev;
- int ret;
+ const char *message = smu_get_message_name(smu, msg);
- ret = smu_cmn_wait_for_response(smu);
- if (ret != 0x1) {
- dev_err(adev->dev, "Msg issuing pre-check failed(0x%x) and "
- "SMU may be not in the right state!\n", ret);
- if (ret != -ETIME)
- ret = -EIO;
- return ret;
+ switch (reg_c2pmsg_90) {
+ case SMU_RESP_NONE:
+ dev_err_ratelimited(adev->dev,
+ "SMU: I'm not done with your previous command!");
+ break;
+ case SMU_RESP_OK:
+ /* The SMU executed the command. It completed with a
+ * successful result.
+ */
+ break;
+ case SMU_RESP_CMD_FAIL:
+ /* The SMU executed the command. It completed with an
+ * unsuccessful result.
+ */
+ break;
+ case SMU_RESP_CMD_UNKNOWN:
+ dev_err_ratelimited(adev->dev,
+ "SMU: unknown command: index:%d param:0x%08X message:%s",
+ msg_index, param, message);
+ break;
+ case SMU_RESP_CMD_BAD_PREREQ:
+ dev_err_ratelimited(adev->dev,
+ "SMU: valid command, bad prerequisites: index:%d param:0x%08X message:%s",
+ msg_index, param, message);
+ break;
+ case SMU_RESP_BUSY_OTHER:
+ dev_err_ratelimited(adev->dev,
+ "SMU: I'm very busy for your command: index:%d param:0x%08X message:%s",
+ msg_index, param, message);
+ break;
+ case SMU_RESP_DEBUG_END:
+ dev_err_ratelimited(adev->dev,
+ "SMU: I'm debugging!");
+ break;
+ default:
+ dev_err_ratelimited(adev->dev,
+ "SMU: response:0x%08X for index:%d param:0x%08X message:%s?",
+ reg_c2pmsg_90, msg_index, param, message);
+ break;
}
+}
+
+static int __smu_cmn_reg2errno(struct smu_context *smu, u32 reg_c2pmsg_90)
+{
+ int res;
+
+ switch (reg_c2pmsg_90) {
+ case SMU_RESP_NONE:
+ /* The SMU is busy--still executing your command.
+ */
+ res = -ETIME;
+ break;
+ case SMU_RESP_OK:
+ res = 0;
+ break;
+ case SMU_RESP_CMD_FAIL:
+ /* Command completed successfully, but the command
+ * status was failure.
+ */
+ res = -EIO;
+ break;
+ case SMU_RESP_CMD_UNKNOWN:
+ /* Unknown command--ignored by the SMU.
+ */
+ res = -EOPNOTSUPP;
+ break;
+ case SMU_RESP_CMD_BAD_PREREQ:
+ /* Valid command--bad prerequisites.
+ */
+ res = -EINVAL;
+ break;
+ case SMU_RESP_BUSY_OTHER:
+ /* The SMU is busy with other commands. The client
+ * should retry in 10 us.
+ */
+ res = -EBUSY;
+ break;
+ default:
+ /* Unknown or debug response from the SMU.
+ */
+ res = -EREMOTEIO;
+ break;
+ }
+
+ return res;
+}
+
+static void __smu_cmn_send_msg(struct smu_context *smu,
+ u16 msg,
+ u32 param)
+{
+ struct amdgpu_device *adev = smu->adev;
WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, param);
WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
+}
- return 0;
+/**
+ * smu_cmn_send_msg_without_waiting -- send the message; don't wait for status
+ * @smu: pointer to an SMU context
+ * @msg_index: message index
+ * @param: message parameter to send to the SMU
+ *
+ * Send a message to the SMU with the parameter passed. Do not wait
+ * for status/result of the message, thus the "without_waiting".
+ *
+ * Return 0 on success, -errno on error if we weren't able to _send_
+ * the message for some reason. See __smu_cmn_reg2errno() for details
+ * of the -errno.
+ */
+int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
+ uint16_t msg_index,
+ uint32_t param)
+{
+ u32 reg;
+ int res;
+
+ if (smu->adev->no_hw_access)
+ return 0;
+
+ reg = __smu_cmn_poll_stat(smu);
+ res = __smu_cmn_reg2errno(smu, reg);
+ if (reg == SMU_RESP_NONE ||
+ reg == SMU_RESP_BUSY_OTHER ||
+ res == -EREMOTEIO)
+ goto Out;
+ __smu_cmn_send_msg(smu, msg_index, param);
+ res = 0;
+Out:
+ return res;
+}
+
+/**
+ * smu_cmn_wait_for_response -- wait for response from the SMU
+ * @smu: pointer to an SMU context
+ *
+ * Wait for status from the SMU.
+ *
+ * Return 0 on success, -errno on error, indicating the execution
+ * status and result of the message being waited for. See
+ * __smu_cmn_reg2errno() for details of the -errno.
+ */
+int smu_cmn_wait_for_response(struct smu_context *smu)
+{
+ u32 reg;
+
+ reg = __smu_cmn_poll_stat(smu);
+ return __smu_cmn_reg2errno(smu, reg);
}
+/**
+ * smu_cmn_send_smc_msg_with_param -- send a message with parameter
+ * @smu: pointer to an SMU context
+ * @msg: message to send
+ * @param: parameter to send to the SMU
+ * @read_arg: pointer to u32 to return a value from the SMU back
+ * to the caller
+ *
+ * Send the message @msg with parameter @param to the SMU, wait for
+ * completion of the command, and return back a value from the SMU in
+ * @read_arg pointer.
+ *
+ * Return 0 on success, -errno on error, if we weren't able to send
+ * the message or if the message completed with some kind of
+ * error. See __smu_cmn_reg2errno() for details of the -errno.
+ *
+ * If we weren't able to send the message to the SMU, we also print
+ * the error to the standard log.
+ *
+ * Command completion status is printed only if the -errno is
+ * -EREMOTEIO, indicating that the SMU returned back an
+ * undefined/unknown/unspecified result. All other cases are
+ * well-defined, not printed, but instead given back to the client to
+ * decide what further to do.
+ *
+ * The return value, @read_arg is read back regardless, to give back
+ * more information to the client, which on error would most likely be
+ * @param, but we can't assume that. This also eliminates more
+ * conditionals.
+ */
int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
enum smu_message_type msg,
uint32_t param,
uint32_t *read_arg)
{
- struct amdgpu_device *adev = smu->adev;
- int ret = 0, index = 0;
+ int res, index;
+ u32 reg;
if (smu->adev->no_hw_access)
return 0;
@@ -136,31 +337,24 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
return index == -EACCES ? 0 : index;
mutex_lock(&smu->message_lock);
- ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index, param);
- if (ret)
- goto out;
-
- ret = smu_cmn_wait_for_response(smu);
- if (ret != 0x1) {
- if (ret == -ETIME) {
- dev_err(adev->dev, "message: %15s (%d) \tparam: 0x%08x is timeout (no response)\n",
- smu_get_message_name(smu, msg), index, param);
- } else {
- dev_err(adev->dev, "failed send message: %15s (%d) \tparam: 0x%08x response %#x\n",
- smu_get_message_name(smu, msg), index, param,
- ret);
- ret = -EIO;
- }
- goto out;
+ reg = __smu_cmn_poll_stat(smu);
+ res = __smu_cmn_reg2errno(smu, reg);
+ if (reg == SMU_RESP_NONE ||
+ reg == SMU_RESP_BUSY_OTHER ||
+ res == -EREMOTEIO) {
+ __smu_cmn_reg_print_error(smu, reg, index, param, msg);
+ goto Out;
}
-
+ __smu_cmn_send_msg(smu, (uint16_t) index, param);
+ reg = __smu_cmn_poll_stat(smu);
+ res = __smu_cmn_reg2errno(smu, reg);
+ if (res == -EREMOTEIO)
+ __smu_cmn_reg_print_error(smu, reg, index, param, msg);
if (read_arg)
smu_cmn_read_arg(smu, read_arg);
-
- ret = 0; /* 0 as driver return value */
-out:
+Out:
mutex_unlock(&smu->message_lock);
- return ret;
+ return res;
}
int smu_cmn_send_smc_msg(struct smu_context *smu,
@@ -516,7 +710,7 @@ size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu,
return 0;
}
- size = sprintf(buf + size, "features high: 0x%08x low: 0x%08x\n",
+ size = sysfs_emit_at(buf, size, "features high: 0x%08x low: 0x%08x\n",
feature_mask[1], feature_mask[0]);
memset(sort_feature, -1, sizeof(sort_feature));
@@ -531,14 +725,14 @@ size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu,
sort_feature[feature_index] = i;
}
- size += sprintf(buf + size, "%-2s. %-20s %-3s : %-s\n",
+ size += sysfs_emit_at(buf, size, "%-2s. %-20s %-3s : %-s\n",
"No", "Feature", "Bit", "State");
for (i = 0; i < SMU_FEATURE_COUNT; i++) {
if (sort_feature[i] < 0)
continue;
- size += sprintf(buf + size, "%02d. %-20s (%2d) : %s\n",
+ size += sysfs_emit_at(buf, size, "%02d. %-20s (%2d) : %s\n",
count++,
smu_get_feature_name(smu, sort_feature[i]),
i,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index 9add5f16ff56..16993daa2ae0 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -27,7 +27,8 @@
#if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || defined(SWSMU_CODE_LAYER_L4)
int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
- uint16_t msg, uint32_t param);
+ uint16_t msg_index,
+ uint32_t param);
int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
enum smu_message_type msg,
uint32_t param,
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index ff45f23f3d56..93b7f09b96ca 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -13,7 +13,6 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
@@ -301,8 +300,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
if (err)
goto free_component_binding;
- drm->irq_enabled = true;
-
drm_kms_helper_poll_init(drm);
err = drm_dev_register(drm, 0);
@@ -313,7 +310,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
free_interrupts:
drm_kms_helper_poll_fini(drm);
- drm->irq_enabled = false;
free_component_binding:
component_unbind_all(mdev->dev, drm);
cleanup_mode_config:
@@ -331,7 +327,6 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
drm_dev_unregister(drm);
drm_kms_helper_poll_fini(drm);
drm_atomic_helper_shutdown(drm);
- drm->irq_enabled = false;
component_unbind_all(mdev->dev, drm);
drm_mode_config_cleanup(drm);
komeda_kms_cleanup_private_objs(kms);
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 81ae92390736..479c2422a2e0 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -29,7 +29,6 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
@@ -38,6 +37,94 @@
#include "hdlcd_drv.h"
#include "hdlcd_regs.h"
+static irqreturn_t hdlcd_irq(int irq, void *arg)
+{
+ struct drm_device *drm = arg;
+ struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ unsigned long irq_status;
+
+ irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
+
+#ifdef CONFIG_DEBUG_FS
+ if (irq_status & HDLCD_INTERRUPT_UNDERRUN)
+ atomic_inc(&hdlcd->buffer_underrun_count);
+
+ if (irq_status & HDLCD_INTERRUPT_DMA_END)
+ atomic_inc(&hdlcd->dma_end_count);
+
+ if (irq_status & HDLCD_INTERRUPT_BUS_ERROR)
+ atomic_inc(&hdlcd->bus_error_count);
+
+ if (irq_status & HDLCD_INTERRUPT_VSYNC)
+ atomic_inc(&hdlcd->vsync_count);
+
+#endif
+ if (irq_status & HDLCD_INTERRUPT_VSYNC)
+ drm_crtc_handle_vblank(&hdlcd->crtc);
+
+ /* acknowledge interrupt(s) */
+ hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
+
+ return IRQ_HANDLED;
+}
+
+static void hdlcd_irq_preinstall(struct drm_device *drm)
+{
+ struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ /* Ensure interrupts are disabled */
+ hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
+ hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
+}
+
+static void hdlcd_irq_postinstall(struct drm_device *drm)
+{
+#ifdef CONFIG_DEBUG_FS
+ struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
+
+ /* enable debug interrupts */
+ irq_mask |= HDLCD_DEBUG_INT_MASK;
+
+ hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
+#endif
+}
+
+static int hdlcd_irq_install(struct drm_device *drm, int irq)
+{
+ int ret;
+
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ hdlcd_irq_preinstall(drm);
+
+ ret = request_irq(irq, hdlcd_irq, 0, drm->driver->name, drm);
+ if (ret)
+ return ret;
+
+ hdlcd_irq_postinstall(drm);
+
+ return 0;
+}
+
+static void hdlcd_irq_uninstall(struct drm_device *drm)
+{
+ struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ /* disable all the interrupts that we might have enabled */
+ unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
+
+#ifdef CONFIG_DEBUG_FS
+ /* disable debug interrupts */
+ irq_mask &= ~HDLCD_DEBUG_INT_MASK;
+#endif
+
+ /* disable vsync interrupts */
+ irq_mask &= ~HDLCD_INTERRUPT_VSYNC;
+ hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
+
+ free_irq(hdlcd->irq, drm);
+}
+
static int hdlcd_load(struct drm_device *drm, unsigned long flags)
{
struct hdlcd_drm_private *hdlcd = drm->dev_private;
@@ -90,7 +177,12 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
goto setup_fail;
}
- ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ goto irq_fail;
+ hdlcd->irq = ret;
+
+ ret = hdlcd_irq_install(drm, hdlcd->irq);
if (ret < 0) {
DRM_ERROR("failed to install IRQ handler\n");
goto irq_fail;
@@ -122,76 +214,6 @@ static void hdlcd_setup_mode_config(struct drm_device *drm)
drm->mode_config.funcs = &hdlcd_mode_config_funcs;
}
-static irqreturn_t hdlcd_irq(int irq, void *arg)
-{
- struct drm_device *drm = arg;
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
- unsigned long irq_status;
-
- irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
-
-#ifdef CONFIG_DEBUG_FS
- if (irq_status & HDLCD_INTERRUPT_UNDERRUN)
- atomic_inc(&hdlcd->buffer_underrun_count);
-
- if (irq_status & HDLCD_INTERRUPT_DMA_END)
- atomic_inc(&hdlcd->dma_end_count);
-
- if (irq_status & HDLCD_INTERRUPT_BUS_ERROR)
- atomic_inc(&hdlcd->bus_error_count);
-
- if (irq_status & HDLCD_INTERRUPT_VSYNC)
- atomic_inc(&hdlcd->vsync_count);
-
-#endif
- if (irq_status & HDLCD_INTERRUPT_VSYNC)
- drm_crtc_handle_vblank(&hdlcd->crtc);
-
- /* acknowledge interrupt(s) */
- hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
-
- return IRQ_HANDLED;
-}
-
-static void hdlcd_irq_preinstall(struct drm_device *drm)
-{
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
- /* Ensure interrupts are disabled */
- hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
- hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
-}
-
-static int hdlcd_irq_postinstall(struct drm_device *drm)
-{
-#ifdef CONFIG_DEBUG_FS
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
- unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
- /* enable debug interrupts */
- irq_mask |= HDLCD_DEBUG_INT_MASK;
-
- hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
-#endif
- return 0;
-}
-
-static void hdlcd_irq_uninstall(struct drm_device *drm)
-{
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
- /* disable all the interrupts that we might have enabled */
- unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-#ifdef CONFIG_DEBUG_FS
- /* disable debug interrupts */
- irq_mask &= ~HDLCD_DEBUG_INT_MASK;
-#endif
-
- /* disable vsync interrupts */
- irq_mask &= ~HDLCD_INTERRUPT_VSYNC;
-
- hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
-}
-
#ifdef CONFIG_DEBUG_FS
static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
{
@@ -236,10 +258,6 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
static const struct drm_driver hdlcd_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
- .irq_handler = hdlcd_irq,
- .irq_preinstall = hdlcd_irq_preinstall,
- .irq_postinstall = hdlcd_irq_postinstall,
- .irq_uninstall = hdlcd_irq_uninstall,
DRM_GEM_CMA_DRIVER_OPS,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = hdlcd_debugfs_init,
@@ -316,7 +334,7 @@ err_pm_active:
err_unload:
of_node_put(hdlcd->crtc.port);
hdlcd->crtc.port = NULL;
- drm_irq_uninstall(drm);
+ hdlcd_irq_uninstall(drm);
of_reserved_mem_device_release(drm->dev);
err_free:
drm_mode_config_cleanup(drm);
@@ -338,7 +356,7 @@ static void hdlcd_drm_unbind(struct device *dev)
hdlcd->crtc.port = NULL;
pm_runtime_get_sync(dev);
drm_atomic_helper_shutdown(drm);
- drm_irq_uninstall(drm);
+ hdlcd_irq_uninstall(drm);
pm_runtime_put(dev);
if (pm_runtime_enabled(dev))
pm_runtime_disable(dev);
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h
index fd438d177b64..909c39c28487 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.h
+++ b/drivers/gpu/drm/arm/hdlcd_drv.h
@@ -11,6 +11,7 @@ struct hdlcd_drm_private {
struct clk *clk;
struct drm_crtc crtc;
struct drm_plane *plane;
+ unsigned int irq;
#ifdef CONFIG_DEBUG_FS
atomic_t buffer_underrun_count;
atomic_t bus_error_count;
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index de59f3302516..78d15b04b105 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -847,8 +847,6 @@ static int malidp_bind(struct device *dev)
if (ret < 0)
goto irq_init_fail;
- drm->irq_enabled = true;
-
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n");
@@ -874,7 +872,6 @@ register_fail:
vblank_fail:
malidp_se_irq_fini(hwdev);
malidp_de_irq_fini(hwdev);
- drm->irq_enabled = false;
irq_init_fail:
drm_atomic_helper_shutdown(drm);
component_unbind_all(dev, drm);
@@ -909,7 +906,6 @@ static void malidp_unbind(struct device *dev)
drm_atomic_helper_shutdown(drm);
malidp_se_irq_fini(hwdev);
malidp_de_irq_fini(hwdev);
- drm->irq_enabled = false;
component_unbind_all(dev, drm);
of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL;
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index dab0a1f0983b..8e3e98f13db4 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -95,7 +95,7 @@ static int armada_drm_bind(struct device *dev)
}
/* Remove early framebuffers */
- ret = drm_aperture_remove_framebuffers(false, "armada-drm-fb");
+ ret = drm_aperture_remove_framebuffers(false, &armada_drm_driver);
if (ret) {
dev_err(dev, "[" DRM_NAME ":%s] can't kick out simple-fb: %d\n",
__func__, ret);
@@ -130,8 +130,6 @@ static int armada_drm_bind(struct device *dev)
if (ret)
goto err_comp;
- priv->drm.irq_enabled = true;
-
drm_mode_config_reset(&priv->drm);
ret = armada_fbdev_init(&priv->drm);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index d3e3e5fdc390..424250535fed 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -247,8 +247,6 @@ static void armada_drm_overlay_plane_atomic_disable(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs armada_overlay_plane_helper_funcs = {
- .prepare_fb = armada_drm_plane_prepare_fb,
- .cleanup_fb = armada_drm_plane_cleanup_fb,
.atomic_check = armada_drm_plane_atomic_check,
.atomic_update = armada_drm_overlay_plane_atomic_update,
.atomic_disable = armada_drm_overlay_plane_atomic_disable,
diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c
index 40209e49f34a..959d7f0a5108 100644
--- a/drivers/gpu/drm/armada/armada_plane.c
+++ b/drivers/gpu/drm/armada/armada_plane.c
@@ -78,33 +78,6 @@ void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
}
}
-int armada_drm_plane_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *state)
-{
- DRM_DEBUG_KMS("[PLANE:%d:%s] [FB:%d]\n",
- plane->base.id, plane->name,
- state->fb ? state->fb->base.id : 0);
-
- /*
- * Take a reference on the new framebuffer - we want to
- * hold on to it while the hardware is displaying it.
- */
- if (state->fb)
- drm_framebuffer_get(state->fb);
- return 0;
-}
-
-void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
- struct drm_plane_state *old_state)
-{
- DRM_DEBUG_KMS("[PLANE:%d:%s] [FB:%d]\n",
- plane->base.id, plane->name,
- old_state->fb ? old_state->fb->base.id : 0);
-
- if (old_state->fb)
- drm_framebuffer_put(old_state->fb);
-}
-
int armada_drm_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
@@ -282,8 +255,6 @@ static void armada_drm_primary_plane_atomic_disable(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs armada_primary_plane_helper_funcs = {
- .prepare_fb = armada_drm_plane_prepare_fb,
- .cleanup_fb = armada_drm_plane_cleanup_fb,
.atomic_check = armada_drm_plane_atomic_check,
.atomic_update = armada_drm_primary_plane_atomic_update,
.atomic_disable = armada_drm_primary_plane_atomic_disable,
diff --git a/drivers/gpu/drm/armada/armada_plane.h b/drivers/gpu/drm/armada/armada_plane.h
index 51dab8d8da22..368415c609a6 100644
--- a/drivers/gpu/drm/armada/armada_plane.h
+++ b/drivers/gpu/drm/armada/armada_plane.h
@@ -21,8 +21,6 @@ struct armada_plane_state {
void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
u16 pitches[3], bool interlaced);
-int armada_drm_plane_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *state);
void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state);
int armada_drm_plane_atomic_check(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c
index 098f96d4d50d..827e62c1daba 100644
--- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c
+++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c
@@ -220,7 +220,6 @@ static const struct drm_simple_display_pipe_funcs aspeed_gfx_funcs = {
.enable = aspeed_gfx_pipe_enable,
.disable = aspeed_gfx_pipe_disable,
.update = aspeed_gfx_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
.enable_vblank = aspeed_gfx_enable_vblank,
.disable_vblank = aspeed_gfx_disable_vblank,
};
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 5aa452b4efe6..86d5cd7b6318 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -100,7 +100,7 @@ static int ast_remove_conflicting_framebuffers(struct pci_dev *pdev)
primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
#endif
- return drm_aperture_remove_conflicting_framebuffers(base, size, primary, "astdrmfb");
+ return drm_aperture_remove_conflicting_framebuffers(base, size, primary, &ast_driver);
}
static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 911f9f414774..39ca338eb80b 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -337,6 +337,11 @@ int ast_mode_config_init(struct ast_private *ast);
#define AST_DP501_LINKRATE 0xf014
#define AST_DP501_EDID_DATA 0xf020
+/* Define for Soc scratched reg */
+#define AST_VRAM_INIT_STATUS_MASK GENMASK(7, 6)
+//#define AST_VRAM_INIT_BY_BMC BIT(7)
+//#define AST_VRAM_INIT_READY BIT(6)
+
int ast_mm_init(struct ast_private *ast);
/* ast post */
@@ -346,6 +351,7 @@ bool ast_is_vga_enabled(struct drm_device *dev);
void ast_post_gpu(struct drm_device *dev);
u32 ast_mindwm(struct ast_private *ast, u32 r);
void ast_moutdwm(struct ast_private *ast, u32 r, u32 v);
+void ast_patch_ahb_2500(struct ast_private *ast);
/* ast dp501 */
void ast_set_dp501_video_output(struct drm_device *dev, u8 mode);
bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 2aff2e6cf450..79a361867955 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -97,6 +97,11 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
+ /* Patch AST2500 */
+ if (((pdev->revision & 0xF0) == 0x40)
+ && ((jregd0 & AST_VRAM_INIT_STATUS_MASK) == 0))
+ ast_patch_ahb_2500(ast);
+
/* Double check it's actually working */
data = ast_read32(ast, 0xf004);
if ((data != 0xFFFFFFFF) && (data != 0x00)) {
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 36d9575aa27b..6bfaefa01818 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -275,7 +275,7 @@ static void ast_set_std_reg(struct ast_private *ast,
ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, stdtable->seq[0]);
for (i = 1; i < 4; i++) {
jreg = stdtable->seq[i];
- ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1) , jreg);
+ ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1), jreg);
}
/* Set CRTC; except base address and offset */
@@ -498,13 +498,15 @@ static void ast_set_sync_reg(struct ast_private *ast,
jreg = ast_io_read8(ast, AST_IO_MISC_PORT_READ);
jreg &= ~0xC0;
- if (vbios_mode->enh_table->flags & NVSync) jreg |= 0x80;
- if (vbios_mode->enh_table->flags & NHSync) jreg |= 0x40;
+ if (vbios_mode->enh_table->flags & NVSync)
+ jreg |= 0x80;
+ if (vbios_mode->enh_table->flags & NHSync)
+ jreg |= 0x40;
ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
}
static void ast_set_start_address_crt1(struct ast_private *ast,
- unsigned offset)
+ unsigned int offset)
{
u32 addr;
@@ -612,8 +614,7 @@ ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
- .prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
- .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
+ DRM_GEM_VRAM_PLANE_HELPER_FUNCS,
.atomic_check = ast_primary_plane_helper_atomic_check,
.atomic_update = ast_primary_plane_helper_atomic_update,
.atomic_disable = ast_primary_plane_helper_atomic_disable,
@@ -807,7 +808,7 @@ ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].map;
u64 dst_off =
ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].off;
- struct dma_buf_map src_map = shadow_plane_state->map[0];
+ struct dma_buf_map src_map = shadow_plane_state->data[0];
unsigned int offset_x, offset_y;
u16 x, y;
u8 x_offset, y_offset;
@@ -1212,6 +1213,7 @@ static int ast_get_modes(struct drm_connector *connector)
struct edid *edid;
int ret;
bool flags = false;
+
if (ast->tx_chip_type == AST_TX_DP501) {
ast->dp501_maxclk = 0xff;
edid = kmalloc(128, GFP_KERNEL);
@@ -1231,8 +1233,8 @@ static int ast_get_modes(struct drm_connector *connector)
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
return ret;
- } else
- drm_connector_update_edid_property(&ast_connector->base, NULL);
+ }
+ drm_connector_update_edid_property(&ast_connector->base, NULL);
return 0;
}
@@ -1272,19 +1274,24 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
}
switch (mode->hdisplay) {
case 640:
- if (mode->vdisplay == 480) flags = MODE_OK;
+ if (mode->vdisplay == 480)
+ flags = MODE_OK;
break;
case 800:
- if (mode->vdisplay == 600) flags = MODE_OK;
+ if (mode->vdisplay == 600)
+ flags = MODE_OK;
break;
case 1024:
- if (mode->vdisplay == 768) flags = MODE_OK;
+ if (mode->vdisplay == 768)
+ flags = MODE_OK;
break;
case 1280:
- if (mode->vdisplay == 1024) flags = MODE_OK;
+ if (mode->vdisplay == 1024)
+ flags = MODE_OK;
break;
case 1600:
- if (mode->vdisplay == 1200) flags = MODE_OK;
+ if (mode->vdisplay == 1200)
+ flags = MODE_OK;
break;
default:
return flags;
@@ -1293,9 +1300,22 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
return flags;
}
+static enum drm_connector_status ast_connector_detect(struct drm_connector
+ *connector, bool force)
+{
+ int r;
+
+ r = ast_get_modes(connector);
+ if (r <= 0)
+ return connector_status_disconnected;
+
+ return connector_status_connected;
+}
+
static void ast_connector_destroy(struct drm_connector *connector)
{
struct ast_connector *ast_connector = to_ast_connector(connector);
+
ast_i2c_destroy(ast_connector->i2c);
drm_connector_cleanup(connector);
}
@@ -1307,6 +1327,7 @@ static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
static const struct drm_connector_funcs ast_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
+ .detect = ast_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = ast_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -1334,7 +1355,8 @@ static int ast_connector_init(struct drm_device *dev)
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;
drm_connector_attach_encoder(connector, encoder);
@@ -1403,6 +1425,8 @@ int ast_mode_config_init(struct ast_private *ast)
drm_mode_config_reset(dev);
+ drm_kms_helper_poll_init(dev);
+
return 0;
}
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 0607658dde51..b5d92f652fd8 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -2028,6 +2028,40 @@ static bool ast_dram_init_2500(struct ast_private *ast)
return true;
}
+void ast_patch_ahb_2500(struct ast_private *ast)
+{
+ u32 data;
+
+ /* Clear bus lock condition */
+ ast_moutdwm(ast, 0x1e600000, 0xAEED1A03);
+ ast_moutdwm(ast, 0x1e600084, 0x00010000);
+ ast_moutdwm(ast, 0x1e600088, 0x00000000);
+ ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+ data = ast_mindwm(ast, 0x1e6e2070);
+ if (data & 0x08000000) { /* check fast reset */
+ /*
+ * If "Fast restet" is enabled for ARM-ICE debugger,
+ * then WDT needs to enable, that
+ * WDT04 is WDT#1 Reload reg.
+ * WDT08 is WDT#1 counter restart reg to avoid system deadlock
+ * WDT0C is WDT#1 control reg
+ * [6:5]:= 01:Full chip
+ * [4]:= 1:1MHz clock source
+ * [1]:= 1:WDT will be cleeared and disabled after timeout occurs
+ * [0]:= 1:WDT enable
+ */
+ ast_moutdwm(ast, 0x1E785004, 0x00000010);
+ ast_moutdwm(ast, 0x1E785008, 0x00004755);
+ ast_moutdwm(ast, 0x1E78500c, 0x00000033);
+ udelay(1000);
+ }
+ do {
+ ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
+ data = ast_mindwm(ast, 0x1e6e2000);
+ } while (data != 1);
+ ast_moutdwm(ast, 0x1e6e207c, 0x08000000); /* clear fast reset */
+}
+
void ast_post_chip_2500(struct drm_device *dev)
{
struct ast_private *ast = to_ast_private(dev);
@@ -2035,39 +2069,44 @@ void ast_post_chip_2500(struct drm_device *dev)
u8 reg;
reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
- if ((reg & 0x80) == 0) {/* vga only */
+ if ((reg & AST_VRAM_INIT_STATUS_MASK) == 0) {/* vga only */
/* Clear bus lock condition */
- ast_moutdwm(ast, 0x1e600000, 0xAEED1A03);
- ast_moutdwm(ast, 0x1e600084, 0x00010000);
- ast_moutdwm(ast, 0x1e600088, 0x00000000);
- ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8);
- ast_write32(ast, 0xf004, 0x1e6e0000);
- ast_write32(ast, 0xf000, 0x1);
- ast_write32(ast, 0x12000, 0x1688a8a8);
- while (ast_read32(ast, 0x12000) != 0x1)
- ;
-
- ast_write32(ast, 0x10000, 0xfc600309);
- while (ast_read32(ast, 0x10000) != 0x1)
- ;
+ ast_patch_ahb_2500(ast);
+
+ /* Disable watchdog */
+ ast_moutdwm(ast, 0x1E78502C, 0x00000000);
+ ast_moutdwm(ast, 0x1E78504C, 0x00000000);
+
+ /*
+ * Reset USB port to patch USB unknown device issue
+ * SCU90 is Multi-function Pin Control #5
+ * [29]:= 1:Enable USB2.0 Host port#1 (that the mutually shared USB2.0 Hub
+ * port).
+ * SCU94 is Multi-function Pin Control #6
+ * [14:13]:= 1x:USB2.0 Host2 controller
+ * SCU70 is Hardware Strap reg
+ * [23]:= 1:CLKIN is 25MHz and USBCK1 = 24/48 MHz (determined by
+ * [18]: 0(24)/1(48) MHz)
+ * SCU7C is Write clear reg to SCU70
+ * [23]:= write 1 and then SCU70[23] will be clear as 0b.
+ */
+ ast_moutdwm(ast, 0x1E6E2090, 0x20000000);
+ ast_moutdwm(ast, 0x1E6E2094, 0x00004000);
+ if (ast_mindwm(ast, 0x1E6E2070) & 0x00800000) {
+ ast_moutdwm(ast, 0x1E6E207C, 0x00800000);
+ mdelay(100);
+ ast_moutdwm(ast, 0x1E6E2070, 0x00800000);
+ }
+ /* Modify eSPI reset pin */
+ temp = ast_mindwm(ast, 0x1E6E2070);
+ if (temp & 0x02000000)
+ ast_moutdwm(ast, 0x1E6E207C, 0x00004000);
/* Slow down CPU/AHB CLK in VGA only mode */
temp = ast_read32(ast, 0x12008);
temp |= 0x73;
ast_write32(ast, 0x12008, temp);
- /* Reset USB port to patch USB unknown device issue */
- ast_moutdwm(ast, 0x1e6e2090, 0x20000000);
- temp = ast_mindwm(ast, 0x1e6e2094);
- temp |= 0x00004000;
- ast_moutdwm(ast, 0x1e6e2094, temp);
- temp = ast_mindwm(ast, 0x1e6e2070);
- if (temp & 0x00800000) {
- ast_moutdwm(ast, 0x1e6e207c, 0x00800000);
- mdelay(100);
- ast_moutdwm(ast, 0x1e6e2070, 0x00800000);
- }
-
if (!ast_dram_init_2500(ast))
drm_err(dev, "DRAM init failed !\n");
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index f09b6dd8754c..1656d27b78b6 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -22,7 +22,6 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
@@ -557,6 +556,51 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
+static void atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev)
+{
+ struct atmel_hlcdc_dc *dc = dev->dev_private;
+ unsigned int cfg = 0;
+ int i;
+
+ /* Enable interrupts on activated layers */
+ for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
+ if (dc->layers[i])
+ cfg |= ATMEL_HLCDC_LAYER_STATUS(i);
+ }
+
+ regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, cfg);
+}
+
+static void atmel_hlcdc_dc_irq_disable(struct drm_device *dev)
+{
+ struct atmel_hlcdc_dc *dc = dev->dev_private;
+ unsigned int isr;
+
+ regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, 0xffffffff);
+ regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
+}
+
+static int atmel_hlcdc_dc_irq_install(struct drm_device *dev, unsigned int irq)
+{
+ int ret;
+
+ atmel_hlcdc_dc_irq_disable(dev);
+
+ ret = devm_request_irq(dev->dev, irq, atmel_hlcdc_dc_irq_handler, 0,
+ dev->driver->name, dev);
+ if (ret)
+ return ret;
+
+ atmel_hlcdc_dc_irq_postinstall(dev);
+
+ return 0;
+}
+
+static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
+{
+ atmel_hlcdc_dc_irq_disable(dev);
+}
+
static const struct drm_mode_config_funcs mode_config_funcs = {
.fb_create = drm_gem_fb_create,
.atomic_check = drm_atomic_helper_check,
@@ -647,7 +691,7 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
drm_mode_config_reset(dev);
pm_runtime_get_sync(dev->dev);
- ret = drm_irq_install(dev, dc->hlcdc->irq);
+ ret = atmel_hlcdc_dc_irq_install(dev, dc->hlcdc->irq);
pm_runtime_put_sync(dev->dev);
if (ret < 0) {
dev_err(dev->dev, "failed to install IRQ handler\n");
@@ -676,7 +720,7 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
drm_mode_config_cleanup(dev);
pm_runtime_get_sync(dev->dev);
- drm_irq_uninstall(dev);
+ atmel_hlcdc_dc_irq_uninstall(dev);
pm_runtime_put_sync(dev->dev);
dev->dev_private = NULL;
@@ -685,40 +729,10 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
clk_disable_unprepare(dc->hlcdc->periph_clk);
}
-static int atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev)
-{
- struct atmel_hlcdc_dc *dc = dev->dev_private;
- unsigned int cfg = 0;
- int i;
-
- /* Enable interrupts on activated layers */
- for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
- if (dc->layers[i])
- cfg |= ATMEL_HLCDC_LAYER_STATUS(i);
- }
-
- regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, cfg);
-
- return 0;
-}
-
-static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
-{
- struct atmel_hlcdc_dc *dc = dev->dev_private;
- unsigned int isr;
-
- regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, 0xffffffff);
- regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
-}
-
DEFINE_DRM_GEM_CMA_FOPS(fops);
static const struct drm_driver atmel_hlcdc_dc_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
- .irq_handler = atmel_hlcdc_dc_irq_handler,
- .irq_preinstall = atmel_hlcdc_dc_irq_uninstall,
- .irq_postinstall = atmel_hlcdc_dc_irq_postinstall,
- .irq_uninstall = atmel_hlcdc_dc_irq_uninstall,
DRM_GEM_CMA_DRIVER_OPS,
.fops = &fops,
.name = "atmel-hlcdc",
diff --git a/drivers/gpu/drm/bochs/Kconfig b/drivers/gpu/drm/bochs/Kconfig
deleted file mode 100644
index 7bcdf294fed8..000000000000
--- a/drivers/gpu/drm/bochs/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config DRM_BOCHS
- tristate "DRM Support for bochs dispi vga interface (qemu stdvga)"
- depends on DRM && PCI && MMU
- select DRM_KMS_HELPER
- select DRM_VRAM_HELPER
- select DRM_TTM
- select DRM_TTM_HELPER
- help
- Choose this option for qemu.
- If M is selected the module will be called bochs-drm.
diff --git a/drivers/gpu/drm/bochs/Makefile b/drivers/gpu/drm/bochs/Makefile
deleted file mode 100644
index 55473371300f..000000000000
--- a/drivers/gpu/drm/bochs/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_hw.o
-
-obj-$(CONFIG_DRM_BOCHS) += bochs-drm.o
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
deleted file mode 100644
index e9645c612aff..000000000000
--- a/drivers/gpu/drm/bochs/bochs.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#include <linux/io.h>
-#include <linux/console.h>
-
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_encoder.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_gem.h>
-#include <drm/drm_gem_vram_helper.h>
-#include <drm/drm_simple_kms_helper.h>
-
-/* ---------------------------------------------------------------------- */
-
-#define VBE_DISPI_IOPORT_INDEX 0x01CE
-#define VBE_DISPI_IOPORT_DATA 0x01CF
-
-#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_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
-
-/* ---------------------------------------------------------------------- */
-
-enum bochs_types {
- BOCHS_QEMU_STDVGA,
- BOCHS_UNKNOWN,
-};
-
-struct bochs_device {
- /* hw */
- void __iomem *mmio;
- int ioports;
- void __iomem *fb_map;
- unsigned long fb_base;
- unsigned long fb_size;
- unsigned long qext_size;
-
- /* mode */
- u16 xres;
- u16 yres;
- u16 yres_virtual;
- u32 stride;
- u32 bpp;
- struct edid *edid;
-
- /* drm */
- struct drm_device *dev;
- struct drm_simple_display_pipe pipe;
- struct drm_connector connector;
-};
-
-/* ---------------------------------------------------------------------- */
-
-/* bochs_hw.c */
-int bochs_hw_init(struct drm_device *dev);
-void bochs_hw_fini(struct drm_device *dev);
-
-void bochs_hw_blank(struct bochs_device *bochs, bool blank);
-void bochs_hw_setmode(struct bochs_device *bochs,
- struct drm_display_mode *mode);
-void bochs_hw_setformat(struct bochs_device *bochs,
- const struct drm_format_info *format);
-void bochs_hw_setbase(struct bochs_device *bochs,
- int x, int y, int stride, u64 addr);
-int bochs_hw_load_edid(struct bochs_device *bochs);
-
-/* bochs_mm.c */
-int bochs_mm_init(struct bochs_device *bochs);
-void bochs_mm_fini(struct bochs_device *bochs);
-
-/* bochs_kms.c */
-int bochs_kms_init(struct bochs_device *bochs);
-
-/* bochs_fbdev.c */
-extern const struct drm_mode_config_funcs bochs_mode_funcs;
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
deleted file mode 100644
index c828cadbabff..000000000000
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ /dev/null
@@ -1,205 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <drm/drm_drv.h>
-#include <drm/drm_aperture.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_managed.h>
-
-#include "bochs.h"
-
-static int bochs_modeset = -1;
-module_param_named(modeset, bochs_modeset, int, 0444);
-MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
-
-/* ---------------------------------------------------------------------- */
-/* drm interface */
-
-static void bochs_unload(struct drm_device *dev)
-{
- struct bochs_device *bochs = dev->dev_private;
-
- bochs_mm_fini(bochs);
-}
-
-static int bochs_load(struct drm_device *dev)
-{
- struct bochs_device *bochs;
- int ret;
-
- bochs = drmm_kzalloc(dev, sizeof(*bochs), GFP_KERNEL);
- if (bochs == NULL)
- return -ENOMEM;
- dev->dev_private = bochs;
- bochs->dev = dev;
-
- ret = bochs_hw_init(dev);
- if (ret)
- goto err;
-
- ret = bochs_mm_init(bochs);
- if (ret)
- goto err;
-
- ret = bochs_kms_init(bochs);
- if (ret)
- goto err;
-
- return 0;
-
-err:
- bochs_unload(dev);
- return ret;
-}
-
-DEFINE_DRM_GEM_FOPS(bochs_fops);
-
-static const struct drm_driver bochs_driver = {
- .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
- .fops = &bochs_fops,
- .name = "bochs-drm",
- .desc = "bochs dispi vga interface (qemu stdvga)",
- .date = "20130925",
- .major = 1,
- .minor = 0,
- DRM_GEM_VRAM_DRIVER,
- .release = bochs_unload,
-};
-
-/* ---------------------------------------------------------------------- */
-/* pm interface */
-
-#ifdef CONFIG_PM_SLEEP
-static int bochs_pm_suspend(struct device *dev)
-{
- struct drm_device *drm_dev = dev_get_drvdata(dev);
-
- return drm_mode_config_helper_suspend(drm_dev);
-}
-
-static int bochs_pm_resume(struct device *dev)
-{
- struct drm_device *drm_dev = dev_get_drvdata(dev);
-
- return drm_mode_config_helper_resume(drm_dev);
-}
-#endif
-
-static const struct dev_pm_ops bochs_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
- bochs_pm_resume)
-};
-
-/* ---------------------------------------------------------------------- */
-/* pci interface */
-
-static int bochs_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct drm_device *dev;
- unsigned long fbsize;
- int ret;
-
- fbsize = pci_resource_len(pdev, 0);
- if (fbsize < 4 * 1024 * 1024) {
- DRM_ERROR("less than 4 MB video memory, ignoring device\n");
- return -ENOMEM;
- }
-
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "bochsdrmfb");
- if (ret)
- return ret;
-
- dev = drm_dev_alloc(&bochs_driver, &pdev->dev);
- if (IS_ERR(dev))
- return PTR_ERR(dev);
-
- ret = pci_enable_device(pdev);
- if (ret)
- goto err_free_dev;
-
- pci_set_drvdata(pdev, dev);
-
- ret = bochs_load(dev);
- if (ret)
- goto err_free_dev;
-
- ret = drm_dev_register(dev, 0);
- if (ret)
- goto err_unload;
-
- drm_fbdev_generic_setup(dev, 32);
- return ret;
-
-err_unload:
- bochs_unload(dev);
-err_free_dev:
- drm_dev_put(dev);
- return ret;
-}
-
-static void bochs_pci_remove(struct pci_dev *pdev)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
-
- drm_dev_unplug(dev);
- drm_atomic_helper_shutdown(dev);
- bochs_hw_fini(dev);
- drm_dev_put(dev);
-}
-
-static const struct pci_device_id bochs_pci_tbl[] = {
- {
- .vendor = 0x1234,
- .device = 0x1111,
- .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
- .subdevice = PCI_SUBDEVICE_ID_QEMU,
- .driver_data = BOCHS_QEMU_STDVGA,
- },
- {
- .vendor = 0x1234,
- .device = 0x1111,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = BOCHS_UNKNOWN,
- },
- { /* end of list */ }
-};
-
-static struct pci_driver bochs_pci_driver = {
- .name = "bochs-drm",
- .id_table = bochs_pci_tbl,
- .probe = bochs_pci_probe,
- .remove = bochs_pci_remove,
- .driver.pm = &bochs_pm_ops,
-};
-
-/* ---------------------------------------------------------------------- */
-/* module init/exit */
-
-static int __init bochs_init(void)
-{
- if (vgacon_text_force() && bochs_modeset == -1)
- return -EINVAL;
-
- if (bochs_modeset == 0)
- return -EINVAL;
-
- return pci_register_driver(&bochs_pci_driver);
-}
-
-static void __exit bochs_exit(void)
-{
- pci_unregister_driver(&bochs_pci_driver);
-}
-
-module_init(bochs_init);
-module_exit(bochs_exit);
-
-MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
-MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c
deleted file mode 100644
index 7d3426d8cc69..000000000000
--- a/drivers/gpu/drm/bochs/bochs_hw.c
+++ /dev/null
@@ -1,323 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- */
-
-#include <linux/pci.h>
-
-#include <drm/drm_drv.h>
-#include <drm/drm_fourcc.h>
-
-#include <video/vga.h>
-#include "bochs.h"
-
-/* ---------------------------------------------------------------------- */
-
-static void bochs_vga_writeb(struct bochs_device *bochs, u16 ioport, u8 val)
-{
- if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
- return;
-
- if (bochs->mmio) {
- int offset = ioport - 0x3c0 + 0x400;
- writeb(val, bochs->mmio + offset);
- } else {
- outb(val, ioport);
- }
-}
-
-static u8 bochs_vga_readb(struct bochs_device *bochs, u16 ioport)
-{
- if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
- return 0xff;
-
- if (bochs->mmio) {
- int offset = ioport - 0x3c0 + 0x400;
- return readb(bochs->mmio + offset);
- } else {
- return inb(ioport);
- }
-}
-
-static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
-{
- u16 ret = 0;
-
- if (bochs->mmio) {
- int offset = 0x500 + (reg << 1);
- ret = readw(bochs->mmio + offset);
- } else {
- outw(reg, VBE_DISPI_IOPORT_INDEX);
- ret = inw(VBE_DISPI_IOPORT_DATA);
- }
- return ret;
-}
-
-static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
-{
- if (bochs->mmio) {
- int offset = 0x500 + (reg << 1);
- writew(val, bochs->mmio + offset);
- } else {
- outw(reg, VBE_DISPI_IOPORT_INDEX);
- outw(val, VBE_DISPI_IOPORT_DATA);
- }
-}
-
-static void bochs_hw_set_big_endian(struct bochs_device *bochs)
-{
- if (bochs->qext_size < 8)
- return;
-
- writel(0xbebebebe, bochs->mmio + 0x604);
-}
-
-static void bochs_hw_set_little_endian(struct bochs_device *bochs)
-{
- if (bochs->qext_size < 8)
- return;
-
- writel(0x1e1e1e1e, bochs->mmio + 0x604);
-}
-
-#ifdef __BIG_ENDIAN
-#define bochs_hw_set_native_endian(_b) bochs_hw_set_big_endian(_b)
-#else
-#define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b)
-#endif
-
-static int bochs_get_edid_block(void *data, u8 *buf,
- unsigned int block, size_t len)
-{
- struct bochs_device *bochs = data;
- size_t i, start = block * EDID_LENGTH;
-
- if (start + len > 0x400 /* vga register offset */)
- return -1;
-
- for (i = 0; i < len; i++) {
- buf[i] = readb(bochs->mmio + start + i);
- }
- return 0;
-}
-
-int bochs_hw_load_edid(struct bochs_device *bochs)
-{
- u8 header[8];
-
- if (!bochs->mmio)
- return -1;
-
- /* check header to detect whenever edid support is enabled in qemu */
- bochs_get_edid_block(bochs, header, 0, ARRAY_SIZE(header));
- if (drm_edid_header_is_valid(header) != 8)
- return -1;
-
- kfree(bochs->edid);
- bochs->edid = drm_do_get_edid(&bochs->connector,
- bochs_get_edid_block, bochs);
- if (bochs->edid == NULL)
- return -1;
-
- return 0;
-}
-
-int bochs_hw_init(struct drm_device *dev)
-{
- struct bochs_device *bochs = dev->dev_private;
- struct pci_dev *pdev = to_pci_dev(dev->dev);
- unsigned long addr, size, mem, ioaddr, iosize;
- u16 id;
-
- if (pdev->resource[2].flags & IORESOURCE_MEM) {
- /* mmio bar with vga and bochs registers present */
- if (pci_request_region(pdev, 2, "bochs-drm") != 0) {
- DRM_ERROR("Cannot request mmio region\n");
- return -EBUSY;
- }
- ioaddr = pci_resource_start(pdev, 2);
- iosize = pci_resource_len(pdev, 2);
- bochs->mmio = ioremap(ioaddr, iosize);
- if (bochs->mmio == NULL) {
- DRM_ERROR("Cannot map mmio region\n");
- return -ENOMEM;
- }
- } else {
- ioaddr = VBE_DISPI_IOPORT_INDEX;
- iosize = 2;
- if (!request_region(ioaddr, iosize, "bochs-drm")) {
- DRM_ERROR("Cannot request ioports\n");
- return -EBUSY;
- }
- bochs->ioports = 1;
- }
-
- id = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID);
- mem = bochs_dispi_read(bochs, VBE_DISPI_INDEX_VIDEO_MEMORY_64K)
- * 64 * 1024;
- if ((id & 0xfff0) != VBE_DISPI_ID0) {
- DRM_ERROR("ID mismatch\n");
- return -ENODEV;
- }
-
- if ((pdev->resource[0].flags & IORESOURCE_MEM) == 0)
- return -ENODEV;
- addr = pci_resource_start(pdev, 0);
- size = pci_resource_len(pdev, 0);
- if (addr == 0)
- return -ENODEV;
- if (size != mem) {
- DRM_ERROR("Size mismatch: pci=%ld, bochs=%ld\n",
- size, mem);
- size = min(size, mem);
- }
-
- if (pci_request_region(pdev, 0, "bochs-drm") != 0)
- DRM_WARN("Cannot request framebuffer, boot fb still active?\n");
-
- bochs->fb_map = ioremap(addr, size);
- if (bochs->fb_map == NULL) {
- DRM_ERROR("Cannot map framebuffer\n");
- return -ENOMEM;
- }
- bochs->fb_base = addr;
- bochs->fb_size = size;
-
- DRM_INFO("Found bochs VGA, ID 0x%x.\n", id);
- DRM_INFO("Framebuffer size %ld kB @ 0x%lx, %s @ 0x%lx.\n",
- size / 1024, addr,
- bochs->ioports ? "ioports" : "mmio",
- ioaddr);
-
- if (bochs->mmio && pdev->revision >= 2) {
- bochs->qext_size = readl(bochs->mmio + 0x600);
- if (bochs->qext_size < 4 || bochs->qext_size > iosize) {
- bochs->qext_size = 0;
- goto noext;
- }
- DRM_DEBUG("Found qemu ext regs, size %ld\n",
- bochs->qext_size);
- bochs_hw_set_native_endian(bochs);
- }
-
-noext:
- return 0;
-}
-
-void bochs_hw_fini(struct drm_device *dev)
-{
- struct bochs_device *bochs = dev->dev_private;
-
- /* TODO: shot down existing vram mappings */
-
- if (bochs->mmio)
- iounmap(bochs->mmio);
- if (bochs->ioports)
- release_region(VBE_DISPI_IOPORT_INDEX, 2);
- if (bochs->fb_map)
- iounmap(bochs->fb_map);
- pci_release_regions(to_pci_dev(dev->dev));
- kfree(bochs->edid);
-}
-
-void bochs_hw_blank(struct bochs_device *bochs, bool blank)
-{
- DRM_DEBUG_DRIVER("hw_blank %d\n", blank);
- /* discard ar_flip_flop */
- (void)bochs_vga_readb(bochs, VGA_IS1_RC);
- /* blank or unblank; we need only update index and set 0x20 */
- bochs_vga_writeb(bochs, VGA_ATT_W, blank ? 0 : 0x20);
-}
-
-void bochs_hw_setmode(struct bochs_device *bochs,
- struct drm_display_mode *mode)
-{
- int idx;
-
- if (!drm_dev_enter(bochs->dev, &idx))
- return;
-
- bochs->xres = mode->hdisplay;
- bochs->yres = mode->vdisplay;
- bochs->bpp = 32;
- bochs->stride = mode->hdisplay * (bochs->bpp / 8);
- bochs->yres_virtual = bochs->fb_size / bochs->stride;
-
- DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n",
- bochs->xres, bochs->yres, bochs->bpp,
- bochs->yres_virtual);
-
- bochs_hw_blank(bochs, false);
-
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE, 0);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_BPP, bochs->bpp);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_XRES, bochs->xres);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_YRES, bochs->yres);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_BANK, 0);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH, bochs->xres);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_HEIGHT,
- bochs->yres_virtual);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, 0);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, 0);
-
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
- VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
-
- drm_dev_exit(idx);
-}
-
-void bochs_hw_setformat(struct bochs_device *bochs,
- const struct drm_format_info *format)
-{
- int idx;
-
- if (!drm_dev_enter(bochs->dev, &idx))
- return;
-
- DRM_DEBUG_DRIVER("format %c%c%c%c\n",
- (format->format >> 0) & 0xff,
- (format->format >> 8) & 0xff,
- (format->format >> 16) & 0xff,
- (format->format >> 24) & 0xff);
-
- switch (format->format) {
- case DRM_FORMAT_XRGB8888:
- bochs_hw_set_little_endian(bochs);
- break;
- case DRM_FORMAT_BGRX8888:
- bochs_hw_set_big_endian(bochs);
- break;
- default:
- /* should not happen */
- DRM_ERROR("%s: Huh? Got framebuffer format 0x%x",
- __func__, format->format);
- break;
- }
-
- drm_dev_exit(idx);
-}
-
-void bochs_hw_setbase(struct bochs_device *bochs,
- int x, int y, int stride, u64 addr)
-{
- unsigned long offset;
- unsigned int vx, vy, vwidth, idx;
-
- if (!drm_dev_enter(bochs->dev, &idx))
- return;
-
- bochs->stride = stride;
- offset = (unsigned long)addr +
- y * bochs->stride +
- x * (bochs->bpp / 8);
- vy = offset / bochs->stride;
- vx = (offset % bochs->stride) * 8 / bochs->bpp;
- vwidth = stride * 8 / bochs->bpp;
-
- DRM_DEBUG_DRIVER("x %d, y %d, addr %llx -> offset %lx, vx %d, vy %d\n",
- x, y, addr, offset, vx, vy);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH, vwidth);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, vx);
- bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, vy);
-
- drm_dev_exit(idx);
-}
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
deleted file mode 100644
index 99410e77d51a..000000000000
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ /dev/null
@@ -1,178 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- */
-
-#include <linux/moduleparam.h>
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_probe_helper.h>
-
-#include "bochs.h"
-
-static int defx = 1024;
-static int defy = 768;
-
-module_param(defx, int, 0444);
-module_param(defy, int, 0444);
-MODULE_PARM_DESC(defx, "default x resolution");
-MODULE_PARM_DESC(defy, "default y resolution");
-
-/* ---------------------------------------------------------------------- */
-
-static const uint32_t bochs_formats[] = {
- DRM_FORMAT_XRGB8888,
- DRM_FORMAT_BGRX8888,
-};
-
-static void bochs_plane_update(struct bochs_device *bochs,
- struct drm_plane_state *state)
-{
- struct drm_gem_vram_object *gbo;
- s64 gpu_addr;
-
- if (!state->fb || !bochs->stride)
- return;
-
- gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
- gpu_addr = drm_gem_vram_offset(gbo);
- if (WARN_ON_ONCE(gpu_addr < 0))
- return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
-
- bochs_hw_setbase(bochs,
- state->crtc_x,
- state->crtc_y,
- state->fb->pitches[0],
- state->fb->offsets[0] + gpu_addr);
- bochs_hw_setformat(bochs, state->fb->format);
-}
-
-static void bochs_pipe_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
-{
- struct bochs_device *bochs = pipe->crtc.dev->dev_private;
-
- bochs_hw_setmode(bochs, &crtc_state->mode);
- bochs_plane_update(bochs, plane_state);
-}
-
-static void bochs_pipe_disable(struct drm_simple_display_pipe *pipe)
-{
- struct bochs_device *bochs = pipe->crtc.dev->dev_private;
-
- bochs_hw_blank(bochs, true);
-}
-
-static void bochs_pipe_update(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *old_state)
-{
- struct bochs_device *bochs = pipe->crtc.dev->dev_private;
-
- bochs_plane_update(bochs, pipe->plane.state);
-}
-
-static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {
- .enable = bochs_pipe_enable,
- .disable = bochs_pipe_disable,
- .update = bochs_pipe_update,
- .prepare_fb = drm_gem_vram_simple_display_pipe_prepare_fb,
- .cleanup_fb = drm_gem_vram_simple_display_pipe_cleanup_fb,
-};
-
-static int bochs_connector_get_modes(struct drm_connector *connector)
-{
- struct bochs_device *bochs =
- container_of(connector, struct bochs_device, connector);
- int count = 0;
-
- if (bochs->edid)
- count = drm_add_edid_modes(connector, bochs->edid);
-
- if (!count) {
- count = drm_add_modes_noedid(connector, 8192, 8192);
- drm_set_preferred_mode(connector, defx, defy);
- }
- return count;
-}
-
-static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
- .get_modes = bochs_connector_get_modes,
-};
-
-static const struct drm_connector_funcs bochs_connector_connector_funcs = {
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .reset = drm_atomic_helper_connector_reset,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static void bochs_connector_init(struct drm_device *dev)
-{
- struct bochs_device *bochs = dev->dev_private;
- struct drm_connector *connector = &bochs->connector;
-
- drm_connector_init(dev, connector, &bochs_connector_connector_funcs,
- DRM_MODE_CONNECTOR_VIRTUAL);
- drm_connector_helper_add(connector,
- &bochs_connector_connector_helper_funcs);
-
- bochs_hw_load_edid(bochs);
- if (bochs->edid) {
- DRM_INFO("Found EDID data blob.\n");
- drm_connector_attach_edid_property(connector);
- drm_connector_update_edid_property(connector, bochs->edid);
- }
-}
-
-static struct drm_framebuffer *
-bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
- const struct drm_mode_fb_cmd2 *mode_cmd)
-{
- if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
- mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
- return ERR_PTR(-EINVAL);
-
- return drm_gem_fb_create(dev, file, mode_cmd);
-}
-
-const struct drm_mode_config_funcs bochs_mode_funcs = {
- .fb_create = bochs_gem_fb_create,
- .mode_valid = drm_vram_helper_mode_valid,
- .atomic_check = drm_atomic_helper_check,
- .atomic_commit = drm_atomic_helper_commit,
-};
-
-int bochs_kms_init(struct bochs_device *bochs)
-{
- int ret;
-
- ret = drmm_mode_config_init(bochs->dev);
- if (ret)
- return ret;
-
- bochs->dev->mode_config.max_width = 8192;
- bochs->dev->mode_config.max_height = 8192;
-
- bochs->dev->mode_config.fb_base = bochs->fb_base;
- bochs->dev->mode_config.preferred_depth = 24;
- bochs->dev->mode_config.prefer_shadow = 0;
- bochs->dev->mode_config.prefer_shadow_fbdev = 1;
- bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
-
- bochs->dev->mode_config.funcs = &bochs_mode_funcs;
-
- bochs_connector_init(bochs->dev);
- drm_simple_display_pipe_init(bochs->dev,
- &bochs->pipe,
- &bochs_pipe_funcs,
- bochs_formats,
- ARRAY_SIZE(bochs_formats),
- NULL,
- &bochs->connector);
-
- drm_mode_config_reset(bochs->dev);
-
- return 0;
-}
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
deleted file mode 100644
index 1b74f530b07c..000000000000
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- */
-
-#include "bochs.h"
-
-/* ---------------------------------------------------------------------- */
-
-int bochs_mm_init(struct bochs_device *bochs)
-{
- struct drm_vram_mm *vmm;
-
- vmm = drm_vram_helper_alloc_mm(bochs->dev, bochs->fb_base,
- bochs->fb_size);
- return PTR_ERR_OR_ZERO(vmm);
-}
-
-void bochs_mm_fini(struct bochs_device *bochs)
-{
- if (!bochs->dev->vram_mm)
- return;
-
- drm_vram_helper_release_mm(bochs->dev);
-}
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 85b673613687..431b6e12a81f 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -303,6 +303,7 @@ config DRM_TI_SN65DSI86
select DRM_PANEL
select DRM_MIPI_DSI
select AUXILIARY_BUS
+ select DRM_DP_AUX_BUS
help
Texas Instruments SN65DSI86 DSI to eDP Bridge driver
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c
index aa19d5a40e31..59d718bde8c4 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c
@@ -165,7 +165,7 @@ int adv7533_attach_dsi(struct adv7511 *adv)
dsi->lanes = adv->num_dsi_lanes;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
+ MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 550814ca2139..b7d2e4449cfa 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1583,7 +1583,6 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
struct analogix_dp_device *dp)
{
struct drm_bridge *bridge;
- int ret;
bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL);
if (!bridge) {
@@ -1596,13 +1595,7 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
bridge->driver_private = dp;
bridge->funcs = &analogix_dp_bridge_funcs;
- ret = drm_bridge_attach(dp->encoder, bridge, NULL, 0);
- if (ret) {
- DRM_ERROR("failed to attach drm bridge\n");
- return -EINVAL;
- }
-
- return 0;
+ return drm_bridge_attach(dp->encoder, bridge, NULL, 0);
}
static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp)
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 7519b7a0f29d..14d73fb1dd15 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -384,6 +384,25 @@ static int anx7625_odfc_config(struct anx7625_data *ctx,
return ret;
}
+/*
+ * The MIPI source video data exist large variation (e.g. 59Hz ~ 61Hz),
+ * anx7625 defined K ratio for matching MIPI input video clock and
+ * DP output video clock. Increase K value can match bigger video data
+ * variation. IVO panel has small variation than DP CTS spec, need
+ * decrease the K value.
+ */
+static int anx7625_set_k_value(struct anx7625_data *ctx)
+{
+ struct edid *edid = (struct edid *)ctx->slimport_edid_p.edid_raw_data;
+
+ if (edid->mfg_id[0] == IVO_MID0 && edid->mfg_id[1] == IVO_MID1)
+ return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+ MIPI_DIGITAL_ADJ_1, 0x3B);
+
+ return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+ MIPI_DIGITAL_ADJ_1, 0x3D);
+}
+
static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
{
struct device *dev = &ctx->client->dev;
@@ -470,9 +489,8 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
MIPI_PLL_N_NUM_15_8, (n >> 8) & 0xff);
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client, MIPI_PLL_N_NUM_7_0,
(n & 0xff));
- /* Diff */
- ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
- MIPI_DIGITAL_ADJ_1, 0x3D);
+
+ anx7625_set_k_value(ctx);
ret |= anx7625_odfc_config(ctx, post_divider - 1);
@@ -1307,7 +1325,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_EOT_PACKET |
+ MIPI_DSI_MODE_NO_EOT_PACKET |
MIPI_DSI_MODE_VIDEO_HSE;
if (mipi_dsi_attach(dsi) < 0) {
@@ -1359,11 +1377,8 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
err = drm_bridge_attach(bridge->encoder,
ctx->pdata.panel_bridge,
&ctx->bridge, flags);
- if (err) {
- DRM_DEV_ERROR(dev,
- "Fail to attach panel bridge: %d\n", err);
+ if (err)
return err;
- }
}
ctx->bridge_attached = 1;
@@ -1730,7 +1745,6 @@ static int __maybe_unused anx7625_suspend(struct device *dev)
if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
anx7625_runtime_pm_suspend(dev);
disable_irq(ctx->pdata.intp_irq);
- flush_workqueue(ctx->workqueue);
}
return 0;
@@ -1790,7 +1804,8 @@ static int anx7625_i2c_probe(struct i2c_client *client,
platform->pdata.intp_irq = client->irq;
if (platform->pdata.intp_irq) {
INIT_WORK(&platform->work, anx7625_work_func);
- platform->workqueue = create_workqueue("anx7625_work");
+ platform->workqueue = alloc_workqueue("anx7625_work",
+ WQ_FREEZABLE | WQ_MEM_RECLAIM, 1);
if (!platform->workqueue) {
DRM_DEV_ERROR(dev, "fail to create work queue\n");
ret = -ENOMEM;
@@ -1874,6 +1889,7 @@ static const struct of_device_id anx_match_table[] = {
{.compatible = "analogix,anx7625",},
{},
};
+MODULE_DEVICE_TABLE(of, anx_match_table);
static struct i2c_driver anx7625_driver = {
.driver = {
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 034c3840028f..6dcf64c703f9 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -210,7 +210,9 @@
#define MIPI_VIDEO_STABLE_CNT 0x0A
#define MIPI_LANE_CTRL_10 0x0F
-#define MIPI_DIGITAL_ADJ_1 0x1B
+#define MIPI_DIGITAL_ADJ_1 0x1B
+#define IVO_MID0 0x26
+#define IVO_MID1 0xCF
#define MIPI_PLL_M_NUM_23_16 0x1E
#define MIPI_PLL_M_NUM_15_8 0x1F
diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c
index b31281f76117..e6e331071a00 100644
--- a/drivers/gpu/drm/bridge/cdns-dsi.c
+++ b/drivers/gpu/drm/bridge/cdns-dsi.c
@@ -829,7 +829,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
tmp = DIV_ROUND_UP(dsi_cfg.htotal, nlanes) -
DIV_ROUND_UP(dsi_cfg.hsa, nlanes);
- if (!(output->dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+ if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes);
tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
@@ -902,7 +902,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
tmp = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
tmp &= ~(IF_VID_SELECT_MASK | HOST_EOT_GEN | IF_VID_MODE);
- if (!(output->dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+ if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
tmp |= HOST_EOT_GEN;
if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO)
diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c
index 7149ed40af83..2f2a09adb4bc 100644
--- a/drivers/gpu/drm/bridge/ite-it66121.c
+++ b/drivers/gpu/drm/bridge/ite-it66121.c
@@ -536,6 +536,8 @@ static int it66121_bridge_attach(struct drm_bridge *bridge,
return -EINVAL;
ret = drm_bridge_attach(bridge->encoder, ctx->next_bridge, bridge, flags);
+ if (ret)
+ return ret;
ret = regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG,
IT66121_CLK_BANK_PWROFF_RCLK, 0);
diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
index 76c720b535fb..1b0c7eaf6c84 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
@@ -487,7 +487,7 @@ static int lt8912_attach_dsi(struct lt8912 *lt)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM |
- MIPI_DSI_MODE_EOT_PACKET;
+ MIPI_DSI_MODE_NO_EOT_PACKET;
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
index 873995f0a741..ed8ac5059cd2 100644
--- a/drivers/gpu/drm/bridge/nwl-dsi.c
+++ b/drivers/gpu/drm/bridge/nwl-dsi.c
@@ -48,12 +48,6 @@ enum transfer_direction {
#define NWL_DSI_ENDPOINT_LCDIF 0
#define NWL_DSI_ENDPOINT_DCSS 1
-struct nwl_dsi_plat_clk_config {
- const char *id;
- struct clk *clk;
- bool present;
-};
-
struct nwl_dsi_transfer {
const struct mipi_dsi_msg *msg;
struct mipi_dsi_packet packet;
@@ -196,7 +190,7 @@ static u32 ps2bc(struct nwl_dsi *dsi, unsigned long long ps)
u32 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
return DIV64_U64_ROUND_UP(ps * dsi->mode.clock * bpp,
- dsi->lanes * 8 * NSEC_PER_SEC);
+ dsi->lanes * 8ULL * NSEC_PER_SEC);
}
/*
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index e7c7c9b9c646..f08d0fded61f 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -143,6 +143,7 @@ struct dw_hdmi_phy_data {
struct dw_hdmi {
struct drm_connector connector;
struct drm_bridge bridge;
+ struct drm_bridge *next_bridge;
unsigned int version;
@@ -2775,7 +2776,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
struct dw_hdmi *hdmi = bridge->driver_private;
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
- return 0;
+ return drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
+ bridge, flags);
return dw_hdmi_connector_create(hdmi);
}
@@ -3160,6 +3162,52 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi)
/* -----------------------------------------------------------------------------
* Probe/remove API, used from platforms based on the DRM bridge API.
*/
+
+static int dw_hdmi_parse_dt(struct dw_hdmi *hdmi)
+{
+ struct device_node *endpoint;
+ struct device_node *remote;
+
+ if (!hdmi->plat_data->output_port)
+ return 0;
+
+ endpoint = of_graph_get_endpoint_by_regs(hdmi->dev->of_node,
+ hdmi->plat_data->output_port,
+ -1);
+ if (!endpoint) {
+ /*
+ * On platforms whose bindings don't make the output port
+ * mandatory (such as Rockchip) the plat_data->output_port
+ * field isn't set, so it's safe to make this a fatal error.
+ */
+ dev_err(hdmi->dev, "Missing endpoint in port@%u\n",
+ hdmi->plat_data->output_port);
+ return -ENODEV;
+ }
+
+ remote = of_graph_get_remote_port_parent(endpoint);
+ of_node_put(endpoint);
+ if (!remote) {
+ dev_err(hdmi->dev, "Endpoint in port@%u unconnected\n",
+ hdmi->plat_data->output_port);
+ return -ENODEV;
+ }
+
+ if (!of_device_is_available(remote)) {
+ dev_err(hdmi->dev, "port@%u remote device is disabled\n",
+ hdmi->plat_data->output_port);
+ of_node_put(remote);
+ return -ENODEV;
+ }
+
+ hdmi->next_bridge = of_drm_find_bridge(remote);
+ of_node_put(remote);
+ if (!hdmi->next_bridge)
+ return -EPROBE_DEFER;
+
+ return 0;
+}
+
struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
const struct dw_hdmi_plat_data *plat_data)
{
@@ -3196,6 +3244,10 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
mutex_init(&hdmi->cec_notifier_mutex);
spin_lock_init(&hdmi->audio_lock);
+ ret = dw_hdmi_parse_dt(hdmi);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
if (ddc_node) {
hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
@@ -3474,7 +3526,6 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0);
if (ret) {
dw_hdmi_remove(hdmi);
- DRM_ERROR("Failed to initialize bridge with drm\n");
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 6b268f9445b3..e44e18a0112a 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -246,6 +246,7 @@ struct dw_mipi_dsi {
struct clk *pclk;
+ bool device_found;
unsigned int lane_mbps; /* per lane */
u32 channel;
u32 lanes;
@@ -309,13 +310,37 @@ static inline u32 dsi_read(struct dw_mipi_dsi *dsi, u32 reg)
return readl(dsi->base + reg);
}
+static int dw_mipi_dsi_panel_or_bridge(struct dw_mipi_dsi *dsi,
+ struct device_node *node)
+{
+ struct drm_bridge *bridge;
+ struct drm_panel *panel;
+ int ret;
+
+ ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
+ if (ret)
+ return ret;
+
+ if (panel) {
+ bridge = drm_panel_bridge_add_typed(panel,
+ DRM_MODE_CONNECTOR_DSI);
+ if (IS_ERR(bridge))
+ return PTR_ERR(bridge);
+ }
+
+ dsi->panel_bridge = bridge;
+
+ if (!dsi->panel_bridge)
+ return -EPROBE_DEFER;
+
+ return 0;
+}
+
static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct dw_mipi_dsi *dsi = host_to_dsi(host);
const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
- struct drm_bridge *bridge;
- struct drm_panel *panel;
int ret;
if (device->lanes > dsi->plat_data->max_data_lanes) {
@@ -329,22 +354,14 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
dsi->format = device->format;
dsi->mode_flags = device->mode_flags;
- ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0,
- &panel, &bridge);
- if (ret)
- return ret;
+ if (!dsi->device_found) {
+ ret = dw_mipi_dsi_panel_or_bridge(dsi, host->dev->of_node);
+ if (ret)
+ return ret;
- if (panel) {
- bridge = drm_panel_bridge_add_typed(panel,
- DRM_MODE_CONNECTOR_DSI);
- if (IS_ERR(bridge))
- return PTR_ERR(bridge);
+ dsi->device_found = true;
}
- dsi->panel_bridge = bridge;
-
- drm_bridge_add(&dsi->bridge);
-
if (pdata->host_ops && pdata->host_ops->attach) {
ret = pdata->host_ops->attach(pdata->priv_data, device);
if (ret < 0)
@@ -999,6 +1016,16 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
/* Set the encoder type as caller does not know it */
bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
+ if (!dsi->device_found) {
+ int ret;
+
+ ret = dw_mipi_dsi_panel_or_bridge(dsi, dsi->dev->of_node);
+ if (ret)
+ return ret;
+
+ dsi->device_found = true;
+ }
+
/* Attach the panel-bridge to the dsi bridge */
return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,
flags);
@@ -1181,6 +1208,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
#ifdef CONFIG_OF
dsi->bridge.of_node = pdev->dev.of_node;
#endif
+ drm_bridge_add(&dsi->bridge);
return dsi;
}
@@ -1229,15 +1257,7 @@ EXPORT_SYMBOL_GPL(dw_mipi_dsi_remove);
*/
int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder)
{
- int ret;
-
- ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
- if (ret) {
- DRM_ERROR("Failed to initialize bridge with drm\n");
- return ret;
- }
-
- return ret;
+ return drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
}
EXPORT_SYMBOL_GPL(dw_mipi_dsi_bind);
diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
index 8ed8302d6bbb..a3db532bbdd1 100644
--- a/drivers/gpu/drm/bridge/tc358768.c
+++ b/drivers/gpu/drm/bridge/tc358768.c
@@ -291,7 +291,7 @@ static int tc358768_calc_pll(struct tc358768_priv *priv,
const struct drm_display_mode *mode,
bool verify_only)
{
- const u32 frs_limits[] = {
+ static const u32 frs_limits[] = {
1000000000,
500000000,
250000000,
@@ -825,7 +825,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
if (!(dsi_dev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
val |= TC358768_DSI_CONTROL_HSCKMD;
- if (dsi_dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET)
+ if (dsi_dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET)
val |= TC358768_DSI_CONTROL_EOTDIS;
tc358768_write(priv, TC358768_DSI_CONFW, val);
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 750f2172ef08..a32f70bc68ea 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -137,7 +137,6 @@ enum sn65dsi83_model {
struct sn65dsi83 {
struct drm_bridge bridge;
- struct drm_display_mode mode;
struct device *dev;
struct regmap *regmap;
struct device_node *host_node;
@@ -147,8 +146,6 @@ struct sn65dsi83 {
int dsi_lanes;
bool lvds_dual_link;
bool lvds_dual_link_even_odd_swap;
- bool lvds_format_24bpp;
- bool lvds_format_jeida;
};
static const struct regmap_range sn65dsi83_readable_ranges[] = {
@@ -291,7 +288,8 @@ err_dsi_attach:
return ret;
}
-static void sn65dsi83_pre_enable(struct drm_bridge *bridge)
+static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
@@ -306,7 +304,8 @@ static void sn65dsi83_pre_enable(struct drm_bridge *bridge)
usleep_range(1000, 1100);
}
-static u8 sn65dsi83_get_lvds_range(struct sn65dsi83 *ctx)
+static u8 sn65dsi83_get_lvds_range(struct sn65dsi83 *ctx,
+ const struct drm_display_mode *mode)
{
/*
* The encoding of the LVDS_CLK_RANGE is as follows:
@@ -322,7 +321,7 @@ static u8 sn65dsi83_get_lvds_range(struct sn65dsi83 *ctx)
* the clock to 25..154 MHz, the range calculation can be simplified
* as follows:
*/
- int mode_clock = ctx->mode.clock;
+ int mode_clock = mode->clock;
if (ctx->lvds_dual_link)
mode_clock /= 2;
@@ -330,7 +329,8 @@ static u8 sn65dsi83_get_lvds_range(struct sn65dsi83 *ctx)
return (mode_clock - 12500) / 25000;
}
-static u8 sn65dsi83_get_dsi_range(struct sn65dsi83 *ctx)
+static u8 sn65dsi83_get_dsi_range(struct sn65dsi83 *ctx,
+ const struct drm_display_mode *mode)
{
/*
* The encoding of the CHA_DSI_CLK_RANGE is as follows:
@@ -346,7 +346,7 @@ static u8 sn65dsi83_get_dsi_range(struct sn65dsi83 *ctx)
* DSI_CLK = mode clock * bpp / dsi_data_lanes / 2
* the 2 is there because the bus is DDR.
*/
- return DIV_ROUND_UP(clamp((unsigned int)ctx->mode.clock *
+ return DIV_ROUND_UP(clamp((unsigned int)mode->clock *
mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) /
ctx->dsi_lanes / 2, 40000U, 500000U), 5000U);
}
@@ -364,23 +364,73 @@ static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)
return dsi_div - 1;
}
-static void sn65dsi83_enable(struct drm_bridge *bridge)
+static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
+ struct drm_atomic_state *state = old_bridge_state->base.state;
+ const struct drm_bridge_state *bridge_state;
+ const struct drm_crtc_state *crtc_state;
+ const struct drm_display_mode *mode;
+ struct drm_connector *connector;
+ struct drm_crtc *crtc;
+ bool lvds_format_24bpp;
+ bool lvds_format_jeida;
unsigned int pval;
+ __le16 le16val;
u16 val;
int ret;
+ /* Get the LVDS format from the bridge state. */
+ bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+
+ switch (bridge_state->output_bus_cfg.format) {
+ case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+ lvds_format_24bpp = false;
+ lvds_format_jeida = true;
+ break;
+ case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+ lvds_format_24bpp = true;
+ lvds_format_jeida = true;
+ break;
+ case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+ lvds_format_24bpp = true;
+ lvds_format_jeida = false;
+ break;
+ default:
+ /*
+ * Some bridges still don't set the correct
+ * LVDS bus pixel format, use SPWG24 default
+ * format until those are fixed.
+ */
+ lvds_format_24bpp = true;
+ lvds_format_jeida = false;
+ dev_warn(ctx->dev,
+ "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n",
+ bridge_state->output_bus_cfg.format);
+ break;
+ }
+
+ /*
+ * Retrieve the CRTC adjusted mode. This requires a little dance to go
+ * from the bridge to the encoder, to the connector and to the CRTC.
+ */
+ connector = drm_atomic_get_new_connector_for_encoder(state,
+ bridge->encoder);
+ crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ mode = &crtc_state->adjusted_mode;
+
/* Clear reset, disable PLL */
regmap_write(ctx->regmap, REG_RC_RESET, 0x00);
regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
/* Reference clock derived from DSI link clock. */
regmap_write(ctx->regmap, REG_RC_LVDS_PLL,
- REG_RC_LVDS_PLL_LVDS_CLK_RANGE(sn65dsi83_get_lvds_range(ctx)) |
+ REG_RC_LVDS_PLL_LVDS_CLK_RANGE(sn65dsi83_get_lvds_range(ctx, mode)) |
REG_RC_LVDS_PLL_HS_CLK_SRC_DPHY);
regmap_write(ctx->regmap, REG_DSI_CLK,
- REG_DSI_CLK_CHA_DSI_CLK_RANGE(sn65dsi83_get_dsi_range(ctx)));
+ REG_DSI_CLK_CHA_DSI_CLK_RANGE(sn65dsi83_get_dsi_range(ctx, mode)));
regmap_write(ctx->regmap, REG_RC_DSI_CLK,
REG_RC_DSI_CLK_DSI_CLK_DIVIDER(sn65dsi83_get_dsi_div(ctx)));
@@ -394,20 +444,20 @@ static void sn65dsi83_enable(struct drm_bridge *bridge)
regmap_write(ctx->regmap, REG_DSI_EQ, 0x00);
/* Set up sync signal polarity. */
- val = (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC ?
+ val = (mode->flags & DRM_MODE_FLAG_NHSYNC ?
REG_LVDS_FMT_HS_NEG_POLARITY : 0) |
- (ctx->mode.flags & DRM_MODE_FLAG_NVSYNC ?
+ (mode->flags & DRM_MODE_FLAG_NVSYNC ?
REG_LVDS_FMT_VS_NEG_POLARITY : 0);
/* Set up bits-per-pixel, 18bpp or 24bpp. */
- if (ctx->lvds_format_24bpp) {
+ if (lvds_format_24bpp) {
val |= REG_LVDS_FMT_CHA_24BPP_MODE;
if (ctx->lvds_dual_link)
val |= REG_LVDS_FMT_CHB_24BPP_MODE;
}
/* Set up LVDS format, JEIDA/Format 1 or SPWG/Format 2 */
- if (ctx->lvds_format_jeida) {
+ if (lvds_format_jeida) {
val |= REG_LVDS_FMT_CHA_24BPP_FORMAT1;
if (ctx->lvds_dual_link)
val |= REG_LVDS_FMT_CHB_24BPP_FORMAT1;
@@ -426,29 +476,29 @@ static void sn65dsi83_enable(struct drm_bridge *bridge)
REG_LVDS_LANE_CHB_LVDS_TERM);
regmap_write(ctx->regmap, REG_LVDS_CM, 0x00);
- val = cpu_to_le16(ctx->mode.hdisplay);
+ le16val = cpu_to_le16(mode->hdisplay);
regmap_bulk_write(ctx->regmap, REG_VID_CHA_ACTIVE_LINE_LENGTH_LOW,
- &val, 2);
- val = cpu_to_le16(ctx->mode.vdisplay);
+ &le16val, 2);
+ le16val = cpu_to_le16(mode->vdisplay);
regmap_bulk_write(ctx->regmap, REG_VID_CHA_VERTICAL_DISPLAY_SIZE_LOW,
- &val, 2);
+ &le16val, 2);
/* 32 + 1 pixel clock to ensure proper operation */
- val = cpu_to_le16(32 + 1);
- regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &val, 2);
- val = cpu_to_le16(ctx->mode.hsync_end - ctx->mode.hsync_start);
+ le16val = cpu_to_le16(32 + 1);
+ regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &le16val, 2);
+ le16val = cpu_to_le16(mode->hsync_end - mode->hsync_start);
regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW,
- &val, 2);
- val = cpu_to_le16(ctx->mode.vsync_end - ctx->mode.vsync_start);
+ &le16val, 2);
+ le16val = cpu_to_le16(mode->vsync_end - mode->vsync_start);
regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW,
- &val, 2);
+ &le16val, 2);
regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH,
- ctx->mode.htotal - ctx->mode.hsync_end);
+ mode->htotal - mode->hsync_end);
regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH,
- ctx->mode.vtotal - ctx->mode.vsync_end);
+ mode->vtotal - mode->vsync_end);
regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH,
- ctx->mode.hsync_start - ctx->mode.hdisplay);
+ mode->hsync_start - mode->hdisplay);
regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH,
- ctx->mode.vsync_start - ctx->mode.vdisplay);
+ mode->vsync_start - mode->vdisplay);
regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00);
/* Enable PLL */
@@ -472,7 +522,8 @@ static void sn65dsi83_enable(struct drm_bridge *bridge)
regmap_write(ctx->regmap, REG_IRQ_STAT, pval);
}
-static void sn65dsi83_disable(struct drm_bridge *bridge)
+static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
@@ -481,7 +532,8 @@ static void sn65dsi83_disable(struct drm_bridge *bridge)
regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
}
-static void sn65dsi83_post_disable(struct drm_bridge *bridge)
+static void sn65dsi83_atomic_post_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
@@ -503,70 +555,44 @@ sn65dsi83_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
-static void sn65dsi83_mode_set(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- const struct drm_display_mode *adj)
-{
- struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
+#define MAX_INPUT_SEL_FORMATS 1
- ctx->mode = *adj;
-}
-
-static bool sn65dsi83_mode_fixup(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adj)
+static u32 *
+sn65dsi83_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts)
{
- struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
- u32 input_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
- struct drm_encoder *encoder = bridge->encoder;
- struct drm_device *ddev = encoder->dev;
- struct drm_connector *connector;
+ u32 *input_fmts;
- /* The DSI format is always RGB888_1X24 */
- list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
- switch (connector->display_info.bus_formats[0]) {
- case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
- ctx->lvds_format_24bpp = false;
- ctx->lvds_format_jeida = true;
- break;
- case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
- ctx->lvds_format_24bpp = true;
- ctx->lvds_format_jeida = true;
- break;
- case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
- ctx->lvds_format_24bpp = true;
- ctx->lvds_format_jeida = false;
- break;
- default:
- /*
- * Some bridges still don't set the correct
- * LVDS bus pixel format, use SPWG24 default
- * format until those are fixed.
- */
- ctx->lvds_format_24bpp = true;
- ctx->lvds_format_jeida = false;
- dev_warn(ctx->dev,
- "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n",
- connector->display_info.bus_formats[0]);
- break;
- }
+ *num_input_fmts = 0;
- drm_display_info_set_bus_formats(&connector->display_info,
- &input_bus_format, 1);
- }
+ input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
+ GFP_KERNEL);
+ if (!input_fmts)
+ return NULL;
+
+ /* This is the DSI-end bus format */
+ input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+ *num_input_fmts = 1;
- return true;
+ return input_fmts;
}
static const struct drm_bridge_funcs sn65dsi83_funcs = {
- .attach = sn65dsi83_attach,
- .pre_enable = sn65dsi83_pre_enable,
- .enable = sn65dsi83_enable,
- .disable = sn65dsi83_disable,
- .post_disable = sn65dsi83_post_disable,
- .mode_valid = sn65dsi83_mode_valid,
- .mode_set = sn65dsi83_mode_set,
- .mode_fixup = sn65dsi83_mode_fixup,
+ .attach = sn65dsi83_attach,
+ .atomic_pre_enable = sn65dsi83_atomic_pre_enable,
+ .atomic_enable = sn65dsi83_atomic_enable,
+ .atomic_disable = sn65dsi83_atomic_disable,
+ .atomic_post_disable = sn65dsi83_atomic_post_disable,
+ .mode_valid = sn65dsi83_mode_valid,
+
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_get_input_bus_fmts = sn65dsi83_atomic_get_input_bus_fmts,
};
static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 45a2969afb2b..41d48a393e7f 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -23,6 +23,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
+#include <drm/drm_dp_aux_bus.h>
#include <drm/drm_dp_helper.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
@@ -116,6 +117,7 @@
* struct ti_sn65dsi86 - Platform data for ti-sn65dsi86 driver.
* @bridge_aux: AUX-bus sub device for MIPI-to-eDP bridge functionality.
* @gpio_aux: AUX-bus sub device for GPIO controller functionality.
+ * @aux_aux: AUX-bus sub device for eDP AUX channel functionality.
*
* @dev: Pointer to the top level (i2c) device.
* @regmap: Regmap for accessing i2c.
@@ -124,9 +126,8 @@
* @connector: Our connector.
* @host_node: Remote DSI node.
* @dsi: Our MIPI DSI source.
- * @edid: Detected EDID of eDP panel.
* @refclk: Our reference clock.
- * @panel: Our panel.
+ * @next_bridge: The bridge on the eDP side.
* @enable_gpio: The GPIO we toggle to enable the bridge.
* @supplies: Data for bulk enabling/disabling our regulators.
* @dp_lanes: Count of dp_lanes we're using.
@@ -148,17 +149,17 @@
struct ti_sn65dsi86 {
struct auxiliary_device bridge_aux;
struct auxiliary_device gpio_aux;
+ struct auxiliary_device aux_aux;
struct device *dev;
struct regmap *regmap;
struct drm_dp_aux aux;
struct drm_bridge bridge;
struct drm_connector connector;
- struct edid *edid;
struct device_node *host_node;
struct mipi_dsi_device *dsi;
struct clk *refclk;
- struct drm_panel *panel;
+ struct drm_bridge *next_bridge;
struct gpio_desc *enable_gpio;
struct regulator_bulk_data supplies[SN_REGULATOR_SUPPLY_NUM];
int dp_lanes;
@@ -306,6 +307,9 @@ static int __maybe_unused ti_sn65dsi86_resume(struct device *dev)
return ret;
}
+ /* td2: min 100 us after regulators before enabling the GPIO */
+ usleep_range(100, 110);
+
gpiod_set_value(pdata->enable_gpio, 1);
/*
@@ -393,35 +397,222 @@ static void ti_sn65dsi86_debugfs_init(struct ti_sn65dsi86 *pdata)
debugfs_create_file("status", 0600, debugfs, pdata, &status_fops);
}
-/* Connector funcs */
-static struct ti_sn65dsi86 *
-connector_to_ti_sn65dsi86(struct drm_connector *connector)
+/* -----------------------------------------------------------------------------
+ * Auxiliary Devices (*not* AUX)
+ */
+
+static void ti_sn65dsi86_uninit_aux(void *data)
{
- return container_of(connector, struct ti_sn65dsi86, connector);
+ auxiliary_device_uninit(data);
}
-static int ti_sn_bridge_connector_get_modes(struct drm_connector *connector)
+static void ti_sn65dsi86_delete_aux(void *data)
{
- struct ti_sn65dsi86 *pdata = connector_to_ti_sn65dsi86(connector);
- struct edid *edid = pdata->edid;
- int num, ret;
+ auxiliary_device_delete(data);
+}
- if (!edid) {
- pm_runtime_get_sync(pdata->dev);
- edid = pdata->edid = drm_get_edid(connector, &pdata->aux.ddc);
- pm_runtime_put_autosuspend(pdata->dev);
+/*
+ * AUX bus docs say that a non-NULL release is mandatory, but it makes no
+ * sense for the model used here where all of the aux devices are allocated
+ * in the single shared structure. We'll use this noop as a workaround.
+ */
+static void ti_sn65dsi86_noop(struct device *dev) {}
+
+static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata,
+ struct auxiliary_device *aux,
+ const char *name)
+{
+ struct device *dev = pdata->dev;
+ int ret;
+
+ aux->name = name;
+ aux->dev.parent = dev;
+ aux->dev.release = ti_sn65dsi86_noop;
+ device_set_of_node_from_dev(&aux->dev, dev);
+ ret = auxiliary_device_init(aux);
+ if (ret)
+ return ret;
+ ret = devm_add_action_or_reset(dev, ti_sn65dsi86_uninit_aux, aux);
+ if (ret)
+ return ret;
+
+ ret = auxiliary_device_add(aux);
+ if (ret)
+ return ret;
+ ret = devm_add_action_or_reset(dev, ti_sn65dsi86_delete_aux, aux);
+
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * AUX Adapter
+ */
+
+static struct ti_sn65dsi86 *aux_to_ti_sn65dsi86(struct drm_dp_aux *aux)
+{
+ return container_of(aux, struct ti_sn65dsi86, aux);
+}
+
+static ssize_t ti_sn_aux_transfer(struct drm_dp_aux *aux,
+ struct drm_dp_aux_msg *msg)
+{
+ struct ti_sn65dsi86 *pdata = aux_to_ti_sn65dsi86(aux);
+ u32 request = msg->request & ~(DP_AUX_I2C_MOT | DP_AUX_I2C_WRITE_STATUS_UPDATE);
+ u32 request_val = AUX_CMD_REQ(msg->request);
+ u8 *buf = msg->buffer;
+ unsigned int len = msg->size;
+ unsigned int val;
+ int ret;
+ u8 addr_len[SN_AUX_LENGTH_REG + 1 - SN_AUX_ADDR_19_16_REG];
+
+ if (len > SN_AUX_MAX_PAYLOAD_BYTES)
+ return -EINVAL;
+
+ pm_runtime_get_sync(pdata->dev);
+ mutex_lock(&pdata->comms_mutex);
+
+ /*
+ * If someone tries to do a DDC over AUX transaction before pre_enable()
+ * on a device without a dedicated reference clock then we just can't
+ * do it. Fail right away. This prevents non-refclk users from reading
+ * the EDID before enabling the panel but such is life.
+ */
+ if (!pdata->comms_enabled) {
+ ret = -EIO;
+ goto exit;
+ }
+
+ switch (request) {
+ case DP_AUX_NATIVE_WRITE:
+ case DP_AUX_I2C_WRITE:
+ case DP_AUX_NATIVE_READ:
+ case DP_AUX_I2C_READ:
+ regmap_write(pdata->regmap, SN_AUX_CMD_REG, request_val);
+ /* Assume it's good */
+ msg->reply = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ BUILD_BUG_ON(sizeof(addr_len) != sizeof(__be32));
+ put_unaligned_be32((msg->address & SN_AUX_ADDR_MASK) << 8 | len,
+ addr_len);
+ regmap_bulk_write(pdata->regmap, SN_AUX_ADDR_19_16_REG, addr_len,
+ ARRAY_SIZE(addr_len));
+
+ if (request == DP_AUX_NATIVE_WRITE || request == DP_AUX_I2C_WRITE)
+ regmap_bulk_write(pdata->regmap, SN_AUX_WDATA_REG(0), buf, len);
+
+ /* Clear old status bits before start so we don't get confused */
+ regmap_write(pdata->regmap, SN_AUX_CMD_STATUS_REG,
+ AUX_IRQ_STATUS_NAT_I2C_FAIL |
+ AUX_IRQ_STATUS_AUX_RPLY_TOUT |
+ AUX_IRQ_STATUS_AUX_SHORT);
+
+ regmap_write(pdata->regmap, SN_AUX_CMD_REG, request_val | AUX_CMD_SEND);
+
+ /* Zero delay loop because i2c transactions are slow already */
+ ret = regmap_read_poll_timeout(pdata->regmap, SN_AUX_CMD_REG, val,
+ !(val & AUX_CMD_SEND), 0, 50 * 1000);
+ if (ret)
+ goto exit;
+
+ ret = regmap_read(pdata->regmap, SN_AUX_CMD_STATUS_REG, &val);
+ if (ret)
+ goto exit;
+
+ if (val & AUX_IRQ_STATUS_AUX_RPLY_TOUT) {
+ /*
+ * The hardware tried the message seven times per the DP spec
+ * but it hit a timeout. We ignore defers here because they're
+ * handled in hardware.
+ */
+ ret = -ETIMEDOUT;
+ goto exit;
}
- if (edid && drm_edid_is_valid(edid)) {
- ret = drm_connector_update_edid_property(connector, edid);
- if (!ret) {
- num = drm_add_edid_modes(connector, edid);
- if (num)
- return num;
+ if (val & AUX_IRQ_STATUS_AUX_SHORT) {
+ ret = regmap_read(pdata->regmap, SN_AUX_LENGTH_REG, &len);
+ if (ret)
+ goto exit;
+ } else if (val & AUX_IRQ_STATUS_NAT_I2C_FAIL) {
+ switch (request) {
+ case DP_AUX_I2C_WRITE:
+ case DP_AUX_I2C_READ:
+ msg->reply |= DP_AUX_I2C_REPLY_NACK;
+ break;
+ case DP_AUX_NATIVE_READ:
+ case DP_AUX_NATIVE_WRITE:
+ msg->reply |= DP_AUX_NATIVE_REPLY_NACK;
+ break;
}
+ len = 0;
+ goto exit;
}
- return drm_panel_get_modes(pdata->panel, connector);
+ if (request != DP_AUX_NATIVE_WRITE && request != DP_AUX_I2C_WRITE && len != 0)
+ ret = regmap_bulk_read(pdata->regmap, SN_AUX_RDATA_REG(0), buf, len);
+
+exit:
+ mutex_unlock(&pdata->comms_mutex);
+ pm_runtime_mark_last_busy(pdata->dev);
+ pm_runtime_put_autosuspend(pdata->dev);
+
+ if (ret)
+ return ret;
+ return len;
+}
+
+static int ti_sn_aux_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
+ int ret;
+
+ pdata->aux.name = "ti-sn65dsi86-aux";
+ pdata->aux.dev = &adev->dev;
+ pdata->aux.transfer = ti_sn_aux_transfer;
+ drm_dp_aux_init(&pdata->aux);
+
+ ret = devm_of_dp_aux_populate_ep_devices(&pdata->aux);
+ if (ret)
+ return ret;
+
+ /*
+ * The eDP to MIPI bridge parts don't work until the AUX channel is
+ * setup so we don't add it in the main driver probe, we add it now.
+ */
+ return ti_sn65dsi86_add_aux_device(pdata, &pdata->bridge_aux, "bridge");
+}
+
+static const struct auxiliary_device_id ti_sn_aux_id_table[] = {
+ { .name = "ti_sn65dsi86.aux", },
+ {},
+};
+
+static struct auxiliary_driver ti_sn_aux_driver = {
+ .name = "aux",
+ .probe = ti_sn_aux_probe,
+ .id_table = ti_sn_aux_id_table,
+};
+
+/* -----------------------------------------------------------------------------
+ * DRM Connector Operations
+ */
+
+static struct ti_sn65dsi86 *
+connector_to_ti_sn65dsi86(struct drm_connector *connector)
+{
+ return container_of(connector, struct ti_sn65dsi86, connector);
+}
+
+static int ti_sn_bridge_connector_get_modes(struct drm_connector *connector)
+{
+ struct ti_sn65dsi86 *pdata = connector_to_ti_sn65dsi86(connector);
+
+ return drm_bridge_get_modes(pdata->next_bridge, connector);
}
static enum drm_mode_status
@@ -448,23 +639,32 @@ static const struct drm_connector_funcs ti_sn_bridge_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
-static struct ti_sn65dsi86 *bridge_to_ti_sn65dsi86(struct drm_bridge *bridge)
+static int ti_sn_bridge_connector_init(struct ti_sn65dsi86 *pdata)
{
- return container_of(bridge, struct ti_sn65dsi86, bridge);
-}
+ int ret;
-static int ti_sn65dsi86_parse_regulators(struct ti_sn65dsi86 *pdata)
-{
- unsigned int i;
- const char * const ti_sn_bridge_supply_names[] = {
- "vcca", "vcc", "vccio", "vpll",
- };
+ ret = drm_connector_init(pdata->bridge.dev, &pdata->connector,
+ &ti_sn_bridge_connector_funcs,
+ DRM_MODE_CONNECTOR_eDP);
+ if (ret) {
+ DRM_ERROR("Failed to initialize connector with drm\n");
+ return ret;
+ }
- for (i = 0; i < SN_REGULATOR_SUPPLY_NUM; i++)
- pdata->supplies[i].supply = ti_sn_bridge_supply_names[i];
+ drm_connector_helper_add(&pdata->connector,
+ &ti_sn_bridge_connector_helper_funcs);
+ drm_connector_attach_encoder(&pdata->connector, pdata->bridge.encoder);
- return devm_regulator_bulk_get(pdata->dev, SN_REGULATOR_SUPPLY_NUM,
- pdata->supplies);
+ return 0;
+}
+
+/*------------------------------------------------------------------------------
+ * DRM Bridge
+ */
+
+static struct ti_sn65dsi86 *bridge_to_ti_sn65dsi86(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct ti_sn65dsi86, bridge);
}
static int ti_sn_bridge_attach(struct drm_bridge *bridge,
@@ -491,17 +691,9 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
return ret;
}
- ret = drm_connector_init(bridge->dev, &pdata->connector,
- &ti_sn_bridge_connector_funcs,
- DRM_MODE_CONNECTOR_eDP);
- if (ret) {
- DRM_ERROR("Failed to initialize connector with drm\n");
+ ret = ti_sn_bridge_connector_init(pdata);
+ if (ret < 0)
goto err_conn_init;
- }
-
- drm_connector_helper_add(&pdata->connector,
- &ti_sn_bridge_connector_helper_funcs);
- drm_connector_attach_encoder(&pdata->connector, bridge->encoder);
/*
* TODO: ideally finding host resource and dsi dev registration needs
@@ -547,8 +739,19 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
}
pdata->dsi = dsi;
+ /* We never want the next bridge to *also* create a connector: */
+ flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR;
+
+ /* Attach the next bridge */
+ ret = drm_bridge_attach(bridge->encoder, pdata->next_bridge,
+ &pdata->bridge, flags);
+ if (ret < 0)
+ goto err_dsi_detach;
+
return 0;
+err_dsi_detach:
+ mipi_dsi_detach(dsi);
err_dsi_attach:
mipi_dsi_device_unregister(dsi);
err_dsi_host:
@@ -567,14 +770,8 @@ static void ti_sn_bridge_disable(struct drm_bridge *bridge)
{
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
- drm_panel_disable(pdata->panel);
-
/* disable video stream */
regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG, VSTREAM_ENABLE, 0);
- /* semi auto link training mode OFF */
- regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0);
- /* disable DP PLL */
- regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 0);
}
static void ti_sn_bridge_set_dsi_rate(struct ti_sn65dsi86 *pdata)
@@ -633,9 +830,9 @@ static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata)
return i;
}
-static void ti_sn_bridge_read_valid_rates(struct ti_sn65dsi86 *pdata,
- bool rate_valid[])
+static unsigned int ti_sn_bridge_read_valid_rates(struct ti_sn65dsi86 *pdata)
{
+ unsigned int valid_rates = 0;
unsigned int rate_per_200khz;
unsigned int rate_mhz;
u8 dpcd_val;
@@ -675,13 +872,13 @@ static void ti_sn_bridge_read_valid_rates(struct ti_sn65dsi86 *pdata,
j < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut);
j++) {
if (ti_sn_bridge_dp_rate_lut[j] == rate_mhz)
- rate_valid[j] = true;
+ valid_rates |= BIT(j);
}
}
for (i = 0; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut); i++) {
- if (rate_valid[i])
- return;
+ if (valid_rates & BIT(i))
+ return valid_rates;
}
DRM_DEV_ERROR(pdata->dev,
"No matching eDP rates in table; falling back\n");
@@ -703,15 +900,17 @@ static void ti_sn_bridge_read_valid_rates(struct ti_sn65dsi86 *pdata,
(int)dpcd_val);
fallthrough;
case DP_LINK_BW_5_4:
- rate_valid[7] = 1;
+ valid_rates |= BIT(7);
fallthrough;
case DP_LINK_BW_2_7:
- rate_valid[4] = 1;
+ valid_rates |= BIT(4);
fallthrough;
case DP_LINK_BW_1_62:
- rate_valid[1] = 1;
+ valid_rates |= BIT(1);
break;
}
+
+ return valid_rates;
}
static void ti_sn_bridge_set_video_timings(struct ti_sn65dsi86 *pdata)
@@ -829,8 +1028,8 @@ exit:
static void ti_sn_bridge_enable(struct drm_bridge *bridge)
{
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
- bool rate_valid[ARRAY_SIZE(ti_sn_bridge_dp_rate_lut)] = { };
const char *last_err_str = "No supported DP rate";
+ unsigned int valid_rates;
int dp_rate_idx;
unsigned int val;
int ret = -EINVAL;
@@ -869,13 +1068,13 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge)
regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK,
val);
- ti_sn_bridge_read_valid_rates(pdata, rate_valid);
+ valid_rates = ti_sn_bridge_read_valid_rates(pdata);
/* Train until we run out of rates */
for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata);
dp_rate_idx < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut);
dp_rate_idx++) {
- if (!rate_valid[dp_rate_idx])
+ if (!(valid_rates & BIT(dp_rate_idx)))
continue;
ret = ti_sn_link_training(pdata, dp_rate_idx, &last_err_str);
@@ -893,8 +1092,6 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge)
/* enable video stream */
regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG, VSTREAM_ENABLE,
VSTREAM_ENABLE);
-
- drm_panel_enable(pdata->panel);
}
static void ti_sn_bridge_pre_enable(struct drm_bridge *bridge)
@@ -906,14 +1103,20 @@ static void ti_sn_bridge_pre_enable(struct drm_bridge *bridge)
if (!pdata->refclk)
ti_sn65dsi86_enable_comms(pdata);
- drm_panel_prepare(pdata->panel);
+ /* td7: min 100 us after enable before DSI data */
+ usleep_range(100, 110);
}
static void ti_sn_bridge_post_disable(struct drm_bridge *bridge)
{
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
- drm_panel_unprepare(pdata->panel);
+ /* semi auto link training mode OFF */
+ regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0);
+ /* Num lanes to 0 as per power sequencing in data sheet */
+ regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK, 0);
+ /* disable DP PLL */
+ regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 0);
if (!pdata->refclk)
ti_sn65dsi86_disable_comms(pdata);
@@ -930,137 +1133,135 @@ static const struct drm_bridge_funcs ti_sn_bridge_funcs = {
.post_disable = ti_sn_bridge_post_disable,
};
-static struct ti_sn65dsi86 *aux_to_ti_sn65dsi86(struct drm_dp_aux *aux)
-{
- return container_of(aux, struct ti_sn65dsi86, aux);
-}
-
-static ssize_t ti_sn_aux_transfer(struct drm_dp_aux *aux,
- struct drm_dp_aux_msg *msg)
+static void ti_sn_bridge_parse_lanes(struct ti_sn65dsi86 *pdata,
+ struct device_node *np)
{
- struct ti_sn65dsi86 *pdata = aux_to_ti_sn65dsi86(aux);
- u32 request = msg->request & ~(DP_AUX_I2C_MOT | DP_AUX_I2C_WRITE_STATUS_UPDATE);
- u32 request_val = AUX_CMD_REQ(msg->request);
- u8 *buf = msg->buffer;
- unsigned int len = msg->size;
- unsigned int val;
- int ret;
- u8 addr_len[SN_AUX_LENGTH_REG + 1 - SN_AUX_ADDR_19_16_REG];
-
- if (len > SN_AUX_MAX_PAYLOAD_BYTES)
- return -EINVAL;
-
- pm_runtime_get_sync(pdata->dev);
- mutex_lock(&pdata->comms_mutex);
+ u32 lane_assignments[SN_MAX_DP_LANES] = { 0, 1, 2, 3 };
+ u32 lane_polarities[SN_MAX_DP_LANES] = { };
+ struct device_node *endpoint;
+ u8 ln_assign = 0;
+ u8 ln_polrs = 0;
+ int dp_lanes;
+ int i;
/*
- * If someone tries to do a DDC over AUX transaction before pre_enable()
- * on a device without a dedicated reference clock then we just can't
- * do it. Fail right away. This prevents non-refclk users from reading
- * the EDID before enabling the panel but such is life.
+ * Read config from the device tree about lane remapping and lane
+ * polarities. These are optional and we assume identity map and
+ * normal polarity if nothing is specified. It's OK to specify just
+ * data-lanes but not lane-polarities but not vice versa.
+ *
+ * Error checking is light (we just make sure we don't crash or
+ * buffer overrun) and we assume dts is well formed and specifying
+ * mappings that the hardware supports.
*/
- if (!pdata->comms_enabled) {
- ret = -EIO;
- goto exit;
+ endpoint = of_graph_get_endpoint_by_regs(np, 1, -1);
+ dp_lanes = of_property_count_u32_elems(endpoint, "data-lanes");
+ if (dp_lanes > 0 && dp_lanes <= SN_MAX_DP_LANES) {
+ of_property_read_u32_array(endpoint, "data-lanes",
+ lane_assignments, dp_lanes);
+ of_property_read_u32_array(endpoint, "lane-polarities",
+ lane_polarities, dp_lanes);
+ } else {
+ dp_lanes = SN_MAX_DP_LANES;
}
+ of_node_put(endpoint);
- switch (request) {
- case DP_AUX_NATIVE_WRITE:
- case DP_AUX_I2C_WRITE:
- case DP_AUX_NATIVE_READ:
- case DP_AUX_I2C_READ:
- regmap_write(pdata->regmap, SN_AUX_CMD_REG, request_val);
- /* Assume it's good */
- msg->reply = 0;
- break;
- default:
- ret = -EINVAL;
- goto exit;
+ /*
+ * Convert into register format. Loop over all lanes even if
+ * data-lanes had fewer elements so that we nicely initialize
+ * the LN_ASSIGN register.
+ */
+ for (i = SN_MAX_DP_LANES - 1; i >= 0; i--) {
+ ln_assign = ln_assign << LN_ASSIGN_WIDTH | lane_assignments[i];
+ ln_polrs = ln_polrs << 1 | lane_polarities[i];
}
- BUILD_BUG_ON(sizeof(addr_len) != sizeof(__be32));
- put_unaligned_be32((msg->address & SN_AUX_ADDR_MASK) << 8 | len,
- addr_len);
- regmap_bulk_write(pdata->regmap, SN_AUX_ADDR_19_16_REG, addr_len,
- ARRAY_SIZE(addr_len));
+ /* Stash in our struct for when we power on */
+ pdata->dp_lanes = dp_lanes;
+ pdata->ln_assign = ln_assign;
+ pdata->ln_polrs = ln_polrs;
+}
- if (request == DP_AUX_NATIVE_WRITE || request == DP_AUX_I2C_WRITE)
- regmap_bulk_write(pdata->regmap, SN_AUX_WDATA_REG(0), buf, len);
+static int ti_sn_bridge_parse_dsi_host(struct ti_sn65dsi86 *pdata)
+{
+ struct device_node *np = pdata->dev->of_node;
- /* Clear old status bits before start so we don't get confused */
- regmap_write(pdata->regmap, SN_AUX_CMD_STATUS_REG,
- AUX_IRQ_STATUS_NAT_I2C_FAIL |
- AUX_IRQ_STATUS_AUX_RPLY_TOUT |
- AUX_IRQ_STATUS_AUX_SHORT);
+ pdata->host_node = of_graph_get_remote_node(np, 0, 0);
- regmap_write(pdata->regmap, SN_AUX_CMD_REG, request_val | AUX_CMD_SEND);
+ if (!pdata->host_node) {
+ DRM_ERROR("remote dsi host node not found\n");
+ return -ENODEV;
+ }
- /* Zero delay loop because i2c transactions are slow already */
- ret = regmap_read_poll_timeout(pdata->regmap, SN_AUX_CMD_REG, val,
- !(val & AUX_CMD_SEND), 0, 50 * 1000);
- if (ret)
- goto exit;
+ return 0;
+}
- ret = regmap_read(pdata->regmap, SN_AUX_CMD_STATUS_REG, &val);
- if (ret)
- goto exit;
+static int ti_sn_bridge_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
+ struct device_node *np = pdata->dev->of_node;
+ struct drm_panel *panel;
+ int ret;
- if (val & AUX_IRQ_STATUS_AUX_RPLY_TOUT) {
- /*
- * The hardware tried the message seven times per the DP spec
- * but it hit a timeout. We ignore defers here because they're
- * handled in hardware.
- */
- ret = -ETIMEDOUT;
- goto exit;
- }
+ ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
+ if (ret)
+ return dev_err_probe(&adev->dev, ret,
+ "could not find any panel node\n");
- if (val & AUX_IRQ_STATUS_AUX_SHORT) {
- ret = regmap_read(pdata->regmap, SN_AUX_LENGTH_REG, &len);
- if (ret)
- goto exit;
- } else if (val & AUX_IRQ_STATUS_NAT_I2C_FAIL) {
- switch (request) {
- case DP_AUX_I2C_WRITE:
- case DP_AUX_I2C_READ:
- msg->reply |= DP_AUX_I2C_REPLY_NACK;
- break;
- case DP_AUX_NATIVE_READ:
- case DP_AUX_NATIVE_WRITE:
- msg->reply |= DP_AUX_NATIVE_REPLY_NACK;
- break;
- }
- len = 0;
- goto exit;
+ pdata->next_bridge = devm_drm_panel_bridge_add(pdata->dev, panel);
+ if (IS_ERR(pdata->next_bridge)) {
+ DRM_ERROR("failed to create panel bridge\n");
+ return PTR_ERR(pdata->next_bridge);
}
- if (request != DP_AUX_NATIVE_WRITE && request != DP_AUX_I2C_WRITE && len != 0)
- ret = regmap_bulk_read(pdata->regmap, SN_AUX_RDATA_REG(0), buf, len);
-
-exit:
- mutex_unlock(&pdata->comms_mutex);
- pm_runtime_mark_last_busy(pdata->dev);
- pm_runtime_put_autosuspend(pdata->dev);
+ ti_sn_bridge_parse_lanes(pdata, np);
+ ret = ti_sn_bridge_parse_dsi_host(pdata);
if (ret)
return ret;
- return len;
+
+ pdata->bridge.funcs = &ti_sn_bridge_funcs;
+ pdata->bridge.of_node = np;
+
+ drm_bridge_add(&pdata->bridge);
+
+ return 0;
}
-static int ti_sn_bridge_parse_dsi_host(struct ti_sn65dsi86 *pdata)
+static void ti_sn_bridge_remove(struct auxiliary_device *adev)
{
- struct device_node *np = pdata->dev->of_node;
+ struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
- pdata->host_node = of_graph_get_remote_node(np, 0, 0);
+ if (!pdata)
+ return;
- if (!pdata->host_node) {
- DRM_ERROR("remote dsi host node not found\n");
- return -ENODEV;
+ if (pdata->dsi) {
+ mipi_dsi_detach(pdata->dsi);
+ mipi_dsi_device_unregister(pdata->dsi);
}
- return 0;
+ drm_bridge_remove(&pdata->bridge);
+
+ of_node_put(pdata->host_node);
}
+static const struct auxiliary_device_id ti_sn_bridge_id_table[] = {
+ { .name = "ti_sn65dsi86.bridge", },
+ {},
+};
+
+static struct auxiliary_driver ti_sn_bridge_driver = {
+ .name = "bridge",
+ .probe = ti_sn_bridge_probe,
+ .remove = ti_sn_bridge_remove,
+ .id_table = ti_sn_bridge_id_table,
+};
+
+/* -----------------------------------------------------------------------------
+ * GPIO Controller
+ */
+
#if defined(CONFIG_OF_GPIO)
static int tn_sn_bridge_of_xlate(struct gpio_chip *chip,
@@ -1265,171 +1466,27 @@ static inline void ti_sn_gpio_unregister(void) {}
#endif
-static void ti_sn_bridge_parse_lanes(struct ti_sn65dsi86 *pdata,
- struct device_node *np)
-{
- u32 lane_assignments[SN_MAX_DP_LANES] = { 0, 1, 2, 3 };
- u32 lane_polarities[SN_MAX_DP_LANES] = { };
- struct device_node *endpoint;
- u8 ln_assign = 0;
- u8 ln_polrs = 0;
- int dp_lanes;
- int i;
-
- /*
- * Read config from the device tree about lane remapping and lane
- * polarities. These are optional and we assume identity map and
- * normal polarity if nothing is specified. It's OK to specify just
- * data-lanes but not lane-polarities but not vice versa.
- *
- * Error checking is light (we just make sure we don't crash or
- * buffer overrun) and we assume dts is well formed and specifying
- * mappings that the hardware supports.
- */
- endpoint = of_graph_get_endpoint_by_regs(np, 1, -1);
- dp_lanes = of_property_count_u32_elems(endpoint, "data-lanes");
- if (dp_lanes > 0 && dp_lanes <= SN_MAX_DP_LANES) {
- of_property_read_u32_array(endpoint, "data-lanes",
- lane_assignments, dp_lanes);
- of_property_read_u32_array(endpoint, "lane-polarities",
- lane_polarities, dp_lanes);
- } else {
- dp_lanes = SN_MAX_DP_LANES;
- }
- of_node_put(endpoint);
-
- /*
- * Convert into register format. Loop over all lanes even if
- * data-lanes had fewer elements so that we nicely initialize
- * the LN_ASSIGN register.
- */
- for (i = SN_MAX_DP_LANES - 1; i >= 0; i--) {
- ln_assign = ln_assign << LN_ASSIGN_WIDTH | lane_assignments[i];
- ln_polrs = ln_polrs << 1 | lane_polarities[i];
- }
-
- /* Stash in our struct for when we power on */
- pdata->dp_lanes = dp_lanes;
- pdata->ln_assign = ln_assign;
- pdata->ln_polrs = ln_polrs;
-}
-
-static int ti_sn_bridge_probe(struct auxiliary_device *adev,
- const struct auxiliary_device_id *id)
-{
- struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
- struct device_node *np = pdata->dev->of_node;
- int ret;
-
- ret = drm_of_find_panel_or_bridge(np, 1, 0, &pdata->panel, NULL);
- if (ret) {
- DRM_ERROR("could not find any panel node\n");
- return ret;
- }
-
- ti_sn_bridge_parse_lanes(pdata, np);
-
- ret = ti_sn_bridge_parse_dsi_host(pdata);
- if (ret)
- return ret;
-
- pdata->aux.name = "ti-sn65dsi86-aux";
- pdata->aux.dev = pdata->dev;
- pdata->aux.transfer = ti_sn_aux_transfer;
- drm_dp_aux_init(&pdata->aux);
-
- pdata->bridge.funcs = &ti_sn_bridge_funcs;
- pdata->bridge.of_node = np;
-
- drm_bridge_add(&pdata->bridge);
-
- return 0;
-}
-
-static void ti_sn_bridge_remove(struct auxiliary_device *adev)
-{
- struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
-
- if (!pdata)
- return;
-
- if (pdata->dsi) {
- mipi_dsi_detach(pdata->dsi);
- mipi_dsi_device_unregister(pdata->dsi);
- }
-
- kfree(pdata->edid);
-
- drm_bridge_remove(&pdata->bridge);
-
- of_node_put(pdata->host_node);
-}
-
-static const struct auxiliary_device_id ti_sn_bridge_id_table[] = {
- { .name = "ti_sn65dsi86.bridge", },
- {},
-};
-
-static struct auxiliary_driver ti_sn_bridge_driver = {
- .name = "bridge",
- .probe = ti_sn_bridge_probe,
- .remove = ti_sn_bridge_remove,
- .id_table = ti_sn_bridge_id_table,
-};
+/* -----------------------------------------------------------------------------
+ * Probe & Remove
+ */
static void ti_sn65dsi86_runtime_disable(void *data)
{
pm_runtime_disable(data);
}
-static void ti_sn65dsi86_uninit_aux(void *data)
-{
- auxiliary_device_uninit(data);
-}
-
-static void ti_sn65dsi86_delete_aux(void *data)
-{
- auxiliary_device_delete(data);
-}
-
-/*
- * AUX bus docs say that a non-NULL release is mandatory, but it makes no
- * sense for the model used here where all of the aux devices are allocated
- * in the single shared structure. We'll use this noop as a workaround.
- */
-static void ti_sn65dsi86_noop(struct device *dev) {}
-
-static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata,
- struct auxiliary_device *aux,
- const char *name)
+static int ti_sn65dsi86_parse_regulators(struct ti_sn65dsi86 *pdata)
{
- struct device *dev = pdata->dev;
- int ret;
-
- /*
- * NOTE: It would be nice to set the "of_node" of our children to be
- * the same "of_node"" that the top-level component has. That doesn't
- * work, though, since pinctrl will try (and fail) to reserve the
- * pins again. Until that gets sorted out the children will just need
- * to look at the of_node of the main device.
- */
-
- aux->name = name;
- aux->dev.parent = dev;
- aux->dev.release = ti_sn65dsi86_noop;
- ret = auxiliary_device_init(aux);
- if (ret)
- return ret;
- ret = devm_add_action_or_reset(dev, ti_sn65dsi86_uninit_aux, aux);
- if (ret)
- return ret;
+ unsigned int i;
+ const char * const ti_sn_bridge_supply_names[] = {
+ "vcca", "vcc", "vccio", "vpll",
+ };
- ret = auxiliary_device_add(aux);
- if (ret)
- return ret;
- ret = devm_add_action_or_reset(dev, ti_sn65dsi86_delete_aux, aux);
+ for (i = 0; i < SN_REGULATOR_SUPPLY_NUM; i++)
+ pdata->supplies[i].supply = ti_sn_bridge_supply_names[i];
- return ret;
+ return devm_regulator_bulk_get(pdata->dev, SN_REGULATOR_SUPPLY_NUM,
+ pdata->supplies);
}
static int ti_sn65dsi86_probe(struct i2c_client *client,
@@ -1454,27 +1511,24 @@ static int ti_sn65dsi86_probe(struct i2c_client *client,
pdata->regmap = devm_regmap_init_i2c(client,
&ti_sn65dsi86_regmap_config);
- if (IS_ERR(pdata->regmap)) {
- DRM_ERROR("regmap i2c init failed\n");
- return PTR_ERR(pdata->regmap);
- }
+ if (IS_ERR(pdata->regmap))
+ return dev_err_probe(dev, PTR_ERR(pdata->regmap),
+ "regmap i2c init failed\n");
- pdata->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
- if (IS_ERR(pdata->enable_gpio)) {
- DRM_ERROR("failed to get enable gpio from DT\n");
- ret = PTR_ERR(pdata->enable_gpio);
- return ret;
- }
+ pdata->enable_gpio = devm_gpiod_get_optional(dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(pdata->enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(pdata->enable_gpio),
+ "failed to get enable gpio from DT\n");
ret = ti_sn65dsi86_parse_regulators(pdata);
- if (ret) {
- DRM_ERROR("failed to parse regulators\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to parse regulators\n");
pdata->refclk = devm_clk_get_optional(dev, "refclk");
if (IS_ERR(pdata->refclk))
- return PTR_ERR(pdata->refclk);
+ return dev_err_probe(dev, PTR_ERR(pdata->refclk),
+ "failed to get reference clock\n");
pm_runtime_enable(dev);
ret = devm_add_action_or_reset(dev, ti_sn65dsi86_runtime_disable, dev);
@@ -1490,10 +1544,11 @@ static int ti_sn65dsi86_probe(struct i2c_client *client,
* motiviation here is to solve the chicken-and-egg problem of probe
* ordering. The bridge wants the panel to be there when it probes.
* The panel wants its HPD GPIO (provided by sn65dsi86 on some boards)
- * when it probes. There will soon be other devices (DDC I2C bus, PWM)
- * that have the same problem. Having sub-devices allows the some sub
- * devices to finish probing even if others return -EPROBE_DEFER and
- * gets us around the problems.
+ * when it probes. The panel and maybe backlight might want the DDC
+ * bus. Soon the PWM provided by the bridge chip will have the same
+ * problem. Having sub-devices allows the some sub devices to finish
+ * probing even if others return -EPROBE_DEFER and gets us around the
+ * problems.
*/
if (IS_ENABLED(CONFIG_OF_GPIO)) {
@@ -1502,7 +1557,13 @@ static int ti_sn65dsi86_probe(struct i2c_client *client,
return ret;
}
- return ti_sn65dsi86_add_aux_device(pdata, &pdata->bridge_aux, "bridge");
+ /*
+ * NOTE: At the end of the AUX channel probe we'll add the aux device
+ * for the bridge. This is because the bridge can't be used until the
+ * AUX channel is there and this is a very simple solution to the
+ * dependency problem.
+ */
+ return ti_sn65dsi86_add_aux_device(pdata, &pdata->aux_aux, "aux");
}
static struct i2c_device_id ti_sn65dsi86_id[] = {
@@ -1539,12 +1600,18 @@ static int __init ti_sn65dsi86_init(void)
if (ret)
goto err_main_was_registered;
- ret = auxiliary_driver_register(&ti_sn_bridge_driver);
+ ret = auxiliary_driver_register(&ti_sn_aux_driver);
if (ret)
goto err_gpio_was_registered;
+ ret = auxiliary_driver_register(&ti_sn_bridge_driver);
+ if (ret)
+ goto err_aux_was_registered;
+
return 0;
+err_aux_was_registered:
+ auxiliary_driver_unregister(&ti_sn_aux_driver);
err_gpio_was_registered:
ti_sn_gpio_unregister();
err_main_was_registered:
@@ -1557,6 +1624,7 @@ module_init(ti_sn65dsi86_init);
static void __exit ti_sn65dsi86_exit(void)
{
auxiliary_driver_unregister(&ti_sn_bridge_driver);
+ auxiliary_driver_unregister(&ti_sn_aux_driver);
ti_sn_gpio_unregister();
i2c_del_driver(&ti_sn65dsi86_driver);
}
diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c
index 9335d9d6cf9a..74bd4a76b253 100644
--- a/drivers/gpu/drm/drm_aperture.c
+++ b/drivers/gpu/drm/drm_aperture.c
@@ -33,6 +33,10 @@
*
* .. code-block:: c
*
+ * static const struct drm_driver example_driver = {
+ * ...
+ * };
+ *
* static int remove_conflicting_framebuffers(struct pci_dev *pdev)
* {
* bool primary = false;
@@ -46,7 +50,7 @@
* #endif
*
* return drm_aperture_remove_conflicting_framebuffers(base, size, primary,
- * "example driver");
+ * &example_driver);
* }
*
* static int probe(struct pci_dev *pdev)
@@ -74,7 +78,7 @@
*
* Drivers that are susceptible to being removed by other drivers, such as
* generic EFI or VESA drivers, have to register themselves as owners of their
- * given framebuffer memory. Ownership of the framebuffer memory is achived
+ * given framebuffer memory. Ownership of the framebuffer memory is achieved
* by calling devm_aperture_acquire_from_firmware(). On success, the driver
* is the owner of the framebuffer range. The function fails if the
* framebuffer is already by another driver. See below for an example.
@@ -274,7 +278,7 @@ static void drm_aperture_detach_drivers(resource_size_t base, resource_size_t si
* @base: the aperture's base address in physical memory
* @size: aperture size in bytes
* @primary: also kick vga16fb if present
- * @name: requesting driver name
+ * @req_driver: requesting DRM driver
*
* This function removes graphics device drivers which use memory range described by
* @base and @size.
@@ -283,7 +287,7 @@ static void drm_aperture_detach_drivers(resource_size_t base, resource_size_t si
* 0 on success, or a negative errno code otherwise
*/
int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
- bool primary, const char *name)
+ bool primary, const struct drm_driver *req_driver)
{
#if IS_REACHABLE(CONFIG_FB)
struct apertures_struct *a;
@@ -296,7 +300,7 @@ int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_
a->ranges[0].base = base;
a->ranges[0].size = size;
- ret = remove_conflicting_framebuffers(a, name, primary);
+ ret = remove_conflicting_framebuffers(a, req_driver->name, primary);
kfree(a);
if (ret)
@@ -312,7 +316,7 @@ EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers);
/**
* drm_aperture_remove_conflicting_pci_framebuffers - remove existing framebuffers for PCI devices
* @pdev: PCI device
- * @name: requesting driver name
+ * @req_driver: requesting DRM driver
*
* This function removes graphics device drivers using memory range configured
* for any of @pdev's memory bars. The function assumes that PCI device with
@@ -321,7 +325,8 @@ EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers);
* Returns:
* 0 on success, or a negative errno code otherwise
*/
-int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name)
+int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
+ const struct drm_driver *req_driver)
{
resource_size_t base, size;
int bar, ret = 0;
@@ -339,7 +344,7 @@ int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const
* otherwise the vga fbdev driver falls over.
*/
#if IS_REACHABLE(CONFIG_FB)
- ret = remove_conflicting_pci_framebuffers(pdev, name);
+ ret = remove_conflicting_pci_framebuffers(pdev, req_driver->name);
#endif
if (ret == 0)
ret = vga_remove_vgacon(pdev);
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index d820423fac32..ff1416cd609a 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -660,7 +660,7 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state,
return -ENOSPC;
}
- clips = drm_plane_get_damage_clips(new_plane_state);
+ clips = __drm_plane_get_damage_clips(new_plane_state);
num_clips = drm_plane_get_damage_clips_count(new_plane_state);
/* Make sure damage clips are valid and inside the fb. */
@@ -723,7 +723,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
* clocks, scaler units, bandwidth and fifo limits shared among a group of
* planes or CRTCs, and so on) it makes sense to model these as independent
* objects. Drivers then need to do similar state tracking and commit ordering for
- * such private (since not exposed to userpace) objects as the atomic core and
+ * such private (since not exposed to userspace) objects as the atomic core and
* helpers already provide for connectors, planes and CRTCs.
*
* To make this easier on drivers the atomic core provides some support to track
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index bc3487964fb5..2c0c6ec92820 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -35,6 +35,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_print.h>
#include <drm/drm_self_refresh_helper.h>
@@ -633,7 +634,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
* connectors and a NULL mode.
*
* The other way around is true as well. enable != 0
- * iff connectors are attached and a mode is set.
+ * implies that connectors are attached and a mode is set.
*/
new_crtc_state->mode_changed = true;
new_crtc_state->connectors_changed = true;
@@ -1685,7 +1686,7 @@ static void commit_work(struct work_struct *work)
}
/**
- * drm_atomic_helper_async_check - check if state can be commited asynchronously
+ * drm_atomic_helper_async_check - check if state can be committed asynchronously
* @dev: DRM device
* @state: the driver state object
*
@@ -1694,7 +1695,7 @@ static void commit_work(struct work_struct *work)
* but just do in-place changes on the current state.
*
* It will return 0 if the commit can happen in an asynchronous fashion or error
- * if not. Note that error just mean it can't be commited asynchronously, if it
+ * if not. Note that error just mean it can't be committed asynchronously, if it
* fails the commit should be treated like a normal synchronous commit.
*/
int drm_atomic_helper_async_check(struct drm_device *dev,
@@ -2405,6 +2406,15 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
ret = funcs->prepare_fb(plane, new_plane_state);
if (ret)
goto fail;
+ } else {
+ WARN_ON_ONCE(funcs->cleanup_fb);
+
+ if (!drm_core_check_feature(dev, DRIVER_GEM))
+ continue;
+
+ ret = drm_gem_plane_helper_prepare_fb(plane, new_plane_state);
+ if (ret)
+ goto fail;
}
}
@@ -2573,7 +2583,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
*
* This function can only be savely used when planes are not allowed to move
* between different CRTCs because this function doesn't handle inter-CRTC
- * depencies. Callers need to ensure that either no such depencies exist,
+ * dependencies. Callers need to ensure that either no such dependencies exist,
* resolve them through ordering of commit calls or through some other means.
*/
void
@@ -2710,7 +2720,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
/**
* drm_atomic_helper_swap_state - store atomic state into current sw state
* @state: atomic state
- * @stall: stall for preceeding commits
+ * @stall: stall for preceding commits
*
* This function stores the atomic state into the current state pointers in all
* driver objects. It should be called after all failing steps have been done
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 7e48d40600ff..909f31833181 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -48,7 +48,7 @@
* in all its forms: The monster ATOMIC IOCTL itself, code for GET_PROPERTY and
* SET_PROPERTY IOCTLs. Plus interface functions for compatibility helpers and
* drivers which have special needs to construct their own atomic updates, e.g.
- * for load detect or similiar.
+ * for load detect or similar.
*/
/**
@@ -753,7 +753,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
* restore the state it wants on VT switch. So if the userspace
* tries to change the link_status from GOOD to BAD, driver
* silently rejects it and returns a 0. This prevents userspace
- * from accidently breaking the display when it restores the
+ * from accidentally breaking the display when it restores the
* state.
*/
if (state->link_status != DRM_LINK_STATUS_GOOD)
@@ -1064,7 +1064,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
* DOC: explicit fencing properties
*
* Explicit fencing allows userspace to control the buffer synchronization
- * between devices. A Fence or a group of fences are transfered to/from
+ * between devices. A Fence or a group of fences are transferred to/from
* userspace using Sync File fds and there are two DRM properties for that.
* IN_FENCE_FD on each DRM Plane to send fences to the kernel and
* OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index b59b26a71ad5..60a6b21474b1 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -52,7 +52,7 @@
*
* In addition only one &drm_master can be the current master for a &drm_device.
* It can be switched through the DROP_MASTER and SET_MASTER IOCTL, or
- * implicitly through closing/openeing the primary device node. See also
+ * implicitly through closing/opening the primary device node. See also
* drm_is_current_master().
*
* Clients can authenticate against the current master (if it matches their own)
@@ -61,6 +61,36 @@
* trusted clients.
*/
+static bool drm_is_current_master_locked(struct drm_file *fpriv)
+{
+ lockdep_assert_once(lockdep_is_held(&fpriv->master_lookup_lock) ||
+ lockdep_is_held(&fpriv->minor->dev->master_mutex));
+
+ return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
+}
+
+/**
+ * drm_is_current_master - checks whether @priv is the current master
+ * @fpriv: DRM file private
+ *
+ * Checks whether @fpriv is current master on its device. This decides whether a
+ * client is allowed to run DRM_MASTER IOCTLs.
+ *
+ * Most of the modern IOCTL which require DRM_MASTER are for kernel modesetting
+ * - the current master is assumed to own the non-shareable display hardware.
+ */
+bool drm_is_current_master(struct drm_file *fpriv)
+{
+ bool ret;
+
+ spin_lock(&fpriv->master_lookup_lock);
+ ret = drm_is_current_master_locked(fpriv);
+ spin_unlock(&fpriv->master_lookup_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_is_current_master);
+
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_auth *auth = data;
@@ -135,16 +165,18 @@ static void drm_set_master(struct drm_device *dev, struct drm_file *fpriv,
static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
{
struct drm_master *old_master;
+ struct drm_master *new_master;
lockdep_assert_held_once(&dev->master_mutex);
WARN_ON(fpriv->is_master);
old_master = fpriv->master;
- fpriv->master = drm_master_create(dev);
- if (!fpriv->master) {
- fpriv->master = old_master;
+ new_master = drm_master_create(dev);
+ if (!new_master)
return -ENOMEM;
- }
+ spin_lock(&fpriv->master_lookup_lock);
+ fpriv->master = new_master;
+ spin_unlock(&fpriv->master_lookup_lock);
fpriv->is_master = 1;
fpriv->authenticated = 1;
@@ -223,7 +255,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
if (ret)
goto out_unlock;
- if (drm_is_current_master(file_priv))
+ if (drm_is_current_master_locked(file_priv))
goto out_unlock;
if (dev->master) {
@@ -272,7 +304,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
if (ret)
goto out_unlock;
- if (!drm_is_current_master(file_priv)) {
+ if (!drm_is_current_master_locked(file_priv)) {
ret = -EINVAL;
goto out_unlock;
}
@@ -303,10 +335,13 @@ int drm_master_open(struct drm_file *file_priv)
* any master object for render clients
*/
mutex_lock(&dev->master_mutex);
- if (!dev->master)
+ if (!dev->master) {
ret = drm_new_set_master(dev, file_priv);
- else
+ } else {
+ spin_lock(&file_priv->master_lookup_lock);
file_priv->master = drm_master_get(dev->master);
+ spin_unlock(&file_priv->master_lookup_lock);
+ }
mutex_unlock(&dev->master_mutex);
return ret;
@@ -322,7 +357,7 @@ void drm_master_release(struct drm_file *file_priv)
if (file_priv->magic)
idr_remove(&file_priv->master->magic_map, file_priv->magic);
- if (!drm_is_current_master(file_priv))
+ if (!drm_is_current_master_locked(file_priv))
goto out;
drm_legacy_lock_master_cleanup(dev, master);
@@ -344,22 +379,6 @@ out:
}
/**
- * drm_is_current_master - checks whether @priv is the current master
- * @fpriv: DRM file private
- *
- * Checks whether @fpriv is current master on its device. This decides whether a
- * client is allowed to run DRM_MASTER IOCTLs.
- *
- * Most of the modern IOCTL which require DRM_MASTER are for kernel modesetting
- * - the current master is assumed to own the non-shareable display hardware.
- */
-bool drm_is_current_master(struct drm_file *fpriv)
-{
- return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
-}
-EXPORT_SYMBOL(drm_is_current_master);
-
-/**
* drm_master_get - reference a master pointer
* @master: &struct drm_master
*
@@ -372,6 +391,31 @@ struct drm_master *drm_master_get(struct drm_master *master)
}
EXPORT_SYMBOL(drm_master_get);
+/**
+ * drm_file_get_master - reference &drm_file.master of @file_priv
+ * @file_priv: DRM file private
+ *
+ * Increments the reference count of @file_priv's &drm_file.master and returns
+ * the &drm_file.master. If @file_priv has no &drm_file.master, returns NULL.
+ *
+ * Master pointers returned from this function should be unreferenced using
+ * drm_master_put().
+ */
+struct drm_master *drm_file_get_master(struct drm_file *file_priv)
+{
+ struct drm_master *master = NULL;
+
+ spin_lock(&file_priv->master_lookup_lock);
+ if (!file_priv->master)
+ goto unlock;
+ master = drm_master_get(file_priv->master);
+
+unlock:
+ spin_unlock(&file_priv->master_lookup_lock);
+ return master;
+}
+EXPORT_SYMBOL(drm_file_get_master);
+
static void drm_master_destroy(struct kref *kref)
{
struct drm_master *master = container_of(kref, struct drm_master, refcount);
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 044acd07c153..a8ed66751c2d 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -28,6 +28,7 @@
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_encoder.h>
+#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
@@ -225,6 +226,15 @@ err_reset_bridge:
bridge->dev = NULL;
bridge->encoder = NULL;
list_del(&bridge->chain_node);
+
+#ifdef CONFIG_OF
+ DRM_ERROR("failed to attach bridge %pOF to encoder %s: %d\n",
+ bridge->of_node, encoder->name, ret);
+#else
+ DRM_ERROR("failed to attach bridge to encoder %s: %d\n",
+ encoder->name, ret);
+#endif
+
return ret;
}
EXPORT_SYMBOL(drm_bridge_attach);
@@ -972,7 +982,7 @@ drm_atomic_bridge_propagate_bus_flags(struct drm_bridge *bridge,
bridge_state->output_bus_cfg.flags = output_flags;
/*
- * Propage the output flags to the input end of the bridge. Again, it's
+ * Propagate the output flags to the input end of the bridge. Again, it's
* not necessarily what all bridges want, but that's what most of them
* do, and by doing that by default we avoid forcing drivers to
* duplicate the "dummy propagation" logic.
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index ae8e4d76209c..fcca21e8efac 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -1502,7 +1502,7 @@ int drm_legacy_freebufs(struct drm_device *dev, void *data,
*
* Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
* about each buffer into user space. For PCI buffers, it calls vm_mmap() with
- * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
+ * offset equal to 0, which drm_mmap() interprets as PCI buffers and calls
* drm_mmap_dma().
*/
int __drm_legacy_mapbufs(struct drm_device *dev, void *data, int *p,
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index 546599f19a93..30cc59fe6ef7 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -170,7 +170,7 @@ drm_clflush_virt_range(void *addr, unsigned long length)
for (; addr < end; addr += size)
clflushopt(addr);
clflushopt(end - 1); /* force serialisation */
- mb(); /*Ensure that evry data cache line entry is flushed*/
+ mb(); /*Ensure that every data cache line entry is flushed*/
return;
}
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index da39e7ff6965..2ba257b1ae20 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -2414,6 +2414,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
struct drm_mode_modeinfo u_mode;
struct drm_mode_modeinfo __user *mode_ptr;
uint32_t __user *encoder_ptr;
+ bool is_current_master;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP;
@@ -2444,9 +2445,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
out_resp->connector_type = connector->connector_type;
out_resp->connector_type_id = connector->connector_type_id;
+ is_current_master = drm_is_current_master(file_priv);
+
mutex_lock(&dev->mode_config.mutex);
if (out_resp->count_modes == 0) {
- if (drm_is_current_master(file_priv))
+ if (is_current_master)
connector->funcs->fill_modes(connector,
dev->mode_config.max_width,
dev->mode_config.max_height);
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 1ca51addb589..edb772947cb4 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -262,6 +262,8 @@ int drm_plane_register_all(struct drm_device *dev);
void drm_plane_unregister_all(struct drm_device *dev);
int drm_plane_check_pixel_format(struct drm_plane *plane,
u32 format, u64 modifier);
+struct drm_mode_rect *
+__drm_plane_get_damage_clips(const struct drm_plane_state *state);
/* drm_bridge.c */
void drm_bridge_detach(struct drm_bridge *bridge);
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index 3a4126dc2520..8eeff0c7bdd4 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -34,44 +34,6 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
-/**
- * DOC: overview
- *
- * FB_DAMAGE_CLIPS is an optional plane property which provides a means to
- * specify a list of damage rectangles on a plane in framebuffer coordinates of
- * the framebuffer attached to the plane. In current context damage is the area
- * of plane framebuffer that has changed since last plane update (also called
- * page-flip), irrespective of whether currently attached framebuffer is same as
- * framebuffer attached during last plane update or not.
- *
- * FB_DAMAGE_CLIPS is a hint to kernel which could be helpful for some drivers
- * to optimize internally especially for virtual devices where each framebuffer
- * change needs to be transmitted over network, usb, etc.
- *
- * Since FB_DAMAGE_CLIPS is a hint so it is an optional property. User-space can
- * ignore damage clips property and in that case driver will do a full plane
- * update. In case damage clips are provided then it is guaranteed that the area
- * inside damage clips will be updated to plane. For efficiency driver can do
- * full update or can update more than specified in damage clips. Since driver
- * is free to read more, user-space must always render the entire visible
- * framebuffer. Otherwise there can be corruptions. Also, if a user-space
- * provides damage clips which doesn't encompass the actual damage to
- * framebuffer (since last plane update) can result in incorrect rendering.
- *
- * FB_DAMAGE_CLIPS is a blob property with the layout of blob data is simply an
- * array of &drm_mode_rect. Unlike plane &drm_plane_state.src coordinates,
- * damage clips are not in 16.16 fixed point. Similar to plane src in
- * framebuffer, damage clips cannot be negative. In damage clip, x1/y1 are
- * inclusive and x2/y2 are exclusive. While kernel does not error for overlapped
- * damage clips, it is strongly discouraged.
- *
- * Drivers that are interested in damage interface for plane should enable
- * FB_DAMAGE_CLIPS property by calling drm_plane_enable_fb_damage_clips().
- * Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and
- * drm_atomic_helper_damage_iter_next() helper iterator function to get damage
- * rectangles clipped to &drm_plane_state.src.
- */
-
static void convert_clip_rect_to_rect(const struct drm_clip_rect *src,
struct drm_mode_rect *dest,
uint32_t num_clips, uint32_t src_inc)
@@ -88,22 +50,6 @@ static void convert_clip_rect_to_rect(const struct drm_clip_rect *src,
}
/**
- * drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property.
- * @plane: Plane on which to enable damage clips property.
- *
- * This function lets driver to enable the damage clips property on a plane.
- */
-void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
-{
- struct drm_device *dev = plane->dev;
- struct drm_mode_config *config = &dev->mode_config;
-
- drm_object_attach_property(&plane->base, config->prop_fb_damage_clips,
- 0);
-}
-EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
-
-/**
* drm_atomic_helper_check_plane_damage - Verify plane damage on atomic_check.
* @state: The driver state object.
* @plane_state: Plane state for which to verify damage.
@@ -170,7 +116,7 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
int ret = 0;
/*
- * When called from ioctl, we are interruptable, but not when called
+ * When called from ioctl, we are interruptible, but not when called
* internally (ie. defio worker)
*/
drm_modeset_acquire_init(&ctx,
@@ -282,7 +228,7 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
if (!state || !state->crtc || !state->fb || !state->visible)
return;
- iter->clips = drm_helper_get_plane_damage_clips(state);
+ iter->clips = (struct drm_rect *)drm_plane_get_damage_clips(state);
iter->num_clips = drm_plane_get_damage_clips_count(state);
/* Round down for x1/y1 and round up for x2/y2 to catch all pixels */
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 3d7182001004..b0a826489488 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -91,6 +91,7 @@ static int drm_clients_info(struct seq_file *m, void *data)
mutex_lock(&dev->filelist_mutex);
list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
struct task_struct *task;
+ bool is_current_master = drm_is_current_master(priv);
rcu_read_lock(); /* locks pid_task()->comm */
task = pid_task(priv->pid, PIDTYPE_PID);
@@ -99,7 +100,7 @@ static int drm_clients_info(struct seq_file *m, void *data)
task ? task->comm : "<unknown>",
pid_vnr(priv->pid),
priv->minor->index,
- drm_is_current_master(priv) ? 'y' : 'n',
+ is_current_master ? 'y' : 'n',
priv->authenticated ? 'y' : 'n',
from_kuid_munged(seq_user_ns(m), uid),
priv->magic);
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
index 3dd70d813f69..bbc3bc4ba844 100644
--- a/drivers/gpu/drm/drm_debugfs_crc.c
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -46,10 +46,10 @@
* it reached a given hardware component (a CRC sampling "source").
*
* Userspace can control generation of CRCs in a given CRTC by writing to the
- * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC.
- * Accepted values are source names (which are driver-specific) and the "auto"
- * keyword, which will let the driver select a default source of frame CRCs
- * for this CRTC.
+ * file dri/0/crtc-N/crc/control in debugfs, with N being the :ref:`index of
+ * the CRTC<crtc_index>`. Accepted values are source names (which are
+ * driver-specific) and the "auto" keyword, which will let the driver select a
+ * default source of frame CRCs for this CRTC.
*
* Once frame CRC generation is enabled, userspace can capture them by reading
* the dri/0/crtc-N/crc/data file. Each line in that file contains the frame
diff --git a/drivers/gpu/drm/drm_dp_aux_bus.c b/drivers/gpu/drm/drm_dp_aux_bus.c
new file mode 100644
index 000000000000..298ea7a49591
--- /dev/null
+++ b/drivers/gpu/drm/drm_dp_aux_bus.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * The DP AUX bus is used for devices that are connected over a DisplayPort
+ * AUX bus. The devices on the far side of the bus are referred to as
+ * endpoints in this code.
+ *
+ * Commonly there is only one device connected to the DP AUX bus: a panel.
+ * Though historically panels (even DP panels) have been modeled as simple
+ * platform devices, putting them under the DP AUX bus allows the panel driver
+ * to perform transactions on that bus.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drm_dp_aux_bus.h>
+#include <drm/drm_dp_helper.h>
+
+/**
+ * dp_aux_ep_match() - The match function for the dp_aux_bus.
+ * @dev: The device to match.
+ * @drv: The driver to try to match against.
+ *
+ * At the moment, we just match on device tree.
+ *
+ * Return: True if this driver matches this device; false otherwise.
+ */
+static int dp_aux_ep_match(struct device *dev, struct device_driver *drv)
+{
+ return !!of_match_device(drv->of_match_table, dev);
+}
+
+/**
+ * dp_aux_ep_probe() - The probe function for the dp_aux_bus.
+ * @dev: The device to probe.
+ *
+ * Calls through to the endpoint driver probe.
+ *
+ * Return: 0 if no error or negative error code.
+ */
+static int dp_aux_ep_probe(struct device *dev)
+{
+ struct dp_aux_ep_driver *aux_ep_drv = to_dp_aux_ep_drv(dev->driver);
+ struct dp_aux_ep_device *aux_ep = to_dp_aux_ep_dev(dev);
+ int ret;
+
+ ret = dev_pm_domain_attach(dev, true);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to attach to PM Domain\n");
+
+ ret = aux_ep_drv->probe(aux_ep);
+ if (ret)
+ dev_pm_domain_detach(dev, true);
+
+ return ret;
+}
+
+/**
+ * dp_aux_ep_remove() - The remove function for the dp_aux_bus.
+ * @dev: The device to remove.
+ *
+ * Calls through to the endpoint driver remove.
+ *
+ */
+static void dp_aux_ep_remove(struct device *dev)
+{
+ struct dp_aux_ep_driver *aux_ep_drv = to_dp_aux_ep_drv(dev->driver);
+ struct dp_aux_ep_device *aux_ep = to_dp_aux_ep_dev(dev);
+
+ if (aux_ep_drv->remove)
+ aux_ep_drv->remove(aux_ep);
+ dev_pm_domain_detach(dev, true);
+}
+
+/**
+ * dp_aux_ep_shutdown() - The shutdown function for the dp_aux_bus.
+ * @dev: The device to shutdown.
+ *
+ * Calls through to the endpoint driver shutdown.
+ */
+static void dp_aux_ep_shutdown(struct device *dev)
+{
+ struct dp_aux_ep_driver *aux_ep_drv;
+
+ if (!dev->driver)
+ return;
+
+ aux_ep_drv = to_dp_aux_ep_drv(dev->driver);
+ if (aux_ep_drv->shutdown)
+ aux_ep_drv->shutdown(to_dp_aux_ep_dev(dev));
+}
+
+static struct bus_type dp_aux_bus_type = {
+ .name = "dp-aux",
+ .match = dp_aux_ep_match,
+ .probe = dp_aux_ep_probe,
+ .remove = dp_aux_ep_remove,
+ .shutdown = dp_aux_ep_shutdown,
+};
+
+static ssize_t modalias_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return of_device_modalias(dev, buf, PAGE_SIZE);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *dp_aux_ep_dev_attrs[] = {
+ &dev_attr_modalias.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(dp_aux_ep_dev);
+
+/**
+ * dp_aux_ep_dev_release() - Free memory for the dp_aux_ep device
+ * @dev: The device to free.
+ *
+ * Return: 0 if no error or negative error code.
+ */
+static void dp_aux_ep_dev_release(struct device *dev)
+{
+ kfree(to_dp_aux_ep_dev(dev));
+}
+
+static struct device_type dp_aux_device_type_type = {
+ .groups = dp_aux_ep_dev_groups,
+ .uevent = of_device_uevent_modalias,
+ .release = dp_aux_ep_dev_release,
+};
+
+/**
+ * of_dp_aux_ep_destroy() - Destroy an DP AUX endpoint device
+ * @dev: The device to destroy.
+ * @data: Not used
+ *
+ * This is just used as a callback by of_dp_aux_depopulate_ep_devices() and
+ * is called for _all_ of the child devices of the device providing the AUX bus.
+ * We'll only act on those that are of type "dp_aux_bus_type".
+ *
+ * This function is effectively an inverse of what's in the loop
+ * in of_dp_aux_populate_ep_devices().
+ *
+ * Return: 0 if no error or negative error code.
+ */
+static int of_dp_aux_ep_destroy(struct device *dev, void *data)
+{
+ struct device_node *np = dev->of_node;
+
+ if (dev->bus != &dp_aux_bus_type)
+ return 0;
+
+ if (!of_node_check_flag(np, OF_POPULATED))
+ return 0;
+
+ of_node_clear_flag(np, OF_POPULATED);
+ of_node_put(np);
+
+ device_unregister(dev);
+
+ return 0;
+}
+
+/**
+ * of_dp_aux_depopulate_ep_devices() - Undo of_dp_aux_populate_ep_devices
+ * @aux: The AUX channel whose devices we want to depopulate
+ *
+ * This will destroy all devices that were created
+ * by of_dp_aux_populate_ep_devices().
+ */
+void of_dp_aux_depopulate_ep_devices(struct drm_dp_aux *aux)
+{
+ device_for_each_child_reverse(aux->dev, NULL, of_dp_aux_ep_destroy);
+}
+EXPORT_SYMBOL_GPL(of_dp_aux_depopulate_ep_devices);
+
+/**
+ * of_dp_aux_populate_ep_devices() - Populate the endpoint devices on the DP AUX
+ * @aux: The AUX channel whose devices we want to populate. It is required that
+ * drm_dp_aux_init() has already been called for this AUX channel.
+ *
+ * This will populate all the devices under the "aux-bus" node of the device
+ * providing the AUX channel (AKA aux->dev).
+ *
+ * When this function finishes, it is _possible_ (but not guaranteed) that
+ * our sub-devices will have finished probing. It should be noted that if our
+ * sub-devices return -EPROBE_DEFER that we will not return any error codes
+ * ourselves but our sub-devices will _not_ have actually probed successfully
+ * yet. There may be other cases (maybe added in the future?) where sub-devices
+ * won't have been probed yet when this function returns, so it's best not to
+ * rely on that.
+ *
+ * If this function succeeds you should later make sure you call
+ * of_dp_aux_depopulate_ep_devices() to undo it, or just use the devm version
+ * of this function.
+ *
+ * Return: 0 if no error or negative error code.
+ */
+int of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux)
+{
+ struct device_node *bus, *np;
+ struct dp_aux_ep_device *aux_ep;
+ int ret;
+
+ /* drm_dp_aux_init() should have been called already; warn if not */
+ WARN_ON_ONCE(!aux->ddc.algo);
+
+ if (!aux->dev->of_node)
+ return 0;
+
+ bus = of_get_child_by_name(aux->dev->of_node, "aux-bus");
+ if (!bus)
+ return 0;
+
+ for_each_available_child_of_node(bus, np) {
+ if (of_node_test_and_set_flag(np, OF_POPULATED))
+ continue;
+
+ aux_ep = kzalloc(sizeof(*aux_ep), GFP_KERNEL);
+ if (!aux_ep)
+ continue;
+ aux_ep->aux = aux;
+
+ aux_ep->dev.parent = aux->dev;
+ aux_ep->dev.bus = &dp_aux_bus_type;
+ aux_ep->dev.type = &dp_aux_device_type_type;
+ aux_ep->dev.of_node = of_node_get(np);
+ dev_set_name(&aux_ep->dev, "aux-%s", dev_name(aux->dev));
+
+ ret = device_register(&aux_ep->dev);
+ if (ret) {
+ dev_err(aux->dev, "Failed to create AUX EP for %pOF: %d\n", np, ret);
+ of_node_clear_flag(np, OF_POPULATED);
+ of_node_put(np);
+
+ /*
+ * As per docs of device_register(), call this instead
+ * of kfree() directly for error cases.
+ */
+ put_device(&aux_ep->dev);
+
+ /*
+ * Following in the footsteps of of_i2c_register_devices(),
+ * we won't fail the whole function here--we'll just
+ * continue registering any other devices we find.
+ */
+ }
+ }
+
+ of_node_put(bus);
+
+ return 0;
+}
+
+static void of_dp_aux_depopulate_ep_devices_void(void *data)
+{
+ of_dp_aux_depopulate_ep_devices(data);
+}
+
+/**
+ * devm_of_dp_aux_populate_ep_devices() - devm wrapper for of_dp_aux_populate_ep_devices()
+ * @aux: The AUX channel whose devices we want to populate
+ *
+ * Handles freeing w/ devm on the device "aux->dev".
+ *
+ * Return: 0 if no error or negative error code.
+ */
+int devm_of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux)
+{
+ int ret;
+
+ ret = of_dp_aux_populate_ep_devices(aux);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(aux->dev,
+ of_dp_aux_depopulate_ep_devices_void,
+ aux);
+}
+EXPORT_SYMBOL_GPL(devm_of_dp_aux_populate_ep_devices);
+
+int __dp_aux_dp_driver_register(struct dp_aux_ep_driver *drv, struct module *owner)
+{
+ drv->driver.owner = owner;
+ drv->driver.bus = &dp_aux_bus_type;
+
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(__dp_aux_dp_driver_register);
+
+void dp_aux_dp_driver_unregister(struct dp_aux_ep_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(dp_aux_dp_driver_unregister);
+
+static int __init dp_aux_bus_init(void)
+{
+ int ret;
+
+ ret = bus_register(&dp_aux_bus_type);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void __exit dp_aux_bus_exit(void)
+{
+ bus_unregister(&dp_aux_bus_type);
+}
+
+subsys_initcall(dp_aux_bus_init);
+module_exit(dp_aux_bus_exit);
+
+MODULE_AUTHOR("Douglas Anderson <dianders@chromium.org>");
+MODULE_DESCRIPTION("DRM DisplayPort AUX bus");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 55b53df6ce34..6d0f2c447f3b 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -33,9 +33,17 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include <drm/drm_dp_mst_helper.h>
+#include <drm/drm_panel.h>
#include "drm_crtc_helper_internal.h"
+struct dp_aux_backlight {
+ struct backlight_device *base;
+ struct drm_dp_aux *aux;
+ struct drm_edp_backlight_info info;
+ bool enabled;
+};
+
/**
* DOC: dp helpers
*
@@ -764,7 +772,7 @@ int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
* It's left up to the driver to check the
* DP dual mode adapter's max TMDS clock.
*
- * Unfortunatley it looks like branch devices
+ * Unfortunately it looks like branch devices
* may not fordward that the DP dual mode i2c
* access so we just usually get i2c nak :(
*/
@@ -1357,7 +1365,7 @@ static int drm_dp_i2c_msg_duration(const struct drm_dp_aux_msg *msg,
}
/*
- * Deterine how many retries should be attempted to successfully transfer
+ * Determine how many retries should be attempted to successfully transfer
* the specified message, based on the estimated durations of the
* i2c and AUX transfers.
*/
@@ -1410,7 +1418,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
/*
* While timeouts can be errors, they're usually normal
* behavior (for instance, when a driver tries to
- * communicate with a non-existant DisplayPort device).
+ * communicate with a non-existent DisplayPort device).
* Avoid spamming the kernel log with timeout errors.
*/
if (ret == -ETIMEDOUT)
@@ -3115,3 +3123,459 @@ int drm_dp_pcon_convert_rgb_to_ycbcr(struct drm_dp_aux *aux, u8 color_spc)
return 0;
}
EXPORT_SYMBOL(drm_dp_pcon_convert_rgb_to_ycbcr);
+
+/**
+ * drm_edp_backlight_set_level() - Set the backlight level of an eDP panel via AUX
+ * @aux: The DP AUX channel to use
+ * @bl: Backlight capability info from drm_edp_backlight_init()
+ * @level: The brightness level to set
+ *
+ * Sets the brightness level of an eDP panel's backlight. Note that the panel's backlight must
+ * already have been enabled by the driver by calling drm_edp_backlight_enable().
+ *
+ * Returns: %0 on success, negative error code on failure
+ */
+int drm_edp_backlight_set_level(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl,
+ u16 level)
+{
+ int ret;
+ u8 buf[2] = { 0 };
+
+ if (bl->lsb_reg_used) {
+ buf[0] = (level & 0xff00) >> 8;
+ buf[1] = (level & 0x00ff);
+ } else {
+ buf[0] = level;
+ }
+
+ ret = drm_dp_dpcd_write(aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB, buf, sizeof(buf));
+ if (ret != sizeof(buf)) {
+ drm_err(aux->drm_dev,
+ "%s: Failed to write aux backlight level: %d\n",
+ aux->name, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_edp_backlight_set_level);
+
+static int
+drm_edp_backlight_set_enable(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl,
+ bool enable)
+{
+ int ret;
+ u8 buf;
+
+ /* The panel uses something other then DPCD for enabling its backlight */
+ if (!bl->aux_enable)
+ return 0;
+
+ ret = drm_dp_dpcd_readb(aux, DP_EDP_DISPLAY_CONTROL_REGISTER, &buf);
+ if (ret != 1) {
+ drm_err(aux->drm_dev, "%s: Failed to read eDP display control register: %d\n",
+ aux->name, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+ if (enable)
+ buf |= DP_EDP_BACKLIGHT_ENABLE;
+ else
+ buf &= ~DP_EDP_BACKLIGHT_ENABLE;
+
+ ret = drm_dp_dpcd_writeb(aux, DP_EDP_DISPLAY_CONTROL_REGISTER, buf);
+ if (ret != 1) {
+ drm_err(aux->drm_dev, "%s: Failed to write eDP display control register: %d\n",
+ aux->name, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * drm_edp_backlight_enable() - Enable an eDP panel's backlight using DPCD
+ * @aux: The DP AUX channel to use
+ * @bl: Backlight capability info from drm_edp_backlight_init()
+ * @level: The initial backlight level to set via AUX, if there is one
+ *
+ * This function handles enabling DPCD backlight controls on a panel over DPCD, while additionally
+ * restoring any important backlight state such as the given backlight level, the brightness byte
+ * count, backlight frequency, etc.
+ *
+ * Note that certain panels, while supporting brightness level controls over DPCD, may not support
+ * having their backlights enabled via the standard %DP_EDP_DISPLAY_CONTROL_REGISTER. On such panels
+ * &drm_edp_backlight_info.aux_enable will be set to %false, this function will skip the step of
+ * programming the %DP_EDP_DISPLAY_CONTROL_REGISTER, and the driver must perform the required
+ * implementation specific step for enabling the backlight after calling this function.
+ *
+ * Returns: %0 on success, negative error code on failure.
+ */
+int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl,
+ const u16 level)
+{
+ int ret;
+ u8 dpcd_buf, new_dpcd_buf;
+
+ ret = drm_dp_dpcd_readb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf);
+ if (ret != 1) {
+ drm_dbg_kms(aux->drm_dev,
+ "%s: Failed to read backlight mode: %d\n", aux->name, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ new_dpcd_buf = dpcd_buf;
+
+ if ((dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) != DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) {
+ new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK;
+ new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD;
+
+ if (bl->pwmgen_bit_count) {
+ ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count);
+ if (ret != 1)
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux pwmgen bit count: %d\n",
+ aux->name, ret);
+ }
+ }
+
+ if (bl->pwm_freq_pre_divider) {
+ ret = drm_dp_dpcd_writeb(aux, DP_EDP_BACKLIGHT_FREQ_SET, bl->pwm_freq_pre_divider);
+ if (ret != 1)
+ drm_dbg_kms(aux->drm_dev,
+ "%s: Failed to write aux backlight frequency: %d\n",
+ aux->name, ret);
+ else
+ new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE;
+ }
+
+ if (new_dpcd_buf != dpcd_buf) {
+ ret = drm_dp_dpcd_writeb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf);
+ if (ret != 1) {
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux backlight mode: %d\n",
+ aux->name, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+ }
+
+ ret = drm_edp_backlight_set_level(aux, bl, level);
+ if (ret < 0)
+ return ret;
+ ret = drm_edp_backlight_set_enable(aux, bl, true);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_edp_backlight_enable);
+
+/**
+ * drm_edp_backlight_disable() - Disable an eDP backlight using DPCD, if supported
+ * @aux: The DP AUX channel to use
+ * @bl: Backlight capability info from drm_edp_backlight_init()
+ *
+ * This function handles disabling DPCD backlight controls on a panel over AUX. Note that some
+ * panels have backlights that are enabled/disabled by other means, despite having their brightness
+ * values controlled through DPCD. On such panels &drm_edp_backlight_info.aux_enable will be set to
+ * %false, this function will become a no-op (and we will skip updating
+ * %DP_EDP_DISPLAY_CONTROL_REGISTER), and the driver must take care to perform it's own
+ * implementation specific step for disabling the backlight.
+ *
+ * Returns: %0 on success or no-op, negative error code on failure.
+ */
+int drm_edp_backlight_disable(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl)
+{
+ int ret;
+
+ ret = drm_edp_backlight_set_enable(aux, bl, false);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_edp_backlight_disable);
+
+static inline int
+drm_edp_backlight_probe_max(struct drm_dp_aux *aux, struct drm_edp_backlight_info *bl,
+ u16 driver_pwm_freq_hz, const u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE])
+{
+ int fxp, fxp_min, fxp_max, fxp_actual, f = 1;
+ int ret;
+ u8 pn, pn_min, pn_max;
+
+ ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT, &pn);
+ if (ret != 1) {
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap: %d\n",
+ aux->name, ret);
+ return -ENODEV;
+ }
+
+ pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
+ bl->max = (1 << pn) - 1;
+ if (!driver_pwm_freq_hz)
+ return 0;
+
+ /*
+ * Set PWM Frequency divider to match desired frequency provided by the driver.
+ * The PWM Frequency is calculated as 27Mhz / (F x P).
+ * - Where F = PWM Frequency Pre-Divider value programmed by field 7:0 of the
+ * EDP_BACKLIGHT_FREQ_SET register (DPCD Address 00728h)
+ * - Where P = 2^Pn, where Pn is the value programmed by field 4:0 of the
+ * EDP_PWMGEN_BIT_COUNT register (DPCD Address 00724h)
+ */
+
+ /* Find desired value of (F x P)
+ * Note that, if F x P is out of supported range, the maximum value or minimum value will
+ * applied automatically. So no need to check that.
+ */
+ fxp = DIV_ROUND_CLOSEST(1000 * DP_EDP_BACKLIGHT_FREQ_BASE_KHZ, driver_pwm_freq_hz);
+
+ /* Use highest possible value of Pn for more granularity of brightness adjustment while
+ * satisfying the conditions below.
+ * - Pn is in the range of Pn_min and Pn_max
+ * - F is in the range of 1 and 255
+ * - FxP is within 25% of desired value.
+ * Note: 25% is arbitrary value and may need some tweak.
+ */
+ ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min);
+ if (ret != 1) {
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap min: %d\n",
+ aux->name, ret);
+ return 0;
+ }
+ ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max);
+ if (ret != 1) {
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap max: %d\n",
+ aux->name, ret);
+ return 0;
+ }
+ pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
+ pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
+
+ /* Ensure frequency is within 25% of desired value */
+ fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
+ fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
+ if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) {
+ drm_dbg_kms(aux->drm_dev,
+ "%s: Driver defined backlight frequency (%d) out of range\n",
+ aux->name, driver_pwm_freq_hz);
+ return 0;
+ }
+
+ for (pn = pn_max; pn >= pn_min; pn--) {
+ f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
+ fxp_actual = f << pn;
+ if (fxp_min <= fxp_actual && fxp_actual <= fxp_max)
+ break;
+ }
+
+ ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, pn);
+ if (ret != 1) {
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux pwmgen bit count: %d\n",
+ aux->name, ret);
+ return 0;
+ }
+ bl->pwmgen_bit_count = pn;
+ bl->max = (1 << pn) - 1;
+
+ if (edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP) {
+ bl->pwm_freq_pre_divider = f;
+ drm_dbg_kms(aux->drm_dev, "%s: Using backlight frequency from driver (%dHz)\n",
+ aux->name, driver_pwm_freq_hz);
+ }
+
+ return 0;
+}
+
+static inline int
+drm_edp_backlight_probe_level(struct drm_dp_aux *aux, struct drm_edp_backlight_info *bl,
+ u8 *current_mode)
+{
+ int ret;
+ u8 buf[2];
+ u8 mode_reg;
+
+ ret = drm_dp_dpcd_readb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &mode_reg);
+ if (ret != 1) {
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to read backlight mode: %d\n",
+ aux->name, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ *current_mode = (mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK);
+ if (*current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) {
+ int size = 1 + bl->lsb_reg_used;
+
+ ret = drm_dp_dpcd_read(aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB, buf, size);
+ if (ret != size) {
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to read backlight level: %d\n",
+ aux->name, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ if (bl->lsb_reg_used)
+ return (buf[0] << 8) | buf[1];
+ else
+ return buf[0];
+ }
+
+ /*
+ * If we're not in DPCD control mode yet, the programmed brightness value is meaningless and
+ * the driver should assume max brightness
+ */
+ return bl->max;
+}
+
+/**
+ * drm_edp_backlight_init() - Probe a display panel's TCON using the standard VESA eDP backlight
+ * interface.
+ * @aux: The DP aux device to use for probing
+ * @bl: The &drm_edp_backlight_info struct to fill out with information on the backlight
+ * @driver_pwm_freq_hz: Optional PWM frequency from the driver in hz
+ * @edp_dpcd: A cached copy of the eDP DPCD
+ * @current_level: Where to store the probed brightness level
+ * @current_mode: Where to store the currently set backlight control mode
+ *
+ * Initializes a &drm_edp_backlight_info struct by probing @aux for it's backlight capabilities,
+ * along with also probing the current and maximum supported brightness levels.
+ *
+ * If @driver_pwm_freq_hz is non-zero, this will be used as the backlight frequency. Otherwise, the
+ * default frequency from the panel is used.
+ *
+ * Returns: %0 on success, negative error code on failure.
+ */
+int
+drm_edp_backlight_init(struct drm_dp_aux *aux, struct drm_edp_backlight_info *bl,
+ u16 driver_pwm_freq_hz, const u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE],
+ u16 *current_level, u8 *current_mode)
+{
+ int ret;
+
+ if (edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP)
+ bl->aux_enable = true;
+ if (edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
+ bl->lsb_reg_used = true;
+
+ ret = drm_edp_backlight_probe_max(aux, bl, driver_pwm_freq_hz, edp_dpcd);
+ if (ret < 0)
+ return ret;
+
+ ret = drm_edp_backlight_probe_level(aux, bl, current_mode);
+ if (ret < 0)
+ return ret;
+ *current_level = ret;
+
+ drm_dbg_kms(aux->drm_dev,
+ "%s: Found backlight level=%d/%d pwm_freq_pre_divider=%d mode=%x\n",
+ aux->name, *current_level, bl->max, bl->pwm_freq_pre_divider, *current_mode);
+ drm_dbg_kms(aux->drm_dev,
+ "%s: Backlight caps: pwmgen_bit_count=%d lsb_reg_used=%d aux_enable=%d\n",
+ aux->name, bl->pwmgen_bit_count, bl->lsb_reg_used, bl->aux_enable);
+ return 0;
+}
+EXPORT_SYMBOL(drm_edp_backlight_init);
+
+#if IS_BUILTIN(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
+ (IS_MODULE(CONFIG_DRM_KMS_HELPER) && IS_MODULE(CONFIG_BACKLIGHT_CLASS_DEVICE))
+
+static int dp_aux_backlight_update_status(struct backlight_device *bd)
+{
+ struct dp_aux_backlight *bl = bl_get_data(bd);
+ u16 brightness = backlight_get_brightness(bd);
+ int ret = 0;
+
+ if (!backlight_is_blank(bd)) {
+ if (!bl->enabled) {
+ drm_edp_backlight_enable(bl->aux, &bl->info, brightness);
+ bl->enabled = true;
+ return 0;
+ }
+ ret = drm_edp_backlight_set_level(bl->aux, &bl->info, brightness);
+ } else {
+ if (bl->enabled) {
+ drm_edp_backlight_disable(bl->aux, &bl->info);
+ bl->enabled = false;
+ }
+ }
+
+ return ret;
+}
+
+static const struct backlight_ops dp_aux_bl_ops = {
+ .update_status = dp_aux_backlight_update_status,
+};
+
+/**
+ * drm_panel_dp_aux_backlight - create and use DP AUX backlight
+ * @panel: DRM panel
+ * @aux: The DP AUX channel to use
+ *
+ * Use this function to create and handle backlight if your panel
+ * supports backlight control over DP AUX channel using DPCD
+ * registers as per VESA's standard backlight control interface.
+ *
+ * When the panel is enabled backlight will be enabled after a
+ * successful call to &drm_panel_funcs.enable()
+ *
+ * When the panel is disabled backlight will be disabled before the
+ * call to &drm_panel_funcs.disable().
+ *
+ * A typical implementation for a panel driver supporting backlight
+ * control over DP AUX will call this function at probe time.
+ * Backlight will then be handled transparently without requiring
+ * any intervention from the driver.
+ *
+ * drm_panel_dp_aux_backlight() must be called after the call to drm_panel_init().
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int drm_panel_dp_aux_backlight(struct drm_panel *panel, struct drm_dp_aux *aux)
+{
+ struct dp_aux_backlight *bl;
+ struct backlight_properties props = { 0 };
+ u16 current_level;
+ u8 current_mode;
+ u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
+ int ret;
+
+ if (!panel || !panel->dev || !aux)
+ return -EINVAL;
+
+ ret = drm_dp_dpcd_read(aux, DP_EDP_DPCD_REV, edp_dpcd,
+ EDP_DISPLAY_CTL_CAP_SIZE);
+ if (ret < 0)
+ return ret;
+
+ if (!drm_edp_backlight_supported(edp_dpcd)) {
+ DRM_DEV_INFO(panel->dev, "DP AUX backlight is not supported\n");
+ return 0;
+ }
+
+ bl = devm_kzalloc(panel->dev, sizeof(*bl), GFP_KERNEL);
+ if (!bl)
+ return -ENOMEM;
+
+ bl->aux = aux;
+
+ ret = drm_edp_backlight_init(aux, &bl->info, 0, edp_dpcd,
+ &current_level, &current_mode);
+ if (ret < 0)
+ return ret;
+
+ props.type = BACKLIGHT_RAW;
+ props.brightness = current_level;
+ props.max_brightness = bl->info.max;
+
+ bl->base = devm_backlight_device_register(panel->dev, "dp_aux_backlight",
+ panel->dev, bl,
+ &dp_aux_bl_ops, &props);
+ if (IS_ERR(bl->base))
+ return PTR_ERR(bl->base);
+
+ backlight_disable(bl->base);
+
+ panel->backlight = bl->base;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_panel_dp_aux_backlight);
+
+#endif
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index ad0795afc21c..86d13d6bc463 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2872,11 +2872,13 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
idx += tosend + 1;
ret = drm_dp_send_sideband_msg(mgr, up, chunk, idx);
- if (unlikely(ret) && drm_debug_enabled(DRM_UT_DP)) {
- struct drm_printer p = drm_debug_printer(DBG_PREFIX);
+ if (ret) {
+ if (drm_debug_enabled(DRM_UT_DP)) {
+ struct drm_printer p = drm_debug_printer(DBG_PREFIX);
- drm_printf(&p, "sideband msg failed to send\n");
- drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
+ drm_printf(&p, "sideband msg failed to send\n");
+ drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
+ }
return ret;
}
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 8804ec7d3215..7a5097467ba5 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -249,7 +249,7 @@ void drm_minor_release(struct drm_minor *minor)
* Finally when everything is up and running and ready for userspace the device
* instance can be published using drm_dev_register().
*
- * There is also deprecated support for initalizing device instances using
+ * There is also deprecated support for initializing device instances using
* bus-specific helpers and the &drm_driver.load callback. But due to
* backwards-compatibility needs the device instance have to be published too
* early, which requires unpretty global locking to make safe and is therefore
@@ -379,7 +379,7 @@ void drm_minor_release(struct drm_minor *minor)
* shortcoming however, drm_dev_unplug() marks the drm_device as unplugged before
* drm_atomic_helper_shutdown() is called. This means that if the disable code
* paths are protected, they will not run on regular driver module unload,
- * possibily leaving the hardware enabled.
+ * possibly leaving the hardware enabled.
*/
/**
diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index ff602f7ec65b..46a3c1b62463 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -98,7 +98,7 @@ void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_payload,
{
int i;
- /* Protect against someone accidently changing struct size */
+ /* Protect against someone accidentally changing struct size */
BUILD_BUG_ON(sizeof(*pps_payload) !=
DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1 + 1);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 81d5f2524246..6325877c5fd6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1919,7 +1919,7 @@ EXPORT_SYMBOL(drm_add_override_edid_modes);
* level, drivers must make all reasonable efforts to expose it as an I2C
* adapter and use drm_get_edid() instead of abusing this function.
*
- * The EDID may be overridden using debugfs override_edid or firmare EDID
+ * The EDID may be overridden using debugfs override_edid or firmware EDID
* (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
* order. Having either of them bypasses actual EDID reads.
*
@@ -5906,7 +5906,7 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
* (ie.vic==0 and s3d_struct==0) we will still send it if we
* know that the sink can handle it. This is based on a
* suggestion in HDMI 2.0 Appendix F. Apparently some sinks
- * have trouble realizing that they shuld switch from 3D to 2D
+ * have trouble realizing that they should switch from 3D to 2D
* mode if the source simply stops sending the infoframe when
* it wants to switch from 3D to 2D.
*/
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d77a24507d30..3ab078321045 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -565,7 +565,7 @@ struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
goto err_release;
/*
- * TODO: We really should be smarter here and alloc an apperture
+ * TODO: We really should be smarter here and alloc an aperture
* for each IORESOURCE_MEM resource helper->dev->dev has and also
* init the ranges of the appertures based on the resources.
* Note some drivers currently count on there being only 1 empty
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index d4f0bac6f8f8..ed25168619fc 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -176,6 +176,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor)
init_waitqueue_head(&file->event_wait);
file->event_space = 4096; /* set aside 4k for event buffer */
+ spin_lock_init(&file->master_lookup_lock);
mutex_init(&file->event_read_lock);
if (drm_core_check_feature(dev, DRIVER_GEM))
@@ -404,7 +405,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
*
* RETURNS:
*
- * 0 on success or negative errno value on falure.
+ * 0 on success or negative errno value on failure.
*/
int drm_open(struct inode *inode, struct file *filp)
{
@@ -547,7 +548,7 @@ EXPORT_SYMBOL(drm_release_noglobal);
* @offset: offset to read
*
* This function must be used by drivers as their &file_operations.read
- * method iff they use DRM events for asynchronous signalling to userspace.
+ * method if they use DRM events for asynchronous signalling to userspace.
* Since events are used by the KMS API for vblank and page flip completion this
* means all modern display drivers must use it.
*
@@ -640,7 +641,7 @@ EXPORT_SYMBOL(drm_read);
* @wait: poll waiter table
*
* This function must be used by drivers as their &file_operations.read method
- * iff they use DRM events for asynchronous signalling to userspace. Since
+ * if they use DRM events for asynchronous signalling to userspace. Since
* events are used by the KMS API for vblank and page flip completion this means
* all modern display drivers must use it.
*
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index 0e885cd34107..5231104b1498 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -412,7 +412,7 @@ EXPORT_SYMBOL(drm_fb_blit_rect_dstclip);
* of the display and the framebuffer mismatch, the copy function will
* attempt to convert between them.
*
- * See drm_fb_blit_rect_dstclip() for more inforamtion.
+ * See drm_fb_blit_rect_dstclip() for more information.
*
* Returns:
* 0 on success, or a negative error code otherwise.
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 4d01464b6f95..07f5abc875e9 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -404,6 +404,9 @@ static void drm_mode_rmfb_work_fn(struct work_struct *w)
struct drm_framebuffer *fb =
list_first_entry(&arg->fbs, typeof(*fb), filp_head);
+ drm_dbg_kms(fb->dev,
+ "Removing [FB:%d] from all active usage due to RMFB ioctl\n",
+ fb->base.id);
list_del_init(&fb->filp_head);
drm_framebuffer_remove(fb);
}
@@ -981,6 +984,10 @@ retry:
if (plane->state->fb != fb)
continue;
+ drm_dbg_kms(dev,
+ "Disabling [PLANE:%d:%s] because [FB:%d] is removed\n",
+ plane->base.id, plane->name, fb->base.id);
+
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
@@ -990,6 +997,11 @@ retry:
if (disable_crtcs && plane_state->crtc->primary == plane) {
struct drm_crtc_state *crtc_state;
+ drm_dbg_kms(dev,
+ "Disabling [CRTC:%d:%s] because [FB:%d] is removed\n",
+ plane_state->crtc->base.id,
+ plane_state->crtc->name, fb->base.id);
+
crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc);
ret = drm_atomic_add_affected_connectors(state, plane_state->crtc);
@@ -1052,6 +1064,10 @@ static void legacy_remove_fb(struct drm_framebuffer *fb)
/* remove from any CRTC */
drm_for_each_crtc(crtc, dev) {
if (crtc->primary->fb == fb) {
+ drm_dbg_kms(dev,
+ "Disabling [CRTC:%d:%s] because [FB:%d] is removed\n",
+ crtc->base.id, crtc->name, fb->base.id);
+
/* should turn off the crtc */
if (drm_crtc_force_disable(crtc))
DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
@@ -1059,8 +1075,12 @@ static void legacy_remove_fb(struct drm_framebuffer *fb)
}
drm_for_each_plane(plane, dev) {
- if (plane->fb == fb)
+ if (plane->fb == fb) {
+ drm_dbg_kms(dev,
+ "Disabling [PLANE:%d:%s] because [FB:%d] is removed\n",
+ plane->base.id, plane->name, fb->base.id);
drm_plane_force_disable(plane);
+ }
}
drm_modeset_unlock_all(dev);
}
@@ -1090,7 +1110,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
/*
* drm ABI mandates that we remove any deleted framebuffers from active
- * useage. But since most sane clients only remove framebuffers they no
+ * usage. But since most sane clients only remove framebuffers they no
* longer need, try to optimize this away.
*
* Since we're holding a reference ourselves, observing a refcount of 1
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index d62fb1a3c916..09c820045859 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -901,7 +901,7 @@ err:
}
/**
- * drm_gem_open - initalizes GEM file-private structures at devnode open time
+ * drm_gem_open - initializes GEM file-private structures at devnode open time
* @dev: drm_device which is being opened by userspace
* @file_private: drm file-private structure to set up
*
@@ -936,7 +936,7 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
* drm_gem_object_release - release GEM buffer object resources
* @obj: GEM buffer object
*
- * This releases any structures and resources used by @obj and is the invers of
+ * This releases any structures and resources used by @obj and is the inverse of
* drm_gem_object_init().
*/
void
@@ -974,28 +974,6 @@ drm_gem_object_free(struct kref *kref)
EXPORT_SYMBOL(drm_gem_object_free);
/**
- * drm_gem_object_put_locked - release a GEM buffer object reference
- * @obj: GEM buffer object
- *
- * This releases a reference to @obj. Callers must hold the
- * &drm_device.struct_mutex lock when calling this function, even when the
- * driver doesn't use &drm_device.struct_mutex for anything.
- *
- * For drivers not encumbered with legacy locking use
- * drm_gem_object_put() instead.
- */
-void
-drm_gem_object_put_locked(struct drm_gem_object *obj)
-{
- if (obj) {
- WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
-
- kref_put(&obj->refcount, drm_gem_object_free);
- }
-}
-EXPORT_SYMBOL(drm_gem_object_put_locked);
-
-/**
* drm_gem_vm_open - vma->ops->open implementation for GEM
* @vma: VM area structure
*
@@ -1148,15 +1126,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
return -EACCES;
}
- if (node->readonly) {
- if (vma->vm_flags & VM_WRITE) {
- drm_gem_object_put(obj);
- return -EINVAL;
- }
-
- vma->vm_flags &= ~VM_MAYWRITE;
- }
-
ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT,
vma);
@@ -1311,6 +1280,9 @@ EXPORT_SYMBOL(drm_gem_unlock_reservations);
* @fence_array: array of dma_fence * for the job to block on.
* @fence: the dma_fence to add to the list of dependencies.
*
+ * This functions consumes the reference for @fence both on success and error
+ * cases.
+ *
* Returns:
* 0 on success, or an error on failing to expand the array.
*/
diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c
index a27135084ae5..e570398abd78 100644
--- a/drivers/gpu/drm/drm_gem_atomic_helper.c
+++ b/drivers/gpu/drm/drm_gem_atomic_helper.c
@@ -52,7 +52,7 @@
*
* The helpers for shadow-buffered planes establish and release mappings,
* and provide struct drm_shadow_plane_state, which stores the plane's mapping
- * for commit-tail functons.
+ * for commit-tail functions.
*
* Shadow-buffered planes can easily be enabled by using the provided macros
* %DRM_GEM_SHADOW_PLANE_FUNCS and %DRM_GEM_SHADOW_PLANE_HELPER_FUNCS.
@@ -135,6 +135,9 @@
* GEM based framebuffer drivers which have their buffers always pinned in
* memory.
*
+ * This function is the default implementation for GEM drivers of
+ * &drm_plane_helper_funcs.prepare_fb if no callback is provided.
+ *
* See drm_atomic_set_fence_for_plane() for a discussion of implicit and
* explicit fencing in atomic modeset updates.
*/
@@ -180,6 +183,27 @@ EXPORT_SYMBOL(drm_gem_simple_display_pipe_prepare_fb);
*/
/**
+ * __drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
+ * @plane: the plane
+ * @new_shadow_plane_state: the new shadow-buffered plane state
+ *
+ * This function duplicates shadow-buffered plane state. This is helpful for drivers
+ * that subclass struct drm_shadow_plane_state.
+ *
+ * The function does not duplicate existing mappings of the shadow buffers.
+ * Mappings are maintained during the atomic commit by the plane's prepare_fb
+ * and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb()
+ * for corresponding helpers.
+ */
+void
+__drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane,
+ struct drm_shadow_plane_state *new_shadow_plane_state)
+{
+ __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base);
+}
+EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state);
+
+/**
* drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
* @plane: the plane
*
@@ -208,13 +232,26 @@ drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane)
new_shadow_plane_state = kzalloc(sizeof(*new_shadow_plane_state), GFP_KERNEL);
if (!new_shadow_plane_state)
return NULL;
- __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base);
+ __drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state);
return &new_shadow_plane_state->base;
}
EXPORT_SYMBOL(drm_gem_duplicate_shadow_plane_state);
/**
+ * __drm_gem_destroy_shadow_plane_state - cleans up shadow-buffered plane state
+ * @shadow_plane_state: the shadow-buffered plane state
+ *
+ * This function cleans up shadow-buffered plane state. Helpful for drivers that
+ * subclass struct drm_shadow_plane_state.
+ */
+void __drm_gem_destroy_shadow_plane_state(struct drm_shadow_plane_state *shadow_plane_state)
+{
+ __drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base);
+}
+EXPORT_SYMBOL(__drm_gem_destroy_shadow_plane_state);
+
+/**
* drm_gem_destroy_shadow_plane_state - deletes shadow-buffered plane state
* @plane: the plane
* @plane_state: the plane state of type struct drm_shadow_plane_state
@@ -229,12 +266,27 @@ void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane,
struct drm_shadow_plane_state *shadow_plane_state =
to_drm_shadow_plane_state(plane_state);
- __drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base);
+ __drm_gem_destroy_shadow_plane_state(shadow_plane_state);
kfree(shadow_plane_state);
}
EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state);
/**
+ * __drm_gem_reset_shadow_plane - resets a shadow-buffered plane
+ * @plane: the plane
+ * @shadow_plane_state: the shadow-buffered plane state
+ *
+ * This function resets state for shadow-buffered planes. Helpful
+ * for drivers that subclass struct drm_shadow_plane_state.
+ */
+void __drm_gem_reset_shadow_plane(struct drm_plane *plane,
+ struct drm_shadow_plane_state *shadow_plane_state)
+{
+ __drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base);
+}
+EXPORT_SYMBOL(__drm_gem_reset_shadow_plane);
+
+/**
* drm_gem_reset_shadow_plane - resets a shadow-buffered plane
* @plane: the plane
*
@@ -255,7 +307,7 @@ void drm_gem_reset_shadow_plane(struct drm_plane *plane)
shadow_plane_state = kzalloc(sizeof(*shadow_plane_state), GFP_KERNEL);
if (!shadow_plane_state)
return;
- __drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base);
+ __drm_gem_reset_shadow_plane(plane, shadow_plane_state);
}
EXPORT_SYMBOL(drm_gem_reset_shadow_plane);
@@ -278,10 +330,7 @@ int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *p
{
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- struct drm_gem_object *obj;
- struct dma_buf_map map;
int ret;
- size_t i;
if (!fb)
return 0;
@@ -290,27 +339,7 @@ int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *p
if (ret)
return ret;
- for (i = 0; i < ARRAY_SIZE(shadow_plane_state->map); ++i) {
- obj = drm_gem_fb_get_obj(fb, i);
- if (!obj)
- continue;
- ret = drm_gem_vmap(obj, &map);
- if (ret)
- goto err_drm_gem_vunmap;
- shadow_plane_state->map[i] = map;
- }
-
- return 0;
-
-err_drm_gem_vunmap:
- while (i) {
- --i;
- obj = drm_gem_fb_get_obj(fb, i);
- if (!obj)
- continue;
- drm_gem_vunmap(obj, &shadow_plane_state->map[i]);
- }
- return ret;
+ return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
}
EXPORT_SYMBOL(drm_gem_prepare_shadow_fb);
@@ -322,25 +351,17 @@ EXPORT_SYMBOL(drm_gem_prepare_shadow_fb);
* This function implements struct &drm_plane_helper_funcs.cleanup_fb.
* This function unmaps all buffer objects of the plane's framebuffer.
*
- * See drm_gem_prepare_shadow_fb() for more inforamtion.
+ * See drm_gem_prepare_shadow_fb() for more information.
*/
void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- size_t i = ARRAY_SIZE(shadow_plane_state->map);
- struct drm_gem_object *obj;
if (!fb)
return;
- while (i) {
- --i;
- obj = drm_gem_fb_get_obj(fb, i);
- if (!obj)
- continue;
- drm_gem_vunmap(obj, &shadow_plane_state->map[i]);
- }
+ drm_gem_fb_vunmap(fb, shadow_plane_state->map);
}
EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb);
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index e2c68822e05c..3c75d79dbb65 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -15,6 +15,8 @@
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_modeset_helper.h>
+#include "drm_internal.h"
+
#define AFBC_HEADER_SIZE 16
#define AFBC_TH_LAYOUT_ALIGNMENT 8
#define AFBC_HDR_ALIGN 64
@@ -48,7 +50,7 @@
struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb,
unsigned int plane)
{
- if (plane >= 4)
+ if (plane >= ARRAY_SIZE(fb->obj))
return NULL;
return fb->obj[plane];
@@ -62,7 +64,8 @@ drm_gem_fb_init(struct drm_device *dev,
struct drm_gem_object **obj, unsigned int num_planes,
const struct drm_framebuffer_funcs *funcs)
{
- int ret, i;
+ unsigned int i;
+ int ret;
drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
@@ -86,9 +89,9 @@ drm_gem_fb_init(struct drm_device *dev,
*/
void drm_gem_fb_destroy(struct drm_framebuffer *fb)
{
- int i;
+ size_t i;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < ARRAY_SIZE(fb->obj); i++)
drm_gem_object_put(fb->obj[i]);
drm_framebuffer_cleanup(fb);
@@ -145,8 +148,9 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
const struct drm_framebuffer_funcs *funcs)
{
const struct drm_format_info *info;
- struct drm_gem_object *objs[4];
- int ret, i;
+ struct drm_gem_object *objs[DRM_FORMAT_MAX_PLANES];
+ unsigned int i;
+ int ret;
info = drm_get_format_info(dev, mode_cmd);
if (!info) {
@@ -187,9 +191,10 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
return 0;
err_gem_object_put:
- for (i--; i >= 0; i--)
+ while (i > 0) {
+ --i;
drm_gem_object_put(objs[i]);
-
+ }
return ret;
}
EXPORT_SYMBOL_GPL(drm_gem_fb_init_with_funcs);
@@ -306,6 +311,184 @@ drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
}
EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);
+/**
+ * drm_gem_fb_vmap - maps all framebuffer BOs into kernel address space
+ * @fb: the framebuffer
+ * @map: returns the mapping's address for each BO
+ * @data: returns the data address for each BO, can be NULL
+ *
+ * This function maps all buffer objects of the given framebuffer into
+ * kernel address space and stores them in struct dma_buf_map. If the
+ * mapping operation fails for one of the BOs, the function unmaps the
+ * already established mappings automatically.
+ *
+ * Callers that want to access a BO's stored data should pass @data.
+ * The argument returns the addresses of the data stored in each BO. This
+ * is different from @map if the framebuffer's offsets field is non-zero.
+ *
+ * See drm_gem_fb_vunmap() for unmapping.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
+ */
+int drm_gem_fb_vmap(struct drm_framebuffer *fb,
+ struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES],
+ struct dma_buf_map data[DRM_FORMAT_MAX_PLANES])
+{
+ struct drm_gem_object *obj;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) {
+ obj = drm_gem_fb_get_obj(fb, i);
+ if (!obj) {
+ dma_buf_map_clear(&map[i]);
+ continue;
+ }
+ ret = drm_gem_vmap(obj, &map[i]);
+ if (ret)
+ goto err_drm_gem_vunmap;
+ }
+
+ if (data) {
+ for (i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) {
+ memcpy(&data[i], &map[i], sizeof(data[i]));
+ if (dma_buf_map_is_null(&data[i]))
+ continue;
+ dma_buf_map_incr(&data[i], fb->offsets[i]);
+ }
+ }
+
+ return 0;
+
+err_drm_gem_vunmap:
+ while (i) {
+ --i;
+ obj = drm_gem_fb_get_obj(fb, i);
+ if (!obj)
+ continue;
+ drm_gem_vunmap(obj, &map[i]);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_fb_vmap);
+
+/**
+ * drm_gem_fb_vunmap - unmaps framebuffer BOs from kernel address space
+ * @fb: the framebuffer
+ * @map: mapping addresses as returned by drm_gem_fb_vmap()
+ *
+ * This function unmaps all buffer objects of the given framebuffer.
+ *
+ * See drm_gem_fb_vmap() for more information.
+ */
+void drm_gem_fb_vunmap(struct drm_framebuffer *fb,
+ struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES])
+{
+ unsigned int i = DRM_FORMAT_MAX_PLANES;
+ struct drm_gem_object *obj;
+
+ while (i) {
+ --i;
+ obj = drm_gem_fb_get_obj(fb, i);
+ if (!obj)
+ continue;
+ if (dma_buf_map_is_null(&map[i]))
+ continue;
+ drm_gem_vunmap(obj, &map[i]);
+ }
+}
+EXPORT_SYMBOL(drm_gem_fb_vunmap);
+
+/**
+ * drm_gem_fb_begin_cpu_access - prepares GEM buffer objects for CPU access
+ * @fb: the framebuffer
+ * @dir: access mode
+ *
+ * Prepares a framebuffer's GEM buffer objects for CPU access. This function
+ * must be called before accessing the BO data within the kernel. For imported
+ * BOs, the function calls dma_buf_begin_cpu_access().
+ *
+ * See drm_gem_fb_end_cpu_access() for signalling the end of CPU access.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
+ */
+int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir)
+{
+ struct dma_buf_attachment *import_attach;
+ struct drm_gem_object *obj;
+ size_t i;
+ int ret, ret2;
+
+ for (i = 0; i < ARRAY_SIZE(fb->obj); ++i) {
+ obj = drm_gem_fb_get_obj(fb, i);
+ if (!obj)
+ continue;
+ import_attach = obj->import_attach;
+ if (!import_attach)
+ continue;
+ ret = dma_buf_begin_cpu_access(import_attach->dmabuf, dir);
+ if (ret)
+ goto err_dma_buf_end_cpu_access;
+ }
+
+ return 0;
+
+err_dma_buf_end_cpu_access:
+ while (i) {
+ --i;
+ obj = drm_gem_fb_get_obj(fb, i);
+ if (!obj)
+ continue;
+ import_attach = obj->import_attach;
+ if (!import_attach)
+ continue;
+ ret2 = dma_buf_end_cpu_access(import_attach->dmabuf, dir);
+ if (ret2) {
+ drm_err(fb->dev,
+ "dma_buf_end_cpu_access() failed during error handling: %d\n",
+ ret2);
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_fb_begin_cpu_access);
+
+/**
+ * drm_gem_fb_end_cpu_access - signals end of CPU access to GEM buffer objects
+ * @fb: the framebuffer
+ * @dir: access mode
+ *
+ * Signals the end of CPU access to the given framebuffer's GEM buffer objects. This
+ * function must be paired with a corresponding call to drm_gem_fb_begin_cpu_access().
+ * For imported BOs, the function calls dma_buf_end_cpu_access().
+ *
+ * See also drm_gem_fb_begin_cpu_access().
+ */
+void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir)
+{
+ size_t i = ARRAY_SIZE(fb->obj);
+ struct dma_buf_attachment *import_attach;
+ struct drm_gem_object *obj;
+ int ret;
+
+ while (i) {
+ --i;
+ obj = drm_gem_fb_get_obj(fb, i);
+ if (!obj)
+ continue;
+ import_attach = obj->import_attach;
+ if (!import_attach)
+ continue;
+ ret = dma_buf_end_cpu_access(import_attach->dmabuf, dir);
+ if (ret)
+ drm_err(fb->dev, "dma_buf_end_cpu_access() failed: %d\n", ret);
+ }
+}
+EXPORT_SYMBOL(drm_gem_fb_end_cpu_access);
+
static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 6d625cee7a6a..a61946374c82 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -368,7 +368,7 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
}
/*
- * drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object
+ * drm_gem_shmem_vunmap - Unmap a virtual mapping for a shmem GEM object
* @shmem: shmem GEM object
* @map: Kernel virtual address where the SHMEM GEM object was mapped
*
@@ -505,13 +505,13 @@ int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
if (!args->pitch || !args->size) {
args->pitch = min_pitch;
- args->size = args->pitch * args->height;
+ args->size = PAGE_ALIGN(args->pitch * args->height);
} else {
/* ensure sane minimum values */
if (args->pitch < min_pitch)
args->pitch = min_pitch;
if (args->size < args->pitch * args->height)
- args->size = args->pitch * args->height;
+ args->size = PAGE_ALIGN(args->pitch * args->height);
}
shmem = drm_gem_shmem_create_with_handle(file, dev, args->size, &args->handle);
diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c
index 2a1229b8364e..43cf7e887d1a 100644
--- a/drivers/gpu/drm/drm_gem_vram_helper.c
+++ b/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -96,7 +96,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
* memory region. Call drm_gem_vram_offset() to retrieve this value. Typically
* it's used to program the hardware's scanout engine for framebuffers, set
* the cursor overlay's image for a mouse cursor, or use it as input to the
- * hardware's draing engine.
+ * hardware's drawing engine.
*
* To access a buffer object's memory from the DRM driver, call
* drm_gem_vram_vmap(). It maps the buffer into kernel address
@@ -1012,9 +1012,8 @@ static void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
* Helpers for integration with struct drm_device
*/
-/* deprecated; use drmm_vram_mm_init() */
-struct drm_vram_mm *drm_vram_helper_alloc_mm(
- struct drm_device *dev, uint64_t vram_base, size_t vram_size)
+static struct drm_vram_mm *drm_vram_helper_alloc_mm(struct drm_device *dev, uint64_t vram_base,
+ size_t vram_size)
{
int ret;
@@ -1036,9 +1035,8 @@ err_kfree:
dev->vram_mm = NULL;
return ERR_PTR(ret);
}
-EXPORT_SYMBOL(drm_vram_helper_alloc_mm);
-void drm_vram_helper_release_mm(struct drm_device *dev)
+static void drm_vram_helper_release_mm(struct drm_device *dev)
{
if (!dev->vram_mm)
return;
@@ -1047,7 +1045,6 @@ void drm_vram_helper_release_mm(struct drm_device *dev)
kfree(dev->vram_mm);
dev->vram_mm = NULL;
}
-EXPORT_SYMBOL(drm_vram_helper_release_mm);
static void drm_vram_mm_release(struct drm_device *dev, void *ptr)
{
diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c
index 910108ccaae1..ca9b8f697202 100644
--- a/drivers/gpu/drm/drm_hdcp.c
+++ b/drivers/gpu/drm/drm_hdcp.c
@@ -280,7 +280,7 @@ exit:
* https://www.digital-cp.com/sites/default/files/specifications/HDCP%20on%20HDMI%20Specification%20Rev2_2_Final1.pdf
*
* Returns:
- * Count of the revoked KSVs or -ve error number incase of the failure.
+ * Count of the revoked KSVs or -ve error number in case of the failure.
*/
int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
u32 ksv_count)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index f454e0424086..be4a52dc4d6f 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -426,7 +426,7 @@ done:
}
/**
- * drm_noop - DRM no-op ioctl implemntation
+ * drm_noop - DRM no-op ioctl implementation
* @dev: DRM device for the ioctl
* @data: data pointer for the ioctl
* @file_priv: DRM file for the ioctl call
@@ -446,7 +446,7 @@ int drm_noop(struct drm_device *dev, void *data,
EXPORT_SYMBOL(drm_noop);
/**
- * drm_invalid_op - DRM invalid ioctl implemntation
+ * drm_invalid_op - DRM invalid ioctl implementation
* @dev: DRM device for the ioctl
* @data: data pointer for the ioctl
* @file_priv: DRM file for the ioctl call
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index c3bd664ea733..13e1d5c4ec82 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -60,50 +60,14 @@
#include <drm/drm.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
-#include <drm/drm_irq.h>
+#include <drm/drm_legacy.h>
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include "drm_internal.h"
-/**
- * DOC: irq helpers
- *
- * The DRM core provides very simple support helpers to enable IRQ handling on a
- * device through the drm_irq_install() and drm_irq_uninstall() functions. This
- * only supports devices with a single interrupt on the main device stored in
- * &drm_device.dev and set as the device paramter in drm_dev_alloc().
- *
- * These IRQ helpers are strictly optional. Drivers which roll their own only
- * need to set &drm_device.irq_enabled to signal the DRM core that vblank
- * interrupts are working. Since these helpers don't automatically clean up the
- * requested interrupt like e.g. devm_request_irq() they're not really
- * recommended.
- */
-
-/**
- * drm_irq_install - install IRQ handler
- * @dev: DRM device
- * @irq: IRQ number to install the handler for
- *
- * Initializes the IRQ related data. Installs the handler, calling the driver
- * &drm_driver.irq_preinstall and &drm_driver.irq_postinstall functions before
- * and after the installation.
- *
- * This is the simplified helper interface provided for drivers with no special
- * needs. Drivers which need to install interrupt handlers for multiple
- * interrupts must instead set &drm_device.irq_enabled to signal the DRM core
- * that vblank interrupts are available.
- *
- * @irq must match the interrupt number that would be passed to request_irq(),
- * if called directly instead of using this helper function.
- *
- * &drm_driver.irq_handler is called to handle the registered interrupt.
- *
- * Returns:
- * Zero on success or a negative error code on failure.
- */
-int drm_irq_install(struct drm_device *dev, int irq)
+#if IS_ENABLED(CONFIG_DRM_LEGACY)
+static int drm_legacy_irq_install(struct drm_device *dev, int irq)
{
int ret;
unsigned long sh_flags = 0;
@@ -140,7 +104,7 @@ int drm_irq_install(struct drm_device *dev, int irq)
if (ret < 0) {
dev->irq_enabled = false;
if (drm_core_check_feature(dev, DRIVER_LEGACY))
- vga_client_register(to_pci_dev(dev->dev), NULL, NULL, NULL);
+ vga_client_unregister(to_pci_dev(dev->dev));
free_irq(irq, dev);
} else {
dev->irq = irq;
@@ -148,25 +112,8 @@ int drm_irq_install(struct drm_device *dev, int irq)
return ret;
}
-EXPORT_SYMBOL(drm_irq_install);
-/**
- * drm_irq_uninstall - uninstall the IRQ handler
- * @dev: DRM device
- *
- * Calls the driver's &drm_driver.irq_uninstall function and unregisters the IRQ
- * handler. This should only be called by drivers which used drm_irq_install()
- * to set up their interrupt handler. Other drivers must only reset
- * &drm_device.irq_enabled to false.
- *
- * Note that for kernel modesetting drivers it is a bug if this function fails.
- * The sanity checks are only to catch buggy user modesetting drivers which call
- * the same function through an ioctl.
- *
- * Returns:
- * Zero on success or a negative error code on failure.
- */
-int drm_irq_uninstall(struct drm_device *dev)
+int drm_legacy_irq_uninstall(struct drm_device *dev)
{
unsigned long irqflags;
bool irq_enabled;
@@ -203,7 +150,7 @@ int drm_irq_uninstall(struct drm_device *dev)
DRM_DEBUG("irq=%d\n", dev->irq);
if (drm_core_check_feature(dev, DRIVER_LEGACY))
- vga_client_register(to_pci_dev(dev->dev), NULL, NULL, NULL);
+ vga_client_unregister(to_pci_dev(dev->dev));
if (dev->driver->irq_uninstall)
dev->driver->irq_uninstall(dev);
@@ -212,41 +159,8 @@ int drm_irq_uninstall(struct drm_device *dev)
return 0;
}
-EXPORT_SYMBOL(drm_irq_uninstall);
+EXPORT_SYMBOL(drm_legacy_irq_uninstall);
-static void devm_drm_irq_uninstall(void *data)
-{
- drm_irq_uninstall(data);
-}
-
-/**
- * devm_drm_irq_install - install IRQ handler
- * @dev: DRM device
- * @irq: IRQ number to install the handler for
- *
- * devm_drm_irq_install is a help function of drm_irq_install.
- *
- * if the driver uses devm_drm_irq_install, there is no need
- * to call drm_irq_uninstall when the drm module get unloaded,
- * as this will done automagically.
- *
- * Returns:
- * Zero on success or a negative error code on failure.
- */
-int devm_drm_irq_install(struct drm_device *dev, int irq)
-{
- int ret;
-
- ret = drm_irq_install(dev, irq);
- if (ret)
- return ret;
-
- return devm_add_action_or_reset(dev->dev,
- devm_drm_irq_uninstall, dev);
-}
-EXPORT_SYMBOL(devm_drm_irq_install);
-
-#if IS_ENABLED(CONFIG_DRM_LEGACY)
int drm_legacy_irq_control(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
@@ -275,13 +189,13 @@ int drm_legacy_irq_control(struct drm_device *dev, void *data,
ctl->irq != irq)
return -EINVAL;
mutex_lock(&dev->struct_mutex);
- ret = drm_irq_install(dev, irq);
+ ret = drm_legacy_irq_install(dev, irq);
mutex_unlock(&dev->struct_mutex);
return ret;
case DRM_UNINST_HANDLER:
mutex_lock(&dev->struct_mutex);
- ret = drm_irq_uninstall(dev);
+ ret = drm_legacy_irq_uninstall(dev);
mutex_unlock(&dev->struct_mutex);
return ret;
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 00fb433bcef1..dee4f24a1808 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -15,19 +15,62 @@
#include "drm_crtc_internal.h"
#include "drm_internal.h"
+/**
+ * DOC: drm leasing
+ *
+ * DRM leases provide information about whether a DRM master may control a DRM
+ * mode setting object. This enables the creation of multiple DRM masters that
+ * manage subsets of display resources.
+ *
+ * The original DRM master of a device 'owns' the available drm resources. It
+ * may create additional DRM masters and 'lease' resources which it controls
+ * to the new DRM master. This gives the new DRM master control over the
+ * leased resources until the owner revokes the lease, or the new DRM master
+ * is closed. Some helpful terminology:
+ *
+ * - An 'owner' is a &struct drm_master that is not leasing objects from
+ * another &struct drm_master, and hence 'owns' the objects. The owner can be
+ * identified as the &struct drm_master for which &drm_master.lessor is NULL.
+ *
+ * - A 'lessor' is a &struct drm_master which is leasing objects to one or more
+ * other &struct drm_master. Currently, lessees are not allowed to
+ * create sub-leases, hence the lessor is the same as the owner.
+ *
+ * - A 'lessee' is a &struct drm_master which is leasing objects from some
+ * other &struct drm_master. Each lessee only leases resources from a single
+ * lessor recorded in &drm_master.lessor, and holds the set of objects that
+ * it is leasing in &drm_master.leases.
+ *
+ * - A 'lease' is a contract between the lessor and lessee that identifies
+ * which resources may be controlled by the lessee. All of the resources
+ * that are leased must be owned by or leased to the lessor, and lessors are
+ * not permitted to lease the same object to multiple lessees.
+ *
+ * The set of objects any &struct drm_master 'controls' is limited to the set
+ * of objects it leases (for lessees) or all objects (for owners).
+ *
+ * Objects not controlled by a &struct drm_master cannot be modified through
+ * the various state manipulating ioctls, and any state reported back to user
+ * space will be edited to make them appear idle and/or unusable. For
+ * instance, connectors always report 'disconnected', while encoders
+ * report no possible crtcs or clones.
+ *
+ * Since each lessee may lease objects from a single lessor, display resource
+ * leases form a tree of &struct drm_master. As lessees are currently not
+ * allowed to create sub-leases, the tree depth is limited to 1. All of
+ * these get activated simultaneously when the top level device owner changes
+ * through the SETMASTER or DROPMASTER IOCTL, so &drm_device.master points to
+ * the owner at the top of the lease tree (i.e. the &struct drm_master for which
+ * &drm_master.lessor is NULL). The full list of lessees that are leasing
+ * objects from the owner can be searched via the owner's
+ * &drm_master.lessee_idr.
+ */
+
#define drm_for_each_lessee(lessee, lessor) \
list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
static uint64_t drm_lease_idr_object;
-/**
- * drm_lease_owner - return ancestor owner drm_master
- * @master: drm_master somewhere within tree of lessees and lessors
- *
- * RETURN:
- *
- * drm_master at the top of the tree (i.e, with lessor NULL
- */
struct drm_master *drm_lease_owner(struct drm_master *master)
{
while (master->lessor != NULL)
@@ -35,16 +78,6 @@ struct drm_master *drm_lease_owner(struct drm_master *master)
return master;
}
-/**
- * _drm_find_lessee - find lessee by id (idr_mutex held)
- * @master: drm_master of lessor
- * @lessee_id: id
- *
- * RETURN:
- *
- * drm_master of the lessee if valid, NULL otherwise
- */
-
static struct drm_master*
_drm_find_lessee(struct drm_master *master, int lessee_id)
{
@@ -52,17 +85,6 @@ _drm_find_lessee(struct drm_master *master, int lessee_id)
return idr_find(&drm_lease_owner(master)->lessee_idr, lessee_id);
}
-/**
- * _drm_lease_held_master - check to see if an object is leased (or owned) by master (idr_mutex held)
- * @master: the master to check the lease status of
- * @id: the id to check
- *
- * Checks if the specified master holds a lease on the object. Return
- * value:
- *
- * true 'master' holds a lease on (or owns) the object
- * false 'master' does not hold a lease.
- */
static int _drm_lease_held_master(struct drm_master *master, int id)
{
lockdep_assert_held(&master->dev->mode_config.idr_mutex);
@@ -71,17 +93,7 @@ static int _drm_lease_held_master(struct drm_master *master, int id)
return true;
}
-/**
- * _drm_has_leased - check to see if an object has been leased (idr_mutex held)
- * @master: the master to check the lease status of
- * @id: the id to check
- *
- * Checks if any lessee of 'master' holds a lease on 'id'. Return
- * value:
- *
- * true Some lessee holds a lease on the object.
- * false No lessee has a lease on the object.
- */
+/* Checks if the given object has been leased to some lessee of drm_master */
static bool _drm_has_leased(struct drm_master *master, int id)
{
struct drm_master *lessee;
@@ -93,58 +105,51 @@ static bool _drm_has_leased(struct drm_master *master, int id)
return false;
}
-/**
- * _drm_lease_held - check drm_mode_object lease status (idr_mutex held)
- * @file_priv: the master drm_file
- * @id: the object id
- *
- * Checks if the specified master holds a lease on the object. Return
- * value:
- *
- * true 'master' holds a lease on (or owns) the object
- * false 'master' does not hold a lease.
- */
+/* Called with idr_mutex held */
bool _drm_lease_held(struct drm_file *file_priv, int id)
{
- if (!file_priv || !file_priv->master)
+ bool ret;
+ struct drm_master *master;
+
+ if (!file_priv)
+ return true;
+
+ master = drm_file_get_master(file_priv);
+ if (!master)
return true;
+ ret = _drm_lease_held_master(master, id);
+ drm_master_put(&master);
- return _drm_lease_held_master(file_priv->master, id);
+ return ret;
}
-/**
- * drm_lease_held - check drm_mode_object lease status (idr_mutex not held)
- * @file_priv: the master drm_file
- * @id: the object id
- *
- * Checks if the specified master holds a lease on the object. Return
- * value:
- *
- * true 'master' holds a lease on (or owns) the object
- * false 'master' does not hold a lease.
- */
bool drm_lease_held(struct drm_file *file_priv, int id)
{
struct drm_master *master;
bool ret;
- if (!file_priv || !file_priv->master || !file_priv->master->lessor)
+ if (!file_priv)
return true;
- master = file_priv->master;
+ master = drm_file_get_master(file_priv);
+ if (!master)
+ return true;
+ if (!master->lessor) {
+ ret = true;
+ goto out;
+ }
mutex_lock(&master->dev->mode_config.idr_mutex);
ret = _drm_lease_held_master(master, id);
mutex_unlock(&master->dev->mode_config.idr_mutex);
+
+out:
+ drm_master_put(&master);
return ret;
}
-/**
- * drm_lease_filter_crtcs - restricted crtc set to leased values (idr_mutex not held)
- * @file_priv: requestor file
- * @crtcs_in: bitmask of crtcs to check
- *
- * Reconstructs a crtc mask based on the crtcs which are visible
- * through the specified file.
+/*
+ * Given a bitmask of crtcs to check, reconstructs a crtc mask based on the
+ * crtcs which are visible through the specified file.
*/
uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
{
@@ -154,10 +159,16 @@ uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
int count_in, count_out;
uint32_t crtcs_out = 0;
- if (!file_priv || !file_priv->master || !file_priv->master->lessor)
+ if (!file_priv)
return crtcs_in;
- master = file_priv->master;
+ master = drm_file_get_master(file_priv);
+ if (!master)
+ return crtcs_in;
+ if (!master->lessor) {
+ crtcs_out = crtcs_in;
+ goto out;
+ }
dev = master->dev;
count_in = count_out = 0;
@@ -176,14 +187,13 @@ uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
count_in++;
}
mutex_unlock(&master->dev->mode_config.idr_mutex);
+
+out:
+ drm_master_put(&master);
return crtcs_out;
}
/*
- * drm_lease_create - create a new drm_master with leased objects (idr_mutex not held)
- * @lessor: lease holder (or owner) of objects
- * @leases: objects to lease to the new drm_master
- *
* Uses drm_master_create to allocate a new drm_master, then checks to
* make sure all of the desired objects can be leased, atomically
* leasing them to the new drmmaster.
@@ -252,15 +262,6 @@ out_lessee:
return ERR_PTR(error);
}
-/**
- * drm_lease_destroy - a master is going away (idr_mutex not held)
- * @master: the drm_master being destroyed
- *
- * All lessees will have been destroyed as they
- * hold a reference on their lessor. Notify any
- * lessor for this master so that it can check
- * the list of lessees.
- */
void drm_lease_destroy(struct drm_master *master)
{
struct drm_device *dev = master->dev;
@@ -294,10 +295,6 @@ void drm_lease_destroy(struct drm_master *master)
DRM_DEBUG_LEASE("drm_lease_destroy done %d\n", master->lessee_id);
}
-/**
- * _drm_lease_revoke - revoke access to all leased objects (idr_mutex held)
- * @top: the master losing its lease
- */
static void _drm_lease_revoke(struct drm_master *top)
{
int object;
@@ -336,10 +333,6 @@ static void _drm_lease_revoke(struct drm_master *top)
}
}
-/**
- * drm_lease_revoke - revoke access to all leased objects (idr_mutex not held)
- * @top: the master losing its lease
- */
void drm_lease_revoke(struct drm_master *top)
{
mutex_lock(&top->dev->mode_config.idr_mutex);
@@ -471,12 +464,7 @@ out_free_objects:
return ret;
}
-/**
- * drm_mode_create_lease_ioctl - create a new lease
- * @dev: the drm device
- * @data: pointer to struct drm_mode_create_lease
- * @lessor_priv: the file being manipulated
- *
+/*
* The master associated with the specified file will have a lease
* created containing the objects specified in the ioctl structure.
* A file descriptor will be allocated for that and returned to the
@@ -489,7 +477,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
size_t object_count;
int ret = 0;
struct idr leases;
- struct drm_master *lessor = lessor_priv->master;
+ struct drm_master *lessor;
struct drm_master *lessee = NULL;
struct file *lessee_file = NULL;
struct file *lessor_file = lessor_priv->filp;
@@ -501,12 +489,6 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP;
- /* Do not allow sub-leases */
- if (lessor->lessor) {
- DRM_DEBUG_LEASE("recursive leasing not allowed\n");
- return -EINVAL;
- }
-
/* need some objects */
if (cl->object_count == 0) {
DRM_DEBUG_LEASE("no objects in lease\n");
@@ -518,12 +500,22 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
return -EINVAL;
}
+ lessor = drm_file_get_master(lessor_priv);
+ /* Do not allow sub-leases */
+ if (lessor->lessor) {
+ DRM_DEBUG_LEASE("recursive leasing not allowed\n");
+ ret = -EINVAL;
+ goto out_lessor;
+ }
+
object_count = cl->object_count;
object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
array_size(object_count, sizeof(__u32)));
- if (IS_ERR(object_ids))
- return PTR_ERR(object_ids);
+ if (IS_ERR(object_ids)) {
+ ret = PTR_ERR(object_ids);
+ goto out_lessor;
+ }
idr_init(&leases);
@@ -534,14 +526,15 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
if (ret) {
DRM_DEBUG_LEASE("lease object lookup failed: %i\n", ret);
idr_destroy(&leases);
- return ret;
+ goto out_lessor;
}
/* Allocate a file descriptor for the lease */
fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
if (fd < 0) {
idr_destroy(&leases);
- return fd;
+ ret = fd;
+ goto out_lessor;
}
DRM_DEBUG_LEASE("Creating lease\n");
@@ -577,6 +570,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
/* Hook up the fd */
fd_install(fd, lessee_file);
+ drm_master_put(&lessor);
DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
return 0;
@@ -586,29 +580,19 @@ out_lessee:
out_leases:
put_unused_fd(fd);
+out_lessor:
+ drm_master_put(&lessor);
DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret);
return ret;
}
-/**
- * drm_mode_list_lessees_ioctl - list lessee ids
- * @dev: the drm device
- * @data: pointer to struct drm_mode_list_lessees
- * @lessor_priv: the file being manipulated
- *
- * Starting from the master associated with the specified file,
- * the master with the provided lessee_id is found, and then
- * an array of lessee ids associated with leases from that master
- * are returned.
- */
-
int drm_mode_list_lessees_ioctl(struct drm_device *dev,
void *data, struct drm_file *lessor_priv)
{
struct drm_mode_list_lessees *arg = data;
__u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr);
__u32 count_lessees = arg->count_lessees;
- struct drm_master *lessor = lessor_priv->master, *lessee;
+ struct drm_master *lessor, *lessee;
int count;
int ret = 0;
@@ -619,6 +603,7 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP;
+ lessor = drm_file_get_master(lessor_priv);
DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id);
mutex_lock(&dev->mode_config.idr_mutex);
@@ -642,26 +627,19 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
arg->count_lessees = count;
mutex_unlock(&dev->mode_config.idr_mutex);
+ drm_master_put(&lessor);
return ret;
}
-/**
- * drm_mode_get_lease_ioctl - list leased objects
- * @dev: the drm device
- * @data: pointer to struct drm_mode_get_lease
- * @lessee_priv: the file being manipulated
- *
- * Return the list of leased objects for the specified lessee
- */
-
+/* Return the list of leased objects for the specified lessee */
int drm_mode_get_lease_ioctl(struct drm_device *dev,
void *data, struct drm_file *lessee_priv)
{
struct drm_mode_get_lease *arg = data;
__u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr);
__u32 count_objects = arg->count_objects;
- struct drm_master *lessee = lessee_priv->master;
+ struct drm_master *lessee;
struct idr *object_idr;
int count;
void *entry;
@@ -675,6 +653,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP;
+ lessee = drm_file_get_master(lessee_priv);
DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id);
mutex_lock(&dev->mode_config.idr_mutex);
@@ -702,16 +681,12 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev,
arg->count_objects = count;
mutex_unlock(&dev->mode_config.idr_mutex);
+ drm_master_put(&lessee);
return ret;
}
-/**
- * drm_mode_revoke_lease_ioctl - revoke lease
- * @dev: the drm device
- * @data: pointer to struct drm_mode_revoke_lease
- * @lessor_priv: the file being manipulated
- *
+/*
* This removes all of the objects from the lease without
* actually getting rid of the lease itself; that way all
* references to it still work correctly
@@ -720,7 +695,7 @@ int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
void *data, struct drm_file *lessor_priv)
{
struct drm_mode_revoke_lease *arg = data;
- struct drm_master *lessor = lessor_priv->master;
+ struct drm_master *lessor;
struct drm_master *lessee;
int ret = 0;
@@ -730,6 +705,7 @@ int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP;
+ lessor = drm_file_get_master(lessor_priv);
mutex_lock(&dev->mode_config.idr_mutex);
lessee = _drm_find_lessee(lessor, arg->lessee_id);
@@ -750,6 +726,7 @@ int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
fail:
mutex_unlock(&dev->mode_config.idr_mutex);
+ drm_master_put(&lessor);
return ret;
}
diff --git a/drivers/gpu/drm/drm_legacy_misc.c b/drivers/gpu/drm/drm_legacy_misc.c
index 83db43b7a25e..d4c5434062d7 100644
--- a/drivers/gpu/drm/drm_legacy_misc.c
+++ b/drivers/gpu/drm/drm_legacy_misc.c
@@ -35,7 +35,6 @@
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
-#include <drm/drm_irq.h>
#include <drm/drm_print.h>
#include "drm_internal.h"
@@ -78,7 +77,7 @@ int drm_legacy_setup(struct drm_device * dev)
void drm_legacy_dev_reinit(struct drm_device *dev)
{
if (dev->irq_enabled)
- drm_irq_uninstall(dev);
+ drm_legacy_irq_uninstall(dev);
mutex_lock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 43a9b739bba7..71b646c4131f 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -7,7 +7,6 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
-#include <linux/dma-buf.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
@@ -202,21 +201,17 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
{
struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem);
- struct dma_buf_attachment *import_attach = gem->import_attach;
void *src = cma_obj->vaddr;
- int ret = 0;
+ int ret;
- if (import_attach) {
- ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
- DMA_FROM_DEVICE);
- if (ret)
- return ret;
- }
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret)
+ return ret;
switch (fb->format->format) {
case DRM_FORMAT_RGB565:
if (swap)
- drm_fb_swab(dst, src, fb, clip, !import_attach);
+ drm_fb_swab(dst, src, fb, clip, !gem->import_attach);
else
drm_fb_memcpy(dst, src, fb, clip);
break;
@@ -229,9 +224,8 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
return -EINVAL;
}
- if (import_attach)
- ret = dma_buf_end_cpu_access(import_attach->dmabuf,
- DMA_FROM_DEVICE);
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
+
return ret;
}
EXPORT_SYMBOL(mipi_dbi_buf_copy);
@@ -928,6 +922,59 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc,
return 0;
}
+static int mipi_dbi_typec1_command_read(struct mipi_dbi *dbi, u8 *cmd,
+ u8 *data, size_t len)
+{
+ struct spi_device *spi = dbi->spi;
+ u32 speed_hz = min_t(u32, MIPI_DBI_MAX_SPI_READ_SPEED,
+ spi->max_speed_hz / 2);
+ struct spi_transfer tr[2] = {
+ {
+ .speed_hz = speed_hz,
+ .bits_per_word = 9,
+ .tx_buf = dbi->tx_buf9,
+ .len = 2,
+ }, {
+ .speed_hz = speed_hz,
+ .bits_per_word = 8,
+ .len = len,
+ .rx_buf = data,
+ },
+ };
+ struct spi_message m;
+ u16 *dst16;
+ int ret;
+
+ if (!len)
+ return -EINVAL;
+
+ if (!spi_is_bpw_supported(spi, 9)) {
+ /*
+ * FIXME: implement something like mipi_dbi_spi1e_transfer() but
+ * for reads using emulation.
+ */
+ dev_err(&spi->dev,
+ "reading on host not supporting 9 bpw not yet implemented\n");
+ return -EOPNOTSUPP;
+ }
+
+ /*
+ * Turn the 8bit command into a 16bit version of the command in the
+ * buffer. Only 9 bits of this will be used when executing the actual
+ * transfer.
+ */
+ dst16 = dbi->tx_buf9;
+ dst16[0] = *cmd;
+
+ spi_message_init_with_transfers(&m, tr, ARRAY_SIZE(tr));
+ ret = spi_sync(spi, &m);
+
+ if (!ret)
+ MIPI_DBI_DEBUG_COMMAND(*cmd, data, len);
+
+ return ret;
+}
+
static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
u8 *parameters, size_t num)
{
@@ -935,7 +982,7 @@ static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
int ret;
if (mipi_dbi_command_is_read(dbi, *cmd))
- return -EOPNOTSUPP;
+ return mipi_dbi_typec1_command_read(dbi, cmd, parameters, num);
MIPI_DBI_DEBUG_COMMAND(*cmd, parameters, num);
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index a4a04d246135..93d48a6f04ab 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -700,7 +700,7 @@ EXPORT_SYMBOL(drm_mm_replace_node);
* interfaces. First a scan operation needs to be initialized with
* drm_mm_scan_init() or drm_mm_scan_init_with_range(). The driver adds
* objects to the roster, probably by walking an LRU list, but this can be
- * freely implemented. Eviction candiates are added using
+ * freely implemented. Eviction candidates are added using
* drm_mm_scan_add_block() until a suitable hole is found or there are no
* further evictable objects. Eviction roster metadata is tracked in &struct
* drm_mm_scan.
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index b26588b52795..86d9e907c0b2 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -91,7 +91,7 @@ void drm_mode_object_register(struct drm_device *dev,
}
/**
- * drm_mode_object_unregister - free a modeset identifer
+ * drm_mode_object_unregister - free a modeset identifier
* @dev: DRM device
* @object: object to free
*
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index ae53ea624c73..1c72208d8133 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1542,7 +1542,7 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
/*
* delim must point to the '=', otherwise it is a syntax error and
- * if delim points to the terminating zero, then delim + 1 wil point
+ * if delim points to the terminating zero, then delim + 1 will point
* past the end of the string.
*/
if (*delim != '=')
@@ -1972,7 +1972,7 @@ int drm_mode_convert_umode(struct drm_device *dev,
out->flags = in->flags;
/*
* Old xf86-video-vmware (possibly others too) used to
- * leave 'type' unititialized. Just ignore any bits we
+ * leave 'type' uninitialized. Just ignore any bits we
* don't like. It's a just hint after all, and more
* useful for the kernel->userspace direction anyway.
*/
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index ca04c34e8251..997b8827fed2 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -315,7 +315,7 @@ static int drm_of_lvds_get_remote_pixels_type(
remote_port = of_graph_get_remote_port(endpoint);
if (!remote_port) {
- of_node_put(remote_port);
+ of_node_put(endpoint);
return -EPIPE;
}
@@ -331,8 +331,10 @@ static int drm_of_lvds_get_remote_pixels_type(
* configurations by passing the endpoints explicitly to
* drm_of_lvds_get_dual_link_pixel_order().
*/
- if (!current_pt || pixels_type != current_pt)
+ if (!current_pt || pixels_type != current_pt) {
+ of_node_put(endpoint);
return -EINVAL;
+ }
}
return pixels_type;
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index b373958ecb30..82afb854141b 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -38,7 +38,7 @@
/**
* DOC: overview
*
- * A plane represents an image source that can be blended with or overlayed on
+ * A plane represents an image source that can be blended with or overlaid on
* top of a CRTC during the scanout process. Planes take their input data from a
* &drm_framebuffer object. The plane itself specifies the cropping and scaling
* of that image, and where it is placed on the visible area of a display
@@ -1397,6 +1397,110 @@ out:
return ret;
}
+/**
+ * DOC: damage tracking
+ *
+ * FB_DAMAGE_CLIPS is an optional plane property which provides a means to
+ * specify a list of damage rectangles on a plane in framebuffer coordinates of
+ * the framebuffer attached to the plane. In current context damage is the area
+ * of plane framebuffer that has changed since last plane update (also called
+ * page-flip), irrespective of whether currently attached framebuffer is same as
+ * framebuffer attached during last plane update or not.
+ *
+ * FB_DAMAGE_CLIPS is a hint to kernel which could be helpful for some drivers
+ * to optimize internally especially for virtual devices where each framebuffer
+ * change needs to be transmitted over network, usb, etc.
+ *
+ * Since FB_DAMAGE_CLIPS is a hint so it is an optional property. User-space can
+ * ignore damage clips property and in that case driver will do a full plane
+ * update. In case damage clips are provided then it is guaranteed that the area
+ * inside damage clips will be updated to plane. For efficiency driver can do
+ * full update or can update more than specified in damage clips. Since driver
+ * is free to read more, user-space must always render the entire visible
+ * framebuffer. Otherwise there can be corruptions. Also, if a user-space
+ * provides damage clips which doesn't encompass the actual damage to
+ * framebuffer (since last plane update) can result in incorrect rendering.
+ *
+ * FB_DAMAGE_CLIPS is a blob property with the layout of blob data is simply an
+ * array of &drm_mode_rect. Unlike plane &drm_plane_state.src coordinates,
+ * damage clips are not in 16.16 fixed point. Similar to plane src in
+ * framebuffer, damage clips cannot be negative. In damage clip, x1/y1 are
+ * inclusive and x2/y2 are exclusive. While kernel does not error for overlapped
+ * damage clips, it is strongly discouraged.
+ *
+ * Drivers that are interested in damage interface for plane should enable
+ * FB_DAMAGE_CLIPS property by calling drm_plane_enable_fb_damage_clips().
+ * Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and
+ * drm_atomic_helper_damage_iter_next() helper iterator function to get damage
+ * rectangles clipped to &drm_plane_state.src.
+ */
+
+/**
+ * drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property.
+ * @plane: Plane on which to enable damage clips property.
+ *
+ * This function lets driver to enable the damage clips property on a plane.
+ */
+void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
+{
+ struct drm_device *dev = plane->dev;
+ struct drm_mode_config *config = &dev->mode_config;
+
+ drm_object_attach_property(&plane->base, config->prop_fb_damage_clips,
+ 0);
+}
+EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
+
+/**
+ * drm_plane_get_damage_clips_count - Returns damage clips count.
+ * @state: Plane state.
+ *
+ * Simple helper to get the number of &drm_mode_rect clips set by user-space
+ * during plane update.
+ *
+ * Return: Number of clips in plane fb_damage_clips blob property.
+ */
+unsigned int
+drm_plane_get_damage_clips_count(const struct drm_plane_state *state)
+{
+ return (state && state->fb_damage_clips) ?
+ state->fb_damage_clips->length/sizeof(struct drm_mode_rect) : 0;
+}
+EXPORT_SYMBOL(drm_plane_get_damage_clips_count);
+
+struct drm_mode_rect *
+__drm_plane_get_damage_clips(const struct drm_plane_state *state)
+{
+ return (struct drm_mode_rect *)((state && state->fb_damage_clips) ?
+ state->fb_damage_clips->data : NULL);
+}
+
+/**
+ * drm_plane_get_damage_clips - Returns damage clips.
+ * @state: Plane state.
+ *
+ * Note that this function returns uapi type &drm_mode_rect. Drivers might want
+ * to use the helper functions drm_atomic_helper_damage_iter_init() and
+ * drm_atomic_helper_damage_iter_next() or drm_atomic_helper_damage_merged() if
+ * the driver can only handle a single damage region at most.
+ *
+ * Return: Damage clips in plane fb_damage_clips blob property.
+ */
+struct drm_mode_rect *
+drm_plane_get_damage_clips(const struct drm_plane_state *state)
+{
+ struct drm_device *dev = state->plane->dev;
+ struct drm_mode_config *config = &dev->mode_config;
+
+ /* check that drm_plane_enable_fb_damage_clips() was called */
+ if (!drm_mode_obj_find_prop_id(&state->plane->base,
+ config->prop_fb_damage_clips->base.id))
+ drm_warn_once(dev, "drm_plane_enable_fb_damage_clips() not called\n");
+
+ return __drm_plane_get_damage_clips(state);
+}
+EXPORT_SYMBOL(drm_plane_get_damage_clips);
+
struct drm_property *
drm_create_scaling_filter_prop(struct drm_device *dev,
unsigned int supported_filters)
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 3aae7ea522f2..5b2d0ca03705 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -210,7 +210,7 @@ static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *c
* We call set_config() directly here rather than using
* drm_mode_set_config_internal. We're reprogramming the same
* connectors that were already in use, so we shouldn't need the extra
- * cross-CRTC fb refcounting to accomodate stealing connectors.
+ * cross-CRTC fb refcounting to accommodate stealing connectors.
* drm_mode_setplane() already handles the basic refcounting for the
* framebuffers involved in this operation.
*/
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 2a54f86856af..deb23dbec8b5 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -73,7 +73,7 @@
* Thus the chain of references always flows in one direction, avoiding loops:
* importing GEM object -> dma-buf -> exported GEM bo. A further complication
* are the lookup caches for import and export. These are required to guarantee
- * that any given object will always have only one uniqe userspace handle. This
+ * that any given object will always have only one unique userspace handle. This
* is required to allow userspace to detect duplicated imports, since some GEM
* drivers do fail command submissions if a given buffer object is listed more
* than once. These import and export caches in &drm_prime_file_private only
@@ -549,7 +549,7 @@ int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
*
* FIXME: The underlying helper functions are named rather inconsistently.
*
- * Exporting buffers
+ * Importing buffers
* ~~~~~~~~~~~~~~~~~
*
* Importing dma-bufs using drm_gem_prime_import() relies on
@@ -807,8 +807,8 @@ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
struct page **pages, unsigned int nr_pages)
{
struct sg_table *sg;
- struct scatterlist *sge;
size_t max_segment = 0;
+ int err;
sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
if (!sg)
@@ -818,13 +818,12 @@ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
max_segment = dma_max_mapping_size(dev->dev);
if (max_segment == 0)
max_segment = UINT_MAX;
- sge = __sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
- nr_pages << PAGE_SHIFT,
- max_segment,
- NULL, 0, GFP_KERNEL);
- if (IS_ERR(sge)) {
+ err = sg_alloc_table_from_pages_segment(sg, pages, nr_pages, 0,
+ nr_pages << PAGE_SHIFT,
+ max_segment, GFP_KERNEL);
+ if (err) {
kfree(sg);
- sg = ERR_CAST(sge);
+ sg = ERR_PTR(err);
}
return sg;
}
diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index 111b932cf2a9..f783d4963d4b 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -25,7 +25,7 @@
#define DEBUG /* for pr_debug() */
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/io.h>
#include <linux/moduleparam.h>
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index e7e1ee2aa352..5606bca3caa8 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -757,7 +757,7 @@ EXPORT_SYMBOL(drm_kms_helper_poll_disable);
* drm_kms_helper_poll_init - initialize and enable output polling
* @dev: drm_device
*
- * This function intializes and then also enables output polling support for
+ * This function initializes and then also enables output polling support for
* @dev. Drivers which do not have reliable hotplug support in hardware can use
* this helper infrastructure to regularly poll such connectors for changes in
* their connection state.
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index 27c824a6eb60..6c353c9dc772 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -434,7 +434,7 @@ EXPORT_SYMBOL(drm_property_add_enum);
/**
* drm_property_destroy - destroy a drm property
* @dev: drm device
- * @property: property to destry
+ * @property: property to destroy
*
* This function frees a property including any attached resources like
* enumeration values.
diff --git a/drivers/gpu/drm/drm_scdc_helper.c b/drivers/gpu/drm/drm_scdc_helper.c
index 991b8c86d78d..48a382464d54 100644
--- a/drivers/gpu/drm/drm_scdc_helper.c
+++ b/drivers/gpu/drm/drm_scdc_helper.c
@@ -241,7 +241,7 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct i2c_adapter *adapter, bool set)
/*
* The spec says that a source should wait minimum 1ms and maximum
* 100ms after writing the TMDS config for clock ratio. Lets allow a
- * wait of upto 2ms here.
+ * wait of up to 2ms here.
*/
usleep_range(1000, 2000);
return true;
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 0b095a313c44..72989ed1baba 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -9,6 +9,8 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h>
@@ -143,6 +145,39 @@ static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = {
.atomic_disable = drm_simple_kms_crtc_disable,
};
+static void drm_simple_kms_crtc_reset(struct drm_crtc *crtc)
+{
+ struct drm_simple_display_pipe *pipe;
+
+ pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
+ if (!pipe->funcs || !pipe->funcs->reset_crtc)
+ return drm_atomic_helper_crtc_reset(crtc);
+
+ return pipe->funcs->reset_crtc(pipe);
+}
+
+static struct drm_crtc_state *drm_simple_kms_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+ struct drm_simple_display_pipe *pipe;
+
+ pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
+ if (!pipe->funcs || !pipe->funcs->duplicate_crtc_state)
+ return drm_atomic_helper_crtc_duplicate_state(crtc);
+
+ return pipe->funcs->duplicate_crtc_state(pipe);
+}
+
+static void drm_simple_kms_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state)
+{
+ struct drm_simple_display_pipe *pipe;
+
+ pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
+ if (!pipe->funcs || !pipe->funcs->destroy_crtc_state)
+ drm_atomic_helper_crtc_destroy_state(crtc, state);
+ else
+ pipe->funcs->destroy_crtc_state(pipe, state);
+}
+
static int drm_simple_kms_crtc_enable_vblank(struct drm_crtc *crtc)
{
struct drm_simple_display_pipe *pipe;
@@ -166,12 +201,12 @@ static void drm_simple_kms_crtc_disable_vblank(struct drm_crtc *crtc)
}
static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = {
- .reset = drm_atomic_helper_crtc_reset,
+ .reset = drm_simple_kms_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
- .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+ .atomic_duplicate_state = drm_simple_kms_crtc_duplicate_state,
+ .atomic_destroy_state = drm_simple_kms_crtc_destroy_state,
.enable_vblank = drm_simple_kms_crtc_enable_vblank,
.disable_vblank = drm_simple_kms_crtc_disable_vblank,
};
@@ -225,8 +260,14 @@ static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane,
struct drm_simple_display_pipe *pipe;
pipe = container_of(plane, struct drm_simple_display_pipe, plane);
- if (!pipe->funcs || !pipe->funcs->prepare_fb)
- return 0;
+ if (!pipe->funcs || !pipe->funcs->prepare_fb) {
+ if (WARN_ON_ONCE(!drm_core_check_feature(plane->dev, DRIVER_GEM)))
+ return 0;
+
+ WARN_ON_ONCE(pipe->funcs && pipe->funcs->cleanup_fb);
+
+ return drm_gem_simple_display_pipe_prepare_fb(pipe, state);
+ }
return pipe->funcs->prepare_fb(pipe, state);
}
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index fdd2ec87cdd1..c9a9d74f338c 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -725,7 +725,7 @@ err_put_fd:
return ret;
}
/**
- * drm_syncobj_open - initalizes syncobj file-private structures at devnode open time
+ * drm_syncobj_open - initializes syncobj file-private structures at devnode open time
* @file_private: drm file-private structure to set up
*
* Called at device open time, sets up the structure for handling refcounting
@@ -861,7 +861,7 @@ static int drm_syncobj_transfer_to_timeline(struct drm_file *file_private,
&fence);
if (ret)
goto err;
- chain = kzalloc(sizeof(struct dma_fence_chain), GFP_KERNEL);
+ chain = dma_fence_chain_alloc();
if (!chain) {
ret = -ENOMEM;
goto err1;
@@ -1402,10 +1402,10 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
goto err_points;
}
for (i = 0; i < args->count_handles; i++) {
- chains[i] = kzalloc(sizeof(struct dma_fence_chain), GFP_KERNEL);
+ chains[i] = dma_fence_chain_alloc();
if (!chains[i]) {
for (j = 0; j < i; j++)
- kfree(chains[j]);
+ dma_fence_chain_free(chains[j]);
ret = -ENOMEM;
goto err_chains;
}
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 3417e1ac7918..b701cda86d0c 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -191,7 +191,7 @@ static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
/*
* "No hw counter" fallback implementation of .get_vblank_counter() hook,
- * if there is no useable hardware frame counter available.
+ * if there is no usable hardware frame counter available.
*/
static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
{
@@ -905,7 +905,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
* and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
* provide a barrier: Any writes done before calling
* drm_crtc_handle_vblank() will be visible to callers of the later
- * functions, iff the vblank count is the same or a later one.
+ * functions, if the vblank count is the same or a later one.
*
* See also &drm_vblank_crtc.count.
*
@@ -968,7 +968,7 @@ static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
* and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
* provide a barrier: Any writes done before calling
* drm_crtc_handle_vblank() will be visible to callers of the later
- * functions, iff the vblank count is the same or a later one.
+ * functions, if the vblank count is the same or a later one.
*
* See also &drm_vblank_crtc.count.
*/
@@ -1737,6 +1737,15 @@ static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe,
reply->tval_usec = ts.tv_nsec / 1000;
}
+static bool drm_wait_vblank_supported(struct drm_device *dev)
+{
+#if IS_ENABLED(CONFIG_DRM_LEGACY)
+ if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY)))
+ return dev->irq_enabled;
+#endif
+ return drm_dev_has_vblank(dev);
+}
+
int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
@@ -1748,7 +1757,7 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
unsigned int pipe_index;
unsigned int flags, pipe, high_pipe;
- if (!dev->irq_enabled)
+ if (!drm_wait_vblank_supported(dev))
return -EOPNOTSUPP;
if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
@@ -1988,7 +1997,7 @@ EXPORT_SYMBOL(drm_handle_vblank);
* and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
* provide a barrier: Any writes done before calling
* drm_crtc_handle_vblank() will be visible to callers of the later
- * functions, iff the vblank count is the same or a later one.
+ * functions, if the vblank count is the same or a later one.
*
* See also &drm_vblank_crtc.count.
*
@@ -2005,7 +2014,7 @@ EXPORT_SYMBOL(drm_crtc_handle_vblank);
* Get crtc VBLANK count.
*
* \param dev DRM device
- * \param data user arguement, pointing to a drm_crtc_get_sequence structure.
+ * \param data user argument, pointing to a drm_crtc_get_sequence structure.
* \param file_priv drm file private for the user's open file descriptor
*/
@@ -2023,7 +2032,7 @@ int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP;
- if (!dev->irq_enabled)
+ if (!drm_dev_has_vblank(dev))
return -EOPNOTSUPP;
crtc = drm_crtc_find(dev, file_priv, get_seq->crtc_id);
@@ -2061,7 +2070,7 @@ int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data,
* Queue a event for VBLANK sequence
*
* \param dev DRM device
- * \param data user arguement, pointing to a drm_crtc_queue_sequence structure.
+ * \param data user argument, pointing to a drm_crtc_queue_sequence structure.
* \param file_priv drm file private for the user's open file descriptor
*/
@@ -2082,7 +2091,7 @@ int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP;
- if (!dev->irq_enabled)
+ if (!drm_dev_has_vblank(dev))
return -EOPNOTSUPP;
crtc = drm_crtc_find(dev, file_priv, queue_seq->crtc_id);
diff --git a/drivers/gpu/drm/drm_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c
index 4565319fa6b3..7de37f8c68fd 100644
--- a/drivers/gpu/drm/drm_vma_manager.c
+++ b/drivers/gpu/drm/drm_vma_manager.c
@@ -361,7 +361,7 @@ EXPORT_SYMBOL(drm_vma_node_revoke);
* This is locked against concurrent access internally.
*
* RETURNS:
- * true iff @filp is on the list
+ * true if @filp is on the list
*/
bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
struct drm_file *tag)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index f0a07278ad04..7dcc6392792d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -468,17 +468,7 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {
ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW),
};
-static const struct file_operations fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
- .compat_ioctl = drm_compat_ioctl,
- .poll = drm_poll,
- .read = drm_read,
- .llseek = no_llseek,
- .mmap = etnaviv_gem_mmap,
-};
+DEFINE_DRM_GEM_FOPS(fops);
static const struct drm_driver etnaviv_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_RENDER,
@@ -487,7 +477,7 @@ static const struct drm_driver etnaviv_drm_driver = {
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table,
- .gem_prime_mmap = etnaviv_gem_prime_mmap,
+ .gem_prime_mmap = drm_gem_prime_mmap,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = etnaviv_debugfs_init,
#endif
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
index 003288ebd896..049ae87de9be 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -47,12 +47,9 @@ struct etnaviv_drm_private {
int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct drm_file *file);
-int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
int etnaviv_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
-int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
- struct vm_area_struct *vma);
struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg);
int etnaviv_gem_prime_pin(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index b8fa6ed3dd73..8f1b5af47dd6 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -130,8 +130,7 @@ static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
{
pgprot_t vm_page_prot;
- vma->vm_flags &= ~VM_PFNMAP;
- vma->vm_flags |= VM_MIXEDMAP;
+ vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
vm_page_prot = vm_get_page_prot(vma->vm_flags);
@@ -154,19 +153,11 @@ static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
return 0;
}
-int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+static int etnaviv_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
- struct etnaviv_gem_object *obj;
- int ret;
-
- ret = drm_gem_mmap(filp, vma);
- if (ret) {
- DBG("mmap failed: %d", ret);
- return ret;
- }
+ struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
- obj = to_etnaviv_bo(vma->vm_private_data);
- return obj->ops->mmap(obj, vma);
+ return etnaviv_obj->ops->mmap(etnaviv_obj, vma);
}
static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
@@ -567,6 +558,7 @@ static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
.unpin = etnaviv_gem_prime_unpin,
.get_sg_table = etnaviv_gem_prime_get_sg_table,
.vmap = etnaviv_gem_prime_vmap,
+ .mmap = etnaviv_gem_mmap,
.vm_ops = &vm_ops,
};
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
index d741b1d735f7..6d8bed9c739d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -34,19 +34,6 @@ int etnaviv_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
return 0;
}
-int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
- struct vm_area_struct *vma)
-{
- struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
- int ret;
-
- ret = drm_gem_mmap_obj(obj, obj->size, vma);
- if (ret < 0)
- return ret;
-
- return etnaviv_obj->ops->mmap(etnaviv_obj, vma);
-}
-
int etnaviv_gem_prime_pin(struct drm_gem_object *obj)
{
if (!obj->import_attach) {
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index 4102bcea3341..c297fffe06eb 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -613,6 +613,12 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
etnaviv_is_model_rev(gpu, GC2000, 0x5108))
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
+ /* Disable SE, RA and TX clock gating on affected core revisions. */
+ if (etnaviv_is_model_rev(gpu, GC7000, 0x6202))
+ pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SE |
+ VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA |
+ VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
+
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ;
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
index dfc0f536b3b9..f2fc645c7956 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
@@ -39,6 +39,37 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
},
{
.model = 0x7000,
+ .revision = 0x6202,
+ .product_id = 0x70003,
+ .customer_id = 0,
+ .eco_id = 0,
+ .stream_count = 8,
+ .register_max = 64,
+ .thread_count = 512,
+ .shader_core_count = 2,
+ .vertex_cache_size = 16,
+ .vertex_output_buffer_size = 1024,
+ .pixel_pipes = 1,
+ .instruction_count = 512,
+ .num_constants = 320,
+ .buffer_size = 0,
+ .varyings_count = 16,
+ .features = 0xe0287cad,
+ .minor_features0 = 0xc1489eff,
+ .minor_features1 = 0xfefbfad9,
+ .minor_features2 = 0xeb9d4fbf,
+ .minor_features3 = 0xedfffced,
+ .minor_features4 = 0xdb0dafc7,
+ .minor_features5 = 0x3b5ac333,
+ .minor_features6 = 0xfccee201,
+ .minor_features7 = 0x03fffa6f,
+ .minor_features8 = 0x00e10ef0,
+ .minor_features9 = 0x0088003c,
+ .minor_features10 = 0x00004040,
+ .minor_features11 = 0x00000024,
+ },
+ {
+ .model = 0x7000,
.revision = 0x6204,
.product_id = ~0U,
.customer_id = ~0U,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
index 19826e504efc..feb6da1b6ceb 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
@@ -190,7 +190,8 @@ int etnaviv_sched_init(struct etnaviv_gpu *gpu)
ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops,
etnaviv_hw_jobs_limit, etnaviv_job_hang_limit,
- msecs_to_jiffies(500), NULL, dev_name(gpu->dev));
+ msecs_to_jiffies(500), NULL, NULL,
+ dev_name(gpu->dev));
if (ret)
return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 9ac51b6ab34b..27664f663c5a 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -109,11 +109,8 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
if (dp->ptn_bridge) {
ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge,
0);
- if (ret) {
- DRM_DEV_ERROR(dp->dev,
- "Failed to attach bridge to drm\n");
+ if (ret)
return ret;
- }
}
return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dma.c b/drivers/gpu/drm/exynos/exynos_drm_dma.c
index 0644936afee2..bf33c3084cb4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dma.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dma.c
@@ -115,6 +115,8 @@ int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
EXYNOS_DEV_ADDR_START, EXYNOS_DEV_ADDR_SIZE);
else if (IS_ENABLED(CONFIG_IOMMU_DMA))
mapping = iommu_get_domain_for_dev(priv->dma_dev);
+ else
+ mapping = ERR_PTR(-ENODEV);
if (IS_ERR(mapping))
return PTR_ERR(mapping);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index e60257f1f24b..d8f1cf4d6b69 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -300,16 +300,6 @@ static int exynos_drm_bind(struct device *dev)
drm_mode_config_reset(drm);
- /*
- * enable drm irq mode.
- * - with irq_enabled = true, we can use the vblank feature.
- *
- * P.S. note that we wouldn't use drm irq handler but
- * just specific driver own one instead because
- * drm framework supports only one irq handler.
- */
- drm->irq_enabled = true;
-
/* init kms poll for handling hpd */
drm_kms_helper_poll_init(drm);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 1d777d8c1a83..e39fac889edc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -809,15 +809,15 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
reg |= DSIM_AUTO_MODE;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSE)
reg |= DSIM_HSE_MODE;
- if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HFP))
+ if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HFP))
reg |= DSIM_HFP_MODE;
- if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HBP))
+ if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HBP))
reg |= DSIM_HBP_MODE;
- if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSA))
+ if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HSA))
reg |= DSIM_HSA_MODE;
}
- if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+ if (!(dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
reg |= DSIM_EOT_DISABLE;
switch (dsi->format) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index cab4d2c370a7..b00230626c6a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -4,6 +4,7 @@
* Authors: Joonyoung Shim <jy0922.shim@samsung.com>
*/
+#include <linux/refcount.h>
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/delay.h>
@@ -208,7 +209,7 @@ struct g2d_cmdlist_userptr {
struct page **pages;
unsigned int npages;
struct sg_table *sgt;
- atomic_t refcount;
+ refcount_t refcount;
bool in_pool;
bool out_of_list;
};
@@ -386,9 +387,9 @@ static void g2d_userptr_put_dma_addr(struct g2d_data *g2d,
if (force)
goto out;
- atomic_dec(&g2d_userptr->refcount);
+ refcount_dec(&g2d_userptr->refcount);
- if (atomic_read(&g2d_userptr->refcount) > 0)
+ if (refcount_read(&g2d_userptr->refcount) > 0)
return;
if (g2d_userptr->in_pool)
@@ -436,7 +437,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct g2d_data *g2d,
* and different size.
*/
if (g2d_userptr->size == size) {
- atomic_inc(&g2d_userptr->refcount);
+ refcount_inc(&g2d_userptr->refcount);
*obj = g2d_userptr;
return &g2d_userptr->dma_addr;
@@ -461,7 +462,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct g2d_data *g2d,
if (!g2d_userptr)
return ERR_PTR(-ENOMEM);
- atomic_set(&g2d_userptr->refcount, 1);
+ refcount_set(&g2d_userptr->refcount, 1);
g2d_userptr->size = size;
start = userptr & PAGE_MASK;
@@ -897,13 +898,14 @@ static void g2d_runqueue_worker(struct work_struct *work)
ret = pm_runtime_resume_and_get(g2d->dev);
if (ret < 0) {
dev_err(g2d->dev, "failed to enable G2D device.\n");
- return;
+ goto out;
}
g2d_dma_start(g2d, g2d->runqueue_node);
}
}
+out:
mutex_unlock(&g2d->runqueue_mutex);
}
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index f893731d6021..c769dec576de 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -970,11 +970,8 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
drm_connector_attach_encoder(connector, encoder);
- if (hdata->bridge) {
+ if (hdata->bridge)
ret = drm_bridge_attach(encoder, hdata->bridge, NULL, 0);
- if (ret)
- DRM_DEV_ERROR(hdata->dev, "Failed to attach bridge\n");
- }
cec_fill_conn_info_from_drm(&conn_info, connector);
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index 7528e8a2d359..660fe573db96 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -23,7 +23,6 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
@@ -51,7 +50,7 @@ static const struct regmap_config fsl_dcu_regmap_config = {
.volatile_reg = fsl_dcu_drm_is_volatile_reg,
};
-static void fsl_dcu_irq_uninstall(struct drm_device *dev)
+static void fsl_dcu_irq_reset(struct drm_device *dev)
{
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
@@ -59,6 +58,45 @@ static void fsl_dcu_irq_uninstall(struct drm_device *dev)
regmap_write(fsl_dev->regmap, DCU_INT_MASK, ~0);
}
+static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
+{
+ struct drm_device *dev = arg;
+ struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+ unsigned int int_status;
+ int ret;
+
+ ret = regmap_read(fsl_dev->regmap, DCU_INT_STATUS, &int_status);
+ if (ret) {
+ dev_err(dev->dev, "read DCU_INT_STATUS failed\n");
+ return IRQ_NONE;
+ }
+
+ if (int_status & DCU_INT_STATUS_VBLANK)
+ drm_handle_vblank(dev, 0);
+
+ regmap_write(fsl_dev->regmap, DCU_INT_STATUS, int_status);
+
+ return IRQ_HANDLED;
+}
+
+static int fsl_dcu_irq_install(struct drm_device *dev, unsigned int irq)
+{
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ fsl_dcu_irq_reset(dev);
+
+ return request_irq(irq, fsl_dcu_drm_irq, 0, dev->driver->name, dev);
+}
+
+static void fsl_dcu_irq_uninstall(struct drm_device *dev)
+{
+ struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+
+ fsl_dcu_irq_reset(dev);
+ free_irq(fsl_dev->irq, dev);
+}
+
static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
{
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
@@ -73,13 +111,13 @@ static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret < 0) {
dev_err(dev->dev, "failed to initialize vblank\n");
- goto done;
+ goto done_vblank;
}
- ret = drm_irq_install(dev, fsl_dev->irq);
+ ret = fsl_dcu_irq_install(dev, fsl_dev->irq);
if (ret < 0) {
dev_err(dev->dev, "failed to install IRQ handler\n");
- goto done;
+ goto done_irq;
}
if (legacyfb_depth != 16 && legacyfb_depth != 24 &&
@@ -90,11 +128,11 @@ static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
}
return 0;
-done:
+done_irq:
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
- drm_irq_uninstall(dev);
+done_vblank:
dev->dev_private = NULL;
return ret;
@@ -106,41 +144,17 @@ static void fsl_dcu_unload(struct drm_device *dev)
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
- drm_irq_uninstall(dev);
+ fsl_dcu_irq_uninstall(dev);
dev->dev_private = NULL;
}
-static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
-{
- struct drm_device *dev = arg;
- struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
- unsigned int int_status;
- int ret;
-
- ret = regmap_read(fsl_dev->regmap, DCU_INT_STATUS, &int_status);
- if (ret) {
- dev_err(dev->dev, "read DCU_INT_STATUS failed\n");
- return IRQ_NONE;
- }
-
- if (int_status & DCU_INT_STATUS_VBLANK)
- drm_handle_vblank(dev, 0);
-
- regmap_write(fsl_dev->regmap, DCU_INT_STATUS, int_status);
-
- return IRQ_HANDLED;
-}
-
DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops);
static const struct drm_driver fsl_dcu_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
.load = fsl_dcu_load,
.unload = fsl_dcu_unload,
- .irq_handler = fsl_dcu_drm_irq,
- .irq_preinstall = fsl_dcu_irq_uninstall,
- .irq_uninstall = fsl_dcu_irq_uninstall,
DRM_GEM_CMA_DRIVER_OPS,
.fops = &fsl_dcu_drm_fops,
.name = "fsl-dcu-drm",
diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c
index 432bdcc57ac9..f9b1f88c73bd 100644
--- a/drivers/gpu/drm/gma500/oaktrail_lvds.c
+++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c
@@ -113,11 +113,11 @@ static void oaktrail_lvds_mode_set(struct drm_encoder *encoder,
/* Find the connector we're trying to set up */
list_for_each_entry(connector, &mode_config->connector_list, head) {
- if (!connector->encoder || connector->encoder->crtc != crtc)
- continue;
+ if (connector->encoder && connector->encoder->crtc == crtc)
+ break;
}
- if (!connector) {
+ if (list_entry_is_head(connector, &mode_config->connector_list, head)) {
DRM_ERROR("Couldn't find connector when setting mode");
gma_power_end(dev);
return;
diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c
index f07641dfa5a4..20ace6010f9f 100644
--- a/drivers/gpu/drm/gma500/power.c
+++ b/drivers/gpu/drm/gma500/power.c
@@ -32,6 +32,7 @@
#include "psb_drv.h"
#include "psb_reg.h"
#include "psb_intel_reg.h"
+#include "psb_irq.h"
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 3850842d58f3..58bce1a60a4d 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -23,7 +23,6 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
-#include <drm/drm_irq.h>
#include <drm/drm_pciids.h>
#include <drm/drm_vblank.h>
@@ -33,6 +32,7 @@
#include "power.h"
#include "psb_drv.h"
#include "psb_intel_reg.h"
+#include "psb_irq.h"
#include "psb_reg.h"
static const struct drm_driver driver;
@@ -380,7 +380,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
- drm_irq_install(dev, pdev->irq);
+ psb_irq_install(dev, pdev->irq);
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
@@ -515,10 +515,6 @@ static const struct drm_driver driver = {
.lastclose = drm_fb_helper_lastclose,
.num_ioctls = ARRAY_SIZE(psb_ioctls),
- .irq_preinstall = psb_irq_preinstall,
- .irq_postinstall = psb_irq_postinstall,
- .irq_uninstall = psb_irq_uninstall,
- .irq_handler = psb_irq_handler,
.dumb_create = psb_gem_dumb_create,
.ioctls = psb_ioctls,
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index d6e7c2c2c947..f2bae270ca7b 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -624,11 +624,6 @@ static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
}
/* psb_irq.c */
-extern irqreturn_t psb_irq_handler(int irq, void *arg);
-extern void psb_irq_preinstall(struct drm_device *dev);
-extern int psb_irq_postinstall(struct drm_device *dev);
-extern void psb_irq_uninstall(struct drm_device *dev);
-
extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
index 104009e78487..deb1fbc1f748 100644
--- a/drivers/gpu/drm/gma500/psb_irq.c
+++ b/drivers/gpu/drm/gma500/psb_irq.c
@@ -8,6 +8,7 @@
*
**************************************************************************/
+#include <drm/drm_drv.h>
#include <drm/drm_vblank.h>
#include "power.h"
@@ -222,7 +223,7 @@ static void psb_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2)
PSB_RSGX32(PSB_CR_EVENT_HOST_CLEAR2);
}
-irqreturn_t psb_irq_handler(int irq, void *arg)
+static irqreturn_t psb_irq_handler(int irq, void *arg)
{
struct drm_device *dev = arg;
struct drm_psb_private *dev_priv = dev->dev_private;
@@ -304,7 +305,7 @@ void psb_irq_preinstall(struct drm_device *dev)
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
}
-int psb_irq_postinstall(struct drm_device *dev)
+void psb_irq_postinstall(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -332,12 +333,31 @@ int psb_irq_postinstall(struct drm_device *dev)
dev_priv->ops->hotplug_enable(dev, true);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+int psb_irq_install(struct drm_device *dev, unsigned int irq)
+{
+ int ret;
+
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ psb_irq_preinstall(dev);
+
+ /* PCI devices require shared interrupts. */
+ ret = request_irq(irq, psb_irq_handler, IRQF_SHARED, dev->driver->name, dev);
+ if (ret)
+ return ret;
+
+ psb_irq_postinstall(dev);
+
return 0;
}
void psb_irq_uninstall(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
unsigned long irqflags;
unsigned int i;
@@ -366,6 +386,8 @@ void psb_irq_uninstall(struct drm_device *dev)
/* This register is safe even if display island is off */
PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+ free_irq(pdev->irq, dev);
}
/*
diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h
index 17c9b0b62471..a97cb49393d8 100644
--- a/drivers/gpu/drm/gma500/psb_irq.h
+++ b/drivers/gpu/drm/gma500/psb_irq.h
@@ -19,9 +19,9 @@ bool sysirq_init(struct drm_device *dev);
void sysirq_uninit(struct drm_device *dev);
void psb_irq_preinstall(struct drm_device *dev);
-int psb_irq_postinstall(struct drm_device *dev);
+void psb_irq_postinstall(struct drm_device *dev);
+int psb_irq_install(struct drm_device *dev, unsigned int irq);
void psb_irq_uninstall(struct drm_device *dev);
-irqreturn_t psb_irq_handler(int irq, void *arg);
int psb_enable_vblank(struct drm_crtc *crtc);
void psb_disable_vblank(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index e8b672dc9832..eb4e08846da4 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -364,7 +364,6 @@ static void gud_debugfs_init(struct drm_minor *minor)
static const struct drm_simple_display_pipe_funcs gud_pipe_funcs = {
.check = gud_pipe_check,
.update = gud_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static const struct drm_mode_config_funcs gud_mode_config_funcs = {
@@ -394,14 +393,42 @@ static const struct drm_driver gud_drm_driver = {
.minor = 0,
};
-static void gud_free_buffers_and_mutex(struct drm_device *drm, void *unused)
+static int gud_alloc_bulk_buffer(struct gud_device *gdrm)
{
- struct gud_device *gdrm = to_gud_device(drm);
+ unsigned int i, num_pages;
+ struct page **pages;
+ void *ptr;
+ int ret;
+
+ gdrm->bulk_buf = vmalloc_32(gdrm->bulk_len);
+ if (!gdrm->bulk_buf)
+ return -ENOMEM;
+
+ num_pages = DIV_ROUND_UP(gdrm->bulk_len, PAGE_SIZE);
+ pages = kmalloc_array(num_pages, sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+
+ for (i = 0, ptr = gdrm->bulk_buf; i < num_pages; i++, ptr += PAGE_SIZE)
+ pages[i] = vmalloc_to_page(ptr);
+
+ ret = sg_alloc_table_from_pages(&gdrm->bulk_sgt, pages, num_pages,
+ 0, gdrm->bulk_len, GFP_KERNEL);
+ kfree(pages);
+
+ return ret;
+}
+
+static void gud_free_buffers_and_mutex(void *data)
+{
+ struct gud_device *gdrm = data;
vfree(gdrm->compress_buf);
- kfree(gdrm->bulk_buf);
+ gdrm->compress_buf = NULL;
+ sg_free_table(&gdrm->bulk_sgt);
+ vfree(gdrm->bulk_buf);
+ gdrm->bulk_buf = NULL;
mutex_destroy(&gdrm->ctrl_lock);
- mutex_destroy(&gdrm->damage_lock);
}
static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -455,7 +482,7 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
INIT_WORK(&gdrm->work, gud_flush_work);
gud_clear_damage(gdrm);
- ret = drmm_add_action_or_reset(drm, gud_free_buffers_and_mutex, NULL);
+ ret = devm_add_action(dev, gud_free_buffers_and_mutex, gdrm);
if (ret)
return ret;
@@ -536,24 +563,17 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (desc.max_buffer_size)
max_buffer_size = le32_to_cpu(desc.max_buffer_size);
-retry:
- /*
- * Use plain kmalloc here since devm_kmalloc() places struct devres at the beginning
- * of the buffer it allocates. This wastes a lot of memory when allocating big buffers.
- * Asking for 2M would actually allocate 4M. This would also prevent getting the biggest
- * possible buffer potentially leading to split transfers.
- */
- gdrm->bulk_buf = kmalloc(max_buffer_size, GFP_KERNEL | __GFP_NOWARN);
- if (!gdrm->bulk_buf) {
- max_buffer_size = roundup_pow_of_two(max_buffer_size) / 2;
- if (max_buffer_size < SZ_512K)
- return -ENOMEM;
- goto retry;
- }
+ /* Prevent a misbehaving device from allocating loads of RAM. 4096x4096@XRGB8888 = 64 MB */
+ if (max_buffer_size > SZ_64M)
+ max_buffer_size = SZ_64M;
gdrm->bulk_pipe = usb_sndbulkpipe(interface_to_usbdev(intf), usb_endpoint_num(bulk_out));
gdrm->bulk_len = max_buffer_size;
+ ret = gud_alloc_bulk_buffer(gdrm);
+ if (ret)
+ return ret;
+
if (gdrm->compression & GUD_COMPRESSION_LZ4) {
gdrm->lz4_comp_mem = devm_kmalloc(dev, LZ4_MEM_COMPRESS, GFP_KERNEL);
if (!gdrm->lz4_comp_mem)
@@ -640,6 +660,7 @@ static int gud_resume(struct usb_interface *intf)
static const struct usb_device_id gud_id_table[] = {
{ USB_DEVICE_INTERFACE_CLASS(0x1d50, 0x614d, USB_CLASS_VENDOR_SPEC) },
+ { USB_DEVICE_INTERFACE_CLASS(0x16d0, 0x10a9, USB_CLASS_VENDOR_SPEC) },
{ }
};
diff --git a/drivers/gpu/drm/gud/gud_internal.h b/drivers/gpu/drm/gud/gud_internal.h
index b65105585578..2a388e27d5d7 100644
--- a/drivers/gpu/drm/gud/gud_internal.h
+++ b/drivers/gpu/drm/gud/gud_internal.h
@@ -5,6 +5,7 @@
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/scatterlist.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
#include <uapi/drm/drm_fourcc.h>
@@ -26,6 +27,7 @@ struct gud_device {
unsigned int bulk_pipe;
void *bulk_buf;
size_t bulk_len;
+ struct sg_table bulk_sgt;
u8 compression;
void *lz4_comp_mem;
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index 2f83ab6b8e61..b9b0e435ea0f 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -3,7 +3,6 @@
* Copyright 2020 Noralf Trønnes
*/
-#include <linux/dma-buf.h>
#include <linux/lz4.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
@@ -15,7 +14,8 @@
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_print.h>
#include <drm/drm_rect.h>
#include <drm/drm_simple_kms_helper.h>
@@ -24,6 +24,19 @@
#include "gud_internal.h"
/*
+ * Some userspace rendering loops runs all displays in the same loop.
+ * This means that a fast display will have to wait for a slow one.
+ * For this reason gud does flushing asynchronous by default.
+ * The down side is that in e.g. a single display setup userspace thinks
+ * the display is insanely fast since the driver reports back immediately
+ * that the flush/pageflip is done. This wastes CPU and power.
+ * Such users might want to set this module parameter to false.
+ */
+static bool gud_async_flush = true;
+module_param_named(async_flush, gud_async_flush, bool, 0644);
+MODULE_PARM_DESC(async_flush, "Enable asynchronous flushing [default=true]");
+
+/*
* FIXME: The driver is probably broken on Big Endian machines.
* See discussion:
* https://lore.kernel.org/dri-devel/CAKb7UvihLX0hgBOP3VBG7O+atwZcUVCPVuBdfmDMpg0NjXe-cQ@mail.gmail.com/
@@ -139,7 +152,8 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
{
struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach;
u8 compression = gdrm->compression;
- struct dma_buf_map map;
+ struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];
+ struct dma_buf_map map_data[DRM_FORMAT_MAX_PLANES];
void *vaddr, *buf;
size_t pitch, len;
int ret = 0;
@@ -149,17 +163,15 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
if (len > gdrm->bulk_len)
return -E2BIG;
- ret = drm_gem_shmem_vmap(fb->obj[0], &map);
+ ret = drm_gem_fb_vmap(fb, map, map_data);
if (ret)
return ret;
- vaddr = map.vaddr + fb->offsets[0];
+ vaddr = map_data[0].vaddr;
- if (import_attach) {
- ret = dma_buf_begin_cpu_access(import_attach->dmabuf, DMA_FROM_DEVICE);
- if (ret)
- goto vunmap;
- }
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret)
+ goto vunmap;
retry:
if (compression)
buf = gdrm->compress_buf;
@@ -212,10 +224,48 @@ retry:
}
end_cpu_access:
- if (import_attach)
- dma_buf_end_cpu_access(import_attach->dmabuf, DMA_FROM_DEVICE);
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
vunmap:
- drm_gem_shmem_vunmap(fb->obj[0], &map);
+ drm_gem_fb_vunmap(fb, map);
+
+ return ret;
+}
+
+struct gud_usb_bulk_context {
+ struct timer_list timer;
+ struct usb_sg_request sgr;
+};
+
+static void gud_usb_bulk_timeout(struct timer_list *t)
+{
+ struct gud_usb_bulk_context *ctx = from_timer(ctx, t, timer);
+
+ usb_sg_cancel(&ctx->sgr);
+}
+
+static int gud_usb_bulk(struct gud_device *gdrm, size_t len)
+{
+ struct gud_usb_bulk_context ctx;
+ int ret;
+
+ ret = usb_sg_init(&ctx.sgr, gud_to_usb_device(gdrm), gdrm->bulk_pipe, 0,
+ gdrm->bulk_sgt.sgl, gdrm->bulk_sgt.nents, len, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ timer_setup_on_stack(&ctx.timer, gud_usb_bulk_timeout, 0);
+ mod_timer(&ctx.timer, jiffies + msecs_to_jiffies(3000));
+
+ usb_sg_wait(&ctx.sgr);
+
+ if (!del_timer_sync(&ctx.timer))
+ ret = -ETIMEDOUT;
+ else if (ctx.sgr.status < 0)
+ ret = ctx.sgr.status;
+ else if (ctx.sgr.bytes != len)
+ ret = -EIO;
+
+ destroy_timer_on_stack(&ctx.timer);
return ret;
}
@@ -223,10 +273,9 @@ vunmap:
static int gud_flush_rect(struct gud_device *gdrm, struct drm_framebuffer *fb,
const struct drm_format_info *format, struct drm_rect *rect)
{
- struct usb_device *usb = gud_to_usb_device(gdrm);
struct gud_set_buffer_req req;
- int ret, actual_length;
size_t len, trlen;
+ int ret;
drm_dbg(&gdrm->drm, "Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
@@ -255,10 +304,7 @@ static int gud_flush_rect(struct gud_device *gdrm, struct drm_framebuffer *fb,
return ret;
}
- ret = usb_bulk_msg(usb, gdrm->bulk_pipe, gdrm->bulk_buf, trlen,
- &actual_length, msecs_to_jiffies(3000));
- if (!ret && trlen != actual_length)
- ret = -EIO;
+ ret = gud_usb_bulk(gdrm, trlen);
if (ret)
gdrm->stats_num_errors++;
@@ -543,6 +589,8 @@ void gud_pipe_update(struct drm_simple_display_pipe *pipe,
if (gdrm->flags & GUD_DISPLAY_FLAG_FULL_UPDATE)
drm_rect_init(&damage, 0, 0, fb->width, fb->height);
gud_fb_queue_damage(gdrm, fb, &damage);
+ if (!gud_async_flush)
+ flush_work(&gdrm->work);
}
if (!crtc->state->enable)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index fa8da0ef707e..89bed78f1466 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -152,8 +152,7 @@ static const struct drm_plane_funcs hibmc_plane_funcs = {
};
static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = {
- .prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
- .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
+ DRM_GEM_VRAM_PLANE_HELPER_FUNCS,
.atomic_check = hibmc_plane_atomic_check,
.atomic_update = hibmc_plane_atomic_update,
};
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index f4bc5386574a..610fc8e135f9 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -19,7 +19,6 @@
#include <drm/drm_drv.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_vram_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_managed.h>
#include <drm/drm_vblank.h>
@@ -28,7 +27,7 @@
DEFINE_DRM_GEM_FOPS(hibmc_fops);
-static irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
+static irqreturn_t hibmc_interrupt(int irq, void *arg)
{
struct drm_device *dev = (struct drm_device *)arg;
struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
@@ -63,7 +62,6 @@ static const struct drm_driver hibmc_driver = {
.dumb_create = hibmc_dumb_create,
.dumb_map_offset = drm_gem_ttm_dumb_map_offset,
.gem_prime_mmap = drm_gem_prime_mmap,
- .irq_handler = hibmc_drm_interrupt,
};
static int __maybe_unused hibmc_pm_suspend(struct device *dev)
@@ -251,10 +249,11 @@ static int hibmc_hw_init(struct hibmc_drm_private *priv)
static int hibmc_unload(struct drm_device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+
drm_atomic_helper_shutdown(dev);
- if (dev->irq_enabled)
- drm_irq_uninstall(dev);
+ free_irq(pdev->irq, dev);
pci_disable_msi(to_pci_dev(dev->dev));
@@ -291,7 +290,9 @@ static int hibmc_load(struct drm_device *dev)
if (ret) {
drm_warn(dev, "enabling MSI failed: %d\n", ret);
} else {
- ret = drm_irq_install(dev, pdev->irq);
+ /* PCI devices require shared interrupts. */
+ ret = request_irq(pdev->irq, hibmc_interrupt, IRQF_SHARED,
+ dev->driver->name, dev);
if (ret)
drm_warn(dev, "install irq failed: %d\n", ret);
}
@@ -314,7 +315,7 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
struct drm_device *dev;
int ret;
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "hibmcdrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &hibmc_driver);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 9b565a057340..952cfdb1961d 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -769,16 +769,9 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
{
struct drm_encoder *encoder = &dsi->encoder;
struct drm_bridge *bridge = dsi->bridge;
- int ret;
/* associate the bridge to dsi encoder */
- ret = drm_bridge_attach(encoder, bridge, NULL, 0);
- if (ret) {
- DRM_ERROR("failed to attach external bridge\n");
- return ret;
- }
-
- return 0;
+ return drm_bridge_attach(encoder, bridge, NULL, 0);
}
static int dsi_bind(struct device *dev, struct device *master, void *data)
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index e590e19db657..98ae9a48f3fe 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -185,8 +185,6 @@ static int kirin_drm_kms_init(struct drm_device *dev,
DRM_ERROR("failed to initialize vblank.\n");
goto err_unbind_all;
}
- /* with irq_enabled = true, we can use the vblank feature. */
- dev->irq_enabled = true;
/* reset all the states of crtc/plane/encoder/connector */
drm_mode_config_reset(dev);
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
index eb06c92c4bfd..cd818a629183 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
@@ -82,7 +82,7 @@ static int hyperv_setup_gen1(struct hyperv_drm_device *hv)
return -ENODEV;
}
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "hypervdrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &hyperv_driver);
if (ret) {
drm_err(dev, "Not able to remove boot fb\n");
return ret;
@@ -127,7 +127,7 @@ static int hyperv_setup_gen2(struct hyperv_drm_device *hv,
drm_aperture_remove_conflicting_framebuffers(screen_info.lfb_base,
screen_info.lfb_size,
false,
- "hypervdrmfb");
+ &hyperv_driver);
hv->fb_size = (unsigned long)hv->mmio_megabytes * 1024 * 1024;
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
index 3aaee4730ec6..6dd4717d3e1e 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
@@ -105,7 +105,7 @@ static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe,
crtc_state->mode.hdisplay,
crtc_state->mode.vdisplay,
plane_state->fb->pitches[0]);
- hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->map[0]);
+ hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->data[0]);
}
static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe,
@@ -133,7 +133,7 @@ static void hyperv_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_rect rect;
if (drm_atomic_helper_damage_merged(old_state, state, &rect)) {
- hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->map[0], &rect);
+ hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->data[0], &rect);
hyperv_update_dirt(hv->hdev, &rect);
}
}
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index d78c82af367c..9fb4dd63342f 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -38,7 +38,6 @@
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
-#include <drm/drm_irq.h>
#include <drm/drm_print.h>
#include <drm/i810_drm.h>
@@ -209,7 +208,7 @@ static int i810_dma_cleanup(struct drm_device *dev)
* is freed, it's too late.
*/
if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
- drm_irq_uninstall(dev);
+ drm_legacy_irq_uninstall(dev);
if (dev->dev_private) {
int i;
diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index 72a38f28393f..47e845353ffa 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -207,6 +207,8 @@ config DRM_I915_LOW_LEVEL_TRACEPOINTS
This provides the ability to precisely monitor engine utilisation
and also analyze the request dependency resolving timeline.
+ Recommended for driver developers only.
+
If in doubt, say "N".
config DRM_I915_DEBUG_VBLANK_EVADE
@@ -220,6 +222,8 @@ config DRM_I915_DEBUG_VBLANK_EVADE
is exceeded, even if there isn't an actual risk of missing
the vblank.
+ Recommended for driver developers only.
+
If in doubt, say "N".
config DRM_I915_DEBUG_RUNTIME_PM
@@ -232,4 +236,6 @@ config DRM_I915_DEBUG_RUNTIME_PM
runtime PM functionality. This may introduce overhead during
driver loading, suspend and resume operations.
+ Recommended for driver developers only.
+
If in doubt, say "N"
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 4f22cac1c49b..642a5b5a1b81 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -38,6 +38,7 @@ i915-y += i915_drv.o \
i915_irq.o \
i915_getparam.o \
i915_mitigations.o \
+ i915_module.o \
i915_params.o \
i915_pci.o \
i915_scatterlist.o \
@@ -89,7 +90,6 @@ gt-y += \
gt/gen8_ppgtt.o \
gt/intel_breadcrumbs.o \
gt/intel_context.o \
- gt/intel_context_param.o \
gt/intel_context_sseu.o \
gt/intel_engine_cs.o \
gt/intel_engine_heartbeat.o \
@@ -108,6 +108,7 @@ gt-y += \
gt/intel_gtt.o \
gt/intel_llc.o \
gt/intel_lrc.o \
+ gt/intel_migrate.o \
gt/intel_mocs.o \
gt/intel_ppgtt.o \
gt/intel_rc6.o \
@@ -135,7 +136,6 @@ i915-y += $(gt-y)
gem-y += \
gem/i915_gem_busy.o \
gem/i915_gem_clflush.o \
- gem/i915_gem_client_blt.o \
gem/i915_gem_context.o \
gem/i915_gem_create.o \
gem/i915_gem_dmabuf.o \
@@ -143,7 +143,6 @@ gem-y += \
gem/i915_gem_execbuffer.o \
gem/i915_gem_internal.o \
gem/i915_gem_object.o \
- gem/i915_gem_object_blt.o \
gem/i915_gem_lmem.o \
gem/i915_gem_mman.o \
gem/i915_gem_pages.o \
@@ -155,21 +154,24 @@ gem-y += \
gem/i915_gem_stolen.o \
gem/i915_gem_throttle.o \
gem/i915_gem_tiling.o \
+ gem/i915_gem_ttm.o \
gem/i915_gem_userptr.o \
gem/i915_gem_wait.o \
gem/i915_gemfs.o
i915-y += \
$(gem-y) \
i915_active.o \
+ i915_buddy.o \
i915_cmd_parser.o \
i915_gem_evict.o \
i915_gem_gtt.o \
+ i915_gem_ww.o \
i915_gem.o \
- i915_globals.o \
i915_query.o \
i915_request.o \
i915_scheduler.o \
i915_trace_points.o \
+ i915_ttm_buddy_manager.o \
i915_vma.o \
intel_wopcm.o
@@ -184,6 +186,8 @@ i915-y += gt/uc/intel_uc.o \
gt/uc/intel_guc_fw.o \
gt/uc/intel_guc_log.o \
gt/uc/intel_guc_log_debugfs.o \
+ gt/uc/intel_guc_rc.o \
+ gt/uc/intel_guc_slpc.o \
gt/uc/intel_guc_submission.o \
gt/uc/intel_huc.o \
gt/uc/intel_huc_debugfs.o \
@@ -265,6 +269,7 @@ i915-y += \
display/intel_pps.o \
display/intel_qp_tables.o \
display/intel_sdvo.o \
+ display/intel_snps_phy.o \
display/intel_tv.o \
display/intel_vdsc.o \
display/intel_vrr.o \
@@ -276,7 +281,9 @@ i915-y += i915_perf.o
# Post-mortem debug and GPU hang state capture
i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
i915-$(CONFIG_DRM_I915_SELFTEST) += \
+ gem/selftests/i915_gem_client_blt.o \
gem/selftests/igt_gem_utils.o \
+ selftests/intel_scheduler_helpers.o \
selftests/i915_random.o \
selftests/i915_selftest.o \
selftests/igt_atomic.o \
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c
index 9643c45a2209..b1439ba78f67 100644
--- a/drivers/gpu/drm/i915/display/i9xx_plane.c
+++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
@@ -912,7 +912,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
zpos = 0;
drm_plane_create_zpos_immutable_property(&plane->base, zpos);
- drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
+ intel_plane_helper_add(plane);
return plane;
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 16812488c5dd..43ec7fcd3f5d 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -729,8 +729,8 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
- struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
- enum pipe pipe = intel_crtc->pipe;
+ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ enum pipe pipe = crtc->pipe;
u32 tmp;
enum port port;
enum transcoder dsi_trans;
@@ -1253,15 +1253,36 @@ static void gen11_dsi_pre_enable(struct intel_atomic_state *state,
gen11_dsi_set_transcoder_timings(encoder, pipe_config);
}
+/*
+ * Wa_1409054076:icl,jsl,ehl
+ * When pipe A is disabled and MIPI DSI is enabled on pipe B,
+ * the AMT KVMR feature will incorrectly see pipe A as enabled.
+ * Set 0x42080 bit 23=1 before enabling DSI on pipe B and leave
+ * it set while DSI is enabled on pipe B
+ */
+static void icl_apply_kvmr_pipe_a_wa(struct intel_encoder *encoder,
+ enum pipe pipe, bool enable)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+
+ if (DISPLAY_VER(dev_priv) == 11 && pipe == PIPE_B)
+ intel_de_rmw(dev_priv, CHICKEN_PAR1_1,
+ IGNORE_KVMR_PIPE_A,
+ enable ? IGNORE_KVMR_PIPE_A : 0);
+}
static void gen11_dsi_enable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
+ struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc);
drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder);
+ /* Wa_1409054076:icl,jsl,ehl */
+ icl_apply_kvmr_pipe_a_wa(encoder, crtc->pipe, true);
+
/* step6d: enable dsi transcoder */
gen11_dsi_enable_transcoder(encoder);
@@ -1415,6 +1436,7 @@ static void gen11_dsi_disable(struct intel_atomic_state *state,
const struct drm_connector_state *old_conn_state)
{
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
+ struct intel_crtc *crtc = to_intel_crtc(old_conn_state->crtc);
/* step1: turn off backlight */
intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_OFF);
@@ -1423,6 +1445,9 @@ static void gen11_dsi_disable(struct intel_atomic_state *state,
/* step2d,e: disable transcoder and wait */
gen11_dsi_disable_transcoder(encoder);
+ /* Wa_1409054076:icl,jsl,ehl */
+ icl_apply_kvmr_pipe_a_wa(encoder, crtc->pipe, false);
+
/* step2f,g: powerdown panel */
gen11_dsi_powerdown_panel(encoder);
@@ -1548,6 +1573,22 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder,
pipe_config->mode_flags |= I915_MODE_FLAG_DSI_PERIODIC_CMD_MODE;
}
+static void gen11_dsi_sync_state(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ enum pipe pipe = intel_crtc->pipe;
+
+ /* wa verify 1409054076:icl,jsl,ehl */
+ if (DISPLAY_VER(dev_priv) == 11 && pipe == PIPE_B &&
+ !(intel_de_read(dev_priv, CHICKEN_PAR1_1) & IGNORE_KVMR_PIPE_A))
+ drm_dbg_kms(&dev_priv->drm,
+ "[ENCODER:%d:%s] BIOS left IGNORE_KVMR_PIPE_A cleared with pipe B enabled\n",
+ encoder->base.base.id,
+ encoder->base.name);
+}
+
static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state)
{
@@ -1966,6 +2007,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
encoder->post_disable = gen11_dsi_post_disable;
encoder->port = port;
encoder->get_config = gen11_dsi_get_config;
+ encoder->sync_state = gen11_dsi_sync_state;
encoder->update_pipe = intel_panel_update_backlight;
encoder->compute_config = gen11_dsi_compute_config;
encoder->get_hw_state = gen11_dsi_get_hw_state;
diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c
index 833d0c1be4f1..7cfe91fc05f2 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.c
+++ b/drivers/gpu/drm/i915/display/intel_acpi.c
@@ -19,6 +19,12 @@ static const guid_t intel_dsm_guid =
GUID_INIT(0x7ed873d3, 0xc2d0, 0x4e4f,
0xa8, 0x54, 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c);
+#define INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED 0 /* No args */
+
+static const guid_t intel_dsm_guid2 =
+ GUID_INIT(0x3e5b41c6, 0xeb1d, 0x4260,
+ 0x9d, 0x15, 0xc7, 0x1f, 0xba, 0xda, 0xe4, 0x14);
+
static char *intel_dsm_port_name(u8 id)
{
switch (id) {
@@ -176,6 +182,19 @@ void intel_unregister_dsm_handler(void)
{
}
+void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915)
+{
+ struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+ acpi_handle dhandle;
+
+ dhandle = ACPI_HANDLE(&pdev->dev);
+ if (!dhandle)
+ return;
+
+ acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID,
+ INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED, NULL);
+}
+
/*
* ACPI Specification, Revision 5.0, Appendix B.3.2 _DOD (Enumerate All Devices
* Attached to the Display Adapter).
diff --git a/drivers/gpu/drm/i915/display/intel_acpi.h b/drivers/gpu/drm/i915/display/intel_acpi.h
index e8b068661d22..9f197401c313 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.h
+++ b/drivers/gpu/drm/i915/display/intel_acpi.h
@@ -11,11 +11,14 @@ struct drm_i915_private;
#ifdef CONFIG_ACPI
void intel_register_dsm_handler(void);
void intel_unregister_dsm_handler(void);
+void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915);
void intel_acpi_device_id_update(struct drm_i915_private *i915);
#else
static inline void intel_register_dsm_handler(void) { return; }
static inline void intel_unregister_dsm_handler(void) { return; }
static inline
+void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915) { return; }
+static inline
void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; }
#endif /* CONFIG_ACPI */
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index 36f52a1d7552..47234d898549 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -601,7 +601,12 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
return 0;
}
-const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
+static const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
.prepare_fb = intel_prepare_plane_fb,
.cleanup_fb = intel_cleanup_plane_fb,
};
+
+void intel_plane_helper_add(struct intel_plane *plane)
+{
+ drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h
index dc4d05e75e1c..62e5a2a77fd4 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h
@@ -17,8 +17,6 @@ struct intel_crtc_state;
struct intel_plane;
struct intel_plane_state;
-extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
-
unsigned int intel_adjusted_rate(const struct drm_rect *src,
const struct drm_rect *dst,
unsigned int rate);
@@ -65,5 +63,6 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
bool can_position);
void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state);
+void intel_plane_helper_add(struct intel_plane *plane);
#endif /* __INTEL_ATOMIC_PLANE_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
index 5f4f316b3ab5..532237588511 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -1001,7 +1001,7 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
/* Catch potential impedance mismatches before they occur! */
BUILD_BUG_ON(sizeof(intel_wakeref_t) > sizeof(unsigned long));
- ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
+ ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK);
if (dev_priv->audio_power_refcount++ == 0) {
if (DISPLAY_VER(dev_priv) >= 9) {
@@ -1034,7 +1034,7 @@ static void i915_audio_component_put_power(struct device *kdev,
if (IS_GEMINILAKE(dev_priv))
glk_force_audio_cdclk(dev_priv, false);
- intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO, cookie);
+ intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK, cookie);
}
static void i915_audio_component_codec_wake_override(struct device *kdev,
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index aa667fa71158..e86e6ed2d3bf 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -1871,12 +1871,12 @@ intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata)
static bool is_port_valid(struct drm_i915_private *i915, enum port port)
{
/*
- * On some ICL/CNL SKUs port F is not present, but broken VBTs mark
+ * On some ICL SKUs port F is not present, but broken VBTs mark
* the port as present. Only try to initialize port F for the
* SKUs that may actually have it.
*/
- if (port == PORT_F && (IS_ICELAKE(i915) || IS_CANNONLAKE(i915)))
- return IS_ICL_WITH_PORT_F(i915) || IS_CNL_WITH_PORT_F(i915);
+ if (port == PORT_F && IS_ICELAKE(i915))
+ return IS_ICL_WITH_PORT_F(i915);
return true;
}
@@ -1998,7 +1998,7 @@ static void parse_ddi_port(struct drm_i915_private *i915,
"Port %c VBT HDMI boost level: %d\n",
port_name(port), hdmi_boost_level);
- /* DP max link rate for CNL+ */
+ /* DP max link rate for GLK+ */
if (i915->vbt.version >= 216) {
if (i915->vbt.version >= 230)
info->dp_max_link_rate = parse_bdb_230_dp_max_link_rate(child->dp_max_link_rate);
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index bfb398f0432e..e91e0e0191fb 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -17,12 +17,53 @@ struct intel_qgv_point {
u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd;
};
+struct intel_psf_gv_point {
+ u8 clk; /* clock in multiples of 16.6666 MHz */
+};
+
struct intel_qgv_info {
struct intel_qgv_point points[I915_NUM_QGV_POINTS];
+ struct intel_psf_gv_point psf_points[I915_NUM_PSF_GV_POINTS];
u8 num_points;
+ u8 num_psf_points;
u8 t_bl;
};
+static int dg1_mchbar_read_qgv_point_info(struct drm_i915_private *dev_priv,
+ struct intel_qgv_point *sp,
+ int point)
+{
+ u32 dclk_ratio, dclk_reference;
+ u32 val;
+
+ val = intel_uncore_read(&dev_priv->uncore, SA_PERF_STATUS_0_0_0_MCHBAR_PC);
+ dclk_ratio = REG_FIELD_GET(DG1_QCLK_RATIO_MASK, val);
+ if (val & DG1_QCLK_REFERENCE)
+ dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */
+ else
+ dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */
+ sp->dclk = dclk_ratio * dclk_reference;
+
+ val = intel_uncore_read(&dev_priv->uncore, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
+ if (val & DG1_GEAR_TYPE)
+ sp->dclk *= 2;
+
+ if (sp->dclk == 0)
+ return -EINVAL;
+
+ val = intel_uncore_read(&dev_priv->uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR);
+ sp->t_rp = REG_FIELD_GET(DG1_DRAM_T_RP_MASK, val);
+ sp->t_rdpre = REG_FIELD_GET(DG1_DRAM_T_RDPRE_MASK, val);
+
+ val = intel_uncore_read(&dev_priv->uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH);
+ sp->t_rcd = REG_FIELD_GET(DG1_DRAM_T_RCD_MASK, val);
+ sp->t_ras = REG_FIELD_GET(DG1_DRAM_T_RAS_MASK, val);
+
+ sp->t_rc = sp->t_rp + sp->t_ras;
+
+ return 0;
+}
+
static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
struct intel_qgv_point *sp,
int point)
@@ -49,6 +90,28 @@ static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
return 0;
}
+static int adls_pcode_read_psf_gv_point_info(struct drm_i915_private *dev_priv,
+ struct intel_psf_gv_point *points)
+{
+ u32 val = 0;
+ int ret;
+ int i;
+
+ ret = sandybridge_pcode_read(dev_priv,
+ ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
+ ADL_PCODE_MEM_SS_READ_PSF_GV_INFO,
+ &val, NULL);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < I915_NUM_PSF_GV_POINTS; i++) {
+ points[i].clk = val & 0xff;
+ val >>= 8;
+ }
+
+ return 0;
+}
+
int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
u32 points_mask)
{
@@ -62,7 +125,7 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
1);
if (ret < 0) {
- drm_err(&dev_priv->drm, "Failed to disable qgv points (%d)\n", ret);
+ drm_err(&dev_priv->drm, "Failed to disable qgv points (%d) points: 0x%x\n", ret, points_mask);
return ret;
}
@@ -76,6 +139,7 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
int i, ret;
qi->num_points = dram_info->num_qgv_points;
+ qi->num_psf_points = dram_info->num_psf_gv_points;
if (DISPLAY_VER(dev_priv) == 12)
switch (dram_info->type) {
@@ -99,7 +163,11 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
for (i = 0; i < qi->num_points; i++) {
struct intel_qgv_point *sp = &qi->points[i];
- ret = icl_pcode_read_qgv_point_info(dev_priv, sp, i);
+ if (IS_DG1(dev_priv))
+ ret = dg1_mchbar_read_qgv_point_info(dev_priv, sp, i);
+ else
+ ret = icl_pcode_read_qgv_point_info(dev_priv, sp, i);
+
if (ret)
return ret;
@@ -109,6 +177,19 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
sp->t_rcd, sp->t_rc);
}
+ if (qi->num_psf_points > 0) {
+ ret = adls_pcode_read_psf_gv_point_info(dev_priv, qi->psf_points);
+ if (ret) {
+ drm_err(&dev_priv->drm, "Failed to read PSF point data; PSF points will not be considered in bandwidth calculations.\n");
+ qi->num_psf_points = 0;
+ }
+
+ for (i = 0; i < qi->num_psf_points; i++)
+ drm_dbg_kms(&dev_priv->drm,
+ "PSF GV %d: CLK=%d \n",
+ i, qi->psf_points[i].clk);
+ }
+
return 0;
}
@@ -118,6 +199,16 @@ static int icl_calc_bw(int dclk, int num, int den)
return DIV_ROUND_CLOSEST(num * dclk * 100, den * 6);
}
+static int adl_calc_psf_bw(int clk)
+{
+ /*
+ * clk is multiples of 16.666MHz (100/6)
+ * According to BSpec PSF GV bandwidth is
+ * calculated as BW = 64 * clk * 16.666Mhz
+ */
+ return DIV_ROUND_CLOSEST(64 * clk * 100, 6);
+}
+
static int icl_sagv_max_dclk(const struct intel_qgv_info *qi)
{
u16 dclk = 0;
@@ -194,6 +285,7 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
bi->num_qgv_points = qi.num_points;
+ bi->num_psf_gv_points = qi.num_psf_points;
for (j = 0; j < qi.num_points; j++) {
const struct intel_qgv_point *sp = &qi.points[j];
@@ -217,6 +309,16 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
i, j, bi->num_planes, bi->deratedbw[j]);
}
+ for (j = 0; j < qi.num_psf_points; j++) {
+ const struct intel_psf_gv_point *sp = &qi.psf_points[j];
+
+ bi->psf_bw[j] = adl_calc_psf_bw(sp->clk);
+
+ drm_dbg_kms(&dev_priv->drm,
+ "BW%d / PSF GV %d: num_planes=%d bw=%u\n",
+ i, j, bi->num_planes, bi->psf_bw[j]);
+ }
+
if (bi->num_planes == 1)
break;
}
@@ -234,6 +336,26 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
return 0;
}
+static void dg2_get_bw_info(struct drm_i915_private *i915)
+{
+ struct intel_bw_info *bi = &i915->max_bw[0];
+
+ /*
+ * DG2 doesn't have SAGV or QGV points, just a constant max bandwidth
+ * that doesn't depend on the number of planes enabled. Create a
+ * single dummy QGV point to reflect that. DG2-G10 platforms have a
+ * constant 50 GB/s bandwidth, whereas DG2-G11 platforms have 38 GB/s.
+ */
+ bi->num_planes = 1;
+ bi->num_qgv_points = 1;
+ if (IS_DG2_G11(i915))
+ bi->deratedbw[0] = 38000;
+ else
+ bi->deratedbw[0] = 50000;
+
+ i915->sagv_status = I915_SAGV_NOT_CONTROLLED;
+}
+
static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
int num_planes, int qgv_point)
{
@@ -262,12 +384,23 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
return 0;
}
+static unsigned int adl_psf_bw(struct drm_i915_private *dev_priv,
+ int psf_gv_point)
+{
+ const struct intel_bw_info *bi =
+ &dev_priv->max_bw[0];
+
+ return bi->psf_bw[psf_gv_point];
+}
+
void intel_bw_init_hw(struct drm_i915_private *dev_priv)
{
if (!HAS_DISPLAY(dev_priv))
return;
- if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
+ if (IS_DG2(dev_priv))
+ dg2_get_bw_info(dev_priv);
+ else if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
icl_get_bw_info(dev_priv, &adls_sa_info);
else if (IS_ROCKETLAKE(dev_priv))
icl_get_bw_info(dev_priv, &rkl_sa_info);
@@ -534,12 +667,24 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
u32 allowed_points = 0;
unsigned int max_bw_point = 0, max_bw = 0;
unsigned int num_qgv_points = dev_priv->max_bw[0].num_qgv_points;
- u32 mask = (1 << num_qgv_points) - 1;
+ unsigned int num_psf_gv_points = dev_priv->max_bw[0].num_psf_gv_points;
+ u32 mask = 0;
/* FIXME earlier gens need some checks too */
if (DISPLAY_VER(dev_priv) < 11)
return 0;
+ /*
+ * We can _not_ use the whole ADLS_QGV_PT_MASK here, as PCode rejects
+ * it with failure if we try masking any unadvertised points.
+ * So need to operate only with those returned from PCode.
+ */
+ if (num_qgv_points > 0)
+ mask |= REG_GENMASK(num_qgv_points - 1, 0);
+
+ if (num_psf_gv_points > 0)
+ mask |= REG_GENMASK(num_psf_gv_points - 1, 0) << ADLS_PSF_PT_SHIFT;
+
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
unsigned int old_data_rate =
@@ -602,23 +747,44 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
max_bw = max_data_rate;
}
if (max_data_rate >= data_rate)
- allowed_points |= BIT(i);
+ allowed_points |= REG_FIELD_PREP(ADLS_QGV_PT_MASK, BIT(i));
+
drm_dbg_kms(&dev_priv->drm, "QGV point %d: max bw %d required %d\n",
i, max_data_rate, data_rate);
}
+ for (i = 0; i < num_psf_gv_points; i++) {
+ unsigned int max_data_rate = adl_psf_bw(dev_priv, i);
+
+ if (max_data_rate >= data_rate)
+ allowed_points |= REG_FIELD_PREP(ADLS_PSF_PT_MASK, BIT(i));
+
+ drm_dbg_kms(&dev_priv->drm, "PSF GV point %d: max bw %d"
+ " required %d\n",
+ i, max_data_rate, data_rate);
+ }
+
/*
* BSpec states that we always should have at least one allowed point
* left, so if we couldn't - simply reject the configuration for obvious
* reasons.
*/
- if (allowed_points == 0) {
+ if ((allowed_points & ADLS_QGV_PT_MASK) == 0) {
drm_dbg_kms(&dev_priv->drm, "No QGV points provide sufficient memory"
" bandwidth %d for display configuration(%d active planes).\n",
data_rate, num_active_planes);
return -EINVAL;
}
+ if (num_psf_gv_points > 0) {
+ if ((allowed_points & ADLS_PSF_PT_MASK) == 0) {
+ drm_dbg_kms(&dev_priv->drm, "No PSF GV points provide sufficient memory"
+ " bandwidth %d for display configuration(%d active planes).\n",
+ data_rate, num_active_planes);
+ return -EINVAL;
+ }
+ }
+
/*
* Leave only single point with highest bandwidth, if
* we can't enable SAGV due to the increased memory latency it may
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 613ffcc68eba..34fa4130d5c4 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1195,17 +1195,6 @@ static const struct intel_cdclk_vals glk_cdclk_table[] = {
{}
};
-static const struct intel_cdclk_vals cnl_cdclk_table[] = {
- { .refclk = 19200, .cdclk = 168000, .divider = 4, .ratio = 35 },
- { .refclk = 19200, .cdclk = 336000, .divider = 2, .ratio = 35 },
- { .refclk = 19200, .cdclk = 528000, .divider = 2, .ratio = 55 },
-
- { .refclk = 24000, .cdclk = 168000, .divider = 4, .ratio = 28 },
- { .refclk = 24000, .cdclk = 336000, .divider = 2, .ratio = 28 },
- { .refclk = 24000, .cdclk = 528000, .divider = 2, .ratio = 44 },
- {}
-};
-
static const struct intel_cdclk_vals icl_cdclk_table[] = {
{ .refclk = 19200, .cdclk = 172800, .divider = 2, .ratio = 18 },
{ .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
@@ -1290,6 +1279,16 @@ static const struct intel_cdclk_vals adlp_cdclk_table[] = {
{}
};
+static const struct intel_cdclk_vals dg2_cdclk_table[] = {
+ { .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 9 },
+ { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
+ { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
+ { .refclk = 38400, .cdclk = 326400, .divider = 4, .ratio = 34 },
+ { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
+ { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
+ {}
+};
+
static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
{
const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
@@ -1329,16 +1328,6 @@ static u8 bxt_calc_voltage_level(int cdclk)
return DIV_ROUND_UP(cdclk, 25000);
}
-static u8 cnl_calc_voltage_level(int cdclk)
-{
- if (cdclk > 336000)
- return 2;
- else if (cdclk > 168000)
- return 1;
- else
- return 0;
-}
-
static u8 icl_calc_voltage_level(int cdclk)
{
if (cdclk > 556800)
@@ -1373,15 +1362,6 @@ static u8 tgl_calc_voltage_level(int cdclk)
return 0;
}
-static void cnl_readout_refclk(struct drm_i915_private *dev_priv,
- struct intel_cdclk_config *cdclk_config)
-{
- if (intel_de_read(dev_priv, SKL_DSSM) & CNL_DSSM_CDCLK_PLL_REFCLK_24MHz)
- cdclk_config->ref = 24000;
- else
- cdclk_config->ref = 19200;
-}
-
static void icl_readout_refclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
@@ -1408,10 +1388,10 @@ static void bxt_de_pll_readout(struct drm_i915_private *dev_priv,
{
u32 val, ratio;
- if (DISPLAY_VER(dev_priv) >= 11)
+ if (IS_DG2(dev_priv))
+ cdclk_config->ref = 38400;
+ else if (DISPLAY_VER(dev_priv) >= 11)
icl_readout_refclk(dev_priv, cdclk_config);
- else if (IS_CANNONLAKE(dev_priv))
- cnl_readout_refclk(dev_priv, cdclk_config);
else
cdclk_config->ref = 19200;
@@ -1427,11 +1407,11 @@ static void bxt_de_pll_readout(struct drm_i915_private *dev_priv,
}
/*
- * CNL+ have the ratio directly in the PLL enable register, gen9lp had
- * it in a separate PLL control register.
+ * DISPLAY_VER >= 11 have the ratio directly in the PLL enable register,
+ * gen9lp had it in a separate PLL control register.
*/
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
- ratio = val & CNL_CDCLK_PLL_RATIO_MASK;
+ if (DISPLAY_VER(dev_priv) >= 11)
+ ratio = val & ICL_CDCLK_PLL_RATIO_MASK;
else
ratio = intel_de_read(dev_priv, BXT_DE_PLL_CTL) & BXT_DE_PLL_RATIO_MASK;
@@ -1518,7 +1498,7 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
dev_priv->cdclk.hw.vco = vco;
}
-static void cnl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
+static void icl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
{
intel_de_rmw(dev_priv, BXT_DE_PLL_ENABLE,
BXT_DE_PLL_PLL_ENABLE, 0);
@@ -1530,12 +1510,12 @@ static void cnl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
dev_priv->cdclk.hw.vco = 0;
}
-static void cnl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
+static void icl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
{
int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
u32 val;
- val = CNL_CDCLK_PLL_RATIO(ratio);
+ val = ICL_CDCLK_PLL_RATIO(ratio);
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
val |= BXT_DE_PLL_PLL_ENABLE;
@@ -1548,18 +1528,13 @@ static void cnl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
dev_priv->cdclk.hw.vco = vco;
}
-static bool has_cdclk_crawl(struct drm_i915_private *i915)
-{
- return INTEL_INFO(i915)->has_cdclk_crawl;
-}
-
static void adlp_cdclk_pll_crawl(struct drm_i915_private *dev_priv, int vco)
{
int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
u32 val;
/* Write PLL ratio without disabling */
- val = CNL_CDCLK_PLL_RATIO(ratio) | BXT_DE_PLL_PLL_ENABLE;
+ val = ICL_CDCLK_PLL_RATIO(ratio) | BXT_DE_PLL_PLL_ENABLE;
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
/* Submit freq change request */
@@ -1628,7 +1603,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
int ret;
/* Inform power controller of upcoming frequency change. */
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 11)
ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE,
@@ -1649,16 +1624,16 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
return;
}
- if (has_cdclk_crawl(dev_priv) && dev_priv->cdclk.hw.vco > 0 && vco > 0) {
+ if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->cdclk.hw.vco > 0 && vco > 0) {
if (dev_priv->cdclk.hw.vco != vco)
adlp_cdclk_pll_crawl(dev_priv, vco);
- } else if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
+ } else if (DISPLAY_VER(dev_priv) >= 11) {
if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk.hw.vco != vco)
- cnl_cdclk_pll_disable(dev_priv);
+ icl_cdclk_pll_disable(dev_priv);
if (dev_priv->cdclk.hw.vco != vco)
- cnl_cdclk_pll_enable(dev_priv, vco);
+ icl_cdclk_pll_enable(dev_priv, vco);
} else {
if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk.hw.vco != vco)
@@ -1684,7 +1659,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
if (pipe != INVALID_PIPE)
intel_wait_for_vblank(dev_priv, pipe);
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) >= 11) {
ret = sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
} else {
@@ -1709,7 +1684,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
intel_update_cdclk(dev_priv);
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 11)
/*
* Can't read out the voltage level :(
* Let's just assume everything is as expected.
@@ -1857,7 +1832,7 @@ static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv,
{
int a_div, b_div;
- if (!has_cdclk_crawl(dev_priv))
+ if (!HAS_CDCLK_CRAWL(dev_priv))
return false;
/*
@@ -2118,7 +2093,7 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
crtc_state->port_clock >= 540000 &&
crtc_state->lane_count == 4) {
if (DISPLAY_VER(dev_priv) == 10) {
- /* Display WA #1145: glk,cnl */
+ /* Display WA #1145: glk */
min_cdclk = max(316800, min_cdclk);
} else if (DISPLAY_VER(dev_priv) == 9 || IS_BROADWELL(dev_priv)) {
/* Display WA #1144: skl,bxt */
@@ -2239,7 +2214,7 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
/*
* Account for port clock min voltage level requirements.
- * This only really does something on CNL+ but can be
+ * This only really does something on DISPLA_VER >= 11 but can be
* called on earlier platforms as well.
*
* Note that this functions assumes that 0 is
@@ -2653,8 +2628,6 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
dev_priv->max_cdclk_freq = 648000;
else
dev_priv->max_cdclk_freq = 652800;
- } else if (IS_CANNONLAKE(dev_priv)) {
- dev_priv->max_cdclk_freq = 528000;
} else if (IS_GEMINILAKE(dev_priv)) {
dev_priv->max_cdclk_freq = 316800;
} else if (IS_BROXTON(dev_priv)) {
@@ -2878,13 +2851,19 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv)
*/
void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
{
- if (IS_ALDERLAKE_P(dev_priv)) {
+ if (IS_DG2(dev_priv)) {
+ dev_priv->display.set_cdclk = bxt_set_cdclk;
+ dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
+ dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
+ dev_priv->display.calc_voltage_level = tgl_calc_voltage_level;
+ dev_priv->cdclk.table = dg2_cdclk_table;
+ } else if (IS_ALDERLAKE_P(dev_priv)) {
dev_priv->display.set_cdclk = bxt_set_cdclk;
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
dev_priv->display.calc_voltage_level = tgl_calc_voltage_level;
- /* Wa_22011320316:adlp[a0] */
- if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ /* Wa_22011320316:adl-p[a0] */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
dev_priv->cdclk.table = adlp_a_step_cdclk_table;
else
dev_priv->cdclk.table = adlp_cdclk_table;
@@ -2912,12 +2891,6 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
dev_priv->display.calc_voltage_level = icl_calc_voltage_level;
dev_priv->cdclk.table = icl_cdclk_table;
- } else if (IS_CANNONLAKE(dev_priv)) {
- dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
- dev_priv->display.set_cdclk = bxt_set_cdclk;
- dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
- dev_priv->display.calc_voltage_level = cnl_calc_voltage_level;
- dev_priv->cdclk.table = cnl_cdclk_table;
} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.set_cdclk = bxt_set_cdclk;
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index dab892d2251b..afcb4bf3826c 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -305,13 +305,12 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
ilk_csc_postoff_limited_range);
} else if (crtc_state->csc_enable) {
/*
- * On GLK+ both pipe CSC and degamma LUT are controlled
+ * On GLK both pipe CSC and degamma LUT are controlled
* by csc_enable. Hence for the cases where the degama
* LUT is needed but CSC is not we need to load an
* identity matrix.
*/
- drm_WARN_ON(&dev_priv->drm, !IS_CANNONLAKE(dev_priv) &&
- !IS_GEMINILAKE(dev_priv));
+ drm_WARN_ON(&dev_priv->drm, !IS_GEMINILAKE(dev_priv));
ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
ilk_csc_coeff_identity,
diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c
index 487c54cd5982..bacdf8a16bcb 100644
--- a/drivers/gpu/drm/i915/display/intel_combo_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c
@@ -23,9 +23,9 @@ enum {
PROCMON_1_05V_DOT_1,
};
-static const struct cnl_procmon {
+static const struct icl_procmon {
u32 dw1, dw9, dw10;
-} cnl_procmon_values[] = {
+} icl_procmon_values[] = {
[PROCMON_0_85V_DOT_0] =
{ .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, },
[PROCMON_0_95V_DOT_0] =
@@ -38,15 +38,10 @@ static const struct cnl_procmon {
{ .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, },
};
-/*
- * CNL has just one set of registers, while gen11 has a set for each combo PHY.
- * The CNL registers are equivalent to the gen11 PHY A registers, that's why we
- * call the ICL macros even though the function has CNL on its name.
- */
-static const struct cnl_procmon *
-cnl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
+static const struct icl_procmon *
+icl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
{
- const struct cnl_procmon *procmon;
+ const struct icl_procmon *procmon;
u32 val;
val = intel_de_read(dev_priv, ICL_PORT_COMP_DW3(phy));
@@ -55,32 +50,32 @@ cnl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
MISSING_CASE(val);
fallthrough;
case VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0:
- procmon = &cnl_procmon_values[PROCMON_0_85V_DOT_0];
+ procmon = &icl_procmon_values[PROCMON_0_85V_DOT_0];
break;
case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_0:
- procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_0];
+ procmon = &icl_procmon_values[PROCMON_0_95V_DOT_0];
break;
case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_1:
- procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_1];
+ procmon = &icl_procmon_values[PROCMON_0_95V_DOT_1];
break;
case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_0:
- procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_0];
+ procmon = &icl_procmon_values[PROCMON_1_05V_DOT_0];
break;
case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_1:
- procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_1];
+ procmon = &icl_procmon_values[PROCMON_1_05V_DOT_1];
break;
}
return procmon;
}
-static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv,
+static void icl_set_procmon_ref_values(struct drm_i915_private *dev_priv,
enum phy phy)
{
- const struct cnl_procmon *procmon;
+ const struct icl_procmon *procmon;
u32 val;
- procmon = cnl_get_procmon_ref_values(dev_priv, phy);
+ procmon = icl_get_procmon_ref_values(dev_priv, phy);
val = intel_de_read(dev_priv, ICL_PORT_COMP_DW1(phy));
val &= ~((0xff << 16) | 0xff);
@@ -109,13 +104,13 @@ static bool check_phy_reg(struct drm_i915_private *dev_priv,
return true;
}
-static bool cnl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
+static bool icl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
enum phy phy)
{
- const struct cnl_procmon *procmon;
+ const struct icl_procmon *procmon;
bool ret;
- procmon = cnl_get_procmon_ref_values(dev_priv, phy);
+ procmon = icl_get_procmon_ref_values(dev_priv, phy);
ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy),
(0xff << 16) | 0xff, procmon->dw1);
@@ -127,61 +122,6 @@ static bool cnl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
return ret;
}
-static bool cnl_combo_phy_enabled(struct drm_i915_private *dev_priv)
-{
- return !(intel_de_read(dev_priv, CHICKEN_MISC_2) & CNL_COMP_PWR_DOWN) &&
- (intel_de_read(dev_priv, CNL_PORT_COMP_DW0) & COMP_INIT);
-}
-
-static bool cnl_combo_phy_verify_state(struct drm_i915_private *dev_priv)
-{
- enum phy phy = PHY_A;
- bool ret;
-
- if (!cnl_combo_phy_enabled(dev_priv))
- return false;
-
- ret = cnl_verify_procmon_ref_values(dev_priv, phy);
-
- ret &= check_phy_reg(dev_priv, phy, CNL_PORT_CL1CM_DW5,
- CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE);
-
- return ret;
-}
-
-static void cnl_combo_phys_init(struct drm_i915_private *dev_priv)
-{
- u32 val;
-
- val = intel_de_read(dev_priv, CHICKEN_MISC_2);
- val &= ~CNL_COMP_PWR_DOWN;
- intel_de_write(dev_priv, CHICKEN_MISC_2, val);
-
- /* Dummy PORT_A to get the correct CNL register from the ICL macro */
- cnl_set_procmon_ref_values(dev_priv, PHY_A);
-
- val = intel_de_read(dev_priv, CNL_PORT_COMP_DW0);
- val |= COMP_INIT;
- intel_de_write(dev_priv, CNL_PORT_COMP_DW0, val);
-
- val = intel_de_read(dev_priv, CNL_PORT_CL1CM_DW5);
- val |= CL_POWER_DOWN_ENABLE;
- intel_de_write(dev_priv, CNL_PORT_CL1CM_DW5, val);
-}
-
-static void cnl_combo_phys_uninit(struct drm_i915_private *dev_priv)
-{
- u32 val;
-
- if (!cnl_combo_phy_verify_state(dev_priv))
- drm_warn(&dev_priv->drm,
- "Combo PHY HW state changed unexpectedly.\n");
-
- val = intel_de_read(dev_priv, CHICKEN_MISC_2);
- val |= CNL_COMP_PWR_DOWN;
- intel_de_write(dev_priv, CHICKEN_MISC_2, val);
-}
-
static bool has_phy_misc(struct drm_i915_private *i915, enum phy phy)
{
/*
@@ -291,7 +231,7 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv,
DCC_MODE_SELECT_CONTINUOSLY);
}
- ret &= cnl_verify_procmon_ref_values(dev_priv, phy);
+ ret &= icl_verify_procmon_ref_values(dev_priv, phy);
if (phy_is_master(dev_priv, phy)) {
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy),
@@ -415,7 +355,7 @@ skip_phy_misc:
intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), val);
}
- cnl_set_procmon_ref_values(dev_priv, phy);
+ icl_set_procmon_ref_values(dev_priv, phy);
if (phy_is_master(dev_priv, phy)) {
val = intel_de_read(dev_priv, ICL_PORT_COMP_DW8(phy));
@@ -474,16 +414,10 @@ skip_phy_misc:
void intel_combo_phy_init(struct drm_i915_private *i915)
{
- if (DISPLAY_VER(i915) >= 11)
- icl_combo_phys_init(i915);
- else if (IS_CANNONLAKE(i915))
- cnl_combo_phys_init(i915);
+ icl_combo_phys_init(i915);
}
void intel_combo_phy_uninit(struct drm_i915_private *i915)
{
- if (DISPLAY_VER(i915) >= 11)
- icl_combo_phys_uninit(i915);
- else if (IS_CANNONLAKE(i915))
- cnl_combo_phys_uninit(i915);
+ icl_combo_phys_uninit(i915);
}
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index 648f1c0d3d39..408f82b0dc7d 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -38,6 +38,7 @@
#include "intel_crt.h"
#include "intel_crtc.h"
#include "intel_ddi.h"
+#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
@@ -1081,6 +1082,8 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
crt->base.enable_clock = hsw_ddi_enable_clock;
crt->base.disable_clock = hsw_ddi_disable_clock;
crt->base.is_clock_enabled = hsw_ddi_is_clock_enabled;
+
+ intel_ddi_buf_trans_init(&crt->base);
} else {
if (HAS_PCH_SPLIT(dev_priv)) {
crt->base.compute_config = pch_crt_compute_config;
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 95ff1707b4bd..254e67141a77 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -163,12 +163,12 @@ static void intel_crtc_free(struct intel_crtc *crtc)
kfree(crtc);
}
-static void intel_crtc_destroy(struct drm_crtc *crtc)
+static void intel_crtc_destroy(struct drm_crtc *_crtc)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *crtc = to_intel_crtc(_crtc);
- drm_crtc_cleanup(crtc);
- kfree(intel_crtc);
+ drm_crtc_cleanup(&crtc->base);
+ kfree(crtc);
}
static int intel_crtc_late_register(struct drm_crtc *crtc)
@@ -335,7 +335,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
}
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 11)
drm_crtc_create_scaling_filter_property(&crtc->base,
BIT(DRM_SCALING_FILTER_DEFAULT) |
BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
index 966e020331fb..c7618fef0143 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -383,7 +383,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
cntl |= MCURSOR_ROTATE_180;
- /* Wa_22012358565:adlp */
+ /* Wa_22012358565:adl-p */
if (DISPLAY_VER(dev_priv) == 13)
cntl |= MCURSOR_ARB_SLOTS(1);
@@ -629,12 +629,16 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
/*
* When crtc is inactive or there is a modeset pending,
- * wait for it to complete in the slowpath
+ * wait for it to complete in the slowpath.
+ * PSR2 selective fetch also requires the slow path as
+ * PSR2 plane and transcoder registers can only be updated during
+ * vblank.
*
* FIXME bigjoiner fastpath would be good
*/
if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
- crtc_state->update_pipe || crtc_state->bigjoiner)
+ crtc_state->update_pipe || crtc_state->bigjoiner ||
+ crtc_state->enable_psr2_sel_fetch)
goto slow;
/*
@@ -801,7 +805,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
if (DISPLAY_VER(dev_priv) >= 12)
drm_plane_enable_fb_damage_clips(&cursor->base);
- drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
+ intel_plane_helper_add(cursor);
return cursor;
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 00dade49665b..9903a78df896 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -51,6 +51,7 @@
#include "intel_panel.h"
#include "intel_pps.h"
#include "intel_psr.h"
+#include "intel_snps_phy.h"
#include "intel_sprite.h"
#include "intel_tc.h"
#include "intel_vdsc.h"
@@ -95,24 +96,18 @@ static int intel_ddi_hdmi_level(struct intel_encoder *encoder,
* values in advance. This function programs the correct values for
* DP/eDP/FDI use cases.
*/
-void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
u32 iboost_bit = 0;
int i, n_entries;
enum port port = encoder->port;
- const struct ddi_buf_trans *ddi_translations;
-
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG))
- ddi_translations = intel_ddi_get_buf_trans_fdi(dev_priv,
- &n_entries);
- else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- ddi_translations = intel_ddi_get_buf_trans_edp(encoder,
- &n_entries);
- else
- ddi_translations = intel_ddi_get_buf_trans_dp(encoder,
- &n_entries);
+ const struct intel_ddi_buf_trans *ddi_translations;
+
+ ddi_translations = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
+ if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
+ return;
/* If we're boosting the current, set bit 31 of trans1 */
if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv) &&
@@ -121,9 +116,9 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
for (i = 0; i < n_entries; i++) {
intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, i),
- ddi_translations[i].trans1 | iboost_bit);
+ ddi_translations->entries[i].hsw.trans1 | iboost_bit);
intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, i),
- ddi_translations[i].trans2);
+ ddi_translations->entries[i].hsw.trans2);
}
}
@@ -132,17 +127,17 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
* values in advance. This function programs the correct values for
* HDMI/DVI use cases.
*/
-static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
- int level)
+static void hsw_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int level)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
u32 iboost_bit = 0;
int n_entries;
enum port port = encoder->port;
- const struct ddi_buf_trans *ddi_translations;
-
- ddi_translations = intel_ddi_get_buf_trans_hdmi(encoder, &n_entries);
+ const struct intel_ddi_buf_trans *ddi_translations;
+ ddi_translations = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
return;
if (drm_WARN_ON_ONCE(&dev_priv->drm, level >= n_entries))
@@ -155,9 +150,9 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
/* Entry 9 is for HDMI: */
intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, 9),
- ddi_translations[level].trans1 | iboost_bit);
+ ddi_translations->entries[level].hsw.trans1 | iboost_bit);
intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, 9),
- ddi_translations[level].trans2);
+ ddi_translations->entries[level].hsw.trans2);
}
void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
@@ -177,14 +172,18 @@ void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
enum port port)
{
+ int ret;
+
/* Wait > 518 usecs for DDI_BUF_CTL to be non idle */
if (DISPLAY_VER(dev_priv) < 10) {
usleep_range(518, 1000);
return;
}
- if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
- DDI_BUF_IS_IDLE), 500))
+ ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
+ DDI_BUF_IS_IDLE), IS_DG2(dev_priv) ? 1200 : 500, 10, 10);
+
+ if (ret)
drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n",
port_name(port));
}
@@ -828,7 +827,7 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
static enum intel_display_power_domain
intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port)
{
- /* CNL+ HW requires corresponding AUX IOs to be powered up for PSR with
+ /* ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
* DC states enabled at the same time, while for driver initiated AUX
* transfers we need the same AUX IOs to be powered but with DC states
* disabled. Accordingly use the AUX power domain here which leaves DC
@@ -948,22 +947,16 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder,
iboost = intel_bios_encoder_dp_boost_level(encoder->devdata);
if (iboost == 0) {
- const struct ddi_buf_trans *ddi_translations;
+ const struct intel_ddi_buf_trans *ddi_translations;
int n_entries;
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- ddi_translations = intel_ddi_get_buf_trans_hdmi(encoder, &n_entries);
- else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- ddi_translations = intel_ddi_get_buf_trans_edp(encoder, &n_entries);
- else
- ddi_translations = intel_ddi_get_buf_trans_dp(encoder, &n_entries);
-
+ ddi_translations = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
return;
if (drm_WARN_ON_ONCE(&dev_priv->drm, level >= n_entries))
level = n_entries - 1;
- iboost = ddi_translations[level].i_boost;
+ iboost = ddi_translations->entries[level].hsw.i_boost;
}
/* Make sure that the requested I_boost is valid */
@@ -983,21 +976,21 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,
int level)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- const struct bxt_ddi_buf_trans *ddi_translations;
+ const struct intel_ddi_buf_trans *ddi_translations;
enum port port = encoder->port;
int n_entries;
- ddi_translations = bxt_get_buf_trans(encoder, crtc_state, &n_entries);
+ ddi_translations = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
return;
if (drm_WARN_ON_ONCE(&dev_priv->drm, level >= n_entries))
level = n_entries - 1;
bxt_ddi_phy_set_signal_level(dev_priv, port,
- ddi_translations[level].margin,
- ddi_translations[level].scale,
- ddi_translations[level].enable,
- ddi_translations[level].deemphasis);
+ ddi_translations->entries[level].bxt.margin,
+ ddi_translations->entries[level].bxt.scale,
+ ddi_translations->entries[level].bxt.enable,
+ ddi_translations->entries[level].bxt.deemphasis);
}
static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
@@ -1005,36 +998,9 @@ static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
{
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- enum port port = encoder->port;
- enum phy phy = intel_port_to_phy(dev_priv, port);
int n_entries;
- if (DISPLAY_VER(dev_priv) >= 12) {
- if (intel_phy_is_combo(dev_priv, phy))
- tgl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
- else if (IS_ALDERLAKE_P(dev_priv))
- adlp_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
- else
- tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
- } else if (DISPLAY_VER(dev_priv) == 11) {
- if (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE))
- jsl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
- else if (IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE))
- ehl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
- else if (intel_phy_is_combo(dev_priv, phy))
- icl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
- else
- icl_get_mg_buf_trans(encoder, crtc_state, &n_entries);
- } else if (IS_CANNONLAKE(dev_priv)) {
- cnl_get_buf_trans(encoder, crtc_state, &n_entries);
- } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
- bxt_get_buf_trans(encoder, crtc_state, &n_entries);
- } else {
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- intel_ddi_get_buf_trans_edp(encoder, &n_entries);
- else
- intel_ddi_get_buf_trans_dp(encoder, &n_entries);
- }
+ encoder->get_buf_trans(encoder, crtc_state, &n_entries);
if (drm_WARN_ON(&dev_priv->drm, n_entries < 1))
n_entries = 1;
@@ -1056,146 +1022,17 @@ static u8 intel_ddi_dp_preemph_max(struct intel_dp *intel_dp)
return DP_TRAIN_PRE_EMPH_LEVEL_3;
}
-static void cnl_ddi_vswing_program(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int level)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- const struct cnl_ddi_buf_trans *ddi_translations;
- enum port port = encoder->port;
- int n_entries, ln;
- u32 val;
-
- ddi_translations = cnl_get_buf_trans(encoder, crtc_state, &n_entries);
-
- if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
- return;
- if (drm_WARN_ON_ONCE(&dev_priv->drm, level >= n_entries))
- level = n_entries - 1;
-
- /* Set PORT_TX_DW5 Scaling Mode Sel to 010b. */
- val = intel_de_read(dev_priv, CNL_PORT_TX_DW5_LN0(port));
- val &= ~SCALING_MODE_SEL_MASK;
- val |= SCALING_MODE_SEL(2);
- intel_de_write(dev_priv, CNL_PORT_TX_DW5_GRP(port), val);
-
- /* Program PORT_TX_DW2 */
- val = intel_de_read(dev_priv, CNL_PORT_TX_DW2_LN0(port));
- val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
- RCOMP_SCALAR_MASK);
- val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel);
- val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);
- /* Rcomp scalar is fixed as 0x98 for every table entry */
- val |= RCOMP_SCALAR(0x98);
- intel_de_write(dev_priv, CNL_PORT_TX_DW2_GRP(port), val);
-
- /* Program PORT_TX_DW4 */
- /* We cannot write to GRP. It would overrite individual loadgen */
- for (ln = 0; ln < 4; ln++) {
- val = intel_de_read(dev_priv, CNL_PORT_TX_DW4_LN(ln, port));
- val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
- CURSOR_COEFF_MASK);
- val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
- val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
- val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
- intel_de_write(dev_priv, CNL_PORT_TX_DW4_LN(ln, port), val);
- }
-
- /* Program PORT_TX_DW5 */
- /* All DW5 values are fixed for every table entry */
- val = intel_de_read(dev_priv, CNL_PORT_TX_DW5_LN0(port));
- val &= ~RTERM_SELECT_MASK;
- val |= RTERM_SELECT(6);
- val |= TAP3_DISABLE;
- intel_de_write(dev_priv, CNL_PORT_TX_DW5_GRP(port), val);
-
- /* Program PORT_TX_DW7 */
- val = intel_de_read(dev_priv, CNL_PORT_TX_DW7_LN0(port));
- val &= ~N_SCALAR_MASK;
- val |= N_SCALAR(ddi_translations[level].dw7_n_scalar);
- intel_de_write(dev_priv, CNL_PORT_TX_DW7_GRP(port), val);
-}
-
-static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int level)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- enum port port = encoder->port;
- int width, rate, ln;
- u32 val;
-
- width = crtc_state->lane_count;
- rate = crtc_state->port_clock;
-
- /*
- * 1. If port type is eDP or DP,
- * set PORT_PCS_DW1 cmnkeeper_enable to 1b,
- * else clear to 0b.
- */
- val = intel_de_read(dev_priv, CNL_PORT_PCS_DW1_LN0(port));
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- val &= ~COMMON_KEEPER_EN;
- else
- val |= COMMON_KEEPER_EN;
- intel_de_write(dev_priv, CNL_PORT_PCS_DW1_GRP(port), val);
-
- /* 2. Program loadgen select */
- /*
- * Program PORT_TX_DW4_LN depending on Bit rate and used lanes
- * <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1)
- * <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0)
- * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
- */
- for (ln = 0; ln <= 3; ln++) {
- val = intel_de_read(dev_priv, CNL_PORT_TX_DW4_LN(ln, port));
- val &= ~LOADGEN_SELECT;
-
- if ((rate <= 600000 && width == 4 && ln >= 1) ||
- (rate <= 600000 && width < 4 && (ln == 1 || ln == 2))) {
- val |= LOADGEN_SELECT;
- }
- intel_de_write(dev_priv, CNL_PORT_TX_DW4_LN(ln, port), val);
- }
-
- /* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
- val = intel_de_read(dev_priv, CNL_PORT_CL1CM_DW5);
- val |= SUS_CLOCK_CONFIG;
- intel_de_write(dev_priv, CNL_PORT_CL1CM_DW5, val);
-
- /* 4. Clear training enable to change swing values */
- val = intel_de_read(dev_priv, CNL_PORT_TX_DW5_LN0(port));
- val &= ~TX_TRAINING_EN;
- intel_de_write(dev_priv, CNL_PORT_TX_DW5_GRP(port), val);
-
- /* 5. Program swing and de-emphasis */
- cnl_ddi_vswing_program(encoder, crtc_state, level);
-
- /* 6. Set training enable to trigger update */
- val = intel_de_read(dev_priv, CNL_PORT_TX_DW5_LN0(port));
- val |= TX_TRAINING_EN;
- intel_de_write(dev_priv, CNL_PORT_TX_DW5_GRP(port), val);
-}
-
static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int level)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- const struct cnl_ddi_buf_trans *ddi_translations;
+ const struct intel_ddi_buf_trans *ddi_translations;
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
int n_entries, ln;
u32 val;
- if (DISPLAY_VER(dev_priv) >= 12)
- ddi_translations = tgl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
- else if (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE))
- ddi_translations = jsl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
- else if (IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE))
- ddi_translations = ehl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
- else
- ddi_translations = icl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
-
+ ddi_translations = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
return;
if (drm_WARN_ON_ONCE(&dev_priv->drm, level >= n_entries))
@@ -1223,8 +1060,8 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder,
val = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN0(phy));
val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
RCOMP_SCALAR_MASK);
- val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel);
- val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);
+ val |= SWING_SEL_UPPER(ddi_translations->entries[level].icl.dw2_swing_sel);
+ val |= SWING_SEL_LOWER(ddi_translations->entries[level].icl.dw2_swing_sel);
/* Program Rcomp scalar for every table entry */
val |= RCOMP_SCALAR(0x98);
intel_de_write(dev_priv, ICL_PORT_TX_DW2_GRP(phy), val);
@@ -1235,16 +1072,16 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder,
val = intel_de_read(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy));
val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
CURSOR_COEFF_MASK);
- val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
- val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
- val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
+ val |= POST_CURSOR_1(ddi_translations->entries[level].icl.dw4_post_cursor_1);
+ val |= POST_CURSOR_2(ddi_translations->entries[level].icl.dw4_post_cursor_2);
+ val |= CURSOR_COEFF(ddi_translations->entries[level].icl.dw4_cursor_coeff);
intel_de_write(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy), val);
}
/* Program PORT_TX_DW7 */
val = intel_de_read(dev_priv, ICL_PORT_TX_DW7_LN0(phy));
val &= ~N_SCALAR_MASK;
- val |= N_SCALAR(ddi_translations[level].dw7_n_scalar);
+ val |= N_SCALAR(ddi_translations->entries[level].icl.dw7_n_scalar);
intel_de_write(dev_priv, ICL_PORT_TX_DW7_GRP(phy), val);
}
@@ -1315,15 +1152,14 @@ static void icl_mg_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
- const struct icl_mg_phy_ddi_buf_trans *ddi_translations;
+ const struct intel_ddi_buf_trans *ddi_translations;
int n_entries, ln;
u32 val;
if (enc_to_dig_port(encoder)->tc_mode == TC_PORT_TBT_ALT)
return;
- ddi_translations = icl_get_mg_buf_trans(encoder, crtc_state, &n_entries);
-
+ ddi_translations = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
return;
if (drm_WARN_ON_ONCE(&dev_priv->drm, level >= n_entries))
@@ -1345,13 +1181,13 @@ static void icl_mg_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
val = intel_de_read(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port));
val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK;
val |= CRI_TXDEEMPH_OVERRIDE_17_12(
- ddi_translations[level].cri_txdeemph_override_17_12);
+ ddi_translations->entries[level].mg.cri_txdeemph_override_17_12);
intel_de_write(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port), val);
val = intel_de_read(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port));
val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK;
val |= CRI_TXDEEMPH_OVERRIDE_17_12(
- ddi_translations[level].cri_txdeemph_override_17_12);
+ ddi_translations->entries[level].mg.cri_txdeemph_override_17_12);
intel_de_write(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port), val);
}
@@ -1361,9 +1197,9 @@ static void icl_mg_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
CRI_TXDEEMPH_OVERRIDE_5_0_MASK);
val |= CRI_TXDEEMPH_OVERRIDE_5_0(
- ddi_translations[level].cri_txdeemph_override_5_0) |
+ ddi_translations->entries[level].mg.cri_txdeemph_override_5_0) |
CRI_TXDEEMPH_OVERRIDE_11_6(
- ddi_translations[level].cri_txdeemph_override_11_6) |
+ ddi_translations->entries[level].mg.cri_txdeemph_override_11_6) |
CRI_TXDEEMPH_OVERRIDE_EN;
intel_de_write(dev_priv, MG_TX1_DRVCTRL(ln, tc_port), val);
@@ -1371,9 +1207,9 @@ static void icl_mg_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
CRI_TXDEEMPH_OVERRIDE_5_0_MASK);
val |= CRI_TXDEEMPH_OVERRIDE_5_0(
- ddi_translations[level].cri_txdeemph_override_5_0) |
+ ddi_translations->entries[level].mg.cri_txdeemph_override_5_0) |
CRI_TXDEEMPH_OVERRIDE_11_6(
- ddi_translations[level].cri_txdeemph_override_11_6) |
+ ddi_translations->entries[level].mg.cri_txdeemph_override_11_6) |
CRI_TXDEEMPH_OVERRIDE_EN;
intel_de_write(dev_priv, MG_TX2_DRVCTRL(ln, tc_port), val);
@@ -1453,18 +1289,14 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
- const struct tgl_dkl_phy_ddi_buf_trans *ddi_translations;
+ const struct intel_ddi_buf_trans *ddi_translations;
u32 val, dpcnt_mask, dpcnt_val;
int n_entries, ln;
if (enc_to_dig_port(encoder)->tc_mode == TC_PORT_TBT_ALT)
return;
- if (IS_ALDERLAKE_P(dev_priv))
- ddi_translations = adlp_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
- else
- ddi_translations = tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
-
+ ddi_translations = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
return;
if (drm_WARN_ON_ONCE(&dev_priv->drm, level >= n_entries))
@@ -1473,9 +1305,9 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
dpcnt_mask = (DKL_TX_PRESHOOT_COEFF_MASK |
DKL_TX_DE_EMPAHSIS_COEFF_MASK |
DKL_TX_VSWING_CONTROL_MASK);
- dpcnt_val = DKL_TX_VSWING_CONTROL(ddi_translations[level].dkl_vswing_control);
- dpcnt_val |= DKL_TX_DE_EMPHASIS_COEFF(ddi_translations[level].dkl_de_emphasis_control);
- dpcnt_val |= DKL_TX_PRESHOOT_COEFF(ddi_translations[level].dkl_preshoot_control);
+ dpcnt_val = DKL_TX_VSWING_CONTROL(ddi_translations->entries[level].dkl.dkl_vswing_control);
+ dpcnt_val |= DKL_TX_DE_EMPHASIS_COEFF(ddi_translations->entries[level].dkl.dkl_de_emphasis_control);
+ dpcnt_val |= DKL_TX_PRESHOOT_COEFF(ddi_translations->entries[level].dkl.dkl_preshoot_control);
for (ln = 0; ln < 2; ln++) {
intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
@@ -1549,33 +1381,33 @@ static int intel_ddi_dp_level(struct intel_dp *intel_dp)
}
static void
-tgl_set_signal_levels(struct intel_dp *intel_dp,
+dg2_set_signal_levels(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
int level = intel_ddi_dp_level(intel_dp);
- tgl_ddi_vswing_sequence(encoder, crtc_state, level);
+ intel_snps_phy_ddi_vswing_sequence(encoder, level);
}
static void
-icl_set_signal_levels(struct intel_dp *intel_dp,
+tgl_set_signal_levels(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
int level = intel_ddi_dp_level(intel_dp);
- icl_ddi_vswing_sequence(encoder, crtc_state, level);
+ tgl_ddi_vswing_sequence(encoder, crtc_state, level);
}
static void
-cnl_set_signal_levels(struct intel_dp *intel_dp,
+icl_set_signal_levels(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
int level = intel_ddi_dp_level(intel_dp);
- cnl_ddi_vswing_sequence(encoder, crtc_state, level);
+ icl_ddi_vswing_sequence(encoder, crtc_state, level);
}
static void
@@ -1613,7 +1445,7 @@ hsw_set_signal_levels(struct intel_dp *intel_dp,
intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
}
-static void _cnl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg,
+static void _icl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg,
u32 clk_sel_mask, u32 clk_sel, u32 clk_off)
{
mutex_lock(&i915->dpll.lock);
@@ -1629,7 +1461,7 @@ static void _cnl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg,
mutex_unlock(&i915->dpll.lock);
}
-static void _cnl_ddi_disable_clock(struct drm_i915_private *i915, i915_reg_t reg,
+static void _icl_ddi_disable_clock(struct drm_i915_private *i915, i915_reg_t reg,
u32 clk_off)
{
mutex_lock(&i915->dpll.lock);
@@ -1639,14 +1471,14 @@ static void _cnl_ddi_disable_clock(struct drm_i915_private *i915, i915_reg_t reg
mutex_unlock(&i915->dpll.lock);
}
-static bool _cnl_ddi_is_clock_enabled(struct drm_i915_private *i915, i915_reg_t reg,
+static bool _icl_ddi_is_clock_enabled(struct drm_i915_private *i915, i915_reg_t reg,
u32 clk_off)
{
return !(intel_de_read(i915, reg) & clk_off);
}
static struct intel_shared_dpll *
-_cnl_ddi_get_pll(struct drm_i915_private *i915, i915_reg_t reg,
+_icl_ddi_get_pll(struct drm_i915_private *i915, i915_reg_t reg,
u32 clk_sel_mask, u32 clk_sel_shift)
{
enum intel_dpll_id id;
@@ -1666,7 +1498,7 @@ static void adls_ddi_enable_clock(struct intel_encoder *encoder,
if (drm_WARN_ON(&i915->drm, !pll))
return;
- _cnl_ddi_enable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
+ _icl_ddi_enable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
pll->info->id << ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy),
ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
@@ -1677,7 +1509,7 @@ static void adls_ddi_disable_clock(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- _cnl_ddi_disable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
+ _icl_ddi_disable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
@@ -1686,7 +1518,7 @@ static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- return _cnl_ddi_is_clock_enabled(i915, ADLS_DPCLKA_CFGCR(phy),
+ return _icl_ddi_is_clock_enabled(i915, ADLS_DPCLKA_CFGCR(phy),
ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
@@ -1695,7 +1527,7 @@ static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- return _cnl_ddi_get_pll(i915, ADLS_DPCLKA_CFGCR(phy),
+ return _icl_ddi_get_pll(i915, ADLS_DPCLKA_CFGCR(phy),
ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy));
}
@@ -1710,7 +1542,7 @@ static void rkl_ddi_enable_clock(struct intel_encoder *encoder,
if (drm_WARN_ON(&i915->drm, !pll))
return;
- _cnl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
+ _icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
@@ -1721,7 +1553,7 @@ static void rkl_ddi_disable_clock(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- _cnl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
+ _icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
@@ -1730,7 +1562,7 @@ static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- return _cnl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
+ return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
@@ -1739,7 +1571,7 @@ static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- return _cnl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
+ return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
}
@@ -1763,7 +1595,7 @@ static void dg1_ddi_enable_clock(struct intel_encoder *encoder,
(pll->info->id >= DPLL_ID_DG1_DPLL2 && phy < PHY_C)))
return;
- _cnl_ddi_enable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
+ _icl_ddi_enable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
@@ -1774,7 +1606,7 @@ static void dg1_ddi_disable_clock(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- _cnl_ddi_disable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
+ _icl_ddi_disable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
@@ -1783,7 +1615,7 @@ static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- return _cnl_ddi_is_clock_enabled(i915, DG1_DPCLKA_CFGCR0(phy),
+ return _icl_ddi_is_clock_enabled(i915, DG1_DPCLKA_CFGCR0(phy),
DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
@@ -1820,7 +1652,7 @@ static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder,
if (drm_WARN_ON(&i915->drm, !pll))
return;
- _cnl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
+ _icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
@@ -1831,7 +1663,7 @@ static void icl_ddi_combo_disable_clock(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- _cnl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
+ _icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
@@ -1840,7 +1672,7 @@ static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- return _cnl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
+ return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
@@ -1849,7 +1681,7 @@ struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- return _cnl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
+ return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
}
@@ -1982,50 +1814,6 @@ static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encode
return intel_get_shared_dpll_by_id(i915, id);
}
-static void cnl_ddi_enable_clock(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
-{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
- enum port port = encoder->port;
-
- if (drm_WARN_ON(&i915->drm, !pll))
- return;
-
- _cnl_ddi_enable_clock(i915, DPCLKA_CFGCR0,
- DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port),
- DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port),
- DPCLKA_CFGCR0_DDI_CLK_OFF(port));
-}
-
-static void cnl_ddi_disable_clock(struct intel_encoder *encoder)
-{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- enum port port = encoder->port;
-
- _cnl_ddi_disable_clock(i915, DPCLKA_CFGCR0,
- DPCLKA_CFGCR0_DDI_CLK_OFF(port));
-}
-
-static bool cnl_ddi_is_clock_enabled(struct intel_encoder *encoder)
-{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- enum port port = encoder->port;
-
- return _cnl_ddi_is_clock_enabled(i915, DPCLKA_CFGCR0,
- DPCLKA_CFGCR0_DDI_CLK_OFF(port));
-}
-
-static struct intel_shared_dpll *cnl_ddi_get_pll(struct intel_encoder *encoder)
-{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- enum port port = encoder->port;
-
- return _cnl_ddi_get_pll(i915, DPCLKA_CFGCR0,
- DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port),
- DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port));
-}
-
static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
@@ -2249,7 +2037,7 @@ void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
ddi_clk_needed = false;
}
- if (ddi_clk_needed || !encoder->disable_clock ||
+ if (ddi_clk_needed || !encoder->is_clock_enabled ||
!encoder->is_clock_enabled(encoder))
return;
@@ -2534,6 +2322,116 @@ static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
OVERLAP_PIXELS_MASK, dss1);
}
+static void dg2_ddi_pre_enable_dp(struct intel_atomic_state *state,
+ struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
+ int level = intel_ddi_dp_level(intel_dp);
+
+ intel_dp_set_link_params(intel_dp, crtc_state->port_clock,
+ crtc_state->lane_count);
+
+ /*
+ * 1. Enable Power Wells
+ *
+ * This was handled at the beginning of intel_atomic_commit_tail(),
+ * before we called down into this function.
+ */
+
+ /* 2. Enable Panel Power if PPS is required */
+ intel_pps_on(intel_dp);
+
+ /*
+ * 3. Enable the port PLL.
+ */
+ intel_ddi_enable_clock(encoder, crtc_state);
+
+ /* 4. Enable IO power */
+ if (!intel_phy_is_tc(dev_priv, phy) ||
+ dig_port->tc_mode != TC_PORT_TBT_ALT)
+ dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
+ dig_port->ddi_io_power_domain);
+
+ /*
+ * 5. The rest of the below are substeps under the bspec's "Enable and
+ * Train Display Port" step. Note that steps that are specific to
+ * MST will be handled by intel_mst_pre_enable_dp() before/after it
+ * calls into this function. Also intel_mst_pre_enable_dp() only calls
+ * us when active_mst_links==0, so any steps designated for "single
+ * stream or multi-stream master transcoder" can just be performed
+ * unconditionally here.
+ */
+
+ /*
+ * 5.a Configure Transcoder Clock Select to direct the Port clock to the
+ * Transcoder.
+ */
+ intel_ddi_enable_pipe_clock(encoder, crtc_state);
+
+ /* 5.b Not relevant to i915 for now */
+
+ /*
+ * 5.c Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
+ * Transport Select
+ */
+ intel_ddi_config_transcoder_func(encoder, crtc_state);
+
+ /*
+ * 5.d Configure & enable DP_TP_CTL with link training pattern 1
+ * selected
+ *
+ * This will be handled by the intel_dp_start_link_train() farther
+ * down this function.
+ */
+
+ /* 5.e Configure voltage swing and related IO settings */
+ intel_snps_phy_ddi_vswing_sequence(encoder, level);
+
+ /*
+ * 5.f Configure and enable DDI_BUF_CTL
+ * 5.g Wait for DDI_BUF_CTL DDI Idle Status = 0b (Not Idle), timeout
+ * after 1200 us.
+ *
+ * We only configure what the register value will be here. Actual
+ * enabling happens during link training farther down.
+ */
+ intel_ddi_init_dp_buf_reg(encoder, crtc_state);
+
+ if (!is_mst)
+ intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
+
+ intel_dp_sink_set_decompression_state(intel_dp, crtc_state, true);
+ /*
+ * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
+ * in the FEC_CONFIGURATION register to 1 before initiating link
+ * training
+ */
+ intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
+
+ /*
+ * 5.h Follow DisplayPort specification training sequence (see notes for
+ * failure handling)
+ * 5.i If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
+ * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
+ * (timeout after 800 us)
+ */
+ intel_dp_start_link_train(intel_dp, crtc_state);
+
+ /* 5.j Set DP_TP_CTL link training to Normal */
+ if (!is_trans_port_sync_mode(crtc_state))
+ intel_dp_stop_link_train(intel_dp, crtc_state);
+
+ /* 5.k Configure and enable FEC if needed */
+ intel_ddi_enable_fec(encoder, crtc_state);
+ intel_dsc_enable(encoder, crtc_state);
+}
+
static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
@@ -2714,12 +2612,10 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
if (DISPLAY_VER(dev_priv) >= 11)
icl_ddi_vswing_sequence(encoder, crtc_state, level);
- else if (IS_CANNONLAKE(dev_priv))
- cnl_ddi_vswing_sequence(encoder, crtc_state, level);
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_ddi_vswing_sequence(encoder, crtc_state, level);
else
- intel_prepare_dp_ddi_buffers(encoder, crtc_state);
+ hsw_prepare_dp_ddi_buffers(encoder, crtc_state);
intel_ddi_power_up_lanes(encoder, crtc_state);
@@ -2751,7 +2647,9 @@ static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (DISPLAY_VER(dev_priv) >= 12)
+ if (IS_DG2(dev_priv))
+ dg2_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
+ else if (DISPLAY_VER(dev_priv) >= 12)
tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
else
hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
@@ -2827,6 +2725,7 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state,
conn_state);
/* FIXME precompute everything properly */
+ /* FIXME how do we turn infoframes off again? */
if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
dig_port->set_infoframes(encoder,
crtc_state->has_infoframe,
@@ -3157,16 +3056,16 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
"[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n",
connector->base.id, connector->name);
- if (DISPLAY_VER(dev_priv) >= 12)
+ if (IS_DG2(dev_priv))
+ intel_snps_phy_ddi_vswing_sequence(encoder, U32_MAX);
+ else if (DISPLAY_VER(dev_priv) >= 12)
tgl_ddi_vswing_sequence(encoder, crtc_state, level);
else if (DISPLAY_VER(dev_priv) == 11)
icl_ddi_vswing_sequence(encoder, crtc_state, level);
- else if (IS_CANNONLAKE(dev_priv))
- cnl_ddi_vswing_sequence(encoder, crtc_state, level);
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_ddi_vswing_sequence(encoder, crtc_state, level);
else
- intel_prepare_hdmi_ddi_buffers(encoder, level);
+ hsw_prepare_hdmi_ddi_buffers(encoder, crtc_state, level);
if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
skl_ddi_set_iboost(encoder, crtc_state, level);
@@ -3260,12 +3159,6 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state,
intel_dp->link_trained = false;
- if (old_crtc_state->has_audio)
- intel_audio_codec_disable(encoder,
- old_crtc_state, old_conn_state);
-
- intel_edp_drrs_disable(intel_dp, old_crtc_state);
- intel_psr_disable(intel_dp, old_crtc_state);
intel_edp_backlight_off(old_conn_state);
/* Disable the decompression in DP Sink */
intel_dp_sink_set_decompression_state(intel_dp, old_crtc_state,
@@ -3283,10 +3176,6 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct drm_connector *connector = old_conn_state->connector;
- if (old_crtc_state->has_audio)
- intel_audio_codec_disable(encoder,
- old_crtc_state, old_conn_state);
-
if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
false, false))
drm_dbg_kms(&i915->drm,
@@ -3294,6 +3183,25 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
connector->base.id, connector->name);
}
+static void intel_pre_disable_ddi(struct intel_atomic_state *state,
+ 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;
+
+ if (old_crtc_state->has_audio)
+ intel_audio_codec_disable(encoder, old_crtc_state,
+ old_conn_state);
+
+ if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
+ return;
+
+ intel_dp = enc_to_intel_dp(encoder);
+ intel_edp_drrs_disable(intel_dp, old_crtc_state);
+ intel_psr_disable(intel_dp, old_crtc_state);
+}
+
static void intel_disable_ddi(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
@@ -3510,7 +3418,7 @@ static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
if (cpu_transcoder == TRANSCODER_EDP)
return false;
- if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO))
+ if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO_MMIO))
return false;
return intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD) &
@@ -3526,8 +3434,6 @@ void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
crtc_state->min_voltage_level = 3;
else if (DISPLAY_VER(dev_priv) >= 11 && crtc_state->port_clock > 594000)
crtc_state->min_voltage_level = 1;
- else if (IS_CANNONLAKE(dev_priv) && crtc_state->port_clock > 594000)
- crtc_state->min_voltage_level = 2;
}
static enum transcoder bdw_transcoder_master_readout(struct drm_i915_private *dev_priv,
@@ -3594,7 +3500,7 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
u32 temp, flags = 0;
@@ -3657,7 +3563,7 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
pipe_config->output_types |= BIT(INTEL_OUTPUT_DP);
pipe_config->lane_count =
((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
- intel_dp_get_m_n(intel_crtc, pipe_config);
+ intel_dp_get_m_n(crtc, pipe_config);
if (DISPLAY_VER(dev_priv) >= 11) {
i915_reg_t dp_tp_ctl = dp_tp_ctl_reg(encoder, pipe_config);
@@ -3687,7 +3593,7 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
pipe_config->mst_master_transcoder =
REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
- intel_dp_get_m_n(intel_crtc, pipe_config);
+ intel_dp_get_m_n(crtc, pipe_config);
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
@@ -3801,6 +3707,15 @@ void intel_ddi_get_clock(struct intel_encoder *encoder,
&crtc_state->dpll_hw_state);
}
+static void dg2_ddi_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state)
+{
+ intel_mpllb_readout_hw_state(encoder, &crtc_state->mpllb_state);
+ crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->mpllb_state);
+
+ intel_ddi_get_config(encoder, crtc_state);
+}
+
static void adls_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state)
{
@@ -3868,13 +3783,6 @@ static void icl_ddi_tc_get_config(struct intel_encoder *encoder,
intel_ddi_get_config(encoder, crtc_state);
}
-static void cnl_ddi_get_config(struct intel_encoder *encoder,
- struct intel_crtc_state *crtc_state)
-{
- intel_ddi_get_clock(encoder, crtc_state, cnl_ddi_get_pll(encoder));
- intel_ddi_get_config(encoder, crtc_state);
-}
-
static void bxt_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state)
{
@@ -4121,12 +4029,12 @@ intel_ddi_init_dp_connector(struct intel_digital_port *dig_port)
dig_port->dp.set_link_train = intel_ddi_set_link_train;
dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train;
- if (DISPLAY_VER(dev_priv) >= 12)
+ if (IS_DG2(dev_priv))
+ dig_port->dp.set_signal_levels = dg2_set_signal_levels;
+ else if (DISPLAY_VER(dev_priv) >= 12)
dig_port->dp.set_signal_levels = tgl_set_signal_levels;
else if (DISPLAY_VER(dev_priv) >= 11)
dig_port->dp.set_signal_levels = icl_set_signal_levels;
- else if (IS_CANNONLAKE(dev_priv))
- dig_port->dp.set_signal_levels = cnl_set_signal_levels;
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
dig_port->dp.set_signal_levels = bxt_set_signal_levels;
else
@@ -4373,15 +4281,6 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
return true;
- /* Cannonlake: Most of SKUs don't support DDI_E, and the only
- * one who does also have a full A/E split called
- * DDI_F what makes DDI_E useless. However for this
- * case let's trust VBT info.
- */
- if (IS_CANNONLAKE(dev_priv) &&
- !intel_bios_is_port_present(dev_priv, PORT_E))
- return true;
-
return false;
}
@@ -4486,15 +4385,6 @@ static enum hpd_pin ehl_hpd_pin(struct drm_i915_private *dev_priv,
return HPD_PORT_A + port - PORT_A;
}
-static enum hpd_pin cnl_hpd_pin(struct drm_i915_private *dev_priv,
- enum port port)
-{
- if (port == PORT_F)
- return HPD_PORT_E;
-
- return HPD_PORT_A + port - PORT_A;
-}
-
static enum hpd_pin skl_hpd_pin(struct drm_i915_private *dev_priv, enum port port)
{
if (HAS_PCH_TGP(dev_priv))
@@ -4513,6 +4403,36 @@ static bool intel_ddi_is_tc(struct drm_i915_private *i915, enum port port)
return false;
}
+static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
+{
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+ intel_dp_encoder_suspend(encoder);
+
+ if (!intel_phy_is_tc(i915, phy))
+ return;
+
+ intel_tc_port_disconnect_phy(dig_port);
+}
+
+static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder)
+{
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+ intel_dp_encoder_shutdown(encoder);
+
+ if (!intel_phy_is_tc(i915, phy))
+ return;
+
+ intel_tc_port_disconnect_phy(dig_port);
+}
+
#define port_tc_name(port) ((port) - PORT_TC1 + '1')
#define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1')
@@ -4616,14 +4536,15 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->enable = intel_enable_ddi;
encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
encoder->pre_enable = intel_ddi_pre_enable;
+ encoder->pre_disable = intel_pre_disable_ddi;
encoder->disable = intel_disable_ddi;
encoder->post_disable = intel_ddi_post_disable;
encoder->update_pipe = intel_ddi_update_pipe;
encoder->get_hw_state = intel_ddi_get_hw_state;
encoder->sync_state = intel_ddi_sync_state;
encoder->initial_fastset_check = intel_ddi_initial_fastset_check;
- encoder->suspend = intel_dp_encoder_suspend;
- encoder->shutdown = intel_dp_encoder_shutdown;
+ encoder->suspend = intel_ddi_encoder_suspend;
+ encoder->shutdown = intel_ddi_encoder_shutdown;
encoder->get_power_domains = intel_ddi_get_power_domains;
encoder->type = INTEL_OUTPUT_DDI;
@@ -4632,7 +4553,11 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->cloneable = 0;
encoder->pipe_mask = ~0;
- if (IS_ALDERLAKE_S(dev_priv)) {
+ if (IS_DG2(dev_priv)) {
+ encoder->enable_clock = intel_mpllb_enable;
+ encoder->disable_clock = intel_mpllb_disable;
+ encoder->get_config = dg2_ddi_get_config;
+ } else if (IS_ALDERLAKE_S(dev_priv)) {
encoder->enable_clock = adls_ddi_enable_clock;
encoder->disable_clock = adls_ddi_disable_clock;
encoder->is_clock_enabled = adls_ddi_is_clock_enabled;
@@ -4671,11 +4596,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
encoder->get_config = icl_ddi_combo_get_config;
}
- } else if (IS_CANNONLAKE(dev_priv)) {
- encoder->enable_clock = cnl_ddi_enable_clock;
- encoder->disable_clock = cnl_ddi_disable_clock;
- encoder->is_clock_enabled = cnl_ddi_is_clock_enabled;
- encoder->get_config = cnl_ddi_get_config;
} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
/* BXT/GLK have fixed PLL->port mapping */
encoder->get_config = bxt_ddi_get_config;
@@ -4691,6 +4611,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->get_config = hsw_ddi_get_config;
}
+ intel_ddi_buf_trans_init(encoder);
+
if (DISPLAY_VER(dev_priv) >= 13)
encoder->hpd_pin = xelpd_hpd_pin(dev_priv, port);
else if (IS_DG1(dev_priv))
@@ -4703,8 +4625,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->hpd_pin = ehl_hpd_pin(dev_priv, port);
else if (DISPLAY_VER(dev_priv) == 11)
encoder->hpd_pin = icl_hpd_pin(dev_priv, port);
- else if (IS_CANNONLAKE(dev_priv))
- encoder->hpd_pin = cnl_hpd_pin(dev_priv, port);
else if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
encoder->hpd_pin = skl_hpd_pin(dev_priv, port);
else
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h
index 59c6b01d4199..7d448485d887 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.h
+++ b/drivers/gpu/drm/i915/display/intel_ddi.h
@@ -40,8 +40,8 @@ bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder);
void hsw_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder);
-void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state);
+void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state);
void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
enum port port);
void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port);
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
index 8bfd00f49f2a..ba2c08f1a797 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
@@ -13,1095 +13,1160 @@
* them for both DP and FDI transports, allowing those ports to
* automatically adapt to HDMI connections as well
*/
-static const struct ddi_buf_trans hsw_ddi_translations_dp[] = {
- { 0x00FFFFFF, 0x0006000E, 0x0 },
- { 0x00D75FFF, 0x0005000A, 0x0 },
- { 0x00C30FFF, 0x00040006, 0x0 },
- { 0x80AAAFFF, 0x000B0000, 0x0 },
- { 0x00FFFFFF, 0x0005000A, 0x0 },
- { 0x00D75FFF, 0x000C0004, 0x0 },
- { 0x80C30FFF, 0x000B0000, 0x0 },
- { 0x00FFFFFF, 0x00040006, 0x0 },
- { 0x80D75FFF, 0x000B0000, 0x0 },
-};
-
-static const struct ddi_buf_trans hsw_ddi_translations_fdi[] = {
- { 0x00FFFFFF, 0x0007000E, 0x0 },
- { 0x00D75FFF, 0x000F000A, 0x0 },
- { 0x00C30FFF, 0x00060006, 0x0 },
- { 0x00AAAFFF, 0x001E0000, 0x0 },
- { 0x00FFFFFF, 0x000F000A, 0x0 },
- { 0x00D75FFF, 0x00160004, 0x0 },
- { 0x00C30FFF, 0x001E0000, 0x0 },
- { 0x00FFFFFF, 0x00060006, 0x0 },
- { 0x00D75FFF, 0x001E0000, 0x0 },
-};
-
-static const struct ddi_buf_trans hsw_ddi_translations_hdmi[] = {
- /* Idx NT mV d T mV d db */
- { 0x00FFFFFF, 0x0006000E, 0x0 },/* 0: 400 400 0 */
- { 0x00E79FFF, 0x000E000C, 0x0 },/* 1: 400 500 2 */
- { 0x00D75FFF, 0x0005000A, 0x0 },/* 2: 400 600 3.5 */
- { 0x00FFFFFF, 0x0005000A, 0x0 },/* 3: 600 600 0 */
- { 0x00E79FFF, 0x001D0007, 0x0 },/* 4: 600 750 2 */
- { 0x00D75FFF, 0x000C0004, 0x0 },/* 5: 600 900 3.5 */
- { 0x00FFFFFF, 0x00040006, 0x0 },/* 6: 800 800 0 */
- { 0x80E79FFF, 0x00030002, 0x0 },/* 7: 800 1000 2 */
- { 0x00FFFFFF, 0x00140005, 0x0 },/* 8: 850 850 0 */
- { 0x00FFFFFF, 0x000C0004, 0x0 },/* 9: 900 900 0 */
- { 0x00FFFFFF, 0x001C0003, 0x0 },/* 10: 950 950 0 */
- { 0x80FFFFFF, 0x00030002, 0x0 },/* 11: 1000 1000 0 */
-};
-
-static const struct ddi_buf_trans bdw_ddi_translations_edp[] = {
- { 0x00FFFFFF, 0x00000012, 0x0 },
- { 0x00EBAFFF, 0x00020011, 0x0 },
- { 0x00C71FFF, 0x0006000F, 0x0 },
- { 0x00AAAFFF, 0x000E000A, 0x0 },
- { 0x00FFFFFF, 0x00020011, 0x0 },
- { 0x00DB6FFF, 0x0005000F, 0x0 },
- { 0x00BEEFFF, 0x000A000C, 0x0 },
- { 0x00FFFFFF, 0x0005000F, 0x0 },
- { 0x00DB6FFF, 0x000A000C, 0x0 },
-};
-
-static const struct ddi_buf_trans bdw_ddi_translations_dp[] = {
- { 0x00FFFFFF, 0x0007000E, 0x0 },
- { 0x00D75FFF, 0x000E000A, 0x0 },
- { 0x00BEFFFF, 0x00140006, 0x0 },
- { 0x80B2CFFF, 0x001B0002, 0x0 },
- { 0x00FFFFFF, 0x000E000A, 0x0 },
- { 0x00DB6FFF, 0x00160005, 0x0 },
- { 0x80C71FFF, 0x001A0002, 0x0 },
- { 0x00F7DFFF, 0x00180004, 0x0 },
- { 0x80D75FFF, 0x001B0002, 0x0 },
-};
-
-static const struct ddi_buf_trans bdw_ddi_translations_fdi[] = {
- { 0x00FFFFFF, 0x0001000E, 0x0 },
- { 0x00D75FFF, 0x0004000A, 0x0 },
- { 0x00C30FFF, 0x00070006, 0x0 },
- { 0x00AAAFFF, 0x000C0000, 0x0 },
- { 0x00FFFFFF, 0x0004000A, 0x0 },
- { 0x00D75FFF, 0x00090004, 0x0 },
- { 0x00C30FFF, 0x000C0000, 0x0 },
- { 0x00FFFFFF, 0x00070006, 0x0 },
- { 0x00D75FFF, 0x000C0000, 0x0 },
-};
-
-static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = {
- /* Idx NT mV d T mV df db */
- { 0x00FFFFFF, 0x0007000E, 0x0 },/* 0: 400 400 0 */
- { 0x00D75FFF, 0x000E000A, 0x0 },/* 1: 400 600 3.5 */
- { 0x00BEFFFF, 0x00140006, 0x0 },/* 2: 400 800 6 */
- { 0x00FFFFFF, 0x0009000D, 0x0 },/* 3: 450 450 0 */
- { 0x00FFFFFF, 0x000E000A, 0x0 },/* 4: 600 600 0 */
- { 0x00D7FFFF, 0x00140006, 0x0 },/* 5: 600 800 2.5 */
- { 0x80CB2FFF, 0x001B0002, 0x0 },/* 6: 600 1000 4.5 */
- { 0x00FFFFFF, 0x00140006, 0x0 },/* 7: 800 800 0 */
- { 0x80E79FFF, 0x001B0002, 0x0 },/* 8: 800 1000 2 */
- { 0x80FFFFFF, 0x001B0002, 0x0 },/* 9: 1000 1000 0 */
+static const union intel_ddi_buf_trans_entry _hsw_ddi_translations_dp[] = {
+ { .hsw = { 0x00FFFFFF, 0x0006000E, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x0005000A, 0x0 } },
+ { .hsw = { 0x00C30FFF, 0x00040006, 0x0 } },
+ { .hsw = { 0x80AAAFFF, 0x000B0000, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x0005000A, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x000C0004, 0x0 } },
+ { .hsw = { 0x80C30FFF, 0x000B0000, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x00040006, 0x0 } },
+ { .hsw = { 0x80D75FFF, 0x000B0000, 0x0 } },
+};
+
+static const struct intel_ddi_buf_trans hsw_ddi_translations_dp = {
+ .entries = _hsw_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_hsw_ddi_translations_dp),
+};
+
+static const union intel_ddi_buf_trans_entry _hsw_ddi_translations_fdi[] = {
+ { .hsw = { 0x00FFFFFF, 0x0007000E, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x000F000A, 0x0 } },
+ { .hsw = { 0x00C30FFF, 0x00060006, 0x0 } },
+ { .hsw = { 0x00AAAFFF, 0x001E0000, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x000F000A, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x00160004, 0x0 } },
+ { .hsw = { 0x00C30FFF, 0x001E0000, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x00060006, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x001E0000, 0x0 } },
+};
+
+static const struct intel_ddi_buf_trans hsw_ddi_translations_fdi = {
+ .entries = _hsw_ddi_translations_fdi,
+ .num_entries = ARRAY_SIZE(_hsw_ddi_translations_fdi),
+};
+
+static const union intel_ddi_buf_trans_entry _hsw_ddi_translations_hdmi[] = {
+ /* Idx NT mV d T mV d db */
+ { .hsw = { 0x00FFFFFF, 0x0006000E, 0x0 } }, /* 0: 400 400 0 */
+ { .hsw = { 0x00E79FFF, 0x000E000C, 0x0 } }, /* 1: 400 500 2 */
+ { .hsw = { 0x00D75FFF, 0x0005000A, 0x0 } }, /* 2: 400 600 3.5 */
+ { .hsw = { 0x00FFFFFF, 0x0005000A, 0x0 } }, /* 3: 600 600 0 */
+ { .hsw = { 0x00E79FFF, 0x001D0007, 0x0 } }, /* 4: 600 750 2 */
+ { .hsw = { 0x00D75FFF, 0x000C0004, 0x0 } }, /* 5: 600 900 3.5 */
+ { .hsw = { 0x00FFFFFF, 0x00040006, 0x0 } }, /* 6: 800 800 0 */
+ { .hsw = { 0x80E79FFF, 0x00030002, 0x0 } }, /* 7: 800 1000 2 */
+ { .hsw = { 0x00FFFFFF, 0x00140005, 0x0 } }, /* 8: 850 850 0 */
+ { .hsw = { 0x00FFFFFF, 0x000C0004, 0x0 } }, /* 9: 900 900 0 */
+ { .hsw = { 0x00FFFFFF, 0x001C0003, 0x0 } }, /* 10: 950 950 0 */
+ { .hsw = { 0x80FFFFFF, 0x00030002, 0x0 } }, /* 11: 1000 1000 0 */
+};
+
+static const struct intel_ddi_buf_trans hsw_ddi_translations_hdmi = {
+ .entries = _hsw_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_hsw_ddi_translations_hdmi),
+ .hdmi_default_entry = 6,
+};
+
+static const union intel_ddi_buf_trans_entry _bdw_ddi_translations_edp[] = {
+ { .hsw = { 0x00FFFFFF, 0x00000012, 0x0 } },
+ { .hsw = { 0x00EBAFFF, 0x00020011, 0x0 } },
+ { .hsw = { 0x00C71FFF, 0x0006000F, 0x0 } },
+ { .hsw = { 0x00AAAFFF, 0x000E000A, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x00020011, 0x0 } },
+ { .hsw = { 0x00DB6FFF, 0x0005000F, 0x0 } },
+ { .hsw = { 0x00BEEFFF, 0x000A000C, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x0005000F, 0x0 } },
+ { .hsw = { 0x00DB6FFF, 0x000A000C, 0x0 } },
+};
+
+static const struct intel_ddi_buf_trans bdw_ddi_translations_edp = {
+ .entries = _bdw_ddi_translations_edp,
+ .num_entries = ARRAY_SIZE(_bdw_ddi_translations_edp),
+};
+
+static const union intel_ddi_buf_trans_entry _bdw_ddi_translations_dp[] = {
+ { .hsw = { 0x00FFFFFF, 0x0007000E, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x000E000A, 0x0 } },
+ { .hsw = { 0x00BEFFFF, 0x00140006, 0x0 } },
+ { .hsw = { 0x80B2CFFF, 0x001B0002, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x000E000A, 0x0 } },
+ { .hsw = { 0x00DB6FFF, 0x00160005, 0x0 } },
+ { .hsw = { 0x80C71FFF, 0x001A0002, 0x0 } },
+ { .hsw = { 0x00F7DFFF, 0x00180004, 0x0 } },
+ { .hsw = { 0x80D75FFF, 0x001B0002, 0x0 } },
+};
+
+static const struct intel_ddi_buf_trans bdw_ddi_translations_dp = {
+ .entries = _bdw_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_bdw_ddi_translations_dp),
+};
+
+static const union intel_ddi_buf_trans_entry _bdw_ddi_translations_fdi[] = {
+ { .hsw = { 0x00FFFFFF, 0x0001000E, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x0004000A, 0x0 } },
+ { .hsw = { 0x00C30FFF, 0x00070006, 0x0 } },
+ { .hsw = { 0x00AAAFFF, 0x000C0000, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x0004000A, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x00090004, 0x0 } },
+ { .hsw = { 0x00C30FFF, 0x000C0000, 0x0 } },
+ { .hsw = { 0x00FFFFFF, 0x00070006, 0x0 } },
+ { .hsw = { 0x00D75FFF, 0x000C0000, 0x0 } },
+};
+
+static const struct intel_ddi_buf_trans bdw_ddi_translations_fdi = {
+ .entries = _bdw_ddi_translations_fdi,
+ .num_entries = ARRAY_SIZE(_bdw_ddi_translations_fdi),
+};
+
+static const union intel_ddi_buf_trans_entry _bdw_ddi_translations_hdmi[] = {
+ /* Idx NT mV d T mV df db */
+ { .hsw = { 0x00FFFFFF, 0x0007000E, 0x0 } }, /* 0: 400 400 0 */
+ { .hsw = { 0x00D75FFF, 0x000E000A, 0x0 } }, /* 1: 400 600 3.5 */
+ { .hsw = { 0x00BEFFFF, 0x00140006, 0x0 } }, /* 2: 400 800 6 */
+ { .hsw = { 0x00FFFFFF, 0x0009000D, 0x0 } }, /* 3: 450 450 0 */
+ { .hsw = { 0x00FFFFFF, 0x000E000A, 0x0 } }, /* 4: 600 600 0 */
+ { .hsw = { 0x00D7FFFF, 0x00140006, 0x0 } }, /* 5: 600 800 2.5 */
+ { .hsw = { 0x80CB2FFF, 0x001B0002, 0x0 } }, /* 6: 600 1000 4.5 */
+ { .hsw = { 0x00FFFFFF, 0x00140006, 0x0 } }, /* 7: 800 800 0 */
+ { .hsw = { 0x80E79FFF, 0x001B0002, 0x0 } }, /* 8: 800 1000 2 */
+ { .hsw = { 0x80FFFFFF, 0x001B0002, 0x0 } }, /* 9: 1000 1000 0 */
+};
+
+static const struct intel_ddi_buf_trans bdw_ddi_translations_hdmi = {
+ .entries = _bdw_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_bdw_ddi_translations_hdmi),
+ .hdmi_default_entry = 7,
};
/* Skylake H and S */
-static const struct ddi_buf_trans skl_ddi_translations_dp[] = {
- { 0x00002016, 0x000000A0, 0x0 },
- { 0x00005012, 0x0000009B, 0x0 },
- { 0x00007011, 0x00000088, 0x0 },
- { 0x80009010, 0x000000C0, 0x1 },
- { 0x00002016, 0x0000009B, 0x0 },
- { 0x00005012, 0x00000088, 0x0 },
- { 0x80007011, 0x000000C0, 0x1 },
- { 0x00002016, 0x000000DF, 0x0 },
- { 0x80005012, 0x000000C0, 0x1 },
+static const union intel_ddi_buf_trans_entry _skl_ddi_translations_dp[] = {
+ { .hsw = { 0x00002016, 0x000000A0, 0x0 } },
+ { .hsw = { 0x00005012, 0x0000009B, 0x0 } },
+ { .hsw = { 0x00007011, 0x00000088, 0x0 } },
+ { .hsw = { 0x80009010, 0x000000C0, 0x1 } },
+ { .hsw = { 0x00002016, 0x0000009B, 0x0 } },
+ { .hsw = { 0x00005012, 0x00000088, 0x0 } },
+ { .hsw = { 0x80007011, 0x000000C0, 0x1 } },
+ { .hsw = { 0x00002016, 0x000000DF, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x1 } },
+};
+
+static const struct intel_ddi_buf_trans skl_ddi_translations_dp = {
+ .entries = _skl_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_skl_ddi_translations_dp),
};
/* Skylake U */
-static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = {
- { 0x0000201B, 0x000000A2, 0x0 },
- { 0x00005012, 0x00000088, 0x0 },
- { 0x80007011, 0x000000CD, 0x1 },
- { 0x80009010, 0x000000C0, 0x1 },
- { 0x0000201B, 0x0000009D, 0x0 },
- { 0x80005012, 0x000000C0, 0x1 },
- { 0x80007011, 0x000000C0, 0x1 },
- { 0x00002016, 0x00000088, 0x0 },
- { 0x80005012, 0x000000C0, 0x1 },
+static const union intel_ddi_buf_trans_entry _skl_u_ddi_translations_dp[] = {
+ { .hsw = { 0x0000201B, 0x000000A2, 0x0 } },
+ { .hsw = { 0x00005012, 0x00000088, 0x0 } },
+ { .hsw = { 0x80007011, 0x000000CD, 0x1 } },
+ { .hsw = { 0x80009010, 0x000000C0, 0x1 } },
+ { .hsw = { 0x0000201B, 0x0000009D, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x1 } },
+ { .hsw = { 0x80007011, 0x000000C0, 0x1 } },
+ { .hsw = { 0x00002016, 0x00000088, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x1 } },
+};
+
+static const struct intel_ddi_buf_trans skl_u_ddi_translations_dp = {
+ .entries = _skl_u_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_skl_u_ddi_translations_dp),
};
/* Skylake Y */
-static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = {
- { 0x00000018, 0x000000A2, 0x0 },
- { 0x00005012, 0x00000088, 0x0 },
- { 0x80007011, 0x000000CD, 0x3 },
- { 0x80009010, 0x000000C0, 0x3 },
- { 0x00000018, 0x0000009D, 0x0 },
- { 0x80005012, 0x000000C0, 0x3 },
- { 0x80007011, 0x000000C0, 0x3 },
- { 0x00000018, 0x00000088, 0x0 },
- { 0x80005012, 0x000000C0, 0x3 },
+static const union intel_ddi_buf_trans_entry _skl_y_ddi_translations_dp[] = {
+ { .hsw = { 0x00000018, 0x000000A2, 0x0 } },
+ { .hsw = { 0x00005012, 0x00000088, 0x0 } },
+ { .hsw = { 0x80007011, 0x000000CD, 0x3 } },
+ { .hsw = { 0x80009010, 0x000000C0, 0x3 } },
+ { .hsw = { 0x00000018, 0x0000009D, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x3 } },
+ { .hsw = { 0x80007011, 0x000000C0, 0x3 } },
+ { .hsw = { 0x00000018, 0x00000088, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x3 } },
+};
+
+static const struct intel_ddi_buf_trans skl_y_ddi_translations_dp = {
+ .entries = _skl_y_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_skl_y_ddi_translations_dp),
};
/* Kabylake H and S */
-static const struct ddi_buf_trans kbl_ddi_translations_dp[] = {
- { 0x00002016, 0x000000A0, 0x0 },
- { 0x00005012, 0x0000009B, 0x0 },
- { 0x00007011, 0x00000088, 0x0 },
- { 0x80009010, 0x000000C0, 0x1 },
- { 0x00002016, 0x0000009B, 0x0 },
- { 0x00005012, 0x00000088, 0x0 },
- { 0x80007011, 0x000000C0, 0x1 },
- { 0x00002016, 0x00000097, 0x0 },
- { 0x80005012, 0x000000C0, 0x1 },
+static const union intel_ddi_buf_trans_entry _kbl_ddi_translations_dp[] = {
+ { .hsw = { 0x00002016, 0x000000A0, 0x0 } },
+ { .hsw = { 0x00005012, 0x0000009B, 0x0 } },
+ { .hsw = { 0x00007011, 0x00000088, 0x0 } },
+ { .hsw = { 0x80009010, 0x000000C0, 0x1 } },
+ { .hsw = { 0x00002016, 0x0000009B, 0x0 } },
+ { .hsw = { 0x00005012, 0x00000088, 0x0 } },
+ { .hsw = { 0x80007011, 0x000000C0, 0x1 } },
+ { .hsw = { 0x00002016, 0x00000097, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x1 } },
+};
+
+static const struct intel_ddi_buf_trans kbl_ddi_translations_dp = {
+ .entries = _kbl_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_kbl_ddi_translations_dp),
};
/* Kabylake U */
-static const struct ddi_buf_trans kbl_u_ddi_translations_dp[] = {
- { 0x0000201B, 0x000000A1, 0x0 },
- { 0x00005012, 0x00000088, 0x0 },
- { 0x80007011, 0x000000CD, 0x3 },
- { 0x80009010, 0x000000C0, 0x3 },
- { 0x0000201B, 0x0000009D, 0x0 },
- { 0x80005012, 0x000000C0, 0x3 },
- { 0x80007011, 0x000000C0, 0x3 },
- { 0x00002016, 0x0000004F, 0x0 },
- { 0x80005012, 0x000000C0, 0x3 },
+static const union intel_ddi_buf_trans_entry _kbl_u_ddi_translations_dp[] = {
+ { .hsw = { 0x0000201B, 0x000000A1, 0x0 } },
+ { .hsw = { 0x00005012, 0x00000088, 0x0 } },
+ { .hsw = { 0x80007011, 0x000000CD, 0x3 } },
+ { .hsw = { 0x80009010, 0x000000C0, 0x3 } },
+ { .hsw = { 0x0000201B, 0x0000009D, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x3 } },
+ { .hsw = { 0x80007011, 0x000000C0, 0x3 } },
+ { .hsw = { 0x00002016, 0x0000004F, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x3 } },
+};
+
+static const struct intel_ddi_buf_trans kbl_u_ddi_translations_dp = {
+ .entries = _kbl_u_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_kbl_u_ddi_translations_dp),
};
/* Kabylake Y */
-static const struct ddi_buf_trans kbl_y_ddi_translations_dp[] = {
- { 0x00001017, 0x000000A1, 0x0 },
- { 0x00005012, 0x00000088, 0x0 },
- { 0x80007011, 0x000000CD, 0x3 },
- { 0x8000800F, 0x000000C0, 0x3 },
- { 0x00001017, 0x0000009D, 0x0 },
- { 0x80005012, 0x000000C0, 0x3 },
- { 0x80007011, 0x000000C0, 0x3 },
- { 0x00001017, 0x0000004C, 0x0 },
- { 0x80005012, 0x000000C0, 0x3 },
+static const union intel_ddi_buf_trans_entry _kbl_y_ddi_translations_dp[] = {
+ { .hsw = { 0x00001017, 0x000000A1, 0x0 } },
+ { .hsw = { 0x00005012, 0x00000088, 0x0 } },
+ { .hsw = { 0x80007011, 0x000000CD, 0x3 } },
+ { .hsw = { 0x8000800F, 0x000000C0, 0x3 } },
+ { .hsw = { 0x00001017, 0x0000009D, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x3 } },
+ { .hsw = { 0x80007011, 0x000000C0, 0x3 } },
+ { .hsw = { 0x00001017, 0x0000004C, 0x0 } },
+ { .hsw = { 0x80005012, 0x000000C0, 0x3 } },
+};
+
+static const struct intel_ddi_buf_trans kbl_y_ddi_translations_dp = {
+ .entries = _kbl_y_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_kbl_y_ddi_translations_dp),
};
/*
* Skylake/Kabylake H and S
* eDP 1.4 low vswing translation parameters
*/
-static const struct ddi_buf_trans skl_ddi_translations_edp[] = {
- { 0x00000018, 0x000000A8, 0x0 },
- { 0x00004013, 0x000000A9, 0x0 },
- { 0x00007011, 0x000000A2, 0x0 },
- { 0x00009010, 0x0000009C, 0x0 },
- { 0x00000018, 0x000000A9, 0x0 },
- { 0x00006013, 0x000000A2, 0x0 },
- { 0x00007011, 0x000000A6, 0x0 },
- { 0x00000018, 0x000000AB, 0x0 },
- { 0x00007013, 0x0000009F, 0x0 },
- { 0x00000018, 0x000000DF, 0x0 },
+static const union intel_ddi_buf_trans_entry _skl_ddi_translations_edp[] = {
+ { .hsw = { 0x00000018, 0x000000A8, 0x0 } },
+ { .hsw = { 0x00004013, 0x000000A9, 0x0 } },
+ { .hsw = { 0x00007011, 0x000000A2, 0x0 } },
+ { .hsw = { 0x00009010, 0x0000009C, 0x0 } },
+ { .hsw = { 0x00000018, 0x000000A9, 0x0 } },
+ { .hsw = { 0x00006013, 0x000000A2, 0x0 } },
+ { .hsw = { 0x00007011, 0x000000A6, 0x0 } },
+ { .hsw = { 0x00000018, 0x000000AB, 0x0 } },
+ { .hsw = { 0x00007013, 0x0000009F, 0x0 } },
+ { .hsw = { 0x00000018, 0x000000DF, 0x0 } },
+};
+
+static const struct intel_ddi_buf_trans skl_ddi_translations_edp = {
+ .entries = _skl_ddi_translations_edp,
+ .num_entries = ARRAY_SIZE(_skl_ddi_translations_edp),
};
/*
* Skylake/Kabylake U
* eDP 1.4 low vswing translation parameters
*/
-static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = {
- { 0x00000018, 0x000000A8, 0x0 },
- { 0x00004013, 0x000000A9, 0x0 },
- { 0x00007011, 0x000000A2, 0x0 },
- { 0x00009010, 0x0000009C, 0x0 },
- { 0x00000018, 0x000000A9, 0x0 },
- { 0x00006013, 0x000000A2, 0x0 },
- { 0x00007011, 0x000000A6, 0x0 },
- { 0x00002016, 0x000000AB, 0x0 },
- { 0x00005013, 0x0000009F, 0x0 },
- { 0x00000018, 0x000000DF, 0x0 },
+static const union intel_ddi_buf_trans_entry _skl_u_ddi_translations_edp[] = {
+ { .hsw = { 0x00000018, 0x000000A8, 0x0 } },
+ { .hsw = { 0x00004013, 0x000000A9, 0x0 } },
+ { .hsw = { 0x00007011, 0x000000A2, 0x0 } },
+ { .hsw = { 0x00009010, 0x0000009C, 0x0 } },
+ { .hsw = { 0x00000018, 0x000000A9, 0x0 } },
+ { .hsw = { 0x00006013, 0x000000A2, 0x0 } },
+ { .hsw = { 0x00007011, 0x000000A6, 0x0 } },
+ { .hsw = { 0x00002016, 0x000000AB, 0x0 } },
+ { .hsw = { 0x00005013, 0x0000009F, 0x0 } },
+ { .hsw = { 0x00000018, 0x000000DF, 0x0 } },
+};
+
+static const struct intel_ddi_buf_trans skl_u_ddi_translations_edp = {
+ .entries = _skl_u_ddi_translations_edp,
+ .num_entries = ARRAY_SIZE(_skl_u_ddi_translations_edp),
};
/*
* Skylake/Kabylake Y
* eDP 1.4 low vswing translation parameters
*/
-static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = {
- { 0x00000018, 0x000000A8, 0x0 },
- { 0x00004013, 0x000000AB, 0x0 },
- { 0x00007011, 0x000000A4, 0x0 },
- { 0x00009010, 0x000000DF, 0x0 },
- { 0x00000018, 0x000000AA, 0x0 },
- { 0x00006013, 0x000000A4, 0x0 },
- { 0x00007011, 0x0000009D, 0x0 },
- { 0x00000018, 0x000000A0, 0x0 },
- { 0x00006012, 0x000000DF, 0x0 },
- { 0x00000018, 0x0000008A, 0x0 },
+static const union intel_ddi_buf_trans_entry _skl_y_ddi_translations_edp[] = {
+ { .hsw = { 0x00000018, 0x000000A8, 0x0 } },
+ { .hsw = { 0x00004013, 0x000000AB, 0x0 } },
+ { .hsw = { 0x00007011, 0x000000A4, 0x0 } },
+ { .hsw = { 0x00009010, 0x000000DF, 0x0 } },
+ { .hsw = { 0x00000018, 0x000000AA, 0x0 } },
+ { .hsw = { 0x00006013, 0x000000A4, 0x0 } },
+ { .hsw = { 0x00007011, 0x0000009D, 0x0 } },
+ { .hsw = { 0x00000018, 0x000000A0, 0x0 } },
+ { .hsw = { 0x00006012, 0x000000DF, 0x0 } },
+ { .hsw = { 0x00000018, 0x0000008A, 0x0 } },
+};
+
+static const struct intel_ddi_buf_trans skl_y_ddi_translations_edp = {
+ .entries = _skl_y_ddi_translations_edp,
+ .num_entries = ARRAY_SIZE(_skl_y_ddi_translations_edp),
};
/* Skylake/Kabylake U, H and S */
-static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
- { 0x00000018, 0x000000AC, 0x0 },
- { 0x00005012, 0x0000009D, 0x0 },
- { 0x00007011, 0x00000088, 0x0 },
- { 0x00000018, 0x000000A1, 0x0 },
- { 0x00000018, 0x00000098, 0x0 },
- { 0x00004013, 0x00000088, 0x0 },
- { 0x80006012, 0x000000CD, 0x1 },
- { 0x00000018, 0x000000DF, 0x0 },
- { 0x80003015, 0x000000CD, 0x1 }, /* Default */
- { 0x80003015, 0x000000C0, 0x1 },
- { 0x80000018, 0x000000C0, 0x1 },
+static const union intel_ddi_buf_trans_entry _skl_ddi_translations_hdmi[] = {
+ { .hsw = { 0x00000018, 0x000000AC, 0x0 } },
+ { .hsw = { 0x00005012, 0x0000009D, 0x0 } },
+ { .hsw = { 0x00007011, 0x00000088, 0x0 } },
+ { .hsw = { 0x00000018, 0x000000A1, 0x0 } },
+ { .hsw = { 0x00000018, 0x00000098, 0x0 } },
+ { .hsw = { 0x00004013, 0x00000088, 0x0 } },
+ { .hsw = { 0x80006012, 0x000000CD, 0x1 } },
+ { .hsw = { 0x00000018, 0x000000DF, 0x0 } },
+ { .hsw = { 0x80003015, 0x000000CD, 0x1 } }, /* Default */
+ { .hsw = { 0x80003015, 0x000000C0, 0x1 } },
+ { .hsw = { 0x80000018, 0x000000C0, 0x1 } },
+};
+
+static const struct intel_ddi_buf_trans skl_ddi_translations_hdmi = {
+ .entries = _skl_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_skl_ddi_translations_hdmi),
+ .hdmi_default_entry = 8,
};
/* Skylake/Kabylake Y */
-static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = {
- { 0x00000018, 0x000000A1, 0x0 },
- { 0x00005012, 0x000000DF, 0x0 },
- { 0x80007011, 0x000000CB, 0x3 },
- { 0x00000018, 0x000000A4, 0x0 },
- { 0x00000018, 0x0000009D, 0x0 },
- { 0x00004013, 0x00000080, 0x0 },
- { 0x80006013, 0x000000C0, 0x3 },
- { 0x00000018, 0x0000008A, 0x0 },
- { 0x80003015, 0x000000C0, 0x3 }, /* Default */
- { 0x80003015, 0x000000C0, 0x3 },
- { 0x80000018, 0x000000C0, 0x3 },
-};
-
-
-static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = {
- /* Idx NT mV diff db */
- { 52, 0x9A, 0, 128, }, /* 0: 400 0 */
- { 78, 0x9A, 0, 85, }, /* 1: 400 3.5 */
- { 104, 0x9A, 0, 64, }, /* 2: 400 6 */
- { 154, 0x9A, 0, 43, }, /* 3: 400 9.5 */
- { 77, 0x9A, 0, 128, }, /* 4: 600 0 */
- { 116, 0x9A, 0, 85, }, /* 5: 600 3.5 */
- { 154, 0x9A, 0, 64, }, /* 6: 600 6 */
- { 102, 0x9A, 0, 128, }, /* 7: 800 0 */
- { 154, 0x9A, 0, 85, }, /* 8: 800 3.5 */
- { 154, 0x9A, 1, 128, }, /* 9: 1200 0 */
-};
-
-static const struct bxt_ddi_buf_trans bxt_ddi_translations_edp[] = {
+static const union intel_ddi_buf_trans_entry _skl_y_ddi_translations_hdmi[] = {
+ { .hsw = { 0x00000018, 0x000000A1, 0x0 } },
+ { .hsw = { 0x00005012, 0x000000DF, 0x0 } },
+ { .hsw = { 0x80007011, 0x000000CB, 0x3 } },
+ { .hsw = { 0x00000018, 0x000000A4, 0x0 } },
+ { .hsw = { 0x00000018, 0x0000009D, 0x0 } },
+ { .hsw = { 0x00004013, 0x00000080, 0x0 } },
+ { .hsw = { 0x80006013, 0x000000C0, 0x3 } },
+ { .hsw = { 0x00000018, 0x0000008A, 0x0 } },
+ { .hsw = { 0x80003015, 0x000000C0, 0x3 } }, /* Default */
+ { .hsw = { 0x80003015, 0x000000C0, 0x3 } },
+ { .hsw = { 0x80000018, 0x000000C0, 0x3 } },
+};
+
+static const struct intel_ddi_buf_trans skl_y_ddi_translations_hdmi = {
+ .entries = _skl_y_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_skl_y_ddi_translations_hdmi),
+ .hdmi_default_entry = 8,
+};
+
+static const union intel_ddi_buf_trans_entry _bxt_ddi_translations_dp[] = {
+ /* Idx NT mV diff db */
+ { .bxt = { 52, 0x9A, 0, 128, } }, /* 0: 400 0 */
+ { .bxt = { 78, 0x9A, 0, 85, } }, /* 1: 400 3.5 */
+ { .bxt = { 104, 0x9A, 0, 64, } }, /* 2: 400 6 */
+ { .bxt = { 154, 0x9A, 0, 43, } }, /* 3: 400 9.5 */
+ { .bxt = { 77, 0x9A, 0, 128, } }, /* 4: 600 0 */
+ { .bxt = { 116, 0x9A, 0, 85, } }, /* 5: 600 3.5 */
+ { .bxt = { 154, 0x9A, 0, 64, } }, /* 6: 600 6 */
+ { .bxt = { 102, 0x9A, 0, 128, } }, /* 7: 800 0 */
+ { .bxt = { 154, 0x9A, 0, 85, } }, /* 8: 800 3.5 */
+ { .bxt = { 154, 0x9A, 1, 128, } }, /* 9: 1200 0 */
+};
+
+static const struct intel_ddi_buf_trans bxt_ddi_translations_dp = {
+ .entries = _bxt_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_bxt_ddi_translations_dp),
+};
+
+static const union intel_ddi_buf_trans_entry _bxt_ddi_translations_edp[] = {
/* Idx NT mV diff db */
- { 26, 0, 0, 128, }, /* 0: 200 0 */
- { 38, 0, 0, 112, }, /* 1: 200 1.5 */
- { 48, 0, 0, 96, }, /* 2: 200 4 */
- { 54, 0, 0, 69, }, /* 3: 200 6 */
- { 32, 0, 0, 128, }, /* 4: 250 0 */
- { 48, 0, 0, 104, }, /* 5: 250 1.5 */
- { 54, 0, 0, 85, }, /* 6: 250 4 */
- { 43, 0, 0, 128, }, /* 7: 300 0 */
- { 54, 0, 0, 101, }, /* 8: 300 1.5 */
- { 48, 0, 0, 128, }, /* 9: 300 0 */
+ { .bxt = { 26, 0, 0, 128, } }, /* 0: 200 0 */
+ { .bxt = { 38, 0, 0, 112, } }, /* 1: 200 1.5 */
+ { .bxt = { 48, 0, 0, 96, } }, /* 2: 200 4 */
+ { .bxt = { 54, 0, 0, 69, } }, /* 3: 200 6 */
+ { .bxt = { 32, 0, 0, 128, } }, /* 4: 250 0 */
+ { .bxt = { 48, 0, 0, 104, } }, /* 5: 250 1.5 */
+ { .bxt = { 54, 0, 0, 85, } }, /* 6: 250 4 */
+ { .bxt = { 43, 0, 0, 128, } }, /* 7: 300 0 */
+ { .bxt = { 54, 0, 0, 101, } }, /* 8: 300 1.5 */
+ { .bxt = { 48, 0, 0, 128, } }, /* 9: 300 0 */
+};
+
+static const struct intel_ddi_buf_trans bxt_ddi_translations_edp = {
+ .entries = _bxt_ddi_translations_edp,
+ .num_entries = ARRAY_SIZE(_bxt_ddi_translations_edp),
};
/* BSpec has 2 recommended values - entries 0 and 8.
* Using the entry with higher vswing.
*/
-static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = {
- /* Idx NT mV diff db */
- { 52, 0x9A, 0, 128, }, /* 0: 400 0 */
- { 52, 0x9A, 0, 85, }, /* 1: 400 3.5 */
- { 52, 0x9A, 0, 64, }, /* 2: 400 6 */
- { 42, 0x9A, 0, 43, }, /* 3: 400 9.5 */
- { 77, 0x9A, 0, 128, }, /* 4: 600 0 */
- { 77, 0x9A, 0, 85, }, /* 5: 600 3.5 */
- { 77, 0x9A, 0, 64, }, /* 6: 600 6 */
- { 102, 0x9A, 0, 128, }, /* 7: 800 0 */
- { 102, 0x9A, 0, 85, }, /* 8: 800 3.5 */
- { 154, 0x9A, 1, 128, }, /* 9: 1200 0 */
-};
-
-/* Voltage Swing Programming for VccIO 0.85V for DP */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_dp_0_85V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x5D, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x6A, 0x38, 0x00, 0x07 }, /* 350 500 3.1 */
- { 0xB, 0x7A, 0x32, 0x00, 0x0D }, /* 350 700 6.0 */
- { 0x6, 0x7C, 0x2D, 0x00, 0x12 }, /* 350 900 8.2 */
- { 0xA, 0x69, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xB, 0x7A, 0x36, 0x00, 0x09 }, /* 500 700 2.9 */
- { 0x6, 0x7C, 0x30, 0x00, 0x0F }, /* 500 900 5.1 */
- { 0xB, 0x7D, 0x3C, 0x00, 0x03 }, /* 650 725 0.9 */
- { 0x6, 0x7C, 0x34, 0x00, 0x0B }, /* 600 900 3.5 */
- { 0x6, 0x7B, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-/* Voltage Swing Programming for VccIO 0.85V for HDMI */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_hdmi_0_85V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x60, 0x3F, 0x00, 0x00 }, /* 450 450 0.0 */
- { 0xB, 0x73, 0x36, 0x00, 0x09 }, /* 450 650 3.2 */
- { 0x6, 0x7F, 0x31, 0x00, 0x0E }, /* 450 850 5.5 */
- { 0xB, 0x73, 0x3F, 0x00, 0x00 }, /* 650 650 0.0 */
- { 0x6, 0x7F, 0x37, 0x00, 0x08 }, /* 650 850 2.3 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 850 850 0.0 */
- { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 850 3.0 */
-};
-
-/* Voltage Swing Programming for VccIO 0.85V for eDP */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_0_85V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x66, 0x3A, 0x00, 0x05 }, /* 384 500 2.3 */
- { 0x0, 0x7F, 0x38, 0x00, 0x07 }, /* 153 200 2.3 */
- { 0x8, 0x7F, 0x38, 0x00, 0x07 }, /* 192 250 2.3 */
- { 0x1, 0x7F, 0x38, 0x00, 0x07 }, /* 230 300 2.3 */
- { 0x9, 0x7F, 0x38, 0x00, 0x07 }, /* 269 350 2.3 */
- { 0xA, 0x66, 0x3C, 0x00, 0x03 }, /* 446 500 1.0 */
- { 0xB, 0x70, 0x3C, 0x00, 0x03 }, /* 460 600 2.3 */
- { 0xC, 0x75, 0x3C, 0x00, 0x03 }, /* 537 700 2.3 */
- { 0x2, 0x7F, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */
-};
-
-/* Voltage Swing Programming for VccIO 0.95V for DP */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_dp_0_95V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x5D, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x6A, 0x38, 0x00, 0x07 }, /* 350 500 3.1 */
- { 0xB, 0x7A, 0x32, 0x00, 0x0D }, /* 350 700 6.0 */
- { 0x6, 0x7C, 0x2D, 0x00, 0x12 }, /* 350 900 8.2 */
- { 0xA, 0x69, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xB, 0x7A, 0x36, 0x00, 0x09 }, /* 500 700 2.9 */
- { 0x6, 0x7C, 0x30, 0x00, 0x0F }, /* 500 900 5.1 */
- { 0xB, 0x7D, 0x3C, 0x00, 0x03 }, /* 650 725 0.9 */
- { 0x6, 0x7C, 0x34, 0x00, 0x0B }, /* 600 900 3.5 */
- { 0x6, 0x7B, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-/* Voltage Swing Programming for VccIO 0.95V for HDMI */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_hdmi_0_95V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x5C, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */
- { 0xB, 0x69, 0x37, 0x00, 0x08 }, /* 400 600 3.5 */
- { 0x5, 0x76, 0x31, 0x00, 0x0E }, /* 400 800 6.0 */
- { 0xA, 0x5E, 0x3F, 0x00, 0x00 }, /* 450 450 0.0 */
- { 0xB, 0x69, 0x3F, 0x00, 0x00 }, /* 600 600 0.0 */
- { 0xB, 0x79, 0x35, 0x00, 0x0A }, /* 600 850 3.0 */
- { 0x6, 0x7D, 0x32, 0x00, 0x0D }, /* 600 1000 4.4 */
- { 0x5, 0x76, 0x3F, 0x00, 0x00 }, /* 800 800 0.0 */
- { 0x6, 0x7D, 0x39, 0x00, 0x06 }, /* 800 1000 1.9 */
- { 0x6, 0x7F, 0x39, 0x00, 0x06 }, /* 850 1050 1.8 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1050 1050 0.0 */
-};
-
-/* Voltage Swing Programming for VccIO 0.95V for eDP */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_0_95V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x61, 0x3A, 0x00, 0x05 }, /* 384 500 2.3 */
- { 0x0, 0x7F, 0x38, 0x00, 0x07 }, /* 153 200 2.3 */
- { 0x8, 0x7F, 0x38, 0x00, 0x07 }, /* 192 250 2.3 */
- { 0x1, 0x7F, 0x38, 0x00, 0x07 }, /* 230 300 2.3 */
- { 0x9, 0x7F, 0x38, 0x00, 0x07 }, /* 269 350 2.3 */
- { 0xA, 0x61, 0x3C, 0x00, 0x03 }, /* 446 500 1.0 */
- { 0xB, 0x68, 0x39, 0x00, 0x06 }, /* 460 600 2.3 */
- { 0xC, 0x6E, 0x39, 0x00, 0x06 }, /* 537 700 2.3 */
- { 0x4, 0x7F, 0x3A, 0x00, 0x05 }, /* 460 600 2.3 */
- { 0x2, 0x7F, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */
-};
-
-/* Voltage Swing Programming for VccIO 1.05V for DP */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_dp_1_05V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x58, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */
- { 0xB, 0x64, 0x37, 0x00, 0x08 }, /* 400 600 3.5 */
- { 0x5, 0x70, 0x31, 0x00, 0x0E }, /* 400 800 6.0 */
- { 0x6, 0x7F, 0x2C, 0x00, 0x13 }, /* 400 1050 8.4 */
- { 0xB, 0x64, 0x3F, 0x00, 0x00 }, /* 600 600 0.0 */
- { 0x5, 0x73, 0x35, 0x00, 0x0A }, /* 600 850 3.0 */
- { 0x6, 0x7F, 0x30, 0x00, 0x0F }, /* 550 1050 5.6 */
- { 0x5, 0x76, 0x3E, 0x00, 0x01 }, /* 850 900 0.5 */
- { 0x6, 0x7F, 0x36, 0x00, 0x09 }, /* 750 1050 2.9 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1050 1050 0.0 */
-};
-
-/* Voltage Swing Programming for VccIO 1.05V for HDMI */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_hdmi_1_05V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x58, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */
- { 0xB, 0x64, 0x37, 0x00, 0x08 }, /* 400 600 3.5 */
- { 0x5, 0x70, 0x31, 0x00, 0x0E }, /* 400 800 6.0 */
- { 0xA, 0x5B, 0x3F, 0x00, 0x00 }, /* 450 450 0.0 */
- { 0xB, 0x64, 0x3F, 0x00, 0x00 }, /* 600 600 0.0 */
- { 0x5, 0x73, 0x35, 0x00, 0x0A }, /* 600 850 3.0 */
- { 0x6, 0x7C, 0x32, 0x00, 0x0D }, /* 600 1000 4.4 */
- { 0x5, 0x70, 0x3F, 0x00, 0x00 }, /* 800 800 0.0 */
- { 0x6, 0x7C, 0x39, 0x00, 0x06 }, /* 800 1000 1.9 */
- { 0x6, 0x7F, 0x39, 0x00, 0x06 }, /* 850 1050 1.8 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1050 1050 0.0 */
-};
-
-/* Voltage Swing Programming for VccIO 1.05V for eDP */
-static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x5E, 0x3A, 0x00, 0x05 }, /* 384 500 2.3 */
- { 0x0, 0x7F, 0x38, 0x00, 0x07 }, /* 153 200 2.3 */
- { 0x8, 0x7F, 0x38, 0x00, 0x07 }, /* 192 250 2.3 */
- { 0x1, 0x7F, 0x38, 0x00, 0x07 }, /* 230 300 2.3 */
- { 0x9, 0x7F, 0x38, 0x00, 0x07 }, /* 269 350 2.3 */
- { 0xA, 0x5E, 0x3C, 0x00, 0x03 }, /* 446 500 1.0 */
- { 0xB, 0x64, 0x39, 0x00, 0x06 }, /* 460 600 2.3 */
- { 0xE, 0x6A, 0x39, 0x00, 0x06 }, /* 537 700 2.3 */
- { 0x2, 0x7F, 0x3F, 0x00, 0x00 }, /* 400 400 0.0 */
+static const union intel_ddi_buf_trans_entry _bxt_ddi_translations_hdmi[] = {
+ /* Idx NT mV diff db */
+ { .bxt = { 52, 0x9A, 0, 128, } }, /* 0: 400 0 */
+ { .bxt = { 52, 0x9A, 0, 85, } }, /* 1: 400 3.5 */
+ { .bxt = { 52, 0x9A, 0, 64, } }, /* 2: 400 6 */
+ { .bxt = { 42, 0x9A, 0, 43, } }, /* 3: 400 9.5 */
+ { .bxt = { 77, 0x9A, 0, 128, } }, /* 4: 600 0 */
+ { .bxt = { 77, 0x9A, 0, 85, } }, /* 5: 600 3.5 */
+ { .bxt = { 77, 0x9A, 0, 64, } }, /* 6: 600 6 */
+ { .bxt = { 102, 0x9A, 0, 128, } }, /* 7: 800 0 */
+ { .bxt = { 102, 0x9A, 0, 85, } }, /* 8: 800 3.5 */
+ { .bxt = { 154, 0x9A, 1, 128, } }, /* 9: 1200 0 */
+};
+
+static const struct intel_ddi_buf_trans bxt_ddi_translations_hdmi = {
+ .entries = _bxt_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_bxt_ddi_translations_hdmi),
+ .hdmi_default_entry = ARRAY_SIZE(_bxt_ddi_translations_hdmi) - 1,
};
/* icl_combo_phy_ddi_translations */
-static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */
- { 0xC, 0x71, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
- { 0x6, 0x7F, 0x2B, 0x00, 0x14 }, /* 350 900 8.2 */
- { 0xA, 0x4C, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x73, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */
- { 0xC, 0x6C, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */
- { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = {
- /* NT mV Trans mV db */
- { 0x0, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 200 0.0 */
- { 0x8, 0x7F, 0x38, 0x00, 0x07 }, /* 200 250 1.9 */
- { 0x1, 0x7F, 0x33, 0x00, 0x0C }, /* 200 300 3.5 */
- { 0x9, 0x7F, 0x31, 0x00, 0x0E }, /* 200 350 4.9 */
- { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 250 0.0 */
- { 0x1, 0x7F, 0x38, 0x00, 0x07 }, /* 250 300 1.6 */
- { 0x9, 0x7F, 0x35, 0x00, 0x0A }, /* 250 350 2.9 */
- { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 300 300 0.0 */
- { 0x9, 0x7F, 0x38, 0x00, 0x07 }, /* 300 350 1.3 */
- { 0x9, 0x7F, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */
- { 0xC, 0x71, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
- { 0x6, 0x7F, 0x2B, 0x00, 0x14 }, /* 350 900 8.2 */
- { 0xA, 0x4C, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x73, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */
- { 0xC, 0x6C, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */
- { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x60, 0x3F, 0x00, 0x00 }, /* 450 450 0.0 */
- { 0xB, 0x73, 0x36, 0x00, 0x09 }, /* 450 650 3.2 */
- { 0x6, 0x7F, 0x31, 0x00, 0x0E }, /* 450 850 5.5 */
- { 0xB, 0x73, 0x3F, 0x00, 0x00 }, /* 650 650 0.0 ALS */
- { 0x6, 0x7F, 0x37, 0x00, 0x08 }, /* 650 850 2.3 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 850 850 0.0 */
- { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 850 3.0 */
-};
-
-static const struct cnl_ddi_buf_trans ehl_combo_phy_ddi_translations_dp[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x33, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x47, 0x36, 0x00, 0x09 }, /* 350 500 3.1 */
- { 0xC, 0x64, 0x34, 0x00, 0x0B }, /* 350 700 6.0 */
- { 0x6, 0x7F, 0x30, 0x00, 0x0F }, /* 350 900 8.2 */
- { 0xA, 0x46, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x64, 0x38, 0x00, 0x07 }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x32, 0x00, 0x0D }, /* 500 900 5.1 */
- { 0xC, 0x61, 0x3F, 0x00, 0x00 }, /* 650 700 0.6 */
- { 0x6, 0x7F, 0x38, 0x00, 0x07 }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans jsl_combo_phy_ddi_translations_edp_hbr[] = {
- /* NT mV Trans mV db */
- { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 200 0.0 */
- { 0x8, 0x7F, 0x38, 0x00, 0x07 }, /* 200 250 1.9 */
- { 0x1, 0x7F, 0x33, 0x00, 0x0C }, /* 200 300 3.5 */
- { 0xA, 0x35, 0x36, 0x00, 0x09 }, /* 200 350 4.9 */
- { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 250 0.0 */
- { 0x1, 0x7F, 0x38, 0x00, 0x07 }, /* 250 300 1.6 */
- { 0xA, 0x35, 0x35, 0x00, 0x0A }, /* 250 350 2.9 */
- { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 300 300 0.0 */
- { 0xA, 0x35, 0x38, 0x00, 0x07 }, /* 300 350 1.3 */
- { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans jsl_combo_phy_ddi_translations_edp_hbr2[] = {
- /* NT mV Trans mV db */
- { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 200 0.0 */
- { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 250 1.9 */
- { 0x1, 0x7F, 0x3D, 0x00, 0x02 }, /* 200 300 3.5 */
- { 0xA, 0x35, 0x38, 0x00, 0x07 }, /* 200 350 4.9 */
- { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 250 0.0 */
- { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 300 1.6 */
- { 0xA, 0x35, 0x3A, 0x00, 0x05 }, /* 250 350 2.9 */
- { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 300 300 0.0 */
- { 0xA, 0x35, 0x38, 0x00, 0x07 }, /* 300 350 1.3 */
- { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans dg1_combo_phy_ddi_translations_dp_rbr_hbr[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x32, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x48, 0x35, 0x00, 0x0A }, /* 350 500 3.1 */
- { 0xC, 0x63, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
- { 0x6, 0x7F, 0x2C, 0x00, 0x13 }, /* 350 900 8.2 */
- { 0xA, 0x43, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x60, 0x36, 0x00, 0x09 }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x30, 0x00, 0x0F }, /* 500 900 5.1 */
- { 0xC, 0x60, 0x3F, 0x00, 0x00 }, /* 650 700 0.6 */
- { 0x6, 0x7F, 0x37, 0x00, 0x08 }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans dg1_combo_phy_ddi_translations_dp_hbr2_hbr3[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x32, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x48, 0x35, 0x00, 0x0A }, /* 350 500 3.1 */
- { 0xC, 0x63, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
- { 0x6, 0x7F, 0x2C, 0x00, 0x13 }, /* 350 900 8.2 */
- { 0xA, 0x43, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x60, 0x36, 0x00, 0x09 }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x30, 0x00, 0x0F }, /* 500 900 5.1 */
- { 0xC, 0x58, 0x3F, 0x00, 0x00 }, /* 650 700 0.6 */
- { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct icl_mg_phy_ddi_buf_trans icl_mg_phy_ddi_translations_rbr_hbr[] = {
- /* Voltage swing pre-emphasis */
- { 0x18, 0x00, 0x00 }, /* 0 0 */
- { 0x1D, 0x00, 0x05 }, /* 0 1 */
- { 0x24, 0x00, 0x0C }, /* 0 2 */
- { 0x2B, 0x00, 0x14 }, /* 0 3 */
- { 0x21, 0x00, 0x00 }, /* 1 0 */
- { 0x2B, 0x00, 0x08 }, /* 1 1 */
- { 0x30, 0x00, 0x0F }, /* 1 2 */
- { 0x31, 0x00, 0x03 }, /* 2 0 */
- { 0x34, 0x00, 0x0B }, /* 2 1 */
- { 0x3F, 0x00, 0x00 }, /* 3 0 */
-};
-
-static const struct icl_mg_phy_ddi_buf_trans icl_mg_phy_ddi_translations_hbr2_hbr3[] = {
- /* Voltage swing pre-emphasis */
- { 0x18, 0x00, 0x00 }, /* 0 0 */
- { 0x1D, 0x00, 0x05 }, /* 0 1 */
- { 0x24, 0x00, 0x0C }, /* 0 2 */
- { 0x2B, 0x00, 0x14 }, /* 0 3 */
- { 0x26, 0x00, 0x00 }, /* 1 0 */
- { 0x2C, 0x00, 0x07 }, /* 1 1 */
- { 0x33, 0x00, 0x0C }, /* 1 2 */
- { 0x2E, 0x00, 0x00 }, /* 2 0 */
- { 0x36, 0x00, 0x09 }, /* 2 1 */
- { 0x3F, 0x00, 0x00 }, /* 3 0 */
-};
-
-static const struct icl_mg_phy_ddi_buf_trans icl_mg_phy_ddi_translations_hdmi[] = {
- /* HDMI Preset VS Pre-emph */
- { 0x1A, 0x0, 0x0 }, /* 1 400mV 0dB */
- { 0x20, 0x0, 0x0 }, /* 2 500mV 0dB */
- { 0x29, 0x0, 0x0 }, /* 3 650mV 0dB */
- { 0x32, 0x0, 0x0 }, /* 4 800mV 0dB */
- { 0x3F, 0x0, 0x0 }, /* 5 1000mV 0dB */
- { 0x3A, 0x0, 0x5 }, /* 6 Full -1.5 dB */
- { 0x39, 0x0, 0x6 }, /* 7 Full -1.8 dB */
- { 0x38, 0x0, 0x7 }, /* 8 Full -2 dB */
- { 0x37, 0x0, 0x8 }, /* 9 Full -2.5 dB */
- { 0x36, 0x0, 0x9 }, /* 10 Full -3 dB */
-};
-
-static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_dp_ddi_trans[] = {
- /* VS pre-emp Non-trans mV Pre-emph dB */
- { 0x7, 0x0, 0x00 }, /* 0 0 400mV 0 dB */
- { 0x5, 0x0, 0x05 }, /* 0 1 400mV 3.5 dB */
- { 0x2, 0x0, 0x0B }, /* 0 2 400mV 6 dB */
- { 0x0, 0x0, 0x18 }, /* 0 3 400mV 9.5 dB */
- { 0x5, 0x0, 0x00 }, /* 1 0 600mV 0 dB */
- { 0x2, 0x0, 0x08 }, /* 1 1 600mV 3.5 dB */
- { 0x0, 0x0, 0x14 }, /* 1 2 600mV 6 dB */
- { 0x2, 0x0, 0x00 }, /* 2 0 800mV 0 dB */
- { 0x0, 0x0, 0x0B }, /* 2 1 800mV 3.5 dB */
- { 0x0, 0x0, 0x00 }, /* 3 0 1200mV 0 dB HDMI default */
-};
-
-static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_dp_ddi_trans_hbr2[] = {
- /* VS pre-emp Non-trans mV Pre-emph dB */
- { 0x7, 0x0, 0x00 }, /* 0 0 400mV 0 dB */
- { 0x5, 0x0, 0x05 }, /* 0 1 400mV 3.5 dB */
- { 0x2, 0x0, 0x0B }, /* 0 2 400mV 6 dB */
- { 0x0, 0x0, 0x19 }, /* 0 3 400mV 9.5 dB */
- { 0x5, 0x0, 0x00 }, /* 1 0 600mV 0 dB */
- { 0x2, 0x0, 0x08 }, /* 1 1 600mV 3.5 dB */
- { 0x0, 0x0, 0x14 }, /* 1 2 600mV 6 dB */
- { 0x2, 0x0, 0x00 }, /* 2 0 800mV 0 dB */
- { 0x0, 0x0, 0x0B }, /* 2 1 800mV 3.5 dB */
- { 0x0, 0x0, 0x00 }, /* 3 0 1200mV 0 dB HDMI default */
-};
-
-static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_hdmi_ddi_trans[] = {
- /* HDMI Preset VS Pre-emph */
- { 0x7, 0x0, 0x0 }, /* 1 400mV 0dB */
- { 0x6, 0x0, 0x0 }, /* 2 500mV 0dB */
- { 0x4, 0x0, 0x0 }, /* 3 650mV 0dB */
- { 0x2, 0x0, 0x0 }, /* 4 800mV 0dB */
- { 0x0, 0x0, 0x0 }, /* 5 1000mV 0dB */
- { 0x0, 0x0, 0x5 }, /* 6 Full -1.5 dB */
- { 0x0, 0x0, 0x6 }, /* 7 Full -1.8 dB */
- { 0x0, 0x0, 0x7 }, /* 8 Full -2 dB */
- { 0x0, 0x0, 0x8 }, /* 9 Full -2.5 dB */
- { 0x0, 0x0, 0xA }, /* 10 Full -3 dB */
-};
-
-static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x32, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */
- { 0xC, 0x71, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
- { 0x6, 0x7D, 0x2B, 0x00, 0x14 }, /* 350 900 8.2 */
- { 0xA, 0x4C, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x73, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */
- { 0xC, 0x6C, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */
- { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr2[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */
- { 0xC, 0x63, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
- { 0x6, 0x7F, 0x2B, 0x00, 0x14 }, /* 350 900 8.2 */
- { 0xA, 0x47, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x63, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */
- { 0xC, 0x61, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */
- { 0x6, 0x7B, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans tgl_uy_combo_phy_ddi_translations_dp_hbr2[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x4F, 0x36, 0x00, 0x09 }, /* 350 500 3.1 */
- { 0xC, 0x60, 0x32, 0x00, 0x0D }, /* 350 700 6.0 */
- { 0xC, 0x7F, 0x2D, 0x00, 0x12 }, /* 350 900 8.2 */
- { 0xC, 0x47, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x6F, 0x36, 0x00, 0x09 }, /* 500 700 2.9 */
- { 0x6, 0x7D, 0x32, 0x00, 0x0D }, /* 500 900 5.1 */
- { 0x6, 0x60, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */
- { 0x6, 0x7F, 0x34, 0x00, 0x0B }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
+static const union intel_ddi_buf_trans_entry _icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x71, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x6C, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
+
+static const struct intel_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3 = {
+ .entries = _icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3,
+ .num_entries = ARRAY_SIZE(_icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3),
+};
+
+static const union intel_ddi_buf_trans_entry _icl_combo_phy_ddi_translations_edp_hbr2[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0x0, 0x7F, 0x3F, 0x00, 0x00 } }, /* 200 200 0.0 */
+ { .icl = { 0x8, 0x7F, 0x38, 0x00, 0x07 } }, /* 200 250 1.9 */
+ { .icl = { 0x1, 0x7F, 0x33, 0x00, 0x0C } }, /* 200 300 3.5 */
+ { .icl = { 0x9, 0x7F, 0x31, 0x00, 0x0E } }, /* 200 350 4.9 */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 250 250 0.0 */
+ { .icl = { 0x1, 0x7F, 0x38, 0x00, 0x07 } }, /* 250 300 1.6 */
+ { .icl = { 0x9, 0x7F, 0x35, 0x00, 0x0A } }, /* 250 350 2.9 */
+ { .icl = { 0x1, 0x7F, 0x3F, 0x00, 0x00 } }, /* 300 300 0.0 */
+ { .icl = { 0x9, 0x7F, 0x38, 0x00, 0x07 } }, /* 300 350 1.3 */
+ { .icl = { 0x9, 0x7F, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+};
+
+static const struct intel_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2 = {
+ .entries = _icl_combo_phy_ddi_translations_edp_hbr2,
+ .num_entries = ARRAY_SIZE(_icl_combo_phy_ddi_translations_edp_hbr2),
+};
+
+static const union intel_ddi_buf_trans_entry _icl_combo_phy_ddi_translations_hdmi[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x60, 0x3F, 0x00, 0x00 } }, /* 450 450 0.0 */
+ { .icl = { 0xB, 0x73, 0x36, 0x00, 0x09 } }, /* 450 650 3.2 */
+ { .icl = { 0x6, 0x7F, 0x31, 0x00, 0x0E } }, /* 450 850 5.5 */
+ { .icl = { 0xB, 0x73, 0x3F, 0x00, 0x00 } }, /* 650 650 0.0 ALS */
+ { .icl = { 0x6, 0x7F, 0x37, 0x00, 0x08 } }, /* 650 850 2.3 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 850 850 0.0 */
+ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 850 3.0 */
+};
+
+static const struct intel_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi = {
+ .entries = _icl_combo_phy_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_icl_combo_phy_ddi_translations_hdmi),
+ .hdmi_default_entry = ARRAY_SIZE(_icl_combo_phy_ddi_translations_hdmi) - 1,
+};
+
+static const union intel_ddi_buf_trans_entry _ehl_combo_phy_ddi_translations_dp[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x33, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x47, 0x36, 0x00, 0x09 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x64, 0x34, 0x00, 0x0B } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x30, 0x00, 0x0F } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x46, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x64, 0x38, 0x00, 0x07 } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x32, 0x00, 0x0D } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x61, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x38, 0x00, 0x07 } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
+
+static const struct intel_ddi_buf_trans ehl_combo_phy_ddi_translations_dp = {
+ .entries = _ehl_combo_phy_ddi_translations_dp,
+ .num_entries = ARRAY_SIZE(_ehl_combo_phy_ddi_translations_dp),
+};
+
+static const union intel_ddi_buf_trans_entry _ehl_combo_phy_ddi_translations_edp_hbr2[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 200 200 0.0 */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 200 250 1.9 */
+ { .icl = { 0x1, 0x7F, 0x3D, 0x00, 0x02 } }, /* 200 300 3.5 */
+ { .icl = { 0xA, 0x35, 0x39, 0x00, 0x06 } }, /* 200 350 4.9 */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 250 250 0.0 */
+ { .icl = { 0x1, 0x7F, 0x3C, 0x00, 0x03 } }, /* 250 300 1.6 */
+ { .icl = { 0xA, 0x35, 0x39, 0x00, 0x06 } }, /* 250 350 2.9 */
+ { .icl = { 0x1, 0x7F, 0x3F, 0x00, 0x00 } }, /* 300 300 0.0 */
+ { .icl = { 0xA, 0x35, 0x38, 0x00, 0x07 } }, /* 300 350 1.3 */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+};
+
+static const struct intel_ddi_buf_trans ehl_combo_phy_ddi_translations_edp_hbr2 = {
+ .entries = _ehl_combo_phy_ddi_translations_edp_hbr2,
+ .num_entries = ARRAY_SIZE(_ehl_combo_phy_ddi_translations_edp_hbr2),
+};
+
+static const union intel_ddi_buf_trans_entry _jsl_combo_phy_ddi_translations_edp_hbr[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 200 200 0.0 */
+ { .icl = { 0x8, 0x7F, 0x38, 0x00, 0x07 } }, /* 200 250 1.9 */
+ { .icl = { 0x1, 0x7F, 0x33, 0x00, 0x0C } }, /* 200 300 3.5 */
+ { .icl = { 0xA, 0x35, 0x36, 0x00, 0x09 } }, /* 200 350 4.9 */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 250 250 0.0 */
+ { .icl = { 0x1, 0x7F, 0x38, 0x00, 0x07 } }, /* 250 300 1.6 */
+ { .icl = { 0xA, 0x35, 0x35, 0x00, 0x0A } }, /* 250 350 2.9 */
+ { .icl = { 0x1, 0x7F, 0x3F, 0x00, 0x00 } }, /* 300 300 0.0 */
+ { .icl = { 0xA, 0x35, 0x38, 0x00, 0x07 } }, /* 300 350 1.3 */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+};
+
+static const struct intel_ddi_buf_trans jsl_combo_phy_ddi_translations_edp_hbr = {
+ .entries = _jsl_combo_phy_ddi_translations_edp_hbr,
+ .num_entries = ARRAY_SIZE(_jsl_combo_phy_ddi_translations_edp_hbr),
+};
+
+static const union intel_ddi_buf_trans_entry _jsl_combo_phy_ddi_translations_edp_hbr2[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 200 200 0.0 */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 200 250 1.9 */
+ { .icl = { 0x1, 0x7F, 0x3D, 0x00, 0x02 } }, /* 200 300 3.5 */
+ { .icl = { 0xA, 0x35, 0x38, 0x00, 0x07 } }, /* 200 350 4.9 */
+ { .icl = { 0x8, 0x7F, 0x3F, 0x00, 0x00 } }, /* 250 250 0.0 */
+ { .icl = { 0x1, 0x7F, 0x3F, 0x00, 0x00 } }, /* 250 300 1.6 */
+ { .icl = { 0xA, 0x35, 0x3A, 0x00, 0x05 } }, /* 250 350 2.9 */
+ { .icl = { 0x1, 0x7F, 0x3F, 0x00, 0x00 } }, /* 300 300 0.0 */
+ { .icl = { 0xA, 0x35, 0x38, 0x00, 0x07 } }, /* 300 350 1.3 */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+};
+
+static const struct intel_ddi_buf_trans jsl_combo_phy_ddi_translations_edp_hbr2 = {
+ .entries = _jsl_combo_phy_ddi_translations_edp_hbr2,
+ .num_entries = ARRAY_SIZE(_jsl_combo_phy_ddi_translations_edp_hbr2),
+};
+
+static const union intel_ddi_buf_trans_entry _dg1_combo_phy_ddi_translations_dp_rbr_hbr[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x32, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x48, 0x35, 0x00, 0x0A } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x63, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2C, 0x00, 0x13 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x43, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x60, 0x36, 0x00, 0x09 } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x30, 0x00, 0x0F } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x60, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x37, 0x00, 0x08 } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
+
+static const struct intel_ddi_buf_trans dg1_combo_phy_ddi_translations_dp_rbr_hbr = {
+ .entries = _dg1_combo_phy_ddi_translations_dp_rbr_hbr,
+ .num_entries = ARRAY_SIZE(_dg1_combo_phy_ddi_translations_dp_rbr_hbr),
+};
+
+static const union intel_ddi_buf_trans_entry _dg1_combo_phy_ddi_translations_dp_hbr2_hbr3[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x32, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x48, 0x35, 0x00, 0x0A } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x63, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2C, 0x00, 0x13 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x43, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x60, 0x36, 0x00, 0x09 } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x30, 0x00, 0x0F } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x58, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
+
+static const struct intel_ddi_buf_trans dg1_combo_phy_ddi_translations_dp_hbr2_hbr3 = {
+ .entries = _dg1_combo_phy_ddi_translations_dp_hbr2_hbr3,
+ .num_entries = ARRAY_SIZE(_dg1_combo_phy_ddi_translations_dp_hbr2_hbr3),
+};
+
+static const union intel_ddi_buf_trans_entry _icl_mg_phy_ddi_translations_rbr_hbr[] = {
+ /* Voltage swing pre-emphasis */
+ { .mg = { 0x18, 0x00, 0x00 } }, /* 0 0 */
+ { .mg = { 0x1D, 0x00, 0x05 } }, /* 0 1 */
+ { .mg = { 0x24, 0x00, 0x0C } }, /* 0 2 */
+ { .mg = { 0x2B, 0x00, 0x14 } }, /* 0 3 */
+ { .mg = { 0x21, 0x00, 0x00 } }, /* 1 0 */
+ { .mg = { 0x2B, 0x00, 0x08 } }, /* 1 1 */
+ { .mg = { 0x30, 0x00, 0x0F } }, /* 1 2 */
+ { .mg = { 0x31, 0x00, 0x03 } }, /* 2 0 */
+ { .mg = { 0x34, 0x00, 0x0B } }, /* 2 1 */
+ { .mg = { 0x3F, 0x00, 0x00 } }, /* 3 0 */
+};
+
+static const struct intel_ddi_buf_trans icl_mg_phy_ddi_translations_rbr_hbr = {
+ .entries = _icl_mg_phy_ddi_translations_rbr_hbr,
+ .num_entries = ARRAY_SIZE(_icl_mg_phy_ddi_translations_rbr_hbr),
+};
+
+static const union intel_ddi_buf_trans_entry _icl_mg_phy_ddi_translations_hbr2_hbr3[] = {
+ /* Voltage swing pre-emphasis */
+ { .mg = { 0x18, 0x00, 0x00 } }, /* 0 0 */
+ { .mg = { 0x1D, 0x00, 0x05 } }, /* 0 1 */
+ { .mg = { 0x24, 0x00, 0x0C } }, /* 0 2 */
+ { .mg = { 0x2B, 0x00, 0x14 } }, /* 0 3 */
+ { .mg = { 0x26, 0x00, 0x00 } }, /* 1 0 */
+ { .mg = { 0x2C, 0x00, 0x07 } }, /* 1 1 */
+ { .mg = { 0x33, 0x00, 0x0C } }, /* 1 2 */
+ { .mg = { 0x2E, 0x00, 0x00 } }, /* 2 0 */
+ { .mg = { 0x36, 0x00, 0x09 } }, /* 2 1 */
+ { .mg = { 0x3F, 0x00, 0x00 } }, /* 3 0 */
+};
+
+static const struct intel_ddi_buf_trans icl_mg_phy_ddi_translations_hbr2_hbr3 = {
+ .entries = _icl_mg_phy_ddi_translations_hbr2_hbr3,
+ .num_entries = ARRAY_SIZE(_icl_mg_phy_ddi_translations_hbr2_hbr3),
+};
+
+static const union intel_ddi_buf_trans_entry _icl_mg_phy_ddi_translations_hdmi[] = {
+ /* HDMI Preset VS Pre-emph */
+ { .mg = { 0x1A, 0x0, 0x0 } }, /* 1 400mV 0dB */
+ { .mg = { 0x20, 0x0, 0x0 } }, /* 2 500mV 0dB */
+ { .mg = { 0x29, 0x0, 0x0 } }, /* 3 650mV 0dB */
+ { .mg = { 0x32, 0x0, 0x0 } }, /* 4 800mV 0dB */
+ { .mg = { 0x3F, 0x0, 0x0 } }, /* 5 1000mV 0dB */
+ { .mg = { 0x3A, 0x0, 0x5 } }, /* 6 Full -1.5 dB */
+ { .mg = { 0x39, 0x0, 0x6 } }, /* 7 Full -1.8 dB */
+ { .mg = { 0x38, 0x0, 0x7 } }, /* 8 Full -2 dB */
+ { .mg = { 0x37, 0x0, 0x8 } }, /* 9 Full -2.5 dB */
+ { .mg = { 0x36, 0x0, 0x9 } }, /* 10 Full -3 dB */
+};
+
+static const struct intel_ddi_buf_trans icl_mg_phy_ddi_translations_hdmi = {
+ .entries = _icl_mg_phy_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_icl_mg_phy_ddi_translations_hdmi),
+ .hdmi_default_entry = ARRAY_SIZE(_icl_mg_phy_ddi_translations_hdmi) - 1,
+};
+
+static const union intel_ddi_buf_trans_entry _tgl_dkl_phy_ddi_translations_dp_hbr[] = {
+ /* VS pre-emp Non-trans mV Pre-emph dB */
+ { .dkl = { 0x7, 0x0, 0x00 } }, /* 0 0 400mV 0 dB */
+ { .dkl = { 0x5, 0x0, 0x05 } }, /* 0 1 400mV 3.5 dB */
+ { .dkl = { 0x2, 0x0, 0x0B } }, /* 0 2 400mV 6 dB */
+ { .dkl = { 0x0, 0x0, 0x18 } }, /* 0 3 400mV 9.5 dB */
+ { .dkl = { 0x5, 0x0, 0x00 } }, /* 1 0 600mV 0 dB */
+ { .dkl = { 0x2, 0x0, 0x08 } }, /* 1 1 600mV 3.5 dB */
+ { .dkl = { 0x0, 0x0, 0x14 } }, /* 1 2 600mV 6 dB */
+ { .dkl = { 0x2, 0x0, 0x00 } }, /* 2 0 800mV 0 dB */
+ { .dkl = { 0x0, 0x0, 0x0B } }, /* 2 1 800mV 3.5 dB */
+ { .dkl = { 0x0, 0x0, 0x00 } }, /* 3 0 1200mV 0 dB HDMI default */
+};
+
+static const struct intel_ddi_buf_trans tgl_dkl_phy_ddi_translations_dp_hbr = {
+ .entries = _tgl_dkl_phy_ddi_translations_dp_hbr,
+ .num_entries = ARRAY_SIZE(_tgl_dkl_phy_ddi_translations_dp_hbr),
+};
+
+static const union intel_ddi_buf_trans_entry _tgl_dkl_phy_ddi_translations_dp_hbr2[] = {
+ /* VS pre-emp Non-trans mV Pre-emph dB */
+ { .dkl = { 0x7, 0x0, 0x00 } }, /* 0 0 400mV 0 dB */
+ { .dkl = { 0x5, 0x0, 0x05 } }, /* 0 1 400mV 3.5 dB */
+ { .dkl = { 0x2, 0x0, 0x0B } }, /* 0 2 400mV 6 dB */
+ { .dkl = { 0x0, 0x0, 0x19 } }, /* 0 3 400mV 9.5 dB */
+ { .dkl = { 0x5, 0x0, 0x00 } }, /* 1 0 600mV 0 dB */
+ { .dkl = { 0x2, 0x0, 0x08 } }, /* 1 1 600mV 3.5 dB */
+ { .dkl = { 0x0, 0x0, 0x14 } }, /* 1 2 600mV 6 dB */
+ { .dkl = { 0x2, 0x0, 0x00 } }, /* 2 0 800mV 0 dB */
+ { .dkl = { 0x0, 0x0, 0x0B } }, /* 2 1 800mV 3.5 dB */
+ { .dkl = { 0x0, 0x0, 0x00 } }, /* 3 0 1200mV 0 dB HDMI default */
+};
+
+static const struct intel_ddi_buf_trans tgl_dkl_phy_ddi_translations_dp_hbr2 = {
+ .entries = _tgl_dkl_phy_ddi_translations_dp_hbr2,
+ .num_entries = ARRAY_SIZE(_tgl_dkl_phy_ddi_translations_dp_hbr2),
+};
+
+static const union intel_ddi_buf_trans_entry _tgl_dkl_phy_ddi_translations_hdmi[] = {
+ /* HDMI Preset VS Pre-emph */
+ { .dkl = { 0x7, 0x0, 0x0 } }, /* 1 400mV 0dB */
+ { .dkl = { 0x6, 0x0, 0x0 } }, /* 2 500mV 0dB */
+ { .dkl = { 0x4, 0x0, 0x0 } }, /* 3 650mV 0dB */
+ { .dkl = { 0x2, 0x0, 0x0 } }, /* 4 800mV 0dB */
+ { .dkl = { 0x0, 0x0, 0x0 } }, /* 5 1000mV 0dB */
+ { .dkl = { 0x0, 0x0, 0x5 } }, /* 6 Full -1.5 dB */
+ { .dkl = { 0x0, 0x0, 0x6 } }, /* 7 Full -1.8 dB */
+ { .dkl = { 0x0, 0x0, 0x7 } }, /* 8 Full -2 dB */
+ { .dkl = { 0x0, 0x0, 0x8 } }, /* 9 Full -2.5 dB */
+ { .dkl = { 0x0, 0x0, 0xA } }, /* 10 Full -3 dB */
+};
+
+static const struct intel_ddi_buf_trans tgl_dkl_phy_ddi_translations_hdmi = {
+ .entries = _tgl_dkl_phy_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_tgl_dkl_phy_ddi_translations_hdmi),
+ .hdmi_default_entry = ARRAY_SIZE(_tgl_dkl_phy_ddi_translations_hdmi) - 1,
+};
+
+static const union intel_ddi_buf_trans_entry _tgl_combo_phy_ddi_translations_dp_hbr[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x32, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x71, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7D, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x6C, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
+
+static const struct intel_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr = {
+ .entries = _tgl_combo_phy_ddi_translations_dp_hbr,
+ .num_entries = ARRAY_SIZE(_tgl_combo_phy_ddi_translations_dp_hbr),
+};
+
+static const union intel_ddi_buf_trans_entry _tgl_combo_phy_ddi_translations_dp_hbr2[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x63, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x47, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x63, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x61, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7B, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
+
+static const struct intel_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr2 = {
+ .entries = _tgl_combo_phy_ddi_translations_dp_hbr2,
+ .num_entries = ARRAY_SIZE(_tgl_combo_phy_ddi_translations_dp_hbr2),
+};
+
+static const union intel_ddi_buf_trans_entry _tgl_uy_combo_phy_ddi_translations_dp_hbr2[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x36, 0x00, 0x09 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x60, 0x32, 0x00, 0x0D } }, /* 350 700 6.0 */
+ { .icl = { 0xC, 0x7F, 0x2D, 0x00, 0x12 } }, /* 350 900 8.2 */
+ { .icl = { 0xC, 0x47, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x6F, 0x36, 0x00, 0x09 } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7D, 0x32, 0x00, 0x0D } }, /* 500 900 5.1 */
+ { .icl = { 0x6, 0x60, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x34, 0x00, 0x0B } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
+
+static const struct intel_ddi_buf_trans tgl_uy_combo_phy_ddi_translations_dp_hbr2 = {
+ .entries = _tgl_uy_combo_phy_ddi_translations_dp_hbr2,
+ .num_entries = ARRAY_SIZE(_tgl_uy_combo_phy_ddi_translations_dp_hbr2),
};
/*
* Cloned the HOBL entry to comply with the voltage and pre-emphasis entries
* that DisplayPort specification requires
*/
-static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_edp_hbr2_hobl[] = {
- /* VS pre-emp */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 0 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 1 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 2 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 3 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 0 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 1 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 2 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 2 0 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 2 1 */
-};
-
-static const struct cnl_ddi_buf_trans rkl_combo_phy_ddi_translations_dp_hbr[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x2F, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x4F, 0x37, 0x00, 0x08 }, /* 350 500 3.1 */
- { 0xC, 0x63, 0x2F, 0x00, 0x10 }, /* 350 700 6.0 */
- { 0x6, 0x7D, 0x2A, 0x00, 0x15 }, /* 350 900 8.2 */
- { 0xA, 0x4C, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x73, 0x34, 0x00, 0x0B }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */
- { 0xC, 0x6E, 0x3E, 0x00, 0x01 }, /* 650 700 0.6 */
- { 0x6, 0x7F, 0x35, 0x00, 0x0A }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct cnl_ddi_buf_trans rkl_combo_phy_ddi_translations_dp_hbr2_hbr3[] = {
- /* NT mV Trans mV db */
- { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */
- { 0xA, 0x50, 0x38, 0x00, 0x07 }, /* 350 500 3.1 */
- { 0xC, 0x61, 0x33, 0x00, 0x0C }, /* 350 700 6.0 */
- { 0x6, 0x7F, 0x2E, 0x00, 0x11 }, /* 350 900 8.2 */
- { 0xA, 0x47, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */
- { 0xC, 0x5F, 0x38, 0x00, 0x07 }, /* 500 700 2.9 */
- { 0x6, 0x7F, 0x2F, 0x00, 0x10 }, /* 500 900 5.1 */
- { 0xC, 0x5F, 0x3F, 0x00, 0x00 }, /* 650 700 0.6 */
- { 0x6, 0x7E, 0x36, 0x00, 0x09 }, /* 600 900 3.5 */
- { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
-};
-
-static const struct tgl_dkl_phy_ddi_buf_trans adlp_dkl_phy_dp_ddi_trans_hbr[] = {
- /* VS pre-emp Non-trans mV Pre-emph dB */
- { 0x7, 0x0, 0x01 }, /* 0 0 400mV 0 dB */
- { 0x5, 0x0, 0x06 }, /* 0 1 400mV 3.5 dB */
- { 0x2, 0x0, 0x0B }, /* 0 2 400mV 6 dB */
- { 0x0, 0x0, 0x17 }, /* 0 3 400mV 9.5 dB */
- { 0x5, 0x0, 0x00 }, /* 1 0 600mV 0 dB */
- { 0x2, 0x0, 0x08 }, /* 1 1 600mV 3.5 dB */
- { 0x0, 0x0, 0x14 }, /* 1 2 600mV 6 dB */
- { 0x2, 0x0, 0x00 }, /* 2 0 800mV 0 dB */
- { 0x0, 0x0, 0x0B }, /* 2 1 800mV 3.5 dB */
- { 0x0, 0x0, 0x00 }, /* 3 0 1200mV 0 dB */
-};
-
-static const struct tgl_dkl_phy_ddi_buf_trans adlp_dkl_phy_dp_ddi_trans_hbr2_hbr3[] = {
- /* VS pre-emp Non-trans mV Pre-emph dB */
- { 0x7, 0x0, 0x00 }, /* 0 0 400mV 0 dB */
- { 0x5, 0x0, 0x04 }, /* 0 1 400mV 3.5 dB */
- { 0x2, 0x0, 0x0A }, /* 0 2 400mV 6 dB */
- { 0x0, 0x0, 0x18 }, /* 0 3 400mV 9.5 dB */
- { 0x5, 0x0, 0x00 }, /* 1 0 600mV 0 dB */
- { 0x2, 0x0, 0x06 }, /* 1 1 600mV 3.5 dB */
- { 0x0, 0x0, 0x14 }, /* 1 2 600mV 6 dB */
- { 0x2, 0x0, 0x00 }, /* 2 0 800mV 0 dB */
- { 0x0, 0x0, 0x09 }, /* 2 1 800mV 3.5 dB */
- { 0x0, 0x0, 0x00 }, /* 3 0 1200mV 0 dB */
-};
-
-bool is_hobl_buf_trans(const struct cnl_ddi_buf_trans *table)
-{
- return table == tgl_combo_phy_ddi_translations_edp_hbr2_hobl;
-}
+static const union intel_ddi_buf_trans_entry _tgl_combo_phy_ddi_translations_edp_hbr2_hobl[] = {
+ /* VS pre-emp */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 0 0 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 0 1 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 0 2 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 0 3 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 1 0 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 1 1 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 1 2 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 2 0 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 2 1 */
+};
-static const struct ddi_buf_trans *
-bdw_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+static const struct intel_ddi_buf_trans tgl_combo_phy_ddi_translations_edp_hbr2_hobl = {
+ .entries = _tgl_combo_phy_ddi_translations_edp_hbr2_hobl,
+ .num_entries = ARRAY_SIZE(_tgl_combo_phy_ddi_translations_edp_hbr2_hobl),
+};
- if (dev_priv->vbt.edp.low_vswing) {
- *n_entries = ARRAY_SIZE(bdw_ddi_translations_edp);
- return bdw_ddi_translations_edp;
- } else {
- *n_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
- return bdw_ddi_translations_dp;
- }
-}
+static const union intel_ddi_buf_trans_entry _rkl_combo_phy_ddi_translations_dp_hbr[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x2F, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x63, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7D, 0x2A, 0x00, 0x15 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x6E, 0x3E, 0x00, 0x01 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
-static const struct ddi_buf_trans *
-skl_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+static const struct intel_ddi_buf_trans rkl_combo_phy_ddi_translations_dp_hbr = {
+ .entries = _rkl_combo_phy_ddi_translations_dp_hbr,
+ .num_entries = ARRAY_SIZE(_rkl_combo_phy_ddi_translations_dp_hbr),
+};
- if (IS_SKL_ULX(dev_priv)) {
- *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
- return skl_y_ddi_translations_dp;
- } else if (IS_SKL_ULT(dev_priv)) {
- *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp);
- return skl_u_ddi_translations_dp;
- } else {
- *n_entries = ARRAY_SIZE(skl_ddi_translations_dp);
- return skl_ddi_translations_dp;
- }
-}
+static const union intel_ddi_buf_trans_entry _rkl_combo_phy_ddi_translations_dp_hbr2_hbr3[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x50, 0x38, 0x00, 0x07 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x61, 0x33, 0x00, 0x0C } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2E, 0x00, 0x11 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x47, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x5F, 0x38, 0x00, 0x07 } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x5F, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7E, 0x36, 0x00, 0x09 } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
-static const struct ddi_buf_trans *
-kbl_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+static const struct intel_ddi_buf_trans rkl_combo_phy_ddi_translations_dp_hbr2_hbr3 = {
+ .entries = _rkl_combo_phy_ddi_translations_dp_hbr2_hbr3,
+ .num_entries = ARRAY_SIZE(_rkl_combo_phy_ddi_translations_dp_hbr2_hbr3),
+};
- if (IS_KBL_ULX(dev_priv) ||
- IS_CFL_ULX(dev_priv) ||
- IS_CML_ULX(dev_priv)) {
- *n_entries = ARRAY_SIZE(kbl_y_ddi_translations_dp);
- return kbl_y_ddi_translations_dp;
- } else if (IS_KBL_ULT(dev_priv) ||
- IS_CFL_ULT(dev_priv) ||
- IS_CML_ULT(dev_priv)) {
- *n_entries = ARRAY_SIZE(kbl_u_ddi_translations_dp);
- return kbl_u_ddi_translations_dp;
- } else {
- *n_entries = ARRAY_SIZE(kbl_ddi_translations_dp);
- return kbl_ddi_translations_dp;
- }
-}
+static const union intel_ddi_buf_trans_entry _adls_combo_phy_ddi_translations_dp_hbr2_hbr3[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x63, 0x31, 0x00, 0x0E } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2C, 0x00, 0x13 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x47, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x63, 0x37, 0x00, 0x08 } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x73, 0x32, 0x00, 0x0D } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x58, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
-static const struct ddi_buf_trans *
-skl_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+static const struct intel_ddi_buf_trans adls_combo_phy_ddi_translations_dp_hbr2_hbr3 = {
+ .entries = _adls_combo_phy_ddi_translations_dp_hbr2_hbr3,
+ .num_entries = ARRAY_SIZE(_adls_combo_phy_ddi_translations_dp_hbr2_hbr3),
+};
- if (dev_priv->vbt.edp.low_vswing) {
- if (IS_SKL_ULX(dev_priv) ||
- IS_KBL_ULX(dev_priv) ||
- IS_CFL_ULX(dev_priv) ||
- IS_CML_ULX(dev_priv)) {
- *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp);
- return skl_y_ddi_translations_edp;
- } else if (IS_SKL_ULT(dev_priv) ||
- IS_KBL_ULT(dev_priv) ||
- IS_CFL_ULT(dev_priv) ||
- IS_CML_ULT(dev_priv)) {
- *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp);
- return skl_u_ddi_translations_edp;
- } else {
- *n_entries = ARRAY_SIZE(skl_ddi_translations_edp);
- return skl_ddi_translations_edp;
- }
- }
+static const union intel_ddi_buf_trans_entry _adls_combo_phy_ddi_translations_edp_hbr2[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0x9, 0x73, 0x3D, 0x00, 0x02 } }, /* 200 200 0.0 */
+ { .icl = { 0x9, 0x7A, 0x3C, 0x00, 0x03 } }, /* 200 250 1.9 */
+ { .icl = { 0x9, 0x7F, 0x3B, 0x00, 0x04 } }, /* 200 300 3.5 */
+ { .icl = { 0x4, 0x6C, 0x33, 0x00, 0x0C } }, /* 200 350 4.9 */
+ { .icl = { 0x2, 0x73, 0x3A, 0x00, 0x05 } }, /* 250 250 0.0 */
+ { .icl = { 0x2, 0x7C, 0x38, 0x00, 0x07 } }, /* 250 300 1.6 */
+ { .icl = { 0x4, 0x5A, 0x36, 0x00, 0x09 } }, /* 250 350 2.9 */
+ { .icl = { 0x4, 0x57, 0x3D, 0x00, 0x02 } }, /* 300 300 0.0 */
+ { .icl = { 0x4, 0x65, 0x38, 0x00, 0x07 } }, /* 300 350 1.3 */
+ { .icl = { 0x4, 0x6C, 0x3A, 0x00, 0x05 } }, /* 350 350 0.0 */
+};
- if (IS_KABYLAKE(dev_priv) ||
- IS_COFFEELAKE(dev_priv) ||
- IS_COMETLAKE(dev_priv))
- return kbl_get_buf_trans_dp(encoder, n_entries);
- else
- return skl_get_buf_trans_dp(encoder, n_entries);
-}
+static const struct intel_ddi_buf_trans adls_combo_phy_ddi_translations_edp_hbr2 = {
+ .entries = _adls_combo_phy_ddi_translations_edp_hbr2,
+ .num_entries = ARRAY_SIZE(_adls_combo_phy_ddi_translations_edp_hbr2),
+};
-static const struct ddi_buf_trans *
-skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries)
-{
- if (IS_SKL_ULX(dev_priv) ||
- IS_KBL_ULX(dev_priv) ||
- IS_CFL_ULX(dev_priv) ||
- IS_CML_ULX(dev_priv)) {
- *n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi);
- return skl_y_ddi_translations_hdmi;
- } else {
- *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi);
- return skl_ddi_translations_hdmi;
- }
-}
+static const union intel_ddi_buf_trans_entry _adls_combo_phy_ddi_translations_edp_hbr3[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x63, 0x31, 0x00, 0x0E } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2C, 0x00, 0x13 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x47, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x63, 0x37, 0x00, 0x08 } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x73, 0x32, 0x00, 0x0D } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x58, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
-static int skl_buf_trans_num_entries(enum port port, int n_entries)
-{
- /* Only DDIA and DDIE can select the 10th register with DP */
- if (port == PORT_A || port == PORT_E)
- return min(n_entries, 10);
- else
- return min(n_entries, 9);
-}
+static const struct intel_ddi_buf_trans adls_combo_phy_ddi_translations_edp_hbr3 = {
+ .entries = _adls_combo_phy_ddi_translations_edp_hbr3,
+ .num_entries = ARRAY_SIZE(_adls_combo_phy_ddi_translations_edp_hbr3),
+};
-const struct ddi_buf_trans *
-intel_ddi_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+static const union intel_ddi_buf_trans_entry _adlp_combo_phy_ddi_translations_hdmi[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0x6, 0x60, 0x3F, 0x00, 0x00 } }, /* 400 400 0.0 */
+ { .icl = { 0x6, 0x68, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xA, 0x73, 0x3F, 0x00, 0x00 } }, /* 650 650 0.0 ALS */
+ { .icl = { 0xA, 0x78, 0x3F, 0x00, 0x00 } }, /* 800 800 0.0 */
+ { .icl = { 0xB, 0x7F, 0x3F, 0x00, 0x00 } }, /* 1000 1000 0.0 Re-timer */
+ { .icl = { 0xB, 0x7F, 0x3B, 0x00, 0x04 } }, /* Full Red -1.5 */
+ { .icl = { 0xB, 0x7F, 0x39, 0x00, 0x06 } }, /* Full Red -1.8 */
+ { .icl = { 0xB, 0x7F, 0x37, 0x00, 0x08 } }, /* Full Red -2.0 CRLS */
+ { .icl = { 0xB, 0x7F, 0x35, 0x00, 0x0A } }, /* Full Red -2.5 */
+ { .icl = { 0xB, 0x7F, 0x33, 0x00, 0x0C } }, /* Full Red -3.0 */
+};
- if (IS_KABYLAKE(dev_priv) ||
- IS_COFFEELAKE(dev_priv) ||
- IS_COMETLAKE(dev_priv)) {
- const struct ddi_buf_trans *ddi_translations =
- kbl_get_buf_trans_dp(encoder, n_entries);
- *n_entries = skl_buf_trans_num_entries(encoder->port, *n_entries);
- return ddi_translations;
- } else if (IS_SKYLAKE(dev_priv)) {
- const struct ddi_buf_trans *ddi_translations =
- skl_get_buf_trans_dp(encoder, n_entries);
- *n_entries = skl_buf_trans_num_entries(encoder->port, *n_entries);
- return ddi_translations;
- } else if (IS_BROADWELL(dev_priv)) {
- *n_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
- return bdw_ddi_translations_dp;
- } else if (IS_HASWELL(dev_priv)) {
- *n_entries = ARRAY_SIZE(hsw_ddi_translations_dp);
- return hsw_ddi_translations_dp;
- }
+static const struct intel_ddi_buf_trans adlp_combo_phy_ddi_translations_hdmi = {
+ .entries = _adlp_combo_phy_ddi_translations_hdmi,
+ .num_entries = ARRAY_SIZE(_adlp_combo_phy_ddi_translations_hdmi),
+ .hdmi_default_entry = ARRAY_SIZE(_adlp_combo_phy_ddi_translations_hdmi) - 1,
+};
- *n_entries = 0;
- return NULL;
-}
+static const union intel_ddi_buf_trans_entry _adlp_combo_phy_ddi_translations_dp_hbr[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x71, 0x31, 0x00, 0x0E } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2C, 0x00, 0x13 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x73, 0x3E, 0x00, 0x01 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
-const struct ddi_buf_trans *
-intel_ddi_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+static const struct intel_ddi_buf_trans adlp_combo_phy_ddi_translations_dp_hbr = {
+ .entries = _adlp_combo_phy_ddi_translations_dp_hbr,
+ .num_entries = ARRAY_SIZE(_adlp_combo_phy_ddi_translations_dp_hbr),
+};
- if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
- const struct ddi_buf_trans *ddi_translations =
- skl_get_buf_trans_edp(encoder, n_entries);
- *n_entries = skl_buf_trans_num_entries(encoder->port, *n_entries);
- return ddi_translations;
- } else if (IS_BROADWELL(dev_priv)) {
- return bdw_get_buf_trans_edp(encoder, n_entries);
- } else if (IS_HASWELL(dev_priv)) {
- *n_entries = ARRAY_SIZE(hsw_ddi_translations_dp);
- return hsw_ddi_translations_dp;
- }
+static const union intel_ddi_buf_trans_entry _adlp_combo_phy_ddi_translations_dp_hbr2_hbr3[] = {
+ /* NT mV Trans mV db */
+ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */
+ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */
+ { .icl = { 0xC, 0x71, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */
+ { .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */
+ { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */
+ { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */
+ { .icl = { 0x6, 0x7F, 0x30, 0x00, 0x0F } }, /* 500 900 5.1 */
+ { .icl = { 0xC, 0x63, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */
+ { .icl = { 0x6, 0x7F, 0x38, 0x00, 0x07 } }, /* 600 900 3.5 */
+ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */
+};
- *n_entries = 0;
- return NULL;
-}
+static const struct intel_ddi_buf_trans adlp_combo_phy_ddi_translations_dp_hbr2_hbr3 = {
+ .entries = _adlp_combo_phy_ddi_translations_dp_hbr2_hbr3,
+ .num_entries = ARRAY_SIZE(_adlp_combo_phy_ddi_translations_dp_hbr2_hbr3),
+};
-const struct ddi_buf_trans *
-intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv,
- int *n_entries)
-{
- if (IS_BROADWELL(dev_priv)) {
- *n_entries = ARRAY_SIZE(bdw_ddi_translations_fdi);
- return bdw_ddi_translations_fdi;
- } else if (IS_HASWELL(dev_priv)) {
- *n_entries = ARRAY_SIZE(hsw_ddi_translations_fdi);
- return hsw_ddi_translations_fdi;
- }
+static const struct intel_ddi_buf_trans adlp_combo_phy_ddi_translations_edp_hbr3 = {
+ .entries = _icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3,
+ .num_entries = ARRAY_SIZE(_icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3),
+};
+
+static const struct intel_ddi_buf_trans adlp_combo_phy_ddi_translations_edp_up_to_hbr2 = {
+ .entries = _icl_combo_phy_ddi_translations_edp_hbr2,
+ .num_entries = ARRAY_SIZE(_icl_combo_phy_ddi_translations_edp_hbr2),
+};
- *n_entries = 0;
- return NULL;
+static const union intel_ddi_buf_trans_entry _adlp_dkl_phy_ddi_translations_dp_hbr[] = {
+ /* VS pre-emp Non-trans mV Pre-emph dB */
+ { .dkl = { 0x7, 0x0, 0x01 } }, /* 0 0 400mV 0 dB */
+ { .dkl = { 0x5, 0x0, 0x06 } }, /* 0 1 400mV 3.5 dB */
+ { .dkl = { 0x2, 0x0, 0x0B } }, /* 0 2 400mV 6 dB */
+ { .dkl = { 0x0, 0x0, 0x17 } }, /* 0 3 400mV 9.5 dB */
+ { .dkl = { 0x5, 0x0, 0x00 } }, /* 1 0 600mV 0 dB */
+ { .dkl = { 0x2, 0x0, 0x08 } }, /* 1 1 600mV 3.5 dB */
+ { .dkl = { 0x0, 0x0, 0x14 } }, /* 1 2 600mV 6 dB */
+ { .dkl = { 0x2, 0x0, 0x00 } }, /* 2 0 800mV 0 dB */
+ { .dkl = { 0x0, 0x0, 0x0B } }, /* 2 1 800mV 3.5 dB */
+ { .dkl = { 0x0, 0x0, 0x00 } }, /* 3 0 1200mV 0 dB */
+};
+
+static const struct intel_ddi_buf_trans adlp_dkl_phy_ddi_translations_dp_hbr = {
+ .entries = _adlp_dkl_phy_ddi_translations_dp_hbr,
+ .num_entries = ARRAY_SIZE(_adlp_dkl_phy_ddi_translations_dp_hbr),
+};
+
+static const union intel_ddi_buf_trans_entry _adlp_dkl_phy_ddi_translations_dp_hbr2_hbr3[] = {
+ /* VS pre-emp Non-trans mV Pre-emph dB */
+ { .dkl = { 0x7, 0x0, 0x00 } }, /* 0 0 400mV 0 dB */
+ { .dkl = { 0x5, 0x0, 0x04 } }, /* 0 1 400mV 3.5 dB */
+ { .dkl = { 0x2, 0x0, 0x0A } }, /* 0 2 400mV 6 dB */
+ { .dkl = { 0x0, 0x0, 0x18 } }, /* 0 3 400mV 9.5 dB */
+ { .dkl = { 0x5, 0x0, 0x00 } }, /* 1 0 600mV 0 dB */
+ { .dkl = { 0x2, 0x0, 0x06 } }, /* 1 1 600mV 3.5 dB */
+ { .dkl = { 0x0, 0x0, 0x14 } }, /* 1 2 600mV 6 dB */
+ { .dkl = { 0x2, 0x0, 0x00 } }, /* 2 0 800mV 0 dB */
+ { .dkl = { 0x0, 0x0, 0x09 } }, /* 2 1 800mV 3.5 dB */
+ { .dkl = { 0x0, 0x0, 0x00 } }, /* 3 0 1200mV 0 dB */
+};
+
+static const struct intel_ddi_buf_trans adlp_dkl_phy_ddi_translations_dp_hbr2_hbr3 = {
+ .entries = _adlp_dkl_phy_ddi_translations_dp_hbr2_hbr3,
+ .num_entries = ARRAY_SIZE(_adlp_dkl_phy_ddi_translations_dp_hbr2_hbr3),
+};
+
+bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table)
+{
+ return table == &tgl_combo_phy_ddi_translations_edp_hbr2_hobl;
}
-const struct ddi_buf_trans *
-intel_ddi_get_buf_trans_hdmi(struct intel_encoder *encoder,
- int *n_entries)
+static const struct intel_ddi_buf_trans *
+intel_get_buf_trans(const struct intel_ddi_buf_trans *ddi_translations, int *num_entries)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ *num_entries = ddi_translations->num_entries;
+ return ddi_translations;
+}
- if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
- return skl_get_buf_trans_hdmi(dev_priv, n_entries);
- } else if (IS_BROADWELL(dev_priv)) {
- *n_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
- return bdw_ddi_translations_hdmi;
- } else if (IS_HASWELL(dev_priv)) {
- *n_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi);
- return hsw_ddi_translations_hdmi;
- }
+static const struct intel_ddi_buf_trans *
+hsw_get_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG))
+ return intel_get_buf_trans(&hsw_ddi_translations_fdi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&hsw_ddi_translations_hdmi, n_entries);
+ else
+ return intel_get_buf_trans(&hsw_ddi_translations_dp, n_entries);
+}
- *n_entries = 0;
- return NULL;
+static const struct intel_ddi_buf_trans *
+bdw_get_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG))
+ return intel_get_buf_trans(&bdw_ddi_translations_fdi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&bdw_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ i915->vbt.edp.low_vswing)
+ return intel_get_buf_trans(&bdw_ddi_translations_edp, n_entries);
+ else
+ return intel_get_buf_trans(&bdw_ddi_translations_dp, n_entries);
}
-static const struct bxt_ddi_buf_trans *
-bxt_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries)
+static int skl_buf_trans_num_entries(enum port port, int n_entries)
{
- *n_entries = ARRAY_SIZE(bxt_ddi_translations_dp);
- return bxt_ddi_translations_dp;
+ /* Only DDIA and DDIE can select the 10th register with DP */
+ if (port == PORT_A || port == PORT_E)
+ return min(n_entries, 10);
+ else
+ return min(n_entries, 9);
}
-static const struct bxt_ddi_buf_trans *
-bxt_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries)
+static const struct intel_ddi_buf_trans *
+_skl_get_buf_trans_dp(struct intel_encoder *encoder,
+ const struct intel_ddi_buf_trans *ddi_translations,
+ int *n_entries)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ ddi_translations = intel_get_buf_trans(ddi_translations, n_entries);
+ *n_entries = skl_buf_trans_num_entries(encoder->port, *n_entries);
+ return ddi_translations;
+}
- if (dev_priv->vbt.edp.low_vswing) {
- *n_entries = ARRAY_SIZE(bxt_ddi_translations_edp);
- return bxt_ddi_translations_edp;
- }
+static const struct intel_ddi_buf_trans *
+skl_y_get_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- return bxt_get_buf_trans_dp(encoder, n_entries);
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&skl_y_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ i915->vbt.edp.low_vswing)
+ return _skl_get_buf_trans_dp(encoder, &skl_y_ddi_translations_edp, n_entries);
+ else
+ return _skl_get_buf_trans_dp(encoder, &skl_y_ddi_translations_dp, n_entries);
}
-static const struct bxt_ddi_buf_trans *
-bxt_get_buf_trans_hdmi(struct intel_encoder *encoder, int *n_entries)
+static const struct intel_ddi_buf_trans *
+skl_u_get_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
{
- *n_entries = ARRAY_SIZE(bxt_ddi_translations_hdmi);
- return bxt_ddi_translations_hdmi;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&skl_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ i915->vbt.edp.low_vswing)
+ return _skl_get_buf_trans_dp(encoder, &skl_u_ddi_translations_edp, n_entries);
+ else
+ return _skl_get_buf_trans_dp(encoder, &skl_u_ddi_translations_dp, n_entries);
}
-const struct bxt_ddi_buf_trans *
-bxt_get_buf_trans(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+skl_get_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return bxt_get_buf_trans_hdmi(encoder, n_entries);
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- return bxt_get_buf_trans_edp(encoder, n_entries);
- return bxt_get_buf_trans_dp(encoder, n_entries);
+ return intel_get_buf_trans(&skl_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ i915->vbt.edp.low_vswing)
+ return _skl_get_buf_trans_dp(encoder, &skl_ddi_translations_edp, n_entries);
+ else
+ return _skl_get_buf_trans_dp(encoder, &skl_ddi_translations_dp, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-cnl_get_buf_trans_hdmi(struct intel_encoder *encoder, int *n_entries)
+static const struct intel_ddi_buf_trans *
+kbl_y_get_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- u32 voltage = intel_de_read(dev_priv, CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK;
-
- if (voltage == VOLTAGE_INFO_0_85V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_0_85V);
- return cnl_ddi_translations_hdmi_0_85V;
- } else if (voltage == VOLTAGE_INFO_0_95V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_0_95V);
- return cnl_ddi_translations_hdmi_0_95V;
- } else if (voltage == VOLTAGE_INFO_1_05V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_1_05V);
- return cnl_ddi_translations_hdmi_1_05V;
- } else {
- *n_entries = 1; /* shut up gcc */
- MISSING_CASE(voltage);
- }
- return NULL;
-}
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
-static const struct cnl_ddi_buf_trans *
-cnl_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries)
-{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- u32 voltage = intel_de_read(dev_priv, CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK;
-
- if (voltage == VOLTAGE_INFO_0_85V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_0_85V);
- return cnl_ddi_translations_dp_0_85V;
- } else if (voltage == VOLTAGE_INFO_0_95V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_0_95V);
- return cnl_ddi_translations_dp_0_95V;
- } else if (voltage == VOLTAGE_INFO_1_05V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_1_05V);
- return cnl_ddi_translations_dp_1_05V;
- } else {
- *n_entries = 1; /* shut up gcc */
- MISSING_CASE(voltage);
- }
- return NULL;
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&skl_y_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ i915->vbt.edp.low_vswing)
+ return _skl_get_buf_trans_dp(encoder, &skl_y_ddi_translations_edp, n_entries);
+ else
+ return _skl_get_buf_trans_dp(encoder, &kbl_y_ddi_translations_dp, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-cnl_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries)
+static const struct intel_ddi_buf_trans *
+kbl_u_get_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- u32 voltage = intel_de_read(dev_priv, CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK;
-
- if (dev_priv->vbt.edp.low_vswing) {
- if (voltage == VOLTAGE_INFO_0_85V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_0_85V);
- return cnl_ddi_translations_edp_0_85V;
- } else if (voltage == VOLTAGE_INFO_0_95V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_0_95V);
- return cnl_ddi_translations_edp_0_95V;
- } else if (voltage == VOLTAGE_INFO_1_05V) {
- *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_1_05V);
- return cnl_ddi_translations_edp_1_05V;
- } else {
- *n_entries = 1; /* shut up gcc */
- MISSING_CASE(voltage);
- }
- return NULL;
- } else {
- return cnl_get_buf_trans_dp(encoder, n_entries);
- }
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&skl_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ i915->vbt.edp.low_vswing)
+ return _skl_get_buf_trans_dp(encoder, &skl_u_ddi_translations_edp, n_entries);
+ else
+ return _skl_get_buf_trans_dp(encoder, &kbl_u_ddi_translations_dp, n_entries);
}
-const struct cnl_ddi_buf_trans *
-cnl_get_buf_trans(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+kbl_get_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return cnl_get_buf_trans_hdmi(encoder, n_entries);
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- return cnl_get_buf_trans_edp(encoder, n_entries);
- return cnl_get_buf_trans_dp(encoder, n_entries);
+ return intel_get_buf_trans(&skl_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ i915->vbt.edp.low_vswing)
+ return _skl_get_buf_trans_dp(encoder, &skl_ddi_translations_edp, n_entries);
+ else
+ return _skl_get_buf_trans_dp(encoder, &kbl_ddi_translations_dp, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-icl_get_combo_buf_trans_hdmi(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries)
+static const struct intel_ddi_buf_trans *
+bxt_get_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
{
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
- return icl_combo_phy_ddi_translations_hdmi;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&bxt_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ i915->vbt.edp.low_vswing)
+ return intel_get_buf_trans(&bxt_ddi_translations_edp, n_entries);
+ else
+ return intel_get_buf_trans(&bxt_ddi_translations_dp, n_entries);
}
-static const struct cnl_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
icl_get_combo_buf_trans_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2);
- return icl_combo_phy_ddi_translations_dp_hbr2;
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3,
+ n_entries);
}
-static const struct cnl_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
icl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
@@ -1109,294 +1174,391 @@ icl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
if (crtc_state->port_clock > 540000) {
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3);
- return icl_combo_phy_ddi_translations_edp_hbr3;
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3,
+ n_entries);
} else if (dev_priv->vbt.edp.low_vswing) {
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2);
- return icl_combo_phy_ddi_translations_edp_hbr2;
- } else if (IS_DG1(dev_priv) && crtc_state->port_clock > 270000) {
- *n_entries = ARRAY_SIZE(dg1_combo_phy_ddi_translations_dp_hbr2_hbr3);
- return dg1_combo_phy_ddi_translations_dp_hbr2_hbr3;
- } else if (IS_DG1(dev_priv)) {
- *n_entries = ARRAY_SIZE(dg1_combo_phy_ddi_translations_dp_rbr_hbr);
- return dg1_combo_phy_ddi_translations_dp_rbr_hbr;
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_edp_hbr2,
+ n_entries);
}
return icl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-const struct cnl_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
icl_get_combo_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return icl_get_combo_buf_trans_hdmi(encoder, crtc_state, n_entries);
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_hdmi, n_entries);
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
return icl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
else
return icl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-static const struct icl_mg_phy_ddi_buf_trans *
-icl_get_mg_buf_trans_hdmi(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries)
-{
- *n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations_hdmi);
- return icl_mg_phy_ddi_translations_hdmi;
-}
-
-static const struct icl_mg_phy_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
icl_get_mg_buf_trans_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (crtc_state->port_clock > 270000) {
- *n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations_hbr2_hbr3);
- return icl_mg_phy_ddi_translations_hbr2_hbr3;
+ return intel_get_buf_trans(&icl_mg_phy_ddi_translations_hbr2_hbr3,
+ n_entries);
} else {
- *n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations_rbr_hbr);
- return icl_mg_phy_ddi_translations_rbr_hbr;
+ return intel_get_buf_trans(&icl_mg_phy_ddi_translations_rbr_hbr,
+ n_entries);
}
}
-const struct icl_mg_phy_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
icl_get_mg_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return icl_get_mg_buf_trans_hdmi(encoder, crtc_state, n_entries);
+ return intel_get_buf_trans(&icl_mg_phy_ddi_translations_hdmi, n_entries);
else
return icl_get_mg_buf_trans_dp(encoder, crtc_state, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-ehl_get_combo_buf_trans_hdmi(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries)
+static const struct intel_ddi_buf_trans *
+ehl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ if (crtc_state->port_clock > 270000)
+ return intel_get_buf_trans(&ehl_combo_phy_ddi_translations_edp_hbr2, n_entries);
+ else
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_edp_hbr2, n_entries);
+}
+
+static const struct intel_ddi_buf_trans *
+ehl_get_combo_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ dev_priv->vbt.edp.low_vswing)
+ return ehl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
+ else
+ return intel_get_buf_trans(&ehl_combo_phy_ddi_translations_dp, n_entries);
+}
+
+static const struct intel_ddi_buf_trans *
+jsl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
{
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
- return icl_combo_phy_ddi_translations_hdmi;
+ if (crtc_state->port_clock > 270000)
+ return intel_get_buf_trans(&jsl_combo_phy_ddi_translations_edp_hbr2, n_entries);
+ else
+ return intel_get_buf_trans(&jsl_combo_phy_ddi_translations_edp_hbr, n_entries);
+}
+
+static const struct intel_ddi_buf_trans *
+jsl_get_combo_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ dev_priv->vbt.edp.low_vswing)
+ return jsl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
+ else
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-ehl_get_combo_buf_trans_dp(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+tgl_get_combo_buf_trans_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
- *n_entries = ARRAY_SIZE(ehl_combo_phy_ddi_translations_dp);
- return ehl_combo_phy_ddi_translations_dp;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+
+ if (crtc_state->port_clock > 270000) {
+ if (IS_TGL_U(dev_priv) || IS_TGL_Y(dev_priv)) {
+ return intel_get_buf_trans(&tgl_uy_combo_phy_ddi_translations_dp_hbr2,
+ n_entries);
+ } else {
+ return intel_get_buf_trans(&tgl_combo_phy_ddi_translations_dp_hbr2,
+ n_entries);
+ }
+ } else {
+ return intel_get_buf_trans(&tgl_combo_phy_ddi_translations_dp_hbr,
+ n_entries);
+ }
}
-static const struct cnl_ddi_buf_trans *
-ehl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+tgl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- if (dev_priv->vbt.edp.low_vswing) {
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2);
- return icl_combo_phy_ddi_translations_edp_hbr2;
+ if (crtc_state->port_clock > 540000) {
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3,
+ n_entries);
+ } else if (dev_priv->vbt.edp.hobl && !intel_dp->hobl_failed) {
+ return intel_get_buf_trans(&tgl_combo_phy_ddi_translations_edp_hbr2_hobl,
+ n_entries);
+ } else if (dev_priv->vbt.edp.low_vswing) {
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_edp_hbr2,
+ n_entries);
}
- return ehl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
+ return tgl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-const struct cnl_ddi_buf_trans *
-ehl_get_combo_buf_trans(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+tgl_get_combo_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return ehl_get_combo_buf_trans_hdmi(encoder, crtc_state, n_entries);
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_hdmi, n_entries);
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- return ehl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
+ return tgl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
else
- return ehl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
+ return tgl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-jsl_get_combo_buf_trans_hdmi(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries)
+static const struct intel_ddi_buf_trans *
+dg1_get_combo_buf_trans_dp(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
{
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
- return icl_combo_phy_ddi_translations_hdmi;
+ if (crtc_state->port_clock > 270000)
+ return intel_get_buf_trans(&dg1_combo_phy_ddi_translations_dp_hbr2_hbr3,
+ n_entries);
+ else
+ return intel_get_buf_trans(&dg1_combo_phy_ddi_translations_dp_rbr_hbr,
+ n_entries);
}
-static const struct cnl_ddi_buf_trans *
-jsl_get_combo_buf_trans_dp(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+dg1_get_combo_buf_trans_edp(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ if (crtc_state->port_clock > 540000)
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3,
+ n_entries);
+ else if (dev_priv->vbt.edp.hobl && !intel_dp->hobl_failed)
+ return intel_get_buf_trans(&tgl_combo_phy_ddi_translations_edp_hbr2_hobl,
+ n_entries);
+ else if (dev_priv->vbt.edp.low_vswing)
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_edp_hbr2,
+ n_entries);
+ else
+ return dg1_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
+}
+
+static const struct intel_ddi_buf_trans *
+dg1_get_combo_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
+ return dg1_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
+ else
+ return dg1_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
+}
+
+static const struct intel_ddi_buf_trans *
+rkl_get_combo_buf_trans_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2);
- return icl_combo_phy_ddi_translations_dp_hbr2;
+ if (crtc_state->port_clock > 270000)
+ return intel_get_buf_trans(&rkl_combo_phy_ddi_translations_dp_hbr2_hbr3, n_entries);
+ else
+ return intel_get_buf_trans(&rkl_combo_phy_ddi_translations_dp_hbr, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-jsl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+rkl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- if (dev_priv->vbt.edp.low_vswing) {
- if (crtc_state->port_clock > 270000) {
- *n_entries = ARRAY_SIZE(jsl_combo_phy_ddi_translations_edp_hbr2);
- return jsl_combo_phy_ddi_translations_edp_hbr2;
- } else {
- *n_entries = ARRAY_SIZE(jsl_combo_phy_ddi_translations_edp_hbr);
- return jsl_combo_phy_ddi_translations_edp_hbr;
- }
+ if (crtc_state->port_clock > 540000) {
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_dp_hbr2_edp_hbr3,
+ n_entries);
+ } else if (dev_priv->vbt.edp.hobl && !intel_dp->hobl_failed) {
+ return intel_get_buf_trans(&tgl_combo_phy_ddi_translations_edp_hbr2_hobl,
+ n_entries);
+ } else if (dev_priv->vbt.edp.low_vswing) {
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_edp_hbr2,
+ n_entries);
}
- return jsl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
+ return rkl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-const struct cnl_ddi_buf_trans *
-jsl_get_combo_buf_trans(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+rkl_get_combo_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return jsl_get_combo_buf_trans_hdmi(encoder, crtc_state, n_entries);
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_hdmi, n_entries);
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- return jsl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
+ return rkl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
else
- return jsl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
+ return rkl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-tgl_get_combo_buf_trans_hdmi(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+adls_get_combo_buf_trans_dp(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ if (crtc_state->port_clock > 270000)
+ return intel_get_buf_trans(&adls_combo_phy_ddi_translations_dp_hbr2_hbr3, n_entries);
+ else
+ return intel_get_buf_trans(&tgl_combo_phy_ddi_translations_dp_hbr, n_entries);
+}
+
+static const struct intel_ddi_buf_trans *
+adls_get_combo_buf_trans_edp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
- return icl_combo_phy_ddi_translations_hdmi;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ if (crtc_state->port_clock > 540000)
+ return intel_get_buf_trans(&adls_combo_phy_ddi_translations_edp_hbr3, n_entries);
+ else if (i915->vbt.edp.hobl && !intel_dp->hobl_failed)
+ return intel_get_buf_trans(&tgl_combo_phy_ddi_translations_edp_hbr2_hobl, n_entries);
+ else if (i915->vbt.edp.low_vswing)
+ return intel_get_buf_trans(&adls_combo_phy_ddi_translations_edp_hbr2, n_entries);
+ else
+ return adls_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-tgl_get_combo_buf_trans_dp(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries)
+static const struct intel_ddi_buf_trans *
+adls_get_combo_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-
- if (crtc_state->port_clock > 270000) {
- if (IS_ROCKETLAKE(dev_priv)) {
- *n_entries = ARRAY_SIZE(rkl_combo_phy_ddi_translations_dp_hbr2_hbr3);
- return rkl_combo_phy_ddi_translations_dp_hbr2_hbr3;
- } else if (IS_TGL_U(dev_priv) || IS_TGL_Y(dev_priv)) {
- *n_entries = ARRAY_SIZE(tgl_uy_combo_phy_ddi_translations_dp_hbr2);
- return tgl_uy_combo_phy_ddi_translations_dp_hbr2;
- } else {
- *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr2);
- return tgl_combo_phy_ddi_translations_dp_hbr2;
- }
- } else {
- if (IS_ROCKETLAKE(dev_priv)) {
- *n_entries = ARRAY_SIZE(rkl_combo_phy_ddi_translations_dp_hbr);
- return rkl_combo_phy_ddi_translations_dp_hbr;
- } else {
- *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr);
- return tgl_combo_phy_ddi_translations_dp_hbr;
- }
- }
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return intel_get_buf_trans(&icl_combo_phy_ddi_translations_hdmi, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
+ return adls_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
+ else
+ return adls_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-static const struct cnl_ddi_buf_trans *
-tgl_get_combo_buf_trans_edp(struct intel_encoder *encoder,
+static const struct intel_ddi_buf_trans *
+adlp_get_combo_buf_trans_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
+ if (crtc_state->port_clock > 270000)
+ return intel_get_buf_trans(&adlp_combo_phy_ddi_translations_dp_hbr2_hbr3, n_entries);
+ else
+ return intel_get_buf_trans(&adlp_combo_phy_ddi_translations_dp_hbr, n_entries);
+}
+
+static const struct intel_ddi_buf_trans *
+adlp_get_combo_buf_trans_edp(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
if (crtc_state->port_clock > 540000) {
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3);
- return icl_combo_phy_ddi_translations_edp_hbr3;
+ return intel_get_buf_trans(&adlp_combo_phy_ddi_translations_edp_hbr3,
+ n_entries);
} else if (dev_priv->vbt.edp.hobl && !intel_dp->hobl_failed) {
- *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_edp_hbr2_hobl);
- return tgl_combo_phy_ddi_translations_edp_hbr2_hobl;
+ return intel_get_buf_trans(&tgl_combo_phy_ddi_translations_edp_hbr2_hobl,
+ n_entries);
} else if (dev_priv->vbt.edp.low_vswing) {
- *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2);
- return icl_combo_phy_ddi_translations_edp_hbr2;
+ return intel_get_buf_trans(&adlp_combo_phy_ddi_translations_edp_up_to_hbr2,
+ n_entries);
}
- return tgl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
+ return adlp_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-const struct cnl_ddi_buf_trans *
-tgl_get_combo_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries)
+static const struct intel_ddi_buf_trans *
+adlp_get_combo_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
{
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return tgl_get_combo_buf_trans_hdmi(encoder, crtc_state, n_entries);
+ return intel_get_buf_trans(&adlp_combo_phy_ddi_translations_hdmi, n_entries);
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- return tgl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
+ return adlp_get_combo_buf_trans_edp(encoder, crtc_state, n_entries);
else
- return tgl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
+ return adlp_get_combo_buf_trans_dp(encoder, crtc_state, n_entries);
}
-static const struct tgl_dkl_phy_ddi_buf_trans *
-tgl_get_dkl_buf_trans_hdmi(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries)
-{
- *n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans);
- return tgl_dkl_phy_hdmi_ddi_trans;
-}
-
-static const struct tgl_dkl_phy_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
tgl_get_dkl_buf_trans_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (crtc_state->port_clock > 270000) {
- *n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans_hbr2);
- return tgl_dkl_phy_dp_ddi_trans_hbr2;
+ return intel_get_buf_trans(&tgl_dkl_phy_ddi_translations_dp_hbr2,
+ n_entries);
} else {
- *n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans);
- return tgl_dkl_phy_dp_ddi_trans;
+ return intel_get_buf_trans(&tgl_dkl_phy_ddi_translations_dp_hbr,
+ n_entries);
}
}
-const struct tgl_dkl_phy_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
tgl_get_dkl_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return tgl_get_dkl_buf_trans_hdmi(encoder, crtc_state, n_entries);
+ return intel_get_buf_trans(&tgl_dkl_phy_ddi_translations_hdmi, n_entries);
else
return tgl_get_dkl_buf_trans_dp(encoder, crtc_state, n_entries);
}
-static const struct tgl_dkl_phy_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
adlp_get_dkl_buf_trans_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (crtc_state->port_clock > 270000) {
- *n_entries = ARRAY_SIZE(adlp_dkl_phy_dp_ddi_trans_hbr2_hbr3);
- return adlp_dkl_phy_dp_ddi_trans_hbr2_hbr3;
+ return intel_get_buf_trans(&adlp_dkl_phy_ddi_translations_dp_hbr2_hbr3,
+ n_entries);
+ } else {
+ return intel_get_buf_trans(&adlp_dkl_phy_ddi_translations_dp_hbr,
+ n_entries);
}
-
- *n_entries = ARRAY_SIZE(adlp_dkl_phy_dp_ddi_trans_hbr);
- return adlp_dkl_phy_dp_ddi_trans_hbr;
}
-const struct tgl_dkl_phy_ddi_buf_trans *
+static const struct intel_ddi_buf_trans *
adlp_get_dkl_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
- return tgl_get_dkl_buf_trans_hdmi(encoder, crtc_state, n_entries);
+ return intel_get_buf_trans(&tgl_dkl_phy_ddi_translations_hdmi, n_entries);
else
return adlp_get_dkl_buf_trans_dp(encoder, crtc_state, n_entries);
}
@@ -1406,43 +1568,68 @@ int intel_ddi_hdmi_num_entries(struct intel_encoder *encoder,
int *default_entry)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ const struct intel_ddi_buf_trans *ddi_translations;
int n_entries;
- if (DISPLAY_VER(dev_priv) >= 12) {
- if (intel_phy_is_combo(dev_priv, phy))
- tgl_get_combo_buf_trans_hdmi(encoder, crtc_state, &n_entries);
- else
- tgl_get_dkl_buf_trans_hdmi(encoder, crtc_state, &n_entries);
- *default_entry = n_entries - 1;
- } else if (DISPLAY_VER(dev_priv) == 11) {
- if (intel_phy_is_combo(dev_priv, phy))
- icl_get_combo_buf_trans_hdmi(encoder, crtc_state, &n_entries);
- else
- icl_get_mg_buf_trans_hdmi(encoder, crtc_state, &n_entries);
- *default_entry = n_entries - 1;
- } else if (IS_CANNONLAKE(dev_priv)) {
- cnl_get_buf_trans_hdmi(encoder, &n_entries);
- *default_entry = n_entries - 1;
- } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
- bxt_get_buf_trans_hdmi(encoder, &n_entries);
- *default_entry = n_entries - 1;
- } else if (DISPLAY_VER(dev_priv) == 9) {
- intel_ddi_get_buf_trans_hdmi(encoder, &n_entries);
- *default_entry = 8;
- } else if (IS_BROADWELL(dev_priv)) {
- intel_ddi_get_buf_trans_hdmi(encoder, &n_entries);
- *default_entry = 7;
- } else if (IS_HASWELL(dev_priv)) {
- intel_ddi_get_buf_trans_hdmi(encoder, &n_entries);
- *default_entry = 6;
- } else {
- drm_WARN(&dev_priv->drm, 1, "ddi translation table missing\n");
+ ddi_translations = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
+
+ if (drm_WARN_ON(&dev_priv->drm, !ddi_translations)) {
+ *default_entry = 0;
return 0;
}
- if (drm_WARN_ON_ONCE(&dev_priv->drm, n_entries == 0))
- return 0;
+ *default_entry = ddi_translations->hdmi_default_entry;
return n_entries;
}
+
+void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+ if (IS_ALDERLAKE_P(i915)) {
+ if (intel_phy_is_combo(i915, phy))
+ encoder->get_buf_trans = adlp_get_combo_buf_trans;
+ else
+ encoder->get_buf_trans = adlp_get_dkl_buf_trans;
+ } else if (IS_ALDERLAKE_S(i915)) {
+ encoder->get_buf_trans = adls_get_combo_buf_trans;
+ } else if (IS_ROCKETLAKE(i915)) {
+ encoder->get_buf_trans = rkl_get_combo_buf_trans;
+ } else if (IS_DG1(i915)) {
+ encoder->get_buf_trans = dg1_get_combo_buf_trans;
+ } else if (DISPLAY_VER(i915) >= 12) {
+ if (intel_phy_is_combo(i915, phy))
+ encoder->get_buf_trans = tgl_get_combo_buf_trans;
+ else
+ encoder->get_buf_trans = tgl_get_dkl_buf_trans;
+ } else if (DISPLAY_VER(i915) == 11) {
+ if (IS_PLATFORM(i915, INTEL_JASPERLAKE))
+ encoder->get_buf_trans = jsl_get_combo_buf_trans;
+ else if (IS_PLATFORM(i915, INTEL_ELKHARTLAKE))
+ encoder->get_buf_trans = ehl_get_combo_buf_trans;
+ else if (intel_phy_is_combo(i915, phy))
+ encoder->get_buf_trans = icl_get_combo_buf_trans;
+ else
+ encoder->get_buf_trans = icl_get_mg_buf_trans;
+ } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
+ encoder->get_buf_trans = bxt_get_buf_trans;
+ } else if (IS_CML_ULX(i915) || IS_CFL_ULX(i915) || IS_KBL_ULX(i915)) {
+ encoder->get_buf_trans = kbl_y_get_buf_trans;
+ } else if (IS_CML_ULT(i915) || IS_CFL_ULT(i915) || IS_KBL_ULT(i915)) {
+ encoder->get_buf_trans = kbl_u_get_buf_trans;
+ } else if (IS_COMETLAKE(i915) || IS_COFFEELAKE(i915) || IS_KABYLAKE(i915)) {
+ encoder->get_buf_trans = kbl_get_buf_trans;
+ } else if (IS_SKL_ULX(i915)) {
+ encoder->get_buf_trans = skl_y_get_buf_trans;
+ } else if (IS_SKL_ULT(i915)) {
+ encoder->get_buf_trans = skl_u_get_buf_trans;
+ } else if (IS_SKYLAKE(i915)) {
+ encoder->get_buf_trans = skl_get_buf_trans;
+ } else if (IS_BROADWELL(i915)) {
+ encoder->get_buf_trans = bdw_get_buf_trans;
+ } else {
+ encoder->get_buf_trans = hsw_get_buf_trans;
+ }
+}
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h
index 4c2efab38642..2acd720f9d4f 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h
@@ -12,7 +12,7 @@ struct drm_i915_private;
struct intel_encoder;
struct intel_crtc_state;
-struct ddi_buf_trans {
+struct hsw_ddi_buf_trans {
u32 trans1; /* balance leg enable, de-emph level */
u32 trans2; /* vref sel, vswing */
u8 i_boost; /* SKL: I_boost; valid: 0x0, 0x1, 0x3, 0x7 */
@@ -25,7 +25,7 @@ struct bxt_ddi_buf_trans {
u8 deemphasis;
};
-struct cnl_ddi_buf_trans {
+struct icl_ddi_buf_trans {
u8 dw2_swing_sel;
u8 dw7_n_scalar;
u8 dw4_cursor_coeff;
@@ -45,60 +45,26 @@ struct tgl_dkl_phy_ddi_buf_trans {
u32 dkl_de_emphasis_control;
};
-bool is_hobl_buf_trans(const struct cnl_ddi_buf_trans *table);
+union intel_ddi_buf_trans_entry {
+ struct hsw_ddi_buf_trans hsw;
+ struct bxt_ddi_buf_trans bxt;
+ struct icl_ddi_buf_trans icl;
+ struct icl_mg_phy_ddi_buf_trans mg;
+ struct tgl_dkl_phy_ddi_buf_trans dkl;
+};
+
+struct intel_ddi_buf_trans {
+ const union intel_ddi_buf_trans_entry *entries;
+ u8 num_entries;
+ u8 hdmi_default_entry;
+};
+
+bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table);
int intel_ddi_hdmi_num_entries(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *default_entry);
-const struct ddi_buf_trans *
-intel_ddi_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries);
-const struct ddi_buf_trans *
-intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv,
- int *n_entries);
-const struct ddi_buf_trans *
-intel_ddi_get_buf_trans_hdmi(struct intel_encoder *encoder,
- int *n_entries);
-const struct ddi_buf_trans *
-intel_ddi_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries);
-
-const struct bxt_ddi_buf_trans *
-bxt_get_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
-
-const struct tgl_dkl_phy_ddi_buf_trans *
-adlp_get_dkl_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
-const struct cnl_ddi_buf_trans *
-tgl_get_combo_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
-const struct tgl_dkl_phy_ddi_buf_trans *
-tgl_get_dkl_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
-const struct cnl_ddi_buf_trans *
-jsl_get_combo_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
-const struct cnl_ddi_buf_trans *
-ehl_get_combo_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
-const struct cnl_ddi_buf_trans *
-icl_get_combo_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
-const struct icl_mg_phy_ddi_buf_trans *
-icl_get_mg_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
-
-const struct cnl_ddi_buf_trans *
-cnl_get_buf_trans(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- int *n_entries);
+void intel_ddi_buf_trans_init(struct intel_encoder *encoder);
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 0a8a2395c8ac..134a6acbd8fb 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -59,6 +59,7 @@
#include "display/intel_hdmi.h"
#include "display/intel_lvds.h"
#include "display/intel_sdvo.h"
+#include "display/intel_snps_phy.h"
#include "display/intel_tv.h"
#include "display/intel_vdsc.h"
#include "display/intel_vrr.h"
@@ -975,7 +976,7 @@ void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
/* FIXME: assert CPU port conditions for SNB+ */
}
- /* Wa_22012358565:adlp */
+ /* Wa_22012358565:adl-p */
if (DISPLAY_VER(dev_priv) == 13)
intel_de_rmw(dev_priv, PIPE_ARB_CTL(pipe),
0, PIPE_ARB_USE_PROG_SLOTS);
@@ -1035,6 +1036,10 @@ void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state)
if (!IS_I830(dev_priv))
val &= ~PIPECONF_ENABLE;
+ if (DISPLAY_VER(dev_priv) >= 12)
+ intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder),
+ FECSTALL_DIS_DPTSTREAM_DPTTG, 0);
+
intel_de_write(dev_priv, reg, val);
if ((val & PIPECONF_ENABLE) == 0)
intel_wait_for_pipe_off(old_crtc_state);
@@ -1331,6 +1336,9 @@ retry:
ret = i915_gem_object_lock(obj, &ww);
if (!ret && phys_cursor)
ret = i915_gem_object_attach_phys(obj, alignment);
+ else if (!ret && HAS_LMEM(dev_priv))
+ ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM);
+ /* TODO: Do we need to sync when migration becomes async? */
if (!ret)
ret = i915_gem_object_pin_pages(obj);
if (ret)
@@ -1914,20 +1922,50 @@ static void intel_dpt_unpin(struct i915_address_space *vm)
i915_vma_put(dpt->vma);
}
+static bool
+intel_reuse_initial_plane_obj(struct drm_i915_private *i915,
+ const struct intel_initial_plane_config *plane_config,
+ struct drm_framebuffer **fb,
+ struct i915_vma **vma)
+{
+ struct intel_crtc *crtc;
+
+ for_each_intel_crtc(&i915->drm, crtc) {
+ struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+ struct intel_plane *plane =
+ to_intel_plane(crtc->base.primary);
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(plane->base.state);
+
+ if (!crtc_state->uapi.active)
+ continue;
+
+ if (!plane_state->ggtt_vma)
+ continue;
+
+ if (intel_plane_ggtt_offset(plane_state) == plane_config->base) {
+ *fb = plane_state->hw.fb;
+ *vma = plane_state->ggtt_vma;
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void
-intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
+intel_find_initial_plane_obj(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config)
{
- struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_crtc *c;
- struct drm_plane *primary = intel_crtc->base.primary;
- struct drm_plane_state *plane_state = primary->state;
- struct intel_plane *intel_plane = to_intel_plane(primary);
- struct intel_plane_state *intel_state =
- to_intel_plane_state(plane_state);
struct intel_crtc_state *crtc_state =
- to_intel_crtc_state(intel_crtc->base.state);
+ to_intel_crtc_state(crtc->base.state);
+ struct intel_plane *plane =
+ to_intel_plane(crtc->base.primary);
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(plane->base.state);
struct drm_framebuffer *fb;
struct i915_vma *vma;
@@ -1939,7 +1977,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
if (!plane_config->fb)
return;
- if (intel_alloc_initial_plane_obj(intel_crtc, plane_config)) {
+ if (intel_alloc_initial_plane_obj(crtc, plane_config)) {
fb = &plane_config->fb->base;
vma = plane_config->vma;
goto valid_fb;
@@ -1949,25 +1987,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
* Failed to alloc the obj, check to see if we should share
* an fb with another CRTC instead
*/
- for_each_crtc(dev, c) {
- struct intel_plane_state *state;
-
- if (c == &intel_crtc->base)
- continue;
-
- if (!to_intel_crtc_state(c->state)->uapi.active)
- continue;
-
- state = to_intel_plane_state(c->primary->state);
- if (!state->ggtt_vma)
- continue;
-
- if (intel_plane_ggtt_offset(state) == plane_config->base) {
- fb = state->hw.fb;
- vma = state->ggtt_vma;
- goto valid_fb;
- }
- }
+ if (intel_reuse_initial_plane_obj(dev_priv, plane_config, &fb, &vma))
+ goto valid_fb;
/*
* We've failed to reconstruct the BIOS FB. Current display state
@@ -1976,7 +1997,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
* simplest solution is to just disable the primary plane now and
* pretend the BIOS never had it enabled.
*/
- intel_plane_disable_noatomic(intel_crtc, intel_plane);
+ intel_plane_disable_noatomic(crtc, plane);
if (crtc_state->bigjoiner) {
struct intel_crtc *slave =
crtc_state->bigjoiner_linked_crtc;
@@ -1986,40 +2007,38 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
return;
valid_fb:
- plane_state->rotation = plane_config->rotation;
- intel_fb_fill_view(to_intel_framebuffer(fb), plane_state->rotation,
- &intel_state->view);
+ plane_state->uapi.rotation = plane_config->rotation;
+ intel_fb_fill_view(to_intel_framebuffer(fb),
+ plane_state->uapi.rotation, &plane_state->view);
__i915_vma_pin(vma);
- intel_state->ggtt_vma = i915_vma_get(vma);
- if (intel_plane_uses_fence(intel_state) && i915_vma_pin_fence(vma) == 0)
- if (vma->fence)
- intel_state->flags |= PLANE_HAS_FENCE;
+ plane_state->ggtt_vma = i915_vma_get(vma);
+ if (intel_plane_uses_fence(plane_state) &&
+ i915_vma_pin_fence(vma) == 0 && vma->fence)
+ plane_state->flags |= PLANE_HAS_FENCE;
- plane_state->src_x = 0;
- plane_state->src_y = 0;
- plane_state->src_w = fb->width << 16;
- plane_state->src_h = fb->height << 16;
+ plane_state->uapi.src_x = 0;
+ plane_state->uapi.src_y = 0;
+ plane_state->uapi.src_w = fb->width << 16;
+ plane_state->uapi.src_h = fb->height << 16;
- plane_state->crtc_x = 0;
- plane_state->crtc_y = 0;
- plane_state->crtc_w = fb->width;
- plane_state->crtc_h = fb->height;
+ plane_state->uapi.crtc_x = 0;
+ plane_state->uapi.crtc_y = 0;
+ plane_state->uapi.crtc_w = fb->width;
+ plane_state->uapi.crtc_h = fb->height;
if (plane_config->tiling)
dev_priv->preserve_bios_swizzle = true;
- plane_state->fb = fb;
+ plane_state->uapi.fb = fb;
drm_framebuffer_get(fb);
- plane_state->crtc = &intel_crtc->base;
- intel_plane_copy_uapi_to_hw_state(intel_state, intel_state,
- intel_crtc);
+ plane_state->uapi.crtc = &crtc->base;
+ intel_plane_copy_uapi_to_hw_state(plane_state, plane_state, crtc);
intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
- atomic_or(to_intel_plane(primary)->frontbuffer_bit,
- &to_intel_frontbuffer(fb)->bits);
+ atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits);
}
unsigned int
@@ -2193,8 +2212,29 @@ unlock:
clear_bit_unlock(I915_RESET_MODESET, &dev_priv->gt.reset.flags);
}
-static void icl_set_pipe_chicken(struct intel_crtc *crtc)
+static bool underrun_recovery_supported(const struct intel_crtc_state *crtc_state)
{
+ if (crtc_state->pch_pfit.enabled &&
+ (crtc_state->pipe_src_w > drm_rect_width(&crtc_state->pch_pfit.dst) ||
+ crtc_state->pipe_src_h > drm_rect_height(&crtc_state->pch_pfit.dst) ||
+ crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420))
+ return false;
+
+ if (crtc_state->dsc.compression_enable)
+ return false;
+
+ if (crtc_state->has_psr2)
+ return false;
+
+ if (crtc_state->splitter.enable)
+ return false;
+
+ return true;
+}
+
+static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 tmp;
@@ -2215,19 +2255,19 @@ static void icl_set_pipe_chicken(struct intel_crtc *crtc)
*/
tmp |= PIXEL_ROUNDING_TRUNC_FB_PASSTHRU;
- /*
- * "The underrun recovery mechanism should be disabled
- * when the following is enabled for this pipe:
- * WiDi
- * Downscaling (this includes YUV420 fullblend)
- * COG
- * DSC
- * PSR2"
- *
- * FIXME: enable whenever possible...
- */
- if (IS_ALDERLAKE_P(dev_priv))
- tmp |= UNDERRUN_RECOVERY_DISABLE;
+ if (IS_DG2(dev_priv)) {
+ /*
+ * Underrun recovery must always be disabled on DG2. However
+ * the chicken bit meaning is inverted compared to other
+ * platforms.
+ */
+ tmp &= ~UNDERRUN_RECOVERY_ENABLE_DG2;
+ } else if (DISPLAY_VER(dev_priv) >= 13) {
+ if (underrun_recovery_supported(crtc_state))
+ tmp &= ~UNDERRUN_RECOVERY_DISABLE_ADLP;
+ else
+ tmp |= UNDERRUN_RECOVERY_DISABLE_ADLP;
+ }
intel_de_write(dev_priv, PIPE_CHICKEN(pipe), tmp);
}
@@ -2706,10 +2746,10 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state)
intel_wait_for_vblank(dev_priv, crtc->pipe);
}
-static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
+static void intel_crtc_dpms_overlay_disable(struct intel_crtc *crtc)
{
- if (intel_crtc->overlay)
- (void) intel_overlay_switch_off(intel_crtc->overlay);
+ if (crtc->overlay)
+ (void) intel_overlay_switch_off(crtc->overlay);
/* Let userspace switch the overlay on again. In most cases userspace
* has to recompute where to put it anyway.
@@ -3177,6 +3217,28 @@ static void intel_encoders_enable(struct intel_atomic_state *state,
}
}
+static void intel_encoders_pre_disable(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+ const struct drm_connector_state *old_conn_state;
+ struct drm_connector *conn;
+ int i;
+
+ for_each_old_connector_in_state(&state->base, conn, old_conn_state, i) {
+ struct intel_encoder *encoder =
+ to_intel_encoder(old_conn_state->best_encoder);
+
+ if (old_conn_state->crtc != &crtc->base)
+ continue;
+
+ if (encoder->pre_disable)
+ encoder->pre_disable(state, encoder, old_crtc_state,
+ old_conn_state);
+ }
+}
+
static void intel_encoders_disable(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -3386,13 +3448,17 @@ static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv,
intel_de_write(dev_priv, CLKGATE_DIS_PSL(pipe), val);
}
-static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
+static void icl_pipe_mbus_enable(struct intel_crtc *crtc, bool joined_mbus)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 val;
- val = MBUS_DBOX_A_CREDIT(2);
+ /* Wa_22010947358:adl-p */
+ if (IS_ALDERLAKE_P(dev_priv))
+ val = joined_mbus ? MBUS_DBOX_A_CREDIT(6) : MBUS_DBOX_A_CREDIT(4);
+ else
+ val = MBUS_DBOX_A_CREDIT(2);
if (DISPLAY_VER(dev_priv) >= 12) {
val |= MBUS_DBOX_BW_CREDIT(2);
@@ -3460,7 +3526,8 @@ static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state,
* Enable sequence steps 1-7 on bigjoiner master
*/
intel_encoders_pre_pll_enable(state, master);
- intel_enable_shared_dpll(master_crtc_state);
+ if (master_crtc_state->shared_dpll)
+ intel_enable_shared_dpll(master_crtc_state);
intel_encoders_pre_enable(state, master);
/* and DSC on slave */
@@ -3518,7 +3585,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
crtc->active = true;
- /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */
+ /* Display WA #1180: WaDisableScalarClockGating: glk */
psl_clkgate_wa = DISPLAY_VER(dev_priv) == 10 &&
new_crtc_state->pch_pfit.enabled;
if (psl_clkgate_wa)
@@ -3542,13 +3609,17 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
hsw_set_linetime_wm(new_crtc_state);
if (DISPLAY_VER(dev_priv) >= 11)
- icl_set_pipe_chicken(crtc);
+ icl_set_pipe_chicken(new_crtc_state);
if (dev_priv->display.initial_watermarks)
dev_priv->display.initial_watermarks(state, crtc);
- if (DISPLAY_VER(dev_priv) >= 11)
- icl_pipe_mbus_enable(crtc);
+ if (DISPLAY_VER(dev_priv) >= 11) {
+ const struct intel_dbuf_state *dbuf_state =
+ intel_atomic_get_new_dbuf_state(state);
+
+ icl_pipe_mbus_enable(crtc, dbuf_state->joined_mbus);
+ }
if (new_crtc_state->bigjoiner_slave)
intel_crtc_vblank_on(new_crtc_state);
@@ -3682,6 +3753,13 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy)
{
if (phy == PHY_NONE)
return false;
+ else if (IS_DG2(dev_priv))
+ /*
+ * DG2 outputs labelled as "combo PHY" in the bspec use
+ * SNPS PHYs with completely different programming,
+ * hence we always return false here.
+ */
+ return false;
else if (IS_ALDERLAKE_S(dev_priv))
return phy <= PHY_E;
else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
@@ -3696,7 +3774,10 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy)
bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
{
- if (IS_ALDERLAKE_P(dev_priv))
+ if (IS_DG2(dev_priv))
+ /* DG2's "TC1" output uses a SNPS PHY */
+ return false;
+ else if (IS_ALDERLAKE_P(dev_priv))
return phy >= PHY_F && phy <= PHY_I;
else if (IS_TIGERLAKE(dev_priv))
return phy >= PHY_D && phy <= PHY_I;
@@ -3706,6 +3787,20 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
return false;
}
+bool intel_phy_is_snps(struct drm_i915_private *dev_priv, enum phy phy)
+{
+ if (phy == PHY_NONE)
+ return false;
+ else if (IS_DG2(dev_priv))
+ /*
+ * All four "combo" ports and the TC1 port (PHY E) use
+ * Synopsis PHYs.
+ */
+ return phy <= PHY_E;
+
+ return false;
+}
+
enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port)
{
if (DISPLAY_VER(i915) >= 13 && port >= PORT_D_XELPD)
@@ -3850,7 +3945,7 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)
}
if (HAS_DDI(dev_priv) && crtc_state->has_audio)
- mask |= BIT_ULL(POWER_DOMAIN_AUDIO);
+ mask |= BIT_ULL(POWER_DOMAIN_AUDIO_MMIO);
if (crtc_state->shared_dpll)
mask |= BIT_ULL(POWER_DOMAIN_DISPLAY_CORE);
@@ -6487,23 +6582,21 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
struct intel_load_detect_pipe *old,
struct drm_modeset_acquire_ctx *ctx)
{
- struct intel_crtc *intel_crtc;
- struct intel_encoder *intel_encoder =
+ struct intel_encoder *encoder =
intel_attached_encoder(to_intel_connector(connector));
- struct drm_crtc *possible_crtc;
- struct drm_encoder *encoder = &intel_encoder->base;
- struct drm_crtc *crtc = NULL;
- struct drm_device *dev = encoder->dev;
+ struct intel_crtc *possible_crtc;
+ struct intel_crtc *crtc = NULL;
+ struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_mode_config *config = &dev->mode_config;
struct drm_atomic_state *state = NULL, *restore_state = NULL;
struct drm_connector_state *connector_state;
struct intel_crtc_state *crtc_state;
- int ret, i = -1;
+ int ret;
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
connector->base.id, connector->name,
- encoder->base.id, encoder->name);
+ encoder->base.base.id, encoder->base.name);
old->restore_state = NULL;
@@ -6521,9 +6614,9 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
/* See if we already have a CRTC for this connector */
if (connector->state->crtc) {
- crtc = connector->state->crtc;
+ crtc = to_intel_crtc(connector->state->crtc);
- ret = drm_modeset_lock(&crtc->mutex, ctx);
+ ret = drm_modeset_lock(&crtc->base.mutex, ctx);
if (ret)
goto fail;
@@ -6532,17 +6625,17 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
}
/* Find an unused one (if possible) */
- for_each_crtc(dev, possible_crtc) {
- i++;
- if (!(encoder->possible_crtcs & (1 << i)))
+ for_each_intel_crtc(dev, possible_crtc) {
+ if (!(encoder->base.possible_crtcs &
+ drm_crtc_mask(&possible_crtc->base)))
continue;
- ret = drm_modeset_lock(&possible_crtc->mutex, ctx);
+ ret = drm_modeset_lock(&possible_crtc->base.mutex, ctx);
if (ret)
goto fail;
- if (possible_crtc->state->enable) {
- drm_modeset_unlock(&possible_crtc->mutex);
+ if (possible_crtc->base.state->enable) {
+ drm_modeset_unlock(&possible_crtc->base.mutex);
continue;
}
@@ -6561,8 +6654,6 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
}
found:
- intel_crtc = to_intel_crtc(crtc);
-
state = drm_atomic_state_alloc(dev);
restore_state = drm_atomic_state_alloc(dev);
if (!state || !restore_state) {
@@ -6579,11 +6670,11 @@ found:
goto fail;
}
- ret = drm_atomic_set_crtc_for_connector(connector_state, crtc);
+ ret = drm_atomic_set_crtc_for_connector(connector_state, &crtc->base);
if (ret)
goto fail;
- crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
+ crtc_state = intel_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
goto fail;
@@ -6596,15 +6687,15 @@ found:
if (ret)
goto fail;
- ret = intel_modeset_disable_planes(state, crtc);
+ ret = intel_modeset_disable_planes(state, &crtc->base);
if (ret)
goto fail;
ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(restore_state, connector));
if (!ret)
- ret = PTR_ERR_OR_ZERO(drm_atomic_get_crtc_state(restore_state, crtc));
+ ret = PTR_ERR_OR_ZERO(drm_atomic_get_crtc_state(restore_state, &crtc->base));
if (!ret)
- ret = drm_atomic_add_affected_planes(restore_state, crtc);
+ ret = drm_atomic_add_affected_planes(restore_state, &crtc->base);
if (ret) {
drm_dbg_kms(&dev_priv->drm,
"Failed to create a copy of old state to restore: %i\n",
@@ -6623,7 +6714,7 @@ found:
drm_atomic_state_put(state);
/* let the connector get through one full cycle before testing */
- intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
return true;
fail:
@@ -7295,12 +7386,13 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
}
if (dev_priv->display.compute_pipe_wm) {
- ret = dev_priv->display.compute_pipe_wm(crtc_state);
+ ret = dev_priv->display.compute_pipe_wm(state, crtc);
if (ret) {
drm_dbg_kms(&dev_priv->drm,
"Target pipe watermarks are invalid\n");
return ret;
}
+
}
if (dev_priv->display.compute_intermediate_wm) {
@@ -7313,7 +7405,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
* old state and the new state. We can program these
* immediately.
*/
- ret = dev_priv->display.compute_intermediate_wm(crtc_state);
+ ret = dev_priv->display.compute_intermediate_wm(state, crtc);
if (ret) {
drm_dbg_kms(&dev_priv->drm,
"No valid intermediate pipe watermarks are possible\n");
@@ -8636,10 +8728,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_BOOL(double_wide);
- PIPE_CONF_CHECK_P(shared_dpll);
+ if (dev_priv->dpll.mgr)
+ PIPE_CONF_CHECK_P(shared_dpll);
/* FIXME do the readout properly and get rid of this quirk */
- if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) {
+ if (dev_priv->dpll.mgr && !PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) {
PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
@@ -8671,7 +8764,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
+ }
+ if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) {
PIPE_CONF_CHECK_X(dsi_pll.ctrl);
PIPE_CONF_CHECK_X(dsi_pll.div);
@@ -9009,6 +9104,10 @@ verify_crtc_state(struct intel_crtc *crtc,
if (!new_crtc_state->hw.active)
return;
+ if (new_crtc_state->bigjoiner_slave)
+ /* No PLLs set for slave */
+ pipe_config->shared_dpll = NULL;
+
intel_pipe_config_sanity_check(dev_priv, pipe_config);
if (!intel_pipe_config_compare(new_crtc_state,
@@ -9112,6 +9211,55 @@ verify_shared_dpll_state(struct intel_crtc *crtc,
}
static void
+verify_mpllb_state(struct intel_atomic_state *state,
+ struct intel_crtc_state *new_crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_mpllb_state mpllb_hw_state = { 0 };
+ struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->mpllb_state;
+ struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+ struct intel_encoder *encoder;
+
+ if (!IS_DG2(i915))
+ return;
+
+ if (!new_crtc_state->hw.active)
+ return;
+
+ if (new_crtc_state->bigjoiner_slave)
+ return;
+
+ encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
+ intel_mpllb_readout_hw_state(encoder, &mpllb_hw_state);
+
+#define MPLLB_CHECK(name) do { \
+ if (mpllb_sw_state->name != mpllb_hw_state.name) { \
+ pipe_config_mismatch(false, crtc, "MPLLB:" __stringify(name), \
+ "(expected 0x%08x, found 0x%08x)", \
+ mpllb_sw_state->name, \
+ mpllb_hw_state.name); \
+ } \
+} while (0)
+
+ MPLLB_CHECK(mpllb_cp);
+ MPLLB_CHECK(mpllb_div);
+ MPLLB_CHECK(mpllb_div2);
+ MPLLB_CHECK(mpllb_fracn1);
+ MPLLB_CHECK(mpllb_fracn2);
+ MPLLB_CHECK(mpllb_sscen);
+ MPLLB_CHECK(mpllb_sscstep);
+
+ /*
+ * ref_control is handled by the hardware/firemware and never
+ * programmed by the software, but the proper values are supplied
+ * in the bspec for verification purposes.
+ */
+ MPLLB_CHECK(ref_control);
+
+#undef MPLLB_CHECK
+}
+
+static void
intel_modeset_verify_crtc(struct intel_crtc *crtc,
struct intel_atomic_state *state,
struct intel_crtc_state *old_crtc_state,
@@ -9124,6 +9272,7 @@ intel_modeset_verify_crtc(struct intel_crtc *crtc,
verify_connector_state(state, crtc);
verify_crtc_state(crtc, old_crtc_state, new_crtc_state);
verify_shared_dpll_state(crtc, old_crtc_state, new_crtc_state);
+ verify_mpllb_state(state, new_crtc_state);
}
static void
@@ -9749,7 +9898,7 @@ static int intel_atomic_check_async(struct intel_atomic_state *state)
/*
* FIXME: This check is kept generic for all platforms.
- * Need to verify this for all gen9 and gen10 platforms to enable
+ * Need to verify this for all gen9 platforms to enable
* this selectively if required.
*/
switch (new_plane_state->hw.fb->modifier) {
@@ -10160,7 +10309,7 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
hsw_set_linetime_wm(new_crtc_state);
if (DISPLAY_VER(dev_priv) >= 11)
- icl_set_pipe_chicken(crtc);
+ icl_set_pipe_chicken(new_crtc_state);
}
static void commit_pipe_pre_planes(struct intel_atomic_state *state,
@@ -10294,6 +10443,8 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave);
+ intel_encoders_pre_disable(state, crtc);
+
intel_crtc_disable_planes(state, crtc);
/*
@@ -11328,7 +11479,12 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
- if (IS_ALDERLAKE_P(dev_priv)) {
+ if (IS_DG2(dev_priv)) {
+ intel_ddi_init(dev_priv, PORT_A);
+ intel_ddi_init(dev_priv, PORT_B);
+ intel_ddi_init(dev_priv, PORT_C);
+ intel_ddi_init(dev_priv, PORT_D_XELPD);
+ } else if (IS_ALDERLAKE_P(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_TC1);
@@ -11375,13 +11531,6 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_C);
vlv_dsi_init(dev_priv);
- } else if (DISPLAY_VER(dev_priv) == 10) {
- intel_ddi_init(dev_priv, PORT_A);
- intel_ddi_init(dev_priv, PORT_B);
- intel_ddi_init(dev_priv, PORT_C);
- intel_ddi_init(dev_priv, PORT_D);
- intel_ddi_init(dev_priv, PORT_E);
- intel_ddi_init(dev_priv, PORT_F);
} else if (DISPLAY_VER(dev_priv) >= 9) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
@@ -11790,7 +11939,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
/* object is backed with LMEM for discrete */
i915 = to_i915(obj->base.dev);
- if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj)) {
+ if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) {
/* object is "remote", not in local memory */
i915_gem_object_put(obj);
return ERR_PTR(-EREMOTE);
@@ -13136,7 +13285,7 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
static void intel_early_display_was(struct drm_i915_private *dev_priv)
{
/*
- * Display WA #1185 WaDisableDARBFClkGating:cnl,glk,icl,ehl,tgl
+ * Display WA #1185 WaDisableDARBFClkGating:glk,icl,ehl,tgl
* Also known as Wa_14010480278.
*/
if (IS_DISPLAY_VER(dev_priv, 10, 12))
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index c9dbaf074d77..284936f0ddab 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -561,6 +561,7 @@ struct drm_display_mode *
intel_encoder_current_mode(struct intel_encoder *encoder);
bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy);
bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy);
+bool intel_phy_is_snps(struct drm_i915_private *dev_priv, enum phy phy);
enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
enum port port);
int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 88bb05d5c483..8fdacb252bb1 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -544,6 +544,11 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
seq_printf(m, "fw loaded: %s\n", yesno(intel_dmc_has_payload(dev_priv)));
seq_printf(m, "path: %s\n", dmc->fw_path);
+ seq_printf(m, "Pipe A fw support: %s\n",
+ yesno(GRAPHICS_VER(dev_priv) >= 12));
+ seq_printf(m, "Pipe A fw loaded: %s\n", yesno(dmc->dmc_info[DMC_FW_PIPEA].payload));
+ seq_printf(m, "Pipe B fw support: %s\n", yesno(IS_ALDERLAKE_P(dev_priv)));
+ seq_printf(m, "Pipe B fw loaded: %s\n", yesno(dmc->dmc_info[DMC_FW_PIPEB].payload));
if (!intel_dmc_has_payload(dev_priv))
goto out;
@@ -582,7 +587,7 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
out:
seq_printf(m, "program base: 0x%08x\n",
- intel_de_read(dev_priv, DMC_PROGRAM(0)));
+ intel_de_read(dev_priv, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)));
seq_printf(m, "ssp base: 0x%08x\n",
intel_de_read(dev_priv, DMC_SSP_BASE));
seq_printf(m, "htp: 0x%08x\n", intel_de_read(dev_priv, DMC_HTP_SKL));
@@ -1225,7 +1230,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
static void drrs_status_per_crtc(struct seq_file *m,
struct drm_device *dev,
- struct intel_crtc *intel_crtc)
+ struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_drrs *drrs = &dev_priv->drrs;
@@ -1237,7 +1242,7 @@ static void drrs_status_per_crtc(struct seq_file *m,
drm_for_each_connector_iter(connector, &conn_iter) {
bool supported = false;
- if (connector->state->crtc != &intel_crtc->base)
+ if (connector->state->crtc != &crtc->base)
continue;
seq_printf(m, "%s:\n", connector->name);
@@ -1252,7 +1257,7 @@ static void drrs_status_per_crtc(struct seq_file *m,
seq_puts(m, "\n");
- if (to_intel_crtc_state(intel_crtc->base.state)->has_drrs) {
+ if (to_intel_crtc_state(crtc->base.state)->has_drrs) {
struct intel_panel *panel;
mutex_lock(&drrs->mutex);
@@ -1298,16 +1303,16 @@ static int i915_drrs_status(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct drm_device *dev = &dev_priv->drm;
- struct intel_crtc *intel_crtc;
+ struct intel_crtc *crtc;
int active_crtc_cnt = 0;
drm_modeset_lock_all(dev);
- for_each_intel_crtc(dev, intel_crtc) {
- if (intel_crtc->base.state->active) {
+ for_each_intel_crtc(dev, crtc) {
+ if (crtc->base.state->active) {
active_crtc_cnt++;
seq_printf(m, "\nCRTC %d: ", active_crtc_cnt);
- drrs_status_per_crtc(m, dev, intel_crtc);
+ drrs_status_per_crtc(m, dev, crtc);
}
}
drm_modeset_unlock_all(dev);
@@ -2064,7 +2069,7 @@ i915_fifo_underrun_reset_write(struct file *filp,
size_t cnt, loff_t *ppos)
{
struct drm_i915_private *dev_priv = filp->private_data;
- struct intel_crtc *intel_crtc;
+ struct intel_crtc *crtc;
struct drm_device *dev = &dev_priv->drm;
int ret;
bool reset;
@@ -2076,15 +2081,15 @@ i915_fifo_underrun_reset_write(struct file *filp,
if (!reset)
return cnt;
- for_each_intel_crtc(dev, intel_crtc) {
+ for_each_intel_crtc(dev, crtc) {
struct drm_crtc_commit *commit;
struct intel_crtc_state *crtc_state;
- ret = drm_modeset_lock_single_interruptible(&intel_crtc->base.mutex);
+ ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex);
if (ret)
return ret;
- crtc_state = to_intel_crtc_state(intel_crtc->base.state);
+ crtc_state = to_intel_crtc_state(crtc->base.state);
commit = crtc_state->uapi.commit;
if (commit) {
ret = wait_for_completion_interruptible(&commit->hw_done);
@@ -2095,12 +2100,12 @@ i915_fifo_underrun_reset_write(struct file *filp,
if (!ret && crtc_state->hw.active) {
drm_dbg_kms(&dev_priv->drm,
"Re-arming FIFO underruns on pipe %c\n",
- pipe_name(intel_crtc->pipe));
+ pipe_name(crtc->pipe));
- intel_crtc_arm_fifo_underrun(intel_crtc, crtc_state);
+ intel_crtc_arm_fifo_underrun(crtc, crtc_state);
}
- drm_modeset_unlock(&intel_crtc->base.mutex);
+ drm_modeset_unlock(&crtc->base.mutex);
if (ret)
return ret;
@@ -2251,6 +2256,11 @@ static int i915_lpsp_capability_show(struct seq_file *m, void *data)
if (connector->status != connector_status_connected)
return -ENODEV;
+ if (DISPLAY_VER(i915) >= 13) {
+ LPSP_CAPABLE(encoder->port <= PORT_B);
+ return 0;
+ }
+
switch (DISPLAY_VER(i915)) {
case 12:
/*
@@ -2385,6 +2395,73 @@ static const struct file_operations i915_dsc_fec_support_fops = {
.write = i915_dsc_fec_support_write
};
+static int i915_dsc_bpp_show(struct seq_file *m, void *data)
+{
+ struct drm_connector *connector = m->private;
+ struct drm_device *dev = connector->dev;
+ struct drm_crtc *crtc;
+ struct intel_crtc_state *crtc_state;
+ struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
+ int ret;
+
+ if (!encoder)
+ return -ENODEV;
+
+ ret = drm_modeset_lock_single_interruptible(&dev->mode_config.connection_mutex);
+ if (ret)
+ return ret;
+
+ crtc = connector->state->crtc;
+ if (connector->status != connector_status_connected || !crtc) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ crtc_state = to_intel_crtc_state(crtc->state);
+ seq_printf(m, "Compressed_BPP: %d\n", crtc_state->dsc.compressed_bpp);
+
+out: drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+ return ret;
+}
+
+static ssize_t i915_dsc_bpp_write(struct file *file,
+ const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ struct drm_connector *connector =
+ ((struct seq_file *)file->private_data)->private;
+ struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ int dsc_bpp = 0;
+ int ret;
+
+ ret = kstrtoint_from_user(ubuf, len, 0, &dsc_bpp);
+ if (ret < 0)
+ return ret;
+
+ intel_dp->force_dsc_bpp = dsc_bpp;
+ *offp += len;
+
+ return len;
+}
+
+static int i915_dsc_bpp_open(struct inode *inode,
+ struct file *file)
+{
+ return single_open(file, i915_dsc_bpp_show,
+ inode->i_private);
+}
+
+static const struct file_operations i915_dsc_bpp_fops = {
+ .owner = THIS_MODULE,
+ .open = i915_dsc_bpp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = i915_dsc_bpp_write
+};
+
/**
* intel_connector_debugfs_add - add i915 specific connector debugfs files
* @connector: pointer to a registered drm_connector
@@ -2423,10 +2500,17 @@ int intel_connector_debugfs_add(struct drm_connector *connector)
connector, &i915_hdcp_sink_capability_fops);
}
- if ((DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) && ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort && !to_intel_connector(connector)->mst_port) || connector->connector_type == DRM_MODE_CONNECTOR_eDP))
- debugfs_create_file("i915_dsc_fec_support", S_IRUGO, root,
+ if (DISPLAY_VER(dev_priv) >= 11 &&
+ ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
+ !to_intel_connector(connector)->mst_port) ||
+ connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
+ debugfs_create_file("i915_dsc_fec_support", 0644, root,
connector, &i915_dsc_fec_support_fops);
+ debugfs_create_file("i915_dsc_bpp", 0644, root,
+ connector, &i915_dsc_bpp_fops);
+ }
+
/* Legacy panels doesn't lpsp on any platform */
if ((DISPLAY_VER(dev_priv) >= 9 || IS_HASWELL(dev_priv) ||
IS_BROADWELL(dev_priv)) &&
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 86b7ac7b65ec..cce1a926fcc1 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -18,6 +18,7 @@
#include "intel_pm.h"
#include "intel_pps.h"
#include "intel_sideband.h"
+#include "intel_snps_phy.h"
#include "intel_tc.h"
#include "intel_vga.h"
@@ -106,8 +107,10 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
return "PORT_OTHER";
case POWER_DOMAIN_VGA:
return "VGA";
- case POWER_DOMAIN_AUDIO:
- return "AUDIO";
+ case POWER_DOMAIN_AUDIO_MMIO:
+ return "AUDIO_MMIO";
+ case POWER_DOMAIN_AUDIO_PLAYBACK:
+ return "AUDIO_PLAYBACK";
case POWER_DOMAIN_AUX_A:
return "AUX_A";
case POWER_DOMAIN_AUX_B:
@@ -341,6 +344,17 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
{
const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
int pw_idx = power_well->desc->hsw.idx;
+ int enable_delay = power_well->desc->hsw.fixed_enable_delay;
+
+ /*
+ * For some power wells we're not supposed to watch the status bit for
+ * an ack, but rather just wait a fixed amount of time and then
+ * proceed. This is only used on DG2.
+ */
+ if (IS_DG2(dev_priv) && enable_delay) {
+ usleep_range(enable_delay, 2 * enable_delay);
+ return;
+ }
/* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */
if (intel_de_wait_for_set(dev_priv, regs->driver,
@@ -436,17 +450,6 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
hsw_wait_for_power_well_enable(dev_priv, power_well, false);
- /* Display WA #1178: cnl */
- if (IS_CANNONLAKE(dev_priv) &&
- pw_idx >= GLK_PW_CTL_IDX_AUX_B &&
- pw_idx <= CNL_PW_CTL_IDX_AUX_F) {
- u32 val;
-
- val = intel_de_read(dev_priv, CNL_AUX_ANAOVRD1(pw_idx));
- val |= CNL_AUX_ANAOVRD1_ENABLE | CNL_AUX_ANAOVRD1_LDO_BYPASS;
- intel_de_write(dev_priv, CNL_AUX_ANAOVRD1(pw_idx), val);
- }
-
if (power_well->desc->hsw.has_fuses) {
enum skl_power_gate pg;
@@ -961,8 +964,9 @@ static void bxt_disable_dc9(struct drm_i915_private *dev_priv)
static void assert_dmc_loaded(struct drm_i915_private *dev_priv)
{
drm_WARN_ONCE(&dev_priv->drm,
- !intel_de_read(dev_priv, DMC_PROGRAM(0)),
- "DMC program storage start is NULL\n");
+ !intel_de_read(dev_priv,
+ DMC_PROGRAM(dev_priv->dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)),
+ "DMC program storage start is NULL\n");
drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, DMC_SSP_BASE),
"DMC SSP Base Not fine\n");
drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, DMC_HTP_SKL),
@@ -2507,7 +2511,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_PORT_DSI) | \
BIT_ULL(POWER_DOMAIN_PORT_CRT) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_AUX_B) | \
BIT_ULL(POWER_DOMAIN_AUX_C) | \
BIT_ULL(POWER_DOMAIN_GMBUS) | \
@@ -2557,7 +2562,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \
BIT_ULL(POWER_DOMAIN_PORT_DSI) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_AUX_B) | \
BIT_ULL(POWER_DOMAIN_AUX_C) | \
BIT_ULL(POWER_DOMAIN_AUX_D) | \
@@ -2590,7 +2596,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \
BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */ \
BIT_ULL(POWER_DOMAIN_VGA) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_INIT))
#define BDW_DISPLAY_POWER_DOMAINS ( \
@@ -2606,7 +2613,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \
BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */ \
BIT_ULL(POWER_DOMAIN_VGA) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_INIT))
#define SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \
@@ -2624,7 +2632,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_AUX_B) | \
BIT_ULL(POWER_DOMAIN_AUX_C) | \
BIT_ULL(POWER_DOMAIN_AUX_D) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
BIT_ULL(POWER_DOMAIN_INIT))
#define SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS ( \
@@ -2659,7 +2668,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT_ULL(POWER_DOMAIN_AUX_B) | \
BIT_ULL(POWER_DOMAIN_AUX_C) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
BIT_ULL(POWER_DOMAIN_INIT))
#define BXT_DISPLAY_DC_OFF_POWER_DOMAINS ( \
@@ -2692,7 +2702,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT_ULL(POWER_DOMAIN_AUX_B) | \
BIT_ULL(POWER_DOMAIN_AUX_C) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
BIT_ULL(POWER_DOMAIN_INIT))
#define GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS ( \
@@ -2731,63 +2742,6 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_GMBUS) | \
BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \
- BIT_ULL(POWER_DOMAIN_PIPE_B) | \
- BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \
- BIT_ULL(POWER_DOMAIN_PIPE_C) | \
- BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \
- BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \
- BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_F_LANES) | \
- BIT_ULL(POWER_DOMAIN_AUX_B) | \
- BIT_ULL(POWER_DOMAIN_AUX_C) | \
- BIT_ULL(POWER_DOMAIN_AUX_D) | \
- BIT_ULL(POWER_DOMAIN_AUX_F) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
- BIT_ULL(POWER_DOMAIN_VGA) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_AUX_A_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_AUX_A) | \
- BIT_ULL(POWER_DOMAIN_AUX_IO_A) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_AUX_B_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_AUX_B) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_AUX_C_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_AUX_C) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_AUX_D_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_AUX_D) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_AUX_F_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_AUX_F) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_DDI_F_IO_POWER_DOMAINS ( \
- BIT_ULL(POWER_DOMAIN_PORT_DDI_F_IO) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-#define CNL_DISPLAY_DC_OFF_POWER_DOMAINS ( \
- CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \
- BIT_ULL(POWER_DOMAIN_GT_IRQ) | \
- BIT_ULL(POWER_DOMAIN_MODESET) | \
- BIT_ULL(POWER_DOMAIN_AUX_A) | \
- BIT_ULL(POWER_DOMAIN_INIT))
-
/*
* ICL PW_0/PG_0 domains (HW/DMC control):
* - PCI
@@ -2829,7 +2783,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_AUX_E_TBT) | \
BIT_ULL(POWER_DOMAIN_AUX_F_TBT) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_INIT))
/*
* - transcoder WD
@@ -2921,7 +2876,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_AUX_TBT5) | \
BIT_ULL(POWER_DOMAIN_AUX_TBT6) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_INIT))
#define TGL_PW_2_POWER_DOMAINS ( \
@@ -2991,7 +2947,8 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
RKL_PW_4_POWER_DOMAINS | \
BIT_ULL(POWER_DOMAIN_PIPE_B) | \
BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \
BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_TC1) | \
@@ -3029,6 +2986,35 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_INIT))
/*
+ * DG1 onwards Audio MMIO/VERBS lies in PG0 power well.
+ */
+#define DG1_PW_3_POWER_DOMAINS ( \
+ TGL_PW_4_POWER_DOMAINS | \
+ BIT_ULL(POWER_DOMAIN_PIPE_B) | \
+ BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \
+ BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_TC1) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_TC2) | \
+ BIT_ULL(POWER_DOMAIN_AUX_USBC1) | \
+ BIT_ULL(POWER_DOMAIN_AUX_USBC2) | \
+ BIT_ULL(POWER_DOMAIN_VGA) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+#define DG1_PW_2_POWER_DOMAINS ( \
+ DG1_PW_3_POWER_DOMAINS | \
+ BIT_ULL(POWER_DOMAIN_TRANSCODER_VDSC_PW2) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+#define DG1_DISPLAY_DC_OFF_POWER_DOMAINS ( \
+ DG1_PW_3_POWER_DOMAINS | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
+ BIT_ULL(POWER_DOMAIN_MODESET) | \
+ BIT_ULL(POWER_DOMAIN_AUX_A) | \
+ BIT_ULL(POWER_DOMAIN_AUX_B) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+/*
* XE_LPD Power Domains
*
* Previous platforms required that PG(n-1) be enabled before PG(n). That
@@ -3073,7 +3059,7 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
XELPD_PW_B_POWER_DOMAINS | \
XELPD_PW_C_POWER_DOMAINS | \
XELPD_PW_D_POWER_DOMAINS | \
- BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_PLAYBACK) | \
BIT_ULL(POWER_DOMAIN_VGA) | \
BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_D_XELPD) | \
@@ -3114,6 +3100,7 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
#define XELPD_DISPLAY_DC_OFF_POWER_DOMAINS ( \
XELPD_PW_2_POWER_DOMAINS | \
+ BIT_ULL(POWER_DOMAIN_AUDIO_MMIO) | \
BIT_ULL(POWER_DOMAIN_MODESET) | \
BIT_ULL(POWER_DOMAIN_AUX_A) | \
BIT_ULL(POWER_DOMAIN_AUX_B) | \
@@ -3694,148 +3681,6 @@ static const struct i915_power_well_desc glk_power_wells[] = {
},
};
-static const struct i915_power_well_desc cnl_power_wells[] = {
- {
- .name = "always-on",
- .always_on = true,
- .domains = POWER_DOMAIN_MASK,
- .ops = &i9xx_always_on_power_well_ops,
- .id = DISP_PW_ID_NONE,
- },
- {
- .name = "power well 1",
- /* Handled by the DMC firmware */
- .always_on = true,
- .domains = 0,
- .ops = &hsw_power_well_ops,
- .id = SKL_DISP_PW_1,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = SKL_PW_CTL_IDX_PW_1,
- .hsw.has_fuses = true,
- },
- },
- {
- .name = "AUX A",
- .domains = CNL_DISPLAY_AUX_A_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = DISP_PW_ID_NONE,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = GLK_PW_CTL_IDX_AUX_A,
- },
- },
- {
- .name = "AUX B",
- .domains = CNL_DISPLAY_AUX_B_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = DISP_PW_ID_NONE,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = GLK_PW_CTL_IDX_AUX_B,
- },
- },
- {
- .name = "AUX C",
- .domains = CNL_DISPLAY_AUX_C_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = DISP_PW_ID_NONE,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = GLK_PW_CTL_IDX_AUX_C,
- },
- },
- {
- .name = "AUX D",
- .domains = CNL_DISPLAY_AUX_D_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = DISP_PW_ID_NONE,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = CNL_PW_CTL_IDX_AUX_D,
- },
- },
- {
- .name = "DC off",
- .domains = CNL_DISPLAY_DC_OFF_POWER_DOMAINS,
- .ops = &gen9_dc_off_power_well_ops,
- .id = SKL_DISP_DC_OFF,
- },
- {
- .name = "power well 2",
- .domains = CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = SKL_DISP_PW_2,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = SKL_PW_CTL_IDX_PW_2,
- .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
- .hsw.has_vga = true,
- .hsw.has_fuses = true,
- },
- },
- {
- .name = "DDI A IO power well",
- .domains = CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = DISP_PW_ID_NONE,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = GLK_PW_CTL_IDX_DDI_A,
- },
- },
- {
- .name = "DDI B IO power well",
- .domains = CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = DISP_PW_ID_NONE,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = SKL_PW_CTL_IDX_DDI_B,
- },
- },
- {
- .name = "DDI C IO power well",
- .domains = CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = DISP_PW_ID_NONE,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = SKL_PW_CTL_IDX_DDI_C,
- },
- },
- {
- .name = "DDI D IO power well",
- .domains = CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = DISP_PW_ID_NONE,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = SKL_PW_CTL_IDX_DDI_D,
- },
- },
- {
- .name = "DDI F IO power well",
- .domains = CNL_DISPLAY_DDI_F_IO_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = CNL_DISP_PW_DDI_F_IO,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = CNL_PW_CTL_IDX_DDI_F,
- },
- },
- {
- .name = "AUX F",
- .domains = CNL_DISPLAY_AUX_F_POWER_DOMAINS,
- .ops = &hsw_power_well_ops,
- .id = CNL_DISP_PW_DDI_F_AUX,
- {
- .hsw.regs = &hsw_power_well_regs,
- .hsw.idx = CNL_PW_CTL_IDX_AUX_F,
- },
- },
-};
-
static const struct i915_power_well_ops icl_aux_power_well_ops = {
.sync_hw = hsw_power_well_sync_hw,
.enable = icl_aux_power_well_enable,
@@ -4642,6 +4487,165 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
},
};
+static const struct i915_power_well_desc dg1_power_wells[] = {
+ {
+ .name = "always-on",
+ .always_on = true,
+ .domains = POWER_DOMAIN_MASK,
+ .ops = &i9xx_always_on_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ },
+ {
+ .name = "power well 1",
+ /* Handled by the DMC firmware */
+ .always_on = true,
+ .domains = 0,
+ .ops = &hsw_power_well_ops,
+ .id = SKL_DISP_PW_1,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_PW_1,
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "DC off",
+ .domains = DG1_DISPLAY_DC_OFF_POWER_DOMAINS,
+ .ops = &gen9_dc_off_power_well_ops,
+ .id = SKL_DISP_DC_OFF,
+ },
+ {
+ .name = "power well 2",
+ .domains = DG1_PW_2_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = SKL_DISP_PW_2,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_PW_2,
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "power well 3",
+ .domains = DG1_PW_3_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = ICL_DISP_PW_3,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_PW_3,
+ .hsw.irq_pipe_mask = BIT(PIPE_B),
+ .hsw.has_vga = true,
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "DDI A IO",
+ .domains = ICL_DDI_IO_A_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
+ }
+ },
+ {
+ .name = "DDI B IO",
+ .domains = ICL_DDI_IO_B_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
+ }
+ },
+ {
+ .name = "DDI IO TC1",
+ .domains = TGL_DDI_IO_TC1_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1,
+ },
+ },
+ {
+ .name = "DDI IO TC2",
+ .domains = TGL_DDI_IO_TC2_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2,
+ },
+ },
+ {
+ .name = "AUX A",
+ .domains = TGL_AUX_A_IO_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
+ },
+ },
+ {
+ .name = "AUX B",
+ .domains = TGL_AUX_B_IO_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
+ },
+ },
+ {
+ .name = "AUX USBC1",
+ .domains = TGL_AUX_IO_USBC1_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1,
+ .hsw.is_tc_tbt = false,
+ },
+ },
+ {
+ .name = "AUX USBC2",
+ .domains = TGL_AUX_IO_USBC2_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2,
+ .hsw.is_tc_tbt = false,
+ },
+ },
+ {
+ .name = "power well 4",
+ .domains = TGL_PW_4_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_PW_4,
+ .hsw.has_fuses = true,
+ .hsw.irq_pipe_mask = BIT(PIPE_C),
+ }
+ },
+ {
+ .name = "power well 5",
+ .domains = TGL_PW_5_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_PW_5,
+ .hsw.has_fuses = true,
+ .hsw.irq_pipe_mask = BIT(PIPE_D),
+ },
+ },
+};
+
static const struct i915_power_well_desc xelpd_power_wells[] = {
{
.name = "always-on",
@@ -4827,6 +4831,7 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
{
.hsw.regs = &icl_aux_power_well_regs,
.hsw.idx = ICL_PW_CTL_IDX_AUX_A,
+ .hsw.fixed_enable_delay = 600,
},
},
{
@@ -4837,6 +4842,7 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
{
.hsw.regs = &icl_aux_power_well_regs,
.hsw.idx = ICL_PW_CTL_IDX_AUX_B,
+ .hsw.fixed_enable_delay = 600,
},
},
{
@@ -4847,6 +4853,7 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
{
.hsw.regs = &icl_aux_power_well_regs,
.hsw.idx = ICL_PW_CTL_IDX_AUX_C,
+ .hsw.fixed_enable_delay = 600,
},
},
{
@@ -4857,6 +4864,7 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
{
.hsw.regs = &icl_aux_power_well_regs,
.hsw.idx = XELPD_PW_CTL_IDX_AUX_D,
+ .hsw.fixed_enable_delay = 600,
},
},
{
@@ -4877,6 +4885,7 @@ static const struct i915_power_well_desc xelpd_power_wells[] = {
{
.hsw.regs = &icl_aux_power_well_regs,
.hsw.idx = TGL_PW_CTL_IDX_AUX_TC1,
+ .hsw.fixed_enable_delay = 600,
},
},
{
@@ -5121,7 +5130,9 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
err = 0;
} else if (DISPLAY_VER(dev_priv) >= 13) {
err = set_power_wells(power_domains, xelpd_power_wells);
- } else if (IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv)) {
+ } else if (IS_DG1(dev_priv)) {
+ err = set_power_wells(power_domains, dg1_power_wells);
+ } else if (IS_ALDERLAKE_S(dev_priv)) {
err = set_power_wells_mask(power_domains, tgl_power_wells,
BIT_ULL(TGL_DISP_PW_TC_COLD_OFF));
} else if (IS_ROCKETLAKE(dev_priv)) {
@@ -5130,12 +5141,6 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
err = set_power_wells(power_domains, tgl_power_wells);
} else if (DISPLAY_VER(dev_priv) == 11) {
err = set_power_wells(power_domains, icl_power_wells);
- } else if (IS_CNL_WITH_PORT_F(dev_priv)) {
- err = set_power_wells(power_domains, cnl_power_wells);
- } else if (IS_CANNONLAKE(dev_priv)) {
- err = set_power_wells_mask(power_domains, cnl_power_wells,
- BIT_ULL(CNL_DISP_PW_DDI_F_IO) |
- BIT_ULL(CNL_DISP_PW_DDI_F_AUX));
} else if (IS_GEMINILAKE(dev_priv)) {
err = set_power_wells(power_domains, glk_power_wells);
} else if (IS_BROXTON(dev_priv)) {
@@ -5690,75 +5695,6 @@ static void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
usleep_range(10, 30); /* 10 us delay per Bspec */
}
-static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume)
-{
- struct i915_power_domains *power_domains = &dev_priv->power_domains;
- struct i915_power_well *well;
-
- gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
-
- /* 1. Enable PCH Reset Handshake */
- intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
-
- if (!HAS_DISPLAY(dev_priv))
- return;
-
- /* 2-3. */
- intel_combo_phy_init(dev_priv);
-
- /*
- * 4. Enable Power Well 1 (PG1).
- * The AUX IO power wells will be enabled on demand.
- */
- mutex_lock(&power_domains->lock);
- well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
- intel_power_well_enable(dev_priv, well);
- mutex_unlock(&power_domains->lock);
-
- /* 5. Enable CD clock */
- intel_cdclk_init_hw(dev_priv);
-
- /* 6. Enable DBUF */
- gen9_dbuf_enable(dev_priv);
-
- if (resume && intel_dmc_has_payload(dev_priv))
- intel_dmc_load_program(dev_priv);
-}
-
-static void cnl_display_core_uninit(struct drm_i915_private *dev_priv)
-{
- struct i915_power_domains *power_domains = &dev_priv->power_domains;
- struct i915_power_well *well;
-
- if (!HAS_DISPLAY(dev_priv))
- return;
-
- gen9_disable_dc_states(dev_priv);
-
- /* 1. Disable all display engine functions -> aready done */
-
- /* 2. Disable DBUF */
- gen9_dbuf_disable(dev_priv);
-
- /* 3. Disable CD clock */
- intel_cdclk_uninit_hw(dev_priv);
-
- /*
- * 4. Disable Power Well 1 (PG1).
- * The AUX IO power wells are toggled on demand, so they are already
- * disabled at this point.
- */
- mutex_lock(&power_domains->lock);
- well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
- intel_power_well_disable(dev_priv, well);
- mutex_unlock(&power_domains->lock);
-
- usleep_range(10, 30); /* 10 us delay per Bspec */
-
- /* 5. */
- intel_combo_phy_uninit(dev_priv);
-}
-
struct buddy_page_mask {
u32 page_mask;
u8 type;
@@ -5797,9 +5733,14 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv)
unsigned long abox_mask = INTEL_INFO(dev_priv)->abox_mask;
int config, i;
+ /* BW_BUDDY registers are not used on dgpu's beyond DG1 */
+ if (IS_DGFX(dev_priv) && !IS_DG1(dev_priv))
+ return;
+
if (IS_ALDERLAKE_S(dev_priv) ||
- IS_DG1_REVID(dev_priv, DG1_REVID_A0, DG1_REVID_A0) ||
- IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
+ IS_DG1_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) ||
+ IS_RKL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) ||
+ IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0))
/* Wa_1409767108:tgl,dg1,adl-s */
table = wa_1409767108_buddy_page_masks;
else
@@ -5821,10 +5762,11 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv)
intel_de_write(dev_priv, BW_BUDDY_PAGE_MASK(i),
table[config].page_mask);
- /* Wa_22010178259:tgl,rkl */
- intel_de_rmw(dev_priv, BW_BUDDY_CTL(i),
- BW_BUDDY_TLB_REQ_TIMER_MASK,
- BW_BUDDY_TLB_REQ_TIMER(0x8));
+ /* Wa_22010178259:tgl,dg1,rkl,adl-s */
+ if (DISPLAY_VER(dev_priv) == 12)
+ intel_de_rmw(dev_priv, BW_BUDDY_CTL(i),
+ BW_BUDDY_TLB_REQ_TIMER_MASK,
+ BW_BUDDY_TLB_REQ_TIMER(0x8));
}
}
}
@@ -5878,11 +5820,15 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
if (DISPLAY_VER(dev_priv) >= 12)
tgl_bw_buddy_init(dev_priv);
+ /* 8. Ensure PHYs have completed calibration and adaptation */
+ if (IS_DG2(dev_priv))
+ intel_snps_phy_wait_for_calibration(dev_priv);
+
if (resume && intel_dmc_has_payload(dev_priv))
intel_dmc_load_program(dev_priv);
- /* Wa_14011508470 */
- if (DISPLAY_VER(dev_priv) == 12) {
+ /* Wa_14011508470:tgl,dg1,rkl,adl-s,adl-p */
+ if (DISPLAY_VER(dev_priv) >= 12) {
val = DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM |
DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR;
intel_uncore_rmw(&dev_priv->uncore, GEN11_CHICKEN_DCPR_2, 0, val);
@@ -6097,8 +6043,6 @@ void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
if (DISPLAY_VER(i915) >= 11) {
icl_display_core_init(i915, resume);
- } else if (IS_CANNONLAKE(i915)) {
- cnl_display_core_init(i915, resume);
} else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
bxt_display_core_init(i915, resume);
} else if (DISPLAY_VER(i915) == 9) {
@@ -6258,8 +6202,6 @@ void intel_power_domains_suspend(struct drm_i915_private *i915,
if (DISPLAY_VER(i915) >= 11)
icl_display_core_uninit(i915);
- else if (IS_CANNONLAKE(i915))
- cnl_display_core_uninit(i915);
else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
bxt_display_core_uninit(i915);
else if (DISPLAY_VER(i915) == 9)
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
index 4f0917df4375..978531841fa3 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -76,7 +76,8 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_PORT_OTHER,
POWER_DOMAIN_VGA,
- POWER_DOMAIN_AUDIO,
+ POWER_DOMAIN_AUDIO_MMIO,
+ POWER_DOMAIN_AUDIO_PLAYBACK,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
@@ -142,8 +143,6 @@ enum i915_power_well_id {
SKL_DISP_PW_MISC_IO,
SKL_DISP_PW_1,
SKL_DISP_PW_2,
- CNL_DISP_PW_DDI_F_IO,
- CNL_DISP_PW_DDI_F_AUX,
ICL_DISP_PW_3,
SKL_DISP_DC_OFF,
TGL_DISP_PW_TC_COLD_OFF,
@@ -223,6 +222,12 @@ struct i915_power_well_desc {
u8 idx;
/* Mask of pipes whose IRQ logic is backed by the pw */
u8 irq_pipe_mask;
+ /*
+ * Instead of waiting for the status bit to ack enables,
+ * just wait a specific amount of time and then consider
+ * the well enabled.
+ */
+ u16 fixed_enable_delay;
/* The pw is backing the VGA functionality */
bool has_vga:1;
bool has_fuses:1;
@@ -386,6 +391,10 @@ intel_display_power_put_all_in_set(struct drm_i915_private *i915,
intel_display_power_put_mask_in_set(i915, power_domain_set, power_domain_set->mask);
}
+/*
+ * FIXME: We should probably switch this to a 0-based scheme to be consistent
+ * with how we now name/number DBUF_CTL instances.
+ */
enum dbuf_slice {
DBUF_S1,
DBUF_S2,
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 04613864cbe8..6beeeeba1bed 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -48,6 +48,7 @@
struct drm_printer;
struct __intel_global_objs_state;
+struct intel_ddi_buf_trans;
/*
* Display related stuff
@@ -195,6 +196,10 @@ struct intel_encoder {
void (*update_complete)(struct intel_atomic_state *,
struct intel_encoder *,
struct intel_crtc *);
+ void (*pre_disable)(struct intel_atomic_state *,
+ struct intel_encoder *,
+ const struct intel_crtc_state *,
+ const struct drm_connector_state *);
void (*disable)(struct intel_atomic_state *,
struct intel_encoder *,
const struct intel_crtc_state *,
@@ -263,6 +268,9 @@ struct intel_encoder {
* Returns whether the port clock is enabled or not.
*/
bool (*is_clock_enabled)(struct intel_encoder *encoder);
+ const struct intel_ddi_buf_trans *(*get_buf_trans)(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries);
enum hpd_pin hpd_pin;
enum intel_display_power_domain power_domain;
/* for communication with audio component; protected by av_mutex */
@@ -310,7 +318,7 @@ struct intel_panel {
/* DPCD backlight */
union {
struct {
- u8 pwmgen_bit_count;
+ struct drm_edp_backlight_info info;
} vesa;
struct {
bool sdr_uses_aux;
@@ -880,6 +888,18 @@ enum intel_output_format {
INTEL_OUTPUT_FORMAT_YCBCR444,
};
+struct intel_mpllb_state {
+ u32 clock; /* in KHz */
+ u32 ref_control;
+ u32 mpllb_cp;
+ u32 mpllb_div;
+ u32 mpllb_div2;
+ u32 mpllb_fracn1;
+ u32 mpllb_fracn2;
+ u32 mpllb_sscen;
+ u32 mpllb_sscstep;
+};
+
struct intel_crtc_state {
/*
* uapi (drm) state. This is the software state shown to userspace.
@@ -1014,7 +1034,10 @@ struct intel_crtc_state {
struct intel_shared_dpll *shared_dpll;
/* Actual register state of the dpll, for shared dpll cross-checking. */
- struct intel_dpll_hw_state dpll_hw_state;
+ union {
+ struct intel_dpll_hw_state dpll_hw_state;
+ struct intel_mpllb_state mpllb_state;
+ };
/*
* ICL reserved DPLLs for the CRTC/port. The active PLL is selected by
@@ -1040,7 +1063,9 @@ struct intel_crtc_state {
bool has_psr;
bool has_psr2;
bool enable_psr2_sel_fetch;
+ bool req_psr2_sdp_prior_scanline;
u32 dc3co_exitline;
+ u16 su_y_granularity;
/*
* Frequence the dpll for the port should run at. Differs from the
@@ -1493,12 +1518,14 @@ struct intel_psr {
bool colorimetry_support;
bool psr2_enabled;
bool psr2_sel_fetch_enabled;
+ bool req_psr2_sdp_prior_scanline;
u8 sink_sync_latency;
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
bool irq_aux_error;
- u16 su_x_granularity;
+ u16 su_w_granularity;
+ u16 su_y_granularity;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
@@ -1604,6 +1631,7 @@ struct intel_dp {
/* Display stream compression testing */
bool force_dsc_en;
+ int force_dsc_bpp;
bool hobl_failed;
bool hobl_active;
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 97308da28059..3c3c6cb5c0df 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -45,6 +45,10 @@
#define GEN12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE
+#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 10)
+#define ADLP_DMC_VERSION_REQUIRED DMC_VERSION(2, 10)
+MODULE_FIRMWARE(ADLP_DMC_PATH);
+
#define ADLS_DMC_PATH DMC_PATH(adls, 2, 01)
#define ADLS_DMC_VERSION_REQUIRED DMC_VERSION(2, 1)
MODULE_FIRMWARE(ADLS_DMC_PATH);
@@ -53,12 +57,12 @@ MODULE_FIRMWARE(ADLS_DMC_PATH);
#define DG1_DMC_VERSION_REQUIRED DMC_VERSION(2, 2)
MODULE_FIRMWARE(DG1_DMC_PATH);
-#define RKL_DMC_PATH DMC_PATH(rkl, 2, 02)
-#define RKL_DMC_VERSION_REQUIRED DMC_VERSION(2, 2)
+#define RKL_DMC_PATH DMC_PATH(rkl, 2, 03)
+#define RKL_DMC_VERSION_REQUIRED DMC_VERSION(2, 3)
MODULE_FIRMWARE(RKL_DMC_PATH);
-#define TGL_DMC_PATH DMC_PATH(tgl, 2, 08)
-#define TGL_DMC_VERSION_REQUIRED DMC_VERSION(2, 8)
+#define TGL_DMC_PATH DMC_PATH(tgl, 2, 12)
+#define TGL_DMC_VERSION_REQUIRED DMC_VERSION(2, 12)
MODULE_FIRMWARE(TGL_DMC_PATH);
#define ICL_DMC_PATH DMC_PATH(icl, 1, 09)
@@ -66,11 +70,6 @@ MODULE_FIRMWARE(TGL_DMC_PATH);
#define ICL_DMC_MAX_FW_SIZE 0x6000
MODULE_FIRMWARE(ICL_DMC_PATH);
-#define CNL_DMC_PATH DMC_PATH(cnl, 1, 07)
-#define CNL_DMC_VERSION_REQUIRED DMC_VERSION(1, 7)
-#define CNL_DMC_MAX_FW_SIZE GLK_DMC_MAX_FW_SIZE
-MODULE_FIRMWARE(CNL_DMC_PATH);
-
#define GLK_DMC_PATH DMC_PATH(glk, 1, 04)
#define GLK_DMC_VERSION_REQUIRED DMC_VERSION(1, 4)
#define GLK_DMC_MAX_FW_SIZE 0x4000
@@ -96,6 +95,7 @@ MODULE_FIRMWARE(BXT_DMC_PATH);
#define PACKAGE_V2_MAX_FW_INFO_ENTRIES 32
#define DMC_V1_MAX_MMIO_COUNT 8
#define DMC_V3_MAX_MMIO_COUNT 20
+#define DMC_V1_MMIO_START_RANGE 0x80000
struct intel_css_header {
/* 0x09 for DMC */
@@ -239,53 +239,18 @@ struct stepping_info {
bool intel_dmc_has_payload(struct drm_i915_private *i915)
{
- return i915->dmc.dmc_payload;
+ return i915->dmc.dmc_info[DMC_FW_MAIN].payload;
}
-static const struct stepping_info skl_stepping_info[] = {
- {'A', '0'}, {'B', '0'}, {'C', '0'},
- {'D', '0'}, {'E', '0'}, {'F', '0'},
- {'G', '0'}, {'H', '0'}, {'I', '0'},
- {'J', '0'}, {'K', '0'}
-};
-
-static const struct stepping_info bxt_stepping_info[] = {
- {'A', '0'}, {'A', '1'}, {'A', '2'},
- {'B', '0'}, {'B', '1'}, {'B', '2'}
-};
-
-static const struct stepping_info icl_stepping_info[] = {
- {'A', '0'}, {'A', '1'}, {'A', '2'},
- {'B', '0'}, {'B', '2'},
- {'C', '0'}
-};
-
-static const struct stepping_info no_stepping_info = { '*', '*' };
-
static const struct stepping_info *
-intel_get_stepping_info(struct drm_i915_private *dev_priv)
+intel_get_stepping_info(struct drm_i915_private *i915,
+ struct stepping_info *si)
{
- const struct stepping_info *si;
- unsigned int size;
-
- if (IS_ICELAKE(dev_priv)) {
- size = ARRAY_SIZE(icl_stepping_info);
- si = icl_stepping_info;
- } else if (IS_SKYLAKE(dev_priv)) {
- size = ARRAY_SIZE(skl_stepping_info);
- si = skl_stepping_info;
- } else if (IS_BROXTON(dev_priv)) {
- size = ARRAY_SIZE(bxt_stepping_info);
- si = bxt_stepping_info;
- } else {
- size = 0;
- si = NULL;
- }
-
- if (INTEL_REVID(dev_priv) < size)
- return si + INTEL_REVID(dev_priv);
+ const char *step_name = intel_step_name(RUNTIME_INFO(i915)->step.display_step);
- return &no_stepping_info;
+ si->stepping = step_name[0];
+ si->substepping = step_name[1];
+ return si;
}
static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
@@ -316,8 +281,8 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
*/
void intel_dmc_load_program(struct drm_i915_private *dev_priv)
{
- u32 *payload = dev_priv->dmc.dmc_payload;
- u32 i, fw_size;
+ struct intel_dmc *dmc = &dev_priv->dmc;
+ u32 id, i;
if (!HAS_DMC(dev_priv)) {
drm_err(&dev_priv->drm,
@@ -325,26 +290,31 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv)
return;
}
- if (!intel_dmc_has_payload(dev_priv)) {
+ if (!dev_priv->dmc.dmc_info[DMC_FW_MAIN].payload) {
drm_err(&dev_priv->drm,
"Tried to program CSR with empty payload\n");
return;
}
- fw_size = dev_priv->dmc.dmc_fw_size;
assert_rpm_wakelock_held(&dev_priv->runtime_pm);
preempt_disable();
- for (i = 0; i < fw_size; i++)
- intel_uncore_write_fw(&dev_priv->uncore, DMC_PROGRAM(i),
- payload[i]);
+ for (id = 0; id < DMC_FW_MAX; id++) {
+ for (i = 0; i < dmc->dmc_info[id].dmc_fw_size; i++) {
+ intel_uncore_write_fw(&dev_priv->uncore,
+ DMC_PROGRAM(dmc->dmc_info[id].start_mmioaddr, i),
+ dmc->dmc_info[id].payload[i]);
+ }
+ }
preempt_enable();
- for (i = 0; i < dev_priv->dmc.mmio_count; i++) {
- intel_de_write(dev_priv, dev_priv->dmc.mmioaddr[i],
- dev_priv->dmc.mmiodata[i]);
+ for (id = 0; id < DMC_FW_MAX; id++) {
+ for (i = 0; i < dmc->dmc_info[id].mmio_count; i++) {
+ intel_de_write(dev_priv, dmc->dmc_info[id].mmioaddr[i],
+ dmc->dmc_info[id].mmiodata[i]);
+ }
}
dev_priv->dmc.dc_state = 0;
@@ -352,62 +322,72 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv)
gen9_set_dc_state_debugmask(dev_priv);
}
+static bool fw_info_matches_stepping(const struct intel_fw_info *fw_info,
+ const struct stepping_info *si)
+{
+ if ((fw_info->substepping == '*' && si->stepping == fw_info->stepping) ||
+ (si->stepping == fw_info->stepping && si->substepping == fw_info->substepping) ||
+ /*
+ * If we don't find a more specific one from above two checks, we
+ * then check for the generic one to be sure to work even with
+ * "broken firmware"
+ */
+ (si->stepping == '*' && si->substepping == fw_info->substepping) ||
+ (fw_info->stepping == '*' && fw_info->substepping == '*'))
+ return true;
+
+ return false;
+}
+
/*
* Search fw_info table for dmc_offset to find firmware binary: num_entries is
* already sanitized.
*/
-static u32 find_dmc_fw_offset(const struct intel_fw_info *fw_info,
+static void dmc_set_fw_offset(struct intel_dmc *dmc,
+ const struct intel_fw_info *fw_info,
unsigned int num_entries,
const struct stepping_info *si,
u8 package_ver)
{
- u32 dmc_offset = DMC_DEFAULT_FW_OFFSET;
- unsigned int i;
+ unsigned int i, id;
+
+ struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc);
for (i = 0; i < num_entries; i++) {
- if (package_ver > 1 && fw_info[i].dmc_id != 0)
- continue;
+ id = package_ver <= 1 ? DMC_FW_MAIN : fw_info[i].dmc_id;
- if (fw_info[i].substepping == '*' &&
- si->stepping == fw_info[i].stepping) {
- dmc_offset = fw_info[i].offset;
- break;
+ if (id >= DMC_FW_MAX) {
+ drm_dbg(&i915->drm, "Unsupported firmware id: %u\n", id);
+ continue;
}
- if (si->stepping == fw_info[i].stepping &&
- si->substepping == fw_info[i].substepping) {
- dmc_offset = fw_info[i].offset;
- break;
- }
+ /* More specific versions come first, so we don't even have to
+ * check for the stepping since we already found a previous FW
+ * for this id.
+ */
+ if (dmc->dmc_info[id].present)
+ continue;
- if (fw_info[i].stepping == '*' &&
- fw_info[i].substepping == '*') {
- /*
- * In theory we should stop the search as generic
- * entries should always come after the more specific
- * ones, but let's continue to make sure to work even
- * with "broken" firmwares. If we don't find a more
- * specific one, then we use this entry
- */
- dmc_offset = fw_info[i].offset;
+ if (fw_info_matches_stepping(&fw_info[i], si)) {
+ dmc->dmc_info[id].present = true;
+ dmc->dmc_info[id].dmc_offset = fw_info[i].offset;
}
}
-
- return dmc_offset;
}
static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
const struct intel_dmc_header_base *dmc_header,
- size_t rem_size)
+ size_t rem_size, u8 dmc_id)
{
struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc);
+ struct dmc_fw_info *dmc_info = &dmc->dmc_info[dmc_id];
unsigned int header_len_bytes, dmc_header_size, payload_size, i;
const u32 *mmioaddr, *mmiodata;
- u32 mmio_count, mmio_count_max;
+ u32 mmio_count, mmio_count_max, start_mmioaddr;
u8 *payload;
- BUILD_BUG_ON(ARRAY_SIZE(dmc->mmioaddr) < DMC_V3_MAX_MMIO_COUNT ||
- ARRAY_SIZE(dmc->mmioaddr) < DMC_V1_MAX_MMIO_COUNT);
+ BUILD_BUG_ON(ARRAY_SIZE(dmc_info->mmioaddr) < DMC_V3_MAX_MMIO_COUNT ||
+ ARRAY_SIZE(dmc_info->mmioaddr) < DMC_V1_MAX_MMIO_COUNT);
/*
* Check if we can access common fields, we will checkc again below
@@ -430,6 +410,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
mmio_count_max = DMC_V3_MAX_MMIO_COUNT;
/* header_len is in dwords */
header_len_bytes = dmc_header->header_len * 4;
+ start_mmioaddr = v3->start_mmioaddr;
dmc_header_size = sizeof(*v3);
} else if (dmc_header->header_ver == 1) {
const struct intel_dmc_header_v1 *v1 =
@@ -443,6 +424,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
mmio_count = v1->mmio_count;
mmio_count_max = DMC_V1_MAX_MMIO_COUNT;
header_len_bytes = dmc_header->header_len;
+ start_mmioaddr = DMC_V1_MMIO_START_RANGE;
dmc_header_size = sizeof(*v1);
} else {
drm_err(&i915->drm, "Unknown DMC fw header version: %u\n",
@@ -463,16 +445,11 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
}
for (i = 0; i < mmio_count; i++) {
- if (mmioaddr[i] < DMC_MMIO_START_RANGE ||
- mmioaddr[i] > DMC_MMIO_END_RANGE) {
- drm_err(&i915->drm, "DMC firmware has wrong mmio address 0x%x\n",
- mmioaddr[i]);
- return 0;
- }
- dmc->mmioaddr[i] = _MMIO(mmioaddr[i]);
- dmc->mmiodata[i] = mmiodata[i];
+ dmc_info->mmioaddr[i] = _MMIO(mmioaddr[i]);
+ dmc_info->mmiodata[i] = mmiodata[i];
}
- dmc->mmio_count = mmio_count;
+ dmc_info->mmio_count = mmio_count;
+ dmc_info->start_mmioaddr = start_mmioaddr;
rem_size -= header_len_bytes;
@@ -485,14 +462,14 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
drm_err(&i915->drm, "DMC FW too big (%u bytes)\n", payload_size);
return 0;
}
- dmc->dmc_fw_size = dmc_header->fw_size;
+ dmc_info->dmc_fw_size = dmc_header->fw_size;
- dmc->dmc_payload = kmalloc(payload_size, GFP_KERNEL);
- if (!dmc->dmc_payload)
+ dmc_info->payload = kmalloc(payload_size, GFP_KERNEL);
+ if (!dmc_info->payload)
return 0;
payload = (u8 *)(dmc_header) + header_len_bytes;
- memcpy(dmc->dmc_payload, payload, payload_size);
+ memcpy(dmc_info->payload, payload, payload_size);
return header_len_bytes + payload_size;
@@ -509,7 +486,7 @@ parse_dmc_fw_package(struct intel_dmc *dmc,
{
struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc);
u32 package_size = sizeof(struct intel_package_header);
- u32 num_entries, max_entries, dmc_offset;
+ u32 num_entries, max_entries;
const struct intel_fw_info *fw_info;
if (rem_size < package_size)
@@ -545,16 +522,11 @@ parse_dmc_fw_package(struct intel_dmc *dmc,
fw_info = (const struct intel_fw_info *)
((u8 *)package_header + sizeof(*package_header));
- dmc_offset = find_dmc_fw_offset(fw_info, num_entries, si,
- package_header->header_ver);
- if (dmc_offset == DMC_DEFAULT_FW_OFFSET) {
- drm_err(&i915->drm, "DMC firmware not supported for %c stepping\n",
- si->stepping);
- return 0;
- }
+ dmc_set_fw_offset(dmc, fw_info, num_entries, si,
+ package_header->header_ver);
/* dmc_offset is in dwords */
- return package_size + dmc_offset * 4;
+ return package_size;
error_truncated:
drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n");
@@ -604,9 +576,11 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv,
struct intel_package_header *package_header;
struct intel_dmc_header_base *dmc_header;
struct intel_dmc *dmc = &dev_priv->dmc;
- const struct stepping_info *si = intel_get_stepping_info(dev_priv);
+ struct stepping_info display_info = { '*', '*'};
+ const struct stepping_info *si = intel_get_stepping_info(dev_priv, &display_info);
u32 readcount = 0;
- u32 r;
+ u32 r, offset;
+ int id;
if (!fw)
return;
@@ -627,9 +601,19 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv,
readcount += r;
- /* Extract dmc_header information */
- dmc_header = (struct intel_dmc_header_base *)&fw->data[readcount];
- parse_dmc_fw_header(dmc, dmc_header, fw->size - readcount);
+ for (id = 0; id < DMC_FW_MAX; id++) {
+ if (!dev_priv->dmc.dmc_info[id].present)
+ continue;
+
+ offset = readcount + dmc->dmc_info[id].dmc_offset * 4;
+ if (fw->size - offset < 0) {
+ drm_err(&dev_priv->drm, "Reading beyond the fw_size\n");
+ continue;
+ }
+
+ dmc_header = (struct intel_dmc_header_base *)&fw->data[offset];
+ parse_dmc_fw_header(dmc, dmc_header, fw->size - offset, id);
+ }
}
static void intel_dmc_runtime_pm_get(struct drm_i915_private *dev_priv)
@@ -705,7 +689,11 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv)
*/
intel_dmc_runtime_pm_get(dev_priv);
- if (IS_ALDERLAKE_S(dev_priv)) {
+ if (IS_ALDERLAKE_P(dev_priv)) {
+ dmc->fw_path = ADLP_DMC_PATH;
+ dmc->required_version = ADLP_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = GEN12_DMC_MAX_FW_SIZE;
+ } else if (IS_ALDERLAKE_S(dev_priv)) {
dmc->fw_path = ADLS_DMC_PATH;
dmc->required_version = ADLS_DMC_VERSION_REQUIRED;
dmc->max_fw_size = GEN12_DMC_MAX_FW_SIZE;
@@ -725,10 +713,6 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv)
dmc->fw_path = ICL_DMC_PATH;
dmc->required_version = ICL_DMC_VERSION_REQUIRED;
dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE;
- } else if (IS_CANNONLAKE(dev_priv)) {
- dmc->fw_path = CNL_DMC_PATH;
- dmc->required_version = CNL_DMC_VERSION_REQUIRED;
- dmc->max_fw_size = CNL_DMC_MAX_FW_SIZE;
} else if (IS_GEMINILAKE(dev_priv)) {
dmc->fw_path = GLK_DMC_PATH;
dmc->required_version = GLK_DMC_VERSION_REQUIRED;
@@ -827,5 +811,5 @@ void intel_dmc_ucode_fini(struct drm_i915_private *dev_priv)
intel_dmc_ucode_suspend(dev_priv);
drm_WARN_ON(&dev_priv->drm, dev_priv->dmc.wakeref);
- kfree(dev_priv->dmc.dmc_payload);
+ kfree(dev_priv->dmc.dmc_info[DMC_FW_MAIN].payload);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h
index 4c22f567b61b..c3c00ff03869 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.h
+++ b/drivers/gpu/drm/i915/display/intel_dmc.h
@@ -16,17 +16,30 @@ struct drm_i915_private;
#define DMC_VERSION_MAJOR(version) ((version) >> 16)
#define DMC_VERSION_MINOR(version) ((version) & 0xffff)
+enum {
+ DMC_FW_MAIN = 0,
+ DMC_FW_PIPEA,
+ DMC_FW_PIPEB,
+ DMC_FW_MAX
+};
+
struct intel_dmc {
struct work_struct work;
const char *fw_path;
u32 required_version;
u32 max_fw_size; /* bytes */
- u32 *dmc_payload;
- u32 dmc_fw_size; /* dwords */
u32 version;
- u32 mmio_count;
- i915_reg_t mmioaddr[20];
- u32 mmiodata[20];
+ struct dmc_fw_info {
+ u32 mmio_count;
+ i915_reg_t mmioaddr[20];
+ u32 mmiodata[20];
+ u32 dmc_offset;
+ u32 start_mmioaddr;
+ u32 dmc_fw_size; /*dwords */
+ u32 *payload;
+ bool present;
+ } dmc_info[DMC_FW_MAX];
+
u32 dc_state;
u32 target_dc_state;
u32 allowed_dc_mask;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 862c1df69cc2..04175f359fd6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -222,29 +222,6 @@ bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
encoder->port != PORT_A);
}
-static int cnl_max_source_rate(struct intel_dp *intel_dp)
-{
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
- enum port port = dig_port->base.port;
-
- u32 voltage = intel_de_read(dev_priv, CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK;
-
- /* Low voltage SKUs are limited to max of 5.4G */
- if (voltage == VOLTAGE_INFO_0_85V)
- return 540000;
-
- /* For this SKU 8.1G is supported in all ports */
- if (IS_CNL_WITH_PORT_F(dev_priv))
- return 810000;
-
- /* For other SKUs, max rate on ports A and D is 5.4G */
- if (port == PORT_A || port == PORT_D)
- return 540000;
-
- return 810000;
-}
-
static int icl_max_source_rate(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -270,7 +247,7 @@ static void
intel_dp_set_source_rates(struct intel_dp *intel_dp)
{
/* The values must be in increasing order */
- static const int cnl_rates[] = {
+ static const int icl_rates[] = {
162000, 216000, 270000, 324000, 432000, 540000, 648000, 810000
};
static const int bxt_rates[] = {
@@ -295,12 +272,10 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
drm_WARN_ON(&dev_priv->drm,
intel_dp->source_rates || intel_dp->num_source_rates);
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
- source_rates = cnl_rates;
- size = ARRAY_SIZE(cnl_rates);
- if (DISPLAY_VER(dev_priv) == 10)
- max_rate = cnl_max_source_rate(intel_dp);
- else if (IS_JSL_EHL(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 11) {
+ source_rates = icl_rates;
+ size = ARRAY_SIZE(icl_rates);
+ if (IS_JSL_EHL(dev_priv))
max_rate = ehl_max_source_rate(intel_dp);
else
max_rate = icl_max_source_rate(intel_dp);
@@ -1274,6 +1249,23 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
pipe_config->pipe_bpp);
pipe_config->dsc.slice_count = dsc_dp_slice_count;
}
+
+ /* As of today we support DSC for only RGB */
+ if (intel_dp->force_dsc_bpp) {
+ if (intel_dp->force_dsc_bpp >= 8 &&
+ intel_dp->force_dsc_bpp < pipe_bpp) {
+ drm_dbg_kms(&dev_priv->drm,
+ "DSC BPP forced to %d",
+ intel_dp->force_dsc_bpp);
+ pipe_config->dsc.compressed_bpp =
+ intel_dp->force_dsc_bpp;
+ } else {
+ drm_dbg_kms(&dev_priv->drm,
+ "Invalid DSC BPP %d",
+ intel_dp->force_dsc_bpp);
+ }
+ }
+
/*
* VDSC engine operates at 1 Pixel per clock, so if peak pixel rate
* is greater than the maximum Cdclock and if slice count is even
@@ -3031,9 +3023,6 @@ void intel_read_dp_sdp(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
unsigned int type)
{
- if (encoder->type != INTEL_OUTPUT_DDI)
- return;
-
switch (type) {
case DP_SDP_VSC:
intel_read_dp_vsc_sdp(encoder, crtc_state,
@@ -3342,6 +3331,9 @@ static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
intel_dp_autotest_phy_ddi_enable(intel_dp, crtc_state);
+ drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
+ intel_dp->train_set, crtc_state->lane_count);
+
drm_dp_set_phy_test_pattern(&intel_dp->aux, data,
link_status[DP_DPCD_REV]);
}
@@ -4736,7 +4728,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv,
int refresh_rate)
{
struct intel_dp *intel_dp = dev_priv->drrs.dp;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
if (refresh_rate <= 0) {
@@ -4750,7 +4742,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv,
return;
}
- if (!intel_crtc) {
+ if (!crtc) {
drm_dbg_kms(&dev_priv->drm,
"DRRS: intel_crtc not initialized\n");
return;
@@ -5233,7 +5225,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
- intel_connector->panel.backlight.power = intel_pps_backlight_power;
+ if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK))
+ intel_connector->panel.backlight.power = intel_pps_backlight_power;
intel_panel_setup_backlight(connector, pipe);
if (fixed_mode) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 7c048d2ecf43..f483f479dd0b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -158,7 +158,6 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
/*
* Max timeout values:
* SKL-GLK: 1.6ms
- * CNL: 3.2ms
* ICL+: 4ms
*/
ret = DP_AUX_CH_CTL_SEND_BUSY |
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
index 8e9ac9ba1d38..6ac568617ef3 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -107,7 +107,7 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector)
u8 tcon_cap[4];
ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap));
- if (ret < 0)
+ if (ret != sizeof(tcon_cap))
return false;
if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP))
@@ -137,7 +137,7 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe
u8 tmp;
u8 buf[2] = { 0 };
- if (drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp) < 0) {
+ if (drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp) != 1) {
drm_err(&i915->drm, "Failed to read current backlight mode from DPCD\n");
return 0;
}
@@ -153,7 +153,8 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe
return panel->backlight.max;
}
- if (drm_dp_dpcd_read(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, sizeof(buf)) < 0) {
+ if (drm_dp_dpcd_read(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf,
+ sizeof(buf)) != sizeof(buf)) {
drm_err(&i915->drm, "Failed to read brightness from DPCD\n");
return 0;
}
@@ -172,7 +173,8 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state,
buf[0] = level & 0xFF;
buf[1] = (level & 0xFF00) >> 8;
- if (drm_dp_dpcd_write(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, 4) < 0)
+ if (drm_dp_dpcd_write(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf,
+ sizeof(buf)) != sizeof(buf))
drm_err(dev, "Failed to write brightness level to DPCD\n");
}
@@ -203,7 +205,7 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state,
u8 old_ctrl, ctrl;
ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl);
- if (ret < 0) {
+ if (ret != 1) {
drm_err(&i915->drm, "Failed to read current backlight control mode: %d\n", ret);
return;
}
@@ -221,7 +223,7 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state,
}
if (ctrl != old_ctrl)
- if (drm_dp_dpcd_writeb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) < 0)
+ if (drm_dp_dpcd_writeb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) != 1)
drm_err(&i915->drm, "Failed to configure DPCD brightness controls\n");
}
@@ -268,153 +270,19 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi
}
/* VESA backlight callbacks */
-static void set_vesa_backlight_enable(struct intel_dp *intel_dp, bool enable)
-{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- u8 reg_val = 0;
-
- /* Early return when display use other mechanism to enable backlight. */
- if (!(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP))
- return;
-
- if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER,
- &reg_val) < 0) {
- drm_dbg_kms(&i915->drm, "Failed to read DPCD register 0x%x\n",
- DP_EDP_DISPLAY_CONTROL_REGISTER);
- return;
- }
- if (enable)
- reg_val |= DP_EDP_BACKLIGHT_ENABLE;
- else
- reg_val &= ~(DP_EDP_BACKLIGHT_ENABLE);
-
- if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER,
- reg_val) != 1) {
- drm_dbg_kms(&i915->drm, "Failed to %s aux backlight\n",
- enabledisable(enable));
- }
-}
-
-static bool intel_dp_aux_vesa_backlight_dpcd_mode(struct intel_connector *connector)
-{
- struct intel_dp *intel_dp = intel_attached_dp(connector);
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- u8 mode_reg;
-
- if (drm_dp_dpcd_readb(&intel_dp->aux,
- DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
- &mode_reg) != 1) {
- drm_dbg_kms(&i915->drm,
- "Failed to read the DPCD register 0x%x\n",
- DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
- return false;
- }
-
- return (mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) ==
- DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD;
-}
-
-/*
- * Read the current backlight value from DPCD register(s) based
- * on if 8-bit(MSB) or 16-bit(MSB and LSB) values are supported
- */
static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, enum pipe unused)
{
- struct intel_dp *intel_dp = intel_attached_dp(connector);
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- u8 read_val[2] = { 0x0 };
- u16 level = 0;
-
- /*
- * If we're not in DPCD control mode yet, the programmed brightness
- * value is meaningless and we should assume max brightness
- */
- if (!intel_dp_aux_vesa_backlight_dpcd_mode(connector))
- return connector->panel.backlight.max;
-
- if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
- &read_val, sizeof(read_val)) < 0) {
- drm_dbg_kms(&i915->drm, "Failed to read DPCD register 0x%x\n",
- DP_EDP_BACKLIGHT_BRIGHTNESS_MSB);
- return 0;
- }
- level = read_val[0];
- if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
- level = (read_val[0] << 8 | read_val[1]);
-
- return level;
+ return connector->panel.backlight.level;
}
-/*
- * Sends the current backlight level over the aux channel, checking if its using
- * 8-bit or 16 bit value (MSB and LSB)
- */
static void
-intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state,
- u32 level)
+intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
- struct intel_dp *intel_dp = intel_attached_dp(connector);
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- u8 vals[2] = { 0x0 };
-
- vals[0] = level;
-
- /* Write the MSB and/or LSB */
- if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) {
- vals[0] = (level & 0xFF00) >> 8;
- vals[1] = (level & 0xFF);
- }
- if (drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
- vals, sizeof(vals)) < 0) {
- drm_dbg_kms(&i915->drm,
- "Failed to write aux backlight level\n");
- return;
- }
-}
-
-/*
- * Set PWM Frequency divider to match desired frequency in vbt.
- * The PWM Frequency is calculated as 27Mhz / (F x P).
- * - Where F = PWM Frequency Pre-Divider value programmed by field 7:0 of the
- * EDP_BACKLIGHT_FREQ_SET register (DPCD Address 00728h)
- * - Where P = 2^Pn, where Pn is the value programmed by field 4:0 of the
- * EDP_PWMGEN_BIT_COUNT register (DPCD Address 00724h)
- */
-static bool intel_dp_aux_vesa_set_pwm_freq(struct intel_connector *connector)
-{
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct intel_dp *intel_dp = intel_attached_dp(connector);
- const u8 pn = connector->panel.backlight.edp.vesa.pwmgen_bit_count;
- int freq, fxp, f, fxp_actual, fxp_min, fxp_max;
-
- freq = dev_priv->vbt.backlight.pwm_freq_hz;
- if (!freq) {
- drm_dbg_kms(&dev_priv->drm,
- "Use panel default backlight frequency\n");
- return false;
- }
-
- fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq);
- f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
- fxp_actual = f << pn;
-
- /* Ensure frequency is within 25% of desired value */
- fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
- fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
-
- if (fxp_min > fxp_actual || fxp_actual > fxp_max) {
- drm_dbg_kms(&dev_priv->drm, "Actual frequency out of range\n");
- return false;
- }
+ struct intel_panel *panel = &connector->panel;
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
- if (drm_dp_dpcd_writeb(&intel_dp->aux,
- DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) {
- drm_dbg_kms(&dev_priv->drm,
- "Failed to write aux backlight freq\n");
- return false;
- }
- return true;
+ drm_edp_backlight_set_level(&intel_dp->aux, &panel->backlight.edp.vesa.info, level);
}
static void
@@ -422,159 +290,46 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
- struct intel_dp *intel_dp = intel_attached_dp(connector);
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_panel *panel = &connector->panel;
- u8 dpcd_buf, new_dpcd_buf, edp_backlight_mode;
- u8 pwmgen_bit_count = panel->backlight.edp.vesa.pwmgen_bit_count;
-
- if (drm_dp_dpcd_readb(&intel_dp->aux,
- DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf) != 1) {
- drm_dbg_kms(&i915->drm, "Failed to read DPCD register 0x%x\n",
- DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
- return;
- }
-
- new_dpcd_buf = dpcd_buf;
- edp_backlight_mode = dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK;
-
- switch (edp_backlight_mode) {
- case DP_EDP_BACKLIGHT_CONTROL_MODE_PWM:
- case DP_EDP_BACKLIGHT_CONTROL_MODE_PRESET:
- case DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT:
- new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK;
- new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD;
-
- if (drm_dp_dpcd_writeb(&intel_dp->aux,
- DP_EDP_PWMGEN_BIT_COUNT,
- pwmgen_bit_count) < 0)
- drm_dbg_kms(&i915->drm,
- "Failed to write aux pwmgen bit count\n");
-
- break;
-
- /* Do nothing when it is already DPCD mode */
- case DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD:
- default:
- break;
- }
-
- if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP)
- if (intel_dp_aux_vesa_set_pwm_freq(connector))
- new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE;
-
- if (new_dpcd_buf != dpcd_buf) {
- if (drm_dp_dpcd_writeb(&intel_dp->aux,
- DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf) < 0) {
- drm_dbg_kms(&i915->drm,
- "Failed to write aux backlight mode\n");
- }
- }
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
- intel_dp_aux_vesa_set_backlight(conn_state, level);
- set_vesa_backlight_enable(intel_dp, true);
+ drm_edp_backlight_enable(&intel_dp->aux, &panel->backlight.edp.vesa.info, level);
}
static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state *old_conn_state,
u32 level)
{
- set_vesa_backlight_enable(enc_to_intel_dp(to_intel_encoder(old_conn_state->best_encoder)),
- false);
-}
-
-static u32 intel_dp_aux_vesa_calc_max_backlight(struct intel_connector *connector)
-{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
- struct intel_dp *intel_dp = intel_attached_dp(connector);
+ struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct intel_panel *panel = &connector->panel;
- u32 max_backlight = 0;
- int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1;
- u8 pn, pn_min, pn_max;
-
- if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT, &pn) == 1) {
- pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
- max_backlight = (1 << pn) - 1;
- }
-
- /* Find desired value of (F x P)
- * Note that, if F x P is out of supported range, the maximum value or
- * minimum value will applied automatically. So no need to check that.
- */
- freq = i915->vbt.backlight.pwm_freq_hz;
- drm_dbg_kms(&i915->drm, "VBT defined backlight frequency %u Hz\n",
- freq);
- if (!freq) {
- drm_dbg_kms(&i915->drm,
- "Use panel default backlight frequency\n");
- return max_backlight;
- }
-
- fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq);
-
- /* Use highest possible value of Pn for more granularity of brightness
- * adjustment while satifying the conditions below.
- * - Pn is in the range of Pn_min and Pn_max
- * - F is in the range of 1 and 255
- * - FxP is within 25% of desired value.
- * Note: 25% is arbitrary value and may need some tweak.
- */
- if (drm_dp_dpcd_readb(&intel_dp->aux,
- DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) {
- drm_dbg_kms(&i915->drm,
- "Failed to read pwmgen bit count cap min\n");
- return max_backlight;
- }
- if (drm_dp_dpcd_readb(&intel_dp->aux,
- DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) {
- drm_dbg_kms(&i915->drm,
- "Failed to read pwmgen bit count cap max\n");
- return max_backlight;
- }
- pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
- pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
-
- fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
- fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
- if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) {
- drm_dbg_kms(&i915->drm,
- "VBT defined backlight frequency out of range\n");
- return max_backlight;
- }
-
- for (pn = pn_max; pn >= pn_min; pn--) {
- f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
- fxp_actual = f << pn;
- if (fxp_min <= fxp_actual && fxp_actual <= fxp_max)
- break;
- }
-
- drm_dbg_kms(&i915->drm, "Using eDP pwmgen bit count of %d\n", pn);
- if (drm_dp_dpcd_writeb(&intel_dp->aux,
- DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) {
- drm_dbg_kms(&i915->drm,
- "Failed to write aux pwmgen bit count\n");
- return max_backlight;
- }
- panel->backlight.edp.vesa.pwmgen_bit_count = pn;
-
- max_backlight = (1 << pn) - 1;
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
- return max_backlight;
+ drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info);
}
-static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector,
- enum pipe pipe)
+static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, enum pipe pipe)
{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_panel *panel = &connector->panel;
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ u16 current_level;
+ u8 current_mode;
+ int ret;
- panel->backlight.max = intel_dp_aux_vesa_calc_max_backlight(connector);
- if (!panel->backlight.max)
- return -ENODEV;
+ ret = drm_edp_backlight_init(&intel_dp->aux, &panel->backlight.edp.vesa.info,
+ i915->vbt.backlight.pwm_freq_hz, intel_dp->edp_dpcd,
+ &current_level, &current_mode);
+ if (ret < 0)
+ return ret;
+ panel->backlight.max = panel->backlight.edp.vesa.info.max;
panel->backlight.min = 0;
- panel->backlight.level = intel_dp_aux_vesa_get_backlight(connector, pipe);
- panel->backlight.enabled = intel_dp_aux_vesa_backlight_dpcd_mode(connector) &&
- panel->backlight.level != 0;
+ if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) {
+ panel->backlight.level = current_level;
+ panel->backlight.enabled = panel->backlight.level != 0;
+ } else {
+ panel->backlight.level = panel->backlight.max;
+ panel->backlight.enabled = false;
+ }
return 0;
}
@@ -585,16 +340,12 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector)
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- /* Check the eDP Display control capabilities registers to determine if
- * the panel can support backlight control over the aux channel.
- *
- * TODO: We currently only support AUX only backlight configurations, not backlights which
+ /* TODO: We currently only support AUX only backlight configurations, not backlights which
* require a mix of PWM and AUX controls to work. In the mean time, these machines typically
* work just fine using normal PWM controls anyway.
*/
- if (intel_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP &&
- (intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) &&
- (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) {
+ if ((intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) &&
+ drm_edp_backlight_supported(intel_dp->edp_dpcd)) {
drm_dbg_kms(&i915->drm, "AUX Backlight Control Supported!\n");
return true;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index b170e272bdee..8d13d7b26a25 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -308,9 +308,9 @@ intel_dp_mst_atomic_check(struct drm_connector *connector,
* connector
*/
if (new_crtc) {
- struct intel_crtc *intel_crtc = to_intel_crtc(new_crtc);
+ struct intel_crtc *crtc = to_intel_crtc(new_crtc);
struct intel_crtc_state *crtc_state =
- intel_atomic_get_new_crtc_state(state, intel_crtc);
+ intel_atomic_get_new_crtc_state(state, crtc);
if (!crtc_state ||
!drm_atomic_crtc_needs_modeset(&crtc_state->uapi) ||
@@ -348,6 +348,16 @@ static void wait_for_act_sent(struct intel_encoder *encoder,
drm_dp_check_act_status(&intel_dp->mst_mgr);
}
+static void intel_mst_pre_disable_dp(struct intel_atomic_state *state,
+ struct intel_encoder *encoder,
+ const struct intel_crtc_state *old_crtc_state,
+ const struct drm_connector_state *old_conn_state)
+{
+ if (old_crtc_state->has_audio)
+ intel_audio_codec_disable(encoder, old_crtc_state,
+ old_conn_state);
+}
+
static void intel_mst_disable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
@@ -372,9 +382,6 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
if (ret) {
drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret);
}
- if (old_crtc_state->has_audio)
- intel_audio_codec_disable(encoder,
- old_crtc_state, old_conn_state);
}
static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
@@ -542,7 +549,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
struct intel_digital_port *dig_port = intel_mst->primary;
struct intel_dp *intel_dp = &dig_port->dp;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- u32 val;
+ enum transcoder trans = pipe_config->cpu_transcoder;
drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder);
@@ -550,12 +557,8 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
intel_ddi_enable_transcoder_func(encoder, pipe_config);
- val = intel_de_read(dev_priv,
- TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
- val |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
- intel_de_write(dev_priv,
- TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder),
- val);
+ intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(trans), 0,
+ TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
drm_dbg_kms(&dev_priv->drm, "active links %d\n",
intel_dp->active_mst_links);
@@ -564,6 +567,10 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+ if (DISPLAY_VER(dev_priv) >= 12 && pipe_config->fec_enable)
+ intel_de_rmw(dev_priv, CHICKEN_TRANS(trans), 0,
+ FECSTALL_DIS_DPTSTREAM_DPTTG);
+
intel_enable_pipe(pipe_config);
intel_crtc_vblank_on(pipe_config);
@@ -835,13 +842,10 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
intel_attach_force_audio_property(connector);
intel_attach_broadcast_rgb_property(connector);
- if (DISPLAY_VER(dev_priv) <= 12) {
- ret = intel_dp_hdcp_init(dig_port, intel_connector);
- if (ret)
- drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP MST init failed, skipping.\n",
- connector->name, connector->base.id);
- }
-
+ ret = intel_dp_hdcp_init(dig_port, intel_connector);
+ if (ret)
+ drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP MST init failed, skipping.\n",
+ connector->name, connector->base.id);
/*
* Reuse the prop from the SST connector because we're
* not allowed to create new props after device registration.
@@ -906,6 +910,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *dig_port, enum pipe
intel_encoder->compute_config = intel_dp_mst_compute_config;
intel_encoder->compute_config_late = intel_dp_mst_compute_config_late;
+ intel_encoder->pre_disable = intel_mst_pre_disable_dp;
intel_encoder->disable = intel_mst_disable_dp;
intel_encoder->post_disable = intel_mst_post_disable_dp;
intel_encoder->update_pipe = intel_ddi_update_pipe;
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 89635da9f6f6..14515e62c05e 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -11,6 +11,7 @@
#include "intel_lvds.h"
#include "intel_panel.h"
#include "intel_sideband.h"
+#include "display/intel_snps_phy.h"
struct intel_limit {
struct {
@@ -923,12 +924,13 @@ static int hsw_crtc_compute_clock(struct intel_crtc *crtc,
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_atomic_state *state =
to_intel_atomic_state(crtc_state->uapi.state);
+ struct intel_encoder *encoder =
+ intel_get_crtc_new_encoder(state, crtc_state);
- if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
- DISPLAY_VER(dev_priv) >= 11) {
- struct intel_encoder *encoder =
- intel_get_crtc_new_encoder(state, crtc_state);
-
+ if (IS_DG2(dev_priv)) {
+ return intel_mpllb_calc_state(crtc_state, encoder);
+ } else if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
+ DISPLAY_VER(dev_priv) >= 11) {
if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
drm_dbg_kms(&dev_priv->drm,
"failed to find PLL for pipe %c\n",
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index 71ac57670043..5c91d125a337 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -168,7 +168,7 @@ intel_combo_pll_enable_reg(struct drm_i915_private *i915,
else if (IS_JSL_EHL(i915) && (pll->info->id == DPLL_ID_EHL_DPLL4))
return MG_PLL_ENABLE(0);
- return CNL_DPLL_ENABLE(pll->info->id);
+ return ICL_DPLL_ENABLE(pll->info->id);
}
static i915_reg_t
@@ -2346,160 +2346,7 @@ static const struct intel_dpll_mgr bxt_pll_mgr = {
.dump_hw_state = bxt_dump_hw_state,
};
-static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll)
-{
- const enum intel_dpll_id id = pll->info->id;
- u32 val;
-
- /* 1. Enable DPLL power in DPLL_ENABLE. */
- val = intel_de_read(dev_priv, CNL_DPLL_ENABLE(id));
- val |= PLL_POWER_ENABLE;
- intel_de_write(dev_priv, CNL_DPLL_ENABLE(id), val);
-
- /* 2. Wait for DPLL power state enabled in DPLL_ENABLE. */
- if (intel_de_wait_for_set(dev_priv, CNL_DPLL_ENABLE(id),
- PLL_POWER_STATE, 5))
- drm_err(&dev_priv->drm, "PLL %d Power not enabled\n", id);
-
- /*
- * 3. Configure DPLL_CFGCR0 to set SSC enable/disable,
- * select DP mode, and set DP link rate.
- */
- val = pll->state.hw_state.cfgcr0;
- intel_de_write(dev_priv, CNL_DPLL_CFGCR0(id), val);
-
- /* 4. Reab back to ensure writes completed */
- intel_de_posting_read(dev_priv, CNL_DPLL_CFGCR0(id));
-
- /* 3. Configure DPLL_CFGCR0 */
- /* Avoid touch CFGCR1 if HDMI mode is not enabled */
- if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
- val = pll->state.hw_state.cfgcr1;
- intel_de_write(dev_priv, CNL_DPLL_CFGCR1(id), val);
- /* 4. Reab back to ensure writes completed */
- intel_de_posting_read(dev_priv, CNL_DPLL_CFGCR1(id));
- }
-
- /*
- * 5. If the frequency will result in a change to the voltage
- * requirement, follow the Display Voltage Frequency Switching
- * Sequence Before Frequency Change
- *
- * Note: DVFS is actually handled via the cdclk code paths,
- * hence we do nothing here.
- */
-
- /* 6. Enable DPLL in DPLL_ENABLE. */
- val = intel_de_read(dev_priv, CNL_DPLL_ENABLE(id));
- val |= PLL_ENABLE;
- intel_de_write(dev_priv, CNL_DPLL_ENABLE(id), val);
-
- /* 7. Wait for PLL lock status in DPLL_ENABLE. */
- if (intel_de_wait_for_set(dev_priv, CNL_DPLL_ENABLE(id), PLL_LOCK, 5))
- drm_err(&dev_priv->drm, "PLL %d not locked\n", id);
-
- /*
- * 8. If the frequency will result in a change to the voltage
- * requirement, follow the Display Voltage Frequency Switching
- * Sequence After Frequency Change
- *
- * Note: DVFS is actually handled via the cdclk code paths,
- * hence we do nothing here.
- */
-
- /*
- * 9. turn on the clock for the DDI and map the DPLL to the DDI
- * Done at intel_ddi_clk_select
- */
-}
-
-static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll)
-{
- const enum intel_dpll_id id = pll->info->id;
- u32 val;
-
- /*
- * 1. Configure DPCLKA_CFGCR0 to turn off the clock for the DDI.
- * Done at intel_ddi_post_disable
- */
-
- /*
- * 2. If the frequency will result in a change to the voltage
- * requirement, follow the Display Voltage Frequency Switching
- * Sequence Before Frequency Change
- *
- * Note: DVFS is actually handled via the cdclk code paths,
- * hence we do nothing here.
- */
-
- /* 3. Disable DPLL through DPLL_ENABLE. */
- val = intel_de_read(dev_priv, CNL_DPLL_ENABLE(id));
- val &= ~PLL_ENABLE;
- intel_de_write(dev_priv, CNL_DPLL_ENABLE(id), val);
-
- /* 4. Wait for PLL not locked status in DPLL_ENABLE. */
- if (intel_de_wait_for_clear(dev_priv, CNL_DPLL_ENABLE(id), PLL_LOCK, 5))
- drm_err(&dev_priv->drm, "PLL %d locked\n", id);
-
- /*
- * 5. If the frequency will result in a change to the voltage
- * requirement, follow the Display Voltage Frequency Switching
- * Sequence After Frequency Change
- *
- * Note: DVFS is actually handled via the cdclk code paths,
- * hence we do nothing here.
- */
-
- /* 6. Disable DPLL power in DPLL_ENABLE. */
- val = intel_de_read(dev_priv, CNL_DPLL_ENABLE(id));
- val &= ~PLL_POWER_ENABLE;
- intel_de_write(dev_priv, CNL_DPLL_ENABLE(id), val);
-
- /* 7. Wait for DPLL power state disabled in DPLL_ENABLE. */
- if (intel_de_wait_for_clear(dev_priv, CNL_DPLL_ENABLE(id),
- PLL_POWER_STATE, 5))
- drm_err(&dev_priv->drm, "PLL %d Power not disabled\n", id);
-}
-
-static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll,
- struct intel_dpll_hw_state *hw_state)
-{
- const enum intel_dpll_id id = pll->info->id;
- intel_wakeref_t wakeref;
- u32 val;
- bool ret;
-
- wakeref = intel_display_power_get_if_enabled(dev_priv,
- POWER_DOMAIN_DISPLAY_CORE);
- if (!wakeref)
- return false;
-
- ret = false;
-
- val = intel_de_read(dev_priv, CNL_DPLL_ENABLE(id));
- if (!(val & PLL_ENABLE))
- goto out;
-
- val = intel_de_read(dev_priv, CNL_DPLL_CFGCR0(id));
- hw_state->cfgcr0 = val;
-
- /* avoid reading back stale values if HDMI mode is not enabled */
- if (val & DPLL_CFGCR0_HDMI_MODE) {
- hw_state->cfgcr1 = intel_de_read(dev_priv,
- CNL_DPLL_CFGCR1(id));
- }
- ret = true;
-
-out:
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
-
- return ret;
-}
-
-static void cnl_wrpll_get_multipliers(int bestdiv, int *pdiv,
+static void icl_wrpll_get_multipliers(int bestdiv, int *pdiv,
int *qdiv, int *kdiv)
{
/* even dividers */
@@ -2538,7 +2385,7 @@ static void cnl_wrpll_get_multipliers(int bestdiv, int *pdiv,
}
}
-static void cnl_wrpll_params_populate(struct skl_wrpll_params *params,
+static void icl_wrpll_params_populate(struct skl_wrpll_params *params,
u32 dco_freq, u32 ref_freq,
int pdiv, int qdiv, int kdiv)
{
@@ -2586,349 +2433,19 @@ static void cnl_wrpll_params_populate(struct skl_wrpll_params *params,
params->dco_fraction = dco & 0x7fff;
}
-static bool
-__cnl_ddi_calculate_wrpll(struct intel_crtc_state *crtc_state,
- struct skl_wrpll_params *wrpll_params,
- int ref_clock)
-{
- u32 afe_clock = crtc_state->port_clock * 5;
- u32 dco_min = 7998000;
- u32 dco_max = 10000000;
- u32 dco_mid = (dco_min + dco_max) / 2;
- static const int dividers[] = { 2, 4, 6, 8, 10, 12, 14, 16,
- 18, 20, 24, 28, 30, 32, 36, 40,
- 42, 44, 48, 50, 52, 54, 56, 60,
- 64, 66, 68, 70, 72, 76, 78, 80,
- 84, 88, 90, 92, 96, 98, 100, 102,
- 3, 5, 7, 9, 15, 21 };
- u32 dco, best_dco = 0, dco_centrality = 0;
- u32 best_dco_centrality = U32_MAX; /* Spec meaning of 999999 MHz */
- int d, best_div = 0, pdiv = 0, qdiv = 0, kdiv = 0;
-
- for (d = 0; d < ARRAY_SIZE(dividers); d++) {
- dco = afe_clock * dividers[d];
-
- if ((dco <= dco_max) && (dco >= dco_min)) {
- dco_centrality = abs(dco - dco_mid);
-
- if (dco_centrality < best_dco_centrality) {
- best_dco_centrality = dco_centrality;
- best_div = dividers[d];
- best_dco = dco;
- }
- }
- }
-
- if (best_div == 0)
- return false;
-
- cnl_wrpll_get_multipliers(best_div, &pdiv, &qdiv, &kdiv);
- cnl_wrpll_params_populate(wrpll_params, best_dco, ref_clock,
- pdiv, qdiv, kdiv);
-
- return true;
-}
-
-static bool
-cnl_ddi_calculate_wrpll(struct intel_crtc_state *crtc_state,
- struct skl_wrpll_params *wrpll_params)
-{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
-
- return __cnl_ddi_calculate_wrpll(crtc_state, wrpll_params,
- i915->dpll.ref_clks.nssc);
-}
-
-static bool cnl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state)
-{
- u32 cfgcr0, cfgcr1;
- struct skl_wrpll_params wrpll_params = { 0, };
-
- cfgcr0 = DPLL_CFGCR0_HDMI_MODE;
-
- if (!cnl_ddi_calculate_wrpll(crtc_state, &wrpll_params))
- return false;
-
- cfgcr0 |= DPLL_CFGCR0_DCO_FRACTION(wrpll_params.dco_fraction) |
- wrpll_params.dco_integer;
-
- cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(wrpll_params.qdiv_ratio) |
- DPLL_CFGCR1_QDIV_MODE(wrpll_params.qdiv_mode) |
- DPLL_CFGCR1_KDIV(wrpll_params.kdiv) |
- DPLL_CFGCR1_PDIV(wrpll_params.pdiv) |
- DPLL_CFGCR1_CENTRAL_FREQ;
-
- memset(&crtc_state->dpll_hw_state, 0,
- sizeof(crtc_state->dpll_hw_state));
-
- crtc_state->dpll_hw_state.cfgcr0 = cfgcr0;
- crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
- return true;
-}
-
/*
- * Display WA #22010492432: ehl, tgl
+ * Display WA #22010492432: ehl, tgl, adl-p
* Program half of the nominal DCO divider fraction value.
*/
static bool
ehl_combo_pll_div_frac_wa_needed(struct drm_i915_private *i915)
{
return ((IS_PLATFORM(i915, INTEL_ELKHARTLAKE) &&
- IS_JSL_EHL_REVID(i915, EHL_REVID_B0, REVID_FOREVER)) ||
- IS_TIGERLAKE(i915)) &&
+ IS_JSL_EHL_DISPLAY_STEP(i915, STEP_B0, STEP_FOREVER)) ||
+ IS_TIGERLAKE(i915) || IS_ALDERLAKE_P(i915)) &&
i915->dpll.ref_clks.nssc == 38400;
}
-static int __cnl_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv,
- const struct intel_shared_dpll *pll,
- const struct intel_dpll_hw_state *pll_state,
- int ref_clock)
-{
- u32 dco_fraction;
- u32 p0, p1, p2, dco_freq;
-
- p0 = pll_state->cfgcr1 & DPLL_CFGCR1_PDIV_MASK;
- p2 = pll_state->cfgcr1 & DPLL_CFGCR1_KDIV_MASK;
-
- if (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1))
- p1 = (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >>
- DPLL_CFGCR1_QDIV_RATIO_SHIFT;
- else
- p1 = 1;
-
-
- switch (p0) {
- case DPLL_CFGCR1_PDIV_2:
- p0 = 2;
- break;
- case DPLL_CFGCR1_PDIV_3:
- p0 = 3;
- break;
- case DPLL_CFGCR1_PDIV_5:
- p0 = 5;
- break;
- case DPLL_CFGCR1_PDIV_7:
- p0 = 7;
- break;
- }
-
- switch (p2) {
- case DPLL_CFGCR1_KDIV_1:
- p2 = 1;
- break;
- case DPLL_CFGCR1_KDIV_2:
- p2 = 2;
- break;
- case DPLL_CFGCR1_KDIV_3:
- p2 = 3;
- break;
- }
-
- dco_freq = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) *
- ref_clock;
-
- dco_fraction = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >>
- DPLL_CFGCR0_DCO_FRACTION_SHIFT;
-
- if (ehl_combo_pll_div_frac_wa_needed(dev_priv))
- dco_fraction *= 2;
-
- dco_freq += (dco_fraction * ref_clock) / 0x8000;
-
- if (drm_WARN_ON(&dev_priv->drm, p0 == 0 || p1 == 0 || p2 == 0))
- return 0;
-
- return dco_freq / (p0 * p1 * p2 * 5);
-}
-
-static int cnl_ddi_wrpll_get_freq(struct drm_i915_private *i915,
- const struct intel_shared_dpll *pll,
- const struct intel_dpll_hw_state *pll_state)
-{
- return __cnl_ddi_wrpll_get_freq(i915, pll, pll_state,
- i915->dpll.ref_clks.nssc);
-}
-
-static bool
-cnl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
-{
- u32 cfgcr0;
-
- cfgcr0 = DPLL_CFGCR0_SSC_ENABLE;
-
- switch (crtc_state->port_clock / 2) {
- case 81000:
- cfgcr0 |= DPLL_CFGCR0_LINK_RATE_810;
- break;
- case 135000:
- cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1350;
- break;
- case 270000:
- cfgcr0 |= DPLL_CFGCR0_LINK_RATE_2700;
- break;
- /* eDP 1.4 rates */
- case 162000:
- cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1620;
- break;
- case 108000:
- cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1080;
- break;
- case 216000:
- cfgcr0 |= DPLL_CFGCR0_LINK_RATE_2160;
- break;
- case 324000:
- /* Some SKUs may require elevated I/O voltage to support this */
- cfgcr0 |= DPLL_CFGCR0_LINK_RATE_3240;
- break;
- case 405000:
- /* Some SKUs may require elevated I/O voltage to support this */
- cfgcr0 |= DPLL_CFGCR0_LINK_RATE_4050;
- break;
- }
-
- memset(&crtc_state->dpll_hw_state, 0,
- sizeof(crtc_state->dpll_hw_state));
-
- crtc_state->dpll_hw_state.cfgcr0 = cfgcr0;
-
- return true;
-}
-
-static int cnl_ddi_lcpll_get_freq(struct drm_i915_private *i915,
- const struct intel_shared_dpll *pll,
- const struct intel_dpll_hw_state *pll_state)
-{
- int link_clock = 0;
-
- switch (pll_state->cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK) {
- case DPLL_CFGCR0_LINK_RATE_810:
- link_clock = 81000;
- break;
- case DPLL_CFGCR0_LINK_RATE_1080:
- link_clock = 108000;
- break;
- case DPLL_CFGCR0_LINK_RATE_1350:
- link_clock = 135000;
- break;
- case DPLL_CFGCR0_LINK_RATE_1620:
- link_clock = 162000;
- break;
- case DPLL_CFGCR0_LINK_RATE_2160:
- link_clock = 216000;
- break;
- case DPLL_CFGCR0_LINK_RATE_2700:
- link_clock = 270000;
- break;
- case DPLL_CFGCR0_LINK_RATE_3240:
- link_clock = 324000;
- break;
- case DPLL_CFGCR0_LINK_RATE_4050:
- link_clock = 405000;
- break;
- default:
- drm_WARN(&i915->drm, 1, "Unsupported link rate\n");
- break;
- }
-
- return link_clock * 2;
-}
-
-static bool cnl_get_dpll(struct intel_atomic_state *state,
- struct intel_crtc *crtc,
- struct intel_encoder *encoder)
-{
- struct intel_crtc_state *crtc_state =
- intel_atomic_get_new_crtc_state(state, crtc);
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- struct intel_shared_dpll *pll;
- bool bret;
-
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
- bret = cnl_ddi_hdmi_pll_dividers(crtc_state);
- if (!bret) {
- drm_dbg_kms(&i915->drm,
- "Could not get HDMI pll dividers.\n");
- return false;
- }
- } else if (intel_crtc_has_dp_encoder(crtc_state)) {
- bret = cnl_ddi_dp_set_dpll_hw_state(crtc_state);
- if (!bret) {
- drm_dbg_kms(&i915->drm,
- "Could not set DP dpll HW state.\n");
- return false;
- }
- } else {
- drm_dbg_kms(&i915->drm,
- "Skip DPLL setup for output_types 0x%x\n",
- crtc_state->output_types);
- return false;
- }
-
- pll = intel_find_shared_dpll(state, crtc,
- &crtc_state->dpll_hw_state,
- BIT(DPLL_ID_SKL_DPLL2) |
- BIT(DPLL_ID_SKL_DPLL1) |
- BIT(DPLL_ID_SKL_DPLL0));
- if (!pll) {
- drm_dbg_kms(&i915->drm, "No PLL selected\n");
- return false;
- }
-
- intel_reference_shared_dpll(state, crtc,
- pll, &crtc_state->dpll_hw_state);
-
- crtc_state->shared_dpll = pll;
-
- return true;
-}
-
-static int cnl_ddi_pll_get_freq(struct drm_i915_private *i915,
- const struct intel_shared_dpll *pll,
- const struct intel_dpll_hw_state *pll_state)
-{
- if (pll_state->cfgcr0 & DPLL_CFGCR0_HDMI_MODE)
- return cnl_ddi_wrpll_get_freq(i915, pll, pll_state);
- else
- return cnl_ddi_lcpll_get_freq(i915, pll, pll_state);
-}
-
-static void cnl_update_dpll_ref_clks(struct drm_i915_private *i915)
-{
- /* No SSC reference */
- i915->dpll.ref_clks.nssc = i915->cdclk.hw.ref;
-}
-
-static void cnl_dump_hw_state(struct drm_i915_private *dev_priv,
- const struct intel_dpll_hw_state *hw_state)
-{
- drm_dbg_kms(&dev_priv->drm, "dpll_hw_state: "
- "cfgcr0: 0x%x, cfgcr1: 0x%x\n",
- hw_state->cfgcr0,
- hw_state->cfgcr1);
-}
-
-static const struct intel_shared_dpll_funcs cnl_ddi_pll_funcs = {
- .enable = cnl_ddi_pll_enable,
- .disable = cnl_ddi_pll_disable,
- .get_hw_state = cnl_ddi_pll_get_hw_state,
- .get_freq = cnl_ddi_pll_get_freq,
-};
-
-static const struct dpll_info cnl_plls[] = {
- { "DPLL 0", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL0, 0 },
- { "DPLL 1", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 },
- { "DPLL 2", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 },
- { },
-};
-
-static const struct intel_dpll_mgr cnl_pll_mgr = {
- .dpll_info = cnl_plls,
- .get_dplls = cnl_get_dpll,
- .put_dplls = intel_put_dpll,
- .update_ref_clks = cnl_update_dpll_ref_clks,
- .dump_hw_state = cnl_dump_hw_state,
-};
-
struct icl_combo_pll_params {
int clock;
struct skl_wrpll_params wrpll;
@@ -3105,17 +2622,104 @@ icl_calc_wrpll(struct intel_crtc_state *crtc_state,
struct skl_wrpll_params *wrpll_params)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ int ref_clock = icl_wrpll_ref_clock(i915);
+ u32 afe_clock = crtc_state->port_clock * 5;
+ u32 dco_min = 7998000;
+ u32 dco_max = 10000000;
+ u32 dco_mid = (dco_min + dco_max) / 2;
+ static const int dividers[] = { 2, 4, 6, 8, 10, 12, 14, 16,
+ 18, 20, 24, 28, 30, 32, 36, 40,
+ 42, 44, 48, 50, 52, 54, 56, 60,
+ 64, 66, 68, 70, 72, 76, 78, 80,
+ 84, 88, 90, 92, 96, 98, 100, 102,
+ 3, 5, 7, 9, 15, 21 };
+ u32 dco, best_dco = 0, dco_centrality = 0;
+ u32 best_dco_centrality = U32_MAX; /* Spec meaning of 999999 MHz */
+ int d, best_div = 0, pdiv = 0, qdiv = 0, kdiv = 0;
- return __cnl_ddi_calculate_wrpll(crtc_state, wrpll_params,
- icl_wrpll_ref_clock(i915));
+ for (d = 0; d < ARRAY_SIZE(dividers); d++) {
+ dco = afe_clock * dividers[d];
+
+ if (dco <= dco_max && dco >= dco_min) {
+ dco_centrality = abs(dco - dco_mid);
+
+ if (dco_centrality < best_dco_centrality) {
+ best_dco_centrality = dco_centrality;
+ best_div = dividers[d];
+ best_dco = dco;
+ }
+ }
+ }
+
+ if (best_div == 0)
+ return false;
+
+ icl_wrpll_get_multipliers(best_div, &pdiv, &qdiv, &kdiv);
+ icl_wrpll_params_populate(wrpll_params, best_dco, ref_clock,
+ pdiv, qdiv, kdiv);
+
+ return true;
}
static int icl_ddi_combo_pll_get_freq(struct drm_i915_private *i915,
const struct intel_shared_dpll *pll,
const struct intel_dpll_hw_state *pll_state)
{
- return __cnl_ddi_wrpll_get_freq(i915, pll, pll_state,
- icl_wrpll_ref_clock(i915));
+ int ref_clock = icl_wrpll_ref_clock(i915);
+ u32 dco_fraction;
+ u32 p0, p1, p2, dco_freq;
+
+ p0 = pll_state->cfgcr1 & DPLL_CFGCR1_PDIV_MASK;
+ p2 = pll_state->cfgcr1 & DPLL_CFGCR1_KDIV_MASK;
+
+ if (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1))
+ p1 = (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >>
+ DPLL_CFGCR1_QDIV_RATIO_SHIFT;
+ else
+ p1 = 1;
+
+ switch (p0) {
+ case DPLL_CFGCR1_PDIV_2:
+ p0 = 2;
+ break;
+ case DPLL_CFGCR1_PDIV_3:
+ p0 = 3;
+ break;
+ case DPLL_CFGCR1_PDIV_5:
+ p0 = 5;
+ break;
+ case DPLL_CFGCR1_PDIV_7:
+ p0 = 7;
+ break;
+ }
+
+ switch (p2) {
+ case DPLL_CFGCR1_KDIV_1:
+ p2 = 1;
+ break;
+ case DPLL_CFGCR1_KDIV_2:
+ p2 = 2;
+ break;
+ case DPLL_CFGCR1_KDIV_3:
+ p2 = 3;
+ break;
+ }
+
+ dco_freq = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) *
+ ref_clock;
+
+ dco_fraction = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >>
+ DPLL_CFGCR0_DCO_FRACTION_SHIFT;
+
+ if (ehl_combo_pll_div_frac_wa_needed(i915))
+ dco_fraction *= 2;
+
+ dco_freq += (dco_fraction * ref_clock) / 0x8000;
+
+ if (drm_WARN_ON(&i915->drm, p0 == 0 || p1 == 0 || p2 == 0))
+ return 0;
+
+ return dco_freq / (p0 * p1 * p2 * 5);
}
static void icl_calc_dpll_state(struct drm_i915_private *i915,
@@ -4131,6 +3735,31 @@ static void icl_pll_enable(struct drm_i915_private *dev_priv,
drm_err(&dev_priv->drm, "PLL %d not locked\n", pll->info->id);
}
+static void adlp_cmtg_clock_gating_wa(struct drm_i915_private *i915, struct intel_shared_dpll *pll)
+{
+ u32 val;
+
+ if (!IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0) ||
+ pll->info->id != DPLL_ID_ICL_DPLL0)
+ return;
+ /*
+ * Wa_16011069516:adl-p[a0]
+ *
+ * All CMTG regs are unreliable until CMTG clock gating is disabled,
+ * so we can only assume the default TRANS_CMTG_CHICKEN reg value and
+ * sanity check this assumption with a double read, which presumably
+ * returns the correct value even with clock gating on.
+ *
+ * Instead of the usual place for workarounds we apply this one here,
+ * since TRANS_CMTG_CHICKEN is only accessible while DPLL0 is enabled.
+ */
+ val = intel_de_read(i915, TRANS_CMTG_CHICKEN);
+ val = intel_de_read(i915, TRANS_CMTG_CHICKEN);
+ intel_de_write(i915, TRANS_CMTG_CHICKEN, DISABLE_DPT_CLK_GATING);
+ if (drm_WARN_ON(&i915->drm, val & ~DISABLE_DPT_CLK_GATING))
+ drm_dbg_kms(&i915->drm, "Unexpected flags in TRANS_CMTG_CHICKEN: %08x\n", val);
+}
+
static void combo_pll_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
@@ -4160,6 +3789,8 @@ static void combo_pll_enable(struct drm_i915_private *dev_priv,
icl_pll_enable(dev_priv, pll, enable_reg);
+ adlp_cmtg_clock_gating_wa(dev_priv, pll);
+
/* DVFS post sequence would be here. See the comment above. */
}
@@ -4462,7 +4093,10 @@ void intel_shared_dpll_init(struct drm_device *dev)
const struct dpll_info *dpll_info;
int i;
- if (IS_ALDERLAKE_P(dev_priv))
+ if (IS_DG2(dev_priv))
+ /* No shared DPLLs on DG2; port PLLs are part of the PHY */
+ dpll_mgr = NULL;
+ else if (IS_ALDERLAKE_P(dev_priv))
dpll_mgr = &adlp_pll_mgr;
else if (IS_ALDERLAKE_S(dev_priv))
dpll_mgr = &adls_pll_mgr;
@@ -4476,8 +4110,6 @@ void intel_shared_dpll_init(struct drm_device *dev)
dpll_mgr = &ehl_pll_mgr;
else if (DISPLAY_VER(dev_priv) >= 11)
dpll_mgr = &icl_pll_mgr;
- else if (IS_CANNONLAKE(dev_priv))
- dpll_mgr = &cnl_pll_mgr;
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
dpll_mgr = &bxt_pll_mgr;
else if (DISPLAY_VER(dev_priv) == 9)
@@ -4668,7 +4300,12 @@ void intel_dpll_readout_hw_state(struct drm_i915_private *i915)
static void sanitize_dpll_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- if (!pll->on || pll->active_mask)
+ if (!pll->on)
+ return;
+
+ adlp_cmtg_clock_gating_wa(i915, pll);
+
+ if (pll->active_mask)
return;
drm_dbg_kms(&i915->drm,
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
index 7fd031a70cfd..30e0aa5ca109 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
@@ -204,9 +204,8 @@ struct intel_dpll_hw_state {
/* HDMI only, 0 when used for DP */
u32 cfgcr1, cfgcr2;
- /* cnl */
+ /* icl */
u32 cfgcr0;
- /* CNL also uses cfgcr1 */
/* bxt */
u32 ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, pcsdw12;
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index 1847a161cb37..ddfc17e21668 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -104,7 +104,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
int i;
u32 fbc_ctl;
- /* Note: fbc.threshold == 1 for i8xx */
+ /* Note: fbc.limit == 1 for i8xx */
cfb_pitch = params->cfb_size / FBC_LL_SIZE;
if (params->fb.stride < cfb_pitch)
cfb_pitch = params->fb.stride;
@@ -148,16 +148,35 @@ static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv)
return intel_de_read(dev_priv, FBC_CONTROL) & FBC_CTL_EN;
}
+static u32 g4x_dpfc_ctl_limit(struct drm_i915_private *i915)
+{
+ const struct intel_fbc_reg_params *params = &i915->fbc.params;
+ int limit = i915->fbc.limit;
+
+ if (params->fb.format->cpp[0] == 2)
+ limit <<= 1;
+
+ switch (limit) {
+ default:
+ MISSING_CASE(limit);
+ fallthrough;
+ case 1:
+ return DPFC_CTL_LIMIT_1X;
+ case 2:
+ return DPFC_CTL_LIMIT_2X;
+ case 4:
+ return DPFC_CTL_LIMIT_4X;
+ }
+}
+
static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
{
struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
u32 dpfc_ctl;
dpfc_ctl = DPFC_CTL_PLANE(params->crtc.i9xx_plane) | DPFC_SR_EN;
- if (params->fb.format->cpp[0] == 2)
- dpfc_ctl |= DPFC_CTL_LIMIT_2X;
- else
- dpfc_ctl |= DPFC_CTL_LIMIT_1X;
+
+ dpfc_ctl |= g4x_dpfc_ctl_limit(dev_priv);
if (params->fence_id >= 0) {
dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fence_id;
@@ -235,24 +254,10 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
{
struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
u32 dpfc_ctl;
- int threshold = dev_priv->fbc.threshold;
dpfc_ctl = DPFC_CTL_PLANE(params->crtc.i9xx_plane);
- if (params->fb.format->cpp[0] == 2)
- threshold++;
- switch (threshold) {
- case 4:
- case 3:
- dpfc_ctl |= DPFC_CTL_LIMIT_4X;
- break;
- case 2:
- dpfc_ctl |= DPFC_CTL_LIMIT_2X;
- break;
- case 1:
- dpfc_ctl |= DPFC_CTL_LIMIT_1X;
- break;
- }
+ dpfc_ctl |= g4x_dpfc_ctl_limit(dev_priv);
if (params->fence_id >= 0) {
dpfc_ctl |= DPFC_CTL_FENCE_EN;
@@ -300,7 +305,6 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
{
struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
u32 dpfc_ctl;
- int threshold = dev_priv->fbc.threshold;
/* Display WA #0529: skl, kbl, bxt. */
if (DISPLAY_VER(dev_priv) == 9) {
@@ -318,21 +322,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
if (IS_IVYBRIDGE(dev_priv))
dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.i9xx_plane);
- if (params->fb.format->cpp[0] == 2)
- threshold++;
-
- switch (threshold) {
- case 4:
- case 3:
- dpfc_ctl |= DPFC_CTL_LIMIT_4X;
- break;
- case 2:
- dpfc_ctl |= DPFC_CTL_LIMIT_2X;
- break;
- case 1:
- dpfc_ctl |= DPFC_CTL_LIMIT_1X;
- break;
- }
+ dpfc_ctl |= g4x_dpfc_ctl_limit(dev_priv);
if (params->fence_id >= 0) {
dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
@@ -433,13 +423,8 @@ static u64 intel_fbc_cfb_base_max(struct drm_i915_private *i915)
return BIT_ULL(32);
}
-static int find_compression_threshold(struct drm_i915_private *dev_priv,
- struct drm_mm_node *node,
- unsigned int size,
- unsigned int fb_cpp)
+static u64 intel_fbc_stolen_end(struct drm_i915_private *dev_priv)
{
- int compression_threshold = 1;
- int ret;
u64 end;
/* The FBC hardware for BDW/SKL doesn't have access to the stolen
@@ -452,51 +437,69 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
else
end = U64_MAX;
- end = min(end, intel_fbc_cfb_base_max(dev_priv));
+ return min(end, intel_fbc_cfb_base_max(dev_priv));
+}
- /* HACK: This code depends on what we will do in *_enable_fbc. If that
- * code changes, this code needs to change as well.
- *
- * The enable_fbc code will attempt to use one of our 2 compression
- * thresholds, therefore, in that case, we only have 1 resort.
+static int intel_fbc_max_limit(struct drm_i915_private *dev_priv, int fb_cpp)
+{
+ /*
+ * FIXME: FBC1 can have arbitrary cfb stride,
+ * so we could support different compression ratios.
*/
+ if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
+ return 1;
+
+ /* WaFbcOnly1to1Ratio:ctg */
+ if (IS_G4X(dev_priv))
+ return 1;
+
+ /* FBC2 can only do 1:1, 1:2, 1:4 */
+ return fb_cpp == 2 ? 2 : 4;
+}
+
+static int find_compression_limit(struct drm_i915_private *dev_priv,
+ unsigned int size,
+ unsigned int fb_cpp)
+{
+ struct intel_fbc *fbc = &dev_priv->fbc;
+ u64 end = intel_fbc_stolen_end(dev_priv);
+ int ret, limit = 1;
/* Try to over-allocate to reduce reallocations and fragmentation. */
- ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size <<= 1,
- 4096, 0, end);
+ ret = i915_gem_stolen_insert_node_in_range(dev_priv, &fbc->compressed_fb,
+ size <<= 1, 4096, 0, end);
if (ret == 0)
- return compression_threshold;
+ return limit;
-again:
- /* HW's ability to limit the CFB is 1:4 */
- if (compression_threshold > 4 ||
- (fb_cpp == 2 && compression_threshold == 2))
- return 0;
-
- ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1,
- 4096, 0, end);
- if (ret && DISPLAY_VER(dev_priv) <= 4) {
- return 0;
- } else if (ret) {
- compression_threshold <<= 1;
- goto again;
- } else {
- return compression_threshold;
+ for (; limit <= intel_fbc_max_limit(dev_priv, fb_cpp); limit <<= 1) {
+ ret = i915_gem_stolen_insert_node_in_range(dev_priv, &fbc->compressed_fb,
+ size >>= 1, 4096, 0, end);
+ if (ret == 0)
+ return limit;
}
+
+ return 0;
}
static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
unsigned int size, unsigned int fb_cpp)
{
struct intel_fbc *fbc = &dev_priv->fbc;
- struct drm_mm_node *compressed_llb;
int ret;
drm_WARN_ON(&dev_priv->drm,
drm_mm_node_allocated(&fbc->compressed_fb));
+ drm_WARN_ON(&dev_priv->drm,
+ drm_mm_node_allocated(&fbc->compressed_llb));
- ret = find_compression_threshold(dev_priv, &fbc->compressed_fb,
- size, fb_cpp);
+ if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) {
+ ret = i915_gem_stolen_insert_node(dev_priv, &fbc->compressed_llb,
+ 4096, 4096);
+ if (ret)
+ goto err;
+ }
+
+ ret = find_compression_limit(dev_priv, size, fb_cpp);
if (!ret)
goto err_llb;
else if (ret > 1) {
@@ -504,51 +507,46 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
"Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
}
- fbc->threshold = ret;
+ fbc->limit = ret;
- if (DISPLAY_VER(dev_priv) >= 5)
+ drm_dbg_kms(&dev_priv->drm,
+ "reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n",
+ fbc->compressed_fb.size, fbc->limit);
+
+ return 0;
+
+err_llb:
+ if (drm_mm_node_allocated(&fbc->compressed_llb))
+ i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_llb);
+err:
+ if (drm_mm_initialized(&dev_priv->mm.stolen))
+ drm_info_once(&dev_priv->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
+ return -ENOSPC;
+}
+
+static void intel_fbc_program_cfb(struct drm_i915_private *dev_priv)
+{
+ struct intel_fbc *fbc = &dev_priv->fbc;
+
+ if (DISPLAY_VER(dev_priv) >= 5) {
intel_de_write(dev_priv, ILK_DPFC_CB_BASE,
fbc->compressed_fb.start);
- else if (IS_GM45(dev_priv)) {
+ } else if (IS_GM45(dev_priv)) {
intel_de_write(dev_priv, DPFC_CB_BASE,
fbc->compressed_fb.start);
} else {
- compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL);
- if (!compressed_llb)
- goto err_fb;
-
- ret = i915_gem_stolen_insert_node(dev_priv, compressed_llb,
- 4096, 4096);
- if (ret)
- goto err_fb;
-
- fbc->compressed_llb = compressed_llb;
-
GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start,
fbc->compressed_fb.start,
U32_MAX));
GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start,
- fbc->compressed_llb->start,
+ fbc->compressed_llb.start,
U32_MAX));
+
intel_de_write(dev_priv, FBC_CFB_BASE,
dev_priv->dsm.start + fbc->compressed_fb.start);
intel_de_write(dev_priv, FBC_LL_BASE,
- dev_priv->dsm.start + compressed_llb->start);
+ dev_priv->dsm.start + fbc->compressed_llb.start);
}
-
- drm_dbg_kms(&dev_priv->drm,
- "reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
- fbc->compressed_fb.size, fbc->threshold);
-
- return 0;
-
-err_fb:
- kfree(compressed_llb);
- i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb);
-err_llb:
- if (drm_mm_initialized(&dev_priv->mm.stolen))
- drm_info_once(&dev_priv->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
- return -ENOSPC;
}
static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
@@ -558,15 +556,10 @@ static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
if (WARN_ON(intel_fbc_hw_is_active(dev_priv)))
return;
- if (!drm_mm_node_allocated(&fbc->compressed_fb))
- return;
-
- if (fbc->compressed_llb) {
- i915_gem_stolen_remove_node(dev_priv, fbc->compressed_llb);
- kfree(fbc->compressed_llb);
- }
-
- i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb);
+ if (drm_mm_node_allocated(&fbc->compressed_llb))
+ i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_llb);
+ if (drm_mm_node_allocated(&fbc->compressed_fb))
+ i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb);
}
void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
@@ -753,7 +746,7 @@ static bool intel_fbc_cfb_size_changed(struct drm_i915_private *dev_priv)
struct intel_fbc *fbc = &dev_priv->fbc;
return intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) >
- fbc->compressed_fb.size * fbc->threshold;
+ fbc->compressed_fb.size * fbc->limit;
}
static u16 intel_fbc_gen9_wa_cfb_stride(struct drm_i915_private *dev_priv)
@@ -763,7 +756,7 @@ static u16 intel_fbc_gen9_wa_cfb_stride(struct drm_i915_private *dev_priv)
if ((DISPLAY_VER(dev_priv) == 9) &&
cache->fb.modifier != I915_FORMAT_MOD_X_TILED)
- return DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->threshold) * 8;
+ return DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->limit) * 8;
else
return 0;
}
@@ -919,11 +912,11 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
}
/*
- * Tigerlake is not supporting FBC with PSR2.
+ * Display 12+ is not supporting FBC with PSR2.
* Recommendation is to keep this combination disabled
* Bspec: 50422 HSD: 14010260002
*/
- if (fbc->state_cache.psr2_active && IS_TIGERLAKE(dev_priv)) {
+ if (fbc->state_cache.psr2_active && DISPLAY_VER(dev_priv) >= 12) {
fbc->no_fbc_reason = "not supported with PSR2";
return false;
}
@@ -1302,6 +1295,8 @@ void intel_fbc_enable(struct intel_atomic_state *state,
fbc->no_fbc_reason = "FBC enabled but not active yet\n";
fbc->crtc = crtc;
+
+ intel_fbc_program_cfb(dev_priv);
out:
mutex_unlock(&fbc->lock);
}
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 4af40229f5ec..df05d285f0bd 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -335,32 +335,43 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
* fbcon), so we just find the biggest and use that.
*/
static bool intel_fbdev_init_bios(struct drm_device *dev,
- struct intel_fbdev *ifbdev)
+ struct intel_fbdev *ifbdev)
{
struct drm_i915_private *i915 = to_i915(dev);
struct intel_framebuffer *fb = NULL;
- struct drm_crtc *crtc;
- struct intel_crtc *intel_crtc;
+ struct intel_crtc *crtc;
unsigned int max_size = 0;
/* Find the largest fb */
- for_each_crtc(dev, crtc) {
+ for_each_intel_crtc(dev, crtc) {
+ struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+ struct intel_plane *plane =
+ to_intel_plane(crtc->base.primary);
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(plane->base.state);
struct drm_i915_gem_object *obj =
- intel_fb_obj(crtc->primary->state->fb);
- intel_crtc = to_intel_crtc(crtc);
+ intel_fb_obj(plane_state->uapi.fb);
- if (!crtc->state->active || !obj) {
+ if (!crtc_state->uapi.active) {
drm_dbg_kms(&i915->drm,
- "pipe %c not active or no fb, skipping\n",
- pipe_name(intel_crtc->pipe));
+ "[CRTC:%d:%s] not active, skipping\n",
+ crtc->base.base.id, crtc->base.name);
+ continue;
+ }
+
+ if (!obj) {
+ drm_dbg_kms(&i915->drm,
+ "[PLANE:%d:%s] no fb, skipping\n",
+ plane->base.base.id, plane->base.name);
continue;
}
if (obj->base.size > max_size) {
drm_dbg_kms(&i915->drm,
- "found possible fb from plane %c\n",
- pipe_name(intel_crtc->pipe));
- fb = to_intel_framebuffer(crtc->primary->state->fb);
+ "found possible fb from [PLANE:%d:%s]\n",
+ plane->base.base.id, plane->base.name);
+ fb = to_intel_framebuffer(plane_state->uapi.fb);
max_size = obj->base.size;
}
}
@@ -372,60 +383,62 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
}
/* Now make sure all the pipes will fit into it */
- for_each_crtc(dev, crtc) {
+ for_each_intel_crtc(dev, crtc) {
+ struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+ struct intel_plane *plane =
+ to_intel_plane(crtc->base.primary);
unsigned int cur_size;
- intel_crtc = to_intel_crtc(crtc);
-
- if (!crtc->state->active) {
+ if (!crtc_state->uapi.active) {
drm_dbg_kms(&i915->drm,
- "pipe %c not active, skipping\n",
- pipe_name(intel_crtc->pipe));
+ "[CRTC:%d:%s] not active, skipping\n",
+ crtc->base.base.id, crtc->base.name);
continue;
}
- drm_dbg_kms(&i915->drm, "checking plane %c for BIOS fb\n",
- pipe_name(intel_crtc->pipe));
+ drm_dbg_kms(&i915->drm, "checking [PLANE:%d:%s] for BIOS fb\n",
+ plane->base.base.id, plane->base.name);
/*
* See if the plane fb we found above will fit on this
* pipe. Note we need to use the selected fb's pitch and bpp
* rather than the current pipe's, since they differ.
*/
- cur_size = crtc->state->adjusted_mode.crtc_hdisplay;
+ cur_size = crtc_state->uapi.adjusted_mode.crtc_hdisplay;
cur_size = cur_size * fb->base.format->cpp[0];
if (fb->base.pitches[0] < cur_size) {
drm_dbg_kms(&i915->drm,
- "fb not wide enough for plane %c (%d vs %d)\n",
- pipe_name(intel_crtc->pipe),
+ "fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n",
+ plane->base.base.id, plane->base.name,
cur_size, fb->base.pitches[0]);
fb = NULL;
break;
}
- cur_size = crtc->state->adjusted_mode.crtc_vdisplay;
+ cur_size = crtc_state->uapi.adjusted_mode.crtc_vdisplay;
cur_size = intel_fb_align_height(&fb->base, 0, cur_size);
cur_size *= fb->base.pitches[0];
drm_dbg_kms(&i915->drm,
- "pipe %c area: %dx%d, bpp: %d, size: %d\n",
- pipe_name(intel_crtc->pipe),
- crtc->state->adjusted_mode.crtc_hdisplay,
- crtc->state->adjusted_mode.crtc_vdisplay,
+ "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n",
+ crtc->base.base.id, crtc->base.name,
+ crtc_state->uapi.adjusted_mode.crtc_hdisplay,
+ crtc_state->uapi.adjusted_mode.crtc_vdisplay,
fb->base.format->cpp[0] * 8,
cur_size);
if (cur_size > max_size) {
drm_dbg_kms(&i915->drm,
- "fb not big enough for plane %c (%d vs %d)\n",
- pipe_name(intel_crtc->pipe),
+ "fb not big enough for [PLANE:%d:%s] (%d vs %d)\n",
+ plane->base.base.id, plane->base.name,
cur_size, max_size);
fb = NULL;
break;
}
drm_dbg_kms(&i915->drm,
- "fb big enough for plane %c (%d >= %d)\n",
- pipe_name(intel_crtc->pipe),
+ "fb big enough [PLANE:%d:%s] (%d >= %d)\n",
+ plane->base.base.id, plane->base.name,
max_size, cur_size);
}
@@ -441,15 +454,20 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
drm_framebuffer_get(&ifbdev->fb->base);
/* Final pass to check if any active pipes don't have fbs */
- for_each_crtc(dev, crtc) {
- intel_crtc = to_intel_crtc(crtc);
-
- if (!crtc->state->active)
+ for_each_intel_crtc(dev, crtc) {
+ struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+ struct intel_plane *plane =
+ to_intel_plane(crtc->base.primary);
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(plane->base.state);
+
+ if (!crtc_state->uapi.active)
continue;
- drm_WARN(dev, !crtc->primary->state->fb,
- "re-used BIOS config but lost an fb on crtc %d\n",
- crtc->base.id);
+ drm_WARN(dev, !plane_state->uapi.fb,
+ "re-used BIOS config but lost an fb on [PLANE:%d:%s]\n",
+ plane->base.base.id, plane->base.name);
}
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index cef1061fd6cb..e10b9cd8e86e 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -4,7 +4,6 @@
*/
#include "intel_atomic.h"
#include "intel_ddi.h"
-#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
@@ -96,10 +95,10 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
}
}
-int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
- struct intel_crtc_state *pipe_config)
+int ilk_fdi_compute_config(struct intel_crtc *crtc,
+ struct intel_crtc_state *pipe_config)
{
- struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *i915 = to_i915(dev);
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
int lane, link_bw, fdi_dotclock, ret;
@@ -125,7 +124,7 @@ retry:
intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
link_bw, &pipe_config->fdi_m_n, false, false);
- ret = ilk_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);
+ ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
if (ret == -EDEADLK)
return ret;
@@ -569,9 +568,9 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
u32 temp, i, rx_ctl_val;
int n_entries;
- intel_ddi_get_buf_trans_fdi(dev_priv, &n_entries);
+ encoder->get_buf_trans(encoder, crtc_state, &n_entries);
- intel_prepare_dp_ddi_buffers(encoder, crtc_state);
+ hsw_prepare_dp_ddi_buffers(encoder, crtc_state);
/* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
* mode set "sequence for CRT port" document:
@@ -691,9 +690,9 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
- enum pipe pipe = intel_crtc->pipe;
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
i915_reg_t reg;
u32 temp;
@@ -726,11 +725,11 @@ void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state)
}
}
-void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc)
+void ilk_fdi_pll_disable(struct intel_crtc *crtc)
{
- struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- enum pipe pipe = intel_crtc->pipe;
+ enum pipe pipe = crtc->pipe;
i915_reg_t reg;
u32 temp;
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index fcf47f98ea36..ceb1bf8a8c3c 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -600,7 +600,7 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
int i = 0, inc, try = 0;
int ret = 0;
- /* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */
+ /* Display WA #0868: skl,bxt,kbl,cfl,glk */
if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_gmbus_clock_gating(dev_priv, false);
else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_CNP(dev_priv))
@@ -713,7 +713,7 @@ timeout:
ret = -EAGAIN;
out:
- /* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */
+ /* Display WA #0868: skl,bxt,kbl,cfl,glk */
if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_gmbus_clock_gating(dev_priv, true);
else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_CNP(dev_priv))
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 7e51c98c475e..b04685bb6439 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -51,6 +51,7 @@
#include "intel_hdmi.h"
#include "intel_lspcon.h"
#include "intel_panel.h"
+#include "intel_snps_phy.h"
static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
{
@@ -270,8 +271,8 @@ static void ibx_write_infoframe(struct intel_encoder *encoder,
{
const u32 *data = frame;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
- i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ i915_reg_t reg = TVIDEO_DIP_CTL(crtc->pipe);
u32 val = intel_de_read(dev_priv, reg);
int i;
@@ -286,13 +287,13 @@ static void ibx_write_infoframe(struct intel_encoder *encoder,
intel_de_write(dev_priv, reg, val);
for (i = 0; i < len; i += 4) {
- intel_de_write(dev_priv, TVIDEO_DIP_DATA(intel_crtc->pipe),
+ intel_de_write(dev_priv, TVIDEO_DIP_DATA(crtc->pipe),
*data);
data++;
}
/* Write every possible data byte to force correct ECC calculation. */
for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
- intel_de_write(dev_priv, TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
+ intel_de_write(dev_priv, TVIDEO_DIP_DATA(crtc->pipe), 0);
val |= g4x_infoframe_enable(type);
val &= ~VIDEO_DIP_FREQ_MASK;
@@ -349,8 +350,8 @@ static void cpt_write_infoframe(struct intel_encoder *encoder,
{
const u32 *data = frame;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
- i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ i915_reg_t reg = TVIDEO_DIP_CTL(crtc->pipe);
u32 val = intel_de_read(dev_priv, reg);
int i;
@@ -368,13 +369,13 @@ static void cpt_write_infoframe(struct intel_encoder *encoder,
intel_de_write(dev_priv, reg, val);
for (i = 0; i < len; i += 4) {
- intel_de_write(dev_priv, TVIDEO_DIP_DATA(intel_crtc->pipe),
+ intel_de_write(dev_priv, TVIDEO_DIP_DATA(crtc->pipe),
*data);
data++;
}
/* Write every possible data byte to force correct ECC calculation. */
for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
- intel_de_write(dev_priv, TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
+ intel_de_write(dev_priv, TVIDEO_DIP_DATA(crtc->pipe), 0);
val |= g4x_infoframe_enable(type);
val &= ~VIDEO_DIP_FREQ_MASK;
@@ -427,8 +428,8 @@ static void vlv_write_infoframe(struct intel_encoder *encoder,
{
const u32 *data = frame;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
- i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ i915_reg_t reg = VLV_TVIDEO_DIP_CTL(crtc->pipe);
u32 val = intel_de_read(dev_priv, reg);
int i;
@@ -444,13 +445,13 @@ static void vlv_write_infoframe(struct intel_encoder *encoder,
for (i = 0; i < len; i += 4) {
intel_de_write(dev_priv,
- VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
+ VLV_TVIDEO_DIP_DATA(crtc->pipe), *data);
data++;
}
/* Write every possible data byte to force correct ECC calculation. */
for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
intel_de_write(dev_priv,
- VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
+ VLV_TVIDEO_DIP_DATA(crtc->pipe), 0);
val |= g4x_infoframe_enable(type);
val &= ~VIDEO_DIP_FREQ_MASK;
@@ -1040,10 +1041,10 @@ static void ibx_set_infoframes(struct intel_encoder *encoder,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
- i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = TVIDEO_DIP_CTL(crtc->pipe);
u32 val = intel_de_read(dev_priv, reg);
u32 port = VIDEO_DIP_PORT(encoder->port);
@@ -1099,9 +1100,9 @@ static void cpt_set_infoframes(struct intel_encoder *encoder,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
- i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = TVIDEO_DIP_CTL(crtc->pipe);
u32 val = intel_de_read(dev_priv, reg);
assert_hdmi_port_disabled(intel_hdmi);
@@ -1148,9 +1149,9 @@ static void vlv_set_infoframes(struct intel_encoder *encoder,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
- i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = VLV_TVIDEO_DIP_CTL(crtc->pipe);
u32 val = intel_de_read(dev_priv, reg);
u32 port = VIDEO_DIP_PORT(encoder->port);
@@ -1465,14 +1466,12 @@ static int kbl_repositioning_enc_en_signal(struct intel_connector *connector,
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_crtc *crtc = connector->base.state->crtc;
- struct intel_crtc *intel_crtc = container_of(crtc,
- struct intel_crtc, base);
+ struct intel_crtc *crtc = to_intel_crtc(connector->base.state->crtc);
u32 scanline;
int ret;
for (;;) {
- scanline = intel_de_read(dev_priv, PIPEDSL(intel_crtc->pipe));
+ scanline = intel_de_read(dev_priv, PIPEDSL(crtc->pipe));
if (scanline > 100 && scanline < 200)
break;
usleep_range(25, 50);
@@ -1852,6 +1851,16 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000)
return MODE_CLOCK_RANGE;
+ /*
+ * SNPS PHYs' MPLLB table-based programming can only handle a fixed
+ * set of link rates.
+ *
+ * FIXME: We will hopefully get an algorithmic way of programming
+ * the MPLLB for HDMI in the future.
+ */
+ if (IS_DG2(dev_priv))
+ return intel_snps_phy_check_hdmi_link_rate(clock);
+
return MODE_OK;
}
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 7f40e9f60bc2..e0381b0fce91 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -411,12 +411,12 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
struct intel_connector *intel_connector =
lvds_encoder->attached_connector;
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
- struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
unsigned int lvds_bpp;
int ret;
/* Should never happen!! */
- if (DISPLAY_VER(dev_priv) < 4 && intel_crtc->pipe == 0) {
+ if (DISPLAY_VER(dev_priv) < 4 && crtc->pipe == 0) {
drm_err(&dev_priv->drm, "Can't support LVDS on pipe A\n");
return -EINVAL;
}
diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c
index dfd724e506b5..3855fba70980 100644
--- a/drivers/gpu/drm/i915/display/intel_opregion.c
+++ b/drivers/gpu/drm/i915/display/intel_opregion.c
@@ -1078,6 +1078,9 @@ void intel_opregion_resume(struct drm_i915_private *i915)
opregion->asle->ardy = ASLE_ARDY_READY;
}
+ /* Some platforms abuse the _DSM to enable MUX */
+ intel_dsm_get_bios_data_funcs_supported(i915);
+
intel_opregion_notify_adapter(i915, PCI_D0);
}
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 77865cf6641f..1b0daf649e82 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -32,6 +32,7 @@
#include "intel_dp_aux.h"
#include "intel_hdmi.h"
#include "intel_psr.h"
+#include "intel_snps_phy.h"
#include "intel_sprite.h"
#include "skl_universal_plane.h"
@@ -265,32 +266,44 @@ static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp)
return val;
}
-static u16 intel_dp_get_su_x_granulartiy(struct intel_dp *intel_dp)
+static void intel_dp_get_su_granularity(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- u16 val;
ssize_t r;
+ u16 w;
+ u8 y;
+
+ /* If sink don't have specific granularity requirements set legacy ones */
+ if (!(intel_dp->psr_dpcd[1] & DP_PSR2_SU_GRANULARITY_REQUIRED)) {
+ /* As PSR2 HW sends full lines, we do not care about x granularity */
+ w = 4;
+ y = 4;
+ goto exit;
+ }
- /*
- * Returning the default X granularity if granularity not required or
- * if DPCD read fails
- */
- if (!(intel_dp->psr_dpcd[1] & DP_PSR2_SU_GRANULARITY_REQUIRED))
- return 4;
-
- r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &val, 2);
+ r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, 2);
if (r != 2)
drm_dbg_kms(&i915->drm,
"Unable to read DP_PSR2_SU_X_GRANULARITY\n");
-
/*
* Spec says that if the value read is 0 the default granularity should
* be used instead.
*/
- if (r != 2 || val == 0)
- val = 4;
+ if (r != 2 || w == 0)
+ w = 4;
- return val;
+ r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y, 1);
+ if (r != 1) {
+ drm_dbg_kms(&i915->drm,
+ "Unable to read DP_PSR2_SU_Y_GRANULARITY\n");
+ y = 4;
+ }
+ if (y == 0)
+ y = 1;
+
+exit:
+ intel_dp->psr.su_w_granularity = w;
+ intel_dp->psr.su_y_granularity = y;
}
void intel_psr_init_dpcd(struct intel_dp *intel_dp)
@@ -346,8 +359,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
if (intel_dp->psr.sink_psr2_support) {
intel_dp->psr.colorimetry_support =
intel_dp_get_colorimetry_status(intel_dp);
- intel_dp->psr.su_x_granularity =
- intel_dp_get_su_x_granulartiy(intel_dp);
+ intel_dp_get_su_granularity(intel_dp);
}
}
}
@@ -407,6 +419,9 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp)
dpcd_val |= DP_PSR_CRC_VERIFICATION;
}
+ if (intel_dp->psr.req_psr2_sdp_prior_scanline)
+ dpcd_val |= DP_PSR_SU_REGION_SCANLINE_CAPTURE;
+
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, dpcd_val);
drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
@@ -520,18 +535,47 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
static void hsw_activate_psr2(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- u32 val;
+ u32 val = EDP_PSR2_ENABLE;
- val = psr_compute_idle_frames(intel_dp) << EDP_PSR2_IDLE_FRAME_SHIFT;
+ val |= psr_compute_idle_frames(intel_dp) << EDP_PSR2_IDLE_FRAME_SHIFT;
+
+ if (!IS_ALDERLAKE_P(dev_priv))
+ val |= EDP_SU_TRACK_ENABLE;
- val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE;
if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <= 12)
val |= EDP_Y_COORDINATE_ENABLE;
val |= EDP_PSR2_FRAME_BEFORE_SU(intel_dp->psr.sink_sync_latency + 1);
val |= intel_psr2_get_tp_time(intel_dp);
- if (DISPLAY_VER(dev_priv) >= 12) {
+ /* Wa_22012278275:adl-p */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_E0)) {
+ static const u8 map[] = {
+ 2, /* 5 lines */
+ 1, /* 6 lines */
+ 0, /* 7 lines */
+ 3, /* 8 lines */
+ 6, /* 9 lines */
+ 5, /* 10 lines */
+ 4, /* 11 lines */
+ 7, /* 12 lines */
+ };
+ /*
+ * Still using the default IO_BUFFER_WAKE and FAST_WAKE, see
+ * comments bellow for more information
+ */
+ u32 tmp, lines = 7;
+
+ val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2;
+
+ tmp = map[lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
+ tmp = tmp << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT;
+ val |= tmp;
+
+ tmp = map[lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
+ tmp = tmp << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT;
+ val |= tmp;
+ } else if (DISPLAY_VER(dev_priv) >= 12) {
/*
* TODO: 7 lines of IO_BUFFER_WAKE and FAST_WAKE are default
* values from BSpec. In order to setting an optimal power
@@ -547,10 +591,12 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
val |= EDP_PSR2_FAST_WAKE(7);
}
+ if (intel_dp->psr.req_psr2_sdp_prior_scanline)
+ val |= EDP_PSR2_SU_SDP_SCANLINE;
+
if (intel_dp->psr.psr2_sel_fetch_enabled) {
- /* WA 1408330847 */
- if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0) ||
- IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0))
+ /* Wa_1408330847 */
+ if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
intel_de_rmw(dev_priv, CHICKEN_PAR1_1,
DIS_RAM_BYPASS_PSR2_MAN_TRACK,
DIS_RAM_BYPASS_PSR2_MAN_TRACK);
@@ -689,6 +735,10 @@ tgl_dc3co_exitline_compute_config(struct intel_dp *intel_dp,
if (!dc3co_is_pipe_port_compatible(intel_dp, crtc_state))
return;
+ /* Wa_16011303918:adl-p */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
+ return;
+
/*
* DC3CO Exit time 200us B.Spec 49196
* PSR2 transcoder Early Exit scanlines = ROUNDUP(200 / line time) + 1
@@ -733,7 +783,7 @@ static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp,
}
/* Wa_14010254185 Wa_14010103792 */
- if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B1)) {
+ if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0)) {
drm_dbg_kms(&dev_priv->drm,
"PSR2 sel fetch not enabled, missing the implementation of WAs\n");
return false;
@@ -742,6 +792,67 @@ static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp,
return crtc_state->enable_psr2_sel_fetch = true;
}
+static bool psr2_granularity_check(struct intel_dp *intel_dp,
+ struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ const int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay;
+ const int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay;
+ u16 y_granularity = 0;
+
+ /* PSR2 HW only send full lines so we only need to validate the width */
+ if (crtc_hdisplay % intel_dp->psr.su_w_granularity)
+ return false;
+
+ if (crtc_vdisplay % intel_dp->psr.su_y_granularity)
+ return false;
+
+ /* HW tracking is only aligned to 4 lines */
+ if (!crtc_state->enable_psr2_sel_fetch)
+ return intel_dp->psr.su_y_granularity == 4;
+
+ /*
+ * adl_p has 1 line granularity. For other platforms with SW tracking we
+ * can adjust the y coordinates to match sink requirement if multiple of
+ * 4.
+ */
+ if (IS_ALDERLAKE_P(dev_priv))
+ y_granularity = intel_dp->psr.su_y_granularity;
+ else if (intel_dp->psr.su_y_granularity <= 2)
+ y_granularity = 4;
+ else if ((intel_dp->psr.su_y_granularity % 4) == 0)
+ y_granularity = intel_dp->psr.su_y_granularity;
+
+ if (y_granularity == 0 || crtc_vdisplay % y_granularity)
+ return false;
+
+ crtc_state->su_y_granularity = y_granularity;
+ return true;
+}
+
+static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_dp,
+ struct intel_crtc_state *crtc_state)
+{
+ const struct drm_display_mode *adjusted_mode = &crtc_state->uapi.adjusted_mode;
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ u32 hblank_total, hblank_ns, req_ns;
+
+ hblank_total = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
+ hblank_ns = div_u64(1000000ULL * hblank_total, adjusted_mode->crtc_clock);
+
+ /* From spec: (72 / number of lanes) * 1000 / symbol clock frequency MHz */
+ req_ns = (72 / crtc_state->lane_count) * 1000 / (crtc_state->port_clock / 1000);
+
+ if ((hblank_ns - req_ns) > 100)
+ return true;
+
+ if (DISPLAY_VER(dev_priv) < 13 || intel_dp->edp_dpcd[0] < DP_EDP_14b)
+ return false;
+
+ crtc_state->req_psr2_sdp_prior_scanline = true;
+ return true;
+}
+
static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
@@ -760,7 +871,8 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
}
/* Wa_16011181250 */
- if (IS_ROCKETLAKE(dev_priv) || IS_ALDERLAKE_S(dev_priv)) {
+ if (IS_ROCKETLAKE(dev_priv) || IS_ALDERLAKE_S(dev_priv) ||
+ IS_DG2(dev_priv)) {
drm_dbg_kms(&dev_priv->drm, "PSR2 is defeatured for this platform\n");
return false;
}
@@ -824,19 +936,6 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
return false;
}
- /*
- * HW sends SU blocks of size four scan lines, which means the starting
- * X coordinate and Y granularity requirements will always be met. We
- * only need to validate the SU block width is a multiple of
- * x granularity.
- */
- if (crtc_hdisplay % intel_dp->psr.su_x_granularity) {
- drm_dbg_kms(&dev_priv->drm,
- "PSR2 not enabled, hdisplay(%d) not multiple of %d\n",
- crtc_hdisplay, intel_dp->psr.su_x_granularity);
- return false;
- }
-
if (HAS_PSR2_SEL_FETCH(dev_priv)) {
if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) &&
!HAS_PSR_HW_TRACKING(dev_priv)) {
@@ -848,11 +947,16 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
/* Wa_2209313811 */
if (!crtc_state->enable_psr2_sel_fetch &&
- IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B1)) {
+ IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0)) {
drm_dbg_kms(&dev_priv->drm, "PSR2 HW tracking is not supported this Display stepping\n");
return false;
}
+ if (!psr2_granularity_check(intel_dp, crtc_state)) {
+ drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, SU granularity not compatible\n");
+ return false;
+ }
+
if (!crtc_state->enable_psr2_sel_fetch &&
(crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v)) {
drm_dbg_kms(&dev_priv->drm,
@@ -862,6 +966,20 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
return false;
}
+ if (!_compute_psr2_sdp_prior_scanline_indication(intel_dp, crtc_state)) {
+ drm_dbg_kms(&dev_priv->drm,
+ "PSR2 not enabled, PSR2 SDP indication do not fit in hblank\n");
+ return false;
+ }
+
+ /* Wa_16011303918:adl-p */
+ if (crtc_state->vrr.enable &&
+ IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) {
+ drm_dbg_kms(&dev_priv->drm,
+ "PSR2 not enabled, not compatible with HW stepping + VRR\n");
+ return false;
+ }
+
tgl_dc3co_exitline_compute_config(intel_dp, crtc_state);
return true;
}
@@ -1048,6 +1166,14 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp)
intel_de_rmw(dev_priv, CHICKEN_PAR1_1, IGNORE_PSR2_HW_TRACKING,
intel_dp->psr.psr2_sel_fetch_enabled ?
IGNORE_PSR2_HW_TRACKING : 0);
+
+ /* Wa_16011168373:adl-p */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) &&
+ intel_dp->psr.psr2_enabled)
+ intel_de_rmw(dev_priv,
+ TRANS_SET_CONTEXT_LATENCY(intel_dp->psr.transcoder),
+ TRANS_SET_CONTEXT_LATENCY_MASK,
+ TRANS_SET_CONTEXT_LATENCY_VALUE(1));
}
static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
@@ -1087,6 +1213,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
struct intel_encoder *encoder = &dig_port->base;
u32 val;
@@ -1101,6 +1228,8 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
intel_dp->psr.dc3co_exit_delay = val;
intel_dp->psr.dc3co_exitline = crtc_state->dc3co_exitline;
intel_dp->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch;
+ intel_dp->psr.req_psr2_sdp_prior_scanline =
+ crtc_state->req_psr2_sdp_prior_scanline;
if (!psr_interrupt_error_check(intel_dp))
return;
@@ -1110,6 +1239,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
intel_dp_compute_psr_vsc_sdp(intel_dp, crtc_state, conn_state,
&intel_dp->psr.vsc);
intel_write_dp_vsc_sdp(encoder, crtc_state, &intel_dp->psr.vsc);
+ intel_snps_phy_update_psr_power_state(dev_priv, phy, true);
intel_psr_enable_sink(intel_dp);
intel_psr_enable_source(intel_dp);
intel_dp->psr.enabled = true;
@@ -1206,6 +1336,8 @@ static void intel_psr_wait_exit_locked(struct intel_dp *intel_dp)
static void intel_psr_disable_locked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum phy phy = intel_port_to_phy(dev_priv,
+ dp_to_dig_port(intel_dp)->base.port);
lockdep_assert_held(&intel_dp->psr.lock);
@@ -1218,13 +1350,21 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
intel_psr_exit(intel_dp);
intel_psr_wait_exit_locked(intel_dp);
- /* WA 1408330847 */
+ /* Wa_1408330847 */
if (intel_dp->psr.psr2_sel_fetch_enabled &&
- (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0) ||
- IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0)))
+ IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
intel_de_rmw(dev_priv, CHICKEN_PAR1_1,
DIS_RAM_BYPASS_PSR2_MAN_TRACK, 0);
+ /* Wa_16011168373:adl-p */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) &&
+ intel_dp->psr.psr2_enabled)
+ intel_de_rmw(dev_priv,
+ TRANS_SET_CONTEXT_LATENCY(intel_dp->psr.transcoder),
+ TRANS_SET_CONTEXT_LATENCY_MASK, 0);
+
+ intel_snps_phy_update_psr_power_state(dev_priv, phy, false);
+
/* Disable PSR on Sink */
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
@@ -1397,21 +1537,32 @@ void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_st
static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
struct drm_rect *clip, bool full_update)
{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 val = PSR2_MAN_TRK_CTL_ENABLE;
if (full_update) {
- val |= PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME;
+ if (IS_ALDERLAKE_P(dev_priv))
+ val |= ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME;
+ else
+ val |= PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME;
+
goto exit;
}
if (clip->y1 == -1)
goto exit;
- drm_WARN_ON(crtc_state->uapi.crtc->dev, clip->y1 % 4 || clip->y2 % 4);
+ if (IS_ALDERLAKE_P(dev_priv)) {
+ val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1);
+ val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2);
+ } else {
+ drm_WARN_ON(crtc_state->uapi.crtc->dev, clip->y1 % 4 || clip->y2 % 4);
- val |= PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE;
- val |= PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1 / 4 + 1);
- val |= PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 / 4 + 1);
+ val |= PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE;
+ val |= PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1 / 4 + 1);
+ val |= PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 / 4 + 1);
+ }
exit:
crtc_state->psr2_man_track_ctl = val;
}
@@ -1432,6 +1583,20 @@ static void clip_area_update(struct drm_rect *overlap_damage_area,
overlap_damage_area->y2 = damage_area->y2;
}
+static void intel_psr2_sel_fetch_pipe_alignment(const struct intel_crtc_state *crtc_state,
+ struct drm_rect *pipe_clip)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ const u16 y_alignment = crtc_state->su_y_granularity;
+
+ pipe_clip->y1 -= pipe_clip->y1 % y_alignment;
+ if (pipe_clip->y2 % y_alignment)
+ pipe_clip->y2 = ((pipe_clip->y2 / y_alignment) + 1) * y_alignment;
+
+ if (IS_ALDERLAKE_P(dev_priv) && crtc_state->dsc.compression_enable)
+ drm_warn(&dev_priv->drm, "Missing PSR2 sel fetch alignment with DSC\n");
+}
+
int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -1540,10 +1705,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
if (full_update)
goto skip_sel_fetch_set_loop;
- /* It must be aligned to 4 lines */
- pipe_clip.y1 -= pipe_clip.y1 % 4;
- if (pipe_clip.y2 % 4)
- pipe_clip.y2 = ((pipe_clip.y2 / 4) + 1) * 4;
+ intel_psr2_sel_fetch_pipe_alignment(crtc_state, &pipe_clip);
/*
* Now that we have the pipe damaged area check if it intersect with
@@ -1564,6 +1726,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
sel_fetch_area = &new_plane_state->psr2_sel_fetch_area;
sel_fetch_area->y1 = inter.y1 - new_plane_state->uapi.dst.y1;
sel_fetch_area->y2 = inter.y2 - new_plane_state->uapi.dst.y1;
+ crtc_state->update_planes |= BIT(plane->id);
}
skip_sel_fetch_set_loop:
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
index 98dd787b00e3..8a52b7a16774 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
@@ -53,6 +53,12 @@ static void quirk_increase_ddi_disabled_time(struct drm_i915_private *i915)
drm_info(&i915->drm, "Applying Increase DDI Disabled quirk\n");
}
+static void quirk_no_pps_backlight_power_hook(struct drm_i915_private *i915)
+{
+ i915->quirks |= QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK;
+ drm_info(&i915->drm, "Applying no pps backlight power quirk\n");
+}
+
struct intel_quirk {
int device;
int subsystem_vendor;
@@ -72,6 +78,12 @@ static int intel_dmi_reverse_brightness(const struct dmi_system_id *id)
return 1;
}
+static int intel_dmi_no_pps_backlight(const struct dmi_system_id *id)
+{
+ DRM_INFO("No pps backlight support on %s\n", id->ident);
+ return 1;
+}
+
static const struct intel_dmi_quirk intel_dmi_quirks[] = {
{
.dmi_id_list = &(const struct dmi_system_id[]) {
@@ -96,6 +108,28 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = {
},
.hook = quirk_invert_brightness,
},
+ {
+ .dmi_id_list = &(const struct dmi_system_id[]) {
+ {
+ .callback = intel_dmi_no_pps_backlight,
+ .ident = "Google Lillipup sku524294",
+ .matches = {DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Google"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Lindar"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "sku524294"),
+ },
+ },
+ {
+ .callback = intel_dmi_no_pps_backlight,
+ .ident = "Google Lillipup sku524295",
+ .matches = {DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Google"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Lindar"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "sku524295"),
+ },
+ },
+ { }
+ },
+ .hook = quirk_no_pps_backlight_power_hook,
+ },
};
static struct intel_quirk intel_quirks[] = {
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index e4f91d7a5c60..6cb27599ea03 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -1824,7 +1824,7 @@ static void intel_enable_sdvo(struct intel_atomic_state *state,
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
- struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
u32 temp;
bool input1, input2;
int i;
@@ -1835,7 +1835,7 @@ static void intel_enable_sdvo(struct intel_atomic_state *state,
intel_sdvo_write_sdvox(intel_sdvo, temp);
for (i = 0; i < 2; i++)
- intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
success = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
/*
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c
new file mode 100644
index 000000000000..18b52b64af95
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
@@ -0,0 +1,862 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#include <linux/util_macros.h>
+
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_snps_phy.h"
+
+/**
+ * DOC: Synopsis PHY support
+ *
+ * Synopsis PHYs are primarily programmed by looking up magic register values
+ * in tables rather than calculating the necessary values at runtime.
+ *
+ * Of special note is that the SNPS PHYs include a dedicated port PLL, known as
+ * an "MPLLB." The MPLLB replaces the shared DPLL functionality used on other
+ * platforms and must be programming directly during the modeset sequence
+ * since it is not handled by the shared DPLL framework as on other platforms.
+ */
+
+void intel_snps_phy_wait_for_calibration(struct drm_i915_private *dev_priv)
+{
+ enum phy phy;
+
+ for_each_phy_masked(phy, ~0) {
+ if (!intel_phy_is_snps(dev_priv, phy))
+ continue;
+
+ if (intel_de_wait_for_clear(dev_priv, ICL_PHY_MISC(phy),
+ DG2_PHY_DP_TX_ACK_MASK, 25))
+ DRM_ERROR("SNPS PHY %c failed to calibrate after 25ms.\n",
+ phy);
+ }
+}
+
+void intel_snps_phy_update_psr_power_state(struct drm_i915_private *dev_priv,
+ enum phy phy, bool enable)
+{
+ u32 val;
+
+ if (!intel_phy_is_snps(dev_priv, phy))
+ return;
+
+ val = REG_FIELD_PREP(SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR,
+ enable ? 2 : 3);
+ intel_uncore_rmw(&dev_priv->uncore, SNPS_PHY_TX_REQ(phy),
+ SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, val);
+}
+
+static const u32 dg2_ddi_translations[] = {
+ /* VS 0, pre-emph 0 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 26),
+
+ /* VS 0, pre-emph 1 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 33) |
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_POST, 6),
+
+ /* VS 0, pre-emph 2 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 38) |
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_POST, 12),
+
+ /* VS 0, pre-emph 3 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 43) |
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_POST, 19),
+
+ /* VS 1, pre-emph 0 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 39),
+
+ /* VS 1, pre-emph 1 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 44) |
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_POST, 8),
+
+ /* VS 1, pre-emph 2 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 47) |
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_POST, 15),
+
+ /* VS 2, pre-emph 0 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 52),
+
+ /* VS 2, pre-emph 1 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 51) |
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_POST, 10),
+
+ /* VS 3, pre-emph 0 */
+ REG_FIELD_PREP(SNPS_PHY_TX_EQ_MAIN, 62),
+};
+
+void intel_snps_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
+ u32 level)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ int n_entries, ln;
+
+ n_entries = ARRAY_SIZE(dg2_ddi_translations);
+ if (level >= n_entries)
+ level = n_entries - 1;
+
+ for (ln = 0; ln < 4; ln++)
+ intel_de_write(dev_priv, SNPS_PHY_TX_EQ(ln, phy),
+ dg2_ddi_translations[level]);
+}
+
+/*
+ * Basic DP link rates with 100 MHz reference clock.
+ */
+
+static const struct intel_mpllb_state dg2_dp_rbr_100 = {
+ .clock = 162000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 226),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 3),
+};
+
+static const struct intel_mpllb_state dg2_dp_hbr1_100 = {
+ .clock = 270000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 184),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
+};
+
+static const struct intel_mpllb_state dg2_dp_hbr2_100 = {
+ .clock = 540000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 184),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
+};
+
+static const struct intel_mpllb_state dg2_dp_hbr3_100 = {
+ .clock = 810000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 19) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 292),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
+};
+
+static const struct intel_mpllb_state *dg2_dp_100_tables[] = {
+ &dg2_dp_rbr_100,
+ &dg2_dp_hbr1_100,
+ &dg2_dp_hbr2_100,
+ &dg2_dp_hbr3_100,
+ NULL,
+};
+
+/*
+ * Basic DP link rates with 38.4 MHz reference clock.
+ */
+
+static const struct intel_mpllb_state dg2_dp_rbr_38_4 = {
+ .clock = 162000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 1),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 25) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 304),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 49152),
+};
+
+static const struct intel_mpllb_state dg2_dp_hbr1_38_4 = {
+ .clock = 270000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 1),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 25) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 248),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 40960),
+};
+
+static const struct intel_mpllb_state dg2_dp_hbr2_38_4 = {
+ .clock = 540000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 1),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 25) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 248),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 40960),
+};
+
+static const struct intel_mpllb_state dg2_dp_hbr3_38_4 = {
+ .clock = 810000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 1),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 26) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 388),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 1),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 61440),
+};
+
+static const struct intel_mpllb_state *dg2_dp_38_4_tables[] = {
+ &dg2_dp_rbr_38_4,
+ &dg2_dp_hbr1_38_4,
+ &dg2_dp_hbr2_38_4,
+ &dg2_dp_hbr3_38_4,
+ NULL,
+};
+
+/*
+ * eDP link rates with 100 MHz reference clock.
+ */
+
+static const struct intel_mpllb_state dg2_edp_r216 = {
+ .clock = 216000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 19) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 312),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 4),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_PEAK, 50961),
+ .mpllb_sscstep =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_STEPSIZE, 65752),
+};
+
+static const struct intel_mpllb_state dg2_edp_r243 = {
+ .clock = 243000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 356),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 2),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_PEAK, 57331),
+ .mpllb_sscstep =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_STEPSIZE, 73971),
+};
+
+static const struct intel_mpllb_state dg2_edp_r324 = {
+ .clock = 324000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 20) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 226),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 3),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_PEAK, 38221),
+ .mpllb_sscstep =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_STEPSIZE, 49314),
+};
+
+static const struct intel_mpllb_state dg2_edp_r432 = {
+ .clock = 432000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 19) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 65) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 127),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 312),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 4),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_PEAK, 50961),
+ .mpllb_sscstep =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_STEPSIZE, 65752),
+};
+
+static const struct intel_mpllb_state *dg2_edp_tables[] = {
+ &dg2_dp_rbr_100,
+ &dg2_edp_r216,
+ &dg2_edp_r243,
+ &dg2_dp_hbr1_100,
+ &dg2_edp_r324,
+ &dg2_edp_r432,
+ &dg2_dp_hbr2_100,
+ &dg2_dp_hbr3_100,
+ NULL,
+};
+
+/*
+ * HDMI link rates with 100 MHz reference clock.
+ */
+
+static const struct intel_mpllb_state dg2_hdmi_25_175 = {
+ .clock = 25175,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 128) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 143),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 36663) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 71),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
+};
+
+static const struct intel_mpllb_state dg2_hdmi_27_0 = {
+ .clock = 27000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 5) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 140) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 2),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
+};
+
+static const struct intel_mpllb_state dg2_hdmi_74_25 = {
+ .clock = 74250,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 2),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
+};
+
+static const struct intel_mpllb_state dg2_hdmi_148_5 = {
+ .clock = 148500,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 2),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
+};
+
+static const struct intel_mpllb_state dg2_hdmi_594 = {
+ .clock = 594000,
+ .ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+ .mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 4) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
+ .mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
+ .mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
+ .mpllb_fracn1 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 5),
+ .mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 2),
+ .mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
+};
+
+static const struct intel_mpllb_state *dg2_hdmi_tables[] = {
+ &dg2_hdmi_25_175,
+ &dg2_hdmi_27_0,
+ &dg2_hdmi_74_25,
+ &dg2_hdmi_148_5,
+ &dg2_hdmi_594,
+ NULL,
+};
+
+static const struct intel_mpllb_state **
+intel_mpllb_tables_get(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
+ return dg2_edp_tables;
+ } else if (intel_crtc_has_dp_encoder(crtc_state)) {
+ /*
+ * FIXME: Initially we're just enabling the "combo" outputs on
+ * port A-D. The MPLLB for those ports takes an input from the
+ * "Display Filter PLL" which always has an output frequency
+ * of 100 MHz, hence the use of the _100 tables below.
+ *
+ * Once we enable port TC1 it will either use the same 100 MHz
+ * "Display Filter PLL" (when strapped to support a native
+ * display connection) or different 38.4 MHz "Filter PLL" when
+ * strapped to support a USB connection, so we'll need to check
+ * that to determine which table to use.
+ */
+ if (0)
+ return dg2_dp_38_4_tables;
+ else
+ return dg2_dp_100_tables;
+ } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+ return dg2_hdmi_tables;
+ }
+
+ MISSING_CASE(encoder->type);
+ return NULL;
+}
+
+int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ const struct intel_mpllb_state **tables;
+ int i;
+
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+ if (intel_snps_phy_check_hdmi_link_rate(crtc_state->port_clock)
+ != MODE_OK) {
+ /*
+ * FIXME: Can only support fixed HDMI frequencies
+ * until we have a proper algorithm under a valid
+ * license.
+ */
+ DRM_DEBUG_KMS("Can't support HDMI link rate %d\n",
+ crtc_state->port_clock);
+ return -EINVAL;
+ }
+ }
+
+ tables = intel_mpllb_tables_get(crtc_state, encoder);
+ if (!tables)
+ return -EINVAL;
+
+ for (i = 0; tables[i]; i++) {
+ if (crtc_state->port_clock <= tables[i]->clock) {
+ crtc_state->mpllb_state = *tables[i];
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+void intel_mpllb_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ const struct intel_mpllb_state *pll_state = &crtc_state->mpllb_state;
+ enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ i915_reg_t enable_reg = (phy <= PHY_D ?
+ DG2_PLL_ENABLE(phy) : MG_PLL_ENABLE(0));
+
+ /*
+ * 3. Software programs the following PLL registers for the desired
+ * frequency.
+ */
+ intel_de_write(dev_priv, SNPS_PHY_MPLLB_CP(phy), pll_state->mpllb_cp);
+ intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV(phy), pll_state->mpllb_div);
+ intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV2(phy), pll_state->mpllb_div2);
+ intel_de_write(dev_priv, SNPS_PHY_MPLLB_SSCEN(phy), pll_state->mpllb_sscen);
+ intel_de_write(dev_priv, SNPS_PHY_MPLLB_SSCSTEP(phy), pll_state->mpllb_sscstep);
+ intel_de_write(dev_priv, SNPS_PHY_MPLLB_FRACN1(phy), pll_state->mpllb_fracn1);
+ intel_de_write(dev_priv, SNPS_PHY_MPLLB_FRACN2(phy), pll_state->mpllb_fracn2);
+
+ /*
+ * 4. If the frequency will result in a change to the voltage
+ * requirement, follow the Display Voltage Frequency Switching -
+ * Sequence Before Frequency Change.
+ *
+ * We handle this step in bxt_set_cdclk().
+ */
+
+ /* 5. Software sets DPLL_ENABLE [PLL Enable] to "1". */
+ intel_uncore_rmw(&dev_priv->uncore, enable_reg, 0, PLL_ENABLE);
+
+ /*
+ * 9. Software sets SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "1". This
+ * will keep the PLL running during the DDI lane programming and any
+ * typeC DP cable disconnect. Do not set the force before enabling the
+ * PLL because that will start the PLL before it has sampled the
+ * divider values.
+ */
+ intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV(phy),
+ pll_state->mpllb_div | SNPS_PHY_MPLLB_FORCE_EN);
+
+ /*
+ * 10. Software polls on register DPLL_ENABLE [PLL Lock] to confirm PLL
+ * is locked at new settings. This register bit is sampling PHY
+ * dp_mpllb_state interface signal.
+ */
+ if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_LOCK, 5))
+ DRM_ERROR("Port %c PLL not locked\n", phy_name(phy));
+
+ /*
+ * 11. If the frequency will result in a change to the voltage
+ * requirement, follow the Display Voltage Frequency Switching -
+ * Sequence After Frequency Change.
+ *
+ * We handle this step in bxt_set_cdclk().
+ */
+}
+
+void intel_mpllb_disable(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ i915_reg_t enable_reg = (phy <= PHY_D ?
+ DG2_PLL_ENABLE(phy) : MG_PLL_ENABLE(0));
+
+ /*
+ * 1. If the frequency will result in a change to the voltage
+ * requirement, follow the Display Voltage Frequency Switching -
+ * Sequence Before Frequency Change.
+ *
+ * We handle this step in bxt_set_cdclk().
+ */
+
+ /* 2. Software programs DPLL_ENABLE [PLL Enable] to "0" */
+ intel_uncore_rmw(&dev_priv->uncore, enable_reg, PLL_ENABLE, 0);
+
+ /*
+ * 4. Software programs SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "0".
+ * This will allow the PLL to stop running.
+ */
+ intel_uncore_rmw(&dev_priv->uncore, SNPS_PHY_MPLLB_DIV(phy),
+ SNPS_PHY_MPLLB_FORCE_EN, 0);
+
+ /*
+ * 5. Software polls DPLL_ENABLE [PLL Lock] for PHY acknowledgment
+ * (dp_txX_ack) that the new transmitter setting request is completed.
+ */
+ if (intel_de_wait_for_clear(dev_priv, enable_reg, PLL_LOCK, 5))
+ DRM_ERROR("Port %c PLL not locked\n", phy_name(phy));
+
+ /*
+ * 6. If the frequency will result in a change to the voltage
+ * requirement, follow the Display Voltage Frequency Switching -
+ * Sequence After Frequency Change.
+ *
+ * We handle this step in bxt_set_cdclk().
+ */
+}
+
+int intel_mpllb_calc_port_clock(struct intel_encoder *encoder,
+ const struct intel_mpllb_state *pll_state)
+{
+ unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
+ unsigned int multiplier, tx_clk_div, refclk;
+ bool frac_en;
+
+ if (0)
+ refclk = 38400;
+ else
+ refclk = 100000;
+
+ refclk >>= REG_FIELD_GET(SNPS_PHY_MPLLB_REF_CLK_DIV, pll_state->mpllb_div2) - 1;
+
+ frac_en = REG_FIELD_GET(SNPS_PHY_MPLLB_FRACN_EN, pll_state->mpllb_fracn1);
+
+ if (frac_en) {
+ frac_quot = REG_FIELD_GET(SNPS_PHY_MPLLB_FRACN_QUOT, pll_state->mpllb_fracn2);
+ frac_rem = REG_FIELD_GET(SNPS_PHY_MPLLB_FRACN_REM, pll_state->mpllb_fracn2);
+ frac_den = REG_FIELD_GET(SNPS_PHY_MPLLB_FRACN_DEN, pll_state->mpllb_fracn1);
+ }
+
+ multiplier = REG_FIELD_GET(SNPS_PHY_MPLLB_MULTIPLIER, pll_state->mpllb_div2) / 2 + 16;
+
+ tx_clk_div = REG_FIELD_GET(SNPS_PHY_MPLLB_TX_CLK_DIV, pll_state->mpllb_div);
+
+ return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) +
+ DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den),
+ 10 << (tx_clk_div + 16));
+}
+
+void intel_mpllb_readout_hw_state(struct intel_encoder *encoder,
+ struct intel_mpllb_state *pll_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+
+ pll_state->mpllb_cp = intel_de_read(dev_priv, SNPS_PHY_MPLLB_CP(phy));
+ pll_state->mpllb_div = intel_de_read(dev_priv, SNPS_PHY_MPLLB_DIV(phy));
+ pll_state->mpllb_div2 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_DIV2(phy));
+ pll_state->mpllb_sscen = intel_de_read(dev_priv, SNPS_PHY_MPLLB_SSCEN(phy));
+ pll_state->mpllb_sscstep = intel_de_read(dev_priv, SNPS_PHY_MPLLB_SSCSTEP(phy));
+ pll_state->mpllb_fracn1 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_FRACN1(phy));
+ pll_state->mpllb_fracn2 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_FRACN2(phy));
+
+ /*
+ * REF_CONTROL is under firmware control and never programmed by the
+ * driver; we read it only for sanity checking purposes. The bspec
+ * only tells us the expected value for one field in this register,
+ * so we'll only read out those specific bits here.
+ */
+ pll_state->ref_control = intel_de_read(dev_priv, SNPS_PHY_REF_CONTROL(phy)) &
+ SNPS_PHY_REF_CONTROL_REF_RANGE;
+
+ /*
+ * MPLLB_DIV is programmed twice, once with the software-computed
+ * state, then again with the MPLLB_FORCE_EN bit added. Drop that
+ * extra bit during readout so that we return the actual expected
+ * software state.
+ */
+ pll_state->mpllb_div &= ~SNPS_PHY_MPLLB_FORCE_EN;
+}
+
+int intel_snps_phy_check_hdmi_link_rate(int clock)
+{
+ const struct intel_mpllb_state **tables = dg2_hdmi_tables;
+ int i;
+
+ for (i = 0; tables[i]; i++) {
+ if (clock == tables[i]->clock)
+ return MODE_OK;
+ }
+
+ return MODE_CLOCK_RANGE;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.h b/drivers/gpu/drm/i915/display/intel_snps_phy.h
new file mode 100644
index 000000000000..6261ff88ef5c
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#ifndef __INTEL_SNPS_PHY_H__
+#define __INTEL_SNPS_PHY_H__
+
+#include <linux/types.h>
+
+struct drm_i915_private;
+struct intel_encoder;
+struct intel_crtc_state;
+struct intel_mpllb_state;
+enum phy;
+
+void intel_snps_phy_wait_for_calibration(struct drm_i915_private *dev_priv);
+void intel_snps_phy_update_psr_power_state(struct drm_i915_private *dev_priv,
+ enum phy phy, bool enable);
+
+int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder);
+void intel_mpllb_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state);
+void intel_mpllb_disable(struct intel_encoder *encoder);
+void intel_mpllb_readout_hw_state(struct intel_encoder *encoder,
+ struct intel_mpllb_state *pll_state);
+int intel_mpllb_calc_port_clock(struct intel_encoder *encoder,
+ const struct intel_mpllb_state *pll_state);
+
+int intel_snps_phy_check_hdmi_link_rate(int clock);
+void intel_snps_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
+ u32 level);
+
+#endif /* __INTEL_SNPS_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index 4ae9a7455b23..08116f41da26 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -1856,7 +1856,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
zpos = sprite + 1;
drm_plane_create_zpos_immutable_property(&plane->base, zpos);
- drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
+ intel_plane_helper_add(plane);
return plane;
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index c23c210a55f5..3ffece568ed9 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -556,7 +556,7 @@ intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
}
static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
- int required_lanes)
+ int required_lanes, bool force_disconnect)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
enum tc_port_mode old_tc_mode = dig_port->tc_mode;
@@ -572,7 +572,8 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
}
icl_tc_phy_disconnect(dig_port);
- icl_tc_phy_connect(dig_port, required_lanes);
+ if (!force_disconnect)
+ icl_tc_phy_connect(dig_port, required_lanes);
drm_dbg_kms(&i915->drm, "Port %s: TC port mode reset (%s -> %s)\n",
dig_port->tc_port_name,
@@ -662,7 +663,7 @@ bool intel_tc_port_connected(struct intel_encoder *encoder)
}
static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
- int required_lanes)
+ int required_lanes, bool force_disconnect)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
intel_wakeref_t wakeref;
@@ -676,8 +677,9 @@ static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
tc_cold_wref = tc_cold_block(dig_port);
- if (intel_tc_port_needs_reset(dig_port))
- intel_tc_port_reset_mode(dig_port, required_lanes);
+ if (force_disconnect || intel_tc_port_needs_reset(dig_port))
+ intel_tc_port_reset_mode(dig_port, required_lanes,
+ force_disconnect);
tc_cold_unblock(dig_port, tc_cold_wref);
}
@@ -688,7 +690,7 @@ static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
void intel_tc_port_lock(struct intel_digital_port *dig_port)
{
- __intel_tc_port_lock(dig_port, 1);
+ __intel_tc_port_lock(dig_port, 1, false);
}
void intel_tc_port_unlock(struct intel_digital_port *dig_port)
@@ -702,6 +704,24 @@ void intel_tc_port_unlock(struct intel_digital_port *dig_port)
wakeref);
}
+/**
+ * intel_tc_port_disconnect_phy: disconnect TypeC PHY from display port
+ * @dig_port: digital port
+ *
+ * Disconnect the given digital port from its TypeC PHY (handing back the
+ * control of the PHY to the TypeC subsystem). The only purpose of this
+ * function is to force the disconnect even with a TypeC display output still
+ * plugged to the TypeC connector, which is required by the TypeC firmwares
+ * during system suspend and shutdown. Otherwise - during the unplug event
+ * handling - the PHY ownership is released automatically by
+ * intel_tc_port_reset_mode(), when calling this function is not required.
+ */
+void intel_tc_port_disconnect_phy(struct intel_digital_port *dig_port)
+{
+ __intel_tc_port_lock(dig_port, 1, true);
+ intel_tc_port_unlock(dig_port);
+}
+
bool intel_tc_port_ref_held(struct intel_digital_port *dig_port)
{
return mutex_is_locked(&dig_port->tc_lock) ||
@@ -711,7 +731,7 @@ bool intel_tc_port_ref_held(struct intel_digital_port *dig_port)
void intel_tc_port_get_link(struct intel_digital_port *dig_port,
int required_lanes)
{
- __intel_tc_port_lock(dig_port, required_lanes);
+ __intel_tc_port_lock(dig_port, required_lanes, false);
dig_port->tc_link_refcount++;
intel_tc_port_unlock(dig_port);
}
diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h
index 0eacbd76ec15..0c881f645e27 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.h
+++ b/drivers/gpu/drm/i915/display/intel_tc.h
@@ -13,6 +13,8 @@ struct intel_digital_port;
struct intel_encoder;
bool intel_tc_port_connected(struct intel_encoder *encoder);
+void intel_tc_port_disconnect_phy(struct intel_digital_port *dig_port);
+
u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port);
u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port);
int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
index aa52af7891f0..d02f09f7e750 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -1420,7 +1420,7 @@ static void intel_tv_pre_enable(struct intel_atomic_state *state,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct intel_tv *intel_tv = enc_to_tv(encoder);
const struct intel_tv_connector_state *tv_conn_state =
to_intel_tv_connector_state(conn_state);
@@ -1466,7 +1466,7 @@ static void intel_tv_pre_enable(struct intel_atomic_state *state,
break;
}
- tv_ctl |= TV_ENC_PIPE_SEL(intel_crtc->pipe);
+ tv_ctl |= TV_ENC_PIPE_SEL(crtc->pipe);
switch (tv_mode->oversample) {
case 8:
@@ -1571,8 +1571,7 @@ static int
intel_tv_detect_type(struct intel_tv *intel_tv,
struct drm_connector *connector)
{
- struct drm_crtc *crtc = connector->state->crtc;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc *crtc = to_intel_crtc(connector->state->crtc);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
u32 tv_ctl, save_tv_ctl;
@@ -1594,7 +1593,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
/* Poll for TV detection */
tv_ctl &= ~(TV_ENC_ENABLE | TV_ENC_PIPE_SEL_MASK | TV_TEST_MODE_MASK);
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
- tv_ctl |= TV_ENC_PIPE_SEL(intel_crtc->pipe);
+ tv_ctl |= TV_ENC_PIPE_SEL(crtc->pipe);
tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
tv_dac |= (TVDAC_STATE_CHG_EN |
@@ -1619,7 +1618,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
intel_de_write(dev_priv, TV_DAC, tv_dac);
intel_de_posting_read(dev_priv, TV_DAC);
- intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
type = -1;
tv_dac = intel_de_read(dev_priv, TV_DAC);
@@ -1652,7 +1651,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
intel_de_posting_read(dev_priv, TV_CTL);
/* For unknown reasons the hw barfs if we don't do this vblank wait. */
- intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
+ intel_wait_for_vblank(dev_priv, crtc->pipe);
/* Restore interrupt config */
if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index dbe24d7e7375..330077c2e588 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -456,7 +456,7 @@ struct child_device_config {
u16 dp_gpio_pin_num; /* 195 */
u8 dp_iboost_level:4; /* 196 */
u8 hdmi_iboost_level:4; /* 196 */
- u8 dp_max_link_rate:3; /* 216/230 CNL+ */
+ u8 dp_max_link_rate:3; /* 216/230 GLK+ */
u8 dp_max_link_rate_reserved:5; /* 216/230 */
} __packed;
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 85749370508c..df3286aa6999 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -348,7 +348,10 @@ bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state)
if (DISPLAY_VER(i915) >= 12)
return true;
- if ((DISPLAY_VER(i915) >= 11 || IS_CANNONLAKE(i915)) && (pipe != PIPE_A || (cpu_transcoder == TRANSCODER_EDP || cpu_transcoder == TRANSCODER_DSI_0 || cpu_transcoder == TRANSCODER_DSI_1)))
+ if (DISPLAY_VER(i915) >= 11 &&
+ (pipe != PIPE_A || cpu_transcoder == TRANSCODER_EDP ||
+ cpu_transcoder == TRANSCODER_DSI_0 ||
+ cpu_transcoder == TRANSCODER_DSI_1))
return true;
return false;
diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c
index f002b82ba9c0..fa779f7ea415 100644
--- a/drivers/gpu/drm/i915/display/intel_vga.c
+++ b/drivers/gpu/drm/i915/display/intel_vga.c
@@ -29,6 +29,9 @@ void intel_vga_disable(struct drm_i915_private *dev_priv)
i915_reg_t vga_reg = intel_vga_cntrl_reg(dev_priv);
u8 sr1;
+ if (intel_de_read(dev_priv, vga_reg) & VGA_DISP_DISABLE)
+ return;
+
/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(SR01, VGA_SR_INDEX);
@@ -121,9 +124,9 @@ intel_vga_set_state(struct drm_i915_private *i915, bool enable_decode)
}
static unsigned int
-intel_vga_set_decode(void *cookie, bool enable_decode)
+intel_vga_set_decode(struct pci_dev *pdev, bool enable_decode)
{
- struct drm_i915_private *i915 = cookie;
+ struct drm_i915_private *i915 = pdev_to_i915(pdev);
intel_vga_set_state(i915, enable_decode);
@@ -136,6 +139,7 @@ intel_vga_set_decode(void *cookie, bool enable_decode)
int intel_vga_register(struct drm_i915_private *i915)
{
+
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
int ret;
@@ -147,7 +151,7 @@ int intel_vga_register(struct drm_i915_private *i915)
* then we do not take part in VGA arbitration and the
* vga_client_register() fails with -ENODEV.
*/
- ret = vga_client_register(pdev, i915, NULL, intel_vga_set_decode);
+ ret = vga_client_register(pdev, intel_vga_set_decode);
if (ret && ret != -ENODEV)
return ret;
@@ -158,5 +162,5 @@ void intel_vga_unregister(struct drm_i915_private *i915)
{
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
- vga_client_register(pdev, NULL, NULL, NULL);
+ vga_client_unregister(pdev);
}
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c
index 394b7bbf48d8..37eabeff8197 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -96,9 +96,8 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
{
struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
- struct intel_crtc *intel_crtc =
- to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
@@ -141,7 +140,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
drm_dbg_kms(&dev_priv->drm,
"scaler_user index %u.%u: "
"Staged freeing scaler id %d scaler_users = 0x%x\n",
- intel_crtc->pipe, scaler_user, *scaler_id,
+ crtc->pipe, scaler_user, *scaler_id,
scaler_state->scaler_users);
*scaler_id = -1;
}
@@ -167,7 +166,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
drm_dbg_kms(&dev_priv->drm,
"scaler_user index %u.%u: src %ux%u dst %ux%u "
"size is out of scaler range\n",
- intel_crtc->pipe, scaler_user, src_w, src_h,
+ crtc->pipe, scaler_user, src_w, src_h,
dst_w, dst_h);
return -EINVAL;
}
@@ -176,7 +175,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
scaler_state->scaler_users |= (1 << scaler_user);
drm_dbg_kms(&dev_priv->drm, "scaler_user index %u.%u: "
"staged scaling request for %ux%u->%ux%u scaler_users = 0x%x\n",
- intel_crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h,
+ crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h,
scaler_state->scaler_users);
return 0;
@@ -295,12 +294,12 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
return 0;
}
-static int cnl_coef_tap(int i)
+static int glk_coef_tap(int i)
{
return i % 7;
}
-static u16 cnl_nearest_filter_coef(int t)
+static u16 glk_nearest_filter_coef(int t)
{
return t == 3 ? 0x0800 : 0x3000;
}
@@ -342,29 +341,29 @@ static u16 cnl_nearest_filter_coef(int t)
*
*/
-static void cnl_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
+static void glk_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
enum pipe pipe, int id, int set)
{
int i;
- intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set),
+ intel_de_write_fw(dev_priv, GLK_PS_COEF_INDEX_SET(pipe, id, set),
PS_COEE_INDEX_AUTO_INC);
for (i = 0; i < 17 * 7; i += 2) {
u32 tmp;
int t;
- t = cnl_coef_tap(i);
- tmp = cnl_nearest_filter_coef(t);
+ t = glk_coef_tap(i);
+ tmp = glk_nearest_filter_coef(t);
- t = cnl_coef_tap(i + 1);
- tmp |= cnl_nearest_filter_coef(t) << 16;
+ t = glk_coef_tap(i + 1);
+ tmp |= glk_nearest_filter_coef(t) << 16;
- intel_de_write_fw(dev_priv, CNL_PS_COEF_DATA_SET(pipe, id, set),
+ intel_de_write_fw(dev_priv, GLK_PS_COEF_DATA_SET(pipe, id, set),
tmp);
}
- intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set), 0);
+ intel_de_write_fw(dev_priv, GLK_PS_COEF_INDEX_SET(pipe, id, set), 0);
}
static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set)
@@ -387,7 +386,7 @@ static void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe
case DRM_SCALING_FILTER_DEFAULT:
break;
case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
- cnl_program_nearest_filter_coefs(dev_priv, pipe, id, set);
+ glk_program_nearest_filter_coefs(dev_priv, pipe, id, set);
break;
default:
MISSING_CASE(filter);
@@ -515,17 +514,17 @@ skl_program_plane_scaler(struct intel_plane *plane,
(crtc_w << 16) | crtc_h);
}
-static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
+static void skl_detach_scaler(struct intel_crtc *crtc, int id)
{
- struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
- intel_de_write_fw(dev_priv, SKL_PS_CTRL(intel_crtc->pipe, id), 0);
- intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(intel_crtc->pipe, id), 0);
- intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(intel_crtc->pipe, id), 0);
+ intel_de_write_fw(dev_priv, SKL_PS_CTRL(crtc->pipe, id), 0);
+ intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(crtc->pipe, id), 0);
+ intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, id), 0);
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
@@ -535,15 +534,15 @@ static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
*/
void skl_detach_scalers(const struct intel_crtc_state *crtc_state)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
const struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
int i;
/* loop through and disable scalers that aren't in use */
- for (i = 0; i < intel_crtc->num_scalers; i++) {
+ for (i = 0; i < crtc->num_scalers; i++) {
if (!scaler_state->scalers[i].in_use)
- skl_detach_scaler(intel_crtc, i);
+ skl_detach_scaler(crtc, i);
}
}
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 92a4fd508e92..724e7b04f3b6 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -835,7 +835,7 @@ static u32 skl_plane_ctl_rotate(unsigned int rotate)
return 0;
}
-static u32 cnl_plane_ctl_flip(unsigned int reflect)
+static u32 icl_plane_ctl_flip(unsigned int reflect)
{
switch (reflect) {
case 0:
@@ -917,8 +917,8 @@ static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
- plane_ctl |= cnl_plane_ctl_flip(rotation &
+ if (DISPLAY_VER(dev_priv) >= 11)
+ plane_ctl |= icl_plane_ctl_flip(rotation &
DRM_MODE_REFLECT_MASK);
if (key->flags & I915_SET_COLORKEY_DESTINATION)
@@ -926,7 +926,7 @@ static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
else if (key->flags & I915_SET_COLORKEY_SOURCE)
plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
- /* Wa_22012358565:adlp */
+ /* Wa_22012358565:adl-p */
if (DISPLAY_VER(dev_priv) == 13)
plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
@@ -1270,7 +1270,7 @@ static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_s
int pipe_src_w = crtc_state->pipe_src_w;
/*
- * Display WA #1175: cnl,glk
+ * Display WA #1175: glk
* Planes other than the cursor may cause FIFO underflow and display
* corruption if starting less than 4 pixels from the right edge of
* the screen.
@@ -1828,7 +1828,7 @@ static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
if (plane_id == PLANE_CURSOR)
return false;
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 11)
return true;
if (IS_GEMINILAKE(dev_priv))
@@ -1910,11 +1910,11 @@ static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
{
/* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
- IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0))
+ IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_D0))
return false;
/* Wa_22011186057 */
- if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
return false;
return plane_id < PLANE_SPRITE4;
@@ -1938,7 +1938,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
/* Wa_22011186057 */
- if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
return false;
break;
default:
@@ -1995,7 +1995,7 @@ static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
enum plane_id plane_id)
{
/* Wa_22011186057 */
- if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
return adlp_step_a_plane_format_modifiers;
else if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
return gen12_plane_format_modifiers_mc_ccs;
@@ -2144,7 +2144,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 11)
supported_rotations |= DRM_MODE_REFLECT_X;
drm_plane_create_rotation_property(&plane->base,
@@ -2174,12 +2174,12 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
if (DISPLAY_VER(dev_priv) >= 12)
drm_plane_enable_fb_damage_clips(&plane->base);
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 11)
drm_plane_create_scaling_filter_property(&plane->base,
BIT(DRM_SCALING_FILTER_DEFAULT) |
BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
- drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
+ intel_plane_helper_add(plane);
return plane;
@@ -2295,7 +2295,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
break;
}
- if ((DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) && val & PLANE_CTL_FLIP_HORIZONTAL)
+ if (DISPLAY_VER(dev_priv) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
plane_config->rotation |= DRM_MODE_REFLECT_X;
/* 90/270 degree rotation would require extra work */
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 084c9c43b2ed..0ee4ff341e25 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -780,10 +780,9 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state,
const struct drm_connector_state *conn_state)
{
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
- struct drm_crtc *crtc = pipe_config->uapi.crtc;
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe;
+ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
enum port port;
u32 val;
bool glk_cold_boot = false;
@@ -1389,7 +1388,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
struct drm_encoder *encoder = &intel_encoder->base;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(encoder));
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
enum port port;
@@ -1397,7 +1396,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
u32 val, tmp;
u16 mode_hdisplay;
- drm_dbg_kms(&dev_priv->drm, "pipe %c\n", pipe_name(intel_crtc->pipe));
+ drm_dbg_kms(&dev_priv->drm, "pipe %c\n", pipe_name(crtc->pipe));
mode_hdisplay = adjusted_mode->crtc_hdisplay;
@@ -1424,7 +1423,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
intel_de_write(dev_priv, MIPI_CTRL(port),
tmp | READ_REQUEST_PRIORITY_HIGH);
} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
- enum pipe pipe = intel_crtc->pipe;
+ enum pipe pipe = crtc->pipe;
tmp = intel_de_read(dev_priv, MIPI_CTRL(port));
tmp &= ~BXT_PIPE_SELECT_MASK;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
index daf9284ef1f5..f0435c6feb68 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
@@ -24,13 +24,11 @@ static void __do_clflush(struct drm_i915_gem_object *obj)
i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
}
-static int clflush_work(struct dma_fence_work *base)
+static void clflush_work(struct dma_fence_work *base)
{
struct clflush *clflush = container_of(base, typeof(*clflush), base);
__do_clflush(clflush->obj);
-
- return 0;
}
static void clflush_release(struct dma_fence_work *base)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c
deleted file mode 100644
index 44821d94544f..000000000000
--- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c
+++ /dev/null
@@ -1,355 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2019 Intel Corporation
- */
-
-#include "i915_drv.h"
-#include "gt/intel_context.h"
-#include "gt/intel_engine_pm.h"
-#include "i915_gem_client_blt.h"
-#include "i915_gem_object_blt.h"
-
-struct i915_sleeve {
- struct i915_vma *vma;
- struct drm_i915_gem_object *obj;
- struct sg_table *pages;
- struct i915_page_sizes page_sizes;
-};
-
-static int vma_set_pages(struct i915_vma *vma)
-{
- struct i915_sleeve *sleeve = vma->private;
-
- vma->pages = sleeve->pages;
- vma->page_sizes = sleeve->page_sizes;
-
- return 0;
-}
-
-static void vma_clear_pages(struct i915_vma *vma)
-{
- GEM_BUG_ON(!vma->pages);
- vma->pages = NULL;
-}
-
-static void vma_bind(struct i915_address_space *vm,
- struct i915_vm_pt_stash *stash,
- struct i915_vma *vma,
- enum i915_cache_level cache_level,
- u32 flags)
-{
- vm->vma_ops.bind_vma(vm, stash, vma, cache_level, flags);
-}
-
-static void vma_unbind(struct i915_address_space *vm, struct i915_vma *vma)
-{
- vm->vma_ops.unbind_vma(vm, vma);
-}
-
-static const struct i915_vma_ops proxy_vma_ops = {
- .set_pages = vma_set_pages,
- .clear_pages = vma_clear_pages,
- .bind_vma = vma_bind,
- .unbind_vma = vma_unbind,
-};
-
-static struct i915_sleeve *create_sleeve(struct i915_address_space *vm,
- struct drm_i915_gem_object *obj,
- struct sg_table *pages,
- struct i915_page_sizes *page_sizes)
-{
- struct i915_sleeve *sleeve;
- struct i915_vma *vma;
- int err;
-
- sleeve = kzalloc(sizeof(*sleeve), GFP_KERNEL);
- if (!sleeve)
- return ERR_PTR(-ENOMEM);
-
- vma = i915_vma_instance(obj, vm, NULL);
- if (IS_ERR(vma)) {
- err = PTR_ERR(vma);
- goto err_free;
- }
-
- vma->private = sleeve;
- vma->ops = &proxy_vma_ops;
-
- sleeve->vma = vma;
- sleeve->pages = pages;
- sleeve->page_sizes = *page_sizes;
-
- return sleeve;
-
-err_free:
- kfree(sleeve);
- return ERR_PTR(err);
-}
-
-static void destroy_sleeve(struct i915_sleeve *sleeve)
-{
- kfree(sleeve);
-}
-
-struct clear_pages_work {
- struct dma_fence dma;
- struct dma_fence_cb cb;
- struct i915_sw_fence wait;
- struct work_struct work;
- struct irq_work irq_work;
- struct i915_sleeve *sleeve;
- struct intel_context *ce;
- u32 value;
-};
-
-static const char *clear_pages_work_driver_name(struct dma_fence *fence)
-{
- return DRIVER_NAME;
-}
-
-static const char *clear_pages_work_timeline_name(struct dma_fence *fence)
-{
- return "clear";
-}
-
-static void clear_pages_work_release(struct dma_fence *fence)
-{
- struct clear_pages_work *w = container_of(fence, typeof(*w), dma);
-
- destroy_sleeve(w->sleeve);
-
- i915_sw_fence_fini(&w->wait);
-
- BUILD_BUG_ON(offsetof(typeof(*w), dma));
- dma_fence_free(&w->dma);
-}
-
-static const struct dma_fence_ops clear_pages_work_ops = {
- .get_driver_name = clear_pages_work_driver_name,
- .get_timeline_name = clear_pages_work_timeline_name,
- .release = clear_pages_work_release,
-};
-
-static void clear_pages_signal_irq_worker(struct irq_work *work)
-{
- struct clear_pages_work *w = container_of(work, typeof(*w), irq_work);
-
- dma_fence_signal(&w->dma);
- dma_fence_put(&w->dma);
-}
-
-static void clear_pages_dma_fence_cb(struct dma_fence *fence,
- struct dma_fence_cb *cb)
-{
- struct clear_pages_work *w = container_of(cb, typeof(*w), cb);
-
- if (fence->error)
- dma_fence_set_error(&w->dma, fence->error);
-
- /*
- * Push the signalling of the fence into yet another worker to avoid
- * the nightmare locking around the fence spinlock.
- */
- irq_work_queue(&w->irq_work);
-}
-
-static void clear_pages_worker(struct work_struct *work)
-{
- struct clear_pages_work *w = container_of(work, typeof(*w), work);
- struct drm_i915_gem_object *obj = w->sleeve->vma->obj;
- struct i915_vma *vma = w->sleeve->vma;
- struct i915_gem_ww_ctx ww;
- struct i915_request *rq;
- struct i915_vma *batch;
- int err = w->dma.error;
-
- if (unlikely(err))
- goto out_signal;
-
- if (obj->cache_dirty) {
- if (i915_gem_object_has_struct_page(obj))
- drm_clflush_sg(w->sleeve->pages);
- obj->cache_dirty = false;
- }
- obj->read_domains = I915_GEM_GPU_DOMAINS;
- obj->write_domain = 0;
-
- i915_gem_ww_ctx_init(&ww, false);
- intel_engine_pm_get(w->ce->engine);
-retry:
- err = intel_context_pin_ww(w->ce, &ww);
- if (err)
- goto out_signal;
-
- batch = intel_emit_vma_fill_blt(w->ce, vma, &ww, w->value);
- if (IS_ERR(batch)) {
- err = PTR_ERR(batch);
- goto out_ctx;
- }
-
- rq = i915_request_create(w->ce);
- if (IS_ERR(rq)) {
- err = PTR_ERR(rq);
- goto out_batch;
- }
-
- /* There's no way the fence has signalled */
- if (dma_fence_add_callback(&rq->fence, &w->cb,
- clear_pages_dma_fence_cb))
- GEM_BUG_ON(1);
-
- err = intel_emit_vma_mark_active(batch, rq);
- if (unlikely(err))
- goto out_request;
-
- /*
- * w->dma is already exported via (vma|obj)->resv we need only
- * keep track of the GPU activity within this vma/request, and
- * propagate the signal from the request to w->dma.
- */
- err = __i915_vma_move_to_active(vma, rq);
- if (err)
- goto out_request;
-
- if (rq->engine->emit_init_breadcrumb) {
- err = rq->engine->emit_init_breadcrumb(rq);
- if (unlikely(err))
- goto out_request;
- }
-
- err = rq->engine->emit_bb_start(rq,
- batch->node.start, batch->node.size,
- 0);
-out_request:
- if (unlikely(err)) {
- i915_request_set_error_once(rq, err);
- err = 0;
- }
-
- i915_request_add(rq);
-out_batch:
- intel_emit_vma_release(w->ce, batch);
-out_ctx:
- intel_context_unpin(w->ce);
-out_signal:
- if (err == -EDEADLK) {
- err = i915_gem_ww_ctx_backoff(&ww);
- if (!err)
- goto retry;
- }
- i915_gem_ww_ctx_fini(&ww);
-
- i915_vma_unpin(w->sleeve->vma);
- intel_engine_pm_put(w->ce->engine);
-
- if (unlikely(err)) {
- dma_fence_set_error(&w->dma, err);
- dma_fence_signal(&w->dma);
- dma_fence_put(&w->dma);
- }
-}
-
-static int pin_wait_clear_pages_work(struct clear_pages_work *w,
- struct intel_context *ce)
-{
- struct i915_vma *vma = w->sleeve->vma;
- struct i915_gem_ww_ctx ww;
- int err;
-
- i915_gem_ww_ctx_init(&ww, false);
-retry:
- err = i915_gem_object_lock(vma->obj, &ww);
- if (err)
- goto out;
-
- err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER);
- if (unlikely(err))
- goto out;
-
- err = i915_sw_fence_await_reservation(&w->wait,
- vma->obj->base.resv, NULL,
- true, 0, I915_FENCE_GFP);
- if (err)
- goto err_unpin_vma;
-
- dma_resv_add_excl_fence(vma->obj->base.resv, &w->dma);
-
-err_unpin_vma:
- if (err)
- i915_vma_unpin(vma);
-out:
- if (err == -EDEADLK) {
- err = i915_gem_ww_ctx_backoff(&ww);
- if (!err)
- goto retry;
- }
- i915_gem_ww_ctx_fini(&ww);
- return err;
-}
-
-static int __i915_sw_fence_call
-clear_pages_work_notify(struct i915_sw_fence *fence,
- enum i915_sw_fence_notify state)
-{
- struct clear_pages_work *w = container_of(fence, typeof(*w), wait);
-
- switch (state) {
- case FENCE_COMPLETE:
- schedule_work(&w->work);
- break;
-
- case FENCE_FREE:
- dma_fence_put(&w->dma);
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-static DEFINE_SPINLOCK(fence_lock);
-
-/* XXX: better name please */
-int i915_gem_schedule_fill_pages_blt(struct drm_i915_gem_object *obj,
- struct intel_context *ce,
- struct sg_table *pages,
- struct i915_page_sizes *page_sizes,
- u32 value)
-{
- struct clear_pages_work *work;
- struct i915_sleeve *sleeve;
- int err;
-
- sleeve = create_sleeve(ce->vm, obj, pages, page_sizes);
- if (IS_ERR(sleeve))
- return PTR_ERR(sleeve);
-
- work = kmalloc(sizeof(*work), GFP_KERNEL);
- if (!work) {
- destroy_sleeve(sleeve);
- return -ENOMEM;
- }
-
- work->value = value;
- work->sleeve = sleeve;
- work->ce = ce;
-
- INIT_WORK(&work->work, clear_pages_worker);
-
- init_irq_work(&work->irq_work, clear_pages_signal_irq_worker);
-
- dma_fence_init(&work->dma, &clear_pages_work_ops, &fence_lock, 0, 0);
- i915_sw_fence_init(&work->wait, clear_pages_work_notify);
-
- err = pin_wait_clear_pages_work(work, ce);
- if (err < 0)
- dma_fence_set_error(&work->dma, err);
-
- dma_fence_get(&work->dma);
- i915_sw_fence_commit(&work->wait);
-
- return err;
-}
-
-#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
-#include "selftests/i915_gem_client_blt.c"
-#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.h b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.h
deleted file mode 100644
index 3dbd28c22ff5..000000000000
--- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2019 Intel Corporation
- */
-#ifndef __I915_GEM_CLIENT_BLT_H__
-#define __I915_GEM_CLIENT_BLT_H__
-
-#include <linux/types.h>
-
-struct drm_i915_gem_object;
-struct i915_page_sizes;
-struct intel_context;
-struct sg_table;
-
-int i915_gem_schedule_fill_pages_blt(struct drm_i915_gem_object *obj,
- struct intel_context *ce,
- struct sg_table *pages,
- struct i915_page_sizes *page_sizes,
- u32 value);
-
-#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 7720b8c22c81..cff72679ad7c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -67,35 +67,32 @@
#include <linux/log2.h>
#include <linux/nospec.h>
+#include <drm/drm_syncobj.h>
+
#include "gt/gen6_ppgtt.h"
#include "gt/intel_context.h"
#include "gt/intel_context_param.h"
#include "gt/intel_engine_heartbeat.h"
#include "gt/intel_engine_user.h"
-#include "gt/intel_execlists_submission.h" /* virtual_engine */
#include "gt/intel_gpu_commands.h"
#include "gt/intel_ring.h"
#include "i915_gem_context.h"
-#include "i915_globals.h"
#include "i915_trace.h"
#include "i915_user_extensions.h"
#define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 1
-static struct i915_global_gem_context {
- struct i915_global base;
- struct kmem_cache *slab_luts;
-} global;
+static struct kmem_cache *slab_luts;
struct i915_lut_handle *i915_lut_handle_alloc(void)
{
- return kmem_cache_alloc(global.slab_luts, GFP_KERNEL);
+ return kmem_cache_alloc(slab_luts, GFP_KERNEL);
}
void i915_lut_handle_free(struct i915_lut_handle *lut)
{
- return kmem_cache_free(global.slab_luts, lut);
+ return kmem_cache_free(slab_luts, lut);
}
static void lut_close(struct i915_gem_context *ctx)
@@ -167,6 +164,577 @@ lookup_user_engine(struct i915_gem_context *ctx,
return i915_gem_context_get_engine(ctx, idx);
}
+static int validate_priority(struct drm_i915_private *i915,
+ const struct drm_i915_gem_context_param *args)
+{
+ s64 priority = args->value;
+
+ if (args->size)
+ return -EINVAL;
+
+ if (!(i915->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY))
+ return -ENODEV;
+
+ if (priority > I915_CONTEXT_MAX_USER_PRIORITY ||
+ priority < I915_CONTEXT_MIN_USER_PRIORITY)
+ return -EINVAL;
+
+ if (priority > I915_CONTEXT_DEFAULT_PRIORITY &&
+ !capable(CAP_SYS_NICE))
+ return -EPERM;
+
+ return 0;
+}
+
+static void proto_context_close(struct i915_gem_proto_context *pc)
+{
+ int i;
+
+ if (pc->vm)
+ i915_vm_put(pc->vm);
+ if (pc->user_engines) {
+ for (i = 0; i < pc->num_user_engines; i++)
+ kfree(pc->user_engines[i].siblings);
+ kfree(pc->user_engines);
+ }
+ kfree(pc);
+}
+
+static int proto_context_set_persistence(struct drm_i915_private *i915,
+ struct i915_gem_proto_context *pc,
+ bool persist)
+{
+ if (persist) {
+ /*
+ * Only contexts that are short-lived [that will expire or be
+ * reset] are allowed to survive past termination. We require
+ * hangcheck to ensure that the persistent requests are healthy.
+ */
+ if (!i915->params.enable_hangcheck)
+ return -EINVAL;
+
+ pc->user_flags |= BIT(UCONTEXT_PERSISTENCE);
+ } else {
+ /* To cancel a context we use "preempt-to-idle" */
+ if (!(i915->caps.scheduler & I915_SCHEDULER_CAP_PREEMPTION))
+ return -ENODEV;
+
+ /*
+ * If the cancel fails, we then need to reset, cleanly!
+ *
+ * If the per-engine reset fails, all hope is lost! We resort
+ * to a full GPU reset in that unlikely case, but realistically
+ * if the engine could not reset, the full reset does not fare
+ * much better. The damage has been done.
+ *
+ * However, if we cannot reset an engine by itself, we cannot
+ * cleanup a hanging persistent context without causing
+ * colateral damage, and we should not pretend we can by
+ * exposing the interface.
+ */
+ if (!intel_has_reset_engine(&i915->gt))
+ return -ENODEV;
+
+ pc->user_flags &= ~BIT(UCONTEXT_PERSISTENCE);
+ }
+
+ return 0;
+}
+
+static struct i915_gem_proto_context *
+proto_context_create(struct drm_i915_private *i915, unsigned int flags)
+{
+ struct i915_gem_proto_context *pc, *err;
+
+ pc = kzalloc(sizeof(*pc), GFP_KERNEL);
+ if (!pc)
+ return ERR_PTR(-ENOMEM);
+
+ pc->num_user_engines = -1;
+ pc->user_engines = NULL;
+ pc->user_flags = BIT(UCONTEXT_BANNABLE) |
+ BIT(UCONTEXT_RECOVERABLE);
+ if (i915->params.enable_hangcheck)
+ pc->user_flags |= BIT(UCONTEXT_PERSISTENCE);
+ pc->sched.priority = I915_PRIORITY_NORMAL;
+
+ if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) {
+ if (!HAS_EXECLISTS(i915)) {
+ err = ERR_PTR(-EINVAL);
+ goto proto_close;
+ }
+ pc->single_timeline = true;
+ }
+
+ return pc;
+
+proto_close:
+ proto_context_close(pc);
+ return err;
+}
+
+static int proto_context_register_locked(struct drm_i915_file_private *fpriv,
+ struct i915_gem_proto_context *pc,
+ u32 *id)
+{
+ int ret;
+ void *old;
+
+ lockdep_assert_held(&fpriv->proto_context_lock);
+
+ ret = xa_alloc(&fpriv->context_xa, id, NULL, xa_limit_32b, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ old = xa_store(&fpriv->proto_context_xa, *id, pc, GFP_KERNEL);
+ if (xa_is_err(old)) {
+ xa_erase(&fpriv->context_xa, *id);
+ return xa_err(old);
+ }
+ WARN_ON(old);
+
+ return 0;
+}
+
+static int proto_context_register(struct drm_i915_file_private *fpriv,
+ struct i915_gem_proto_context *pc,
+ u32 *id)
+{
+ int ret;
+
+ mutex_lock(&fpriv->proto_context_lock);
+ ret = proto_context_register_locked(fpriv, pc, id);
+ mutex_unlock(&fpriv->proto_context_lock);
+
+ return ret;
+}
+
+static int set_proto_ctx_vm(struct drm_i915_file_private *fpriv,
+ struct i915_gem_proto_context *pc,
+ const struct drm_i915_gem_context_param *args)
+{
+ struct drm_i915_private *i915 = fpriv->dev_priv;
+ struct i915_address_space *vm;
+
+ if (args->size)
+ return -EINVAL;
+
+ if (!HAS_FULL_PPGTT(i915))
+ return -ENODEV;
+
+ if (upper_32_bits(args->value))
+ return -ENOENT;
+
+ vm = i915_gem_vm_lookup(fpriv, args->value);
+ if (!vm)
+ return -ENOENT;
+
+ if (pc->vm)
+ i915_vm_put(pc->vm);
+ pc->vm = vm;
+
+ return 0;
+}
+
+struct set_proto_ctx_engines {
+ struct drm_i915_private *i915;
+ unsigned num_engines;
+ struct i915_gem_proto_engine *engines;
+};
+
+static int
+set_proto_ctx_engines_balance(struct i915_user_extension __user *base,
+ void *data)
+{
+ struct i915_context_engines_load_balance __user *ext =
+ container_of_user(base, typeof(*ext), base);
+ const struct set_proto_ctx_engines *set = data;
+ struct drm_i915_private *i915 = set->i915;
+ struct intel_engine_cs **siblings;
+ u16 num_siblings, idx;
+ unsigned int n;
+ int err;
+
+ if (!HAS_EXECLISTS(i915))
+ return -ENODEV;
+
+ if (get_user(idx, &ext->engine_index))
+ return -EFAULT;
+
+ if (idx >= set->num_engines) {
+ drm_dbg(&i915->drm, "Invalid placement value, %d >= %d\n",
+ idx, set->num_engines);
+ return -EINVAL;
+ }
+
+ idx = array_index_nospec(idx, set->num_engines);
+ if (set->engines[idx].type != I915_GEM_ENGINE_TYPE_INVALID) {
+ drm_dbg(&i915->drm,
+ "Invalid placement[%d], already occupied\n", idx);
+ return -EEXIST;
+ }
+
+ if (get_user(num_siblings, &ext->num_siblings))
+ return -EFAULT;
+
+ err = check_user_mbz(&ext->flags);
+ if (err)
+ return err;
+
+ err = check_user_mbz(&ext->mbz64);
+ if (err)
+ return err;
+
+ if (num_siblings == 0)
+ return 0;
+
+ siblings = kmalloc_array(num_siblings, sizeof(*siblings), GFP_KERNEL);
+ if (!siblings)
+ return -ENOMEM;
+
+ for (n = 0; n < num_siblings; n++) {
+ struct i915_engine_class_instance ci;
+
+ if (copy_from_user(&ci, &ext->engines[n], sizeof(ci))) {
+ err = -EFAULT;
+ goto err_siblings;
+ }
+
+ siblings[n] = intel_engine_lookup_user(i915,
+ ci.engine_class,
+ ci.engine_instance);
+ if (!siblings[n]) {
+ drm_dbg(&i915->drm,
+ "Invalid sibling[%d]: { class:%d, inst:%d }\n",
+ n, ci.engine_class, ci.engine_instance);
+ err = -EINVAL;
+ goto err_siblings;
+ }
+ }
+
+ if (num_siblings == 1) {
+ set->engines[idx].type = I915_GEM_ENGINE_TYPE_PHYSICAL;
+ set->engines[idx].engine = siblings[0];
+ kfree(siblings);
+ } else {
+ set->engines[idx].type = I915_GEM_ENGINE_TYPE_BALANCED;
+ set->engines[idx].num_siblings = num_siblings;
+ set->engines[idx].siblings = siblings;
+ }
+
+ return 0;
+
+err_siblings:
+ kfree(siblings);
+
+ return err;
+}
+
+static int
+set_proto_ctx_engines_bond(struct i915_user_extension __user *base, void *data)
+{
+ struct i915_context_engines_bond __user *ext =
+ container_of_user(base, typeof(*ext), base);
+ const struct set_proto_ctx_engines *set = data;
+ struct drm_i915_private *i915 = set->i915;
+ struct i915_engine_class_instance ci;
+ struct intel_engine_cs *master;
+ u16 idx, num_bonds;
+ int err, n;
+
+ if (get_user(idx, &ext->virtual_index))
+ return -EFAULT;
+
+ if (idx >= set->num_engines) {
+ drm_dbg(&i915->drm,
+ "Invalid index for virtual engine: %d >= %d\n",
+ idx, set->num_engines);
+ return -EINVAL;
+ }
+
+ idx = array_index_nospec(idx, set->num_engines);
+ if (set->engines[idx].type == I915_GEM_ENGINE_TYPE_INVALID) {
+ drm_dbg(&i915->drm, "Invalid engine at %d\n", idx);
+ return -EINVAL;
+ }
+
+ if (set->engines[idx].type != I915_GEM_ENGINE_TYPE_PHYSICAL) {
+ drm_dbg(&i915->drm,
+ "Bonding with virtual engines not allowed\n");
+ return -EINVAL;
+ }
+
+ err = check_user_mbz(&ext->flags);
+ if (err)
+ return err;
+
+ for (n = 0; n < ARRAY_SIZE(ext->mbz64); n++) {
+ err = check_user_mbz(&ext->mbz64[n]);
+ if (err)
+ return err;
+ }
+
+ if (copy_from_user(&ci, &ext->master, sizeof(ci)))
+ return -EFAULT;
+
+ master = intel_engine_lookup_user(i915,
+ ci.engine_class,
+ ci.engine_instance);
+ if (!master) {
+ drm_dbg(&i915->drm,
+ "Unrecognised master engine: { class:%u, instance:%u }\n",
+ ci.engine_class, ci.engine_instance);
+ return -EINVAL;
+ }
+
+ if (intel_engine_uses_guc(master)) {
+ DRM_DEBUG("bonding extension not supported with GuC submission");
+ return -ENODEV;
+ }
+
+ if (get_user(num_bonds, &ext->num_bonds))
+ return -EFAULT;
+
+ for (n = 0; n < num_bonds; n++) {
+ struct intel_engine_cs *bond;
+
+ if (copy_from_user(&ci, &ext->engines[n], sizeof(ci)))
+ return -EFAULT;
+
+ bond = intel_engine_lookup_user(i915,
+ ci.engine_class,
+ ci.engine_instance);
+ if (!bond) {
+ drm_dbg(&i915->drm,
+ "Unrecognised engine[%d] for bonding: { class:%d, instance: %d }\n",
+ n, ci.engine_class, ci.engine_instance);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static const i915_user_extension_fn set_proto_ctx_engines_extensions[] = {
+ [I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE] = set_proto_ctx_engines_balance,
+ [I915_CONTEXT_ENGINES_EXT_BOND] = set_proto_ctx_engines_bond,
+};
+
+static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
+ struct i915_gem_proto_context *pc,
+ const struct drm_i915_gem_context_param *args)
+{
+ struct drm_i915_private *i915 = fpriv->dev_priv;
+ struct set_proto_ctx_engines set = { .i915 = i915 };
+ struct i915_context_param_engines __user *user =
+ u64_to_user_ptr(args->value);
+ unsigned int n;
+ u64 extensions;
+ int err;
+
+ if (pc->num_user_engines >= 0) {
+ drm_dbg(&i915->drm, "Cannot set engines twice");
+ return -EINVAL;
+ }
+
+ if (args->size < sizeof(*user) ||
+ !IS_ALIGNED(args->size - sizeof(*user), sizeof(*user->engines))) {
+ drm_dbg(&i915->drm, "Invalid size for engine array: %d\n",
+ args->size);
+ return -EINVAL;
+ }
+
+ set.num_engines = (args->size - sizeof(*user)) / sizeof(*user->engines);
+ /* RING_MASK has no shift so we can use it directly here */
+ if (set.num_engines > I915_EXEC_RING_MASK + 1)
+ return -EINVAL;
+
+ set.engines = kmalloc_array(set.num_engines, sizeof(*set.engines), GFP_KERNEL);
+ if (!set.engines)
+ return -ENOMEM;
+
+ for (n = 0; n < set.num_engines; n++) {
+ struct i915_engine_class_instance ci;
+ struct intel_engine_cs *engine;
+
+ if (copy_from_user(&ci, &user->engines[n], sizeof(ci))) {
+ kfree(set.engines);
+ return -EFAULT;
+ }
+
+ memset(&set.engines[n], 0, sizeof(set.engines[n]));
+
+ if (ci.engine_class == (u16)I915_ENGINE_CLASS_INVALID &&
+ ci.engine_instance == (u16)I915_ENGINE_CLASS_INVALID_NONE)
+ continue;
+
+ engine = intel_engine_lookup_user(i915,
+ ci.engine_class,
+ ci.engine_instance);
+ if (!engine) {
+ drm_dbg(&i915->drm,
+ "Invalid engine[%d]: { class:%d, instance:%d }\n",
+ n, ci.engine_class, ci.engine_instance);
+ kfree(set.engines);
+ return -ENOENT;
+ }
+
+ set.engines[n].type = I915_GEM_ENGINE_TYPE_PHYSICAL;
+ set.engines[n].engine = engine;
+ }
+
+ err = -EFAULT;
+ if (!get_user(extensions, &user->extensions))
+ err = i915_user_extensions(u64_to_user_ptr(extensions),
+ set_proto_ctx_engines_extensions,
+ ARRAY_SIZE(set_proto_ctx_engines_extensions),
+ &set);
+ if (err) {
+ kfree(set.engines);
+ return err;
+ }
+
+ pc->num_user_engines = set.num_engines;
+ pc->user_engines = set.engines;
+
+ return 0;
+}
+
+static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
+ struct i915_gem_proto_context *pc,
+ struct drm_i915_gem_context_param *args)
+{
+ struct drm_i915_private *i915 = fpriv->dev_priv;
+ struct drm_i915_gem_context_param_sseu user_sseu;
+ struct intel_sseu *sseu;
+ int ret;
+
+ if (args->size < sizeof(user_sseu))
+ return -EINVAL;
+
+ if (GRAPHICS_VER(i915) != 11)
+ return -ENODEV;
+
+ if (copy_from_user(&user_sseu, u64_to_user_ptr(args->value),
+ sizeof(user_sseu)))
+ return -EFAULT;
+
+ if (user_sseu.rsvd)
+ return -EINVAL;
+
+ if (user_sseu.flags & ~(I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX))
+ return -EINVAL;
+
+ if (!!(user_sseu.flags & I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX) != (pc->num_user_engines >= 0))
+ return -EINVAL;
+
+ if (pc->num_user_engines >= 0) {
+ int idx = user_sseu.engine.engine_instance;
+ struct i915_gem_proto_engine *pe;
+
+ if (idx >= pc->num_user_engines)
+ return -EINVAL;
+
+ pe = &pc->user_engines[idx];
+
+ /* Only render engine supports RPCS configuration. */
+ if (pe->engine->class != RENDER_CLASS)
+ return -EINVAL;
+
+ sseu = &pe->sseu;
+ } else {
+ /* Only render engine supports RPCS configuration. */
+ if (user_sseu.engine.engine_class != I915_ENGINE_CLASS_RENDER)
+ return -EINVAL;
+
+ /* There is only one render engine */
+ if (user_sseu.engine.engine_instance != 0)
+ return -EINVAL;
+
+ sseu = &pc->legacy_rcs_sseu;
+ }
+
+ ret = i915_gem_user_to_context_sseu(&i915->gt, &user_sseu, sseu);
+ if (ret)
+ return ret;
+
+ args->size = sizeof(user_sseu);
+
+ return 0;
+}
+
+static int set_proto_ctx_param(struct drm_i915_file_private *fpriv,
+ struct i915_gem_proto_context *pc,
+ struct drm_i915_gem_context_param *args)
+{
+ int ret = 0;
+
+ switch (args->param) {
+ case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:
+ if (args->size)
+ ret = -EINVAL;
+ else if (args->value)
+ pc->user_flags |= BIT(UCONTEXT_NO_ERROR_CAPTURE);
+ else
+ pc->user_flags &= ~BIT(UCONTEXT_NO_ERROR_CAPTURE);
+ break;
+
+ case I915_CONTEXT_PARAM_BANNABLE:
+ if (args->size)
+ ret = -EINVAL;
+ else if (!capable(CAP_SYS_ADMIN) && !args->value)
+ ret = -EPERM;
+ else if (args->value)
+ pc->user_flags |= BIT(UCONTEXT_BANNABLE);
+ else
+ pc->user_flags &= ~BIT(UCONTEXT_BANNABLE);
+ break;
+
+ case I915_CONTEXT_PARAM_RECOVERABLE:
+ if (args->size)
+ ret = -EINVAL;
+ else if (args->value)
+ pc->user_flags |= BIT(UCONTEXT_RECOVERABLE);
+ else
+ pc->user_flags &= ~BIT(UCONTEXT_RECOVERABLE);
+ break;
+
+ case I915_CONTEXT_PARAM_PRIORITY:
+ ret = validate_priority(fpriv->dev_priv, args);
+ if (!ret)
+ pc->sched.priority = args->value;
+ break;
+
+ case I915_CONTEXT_PARAM_SSEU:
+ ret = set_proto_ctx_sseu(fpriv, pc, args);
+ break;
+
+ case I915_CONTEXT_PARAM_VM:
+ ret = set_proto_ctx_vm(fpriv, pc, args);
+ break;
+
+ case I915_CONTEXT_PARAM_ENGINES:
+ ret = set_proto_ctx_engines(fpriv, pc, args);
+ break;
+
+ case I915_CONTEXT_PARAM_PERSISTENCE:
+ if (args->size)
+ ret = -EINVAL;
+ ret = proto_context_set_persistence(fpriv->dev_priv, pc,
+ args->value);
+ break;
+
+ case I915_CONTEXT_PARAM_NO_ZEROMAP:
+ case I915_CONTEXT_PARAM_BAN_PERIOD:
+ case I915_CONTEXT_PARAM_RINGSIZE:
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
static struct i915_address_space *
context_get_vm_rcu(struct i915_gem_context *ctx)
{
@@ -205,14 +773,16 @@ context_get_vm_rcu(struct i915_gem_context *ctx)
} while (1);
}
-static void intel_context_set_gem(struct intel_context *ce,
- struct i915_gem_context *ctx)
+static int intel_context_set_gem(struct intel_context *ce,
+ struct i915_gem_context *ctx,
+ struct intel_sseu sseu)
{
+ int ret = 0;
+
GEM_BUG_ON(rcu_access_pointer(ce->gem_context));
RCU_INIT_POINTER(ce->gem_context, ctx);
- if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))
- ce->ring = __intel_context_ring_size(SZ_16K);
+ ce->ring_size = SZ_16K;
if (rcu_access_pointer(ctx->vm)) {
struct i915_address_space *vm;
@@ -225,15 +795,23 @@ static void intel_context_set_gem(struct intel_context *ce,
ce->vm = vm;
}
- GEM_BUG_ON(ce->timeline);
- if (ctx->timeline)
- ce->timeline = intel_timeline_get(ctx->timeline);
-
if (ctx->sched.priority >= I915_PRIORITY_NORMAL &&
- intel_engine_has_timeslices(ce->engine))
+ intel_engine_has_timeslices(ce->engine) &&
+ intel_engine_has_semaphores(ce->engine))
__set_bit(CONTEXT_USE_SEMAPHORES, &ce->flags);
- intel_context_set_watchdog_us(ce, ctx->watchdog.timeout_us);
+ if (IS_ACTIVE(CONFIG_DRM_I915_REQUEST_TIMEOUT) &&
+ ctx->i915->params.request_timeout_ms) {
+ unsigned int timeout_ms = ctx->i915->params.request_timeout_ms;
+
+ intel_context_set_watchdog_us(ce, (u64)timeout_ms * 1000);
+ }
+
+ /* A valid SSEU has no zero fields */
+ if (sseu.slice_mask && !WARN_ON(ce->engine->class != RENDER_CLASS))
+ ret = intel_context_reconfigure_sseu(ce, sseu);
+
+ return ret;
}
static void __free_engines(struct i915_gem_engines *e, unsigned int count)
@@ -301,11 +879,12 @@ static struct i915_gem_engines *alloc_engines(unsigned int count)
return e;
}
-static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
+static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx,
+ struct intel_sseu rcs_sseu)
{
const struct intel_gt *gt = &ctx->i915->gt;
struct intel_engine_cs *engine;
- struct i915_gem_engines *e;
+ struct i915_gem_engines *e, *err;
enum intel_engine_id id;
e = alloc_engines(I915_NUM_ENGINES);
@@ -314,6 +893,8 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
for_each_engine(engine, gt, id) {
struct intel_context *ce;
+ struct intel_sseu sseu = {};
+ int ret;
if (engine->legacy_idx == INVALID_ENGINE)
continue;
@@ -323,18 +904,79 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
ce = intel_context_create(engine);
if (IS_ERR(ce)) {
- __free_engines(e, e->num_engines + 1);
- return ERR_CAST(ce);
+ err = ERR_CAST(ce);
+ goto free_engines;
}
- intel_context_set_gem(ce, ctx);
-
e->engines[engine->legacy_idx] = ce;
- e->num_engines = max(e->num_engines, engine->legacy_idx);
+ e->num_engines = max(e->num_engines, engine->legacy_idx + 1);
+
+ if (engine->class == RENDER_CLASS)
+ sseu = rcs_sseu;
+
+ ret = intel_context_set_gem(ce, ctx, sseu);
+ if (ret) {
+ err = ERR_PTR(ret);
+ goto free_engines;
+ }
+
+ }
+
+ return e;
+
+free_engines:
+ free_engines(e);
+ return err;
+}
+
+static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
+ unsigned int num_engines,
+ struct i915_gem_proto_engine *pe)
+{
+ struct i915_gem_engines *e, *err;
+ unsigned int n;
+
+ e = alloc_engines(num_engines);
+ for (n = 0; n < num_engines; n++) {
+ struct intel_context *ce;
+ int ret;
+
+ switch (pe[n].type) {
+ case I915_GEM_ENGINE_TYPE_PHYSICAL:
+ ce = intel_context_create(pe[n].engine);
+ break;
+
+ case I915_GEM_ENGINE_TYPE_BALANCED:
+ ce = intel_engine_create_virtual(pe[n].siblings,
+ pe[n].num_siblings);
+ break;
+
+ case I915_GEM_ENGINE_TYPE_INVALID:
+ default:
+ GEM_WARN_ON(pe[n].type != I915_GEM_ENGINE_TYPE_INVALID);
+ continue;
+ }
+
+ if (IS_ERR(ce)) {
+ err = ERR_CAST(ce);
+ goto free_engines;
+ }
+
+ e->engines[n] = ce;
+
+ ret = intel_context_set_gem(ce, ctx, pe->sseu);
+ if (ret) {
+ err = ERR_PTR(ret);
+ goto free_engines;
+ }
}
- e->num_engines++;
+ e->num_engines = num_engines;
return e;
+
+free_engines:
+ free_engines(e);
+ return err;
}
void i915_gem_context_release(struct kref *ref)
@@ -347,9 +989,6 @@ void i915_gem_context_release(struct kref *ref)
mutex_destroy(&ctx->engines_mutex);
mutex_destroy(&ctx->lut_mutex);
- if (ctx->timeline)
- intel_timeline_put(ctx->timeline);
-
put_pid(ctx->pid);
mutex_destroy(&ctx->mutex);
@@ -441,7 +1080,7 @@ static void kill_engines(struct i915_gem_engines *engines, bool ban)
for_each_gem_engine(ce, engines, it) {
struct intel_engine_cs *engine;
- if (ban && intel_context_set_banned(ce))
+ if (ban && intel_context_ban(ce, NULL))
continue;
/*
@@ -566,6 +1205,9 @@ static void context_close(struct i915_gem_context *ctx)
if (vm)
i915_vm_close(vm);
+ if (ctx->syncobj)
+ drm_syncobj_put(ctx->syncobj);
+
ctx->file_priv = ERR_PTR(-EBADF);
/*
@@ -635,57 +1277,6 @@ static int __context_set_persistence(struct i915_gem_context *ctx, bool state)
return 0;
}
-static struct i915_gem_context *
-__create_context(struct drm_i915_private *i915)
-{
- struct i915_gem_context *ctx;
- struct i915_gem_engines *e;
- int err;
- int i;
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&ctx->ref);
- ctx->i915 = i915;
- ctx->sched.priority = I915_PRIORITY_NORMAL;
- mutex_init(&ctx->mutex);
- INIT_LIST_HEAD(&ctx->link);
-
- spin_lock_init(&ctx->stale.lock);
- INIT_LIST_HEAD(&ctx->stale.engines);
-
- mutex_init(&ctx->engines_mutex);
- e = default_engines(ctx);
- if (IS_ERR(e)) {
- err = PTR_ERR(e);
- goto err_free;
- }
- RCU_INIT_POINTER(ctx->engines, e);
-
- INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
- mutex_init(&ctx->lut_mutex);
-
- /* NB: Mark all slices as needing a remap so that when the context first
- * loads it will restore whatever remap state already exists. If there
- * is no remap info, it will be a NOP. */
- ctx->remap_slice = ALL_L3_SLICES(i915);
-
- i915_gem_context_set_bannable(ctx);
- i915_gem_context_set_recoverable(ctx);
- __context_set_persistence(ctx, true /* cgroup hook? */);
-
- for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++)
- ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES;
-
- return ctx;
-
-err_free:
- kfree(ctx);
- return ERR_PTR(err);
-}
-
static inline struct i915_gem_engines *
__context_engines_await(const struct i915_gem_context *ctx,
bool *user_engines)
@@ -714,168 +1305,112 @@ __context_engines_await(const struct i915_gem_context *ctx,
return engines;
}
-static int
+static void
context_apply_all(struct i915_gem_context *ctx,
- int (*fn)(struct intel_context *ce, void *data),
+ void (*fn)(struct intel_context *ce, void *data),
void *data)
{
struct i915_gem_engines_iter it;
struct i915_gem_engines *e;
struct intel_context *ce;
- int err = 0;
e = __context_engines_await(ctx, NULL);
- for_each_gem_engine(ce, e, it) {
- err = fn(ce, data);
- if (err)
- break;
- }
+ for_each_gem_engine(ce, e, it)
+ fn(ce, data);
i915_sw_fence_complete(&e->fence);
-
- return err;
-}
-
-static int __apply_ppgtt(struct intel_context *ce, void *vm)
-{
- i915_vm_put(ce->vm);
- ce->vm = i915_vm_get(vm);
- return 0;
-}
-
-static struct i915_address_space *
-__set_ppgtt(struct i915_gem_context *ctx, struct i915_address_space *vm)
-{
- struct i915_address_space *old;
-
- old = rcu_replace_pointer(ctx->vm,
- i915_vm_open(vm),
- lockdep_is_held(&ctx->mutex));
- GEM_BUG_ON(old && i915_vm_is_4lvl(vm) != i915_vm_is_4lvl(old));
-
- context_apply_all(ctx, __apply_ppgtt, vm);
-
- return old;
-}
-
-static void __assign_ppgtt(struct i915_gem_context *ctx,
- struct i915_address_space *vm)
-{
- if (vm == rcu_access_pointer(ctx->vm))
- return;
-
- vm = __set_ppgtt(ctx, vm);
- if (vm)
- i915_vm_close(vm);
-}
-
-static void __set_timeline(struct intel_timeline **dst,
- struct intel_timeline *src)
-{
- struct intel_timeline *old = *dst;
-
- *dst = src ? intel_timeline_get(src) : NULL;
-
- if (old)
- intel_timeline_put(old);
-}
-
-static int __apply_timeline(struct intel_context *ce, void *timeline)
-{
- __set_timeline(&ce->timeline, timeline);
- return 0;
-}
-
-static void __assign_timeline(struct i915_gem_context *ctx,
- struct intel_timeline *timeline)
-{
- __set_timeline(&ctx->timeline, timeline);
- context_apply_all(ctx, __apply_timeline, timeline);
-}
-
-static int __apply_watchdog(struct intel_context *ce, void *timeout_us)
-{
- return intel_context_set_watchdog_us(ce, (uintptr_t)timeout_us);
-}
-
-static int
-__set_watchdog(struct i915_gem_context *ctx, unsigned long timeout_us)
-{
- int ret;
-
- ret = context_apply_all(ctx, __apply_watchdog,
- (void *)(uintptr_t)timeout_us);
- if (!ret)
- ctx->watchdog.timeout_us = timeout_us;
-
- return ret;
-}
-
-static void __set_default_fence_expiry(struct i915_gem_context *ctx)
-{
- struct drm_i915_private *i915 = ctx->i915;
- int ret;
-
- if (!IS_ACTIVE(CONFIG_DRM_I915_REQUEST_TIMEOUT) ||
- !i915->params.request_timeout_ms)
- return;
-
- /* Default expiry for user fences. */
- ret = __set_watchdog(ctx, i915->params.request_timeout_ms * 1000);
- if (ret)
- drm_notice(&i915->drm,
- "Failed to configure default fence expiry! (%d)",
- ret);
}
static struct i915_gem_context *
-i915_gem_create_context(struct drm_i915_private *i915, unsigned int flags)
+i915_gem_create_context(struct drm_i915_private *i915,
+ const struct i915_gem_proto_context *pc)
{
struct i915_gem_context *ctx;
+ struct i915_address_space *vm = NULL;
+ struct i915_gem_engines *e;
+ int err;
+ int i;
- if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE &&
- !HAS_EXECLISTS(i915))
- return ERR_PTR(-EINVAL);
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
- ctx = __create_context(i915);
- if (IS_ERR(ctx))
- return ctx;
+ kref_init(&ctx->ref);
+ ctx->i915 = i915;
+ ctx->sched = pc->sched;
+ mutex_init(&ctx->mutex);
+ INIT_LIST_HEAD(&ctx->link);
- if (HAS_FULL_PPGTT(i915)) {
+ spin_lock_init(&ctx->stale.lock);
+ INIT_LIST_HEAD(&ctx->stale.engines);
+
+ if (pc->vm) {
+ vm = i915_vm_get(pc->vm);
+ } else if (HAS_FULL_PPGTT(i915)) {
struct i915_ppgtt *ppgtt;
ppgtt = i915_ppgtt_create(&i915->gt);
if (IS_ERR(ppgtt)) {
drm_dbg(&i915->drm, "PPGTT setup failed (%ld)\n",
PTR_ERR(ppgtt));
- context_close(ctx);
- return ERR_CAST(ppgtt);
+ err = PTR_ERR(ppgtt);
+ goto err_ctx;
}
+ vm = &ppgtt->vm;
+ }
+ if (vm) {
+ RCU_INIT_POINTER(ctx->vm, i915_vm_open(vm));
- mutex_lock(&ctx->mutex);
- __assign_ppgtt(ctx, &ppgtt->vm);
- mutex_unlock(&ctx->mutex);
+ /* i915_vm_open() takes a reference */
+ i915_vm_put(vm);
+ }
- i915_vm_put(&ppgtt->vm);
+ mutex_init(&ctx->engines_mutex);
+ if (pc->num_user_engines >= 0) {
+ i915_gem_context_set_user_engines(ctx);
+ e = user_engines(ctx, pc->num_user_engines, pc->user_engines);
+ } else {
+ i915_gem_context_clear_user_engines(ctx);
+ e = default_engines(ctx, pc->legacy_rcs_sseu);
+ }
+ if (IS_ERR(e)) {
+ err = PTR_ERR(e);
+ goto err_vm;
}
+ RCU_INIT_POINTER(ctx->engines, e);
- if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) {
- struct intel_timeline *timeline;
+ INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
+ mutex_init(&ctx->lut_mutex);
- timeline = intel_timeline_create(&i915->gt);
- if (IS_ERR(timeline)) {
- context_close(ctx);
- return ERR_CAST(timeline);
- }
+ /* NB: Mark all slices as needing a remap so that when the context first
+ * loads it will restore whatever remap state already exists. If there
+ * is no remap info, it will be a NOP. */
+ ctx->remap_slice = ALL_L3_SLICES(i915);
- __assign_timeline(ctx, timeline);
- intel_timeline_put(timeline);
- }
+ ctx->user_flags = pc->user_flags;
- __set_default_fence_expiry(ctx);
+ for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++)
+ ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES;
+
+ if (pc->single_timeline) {
+ err = drm_syncobj_create(&ctx->syncobj,
+ DRM_SYNCOBJ_CREATE_SIGNALED,
+ NULL);
+ if (err)
+ goto err_engines;
+ }
trace_i915_context_create(ctx);
return ctx;
+
+err_engines:
+ free_engines(e);
+err_vm:
+ if (ctx->vm)
+ i915_vm_close(ctx->vm);
+err_ctx:
+ kfree(ctx);
+ return ERR_PTR(err);
}
static void init_contexts(struct i915_gem_contexts *gc)
@@ -889,83 +1424,83 @@ void i915_gem_init__contexts(struct drm_i915_private *i915)
init_contexts(&i915->gem.contexts);
}
-static int gem_context_register(struct i915_gem_context *ctx,
- struct drm_i915_file_private *fpriv,
- u32 *id)
+static void gem_context_register(struct i915_gem_context *ctx,
+ struct drm_i915_file_private *fpriv,
+ u32 id)
{
struct drm_i915_private *i915 = ctx->i915;
- struct i915_address_space *vm;
- int ret;
+ void *old;
ctx->file_priv = fpriv;
- mutex_lock(&ctx->mutex);
- vm = i915_gem_context_vm(ctx);
- if (vm)
- WRITE_ONCE(vm->file, fpriv); /* XXX */
- mutex_unlock(&ctx->mutex);
-
ctx->pid = get_task_pid(current, PIDTYPE_PID);
snprintf(ctx->name, sizeof(ctx->name), "%s[%d]",
current->comm, pid_nr(ctx->pid));
/* And finally expose ourselves to userspace via the idr */
- ret = xa_alloc(&fpriv->context_xa, id, ctx, xa_limit_32b, GFP_KERNEL);
- if (ret)
- goto err_pid;
+ old = xa_store(&fpriv->context_xa, id, ctx, GFP_KERNEL);
+ WARN_ON(old);
spin_lock(&i915->gem.contexts.lock);
list_add_tail(&ctx->link, &i915->gem.contexts.list);
spin_unlock(&i915->gem.contexts.lock);
-
- return 0;
-
-err_pid:
- put_pid(fetch_and_zero(&ctx->pid));
- return ret;
}
int i915_gem_context_open(struct drm_i915_private *i915,
struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct i915_gem_proto_context *pc;
struct i915_gem_context *ctx;
int err;
- u32 id;
- xa_init_flags(&file_priv->context_xa, XA_FLAGS_ALLOC);
+ mutex_init(&file_priv->proto_context_lock);
+ xa_init_flags(&file_priv->proto_context_xa, XA_FLAGS_ALLOC);
+
+ /* 0 reserved for the default context */
+ xa_init_flags(&file_priv->context_xa, XA_FLAGS_ALLOC1);
/* 0 reserved for invalid/unassigned ppgtt */
xa_init_flags(&file_priv->vm_xa, XA_FLAGS_ALLOC1);
- ctx = i915_gem_create_context(i915, 0);
+ pc = proto_context_create(i915, 0);
+ if (IS_ERR(pc)) {
+ err = PTR_ERR(pc);
+ goto err;
+ }
+
+ ctx = i915_gem_create_context(i915, pc);
+ proto_context_close(pc);
if (IS_ERR(ctx)) {
err = PTR_ERR(ctx);
goto err;
}
- err = gem_context_register(ctx, file_priv, &id);
- if (err < 0)
- goto err_ctx;
+ gem_context_register(ctx, file_priv, 0);
- GEM_BUG_ON(id);
return 0;
-err_ctx:
- context_close(ctx);
err:
xa_destroy(&file_priv->vm_xa);
xa_destroy(&file_priv->context_xa);
+ xa_destroy(&file_priv->proto_context_xa);
+ mutex_destroy(&file_priv->proto_context_lock);
return err;
}
void i915_gem_context_close(struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct i915_gem_proto_context *pc;
struct i915_address_space *vm;
struct i915_gem_context *ctx;
unsigned long idx;
+ xa_for_each(&file_priv->proto_context_xa, idx, pc)
+ proto_context_close(pc);
+ xa_destroy(&file_priv->proto_context_xa);
+ mutex_destroy(&file_priv->proto_context_lock);
+
xa_for_each(&file_priv->context_xa, idx, ctx)
context_close(ctx);
xa_destroy(&file_priv->context_xa);
@@ -995,8 +1530,6 @@ int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,
if (IS_ERR(ppgtt))
return PTR_ERR(ppgtt);
- ppgtt->vm.file = file_priv;
-
if (args->extensions) {
err = i915_user_extensions(u64_to_user_ptr(args->extensions),
NULL, 0,
@@ -1040,120 +1573,6 @@ int i915_gem_vm_destroy_ioctl(struct drm_device *dev, void *data,
return 0;
}
-struct context_barrier_task {
- struct i915_active base;
- void (*task)(void *data);
- void *data;
-};
-
-static void cb_retire(struct i915_active *base)
-{
- struct context_barrier_task *cb = container_of(base, typeof(*cb), base);
-
- if (cb->task)
- cb->task(cb->data);
-
- i915_active_fini(&cb->base);
- kfree(cb);
-}
-
-I915_SELFTEST_DECLARE(static intel_engine_mask_t context_barrier_inject_fault);
-static int context_barrier_task(struct i915_gem_context *ctx,
- intel_engine_mask_t engines,
- bool (*skip)(struct intel_context *ce, void *data),
- int (*pin)(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void *data),
- int (*emit)(struct i915_request *rq, void *data),
- void (*task)(void *data),
- void *data)
-{
- struct context_barrier_task *cb;
- struct i915_gem_engines_iter it;
- struct i915_gem_engines *e;
- struct i915_gem_ww_ctx ww;
- struct intel_context *ce;
- int err = 0;
-
- GEM_BUG_ON(!task);
-
- cb = kmalloc(sizeof(*cb), GFP_KERNEL);
- if (!cb)
- return -ENOMEM;
-
- i915_active_init(&cb->base, NULL, cb_retire, 0);
- err = i915_active_acquire(&cb->base);
- if (err) {
- kfree(cb);
- return err;
- }
-
- e = __context_engines_await(ctx, NULL);
- if (!e) {
- i915_active_release(&cb->base);
- return -ENOENT;
- }
-
- for_each_gem_engine(ce, e, it) {
- struct i915_request *rq;
-
- if (I915_SELFTEST_ONLY(context_barrier_inject_fault &
- ce->engine->mask)) {
- err = -ENXIO;
- break;
- }
-
- if (!(ce->engine->mask & engines))
- continue;
-
- if (skip && skip(ce, data))
- continue;
-
- i915_gem_ww_ctx_init(&ww, true);
-retry:
- err = intel_context_pin_ww(ce, &ww);
- if (err)
- goto err;
-
- if (pin)
- err = pin(ce, &ww, data);
- if (err)
- goto err_unpin;
-
- rq = i915_request_create(ce);
- if (IS_ERR(rq)) {
- err = PTR_ERR(rq);
- goto err_unpin;
- }
-
- err = 0;
- if (emit)
- err = emit(rq, data);
- if (err == 0)
- err = i915_active_add_request(&cb->base, rq);
-
- i915_request_add(rq);
-err_unpin:
- intel_context_unpin(ce);
-err:
- if (err == -EDEADLK) {
- err = i915_gem_ww_ctx_backoff(&ww);
- if (!err)
- goto retry;
- }
- i915_gem_ww_ctx_fini(&ww);
-
- if (err)
- break;
- }
- i915_sw_fence_complete(&e->fence);
-
- cb->task = err ? NULL : task; /* caller needs to unwind instead */
- cb->data = data;
-
- i915_active_release(&cb->base);
-
- return err;
-}
-
static int get_ppgtt(struct drm_i915_file_private *file_priv,
struct i915_gem_context *ctx,
struct drm_i915_gem_context_param *args)
@@ -1186,211 +1605,6 @@ err_put:
return err;
}
-static void set_ppgtt_barrier(void *data)
-{
- struct i915_address_space *old = data;
-
- if (GRAPHICS_VER(old->i915) < 8)
- gen6_ppgtt_unpin_all(i915_vm_to_ppgtt(old));
-
- i915_vm_close(old);
-}
-
-static int pin_ppgtt_update(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void *data)
-{
- struct i915_address_space *vm = ce->vm;
-
- if (!HAS_LOGICAL_RING_CONTEXTS(vm->i915))
- /* ppGTT is not part of the legacy context image */
- return gen6_ppgtt_pin(i915_vm_to_ppgtt(vm), ww);
-
- return 0;
-}
-
-static int emit_ppgtt_update(struct i915_request *rq, void *data)
-{
- struct i915_address_space *vm = rq->context->vm;
- struct intel_engine_cs *engine = rq->engine;
- u32 base = engine->mmio_base;
- u32 *cs;
- int i;
-
- if (i915_vm_is_4lvl(vm)) {
- struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
- const dma_addr_t pd_daddr = px_dma(ppgtt->pd);
-
- cs = intel_ring_begin(rq, 6);
- if (IS_ERR(cs))
- return PTR_ERR(cs);
-
- *cs++ = MI_LOAD_REGISTER_IMM(2);
-
- *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(base, 0));
- *cs++ = upper_32_bits(pd_daddr);
- *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(base, 0));
- *cs++ = lower_32_bits(pd_daddr);
-
- *cs++ = MI_NOOP;
- intel_ring_advance(rq, cs);
- } else if (HAS_LOGICAL_RING_CONTEXTS(engine->i915)) {
- struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
- int err;
-
- /* Magic required to prevent forcewake errors! */
- err = engine->emit_flush(rq, EMIT_INVALIDATE);
- if (err)
- return err;
-
- cs = intel_ring_begin(rq, 4 * GEN8_3LVL_PDPES + 2);
- if (IS_ERR(cs))
- return PTR_ERR(cs);
-
- *cs++ = MI_LOAD_REGISTER_IMM(2 * GEN8_3LVL_PDPES) | MI_LRI_FORCE_POSTED;
- for (i = GEN8_3LVL_PDPES; i--; ) {
- const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
-
- *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(base, i));
- *cs++ = upper_32_bits(pd_daddr);
- *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(base, i));
- *cs++ = lower_32_bits(pd_daddr);
- }
- *cs++ = MI_NOOP;
- intel_ring_advance(rq, cs);
- }
-
- return 0;
-}
-
-static bool skip_ppgtt_update(struct intel_context *ce, void *data)
-{
- if (HAS_LOGICAL_RING_CONTEXTS(ce->engine->i915))
- return !ce->state;
- else
- return !atomic_read(&ce->pin_count);
-}
-
-static int set_ppgtt(struct drm_i915_file_private *file_priv,
- struct i915_gem_context *ctx,
- struct drm_i915_gem_context_param *args)
-{
- struct i915_address_space *vm, *old;
- int err;
-
- if (args->size)
- return -EINVAL;
-
- if (!rcu_access_pointer(ctx->vm))
- return -ENODEV;
-
- if (upper_32_bits(args->value))
- return -ENOENT;
-
- rcu_read_lock();
- vm = xa_load(&file_priv->vm_xa, args->value);
- if (vm && !kref_get_unless_zero(&vm->ref))
- vm = NULL;
- rcu_read_unlock();
- if (!vm)
- return -ENOENT;
-
- err = mutex_lock_interruptible(&ctx->mutex);
- if (err)
- goto out;
-
- if (i915_gem_context_is_closed(ctx)) {
- err = -ENOENT;
- goto unlock;
- }
-
- if (vm == rcu_access_pointer(ctx->vm))
- goto unlock;
-
- old = __set_ppgtt(ctx, vm);
-
- /* Teardown the existing obj:vma cache, it will have to be rebuilt. */
- lut_close(ctx);
-
- /*
- * We need to flush any requests using the current ppgtt before
- * we release it as the requests do not hold a reference themselves,
- * only indirectly through the context.
- */
- err = context_barrier_task(ctx, ALL_ENGINES,
- skip_ppgtt_update,
- pin_ppgtt_update,
- emit_ppgtt_update,
- set_ppgtt_barrier,
- old);
- if (err) {
- i915_vm_close(__set_ppgtt(ctx, old));
- i915_vm_close(old);
- lut_close(ctx); /* force a rebuild of the old obj:vma cache */
- }
-
-unlock:
- mutex_unlock(&ctx->mutex);
-out:
- i915_vm_put(vm);
- return err;
-}
-
-static int __apply_ringsize(struct intel_context *ce, void *sz)
-{
- return intel_context_set_ring_size(ce, (unsigned long)sz);
-}
-
-static int set_ringsize(struct i915_gem_context *ctx,
- struct drm_i915_gem_context_param *args)
-{
- if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
- return -ENODEV;
-
- if (args->size)
- return -EINVAL;
-
- if (!IS_ALIGNED(args->value, I915_GTT_PAGE_SIZE))
- return -EINVAL;
-
- if (args->value < I915_GTT_PAGE_SIZE)
- return -EINVAL;
-
- if (args->value > 128 * I915_GTT_PAGE_SIZE)
- return -EINVAL;
-
- return context_apply_all(ctx,
- __apply_ringsize,
- __intel_context_ring_size(args->value));
-}
-
-static int __get_ringsize(struct intel_context *ce, void *arg)
-{
- long sz;
-
- sz = intel_context_get_ring_size(ce);
- GEM_BUG_ON(sz > INT_MAX);
-
- return sz; /* stop on first engine */
-}
-
-static int get_ringsize(struct i915_gem_context *ctx,
- struct drm_i915_gem_context_param *args)
-{
- int sz;
-
- if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
- return -ENODEV;
-
- if (args->size)
- return -EINVAL;
-
- sz = context_apply_all(ctx, __get_ringsize, NULL);
- if (sz < 0)
- return sz;
-
- args->value = sz;
- return 0;
-}
-
int
i915_gem_user_to_context_sseu(struct intel_gt *gt,
const struct drm_i915_gem_context_param_sseu *user,
@@ -1545,382 +1759,6 @@ out_ce:
return ret;
}
-struct set_engines {
- struct i915_gem_context *ctx;
- struct i915_gem_engines *engines;
-};
-
-static int
-set_engines__load_balance(struct i915_user_extension __user *base, void *data)
-{
- struct i915_context_engines_load_balance __user *ext =
- container_of_user(base, typeof(*ext), base);
- const struct set_engines *set = data;
- struct drm_i915_private *i915 = set->ctx->i915;
- struct intel_engine_cs *stack[16];
- struct intel_engine_cs **siblings;
- struct intel_context *ce;
- u16 num_siblings, idx;
- unsigned int n;
- int err;
-
- if (!HAS_EXECLISTS(i915))
- return -ENODEV;
-
- if (intel_uc_uses_guc_submission(&i915->gt.uc))
- return -ENODEV; /* not implement yet */
-
- if (get_user(idx, &ext->engine_index))
- return -EFAULT;
-
- if (idx >= set->engines->num_engines) {
- drm_dbg(&i915->drm, "Invalid placement value, %d >= %d\n",
- idx, set->engines->num_engines);
- return -EINVAL;
- }
-
- idx = array_index_nospec(idx, set->engines->num_engines);
- if (set->engines->engines[idx]) {
- drm_dbg(&i915->drm,
- "Invalid placement[%d], already occupied\n", idx);
- return -EEXIST;
- }
-
- if (get_user(num_siblings, &ext->num_siblings))
- return -EFAULT;
-
- err = check_user_mbz(&ext->flags);
- if (err)
- return err;
-
- err = check_user_mbz(&ext->mbz64);
- if (err)
- return err;
-
- siblings = stack;
- if (num_siblings > ARRAY_SIZE(stack)) {
- siblings = kmalloc_array(num_siblings,
- sizeof(*siblings),
- GFP_KERNEL);
- if (!siblings)
- return -ENOMEM;
- }
-
- for (n = 0; n < num_siblings; n++) {
- struct i915_engine_class_instance ci;
-
- if (copy_from_user(&ci, &ext->engines[n], sizeof(ci))) {
- err = -EFAULT;
- goto out_siblings;
- }
-
- siblings[n] = intel_engine_lookup_user(i915,
- ci.engine_class,
- ci.engine_instance);
- if (!siblings[n]) {
- drm_dbg(&i915->drm,
- "Invalid sibling[%d]: { class:%d, inst:%d }\n",
- n, ci.engine_class, ci.engine_instance);
- err = -EINVAL;
- goto out_siblings;
- }
- }
-
- ce = intel_execlists_create_virtual(siblings, n);
- if (IS_ERR(ce)) {
- err = PTR_ERR(ce);
- goto out_siblings;
- }
-
- intel_context_set_gem(ce, set->ctx);
-
- if (cmpxchg(&set->engines->engines[idx], NULL, ce)) {
- intel_context_put(ce);
- err = -EEXIST;
- goto out_siblings;
- }
-
-out_siblings:
- if (siblings != stack)
- kfree(siblings);
-
- return err;
-}
-
-static int
-set_engines__bond(struct i915_user_extension __user *base, void *data)
-{
- struct i915_context_engines_bond __user *ext =
- container_of_user(base, typeof(*ext), base);
- const struct set_engines *set = data;
- struct drm_i915_private *i915 = set->ctx->i915;
- struct i915_engine_class_instance ci;
- struct intel_engine_cs *virtual;
- struct intel_engine_cs *master;
- u16 idx, num_bonds;
- int err, n;
-
- if (get_user(idx, &ext->virtual_index))
- return -EFAULT;
-
- if (idx >= set->engines->num_engines) {
- drm_dbg(&i915->drm,
- "Invalid index for virtual engine: %d >= %d\n",
- idx, set->engines->num_engines);
- return -EINVAL;
- }
-
- idx = array_index_nospec(idx, set->engines->num_engines);
- if (!set->engines->engines[idx]) {
- drm_dbg(&i915->drm, "Invalid engine at %d\n", idx);
- return -EINVAL;
- }
- virtual = set->engines->engines[idx]->engine;
-
- err = check_user_mbz(&ext->flags);
- if (err)
- return err;
-
- for (n = 0; n < ARRAY_SIZE(ext->mbz64); n++) {
- err = check_user_mbz(&ext->mbz64[n]);
- if (err)
- return err;
- }
-
- if (copy_from_user(&ci, &ext->master, sizeof(ci)))
- return -EFAULT;
-
- master = intel_engine_lookup_user(i915,
- ci.engine_class, ci.engine_instance);
- if (!master) {
- drm_dbg(&i915->drm,
- "Unrecognised master engine: { class:%u, instance:%u }\n",
- ci.engine_class, ci.engine_instance);
- return -EINVAL;
- }
-
- if (get_user(num_bonds, &ext->num_bonds))
- return -EFAULT;
-
- for (n = 0; n < num_bonds; n++) {
- struct intel_engine_cs *bond;
-
- if (copy_from_user(&ci, &ext->engines[n], sizeof(ci)))
- return -EFAULT;
-
- bond = intel_engine_lookup_user(i915,
- ci.engine_class,
- ci.engine_instance);
- if (!bond) {
- drm_dbg(&i915->drm,
- "Unrecognised engine[%d] for bonding: { class:%d, instance: %d }\n",
- n, ci.engine_class, ci.engine_instance);
- return -EINVAL;
- }
-
- /*
- * A non-virtual engine has no siblings to choose between; and
- * a submit fence will always be directed to the one engine.
- */
- if (intel_engine_is_virtual(virtual)) {
- err = intel_virtual_engine_attach_bond(virtual,
- master,
- bond);
- if (err)
- return err;
- }
- }
-
- return 0;
-}
-
-static const i915_user_extension_fn set_engines__extensions[] = {
- [I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE] = set_engines__load_balance,
- [I915_CONTEXT_ENGINES_EXT_BOND] = set_engines__bond,
-};
-
-static int
-set_engines(struct i915_gem_context *ctx,
- const struct drm_i915_gem_context_param *args)
-{
- struct drm_i915_private *i915 = ctx->i915;
- struct i915_context_param_engines __user *user =
- u64_to_user_ptr(args->value);
- struct set_engines set = { .ctx = ctx };
- unsigned int num_engines, n;
- u64 extensions;
- int err;
-
- if (!args->size) { /* switch back to legacy user_ring_map */
- if (!i915_gem_context_user_engines(ctx))
- return 0;
-
- set.engines = default_engines(ctx);
- if (IS_ERR(set.engines))
- return PTR_ERR(set.engines);
-
- goto replace;
- }
-
- BUILD_BUG_ON(!IS_ALIGNED(sizeof(*user), sizeof(*user->engines)));
- if (args->size < sizeof(*user) ||
- !IS_ALIGNED(args->size, sizeof(*user->engines))) {
- drm_dbg(&i915->drm, "Invalid size for engine array: %d\n",
- args->size);
- return -EINVAL;
- }
-
- /*
- * Note that I915_EXEC_RING_MASK limits execbuf to only using the
- * first 64 engines defined here.
- */
- num_engines = (args->size - sizeof(*user)) / sizeof(*user->engines);
- set.engines = alloc_engines(num_engines);
- if (!set.engines)
- return -ENOMEM;
-
- for (n = 0; n < num_engines; n++) {
- struct i915_engine_class_instance ci;
- struct intel_engine_cs *engine;
- struct intel_context *ce;
-
- if (copy_from_user(&ci, &user->engines[n], sizeof(ci))) {
- __free_engines(set.engines, n);
- return -EFAULT;
- }
-
- if (ci.engine_class == (u16)I915_ENGINE_CLASS_INVALID &&
- ci.engine_instance == (u16)I915_ENGINE_CLASS_INVALID_NONE) {
- set.engines->engines[n] = NULL;
- continue;
- }
-
- engine = intel_engine_lookup_user(ctx->i915,
- ci.engine_class,
- ci.engine_instance);
- if (!engine) {
- drm_dbg(&i915->drm,
- "Invalid engine[%d]: { class:%d, instance:%d }\n",
- n, ci.engine_class, ci.engine_instance);
- __free_engines(set.engines, n);
- return -ENOENT;
- }
-
- ce = intel_context_create(engine);
- if (IS_ERR(ce)) {
- __free_engines(set.engines, n);
- return PTR_ERR(ce);
- }
-
- intel_context_set_gem(ce, ctx);
-
- set.engines->engines[n] = ce;
- }
- set.engines->num_engines = num_engines;
-
- err = -EFAULT;
- if (!get_user(extensions, &user->extensions))
- err = i915_user_extensions(u64_to_user_ptr(extensions),
- set_engines__extensions,
- ARRAY_SIZE(set_engines__extensions),
- &set);
- if (err) {
- free_engines(set.engines);
- return err;
- }
-
-replace:
- mutex_lock(&ctx->engines_mutex);
- if (i915_gem_context_is_closed(ctx)) {
- mutex_unlock(&ctx->engines_mutex);
- free_engines(set.engines);
- return -ENOENT;
- }
- if (args->size)
- i915_gem_context_set_user_engines(ctx);
- else
- i915_gem_context_clear_user_engines(ctx);
- set.engines = rcu_replace_pointer(ctx->engines, set.engines, 1);
- mutex_unlock(&ctx->engines_mutex);
-
- /* Keep track of old engine sets for kill_context() */
- engines_idle_release(ctx, set.engines);
-
- return 0;
-}
-
-static int
-get_engines(struct i915_gem_context *ctx,
- struct drm_i915_gem_context_param *args)
-{
- struct i915_context_param_engines __user *user;
- struct i915_gem_engines *e;
- size_t n, count, size;
- bool user_engines;
- int err = 0;
-
- e = __context_engines_await(ctx, &user_engines);
- if (!e)
- return -ENOENT;
-
- if (!user_engines) {
- i915_sw_fence_complete(&e->fence);
- args->size = 0;
- return 0;
- }
-
- count = e->num_engines;
-
- /* Be paranoid in case we have an impedance mismatch */
- if (!check_struct_size(user, engines, count, &size)) {
- err = -EINVAL;
- goto err_free;
- }
- if (overflows_type(size, args->size)) {
- err = -EINVAL;
- goto err_free;
- }
-
- if (!args->size) {
- args->size = size;
- goto err_free;
- }
-
- if (args->size < size) {
- err = -EINVAL;
- goto err_free;
- }
-
- user = u64_to_user_ptr(args->value);
- if (put_user(0, &user->extensions)) {
- err = -EFAULT;
- goto err_free;
- }
-
- for (n = 0; n < count; n++) {
- struct i915_engine_class_instance ci = {
- .engine_class = I915_ENGINE_CLASS_INVALID,
- .engine_instance = I915_ENGINE_CLASS_INVALID_NONE,
- };
-
- if (e->engines[n]) {
- ci.engine_class = e->engines[n]->engine->uabi_class;
- ci.engine_instance = e->engines[n]->engine->uabi_instance;
- }
-
- if (copy_to_user(&user->engines[n], &ci, sizeof(ci))) {
- err = -EFAULT;
- goto err_free;
- }
- }
-
- args->size = size;
-
-err_free:
- i915_sw_fence_complete(&e->fence);
- return err;
-}
-
static int
set_persistence(struct i915_gem_context *ctx,
const struct drm_i915_gem_context_param *args)
@@ -1931,41 +1769,30 @@ set_persistence(struct i915_gem_context *ctx,
return __context_set_persistence(ctx, args->value);
}
-static int __apply_priority(struct intel_context *ce, void *arg)
+static void __apply_priority(struct intel_context *ce, void *arg)
{
struct i915_gem_context *ctx = arg;
if (!intel_engine_has_timeslices(ce->engine))
- return 0;
+ return;
- if (ctx->sched.priority >= I915_PRIORITY_NORMAL)
+ if (ctx->sched.priority >= I915_PRIORITY_NORMAL &&
+ intel_engine_has_semaphores(ce->engine))
intel_context_set_use_semaphores(ce);
else
intel_context_clear_use_semaphores(ce);
-
- return 0;
}
static int set_priority(struct i915_gem_context *ctx,
const struct drm_i915_gem_context_param *args)
{
- s64 priority = args->value;
-
- if (args->size)
- return -EINVAL;
-
- if (!(ctx->i915->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY))
- return -ENODEV;
-
- if (priority > I915_CONTEXT_MAX_USER_PRIORITY ||
- priority < I915_CONTEXT_MIN_USER_PRIORITY)
- return -EINVAL;
+ int err;
- if (priority > I915_CONTEXT_DEFAULT_PRIORITY &&
- !capable(CAP_SYS_NICE))
- return -EPERM;
+ err = validate_priority(ctx->i915, args);
+ if (err)
+ return err;
- ctx->sched.priority = priority;
+ ctx->sched.priority = args->value;
context_apply_all(ctx, __apply_priority, ctx);
return 0;
@@ -1978,15 +1805,6 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
int ret = 0;
switch (args->param) {
- case I915_CONTEXT_PARAM_NO_ZEROMAP:
- if (args->size)
- ret = -EINVAL;
- else if (args->value)
- set_bit(UCONTEXT_NO_ZEROMAP, &ctx->user_flags);
- else
- clear_bit(UCONTEXT_NO_ZEROMAP, &ctx->user_flags);
- break;
-
case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:
if (args->size)
ret = -EINVAL;
@@ -2024,23 +1842,15 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
ret = set_sseu(ctx, args);
break;
- case I915_CONTEXT_PARAM_VM:
- ret = set_ppgtt(fpriv, ctx, args);
- break;
-
- case I915_CONTEXT_PARAM_ENGINES:
- ret = set_engines(ctx, args);
- break;
-
case I915_CONTEXT_PARAM_PERSISTENCE:
ret = set_persistence(ctx, args);
break;
- case I915_CONTEXT_PARAM_RINGSIZE:
- ret = set_ringsize(ctx, args);
- break;
-
+ case I915_CONTEXT_PARAM_NO_ZEROMAP:
case I915_CONTEXT_PARAM_BAN_PERIOD:
+ case I915_CONTEXT_PARAM_RINGSIZE:
+ case I915_CONTEXT_PARAM_VM:
+ case I915_CONTEXT_PARAM_ENGINES:
default:
ret = -EINVAL;
break;
@@ -2050,7 +1860,7 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
}
struct create_ext {
- struct i915_gem_context *ctx;
+ struct i915_gem_proto_context *pc;
struct drm_i915_file_private *fpriv;
};
@@ -2065,233 +1875,84 @@ static int create_setparam(struct i915_user_extension __user *ext, void *data)
if (local.param.ctx_id)
return -EINVAL;
- return ctx_setparam(arg->fpriv, arg->ctx, &local.param);
+ return set_proto_ctx_param(arg->fpriv, arg->pc, &local.param);
}
-static int copy_ring_size(struct intel_context *dst,
- struct intel_context *src)
+static int invalid_ext(struct i915_user_extension __user *ext, void *data)
{
- long sz;
-
- sz = intel_context_get_ring_size(src);
- if (sz < 0)
- return sz;
-
- return intel_context_set_ring_size(dst, sz);
+ return -EINVAL;
}
-static int clone_engines(struct i915_gem_context *dst,
- struct i915_gem_context *src)
-{
- struct i915_gem_engines *clone, *e;
- bool user_engines;
- unsigned long n;
-
- e = __context_engines_await(src, &user_engines);
- if (!e)
- return -ENOENT;
-
- clone = alloc_engines(e->num_engines);
- if (!clone)
- goto err_unlock;
-
- for (n = 0; n < e->num_engines; n++) {
- struct intel_engine_cs *engine;
-
- if (!e->engines[n]) {
- clone->engines[n] = NULL;
- continue;
- }
- engine = e->engines[n]->engine;
-
- /*
- * Virtual engines are singletons; they can only exist
- * inside a single context, because they embed their
- * HW context... As each virtual context implies a single
- * timeline (each engine can only dequeue a single request
- * at any time), it would be surprising for two contexts
- * to use the same engine. So let's create a copy of
- * the virtual engine instead.
- */
- if (intel_engine_is_virtual(engine))
- clone->engines[n] =
- intel_execlists_clone_virtual(engine);
- else
- clone->engines[n] = intel_context_create(engine);
- if (IS_ERR_OR_NULL(clone->engines[n])) {
- __free_engines(clone, n);
- goto err_unlock;
- }
-
- intel_context_set_gem(clone->engines[n], dst);
-
- /* Copy across the preferred ringsize */
- if (copy_ring_size(clone->engines[n], e->engines[n])) {
- __free_engines(clone, n + 1);
- goto err_unlock;
- }
- }
- clone->num_engines = n;
- i915_sw_fence_complete(&e->fence);
-
- /* Serialised by constructor */
- engines_idle_release(dst, rcu_replace_pointer(dst->engines, clone, 1));
- if (user_engines)
- i915_gem_context_set_user_engines(dst);
- else
- i915_gem_context_clear_user_engines(dst);
- return 0;
-
-err_unlock:
- i915_sw_fence_complete(&e->fence);
- return -ENOMEM;
-}
-
-static int clone_flags(struct i915_gem_context *dst,
- struct i915_gem_context *src)
-{
- dst->user_flags = src->user_flags;
- return 0;
-}
-
-static int clone_schedattr(struct i915_gem_context *dst,
- struct i915_gem_context *src)
-{
- dst->sched = src->sched;
- return 0;
-}
-
-static int clone_sseu(struct i915_gem_context *dst,
- struct i915_gem_context *src)
-{
- struct i915_gem_engines *e = i915_gem_context_lock_engines(src);
- struct i915_gem_engines *clone;
- unsigned long n;
- int err;
-
- /* no locking required; sole access under constructor*/
- clone = __context_engines_static(dst);
- if (e->num_engines != clone->num_engines) {
- err = -EINVAL;
- goto unlock;
- }
-
- for (n = 0; n < e->num_engines; n++) {
- struct intel_context *ce = e->engines[n];
-
- if (clone->engines[n]->engine->class != ce->engine->class) {
- /* Must have compatible engine maps! */
- err = -EINVAL;
- goto unlock;
- }
-
- /* serialises with set_sseu */
- err = intel_context_lock_pinned(ce);
- if (err)
- goto unlock;
-
- clone->engines[n]->sseu = ce->sseu;
- intel_context_unlock_pinned(ce);
- }
-
- err = 0;
-unlock:
- i915_gem_context_unlock_engines(src);
- return err;
-}
+static const i915_user_extension_fn create_extensions[] = {
+ [I915_CONTEXT_CREATE_EXT_SETPARAM] = create_setparam,
+ [I915_CONTEXT_CREATE_EXT_CLONE] = invalid_ext,
+};
-static int clone_timeline(struct i915_gem_context *dst,
- struct i915_gem_context *src)
+static bool client_is_banned(struct drm_i915_file_private *file_priv)
{
- if (src->timeline)
- __assign_timeline(dst, src->timeline);
-
- return 0;
+ return atomic_read(&file_priv->ban_score) >= I915_CLIENT_SCORE_BANNED;
}
-static int clone_vm(struct i915_gem_context *dst,
- struct i915_gem_context *src)
+static inline struct i915_gem_context *
+__context_lookup(struct drm_i915_file_private *file_priv, u32 id)
{
- struct i915_address_space *vm;
- int err = 0;
-
- if (!rcu_access_pointer(src->vm))
- return 0;
+ struct i915_gem_context *ctx;
rcu_read_lock();
- vm = context_get_vm_rcu(src);
+ ctx = xa_load(&file_priv->context_xa, id);
+ if (ctx && !kref_get_unless_zero(&ctx->ref))
+ ctx = NULL;
rcu_read_unlock();
- if (!mutex_lock_interruptible(&dst->mutex)) {
- __assign_ppgtt(dst, vm);
- mutex_unlock(&dst->mutex);
- } else {
- err = -EINTR;
- }
-
- i915_vm_put(vm);
- return err;
+ return ctx;
}
-static int create_clone(struct i915_user_extension __user *ext, void *data)
-{
- static int (* const fn[])(struct i915_gem_context *dst,
- struct i915_gem_context *src) = {
-#define MAP(x, y) [ilog2(I915_CONTEXT_CLONE_##x)] = y
- MAP(ENGINES, clone_engines),
- MAP(FLAGS, clone_flags),
- MAP(SCHEDATTR, clone_schedattr),
- MAP(SSEU, clone_sseu),
- MAP(TIMELINE, clone_timeline),
- MAP(VM, clone_vm),
-#undef MAP
- };
- struct drm_i915_gem_context_create_ext_clone local;
- const struct create_ext *arg = data;
- struct i915_gem_context *dst = arg->ctx;
- struct i915_gem_context *src;
- int err, bit;
+static struct i915_gem_context *
+finalize_create_context_locked(struct drm_i915_file_private *file_priv,
+ struct i915_gem_proto_context *pc, u32 id)
+{
+ struct i915_gem_context *ctx;
+ void *old;
- if (copy_from_user(&local, ext, sizeof(local)))
- return -EFAULT;
+ lockdep_assert_held(&file_priv->proto_context_lock);
- BUILD_BUG_ON(GENMASK(BITS_PER_TYPE(local.flags) - 1, ARRAY_SIZE(fn)) !=
- I915_CONTEXT_CLONE_UNKNOWN);
+ ctx = i915_gem_create_context(file_priv->dev_priv, pc);
+ if (IS_ERR(ctx))
+ return ctx;
- if (local.flags & I915_CONTEXT_CLONE_UNKNOWN)
- return -EINVAL;
+ gem_context_register(ctx, file_priv, id);
- if (local.rsvd)
- return -EINVAL;
+ old = xa_erase(&file_priv->proto_context_xa, id);
+ GEM_BUG_ON(old != pc);
+ proto_context_close(pc);
- rcu_read_lock();
- src = __i915_gem_context_lookup_rcu(arg->fpriv, local.clone_id);
- rcu_read_unlock();
- if (!src)
- return -ENOENT;
+ /* One for the xarray and one for the caller */
+ return i915_gem_context_get(ctx);
+}
- GEM_BUG_ON(src == dst);
+struct i915_gem_context *
+i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
+{
+ struct i915_gem_proto_context *pc;
+ struct i915_gem_context *ctx;
- for (bit = 0; bit < ARRAY_SIZE(fn); bit++) {
- if (!(local.flags & BIT(bit)))
- continue;
+ ctx = __context_lookup(file_priv, id);
+ if (ctx)
+ return ctx;
- err = fn[bit](dst, src);
- if (err)
- return err;
+ mutex_lock(&file_priv->proto_context_lock);
+ /* Try one more time under the lock */
+ ctx = __context_lookup(file_priv, id);
+ if (!ctx) {
+ pc = xa_load(&file_priv->proto_context_xa, id);
+ if (!pc)
+ ctx = ERR_PTR(-ENOENT);
+ else
+ ctx = finalize_create_context_locked(file_priv, pc, id);
}
+ mutex_unlock(&file_priv->proto_context_lock);
- return 0;
-}
-
-static const i915_user_extension_fn create_extensions[] = {
- [I915_CONTEXT_CREATE_EXT_SETPARAM] = create_setparam,
- [I915_CONTEXT_CREATE_EXT_CLONE] = create_clone,
-};
-
-static bool client_is_banned(struct drm_i915_file_private *file_priv)
-{
- return atomic_read(&file_priv->ban_score) >= I915_CLIENT_SCORE_BANNED;
+ return ctx;
}
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
@@ -2321,9 +1982,9 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
return -EIO;
}
- ext_data.ctx = i915_gem_create_context(i915, args->flags);
- if (IS_ERR(ext_data.ctx))
- return PTR_ERR(ext_data.ctx);
+ ext_data.pc = proto_context_create(i915, args->flags);
+ if (IS_ERR(ext_data.pc))
+ return PTR_ERR(ext_data.pc);
if (args->flags & I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS) {
ret = i915_user_extensions(u64_to_user_ptr(args->extensions),
@@ -2331,20 +1992,39 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
ARRAY_SIZE(create_extensions),
&ext_data);
if (ret)
- goto err_ctx;
+ goto err_pc;
}
- ret = gem_context_register(ext_data.ctx, ext_data.fpriv, &id);
- if (ret < 0)
- goto err_ctx;
+ if (GRAPHICS_VER(i915) > 12) {
+ struct i915_gem_context *ctx;
+
+ /* Get ourselves a context ID */
+ ret = xa_alloc(&ext_data.fpriv->context_xa, &id, NULL,
+ xa_limit_32b, GFP_KERNEL);
+ if (ret)
+ goto err_pc;
+
+ ctx = i915_gem_create_context(i915, ext_data.pc);
+ if (IS_ERR(ctx)) {
+ ret = PTR_ERR(ctx);
+ goto err_pc;
+ }
+
+ proto_context_close(ext_data.pc);
+ gem_context_register(ctx, ext_data.fpriv, id);
+ } else {
+ ret = proto_context_register(ext_data.fpriv, ext_data.pc, &id);
+ if (ret < 0)
+ goto err_pc;
+ }
args->ctx_id = id;
drm_dbg(&i915->drm, "HW context %d created\n", args->ctx_id);
return 0;
-err_ctx:
- context_close(ext_data.ctx);
+err_pc:
+ proto_context_close(ext_data.pc);
return ret;
}
@@ -2353,6 +2033,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_context_destroy *args = data;
struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct i915_gem_proto_context *pc;
struct i915_gem_context *ctx;
if (args->pad != 0)
@@ -2361,11 +2042,24 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
if (!args->ctx_id)
return -ENOENT;
+ /* We need to hold the proto-context lock here to prevent races
+ * with finalize_create_context_locked().
+ */
+ mutex_lock(&file_priv->proto_context_lock);
ctx = xa_erase(&file_priv->context_xa, args->ctx_id);
- if (!ctx)
+ pc = xa_erase(&file_priv->proto_context_xa, args->ctx_id);
+ mutex_unlock(&file_priv->proto_context_lock);
+
+ if (!ctx && !pc)
return -ENOENT;
+ GEM_WARN_ON(ctx && pc);
+
+ if (pc)
+ proto_context_close(pc);
+
+ if (ctx)
+ context_close(ctx);
- context_close(ctx);
return 0;
}
@@ -2433,15 +2127,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
int ret = 0;
ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
- if (!ctx)
- return -ENOENT;
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
switch (args->param) {
- case I915_CONTEXT_PARAM_NO_ZEROMAP:
- args->size = 0;
- args->value = test_bit(UCONTEXT_NO_ZEROMAP, &ctx->user_flags);
- break;
-
case I915_CONTEXT_PARAM_GTT_SIZE:
args->size = 0;
rcu_read_lock();
@@ -2480,20 +2169,15 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
ret = get_ppgtt(file_priv, ctx, args);
break;
- case I915_CONTEXT_PARAM_ENGINES:
- ret = get_engines(ctx, args);
- break;
-
case I915_CONTEXT_PARAM_PERSISTENCE:
args->size = 0;
args->value = i915_gem_context_is_persistent(ctx);
break;
- case I915_CONTEXT_PARAM_RINGSIZE:
- ret = get_ringsize(ctx, args);
- break;
-
+ case I915_CONTEXT_PARAM_NO_ZEROMAP:
case I915_CONTEXT_PARAM_BAN_PERIOD:
+ case I915_CONTEXT_PARAM_ENGINES:
+ case I915_CONTEXT_PARAM_RINGSIZE:
default:
ret = -EINVAL;
break;
@@ -2508,16 +2192,32 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_file_private *file_priv = file->driver_priv;
struct drm_i915_gem_context_param *args = data;
+ struct i915_gem_proto_context *pc;
struct i915_gem_context *ctx;
- int ret;
+ int ret = 0;
- ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
- if (!ctx)
- return -ENOENT;
+ mutex_lock(&file_priv->proto_context_lock);
+ ctx = __context_lookup(file_priv, args->ctx_id);
+ if (!ctx) {
+ pc = xa_load(&file_priv->proto_context_xa, args->ctx_id);
+ if (pc) {
+ /* Contexts should be finalized inside
+ * GEM_CONTEXT_CREATE starting with graphics
+ * version 13.
+ */
+ WARN_ON(GRAPHICS_VER(file_priv->dev_priv) > 12);
+ ret = set_proto_ctx_param(file_priv, pc, args);
+ } else {
+ ret = -ENOENT;
+ }
+ }
+ mutex_unlock(&file_priv->proto_context_lock);
- ret = ctx_setparam(file_priv, ctx, args);
+ if (ctx) {
+ ret = ctx_setparam(file_priv, ctx, args);
+ i915_gem_context_put(ctx);
+ }
- i915_gem_context_put(ctx);
return ret;
}
@@ -2527,16 +2227,13 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
struct drm_i915_private *i915 = to_i915(dev);
struct drm_i915_reset_stats *args = data;
struct i915_gem_context *ctx;
- int ret;
if (args->flags || args->pad)
return -EINVAL;
- ret = -ENOENT;
- rcu_read_lock();
- ctx = __i915_gem_context_lookup_rcu(file->driver_priv, args->ctx_id);
- if (!ctx)
- goto out;
+ ctx = i915_gem_context_lookup(file->driver_priv, args->ctx_id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
/*
* We opt for unserialised reads here. This may result in tearing
@@ -2553,10 +2250,8 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
args->batch_active = atomic_read(&ctx->guilty_count);
args->batch_pending = atomic_read(&ctx->active_count);
- ret = 0;
-out:
- rcu_read_unlock();
- return ret;
+ i915_gem_context_put(ctx);
+ return 0;
}
/* GEM context-engines iterator: for_each_gem_engine() */
@@ -2584,27 +2279,16 @@ i915_gem_engines_iter_next(struct i915_gem_engines_iter *it)
#include "selftests/i915_gem_context.c"
#endif
-static void i915_global_gem_context_shrink(void)
+void i915_gem_context_module_exit(void)
{
- kmem_cache_shrink(global.slab_luts);
+ kmem_cache_destroy(slab_luts);
}
-static void i915_global_gem_context_exit(void)
-{
- kmem_cache_destroy(global.slab_luts);
-}
-
-static struct i915_global_gem_context global = { {
- .shrink = i915_global_gem_context_shrink,
- .exit = i915_global_gem_context_exit,
-} };
-
-int __init i915_global_gem_context_init(void)
+int __init i915_gem_context_module_init(void)
{
- global.slab_luts = KMEM_CACHE(i915_lut_handle, 0);
- if (!global.slab_luts)
+ slab_luts = KMEM_CACHE(i915_lut_handle, 0);
+ if (!slab_luts)
return -ENOMEM;
- i915_global_register(&global.base);
return 0;
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.h b/drivers/gpu/drm/i915/gem/i915_gem_context.h
index b5c908f3f4f2..18060536b0c2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.h
@@ -133,6 +133,9 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
+struct i915_gem_context *
+i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id);
+
static inline struct i915_gem_context *
i915_gem_context_get(struct i915_gem_context *ctx)
{
@@ -221,6 +224,9 @@ i915_gem_engines_iter_next(struct i915_gem_engines_iter *it);
for (i915_gem_engines_iter_init(&(it), (engines)); \
((ce) = i915_gem_engines_iter_next(&(it)));)
+void i915_gem_context_module_exit(void);
+int i915_gem_context_module_init(void);
+
struct i915_lut_handle *i915_lut_handle_alloc(void);
void i915_lut_handle_free(struct i915_lut_handle *lut);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
index 340473aa70de..94c03a97cb77 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
@@ -30,33 +30,187 @@ struct i915_address_space;
struct intel_timeline;
struct intel_ring;
+/**
+ * struct i915_gem_engines - A set of engines
+ */
struct i915_gem_engines {
union {
+ /** @link: Link in i915_gem_context::stale::engines */
struct list_head link;
+
+ /** @rcu: RCU to use when freeing */
struct rcu_head rcu;
};
+
+ /** @fence: Fence used for delayed destruction of engines */
struct i915_sw_fence fence;
+
+ /** @ctx: i915_gem_context backpointer */
struct i915_gem_context *ctx;
+
+ /** @num_engines: Number of engines in this set */
unsigned int num_engines;
+
+ /** @engines: Array of engines */
struct intel_context *engines[];
};
+/**
+ * struct i915_gem_engines_iter - Iterator for an i915_gem_engines set
+ */
struct i915_gem_engines_iter {
+ /** @idx: Index into i915_gem_engines::engines */
unsigned int idx;
+
+ /** @engines: Engine set being iterated */
const struct i915_gem_engines *engines;
};
/**
+ * enum i915_gem_engine_type - Describes the type of an i915_gem_proto_engine
+ */
+enum i915_gem_engine_type {
+ /** @I915_GEM_ENGINE_TYPE_INVALID: An invalid engine */
+ I915_GEM_ENGINE_TYPE_INVALID = 0,
+
+ /** @I915_GEM_ENGINE_TYPE_PHYSICAL: A single physical engine */
+ I915_GEM_ENGINE_TYPE_PHYSICAL,
+
+ /** @I915_GEM_ENGINE_TYPE_BALANCED: A load-balanced engine set */
+ I915_GEM_ENGINE_TYPE_BALANCED,
+};
+
+/**
+ * struct i915_gem_proto_engine - prototype engine
+ *
+ * This struct describes an engine that a context may contain. Engines
+ * have three types:
+ *
+ * - I915_GEM_ENGINE_TYPE_INVALID: Invalid engines can be created but they
+ * show up as a NULL in i915_gem_engines::engines[i] and any attempt to
+ * use them by the user results in -EINVAL. They are also useful during
+ * proto-context construction because the client may create invalid
+ * engines and then set them up later as virtual engines.
+ *
+ * - I915_GEM_ENGINE_TYPE_PHYSICAL: A single physical engine, described by
+ * i915_gem_proto_engine::engine.
+ *
+ * - I915_GEM_ENGINE_TYPE_BALANCED: A load-balanced engine set, described
+ * i915_gem_proto_engine::num_siblings and i915_gem_proto_engine::siblings.
+ */
+struct i915_gem_proto_engine {
+ /** @type: Type of this engine */
+ enum i915_gem_engine_type type;
+
+ /** @engine: Engine, for physical */
+ struct intel_engine_cs *engine;
+
+ /** @num_siblings: Number of balanced siblings */
+ unsigned int num_siblings;
+
+ /** @siblings: Balanced siblings */
+ struct intel_engine_cs **siblings;
+
+ /** @sseu: Client-set SSEU parameters */
+ struct intel_sseu sseu;
+};
+
+/**
+ * struct i915_gem_proto_context - prototype context
+ *
+ * The struct i915_gem_proto_context represents the creation parameters for
+ * a struct i915_gem_context. This is used to gather parameters provided
+ * either through creation flags or via SET_CONTEXT_PARAM so that, when we
+ * create the final i915_gem_context, those parameters can be immutable.
+ *
+ * The context uAPI allows for two methods of setting context parameters:
+ * SET_CONTEXT_PARAM and CONTEXT_CREATE_EXT_SETPARAM. The former is
+ * allowed to be called at any time while the later happens as part of
+ * GEM_CONTEXT_CREATE. When these were initially added, Currently,
+ * everything settable via one is settable via the other. While some
+ * params are fairly simple and setting them on a live context is harmless
+ * such the context priority, others are far trickier such as the VM or the
+ * set of engines. To avoid some truly nasty race conditions, we don't
+ * allow setting the VM or the set of engines on live contexts.
+ *
+ * The way we dealt with this without breaking older userspace that sets
+ * the VM or engine set via SET_CONTEXT_PARAM is to delay the creation of
+ * the actual context until after the client is done configuring it with
+ * SET_CONTEXT_PARAM. From the perspective of the client, it has the same
+ * u32 context ID the whole time. From the perspective of i915, however,
+ * it's an i915_gem_proto_context right up until the point where we attempt
+ * to do something which the proto-context can't handle at which point the
+ * real context gets created.
+ *
+ * This is accomplished via a little xarray dance. When GEM_CONTEXT_CREATE
+ * is called, we create a proto-context, reserve a slot in context_xa but
+ * leave it NULL, the proto-context in the corresponding slot in
+ * proto_context_xa. Then, whenever we go to look up a context, we first
+ * check context_xa. If it's there, we return the i915_gem_context and
+ * we're done. If it's not, we look in proto_context_xa and, if we find it
+ * there, we create the actual context and kill the proto-context.
+ *
+ * At the time we made this change (April, 2021), we did a fairly complete
+ * audit of existing userspace to ensure this wouldn't break anything:
+ *
+ * - Mesa/i965 didn't use the engines or VM APIs at all
+ *
+ * - Mesa/ANV used the engines API but via CONTEXT_CREATE_EXT_SETPARAM and
+ * didn't use the VM API.
+ *
+ * - Mesa/iris didn't use the engines or VM APIs at all
+ *
+ * - The open-source compute-runtime didn't yet use the engines API but
+ * did use the VM API via SET_CONTEXT_PARAM. However, CONTEXT_SETPARAM
+ * was always the second ioctl on that context, immediately following
+ * GEM_CONTEXT_CREATE.
+ *
+ * - The media driver sets engines and bonding/balancing via
+ * SET_CONTEXT_PARAM. However, CONTEXT_SETPARAM to set the VM was
+ * always the second ioctl on that context, immediately following
+ * GEM_CONTEXT_CREATE and setting engines immediately followed that.
+ *
+ * In order for this dance to work properly, any modification to an
+ * i915_gem_proto_context that is exposed to the client via
+ * drm_i915_file_private::proto_context_xa must be guarded by
+ * drm_i915_file_private::proto_context_lock. The exception is when a
+ * proto-context has not yet been exposed such as when handling
+ * CONTEXT_CREATE_SET_PARAM during GEM_CONTEXT_CREATE.
+ */
+struct i915_gem_proto_context {
+ /** @vm: See &i915_gem_context.vm */
+ struct i915_address_space *vm;
+
+ /** @user_flags: See &i915_gem_context.user_flags */
+ unsigned long user_flags;
+
+ /** @sched: See &i915_gem_context.sched */
+ struct i915_sched_attr sched;
+
+ /** @num_user_engines: Number of user-specified engines or -1 */
+ int num_user_engines;
+
+ /** @user_engines: User-specified engines */
+ struct i915_gem_proto_engine *user_engines;
+
+ /** @legacy_rcs_sseu: Client-set SSEU parameters for the legacy RCS */
+ struct intel_sseu legacy_rcs_sseu;
+
+ /** @single_timeline: See See &i915_gem_context.syncobj */
+ bool single_timeline;
+};
+
+/**
* struct i915_gem_context - client state
*
* The struct i915_gem_context represents the combined view of the driver and
* logical hardware state for a particular client.
*/
struct i915_gem_context {
- /** i915: i915 device backpointer */
+ /** @i915: i915 device backpointer */
struct drm_i915_private *i915;
- /** file_priv: owning file descriptor */
+ /** @file_priv: owning file descriptor */
struct drm_i915_file_private *file_priv;
/**
@@ -81,9 +235,23 @@ struct i915_gem_context {
* CONTEXT_USER_ENGINES flag is set).
*/
struct i915_gem_engines __rcu *engines;
- struct mutex engines_mutex; /* guards writes to engines */
- struct intel_timeline *timeline;
+ /** @engines_mutex: guards writes to engines */
+ struct mutex engines_mutex;
+
+ /**
+ * @syncobj: Shared timeline syncobj
+ *
+ * When the SHARED_TIMELINE flag is set on context creation, we
+ * emulate a single timeline across all engines using this syncobj.
+ * For every execbuffer2 call, this syncobj is used as both an in-
+ * and out-fence. Unlike the real intel_timeline, this doesn't
+ * provide perfect atomic in-order guarantees if the client races
+ * with itself by calling execbuffer2 twice concurrently. However,
+ * if userspace races with itself, that's not likely to yield well-
+ * defined results anyway so we choose to not care.
+ */
+ struct drm_syncobj *syncobj;
/**
* @vm: unique address space (GTT)
@@ -106,7 +274,7 @@ struct i915_gem_context {
*/
struct pid *pid;
- /** link: place with &drm_i915_private.context_list */
+ /** @link: place with &drm_i915_private.context_list */
struct list_head link;
/**
@@ -129,7 +297,6 @@ struct i915_gem_context {
* @user_flags: small set of booleans controlled by the user
*/
unsigned long user_flags;
-#define UCONTEXT_NO_ZEROMAP 0
#define UCONTEXT_NO_ERROR_CAPTURE 1
#define UCONTEXT_BANNABLE 2
#define UCONTEXT_RECOVERABLE 3
@@ -142,11 +309,13 @@ struct i915_gem_context {
#define CONTEXT_CLOSED 0
#define CONTEXT_USER_ENGINES 1
+ /** @mutex: guards everything that isn't engines or handles_vma */
struct mutex mutex;
+ /** @sched: scheduler parameters */
struct i915_sched_attr sched;
- /** guilty_count: How many times this context has caused a GPU hang. */
+ /** @guilty_count: How many times this context has caused a GPU hang. */
atomic_t guilty_count;
/**
* @active_count: How many times this context was active during a GPU
@@ -154,25 +323,23 @@ struct i915_gem_context {
*/
atomic_t active_count;
- struct {
- u64 timeout_us;
- } watchdog;
-
/**
* @hang_timestamp: The last time(s) this context caused a GPU hang
*/
unsigned long hang_timestamp[2];
#define CONTEXT_FAST_HANG_JIFFIES (120 * HZ) /* 3 hangs within 120s? Banned! */
- /** remap_slice: Bitmask of cache lines that need remapping */
+ /** @remap_slice: Bitmask of cache lines that need remapping */
u8 remap_slice;
/**
- * handles_vma: rbtree to look up our context specific obj/vma for
+ * @handles_vma: rbtree to look up our context specific obj/vma for
* the user handle. (user handles are per fd, but the binding is
* per vm, which may be one per context or shared with the global GTT)
*/
struct radix_tree_root handles_vma;
+
+ /** @lut_mutex: Locks handles_vma */
struct mutex lut_mutex;
/**
@@ -184,8 +351,11 @@ struct i915_gem_context {
*/
char name[TASK_COMM_LEN + 8];
+ /** @stale: tracks stale engines to be destroyed */
struct {
+ /** @lock: guards engines */
spinlock_t lock;
+ /** @engines: list of stale engines */
struct list_head engines;
} stale;
};
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_create.c b/drivers/gpu/drm/i915/gem/i915_gem_create.c
index 548ddf39d853..23fee13a3384 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_create.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_create.c
@@ -11,13 +11,14 @@
#include "i915_trace.h"
#include "i915_user_extensions.h"
-static u32 object_max_page_size(struct drm_i915_gem_object *obj)
+static u32 object_max_page_size(struct intel_memory_region **placements,
+ unsigned int n_placements)
{
u32 max_page_size = 0;
int i;
- for (i = 0; i < obj->mm.n_placements; i++) {
- struct intel_memory_region *mr = obj->mm.placements[i];
+ for (i = 0; i < n_placements; i++) {
+ struct intel_memory_region *mr = placements[i];
GEM_BUG_ON(!is_power_of_2(mr->min_page_size));
max_page_size = max_t(u32, max_page_size, mr->min_page_size);
@@ -27,10 +28,13 @@ static u32 object_max_page_size(struct drm_i915_gem_object *obj)
return max_page_size;
}
-static void object_set_placements(struct drm_i915_gem_object *obj,
- struct intel_memory_region **placements,
- unsigned int n_placements)
+static int object_set_placements(struct drm_i915_gem_object *obj,
+ struct intel_memory_region **placements,
+ unsigned int n_placements)
{
+ struct intel_memory_region **arr;
+ unsigned int i;
+
GEM_BUG_ON(!n_placements);
/*
@@ -44,9 +48,20 @@ static void object_set_placements(struct drm_i915_gem_object *obj,
obj->mm.placements = &i915->mm.regions[mr->id];
obj->mm.n_placements = 1;
} else {
- obj->mm.placements = placements;
+ arr = kmalloc_array(n_placements,
+ sizeof(struct intel_memory_region *),
+ GFP_KERNEL);
+ if (!arr)
+ return -ENOMEM;
+
+ for (i = 0; i < n_placements; i++)
+ arr[i] = placements[i];
+
+ obj->mm.placements = arr;
obj->mm.n_placements = n_placements;
}
+
+ return 0;
}
static int i915_gem_publish(struct drm_i915_gem_object *obj,
@@ -67,40 +82,67 @@ static int i915_gem_publish(struct drm_i915_gem_object *obj,
return 0;
}
-static int
-i915_gem_setup(struct drm_i915_gem_object *obj, u64 size)
+/**
+ * Creates a new object using the same path as DRM_I915_GEM_CREATE_EXT
+ * @i915: i915 private
+ * @size: size of the buffer, in bytes
+ * @placements: possible placement regions, in priority order
+ * @n_placements: number of possible placement regions
+ *
+ * This function is exposed primarily for selftests and does very little
+ * error checking. It is assumed that the set of placement regions has
+ * already been verified to be valid.
+ */
+struct drm_i915_gem_object *
+__i915_gem_object_create_user(struct drm_i915_private *i915, u64 size,
+ struct intel_memory_region **placements,
+ unsigned int n_placements)
{
- struct intel_memory_region *mr = obj->mm.placements[0];
+ struct intel_memory_region *mr = placements[0];
+ struct drm_i915_gem_object *obj;
unsigned int flags;
int ret;
- size = round_up(size, object_max_page_size(obj));
+ i915_gem_flush_free_objects(i915);
+
+ size = round_up(size, object_max_page_size(placements, n_placements));
if (size == 0)
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
/* For most of the ABI (e.g. mmap) we think in system pages */
GEM_BUG_ON(!IS_ALIGNED(size, PAGE_SIZE));
if (i915_gem_object_size_2big(size))
- return -E2BIG;
+ return ERR_PTR(-E2BIG);
+
+ obj = i915_gem_object_alloc();
+ if (!obj)
+ return ERR_PTR(-ENOMEM);
+
+ ret = object_set_placements(obj, placements, n_placements);
+ if (ret)
+ goto object_free;
/*
- * For now resort to CPU based clearing for device local-memory, in the
- * near future this will use the blitter engine for accelerated, GPU
- * based clearing.
+ * I915_BO_ALLOC_USER will make sure the object is cleared before
+ * any user access.
*/
- flags = 0;
- if (mr->type == INTEL_MEMORY_LOCAL)
- flags = I915_BO_ALLOC_CPU_CLEAR;
+ flags = I915_BO_ALLOC_USER;
- ret = mr->ops->init_object(mr, obj, size, flags);
+ ret = mr->ops->init_object(mr, obj, size, 0, flags);
if (ret)
- return ret;
+ goto object_free;
GEM_BUG_ON(size != obj->base.size);
trace_i915_gem_object_create(obj);
- return 0;
+ return obj;
+
+object_free:
+ if (obj->mm.n_placements > 1)
+ kfree(obj->mm.placements);
+ i915_gem_object_free(obj);
+ return ERR_PTR(ret);
}
int
@@ -113,7 +155,6 @@ i915_gem_dumb_create(struct drm_file *file,
enum intel_memory_type mem_type;
int cpp = DIV_ROUND_UP(args->bpp, 8);
u32 format;
- int ret;
switch (cpp) {
case 1:
@@ -146,22 +187,13 @@ i915_gem_dumb_create(struct drm_file *file,
if (HAS_LMEM(to_i915(dev)))
mem_type = INTEL_MEMORY_LOCAL;
- obj = i915_gem_object_alloc();
- if (!obj)
- return -ENOMEM;
-
mr = intel_memory_region_by_type(to_i915(dev), mem_type);
- object_set_placements(obj, &mr, 1);
- ret = i915_gem_setup(obj, args->size);
- if (ret)
- goto object_free;
+ obj = __i915_gem_object_create_user(to_i915(dev), args->size, &mr, 1);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
return i915_gem_publish(obj, file, &args->size, &args->handle);
-
-object_free:
- i915_gem_object_free(obj);
- return ret;
}
/**
@@ -178,31 +210,20 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
struct drm_i915_gem_create *args = data;
struct drm_i915_gem_object *obj;
struct intel_memory_region *mr;
- int ret;
-
- i915_gem_flush_free_objects(i915);
-
- obj = i915_gem_object_alloc();
- if (!obj)
- return -ENOMEM;
mr = intel_memory_region_by_type(i915, INTEL_MEMORY_SYSTEM);
- object_set_placements(obj, &mr, 1);
- ret = i915_gem_setup(obj, args->size);
- if (ret)
- goto object_free;
+ obj = __i915_gem_object_create_user(i915, args->size, &mr, 1);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
return i915_gem_publish(obj, file, &args->size, &args->handle);
-
-object_free:
- i915_gem_object_free(obj);
- return ret;
}
struct create_ext {
struct drm_i915_private *i915;
- struct drm_i915_gem_object *vanilla_object;
+ struct intel_memory_region *placements[INTEL_REGION_UNKNOWN];
+ unsigned int n_placements;
};
static void repr_placements(char *buf, size_t size,
@@ -233,8 +254,7 @@ static int set_placements(struct drm_i915_gem_create_ext_memory_regions *args,
struct drm_i915_private *i915 = ext_data->i915;
struct drm_i915_gem_memory_class_instance __user *uregions =
u64_to_user_ptr(args->regions);
- struct drm_i915_gem_object *obj = ext_data->vanilla_object;
- struct intel_memory_region **placements;
+ struct intel_memory_region *placements[INTEL_REGION_UNKNOWN];
u32 mask;
int i, ret = 0;
@@ -248,6 +268,8 @@ static int set_placements(struct drm_i915_gem_create_ext_memory_regions *args,
ret = -EINVAL;
}
+ BUILD_BUG_ON(ARRAY_SIZE(i915->mm.regions) != ARRAY_SIZE(placements));
+ BUILD_BUG_ON(ARRAY_SIZE(ext_data->placements) != ARRAY_SIZE(placements));
if (args->num_regions > ARRAY_SIZE(i915->mm.regions)) {
drm_dbg(&i915->drm, "num_regions is too large\n");
ret = -EINVAL;
@@ -256,21 +278,13 @@ static int set_placements(struct drm_i915_gem_create_ext_memory_regions *args,
if (ret)
return ret;
- placements = kmalloc_array(args->num_regions,
- sizeof(struct intel_memory_region *),
- GFP_KERNEL);
- if (!placements)
- return -ENOMEM;
-
mask = 0;
for (i = 0; i < args->num_regions; i++) {
struct drm_i915_gem_memory_class_instance region;
struct intel_memory_region *mr;
- if (copy_from_user(&region, uregions, sizeof(region))) {
- ret = -EFAULT;
- goto out_free;
- }
+ if (copy_from_user(&region, uregions, sizeof(region)))
+ return -EFAULT;
mr = intel_memory_region_lookup(i915,
region.memory_class,
@@ -296,14 +310,14 @@ static int set_placements(struct drm_i915_gem_create_ext_memory_regions *args,
++uregions;
}
- if (obj->mm.placements) {
+ if (ext_data->n_placements) {
ret = -EINVAL;
goto out_dump;
}
- object_set_placements(obj, placements, args->num_regions);
- if (args->num_regions == 1)
- kfree(placements);
+ ext_data->n_placements = args->num_regions;
+ for (i = 0; i < args->num_regions; i++)
+ ext_data->placements[i] = placements[i];
return 0;
@@ -311,11 +325,11 @@ out_dump:
if (1) {
char buf[256];
- if (obj->mm.placements) {
+ if (ext_data->n_placements) {
repr_placements(buf,
sizeof(buf),
- obj->mm.placements,
- obj->mm.n_placements);
+ ext_data->placements,
+ ext_data->n_placements);
drm_dbg(&i915->drm,
"Placements were already set in previous EXT. Existing placements: %s\n",
buf);
@@ -325,8 +339,6 @@ out_dump:
drm_dbg(&i915->drm, "New placements(so far validated): %s\n", buf);
}
-out_free:
- kfree(placements);
return ret;
}
@@ -361,44 +373,30 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data,
struct drm_i915_private *i915 = to_i915(dev);
struct drm_i915_gem_create_ext *args = data;
struct create_ext ext_data = { .i915 = i915 };
- struct intel_memory_region **placements_ext;
struct drm_i915_gem_object *obj;
int ret;
if (args->flags)
return -EINVAL;
- i915_gem_flush_free_objects(i915);
-
- obj = i915_gem_object_alloc();
- if (!obj)
- return -ENOMEM;
-
- ext_data.vanilla_object = obj;
ret = i915_user_extensions(u64_to_user_ptr(args->extensions),
create_extensions,
ARRAY_SIZE(create_extensions),
&ext_data);
- placements_ext = obj->mm.placements;
if (ret)
- goto object_free;
+ return ret;
- if (!placements_ext) {
- struct intel_memory_region *mr =
+ if (!ext_data.n_placements) {
+ ext_data.placements[0] =
intel_memory_region_by_type(i915, INTEL_MEMORY_SYSTEM);
-
- object_set_placements(obj, &mr, 1);
+ ext_data.n_placements = 1;
}
- ret = i915_gem_setup(obj, args->size);
- if (ret)
- goto object_free;
+ obj = __i915_gem_object_create_user(i915, args->size,
+ ext_data.placements,
+ ext_data.n_placements);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
return i915_gem_publish(obj, file, &args->size, &args->handle);
-
-object_free:
- if (obj->mm.n_placements > 1)
- kfree(placements_ext);
- i915_gem_object_free(obj);
- return ret;
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 616c3a2f1baf..afa34111de02 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -12,6 +12,8 @@
#include "i915_gem_object.h"
#include "i915_scatterlist.h"
+I915_SELFTEST_DECLARE(static bool force_different_devices;)
+
static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
{
return to_intel_bo(buf->priv);
@@ -25,15 +27,11 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
struct scatterlist *src, *dst;
int ret, i;
- ret = i915_gem_object_pin_pages_unlocked(obj);
- if (ret)
- goto err;
-
/* Copy sg so that we make an independent mapping */
st = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
if (st == NULL) {
ret = -ENOMEM;
- goto err_unpin_pages;
+ goto err;
}
ret = sg_alloc_table(st, obj->mm.pages->nents, GFP_KERNEL);
@@ -58,8 +56,6 @@ err_free_sg:
sg_free_table(st);
err_free:
kfree(st);
-err_unpin_pages:
- i915_gem_object_unpin_pages(obj);
err:
return ERR_PTR(ret);
}
@@ -68,13 +64,9 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
struct sg_table *sg,
enum dma_data_direction dir)
{
- struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf);
-
dma_unmap_sgtable(attachment->dev, sg, dir, DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sg);
kfree(sg);
-
- i915_gem_object_unpin_pages(obj);
}
static int i915_gem_dmabuf_vmap(struct dma_buf *dma_buf, struct dma_buf_map *map)
@@ -168,7 +160,46 @@ retry:
return err;
}
+static int i915_gem_dmabuf_attach(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attach)
+{
+ struct drm_i915_gem_object *obj = dma_buf_to_obj(dmabuf);
+ struct i915_gem_ww_ctx ww;
+ int err;
+
+ if (!i915_gem_object_can_migrate(obj, INTEL_REGION_SMEM))
+ return -EOPNOTSUPP;
+
+ for_i915_gem_ww(&ww, err, true) {
+ err = i915_gem_object_lock(obj, &ww);
+ if (err)
+ continue;
+
+ err = i915_gem_object_migrate(obj, &ww, INTEL_REGION_SMEM);
+ if (err)
+ continue;
+
+ err = i915_gem_object_wait_migration(obj, 0);
+ if (err)
+ continue;
+
+ err = i915_gem_object_pin_pages(obj);
+ }
+
+ return err;
+}
+
+static void i915_gem_dmabuf_detach(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attach)
+{
+ struct drm_i915_gem_object *obj = dma_buf_to_obj(dmabuf);
+
+ i915_gem_object_unpin_pages(obj);
+}
+
static const struct dma_buf_ops i915_dmabuf_ops = {
+ .attach = i915_gem_dmabuf_attach,
+ .detach = i915_gem_dmabuf_detach,
.map_dma_buf = i915_gem_map_dma_buf,
.unmap_dma_buf = i915_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
@@ -204,6 +235,8 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
struct sg_table *pages;
unsigned int sg_page_sizes;
+ assert_object_held(obj);
+
pages = dma_buf_map_attachment(obj->base.import_attach,
DMA_BIDIRECTIONAL);
if (IS_ERR(pages))
@@ -241,7 +274,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
if (dma_buf->ops == &i915_dmabuf_ops) {
obj = dma_buf_to_obj(dma_buf);
/* is it from our device? */
- if (obj->base.dev == dev) {
+ if (obj->base.dev == dev &&
+ !I915_SELFTEST_ONLY(force_different_devices)) {
/*
* Importing dmabuf exported from out own gem increases
* refcount on gem itself instead of f_count of dmabuf.
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 073822100da7..b684a62bf3b0 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -268,6 +268,9 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
struct drm_i915_gem_object *obj;
int err = 0;
+ if (IS_DGFX(to_i915(dev)))
+ return -ENODEV;
+
rcu_read_lock();
obj = i915_gem_object_lookup_rcu(file, args->handle);
if (!obj) {
@@ -303,6 +306,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
enum i915_cache_level level;
int ret = 0;
+ if (IS_DGFX(i915))
+ return -ENODEV;
+
switch (args->caching) {
case I915_CACHING_NONE:
level = I915_CACHE_NONE;
@@ -375,7 +381,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
struct i915_vma *vma;
int ret;
- /* Frame buffer must be in LMEM (no migration yet) */
+ /* Frame buffer must be in LMEM */
if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj))
return ERR_PTR(-EINVAL);
@@ -484,6 +490,9 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
u32 write_domain = args->write_domain;
int err;
+ if (IS_DGFX(to_i915(dev)))
+ return -ENODEV;
+
/* Only handle setting domains to types used by the CPU. */
if ((write_domain | read_domains) & I915_GEM_GPU_DOMAINS)
return -EINVAL;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 4a6419d7be93..1aa249908b64 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -277,18 +277,9 @@ struct i915_execbuffer {
bool has_llc : 1;
bool has_fence : 1;
bool needs_unfenced : 1;
-
- struct i915_request *rq;
- u32 *rq_cmd;
- unsigned int rq_size;
- struct intel_gt_buffer_pool_node *pool;
} reloc_cache;
- struct intel_gt_buffer_pool_node *reloc_pool; /** relocation pool for -EDEADLK handling */
- struct intel_context *reloc_context;
-
u64 invalid_flags; /** Set of execobj.flags that are invalid */
- u32 context_flags; /** Set of execobj.flags to insert from the ctx */
u64 batch_len; /** Length of batch within object */
u32 batch_start_offset; /** Location within object of batch */
@@ -539,9 +530,6 @@ eb_validate_vma(struct i915_execbuffer *eb,
entry->flags |= EXEC_OBJECT_NEEDS_GTT | __EXEC_OBJECT_NEEDS_MAP;
}
- if (!(entry->flags & EXEC_OBJECT_PINNED))
- entry->flags |= eb->context_flags;
-
return 0;
}
@@ -741,17 +729,13 @@ static int eb_select_context(struct i915_execbuffer *eb)
struct i915_gem_context *ctx;
ctx = i915_gem_context_lookup(eb->file->driver_priv, eb->args->rsvd1);
- if (unlikely(!ctx))
- return -ENOENT;
+ if (unlikely(IS_ERR(ctx)))
+ return PTR_ERR(ctx);
eb->gem_context = ctx;
if (rcu_access_pointer(ctx->vm))
eb->invalid_flags |= EXEC_OBJECT_NEEDS_GTT;
- eb->context_flags = 0;
- if (test_bit(UCONTEXT_NO_ZEROMAP, &ctx->user_flags))
- eb->context_flags |= __EXEC_OBJECT_NEEDS_BIAS;
-
return 0;
}
@@ -920,21 +904,38 @@ err:
return err;
}
-static int eb_validate_vmas(struct i915_execbuffer *eb)
+static int eb_lock_vmas(struct i915_execbuffer *eb)
{
unsigned int i;
int err;
- INIT_LIST_HEAD(&eb->unbound);
-
for (i = 0; i < eb->buffer_count; i++) {
- struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
struct eb_vma *ev = &eb->vma[i];
struct i915_vma *vma = ev->vma;
err = i915_gem_object_lock(vma->obj, &eb->ww);
if (err)
return err;
+ }
+
+ return 0;
+}
+
+static int eb_validate_vmas(struct i915_execbuffer *eb)
+{
+ unsigned int i;
+ int err;
+
+ INIT_LIST_HEAD(&eb->unbound);
+
+ err = eb_lock_vmas(eb);
+ if (err)
+ return err;
+
+ for (i = 0; i < eb->buffer_count; i++) {
+ struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
+ struct eb_vma *ev = &eb->vma[i];
+ struct i915_vma *vma = ev->vma;
err = eb_pin_vma(eb, entry, ev);
if (err == -EDEADLK)
@@ -992,7 +993,7 @@ eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle)
}
}
-static void eb_release_vmas(struct i915_execbuffer *eb, bool final, bool release_userptr)
+static void eb_release_vmas(struct i915_execbuffer *eb, bool final)
{
const unsigned int count = eb->buffer_count;
unsigned int i;
@@ -1006,11 +1007,6 @@ static void eb_release_vmas(struct i915_execbuffer *eb, bool final, bool release
eb_unreserve_vma(ev);
- if (release_userptr && ev->flags & __EXEC_OBJECT_USERPTR_INIT) {
- ev->flags &= ~__EXEC_OBJECT_USERPTR_INIT;
- i915_gem_object_userptr_submit_fini(vma->obj);
- }
-
if (final)
i915_vma_put(vma);
}
@@ -1020,8 +1016,6 @@ static void eb_release_vmas(struct i915_execbuffer *eb, bool final, bool release
static void eb_destroy(const struct i915_execbuffer *eb)
{
- GEM_BUG_ON(eb->reloc_cache.rq);
-
if (eb->lut_size > 0)
kfree(eb->buckets);
}
@@ -1033,14 +1027,6 @@ relocation_target(const struct drm_i915_gem_relocation_entry *reloc,
return gen8_canonical_addr((int)reloc->delta + target->node.start);
}
-static void reloc_cache_clear(struct reloc_cache *cache)
-{
- cache->rq = NULL;
- cache->rq_cmd = NULL;
- cache->pool = NULL;
- cache->rq_size = 0;
-}
-
static void reloc_cache_init(struct reloc_cache *cache,
struct drm_i915_private *i915)
{
@@ -1053,7 +1039,6 @@ static void reloc_cache_init(struct reloc_cache *cache,
cache->has_fence = cache->graphics_ver < 4;
cache->needs_unfenced = INTEL_INFO(i915)->unfenced_needs_alignment;
cache->node.flags = 0;
- reloc_cache_clear(cache);
}
static inline void *unmask_page(unsigned long p)
@@ -1075,48 +1060,10 @@ static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache)
return &i915->ggtt;
}
-static void reloc_cache_put_pool(struct i915_execbuffer *eb, struct reloc_cache *cache)
-{
- if (!cache->pool)
- return;
-
- /*
- * This is a bit nasty, normally we keep objects locked until the end
- * of execbuffer, but we already submit this, and have to unlock before
- * dropping the reference. Fortunately we can only hold 1 pool node at
- * a time, so this should be harmless.
- */
- i915_gem_ww_unlock_single(cache->pool->obj);
- intel_gt_buffer_pool_put(cache->pool);
- cache->pool = NULL;
-}
-
-static void reloc_gpu_flush(struct i915_execbuffer *eb, struct reloc_cache *cache)
-{
- struct drm_i915_gem_object *obj = cache->rq->batch->obj;
-
- GEM_BUG_ON(cache->rq_size >= obj->base.size / sizeof(u32));
- cache->rq_cmd[cache->rq_size] = MI_BATCH_BUFFER_END;
-
- i915_gem_object_flush_map(obj);
- i915_gem_object_unpin_map(obj);
-
- intel_gt_chipset_flush(cache->rq->engine->gt);
-
- i915_request_add(cache->rq);
- reloc_cache_put_pool(eb, cache);
- reloc_cache_clear(cache);
-
- eb->reloc_pool = NULL;
-}
-
static void reloc_cache_reset(struct reloc_cache *cache, struct i915_execbuffer *eb)
{
void *vaddr;
- if (cache->rq)
- reloc_gpu_flush(eb, cache);
-
if (!cache->vaddr)
return;
@@ -1298,295 +1245,6 @@ static void clflush_write32(u32 *addr, u32 value, unsigned int flushes)
*addr = value;
}
-static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma)
-{
- struct drm_i915_gem_object *obj = vma->obj;
- int err;
-
- assert_vma_held(vma);
-
- if (obj->cache_dirty & ~obj->cache_coherent)
- i915_gem_clflush_object(obj, 0);
- obj->write_domain = 0;
-
- err = i915_request_await_object(rq, vma->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
-
- return err;
-}
-
-static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
- struct intel_engine_cs *engine,
- struct i915_vma *vma,
- unsigned int len)
-{
- struct reloc_cache *cache = &eb->reloc_cache;
- struct intel_gt_buffer_pool_node *pool = eb->reloc_pool;
- struct i915_request *rq;
- struct i915_vma *batch;
- u32 *cmd;
- int err;
-
- if (!pool) {
- pool = intel_gt_get_buffer_pool(engine->gt, PAGE_SIZE,
- cache->has_llc ?
- I915_MAP_WB :
- I915_MAP_WC);
- if (IS_ERR(pool))
- return PTR_ERR(pool);
- }
- eb->reloc_pool = NULL;
-
- err = i915_gem_object_lock(pool->obj, &eb->ww);
- if (err)
- goto err_pool;
-
- cmd = i915_gem_object_pin_map(pool->obj, pool->type);
- if (IS_ERR(cmd)) {
- err = PTR_ERR(cmd);
- goto err_pool;
- }
- intel_gt_buffer_pool_mark_used(pool);
-
- memset32(cmd, 0, pool->obj->base.size / sizeof(u32));
-
- batch = i915_vma_instance(pool->obj, vma->vm, NULL);
- if (IS_ERR(batch)) {
- err = PTR_ERR(batch);
- goto err_unmap;
- }
-
- err = i915_vma_pin_ww(batch, &eb->ww, 0, 0, PIN_USER | PIN_NONBLOCK);
- if (err)
- goto err_unmap;
-
- if (engine == eb->context->engine) {
- rq = i915_request_create(eb->context);
- } else {
- struct intel_context *ce = eb->reloc_context;
-
- if (!ce) {
- ce = intel_context_create(engine);
- if (IS_ERR(ce)) {
- err = PTR_ERR(ce);
- goto err_unpin;
- }
-
- i915_vm_put(ce->vm);
- ce->vm = i915_vm_get(eb->context->vm);
- eb->reloc_context = ce;
- }
-
- err = intel_context_pin_ww(ce, &eb->ww);
- if (err)
- goto err_unpin;
-
- rq = i915_request_create(ce);
- intel_context_unpin(ce);
- }
- if (IS_ERR(rq)) {
- err = PTR_ERR(rq);
- goto err_unpin;
- }
-
- err = intel_gt_buffer_pool_mark_active(pool, rq);
- if (err)
- goto err_request;
-
- err = reloc_move_to_gpu(rq, vma);
- if (err)
- goto err_request;
-
- err = eb->engine->emit_bb_start(rq,
- batch->node.start, PAGE_SIZE,
- cache->graphics_ver > 5 ? 0 : I915_DISPATCH_SECURE);
- if (err)
- goto skip_request;
-
- assert_vma_held(batch);
- err = i915_request_await_object(rq, batch->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(batch, rq, 0);
- if (err)
- goto skip_request;
-
- rq->batch = batch;
- i915_vma_unpin(batch);
-
- cache->rq = rq;
- cache->rq_cmd = cmd;
- cache->rq_size = 0;
- cache->pool = pool;
-
- /* Return with batch mapping (cmd) still pinned */
- return 0;
-
-skip_request:
- i915_request_set_error_once(rq, err);
-err_request:
- i915_request_add(rq);
-err_unpin:
- i915_vma_unpin(batch);
-err_unmap:
- i915_gem_object_unpin_map(pool->obj);
-err_pool:
- eb->reloc_pool = pool;
- return err;
-}
-
-static bool reloc_can_use_engine(const struct intel_engine_cs *engine)
-{
- return engine->class != VIDEO_DECODE_CLASS || GRAPHICS_VER(engine->i915) != 6;
-}
-
-static u32 *reloc_gpu(struct i915_execbuffer *eb,
- struct i915_vma *vma,
- unsigned int len)
-{
- struct reloc_cache *cache = &eb->reloc_cache;
- u32 *cmd;
-
- if (cache->rq_size > PAGE_SIZE/sizeof(u32) - (len + 1))
- reloc_gpu_flush(eb, cache);
-
- if (unlikely(!cache->rq)) {
- int err;
- struct intel_engine_cs *engine = eb->engine;
-
- /* If we need to copy for the cmdparser, we will stall anyway */
- if (eb_use_cmdparser(eb))
- return ERR_PTR(-EWOULDBLOCK);
-
- if (!reloc_can_use_engine(engine)) {
- engine = engine->gt->engine_class[COPY_ENGINE_CLASS][0];
- if (!engine)
- return ERR_PTR(-ENODEV);
- }
-
- err = __reloc_gpu_alloc(eb, engine, vma, len);
- if (unlikely(err))
- return ERR_PTR(err);
- }
-
- cmd = cache->rq_cmd + cache->rq_size;
- cache->rq_size += len;
-
- return cmd;
-}
-
-static inline bool use_reloc_gpu(struct i915_vma *vma)
-{
- if (DBG_FORCE_RELOC == FORCE_GPU_RELOC)
- return true;
-
- if (DBG_FORCE_RELOC)
- return false;
-
- return !dma_resv_test_signaled(vma->resv, true);
-}
-
-static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset)
-{
- struct page *page;
- unsigned long addr;
-
- GEM_BUG_ON(vma->pages != vma->obj->mm.pages);
-
- page = i915_gem_object_get_page(vma->obj, offset >> PAGE_SHIFT);
- addr = PFN_PHYS(page_to_pfn(page));
- GEM_BUG_ON(overflows_type(addr, u32)); /* expected dma32 */
-
- return addr + offset_in_page(offset);
-}
-
-static int __reloc_entry_gpu(struct i915_execbuffer *eb,
- struct i915_vma *vma,
- u64 offset,
- u64 target_addr)
-{
- const unsigned int ver = eb->reloc_cache.graphics_ver;
- unsigned int len;
- u32 *batch;
- u64 addr;
-
- if (ver >= 8)
- len = offset & 7 ? 8 : 5;
- else if (ver >= 4)
- len = 4;
- else
- len = 3;
-
- batch = reloc_gpu(eb, vma, len);
- if (batch == ERR_PTR(-EDEADLK))
- return -EDEADLK;
- else if (IS_ERR(batch))
- return false;
-
- addr = gen8_canonical_addr(vma->node.start + offset);
- if (ver >= 8) {
- if (offset & 7) {
- *batch++ = MI_STORE_DWORD_IMM_GEN4;
- *batch++ = lower_32_bits(addr);
- *batch++ = upper_32_bits(addr);
- *batch++ = lower_32_bits(target_addr);
-
- addr = gen8_canonical_addr(addr + 4);
-
- *batch++ = MI_STORE_DWORD_IMM_GEN4;
- *batch++ = lower_32_bits(addr);
- *batch++ = upper_32_bits(addr);
- *batch++ = upper_32_bits(target_addr);
- } else {
- *batch++ = (MI_STORE_DWORD_IMM_GEN4 | (1 << 21)) + 1;
- *batch++ = lower_32_bits(addr);
- *batch++ = upper_32_bits(addr);
- *batch++ = lower_32_bits(target_addr);
- *batch++ = upper_32_bits(target_addr);
- }
- } else if (ver >= 6) {
- *batch++ = MI_STORE_DWORD_IMM_GEN4;
- *batch++ = 0;
- *batch++ = addr;
- *batch++ = target_addr;
- } else if (IS_I965G(eb->i915)) {
- *batch++ = MI_STORE_DWORD_IMM_GEN4;
- *batch++ = 0;
- *batch++ = vma_phys_addr(vma, offset);
- *batch++ = target_addr;
- } else if (ver >= 4) {
- *batch++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
- *batch++ = 0;
- *batch++ = addr;
- *batch++ = target_addr;
- } else if (ver >= 3 &&
- !(IS_I915G(eb->i915) || IS_I915GM(eb->i915))) {
- *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
- *batch++ = addr;
- *batch++ = target_addr;
- } else {
- *batch++ = MI_STORE_DWORD_IMM;
- *batch++ = vma_phys_addr(vma, offset);
- *batch++ = target_addr;
- }
-
- return true;
-}
-
-static int reloc_entry_gpu(struct i915_execbuffer *eb,
- struct i915_vma *vma,
- u64 offset,
- u64 target_addr)
-{
- if (eb->reloc_cache.vaddr)
- return false;
-
- if (!use_reloc_gpu(vma))
- return false;
-
- return __reloc_entry_gpu(eb, vma, offset, target_addr);
-}
-
static u64
relocate_entry(struct i915_vma *vma,
const struct drm_i915_gem_relocation_entry *reloc,
@@ -1595,32 +1253,25 @@ relocate_entry(struct i915_vma *vma,
{
u64 target_addr = relocation_target(reloc, target);
u64 offset = reloc->offset;
- int reloc_gpu = reloc_entry_gpu(eb, vma, offset, target_addr);
-
- if (reloc_gpu < 0)
- return reloc_gpu;
-
- if (!reloc_gpu) {
- bool wide = eb->reloc_cache.use_64bit_reloc;
- void *vaddr;
+ bool wide = eb->reloc_cache.use_64bit_reloc;
+ void *vaddr;
repeat:
- vaddr = reloc_vaddr(vma->obj, eb,
- offset >> PAGE_SHIFT);
- if (IS_ERR(vaddr))
- return PTR_ERR(vaddr);
-
- GEM_BUG_ON(!IS_ALIGNED(offset, sizeof(u32)));
- clflush_write32(vaddr + offset_in_page(offset),
- lower_32_bits(target_addr),
- eb->reloc_cache.vaddr);
-
- if (wide) {
- offset += sizeof(u32);
- target_addr >>= 32;
- wide = false;
- goto repeat;
- }
+ vaddr = reloc_vaddr(vma->obj, eb,
+ offset >> PAGE_SHIFT);
+ if (IS_ERR(vaddr))
+ return PTR_ERR(vaddr);
+
+ GEM_BUG_ON(!IS_ALIGNED(offset, sizeof(u32)));
+ clflush_write32(vaddr + offset_in_page(offset),
+ lower_32_bits(target_addr),
+ eb->reloc_cache.vaddr);
+
+ if (wide) {
+ offset += sizeof(u32);
+ target_addr >>= 32;
+ wide = false;
+ goto repeat;
}
return target->node.start | UPDATE;
@@ -1992,7 +1643,7 @@ repeat:
}
/* We may process another execbuffer during the unlock... */
- eb_release_vmas(eb, false, true);
+ eb_release_vmas(eb, false);
i915_gem_ww_ctx_fini(&eb->ww);
if (rq) {
@@ -2061,9 +1712,7 @@ repeat_validate:
list_for_each_entry(ev, &eb->relocs, reloc_link) {
if (!have_copy) {
- pagefault_disable();
err = eb_relocate_vma(eb, ev);
- pagefault_enable();
if (err)
break;
} else {
@@ -2096,7 +1745,7 @@ repeat_validate:
err:
if (err == -EDEADLK) {
- eb_release_vmas(eb, false, false);
+ eb_release_vmas(eb, false);
err = i915_gem_ww_ctx_backoff(&eb->ww);
if (!err)
goto repeat_validate;
@@ -2193,7 +1842,7 @@ retry:
err:
if (err == -EDEADLK) {
- eb_release_vmas(eb, false, false);
+ eb_release_vmas(eb, false);
err = i915_gem_ww_ctx_backoff(&eb->ww);
if (!err)
goto retry;
@@ -2270,7 +1919,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
#ifdef CONFIG_MMU_NOTIFIER
if (!err && (eb->args->flags & __EXEC_USERPTR_USED)) {
- spin_lock(&eb->i915->mm.notifier_lock);
+ read_lock(&eb->i915->mm.notifier_lock);
/*
* count is always at least 1, otherwise __EXEC_USERPTR_USED
@@ -2288,7 +1937,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
break;
}
- spin_unlock(&eb->i915->mm.notifier_lock);
+ read_unlock(&eb->i915->mm.notifier_lock);
}
#endif
@@ -2782,7 +2431,7 @@ __free_fence_array(struct eb_fence *fences, unsigned int n)
while (n--) {
drm_syncobj_put(ptr_mask_bits(fences[n].syncobj, 2));
dma_fence_put(fences[n].dma_fence);
- kfree(fences[n].chain_fence);
+ dma_fence_chain_free(fences[n].chain_fence);
}
kvfree(fences);
}
@@ -2896,9 +2545,7 @@ add_timeline_fence_array(struct i915_execbuffer *eb,
return -EINVAL;
}
- f->chain_fence =
- kmalloc(sizeof(*f->chain_fence),
- GFP_KERNEL);
+ f->chain_fence = dma_fence_chain_alloc();
if (!f->chain_fence) {
drm_syncobj_put(syncobj);
dma_fence_put(fence);
@@ -3158,8 +2805,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
eb.exec = exec;
eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1);
eb.vma[0].vma = NULL;
- eb.reloc_pool = eb.batch_pool = NULL;
- eb.reloc_context = NULL;
+ eb.batch_pool = NULL;
eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
reloc_cache_init(&eb.reloc_cache, eb.i915);
@@ -3234,7 +2880,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
err = eb_lookup_vmas(&eb);
if (err) {
- eb_release_vmas(&eb, true, true);
+ eb_release_vmas(&eb, true);
goto err_engine;
}
@@ -3257,9 +2903,6 @@ i915_gem_do_execbuffer(struct drm_device *dev,
batch = eb.batch->vma;
- /* All GPU relocation batches must be submitted prior to the user rq */
- GEM_BUG_ON(eb.reloc_cache.rq);
-
/* Allocate a request for this batch buffer nice and early. */
eb.request = i915_request_create(eb.context);
if (IS_ERR(eb.request)) {
@@ -3267,11 +2910,20 @@ i915_gem_do_execbuffer(struct drm_device *dev,
goto err_vma;
}
+ if (unlikely(eb.gem_context->syncobj)) {
+ struct dma_fence *fence;
+
+ fence = drm_syncobj_fence_get(eb.gem_context->syncobj);
+ err = i915_request_await_dma_fence(eb.request, fence);
+ dma_fence_put(fence);
+ if (err)
+ goto err_ext;
+ }
+
if (in_fence) {
if (args->flags & I915_EXEC_FENCE_SUBMIT)
err = i915_request_await_execution(eb.request,
- in_fence,
- eb.engine->bond_execute);
+ in_fence);
else
err = i915_request_await_dma_fence(eb.request,
in_fence);
@@ -3324,10 +2976,16 @@ err_request:
fput(out_fence->file);
}
}
+
+ if (unlikely(eb.gem_context->syncobj)) {
+ drm_syncobj_replace_fence(eb.gem_context->syncobj,
+ &eb.request->fence);
+ }
+
i915_request_put(eb.request);
err_vma:
- eb_release_vmas(&eb, true, true);
+ eb_release_vmas(&eb, true);
if (eb.trampoline)
i915_vma_unpin(eb.trampoline);
WARN_ON(err == -EDEADLK);
@@ -3335,10 +2993,6 @@ err_vma:
if (eb.batch_pool)
intel_gt_buffer_pool_put(eb.batch_pool);
- if (eb.reloc_pool)
- intel_gt_buffer_pool_put(eb.reloc_pool);
- if (eb.reloc_context)
- intel_context_put(eb.reloc_context);
err_engine:
eb_put_engine(&eb);
err_context:
@@ -3452,7 +3106,3 @@ end:;
kvfree(exec2_list);
return err;
}
-
-#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
-#include "selftests/i915_gem_execbuffer.c"
-#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
index ce6b664b10aa..e5ae9c06510c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
@@ -42,7 +42,7 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
max_order = MAX_ORDER;
#ifdef CONFIG_SWIOTLB
- if (is_swiotlb_active()) {
+ if (is_swiotlb_active(obj->base.dev->dev)) {
unsigned int max_segment;
max_segment = swiotlb_max_segment();
@@ -177,8 +177,8 @@ i915_gem_object_create_internal(struct drm_i915_private *i915,
return ERR_PTR(-ENOMEM);
drm_gem_private_object_init(&i915->drm, &obj->base, size);
- i915_gem_object_init(obj, &i915_gem_object_internal_ops, &lock_class,
- I915_BO_ALLOC_STRUCT_PAGE);
+ i915_gem_object_init(obj, &i915_gem_object_internal_ops, &lock_class, 0);
+ obj->mem_flags |= I915_BO_FLAG_STRUCT_PAGE;
/*
* Mark the object as volatile, such that the pages are marked as
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
index 3b4aa28a076d..eb345305dc52 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c
@@ -4,74 +4,10 @@
*/
#include "intel_memory_region.h"
-#include "intel_region_ttm.h"
#include "gem/i915_gem_region.h"
#include "gem/i915_gem_lmem.h"
#include "i915_drv.h"
-static void lmem_put_pages(struct drm_i915_gem_object *obj,
- struct sg_table *pages)
-{
- intel_region_ttm_node_free(obj->mm.region, obj->mm.st_mm_node);
- obj->mm.dirty = false;
- sg_free_table(pages);
- kfree(pages);
-}
-
-static int lmem_get_pages(struct drm_i915_gem_object *obj)
-{
- unsigned int flags;
- struct sg_table *pages;
-
- flags = I915_ALLOC_MIN_PAGE_SIZE;
- if (obj->flags & I915_BO_ALLOC_CONTIGUOUS)
- flags |= I915_ALLOC_CONTIGUOUS;
-
- obj->mm.st_mm_node = intel_region_ttm_node_alloc(obj->mm.region,
- obj->base.size,
- flags);
- if (IS_ERR(obj->mm.st_mm_node))
- return PTR_ERR(obj->mm.st_mm_node);
-
- /* Range manager is always contigous */
- if (obj->mm.region->is_range_manager)
- obj->flags |= I915_BO_ALLOC_CONTIGUOUS;
- pages = intel_region_ttm_node_to_st(obj->mm.region, obj->mm.st_mm_node);
- if (IS_ERR(pages)) {
- intel_region_ttm_node_free(obj->mm.region, obj->mm.st_mm_node);
- return PTR_ERR(pages);
- }
-
- __i915_gem_object_set_pages(obj, pages, i915_sg_dma_sizes(pages->sgl));
-
- if (obj->flags & I915_BO_ALLOC_CPU_CLEAR) {
- void __iomem *vaddr =
- i915_gem_object_lmem_io_map(obj, 0, obj->base.size);
-
- if (!vaddr) {
- struct sg_table *pages =
- __i915_gem_object_unset_pages(obj);
-
- if (!IS_ERR_OR_NULL(pages))
- lmem_put_pages(obj, pages);
- }
-
- memset_io(vaddr, 0, obj->base.size);
- io_mapping_unmap(vaddr);
- }
-
- return 0;
-}
-
-const struct drm_i915_gem_object_ops i915_gem_lmem_obj_ops = {
- .name = "i915_gem_object_lmem",
- .flags = I915_GEM_OBJECT_HAS_IOMEM,
-
- .get_pages = lmem_get_pages,
- .put_pages = lmem_put_pages,
- .release = i915_gem_object_release_memory_region,
-};
-
void __iomem *
i915_gem_object_lmem_io_map(struct drm_i915_gem_object *obj,
unsigned long n,
@@ -87,39 +23,91 @@ i915_gem_object_lmem_io_map(struct drm_i915_gem_object *obj,
return io_mapping_map_wc(&obj->mm.region->iomap, offset, size);
}
+/**
+ * i915_gem_object_is_lmem - Whether the object is resident in
+ * lmem
+ * @obj: The object to check.
+ *
+ * Even if an object is allowed to migrate and change memory region,
+ * this function checks whether it will always be present in lmem when
+ * valid *or* if that's not the case, whether it's currently resident in lmem.
+ * For migratable and evictable objects, the latter only makes sense when
+ * the object is locked.
+ *
+ * Return: Whether the object migratable but resident in lmem, or not
+ * migratable and will be present in lmem when valid.
+ */
bool i915_gem_object_is_lmem(struct drm_i915_gem_object *obj)
{
- struct intel_memory_region *mr = obj->mm.region;
+ struct intel_memory_region *mr = READ_ONCE(obj->mm.region);
+#ifdef CONFIG_LOCKDEP
+ if (i915_gem_object_migratable(obj) &&
+ i915_gem_object_evictable(obj))
+ assert_object_held(obj);
+#endif
return mr && (mr->type == INTEL_MEMORY_LOCAL ||
mr->type == INTEL_MEMORY_STOLEN_LOCAL);
}
+/**
+ * __i915_gem_object_is_lmem - Whether the object is resident in
+ * lmem while in the fence signaling critical path.
+ * @obj: The object to check.
+ *
+ * This function is intended to be called from within the fence signaling
+ * path where the fence keeps the object from being migrated. For example
+ * during gpu reset or similar.
+ *
+ * Return: Whether the object is resident in lmem.
+ */
+bool __i915_gem_object_is_lmem(struct drm_i915_gem_object *obj)
+{
+ struct intel_memory_region *mr = READ_ONCE(obj->mm.region);
+
+#ifdef CONFIG_LOCKDEP
+ GEM_WARN_ON(dma_resv_test_signaled(obj->base.resv, true));
+#endif
+ return mr && (mr->type == INTEL_MEMORY_LOCAL ||
+ mr->type == INTEL_MEMORY_STOLEN_LOCAL);
+}
+
+/**
+ * __i915_gem_object_create_lmem_with_ps - Create lmem object and force the
+ * minimum page size for the backing pages.
+ * @i915: The i915 instance.
+ * @size: The size in bytes for the object. Note that we need to round the size
+ * up depending on the @page_size. The final object size can be fished out from
+ * the drm GEM object.
+ * @page_size: The requested minimum page size in bytes for this object. This is
+ * useful if we need something bigger than the regions min_page_size due to some
+ * hw restriction, or in some very specialised cases where it needs to be
+ * smaller, where the internal fragmentation cost is too great when rounding up
+ * the object size.
+ * @flags: The optional BO allocation flags.
+ *
+ * Note that this interface assumes you know what you are doing when forcing the
+ * @page_size. If this is smaller than the regions min_page_size then it can
+ * never be inserted into any GTT, otherwise it might lead to undefined
+ * behaviour.
+ *
+ * Return: The object pointer, which might be an ERR_PTR in the case of failure.
+ */
struct drm_i915_gem_object *
-i915_gem_object_create_lmem(struct drm_i915_private *i915,
- resource_size_t size,
- unsigned int flags)
+__i915_gem_object_create_lmem_with_ps(struct drm_i915_private *i915,
+ resource_size_t size,
+ resource_size_t page_size,
+ unsigned int flags)
{
return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM],
- size, flags);
+ size, page_size, flags);
}
-int __i915_gem_lmem_object_init(struct intel_memory_region *mem,
- struct drm_i915_gem_object *obj,
- resource_size_t size,
- unsigned int flags)
+struct drm_i915_gem_object *
+i915_gem_object_create_lmem(struct drm_i915_private *i915,
+ resource_size_t size,
+ unsigned int flags)
{
- static struct lock_class_key lock_class;
- struct drm_i915_private *i915 = mem->i915;
-
- drm_gem_private_object_init(&i915->drm, &obj->base, size);
- i915_gem_object_init(obj, &i915_gem_lmem_obj_ops, &lock_class, flags);
-
- obj->read_domains = I915_GEM_DOMAIN_WC | I915_GEM_DOMAIN_GTT;
-
- i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
-
- i915_gem_object_init_memory_region(obj, mem);
-
- return 0;
+ return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM],
+ size, 0, flags);
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.h b/drivers/gpu/drm/i915/gem/i915_gem_lmem.h
index fac6bc5a5ebb..4ee81fc66302 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.h
@@ -21,14 +21,16 @@ i915_gem_object_lmem_io_map(struct drm_i915_gem_object *obj,
bool i915_gem_object_is_lmem(struct drm_i915_gem_object *obj);
+bool __i915_gem_object_is_lmem(struct drm_i915_gem_object *obj);
+
+struct drm_i915_gem_object *
+__i915_gem_object_create_lmem_with_ps(struct drm_i915_private *i915,
+ resource_size_t size,
+ resource_size_t page_size,
+ unsigned int flags);
struct drm_i915_gem_object *
i915_gem_object_create_lmem(struct drm_i915_private *i915,
resource_size_t size,
unsigned int flags);
-int __i915_gem_lmem_object_init(struct intel_memory_region *mem,
- struct drm_i915_gem_object *obj,
- resource_size_t size,
- unsigned int flags);
-
#endif /* !__I915_GEM_LMEM_H */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index 215326764606..5130e8ed9564 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -19,6 +19,7 @@
#include "i915_gem_mman.h"
#include "i915_trace.h"
#include "i915_user_extensions.h"
+#include "i915_gem_ttm.h"
#include "i915_vma.h"
static inline bool
@@ -624,6 +625,8 @@ mmap_offset_attach(struct drm_i915_gem_object *obj,
struct i915_mmap_offset *mmo;
int err;
+ GEM_BUG_ON(obj->ops->mmap_offset || obj->ops->mmap_ops);
+
mmo = lookup_mmo(obj, mmap_type);
if (mmo)
goto out;
@@ -642,7 +645,8 @@ mmap_offset_attach(struct drm_i915_gem_object *obj,
goto insert;
/* Attempt to reap some mmap space from dead objects */
- err = intel_gt_retire_requests_timeout(&i915->gt, MAX_SCHEDULE_TIMEOUT);
+ err = intel_gt_retire_requests_timeout(&i915->gt, MAX_SCHEDULE_TIMEOUT,
+ NULL);
if (err)
goto err;
@@ -666,40 +670,58 @@ err:
}
static int
-__assign_mmap_offset(struct drm_file *file,
- u32 handle,
+__assign_mmap_offset(struct drm_i915_gem_object *obj,
enum i915_mmap_type mmap_type,
- u64 *offset)
+ u64 *offset, struct drm_file *file)
{
- struct drm_i915_gem_object *obj;
struct i915_mmap_offset *mmo;
- int err;
- obj = i915_gem_object_lookup(file, handle);
- if (!obj)
- return -ENOENT;
+ if (i915_gem_object_never_mmap(obj))
+ return -ENODEV;
- if (i915_gem_object_never_mmap(obj)) {
- err = -ENODEV;
- goto out;
+ if (obj->ops->mmap_offset) {
+ if (mmap_type != I915_MMAP_TYPE_FIXED)
+ return -ENODEV;
+
+ *offset = obj->ops->mmap_offset(obj);
+ return 0;
}
+ if (mmap_type == I915_MMAP_TYPE_FIXED)
+ return -ENODEV;
+
if (mmap_type != I915_MMAP_TYPE_GTT &&
!i915_gem_object_has_struct_page(obj) &&
- !i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_IOMEM)) {
- err = -ENODEV;
- goto out;
- }
+ !i915_gem_object_has_iomem(obj))
+ return -ENODEV;
mmo = mmap_offset_attach(obj, mmap_type, file);
- if (IS_ERR(mmo)) {
- err = PTR_ERR(mmo);
- goto out;
- }
+ if (IS_ERR(mmo))
+ return PTR_ERR(mmo);
*offset = drm_vma_node_offset_addr(&mmo->vma_node);
- err = 0;
-out:
+ return 0;
+}
+
+static int
+__assign_mmap_offset_handle(struct drm_file *file,
+ u32 handle,
+ enum i915_mmap_type mmap_type,
+ u64 *offset)
+{
+ struct drm_i915_gem_object *obj;
+ int err;
+
+ obj = i915_gem_object_lookup(file, handle);
+ if (!obj)
+ return -ENOENT;
+
+ err = i915_gem_object_lock_interruptible(obj, NULL);
+ if (err)
+ goto out_put;
+ err = __assign_mmap_offset(obj, mmap_type, offset, file);
+ i915_gem_object_unlock(obj);
+out_put:
i915_gem_object_put(obj);
return err;
}
@@ -712,14 +734,16 @@ i915_gem_dumb_mmap_offset(struct drm_file *file,
{
enum i915_mmap_type mmap_type;
- if (boot_cpu_has(X86_FEATURE_PAT))
+ if (HAS_LMEM(to_i915(dev)))
+ mmap_type = I915_MMAP_TYPE_FIXED;
+ else if (boot_cpu_has(X86_FEATURE_PAT))
mmap_type = I915_MMAP_TYPE_WC;
else if (!i915_ggtt_has_aperture(&to_i915(dev)->ggtt))
return -ENODEV;
else
mmap_type = I915_MMAP_TYPE_GTT;
- return __assign_mmap_offset(file, handle, mmap_type, offset);
+ return __assign_mmap_offset_handle(file, handle, mmap_type, offset);
}
/**
@@ -783,11 +807,15 @@ i915_gem_mmap_offset_ioctl(struct drm_device *dev, void *data,
type = I915_MMAP_TYPE_UC;
break;
+ case I915_MMAP_OFFSET_FIXED:
+ type = I915_MMAP_TYPE_FIXED;
+ break;
+
default:
return -EINVAL;
}
- return __assign_mmap_offset(file, args->handle, type, &args->offset);
+ return __assign_mmap_offset_handle(file, args->handle, type, &args->offset);
}
static void vm_open(struct vm_area_struct *vma)
@@ -891,8 +919,18 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
* destroyed and will be invalid when the vma manager lock
* is released.
*/
- mmo = container_of(node, struct i915_mmap_offset, vma_node);
- obj = i915_gem_object_get_rcu(mmo->obj);
+ if (!node->driver_private) {
+ mmo = container_of(node, struct i915_mmap_offset, vma_node);
+ obj = i915_gem_object_get_rcu(mmo->obj);
+
+ GEM_BUG_ON(obj && obj->ops->mmap_ops);
+ } else {
+ obj = i915_gem_object_get_rcu
+ (container_of(node, struct drm_i915_gem_object,
+ base.vma_node));
+
+ GEM_BUG_ON(obj && !obj->ops->mmap_ops);
+ }
}
drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
rcu_read_unlock();
@@ -913,8 +951,7 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
return PTR_ERR(anon);
}
- vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
- vma->vm_private_data = mmo;
+ vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
/*
* We keep the ref on mmo->obj, not vm_file, but we require
@@ -928,6 +965,15 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
/* Drop the initial creation reference, the vma is now holding one. */
fput(anon);
+ if (obj->ops->mmap_ops) {
+ vma->vm_page_prot = pgprot_decrypted(vm_get_page_prot(vma->vm_flags));
+ vma->vm_ops = obj->ops->mmap_ops;
+ vma->vm_private_data = node->driver_private;
+ return 0;
+ }
+
+ vma->vm_private_data = mmo;
+
switch (mmo->mmap_type) {
case I915_MMAP_TYPE_WC:
vma->vm_page_prot =
@@ -935,6 +981,9 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &vm_ops_cpu;
break;
+ case I915_MMAP_TYPE_FIXED:
+ GEM_WARN_ON(1);
+ fallthrough;
case I915_MMAP_TYPE_WB:
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
vma->vm_ops = &vm_ops_cpu;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 5706d471692d..6fb9afb65034 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -30,14 +30,10 @@
#include "i915_gem_context.h"
#include "i915_gem_mman.h"
#include "i915_gem_object.h"
-#include "i915_globals.h"
#include "i915_memcpy.h"
#include "i915_trace.h"
-static struct i915_global_object {
- struct i915_global base;
- struct kmem_cache *slab_objects;
-} global;
+static struct kmem_cache *slab_objects;
static const struct drm_gem_object_funcs i915_gem_object_funcs;
@@ -45,7 +41,7 @@ struct drm_i915_gem_object *i915_gem_object_alloc(void)
{
struct drm_i915_gem_object *obj;
- obj = kmem_cache_zalloc(global.slab_objects, GFP_KERNEL);
+ obj = kmem_cache_zalloc(slab_objects, GFP_KERNEL);
if (!obj)
return NULL;
obj->base.funcs = &i915_gem_object_funcs;
@@ -55,7 +51,7 @@ struct drm_i915_gem_object *i915_gem_object_alloc(void)
void i915_gem_object_free(struct drm_i915_gem_object *obj)
{
- return kmem_cache_free(global.slab_objects, obj);
+ return kmem_cache_free(slab_objects, obj);
}
void i915_gem_object_init(struct drm_i915_gem_object *obj,
@@ -172,7 +168,7 @@ static void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *f
}
}
-static void __i915_gem_free_object_rcu(struct rcu_head *head)
+void __i915_gem_free_object_rcu(struct rcu_head *head)
{
struct drm_i915_gem_object *obj =
container_of(head, typeof(*obj), rcu);
@@ -208,59 +204,69 @@ static void __i915_gem_object_free_mmaps(struct drm_i915_gem_object *obj)
}
}
-static void __i915_gem_free_objects(struct drm_i915_private *i915,
- struct llist_node *freed)
+void __i915_gem_free_object(struct drm_i915_gem_object *obj)
{
- struct drm_i915_gem_object *obj, *on;
+ trace_i915_gem_object_destroy(obj);
- llist_for_each_entry_safe(obj, on, freed, freed) {
- trace_i915_gem_object_destroy(obj);
+ if (!list_empty(&obj->vma.list)) {
+ struct i915_vma *vma;
+
+ /*
+ * Note that the vma keeps an object reference while
+ * it is active, so it *should* not sleep while we
+ * destroy it. Our debug code errs insits it *might*.
+ * For the moment, play along.
+ */
+ spin_lock(&obj->vma.lock);
+ while ((vma = list_first_entry_or_null(&obj->vma.list,
+ struct i915_vma,
+ obj_link))) {
+ GEM_BUG_ON(vma->obj != obj);
+ spin_unlock(&obj->vma.lock);
- if (!list_empty(&obj->vma.list)) {
- struct i915_vma *vma;
+ __i915_vma_put(vma);
- /*
- * Note that the vma keeps an object reference while
- * it is active, so it *should* not sleep while we
- * destroy it. Our debug code errs insits it *might*.
- * For the moment, play along.
- */
spin_lock(&obj->vma.lock);
- while ((vma = list_first_entry_or_null(&obj->vma.list,
- struct i915_vma,
- obj_link))) {
- GEM_BUG_ON(vma->obj != obj);
- spin_unlock(&obj->vma.lock);
+ }
+ spin_unlock(&obj->vma.lock);
+ }
- __i915_vma_put(vma);
+ __i915_gem_object_free_mmaps(obj);
- spin_lock(&obj->vma.lock);
- }
- spin_unlock(&obj->vma.lock);
- }
+ GEM_BUG_ON(!list_empty(&obj->lut_list));
- __i915_gem_object_free_mmaps(obj);
+ atomic_set(&obj->mm.pages_pin_count, 0);
+ __i915_gem_object_put_pages(obj);
+ GEM_BUG_ON(i915_gem_object_has_pages(obj));
+ bitmap_free(obj->bit_17);
- GEM_BUG_ON(!list_empty(&obj->lut_list));
+ if (obj->base.import_attach)
+ drm_prime_gem_destroy(&obj->base, NULL);
- atomic_set(&obj->mm.pages_pin_count, 0);
- __i915_gem_object_put_pages(obj);
- GEM_BUG_ON(i915_gem_object_has_pages(obj));
- bitmap_free(obj->bit_17);
+ drm_gem_free_mmap_offset(&obj->base);
- if (obj->base.import_attach)
- drm_prime_gem_destroy(&obj->base, NULL);
+ if (obj->ops->release)
+ obj->ops->release(obj);
- drm_gem_free_mmap_offset(&obj->base);
+ if (obj->mm.n_placements > 1)
+ kfree(obj->mm.placements);
- if (obj->ops->release)
- obj->ops->release(obj);
+ if (obj->shares_resv_from)
+ i915_vm_resv_put(obj->shares_resv_from);
+}
- if (obj->mm.n_placements > 1)
- kfree(obj->mm.placements);
+static void __i915_gem_free_objects(struct drm_i915_private *i915,
+ struct llist_node *freed)
+{
+ struct drm_i915_gem_object *obj, *on;
- if (obj->shares_resv_from)
- i915_vm_resv_put(obj->shares_resv_from);
+ llist_for_each_entry_safe(obj, on, freed, freed) {
+ might_sleep();
+ if (obj->ops->delayed_free) {
+ obj->ops->delayed_free(obj);
+ continue;
+ }
+ __i915_gem_free_object(obj);
/* But keep the pointer alive for RCU-protected lookups */
call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
@@ -318,6 +324,7 @@ static void i915_gem_free_object(struct drm_gem_object *gem_obj)
* worker and performing frees directly from subsequent allocations for
* crude but effective memory throttling.
*/
+
if (llist_add(&obj->freed, &i915->mm.free_list))
queue_work(i915->wq, &i915->mm.free_work);
}
@@ -410,34 +417,254 @@ int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset,
return 0;
}
-void i915_gem_init__objects(struct drm_i915_private *i915)
+/**
+ * i915_gem_object_evictable - Whether object is likely evictable after unbind.
+ * @obj: The object to check
+ *
+ * This function checks whether the object is likely unvictable after unbind.
+ * If the object is not locked when checking, the result is only advisory.
+ * If the object is locked when checking, and the function returns true,
+ * then an eviction should indeed be possible. But since unlocked vma
+ * unpinning and unbinding is currently possible, the object can actually
+ * become evictable even if this function returns false.
+ *
+ * Return: true if the object may be evictable. False otherwise.
+ */
+bool i915_gem_object_evictable(struct drm_i915_gem_object *obj)
{
- INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
+ struct i915_vma *vma;
+ int pin_count = atomic_read(&obj->mm.pages_pin_count);
+
+ if (!pin_count)
+ return true;
+
+ spin_lock(&obj->vma.lock);
+ list_for_each_entry(vma, &obj->vma.list, obj_link) {
+ if (i915_vma_is_pinned(vma)) {
+ spin_unlock(&obj->vma.lock);
+ return false;
+ }
+ if (atomic_read(&vma->pages_count))
+ pin_count--;
+ }
+ spin_unlock(&obj->vma.lock);
+ GEM_WARN_ON(pin_count < 0);
+
+ return pin_count == 0;
+}
+
+/**
+ * i915_gem_object_migratable - Whether the object is migratable out of the
+ * current region.
+ * @obj: Pointer to the object.
+ *
+ * Return: Whether the object is allowed to be resident in other
+ * regions than the current while pages are present.
+ */
+bool i915_gem_object_migratable(struct drm_i915_gem_object *obj)
+{
+ struct intel_memory_region *mr = READ_ONCE(obj->mm.region);
+
+ if (!mr)
+ return false;
+
+ return obj->mm.n_placements > 1;
}
-static void i915_global_objects_shrink(void)
+/**
+ * i915_gem_object_has_struct_page - Whether the object is page-backed
+ * @obj: The object to query.
+ *
+ * This function should only be called while the object is locked or pinned,
+ * otherwise the page backing may change under the caller.
+ *
+ * Return: True if page-backed, false otherwise.
+ */
+bool i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
{
- kmem_cache_shrink(global.slab_objects);
+#ifdef CONFIG_LOCKDEP
+ if (IS_DGFX(to_i915(obj->base.dev)) &&
+ i915_gem_object_evictable((void __force *)obj))
+ assert_object_held_shared(obj);
+#endif
+ return obj->mem_flags & I915_BO_FLAG_STRUCT_PAGE;
}
-static void i915_global_objects_exit(void)
+/**
+ * i915_gem_object_has_iomem - Whether the object is iomem-backed
+ * @obj: The object to query.
+ *
+ * This function should only be called while the object is locked or pinned,
+ * otherwise the iomem backing may change under the caller.
+ *
+ * Return: True if iomem-backed, false otherwise.
+ */
+bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
{
- kmem_cache_destroy(global.slab_objects);
+#ifdef CONFIG_LOCKDEP
+ if (IS_DGFX(to_i915(obj->base.dev)) &&
+ i915_gem_object_evictable((void __force *)obj))
+ assert_object_held_shared(obj);
+#endif
+ return obj->mem_flags & I915_BO_FLAG_IOMEM;
}
-static struct i915_global_object global = { {
- .shrink = i915_global_objects_shrink,
- .exit = i915_global_objects_exit,
-} };
+/**
+ * i915_gem_object_can_migrate - Whether an object likely can be migrated
+ *
+ * @obj: The object to migrate
+ * @id: The region intended to migrate to
+ *
+ * Check whether the object backend supports migration to the
+ * given region. Note that pinning may affect the ability to migrate as
+ * returned by this function.
+ *
+ * This function is primarily intended as a helper for checking the
+ * possibility to migrate objects and might be slightly less permissive
+ * than i915_gem_object_migrate() when it comes to objects with the
+ * I915_BO_ALLOC_USER flag set.
+ *
+ * Return: true if migration is possible, false otherwise.
+ */
+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
+ enum intel_region_id id)
+{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ unsigned int num_allowed = obj->mm.n_placements;
+ struct intel_memory_region *mr;
+ unsigned int i;
+
+ GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
+ GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
+
+ mr = i915->mm.regions[id];
+ if (!mr)
+ return false;
+
+ if (obj->mm.region == mr)
+ return true;
+
+ if (!i915_gem_object_evictable(obj))
+ return false;
+
+ if (!obj->ops->migrate)
+ return false;
+
+ if (!(obj->flags & I915_BO_ALLOC_USER))
+ return true;
+
+ if (num_allowed == 0)
+ return false;
+
+ for (i = 0; i < num_allowed; ++i) {
+ if (mr == obj->mm.placements[i])
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * i915_gem_object_migrate - Migrate an object to the desired region id
+ * @obj: The object to migrate.
+ * @ww: An optional struct i915_gem_ww_ctx. If NULL, the backend may
+ * not be successful in evicting other objects to make room for this object.
+ * @id: The region id to migrate to.
+ *
+ * Attempt to migrate the object to the desired memory region. The
+ * object backend must support migration and the object may not be
+ * pinned, (explicitly pinned pages or pinned vmas). The object must
+ * be locked.
+ * On successful completion, the object will have pages pointing to
+ * memory in the new region, but an async migration task may not have
+ * completed yet, and to accomplish that, i915_gem_object_wait_migration()
+ * must be called.
+ *
+ * Note: the @ww parameter is not used yet, but included to make sure
+ * callers put some effort into obtaining a valid ww ctx if one is
+ * available.
+ *
+ * Return: 0 on success. Negative error code on failure. In particular may
+ * return -ENXIO on lack of region space, -EDEADLK for deadlock avoidance
+ * if @ww is set, -EINTR or -ERESTARTSYS if signal pending, and
+ * -EBUSY if the object is pinned.
+ */
+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
+ struct i915_gem_ww_ctx *ww,
+ enum intel_region_id id)
+{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ struct intel_memory_region *mr;
+
+ GEM_BUG_ON(id >= INTEL_REGION_UNKNOWN);
+ GEM_BUG_ON(obj->mm.madv != I915_MADV_WILLNEED);
+ assert_object_held(obj);
+
+ mr = i915->mm.regions[id];
+ GEM_BUG_ON(!mr);
+
+ if (!i915_gem_object_can_migrate(obj, id))
+ return -EINVAL;
+
+ if (!obj->ops->migrate) {
+ if (GEM_WARN_ON(obj->mm.region != mr))
+ return -EINVAL;
+ return 0;
+ }
+
+ return obj->ops->migrate(obj, mr);
+}
+
+/**
+ * i915_gem_object_placement_possible - Check whether the object can be
+ * placed at certain memory type
+ * @obj: Pointer to the object
+ * @type: The memory type to check
+ *
+ * Return: True if the object can be placed in @type. False otherwise.
+ */
+bool i915_gem_object_placement_possible(struct drm_i915_gem_object *obj,
+ enum intel_memory_type type)
+{
+ unsigned int i;
+
+ if (!obj->mm.n_placements) {
+ switch (type) {
+ case INTEL_MEMORY_LOCAL:
+ return i915_gem_object_has_iomem(obj);
+ case INTEL_MEMORY_SYSTEM:
+ return i915_gem_object_has_pages(obj);
+ default:
+ /* Ignore stolen for now */
+ GEM_BUG_ON(1);
+ return false;
+ }
+ }
+
+ for (i = 0; i < obj->mm.n_placements; i++) {
+ if (obj->mm.placements[i]->type == type)
+ return true;
+ }
+
+ return false;
+}
+
+void i915_gem_init__objects(struct drm_i915_private *i915)
+{
+ INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
+}
+
+void i915_objects_module_exit(void)
+{
+ kmem_cache_destroy(slab_objects);
+}
-int __init i915_global_objects_init(void)
+int __init i915_objects_module_init(void)
{
- global.slab_objects =
- KMEM_CACHE(drm_i915_gem_object, SLAB_HWCACHE_ALIGN);
- if (!global.slab_objects)
+ slab_objects = KMEM_CACHE(drm_i915_gem_object, SLAB_HWCACHE_ALIGN);
+ if (!slab_objects)
return -ENOMEM;
- i915_global_register(&global.base);
return 0;
}
@@ -450,6 +677,7 @@ static const struct drm_gem_object_funcs i915_gem_object_funcs = {
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/huge_gem_object.c"
#include "selftests/huge_pages.c"
+#include "selftests/i915_gem_migrate.c"
#include "selftests/i915_gem_object.c"
#include "selftests/i915_gem_coherency.c"
#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 7c0eb425cb3b..48112b9d76df 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -12,10 +12,14 @@
#include <drm/drm_device.h>
#include "display/intel_frontbuffer.h"
+#include "intel_memory_region.h"
#include "i915_gem_object_types.h"
#include "i915_gem_gtt.h"
+#include "i915_gem_ww.h"
#include "i915_vma_types.h"
+enum intel_region_id;
+
/*
* XXX: There is a prevalence of the assumption that we fit the
* object's page count inside a 32bit _signed_ variable. Let's document
@@ -44,6 +48,9 @@ static inline bool i915_gem_object_size_2big(u64 size)
void i915_gem_init__objects(struct drm_i915_private *i915);
+void i915_objects_module_exit(void);
+int i915_objects_module_init(void);
+
struct drm_i915_gem_object *i915_gem_object_alloc(void);
void i915_gem_object_free(struct drm_i915_gem_object *obj);
@@ -57,6 +64,10 @@ i915_gem_object_create_shmem(struct drm_i915_private *i915,
struct drm_i915_gem_object *
i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
const void *data, resource_size_t size);
+struct drm_i915_gem_object *
+__i915_gem_object_create_user(struct drm_i915_private *i915, u64 size,
+ struct intel_memory_region **placements,
+ unsigned int n_placements);
extern const struct drm_i915_gem_object_ops i915_gem_shmem_ops;
@@ -147,7 +158,7 @@ i915_gem_object_put(struct drm_i915_gem_object *obj)
/*
* If more than one potential simultaneous locker, assert held.
*/
-static inline void assert_object_held_shared(struct drm_i915_gem_object *obj)
+static inline void assert_object_held_shared(const struct drm_i915_gem_object *obj)
{
/*
* Note mm list lookup is protected by
@@ -169,13 +180,17 @@ static inline int __i915_gem_object_lock(struct drm_i915_gem_object *obj,
else
ret = dma_resv_lock(obj->base.resv, ww ? &ww->ctx : NULL);
- if (!ret && ww)
+ if (!ret && ww) {
+ i915_gem_object_get(obj);
list_add_tail(&obj->obj_link, &ww->obj_list);
+ }
if (ret == -EALREADY)
ret = 0;
- if (ret == -EDEADLK)
+ if (ret == -EDEADLK) {
+ i915_gem_object_get(obj);
ww->contended = obj;
+ }
return ret;
}
@@ -200,6 +215,9 @@ static inline bool i915_gem_object_trylock(struct drm_i915_gem_object *obj)
static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj)
{
+ if (obj->ops->adjust_lru)
+ obj->ops->adjust_lru(obj);
+
dma_resv_unlock(obj->base.resv);
}
@@ -258,17 +276,9 @@ i915_gem_object_type_has(const struct drm_i915_gem_object *obj,
return obj->ops->flags & flags;
}
-static inline bool
-i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
-{
- return obj->flags & I915_BO_ALLOC_STRUCT_PAGE;
-}
+bool i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj);
-static inline bool
-i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
-{
- return i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_IOMEM);
-}
+bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj);
static inline bool
i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj)
@@ -339,22 +349,22 @@ struct scatterlist *
__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
struct i915_gem_object_page_iter *iter,
unsigned int n,
- unsigned int *offset, bool allow_alloc);
+ unsigned int *offset, bool dma);
static inline struct scatterlist *
i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
unsigned int n,
- unsigned int *offset, bool allow_alloc)
+ unsigned int *offset)
{
- return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, allow_alloc);
+ return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
}
static inline struct scatterlist *
i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
unsigned int n,
- unsigned int *offset, bool allow_alloc)
+ unsigned int *offset)
{
- return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, allow_alloc);
+ return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
}
struct page *
@@ -587,6 +597,27 @@ int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset,
bool i915_gem_object_is_shmem(const struct drm_i915_gem_object *obj);
+void __i915_gem_free_object_rcu(struct rcu_head *head);
+
+void __i915_gem_free_object(struct drm_i915_gem_object *obj);
+
+bool i915_gem_object_evictable(struct drm_i915_gem_object *obj);
+
+bool i915_gem_object_migratable(struct drm_i915_gem_object *obj);
+
+int i915_gem_object_migrate(struct drm_i915_gem_object *obj,
+ struct i915_gem_ww_ctx *ww,
+ enum intel_region_id id);
+
+bool i915_gem_object_can_migrate(struct drm_i915_gem_object *obj,
+ enum intel_region_id id);
+
+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
+ unsigned int flags);
+
+bool i915_gem_object_placement_possible(struct drm_i915_gem_object *obj,
+ enum intel_memory_type type);
+
#ifdef CONFIG_MMU_NOTIFIER
static inline bool
i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
@@ -596,14 +627,12 @@ i915_gem_object_is_userptr(struct drm_i915_gem_object *obj)
int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj);
int i915_gem_object_userptr_submit_done(struct drm_i915_gem_object *obj);
-void i915_gem_object_userptr_submit_fini(struct drm_i915_gem_object *obj);
int i915_gem_object_userptr_validate(struct drm_i915_gem_object *obj);
#else
static inline bool i915_gem_object_is_userptr(struct drm_i915_gem_object *obj) { return false; }
static inline int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj) { GEM_BUG_ON(1); return -ENODEV; }
static inline int i915_gem_object_userptr_submit_done(struct drm_i915_gem_object *obj) { GEM_BUG_ON(1); return -ENODEV; }
-static inline void i915_gem_object_userptr_submit_fini(struct drm_i915_gem_object *obj) { GEM_BUG_ON(1); }
static inline int i915_gem_object_userptr_validate(struct drm_i915_gem_object *obj) { GEM_BUG_ON(1); return -ENODEV; }
#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c
deleted file mode 100644
index 3e28c68fda3e..000000000000
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c
+++ /dev/null
@@ -1,461 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2019 Intel Corporation
- */
-
-#include "i915_drv.h"
-#include "gt/intel_context.h"
-#include "gt/intel_engine_pm.h"
-#include "gt/intel_gpu_commands.h"
-#include "gt/intel_gt.h"
-#include "gt/intel_gt_buffer_pool.h"
-#include "gt/intel_ring.h"
-#include "i915_gem_clflush.h"
-#include "i915_gem_object_blt.h"
-
-struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce,
- struct i915_vma *vma,
- struct i915_gem_ww_ctx *ww,
- u32 value)
-{
- struct drm_i915_private *i915 = ce->vm->i915;
- const u32 block_size = SZ_8M; /* ~1ms at 8GiB/s preemption delay */
- struct intel_gt_buffer_pool_node *pool;
- struct i915_vma *batch;
- u64 offset;
- u64 count;
- u64 rem;
- u32 size;
- u32 *cmd;
- int err;
-
- GEM_BUG_ON(intel_engine_is_virtual(ce->engine));
- intel_engine_pm_get(ce->engine);
-
- count = div_u64(round_up(vma->size, block_size), block_size);
- size = (1 + 8 * count) * sizeof(u32);
- size = round_up(size, PAGE_SIZE);
- pool = intel_gt_get_buffer_pool(ce->engine->gt, size, I915_MAP_WC);
- if (IS_ERR(pool)) {
- err = PTR_ERR(pool);
- goto out_pm;
- }
-
- err = i915_gem_object_lock(pool->obj, ww);
- if (err)
- goto out_put;
-
- batch = i915_vma_instance(pool->obj, ce->vm, NULL);
- if (IS_ERR(batch)) {
- err = PTR_ERR(batch);
- goto out_put;
- }
-
- err = i915_vma_pin_ww(batch, ww, 0, 0, PIN_USER);
- if (unlikely(err))
- goto out_put;
-
- /* we pinned the pool, mark it as such */
- intel_gt_buffer_pool_mark_used(pool);
-
- cmd = i915_gem_object_pin_map(pool->obj, pool->type);
- if (IS_ERR(cmd)) {
- err = PTR_ERR(cmd);
- goto out_unpin;
- }
-
- rem = vma->size;
- offset = vma->node.start;
-
- do {
- u32 size = min_t(u64, rem, block_size);
-
- GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX);
-
- if (GRAPHICS_VER(i915) >= 8) {
- *cmd++ = XY_COLOR_BLT_CMD | BLT_WRITE_RGBA | (7 - 2);
- *cmd++ = BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | PAGE_SIZE;
- *cmd++ = 0;
- *cmd++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE / 4;
- *cmd++ = lower_32_bits(offset);
- *cmd++ = upper_32_bits(offset);
- *cmd++ = value;
- } else {
- *cmd++ = XY_COLOR_BLT_CMD | BLT_WRITE_RGBA | (6 - 2);
- *cmd++ = BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | PAGE_SIZE;
- *cmd++ = 0;
- *cmd++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE / 4;
- *cmd++ = offset;
- *cmd++ = value;
- }
-
- /* Allow ourselves to be preempted in between blocks. */
- *cmd++ = MI_ARB_CHECK;
-
- offset += size;
- rem -= size;
- } while (rem);
-
- *cmd = MI_BATCH_BUFFER_END;
-
- i915_gem_object_flush_map(pool->obj);
- i915_gem_object_unpin_map(pool->obj);
-
- intel_gt_chipset_flush(ce->vm->gt);
-
- batch->private = pool;
- return batch;
-
-out_unpin:
- i915_vma_unpin(batch);
-out_put:
- intel_gt_buffer_pool_put(pool);
-out_pm:
- intel_engine_pm_put(ce->engine);
- return ERR_PTR(err);
-}
-
-int intel_emit_vma_mark_active(struct i915_vma *vma, struct i915_request *rq)
-{
- int err;
-
- err = i915_request_await_object(rq, vma->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, 0);
- if (unlikely(err))
- return err;
-
- return intel_gt_buffer_pool_mark_active(vma->private, rq);
-}
-
-void intel_emit_vma_release(struct intel_context *ce, struct i915_vma *vma)
-{
- i915_vma_unpin(vma);
- intel_gt_buffer_pool_put(vma->private);
- intel_engine_pm_put(ce->engine);
-}
-
-static int
-move_obj_to_gpu(struct drm_i915_gem_object *obj,
- struct i915_request *rq,
- bool write)
-{
- if (obj->cache_dirty & ~obj->cache_coherent)
- i915_gem_clflush_object(obj, 0);
-
- return i915_request_await_object(rq, obj, write);
-}
-
-int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj,
- struct intel_context *ce,
- u32 value)
-{
- struct i915_gem_ww_ctx ww;
- struct i915_request *rq;
- struct i915_vma *batch;
- struct i915_vma *vma;
- int err;
-
- vma = i915_vma_instance(obj, ce->vm, NULL);
- if (IS_ERR(vma))
- return PTR_ERR(vma);
-
- i915_gem_ww_ctx_init(&ww, true);
- intel_engine_pm_get(ce->engine);
-retry:
- err = i915_gem_object_lock(obj, &ww);
- if (err)
- goto out;
-
- err = intel_context_pin_ww(ce, &ww);
- if (err)
- goto out;
-
- err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER);
- if (err)
- goto out_ctx;
-
- batch = intel_emit_vma_fill_blt(ce, vma, &ww, value);
- if (IS_ERR(batch)) {
- err = PTR_ERR(batch);
- goto out_vma;
- }
-
- rq = i915_request_create(ce);
- if (IS_ERR(rq)) {
- err = PTR_ERR(rq);
- goto out_batch;
- }
-
- err = intel_emit_vma_mark_active(batch, rq);
- if (unlikely(err))
- goto out_request;
-
- err = move_obj_to_gpu(vma->obj, rq, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
- if (unlikely(err))
- goto out_request;
-
- if (ce->engine->emit_init_breadcrumb)
- err = ce->engine->emit_init_breadcrumb(rq);
-
- if (likely(!err))
- err = ce->engine->emit_bb_start(rq,
- batch->node.start,
- batch->node.size,
- 0);
-out_request:
- if (unlikely(err))
- i915_request_set_error_once(rq, err);
-
- i915_request_add(rq);
-out_batch:
- intel_emit_vma_release(ce, batch);
-out_vma:
- i915_vma_unpin(vma);
-out_ctx:
- intel_context_unpin(ce);
-out:
- if (err == -EDEADLK) {
- err = i915_gem_ww_ctx_backoff(&ww);
- if (!err)
- goto retry;
- }
- i915_gem_ww_ctx_fini(&ww);
- intel_engine_pm_put(ce->engine);
- return err;
-}
-
-/* Wa_1209644611:icl,ehl */
-static bool wa_1209644611_applies(struct drm_i915_private *i915, u32 size)
-{
- u32 height = size >> PAGE_SHIFT;
-
- if (GRAPHICS_VER(i915) != 11)
- return false;
-
- return height % 4 == 3 && height <= 8;
-}
-
-struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
- struct i915_gem_ww_ctx *ww,
- struct i915_vma *src,
- struct i915_vma *dst)
-{
- struct drm_i915_private *i915 = ce->vm->i915;
- const u32 block_size = SZ_8M; /* ~1ms at 8GiB/s preemption delay */
- struct intel_gt_buffer_pool_node *pool;
- struct i915_vma *batch;
- u64 src_offset, dst_offset;
- u64 count, rem;
- u32 size, *cmd;
- int err;
-
- GEM_BUG_ON(src->size != dst->size);
-
- GEM_BUG_ON(intel_engine_is_virtual(ce->engine));
- intel_engine_pm_get(ce->engine);
-
- count = div_u64(round_up(dst->size, block_size), block_size);
- size = (1 + 11 * count) * sizeof(u32);
- size = round_up(size, PAGE_SIZE);
- pool = intel_gt_get_buffer_pool(ce->engine->gt, size, I915_MAP_WC);
- if (IS_ERR(pool)) {
- err = PTR_ERR(pool);
- goto out_pm;
- }
-
- err = i915_gem_object_lock(pool->obj, ww);
- if (err)
- goto out_put;
-
- batch = i915_vma_instance(pool->obj, ce->vm, NULL);
- if (IS_ERR(batch)) {
- err = PTR_ERR(batch);
- goto out_put;
- }
-
- err = i915_vma_pin_ww(batch, ww, 0, 0, PIN_USER);
- if (unlikely(err))
- goto out_put;
-
- /* we pinned the pool, mark it as such */
- intel_gt_buffer_pool_mark_used(pool);
-
- cmd = i915_gem_object_pin_map(pool->obj, pool->type);
- if (IS_ERR(cmd)) {
- err = PTR_ERR(cmd);
- goto out_unpin;
- }
-
- rem = src->size;
- src_offset = src->node.start;
- dst_offset = dst->node.start;
-
- do {
- size = min_t(u64, rem, block_size);
- GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX);
-
- if (GRAPHICS_VER(i915) >= 9 &&
- !wa_1209644611_applies(i915, size)) {
- *cmd++ = GEN9_XY_FAST_COPY_BLT_CMD | (10 - 2);
- *cmd++ = BLT_DEPTH_32 | PAGE_SIZE;
- *cmd++ = 0;
- *cmd++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE / 4;
- *cmd++ = lower_32_bits(dst_offset);
- *cmd++ = upper_32_bits(dst_offset);
- *cmd++ = 0;
- *cmd++ = PAGE_SIZE;
- *cmd++ = lower_32_bits(src_offset);
- *cmd++ = upper_32_bits(src_offset);
- } else if (GRAPHICS_VER(i915) >= 8) {
- *cmd++ = XY_SRC_COPY_BLT_CMD | BLT_WRITE_RGBA | (10 - 2);
- *cmd++ = BLT_DEPTH_32 | BLT_ROP_SRC_COPY | PAGE_SIZE;
- *cmd++ = 0;
- *cmd++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE / 4;
- *cmd++ = lower_32_bits(dst_offset);
- *cmd++ = upper_32_bits(dst_offset);
- *cmd++ = 0;
- *cmd++ = PAGE_SIZE;
- *cmd++ = lower_32_bits(src_offset);
- *cmd++ = upper_32_bits(src_offset);
- } else {
- *cmd++ = SRC_COPY_BLT_CMD | BLT_WRITE_RGBA | (6 - 2);
- *cmd++ = BLT_DEPTH_32 | BLT_ROP_SRC_COPY | PAGE_SIZE;
- *cmd++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE;
- *cmd++ = dst_offset;
- *cmd++ = PAGE_SIZE;
- *cmd++ = src_offset;
- }
-
- /* Allow ourselves to be preempted in between blocks. */
- *cmd++ = MI_ARB_CHECK;
-
- src_offset += size;
- dst_offset += size;
- rem -= size;
- } while (rem);
-
- *cmd = MI_BATCH_BUFFER_END;
-
- i915_gem_object_flush_map(pool->obj);
- i915_gem_object_unpin_map(pool->obj);
-
- intel_gt_chipset_flush(ce->vm->gt);
- batch->private = pool;
- return batch;
-
-out_unpin:
- i915_vma_unpin(batch);
-out_put:
- intel_gt_buffer_pool_put(pool);
-out_pm:
- intel_engine_pm_put(ce->engine);
- return ERR_PTR(err);
-}
-
-int i915_gem_object_copy_blt(struct drm_i915_gem_object *src,
- struct drm_i915_gem_object *dst,
- struct intel_context *ce)
-{
- struct i915_address_space *vm = ce->vm;
- struct i915_vma *vma[2], *batch;
- struct i915_gem_ww_ctx ww;
- struct i915_request *rq;
- int err, i;
-
- vma[0] = i915_vma_instance(src, vm, NULL);
- if (IS_ERR(vma[0]))
- return PTR_ERR(vma[0]);
-
- vma[1] = i915_vma_instance(dst, vm, NULL);
- if (IS_ERR(vma[1]))
- return PTR_ERR(vma[1]);
-
- i915_gem_ww_ctx_init(&ww, true);
- intel_engine_pm_get(ce->engine);
-retry:
- err = i915_gem_object_lock(src, &ww);
- if (!err)
- err = i915_gem_object_lock(dst, &ww);
- if (!err)
- err = intel_context_pin_ww(ce, &ww);
- if (err)
- goto out;
-
- err = i915_vma_pin_ww(vma[0], &ww, 0, 0, PIN_USER);
- if (err)
- goto out_ctx;
-
- err = i915_vma_pin_ww(vma[1], &ww, 0, 0, PIN_USER);
- if (unlikely(err))
- goto out_unpin_src;
-
- batch = intel_emit_vma_copy_blt(ce, &ww, vma[0], vma[1]);
- if (IS_ERR(batch)) {
- err = PTR_ERR(batch);
- goto out_unpin_dst;
- }
-
- rq = i915_request_create(ce);
- if (IS_ERR(rq)) {
- err = PTR_ERR(rq);
- goto out_batch;
- }
-
- err = intel_emit_vma_mark_active(batch, rq);
- if (unlikely(err))
- goto out_request;
-
- for (i = 0; i < ARRAY_SIZE(vma); i++) {
- err = move_obj_to_gpu(vma[i]->obj, rq, i);
- if (unlikely(err))
- goto out_request;
- }
-
- for (i = 0; i < ARRAY_SIZE(vma); i++) {
- unsigned int flags = i ? EXEC_OBJECT_WRITE : 0;
-
- err = i915_vma_move_to_active(vma[i], rq, flags);
- if (unlikely(err))
- goto out_request;
- }
-
- if (rq->engine->emit_init_breadcrumb) {
- err = rq->engine->emit_init_breadcrumb(rq);
- if (unlikely(err))
- goto out_request;
- }
-
- err = rq->engine->emit_bb_start(rq,
- batch->node.start, batch->node.size,
- 0);
-
-out_request:
- if (unlikely(err))
- i915_request_set_error_once(rq, err);
-
- i915_request_add(rq);
-out_batch:
- intel_emit_vma_release(ce, batch);
-out_unpin_dst:
- i915_vma_unpin(vma[1]);
-out_unpin_src:
- i915_vma_unpin(vma[0]);
-out_ctx:
- intel_context_unpin(ce);
-out:
- if (err == -EDEADLK) {
- err = i915_gem_ww_ctx_backoff(&ww);
- if (!err)
- goto retry;
- }
- i915_gem_ww_ctx_fini(&ww);
- intel_engine_pm_put(ce->engine);
- return err;
-}
-
-#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
-#include "selftests/i915_gem_object_blt.c"
-#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h
deleted file mode 100644
index 2409fdcccf0e..000000000000
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2019 Intel Corporation
- */
-
-#ifndef __I915_GEM_OBJECT_BLT_H__
-#define __I915_GEM_OBJECT_BLT_H__
-
-#include <linux/types.h>
-
-#include "gt/intel_context.h"
-#include "gt/intel_engine_pm.h"
-#include "i915_vma.h"
-
-struct drm_i915_gem_object;
-struct i915_gem_ww_ctx;
-
-struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce,
- struct i915_vma *vma,
- struct i915_gem_ww_ctx *ww,
- u32 value);
-
-struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
- struct i915_gem_ww_ctx *ww,
- struct i915_vma *src,
- struct i915_vma *dst);
-
-int intel_emit_vma_mark_active(struct i915_vma *vma, struct i915_request *rq);
-void intel_emit_vma_release(struct intel_context *ce, struct i915_vma *vma);
-
-int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj,
- struct intel_context *ce,
- u32 value);
-
-int i915_gem_object_copy_blt(struct drm_i915_gem_object *src,
- struct drm_i915_gem_object *dst,
- struct intel_context *ce);
-
-#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index d047ea126029..2471f36aaff3 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -18,6 +18,7 @@
struct drm_i915_gem_object;
struct intel_fronbuffer;
+struct intel_memory_region;
/*
* struct i915_lut_handle tracks the fast lookups from handle to vma used
@@ -33,10 +34,9 @@ struct i915_lut_handle {
struct drm_i915_gem_object_ops {
unsigned int flags;
-#define I915_GEM_OBJECT_HAS_IOMEM BIT(1)
-#define I915_GEM_OBJECT_IS_SHRINKABLE BIT(2)
-#define I915_GEM_OBJECT_IS_PROXY BIT(3)
-#define I915_GEM_OBJECT_NO_MMAP BIT(4)
+#define I915_GEM_OBJECT_IS_SHRINKABLE BIT(1)
+#define I915_GEM_OBJECT_IS_PROXY BIT(2)
+#define I915_GEM_OBJECT_NO_MMAP BIT(3)
/* Interface between the GEM object and its backing storage.
* get_pages() is called once prior to the use of the associated set
@@ -61,13 +61,117 @@ struct drm_i915_gem_object_ops {
const struct drm_i915_gem_pread *arg);
int (*pwrite)(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_pwrite *arg);
+ u64 (*mmap_offset)(struct drm_i915_gem_object *obj);
int (*dmabuf_export)(struct drm_i915_gem_object *obj);
+
+ /**
+ * adjust_lru - notify that the madvise value was updated
+ * @obj: The gem object
+ *
+ * The madvise value may have been updated, or object was recently
+ * referenced so act accordingly (Perhaps changing an LRU list etc).
+ */
+ void (*adjust_lru)(struct drm_i915_gem_object *obj);
+
+ /**
+ * delayed_free - Override the default delayed free implementation
+ */
+ void (*delayed_free)(struct drm_i915_gem_object *obj);
+
+ /**
+ * migrate - Migrate object to a different region either for
+ * pinning or for as long as the object lock is held.
+ */
+ int (*migrate)(struct drm_i915_gem_object *obj,
+ struct intel_memory_region *mr);
+
void (*release)(struct drm_i915_gem_object *obj);
+ const struct vm_operations_struct *mmap_ops;
const char *name; /* friendly name for debug, e.g. lockdep classes */
};
+/**
+ * enum i915_cache_level - The supported GTT caching values for system memory
+ * pages.
+ *
+ * These translate to some special GTT PTE bits when binding pages into some
+ * address space. It also determines whether an object, or rather its pages are
+ * coherent with the GPU, when also reading or writing through the CPU cache
+ * with those pages.
+ *
+ * Userspace can also control this through struct drm_i915_gem_caching.
+ */
+enum i915_cache_level {
+ /**
+ * @I915_CACHE_NONE:
+ *
+ * GPU access is not coherent with the CPU cache. If the cache is dirty
+ * and we need the underlying pages to be coherent with some later GPU
+ * access then we need to manually flush the pages.
+ *
+ * On shared LLC platforms reads and writes through the CPU cache are
+ * still coherent even with this setting. See also
+ * &drm_i915_gem_object.cache_coherent for more details. Due to this we
+ * should only ever use uncached for scanout surfaces, otherwise we end
+ * up over-flushing in some places.
+ *
+ * This is the default on non-LLC platforms.
+ */
+ I915_CACHE_NONE = 0,
+ /**
+ * @I915_CACHE_LLC:
+ *
+ * GPU access is coherent with the CPU cache. If the cache is dirty,
+ * then the GPU will ensure that access remains coherent, when both
+ * reading and writing through the CPU cache. GPU writes can dirty the
+ * CPU cache.
+ *
+ * Not used for scanout surfaces.
+ *
+ * Applies to both platforms with shared LLC(HAS_LLC), and snooping
+ * based platforms(HAS_SNOOP).
+ *
+ * This is the default on shared LLC platforms. The only exception is
+ * scanout objects, where the display engine is not coherent with the
+ * CPU cache. For such objects I915_CACHE_NONE or I915_CACHE_WT is
+ * automatically applied by the kernel in pin_for_display, if userspace
+ * has not done so already.
+ */
+ I915_CACHE_LLC,
+ /**
+ * @I915_CACHE_L3_LLC:
+ *
+ * Explicitly enable the Gfx L3 cache, with coherent LLC.
+ *
+ * The Gfx L3 sits between the domain specific caches, e.g
+ * sampler/render caches, and the larger LLC. LLC is coherent with the
+ * GPU, but L3 is only visible to the GPU, so likely needs to be flushed
+ * when the workload completes.
+ *
+ * Not used for scanout surfaces.
+ *
+ * Only exposed on some gen7 + GGTT. More recent hardware has dropped
+ * this explicit setting, where it should now be enabled by default.
+ */
+ I915_CACHE_L3_LLC,
+ /**
+ * @I915_CACHE_WT:
+ *
+ * Write-through. Used for scanout surfaces.
+ *
+ * The GPU can utilise the caches, while still having the display engine
+ * be coherent with GPU writes, as a result we don't need to flush the
+ * CPU caches when moving out of the render domain. This is the default
+ * setting chosen by the kernel, if supported by the HW, otherwise we
+ * fallback to I915_CACHE_NONE. On the CPU side writes through the CPU
+ * cache still need to be flushed, to remain coherent with the display
+ * engine.
+ */
+ I915_CACHE_WT,
+};
+
enum i915_map_type {
I915_MAP_WB = 0,
I915_MAP_WC,
@@ -81,6 +185,7 @@ enum i915_mmap_type {
I915_MMAP_TYPE_WC,
I915_MMAP_TYPE_WB,
I915_MMAP_TYPE_UC,
+ I915_MMAP_TYPE_FIXED,
};
struct i915_mmap_offset {
@@ -185,23 +290,138 @@ struct drm_i915_gem_object {
unsigned long flags;
#define I915_BO_ALLOC_CONTIGUOUS BIT(0)
#define I915_BO_ALLOC_VOLATILE BIT(1)
-#define I915_BO_ALLOC_STRUCT_PAGE BIT(2)
-#define I915_BO_ALLOC_CPU_CLEAR BIT(3)
+#define I915_BO_ALLOC_CPU_CLEAR BIT(2)
+#define I915_BO_ALLOC_USER BIT(3)
#define I915_BO_ALLOC_FLAGS (I915_BO_ALLOC_CONTIGUOUS | \
I915_BO_ALLOC_VOLATILE | \
- I915_BO_ALLOC_STRUCT_PAGE | \
- I915_BO_ALLOC_CPU_CLEAR)
+ I915_BO_ALLOC_CPU_CLEAR | \
+ I915_BO_ALLOC_USER)
#define I915_BO_READONLY BIT(4)
#define I915_TILING_QUIRK_BIT 5 /* unknown swizzling; do not release! */
- /*
- * Is the object to be mapped as read-only to the GPU
- * Only honoured if hardware has relevant pte bit
+ /**
+ * @mem_flags - Mutable placement-related flags
+ *
+ * These are flags that indicate specifics of the memory region
+ * the object is currently in. As such they are only stable
+ * either under the object lock or if the object is pinned.
+ */
+ unsigned int mem_flags;
+#define I915_BO_FLAG_STRUCT_PAGE BIT(0) /* Object backed by struct pages */
+#define I915_BO_FLAG_IOMEM BIT(1) /* Object backed by IO memory */
+ /**
+ * @cache_level: The desired GTT caching level.
+ *
+ * See enum i915_cache_level for possible values, along with what
+ * each does.
*/
unsigned int cache_level:3;
- unsigned int cache_coherent:2;
+ /**
+ * @cache_coherent:
+ *
+ * Track whether the pages are coherent with the GPU if reading or
+ * writing through the CPU caches. The largely depends on the
+ * @cache_level setting.
+ *
+ * On platforms which don't have the shared LLC(HAS_SNOOP), like on Atom
+ * platforms, coherency must be explicitly requested with some special
+ * GTT caching bits(see enum i915_cache_level). When enabling coherency
+ * it does come at a performance and power cost on such platforms. On
+ * the flip side the kernel does not need to manually flush any buffers
+ * which need to be coherent with the GPU, if the object is not coherent
+ * i.e @cache_coherent is zero.
+ *
+ * On platforms that share the LLC with the CPU(HAS_LLC), all GT memory
+ * access will automatically snoop the CPU caches(even with CACHE_NONE).
+ * The one exception is when dealing with the display engine, like with
+ * scanout surfaces. To handle this the kernel will always flush the
+ * surface out of the CPU caches when preparing it for scanout. Also
+ * note that since scanout surfaces are only ever read by the display
+ * engine we only need to care about flushing any writes through the CPU
+ * cache, reads on the other hand will always be coherent.
+ *
+ * Something strange here is why @cache_coherent is not a simple
+ * boolean, i.e coherent vs non-coherent. The reasoning for this is back
+ * to the display engine not being fully coherent. As a result scanout
+ * surfaces will either be marked as I915_CACHE_NONE or I915_CACHE_WT.
+ * In the case of seeing I915_CACHE_NONE the kernel makes the assumption
+ * that this is likely a scanout surface, and will set @cache_coherent
+ * as only I915_BO_CACHE_COHERENT_FOR_READ, on platforms with the shared
+ * LLC. The kernel uses this to always flush writes through the CPU
+ * cache as early as possible, where it can, in effect keeping
+ * @cache_dirty clean, so we can potentially avoid stalling when
+ * flushing the surface just before doing the scanout. This does mean
+ * we might unnecessarily flush non-scanout objects in some places, but
+ * the default assumption is that all normal objects should be using
+ * I915_CACHE_LLC, at least on platforms with the shared LLC.
+ *
+ * Supported values:
+ *
+ * I915_BO_CACHE_COHERENT_FOR_READ:
+ *
+ * On shared LLC platforms, we use this for special scanout surfaces,
+ * where the display engine is not coherent with the CPU cache. As such
+ * we need to ensure we flush any writes before doing the scanout. As an
+ * optimisation we try to flush any writes as early as possible to avoid
+ * stalling later.
+ *
+ * Thus for scanout surfaces using I915_CACHE_NONE, on shared LLC
+ * platforms, we use:
+ *
+ * cache_coherent = I915_BO_CACHE_COHERENT_FOR_READ
+ *
+ * While for normal objects that are fully coherent, including special
+ * scanout surfaces marked as I915_CACHE_WT, we use:
+ *
+ * cache_coherent = I915_BO_CACHE_COHERENT_FOR_READ |
+ * I915_BO_CACHE_COHERENT_FOR_WRITE
+ *
+ * And then for objects that are not coherent at all we use:
+ *
+ * cache_coherent = 0
+ *
+ * I915_BO_CACHE_COHERENT_FOR_WRITE:
+ *
+ * When writing through the CPU cache, the GPU is still coherent. Note
+ * that this also implies I915_BO_CACHE_COHERENT_FOR_READ.
+ */
#define I915_BO_CACHE_COHERENT_FOR_READ BIT(0)
#define I915_BO_CACHE_COHERENT_FOR_WRITE BIT(1)
+ unsigned int cache_coherent:2;
+
+ /**
+ * @cache_dirty:
+ *
+ * Track if we are we dirty with writes through the CPU cache for this
+ * object. As a result reading directly from main memory might yield
+ * stale data.
+ *
+ * This also ties into whether the kernel is tracking the object as
+ * coherent with the GPU, as per @cache_coherent, as it determines if
+ * flushing might be needed at various points.
+ *
+ * Another part of @cache_dirty is managing flushing when first
+ * acquiring the pages for system memory, at this point the pages are
+ * considered foreign, so the default assumption is that the cache is
+ * dirty, for example the page zeroing done by the kernel might leave
+ * writes though the CPU cache, or swapping-in, while the actual data in
+ * main memory is potentially stale. Note that this is a potential
+ * security issue when dealing with userspace objects and zeroing. Now,
+ * whether we actually need apply the big sledgehammer of flushing all
+ * the pages on acquire depends on if @cache_coherent is marked as
+ * I915_BO_CACHE_COHERENT_FOR_WRITE, i.e that the GPU will be coherent
+ * for both reads and writes though the CPU cache.
+ *
+ * Note that on shared LLC platforms we still apply the heavy flush for
+ * I915_CACHE_NONE objects, under the assumption that this is going to
+ * be used for scanout.
+ *
+ * Update: On some hardware there is now also the 'Bypass LLC' MOCS
+ * entry, which defeats our @cache_coherent tracking, since userspace
+ * can freely bypass the CPU cache when touching the pages with the GPU,
+ * where the kernel is completely unaware. On such platform we need
+ * apply the sledgehammer-on-acquire regardless of the @cache_coherent.
+ */
unsigned int cache_dirty:1;
/**
@@ -247,9 +467,10 @@ struct drm_i915_gem_object {
struct intel_memory_region *region;
/**
- * Memory manager node allocated for this object.
+ * Memory manager resource allocated for this object. Only
+ * needed for the mock region.
*/
- void *st_mm_node;
+ struct ttm_resource *res;
/**
* Element within memory_region->objects or region->purgeable
@@ -310,6 +531,12 @@ struct drm_i915_gem_object {
bool dirty:1;
} mm;
+ struct {
+ struct sg_table *cached_io_st;
+ struct i915_gem_object_page_iter get_io_page;
+ bool created:1;
+ } ttm;
+
/** Record of address bit 17 of each page at last unbind. */
unsigned long *bit_17;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index 6444e097016d..8eb1c3a6fc9c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -321,8 +321,7 @@ static void *i915_gem_object_map_pfn(struct drm_i915_gem_object *obj,
dma_addr_t addr;
void *vaddr;
- if (type != I915_MAP_WC)
- return ERR_PTR(-ENODEV);
+ GEM_BUG_ON(type != I915_MAP_WC);
if (n_pfn > ARRAY_SIZE(stack)) {
/* Too big for stack -- allocate temporary array instead */
@@ -351,7 +350,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
int err;
if (!i915_gem_object_has_struct_page(obj) &&
- !i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_IOMEM))
+ !i915_gem_object_has_iomem(obj))
return ERR_PTR(-ENXIO);
assert_object_held(obj);
@@ -374,6 +373,34 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
}
GEM_BUG_ON(!i915_gem_object_has_pages(obj));
+ /*
+ * For discrete our CPU mappings needs to be consistent in order to
+ * function correctly on !x86. When mapping things through TTM, we use
+ * the same rules to determine the caching type.
+ *
+ * The caching rules, starting from DG1:
+ *
+ * - If the object can be placed in device local-memory, then the
+ * pages should be allocated and mapped as write-combined only.
+ *
+ * - Everything else is always allocated and mapped as write-back,
+ * with the guarantee that everything is also coherent with the
+ * GPU.
+ *
+ * Internal users of lmem are already expected to get this right, so no
+ * fudging needed there.
+ */
+ if (i915_gem_object_placement_possible(obj, INTEL_MEMORY_LOCAL)) {
+ if (type != I915_MAP_WC && !obj->mm.n_placements) {
+ ptr = ERR_PTR(-ENODEV);
+ goto err_unpin;
+ }
+
+ type = I915_MAP_WC;
+ } else if (IS_DGFX(to_i915(obj->base.dev))) {
+ type = I915_MAP_WB;
+ }
+
ptr = page_unpack_bits(obj->mm.mapping, &has_type);
if (ptr && has_type != type) {
if (pinned) {
@@ -467,9 +494,8 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
struct i915_gem_object_page_iter *iter,
unsigned int n,
unsigned int *offset,
- bool allow_alloc)
+ bool dma)
{
- const bool dma = iter == &obj->mm.get_dma_page;
struct scatterlist *sg;
unsigned int idx, count;
@@ -490,9 +516,6 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
if (n < READ_ONCE(iter->sg_idx))
goto lookup;
- if (!allow_alloc)
- goto manual_lookup;
-
mutex_lock(&iter->lock);
/* We prefer to reuse the last sg so that repeated lookup of this
@@ -542,16 +565,7 @@ scan:
if (unlikely(n < idx)) /* insertion completed by another thread */
goto lookup;
- goto manual_walk;
-
-manual_lookup:
- idx = 0;
- sg = obj->mm.pages->sgl;
- count = __sg_page_count(sg);
-
-manual_walk:
- /*
- * In case we failed to insert the entry into the radixtree, we need
+ /* In case we failed to insert the entry into the radixtree, we need
* to look beyond the current sg.
*/
while (idx + count <= n) {
@@ -598,7 +612,7 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
GEM_BUG_ON(!i915_gem_object_has_struct_page(obj));
- sg = i915_gem_object_get_sg(obj, n, &offset, true);
+ sg = i915_gem_object_get_sg(obj, n, &offset);
return nth_page(sg_page(sg), offset);
}
@@ -624,7 +638,7 @@ i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
struct scatterlist *sg;
unsigned int offset;
- sg = i915_gem_object_get_sg_dma(obj, n, &offset, true);
+ sg = i915_gem_object_get_sg_dma(obj, n, &offset);
if (len)
*len = sg_dma_len(sg) - (offset << PAGE_SHIFT);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
index be72ad0634ba..7986612f48fa 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
@@ -76,7 +76,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
/* We're no longer struct page backed */
- obj->flags &= ~I915_BO_ALLOC_STRUCT_PAGE;
+ obj->mem_flags &= ~I915_BO_FLAG_STRUCT_PAGE;
__i915_gem_object_set_pages(obj, st, sg->length);
return 0;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c
index f25e6646c5b7..1f557b2178ed 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c
@@ -13,16 +13,8 @@ void i915_gem_object_init_memory_region(struct drm_i915_gem_object *obj,
{
obj->mm.region = intel_memory_region_get(mem);
- if (obj->base.size <= mem->min_page_size)
- obj->flags |= I915_BO_ALLOC_CONTIGUOUS;
-
mutex_lock(&mem->objects.lock);
-
- if (obj->flags & I915_BO_ALLOC_VOLATILE)
- list_add(&obj->mm.region_link, &mem->objects.purgeable);
- else
- list_add(&obj->mm.region_link, &mem->objects.list);
-
+ list_add(&obj->mm.region_link, &mem->objects.list);
mutex_unlock(&mem->objects.lock);
}
@@ -40,9 +32,11 @@ void i915_gem_object_release_memory_region(struct drm_i915_gem_object *obj)
struct drm_i915_gem_object *
i915_gem_object_create_region(struct intel_memory_region *mem,
resource_size_t size,
+ resource_size_t page_size,
unsigned int flags)
{
struct drm_i915_gem_object *obj;
+ resource_size_t default_page_size;
int err;
/*
@@ -56,7 +50,14 @@ i915_gem_object_create_region(struct intel_memory_region *mem,
if (!mem)
return ERR_PTR(-ENODEV);
- size = round_up(size, mem->min_page_size);
+ default_page_size = mem->min_page_size;
+ if (page_size)
+ default_page_size = page_size;
+
+ GEM_BUG_ON(!is_power_of_2_u64(default_page_size));
+ GEM_BUG_ON(default_page_size < PAGE_SIZE);
+
+ size = round_up(size, default_page_size);
GEM_BUG_ON(!size);
GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_MIN_ALIGNMENT));
@@ -68,7 +69,7 @@ i915_gem_object_create_region(struct intel_memory_region *mem,
if (!obj)
return ERR_PTR(-ENOMEM);
- err = mem->ops->init_object(mem, obj, size, flags);
+ err = mem->ops->init_object(mem, obj, size, page_size, flags);
if (err)
goto err_object_free;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.h b/drivers/gpu/drm/i915/gem/i915_gem_region.h
index 84fcb3297400..1008e580a89a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.h
@@ -19,6 +19,7 @@ void i915_gem_object_release_memory_region(struct drm_i915_gem_object *obj);
struct drm_i915_gem_object *
i915_gem_object_create_region(struct intel_memory_region *mem,
resource_size_t size,
+ resource_size_t page_size,
unsigned int flags);
#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index 5d16c4462fda..11f072193f3b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -182,6 +182,24 @@ rebuild_st:
if (i915_gem_object_needs_bit17_swizzle(obj))
i915_gem_object_do_bit_17_swizzle(obj, st);
+ /*
+ * EHL and JSL add the 'Bypass LLC' MOCS entry, which should make it
+ * possible for userspace to bypass the GTT caching bits set by the
+ * kernel, as per the given object cache_level. This is troublesome
+ * since the heavy flush we apply when first gathering the pages is
+ * skipped if the kernel thinks the object is coherent with the GPU. As
+ * a result it might be possible to bypass the cache and read the
+ * contents of the page directly, which could be stale data. If it's
+ * just a case of userspace shooting themselves in the foot then so be
+ * it, but since i915 takes the stance of always zeroing memory before
+ * handing it to userspace, we need to prevent this.
+ *
+ * By setting cache_dirty here we make the clflush in set_pages
+ * unconditional on such platforms.
+ */
+ if (IS_JSL_EHL(i915) && obj->flags & I915_BO_ALLOC_USER)
+ obj->cache_dirty = true;
+
__i915_gem_object_set_pages(obj, st, sg_page_sizes);
return 0;
@@ -302,6 +320,7 @@ void i915_gem_object_put_pages_shmem(struct drm_i915_gem_object *obj, struct sg_
struct pagevec pvec;
struct page *page;
+ GEM_WARN_ON(IS_DGFX(to_i915(obj->base.dev)));
__i915_gem_object_release_shmem(obj, pages, true);
i915_gem_gtt_finish_pages(obj, pages);
@@ -444,7 +463,7 @@ shmem_pread(struct drm_i915_gem_object *obj,
static void shmem_release(struct drm_i915_gem_object *obj)
{
- if (obj->flags & I915_BO_ALLOC_STRUCT_PAGE)
+ if (i915_gem_object_has_struct_page(obj))
i915_gem_object_release_memory_region(obj);
fput(obj->base.filp);
@@ -489,6 +508,7 @@ static int __create_shmem(struct drm_i915_private *i915,
static int shmem_object_init(struct intel_memory_region *mem,
struct drm_i915_gem_object *obj,
resource_size_t size,
+ resource_size_t page_size,
unsigned int flags)
{
static struct lock_class_key lock_class;
@@ -513,9 +533,8 @@ static int shmem_object_init(struct intel_memory_region *mem,
mapping_set_gfp_mask(mapping, mask);
GEM_BUG_ON(!(mapping_gfp_mask(mapping) & __GFP_RECLAIM));
- i915_gem_object_init(obj, &i915_gem_shmem_ops, &lock_class,
- I915_BO_ALLOC_STRUCT_PAGE);
-
+ i915_gem_object_init(obj, &i915_gem_shmem_ops, &lock_class, 0);
+ obj->mem_flags |= I915_BO_FLAG_STRUCT_PAGE;
obj->write_domain = I915_GEM_DOMAIN_CPU;
obj->read_domains = I915_GEM_DOMAIN_CPU;
@@ -548,7 +567,7 @@ i915_gem_object_create_shmem(struct drm_i915_private *i915,
resource_size_t size)
{
return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_SMEM],
- size, 0);
+ size, 0, 0);
}
/* Allocate a new GEM object and fill it with the supplied data */
@@ -561,6 +580,7 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv,
resource_size_t offset;
int err;
+ GEM_WARN_ON(IS_DGFX(dev_priv));
obj = i915_gem_object_create_shmem(dev_priv, round_up(size, PAGE_SIZE));
if (IS_ERR(obj))
return obj;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index b0c3a7dc60d1..ddd37ccb1362 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -447,7 +447,6 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
break;
case 8:
case 9:
- case 10:
if (IS_LP(i915))
chv_get_stolen_reserved(i915, uncore,
&reserved_base, &reserved_size);
@@ -670,6 +669,7 @@ static int __i915_gem_object_create_stolen(struct intel_memory_region *mem,
static int _i915_gem_object_stolen_init(struct intel_memory_region *mem,
struct drm_i915_gem_object *obj,
resource_size_t size,
+ resource_size_t page_size,
unsigned int flags)
{
struct drm_i915_private *i915 = mem->i915;
@@ -708,7 +708,7 @@ struct drm_i915_gem_object *
i915_gem_object_create_stolen(struct drm_i915_private *i915,
resource_size_t size)
{
- return i915_gem_object_create_region(i915->mm.stolen_region, size, 0);
+ return i915_gem_object_create_region(i915->mm.stolen_region, size, 0, 0);
}
static int init_stolen_smem(struct intel_memory_region *mem)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
new file mode 100644
index 000000000000..35eedc14f522
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -0,0 +1,964 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <drm/ttm/ttm_bo_driver.h>
+#include <drm/ttm/ttm_placement.h>
+
+#include "i915_drv.h"
+#include "intel_memory_region.h"
+#include "intel_region_ttm.h"
+
+#include "gem/i915_gem_object.h"
+#include "gem/i915_gem_region.h"
+#include "gem/i915_gem_ttm.h"
+#include "gem/i915_gem_mman.h"
+
+#include "gt/intel_migrate.h"
+#include "gt/intel_engine_pm.h"
+
+#define I915_PL_LMEM0 TTM_PL_PRIV
+#define I915_PL_SYSTEM TTM_PL_SYSTEM
+#define I915_PL_STOLEN TTM_PL_VRAM
+#define I915_PL_GGTT TTM_PL_TT
+
+#define I915_TTM_PRIO_PURGE 0
+#define I915_TTM_PRIO_NO_PAGES 1
+#define I915_TTM_PRIO_HAS_PAGES 2
+
+/*
+ * Size of struct ttm_place vector in on-stack struct ttm_placement allocs
+ */
+#define I915_TTM_MAX_PLACEMENTS INTEL_REGION_UNKNOWN
+
+/**
+ * struct i915_ttm_tt - TTM page vector with additional private information
+ * @ttm: The base TTM page vector.
+ * @dev: The struct device used for dma mapping and unmapping.
+ * @cached_st: The cached scatter-gather table.
+ *
+ * Note that DMA may be going on right up to the point where the page-
+ * vector is unpopulated in delayed destroy. Hence keep the
+ * scatter-gather table mapped and cached up to that point. This is
+ * different from the cached gem object io scatter-gather table which
+ * doesn't have an associated dma mapping.
+ */
+struct i915_ttm_tt {
+ struct ttm_tt ttm;
+ struct device *dev;
+ struct sg_table *cached_st;
+};
+
+static const struct ttm_place sys_placement_flags = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .mem_type = I915_PL_SYSTEM,
+ .flags = 0,
+};
+
+static struct ttm_placement i915_sys_placement = {
+ .num_placement = 1,
+ .placement = &sys_placement_flags,
+ .num_busy_placement = 1,
+ .busy_placement = &sys_placement_flags,
+};
+
+static int i915_ttm_err_to_gem(int err)
+{
+ /* Fastpath */
+ if (likely(!err))
+ return 0;
+
+ switch (err) {
+ case -EBUSY:
+ /*
+ * TTM likes to convert -EDEADLK to -EBUSY, and wants us to
+ * restart the operation, since we don't record the contending
+ * lock. We use -EAGAIN to restart.
+ */
+ return -EAGAIN;
+ case -ENOSPC:
+ /*
+ * Memory type / region is full, and we can't evict.
+ * Except possibly system, that returns -ENOMEM;
+ */
+ return -ENXIO;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+static bool gpu_binds_iomem(struct ttm_resource *mem)
+{
+ return mem->mem_type != TTM_PL_SYSTEM;
+}
+
+static bool cpu_maps_iomem(struct ttm_resource *mem)
+{
+ /* Once / if we support GGTT, this is also false for cached ttm_tts */
+ return mem->mem_type != TTM_PL_SYSTEM;
+}
+
+static enum i915_cache_level
+i915_ttm_cache_level(struct drm_i915_private *i915, struct ttm_resource *res,
+ struct ttm_tt *ttm)
+{
+ return ((HAS_LLC(i915) || HAS_SNOOP(i915)) && !gpu_binds_iomem(res) &&
+ ttm->caching == ttm_cached) ? I915_CACHE_LLC :
+ I915_CACHE_NONE;
+}
+
+static void i915_ttm_adjust_lru(struct drm_i915_gem_object *obj);
+
+static enum ttm_caching
+i915_ttm_select_tt_caching(const struct drm_i915_gem_object *obj)
+{
+ /*
+ * Objects only allowed in system get cached cpu-mappings.
+ * Other objects get WC mapping for now. Even if in system.
+ */
+ if (obj->mm.region->type == INTEL_MEMORY_SYSTEM &&
+ obj->mm.n_placements <= 1)
+ return ttm_cached;
+
+ return ttm_write_combined;
+}
+
+static void
+i915_ttm_place_from_region(const struct intel_memory_region *mr,
+ struct ttm_place *place,
+ unsigned int flags)
+{
+ memset(place, 0, sizeof(*place));
+ place->mem_type = intel_region_to_ttm_type(mr);
+
+ if (flags & I915_BO_ALLOC_CONTIGUOUS)
+ place->flags = TTM_PL_FLAG_CONTIGUOUS;
+}
+
+static void
+i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj,
+ struct ttm_place *requested,
+ struct ttm_place *busy,
+ struct ttm_placement *placement)
+{
+ unsigned int num_allowed = obj->mm.n_placements;
+ unsigned int flags = obj->flags;
+ unsigned int i;
+
+ placement->num_placement = 1;
+ i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] :
+ obj->mm.region, requested, flags);
+
+ /* Cache this on object? */
+ placement->num_busy_placement = num_allowed;
+ for (i = 0; i < placement->num_busy_placement; ++i)
+ i915_ttm_place_from_region(obj->mm.placements[i], busy + i, flags);
+
+ if (num_allowed == 0) {
+ *busy = *requested;
+ placement->num_busy_placement = 1;
+ }
+
+ placement->placement = requested;
+ placement->busy_placement = busy;
+}
+
+static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo,
+ uint32_t page_flags)
+{
+ struct ttm_resource_manager *man =
+ ttm_manager_type(bo->bdev, bo->resource->mem_type);
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+ struct i915_ttm_tt *i915_tt;
+ int ret;
+
+ i915_tt = kzalloc(sizeof(*i915_tt), GFP_KERNEL);
+ if (!i915_tt)
+ return NULL;
+
+ if (obj->flags & I915_BO_ALLOC_CPU_CLEAR &&
+ man->use_tt)
+ page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC;
+
+ ret = ttm_tt_init(&i915_tt->ttm, bo, page_flags,
+ i915_ttm_select_tt_caching(obj));
+ if (ret) {
+ kfree(i915_tt);
+ return NULL;
+ }
+
+ i915_tt->dev = obj->base.dev->dev;
+
+ return &i915_tt->ttm;
+}
+
+static void i915_ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm)
+{
+ struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
+
+ if (i915_tt->cached_st) {
+ dma_unmap_sgtable(i915_tt->dev, i915_tt->cached_st,
+ DMA_BIDIRECTIONAL, 0);
+ sg_free_table(i915_tt->cached_st);
+ kfree(i915_tt->cached_st);
+ i915_tt->cached_st = NULL;
+ }
+ ttm_pool_free(&bdev->pool, ttm);
+}
+
+static void i915_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
+{
+ struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
+
+ ttm_tt_destroy_common(bdev, ttm);
+ ttm_tt_fini(ttm);
+ kfree(i915_tt);
+}
+
+static bool i915_ttm_eviction_valuable(struct ttm_buffer_object *bo,
+ const struct ttm_place *place)
+{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+
+ /* Will do for now. Our pinned objects are still on TTM's LRU lists */
+ return i915_gem_object_evictable(obj);
+}
+
+static void i915_ttm_evict_flags(struct ttm_buffer_object *bo,
+ struct ttm_placement *placement)
+{
+ *placement = i915_sys_placement;
+}
+
+static int i915_ttm_move_notify(struct ttm_buffer_object *bo)
+{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+ int ret;
+
+ ret = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE);
+ if (ret)
+ return ret;
+
+ ret = __i915_gem_object_put_pages(obj);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void i915_ttm_free_cached_io_st(struct drm_i915_gem_object *obj)
+{
+ struct radix_tree_iter iter;
+ void __rcu **slot;
+
+ if (!obj->ttm.cached_io_st)
+ return;
+
+ rcu_read_lock();
+ radix_tree_for_each_slot(slot, &obj->ttm.get_io_page.radix, &iter, 0)
+ radix_tree_delete(&obj->ttm.get_io_page.radix, iter.index);
+ rcu_read_unlock();
+
+ sg_free_table(obj->ttm.cached_io_st);
+ kfree(obj->ttm.cached_io_st);
+ obj->ttm.cached_io_st = NULL;
+}
+
+static void
+i915_ttm_adjust_domains_after_move(struct drm_i915_gem_object *obj)
+{
+ struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
+
+ if (cpu_maps_iomem(bo->resource) || bo->ttm->caching != ttm_cached) {
+ obj->write_domain = I915_GEM_DOMAIN_WC;
+ obj->read_domains = I915_GEM_DOMAIN_WC;
+ } else {
+ obj->write_domain = I915_GEM_DOMAIN_CPU;
+ obj->read_domains = I915_GEM_DOMAIN_CPU;
+ }
+}
+
+static void i915_ttm_adjust_gem_after_move(struct drm_i915_gem_object *obj)
+{
+ struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
+ unsigned int cache_level;
+ unsigned int i;
+
+ /*
+ * If object was moved to an allowable region, update the object
+ * region to consider it migrated. Note that if it's currently not
+ * in an allowable region, it's evicted and we don't update the
+ * object region.
+ */
+ if (intel_region_to_ttm_type(obj->mm.region) != bo->resource->mem_type) {
+ for (i = 0; i < obj->mm.n_placements; ++i) {
+ struct intel_memory_region *mr = obj->mm.placements[i];
+
+ if (intel_region_to_ttm_type(mr) == bo->resource->mem_type &&
+ mr != obj->mm.region) {
+ i915_gem_object_release_memory_region(obj);
+ i915_gem_object_init_memory_region(obj, mr);
+ break;
+ }
+ }
+ }
+
+ obj->mem_flags &= ~(I915_BO_FLAG_STRUCT_PAGE | I915_BO_FLAG_IOMEM);
+
+ obj->mem_flags |= cpu_maps_iomem(bo->resource) ? I915_BO_FLAG_IOMEM :
+ I915_BO_FLAG_STRUCT_PAGE;
+
+ cache_level = i915_ttm_cache_level(to_i915(bo->base.dev), bo->resource,
+ bo->ttm);
+ i915_gem_object_set_cache_coherency(obj, cache_level);
+}
+
+static void i915_ttm_purge(struct drm_i915_gem_object *obj)
+{
+ struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
+ struct ttm_operation_ctx ctx = {
+ .interruptible = true,
+ .no_wait_gpu = false,
+ };
+ struct ttm_placement place = {};
+ int ret;
+
+ if (obj->mm.madv == __I915_MADV_PURGED)
+ return;
+
+ /* TTM's purge interface. Note that we might be reentering. */
+ ret = ttm_bo_validate(bo, &place, &ctx);
+ if (!ret) {
+ obj->write_domain = 0;
+ obj->read_domains = 0;
+ i915_ttm_adjust_gem_after_move(obj);
+ i915_ttm_free_cached_io_st(obj);
+ obj->mm.madv = __I915_MADV_PURGED;
+ }
+}
+
+static void i915_ttm_swap_notify(struct ttm_buffer_object *bo)
+{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+ int ret = i915_ttm_move_notify(bo);
+
+ GEM_WARN_ON(ret);
+ GEM_WARN_ON(obj->ttm.cached_io_st);
+ if (!ret && obj->mm.madv != I915_MADV_WILLNEED)
+ i915_ttm_purge(obj);
+}
+
+static void i915_ttm_delete_mem_notify(struct ttm_buffer_object *bo)
+{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+
+ if (likely(obj)) {
+ /* This releases all gem object bindings to the backend. */
+ i915_ttm_free_cached_io_st(obj);
+ __i915_gem_free_object(obj);
+ }
+}
+
+static struct intel_memory_region *
+i915_ttm_region(struct ttm_device *bdev, int ttm_mem_type)
+{
+ struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev);
+
+ /* There's some room for optimization here... */
+ GEM_BUG_ON(ttm_mem_type != I915_PL_SYSTEM &&
+ ttm_mem_type < I915_PL_LMEM0);
+ if (ttm_mem_type == I915_PL_SYSTEM)
+ return intel_memory_region_lookup(i915, INTEL_MEMORY_SYSTEM,
+ 0);
+
+ return intel_memory_region_lookup(i915, INTEL_MEMORY_LOCAL,
+ ttm_mem_type - I915_PL_LMEM0);
+}
+
+static struct sg_table *i915_ttm_tt_get_st(struct ttm_tt *ttm)
+{
+ struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
+ struct sg_table *st;
+ int ret;
+
+ if (i915_tt->cached_st)
+ return i915_tt->cached_st;
+
+ st = kzalloc(sizeof(*st), GFP_KERNEL);
+ if (!st)
+ return ERR_PTR(-ENOMEM);
+
+ ret = sg_alloc_table_from_pages_segment(st,
+ ttm->pages, ttm->num_pages,
+ 0, (unsigned long)ttm->num_pages << PAGE_SHIFT,
+ i915_sg_segment_size(), GFP_KERNEL);
+ if (ret) {
+ kfree(st);
+ return ERR_PTR(ret);
+ }
+
+ ret = dma_map_sgtable(i915_tt->dev, st, DMA_BIDIRECTIONAL, 0);
+ if (ret) {
+ sg_free_table(st);
+ kfree(st);
+ return ERR_PTR(ret);
+ }
+
+ i915_tt->cached_st = st;
+ return st;
+}
+
+static struct sg_table *
+i915_ttm_resource_get_st(struct drm_i915_gem_object *obj,
+ struct ttm_resource *res)
+{
+ struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
+
+ if (!gpu_binds_iomem(res))
+ return i915_ttm_tt_get_st(bo->ttm);
+
+ /*
+ * If CPU mapping differs, we need to add the ttm_tt pages to
+ * the resulting st. Might make sense for GGTT.
+ */
+ GEM_WARN_ON(!cpu_maps_iomem(res));
+ return intel_region_ttm_resource_to_st(obj->mm.region, res);
+}
+
+static int i915_ttm_accel_move(struct ttm_buffer_object *bo,
+ struct ttm_resource *dst_mem,
+ struct sg_table *dst_st)
+{
+ struct drm_i915_private *i915 = container_of(bo->bdev, typeof(*i915),
+ bdev);
+ struct ttm_resource_manager *src_man =
+ ttm_manager_type(bo->bdev, bo->resource->mem_type);
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+ struct sg_table *src_st;
+ struct i915_request *rq;
+ struct ttm_tt *ttm = bo->ttm;
+ enum i915_cache_level src_level, dst_level;
+ int ret;
+
+ if (!i915->gt.migrate.context)
+ return -EINVAL;
+
+ dst_level = i915_ttm_cache_level(i915, dst_mem, ttm);
+ if (!ttm || !ttm_tt_is_populated(ttm)) {
+ if (bo->type == ttm_bo_type_kernel)
+ return -EINVAL;
+
+ if (ttm && !(ttm->page_flags & TTM_PAGE_FLAG_ZERO_ALLOC))
+ return 0;
+
+ intel_engine_pm_get(i915->gt.migrate.context->engine);
+ ret = intel_context_migrate_clear(i915->gt.migrate.context, NULL,
+ dst_st->sgl, dst_level,
+ gpu_binds_iomem(dst_mem),
+ 0, &rq);
+
+ if (!ret && rq) {
+ i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT);
+ i915_request_put(rq);
+ }
+ intel_engine_pm_put(i915->gt.migrate.context->engine);
+ } else {
+ src_st = src_man->use_tt ? i915_ttm_tt_get_st(ttm) :
+ obj->ttm.cached_io_st;
+
+ src_level = i915_ttm_cache_level(i915, bo->resource, ttm);
+ intel_engine_pm_get(i915->gt.migrate.context->engine);
+ ret = intel_context_migrate_copy(i915->gt.migrate.context,
+ NULL, src_st->sgl, src_level,
+ gpu_binds_iomem(bo->resource),
+ dst_st->sgl, dst_level,
+ gpu_binds_iomem(dst_mem),
+ &rq);
+ if (!ret && rq) {
+ i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT);
+ i915_request_put(rq);
+ }
+ intel_engine_pm_put(i915->gt.migrate.context->engine);
+ }
+
+ return ret;
+}
+
+static int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
+ struct ttm_operation_ctx *ctx,
+ struct ttm_resource *dst_mem,
+ struct ttm_place *hop)
+{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+ struct ttm_resource_manager *dst_man =
+ ttm_manager_type(bo->bdev, dst_mem->mem_type);
+ struct intel_memory_region *dst_reg, *src_reg;
+ union {
+ struct ttm_kmap_iter_tt tt;
+ struct ttm_kmap_iter_iomap io;
+ } _dst_iter, _src_iter;
+ struct ttm_kmap_iter *dst_iter, *src_iter;
+ struct sg_table *dst_st;
+ int ret;
+
+ dst_reg = i915_ttm_region(bo->bdev, dst_mem->mem_type);
+ src_reg = i915_ttm_region(bo->bdev, bo->resource->mem_type);
+ GEM_BUG_ON(!dst_reg || !src_reg);
+
+ /* Sync for now. We could do the actual copy async. */
+ ret = ttm_bo_wait_ctx(bo, ctx);
+ if (ret)
+ return ret;
+
+ ret = i915_ttm_move_notify(bo);
+ if (ret)
+ return ret;
+
+ if (obj->mm.madv != I915_MADV_WILLNEED) {
+ i915_ttm_purge(obj);
+ ttm_resource_free(bo, &dst_mem);
+ return 0;
+ }
+
+ /* Populate ttm with pages if needed. Typically system memory. */
+ if (bo->ttm && (dst_man->use_tt ||
+ (bo->ttm->page_flags & TTM_PAGE_FLAG_SWAPPED))) {
+ ret = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
+ if (ret)
+ return ret;
+ }
+
+ dst_st = i915_ttm_resource_get_st(obj, dst_mem);
+ if (IS_ERR(dst_st))
+ return PTR_ERR(dst_st);
+
+ ret = i915_ttm_accel_move(bo, dst_mem, dst_st);
+ if (ret) {
+ /* If we start mapping GGTT, we can no longer use man::use_tt here. */
+ dst_iter = !cpu_maps_iomem(dst_mem) ?
+ ttm_kmap_iter_tt_init(&_dst_iter.tt, bo->ttm) :
+ ttm_kmap_iter_iomap_init(&_dst_iter.io, &dst_reg->iomap,
+ dst_st, dst_reg->region.start);
+
+ src_iter = !cpu_maps_iomem(bo->resource) ?
+ ttm_kmap_iter_tt_init(&_src_iter.tt, bo->ttm) :
+ ttm_kmap_iter_iomap_init(&_src_iter.io, &src_reg->iomap,
+ obj->ttm.cached_io_st,
+ src_reg->region.start);
+
+ ttm_move_memcpy(bo, dst_mem->num_pages, dst_iter, src_iter);
+ }
+ /* Below dst_mem becomes bo->resource. */
+ ttm_bo_move_sync_cleanup(bo, dst_mem);
+ i915_ttm_adjust_domains_after_move(obj);
+ i915_ttm_free_cached_io_st(obj);
+
+ if (gpu_binds_iomem(dst_mem) || cpu_maps_iomem(dst_mem)) {
+ obj->ttm.cached_io_st = dst_st;
+ obj->ttm.get_io_page.sg_pos = dst_st->sgl;
+ obj->ttm.get_io_page.sg_idx = 0;
+ }
+
+ i915_ttm_adjust_gem_after_move(obj);
+ return 0;
+}
+
+static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)
+{
+ if (!cpu_maps_iomem(mem))
+ return 0;
+
+ mem->bus.caching = ttm_write_combined;
+ mem->bus.is_iomem = true;
+
+ return 0;
+}
+
+static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
+ unsigned long page_offset)
+{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+ unsigned long base = obj->mm.region->iomap.base - obj->mm.region->region.start;
+ struct scatterlist *sg;
+ unsigned int ofs;
+
+ GEM_WARN_ON(bo->ttm);
+
+ sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs, true);
+
+ return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs;
+}
+
+static struct ttm_device_funcs i915_ttm_bo_driver = {
+ .ttm_tt_create = i915_ttm_tt_create,
+ .ttm_tt_unpopulate = i915_ttm_tt_unpopulate,
+ .ttm_tt_destroy = i915_ttm_tt_destroy,
+ .eviction_valuable = i915_ttm_eviction_valuable,
+ .evict_flags = i915_ttm_evict_flags,
+ .move = i915_ttm_move,
+ .swap_notify = i915_ttm_swap_notify,
+ .delete_mem_notify = i915_ttm_delete_mem_notify,
+ .io_mem_reserve = i915_ttm_io_mem_reserve,
+ .io_mem_pfn = i915_ttm_io_mem_pfn,
+};
+
+/**
+ * i915_ttm_driver - Return a pointer to the TTM device funcs
+ *
+ * Return: Pointer to statically allocated TTM device funcs.
+ */
+struct ttm_device_funcs *i915_ttm_driver(void)
+{
+ return &i915_ttm_bo_driver;
+}
+
+static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
+ struct ttm_placement *placement)
+{
+ struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
+ struct ttm_operation_ctx ctx = {
+ .interruptible = true,
+ .no_wait_gpu = false,
+ };
+ struct sg_table *st;
+ int real_num_busy;
+ int ret;
+
+ /* First try only the requested placement. No eviction. */
+ real_num_busy = fetch_and_zero(&placement->num_busy_placement);
+ ret = ttm_bo_validate(bo, placement, &ctx);
+ if (ret) {
+ ret = i915_ttm_err_to_gem(ret);
+ /*
+ * Anything that wants to restart the operation gets to
+ * do that.
+ */
+ if (ret == -EDEADLK || ret == -EINTR || ret == -ERESTARTSYS ||
+ ret == -EAGAIN)
+ return ret;
+
+ /*
+ * If the initial attempt fails, allow all accepted placements,
+ * evicting if necessary.
+ */
+ placement->num_busy_placement = real_num_busy;
+ ret = ttm_bo_validate(bo, placement, &ctx);
+ if (ret)
+ return i915_ttm_err_to_gem(ret);
+ }
+
+ i915_ttm_adjust_lru(obj);
+ if (bo->ttm && !ttm_tt_is_populated(bo->ttm)) {
+ ret = ttm_tt_populate(bo->bdev, bo->ttm, &ctx);
+ if (ret)
+ return ret;
+
+ i915_ttm_adjust_domains_after_move(obj);
+ i915_ttm_adjust_gem_after_move(obj);
+ }
+
+ if (!i915_gem_object_has_pages(obj)) {
+ /* Object either has a page vector or is an iomem object */
+ st = bo->ttm ? i915_ttm_tt_get_st(bo->ttm) : obj->ttm.cached_io_st;
+ if (IS_ERR(st))
+ return PTR_ERR(st);
+
+ __i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
+ }
+
+ return ret;
+}
+
+static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
+{
+ struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
+ struct ttm_placement placement;
+
+ GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
+
+ /* Move to the requested placement. */
+ i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
+
+ return __i915_ttm_get_pages(obj, &placement);
+}
+
+/**
+ * DOC: Migration vs eviction
+ *
+ * GEM migration may not be the same as TTM migration / eviction. If
+ * the TTM core decides to evict an object it may be evicted to a
+ * TTM memory type that is not in the object's allowable GEM regions, or
+ * in fact theoretically to a TTM memory type that doesn't correspond to
+ * a GEM memory region. In that case the object's GEM region is not
+ * updated, and the data is migrated back to the GEM region at
+ * get_pages time. TTM may however set up CPU ptes to the object even
+ * when it is evicted.
+ * Gem forced migration using the i915_ttm_migrate() op, is allowed even
+ * to regions that are not in the object's list of allowable placements.
+ */
+static int i915_ttm_migrate(struct drm_i915_gem_object *obj,
+ struct intel_memory_region *mr)
+{
+ struct ttm_place requested;
+ struct ttm_placement placement;
+ int ret;
+
+ i915_ttm_place_from_region(mr, &requested, obj->flags);
+ placement.num_placement = 1;
+ placement.num_busy_placement = 1;
+ placement.placement = &requested;
+ placement.busy_placement = &requested;
+
+ ret = __i915_ttm_get_pages(obj, &placement);
+ if (ret)
+ return ret;
+
+ /*
+ * Reinitialize the region bindings. This is primarily
+ * required for objects where the new region is not in
+ * its allowable placements.
+ */
+ if (obj->mm.region != mr) {
+ i915_gem_object_release_memory_region(obj);
+ i915_gem_object_init_memory_region(obj, mr);
+ }
+
+ return 0;
+}
+
+static void i915_ttm_put_pages(struct drm_i915_gem_object *obj,
+ struct sg_table *st)
+{
+ /*
+ * We're currently not called from a shrinker, so put_pages()
+ * typically means the object is about to destroyed, or called
+ * from move_notify(). So just avoid doing much for now.
+ * If the object is not destroyed next, The TTM eviction logic
+ * and shrinkers will move it out if needed.
+ */
+
+ i915_ttm_adjust_lru(obj);
+}
+
+static void i915_ttm_adjust_lru(struct drm_i915_gem_object *obj)
+{
+ struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
+
+ /*
+ * Don't manipulate the TTM LRUs while in TTM bo destruction.
+ * We're called through i915_ttm_delete_mem_notify().
+ */
+ if (!kref_read(&bo->kref))
+ return;
+
+ /*
+ * Put on the correct LRU list depending on the MADV status
+ */
+ spin_lock(&bo->bdev->lru_lock);
+ if (obj->mm.madv != I915_MADV_WILLNEED) {
+ bo->priority = I915_TTM_PRIO_PURGE;
+ } else if (!i915_gem_object_has_pages(obj)) {
+ if (bo->priority < I915_TTM_PRIO_HAS_PAGES)
+ bo->priority = I915_TTM_PRIO_HAS_PAGES;
+ } else {
+ if (bo->priority > I915_TTM_PRIO_NO_PAGES)
+ bo->priority = I915_TTM_PRIO_NO_PAGES;
+ }
+
+ ttm_bo_move_to_lru_tail(bo, bo->resource, NULL);
+ spin_unlock(&bo->bdev->lru_lock);
+}
+
+/*
+ * TTM-backed gem object destruction requires some clarification.
+ * Basically we have two possibilities here. We can either rely on the
+ * i915 delayed destruction and put the TTM object when the object
+ * is idle. This would be detected by TTM which would bypass the
+ * TTM delayed destroy handling. The other approach is to put the TTM
+ * object early and rely on the TTM destroyed handling, and then free
+ * the leftover parts of the GEM object once TTM's destroyed list handling is
+ * complete. For now, we rely on the latter for two reasons:
+ * a) TTM can evict an object even when it's on the delayed destroy list,
+ * which in theory allows for complete eviction.
+ * b) There is work going on in TTM to allow freeing an object even when
+ * it's not idle, and using the TTM destroyed list handling could help us
+ * benefit from that.
+ */
+static void i915_ttm_delayed_free(struct drm_i915_gem_object *obj)
+{
+ if (obj->ttm.created) {
+ ttm_bo_put(i915_gem_to_ttm(obj));
+ } else {
+ __i915_gem_free_object(obj);
+ call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
+ }
+}
+
+static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
+{
+ struct vm_area_struct *area = vmf->vma;
+ struct drm_i915_gem_object *obj =
+ i915_ttm_to_gem(area->vm_private_data);
+
+ /* Sanity check that we allow writing into this object */
+ if (unlikely(i915_gem_object_is_readonly(obj) &&
+ area->vm_flags & VM_WRITE))
+ return VM_FAULT_SIGBUS;
+
+ return ttm_bo_vm_fault(vmf);
+}
+
+static int
+vm_access_ttm(struct vm_area_struct *area, unsigned long addr,
+ void *buf, int len, int write)
+{
+ struct drm_i915_gem_object *obj =
+ i915_ttm_to_gem(area->vm_private_data);
+
+ if (i915_gem_object_is_readonly(obj) && write)
+ return -EACCES;
+
+ return ttm_bo_vm_access(area, addr, buf, len, write);
+}
+
+static void ttm_vm_open(struct vm_area_struct *vma)
+{
+ struct drm_i915_gem_object *obj =
+ i915_ttm_to_gem(vma->vm_private_data);
+
+ GEM_BUG_ON(!obj);
+ i915_gem_object_get(obj);
+}
+
+static void ttm_vm_close(struct vm_area_struct *vma)
+{
+ struct drm_i915_gem_object *obj =
+ i915_ttm_to_gem(vma->vm_private_data);
+
+ GEM_BUG_ON(!obj);
+ i915_gem_object_put(obj);
+}
+
+static const struct vm_operations_struct vm_ops_ttm = {
+ .fault = vm_fault_ttm,
+ .access = vm_access_ttm,
+ .open = ttm_vm_open,
+ .close = ttm_vm_close,
+};
+
+static u64 i915_ttm_mmap_offset(struct drm_i915_gem_object *obj)
+{
+ /* The ttm_bo must be allocated with I915_BO_ALLOC_USER */
+ GEM_BUG_ON(!drm_mm_node_allocated(&obj->base.vma_node.vm_node));
+
+ return drm_vma_node_offset_addr(&obj->base.vma_node);
+}
+
+static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = {
+ .name = "i915_gem_object_ttm",
+
+ .get_pages = i915_ttm_get_pages,
+ .put_pages = i915_ttm_put_pages,
+ .truncate = i915_ttm_purge,
+ .adjust_lru = i915_ttm_adjust_lru,
+ .delayed_free = i915_ttm_delayed_free,
+ .migrate = i915_ttm_migrate,
+ .mmap_offset = i915_ttm_mmap_offset,
+ .mmap_ops = &vm_ops_ttm,
+};
+
+void i915_ttm_bo_destroy(struct ttm_buffer_object *bo)
+{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+
+ i915_gem_object_release_memory_region(obj);
+ mutex_destroy(&obj->ttm.get_io_page.lock);
+ if (obj->ttm.created)
+ call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
+}
+
+/**
+ * __i915_gem_ttm_object_init - Initialize a ttm-backed i915 gem object
+ * @mem: The initial memory region for the object.
+ * @obj: The gem object.
+ * @size: Object size in bytes.
+ * @flags: gem object flags.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
+ struct drm_i915_gem_object *obj,
+ resource_size_t size,
+ resource_size_t page_size,
+ unsigned int flags)
+{
+ static struct lock_class_key lock_class;
+ struct drm_i915_private *i915 = mem->i915;
+ struct ttm_operation_ctx ctx = {
+ .interruptible = true,
+ .no_wait_gpu = false,
+ };
+ enum ttm_bo_type bo_type;
+ int ret;
+
+ drm_gem_private_object_init(&i915->drm, &obj->base, size);
+ i915_gem_object_init(obj, &i915_gem_ttm_obj_ops, &lock_class, flags);
+ i915_gem_object_init_memory_region(obj, mem);
+ i915_gem_object_make_unshrinkable(obj);
+ INIT_RADIX_TREE(&obj->ttm.get_io_page.radix, GFP_KERNEL | __GFP_NOWARN);
+ mutex_init(&obj->ttm.get_io_page.lock);
+ bo_type = (obj->flags & I915_BO_ALLOC_USER) ? ttm_bo_type_device :
+ ttm_bo_type_kernel;
+
+ obj->base.vma_node.driver_private = i915_gem_to_ttm(obj);
+
+ /* Forcing the page size is kernel internal only */
+ GEM_BUG_ON(page_size && obj->mm.n_placements);
+
+ /*
+ * If this function fails, it will call the destructor, but
+ * our caller still owns the object. So no freeing in the
+ * destructor until obj->ttm.created is true.
+ * Similarly, in delayed_destroy, we can't call ttm_bo_put()
+ * until successful initialization.
+ */
+ ret = ttm_bo_init_reserved(&i915->bdev, i915_gem_to_ttm(obj), size,
+ bo_type, &i915_sys_placement,
+ page_size >> PAGE_SHIFT,
+ &ctx, NULL, NULL, i915_ttm_bo_destroy);
+ if (ret)
+ return i915_ttm_err_to_gem(ret);
+
+ obj->ttm.created = true;
+ i915_ttm_adjust_domains_after_move(obj);
+ i915_ttm_adjust_gem_after_move(obj);
+ i915_gem_object_unlock(obj);
+
+ return 0;
+}
+
+static const struct intel_memory_region_ops ttm_system_region_ops = {
+ .init_object = __i915_gem_ttm_object_init,
+};
+
+struct intel_memory_region *
+i915_gem_ttm_system_setup(struct drm_i915_private *i915,
+ u16 type, u16 instance)
+{
+ struct intel_memory_region *mr;
+
+ mr = intel_memory_region_create(i915, 0,
+ totalram_pages() << PAGE_SHIFT,
+ PAGE_SIZE, 0,
+ type, instance,
+ &ttm_system_region_ops);
+ if (IS_ERR(mr))
+ return mr;
+
+ intel_memory_region_set_name(mr, "system-ttm");
+ return mr;
+}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
new file mode 100644
index 000000000000..40927f67b6d9
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+#ifndef _I915_GEM_TTM_H_
+#define _I915_GEM_TTM_H_
+
+#include "gem/i915_gem_object_types.h"
+
+/**
+ * i915_gem_to_ttm - Convert a struct drm_i915_gem_object to a
+ * struct ttm_buffer_object.
+ * @obj: Pointer to the gem object.
+ *
+ * Return: Pointer to the embedded struct ttm_buffer_object.
+ */
+static inline struct ttm_buffer_object *
+i915_gem_to_ttm(struct drm_i915_gem_object *obj)
+{
+ return &obj->__do_not_access;
+}
+
+/*
+ * i915 ttm gem object destructor. Internal use only.
+ */
+void i915_ttm_bo_destroy(struct ttm_buffer_object *bo);
+
+/**
+ * i915_ttm_to_gem - Convert a struct ttm_buffer_object to an embedding
+ * struct drm_i915_gem_object.
+ *
+ * Return: Pointer to the embedding struct ttm_buffer_object, or NULL
+ * if the object was not an i915 ttm object.
+ */
+static inline struct drm_i915_gem_object *
+i915_ttm_to_gem(struct ttm_buffer_object *bo)
+{
+ if (GEM_WARN_ON(bo->destroy != i915_ttm_bo_destroy))
+ return NULL;
+
+ return container_of(bo, struct drm_i915_gem_object, __do_not_access);
+}
+
+int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
+ struct drm_i915_gem_object *obj,
+ resource_size_t size,
+ resource_size_t page_size,
+ unsigned int flags);
+#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index 7487bab11f0b..8ea0fa665e53 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -67,11 +67,11 @@ static bool i915_gem_userptr_invalidate(struct mmu_interval_notifier *mni,
if (!mmu_notifier_range_blockable(range))
return false;
- spin_lock(&i915->mm.notifier_lock);
+ write_lock(&i915->mm.notifier_lock);
mmu_interval_set_seq(mni, cur_seq);
- spin_unlock(&i915->mm.notifier_lock);
+ write_unlock(&i915->mm.notifier_lock);
/*
* We don't wait when the process is exiting. This is valid
@@ -107,16 +107,15 @@ i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj)
static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
{
- struct drm_i915_private *i915 = to_i915(obj->base.dev);
struct page **pvec = NULL;
- spin_lock(&i915->mm.notifier_lock);
+ assert_object_held_shared(obj);
+
if (!--obj->userptr.page_ref) {
pvec = obj->userptr.pvec;
obj->userptr.pvec = NULL;
}
GEM_BUG_ON(obj->userptr.page_ref < 0);
- spin_unlock(&i915->mm.notifier_lock);
if (pvec) {
const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
@@ -128,12 +127,10 @@ static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
{
- struct drm_i915_private *i915 = to_i915(obj->base.dev);
const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
unsigned int max_segment = i915_sg_segment_size();
struct sg_table *st;
unsigned int sg_page_sizes;
- struct scatterlist *sg;
struct page **pvec;
int ret;
@@ -141,25 +138,20 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
if (!st)
return -ENOMEM;
- spin_lock(&i915->mm.notifier_lock);
- if (GEM_WARN_ON(!obj->userptr.page_ref)) {
- spin_unlock(&i915->mm.notifier_lock);
- ret = -EFAULT;
+ if (!obj->userptr.page_ref) {
+ ret = -EAGAIN;
goto err_free;
}
obj->userptr.page_ref++;
pvec = obj->userptr.pvec;
- spin_unlock(&i915->mm.notifier_lock);
alloc_table:
- sg = __sg_alloc_table_from_pages(st, pvec, num_pages, 0,
- num_pages << PAGE_SHIFT, max_segment,
- NULL, 0, GFP_KERNEL);
- if (IS_ERR(sg)) {
- ret = PTR_ERR(sg);
+ ret = sg_alloc_table_from_pages_segment(st, pvec, num_pages, 0,
+ num_pages << PAGE_SHIFT,
+ max_segment, GFP_KERNEL);
+ if (ret)
goto err;
- }
ret = i915_gem_gtt_prepare_pages(obj, st);
if (ret) {
@@ -241,7 +233,7 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
i915_gem_object_userptr_drop_ref(obj);
}
-static int i915_gem_object_userptr_unbind(struct drm_i915_gem_object *obj, bool get_pages)
+static int i915_gem_object_userptr_unbind(struct drm_i915_gem_object *obj)
{
struct sg_table *pages;
int err;
@@ -259,15 +251,11 @@ static int i915_gem_object_userptr_unbind(struct drm_i915_gem_object *obj, bool
if (!IS_ERR_OR_NULL(pages))
i915_gem_userptr_put_pages(obj, pages);
- if (get_pages)
- err = ____i915_gem_object_get_pages(obj);
-
return err;
}
int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj)
{
- struct drm_i915_private *i915 = to_i915(obj->base.dev);
const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
struct page **pvec;
unsigned int gup_flags = 0;
@@ -277,39 +265,22 @@ int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj)
if (obj->userptr.notifier.mm != current->mm)
return -EFAULT;
+ notifier_seq = mmu_interval_read_begin(&obj->userptr.notifier);
+
ret = i915_gem_object_lock_interruptible(obj, NULL);
if (ret)
return ret;
- /* optimistically try to preserve current pages while unlocked */
- if (i915_gem_object_has_pages(obj) &&
- !mmu_interval_check_retry(&obj->userptr.notifier,
- obj->userptr.notifier_seq)) {
- spin_lock(&i915->mm.notifier_lock);
- if (obj->userptr.pvec &&
- !mmu_interval_read_retry(&obj->userptr.notifier,
- obj->userptr.notifier_seq)) {
- obj->userptr.page_ref++;
-
- /* We can keep using the current binding, this is the fastpath */
- ret = 1;
- }
- spin_unlock(&i915->mm.notifier_lock);
+ if (notifier_seq == obj->userptr.notifier_seq && obj->userptr.pvec) {
+ i915_gem_object_unlock(obj);
+ return 0;
}
- if (!ret) {
- /* Make sure userptr is unbound for next attempt, so we don't use stale pages. */
- ret = i915_gem_object_userptr_unbind(obj, false);
- }
+ ret = i915_gem_object_userptr_unbind(obj);
i915_gem_object_unlock(obj);
- if (ret < 0)
+ if (ret)
return ret;
- if (ret > 0)
- return 0;
-
- notifier_seq = mmu_interval_read_begin(&obj->userptr.notifier);
-
pvec = kvmalloc_array(num_pages, sizeof(struct page *), GFP_KERNEL);
if (!pvec)
return -ENOMEM;
@@ -329,7 +300,9 @@ int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj)
}
ret = 0;
- spin_lock(&i915->mm.notifier_lock);
+ ret = i915_gem_object_lock_interruptible(obj, NULL);
+ if (ret)
+ goto out;
if (mmu_interval_read_retry(&obj->userptr.notifier,
!obj->userptr.page_ref ? notifier_seq :
@@ -341,12 +314,14 @@ int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj)
if (!obj->userptr.page_ref++) {
obj->userptr.pvec = pvec;
obj->userptr.notifier_seq = notifier_seq;
-
pvec = NULL;
+ ret = ____i915_gem_object_get_pages(obj);
}
+ obj->userptr.page_ref--;
+
out_unlock:
- spin_unlock(&i915->mm.notifier_lock);
+ i915_gem_object_unlock(obj);
out:
if (pvec) {
@@ -369,11 +344,6 @@ int i915_gem_object_userptr_submit_done(struct drm_i915_gem_object *obj)
return 0;
}
-void i915_gem_object_userptr_submit_fini(struct drm_i915_gem_object *obj)
-{
- i915_gem_object_userptr_drop_ref(obj);
-}
-
int i915_gem_object_userptr_validate(struct drm_i915_gem_object *obj)
{
int err;
@@ -396,7 +366,6 @@ int i915_gem_object_userptr_validate(struct drm_i915_gem_object *obj)
i915_gem_object_unlock(obj);
}
- i915_gem_object_userptr_submit_fini(obj);
return err;
}
@@ -450,6 +419,34 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
#endif
+static int
+probe_range(struct mm_struct *mm, unsigned long addr, unsigned long len)
+{
+ const unsigned long end = addr + len;
+ struct vm_area_struct *vma;
+ int ret = -EFAULT;
+
+ mmap_read_lock(mm);
+ for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
+ /* Check for holes, note that we also update the addr below */
+ if (vma->vm_start > addr)
+ break;
+
+ if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
+ break;
+
+ if (vma->vm_end >= end) {
+ ret = 0;
+ break;
+ }
+
+ addr = vma->vm_end;
+ }
+ mmap_read_unlock(mm);
+
+ return ret;
+}
+
/*
* Creates a new mm object that wraps some normal memory from the process
* context - user memory.
@@ -505,7 +502,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
}
if (args->flags & ~(I915_USERPTR_READ_ONLY |
- I915_USERPTR_UNSYNCHRONIZED))
+ I915_USERPTR_UNSYNCHRONIZED |
+ I915_USERPTR_PROBE))
return -EINVAL;
if (i915_gem_object_size_2big(args->user_size))
@@ -532,14 +530,24 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
return -ENODEV;
}
+ if (args->flags & I915_USERPTR_PROBE) {
+ /*
+ * Check that the range pointed to represents real struct
+ * pages and not iomappings (at this moment in time!)
+ */
+ ret = probe_range(current->mm, args->user_ptr, args->user_size);
+ if (ret)
+ return ret;
+ }
+
#ifdef CONFIG_MMU_NOTIFIER
obj = i915_gem_object_alloc();
if (obj == NULL)
return -ENOMEM;
drm_gem_private_object_init(dev, &obj->base, args->user_size);
- i915_gem_object_init(obj, &i915_gem_userptr_ops, &lock_class,
- I915_BO_ALLOC_STRUCT_PAGE);
+ i915_gem_object_init(obj, &i915_gem_userptr_ops, &lock_class, 0);
+ obj->mem_flags = I915_BO_FLAG_STRUCT_PAGE;
obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->write_domain = I915_GEM_DOMAIN_CPU;
i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC);
@@ -572,7 +580,7 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
int i915_gem_init_userptr(struct drm_i915_private *dev_priv)
{
#ifdef CONFIG_MMU_NOTIFIER
- spin_lock_init(&dev_priv->mm.notifier_lock);
+ rwlock_init(&dev_priv->mm.notifier_lock);
#endif
return 0;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
index 1e97520c62b2..f909aaa09d9c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c
@@ -104,8 +104,8 @@ static void fence_set_priority(struct dma_fence *fence,
engine = rq->engine;
rcu_read_lock(); /* RCU serialisation for set-wedged protection */
- if (engine->schedule)
- engine->schedule(rq, attr);
+ if (engine->sched_engine->schedule)
+ engine->sched_engine->schedule(rq, attr);
rcu_read_unlock();
}
@@ -290,3 +290,22 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
i915_gem_object_put(obj);
return ret;
}
+
+/**
+ * i915_gem_object_wait_migration - Sync an accelerated migration operation
+ * @obj: The migrating object.
+ * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
+ *
+ * Wait for any pending async migration operation on the object,
+ * whether it's explicitly (i915_gem_object_migrate()) or implicitly
+ * (swapin, initial clearing) initiated.
+ *
+ * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
+ */
+int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
+ unsigned int flags)
+{
+ might_sleep();
+ /* NOP for now. */
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c
index 0c8ecfdf5405..f963b8e1e37b 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c
@@ -114,8 +114,8 @@ huge_gem_object(struct drm_i915_private *i915,
return ERR_PTR(-ENOMEM);
drm_gem_private_object_init(&i915->drm, &obj->base, dma_size);
- i915_gem_object_init(obj, &huge_ops, &lock_class,
- I915_BO_ALLOC_STRUCT_PAGE);
+ i915_gem_object_init(obj, &huge_ops, &lock_class, 0);
+ obj->mem_flags |= I915_BO_FLAG_STRUCT_PAGE;
obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->write_domain = I915_GEM_DOMAIN_CPU;
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index dadd485bc52f..a094f3ce1a90 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -167,9 +167,8 @@ huge_pages_object(struct drm_i915_private *i915,
return ERR_PTR(-ENOMEM);
drm_gem_private_object_init(&i915->drm, &obj->base, size);
- i915_gem_object_init(obj, &huge_page_ops, &lock_class,
- I915_BO_ALLOC_STRUCT_PAGE);
-
+ i915_gem_object_init(obj, &huge_page_ops, &lock_class, 0);
+ obj->mem_flags |= I915_BO_FLAG_STRUCT_PAGE;
i915_gem_object_set_volatile(obj);
obj->write_domain = I915_GEM_DOMAIN_CPU;
@@ -497,7 +496,8 @@ static int igt_mock_memory_region_huge_pages(void *arg)
int i;
for (i = 0; i < ARRAY_SIZE(flags); ++i) {
- obj = i915_gem_object_create_region(mem, page_size,
+ obj = i915_gem_object_create_region(mem,
+ page_size, page_size,
flags[i]);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c
index 176e6b22f87f..ecbcbb86ae1e 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c
@@ -5,6 +5,7 @@
#include "i915_selftest.h"
+#include "gt/intel_context.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_gt.h"
#include "gt/intel_gpu_commands.h"
@@ -16,118 +17,6 @@
#include "huge_gem_object.h"
#include "mock_context.h"
-static int __igt_client_fill(struct intel_engine_cs *engine)
-{
- struct intel_context *ce = engine->kernel_context;
- struct drm_i915_gem_object *obj;
- I915_RND_STATE(prng);
- IGT_TIMEOUT(end);
- u32 *vaddr;
- int err = 0;
-
- intel_engine_pm_get(engine);
- do {
- const u32 max_block_size = S16_MAX * PAGE_SIZE;
- u32 sz = min_t(u64, ce->vm->total >> 4, prandom_u32_state(&prng));
- u32 phys_sz = sz % (max_block_size + 1);
- u32 val = prandom_u32_state(&prng);
- u32 i;
-
- sz = round_up(sz, PAGE_SIZE);
- phys_sz = round_up(phys_sz, PAGE_SIZE);
-
- pr_debug("%s with phys_sz= %x, sz=%x, val=%x\n", __func__,
- phys_sz, sz, val);
-
- obj = huge_gem_object(engine->i915, phys_sz, sz);
- if (IS_ERR(obj)) {
- err = PTR_ERR(obj);
- goto err_flush;
- }
-
- vaddr = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WB);
- if (IS_ERR(vaddr)) {
- err = PTR_ERR(vaddr);
- goto err_put;
- }
-
- /*
- * XXX: The goal is move this to get_pages, so try to dirty the
- * CPU cache first to check that we do the required clflush
- * before scheduling the blt for !llc platforms. This matches
- * some version of reality where at get_pages the pages
- * themselves may not yet be coherent with the GPU(swap-in). If
- * we are missing the flush then we should see the stale cache
- * values after we do the set_to_cpu_domain and pick it up as a
- * test failure.
- */
- memset32(vaddr, val ^ 0xdeadbeaf,
- huge_gem_object_phys_size(obj) / sizeof(u32));
-
- if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE))
- obj->cache_dirty = true;
-
- err = i915_gem_schedule_fill_pages_blt(obj, ce, obj->mm.pages,
- &obj->mm.page_sizes,
- val);
- if (err)
- goto err_unpin;
-
- i915_gem_object_lock(obj, NULL);
- err = i915_gem_object_set_to_cpu_domain(obj, false);
- i915_gem_object_unlock(obj);
- if (err)
- goto err_unpin;
-
- for (i = 0; i < huge_gem_object_phys_size(obj) / sizeof(u32); ++i) {
- if (vaddr[i] != val) {
- pr_err("vaddr[%u]=%x, expected=%x\n", i,
- vaddr[i], val);
- err = -EINVAL;
- goto err_unpin;
- }
- }
-
- i915_gem_object_unpin_map(obj);
- i915_gem_object_put(obj);
- } while (!time_after(jiffies, end));
-
- goto err_flush;
-
-err_unpin:
- i915_gem_object_unpin_map(obj);
-err_put:
- i915_gem_object_put(obj);
-err_flush:
- if (err == -ENOMEM)
- err = 0;
- intel_engine_pm_put(engine);
-
- return err;
-}
-
-static int igt_client_fill(void *arg)
-{
- int inst = 0;
-
- do {
- struct intel_engine_cs *engine;
- int err;
-
- engine = intel_engine_lookup_user(arg,
- I915_ENGINE_CLASS_COPY,
- inst++);
- if (!engine)
- return 0;
-
- err = __igt_client_fill(engine);
- if (err == -ENOMEM)
- err = 0;
- if (err)
- return err;
- } while (1);
-}
-
#define WIDTH 512
#define HEIGHT 32
@@ -693,7 +582,6 @@ static int igt_client_tiled_blits(void *arg)
int i915_gem_client_blt_live_selftests(struct drm_i915_private *i915)
{
static const struct i915_subtest tests[] = {
- SUBTEST(igt_client_fill),
SUBTEST(igt_client_tiled_blits),
};
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
index dbcfa28a9d91..8eb5050f8cb3 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -680,7 +680,7 @@ static int igt_ctx_exec(void *arg)
struct i915_gem_context *ctx;
struct intel_context *ce;
- ctx = kernel_context(i915);
+ ctx = kernel_context(i915, NULL);
if (IS_ERR(ctx)) {
err = PTR_ERR(ctx);
goto out_file;
@@ -813,16 +813,12 @@ static int igt_shared_ctx_exec(void *arg)
struct i915_gem_context *ctx;
struct intel_context *ce;
- ctx = kernel_context(i915);
+ ctx = kernel_context(i915, ctx_vm(parent));
if (IS_ERR(ctx)) {
err = PTR_ERR(ctx);
goto out_test;
}
- mutex_lock(&ctx->mutex);
- __assign_ppgtt(ctx, ctx_vm(parent));
- mutex_unlock(&ctx->mutex);
-
ce = i915_gem_context_get_engine(ctx, engine->legacy_idx);
GEM_BUG_ON(IS_ERR(ce));
@@ -1875,125 +1871,6 @@ out_file:
return err;
}
-static bool skip_unused_engines(struct intel_context *ce, void *data)
-{
- return !ce->state;
-}
-
-static void mock_barrier_task(void *data)
-{
- unsigned int *counter = data;
-
- ++*counter;
-}
-
-static int mock_context_barrier(void *arg)
-{
-#undef pr_fmt
-#define pr_fmt(x) "context_barrier_task():" # x
- struct drm_i915_private *i915 = arg;
- struct i915_gem_context *ctx;
- struct i915_request *rq;
- unsigned int counter;
- int err;
-
- /*
- * The context barrier provides us with a callback after it emits
- * a request; useful for retiring old state after loading new.
- */
-
- ctx = mock_context(i915, "mock");
- if (!ctx)
- return -ENOMEM;
-
- counter = 0;
- err = context_barrier_task(ctx, 0, NULL, NULL, NULL,
- mock_barrier_task, &counter);
- if (err) {
- pr_err("Failed at line %d, err=%d\n", __LINE__, err);
- goto out;
- }
- if (counter == 0) {
- pr_err("Did not retire immediately with 0 engines\n");
- err = -EINVAL;
- goto out;
- }
-
- counter = 0;
- err = context_barrier_task(ctx, ALL_ENGINES, skip_unused_engines,
- NULL, NULL, mock_barrier_task, &counter);
- if (err) {
- pr_err("Failed at line %d, err=%d\n", __LINE__, err);
- goto out;
- }
- if (counter == 0) {
- pr_err("Did not retire immediately for all unused engines\n");
- err = -EINVAL;
- goto out;
- }
-
- rq = igt_request_alloc(ctx, i915->gt.engine[RCS0]);
- if (IS_ERR(rq)) {
- pr_err("Request allocation failed!\n");
- goto out;
- }
- i915_request_add(rq);
-
- counter = 0;
- context_barrier_inject_fault = BIT(RCS0);
- err = context_barrier_task(ctx, ALL_ENGINES, NULL, NULL, NULL,
- mock_barrier_task, &counter);
- context_barrier_inject_fault = 0;
- if (err == -ENXIO)
- err = 0;
- else
- pr_err("Did not hit fault injection!\n");
- if (counter != 0) {
- pr_err("Invoked callback on error!\n");
- err = -EIO;
- }
- if (err)
- goto out;
-
- counter = 0;
- err = context_barrier_task(ctx, ALL_ENGINES, skip_unused_engines,
- NULL, NULL, mock_barrier_task, &counter);
- if (err) {
- pr_err("Failed at line %d, err=%d\n", __LINE__, err);
- goto out;
- }
- mock_device_flush(i915);
- if (counter == 0) {
- pr_err("Did not retire on each active engines\n");
- err = -EINVAL;
- goto out;
- }
-
-out:
- mock_context_close(ctx);
- return err;
-#undef pr_fmt
-#define pr_fmt(x) x
-}
-
-int i915_gem_context_mock_selftests(void)
-{
- static const struct i915_subtest tests[] = {
- SUBTEST(mock_context_barrier),
- };
- struct drm_i915_private *i915;
- int err;
-
- i915 = mock_gem_device();
- if (!i915)
- return -ENOMEM;
-
- err = i915_subtests(tests, i915);
-
- mock_destroy_device(i915);
- return err;
-}
-
int i915_gem_context_live_selftests(struct drm_i915_private *i915)
{
static const struct i915_subtest tests[] = {
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
index dd74bc09ec88..ffae7df5e4d7 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
@@ -35,7 +35,7 @@ static int igt_dmabuf_export(void *arg)
static int igt_dmabuf_import_self(void *arg)
{
struct drm_i915_private *i915 = arg;
- struct drm_i915_gem_object *obj;
+ struct drm_i915_gem_object *obj, *import_obj;
struct drm_gem_object *import;
struct dma_buf *dmabuf;
int err;
@@ -65,10 +65,19 @@ static int igt_dmabuf_import_self(void *arg)
err = -EINVAL;
goto out_import;
}
+ import_obj = to_intel_bo(import);
+
+ i915_gem_object_lock(import_obj, NULL);
+ err = __i915_gem_object_get_pages(import_obj);
+ i915_gem_object_unlock(import_obj);
+ if (err) {
+ pr_err("Same object dma-buf get_pages failed!\n");
+ goto out_import;
+ }
err = 0;
out_import:
- i915_gem_object_put(to_intel_bo(import));
+ i915_gem_object_put(import_obj);
out_dmabuf:
dma_buf_put(dmabuf);
out:
@@ -76,6 +85,180 @@ out:
return err;
}
+static int igt_dmabuf_import_same_driver_lmem(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_memory_region *lmem = i915->mm.regions[INTEL_REGION_LMEM];
+ struct drm_i915_gem_object *obj;
+ struct drm_gem_object *import;
+ struct dma_buf *dmabuf;
+ int err;
+
+ if (!lmem)
+ return 0;
+
+ force_different_devices = true;
+
+ obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &lmem, 1);
+ if (IS_ERR(obj)) {
+ pr_err("__i915_gem_object_create_user failed with err=%ld\n",
+ PTR_ERR(dmabuf));
+ err = PTR_ERR(obj);
+ goto out_ret;
+ }
+
+ dmabuf = i915_gem_prime_export(&obj->base, 0);
+ if (IS_ERR(dmabuf)) {
+ pr_err("i915_gem_prime_export failed with err=%ld\n",
+ PTR_ERR(dmabuf));
+ err = PTR_ERR(dmabuf);
+ goto out;
+ }
+
+ /*
+ * We expect an import of an LMEM-only object to fail with
+ * -EOPNOTSUPP because it can't be migrated to SMEM.
+ */
+ import = i915_gem_prime_import(&i915->drm, dmabuf);
+ if (!IS_ERR(import)) {
+ drm_gem_object_put(import);
+ pr_err("i915_gem_prime_import succeeded when it shouldn't have\n");
+ err = -EINVAL;
+ } else if (PTR_ERR(import) != -EOPNOTSUPP) {
+ pr_err("i915_gem_prime_import failed with the wrong err=%ld\n",
+ PTR_ERR(import));
+ err = PTR_ERR(import);
+ }
+
+ dma_buf_put(dmabuf);
+out:
+ i915_gem_object_put(obj);
+out_ret:
+ force_different_devices = false;
+ return err;
+}
+
+static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
+ struct intel_memory_region **regions,
+ unsigned int num_regions)
+{
+ struct drm_i915_gem_object *obj, *import_obj;
+ struct drm_gem_object *import;
+ struct dma_buf *dmabuf;
+ struct dma_buf_attachment *import_attach;
+ struct sg_table *st;
+ long timeout;
+ int err;
+
+ force_different_devices = true;
+
+ obj = __i915_gem_object_create_user(i915, PAGE_SIZE,
+ regions, num_regions);
+ if (IS_ERR(obj)) {
+ pr_err("__i915_gem_object_create_user failed with err=%ld\n",
+ PTR_ERR(dmabuf));
+ err = PTR_ERR(obj);
+ goto out_ret;
+ }
+
+ dmabuf = i915_gem_prime_export(&obj->base, 0);
+ if (IS_ERR(dmabuf)) {
+ pr_err("i915_gem_prime_export failed with err=%ld\n",
+ PTR_ERR(dmabuf));
+ err = PTR_ERR(dmabuf);
+ goto out;
+ }
+
+ import = i915_gem_prime_import(&i915->drm, dmabuf);
+ if (IS_ERR(import)) {
+ pr_err("i915_gem_prime_import failed with err=%ld\n",
+ PTR_ERR(import));
+ err = PTR_ERR(import);
+ goto out_dmabuf;
+ }
+
+ if (import == &obj->base) {
+ pr_err("i915_gem_prime_import reused gem object!\n");
+ err = -EINVAL;
+ goto out_import;
+ }
+
+ import_obj = to_intel_bo(import);
+
+ i915_gem_object_lock(import_obj, NULL);
+ err = __i915_gem_object_get_pages(import_obj);
+ if (err) {
+ pr_err("Different objects dma-buf get_pages failed!\n");
+ i915_gem_object_unlock(import_obj);
+ goto out_import;
+ }
+
+ /*
+ * If the exported object is not in system memory, something
+ * weird is going on. TODO: When p2p is supported, this is no
+ * longer considered weird.
+ */
+ if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
+ pr_err("Exported dma-buf is not in system memory\n");
+ err = -EINVAL;
+ }
+
+ i915_gem_object_unlock(import_obj);
+
+ /* Now try a fake an importer */
+ import_attach = dma_buf_attach(dmabuf, obj->base.dev->dev);
+ if (IS_ERR(import_attach)) {
+ err = PTR_ERR(import_attach);
+ goto out_import;
+ }
+
+ st = dma_buf_map_attachment(import_attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR(st)) {
+ err = PTR_ERR(st);
+ goto out_detach;
+ }
+
+ timeout = dma_resv_wait_timeout(dmabuf->resv, false, true, 5 * HZ);
+ if (!timeout) {
+ pr_err("dmabuf wait for exclusive fence timed out.\n");
+ timeout = -ETIME;
+ }
+ err = timeout > 0 ? 0 : timeout;
+ dma_buf_unmap_attachment(import_attach, st, DMA_BIDIRECTIONAL);
+out_detach:
+ dma_buf_detach(dmabuf, import_attach);
+out_import:
+ i915_gem_object_put(import_obj);
+out_dmabuf:
+ dma_buf_put(dmabuf);
+out:
+ i915_gem_object_put(obj);
+out_ret:
+ force_different_devices = false;
+ return err;
+}
+
+static int igt_dmabuf_import_same_driver_smem(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_memory_region *smem = i915->mm.regions[INTEL_REGION_SMEM];
+
+ return igt_dmabuf_import_same_driver(i915, &smem, 1);
+}
+
+static int igt_dmabuf_import_same_driver_lmem_smem(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_memory_region *regions[2];
+
+ if (!i915->mm.regions[INTEL_REGION_LMEM])
+ return 0;
+
+ regions[0] = i915->mm.regions[INTEL_REGION_LMEM];
+ regions[1] = i915->mm.regions[INTEL_REGION_SMEM];
+ return igt_dmabuf_import_same_driver(i915, regions, 2);
+}
+
static int igt_dmabuf_import(void *arg)
{
struct drm_i915_private *i915 = arg;
@@ -286,6 +469,9 @@ int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915)
{
static const struct i915_subtest tests[] = {
SUBTEST(igt_dmabuf_export),
+ SUBTEST(igt_dmabuf_import_same_driver_lmem),
+ SUBTEST(igt_dmabuf_import_same_driver_smem),
+ SUBTEST(igt_dmabuf_import_same_driver_lmem_smem),
};
return i915_subtests(tests, i915);
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
new file mode 100644
index 000000000000..28a700f08b49
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020-2021 Intel Corporation
+ */
+
+#include "gt/intel_migrate.h"
+
+static int igt_fill_check_buffer(struct drm_i915_gem_object *obj,
+ bool fill)
+{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ unsigned int i, count = obj->base.size / sizeof(u32);
+ enum i915_map_type map_type =
+ i915_coherent_map_type(i915, obj, false);
+ u32 *cur;
+ int err = 0;
+
+ assert_object_held(obj);
+ cur = i915_gem_object_pin_map(obj, map_type);
+ if (IS_ERR(cur))
+ return PTR_ERR(cur);
+
+ if (fill)
+ for (i = 0; i < count; ++i)
+ *cur++ = i;
+ else
+ for (i = 0; i < count; ++i)
+ if (*cur++ != i) {
+ pr_err("Object content mismatch at location %d of %d\n", i, count);
+ err = -EINVAL;
+ break;
+ }
+
+ i915_gem_object_unpin_map(obj);
+
+ return err;
+}
+
+static int igt_create_migrate(struct intel_gt *gt, enum intel_region_id src,
+ enum intel_region_id dst)
+{
+ struct drm_i915_private *i915 = gt->i915;
+ struct intel_memory_region *src_mr = i915->mm.regions[src];
+ struct drm_i915_gem_object *obj;
+ struct i915_gem_ww_ctx ww;
+ int err = 0;
+
+ GEM_BUG_ON(!src_mr);
+
+ /* Switch object backing-store on create */
+ obj = i915_gem_object_create_region(src_mr, PAGE_SIZE, 0, 0);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
+
+ for_i915_gem_ww(&ww, err, true) {
+ err = i915_gem_object_lock(obj, &ww);
+ if (err)
+ continue;
+
+ err = igt_fill_check_buffer(obj, true);
+ if (err)
+ continue;
+
+ err = i915_gem_object_migrate(obj, &ww, dst);
+ if (err)
+ continue;
+
+ err = i915_gem_object_pin_pages(obj);
+ if (err)
+ continue;
+
+ if (i915_gem_object_can_migrate(obj, src))
+ err = -EINVAL;
+
+ i915_gem_object_unpin_pages(obj);
+ err = i915_gem_object_wait_migration(obj, true);
+ if (err)
+ continue;
+
+ err = igt_fill_check_buffer(obj, false);
+ }
+ i915_gem_object_put(obj);
+
+ return err;
+}
+
+static int igt_smem_create_migrate(void *arg)
+{
+ return igt_create_migrate(arg, INTEL_REGION_LMEM, INTEL_REGION_SMEM);
+}
+
+static int igt_lmem_create_migrate(void *arg)
+{
+ return igt_create_migrate(arg, INTEL_REGION_SMEM, INTEL_REGION_LMEM);
+}
+
+static int igt_same_create_migrate(void *arg)
+{
+ return igt_create_migrate(arg, INTEL_REGION_LMEM, INTEL_REGION_LMEM);
+}
+
+static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww,
+ struct drm_i915_gem_object *obj)
+{
+ int err;
+
+ err = i915_gem_object_lock(obj, ww);
+ if (err)
+ return err;
+
+ if (i915_gem_object_is_lmem(obj)) {
+ err = i915_gem_object_migrate(obj, ww, INTEL_REGION_SMEM);
+ if (err) {
+ pr_err("Object failed migration to smem\n");
+ if (err)
+ return err;
+ }
+
+ if (i915_gem_object_is_lmem(obj)) {
+ pr_err("object still backed by lmem\n");
+ err = -EINVAL;
+ }
+
+ if (!i915_gem_object_has_struct_page(obj)) {
+ pr_err("object not backed by struct page\n");
+ err = -EINVAL;
+ }
+
+ } else {
+ err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM);
+ if (err) {
+ pr_err("Object failed migration to lmem\n");
+ if (err)
+ return err;
+ }
+
+ if (i915_gem_object_has_struct_page(obj)) {
+ pr_err("object still backed by struct page\n");
+ err = -EINVAL;
+ }
+
+ if (!i915_gem_object_is_lmem(obj)) {
+ pr_err("object not backed by lmem\n");
+ err = -EINVAL;
+ }
+ }
+
+ return err;
+}
+
+static int igt_lmem_pages_migrate(void *arg)
+{
+ struct intel_gt *gt = arg;
+ struct drm_i915_private *i915 = gt->i915;
+ struct drm_i915_gem_object *obj;
+ struct i915_gem_ww_ctx ww;
+ struct i915_request *rq;
+ int err;
+ int i;
+
+ /* From LMEM to shmem and back again */
+
+ obj = i915_gem_object_create_lmem(i915, SZ_2M, 0);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
+
+ /* Initial GPU fill, sync, CPU initialization. */
+ for_i915_gem_ww(&ww, err, true) {
+ err = i915_gem_object_lock(obj, &ww);
+ if (err)
+ continue;
+
+ err = ____i915_gem_object_get_pages(obj);
+ if (err)
+ continue;
+
+ err = intel_migrate_clear(&gt->migrate, &ww, NULL,
+ obj->mm.pages->sgl, obj->cache_level,
+ i915_gem_object_is_lmem(obj),
+ 0xdeadbeaf, &rq);
+ if (rq) {
+ dma_resv_add_excl_fence(obj->base.resv, &rq->fence);
+ i915_request_put(rq);
+ }
+ if (err)
+ continue;
+
+ err = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE,
+ 5 * HZ);
+ if (err)
+ continue;
+
+ err = igt_fill_check_buffer(obj, true);
+ if (err)
+ continue;
+ }
+ if (err)
+ goto out_put;
+
+ /*
+ * Migrate to and from smem without explicitly syncing.
+ * Finalize with data in smem for fast readout.
+ */
+ for (i = 1; i <= 5; ++i) {
+ for_i915_gem_ww(&ww, err, true)
+ err = lmem_pages_migrate_one(&ww, obj);
+ if (err)
+ goto out_put;
+ }
+
+ err = i915_gem_object_lock_interruptible(obj, NULL);
+ if (err)
+ goto out_put;
+
+ /* Finally sync migration and check content. */
+ err = i915_gem_object_wait_migration(obj, true);
+ if (err)
+ goto out_unlock;
+
+ err = igt_fill_check_buffer(obj, false);
+
+out_unlock:
+ i915_gem_object_unlock(obj);
+out_put:
+ i915_gem_object_put(obj);
+
+ return err;
+}
+
+int i915_gem_migrate_live_selftests(struct drm_i915_private *i915)
+{
+ static const struct i915_subtest tests[] = {
+ SUBTEST(igt_smem_create_migrate),
+ SUBTEST(igt_lmem_create_migrate),
+ SUBTEST(igt_same_create_migrate),
+ SUBTEST(igt_lmem_pages_migrate),
+ };
+
+ if (!HAS_LMEM(i915))
+ return 0;
+
+ return intel_gt_live_subtests(tests, &i915->gt);
+}
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 5575172c66f5..b20f5621f62b 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -573,21 +573,30 @@ err:
return 0;
}
+static enum i915_mmap_type default_mapping(struct drm_i915_private *i915)
+{
+ if (HAS_LMEM(i915))
+ return I915_MMAP_TYPE_FIXED;
+
+ return I915_MMAP_TYPE_GTT;
+}
+
static bool assert_mmap_offset(struct drm_i915_private *i915,
unsigned long size,
int expected)
{
struct drm_i915_gem_object *obj;
- struct i915_mmap_offset *mmo;
+ u64 offset;
+ int ret;
obj = i915_gem_object_create_internal(i915, size);
if (IS_ERR(obj))
- return false;
+ return expected && expected == PTR_ERR(obj);
- mmo = mmap_offset_attach(obj, I915_MMAP_OFFSET_GTT, NULL);
+ ret = __assign_mmap_offset(obj, default_mapping(i915), &offset, NULL);
i915_gem_object_put(obj);
- return PTR_ERR_OR_ZERO(mmo) == expected;
+ return ret == expected;
}
static void disable_retire_worker(struct drm_i915_private *i915)
@@ -622,8 +631,8 @@ static int igt_mmap_offset_exhaustion(void *arg)
struct drm_mm *mm = &i915->drm.vma_offset_manager->vm_addr_space_mm;
struct drm_i915_gem_object *obj;
struct drm_mm_node *hole, *next;
- struct i915_mmap_offset *mmo;
int loop, err = 0;
+ u64 offset;
/* Disable background reaper */
disable_retire_worker(i915);
@@ -684,13 +693,13 @@ static int igt_mmap_offset_exhaustion(void *arg)
obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
+ pr_err("Unable to create object for reclaimed hole\n");
goto out;
}
- mmo = mmap_offset_attach(obj, I915_MMAP_OFFSET_GTT, NULL);
- if (IS_ERR(mmo)) {
+ err = __assign_mmap_offset(obj, default_mapping(i915), &offset, NULL);
+ if (err) {
pr_err("Unable to insert object into reclaimed hole\n");
- err = PTR_ERR(mmo);
goto err_obj;
}
@@ -830,34 +839,25 @@ static int wc_check(struct drm_i915_gem_object *obj)
static bool can_mmap(struct drm_i915_gem_object *obj, enum i915_mmap_type type)
{
- if (type == I915_MMAP_TYPE_GTT &&
- !i915_ggtt_has_aperture(&to_i915(obj->base.dev)->ggtt))
- return false;
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ bool no_map;
- if (type != I915_MMAP_TYPE_GTT &&
- !i915_gem_object_has_struct_page(obj) &&
- !i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_IOMEM))
+ if (HAS_LMEM(i915))
+ return type == I915_MMAP_TYPE_FIXED;
+ else if (type == I915_MMAP_TYPE_FIXED)
return false;
- return true;
-}
-
-static void object_set_placements(struct drm_i915_gem_object *obj,
- struct intel_memory_region **placements,
- unsigned int n_placements)
-{
- GEM_BUG_ON(!n_placements);
+ if (type == I915_MMAP_TYPE_GTT &&
+ !i915_ggtt_has_aperture(&to_i915(obj->base.dev)->ggtt))
+ return false;
- if (n_placements == 1) {
- struct drm_i915_private *i915 = to_i915(obj->base.dev);
- struct intel_memory_region *mr = placements[0];
+ i915_gem_object_lock(obj, NULL);
+ no_map = (type != I915_MMAP_TYPE_GTT &&
+ !i915_gem_object_has_struct_page(obj) &&
+ !i915_gem_object_has_iomem(obj));
+ i915_gem_object_unlock(obj);
- obj->mm.placements = &i915->mm.regions[mr->id];
- obj->mm.n_placements = 1;
- } else {
- obj->mm.placements = placements;
- obj->mm.n_placements = n_placements;
- }
+ return !no_map;
}
#define expand32(x) (((x) << 0) | ((x) << 8) | ((x) << 16) | ((x) << 24))
@@ -865,10 +865,10 @@ static int __igt_mmap(struct drm_i915_private *i915,
struct drm_i915_gem_object *obj,
enum i915_mmap_type type)
{
- struct i915_mmap_offset *mmo;
struct vm_area_struct *area;
unsigned long addr;
int err, i;
+ u64 offset;
if (!can_mmap(obj, type))
return 0;
@@ -879,11 +879,11 @@ static int __igt_mmap(struct drm_i915_private *i915,
if (err)
return err;
- mmo = mmap_offset_attach(obj, type, NULL);
- if (IS_ERR(mmo))
- return PTR_ERR(mmo);
+ err = __assign_mmap_offset(obj, type, &offset, NULL);
+ if (err)
+ return err;
- addr = igt_mmap_node(i915, &mmo->vma_node, 0, PROT_WRITE, MAP_SHARED);
+ addr = igt_mmap_offset(i915, offset, obj->base.size, PROT_WRITE, MAP_SHARED);
if (IS_ERR_VALUE(addr))
return addr;
@@ -897,13 +897,6 @@ static int __igt_mmap(struct drm_i915_private *i915,
goto out_unmap;
}
- if (area->vm_private_data != mmo) {
- pr_err("%s: vm_area_struct did not point back to our mmap_offset object!\n",
- obj->mm.region->name);
- err = -EINVAL;
- goto out_unmap;
- }
-
for (i = 0; i < obj->base.size / sizeof(u32); i++) {
u32 __user *ux = u64_to_user_ptr((u64)(addr + i * sizeof(*ux)));
u32 x;
@@ -961,18 +954,18 @@ static int igt_mmap(void *arg)
struct drm_i915_gem_object *obj;
int err;
- obj = i915_gem_object_create_region(mr, sizes[i], 0);
+ obj = __i915_gem_object_create_user(i915, sizes[i], &mr, 1);
if (obj == ERR_PTR(-ENODEV))
continue;
if (IS_ERR(obj))
return PTR_ERR(obj);
- object_set_placements(obj, &mr, 1);
-
err = __igt_mmap(i915, obj, I915_MMAP_TYPE_GTT);
if (err == 0)
err = __igt_mmap(i915, obj, I915_MMAP_TYPE_WC);
+ if (err == 0)
+ err = __igt_mmap(i915, obj, I915_MMAP_TYPE_FIXED);
i915_gem_object_put(obj);
if (err)
@@ -990,26 +983,33 @@ static const char *repr_mmap_type(enum i915_mmap_type type)
case I915_MMAP_TYPE_WB: return "wb";
case I915_MMAP_TYPE_WC: return "wc";
case I915_MMAP_TYPE_UC: return "uc";
+ case I915_MMAP_TYPE_FIXED: return "fixed";
default: return "unknown";
}
}
-static bool can_access(const struct drm_i915_gem_object *obj)
+static bool can_access(struct drm_i915_gem_object *obj)
{
- return i915_gem_object_has_struct_page(obj) ||
- i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_IOMEM);
+ bool access;
+
+ i915_gem_object_lock(obj, NULL);
+ access = i915_gem_object_has_struct_page(obj) ||
+ i915_gem_object_has_iomem(obj);
+ i915_gem_object_unlock(obj);
+
+ return access;
}
static int __igt_mmap_access(struct drm_i915_private *i915,
struct drm_i915_gem_object *obj,
enum i915_mmap_type type)
{
- struct i915_mmap_offset *mmo;
unsigned long __user *ptr;
unsigned long A, B;
unsigned long x, y;
unsigned long addr;
int err;
+ u64 offset;
memset(&A, 0xAA, sizeof(A));
memset(&B, 0xBB, sizeof(B));
@@ -1017,11 +1017,11 @@ static int __igt_mmap_access(struct drm_i915_private *i915,
if (!can_mmap(obj, type) || !can_access(obj))
return 0;
- mmo = mmap_offset_attach(obj, type, NULL);
- if (IS_ERR(mmo))
- return PTR_ERR(mmo);
+ err = __assign_mmap_offset(obj, type, &offset, NULL);
+ if (err)
+ return err;
- addr = igt_mmap_node(i915, &mmo->vma_node, 0, PROT_WRITE, MAP_SHARED);
+ addr = igt_mmap_offset(i915, offset, obj->base.size, PROT_WRITE, MAP_SHARED);
if (IS_ERR_VALUE(addr))
return addr;
ptr = (unsigned long __user *)addr;
@@ -1081,15 +1081,13 @@ static int igt_mmap_access(void *arg)
struct drm_i915_gem_object *obj;
int err;
- obj = i915_gem_object_create_region(mr, PAGE_SIZE, 0);
+ obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1);
if (obj == ERR_PTR(-ENODEV))
continue;
if (IS_ERR(obj))
return PTR_ERR(obj);
- object_set_placements(obj, &mr, 1);
-
err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_GTT);
if (err == 0)
err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_WB);
@@ -1097,6 +1095,8 @@ static int igt_mmap_access(void *arg)
err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_WC);
if (err == 0)
err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_UC);
+ if (err == 0)
+ err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_FIXED);
i915_gem_object_put(obj);
if (err)
@@ -1111,11 +1111,11 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915,
enum i915_mmap_type type)
{
struct intel_engine_cs *engine;
- struct i915_mmap_offset *mmo;
unsigned long addr;
u32 __user *ux;
u32 bbe;
int err;
+ u64 offset;
/*
* Verify that the mmap access into the backing store aligns with
@@ -1132,11 +1132,11 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915,
if (err)
return err;
- mmo = mmap_offset_attach(obj, type, NULL);
- if (IS_ERR(mmo))
- return PTR_ERR(mmo);
+ err = __assign_mmap_offset(obj, type, &offset, NULL);
+ if (err)
+ return err;
- addr = igt_mmap_node(i915, &mmo->vma_node, 0, PROT_WRITE, MAP_SHARED);
+ addr = igt_mmap_offset(i915, offset, obj->base.size, PROT_WRITE, MAP_SHARED);
if (IS_ERR_VALUE(addr))
return addr;
@@ -1226,18 +1226,18 @@ static int igt_mmap_gpu(void *arg)
struct drm_i915_gem_object *obj;
int err;
- obj = i915_gem_object_create_region(mr, PAGE_SIZE, 0);
+ obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1);
if (obj == ERR_PTR(-ENODEV))
continue;
if (IS_ERR(obj))
return PTR_ERR(obj);
- object_set_placements(obj, &mr, 1);
-
err = __igt_mmap_gpu(i915, obj, I915_MMAP_TYPE_GTT);
if (err == 0)
err = __igt_mmap_gpu(i915, obj, I915_MMAP_TYPE_WC);
+ if (err == 0)
+ err = __igt_mmap_gpu(i915, obj, I915_MMAP_TYPE_FIXED);
i915_gem_object_put(obj);
if (err)
@@ -1303,18 +1303,18 @@ static int __igt_mmap_revoke(struct drm_i915_private *i915,
struct drm_i915_gem_object *obj,
enum i915_mmap_type type)
{
- struct i915_mmap_offset *mmo;
unsigned long addr;
int err;
+ u64 offset;
if (!can_mmap(obj, type))
return 0;
- mmo = mmap_offset_attach(obj, type, NULL);
- if (IS_ERR(mmo))
- return PTR_ERR(mmo);
+ err = __assign_mmap_offset(obj, type, &offset, NULL);
+ if (err)
+ return err;
- addr = igt_mmap_node(i915, &mmo->vma_node, 0, PROT_WRITE, MAP_SHARED);
+ addr = igt_mmap_offset(i915, offset, obj->base.size, PROT_WRITE, MAP_SHARED);
if (IS_ERR_VALUE(addr))
return addr;
@@ -1350,10 +1350,20 @@ static int __igt_mmap_revoke(struct drm_i915_private *i915,
}
}
- err = check_absent(addr, obj->base.size);
- if (err) {
- pr_err("%s: was not absent\n", obj->mm.region->name);
- goto out_unmap;
+ if (!obj->ops->mmap_ops) {
+ err = check_absent(addr, obj->base.size);
+ if (err) {
+ pr_err("%s: was not absent\n", obj->mm.region->name);
+ goto out_unmap;
+ }
+ } else {
+ /* ttm allows access to evicted regions by design */
+
+ err = check_present(addr, obj->base.size);
+ if (err) {
+ pr_err("%s: was not present\n", obj->mm.region->name);
+ goto out_unmap;
+ }
}
out_unmap:
@@ -1371,18 +1381,18 @@ static int igt_mmap_revoke(void *arg)
struct drm_i915_gem_object *obj;
int err;
- obj = i915_gem_object_create_region(mr, PAGE_SIZE, 0);
+ obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1);
if (obj == ERR_PTR(-ENODEV))
continue;
if (IS_ERR(obj))
return PTR_ERR(obj);
- object_set_placements(obj, &mr, 1);
-
err = __igt_mmap_revoke(i915, obj, I915_MMAP_TYPE_GTT);
if (err == 0)
err = __igt_mmap_revoke(i915, obj, I915_MMAP_TYPE_WC);
+ if (err == 0)
+ err = __igt_mmap_revoke(i915, obj, I915_MMAP_TYPE_FIXED);
i915_gem_object_put(obj);
if (err)
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c
deleted file mode 100644
index 8c335d1a8406..000000000000
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c
+++ /dev/null
@@ -1,597 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2019 Intel Corporation
- */
-
-#include <linux/sort.h>
-
-#include "gt/intel_gt.h"
-#include "gt/intel_engine_user.h"
-
-#include "i915_selftest.h"
-
-#include "gem/i915_gem_context.h"
-#include "selftests/igt_flush_test.h"
-#include "selftests/i915_random.h"
-#include "selftests/mock_drm.h"
-#include "huge_gem_object.h"
-#include "mock_context.h"
-
-static int wrap_ktime_compare(const void *A, const void *B)
-{
- const ktime_t *a = A, *b = B;
-
- return ktime_compare(*a, *b);
-}
-
-static int __perf_fill_blt(struct drm_i915_gem_object *obj)
-{
- struct drm_i915_private *i915 = to_i915(obj->base.dev);
- int inst = 0;
-
- do {
- struct intel_engine_cs *engine;
- ktime_t t[5];
- int pass;
- int err;
-
- engine = intel_engine_lookup_user(i915,
- I915_ENGINE_CLASS_COPY,
- inst++);
- if (!engine)
- return 0;
-
- intel_engine_pm_get(engine);
- for (pass = 0; pass < ARRAY_SIZE(t); pass++) {
- struct intel_context *ce = engine->kernel_context;
- ktime_t t0, t1;
-
- t0 = ktime_get();
-
- err = i915_gem_object_fill_blt(obj, ce, 0);
- if (err)
- break;
-
- err = i915_gem_object_wait(obj,
- I915_WAIT_ALL,
- MAX_SCHEDULE_TIMEOUT);
- if (err)
- break;
-
- t1 = ktime_get();
- t[pass] = ktime_sub(t1, t0);
- }
- intel_engine_pm_put(engine);
- if (err)
- return err;
-
- sort(t, ARRAY_SIZE(t), sizeof(*t), wrap_ktime_compare, NULL);
- pr_info("%s: blt %zd KiB fill: %lld MiB/s\n",
- engine->name,
- obj->base.size >> 10,
- div64_u64(mul_u32_u32(4 * obj->base.size,
- 1000 * 1000 * 1000),
- t[1] + 2 * t[2] + t[3]) >> 20);
- } while (1);
-}
-
-static int perf_fill_blt(void *arg)
-{
- struct drm_i915_private *i915 = arg;
- static const unsigned long sizes[] = {
- SZ_4K,
- SZ_64K,
- SZ_2M,
- SZ_64M
- };
- int i;
-
- for (i = 0; i < ARRAY_SIZE(sizes); i++) {
- struct drm_i915_gem_object *obj;
- int err;
-
- obj = i915_gem_object_create_internal(i915, sizes[i]);
- if (IS_ERR(obj))
- return PTR_ERR(obj);
-
- err = __perf_fill_blt(obj);
- i915_gem_object_put(obj);
- if (err)
- return err;
- }
-
- return 0;
-}
-
-static int __perf_copy_blt(struct drm_i915_gem_object *src,
- struct drm_i915_gem_object *dst)
-{
- struct drm_i915_private *i915 = to_i915(src->base.dev);
- int inst = 0;
-
- do {
- struct intel_engine_cs *engine;
- ktime_t t[5];
- int pass;
- int err = 0;
-
- engine = intel_engine_lookup_user(i915,
- I915_ENGINE_CLASS_COPY,
- inst++);
- if (!engine)
- return 0;
-
- intel_engine_pm_get(engine);
- for (pass = 0; pass < ARRAY_SIZE(t); pass++) {
- struct intel_context *ce = engine->kernel_context;
- ktime_t t0, t1;
-
- t0 = ktime_get();
-
- err = i915_gem_object_copy_blt(src, dst, ce);
- if (err)
- break;
-
- err = i915_gem_object_wait(dst,
- I915_WAIT_ALL,
- MAX_SCHEDULE_TIMEOUT);
- if (err)
- break;
-
- t1 = ktime_get();
- t[pass] = ktime_sub(t1, t0);
- }
- intel_engine_pm_put(engine);
- if (err)
- return err;
-
- sort(t, ARRAY_SIZE(t), sizeof(*t), wrap_ktime_compare, NULL);
- pr_info("%s: blt %zd KiB copy: %lld MiB/s\n",
- engine->name,
- src->base.size >> 10,
- div64_u64(mul_u32_u32(4 * src->base.size,
- 1000 * 1000 * 1000),
- t[1] + 2 * t[2] + t[3]) >> 20);
- } while (1);
-}
-
-static int perf_copy_blt(void *arg)
-{
- struct drm_i915_private *i915 = arg;
- static const unsigned long sizes[] = {
- SZ_4K,
- SZ_64K,
- SZ_2M,
- SZ_64M
- };
- int i;
-
- for (i = 0; i < ARRAY_SIZE(sizes); i++) {
- struct drm_i915_gem_object *src, *dst;
- int err;
-
- src = i915_gem_object_create_internal(i915, sizes[i]);
- if (IS_ERR(src))
- return PTR_ERR(src);
-
- dst = i915_gem_object_create_internal(i915, sizes[i]);
- if (IS_ERR(dst)) {
- err = PTR_ERR(dst);
- goto err_src;
- }
-
- err = __perf_copy_blt(src, dst);
-
- i915_gem_object_put(dst);
-err_src:
- i915_gem_object_put(src);
- if (err)
- return err;
- }
-
- return 0;
-}
-
-struct igt_thread_arg {
- struct intel_engine_cs *engine;
- struct i915_gem_context *ctx;
- struct file *file;
- struct rnd_state prng;
- unsigned int n_cpus;
-};
-
-static int igt_fill_blt_thread(void *arg)
-{
- struct igt_thread_arg *thread = arg;
- struct intel_engine_cs *engine = thread->engine;
- struct rnd_state *prng = &thread->prng;
- struct drm_i915_gem_object *obj;
- struct i915_gem_context *ctx;
- struct intel_context *ce;
- unsigned int prio;
- IGT_TIMEOUT(end);
- u64 total, max;
- int err;
-
- ctx = thread->ctx;
- if (!ctx) {
- ctx = live_context_for_engine(engine, thread->file);
- if (IS_ERR(ctx))
- return PTR_ERR(ctx);
-
- prio = i915_prandom_u32_max_state(I915_PRIORITY_MAX, prng);
- ctx->sched.priority = prio;
- }
-
- ce = i915_gem_context_get_engine(ctx, 0);
- GEM_BUG_ON(IS_ERR(ce));
-
- /*
- * If we have a tiny shared address space, like for the GGTT
- * then we can't be too greedy.
- */
- max = ce->vm->total;
- if (i915_is_ggtt(ce->vm) || thread->ctx)
- max = div_u64(max, thread->n_cpus);
- max >>= 4;
-
- total = PAGE_SIZE;
- do {
- /* Aim to keep the runtime under reasonable bounds! */
- const u32 max_phys_size = SZ_64K;
- u32 val = prandom_u32_state(prng);
- u32 phys_sz;
- u32 sz;
- u32 *vaddr;
- u32 i;
-
- total = min(total, max);
- sz = i915_prandom_u32_max_state(total, prng) + 1;
- phys_sz = sz % max_phys_size + 1;
-
- sz = round_up(sz, PAGE_SIZE);
- phys_sz = round_up(phys_sz, PAGE_SIZE);
- phys_sz = min(phys_sz, sz);
-
- pr_debug("%s with phys_sz= %x, sz=%x, val=%x\n", __func__,
- phys_sz, sz, val);
-
- obj = huge_gem_object(engine->i915, phys_sz, sz);
- if (IS_ERR(obj)) {
- err = PTR_ERR(obj);
- goto err_flush;
- }
-
- vaddr = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WB);
- if (IS_ERR(vaddr)) {
- err = PTR_ERR(vaddr);
- goto err_put;
- }
-
- /*
- * Make sure the potentially async clflush does its job, if
- * required.
- */
- memset32(vaddr, val ^ 0xdeadbeaf,
- huge_gem_object_phys_size(obj) / sizeof(u32));
-
- if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE))
- obj->cache_dirty = true;
-
- err = i915_gem_object_fill_blt(obj, ce, val);
- if (err)
- goto err_unpin;
-
- err = i915_gem_object_wait(obj, 0, MAX_SCHEDULE_TIMEOUT);
- if (err)
- goto err_unpin;
-
- for (i = 0; i < huge_gem_object_phys_size(obj) / sizeof(u32); i += 17) {
- if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
- drm_clflush_virt_range(&vaddr[i], sizeof(vaddr[i]));
-
- if (vaddr[i] != val) {
- pr_err("vaddr[%u]=%x, expected=%x\n", i,
- vaddr[i], val);
- err = -EINVAL;
- goto err_unpin;
- }
- }
-
- i915_gem_object_unpin_map(obj);
- i915_gem_object_put(obj);
-
- total <<= 1;
- } while (!time_after(jiffies, end));
-
- goto err_flush;
-
-err_unpin:
- i915_gem_object_unpin_map(obj);
-err_put:
- i915_gem_object_put(obj);
-err_flush:
- if (err == -ENOMEM)
- err = 0;
-
- intel_context_put(ce);
- return err;
-}
-
-static int igt_copy_blt_thread(void *arg)
-{
- struct igt_thread_arg *thread = arg;
- struct intel_engine_cs *engine = thread->engine;
- struct rnd_state *prng = &thread->prng;
- struct drm_i915_gem_object *src, *dst;
- struct i915_gem_context *ctx;
- struct intel_context *ce;
- unsigned int prio;
- IGT_TIMEOUT(end);
- u64 total, max;
- int err;
-
- ctx = thread->ctx;
- if (!ctx) {
- ctx = live_context_for_engine(engine, thread->file);
- if (IS_ERR(ctx))
- return PTR_ERR(ctx);
-
- prio = i915_prandom_u32_max_state(I915_PRIORITY_MAX, prng);
- ctx->sched.priority = prio;
- }
-
- ce = i915_gem_context_get_engine(ctx, 0);
- GEM_BUG_ON(IS_ERR(ce));
-
- /*
- * If we have a tiny shared address space, like for the GGTT
- * then we can't be too greedy.
- */
- max = ce->vm->total;
- if (i915_is_ggtt(ce->vm) || thread->ctx)
- max = div_u64(max, thread->n_cpus);
- max >>= 4;
-
- total = PAGE_SIZE;
- do {
- /* Aim to keep the runtime under reasonable bounds! */
- const u32 max_phys_size = SZ_64K;
- u32 val = prandom_u32_state(prng);
- u32 phys_sz;
- u32 sz;
- u32 *vaddr;
- u32 i;
-
- total = min(total, max);
- sz = i915_prandom_u32_max_state(total, prng) + 1;
- phys_sz = sz % max_phys_size + 1;
-
- sz = round_up(sz, PAGE_SIZE);
- phys_sz = round_up(phys_sz, PAGE_SIZE);
- phys_sz = min(phys_sz, sz);
-
- pr_debug("%s with phys_sz= %x, sz=%x, val=%x\n", __func__,
- phys_sz, sz, val);
-
- src = huge_gem_object(engine->i915, phys_sz, sz);
- if (IS_ERR(src)) {
- err = PTR_ERR(src);
- goto err_flush;
- }
-
- vaddr = i915_gem_object_pin_map_unlocked(src, I915_MAP_WB);
- if (IS_ERR(vaddr)) {
- err = PTR_ERR(vaddr);
- goto err_put_src;
- }
-
- memset32(vaddr, val,
- huge_gem_object_phys_size(src) / sizeof(u32));
-
- i915_gem_object_unpin_map(src);
-
- if (!(src->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
- src->cache_dirty = true;
-
- dst = huge_gem_object(engine->i915, phys_sz, sz);
- if (IS_ERR(dst)) {
- err = PTR_ERR(dst);
- goto err_put_src;
- }
-
- vaddr = i915_gem_object_pin_map_unlocked(dst, I915_MAP_WB);
- if (IS_ERR(vaddr)) {
- err = PTR_ERR(vaddr);
- goto err_put_dst;
- }
-
- memset32(vaddr, val ^ 0xdeadbeaf,
- huge_gem_object_phys_size(dst) / sizeof(u32));
-
- if (!(dst->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE))
- dst->cache_dirty = true;
-
- err = i915_gem_object_copy_blt(src, dst, ce);
- if (err)
- goto err_unpin;
-
- err = i915_gem_object_wait(dst, 0, MAX_SCHEDULE_TIMEOUT);
- if (err)
- goto err_unpin;
-
- for (i = 0; i < huge_gem_object_phys_size(dst) / sizeof(u32); i += 17) {
- if (!(dst->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
- drm_clflush_virt_range(&vaddr[i], sizeof(vaddr[i]));
-
- if (vaddr[i] != val) {
- pr_err("vaddr[%u]=%x, expected=%x\n", i,
- vaddr[i], val);
- err = -EINVAL;
- goto err_unpin;
- }
- }
-
- i915_gem_object_unpin_map(dst);
-
- i915_gem_object_put(src);
- i915_gem_object_put(dst);
-
- total <<= 1;
- } while (!time_after(jiffies, end));
-
- goto err_flush;
-
-err_unpin:
- i915_gem_object_unpin_map(dst);
-err_put_dst:
- i915_gem_object_put(dst);
-err_put_src:
- i915_gem_object_put(src);
-err_flush:
- if (err == -ENOMEM)
- err = 0;
-
- intel_context_put(ce);
- return err;
-}
-
-static int igt_threaded_blt(struct intel_engine_cs *engine,
- int (*blt_fn)(void *arg),
- unsigned int flags)
-#define SINGLE_CTX BIT(0)
-{
- struct igt_thread_arg *thread;
- struct task_struct **tsk;
- unsigned int n_cpus, i;
- I915_RND_STATE(prng);
- int err = 0;
-
- n_cpus = num_online_cpus() + 1;
-
- tsk = kcalloc(n_cpus, sizeof(struct task_struct *), GFP_KERNEL);
- if (!tsk)
- return 0;
-
- thread = kcalloc(n_cpus, sizeof(struct igt_thread_arg), GFP_KERNEL);
- if (!thread)
- goto out_tsk;
-
- thread[0].file = mock_file(engine->i915);
- if (IS_ERR(thread[0].file)) {
- err = PTR_ERR(thread[0].file);
- goto out_thread;
- }
-
- if (flags & SINGLE_CTX) {
- thread[0].ctx = live_context_for_engine(engine, thread[0].file);
- if (IS_ERR(thread[0].ctx)) {
- err = PTR_ERR(thread[0].ctx);
- goto out_file;
- }
- }
-
- for (i = 0; i < n_cpus; ++i) {
- thread[i].engine = engine;
- thread[i].file = thread[0].file;
- thread[i].ctx = thread[0].ctx;
- thread[i].n_cpus = n_cpus;
- thread[i].prng =
- I915_RND_STATE_INITIALIZER(prandom_u32_state(&prng));
-
- tsk[i] = kthread_run(blt_fn, &thread[i], "igt/blt-%d", i);
- if (IS_ERR(tsk[i])) {
- err = PTR_ERR(tsk[i]);
- break;
- }
-
- get_task_struct(tsk[i]);
- }
-
- yield(); /* start all threads before we kthread_stop() */
-
- for (i = 0; i < n_cpus; ++i) {
- int status;
-
- if (IS_ERR_OR_NULL(tsk[i]))
- continue;
-
- status = kthread_stop(tsk[i]);
- if (status && !err)
- err = status;
-
- put_task_struct(tsk[i]);
- }
-
-out_file:
- fput(thread[0].file);
-out_thread:
- kfree(thread);
-out_tsk:
- kfree(tsk);
- return err;
-}
-
-static int test_copy_engines(struct drm_i915_private *i915,
- int (*fn)(void *arg),
- unsigned int flags)
-{
- struct intel_engine_cs *engine;
- int ret;
-
- for_each_uabi_class_engine(engine, I915_ENGINE_CLASS_COPY, i915) {
- ret = igt_threaded_blt(engine, fn, flags);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static int igt_fill_blt(void *arg)
-{
- return test_copy_engines(arg, igt_fill_blt_thread, 0);
-}
-
-static int igt_fill_blt_ctx0(void *arg)
-{
- return test_copy_engines(arg, igt_fill_blt_thread, SINGLE_CTX);
-}
-
-static int igt_copy_blt(void *arg)
-{
- return test_copy_engines(arg, igt_copy_blt_thread, 0);
-}
-
-static int igt_copy_blt_ctx0(void *arg)
-{
- return test_copy_engines(arg, igt_copy_blt_thread, SINGLE_CTX);
-}
-
-int i915_gem_object_blt_live_selftests(struct drm_i915_private *i915)
-{
- static const struct i915_subtest tests[] = {
- SUBTEST(igt_fill_blt),
- SUBTEST(igt_fill_blt_ctx0),
- SUBTEST(igt_copy_blt),
- SUBTEST(igt_copy_blt_ctx0),
- };
-
- if (intel_gt_is_wedged(&i915->gt))
- return 0;
-
- return i915_live_subtests(tests, i915);
-}
-
-int i915_gem_object_blt_perf_selftests(struct drm_i915_private *i915)
-{
- static const struct i915_subtest tests[] = {
- SUBTEST(perf_fill_blt),
- SUBTEST(perf_copy_blt),
- };
-
- if (intel_gt_is_wedged(&i915->gt))
- return 0;
-
- return i915_live_subtests(tests, i915);
-}
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c
index 3a6ce87f8b52..d43d8dae0f69 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c
@@ -25,13 +25,14 @@ static int mock_phys_object(void *arg)
goto out;
}
+ i915_gem_object_lock(obj, NULL);
if (!i915_gem_object_has_struct_page(obj)) {
+ i915_gem_object_unlock(obj);
err = -EINVAL;
pr_err("shmem has no struct page\n");
goto out_obj;
}
- i915_gem_object_lock(obj, NULL);
err = i915_gem_object_attach_phys(obj, PAGE_SIZE);
i915_gem_object_unlock(obj);
if (err) {
diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.c b/drivers/gpu/drm/i915/gem/selftests/mock_context.c
index 51b5a3421b40..fee070df1c97 100644
--- a/drivers/gpu/drm/i915/gem/selftests/mock_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.c
@@ -14,6 +14,7 @@ mock_context(struct drm_i915_private *i915,
{
struct i915_gem_context *ctx;
struct i915_gem_engines *e;
+ struct intel_sseu null_sseu = {};
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -30,15 +31,6 @@ mock_context(struct drm_i915_private *i915,
i915_gem_context_set_persistence(ctx);
- mutex_init(&ctx->engines_mutex);
- e = default_engines(ctx);
- if (IS_ERR(e))
- goto err_free;
- RCU_INIT_POINTER(ctx->engines, e);
-
- INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
- mutex_init(&ctx->lut_mutex);
-
if (name) {
struct i915_ppgtt *ppgtt;
@@ -46,25 +38,29 @@ mock_context(struct drm_i915_private *i915,
ppgtt = mock_ppgtt(i915, name);
if (!ppgtt)
- goto err_put;
-
- mutex_lock(&ctx->mutex);
- __set_ppgtt(ctx, &ppgtt->vm);
- mutex_unlock(&ctx->mutex);
+ goto err_free;
+ ctx->vm = i915_vm_open(&ppgtt->vm);
i915_vm_put(&ppgtt->vm);
}
+ mutex_init(&ctx->engines_mutex);
+ e = default_engines(ctx, null_sseu);
+ if (IS_ERR(e))
+ goto err_vm;
+ RCU_INIT_POINTER(ctx->engines, e);
+
+ INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
+ mutex_init(&ctx->lut_mutex);
+
return ctx;
+err_vm:
+ if (ctx->vm)
+ i915_vm_close(ctx->vm);
err_free:
kfree(ctx);
return NULL;
-
-err_put:
- i915_gem_context_set_closed(ctx);
- i915_gem_context_put(ctx);
- return NULL;
}
void mock_context_close(struct i915_gem_context *ctx)
@@ -80,20 +76,29 @@ void mock_init_contexts(struct drm_i915_private *i915)
struct i915_gem_context *
live_context(struct drm_i915_private *i915, struct file *file)
{
+ struct drm_i915_file_private *fpriv = to_drm_file(file)->driver_priv;
+ struct i915_gem_proto_context *pc;
struct i915_gem_context *ctx;
int err;
u32 id;
- ctx = i915_gem_create_context(i915, 0);
+ pc = proto_context_create(i915, 0);
+ if (IS_ERR(pc))
+ return ERR_CAST(pc);
+
+ ctx = i915_gem_create_context(i915, pc);
+ proto_context_close(pc);
if (IS_ERR(ctx))
return ctx;
i915_gem_context_set_no_error_capture(ctx);
- err = gem_context_register(ctx, to_drm_file(file)->driver_priv, &id);
+ err = xa_alloc(&fpriv->context_xa, &id, NULL, xa_limit_32b, GFP_KERNEL);
if (err < 0)
goto err_ctx;
+ gem_context_register(ctx, fpriv, id);
+
return ctx;
err_ctx:
@@ -106,6 +111,7 @@ live_context_for_engine(struct intel_engine_cs *engine, struct file *file)
{
struct i915_gem_engines *engines;
struct i915_gem_context *ctx;
+ struct intel_sseu null_sseu = {};
struct intel_context *ce;
engines = alloc_engines(1);
@@ -124,7 +130,7 @@ live_context_for_engine(struct intel_engine_cs *engine, struct file *file)
return ERR_CAST(ce);
}
- intel_context_set_gem(ce, ctx);
+ intel_context_set_gem(ce, ctx, null_sseu);
engines->engines[0] = ce;
engines->num_engines = 1;
@@ -139,11 +145,24 @@ live_context_for_engine(struct intel_engine_cs *engine, struct file *file)
}
struct i915_gem_context *
-kernel_context(struct drm_i915_private *i915)
+kernel_context(struct drm_i915_private *i915,
+ struct i915_address_space *vm)
{
struct i915_gem_context *ctx;
+ struct i915_gem_proto_context *pc;
+
+ pc = proto_context_create(i915, 0);
+ if (IS_ERR(pc))
+ return ERR_CAST(pc);
+
+ if (vm) {
+ if (pc->vm)
+ i915_vm_put(pc->vm);
+ pc->vm = i915_vm_get(vm);
+ }
- ctx = i915_gem_create_context(i915, 0);
+ ctx = i915_gem_create_context(i915, pc);
+ proto_context_close(pc);
if (IS_ERR(ctx))
return ctx;
diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.h b/drivers/gpu/drm/i915/gem/selftests/mock_context.h
index 2a6121d33352..7a02fd9b5866 100644
--- a/drivers/gpu/drm/i915/gem/selftests/mock_context.h
+++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.h
@@ -10,6 +10,7 @@
struct file;
struct drm_i915_private;
struct intel_engine_cs;
+struct i915_address_space;
void mock_init_contexts(struct drm_i915_private *i915);
@@ -25,7 +26,8 @@ live_context(struct drm_i915_private *i915, struct file *file);
struct i915_gem_context *
live_context_for_engine(struct intel_engine_cs *engine, struct file *file);
-struct i915_gem_context *kernel_context(struct drm_i915_private *i915);
+struct i915_gem_context *kernel_context(struct drm_i915_private *i915,
+ struct i915_address_space *vm);
void kernel_context_close(struct i915_gem_context *ctx);
#endif /* !__MOCK_CONTEXT_H */
diff --git a/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c b/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c
index 4270b5a34a83..d6f5836396f8 100644
--- a/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c
@@ -437,20 +437,20 @@ static int frequency_show(struct seq_file *m, void *unused)
max_freq = (IS_GEN9_LP(i915) ? rp_state_cap >> 0 :
rp_state_cap >> 16) & 0xff;
max_freq *= (IS_GEN9_BC(i915) ||
- GRAPHICS_VER(i915) >= 10 ? GEN9_FREQ_SCALER : 1);
+ GRAPHICS_VER(i915) >= 11 ? GEN9_FREQ_SCALER : 1);
seq_printf(m, "Lowest (RPN) frequency: %dMHz\n",
intel_gpu_freq(rps, max_freq));
max_freq = (rp_state_cap & 0xff00) >> 8;
max_freq *= (IS_GEN9_BC(i915) ||
- GRAPHICS_VER(i915) >= 10 ? GEN9_FREQ_SCALER : 1);
+ GRAPHICS_VER(i915) >= 11 ? GEN9_FREQ_SCALER : 1);
seq_printf(m, "Nominal (RP1) frequency: %dMHz\n",
intel_gpu_freq(rps, max_freq));
max_freq = (IS_GEN9_LP(i915) ? rp_state_cap >> 16 :
rp_state_cap >> 0) & 0xff;
max_freq *= (IS_GEN9_BC(i915) ||
- GRAPHICS_VER(i915) >= 10 ? GEN9_FREQ_SCALER : 1);
+ GRAPHICS_VER(i915) >= 11 ? GEN9_FREQ_SCALER : 1);
seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
intel_gpu_freq(rps, max_freq));
seq_printf(m, "Max overclocked frequency: %dMHz\n",
@@ -500,7 +500,7 @@ static int llc_show(struct seq_file *m, void *data)
min_gpu_freq = rps->min_freq;
max_gpu_freq = rps->max_freq;
- if (IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 10) {
+ if (IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 11) {
/* Convert GT frequency to 50 HZ units */
min_gpu_freq /= GEN9_FREQ_SCALER;
max_gpu_freq /= GEN9_FREQ_SCALER;
@@ -518,7 +518,7 @@ static int llc_show(struct seq_file *m, void *data)
intel_gpu_freq(rps,
(gpu_freq *
(IS_GEN9_BC(i915) ||
- GRAPHICS_VER(i915) >= 10 ?
+ GRAPHICS_VER(i915) >= 11 ?
GEN9_FREQ_SCALER : 1))),
((ia_freq >> 0) & 0xff) * 100,
((ia_freq >> 8) & 0xff) * 100);
diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
index 94e0a5669f90..461844dffd7e 100644
--- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
@@ -42,7 +42,7 @@ int gen8_emit_flush_rcs(struct i915_request *rq, u32 mode)
vf_flush_wa = true;
/* WaForGAMHang:kbl */
- if (IS_KBL_GT_STEP(rq->engine->i915, 0, STEP_B0))
+ if (IS_KBL_GT_STEP(rq->engine->i915, 0, STEP_C0))
dc_flush_wa = true;
}
@@ -208,7 +208,7 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
flags |= PIPE_CONTROL_FLUSH_L3;
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
- /* Wa_1409600907:tgl */
+ /* Wa_1409600907:tgl,adl-p */
flags |= PIPE_CONTROL_DEPTH_STALL;
flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
flags |= PIPE_CONTROL_FLUSH_ENABLE;
@@ -279,7 +279,7 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode)
if (mode & EMIT_INVALIDATE)
aux_inv = rq->engine->mask & ~BIT(BCS0);
if (aux_inv)
- cmd += 2 * hweight8(aux_inv) + 2;
+ cmd += 2 * hweight32(aux_inv) + 2;
cs = intel_ring_begin(rq, cmd);
if (IS_ERR(cs))
@@ -313,9 +313,8 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode)
struct intel_engine_cs *engine;
unsigned int tmp;
- *cs++ = MI_LOAD_REGISTER_IMM(hweight8(aux_inv));
- for_each_engine_masked(engine, rq->engine->gt,
- aux_inv, tmp) {
+ *cs++ = MI_LOAD_REGISTER_IMM(hweight32(aux_inv));
+ for_each_engine_masked(engine, rq->engine->gt, aux_inv, tmp) {
*cs++ = i915_mmio_reg_offset(aux_inv_reg(engine));
*cs++ = AUX_INV;
}
@@ -506,7 +505,8 @@ gen8_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs)
*cs++ = MI_USER_INTERRUPT;
*cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
- if (intel_engine_has_semaphores(rq->engine))
+ if (intel_engine_has_semaphores(rq->engine) &&
+ !intel_uc_uses_guc_submission(&rq->engine->gt->uc))
cs = emit_preempt_busywait(rq, cs);
rq->tail = intel_ring_offset(rq, cs);
@@ -598,7 +598,8 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs)
*cs++ = MI_USER_INTERRUPT;
*cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
- if (intel_engine_has_semaphores(rq->engine))
+ if (intel_engine_has_semaphores(rq->engine) &&
+ !intel_uc_uses_guc_submission(&rq->engine->gt->uc))
cs = gen12_emit_preempt_busywait(rq, cs);
rq->tail = intel_ring_offset(rq, cs);
diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
index da4f5eb43ac2..6e0e52eeb87a 100644
--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
@@ -358,6 +358,54 @@ static void gen8_ppgtt_alloc(struct i915_address_space *vm,
&start, start + length, vm->top);
}
+static void __gen8_ppgtt_foreach(struct i915_address_space *vm,
+ struct i915_page_directory *pd,
+ u64 *start, u64 end, int lvl,
+ void (*fn)(struct i915_address_space *vm,
+ struct i915_page_table *pt,
+ void *data),
+ void *data)
+{
+ unsigned int idx, len;
+
+ len = gen8_pd_range(*start, end, lvl--, &idx);
+
+ spin_lock(&pd->lock);
+ do {
+ struct i915_page_table *pt = pd->entry[idx];
+
+ atomic_inc(&pt->used);
+ spin_unlock(&pd->lock);
+
+ if (lvl) {
+ __gen8_ppgtt_foreach(vm, as_pd(pt), start, end, lvl,
+ fn, data);
+ } else {
+ fn(vm, pt, data);
+ *start += gen8_pt_count(*start, end);
+ }
+
+ spin_lock(&pd->lock);
+ atomic_dec(&pt->used);
+ } while (idx++, --len);
+ spin_unlock(&pd->lock);
+}
+
+static void gen8_ppgtt_foreach(struct i915_address_space *vm,
+ u64 start, u64 length,
+ void (*fn)(struct i915_address_space *vm,
+ struct i915_page_table *pt,
+ void *data),
+ void *data)
+{
+ start >>= GEN8_PTE_SHIFT;
+ length >>= GEN8_PTE_SHIFT;
+
+ __gen8_ppgtt_foreach(vm, i915_vm_to_ppgtt(vm)->pd,
+ &start, start + length, vm->top,
+ fn, data);
+}
+
static __always_inline u64
gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt,
struct i915_page_directory *pdp,
@@ -552,6 +600,24 @@ static void gen8_ppgtt_insert(struct i915_address_space *vm,
}
}
+static void gen8_ppgtt_insert_entry(struct i915_address_space *vm,
+ dma_addr_t addr,
+ u64 offset,
+ enum i915_cache_level level,
+ u32 flags)
+{
+ u64 idx = offset >> GEN8_PTE_SHIFT;
+ struct i915_page_directory * const pdp =
+ gen8_pdp_for_page_index(vm, idx);
+ struct i915_page_directory *pd =
+ i915_pd_entry(pdp, gen8_pd_index(idx, 2));
+ gen8_pte_t *vaddr;
+
+ vaddr = px_vaddr(i915_pt_entry(pd, gen8_pd_index(idx, 1)));
+ vaddr[gen8_pd_index(idx, 0)] = gen8_pte_encode(addr, level, flags);
+ clflush_cache_range(&vaddr[gen8_pd_index(idx, 0)], sizeof(*vaddr));
+}
+
static int gen8_init_scratch(struct i915_address_space *vm)
{
u32 pte_flags;
@@ -731,8 +797,10 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND;
ppgtt->vm.insert_entries = gen8_ppgtt_insert;
+ ppgtt->vm.insert_page = gen8_ppgtt_insert_entry;
ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
ppgtt->vm.clear_range = gen8_ppgtt_clear;
+ ppgtt->vm.foreach = gen8_ppgtt_foreach;
ppgtt->vm.pte_encode = gen8_pte_encode;
diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
index 38cc42783dfb..209cf265bf74 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
@@ -15,28 +15,14 @@
#include "intel_gt_pm.h"
#include "intel_gt_requests.h"
-static bool irq_enable(struct intel_engine_cs *engine)
+static bool irq_enable(struct intel_breadcrumbs *b)
{
- if (!engine->irq_enable)
- return false;
-
- /* Caller disables interrupts */
- spin_lock(&engine->gt->irq_lock);
- engine->irq_enable(engine);
- spin_unlock(&engine->gt->irq_lock);
-
- return true;
+ return intel_engine_irq_enable(b->irq_engine);
}
-static void irq_disable(struct intel_engine_cs *engine)
+static void irq_disable(struct intel_breadcrumbs *b)
{
- if (!engine->irq_disable)
- return;
-
- /* Caller disables interrupts */
- spin_lock(&engine->gt->irq_lock);
- engine->irq_disable(engine);
- spin_unlock(&engine->gt->irq_lock);
+ intel_engine_irq_disable(b->irq_engine);
}
static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
@@ -57,7 +43,7 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
WRITE_ONCE(b->irq_armed, true);
/* Requests may have completed before we could enable the interrupt. */
- if (!b->irq_enabled++ && irq_enable(b->irq_engine))
+ if (!b->irq_enabled++ && b->irq_enable(b))
irq_work_queue(&b->irq_work);
}
@@ -76,7 +62,7 @@ static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
{
GEM_BUG_ON(!b->irq_enabled);
if (!--b->irq_enabled)
- irq_disable(b->irq_engine);
+ b->irq_disable(b);
WRITE_ONCE(b->irq_armed, false);
intel_gt_pm_put_async(b->irq_engine->gt);
@@ -259,6 +245,9 @@ static void signal_irq_work(struct irq_work *work)
llist_entry(signal, typeof(*rq), signal_node);
struct list_head cb_list;
+ if (rq->engine->sched_engine->retire_inflight_request_prio)
+ rq->engine->sched_engine->retire_inflight_request_prio(rq);
+
spin_lock(&rq->lock);
list_replace(&rq->fence.cb_list, &cb_list);
__dma_fence_signal__timestamp(&rq->fence, timestamp);
@@ -281,7 +270,7 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine)
if (!b)
return NULL;
- b->irq_engine = irq_engine;
+ kref_init(&b->ref);
spin_lock_init(&b->signalers_lock);
INIT_LIST_HEAD(&b->signalers);
@@ -290,6 +279,10 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine)
spin_lock_init(&b->irq_lock);
init_irq_work(&b->irq_work, signal_irq_work);
+ b->irq_engine = irq_engine;
+ b->irq_enable = irq_enable;
+ b->irq_disable = irq_disable;
+
return b;
}
@@ -303,9 +296,9 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs *b)
spin_lock_irqsave(&b->irq_lock, flags);
if (b->irq_enabled)
- irq_enable(b->irq_engine);
+ b->irq_enable(b);
else
- irq_disable(b->irq_engine);
+ b->irq_disable(b);
spin_unlock_irqrestore(&b->irq_lock, flags);
}
@@ -325,11 +318,14 @@ void __intel_breadcrumbs_park(struct intel_breadcrumbs *b)
}
}
-void intel_breadcrumbs_free(struct intel_breadcrumbs *b)
+void intel_breadcrumbs_free(struct kref *kref)
{
+ struct intel_breadcrumbs *b = container_of(kref, typeof(*b), ref);
+
irq_work_sync(&b->irq_work);
GEM_BUG_ON(!list_empty(&b->signalers));
GEM_BUG_ON(b->irq_armed);
+
kfree(b);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
index 3ce5ce270b04..be0d4f379a85 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h
@@ -9,7 +9,7 @@
#include <linux/atomic.h>
#include <linux/irq_work.h>
-#include "intel_engine_types.h"
+#include "intel_breadcrumbs_types.h"
struct drm_printer;
struct i915_request;
@@ -17,7 +17,7 @@ struct intel_breadcrumbs;
struct intel_breadcrumbs *
intel_breadcrumbs_create(struct intel_engine_cs *irq_engine);
-void intel_breadcrumbs_free(struct intel_breadcrumbs *b);
+void intel_breadcrumbs_free(struct kref *kref);
void intel_breadcrumbs_reset(struct intel_breadcrumbs *b);
void __intel_breadcrumbs_park(struct intel_breadcrumbs *b);
@@ -48,4 +48,16 @@ void i915_request_cancel_breadcrumb(struct i915_request *request);
void intel_context_remove_breadcrumbs(struct intel_context *ce,
struct intel_breadcrumbs *b);
+static inline struct intel_breadcrumbs *
+intel_breadcrumbs_get(struct intel_breadcrumbs *b)
+{
+ kref_get(&b->ref);
+ return b;
+}
+
+static inline void intel_breadcrumbs_put(struct intel_breadcrumbs *b)
+{
+ kref_put(&b->ref, intel_breadcrumbs_free);
+}
+
#endif /* __INTEL_BREADCRUMBS__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h b/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h
index 3a084ce8ff5e..72dfd3748c4c 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h
@@ -7,10 +7,13 @@
#define __INTEL_BREADCRUMBS_TYPES__
#include <linux/irq_work.h>
+#include <linux/kref.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/types.h>
+#include "intel_engine_types.h"
+
/*
* Rather than have every client wait upon all user interrupts,
* with the herd waking after every interrupt and each doing the
@@ -29,6 +32,7 @@
* the overhead of waking that client is much preferred.
*/
struct intel_breadcrumbs {
+ struct kref ref;
atomic_t active;
spinlock_t signalers_lock; /* protects the list of signalers */
@@ -42,7 +46,10 @@ struct intel_breadcrumbs {
bool irq_armed;
/* Not all breadcrumbs are attached to physical HW */
+ intel_engine_mask_t engine_mask;
struct intel_engine_cs *irq_engine;
+ bool (*irq_enable)(struct intel_breadcrumbs *b);
+ void (*irq_disable)(struct intel_breadcrumbs *b);
};
#endif /* __INTEL_BREADCRUMBS_TYPES__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c
index 4033184f13b9..745e84c72c90 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -7,28 +7,26 @@
#include "gem/i915_gem_pm.h"
#include "i915_drv.h"
-#include "i915_globals.h"
+#include "i915_trace.h"
#include "intel_context.h"
#include "intel_engine.h"
#include "intel_engine_pm.h"
#include "intel_ring.h"
-static struct i915_global_context {
- struct i915_global base;
- struct kmem_cache *slab_ce;
-} global;
+static struct kmem_cache *slab_ce;
static struct intel_context *intel_context_alloc(void)
{
- return kmem_cache_zalloc(global.slab_ce, GFP_KERNEL);
+ return kmem_cache_zalloc(slab_ce, GFP_KERNEL);
}
static void rcu_context_free(struct rcu_head *rcu)
{
struct intel_context *ce = container_of(rcu, typeof(*ce), rcu);
- kmem_cache_free(global.slab_ce, ce);
+ trace_intel_context_free(ce);
+ kmem_cache_free(slab_ce, ce);
}
void intel_context_free(struct intel_context *ce)
@@ -46,6 +44,7 @@ intel_context_create(struct intel_engine_cs *engine)
return ERR_PTR(-ENOMEM);
intel_context_init(ce, engine);
+ trace_intel_context_create(ce);
return ce;
}
@@ -80,7 +79,7 @@ static int intel_context_active_acquire(struct intel_context *ce)
__i915_active_acquire(&ce->active);
- if (intel_context_is_barrier(ce))
+ if (intel_context_is_barrier(ce) || intel_engine_uses_guc(ce->engine))
return 0;
/* Preallocate tracking nodes */
@@ -268,6 +267,8 @@ int __intel_context_do_pin_ww(struct intel_context *ce,
GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */
+ trace_intel_context_do_pin(ce);
+
err_unlock:
mutex_unlock(&ce->pin_mutex);
err_post_unpin:
@@ -306,9 +307,9 @@ retry:
return err;
}
-void intel_context_unpin(struct intel_context *ce)
+void __intel_context_do_unpin(struct intel_context *ce, int sub)
{
- if (!atomic_dec_and_test(&ce->pin_count))
+ if (!atomic_sub_and_test(sub, &ce->pin_count))
return;
CE_TRACE(ce, "unpin\n");
@@ -323,6 +324,7 @@ void intel_context_unpin(struct intel_context *ce)
*/
intel_context_get(ce);
intel_context_active_release(ce);
+ trace_intel_context_do_unpin(ce);
intel_context_put(ce);
}
@@ -360,6 +362,12 @@ static int __intel_context_active(struct i915_active *active)
return 0;
}
+static int sw_fence_dummy_notify(struct i915_sw_fence *sf,
+ enum i915_sw_fence_notify state)
+{
+ return NOTIFY_DONE;
+}
+
void
intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
{
@@ -371,7 +379,8 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
ce->engine = engine;
ce->ops = engine->cops;
ce->sseu = engine->sseu;
- ce->ring = __intel_context_ring_size(SZ_4K);
+ ce->ring = NULL;
+ ce->ring_size = SZ_4K;
ewma_runtime_init(&ce->runtime.avg);
@@ -383,6 +392,22 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
mutex_init(&ce->pin_mutex);
+ spin_lock_init(&ce->guc_state.lock);
+ INIT_LIST_HEAD(&ce->guc_state.fences);
+
+ spin_lock_init(&ce->guc_active.lock);
+ INIT_LIST_HEAD(&ce->guc_active.requests);
+
+ ce->guc_id = GUC_INVALID_LRC_ID;
+ INIT_LIST_HEAD(&ce->guc_id_link);
+
+ /*
+ * Initialize fence to be complete as this is expected to be complete
+ * unless there is a pending schedule disable outstanding.
+ */
+ i915_sw_fence_init(&ce->guc_blocked, sw_fence_dummy_notify);
+ i915_sw_fence_commit(&ce->guc_blocked);
+
i915_active_init(&ce->active,
__intel_context_active, __intel_context_retire, 0);
}
@@ -397,28 +422,17 @@ void intel_context_fini(struct intel_context *ce)
i915_active_fini(&ce->active);
}
-static void i915_global_context_shrink(void)
-{
- kmem_cache_shrink(global.slab_ce);
-}
-
-static void i915_global_context_exit(void)
+void i915_context_module_exit(void)
{
- kmem_cache_destroy(global.slab_ce);
+ kmem_cache_destroy(slab_ce);
}
-static struct i915_global_context global = { {
- .shrink = i915_global_context_shrink,
- .exit = i915_global_context_exit,
-} };
-
-int __init i915_global_context_init(void)
+int __init i915_context_module_init(void)
{
- global.slab_ce = KMEM_CACHE(intel_context, SLAB_HWCACHE_ALIGN);
- if (!global.slab_ce)
+ slab_ce = KMEM_CACHE(intel_context, SLAB_HWCACHE_ALIGN);
+ if (!slab_ce)
return -ENOMEM;
- i915_global_register(&global.base);
return 0;
}
@@ -499,6 +513,26 @@ retry:
return rq;
}
+struct i915_request *intel_context_find_active_request(struct intel_context *ce)
+{
+ struct i915_request *rq, *active = NULL;
+ unsigned long flags;
+
+ GEM_BUG_ON(!intel_engine_uses_guc(ce->engine));
+
+ spin_lock_irqsave(&ce->guc_active.lock, flags);
+ list_for_each_entry_reverse(rq, &ce->guc_active.requests,
+ sched.link) {
+ if (i915_request_completed(rq))
+ break;
+
+ active = rq;
+ }
+ spin_unlock_irqrestore(&ce->guc_active.lock, flags);
+
+ return active;
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftest_context.c"
#endif
diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h
index f83a73a2b39f..c41098950746 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.h
+++ b/drivers/gpu/drm/i915/gt/intel_context.h
@@ -16,6 +16,7 @@
#include "intel_engine_types.h"
#include "intel_ring_types.h"
#include "intel_timeline_types.h"
+#include "i915_trace.h"
#define CE_TRACE(ce, fmt, ...) do { \
const struct intel_context *ce__ = (ce); \
@@ -30,6 +31,9 @@ void intel_context_init(struct intel_context *ce,
struct intel_engine_cs *engine);
void intel_context_fini(struct intel_context *ce);
+void i915_context_module_exit(void);
+int i915_context_module_init(void);
+
struct intel_context *
intel_context_create(struct intel_engine_cs *engine);
@@ -69,6 +73,13 @@ intel_context_is_pinned(struct intel_context *ce)
return atomic_read(&ce->pin_count);
}
+static inline void intel_context_cancel_request(struct intel_context *ce,
+ struct i915_request *rq)
+{
+ GEM_BUG_ON(!ce->ops->cancel_request);
+ return ce->ops->cancel_request(ce, rq);
+}
+
/**
* intel_context_unlock_pinned - Releases the earlier locking of 'pinned' status
* @ce - the context
@@ -113,7 +124,32 @@ static inline void __intel_context_pin(struct intel_context *ce)
atomic_inc(&ce->pin_count);
}
-void intel_context_unpin(struct intel_context *ce);
+void __intel_context_do_unpin(struct intel_context *ce, int sub);
+
+static inline void intel_context_sched_disable_unpin(struct intel_context *ce)
+{
+ __intel_context_do_unpin(ce, 2);
+}
+
+static inline void intel_context_unpin(struct intel_context *ce)
+{
+ if (!ce->ops->sched_disable) {
+ __intel_context_do_unpin(ce, 1);
+ } else {
+ /*
+ * Move ownership of this pin to the scheduling disable which is
+ * an async operation. When that operation completes the above
+ * intel_context_sched_disable_unpin is called potentially
+ * unpinning the context.
+ */
+ while (!atomic_add_unless(&ce->pin_count, -1, 1)) {
+ if (atomic_cmpxchg(&ce->pin_count, 1, 2) == 1) {
+ ce->ops->sched_disable(ce);
+ break;
+ }
+ }
+ }
+}
void intel_context_enter_engine(struct intel_context *ce);
void intel_context_exit_engine(struct intel_context *ce);
@@ -175,10 +211,8 @@ int intel_context_prepare_remote_request(struct intel_context *ce,
struct i915_request *intel_context_create_request(struct intel_context *ce);
-static inline struct intel_ring *__intel_context_ring_size(u64 sz)
-{
- return u64_to_ptr(struct intel_ring, sz);
-}
+struct i915_request *
+intel_context_find_active_request(struct intel_context *ce);
static inline bool intel_context_is_barrier(const struct intel_context *ce)
{
@@ -220,6 +254,18 @@ static inline bool intel_context_set_banned(struct intel_context *ce)
return test_and_set_bit(CONTEXT_BANNED, &ce->flags);
}
+static inline bool intel_context_ban(struct intel_context *ce,
+ struct i915_request *rq)
+{
+ bool ret = intel_context_set_banned(ce);
+
+ trace_intel_context_ban(ce);
+ if (ce->ops->ban)
+ ce->ops->ban(ce, rq);
+
+ return ret;
+}
+
static inline bool
intel_context_force_single_submission(const struct intel_context *ce)
{
diff --git a/drivers/gpu/drm/i915/gt/intel_context_param.c b/drivers/gpu/drm/i915/gt/intel_context_param.c
deleted file mode 100644
index 65dcd090245d..000000000000
--- a/drivers/gpu/drm/i915/gt/intel_context_param.c
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2019 Intel Corporation
- */
-
-#include "i915_active.h"
-#include "intel_context.h"
-#include "intel_context_param.h"
-#include "intel_ring.h"
-
-int intel_context_set_ring_size(struct intel_context *ce, long sz)
-{
- int err;
-
- if (intel_context_lock_pinned(ce))
- return -EINTR;
-
- err = i915_active_wait(&ce->active);
- if (err < 0)
- goto unlock;
-
- if (intel_context_is_pinned(ce)) {
- err = -EBUSY; /* In active use, come back later! */
- goto unlock;
- }
-
- if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
- struct intel_ring *ring;
-
- /* Replace the existing ringbuffer */
- ring = intel_engine_create_ring(ce->engine, sz);
- if (IS_ERR(ring)) {
- err = PTR_ERR(ring);
- goto unlock;
- }
-
- intel_ring_put(ce->ring);
- ce->ring = ring;
-
- /* Context image will be updated on next pin */
- } else {
- ce->ring = __intel_context_ring_size(sz);
- }
-
-unlock:
- intel_context_unlock_pinned(ce);
- return err;
-}
-
-long intel_context_get_ring_size(struct intel_context *ce)
-{
- long sz = (unsigned long)READ_ONCE(ce->ring);
-
- if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
- if (intel_context_lock_pinned(ce))
- return -EINTR;
-
- sz = ce->ring->size;
- intel_context_unlock_pinned(ce);
- }
-
- return sz;
-}
diff --git a/drivers/gpu/drm/i915/gt/intel_context_param.h b/drivers/gpu/drm/i915/gt/intel_context_param.h
index 3ecacc675f41..0c69cb42d075 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_param.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_param.h
@@ -10,14 +10,10 @@
#include "intel_context.h"
-int intel_context_set_ring_size(struct intel_context *ce, long sz);
-long intel_context_get_ring_size(struct intel_context *ce);
-
-static inline int
+static inline void
intel_context_set_watchdog_us(struct intel_context *ce, u64 timeout_us)
{
ce->watchdog.timeout_us = timeout_us;
- return 0;
}
#endif /* INTEL_CONTEXT_PARAM_H */
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h
index ed8c447a7346..e54351a170e2 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -13,12 +13,14 @@
#include <linux/types.h>
#include "i915_active_types.h"
+#include "i915_sw_fence.h"
#include "i915_utils.h"
#include "intel_engine_types.h"
#include "intel_sseu.h"
-#define CONTEXT_REDZONE POISON_INUSE
+#include "uc/intel_guc_fwif.h"
+#define CONTEXT_REDZONE POISON_INUSE
DECLARE_EWMA(runtime, 3, 8);
struct i915_gem_context;
@@ -35,16 +37,29 @@ struct intel_context_ops {
int (*alloc)(struct intel_context *ce);
+ void (*ban)(struct intel_context *ce, struct i915_request *rq);
+
int (*pre_pin)(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void **vaddr);
int (*pin)(struct intel_context *ce, void *vaddr);
void (*unpin)(struct intel_context *ce);
void (*post_unpin)(struct intel_context *ce);
+ void (*cancel_request)(struct intel_context *ce,
+ struct i915_request *rq);
+
void (*enter)(struct intel_context *ce);
void (*exit)(struct intel_context *ce);
+ void (*sched_disable)(struct intel_context *ce);
+
void (*reset)(struct intel_context *ce);
void (*destroy)(struct kref *kref);
+
+ /* virtual engine/context interface */
+ struct intel_context *(*create_virtual)(struct intel_engine_cs **engine,
+ unsigned int count);
+ struct intel_engine_cs *(*get_sibling)(struct intel_engine_cs *engine,
+ unsigned int sibling);
};
struct intel_context {
@@ -82,6 +97,7 @@ struct intel_context {
spinlock_t signal_lock; /* protects signals, the list of requests */
struct i915_vma *state;
+ u32 ring_size;
struct intel_ring *ring;
struct intel_timeline *timeline;
@@ -95,6 +111,7 @@ struct intel_context {
#define CONTEXT_BANNED 6
#define CONTEXT_FORCE_SINGLE_SUBMISSION 7
#define CONTEXT_NOPREEMPT 8
+#define CONTEXT_LRCA_DIRTY 9
struct {
u64 timeout_us;
@@ -136,6 +153,51 @@ struct intel_context {
struct intel_sseu sseu;
u8 wa_bb_page; /* if set, page num reserved for context workarounds */
+
+ struct {
+ /** lock: protects everything in guc_state */
+ spinlock_t lock;
+ /**
+ * sched_state: scheduling state of this context using GuC
+ * submission
+ */
+ u16 sched_state;
+ /*
+ * fences: maintains of list of requests that have a submit
+ * fence related to GuC submission
+ */
+ struct list_head fences;
+ } guc_state;
+
+ struct {
+ /** lock: protects everything in guc_active */
+ spinlock_t lock;
+ /** requests: active requests on this context */
+ struct list_head requests;
+ } guc_active;
+
+ /* GuC scheduling state flags that do not require a lock. */
+ atomic_t guc_sched_state_no_lock;
+
+ /* GuC LRC descriptor ID */
+ u16 guc_id;
+
+ /* GuC LRC descriptor reference count */
+ atomic_t guc_id_ref;
+
+ /*
+ * GuC ID link - in list when unpinned but guc_id still valid in GuC
+ */
+ struct list_head guc_id_link;
+
+ /* GuC context blocked fence */
+ struct i915_sw_fence guc_blocked;
+
+ /*
+ * GuC priority management
+ */
+ u8 guc_prio;
+ u32 guc_prio_count[GUC_CLIENT_PRIORITY_NUM];
};
#endif /* __INTEL_CONTEXT_TYPES__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h
index 8d9184920c51..87579affb952 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -19,7 +19,9 @@
#include "intel_workarounds.h"
struct drm_printer;
+struct intel_context;
struct intel_gt;
+struct lock_class_key;
/* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill,
* but keeps the logic simple. Indeed, the whole purpose of this macro is just
@@ -123,20 +125,6 @@ execlists_active(const struct intel_engine_execlists *execlists)
return active;
}
-static inline void
-execlists_active_lock_bh(struct intel_engine_execlists *execlists)
-{
- local_bh_disable(); /* prevent local softirq and lock recursion */
- tasklet_lock(&execlists->tasklet);
-}
-
-static inline void
-execlists_active_unlock_bh(struct intel_engine_execlists *execlists)
-{
- tasklet_unlock(&execlists->tasklet);
- local_bh_enable(); /* restore softirq, and kick ksoftirqd! */
-}
-
struct i915_request *
execlists_unwind_incomplete_requests(struct intel_engine_execlists *execlists);
@@ -186,11 +174,12 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
#define I915_GEM_HWS_PREEMPT_ADDR (I915_GEM_HWS_PREEMPT * sizeof(u32))
#define I915_GEM_HWS_SEQNO 0x40
#define I915_GEM_HWS_SEQNO_ADDR (I915_GEM_HWS_SEQNO * sizeof(u32))
+#define I915_GEM_HWS_MIGRATE (0x42 * sizeof(u32))
#define I915_GEM_HWS_SCRATCH 0x80
#define I915_HWS_CSB_BUF0_INDEX 0x10
#define I915_HWS_CSB_WRITE_INDEX 0x1f
-#define CNL_HWS_CSB_WRITE_INDEX 0x2f
+#define ICL_HWS_CSB_WRITE_INDEX 0x2f
void intel_engine_stop(struct intel_engine_cs *engine);
void intel_engine_cleanup(struct intel_engine_cs *engine);
@@ -223,6 +212,9 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine,
void intel_engine_init_execlists(struct intel_engine_cs *engine);
+bool intel_engine_irq_enable(struct intel_engine_cs *engine);
+void intel_engine_irq_disable(struct intel_engine_cs *engine);
+
static inline void __intel_engine_reset(struct intel_engine_cs *engine,
bool stalled)
{
@@ -248,17 +240,27 @@ __printf(3, 4)
void intel_engine_dump(struct intel_engine_cs *engine,
struct drm_printer *m,
const char *header, ...);
+void intel_engine_dump_active_requests(struct list_head *requests,
+ struct i915_request *hung_rq,
+ struct drm_printer *m);
ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine,
ktime_t *now);
struct i915_request *
-intel_engine_find_active_request(struct intel_engine_cs *engine);
+intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine);
u32 intel_engine_context_size(struct intel_gt *gt, u8 class);
+struct intel_context *
+intel_engine_create_pinned_context(struct intel_engine_cs *engine,
+ struct i915_address_space *vm,
+ unsigned int ring_size,
+ unsigned int hwsp,
+ struct lock_class_key *key,
+ const char *name);
+
+void intel_engine_destroy_pinned_context(struct intel_context *ce);
-void intel_engine_init_active(struct intel_engine_cs *engine,
- unsigned int subclass);
#define ENGINE_PHYSICAL 0
#define ENGINE_MOCK 1
#define ENGINE_VIRTUAL 2
@@ -277,13 +279,60 @@ intel_engine_has_preempt_reset(const struct intel_engine_cs *engine)
return intel_engine_has_preemption(engine);
}
+struct intel_context *
+intel_engine_create_virtual(struct intel_engine_cs **siblings,
+ unsigned int count);
+
+static inline bool
+intel_virtual_engine_has_heartbeat(const struct intel_engine_cs *engine)
+{
+ /*
+ * For non-GuC submission we expect the back-end to look at the
+ * heartbeat status of the actual physical engine that the work
+ * has been (or is being) scheduled on, so we should only reach
+ * here with GuC submission enabled.
+ */
+ GEM_BUG_ON(!intel_engine_uses_guc(engine));
+
+ return intel_guc_virtual_engine_has_heartbeat(engine);
+}
+
static inline bool
intel_engine_has_heartbeat(const struct intel_engine_cs *engine)
{
if (!IS_ACTIVE(CONFIG_DRM_I915_HEARTBEAT_INTERVAL))
return false;
- return READ_ONCE(engine->props.heartbeat_interval_ms);
+ if (intel_engine_is_virtual(engine))
+ return intel_virtual_engine_has_heartbeat(engine);
+ else
+ return READ_ONCE(engine->props.heartbeat_interval_ms);
+}
+
+static inline struct intel_engine_cs *
+intel_engine_get_sibling(struct intel_engine_cs *engine, unsigned int sibling)
+{
+ GEM_BUG_ON(!intel_engine_is_virtual(engine));
+ return engine->cops->get_sibling(engine, sibling);
+}
+
+static inline void
+intel_engine_set_hung_context(struct intel_engine_cs *engine,
+ struct intel_context *ce)
+{
+ engine->hung_ce = ce;
+}
+
+static inline void
+intel_engine_clear_hung_context(struct intel_engine_cs *engine)
+{
+ intel_engine_set_hung_context(engine, NULL);
+}
+
+static inline struct intel_context *
+intel_engine_get_hung_context(struct intel_engine_cs *engine)
+{
+ return engine->hung_ce;
}
#endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 7f03df236613..0d9105a31d84 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -35,14 +35,12 @@
#define DEFAULT_LR_CONTEXT_RENDER_SIZE (22 * PAGE_SIZE)
#define GEN8_LR_CONTEXT_RENDER_SIZE (20 * PAGE_SIZE)
#define GEN9_LR_CONTEXT_RENDER_SIZE (22 * PAGE_SIZE)
-#define GEN10_LR_CONTEXT_RENDER_SIZE (18 * PAGE_SIZE)
#define GEN11_LR_CONTEXT_RENDER_SIZE (14 * PAGE_SIZE)
#define GEN8_LR_CONTEXT_OTHER_SIZE ( 2 * PAGE_SIZE)
#define MAX_MMIO_BASES 3
struct engine_info {
- unsigned int hw_id;
u8 class;
u8 instance;
/* mmio bases table *must* be sorted in reverse graphics_ver order */
@@ -54,7 +52,6 @@ struct engine_info {
static const struct engine_info intel_engines[] = {
[RCS0] = {
- .hw_id = RCS0_HW,
.class = RENDER_CLASS,
.instance = 0,
.mmio_bases = {
@@ -62,7 +59,6 @@ static const struct engine_info intel_engines[] = {
},
},
[BCS0] = {
- .hw_id = BCS0_HW,
.class = COPY_ENGINE_CLASS,
.instance = 0,
.mmio_bases = {
@@ -70,7 +66,6 @@ static const struct engine_info intel_engines[] = {
},
},
[VCS0] = {
- .hw_id = VCS0_HW,
.class = VIDEO_DECODE_CLASS,
.instance = 0,
.mmio_bases = {
@@ -80,7 +75,6 @@ static const struct engine_info intel_engines[] = {
},
},
[VCS1] = {
- .hw_id = VCS1_HW,
.class = VIDEO_DECODE_CLASS,
.instance = 1,
.mmio_bases = {
@@ -89,7 +83,6 @@ static const struct engine_info intel_engines[] = {
},
},
[VCS2] = {
- .hw_id = VCS2_HW,
.class = VIDEO_DECODE_CLASS,
.instance = 2,
.mmio_bases = {
@@ -97,15 +90,41 @@ static const struct engine_info intel_engines[] = {
},
},
[VCS3] = {
- .hw_id = VCS3_HW,
.class = VIDEO_DECODE_CLASS,
.instance = 3,
.mmio_bases = {
{ .graphics_ver = 11, .base = GEN11_BSD4_RING_BASE }
},
},
+ [VCS4] = {
+ .class = VIDEO_DECODE_CLASS,
+ .instance = 4,
+ .mmio_bases = {
+ { .graphics_ver = 12, .base = XEHP_BSD5_RING_BASE }
+ },
+ },
+ [VCS5] = {
+ .class = VIDEO_DECODE_CLASS,
+ .instance = 5,
+ .mmio_bases = {
+ { .graphics_ver = 12, .base = XEHP_BSD6_RING_BASE }
+ },
+ },
+ [VCS6] = {
+ .class = VIDEO_DECODE_CLASS,
+ .instance = 6,
+ .mmio_bases = {
+ { .graphics_ver = 12, .base = XEHP_BSD7_RING_BASE }
+ },
+ },
+ [VCS7] = {
+ .class = VIDEO_DECODE_CLASS,
+ .instance = 7,
+ .mmio_bases = {
+ { .graphics_ver = 12, .base = XEHP_BSD8_RING_BASE }
+ },
+ },
[VECS0] = {
- .hw_id = VECS0_HW,
.class = VIDEO_ENHANCEMENT_CLASS,
.instance = 0,
.mmio_bases = {
@@ -114,13 +133,26 @@ static const struct engine_info intel_engines[] = {
},
},
[VECS1] = {
- .hw_id = VECS1_HW,
.class = VIDEO_ENHANCEMENT_CLASS,
.instance = 1,
.mmio_bases = {
{ .graphics_ver = 11, .base = GEN11_VEBOX2_RING_BASE }
},
},
+ [VECS2] = {
+ .class = VIDEO_ENHANCEMENT_CLASS,
+ .instance = 2,
+ .mmio_bases = {
+ { .graphics_ver = 12, .base = XEHP_VEBOX3_RING_BASE }
+ },
+ },
+ [VECS3] = {
+ .class = VIDEO_ENHANCEMENT_CLASS,
+ .instance = 3,
+ .mmio_bases = {
+ { .graphics_ver = 12, .base = XEHP_VEBOX4_RING_BASE }
+ },
+ },
};
/**
@@ -153,8 +185,6 @@ u32 intel_engine_context_size(struct intel_gt *gt, u8 class)
case 12:
case 11:
return GEN11_LR_CONTEXT_RENDER_SIZE;
- case 10:
- return GEN10_LR_CONTEXT_RENDER_SIZE;
case 9:
return GEN9_LR_CONTEXT_RENDER_SIZE;
case 8:
@@ -269,6 +299,8 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
BUILD_BUG_ON(MAX_ENGINE_CLASS >= BIT(GEN11_ENGINE_CLASS_WIDTH));
BUILD_BUG_ON(MAX_ENGINE_INSTANCE >= BIT(GEN11_ENGINE_INSTANCE_WIDTH));
+ BUILD_BUG_ON(I915_MAX_VCS > (MAX_ENGINE_INSTANCE + 1));
+ BUILD_BUG_ON(I915_MAX_VECS > (MAX_ENGINE_INSTANCE + 1));
if (GEM_DEBUG_WARN_ON(id >= ARRAY_SIZE(gt->engine)))
return -EINVAL;
@@ -294,7 +326,6 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
engine->i915 = i915;
engine->gt = gt;
engine->uncore = gt->uncore;
- engine->hw_id = info->hw_id;
guc_class = engine_class_to_guc_class(info->class);
engine->guc_id = MAKE_GUC_ID(guc_class, info->instance);
engine->mmio_base = __engine_mmio_base(i915, info->mmio_bases);
@@ -328,9 +359,6 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
if (engine->context_size)
DRIVER_CAPS(i915)->has_logical_contexts = true;
- /* Nothing to do here, execute in order of dependencies */
- engine->schedule = NULL;
-
ewma__engine_latency_init(&engine->latency);
seqcount_init(&engine->stats.lock);
@@ -445,6 +473,28 @@ void intel_engines_free(struct intel_gt *gt)
}
}
+static
+bool gen11_vdbox_has_sfc(struct drm_i915_private *i915,
+ unsigned int physical_vdbox,
+ unsigned int logical_vdbox, u16 vdbox_mask)
+{
+ /*
+ * In Gen11, only even numbered logical VDBOXes are hooked
+ * up to an SFC (Scaler & Format Converter) unit.
+ * In Gen12, Even numbered physical instance always are connected
+ * to an SFC. Odd numbered physical instances have SFC only if
+ * previous even instance is fused off.
+ */
+ if (GRAPHICS_VER(i915) == 12)
+ return (physical_vdbox % 2 == 0) ||
+ !(BIT(physical_vdbox - 1) & vdbox_mask);
+ else if (GRAPHICS_VER(i915) == 11)
+ return logical_vdbox % 2 == 0;
+
+ MISSING_CASE(GRAPHICS_VER(i915));
+ return false;
+}
+
/*
* Determine which engines are fused off in our particular hardware.
* Note that we have a catch-22 situation where we need to be able to access
@@ -471,7 +521,14 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt)
if (GRAPHICS_VER(i915) < 11)
return info->engine_mask;
- media_fuse = ~intel_uncore_read(uncore, GEN11_GT_VEBOX_VDBOX_DISABLE);
+ /*
+ * On newer platforms the fusing register is called 'enable' and has
+ * enable semantics, while on older platforms it is called 'disable'
+ * and bits have disable semantices.
+ */
+ media_fuse = intel_uncore_read(uncore, GEN11_GT_VEBOX_VDBOX_DISABLE);
+ if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
+ media_fuse = ~media_fuse;
vdbox_mask = media_fuse & GEN11_GT_VDBOX_DISABLE_MASK;
vebox_mask = (media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >>
@@ -489,13 +546,9 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt)
continue;
}
- /*
- * In Gen11, only even numbered logical VDBOXes are
- * hooked up to an SFC (Scaler & Format Converter) unit.
- * In TGL each VDBOX has access to an SFC.
- */
- if (GRAPHICS_VER(i915) >= 12 || logical_vdbox++ % 2 == 0)
+ if (gen11_vdbox_has_sfc(i915, i, logical_vdbox, vdbox_mask))
gt->info.vdbox_sfc_access |= BIT(i);
+ logical_vdbox++;
}
drm_dbg(&i915->drm, "vdbox enable: %04x, instances: %04lx\n",
vdbox_mask, VDBOX_MASK(gt));
@@ -585,9 +638,6 @@ void intel_engine_init_execlists(struct intel_engine_cs *engine)
memset(execlists->pending, 0, sizeof(execlists->pending));
execlists->active =
memset(execlists->inflight, 0, sizeof(execlists->inflight));
-
- execlists->queue_priority_hint = INT_MIN;
- execlists->queue = RB_ROOT_CACHED;
}
static void cleanup_status_page(struct intel_engine_cs *engine)
@@ -714,11 +764,17 @@ static int engine_setup_common(struct intel_engine_cs *engine)
goto err_status;
}
+ engine->sched_engine = i915_sched_engine_create(ENGINE_PHYSICAL);
+ if (!engine->sched_engine) {
+ err = -ENOMEM;
+ goto err_sched_engine;
+ }
+ engine->sched_engine->private_data = engine;
+
err = intel_engine_init_cmd_parser(engine);
if (err)
goto err_cmd_parser;
- intel_engine_init_active(engine, ENGINE_PHYSICAL);
intel_engine_init_execlists(engine);
intel_engine_init__pm(engine);
intel_engine_init_retire(engine);
@@ -737,7 +793,9 @@ static int engine_setup_common(struct intel_engine_cs *engine)
return 0;
err_cmd_parser:
- intel_breadcrumbs_free(engine->breadcrumbs);
+ i915_sched_engine_put(engine->sched_engine);
+err_sched_engine:
+ intel_breadcrumbs_put(engine->breadcrumbs);
err_status:
cleanup_status_page(engine);
return err;
@@ -775,11 +833,11 @@ static int measure_breadcrumb_dw(struct intel_context *ce)
frame->rq.ring = &frame->ring;
mutex_lock(&ce->timeline->mutex);
- spin_lock_irq(&engine->active.lock);
+ spin_lock_irq(&engine->sched_engine->lock);
dw = engine->emit_fini_breadcrumb(&frame->rq, frame->cs) - frame->cs;
- spin_unlock_irq(&engine->active.lock);
+ spin_unlock_irq(&engine->sched_engine->lock);
mutex_unlock(&ce->timeline->mutex);
GEM_BUG_ON(dw & 1); /* RING_TAIL must be qword aligned */
@@ -788,33 +846,13 @@ static int measure_breadcrumb_dw(struct intel_context *ce)
return dw;
}
-void
-intel_engine_init_active(struct intel_engine_cs *engine, unsigned int subclass)
-{
- INIT_LIST_HEAD(&engine->active.requests);
- INIT_LIST_HEAD(&engine->active.hold);
-
- spin_lock_init(&engine->active.lock);
- lockdep_set_subclass(&engine->active.lock, subclass);
-
- /*
- * Due to an interesting quirk in lockdep's internal debug tracking,
- * after setting a subclass we must ensure the lock is used. Otherwise,
- * nr_unused_locks is incremented once too often.
- */
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- local_irq_disable();
- lock_map_acquire(&engine->active.lock.dep_map);
- lock_map_release(&engine->active.lock.dep_map);
- local_irq_enable();
-#endif
-}
-
-static struct intel_context *
-create_pinned_context(struct intel_engine_cs *engine,
- unsigned int hwsp,
- struct lock_class_key *key,
- const char *name)
+struct intel_context *
+intel_engine_create_pinned_context(struct intel_engine_cs *engine,
+ struct i915_address_space *vm,
+ unsigned int ring_size,
+ unsigned int hwsp,
+ struct lock_class_key *key,
+ const char *name)
{
struct intel_context *ce;
int err;
@@ -825,6 +863,11 @@ create_pinned_context(struct intel_engine_cs *engine,
__set_bit(CONTEXT_BARRIER_BIT, &ce->flags);
ce->timeline = page_pack_bits(NULL, hwsp);
+ ce->ring = NULL;
+ ce->ring_size = ring_size;
+
+ i915_vm_put(ce->vm);
+ ce->vm = i915_vm_get(vm);
err = intel_context_pin(ce); /* perma-pin so it is always available */
if (err) {
@@ -843,7 +886,7 @@ create_pinned_context(struct intel_engine_cs *engine,
return ce;
}
-static void destroy_pinned_context(struct intel_context *ce)
+void intel_engine_destroy_pinned_context(struct intel_context *ce)
{
struct intel_engine_cs *engine = ce->engine;
struct i915_vma *hwsp = engine->status_page.vma;
@@ -863,8 +906,9 @@ create_kernel_context(struct intel_engine_cs *engine)
{
static struct lock_class_key kernel;
- return create_pinned_context(engine, I915_GEM_HWS_SEQNO_ADDR,
- &kernel, "kernel_context");
+ return intel_engine_create_pinned_context(engine, engine->gt->vm, SZ_4K,
+ I915_GEM_HWS_SEQNO_ADDR,
+ &kernel, "kernel_context");
}
/**
@@ -907,7 +951,7 @@ static int engine_init_common(struct intel_engine_cs *engine)
return 0;
err_context:
- destroy_pinned_context(ce);
+ intel_engine_destroy_pinned_context(ce);
return ret;
}
@@ -957,10 +1001,10 @@ int intel_engines_init(struct intel_gt *gt)
*/
void intel_engine_cleanup_common(struct intel_engine_cs *engine)
{
- GEM_BUG_ON(!list_empty(&engine->active.requests));
- tasklet_kill(&engine->execlists.tasklet); /* flush the callback */
+ GEM_BUG_ON(!list_empty(&engine->sched_engine->requests));
- intel_breadcrumbs_free(engine->breadcrumbs);
+ i915_sched_engine_put(engine->sched_engine);
+ intel_breadcrumbs_put(engine->breadcrumbs);
intel_engine_fini_retire(engine);
intel_engine_cleanup_cmd_parser(engine);
@@ -969,7 +1013,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
fput(engine->default_state);
if (engine->kernel_context)
- destroy_pinned_context(engine->kernel_context);
+ intel_engine_destroy_pinned_context(engine->kernel_context);
GEM_BUG_ON(!llist_empty(&engine->barrier_tasks));
cleanup_status_page(engine);
@@ -1105,45 +1149,8 @@ static u32
read_subslice_reg(const struct intel_engine_cs *engine,
int slice, int subslice, i915_reg_t reg)
{
- struct drm_i915_private *i915 = engine->i915;
- struct intel_uncore *uncore = engine->uncore;
- u32 mcr_mask, mcr_ss, mcr, old_mcr, val;
- enum forcewake_domains fw_domains;
-
- if (GRAPHICS_VER(i915) >= 11) {
- mcr_mask = GEN11_MCR_SLICE_MASK | GEN11_MCR_SUBSLICE_MASK;
- mcr_ss = GEN11_MCR_SLICE(slice) | GEN11_MCR_SUBSLICE(subslice);
- } else {
- mcr_mask = GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK;
- mcr_ss = GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice);
- }
-
- fw_domains = intel_uncore_forcewake_for_reg(uncore, reg,
- FW_REG_READ);
- fw_domains |= intel_uncore_forcewake_for_reg(uncore,
- GEN8_MCR_SELECTOR,
- FW_REG_READ | FW_REG_WRITE);
-
- spin_lock_irq(&uncore->lock);
- intel_uncore_forcewake_get__locked(uncore, fw_domains);
-
- old_mcr = mcr = intel_uncore_read_fw(uncore, GEN8_MCR_SELECTOR);
-
- mcr &= ~mcr_mask;
- mcr |= mcr_ss;
- intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr);
-
- val = intel_uncore_read_fw(uncore, reg);
-
- mcr &= ~mcr_mask;
- mcr |= old_mcr & mcr_mask;
-
- intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr);
-
- intel_uncore_forcewake_put__locked(uncore, fw_domains);
- spin_unlock_irq(&uncore->lock);
-
- return val;
+ return intel_uncore_read_with_mcr_steering(engine->uncore, reg,
+ slice, subslice);
}
/* NB: please notice the memset */
@@ -1243,7 +1250,7 @@ static bool ring_is_idle(struct intel_engine_cs *engine)
void __intel_engine_flush_submission(struct intel_engine_cs *engine, bool sync)
{
- struct tasklet_struct *t = &engine->execlists.tasklet;
+ struct tasklet_struct *t = &engine->sched_engine->tasklet;
if (!t->callback)
return;
@@ -1283,7 +1290,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine)
intel_engine_flush_submission(engine);
/* ELSP is empty, but there are ready requests? E.g. after reset */
- if (!RB_EMPTY_ROOT(&engine->execlists.queue.rb_root))
+ if (!i915_sched_engine_is_empty(engine->sched_engine))
return false;
/* Ring stopped? */
@@ -1314,6 +1321,30 @@ bool intel_engines_are_idle(struct intel_gt *gt)
return true;
}
+bool intel_engine_irq_enable(struct intel_engine_cs *engine)
+{
+ if (!engine->irq_enable)
+ return false;
+
+ /* Caller disables interrupts */
+ spin_lock(&engine->gt->irq_lock);
+ engine->irq_enable(engine);
+ spin_unlock(&engine->gt->irq_lock);
+
+ return true;
+}
+
+void intel_engine_irq_disable(struct intel_engine_cs *engine)
+{
+ if (!engine->irq_disable)
+ return;
+
+ /* Caller disables interrupts */
+ spin_lock(&engine->gt->irq_lock);
+ engine->irq_disable(engine);
+ spin_unlock(&engine->gt->irq_lock);
+}
+
void intel_engines_reset_default_submission(struct intel_gt *gt)
{
struct intel_engine_cs *engine;
@@ -1349,7 +1380,7 @@ static struct intel_timeline *get_timeline(struct i915_request *rq)
struct intel_timeline *tl;
/*
- * Even though we are holding the engine->active.lock here, there
+ * Even though we are holding the engine->sched_engine->lock here, there
* is no control over the submission queue per-se and we are
* inspecting the active state at a random point in time, with an
* unknown queue. Play safe and make sure the timeline remains valid.
@@ -1504,8 +1535,8 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
drm_printf(m, "\tExeclist tasklet queued? %s (%s), preempt? %s, timeslice? %s\n",
yesno(test_bit(TASKLET_STATE_SCHED,
- &engine->execlists.tasklet.state)),
- enableddisabled(!atomic_read(&engine->execlists.tasklet.count)),
+ &engine->sched_engine->tasklet.state)),
+ enableddisabled(!atomic_read(&engine->sched_engine->tasklet.count)),
repr_timer(&engine->execlists.preempt),
repr_timer(&engine->execlists.timer));
@@ -1529,7 +1560,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
idx, hws[idx * 2], hws[idx * 2 + 1]);
}
- execlists_active_lock_bh(execlists);
+ i915_sched_engine_active_lock_bh(engine->sched_engine);
rcu_read_lock();
for (port = execlists->active; (rq = *port); port++) {
char hdr[160];
@@ -1560,7 +1591,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
i915_request_show(m, rq, hdr, 0);
}
rcu_read_unlock();
- execlists_active_unlock_bh(execlists);
+ i915_sched_engine_active_unlock_bh(engine->sched_engine);
} else if (GRAPHICS_VER(dev_priv) > 6) {
drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
ENGINE_READ(engine, RING_PP_DIR_BASE));
@@ -1650,6 +1681,98 @@ static void print_properties(struct intel_engine_cs *engine,
read_ul(&engine->defaults, p->offset));
}
+static void engine_dump_request(struct i915_request *rq, struct drm_printer *m, const char *msg)
+{
+ struct intel_timeline *tl = get_timeline(rq);
+
+ i915_request_show(m, rq, msg, 0);
+
+ drm_printf(m, "\t\tring->start: 0x%08x\n",
+ i915_ggtt_offset(rq->ring->vma));
+ drm_printf(m, "\t\tring->head: 0x%08x\n",
+ rq->ring->head);
+ drm_printf(m, "\t\tring->tail: 0x%08x\n",
+ rq->ring->tail);
+ drm_printf(m, "\t\tring->emit: 0x%08x\n",
+ rq->ring->emit);
+ drm_printf(m, "\t\tring->space: 0x%08x\n",
+ rq->ring->space);
+
+ if (tl) {
+ drm_printf(m, "\t\tring->hwsp: 0x%08x\n",
+ tl->hwsp_offset);
+ intel_timeline_put(tl);
+ }
+
+ print_request_ring(m, rq);
+
+ if (rq->context->lrc_reg_state) {
+ drm_printf(m, "Logical Ring Context:\n");
+ hexdump(m, rq->context->lrc_reg_state, PAGE_SIZE);
+ }
+}
+
+void intel_engine_dump_active_requests(struct list_head *requests,
+ struct i915_request *hung_rq,
+ struct drm_printer *m)
+{
+ struct i915_request *rq;
+ const char *msg;
+ enum i915_request_state state;
+
+ list_for_each_entry(rq, requests, sched.link) {
+ if (rq == hung_rq)
+ continue;
+
+ state = i915_test_request_state(rq);
+ if (state < I915_REQUEST_QUEUED)
+ continue;
+
+ if (state == I915_REQUEST_ACTIVE)
+ msg = "\t\tactive on engine";
+ else
+ msg = "\t\tactive in queue";
+
+ engine_dump_request(rq, m, msg);
+ }
+}
+
+static void engine_dump_active_requests(struct intel_engine_cs *engine, struct drm_printer *m)
+{
+ struct i915_request *hung_rq = NULL;
+ struct intel_context *ce;
+ bool guc;
+
+ /*
+ * No need for an engine->irq_seqno_barrier() before the seqno reads.
+ * The GPU is still running so requests are still executing and any
+ * hardware reads will be out of date by the time they are reported.
+ * But the intention here is just to report an instantaneous snapshot
+ * so that's fine.
+ */
+ lockdep_assert_held(&engine->sched_engine->lock);
+
+ drm_printf(m, "\tRequests:\n");
+
+ guc = intel_uc_uses_guc_submission(&engine->gt->uc);
+ if (guc) {
+ ce = intel_engine_get_hung_context(engine);
+ if (ce)
+ hung_rq = intel_context_find_active_request(ce);
+ } else {
+ hung_rq = intel_engine_execlist_find_hung_request(engine);
+ }
+
+ if (hung_rq)
+ engine_dump_request(hung_rq, m, "\t\thung");
+
+ if (guc)
+ intel_guc_dump_active_requests(engine, hung_rq, m);
+ else
+ intel_engine_dump_active_requests(&engine->sched_engine->requests,
+ hung_rq, m);
+}
+
void intel_engine_dump(struct intel_engine_cs *engine,
struct drm_printer *m,
const char *header, ...)
@@ -1694,41 +1817,12 @@ void intel_engine_dump(struct intel_engine_cs *engine,
i915_reset_count(error));
print_properties(engine, m);
- drm_printf(m, "\tRequests:\n");
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
+ engine_dump_active_requests(engine, m);
- spin_lock_irqsave(&engine->active.lock, flags);
- rq = intel_engine_find_active_request(engine);
- if (rq) {
- struct intel_timeline *tl = get_timeline(rq);
-
- i915_request_show(m, rq, "\t\tactive ", 0);
-
- drm_printf(m, "\t\tring->start: 0x%08x\n",
- i915_ggtt_offset(rq->ring->vma));
- drm_printf(m, "\t\tring->head: 0x%08x\n",
- rq->ring->head);
- drm_printf(m, "\t\tring->tail: 0x%08x\n",
- rq->ring->tail);
- drm_printf(m, "\t\tring->emit: 0x%08x\n",
- rq->ring->emit);
- drm_printf(m, "\t\tring->space: 0x%08x\n",
- rq->ring->space);
-
- if (tl) {
- drm_printf(m, "\t\tring->hwsp: 0x%08x\n",
- tl->hwsp_offset);
- intel_timeline_put(tl);
- }
-
- print_request_ring(m, rq);
-
- if (rq->context->lrc_reg_state) {
- drm_printf(m, "Logical Ring Context:\n");
- hexdump(m, rq->context->lrc_reg_state, PAGE_SIZE);
- }
- }
- drm_printf(m, "\tOn hold?: %lu\n", list_count(&engine->active.hold));
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ drm_printf(m, "\tOn hold?: %lu\n",
+ list_count(&engine->sched_engine->hold));
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base);
wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm);
@@ -1785,19 +1879,33 @@ ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, ktime_t *now)
return total;
}
-static bool match_ring(struct i915_request *rq)
+struct intel_context *
+intel_engine_create_virtual(struct intel_engine_cs **siblings,
+ unsigned int count)
{
- u32 ring = ENGINE_READ(rq->engine, RING_START);
+ if (count == 0)
+ return ERR_PTR(-EINVAL);
+
+ if (count == 1)
+ return intel_context_create(siblings[0]);
- return ring == i915_ggtt_offset(rq->ring->vma);
+ GEM_BUG_ON(!siblings[0]->cops->create_virtual);
+ return siblings[0]->cops->create_virtual(siblings, count);
}
struct i915_request *
-intel_engine_find_active_request(struct intel_engine_cs *engine)
+intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine)
{
struct i915_request *request, *active = NULL;
/*
+ * This search does not work in GuC submission mode. However, the GuC
+ * will report the hanging context directly to the driver itself. So
+ * the driver should never get here when in GuC mode.
+ */
+ GEM_BUG_ON(intel_uc_uses_guc_submission(&engine->gt->uc));
+
+ /*
* 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
@@ -1808,7 +1916,7 @@ intel_engine_find_active_request(struct intel_engine_cs *engine)
* At all other times, we must assume the GPU is still running, but
* we only care about the snapshot of this moment.
*/
- lockdep_assert_held(&engine->active.lock);
+ lockdep_assert_held(&engine->sched_engine->lock);
rcu_read_lock();
request = execlists_active(&engine->execlists);
@@ -1826,15 +1934,9 @@ intel_engine_find_active_request(struct intel_engine_cs *engine)
if (active)
return active;
- list_for_each_entry(request, &engine->active.requests, sched.link) {
- if (__i915_request_is_complete(request))
- continue;
-
- if (!__i915_request_has_started(request))
- continue;
-
- /* More than one preemptible request may match! */
- if (!match_ring(request))
+ list_for_each_entry(request, &engine->sched_engine->requests,
+ sched.link) {
+ if (i915_test_request_state(request) != I915_REQUEST_ACTIVE)
continue;
active = request;
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
index b99ac41695f3..74775ae961b2 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
@@ -70,12 +70,38 @@ static void show_heartbeat(const struct i915_request *rq,
{
struct drm_printer p = drm_debug_printer("heartbeat");
- intel_engine_dump(engine, &p,
- "%s heartbeat {seqno:%llx:%lld, prio:%d} not ticking\n",
- engine->name,
- rq->fence.context,
- rq->fence.seqno,
- rq->sched.attr.priority);
+ if (!rq) {
+ intel_engine_dump(engine, &p,
+ "%s heartbeat not ticking\n",
+ engine->name);
+ } else {
+ intel_engine_dump(engine, &p,
+ "%s heartbeat {seqno:%llx:%lld, prio:%d} not ticking\n",
+ engine->name,
+ rq->fence.context,
+ rq->fence.seqno,
+ rq->sched.attr.priority);
+ }
+}
+
+static void
+reset_engine(struct intel_engine_cs *engine, struct i915_request *rq)
+{
+ if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
+ show_heartbeat(rq, engine);
+
+ if (intel_engine_uses_guc(engine))
+ /*
+ * GuC itself is toast or GuC's hang detection
+ * is disabled. Either way, need to find the
+ * hang culprit manually.
+ */
+ intel_guc_find_hung_context(engine);
+
+ intel_gt_handle_error(engine->gt, engine->mask,
+ I915_ERROR_CAPTURE,
+ "stopped heartbeat on %s",
+ engine->name);
}
static void heartbeat(struct work_struct *wrk)
@@ -102,6 +128,11 @@ static void heartbeat(struct work_struct *wrk)
if (intel_gt_is_wedged(engine->gt))
goto out;
+ if (i915_sched_engine_disabled(engine->sched_engine)) {
+ reset_engine(engine, engine->heartbeat.systole);
+ goto out;
+ }
+
if (engine->heartbeat.systole) {
long delay = READ_ONCE(engine->props.heartbeat_interval_ms);
@@ -121,7 +152,7 @@ static void heartbeat(struct work_struct *wrk)
* but all other contexts, including the kernel
* context are stuck waiting for the signal.
*/
- } else if (engine->schedule &&
+ } else if (engine->sched_engine->schedule &&
rq->sched.attr.priority < I915_PRIORITY_BARRIER) {
/*
* Gradually raise the priority of the heartbeat to
@@ -136,16 +167,10 @@ static void heartbeat(struct work_struct *wrk)
attr.priority = I915_PRIORITY_BARRIER;
local_bh_disable();
- engine->schedule(rq, &attr);
+ engine->sched_engine->schedule(rq, &attr);
local_bh_enable();
} else {
- if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
- show_heartbeat(rq, engine);
-
- intel_gt_handle_error(engine->gt, engine->mask,
- I915_ERROR_CAPTURE,
- "stopped heartbeat on %s",
- engine->name);
+ reset_engine(engine, rq);
}
rq->emitted_jiffies = jiffies;
@@ -194,6 +219,25 @@ void intel_engine_park_heartbeat(struct intel_engine_cs *engine)
i915_request_put(fetch_and_zero(&engine->heartbeat.systole));
}
+void intel_gt_unpark_heartbeats(struct intel_gt *gt)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ for_each_engine(engine, gt, id)
+ if (intel_engine_pm_is_awake(engine))
+ intel_engine_unpark_heartbeat(engine);
+}
+
+void intel_gt_park_heartbeats(struct intel_gt *gt)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ for_each_engine(engine, gt, id)
+ intel_engine_park_heartbeat(engine);
+}
+
void intel_engine_init_heartbeat(struct intel_engine_cs *engine)
{
INIT_DELAYED_WORK(&engine->heartbeat.work, heartbeat);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
index a488ea3e84a3..5da6d809a87a 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
@@ -7,6 +7,7 @@
#define INTEL_ENGINE_HEARTBEAT_H
struct intel_engine_cs;
+struct intel_gt;
void intel_engine_init_heartbeat(struct intel_engine_cs *engine);
@@ -16,6 +17,9 @@ int intel_engine_set_heartbeat(struct intel_engine_cs *engine,
void intel_engine_park_heartbeat(struct intel_engine_cs *engine);
void intel_engine_unpark_heartbeat(struct intel_engine_cs *engine);
+void intel_gt_park_heartbeats(struct intel_gt *gt);
+void intel_gt_unpark_heartbeats(struct intel_gt *gt);
+
int intel_engine_pulse(struct intel_engine_cs *engine);
int intel_engine_flush_barriers(struct intel_engine_cs *engine);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
index 47f4397095e5..1f07ac4e0672 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
@@ -275,13 +275,11 @@ static int __engine_park(struct intel_wakeref *wf)
intel_breadcrumbs_park(engine->breadcrumbs);
/* Must be reset upon idling, or we may miss the busy wakeup. */
- GEM_BUG_ON(engine->execlists.queue_priority_hint != INT_MIN);
+ GEM_BUG_ON(engine->sched_engine->queue_priority_hint != INT_MIN);
if (engine->park)
engine->park(engine);
- engine->execlists.no_priolist = false;
-
/* While gt calls i915_vma_parked(), we have to break the lock cycle */
intel_gt_pm_put_async(engine->gt);
return 0;
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index e113f93b3274..ed91bcff20eb 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -21,32 +21,20 @@
#include "i915_pmu.h"
#include "i915_priolist_types.h"
#include "i915_selftest.h"
-#include "intel_breadcrumbs_types.h"
#include "intel_sseu.h"
#include "intel_timeline_types.h"
#include "intel_uncore.h"
#include "intel_wakeref.h"
#include "intel_workarounds_types.h"
-/* Legacy HW Engine ID */
-
-#define RCS0_HW 0
-#define VCS0_HW 1
-#define BCS0_HW 2
-#define VECS0_HW 3
-#define VCS1_HW 4
-#define VCS2_HW 6
-#define VCS3_HW 7
-#define VECS1_HW 12
-
-/* Gen11+ HW Engine class + instance */
+/* HW Engine class + instance */
#define RENDER_CLASS 0
#define VIDEO_DECODE_CLASS 1
#define VIDEO_ENHANCEMENT_CLASS 2
#define COPY_ENGINE_CLASS 3
#define OTHER_CLASS 4
#define MAX_ENGINE_CLASS 4
-#define MAX_ENGINE_INSTANCE 3
+#define MAX_ENGINE_INSTANCE 7
#define I915_MAX_SLICES 3
#define I915_MAX_SUBSLICES 8
@@ -59,11 +47,13 @@ struct drm_i915_reg_table;
struct i915_gem_context;
struct i915_request;
struct i915_sched_attr;
+struct i915_sched_engine;
struct intel_gt;
struct intel_ring;
struct intel_uncore;
+struct intel_breadcrumbs;
-typedef u8 intel_engine_mask_t;
+typedef u32 intel_engine_mask_t;
#define ALL_ENGINES ((intel_engine_mask_t)~0ul)
struct intel_hw_status_page {
@@ -100,8 +90,8 @@ struct i915_ctx_workarounds {
struct i915_vma *vma;
};
-#define I915_MAX_VCS 4
-#define I915_MAX_VECS 2
+#define I915_MAX_VCS 8
+#define I915_MAX_VECS 4
/*
* Engine IDs definitions.
@@ -114,9 +104,15 @@ enum intel_engine_id {
VCS1,
VCS2,
VCS3,
+ VCS4,
+ VCS5,
+ VCS6,
+ VCS7,
#define _VCS(n) (VCS0 + (n))
VECS0,
VECS1,
+ VECS2,
+ VECS3,
#define _VECS(n) (VECS0 + (n))
I915_NUM_ENGINES
#define INVALID_ENGINE ((enum intel_engine_id)-1)
@@ -138,11 +134,6 @@ struct st_preempt_hang {
*/
struct intel_engine_execlists {
/**
- * @tasklet: softirq tasklet for bottom handler
- */
- struct tasklet_struct tasklet;
-
- /**
* @timer: kick the current context if its timeslice expires
*/
struct timer_list timer;
@@ -153,11 +144,6 @@ struct intel_engine_execlists {
struct timer_list preempt;
/**
- * @default_priolist: priority list for I915_PRIORITY_NORMAL
- */
- struct i915_priolist default_priolist;
-
- /**
* @ccid: identifier for contexts submitted to this engine
*/
u32 ccid;
@@ -192,11 +178,6 @@ struct intel_engine_execlists {
u32 reset_ccid;
/**
- * @no_priolist: priority lists disabled
- */
- bool no_priolist;
-
- /**
* @submit_reg: gen-specific execlist submission register
* set to the ExecList Submission Port (elsp) register pre-Gen11 and to
* the ExecList Submission Queue Contents register array for Gen11+
@@ -238,23 +219,10 @@ struct intel_engine_execlists {
unsigned int port_mask;
/**
- * @queue_priority_hint: Highest pending priority.
- *
- * When we add requests into the queue, or adjust the priority of
- * executing requests, we compute the maximum priority of those
- * pending requests. We can then use this value to determine if
- * we need to preempt the executing requests to service the queue.
- * However, since the we may have recorded the priority of an inflight
- * request we wanted to preempt but since completed, at the time of
- * dequeuing the priority hint may no longer may match the highest
- * available request priority.
+ * @virtual: Queue of requets on a virtual engine, sorted by priority.
+ * Each RB entry is a struct i915_priolist containing a list of requests
+ * of the same priority.
*/
- int queue_priority_hint;
-
- /**
- * @queue: queue of requests, in priority lists
- */
- struct rb_root_cached queue;
struct rb_root_cached virtual;
/**
@@ -295,7 +263,6 @@ struct intel_engine_cs {
enum intel_engine_id id;
enum intel_engine_id legacy_idx;
- unsigned int hw_id;
unsigned int guc_id;
intel_engine_mask_t mask;
@@ -326,15 +293,13 @@ struct intel_engine_cs {
struct intel_sseu sseu;
- struct {
- spinlock_t lock;
- struct list_head requests;
- struct list_head hold; /* ready requests, but on hold */
- } active;
+ struct i915_sched_engine *sched_engine;
/* keep a request in reserve for a [pm] barrier under oom */
struct i915_request *request_pool;
+ struct intel_context *hung_ce;
+
struct llist_head barrier_tasks;
struct intel_context *kernel_context; /* pinned */
@@ -419,6 +384,8 @@ struct intel_engine_cs {
void (*park)(struct intel_engine_cs *engine);
void (*unpark)(struct intel_engine_cs *engine);
+ void (*bump_serial)(struct intel_engine_cs *engine);
+
void (*set_default_submission)(struct intel_engine_cs *engine);
const struct intel_context_ops *cops;
@@ -447,22 +414,13 @@ struct intel_engine_cs {
*/
void (*submit_request)(struct i915_request *rq);
- /*
- * Called on signaling of a SUBMIT_FENCE, passing along the signaling
- * request down to the bonded pairs.
- */
- void (*bond_execute)(struct i915_request *rq,
- struct dma_fence *signal);
+ void (*release)(struct intel_engine_cs *engine);
/*
- * Call when the priority on a request has changed and it and its
- * dependencies may need rescheduling. Note the request itself may
- * not be ready to run!
+ * Add / remove request from engine active tracking
*/
- void (*schedule)(struct i915_request *request,
- const struct i915_sched_attr *attr);
-
- void (*release)(struct intel_engine_cs *engine);
+ void (*add_active_request)(struct i915_request *rq);
+ void (*remove_active_request)(struct i915_request *rq);
struct intel_engine_execlists execlists;
@@ -485,6 +443,7 @@ struct intel_engine_cs {
#define I915_ENGINE_IS_VIRTUAL BIT(5)
#define I915_ENGINE_HAS_RELATIVE_MMIO BIT(6)
#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(7)
+#define I915_ENGINE_WANT_FORCED_PREEMPTION BIT(8)
unsigned int flags;
/*
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c
index 3cca7ea2d6ea..8f8bea08e734 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c
@@ -11,6 +11,7 @@
#include "intel_engine.h"
#include "intel_engine_user.h"
#include "intel_gt.h"
+#include "uc/intel_guc_submission.h"
struct intel_engine_cs *
intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
@@ -108,13 +109,16 @@ static void set_scheduler_caps(struct drm_i915_private *i915)
for_each_uabi_engine(engine, i915) { /* all engines must agree! */
int i;
- if (engine->schedule)
+ if (engine->sched_engine->schedule)
enabled |= (I915_SCHEDULER_CAP_ENABLED |
I915_SCHEDULER_CAP_PRIORITY);
else
disabled |= (I915_SCHEDULER_CAP_ENABLED |
I915_SCHEDULER_CAP_PRIORITY);
+ if (intel_uc_uses_guc_submission(&i915->gt.uc))
+ enabled |= I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP;
+
for (i = 0; i < ARRAY_SIZE(map); i++) {
if (engine->flags & BIT(map[i].engine))
enabled |= BIT(map[i].sched);
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index fc77592d88a9..de5f9c86b9a4 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -114,6 +114,7 @@
#include "gen8_engine_cs.h"
#include "intel_breadcrumbs.h"
#include "intel_context.h"
+#include "intel_engine_heartbeat.h"
#include "intel_engine_pm.h"
#include "intel_engine_stats.h"
#include "intel_execlists_submission.h"
@@ -153,6 +154,12 @@
#define GEN12_CSB_CTX_VALID(csb_dw) \
(FIELD_GET(GEN12_CSB_SW_CTX_ID_MASK, csb_dw) != GEN12_IDLE_CTX_ID)
+#define XEHP_CTX_STATUS_SWITCHED_TO_NEW_QUEUE BIT(1) /* upper csb dword */
+#define XEHP_CSB_SW_CTX_ID_MASK GENMASK(31, 10)
+#define XEHP_IDLE_CTX_ID 0xFFFF
+#define XEHP_CSB_CTX_VALID(csb_dw) \
+ (FIELD_GET(XEHP_CSB_SW_CTX_ID_MASK, csb_dw) != XEHP_IDLE_CTX_ID)
+
/* Typical size of the average request (2 pipecontrols and a MI_BB) */
#define EXECLISTS_REQUEST_SIZE 64 /* bytes */
@@ -182,18 +189,6 @@ struct virtual_engine {
int prio;
} nodes[I915_NUM_ENGINES];
- /*
- * Keep track of bonded pairs -- restrictions upon on our selection
- * of physical engines any particular request may be submitted to.
- * If we receive a submit-fence from a master engine, we will only
- * use one of sibling_mask physical engines.
- */
- struct ve_bond {
- const struct intel_engine_cs *master;
- intel_engine_mask_t sibling_mask;
- } *bonds;
- unsigned int num_bonds;
-
/* And finally, which physical engines this virtual engine maps onto. */
unsigned int num_siblings;
struct intel_engine_cs *siblings[];
@@ -205,6 +200,9 @@ static struct virtual_engine *to_virtual_engine(struct intel_engine_cs *engine)
return container_of(engine, struct virtual_engine, base);
}
+static struct intel_context *
+execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count);
+
static struct i915_request *
__active_request(const struct intel_timeline * const tl,
struct i915_request *rq,
@@ -273,11 +271,11 @@ static int effective_prio(const struct i915_request *rq)
return prio;
}
-static int queue_prio(const struct intel_engine_execlists *execlists)
+static int queue_prio(const struct i915_sched_engine *sched_engine)
{
struct rb_node *rb;
- rb = rb_first_cached(&execlists->queue);
+ rb = rb_first_cached(&sched_engine->queue);
if (!rb)
return INT_MIN;
@@ -318,14 +316,14 @@ static bool need_preempt(const struct intel_engine_cs *engine,
* to preserve FIFO ordering of dependencies.
*/
last_prio = max(effective_prio(rq), I915_PRIORITY_NORMAL - 1);
- if (engine->execlists.queue_priority_hint <= last_prio)
+ if (engine->sched_engine->queue_priority_hint <= last_prio)
return false;
/*
* Check against the first request in ELSP[1], it will, thanks to the
* power of PI, be the highest priority of that context.
*/
- if (!list_is_last(&rq->sched.link, &engine->active.requests) &&
+ if (!list_is_last(&rq->sched.link, &engine->sched_engine->requests) &&
rq_prio(list_next_entry(rq, sched.link)) > last_prio)
return true;
@@ -340,7 +338,7 @@ static bool need_preempt(const struct intel_engine_cs *engine,
* context, it's priority would not exceed ELSP[0] aka last_prio.
*/
return max(virtual_prio(&engine->execlists),
- queue_prio(&engine->execlists)) > last_prio;
+ queue_prio(engine->sched_engine)) > last_prio;
}
__maybe_unused static bool
@@ -367,10 +365,10 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
struct list_head *pl;
int prio = I915_PRIORITY_INVALID;
- lockdep_assert_held(&engine->active.lock);
+ lockdep_assert_held(&engine->sched_engine->lock);
list_for_each_entry_safe_reverse(rq, rn,
- &engine->active.requests,
+ &engine->sched_engine->requests,
sched.link) {
if (__i915_request_is_complete(rq)) {
list_del_init(&rq->sched.link);
@@ -382,9 +380,10 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
GEM_BUG_ON(rq_prio(rq) == I915_PRIORITY_INVALID);
if (rq_prio(rq) != prio) {
prio = rq_prio(rq);
- pl = i915_sched_lookup_priolist(engine, prio);
+ pl = i915_sched_lookup_priolist(engine->sched_engine,
+ prio);
}
- GEM_BUG_ON(RB_EMPTY_ROOT(&engine->execlists.queue.rb_root));
+ GEM_BUG_ON(i915_sched_engine_is_empty(engine->sched_engine));
list_move(&rq->sched.link, pl);
set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
@@ -489,6 +488,16 @@ __execlists_schedule_in(struct i915_request *rq)
/* Use a fixed tag for OA and friends */
GEM_BUG_ON(ce->tag <= BITS_PER_LONG);
ce->lrc.ccid = ce->tag;
+ } else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) {
+ /* We don't need a strict matching tag, just different values */
+ unsigned int tag = ffs(READ_ONCE(engine->context_tag));
+
+ GEM_BUG_ON(tag == 0 || tag >= BITS_PER_LONG);
+ clear_bit(tag - 1, &engine->context_tag);
+ ce->lrc.ccid = tag << (XEHP_SW_CTX_ID_SHIFT - 32);
+
+ BUILD_BUG_ON(BITS_PER_LONG > GEN12_MAX_CONTEXT_HW_ID);
+
} else {
/* We don't need a strict matching tag, just different values */
unsigned int tag = __ffs(engine->context_tag);
@@ -534,13 +543,13 @@ resubmit_virtual_request(struct i915_request *rq, struct virtual_engine *ve)
{
struct intel_engine_cs *engine = rq->engine;
- spin_lock_irq(&engine->active.lock);
+ spin_lock_irq(&engine->sched_engine->lock);
clear_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
WRITE_ONCE(rq->engine, &ve->base);
ve->base.submit_request(rq);
- spin_unlock_irq(&engine->active.lock);
+ spin_unlock_irq(&engine->sched_engine->lock);
}
static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
@@ -569,7 +578,7 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
resubmit_virtual_request(rq, ve);
if (READ_ONCE(ve->request))
- tasklet_hi_schedule(&ve->base.execlists.tasklet);
+ tasklet_hi_schedule(&ve->base.sched_engine->tasklet);
}
static void __execlists_schedule_out(struct i915_request * const rq,
@@ -579,7 +588,7 @@ static void __execlists_schedule_out(struct i915_request * const rq,
unsigned int ccid;
/*
- * NB process_csb() is not under the engine->active.lock and hence
+ * NB process_csb() is not under the engine->sched_engine->lock and hence
* schedule_out can race with schedule_in meaning that we should
* refrain from doing non-trivial work here.
*/
@@ -599,8 +608,14 @@ static void __execlists_schedule_out(struct i915_request * const rq,
intel_engine_add_retire(engine, ce->timeline);
ccid = ce->lrc.ccid;
- ccid >>= GEN11_SW_CTX_ID_SHIFT - 32;
- ccid &= GEN12_MAX_CONTEXT_HW_ID;
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) {
+ ccid >>= XEHP_SW_CTX_ID_SHIFT - 32;
+ ccid &= XEHP_MAX_CONTEXT_HW_ID;
+ } else {
+ ccid >>= GEN11_SW_CTX_ID_SHIFT - 32;
+ ccid &= GEN12_MAX_CONTEXT_HW_ID;
+ }
+
if (ccid < BITS_PER_LONG) {
GEM_BUG_ON(ccid == 0);
GEM_BUG_ON(test_bit(ccid - 1, &engine->context_tag));
@@ -738,9 +753,9 @@ trace_ports(const struct intel_engine_execlists *execlists,
}
static bool
-reset_in_progress(const struct intel_engine_execlists *execlists)
+reset_in_progress(const struct intel_engine_cs *engine)
{
- return unlikely(!__tasklet_is_enabled(&execlists->tasklet));
+ return unlikely(!__tasklet_is_enabled(&engine->sched_engine->tasklet));
}
static __maybe_unused noinline bool
@@ -756,7 +771,7 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
trace_ports(execlists, msg, execlists->pending);
/* We may be messing around with the lists during reset, lalala */
- if (reset_in_progress(execlists))
+ if (reset_in_progress(engine))
return true;
if (!execlists->pending[0]) {
@@ -1096,7 +1111,8 @@ static void defer_active(struct intel_engine_cs *engine)
if (!rq)
return;
- defer_request(rq, i915_sched_lookup_priolist(engine, rq_prio(rq)));
+ defer_request(rq, i915_sched_lookup_priolist(engine->sched_engine,
+ rq_prio(rq)));
}
static bool
@@ -1133,13 +1149,14 @@ static bool needs_timeslice(const struct intel_engine_cs *engine,
return false;
/* If ELSP[1] is occupied, always check to see if worth slicing */
- if (!list_is_last_rcu(&rq->sched.link, &engine->active.requests)) {
+ if (!list_is_last_rcu(&rq->sched.link,
+ &engine->sched_engine->requests)) {
ENGINE_TRACE(engine, "timeslice required for second inflight context\n");
return true;
}
/* Otherwise, ELSP[0] is by itself, but may be waiting in the queue */
- if (!RB_EMPTY_ROOT(&engine->execlists.queue.rb_root)) {
+ if (!i915_sched_engine_is_empty(engine->sched_engine)) {
ENGINE_TRACE(engine, "timeslice required for queue\n");
return true;
}
@@ -1187,7 +1204,7 @@ static void start_timeslice(struct intel_engine_cs *engine)
* its timeslice, so recheck.
*/
if (!timer_pending(&el->timer))
- tasklet_hi_schedule(&el->tasklet);
+ tasklet_hi_schedule(&engine->sched_engine->tasklet);
return;
}
@@ -1236,6 +1253,7 @@ static bool completed(const struct i915_request *rq)
static void execlists_dequeue(struct intel_engine_cs *engine)
{
struct intel_engine_execlists * const execlists = &engine->execlists;
+ struct i915_sched_engine * const sched_engine = engine->sched_engine;
struct i915_request **port = execlists->pending;
struct i915_request ** const last_port = port + execlists->port_mask;
struct i915_request *last, * const *active;
@@ -1265,7 +1283,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* and context switches) submission.
*/
- spin_lock(&engine->active.lock);
+ spin_lock(&sched_engine->lock);
/*
* If the queue is higher priority than the last
@@ -1287,7 +1305,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
last->fence.context,
last->fence.seqno,
last->sched.attr.priority,
- execlists->queue_priority_hint);
+ sched_engine->queue_priority_hint);
record_preemption(execlists);
/*
@@ -1313,7 +1331,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
yesno(timer_expired(&execlists->timer)),
last->fence.context, last->fence.seqno,
rq_prio(last),
- execlists->queue_priority_hint,
+ sched_engine->queue_priority_hint,
yesno(timeslice_yield(execlists, last)));
/*
@@ -1365,7 +1383,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* Even if ELSP[1] is occupied and not worthy
* of timeslices, our queue might be.
*/
- spin_unlock(&engine->active.lock);
+ spin_unlock(&sched_engine->lock);
return;
}
}
@@ -1375,7 +1393,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
while ((ve = first_virtual_engine(engine))) {
struct i915_request *rq;
- spin_lock(&ve->base.active.lock);
+ spin_lock(&ve->base.sched_engine->lock);
rq = ve->request;
if (unlikely(!virtual_matches(ve, rq, engine)))
@@ -1384,14 +1402,14 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
GEM_BUG_ON(rq->engine != &ve->base);
GEM_BUG_ON(rq->context != &ve->context);
- if (unlikely(rq_prio(rq) < queue_prio(execlists))) {
- spin_unlock(&ve->base.active.lock);
+ if (unlikely(rq_prio(rq) < queue_prio(sched_engine))) {
+ spin_unlock(&ve->base.sched_engine->lock);
break;
}
if (last && !can_merge_rq(last, rq)) {
- spin_unlock(&ve->base.active.lock);
- spin_unlock(&engine->active.lock);
+ spin_unlock(&ve->base.sched_engine->lock);
+ spin_unlock(&engine->sched_engine->lock);
return; /* leave this for another sibling */
}
@@ -1405,7 +1423,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
yesno(engine != ve->siblings[0]));
WRITE_ONCE(ve->request, NULL);
- WRITE_ONCE(ve->base.execlists.queue_priority_hint, INT_MIN);
+ WRITE_ONCE(ve->base.sched_engine->queue_priority_hint, INT_MIN);
rb = &ve->nodes[engine->id].rb;
rb_erase_cached(rb, &execlists->virtual);
@@ -1437,7 +1455,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
i915_request_put(rq);
unlock:
- spin_unlock(&ve->base.active.lock);
+ spin_unlock(&ve->base.sched_engine->lock);
/*
* Hmm, we have a bunch of virtual engine requests,
@@ -1450,7 +1468,7 @@ unlock:
break;
}
- while ((rb = rb_first_cached(&execlists->queue))) {
+ while ((rb = rb_first_cached(&sched_engine->queue))) {
struct i915_priolist *p = to_priolist(rb);
struct i915_request *rq, *rn;
@@ -1529,7 +1547,7 @@ unlock:
}
}
- rb_erase_cached(&p->node, &execlists->queue);
+ rb_erase_cached(&p->node, &sched_engine->queue);
i915_priolist_free(p);
}
done:
@@ -1551,8 +1569,9 @@ done:
* request triggering preemption on the next dequeue (or subsequent
* interrupt for secondary ports).
*/
- execlists->queue_priority_hint = queue_prio(execlists);
- spin_unlock(&engine->active.lock);
+ sched_engine->queue_priority_hint = queue_prio(sched_engine);
+ i915_sched_engine_reset_on_empty(sched_engine);
+ spin_unlock(&sched_engine->lock);
/*
* We can skip poking the HW if we ended up with exactly the same set
@@ -1655,13 +1674,24 @@ static void invalidate_csb_entries(const u64 *first, const u64 *last)
* bits 44-46: reserved
* bits 47-57: sw context id of the lrc the GT switched away from
* bits 58-63: sw counter of the lrc the GT switched away from
+ *
+ * Xe_HP csb shuffles things around compared to TGL:
+ *
+ * bits 0-3: context switch detail (same possible values as TGL)
+ * bits 4-9: engine instance
+ * bits 10-25: sw context id of the lrc the GT switched to
+ * bits 26-31: sw counter of the lrc the GT switched to
+ * bit 32: semaphore wait mode (poll or signal), Only valid when
+ * switch detail is set to "wait on semaphore"
+ * bit 33: switched to new queue
+ * bits 34-41: wait detail (for switch detail 1 to 4)
+ * bits 42-57: sw context id of the lrc the GT switched away from
+ * bits 58-63: sw counter of the lrc the GT switched away from
*/
-static bool gen12_csb_parse(const u64 csb)
+static inline bool
+__gen12_csb_parse(bool ctx_to_valid, bool ctx_away_valid, bool new_queue,
+ u8 switch_detail)
{
- bool ctx_away_valid = GEN12_CSB_CTX_VALID(upper_32_bits(csb));
- bool new_queue =
- lower_32_bits(csb) & GEN12_CTX_STATUS_SWITCHED_TO_NEW_QUEUE;
-
/*
* The context switch detail is not guaranteed to be 5 when a preemption
* occurs, so we can't just check for that. The check below works for
@@ -1670,7 +1700,7 @@ static bool gen12_csb_parse(const u64 csb)
* would require some extra handling, but we don't support that.
*/
if (!ctx_away_valid || new_queue) {
- GEM_BUG_ON(!GEN12_CSB_CTX_VALID(lower_32_bits(csb)));
+ GEM_BUG_ON(!ctx_to_valid);
return true;
}
@@ -1679,10 +1709,26 @@ static bool gen12_csb_parse(const u64 csb)
* context switch on an unsuccessful wait instruction since we always
* use polling mode.
*/
- GEM_BUG_ON(GEN12_CTX_SWITCH_DETAIL(upper_32_bits(csb)));
+ GEM_BUG_ON(switch_detail);
return false;
}
+static bool xehp_csb_parse(const u64 csb)
+{
+ return __gen12_csb_parse(XEHP_CSB_CTX_VALID(lower_32_bits(csb)), /* cxt to */
+ XEHP_CSB_CTX_VALID(upper_32_bits(csb)), /* cxt away */
+ upper_32_bits(csb) & XEHP_CTX_STATUS_SWITCHED_TO_NEW_QUEUE,
+ GEN12_CTX_SWITCH_DETAIL(lower_32_bits(csb)));
+}
+
+static bool gen12_csb_parse(const u64 csb)
+{
+ return __gen12_csb_parse(GEN12_CSB_CTX_VALID(lower_32_bits(csb)), /* cxt to */
+ GEN12_CSB_CTX_VALID(upper_32_bits(csb)), /* cxt away */
+ lower_32_bits(csb) & GEN12_CTX_STATUS_SWITCHED_TO_NEW_QUEUE,
+ GEN12_CTX_SWITCH_DETAIL(upper_32_bits(csb)));
+}
+
static bool gen8_csb_parse(const u64 csb)
{
return csb & (GEN8_CTX_STATUS_IDLE_ACTIVE | GEN8_CTX_STATUS_PREEMPTED);
@@ -1767,8 +1813,8 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
* access. Either we are inside the tasklet, or the tasklet is disabled
* and we assume that is only inside the reset paths and so serialised.
*/
- GEM_BUG_ON(!tasklet_is_locked(&execlists->tasklet) &&
- !reset_in_progress(execlists));
+ GEM_BUG_ON(!tasklet_is_locked(&engine->sched_engine->tasklet) &&
+ !reset_in_progress(engine));
/*
* Note that csb_write, csb_status may be either in HWSP or mmio.
@@ -1847,7 +1893,9 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
ENGINE_TRACE(engine, "csb[%d]: status=0x%08x:0x%08x\n",
head, upper_32_bits(csb), lower_32_bits(csb));
- if (GRAPHICS_VER(engine->i915) >= 12)
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50))
+ promote = xehp_csb_parse(csb);
+ else if (GRAPHICS_VER(engine->i915) >= 12)
promote = gen12_csb_parse(csb);
else
promote = gen8_csb_parse(csb);
@@ -1979,7 +2027,8 @@ static void __execlists_hold(struct i915_request *rq)
__i915_request_unsubmit(rq);
clear_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
- list_move_tail(&rq->sched.link, &rq->engine->active.hold);
+ list_move_tail(&rq->sched.link,
+ &rq->engine->sched_engine->hold);
i915_request_set_hold(rq);
RQ_TRACE(rq, "on hold\n");
@@ -2016,7 +2065,7 @@ static bool execlists_hold(struct intel_engine_cs *engine,
if (i915_request_on_hold(rq))
return false;
- spin_lock_irq(&engine->active.lock);
+ spin_lock_irq(&engine->sched_engine->lock);
if (__i915_request_is_complete(rq)) { /* too late! */
rq = NULL;
@@ -2032,10 +2081,10 @@ static bool execlists_hold(struct intel_engine_cs *engine,
GEM_BUG_ON(i915_request_on_hold(rq));
GEM_BUG_ON(rq->engine != engine);
__execlists_hold(rq);
- GEM_BUG_ON(list_empty(&engine->active.hold));
+ GEM_BUG_ON(list_empty(&engine->sched_engine->hold));
unlock:
- spin_unlock_irq(&engine->active.lock);
+ spin_unlock_irq(&engine->sched_engine->lock);
return rq;
}
@@ -2079,7 +2128,7 @@ static void __execlists_unhold(struct i915_request *rq)
i915_request_clear_hold(rq);
list_move_tail(&rq->sched.link,
- i915_sched_lookup_priolist(rq->engine,
+ i915_sched_lookup_priolist(rq->engine->sched_engine,
rq_prio(rq)));
set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
@@ -2115,7 +2164,7 @@ static void __execlists_unhold(struct i915_request *rq)
static void execlists_unhold(struct intel_engine_cs *engine,
struct i915_request *rq)
{
- spin_lock_irq(&engine->active.lock);
+ spin_lock_irq(&engine->sched_engine->lock);
/*
* Move this request back to the priority queue, and all of its
@@ -2123,12 +2172,12 @@ static void execlists_unhold(struct intel_engine_cs *engine,
*/
__execlists_unhold(rq);
- if (rq_prio(rq) > engine->execlists.queue_priority_hint) {
- engine->execlists.queue_priority_hint = rq_prio(rq);
- tasklet_hi_schedule(&engine->execlists.tasklet);
+ if (rq_prio(rq) > engine->sched_engine->queue_priority_hint) {
+ engine->sched_engine->queue_priority_hint = rq_prio(rq);
+ tasklet_hi_schedule(&engine->sched_engine->tasklet);
}
- spin_unlock_irq(&engine->active.lock);
+ spin_unlock_irq(&engine->sched_engine->lock);
}
struct execlists_capture {
@@ -2258,13 +2307,13 @@ static void execlists_capture(struct intel_engine_cs *engine)
if (!cap)
return;
- spin_lock_irq(&engine->active.lock);
+ spin_lock_irq(&engine->sched_engine->lock);
cap->rq = active_context(engine, active_ccid(engine));
if (cap->rq) {
cap->rq = active_request(cap->rq->context->timeline, cap->rq);
cap->rq = i915_request_get_rcu(cap->rq);
}
- spin_unlock_irq(&engine->active.lock);
+ spin_unlock_irq(&engine->sched_engine->lock);
if (!cap->rq)
goto err_free;
@@ -2316,13 +2365,13 @@ static void execlists_reset(struct intel_engine_cs *engine, const char *msg)
ENGINE_TRACE(engine, "reset for %s\n", msg);
/* Mark this tasklet as disabled to avoid waiting for it to complete */
- tasklet_disable_nosync(&engine->execlists.tasklet);
+ tasklet_disable_nosync(&engine->sched_engine->tasklet);
ring_set_paused(engine, 1); /* Freeze the current request in place */
execlists_capture(engine);
intel_engine_reset(engine, msg);
- tasklet_enable(&engine->execlists.tasklet);
+ tasklet_enable(&engine->sched_engine->tasklet);
clear_and_wake_up_bit(bit, lock);
}
@@ -2345,8 +2394,9 @@ static bool preempt_timeout(const struct intel_engine_cs *const engine)
*/
static void execlists_submission_tasklet(struct tasklet_struct *t)
{
- struct intel_engine_cs * const engine =
- from_tasklet(engine, t, execlists.tasklet);
+ struct i915_sched_engine *sched_engine =
+ from_tasklet(sched_engine, t, tasklet);
+ struct intel_engine_cs * const engine = sched_engine->private_data;
struct i915_request *post[2 * EXECLIST_MAX_PORTS];
struct i915_request **inactive;
@@ -2421,13 +2471,16 @@ static void execlists_irq_handler(struct intel_engine_cs *engine, u16 iir)
intel_engine_signal_breadcrumbs(engine);
if (tasklet)
- tasklet_hi_schedule(&engine->execlists.tasklet);
+ tasklet_hi_schedule(&engine->sched_engine->tasklet);
}
static void __execlists_kick(struct intel_engine_execlists *execlists)
{
+ struct intel_engine_cs *engine =
+ container_of(execlists, typeof(*engine), execlists);
+
/* Kick the tasklet for some interrupt coalescing and reset handling */
- tasklet_hi_schedule(&execlists->tasklet);
+ tasklet_hi_schedule(&engine->sched_engine->tasklet);
}
#define execlists_kick(t, member) \
@@ -2448,19 +2501,20 @@ static void queue_request(struct intel_engine_cs *engine,
{
GEM_BUG_ON(!list_empty(&rq->sched.link));
list_add_tail(&rq->sched.link,
- i915_sched_lookup_priolist(engine, rq_prio(rq)));
+ i915_sched_lookup_priolist(engine->sched_engine,
+ rq_prio(rq)));
set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
}
static bool submit_queue(struct intel_engine_cs *engine,
const struct i915_request *rq)
{
- struct intel_engine_execlists *execlists = &engine->execlists;
+ struct i915_sched_engine *sched_engine = engine->sched_engine;
- if (rq_prio(rq) <= execlists->queue_priority_hint)
+ if (rq_prio(rq) <= sched_engine->queue_priority_hint)
return false;
- execlists->queue_priority_hint = rq_prio(rq);
+ sched_engine->queue_priority_hint = rq_prio(rq);
return true;
}
@@ -2468,7 +2522,7 @@ static bool ancestor_on_hold(const struct intel_engine_cs *engine,
const struct i915_request *rq)
{
GEM_BUG_ON(i915_request_on_hold(rq));
- return !list_empty(&engine->active.hold) && hold_request(rq);
+ return !list_empty(&engine->sched_engine->hold) && hold_request(rq);
}
static void execlists_submit_request(struct i915_request *request)
@@ -2477,23 +2531,24 @@ static void execlists_submit_request(struct i915_request *request)
unsigned long flags;
/* Will be called from irq-context when using foreign fences. */
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
if (unlikely(ancestor_on_hold(engine, request))) {
RQ_TRACE(request, "ancestor on hold\n");
- list_add_tail(&request->sched.link, &engine->active.hold);
+ list_add_tail(&request->sched.link,
+ &engine->sched_engine->hold);
i915_request_set_hold(request);
} else {
queue_request(engine, request);
- GEM_BUG_ON(RB_EMPTY_ROOT(&engine->execlists.queue.rb_root));
+ GEM_BUG_ON(i915_sched_engine_is_empty(engine->sched_engine));
GEM_BUG_ON(list_empty(&request->sched.link));
if (submit_queue(engine, request))
__execlists_kick(&engine->execlists);
}
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
}
static int
@@ -2533,11 +2588,26 @@ static int execlists_context_alloc(struct intel_context *ce)
return lrc_alloc(ce, ce->engine);
}
+static void execlists_context_cancel_request(struct intel_context *ce,
+ struct i915_request *rq)
+{
+ struct intel_engine_cs *engine = NULL;
+
+ i915_request_active_engine(rq, &engine);
+
+ if (engine && intel_engine_pulse(engine))
+ intel_gt_handle_error(engine->gt, engine->mask, 0,
+ "request cancellation by %s",
+ current->comm);
+}
+
static const struct intel_context_ops execlists_context_ops = {
.flags = COPS_HAS_INFLIGHT,
.alloc = execlists_context_alloc,
+ .cancel_request = execlists_context_cancel_request,
+
.pre_pin = execlists_context_pre_pin,
.pin = execlists_context_pin,
.unpin = lrc_unpin,
@@ -2548,6 +2618,8 @@ static const struct intel_context_ops execlists_context_ops = {
.reset = lrc_reset,
.destroy = lrc_destroy,
+
+ .create_virtual = execlists_create_virtual,
};
static int emit_pdps(struct i915_request *rq)
@@ -2800,10 +2872,8 @@ static int execlists_resume(struct intel_engine_cs *engine)
static void execlists_reset_prepare(struct intel_engine_cs *engine)
{
- struct intel_engine_execlists * const execlists = &engine->execlists;
-
ENGINE_TRACE(engine, "depth<-%d\n",
- atomic_read(&execlists->tasklet.count));
+ atomic_read(&engine->sched_engine->tasklet.count));
/*
* Prevent request submission to the hardware until we have
@@ -2814,8 +2884,8 @@ static void execlists_reset_prepare(struct intel_engine_cs *engine)
* Turning off the execlists->tasklet until the reset is over
* prevents the race.
*/
- __tasklet_disable_sync_once(&execlists->tasklet);
- GEM_BUG_ON(!reset_in_progress(execlists));
+ __tasklet_disable_sync_once(&engine->sched_engine->tasklet);
+ GEM_BUG_ON(!reset_in_progress(engine));
/*
* We stop engines, otherwise we might get failed reset and a
@@ -2957,24 +3027,26 @@ static void execlists_reset_rewind(struct intel_engine_cs *engine, bool stalled)
/* Push back any incomplete requests for replay after the reset. */
rcu_read_lock();
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
__unwind_incomplete_requests(engine);
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
rcu_read_unlock();
}
static void nop_submission_tasklet(struct tasklet_struct *t)
{
- struct intel_engine_cs * const engine =
- from_tasklet(engine, t, execlists.tasklet);
+ struct i915_sched_engine *sched_engine =
+ from_tasklet(sched_engine, t, tasklet);
+ struct intel_engine_cs * const engine = sched_engine->private_data;
/* The driver is wedged; don't process any more events. */
- WRITE_ONCE(engine->execlists.queue_priority_hint, INT_MIN);
+ WRITE_ONCE(engine->sched_engine->queue_priority_hint, INT_MIN);
}
static void execlists_reset_cancel(struct intel_engine_cs *engine)
{
struct intel_engine_execlists * const execlists = &engine->execlists;
+ struct i915_sched_engine * const sched_engine = engine->sched_engine;
struct i915_request *rq, *rn;
struct rb_node *rb;
unsigned long flags;
@@ -2998,15 +3070,15 @@ static void execlists_reset_cancel(struct intel_engine_cs *engine)
execlists_reset_csb(engine, true);
rcu_read_lock();
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
/* Mark all executing requests as skipped. */
- list_for_each_entry(rq, &engine->active.requests, sched.link)
+ list_for_each_entry(rq, &engine->sched_engine->requests, sched.link)
i915_request_put(i915_request_mark_eio(rq));
intel_engine_signal_breadcrumbs(engine);
/* Flush the queued requests to the timeline list (for retiring). */
- while ((rb = rb_first_cached(&execlists->queue))) {
+ while ((rb = rb_first_cached(&sched_engine->queue))) {
struct i915_priolist *p = to_priolist(rb);
priolist_for_each_request_consume(rq, rn, p) {
@@ -3016,12 +3088,12 @@ static void execlists_reset_cancel(struct intel_engine_cs *engine)
}
}
- rb_erase_cached(&p->node, &execlists->queue);
+ rb_erase_cached(&p->node, &sched_engine->queue);
i915_priolist_free(p);
}
/* On-hold requests will be flushed to timeline upon their release */
- list_for_each_entry(rq, &engine->active.hold, sched.link)
+ list_for_each_entry(rq, &sched_engine->hold, sched.link)
i915_request_put(i915_request_mark_eio(rq));
/* Cancel all attached virtual engines */
@@ -3032,7 +3104,7 @@ static void execlists_reset_cancel(struct intel_engine_cs *engine)
rb_erase_cached(rb, &execlists->virtual);
RB_CLEAR_NODE(rb);
- spin_lock(&ve->base.active.lock);
+ spin_lock(&ve->base.sched_engine->lock);
rq = fetch_and_zero(&ve->request);
if (rq) {
if (i915_request_mark_eio(rq)) {
@@ -3042,20 +3114,20 @@ static void execlists_reset_cancel(struct intel_engine_cs *engine)
}
i915_request_put(rq);
- ve->base.execlists.queue_priority_hint = INT_MIN;
+ ve->base.sched_engine->queue_priority_hint = INT_MIN;
}
- spin_unlock(&ve->base.active.lock);
+ spin_unlock(&ve->base.sched_engine->lock);
}
/* Remaining _unready_ requests will be nop'ed when submitted */
- execlists->queue_priority_hint = INT_MIN;
- execlists->queue = RB_ROOT_CACHED;
+ sched_engine->queue_priority_hint = INT_MIN;
+ sched_engine->queue = RB_ROOT_CACHED;
- GEM_BUG_ON(__tasklet_is_enabled(&execlists->tasklet));
- execlists->tasklet.callback = nop_submission_tasklet;
+ GEM_BUG_ON(__tasklet_is_enabled(&engine->sched_engine->tasklet));
+ engine->sched_engine->tasklet.callback = nop_submission_tasklet;
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
rcu_read_unlock();
}
@@ -3073,14 +3145,14 @@ static void execlists_reset_finish(struct intel_engine_cs *engine)
* reset as the next level of recovery, and as a final resort we
* will declare the device wedged.
*/
- GEM_BUG_ON(!reset_in_progress(execlists));
+ GEM_BUG_ON(!reset_in_progress(engine));
/* And kick in case we missed a new request submission. */
- if (__tasklet_enable(&execlists->tasklet))
+ if (__tasklet_enable(&engine->sched_engine->tasklet))
__execlists_kick(execlists);
ENGINE_TRACE(engine, "depth->%d\n",
- atomic_read(&execlists->tasklet.count));
+ atomic_read(&engine->sched_engine->tasklet.count));
}
static void gen8_logical_ring_enable_irq(struct intel_engine_cs *engine)
@@ -3101,6 +3173,42 @@ static void execlists_park(struct intel_engine_cs *engine)
cancel_timer(&engine->execlists.preempt);
}
+static void add_to_engine(struct i915_request *rq)
+{
+ lockdep_assert_held(&rq->engine->sched_engine->lock);
+ list_move_tail(&rq->sched.link, &rq->engine->sched_engine->requests);
+}
+
+static void remove_from_engine(struct i915_request *rq)
+{
+ struct intel_engine_cs *engine, *locked;
+
+ /*
+ * Virtual engines complicate acquiring the engine timeline lock,
+ * as their rq->engine pointer is not stable until under that
+ * engine lock. The simple ploy we use is to take the lock then
+ * check that the rq still belongs to the newly locked engine.
+ */
+ locked = READ_ONCE(rq->engine);
+ spin_lock_irq(&locked->sched_engine->lock);
+ while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) {
+ spin_unlock(&locked->sched_engine->lock);
+ spin_lock(&engine->sched_engine->lock);
+ locked = engine;
+ }
+ list_del_init(&rq->sched.link);
+
+ clear_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+ clear_bit(I915_FENCE_FLAG_HOLD, &rq->fence.flags);
+
+ /* Prevent further __await_execution() registering a cb, then flush */
+ set_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags);
+
+ spin_unlock_irq(&locked->sched_engine->lock);
+
+ i915_request_notify_execute_cb_imm(rq);
+}
+
static bool can_preempt(struct intel_engine_cs *engine)
{
if (GRAPHICS_VER(engine->i915) > 8)
@@ -3110,11 +3218,62 @@ static bool can_preempt(struct intel_engine_cs *engine)
return engine->class != RENDER_CLASS;
}
+static void kick_execlists(const struct i915_request *rq, int prio)
+{
+ struct intel_engine_cs *engine = rq->engine;
+ struct i915_sched_engine *sched_engine = engine->sched_engine;
+ const struct i915_request *inflight;
+
+ /*
+ * We only need to kick the tasklet once for the high priority
+ * new context we add into the queue.
+ */
+ if (prio <= sched_engine->queue_priority_hint)
+ return;
+
+ rcu_read_lock();
+
+ /* Nothing currently active? We're overdue for a submission! */
+ inflight = execlists_active(&engine->execlists);
+ if (!inflight)
+ goto unlock;
+
+ /*
+ * If we are already the currently executing context, don't
+ * bother evaluating if we should preempt ourselves.
+ */
+ if (inflight->context == rq->context)
+ goto unlock;
+
+ ENGINE_TRACE(engine,
+ "bumping queue-priority-hint:%d for rq:%llx:%lld, inflight:%llx:%lld prio %d\n",
+ prio,
+ rq->fence.context, rq->fence.seqno,
+ inflight->fence.context, inflight->fence.seqno,
+ inflight->sched.attr.priority);
+
+ sched_engine->queue_priority_hint = prio;
+
+ /*
+ * Allow preemption of low -> normal -> high, but we do
+ * not allow low priority tasks to preempt other low priority
+ * tasks under the impression that latency for low priority
+ * tasks does not matter (as much as background throughput),
+ * so kiss.
+ */
+ if (prio >= max(I915_PRIORITY_NORMAL, rq_prio(inflight)))
+ tasklet_hi_schedule(&sched_engine->tasklet);
+
+unlock:
+ rcu_read_unlock();
+}
+
static void execlists_set_default_submission(struct intel_engine_cs *engine)
{
engine->submit_request = execlists_submit_request;
- engine->schedule = i915_schedule;
- engine->execlists.tasklet.callback = execlists_submission_tasklet;
+ engine->sched_engine->schedule = i915_schedule;
+ engine->sched_engine->kick_backend = kick_execlists;
+ engine->sched_engine->tasklet.callback = execlists_submission_tasklet;
}
static void execlists_shutdown(struct intel_engine_cs *engine)
@@ -3122,7 +3281,7 @@ static void execlists_shutdown(struct intel_engine_cs *engine)
/* Synchronise with residual timers and any softirq they raise */
del_timer_sync(&engine->execlists.timer);
del_timer_sync(&engine->execlists.preempt);
- tasklet_kill(&engine->execlists.tasklet);
+ tasklet_kill(&engine->sched_engine->tasklet);
}
static void execlists_release(struct intel_engine_cs *engine)
@@ -3144,6 +3303,8 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine)
engine->cops = &execlists_context_ops;
engine->request_alloc = execlists_request_alloc;
+ engine->add_active_request = add_to_engine;
+ engine->remove_active_request = remove_from_engine;
engine->reset.prepare = execlists_reset_prepare;
engine->reset.rewind = execlists_reset_rewind;
@@ -3238,7 +3399,7 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine)
struct intel_uncore *uncore = engine->uncore;
u32 base = engine->mmio_base;
- tasklet_setup(&engine->execlists.tasklet, execlists_submission_tasklet);
+ tasklet_setup(&engine->sched_engine->tasklet, execlists_submission_tasklet);
timer_setup(&engine->execlists.timer, execlists_timeslice, 0);
timer_setup(&engine->execlists.preempt, execlists_preempt, 0);
@@ -3255,6 +3416,10 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine)
i915_mmio_reg_offset(RING_EXECLIST_SQ_CONTENTS(base));
execlists->ctrl_reg = uncore->regs +
i915_mmio_reg_offset(RING_EXECLIST_CONTROL(base));
+
+ engine->fw_domain = intel_uncore_forcewake_for_reg(engine->uncore,
+ RING_EXECLIST_CONTROL(engine->mmio_base),
+ FW_REG_WRITE);
} else {
execlists->submit_reg = uncore->regs +
i915_mmio_reg_offset(RING_ELSP(base));
@@ -3272,7 +3437,8 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine)
execlists->csb_size = GEN11_CSB_ENTRIES;
engine->context_tag = GENMASK(BITS_PER_LONG - 2, 0);
- if (GRAPHICS_VER(engine->i915) >= 11) {
+ if (GRAPHICS_VER(engine->i915) >= 11 &&
+ GRAPHICS_VER_FULL(engine->i915) < IP_VER(12, 50)) {
execlists->ccid |= engine->instance << (GEN11_ENGINE_INSTANCE_SHIFT - 32);
execlists->ccid |= engine->class << (GEN11_ENGINE_CLASS_SHIFT - 32);
}
@@ -3286,7 +3452,7 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine)
static struct list_head *virtual_queue(struct virtual_engine *ve)
{
- return &ve->base.execlists.default_priolist.requests;
+ return &ve->base.sched_engine->default_priolist.requests;
}
static void rcu_virtual_context_destroy(struct work_struct *wrk)
@@ -3301,7 +3467,7 @@ static void rcu_virtual_context_destroy(struct work_struct *wrk)
if (unlikely(ve->request)) {
struct i915_request *old;
- spin_lock_irq(&ve->base.active.lock);
+ spin_lock_irq(&ve->base.sched_engine->lock);
old = fetch_and_zero(&ve->request);
if (old) {
@@ -3310,7 +3476,7 @@ static void rcu_virtual_context_destroy(struct work_struct *wrk)
i915_request_put(old);
}
- spin_unlock_irq(&ve->base.active.lock);
+ spin_unlock_irq(&ve->base.sched_engine->lock);
}
/*
@@ -3320,7 +3486,7 @@ static void rcu_virtual_context_destroy(struct work_struct *wrk)
* rbtrees as in the case it is running in parallel, it may reinsert
* the rb_node into a sibling.
*/
- tasklet_kill(&ve->base.execlists.tasklet);
+ tasklet_kill(&ve->base.sched_engine->tasklet);
/* Decouple ourselves from the siblings, no more access allowed. */
for (n = 0; n < ve->num_siblings; n++) {
@@ -3330,24 +3496,26 @@ static void rcu_virtual_context_destroy(struct work_struct *wrk)
if (RB_EMPTY_NODE(node))
continue;
- spin_lock_irq(&sibling->active.lock);
+ spin_lock_irq(&sibling->sched_engine->lock);
- /* Detachment is lazily performed in the execlists tasklet */
+ /* Detachment is lazily performed in the sched_engine->tasklet */
if (!RB_EMPTY_NODE(node))
rb_erase_cached(node, &sibling->execlists.virtual);
- spin_unlock_irq(&sibling->active.lock);
+ spin_unlock_irq(&sibling->sched_engine->lock);
}
- GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.execlists.tasklet));
+ GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.sched_engine->tasklet));
GEM_BUG_ON(!list_empty(virtual_queue(ve)));
lrc_fini(&ve->context);
intel_context_fini(&ve->context);
- intel_breadcrumbs_free(ve->base.breadcrumbs);
+ if (ve->base.breadcrumbs)
+ intel_breadcrumbs_put(ve->base.breadcrumbs);
+ if (ve->base.sched_engine)
+ i915_sched_engine_put(ve->base.sched_engine);
intel_engine_free_request_pool(&ve->base);
- kfree(ve->bonds);
kfree(ve);
}
@@ -3440,11 +3608,24 @@ static void virtual_context_exit(struct intel_context *ce)
intel_engine_pm_put(ve->siblings[n]);
}
+static struct intel_engine_cs *
+virtual_get_sibling(struct intel_engine_cs *engine, unsigned int sibling)
+{
+ struct virtual_engine *ve = to_virtual_engine(engine);
+
+ if (sibling >= ve->num_siblings)
+ return NULL;
+
+ return ve->siblings[sibling];
+}
+
static const struct intel_context_ops virtual_context_ops = {
.flags = COPS_HAS_INFLIGHT,
.alloc = virtual_context_alloc,
+ .cancel_request = execlists_context_cancel_request,
+
.pre_pin = virtual_context_pre_pin,
.pin = virtual_context_pin,
.unpin = lrc_unpin,
@@ -3454,6 +3635,8 @@ static const struct intel_context_ops virtual_context_ops = {
.exit = virtual_context_exit,
.destroy = virtual_context_destroy,
+
+ .get_sibling = virtual_get_sibling,
};
static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve)
@@ -3475,16 +3658,18 @@ static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve)
ENGINE_TRACE(&ve->base, "rq=%llx:%lld, mask=%x, prio=%d\n",
rq->fence.context, rq->fence.seqno,
- mask, ve->base.execlists.queue_priority_hint);
+ mask, ve->base.sched_engine->queue_priority_hint);
return mask;
}
static void virtual_submission_tasklet(struct tasklet_struct *t)
{
+ struct i915_sched_engine *sched_engine =
+ from_tasklet(sched_engine, t, tasklet);
struct virtual_engine * const ve =
- from_tasklet(ve, t, base.execlists.tasklet);
- const int prio = READ_ONCE(ve->base.execlists.queue_priority_hint);
+ (struct virtual_engine *)sched_engine->private_data;
+ const int prio = READ_ONCE(sched_engine->queue_priority_hint);
intel_engine_mask_t mask;
unsigned int n;
@@ -3503,7 +3688,7 @@ static void virtual_submission_tasklet(struct tasklet_struct *t)
if (!READ_ONCE(ve->request))
break; /* already handled by a sibling's tasklet */
- spin_lock_irq(&sibling->active.lock);
+ spin_lock_irq(&sibling->sched_engine->lock);
if (unlikely(!(mask & sibling->mask))) {
if (!RB_EMPTY_NODE(&node->rb)) {
@@ -3552,11 +3737,11 @@ static void virtual_submission_tasklet(struct tasklet_struct *t)
submit_engine:
GEM_BUG_ON(RB_EMPTY_NODE(&node->rb));
node->prio = prio;
- if (first && prio > sibling->execlists.queue_priority_hint)
- tasklet_hi_schedule(&sibling->execlists.tasklet);
+ if (first && prio > sibling->sched_engine->queue_priority_hint)
+ tasklet_hi_schedule(&sibling->sched_engine->tasklet);
unlock_engine:
- spin_unlock_irq(&sibling->active.lock);
+ spin_unlock_irq(&sibling->sched_engine->lock);
if (intel_context_inflight(&ve->context))
break;
@@ -3574,7 +3759,7 @@ static void virtual_submit_request(struct i915_request *rq)
GEM_BUG_ON(ve->base.submit_request != virtual_submit_request);
- spin_lock_irqsave(&ve->base.active.lock, flags);
+ spin_lock_irqsave(&ve->base.sched_engine->lock, flags);
/* By the time we resubmit a request, it may be completed */
if (__i915_request_is_complete(rq)) {
@@ -3588,68 +3773,25 @@ static void virtual_submit_request(struct i915_request *rq)
i915_request_put(ve->request);
}
- ve->base.execlists.queue_priority_hint = rq_prio(rq);
+ ve->base.sched_engine->queue_priority_hint = rq_prio(rq);
ve->request = i915_request_get(rq);
GEM_BUG_ON(!list_empty(virtual_queue(ve)));
list_move_tail(&rq->sched.link, virtual_queue(ve));
- tasklet_hi_schedule(&ve->base.execlists.tasklet);
+ tasklet_hi_schedule(&ve->base.sched_engine->tasklet);
unlock:
- spin_unlock_irqrestore(&ve->base.active.lock, flags);
+ spin_unlock_irqrestore(&ve->base.sched_engine->lock, flags);
}
-static struct ve_bond *
-virtual_find_bond(struct virtual_engine *ve,
- const struct intel_engine_cs *master)
-{
- int i;
-
- for (i = 0; i < ve->num_bonds; i++) {
- if (ve->bonds[i].master == master)
- return &ve->bonds[i];
- }
-
- return NULL;
-}
-
-static void
-virtual_bond_execute(struct i915_request *rq, struct dma_fence *signal)
-{
- struct virtual_engine *ve = to_virtual_engine(rq->engine);
- intel_engine_mask_t allowed, exec;
- struct ve_bond *bond;
-
- allowed = ~to_request(signal)->engine->mask;
-
- bond = virtual_find_bond(ve, to_request(signal)->engine);
- if (bond)
- allowed &= bond->sibling_mask;
-
- /* Restrict the bonded request to run on only the available engines */
- exec = READ_ONCE(rq->execution_mask);
- while (!try_cmpxchg(&rq->execution_mask, &exec, exec & allowed))
- ;
-
- /* Prevent the master from being re-run on the bonded engines */
- to_request(signal)->execution_mask &= ~allowed;
-}
-
-struct intel_context *
-intel_execlists_create_virtual(struct intel_engine_cs **siblings,
- unsigned int count)
+static struct intel_context *
+execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count)
{
struct virtual_engine *ve;
unsigned int n;
int err;
- if (count == 0)
- return ERR_PTR(-EINVAL);
-
- if (count == 1)
- return intel_context_create(siblings[0]);
-
ve = kzalloc(struct_size(ve, siblings, count), GFP_KERNEL);
if (!ve)
return ERR_PTR(-ENOMEM);
@@ -3681,19 +3823,24 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings,
snprintf(ve->base.name, sizeof(ve->base.name), "virtual");
- intel_engine_init_active(&ve->base, ENGINE_VIRTUAL);
intel_engine_init_execlists(&ve->base);
+ ve->base.sched_engine = i915_sched_engine_create(ENGINE_VIRTUAL);
+ if (!ve->base.sched_engine) {
+ err = -ENOMEM;
+ goto err_put;
+ }
+ ve->base.sched_engine->private_data = &ve->base;
+
ve->base.cops = &virtual_context_ops;
ve->base.request_alloc = execlists_request_alloc;
- ve->base.schedule = i915_schedule;
+ ve->base.sched_engine->schedule = i915_schedule;
+ ve->base.sched_engine->kick_backend = kick_execlists;
ve->base.submit_request = virtual_submit_request;
- ve->base.bond_execute = virtual_bond_execute;
INIT_LIST_HEAD(virtual_queue(ve));
- ve->base.execlists.queue_priority_hint = INT_MIN;
- tasklet_setup(&ve->base.execlists.tasklet, virtual_submission_tasklet);
+ tasklet_setup(&ve->base.sched_engine->tasklet, virtual_submission_tasklet);
intel_context_init(&ve->context, &ve->base);
@@ -3721,7 +3868,7 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings,
* layering if we handle cloning of the requests and
* submitting a copy into each backend.
*/
- if (sibling->execlists.tasklet.callback !=
+ if (sibling->sched_engine->tasklet.callback !=
execlists_submission_tasklet) {
err = -ENODEV;
goto err_put;
@@ -3756,6 +3903,8 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings,
"v%dx%d", ve->base.class, count);
ve->base.context_size = sibling->context_size;
+ ve->base.add_active_request = sibling->add_active_request;
+ ve->base.remove_active_request = sibling->remove_active_request;
ve->base.emit_bb_start = sibling->emit_bb_start;
ve->base.emit_flush = sibling->emit_flush;
ve->base.emit_init_breadcrumb = sibling->emit_init_breadcrumb;
@@ -3776,70 +3925,6 @@ err_put:
return ERR_PTR(err);
}
-struct intel_context *
-intel_execlists_clone_virtual(struct intel_engine_cs *src)
-{
- struct virtual_engine *se = to_virtual_engine(src);
- struct intel_context *dst;
-
- dst = intel_execlists_create_virtual(se->siblings,
- se->num_siblings);
- if (IS_ERR(dst))
- return dst;
-
- if (se->num_bonds) {
- struct virtual_engine *de = to_virtual_engine(dst->engine);
-
- de->bonds = kmemdup(se->bonds,
- sizeof(*se->bonds) * se->num_bonds,
- GFP_KERNEL);
- if (!de->bonds) {
- intel_context_put(dst);
- return ERR_PTR(-ENOMEM);
- }
-
- de->num_bonds = se->num_bonds;
- }
-
- return dst;
-}
-
-int intel_virtual_engine_attach_bond(struct intel_engine_cs *engine,
- const struct intel_engine_cs *master,
- const struct intel_engine_cs *sibling)
-{
- struct virtual_engine *ve = to_virtual_engine(engine);
- struct ve_bond *bond;
- int n;
-
- /* Sanity check the sibling is part of the virtual engine */
- for (n = 0; n < ve->num_siblings; n++)
- if (sibling == ve->siblings[n])
- break;
- if (n == ve->num_siblings)
- return -EINVAL;
-
- bond = virtual_find_bond(ve, master);
- if (bond) {
- bond->sibling_mask |= sibling->mask;
- return 0;
- }
-
- bond = krealloc(ve->bonds,
- sizeof(*bond) * (ve->num_bonds + 1),
- GFP_KERNEL);
- if (!bond)
- return -ENOMEM;
-
- bond[ve->num_bonds].master = master;
- bond[ve->num_bonds].sibling_mask = sibling->mask;
-
- ve->bonds = bond;
- ve->num_bonds++;
-
- return 0;
-}
-
void intel_execlists_show_requests(struct intel_engine_cs *engine,
struct drm_printer *m,
void (*show_request)(struct drm_printer *m,
@@ -3849,16 +3934,17 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
unsigned int max)
{
const struct intel_engine_execlists *execlists = &engine->execlists;
+ struct i915_sched_engine *sched_engine = engine->sched_engine;
struct i915_request *rq, *last;
unsigned long flags;
unsigned int count;
struct rb_node *rb;
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&sched_engine->lock, flags);
last = NULL;
count = 0;
- list_for_each_entry(rq, &engine->active.requests, sched.link) {
+ list_for_each_entry(rq, &sched_engine->requests, sched.link) {
if (count++ < max - 1)
show_request(m, rq, "\t\t", 0);
else
@@ -3873,13 +3959,13 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
show_request(m, last, "\t\t", 0);
}
- if (execlists->queue_priority_hint != INT_MIN)
+ if (sched_engine->queue_priority_hint != INT_MIN)
drm_printf(m, "\t\tQueue priority hint: %d\n",
- READ_ONCE(execlists->queue_priority_hint));
+ READ_ONCE(sched_engine->queue_priority_hint));
last = NULL;
count = 0;
- for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
+ for (rb = rb_first_cached(&sched_engine->queue); rb; rb = rb_next(rb)) {
struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
priolist_for_each_request(rq, p) {
@@ -3921,7 +4007,7 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
show_request(m, last, "\t\t", 0);
}
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&sched_engine->lock, flags);
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.h b/drivers/gpu/drm/i915/gt/intel_execlists_submission.h
index 4ca9b475e252..a1aa92c983a5 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.h
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.h
@@ -32,15 +32,7 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
int indent),
unsigned int max);
-struct intel_context *
-intel_execlists_create_virtual(struct intel_engine_cs **siblings,
- unsigned int count);
-
-struct intel_context *
-intel_execlists_clone_virtual(struct intel_engine_cs *src);
-
-int intel_virtual_engine_attach_bond(struct intel_engine_cs *engine,
- const struct intel_engine_cs *master,
- const struct intel_engine_cs *sibling);
+bool
+intel_engine_in_execlists_submission_mode(const struct intel_engine_cs *engine);
#endif /* __INTEL_EXECLISTS_SUBMISSION_H__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c
index 20e46b843324..de3ac58fceec 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c
@@ -826,13 +826,13 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
phys_addr = pci_resource_start(pdev, 0) + pci_resource_len(pdev, 0) / 2;
/*
- * On BXT+/CNL+ writes larger than 64 bit to the GTT pagetable range
+ * On BXT+/ICL+ writes larger than 64 bit to the GTT pagetable range
* will be dropped. For WC mappings in general we have 64 byte burst
* writes when the WC buffer is flushed, so we can't use it, but have to
* resort to an uncached mapping. The WC issue is easily caught by the
* readback check when writing GTT PTE entries.
*/
- if (IS_GEN9_LP(i915) || GRAPHICS_VER(i915) >= 10)
+ if (IS_GEN9_LP(i915) || GRAPHICS_VER(i915) >= 11)
ggtt->gsm = ioremap(phys_addr, size);
else
ggtt->gsm = ioremap_wc(phys_addr, size);
@@ -1494,7 +1494,7 @@ intel_partial_pages(const struct i915_ggtt_view *view,
if (ret)
goto err_sg_alloc;
- iter = i915_gem_object_get_sg_dma(obj, view->partial.offset, &offset, true);
+ iter = i915_gem_object_get_sg_dma(obj, view->partial.offset, &offset);
GEM_BUG_ON(!iter);
sg = st->sgl;
diff --git a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
index 2694dbb9967e..1c3af0fc0456 100644
--- a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
+++ b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
@@ -123,8 +123,10 @@
#define MI_SEMAPHORE_SAD_NEQ_SDD (5 << 12)
#define MI_SEMAPHORE_TOKEN_MASK REG_GENMASK(9, 5)
#define MI_SEMAPHORE_TOKEN_SHIFT 5
+#define MI_STORE_DATA_IMM MI_INSTR(0x20, 0)
#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1)
#define MI_STORE_DWORD_IMM_GEN4 MI_INSTR(0x20, 2)
+#define MI_STORE_QWORD_IMM_GEN8 (MI_INSTR(0x20, 3) | REG_BIT(21))
#define MI_MEM_VIRTUAL (1 << 22) /* 945,g33,965 */
#define MI_USE_GGTT (1 << 22) /* g4x+ */
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 2161bf01ef8b..62d40c986642 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -13,6 +13,7 @@
#include "intel_gt_clock_utils.h"
#include "intel_gt_pm.h"
#include "intel_gt_requests.h"
+#include "intel_migrate.h"
#include "intel_mocs.h"
#include "intel_rc6.h"
#include "intel_renderstate.h"
@@ -40,8 +41,8 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
intel_gt_init_timelines(gt);
intel_gt_pm_init_early(gt);
- intel_rps_init_early(&gt->rps);
intel_uc_init_early(&gt->uc);
+ intel_rps_init_early(&gt->rps);
}
int intel_gt_probe_lmem(struct intel_gt *gt)
@@ -83,13 +84,73 @@ void intel_gt_init_hw_early(struct intel_gt *gt, struct i915_ggtt *ggtt)
gt->ggtt = ggtt;
}
+static const struct intel_mmio_range icl_l3bank_steering_table[] = {
+ { 0x00B100, 0x00B3FF },
+ {},
+};
+
+static const struct intel_mmio_range xehpsdv_mslice_steering_table[] = {
+ { 0x004000, 0x004AFF },
+ { 0x00C800, 0x00CFFF },
+ { 0x00DD00, 0x00DDFF },
+ { 0x00E900, 0x00FFFF }, /* 0xEA00 - OxEFFF is unused */
+ {},
+};
+
+static const struct intel_mmio_range xehpsdv_lncf_steering_table[] = {
+ { 0x00B000, 0x00B0FF },
+ { 0x00D800, 0x00D8FF },
+ {},
+};
+
+static const struct intel_mmio_range dg2_lncf_steering_table[] = {
+ { 0x00B000, 0x00B0FF },
+ { 0x00D880, 0x00D8FF },
+ {},
+};
+
+static u16 slicemask(struct intel_gt *gt, int count)
+{
+ u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
+
+ return intel_slicemask_from_dssmask(dss_mask, count);
+}
+
int intel_gt_init_mmio(struct intel_gt *gt)
{
+ struct drm_i915_private *i915 = gt->i915;
+
intel_gt_init_clock_frequency(gt);
intel_uc_init_mmio(&gt->uc);
intel_sseu_info_init(gt);
+ /*
+ * An mslice is unavailable only if both the meml3 for the slice is
+ * disabled *and* all of the DSS in the slice (quadrant) are disabled.
+ */
+ if (HAS_MSLICES(i915))
+ gt->info.mslice_mask =
+ slicemask(gt, GEN_DSS_PER_MSLICE) |
+ (intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
+ GEN12_MEML3_EN_MASK);
+
+ if (IS_DG2(i915)) {
+ gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
+ gt->steering_table[LNCF] = dg2_lncf_steering_table;
+ } else if (IS_XEHPSDV(i915)) {
+ gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
+ gt->steering_table[LNCF] = xehpsdv_lncf_steering_table;
+ } else if (GRAPHICS_VER(i915) >= 11 &&
+ GRAPHICS_VER_FULL(i915) < IP_VER(12, 50)) {
+ gt->steering_table[L3BANK] = icl_l3bank_steering_table;
+ gt->info.l3bank_mask =
+ ~intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
+ GEN10_L3BANK_MASK;
+ } else if (HAS_MSLICES(i915)) {
+ MISSING_CASE(INTEL_INFO(i915)->platform);
+ }
+
return intel_engines_init_mmio(gt);
}
@@ -192,7 +253,7 @@ static void clear_register(struct intel_uncore *uncore, i915_reg_t reg)
intel_uncore_rmw(uncore, reg, 0, 0);
}
-static void gen8_clear_engine_error_register(struct intel_engine_cs *engine)
+static void gen6_clear_engine_error_register(struct intel_engine_cs *engine)
{
GEN6_RING_FAULT_REG_RMW(engine, RING_FAULT_VALID, 0);
GEN6_RING_FAULT_REG_POSTING_READ(engine);
@@ -238,7 +299,7 @@ intel_gt_clear_error_registers(struct intel_gt *gt,
enum intel_engine_id id;
for_each_engine_masked(engine, gt, engine_mask, id)
- gen8_clear_engine_error_register(engine);
+ gen6_clear_engine_error_register(engine);
}
}
@@ -572,6 +633,25 @@ static void __intel_gt_disable(struct intel_gt *gt)
GEM_BUG_ON(intel_gt_pm_is_awake(gt));
}
+int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout)
+{
+ long remaining_timeout;
+
+ /* If the device is asleep, we have no requests outstanding */
+ if (!intel_gt_pm_is_awake(gt))
+ return 0;
+
+ while ((timeout = intel_gt_retire_requests_timeout(gt, timeout,
+ &remaining_timeout)) > 0) {
+ cond_resched();
+ if (signal_pending(current))
+ return -EINTR;
+ }
+
+ return timeout ? timeout : intel_uc_wait_for_idle(&gt->uc,
+ remaining_timeout);
+}
+
int intel_gt_init(struct intel_gt *gt)
{
int err;
@@ -622,10 +702,14 @@ int intel_gt_init(struct intel_gt *gt)
if (err)
goto err_gt;
+ intel_uc_init_late(&gt->uc);
+
err = i915_inject_probe_error(gt->i915, -EIO);
if (err)
goto err_gt;
+ intel_migrate_init(&gt->migrate, gt);
+
goto out_fw;
err_gt:
__intel_gt_disable(gt);
@@ -649,6 +733,7 @@ void intel_gt_driver_remove(struct intel_gt *gt)
{
__intel_gt_disable(gt);
+ intel_migrate_fini(&gt->migrate);
intel_uc_driver_remove(&gt->uc);
intel_engines_release(gt);
@@ -697,6 +782,112 @@ void intel_gt_driver_late_release(struct intel_gt *gt)
intel_engines_free(gt);
}
+/**
+ * intel_gt_reg_needs_read_steering - determine whether a register read
+ * requires explicit steering
+ * @gt: GT structure
+ * @reg: the register to check steering requirements for
+ * @type: type of multicast steering to check
+ *
+ * Determines whether @reg needs explicit steering of a specific type for
+ * reads.
+ *
+ * Returns false if @reg does not belong to a register range of the given
+ * steering type, or if the default (subslice-based) steering IDs are suitable
+ * for @type steering too.
+ */
+static bool intel_gt_reg_needs_read_steering(struct intel_gt *gt,
+ i915_reg_t reg,
+ enum intel_steering_type type)
+{
+ const u32 offset = i915_mmio_reg_offset(reg);
+ const struct intel_mmio_range *entry;
+
+ if (likely(!intel_gt_needs_read_steering(gt, type)))
+ return false;
+
+ for (entry = gt->steering_table[type]; entry->end; entry++) {
+ if (offset >= entry->start && offset <= entry->end)
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * intel_gt_get_valid_steering - determines valid IDs for a class of MCR steering
+ * @gt: GT structure
+ * @type: multicast register type
+ * @sliceid: Slice ID returned
+ * @subsliceid: Subslice ID returned
+ *
+ * Determines sliceid and subsliceid values that will steer reads
+ * of a specific multicast register class to a valid value.
+ */
+static void intel_gt_get_valid_steering(struct intel_gt *gt,
+ enum intel_steering_type type,
+ u8 *sliceid, u8 *subsliceid)
+{
+ switch (type) {
+ case L3BANK:
+ GEM_DEBUG_WARN_ON(!gt->info.l3bank_mask); /* should be impossible! */
+
+ *sliceid = 0; /* unused */
+ *subsliceid = __ffs(gt->info.l3bank_mask);
+ break;
+ case MSLICE:
+ GEM_DEBUG_WARN_ON(!gt->info.mslice_mask); /* should be impossible! */
+
+ *sliceid = __ffs(gt->info.mslice_mask);
+ *subsliceid = 0; /* unused */
+ break;
+ case LNCF:
+ GEM_DEBUG_WARN_ON(!gt->info.mslice_mask); /* should be impossible! */
+
+ /*
+ * An LNCF is always present if its mslice is present, so we
+ * can safely just steer to LNCF 0 in all cases.
+ */
+ *sliceid = __ffs(gt->info.mslice_mask) << 1;
+ *subsliceid = 0; /* unused */
+ break;
+ default:
+ MISSING_CASE(type);
+ *sliceid = 0;
+ *subsliceid = 0;
+ }
+}
+
+/**
+ * intel_gt_read_register_fw - reads a GT register with support for multicast
+ * @gt: GT structure
+ * @reg: register to read
+ *
+ * This function will read a GT register. If the register is a multicast
+ * register, the read will be steered to a valid instance (i.e., one that
+ * isn't fused off or powered down by power gating).
+ *
+ * Returns the value from a valid instance of @reg.
+ */
+u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg)
+{
+ int type;
+ u8 sliceid, subsliceid;
+
+ for (type = 0; type < NUM_STEERING_TYPES; type++) {
+ if (intel_gt_reg_needs_read_steering(gt, reg, type)) {
+ intel_gt_get_valid_steering(gt, type, &sliceid,
+ &subsliceid);
+ return intel_uncore_read_with_mcr_steering_fw(gt->uncore,
+ reg,
+ sliceid,
+ subsliceid);
+ }
+ }
+
+ return intel_uncore_read_fw(gt->uncore, reg);
+}
+
void intel_gt_info_print(const struct intel_gt_info *info,
struct drm_printer *p)
{
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h
index 7ec395cace69..74e771871a9b 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt.h
@@ -48,6 +48,8 @@ void intel_gt_driver_release(struct intel_gt *gt);
void intel_gt_driver_late_release(struct intel_gt *gt);
+int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout);
+
void intel_gt_check_and_clear_faults(struct intel_gt *gt);
void intel_gt_clear_error_registers(struct intel_gt *gt,
intel_engine_mask_t engine_mask);
@@ -75,6 +77,14 @@ static inline bool intel_gt_is_wedged(const struct intel_gt *gt)
return unlikely(test_bit(I915_WEDGED, &gt->reset.flags));
}
+static inline bool intel_gt_needs_read_steering(struct intel_gt *gt,
+ enum intel_steering_type type)
+{
+ return gt->steering_table[type];
+}
+
+u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg);
+
void intel_gt_info_print(const struct intel_gt_info *info,
struct drm_printer *p);
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
index 9f0e729d2d15..3513d6f90747 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
@@ -24,8 +24,8 @@ static u32 read_reference_ts_freq(struct intel_uncore *uncore)
return base_freq + frac_freq;
}
-static u32 gen10_get_crystal_clock_freq(struct intel_uncore *uncore,
- u32 rpm_config_reg)
+static u32 gen9_get_crystal_clock_freq(struct intel_uncore *uncore,
+ u32 rpm_config_reg)
{
u32 f19_2_mhz = 19200000;
u32 f24_mhz = 24000000;
@@ -128,10 +128,10 @@ static u32 read_clock_frequency(struct intel_uncore *uncore)
} else {
u32 c0 = intel_uncore_read(uncore, RPM_CONFIG0);
- if (GRAPHICS_VER(uncore->i915) <= 10)
- freq = gen10_get_crystal_clock_freq(uncore, c0);
- else
+ if (GRAPHICS_VER(uncore->i915) >= 11)
freq = gen11_get_crystal_clock_freq(uncore, c0);
+ else
+ freq = gen9_get_crystal_clock_freq(uncore, c0);
/*
* Now figure out how the command stream's timestamp
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
index c13462274fe8..b2de83be4d97 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
@@ -184,7 +184,13 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
intel_uncore_write(uncore, GEN11_BCS_RSVD_INTR_MASK, ~0);
intel_uncore_write(uncore, GEN11_VCS0_VCS1_INTR_MASK, ~0);
intel_uncore_write(uncore, GEN11_VCS2_VCS3_INTR_MASK, ~0);
+ if (HAS_ENGINE(gt, VCS4) || HAS_ENGINE(gt, VCS5))
+ intel_uncore_write(uncore, GEN12_VCS4_VCS5_INTR_MASK, ~0);
+ if (HAS_ENGINE(gt, VCS6) || HAS_ENGINE(gt, VCS7))
+ intel_uncore_write(uncore, GEN12_VCS6_VCS7_INTR_MASK, ~0);
intel_uncore_write(uncore, GEN11_VECS0_VECS1_INTR_MASK, ~0);
+ if (HAS_ENGINE(gt, VECS2) || HAS_ENGINE(gt, VECS3))
+ intel_uncore_write(uncore, GEN12_VECS2_VECS3_INTR_MASK, ~0);
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK, ~0);
@@ -218,8 +224,13 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
intel_uncore_write(uncore, GEN11_BCS_RSVD_INTR_MASK, ~smask);
intel_uncore_write(uncore, GEN11_VCS0_VCS1_INTR_MASK, ~dmask);
intel_uncore_write(uncore, GEN11_VCS2_VCS3_INTR_MASK, ~dmask);
+ if (HAS_ENGINE(gt, VCS4) || HAS_ENGINE(gt, VCS5))
+ intel_uncore_write(uncore, GEN12_VCS4_VCS5_INTR_MASK, ~dmask);
+ if (HAS_ENGINE(gt, VCS6) || HAS_ENGINE(gt, VCS7))
+ intel_uncore_write(uncore, GEN12_VCS6_VCS7_INTR_MASK, ~dmask);
intel_uncore_write(uncore, GEN11_VECS0_VECS1_INTR_MASK, ~dmask);
-
+ if (HAS_ENGINE(gt, VECS2) || HAS_ENGINE(gt, VECS3))
+ intel_uncore_write(uncore, GEN12_VECS2_VECS3_INTR_MASK, ~dmask);
/*
* RPS interrupts will get enabled/disabled on demand when RPS itself
* is enabled/disabled.
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index aef3084e8b16..dea8e2479897 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -6,7 +6,6 @@
#include <linux/suspend.h>
#include "i915_drv.h"
-#include "i915_globals.h"
#include "i915_params.h"
#include "intel_context.h"
#include "intel_engine_pm.h"
@@ -67,8 +66,6 @@ static int __gt_unpark(struct intel_wakeref *wf)
GT_TRACE(gt, "\n");
- i915_globals_unpark();
-
/*
* It seems that the DMC likes to transition between the DC states a lot
* when there are no connected displays (no active power domains) during
@@ -116,8 +113,6 @@ static int __gt_park(struct intel_wakeref *wf)
GEM_BUG_ON(!wakeref);
intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref);
- i915_globals_park();
-
return 0;
}
@@ -174,8 +169,6 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
if (intel_gt_is_wedged(gt))
intel_gt_unset_wedged(gt);
- intel_uc_sanitize(&gt->uc);
-
for_each_engine(engine, gt, id)
if (engine->reset.prepare)
engine->reset.prepare(engine);
@@ -191,6 +184,8 @@ static void gt_sanitize(struct intel_gt *gt, bool force)
__intel_engine_reset(engine, false);
}
+ intel_uc_reset(&gt->uc, false);
+
for_each_engine(engine, gt, id)
if (engine->reset.finish)
engine->reset.finish(engine);
@@ -243,6 +238,8 @@ int intel_gt_resume(struct intel_gt *gt)
goto err_wedged;
}
+ intel_uc_reset_finish(&gt->uc);
+
intel_rps_enable(&gt->rps);
intel_llc_enable(&gt->llc);
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c
index 647eca9d867a..edb881d75630 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c
@@ -130,7 +130,8 @@ void intel_engine_fini_retire(struct intel_engine_cs *engine)
GEM_BUG_ON(engine->retire);
}
-long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout)
+long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout,
+ long *remaining_timeout)
{
struct intel_gt_timelines *timelines = &gt->timelines;
struct intel_timeline *tl, *tn;
@@ -195,22 +196,10 @@ out_active: spin_lock(&timelines->lock);
if (flush_submission(gt, timeout)) /* Wait, there's more! */
active_count++;
- return active_count ? timeout : 0;
-}
-
-int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout)
-{
- /* If the device is asleep, we have no requests outstanding */
- if (!intel_gt_pm_is_awake(gt))
- return 0;
-
- while ((timeout = intel_gt_retire_requests_timeout(gt, timeout)) > 0) {
- cond_resched();
- if (signal_pending(current))
- return -EINTR;
- }
+ if (remaining_timeout)
+ *remaining_timeout = timeout;
- return timeout;
+ return active_count ? timeout : 0;
}
static void retire_work_handler(struct work_struct *work)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.h b/drivers/gpu/drm/i915/gt/intel_gt_requests.h
index fcc30a6e4fe9..51dbe0e3294e 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_requests.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.h
@@ -6,14 +6,17 @@
#ifndef INTEL_GT_REQUESTS_H
#define INTEL_GT_REQUESTS_H
+#include <stddef.h>
+
struct intel_engine_cs;
struct intel_gt;
struct intel_timeline;
-long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout);
+long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout,
+ long *remaining_timeout);
static inline void intel_gt_retire_requests(struct intel_gt *gt)
{
- intel_gt_retire_requests_timeout(gt, 0);
+ intel_gt_retire_requests_timeout(gt, 0, NULL);
}
void intel_engine_init_retire(struct intel_engine_cs *engine);
@@ -21,8 +24,6 @@ void intel_engine_add_retire(struct intel_engine_cs *engine,
struct intel_timeline *tl);
void intel_engine_fini_retire(struct intel_engine_cs *engine);
-int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout);
-
void intel_gt_init_requests(struct intel_gt *gt);
void intel_gt_park_requests(struct intel_gt *gt);
void intel_gt_unpark_requests(struct intel_gt *gt);
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h
index fecfacf551d5..a81e21bf1bd1 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
@@ -24,6 +24,7 @@
#include "intel_reset_types.h"
#include "intel_rc6_types.h"
#include "intel_rps_types.h"
+#include "intel_migrate_types.h"
#include "intel_wakeref.h"
struct drm_i915_private;
@@ -31,6 +32,33 @@ struct i915_ggtt;
struct intel_engine_cs;
struct intel_uncore;
+struct intel_mmio_range {
+ u32 start;
+ u32 end;
+};
+
+/*
+ * The hardware has multiple kinds of multicast register ranges that need
+ * special register steering (and future platforms are expected to add
+ * additional types).
+ *
+ * During driver startup, we initialize the steering control register to
+ * direct reads to a slice/subslice that are valid for the 'subslice' class
+ * of multicast registers. If another type of steering does not have any
+ * overlap in valid steering targets with 'subslice' style registers, we will
+ * need to explicitly re-steer reads of registers of the other type.
+ *
+ * Only the replication types that may need additional non-default steering
+ * are listed here.
+ */
+enum intel_steering_type {
+ L3BANK,
+ MSLICE,
+ LNCF,
+
+ NUM_STEERING_TYPES
+};
+
enum intel_submission_method {
INTEL_SUBMISSION_RING,
INTEL_SUBMISSION_ELSP,
@@ -145,8 +173,15 @@ struct intel_gt {
struct i915_vma *scratch;
+ struct intel_migrate migrate;
+
+ const struct intel_mmio_range *steering_table[NUM_STEERING_TYPES];
+
struct intel_gt_info {
intel_engine_mask_t engine_mask;
+
+ u32 l3bank_mask;
+
u8 num_engines;
/* Media engine access to SFC per instance */
@@ -154,6 +189,8 @@ struct intel_gt {
/* Slice/subslice/EU info */
struct sseu_dev_info sseu;
+
+ unsigned long mslice_mask;
} info;
};
diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c
index 084ea65d59c0..e137dd32b5b8 100644
--- a/drivers/gpu/drm/i915/gt/intel_gtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gtt.c
@@ -16,7 +16,19 @@ struct drm_i915_gem_object *alloc_pt_lmem(struct i915_address_space *vm, int sz)
{
struct drm_i915_gem_object *obj;
- obj = i915_gem_object_create_lmem(vm->i915, sz, 0);
+ /*
+ * To avoid severe over-allocation when dealing with min_page_size
+ * restrictions, we override that behaviour here by allowing an object
+ * size and page layout which can be smaller. In practice this should be
+ * totally fine, since GTT paging structures are not typically inserted
+ * into the GTT.
+ *
+ * Note that we also hit this path for the scratch page, and for this
+ * case it might need to be 64K, but that should work fine here since we
+ * used the passed in size for the page size, which should ensure it
+ * also has the same alignment.
+ */
+ obj = __i915_gem_object_create_lmem_with_ps(vm->i915, sz, sz, 0);
/*
* Ensure all paging structures for this vm share the same dma-resv
* object underneath, with the idea that one object_lock() will lock
@@ -414,7 +426,7 @@ static void tgl_setup_private_ppat(struct intel_uncore *uncore)
intel_uncore_write(uncore, GEN12_PAT_INDEX(7), GEN8_PPAT_WB);
}
-static void cnl_setup_private_ppat(struct intel_uncore *uncore)
+static void icl_setup_private_ppat(struct intel_uncore *uncore)
{
intel_uncore_write(uncore,
GEN10_PAT_INDEX(0),
@@ -514,8 +526,8 @@ void setup_private_pat(struct intel_uncore *uncore)
if (GRAPHICS_VER(i915) >= 12)
tgl_setup_private_ppat(uncore);
- else if (GRAPHICS_VER(i915) >= 10)
- cnl_setup_private_ppat(uncore);
+ else if (GRAPHICS_VER(i915) >= 11)
+ icl_setup_private_ppat(uncore);
else if (IS_CHERRYVIEW(i915) || IS_GEN9_LP(i915))
chv_setup_private_ppat(uncore);
else
diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h
index edea95b97c36..bc7153018ebd 100644
--- a/drivers/gpu/drm/i915/gt/intel_gtt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gtt.h
@@ -140,7 +140,6 @@ typedef u64 gen8_pte_t;
enum i915_cache_level;
-struct drm_i915_file_private;
struct drm_i915_gem_object;
struct i915_fence_reg;
struct i915_vma;
@@ -220,16 +219,6 @@ struct i915_address_space {
struct intel_gt *gt;
struct drm_i915_private *i915;
struct device *dma;
- /*
- * Every address space belongs to a struct file - except for the global
- * GTT that is owned by the driver (and so @file is set to NULL). In
- * principle, no information should leak from one context to another
- * (or between files/processes etc) unless explicitly shared by the
- * owner. Tracking the owner is important in order to free up per-file
- * objects along with the file, to aide resource tracking, and to
- * assign blame.
- */
- struct drm_i915_file_private *file;
u64 total; /* size addr space maps (ex. 2GB for ggtt) */
u64 reserved; /* size addr space reserved */
@@ -296,6 +285,13 @@ struct i915_address_space {
u32 flags);
void (*cleanup)(struct i915_address_space *vm);
+ void (*foreach)(struct i915_address_space *vm,
+ u64 start, u64 length,
+ void (*fn)(struct i915_address_space *vm,
+ struct i915_page_table *pt,
+ void *data),
+ void *data);
+
struct i915_vma_ops vma_ops;
I915_SELFTEST_DECLARE(struct fault_attr fault_attr);
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index a27bac0a4bfb..bb4af4977920 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -70,7 +70,7 @@ static void set_offsets(u32 *regs,
if (close) {
/* Close the batch; used mainly by live_lrc_layout() */
*regs = MI_BATCH_BUFFER_END;
- if (GRAPHICS_VER(engine->i915) >= 10)
+ if (GRAPHICS_VER(engine->i915) >= 11)
*regs |= BIT(0);
}
}
@@ -484,6 +484,47 @@ static const u8 gen12_rcs_offsets[] = {
END
};
+static const u8 xehp_rcs_offsets[] = {
+ NOP(1),
+ LRI(13, POSTED),
+ REG16(0x244),
+ REG(0x034),
+ REG(0x030),
+ REG(0x038),
+ REG(0x03c),
+ REG(0x168),
+ REG(0x140),
+ REG(0x110),
+ REG(0x1c0),
+ REG(0x1c4),
+ REG(0x1c8),
+ REG(0x180),
+ REG16(0x2b4),
+
+ NOP(5),
+ LRI(9, POSTED),
+ REG16(0x3a8),
+ REG16(0x28c),
+ REG16(0x288),
+ REG16(0x284),
+ REG16(0x280),
+ REG16(0x27c),
+ REG16(0x278),
+ REG16(0x274),
+ REG16(0x270),
+
+ LRI(3, POSTED),
+ REG(0x1b0),
+ REG16(0x5a8),
+ REG16(0x5ac),
+
+ NOP(6),
+ LRI(1, 0),
+ REG(0x0c8),
+
+ END
+};
+
#undef END
#undef REG16
#undef REG
@@ -502,7 +543,9 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
!intel_engine_has_relative_mmio(engine));
if (engine->class == RENDER_CLASS) {
- if (GRAPHICS_VER(engine->i915) >= 12)
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50))
+ return xehp_rcs_offsets;
+ else if (GRAPHICS_VER(engine->i915) >= 12)
return gen12_rcs_offsets;
else if (GRAPHICS_VER(engine->i915) >= 11)
return gen11_rcs_offsets;
@@ -522,7 +565,9 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
static int lrc_ring_mi_mode(const struct intel_engine_cs *engine)
{
- if (GRAPHICS_VER(engine->i915) >= 12)
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50))
+ return 0x70;
+ else if (GRAPHICS_VER(engine->i915) >= 12)
return 0x60;
else if (GRAPHICS_VER(engine->i915) >= 9)
return 0x54;
@@ -534,7 +579,9 @@ static int lrc_ring_mi_mode(const struct intel_engine_cs *engine)
static int lrc_ring_gpr0(const struct intel_engine_cs *engine)
{
- if (GRAPHICS_VER(engine->i915) >= 12)
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50))
+ return 0x84;
+ else if (GRAPHICS_VER(engine->i915) >= 12)
return 0x74;
else if (GRAPHICS_VER(engine->i915) >= 9)
return 0x68;
@@ -578,10 +625,16 @@ static int lrc_ring_indirect_offset(const struct intel_engine_cs *engine)
static int lrc_ring_cmd_buf_cctl(const struct intel_engine_cs *engine)
{
- if (engine->class != RENDER_CLASS)
- return -1;
- if (GRAPHICS_VER(engine->i915) >= 12)
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50))
+ /*
+ * Note that the CSFE context has a dummy slot for CMD_BUF_CCTL
+ * simply to match the RCS context image layout.
+ */
+ return 0xc6;
+ else if (engine->class != RENDER_CLASS)
+ return -1;
+ else if (GRAPHICS_VER(engine->i915) >= 12)
return 0xb6;
else if (GRAPHICS_VER(engine->i915) >= 11)
return 0xaa;
@@ -600,8 +653,6 @@ lrc_ring_indirect_offset_default(const struct intel_engine_cs *engine)
return GEN12_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT;
case 11:
return GEN11_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT;
- case 10:
- return GEN10_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT;
case 9:
return GEN9_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT;
case 8:
@@ -845,7 +896,7 @@ int lrc_alloc(struct intel_context *ce, struct intel_engine_cs *engine)
if (IS_ERR(vma))
return PTR_ERR(vma);
- ring = intel_engine_create_ring(engine, (unsigned long)ce->ring);
+ ring = intel_engine_create_ring(engine, ce->ring_size);
if (IS_ERR(ring)) {
err = PTR_ERR(ring);
goto err_vma;
@@ -1101,6 +1152,14 @@ setup_indirect_ctx_bb(const struct intel_context *ce,
* bits 55-60: SW counter
* bits 61-63: engine class
*
+ * On Xe_HP, the upper dword of the descriptor has a new format:
+ *
+ * bits 32-37: virtual function number
+ * bit 38: mbz, reserved for use by hardware
+ * bits 39-54: SW context ID
+ * bits 55-57: reserved
+ * bits 58-63: SW counter
+ *
* engine info, SW context ID and SW counter need to form a unique number
* (Context ID) per lrc.
*/
@@ -1387,40 +1446,6 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
return batch;
}
-static u32 *
-gen10_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
-{
- int i;
-
- /*
- * WaPipeControlBefore3DStateSamplePattern: cnl
- *
- * Ensure the engine is idle prior to programming a
- * 3DSTATE_SAMPLE_PATTERN during a context restore.
- */
- batch = gen8_emit_pipe_control(batch,
- PIPE_CONTROL_CS_STALL,
- 0);
- /*
- * WaPipeControlBefore3DStateSamplePattern says we need 4 dwords for
- * the PIPE_CONTROL followed by 12 dwords of 0x0, so 16 dwords in
- * total. However, a PIPE_CONTROL is 6 dwords long, not 4, which is
- * confusing. Since gen8_emit_pipe_control() already advances the
- * batch by 6 dwords, we advance the other 10 here, completing a
- * cacheline. It's not clear if the workaround requires this padding
- * before other commands, or if it's just the regular padding we would
- * already have for the workaround bb, so leave it here for now.
- */
- for (i = 0; i < 10; i++)
- *batch++ = MI_NOOP;
-
- /* Pad to end of cacheline */
- while ((unsigned long)batch % CACHELINE_BYTES)
- *batch++ = MI_NOOP;
-
- return batch;
-}
-
#define CTX_WA_BB_SIZE (PAGE_SIZE)
static int lrc_create_wa_ctx(struct intel_engine_cs *engine)
@@ -1473,10 +1498,6 @@ void lrc_init_wa_ctx(struct intel_engine_cs *engine)
case 12:
case 11:
return;
- case 10:
- wa_bb_fn[0] = gen10_init_indirectctx_bb;
- wa_bb_fn[1] = NULL;
- break;
case 9:
wa_bb_fn[0] = gen9_init_indirectctx_bb;
wa_bb_fn[1] = NULL;
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc_reg.h b/drivers/gpu/drm/i915/gt/intel_lrc_reg.h
index 41e5350a7a05..f785d0ed238f 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc_reg.h
+++ b/drivers/gpu/drm/i915/gt/intel_lrc_reg.h
@@ -87,9 +87,10 @@
#define GEN11_CSB_WRITE_PTR_MASK (GEN11_CSB_PTR_MASK << 0)
#define MAX_CONTEXT_HW_ID (1 << 21) /* exclusive */
-#define MAX_GUC_CONTEXT_HW_ID (1 << 20) /* exclusive */
#define GEN11_MAX_CONTEXT_HW_ID (1 << 11) /* exclusive */
/* in Gen12 ID 0x7FF is reserved to indicate idle */
#define GEN12_MAX_CONTEXT_HW_ID (GEN11_MAX_CONTEXT_HW_ID - 1)
+/* in Xe_HP ID 0xFFFF is reserved to indicate "invalid context" */
+#define XEHP_MAX_CONTEXT_HW_ID 0xFFFF
#endif /* _INTEL_LRC_REG_H_ */
diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c
new file mode 100644
index 000000000000..1dac21aa7e5c
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/intel_migrate.c
@@ -0,0 +1,688 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "intel_context.h"
+#include "intel_gpu_commands.h"
+#include "intel_gt.h"
+#include "intel_gtt.h"
+#include "intel_migrate.h"
+#include "intel_ring.h"
+
+struct insert_pte_data {
+ u64 offset;
+ bool is_lmem;
+};
+
+#define CHUNK_SZ SZ_8M /* ~1ms at 8GiB/s preemption delay */
+
+static bool engine_supports_migration(struct intel_engine_cs *engine)
+{
+ if (!engine)
+ return false;
+
+ /*
+ * We need the ability to prevent aribtration (MI_ARB_ON_OFF),
+ * the ability to write PTE using inline data (MI_STORE_DATA)
+ * and of course the ability to do the block transfer (blits).
+ */
+ GEM_BUG_ON(engine->class != COPY_ENGINE_CLASS);
+
+ return true;
+}
+
+static void insert_pte(struct i915_address_space *vm,
+ struct i915_page_table *pt,
+ void *data)
+{
+ struct insert_pte_data *d = data;
+
+ vm->insert_page(vm, px_dma(pt), d->offset, I915_CACHE_NONE,
+ d->is_lmem ? PTE_LM : 0);
+ d->offset += PAGE_SIZE;
+}
+
+static struct i915_address_space *migrate_vm(struct intel_gt *gt)
+{
+ struct i915_vm_pt_stash stash = {};
+ struct i915_ppgtt *vm;
+ int err;
+ int i;
+
+ /*
+ * We construct a very special VM for use by all migration contexts,
+ * it is kept pinned so that it can be used at any time. As we need
+ * to pre-allocate the page directories for the migration VM, this
+ * limits us to only using a small number of prepared vma.
+ *
+ * To be able to pipeline and reschedule migration operations while
+ * avoiding unnecessary contention on the vm itself, the PTE updates
+ * are inline with the blits. All the blits use the same fixed
+ * addresses, with the backing store redirection being updated on the
+ * fly. Only 2 implicit vma are used for all migration operations.
+ *
+ * We lay the ppGTT out as:
+ *
+ * [0, CHUNK_SZ) -> first object
+ * [CHUNK_SZ, 2 * CHUNK_SZ) -> second object
+ * [2 * CHUNK_SZ, 2 * CHUNK_SZ + 2 * CHUNK_SZ >> 9] -> PTE
+ *
+ * By exposing the dma addresses of the page directories themselves
+ * within the ppGTT, we are then able to rewrite the PTE prior to use.
+ * But the PTE update and subsequent migration operation must be atomic,
+ * i.e. within the same non-preemptible window so that we do not switch
+ * to another migration context that overwrites the PTE.
+ *
+ * TODO: Add support for huge LMEM PTEs
+ */
+
+ vm = i915_ppgtt_create(gt);
+ if (IS_ERR(vm))
+ return ERR_CAST(vm);
+
+ if (!vm->vm.allocate_va_range || !vm->vm.foreach) {
+ err = -ENODEV;
+ goto err_vm;
+ }
+
+ /*
+ * Each engine instance is assigned its own chunk in the VM, so
+ * that we can run multiple instances concurrently
+ */
+ for (i = 0; i < ARRAY_SIZE(gt->engine_class[COPY_ENGINE_CLASS]); i++) {
+ struct intel_engine_cs *engine;
+ u64 base = (u64)i << 32;
+ struct insert_pte_data d = {};
+ struct i915_gem_ww_ctx ww;
+ u64 sz;
+
+ engine = gt->engine_class[COPY_ENGINE_CLASS][i];
+ if (!engine_supports_migration(engine))
+ continue;
+
+ /*
+ * We copy in 8MiB chunks. Each PDE covers 2MiB, so we need
+ * 4x2 page directories for source/destination.
+ */
+ sz = 2 * CHUNK_SZ;
+ d.offset = base + sz;
+
+ /*
+ * We need another page directory setup so that we can write
+ * the 8x512 PTE in each chunk.
+ */
+ sz += (sz >> 12) * sizeof(u64);
+
+ err = i915_vm_alloc_pt_stash(&vm->vm, &stash, sz);
+ if (err)
+ goto err_vm;
+
+ for_i915_gem_ww(&ww, err, true) {
+ err = i915_vm_lock_objects(&vm->vm, &ww);
+ if (err)
+ continue;
+ err = i915_vm_map_pt_stash(&vm->vm, &stash);
+ if (err)
+ continue;
+
+ vm->vm.allocate_va_range(&vm->vm, &stash, base, sz);
+ }
+ i915_vm_free_pt_stash(&vm->vm, &stash);
+ if (err)
+ goto err_vm;
+
+ /* Now allow the GPU to rewrite the PTE via its own ppGTT */
+ d.is_lmem = i915_gem_object_is_lmem(vm->vm.scratch[0]);
+ vm->vm.foreach(&vm->vm, base, base + sz, insert_pte, &d);
+ }
+
+ return &vm->vm;
+
+err_vm:
+ i915_vm_put(&vm->vm);
+ return ERR_PTR(err);
+}
+
+static struct intel_engine_cs *first_copy_engine(struct intel_gt *gt)
+{
+ struct intel_engine_cs *engine;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(gt->engine_class[COPY_ENGINE_CLASS]); i++) {
+ engine = gt->engine_class[COPY_ENGINE_CLASS][i];
+ if (engine_supports_migration(engine))
+ return engine;
+ }
+
+ return NULL;
+}
+
+static struct intel_context *pinned_context(struct intel_gt *gt)
+{
+ static struct lock_class_key key;
+ struct intel_engine_cs *engine;
+ struct i915_address_space *vm;
+ struct intel_context *ce;
+
+ engine = first_copy_engine(gt);
+ if (!engine)
+ return ERR_PTR(-ENODEV);
+
+ vm = migrate_vm(gt);
+ if (IS_ERR(vm))
+ return ERR_CAST(vm);
+
+ ce = intel_engine_create_pinned_context(engine, vm, SZ_512K,
+ I915_GEM_HWS_MIGRATE,
+ &key, "migrate");
+ i915_vm_put(vm);
+ return ce;
+}
+
+int intel_migrate_init(struct intel_migrate *m, struct intel_gt *gt)
+{
+ struct intel_context *ce;
+
+ memset(m, 0, sizeof(*m));
+
+ ce = pinned_context(gt);
+ if (IS_ERR(ce))
+ return PTR_ERR(ce);
+
+ m->context = ce;
+ return 0;
+}
+
+static int random_index(unsigned int max)
+{
+ return upper_32_bits(mul_u32_u32(get_random_u32(), max));
+}
+
+static struct intel_context *__migrate_engines(struct intel_gt *gt)
+{
+ struct intel_engine_cs *engines[MAX_ENGINE_INSTANCE];
+ struct intel_engine_cs *engine;
+ unsigned int count, i;
+
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(gt->engine_class[COPY_ENGINE_CLASS]); i++) {
+ engine = gt->engine_class[COPY_ENGINE_CLASS][i];
+ if (engine_supports_migration(engine))
+ engines[count++] = engine;
+ }
+
+ return intel_context_create(engines[random_index(count)]);
+}
+
+struct intel_context *intel_migrate_create_context(struct intel_migrate *m)
+{
+ struct intel_context *ce;
+
+ /*
+ * We randomly distribute contexts across the engines upon constrction,
+ * as they all share the same pinned vm, and so in order to allow
+ * multiple blits to run in parallel, we must construct each blit
+ * to use a different range of the vm for its GTT. This has to be
+ * known at construction, so we can not use the late greedy load
+ * balancing of the virtual-engine.
+ */
+ ce = __migrate_engines(m->context->engine->gt);
+ if (IS_ERR(ce))
+ return ce;
+
+ ce->ring = NULL;
+ ce->ring_size = SZ_256K;
+
+ i915_vm_put(ce->vm);
+ ce->vm = i915_vm_get(m->context->vm);
+
+ return ce;
+}
+
+static inline struct sgt_dma sg_sgt(struct scatterlist *sg)
+{
+ dma_addr_t addr = sg_dma_address(sg);
+
+ return (struct sgt_dma){ sg, addr, addr + sg_dma_len(sg) };
+}
+
+static int emit_no_arbitration(struct i915_request *rq)
+{
+ u32 *cs;
+
+ cs = intel_ring_begin(rq, 2);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+
+ /* Explicitly disable preemption for this request. */
+ *cs++ = MI_ARB_ON_OFF;
+ *cs++ = MI_NOOP;
+ intel_ring_advance(rq, cs);
+
+ return 0;
+}
+
+static int emit_pte(struct i915_request *rq,
+ struct sgt_dma *it,
+ enum i915_cache_level cache_level,
+ bool is_lmem,
+ u64 offset,
+ int length)
+{
+ const u64 encode = rq->context->vm->pte_encode(0, cache_level,
+ is_lmem ? PTE_LM : 0);
+ struct intel_ring *ring = rq->ring;
+ int total = 0;
+ u32 *hdr, *cs;
+ int pkt;
+
+ GEM_BUG_ON(GRAPHICS_VER(rq->engine->i915) < 8);
+
+ /* Compute the page directory offset for the target address range */
+ offset += (u64)rq->engine->instance << 32;
+ offset >>= 12;
+ offset *= sizeof(u64);
+ offset += 2 * CHUNK_SZ;
+
+ cs = intel_ring_begin(rq, 6);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+
+ /* Pack as many PTE updates as possible into a single MI command */
+ pkt = min_t(int, 0x400, ring->space / sizeof(u32) + 5);
+ pkt = min_t(int, pkt, (ring->size - ring->emit) / sizeof(u32) + 5);
+
+ hdr = cs;
+ *cs++ = MI_STORE_DATA_IMM | REG_BIT(21); /* as qword elements */
+ *cs++ = lower_32_bits(offset);
+ *cs++ = upper_32_bits(offset);
+
+ do {
+ if (cs - hdr >= pkt) {
+ *hdr += cs - hdr - 2;
+ *cs++ = MI_NOOP;
+
+ ring->emit = (void *)cs - ring->vaddr;
+ intel_ring_advance(rq, cs);
+ intel_ring_update_space(ring);
+
+ cs = intel_ring_begin(rq, 6);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+
+ pkt = min_t(int, 0x400, ring->space / sizeof(u32) + 5);
+ pkt = min_t(int, pkt, (ring->size - ring->emit) / sizeof(u32) + 5);
+
+ hdr = cs;
+ *cs++ = MI_STORE_DATA_IMM | REG_BIT(21);
+ *cs++ = lower_32_bits(offset);
+ *cs++ = upper_32_bits(offset);
+ }
+
+ *cs++ = lower_32_bits(encode | it->dma);
+ *cs++ = upper_32_bits(encode | it->dma);
+
+ offset += 8;
+ total += I915_GTT_PAGE_SIZE;
+
+ it->dma += I915_GTT_PAGE_SIZE;
+ if (it->dma >= it->max) {
+ it->sg = __sg_next(it->sg);
+ if (!it->sg || sg_dma_len(it->sg) == 0)
+ break;
+
+ it->dma = sg_dma_address(it->sg);
+ it->max = it->dma + sg_dma_len(it->sg);
+ }
+ } while (total < length);
+
+ *hdr += cs - hdr - 2;
+ *cs++ = MI_NOOP;
+
+ ring->emit = (void *)cs - ring->vaddr;
+ intel_ring_advance(rq, cs);
+ intel_ring_update_space(ring);
+
+ return total;
+}
+
+static bool wa_1209644611_applies(int ver, u32 size)
+{
+ u32 height = size >> PAGE_SHIFT;
+
+ if (ver != 11)
+ return false;
+
+ return height % 4 == 3 && height <= 8;
+}
+
+static int emit_copy(struct i915_request *rq, int size)
+{
+ const int ver = GRAPHICS_VER(rq->engine->i915);
+ u32 instance = rq->engine->instance;
+ u32 *cs;
+
+ cs = intel_ring_begin(rq, ver >= 8 ? 10 : 6);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+
+ if (ver >= 9 && !wa_1209644611_applies(ver, size)) {
+ *cs++ = GEN9_XY_FAST_COPY_BLT_CMD | (10 - 2);
+ *cs++ = BLT_DEPTH_32 | PAGE_SIZE;
+ *cs++ = 0;
+ *cs++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE / 4;
+ *cs++ = CHUNK_SZ; /* dst offset */
+ *cs++ = instance;
+ *cs++ = 0;
+ *cs++ = PAGE_SIZE;
+ *cs++ = 0; /* src offset */
+ *cs++ = instance;
+ } else if (ver >= 8) {
+ *cs++ = XY_SRC_COPY_BLT_CMD | BLT_WRITE_RGBA | (10 - 2);
+ *cs++ = BLT_DEPTH_32 | BLT_ROP_SRC_COPY | PAGE_SIZE;
+ *cs++ = 0;
+ *cs++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE / 4;
+ *cs++ = CHUNK_SZ; /* dst offset */
+ *cs++ = instance;
+ *cs++ = 0;
+ *cs++ = PAGE_SIZE;
+ *cs++ = 0; /* src offset */
+ *cs++ = instance;
+ } else {
+ GEM_BUG_ON(instance);
+ *cs++ = SRC_COPY_BLT_CMD | BLT_WRITE_RGBA | (6 - 2);
+ *cs++ = BLT_DEPTH_32 | BLT_ROP_SRC_COPY | PAGE_SIZE;
+ *cs++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE;
+ *cs++ = CHUNK_SZ; /* dst offset */
+ *cs++ = PAGE_SIZE;
+ *cs++ = 0; /* src offset */
+ }
+
+ intel_ring_advance(rq, cs);
+ return 0;
+}
+
+int
+intel_context_migrate_copy(struct intel_context *ce,
+ struct dma_fence *await,
+ struct scatterlist *src,
+ enum i915_cache_level src_cache_level,
+ bool src_is_lmem,
+ struct scatterlist *dst,
+ enum i915_cache_level dst_cache_level,
+ bool dst_is_lmem,
+ struct i915_request **out)
+{
+ struct sgt_dma it_src = sg_sgt(src), it_dst = sg_sgt(dst);
+ struct i915_request *rq;
+ int err;
+
+ GEM_BUG_ON(ce->vm != ce->engine->gt->migrate.context->vm);
+ *out = NULL;
+
+ GEM_BUG_ON(ce->ring->size < SZ_64K);
+
+ do {
+ int len;
+
+ rq = i915_request_create(ce);
+ if (IS_ERR(rq)) {
+ err = PTR_ERR(rq);
+ goto out_ce;
+ }
+
+ if (await) {
+ err = i915_request_await_dma_fence(rq, await);
+ if (err)
+ goto out_rq;
+
+ if (rq->engine->emit_init_breadcrumb) {
+ err = rq->engine->emit_init_breadcrumb(rq);
+ if (err)
+ goto out_rq;
+ }
+
+ await = NULL;
+ }
+
+ /* The PTE updates + copy must not be interrupted. */
+ err = emit_no_arbitration(rq);
+ if (err)
+ goto out_rq;
+
+ len = emit_pte(rq, &it_src, src_cache_level, src_is_lmem, 0,
+ CHUNK_SZ);
+ if (len <= 0) {
+ err = len;
+ goto out_rq;
+ }
+
+ err = emit_pte(rq, &it_dst, dst_cache_level, dst_is_lmem,
+ CHUNK_SZ, len);
+ if (err < 0)
+ goto out_rq;
+ if (err < len) {
+ err = -EINVAL;
+ goto out_rq;
+ }
+
+ err = rq->engine->emit_flush(rq, EMIT_INVALIDATE);
+ if (err)
+ goto out_rq;
+
+ err = emit_copy(rq, len);
+
+ /* Arbitration is re-enabled between requests. */
+out_rq:
+ if (*out)
+ i915_request_put(*out);
+ *out = i915_request_get(rq);
+ i915_request_add(rq);
+ if (err || !it_src.sg || !sg_dma_len(it_src.sg))
+ break;
+
+ cond_resched();
+ } while (1);
+
+out_ce:
+ return err;
+}
+
+static int emit_clear(struct i915_request *rq, int size, u32 value)
+{
+ const int ver = GRAPHICS_VER(rq->engine->i915);
+ u32 instance = rq->engine->instance;
+ u32 *cs;
+
+ GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX);
+
+ cs = intel_ring_begin(rq, ver >= 8 ? 8 : 6);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+
+ if (ver >= 8) {
+ *cs++ = XY_COLOR_BLT_CMD | BLT_WRITE_RGBA | (7 - 2);
+ *cs++ = BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | PAGE_SIZE;
+ *cs++ = 0;
+ *cs++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE / 4;
+ *cs++ = 0; /* offset */
+ *cs++ = instance;
+ *cs++ = value;
+ *cs++ = MI_NOOP;
+ } else {
+ GEM_BUG_ON(instance);
+ *cs++ = XY_COLOR_BLT_CMD | BLT_WRITE_RGBA | (6 - 2);
+ *cs++ = BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | PAGE_SIZE;
+ *cs++ = 0;
+ *cs++ = size >> PAGE_SHIFT << 16 | PAGE_SIZE / 4;
+ *cs++ = 0;
+ *cs++ = value;
+ }
+
+ intel_ring_advance(rq, cs);
+ return 0;
+}
+
+int
+intel_context_migrate_clear(struct intel_context *ce,
+ struct dma_fence *await,
+ struct scatterlist *sg,
+ enum i915_cache_level cache_level,
+ bool is_lmem,
+ u32 value,
+ struct i915_request **out)
+{
+ struct sgt_dma it = sg_sgt(sg);
+ struct i915_request *rq;
+ int err;
+
+ GEM_BUG_ON(ce->vm != ce->engine->gt->migrate.context->vm);
+ *out = NULL;
+
+ GEM_BUG_ON(ce->ring->size < SZ_64K);
+
+ do {
+ int len;
+
+ rq = i915_request_create(ce);
+ if (IS_ERR(rq)) {
+ err = PTR_ERR(rq);
+ goto out_ce;
+ }
+
+ if (await) {
+ err = i915_request_await_dma_fence(rq, await);
+ if (err)
+ goto out_rq;
+
+ if (rq->engine->emit_init_breadcrumb) {
+ err = rq->engine->emit_init_breadcrumb(rq);
+ if (err)
+ goto out_rq;
+ }
+
+ await = NULL;
+ }
+
+ /* The PTE updates + clear must not be interrupted. */
+ err = emit_no_arbitration(rq);
+ if (err)
+ goto out_rq;
+
+ len = emit_pte(rq, &it, cache_level, is_lmem, 0, CHUNK_SZ);
+ if (len <= 0) {
+ err = len;
+ goto out_rq;
+ }
+
+ err = rq->engine->emit_flush(rq, EMIT_INVALIDATE);
+ if (err)
+ goto out_rq;
+
+ err = emit_clear(rq, len, value);
+
+ /* Arbitration is re-enabled between requests. */
+out_rq:
+ if (*out)
+ i915_request_put(*out);
+ *out = i915_request_get(rq);
+ i915_request_add(rq);
+ if (err || !it.sg || !sg_dma_len(it.sg))
+ break;
+
+ cond_resched();
+ } while (1);
+
+out_ce:
+ return err;
+}
+
+int intel_migrate_copy(struct intel_migrate *m,
+ struct i915_gem_ww_ctx *ww,
+ struct dma_fence *await,
+ struct scatterlist *src,
+ enum i915_cache_level src_cache_level,
+ bool src_is_lmem,
+ struct scatterlist *dst,
+ enum i915_cache_level dst_cache_level,
+ bool dst_is_lmem,
+ struct i915_request **out)
+{
+ struct intel_context *ce;
+ int err;
+
+ *out = NULL;
+ if (!m->context)
+ return -ENODEV;
+
+ ce = intel_migrate_create_context(m);
+ if (IS_ERR(ce))
+ ce = intel_context_get(m->context);
+ GEM_BUG_ON(IS_ERR(ce));
+
+ err = intel_context_pin_ww(ce, ww);
+ if (err)
+ goto out;
+
+ err = intel_context_migrate_copy(ce, await,
+ src, src_cache_level, src_is_lmem,
+ dst, dst_cache_level, dst_is_lmem,
+ out);
+
+ intel_context_unpin(ce);
+out:
+ intel_context_put(ce);
+ return err;
+}
+
+int
+intel_migrate_clear(struct intel_migrate *m,
+ struct i915_gem_ww_ctx *ww,
+ struct dma_fence *await,
+ struct scatterlist *sg,
+ enum i915_cache_level cache_level,
+ bool is_lmem,
+ u32 value,
+ struct i915_request **out)
+{
+ struct intel_context *ce;
+ int err;
+
+ *out = NULL;
+ if (!m->context)
+ return -ENODEV;
+
+ ce = intel_migrate_create_context(m);
+ if (IS_ERR(ce))
+ ce = intel_context_get(m->context);
+ GEM_BUG_ON(IS_ERR(ce));
+
+ err = intel_context_pin_ww(ce, ww);
+ if (err)
+ goto out;
+
+ err = intel_context_migrate_clear(ce, await, sg, cache_level,
+ is_lmem, value, out);
+
+ intel_context_unpin(ce);
+out:
+ intel_context_put(ce);
+ return err;
+}
+
+void intel_migrate_fini(struct intel_migrate *m)
+{
+ struct intel_context *ce;
+
+ ce = fetch_and_zero(&m->context);
+ if (!ce)
+ return;
+
+ intel_engine_destroy_pinned_context(ce);
+}
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftest_migrate.c"
+#endif
diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.h b/drivers/gpu/drm/i915/gt/intel_migrate.h
new file mode 100644
index 000000000000..4e18e755a00b
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/intel_migrate.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __INTEL_MIGRATE__
+#define __INTEL_MIGRATE__
+
+#include <linux/types.h>
+
+#include "intel_migrate_types.h"
+
+struct dma_fence;
+struct i915_request;
+struct i915_gem_ww_ctx;
+struct intel_gt;
+struct scatterlist;
+enum i915_cache_level;
+
+int intel_migrate_init(struct intel_migrate *m, struct intel_gt *gt);
+
+struct intel_context *intel_migrate_create_context(struct intel_migrate *m);
+
+int intel_migrate_copy(struct intel_migrate *m,
+ struct i915_gem_ww_ctx *ww,
+ struct dma_fence *await,
+ struct scatterlist *src,
+ enum i915_cache_level src_cache_level,
+ bool src_is_lmem,
+ struct scatterlist *dst,
+ enum i915_cache_level dst_cache_level,
+ bool dst_is_lmem,
+ struct i915_request **out);
+
+int intel_context_migrate_copy(struct intel_context *ce,
+ struct dma_fence *await,
+ struct scatterlist *src,
+ enum i915_cache_level src_cache_level,
+ bool src_is_lmem,
+ struct scatterlist *dst,
+ enum i915_cache_level dst_cache_level,
+ bool dst_is_lmem,
+ struct i915_request **out);
+
+int
+intel_migrate_clear(struct intel_migrate *m,
+ struct i915_gem_ww_ctx *ww,
+ struct dma_fence *await,
+ struct scatterlist *sg,
+ enum i915_cache_level cache_level,
+ bool is_lmem,
+ u32 value,
+ struct i915_request **out);
+int
+intel_context_migrate_clear(struct intel_context *ce,
+ struct dma_fence *await,
+ struct scatterlist *sg,
+ enum i915_cache_level cache_level,
+ bool is_lmem,
+ u32 value,
+ struct i915_request **out);
+
+void intel_migrate_fini(struct intel_migrate *m);
+
+#endif /* __INTEL_MIGRATE__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_migrate_types.h b/drivers/gpu/drm/i915/gt/intel_migrate_types.h
new file mode 100644
index 000000000000..d98230597f42
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/intel_migrate_types.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __INTEL_MIGRATE_TYPES__
+#define __INTEL_MIGRATE_TYPES__
+
+struct intel_context;
+
+struct intel_migrate {
+ struct intel_context *context;
+};
+
+#endif /* __INTEL_MIGRATE_TYPES__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c
index 17848807f111..582c4423b95d 100644
--- a/drivers/gpu/drm/i915/gt/intel_mocs.c
+++ b/drivers/gpu/drm/i915/gt/intel_mocs.c
@@ -352,7 +352,7 @@ static unsigned int get_mocs_settings(const struct drm_i915_private *i915,
table->size = ARRAY_SIZE(icl_mocs_table);
table->table = icl_mocs_table;
table->n_entries = GEN9_NUM_MOCS_ENTRIES;
- } else if (IS_GEN9_BC(i915) || IS_CANNONLAKE(i915)) {
+ } else if (IS_GEN9_BC(i915)) {
table->size = ARRAY_SIZE(skl_mocs_table);
table->n_entries = GEN9_NUM_MOCS_ENTRIES;
table->table = skl_mocs_table;
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
index 259d7eb4e165..799d382eea79 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6.c
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
@@ -62,20 +62,25 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
u32 pg_enable;
int i;
- /* 2b: Program RC6 thresholds.*/
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85);
- set(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150);
+ /*
+ * With GuCRC, these parameters are set by GuC
+ */
+ if (!intel_uc_uses_guc_rc(&gt->uc)) {
+ /* 2b: Program RC6 thresholds.*/
+ set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85);
+ set(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150);
- set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
- set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
- for_each_engine(engine, rc6_to_gt(rc6), id)
- set(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
+ set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+ set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+ for_each_engine(engine, rc6_to_gt(rc6), id)
+ set(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
- set(uncore, GUC_MAX_IDLE_COUNT, 0xA);
+ set(uncore, GUC_MAX_IDLE_COUNT, 0xA);
- set(uncore, GEN6_RC_SLEEP, 0);
+ set(uncore, GEN6_RC_SLEEP, 0);
- set(uncore, GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+ set(uncore, GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+ }
/*
* 2c: Program Coarse Power Gating Policies.
@@ -98,11 +103,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60);
set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60);
- /* 3a: Enable RC6 */
- rc6->ctl_enable =
- GEN6_RC_CTL_HW_ENABLE |
- GEN6_RC_CTL_RC6_ENABLE |
- GEN6_RC_CTL_EI_MODE(1);
+ /* 3a: Enable RC6
+ *
+ * With GuCRC, we do not enable bit 31 of RC_CTL,
+ * thus allowing GuC to control RC6 entry/exit fully instead.
+ * We will not set the HW ENABLE and EI bits
+ */
+ if (!intel_guc_rc_enable(&gt->uc.guc))
+ rc6->ctl_enable = GEN6_RC_CTL_RC6_ENABLE;
+ else
+ rc6->ctl_enable =
+ GEN6_RC_CTL_HW_ENABLE |
+ GEN6_RC_CTL_RC6_ENABLE |
+ GEN6_RC_CTL_EI_MODE(1);
pg_enable =
GEN9_RENDER_PG_ENABLE |
@@ -126,7 +139,7 @@ static void gen9_rc6_enable(struct intel_rc6 *rc6)
enum intel_engine_id id;
/* 2b: Program RC6 thresholds.*/
- if (GRAPHICS_VER(rc6_to_i915(rc6)) >= 10) {
+ if (GRAPHICS_VER(rc6_to_i915(rc6)) >= 11) {
set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85);
set(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150);
} else if (IS_SKYLAKE(rc6_to_i915(rc6))) {
@@ -513,6 +526,10 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6)
{
struct drm_i915_private *i915 = rc6_to_i915(rc6);
struct intel_uncore *uncore = rc6_to_uncore(rc6);
+ struct intel_gt *gt = rc6_to_gt(rc6);
+
+ /* Take control of RC6 back from GuC */
+ intel_guc_rc_disable(&gt->uc.guc);
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
if (GRAPHICS_VER(i915) >= 9)
diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c
index f7366b054f8e..a74b72f50cc9 100644
--- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c
+++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c
@@ -9,7 +9,8 @@
#include "intel_region_ttm.h"
#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
-#include "intel_region_lmem.h"
+#include "gem/i915_gem_ttm.h"
+#include "gt/intel_gt.h"
static int init_fake_lmem_bar(struct intel_memory_region *mem)
{
@@ -107,7 +108,7 @@ out_no_io:
static const struct intel_memory_region_ops intel_region_lmem_ops = {
.init = region_lmem_init,
.release = region_lmem_release,
- .init_object = __i915_gem_lmem_object_init,
+ .init_object = __i915_gem_ttm_object_init,
};
struct intel_memory_region *
@@ -157,7 +158,7 @@ intel_gt_setup_fake_lmem(struct intel_gt *gt)
static bool get_legacy_lowmem_region(struct intel_uncore *uncore,
u64 *start, u32 *size)
{
- if (!IS_DG1_REVID(uncore->i915, DG1_REVID_A0, DG1_REVID_B0))
+ if (!IS_DG1_GT_STEP(uncore->i915, STEP_A0, STEP_C0))
return false;
*start = 0;
diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.h b/drivers/gpu/drm/i915/gt/intel_renderstate.h
index 48f009203917..4da4c5234ef0 100644
--- a/drivers/gpu/drm/i915/gt/intel_renderstate.h
+++ b/drivers/gpu/drm/i915/gt/intel_renderstate.h
@@ -8,6 +8,7 @@
#include <linux/types.h>
#include "i915_gem.h"
+#include "i915_gem_ww.h"
struct i915_request;
struct intel_context;
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
index 72251638d4ea..91200c43951f 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -22,7 +22,6 @@
#include "intel_reset.h"
#include "uc/intel_guc.h"
-#include "uc/intel_guc_submission.h"
#define RESET_MAX_RETRIES 3
@@ -39,21 +38,6 @@ static void rmw_clear_fw(struct intel_uncore *uncore, i915_reg_t reg, u32 clr)
intel_uncore_rmw_fw(uncore, reg, clr, 0);
}
-static void skip_context(struct i915_request *rq)
-{
- struct intel_context *hung_ctx = rq->context;
-
- list_for_each_entry_from_rcu(rq, &hung_ctx->timeline->requests, link) {
- if (!i915_request_is_active(rq))
- return;
-
- if (rq->context == hung_ctx) {
- i915_request_set_error_once(rq, -EIO);
- __i915_request_skip(rq);
- }
- }
-}
-
static void client_mark_guilty(struct i915_gem_context *ctx, bool banned)
{
struct drm_i915_file_private *file_priv = ctx->file_priv;
@@ -88,10 +72,8 @@ static bool mark_guilty(struct i915_request *rq)
bool banned;
int i;
- if (intel_context_is_closed(rq->context)) {
- intel_context_set_banned(rq->context);
+ if (intel_context_is_closed(rq->context))
return true;
- }
rcu_read_lock();
ctx = rcu_dereference(rq->context->gem_context);
@@ -123,11 +105,9 @@ static bool mark_guilty(struct i915_request *rq)
banned = !i915_gem_context_is_recoverable(ctx);
if (time_before(jiffies, prev_hang + CONTEXT_FAST_HANG_JIFFIES))
banned = true;
- if (banned) {
+ if (banned)
drm_dbg(&ctx->i915->drm, "context %s: guilty %d, banned\n",
ctx->name, atomic_read(&ctx->guilty_count));
- intel_context_set_banned(rq->context);
- }
client_mark_guilty(ctx, banned);
@@ -149,6 +129,8 @@ static void mark_innocent(struct i915_request *rq)
void __i915_request_reset(struct i915_request *rq, bool guilty)
{
+ bool banned = false;
+
RQ_TRACE(rq, "guilty? %s\n", yesno(guilty));
GEM_BUG_ON(__i915_request_is_complete(rq));
@@ -156,13 +138,15 @@ void __i915_request_reset(struct i915_request *rq, bool guilty)
if (guilty) {
i915_request_set_error_once(rq, -EIO);
__i915_request_skip(rq);
- if (mark_guilty(rq))
- skip_context(rq);
+ banned = mark_guilty(rq);
} else {
i915_request_set_error_once(rq, -EAGAIN);
mark_innocent(rq);
}
rcu_read_unlock();
+
+ if (banned)
+ intel_context_ban(rq->context, rq);
}
static bool i915_in_reset(struct pci_dev *pdev)
@@ -515,8 +499,14 @@ static int gen11_reset_engines(struct intel_gt *gt,
[VCS1] = GEN11_GRDOM_MEDIA2,
[VCS2] = GEN11_GRDOM_MEDIA3,
[VCS3] = GEN11_GRDOM_MEDIA4,
+ [VCS4] = GEN11_GRDOM_MEDIA5,
+ [VCS5] = GEN11_GRDOM_MEDIA6,
+ [VCS6] = GEN11_GRDOM_MEDIA7,
+ [VCS7] = GEN11_GRDOM_MEDIA8,
[VECS0] = GEN11_GRDOM_VECS,
[VECS1] = GEN11_GRDOM_VECS2,
+ [VECS2] = GEN11_GRDOM_VECS3,
+ [VECS3] = GEN11_GRDOM_VECS4,
};
struct intel_engine_cs *engine;
intel_engine_mask_t tmp;
@@ -826,6 +816,8 @@ static int gt_reset(struct intel_gt *gt, intel_engine_mask_t stalled_mask)
__intel_engine_reset(engine, stalled_mask & engine->mask);
local_bh_enable();
+ intel_uc_reset(&gt->uc, true);
+
intel_ggtt_restore_fences(gt->ggtt);
return err;
@@ -850,6 +842,8 @@ static void reset_finish(struct intel_gt *gt, intel_engine_mask_t awake)
if (awake & engine->mask)
intel_engine_pm_put(engine);
}
+
+ intel_uc_reset_finish(&gt->uc);
}
static void nop_submit_request(struct i915_request *request)
@@ -903,6 +897,7 @@ static void __intel_gt_set_wedged(struct intel_gt *gt)
for_each_engine(engine, gt, id)
if (engine->reset.cancel)
engine->reset.cancel(engine);
+ intel_uc_cancel_requests(&gt->uc);
local_bh_enable();
reset_finish(gt, awake);
@@ -1191,6 +1186,9 @@ int __intel_engine_reset_bh(struct intel_engine_cs *engine, const char *msg)
ENGINE_TRACE(engine, "flags=%lx\n", gt->reset.flags);
GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &gt->reset.flags));
+ if (intel_engine_uses_guc(engine))
+ return -ENODEV;
+
if (!intel_engine_pm_get_if_awake(engine))
return 0;
@@ -1201,13 +1199,10 @@ int __intel_engine_reset_bh(struct intel_engine_cs *engine, const char *msg)
"Resetting %s for %s\n", engine->name, msg);
atomic_inc(&engine->i915->gpu_error.reset_engine_count[engine->uabi_class]);
- if (intel_engine_uses_guc(engine))
- ret = intel_guc_reset_engine(&engine->gt->uc.guc, engine);
- else
- ret = intel_gt_reset_engine(engine);
+ ret = intel_gt_reset_engine(engine);
if (ret) {
/* If we fail here, we expect to fallback to a global reset */
- ENGINE_TRACE(engine, "Failed to reset, err: %d\n", ret);
+ ENGINE_TRACE(engine, "Failed to reset %s, err: %d\n", engine->name, ret);
goto out;
}
@@ -1341,7 +1336,8 @@ void intel_gt_handle_error(struct intel_gt *gt,
* Try engine reset when available. We fall back to full reset if
* single reset fails.
*/
- if (intel_has_reset_engine(gt) && !intel_gt_is_wedged(gt)) {
+ if (!intel_uc_uses_guc_submission(&gt->uc) &&
+ intel_has_reset_engine(gt) && !intel_gt_is_wedged(gt)) {
local_bh_disable();
for_each_engine_masked(engine, gt, engine_mask, tmp) {
BUILD_BUG_ON(I915_RESET_MODESET >= I915_RESET_ENGINE);
diff --git a/drivers/gpu/drm/i915/gt/intel_ring.h b/drivers/gpu/drm/i915/gt/intel_ring.h
index dbf5f14a136f..1b32dadfb8c3 100644
--- a/drivers/gpu/drm/i915/gt/intel_ring.h
+++ b/drivers/gpu/drm/i915/gt/intel_ring.h
@@ -49,6 +49,7 @@ static inline void intel_ring_advance(struct i915_request *rq, u32 *cs)
* intel_ring_begin()).
*/
GEM_BUG_ON((rq->ring->vaddr + rq->ring->emit) != cs);
+ GEM_BUG_ON(!IS_ALIGNED(rq->ring->emit, 8)); /* RING_TAIL qword align */
}
static inline u32 intel_ring_wrap(const struct intel_ring *ring, u32 pos)
diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c
index 37d74d4ed59b..2958e2fae380 100644
--- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c
@@ -16,6 +16,7 @@
#include "intel_reset.h"
#include "intel_ring.h"
#include "shmem_utils.h"
+#include "intel_engine_heartbeat.h"
/* Rough estimate of the typical request size, performing a flush,
* set-context and then emitting the batch.
@@ -342,9 +343,9 @@ static void reset_rewind(struct intel_engine_cs *engine, bool stalled)
u32 head;
rq = NULL;
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
rcu_read_lock();
- list_for_each_entry(pos, &engine->active.requests, sched.link) {
+ list_for_each_entry(pos, &engine->sched_engine->requests, sched.link) {
if (!__i915_request_is_complete(pos)) {
rq = pos;
break;
@@ -399,7 +400,7 @@ static void reset_rewind(struct intel_engine_cs *engine, bool stalled)
}
engine->legacy.ring->head = intel_ring_wrap(engine->legacy.ring, head);
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
}
static void reset_finish(struct intel_engine_cs *engine)
@@ -411,16 +412,16 @@ static void reset_cancel(struct intel_engine_cs *engine)
struct i915_request *request;
unsigned long flags;
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
/* Mark all submitted requests as skipped. */
- list_for_each_entry(request, &engine->active.requests, sched.link)
+ list_for_each_entry(request, &engine->sched_engine->requests, sched.link)
i915_request_put(i915_request_mark_eio(request));
intel_engine_signal_breadcrumbs(engine);
/* Remaining _unready_ requests will be nop'ed when submitted */
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
}
static void i9xx_submit_request(struct i915_request *request)
@@ -586,9 +587,44 @@ static void ring_context_reset(struct intel_context *ce)
clear_bit(CONTEXT_VALID_BIT, &ce->flags);
}
+static void ring_context_ban(struct intel_context *ce,
+ struct i915_request *rq)
+{
+ struct intel_engine_cs *engine;
+
+ if (!rq || !i915_request_is_active(rq))
+ return;
+
+ engine = rq->engine;
+ lockdep_assert_held(&engine->sched_engine->lock);
+ list_for_each_entry_continue(rq, &engine->sched_engine->requests,
+ sched.link)
+ if (rq->context == ce) {
+ i915_request_set_error_once(rq, -EIO);
+ __i915_request_skip(rq);
+ }
+}
+
+static void ring_context_cancel_request(struct intel_context *ce,
+ struct i915_request *rq)
+{
+ struct intel_engine_cs *engine = NULL;
+
+ i915_request_active_engine(rq, &engine);
+
+ if (engine && intel_engine_pulse(engine))
+ intel_gt_handle_error(engine->gt, engine->mask, 0,
+ "request cancellation by %s",
+ current->comm);
+}
+
static const struct intel_context_ops ring_context_ops = {
.alloc = ring_context_alloc,
+ .cancel_request = ring_context_cancel_request,
+
+ .ban = ring_context_ban,
+
.pre_pin = ring_context_pre_pin,
.pin = ring_context_pin,
.unpin = ring_context_unpin,
@@ -1047,6 +1083,25 @@ static void setup_irq(struct intel_engine_cs *engine)
}
}
+static void add_to_engine(struct i915_request *rq)
+{
+ lockdep_assert_held(&rq->engine->sched_engine->lock);
+ list_move_tail(&rq->sched.link, &rq->engine->sched_engine->requests);
+}
+
+static void remove_from_engine(struct i915_request *rq)
+{
+ spin_lock_irq(&rq->engine->sched_engine->lock);
+ list_del_init(&rq->sched.link);
+
+ /* Prevent further __await_execution() registering a cb, then flush */
+ set_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags);
+
+ spin_unlock_irq(&rq->engine->sched_engine->lock);
+
+ i915_request_notify_execute_cb_imm(rq);
+}
+
static void setup_common(struct intel_engine_cs *engine)
{
struct drm_i915_private *i915 = engine->i915;
@@ -1064,6 +1119,9 @@ static void setup_common(struct intel_engine_cs *engine)
engine->reset.cancel = reset_cancel;
engine->reset.finish = reset_finish;
+ engine->add_active_request = add_to_engine;
+ engine->remove_active_request = remove_from_engine;
+
engine->cops = &ring_context_ops;
engine->request_alloc = ring_request_alloc;
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
index 06e9a8ed4e03..d812b27835f8 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -37,6 +37,20 @@ static struct intel_uncore *rps_to_uncore(struct intel_rps *rps)
return rps_to_gt(rps)->uncore;
}
+static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps)
+{
+ struct intel_gt *gt = rps_to_gt(rps);
+
+ return &gt->uc.guc.slpc;
+}
+
+static bool rps_uses_slpc(struct intel_rps *rps)
+{
+ struct intel_gt *gt = rps_to_gt(rps);
+
+ return intel_uc_uses_guc_slpc(&gt->uc);
+}
+
static u32 rps_pm_sanitize_mask(struct intel_rps *rps, u32 mask)
{
return mask & ~rps->pm_intrmsk_mbz;
@@ -167,6 +181,8 @@ static void rps_enable_interrupts(struct intel_rps *rps)
{
struct intel_gt *gt = rps_to_gt(rps);
+ GEM_BUG_ON(rps_uses_slpc(rps));
+
GT_TRACE(gt, "interrupts:on rps->pm_events: %x, rps_pm_mask:%x\n",
rps->pm_events, rps_pm_mask(rps, rps->last_freq));
@@ -771,6 +787,8 @@ static int gen6_rps_set(struct intel_rps *rps, u8 val)
struct drm_i915_private *i915 = rps_to_i915(rps);
u32 swreq;
+ GEM_BUG_ON(rps_uses_slpc(rps));
+
if (GRAPHICS_VER(i915) >= 9)
swreq = GEN9_FREQUENCY(val);
else if (IS_HASWELL(i915) || IS_BROADWELL(i915))
@@ -861,6 +879,9 @@ void intel_rps_park(struct intel_rps *rps)
{
int adj;
+ if (!intel_rps_is_enabled(rps))
+ return;
+
GEM_BUG_ON(atomic_read(&rps->num_waiters));
if (!intel_rps_clear_active(rps))
@@ -999,7 +1020,7 @@ static void gen6_rps_init(struct intel_rps *rps)
rps->efficient_freq = rps->rp1_freq;
if (IS_HASWELL(i915) || IS_BROADWELL(i915) ||
- IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 10) {
+ IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 11) {
u32 ddcc_status = 0;
if (sandybridge_pcode_read(i915,
@@ -1012,7 +1033,7 @@ static void gen6_rps_init(struct intel_rps *rps)
rps->max_freq);
}
- if (IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 10) {
+ if (IS_GEN9_BC(i915) || GRAPHICS_VER(i915) >= 11) {
/* Store the frequency values in 16.66 MHZ units, which is
* the natural hardware unit for SKL
*/
@@ -1356,6 +1377,9 @@ void intel_rps_enable(struct intel_rps *rps)
if (!HAS_RPS(i915))
return;
+ if (rps_uses_slpc(rps))
+ return;
+
intel_gt_check_clock_frequency(rps_to_gt(rps));
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
@@ -1829,6 +1853,9 @@ void intel_rps_init(struct intel_rps *rps)
{
struct drm_i915_private *i915 = rps_to_i915(rps);
+ if (rps_uses_slpc(rps))
+ return;
+
if (IS_CHERRYVIEW(i915))
chv_rps_init(rps);
else if (IS_VALLEYVIEW(i915))
@@ -1877,10 +1904,17 @@ void intel_rps_init(struct intel_rps *rps)
if (GRAPHICS_VER(i915) >= 8 && GRAPHICS_VER(i915) < 11)
rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC;
+
+ /* GuC needs ARAT expired interrupt unmasked */
+ if (intel_uc_uses_guc_submission(&rps_to_gt(rps)->uc))
+ rps->pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK;
}
void intel_rps_sanitize(struct intel_rps *rps)
{
+ if (rps_uses_slpc(rps))
+ return;
+
if (GRAPHICS_VER(rps_to_i915(rps)) >= 6)
rps_disable_interrupts(rps);
}
@@ -1936,6 +1970,176 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
return freq;
}
+u32 intel_rps_read_punit_req(struct intel_rps *rps)
+{
+ struct intel_uncore *uncore = rps_to_uncore(rps);
+
+ return intel_uncore_read(uncore, GEN6_RPNSWREQ);
+}
+
+static u32 intel_rps_get_req(u32 pureq)
+{
+ u32 req = pureq >> GEN9_SW_REQ_UNSLICE_RATIO_SHIFT;
+
+ return req;
+}
+
+u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps)
+{
+ u32 freq = intel_rps_get_req(intel_rps_read_punit_req(rps));
+
+ return intel_gpu_freq(rps, freq);
+}
+
+u32 intel_rps_get_requested_frequency(struct intel_rps *rps)
+{
+ if (rps_uses_slpc(rps))
+ return intel_rps_read_punit_req_frequency(rps);
+ else
+ return intel_gpu_freq(rps, rps->cur_freq);
+}
+
+u32 intel_rps_get_max_frequency(struct intel_rps *rps)
+{
+ struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+ if (rps_uses_slpc(rps))
+ return slpc->max_freq_softlimit;
+ else
+ return intel_gpu_freq(rps, rps->max_freq_softlimit);
+}
+
+u32 intel_rps_get_rp0_frequency(struct intel_rps *rps)
+{
+ struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+ if (rps_uses_slpc(rps))
+ return slpc->rp0_freq;
+ else
+ return intel_gpu_freq(rps, rps->rp0_freq);
+}
+
+u32 intel_rps_get_rp1_frequency(struct intel_rps *rps)
+{
+ struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+ if (rps_uses_slpc(rps))
+ return slpc->rp1_freq;
+ else
+ return intel_gpu_freq(rps, rps->rp1_freq);
+}
+
+u32 intel_rps_get_rpn_frequency(struct intel_rps *rps)
+{
+ struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+ if (rps_uses_slpc(rps))
+ return slpc->min_freq;
+ else
+ return intel_gpu_freq(rps, rps->min_freq);
+}
+
+static int set_max_freq(struct intel_rps *rps, u32 val)
+{
+ struct drm_i915_private *i915 = rps_to_i915(rps);
+ int ret = 0;
+
+ mutex_lock(&rps->lock);
+
+ val = intel_freq_opcode(rps, val);
+ if (val < rps->min_freq ||
+ val > rps->max_freq ||
+ val < rps->min_freq_softlimit) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ if (val > rps->rp0_freq)
+ drm_dbg(&i915->drm, "User requested overclocking to %d\n",
+ intel_gpu_freq(rps, val));
+
+ rps->max_freq_softlimit = val;
+
+ val = clamp_t(int, rps->cur_freq,
+ rps->min_freq_softlimit,
+ rps->max_freq_softlimit);
+
+ /*
+ * We still need *_set_rps to process the new max_delay and
+ * update the interrupt limits and PMINTRMSK even though
+ * frequency request may be unchanged.
+ */
+ intel_rps_set(rps, val);
+
+unlock:
+ mutex_unlock(&rps->lock);
+
+ return ret;
+}
+
+int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val)
+{
+ struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+ if (rps_uses_slpc(rps))
+ return intel_guc_slpc_set_max_freq(slpc, val);
+ else
+ return set_max_freq(rps, val);
+}
+
+u32 intel_rps_get_min_frequency(struct intel_rps *rps)
+{
+ struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+ if (rps_uses_slpc(rps))
+ return slpc->min_freq_softlimit;
+ else
+ return intel_gpu_freq(rps, rps->min_freq_softlimit);
+}
+
+static int set_min_freq(struct intel_rps *rps, u32 val)
+{
+ int ret = 0;
+
+ mutex_lock(&rps->lock);
+
+ val = intel_freq_opcode(rps, val);
+ if (val < rps->min_freq ||
+ val > rps->max_freq ||
+ val > rps->max_freq_softlimit) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ rps->min_freq_softlimit = val;
+
+ val = clamp_t(int, rps->cur_freq,
+ rps->min_freq_softlimit,
+ rps->max_freq_softlimit);
+
+ /*
+ * We still need *_set_rps to process the new min_delay and
+ * update the interrupt limits and PMINTRMSK even though
+ * frequency request may be unchanged.
+ */
+ intel_rps_set(rps, val);
+
+unlock:
+ mutex_unlock(&rps->lock);
+
+ return ret;
+}
+
+int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val)
+{
+ struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+
+ if (rps_uses_slpc(rps))
+ return intel_guc_slpc_set_min_freq(slpc, val);
+ else
+ return set_min_freq(rps, val);
+}
+
/* External interface for intel_ips.ko */
static struct drm_i915_private __rcu *ips_mchdev;
@@ -2129,4 +2333,5 @@ EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftest_rps.c"
+#include "selftest_slpc.c"
#endif
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h
index 1d2cfc98b510..4213bcce1667 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.h
+++ b/drivers/gpu/drm/i915/gt/intel_rps.h
@@ -31,6 +31,16 @@ int intel_gpu_freq(struct intel_rps *rps, int val);
int intel_freq_opcode(struct intel_rps *rps, int val);
u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1);
u32 intel_rps_read_actual_frequency(struct intel_rps *rps);
+u32 intel_rps_get_requested_frequency(struct intel_rps *rps);
+u32 intel_rps_get_min_frequency(struct intel_rps *rps);
+int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val);
+u32 intel_rps_get_max_frequency(struct intel_rps *rps);
+int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val);
+u32 intel_rps_get_rp0_frequency(struct intel_rps *rps);
+u32 intel_rps_get_rp1_frequency(struct intel_rps *rps);
+u32 intel_rps_get_rpn_frequency(struct intel_rps *rps);
+u32 intel_rps_read_punit_req(struct intel_rps *rps);
+u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps);
void gen5_rps_irq_handler(struct intel_rps *rps);
void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir);
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index 367fd44b81c8..bbd272943c3f 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -139,17 +139,36 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
* Gen12 has Dual-Subslices, which behave similarly to 2 gen11 SS.
* Instead of splitting these, provide userspace with an array
* of DSS to more closely represent the hardware resource.
+ *
+ * In addition, the concept of slice has been removed in Xe_HP.
+ * To be compatible with prior generations, assume a single slice
+ * across the entire device. Then calculate out the DSS for each
+ * workload type within that software slice.
*/
- intel_sseu_set_info(sseu, 1, 6, 16);
+ if (IS_DG2(gt->i915) || IS_XEHPSDV(gt->i915))
+ intel_sseu_set_info(sseu, 1, 32, 16);
+ else
+ intel_sseu_set_info(sseu, 1, 6, 16);
- s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
- GEN11_GT_S_ENA_MASK;
+ /*
+ * As mentioned above, Xe_HP does not have the concept of a slice.
+ * Enable one for software backwards compatibility.
+ */
+ if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
+ s_en = 0x1;
+ else
+ s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
+ GEN11_GT_S_ENA_MASK;
dss_en = intel_uncore_read(uncore, GEN12_GT_DSS_ENABLE);
/* one bit per pair of EUs */
- eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
- GEN11_EU_DIS_MASK);
+ if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
+ eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
+ else
+ eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
+ GEN11_EU_DIS_MASK);
+
for (eu = 0; eu < sseu->max_eus_per_subslice / 2; eu++)
if (eu_en_fuse & BIT(eu))
eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
@@ -188,83 +207,6 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
sseu->has_eu_pg = 1;
}
-static void gen10_sseu_info_init(struct intel_gt *gt)
-{
- struct intel_uncore *uncore = gt->uncore;
- struct sseu_dev_info *sseu = &gt->info.sseu;
- const u32 fuse2 = intel_uncore_read(uncore, GEN8_FUSE2);
- const int eu_mask = 0xff;
- u32 subslice_mask, eu_en;
- int s, ss;
-
- intel_sseu_set_info(sseu, 6, 4, 8);
-
- sseu->slice_mask = (fuse2 & GEN10_F2_S_ENA_MASK) >>
- GEN10_F2_S_ENA_SHIFT;
-
- /* Slice0 */
- eu_en = ~intel_uncore_read(uncore, GEN8_EU_DISABLE0);
- for (ss = 0; ss < sseu->max_subslices; ss++)
- sseu_set_eus(sseu, 0, ss, (eu_en >> (8 * ss)) & eu_mask);
- /* Slice1 */
- sseu_set_eus(sseu, 1, 0, (eu_en >> 24) & eu_mask);
- eu_en = ~intel_uncore_read(uncore, GEN8_EU_DISABLE1);
- sseu_set_eus(sseu, 1, 1, eu_en & eu_mask);
- /* Slice2 */
- sseu_set_eus(sseu, 2, 0, (eu_en >> 8) & eu_mask);
- sseu_set_eus(sseu, 2, 1, (eu_en >> 16) & eu_mask);
- /* Slice3 */
- sseu_set_eus(sseu, 3, 0, (eu_en >> 24) & eu_mask);
- eu_en = ~intel_uncore_read(uncore, GEN8_EU_DISABLE2);
- sseu_set_eus(sseu, 3, 1, eu_en & eu_mask);
- /* Slice4 */
- sseu_set_eus(sseu, 4, 0, (eu_en >> 8) & eu_mask);
- sseu_set_eus(sseu, 4, 1, (eu_en >> 16) & eu_mask);
- /* Slice5 */
- sseu_set_eus(sseu, 5, 0, (eu_en >> 24) & eu_mask);
- eu_en = ~intel_uncore_read(uncore, GEN10_EU_DISABLE3);
- sseu_set_eus(sseu, 5, 1, eu_en & eu_mask);
-
- subslice_mask = (1 << 4) - 1;
- subslice_mask &= ~((fuse2 & GEN10_F2_SS_DIS_MASK) >>
- GEN10_F2_SS_DIS_SHIFT);
-
- for (s = 0; s < sseu->max_slices; s++) {
- u32 subslice_mask_with_eus = subslice_mask;
-
- for (ss = 0; ss < sseu->max_subslices; ss++) {
- if (sseu_get_eus(sseu, s, ss) == 0)
- subslice_mask_with_eus &= ~BIT(ss);
- }
-
- /*
- * Slice0 can have up to 3 subslices, but there are only 2 in
- * slice1/2.
- */
- intel_sseu_set_subslices(sseu, s, s == 0 ?
- subslice_mask_with_eus :
- subslice_mask_with_eus & 0x3);
- }
-
- sseu->eu_total = compute_eu_total(sseu);
-
- /*
- * CNL is expected to always have a uniform distribution
- * of EU across subslices with the exception that any one
- * EU in any one subslice may be fused off for die
- * recovery.
- */
- sseu->eu_per_subslice =
- intel_sseu_subslice_total(sseu) ?
- DIV_ROUND_UP(sseu->eu_total, intel_sseu_subslice_total(sseu)) :
- 0;
-
- /* No restrictions on Power Gating */
- sseu->has_slice_pg = 1;
- sseu->has_subslice_pg = 1;
- sseu->has_eu_pg = 1;
-}
-
static void cherryview_sseu_info_init(struct intel_gt *gt)
{
struct sseu_dev_info *sseu = &gt->info.sseu;
@@ -592,8 +534,6 @@ void intel_sseu_info_init(struct intel_gt *gt)
bdw_sseu_info_init(gt);
else if (GRAPHICS_VER(i915) == 9)
gen9_sseu_info_init(gt);
- else if (GRAPHICS_VER(i915) == 10)
- gen10_sseu_info_init(gt);
else if (GRAPHICS_VER(i915) == 11)
gen11_sseu_info_init(gt);
else if (GRAPHICS_VER(i915) >= 12)
@@ -759,3 +699,21 @@ void intel_sseu_print_topology(const struct sseu_dev_info *sseu,
}
}
}
+
+u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
+{
+ u16 slice_mask = 0;
+ int i;
+
+ WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
+
+ for (i = 0; dss_mask; i++) {
+ if (dss_mask & GENMASK(dss_per_slice - 1, 0))
+ slice_mask |= BIT(i);
+
+ dss_mask >>= dss_per_slice;
+ }
+
+ return slice_mask;
+}
+
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
index 4cd1a8a7298a..22fef98887c0 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.h
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
@@ -15,13 +15,17 @@ struct drm_i915_private;
struct intel_gt;
struct drm_printer;
-#define GEN_MAX_SLICES (6) /* CNL upper bound */
-#define GEN_MAX_SUBSLICES (8) /* ICL upper bound */
+#define GEN_MAX_SLICES (3) /* SKL upper bound */
+#define GEN_MAX_SUBSLICES (32) /* XEHPSDV upper bound */
#define GEN_SSEU_STRIDE(max_entries) DIV_ROUND_UP(max_entries, BITS_PER_BYTE)
#define GEN_MAX_SUBSLICE_STRIDE GEN_SSEU_STRIDE(GEN_MAX_SUBSLICES)
#define GEN_MAX_EUS (16) /* TGL upper bound */
#define GEN_MAX_EU_STRIDE GEN_SSEU_STRIDE(GEN_MAX_EUS)
+#define GEN_DSS_PER_GSLICE 4
+#define GEN_DSS_PER_CSLICE 8
+#define GEN_DSS_PER_MSLICE 8
+
struct sseu_dev_info {
u8 slice_mask;
u8 subslice_mask[GEN_MAX_SLICES * GEN_MAX_SUBSLICE_STRIDE];
@@ -104,4 +108,6 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p);
void intel_sseu_print_topology(const struct sseu_dev_info *sseu,
struct drm_printer *p);
+u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
+
#endif /* __INTEL_SSEU_H__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
index 714fe8495775..1ba8b7da9d37 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
@@ -50,10 +50,10 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
#undef SS_MAX
}
-static void gen10_sseu_device_status(struct intel_gt *gt,
+static void gen11_sseu_device_status(struct intel_gt *gt,
struct sseu_dev_info *sseu)
{
-#define SS_MAX 6
+#define SS_MAX 8
struct intel_uncore *uncore = gt->uncore;
const struct intel_gt_info *info = &gt->info;
u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2];
@@ -267,8 +267,8 @@ int intel_sseu_status(struct seq_file *m, struct intel_gt *gt)
bdw_sseu_device_status(gt, &sseu);
else if (GRAPHICS_VER(i915) == 9)
gen9_sseu_device_status(gt, &sseu);
- else if (GRAPHICS_VER(i915) >= 10)
- gen10_sseu_device_status(gt, &sseu);
+ else if (GRAPHICS_VER(i915) >= 11)
+ gen11_sseu_device_status(gt, &sseu);
}
i915_print_sseu_info(m, false, HAS_POOLED_EU(i915), &sseu);
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index b62d1e31a645..aae609d7d85d 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -150,13 +150,14 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
}
static void wa_add(struct i915_wa_list *wal, i915_reg_t reg,
- u32 clear, u32 set, u32 read_mask)
+ u32 clear, u32 set, u32 read_mask, bool masked_reg)
{
struct i915_wa wa = {
.reg = reg,
.clr = clear,
.set = set,
.read = read_mask,
+ .masked_reg = masked_reg,
};
_wa_add(wal, &wa);
@@ -165,7 +166,7 @@ static void wa_add(struct i915_wa_list *wal, i915_reg_t reg,
static void
wa_write_clr_set(struct i915_wa_list *wal, i915_reg_t reg, u32 clear, u32 set)
{
- wa_add(wal, reg, clear, set, clear);
+ wa_add(wal, reg, clear, set, clear, false);
}
static void
@@ -200,20 +201,20 @@ wa_write_clr(struct i915_wa_list *wal, i915_reg_t reg, u32 clr)
static void
wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
{
- wa_add(wal, reg, 0, _MASKED_BIT_ENABLE(val), val);
+ wa_add(wal, reg, 0, _MASKED_BIT_ENABLE(val), val, true);
}
static void
wa_masked_dis(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
{
- wa_add(wal, reg, 0, _MASKED_BIT_DISABLE(val), val);
+ wa_add(wal, reg, 0, _MASKED_BIT_DISABLE(val), val, true);
}
static void
wa_masked_field_set(struct i915_wa_list *wal, i915_reg_t reg,
u32 mask, u32 val)
{
- wa_add(wal, reg, 0, _MASKED_FIELD(mask, val), mask);
+ wa_add(wal, reg, 0, _MASKED_FIELD(mask, val), mask, true);
}
static void gen6_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -514,53 +515,15 @@ static void cfl_ctx_workarounds_init(struct intel_engine_cs *engine,
GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
}
-static void cnl_ctx_workarounds_init(struct intel_engine_cs *engine,
- struct i915_wa_list *wal)
-{
- /* WaForceContextSaveRestoreNonCoherent:cnl */
- wa_masked_en(wal, CNL_HDC_CHICKEN0,
- HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT);
-
- /* WaDisableReplayBufferBankArbitrationOptimization:cnl */
- wa_masked_en(wal, COMMON_SLICE_CHICKEN2,
- GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
-
- /* WaPushConstantDereferenceHoldDisable:cnl */
- wa_masked_en(wal, GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE);
-
- /* FtrEnableFastAnisoL1BankingFix:cnl */
- wa_masked_en(wal, HALF_SLICE_CHICKEN3, CNL_FAST_ANISO_L1_BANKING_FIX);
-
- /* WaDisable3DMidCmdPreemption:cnl */
- wa_masked_dis(wal, GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL);
-
- /* WaDisableGPGPUMidCmdPreemption:cnl */
- wa_masked_field_set(wal, GEN8_CS_CHICKEN1,
- GEN9_PREEMPT_GPGPU_LEVEL_MASK,
- GEN9_PREEMPT_GPGPU_COMMAND_LEVEL);
-
- /* WaDisableEarlyEOT:cnl */
- wa_masked_en(wal, GEN8_ROW_CHICKEN, DISABLE_EARLY_EOT);
-}
-
static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal)
{
- struct drm_i915_private *i915 = engine->i915;
-
- /* WaDisableBankHangMode:icl */
+ /* Wa_1406697149 (WaDisableBankHangMode:icl) */
wa_write(wal,
GEN8_L3CNTLREG,
intel_uncore_read(engine->uncore, GEN8_L3CNTLREG) |
GEN8_ERRDETBCTRL);
- /* Wa_1604370585:icl (pre-prod)
- * Formerly known as WaPushConstantDereferenceHoldDisable
- */
- if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
- wa_masked_en(wal, GEN7_ROW_CHICKEN2,
- PUSH_CONSTANT_DEREF_DISABLE);
-
/* WaForceEnableNonCoherent:icl
* This is not the same workaround as in early Gen9 platforms, where
* lacking this could cause system hangs, but coherency performance
@@ -570,23 +533,11 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
*/
wa_masked_en(wal, ICL_HDC_MODE, HDC_FORCE_NON_COHERENT);
- /* Wa_2006611047:icl (pre-prod)
- * Formerly known as WaDisableImprovedTdlClkGating
- */
- if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
- wa_masked_en(wal, GEN7_ROW_CHICKEN2,
- GEN11_TDL_CLOCK_GATING_FIX_DISABLE);
-
- /* Wa_2006665173:icl (pre-prod) */
- if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
- wa_masked_en(wal, GEN11_COMMON_SLICE_CHICKEN3,
- GEN11_BLEND_EMB_FIX_DISABLE_IN_RCC);
-
/* WaEnableFloatBlendOptimization:icl */
- wa_write_clr_set(wal,
- GEN10_CACHE_MODE_SS,
- 0, /* write-only, so skip validation */
- _MASKED_BIT_ENABLE(FLOAT_BLEND_OPTIMIZATION_ENABLE));
+ wa_add(wal, GEN10_CACHE_MODE_SS, 0,
+ _MASKED_BIT_ENABLE(FLOAT_BLEND_OPTIMIZATION_ENABLE),
+ 0 /* write-only, so skip validation */,
+ true);
/* WaDisableGPGPUMidThreadPreemption:icl */
wa_masked_field_set(wal, GEN8_CS_CHICKEN1,
@@ -631,7 +582,7 @@ static void gen12_ctx_gt_tuning_init(struct intel_engine_cs *engine,
FF_MODE2,
FF_MODE2_TDS_TIMER_MASK,
FF_MODE2_TDS_TIMER_128,
- 0);
+ 0, false);
}
static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -640,15 +591,16 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine,
gen12_ctx_gt_tuning_init(engine, wal);
/*
- * Wa_1409142259:tgl
- * Wa_1409347922:tgl
- * Wa_1409252684:tgl
- * Wa_1409217633:tgl
- * Wa_1409207793:tgl
- * Wa_1409178076:tgl
- * Wa_1408979724:tgl
- * Wa_14010443199:rkl
- * Wa_14010698770:rkl
+ * Wa_1409142259:tgl,dg1,adl-p
+ * Wa_1409347922:tgl,dg1,adl-p
+ * Wa_1409252684:tgl,dg1,adl-p
+ * Wa_1409217633:tgl,dg1,adl-p
+ * Wa_1409207793:tgl,dg1,adl-p
+ * Wa_1409178076:tgl,dg1,adl-p
+ * Wa_1408979724:tgl,dg1,adl-p
+ * Wa_14010443199:tgl,rkl,dg1,adl-p
+ * Wa_14010698770:tgl,rkl,dg1,adl-s,adl-p
+ * Wa_1409342910:tgl,rkl,dg1,adl-s,adl-p
*/
wa_masked_en(wal, GEN11_COMMON_SLICE_CHICKEN3,
GEN12_DISABLE_CPS_AWARE_COLOR_PIPE);
@@ -668,7 +620,14 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine,
FF_MODE2,
FF_MODE2_GS_TIMER_MASK,
FF_MODE2_GS_TIMER_224,
- 0);
+ 0, false);
+
+ /*
+ * Wa_14012131227:dg1
+ * Wa_1508744258:tgl,rkl,dg1,adl-s,adl-p
+ */
+ wa_masked_en(wal, GEN7_COMMON_SLICE_CHICKEN1,
+ GEN9_RHWO_OPTIMIZATION_DISABLE);
}
static void dg1_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -703,8 +662,6 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine,
gen12_ctx_workarounds_init(engine, wal);
else if (GRAPHICS_VER(i915) == 11)
icl_ctx_workarounds_init(engine, wal);
- else if (IS_CANNONLAKE(i915))
- cnl_ctx_workarounds_init(engine, wal);
else if (IS_COFFEELAKE(i915) || IS_COMETLAKE(i915))
cfl_ctx_workarounds_init(engine, wal);
else if (IS_GEMINILAKE(i915))
@@ -839,7 +796,7 @@ hsw_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
wa_add(wal,
HSW_ROW_CHICKEN3, 0,
_MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE),
- 0 /* XXX does this reg exist? */);
+ 0 /* XXX does this reg exist? */, true);
/* WaVSRefCountFullforceMissDisable:hsw */
wa_write_clr(wal, GEN7_FF_THREAD_MODE, GEN7_FF_VS_REF_CNT_FFME);
@@ -882,30 +839,19 @@ skl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
/* WaInPlaceDecompressionHang:skl */
- if (IS_SKL_REVID(i915, SKL_REVID_H0, REVID_FOREVER))
+ if (IS_SKL_GT_STEP(i915, STEP_A0, STEP_H0))
wa_write_or(wal,
GEN9_GAMT_ECO_REG_RW_IA,
GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
}
static void
-bxt_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
-{
- gen9_gt_workarounds_init(i915, wal);
-
- /* WaInPlaceDecompressionHang:bxt */
- wa_write_or(wal,
- GEN9_GAMT_ECO_REG_RW_IA,
- GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
-}
-
-static void
kbl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
{
gen9_gt_workarounds_init(i915, wal);
/* WaDisableDynamicCreditSharing:kbl */
- if (IS_KBL_GT_STEP(i915, 0, STEP_B0))
+ if (IS_KBL_GT_STEP(i915, 0, STEP_C0))
wa_write_or(wal,
GAMT_CHKN_BIT_REG,
GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
@@ -943,98 +889,144 @@ cfl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
}
+static void __set_mcr_steering(struct i915_wa_list *wal,
+ i915_reg_t steering_reg,
+ unsigned int slice, unsigned int subslice)
+{
+ u32 mcr, mcr_mask;
+
+ mcr = GEN11_MCR_SLICE(slice) | GEN11_MCR_SUBSLICE(subslice);
+ mcr_mask = GEN11_MCR_SLICE_MASK | GEN11_MCR_SUBSLICE_MASK;
+
+ wa_write_clr_set(wal, steering_reg, mcr_mask, mcr);
+}
+
+static void __add_mcr_wa(struct drm_i915_private *i915, struct i915_wa_list *wal,
+ unsigned int slice, unsigned int subslice)
+{
+ drm_dbg(&i915->drm, "MCR slice=0x%x, subslice=0x%x\n", slice, subslice);
+
+ __set_mcr_steering(wal, GEN8_MCR_SELECTOR, slice, subslice);
+}
+
static void
-wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
+icl_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
{
const struct sseu_dev_info *sseu = &i915->gt.info.sseu;
unsigned int slice, subslice;
- u32 l3_en, mcr, mcr_mask;
- GEM_BUG_ON(GRAPHICS_VER(i915) < 10);
+ GEM_BUG_ON(GRAPHICS_VER(i915) < 11);
+ GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
+ slice = 0;
/*
- * WaProgramMgsrForL3BankSpecificMmioReads: cnl,icl
- * L3Banks could be fused off in single slice scenario. If that is
- * the case, we might need to program MCR select to a valid L3Bank
- * by default, to make sure we correctly read certain registers
- * later on (in the range 0xB100 - 0xB3FF).
+ * Although a platform may have subslices, we need to always steer
+ * reads to the lowest instance that isn't fused off. When Render
+ * Power Gating is enabled, grabbing forcewake will only power up a
+ * single subslice (the "minconfig") if there isn't a real workload
+ * that needs to be run; this means that if we steer register reads to
+ * one of the higher subslices, we run the risk of reading back 0's or
+ * random garbage.
+ */
+ subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
+
+ /*
+ * If the subslice we picked above also steers us to a valid L3 bank,
+ * then we can just rely on the default steering and won't need to
+ * worry about explicitly re-steering L3BANK reads later.
+ */
+ if (i915->gt.info.l3bank_mask & BIT(subslice))
+ i915->gt.steering_table[L3BANK] = NULL;
+
+ __add_mcr_wa(i915, wal, slice, subslice);
+}
+
+static void
+xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
+{
+ struct drm_i915_private *i915 = gt->i915;
+ const struct sseu_dev_info *sseu = &gt->info.sseu;
+ unsigned long slice, subslice = 0, slice_mask = 0;
+ u64 dss_mask = 0;
+ u32 lncf_mask = 0;
+ int i;
+
+ /*
+ * On Xe_HP the steering increases in complexity. There are now several
+ * more units that require steering and we're not guaranteed to be able
+ * to find a common setting for all of them. These are:
+ * - GSLICE (fusable)
+ * - DSS (sub-unit within gslice; fusable)
+ * - L3 Bank (fusable)
+ * - MSLICE (fusable)
+ * - LNCF (sub-unit within mslice; always present if mslice is present)
*
- * WaProgramMgsrForCorrectSliceSpecificMmioReads:cnl,icl
- * Before any MMIO read into slice/subslice specific registers, MCR
- * packet control register needs to be programmed to point to any
- * enabled s/ss pair. Otherwise, incorrect values will be returned.
- * This means each subsequent MMIO read will be forwarded to an
- * specific s/ss combination, but this is OK since these registers
- * are consistent across s/ss in almost all cases. In the rare
- * occasions, such as INSTDONE, where this value is dependent
- * on s/ss combo, the read should be done with read_subslice_reg.
+ * We'll do our default/implicit steering based on GSLICE (in the
+ * sliceid field) and DSS (in the subsliceid field). If we can
+ * find overlap between the valid MSLICE and/or LNCF values with
+ * a suitable GSLICE, then we can just re-use the default value and
+ * skip and explicit steering at runtime.
*
- * Since GEN8_MCR_SELECTOR contains dual-purpose bits which select both
- * to which subslice, or to which L3 bank, the respective mmio reads
- * will go, we have to find a common index which works for both
- * accesses.
+ * We only need to look for overlap between GSLICE/MSLICE/LNCF to find
+ * a valid sliceid value. DSS steering is the only type of steering
+ * that utilizes the 'subsliceid' bits.
*
- * Case where we cannot find a common index fortunately should not
- * happen in production hardware, so we only emit a warning instead of
- * implementing something more complex that requires checking the range
- * of every MMIO read.
+ * Also note that, even though the steering domain is called "GSlice"
+ * and it is encoded in the register using the gslice format, the spec
+ * says that the combined (geometry | compute) fuse should be used to
+ * select the steering.
*/
- if (GRAPHICS_VER(i915) >= 10 && is_power_of_2(sseu->slice_mask)) {
- u32 l3_fuse =
- intel_uncore_read(&i915->uncore, GEN10_MIRROR_FUSE3) &
- GEN10_L3BANK_MASK;
+ /* Find the potential gslice candidates */
+ dss_mask = intel_sseu_get_subslices(sseu, 0);
+ slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
- drm_dbg(&i915->drm, "L3 fuse = %x\n", l3_fuse);
- l3_en = ~(l3_fuse << GEN10_L3BANK_PAIR_COUNT | l3_fuse);
- } else {
- l3_en = ~0;
- }
+ /*
+ * Find the potential LNCF candidates. Either LNCF within a valid
+ * mslice is fine.
+ */
+ for_each_set_bit(i, &gt->info.mslice_mask, GEN12_MAX_MSLICES)
+ lncf_mask |= (0x3 << (i * 2));
- slice = fls(sseu->slice_mask) - 1;
- subslice = fls(l3_en & intel_sseu_get_subslices(sseu, slice));
- if (!subslice) {
- drm_warn(&i915->drm,
- "No common index found between subslice mask %x and L3 bank mask %x!\n",
- intel_sseu_get_subslices(sseu, slice), l3_en);
- subslice = fls(l3_en);
- drm_WARN_ON(&i915->drm, !subslice);
- }
- subslice--;
-
- if (GRAPHICS_VER(i915) >= 11) {
- mcr = GEN11_MCR_SLICE(slice) | GEN11_MCR_SUBSLICE(subslice);
- mcr_mask = GEN11_MCR_SLICE_MASK | GEN11_MCR_SUBSLICE_MASK;
- } else {
- mcr = GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice);
- mcr_mask = GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK;
+ /*
+ * Are there any sliceid values that work for both GSLICE and LNCF
+ * steering?
+ */
+ if (slice_mask & lncf_mask) {
+ slice_mask &= lncf_mask;
+ gt->steering_table[LNCF] = NULL;
}
- drm_dbg(&i915->drm, "MCR slice/subslice = %x\n", mcr);
+ /* How about sliceid values that also work for MSLICE steering? */
+ if (slice_mask & gt->info.mslice_mask) {
+ slice_mask &= gt->info.mslice_mask;
+ gt->steering_table[MSLICE] = NULL;
+ }
- wa_write_clr_set(wal, GEN8_MCR_SELECTOR, mcr_mask, mcr);
-}
+ slice = __ffs(slice_mask);
+ subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
+ WARN_ON(subslice > GEN_DSS_PER_GSLICE);
+ WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
-static void
-cnl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
-{
- wa_init_mcr(i915, wal);
+ __add_mcr_wa(i915, wal, slice, subslice);
- /* WaInPlaceDecompressionHang:cnl */
- wa_write_or(wal,
- GEN9_GAMT_ECO_REG_RW_IA,
- GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
+ /*
+ * SQIDI ranges are special because they use different steering
+ * registers than everything else we work with. On XeHP SDV and
+ * DG2-G10, any value in the steering registers will work fine since
+ * all instances are present, but DG2-G11 only has SQIDI instances at
+ * ID's 2 and 3, so we need to steer to one of those. For simplicity
+ * we'll just steer to a hardcoded "2" since that value will work
+ * everywhere.
+ */
+ __set_mcr_steering(wal, MCFG_MCR_SELECTOR, 0, 2);
+ __set_mcr_steering(wal, SF_MCR_SELECTOR, 0, 2);
}
static void
icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
{
- wa_init_mcr(i915, wal);
-
- /* WaInPlaceDecompressionHang:icl */
- wa_write_or(wal,
- GEN9_GAMT_ECO_REG_RW_IA,
- GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
+ icl_wa_init_mcr(i915, wal);
/* WaModifyGamTlbPartitioning:icl */
wa_write_clr_set(wal,
@@ -1057,18 +1049,6 @@ icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
GEN8_GAMW_ECO_DEV_RW_IA,
GAMW_ECO_DEV_CTX_RELOAD_DISABLE);
- /* Wa_1405779004:icl (pre-prod) */
- if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
- wa_write_or(wal,
- SLICE_UNIT_LEVEL_CLKGATE,
- MSCUNIT_CLKGATE_DIS);
-
- /* Wa_1406838659:icl (pre-prod) */
- if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
- wa_write_or(wal,
- INF_UNIT_LEVEL_CLKGATE,
- CGPSF_CLKGATE_DIS);
-
/* Wa_1406463099:icl
* Formerly known as WaGamTlbPendError
*/
@@ -1078,10 +1058,16 @@ icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
/* Wa_1607087056:icl,ehl,jsl */
if (IS_ICELAKE(i915) ||
- IS_JSL_EHL_REVID(i915, EHL_REVID_A0, EHL_REVID_A0))
+ IS_JSL_EHL_GT_STEP(i915, STEP_A0, STEP_B0))
wa_write_or(wal,
SLICE_UNIT_LEVEL_CLKGATE,
L3_CLKGATE_DIS | L3_CR2X_CLKGATE_DIS);
+
+ /*
+ * This is not a documented workaround, but rather an optimization
+ * to reduce sampler power.
+ */
+ wa_write_clr(wal, GEN10_DFR_RATIO_EN_AND_CHICKEN, DFR_DISABLE);
}
/*
@@ -1111,10 +1097,13 @@ static void
gen12_gt_workarounds_init(struct drm_i915_private *i915,
struct i915_wa_list *wal)
{
- wa_init_mcr(i915, wal);
+ icl_wa_init_mcr(i915, wal);
- /* Wa_14011060649:tgl,rkl,dg1,adls */
+ /* Wa_14011060649:tgl,rkl,dg1,adl-s,adl-p */
wa_14011060649(i915, wal);
+
+ /* Wa_14011059788:tgl,rkl,adl-s,dg1,adl-p */
+ wa_write_or(wal, GEN10_DFR_RATIO_EN_AND_CHICKEN, DFR_DISABLE);
}
static void
@@ -1123,19 +1112,19 @@ tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
gen12_gt_workarounds_init(i915, wal);
/* Wa_1409420604:tgl */
- if (IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_A0))
+ if (IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_B0))
wa_write_or(wal,
SUBSLICE_UNIT_LEVEL_CLKGATE2,
CPSSUNIT_CLKGATE_DIS);
/* Wa_1607087056:tgl also know as BUG:1409180338 */
- if (IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_A0))
+ if (IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_B0))
wa_write_or(wal,
SLICE_UNIT_LEVEL_CLKGATE,
L3_CLKGATE_DIS | L3_CR2X_CLKGATE_DIS);
/* Wa_1408615072:tgl[a0] */
- if (IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_A0))
+ if (IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_B0))
wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE2,
VSUNIT_CLKGATE_DIS_TGL);
}
@@ -1146,7 +1135,7 @@ dg1_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
gen12_gt_workarounds_init(i915, wal);
/* Wa_1607087056:dg1 */
- if (IS_DG1_REVID(i915, DG1_REVID_A0, DG1_REVID_A0))
+ if (IS_DG1_GT_STEP(i915, STEP_A0, STEP_B0))
wa_write_or(wal,
SLICE_UNIT_LEVEL_CLKGATE,
L3_CLKGATE_DIS | L3_CR2X_CLKGATE_DIS);
@@ -1165,9 +1154,17 @@ dg1_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
}
static void
+xehpsdv_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
+{
+ xehp_init_mcr(&i915->gt, wal);
+}
+
+static void
gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal)
{
- if (IS_DG1(i915))
+ if (IS_XEHPSDV(i915))
+ xehpsdv_gt_workarounds_init(i915, wal);
+ else if (IS_DG1(i915))
dg1_gt_workarounds_init(i915, wal);
else if (IS_TIGERLAKE(i915))
tgl_gt_workarounds_init(i915, wal);
@@ -1175,8 +1172,6 @@ gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal)
gen12_gt_workarounds_init(i915, wal);
else if (GRAPHICS_VER(i915) == 11)
icl_gt_workarounds_init(i915, wal);
- else if (IS_CANNONLAKE(i915))
- cnl_gt_workarounds_init(i915, wal);
else if (IS_COFFEELAKE(i915) || IS_COMETLAKE(i915))
cfl_gt_workarounds_init(i915, wal);
else if (IS_GEMINILAKE(i915))
@@ -1184,7 +1179,7 @@ gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal)
else if (IS_KABYLAKE(i915))
kbl_gt_workarounds_init(i915, wal);
else if (IS_BROXTON(i915))
- bxt_gt_workarounds_init(i915, wal);
+ gen9_gt_workarounds_init(i915, wal);
else if (IS_SKYLAKE(i915))
skl_gt_workarounds_init(i915, wal);
else if (IS_HASWELL(i915))
@@ -1247,8 +1242,9 @@ wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char *from)
}
static void
-wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal)
+wa_list_apply(struct intel_gt *gt, const struct i915_wa_list *wal)
{
+ struct intel_uncore *uncore = gt->uncore;
enum forcewake_domains fw;
unsigned long flags;
struct i915_wa *wa;
@@ -1263,13 +1259,16 @@ wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal)
intel_uncore_forcewake_get__locked(uncore, fw);
for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
- if (wa->clr)
- intel_uncore_rmw_fw(uncore, wa->reg, wa->clr, wa->set);
- else
- intel_uncore_write_fw(uncore, wa->reg, wa->set);
+ u32 val, old = 0;
+
+ /* open-coded rmw due to steering */
+ old = wa->clr ? intel_gt_read_register_fw(gt, wa->reg) : 0;
+ val = (old & ~wa->clr) | wa->set;
+ if (val != old || !wa->clr)
+ intel_uncore_write_fw(uncore, wa->reg, val);
+
if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
- wa_verify(wa,
- intel_uncore_read_fw(uncore, wa->reg),
+ wa_verify(wa, intel_gt_read_register_fw(gt, wa->reg),
wal->name, "application");
}
@@ -1279,28 +1278,39 @@ wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal)
void intel_gt_apply_workarounds(struct intel_gt *gt)
{
- wa_list_apply(gt->uncore, &gt->i915->gt_wa_list);
+ wa_list_apply(gt, &gt->i915->gt_wa_list);
}
-static bool wa_list_verify(struct intel_uncore *uncore,
+static bool wa_list_verify(struct intel_gt *gt,
const struct i915_wa_list *wal,
const char *from)
{
+ struct intel_uncore *uncore = gt->uncore;
struct i915_wa *wa;
+ enum forcewake_domains fw;
+ unsigned long flags;
unsigned int i;
bool ok = true;
+ fw = wal_get_fw_for_rmw(uncore, wal);
+
+ spin_lock_irqsave(&uncore->lock, flags);
+ intel_uncore_forcewake_get__locked(uncore, fw);
+
for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
ok &= wa_verify(wa,
- intel_uncore_read(uncore, wa->reg),
+ intel_gt_read_register_fw(gt, wa->reg),
wal->name, from);
+ intel_uncore_forcewake_put__locked(uncore, fw);
+ spin_unlock_irqrestore(&uncore->lock, flags);
+
return ok;
}
bool intel_gt_verify_workarounds(struct intel_gt *gt, const char *from)
{
- return wa_list_verify(gt->uncore, &gt->i915->gt_wa_list, from);
+ return wa_list_verify(gt, &gt->i915->gt_wa_list, from);
}
__maybe_unused
@@ -1438,17 +1448,6 @@ static void cml_whitelist_build(struct intel_engine_cs *engine)
cfl_whitelist_build(engine);
}
-static void cnl_whitelist_build(struct intel_engine_cs *engine)
-{
- struct i915_wa_list *w = &engine->whitelist;
-
- if (engine->class != RENDER_CLASS)
- return;
-
- /* WaEnablePreemptionGranularityControlByUMD:cnl */
- whitelist_reg(w, GEN8_CS_CHICKEN1);
-}
-
static void icl_whitelist_build(struct intel_engine_cs *engine)
{
struct i915_wa_list *w = &engine->whitelist;
@@ -1542,7 +1541,7 @@ static void dg1_whitelist_build(struct intel_engine_cs *engine)
tgl_whitelist_build(engine);
/* GEN:BUG:1409280441:dg1 */
- if (IS_DG1_REVID(engine->i915, DG1_REVID_A0, DG1_REVID_A0) &&
+ if (IS_DG1_GT_STEP(engine->i915, STEP_A0, STEP_B0) &&
(engine->class == RENDER_CLASS ||
engine->class == COPY_ENGINE_CLASS))
whitelist_reg_ext(w, RING_ID(engine->mmio_base),
@@ -1562,8 +1561,6 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine)
tgl_whitelist_build(engine);
else if (GRAPHICS_VER(i915) == 11)
icl_whitelist_build(engine);
- else if (IS_CANNONLAKE(i915))
- cnl_whitelist_build(engine);
else if (IS_COMETLAKE(i915))
cml_whitelist_build(engine);
else if (IS_COFFEELAKE(i915))
@@ -1612,8 +1609,8 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
{
struct drm_i915_private *i915 = engine->i915;
- if (IS_DG1_REVID(i915, DG1_REVID_A0, DG1_REVID_A0) ||
- IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_A0)) {
+ if (IS_DG1_GT_STEP(i915, STEP_A0, STEP_B0) ||
+ IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_B0)) {
/*
* Wa_1607138336:tgl[a0],dg1[a0]
* Wa_1607063988:tgl[a0],dg1[a0]
@@ -1623,7 +1620,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN12_DISABLE_POSH_BUSY_FF_DOP_CG);
}
- if (IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_A0)) {
+ if (IS_TGL_UY_GT_STEP(i915, STEP_A0, STEP_B0)) {
/*
* Wa_1606679103:tgl
* (see also Wa_1606682166:icl)
@@ -1633,44 +1630,46 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN7_DISABLE_SAMPLER_PREFETCH);
}
- if (IS_ALDERLAKE_S(i915) || IS_DG1(i915) ||
+ if (IS_ALDERLAKE_P(i915) || IS_ALDERLAKE_S(i915) || IS_DG1(i915) ||
IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) {
- /* Wa_1606931601:tgl,rkl,dg1,adl-s */
+ /* Wa_1606931601:tgl,rkl,dg1,adl-s,adl-p */
wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_DISABLE_EARLY_READ);
/*
* Wa_1407928979:tgl A*
* Wa_18011464164:tgl[B0+],dg1[B0+]
* Wa_22010931296:tgl[B0+],dg1[B0+]
- * Wa_14010919138:rkl,dg1,adl-s
+ * Wa_14010919138:rkl,dg1,adl-s,adl-p
*/
wa_write_or(wal, GEN7_FF_THREAD_MODE,
GEN12_FF_TESSELATION_DOP_GATE_DISABLE);
/*
- * Wa_1606700617:tgl,dg1
- * Wa_22010271021:tgl,rkl,dg1, adl-s
+ * Wa_1606700617:tgl,dg1,adl-p
+ * Wa_22010271021:tgl,rkl,dg1,adl-s,adl-p
+ * Wa_14010826681:tgl,dg1,rkl,adl-p
*/
wa_masked_en(wal,
GEN9_CS_DEBUG_MODE1,
FF_DOP_CLOCK_GATE_DISABLE);
}
- if (IS_ALDERLAKE_S(i915) || IS_DG1_REVID(i915, DG1_REVID_A0, DG1_REVID_A0) ||
+ if (IS_ALDERLAKE_P(i915) || IS_ALDERLAKE_S(i915) ||
+ IS_DG1_GT_STEP(i915, STEP_A0, STEP_B0) ||
IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) {
- /* Wa_1409804808:tgl,rkl,dg1[a0],adl-s */
+ /* Wa_1409804808:tgl,rkl,dg1[a0],adl-s,adl-p */
wa_masked_en(wal, GEN7_ROW_CHICKEN2,
GEN12_PUSH_CONST_DEREF_HOLD_DIS);
/*
* Wa_1409085225:tgl
- * Wa_14010229206:tgl,rkl,dg1[a0],adl-s
+ * Wa_14010229206:tgl,rkl,dg1[a0],adl-s,adl-p
*/
wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN12_DISABLE_TDL_PUSH);
}
- if (IS_DG1_REVID(i915, DG1_REVID_A0, DG1_REVID_A0) ||
+ if (IS_DG1_GT_STEP(i915, STEP_A0, STEP_B0) ||
IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) {
/*
* Wa_1607030317:tgl
@@ -1688,8 +1687,9 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN8_RC_SEMA_IDLE_MSG_DISABLE);
}
- if (IS_DG1(i915) || IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) {
- /* Wa_1406941453:tgl,rkl,dg1 */
+ if (IS_DG1(i915) || IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915) ||
+ IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) {
+ /* Wa_1406941453:tgl,rkl,dg1,adl-s,adl-p */
wa_masked_en(wal,
GEN10_SAMPLER_MODE,
ENABLE_SMALLPL);
@@ -1701,11 +1701,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
_3D_CHICKEN3,
_3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE);
- /* WaPipelineFlushCoherentLines:icl */
- wa_write_or(wal,
- GEN8_L3SQCREG4,
- GEN8_LQSC_FLUSH_COHERENT_LINES);
-
/*
* Wa_1405543622:icl
* Formerly known as WaGAPZPriorityScheme
@@ -1735,19 +1730,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN8_L3SQCREG4,
GEN11_LQSC_CLEAN_EVICT_DISABLE);
- /* WaForwardProgressSoftReset:icl */
- wa_write_or(wal,
- GEN10_SCRATCH_LNCF2,
- PMFLUSHDONE_LNICRSDROP |
- PMFLUSH_GAPL3UNBLOCK |
- PMFLUSHDONE_LNEBLK);
-
- /* Wa_1406609255:icl (pre-prod) */
- if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
- wa_write_or(wal,
- GEN7_SARCHKMD,
- GEN7_DISABLE_DEMAND_PREFETCH);
-
/* Wa_1606682166:icl */
wa_write_or(wal,
GEN7_SARCHKMD,
@@ -1947,10 +1929,10 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
* disable bit, which we don't touch here, but it's good
* to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
*/
- wa_add(wal, GEN7_GT_MODE, 0,
- _MASKED_FIELD(GEN6_WIZ_HASHING_MASK,
- GEN6_WIZ_HASHING_16x4),
- GEN6_WIZ_HASHING_16x4);
+ wa_masked_field_set(wal,
+ GEN7_GT_MODE,
+ GEN6_WIZ_HASHING_MASK,
+ GEN6_WIZ_HASHING_16x4);
}
if (IS_GRAPHICS_VER(i915, 6, 7))
@@ -2000,10 +1982,10 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
* disable bit, which we don't touch here, but it's good
* to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
*/
- wa_add(wal,
- GEN6_GT_MODE, 0,
- _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4),
- GEN6_WIZ_HASHING_16x4);
+ wa_masked_field_set(wal,
+ GEN6_GT_MODE,
+ GEN6_WIZ_HASHING_MASK,
+ GEN6_WIZ_HASHING_16x4);
/* WaDisable_RenderCache_OperationalFlush:snb */
wa_masked_dis(wal, CACHE_MODE_0, RC_OP_FLUSH_ENABLE);
@@ -2024,7 +2006,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
wa_add(wal, MI_MODE,
0, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH),
/* XXX bit doesn't stick on Broadwater */
- IS_I965G(i915) ? 0 : VS_TIMER_DISPATCH);
+ IS_I965G(i915) ? 0 : VS_TIMER_DISPATCH, true);
if (GRAPHICS_VER(i915) == 4)
/*
@@ -2039,7 +2021,8 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
*/
wa_add(wal, ECOSKPD,
0, _MASKED_BIT_ENABLE(ECO_CONSTANT_BUFFER_SR_DISABLE),
- 0 /* XXX bit doesn't stick on Broadwater */);
+ 0 /* XXX bit doesn't stick on Broadwater */,
+ true);
}
static void
@@ -2048,7 +2031,7 @@ xcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
struct drm_i915_private *i915 = engine->i915;
/* WaKBLVECSSemaphoreWaitPoll:kbl */
- if (IS_KBL_GT_STEP(i915, STEP_A0, STEP_E0)) {
+ if (IS_KBL_GT_STEP(i915, STEP_A0, STEP_F0)) {
wa_write(wal,
RING_SEMA_WAIT_POLL(engine->mmio_base),
1);
@@ -2081,7 +2064,7 @@ void intel_engine_init_workarounds(struct intel_engine_cs *engine)
void intel_engine_apply_workarounds(struct intel_engine_cs *engine)
{
- wa_list_apply(engine->uncore, &engine->wa_list);
+ wa_list_apply(engine->gt, &engine->wa_list);
}
struct mcr_range {
@@ -2107,12 +2090,31 @@ static const struct mcr_range mcr_ranges_gen12[] = {
{},
};
+static const struct mcr_range mcr_ranges_xehp[] = {
+ { .start = 0x4000, .end = 0x4aff },
+ { .start = 0x5200, .end = 0x52ff },
+ { .start = 0x5400, .end = 0x7fff },
+ { .start = 0x8140, .end = 0x815f },
+ { .start = 0x8c80, .end = 0x8dff },
+ { .start = 0x94d0, .end = 0x955f },
+ { .start = 0x9680, .end = 0x96ff },
+ { .start = 0xb000, .end = 0xb3ff },
+ { .start = 0xc800, .end = 0xcfff },
+ { .start = 0xd800, .end = 0xd8ff },
+ { .start = 0xdc00, .end = 0xffff },
+ { .start = 0x17000, .end = 0x17fff },
+ { .start = 0x24a00, .end = 0x24a7f },
+ {},
+};
+
static bool mcr_range(struct drm_i915_private *i915, u32 offset)
{
const struct mcr_range *mcr_ranges;
int i;
- if (GRAPHICS_VER(i915) >= 12)
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+ mcr_ranges = mcr_ranges_xehp;
+ else if (GRAPHICS_VER(i915) >= 12)
mcr_ranges = mcr_ranges_gen12;
else if (GRAPHICS_VER(i915) >= 8)
mcr_ranges = mcr_ranges_gen8;
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
index c214111ea367..1e873681795d 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
@@ -15,6 +15,7 @@ struct i915_wa {
u32 clr;
u32 set;
u32 read;
+ bool masked_reg;
};
struct i915_wa_list {
diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c
index 32589c6625e1..2c1af030310c 100644
--- a/drivers/gpu/drm/i915/gt/mock_engine.c
+++ b/drivers/gpu/drm/i915/gt/mock_engine.c
@@ -235,6 +235,34 @@ static void mock_submit_request(struct i915_request *request)
spin_unlock_irqrestore(&engine->hw_lock, flags);
}
+static void mock_add_to_engine(struct i915_request *rq)
+{
+ lockdep_assert_held(&rq->engine->sched_engine->lock);
+ list_move_tail(&rq->sched.link, &rq->engine->sched_engine->requests);
+}
+
+static void mock_remove_from_engine(struct i915_request *rq)
+{
+ struct intel_engine_cs *engine, *locked;
+
+ /*
+ * Virtual engines complicate acquiring the engine timeline lock,
+ * as their rq->engine pointer is not stable until under that
+ * engine lock. The simple ploy we use is to take the lock then
+ * check that the rq still belongs to the newly locked engine.
+ */
+
+ locked = READ_ONCE(rq->engine);
+ spin_lock_irq(&locked->sched_engine->lock);
+ while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) {
+ spin_unlock(&locked->sched_engine->lock);
+ spin_lock(&engine->sched_engine->lock);
+ locked = engine;
+ }
+ list_del_init(&rq->sched.link);
+ spin_unlock_irq(&locked->sched_engine->lock);
+}
+
static void mock_reset_prepare(struct intel_engine_cs *engine)
{
}
@@ -253,10 +281,10 @@ static void mock_reset_cancel(struct intel_engine_cs *engine)
del_timer_sync(&mock->hw_delay);
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
/* Mark all submitted requests as skipped. */
- list_for_each_entry(rq, &engine->active.requests, sched.link)
+ list_for_each_entry(rq, &engine->sched_engine->requests, sched.link)
i915_request_put(i915_request_mark_eio(rq));
intel_engine_signal_breadcrumbs(engine);
@@ -269,7 +297,7 @@ static void mock_reset_cancel(struct intel_engine_cs *engine)
}
INIT_LIST_HEAD(&mock->hw_queue);
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
}
static void mock_reset_finish(struct intel_engine_cs *engine)
@@ -283,7 +311,8 @@ static void mock_engine_release(struct intel_engine_cs *engine)
GEM_BUG_ON(timer_pending(&mock->hw_delay));
- intel_breadcrumbs_free(engine->breadcrumbs);
+ i915_sched_engine_put(engine->sched_engine);
+ intel_breadcrumbs_put(engine->breadcrumbs);
intel_context_unpin(engine->kernel_context);
intel_context_put(engine->kernel_context);
@@ -320,6 +349,8 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
engine->base.emit_flush = mock_emit_flush;
engine->base.emit_fini_breadcrumb = mock_emit_breadcrumb;
engine->base.submit_request = mock_submit_request;
+ engine->base.add_active_request = mock_add_to_engine;
+ engine->base.remove_active_request = mock_remove_from_engine;
engine->base.reset.prepare = mock_reset_prepare;
engine->base.reset.rewind = mock_reset_rewind;
@@ -345,14 +376,18 @@ int mock_engine_init(struct intel_engine_cs *engine)
{
struct intel_context *ce;
- intel_engine_init_active(engine, ENGINE_MOCK);
+ engine->sched_engine = i915_sched_engine_create(ENGINE_MOCK);
+ if (!engine->sched_engine)
+ return -ENOMEM;
+ engine->sched_engine->private_data = engine;
+
intel_engine_init_execlists(engine);
intel_engine_init__pm(engine);
intel_engine_init_retire(engine);
engine->breadcrumbs = intel_breadcrumbs_create(NULL);
if (!engine->breadcrumbs)
- return -ENOMEM;
+ goto err_schedule;
ce = create_kernel_context(engine);
if (IS_ERR(ce))
@@ -365,7 +400,9 @@ int mock_engine_init(struct intel_engine_cs *engine)
return 0;
err_breadcrumbs:
- intel_breadcrumbs_free(engine->breadcrumbs);
+ intel_breadcrumbs_put(engine->breadcrumbs);
+err_schedule:
+ i915_sched_engine_put(engine->sched_engine);
return -ENOMEM;
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c
index 26685b927169..fa7b99a671dd 100644
--- a/drivers/gpu/drm/i915/gt/selftest_context.c
+++ b/drivers/gpu/drm/i915/gt/selftest_context.c
@@ -209,7 +209,13 @@ static int __live_active_context(struct intel_engine_cs *engine)
* This test makes sure that the context is kept alive until a
* subsequent idle-barrier (emitted when the engine wakeref hits 0
* with no more outstanding requests).
+ *
+ * In GuC submission mode we don't use idle barriers and we instead
+ * get a message from the GuC to signal that it is safe to unpin the
+ * context from memory.
*/
+ if (intel_engine_uses_guc(engine))
+ return 0;
if (intel_engine_pm_is_awake(engine)) {
pr_err("%s is awake before starting %s!\n",
@@ -357,7 +363,11 @@ static int __live_remote_context(struct intel_engine_cs *engine)
* on the context image remotely (intel_context_prepare_remote_request),
* which inserts foreign fences into intel_context.active, does not
* clobber the idle-barrier.
+ *
+ * In GuC submission mode we don't use idle barriers.
*/
+ if (intel_engine_uses_guc(engine))
+ return 0;
if (intel_engine_pm_is_awake(engine)) {
pr_err("%s is awake before starting %s!\n",
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
index 4896e4ccad50..317eebf086c3 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
@@ -405,3 +405,25 @@ void st_engine_heartbeat_enable(struct intel_engine_cs *engine)
engine->props.heartbeat_interval_ms =
engine->defaults.heartbeat_interval_ms;
}
+
+void st_engine_heartbeat_disable_no_pm(struct intel_engine_cs *engine)
+{
+ engine->props.heartbeat_interval_ms = 0;
+
+ /*
+ * Park the heartbeat but without holding the PM lock as that
+ * makes the engines appear not-idle. Note that if/when unpark
+ * is called due to the PM lock being acquired later the
+ * heartbeat still won't be enabled because of the above = 0.
+ */
+ if (intel_engine_pm_get_if_awake(engine)) {
+ intel_engine_park_heartbeat(engine);
+ intel_engine_pm_put(engine);
+ }
+}
+
+void st_engine_heartbeat_enable_no_pm(struct intel_engine_cs *engine)
+{
+ engine->props.heartbeat_interval_ms =
+ engine->defaults.heartbeat_interval_ms;
+}
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h
index cd27113d5400..81da2cd8e406 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.h
@@ -9,6 +9,8 @@
struct intel_engine_cs;
void st_engine_heartbeat_disable(struct intel_engine_cs *engine);
+void st_engine_heartbeat_disable_no_pm(struct intel_engine_cs *engine);
void st_engine_heartbeat_enable(struct intel_engine_cs *engine);
+void st_engine_heartbeat_enable_no_pm(struct intel_engine_cs *engine);
#endif /* SELFTEST_ENGINE_HEARTBEAT_H */
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
index 72cca3f0da21..75569666105d 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
@@ -173,8 +173,8 @@ static int __live_engine_timestamps(struct intel_engine_cs *engine)
d_ctx = trifilter(s_ctx);
d_ctx *= engine->gt->clock_frequency;
- if (IS_ICELAKE(engine->i915))
- d_ring *= 12500000; /* Fixed 80ns for icl ctx timestamp? */
+ if (GRAPHICS_VER(engine->i915) == 11)
+ d_ring *= 12500000; /* Fixed 80ns for GEN11 ctx timestamp? */
else
d_ring *= engine->gt->clock_frequency;
diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c
index 1c8108d30b85..f12ffe797639 100644
--- a/drivers/gpu/drm/i915/gt/selftest_execlists.c
+++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c
@@ -43,7 +43,7 @@ static int wait_for_submit(struct intel_engine_cs *engine,
unsigned long timeout)
{
/* Ignore our own attempts to suppress excess tasklets */
- tasklet_hi_schedule(&engine->execlists.tasklet);
+ tasklet_hi_schedule(&engine->sched_engine->tasklet);
timeout += jiffies;
do {
@@ -273,7 +273,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
};
/* Alternatively preempt the spinner with ce[1] */
- engine->schedule(rq[1], &attr);
+ engine->sched_engine->schedule(rq[1], &attr);
}
/* And switch back to ce[0] for good measure */
@@ -553,13 +553,13 @@ static int live_pin_rewind(void *arg)
static int engine_lock_reset_tasklet(struct intel_engine_cs *engine)
{
- tasklet_disable(&engine->execlists.tasklet);
+ tasklet_disable(&engine->sched_engine->tasklet);
local_bh_disable();
if (test_and_set_bit(I915_RESET_ENGINE + engine->id,
&engine->gt->reset.flags)) {
local_bh_enable();
- tasklet_enable(&engine->execlists.tasklet);
+ tasklet_enable(&engine->sched_engine->tasklet);
intel_gt_set_wedged(engine->gt);
return -EBUSY;
@@ -574,7 +574,7 @@ static void engine_unlock_reset_tasklet(struct intel_engine_cs *engine)
&engine->gt->reset.flags);
local_bh_enable();
- tasklet_enable(&engine->execlists.tasklet);
+ tasklet_enable(&engine->sched_engine->tasklet);
}
static int live_hold_reset(void *arg)
@@ -628,7 +628,7 @@ static int live_hold_reset(void *arg)
if (err)
goto out;
- engine->execlists.tasklet.callback(&engine->execlists.tasklet);
+ engine->sched_engine->tasklet.callback(&engine->sched_engine->tasklet);
GEM_BUG_ON(execlists_active(&engine->execlists) != rq);
i915_request_get(rq);
@@ -917,7 +917,7 @@ release_queue(struct intel_engine_cs *engine,
i915_request_add(rq);
local_bh_disable();
- engine->schedule(rq, &attr);
+ engine->sched_engine->schedule(rq, &attr);
local_bh_enable(); /* kick tasklet */
i915_request_put(rq);
@@ -1200,7 +1200,7 @@ static int live_timeslice_rewind(void *arg)
while (i915_request_is_active(rq[A2])) { /* semaphore yield! */
/* Wait for the timeslice to kick in */
del_timer(&engine->execlists.timer);
- tasklet_hi_schedule(&engine->execlists.tasklet);
+ tasklet_hi_schedule(&engine->sched_engine->tasklet);
intel_engine_flush_submission(engine);
}
/* -> ELSP[] = { { A:rq1 }, { B:rq1 } } */
@@ -1342,7 +1342,7 @@ static int live_timeslice_queue(void *arg)
err = PTR_ERR(rq);
goto err_heartbeat;
}
- engine->schedule(rq, &attr);
+ engine->sched_engine->schedule(rq, &attr);
err = wait_for_submit(engine, rq, HZ / 2);
if (err) {
pr_err("%s: Timed out trying to submit semaphores\n",
@@ -1539,12 +1539,12 @@ static int live_busywait_preempt(void *arg)
* preempt the busywaits used to synchronise between rings.
*/
- ctx_hi = kernel_context(gt->i915);
+ ctx_hi = kernel_context(gt->i915, NULL);
if (!ctx_hi)
return -ENOMEM;
ctx_hi->sched.priority = I915_CONTEXT_MAX_USER_PRIORITY;
- ctx_lo = kernel_context(gt->i915);
+ ctx_lo = kernel_context(gt->i915, NULL);
if (!ctx_lo)
goto err_ctx_hi;
ctx_lo->sched.priority = I915_CONTEXT_MIN_USER_PRIORITY;
@@ -1741,12 +1741,12 @@ static int live_preempt(void *arg)
if (igt_spinner_init(&spin_lo, gt))
goto err_spin_hi;
- ctx_hi = kernel_context(gt->i915);
+ ctx_hi = kernel_context(gt->i915, NULL);
if (!ctx_hi)
goto err_spin_lo;
ctx_hi->sched.priority = I915_CONTEXT_MAX_USER_PRIORITY;
- ctx_lo = kernel_context(gt->i915);
+ ctx_lo = kernel_context(gt->i915, NULL);
if (!ctx_lo)
goto err_ctx_hi;
ctx_lo->sched.priority = I915_CONTEXT_MIN_USER_PRIORITY;
@@ -1833,11 +1833,11 @@ static int live_late_preempt(void *arg)
if (igt_spinner_init(&spin_lo, gt))
goto err_spin_hi;
- ctx_hi = kernel_context(gt->i915);
+ ctx_hi = kernel_context(gt->i915, NULL);
if (!ctx_hi)
goto err_spin_lo;
- ctx_lo = kernel_context(gt->i915);
+ ctx_lo = kernel_context(gt->i915, NULL);
if (!ctx_lo)
goto err_ctx_hi;
@@ -1884,7 +1884,7 @@ static int live_late_preempt(void *arg)
}
attr.priority = I915_PRIORITY_MAX;
- engine->schedule(rq, &attr);
+ engine->sched_engine->schedule(rq, &attr);
if (!igt_wait_for_spinner(&spin_hi, rq)) {
pr_err("High priority context failed to preempt the low priority context\n");
@@ -1927,7 +1927,7 @@ struct preempt_client {
static int preempt_client_init(struct intel_gt *gt, struct preempt_client *c)
{
- c->ctx = kernel_context(gt->i915);
+ c->ctx = kernel_context(gt->i915, NULL);
if (!c->ctx)
return -ENOMEM;
@@ -2497,7 +2497,7 @@ static int live_suppress_self_preempt(void *arg)
i915_request_add(rq_b);
GEM_BUG_ON(i915_request_completed(rq_a));
- engine->schedule(rq_a, &attr);
+ engine->sched_engine->schedule(rq_a, &attr);
igt_spinner_end(&a.spin);
if (!igt_wait_for_spinner(&b.spin, rq_b)) {
@@ -2629,7 +2629,7 @@ static int live_chain_preempt(void *arg)
i915_request_get(rq);
i915_request_add(rq);
- engine->schedule(rq, &attr);
+ engine->sched_engine->schedule(rq, &attr);
igt_spinner_end(&hi.spin);
if (i915_request_wait(rq, 0, HZ / 5) < 0) {
@@ -2810,7 +2810,7 @@ static int __live_preempt_ring(struct intel_engine_cs *engine,
goto err_ce;
}
- tmp->ring = __intel_context_ring_size(ring_sz);
+ tmp->ring_size = ring_sz;
err = intel_context_pin(tmp);
if (err) {
@@ -2988,7 +2988,7 @@ static int live_preempt_gang(void *arg)
break;
/* Submit each spinner at increasing priority */
- engine->schedule(rq, &attr);
+ engine->sched_engine->schedule(rq, &attr);
} while (prio <= I915_PRIORITY_MAX &&
!__igt_timeout(end_time, NULL));
pr_debug("%s: Preempt chain of %d requests\n",
@@ -3236,7 +3236,7 @@ static int preempt_user(struct intel_engine_cs *engine,
i915_request_get(rq);
i915_request_add(rq);
- engine->schedule(rq, &attr);
+ engine->sched_engine->schedule(rq, &attr);
if (i915_request_wait(rq, 0, HZ / 2) < 0)
err = -ETIME;
@@ -3384,12 +3384,12 @@ static int live_preempt_timeout(void *arg)
if (igt_spinner_init(&spin_lo, gt))
return -ENOMEM;
- ctx_hi = kernel_context(gt->i915);
+ ctx_hi = kernel_context(gt->i915, NULL);
if (!ctx_hi)
goto err_spin_lo;
ctx_hi->sched.priority = I915_CONTEXT_MAX_USER_PRIORITY;
- ctx_lo = kernel_context(gt->i915);
+ ctx_lo = kernel_context(gt->i915, NULL);
if (!ctx_lo)
goto err_ctx_hi;
ctx_lo->sched.priority = I915_CONTEXT_MIN_USER_PRIORITY;
@@ -3561,12 +3561,16 @@ static int smoke_crescendo(struct preempt_smoke *smoke, unsigned int flags)
#define BATCH BIT(0)
{
struct task_struct *tsk[I915_NUM_ENGINES] = {};
- struct preempt_smoke arg[I915_NUM_ENGINES];
+ struct preempt_smoke *arg;
struct intel_engine_cs *engine;
enum intel_engine_id id;
unsigned long count;
int err = 0;
+ arg = kmalloc_array(I915_NUM_ENGINES, sizeof(*arg), GFP_KERNEL);
+ if (!arg)
+ return -ENOMEM;
+
for_each_engine(engine, smoke->gt, id) {
arg[id] = *smoke;
arg[id].engine = engine;
@@ -3574,7 +3578,7 @@ static int smoke_crescendo(struct preempt_smoke *smoke, unsigned int flags)
arg[id].batch = NULL;
arg[id].count = 0;
- tsk[id] = kthread_run(smoke_crescendo_thread, &arg,
+ tsk[id] = kthread_run(smoke_crescendo_thread, arg,
"igt/smoke:%d", id);
if (IS_ERR(tsk[id])) {
err = PTR_ERR(tsk[id]);
@@ -3603,6 +3607,8 @@ static int smoke_crescendo(struct preempt_smoke *smoke, unsigned int flags)
pr_info("Submitted %lu crescendo:%x requests across %d engines and %d contexts\n",
count, flags, smoke->gt->info.num_engines, smoke->ncontext);
+
+ kfree(arg);
return 0;
}
@@ -3676,7 +3682,7 @@ static int live_preempt_smoke(void *arg)
}
for (n = 0; n < smoke.ncontext; n++) {
- smoke.contexts[n] = kernel_context(smoke.gt->i915);
+ smoke.contexts[n] = kernel_context(smoke.gt->i915, NULL);
if (!smoke.contexts[n])
goto err_ctx;
}
@@ -3727,7 +3733,7 @@ static int nop_virtual_engine(struct intel_gt *gt,
GEM_BUG_ON(!nctx || nctx > ARRAY_SIZE(ve));
for (n = 0; n < nctx; n++) {
- ve[n] = intel_execlists_create_virtual(siblings, nsibling);
+ ve[n] = intel_engine_create_virtual(siblings, nsibling);
if (IS_ERR(ve[n])) {
err = PTR_ERR(ve[n]);
nctx = n;
@@ -3923,7 +3929,7 @@ static int mask_virtual_engine(struct intel_gt *gt,
* restrict it to our desired engine within the virtual engine.
*/
- ve = intel_execlists_create_virtual(siblings, nsibling);
+ ve = intel_engine_create_virtual(siblings, nsibling);
if (IS_ERR(ve)) {
err = PTR_ERR(ve);
goto out_close;
@@ -4054,7 +4060,7 @@ static int slicein_virtual_engine(struct intel_gt *gt,
i915_request_add(rq);
}
- ce = intel_execlists_create_virtual(siblings, nsibling);
+ ce = intel_engine_create_virtual(siblings, nsibling);
if (IS_ERR(ce)) {
err = PTR_ERR(ce);
goto out;
@@ -4106,7 +4112,7 @@ static int sliceout_virtual_engine(struct intel_gt *gt,
/* XXX We do not handle oversubscription and fairness with normal rq */
for (n = 0; n < nsibling; n++) {
- ce = intel_execlists_create_virtual(siblings, nsibling);
+ ce = intel_engine_create_virtual(siblings, nsibling);
if (IS_ERR(ce)) {
err = PTR_ERR(ce);
goto out;
@@ -4208,7 +4214,7 @@ static int preserved_virtual_engine(struct intel_gt *gt,
if (err)
goto out_scratch;
- ve = intel_execlists_create_virtual(siblings, nsibling);
+ ve = intel_engine_create_virtual(siblings, nsibling);
if (IS_ERR(ve)) {
err = PTR_ERR(ve);
goto out_scratch;
@@ -4328,234 +4334,6 @@ static int live_virtual_preserved(void *arg)
return 0;
}
-static int bond_virtual_engine(struct intel_gt *gt,
- unsigned int class,
- struct intel_engine_cs **siblings,
- unsigned int nsibling,
- unsigned int flags)
-#define BOND_SCHEDULE BIT(0)
-{
- struct intel_engine_cs *master;
- struct i915_request *rq[16];
- enum intel_engine_id id;
- struct igt_spinner spin;
- unsigned long n;
- int err;
-
- /*
- * A set of bonded requests is intended to be run concurrently
- * across a number of engines. We use one request per-engine
- * and a magic fence to schedule each of the bonded requests
- * at the same time. A consequence of our current scheduler is that
- * we only move requests to the HW ready queue when the request
- * becomes ready, that is when all of its prerequisite fences have
- * been signaled. As one of those fences is the master submit fence,
- * there is a delay on all secondary fences as the HW may be
- * currently busy. Equally, as all the requests are independent,
- * they may have other fences that delay individual request
- * submission to HW. Ergo, we do not guarantee that all requests are
- * immediately submitted to HW at the same time, just that if the
- * rules are abided by, they are ready at the same time as the
- * first is submitted. Userspace can embed semaphores in its batch
- * to ensure parallel execution of its phases as it requires.
- * Though naturally it gets requested that perhaps the scheduler should
- * take care of parallel execution, even across preemption events on
- * different HW. (The proper answer is of course "lalalala".)
- *
- * With the submit-fence, we have identified three possible phases
- * of synchronisation depending on the master fence: queued (not
- * ready), executing, and signaled. The first two are quite simple
- * and checked below. However, the signaled master fence handling is
- * contentious. Currently we do not distinguish between a signaled
- * fence and an expired fence, as once signaled it does not convey
- * any information about the previous execution. It may even be freed
- * and hence checking later it may not exist at all. Ergo we currently
- * do not apply the bonding constraint for an already signaled fence,
- * as our expectation is that it should not constrain the secondaries
- * and is outside of the scope of the bonded request API (i.e. all
- * userspace requests are meant to be running in parallel). As
- * it imposes no constraint, and is effectively a no-op, we do not
- * check below as normal execution flows are checked extensively above.
- *
- * XXX Is the degenerate handling of signaled submit fences the
- * expected behaviour for userpace?
- */
-
- GEM_BUG_ON(nsibling >= ARRAY_SIZE(rq) - 1);
-
- if (igt_spinner_init(&spin, gt))
- return -ENOMEM;
-
- err = 0;
- rq[0] = ERR_PTR(-ENOMEM);
- for_each_engine(master, gt, id) {
- struct i915_sw_fence fence = {};
- struct intel_context *ce;
-
- if (master->class == class)
- continue;
-
- ce = intel_context_create(master);
- if (IS_ERR(ce)) {
- err = PTR_ERR(ce);
- goto out;
- }
-
- memset_p((void *)rq, ERR_PTR(-EINVAL), ARRAY_SIZE(rq));
-
- rq[0] = igt_spinner_create_request(&spin, ce, MI_NOOP);
- intel_context_put(ce);
- if (IS_ERR(rq[0])) {
- err = PTR_ERR(rq[0]);
- goto out;
- }
- i915_request_get(rq[0]);
-
- if (flags & BOND_SCHEDULE) {
- onstack_fence_init(&fence);
- err = i915_sw_fence_await_sw_fence_gfp(&rq[0]->submit,
- &fence,
- GFP_KERNEL);
- }
-
- i915_request_add(rq[0]);
- if (err < 0)
- goto out;
-
- if (!(flags & BOND_SCHEDULE) &&
- !igt_wait_for_spinner(&spin, rq[0])) {
- err = -EIO;
- goto out;
- }
-
- for (n = 0; n < nsibling; n++) {
- struct intel_context *ve;
-
- ve = intel_execlists_create_virtual(siblings, nsibling);
- if (IS_ERR(ve)) {
- err = PTR_ERR(ve);
- onstack_fence_fini(&fence);
- goto out;
- }
-
- err = intel_virtual_engine_attach_bond(ve->engine,
- master,
- siblings[n]);
- if (err) {
- intel_context_put(ve);
- onstack_fence_fini(&fence);
- goto out;
- }
-
- err = intel_context_pin(ve);
- intel_context_put(ve);
- if (err) {
- onstack_fence_fini(&fence);
- goto out;
- }
-
- rq[n + 1] = i915_request_create(ve);
- intel_context_unpin(ve);
- if (IS_ERR(rq[n + 1])) {
- err = PTR_ERR(rq[n + 1]);
- onstack_fence_fini(&fence);
- goto out;
- }
- i915_request_get(rq[n + 1]);
-
- err = i915_request_await_execution(rq[n + 1],
- &rq[0]->fence,
- ve->engine->bond_execute);
- i915_request_add(rq[n + 1]);
- if (err < 0) {
- onstack_fence_fini(&fence);
- goto out;
- }
- }
- onstack_fence_fini(&fence);
- intel_engine_flush_submission(master);
- igt_spinner_end(&spin);
-
- if (i915_request_wait(rq[0], 0, HZ / 10) < 0) {
- pr_err("Master request did not execute (on %s)!\n",
- rq[0]->engine->name);
- err = -EIO;
- goto out;
- }
-
- for (n = 0; n < nsibling; n++) {
- if (i915_request_wait(rq[n + 1], 0,
- MAX_SCHEDULE_TIMEOUT) < 0) {
- err = -EIO;
- goto out;
- }
-
- if (rq[n + 1]->engine != siblings[n]) {
- pr_err("Bonded request did not execute on target engine: expected %s, used %s; master was %s\n",
- siblings[n]->name,
- rq[n + 1]->engine->name,
- rq[0]->engine->name);
- err = -EINVAL;
- goto out;
- }
- }
-
- for (n = 0; !IS_ERR(rq[n]); n++)
- i915_request_put(rq[n]);
- rq[0] = ERR_PTR(-ENOMEM);
- }
-
-out:
- for (n = 0; !IS_ERR(rq[n]); n++)
- i915_request_put(rq[n]);
- if (igt_flush_test(gt->i915))
- err = -EIO;
-
- igt_spinner_fini(&spin);
- return err;
-}
-
-static int live_virtual_bond(void *arg)
-{
- static const struct phase {
- const char *name;
- unsigned int flags;
- } phases[] = {
- { "", 0 },
- { "schedule", BOND_SCHEDULE },
- { },
- };
- struct intel_gt *gt = arg;
- struct intel_engine_cs *siblings[MAX_ENGINE_INSTANCE + 1];
- unsigned int class;
- int err;
-
- if (intel_uc_uses_guc_submission(&gt->uc))
- return 0;
-
- for (class = 0; class <= MAX_ENGINE_CLASS; class++) {
- const struct phase *p;
- int nsibling;
-
- nsibling = select_siblings(gt, class, siblings);
- if (nsibling < 2)
- continue;
-
- for (p = phases; p->name; p++) {
- err = bond_virtual_engine(gt,
- class, siblings, nsibling,
- p->flags);
- if (err) {
- pr_err("%s(%s): failed class=%d, nsibling=%d, err=%d\n",
- __func__, p->name, class, nsibling, err);
- return err;
- }
- }
- }
-
- return 0;
-}
-
static int reset_virtual_engine(struct intel_gt *gt,
struct intel_engine_cs **siblings,
unsigned int nsibling)
@@ -4576,7 +4354,7 @@ static int reset_virtual_engine(struct intel_gt *gt,
if (igt_spinner_init(&spin, gt))
return -ENOMEM;
- ve = intel_execlists_create_virtual(siblings, nsibling);
+ ve = intel_engine_create_virtual(siblings, nsibling);
if (IS_ERR(ve)) {
err = PTR_ERR(ve);
goto out_spin;
@@ -4606,13 +4384,13 @@ static int reset_virtual_engine(struct intel_gt *gt,
if (err)
goto out_heartbeat;
- engine->execlists.tasklet.callback(&engine->execlists.tasklet);
+ engine->sched_engine->tasklet.callback(&engine->sched_engine->tasklet);
GEM_BUG_ON(execlists_active(&engine->execlists) != rq);
/* Fake a preemption event; failed of course */
- spin_lock_irq(&engine->active.lock);
+ spin_lock_irq(&engine->sched_engine->lock);
__unwind_incomplete_requests(engine);
- spin_unlock_irq(&engine->active.lock);
+ spin_unlock_irq(&engine->sched_engine->lock);
GEM_BUG_ON(rq->engine != engine);
/* Reset the engine while keeping our active request on hold */
@@ -4721,7 +4499,6 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915)
SUBTEST(live_virtual_mask),
SUBTEST(live_virtual_preserved),
SUBTEST(live_virtual_slice),
- SUBTEST(live_virtual_bond),
SUBTEST(live_virtual_reset),
};
diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
index 853246fad05f..2c1ed32ca5ac 100644
--- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
@@ -17,6 +17,8 @@
#include "selftests/igt_flush_test.h"
#include "selftests/igt_reset.h"
#include "selftests/igt_atomic.h"
+#include "selftests/igt_spinner.h"
+#include "selftests/intel_scheduler_helpers.h"
#include "selftests/mock_drm.h"
@@ -42,7 +44,7 @@ static int hang_init(struct hang *h, struct intel_gt *gt)
memset(h, 0, sizeof(*h));
h->gt = gt;
- h->ctx = kernel_context(gt->i915);
+ h->ctx = kernel_context(gt->i915, NULL);
if (IS_ERR(h->ctx))
return PTR_ERR(h->ctx);
@@ -378,6 +380,7 @@ static int igt_reset_nop(void *arg)
ce = intel_context_create(engine);
if (IS_ERR(ce)) {
err = PTR_ERR(ce);
+ pr_err("[%s] Create context failed: %d!\n", engine->name, err);
break;
}
@@ -387,6 +390,8 @@ static int igt_reset_nop(void *arg)
rq = intel_context_create_request(ce);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
+ pr_err("[%s] Create request failed: %d!\n",
+ engine->name, err);
break;
}
@@ -401,24 +406,31 @@ static int igt_reset_nop(void *arg)
igt_global_reset_unlock(gt);
if (intel_gt_is_wedged(gt)) {
+ pr_err("[%s] GT is wedged!\n", engine->name);
err = -EIO;
break;
}
if (i915_reset_count(global) != reset_count + ++count) {
- pr_err("Full GPU reset not recorded!\n");
+ pr_err("[%s] Reset not recorded: %d vs %d + %d!\n",
+ engine->name, i915_reset_count(global), reset_count, count);
err = -EINVAL;
break;
}
err = igt_flush_test(gt->i915);
- if (err)
+ if (err) {
+ pr_err("[%s] Flush failed: %d!\n", engine->name, err);
break;
+ }
} while (time_before(jiffies, end_time));
pr_info("%s: %d resets\n", __func__, count);
- if (igt_flush_test(gt->i915))
+ if (igt_flush_test(gt->i915)) {
+ pr_err("Post flush failed: %d!\n", err);
err = -EIO;
+ }
+
return err;
}
@@ -440,9 +452,19 @@ static int igt_reset_nop_engine(void *arg)
IGT_TIMEOUT(end_time);
int err;
+ if (intel_engine_uses_guc(engine)) {
+ /* Engine level resets are triggered by GuC when a hang
+ * is detected. They can't be triggered by the KMD any
+ * more. Thus a nop batch cannot be used as a reset test
+ */
+ continue;
+ }
+
ce = intel_context_create(engine);
- if (IS_ERR(ce))
+ if (IS_ERR(ce)) {
+ pr_err("[%s] Create context failed: %pe!\n", engine->name, ce);
return PTR_ERR(ce);
+ }
reset_count = i915_reset_count(global);
reset_engine_count = i915_reset_engine_count(global, engine);
@@ -549,9 +571,15 @@ static int igt_reset_fail_engine(void *arg)
IGT_TIMEOUT(end_time);
int err;
+ /* Can't manually break the reset if i915 doesn't perform it */
+ if (intel_engine_uses_guc(engine))
+ continue;
+
ce = intel_context_create(engine);
- if (IS_ERR(ce))
+ if (IS_ERR(ce)) {
+ pr_err("[%s] Create context failed: %pe!\n", engine->name, ce);
return PTR_ERR(ce);
+ }
st_engine_heartbeat_disable(engine);
set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
@@ -686,8 +714,12 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
for_each_engine(engine, gt, id) {
unsigned int reset_count, reset_engine_count;
unsigned long count;
+ bool using_guc = intel_engine_uses_guc(engine);
IGT_TIMEOUT(end_time);
+ if (using_guc && !active)
+ continue;
+
if (active && !intel_engine_can_store_dword(engine))
continue;
@@ -705,13 +737,24 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
count = 0;
do {
- if (active) {
- struct i915_request *rq;
+ struct i915_request *rq = NULL;
+ struct intel_selftest_saved_policy saved;
+ int err2;
+
+ err = intel_selftest_modify_policy(engine, &saved,
+ SELFTEST_SCHEDULER_MODIFY_FAST_RESET);
+ if (err) {
+ pr_err("[%s] Modify policy failed: %d!\n", engine->name, err);
+ break;
+ }
+ if (active) {
rq = hang_create_request(&h, engine);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
- break;
+ pr_err("[%s] Create hang request failed: %d!\n",
+ engine->name, err);
+ goto restore;
}
i915_request_get(rq);
@@ -727,34 +770,59 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
i915_request_put(rq);
err = -EIO;
- break;
+ goto restore;
}
+ }
- i915_request_put(rq);
+ if (!using_guc) {
+ err = intel_engine_reset(engine, NULL);
+ if (err) {
+ pr_err("intel_engine_reset(%s) failed, err:%d\n",
+ engine->name, err);
+ goto skip;
+ }
}
- err = intel_engine_reset(engine, NULL);
- if (err) {
- pr_err("intel_engine_reset(%s) failed, err:%d\n",
- engine->name, err);
- break;
+ if (rq) {
+ /* Ensure the reset happens and kills the engine */
+ err = intel_selftest_wait_for_rq(rq);
+ if (err)
+ pr_err("[%s] Wait for request %lld:%lld [0x%04X] failed: %d!\n",
+ engine->name, rq->fence.context,
+ rq->fence.seqno, rq->context->guc_id, err);
}
+skip:
+ if (rq)
+ i915_request_put(rq);
+
if (i915_reset_count(global) != reset_count) {
pr_err("Full GPU reset recorded! (engine reset expected)\n");
err = -EINVAL;
- break;
+ goto restore;
}
- if (i915_reset_engine_count(global, engine) !=
- ++reset_engine_count) {
- pr_err("%s engine reset not recorded!\n",
- engine->name);
- err = -EINVAL;
- break;
+ /* GuC based resets are not logged per engine */
+ if (!using_guc) {
+ if (i915_reset_engine_count(global, engine) !=
+ ++reset_engine_count) {
+ pr_err("%s engine reset not recorded!\n",
+ engine->name);
+ err = -EINVAL;
+ goto restore;
+ }
}
count++;
+
+restore:
+ err2 = intel_selftest_restore_policy(engine, &saved);
+ if (err2)
+ pr_err("[%s] Restore policy failed: %d!\n", engine->name, err);
+ if (err == 0)
+ err = err2;
+ if (err)
+ break;
} while (time_before(jiffies, end_time));
clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
st_engine_heartbeat_enable(engine);
@@ -765,12 +833,16 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active)
break;
err = igt_flush_test(gt->i915);
- if (err)
+ if (err) {
+ pr_err("[%s] Flush failed: %d!\n", engine->name, err);
break;
+ }
}
- if (intel_gt_is_wedged(gt))
+ if (intel_gt_is_wedged(gt)) {
+ pr_err("GT is wedged!\n");
err = -EIO;
+ }
if (active)
hang_fini(&h);
@@ -807,7 +879,7 @@ static int active_request_put(struct i915_request *rq)
if (!rq)
return 0;
- if (i915_request_wait(rq, 0, 5 * HZ) < 0) {
+ if (i915_request_wait(rq, 0, 10 * HZ) < 0) {
GEM_TRACE("%s timed out waiting for completion of fence %llx:%lld\n",
rq->engine->name,
rq->fence.context,
@@ -837,6 +909,7 @@ static int active_engine(void *data)
ce[count] = intel_context_create(engine);
if (IS_ERR(ce[count])) {
err = PTR_ERR(ce[count]);
+ pr_err("[%s] Create context #%ld failed: %d!\n", engine->name, count, err);
while (--count)
intel_context_put(ce[count]);
return err;
@@ -852,23 +925,26 @@ static int active_engine(void *data)
new = intel_context_create_request(ce[idx]);
if (IS_ERR(new)) {
err = PTR_ERR(new);
+ pr_err("[%s] Create request #%d failed: %d!\n", engine->name, idx, err);
break;
}
rq[idx] = i915_request_get(new);
i915_request_add(new);
- if (engine->schedule && arg->flags & TEST_PRIORITY) {
+ if (engine->sched_engine->schedule && arg->flags & TEST_PRIORITY) {
struct i915_sched_attr attr = {
.priority =
i915_prandom_u32_max_state(512, &prng),
};
- engine->schedule(rq[idx], &attr);
+ engine->sched_engine->schedule(rq[idx], &attr);
}
err = active_request_put(old);
- if (err)
+ if (err) {
+ pr_err("[%s] Request put failed: %d!\n", engine->name, err);
break;
+ }
cond_resched();
}
@@ -876,6 +952,9 @@ static int active_engine(void *data)
for (count = 0; count < ARRAY_SIZE(rq); count++) {
int err__ = active_request_put(rq[count]);
+ if (err)
+ pr_err("[%s] Request put #%ld failed: %d!\n", engine->name, count, err);
+
/* Keep the first error */
if (!err)
err = err__;
@@ -916,10 +995,13 @@ static int __igt_reset_engines(struct intel_gt *gt,
struct active_engine threads[I915_NUM_ENGINES] = {};
unsigned long device = i915_reset_count(global);
unsigned long count = 0, reported;
+ bool using_guc = intel_engine_uses_guc(engine);
IGT_TIMEOUT(end_time);
- if (flags & TEST_ACTIVE &&
- !intel_engine_can_store_dword(engine))
+ if (flags & TEST_ACTIVE) {
+ if (!intel_engine_can_store_dword(engine))
+ continue;
+ } else if (using_guc)
continue;
if (!wait_for_idle(engine)) {
@@ -949,6 +1031,7 @@ static int __igt_reset_engines(struct intel_gt *gt,
"igt/%s", other->name);
if (IS_ERR(tsk)) {
err = PTR_ERR(tsk);
+ pr_err("[%s] Thread spawn failed: %d!\n", engine->name, err);
goto unwind;
}
@@ -958,16 +1041,27 @@ static int __igt_reset_engines(struct intel_gt *gt,
yield(); /* start all threads before we begin */
- st_engine_heartbeat_disable(engine);
+ st_engine_heartbeat_disable_no_pm(engine);
set_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
do {
struct i915_request *rq = NULL;
+ struct intel_selftest_saved_policy saved;
+ int err2;
+
+ err = intel_selftest_modify_policy(engine, &saved,
+ SELFTEST_SCHEDULER_MODIFY_FAST_RESET);
+ if (err) {
+ pr_err("[%s] Modify policy failed: %d!\n", engine->name, err);
+ break;
+ }
if (flags & TEST_ACTIVE) {
rq = hang_create_request(&h, engine);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
- break;
+ pr_err("[%s] Create hang request failed: %d!\n",
+ engine->name, err);
+ goto restore;
}
i915_request_get(rq);
@@ -983,32 +1077,44 @@ static int __igt_reset_engines(struct intel_gt *gt,
i915_request_put(rq);
err = -EIO;
- break;
+ goto restore;
}
+ } else {
+ intel_engine_pm_get(engine);
}
- err = intel_engine_reset(engine, NULL);
- if (err) {
- pr_err("i915_reset_engine(%s:%s): failed, err=%d\n",
- engine->name, test_name, err);
- break;
+ if (!using_guc) {
+ err = intel_engine_reset(engine, NULL);
+ if (err) {
+ pr_err("i915_reset_engine(%s:%s): failed, err=%d\n",
+ engine->name, test_name, err);
+ goto restore;
+ }
+ }
+
+ if (rq) {
+ /* Ensure the reset happens and kills the engine */
+ err = intel_selftest_wait_for_rq(rq);
+ if (err)
+ pr_err("[%s] Wait for request %lld:%lld [0x%04X] failed: %d!\n",
+ engine->name, rq->fence.context,
+ rq->fence.seqno, rq->context->guc_id, err);
}
count++;
if (rq) {
if (rq->fence.error != -EIO) {
- pr_err("i915_reset_engine(%s:%s):"
- " failed to reset request %llx:%lld\n",
+ pr_err("i915_reset_engine(%s:%s): failed to reset request %lld:%lld [0x%04X]\n",
engine->name, test_name,
rq->fence.context,
- rq->fence.seqno);
+ rq->fence.seqno, rq->context->guc_id);
i915_request_put(rq);
GEM_TRACE_DUMP();
intel_gt_set_wedged(gt);
err = -EIO;
- break;
+ goto restore;
}
if (i915_request_wait(rq, 0, HZ / 5) < 0) {
@@ -1027,12 +1133,15 @@ static int __igt_reset_engines(struct intel_gt *gt,
GEM_TRACE_DUMP();
intel_gt_set_wedged(gt);
err = -EIO;
- break;
+ goto restore;
}
i915_request_put(rq);
}
+ if (!(flags & TEST_ACTIVE))
+ intel_engine_pm_put(engine);
+
if (!(flags & TEST_SELF) && !wait_for_idle(engine)) {
struct drm_printer p =
drm_info_printer(gt->i915->drm.dev);
@@ -1044,22 +1153,34 @@ static int __igt_reset_engines(struct intel_gt *gt,
"%s\n", engine->name);
err = -EIO;
- break;
+ goto restore;
}
+
+restore:
+ err2 = intel_selftest_restore_policy(engine, &saved);
+ if (err2)
+ pr_err("[%s] Restore policy failed: %d!\n", engine->name, err2);
+ if (err == 0)
+ err = err2;
+ if (err)
+ break;
} while (time_before(jiffies, end_time));
clear_bit(I915_RESET_ENGINE + id, &gt->reset.flags);
- st_engine_heartbeat_enable(engine);
+ st_engine_heartbeat_enable_no_pm(engine);
pr_info("i915_reset_engine(%s:%s): %lu resets\n",
engine->name, test_name, count);
- reported = i915_reset_engine_count(global, engine);
- reported -= threads[engine->id].resets;
- if (reported != count) {
- pr_err("i915_reset_engine(%s:%s): reset %lu times, but reported %lu\n",
- engine->name, test_name, count, reported);
- if (!err)
- err = -EINVAL;
+ /* GuC based resets are not logged per engine */
+ if (!using_guc) {
+ reported = i915_reset_engine_count(global, engine);
+ reported -= threads[engine->id].resets;
+ if (reported != count) {
+ pr_err("i915_reset_engine(%s:%s): reset %lu times, but reported %lu\n",
+ engine->name, test_name, count, reported);
+ if (!err)
+ err = -EINVAL;
+ }
}
unwind:
@@ -1078,15 +1199,18 @@ unwind:
}
put_task_struct(threads[tmp].task);
- if (other->uabi_class != engine->uabi_class &&
- threads[tmp].resets !=
- i915_reset_engine_count(global, other)) {
- pr_err("Innocent engine %s was reset (count=%ld)\n",
- other->name,
- i915_reset_engine_count(global, other) -
- threads[tmp].resets);
- if (!err)
- err = -EINVAL;
+ /* GuC based resets are not logged per engine */
+ if (!using_guc) {
+ if (other->uabi_class != engine->uabi_class &&
+ threads[tmp].resets !=
+ i915_reset_engine_count(global, other)) {
+ pr_err("Innocent engine %s was reset (count=%ld)\n",
+ other->name,
+ i915_reset_engine_count(global, other) -
+ threads[tmp].resets);
+ if (!err)
+ err = -EINVAL;
+ }
}
}
@@ -1101,8 +1225,10 @@ unwind:
break;
err = igt_flush_test(gt->i915);
- if (err)
+ if (err) {
+ pr_err("[%s] Flush failed: %d!\n", engine->name, err);
break;
+ }
}
if (intel_gt_is_wedged(gt))
@@ -1180,12 +1306,15 @@ static int igt_reset_wait(void *arg)
igt_global_reset_lock(gt);
err = hang_init(&h, gt);
- if (err)
+ if (err) {
+ pr_err("[%s] Hang init failed: %d!\n", engine->name, err);
goto unlock;
+ }
rq = hang_create_request(&h, engine);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
+ pr_err("[%s] Create hang request failed: %d!\n", engine->name, err);
goto fini;
}
@@ -1310,12 +1439,15 @@ static int __igt_reset_evict_vma(struct intel_gt *gt,
/* Check that we can recover an unbind stuck on a hanging request */
err = hang_init(&h, gt);
- if (err)
+ if (err) {
+ pr_err("[%s] Hang init failed: %d!\n", engine->name, err);
return err;
+ }
obj = i915_gem_object_create_internal(gt->i915, SZ_1M);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
+ pr_err("[%s] Create object failed: %d!\n", engine->name, err);
goto fini;
}
@@ -1330,12 +1462,14 @@ static int __igt_reset_evict_vma(struct intel_gt *gt,
arg.vma = i915_vma_instance(obj, vm, NULL);
if (IS_ERR(arg.vma)) {
err = PTR_ERR(arg.vma);
+ pr_err("[%s] VMA instance failed: %d!\n", engine->name, err);
goto out_obj;
}
rq = hang_create_request(&h, engine);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
+ pr_err("[%s] Create hang request failed: %d!\n", engine->name, err);
goto out_obj;
}
@@ -1347,6 +1481,7 @@ static int __igt_reset_evict_vma(struct intel_gt *gt,
err = i915_vma_pin(arg.vma, 0, 0, pin_flags);
if (err) {
i915_request_add(rq);
+ pr_err("[%s] VMA pin failed: %d!\n", engine->name, err);
goto out_obj;
}
@@ -1363,8 +1498,14 @@ static int __igt_reset_evict_vma(struct intel_gt *gt,
i915_vma_lock(arg.vma);
err = i915_request_await_object(rq, arg.vma->obj,
flags & EXEC_OBJECT_WRITE);
- if (err == 0)
+ if (err == 0) {
err = i915_vma_move_to_active(arg.vma, rq, flags);
+ if (err)
+ pr_err("[%s] Move to active failed: %d!\n", engine->name, err);
+ } else {
+ pr_err("[%s] Request await failed: %d!\n", engine->name, err);
+ }
+
i915_vma_unlock(arg.vma);
if (flags & EXEC_OBJECT_NEEDS_FENCE)
@@ -1392,6 +1533,7 @@ static int __igt_reset_evict_vma(struct intel_gt *gt,
tsk = kthread_run(fn, &arg, "igt/evict_vma");
if (IS_ERR(tsk)) {
err = PTR_ERR(tsk);
+ pr_err("[%s] Thread spawn failed: %d!\n", engine->name, err);
tsk = NULL;
goto out_reset;
}
@@ -1508,17 +1650,29 @@ static int igt_reset_queue(void *arg)
goto unlock;
for_each_engine(engine, gt, id) {
+ struct intel_selftest_saved_policy saved;
struct i915_request *prev;
IGT_TIMEOUT(end_time);
unsigned int count;
+ bool using_guc = intel_engine_uses_guc(engine);
if (!intel_engine_can_store_dword(engine))
continue;
+ if (using_guc) {
+ err = intel_selftest_modify_policy(engine, &saved,
+ SELFTEST_SCHEDULER_MODIFY_NO_HANGCHECK);
+ if (err) {
+ pr_err("[%s] Modify policy failed: %d!\n", engine->name, err);
+ goto fini;
+ }
+ }
+
prev = hang_create_request(&h, engine);
if (IS_ERR(prev)) {
err = PTR_ERR(prev);
- goto fini;
+ pr_err("[%s] Create 'prev' hang request failed: %d!\n", engine->name, err);
+ goto restore;
}
i915_request_get(prev);
@@ -1532,7 +1686,8 @@ static int igt_reset_queue(void *arg)
rq = hang_create_request(&h, engine);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
- goto fini;
+ pr_err("[%s] Create hang request failed: %d!\n", engine->name, err);
+ goto restore;
}
i915_request_get(rq);
@@ -1557,7 +1712,7 @@ static int igt_reset_queue(void *arg)
GEM_TRACE_DUMP();
intel_gt_set_wedged(gt);
- goto fini;
+ goto restore;
}
if (!wait_until_running(&h, prev)) {
@@ -1575,7 +1730,7 @@ static int igt_reset_queue(void *arg)
intel_gt_set_wedged(gt);
err = -EIO;
- goto fini;
+ goto restore;
}
reset_count = fake_hangcheck(gt, BIT(id));
@@ -1586,7 +1741,7 @@ static int igt_reset_queue(void *arg)
i915_request_put(rq);
i915_request_put(prev);
err = -EINVAL;
- goto fini;
+ goto restore;
}
if (rq->fence.error) {
@@ -1595,7 +1750,7 @@ static int igt_reset_queue(void *arg)
i915_request_put(rq);
i915_request_put(prev);
err = -EINVAL;
- goto fini;
+ goto restore;
}
if (i915_reset_count(global) == reset_count) {
@@ -1603,7 +1758,7 @@ static int igt_reset_queue(void *arg)
i915_request_put(rq);
i915_request_put(prev);
err = -EINVAL;
- goto fini;
+ goto restore;
}
i915_request_put(prev);
@@ -1618,9 +1773,24 @@ static int igt_reset_queue(void *arg)
i915_request_put(prev);
- err = igt_flush_test(gt->i915);
+restore:
+ if (using_guc) {
+ int err2 = intel_selftest_restore_policy(engine, &saved);
+
+ if (err2)
+ pr_err("%s:%d> [%s] Restore policy failed: %d!\n",
+ __func__, __LINE__, engine->name, err2);
+ if (err == 0)
+ err = err2;
+ }
if (err)
+ goto fini;
+
+ err = igt_flush_test(gt->i915);
+ if (err) {
+ pr_err("[%s] Flush failed: %d!\n", engine->name, err);
break;
+ }
}
fini:
@@ -1653,12 +1823,15 @@ static int igt_handle_error(void *arg)
return 0;
err = hang_init(&h, gt);
- if (err)
+ if (err) {
+ pr_err("[%s] Hang init failed: %d!\n", engine->name, err);
return err;
+ }
rq = hang_create_request(&h, engine);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
+ pr_err("[%s] Create hang request failed: %d!\n", engine->name, err);
goto err_fini;
}
@@ -1702,7 +1875,7 @@ static int __igt_atomic_reset_engine(struct intel_engine_cs *engine,
const struct igt_atomic_section *p,
const char *mode)
{
- struct tasklet_struct * const t = &engine->execlists.tasklet;
+ struct tasklet_struct * const t = &engine->sched_engine->tasklet;
int err;
GEM_TRACE("i915_reset_engine(%s:%s) under %s\n",
@@ -1743,12 +1916,15 @@ static int igt_atomic_reset_engine(struct intel_engine_cs *engine,
return err;
err = hang_init(&h, engine->gt);
- if (err)
+ if (err) {
+ pr_err("[%s] Hang init failed: %d!\n", engine->name, err);
return err;
+ }
rq = hang_create_request(&h, engine);
if (IS_ERR(rq)) {
err = PTR_ERR(rq);
+ pr_err("[%s] Create hang request failed: %d!\n", engine->name, err);
goto out;
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c
index 3119016d9910..b0977a3b699b 100644
--- a/drivers/gpu/drm/i915/gt/selftest_lrc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c
@@ -49,7 +49,7 @@ static int wait_for_submit(struct intel_engine_cs *engine,
unsigned long timeout)
{
/* Ignore our own attempts to suppress excess tasklets */
- tasklet_hi_schedule(&engine->execlists.tasklet);
+ tasklet_hi_schedule(&engine->sched_engine->tasklet);
timeout += jiffies;
do {
@@ -1613,12 +1613,12 @@ static void garbage_reset(struct intel_engine_cs *engine,
local_bh_disable();
if (!test_and_set_bit(bit, lock)) {
- tasklet_disable(&engine->execlists.tasklet);
+ tasklet_disable(&engine->sched_engine->tasklet);
if (!rq->fence.error)
__intel_engine_reset_bh(engine, NULL);
- tasklet_enable(&engine->execlists.tasklet);
+ tasklet_enable(&engine->sched_engine->tasklet);
clear_and_wake_up_bit(bit, lock);
}
local_bh_enable();
diff --git a/drivers/gpu/drm/i915/gt/selftest_migrate.c b/drivers/gpu/drm/i915/gt/selftest_migrate.c
new file mode 100644
index 000000000000..12ef2837c89b
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/selftest_migrate.c
@@ -0,0 +1,669 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <linux/sort.h>
+
+#include "selftests/i915_random.h"
+
+static const unsigned int sizes[] = {
+ SZ_4K,
+ SZ_64K,
+ SZ_2M,
+ CHUNK_SZ - SZ_4K,
+ CHUNK_SZ,
+ CHUNK_SZ + SZ_4K,
+ SZ_64M,
+};
+
+static struct drm_i915_gem_object *
+create_lmem_or_internal(struct drm_i915_private *i915, size_t size)
+{
+ struct drm_i915_gem_object *obj;
+
+ obj = i915_gem_object_create_lmem(i915, size, 0);
+ if (!IS_ERR(obj))
+ return obj;
+
+ return i915_gem_object_create_internal(i915, size);
+}
+
+static int copy(struct intel_migrate *migrate,
+ int (*fn)(struct intel_migrate *migrate,
+ struct i915_gem_ww_ctx *ww,
+ struct drm_i915_gem_object *src,
+ struct drm_i915_gem_object *dst,
+ struct i915_request **out),
+ u32 sz, struct rnd_state *prng)
+{
+ struct drm_i915_private *i915 = migrate->context->engine->i915;
+ struct drm_i915_gem_object *src, *dst;
+ struct i915_request *rq;
+ struct i915_gem_ww_ctx ww;
+ u32 *vaddr;
+ int err = 0;
+ int i;
+
+ src = create_lmem_or_internal(i915, sz);
+ if (IS_ERR(src))
+ return 0;
+
+ dst = i915_gem_object_create_internal(i915, sz);
+ if (IS_ERR(dst))
+ goto err_free_src;
+
+ for_i915_gem_ww(&ww, err, true) {
+ err = i915_gem_object_lock(src, &ww);
+ if (err)
+ continue;
+
+ err = i915_gem_object_lock(dst, &ww);
+ if (err)
+ continue;
+
+ vaddr = i915_gem_object_pin_map(src, I915_MAP_WC);
+ if (IS_ERR(vaddr)) {
+ err = PTR_ERR(vaddr);
+ continue;
+ }
+
+ for (i = 0; i < sz / sizeof(u32); i++)
+ vaddr[i] = i;
+ i915_gem_object_flush_map(src);
+
+ vaddr = i915_gem_object_pin_map(dst, I915_MAP_WC);
+ if (IS_ERR(vaddr)) {
+ err = PTR_ERR(vaddr);
+ goto unpin_src;
+ }
+
+ for (i = 0; i < sz / sizeof(u32); i++)
+ vaddr[i] = ~i;
+ i915_gem_object_flush_map(dst);
+
+ err = fn(migrate, &ww, src, dst, &rq);
+ if (!err)
+ continue;
+
+ if (err != -EDEADLK && err != -EINTR && err != -ERESTARTSYS)
+ pr_err("%ps failed, size: %u\n", fn, sz);
+ if (rq) {
+ i915_request_wait(rq, 0, HZ);
+ i915_request_put(rq);
+ }
+ i915_gem_object_unpin_map(dst);
+unpin_src:
+ i915_gem_object_unpin_map(src);
+ }
+ if (err)
+ goto err_out;
+
+ if (rq) {
+ if (i915_request_wait(rq, 0, HZ) < 0) {
+ pr_err("%ps timed out, size: %u\n", fn, sz);
+ err = -ETIME;
+ }
+ i915_request_put(rq);
+ }
+
+ for (i = 0; !err && i < sz / PAGE_SIZE; i++) {
+ int x = i * 1024 + i915_prandom_u32_max_state(1024, prng);
+
+ if (vaddr[x] != x) {
+ pr_err("%ps failed, size: %u, offset: %zu\n",
+ fn, sz, x * sizeof(u32));
+ igt_hexdump(vaddr + i * 1024, 4096);
+ err = -EINVAL;
+ }
+ }
+
+ i915_gem_object_unpin_map(dst);
+ i915_gem_object_unpin_map(src);
+
+err_out:
+ i915_gem_object_put(dst);
+err_free_src:
+ i915_gem_object_put(src);
+
+ return err;
+}
+
+static int clear(struct intel_migrate *migrate,
+ int (*fn)(struct intel_migrate *migrate,
+ struct i915_gem_ww_ctx *ww,
+ struct drm_i915_gem_object *obj,
+ u32 value,
+ struct i915_request **out),
+ u32 sz, struct rnd_state *prng)
+{
+ struct drm_i915_private *i915 = migrate->context->engine->i915;
+ struct drm_i915_gem_object *obj;
+ struct i915_request *rq;
+ struct i915_gem_ww_ctx ww;
+ u32 *vaddr;
+ int err = 0;
+ int i;
+
+ obj = create_lmem_or_internal(i915, sz);
+ if (IS_ERR(obj))
+ return 0;
+
+ for_i915_gem_ww(&ww, err, true) {
+ err = i915_gem_object_lock(obj, &ww);
+ if (err)
+ continue;
+
+ vaddr = i915_gem_object_pin_map(obj, I915_MAP_WC);
+ if (IS_ERR(vaddr)) {
+ err = PTR_ERR(vaddr);
+ continue;
+ }
+
+ for (i = 0; i < sz / sizeof(u32); i++)
+ vaddr[i] = ~i;
+ i915_gem_object_flush_map(obj);
+
+ err = fn(migrate, &ww, obj, sz, &rq);
+ if (!err)
+ continue;
+
+ if (err != -EDEADLK && err != -EINTR && err != -ERESTARTSYS)
+ pr_err("%ps failed, size: %u\n", fn, sz);
+ if (rq) {
+ i915_request_wait(rq, 0, HZ);
+ i915_request_put(rq);
+ }
+ i915_gem_object_unpin_map(obj);
+ }
+ if (err)
+ goto err_out;
+
+ if (rq) {
+ if (i915_request_wait(rq, 0, HZ) < 0) {
+ pr_err("%ps timed out, size: %u\n", fn, sz);
+ err = -ETIME;
+ }
+ i915_request_put(rq);
+ }
+
+ for (i = 0; !err && i < sz / PAGE_SIZE; i++) {
+ int x = i * 1024 + i915_prandom_u32_max_state(1024, prng);
+
+ if (vaddr[x] != sz) {
+ pr_err("%ps failed, size: %u, offset: %zu\n",
+ fn, sz, x * sizeof(u32));
+ igt_hexdump(vaddr + i * 1024, 4096);
+ err = -EINVAL;
+ }
+ }
+
+ i915_gem_object_unpin_map(obj);
+err_out:
+ i915_gem_object_put(obj);
+
+ return err;
+}
+
+static int __migrate_copy(struct intel_migrate *migrate,
+ struct i915_gem_ww_ctx *ww,
+ struct drm_i915_gem_object *src,
+ struct drm_i915_gem_object *dst,
+ struct i915_request **out)
+{
+ return intel_migrate_copy(migrate, ww, NULL,
+ src->mm.pages->sgl, src->cache_level,
+ i915_gem_object_is_lmem(src),
+ dst->mm.pages->sgl, dst->cache_level,
+ i915_gem_object_is_lmem(dst),
+ out);
+}
+
+static int __global_copy(struct intel_migrate *migrate,
+ struct i915_gem_ww_ctx *ww,
+ struct drm_i915_gem_object *src,
+ struct drm_i915_gem_object *dst,
+ struct i915_request **out)
+{
+ return intel_context_migrate_copy(migrate->context, NULL,
+ src->mm.pages->sgl, src->cache_level,
+ i915_gem_object_is_lmem(src),
+ dst->mm.pages->sgl, dst->cache_level,
+ i915_gem_object_is_lmem(dst),
+ out);
+}
+
+static int
+migrate_copy(struct intel_migrate *migrate, u32 sz, struct rnd_state *prng)
+{
+ return copy(migrate, __migrate_copy, sz, prng);
+}
+
+static int
+global_copy(struct intel_migrate *migrate, u32 sz, struct rnd_state *prng)
+{
+ return copy(migrate, __global_copy, sz, prng);
+}
+
+static int __migrate_clear(struct intel_migrate *migrate,
+ struct i915_gem_ww_ctx *ww,
+ struct drm_i915_gem_object *obj,
+ u32 value,
+ struct i915_request **out)
+{
+ return intel_migrate_clear(migrate, ww, NULL,
+ obj->mm.pages->sgl,
+ obj->cache_level,
+ i915_gem_object_is_lmem(obj),
+ value, out);
+}
+
+static int __global_clear(struct intel_migrate *migrate,
+ struct i915_gem_ww_ctx *ww,
+ struct drm_i915_gem_object *obj,
+ u32 value,
+ struct i915_request **out)
+{
+ return intel_context_migrate_clear(migrate->context, NULL,
+ obj->mm.pages->sgl,
+ obj->cache_level,
+ i915_gem_object_is_lmem(obj),
+ value, out);
+}
+
+static int
+migrate_clear(struct intel_migrate *migrate, u32 sz, struct rnd_state *prng)
+{
+ return clear(migrate, __migrate_clear, sz, prng);
+}
+
+static int
+global_clear(struct intel_migrate *migrate, u32 sz, struct rnd_state *prng)
+{
+ return clear(migrate, __global_clear, sz, prng);
+}
+
+static int live_migrate_copy(void *arg)
+{
+ struct intel_migrate *migrate = arg;
+ struct drm_i915_private *i915 = migrate->context->engine->i915;
+ I915_RND_STATE(prng);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sizes); i++) {
+ int err;
+
+ err = migrate_copy(migrate, sizes[i], &prng);
+ if (err == 0)
+ err = global_copy(migrate, sizes[i], &prng);
+ i915_gem_drain_freed_objects(i915);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int live_migrate_clear(void *arg)
+{
+ struct intel_migrate *migrate = arg;
+ struct drm_i915_private *i915 = migrate->context->engine->i915;
+ I915_RND_STATE(prng);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sizes); i++) {
+ int err;
+
+ err = migrate_clear(migrate, sizes[i], &prng);
+ if (err == 0)
+ err = global_clear(migrate, sizes[i], &prng);
+
+ i915_gem_drain_freed_objects(i915);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+struct threaded_migrate {
+ struct intel_migrate *migrate;
+ struct task_struct *tsk;
+ struct rnd_state prng;
+};
+
+static int threaded_migrate(struct intel_migrate *migrate,
+ int (*fn)(void *arg),
+ unsigned int flags)
+{
+ const unsigned int n_cpus = num_online_cpus() + 1;
+ struct threaded_migrate *thread;
+ I915_RND_STATE(prng);
+ unsigned int i;
+ int err = 0;
+
+ thread = kcalloc(n_cpus, sizeof(*thread), GFP_KERNEL);
+ if (!thread)
+ return 0;
+
+ for (i = 0; i < n_cpus; ++i) {
+ struct task_struct *tsk;
+
+ thread[i].migrate = migrate;
+ thread[i].prng =
+ I915_RND_STATE_INITIALIZER(prandom_u32_state(&prng));
+
+ tsk = kthread_run(fn, &thread[i], "igt-%d", i);
+ if (IS_ERR(tsk)) {
+ err = PTR_ERR(tsk);
+ break;
+ }
+
+ get_task_struct(tsk);
+ thread[i].tsk = tsk;
+ }
+
+ msleep(10); /* start all threads before we kthread_stop() */
+
+ for (i = 0; i < n_cpus; ++i) {
+ struct task_struct *tsk = thread[i].tsk;
+ int status;
+
+ if (IS_ERR_OR_NULL(tsk))
+ continue;
+
+ status = kthread_stop(tsk);
+ if (status && !err)
+ err = status;
+
+ put_task_struct(tsk);
+ }
+
+ kfree(thread);
+ return err;
+}
+
+static int __thread_migrate_copy(void *arg)
+{
+ struct threaded_migrate *tm = arg;
+
+ return migrate_copy(tm->migrate, 2 * CHUNK_SZ, &tm->prng);
+}
+
+static int thread_migrate_copy(void *arg)
+{
+ return threaded_migrate(arg, __thread_migrate_copy, 0);
+}
+
+static int __thread_global_copy(void *arg)
+{
+ struct threaded_migrate *tm = arg;
+
+ return global_copy(tm->migrate, 2 * CHUNK_SZ, &tm->prng);
+}
+
+static int thread_global_copy(void *arg)
+{
+ return threaded_migrate(arg, __thread_global_copy, 0);
+}
+
+static int __thread_migrate_clear(void *arg)
+{
+ struct threaded_migrate *tm = arg;
+
+ return migrate_clear(tm->migrate, 2 * CHUNK_SZ, &tm->prng);
+}
+
+static int __thread_global_clear(void *arg)
+{
+ struct threaded_migrate *tm = arg;
+
+ return global_clear(tm->migrate, 2 * CHUNK_SZ, &tm->prng);
+}
+
+static int thread_migrate_clear(void *arg)
+{
+ return threaded_migrate(arg, __thread_migrate_clear, 0);
+}
+
+static int thread_global_clear(void *arg)
+{
+ return threaded_migrate(arg, __thread_global_clear, 0);
+}
+
+int intel_migrate_live_selftests(struct drm_i915_private *i915)
+{
+ static const struct i915_subtest tests[] = {
+ SUBTEST(live_migrate_copy),
+ SUBTEST(live_migrate_clear),
+ SUBTEST(thread_migrate_copy),
+ SUBTEST(thread_migrate_clear),
+ SUBTEST(thread_global_copy),
+ SUBTEST(thread_global_clear),
+ };
+ struct intel_gt *gt = &i915->gt;
+
+ if (!gt->migrate.context)
+ return 0;
+
+ return i915_subtests(tests, &gt->migrate);
+}
+
+static struct drm_i915_gem_object *
+create_init_lmem_internal(struct intel_gt *gt, size_t sz, bool try_lmem)
+{
+ struct drm_i915_gem_object *obj = NULL;
+ int err;
+
+ if (try_lmem)
+ obj = i915_gem_object_create_lmem(gt->i915, sz, 0);
+
+ if (IS_ERR_OR_NULL(obj)) {
+ obj = i915_gem_object_create_internal(gt->i915, sz);
+ if (IS_ERR(obj))
+ return obj;
+ }
+
+ i915_gem_object_trylock(obj);
+ err = i915_gem_object_pin_pages(obj);
+ if (err) {
+ i915_gem_object_unlock(obj);
+ i915_gem_object_put(obj);
+ return ERR_PTR(err);
+ }
+
+ return obj;
+}
+
+static int wrap_ktime_compare(const void *A, const void *B)
+{
+ const ktime_t *a = A, *b = B;
+
+ return ktime_compare(*a, *b);
+}
+
+static int __perf_clear_blt(struct intel_context *ce,
+ struct scatterlist *sg,
+ enum i915_cache_level cache_level,
+ bool is_lmem,
+ size_t sz)
+{
+ ktime_t t[5];
+ int pass;
+ int err = 0;
+
+ for (pass = 0; pass < ARRAY_SIZE(t); pass++) {
+ struct i915_request *rq;
+ ktime_t t0, t1;
+
+ t0 = ktime_get();
+
+ err = intel_context_migrate_clear(ce, NULL, sg, cache_level,
+ is_lmem, 0, &rq);
+ if (rq) {
+ if (i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT) < 0)
+ err = -EIO;
+ i915_request_put(rq);
+ }
+ if (err)
+ break;
+
+ t1 = ktime_get();
+ t[pass] = ktime_sub(t1, t0);
+ }
+ if (err)
+ return err;
+
+ sort(t, ARRAY_SIZE(t), sizeof(*t), wrap_ktime_compare, NULL);
+ pr_info("%s: %zd KiB fill: %lld MiB/s\n",
+ ce->engine->name, sz >> 10,
+ div64_u64(mul_u32_u32(4 * sz,
+ 1000 * 1000 * 1000),
+ t[1] + 2 * t[2] + t[3]) >> 20);
+ return 0;
+}
+
+static int perf_clear_blt(void *arg)
+{
+ struct intel_gt *gt = arg;
+ static const unsigned long sizes[] = {
+ SZ_4K,
+ SZ_64K,
+ SZ_2M,
+ SZ_64M
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sizes); i++) {
+ struct drm_i915_gem_object *dst;
+ int err;
+
+ dst = create_init_lmem_internal(gt, sizes[i], true);
+ if (IS_ERR(dst))
+ return PTR_ERR(dst);
+
+ err = __perf_clear_blt(gt->migrate.context,
+ dst->mm.pages->sgl,
+ I915_CACHE_NONE,
+ i915_gem_object_is_lmem(dst),
+ sizes[i]);
+
+ i915_gem_object_unlock(dst);
+ i915_gem_object_put(dst);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int __perf_copy_blt(struct intel_context *ce,
+ struct scatterlist *src,
+ enum i915_cache_level src_cache_level,
+ bool src_is_lmem,
+ struct scatterlist *dst,
+ enum i915_cache_level dst_cache_level,
+ bool dst_is_lmem,
+ size_t sz)
+{
+ ktime_t t[5];
+ int pass;
+ int err = 0;
+
+ for (pass = 0; pass < ARRAY_SIZE(t); pass++) {
+ struct i915_request *rq;
+ ktime_t t0, t1;
+
+ t0 = ktime_get();
+
+ err = intel_context_migrate_copy(ce, NULL,
+ src, src_cache_level,
+ src_is_lmem,
+ dst, dst_cache_level,
+ dst_is_lmem,
+ &rq);
+ if (rq) {
+ if (i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT) < 0)
+ err = -EIO;
+ i915_request_put(rq);
+ }
+ if (err)
+ break;
+
+ t1 = ktime_get();
+ t[pass] = ktime_sub(t1, t0);
+ }
+ if (err)
+ return err;
+
+ sort(t, ARRAY_SIZE(t), sizeof(*t), wrap_ktime_compare, NULL);
+ pr_info("%s: %zd KiB copy: %lld MiB/s\n",
+ ce->engine->name, sz >> 10,
+ div64_u64(mul_u32_u32(4 * sz,
+ 1000 * 1000 * 1000),
+ t[1] + 2 * t[2] + t[3]) >> 20);
+ return 0;
+}
+
+static int perf_copy_blt(void *arg)
+{
+ struct intel_gt *gt = arg;
+ static const unsigned long sizes[] = {
+ SZ_4K,
+ SZ_64K,
+ SZ_2M,
+ SZ_64M
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sizes); i++) {
+ struct drm_i915_gem_object *src, *dst;
+ int err;
+
+ src = create_init_lmem_internal(gt, sizes[i], true);
+ if (IS_ERR(src))
+ return PTR_ERR(src);
+
+ dst = create_init_lmem_internal(gt, sizes[i], false);
+ if (IS_ERR(dst)) {
+ err = PTR_ERR(dst);
+ goto err_src;
+ }
+
+ err = __perf_copy_blt(gt->migrate.context,
+ src->mm.pages->sgl,
+ I915_CACHE_NONE,
+ i915_gem_object_is_lmem(src),
+ dst->mm.pages->sgl,
+ I915_CACHE_NONE,
+ i915_gem_object_is_lmem(dst),
+ sizes[i]);
+
+ i915_gem_object_unlock(dst);
+ i915_gem_object_put(dst);
+err_src:
+ i915_gem_object_unlock(src);
+ i915_gem_object_put(src);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int intel_migrate_perf_selftests(struct drm_i915_private *i915)
+{
+ static const struct i915_subtest tests[] = {
+ SUBTEST(perf_clear_blt),
+ SUBTEST(perf_copy_blt),
+ };
+ struct intel_gt *gt = &i915->gt;
+
+ if (intel_gt_is_wedged(gt))
+ return 0;
+
+ if (!gt->migrate.context)
+ return 0;
+
+ return intel_gt_live_subtests(tests, gt);
+}
diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c
index b9bb0e6e97f7..13d25bf2a94a 100644
--- a/drivers/gpu/drm/i915/gt/selftest_mocs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c
@@ -10,6 +10,7 @@
#include "gem/selftests/mock_context.h"
#include "selftests/igt_reset.h"
#include "selftests/igt_spinner.h"
+#include "selftests/intel_scheduler_helpers.h"
struct live_mocs {
struct drm_i915_mocs_table table;
@@ -28,7 +29,7 @@ static struct intel_context *mocs_context_create(struct intel_engine_cs *engine)
return ce;
/* We build large requests to read the registers from the ring */
- ce->ring = __intel_context_ring_size(SZ_16K);
+ ce->ring_size = SZ_16K;
return ce;
}
@@ -318,7 +319,8 @@ static int live_mocs_clean(void *arg)
}
static int active_engine_reset(struct intel_context *ce,
- const char *reason)
+ const char *reason,
+ bool using_guc)
{
struct igt_spinner spin;
struct i915_request *rq;
@@ -335,9 +337,13 @@ static int active_engine_reset(struct intel_context *ce,
}
err = request_add_spin(rq, &spin);
- if (err == 0)
+ if (err == 0 && !using_guc)
err = intel_engine_reset(ce->engine, reason);
+ /* Ensure the reset happens and kills the engine */
+ if (err == 0)
+ err = intel_selftest_wait_for_rq(rq);
+
igt_spinner_end(&spin);
igt_spinner_fini(&spin);
@@ -345,21 +351,23 @@ static int active_engine_reset(struct intel_context *ce,
}
static int __live_mocs_reset(struct live_mocs *mocs,
- struct intel_context *ce)
+ struct intel_context *ce, bool using_guc)
{
struct intel_gt *gt = ce->engine->gt;
int err;
if (intel_has_reset_engine(gt)) {
- err = intel_engine_reset(ce->engine, "mocs");
- if (err)
- return err;
-
- err = check_mocs_engine(mocs, ce);
- if (err)
- return err;
+ if (!using_guc) {
+ err = intel_engine_reset(ce->engine, "mocs");
+ if (err)
+ return err;
+
+ err = check_mocs_engine(mocs, ce);
+ if (err)
+ return err;
+ }
- err = active_engine_reset(ce, "mocs");
+ err = active_engine_reset(ce, "mocs", using_guc);
if (err)
return err;
@@ -395,19 +403,33 @@ static int live_mocs_reset(void *arg)
igt_global_reset_lock(gt);
for_each_engine(engine, gt, id) {
+ bool using_guc = intel_engine_uses_guc(engine);
+ struct intel_selftest_saved_policy saved;
struct intel_context *ce;
+ int err2;
+
+ err = intel_selftest_modify_policy(engine, &saved,
+ SELFTEST_SCHEDULER_MODIFY_FAST_RESET);
+ if (err)
+ break;
ce = mocs_context_create(engine);
if (IS_ERR(ce)) {
err = PTR_ERR(ce);
- break;
+ goto restore;
}
intel_engine_pm_get(engine);
- err = __live_mocs_reset(&mocs, ce);
- intel_engine_pm_put(engine);
+ err = __live_mocs_reset(&mocs, ce, using_guc);
+
+ intel_engine_pm_put(engine);
intel_context_put(ce);
+
+restore:
+ err2 = intel_selftest_restore_policy(engine, &saved);
+ if (err == 0)
+ err = err2;
if (err)
break;
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c
index 8784257ec808..7a50c9f4071b 100644
--- a/drivers/gpu/drm/i915/gt/selftest_reset.c
+++ b/drivers/gpu/drm/i915/gt/selftest_reset.c
@@ -321,7 +321,7 @@ static int igt_atomic_engine_reset(void *arg)
goto out_unlock;
for_each_engine(engine, gt, id) {
- struct tasklet_struct *t = &engine->execlists.tasklet;
+ struct tasklet_struct *t = &engine->sched_engine->tasklet;
if (t->func)
tasklet_disable(t);
diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
new file mode 100644
index 000000000000..9334bad131a2
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#define NUM_STEPS 5
+#define H2G_DELAY 50000
+#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 10000)
+#define FREQUENCY_REQ_UNIT DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, \
+ GEN9_FREQ_SCALER)
+
+static int slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 freq)
+{
+ int ret;
+
+ ret = intel_guc_slpc_set_min_freq(slpc, freq);
+ if (ret)
+ pr_err("Could not set min frequency to [%u]\n", freq);
+ else /* Delay to ensure h2g completes */
+ delay_for_h2g();
+
+ return ret;
+}
+
+static int slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 freq)
+{
+ int ret;
+
+ ret = intel_guc_slpc_set_max_freq(slpc, freq);
+ if (ret)
+ pr_err("Could not set maximum frequency [%u]\n",
+ freq);
+ else /* Delay to ensure h2g completes */
+ delay_for_h2g();
+
+ return ret;
+}
+
+static int live_slpc_clamp_min(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_gt *gt = &i915->gt;
+ struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
+ struct intel_rps *rps = &gt->rps;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+ struct igt_spinner spin;
+ u32 slpc_min_freq, slpc_max_freq;
+ int err = 0;
+
+ if (!intel_uc_uses_guc_slpc(&gt->uc))
+ return 0;
+
+ if (igt_spinner_init(&spin, gt))
+ return -ENOMEM;
+
+ if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
+ pr_err("Could not get SLPC max freq\n");
+ return -EIO;
+ }
+
+ if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
+ pr_err("Could not get SLPC min freq\n");
+ return -EIO;
+ }
+
+ if (slpc_min_freq == slpc_max_freq) {
+ pr_err("Min/Max are fused to the same value\n");
+ return -EINVAL;
+ }
+
+ intel_gt_pm_wait_for_idle(gt);
+ intel_gt_pm_get(gt);
+ for_each_engine(engine, gt, id) {
+ struct i915_request *rq;
+ u32 step, min_freq, req_freq;
+ u32 act_freq, max_act_freq;
+
+ if (!intel_engine_can_store_dword(engine))
+ continue;
+
+ /* Go from min to max in 5 steps */
+ step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS;
+ max_act_freq = slpc_min_freq;
+ for (min_freq = slpc_min_freq; min_freq < slpc_max_freq;
+ min_freq += step) {
+ err = slpc_set_min_freq(slpc, min_freq);
+ if (err)
+ break;
+
+ st_engine_heartbeat_disable(engine);
+
+ rq = igt_spinner_create_request(&spin,
+ engine->kernel_context,
+ MI_NOOP);
+ if (IS_ERR(rq)) {
+ err = PTR_ERR(rq);
+ st_engine_heartbeat_enable(engine);
+ break;
+ }
+
+ i915_request_add(rq);
+
+ if (!igt_wait_for_spinner(&spin, rq)) {
+ pr_err("%s: Spinner did not start\n",
+ engine->name);
+ igt_spinner_end(&spin);
+ st_engine_heartbeat_enable(engine);
+ intel_gt_set_wedged(engine->gt);
+ err = -EIO;
+ break;
+ }
+
+ /* Wait for GuC to detect business and raise
+ * requested frequency if necessary.
+ */
+ delay_for_h2g();
+
+ req_freq = intel_rps_read_punit_req_frequency(rps);
+
+ /* GuC requests freq in multiples of 50/3 MHz */
+ if (req_freq < (min_freq - FREQUENCY_REQ_UNIT)) {
+ pr_err("SWReq is %d, should be at least %d\n", req_freq,
+ min_freq - FREQUENCY_REQ_UNIT);
+ igt_spinner_end(&spin);
+ st_engine_heartbeat_enable(engine);
+ err = -EINVAL;
+ break;
+ }
+
+ act_freq = intel_rps_read_actual_frequency(rps);
+ if (act_freq > max_act_freq)
+ max_act_freq = act_freq;
+
+ igt_spinner_end(&spin);
+ st_engine_heartbeat_enable(engine);
+ }
+
+ pr_info("Max actual frequency for %s was %d\n",
+ engine->name, max_act_freq);
+
+ /* Actual frequency should rise above min */
+ if (max_act_freq == slpc_min_freq) {
+ pr_err("Actual freq did not rise above min\n");
+ err = -EINVAL;
+ }
+
+ if (err)
+ break;
+ }
+
+ /* Restore min/max frequencies */
+ slpc_set_max_freq(slpc, slpc_max_freq);
+ slpc_set_min_freq(slpc, slpc_min_freq);
+
+ if (igt_flush_test(gt->i915))
+ err = -EIO;
+
+ intel_gt_pm_put(gt);
+ igt_spinner_fini(&spin);
+ intel_gt_pm_wait_for_idle(gt);
+
+ return err;
+}
+
+static int live_slpc_clamp_max(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_gt *gt = &i915->gt;
+ struct intel_guc_slpc *slpc;
+ struct intel_rps *rps;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+ struct igt_spinner spin;
+ int err = 0;
+ u32 slpc_min_freq, slpc_max_freq;
+
+ slpc = &gt->uc.guc.slpc;
+ rps = &gt->rps;
+
+ if (!intel_uc_uses_guc_slpc(&gt->uc))
+ return 0;
+
+ if (igt_spinner_init(&spin, gt))
+ return -ENOMEM;
+
+ if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
+ pr_err("Could not get SLPC max freq\n");
+ return -EIO;
+ }
+
+ if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
+ pr_err("Could not get SLPC min freq\n");
+ return -EIO;
+ }
+
+ if (slpc_min_freq == slpc_max_freq) {
+ pr_err("Min/Max are fused to the same value\n");
+ return -EINVAL;
+ }
+
+ intel_gt_pm_wait_for_idle(gt);
+ intel_gt_pm_get(gt);
+ for_each_engine(engine, gt, id) {
+ struct i915_request *rq;
+ u32 max_freq, req_freq;
+ u32 act_freq, max_act_freq;
+ u32 step;
+
+ if (!intel_engine_can_store_dword(engine))
+ continue;
+
+ /* Go from max to min in 5 steps */
+ step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS;
+ max_act_freq = slpc_min_freq;
+ for (max_freq = slpc_max_freq; max_freq > slpc_min_freq;
+ max_freq -= step) {
+ err = slpc_set_max_freq(slpc, max_freq);
+ if (err)
+ break;
+
+ st_engine_heartbeat_disable(engine);
+
+ rq = igt_spinner_create_request(&spin,
+ engine->kernel_context,
+ MI_NOOP);
+ if (IS_ERR(rq)) {
+ st_engine_heartbeat_enable(engine);
+ err = PTR_ERR(rq);
+ break;
+ }
+
+ i915_request_add(rq);
+
+ if (!igt_wait_for_spinner(&spin, rq)) {
+ pr_err("%s: SLPC spinner did not start\n",
+ engine->name);
+ igt_spinner_end(&spin);
+ st_engine_heartbeat_enable(engine);
+ intel_gt_set_wedged(engine->gt);
+ err = -EIO;
+ break;
+ }
+
+ delay_for_h2g();
+
+ /* Verify that SWREQ indeed was set to specific value */
+ req_freq = intel_rps_read_punit_req_frequency(rps);
+
+ /* GuC requests freq in multiples of 50/3 MHz */
+ if (req_freq > (max_freq + FREQUENCY_REQ_UNIT)) {
+ pr_err("SWReq is %d, should be at most %d\n", req_freq,
+ max_freq + FREQUENCY_REQ_UNIT);
+ igt_spinner_end(&spin);
+ st_engine_heartbeat_enable(engine);
+ err = -EINVAL;
+ break;
+ }
+
+ act_freq = intel_rps_read_actual_frequency(rps);
+ if (act_freq > max_act_freq)
+ max_act_freq = act_freq;
+
+ st_engine_heartbeat_enable(engine);
+ igt_spinner_end(&spin);
+
+ if (err)
+ break;
+ }
+
+ pr_info("Max actual frequency for %s was %d\n",
+ engine->name, max_act_freq);
+
+ /* Actual frequency should rise above min */
+ if (max_act_freq == slpc_min_freq) {
+ pr_err("Actual freq did not rise above min\n");
+ err = -EINVAL;
+ }
+
+ if (igt_flush_test(gt->i915)) {
+ err = -EIO;
+ break;
+ }
+
+ if (err)
+ break;
+ }
+
+ /* Restore min/max freq */
+ slpc_set_max_freq(slpc, slpc_max_freq);
+ slpc_set_min_freq(slpc, slpc_min_freq);
+
+ intel_gt_pm_put(gt);
+ igt_spinner_fini(&spin);
+ intel_gt_pm_wait_for_idle(gt);
+
+ return err;
+}
+
+int intel_slpc_live_selftests(struct drm_i915_private *i915)
+{
+ static const struct i915_subtest tests[] = {
+ SUBTEST(live_slpc_clamp_max),
+ SUBTEST(live_slpc_clamp_min),
+ };
+
+ if (intel_gt_is_wedged(&i915->gt))
+ return 0;
+
+ return i915_live_subtests(tests, i915);
+}
diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c
index 64da0c91dec1..d0b6a3afcf44 100644
--- a/drivers/gpu/drm/i915/gt/selftest_timeline.c
+++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c
@@ -874,7 +874,7 @@ static int create_watcher(struct hwsp_watcher *w,
if (IS_ERR(ce))
return PTR_ERR(ce);
- ce->ring = __intel_context_ring_size(ringsz);
+ ce->ring_size = ringsz;
w->rq = intel_context_create_request(ce);
intel_context_put(ce);
if (IS_ERR(w->rq))
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index c30754daf4b1..e623ac45f4aa 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -12,6 +12,7 @@
#include "selftests/igt_flush_test.h"
#include "selftests/igt_reset.h"
#include "selftests/igt_spinner.h"
+#include "selftests/intel_scheduler_helpers.h"
#include "selftests/mock_drm.h"
#include "gem/selftests/igt_gem_utils.h"
@@ -261,28 +262,34 @@ static int do_engine_reset(struct intel_engine_cs *engine)
return intel_engine_reset(engine, "live_workarounds");
}
+static int do_guc_reset(struct intel_engine_cs *engine)
+{
+ /* Currently a no-op as the reset is handled by GuC */
+ return 0;
+}
+
static int
switch_to_scratch_context(struct intel_engine_cs *engine,
- struct igt_spinner *spin)
+ struct igt_spinner *spin,
+ struct i915_request **rq)
{
struct intel_context *ce;
- struct i915_request *rq;
int err = 0;
ce = intel_context_create(engine);
if (IS_ERR(ce))
return PTR_ERR(ce);
- rq = igt_spinner_create_request(spin, ce, MI_NOOP);
+ *rq = igt_spinner_create_request(spin, ce, MI_NOOP);
intel_context_put(ce);
- if (IS_ERR(rq)) {
+ if (IS_ERR(*rq)) {
spin = NULL;
- err = PTR_ERR(rq);
+ err = PTR_ERR(*rq);
goto err;
}
- err = request_add_spin(rq, spin);
+ err = request_add_spin(*rq, spin);
err:
if (err && spin)
igt_spinner_end(spin);
@@ -296,6 +303,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
{
struct intel_context *ce, *tmp;
struct igt_spinner spin;
+ struct i915_request *rq;
intel_wakeref_t wakeref;
int err;
@@ -316,13 +324,24 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
goto out_spin;
}
- err = switch_to_scratch_context(engine, &spin);
+ err = switch_to_scratch_context(engine, &spin, &rq);
if (err)
goto out_spin;
+ /* Ensure the spinner hasn't aborted */
+ if (i915_request_completed(rq)) {
+ pr_err("%s spinner failed to start\n", name);
+ err = -ETIMEDOUT;
+ goto out_spin;
+ }
+
with_intel_runtime_pm(engine->uncore->rpm, wakeref)
err = reset(engine);
+ /* Ensure the reset happens and kills the engine */
+ if (err == 0)
+ err = intel_selftest_wait_for_rq(rq);
+
igt_spinner_end(&spin);
if (err) {
@@ -787,9 +806,28 @@ static int live_reset_whitelist(void *arg)
continue;
if (intel_has_reset_engine(gt)) {
- err = check_whitelist_across_reset(engine,
- do_engine_reset,
- "engine");
+ if (intel_engine_uses_guc(engine)) {
+ struct intel_selftest_saved_policy saved;
+ int err2;
+
+ err = intel_selftest_modify_policy(engine, &saved,
+ SELFTEST_SCHEDULER_MODIFY_FAST_RESET);
+ if (err)
+ goto out;
+
+ err = check_whitelist_across_reset(engine,
+ do_guc_reset,
+ "guc");
+
+ err2 = intel_selftest_restore_policy(engine, &saved);
+ if (err == 0)
+ err = err2;
+ } else {
+ err = check_whitelist_across_reset(engine,
+ do_engine_reset,
+ "engine");
+ }
+
if (err)
goto out;
}
@@ -1147,7 +1185,7 @@ verify_wa_lists(struct intel_gt *gt, struct wa_lists *lists,
enum intel_engine_id id;
bool ok = true;
- ok &= wa_list_verify(gt->uncore, &lists->gt_wa_list, str);
+ ok &= wa_list_verify(gt, &lists->gt_wa_list, str);
for_each_engine(engine, gt, id) {
struct intel_context *ce;
@@ -1175,31 +1213,36 @@ live_gpu_reset_workarounds(void *arg)
{
struct intel_gt *gt = arg;
intel_wakeref_t wakeref;
- struct wa_lists lists;
+ struct wa_lists *lists;
bool ok;
if (!intel_has_gpu_reset(gt))
return 0;
+ lists = kzalloc(sizeof(*lists), GFP_KERNEL);
+ if (!lists)
+ return -ENOMEM;
+
pr_info("Verifying after GPU reset...\n");
igt_global_reset_lock(gt);
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
- reference_lists_init(gt, &lists);
+ reference_lists_init(gt, lists);
- ok = verify_wa_lists(gt, &lists, "before reset");
+ ok = verify_wa_lists(gt, lists, "before reset");
if (!ok)
goto out;
intel_gt_reset(gt, ALL_ENGINES, "live_workarounds");
- ok = verify_wa_lists(gt, &lists, "after reset");
+ ok = verify_wa_lists(gt, lists, "after reset");
out:
- reference_lists_fini(gt, &lists);
+ reference_lists_fini(gt, lists);
intel_runtime_pm_put(gt->uncore->rpm, wakeref);
igt_global_reset_unlock(gt);
+ kfree(lists);
return ok ? 0 : -ESRCH;
}
@@ -1214,43 +1257,57 @@ live_engine_reset_workarounds(void *arg)
struct igt_spinner spin;
struct i915_request *rq;
intel_wakeref_t wakeref;
- struct wa_lists lists;
+ struct wa_lists *lists;
int ret = 0;
if (!intel_has_reset_engine(gt))
return 0;
+ lists = kzalloc(sizeof(*lists), GFP_KERNEL);
+ if (!lists)
+ return -ENOMEM;
+
igt_global_reset_lock(gt);
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
- reference_lists_init(gt, &lists);
+ reference_lists_init(gt, lists);
for_each_engine(engine, gt, id) {
+ struct intel_selftest_saved_policy saved;
+ bool using_guc = intel_engine_uses_guc(engine);
bool ok;
+ int ret2;
pr_info("Verifying after %s reset...\n", engine->name);
+ ret = intel_selftest_modify_policy(engine, &saved,
+ SELFTEST_SCHEDULER_MODIFY_FAST_RESET);
+ if (ret)
+ break;
+
ce = intel_context_create(engine);
if (IS_ERR(ce)) {
ret = PTR_ERR(ce);
- break;
+ goto restore;
}
- ok = verify_wa_lists(gt, &lists, "before reset");
- if (!ok) {
- ret = -ESRCH;
- goto err;
- }
+ if (!using_guc) {
+ ok = verify_wa_lists(gt, lists, "before reset");
+ if (!ok) {
+ ret = -ESRCH;
+ goto err;
+ }
- ret = intel_engine_reset(engine, "live_workarounds:idle");
- if (ret) {
- pr_err("%s: Reset failed while idle\n", engine->name);
- goto err;
- }
+ ret = intel_engine_reset(engine, "live_workarounds:idle");
+ if (ret) {
+ pr_err("%s: Reset failed while idle\n", engine->name);
+ goto err;
+ }
- ok = verify_wa_lists(gt, &lists, "after idle reset");
- if (!ok) {
- ret = -ESRCH;
- goto err;
+ ok = verify_wa_lists(gt, lists, "after idle reset");
+ if (!ok) {
+ ret = -ESRCH;
+ goto err;
+ }
}
ret = igt_spinner_init(&spin, engine->gt);
@@ -1271,32 +1328,49 @@ live_engine_reset_workarounds(void *arg)
goto err;
}
- ret = intel_engine_reset(engine, "live_workarounds:active");
- if (ret) {
- pr_err("%s: Reset failed on an active spinner\n",
- engine->name);
- igt_spinner_fini(&spin);
- goto err;
+ /* Ensure the spinner hasn't aborted */
+ if (i915_request_completed(rq)) {
+ ret = -ETIMEDOUT;
+ goto skip;
}
+ if (!using_guc) {
+ ret = intel_engine_reset(engine, "live_workarounds:active");
+ if (ret) {
+ pr_err("%s: Reset failed on an active spinner\n",
+ engine->name);
+ igt_spinner_fini(&spin);
+ goto err;
+ }
+ }
+
+ /* Ensure the reset happens and kills the engine */
+ if (ret == 0)
+ ret = intel_selftest_wait_for_rq(rq);
+
+skip:
igt_spinner_end(&spin);
igt_spinner_fini(&spin);
- ok = verify_wa_lists(gt, &lists, "after busy reset");
- if (!ok) {
+ ok = verify_wa_lists(gt, lists, "after busy reset");
+ if (!ok)
ret = -ESRCH;
- goto err;
- }
err:
intel_context_put(ce);
+
+restore:
+ ret2 = intel_selftest_restore_policy(engine, &saved);
+ if (ret == 0)
+ ret = ret2;
if (ret)
break;
}
- reference_lists_fini(gt, &lists);
+ reference_lists_fini(gt, lists);
intel_runtime_pm_put(gt->uncore->rpm, wakeref);
igt_global_reset_unlock(gt);
+ kfree(lists);
igt_flush_test(gt->i915);
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
index 90efef8a73e4..8ff582222aff 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
@@ -6,6 +6,113 @@
#ifndef _ABI_GUC_ACTIONS_ABI_H
#define _ABI_GUC_ACTIONS_ABI_H
+/**
+ * DOC: HOST2GUC_REGISTER_CTB
+ *
+ * This message is used as part of the `CTB based communication`_ setup.
+ *
+ * This message must be sent as `MMIO HXG Message`_.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN = GUC_HXG_ORIGIN_HOST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_REQUEST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | DATA0 = MBZ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | ACTION = _`GUC_ACTION_HOST2GUC_REGISTER_CTB` = 0x4505 |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:12 | RESERVED = MBZ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 11:8 | **TYPE** - type for the `CT Buffer`_ |
+ * | | | |
+ * | | | - _`GUC_CTB_TYPE_HOST2GUC` = 0 |
+ * | | | - _`GUC_CTB_TYPE_GUC2HOST` = 1 |
+ * | +-------+--------------------------------------------------------------+
+ * | | 7:0 | **SIZE** - size of the `CT Buffer`_ in 4K units minus 1 |
+ * +---+-------+--------------------------------------------------------------+
+ * | 2 | 31:0 | **DESC_ADDR** - GGTT address of the `CTB Descriptor`_ |
+ * +---+-------+--------------------------------------------------------------+
+ * | 3 | 31:0 | **BUFF_ADDF** - GGTT address of the `CT Buffer`_ |
+ * +---+-------+--------------------------------------------------------------+
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN = GUC_HXG_ORIGIN_GUC_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_RESPONSE_SUCCESS_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:0 | DATA0 = MBZ |
+ * +---+-------+--------------------------------------------------------------+
+ */
+#define GUC_ACTION_HOST2GUC_REGISTER_CTB 0x4505
+
+#define HOST2GUC_REGISTER_CTB_REQUEST_MSG_LEN (GUC_HXG_REQUEST_MSG_MIN_LEN + 3u)
+#define HOST2GUC_REGISTER_CTB_REQUEST_MSG_0_MBZ GUC_HXG_REQUEST_MSG_0_DATA0
+#define HOST2GUC_REGISTER_CTB_REQUEST_MSG_1_MBZ (0xfffff << 12)
+#define HOST2GUC_REGISTER_CTB_REQUEST_MSG_1_TYPE (0xf << 8)
+#define GUC_CTB_TYPE_HOST2GUC 0u
+#define GUC_CTB_TYPE_GUC2HOST 1u
+#define HOST2GUC_REGISTER_CTB_REQUEST_MSG_1_SIZE (0xff << 0)
+#define HOST2GUC_REGISTER_CTB_REQUEST_MSG_2_DESC_ADDR GUC_HXG_REQUEST_MSG_n_DATAn
+#define HOST2GUC_REGISTER_CTB_REQUEST_MSG_3_BUFF_ADDR GUC_HXG_REQUEST_MSG_n_DATAn
+
+#define HOST2GUC_REGISTER_CTB_RESPONSE_MSG_LEN GUC_HXG_RESPONSE_MSG_MIN_LEN
+#define HOST2GUC_REGISTER_CTB_RESPONSE_MSG_0_MBZ GUC_HXG_RESPONSE_MSG_0_DATA0
+
+/**
+ * DOC: HOST2GUC_DEREGISTER_CTB
+ *
+ * This message is used as part of the `CTB based communication`_ teardown.
+ *
+ * This message must be sent as `MMIO HXG Message`_.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN = GUC_HXG_ORIGIN_HOST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_REQUEST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | DATA0 = MBZ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | ACTION = _`GUC_ACTION_HOST2GUC_DEREGISTER_CTB` = 0x4506 |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:12 | RESERVED = MBZ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 11:8 | **TYPE** - type of the `CT Buffer`_ |
+ * | | | |
+ * | | | see `GUC_ACTION_HOST2GUC_REGISTER_CTB`_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 7:0 | RESERVED = MBZ |
+ * +---+-------+--------------------------------------------------------------+
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN = GUC_HXG_ORIGIN_GUC_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_RESPONSE_SUCCESS_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:0 | DATA0 = MBZ |
+ * +---+-------+--------------------------------------------------------------+
+ */
+#define GUC_ACTION_HOST2GUC_DEREGISTER_CTB 0x4506
+
+#define HOST2GUC_DEREGISTER_CTB_REQUEST_MSG_LEN (GUC_HXG_REQUEST_MSG_MIN_LEN + 1u)
+#define HOST2GUC_DEREGISTER_CTB_REQUEST_MSG_0_MBZ GUC_HXG_REQUEST_MSG_0_DATA0
+#define HOST2GUC_DEREGISTER_CTB_REQUEST_MSG_1_MBZ (0xfffff << 12)
+#define HOST2GUC_DEREGISTER_CTB_REQUEST_MSG_1_TYPE (0xf << 8)
+#define HOST2GUC_DEREGISTER_CTB_REQUEST_MSG_1_MBZ2 (0xff << 0)
+
+#define HOST2GUC_DEREGISTER_CTB_RESPONSE_MSG_LEN GUC_HXG_RESPONSE_MSG_MIN_LEN
+#define HOST2GUC_DEREGISTER_CTB_RESPONSE_MSG_0_MBZ GUC_HXG_RESPONSE_MSG_0_DATA0
+
+/* legacy definitions */
+
enum intel_guc_action {
INTEL_GUC_ACTION_DEFAULT = 0x0,
INTEL_GUC_ACTION_REQUEST_PREEMPTION = 0x2,
@@ -17,13 +124,33 @@ enum intel_guc_action {
INTEL_GUC_ACTION_FORCE_LOG_BUFFER_FLUSH = 0x302,
INTEL_GUC_ACTION_ENTER_S_STATE = 0x501,
INTEL_GUC_ACTION_EXIT_S_STATE = 0x502,
- INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003,
+ INTEL_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE = 0x506,
+ INTEL_GUC_ACTION_SCHED_CONTEXT = 0x1000,
+ INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_SET = 0x1001,
+ INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002,
+ INTEL_GUC_ACTION_SCHED_ENGINE_MODE_SET = 0x1003,
+ INTEL_GUC_ACTION_SCHED_ENGINE_MODE_DONE = 0x1004,
+ INTEL_GUC_ACTION_SET_CONTEXT_PRIORITY = 0x1005,
+ INTEL_GUC_ACTION_SET_CONTEXT_EXECUTION_QUANTUM = 0x1006,
+ INTEL_GUC_ACTION_SET_CONTEXT_PREEMPTION_TIMEOUT = 0x1007,
+ INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008,
+ INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009,
+ INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004,
INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
+ INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502,
+ INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503,
INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505,
INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER = 0x4506,
+ INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600,
+ INTEL_GUC_ACTION_RESET_CLIENT = 0x5507,
INTEL_GUC_ACTION_LIMIT
};
+enum intel_guc_rc_options {
+ INTEL_GUCRC_HOST_CONTROL,
+ INTEL_GUCRC_FIRMWARE_CONTROL,
+};
+
enum intel_guc_preempt_options {
INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h
new file mode 100644
index 000000000000..7a8d4bfc5f6a
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h
@@ -0,0 +1,235 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef _GUC_ACTIONS_SLPC_ABI_H_
+#define _GUC_ACTIONS_SLPC_ABI_H_
+
+#include <linux/types.h>
+#include "i915_reg.h"
+
+/**
+ * DOC: SLPC SHARED DATA STRUCTURE
+ *
+ * +----+------+--------------------------------------------------------------+
+ * | CL | Bytes| Description |
+ * +====+======+==============================================================+
+ * | 1 | 0-3 | SHARED DATA SIZE |
+ * | +------+--------------------------------------------------------------+
+ * | | 4-7 | GLOBAL STATE |
+ * | +------+--------------------------------------------------------------+
+ * | | 8-11 | DISPLAY DATA ADDRESS |
+ * | +------+--------------------------------------------------------------+
+ * | | 12:63| PADDING |
+ * +----+------+--------------------------------------------------------------+
+ * | | 0:63 | PADDING(PLATFORM INFO) |
+ * +----+------+--------------------------------------------------------------+
+ * | 3 | 0-3 | TASK STATE DATA |
+ * + +------+--------------------------------------------------------------+
+ * | | 4:63 | PADDING |
+ * +----+------+--------------------------------------------------------------+
+ * |4-21|0:1087| OVERRIDE PARAMS AND BIT FIELDS |
+ * +----+------+--------------------------------------------------------------+
+ * | | | PADDING + EXTRA RESERVED PAGE |
+ * +----+------+--------------------------------------------------------------+
+ */
+
+/*
+ * SLPC exposes certain parameters for global configuration by the host.
+ * These are referred to as override parameters, because in most cases
+ * the host will not need to modify the default values used by SLPC.
+ * SLPC remembers the default values which allows the host to easily restore
+ * them by simply unsetting the override. The host can set or unset override
+ * parameters during SLPC (re-)initialization using the SLPC Reset event.
+ * The host can also set or unset override parameters on the fly using the
+ * Parameter Set and Parameter Unset events
+ */
+
+#define SLPC_MAX_OVERRIDE_PARAMETERS 256
+#define SLPC_OVERRIDE_BITFIELD_SIZE \
+ (SLPC_MAX_OVERRIDE_PARAMETERS / 32)
+
+#define SLPC_PAGE_SIZE_BYTES 4096
+#define SLPC_CACHELINE_SIZE_BYTES 64
+#define SLPC_SHARED_DATA_SIZE_BYTE_HEADER SLPC_CACHELINE_SIZE_BYTES
+#define SLPC_SHARED_DATA_SIZE_BYTE_PLATFORM_INFO SLPC_CACHELINE_SIZE_BYTES
+#define SLPC_SHARED_DATA_SIZE_BYTE_TASK_STATE SLPC_CACHELINE_SIZE_BYTES
+#define SLPC_SHARED_DATA_MODE_DEFN_TABLE_SIZE SLPC_PAGE_SIZE_BYTES
+#define SLPC_SHARED_DATA_SIZE_BYTE_MAX (2 * SLPC_PAGE_SIZE_BYTES)
+
+/*
+ * Cacheline size aligned (Total size needed for
+ * SLPM_KMD_MAX_OVERRIDE_PARAMETERS=256 is 1088 bytes)
+ */
+#define SLPC_OVERRIDE_PARAMS_TOTAL_BYTES (((((SLPC_MAX_OVERRIDE_PARAMETERS * 4) \
+ + ((SLPC_MAX_OVERRIDE_PARAMETERS / 32) * 4)) \
+ + (SLPC_CACHELINE_SIZE_BYTES - 1)) / SLPC_CACHELINE_SIZE_BYTES) * \
+ SLPC_CACHELINE_SIZE_BYTES)
+
+#define SLPC_SHARED_DATA_SIZE_BYTE_OTHER (SLPC_SHARED_DATA_SIZE_BYTE_MAX - \
+ (SLPC_SHARED_DATA_SIZE_BYTE_HEADER \
+ + SLPC_SHARED_DATA_SIZE_BYTE_PLATFORM_INFO \
+ + SLPC_SHARED_DATA_SIZE_BYTE_TASK_STATE \
+ + SLPC_OVERRIDE_PARAMS_TOTAL_BYTES \
+ + SLPC_SHARED_DATA_MODE_DEFN_TABLE_SIZE))
+
+enum slpc_task_enable {
+ SLPC_PARAM_TASK_DEFAULT = 0,
+ SLPC_PARAM_TASK_ENABLED,
+ SLPC_PARAM_TASK_DISABLED,
+ SLPC_PARAM_TASK_UNKNOWN
+};
+
+enum slpc_global_state {
+ SLPC_GLOBAL_STATE_NOT_RUNNING = 0,
+ SLPC_GLOBAL_STATE_INITIALIZING = 1,
+ SLPC_GLOBAL_STATE_RESETTING = 2,
+ SLPC_GLOBAL_STATE_RUNNING = 3,
+ SLPC_GLOBAL_STATE_SHUTTING_DOWN = 4,
+ SLPC_GLOBAL_STATE_ERROR = 5
+};
+
+enum slpc_param_id {
+ SLPC_PARAM_TASK_ENABLE_GTPERF = 0,
+ SLPC_PARAM_TASK_DISABLE_GTPERF = 1,
+ SLPC_PARAM_TASK_ENABLE_BALANCER = 2,
+ SLPC_PARAM_TASK_DISABLE_BALANCER = 3,
+ SLPC_PARAM_TASK_ENABLE_DCC = 4,
+ SLPC_PARAM_TASK_DISABLE_DCC = 5,
+ SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ = 6,
+ SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ = 7,
+ SLPC_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ = 8,
+ SLPC_PARAM_GLOBAL_MAX_GT_SLICE_FREQ_MHZ = 9,
+ SLPC_PARAM_GTPERF_THRESHOLD_MAX_FPS = 10,
+ SLPC_PARAM_GLOBAL_DISABLE_GT_FREQ_MANAGEMENT = 11,
+ SLPC_PARAM_GTPERF_ENABLE_FRAMERATE_STALLING = 12,
+ SLPC_PARAM_GLOBAL_DISABLE_RC6_MODE_CHANGE = 13,
+ SLPC_PARAM_GLOBAL_OC_UNSLICE_FREQ_MHZ = 14,
+ SLPC_PARAM_GLOBAL_OC_SLICE_FREQ_MHZ = 15,
+ SLPC_PARAM_GLOBAL_ENABLE_IA_GT_BALANCING = 16,
+ SLPC_PARAM_GLOBAL_ENABLE_ADAPTIVE_BURST_TURBO = 17,
+ SLPC_PARAM_GLOBAL_ENABLE_EVAL_MODE = 18,
+ SLPC_PARAM_GLOBAL_ENABLE_BALANCER_IN_NON_GAMING_MODE = 19,
+ SLPC_PARAM_GLOBAL_RT_MODE_TURBO_FREQ_DELTA_MHZ = 20,
+ SLPC_PARAM_PWRGATE_RC_MODE = 21,
+ SLPC_PARAM_EDR_MODE_COMPUTE_TIMEOUT_MS = 22,
+ SLPC_PARAM_EDR_QOS_FREQ_MHZ = 23,
+ SLPC_PARAM_MEDIA_FF_RATIO_MODE = 24,
+ SLPC_PARAM_ENABLE_IA_FREQ_LIMITING = 25,
+ SLPC_PARAM_STRATEGIES = 26,
+ SLPC_PARAM_POWER_PROFILE = 27,
+ SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY = 28,
+ SLPC_MAX_PARAM = 32,
+};
+
+enum slpc_event_id {
+ SLPC_EVENT_RESET = 0,
+ SLPC_EVENT_SHUTDOWN = 1,
+ SLPC_EVENT_PLATFORM_INFO_CHANGE = 2,
+ SLPC_EVENT_DISPLAY_MODE_CHANGE = 3,
+ SLPC_EVENT_FLIP_COMPLETE = 4,
+ SLPC_EVENT_QUERY_TASK_STATE = 5,
+ SLPC_EVENT_PARAMETER_SET = 6,
+ SLPC_EVENT_PARAMETER_UNSET = 7,
+};
+
+struct slpc_task_state_data {
+ union {
+ u32 task_status_padding;
+ struct {
+ u32 status;
+#define SLPC_GTPERF_TASK_ENABLED REG_BIT(0)
+#define SLPC_DCC_TASK_ENABLED REG_BIT(11)
+#define SLPC_IN_DCC REG_BIT(12)
+#define SLPC_BALANCER_ENABLED REG_BIT(15)
+#define SLPC_IBC_TASK_ENABLED REG_BIT(16)
+#define SLPC_BALANCER_IA_LMT_ENABLED REG_BIT(17)
+#define SLPC_BALANCER_IA_LMT_ACTIVE REG_BIT(18)
+ };
+ };
+ union {
+ u32 freq_padding;
+ struct {
+#define SLPC_MAX_UNSLICE_FREQ_MASK REG_GENMASK(7, 0)
+#define SLPC_MIN_UNSLICE_FREQ_MASK REG_GENMASK(15, 8)
+#define SLPC_MAX_SLICE_FREQ_MASK REG_GENMASK(23, 16)
+#define SLPC_MIN_SLICE_FREQ_MASK REG_GENMASK(31, 24)
+ u32 freq;
+ };
+ };
+} __packed;
+
+struct slpc_shared_data_header {
+ /* Total size in bytes of this shared buffer. */
+ u32 size;
+ u32 global_state;
+ u32 display_data_addr;
+} __packed;
+
+struct slpc_override_params {
+ u32 bits[SLPC_OVERRIDE_BITFIELD_SIZE];
+ u32 values[SLPC_MAX_OVERRIDE_PARAMETERS];
+} __packed;
+
+struct slpc_shared_data {
+ struct slpc_shared_data_header header;
+ u8 shared_data_header_pad[SLPC_SHARED_DATA_SIZE_BYTE_HEADER -
+ sizeof(struct slpc_shared_data_header)];
+
+ u8 platform_info_pad[SLPC_SHARED_DATA_SIZE_BYTE_PLATFORM_INFO];
+
+ struct slpc_task_state_data task_state_data;
+ u8 task_state_data_pad[SLPC_SHARED_DATA_SIZE_BYTE_TASK_STATE -
+ sizeof(struct slpc_task_state_data)];
+
+ struct slpc_override_params override_params;
+ u8 override_params_pad[SLPC_OVERRIDE_PARAMS_TOTAL_BYTES -
+ sizeof(struct slpc_override_params)];
+
+ u8 shared_data_pad[SLPC_SHARED_DATA_SIZE_BYTE_OTHER];
+
+ /* PAGE 2 (4096 bytes), mode based parameter will be removed soon */
+ u8 reserved_mode_definition[4096];
+} __packed;
+
+/**
+ * DOC: SLPC H2G MESSAGE FORMAT
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN = GUC_HXG_ORIGIN_HOST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_REQUEST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | DATA0 = MBZ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | ACTION = _`GUC_ACTION_HOST2GUC_PC_SLPM_REQUEST` = 0x3003 |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:8 | **EVENT_ID** |
+ * + +-------+--------------------------------------------------------------+
+ * | | 7:0 | **EVENT_ARGC** - number of data arguments |
+ * +---+-------+--------------------------------------------------------------+
+ * | 2 | 31:0 | **EVENT_DATA1** |
+ * +---+-------+--------------------------------------------------------------+
+ * |...| 31:0 | ... |
+ * +---+-------+--------------------------------------------------------------+
+ * |2+n| 31:0 | **EVENT_DATAn** |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST 0x3003
+
+#define HOST2GUC_PC_SLPC_REQUEST_MSG_MIN_LEN \
+ (GUC_HXG_REQUEST_MSG_MIN_LEN + 1u)
+#define HOST2GUC_PC_SLPC_EVENT_MAX_INPUT_ARGS 9
+#define HOST2GUC_PC_SLPC_REQUEST_MSG_MAX_LEN \
+ (HOST2GUC_PC_SLPC_REQUEST_REQUEST_MSG_MIN_LEN + \
+ HOST2GUC_PC_SLPC_EVENT_MAX_INPUT_ARGS)
+#define HOST2GUC_PC_SLPC_REQUEST_MSG_0_MBZ GUC_HXG_REQUEST_MSG_0_DATA0
+#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ID (0xff << 8)
+#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC (0xff << 0)
+#define HOST2GUC_PC_SLPC_REQUEST_MSG_N_EVENT_DATA_N GUC_HXG_REQUEST_MSG_n_DATAn
+
+#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
index d38935f47ecf..99e1fad5ca20 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
@@ -7,6 +7,111 @@
#define _ABI_GUC_COMMUNICATION_CTB_ABI_H
#include <linux/types.h>
+#include <linux/build_bug.h>
+
+#include "guc_messages_abi.h"
+
+/**
+ * DOC: CT Buffer
+ *
+ * Circular buffer used to send `CTB Message`_
+ */
+
+/**
+ * DOC: CTB Descriptor
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31:0 | **HEAD** - offset (in dwords) to the last dword that was |
+ * | | | read from the `CT Buffer`_. |
+ * | | | It can only be updated by the receiver. |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:0 | **TAIL** - offset (in dwords) to the last dword that was |
+ * | | | written to the `CT Buffer`_. |
+ * | | | It can only be updated by the sender. |
+ * +---+-------+--------------------------------------------------------------+
+ * | 2 | 31:0 | **STATUS** - status of the CTB |
+ * | | | |
+ * | | | - _`GUC_CTB_STATUS_NO_ERROR` = 0 (normal operation) |
+ * | | | - _`GUC_CTB_STATUS_OVERFLOW` = 1 (head/tail too large) |
+ * | | | - _`GUC_CTB_STATUS_UNDERFLOW` = 2 (truncated message) |
+ * | | | - _`GUC_CTB_STATUS_MISMATCH` = 4 (head/tail modified) |
+ * +---+-------+--------------------------------------------------------------+
+ * |...| | RESERVED = MBZ |
+ * +---+-------+--------------------------------------------------------------+
+ * | 15| 31:0 | RESERVED = MBZ |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+struct guc_ct_buffer_desc {
+ u32 head;
+ u32 tail;
+ u32 status;
+#define GUC_CTB_STATUS_NO_ERROR 0
+#define GUC_CTB_STATUS_OVERFLOW (1 << 0)
+#define GUC_CTB_STATUS_UNDERFLOW (1 << 1)
+#define GUC_CTB_STATUS_MISMATCH (1 << 2)
+ u32 reserved[13];
+} __packed;
+static_assert(sizeof(struct guc_ct_buffer_desc) == 64);
+
+/**
+ * DOC: CTB Message
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31:16 | **FENCE** - message identifier |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:12 | **FORMAT** - format of the CTB message |
+ * | | | - _`GUC_CTB_FORMAT_HXG` = 0 - see `CTB HXG Message`_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 11:8 | **RESERVED** |
+ * | +-------+--------------------------------------------------------------+
+ * | | 7:0 | **NUM_DWORDS** - length of the CTB message (w/o header) |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:0 | optional (depends on FORMAT) |
+ * +---+-------+ |
+ * |...| | |
+ * +---+-------+ |
+ * | n | 31:0 | |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_CTB_HDR_LEN 1u
+#define GUC_CTB_MSG_MIN_LEN GUC_CTB_HDR_LEN
+#define GUC_CTB_MSG_MAX_LEN 256u
+#define GUC_CTB_MSG_0_FENCE (0xffff << 16)
+#define GUC_CTB_MSG_0_FORMAT (0xf << 12)
+#define GUC_CTB_FORMAT_HXG 0u
+#define GUC_CTB_MSG_0_RESERVED (0xf << 8)
+#define GUC_CTB_MSG_0_NUM_DWORDS (0xff << 0)
+
+/**
+ * DOC: CTB HXG Message
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31:16 | FENCE |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:12 | FORMAT = GUC_CTB_FORMAT_HXG_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 11:8 | RESERVED = MBZ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 7:0 | NUM_DWORDS = length (in dwords) of the embedded HXG message |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:0 | +--------------------------------------------------------+ |
+ * +---+-------+ | | |
+ * |...| | | Embedded `HXG Message`_ | |
+ * +---+-------+ | | |
+ * | n | 31:0 | +--------------------------------------------------------+ |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_CTB_HXG_MSG_MIN_LEN (GUC_CTB_MSG_MIN_LEN + GUC_HXG_MSG_MIN_LEN)
+#define GUC_CTB_HXG_MSG_MAX_LEN GUC_CTB_MSG_MAX_LEN
/**
* DOC: CTB based communication
@@ -61,28 +166,6 @@
*/
/*
- * Describes single command transport buffer.
- * Used by both guc-master and clients.
- */
-struct guc_ct_buffer_desc {
- u32 addr; /* gfx address */
- u64 host_private; /* host private data */
- u32 size; /* size in bytes */
- u32 head; /* offset updated by GuC*/
- u32 tail; /* offset updated by owner */
- u32 is_in_error; /* error indicator */
- u32 reserved1;
- u32 reserved2;
- u32 owner; /* id of the channel owner */
- u32 owner_sub_id; /* owner-defined field for extra tracking */
- u32 reserved[5];
-} __packed;
-
-/* Type of command transport buffer */
-#define INTEL_GUC_CT_BUFFER_TYPE_SEND 0x0u
-#define INTEL_GUC_CT_BUFFER_TYPE_RECV 0x1u
-
-/*
* Definition of the command transport message header (DW0)
*
* bit[4..0] message len (in dwords)
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h
index be066a62e9e0..bbf1ddb77434 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h
@@ -7,46 +7,43 @@
#define _ABI_GUC_COMMUNICATION_MMIO_ABI_H
/**
- * DOC: MMIO based communication
+ * DOC: GuC MMIO based communication
*
- * The MMIO based communication between Host and GuC uses software scratch
- * registers, where first register holds data treated as message header,
- * and other registers are used to hold message payload.
+ * The MMIO based communication between Host and GuC relies on special
+ * hardware registers which format could be defined by the software
+ * (so called scratch registers).
*
- * For Gen9+, GuC uses software scratch registers 0xC180-0xC1B8,
- * but no H2G command takes more than 8 parameters and the GuC FW
- * itself uses an 8-element array to store the H2G message.
+ * Each MMIO based message, both Host to GuC (H2G) and GuC to Host (G2H)
+ * messages, which maximum length depends on number of available scratch
+ * registers, is directly written into those scratch registers.
*
- * +-----------+---------+---------+---------+
- * | MMIO[0] | MMIO[1] | ... | MMIO[n] |
- * +-----------+---------+---------+---------+
- * | header | optional payload |
- * +======+====+=========+=========+=========+
- * | 31:28|type| | | |
- * +------+----+ | | |
- * | 27:16|data| | | |
- * +------+----+ | | |
- * | 15:0|code| | | |
- * +------+----+---------+---------+---------+
+ * For Gen9+, there are 16 software scratch registers 0xC180-0xC1B8,
+ * but no H2G command takes more than 4 parameters and the GuC firmware
+ * itself uses an 4-element array to store the H2G message.
*
- * The message header consists of:
+ * For Gen11+, there are additional 4 registers 0x190240-0x19024C, which
+ * are, regardless on lower count, preferred over legacy ones.
*
- * - **type**, indicates message type
- * - **code**, indicates message code, is specific for **type**
- * - **data**, indicates message data, optional, depends on **code**
- *
- * The following message **types** are supported:
- *
- * - **REQUEST**, indicates Host-to-GuC request, requested GuC action code
- * must be priovided in **code** field. Optional action specific parameters
- * can be provided in remaining payload registers or **data** field.
- *
- * - **RESPONSE**, indicates GuC-to-Host response from earlier GuC request,
- * action response status will be provided in **code** field. Optional
- * response data can be returned in remaining payload registers or **data**
- * field.
+ * The MMIO based communication is mainly used during driver initialization
+ * phase to setup the `CTB based communication`_ that will be used afterwards.
*/
-#define GUC_MAX_MMIO_MSG_LEN 8
+#define GUC_MAX_MMIO_MSG_LEN 4
+
+/**
+ * DOC: MMIO HXG Message
+ *
+ * Format of the MMIO messages follows definitions of `HXG Message`_.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31:0 | +--------------------------------------------------------+ |
+ * +---+-------+ | | |
+ * |...| | | Embedded `HXG Message`_ | |
+ * +---+-------+ | | |
+ * | n | 31:0 | +--------------------------------------------------------+ |
+ * +---+-------+--------------------------------------------------------------+
+ */
#endif /* _ABI_GUC_COMMUNICATION_MMIO_ABI_H */
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h
index 775e21f3058c..29ac823acd4c 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h
@@ -6,6 +6,219 @@
#ifndef _ABI_GUC_MESSAGES_ABI_H
#define _ABI_GUC_MESSAGES_ABI_H
+/**
+ * DOC: HXG Message
+ *
+ * All messages exchanged with GuC are defined using 32 bit dwords.
+ * First dword is treated as a message header. Remaining dwords are optional.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | | | |
+ * | 0 | 31 | **ORIGIN** - originator of the message |
+ * | | | - _`GUC_HXG_ORIGIN_HOST` = 0 |
+ * | | | - _`GUC_HXG_ORIGIN_GUC` = 1 |
+ * | | | |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | **TYPE** - message type |
+ * | | | - _`GUC_HXG_TYPE_REQUEST` = 0 |
+ * | | | - _`GUC_HXG_TYPE_EVENT` = 1 |
+ * | | | - _`GUC_HXG_TYPE_NO_RESPONSE_BUSY` = 3 |
+ * | | | - _`GUC_HXG_TYPE_NO_RESPONSE_RETRY` = 5 |
+ * | | | - _`GUC_HXG_TYPE_RESPONSE_FAILURE` = 6 |
+ * | | | - _`GUC_HXG_TYPE_RESPONSE_SUCCESS` = 7 |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:0 | **AUX** - auxiliary data (depends on TYPE) |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:0 | |
+ * +---+-------+ |
+ * |...| | **PAYLOAD** - optional payload (depends on TYPE) |
+ * +---+-------+ |
+ * | n | 31:0 | |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_HXG_MSG_MIN_LEN 1u
+#define GUC_HXG_MSG_0_ORIGIN (0x1 << 31)
+#define GUC_HXG_ORIGIN_HOST 0u
+#define GUC_HXG_ORIGIN_GUC 1u
+#define GUC_HXG_MSG_0_TYPE (0x7 << 28)
+#define GUC_HXG_TYPE_REQUEST 0u
+#define GUC_HXG_TYPE_EVENT 1u
+#define GUC_HXG_TYPE_NO_RESPONSE_BUSY 3u
+#define GUC_HXG_TYPE_NO_RESPONSE_RETRY 5u
+#define GUC_HXG_TYPE_RESPONSE_FAILURE 6u
+#define GUC_HXG_TYPE_RESPONSE_SUCCESS 7u
+#define GUC_HXG_MSG_0_AUX (0xfffffff << 0)
+#define GUC_HXG_MSG_n_PAYLOAD (0xffffffff << 0)
+
+/**
+ * DOC: HXG Request
+ *
+ * The `HXG Request`_ message should be used to initiate synchronous activity
+ * for which confirmation or return data is expected.
+ *
+ * The recipient of this message shall use `HXG Response`_, `HXG Failure`_
+ * or `HXG Retry`_ message as a definite reply, and may use `HXG Busy`_
+ * message as a intermediate reply.
+ *
+ * Format of @DATA0 and all @DATAn fields depends on the @ACTION code.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_REQUEST_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | **DATA0** - request data (depends on ACTION) |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | **ACTION** - requested action code |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:0 | |
+ * +---+-------+ |
+ * |...| | **DATAn** - optional data (depends on ACTION) |
+ * +---+-------+ |
+ * | n | 31:0 | |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_HXG_REQUEST_MSG_MIN_LEN GUC_HXG_MSG_MIN_LEN
+#define GUC_HXG_REQUEST_MSG_0_DATA0 (0xfff << 16)
+#define GUC_HXG_REQUEST_MSG_0_ACTION (0xffff << 0)
+#define GUC_HXG_REQUEST_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD
+
+/**
+ * DOC: HXG Event
+ *
+ * The `HXG Event`_ message should be used to initiate asynchronous activity
+ * that does not involves immediate confirmation nor data.
+ *
+ * Format of @DATA0 and all @DATAn fields depends on the @ACTION code.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_EVENT_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | **DATA0** - event data (depends on ACTION) |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | **ACTION** - event action code |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:0 | |
+ * +---+-------+ |
+ * |...| | **DATAn** - optional event data (depends on ACTION) |
+ * +---+-------+ |
+ * | n | 31:0 | |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_HXG_EVENT_MSG_MIN_LEN GUC_HXG_MSG_MIN_LEN
+#define GUC_HXG_EVENT_MSG_0_DATA0 (0xfff << 16)
+#define GUC_HXG_EVENT_MSG_0_ACTION (0xffff << 0)
+#define GUC_HXG_EVENT_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD
+
+/**
+ * DOC: HXG Busy
+ *
+ * The `HXG Busy`_ message may be used to acknowledge reception of the `HXG Request`_
+ * message if the recipient expects that it processing will be longer than default
+ * timeout.
+ *
+ * The @COUNTER field may be used as a progress indicator.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_NO_RESPONSE_BUSY_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:0 | **COUNTER** - progress indicator |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_HXG_BUSY_MSG_LEN GUC_HXG_MSG_MIN_LEN
+#define GUC_HXG_BUSY_MSG_0_COUNTER GUC_HXG_MSG_0_AUX
+
+/**
+ * DOC: HXG Retry
+ *
+ * The `HXG Retry`_ message should be used by recipient to indicate that the
+ * `HXG Request`_ message was dropped and it should be resent again.
+ *
+ * The @REASON field may be used to provide additional information.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_NO_RESPONSE_RETRY_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:0 | **REASON** - reason for retry |
+ * | | | - _`GUC_HXG_RETRY_REASON_UNSPECIFIED` = 0 |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_HXG_RETRY_MSG_LEN GUC_HXG_MSG_MIN_LEN
+#define GUC_HXG_RETRY_MSG_0_REASON GUC_HXG_MSG_0_AUX
+#define GUC_HXG_RETRY_REASON_UNSPECIFIED 0u
+
+/**
+ * DOC: HXG Failure
+ *
+ * The `HXG Failure`_ message shall be used as a reply to the `HXG Request`_
+ * message that could not be processed due to an error.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_RESPONSE_FAILURE_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | **HINT** - additional error hint |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | **ERROR** - error/result code |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_HXG_FAILURE_MSG_LEN GUC_HXG_MSG_MIN_LEN
+#define GUC_HXG_FAILURE_MSG_0_HINT (0xfff << 16)
+#define GUC_HXG_FAILURE_MSG_0_ERROR (0xffff << 0)
+
+/**
+ * DOC: HXG Response
+ *
+ * The `HXG Response`_ message shall be used as a reply to the `HXG Request`_
+ * message that was successfully processed without an error.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = GUC_HXG_TYPE_RESPONSE_SUCCESS_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:0 | **DATA0** - data (depends on ACTION from `HXG Request`_) |
+ * +---+-------+--------------------------------------------------------------+
+ * | 1 | 31:0 | |
+ * +---+-------+ |
+ * |...| | **DATAn** - data (depends on ACTION from `HXG Request`_) |
+ * +---+-------+ |
+ * | n | 31:0 | |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+#define GUC_HXG_RESPONSE_MSG_MIN_LEN GUC_HXG_MSG_MIN_LEN
+#define GUC_HXG_RESPONSE_MSG_0_DATA0 GUC_HXG_MSG_0_AUX
+#define GUC_HXG_RESPONSE_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD
+
+/* deprecated */
#define INTEL_GUC_MSG_TYPE_SHIFT 28
#define INTEL_GUC_MSG_TYPE_MASK (0xF << INTEL_GUC_MSG_TYPE_SHIFT)
#define INTEL_GUC_MSG_DATA_SHIFT 16
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index f147cb389a20..fbfcae727d7f 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -7,6 +7,7 @@
#include "gt/intel_gt_irq.h"
#include "gt/intel_gt_pm_irq.h"
#include "intel_guc.h"
+#include "intel_guc_slpc.h"
#include "intel_guc_ads.h"
#include "intel_guc_submission.h"
#include "i915_drv.h"
@@ -157,6 +158,8 @@ void intel_guc_init_early(struct intel_guc *guc)
intel_guc_ct_init_early(&guc->ct);
intel_guc_log_init_early(&guc->log);
intel_guc_submission_init_early(guc);
+ intel_guc_slpc_init_early(&guc->slpc);
+ intel_guc_rc_init_early(guc);
mutex_init(&guc->send_mutex);
spin_lock_init(&guc->irq_lock);
@@ -180,6 +183,11 @@ void intel_guc_init_early(struct intel_guc *guc)
}
}
+void intel_guc_init_late(struct intel_guc *guc)
+{
+ intel_guc_ads_init_late(guc);
+}
+
static u32 guc_ctl_debug_flags(struct intel_guc *guc)
{
u32 level = intel_guc_log_get_level(&guc->log);
@@ -201,6 +209,9 @@ static u32 guc_ctl_feature_flags(struct intel_guc *guc)
if (!intel_guc_submission_is_used(guc))
flags |= GUC_CTL_DISABLE_SCHEDULER;
+ if (intel_guc_slpc_is_used(guc))
+ flags |= GUC_CTL_ENABLE_SLPC;
+
return flags;
}
@@ -219,24 +230,19 @@ static u32 guc_ctl_log_params_flags(struct intel_guc *guc)
BUILD_BUG_ON(!CRASH_BUFFER_SIZE);
BUILD_BUG_ON(!IS_ALIGNED(CRASH_BUFFER_SIZE, UNIT));
- BUILD_BUG_ON(!DPC_BUFFER_SIZE);
- BUILD_BUG_ON(!IS_ALIGNED(DPC_BUFFER_SIZE, UNIT));
- BUILD_BUG_ON(!ISR_BUFFER_SIZE);
- BUILD_BUG_ON(!IS_ALIGNED(ISR_BUFFER_SIZE, UNIT));
+ BUILD_BUG_ON(!DEBUG_BUFFER_SIZE);
+ BUILD_BUG_ON(!IS_ALIGNED(DEBUG_BUFFER_SIZE, UNIT));
BUILD_BUG_ON((CRASH_BUFFER_SIZE / UNIT - 1) >
(GUC_LOG_CRASH_MASK >> GUC_LOG_CRASH_SHIFT));
- BUILD_BUG_ON((DPC_BUFFER_SIZE / UNIT - 1) >
- (GUC_LOG_DPC_MASK >> GUC_LOG_DPC_SHIFT));
- BUILD_BUG_ON((ISR_BUFFER_SIZE / UNIT - 1) >
- (GUC_LOG_ISR_MASK >> GUC_LOG_ISR_SHIFT));
+ BUILD_BUG_ON((DEBUG_BUFFER_SIZE / UNIT - 1) >
+ (GUC_LOG_DEBUG_MASK >> GUC_LOG_DEBUG_SHIFT));
flags = GUC_LOG_VALID |
GUC_LOG_NOTIFY_ON_HALF_FULL |
FLAG |
((CRASH_BUFFER_SIZE / UNIT - 1) << GUC_LOG_CRASH_SHIFT) |
- ((DPC_BUFFER_SIZE / UNIT - 1) << GUC_LOG_DPC_SHIFT) |
- ((ISR_BUFFER_SIZE / UNIT - 1) << GUC_LOG_ISR_SHIFT) |
+ ((DEBUG_BUFFER_SIZE / UNIT - 1) << GUC_LOG_DEBUG_SHIFT) |
(offset << GUC_LOG_BUF_ADDR_SHIFT);
#undef UNIT
@@ -331,6 +337,12 @@ int intel_guc_init(struct intel_guc *guc)
goto err_ct;
}
+ if (intel_guc_slpc_is_used(guc)) {
+ ret = intel_guc_slpc_init(&guc->slpc);
+ if (ret)
+ goto err_submission;
+ }
+
/* now that everything is perma-pinned, initialize the parameters */
guc_init_params(guc);
@@ -341,6 +353,8 @@ int intel_guc_init(struct intel_guc *guc)
return 0;
+err_submission:
+ intel_guc_submission_fini(guc);
err_ct:
intel_guc_ct_fini(&guc->ct);
err_ads:
@@ -363,6 +377,9 @@ void intel_guc_fini(struct intel_guc *guc)
i915_ggtt_disable_guc(gt->ggtt);
+ if (intel_guc_slpc_is_used(guc))
+ intel_guc_slpc_fini(&guc->slpc);
+
if (intel_guc_submission_is_used(guc))
intel_guc_submission_fini(guc);
@@ -376,29 +393,27 @@ void intel_guc_fini(struct intel_guc *guc)
/*
* This function implements the MMIO based host to GuC interface.
*/
-int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len,
+int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request, u32 len,
u32 *response_buf, u32 response_buf_size)
{
+ struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
struct intel_uncore *uncore = guc_to_gt(guc)->uncore;
- u32 status;
+ u32 header;
int i;
int ret;
GEM_BUG_ON(!len);
GEM_BUG_ON(len > guc->send_regs.count);
- /* We expect only action code */
- GEM_BUG_ON(*action & ~INTEL_GUC_MSG_CODE_MASK);
-
- /* If CT is available, we expect to use MMIO only during init/fini */
- GEM_BUG_ON(*action != INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER &&
- *action != INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER);
+ GEM_BUG_ON(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, request[0]) != GUC_HXG_ORIGIN_HOST);
+ GEM_BUG_ON(FIELD_GET(GUC_HXG_MSG_0_TYPE, request[0]) != GUC_HXG_TYPE_REQUEST);
mutex_lock(&guc->send_mutex);
intel_uncore_forcewake_get(uncore, guc->send_regs.fw_domains);
+retry:
for (i = 0; i < len; i++)
- intel_uncore_write(uncore, guc_send_reg(guc, i), action[i]);
+ intel_uncore_write(uncore, guc_send_reg(guc, i), request[i]);
intel_uncore_posting_read(uncore, guc_send_reg(guc, i - 1));
@@ -410,30 +425,74 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len,
*/
ret = __intel_wait_for_register_fw(uncore,
guc_send_reg(guc, 0),
- INTEL_GUC_MSG_TYPE_MASK,
- INTEL_GUC_MSG_TYPE_RESPONSE <<
- INTEL_GUC_MSG_TYPE_SHIFT,
- 10, 10, &status);
- /* If GuC explicitly returned an error, convert it to -EIO */
- if (!ret && !INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(status))
- ret = -EIO;
+ GUC_HXG_MSG_0_ORIGIN,
+ FIELD_PREP(GUC_HXG_MSG_0_ORIGIN,
+ GUC_HXG_ORIGIN_GUC),
+ 10, 10, &header);
+ if (unlikely(ret)) {
+timeout:
+ drm_err(&i915->drm, "mmio request %#x: no reply %x\n",
+ request[0], header);
+ goto out;
+ }
- if (ret) {
- DRM_ERROR("MMIO: GuC action %#x failed with error %d %#x\n",
- action[0], ret, status);
+ if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) == GUC_HXG_TYPE_NO_RESPONSE_BUSY) {
+#define done ({ header = intel_uncore_read(uncore, guc_send_reg(guc, 0)); \
+ FIELD_GET(GUC_HXG_MSG_0_ORIGIN, header) != GUC_HXG_ORIGIN_GUC || \
+ FIELD_GET(GUC_HXG_MSG_0_TYPE, header) != GUC_HXG_TYPE_NO_RESPONSE_BUSY; })
+
+ ret = wait_for(done, 1000);
+ if (unlikely(ret))
+ goto timeout;
+ if (unlikely(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, header) !=
+ GUC_HXG_ORIGIN_GUC))
+ goto proto;
+#undef done
+ }
+
+ if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) == GUC_HXG_TYPE_NO_RESPONSE_RETRY) {
+ u32 reason = FIELD_GET(GUC_HXG_RETRY_MSG_0_REASON, header);
+
+ drm_dbg(&i915->drm, "mmio request %#x: retrying, reason %u\n",
+ request[0], reason);
+ goto retry;
+ }
+
+ if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) == GUC_HXG_TYPE_RESPONSE_FAILURE) {
+ u32 hint = FIELD_GET(GUC_HXG_FAILURE_MSG_0_HINT, header);
+ u32 error = FIELD_GET(GUC_HXG_FAILURE_MSG_0_ERROR, header);
+
+ drm_err(&i915->drm, "mmio request %#x: failure %x/%u\n",
+ request[0], error, hint);
+ ret = -ENXIO;
+ goto out;
+ }
+
+ if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) != GUC_HXG_TYPE_RESPONSE_SUCCESS) {
+proto:
+ drm_err(&i915->drm, "mmio request %#x: unexpected reply %#x\n",
+ request[0], header);
+ ret = -EPROTO;
goto out;
}
if (response_buf) {
- int count = min(response_buf_size, guc->send_regs.count - 1);
+ int count = min(response_buf_size, guc->send_regs.count);
+
+ GEM_BUG_ON(!count);
- for (i = 0; i < count; i++)
+ response_buf[0] = header;
+
+ for (i = 1; i < count; i++)
response_buf[i] = intel_uncore_read(uncore,
- guc_send_reg(guc, i + 1));
- }
+ guc_send_reg(guc, i));
- /* Use data from the GuC response as our return value */
- ret = INTEL_GUC_MSG_TO_DATA(status);
+ /* Use number of copied dwords as our return value */
+ ret = count;
+ } else {
+ /* Use data from the GuC response as our return value */
+ ret = FIELD_GET(GUC_HXG_RESPONSE_MSG_0_DATA0, header);
+ }
out:
intel_uncore_forcewake_put(uncore, guc->send_regs.fw_domains);
@@ -487,65 +546,35 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset)
*/
int intel_guc_suspend(struct intel_guc *guc)
{
- struct intel_uncore *uncore = guc_to_gt(guc)->uncore;
int ret;
- u32 status;
u32 action[] = {
- INTEL_GUC_ACTION_ENTER_S_STATE,
- GUC_POWER_D1, /* any value greater than GUC_POWER_D0 */
+ INTEL_GUC_ACTION_RESET_CLIENT,
};
- /*
- * If GuC communication is enabled but submission is not supported,
- * we do not need to suspend the GuC.
- */
- if (!intel_guc_submission_is_used(guc) || !intel_guc_is_ready(guc))
+ if (!intel_guc_is_ready(guc))
return 0;
- /*
- * The ENTER_S_STATE action queues the save/restore operation in GuC FW
- * and then returns, so waiting on the H2G is not enough to guarantee
- * GuC is done. When all the processing is done, GuC writes
- * INTEL_GUC_SLEEP_STATE_SUCCESS to scratch register 14, so we can poll
- * on that. Note that GuC does not ensure that the value in the register
- * is different from INTEL_GUC_SLEEP_STATE_SUCCESS while the action is
- * in progress so we need to take care of that ourselves as well.
- */
-
- intel_uncore_write(uncore, SOFT_SCRATCH(14),
- INTEL_GUC_SLEEP_STATE_INVALID_MASK);
-
- ret = intel_guc_send(guc, action, ARRAY_SIZE(action));
- if (ret)
- return ret;
-
- ret = __intel_wait_for_register(uncore, SOFT_SCRATCH(14),
- INTEL_GUC_SLEEP_STATE_INVALID_MASK,
- 0, 0, 10, &status);
- if (ret)
- return ret;
-
- if (status != INTEL_GUC_SLEEP_STATE_SUCCESS) {
- DRM_ERROR("GuC failed to change sleep state. "
- "action=0x%x, err=%u\n",
- action[0], status);
- return -EIO;
+ if (intel_guc_submission_is_used(guc)) {
+ /*
+ * This H2G MMIO command tears down the GuC in two steps. First it will
+ * generate a G2H CTB for every active context indicating a reset. In
+ * practice the i915 shouldn't ever get a G2H as suspend should only be
+ * called when the GPU is idle. Next, it tears down the CTBs and this
+ * H2G MMIO command completes.
+ *
+ * Don't abort on a failure code from the GuC. Keep going and do the
+ * clean up in santize() and re-initialisation on resume and hopefully
+ * the error here won't be problematic.
+ */
+ ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0);
+ if (ret)
+ DRM_ERROR("GuC suspend: RESET_CLIENT action failed with error %d!\n", ret);
}
- return 0;
-}
-
-/**
- * intel_guc_reset_engine() - ask GuC to reset an engine
- * @guc: intel_guc structure
- * @engine: engine to be reset
- */
-int intel_guc_reset_engine(struct intel_guc *guc,
- struct intel_engine_cs *engine)
-{
- /* XXX: to be implemented with submission interface rework */
+ /* Signal that the GuC isn't running. */
+ intel_guc_sanitize(guc);
- return -ENODEV;
+ return 0;
}
/**
@@ -554,7 +583,12 @@ int intel_guc_reset_engine(struct intel_guc *guc,
*/
int intel_guc_resume(struct intel_guc *guc)
{
- /* XXX: to be implemented with submission interface rework */
+ /*
+ * NB: This function can still be called even if GuC submission is
+ * disabled, e.g. if GuC is enabled for HuC authentication only. Thus,
+ * if any code is later added here, it must be support doing nothing
+ * if submission is disabled (as per intel_guc_suspend).
+ */
return 0;
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 4abc59f6f3cd..2e27fe59786b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -6,12 +6,16 @@
#ifndef _INTEL_GUC_H_
#define _INTEL_GUC_H_
+#include <linux/xarray.h>
+#include <linux/delay.h>
+
#include "intel_uncore.h"
#include "intel_guc_fw.h"
#include "intel_guc_fwif.h"
#include "intel_guc_ct.h"
#include "intel_guc_log.h"
#include "intel_guc_reg.h"
+#include "intel_guc_slpc_types.h"
#include "intel_uc_fw.h"
#include "i915_utils.h"
#include "i915_vma.h"
@@ -27,24 +31,47 @@ struct intel_guc {
struct intel_uc_fw fw;
struct intel_guc_log log;
struct intel_guc_ct ct;
+ struct intel_guc_slpc slpc;
+
+ /* Global engine used to submit requests to GuC */
+ struct i915_sched_engine *sched_engine;
+ struct i915_request *stalled_request;
/* intel_guc_recv interrupt related state */
spinlock_t irq_lock;
unsigned int msg_enabled_mask;
+ atomic_t outstanding_submission_g2h;
+
struct {
void (*reset)(struct intel_guc *guc);
void (*enable)(struct intel_guc *guc);
void (*disable)(struct intel_guc *guc);
} interrupts;
+ /*
+ * contexts_lock protects the pool of free guc ids and a linked list of
+ * guc ids available to be stolen
+ */
+ spinlock_t contexts_lock;
+ struct ida guc_ids;
+ struct list_head guc_id_list;
+
+ bool submission_supported;
bool submission_selected;
+ bool rc_supported;
+ bool rc_selected;
struct i915_vma *ads_vma;
struct __guc_ads_blob *ads_blob;
+ u32 ads_regset_size;
+ u32 ads_golden_ctxt_size;
- struct i915_vma *stage_desc_pool;
- void *stage_desc_pool_vaddr;
+ struct i915_vma *lrc_desc_pool;
+ void *lrc_desc_pool_vaddr;
+
+ /* guc_id to intel_context lookup */
+ struct xarray context_lookup;
/* Control params for fw initialization */
u32 params[GUC_CTL_MAX_DWORDS];
@@ -74,7 +101,15 @@ static inline struct intel_guc *log_to_guc(struct intel_guc_log *log)
static
inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len)
{
- return intel_guc_ct_send(&guc->ct, action, len, NULL, 0);
+ return intel_guc_ct_send(&guc->ct, action, len, NULL, 0, 0);
+}
+
+static
+inline int intel_guc_send_nb(struct intel_guc *guc, const u32 *action, u32 len,
+ u32 g2h_len_dw)
+{
+ return intel_guc_ct_send(&guc->ct, action, len, NULL, 0,
+ MAKE_SEND_FLAGS(g2h_len_dw));
}
static inline int
@@ -82,7 +117,43 @@ intel_guc_send_and_receive(struct intel_guc *guc, const u32 *action, u32 len,
u32 *response_buf, u32 response_buf_size)
{
return intel_guc_ct_send(&guc->ct, action, len,
- response_buf, response_buf_size);
+ response_buf, response_buf_size, 0);
+}
+
+static inline int intel_guc_send_busy_loop(struct intel_guc *guc,
+ const u32 *action,
+ u32 len,
+ u32 g2h_len_dw,
+ bool loop)
+{
+ int err;
+ unsigned int sleep_period_ms = 1;
+ bool not_atomic = !in_atomic() && !irqs_disabled();
+
+ /*
+ * FIXME: Have caller pass in if we are in an atomic context to avoid
+ * using in_atomic(). It is likely safe here as we check for irqs
+ * disabled which basically all the spin locks in the i915 do but
+ * regardless this should be cleaned up.
+ */
+
+ /* No sleeping with spin locks, just busy loop */
+ might_sleep_if(loop && not_atomic);
+
+retry:
+ err = intel_guc_send_nb(guc, action, len, g2h_len_dw);
+ if (unlikely(err == -EBUSY && loop)) {
+ if (likely(not_atomic)) {
+ if (msleep_interruptible(sleep_period_ms))
+ return -EINTR;
+ sleep_period_ms = sleep_period_ms << 1;
+ } else {
+ cpu_relax();
+ }
+ goto retry;
+ }
+
+ return err;
}
static inline void intel_guc_to_host_event_handler(struct intel_guc *guc)
@@ -118,6 +189,7 @@ static inline u32 intel_guc_ggtt_offset(struct intel_guc *guc,
}
void intel_guc_init_early(struct intel_guc *guc);
+void intel_guc_init_late(struct intel_guc *guc);
void intel_guc_init_send_regs(struct intel_guc *guc);
void intel_guc_write_params(struct intel_guc *guc);
int intel_guc_init(struct intel_guc *guc);
@@ -160,9 +232,25 @@ static inline bool intel_guc_is_ready(struct intel_guc *guc)
return intel_guc_is_fw_running(guc) && intel_guc_ct_enabled(&guc->ct);
}
+static inline void intel_guc_reset_interrupts(struct intel_guc *guc)
+{
+ guc->interrupts.reset(guc);
+}
+
+static inline void intel_guc_enable_interrupts(struct intel_guc *guc)
+{
+ guc->interrupts.enable(guc);
+}
+
+static inline void intel_guc_disable_interrupts(struct intel_guc *guc)
+{
+ guc->interrupts.disable(guc);
+}
+
static inline int intel_guc_sanitize(struct intel_guc *guc)
{
intel_uc_fw_sanitize(&guc->fw);
+ intel_guc_disable_interrupts(guc);
intel_guc_ct_sanitize(&guc->ct);
guc->mmio_msg = 0;
@@ -183,8 +271,27 @@ static inline void intel_guc_disable_msg(struct intel_guc *guc, u32 mask)
spin_unlock_irq(&guc->irq_lock);
}
-int intel_guc_reset_engine(struct intel_guc *guc,
- struct intel_engine_cs *engine);
+int intel_guc_wait_for_idle(struct intel_guc *guc, long timeout);
+
+int intel_guc_deregister_done_process_msg(struct intel_guc *guc,
+ const u32 *msg, u32 len);
+int intel_guc_sched_done_process_msg(struct intel_guc *guc,
+ const u32 *msg, u32 len);
+int intel_guc_context_reset_process_msg(struct intel_guc *guc,
+ const u32 *msg, u32 len);
+int intel_guc_engine_failure_process_msg(struct intel_guc *guc,
+ const u32 *msg, u32 len);
+
+void intel_guc_find_hung_context(struct intel_engine_cs *engine);
+
+int intel_guc_global_policies_update(struct intel_guc *guc);
+
+void intel_guc_context_ban(struct intel_context *ce, struct i915_request *rq);
+
+void intel_guc_submission_reset_prepare(struct intel_guc *guc);
+void intel_guc_submission_reset(struct intel_guc *guc, bool stalled);
+void intel_guc_submission_reset_finish(struct intel_guc *guc);
+void intel_guc_submission_cancel_requests(struct intel_guc *guc);
void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index 9abfbc6edbd6..6926919bcac6 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -3,8 +3,11 @@
* Copyright © 2014-2019 Intel Corporation
*/
+#include <linux/bsearch.h>
+
#include "gt/intel_gt.h"
#include "gt/intel_lrc.h"
+#include "gt/shmem_utils.h"
#include "intel_guc_ads.h"
#include "intel_guc_fwif.h"
#include "intel_uc.h"
@@ -23,10 +26,15 @@
* | guc_policies |
* +---------------------------------------+
* | guc_gt_system_info |
- * +---------------------------------------+
- * | guc_clients_info |
- * +---------------------------------------+
- * | guc_ct_pool_entry[size] |
+ * +---------------------------------------+ <== static
+ * | guc_mmio_reg[countA] (engine 0.0) |
+ * | guc_mmio_reg[countB] (engine 0.1) |
+ * | guc_mmio_reg[countC] (engine 1.0) |
+ * | ... |
+ * +---------------------------------------+ <== dynamic
+ * | padding |
+ * +---------------------------------------+ <== 4K aligned
+ * | golden contexts |
* +---------------------------------------+
* | padding |
* +---------------------------------------+ <== 4K aligned
@@ -39,18 +47,49 @@ struct __guc_ads_blob {
struct guc_ads ads;
struct guc_policies policies;
struct guc_gt_system_info system_info;
- struct guc_clients_info clients_info;
- struct guc_ct_pool_entry ct_pool[GUC_CT_POOL_SIZE];
+ /* From here on, location is dynamic! Refer to above diagram. */
+ struct guc_mmio_reg regset[0];
} __packed;
+static u32 guc_ads_regset_size(struct intel_guc *guc)
+{
+ GEM_BUG_ON(!guc->ads_regset_size);
+ return guc->ads_regset_size;
+}
+
+static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc)
+{
+ return PAGE_ALIGN(guc->ads_golden_ctxt_size);
+}
+
static u32 guc_ads_private_data_size(struct intel_guc *guc)
{
return PAGE_ALIGN(guc->fw.private_data_size);
}
+static u32 guc_ads_regset_offset(struct intel_guc *guc)
+{
+ return offsetof(struct __guc_ads_blob, regset);
+}
+
+static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc)
+{
+ u32 offset;
+
+ offset = guc_ads_regset_offset(guc) +
+ guc_ads_regset_size(guc);
+
+ return PAGE_ALIGN(offset);
+}
+
static u32 guc_ads_private_data_offset(struct intel_guc *guc)
{
- return PAGE_ALIGN(sizeof(struct __guc_ads_blob));
+ u32 offset;
+
+ offset = guc_ads_golden_ctxt_offset(guc) +
+ guc_ads_golden_ctxt_size(guc);
+
+ return PAGE_ALIGN(offset);
}
static u32 guc_ads_blob_size(struct intel_guc *guc)
@@ -59,36 +98,66 @@ static u32 guc_ads_blob_size(struct intel_guc *guc)
guc_ads_private_data_size(guc);
}
-static void guc_policy_init(struct guc_policy *policy)
+static void guc_policies_init(struct intel_guc *guc, struct guc_policies *policies)
{
- policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US;
- policy->preemption_time = POLICY_DEFAULT_PREEMPTION_TIME_US;
- policy->fault_time = POLICY_DEFAULT_FAULT_TIME_US;
- policy->policy_flags = 0;
+ struct intel_gt *gt = guc_to_gt(guc);
+ struct drm_i915_private *i915 = gt->i915;
+
+ policies->dpc_promote_time = GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US;
+ policies->max_num_work_items = GLOBAL_POLICY_MAX_NUM_WI;
+
+ policies->global_flags = 0;
+ if (i915->params.reset < 2)
+ policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET;
+
+ policies->is_valid = 1;
}
-static void guc_policies_init(struct guc_policies *policies)
+void intel_guc_ads_print_policy_info(struct intel_guc *guc,
+ struct drm_printer *dp)
{
- struct guc_policy *policy;
- u32 p, i;
+ struct __guc_ads_blob *blob = guc->ads_blob;
- policies->dpc_promote_time = POLICY_DEFAULT_DPC_PROMOTE_TIME_US;
- policies->max_num_work_items = POLICY_MAX_NUM_WI;
+ if (unlikely(!blob))
+ return;
- for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) {
- for (i = 0; i < GUC_MAX_ENGINE_CLASSES; i++) {
- policy = &policies->policy[p][i];
+ drm_printf(dp, "Global scheduling policies:\n");
+ drm_printf(dp, " DPC promote time = %u\n", blob->policies.dpc_promote_time);
+ drm_printf(dp, " Max num work items = %u\n", blob->policies.max_num_work_items);
+ drm_printf(dp, " Flags = %u\n", blob->policies.global_flags);
+}
- guc_policy_init(policy);
- }
- }
+static int guc_action_policies_update(struct intel_guc *guc, u32 policy_offset)
+{
+ u32 action[] = {
+ INTEL_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE,
+ policy_offset
+ };
- policies->is_valid = 1;
+ return intel_guc_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true);
}
-static void guc_ct_pool_entries_init(struct guc_ct_pool_entry *pool, u32 num)
+int intel_guc_global_policies_update(struct intel_guc *guc)
{
- memset(pool, 0, num * sizeof(*pool));
+ struct __guc_ads_blob *blob = guc->ads_blob;
+ struct intel_gt *gt = guc_to_gt(guc);
+ intel_wakeref_t wakeref;
+ int ret;
+
+ if (!blob)
+ return -EOPNOTSUPP;
+
+ GEM_BUG_ON(!blob->ads.scheduler_policies);
+
+ guc_policies_init(guc, &blob->policies);
+
+ if (!intel_guc_is_ready(guc))
+ return 0;
+
+ with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref)
+ ret = guc_action_policies_update(guc, blob->ads.scheduler_policies);
+
+ return ret;
}
static void guc_mapping_table_init(struct intel_gt *gt,
@@ -113,53 +182,324 @@ static void guc_mapping_table_init(struct intel_gt *gt,
}
/*
- * The first 80 dwords of the register state context, containing the
- * execlists and ppgtt registers.
+ * The save/restore register list must be pre-calculated to a temporary
+ * buffer of driver defined size before it can be generated in place
+ * inside the ADS.
*/
-#define LR_HW_CONTEXT_SIZE (80 * sizeof(u32))
+#define MAX_MMIO_REGS 128 /* Arbitrary size, increase as needed */
+struct temp_regset {
+ struct guc_mmio_reg *registers;
+ u32 used;
+ u32 size;
+};
-static void __guc_ads_init(struct intel_guc *guc)
+static int guc_mmio_reg_cmp(const void *a, const void *b)
+{
+ const struct guc_mmio_reg *ra = a;
+ const struct guc_mmio_reg *rb = b;
+
+ return (int)ra->offset - (int)rb->offset;
+}
+
+static void guc_mmio_reg_add(struct temp_regset *regset,
+ u32 offset, u32 flags)
+{
+ u32 count = regset->used;
+ struct guc_mmio_reg reg = {
+ .offset = offset,
+ .flags = flags,
+ };
+ struct guc_mmio_reg *slot;
+
+ GEM_BUG_ON(count >= regset->size);
+
+ /*
+ * The mmio list is built using separate lists within the driver.
+ * It's possible that at some point we may attempt to add the same
+ * register more than once. Do not consider this an error; silently
+ * move on if the register is already in the list.
+ */
+ if (bsearch(&reg, regset->registers, count,
+ sizeof(reg), guc_mmio_reg_cmp))
+ return;
+
+ slot = &regset->registers[count];
+ regset->used++;
+ *slot = reg;
+
+ while (slot-- > regset->registers) {
+ GEM_BUG_ON(slot[0].offset == slot[1].offset);
+ if (slot[1].offset > slot[0].offset)
+ break;
+
+ swap(slot[1], slot[0]);
+ }
+}
+
+#define GUC_MMIO_REG_ADD(regset, reg, masked) \
+ guc_mmio_reg_add(regset, \
+ i915_mmio_reg_offset((reg)), \
+ (masked) ? GUC_REGSET_MASKED : 0)
+
+static void guc_mmio_regset_init(struct temp_regset *regset,
+ struct intel_engine_cs *engine)
+{
+ const u32 base = engine->mmio_base;
+ struct i915_wa_list *wal = &engine->wa_list;
+ struct i915_wa *wa;
+ unsigned int i;
+
+ regset->used = 0;
+
+ GUC_MMIO_REG_ADD(regset, RING_MODE_GEN7(base), true);
+ GUC_MMIO_REG_ADD(regset, RING_HWS_PGA(base), false);
+ GUC_MMIO_REG_ADD(regset, RING_IMR(base), false);
+
+ for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
+ GUC_MMIO_REG_ADD(regset, wa->reg, wa->masked_reg);
+
+ /* Be extra paranoid and include all whitelist registers. */
+ for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++)
+ GUC_MMIO_REG_ADD(regset,
+ RING_FORCE_TO_NONPRIV(base, i),
+ false);
+
+ /* add in local MOCS registers */
+ for (i = 0; i < GEN9_LNCFCMOCS_REG_COUNT; i++)
+ GUC_MMIO_REG_ADD(regset, GEN9_LNCFCMOCS(i), false);
+}
+
+static int guc_mmio_reg_state_query(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
- struct drm_i915_private *i915 = gt->i915;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+ struct temp_regset temp_set;
+ u32 total;
+
+ /*
+ * Need to actually build the list in order to filter out
+ * duplicates and other such data dependent constructions.
+ */
+ temp_set.size = MAX_MMIO_REGS;
+ temp_set.registers = kmalloc_array(temp_set.size,
+ sizeof(*temp_set.registers),
+ GFP_KERNEL);
+ if (!temp_set.registers)
+ return -ENOMEM;
+
+ total = 0;
+ for_each_engine(engine, gt, id) {
+ guc_mmio_regset_init(&temp_set, engine);
+ total += temp_set.used;
+ }
+
+ kfree(temp_set.registers);
+
+ return total * sizeof(struct guc_mmio_reg);
+}
+
+static void guc_mmio_reg_state_init(struct intel_guc *guc,
+ struct __guc_ads_blob *blob)
+{
+ struct intel_gt *gt = guc_to_gt(guc);
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+ struct temp_regset temp_set;
+ struct guc_mmio_reg_set *ads_reg_set;
+ u32 addr_ggtt, offset;
+ u8 guc_class;
+
+ offset = guc_ads_regset_offset(guc);
+ addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
+ temp_set.registers = (struct guc_mmio_reg *)(((u8 *)blob) + offset);
+ temp_set.size = guc->ads_regset_size / sizeof(temp_set.registers[0]);
+
+ for_each_engine(engine, gt, id) {
+ /* Class index is checked in class converter */
+ GEM_BUG_ON(engine->instance >= GUC_MAX_INSTANCES_PER_CLASS);
+
+ guc_class = engine_class_to_guc_class(engine->class);
+ ads_reg_set = &blob->ads.reg_state_list[guc_class][engine->instance];
+
+ guc_mmio_regset_init(&temp_set, engine);
+ if (!temp_set.used) {
+ ads_reg_set->address = 0;
+ ads_reg_set->count = 0;
+ continue;
+ }
+
+ ads_reg_set->address = addr_ggtt;
+ ads_reg_set->count = temp_set.used;
+
+ temp_set.size -= temp_set.used;
+ temp_set.registers += temp_set.used;
+ addr_ggtt += temp_set.used * sizeof(struct guc_mmio_reg);
+ }
+
+ GEM_BUG_ON(temp_set.size);
+}
+
+static void fill_engine_enable_masks(struct intel_gt *gt,
+ struct guc_gt_system_info *info)
+{
+ info->engine_enabled_masks[GUC_RENDER_CLASS] = 1;
+ info->engine_enabled_masks[GUC_BLITTER_CLASS] = 1;
+ info->engine_enabled_masks[GUC_VIDEO_CLASS] = VDBOX_MASK(gt);
+ info->engine_enabled_masks[GUC_VIDEOENHANCE_CLASS] = VEBOX_MASK(gt);
+}
+
+static int guc_prep_golden_context(struct intel_guc *guc,
+ struct __guc_ads_blob *blob)
+{
+ struct intel_gt *gt = guc_to_gt(guc);
+ u32 addr_ggtt, offset;
+ u32 total_size = 0, alloc_size, real_size;
+ u8 engine_class, guc_class;
+ struct guc_gt_system_info *info, local_info;
+
+ /*
+ * Reserve the memory for the golden contexts and point GuC at it but
+ * leave it empty for now. The context data will be filled in later
+ * once there is something available to put there.
+ *
+ * Note that the HWSP and ring context are not included.
+ *
+ * Note also that the storage must be pinned in the GGTT, so that the
+ * address won't change after GuC has been told where to find it. The
+ * GuC will also validate that the LRC base + size fall within the
+ * allowed GGTT range.
+ */
+ if (blob) {
+ offset = guc_ads_golden_ctxt_offset(guc);
+ addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
+ info = &blob->system_info;
+ } else {
+ memset(&local_info, 0, sizeof(local_info));
+ info = &local_info;
+ fill_engine_enable_masks(gt, info);
+ }
+
+ for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) {
+ if (engine_class == OTHER_CLASS)
+ continue;
+
+ guc_class = engine_class_to_guc_class(engine_class);
+
+ if (!info->engine_enabled_masks[guc_class])
+ continue;
+
+ real_size = intel_engine_context_size(gt, engine_class);
+ alloc_size = PAGE_ALIGN(real_size);
+ total_size += alloc_size;
+
+ if (!blob)
+ continue;
+
+ blob->ads.eng_state_size[guc_class] = real_size;
+ blob->ads.golden_context_lrca[guc_class] = addr_ggtt;
+ addr_ggtt += alloc_size;
+ }
+
+ if (!blob)
+ return total_size;
+
+ GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size);
+ return total_size;
+}
+
+static struct intel_engine_cs *find_engine_state(struct intel_gt *gt, u8 engine_class)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ for_each_engine(engine, gt, id) {
+ if (engine->class != engine_class)
+ continue;
+
+ if (!engine->default_state)
+ continue;
+
+ return engine;
+ }
+
+ return NULL;
+}
+
+static void guc_init_golden_context(struct intel_guc *guc)
+{
struct __guc_ads_blob *blob = guc->ads_blob;
- const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE;
- u32 base;
+ struct intel_engine_cs *engine;
+ struct intel_gt *gt = guc_to_gt(guc);
+ u32 addr_ggtt, offset;
+ u32 total_size = 0, alloc_size, real_size;
u8 engine_class, guc_class;
+ u8 *ptr;
- /* GuC scheduling policies */
- guc_policies_init(&blob->policies);
+ /* Skip execlist and PPGTT registers + HWSP */
+ const u32 lr_hw_context_size = 80 * sizeof(u32);
+ const u32 skip_size = LRC_PPHWSP_SZ * PAGE_SIZE +
+ lr_hw_context_size;
+
+ if (!intel_uc_uses_guc_submission(&gt->uc))
+ return;
+
+ GEM_BUG_ON(!blob);
/*
- * GuC expects a per-engine-class context image and size
- * (minus hwsp and ring context). The context image will be
- * used to reinitialize engines after a reset. It must exist
- * and be pinned in the GGTT, so that the address won't change after
- * we have told GuC where to find it. The context size will be used
- * to validate that the LRC base + size fall within allowed GGTT.
+ * Go back and fill in the golden context data now that it is
+ * available.
*/
+ offset = guc_ads_golden_ctxt_offset(guc);
+ addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
+ ptr = ((u8 *)blob) + offset;
+
for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) {
if (engine_class == OTHER_CLASS)
continue;
guc_class = engine_class_to_guc_class(engine_class);
- /*
- * TODO: Set context pointer to default state to allow
- * GuC to re-init guilty contexts after internal reset.
- */
- blob->ads.golden_context_lrca[guc_class] = 0;
- blob->ads.eng_state_size[guc_class] =
- intel_engine_context_size(guc_to_gt(guc),
- engine_class) -
- skipped_size;
+ if (!blob->system_info.engine_enabled_masks[guc_class])
+ continue;
+
+ real_size = intel_engine_context_size(gt, engine_class);
+ alloc_size = PAGE_ALIGN(real_size);
+ total_size += alloc_size;
+
+ engine = find_engine_state(gt, engine_class);
+ if (!engine) {
+ drm_err(&gt->i915->drm, "No engine state recorded for class %d!\n",
+ engine_class);
+ blob->ads.eng_state_size[guc_class] = 0;
+ blob->ads.golden_context_lrca[guc_class] = 0;
+ continue;
+ }
+
+ GEM_BUG_ON(blob->ads.eng_state_size[guc_class] != real_size);
+ GEM_BUG_ON(blob->ads.golden_context_lrca[guc_class] != addr_ggtt);
+ addr_ggtt += alloc_size;
+
+ shmem_read(engine->default_state, skip_size, ptr + skip_size,
+ real_size - skip_size);
+ ptr += alloc_size;
}
+ GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size);
+}
+
+static void __guc_ads_init(struct intel_guc *guc)
+{
+ struct intel_gt *gt = guc_to_gt(guc);
+ struct drm_i915_private *i915 = gt->i915;
+ struct __guc_ads_blob *blob = guc->ads_blob;
+ u32 base;
+
+ /* GuC scheduling policies */
+ guc_policies_init(guc, &blob->policies);
+
/* System info */
- blob->system_info.engine_enabled_masks[GUC_RENDER_CLASS] = 1;
- blob->system_info.engine_enabled_masks[GUC_BLITTER_CLASS] = 1;
- blob->system_info.engine_enabled_masks[GUC_VIDEO_CLASS] = VDBOX_MASK(gt);
- blob->system_info.engine_enabled_masks[GUC_VIDEOENHANCE_CLASS] = VEBOX_MASK(gt);
+ fill_engine_enable_masks(gt, &blob->system_info);
blob->system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_SLICE_ENABLED] =
hweight8(gt->info.sseu.slice_mask);
@@ -174,21 +514,19 @@ static void __guc_ads_init(struct intel_guc *guc)
GEN12_DOORBELLS_PER_SQIDI) + 1;
}
+ /* Golden contexts for re-initialising after a watchdog reset */
+ guc_prep_golden_context(guc, blob);
+
guc_mapping_table_init(guc_to_gt(guc), &blob->system_info);
base = intel_guc_ggtt_offset(guc, guc->ads_vma);
- /* Clients info */
- guc_ct_pool_entries_init(blob->ct_pool, ARRAY_SIZE(blob->ct_pool));
-
- blob->clients_info.clients_num = 1;
- blob->clients_info.ct_pool_addr = base + ptr_offset(blob, ct_pool);
- blob->clients_info.ct_pool_count = ARRAY_SIZE(blob->ct_pool);
-
/* ADS */
blob->ads.scheduler_policies = base + ptr_offset(blob, policies);
blob->ads.gt_system_info = base + ptr_offset(blob, system_info);
- blob->ads.clients_info = base + ptr_offset(blob, clients_info);
+
+ /* MMIO save/restore list */
+ guc_mmio_reg_state_init(guc, blob);
/* Private Data */
blob->ads.private_data = base + guc_ads_private_data_offset(guc);
@@ -210,6 +548,19 @@ int intel_guc_ads_create(struct intel_guc *guc)
GEM_BUG_ON(guc->ads_vma);
+ /* Need to calculate the reg state size dynamically: */
+ ret = guc_mmio_reg_state_query(guc);
+ if (ret < 0)
+ return ret;
+ guc->ads_regset_size = ret;
+
+ /* Likewise the golden contexts: */
+ ret = guc_prep_golden_context(guc, NULL);
+ if (ret < 0)
+ return ret;
+ guc->ads_golden_ctxt_size = ret;
+
+ /* Now the total size can be determined: */
size = guc_ads_blob_size(guc);
ret = intel_guc_allocate_and_map_vma(guc, size, &guc->ads_vma,
@@ -222,6 +573,18 @@ int intel_guc_ads_create(struct intel_guc *guc)
return 0;
}
+void intel_guc_ads_init_late(struct intel_guc *guc)
+{
+ /*
+ * The golden context setup requires the saved engine state from
+ * __engines_record_defaults(). However, that requires engines to be
+ * operational which means the ADS must already have been configured.
+ * Fortunately, the golden context state is not needed until a hang
+ * occurs, so it can be filled in during this late init phase.
+ */
+ guc_init_golden_context(guc);
+}
+
void intel_guc_ads_destroy(struct intel_guc *guc)
{
i915_vma_unpin_and_release(&guc->ads_vma, I915_VMA_RELEASE_MAP);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h
index b00d3ae1113a..3d85051d57e4 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h
@@ -7,9 +7,13 @@
#define _INTEL_GUC_ADS_H_
struct intel_guc;
+struct drm_printer;
int intel_guc_ads_create(struct intel_guc *guc);
void intel_guc_ads_destroy(struct intel_guc *guc);
+void intel_guc_ads_init_late(struct intel_guc *guc);
void intel_guc_ads_reset(struct intel_guc *guc);
+void intel_guc_ads_print_policy_info(struct intel_guc *guc,
+ struct drm_printer *p);
#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
index 8f7b148fef58..22b4733b55e2 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
@@ -3,6 +3,11 @@
* Copyright © 2016-2019 Intel Corporation
*/
+#include <linux/circ_buf.h>
+#include <linux/ktime.h>
+#include <linux/time64.h>
+#include <linux/timekeeping.h>
+
#include "i915_drv.h"
#include "intel_guc_ct.h"
#include "gt/intel_gt.h"
@@ -58,11 +63,17 @@ static inline struct drm_device *ct_to_drm(struct intel_guc_ct *ct)
* +--------+-----------------------------------------------+------+
*
* Size of each `CT Buffer`_ must be multiple of 4K.
- * As we don't expect too many messages, for now use minimum sizes.
+ * We don't expect too many messages in flight at any time, unless we are
+ * using the GuC submission. In that case each request requires a minimum
+ * 2 dwords which gives us a maximum 256 queue'd requests. Hopefully this
+ * enough space to avoid backpressure on the driver. We increase the size
+ * of the receive buffer (relative to the send) to ensure a G2H response
+ * CTB has a landing spot.
*/
#define CTB_DESC_SIZE ALIGN(sizeof(struct guc_ct_buffer_desc), SZ_2K)
#define CTB_H2G_BUFFER_SIZE (SZ_4K)
-#define CTB_G2H_BUFFER_SIZE (SZ_4K)
+#define CTB_G2H_BUFFER_SIZE (4 * CTB_H2G_BUFFER_SIZE)
+#define G2H_ROOM_BUFFER_SIZE (CTB_G2H_BUFFER_SIZE / 4)
struct ct_request {
struct list_head link;
@@ -98,66 +109,84 @@ void intel_guc_ct_init_early(struct intel_guc_ct *ct)
INIT_LIST_HEAD(&ct->requests.incoming);
INIT_WORK(&ct->requests.worker, ct_incoming_request_worker_func);
tasklet_setup(&ct->receive_tasklet, ct_receive_tasklet_func);
+ init_waitqueue_head(&ct->wq);
}
static inline const char *guc_ct_buffer_type_to_str(u32 type)
{
switch (type) {
- case INTEL_GUC_CT_BUFFER_TYPE_SEND:
+ case GUC_CTB_TYPE_HOST2GUC:
return "SEND";
- case INTEL_GUC_CT_BUFFER_TYPE_RECV:
+ case GUC_CTB_TYPE_GUC2HOST:
return "RECV";
default:
return "<invalid>";
}
}
-static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc,
- u32 cmds_addr, u32 size)
+static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc)
{
memset(desc, 0, sizeof(*desc));
- desc->addr = cmds_addr;
- desc->size = size;
- desc->owner = CTB_OWNER_HOST;
}
-static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb, u32 cmds_addr)
+static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb)
{
- guc_ct_buffer_desc_init(ctb->desc, cmds_addr, ctb->size);
+ u32 space;
+
+ ctb->broken = false;
+ ctb->tail = 0;
+ ctb->head = 0;
+ space = CIRC_SPACE(ctb->tail, ctb->head, ctb->size) - ctb->resv_space;
+ atomic_set(&ctb->space, space);
+
+ guc_ct_buffer_desc_init(ctb->desc);
}
static void guc_ct_buffer_init(struct intel_guc_ct_buffer *ctb,
struct guc_ct_buffer_desc *desc,
- u32 *cmds, u32 size)
+ u32 *cmds, u32 size_in_bytes, u32 resv_space)
{
- GEM_BUG_ON(size % 4);
+ GEM_BUG_ON(size_in_bytes % 4);
ctb->desc = desc;
ctb->cmds = cmds;
- ctb->size = size;
+ ctb->size = size_in_bytes / 4;
+ ctb->resv_space = resv_space / 4;
- guc_ct_buffer_reset(ctb, 0);
+ guc_ct_buffer_reset(ctb);
}
-static int guc_action_register_ct_buffer(struct intel_guc *guc,
- u32 desc_addr,
- u32 type)
+static int guc_action_register_ct_buffer(struct intel_guc *guc, u32 type,
+ u32 desc_addr, u32 buff_addr, u32 size)
{
- u32 action[] = {
- INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER,
- desc_addr,
- sizeof(struct guc_ct_buffer_desc),
- type
+ u32 request[HOST2GUC_REGISTER_CTB_REQUEST_MSG_LEN] = {
+ FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
+ FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
+ FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_HOST2GUC_REGISTER_CTB),
+ FIELD_PREP(HOST2GUC_REGISTER_CTB_REQUEST_MSG_1_SIZE, size / SZ_4K - 1) |
+ FIELD_PREP(HOST2GUC_REGISTER_CTB_REQUEST_MSG_1_TYPE, type),
+ FIELD_PREP(HOST2GUC_REGISTER_CTB_REQUEST_MSG_2_DESC_ADDR, desc_addr),
+ FIELD_PREP(HOST2GUC_REGISTER_CTB_REQUEST_MSG_3_BUFF_ADDR, buff_addr),
};
- /* Can't use generic send(), CT registration must go over MMIO */
- return intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0);
+ GEM_BUG_ON(type != GUC_CTB_TYPE_HOST2GUC && type != GUC_CTB_TYPE_GUC2HOST);
+ GEM_BUG_ON(size % SZ_4K);
+
+ /* CT registration must go over MMIO */
+ return intel_guc_send_mmio(guc, request, ARRAY_SIZE(request), NULL, 0);
}
-static int ct_register_buffer(struct intel_guc_ct *ct, u32 desc_addr, u32 type)
+static int ct_register_buffer(struct intel_guc_ct *ct, u32 type,
+ u32 desc_addr, u32 buff_addr, u32 size)
{
- int err = guc_action_register_ct_buffer(ct_to_guc(ct), desc_addr, type);
+ int err;
+
+ err = i915_inject_probe_error(guc_to_gt(ct_to_guc(ct))->i915, -ENXIO);
+ if (unlikely(err))
+ return err;
+ err = guc_action_register_ct_buffer(ct_to_guc(ct), type,
+ desc_addr, buff_addr, size);
if (unlikely(err))
CT_ERROR(ct, "Failed to register %s buffer (err=%d)\n",
guc_ct_buffer_type_to_str(type), err);
@@ -166,14 +195,17 @@ static int ct_register_buffer(struct intel_guc_ct *ct, u32 desc_addr, u32 type)
static int guc_action_deregister_ct_buffer(struct intel_guc *guc, u32 type)
{
- u32 action[] = {
- INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER,
- CTB_OWNER_HOST,
- type
+ u32 request[HOST2GUC_DEREGISTER_CTB_REQUEST_MSG_LEN] = {
+ FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) |
+ FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) |
+ FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_HOST2GUC_DEREGISTER_CTB),
+ FIELD_PREP(HOST2GUC_DEREGISTER_CTB_REQUEST_MSG_1_TYPE, type),
};
- /* Can't use generic send(), CT deregistration must go over MMIO */
- return intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0);
+ GEM_BUG_ON(type != GUC_CTB_TYPE_HOST2GUC && type != GUC_CTB_TYPE_GUC2HOST);
+
+ /* CT deregistration must go over MMIO */
+ return intel_guc_send_mmio(guc, request, ARRAY_SIZE(request), NULL, 0);
}
static int ct_deregister_buffer(struct intel_guc_ct *ct, u32 type)
@@ -200,10 +232,15 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
struct guc_ct_buffer_desc *desc;
u32 blob_size;
u32 cmds_size;
+ u32 resv_space;
void *blob;
u32 *cmds;
int err;
+ err = i915_inject_probe_error(guc_to_gt(guc)->i915, -ENXIO);
+ if (err)
+ return err;
+
GEM_BUG_ON(ct->vma);
blob_size = 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE + CTB_G2H_BUFFER_SIZE;
@@ -220,19 +257,23 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
desc = blob;
cmds = blob + 2 * CTB_DESC_SIZE;
cmds_size = CTB_H2G_BUFFER_SIZE;
- CT_DEBUG(ct, "%s desc %#tx cmds %#tx size %u\n", "send",
- ptrdiff(desc, blob), ptrdiff(cmds, blob), cmds_size);
+ resv_space = 0;
+ CT_DEBUG(ct, "%s desc %#tx cmds %#tx size %u/%u\n", "send",
+ ptrdiff(desc, blob), ptrdiff(cmds, blob), cmds_size,
+ resv_space);
- guc_ct_buffer_init(&ct->ctbs.send, desc, cmds, cmds_size);
+ guc_ct_buffer_init(&ct->ctbs.send, desc, cmds, cmds_size, resv_space);
/* store pointers to desc and cmds for recv ctb */
desc = blob + CTB_DESC_SIZE;
cmds = blob + 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE;
cmds_size = CTB_G2H_BUFFER_SIZE;
- CT_DEBUG(ct, "%s desc %#tx cmds %#tx size %u\n", "recv",
- ptrdiff(desc, blob), ptrdiff(cmds, blob), cmds_size);
+ resv_space = G2H_ROOM_BUFFER_SIZE;
+ CT_DEBUG(ct, "%s desc %#tx cmds %#tx size %u/%u\n", "recv",
+ ptrdiff(desc, blob), ptrdiff(cmds, blob), cmds_size,
+ resv_space);
- guc_ct_buffer_init(&ct->ctbs.recv, desc, cmds, cmds_size);
+ guc_ct_buffer_init(&ct->ctbs.recv, desc, cmds, cmds_size, resv_space);
return 0;
}
@@ -261,7 +302,7 @@ void intel_guc_ct_fini(struct intel_guc_ct *ct)
int intel_guc_ct_enable(struct intel_guc_ct *ct)
{
struct intel_guc *guc = ct_to_guc(ct);
- u32 base, cmds;
+ u32 base, desc, cmds;
void *blob;
int err;
@@ -277,32 +318,36 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
GEM_BUG_ON(blob != ct->ctbs.send.desc);
/* (re)initialize descriptors */
- cmds = base + ptrdiff(ct->ctbs.send.cmds, blob);
- guc_ct_buffer_reset(&ct->ctbs.send, cmds);
-
- cmds = base + ptrdiff(ct->ctbs.recv.cmds, blob);
- guc_ct_buffer_reset(&ct->ctbs.recv, cmds);
+ guc_ct_buffer_reset(&ct->ctbs.send);
+ guc_ct_buffer_reset(&ct->ctbs.recv);
/*
* Register both CT buffers starting with RECV buffer.
* Descriptors are in first half of the blob.
*/
- err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs.recv.desc, blob),
- INTEL_GUC_CT_BUFFER_TYPE_RECV);
+ desc = base + ptrdiff(ct->ctbs.recv.desc, blob);
+ cmds = base + ptrdiff(ct->ctbs.recv.cmds, blob);
+ err = ct_register_buffer(ct, GUC_CTB_TYPE_GUC2HOST,
+ desc, cmds, ct->ctbs.recv.size * 4);
+
if (unlikely(err))
goto err_out;
- err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs.send.desc, blob),
- INTEL_GUC_CT_BUFFER_TYPE_SEND);
+ desc = base + ptrdiff(ct->ctbs.send.desc, blob);
+ cmds = base + ptrdiff(ct->ctbs.send.cmds, blob);
+ err = ct_register_buffer(ct, GUC_CTB_TYPE_HOST2GUC,
+ desc, cmds, ct->ctbs.send.size * 4);
+
if (unlikely(err))
goto err_deregister;
ct->enabled = true;
+ ct->stall_time = KTIME_MAX;
return 0;
err_deregister:
- ct_deregister_buffer(ct, INTEL_GUC_CT_BUFFER_TYPE_RECV);
+ ct_deregister_buffer(ct, GUC_CTB_TYPE_GUC2HOST);
err_out:
CT_PROBE_ERROR(ct, "Failed to enable CTB (%pe)\n", ERR_PTR(err));
return err;
@@ -321,8 +366,8 @@ void intel_guc_ct_disable(struct intel_guc_ct *ct)
ct->enabled = false;
if (intel_guc_is_fw_running(guc)) {
- ct_deregister_buffer(ct, INTEL_GUC_CT_BUFFER_TYPE_SEND);
- ct_deregister_buffer(ct, INTEL_GUC_CT_BUFFER_TYPE_RECV);
+ ct_deregister_buffer(ct, GUC_CTB_TYPE_HOST2GUC);
+ ct_deregister_buffer(ct, GUC_CTB_TYPE_GUC2HOST);
}
}
@@ -354,81 +399,63 @@ static void write_barrier(struct intel_guc_ct *ct)
}
}
-/**
- * DOC: CTB Host to GuC request
- *
- * Format of the CTB Host to GuC request message is as follows::
- *
- * +------------+---------+---------+---------+---------+
- * | msg[0] | [1] | [2] | ... | [n-1] |
- * +------------+---------+---------+---------+---------+
- * | MESSAGE | MESSAGE PAYLOAD |
- * + HEADER +---------+---------+---------+---------+
- * | | 0 | 1 | ... | n |
- * +============+=========+=========+=========+=========+
- * | len >= 1 | FENCE | request specific data |
- * +------+-----+---------+---------+---------+---------+
- *
- * ^-----------------len-------------------^
- */
-
static int ct_write(struct intel_guc_ct *ct,
const u32 *action,
u32 len /* in dwords */,
- u32 fence)
+ u32 fence, u32 flags)
{
struct intel_guc_ct_buffer *ctb = &ct->ctbs.send;
struct guc_ct_buffer_desc *desc = ctb->desc;
- u32 head = desc->head;
- u32 tail = desc->tail;
+ u32 tail = ctb->tail;
u32 size = ctb->size;
- u32 used;
u32 header;
+ u32 hxg;
+ u32 type;
u32 *cmds = ctb->cmds;
unsigned int i;
- if (unlikely(desc->is_in_error))
- return -EPIPE;
-
- if (unlikely(!IS_ALIGNED(head | tail, 4) ||
- (tail | head) >= size))
+ if (unlikely(desc->status))
goto corrupted;
- /* later calculations will be done in dwords */
- head /= 4;
- tail /= 4;
- size /= 4;
-
- /*
- * tail == head condition indicates empty. GuC FW does not support
- * using up the entire buffer to get tail == head meaning full.
- */
- if (tail < head)
- used = (size - head) + tail;
- else
- used = tail - head;
+ GEM_BUG_ON(tail > size);
- /* make sure there is a space including extra dw for the fence */
- if (unlikely(used + len + 1 >= size))
- return -ENOSPC;
+#ifdef CONFIG_DRM_I915_DEBUG_GUC
+ if (unlikely(tail != READ_ONCE(desc->tail))) {
+ CT_ERROR(ct, "Tail was modified %u != %u\n",
+ desc->tail, tail);
+ desc->status |= GUC_CTB_STATUS_MISMATCH;
+ goto corrupted;
+ }
+ if (unlikely(READ_ONCE(desc->head) >= size)) {
+ CT_ERROR(ct, "Invalid head offset %u >= %u)\n",
+ desc->head, size);
+ desc->status |= GUC_CTB_STATUS_OVERFLOW;
+ goto corrupted;
+ }
+#endif
/*
- * Write the message. The format is the following:
- * DW0: header (including action code)
- * DW1: fence
- * DW2+: action data
+ * dw0: CT header (including fence)
+ * dw1: HXG header (including action code)
+ * dw2+: action data
*/
- header = (len << GUC_CT_MSG_LEN_SHIFT) |
- GUC_CT_MSG_SEND_STATUS |
- (action[0] << GUC_CT_MSG_ACTION_SHIFT);
+ header = FIELD_PREP(GUC_CTB_MSG_0_FORMAT, GUC_CTB_FORMAT_HXG) |
+ FIELD_PREP(GUC_CTB_MSG_0_NUM_DWORDS, len) |
+ FIELD_PREP(GUC_CTB_MSG_0_FENCE, fence);
- CT_DEBUG(ct, "writing %*ph %*ph %*ph\n",
- 4, &header, 4, &fence, 4 * (len - 1), &action[1]);
+ type = (flags & INTEL_GUC_CT_SEND_NB) ? GUC_HXG_TYPE_EVENT :
+ GUC_HXG_TYPE_REQUEST;
+ hxg = FIELD_PREP(GUC_HXG_MSG_0_TYPE, type) |
+ FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION |
+ GUC_HXG_EVENT_MSG_0_DATA0, action[0]);
+
+ CT_DEBUG(ct, "writing (tail %u) %*ph %*ph %*ph\n",
+ tail, 4, &header, 4, &hxg, 4 * (len - 1), &action[1]);
cmds[tail] = header;
tail = (tail + 1) % size;
- cmds[tail] = fence;
+ cmds[tail] = hxg;
tail = (tail + 1) % size;
for (i = 1; i < len; i++) {
@@ -443,14 +470,20 @@ static int ct_write(struct intel_guc_ct *ct,
*/
write_barrier(ct);
- /* now update desc tail (back in bytes) */
- desc->tail = tail * 4;
+ /* update local copies */
+ ctb->tail = tail;
+ GEM_BUG_ON(atomic_read(&ctb->space) < len + GUC_CTB_HDR_LEN);
+ atomic_sub(len + GUC_CTB_HDR_LEN, &ctb->space);
+
+ /* now update descriptor */
+ WRITE_ONCE(desc->tail, tail);
+
return 0;
corrupted:
- CT_ERROR(ct, "Corrupted descriptor addr=%#x head=%u tail=%u size=%u\n",
- desc->addr, desc->head, desc->tail, desc->size);
- desc->is_in_error = 1;
+ CT_ERROR(ct, "Corrupted descriptor head=%u tail=%u status=%#x\n",
+ desc->head, desc->tail, desc->status);
+ ctb->broken = true;
return -EPIPE;
}
@@ -459,7 +492,7 @@ corrupted:
* @req: pointer to pending request
* @status: placeholder for status
*
- * For each sent request, Guc shall send bac CT response message.
+ * For each sent request, GuC shall send back CT response message.
* Our message handler will update status of tracked request once
* response message with given fence is received. Wait here and
* check for valid response status value.
@@ -475,12 +508,18 @@ static int wait_for_ct_request_update(struct ct_request *req, u32 *status)
/*
* Fast commands should complete in less than 10us, so sample quickly
* up to that length of time, then switch to a slower sleep-wait loop.
- * No GuC command should ever take longer than 10ms.
+ * No GuC command should ever take longer than 10ms but many GuC
+ * commands can be inflight at time, so use a 1s timeout on the slower
+ * sleep-wait loop.
*/
-#define done INTEL_GUC_MSG_IS_RESPONSE(READ_ONCE(req->status))
- err = wait_for_us(done, 10);
+#define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10
+#define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000
+#define done \
+ (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
+ GUC_HXG_ORIGIN_GUC)
+ err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS);
if (err)
- err = wait_for(done, 10);
+ err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS);
#undef done
if (unlikely(err))
@@ -490,6 +529,131 @@ static int wait_for_ct_request_update(struct ct_request *req, u32 *status)
return err;
}
+#define GUC_CTB_TIMEOUT_MS 1500
+static inline bool ct_deadlocked(struct intel_guc_ct *ct)
+{
+ long timeout = GUC_CTB_TIMEOUT_MS;
+ bool ret = ktime_ms_delta(ktime_get(), ct->stall_time) > timeout;
+
+ if (unlikely(ret)) {
+ struct guc_ct_buffer_desc *send = ct->ctbs.send.desc;
+ struct guc_ct_buffer_desc *recv = ct->ctbs.send.desc;
+
+ CT_ERROR(ct, "Communication stalled for %lld ms, desc status=%#x,%#x\n",
+ ktime_ms_delta(ktime_get(), ct->stall_time),
+ send->status, recv->status);
+ ct->ctbs.send.broken = true;
+ }
+
+ return ret;
+}
+
+static inline bool g2h_has_room(struct intel_guc_ct *ct, u32 g2h_len_dw)
+{
+ struct intel_guc_ct_buffer *ctb = &ct->ctbs.recv;
+
+ /*
+ * We leave a certain amount of space in the G2H CTB buffer for
+ * unexpected G2H CTBs (e.g. logging, engine hang, etc...)
+ */
+ return !g2h_len_dw || atomic_read(&ctb->space) >= g2h_len_dw;
+}
+
+static inline void g2h_reserve_space(struct intel_guc_ct *ct, u32 g2h_len_dw)
+{
+ lockdep_assert_held(&ct->ctbs.send.lock);
+
+ GEM_BUG_ON(!g2h_has_room(ct, g2h_len_dw));
+
+ if (g2h_len_dw)
+ atomic_sub(g2h_len_dw, &ct->ctbs.recv.space);
+}
+
+static inline void g2h_release_space(struct intel_guc_ct *ct, u32 g2h_len_dw)
+{
+ atomic_add(g2h_len_dw, &ct->ctbs.recv.space);
+}
+
+static inline bool h2g_has_room(struct intel_guc_ct *ct, u32 len_dw)
+{
+ struct intel_guc_ct_buffer *ctb = &ct->ctbs.send;
+ struct guc_ct_buffer_desc *desc = ctb->desc;
+ u32 head;
+ u32 space;
+
+ if (atomic_read(&ctb->space) >= len_dw)
+ return true;
+
+ head = READ_ONCE(desc->head);
+ if (unlikely(head > ctb->size)) {
+ CT_ERROR(ct, "Invalid head offset %u >= %u)\n",
+ head, ctb->size);
+ desc->status |= GUC_CTB_STATUS_OVERFLOW;
+ ctb->broken = true;
+ return false;
+ }
+
+ space = CIRC_SPACE(ctb->tail, head, ctb->size);
+ atomic_set(&ctb->space, space);
+
+ return space >= len_dw;
+}
+
+static int has_room_nb(struct intel_guc_ct *ct, u32 h2g_dw, u32 g2h_dw)
+{
+ lockdep_assert_held(&ct->ctbs.send.lock);
+
+ if (unlikely(!h2g_has_room(ct, h2g_dw) || !g2h_has_room(ct, g2h_dw))) {
+ if (ct->stall_time == KTIME_MAX)
+ ct->stall_time = ktime_get();
+
+ if (unlikely(ct_deadlocked(ct)))
+ return -EPIPE;
+ else
+ return -EBUSY;
+ }
+
+ ct->stall_time = KTIME_MAX;
+ return 0;
+}
+
+#define G2H_LEN_DW(f) ({ \
+ typeof(f) f_ = (f); \
+ FIELD_GET(INTEL_GUC_CT_SEND_G2H_DW_MASK, f_) ? \
+ FIELD_GET(INTEL_GUC_CT_SEND_G2H_DW_MASK, f_) + \
+ GUC_CTB_HXG_MSG_MIN_LEN : 0; \
+})
+static int ct_send_nb(struct intel_guc_ct *ct,
+ const u32 *action,
+ u32 len,
+ u32 flags)
+{
+ struct intel_guc_ct_buffer *ctb = &ct->ctbs.send;
+ unsigned long spin_flags;
+ u32 g2h_len_dw = G2H_LEN_DW(flags);
+ u32 fence;
+ int ret;
+
+ spin_lock_irqsave(&ctb->lock, spin_flags);
+
+ ret = has_room_nb(ct, len + GUC_CTB_HDR_LEN, g2h_len_dw);
+ if (unlikely(ret))
+ goto out;
+
+ fence = ct_get_next_fence(ct);
+ ret = ct_write(ct, action, len, fence, flags);
+ if (unlikely(ret))
+ goto out;
+
+ g2h_reserve_space(ct, g2h_len_dw);
+ intel_guc_notify(ct_to_guc(ct));
+
+out:
+ spin_unlock_irqrestore(&ctb->lock, spin_flags);
+
+ return ret;
+}
+
static int ct_send(struct intel_guc_ct *ct,
const u32 *action,
u32 len,
@@ -497,8 +661,10 @@ static int ct_send(struct intel_guc_ct *ct,
u32 response_buf_size,
u32 *status)
{
+ struct intel_guc_ct_buffer *ctb = &ct->ctbs.send;
struct ct_request request;
unsigned long flags;
+ unsigned int sleep_period_ms = 1;
u32 fence;
int err;
@@ -506,8 +672,33 @@ static int ct_send(struct intel_guc_ct *ct,
GEM_BUG_ON(!len);
GEM_BUG_ON(len & ~GUC_CT_MSG_LEN_MASK);
GEM_BUG_ON(!response_buf && response_buf_size);
+ might_sleep();
+
+ /*
+ * We use a lazy spin wait loop here as we believe that if the CT
+ * buffers are sized correctly the flow control condition should be
+ * rare. Reserving the maximum size in the G2H credits as we don't know
+ * how big the response is going to be.
+ */
+retry:
+ spin_lock_irqsave(&ctb->lock, flags);
+ if (unlikely(!h2g_has_room(ct, len + GUC_CTB_HDR_LEN) ||
+ !g2h_has_room(ct, GUC_CTB_HXG_MSG_MAX_LEN))) {
+ if (ct->stall_time == KTIME_MAX)
+ ct->stall_time = ktime_get();
+ spin_unlock_irqrestore(&ctb->lock, flags);
+
+ if (unlikely(ct_deadlocked(ct)))
+ return -EPIPE;
+
+ if (msleep_interruptible(sleep_period_ms))
+ return -EINTR;
+ sleep_period_ms = sleep_period_ms << 1;
+
+ goto retry;
+ }
- spin_lock_irqsave(&ct->ctbs.send.lock, flags);
+ ct->stall_time = KTIME_MAX;
fence = ct_get_next_fence(ct);
request.fence = fence;
@@ -519,9 +710,10 @@ static int ct_send(struct intel_guc_ct *ct,
list_add_tail(&request.link, &ct->requests.pending);
spin_unlock(&ct->requests.lock);
- err = ct_write(ct, action, len, fence);
+ err = ct_write(ct, action, len, fence, 0);
+ g2h_reserve_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
- spin_unlock_irqrestore(&ct->ctbs.send.lock, flags);
+ spin_unlock_irqrestore(&ctb->lock, flags);
if (unlikely(err))
goto unlink;
@@ -529,24 +721,25 @@ static int ct_send(struct intel_guc_ct *ct,
intel_guc_notify(ct_to_guc(ct));
err = wait_for_ct_request_update(&request, status);
+ g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
if (unlikely(err))
goto unlink;
- if (!INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(*status)) {
+ if (FIELD_GET(GUC_HXG_MSG_0_TYPE, *status) != GUC_HXG_TYPE_RESPONSE_SUCCESS) {
err = -EIO;
goto unlink;
}
if (response_buf) {
/* There shall be no data in the status */
- WARN_ON(INTEL_GUC_MSG_TO_DATA(request.status));
+ WARN_ON(FIELD_GET(GUC_HXG_RESPONSE_MSG_0_DATA0, request.status));
/* Return actual response len */
err = request.response_len;
} else {
/* There shall be no response payload */
WARN_ON(request.response_len);
/* Return data decoded from the status dword */
- err = INTEL_GUC_MSG_TO_DATA(*status);
+ err = FIELD_GET(GUC_HXG_RESPONSE_MSG_0_DATA0, *status);
}
unlink:
@@ -561,16 +754,25 @@ unlink:
* Command Transport (CT) buffer based GuC send function.
*/
int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len,
- u32 *response_buf, u32 response_buf_size)
+ u32 *response_buf, u32 response_buf_size, u32 flags)
{
u32 status = ~0; /* undefined */
int ret;
if (unlikely(!ct->enabled)) {
- WARN(1, "Unexpected send: action=%#x\n", *action);
+ struct intel_guc *guc = ct_to_guc(ct);
+ struct intel_uc *uc = container_of(guc, struct intel_uc, guc);
+
+ WARN(!uc->reset_in_progress, "Unexpected send: action=%#x\n", *action);
return -ENODEV;
}
+ if (unlikely(ct->ctbs.send.broken))
+ return -EPIPE;
+
+ if (flags & INTEL_GUC_CT_SEND_NB)
+ return ct_send_nb(ct, action, len, flags);
+
ret = ct_send(ct, action, len, response_buf, response_buf_size, &status);
if (unlikely(ret < 0)) {
CT_ERROR(ct, "Sending action %#x failed (err=%d status=%#X)\n",
@@ -583,21 +785,6 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len,
return ret;
}
-static inline unsigned int ct_header_get_len(u32 header)
-{
- return (header >> GUC_CT_MSG_LEN_SHIFT) & GUC_CT_MSG_LEN_MASK;
-}
-
-static inline unsigned int ct_header_get_action(u32 header)
-{
- return (header >> GUC_CT_MSG_ACTION_SHIFT) & GUC_CT_MSG_ACTION_MASK;
-}
-
-static inline bool ct_header_is_response(u32 header)
-{
- return !!(header & GUC_CT_MSG_IS_RESPONSE);
-}
-
static struct ct_incoming_msg *ct_alloc_msg(u32 num_dwords)
{
struct ct_incoming_msg *msg;
@@ -621,8 +808,8 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg)
{
struct intel_guc_ct_buffer *ctb = &ct->ctbs.recv;
struct guc_ct_buffer_desc *desc = ctb->desc;
- u32 head = desc->head;
- u32 tail = desc->tail;
+ u32 head = ctb->head;
+ u32 tail = READ_ONCE(desc->tail);
u32 size = ctb->size;
u32 *cmds = ctb->cmds;
s32 available;
@@ -630,17 +817,28 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg)
unsigned int i;
u32 header;
- if (unlikely(desc->is_in_error))
+ if (unlikely(ctb->broken))
return -EPIPE;
- if (unlikely(!IS_ALIGNED(head | tail, 4) ||
- (tail | head) >= size))
+ if (unlikely(desc->status))
goto corrupted;
- /* later calculations will be done in dwords */
- head /= 4;
- tail /= 4;
- size /= 4;
+ GEM_BUG_ON(head > size);
+
+#ifdef CONFIG_DRM_I915_DEBUG_GUC
+ if (unlikely(head != READ_ONCE(desc->head))) {
+ CT_ERROR(ct, "Head was modified %u != %u\n",
+ desc->head, head);
+ desc->status |= GUC_CTB_STATUS_MISMATCH;
+ goto corrupted;
+ }
+#endif
+ if (unlikely(tail >= size)) {
+ CT_ERROR(ct, "Invalid tail offset %u >= %u)\n",
+ tail, size);
+ desc->status |= GUC_CTB_STATUS_OVERFLOW;
+ goto corrupted;
+ }
/* tail == head condition indicates empty */
available = tail - head;
@@ -652,14 +850,14 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg)
/* beware of buffer wrap case */
if (unlikely(available < 0))
available += size;
- CT_DEBUG(ct, "available %d (%u:%u)\n", available, head, tail);
+ CT_DEBUG(ct, "available %d (%u:%u:%u)\n", available, head, tail, size);
GEM_BUG_ON(available < 0);
header = cmds[head];
head = (head + 1) % size;
/* message len with header */
- len = ct_header_get_len(header) + 1;
+ len = FIELD_GET(GUC_CTB_MSG_0_NUM_DWORDS, header) + GUC_CTB_MSG_MIN_LEN;
if (unlikely(len > (u32)available)) {
CT_ERROR(ct, "Incomplete message %*ph %*ph %*ph\n",
4, &header,
@@ -667,6 +865,7 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg)
size - head : available - 1), &cmds[head],
4 * (head + available - 1 > size ?
available - 1 - size + head : 0), &cmds[0]);
+ desc->status |= GUC_CTB_STATUS_UNDERFLOW;
goto corrupted;
}
@@ -689,65 +888,39 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg)
}
CT_DEBUG(ct, "received %*ph\n", 4 * len, (*msg)->msg);
- desc->head = head * 4;
+ /* update local copies */
+ ctb->head = head;
+
+ /* now update descriptor */
+ WRITE_ONCE(desc->head, head);
+
return available - len;
corrupted:
- CT_ERROR(ct, "Corrupted descriptor addr=%#x head=%u tail=%u size=%u\n",
- desc->addr, desc->head, desc->tail, desc->size);
- desc->is_in_error = 1;
+ CT_ERROR(ct, "Corrupted descriptor head=%u tail=%u status=%#x\n",
+ desc->head, desc->tail, desc->status);
+ ctb->broken = true;
return -EPIPE;
}
-/**
- * DOC: CTB GuC to Host response
- *
- * Format of the CTB GuC to Host response message is as follows::
- *
- * +------------+---------+---------+---------+---------+---------+
- * | msg[0] | [1] | [2] | [3] | ... | [n-1] |
- * +------------+---------+---------+---------+---------+---------+
- * | MESSAGE | MESSAGE PAYLOAD |
- * + HEADER +---------+---------+---------+---------+---------+
- * | | 0 | 1 | 2 | ... | n |
- * +============+=========+=========+=========+=========+=========+
- * | len >= 2 | FENCE | STATUS | response specific data |
- * +------+-----+---------+---------+---------+---------+---------+
- *
- * ^-----------------------len-----------------------^
- */
-
static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *response)
{
- u32 header = response->msg[0];
- u32 len = ct_header_get_len(header);
- u32 fence;
- u32 status;
- u32 datalen;
+ u32 len = FIELD_GET(GUC_CTB_MSG_0_NUM_DWORDS, response->msg[0]);
+ u32 fence = FIELD_GET(GUC_CTB_MSG_0_FENCE, response->msg[0]);
+ const u32 *hxg = &response->msg[GUC_CTB_MSG_MIN_LEN];
+ const u32 *data = &hxg[GUC_HXG_MSG_MIN_LEN];
+ u32 datalen = len - GUC_HXG_MSG_MIN_LEN;
struct ct_request *req;
unsigned long flags;
bool found = false;
int err = 0;
- GEM_BUG_ON(!ct_header_is_response(header));
-
- /* Response payload shall at least include fence and status */
- if (unlikely(len < 2)) {
- CT_ERROR(ct, "Corrupted response (len %u)\n", len);
- return -EPROTO;
- }
-
- fence = response->msg[1];
- status = response->msg[2];
- datalen = len - 2;
-
- /* Format of the status follows RESPONSE message */
- if (unlikely(!INTEL_GUC_MSG_IS_RESPONSE(status))) {
- CT_ERROR(ct, "Corrupted response (status %#x)\n", status);
- return -EPROTO;
- }
+ GEM_BUG_ON(len < GUC_HXG_MSG_MIN_LEN);
+ GEM_BUG_ON(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, hxg[0]) != GUC_HXG_ORIGIN_GUC);
+ GEM_BUG_ON(FIELD_GET(GUC_HXG_MSG_0_TYPE, hxg[0]) != GUC_HXG_TYPE_RESPONSE_SUCCESS &&
+ FIELD_GET(GUC_HXG_MSG_0_TYPE, hxg[0]) != GUC_HXG_TYPE_RESPONSE_FAILURE);
- CT_DEBUG(ct, "response fence %u status %#x\n", fence, status);
+ CT_DEBUG(ct, "response fence %u status %#x\n", fence, hxg[0]);
spin_lock_irqsave(&ct->requests.lock, flags);
list_for_each_entry(req, &ct->requests.pending, link) {
@@ -763,18 +936,22 @@ static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *r
err = -EMSGSIZE;
}
if (datalen)
- memcpy(req->response_buf, response->msg + 3, 4 * datalen);
+ memcpy(req->response_buf, data, 4 * datalen);
req->response_len = datalen;
- WRITE_ONCE(req->status, status);
+ WRITE_ONCE(req->status, hxg[0]);
found = true;
break;
}
- spin_unlock_irqrestore(&ct->requests.lock, flags);
-
if (!found) {
CT_ERROR(ct, "Unsolicited response (fence %u)\n", fence);
- return -ENOKEY;
+ CT_ERROR(ct, "Could not find fence=%u, last_fence=%u\n", fence,
+ ct->requests.last_fence);
+ list_for_each_entry(req, &ct->requests.pending, link)
+ CT_ERROR(ct, "request %u awaits response\n",
+ req->fence);
+ err = -ENOKEY;
}
+ spin_unlock_irqrestore(&ct->requests.lock, flags);
if (unlikely(err))
return err;
@@ -786,14 +963,16 @@ static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *r
static int ct_process_request(struct intel_guc_ct *ct, struct ct_incoming_msg *request)
{
struct intel_guc *guc = ct_to_guc(ct);
- u32 header, action, len;
+ const u32 *hxg;
const u32 *payload;
+ u32 hxg_len, action, len;
int ret;
- header = request->msg[0];
- payload = &request->msg[1];
- action = ct_header_get_action(header);
- len = ct_header_get_len(header);
+ hxg = &request->msg[GUC_CTB_MSG_MIN_LEN];
+ hxg_len = request->size - GUC_CTB_MSG_MIN_LEN;
+ payload = &hxg[GUC_HXG_MSG_MIN_LEN];
+ action = FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, hxg[0]);
+ len = hxg_len - GUC_HXG_MSG_MIN_LEN;
CT_DEBUG(ct, "request %x %*ph\n", action, 4 * len, payload);
@@ -801,6 +980,19 @@ static int ct_process_request(struct intel_guc_ct *ct, struct ct_incoming_msg *r
case INTEL_GUC_ACTION_DEFAULT:
ret = intel_guc_to_host_process_recv_msg(guc, payload, len);
break;
+ case INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
+ ret = intel_guc_deregister_done_process_msg(guc, payload,
+ len);
+ break;
+ case INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
+ ret = intel_guc_sched_done_process_msg(guc, payload, len);
+ break;
+ case INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION:
+ ret = intel_guc_context_reset_process_msg(guc, payload, len);
+ break;
+ case INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION:
+ ret = intel_guc_engine_failure_process_msg(guc, payload, len);
+ break;
default:
ret = -EOPNOTSUPP;
break;
@@ -855,29 +1047,24 @@ static void ct_incoming_request_worker_func(struct work_struct *w)
queue_work(system_unbound_wq, &ct->requests.worker);
}
-/**
- * DOC: CTB GuC to Host request
- *
- * Format of the CTB GuC to Host request message is as follows::
- *
- * +------------+---------+---------+---------+---------+---------+
- * | msg[0] | [1] | [2] | [3] | ... | [n-1] |
- * +------------+---------+---------+---------+---------+---------+
- * | MESSAGE | MESSAGE PAYLOAD |
- * + HEADER +---------+---------+---------+---------+---------+
- * | | 0 | 1 | 2 | ... | n |
- * +============+=========+=========+=========+=========+=========+
- * | len | request specific data |
- * +------+-----+---------+---------+---------+---------+---------+
- *
- * ^-----------------------len-----------------------^
- */
-
-static int ct_handle_request(struct intel_guc_ct *ct, struct ct_incoming_msg *request)
+static int ct_handle_event(struct intel_guc_ct *ct, struct ct_incoming_msg *request)
{
+ const u32 *hxg = &request->msg[GUC_CTB_MSG_MIN_LEN];
+ u32 action = FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, hxg[0]);
unsigned long flags;
- GEM_BUG_ON(ct_header_is_response(request->msg[0]));
+ GEM_BUG_ON(FIELD_GET(GUC_HXG_MSG_0_TYPE, hxg[0]) != GUC_HXG_TYPE_EVENT);
+
+ /*
+ * Adjusting the space must be done in IRQ or deadlock can occur as the
+ * CTB processing in the below workqueue can send CTBs which creates a
+ * circular dependency if the space was returned there.
+ */
+ switch (action) {
+ case INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
+ case INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
+ g2h_release_space(ct, request->size);
+ }
spin_lock_irqsave(&ct->requests.lock, flags);
list_add_tail(&request->link, &ct->requests.incoming);
@@ -887,15 +1074,53 @@ static int ct_handle_request(struct intel_guc_ct *ct, struct ct_incoming_msg *re
return 0;
}
-static void ct_handle_msg(struct intel_guc_ct *ct, struct ct_incoming_msg *msg)
+static int ct_handle_hxg(struct intel_guc_ct *ct, struct ct_incoming_msg *msg)
{
- u32 header = msg->msg[0];
+ u32 origin, type;
+ u32 *hxg;
int err;
- if (ct_header_is_response(header))
+ if (unlikely(msg->size < GUC_CTB_HXG_MSG_MIN_LEN))
+ return -EBADMSG;
+
+ hxg = &msg->msg[GUC_CTB_MSG_MIN_LEN];
+
+ origin = FIELD_GET(GUC_HXG_MSG_0_ORIGIN, hxg[0]);
+ if (unlikely(origin != GUC_HXG_ORIGIN_GUC)) {
+ err = -EPROTO;
+ goto failed;
+ }
+
+ type = FIELD_GET(GUC_HXG_MSG_0_TYPE, hxg[0]);
+ switch (type) {
+ case GUC_HXG_TYPE_EVENT:
+ err = ct_handle_event(ct, msg);
+ break;
+ case GUC_HXG_TYPE_RESPONSE_SUCCESS:
+ case GUC_HXG_TYPE_RESPONSE_FAILURE:
err = ct_handle_response(ct, msg);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ }
+
+ if (unlikely(err)) {
+failed:
+ CT_ERROR(ct, "Failed to handle HXG message (%pe) %*ph\n",
+ ERR_PTR(err), 4 * GUC_HXG_MSG_MIN_LEN, hxg);
+ }
+ return err;
+}
+
+static void ct_handle_msg(struct intel_guc_ct *ct, struct ct_incoming_msg *msg)
+{
+ u32 format = FIELD_GET(GUC_CTB_MSG_0_FORMAT, msg->msg[0]);
+ int err;
+
+ if (format == GUC_CTB_FORMAT_HXG)
+ err = ct_handle_hxg(ct, msg);
else
- err = ct_handle_request(ct, msg);
+ err = -EOPNOTSUPP;
if (unlikely(err)) {
CT_ERROR(ct, "Failed to process CT message (%pe) %*ph\n",
@@ -958,3 +1183,25 @@ void intel_guc_ct_event_handler(struct intel_guc_ct *ct)
ct_try_receive_message(ct);
}
+
+void intel_guc_ct_print_info(struct intel_guc_ct *ct,
+ struct drm_printer *p)
+{
+ drm_printf(p, "CT %s\n", enableddisabled(ct->enabled));
+
+ if (!ct->enabled)
+ return;
+
+ drm_printf(p, "H2G Space: %u\n",
+ atomic_read(&ct->ctbs.send.space) * 4);
+ drm_printf(p, "Head: %u\n",
+ ct->ctbs.send.desc->head);
+ drm_printf(p, "Tail: %u\n",
+ ct->ctbs.send.desc->tail);
+ drm_printf(p, "G2H Space: %u\n",
+ atomic_read(&ct->ctbs.recv.space) * 4);
+ drm_printf(p, "Head: %u\n",
+ ct->ctbs.recv.desc->head);
+ drm_printf(p, "Tail: %u\n",
+ ct->ctbs.recv.desc->tail);
+}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
index cb222f202301..f709a19c7e21 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
@@ -9,11 +9,14 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
+#include <linux/ktime.h>
+#include <linux/wait.h>
#include "intel_guc_fwif.h"
struct i915_vma;
struct intel_guc;
+struct drm_printer;
/**
* DOC: Command Transport (CT).
@@ -31,16 +34,25 @@ struct intel_guc;
* @lock: protects access to the commands buffer and buffer descriptor
* @desc: pointer to the buffer descriptor
* @cmds: pointer to the commands buffer
- * @size: size of the commands buffer
+ * @size: size of the commands buffer in dwords
+ * @resv_space: reserved space in buffer in dwords
+ * @head: local shadow copy of head in dwords
+ * @tail: local shadow copy of tail in dwords
+ * @space: local shadow copy of space in dwords
+ * @broken: flag to indicate if descriptor data is broken
*/
struct intel_guc_ct_buffer {
spinlock_t lock;
struct guc_ct_buffer_desc *desc;
u32 *cmds;
u32 size;
+ u32 resv_space;
+ u32 tail;
+ u32 head;
+ atomic_t space;
+ bool broken;
};
-
/** Top-level structure for Command Transport related data
*
* Includes a pair of CT buffers for bi-directional communication and tracking
@@ -58,8 +70,11 @@ struct intel_guc_ct {
struct tasklet_struct receive_tasklet;
+ /** @wq: wait queue for g2h chanenl */
+ wait_queue_head_t wq;
+
struct {
- u32 last_fence; /* last fence used to send request */
+ u16 last_fence; /* last fence used to send request */
spinlock_t lock; /* protects pending requests list */
struct list_head pending; /* requests waiting for response */
@@ -67,6 +82,9 @@ struct intel_guc_ct {
struct list_head incoming; /* incoming requests */
struct work_struct worker; /* handler for incoming requests */
} requests;
+
+ /** @stall_time: time of first time a CTB submission is stalled */
+ ktime_t stall_time;
};
void intel_guc_ct_init_early(struct intel_guc_ct *ct);
@@ -85,8 +103,18 @@ static inline bool intel_guc_ct_enabled(struct intel_guc_ct *ct)
return ct->enabled;
}
+#define INTEL_GUC_CT_SEND_NB BIT(31)
+#define INTEL_GUC_CT_SEND_G2H_DW_SHIFT 0
+#define INTEL_GUC_CT_SEND_G2H_DW_MASK (0xff << INTEL_GUC_CT_SEND_G2H_DW_SHIFT)
+#define MAKE_SEND_FLAGS(len) ({ \
+ typeof(len) len_ = (len); \
+ GEM_BUG_ON(!FIELD_FIT(INTEL_GUC_CT_SEND_G2H_DW_MASK, len_)); \
+ (FIELD_PREP(INTEL_GUC_CT_SEND_G2H_DW_MASK, len_) | INTEL_GUC_CT_SEND_NB); \
+})
int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len,
- u32 *response_buf, u32 response_buf_size);
+ u32 *response_buf, u32 response_buf_size, u32 flags);
void intel_guc_ct_event_handler(struct intel_guc_ct *ct);
+void intel_guc_ct_print_info(struct intel_guc_ct *ct, struct drm_printer *p);
+
#endif /* _INTEL_GUC_CT_H_ */
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
index fe7cb7b29a1e..887c8c8f35db 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
@@ -9,6 +9,10 @@
#include "intel_guc.h"
#include "intel_guc_debugfs.h"
#include "intel_guc_log_debugfs.h"
+#include "gt/uc/intel_guc_ct.h"
+#include "gt/uc/intel_guc_ads.h"
+#include "gt/uc/intel_guc_submission.h"
+#include "gt/uc/intel_guc_slpc.h"
static int guc_info_show(struct seq_file *m, void *data)
{
@@ -22,16 +26,57 @@ static int guc_info_show(struct seq_file *m, void *data)
drm_puts(&p, "\n");
intel_guc_log_info(&guc->log, &p);
- /* Add more as required ... */
+ if (!intel_guc_submission_is_used(guc))
+ return 0;
+
+ intel_guc_ct_print_info(&guc->ct, &p);
+ intel_guc_submission_print_info(guc, &p);
+ intel_guc_ads_print_policy_info(guc, &p);
return 0;
}
DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_info);
+static int guc_registered_contexts_show(struct seq_file *m, void *data)
+{
+ struct intel_guc *guc = m->private;
+ struct drm_printer p = drm_seq_file_printer(m);
+
+ if (!intel_guc_submission_is_used(guc))
+ return -ENODEV;
+
+ intel_guc_submission_print_context_info(guc, &p);
+
+ return 0;
+}
+DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_registered_contexts);
+
+static int guc_slpc_info_show(struct seq_file *m, void *unused)
+{
+ struct intel_guc *guc = m->private;
+ struct intel_guc_slpc *slpc = &guc->slpc;
+ struct drm_printer p = drm_seq_file_printer(m);
+
+ if (!intel_guc_slpc_is_used(guc))
+ return -ENODEV;
+
+ return intel_guc_slpc_print_info(slpc, &p);
+}
+DEFINE_GT_DEBUGFS_ATTRIBUTE(guc_slpc_info);
+
+static bool intel_eval_slpc_support(void *data)
+{
+ struct intel_guc *guc = (struct intel_guc *)data;
+
+ return intel_guc_slpc_is_used(guc);
+}
+
void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root)
{
static const struct debugfs_gt_file files[] = {
{ "guc_info", &guc_info_fops, NULL },
+ { "guc_registered_contexts", &guc_registered_contexts_fops, NULL },
+ { "guc_slpc_info", &guc_slpc_info_fops, &intel_eval_slpc_support},
};
if (!intel_guc_is_supported(guc))
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
index e9a9d85e2aa3..fa4be13c8854 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
@@ -12,19 +12,27 @@
#include "gt/intel_engine_types.h"
#include "abi/guc_actions_abi.h"
+#include "abi/guc_actions_slpc_abi.h"
#include "abi/guc_errors_abi.h"
#include "abi/guc_communication_mmio_abi.h"
#include "abi/guc_communication_ctb_abi.h"
#include "abi/guc_messages_abi.h"
+/* Payload length only i.e. don't include G2H header length */
+#define G2H_LEN_DW_SCHED_CONTEXT_MODE_SET 2
+#define G2H_LEN_DW_DEREGISTER_CONTEXT 1
+
+#define GUC_CONTEXT_DISABLE 0
+#define GUC_CONTEXT_ENABLE 1
+
#define GUC_CLIENT_PRIORITY_KMD_HIGH 0
#define GUC_CLIENT_PRIORITY_HIGH 1
#define GUC_CLIENT_PRIORITY_KMD_NORMAL 2
#define GUC_CLIENT_PRIORITY_NORMAL 3
#define GUC_CLIENT_PRIORITY_NUM 4
-#define GUC_MAX_STAGE_DESCRIPTORS 1024
-#define GUC_INVALID_STAGE_ID GUC_MAX_STAGE_DESCRIPTORS
+#define GUC_MAX_LRC_DESCRIPTORS 65535
+#define GUC_INVALID_LRC_ID GUC_MAX_LRC_DESCRIPTORS
#define GUC_RENDER_ENGINE 0
#define GUC_VIDEO_ENGINE 1
@@ -81,15 +89,14 @@
#define GUC_LOG_ALLOC_IN_MEGABYTE (1 << 3)
#define GUC_LOG_CRASH_SHIFT 4
#define GUC_LOG_CRASH_MASK (0x3 << GUC_LOG_CRASH_SHIFT)
-#define GUC_LOG_DPC_SHIFT 6
-#define GUC_LOG_DPC_MASK (0x7 << GUC_LOG_DPC_SHIFT)
-#define GUC_LOG_ISR_SHIFT 9
-#define GUC_LOG_ISR_MASK (0x7 << GUC_LOG_ISR_SHIFT)
+#define GUC_LOG_DEBUG_SHIFT 6
+#define GUC_LOG_DEBUG_MASK (0xF << GUC_LOG_DEBUG_SHIFT)
#define GUC_LOG_BUF_ADDR_SHIFT 12
#define GUC_CTL_WA 1
#define GUC_CTL_FEATURE 2
#define GUC_CTL_DISABLE_SCHEDULER (1 << 14)
+#define GUC_CTL_ENABLE_SLPC BIT(2)
#define GUC_CTL_DEBUG 3
#define GUC_LOG_VERBOSITY_SHIFT 0
@@ -136,6 +143,11 @@
#define GUC_ID_TO_ENGINE_INSTANCE(guc_id) \
(((guc_id) & GUC_ENGINE_INSTANCE_MASK) >> GUC_ENGINE_INSTANCE_SHIFT)
+#define SLPC_EVENT(id, c) (\
+FIELD_PREP(HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ID, id) | \
+FIELD_PREP(HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC, c) \
+)
+
static inline u8 engine_class_to_guc_class(u8 class)
{
BUILD_BUG_ON(GUC_RENDER_CLASS != RENDER_CLASS);
@@ -177,66 +189,40 @@ struct guc_process_desc {
u32 reserved[30];
} __packed;
-/* engine id and context id is packed into guc_execlist_context.context_id*/
-#define GUC_ELC_CTXID_OFFSET 0
-#define GUC_ELC_ENGINE_OFFSET 29
+#define CONTEXT_REGISTRATION_FLAG_KMD BIT(0)
-/* The execlist context including software and HW information */
-struct guc_execlist_context {
- u32 context_desc;
- u32 context_id;
- u32 ring_status;
- u32 ring_lrca;
- u32 ring_begin;
- u32 ring_end;
- u32 ring_next_free_location;
- u32 ring_current_tail_pointer_value;
- u8 engine_state_submit_value;
- u8 engine_state_wait_value;
- u16 pagefault_count;
- u16 engine_submit_queue_count;
-} __packed;
+#define CONTEXT_POLICY_DEFAULT_EXECUTION_QUANTUM_US 1000000
+#define CONTEXT_POLICY_DEFAULT_PREEMPTION_TIME_US 500000
+
+/* Preempt to idle on quantum expiry */
+#define CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE BIT(0)
/*
- * This structure describes a stage set arranged for a particular communication
- * between uKernel (GuC) and Driver (KMD). Technically, this is known as a
- * "GuC Context descriptor" in the specs, but we use the term "stage descriptor"
- * to avoid confusion with all the other things already named "context" in the
- * driver. A static pool of these descriptors are stored inside a GEM object
- * (stage_desc_pool) which is held for the entire lifetime of our interaction
- * with the GuC, being allocated before the GuC is loaded with its firmware.
+ * GuC Context registration descriptor.
+ * FIXME: This is only required to exist during context registration.
+ * The current 1:1 between guc_lrc_desc and LRCs for the lifetime of the LRC
+ * is not required.
*/
-struct guc_stage_desc {
- u32 sched_common_area;
- u32 stage_id;
- u32 pas_id;
- u8 engines_used;
- u64 db_trigger_cpu;
- u32 db_trigger_uk;
- u64 db_trigger_phy;
- u16 db_id;
-
- struct guc_execlist_context lrc[GUC_MAX_ENGINES_NUM];
-
- u8 attribute;
-
+struct guc_lrc_desc {
+ u32 hw_context_desc;
+ u32 slpm_perf_mode_hint; /* SPLC v1 only */
+ u32 slpm_freq_hint;
+ u32 engine_submit_mask; /* In logical space */
+ u8 engine_class;
+ u8 reserved0[3];
u32 priority;
-
- u32 wq_sampled_tail_offset;
- u32 wq_total_submit_enqueues;
-
u32 process_desc;
u32 wq_addr;
u32 wq_size;
-
- u32 engine_presence;
-
- u8 engine_suspended;
-
- u8 reserved0[3];
- u64 reserved1[1];
-
- u64 desc_private;
+ u32 context_flags; /* CONTEXT_REGISTRATION_* */
+ /* Time for one workload to execute. (in micro seconds) */
+ u32 execution_quantum;
+ /* Time to wait for a preemption request to complete before issuing a
+ * reset. (in micro seconds).
+ */
+ u32 preemption_timeout;
+ u32 policy_flags; /* CONTEXT_POLICY_* */
+ u32 reserved1[19];
} __packed;
#define GUC_POWER_UNSPECIFIED 0
@@ -247,32 +233,14 @@ struct guc_stage_desc {
/* Scheduling policy settings */
-/* Reset engine upon preempt failure */
-#define POLICY_RESET_ENGINE (1<<0)
-/* Preempt to idle on quantum expiry */
-#define POLICY_PREEMPT_TO_IDLE (1<<1)
+#define GLOBAL_POLICY_MAX_NUM_WI 15
-#define POLICY_MAX_NUM_WI 15
-#define POLICY_DEFAULT_DPC_PROMOTE_TIME_US 500000
-#define POLICY_DEFAULT_EXECUTION_QUANTUM_US 1000000
-#define POLICY_DEFAULT_PREEMPTION_TIME_US 500000
-#define POLICY_DEFAULT_FAULT_TIME_US 250000
+/* Don't reset an engine upon preemption failure */
+#define GLOBAL_POLICY_DISABLE_ENGINE_RESET BIT(0)
-struct guc_policy {
- /* Time for one workload to execute. (in micro seconds) */
- u32 execution_quantum;
- /* Time to wait for a preemption request to completed before issuing a
- * reset. (in micro seconds). */
- u32 preemption_time;
- /* How much time to allow to run after the first fault is observed.
- * Then preempt afterwards. (in micro seconds) */
- u32 fault_time;
- u32 policy_flags;
- u32 reserved[8];
-} __packed;
+#define GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US 500000
struct guc_policies {
- struct guc_policy policy[GUC_CLIENT_PRIORITY_NUM][GUC_MAX_ENGINE_CLASSES];
u32 submission_queue_depth[GUC_MAX_ENGINE_CLASSES];
/* In micro seconds. How much time to allow before DPC processing is
* called back via interrupt (to prevent DPC queue drain starving).
@@ -286,6 +254,7 @@ struct guc_policies {
* idle. */
u32 max_num_work_items;
+ u32 global_flags;
u32 reserved[4];
} __packed;
@@ -311,29 +280,13 @@ struct guc_gt_system_info {
u32 generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_MAX];
} __packed;
-/* Clients info */
-struct guc_ct_pool_entry {
- struct guc_ct_buffer_desc desc;
- u32 reserved[7];
-} __packed;
-
-#define GUC_CT_POOL_SIZE 2
-
-struct guc_clients_info {
- u32 clients_num;
- u32 reserved0[13];
- u32 ct_pool_addr;
- u32 ct_pool_count;
- u32 reserved[4];
-} __packed;
-
/* GuC Additional Data Struct */
struct guc_ads {
struct guc_mmio_reg_set reg_state_list[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS];
u32 reserved0;
u32 scheduler_policies;
u32 gt_system_info;
- u32 clients_info;
+ u32 reserved1;
u32 control_data;
u32 golden_context_lrca[GUC_MAX_ENGINE_CLASSES];
u32 eng_state_size[GUC_MAX_ENGINE_CLASSES];
@@ -344,8 +297,7 @@ struct guc_ads {
/* GuC logging structures */
enum guc_log_buffer_type {
- GUC_ISR_LOG_BUFFER,
- GUC_DPC_LOG_BUFFER,
+ GUC_DEBUG_LOG_BUFFER,
GUC_CRASH_DUMP_LOG_BUFFER,
GUC_MAX_LOG_BUFFER
};
@@ -414,23 +366,6 @@ struct guc_shared_ctx_data {
struct guc_ctx_report preempt_ctx_report[GUC_MAX_ENGINES_NUM];
} __packed;
-#define __INTEL_GUC_MSG_GET(T, m) \
- (((m) & INTEL_GUC_MSG_ ## T ## _MASK) >> INTEL_GUC_MSG_ ## T ## _SHIFT)
-#define INTEL_GUC_MSG_TO_TYPE(m) __INTEL_GUC_MSG_GET(TYPE, m)
-#define INTEL_GUC_MSG_TO_DATA(m) __INTEL_GUC_MSG_GET(DATA, m)
-#define INTEL_GUC_MSG_TO_CODE(m) __INTEL_GUC_MSG_GET(CODE, m)
-
-#define __INTEL_GUC_MSG_TYPE_IS(T, m) \
- (INTEL_GUC_MSG_TO_TYPE(m) == INTEL_GUC_MSG_TYPE_ ## T)
-#define INTEL_GUC_MSG_IS_REQUEST(m) __INTEL_GUC_MSG_TYPE_IS(REQUEST, m)
-#define INTEL_GUC_MSG_IS_RESPONSE(m) __INTEL_GUC_MSG_TYPE_IS(RESPONSE, m)
-
-#define INTEL_GUC_MSG_IS_RESPONSE_SUCCESS(m) \
- (typecheck(u32, (m)) && \
- ((m) & (INTEL_GUC_MSG_TYPE_MASK | INTEL_GUC_MSG_CODE_MASK)) == \
- ((INTEL_GUC_MSG_TYPE_RESPONSE << INTEL_GUC_MSG_TYPE_SHIFT) | \
- (INTEL_GUC_RESPONSE_STATUS_SUCCESS << INTEL_GUC_MSG_CODE_SHIFT)))
-
/* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */
enum intel_guc_recv_message {
INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED = BIT(1),
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
index c36d5eb5bbb9..ac0931f0374b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
@@ -197,10 +197,8 @@ static bool guc_check_log_buf_overflow(struct intel_guc_log *log,
static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type)
{
switch (type) {
- case GUC_ISR_LOG_BUFFER:
- return ISR_BUFFER_SIZE;
- case GUC_DPC_LOG_BUFFER:
- return DPC_BUFFER_SIZE;
+ case GUC_DEBUG_LOG_BUFFER:
+ return DEBUG_BUFFER_SIZE;
case GUC_CRASH_DUMP_LOG_BUFFER:
return CRASH_BUFFER_SIZE;
default:
@@ -245,7 +243,7 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log)
src_data += PAGE_SIZE;
dst_data += PAGE_SIZE;
- for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
+ for (type = GUC_DEBUG_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
/*
* Make a copy of the state structure, inside GuC log buffer
* (which is uncached mapped), on the stack to avoid reading
@@ -463,21 +461,16 @@ int intel_guc_log_create(struct intel_guc_log *log)
* +===============================+ 00B
* | Crash dump state header |
* +-------------------------------+ 32B
- * | DPC state header |
+ * | Debug state header |
* +-------------------------------+ 64B
- * | ISR state header |
- * +-------------------------------+ 96B
* | |
* +===============================+ PAGE_SIZE (4KB)
* | Crash Dump logs |
* +===============================+ + CRASH_SIZE
- * | DPC logs |
- * +===============================+ + DPC_SIZE
- * | ISR logs |
- * +===============================+ + ISR_SIZE
+ * | Debug logs |
+ * +===============================+ + DEBUG_SIZE
*/
- guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DPC_BUFFER_SIZE +
- ISR_BUFFER_SIZE;
+ guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE;
vma = intel_guc_allocate_vma(guc, guc_log_size);
if (IS_ERR(vma)) {
@@ -675,10 +668,8 @@ static const char *
stringify_guc_log_type(enum guc_log_buffer_type type)
{
switch (type) {
- case GUC_ISR_LOG_BUFFER:
- return "ISR";
- case GUC_DPC_LOG_BUFFER:
- return "DPC";
+ case GUC_DEBUG_LOG_BUFFER:
+ return "DEBUG";
case GUC_CRASH_DUMP_LOG_BUFFER:
return "CRASH";
default:
@@ -708,7 +699,7 @@ void intel_guc_log_info(struct intel_guc_log *log, struct drm_printer *p)
drm_printf(p, "\tRelay full count: %u\n", log->relay.full_count);
- for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
+ for (type = GUC_DEBUG_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
drm_printf(p, "\t%s:\tflush count %10u, overflow count %10u\n",
stringify_guc_log_type(type),
log->stats[type].flush,
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
index 11fccd0b2294..ac1ee1d5ce10 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
@@ -17,12 +17,10 @@ struct intel_guc;
#ifdef CONFIG_DRM_I915_DEBUG_GUC
#define CRASH_BUFFER_SIZE SZ_2M
-#define DPC_BUFFER_SIZE SZ_8M
-#define ISR_BUFFER_SIZE SZ_8M
+#define DEBUG_BUFFER_SIZE SZ_16M
#else
#define CRASH_BUFFER_SIZE SZ_8K
-#define DPC_BUFFER_SIZE SZ_32K
-#define ISR_BUFFER_SIZE SZ_32K
+#define DEBUG_BUFFER_SIZE SZ_64K
#endif
/*
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
new file mode 100644
index 000000000000..fc805d466d99
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "intel_guc_rc.h"
+#include "gt/intel_gt.h"
+#include "i915_drv.h"
+
+static bool __guc_rc_supported(struct intel_guc *guc)
+{
+ /* GuC RC is unavailable for pre-Gen12 */
+ return guc->submission_supported &&
+ GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
+}
+
+static bool __guc_rc_selected(struct intel_guc *guc)
+{
+ if (!intel_guc_rc_is_supported(guc))
+ return false;
+
+ return guc->submission_selected;
+}
+
+void intel_guc_rc_init_early(struct intel_guc *guc)
+{
+ guc->rc_supported = __guc_rc_supported(guc);
+ guc->rc_selected = __guc_rc_selected(guc);
+}
+
+static int guc_action_control_gucrc(struct intel_guc *guc, bool enable)
+{
+ u32 rc_mode = enable ? INTEL_GUCRC_FIRMWARE_CONTROL :
+ INTEL_GUCRC_HOST_CONTROL;
+ u32 action[] = {
+ INTEL_GUC_ACTION_SETUP_PC_GUCRC,
+ rc_mode
+ };
+ int ret;
+
+ ret = intel_guc_send(guc, action, ARRAY_SIZE(action));
+ ret = ret > 0 ? -EPROTO : ret;
+
+ return ret;
+}
+
+static int __guc_rc_control(struct intel_guc *guc, bool enable)
+{
+ struct intel_gt *gt = guc_to_gt(guc);
+ struct drm_device *drm = &guc_to_gt(guc)->i915->drm;
+ int ret;
+
+ if (!intel_uc_uses_guc_rc(&gt->uc))
+ return -EOPNOTSUPP;
+
+ if (!intel_guc_is_ready(guc))
+ return -EINVAL;
+
+ ret = guc_action_control_gucrc(guc, enable);
+ if (ret) {
+ drm_err(drm, "Failed to %s GuC RC (%pe)\n",
+ enabledisable(enable), ERR_PTR(ret));
+ return ret;
+ }
+
+ drm_info(&gt->i915->drm, "GuC RC: %s\n",
+ enableddisabled(enable));
+
+ return 0;
+}
+
+int intel_guc_rc_enable(struct intel_guc *guc)
+{
+ return __guc_rc_control(guc, true);
+}
+
+int intel_guc_rc_disable(struct intel_guc *guc)
+{
+ return __guc_rc_control(guc, false);
+}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
new file mode 100644
index 000000000000..57e86c337838
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef _INTEL_GUC_RC_H_
+#define _INTEL_GUC_RC_H_
+
+#include "intel_guc_submission.h"
+
+void intel_guc_rc_init_early(struct intel_guc *guc);
+
+static inline bool intel_guc_rc_is_supported(struct intel_guc *guc)
+{
+ return guc->rc_supported;
+}
+
+static inline bool intel_guc_rc_is_wanted(struct intel_guc *guc)
+{
+ return guc->submission_selected && intel_guc_rc_is_supported(guc);
+}
+
+static inline bool intel_guc_rc_is_used(struct intel_guc *guc)
+{
+ return intel_guc_submission_is_used(guc) && intel_guc_rc_is_wanted(guc);
+}
+
+int intel_guc_rc_enable(struct intel_guc *guc);
+int intel_guc_rc_disable(struct intel_guc *guc);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
new file mode 100644
index 000000000000..65a3e7fdb2b2
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -0,0 +1,626 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "intel_guc_slpc.h"
+#include "gt/intel_gt.h"
+
+static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc)
+{
+ return container_of(slpc, struct intel_guc, slpc);
+}
+
+static inline struct intel_gt *slpc_to_gt(struct intel_guc_slpc *slpc)
+{
+ return guc_to_gt(slpc_to_guc(slpc));
+}
+
+static inline struct drm_i915_private *slpc_to_i915(struct intel_guc_slpc *slpc)
+{
+ return slpc_to_gt(slpc)->i915;
+}
+
+static bool __detect_slpc_supported(struct intel_guc *guc)
+{
+ /* GuC SLPC is unavailable for pre-Gen12 */
+ return guc->submission_supported &&
+ GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
+}
+
+static bool __guc_slpc_selected(struct intel_guc *guc)
+{
+ if (!intel_guc_slpc_is_supported(guc))
+ return false;
+
+ return guc->submission_selected;
+}
+
+void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc)
+{
+ struct intel_guc *guc = slpc_to_guc(slpc);
+
+ slpc->supported = __detect_slpc_supported(guc);
+ slpc->selected = __guc_slpc_selected(guc);
+}
+
+static void slpc_mem_set_param(struct slpc_shared_data *data,
+ u32 id, u32 value)
+{
+ GEM_BUG_ON(id >= SLPC_MAX_OVERRIDE_PARAMETERS);
+ /*
+ * When the flag bit is set, corresponding value will be read
+ * and applied by SLPC.
+ */
+ data->override_params.bits[id >> 5] |= (1 << (id % 32));
+ data->override_params.values[id] = value;
+}
+
+static void slpc_mem_set_enabled(struct slpc_shared_data *data,
+ u8 enable_id, u8 disable_id)
+{
+ /*
+ * Enabling a param involves setting the enable_id
+ * to 1 and disable_id to 0.
+ */
+ slpc_mem_set_param(data, enable_id, 1);
+ slpc_mem_set_param(data, disable_id, 0);
+}
+
+static void slpc_mem_set_disabled(struct slpc_shared_data *data,
+ u8 enable_id, u8 disable_id)
+{
+ /*
+ * Disabling a param involves setting the enable_id
+ * to 0 and disable_id to 1.
+ */
+ slpc_mem_set_param(data, disable_id, 1);
+ slpc_mem_set_param(data, enable_id, 0);
+}
+
+int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
+{
+ struct intel_guc *guc = slpc_to_guc(slpc);
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data));
+ int err;
+
+ GEM_BUG_ON(slpc->vma);
+
+ err = intel_guc_allocate_and_map_vma(guc, size, &slpc->vma, (void **)&slpc->vaddr);
+ if (unlikely(err)) {
+ drm_err(&i915->drm,
+ "Failed to allocate SLPC struct (err=%pe)\n",
+ ERR_PTR(err));
+ return err;
+ }
+
+ slpc->max_freq_softlimit = 0;
+ slpc->min_freq_softlimit = 0;
+
+ return err;
+}
+
+static u32 slpc_get_state(struct intel_guc_slpc *slpc)
+{
+ struct slpc_shared_data *data;
+
+ GEM_BUG_ON(!slpc->vma);
+
+ drm_clflush_virt_range(slpc->vaddr, sizeof(u32));
+ data = slpc->vaddr;
+
+ return data->header.global_state;
+}
+
+static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value)
+{
+ u32 request[] = {
+ GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+ SLPC_EVENT(SLPC_EVENT_PARAMETER_SET, 2),
+ id,
+ value,
+ };
+ int ret;
+
+ ret = intel_guc_send(guc, request, ARRAY_SIZE(request));
+
+ return ret > 0 ? -EPROTO : ret;
+}
+
+static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id)
+{
+ u32 request[] = {
+ GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+ SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2),
+ id,
+ };
+
+ return intel_guc_send(guc, request, ARRAY_SIZE(request));
+}
+
+static bool slpc_is_running(struct intel_guc_slpc *slpc)
+{
+ return slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING;
+}
+
+static int guc_action_slpc_query(struct intel_guc *guc, u32 offset)
+{
+ u32 request[] = {
+ GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+ SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2),
+ offset,
+ 0,
+ };
+ int ret;
+
+ ret = intel_guc_send(guc, request, ARRAY_SIZE(request));
+
+ return ret > 0 ? -EPROTO : ret;
+}
+
+static int slpc_query_task_state(struct intel_guc_slpc *slpc)
+{
+ struct intel_guc *guc = slpc_to_guc(slpc);
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ u32 offset = intel_guc_ggtt_offset(guc, slpc->vma);
+ int ret;
+
+ ret = guc_action_slpc_query(guc, offset);
+ if (unlikely(ret))
+ drm_err(&i915->drm, "Failed to query task state (%pe)\n",
+ ERR_PTR(ret));
+
+ drm_clflush_virt_range(slpc->vaddr, SLPC_PAGE_SIZE_BYTES);
+
+ return ret;
+}
+
+static int slpc_set_param(struct intel_guc_slpc *slpc, u8 id, u32 value)
+{
+ struct intel_guc *guc = slpc_to_guc(slpc);
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ int ret;
+
+ GEM_BUG_ON(id >= SLPC_MAX_PARAM);
+
+ ret = guc_action_slpc_set_param(guc, id, value);
+ if (ret)
+ drm_err(&i915->drm, "Failed to set param %d to %u (%pe)\n",
+ id, value, ERR_PTR(ret));
+
+ return ret;
+}
+
+static int slpc_unset_param(struct intel_guc_slpc *slpc,
+ u8 id)
+{
+ struct intel_guc *guc = slpc_to_guc(slpc);
+
+ GEM_BUG_ON(id >= SLPC_MAX_PARAM);
+
+ return guc_action_slpc_unset_param(guc, id);
+}
+
+static const char *slpc_global_state_to_string(enum slpc_global_state state)
+{
+ switch (state) {
+ case SLPC_GLOBAL_STATE_NOT_RUNNING:
+ return "not running";
+ case SLPC_GLOBAL_STATE_INITIALIZING:
+ return "initializing";
+ case SLPC_GLOBAL_STATE_RESETTING:
+ return "resetting";
+ case SLPC_GLOBAL_STATE_RUNNING:
+ return "running";
+ case SLPC_GLOBAL_STATE_SHUTTING_DOWN:
+ return "shutting down";
+ case SLPC_GLOBAL_STATE_ERROR:
+ return "error";
+ default:
+ return "unknown";
+ }
+}
+
+static const char *slpc_get_state_string(struct intel_guc_slpc *slpc)
+{
+ return slpc_global_state_to_string(slpc_get_state(slpc));
+}
+
+static int guc_action_slpc_reset(struct intel_guc *guc, u32 offset)
+{
+ u32 request[] = {
+ GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+ SLPC_EVENT(SLPC_EVENT_RESET, 2),
+ offset,
+ 0,
+ };
+ int ret;
+
+ ret = intel_guc_send(guc, request, ARRAY_SIZE(request));
+
+ return ret > 0 ? -EPROTO : ret;
+}
+
+static int slpc_reset(struct intel_guc_slpc *slpc)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ struct intel_guc *guc = slpc_to_guc(slpc);
+ u32 offset = intel_guc_ggtt_offset(guc, slpc->vma);
+ int ret;
+
+ ret = guc_action_slpc_reset(guc, offset);
+
+ if (unlikely(ret < 0)) {
+ drm_err(&i915->drm, "SLPC reset action failed (%pe)\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ if (!ret) {
+ if (wait_for(slpc_is_running(slpc), SLPC_RESET_TIMEOUT_MS)) {
+ drm_err(&i915->drm, "SLPC not enabled! State = %s\n",
+ slpc_get_state_string(slpc));
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static u32 slpc_decode_min_freq(struct intel_guc_slpc *slpc)
+{
+ struct slpc_shared_data *data = slpc->vaddr;
+
+ GEM_BUG_ON(!slpc->vma);
+
+ return DIV_ROUND_CLOSEST(REG_FIELD_GET(SLPC_MIN_UNSLICE_FREQ_MASK,
+ data->task_state_data.freq) *
+ GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER);
+}
+
+static u32 slpc_decode_max_freq(struct intel_guc_slpc *slpc)
+{
+ struct slpc_shared_data *data = slpc->vaddr;
+
+ GEM_BUG_ON(!slpc->vma);
+
+ return DIV_ROUND_CLOSEST(REG_FIELD_GET(SLPC_MAX_UNSLICE_FREQ_MASK,
+ data->task_state_data.freq) *
+ GT_FREQUENCY_MULTIPLIER, GEN9_FREQ_SCALER);
+}
+
+static void slpc_shared_data_reset(struct slpc_shared_data *data)
+{
+ memset(data, 0, sizeof(struct slpc_shared_data));
+
+ data->header.size = sizeof(struct slpc_shared_data);
+
+ /* Enable only GTPERF task, disable others */
+ slpc_mem_set_enabled(data, SLPC_PARAM_TASK_ENABLE_GTPERF,
+ SLPC_PARAM_TASK_DISABLE_GTPERF);
+
+ slpc_mem_set_disabled(data, SLPC_PARAM_TASK_ENABLE_BALANCER,
+ SLPC_PARAM_TASK_DISABLE_BALANCER);
+
+ slpc_mem_set_disabled(data, SLPC_PARAM_TASK_ENABLE_DCC,
+ SLPC_PARAM_TASK_DISABLE_DCC);
+}
+
+/**
+ * intel_guc_slpc_set_max_freq() - Set max frequency limit for SLPC.
+ * @slpc: pointer to intel_guc_slpc.
+ * @val: frequency (MHz)
+ *
+ * This function will invoke GuC SLPC action to update the max frequency
+ * limit for unslice.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ intel_wakeref_t wakeref;
+ int ret;
+
+ if (val < slpc->min_freq ||
+ val > slpc->rp0_freq ||
+ val < slpc->min_freq_softlimit)
+ return -EINVAL;
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+ ret = slpc_set_param(slpc,
+ SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
+ val);
+
+ /* Return standardized err code for sysfs calls */
+ if (ret)
+ ret = -EIO;
+ }
+
+ if (!ret)
+ slpc->max_freq_softlimit = val;
+
+ return ret;
+}
+
+/**
+ * intel_guc_slpc_get_max_freq() - Get max frequency limit for SLPC.
+ * @slpc: pointer to intel_guc_slpc.
+ * @val: pointer to val which will hold max frequency (MHz)
+ *
+ * This function will invoke GuC SLPC action to read the max frequency
+ * limit for unslice.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ intel_wakeref_t wakeref;
+ int ret = 0;
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+ /* Force GuC to update task data */
+ ret = slpc_query_task_state(slpc);
+
+ if (!ret)
+ *val = slpc_decode_max_freq(slpc);
+ }
+
+ return ret;
+}
+
+/**
+ * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC.
+ * @slpc: pointer to intel_guc_slpc.
+ * @val: frequency (MHz)
+ *
+ * This function will invoke GuC SLPC action to update the min unslice
+ * frequency.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ intel_wakeref_t wakeref;
+ int ret;
+
+ if (val < slpc->min_freq ||
+ val > slpc->rp0_freq ||
+ val > slpc->max_freq_softlimit)
+ return -EINVAL;
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+ ret = slpc_set_param(slpc,
+ SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
+ val);
+
+ /* Return standardized err code for sysfs calls */
+ if (ret)
+ ret = -EIO;
+ }
+
+ if (!ret)
+ slpc->min_freq_softlimit = val;
+
+ return ret;
+}
+
+/**
+ * intel_guc_slpc_get_min_freq() - Get min frequency limit for SLPC.
+ * @slpc: pointer to intel_guc_slpc.
+ * @val: pointer to val which will hold min frequency (MHz)
+ *
+ * This function will invoke GuC SLPC action to read the min frequency
+ * limit for unslice.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ intel_wakeref_t wakeref;
+ int ret = 0;
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+ /* Force GuC to update task data */
+ ret = slpc_query_task_state(slpc);
+
+ if (!ret)
+ *val = slpc_decode_min_freq(slpc);
+ }
+
+ return ret;
+}
+
+void intel_guc_pm_intrmsk_enable(struct intel_gt *gt)
+{
+ u32 pm_intrmsk_mbz = 0;
+
+ /*
+ * Allow GuC to receive ARAT timer expiry event.
+ * This interrupt register is setup by RPS code
+ * when host based Turbo is enabled.
+ */
+ pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK;
+
+ intel_uncore_rmw(gt->uncore,
+ GEN6_PMINTRMSK, pm_intrmsk_mbz, 0);
+}
+
+static int slpc_set_softlimits(struct intel_guc_slpc *slpc)
+{
+ int ret = 0;
+
+ /*
+ * Softlimits are initially equivalent to platform limits
+ * unless they have deviated from defaults, in which case,
+ * we retain the values and set min/max accordingly.
+ */
+ if (!slpc->max_freq_softlimit)
+ slpc->max_freq_softlimit = slpc->rp0_freq;
+ else if (slpc->max_freq_softlimit != slpc->rp0_freq)
+ ret = intel_guc_slpc_set_max_freq(slpc,
+ slpc->max_freq_softlimit);
+
+ if (unlikely(ret))
+ return ret;
+
+ if (!slpc->min_freq_softlimit)
+ slpc->min_freq_softlimit = slpc->min_freq;
+ else if (slpc->min_freq_softlimit != slpc->min_freq)
+ return intel_guc_slpc_set_min_freq(slpc,
+ slpc->min_freq_softlimit);
+
+ return 0;
+}
+
+static int slpc_ignore_eff_freq(struct intel_guc_slpc *slpc, bool ignore)
+{
+ int ret = 0;
+
+ if (ignore) {
+ ret = slpc_set_param(slpc,
+ SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY,
+ ignore);
+ if (!ret)
+ return slpc_set_param(slpc,
+ SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
+ slpc->min_freq);
+ } else {
+ ret = slpc_unset_param(slpc,
+ SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY);
+ if (!ret)
+ return slpc_unset_param(slpc,
+ SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ);
+ }
+
+ return ret;
+}
+
+static int slpc_use_fused_rp0(struct intel_guc_slpc *slpc)
+{
+ /* Force SLPC to used platform rp0 */
+ return slpc_set_param(slpc,
+ SLPC_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ,
+ slpc->rp0_freq);
+}
+
+static void slpc_get_rp_values(struct intel_guc_slpc *slpc)
+{
+ u32 rp_state_cap;
+
+ rp_state_cap = intel_uncore_read(slpc_to_gt(slpc)->uncore,
+ GEN6_RP_STATE_CAP);
+
+ slpc->rp0_freq = REG_FIELD_GET(RP0_CAP_MASK, rp_state_cap) *
+ GT_FREQUENCY_MULTIPLIER;
+ slpc->rp1_freq = REG_FIELD_GET(RP1_CAP_MASK, rp_state_cap) *
+ GT_FREQUENCY_MULTIPLIER;
+ slpc->min_freq = REG_FIELD_GET(RPN_CAP_MASK, rp_state_cap) *
+ GT_FREQUENCY_MULTIPLIER;
+}
+
+/*
+ * intel_guc_slpc_enable() - Start SLPC
+ * @slpc: pointer to intel_guc_slpc.
+ *
+ * SLPC is enabled by setting up the shared data structure and
+ * sending reset event to GuC SLPC. Initial data is setup in
+ * intel_guc_slpc_init. Here we send the reset event. We do
+ * not currently need a slpc_disable since this is taken care
+ * of automatically when a reset/suspend occurs and the GuC
+ * CTB is destroyed.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ int ret;
+
+ GEM_BUG_ON(!slpc->vma);
+
+ slpc_shared_data_reset(slpc->vaddr);
+
+ ret = slpc_reset(slpc);
+ if (unlikely(ret < 0)) {
+ drm_err(&i915->drm, "SLPC Reset event returned (%pe)\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ ret = slpc_query_task_state(slpc);
+ if (unlikely(ret < 0))
+ return ret;
+
+ intel_guc_pm_intrmsk_enable(&i915->gt);
+
+ slpc_get_rp_values(slpc);
+
+ /* Ignore efficient freq and set min to platform min */
+ ret = slpc_ignore_eff_freq(slpc, true);
+ if (unlikely(ret)) {
+ drm_err(&i915->drm, "Failed to set SLPC min to RPn (%pe)\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ /* Set SLPC max limit to RP0 */
+ ret = slpc_use_fused_rp0(slpc);
+ if (unlikely(ret)) {
+ drm_err(&i915->drm, "Failed to set SLPC max to RP0 (%pe)\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ /* Revert SLPC min/max to softlimits if necessary */
+ ret = slpc_set_softlimits(slpc);
+ if (unlikely(ret)) {
+ drm_err(&i915->drm, "Failed to set SLPC softlimits (%pe)\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ struct slpc_shared_data *data = slpc->vaddr;
+ struct slpc_task_state_data *slpc_tasks;
+ intel_wakeref_t wakeref;
+ int ret = 0;
+
+ GEM_BUG_ON(!slpc->vma);
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+ ret = slpc_query_task_state(slpc);
+
+ if (!ret) {
+ slpc_tasks = &data->task_state_data;
+
+ drm_printf(p, "\tSLPC state: %s\n", slpc_get_state_string(slpc));
+ drm_printf(p, "\tGTPERF task active: %s\n",
+ yesno(slpc_tasks->status & SLPC_GTPERF_TASK_ENABLED));
+ drm_printf(p, "\tMax freq: %u MHz\n",
+ slpc_decode_max_freq(slpc));
+ drm_printf(p, "\tMin freq: %u MHz\n",
+ slpc_decode_min_freq(slpc));
+ }
+ }
+
+ return ret;
+}
+
+void intel_guc_slpc_fini(struct intel_guc_slpc *slpc)
+{
+ if (!slpc->vma)
+ return;
+
+ i915_vma_unpin_and_release(&slpc->vma, I915_VMA_RELEASE_MAP);
+}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
new file mode 100644
index 000000000000..e45054d5b9b4
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef _INTEL_GUC_SLPC_H_
+#define _INTEL_GUC_SLPC_H_
+
+#include "intel_guc_submission.h"
+#include "intel_guc_slpc_types.h"
+
+struct intel_gt;
+struct drm_printer;
+
+static inline bool intel_guc_slpc_is_supported(struct intel_guc *guc)
+{
+ return guc->slpc.supported;
+}
+
+static inline bool intel_guc_slpc_is_wanted(struct intel_guc *guc)
+{
+ return guc->slpc.selected;
+}
+
+static inline bool intel_guc_slpc_is_used(struct intel_guc *guc)
+{
+ return intel_guc_submission_is_used(guc) && intel_guc_slpc_is_wanted(guc);
+}
+
+void intel_guc_slpc_init_early(struct intel_guc_slpc *slpc);
+
+int intel_guc_slpc_init(struct intel_guc_slpc *slpc);
+int intel_guc_slpc_enable(struct intel_guc_slpc *slpc);
+void intel_guc_slpc_fini(struct intel_guc_slpc *slpc);
+int intel_guc_slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 val);
+int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val);
+int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val);
+int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
+int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p);
+void intel_guc_pm_intrmsk_enable(struct intel_gt *gt);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h
new file mode 100644
index 000000000000..41d13527666f
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef _INTEL_GUC_SLPC_TYPES_H_
+#define _INTEL_GUC_SLPC_TYPES_H_
+
+#include <linux/types.h>
+
+#define SLPC_RESET_TIMEOUT_MS 5
+
+struct intel_guc_slpc {
+ struct i915_vma *vma;
+ struct slpc_shared_data *vaddr;
+ bool supported;
+ bool selected;
+
+ /* platform frequency limits */
+ u32 min_freq;
+ u32 rp0_freq;
+ u32 rp1_freq;
+
+ /* frequency softlimits */
+ u32 min_freq_softlimit;
+ u32 max_freq_softlimit;
+};
+
+#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 7c8ff9792f7b..87d8dc8f51b9 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -10,10 +10,13 @@
#include "gt/intel_breadcrumbs.h"
#include "gt/intel_context.h"
#include "gt/intel_engine_pm.h"
+#include "gt/intel_engine_heartbeat.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_irq.h"
#include "gt/intel_gt_pm.h"
+#include "gt/intel_gt_requests.h"
#include "gt/intel_lrc.h"
+#include "gt/intel_lrc_reg.h"
#include "gt/intel_mocs.h"
#include "gt/intel_ring.h"
@@ -58,244 +61,705 @@
*
*/
+/* GuC Virtual Engine */
+struct guc_virtual_engine {
+ struct intel_engine_cs base;
+ struct intel_context context;
+};
+
+static struct intel_context *
+guc_create_virtual(struct intel_engine_cs **siblings, unsigned int count);
+
#define GUC_REQUEST_SIZE 64 /* bytes */
-static inline struct i915_priolist *to_priolist(struct rb_node *rb)
+/*
+ * Below is a set of functions which control the GuC scheduling state which do
+ * not require a lock as all state transitions are mutually exclusive. i.e. It
+ * is not possible for the context pinning code and submission, for the same
+ * context, to be executing simultaneously. We still need an atomic as it is
+ * possible for some of the bits to changing at the same time though.
+ */
+#define SCHED_STATE_NO_LOCK_ENABLED BIT(0)
+#define SCHED_STATE_NO_LOCK_PENDING_ENABLE BIT(1)
+#define SCHED_STATE_NO_LOCK_REGISTERED BIT(2)
+static inline bool context_enabled(struct intel_context *ce)
{
- return rb_entry(rb, struct i915_priolist, node);
+ return (atomic_read(&ce->guc_sched_state_no_lock) &
+ SCHED_STATE_NO_LOCK_ENABLED);
}
-static struct guc_stage_desc *__get_stage_desc(struct intel_guc *guc, u32 id)
+static inline void set_context_enabled(struct intel_context *ce)
{
- struct guc_stage_desc *base = guc->stage_desc_pool_vaddr;
+ atomic_or(SCHED_STATE_NO_LOCK_ENABLED, &ce->guc_sched_state_no_lock);
+}
- return &base[id];
+static inline void clr_context_enabled(struct intel_context *ce)
+{
+ atomic_and((u32)~SCHED_STATE_NO_LOCK_ENABLED,
+ &ce->guc_sched_state_no_lock);
}
-static int guc_stage_desc_pool_create(struct intel_guc *guc)
+static inline bool context_pending_enable(struct intel_context *ce)
{
- u32 size = PAGE_ALIGN(sizeof(struct guc_stage_desc) *
- GUC_MAX_STAGE_DESCRIPTORS);
+ return (atomic_read(&ce->guc_sched_state_no_lock) &
+ SCHED_STATE_NO_LOCK_PENDING_ENABLE);
+}
- return intel_guc_allocate_and_map_vma(guc, size, &guc->stage_desc_pool,
- &guc->stage_desc_pool_vaddr);
+static inline void set_context_pending_enable(struct intel_context *ce)
+{
+ atomic_or(SCHED_STATE_NO_LOCK_PENDING_ENABLE,
+ &ce->guc_sched_state_no_lock);
+}
+
+static inline void clr_context_pending_enable(struct intel_context *ce)
+{
+ atomic_and((u32)~SCHED_STATE_NO_LOCK_PENDING_ENABLE,
+ &ce->guc_sched_state_no_lock);
}
-static void guc_stage_desc_pool_destroy(struct intel_guc *guc)
+static inline bool context_registered(struct intel_context *ce)
{
- i915_vma_unpin_and_release(&guc->stage_desc_pool, I915_VMA_RELEASE_MAP);
+ return (atomic_read(&ce->guc_sched_state_no_lock) &
+ SCHED_STATE_NO_LOCK_REGISTERED);
+}
+
+static inline void set_context_registered(struct intel_context *ce)
+{
+ atomic_or(SCHED_STATE_NO_LOCK_REGISTERED,
+ &ce->guc_sched_state_no_lock);
+}
+
+static inline void clr_context_registered(struct intel_context *ce)
+{
+ atomic_and((u32)~SCHED_STATE_NO_LOCK_REGISTERED,
+ &ce->guc_sched_state_no_lock);
}
/*
- * Initialise/clear the stage descriptor shared with the GuC firmware.
- *
- * This descriptor tells the GuC where (in GGTT space) to find the important
- * data structures related to work submission (process descriptor, write queue,
- * etc).
+ * Below is a set of functions which control the GuC scheduling state which
+ * require a lock, aside from the special case where the functions are called
+ * from guc_lrc_desc_pin(). In that case it isn't possible for any other code
+ * path to be executing on the context.
*/
-static void guc_stage_desc_init(struct intel_guc *guc)
+#define SCHED_STATE_WAIT_FOR_DEREGISTER_TO_REGISTER BIT(0)
+#define SCHED_STATE_DESTROYED BIT(1)
+#define SCHED_STATE_PENDING_DISABLE BIT(2)
+#define SCHED_STATE_BANNED BIT(3)
+#define SCHED_STATE_BLOCKED_SHIFT 4
+#define SCHED_STATE_BLOCKED BIT(SCHED_STATE_BLOCKED_SHIFT)
+#define SCHED_STATE_BLOCKED_MASK (0xfff << SCHED_STATE_BLOCKED_SHIFT)
+static inline void init_sched_state(struct intel_context *ce)
+{
+ /* Only should be called from guc_lrc_desc_pin() */
+ atomic_set(&ce->guc_sched_state_no_lock, 0);
+ ce->guc_state.sched_state = 0;
+}
+
+static inline bool
+context_wait_for_deregister_to_register(struct intel_context *ce)
+{
+ return ce->guc_state.sched_state &
+ SCHED_STATE_WAIT_FOR_DEREGISTER_TO_REGISTER;
+}
+
+static inline void
+set_context_wait_for_deregister_to_register(struct intel_context *ce)
{
- struct guc_stage_desc *desc;
+ /* Only should be called from guc_lrc_desc_pin() without lock */
+ ce->guc_state.sched_state |=
+ SCHED_STATE_WAIT_FOR_DEREGISTER_TO_REGISTER;
+}
- /* we only use 1 stage desc, so hardcode it to 0 */
- desc = __get_stage_desc(guc, 0);
- memset(desc, 0, sizeof(*desc));
+static inline void
+clr_context_wait_for_deregister_to_register(struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_state.lock);
+ ce->guc_state.sched_state &=
+ ~SCHED_STATE_WAIT_FOR_DEREGISTER_TO_REGISTER;
+}
- desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE |
- GUC_STAGE_DESC_ATTR_KERNEL;
+static inline bool
+context_destroyed(struct intel_context *ce)
+{
+ return ce->guc_state.sched_state & SCHED_STATE_DESTROYED;
+}
- desc->stage_id = 0;
- desc->priority = GUC_CLIENT_PRIORITY_KMD_NORMAL;
+static inline void
+set_context_destroyed(struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_state.lock);
+ ce->guc_state.sched_state |= SCHED_STATE_DESTROYED;
+}
- desc->wq_size = GUC_WQ_SIZE;
+static inline bool context_pending_disable(struct intel_context *ce)
+{
+ return ce->guc_state.sched_state & SCHED_STATE_PENDING_DISABLE;
}
-static void guc_stage_desc_fini(struct intel_guc *guc)
+static inline void set_context_pending_disable(struct intel_context *ce)
{
- struct guc_stage_desc *desc;
+ lockdep_assert_held(&ce->guc_state.lock);
+ ce->guc_state.sched_state |= SCHED_STATE_PENDING_DISABLE;
+}
- desc = __get_stage_desc(guc, 0);
- memset(desc, 0, sizeof(*desc));
+static inline void clr_context_pending_disable(struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_state.lock);
+ ce->guc_state.sched_state &= ~SCHED_STATE_PENDING_DISABLE;
}
-static void guc_add_request(struct intel_guc *guc, struct i915_request *rq)
+static inline bool context_banned(struct intel_context *ce)
{
- /* Leaving stub as this function will be used in future patches */
+ return ce->guc_state.sched_state & SCHED_STATE_BANNED;
}
-/*
- * When we're doing submissions using regular execlists backend, writing to
- * ELSP from CPU side is enough to make sure that writes to ringbuffer pages
- * pinned in mappable aperture portion of GGTT are visible to command streamer.
- * Writes done by GuC on our behalf are not guaranteeing such ordering,
- * therefore, to ensure the flush, we're issuing a POSTING READ.
- */
-static void flush_ggtt_writes(struct i915_vma *vma)
+static inline void set_context_banned(struct intel_context *ce)
{
- if (i915_vma_is_map_and_fenceable(vma))
- intel_uncore_posting_read_fw(vma->vm->gt->uncore,
- GUC_STATUS);
+ lockdep_assert_held(&ce->guc_state.lock);
+ ce->guc_state.sched_state |= SCHED_STATE_BANNED;
}
-static void guc_submit(struct intel_engine_cs *engine,
- struct i915_request **out,
- struct i915_request **end)
+static inline void clr_context_banned(struct intel_context *ce)
{
- struct intel_guc *guc = &engine->gt->uc.guc;
+ lockdep_assert_held(&ce->guc_state.lock);
+ ce->guc_state.sched_state &= ~SCHED_STATE_BANNED;
+}
- do {
- struct i915_request *rq = *out++;
+static inline u32 context_blocked(struct intel_context *ce)
+{
+ return (ce->guc_state.sched_state & SCHED_STATE_BLOCKED_MASK) >>
+ SCHED_STATE_BLOCKED_SHIFT;
+}
- flush_ggtt_writes(rq->ring->vma);
- guc_add_request(guc, rq);
- } while (out != end);
+static inline void incr_context_blocked(struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->engine->sched_engine->lock);
+ lockdep_assert_held(&ce->guc_state.lock);
+
+ ce->guc_state.sched_state += SCHED_STATE_BLOCKED;
+
+ GEM_BUG_ON(!context_blocked(ce)); /* Overflow check */
}
-static inline int rq_prio(const struct i915_request *rq)
+static inline void decr_context_blocked(struct intel_context *ce)
{
- return rq->sched.attr.priority;
+ lockdep_assert_held(&ce->engine->sched_engine->lock);
+ lockdep_assert_held(&ce->guc_state.lock);
+
+ GEM_BUG_ON(!context_blocked(ce)); /* Underflow check */
+
+ ce->guc_state.sched_state -= SCHED_STATE_BLOCKED;
}
-static struct i915_request *schedule_in(struct i915_request *rq, int idx)
+static inline bool context_guc_id_invalid(struct intel_context *ce)
{
- trace_i915_request_in(rq, idx);
+ return ce->guc_id == GUC_INVALID_LRC_ID;
+}
+
+static inline void set_context_guc_id_invalid(struct intel_context *ce)
+{
+ ce->guc_id = GUC_INVALID_LRC_ID;
+}
+
+static inline struct intel_guc *ce_to_guc(struct intel_context *ce)
+{
+ return &ce->engine->gt->uc.guc;
+}
+
+static inline struct i915_priolist *to_priolist(struct rb_node *rb)
+{
+ return rb_entry(rb, struct i915_priolist, node);
+}
+
+static struct guc_lrc_desc *__get_lrc_desc(struct intel_guc *guc, u32 index)
+{
+ struct guc_lrc_desc *base = guc->lrc_desc_pool_vaddr;
+
+ GEM_BUG_ON(index >= GUC_MAX_LRC_DESCRIPTORS);
+
+ return &base[index];
+}
+
+static inline struct intel_context *__get_context(struct intel_guc *guc, u32 id)
+{
+ struct intel_context *ce = xa_load(&guc->context_lookup, id);
+
+ GEM_BUG_ON(id >= GUC_MAX_LRC_DESCRIPTORS);
+
+ return ce;
+}
+
+static int guc_lrc_desc_pool_create(struct intel_guc *guc)
+{
+ u32 size;
+ int ret;
+
+ size = PAGE_ALIGN(sizeof(struct guc_lrc_desc) *
+ GUC_MAX_LRC_DESCRIPTORS);
+ ret = intel_guc_allocate_and_map_vma(guc, size, &guc->lrc_desc_pool,
+ (void **)&guc->lrc_desc_pool_vaddr);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void guc_lrc_desc_pool_destroy(struct intel_guc *guc)
+{
+ guc->lrc_desc_pool_vaddr = NULL;
+ i915_vma_unpin_and_release(&guc->lrc_desc_pool, I915_VMA_RELEASE_MAP);
+}
+
+static inline bool guc_submission_initialized(struct intel_guc *guc)
+{
+ return !!guc->lrc_desc_pool_vaddr;
+}
+
+static inline void reset_lrc_desc(struct intel_guc *guc, u32 id)
+{
+ if (likely(guc_submission_initialized(guc))) {
+ struct guc_lrc_desc *desc = __get_lrc_desc(guc, id);
+ unsigned long flags;
+
+ memset(desc, 0, sizeof(*desc));
+
+ /*
+ * xarray API doesn't have xa_erase_irqsave wrapper, so calling
+ * the lower level functions directly.
+ */
+ xa_lock_irqsave(&guc->context_lookup, flags);
+ __xa_erase(&guc->context_lookup, id);
+ xa_unlock_irqrestore(&guc->context_lookup, flags);
+ }
+}
+
+static inline bool lrc_desc_registered(struct intel_guc *guc, u32 id)
+{
+ return __get_context(guc, id);
+}
+
+static inline void set_lrc_desc_registered(struct intel_guc *guc, u32 id,
+ struct intel_context *ce)
+{
+ unsigned long flags;
/*
- * Currently we are not tracking the rq->context being inflight
- * (ce->inflight = rq->engine). It is only used by the execlists
- * backend at the moment, a similar counting strategy would be
- * required if we generalise the inflight tracking.
+ * xarray API doesn't have xa_save_irqsave wrapper, so calling the
+ * lower level functions directly.
*/
+ xa_lock_irqsave(&guc->context_lookup, flags);
+ __xa_store(&guc->context_lookup, id, ce, GFP_ATOMIC);
+ xa_unlock_irqrestore(&guc->context_lookup, flags);
+}
+
+static int guc_submission_send_busy_loop(struct intel_guc *guc,
+ const u32 *action,
+ u32 len,
+ u32 g2h_len_dw,
+ bool loop)
+{
+ int err;
+
+ err = intel_guc_send_busy_loop(guc, action, len, g2h_len_dw, loop);
+
+ if (!err && g2h_len_dw)
+ atomic_inc(&guc->outstanding_submission_g2h);
+
+ return err;
+}
+
+int intel_guc_wait_for_pending_msg(struct intel_guc *guc,
+ atomic_t *wait_var,
+ bool interruptible,
+ long timeout)
+{
+ const int state = interruptible ?
+ TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
+ DEFINE_WAIT(wait);
- __intel_gt_pm_get(rq->engine->gt);
- return i915_request_get(rq);
+ might_sleep();
+ GEM_BUG_ON(timeout < 0);
+
+ if (!atomic_read(wait_var))
+ return 0;
+
+ if (!timeout)
+ return -ETIME;
+
+ for (;;) {
+ prepare_to_wait(&guc->ct.wq, &wait, state);
+
+ if (!atomic_read(wait_var))
+ break;
+
+ if (signal_pending_state(state, current)) {
+ timeout = -EINTR;
+ break;
+ }
+
+ if (!timeout) {
+ timeout = -ETIME;
+ break;
+ }
+
+ timeout = io_schedule_timeout(timeout);
+ }
+ finish_wait(&guc->ct.wq, &wait);
+
+ return (timeout < 0) ? timeout : 0;
}
-static void schedule_out(struct i915_request *rq)
+int intel_guc_wait_for_idle(struct intel_guc *guc, long timeout)
{
- trace_i915_request_out(rq);
+ if (!intel_uc_uses_guc_submission(&guc_to_gt(guc)->uc))
+ return 0;
- intel_gt_pm_put_async(rq->engine->gt);
- i915_request_put(rq);
+ return intel_guc_wait_for_pending_msg(guc,
+ &guc->outstanding_submission_g2h,
+ true, timeout);
}
-static void __guc_dequeue(struct intel_engine_cs *engine)
+static int guc_lrc_desc_pin(struct intel_context *ce, bool loop);
+
+static int guc_add_request(struct intel_guc *guc, struct i915_request *rq)
{
- struct intel_engine_execlists * const execlists = &engine->execlists;
- struct i915_request **first = execlists->inflight;
- struct i915_request ** const last_port = first + execlists->port_mask;
- struct i915_request *last = first[0];
- struct i915_request **port;
- bool submit = false;
- struct rb_node *rb;
+ int err = 0;
+ struct intel_context *ce = rq->context;
+ u32 action[3];
+ int len = 0;
+ u32 g2h_len_dw = 0;
+ bool enabled;
- lockdep_assert_held(&engine->active.lock);
+ /*
+ * Corner case where requests were sitting in the priority list or a
+ * request resubmitted after the context was banned.
+ */
+ if (unlikely(intel_context_is_banned(ce))) {
+ i915_request_put(i915_request_mark_eio(rq));
+ intel_engine_signal_breadcrumbs(ce->engine);
+ goto out;
+ }
- if (last) {
- if (*++first)
- return;
+ GEM_BUG_ON(!atomic_read(&ce->guc_id_ref));
+ GEM_BUG_ON(context_guc_id_invalid(ce));
- last = NULL;
+ /*
+ * Corner case where the GuC firmware was blown away and reloaded while
+ * this context was pinned.
+ */
+ if (unlikely(!lrc_desc_registered(guc, ce->guc_id))) {
+ err = guc_lrc_desc_pin(ce, false);
+ if (unlikely(err))
+ goto out;
}
/*
- * We write directly into the execlists->inflight queue and don't use
- * the execlists->pending queue, as we don't have a distinct switch
- * event.
+ * The request / context will be run on the hardware when scheduling
+ * gets enabled in the unblock.
*/
- port = first;
- while ((rb = rb_first_cached(&execlists->queue))) {
+ if (unlikely(context_blocked(ce)))
+ goto out;
+
+ enabled = context_enabled(ce);
+
+ if (!enabled) {
+ action[len++] = INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_SET;
+ action[len++] = ce->guc_id;
+ action[len++] = GUC_CONTEXT_ENABLE;
+ set_context_pending_enable(ce);
+ intel_context_get(ce);
+ g2h_len_dw = G2H_LEN_DW_SCHED_CONTEXT_MODE_SET;
+ } else {
+ action[len++] = INTEL_GUC_ACTION_SCHED_CONTEXT;
+ action[len++] = ce->guc_id;
+ }
+
+ err = intel_guc_send_nb(guc, action, len, g2h_len_dw);
+ if (!enabled && !err) {
+ trace_intel_context_sched_enable(ce);
+ atomic_inc(&guc->outstanding_submission_g2h);
+ set_context_enabled(ce);
+ } else if (!enabled) {
+ clr_context_pending_enable(ce);
+ intel_context_put(ce);
+ }
+ if (likely(!err))
+ trace_i915_request_guc_submit(rq);
+
+out:
+ return err;
+}
+
+static inline void guc_set_lrc_tail(struct i915_request *rq)
+{
+ rq->context->lrc_reg_state[CTX_RING_TAIL] =
+ intel_ring_set_tail(rq->ring, rq->tail);
+}
+
+static inline int rq_prio(const struct i915_request *rq)
+{
+ return rq->sched.attr.priority;
+}
+
+static int guc_dequeue_one_context(struct intel_guc *guc)
+{
+ struct i915_sched_engine * const sched_engine = guc->sched_engine;
+ struct i915_request *last = NULL;
+ bool submit = false;
+ struct rb_node *rb;
+ int ret;
+
+ lockdep_assert_held(&sched_engine->lock);
+
+ if (guc->stalled_request) {
+ submit = true;
+ last = guc->stalled_request;
+ goto resubmit;
+ }
+
+ while ((rb = rb_first_cached(&sched_engine->queue))) {
struct i915_priolist *p = to_priolist(rb);
struct i915_request *rq, *rn;
priolist_for_each_request_consume(rq, rn, p) {
- if (last && rq->context != last->context) {
- if (port == last_port)
- goto done;
-
- *port = schedule_in(last,
- port - execlists->inflight);
- port++;
- }
+ if (last && rq->context != last->context)
+ goto done;
list_del_init(&rq->sched.link);
+
__i915_request_submit(rq);
- submit = true;
+
+ trace_i915_request_in(rq, 0);
last = rq;
+ submit = true;
}
- rb_erase_cached(&p->node, &execlists->queue);
+ rb_erase_cached(&p->node, &sched_engine->queue);
i915_priolist_free(p);
}
done:
- execlists->queue_priority_hint =
- rb ? to_priolist(rb)->priority : INT_MIN;
if (submit) {
- *port = schedule_in(last, port - execlists->inflight);
- *++port = NULL;
- guc_submit(engine, first, port);
+ guc_set_lrc_tail(last);
+resubmit:
+ ret = guc_add_request(guc, last);
+ if (unlikely(ret == -EPIPE))
+ goto deadlk;
+ else if (ret == -EBUSY) {
+ tasklet_schedule(&sched_engine->tasklet);
+ guc->stalled_request = last;
+ return false;
+ }
}
- execlists->active = execlists->inflight;
+
+ guc->stalled_request = NULL;
+ return submit;
+
+deadlk:
+ sched_engine->tasklet.callback = NULL;
+ tasklet_disable_nosync(&sched_engine->tasklet);
+ return false;
}
static void guc_submission_tasklet(struct tasklet_struct *t)
{
- struct intel_engine_cs * const engine =
- from_tasklet(engine, t, execlists.tasklet);
- struct intel_engine_execlists * const execlists = &engine->execlists;
- struct i915_request **port, *rq;
+ struct i915_sched_engine *sched_engine =
+ from_tasklet(sched_engine, t, tasklet);
unsigned long flags;
+ bool loop;
- spin_lock_irqsave(&engine->active.lock, flags);
-
- for (port = execlists->inflight; (rq = *port); port++) {
- if (!i915_request_completed(rq))
- break;
+ spin_lock_irqsave(&sched_engine->lock, flags);
- schedule_out(rq);
- }
- if (port != execlists->inflight) {
- int idx = port - execlists->inflight;
- int rem = ARRAY_SIZE(execlists->inflight) - idx;
- memmove(execlists->inflight, port, rem * sizeof(*port));
- }
+ do {
+ loop = guc_dequeue_one_context(sched_engine->private_data);
+ } while (loop);
- __guc_dequeue(engine);
+ i915_sched_engine_reset_on_empty(sched_engine);
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&sched_engine->lock, flags);
}
static void cs_irq_handler(struct intel_engine_cs *engine, u16 iir)
{
- if (iir & GT_RENDER_USER_INTERRUPT) {
+ if (iir & GT_RENDER_USER_INTERRUPT)
intel_engine_signal_breadcrumbs(engine);
- tasklet_hi_schedule(&engine->execlists.tasklet);
+}
+
+static void __guc_context_destroy(struct intel_context *ce);
+static void release_guc_id(struct intel_guc *guc, struct intel_context *ce);
+static void guc_signal_context_fence(struct intel_context *ce);
+static void guc_cancel_context_requests(struct intel_context *ce);
+static void guc_blocked_fence_complete(struct intel_context *ce);
+
+static void scrub_guc_desc_for_outstanding_g2h(struct intel_guc *guc)
+{
+ struct intel_context *ce;
+ unsigned long index, flags;
+ bool pending_disable, pending_enable, deregister, destroyed, banned;
+
+ xa_for_each(&guc->context_lookup, index, ce) {
+ /* Flush context */
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ /*
+ * Once we are at this point submission_disabled() is guaranteed
+ * to be visible to all callers who set the below flags (see above
+ * flush and flushes in reset_prepare). If submission_disabled()
+ * is set, the caller shouldn't set these flags.
+ */
+
+ destroyed = context_destroyed(ce);
+ pending_enable = context_pending_enable(ce);
+ pending_disable = context_pending_disable(ce);
+ deregister = context_wait_for_deregister_to_register(ce);
+ banned = context_banned(ce);
+ init_sched_state(ce);
+
+ if (pending_enable || destroyed || deregister) {
+ atomic_dec(&guc->outstanding_submission_g2h);
+ if (deregister)
+ guc_signal_context_fence(ce);
+ if (destroyed) {
+ release_guc_id(guc, ce);
+ __guc_context_destroy(ce);
+ }
+ if (pending_enable || deregister)
+ intel_context_put(ce);
+ }
+
+ /* Not mutualy exclusive with above if statement. */
+ if (pending_disable) {
+ guc_signal_context_fence(ce);
+ if (banned) {
+ guc_cancel_context_requests(ce);
+ intel_engine_signal_breadcrumbs(ce->engine);
+ }
+ intel_context_sched_disable_unpin(ce);
+ atomic_dec(&guc->outstanding_submission_g2h);
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ guc_blocked_fence_complete(ce);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ intel_context_put(ce);
+ }
}
}
-static void guc_reset_prepare(struct intel_engine_cs *engine)
+static inline bool
+submission_disabled(struct intel_guc *guc)
+{
+ struct i915_sched_engine * const sched_engine = guc->sched_engine;
+
+ return unlikely(!sched_engine ||
+ !__tasklet_is_enabled(&sched_engine->tasklet));
+}
+
+static void disable_submission(struct intel_guc *guc)
{
- struct intel_engine_execlists * const execlists = &engine->execlists;
+ struct i915_sched_engine * const sched_engine = guc->sched_engine;
+
+ if (__tasklet_is_enabled(&sched_engine->tasklet)) {
+ GEM_BUG_ON(!guc->ct.enabled);
+ __tasklet_disable_sync_once(&sched_engine->tasklet);
+ sched_engine->tasklet.callback = NULL;
+ }
+}
+
+static void enable_submission(struct intel_guc *guc)
+{
+ struct i915_sched_engine * const sched_engine = guc->sched_engine;
+ unsigned long flags;
- ENGINE_TRACE(engine, "\n");
+ spin_lock_irqsave(&guc->sched_engine->lock, flags);
+ sched_engine->tasklet.callback = guc_submission_tasklet;
+ wmb(); /* Make sure callback visible */
+ if (!__tasklet_is_enabled(&sched_engine->tasklet) &&
+ __tasklet_enable(&sched_engine->tasklet)) {
+ GEM_BUG_ON(!guc->ct.enabled);
+
+ /* And kick in case we missed a new request submission. */
+ tasklet_hi_schedule(&sched_engine->tasklet);
+ }
+ spin_unlock_irqrestore(&guc->sched_engine->lock, flags);
+}
+
+static void guc_flush_submissions(struct intel_guc *guc)
+{
+ struct i915_sched_engine * const sched_engine = guc->sched_engine;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sched_engine->lock, flags);
+ spin_unlock_irqrestore(&sched_engine->lock, flags);
+}
+
+void intel_guc_submission_reset_prepare(struct intel_guc *guc)
+{
+ int i;
+
+ if (unlikely(!guc_submission_initialized(guc))) {
+ /* Reset called during driver load? GuC not yet initialised! */
+ return;
+ }
+
+ intel_gt_park_heartbeats(guc_to_gt(guc));
+ disable_submission(guc);
+ guc->interrupts.disable(guc);
+
+ /* Flush IRQ handler */
+ spin_lock_irq(&guc_to_gt(guc)->irq_lock);
+ spin_unlock_irq(&guc_to_gt(guc)->irq_lock);
+
+ guc_flush_submissions(guc);
/*
- * Prevent request submission to the hardware until we have
- * completed the reset in i915_gem_reset_finish(). If a request
- * is completed by one engine, it may then queue a request
- * to a second via its execlists->tasklet *just* as we are
- * calling engine->init_hw() and also writing the ELSP.
- * Turning off the execlists->tasklet until the reset is over
- * prevents the race.
+ * Handle any outstanding G2Hs before reset. Call IRQ handler directly
+ * each pass as interrupt have been disabled. We always scrub for
+ * outstanding G2H as it is possible for outstanding_submission_g2h to
+ * be incremented after the context state update.
*/
- __tasklet_disable_sync_once(&execlists->tasklet);
+ for (i = 0; i < 4 && atomic_read(&guc->outstanding_submission_g2h); ++i) {
+ intel_guc_to_host_event_handler(guc);
+#define wait_for_reset(guc, wait_var) \
+ intel_guc_wait_for_pending_msg(guc, wait_var, false, (HZ / 20))
+ do {
+ wait_for_reset(guc, &guc->outstanding_submission_g2h);
+ } while (!list_empty(&guc->ct.requests.incoming));
+ }
+ scrub_guc_desc_for_outstanding_g2h(guc);
+}
+
+static struct intel_engine_cs *
+guc_virtual_get_sibling(struct intel_engine_cs *ve, unsigned int sibling)
+{
+ struct intel_engine_cs *engine;
+ intel_engine_mask_t tmp, mask = ve->mask;
+ unsigned int num_siblings = 0;
+
+ for_each_engine_masked(engine, ve->gt, mask, tmp)
+ if (num_siblings++ == sibling)
+ return engine;
+
+ return NULL;
+}
+
+static inline struct intel_engine_cs *
+__context_to_physical_engine(struct intel_context *ce)
+{
+ struct intel_engine_cs *engine = ce->engine;
+
+ if (intel_engine_is_virtual(engine))
+ engine = guc_virtual_get_sibling(engine, 0);
+
+ return engine;
}
-static void guc_reset_state(struct intel_context *ce,
- struct intel_engine_cs *engine,
- u32 head,
- bool scrub)
+static void guc_reset_state(struct intel_context *ce, u32 head, bool scrub)
{
+ struct intel_engine_cs *engine = __context_to_physical_engine(ce);
+
+ if (intel_context_is_banned(ce))
+ return;
+
GEM_BUG_ON(!intel_context_is_pinned(ce));
/*
@@ -313,37 +777,132 @@ static void guc_reset_state(struct intel_context *ce,
lrc_update_regs(ce, engine, head);
}
-static void guc_reset_rewind(struct intel_engine_cs *engine, bool stalled)
+static void guc_reset_nop(struct intel_engine_cs *engine)
{
- struct intel_engine_execlists * const execlists = &engine->execlists;
- struct i915_request *rq;
+}
+
+static void guc_rewind_nop(struct intel_engine_cs *engine, bool stalled)
+{
+}
+
+static void
+__unwind_incomplete_requests(struct intel_context *ce)
+{
+ struct i915_request *rq, *rn;
+ struct list_head *pl;
+ int prio = I915_PRIORITY_INVALID;
+ struct i915_sched_engine * const sched_engine =
+ ce->engine->sched_engine;
unsigned long flags;
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&sched_engine->lock, flags);
+ spin_lock(&ce->guc_active.lock);
+ list_for_each_entry_safe(rq, rn,
+ &ce->guc_active.requests,
+ sched.link) {
+ if (i915_request_completed(rq))
+ continue;
- /* Push back any incomplete requests for replay after the reset. */
- rq = execlists_unwind_incomplete_requests(execlists);
- if (!rq)
- goto out_unlock;
+ list_del_init(&rq->sched.link);
+ spin_unlock(&ce->guc_active.lock);
+
+ __i915_request_unsubmit(rq);
+
+ /* Push the request back into the queue for later resubmission. */
+ GEM_BUG_ON(rq_prio(rq) == I915_PRIORITY_INVALID);
+ if (rq_prio(rq) != prio) {
+ prio = rq_prio(rq);
+ pl = i915_sched_lookup_priolist(sched_engine, prio);
+ }
+ GEM_BUG_ON(i915_sched_engine_is_empty(sched_engine));
+
+ list_add_tail(&rq->sched.link, pl);
+ set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+
+ spin_lock(&ce->guc_active.lock);
+ }
+ spin_unlock(&ce->guc_active.lock);
+ spin_unlock_irqrestore(&sched_engine->lock, flags);
+}
+
+static void __guc_reset_context(struct intel_context *ce, bool stalled)
+{
+ struct i915_request *rq;
+ u32 head;
+
+ intel_context_get(ce);
+
+ /*
+ * GuC will implicitly mark the context as non-schedulable
+ * when it sends the reset notification. Make sure our state
+ * reflects this change. The context will be marked enabled
+ * on resubmission.
+ */
+ clr_context_enabled(ce);
+
+ rq = intel_context_find_active_request(ce);
+ if (!rq) {
+ head = ce->ring->tail;
+ stalled = false;
+ goto out_replay;
+ }
if (!i915_request_started(rq))
stalled = false;
+ GEM_BUG_ON(i915_active_is_idle(&ce->active));
+ head = intel_ring_wrap(ce->ring, rq->head);
__i915_request_reset(rq, stalled);
- guc_reset_state(rq->context, engine, rq->head, stalled);
-out_unlock:
- spin_unlock_irqrestore(&engine->active.lock, flags);
+out_replay:
+ guc_reset_state(ce, head, stalled);
+ __unwind_incomplete_requests(ce);
+ intel_context_put(ce);
+}
+
+void intel_guc_submission_reset(struct intel_guc *guc, bool stalled)
+{
+ struct intel_context *ce;
+ unsigned long index;
+
+ if (unlikely(!guc_submission_initialized(guc))) {
+ /* Reset called during driver load? GuC not yet initialised! */
+ return;
+ }
+
+ xa_for_each(&guc->context_lookup, index, ce)
+ if (intel_context_is_pinned(ce))
+ __guc_reset_context(ce, stalled);
+
+ /* GuC is blown away, drop all references to contexts */
+ xa_destroy(&guc->context_lookup);
}
-static void guc_reset_cancel(struct intel_engine_cs *engine)
+static void guc_cancel_context_requests(struct intel_context *ce)
+{
+ struct i915_sched_engine *sched_engine = ce_to_guc(ce)->sched_engine;
+ struct i915_request *rq;
+ unsigned long flags;
+
+ /* Mark all executing requests as skipped. */
+ spin_lock_irqsave(&sched_engine->lock, flags);
+ spin_lock(&ce->guc_active.lock);
+ list_for_each_entry(rq, &ce->guc_active.requests, sched.link)
+ i915_request_put(i915_request_mark_eio(rq));
+ spin_unlock(&ce->guc_active.lock);
+ spin_unlock_irqrestore(&sched_engine->lock, flags);
+}
+
+static void
+guc_cancel_sched_engine_requests(struct i915_sched_engine *sched_engine)
{
- struct intel_engine_execlists * const execlists = &engine->execlists;
struct i915_request *rq, *rn;
struct rb_node *rb;
unsigned long flags;
- ENGINE_TRACE(engine, "\n");
+ /* Can be called during boot if GuC fails to load */
+ if (!sched_engine)
+ return;
/*
* Before we call engine->cancel_requests(), we should have exclusive
@@ -359,47 +918,67 @@ static void guc_reset_cancel(struct intel_engine_cs *engine)
* submission's irq state, we also wish to remind ourselves that
* it is irq state.)
*/
- spin_lock_irqsave(&engine->active.lock, flags);
-
- /* Mark all executing requests as skipped. */
- list_for_each_entry(rq, &engine->active.requests, sched.link) {
- i915_request_set_error_once(rq, -EIO);
- i915_request_mark_complete(rq);
- }
+ spin_lock_irqsave(&sched_engine->lock, flags);
/* Flush the queued requests to the timeline list (for retiring). */
- while ((rb = rb_first_cached(&execlists->queue))) {
+ while ((rb = rb_first_cached(&sched_engine->queue))) {
struct i915_priolist *p = to_priolist(rb);
priolist_for_each_request_consume(rq, rn, p) {
list_del_init(&rq->sched.link);
+
__i915_request_submit(rq);
- dma_fence_set_error(&rq->fence, -EIO);
- i915_request_mark_complete(rq);
+
+ i915_request_put(i915_request_mark_eio(rq));
}
- rb_erase_cached(&p->node, &execlists->queue);
+ rb_erase_cached(&p->node, &sched_engine->queue);
i915_priolist_free(p);
}
/* Remaining _unready_ requests will be nop'ed when submitted */
- execlists->queue_priority_hint = INT_MIN;
- execlists->queue = RB_ROOT_CACHED;
+ sched_engine->queue_priority_hint = INT_MIN;
+ sched_engine->queue = RB_ROOT_CACHED;
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&sched_engine->lock, flags);
}
-static void guc_reset_finish(struct intel_engine_cs *engine)
+void intel_guc_submission_cancel_requests(struct intel_guc *guc)
{
- struct intel_engine_execlists * const execlists = &engine->execlists;
+ struct intel_context *ce;
+ unsigned long index;
- if (__tasklet_enable(&execlists->tasklet))
- /* And kick in case we missed a new request submission. */
- tasklet_hi_schedule(&execlists->tasklet);
+ xa_for_each(&guc->context_lookup, index, ce)
+ if (intel_context_is_pinned(ce))
+ guc_cancel_context_requests(ce);
+
+ guc_cancel_sched_engine_requests(guc->sched_engine);
- ENGINE_TRACE(engine, "depth->%d\n",
- atomic_read(&execlists->tasklet.count));
+ /* GuC is blown away, drop all references to contexts */
+ xa_destroy(&guc->context_lookup);
+}
+
+void intel_guc_submission_reset_finish(struct intel_guc *guc)
+{
+ /* Reset called during driver load or during wedge? */
+ if (unlikely(!guc_submission_initialized(guc) ||
+ test_bit(I915_WEDGED, &guc_to_gt(guc)->reset.flags))) {
+ return;
+ }
+
+ /*
+ * Technically possible for either of these values to be non-zero here,
+ * but very unlikely + harmless. Regardless let's add a warn so we can
+ * see in CI if this happens frequently / a precursor to taking down the
+ * machine.
+ */
+ GEM_WARN_ON(atomic_read(&guc->outstanding_submission_g2h));
+ atomic_set(&guc->outstanding_submission_g2h, 0);
+
+ intel_guc_global_policies_update(guc);
+ enable_submission(guc);
+ intel_gt_unpark_heartbeats(guc_to_gt(guc));
}
/*
@@ -410,43 +989,986 @@ int intel_guc_submission_init(struct intel_guc *guc)
{
int ret;
- if (guc->stage_desc_pool)
+ if (guc->lrc_desc_pool)
return 0;
- ret = guc_stage_desc_pool_create(guc);
+ ret = guc_lrc_desc_pool_create(guc);
if (ret)
return ret;
/*
* Keep static analysers happy, let them know that we allocated the
* vma after testing that it didn't exist earlier.
*/
- GEM_BUG_ON(!guc->stage_desc_pool);
+ GEM_BUG_ON(!guc->lrc_desc_pool);
+
+ xa_init_flags(&guc->context_lookup, XA_FLAGS_LOCK_IRQ);
+
+ spin_lock_init(&guc->contexts_lock);
+ INIT_LIST_HEAD(&guc->guc_id_list);
+ ida_init(&guc->guc_ids);
return 0;
}
void intel_guc_submission_fini(struct intel_guc *guc)
{
- if (guc->stage_desc_pool) {
- guc_stage_desc_pool_destroy(guc);
+ if (!guc->lrc_desc_pool)
+ return;
+
+ guc_lrc_desc_pool_destroy(guc);
+ i915_sched_engine_put(guc->sched_engine);
+}
+
+static inline void queue_request(struct i915_sched_engine *sched_engine,
+ struct i915_request *rq,
+ int prio)
+{
+ GEM_BUG_ON(!list_empty(&rq->sched.link));
+ list_add_tail(&rq->sched.link,
+ i915_sched_lookup_priolist(sched_engine, prio));
+ set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+}
+
+static int guc_bypass_tasklet_submit(struct intel_guc *guc,
+ struct i915_request *rq)
+{
+ int ret;
+
+ __i915_request_submit(rq);
+
+ trace_i915_request_in(rq, 0);
+
+ guc_set_lrc_tail(rq);
+ ret = guc_add_request(guc, rq);
+ if (ret == -EBUSY)
+ guc->stalled_request = rq;
+
+ if (unlikely(ret == -EPIPE))
+ disable_submission(guc);
+
+ return ret;
+}
+
+static void guc_submit_request(struct i915_request *rq)
+{
+ struct i915_sched_engine *sched_engine = rq->engine->sched_engine;
+ struct intel_guc *guc = &rq->engine->gt->uc.guc;
+ unsigned long flags;
+
+ /* Will be called from irq-context when using foreign fences. */
+ spin_lock_irqsave(&sched_engine->lock, flags);
+
+ if (submission_disabled(guc) || guc->stalled_request ||
+ !i915_sched_engine_is_empty(sched_engine))
+ queue_request(sched_engine, rq, rq_prio(rq));
+ else if (guc_bypass_tasklet_submit(guc, rq) == -EBUSY)
+ tasklet_hi_schedule(&sched_engine->tasklet);
+
+ spin_unlock_irqrestore(&sched_engine->lock, flags);
+}
+
+static int new_guc_id(struct intel_guc *guc)
+{
+ return ida_simple_get(&guc->guc_ids, 0,
+ GUC_MAX_LRC_DESCRIPTORS, GFP_KERNEL |
+ __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
+}
+
+static void __release_guc_id(struct intel_guc *guc, struct intel_context *ce)
+{
+ if (!context_guc_id_invalid(ce)) {
+ ida_simple_remove(&guc->guc_ids, ce->guc_id);
+ reset_lrc_desc(guc, ce->guc_id);
+ set_context_guc_id_invalid(ce);
}
+ if (!list_empty(&ce->guc_id_link))
+ list_del_init(&ce->guc_id_link);
}
-static int guc_context_alloc(struct intel_context *ce)
+static void release_guc_id(struct intel_guc *guc, struct intel_context *ce)
{
- return lrc_alloc(ce, ce->engine);
+ unsigned long flags;
+
+ spin_lock_irqsave(&guc->contexts_lock, flags);
+ __release_guc_id(guc, ce);
+ spin_unlock_irqrestore(&guc->contexts_lock, flags);
+}
+
+static int steal_guc_id(struct intel_guc *guc)
+{
+ struct intel_context *ce;
+ int guc_id;
+
+ lockdep_assert_held(&guc->contexts_lock);
+
+ if (!list_empty(&guc->guc_id_list)) {
+ ce = list_first_entry(&guc->guc_id_list,
+ struct intel_context,
+ guc_id_link);
+
+ GEM_BUG_ON(atomic_read(&ce->guc_id_ref));
+ GEM_BUG_ON(context_guc_id_invalid(ce));
+
+ list_del_init(&ce->guc_id_link);
+ guc_id = ce->guc_id;
+ clr_context_registered(ce);
+ set_context_guc_id_invalid(ce);
+ return guc_id;
+ } else {
+ return -EAGAIN;
+ }
+}
+
+static int assign_guc_id(struct intel_guc *guc, u16 *out)
+{
+ int ret;
+
+ lockdep_assert_held(&guc->contexts_lock);
+
+ ret = new_guc_id(guc);
+ if (unlikely(ret < 0)) {
+ ret = steal_guc_id(guc);
+ if (ret < 0)
+ return ret;
+ }
+
+ *out = ret;
+ return 0;
+}
+
+#define PIN_GUC_ID_TRIES 4
+static int pin_guc_id(struct intel_guc *guc, struct intel_context *ce)
+{
+ int ret = 0;
+ unsigned long flags, tries = PIN_GUC_ID_TRIES;
+
+ GEM_BUG_ON(atomic_read(&ce->guc_id_ref));
+
+try_again:
+ spin_lock_irqsave(&guc->contexts_lock, flags);
+
+ if (context_guc_id_invalid(ce)) {
+ ret = assign_guc_id(guc, &ce->guc_id);
+ if (ret)
+ goto out_unlock;
+ ret = 1; /* Indidcates newly assigned guc_id */
+ }
+ if (!list_empty(&ce->guc_id_link))
+ list_del_init(&ce->guc_id_link);
+ atomic_inc(&ce->guc_id_ref);
+
+out_unlock:
+ spin_unlock_irqrestore(&guc->contexts_lock, flags);
+
+ /*
+ * -EAGAIN indicates no guc_ids are available, let's retire any
+ * outstanding requests to see if that frees up a guc_id. If the first
+ * retire didn't help, insert a sleep with the timeslice duration before
+ * attempting to retire more requests. Double the sleep period each
+ * subsequent pass before finally giving up. The sleep period has max of
+ * 100ms and minimum of 1ms.
+ */
+ if (ret == -EAGAIN && --tries) {
+ if (PIN_GUC_ID_TRIES - tries > 1) {
+ unsigned int timeslice_shifted =
+ ce->engine->props.timeslice_duration_ms <<
+ (PIN_GUC_ID_TRIES - tries - 2);
+ unsigned int max = min_t(unsigned int, 100,
+ timeslice_shifted);
+
+ msleep(max_t(unsigned int, max, 1));
+ }
+ intel_gt_retire_requests(guc_to_gt(guc));
+ goto try_again;
+ }
+
+ return ret;
+}
+
+static void unpin_guc_id(struct intel_guc *guc, struct intel_context *ce)
+{
+ unsigned long flags;
+
+ GEM_BUG_ON(atomic_read(&ce->guc_id_ref) < 0);
+
+ if (unlikely(context_guc_id_invalid(ce)))
+ return;
+
+ spin_lock_irqsave(&guc->contexts_lock, flags);
+ if (!context_guc_id_invalid(ce) && list_empty(&ce->guc_id_link) &&
+ !atomic_read(&ce->guc_id_ref))
+ list_add_tail(&ce->guc_id_link, &guc->guc_id_list);
+ spin_unlock_irqrestore(&guc->contexts_lock, flags);
+}
+
+static int __guc_action_register_context(struct intel_guc *guc,
+ u32 guc_id,
+ u32 offset,
+ bool loop)
+{
+ u32 action[] = {
+ INTEL_GUC_ACTION_REGISTER_CONTEXT,
+ guc_id,
+ offset,
+ };
+
+ return guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action),
+ 0, loop);
+}
+
+static int register_context(struct intel_context *ce, bool loop)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+ u32 offset = intel_guc_ggtt_offset(guc, guc->lrc_desc_pool) +
+ ce->guc_id * sizeof(struct guc_lrc_desc);
+ int ret;
+
+ trace_intel_context_register(ce);
+
+ ret = __guc_action_register_context(guc, ce->guc_id, offset, loop);
+ if (likely(!ret))
+ set_context_registered(ce);
+
+ return ret;
+}
+
+static int __guc_action_deregister_context(struct intel_guc *guc,
+ u32 guc_id,
+ bool loop)
+{
+ u32 action[] = {
+ INTEL_GUC_ACTION_DEREGISTER_CONTEXT,
+ guc_id,
+ };
+
+ return guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action),
+ G2H_LEN_DW_DEREGISTER_CONTEXT,
+ loop);
+}
+
+static int deregister_context(struct intel_context *ce, u32 guc_id, bool loop)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+
+ trace_intel_context_deregister(ce);
+
+ return __guc_action_deregister_context(guc, guc_id, loop);
+}
+
+static intel_engine_mask_t adjust_engine_mask(u8 class, intel_engine_mask_t mask)
+{
+ switch (class) {
+ case RENDER_CLASS:
+ return mask >> RCS0;
+ case VIDEO_ENHANCEMENT_CLASS:
+ return mask >> VECS0;
+ case VIDEO_DECODE_CLASS:
+ return mask >> VCS0;
+ case COPY_ENGINE_CLASS:
+ return mask >> BCS0;
+ default:
+ MISSING_CASE(class);
+ return 0;
+ }
+}
+
+static void guc_context_policy_init(struct intel_engine_cs *engine,
+ struct guc_lrc_desc *desc)
+{
+ desc->policy_flags = 0;
+
+ if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION)
+ desc->policy_flags |= CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE;
+
+ /* NB: For both of these, zero means disabled. */
+ desc->execution_quantum = engine->props.timeslice_duration_ms * 1000;
+ desc->preemption_timeout = engine->props.preempt_timeout_ms * 1000;
+}
+
+static inline u8 map_i915_prio_to_guc_prio(int prio);
+
+static int guc_lrc_desc_pin(struct intel_context *ce, bool loop)
+{
+ struct intel_engine_cs *engine = ce->engine;
+ struct intel_runtime_pm *runtime_pm = engine->uncore->rpm;
+ struct intel_guc *guc = &engine->gt->uc.guc;
+ u32 desc_idx = ce->guc_id;
+ struct guc_lrc_desc *desc;
+ const struct i915_gem_context *ctx;
+ int prio = I915_CONTEXT_DEFAULT_PRIORITY;
+ bool context_registered;
+ intel_wakeref_t wakeref;
+ int ret = 0;
+
+ GEM_BUG_ON(!engine->mask);
+
+ /*
+ * Ensure LRC + CT vmas are is same region as write barrier is done
+ * based on CT vma region.
+ */
+ GEM_BUG_ON(i915_gem_object_is_lmem(guc->ct.vma->obj) !=
+ i915_gem_object_is_lmem(ce->ring->vma->obj));
+
+ context_registered = lrc_desc_registered(guc, desc_idx);
+
+ rcu_read_lock();
+ ctx = rcu_dereference(ce->gem_context);
+ if (ctx)
+ prio = ctx->sched.priority;
+ rcu_read_unlock();
+
+ reset_lrc_desc(guc, desc_idx);
+ set_lrc_desc_registered(guc, desc_idx, ce);
+
+ desc = __get_lrc_desc(guc, desc_idx);
+ desc->engine_class = engine_class_to_guc_class(engine->class);
+ desc->engine_submit_mask = adjust_engine_mask(engine->class,
+ engine->mask);
+ desc->hw_context_desc = ce->lrc.lrca;
+ ce->guc_prio = map_i915_prio_to_guc_prio(prio);
+ desc->priority = ce->guc_prio;
+ desc->context_flags = CONTEXT_REGISTRATION_FLAG_KMD;
+ guc_context_policy_init(engine, desc);
+ init_sched_state(ce);
+
+ /*
+ * The context_lookup xarray is used to determine if the hardware
+ * context is currently registered. There are two cases in which it
+ * could be registered either the guc_id has been stolen from another
+ * context or the lrc descriptor address of this context has changed. In
+ * either case the context needs to be deregistered with the GuC before
+ * registering this context.
+ */
+ if (context_registered) {
+ trace_intel_context_steal_guc_id(ce);
+ if (!loop) {
+ set_context_wait_for_deregister_to_register(ce);
+ intel_context_get(ce);
+ } else {
+ bool disabled;
+ unsigned long flags;
+
+ /* Seal race with Reset */
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ disabled = submission_disabled(guc);
+ if (likely(!disabled)) {
+ set_context_wait_for_deregister_to_register(ce);
+ intel_context_get(ce);
+ }
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+ if (unlikely(disabled)) {
+ reset_lrc_desc(guc, desc_idx);
+ return 0; /* Will get registered later */
+ }
+ }
+
+ /*
+ * If stealing the guc_id, this ce has the same guc_id as the
+ * context whose guc_id was stolen.
+ */
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ ret = deregister_context(ce, ce->guc_id, loop);
+ if (unlikely(ret == -EBUSY)) {
+ clr_context_wait_for_deregister_to_register(ce);
+ intel_context_put(ce);
+ } else if (unlikely(ret == -ENODEV)) {
+ ret = 0; /* Will get registered later */
+ }
+ } else {
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ ret = register_context(ce, loop);
+ if (unlikely(ret == -EBUSY))
+ reset_lrc_desc(guc, desc_idx);
+ else if (unlikely(ret == -ENODEV))
+ ret = 0; /* Will get registered later */
+ }
+
+ return ret;
+}
+
+static int __guc_context_pre_pin(struct intel_context *ce,
+ struct intel_engine_cs *engine,
+ struct i915_gem_ww_ctx *ww,
+ void **vaddr)
+{
+ return lrc_pre_pin(ce, engine, ww, vaddr);
+}
+
+static int __guc_context_pin(struct intel_context *ce,
+ struct intel_engine_cs *engine,
+ void *vaddr)
+{
+ if (i915_ggtt_offset(ce->state) !=
+ (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK))
+ set_bit(CONTEXT_LRCA_DIRTY, &ce->flags);
+
+ /*
+ * GuC context gets pinned in guc_request_alloc. See that function for
+ * explaination of why.
+ */
+
+ return lrc_pin(ce, engine, vaddr);
}
static int guc_context_pre_pin(struct intel_context *ce,
struct i915_gem_ww_ctx *ww,
void **vaddr)
{
- return lrc_pre_pin(ce, ce->engine, ww, vaddr);
+ return __guc_context_pre_pin(ce, ce->engine, ww, vaddr);
}
static int guc_context_pin(struct intel_context *ce, void *vaddr)
{
- return lrc_pin(ce, ce->engine, vaddr);
+ return __guc_context_pin(ce, ce->engine, vaddr);
+}
+
+static void guc_context_unpin(struct intel_context *ce)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+
+ unpin_guc_id(guc, ce);
+ lrc_unpin(ce);
+}
+
+static void guc_context_post_unpin(struct intel_context *ce)
+{
+ lrc_post_unpin(ce);
+}
+
+static void __guc_context_sched_enable(struct intel_guc *guc,
+ struct intel_context *ce)
+{
+ u32 action[] = {
+ INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_SET,
+ ce->guc_id,
+ GUC_CONTEXT_ENABLE
+ };
+
+ trace_intel_context_sched_enable(ce);
+
+ guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action),
+ G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, true);
+}
+
+static void __guc_context_sched_disable(struct intel_guc *guc,
+ struct intel_context *ce,
+ u16 guc_id)
+{
+ u32 action[] = {
+ INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_SET,
+ guc_id, /* ce->guc_id not stable */
+ GUC_CONTEXT_DISABLE
+ };
+
+ GEM_BUG_ON(guc_id == GUC_INVALID_LRC_ID);
+
+ trace_intel_context_sched_disable(ce);
+
+ guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action),
+ G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, true);
+}
+
+static void guc_blocked_fence_complete(struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_state.lock);
+
+ if (!i915_sw_fence_done(&ce->guc_blocked))
+ i915_sw_fence_complete(&ce->guc_blocked);
+}
+
+static void guc_blocked_fence_reinit(struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_state.lock);
+ GEM_BUG_ON(!i915_sw_fence_done(&ce->guc_blocked));
+
+ /*
+ * This fence is always complete unless a pending schedule disable is
+ * outstanding. We arm the fence here and complete it when we receive
+ * the pending schedule disable complete message.
+ */
+ i915_sw_fence_fini(&ce->guc_blocked);
+ i915_sw_fence_reinit(&ce->guc_blocked);
+ i915_sw_fence_await(&ce->guc_blocked);
+ i915_sw_fence_commit(&ce->guc_blocked);
+}
+
+static u16 prep_context_pending_disable(struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_state.lock);
+
+ set_context_pending_disable(ce);
+ clr_context_enabled(ce);
+ guc_blocked_fence_reinit(ce);
+ intel_context_get(ce);
+
+ return ce->guc_id;
+}
+
+static struct i915_sw_fence *guc_context_block(struct intel_context *ce)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+ struct i915_sched_engine *sched_engine = ce->engine->sched_engine;
+ unsigned long flags;
+ struct intel_runtime_pm *runtime_pm = ce->engine->uncore->rpm;
+ intel_wakeref_t wakeref;
+ u16 guc_id;
+ bool enabled;
+
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+
+ /*
+ * Sync with submission path, increment before below changes to context
+ * state.
+ */
+ spin_lock(&sched_engine->lock);
+ incr_context_blocked(ce);
+ spin_unlock(&sched_engine->lock);
+
+ enabled = context_enabled(ce);
+ if (unlikely(!enabled || submission_disabled(guc))) {
+ if (enabled)
+ clr_context_enabled(ce);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+ return &ce->guc_blocked;
+ }
+
+ /*
+ * We add +2 here as the schedule disable complete CTB handler calls
+ * intel_context_sched_disable_unpin (-2 to pin_count).
+ */
+ atomic_add(2, &ce->pin_count);
+
+ guc_id = prep_context_pending_disable(ce);
+
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ __guc_context_sched_disable(guc, ce, guc_id);
+
+ return &ce->guc_blocked;
+}
+
+static void guc_context_unblock(struct intel_context *ce)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+ struct i915_sched_engine *sched_engine = ce->engine->sched_engine;
+ unsigned long flags;
+ struct intel_runtime_pm *runtime_pm = ce->engine->uncore->rpm;
+ intel_wakeref_t wakeref;
+ bool enable;
+
+ GEM_BUG_ON(context_enabled(ce));
+
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+
+ if (unlikely(submission_disabled(guc) ||
+ !intel_context_is_pinned(ce) ||
+ context_pending_disable(ce) ||
+ context_blocked(ce) > 1)) {
+ enable = false;
+ } else {
+ enable = true;
+ set_context_pending_enable(ce);
+ set_context_enabled(ce);
+ intel_context_get(ce);
+ }
+
+ /*
+ * Sync with submission path, decrement after above changes to context
+ * state.
+ */
+ spin_lock(&sched_engine->lock);
+ decr_context_blocked(ce);
+ spin_unlock(&sched_engine->lock);
+
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ if (enable) {
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ __guc_context_sched_enable(guc, ce);
+ }
+}
+
+static void guc_context_cancel_request(struct intel_context *ce,
+ struct i915_request *rq)
+{
+ if (i915_sw_fence_signaled(&rq->submit)) {
+ struct i915_sw_fence *fence = guc_context_block(ce);
+
+ i915_sw_fence_wait(fence);
+ if (!i915_request_completed(rq)) {
+ __i915_request_skip(rq);
+ guc_reset_state(ce, intel_ring_wrap(ce->ring, rq->head),
+ true);
+ }
+ guc_context_unblock(ce);
+ }
+}
+
+static void __guc_context_set_preemption_timeout(struct intel_guc *guc,
+ u16 guc_id,
+ u32 preemption_timeout)
+{
+ u32 action[] = {
+ INTEL_GUC_ACTION_SET_CONTEXT_PREEMPTION_TIMEOUT,
+ guc_id,
+ preemption_timeout
+ };
+
+ intel_guc_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true);
+}
+
+static void guc_context_ban(struct intel_context *ce, struct i915_request *rq)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+ struct intel_runtime_pm *runtime_pm =
+ &ce->engine->gt->i915->runtime_pm;
+ intel_wakeref_t wakeref;
+ unsigned long flags;
+
+ guc_flush_submissions(guc);
+
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ set_context_banned(ce);
+
+ if (submission_disabled(guc) ||
+ (!context_enabled(ce) && !context_pending_disable(ce))) {
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ guc_cancel_context_requests(ce);
+ intel_engine_signal_breadcrumbs(ce->engine);
+ } else if (!context_pending_disable(ce)) {
+ u16 guc_id;
+
+ /*
+ * We add +2 here as the schedule disable complete CTB handler
+ * calls intel_context_sched_disable_unpin (-2 to pin_count).
+ */
+ atomic_add(2, &ce->pin_count);
+
+ guc_id = prep_context_pending_disable(ce);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ /*
+ * In addition to disabling scheduling, set the preemption
+ * timeout to the minimum value (1 us) so the banned context
+ * gets kicked off the HW ASAP.
+ */
+ with_intel_runtime_pm(runtime_pm, wakeref) {
+ __guc_context_set_preemption_timeout(guc, guc_id, 1);
+ __guc_context_sched_disable(guc, ce, guc_id);
+ }
+ } else {
+ if (!context_guc_id_invalid(ce))
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ __guc_context_set_preemption_timeout(guc,
+ ce->guc_id,
+ 1);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+ }
+}
+
+static void guc_context_sched_disable(struct intel_context *ce)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+ unsigned long flags;
+ struct intel_runtime_pm *runtime_pm = &ce->engine->gt->i915->runtime_pm;
+ intel_wakeref_t wakeref;
+ u16 guc_id;
+ bool enabled;
+
+ if (submission_disabled(guc) || context_guc_id_invalid(ce) ||
+ !lrc_desc_registered(guc, ce->guc_id)) {
+ clr_context_enabled(ce);
+ goto unpin;
+ }
+
+ if (!context_enabled(ce))
+ goto unpin;
+
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+
+ /*
+ * We have to check if the context has been disabled by another thread.
+ * We also have to check if the context has been pinned again as another
+ * pin operation is allowed to pass this function. Checking the pin
+ * count, within ce->guc_state.lock, synchronizes this function with
+ * guc_request_alloc ensuring a request doesn't slip through the
+ * 'context_pending_disable' fence. Checking within the spin lock (can't
+ * sleep) ensures another process doesn't pin this context and generate
+ * a request before we set the 'context_pending_disable' flag here.
+ */
+ enabled = context_enabled(ce);
+ if (unlikely(!enabled || submission_disabled(guc))) {
+ if (enabled)
+ clr_context_enabled(ce);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+ goto unpin;
+ }
+ if (unlikely(atomic_add_unless(&ce->pin_count, -2, 2))) {
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+ return;
+ }
+ guc_id = prep_context_pending_disable(ce);
+
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ __guc_context_sched_disable(guc, ce, guc_id);
+
+ return;
+unpin:
+ intel_context_sched_disable_unpin(ce);
+}
+
+static inline void guc_lrc_desc_unpin(struct intel_context *ce)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+
+ GEM_BUG_ON(!lrc_desc_registered(guc, ce->guc_id));
+ GEM_BUG_ON(ce != __get_context(guc, ce->guc_id));
+ GEM_BUG_ON(context_enabled(ce));
+
+ clr_context_registered(ce);
+ deregister_context(ce, ce->guc_id, true);
+}
+
+static void __guc_context_destroy(struct intel_context *ce)
+{
+ GEM_BUG_ON(ce->guc_prio_count[GUC_CLIENT_PRIORITY_KMD_HIGH] ||
+ ce->guc_prio_count[GUC_CLIENT_PRIORITY_HIGH] ||
+ ce->guc_prio_count[GUC_CLIENT_PRIORITY_KMD_NORMAL] ||
+ ce->guc_prio_count[GUC_CLIENT_PRIORITY_NORMAL]);
+
+ lrc_fini(ce);
+ intel_context_fini(ce);
+
+ if (intel_engine_is_virtual(ce->engine)) {
+ struct guc_virtual_engine *ve =
+ container_of(ce, typeof(*ve), context);
+
+ if (ve->base.breadcrumbs)
+ intel_breadcrumbs_put(ve->base.breadcrumbs);
+
+ kfree(ve);
+ } else {
+ intel_context_free(ce);
+ }
+}
+
+static void guc_context_destroy(struct kref *kref)
+{
+ struct intel_context *ce = container_of(kref, typeof(*ce), ref);
+ struct intel_runtime_pm *runtime_pm = ce->engine->uncore->rpm;
+ struct intel_guc *guc = ce_to_guc(ce);
+ intel_wakeref_t wakeref;
+ unsigned long flags;
+ bool disabled;
+
+ /*
+ * If the guc_id is invalid this context has been stolen and we can free
+ * it immediately. Also can be freed immediately if the context is not
+ * registered with the GuC or the GuC is in the middle of a reset.
+ */
+ if (context_guc_id_invalid(ce)) {
+ __guc_context_destroy(ce);
+ return;
+ } else if (submission_disabled(guc) ||
+ !lrc_desc_registered(guc, ce->guc_id)) {
+ release_guc_id(guc, ce);
+ __guc_context_destroy(ce);
+ return;
+ }
+
+ /*
+ * We have to acquire the context spinlock and check guc_id again, if it
+ * is valid it hasn't been stolen and needs to be deregistered. We
+ * delete this context from the list of unpinned guc_ids available to
+ * steal to seal a race with guc_lrc_desc_pin(). When the G2H CTB
+ * returns indicating this context has been deregistered the guc_id is
+ * returned to the pool of available guc_ids.
+ */
+ spin_lock_irqsave(&guc->contexts_lock, flags);
+ if (context_guc_id_invalid(ce)) {
+ spin_unlock_irqrestore(&guc->contexts_lock, flags);
+ __guc_context_destroy(ce);
+ return;
+ }
+
+ if (!list_empty(&ce->guc_id_link))
+ list_del_init(&ce->guc_id_link);
+ spin_unlock_irqrestore(&guc->contexts_lock, flags);
+
+ /* Seal race with Reset */
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ disabled = submission_disabled(guc);
+ if (likely(!disabled))
+ set_context_destroyed(ce);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+ if (unlikely(disabled)) {
+ release_guc_id(guc, ce);
+ __guc_context_destroy(ce);
+ return;
+ }
+
+ /*
+ * We defer GuC context deregistration until the context is destroyed
+ * in order to save on CTBs. With this optimization ideally we only need
+ * 1 CTB to register the context during the first pin and 1 CTB to
+ * deregister the context when the context is destroyed. Without this
+ * optimization, a CTB would be needed every pin & unpin.
+ *
+ * XXX: Need to acqiure the runtime wakeref as this can be triggered
+ * from context_free_worker when runtime wakeref is not held.
+ * guc_lrc_desc_unpin requires the runtime as a GuC register is written
+ * in H2G CTB to deregister the context. A future patch may defer this
+ * H2G CTB if the runtime wakeref is zero.
+ */
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ guc_lrc_desc_unpin(ce);
+}
+
+static int guc_context_alloc(struct intel_context *ce)
+{
+ return lrc_alloc(ce, ce->engine);
+}
+
+static void guc_context_set_prio(struct intel_guc *guc,
+ struct intel_context *ce,
+ u8 prio)
+{
+ u32 action[] = {
+ INTEL_GUC_ACTION_SET_CONTEXT_PRIORITY,
+ ce->guc_id,
+ prio,
+ };
+
+ GEM_BUG_ON(prio < GUC_CLIENT_PRIORITY_KMD_HIGH ||
+ prio > GUC_CLIENT_PRIORITY_NORMAL);
+
+ if (ce->guc_prio == prio || submission_disabled(guc) ||
+ !context_registered(ce))
+ return;
+
+ guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true);
+
+ ce->guc_prio = prio;
+ trace_intel_context_set_prio(ce);
+}
+
+static inline u8 map_i915_prio_to_guc_prio(int prio)
+{
+ if (prio == I915_PRIORITY_NORMAL)
+ return GUC_CLIENT_PRIORITY_KMD_NORMAL;
+ else if (prio < I915_PRIORITY_NORMAL)
+ return GUC_CLIENT_PRIORITY_NORMAL;
+ else if (prio < I915_PRIORITY_DISPLAY)
+ return GUC_CLIENT_PRIORITY_HIGH;
+ else
+ return GUC_CLIENT_PRIORITY_KMD_HIGH;
+}
+
+static inline void add_context_inflight_prio(struct intel_context *ce,
+ u8 guc_prio)
+{
+ lockdep_assert_held(&ce->guc_active.lock);
+ GEM_BUG_ON(guc_prio >= ARRAY_SIZE(ce->guc_prio_count));
+
+ ++ce->guc_prio_count[guc_prio];
+
+ /* Overflow protection */
+ GEM_WARN_ON(!ce->guc_prio_count[guc_prio]);
+}
+
+static inline void sub_context_inflight_prio(struct intel_context *ce,
+ u8 guc_prio)
+{
+ lockdep_assert_held(&ce->guc_active.lock);
+ GEM_BUG_ON(guc_prio >= ARRAY_SIZE(ce->guc_prio_count));
+
+ /* Underflow protection */
+ GEM_WARN_ON(!ce->guc_prio_count[guc_prio]);
+
+ --ce->guc_prio_count[guc_prio];
+}
+
+static inline void update_context_prio(struct intel_context *ce)
+{
+ struct intel_guc *guc = &ce->engine->gt->uc.guc;
+ int i;
+
+ BUILD_BUG_ON(GUC_CLIENT_PRIORITY_KMD_HIGH != 0);
+ BUILD_BUG_ON(GUC_CLIENT_PRIORITY_KMD_HIGH > GUC_CLIENT_PRIORITY_NORMAL);
+
+ lockdep_assert_held(&ce->guc_active.lock);
+
+ for (i = 0; i < ARRAY_SIZE(ce->guc_prio_count); ++i) {
+ if (ce->guc_prio_count[i]) {
+ guc_context_set_prio(guc, ce, i);
+ break;
+ }
+ }
+}
+
+static inline bool new_guc_prio_higher(u8 old_guc_prio, u8 new_guc_prio)
+{
+ /* Lower value is higher priority */
+ return new_guc_prio < old_guc_prio;
+}
+
+static void add_to_context(struct i915_request *rq)
+{
+ struct intel_context *ce = rq->context;
+ u8 new_guc_prio = map_i915_prio_to_guc_prio(rq_prio(rq));
+
+ GEM_BUG_ON(rq->guc_prio == GUC_PRIO_FINI);
+
+ spin_lock(&ce->guc_active.lock);
+ list_move_tail(&rq->sched.link, &ce->guc_active.requests);
+
+ if (rq->guc_prio == GUC_PRIO_INIT) {
+ rq->guc_prio = new_guc_prio;
+ add_context_inflight_prio(ce, rq->guc_prio);
+ } else if (new_guc_prio_higher(rq->guc_prio, new_guc_prio)) {
+ sub_context_inflight_prio(ce, rq->guc_prio);
+ rq->guc_prio = new_guc_prio;
+ add_context_inflight_prio(ce, rq->guc_prio);
+ }
+ update_context_prio(ce);
+
+ spin_unlock(&ce->guc_active.lock);
+}
+
+static void guc_prio_fini(struct i915_request *rq, struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_active.lock);
+
+ if (rq->guc_prio != GUC_PRIO_INIT &&
+ rq->guc_prio != GUC_PRIO_FINI) {
+ sub_context_inflight_prio(ce, rq->guc_prio);
+ update_context_prio(ce);
+ }
+ rq->guc_prio = GUC_PRIO_FINI;
+}
+
+static void remove_from_context(struct i915_request *rq)
+{
+ struct intel_context *ce = rq->context;
+
+ spin_lock_irq(&ce->guc_active.lock);
+
+ list_del_init(&rq->sched.link);
+ clear_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+
+ /* Prevent further __await_execution() registering a cb, then flush */
+ set_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags);
+
+ guc_prio_fini(rq, ce);
+
+ spin_unlock_irq(&ce->guc_active.lock);
+
+ atomic_dec(&ce->guc_id_ref);
+ i915_request_notify_execute_cb_imm(rq);
}
static const struct intel_context_ops guc_context_ops = {
@@ -454,28 +1976,71 @@ static const struct intel_context_ops guc_context_ops = {
.pre_pin = guc_context_pre_pin,
.pin = guc_context_pin,
- .unpin = lrc_unpin,
- .post_unpin = lrc_post_unpin,
+ .unpin = guc_context_unpin,
+ .post_unpin = guc_context_post_unpin,
+
+ .ban = guc_context_ban,
+
+ .cancel_request = guc_context_cancel_request,
.enter = intel_context_enter_engine,
.exit = intel_context_exit_engine,
+ .sched_disable = guc_context_sched_disable,
+
.reset = lrc_reset,
- .destroy = lrc_destroy,
+ .destroy = guc_context_destroy,
+
+ .create_virtual = guc_create_virtual,
};
-static int guc_request_alloc(struct i915_request *request)
+static void __guc_signal_context_fence(struct intel_context *ce)
{
+ struct i915_request *rq;
+
+ lockdep_assert_held(&ce->guc_state.lock);
+
+ if (!list_empty(&ce->guc_state.fences))
+ trace_intel_context_fence_release(ce);
+
+ list_for_each_entry(rq, &ce->guc_state.fences, guc_fence_link)
+ i915_sw_fence_complete(&rq->submit);
+
+ INIT_LIST_HEAD(&ce->guc_state.fences);
+}
+
+static void guc_signal_context_fence(struct intel_context *ce)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ clr_context_wait_for_deregister_to_register(ce);
+ __guc_signal_context_fence(ce);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+}
+
+static bool context_needs_register(struct intel_context *ce, bool new_guc_id)
+{
+ return (new_guc_id || test_bit(CONTEXT_LRCA_DIRTY, &ce->flags) ||
+ !lrc_desc_registered(ce_to_guc(ce), ce->guc_id)) &&
+ !submission_disabled(ce_to_guc(ce));
+}
+
+static int guc_request_alloc(struct i915_request *rq)
+{
+ struct intel_context *ce = rq->context;
+ struct intel_guc *guc = ce_to_guc(ce);
+ unsigned long flags;
int ret;
- GEM_BUG_ON(!intel_context_is_pinned(request->context));
+ GEM_BUG_ON(!intel_context_is_pinned(rq->context));
/*
* Flush enough space to reduce the likelihood of waiting after
* we start building the request - in which case we will just
* have to repeat work.
*/
- request->reserved_space += GUC_REQUEST_SIZE;
+ rq->reserved_space += GUC_REQUEST_SIZE;
/*
* Note that after this point, we have committed to using
@@ -486,40 +2051,232 @@ static int guc_request_alloc(struct i915_request *request)
*/
/* Unconditionally invalidate GPU caches and TLBs. */
- ret = request->engine->emit_flush(request, EMIT_INVALIDATE);
+ ret = rq->engine->emit_flush(rq, EMIT_INVALIDATE);
if (ret)
return ret;
- request->reserved_space -= GUC_REQUEST_SIZE;
+ rq->reserved_space -= GUC_REQUEST_SIZE;
+
+ /*
+ * Call pin_guc_id here rather than in the pinning step as with
+ * dma_resv, contexts can be repeatedly pinned / unpinned trashing the
+ * guc_ids and creating horrible race conditions. This is especially bad
+ * when guc_ids are being stolen due to over subscription. By the time
+ * this function is reached, it is guaranteed that the guc_id will be
+ * persistent until the generated request is retired. Thus, sealing these
+ * race conditions. It is still safe to fail here if guc_ids are
+ * exhausted and return -EAGAIN to the user indicating that they can try
+ * again in the future.
+ *
+ * There is no need for a lock here as the timeline mutex ensures at
+ * most one context can be executing this code path at once. The
+ * guc_id_ref is incremented once for every request in flight and
+ * decremented on each retire. When it is zero, a lock around the
+ * increment (in pin_guc_id) is needed to seal a race with unpin_guc_id.
+ */
+ if (atomic_add_unless(&ce->guc_id_ref, 1, 0))
+ goto out;
+
+ ret = pin_guc_id(guc, ce); /* returns 1 if new guc_id assigned */
+ if (unlikely(ret < 0))
+ return ret;
+ if (context_needs_register(ce, !!ret)) {
+ ret = guc_lrc_desc_pin(ce, true);
+ if (unlikely(ret)) { /* unwind */
+ if (ret == -EPIPE) {
+ disable_submission(guc);
+ goto out; /* GPU will be reset */
+ }
+ atomic_dec(&ce->guc_id_ref);
+ unpin_guc_id(guc, ce);
+ return ret;
+ }
+ }
+
+ clear_bit(CONTEXT_LRCA_DIRTY, &ce->flags);
+
+out:
+ /*
+ * We block all requests on this context if a G2H is pending for a
+ * schedule disable or context deregistration as the GuC will fail a
+ * schedule enable or context registration if either G2H is pending
+ * respectfully. Once a G2H returns, the fence is released that is
+ * blocking these requests (see guc_signal_context_fence).
+ *
+ * We can safely check the below fields outside of the lock as it isn't
+ * possible for these fields to transition from being clear to set but
+ * converse is possible, hence the need for the check within the lock.
+ */
+ if (likely(!context_wait_for_deregister_to_register(ce) &&
+ !context_pending_disable(ce)))
+ return 0;
+
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ if (context_wait_for_deregister_to_register(ce) ||
+ context_pending_disable(ce)) {
+ i915_sw_fence_await(&rq->submit);
+
+ list_add_tail(&rq->guc_fence_link, &ce->guc_state.fences);
+ }
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
return 0;
}
-static inline void queue_request(struct intel_engine_cs *engine,
- struct i915_request *rq,
- int prio)
+static int guc_virtual_context_pre_pin(struct intel_context *ce,
+ struct i915_gem_ww_ctx *ww,
+ void **vaddr)
{
- GEM_BUG_ON(!list_empty(&rq->sched.link));
- list_add_tail(&rq->sched.link,
- i915_sched_lookup_priolist(engine, prio));
- set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+ struct intel_engine_cs *engine = guc_virtual_get_sibling(ce->engine, 0);
+
+ return __guc_context_pre_pin(ce, engine, ww, vaddr);
}
-static void guc_submit_request(struct i915_request *rq)
+static int guc_virtual_context_pin(struct intel_context *ce, void *vaddr)
{
- struct intel_engine_cs *engine = rq->engine;
- unsigned long flags;
+ struct intel_engine_cs *engine = guc_virtual_get_sibling(ce->engine, 0);
- /* Will be called from irq-context when using foreign fences. */
- spin_lock_irqsave(&engine->active.lock, flags);
+ return __guc_context_pin(ce, engine, vaddr);
+}
- queue_request(engine, rq, rq_prio(rq));
+static void guc_virtual_context_enter(struct intel_context *ce)
+{
+ intel_engine_mask_t tmp, mask = ce->engine->mask;
+ struct intel_engine_cs *engine;
- GEM_BUG_ON(RB_EMPTY_ROOT(&engine->execlists.queue.rb_root));
- GEM_BUG_ON(list_empty(&rq->sched.link));
+ for_each_engine_masked(engine, ce->engine->gt, mask, tmp)
+ intel_engine_pm_get(engine);
- tasklet_hi_schedule(&engine->execlists.tasklet);
+ intel_timeline_enter(ce->timeline);
+}
+
+static void guc_virtual_context_exit(struct intel_context *ce)
+{
+ intel_engine_mask_t tmp, mask = ce->engine->mask;
+ struct intel_engine_cs *engine;
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ for_each_engine_masked(engine, ce->engine->gt, mask, tmp)
+ intel_engine_pm_put(engine);
+
+ intel_timeline_exit(ce->timeline);
+}
+
+static int guc_virtual_context_alloc(struct intel_context *ce)
+{
+ struct intel_engine_cs *engine = guc_virtual_get_sibling(ce->engine, 0);
+
+ return lrc_alloc(ce, engine);
+}
+
+static const struct intel_context_ops virtual_guc_context_ops = {
+ .alloc = guc_virtual_context_alloc,
+
+ .pre_pin = guc_virtual_context_pre_pin,
+ .pin = guc_virtual_context_pin,
+ .unpin = guc_context_unpin,
+ .post_unpin = guc_context_post_unpin,
+
+ .ban = guc_context_ban,
+
+ .cancel_request = guc_context_cancel_request,
+
+ .enter = guc_virtual_context_enter,
+ .exit = guc_virtual_context_exit,
+
+ .sched_disable = guc_context_sched_disable,
+
+ .destroy = guc_context_destroy,
+
+ .get_sibling = guc_virtual_get_sibling,
+};
+
+static bool
+guc_irq_enable_breadcrumbs(struct intel_breadcrumbs *b)
+{
+ struct intel_engine_cs *sibling;
+ intel_engine_mask_t tmp, mask = b->engine_mask;
+ bool result = false;
+
+ for_each_engine_masked(sibling, b->irq_engine->gt, mask, tmp)
+ result |= intel_engine_irq_enable(sibling);
+
+ return result;
+}
+
+static void
+guc_irq_disable_breadcrumbs(struct intel_breadcrumbs *b)
+{
+ struct intel_engine_cs *sibling;
+ intel_engine_mask_t tmp, mask = b->engine_mask;
+
+ for_each_engine_masked(sibling, b->irq_engine->gt, mask, tmp)
+ intel_engine_irq_disable(sibling);
+}
+
+static void guc_init_breadcrumbs(struct intel_engine_cs *engine)
+{
+ int i;
+
+ /*
+ * In GuC submission mode we do not know which physical engine a request
+ * will be scheduled on, this creates a problem because the breadcrumb
+ * interrupt is per physical engine. To work around this we attach
+ * requests and direct all breadcrumb interrupts to the first instance
+ * of an engine per class. In addition all breadcrumb interrupts are
+ * enabled / disabled across an engine class in unison.
+ */
+ for (i = 0; i < MAX_ENGINE_INSTANCE; ++i) {
+ struct intel_engine_cs *sibling =
+ engine->gt->engine_class[engine->class][i];
+
+ if (sibling) {
+ if (engine->breadcrumbs != sibling->breadcrumbs) {
+ intel_breadcrumbs_put(engine->breadcrumbs);
+ engine->breadcrumbs =
+ intel_breadcrumbs_get(sibling->breadcrumbs);
+ }
+ break;
+ }
+ }
+
+ if (engine->breadcrumbs) {
+ engine->breadcrumbs->engine_mask |= engine->mask;
+ engine->breadcrumbs->irq_enable = guc_irq_enable_breadcrumbs;
+ engine->breadcrumbs->irq_disable = guc_irq_disable_breadcrumbs;
+ }
+}
+
+static void guc_bump_inflight_request_prio(struct i915_request *rq,
+ int prio)
+{
+ struct intel_context *ce = rq->context;
+ u8 new_guc_prio = map_i915_prio_to_guc_prio(prio);
+
+ /* Short circuit function */
+ if (prio < I915_PRIORITY_NORMAL ||
+ rq->guc_prio == GUC_PRIO_FINI ||
+ (rq->guc_prio != GUC_PRIO_INIT &&
+ !new_guc_prio_higher(rq->guc_prio, new_guc_prio)))
+ return;
+
+ spin_lock(&ce->guc_active.lock);
+ if (rq->guc_prio != GUC_PRIO_FINI) {
+ if (rq->guc_prio != GUC_PRIO_INIT)
+ sub_context_inflight_prio(ce, rq->guc_prio);
+ rq->guc_prio = new_guc_prio;
+ add_context_inflight_prio(ce, rq->guc_prio);
+ update_context_prio(ce);
+ }
+ spin_unlock(&ce->guc_active.lock);
+}
+
+static void guc_retire_inflight_request_prio(struct i915_request *rq)
+{
+ struct intel_context *ce = rq->context;
+
+ spin_lock(&ce->guc_active.lock);
+ guc_prio_fini(rq, ce);
+ spin_unlock(&ce->guc_active.lock);
}
static void sanitize_hwsp(struct intel_engine_cs *engine)
@@ -588,21 +2345,68 @@ static int guc_resume(struct intel_engine_cs *engine)
return 0;
}
+static bool guc_sched_engine_disabled(struct i915_sched_engine *sched_engine)
+{
+ return !sched_engine->tasklet.callback;
+}
+
static void guc_set_default_submission(struct intel_engine_cs *engine)
{
engine->submit_request = guc_submit_request;
}
+static inline void guc_kernel_context_pin(struct intel_guc *guc,
+ struct intel_context *ce)
+{
+ if (context_guc_id_invalid(ce))
+ pin_guc_id(guc, ce);
+ guc_lrc_desc_pin(ce, true);
+}
+
+static inline void guc_init_lrc_mapping(struct intel_guc *guc)
+{
+ struct intel_gt *gt = guc_to_gt(guc);
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ /* make sure all descriptors are clean... */
+ xa_destroy(&guc->context_lookup);
+
+ /*
+ * Some contexts might have been pinned before we enabled GuC
+ * submission, so we need to add them to the GuC bookeeping.
+ * Also, after a reset the of the GuC we want to make sure that the
+ * information shared with GuC is properly reset. The kernel LRCs are
+ * not attached to the gem_context, so they need to be added separately.
+ *
+ * Note: we purposefully do not check the return of guc_lrc_desc_pin,
+ * because that function can only fail if a reset is just starting. This
+ * is at the end of reset so presumably another reset isn't happening
+ * and even it did this code would be run again.
+ */
+
+ for_each_engine(engine, gt, id)
+ if (engine->kernel_context)
+ guc_kernel_context_pin(guc, engine->kernel_context);
+}
+
static void guc_release(struct intel_engine_cs *engine)
{
engine->sanitize = NULL; /* no longer in control, nothing to sanitize */
- tasklet_kill(&engine->execlists.tasklet);
-
intel_engine_cleanup_common(engine);
lrc_fini_wa_ctx(engine);
}
+static void virtual_guc_bump_serial(struct intel_engine_cs *engine)
+{
+ struct intel_engine_cs *e;
+ intel_engine_mask_t tmp, mask = engine->mask;
+
+ for_each_engine_masked(e, engine->gt, mask, tmp)
+ e->serial++;
+}
+
static void guc_default_vfuncs(struct intel_engine_cs *engine)
{
/* Default vfuncs which can be overridden by each engine. */
@@ -611,13 +2415,15 @@ static void guc_default_vfuncs(struct intel_engine_cs *engine)
engine->cops = &guc_context_ops;
engine->request_alloc = guc_request_alloc;
+ engine->add_active_request = add_to_context;
+ engine->remove_active_request = remove_from_context;
- engine->schedule = i915_schedule;
+ engine->sched_engine->schedule = i915_schedule;
- engine->reset.prepare = guc_reset_prepare;
- engine->reset.rewind = guc_reset_rewind;
- engine->reset.cancel = guc_reset_cancel;
- engine->reset.finish = guc_reset_finish;
+ engine->reset.prepare = guc_reset_nop;
+ engine->reset.rewind = guc_rewind_nop;
+ engine->reset.cancel = guc_reset_nop;
+ engine->reset.finish = guc_reset_nop;
engine->emit_flush = gen8_emit_flush_xcs;
engine->emit_init_breadcrumb = gen8_emit_init_breadcrumb;
@@ -629,13 +2435,13 @@ static void guc_default_vfuncs(struct intel_engine_cs *engine)
engine->set_default_submission = guc_set_default_submission;
engine->flags |= I915_ENGINE_HAS_PREEMPTION;
+ engine->flags |= I915_ENGINE_HAS_TIMESLICES;
/*
* TODO: GuC supports timeslicing and semaphores as well, but they're
* handled by the firmware so some minor tweaks are required before
* enabling.
*
- * engine->flags |= I915_ENGINE_HAS_TIMESLICES;
* engine->flags |= I915_ENGINE_HAS_SEMAPHORES;
*/
@@ -666,9 +2472,21 @@ static inline void guc_default_irqs(struct intel_engine_cs *engine)
intel_engine_set_irq_handler(engine, cs_irq_handler);
}
+static void guc_sched_engine_destroy(struct kref *kref)
+{
+ struct i915_sched_engine *sched_engine =
+ container_of(kref, typeof(*sched_engine), ref);
+ struct intel_guc *guc = sched_engine->private_data;
+
+ guc->sched_engine = NULL;
+ tasklet_kill(&sched_engine->tasklet); /* flush the callback */
+ kfree(sched_engine);
+}
+
int intel_guc_submission_setup(struct intel_engine_cs *engine)
{
struct drm_i915_private *i915 = engine->i915;
+ struct intel_guc *guc = &engine->gt->uc.guc;
/*
* The setup relies on several assumptions (e.g. irqs always enabled)
@@ -676,10 +2494,28 @@ int intel_guc_submission_setup(struct intel_engine_cs *engine)
*/
GEM_BUG_ON(GRAPHICS_VER(i915) < 11);
- tasklet_setup(&engine->execlists.tasklet, guc_submission_tasklet);
+ if (!guc->sched_engine) {
+ guc->sched_engine = i915_sched_engine_create(ENGINE_VIRTUAL);
+ if (!guc->sched_engine)
+ return -ENOMEM;
+
+ guc->sched_engine->schedule = i915_schedule;
+ guc->sched_engine->disabled = guc_sched_engine_disabled;
+ guc->sched_engine->private_data = guc;
+ guc->sched_engine->destroy = guc_sched_engine_destroy;
+ guc->sched_engine->bump_inflight_request_prio =
+ guc_bump_inflight_request_prio;
+ guc->sched_engine->retire_inflight_request_prio =
+ guc_retire_inflight_request_prio;
+ tasklet_setup(&guc->sched_engine->tasklet,
+ guc_submission_tasklet);
+ }
+ i915_sched_engine_put(engine->sched_engine);
+ engine->sched_engine = i915_sched_engine_get(guc->sched_engine);
guc_default_vfuncs(engine);
guc_default_irqs(engine);
+ guc_init_breadcrumbs(engine);
if (engine->class == RENDER_CLASS)
rcs_submission_override(engine);
@@ -695,18 +2531,19 @@ int intel_guc_submission_setup(struct intel_engine_cs *engine)
void intel_guc_submission_enable(struct intel_guc *guc)
{
- guc_stage_desc_init(guc);
+ guc_init_lrc_mapping(guc);
}
void intel_guc_submission_disable(struct intel_guc *guc)
{
- struct intel_gt *gt = guc_to_gt(guc);
-
- GEM_BUG_ON(gt->awake); /* GT should be parked first */
-
/* Note: By the time we're here, GuC may have already been reset */
+}
- guc_stage_desc_fini(guc);
+static bool __guc_submission_supported(struct intel_guc *guc)
+{
+ /* GuC submission is unavailable for pre-Gen11 */
+ return intel_guc_is_supported(guc) &&
+ GRAPHICS_VER(guc_to_gt(guc)->i915) >= 11;
}
static bool __guc_submission_selected(struct intel_guc *guc)
@@ -721,5 +2558,481 @@ static bool __guc_submission_selected(struct intel_guc *guc)
void intel_guc_submission_init_early(struct intel_guc *guc)
{
+ guc->submission_supported = __guc_submission_supported(guc);
guc->submission_selected = __guc_submission_selected(guc);
}
+
+static inline struct intel_context *
+g2h_context_lookup(struct intel_guc *guc, u32 desc_idx)
+{
+ struct intel_context *ce;
+
+ if (unlikely(desc_idx >= GUC_MAX_LRC_DESCRIPTORS)) {
+ drm_err(&guc_to_gt(guc)->i915->drm,
+ "Invalid desc_idx %u", desc_idx);
+ return NULL;
+ }
+
+ ce = __get_context(guc, desc_idx);
+ if (unlikely(!ce)) {
+ drm_err(&guc_to_gt(guc)->i915->drm,
+ "Context is NULL, desc_idx %u", desc_idx);
+ return NULL;
+ }
+
+ return ce;
+}
+
+static void decr_outstanding_submission_g2h(struct intel_guc *guc)
+{
+ if (atomic_dec_and_test(&guc->outstanding_submission_g2h))
+ wake_up_all(&guc->ct.wq);
+}
+
+int intel_guc_deregister_done_process_msg(struct intel_guc *guc,
+ const u32 *msg,
+ u32 len)
+{
+ struct intel_context *ce;
+ u32 desc_idx = msg[0];
+
+ if (unlikely(len < 1)) {
+ drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len);
+ return -EPROTO;
+ }
+
+ ce = g2h_context_lookup(guc, desc_idx);
+ if (unlikely(!ce))
+ return -EPROTO;
+
+ trace_intel_context_deregister_done(ce);
+
+ if (context_wait_for_deregister_to_register(ce)) {
+ struct intel_runtime_pm *runtime_pm =
+ &ce->engine->gt->i915->runtime_pm;
+ intel_wakeref_t wakeref;
+
+ /*
+ * Previous owner of this guc_id has been deregistered, now safe
+ * register this context.
+ */
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ register_context(ce, true);
+ guc_signal_context_fence(ce);
+ intel_context_put(ce);
+ } else if (context_destroyed(ce)) {
+ /* Context has been destroyed */
+ release_guc_id(guc, ce);
+ __guc_context_destroy(ce);
+ }
+
+ decr_outstanding_submission_g2h(guc);
+
+ return 0;
+}
+
+int intel_guc_sched_done_process_msg(struct intel_guc *guc,
+ const u32 *msg,
+ u32 len)
+{
+ struct intel_context *ce;
+ unsigned long flags;
+ u32 desc_idx = msg[0];
+
+ if (unlikely(len < 2)) {
+ drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len);
+ return -EPROTO;
+ }
+
+ ce = g2h_context_lookup(guc, desc_idx);
+ if (unlikely(!ce))
+ return -EPROTO;
+
+ if (unlikely(context_destroyed(ce) ||
+ (!context_pending_enable(ce) &&
+ !context_pending_disable(ce)))) {
+ drm_err(&guc_to_gt(guc)->i915->drm,
+ "Bad context sched_state 0x%x, 0x%x, desc_idx %u",
+ atomic_read(&ce->guc_sched_state_no_lock),
+ ce->guc_state.sched_state, desc_idx);
+ return -EPROTO;
+ }
+
+ trace_intel_context_sched_done(ce);
+
+ if (context_pending_enable(ce)) {
+ clr_context_pending_enable(ce);
+ } else if (context_pending_disable(ce)) {
+ bool banned;
+
+ /*
+ * Unpin must be done before __guc_signal_context_fence,
+ * otherwise a race exists between the requests getting
+ * submitted + retired before this unpin completes resulting in
+ * the pin_count going to zero and the context still being
+ * enabled.
+ */
+ intel_context_sched_disable_unpin(ce);
+
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ banned = context_banned(ce);
+ clr_context_banned(ce);
+ clr_context_pending_disable(ce);
+ __guc_signal_context_fence(ce);
+ guc_blocked_fence_complete(ce);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ if (banned) {
+ guc_cancel_context_requests(ce);
+ intel_engine_signal_breadcrumbs(ce->engine);
+ }
+ }
+
+ decr_outstanding_submission_g2h(guc);
+ intel_context_put(ce);
+
+ return 0;
+}
+
+static void capture_error_state(struct intel_guc *guc,
+ struct intel_context *ce)
+{
+ struct intel_gt *gt = guc_to_gt(guc);
+ struct drm_i915_private *i915 = gt->i915;
+ struct intel_engine_cs *engine = __context_to_physical_engine(ce);
+ intel_wakeref_t wakeref;
+
+ intel_engine_set_hung_context(engine, ce);
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref)
+ i915_capture_error_state(gt, engine->mask);
+ atomic_inc(&i915->gpu_error.reset_engine_count[engine->uabi_class]);
+}
+
+static void guc_context_replay(struct intel_context *ce)
+{
+ struct i915_sched_engine *sched_engine = ce->engine->sched_engine;
+
+ __guc_reset_context(ce, true);
+ tasklet_hi_schedule(&sched_engine->tasklet);
+}
+
+static void guc_handle_context_reset(struct intel_guc *guc,
+ struct intel_context *ce)
+{
+ trace_intel_context_reset(ce);
+
+ if (likely(!intel_context_is_banned(ce))) {
+ capture_error_state(guc, ce);
+ guc_context_replay(ce);
+ }
+}
+
+int intel_guc_context_reset_process_msg(struct intel_guc *guc,
+ const u32 *msg, u32 len)
+{
+ struct intel_context *ce;
+ int desc_idx;
+
+ if (unlikely(len != 1)) {
+ drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len);
+ return -EPROTO;
+ }
+
+ desc_idx = msg[0];
+ ce = g2h_context_lookup(guc, desc_idx);
+ if (unlikely(!ce))
+ return -EPROTO;
+
+ guc_handle_context_reset(guc, ce);
+
+ return 0;
+}
+
+static struct intel_engine_cs *
+guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance)
+{
+ struct intel_gt *gt = guc_to_gt(guc);
+ u8 engine_class = guc_class_to_engine_class(guc_class);
+
+ /* Class index is checked in class converter */
+ GEM_BUG_ON(instance > MAX_ENGINE_INSTANCE);
+
+ return gt->engine_class[engine_class][instance];
+}
+
+int intel_guc_engine_failure_process_msg(struct intel_guc *guc,
+ const u32 *msg, u32 len)
+{
+ struct intel_engine_cs *engine;
+ u8 guc_class, instance;
+ u32 reason;
+
+ if (unlikely(len != 3)) {
+ drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len);
+ return -EPROTO;
+ }
+
+ guc_class = msg[0];
+ instance = msg[1];
+ reason = msg[2];
+
+ engine = guc_lookup_engine(guc, guc_class, instance);
+ if (unlikely(!engine)) {
+ drm_err(&guc_to_gt(guc)->i915->drm,
+ "Invalid engine %d:%d", guc_class, instance);
+ return -EPROTO;
+ }
+
+ intel_gt_handle_error(guc_to_gt(guc), engine->mask,
+ I915_ERROR_CAPTURE,
+ "GuC failed to reset %s (reason=0x%08x)\n",
+ engine->name, reason);
+
+ return 0;
+}
+
+void intel_guc_find_hung_context(struct intel_engine_cs *engine)
+{
+ struct intel_guc *guc = &engine->gt->uc.guc;
+ struct intel_context *ce;
+ struct i915_request *rq;
+ unsigned long index;
+
+ /* Reset called during driver load? GuC not yet initialised! */
+ if (unlikely(!guc_submission_initialized(guc)))
+ return;
+
+ xa_for_each(&guc->context_lookup, index, ce) {
+ if (!intel_context_is_pinned(ce))
+ continue;
+
+ if (intel_engine_is_virtual(ce->engine)) {
+ if (!(ce->engine->mask & engine->mask))
+ continue;
+ } else {
+ if (ce->engine != engine)
+ continue;
+ }
+
+ list_for_each_entry(rq, &ce->guc_active.requests, sched.link) {
+ if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE)
+ continue;
+
+ intel_engine_set_hung_context(engine, ce);
+
+ /* Can only cope with one hang at a time... */
+ return;
+ }
+ }
+}
+
+void intel_guc_dump_active_requests(struct intel_engine_cs *engine,
+ struct i915_request *hung_rq,
+ struct drm_printer *m)
+{
+ struct intel_guc *guc = &engine->gt->uc.guc;
+ struct intel_context *ce;
+ unsigned long index;
+ unsigned long flags;
+
+ /* Reset called during driver load? GuC not yet initialised! */
+ if (unlikely(!guc_submission_initialized(guc)))
+ return;
+
+ xa_for_each(&guc->context_lookup, index, ce) {
+ if (!intel_context_is_pinned(ce))
+ continue;
+
+ if (intel_engine_is_virtual(ce->engine)) {
+ if (!(ce->engine->mask & engine->mask))
+ continue;
+ } else {
+ if (ce->engine != engine)
+ continue;
+ }
+
+ spin_lock_irqsave(&ce->guc_active.lock, flags);
+ intel_engine_dump_active_requests(&ce->guc_active.requests,
+ hung_rq, m);
+ spin_unlock_irqrestore(&ce->guc_active.lock, flags);
+ }
+}
+
+void intel_guc_submission_print_info(struct intel_guc *guc,
+ struct drm_printer *p)
+{
+ struct i915_sched_engine *sched_engine = guc->sched_engine;
+ struct rb_node *rb;
+ unsigned long flags;
+
+ if (!sched_engine)
+ return;
+
+ drm_printf(p, "GuC Number Outstanding Submission G2H: %u\n",
+ atomic_read(&guc->outstanding_submission_g2h));
+ drm_printf(p, "GuC tasklet count: %u\n\n",
+ atomic_read(&sched_engine->tasklet.count));
+
+ spin_lock_irqsave(&sched_engine->lock, flags);
+ drm_printf(p, "Requests in GuC submit tasklet:\n");
+ for (rb = rb_first_cached(&sched_engine->queue); rb; rb = rb_next(rb)) {
+ struct i915_priolist *pl = to_priolist(rb);
+ struct i915_request *rq;
+
+ priolist_for_each_request(rq, pl)
+ drm_printf(p, "guc_id=%u, seqno=%llu\n",
+ rq->context->guc_id,
+ rq->fence.seqno);
+ }
+ spin_unlock_irqrestore(&sched_engine->lock, flags);
+ drm_printf(p, "\n");
+}
+
+static inline void guc_log_context_priority(struct drm_printer *p,
+ struct intel_context *ce)
+{
+ int i;
+
+ drm_printf(p, "\t\tPriority: %d\n",
+ ce->guc_prio);
+ drm_printf(p, "\t\tNumber Requests (lower index == higher priority)\n");
+ for (i = GUC_CLIENT_PRIORITY_KMD_HIGH;
+ i < GUC_CLIENT_PRIORITY_NUM; ++i) {
+ drm_printf(p, "\t\tNumber requests in priority band[%d]: %d\n",
+ i, ce->guc_prio_count[i]);
+ }
+ drm_printf(p, "\n");
+}
+
+void intel_guc_submission_print_context_info(struct intel_guc *guc,
+ struct drm_printer *p)
+{
+ struct intel_context *ce;
+ unsigned long index;
+
+ xa_for_each(&guc->context_lookup, index, ce) {
+ drm_printf(p, "GuC lrc descriptor %u:\n", ce->guc_id);
+ drm_printf(p, "\tHW Context Desc: 0x%08x\n", ce->lrc.lrca);
+ drm_printf(p, "\t\tLRC Head: Internal %u, Memory %u\n",
+ ce->ring->head,
+ ce->lrc_reg_state[CTX_RING_HEAD]);
+ drm_printf(p, "\t\tLRC Tail: Internal %u, Memory %u\n",
+ ce->ring->tail,
+ ce->lrc_reg_state[CTX_RING_TAIL]);
+ drm_printf(p, "\t\tContext Pin Count: %u\n",
+ atomic_read(&ce->pin_count));
+ drm_printf(p, "\t\tGuC ID Ref Count: %u\n",
+ atomic_read(&ce->guc_id_ref));
+ drm_printf(p, "\t\tSchedule State: 0x%x, 0x%x\n\n",
+ ce->guc_state.sched_state,
+ atomic_read(&ce->guc_sched_state_no_lock));
+
+ guc_log_context_priority(p, ce);
+ }
+}
+
+static struct intel_context *
+guc_create_virtual(struct intel_engine_cs **siblings, unsigned int count)
+{
+ struct guc_virtual_engine *ve;
+ struct intel_guc *guc;
+ unsigned int n;
+ int err;
+
+ ve = kzalloc(sizeof(*ve), GFP_KERNEL);
+ if (!ve)
+ return ERR_PTR(-ENOMEM);
+
+ guc = &siblings[0]->gt->uc.guc;
+
+ ve->base.i915 = siblings[0]->i915;
+ ve->base.gt = siblings[0]->gt;
+ ve->base.uncore = siblings[0]->uncore;
+ ve->base.id = -1;
+
+ ve->base.uabi_class = I915_ENGINE_CLASS_INVALID;
+ ve->base.instance = I915_ENGINE_CLASS_INVALID_VIRTUAL;
+ ve->base.uabi_instance = I915_ENGINE_CLASS_INVALID_VIRTUAL;
+ ve->base.saturated = ALL_ENGINES;
+
+ snprintf(ve->base.name, sizeof(ve->base.name), "virtual");
+
+ ve->base.sched_engine = i915_sched_engine_get(guc->sched_engine);
+
+ ve->base.cops = &virtual_guc_context_ops;
+ ve->base.request_alloc = guc_request_alloc;
+ ve->base.bump_serial = virtual_guc_bump_serial;
+
+ ve->base.submit_request = guc_submit_request;
+
+ ve->base.flags = I915_ENGINE_IS_VIRTUAL;
+
+ intel_context_init(&ve->context, &ve->base);
+
+ for (n = 0; n < count; n++) {
+ struct intel_engine_cs *sibling = siblings[n];
+
+ GEM_BUG_ON(!is_power_of_2(sibling->mask));
+ if (sibling->mask & ve->base.mask) {
+ DRM_DEBUG("duplicate %s entry in load balancer\n",
+ sibling->name);
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ ve->base.mask |= sibling->mask;
+
+ if (n != 0 && ve->base.class != sibling->class) {
+ DRM_DEBUG("invalid mixing of engine class, sibling %d, already %d\n",
+ sibling->class, ve->base.class);
+ err = -EINVAL;
+ goto err_put;
+ } else if (n == 0) {
+ ve->base.class = sibling->class;
+ ve->base.uabi_class = sibling->uabi_class;
+ snprintf(ve->base.name, sizeof(ve->base.name),
+ "v%dx%d", ve->base.class, count);
+ ve->base.context_size = sibling->context_size;
+
+ ve->base.add_active_request =
+ sibling->add_active_request;
+ ve->base.remove_active_request =
+ sibling->remove_active_request;
+ ve->base.emit_bb_start = sibling->emit_bb_start;
+ ve->base.emit_flush = sibling->emit_flush;
+ ve->base.emit_init_breadcrumb =
+ sibling->emit_init_breadcrumb;
+ ve->base.emit_fini_breadcrumb =
+ sibling->emit_fini_breadcrumb;
+ ve->base.emit_fini_breadcrumb_dw =
+ sibling->emit_fini_breadcrumb_dw;
+ ve->base.breadcrumbs =
+ intel_breadcrumbs_get(sibling->breadcrumbs);
+
+ ve->base.flags |= sibling->flags;
+
+ ve->base.props.timeslice_duration_ms =
+ sibling->props.timeslice_duration_ms;
+ ve->base.props.preempt_timeout_ms =
+ sibling->props.preempt_timeout_ms;
+ }
+ }
+
+ return &ve->context;
+
+err_put:
+ intel_context_put(&ve->context);
+ return ERR_PTR(err);
+}
+
+bool intel_guc_virtual_engine_has_heartbeat(const struct intel_engine_cs *ve)
+{
+ struct intel_engine_cs *engine;
+ intel_engine_mask_t tmp, mask = ve->mask;
+
+ for_each_engine_masked(engine, ve->gt, mask, tmp)
+ if (READ_ONCE(engine->props.heartbeat_interval_ms))
+ return true;
+
+ return false;
+}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
index 3f7005018939..c7ef44fa0c36 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h
@@ -10,6 +10,7 @@
#include "intel_guc.h"
+struct drm_printer;
struct intel_engine_cs;
void intel_guc_submission_init_early(struct intel_guc *guc);
@@ -20,11 +21,24 @@ void intel_guc_submission_fini(struct intel_guc *guc);
int intel_guc_preempt_work_create(struct intel_guc *guc);
void intel_guc_preempt_work_destroy(struct intel_guc *guc);
int intel_guc_submission_setup(struct intel_engine_cs *engine);
+void intel_guc_submission_print_info(struct intel_guc *guc,
+ struct drm_printer *p);
+void intel_guc_submission_print_context_info(struct intel_guc *guc,
+ struct drm_printer *p);
+void intel_guc_dump_active_requests(struct intel_engine_cs *engine,
+ struct i915_request *hung_rq,
+ struct drm_printer *m);
+
+bool intel_guc_virtual_engine_has_heartbeat(const struct intel_engine_cs *ve);
+
+int intel_guc_wait_for_pending_msg(struct intel_guc *guc,
+ atomic_t *wait_var,
+ bool interruptible,
+ long timeout);
static inline bool intel_guc_submission_is_supported(struct intel_guc *guc)
{
- /* XXX: GuC submission is unavailable for now */
- return false;
+ return guc->submission_supported;
}
static inline bool intel_guc_submission_is_wanted(struct intel_guc *guc)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index 6d8b9233214e..b104fb7607eb 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -34,8 +34,14 @@ static void uc_expand_default_options(struct intel_uc *uc)
return;
}
- /* Default: enable HuC authentication only */
- i915->params.enable_guc = ENABLE_GUC_LOAD_HUC;
+ /* Intermediate platforms are HuC authentication only */
+ if (IS_DG1(i915) || IS_ALDERLAKE_S(i915)) {
+ i915->params.enable_guc = ENABLE_GUC_LOAD_HUC;
+ return;
+ }
+
+ /* Default: enable HuC authentication and GuC submission */
+ i915->params.enable_guc = ENABLE_GUC_LOAD_HUC | ENABLE_GUC_SUBMISSION;
}
/* Reset GuC providing us with fresh state for both GuC and HuC.
@@ -69,16 +75,18 @@ static void __confirm_options(struct intel_uc *uc)
struct drm_i915_private *i915 = uc_to_gt(uc)->i915;
drm_dbg(&i915->drm,
- "enable_guc=%d (guc:%s submission:%s huc:%s)\n",
+ "enable_guc=%d (guc:%s submission:%s huc:%s slpc:%s)\n",
i915->params.enable_guc,
yesno(intel_uc_wants_guc(uc)),
yesno(intel_uc_wants_guc_submission(uc)),
- yesno(intel_uc_wants_huc(uc)));
+ yesno(intel_uc_wants_huc(uc)),
+ yesno(intel_uc_wants_guc_slpc(uc)));
if (i915->params.enable_guc == 0) {
GEM_BUG_ON(intel_uc_wants_guc(uc));
GEM_BUG_ON(intel_uc_wants_guc_submission(uc));
GEM_BUG_ON(intel_uc_wants_huc(uc));
+ GEM_BUG_ON(intel_uc_wants_guc_slpc(uc));
return;
}
@@ -120,6 +128,11 @@ void intel_uc_init_early(struct intel_uc *uc)
uc->ops = &uc_ops_off;
}
+void intel_uc_init_late(struct intel_uc *uc)
+{
+ intel_guc_init_late(&uc->guc);
+}
+
void intel_uc_driver_late_release(struct intel_uc *uc)
{
}
@@ -207,21 +220,6 @@ static void guc_handle_mmio_msg(struct intel_guc *guc)
spin_unlock_irq(&guc->irq_lock);
}
-static void guc_reset_interrupts(struct intel_guc *guc)
-{
- guc->interrupts.reset(guc);
-}
-
-static void guc_enable_interrupts(struct intel_guc *guc)
-{
- guc->interrupts.enable(guc);
-}
-
-static void guc_disable_interrupts(struct intel_guc *guc)
-{
- guc->interrupts.disable(guc);
-}
-
static int guc_enable_communication(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
@@ -242,7 +240,7 @@ static int guc_enable_communication(struct intel_guc *guc)
guc_get_mmio_msg(guc);
guc_handle_mmio_msg(guc);
- guc_enable_interrupts(guc);
+ intel_guc_enable_interrupts(guc);
/* check for CT messages received before we enabled interrupts */
spin_lock_irq(&gt->irq_lock);
@@ -265,7 +263,7 @@ static void guc_disable_communication(struct intel_guc *guc)
*/
guc_clear_mmio_msg(guc);
- guc_disable_interrupts(guc);
+ intel_guc_disable_interrupts(guc);
intel_guc_ct_disable(&guc->ct);
@@ -323,9 +321,6 @@ static int __uc_init(struct intel_uc *uc)
if (i915_inject_probe_failure(uc_to_gt(uc)->i915))
return -ENOMEM;
- /* XXX: GuC submission is unavailable for now */
- GEM_BUG_ON(intel_uc_uses_guc_submission(uc));
-
ret = intel_guc_init(guc);
if (ret)
return ret;
@@ -463,7 +458,7 @@ static int __uc_init_hw(struct intel_uc *uc)
if (ret)
goto err_out;
- guc_reset_interrupts(guc);
+ intel_guc_reset_interrupts(guc);
/* WaEnableuKernelHeaderValidFix:skl */
/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
@@ -505,12 +500,21 @@ static int __uc_init_hw(struct intel_uc *uc)
if (intel_uc_uses_guc_submission(uc))
intel_guc_submission_enable(guc);
+ if (intel_uc_uses_guc_slpc(uc)) {
+ ret = intel_guc_slpc_enable(&guc->slpc);
+ if (ret)
+ goto err_submission;
+ }
+
drm_info(&i915->drm, "%s firmware %s version %u.%u %s:%s\n",
intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_GUC), guc->fw.path,
guc->fw.major_ver_found, guc->fw.minor_ver_found,
"submission",
enableddisabled(intel_uc_uses_guc_submission(uc)));
+ drm_info(&i915->drm, "GuC SLPC: %s\n",
+ enableddisabled(intel_uc_uses_guc_slpc(uc)));
+
if (intel_uc_uses_huc(uc)) {
drm_info(&i915->drm, "%s firmware %s version %u.%u %s:%s\n",
intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_HUC),
@@ -525,6 +529,8 @@ static int __uc_init_hw(struct intel_uc *uc)
/*
* We've failed to load the firmware :(
*/
+err_submission:
+ intel_guc_submission_disable(guc);
err_log_capture:
__uc_capture_load_err_log(uc);
err_out:
@@ -565,23 +571,67 @@ void intel_uc_reset_prepare(struct intel_uc *uc)
{
struct intel_guc *guc = &uc->guc;
- if (!intel_guc_is_ready(guc))
+ uc->reset_in_progress = true;
+
+ /* Nothing to do if GuC isn't supported */
+ if (!intel_uc_supports_guc(uc))
return;
+ /* Firmware expected to be running when this function is called */
+ if (!intel_guc_is_ready(guc))
+ goto sanitize;
+
+ if (intel_uc_uses_guc_submission(uc))
+ intel_guc_submission_reset_prepare(guc);
+
+sanitize:
__uc_sanitize(uc);
}
+void intel_uc_reset(struct intel_uc *uc, bool stalled)
+{
+ struct intel_guc *guc = &uc->guc;
+
+ /* Firmware can not be running when this function is called */
+ if (intel_uc_uses_guc_submission(uc))
+ intel_guc_submission_reset(guc, stalled);
+}
+
+void intel_uc_reset_finish(struct intel_uc *uc)
+{
+ struct intel_guc *guc = &uc->guc;
+
+ uc->reset_in_progress = false;
+
+ /* Firmware expected to be running when this function is called */
+ if (intel_guc_is_fw_running(guc) && intel_uc_uses_guc_submission(uc))
+ intel_guc_submission_reset_finish(guc);
+}
+
+void intel_uc_cancel_requests(struct intel_uc *uc)
+{
+ struct intel_guc *guc = &uc->guc;
+
+ /* Firmware can not be running when this function is called */
+ if (intel_uc_uses_guc_submission(uc))
+ intel_guc_submission_cancel_requests(guc);
+}
+
void intel_uc_runtime_suspend(struct intel_uc *uc)
{
struct intel_guc *guc = &uc->guc;
- int err;
if (!intel_guc_is_ready(guc))
return;
- err = intel_guc_suspend(guc);
- if (err)
- DRM_DEBUG_DRIVER("Failed to suspend GuC, err=%d", err);
+ /*
+ * Wait for any outstanding CTB before tearing down communication /w the
+ * GuC.
+ */
+#define OUTSTANDING_CTB_TIMEOUT_PERIOD (HZ / 5)
+ intel_guc_wait_for_pending_msg(guc, &guc->outstanding_submission_g2h,
+ false, OUTSTANDING_CTB_TIMEOUT_PERIOD);
+ GEM_WARN_ON(atomic_read(&guc->outstanding_submission_g2h));
guc_disable_communication(guc);
}
@@ -590,17 +640,22 @@ void intel_uc_suspend(struct intel_uc *uc)
{
struct intel_guc *guc = &uc->guc;
intel_wakeref_t wakeref;
+ int err;
if (!intel_guc_is_ready(guc))
return;
- with_intel_runtime_pm(uc_to_gt(uc)->uncore->rpm, wakeref)
- intel_uc_runtime_suspend(uc);
+ with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) {
+ err = intel_guc_suspend(guc);
+ if (err)
+ DRM_DEBUG_DRIVER("Failed to suspend GuC, err=%d", err);
+ }
}
static int __uc_resume(struct intel_uc *uc, bool enable_communication)
{
struct intel_guc *guc = &uc->guc;
+ struct intel_gt *gt = guc_to_gt(guc);
int err;
if (!intel_guc_is_fw_running(guc))
@@ -612,6 +667,13 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication)
if (enable_communication)
guc_enable_communication(guc);
+ /* If we are only resuming GuC communication but not reloading
+ * GuC, we need to ensure the ARAT timer interrupt is enabled
+ * again. In case of GuC reload, it is enabled during SLPC enable.
+ */
+ if (enable_communication && intel_uc_uses_guc_slpc(uc))
+ intel_guc_pm_intrmsk_enable(gt);
+
err = intel_guc_resume(guc);
if (err) {
DRM_DEBUG_DRIVER("Failed to resume GuC, err=%d", err);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
index 9c954c589edf..866b462821c0 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
@@ -7,7 +7,9 @@
#define _INTEL_UC_H_
#include "intel_guc.h"
+#include "intel_guc_rc.h"
#include "intel_guc_submission.h"
+#include "intel_guc_slpc.h"
#include "intel_huc.h"
#include "i915_params.h"
@@ -30,13 +32,19 @@ struct intel_uc {
/* Snapshot of GuC log from last failed load */
struct drm_i915_gem_object *load_err_log;
+
+ bool reset_in_progress;
};
void intel_uc_init_early(struct intel_uc *uc);
+void intel_uc_init_late(struct intel_uc *uc);
void intel_uc_driver_late_release(struct intel_uc *uc);
void intel_uc_driver_remove(struct intel_uc *uc);
void intel_uc_init_mmio(struct intel_uc *uc);
void intel_uc_reset_prepare(struct intel_uc *uc);
+void intel_uc_reset(struct intel_uc *uc, bool stalled);
+void intel_uc_reset_finish(struct intel_uc *uc);
+void intel_uc_cancel_requests(struct intel_uc *uc);
void intel_uc_suspend(struct intel_uc *uc);
void intel_uc_runtime_suspend(struct intel_uc *uc);
int intel_uc_resume(struct intel_uc *uc);
@@ -77,10 +85,17 @@ __uc_state_checker(x, func, uses, used)
uc_state_checkers(guc, guc);
uc_state_checkers(huc, huc);
uc_state_checkers(guc, guc_submission);
+uc_state_checkers(guc, guc_slpc);
+uc_state_checkers(guc, guc_rc);
#undef uc_state_checkers
#undef __uc_state_checker
+static inline int intel_uc_wait_for_idle(struct intel_uc *uc, long timeout)
+{
+ return intel_guc_wait_for_idle(&uc->guc, timeout);
+}
+
#define intel_uc_ops_function(_NAME, _OPS, _TYPE, _RET) \
static inline _TYPE intel_uc_##_NAME(struct intel_uc *uc) \
{ \
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index df647c9a8d56..3a16d08608a5 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -48,19 +48,20 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
* firmware as TGL.
*/
#define INTEL_UC_FIRMWARE_DEFS(fw_def, guc_def, huc_def) \
- fw_def(ALDERLAKE_S, 0, guc_def(tgl, 49, 0, 1), huc_def(tgl, 7, 5, 0)) \
- fw_def(ROCKETLAKE, 0, guc_def(tgl, 49, 0, 1), huc_def(tgl, 7, 5, 0)) \
- fw_def(TIGERLAKE, 0, guc_def(tgl, 49, 0, 1), huc_def(tgl, 7, 5, 0)) \
- fw_def(JASPERLAKE, 0, guc_def(ehl, 49, 0, 1), huc_def(ehl, 9, 0, 0)) \
- fw_def(ELKHARTLAKE, 0, guc_def(ehl, 49, 0, 1), huc_def(ehl, 9, 0, 0)) \
- fw_def(ICELAKE, 0, guc_def(icl, 49, 0, 1), huc_def(icl, 9, 0, 0)) \
- fw_def(COMETLAKE, 5, guc_def(cml, 49, 0, 1), huc_def(cml, 4, 0, 0)) \
- fw_def(COMETLAKE, 0, guc_def(kbl, 49, 0, 1), huc_def(kbl, 4, 0, 0)) \
- fw_def(COFFEELAKE, 0, guc_def(kbl, 49, 0, 1), huc_def(kbl, 4, 0, 0)) \
- fw_def(GEMINILAKE, 0, guc_def(glk, 49, 0, 1), huc_def(glk, 4, 0, 0)) \
- fw_def(KABYLAKE, 0, guc_def(kbl, 49, 0, 1), huc_def(kbl, 4, 0, 0)) \
- fw_def(BROXTON, 0, guc_def(bxt, 49, 0, 1), huc_def(bxt, 2, 0, 0)) \
- fw_def(SKYLAKE, 0, guc_def(skl, 49, 0, 1), huc_def(skl, 2, 0, 0))
+ fw_def(ALDERLAKE_P, 0, guc_def(adlp, 62, 0, 3), huc_def(tgl, 7, 9, 3)) \
+ fw_def(ALDERLAKE_S, 0, guc_def(tgl, 62, 0, 0), huc_def(tgl, 7, 9, 3)) \
+ fw_def(ROCKETLAKE, 0, guc_def(tgl, 62, 0, 0), huc_def(tgl, 7, 9, 3)) \
+ fw_def(TIGERLAKE, 0, guc_def(tgl, 62, 0, 0), huc_def(tgl, 7, 9, 3)) \
+ fw_def(JASPERLAKE, 0, guc_def(ehl, 62, 0, 0), huc_def(ehl, 9, 0, 0)) \
+ fw_def(ELKHARTLAKE, 0, guc_def(ehl, 62, 0, 0), huc_def(ehl, 9, 0, 0)) \
+ fw_def(ICELAKE, 0, guc_def(icl, 62, 0, 0), huc_def(icl, 9, 0, 0)) \
+ fw_def(COMETLAKE, 5, guc_def(cml, 62, 0, 0), huc_def(cml, 4, 0, 0)) \
+ fw_def(COMETLAKE, 0, guc_def(kbl, 62, 0, 0), huc_def(kbl, 4, 0, 0)) \
+ fw_def(COFFEELAKE, 0, guc_def(kbl, 62, 0, 0), huc_def(kbl, 4, 0, 0)) \
+ fw_def(GEMINILAKE, 0, guc_def(glk, 62, 0, 0), huc_def(glk, 4, 0, 0)) \
+ fw_def(KABYLAKE, 0, guc_def(kbl, 62, 0, 0), huc_def(kbl, 4, 0, 0)) \
+ fw_def(BROXTON, 0, guc_def(bxt, 62, 0, 0), huc_def(bxt, 2, 0, 0)) \
+ fw_def(SKYLAKE, 0, guc_def(skl, 62, 0, 0), huc_def(skl, 2, 0, 0))
#define __MAKE_UC_FW_PATH(prefix_, name_, major_, minor_, patch_) \
"i915/" \
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index cc2c05e18206..e5c2fdfc20e3 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1055,7 +1055,7 @@ static bool vgpu_ips_enabled(struct intel_vgpu *vgpu)
{
struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915;
- if (GRAPHICS_VER(dev_priv) == 9 || GRAPHICS_VER(dev_priv) == 10) {
+ if (GRAPHICS_VER(dev_priv) == 9) {
u32 ips = vgpu_vreg_t(vgpu, GEN8_GAMW_ECO_DEV_RW_IA) &
GAMW_ECO_ENABLE_64K_IPS_FIELD;
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 1ac98f8aba31..7efa386449d1 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -885,7 +885,7 @@ static int intel_vgpu_group_notifier(struct notifier_block *nb,
return NOTIFY_OK;
}
-static int intel_vgpu_open(struct mdev_device *mdev)
+static int intel_vgpu_open_device(struct mdev_device *mdev)
{
struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);
@@ -1004,7 +1004,7 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)
vgpu->handle = 0;
}
-static void intel_vgpu_release(struct mdev_device *mdev)
+static void intel_vgpu_close_device(struct mdev_device *mdev)
{
struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
@@ -1753,8 +1753,8 @@ static struct mdev_parent_ops intel_vgpu_ops = {
.create = intel_vgpu_create,
.remove = intel_vgpu_remove,
- .open = intel_vgpu_open,
- .release = intel_vgpu_release,
+ .open_device = intel_vgpu_open_device,
+ .close_device = intel_vgpu_close_device,
.read = intel_vgpu_read,
.write = intel_vgpu_write,
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
index 734c37c5e347..b56a8e37a3cd 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -1409,11 +1409,8 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu)
intel_context_set_single_submission(ce);
/* Max ring buffer size */
- if (!intel_uc_wants_guc_submission(&engine->gt->uc)) {
- const unsigned int ring_size = 512 * SZ_4K;
-
- ce->ring = __intel_context_ring_size(ring_size);
- }
+ if (!intel_uc_wants_guc_submission(&engine->gt->uc))
+ ce->ring_size = SZ_2M;
s->shadow[i] = ce;
}
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index b1aa1c482c32..3103c1e1fd14 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -13,7 +13,6 @@
#include "i915_drv.h"
#include "i915_active.h"
-#include "i915_globals.h"
/*
* Active refs memory management
@@ -22,10 +21,7 @@
* they idle (when we know the active requests are inactive) and allocate the
* nodes from a local slab cache to hopefully reduce the fragmentation.
*/
-static struct i915_global_active {
- struct i915_global base;
- struct kmem_cache *slab_cache;
-} global;
+static struct kmem_cache *slab_cache;
struct active_node {
struct rb_node node;
@@ -174,7 +170,7 @@ __active_retire(struct i915_active *ref)
/* Finally free the discarded timeline tree */
rbtree_postorder_for_each_entry_safe(it, n, &root, node) {
GEM_BUG_ON(i915_active_fence_isset(&it->base));
- kmem_cache_free(global.slab_cache, it);
+ kmem_cache_free(slab_cache, it);
}
}
@@ -322,7 +318,7 @@ active_instance(struct i915_active *ref, u64 idx)
* XXX: We should preallocate this before i915_active_ref() is ever
* called, but we cannot call into fs_reclaim() anyway, so use GFP_ATOMIC.
*/
- node = kmem_cache_alloc(global.slab_cache, GFP_ATOMIC);
+ node = kmem_cache_alloc(slab_cache, GFP_ATOMIC);
if (!node)
goto out;
@@ -788,7 +784,7 @@ void i915_active_fini(struct i915_active *ref)
mutex_destroy(&ref->mutex);
if (ref->cache)
- kmem_cache_free(global.slab_cache, ref->cache);
+ kmem_cache_free(slab_cache, ref->cache);
}
static inline bool is_idle_barrier(struct active_node *node, u64 idx)
@@ -908,7 +904,7 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref,
node = reuse_idle_barrier(ref, idx);
rcu_read_unlock();
if (!node) {
- node = kmem_cache_alloc(global.slab_cache, GFP_KERNEL);
+ node = kmem_cache_alloc(slab_cache, GFP_KERNEL);
if (!node)
goto unwind;
@@ -956,7 +952,7 @@ unwind:
atomic_dec(&ref->count);
intel_engine_pm_put(barrier_to_engine(node));
- kmem_cache_free(global.slab_cache, node);
+ kmem_cache_free(slab_cache, node);
}
return -ENOMEM;
}
@@ -1176,27 +1172,16 @@ struct i915_active *i915_active_create(void)
#include "selftests/i915_active.c"
#endif
-static void i915_global_active_shrink(void)
+void i915_active_module_exit(void)
{
- kmem_cache_shrink(global.slab_cache);
+ kmem_cache_destroy(slab_cache);
}
-static void i915_global_active_exit(void)
+int __init i915_active_module_init(void)
{
- kmem_cache_destroy(global.slab_cache);
-}
-
-static struct i915_global_active global = { {
- .shrink = i915_global_active_shrink,
- .exit = i915_global_active_exit,
-} };
-
-int __init i915_global_active_init(void)
-{
- global.slab_cache = KMEM_CACHE(active_node, SLAB_HWCACHE_ALIGN);
- if (!global.slab_cache)
+ slab_cache = KMEM_CACHE(active_node, SLAB_HWCACHE_ALIGN);
+ if (!slab_cache)
return -ENOMEM;
- i915_global_register(&global.base);
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h
index d0feda68b874..5fcdb0e2bc9e 100644
--- a/drivers/gpu/drm/i915/i915_active.h
+++ b/drivers/gpu/drm/i915/i915_active.h
@@ -247,4 +247,7 @@ static inline int __i915_request_await_exclusive(struct i915_request *rq,
return err;
}
+void i915_active_module_exit(void);
+int i915_active_module_init(void);
+
#endif /* _I915_ACTIVE_H_ */
diff --git a/drivers/gpu/drm/i915/i915_buddy.c b/drivers/gpu/drm/i915/i915_buddy.c
new file mode 100644
index 000000000000..7b274c51cac0
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_buddy.c
@@ -0,0 +1,421 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <linux/kmemleak.h>
+
+#include "i915_buddy.h"
+
+#include "i915_gem.h"
+#include "i915_utils.h"
+
+static struct kmem_cache *slab_blocks;
+
+static struct i915_buddy_block *i915_block_alloc(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *parent,
+ unsigned int order,
+ u64 offset)
+{
+ struct i915_buddy_block *block;
+
+ GEM_BUG_ON(order > I915_BUDDY_MAX_ORDER);
+
+ block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
+ if (!block)
+ return NULL;
+
+ block->header = offset;
+ block->header |= order;
+ block->parent = parent;
+
+ GEM_BUG_ON(block->header & I915_BUDDY_HEADER_UNUSED);
+ return block;
+}
+
+static void i915_block_free(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+ kmem_cache_free(slab_blocks, block);
+}
+
+static void mark_allocated(struct i915_buddy_block *block)
+{
+ block->header &= ~I915_BUDDY_HEADER_STATE;
+ block->header |= I915_BUDDY_ALLOCATED;
+
+ list_del(&block->link);
+}
+
+static void mark_free(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+ block->header &= ~I915_BUDDY_HEADER_STATE;
+ block->header |= I915_BUDDY_FREE;
+
+ list_add(&block->link,
+ &mm->free_list[i915_buddy_block_order(block)]);
+}
+
+static void mark_split(struct i915_buddy_block *block)
+{
+ block->header &= ~I915_BUDDY_HEADER_STATE;
+ block->header |= I915_BUDDY_SPLIT;
+
+ list_del(&block->link);
+}
+
+int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size)
+{
+ unsigned int i;
+ u64 offset;
+
+ if (size < chunk_size)
+ return -EINVAL;
+
+ if (chunk_size < PAGE_SIZE)
+ return -EINVAL;
+
+ if (!is_power_of_2(chunk_size))
+ return -EINVAL;
+
+ size = round_down(size, chunk_size);
+
+ mm->size = size;
+ mm->chunk_size = chunk_size;
+ mm->max_order = ilog2(size) - ilog2(chunk_size);
+
+ GEM_BUG_ON(mm->max_order > I915_BUDDY_MAX_ORDER);
+
+ mm->free_list = kmalloc_array(mm->max_order + 1,
+ sizeof(struct list_head),
+ GFP_KERNEL);
+ if (!mm->free_list)
+ return -ENOMEM;
+
+ for (i = 0; i <= mm->max_order; ++i)
+ INIT_LIST_HEAD(&mm->free_list[i]);
+
+ mm->n_roots = hweight64(size);
+
+ mm->roots = kmalloc_array(mm->n_roots,
+ sizeof(struct i915_buddy_block *),
+ GFP_KERNEL);
+ if (!mm->roots)
+ goto out_free_list;
+
+ offset = 0;
+ i = 0;
+
+ /*
+ * Split into power-of-two blocks, in case we are given a size that is
+ * not itself a power-of-two.
+ */
+ do {
+ struct i915_buddy_block *root;
+ unsigned int order;
+ u64 root_size;
+
+ root_size = rounddown_pow_of_two(size);
+ order = ilog2(root_size) - ilog2(chunk_size);
+
+ root = i915_block_alloc(mm, NULL, order, offset);
+ if (!root)
+ goto out_free_roots;
+
+ mark_free(mm, root);
+
+ GEM_BUG_ON(i > mm->max_order);
+ GEM_BUG_ON(i915_buddy_block_size(mm, root) < chunk_size);
+
+ mm->roots[i] = root;
+
+ offset += root_size;
+ size -= root_size;
+ i++;
+ } while (size);
+
+ return 0;
+
+out_free_roots:
+ while (i--)
+ i915_block_free(mm, mm->roots[i]);
+ kfree(mm->roots);
+out_free_list:
+ kfree(mm->free_list);
+ return -ENOMEM;
+}
+
+void i915_buddy_fini(struct i915_buddy_mm *mm)
+{
+ int i;
+
+ for (i = 0; i < mm->n_roots; ++i) {
+ GEM_WARN_ON(!i915_buddy_block_is_free(mm->roots[i]));
+ i915_block_free(mm, mm->roots[i]);
+ }
+
+ kfree(mm->roots);
+ kfree(mm->free_list);
+}
+
+static int split_block(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+ unsigned int block_order = i915_buddy_block_order(block) - 1;
+ u64 offset = i915_buddy_block_offset(block);
+
+ GEM_BUG_ON(!i915_buddy_block_is_free(block));
+ GEM_BUG_ON(!i915_buddy_block_order(block));
+
+ block->left = i915_block_alloc(mm, block, block_order, offset);
+ if (!block->left)
+ return -ENOMEM;
+
+ block->right = i915_block_alloc(mm, block, block_order,
+ offset + (mm->chunk_size << block_order));
+ if (!block->right) {
+ i915_block_free(mm, block->left);
+ return -ENOMEM;
+ }
+
+ mark_free(mm, block->left);
+ mark_free(mm, block->right);
+
+ mark_split(block);
+
+ return 0;
+}
+
+static struct i915_buddy_block *
+get_buddy(struct i915_buddy_block *block)
+{
+ struct i915_buddy_block *parent;
+
+ parent = block->parent;
+ if (!parent)
+ return NULL;
+
+ if (parent->left == block)
+ return parent->right;
+
+ return parent->left;
+}
+
+static void __i915_buddy_free(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+ struct i915_buddy_block *parent;
+
+ while ((parent = block->parent)) {
+ struct i915_buddy_block *buddy;
+
+ buddy = get_buddy(block);
+
+ if (!i915_buddy_block_is_free(buddy))
+ break;
+
+ list_del(&buddy->link);
+
+ i915_block_free(mm, block);
+ i915_block_free(mm, buddy);
+
+ block = parent;
+ }
+
+ mark_free(mm, block);
+}
+
+void i915_buddy_free(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+ GEM_BUG_ON(!i915_buddy_block_is_allocated(block));
+ __i915_buddy_free(mm, block);
+}
+
+void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head *objects)
+{
+ struct i915_buddy_block *block, *on;
+
+ list_for_each_entry_safe(block, on, objects, link) {
+ i915_buddy_free(mm, block);
+ cond_resched();
+ }
+ INIT_LIST_HEAD(objects);
+}
+
+/*
+ * Allocate power-of-two block. The order value here translates to:
+ *
+ * 0 = 2^0 * mm->chunk_size
+ * 1 = 2^1 * mm->chunk_size
+ * 2 = 2^2 * mm->chunk_size
+ * ...
+ */
+struct i915_buddy_block *
+i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned int order)
+{
+ struct i915_buddy_block *block = NULL;
+ unsigned int i;
+ int err;
+
+ for (i = order; i <= mm->max_order; ++i) {
+ block = list_first_entry_or_null(&mm->free_list[i],
+ struct i915_buddy_block,
+ link);
+ if (block)
+ break;
+ }
+
+ if (!block)
+ return ERR_PTR(-ENOSPC);
+
+ GEM_BUG_ON(!i915_buddy_block_is_free(block));
+
+ while (i != order) {
+ err = split_block(mm, block);
+ if (unlikely(err))
+ goto out_free;
+
+ /* Go low */
+ block = block->left;
+ i--;
+ }
+
+ mark_allocated(block);
+ kmemleak_update_trace(block);
+ return block;
+
+out_free:
+ if (i != order)
+ __i915_buddy_free(mm, block);
+ return ERR_PTR(err);
+}
+
+static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
+{
+ return s1 <= e2 && e1 >= s2;
+}
+
+static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
+{
+ return s1 <= s2 && e1 >= e2;
+}
+
+/*
+ * Allocate range. Note that it's safe to chain together multiple alloc_ranges
+ * with the same blocks list.
+ *
+ * Intended for pre-allocating portions of the address space, for example to
+ * reserve a block for the initial framebuffer or similar, hence the expectation
+ * here is that i915_buddy_alloc() is still the main vehicle for
+ * allocations, so if that's not the case then the drm_mm range allocator is
+ * probably a much better fit, and so you should probably go use that instead.
+ */
+int i915_buddy_alloc_range(struct i915_buddy_mm *mm,
+ struct list_head *blocks,
+ u64 start, u64 size)
+{
+ struct i915_buddy_block *block;
+ struct i915_buddy_block *buddy;
+ LIST_HEAD(allocated);
+ LIST_HEAD(dfs);
+ u64 end;
+ int err;
+ int i;
+
+ if (size < mm->chunk_size)
+ return -EINVAL;
+
+ if (!IS_ALIGNED(size | start, mm->chunk_size))
+ return -EINVAL;
+
+ if (range_overflows(start, size, mm->size))
+ return -EINVAL;
+
+ for (i = 0; i < mm->n_roots; ++i)
+ list_add_tail(&mm->roots[i]->tmp_link, &dfs);
+
+ end = start + size - 1;
+
+ do {
+ u64 block_start;
+ u64 block_end;
+
+ block = list_first_entry_or_null(&dfs,
+ struct i915_buddy_block,
+ tmp_link);
+ if (!block)
+ break;
+
+ list_del(&block->tmp_link);
+
+ block_start = i915_buddy_block_offset(block);
+ block_end = block_start + i915_buddy_block_size(mm, block) - 1;
+
+ if (!overlaps(start, end, block_start, block_end))
+ continue;
+
+ if (i915_buddy_block_is_allocated(block)) {
+ err = -ENOSPC;
+ goto err_free;
+ }
+
+ if (contains(start, end, block_start, block_end)) {
+ if (!i915_buddy_block_is_free(block)) {
+ err = -ENOSPC;
+ goto err_free;
+ }
+
+ mark_allocated(block);
+ list_add_tail(&block->link, &allocated);
+ continue;
+ }
+
+ if (!i915_buddy_block_is_split(block)) {
+ err = split_block(mm, block);
+ if (unlikely(err))
+ goto err_undo;
+ }
+
+ list_add(&block->right->tmp_link, &dfs);
+ list_add(&block->left->tmp_link, &dfs);
+ } while (1);
+
+ list_splice_tail(&allocated, blocks);
+ return 0;
+
+err_undo:
+ /*
+ * We really don't want to leave around a bunch of split blocks, since
+ * bigger is better, so make sure we merge everything back before we
+ * free the allocated blocks.
+ */
+ buddy = get_buddy(block);
+ if (buddy &&
+ (i915_buddy_block_is_free(block) &&
+ i915_buddy_block_is_free(buddy)))
+ __i915_buddy_free(mm, block);
+
+err_free:
+ i915_buddy_free_list(mm, &allocated);
+ return err;
+}
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/i915_buddy.c"
+#endif
+
+void i915_buddy_module_exit(void)
+{
+ kmem_cache_destroy(slab_blocks);
+}
+
+int __init i915_buddy_module_init(void)
+{
+ slab_blocks = KMEM_CACHE(i915_buddy_block, 0);
+ if (!slab_blocks)
+ return -ENOMEM;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_buddy.h b/drivers/gpu/drm/i915/i915_buddy.h
new file mode 100644
index 000000000000..3940d632f208
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_buddy.h
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef __I915_BUDDY_H__
+#define __I915_BUDDY_H__
+
+#include <linux/bitops.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+struct i915_buddy_block {
+#define I915_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
+#define I915_BUDDY_HEADER_STATE GENMASK_ULL(11, 10)
+#define I915_BUDDY_ALLOCATED (1 << 10)
+#define I915_BUDDY_FREE (2 << 10)
+#define I915_BUDDY_SPLIT (3 << 10)
+/* Free to be used, if needed in the future */
+#define I915_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6)
+#define I915_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0)
+ u64 header;
+
+ struct i915_buddy_block *left;
+ struct i915_buddy_block *right;
+ struct i915_buddy_block *parent;
+
+ void *private; /* owned by creator */
+
+ /*
+ * While the block is allocated by the user through i915_buddy_alloc*,
+ * the user has ownership of the link, for example to maintain within
+ * a list, if so desired. As soon as the block is freed with
+ * i915_buddy_free* ownership is given back to the mm.
+ */
+ struct list_head link;
+ struct list_head tmp_link;
+};
+
+/* Order-zero must be at least PAGE_SIZE */
+#define I915_BUDDY_MAX_ORDER (63 - PAGE_SHIFT)
+
+/*
+ * Binary Buddy System.
+ *
+ * Locking should be handled by the user, a simple mutex around
+ * i915_buddy_alloc* and i915_buddy_free* should suffice.
+ */
+struct i915_buddy_mm {
+ /* Maintain a free list for each order. */
+ struct list_head *free_list;
+
+ /*
+ * Maintain explicit binary tree(s) to track the allocation of the
+ * address space. This gives us a simple way of finding a buddy block
+ * and performing the potentially recursive merge step when freeing a
+ * block. Nodes are either allocated or free, in which case they will
+ * also exist on the respective free list.
+ */
+ struct i915_buddy_block **roots;
+
+ /*
+ * Anything from here is public, and remains static for the lifetime of
+ * the mm. Everything above is considered do-not-touch.
+ */
+ unsigned int n_roots;
+ unsigned int max_order;
+
+ /* Must be at least PAGE_SIZE */
+ u64 chunk_size;
+ u64 size;
+};
+
+static inline u64
+i915_buddy_block_offset(struct i915_buddy_block *block)
+{
+ return block->header & I915_BUDDY_HEADER_OFFSET;
+}
+
+static inline unsigned int
+i915_buddy_block_order(struct i915_buddy_block *block)
+{
+ return block->header & I915_BUDDY_HEADER_ORDER;
+}
+
+static inline unsigned int
+i915_buddy_block_state(struct i915_buddy_block *block)
+{
+ return block->header & I915_BUDDY_HEADER_STATE;
+}
+
+static inline bool
+i915_buddy_block_is_allocated(struct i915_buddy_block *block)
+{
+ return i915_buddy_block_state(block) == I915_BUDDY_ALLOCATED;
+}
+
+static inline bool
+i915_buddy_block_is_free(struct i915_buddy_block *block)
+{
+ return i915_buddy_block_state(block) == I915_BUDDY_FREE;
+}
+
+static inline bool
+i915_buddy_block_is_split(struct i915_buddy_block *block)
+{
+ return i915_buddy_block_state(block) == I915_BUDDY_SPLIT;
+}
+
+static inline u64
+i915_buddy_block_size(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+ return mm->chunk_size << i915_buddy_block_order(block);
+}
+
+int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size);
+
+void i915_buddy_fini(struct i915_buddy_mm *mm);
+
+struct i915_buddy_block *
+i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned int order);
+
+int i915_buddy_alloc_range(struct i915_buddy_mm *mm,
+ struct list_head *blocks,
+ u64 start, u64 size);
+
+void i915_buddy_free(struct i915_buddy_mm *mm, struct i915_buddy_block *block);
+
+void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head *objects);
+
+void i915_buddy_module_exit(void);
+int i915_buddy_module_init(void);
+
+#endif
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index a3b4d99d64b9..e0403ce9ce69 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -1468,42 +1468,43 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
* space. Parsing should be faster in some cases this way.
*/
batch_end = cmd + batch_length / sizeof(*batch_end);
- while (*cmd != MI_BATCH_BUFFER_END) {
- u32 length = 1;
-
- if (*cmd != MI_NOOP) { /* MI_NOOP == 0 */
- desc = find_cmd(engine, *cmd, desc, &default_desc);
- if (!desc) {
- DRM_DEBUG("CMD: Unrecognized command: 0x%08X\n", *cmd);
- ret = -EINVAL;
- break;
- }
+ do {
+ u32 length;
- if (desc->flags & CMD_DESC_FIXED)
- length = desc->length.fixed;
- else
- length = (*cmd & desc->length.mask) + LENGTH_BIAS;
+ if (*cmd == MI_BATCH_BUFFER_END)
+ break;
- if ((batch_end - cmd) < length) {
- DRM_DEBUG("CMD: Command length exceeds batch length: 0x%08X length=%u batchlen=%td\n",
- *cmd,
- length,
- batch_end - cmd);
- ret = -EINVAL;
- break;
- }
+ desc = find_cmd(engine, *cmd, desc, &default_desc);
+ if (!desc) {
+ DRM_DEBUG("CMD: Unrecognized command: 0x%08X\n", *cmd);
+ ret = -EINVAL;
+ break;
+ }
- if (!check_cmd(engine, desc, cmd, length)) {
- ret = -EACCES;
- break;
- }
+ if (desc->flags & CMD_DESC_FIXED)
+ length = desc->length.fixed;
+ else
+ length = (*cmd & desc->length.mask) + LENGTH_BIAS;
- if (cmd_desc_is(desc, MI_BATCH_BUFFER_START)) {
- ret = check_bbstart(cmd, offset, length, batch_length,
- batch_addr, shadow_addr,
- jump_whitelist);
- break;
- }
+ if ((batch_end - cmd) < length) {
+ DRM_DEBUG("CMD: Command length exceeds batch length: 0x%08X length=%u batchlen=%td\n",
+ *cmd,
+ length,
+ batch_end - cmd);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!check_cmd(engine, desc, cmd, length)) {
+ ret = -EACCES;
+ break;
+ }
+
+ if (cmd_desc_is(desc, MI_BATCH_BUFFER_START)) {
+ ret = check_bbstart(cmd, offset, length, batch_length,
+ batch_addr, shadow_addr,
+ jump_whitelist);
+ break;
}
if (!IS_ERR_OR_NULL(jump_whitelist))
@@ -1516,7 +1517,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
ret = -EINVAL;
break;
}
- }
+ } while (1);
if (trampoline) {
/*
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index cc745751ac53..44969f5dde50 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -538,20 +538,20 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 0 :
rp_state_cap >> 16) & 0xff;
max_freq *= (IS_GEN9_BC(dev_priv) ||
- GRAPHICS_VER(dev_priv) >= 10 ? GEN9_FREQ_SCALER : 1);
+ GRAPHICS_VER(dev_priv) >= 11 ? GEN9_FREQ_SCALER : 1);
seq_printf(m, "Lowest (RPN) frequency: %dMHz\n",
intel_gpu_freq(rps, max_freq));
max_freq = (rp_state_cap & 0xff00) >> 8;
max_freq *= (IS_GEN9_BC(dev_priv) ||
- GRAPHICS_VER(dev_priv) >= 10 ? GEN9_FREQ_SCALER : 1);
+ GRAPHICS_VER(dev_priv) >= 11 ? GEN9_FREQ_SCALER : 1);
seq_printf(m, "Nominal (RP1) frequency: %dMHz\n",
intel_gpu_freq(rps, max_freq));
max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 16 :
rp_state_cap >> 0) & 0xff;
max_freq *= (IS_GEN9_BC(dev_priv) ||
- GRAPHICS_VER(dev_priv) >= 10 ? GEN9_FREQ_SCALER : 1);
+ GRAPHICS_VER(dev_priv) >= 11 ? GEN9_FREQ_SCALER : 1);
seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
intel_gpu_freq(rps, max_freq));
seq_printf(m, "Max overclocked frequency: %dMHz\n",
@@ -636,7 +636,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
intel_uncore_read16(uncore, C0DRB3_BW));
seq_printf(m, "C1DRB3 = 0x%04x\n",
intel_uncore_read16(uncore, C1DRB3_BW));
- } else if (INTEL_GEN(dev_priv) >= 6) {
+ } else if (GRAPHICS_VER(dev_priv) >= 6) {
seq_printf(m, "MAD_DIMM_C0 = 0x%08x\n",
intel_uncore_read(uncore, MAD_DIMM_C0));
seq_printf(m, "MAD_DIMM_C1 = 0x%08x\n",
diff --git a/drivers/gpu/drm/i915/i915_debugfs_params.c b/drivers/gpu/drm/i915/i915_debugfs_params.c
index 4e2b077692cb..20424275d41e 100644
--- a/drivers/gpu/drm/i915/i915_debugfs_params.c
+++ b/drivers/gpu/drm/i915/i915_debugfs_params.c
@@ -6,9 +6,21 @@
#include <linux/kernel.h>
#include "i915_debugfs_params.h"
+#include "gt/intel_gt.h"
+#include "gt/uc/intel_guc.h"
#include "i915_drv.h"
#include "i915_params.h"
+#define MATCH_DEBUGFS_NODE_NAME(_file, _name) \
+ (strcmp((_file)->f_path.dentry->d_name.name, (_name)) == 0)
+
+#define GET_I915(i915, name, ptr) \
+ do { \
+ struct i915_params *params; \
+ params = container_of(((void *)(ptr)), typeof(*params), name); \
+ (i915) = container_of(params, typeof(*(i915)), params); \
+ } while (0)
+
/* int param */
static int i915_param_int_show(struct seq_file *m, void *data)
{
@@ -24,6 +36,16 @@ static int i915_param_int_open(struct inode *inode, struct file *file)
return single_open(file, i915_param_int_show, inode->i_private);
}
+static int notify_guc(struct drm_i915_private *i915)
+{
+ int ret = 0;
+
+ if (intel_uc_uses_guc_submission(&i915->gt.uc))
+ ret = intel_guc_global_policies_update(&i915->gt.uc.guc);
+
+ return ret;
+}
+
static ssize_t i915_param_int_write(struct file *file,
const char __user *ubuf, size_t len,
loff_t *offp)
@@ -81,8 +103,10 @@ static ssize_t i915_param_uint_write(struct file *file,
const char __user *ubuf, size_t len,
loff_t *offp)
{
+ struct drm_i915_private *i915;
struct seq_file *m = file->private_data;
unsigned int *value = m->private;
+ unsigned int old = *value;
int ret;
ret = kstrtouint_from_user(ubuf, len, 0, value);
@@ -95,6 +119,14 @@ static ssize_t i915_param_uint_write(struct file *file,
*value = b;
}
+ if (!ret && MATCH_DEBUGFS_NODE_NAME(file, "reset")) {
+ GET_I915(i915, reset, value);
+
+ ret = notify_guc(i915);
+ if (ret)
+ *value = old;
+ }
+
return ret ?: len;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 73de45472f60..59fb4c710c8c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -271,10 +271,11 @@ static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
bool pre = false;
pre |= IS_HSW_EARLY_SDV(dev_priv);
- pre |= IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0);
- pre |= IS_BXT_REVID(dev_priv, 0, BXT_REVID_B_LAST);
- pre |= IS_KBL_GT_STEP(dev_priv, 0, STEP_A0);
- pre |= IS_GLK_REVID(dev_priv, 0, GLK_REVID_A2);
+ pre |= IS_SKYLAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x6;
+ pre |= IS_BROXTON(dev_priv) && INTEL_REVID(dev_priv) < 0xA;
+ pre |= IS_KABYLAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x1;
+ pre |= IS_GEMINILAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x3;
+ pre |= IS_ICELAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x7;
if (pre) {
drm_err(&dev_priv->drm, "This is a pre-production stepping. "
@@ -561,7 +562,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
if (ret)
goto err_perf;
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "inteldrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, dev_priv->drm.driver);
if (ret)
goto err_ggtt;
@@ -619,7 +620,9 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
intel_opregion_setup(dev_priv);
- intel_pcode_init(dev_priv);
+ ret = intel_pcode_init(dev_priv);
+ if (ret)
+ goto err_msi;
/*
* Fill the dram structure to get the system dram info. This will be
@@ -1230,6 +1233,10 @@ static int i915_drm_resume(struct drm_device *dev)
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
+ ret = intel_pcode_init(dev_priv);
+ if (ret)
+ return ret;
+
sanitize_gpu(dev_priv);
ret = i915_ggtt_enable_hw(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b30397b04529..005b1cec7007 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -202,6 +202,68 @@ struct drm_i915_file_private {
struct rcu_head rcu;
};
+ /** @proto_context_lock: Guards all struct i915_gem_proto_context
+ * operations
+ *
+ * This not only guards @proto_context_xa, but is always held
+ * whenever we manipulate any struct i915_gem_proto_context,
+ * including finalizing it on first actual use of the GEM context.
+ *
+ * See i915_gem_proto_context.
+ */
+ struct mutex proto_context_lock;
+
+ /** @proto_context_xa: xarray of struct i915_gem_proto_context
+ *
+ * Historically, the context uAPI allowed for two methods of
+ * setting context parameters: SET_CONTEXT_PARAM and
+ * CONTEXT_CREATE_EXT_SETPARAM. The former is allowed to be called
+ * at any time while the later happens as part of
+ * GEM_CONTEXT_CREATE. Everything settable via one was settable
+ * via the other. While some params are fairly simple and setting
+ * them on a live context is harmless such as the context priority,
+ * others are far trickier such as the VM or the set of engines.
+ * In order to swap out the VM, for instance, we have to delay
+ * until all current in-flight work is complete, swap in the new
+ * VM, and then continue. This leads to a plethora of potential
+ * race conditions we'd really rather avoid.
+ *
+ * We have since disallowed setting these more complex parameters
+ * on active contexts. This works by delaying the creation of the
+ * actual context until after the client is done configuring it
+ * with SET_CONTEXT_PARAM. From the perspective of the client, it
+ * has the same u32 context ID the whole time. From the
+ * perspective of i915, however, it's a struct i915_gem_proto_context
+ * right up until the point where we attempt to do something which
+ * the proto-context can't handle. Then the struct i915_gem_context
+ * gets created.
+ *
+ * This is accomplished via a little xarray dance. When
+ * GEM_CONTEXT_CREATE is called, we create a struct
+ * i915_gem_proto_context, reserve a slot in @context_xa but leave
+ * it NULL, and place the proto-context in the corresponding slot
+ * in @proto_context_xa. Then, in i915_gem_context_lookup(), we
+ * first check @context_xa. If it's there, we return the struct
+ * i915_gem_context and we're done. If it's not, we look in
+ * @proto_context_xa and, if we find it there, we create the actual
+ * context and kill the proto-context.
+ *
+ * In order for this dance to work properly, everything which ever
+ * touches a struct i915_gem_proto_context is guarded by
+ * @proto_context_lock, including context creation. Yes, this
+ * means context creation now takes a giant global lock but it
+ * can't really be helped and that should never be on any driver's
+ * fast-path anyway.
+ */
+ struct xarray proto_context_xa;
+
+ /** @context_xa: xarray of fully created i915_gem_context
+ *
+ * Write access to this xarray is guarded by @proto_context_lock.
+ * Otherwise, writers may race with finalize_create_context_locked().
+ *
+ * See @proto_context_xa.
+ */
struct xarray context_xa;
struct xarray vm_xa;
@@ -270,8 +332,10 @@ struct drm_i915_display_funcs {
int (*bw_calc_min_cdclk)(struct intel_atomic_state *state);
int (*get_fifo_size)(struct drm_i915_private *dev_priv,
enum i9xx_plane_id i9xx_plane);
- int (*compute_pipe_wm)(struct intel_crtc_state *crtc_state);
- int (*compute_intermediate_wm)(struct intel_crtc_state *crtc_state);
+ int (*compute_pipe_wm)(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
+ int (*compute_intermediate_wm)(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
void (*initial_watermarks)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void (*atomic_update_watermarks)(struct intel_atomic_state *state,
@@ -330,15 +394,6 @@ struct drm_i915_display_funcs {
void (*read_luts)(struct intel_crtc_state *crtc_state);
};
-enum i915_cache_level {
- I915_CACHE_NONE = 0,
- I915_CACHE_LLC, /* also used for snoopable memory on non-LLC */
- I915_CACHE_L3_LLC, /* gen7+, L3 sits between the domain specifc
- caches, eg sampler/render caches, and the
- large Last-Level-Cache. LLC is coherent with
- the CPU, but L3 is only visible to the GPU. */
- I915_CACHE_WT, /* hsw:gt3e WriteThrough for scanouts */
-};
#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */
@@ -346,13 +401,14 @@ struct intel_fbc {
/* This is always the inner lock when overlapping with struct_mutex and
* it's the outer lock when overlapping with stolen_lock. */
struct mutex lock;
- unsigned threshold;
unsigned int possible_framebuffer_bits;
unsigned int busy_bits;
struct intel_crtc *crtc;
struct drm_mm_node compressed_fb;
- struct drm_mm_node *compressed_llb;
+ struct drm_mm_node compressed_llb;
+
+ u8 limit;
bool false_color;
@@ -467,6 +523,7 @@ struct i915_drrs {
#define QUIRK_PIN_SWIZZLED_PAGES (1<<5)
#define QUIRK_INCREASE_T12_DELAY (1<<6)
#define QUIRK_INCREASE_DDI_DISABLED_TIME (1<<7)
+#define QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK (1<<8)
struct intel_fbdev;
struct intel_fbc_work;
@@ -552,7 +609,7 @@ struct i915_gem_mm {
* notifier_lock for mmu notifiers, memory may not be allocated
* while holding this lock.
*/
- spinlock_t notifier_lock;
+ rwlock_t notifier_lock;
#endif
/* shrinker accounting, also useful for userland debugging */
@@ -576,6 +633,9 @@ i915_fence_timeout(const struct drm_i915_private *i915)
#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915))
+/* Amount of PSF GV points, BSpec precisely defines this */
+#define I915_NUM_PSF_GV_POINTS 3
+
struct ddi_vbt_port_info {
/* Non-NULL if port present. */
struct intel_bios_encoder_data *devdata;
@@ -1089,12 +1149,16 @@ struct drm_i915_private {
INTEL_DRAM_LPDDR5,
} type;
u8 num_qgv_points;
+ u8 num_psf_gv_points;
} dram_info;
struct intel_bw_info {
/* for each QGV point */
unsigned int deratedbw[I915_NUM_QGV_POINTS];
+ /* for each PSF GV point */
+ unsigned int psf_bw[I915_NUM_PSF_GV_POINTS];
u8 num_qgv_points;
+ u8 num_psf_gv_points;
u8 num_planes;
} max_bw[6];
@@ -1134,6 +1198,8 @@ struct drm_i915_private {
/* For i915gm/i945gm vblank irq workaround */
u8 vblank_enabled;
+ bool irq_enabled;
+
/* perform PHY state sanity checks? */
bool chv_phy_assert[2];
@@ -1237,26 +1303,17 @@ static inline struct drm_i915_private *pdev_to_i915(struct pci_dev *pdev)
#define INTEL_DEVID(dev_priv) (RUNTIME_INFO(dev_priv)->device_id)
-/*
- * Deprecated: this will be replaced by individual IP checks:
- * GRAPHICS_VER(), MEDIA_VER() and DISPLAY_VER()
- */
-#define INTEL_GEN(dev_priv) GRAPHICS_VER(dev_priv)
-/*
- * Deprecated: use IS_GRAPHICS_VER(), IS_MEDIA_VER() and IS_DISPLAY_VER() as
- * appropriate.
- */
-#define IS_GEN_RANGE(dev_priv, s, e) IS_GRAPHICS_VER(dev_priv, (s), (e))
-/*
- * Deprecated: use GRAPHICS_VER(), MEDIA_VER() and DISPLAY_VER() as appropriate.
- */
-#define IS_GEN(dev_priv, n) (GRAPHICS_VER(dev_priv) == (n))
+#define IP_VER(ver, rel) ((ver) << 8 | (rel))
#define GRAPHICS_VER(i915) (INTEL_INFO(i915)->graphics_ver)
+#define GRAPHICS_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->graphics_ver, \
+ INTEL_INFO(i915)->graphics_rel)
#define IS_GRAPHICS_VER(i915, from, until) \
(GRAPHICS_VER(i915) >= (from) && GRAPHICS_VER(i915) <= (until))
#define MEDIA_VER(i915) (INTEL_INFO(i915)->media_ver)
+#define MEDIA_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->media_ver, \
+ INTEL_INFO(i915)->media_rel)
#define IS_MEDIA_VER(i915, from, until) \
(MEDIA_VER(i915) >= (from) && MEDIA_VER(i915) <= (until))
@@ -1264,29 +1321,20 @@ static inline struct drm_i915_private *pdev_to_i915(struct pci_dev *pdev)
#define IS_DISPLAY_VER(i915, from, until) \
(DISPLAY_VER(i915) >= (from) && DISPLAY_VER(i915) <= (until))
-#define REVID_FOREVER 0xff
#define INTEL_REVID(dev_priv) (to_pci_dev((dev_priv)->drm.dev)->revision)
#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb)
-/*
- * Return true if revision is in range [since,until] inclusive.
- *
- * Use 0 for open-ended since, and REVID_FOREVER for open-ended until.
- */
-#define IS_REVID(p, since, until) \
- (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until))
-
#define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step)
#define INTEL_GT_STEP(__i915) (RUNTIME_INFO(__i915)->step.gt_step)
#define IS_DISPLAY_STEP(__i915, since, until) \
(drm_WARN_ON(&(__i915)->drm, INTEL_DISPLAY_STEP(__i915) == STEP_NONE), \
- INTEL_DISPLAY_STEP(__i915) >= (since) && INTEL_DISPLAY_STEP(__i915) <= (until))
+ INTEL_DISPLAY_STEP(__i915) >= (since) && INTEL_DISPLAY_STEP(__i915) < (until))
#define IS_GT_STEP(__i915, since, until) \
(drm_WARN_ON(&(__i915)->drm, INTEL_GT_STEP(__i915) == STEP_NONE), \
- INTEL_GT_STEP(__i915) >= (since) && INTEL_GT_STEP(__i915) <= (until))
+ INTEL_GT_STEP(__i915) >= (since) && INTEL_GT_STEP(__i915) < (until))
static __always_inline unsigned int
__platform_mask_index(const struct intel_runtime_info *info,
@@ -1385,7 +1433,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define IS_GEMINILAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_GEMINILAKE)
#define IS_COFFEELAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_COFFEELAKE)
#define IS_COMETLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_COMETLAKE)
-#define IS_CANNONLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_CANNONLAKE)
+#define IS_CANNONLAKE(dev_priv) 0
#define IS_ICELAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_ICELAKE)
#define IS_JSL_EHL(dev_priv) (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE) || \
IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE))
@@ -1394,6 +1442,12 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define IS_DG1(dev_priv) IS_PLATFORM(dev_priv, INTEL_DG1)
#define IS_ALDERLAKE_S(dev_priv) IS_PLATFORM(dev_priv, INTEL_ALDERLAKE_S)
#define IS_ALDERLAKE_P(dev_priv) IS_PLATFORM(dev_priv, INTEL_ALDERLAKE_P)
+#define IS_XEHPSDV(dev_priv) IS_PLATFORM(dev_priv, INTEL_XEHPSDV)
+#define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, INTEL_DG2)
+#define IS_DG2_G10(dev_priv) \
+ IS_SUBPLATFORM(dev_priv, INTEL_DG2, INTEL_SUBPLATFORM_G10)
+#define IS_DG2_G11(dev_priv) \
+ IS_SUBPLATFORM(dev_priv, INTEL_DG2, INTEL_SUBPLATFORM_G11)
#define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \
(INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00)
#define IS_BDW_ULT(dev_priv) \
@@ -1445,8 +1499,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define IS_CML_GT2(dev_priv) (IS_COMETLAKE(dev_priv) && \
INTEL_INFO(dev_priv)->gt == 2)
-#define IS_CNL_WITH_PORT_F(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_CANNONLAKE, INTEL_SUBPLATFORM_PORTF)
#define IS_ICL_WITH_PORT_F(dev_priv) \
IS_SUBPLATFORM(dev_priv, INTEL_ICELAKE, INTEL_SUBPLATFORM_PORTF)
@@ -1456,60 +1508,17 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define IS_TGL_Y(dev_priv) \
IS_SUBPLATFORM(dev_priv, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_ULX)
-#define SKL_REVID_A0 0x0
-#define SKL_REVID_B0 0x1
-#define SKL_REVID_C0 0x2
-#define SKL_REVID_D0 0x3
-#define SKL_REVID_E0 0x4
-#define SKL_REVID_F0 0x5
-#define SKL_REVID_G0 0x6
-#define SKL_REVID_H0 0x7
-
-#define IS_SKL_REVID(p, since, until) (IS_SKYLAKE(p) && IS_REVID(p, since, until))
-
-#define BXT_REVID_A0 0x0
-#define BXT_REVID_A1 0x1
-#define BXT_REVID_B0 0x3
-#define BXT_REVID_B_LAST 0x8
-#define BXT_REVID_C0 0x9
-
-#define IS_BXT_REVID(dev_priv, since, until) \
- (IS_BROXTON(dev_priv) && IS_REVID(dev_priv, since, until))
+#define IS_SKL_GT_STEP(p, since, until) (IS_SKYLAKE(p) && IS_GT_STEP(p, since, until))
#define IS_KBL_GT_STEP(dev_priv, since, until) \
(IS_KABYLAKE(dev_priv) && IS_GT_STEP(dev_priv, since, until))
#define IS_KBL_DISPLAY_STEP(dev_priv, since, until) \
(IS_KABYLAKE(dev_priv) && IS_DISPLAY_STEP(dev_priv, since, until))
-#define GLK_REVID_A0 0x0
-#define GLK_REVID_A1 0x1
-#define GLK_REVID_A2 0x2
-#define GLK_REVID_B0 0x3
-
-#define IS_GLK_REVID(dev_priv, since, until) \
- (IS_GEMINILAKE(dev_priv) && IS_REVID(dev_priv, since, until))
-
-#define CNL_REVID_A0 0x0
-#define CNL_REVID_B0 0x1
-#define CNL_REVID_C0 0x2
-
-#define IS_CNL_REVID(p, since, until) \
- (IS_CANNONLAKE(p) && IS_REVID(p, since, until))
-
-#define ICL_REVID_A0 0x0
-#define ICL_REVID_A2 0x1
-#define ICL_REVID_B0 0x3
-#define ICL_REVID_B2 0x4
-#define ICL_REVID_C0 0x5
-
-#define IS_ICL_REVID(p, since, until) \
- (IS_ICELAKE(p) && IS_REVID(p, since, until))
-
-#define EHL_REVID_A0 0x0
-#define EHL_REVID_B0 0x1
-
-#define IS_JSL_EHL_REVID(p, since, until) \
- (IS_JSL_EHL(p) && IS_REVID(p, since, until))
+#define IS_JSL_EHL_GT_STEP(p, since, until) \
+ (IS_JSL_EHL(p) && IS_GT_STEP(p, since, until))
+#define IS_JSL_EHL_DISPLAY_STEP(p, since, until) \
+ (IS_JSL_EHL(p) && IS_DISPLAY_STEP(p, since, until))
#define IS_TGL_DISPLAY_STEP(__i915, since, until) \
(IS_TIGERLAKE(__i915) && \
@@ -1523,18 +1532,13 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
(IS_TIGERLAKE(__i915) && !(IS_TGL_U(__i915) || IS_TGL_Y(__i915)) && \
IS_GT_STEP(__i915, since, until))
-#define RKL_REVID_A0 0x0
-#define RKL_REVID_B0 0x1
-#define RKL_REVID_C0 0x4
+#define IS_RKL_DISPLAY_STEP(p, since, until) \
+ (IS_ROCKETLAKE(p) && IS_DISPLAY_STEP(p, since, until))
-#define IS_RKL_REVID(p, since, until) \
- (IS_ROCKETLAKE(p) && IS_REVID(p, since, until))
-
-#define DG1_REVID_A0 0x0
-#define DG1_REVID_B0 0x1
-
-#define IS_DG1_REVID(p, since, until) \
- (IS_DG1(p) && IS_REVID(p, since, until))
+#define IS_DG1_GT_STEP(p, since, until) \
+ (IS_DG1(p) && IS_GT_STEP(p, since, until))
+#define IS_DG1_DISPLAY_STEP(p, since, until) \
+ (IS_DG1(p) && IS_DISPLAY_STEP(p, since, until))
#define IS_ADLS_DISPLAY_STEP(__i915, since, until) \
(IS_ALDERLAKE_S(__i915) && \
@@ -1552,6 +1556,31 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
(IS_ALDERLAKE_P(__i915) && \
IS_GT_STEP(__i915, since, until))
+#define IS_XEHPSDV_GT_STEP(__i915, since, until) \
+ (IS_XEHPSDV(__i915) && IS_GT_STEP(__i915, since, until))
+
+/*
+ * DG2 hardware steppings are a bit unusual. The hardware design was forked
+ * to create two variants (G10 and G11) which have distinct workaround sets.
+ * The G11 fork of the DG2 design resets the GT stepping back to "A0" for its
+ * first iteration, even though it's more similar to a G10 B0 stepping in terms
+ * of functionality and workarounds. However the display stepping does not
+ * reset in the same manner --- a specific stepping like "B0" has a consistent
+ * meaning regardless of whether it belongs to a G10 or G11 DG2.
+ *
+ * TLDR: All GT workarounds and stepping-specific logic must be applied in
+ * relation to a specific subplatform (G10 or G11), whereas display workarounds
+ * and stepping-specific logic will be applied with a general DG2-wide stepping
+ * number.
+ */
+#define IS_DG2_GT_STEP(__i915, variant, since, until) \
+ (IS_SUBPLATFORM(__i915, INTEL_DG2, INTEL_SUBPLATFORM_##variant) && \
+ IS_GT_STEP(__i915, since, until))
+
+#define IS_DG2_DISP_STEP(__i915, since, until) \
+ (IS_DG2(__i915) && \
+ IS_DISPLAY_STEP(__i915, since, until))
+
#define IS_LP(dev_priv) (INTEL_INFO(dev_priv)->is_lp)
#define IS_GEN9_LP(dev_priv) (GRAPHICS_VER(dev_priv) == 9 && IS_LP(dev_priv))
#define IS_GEN9_BC(dev_priv) (GRAPHICS_VER(dev_priv) == 9 && !IS_LP(dev_priv))
@@ -1589,8 +1618,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define HAS_LOGICAL_RING_ELSQ(dev_priv) \
(INTEL_INFO(dev_priv)->has_logical_ring_elsq)
-#define HAS_MASTER_UNIT_IRQ(dev_priv) (INTEL_INFO(dev_priv)->has_master_unit_irq)
-
#define HAS_EXECLISTS(dev_priv) HAS_LOGICAL_RING_CONTEXTS(dev_priv)
#define INTEL_PPGTT(dev_priv) (INTEL_INFO(dev_priv)->ppgtt_type)
@@ -1616,12 +1643,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
/* WaRsDisableCoarsePowerGating:skl,cnl */
#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
- (IS_CANNONLAKE(dev_priv) || \
- IS_SKL_GT3(dev_priv) || \
- IS_SKL_GT4(dev_priv))
+ (IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
#define HAS_GMBUS_IRQ(dev_priv) (GRAPHICS_VER(dev_priv) >= 4)
-#define HAS_GMBUS_BURST_READ(dev_priv) (GRAPHICS_VER(dev_priv) >= 10 || \
+#define HAS_GMBUS_BURST_READ(dev_priv) (GRAPHICS_VER(dev_priv) >= 11 || \
IS_GEMINILAKE(dev_priv) || \
IS_KABYLAKE(dev_priv))
@@ -1641,6 +1666,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define HAS_DP_MST(dev_priv) (INTEL_INFO(dev_priv)->display.has_dp_mst)
+#define HAS_CDCLK_CRAWL(dev_priv) (INTEL_INFO(dev_priv)->display.has_cdclk_crawl)
#define HAS_DDI(dev_priv) (INTEL_INFO(dev_priv)->display.has_ddi)
#define HAS_FPGA_DBG_UNCLAIMED(dev_priv) (INTEL_INFO(dev_priv)->display.has_fpga_dbg)
#define HAS_PSR(dev_priv) (INTEL_INFO(dev_priv)->display.has_psr)
@@ -1662,6 +1688,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define HAS_RUNTIME_PM(dev_priv) (INTEL_INFO(dev_priv)->has_runtime_pm)
#define HAS_64BIT_RELOC(dev_priv) (INTEL_INFO(dev_priv)->has_64bit_reloc)
+#define HAS_MSLICES(dev_priv) \
+ (INTEL_INFO(dev_priv)->has_mslices)
+
#define HAS_IPC(dev_priv) (INTEL_INFO(dev_priv)->display.has_ipc)
#define HAS_REGION(i915, i) (INTEL_INFO(i915)->memory_regions & (i))
@@ -1751,9 +1780,6 @@ void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv);
void i915_gem_init_early(struct drm_i915_private *dev_priv);
void i915_gem_cleanup_early(struct drm_i915_private *dev_priv);
-struct intel_memory_region *i915_gem_shmem_setup(struct drm_i915_private *i915,
- u16 type, u16 instance);
-
static inline void i915_gem_drain_freed_objects(struct drm_i915_private *i915)
{
/*
@@ -1850,24 +1876,18 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags);
-static inline struct i915_gem_context *
-__i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
-{
- return xa_load(&file_priv->context_xa, id);
-}
-
-static inline struct i915_gem_context *
-i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
+static inline struct i915_address_space *
+i915_gem_vm_lookup(struct drm_i915_file_private *file_priv, u32 id)
{
- struct i915_gem_context *ctx;
+ struct i915_address_space *vm;
rcu_read_lock();
- ctx = __i915_gem_context_lookup_rcu(file_priv, id);
- if (ctx && !kref_get_unless_zero(&ctx->ref))
- ctx = NULL;
+ vm = xa_load(&file_priv->vm_xa, id);
+ if (vm && !kref_get_unless_zero(&vm->ref))
+ vm = NULL;
rcu_read_unlock();
- return ctx;
+ return vm;
}
/* i915_gem_evict.c */
@@ -1934,8 +1954,8 @@ int remap_io_sg(struct vm_area_struct *vma,
static inline int intel_hws_csb_write_index(struct drm_i915_private *i915)
{
- if (GRAPHICS_VER(i915) >= 10)
- return CNL_HWS_CSB_WRITE_INDEX;
+ if (GRAPHICS_VER(i915) >= 11)
+ return ICL_HWS_CSB_WRITE_INDEX;
else
return I915_HWS_CSB_WRITE_INDEX;
}
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 589388dec48a..590efc8b0265 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -469,12 +469,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
if (ret != -ENODEV)
goto out;
- ret = -ENODEV;
- if (obj->ops->pread)
- ret = obj->ops->pread(obj, args);
- if (ret != -ENODEV)
- goto out;
-
ret = i915_gem_object_wait(obj,
I915_WAIT_INTERRUPTIBLE,
MAX_SCHEDULE_TIMEOUT);
@@ -1005,8 +999,11 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
}
}
- if (obj->mm.madv != __I915_MADV_PURGED)
+ if (obj->mm.madv != __I915_MADV_PURGED) {
obj->mm.madv = args->madv;
+ if (obj->ops->adjust_lru)
+ obj->ops->adjust_lru(obj);
+ }
if (i915_gem_object_has_pages(obj)) {
unsigned long flags;
@@ -1204,58 +1201,6 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file)
return ret;
}
-void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ww, bool intr)
-{
- ww_acquire_init(&ww->ctx, &reservation_ww_class);
- INIT_LIST_HEAD(&ww->obj_list);
- ww->intr = intr;
- ww->contended = NULL;
-}
-
-static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww)
-{
- struct drm_i915_gem_object *obj;
-
- while ((obj = list_first_entry_or_null(&ww->obj_list, struct drm_i915_gem_object, obj_link))) {
- list_del(&obj->obj_link);
- i915_gem_object_unlock(obj);
- }
-}
-
-void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj)
-{
- list_del(&obj->obj_link);
- i915_gem_object_unlock(obj);
-}
-
-void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ww)
-{
- i915_gem_ww_ctx_unlock_all(ww);
- WARN_ON(ww->contended);
- ww_acquire_fini(&ww->ctx);
-}
-
-int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ww)
-{
- int ret = 0;
-
- if (WARN_ON(!ww->contended))
- return -EINVAL;
-
- i915_gem_ww_ctx_unlock_all(ww);
- if (ww->intr)
- ret = dma_resv_lock_slow_interruptible(ww->contended->base.resv, &ww->ctx);
- else
- dma_resv_lock_slow(ww->contended->base.resv, &ww->ctx);
-
- if (!ret)
- list_add_tail(&ww->contended->obj_link, &ww->obj_list);
-
- ww->contended = NULL;
-
- return ret;
-}
-
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_gem_device.c"
#include "selftests/i915_gem.c"
diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h
index 440c35f1abc9..d0752e5553db 100644
--- a/drivers/gpu/drm/i915/i915_gem.h
+++ b/drivers/gpu/drm/i915/i915_gem.h
@@ -123,16 +123,4 @@ static inline bool __tasklet_is_scheduled(struct tasklet_struct *t)
return test_bit(TASKLET_STATE_SCHED, &t->state);
}
-struct i915_gem_ww_ctx {
- struct ww_acquire_ctx ctx;
- struct list_head obj_list;
- bool intr;
- struct drm_i915_gem_object *contended;
-};
-
-void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ctx, bool intr);
-void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ctx);
-int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ctx);
-void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj);
-
#endif /* __I915_GEM_H__ */
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 4d2d59a9942b..2b73ddb11c66 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -27,6 +27,7 @@
*/
#include "gem/i915_gem_context.h"
+#include "gt/intel_gt.h"
#include "gt/intel_gt_requests.h"
#include "i915_drv.h"
diff --git a/drivers/gpu/drm/i915/i915_gem_ww.c b/drivers/gpu/drm/i915/i915_gem_ww.c
new file mode 100644
index 000000000000..3f6ff139478e
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_ww.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+#include <linux/dma-resv.h>
+#include "i915_gem_ww.h"
+#include "gem/i915_gem_object.h"
+
+void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ww, bool intr)
+{
+ ww_acquire_init(&ww->ctx, &reservation_ww_class);
+ INIT_LIST_HEAD(&ww->obj_list);
+ ww->intr = intr;
+ ww->contended = NULL;
+}
+
+static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww)
+{
+ struct drm_i915_gem_object *obj;
+
+ while ((obj = list_first_entry_or_null(&ww->obj_list, struct drm_i915_gem_object, obj_link))) {
+ list_del(&obj->obj_link);
+ i915_gem_object_unlock(obj);
+ i915_gem_object_put(obj);
+ }
+}
+
+void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj)
+{
+ list_del(&obj->obj_link);
+ i915_gem_object_unlock(obj);
+ i915_gem_object_put(obj);
+}
+
+void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ww)
+{
+ i915_gem_ww_ctx_unlock_all(ww);
+ WARN_ON(ww->contended);
+ ww_acquire_fini(&ww->ctx);
+}
+
+int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ww)
+{
+ int ret = 0;
+
+ if (WARN_ON(!ww->contended))
+ return -EINVAL;
+
+ i915_gem_ww_ctx_unlock_all(ww);
+ if (ww->intr)
+ ret = dma_resv_lock_slow_interruptible(ww->contended->base.resv, &ww->ctx);
+ else
+ dma_resv_lock_slow(ww->contended->base.resv, &ww->ctx);
+
+ if (!ret)
+ list_add_tail(&ww->contended->obj_link, &ww->obj_list);
+ else
+ i915_gem_object_put(ww->contended);
+
+ ww->contended = NULL;
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_ww.h b/drivers/gpu/drm/i915/i915_gem_ww.h
new file mode 100644
index 000000000000..f6b1a796667b
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_ww.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+#ifndef __I915_GEM_WW_H__
+#define __I915_GEM_WW_H__
+
+#include <drm/drm_drv.h>
+
+struct i915_gem_ww_ctx {
+ struct ww_acquire_ctx ctx;
+ struct list_head obj_list;
+ struct drm_i915_gem_object *contended;
+ unsigned short intr;
+ unsigned short loop;
+};
+
+void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ctx, bool intr);
+void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ctx);
+int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ctx);
+void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj);
+
+/* Internal functions used by the inlines! Don't use. */
+static inline int __i915_gem_ww_fini(struct i915_gem_ww_ctx *ww, int err)
+{
+ ww->loop = 0;
+ if (err == -EDEADLK) {
+ err = i915_gem_ww_ctx_backoff(ww);
+ if (!err)
+ ww->loop = 1;
+ }
+
+ if (!ww->loop)
+ i915_gem_ww_ctx_fini(ww);
+
+ return err;
+}
+
+static inline void
+__i915_gem_ww_init(struct i915_gem_ww_ctx *ww, bool intr)
+{
+ i915_gem_ww_ctx_init(ww, intr);
+ ww->loop = 1;
+}
+
+#define for_i915_gem_ww(_ww, _err, _intr) \
+ for (__i915_gem_ww_init(_ww, _intr); (_ww)->loop; \
+ _err = __i915_gem_ww_fini(_ww, _err))
+
+#endif
diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
index 24e18219eb50..77490cb5ff9c 100644
--- a/drivers/gpu/drm/i915/i915_getparam.c
+++ b/drivers/gpu/drm/i915/i915_getparam.c
@@ -15,7 +15,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
struct pci_dev *pdev = to_pci_dev(dev->dev);
const struct sseu_dev_info *sseu = &i915->gt.info.sseu;
drm_i915_getparam_t *param = data;
- int value;
+ int value = 0;
switch (param->param) {
case I915_PARAM_IRQ_ACTIVE:
@@ -134,6 +134,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
case I915_PARAM_HAS_EXEC_FENCE_ARRAY:
case I915_PARAM_HAS_EXEC_SUBMIT_FENCE:
case I915_PARAM_HAS_EXEC_TIMELINE_FENCES:
+ case I915_PARAM_HAS_USERPTR_PROBE:
/* For the time being all of these are always true;
* if some supported hardware does not have one of these
* features this value needs to be provided from
@@ -150,7 +151,9 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
return -ENODEV;
break;
case I915_PARAM_SUBSLICE_MASK:
- value = sseu->subslice_mask[0];
+ /* Only copy bits from the first slice */
+ memcpy(&value, sseu->subslice_mask,
+ min(sseu->ss_stride, (u8)sizeof(value)));
if (!value)
return -ENODEV;
break;
diff --git a/drivers/gpu/drm/i915/i915_globals.c b/drivers/gpu/drm/i915/i915_globals.c
deleted file mode 100644
index 3acb0b6be284..000000000000
--- a/drivers/gpu/drm/i915/i915_globals.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * SPDX-License-Identifier: MIT
- *
- * Copyright © 2019 Intel Corporation
- */
-
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-
-#include "i915_active.h"
-#include "gem/i915_gem_context.h"
-#include "gem/i915_gem_object.h"
-#include "i915_globals.h"
-#include "i915_request.h"
-#include "i915_scheduler.h"
-#include "i915_vma.h"
-
-static LIST_HEAD(globals);
-
-static atomic_t active;
-static atomic_t epoch;
-static struct park_work {
- struct delayed_work work;
- struct rcu_head rcu;
- unsigned long flags;
-#define PENDING 0
- int epoch;
-} park;
-
-static void i915_globals_shrink(void)
-{
- struct i915_global *global;
-
- /*
- * kmem_cache_shrink() discards empty slabs and reorders partially
- * filled slabs to prioritise allocating from the mostly full slabs,
- * with the aim of reducing fragmentation.
- */
- list_for_each_entry(global, &globals, link)
- global->shrink();
-}
-
-static void __i915_globals_grace(struct rcu_head *rcu)
-{
- /* Ratelimit parking as shrinking is quite slow */
- schedule_delayed_work(&park.work, round_jiffies_up_relative(2 * HZ));
-}
-
-static void __i915_globals_queue_rcu(void)
-{
- park.epoch = atomic_inc_return(&epoch);
- if (!atomic_read(&active)) {
- init_rcu_head(&park.rcu);
- call_rcu(&park.rcu, __i915_globals_grace);
- }
-}
-
-static void __i915_globals_park(struct work_struct *work)
-{
- destroy_rcu_head(&park.rcu);
-
- /* Confirm nothing woke up in the last grace period */
- if (park.epoch != atomic_read(&epoch)) {
- __i915_globals_queue_rcu();
- return;
- }
-
- clear_bit(PENDING, &park.flags);
- i915_globals_shrink();
-}
-
-void __init i915_global_register(struct i915_global *global)
-{
- GEM_BUG_ON(!global->shrink);
- GEM_BUG_ON(!global->exit);
-
- list_add_tail(&global->link, &globals);
-}
-
-static void __i915_globals_cleanup(void)
-{
- struct i915_global *global, *next;
-
- list_for_each_entry_safe_reverse(global, next, &globals, link)
- global->exit();
-}
-
-static __initconst int (* const initfn[])(void) = {
- i915_global_active_init,
- i915_global_context_init,
- i915_global_gem_context_init,
- i915_global_objects_init,
- i915_global_request_init,
- i915_global_scheduler_init,
- i915_global_vma_init,
-};
-
-int __init i915_globals_init(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(initfn); i++) {
- int err;
-
- err = initfn[i]();
- if (err) {
- __i915_globals_cleanup();
- return err;
- }
- }
-
- INIT_DELAYED_WORK(&park.work, __i915_globals_park);
- return 0;
-}
-
-void i915_globals_park(void)
-{
- /*
- * Defer shrinking the global slab caches (and other work) until
- * after a RCU grace period has completed with no activity. This
- * is to try and reduce the latency impact on the consumers caused
- * by us shrinking the caches the same time as they are trying to
- * allocate, with the assumption being that if we idle long enough
- * for an RCU grace period to elapse since the last use, it is likely
- * to be longer until we need the caches again.
- */
- if (!atomic_dec_and_test(&active))
- return;
-
- /* Queue cleanup after the next RCU grace period has freed slabs */
- if (!test_and_set_bit(PENDING, &park.flags))
- __i915_globals_queue_rcu();
-}
-
-void i915_globals_unpark(void)
-{
- atomic_inc(&epoch);
- atomic_inc(&active);
-}
-
-static void __i915_globals_flush(void)
-{
- atomic_inc(&active); /* skip shrinking */
-
- rcu_barrier(); /* wait for the work to be queued */
- flush_delayed_work(&park.work);
-
- atomic_dec(&active);
-}
-
-void i915_globals_exit(void)
-{
- GEM_BUG_ON(atomic_read(&active));
-
- __i915_globals_flush();
- __i915_globals_cleanup();
-
- /* And ensure that our DESTROY_BY_RCU slabs are truly destroyed */
- rcu_barrier();
-}
diff --git a/drivers/gpu/drm/i915/i915_globals.h b/drivers/gpu/drm/i915/i915_globals.h
deleted file mode 100644
index 2d199f411a4a..000000000000
--- a/drivers/gpu/drm/i915/i915_globals.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * SPDX-License-Identifier: MIT
- *
- * Copyright © 2019 Intel Corporation
- */
-
-#ifndef _I915_GLOBALS_H_
-#define _I915_GLOBALS_H_
-
-#include <linux/types.h>
-
-typedef void (*i915_global_func_t)(void);
-
-struct i915_global {
- struct list_head link;
-
- i915_global_func_t shrink;
- i915_global_func_t exit;
-};
-
-void i915_global_register(struct i915_global *global);
-
-int i915_globals_init(void);
-void i915_globals_park(void);
-void i915_globals_unpark(void);
-void i915_globals_exit(void);
-
-/* constructors */
-int i915_global_active_init(void);
-int i915_global_context_init(void);
-int i915_global_gem_context_init(void);
-int i915_global_objects_init(void);
-int i915_global_request_init(void);
-int i915_global_scheduler_init(void);
-int i915_global_vma_init(void);
-
-#endif /* _I915_GLOBALS_H_ */
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 966664610c8c..9cf6ac575de1 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1048,7 +1048,7 @@ i915_vma_coredump_create(const struct intel_gt *gt,
if (ret)
break;
}
- } else if (i915_gem_object_is_lmem(vma->obj)) {
+ } else if (__i915_gem_object_is_lmem(vma->obj)) {
struct intel_memory_region *mem = vma->obj->mm.region;
dma_addr_t dma;
@@ -1438,20 +1438,37 @@ capture_engine(struct intel_engine_cs *engine,
{
struct intel_engine_capture_vma *capture = NULL;
struct intel_engine_coredump *ee;
- struct i915_request *rq;
+ struct intel_context *ce;
+ struct i915_request *rq = NULL;
unsigned long flags;
ee = intel_engine_coredump_alloc(engine, GFP_KERNEL);
if (!ee)
return NULL;
- spin_lock_irqsave(&engine->active.lock, flags);
- rq = intel_engine_find_active_request(engine);
+ ce = intel_engine_get_hung_context(engine);
+ if (ce) {
+ intel_engine_clear_hung_context(engine);
+ rq = intel_context_find_active_request(ce);
+ if (!rq || !i915_request_started(rq))
+ goto no_request_capture;
+ } else {
+ /*
+ * Getting here with GuC enabled means it is a forced error capture
+ * with no actual hang. So, no need to attempt the execlist search.
+ */
+ if (!intel_uc_uses_guc_submission(&engine->gt->uc)) {
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
+ rq = intel_engine_execlist_find_hung_request(engine);
+ spin_unlock_irqrestore(&engine->sched_engine->lock,
+ flags);
+ }
+ }
if (rq)
capture = intel_engine_coredump_add_request(ee, rq,
ATOMIC_MAYFAIL);
- spin_unlock_irqrestore(&engine->active.lock, flags);
if (!capture) {
+no_request_capture:
kfree(ee);
return NULL;
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index c3816f5c6900..9bc4f4a8e12e 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -207,7 +207,7 @@ static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
(!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
return;
- if (HAS_PCH_DG1(dev_priv))
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
hpd->pch_hpd = hpd_sde_dg1;
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
hpd->pch_hpd = hpd_icp;
@@ -2297,11 +2297,10 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
GEN9_AUX_CHANNEL_C |
GEN9_AUX_CHANNEL_D;
- if (IS_CNL_WITH_PORT_F(dev_priv) || DISPLAY_VER(dev_priv) == 11)
- mask |= CNL_AUX_CHANNEL_F;
-
- if (DISPLAY_VER(dev_priv) == 11)
+ if (DISPLAY_VER(dev_priv) == 11) {
+ mask |= ICL_AUX_CHANNEL_F;
mask |= ICL_AUX_CHANNEL_E;
+ }
return mask;
}
@@ -2698,11 +2697,9 @@ gen11_display_irq_handler(struct drm_i915_private *i915)
enable_rpm_wakeref_asserts(&i915->runtime_pm);
}
-static __always_inline irqreturn_t
-__gen11_irq_handler(struct drm_i915_private * const i915,
- u32 (*intr_disable)(void __iomem * const regs),
- void (*intr_enable)(void __iomem * const regs))
+static irqreturn_t gen11_irq_handler(int irq, void *arg)
{
+ struct drm_i915_private *i915 = arg;
void __iomem * const regs = i915->uncore.regs;
struct intel_gt *gt = &i915->gt;
u32 master_ctl;
@@ -2711,9 +2708,9 @@ __gen11_irq_handler(struct drm_i915_private * const i915,
if (!intel_irqs_enabled(i915))
return IRQ_NONE;
- master_ctl = intr_disable(regs);
+ master_ctl = gen11_master_intr_disable(regs);
if (!master_ctl) {
- intr_enable(regs);
+ gen11_master_intr_enable(regs);
return IRQ_NONE;
}
@@ -2726,7 +2723,7 @@ __gen11_irq_handler(struct drm_i915_private * const i915,
gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl);
- intr_enable(regs);
+ gen11_master_intr_enable(regs);
gen11_gu_misc_irq_handler(gt, gu_misc_iir);
@@ -2735,51 +2732,69 @@ __gen11_irq_handler(struct drm_i915_private * const i915,
return IRQ_HANDLED;
}
-static irqreturn_t gen11_irq_handler(int irq, void *arg)
-{
- return __gen11_irq_handler(arg,
- gen11_master_intr_disable,
- gen11_master_intr_enable);
-}
-
-static u32 dg1_master_intr_disable_and_ack(void __iomem * const regs)
+static inline u32 dg1_master_intr_disable(void __iomem * const regs)
{
u32 val;
/* First disable interrupts */
- raw_reg_write(regs, DG1_MSTR_UNIT_INTR, 0);
+ raw_reg_write(regs, DG1_MSTR_TILE_INTR, 0);
/* Get the indication levels and ack the master unit */
- val = raw_reg_read(regs, DG1_MSTR_UNIT_INTR);
+ val = raw_reg_read(regs, DG1_MSTR_TILE_INTR);
if (unlikely(!val))
return 0;
- raw_reg_write(regs, DG1_MSTR_UNIT_INTR, val);
-
- /*
- * Now with master disabled, get a sample of level indications
- * for this interrupt and ack them right away - we keep GEN11_MASTER_IRQ
- * out as this bit doesn't exist anymore for DG1
- */
- val = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ) & ~GEN11_MASTER_IRQ;
- if (unlikely(!val))
- return 0;
-
- raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, val);
+ raw_reg_write(regs, DG1_MSTR_TILE_INTR, val);
return val;
}
static inline void dg1_master_intr_enable(void __iomem * const regs)
{
- raw_reg_write(regs, DG1_MSTR_UNIT_INTR, DG1_MSTR_IRQ);
+ raw_reg_write(regs, DG1_MSTR_TILE_INTR, DG1_MSTR_IRQ);
}
static irqreturn_t dg1_irq_handler(int irq, void *arg)
{
- return __gen11_irq_handler(arg,
- dg1_master_intr_disable_and_ack,
- dg1_master_intr_enable);
+ struct drm_i915_private * const i915 = arg;
+ struct intel_gt *gt = &i915->gt;
+ void __iomem * const regs = i915->uncore.regs;
+ u32 master_tile_ctl, master_ctl;
+ u32 gu_misc_iir;
+
+ if (!intel_irqs_enabled(i915))
+ return IRQ_NONE;
+
+ master_tile_ctl = dg1_master_intr_disable(regs);
+ if (!master_tile_ctl) {
+ dg1_master_intr_enable(regs);
+ return IRQ_NONE;
+ }
+
+ /* FIXME: we only support tile 0 for now. */
+ if (master_tile_ctl & DG1_MSTR_TILE(0)) {
+ master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
+ raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl);
+ } else {
+ DRM_ERROR("Tile not supported: 0x%08x\n", master_tile_ctl);
+ dg1_master_intr_enable(regs);
+ return IRQ_NONE;
+ }
+
+ gen11_gt_irq_handler(gt, master_ctl);
+
+ if (master_ctl & GEN11_DISPLAY_IRQ)
+ gen11_display_irq_handler(i915);
+
+ gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl);
+
+ dg1_master_intr_enable(regs);
+
+ gen11_gu_misc_irq_handler(gt, gu_misc_iir);
+
+ pmu_irq_stats(i915, IRQ_HANDLED);
+
+ return IRQ_HANDLED;
}
/* Called from drm generic code, passed 'crtc' which
@@ -2880,14 +2895,14 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
return true;
}
-int bdw_enable_vblank(struct drm_crtc *crtc)
+int bdw_enable_vblank(struct drm_crtc *_crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe;
+ struct intel_crtc *crtc = to_intel_crtc(_crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
unsigned long irqflags;
- if (gen11_dsi_configure_te(intel_crtc, true))
+ if (gen11_dsi_configure_te(crtc, true))
return 0;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
@@ -2898,7 +2913,7 @@ int bdw_enable_vblank(struct drm_crtc *crtc)
* PSR is active as no frames are generated, so check only for PSR.
*/
if (HAS_PSR(dev_priv))
- drm_crtc_vblank_restore(crtc);
+ drm_crtc_vblank_restore(&crtc->base);
return 0;
}
@@ -2952,14 +2967,14 @@ void ilk_disable_vblank(struct drm_crtc *crtc)
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
-void bdw_disable_vblank(struct drm_crtc *crtc)
+void bdw_disable_vblank(struct drm_crtc *_crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe;
+ struct intel_crtc *crtc = to_intel_crtc(_crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
unsigned long irqflags;
- if (gen11_dsi_configure_te(intel_crtc, false))
+ if (gen11_dsi_configure_te(crtc, false))
return;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
@@ -3146,10 +3161,20 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
- if (HAS_MASTER_UNIT_IRQ(dev_priv))
- dg1_master_intr_disable_and_ack(dev_priv->uncore.regs);
- else
- gen11_master_intr_disable(dev_priv->uncore.regs);
+ gen11_master_intr_disable(dev_priv->uncore.regs);
+
+ gen11_gt_irq_reset(&dev_priv->gt);
+ gen11_display_irq_reset(dev_priv);
+
+ GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_);
+ GEN3_IRQ_RESET(uncore, GEN8_PCU_);
+}
+
+static void dg1_irq_reset(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+
+ dg1_master_intr_disable(dev_priv->uncore.regs);
gen11_gt_irq_reset(&dev_priv->gt);
gen11_display_irq_reset(dev_priv);
@@ -3841,13 +3866,28 @@ static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
- if (HAS_MASTER_UNIT_IRQ(dev_priv)) {
- dg1_master_intr_enable(uncore->regs);
- intel_uncore_posting_read(&dev_priv->uncore, DG1_MSTR_UNIT_INTR);
- } else {
- gen11_master_intr_enable(uncore->regs);
- intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ);
+ gen11_master_intr_enable(uncore->regs);
+ intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ);
+}
+
+static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+ u32 gu_misc_masked = GEN11_GU_MISC_GSE;
+
+ gen11_gt_irq_postinstall(&dev_priv->gt);
+
+ GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
+
+ if (HAS_DISPLAY(dev_priv)) {
+ icp_irq_postinstall(dev_priv);
+ gen8_de_irq_postinstall(dev_priv);
+ intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
+ GEN11_DISPLAY_IRQ_ENABLE);
}
+
+ dg1_master_intr_enable(dev_priv->uncore.regs);
+ intel_uncore_posting_read(&dev_priv->uncore, DG1_MSTR_TILE_INTR);
}
static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
@@ -4386,9 +4426,9 @@ static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv)
else
return i8xx_irq_handler;
} else {
- if (HAS_MASTER_UNIT_IRQ(dev_priv))
+ if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
return dg1_irq_handler;
- if (GRAPHICS_VER(dev_priv) >= 11)
+ else if (GRAPHICS_VER(dev_priv) >= 11)
return gen11_irq_handler;
else if (GRAPHICS_VER(dev_priv) >= 8)
return gen8_irq_handler;
@@ -4411,7 +4451,9 @@ static void intel_irq_reset(struct drm_i915_private *dev_priv)
else
i8xx_irq_reset(dev_priv);
} else {
- if (GRAPHICS_VER(dev_priv) >= 11)
+ if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
+ dg1_irq_reset(dev_priv);
+ else if (GRAPHICS_VER(dev_priv) >= 11)
gen11_irq_reset(dev_priv);
else if (GRAPHICS_VER(dev_priv) >= 8)
gen8_irq_reset(dev_priv);
@@ -4434,7 +4476,9 @@ static void intel_irq_postinstall(struct drm_i915_private *dev_priv)
else
i8xx_irq_postinstall(dev_priv);
} else {
- if (GRAPHICS_VER(dev_priv) >= 11)
+ if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
+ dg1_irq_postinstall(dev_priv);
+ else if (GRAPHICS_VER(dev_priv) >= 11)
gen11_irq_postinstall(dev_priv);
else if (GRAPHICS_VER(dev_priv) >= 8)
gen8_irq_postinstall(dev_priv);
@@ -4466,14 +4510,14 @@ int intel_irq_install(struct drm_i915_private *dev_priv)
*/
dev_priv->runtime_pm.irqs_enabled = true;
- dev_priv->drm.irq_enabled = true;
+ dev_priv->irq_enabled = true;
intel_irq_reset(dev_priv);
ret = request_irq(irq, intel_irq_handler(dev_priv),
IRQF_SHARED, DRIVER_NAME, dev_priv);
if (ret < 0) {
- dev_priv->drm.irq_enabled = false;
+ dev_priv->irq_enabled = false;
return ret;
}
@@ -4499,10 +4543,10 @@ void intel_irq_uninstall(struct drm_i915_private *dev_priv)
* intel_modeset_driver_remove() calling us out of sequence.
* Would be nice if it didn't do that...
*/
- if (!dev_priv->drm.irq_enabled)
+ if (!dev_priv->irq_enabled)
return;
- dev_priv->drm.irq_enabled = false;
+ dev_priv->irq_enabled = false;
intel_irq_reset(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_module.c b/drivers/gpu/drm/i915/i915_module.c
new file mode 100644
index 000000000000..d8b4482c69d0
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_module.c
@@ -0,0 +1,124 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <linux/console.h>
+
+#include "gem/i915_gem_context.h"
+#include "gem/i915_gem_object.h"
+#include "i915_active.h"
+#include "i915_buddy.h"
+#include "i915_params.h"
+#include "i915_pci.h"
+#include "i915_perf.h"
+#include "i915_request.h"
+#include "i915_scheduler.h"
+#include "i915_selftest.h"
+#include "i915_vma.h"
+
+static int i915_check_nomodeset(void)
+{
+ bool use_kms = true;
+
+ /*
+ * Enable KMS by default, unless explicitly overriden by
+ * either the i915.modeset prarameter or by the
+ * vga_text_mode_force boot option.
+ */
+
+ if (i915_modparams.modeset == 0)
+ use_kms = false;
+
+ if (vgacon_text_force() && i915_modparams.modeset == -1)
+ use_kms = false;
+
+ if (!use_kms) {
+ /* Silently fail loading to not upset userspace. */
+ DRM_DEBUG_DRIVER("KMS disabled.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+static const struct {
+ int (*init)(void);
+ void (*exit)(void);
+} init_funcs[] = {
+ { .init = i915_check_nomodeset },
+ { .init = i915_active_module_init,
+ .exit = i915_active_module_exit },
+ { .init = i915_buddy_module_init,
+ .exit = i915_buddy_module_exit },
+ { .init = i915_context_module_init,
+ .exit = i915_context_module_exit },
+ { .init = i915_gem_context_module_init,
+ .exit = i915_gem_context_module_exit },
+ { .init = i915_objects_module_init,
+ .exit = i915_objects_module_exit },
+ { .init = i915_request_module_init,
+ .exit = i915_request_module_exit },
+ { .init = i915_scheduler_module_init,
+ .exit = i915_scheduler_module_exit },
+ { .init = i915_vma_module_init,
+ .exit = i915_vma_module_exit },
+ { .init = i915_mock_selftests },
+ { .init = i915_pmu_init,
+ .exit = i915_pmu_exit },
+ { .init = i915_register_pci_driver,
+ .exit = i915_unregister_pci_driver },
+ { .init = i915_perf_sysctl_register,
+ .exit = i915_perf_sysctl_unregister },
+};
+static int init_progress;
+
+static int __init i915_init(void)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(init_funcs); i++) {
+ err = init_funcs[i].init();
+ if (err < 0) {
+ while (i--) {
+ if (init_funcs[i].exit)
+ init_funcs[i].exit();
+ }
+ return err;
+ } else if (err > 0) {
+ /*
+ * Early-exit success is reserved for things which
+ * don't have an exit() function because we have no
+ * idea how far they got or how to partially tear
+ * them down.
+ */
+ WARN_ON(init_funcs[i].exit);
+ break;
+ }
+ }
+
+ init_progress = i;
+
+ return 0;
+}
+
+static void __exit i915_exit(void)
+{
+ int i;
+
+ for (i = init_progress - 1; i >= 0; i--) {
+ GEM_BUG_ON(i >= ARRAY_SIZE(init_funcs));
+ if (init_funcs[i].exit)
+ init_funcs[i].exit();
+ }
+}
+
+module_init(i915_init);
+module_exit(i915_exit);
+
+MODULE_AUTHOR("Tungsten Graphics, Inc.");
+MODULE_AUTHOR("Intel Corporation");
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 2880ec57c97d..1bbd09ad5287 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -22,18 +22,13 @@
*
*/
-#include <linux/console.h>
#include <linux/vga_switcheroo.h>
#include <drm/drm_drv.h>
#include <drm/i915_pciids.h>
-#include "display/intel_fbdev.h"
-
#include "i915_drv.h"
-#include "i915_perf.h"
-#include "i915_globals.h"
-#include "i915_selftest.h"
+#include "i915_pci.h"
#define PLATFORM(x) .platform = (x)
#define GEN(x) \
@@ -787,27 +782,13 @@ static const struct intel_device_info cml_gt2_info = {
.gt = 2,
};
-#define GEN10_FEATURES \
- GEN9_FEATURES, \
- GEN(10), \
- .dbuf.size = 1024 - 4, /* 4 blocks for bypass path allocation */ \
- .display.has_dsc = 1, \
- .has_coherent_ggtt = false, \
- GLK_COLORS
-
-static const struct intel_device_info cnl_info = {
- GEN10_FEATURES,
- PLATFORM(INTEL_CANNONLAKE),
- .gt = 2,
-};
-
#define GEN11_DEFAULT_PAGE_SIZES \
.page_sizes = I915_GTT_PAGE_SIZE_4K | \
I915_GTT_PAGE_SIZE_64K | \
I915_GTT_PAGE_SIZE_2M
#define GEN11_FEATURES \
- GEN10_FEATURES, \
+ GEN9_FEATURES, \
GEN11_DEFAULT_PAGE_SIZES, \
.abox_mask = BIT(0), \
.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
@@ -830,10 +811,12 @@ static const struct intel_device_info cnl_info = {
[TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
}, \
GEN(11), \
+ .color = { .degamma_lut_size = 33, .gamma_lut_size = 262145 }, \
.dbuf.size = 2048, \
.dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2), \
- .has_logical_ring_elsq = 1, \
- .color = { .degamma_lut_size = 33, .gamma_lut_size = 262145 }
+ .display.has_dsc = 1, \
+ .has_coherent_ggtt = false, \
+ .has_logical_ring_elsq = 1
static const struct intel_device_info icl_info = {
GEN11_FEATURES,
@@ -845,7 +828,6 @@ static const struct intel_device_info icl_info = {
static const struct intel_device_info ehl_info = {
GEN11_FEATURES,
PLATFORM(INTEL_ELKHARTLAKE),
- .require_force_probe = 1,
.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0),
.ppgtt_size = 36,
};
@@ -853,7 +835,6 @@ static const struct intel_device_info ehl_info = {
static const struct intel_device_info jsl_info = {
GEN11_FEATURES,
PLATFORM(INTEL_JASPERLAKE),
- .require_force_probe = 1,
.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0),
.ppgtt_size = 36,
};
@@ -909,7 +890,6 @@ static const struct intel_device_info rkl_info = {
#define DGFX_FEATURES \
.memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \
- .has_master_unit_irq = 1, \
.has_llc = 0, \
.has_snoop = 1, \
.is_dgfx = 1
@@ -917,6 +897,7 @@ static const struct intel_device_info rkl_info = {
static const struct intel_device_info dg1_info __maybe_unused = {
GEN12_FEATURES,
DGFX_FEATURES,
+ .graphics_rel = 10,
PLATFORM(INTEL_DG1),
.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
.require_force_probe = 1,
@@ -936,26 +917,60 @@ static const struct intel_device_info adl_s_info = {
.display.has_psr_hw_tracking = 0,
.platform_engine_mask =
BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2),
- .dma_mask_size = 46,
+ .dma_mask_size = 39,
};
+#define XE_LPD_CURSOR_OFFSETS \
+ .cursor_offsets = { \
+ [PIPE_A] = CURSOR_A_OFFSET, \
+ [PIPE_B] = IVB_CURSOR_B_OFFSET, \
+ [PIPE_C] = IVB_CURSOR_C_OFFSET, \
+ [PIPE_D] = TGL_CURSOR_D_OFFSET, \
+ }
+
#define XE_LPD_FEATURES \
- .display.ver = 13, \
- .display.has_psr_hw_tracking = 0, \
- .abox_mask = GENMASK(1, 0), \
- .pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
- .cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
- BIT(TRANSCODER_C) | BIT(TRANSCODER_D), \
- .dbuf.size = 4096, \
- .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | BIT(DBUF_S4)
+ .abox_mask = GENMASK(1, 0), \
+ .color = { .degamma_lut_size = 0, .gamma_lut_size = 0 }, \
+ .cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_D), \
+ .dbuf.size = 4096, \
+ .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | \
+ BIT(DBUF_S4), \
+ .display.has_ddi = 1, \
+ .display.has_dmc = 1, \
+ .display.has_dp_mst = 1, \
+ .display.has_dsb = 1, \
+ .display.has_dsc = 1, \
+ .display.has_fbc = 1, \
+ .display.has_fpga_dbg = 1, \
+ .display.has_hdcp = 1, \
+ .display.has_hotplug = 1, \
+ .display.has_ipc = 1, \
+ .display.has_psr = 1, \
+ .display.ver = 13, \
+ .pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ [TRANSCODER_B] = PIPE_B_OFFSET, \
+ [TRANSCODER_C] = PIPE_C_OFFSET, \
+ [TRANSCODER_D] = PIPE_D_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
+ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
+ [TRANSCODER_D] = TRANSCODER_D_OFFSET, \
+ }, \
+ XE_LPD_CURSOR_OFFSETS
static const struct intel_device_info adl_p_info = {
GEN12_FEATURES,
XE_LPD_FEATURES,
PLATFORM(INTEL_ALDERLAKE_P),
- .has_cdclk_crawl = 1,
.require_force_probe = 1,
+ .display.has_cdclk_crawl = 1,
.display.has_modular_fia = 1,
+ .display.has_psr_hw_tracking = 0,
.platform_engine_mask =
BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2),
.ppgtt_size = 48,
@@ -963,6 +978,67 @@ static const struct intel_device_info adl_p_info = {
};
#undef GEN
+
+#define XE_HP_PAGE_SIZES \
+ .page_sizes = I915_GTT_PAGE_SIZE_4K | \
+ I915_GTT_PAGE_SIZE_64K | \
+ I915_GTT_PAGE_SIZE_2M
+
+#define XE_HP_FEATURES \
+ .graphics_ver = 12, \
+ .graphics_rel = 50, \
+ XE_HP_PAGE_SIZES, \
+ .dma_mask_size = 46, \
+ .has_64bit_reloc = 1, \
+ .has_global_mocs = 1, \
+ .has_gt_uc = 1, \
+ .has_llc = 1, \
+ .has_logical_ring_contexts = 1, \
+ .has_logical_ring_elsq = 1, \
+ .has_mslices = 1, \
+ .has_rc6 = 1, \
+ .has_reset_engine = 1, \
+ .has_rps = 1, \
+ .has_runtime_pm = 1, \
+ .ppgtt_size = 48, \
+ .ppgtt_type = INTEL_PPGTT_FULL
+
+#define XE_HPM_FEATURES \
+ .media_ver = 12, \
+ .media_rel = 50
+
+__maybe_unused
+static const struct intel_device_info xehpsdv_info = {
+ XE_HP_FEATURES,
+ XE_HPM_FEATURES,
+ DGFX_FEATURES,
+ PLATFORM(INTEL_XEHPSDV),
+ .display = { },
+ .pipe_mask = 0,
+ .platform_engine_mask =
+ BIT(RCS0) | BIT(BCS0) |
+ BIT(VECS0) | BIT(VECS1) | BIT(VECS2) | BIT(VECS3) |
+ BIT(VCS0) | BIT(VCS1) | BIT(VCS2) | BIT(VCS3) |
+ BIT(VCS4) | BIT(VCS5) | BIT(VCS6) | BIT(VCS7),
+ .require_force_probe = 1,
+};
+
+__maybe_unused
+static const struct intel_device_info dg2_info = {
+ XE_HP_FEATURES,
+ XE_HPM_FEATURES,
+ XE_LPD_FEATURES,
+ DGFX_FEATURES,
+ .graphics_rel = 55,
+ .media_rel = 55,
+ PLATFORM(INTEL_DG2),
+ .platform_engine_mask =
+ BIT(RCS0) | BIT(BCS0) |
+ BIT(VECS0) | BIT(VECS1) |
+ BIT(VCS0) | BIT(VCS2),
+ .require_force_probe = 1,
+};
+
#undef PLATFORM
/*
@@ -1032,7 +1108,6 @@ static const struct pci_device_id pciidlist[] = {
INTEL_CML_GT2_IDS(&cml_gt2_info),
INTEL_CML_U_GT1_IDS(&cml_gt1_info),
INTEL_CML_U_GT2_IDS(&cml_gt2_info),
- INTEL_CNL_IDS(&cnl_info),
INTEL_ICL_11_IDS(&icl_info),
INTEL_EHL_IDS(&ehl_info),
INTEL_JSL_IDS(&jsl_info),
@@ -1159,66 +1234,12 @@ static struct pci_driver i915_pci_driver = {
.driver.pm = &i915_pm_ops,
};
-static int __init i915_init(void)
+int i915_register_pci_driver(void)
{
- bool use_kms = true;
- int err;
-
- err = i915_globals_init();
- if (err)
- return err;
-
- err = i915_mock_selftests();
- if (err)
- return err > 0 ? 0 : err;
-
- /*
- * Enable KMS by default, unless explicitly overriden by
- * either the i915.modeset prarameter or by the
- * vga_text_mode_force boot option.
- */
-
- if (i915_modparams.modeset == 0)
- use_kms = false;
-
- if (vgacon_text_force() && i915_modparams.modeset == -1)
- use_kms = false;
-
- if (!use_kms) {
- /* Silently fail loading to not upset userspace. */
- DRM_DEBUG_DRIVER("KMS disabled.\n");
- return 0;
- }
-
- i915_pmu_init();
-
- err = pci_register_driver(&i915_pci_driver);
- if (err) {
- i915_pmu_exit();
- i915_globals_exit();
- return err;
- }
-
- i915_perf_sysctl_register();
- return 0;
+ return pci_register_driver(&i915_pci_driver);
}
-static void __exit i915_exit(void)
+void i915_unregister_pci_driver(void)
{
- if (!i915_pci_driver.driver.owner)
- return;
-
- i915_perf_sysctl_unregister();
pci_unregister_driver(&i915_pci_driver);
- i915_globals_exit();
- i915_pmu_exit();
}
-
-module_init(i915_init);
-module_exit(i915_exit);
-
-MODULE_AUTHOR("Tungsten Graphics, Inc.");
-MODULE_AUTHOR("Intel Corporation");
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/i915/i915_pci.h b/drivers/gpu/drm/i915/i915_pci.h
new file mode 100644
index 000000000000..b386f319f52e
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_pci.h
@@ -0,0 +1,8 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2021 Intel Corporation
+ */
+
+int i915_register_pci_driver(void);
+void i915_unregister_pci_driver(void);
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 9f94914958c3..2f01b8c0284c 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -1256,7 +1256,6 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
case 8:
case 9:
- case 10:
if (intel_engine_uses_guc(ce->engine)) {
/*
* When using GuC, the context descriptor we write in
@@ -1284,17 +1283,26 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
break;
case 11:
- case 12: {
- stream->specific_ctx_id_mask =
- ((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
- /*
- * Pick an unused context id
- * 0 - BITS_PER_LONG are used by other contexts
- * GEN12_MAX_CONTEXT_HW_ID (0x7ff) is used by idle context
- */
- stream->specific_ctx_id = (GEN12_MAX_CONTEXT_HW_ID - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
+ case 12:
+ if (GRAPHICS_VER_FULL(ce->engine->i915) >= IP_VER(12, 50)) {
+ stream->specific_ctx_id_mask =
+ ((1U << XEHP_SW_CTX_ID_WIDTH) - 1) <<
+ (XEHP_SW_CTX_ID_SHIFT - 32);
+ stream->specific_ctx_id =
+ (XEHP_MAX_CONTEXT_HW_ID - 1) <<
+ (XEHP_SW_CTX_ID_SHIFT - 32);
+ } else {
+ stream->specific_ctx_id_mask =
+ ((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
+ /*
+ * Pick an unused context id
+ * 0 - BITS_PER_LONG are used by other contexts
+ * GEN12_MAX_CONTEXT_HW_ID (0x7ff) is used by idle context
+ */
+ stream->specific_ctx_id =
+ (GEN12_MAX_CONTEXT_HW_ID - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
+ }
break;
- }
default:
MISSING_CASE(GRAPHICS_VER(ce->engine->i915));
@@ -2580,7 +2588,7 @@ static void gen8_disable_metric_set(struct i915_perf_stream *stream)
intel_uncore_rmw(uncore, GDT_CHICKEN_BITS, GT_NOA_ENABLE, 0);
}
-static void gen10_disable_metric_set(struct i915_perf_stream *stream)
+static void gen11_disable_metric_set(struct i915_perf_stream *stream)
{
struct intel_uncore *uncore = stream->uncore;
@@ -3414,10 +3422,10 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf,
struct drm_i915_file_private *file_priv = file->driver_priv;
specific_ctx = i915_gem_context_lookup(file_priv, ctx_handle);
- if (!specific_ctx) {
+ if (IS_ERR(specific_ctx)) {
DRM_DEBUG("Failed to look up context with ID %u for opening perf stream\n",
ctx_handle);
- ret = -ENOENT;
+ ret = PTR_ERR(specific_ctx);
goto err;
}
}
@@ -3887,7 +3895,7 @@ static bool gen8_is_valid_mux_addr(struct i915_perf *perf, u32 addr)
REG_IN_RANGE(addr, RPM_CONFIG0, NOA_CONFIG(8));
}
-static bool gen10_is_valid_mux_addr(struct i915_perf *perf, u32 addr)
+static bool gen11_is_valid_mux_addr(struct i915_perf *perf, u32 addr)
{
return gen8_is_valid_mux_addr(perf, addr) ||
REG_EQUAL(addr, GEN10_NOA_WRITE_HIGH) ||
@@ -4310,7 +4318,6 @@ static void oa_init_supported_formats(struct i915_perf *perf)
case INTEL_GEMINILAKE:
case INTEL_COFFEELAKE:
case INTEL_COMETLAKE:
- case INTEL_CANNONLAKE:
case INTEL_ICELAKE:
case INTEL_ELKHARTLAKE:
case INTEL_JASPERLAKE:
@@ -4395,27 +4402,23 @@ void i915_perf_init(struct drm_i915_private *i915)
perf->gen8_valid_ctx_bit = BIT(16);
}
- } else if (IS_GRAPHICS_VER(i915, 10, 11)) {
+ } else if (GRAPHICS_VER(i915) == 11) {
perf->ops.is_valid_b_counter_reg =
gen7_is_valid_b_counter_addr;
perf->ops.is_valid_mux_reg =
- gen10_is_valid_mux_addr;
+ gen11_is_valid_mux_addr;
perf->ops.is_valid_flex_reg =
gen8_is_valid_flex_addr;
perf->ops.oa_enable = gen8_oa_enable;
perf->ops.oa_disable = gen8_oa_disable;
perf->ops.enable_metric_set = gen8_enable_metric_set;
- perf->ops.disable_metric_set = gen10_disable_metric_set;
+ perf->ops.disable_metric_set = gen11_disable_metric_set;
perf->ops.oa_hw_tail_read = gen8_oa_hw_tail_read;
- if (GRAPHICS_VER(i915) == 10) {
- perf->ctx_oactxctrl_offset = 0x128;
- perf->ctx_flexeu0_offset = 0x3de;
- } else {
- perf->ctx_oactxctrl_offset = 0x124;
- perf->ctx_flexeu0_offset = 0x78e;
- }
+ perf->ctx_oactxctrl_offset = 0x124;
+ perf->ctx_flexeu0_offset = 0x78e;
+
perf->gen8_valid_ctx_bit = BIT(16);
} else if (GRAPHICS_VER(i915) == 12) {
perf->ops.is_valid_b_counter_reg =
@@ -4483,9 +4486,10 @@ static int destroy_config(int id, void *p, void *data)
return 0;
}
-void i915_perf_sysctl_register(void)
+int i915_perf_sysctl_register(void)
{
sysctl_header = register_sysctl_table(dev_root);
+ return 0;
}
void i915_perf_sysctl_unregister(void)
diff --git a/drivers/gpu/drm/i915/i915_perf.h b/drivers/gpu/drm/i915/i915_perf.h
index 882fdd0a7680..1d1329e5af3a 100644
--- a/drivers/gpu/drm/i915/i915_perf.h
+++ b/drivers/gpu/drm/i915/i915_perf.h
@@ -23,7 +23,7 @@ void i915_perf_fini(struct drm_i915_private *i915);
void i915_perf_register(struct drm_i915_private *i915);
void i915_perf_unregister(struct drm_i915_private *i915);
int i915_perf_ioctl_version(void);
-void i915_perf_sysctl_register(void);
+int i915_perf_sysctl_register(void);
void i915_perf_sysctl_unregister(void);
int i915_perf_open_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index 34d37d46a126..0b488d49694c 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -407,7 +407,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) {
add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
- intel_gpu_freq(rps, rps->cur_freq),
+ intel_rps_get_requested_frequency(rps),
period_ns / 1000);
}
@@ -1088,7 +1088,7 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
-void i915_pmu_init(void)
+int i915_pmu_init(void)
{
int ret;
@@ -1101,6 +1101,8 @@ void i915_pmu_init(void)
ret);
else
cpuhp_slot = ret;
+
+ return 0;
}
void i915_pmu_exit(void)
diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h
index 60f9595f902c..449057648f39 100644
--- a/drivers/gpu/drm/i915/i915_pmu.h
+++ b/drivers/gpu/drm/i915/i915_pmu.h
@@ -147,14 +147,14 @@ struct i915_pmu {
};
#ifdef CONFIG_PERF_EVENTS
-void i915_pmu_init(void);
+int i915_pmu_init(void);
void i915_pmu_exit(void);
void i915_pmu_register(struct drm_i915_private *i915);
void i915_pmu_unregister(struct drm_i915_private *i915);
void i915_pmu_gt_parked(struct drm_i915_private *i915);
void i915_pmu_gt_unparked(struct drm_i915_private *i915);
#else
-static inline void i915_pmu_init(void) {}
+static inline int i915_pmu_init(void) { return 0; }
static inline void i915_pmu_exit(void) {}
static inline void i915_pmu_register(struct drm_i915_private *i915) {}
static inline void i915_pmu_unregister(struct drm_i915_private *i915) {}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 476bb3b9ad11..664970f2bc62 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -395,10 +395,18 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define GEN11_GRDOM_MEDIA2 (1 << 6)
#define GEN11_GRDOM_MEDIA3 (1 << 7)
#define GEN11_GRDOM_MEDIA4 (1 << 8)
+#define GEN11_GRDOM_MEDIA5 (1 << 9)
+#define GEN11_GRDOM_MEDIA6 (1 << 10)
+#define GEN11_GRDOM_MEDIA7 (1 << 11)
+#define GEN11_GRDOM_MEDIA8 (1 << 12)
#define GEN11_GRDOM_VECS (1 << 13)
#define GEN11_GRDOM_VECS2 (1 << 14)
+#define GEN11_GRDOM_VECS3 (1 << 15)
+#define GEN11_GRDOM_VECS4 (1 << 16)
#define GEN11_GRDOM_SFC0 (1 << 17)
#define GEN11_GRDOM_SFC1 (1 << 18)
+#define GEN11_GRDOM_SFC2 (1 << 19)
+#define GEN11_GRDOM_SFC3 (1 << 20)
#define GEN11_VCS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << ((instance) >> 1))
#define GEN11_VECS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << (instance))
@@ -1877,7 +1885,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC)
/*
- * CNL/ICL Port/COMBO-PHY Registers
+ * ICL Port/COMBO-PHY Registers
*/
#define _ICL_COMBOPHY_A 0x162000
#define _ICL_COMBOPHY_B 0x6C000
@@ -1891,11 +1899,10 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
_RKL_COMBOPHY_D, \
_ADL_COMBOPHY_E)
-/* CNL/ICL Port CL_DW registers */
+/* ICL Port CL_DW registers */
#define _ICL_PORT_CL_DW(dw, phy) (_ICL_COMBOPHY(phy) + \
4 * (dw))
-#define CNL_PORT_CL1CM_DW5 _MMIO(0x162014)
#define ICL_PORT_CL_DW5(phy) _MMIO(_ICL_PORT_CL_DW(5, phy))
#define CL_POWER_DOWN_ENABLE (1 << 4)
#define SUS_CLOCK_CONFIG (3 << 0)
@@ -1920,19 +1927,16 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define ICL_PORT_CL_DW12(phy) _MMIO(_ICL_PORT_CL_DW(12, phy))
#define ICL_LANE_ENABLE_AUX (1 << 0)
-/* CNL/ICL Port COMP_DW registers */
+/* ICL Port COMP_DW registers */
#define _ICL_PORT_COMP 0x100
#define _ICL_PORT_COMP_DW(dw, phy) (_ICL_COMBOPHY(phy) + \
_ICL_PORT_COMP + 4 * (dw))
-#define CNL_PORT_COMP_DW0 _MMIO(0x162100)
#define ICL_PORT_COMP_DW0(phy) _MMIO(_ICL_PORT_COMP_DW(0, phy))
#define COMP_INIT (1 << 31)
-#define CNL_PORT_COMP_DW1 _MMIO(0x162104)
#define ICL_PORT_COMP_DW1(phy) _MMIO(_ICL_PORT_COMP_DW(1, phy))
-#define CNL_PORT_COMP_DW3 _MMIO(0x16210c)
#define ICL_PORT_COMP_DW3(phy) _MMIO(_ICL_PORT_COMP_DW(3, phy))
#define PROCESS_INFO_DOT_0 (0 << 26)
#define PROCESS_INFO_DOT_1 (1 << 26)
@@ -1948,38 +1952,11 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define ICL_PORT_COMP_DW8(phy) _MMIO(_ICL_PORT_COMP_DW(8, phy))
#define IREFGEN (1 << 24)
-#define CNL_PORT_COMP_DW9 _MMIO(0x162124)
#define ICL_PORT_COMP_DW9(phy) _MMIO(_ICL_PORT_COMP_DW(9, phy))
-#define CNL_PORT_COMP_DW10 _MMIO(0x162128)
#define ICL_PORT_COMP_DW10(phy) _MMIO(_ICL_PORT_COMP_DW(10, phy))
-/* CNL/ICL Port PCS registers */
-#define _CNL_PORT_PCS_DW1_GRP_AE 0x162304
-#define _CNL_PORT_PCS_DW1_GRP_B 0x162384
-#define _CNL_PORT_PCS_DW1_GRP_C 0x162B04
-#define _CNL_PORT_PCS_DW1_GRP_D 0x162B84
-#define _CNL_PORT_PCS_DW1_GRP_F 0x162A04
-#define _CNL_PORT_PCS_DW1_LN0_AE 0x162404
-#define _CNL_PORT_PCS_DW1_LN0_B 0x162604
-#define _CNL_PORT_PCS_DW1_LN0_C 0x162C04
-#define _CNL_PORT_PCS_DW1_LN0_D 0x162E04
-#define _CNL_PORT_PCS_DW1_LN0_F 0x162804
-#define CNL_PORT_PCS_DW1_GRP(phy) _MMIO(_PICK(phy, \
- _CNL_PORT_PCS_DW1_GRP_AE, \
- _CNL_PORT_PCS_DW1_GRP_B, \
- _CNL_PORT_PCS_DW1_GRP_C, \
- _CNL_PORT_PCS_DW1_GRP_D, \
- _CNL_PORT_PCS_DW1_GRP_AE, \
- _CNL_PORT_PCS_DW1_GRP_F))
-#define CNL_PORT_PCS_DW1_LN0(phy) _MMIO(_PICK(phy, \
- _CNL_PORT_PCS_DW1_LN0_AE, \
- _CNL_PORT_PCS_DW1_LN0_B, \
- _CNL_PORT_PCS_DW1_LN0_C, \
- _CNL_PORT_PCS_DW1_LN0_D, \
- _CNL_PORT_PCS_DW1_LN0_AE, \
- _CNL_PORT_PCS_DW1_LN0_F))
-
+/* ICL Port PCS registers */
#define _ICL_PORT_PCS_AUX 0x300
#define _ICL_PORT_PCS_GRP 0x600
#define _ICL_PORT_PCS_LN(ln) (0x800 + (ln) * 0x100)
@@ -1998,34 +1975,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define LATENCY_OPTIM_MASK (0x3 << 2)
#define LATENCY_OPTIM_VAL(x) ((x) << 2)
-/* CNL/ICL Port TX registers */
-#define _CNL_PORT_TX_AE_GRP_OFFSET 0x162340
-#define _CNL_PORT_TX_B_GRP_OFFSET 0x1623C0
-#define _CNL_PORT_TX_C_GRP_OFFSET 0x162B40
-#define _CNL_PORT_TX_D_GRP_OFFSET 0x162BC0
-#define _CNL_PORT_TX_F_GRP_OFFSET 0x162A40
-#define _CNL_PORT_TX_AE_LN0_OFFSET 0x162440
-#define _CNL_PORT_TX_B_LN0_OFFSET 0x162640
-#define _CNL_PORT_TX_C_LN0_OFFSET 0x162C40
-#define _CNL_PORT_TX_D_LN0_OFFSET 0x162E40
-#define _CNL_PORT_TX_F_LN0_OFFSET 0x162840
-#define _CNL_PORT_TX_DW_GRP(dw, port) (_PICK((port), \
- _CNL_PORT_TX_AE_GRP_OFFSET, \
- _CNL_PORT_TX_B_GRP_OFFSET, \
- _CNL_PORT_TX_B_GRP_OFFSET, \
- _CNL_PORT_TX_D_GRP_OFFSET, \
- _CNL_PORT_TX_AE_GRP_OFFSET, \
- _CNL_PORT_TX_F_GRP_OFFSET) + \
- 4 * (dw))
-#define _CNL_PORT_TX_DW_LN0(dw, port) (_PICK((port), \
- _CNL_PORT_TX_AE_LN0_OFFSET, \
- _CNL_PORT_TX_B_LN0_OFFSET, \
- _CNL_PORT_TX_B_LN0_OFFSET, \
- _CNL_PORT_TX_D_LN0_OFFSET, \
- _CNL_PORT_TX_AE_LN0_OFFSET, \
- _CNL_PORT_TX_F_LN0_OFFSET) + \
- 4 * (dw))
-
+/* ICL Port TX registers */
#define _ICL_PORT_TX_AUX 0x380
#define _ICL_PORT_TX_GRP 0x680
#define _ICL_PORT_TX_LN(ln) (0x880 + (ln) * 0x100)
@@ -2037,8 +1987,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define _ICL_PORT_TX_DW_LN(dw, ln, phy) (_ICL_COMBOPHY(phy) + \
_ICL_PORT_TX_LN(ln) + 4 * (dw))
-#define CNL_PORT_TX_DW2_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(2, port))
-#define CNL_PORT_TX_DW2_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(2, port))
#define ICL_PORT_TX_DW2_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(2, phy))
#define ICL_PORT_TX_DW2_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(2, phy))
#define ICL_PORT_TX_DW2_LN0(phy) _MMIO(_ICL_PORT_TX_DW_LN(2, 0, phy))
@@ -2051,13 +1999,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define RCOMP_SCALAR(x) ((x) << 0)
#define RCOMP_SCALAR_MASK (0xFF << 0)
-#define _CNL_PORT_TX_DW4_LN0_AE 0x162450
-#define _CNL_PORT_TX_DW4_LN1_AE 0x1624D0
-#define CNL_PORT_TX_DW4_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(4, (port)))
-#define CNL_PORT_TX_DW4_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)))
-#define CNL_PORT_TX_DW4_LN(ln, port) _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \
- ((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \
- _CNL_PORT_TX_DW4_LN0_AE)))
#define ICL_PORT_TX_DW4_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(4, phy))
#define ICL_PORT_TX_DW4_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(4, phy))
#define ICL_PORT_TX_DW4_LN0(phy) _MMIO(_ICL_PORT_TX_DW_LN(4, 0, phy))
@@ -2070,8 +2011,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define CURSOR_COEFF(x) ((x) << 0)
#define CURSOR_COEFF_MASK (0x3F << 0)
-#define CNL_PORT_TX_DW5_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(5, port))
-#define CNL_PORT_TX_DW5_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(5, port))
#define ICL_PORT_TX_DW5_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(5, phy))
#define ICL_PORT_TX_DW5_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(5, phy))
#define ICL_PORT_TX_DW5_LN0(phy) _MMIO(_ICL_PORT_TX_DW_LN(5, 0, phy))
@@ -2083,8 +2022,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define RTERM_SELECT(x) ((x) << 3)
#define RTERM_SELECT_MASK (0x7 << 3)
-#define CNL_PORT_TX_DW7_GRP(port) _MMIO(_CNL_PORT_TX_DW_GRP(7, (port)))
-#define CNL_PORT_TX_DW7_LN0(port) _MMIO(_CNL_PORT_TX_DW_LN0(7, (port)))
#define ICL_PORT_TX_DW7_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(7, phy))
#define ICL_PORT_TX_DW7_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(7, phy))
#define ICL_PORT_TX_DW7_LN0(phy) _MMIO(_ICL_PORT_TX_DW_LN(7, 0, phy))
@@ -2278,6 +2215,68 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define MG_DP_MODE_CFG_DP_X2_MODE (1 << 7)
#define MG_DP_MODE_CFG_DP_X1_MODE (1 << 6)
+/*
+ * DG2 SNPS PHY registers (TC1 = PHY_E)
+ */
+#define _SNPS_PHY_A_BASE 0x168000
+#define _SNPS_PHY_B_BASE 0x169000
+#define _SNPS_PHY(phy) _PHY(phy, \
+ _SNPS_PHY_A_BASE, \
+ _SNPS_PHY_B_BASE)
+#define _SNPS2(phy, reg) (_SNPS_PHY(phy) - \
+ _SNPS_PHY_A_BASE + (reg))
+#define _MMIO_SNPS(phy, reg) _MMIO(_SNPS2(phy, reg))
+#define _MMIO_SNPS_LN(ln, phy, reg) _MMIO(_SNPS2(phy, \
+ (reg) + (ln) * 0x10))
+
+#define SNPS_PHY_MPLLB_CP(phy) _MMIO_SNPS(phy, 0x168000)
+#define SNPS_PHY_MPLLB_CP_INT REG_GENMASK(31, 25)
+#define SNPS_PHY_MPLLB_CP_INT_GS REG_GENMASK(23, 17)
+#define SNPS_PHY_MPLLB_CP_PROP REG_GENMASK(15, 9)
+#define SNPS_PHY_MPLLB_CP_PROP_GS REG_GENMASK(7, 1)
+
+#define SNPS_PHY_MPLLB_DIV(phy) _MMIO_SNPS(phy, 0x168004)
+#define SNPS_PHY_MPLLB_FORCE_EN REG_BIT(31)
+#define SNPS_PHY_MPLLB_DIV5_CLK_EN REG_BIT(29)
+#define SNPS_PHY_MPLLB_V2I REG_GENMASK(27, 26)
+#define SNPS_PHY_MPLLB_FREQ_VCO REG_GENMASK(25, 24)
+#define SNPS_PHY_MPLLB_PMIX_EN REG_BIT(10)
+#define SNPS_PHY_MPLLB_TX_CLK_DIV REG_GENMASK(7, 5)
+
+#define SNPS_PHY_MPLLB_FRACN1(phy) _MMIO_SNPS(phy, 0x168008)
+#define SNPS_PHY_MPLLB_FRACN_EN REG_BIT(31)
+#define SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN REG_BIT(30)
+#define SNPS_PHY_MPLLB_FRACN_DEN REG_GENMASK(15, 0)
+
+#define SNPS_PHY_MPLLB_FRACN2(phy) _MMIO_SNPS(phy, 0x16800C)
+#define SNPS_PHY_MPLLB_FRACN_REM REG_GENMASK(31, 16)
+#define SNPS_PHY_MPLLB_FRACN_QUOT REG_GENMASK(15, 0)
+
+#define SNPS_PHY_MPLLB_SSCEN(phy) _MMIO_SNPS(phy, 0x168014)
+#define SNPS_PHY_MPLLB_SSC_EN REG_BIT(31)
+#define SNPS_PHY_MPLLB_SSC_UP_SPREAD REG_BIT(30)
+#define SNPS_PHY_MPLLB_SSC_PEAK REG_GENMASK(29, 10)
+
+#define SNPS_PHY_MPLLB_SSCSTEP(phy) _MMIO_SNPS(phy, 0x168018)
+#define SNPS_PHY_MPLLB_SSC_STEPSIZE REG_GENMASK(31, 11)
+
+#define SNPS_PHY_MPLLB_DIV2(phy) _MMIO_SNPS(phy, 0x16801C)
+#define SNPS_PHY_MPLLB_HDMI_PIXEL_CLK_DIV REG_GENMASK(19, 18)
+#define SNPS_PHY_MPLLB_HDMI_DIV REG_GENMASK(17, 15)
+#define SNPS_PHY_MPLLB_REF_CLK_DIV REG_GENMASK(14, 12)
+#define SNPS_PHY_MPLLB_MULTIPLIER REG_GENMASK(11, 0)
+
+#define SNPS_PHY_REF_CONTROL(phy) _MMIO_SNPS(phy, 0x168188)
+#define SNPS_PHY_REF_CONTROL_REF_RANGE REG_GENMASK(31, 27)
+
+#define SNPS_PHY_TX_REQ(phy) _MMIO_SNPS(phy, 0x168200)
+#define SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR REG_GENMASK(31, 30)
+
+#define SNPS_PHY_TX_EQ(ln, phy) _MMIO_SNPS_LN(ln, phy, 0x168300)
+#define SNPS_PHY_TX_EQ_MAIN REG_GENMASK(23, 18)
+#define SNPS_PHY_TX_EQ_POST REG_GENMASK(15, 10)
+#define SNPS_PHY_TX_EQ_PRE REG_GENMASK(7, 2)
+
/* The spec defines this only for BXT PHY0, but lets assume that this
* would exist for PHY1 too if it had a second channel.
*/
@@ -2516,9 +2515,15 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define GEN11_BSD2_RING_BASE 0x1c4000
#define GEN11_BSD3_RING_BASE 0x1d0000
#define GEN11_BSD4_RING_BASE 0x1d4000
+#define XEHP_BSD5_RING_BASE 0x1e0000
+#define XEHP_BSD6_RING_BASE 0x1e4000
+#define XEHP_BSD7_RING_BASE 0x1f0000
+#define XEHP_BSD8_RING_BASE 0x1f4000
#define VEBOX_RING_BASE 0x1a000
#define GEN11_VEBOX_RING_BASE 0x1c8000
#define GEN11_VEBOX2_RING_BASE 0x1d8000
+#define XEHP_VEBOX3_RING_BASE 0x1e8000
+#define XEHP_VEBOX4_RING_BASE 0x1f8000
#define BLT_RING_BASE 0x22000
#define RING_TAIL(base) _MMIO((base) + 0x30)
#define RING_HEAD(base) _MMIO((base) + 0x34)
@@ -2572,7 +2577,16 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define ARB_MODE_BWGTLB_DISABLE (1 << 9)
#define ARB_MODE_SWIZZLE_BDW (1 << 1)
#define RENDER_HWS_PGA_GEN7 _MMIO(0x04080)
-#define RING_FAULT_REG(engine) _MMIO(0x4094 + 0x100 * (engine)->hw_id)
+
+#define _RING_FAULT_REG_RCS 0x4094
+#define _RING_FAULT_REG_VCS 0x4194
+#define _RING_FAULT_REG_BCS 0x4294
+#define _RING_FAULT_REG_VECS 0x4394
+#define RING_FAULT_REG(engine) _MMIO(_PICK((engine)->class, \
+ _RING_FAULT_REG_RCS, \
+ _RING_FAULT_REG_VCS, \
+ _RING_FAULT_REG_VECS, \
+ _RING_FAULT_REG_BCS))
#define GEN8_RING_FAULT_REG _MMIO(0x4094)
#define GEN12_RING_FAULT_REG _MMIO(0xcec4)
#define GEN8_RING_FAULT_ENGINE_ID(x) (((x) >> 12) & 0x7)
@@ -2672,6 +2686,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define GEN12_SC_INSTDONE_EXTRA2 _MMIO(0x7108)
#define GEN7_SAMPLER_INSTDONE _MMIO(0xe160)
#define GEN7_ROW_INSTDONE _MMIO(0xe164)
+#define MCFG_MCR_SELECTOR _MMIO(0xfd0)
+#define SF_MCR_SELECTOR _MMIO(0xfd8)
#define GEN8_MCR_SELECTOR _MMIO(0xfdc)
#define GEN8_MCR_SLICE(slice) (((slice) & 3) << 26)
#define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3)
@@ -3099,6 +3115,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define GEN10_MIRROR_FUSE3 _MMIO(0x9118)
#define GEN10_L3BANK_PAIR_COUNT 4
#define GEN10_L3BANK_MASK 0x0F
+/* on Xe_HP the same fuses indicates mslices instead of L3 banks */
+#define GEN12_MAX_MSLICES 4
+#define GEN12_MEML3_EN_MASK 0x0F
#define GEN8_EU_DISABLE0 _MMIO(0x9134)
#define GEN8_EU_DIS0_S0_MASK 0xffffff
@@ -3133,6 +3152,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define GEN12_GT_DSS_ENABLE _MMIO(0x913C)
+#define XEHP_EU_ENABLE _MMIO(0x9134)
+#define XEHP_EU_ENA_MASK 0xFF
+
#define GEN6_BSD_SLEEP_PSMI_CONTROL _MMIO(0x12050)
#define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0)
#define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2)
@@ -4086,6 +4108,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define BXT_GT_PERF_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x7070)
#define GEN6_RP_STATE_LIMITS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5994)
#define GEN6_RP_STATE_CAP _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5998)
+#define RP0_CAP_MASK REG_GENMASK(7, 0)
+#define RP1_CAP_MASK REG_GENMASK(15, 8)
+#define RPN_CAP_MASK REG_GENMASK(23, 16)
#define BXT_RP_STATE_CAP _MMIO(0x138170)
#define GEN9_RP_STATE_LIMITS _MMIO(0x138148)
@@ -4142,6 +4167,7 @@ enum {
FAULT_AND_CONTINUE /* Unsupported */
};
+#define CTX_GTT_ADDRESS_MASK GENMASK(31, 12)
#define GEN8_CTX_VALID (1 << 0)
#define GEN8_CTX_FORCE_PD_RESTORE (1 << 1)
#define GEN8_CTX_FORCE_RESTORE (1 << 2)
@@ -4158,6 +4184,11 @@ enum {
#define GEN11_ENGINE_INSTANCE_SHIFT 48
#define GEN11_ENGINE_INSTANCE_WIDTH 6
+#define XEHP_SW_CTX_ID_SHIFT 39
+#define XEHP_SW_CTX_ID_WIDTH 16
+#define XEHP_SW_COUNTER_SHIFT 58
+#define XEHP_SW_COUNTER_WIDTH 6
+
#define CHV_CLK_CTL1 _MMIO(0x101100)
#define VLV_CLK_CTL2 _MMIO(0x101104)
#define CLK_CTL2_CZCOUNT_30NS_SHIFT 28
@@ -4586,23 +4617,26 @@ enum {
#define _PSR2_CTL_EDP 0x6f900
#define EDP_PSR2_CTL(tran) _MMIO_TRANS2(tran, _PSR2_CTL_A)
#define EDP_PSR2_ENABLE (1 << 31)
-#define EDP_SU_TRACK_ENABLE (1 << 30)
+#define EDP_SU_TRACK_ENABLE (1 << 30) /* up to adl-p */
#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_2 (0 << 28)
#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_3 (1 << 28)
#define EDP_Y_COORDINATE_ENABLE REG_BIT(25) /* display 10, 11 and 12 */
+#define EDP_PSR2_SU_SDP_SCANLINE REG_BIT(25) /* display 13+ */
#define EDP_MAX_SU_DISABLE_TIME(t) ((t) << 20)
#define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f << 20)
#define EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES 8
#define EDP_PSR2_IO_BUFFER_WAKE(lines) ((EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES - (lines)) << 13)
#define EDP_PSR2_IO_BUFFER_WAKE_MASK (3 << 13)
#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES 5
-#define TGL_EDP_PSR2_IO_BUFFER_WAKE(lines) (((lines) - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES) << 13)
+#define TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT 13
+#define TGL_EDP_PSR2_IO_BUFFER_WAKE(lines) (((lines) - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES) << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT)
#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MASK (7 << 13)
#define EDP_PSR2_FAST_WAKE_MAX_LINES 8
#define EDP_PSR2_FAST_WAKE(lines) ((EDP_PSR2_FAST_WAKE_MAX_LINES - (lines)) << 11)
#define EDP_PSR2_FAST_WAKE_MASK (3 << 11)
#define TGL_EDP_PSR2_FAST_WAKE_MIN_LINES 5
-#define TGL_EDP_PSR2_FAST_WAKE(lines) (((lines) - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES) << 10)
+#define TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT 10
+#define TGL_EDP_PSR2_FAST_WAKE(lines) (((lines) - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES) << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT)
#define TGL_EDP_PSR2_FAST_WAKE_MASK (7 << 10)
#define EDP_PSR2_TP2_TIME_500us (0 << 8)
#define EDP_PSR2_TP2_TIME_100us (1 << 8)
@@ -4652,17 +4686,23 @@ enum {
#define PSR2_SU_STATUS_MASK(frame) (0x3ff << PSR2_SU_STATUS_SHIFT(frame))
#define PSR2_SU_STATUS_FRAMES 8
-#define _PSR2_MAN_TRK_CTL_A 0x60910
-#define _PSR2_MAN_TRK_CTL_EDP 0x6f910
-#define PSR2_MAN_TRK_CTL(tran) _MMIO_TRANS2(tran, _PSR2_MAN_TRK_CTL_A)
-#define PSR2_MAN_TRK_CTL_ENABLE REG_BIT(31)
-#define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK REG_GENMASK(30, 21)
-#define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val)
+#define _PSR2_MAN_TRK_CTL_A 0x60910
+#define _PSR2_MAN_TRK_CTL_EDP 0x6f910
+#define PSR2_MAN_TRK_CTL(tran) _MMIO_TRANS2(tran, _PSR2_MAN_TRK_CTL_A)
+#define PSR2_MAN_TRK_CTL_ENABLE REG_BIT(31)
+#define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK REG_GENMASK(30, 21)
+#define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val)
#define PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(20, 11)
#define PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val)
-#define PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(3)
-#define PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(2)
-#define PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(1)
+#define PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(3)
+#define PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(2)
+#define PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(1)
+#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK REG_GENMASK(28, 16)
+#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val)
+#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(12, 0)
+#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val)
+#define ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(14)
+#define ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(13)
/* Icelake DSC Rate Control Range Parameter Registers */
#define DSCA_RC_RANGE_PARAMETERS_0 _MMIO(0x6B240)
@@ -7717,11 +7757,11 @@ enum {
#define SKL_PS_ECC_STAT(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_ECC_STAT_1A, _PS_ECC_STAT_2A), \
_ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B))
-#define CNL_PS_COEF_INDEX_SET(pipe, id, set) _MMIO_PIPE(pipe, \
+#define GLK_PS_COEF_INDEX_SET(pipe, id, set) _MMIO_PIPE(pipe, \
_ID(id, _PS_COEF_SET0_INDEX_1A, _PS_COEF_SET0_INDEX_2A) + (set) * 8, \
_ID(id, _PS_COEF_SET0_INDEX_1B, _PS_COEF_SET0_INDEX_2B) + (set) * 8)
-#define CNL_PS_COEF_DATA_SET(pipe, id, set) _MMIO_PIPE(pipe, \
+#define GLK_PS_COEF_DATA_SET(pipe, id, set) _MMIO_PIPE(pipe, \
_ID(id, _PS_COEF_SET0_DATA_1A, _PS_COEF_SET0_DATA_2A) + (set) * 8, \
_ID(id, _PS_COEF_SET0_DATA_1B, _PS_COEF_SET0_DATA_2B) + (set) * 8)
/* legacy palette */
@@ -7757,7 +7797,7 @@ enum {
#define GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED (3 << 0) /* icl + */
/* DMC */
-#define DMC_PROGRAM(i) _MMIO(0x80000 + (i) * 4)
+#define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4)
#define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0
#define DMC_HTP_ADDR_SKL 0x00500034
#define DMC_SSP_BASE _MMIO(0x8F074)
@@ -7936,7 +7976,7 @@ enum {
#define DSI1_NON_TE (1 << 31)
#define DSI0_NON_TE (1 << 30)
#define ICL_AUX_CHANNEL_E (1 << 29)
-#define CNL_AUX_CHANNEL_F (1 << 28)
+#define ICL_AUX_CHANNEL_F (1 << 28)
#define GEN9_AUX_CHANNEL_D (1 << 27)
#define GEN9_AUX_CHANNEL_C (1 << 26)
#define GEN9_AUX_CHANNEL_B (1 << 25)
@@ -7988,9 +8028,9 @@ enum {
#define GEN11_GT_DW1_IRQ (1 << 1)
#define GEN11_GT_DW0_IRQ (1 << 0)
-#define DG1_MSTR_UNIT_INTR _MMIO(0x190008)
+#define DG1_MSTR_TILE_INTR _MMIO(0x190008)
#define DG1_MSTR_IRQ REG_BIT(31)
-#define DG1_MSTR_UNIT(u) REG_BIT(u)
+#define DG1_MSTR_TILE(t) REG_BIT(t)
#define GEN11_DISPLAY_INT_CTL _MMIO(0x44200)
#define GEN11_DISPLAY_IRQ_ENABLE (1 << 31)
@@ -8073,7 +8113,10 @@ enum {
#define GEN11_BCS_RSVD_INTR_MASK _MMIO(0x1900a0)
#define GEN11_VCS0_VCS1_INTR_MASK _MMIO(0x1900a8)
#define GEN11_VCS2_VCS3_INTR_MASK _MMIO(0x1900ac)
+#define GEN12_VCS4_VCS5_INTR_MASK _MMIO(0x1900b0)
+#define GEN12_VCS6_VCS7_INTR_MASK _MMIO(0x1900b4)
#define GEN11_VECS0_VECS1_INTR_MASK _MMIO(0x1900d0)
+#define GEN12_VECS2_VECS3_INTR_MASK _MMIO(0x1900d4)
#define GEN11_GUC_SG_INTR_MASK _MMIO(0x1900e8)
#define GEN11_GPM_WGBOXPERF_INTR_MASK _MMIO(0x1900ec)
#define GEN11_CRYPTO_RSVD_INTR_MASK _MMIO(0x1900f0)
@@ -8113,6 +8156,7 @@ enum {
# define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2)
#define CHICKEN_PAR1_1 _MMIO(0x42080)
+#define IGNORE_KVMR_PIPE_A REG_BIT(23)
#define KBL_ARB_FILL_SPARE_22 REG_BIT(22)
#define DIS_RAM_BYPASS_PSR2_MAN_TRACK (1 << 16)
#define SKL_DE_COMPRESSED_HASH_MODE (1 << 15)
@@ -8125,7 +8169,6 @@ enum {
#define KVM_CONFIG_CHANGE_NOTIFICATION_SELECT (1 << 14)
#define CHICKEN_MISC_2 _MMIO(0x42084)
-#define CNL_COMP_PWR_DOWN (1 << 23)
#define KBL_ARB_FILL_SPARE_14 REG_BIT(14)
#define KBL_ARB_FILL_SPARE_13 REG_BIT(13)
#define GLK_CL2_PWR_DOWN (1 << 12)
@@ -8163,15 +8206,16 @@ enum {
[TRANSCODER_B] = _CHICKEN_TRANS_B, \
[TRANSCODER_C] = _CHICKEN_TRANS_C, \
[TRANSCODER_D] = _CHICKEN_TRANS_D))
-#define HSW_FRAME_START_DELAY_MASK (3 << 27)
-#define HSW_FRAME_START_DELAY(x) ((x) << 27) /* 0-3 */
-#define VSC_DATA_SEL_SOFTWARE_CONTROL (1 << 25) /* GLK and CNL+ */
-#define DDI_TRAINING_OVERRIDE_ENABLE (1 << 19)
-#define DDI_TRAINING_OVERRIDE_VALUE (1 << 18)
-#define DDIE_TRAINING_OVERRIDE_ENABLE (1 << 17) /* CHICKEN_TRANS_A only */
-#define DDIE_TRAINING_OVERRIDE_VALUE (1 << 16) /* CHICKEN_TRANS_A only */
-#define PSR2_ADD_VERTICAL_LINE_COUNT (1 << 15)
-#define PSR2_VSC_ENABLE_PROG_HEADER (1 << 12)
+#define HSW_FRAME_START_DELAY_MASK REG_GENMASK(28, 27)
+#define HSW_FRAME_START_DELAY(x) REG_FIELD_PREP(HSW_FRAME_START_DELAY_MASK, x)
+#define VSC_DATA_SEL_SOFTWARE_CONTROL REG_BIT(25) /* GLK */
+#define FECSTALL_DIS_DPTSTREAM_DPTTG REG_BIT(23)
+#define DDI_TRAINING_OVERRIDE_ENABLE REG_BIT(19)
+#define DDI_TRAINING_OVERRIDE_VALUE REG_BIT(18)
+#define DDIE_TRAINING_OVERRIDE_ENABLE REG_BIT(17) /* CHICKEN_TRANS_A only */
+#define DDIE_TRAINING_OVERRIDE_VALUE REG_BIT(16) /* CHICKEN_TRANS_A only */
+#define PSR2_ADD_VERTICAL_LINE_COUNT REG_BIT(15)
+#define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12)
#define DISP_ARB_CTL _MMIO(0x45000)
#define DISP_FBC_MEMORY_WAKE (1 << 31)
@@ -8229,9 +8273,8 @@ enum {
#define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430)
#define SKL_SELECT_ALTERNATE_DC_EXIT (1 << 30)
-#define CNL_DELAY_PMRSP (1 << 22)
+#define ICL_DELAY_PMRSP (1 << 22)
#define MASK_WAKEMEM (1 << 13)
-#define CNL_DDI_CLOCK_REG_ACCESS_ON (1 << 7)
#define GEN11_CHICKEN_DCPR_2 _MMIO(0x46434)
#define DCPR_MASK_MAXLATENCY_MEMUP_CLR REG_BIT(27)
@@ -8252,10 +8295,9 @@ enum {
#define SKL_DFSM_PIPE_B_DISABLE (1 << 21)
#define SKL_DFSM_PIPE_C_DISABLE (1 << 28)
#define TGL_DFSM_PIPE_D_DISABLE (1 << 22)
-#define CNL_DFSM_DISPLAY_DSC_DISABLE (1 << 7)
+#define GLK_DFSM_DISPLAY_DSC_DISABLE (1 << 7)
#define SKL_DSSM _MMIO(0x51004)
-#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz (1 << 31)
#define ICL_DSSM_CDCLK_PLL_REFCLK_MASK (7 << 29)
#define ICL_DSSM_CDCLK_PLL_REFCLK_24MHz (0 << 29)
#define ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz (1 << 29)
@@ -8354,7 +8396,6 @@ enum {
/* GEN8 chicken */
#define HDC_CHICKEN0 _MMIO(0x7300)
-#define CNL_HDC_CHICKEN0 _MMIO(0xE5F0)
#define ICL_HDC_MODE _MMIO(0xE5F4)
#define HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE (1 << 15)
#define HDC_FENCE_DEST_SLM_DISABLE (1 << 14)
@@ -8388,7 +8429,8 @@ enum {
#define _PIPEC_CHICKEN 0x72038
#define PIPE_CHICKEN(pipe) _MMIO_PIPE(pipe, _PIPEA_CHICKEN,\
_PIPEB_CHICKEN)
-#define UNDERRUN_RECOVERY_DISABLE REG_BIT(30)
+#define UNDERRUN_RECOVERY_DISABLE_ADLP REG_BIT(30)
+#define UNDERRUN_RECOVERY_ENABLE_DG2 REG_BIT(30)
#define PIXEL_ROUNDING_TRUNC_FB_PASSTHRU (1 << 15)
#define PER_PIXEL_ALPHA_BYPASS_EN (1 << 7)
@@ -9200,6 +9242,8 @@ enum {
#define GEN9_FREQUENCY(x) ((x) << 23)
#define GEN6_OFFSET(x) ((x) << 19)
#define GEN6_AGGRESSIVE_TURBO (0 << 15)
+#define GEN9_SW_REQ_UNSLICE_RATIO_SHIFT 23
+
#define GEN6_RC_VIDEO_FREQ _MMIO(0xA00C)
#define GEN6_RC_CONTROL _MMIO(0xA090)
#define GEN6_RC_CTL_RC6pp_ENABLE (1 << 16)
@@ -9368,9 +9412,13 @@ enum {
#define ICL_PCODE_MEM_SUBSYSYSTEM_INFO 0xd
#define ICL_PCODE_MEM_SS_READ_GLOBAL_INFO (0x0 << 8)
#define ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point) (((point) << 16) | (0x1 << 8))
+#define ADL_PCODE_MEM_SS_READ_PSF_GV_INFO ((0) | (0x2 << 8))
#define ICL_PCODE_SAGV_DE_MEM_SS_CONFIG 0xe
#define ICL_PCODE_POINTS_RESTRICTED 0x0
-#define ICL_PCODE_POINTS_RESTRICTED_MASK 0x1
+#define ICL_PCODE_POINTS_RESTRICTED_MASK 0xf
+#define ADLS_PSF_PT_SHIFT 8
+#define ADLS_QGV_PT_MASK REG_GENMASK(7, 0)
+#define ADLS_PSF_PT_MASK REG_GENMASK(10, 8)
#define GEN6_PCODE_READ_D_COMP 0x10
#define GEN6_PCODE_WRITE_D_COMP 0x11
#define ICL_PCODE_EXIT_TCCOLD 0x12
@@ -9530,7 +9578,6 @@ enum {
#define HSW_SAMPLE_C_PERFORMANCE (1 << 9)
#define GEN8_CENTROID_PIXEL_OPT_DIS (1 << 8)
#define GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC (1 << 5)
-#define CNL_FAST_ANISO_L1_BANKING_FIX (1 << 4)
#define GEN8_SAMPLER_POWER_BYPASS_DIS (1 << 1)
#define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194)
@@ -9711,15 +9758,12 @@ enum {
/* HSW/BDW power well */
#define HSW_PW_CTL_IDX_GLOBAL 15
-/* SKL/BXT/GLK/CNL power wells */
+/* SKL/BXT/GLK power wells */
#define SKL_PW_CTL_IDX_PW_2 15
#define SKL_PW_CTL_IDX_PW_1 14
-#define CNL_PW_CTL_IDX_AUX_F 12
-#define CNL_PW_CTL_IDX_AUX_D 11
#define GLK_PW_CTL_IDX_AUX_C 10
#define GLK_PW_CTL_IDX_AUX_B 9
#define GLK_PW_CTL_IDX_AUX_A 8
-#define CNL_PW_CTL_IDX_DDI_F 6
#define SKL_PW_CTL_IDX_DDI_D 4
#define SKL_PW_CTL_IDX_DDI_C 3
#define SKL_PW_CTL_IDX_DDI_B 2
@@ -9818,19 +9862,6 @@ enum skl_power_gate {
((pw_idx) - ICL_PW_CTL_IDX_PW_1 + SKL_PG1)
#define SKL_FUSE_PG_DIST_STATUS(pg) (1 << (27 - (pg)))
-#define _CNL_AUX_REG_IDX(pw_idx) ((pw_idx) - GLK_PW_CTL_IDX_AUX_B)
-#define _CNL_AUX_ANAOVRD1_B 0x162250
-#define _CNL_AUX_ANAOVRD1_C 0x162210
-#define _CNL_AUX_ANAOVRD1_D 0x1622D0
-#define _CNL_AUX_ANAOVRD1_F 0x162A90
-#define CNL_AUX_ANAOVRD1(pw_idx) _MMIO(_PICK(_CNL_AUX_REG_IDX(pw_idx), \
- _CNL_AUX_ANAOVRD1_B, \
- _CNL_AUX_ANAOVRD1_C, \
- _CNL_AUX_ANAOVRD1_D, \
- _CNL_AUX_ANAOVRD1_F))
-#define CNL_AUX_ANAOVRD1_ENABLE (1 << 16)
-#define CNL_AUX_ANAOVRD1_LDO_BYPASS (1 << 23)
-
#define _ICL_AUX_REG_IDX(pw_idx) ((pw_idx) - ICL_PW_CTL_IDX_AUX_A)
#define _ICL_AUX_ANAOVRD1_A 0x162398
#define _ICL_AUX_ANAOVRD1_B 0x6C398
@@ -10130,11 +10161,11 @@ enum skl_power_gate {
#define TRANS_DDI_BPC_10 (1 << 20)
#define TRANS_DDI_BPC_6 (2 << 20)
#define TRANS_DDI_BPC_12 (3 << 20)
-#define TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK REG_GENMASK(19, 18) /* bdw-cnl */
+#define TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK REG_GENMASK(19, 18)
#define TRANS_DDI_PORT_SYNC_MASTER_SELECT(x) REG_FIELD_PREP(TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK, (x))
#define TRANS_DDI_PVSYNC (1 << 17)
#define TRANS_DDI_PHSYNC (1 << 16)
-#define TRANS_DDI_PORT_SYNC_ENABLE REG_BIT(15) /* bdw-cnl */
+#define TRANS_DDI_PORT_SYNC_ENABLE REG_BIT(15)
#define TRANS_DDI_EDP_INPUT_MASK (7 << 12)
#define TRANS_DDI_EDP_INPUT_A_ON (0 << 12)
#define TRANS_DDI_EDP_INPUT_A_ONOFF (4 << 12)
@@ -10167,6 +10198,9 @@ enum skl_power_gate {
#define PORT_SYNC_MODE_MASTER_SELECT_MASK REG_GENMASK(2, 0)
#define PORT_SYNC_MODE_MASTER_SELECT(x) REG_FIELD_PREP(PORT_SYNC_MODE_MASTER_SELECT_MASK, (x))
+#define TRANS_CMTG_CHICKEN _MMIO(0x6fa90)
+#define DISABLE_DPT_CLK_GATING REG_BIT(1)
+
/* DisplayPort Transport Control */
#define _DP_TP_CTL_A 0x64040
#define _DP_TP_CTL_B 0x64140
@@ -10371,6 +10405,14 @@ enum skl_power_gate {
#define TRANS_MSA_MISC(tran) _MMIO_TRANS2(tran, _TRANSA_MSA_MISC)
/* See DP_MSA_MISC_* for the bit definitions */
+#define _TRANS_A_SET_CONTEXT_LATENCY 0x6007C
+#define _TRANS_B_SET_CONTEXT_LATENCY 0x6107C
+#define _TRANS_C_SET_CONTEXT_LATENCY 0x6207C
+#define _TRANS_D_SET_CONTEXT_LATENCY 0x6307C
+#define TRANS_SET_CONTEXT_LATENCY(tran) _MMIO_TRANS2(tran, _TRANS_A_SET_CONTEXT_LATENCY)
+#define TRANS_SET_CONTEXT_LATENCY_MASK REG_GENMASK(15, 0)
+#define TRANS_SET_CONTEXT_LATENCY_VALUE(x) REG_FIELD_PREP(TRANS_SET_CONTEXT_LATENCY_MASK, (x))
+
/* LCPLL Control */
#define LCPLL_CTL _MMIO(0x130040)
#define LCPLL_PLL_DISABLE (1 << 31)
@@ -10482,17 +10524,6 @@ enum skl_power_gate {
#define DPLL_CFGCR1(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR1)
#define DPLL_CFGCR2(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR2, _DPLL2_CFGCR2)
-/*
- * CNL Clocks
- */
-#define DPCLKA_CFGCR0 _MMIO(0x6C200)
-#define DPCLKA_CFGCR0_DDI_CLK_OFF(port) (1 << ((port) == PORT_F ? 23 : \
- (port) + 10))
-#define DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port) ((port) == PORT_F ? 21 : \
- (port) * 2)
-#define DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port) (3 << DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port))
-#define DPCLKA_CFGCR0_DDI_CLK_SEL(pll, port) ((pll) << DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port))
-
/* ICL Clocks */
#define ICL_DPCLKA_CFGCR0 _MMIO(0x164280)
#define ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) (1 << _PICK(phy, 10, 11, 24, 4, 5))
@@ -10548,7 +10579,7 @@ enum skl_power_gate {
ADLS_DPCLKA_DDIJ_SEL_MASK, \
ADLS_DPCLKA_DDIK_SEL_MASK)
-/* CNL PLL */
+/* ICL PLL */
#define DPLL0_ENABLE 0x46010
#define DPLL1_ENABLE 0x46014
#define _ADLS_DPLL2_ENABLE 0x46018
@@ -10557,9 +10588,14 @@ enum skl_power_gate {
#define PLL_LOCK (1 << 30)
#define PLL_POWER_ENABLE (1 << 27)
#define PLL_POWER_STATE (1 << 26)
-#define CNL_DPLL_ENABLE(pll) _MMIO_PLL3(pll, DPLL0_ENABLE, DPLL1_ENABLE, \
+#define ICL_DPLL_ENABLE(pll) _MMIO_PLL3(pll, DPLL0_ENABLE, DPLL1_ENABLE, \
_ADLS_DPLL2_ENABLE, _ADLS_DPLL3_ENABLE)
+#define _DG2_PLL3_ENABLE 0x4601C
+
+#define DG2_PLL_ENABLE(pll) _MMIO_PLL3(pll, DPLL0_ENABLE, DPLL1_ENABLE, \
+ _ADLS_DPLL2_ENABLE, _DG2_PLL3_ENABLE)
+
#define TBT_PLL_ENABLE _MMIO(0x46020)
#define _MG_PLL1_ENABLE 0x46030
@@ -10725,60 +10761,52 @@ enum skl_power_gate {
_MG_PLL_TDC_COLDST_BIAS_PORT1, \
_MG_PLL_TDC_COLDST_BIAS_PORT2)
-#define _CNL_DPLL0_CFGCR0 0x6C000
-#define _CNL_DPLL1_CFGCR0 0x6C080
-#define DPLL_CFGCR0_HDMI_MODE (1 << 30)
-#define DPLL_CFGCR0_SSC_ENABLE (1 << 29)
-#define DPLL_CFGCR0_SSC_ENABLE_ICL (1 << 25)
-#define DPLL_CFGCR0_LINK_RATE_MASK (0xf << 25)
-#define DPLL_CFGCR0_LINK_RATE_2700 (0 << 25)
-#define DPLL_CFGCR0_LINK_RATE_1350 (1 << 25)
-#define DPLL_CFGCR0_LINK_RATE_810 (2 << 25)
-#define DPLL_CFGCR0_LINK_RATE_1620 (3 << 25)
-#define DPLL_CFGCR0_LINK_RATE_1080 (4 << 25)
-#define DPLL_CFGCR0_LINK_RATE_2160 (5 << 25)
-#define DPLL_CFGCR0_LINK_RATE_3240 (6 << 25)
-#define DPLL_CFGCR0_LINK_RATE_4050 (7 << 25)
-#define DPLL_CFGCR0_DCO_FRACTION_MASK (0x7fff << 10)
-#define DPLL_CFGCR0_DCO_FRACTION_SHIFT (10)
-#define DPLL_CFGCR0_DCO_FRACTION(x) ((x) << 10)
-#define DPLL_CFGCR0_DCO_INTEGER_MASK (0x3ff)
-#define CNL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR0, _CNL_DPLL1_CFGCR0)
-
-#define _CNL_DPLL0_CFGCR1 0x6C004
-#define _CNL_DPLL1_CFGCR1 0x6C084
-#define DPLL_CFGCR1_QDIV_RATIO_MASK (0xff << 10)
-#define DPLL_CFGCR1_QDIV_RATIO_SHIFT (10)
-#define DPLL_CFGCR1_QDIV_RATIO(x) ((x) << 10)
-#define DPLL_CFGCR1_QDIV_MODE_SHIFT (9)
-#define DPLL_CFGCR1_QDIV_MODE(x) ((x) << 9)
-#define DPLL_CFGCR1_KDIV_MASK (7 << 6)
-#define DPLL_CFGCR1_KDIV_SHIFT (6)
-#define DPLL_CFGCR1_KDIV(x) ((x) << 6)
-#define DPLL_CFGCR1_KDIV_1 (1 << 6)
-#define DPLL_CFGCR1_KDIV_2 (2 << 6)
-#define DPLL_CFGCR1_KDIV_3 (4 << 6)
-#define DPLL_CFGCR1_PDIV_MASK (0xf << 2)
-#define DPLL_CFGCR1_PDIV_SHIFT (2)
-#define DPLL_CFGCR1_PDIV(x) ((x) << 2)
-#define DPLL_CFGCR1_PDIV_2 (1 << 2)
-#define DPLL_CFGCR1_PDIV_3 (2 << 2)
-#define DPLL_CFGCR1_PDIV_5 (4 << 2)
-#define DPLL_CFGCR1_PDIV_7 (8 << 2)
-#define DPLL_CFGCR1_CENTRAL_FREQ (3 << 0)
-#define DPLL_CFGCR1_CENTRAL_FREQ_8400 (3 << 0)
-#define TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL (0 << 0)
-#define CNL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR1, _CNL_DPLL1_CFGCR1)
-
#define _ICL_DPLL0_CFGCR0 0x164000
#define _ICL_DPLL1_CFGCR0 0x164080
#define ICL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _ICL_DPLL0_CFGCR0, \
_ICL_DPLL1_CFGCR0)
+#define DPLL_CFGCR0_HDMI_MODE (1 << 30)
+#define DPLL_CFGCR0_SSC_ENABLE (1 << 29)
+#define DPLL_CFGCR0_SSC_ENABLE_ICL (1 << 25)
+#define DPLL_CFGCR0_LINK_RATE_MASK (0xf << 25)
+#define DPLL_CFGCR0_LINK_RATE_2700 (0 << 25)
+#define DPLL_CFGCR0_LINK_RATE_1350 (1 << 25)
+#define DPLL_CFGCR0_LINK_RATE_810 (2 << 25)
+#define DPLL_CFGCR0_LINK_RATE_1620 (3 << 25)
+#define DPLL_CFGCR0_LINK_RATE_1080 (4 << 25)
+#define DPLL_CFGCR0_LINK_RATE_2160 (5 << 25)
+#define DPLL_CFGCR0_LINK_RATE_3240 (6 << 25)
+#define DPLL_CFGCR0_LINK_RATE_4050 (7 << 25)
+#define DPLL_CFGCR0_DCO_FRACTION_MASK (0x7fff << 10)
+#define DPLL_CFGCR0_DCO_FRACTION_SHIFT (10)
+#define DPLL_CFGCR0_DCO_FRACTION(x) ((x) << 10)
+#define DPLL_CFGCR0_DCO_INTEGER_MASK (0x3ff)
#define _ICL_DPLL0_CFGCR1 0x164004
#define _ICL_DPLL1_CFGCR1 0x164084
#define ICL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _ICL_DPLL0_CFGCR1, \
_ICL_DPLL1_CFGCR1)
+#define DPLL_CFGCR1_QDIV_RATIO_MASK (0xff << 10)
+#define DPLL_CFGCR1_QDIV_RATIO_SHIFT (10)
+#define DPLL_CFGCR1_QDIV_RATIO(x) ((x) << 10)
+#define DPLL_CFGCR1_QDIV_MODE_SHIFT (9)
+#define DPLL_CFGCR1_QDIV_MODE(x) ((x) << 9)
+#define DPLL_CFGCR1_KDIV_MASK (7 << 6)
+#define DPLL_CFGCR1_KDIV_SHIFT (6)
+#define DPLL_CFGCR1_KDIV(x) ((x) << 6)
+#define DPLL_CFGCR1_KDIV_1 (1 << 6)
+#define DPLL_CFGCR1_KDIV_2 (2 << 6)
+#define DPLL_CFGCR1_KDIV_3 (4 << 6)
+#define DPLL_CFGCR1_PDIV_MASK (0xf << 2)
+#define DPLL_CFGCR1_PDIV_SHIFT (2)
+#define DPLL_CFGCR1_PDIV(x) ((x) << 2)
+#define DPLL_CFGCR1_PDIV_2 (1 << 2)
+#define DPLL_CFGCR1_PDIV_3 (2 << 2)
+#define DPLL_CFGCR1_PDIV_5 (4 << 2)
+#define DPLL_CFGCR1_PDIV_7 (8 << 2)
+#define DPLL_CFGCR1_CENTRAL_FREQ (3 << 0)
+#define DPLL_CFGCR1_CENTRAL_FREQ_8400 (3 << 0)
+#define TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL (0 << 0)
#define _TGL_DPLL0_CFGCR0 0x164284
#define _TGL_DPLL1_CFGCR0 0x16428C
@@ -10998,8 +11026,8 @@ enum skl_power_gate {
#define BXT_DE_PLL_LOCK (1 << 30)
#define BXT_DE_PLL_FREQ_REQ (1 << 23)
#define BXT_DE_PLL_FREQ_REQ_ACK (1 << 22)
-#define CNL_CDCLK_PLL_RATIO(x) (x)
-#define CNL_CDCLK_PLL_RATIO_MASK 0xff
+#define ICL_CDCLK_PLL_RATIO(x) (x)
+#define ICL_CDCLK_PLL_RATIO_MASK 0xff
/* GEN9 DC */
#define DC_STATE_EN _MMIO(0x45504)
@@ -11054,6 +11082,7 @@ enum skl_power_gate {
#define SKL_MEMORY_FREQ_MULTIPLIER_HZ 266666666
#define SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5E04)
#define SKL_REQ_DATA_MASK (0xF << 0)
+#define DG1_GEAR_TYPE REG_BIT(16)
#define SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5000)
#define SKL_DRAM_DDR_TYPE_MASK (0x3 << 0)
@@ -11076,18 +11105,29 @@ enum skl_power_gate {
#define SKL_DRAM_RANK_1 (0x0 << 10)
#define SKL_DRAM_RANK_2 (0x1 << 10)
#define SKL_DRAM_RANK_MASK (0x1 << 10)
-#define CNL_DRAM_SIZE_MASK 0x7F
-#define CNL_DRAM_WIDTH_MASK (0x3 << 7)
-#define CNL_DRAM_WIDTH_SHIFT 7
-#define CNL_DRAM_WIDTH_X8 (0x0 << 7)
-#define CNL_DRAM_WIDTH_X16 (0x1 << 7)
-#define CNL_DRAM_WIDTH_X32 (0x2 << 7)
-#define CNL_DRAM_RANK_MASK (0x3 << 9)
-#define CNL_DRAM_RANK_SHIFT 9
-#define CNL_DRAM_RANK_1 (0x0 << 9)
-#define CNL_DRAM_RANK_2 (0x1 << 9)
-#define CNL_DRAM_RANK_3 (0x2 << 9)
-#define CNL_DRAM_RANK_4 (0x3 << 9)
+#define ICL_DRAM_SIZE_MASK 0x7F
+#define ICL_DRAM_WIDTH_MASK (0x3 << 7)
+#define ICL_DRAM_WIDTH_SHIFT 7
+#define ICL_DRAM_WIDTH_X8 (0x0 << 7)
+#define ICL_DRAM_WIDTH_X16 (0x1 << 7)
+#define ICL_DRAM_WIDTH_X32 (0x2 << 7)
+#define ICL_DRAM_RANK_MASK (0x3 << 9)
+#define ICL_DRAM_RANK_SHIFT 9
+#define ICL_DRAM_RANK_1 (0x0 << 9)
+#define ICL_DRAM_RANK_2 (0x1 << 9)
+#define ICL_DRAM_RANK_3 (0x2 << 9)
+#define ICL_DRAM_RANK_4 (0x3 << 9)
+
+#define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918)
+#define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2)
+#define DG1_QCLK_REFERENCE REG_BIT(10)
+
+#define MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x4000)
+#define DG1_DRAM_T_RDPRE_MASK REG_GENMASK(16, 11)
+#define DG1_DRAM_T_RP_MASK REG_GENMASK(6, 0)
+#define MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x4004)
+#define DG1_DRAM_T_RCD_MASK REG_GENMASK(15, 9)
+#define DG1_DRAM_T_RAS_MASK REG_GENMASK(8, 1)
/*
* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
@@ -12290,6 +12330,7 @@ enum skl_power_gate {
/* MOCS (Memory Object Control State) registers */
#define GEN9_LNCFCMOCS(i) _MMIO(0xb020 + (i) * 4) /* L3 Cache Control */
+#define GEN9_LNCFCMOCS_REG_COUNT 32
#define __GEN9_RCS0_MOCS0 0xc800
#define GEN9_GFX_MOCS(i) _MMIO(__GEN9_RCS0_MOCS0 + (i) * 4)
@@ -12337,6 +12378,7 @@ enum skl_power_gate {
_ICL_PHY_MISC_B)
#define ICL_PHY_MISC_MUX_DDID (1 << 28)
#define ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN (1 << 23)
+#define DG2_PHY_DP_TX_ACK_MASK REG_GENMASK(23, 20)
/* Icelake Display Stream Compression Registers */
#define DSCA_PICTURE_PARAMETER_SET_0 _MMIO(0x6B200)
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 37aef1308573..ce446716d092 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -42,22 +42,17 @@
#include "i915_active.h"
#include "i915_drv.h"
-#include "i915_globals.h"
#include "i915_trace.h"
#include "intel_pm.h"
struct execute_cb {
struct irq_work work;
struct i915_sw_fence *fence;
- void (*hook)(struct i915_request *rq, struct dma_fence *signal);
struct i915_request *signal;
};
-static struct i915_global_request {
- struct i915_global base;
- struct kmem_cache *slab_requests;
- struct kmem_cache *slab_execute_cbs;
-} global;
+static struct kmem_cache *slab_requests;
+static struct kmem_cache *slab_execute_cbs;
static const char *i915_fence_get_driver_name(struct dma_fence *fence)
{
@@ -108,13 +103,16 @@ static signed long i915_fence_wait(struct dma_fence *fence,
struct kmem_cache *i915_request_slab_cache(void)
{
- return global.slab_requests;
+ return slab_requests;
}
static void i915_fence_release(struct dma_fence *fence)
{
struct i915_request *rq = to_request(fence);
+ GEM_BUG_ON(rq->guc_prio != GUC_PRIO_INIT &&
+ rq->guc_prio != GUC_PRIO_FINI);
+
/*
* The request is put onto a RCU freelist (i.e. the address
* is immediately reused), mark the fences as being freed now.
@@ -126,41 +124,19 @@ static void i915_fence_release(struct dma_fence *fence)
i915_sw_fence_fini(&rq->semaphore);
/*
- * Keep one request on each engine for reserved use under mempressure
- *
- * We do not hold a reference to the engine here and so have to be
- * very careful in what rq->engine we poke. The virtual engine is
- * referenced via the rq->context and we released that ref during
- * i915_request_retire(), ergo we must not dereference a virtual
- * engine here. Not that we would want to, as the only consumer of
- * the reserved engine->request_pool is the power management parking,
- * which must-not-fail, and that is only run on the physical engines.
- *
- * Since the request must have been executed to be have completed,
- * we know that it will have been processed by the HW and will
- * not be unsubmitted again, so rq->engine and rq->execution_mask
- * at this point is stable. rq->execution_mask will be a single
- * bit if the last and _only_ engine it could execution on was a
- * physical engine, if it's multiple bits then it started on and
- * could still be on a virtual engine. Thus if the mask is not a
- * power-of-two we assume that rq->engine may still be a virtual
- * engine and so a dangling invalid pointer that we cannot dereference
- *
- * For example, consider the flow of a bonded request through a virtual
- * engine. The request is created with a wide engine mask (all engines
- * that we might execute on). On processing the bond, the request mask
- * is reduced to one or more engines. If the request is subsequently
- * bound to a single engine, it will then be constrained to only
- * execute on that engine and never returned to the virtual engine
- * after timeslicing away, see __unwind_incomplete_requests(). Thus we
- * know that if the rq->execution_mask is a single bit, rq->engine
- * can be a physical engine with the exact corresponding mask.
+ * Keep one request on each engine for reserved use under mempressure,
+ * do not use with virtual engines as this really is only needed for
+ * kernel contexts.
*/
- if (is_power_of_2(rq->execution_mask) &&
- !cmpxchg(&rq->engine->request_pool, NULL, rq))
+ if (!intel_engine_is_virtual(rq->engine) &&
+ !cmpxchg(&rq->engine->request_pool, NULL, rq)) {
+ intel_context_put(rq->context);
return;
+ }
+
+ intel_context_put(rq->context);
- kmem_cache_free(global.slab_requests, rq);
+ kmem_cache_free(slab_requests, rq);
}
const struct dma_fence_ops i915_fence_ops = {
@@ -177,18 +153,7 @@ static void irq_execute_cb(struct irq_work *wrk)
struct execute_cb *cb = container_of(wrk, typeof(*cb), work);
i915_sw_fence_complete(cb->fence);
- kmem_cache_free(global.slab_execute_cbs, cb);
-}
-
-static void irq_execute_cb_hook(struct irq_work *wrk)
-{
- struct execute_cb *cb = container_of(wrk, typeof(*cb), work);
-
- cb->hook(container_of(cb->fence, struct i915_request, submit),
- &cb->signal->fence);
- i915_request_put(cb->signal);
-
- irq_execute_cb(wrk);
+ kmem_cache_free(slab_execute_cbs, cb);
}
static __always_inline void
@@ -216,7 +181,7 @@ static bool irq_work_imm(struct irq_work *wrk)
return false;
}
-static void __notify_execute_cb_imm(struct i915_request *rq)
+void i915_request_notify_execute_cb_imm(struct i915_request *rq)
{
__notify_execute_cb(rq, irq_work_imm);
}
@@ -272,11 +237,11 @@ i915_request_active_engine(struct i915_request *rq,
* check that we have acquired the lock on the final engine.
*/
locked = READ_ONCE(rq->engine);
- spin_lock_irq(&locked->active.lock);
+ spin_lock_irq(&locked->sched_engine->lock);
while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) {
- spin_unlock(&locked->active.lock);
+ spin_unlock(&locked->sched_engine->lock);
locked = engine;
- spin_lock(&locked->active.lock);
+ spin_lock(&locked->sched_engine->lock);
}
if (i915_request_is_active(rq)) {
@@ -285,42 +250,11 @@ i915_request_active_engine(struct i915_request *rq,
ret = true;
}
- spin_unlock_irq(&locked->active.lock);
+ spin_unlock_irq(&locked->sched_engine->lock);
return ret;
}
-
-static void remove_from_engine(struct i915_request *rq)
-{
- struct intel_engine_cs *engine, *locked;
-
- /*
- * Virtual engines complicate acquiring the engine timeline lock,
- * as their rq->engine pointer is not stable until under that
- * engine lock. The simple ploy we use is to take the lock then
- * check that the rq still belongs to the newly locked engine.
- */
- locked = READ_ONCE(rq->engine);
- spin_lock_irq(&locked->active.lock);
- while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) {
- spin_unlock(&locked->active.lock);
- spin_lock(&engine->active.lock);
- locked = engine;
- }
- list_del_init(&rq->sched.link);
-
- clear_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
- clear_bit(I915_FENCE_FLAG_HOLD, &rq->fence.flags);
-
- /* Prevent further __await_execution() registering a cb, then flush */
- set_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags);
-
- spin_unlock_irq(&locked->active.lock);
-
- __notify_execute_cb_imm(rq);
-}
-
static void __rq_init_watchdog(struct i915_request *rq)
{
rq->watchdog.timer.function = NULL;
@@ -417,8 +351,7 @@ bool i915_request_retire(struct i915_request *rq)
* after removing the breadcrumb and signaling it, so that we do not
* inadvertently attach the breadcrumb to a completed request.
*/
- if (!list_empty(&rq->sched.link))
- remove_from_engine(rq);
+ rq->engine->remove_active_request(rq);
GEM_BUG_ON(!llist_empty(&rq->execute_cb));
__list_del_entry(&rq->link); /* poison neither prev/next (RCU walks) */
@@ -443,6 +376,7 @@ void i915_request_retire_upto(struct i915_request *rq)
do {
tmp = list_first_entry(&tl->requests, typeof(*tmp), link);
+ GEM_BUG_ON(!i915_request_completed(tmp));
} while (i915_request_retire(tmp) && tmp != rq);
}
@@ -517,19 +451,14 @@ static bool __request_in_flight(const struct i915_request *signal)
static int
__await_execution(struct i915_request *rq,
struct i915_request *signal,
- void (*hook)(struct i915_request *rq,
- struct dma_fence *signal),
gfp_t gfp)
{
struct execute_cb *cb;
- if (i915_request_is_active(signal)) {
- if (hook)
- hook(rq, &signal->fence);
+ if (i915_request_is_active(signal))
return 0;
- }
- cb = kmem_cache_alloc(global.slab_execute_cbs, gfp);
+ cb = kmem_cache_alloc(slab_execute_cbs, gfp);
if (!cb)
return -ENOMEM;
@@ -537,12 +466,6 @@ __await_execution(struct i915_request *rq,
i915_sw_fence_await(cb->fence);
init_irq_work(&cb->work, irq_execute_cb);
- if (hook) {
- cb->hook = hook;
- cb->signal = i915_request_get(signal);
- cb->work.func = irq_execute_cb_hook;
- }
-
/*
* Register the callback first, then see if the signaler is already
* active. This ensures that if we race with the
@@ -559,7 +482,7 @@ __await_execution(struct i915_request *rq,
if (llist_add(&cb->work.node.llist, &signal->execute_cb)) {
if (i915_request_is_active(signal) ||
__request_in_flight(signal))
- __notify_execute_cb_imm(signal);
+ i915_request_notify_execute_cb_imm(signal);
}
return 0;
@@ -637,7 +560,7 @@ bool __i915_request_submit(struct i915_request *request)
RQ_TRACE(request, "\n");
GEM_BUG_ON(!irqs_disabled());
- lockdep_assert_held(&engine->active.lock);
+ lockdep_assert_held(&engine->sched_engine->lock);
/*
* With the advent of preempt-to-busy, we frequently encounter
@@ -649,7 +572,7 @@ bool __i915_request_submit(struct i915_request *request)
*
* We must remove the request from the caller's priority queue,
* and the caller must only call us when the request is in their
- * priority queue, under the active.lock. This ensures that the
+ * priority queue, under the sched_engine->lock. This ensures that the
* request has *not* yet been retired and we can safely move
* the request into the engine->active.list where it will be
* dropped upon retiring. (Otherwise if resubmit a *retired*
@@ -690,11 +613,15 @@ bool __i915_request_submit(struct i915_request *request)
request->ring->vaddr + request->postfix);
trace_i915_request_execute(request);
- engine->serial++;
+ if (engine->bump_serial)
+ engine->bump_serial(engine);
+ else
+ engine->serial++;
+
result = true;
GEM_BUG_ON(test_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags));
- list_move_tail(&request->sched.link, &engine->active.requests);
+ engine->add_active_request(request);
active:
clear_bit(I915_FENCE_FLAG_PQUEUE, &request->fence.flags);
set_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags);
@@ -724,11 +651,11 @@ void i915_request_submit(struct i915_request *request)
unsigned long flags;
/* Will be called from irq-context when using foreign fences. */
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
__i915_request_submit(request);
- spin_unlock_irqrestore(&engine->active.lock, flags);
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
}
void __i915_request_unsubmit(struct i915_request *request)
@@ -742,7 +669,7 @@ void __i915_request_unsubmit(struct i915_request *request)
RQ_TRACE(request, "\n");
GEM_BUG_ON(!irqs_disabled());
- lockdep_assert_held(&engine->active.lock);
+ lockdep_assert_held(&engine->sched_engine->lock);
/*
* Before we remove this breadcrumb from the signal list, we have
@@ -775,23 +702,11 @@ void i915_request_unsubmit(struct i915_request *request)
unsigned long flags;
/* Will be called from irq-context when using foreign fences. */
- spin_lock_irqsave(&engine->active.lock, flags);
+ spin_lock_irqsave(&engine->sched_engine->lock, flags);
__i915_request_unsubmit(request);
- spin_unlock_irqrestore(&engine->active.lock, flags);
-}
-
-static void __cancel_request(struct i915_request *rq)
-{
- struct intel_engine_cs *engine = NULL;
-
- i915_request_active_engine(rq, &engine);
-
- if (engine && intel_engine_pulse(engine))
- intel_gt_handle_error(engine->gt, engine->mask, 0,
- "request cancellation by %s",
- current->comm);
+ spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
}
void i915_request_cancel(struct i915_request *rq, int error)
@@ -801,7 +716,7 @@ void i915_request_cancel(struct i915_request *rq, int error)
set_bit(I915_FENCE_FLAG_SENTINEL, &rq->fence.flags);
- __cancel_request(rq);
+ intel_context_cancel_request(rq->context, rq);
}
static int __i915_sw_fence_call
@@ -889,7 +804,7 @@ request_alloc_slow(struct intel_timeline *tl,
rq = list_first_entry(&tl->requests, typeof(*rq), link);
i915_request_retire(rq);
- rq = kmem_cache_alloc(global.slab_requests,
+ rq = kmem_cache_alloc(slab_requests,
gfp | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
if (rq)
return rq;
@@ -902,7 +817,7 @@ request_alloc_slow(struct intel_timeline *tl,
retire_requests(tl);
out:
- return kmem_cache_alloc(global.slab_requests, gfp);
+ return kmem_cache_alloc(slab_requests, gfp);
}
static void __i915_request_ctor(void *arg)
@@ -963,7 +878,7 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
*
* Do not use kmem_cache_zalloc() here!
*/
- rq = kmem_cache_alloc(global.slab_requests,
+ rq = kmem_cache_alloc(slab_requests,
gfp | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
if (unlikely(!rq)) {
rq = request_alloc_slow(tl, &ce->engine->request_pool, gfp);
@@ -973,7 +888,19 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
}
}
- rq->context = ce;
+ /*
+ * Hold a reference to the intel_context over life of an i915_request.
+ * Without this an i915_request can exist after the context has been
+ * destroyed (e.g. request retired, context closed, but user space holds
+ * a reference to the request from an out fence). In the case of GuC
+ * submission + virtual engine, the engine that the request references
+ * is also destroyed which can trigger bad pointer dref in fence ops
+ * (e.g. i915_fence_get_driver_name). We could likely change these
+ * functions to avoid touching the engine but let's just be safe and
+ * hold the intel_context reference. In execlist mode the request always
+ * eventually points to a physical engine so this isn't an issue.
+ */
+ rq->context = intel_context_get(ce);
rq->engine = ce->engine;
rq->ring = ce->ring;
rq->execution_mask = ce->engine->mask;
@@ -996,6 +923,8 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
rq->rcustate = get_state_synchronize_rcu(); /* acts as smp_mb() */
+ rq->guc_prio = GUC_PRIO_INIT;
+
/* We bump the ref for the fence chain */
i915_sw_fence_reinit(&i915_request_get(rq)->submit);
i915_sw_fence_reinit(&i915_request_get(rq)->semaphore);
@@ -1050,7 +979,8 @@ err_unwind:
GEM_BUG_ON(!list_empty(&rq->sched.waiters_list));
err_free:
- kmem_cache_free(global.slab_requests, rq);
+ intel_context_put(ce);
+ kmem_cache_free(slab_requests, rq);
err_unreserve:
intel_context_unpin(ce);
return ERR_PTR(ret);
@@ -1253,7 +1183,7 @@ emit_semaphore_wait(struct i915_request *to,
goto await_fence;
/* Only submit our spinner after the signaler is running! */
- if (__await_execution(to, from, NULL, gfp))
+ if (__await_execution(to, from, gfp))
goto await_fence;
if (__emit_semaphore_wait(to, from, from->fence.seqno))
@@ -1284,16 +1214,14 @@ static int intel_timeline_sync_set_start(struct intel_timeline *tl,
static int
__i915_request_await_execution(struct i915_request *to,
- struct i915_request *from,
- void (*hook)(struct i915_request *rq,
- struct dma_fence *signal))
+ struct i915_request *from)
{
int err;
GEM_BUG_ON(intel_context_is_barrier(from->context));
/* Submit both requests at the same time */
- err = __await_execution(to, from, hook, I915_FENCE_GFP);
+ err = __await_execution(to, from, I915_FENCE_GFP);
if (err)
return err;
@@ -1343,7 +1271,7 @@ __i915_request_await_execution(struct i915_request *to,
}
/* Couple the dependency tree for PI on this exposed to->fence */
- if (to->engine->schedule) {
+ if (to->engine->sched_engine->schedule) {
err = i915_sched_node_add_dependency(&to->sched,
&from->sched,
I915_DEPENDENCY_WEAK);
@@ -1406,9 +1334,7 @@ i915_request_await_external(struct i915_request *rq, struct dma_fence *fence)
int
i915_request_await_execution(struct i915_request *rq,
- struct dma_fence *fence,
- void (*hook)(struct i915_request *rq,
- struct dma_fence *signal))
+ struct dma_fence *fence)
{
struct dma_fence **child = &fence;
unsigned int nchild = 1;
@@ -1439,8 +1365,7 @@ i915_request_await_execution(struct i915_request *rq,
if (dma_fence_is_i915(fence))
ret = __i915_request_await_execution(rq,
- to_request(fence),
- hook);
+ to_request(fence));
else
ret = i915_request_await_external(rq, fence);
if (ret < 0)
@@ -1466,7 +1391,7 @@ await_request_submit(struct i915_request *to, struct i915_request *from)
&from->submit,
I915_FENCE_GFP);
else
- return __i915_request_await_execution(to, from, NULL);
+ return __i915_request_await_execution(to, from);
}
static int
@@ -1482,7 +1407,7 @@ i915_request_await_request(struct i915_request *to, struct i915_request *from)
return 0;
}
- if (to->engine->schedule) {
+ if (to->engine->sched_engine->schedule) {
ret = i915_sched_node_add_dependency(&to->sched,
&from->sched,
I915_DEPENDENCY_EXTERNAL);
@@ -1490,7 +1415,8 @@ i915_request_await_request(struct i915_request *to, struct i915_request *from)
return ret;
}
- if (is_power_of_2(to->execution_mask | READ_ONCE(from->execution_mask)))
+ if (!intel_engine_uses_guc(to->engine) &&
+ is_power_of_2(to->execution_mask | READ_ONCE(from->execution_mask)))
ret = await_request_submit(to, from);
else
ret = emit_semaphore_wait(to, from, I915_FENCE_GFP);
@@ -1649,6 +1575,8 @@ __i915_request_add_to_timeline(struct i915_request *rq)
prev = to_request(__i915_active_fence_set(&timeline->last_request,
&rq->fence));
if (prev && !__i915_request_is_complete(prev)) {
+ bool uses_guc = intel_engine_uses_guc(rq->engine);
+
/*
* The requests are supposed to be kept in order. However,
* we need to be wary in case the timeline->last_request
@@ -1659,7 +1587,9 @@ __i915_request_add_to_timeline(struct i915_request *rq)
i915_seqno_passed(prev->fence.seqno,
rq->fence.seqno));
- if (is_power_of_2(READ_ONCE(prev->engine)->mask | rq->engine->mask))
+ if ((!uses_guc &&
+ is_power_of_2(READ_ONCE(prev->engine)->mask | rq->engine->mask)) ||
+ (uses_guc && prev->context == rq->context))
i915_sw_fence_await_sw_fence(&rq->submit,
&prev->submit,
&rq->submitq);
@@ -1667,7 +1597,7 @@ __i915_request_add_to_timeline(struct i915_request *rq)
__i915_sw_fence_await_dma_fence(&rq->submit,
&prev->fence,
&rq->dmaq);
- if (rq->engine->schedule)
+ if (rq->engine->sched_engine->schedule)
__i915_sched_node_add_dependency(&rq->sched,
&prev->sched,
&rq->dep,
@@ -1739,8 +1669,8 @@ void __i915_request_queue(struct i915_request *rq,
* decide whether to preempt the entire chain so that it is ready to
* run at the earliest possible convenience.
*/
- if (attr && rq->engine->schedule)
- rq->engine->schedule(rq, attr);
+ if (attr && rq->engine->sched_engine->schedule)
+ rq->engine->sched_engine->schedule(rq, attr);
local_bh_disable();
__i915_request_queue_bh(rq);
@@ -2100,31 +2030,61 @@ void i915_request_show(struct drm_printer *m,
name);
}
-#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
-#include "selftests/mock_request.c"
-#include "selftests/i915_request.c"
-#endif
+static bool engine_match_ring(struct intel_engine_cs *engine, struct i915_request *rq)
+{
+ u32 ring = ENGINE_READ(engine, RING_START);
+
+ return ring == i915_ggtt_offset(rq->ring->vma);
+}
-static void i915_global_request_shrink(void)
+static bool match_ring(struct i915_request *rq)
{
- kmem_cache_shrink(global.slab_execute_cbs);
- kmem_cache_shrink(global.slab_requests);
+ struct intel_engine_cs *engine;
+ bool found;
+ int i;
+
+ if (!intel_engine_is_virtual(rq->engine))
+ return engine_match_ring(rq->engine, rq);
+
+ found = false;
+ i = 0;
+ while ((engine = intel_engine_get_sibling(rq->engine, i++))) {
+ found = engine_match_ring(engine, rq);
+ if (found)
+ break;
+ }
+
+ return found;
}
-static void i915_global_request_exit(void)
+enum i915_request_state i915_test_request_state(struct i915_request *rq)
{
- kmem_cache_destroy(global.slab_execute_cbs);
- kmem_cache_destroy(global.slab_requests);
+ if (i915_request_completed(rq))
+ return I915_REQUEST_COMPLETE;
+
+ if (!i915_request_started(rq))
+ return I915_REQUEST_PENDING;
+
+ if (match_ring(rq))
+ return I915_REQUEST_ACTIVE;
+
+ return I915_REQUEST_QUEUED;
}
-static struct i915_global_request global = { {
- .shrink = i915_global_request_shrink,
- .exit = i915_global_request_exit,
-} };
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/mock_request.c"
+#include "selftests/i915_request.c"
+#endif
+
+void i915_request_module_exit(void)
+{
+ kmem_cache_destroy(slab_execute_cbs);
+ kmem_cache_destroy(slab_requests);
+}
-int __init i915_global_request_init(void)
+int __init i915_request_module_init(void)
{
- global.slab_requests =
+ slab_requests =
kmem_cache_create("i915_request",
sizeof(struct i915_request),
__alignof__(struct i915_request),
@@ -2132,20 +2092,19 @@ int __init i915_global_request_init(void)
SLAB_RECLAIM_ACCOUNT |
SLAB_TYPESAFE_BY_RCU,
__i915_request_ctor);
- if (!global.slab_requests)
+ if (!slab_requests)
return -ENOMEM;
- global.slab_execute_cbs = KMEM_CACHE(execute_cb,
+ slab_execute_cbs = KMEM_CACHE(execute_cb,
SLAB_HWCACHE_ALIGN |
SLAB_RECLAIM_ACCOUNT |
SLAB_TYPESAFE_BY_RCU);
- if (!global.slab_execute_cbs)
+ if (!slab_execute_cbs)
goto err_requests;
- i915_global_register(&global.base);
return 0;
err_requests:
- kmem_cache_destroy(global.slab_requests);
+ kmem_cache_destroy(slab_requests);
return -ENOMEM;
}
diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h
index 270f6cd37650..1bc1349ba3c2 100644
--- a/drivers/gpu/drm/i915/i915_request.h
+++ b/drivers/gpu/drm/i915/i915_request.h
@@ -285,6 +285,23 @@ struct i915_request {
struct hrtimer timer;
} watchdog;
+ /*
+ * Requests may need to be stalled when using GuC submission waiting for
+ * certain GuC operations to complete. If that is the case, stalled
+ * requests are added to a per context list of stalled requests. The
+ * below list_head is the link in that list.
+ */
+ struct list_head guc_fence_link;
+
+ /**
+ * Priority level while the request is inflight. Differs from i915
+ * scheduler priority. See comment above
+ * I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP for details.
+ */
+#define GUC_PRIO_INIT 0xff
+#define GUC_PRIO_FINI 0xfe
+ u8 guc_prio;
+
I915_SELFTEST_DECLARE(struct {
struct list_head link;
unsigned long delay;
@@ -352,9 +369,7 @@ int i915_request_await_object(struct i915_request *to,
int i915_request_await_dma_fence(struct i915_request *rq,
struct dma_fence *fence);
int i915_request_await_execution(struct i915_request *rq,
- struct dma_fence *fence,
- void (*hook)(struct i915_request *rq,
- struct dma_fence *signal));
+ struct dma_fence *fence);
void i915_request_add(struct i915_request *rq);
@@ -613,7 +628,7 @@ i915_request_active_timeline(const struct i915_request *rq)
* this submission.
*/
return rcu_dereference_protected(rq->timeline,
- lockdep_is_held(&rq->engine->active.lock));
+ lockdep_is_held(&rq->engine->sched_engine->lock));
}
static inline u32
@@ -641,4 +656,19 @@ bool
i915_request_active_engine(struct i915_request *rq,
struct intel_engine_cs **active);
+void i915_request_notify_execute_cb_imm(struct i915_request *rq);
+
+enum i915_request_state {
+ I915_REQUEST_UNKNOWN = 0,
+ I915_REQUEST_COMPLETE,
+ I915_REQUEST_PENDING,
+ I915_REQUEST_QUEUED,
+ I915_REQUEST_ACTIVE,
+};
+
+enum i915_request_state i915_test_request_state(struct i915_request *rq);
+
+void i915_request_module_exit(void);
+int i915_request_module_init(void);
+
#endif /* I915_REQUEST_H */
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915/i915_scatterlist.c
index 69e9e6c3135e..4a6712dca838 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.c
+++ b/drivers/gpu/drm/i915/i915_scatterlist.c
@@ -6,6 +6,9 @@
#include "i915_scatterlist.h"
+#include "i915_buddy.h"
+#include "i915_ttm_buddy_manager.h"
+
#include <drm/drm_mm.h>
#include <linux/slab.h>
@@ -104,6 +107,83 @@ struct sg_table *i915_sg_from_mm_node(const struct drm_mm_node *node,
return st;
}
+/**
+ * i915_sg_from_buddy_resource - Create an sg_table from a struct
+ * i915_buddy_block list
+ * @res: The struct i915_ttm_buddy_resource.
+ * @region_start: An offset to add to the dma addresses of the sg list.
+ *
+ * Create a struct sg_table, initializing it from struct i915_buddy_block list,
+ * taking a maximum segment length into account, splitting into segments
+ * if necessary.
+ *
+ * Return: A pointer to a kmalloced struct sg_table on success, negative
+ * error code cast to an error pointer on failure.
+ */
+struct sg_table *i915_sg_from_buddy_resource(struct ttm_resource *res,
+ u64 region_start)
+{
+ struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
+ const u64 size = res->num_pages << PAGE_SHIFT;
+ const u64 max_segment = rounddown(UINT_MAX, PAGE_SIZE);
+ struct i915_buddy_mm *mm = bman_res->mm;
+ struct list_head *blocks = &bman_res->blocks;
+ struct i915_buddy_block *block;
+ struct scatterlist *sg;
+ struct sg_table *st;
+ resource_size_t prev_end;
+
+ GEM_BUG_ON(list_empty(blocks));
+
+ st = kmalloc(sizeof(*st), GFP_KERNEL);
+ if (!st)
+ return ERR_PTR(-ENOMEM);
+
+ if (sg_alloc_table(st, res->num_pages, GFP_KERNEL)) {
+ kfree(st);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ sg = st->sgl;
+ st->nents = 0;
+ prev_end = (resource_size_t)-1;
+
+ list_for_each_entry(block, blocks, link) {
+ u64 block_size, offset;
+
+ block_size = min_t(u64, size, i915_buddy_block_size(mm, block));
+ offset = i915_buddy_block_offset(block);
+
+ while (block_size) {
+ u64 len;
+
+ if (offset != prev_end || sg->length >= max_segment) {
+ if (st->nents)
+ sg = __sg_next(sg);
+
+ sg_dma_address(sg) = region_start + offset;
+ sg_dma_len(sg) = 0;
+ sg->length = 0;
+ st->nents++;
+ }
+
+ len = min(block_size, max_segment - sg->length);
+ sg->length += len;
+ sg_dma_len(sg) += len;
+
+ offset += len;
+ block_size -= len;
+
+ prev_end = offset;
+ }
+ }
+
+ sg_mark_end(sg);
+ i915_sg_trim(st);
+
+ return st;
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/scatterlist.c"
#endif
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h
index 5acca45ea981..b8bd5925b03f 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.h
+++ b/drivers/gpu/drm/i915/i915_scatterlist.h
@@ -14,6 +14,7 @@
#include "i915_gem.h"
struct drm_mm_node;
+struct ttm_resource;
/*
* Optimised SGL iterator for GEM objects
@@ -145,4 +146,8 @@ bool i915_sg_trim(struct sg_table *orig_st);
struct sg_table *i915_sg_from_mm_node(const struct drm_mm_node *node,
u64 region_start);
+
+struct sg_table *i915_sg_from_buddy_resource(struct ttm_resource *res,
+ u64 region_start);
+
#endif
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index efa638c3acc7..762127dd56c5 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -7,15 +7,11 @@
#include <linux/mutex.h>
#include "i915_drv.h"
-#include "i915_globals.h"
#include "i915_request.h"
#include "i915_scheduler.h"
-static struct i915_global_scheduler {
- struct i915_global base;
- struct kmem_cache *slab_dependencies;
- struct kmem_cache *slab_priorities;
-} global;
+static struct kmem_cache *slab_dependencies;
+static struct kmem_cache *slab_priorities;
static DEFINE_SPINLOCK(schedule_lock);
@@ -40,7 +36,7 @@ static inline struct i915_priolist *to_priolist(struct rb_node *rb)
return rb_entry(rb, struct i915_priolist, node);
}
-static void assert_priolists(struct intel_engine_execlists * const execlists)
+static void assert_priolists(struct i915_sched_engine * const sched_engine)
{
struct rb_node *rb;
long last_prio;
@@ -48,11 +44,11 @@ static void assert_priolists(struct intel_engine_execlists * const execlists)
if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
return;
- GEM_BUG_ON(rb_first_cached(&execlists->queue) !=
- rb_first(&execlists->queue.rb_root));
+ GEM_BUG_ON(rb_first_cached(&sched_engine->queue) !=
+ rb_first(&sched_engine->queue.rb_root));
last_prio = INT_MAX;
- for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
+ for (rb = rb_first_cached(&sched_engine->queue); rb; rb = rb_next(rb)) {
const struct i915_priolist *p = to_priolist(rb);
GEM_BUG_ON(p->priority > last_prio);
@@ -61,23 +57,22 @@ static void assert_priolists(struct intel_engine_execlists * const execlists)
}
struct list_head *
-i915_sched_lookup_priolist(struct intel_engine_cs *engine, int prio)
+i915_sched_lookup_priolist(struct i915_sched_engine *sched_engine, int prio)
{
- struct intel_engine_execlists * const execlists = &engine->execlists;
struct i915_priolist *p;
struct rb_node **parent, *rb;
bool first = true;
- lockdep_assert_held(&engine->active.lock);
- assert_priolists(execlists);
+ lockdep_assert_held(&sched_engine->lock);
+ assert_priolists(sched_engine);
- if (unlikely(execlists->no_priolist))
+ if (unlikely(sched_engine->no_priolist))
prio = I915_PRIORITY_NORMAL;
find_priolist:
/* most positive priority is scheduled first, equal priorities fifo */
rb = NULL;
- parent = &execlists->queue.rb_root.rb_node;
+ parent = &sched_engine->queue.rb_root.rb_node;
while (*parent) {
rb = *parent;
p = to_priolist(rb);
@@ -92,9 +87,9 @@ find_priolist:
}
if (prio == I915_PRIORITY_NORMAL) {
- p = &execlists->default_priolist;
+ p = &sched_engine->default_priolist;
} else {
- p = kmem_cache_alloc(global.slab_priorities, GFP_ATOMIC);
+ p = kmem_cache_alloc(slab_priorities, GFP_ATOMIC);
/* Convert an allocation failure to a priority bump */
if (unlikely(!p)) {
prio = I915_PRIORITY_NORMAL; /* recurses just once */
@@ -107,7 +102,7 @@ find_priolist:
* requests, so if userspace lied about their
* dependencies that reordering may be visible.
*/
- execlists->no_priolist = true;
+ sched_engine->no_priolist = true;
goto find_priolist;
}
}
@@ -116,27 +111,27 @@ find_priolist:
INIT_LIST_HEAD(&p->requests);
rb_link_node(&p->node, rb, parent);
- rb_insert_color_cached(&p->node, &execlists->queue, first);
+ rb_insert_color_cached(&p->node, &sched_engine->queue, first);
return &p->requests;
}
void __i915_priolist_free(struct i915_priolist *p)
{
- kmem_cache_free(global.slab_priorities, p);
+ kmem_cache_free(slab_priorities, p);
}
struct sched_cache {
struct list_head *priolist;
};
-static struct intel_engine_cs *
-sched_lock_engine(const struct i915_sched_node *node,
- struct intel_engine_cs *locked,
+static struct i915_sched_engine *
+lock_sched_engine(struct i915_sched_node *node,
+ struct i915_sched_engine *locked,
struct sched_cache *cache)
{
const struct i915_request *rq = node_to_request(node);
- struct intel_engine_cs *engine;
+ struct i915_sched_engine *sched_engine;
GEM_BUG_ON(!locked);
@@ -146,81 +141,22 @@ sched_lock_engine(const struct i915_sched_node *node,
* engine lock. The simple ploy we use is to take the lock then
* check that the rq still belongs to the newly locked engine.
*/
- while (locked != (engine = READ_ONCE(rq->engine))) {
- spin_unlock(&locked->active.lock);
+ while (locked != (sched_engine = READ_ONCE(rq->engine)->sched_engine)) {
+ spin_unlock(&locked->lock);
memset(cache, 0, sizeof(*cache));
- spin_lock(&engine->active.lock);
- locked = engine;
+ spin_lock(&sched_engine->lock);
+ locked = sched_engine;
}
- GEM_BUG_ON(locked != engine);
+ GEM_BUG_ON(locked != sched_engine);
return locked;
}
-static inline int rq_prio(const struct i915_request *rq)
-{
- return rq->sched.attr.priority;
-}
-
-static inline bool need_preempt(int prio, int active)
-{
- /*
- * Allow preemption of low -> normal -> high, but we do
- * not allow low priority tasks to preempt other low priority
- * tasks under the impression that latency for low priority
- * tasks does not matter (as much as background throughput),
- * so kiss.
- */
- return prio >= max(I915_PRIORITY_NORMAL, active);
-}
-
-static void kick_submission(struct intel_engine_cs *engine,
- const struct i915_request *rq,
- int prio)
-{
- const struct i915_request *inflight;
-
- /*
- * We only need to kick the tasklet once for the high priority
- * new context we add into the queue.
- */
- if (prio <= engine->execlists.queue_priority_hint)
- return;
-
- rcu_read_lock();
-
- /* Nothing currently active? We're overdue for a submission! */
- inflight = execlists_active(&engine->execlists);
- if (!inflight)
- goto unlock;
-
- /*
- * If we are already the currently executing context, don't
- * bother evaluating if we should preempt ourselves.
- */
- if (inflight->context == rq->context)
- goto unlock;
-
- ENGINE_TRACE(engine,
- "bumping queue-priority-hint:%d for rq:%llx:%lld, inflight:%llx:%lld prio %d\n",
- prio,
- rq->fence.context, rq->fence.seqno,
- inflight->fence.context, inflight->fence.seqno,
- inflight->sched.attr.priority);
-
- engine->execlists.queue_priority_hint = prio;
- if (need_preempt(prio, rq_prio(inflight)))
- tasklet_hi_schedule(&engine->execlists.tasklet);
-
-unlock:
- rcu_read_unlock();
-}
-
static void __i915_schedule(struct i915_sched_node *node,
const struct i915_sched_attr *attr)
{
const int prio = max(attr->priority, node->attr.priority);
- struct intel_engine_cs *engine;
+ struct i915_sched_engine *sched_engine;
struct i915_dependency *dep, *p;
struct i915_dependency stack;
struct sched_cache cache;
@@ -295,23 +231,31 @@ static void __i915_schedule(struct i915_sched_node *node,
}
memset(&cache, 0, sizeof(cache));
- engine = node_to_request(node)->engine;
- spin_lock(&engine->active.lock);
+ sched_engine = node_to_request(node)->engine->sched_engine;
+ spin_lock(&sched_engine->lock);
/* Fifo and depth-first replacement ensure our deps execute before us */
- engine = sched_lock_engine(node, engine, &cache);
+ sched_engine = lock_sched_engine(node, sched_engine, &cache);
list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) {
+ struct i915_request *from = container_of(dep->signaler,
+ struct i915_request,
+ sched);
INIT_LIST_HEAD(&dep->dfs_link);
node = dep->signaler;
- engine = sched_lock_engine(node, engine, &cache);
- lockdep_assert_held(&engine->active.lock);
+ sched_engine = lock_sched_engine(node, sched_engine, &cache);
+ lockdep_assert_held(&sched_engine->lock);
/* Recheck after acquiring the engine->timeline.lock */
if (prio <= node->attr.priority || node_signaled(node))
continue;
- GEM_BUG_ON(node_to_request(node)->engine != engine);
+ GEM_BUG_ON(node_to_request(node)->engine->sched_engine !=
+ sched_engine);
+
+ /* Must be called before changing the nodes priority */
+ if (sched_engine->bump_inflight_request_prio)
+ sched_engine->bump_inflight_request_prio(from, prio);
WRITE_ONCE(node->attr.priority, prio);
@@ -329,16 +273,17 @@ static void __i915_schedule(struct i915_sched_node *node,
if (i915_request_in_priority_queue(node_to_request(node))) {
if (!cache.priolist)
cache.priolist =
- i915_sched_lookup_priolist(engine,
+ i915_sched_lookup_priolist(sched_engine,
prio);
list_move_tail(&node->link, cache.priolist);
}
/* Defer (tasklet) submission until after all of our updates. */
- kick_submission(engine, node_to_request(node), prio);
+ if (sched_engine->kick_backend)
+ sched_engine->kick_backend(node_to_request(node), prio);
}
- spin_unlock(&engine->active.lock);
+ spin_unlock(&sched_engine->lock);
}
void i915_schedule(struct i915_request *rq, const struct i915_sched_attr *attr)
@@ -371,13 +316,13 @@ void i915_sched_node_reinit(struct i915_sched_node *node)
static struct i915_dependency *
i915_dependency_alloc(void)
{
- return kmem_cache_alloc(global.slab_dependencies, GFP_KERNEL);
+ return kmem_cache_alloc(slab_dependencies, GFP_KERNEL);
}
static void
i915_dependency_free(struct i915_dependency *dep)
{
- kmem_cache_free(global.slab_dependencies, dep);
+ kmem_cache_free(slab_dependencies, dep);
}
bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
@@ -489,39 +434,78 @@ void i915_request_show_with_schedule(struct drm_printer *m,
rcu_read_unlock();
}
-static void i915_global_scheduler_shrink(void)
+static void default_destroy(struct kref *kref)
+{
+ struct i915_sched_engine *sched_engine =
+ container_of(kref, typeof(*sched_engine), ref);
+
+ tasklet_kill(&sched_engine->tasklet); /* flush the callback */
+ kfree(sched_engine);
+}
+
+static bool default_disabled(struct i915_sched_engine *sched_engine)
{
- kmem_cache_shrink(global.slab_dependencies);
- kmem_cache_shrink(global.slab_priorities);
+ return false;
}
-static void i915_global_scheduler_exit(void)
+struct i915_sched_engine *
+i915_sched_engine_create(unsigned int subclass)
{
- kmem_cache_destroy(global.slab_dependencies);
- kmem_cache_destroy(global.slab_priorities);
+ struct i915_sched_engine *sched_engine;
+
+ sched_engine = kzalloc(sizeof(*sched_engine), GFP_KERNEL);
+ if (!sched_engine)
+ return NULL;
+
+ kref_init(&sched_engine->ref);
+
+ sched_engine->queue = RB_ROOT_CACHED;
+ sched_engine->queue_priority_hint = INT_MIN;
+ sched_engine->destroy = default_destroy;
+ sched_engine->disabled = default_disabled;
+
+ INIT_LIST_HEAD(&sched_engine->requests);
+ INIT_LIST_HEAD(&sched_engine->hold);
+
+ spin_lock_init(&sched_engine->lock);
+ lockdep_set_subclass(&sched_engine->lock, subclass);
+
+ /*
+ * Due to an interesting quirk in lockdep's internal debug tracking,
+ * after setting a subclass we must ensure the lock is used. Otherwise,
+ * nr_unused_locks is incremented once too often.
+ */
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ local_irq_disable();
+ lock_map_acquire(&sched_engine->lock.dep_map);
+ lock_map_release(&sched_engine->lock.dep_map);
+ local_irq_enable();
+#endif
+
+ return sched_engine;
}
-static struct i915_global_scheduler global = { {
- .shrink = i915_global_scheduler_shrink,
- .exit = i915_global_scheduler_exit,
-} };
+void i915_scheduler_module_exit(void)
+{
+ kmem_cache_destroy(slab_dependencies);
+ kmem_cache_destroy(slab_priorities);
+}
-int __init i915_global_scheduler_init(void)
+int __init i915_scheduler_module_init(void)
{
- global.slab_dependencies = KMEM_CACHE(i915_dependency,
+ slab_dependencies = KMEM_CACHE(i915_dependency,
SLAB_HWCACHE_ALIGN |
SLAB_TYPESAFE_BY_RCU);
- if (!global.slab_dependencies)
+ if (!slab_dependencies)
return -ENOMEM;
- global.slab_priorities = KMEM_CACHE(i915_priolist, 0);
- if (!global.slab_priorities)
+ slab_priorities = KMEM_CACHE(i915_priolist, 0);
+ if (!slab_priorities)
goto err_priorities;
- i915_global_register(&global.base);
return 0;
err_priorities:
- kmem_cache_destroy(global.slab_priorities);
+ kmem_cache_destroy(slab_priorities);
return -ENOMEM;
}
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 858a0938f47a..0b9b86af6c7f 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -39,7 +39,7 @@ void i915_schedule(struct i915_request *request,
const struct i915_sched_attr *attr);
struct list_head *
-i915_sched_lookup_priolist(struct intel_engine_cs *engine, int prio);
+i915_sched_lookup_priolist(struct i915_sched_engine *sched_engine, int prio);
void __i915_priolist_free(struct i915_priolist *p);
static inline void i915_priolist_free(struct i915_priolist *p)
@@ -48,9 +48,61 @@ static inline void i915_priolist_free(struct i915_priolist *p)
__i915_priolist_free(p);
}
+struct i915_sched_engine *
+i915_sched_engine_create(unsigned int subclass);
+
+static inline struct i915_sched_engine *
+i915_sched_engine_get(struct i915_sched_engine *sched_engine)
+{
+ kref_get(&sched_engine->ref);
+ return sched_engine;
+}
+
+static inline void
+i915_sched_engine_put(struct i915_sched_engine *sched_engine)
+{
+ kref_put(&sched_engine->ref, sched_engine->destroy);
+}
+
+static inline bool
+i915_sched_engine_is_empty(struct i915_sched_engine *sched_engine)
+{
+ return RB_EMPTY_ROOT(&sched_engine->queue.rb_root);
+}
+
+static inline void
+i915_sched_engine_reset_on_empty(struct i915_sched_engine *sched_engine)
+{
+ if (i915_sched_engine_is_empty(sched_engine))
+ sched_engine->no_priolist = false;
+}
+
+static inline void
+i915_sched_engine_active_lock_bh(struct i915_sched_engine *sched_engine)
+{
+ local_bh_disable(); /* prevent local softirq and lock recursion */
+ tasklet_lock(&sched_engine->tasklet);
+}
+
+static inline void
+i915_sched_engine_active_unlock_bh(struct i915_sched_engine *sched_engine)
+{
+ tasklet_unlock(&sched_engine->tasklet);
+ local_bh_enable(); /* restore softirq, and kick ksoftirqd! */
+}
+
void i915_request_show_with_schedule(struct drm_printer *m,
const struct i915_request *rq,
const char *prefix,
int indent);
+static inline bool
+i915_sched_engine_disabled(struct i915_sched_engine *sched_engine)
+{
+ return sched_engine->disabled(sched_engine);
+}
+
+void i915_scheduler_module_exit(void);
+int i915_scheduler_module_init(void);
+
#endif /* _I915_SCHEDULER_H_ */
diff --git a/drivers/gpu/drm/i915/i915_scheduler_types.h b/drivers/gpu/drm/i915/i915_scheduler_types.h
index 343ed44d5ed4..b0a1b58c7893 100644
--- a/drivers/gpu/drm/i915/i915_scheduler_types.h
+++ b/drivers/gpu/drm/i915/i915_scheduler_types.h
@@ -91,4 +91,115 @@ struct i915_dependency {
&(rq__)->sched.signalers_list, \
signal_link)
+/**
+ * struct i915_sched_engine - scheduler engine
+ *
+ * A schedule engine represents a submission queue with different priority
+ * bands. It contains all the common state (relative to the backend) to queue,
+ * track, and submit a request.
+ *
+ * This object at the moment is quite i915 specific but will transition into a
+ * container for the drm_gpu_scheduler plus a few other variables once the i915
+ * is integrated with the DRM scheduler.
+ */
+struct i915_sched_engine {
+ /**
+ * @ref: reference count of schedule engine object
+ */
+ struct kref ref;
+
+ /**
+ * @lock: protects requests in priority lists, requests, hold and
+ * tasklet while running
+ */
+ spinlock_t lock;
+
+ /**
+ * @requests: list of requests inflight on this schedule engine
+ */
+ struct list_head requests;
+
+ /**
+ * @hold: list of ready requests, but on hold
+ */
+ struct list_head hold;
+
+ /**
+ * @tasklet: softirq tasklet for submission
+ */
+ struct tasklet_struct tasklet;
+
+ /**
+ * @default_priolist: priority list for I915_PRIORITY_NORMAL
+ */
+ struct i915_priolist default_priolist;
+
+ /**
+ * @queue_priority_hint: Highest pending priority.
+ *
+ * When we add requests into the queue, or adjust the priority of
+ * executing requests, we compute the maximum priority of those
+ * pending requests. We can then use this value to determine if
+ * we need to preempt the executing requests to service the queue.
+ * However, since the we may have recorded the priority of an inflight
+ * request we wanted to preempt but since completed, at the time of
+ * dequeuing the priority hint may no longer may match the highest
+ * available request priority.
+ */
+ int queue_priority_hint;
+
+ /**
+ * @queue: queue of requests, in priority lists
+ */
+ struct rb_root_cached queue;
+
+ /**
+ * @no_priolist: priority lists disabled
+ */
+ bool no_priolist;
+
+ /**
+ * @private_data: private data of the submission backend
+ */
+ void *private_data;
+
+ /**
+ * @destroy: destroy schedule engine / cleanup in backend
+ */
+ void (*destroy)(struct kref *kref);
+
+ /**
+ * @disabled: check if backend has disabled submission
+ */
+ bool (*disabled)(struct i915_sched_engine *sched_engine);
+
+ /**
+ * @kick_backend: kick backend after a request's priority has changed
+ */
+ void (*kick_backend)(const struct i915_request *rq,
+ int prio);
+
+ /**
+ * @bump_inflight_request_prio: update priority of an inflight request
+ */
+ void (*bump_inflight_request_prio)(struct i915_request *rq,
+ int prio);
+
+ /**
+ * @retire_inflight_request_prio: indicate request is retired to
+ * priority tracking
+ */
+ void (*retire_inflight_request_prio)(struct i915_request *rq);
+
+ /**
+ * @schedule: adjust priority of request
+ *
+ * Call when the priority on a request has changed and it and its
+ * dependencies may need rescheduling. Note the request itself may
+ * not be ready to run!
+ */
+ void (*schedule)(struct i915_request *request,
+ const struct i915_sched_attr *attr);
+};
+
#endif /* _I915_SCHEDULER_TYPES_H_ */
diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.c b/drivers/gpu/drm/i915/i915_sw_fence_work.c
index a3a81bb8f2c3..5b33ef23d54c 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence_work.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence_work.c
@@ -16,11 +16,8 @@ static void fence_complete(struct dma_fence_work *f)
static void fence_work(struct work_struct *work)
{
struct dma_fence_work *f = container_of(work, typeof(*f), work);
- int err;
- err = f->ops->work(f);
- if (err)
- dma_fence_set_error(&f->dma, err);
+ f->ops->work(f);
fence_complete(f);
dma_fence_put(&f->dma);
diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.h b/drivers/gpu/drm/i915/i915_sw_fence_work.h
index 2c409f11c5c5..d56806918d13 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence_work.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence_work.h
@@ -17,7 +17,7 @@ struct dma_fence_work;
struct dma_fence_work_ops {
const char *name;
- int (*work)(struct dma_fence_work *f);
+ void (*work)(struct dma_fence_work *f);
void (*release)(struct dma_fence_work *f);
};
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 873bf996ceb5..cdf0e9c6fd73 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -272,7 +272,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
struct intel_rps *rps = &i915->gt.rps;
- return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->cur_freq));
+ return sysfs_emit(buf, "%d\n", intel_rps_get_requested_frequency(rps));
}
static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -326,9 +326,10 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
{
struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
- struct intel_rps *rps = &dev_priv->gt.rps;
+ struct intel_gt *gt = &dev_priv->gt;
+ struct intel_rps *rps = &gt->rps;
- return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->max_freq_softlimit));
+ return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps));
}
static ssize_t gt_max_freq_mhz_store(struct device *kdev,
@@ -336,7 +337,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
const char *buf, size_t count)
{
struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
- struct intel_rps *rps = &dev_priv->gt.rps;
+ struct intel_gt *gt = &dev_priv->gt;
+ struct intel_rps *rps = &gt->rps;
ssize_t ret;
u32 val;
@@ -344,53 +346,26 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
if (ret)
return ret;
- mutex_lock(&rps->lock);
-
- val = intel_freq_opcode(rps, val);
- if (val < rps->min_freq ||
- val > rps->max_freq ||
- val < rps->min_freq_softlimit) {
- ret = -EINVAL;
- goto unlock;
- }
-
- if (val > rps->rp0_freq)
- DRM_DEBUG("User requested overclocking to %d\n",
- intel_gpu_freq(rps, val));
-
- rps->max_freq_softlimit = val;
-
- val = clamp_t(int, rps->cur_freq,
- rps->min_freq_softlimit,
- rps->max_freq_softlimit);
-
- /*
- * We still need *_set_rps to process the new max_delay and
- * update the interrupt limits and PMINTRMSK even though
- * frequency request may be unchanged.
- */
- intel_rps_set(rps, val);
-
-unlock:
- mutex_unlock(&rps->lock);
+ ret = intel_rps_set_max_frequency(rps, val);
return ret ?: count;
}
static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
{
- struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
- struct intel_rps *rps = &dev_priv->gt.rps;
+ struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
+ struct intel_gt *gt = &i915->gt;
+ struct intel_rps *rps = &gt->rps;
- return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->min_freq_softlimit));
+ return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps));
}
static ssize_t gt_min_freq_mhz_store(struct device *kdev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
- struct intel_rps *rps = &dev_priv->gt.rps;
+ struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
+ struct intel_rps *rps = &i915->gt.rps;
ssize_t ret;
u32 val;
@@ -398,31 +373,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
if (ret)
return ret;
- mutex_lock(&rps->lock);
-
- val = intel_freq_opcode(rps, val);
- if (val < rps->min_freq ||
- val > rps->max_freq ||
- val > rps->max_freq_softlimit) {
- ret = -EINVAL;
- goto unlock;
- }
-
- rps->min_freq_softlimit = val;
-
- val = clamp_t(int, rps->cur_freq,
- rps->min_freq_softlimit,
- rps->max_freq_softlimit);
-
- /*
- * We still need *_set_rps to process the new min_delay and
- * update the interrupt limits and PMINTRMSK even though
- * frequency request may be unchanged.
- */
- intel_rps_set(rps, val);
-
-unlock:
- mutex_unlock(&rps->lock);
+ ret = intel_rps_set_min_frequency(rps, val);
return ret ?: count;
}
@@ -448,11 +399,11 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
u32 val;
if (attr == &dev_attr_gt_RP0_freq_mhz)
- val = intel_gpu_freq(rps, rps->rp0_freq);
+ val = intel_rps_get_rp0_frequency(rps);
else if (attr == &dev_attr_gt_RP1_freq_mhz)
- val = intel_gpu_freq(rps, rps->rp1_freq);
+ val = intel_rps_get_rp1_frequency(rps);
else if (attr == &dev_attr_gt_RPn_freq_mhz)
- val = intel_gpu_freq(rps, rps->min_freq);
+ val = intel_rps_get_rpn_frequency(rps);
else
BUG();
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 6778ad2a14a4..806ad688274b 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -794,30 +794,40 @@ DECLARE_EVENT_CLASS(i915_request,
TP_STRUCT__entry(
__field(u32, dev)
__field(u64, ctx)
+ __field(u32, guc_id)
__field(u16, class)
__field(u16, instance)
__field(u32, seqno)
+ __field(u32, tail)
),
TP_fast_assign(
__entry->dev = rq->engine->i915->drm.primary->index;
__entry->class = rq->engine->uabi_class;
__entry->instance = rq->engine->uabi_instance;
+ __entry->guc_id = rq->context->guc_id;
__entry->ctx = rq->fence.context;
__entry->seqno = rq->fence.seqno;
+ __entry->tail = rq->tail;
),
- TP_printk("dev=%u, engine=%u:%u, ctx=%llu, seqno=%u",
+ TP_printk("dev=%u, engine=%u:%u, guc_id=%u, ctx=%llu, seqno=%u, tail=%u",
__entry->dev, __entry->class, __entry->instance,
- __entry->ctx, __entry->seqno)
+ __entry->guc_id, __entry->ctx, __entry->seqno,
+ __entry->tail)
);
DEFINE_EVENT(i915_request, i915_request_add,
- TP_PROTO(struct i915_request *rq),
- TP_ARGS(rq)
+ TP_PROTO(struct i915_request *rq),
+ TP_ARGS(rq)
);
#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS)
+DEFINE_EVENT(i915_request, i915_request_guc_submit,
+ TP_PROTO(struct i915_request *rq),
+ TP_ARGS(rq)
+);
+
DEFINE_EVENT(i915_request, i915_request_submit,
TP_PROTO(struct i915_request *rq),
TP_ARGS(rq)
@@ -885,9 +895,117 @@ TRACE_EVENT(i915_request_out,
__entry->ctx, __entry->seqno, __entry->completed)
);
+DECLARE_EVENT_CLASS(intel_context,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce),
+
+ TP_STRUCT__entry(
+ __field(u32, guc_id)
+ __field(int, pin_count)
+ __field(u32, sched_state)
+ __field(u32, guc_sched_state_no_lock)
+ __field(u8, guc_prio)
+ ),
+
+ TP_fast_assign(
+ __entry->guc_id = ce->guc_id;
+ __entry->pin_count = atomic_read(&ce->pin_count);
+ __entry->sched_state = ce->guc_state.sched_state;
+ __entry->guc_sched_state_no_lock =
+ atomic_read(&ce->guc_sched_state_no_lock);
+ __entry->guc_prio = ce->guc_prio;
+ ),
+
+ TP_printk("guc_id=%d, pin_count=%d sched_state=0x%x,0x%x, guc_prio=%u",
+ __entry->guc_id, __entry->pin_count,
+ __entry->sched_state,
+ __entry->guc_sched_state_no_lock,
+ __entry->guc_prio)
+);
+
+DEFINE_EVENT(intel_context, intel_context_set_prio,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_reset,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_ban,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_register,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_deregister,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_deregister_done,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_sched_enable,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_sched_disable,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_sched_done,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_create,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_fence_release,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_free,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_steal_guc_id,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_do_pin,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
+DEFINE_EVENT(intel_context, intel_context_do_unpin,
+ TP_PROTO(struct intel_context *ce),
+ TP_ARGS(ce)
+);
+
#else
#if !defined(TRACE_HEADER_MULTI_READ)
static inline void
+trace_i915_request_guc_submit(struct i915_request *rq)
+{
+}
+
+static inline void
trace_i915_request_submit(struct i915_request *rq)
{
}
@@ -906,6 +1024,81 @@ static inline void
trace_i915_request_out(struct i915_request *rq)
{
}
+
+static inline void
+trace_intel_context_set_prio(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_reset(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_ban(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_register(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_deregister(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_deregister_done(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_sched_enable(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_sched_disable(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_sched_done(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_create(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_fence_release(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_free(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_steal_guc_id(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_do_pin(struct intel_context *ce)
+{
+}
+
+static inline void
+trace_intel_context_do_unpin(struct intel_context *ce)
+{
+}
#endif
#endif
diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
new file mode 100644
index 000000000000..6877362f6b85
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <linux/slab.h>
+
+#include <drm/ttm/ttm_bo_driver.h>
+#include <drm/ttm/ttm_placement.h>
+
+#include "i915_ttm_buddy_manager.h"
+
+#include "i915_buddy.h"
+#include "i915_gem.h"
+
+struct i915_ttm_buddy_manager {
+ struct ttm_resource_manager manager;
+ struct i915_buddy_mm mm;
+ struct list_head reserved;
+ struct mutex lock;
+ u64 default_page_size;
+};
+
+static struct i915_ttm_buddy_manager *
+to_buddy_manager(struct ttm_resource_manager *man)
+{
+ return container_of(man, struct i915_ttm_buddy_manager, manager);
+}
+
+static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
+ struct ttm_buffer_object *bo,
+ const struct ttm_place *place,
+ struct ttm_resource **res)
+{
+ struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
+ struct i915_ttm_buddy_resource *bman_res;
+ struct i915_buddy_mm *mm = &bman->mm;
+ unsigned long n_pages;
+ unsigned int min_order;
+ u64 min_page_size;
+ u64 size;
+ int err;
+
+ GEM_BUG_ON(place->fpfn || place->lpfn);
+
+ bman_res = kzalloc(sizeof(*bman_res), GFP_KERNEL);
+ if (!bman_res)
+ return -ENOMEM;
+
+ ttm_resource_init(bo, place, &bman_res->base);
+ INIT_LIST_HEAD(&bman_res->blocks);
+ bman_res->mm = mm;
+
+ GEM_BUG_ON(!bman_res->base.num_pages);
+ size = bman_res->base.num_pages << PAGE_SHIFT;
+
+ min_page_size = bman->default_page_size;
+ if (bo->page_alignment)
+ min_page_size = bo->page_alignment << PAGE_SHIFT;
+
+ GEM_BUG_ON(min_page_size < mm->chunk_size);
+ min_order = ilog2(min_page_size) - ilog2(mm->chunk_size);
+ if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
+ size = roundup_pow_of_two(size);
+ min_order = ilog2(size) - ilog2(mm->chunk_size);
+ }
+
+ if (size > mm->size) {
+ err = -E2BIG;
+ goto err_free_res;
+ }
+
+ n_pages = size >> ilog2(mm->chunk_size);
+
+ do {
+ struct i915_buddy_block *block;
+ unsigned int order;
+
+ order = fls(n_pages) - 1;
+ GEM_BUG_ON(order > mm->max_order);
+ GEM_BUG_ON(order < min_order);
+
+ do {
+ mutex_lock(&bman->lock);
+ block = i915_buddy_alloc(mm, order);
+ mutex_unlock(&bman->lock);
+ if (!IS_ERR(block))
+ break;
+
+ if (order-- == min_order) {
+ err = -ENOSPC;
+ goto err_free_blocks;
+ }
+ } while (1);
+
+ n_pages -= BIT(order);
+
+ list_add_tail(&block->link, &bman_res->blocks);
+
+ if (!n_pages)
+ break;
+ } while (1);
+
+ *res = &bman_res->base;
+ return 0;
+
+err_free_blocks:
+ mutex_lock(&bman->lock);
+ i915_buddy_free_list(mm, &bman_res->blocks);
+ mutex_unlock(&bman->lock);
+err_free_res:
+ kfree(bman_res);
+ return err;
+}
+
+static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man,
+ struct ttm_resource *res)
+{
+ struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
+ struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
+
+ mutex_lock(&bman->lock);
+ i915_buddy_free_list(&bman->mm, &bman_res->blocks);
+ mutex_unlock(&bman->lock);
+
+ kfree(bman_res);
+}
+
+static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = {
+ .alloc = i915_ttm_buddy_man_alloc,
+ .free = i915_ttm_buddy_man_free,
+};
+
+
+/**
+ * i915_ttm_buddy_man_init - Setup buddy allocator based ttm manager
+ * @bdev: The ttm device
+ * @type: Memory type we want to manage
+ * @use_tt: Set use_tt for the manager
+ * @size: The size in bytes to manage
+ * @default_page_size: The default minimum page size in bytes for allocations,
+ * this must be at least as large as @chunk_size, and can be overridden by
+ * setting the BO page_alignment, to be larger or smaller as needed.
+ * @chunk_size: The minimum page size in bytes for our allocations i.e
+ * order-zero
+ *
+ * Note that the starting address is assumed to be zero here, since this
+ * simplifies keeping the property where allocated blocks having natural
+ * power-of-two alignment. So long as the real starting address is some large
+ * power-of-two, or naturally start from zero, then this should be fine. Also
+ * the &i915_ttm_buddy_man_reserve interface can be used to preserve alignment
+ * if say there is some unusable range from the start of the region. We can
+ * revisit this in the future and make the interface accept an actual starting
+ * offset and let it take care of the rest.
+ *
+ * Note that if the @size is not aligned to the @chunk_size then we perform the
+ * required rounding to get the usable size. The final size in pages can be
+ * taken from &ttm_resource_manager.size.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int i915_ttm_buddy_man_init(struct ttm_device *bdev,
+ unsigned int type, bool use_tt,
+ u64 size, u64 default_page_size,
+ u64 chunk_size)
+{
+ struct ttm_resource_manager *man;
+ struct i915_ttm_buddy_manager *bman;
+ int err;
+
+ bman = kzalloc(sizeof(*bman), GFP_KERNEL);
+ if (!bman)
+ return -ENOMEM;
+
+ err = i915_buddy_init(&bman->mm, size, chunk_size);
+ if (err)
+ goto err_free_bman;
+
+ mutex_init(&bman->lock);
+ INIT_LIST_HEAD(&bman->reserved);
+ GEM_BUG_ON(default_page_size < chunk_size);
+ bman->default_page_size = default_page_size;
+
+ man = &bman->manager;
+ man->use_tt = use_tt;
+ man->func = &i915_ttm_buddy_manager_func;
+ ttm_resource_manager_init(man, bman->mm.size >> PAGE_SHIFT);
+
+ ttm_resource_manager_set_used(man, true);
+ ttm_set_driver_manager(bdev, type, man);
+
+ return 0;
+
+err_free_bman:
+ kfree(bman);
+ return err;
+}
+
+/**
+ * i915_ttm_buddy_man_fini - Destroy the buddy allocator ttm manager
+ * @bdev: The ttm device
+ * @type: Memory type we want to manage
+ *
+ * Note that if we reserved anything with &i915_ttm_buddy_man_reserve, this will
+ * also be freed for us here.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type)
+{
+ struct ttm_resource_manager *man = ttm_manager_type(bdev, type);
+ struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
+ struct i915_buddy_mm *mm = &bman->mm;
+ int ret;
+
+ ttm_resource_manager_set_used(man, false);
+
+ ret = ttm_resource_manager_evict_all(bdev, man);
+ if (ret)
+ return ret;
+
+ ttm_set_driver_manager(bdev, type, NULL);
+
+ mutex_lock(&bman->lock);
+ i915_buddy_free_list(mm, &bman->reserved);
+ i915_buddy_fini(mm);
+ mutex_unlock(&bman->lock);
+
+ ttm_resource_manager_cleanup(man);
+ kfree(bman);
+
+ return 0;
+}
+
+/**
+ * i915_ttm_buddy_man_reserve - Reserve address range
+ * @man: The buddy allocator ttm manager
+ * @start: The offset in bytes, where the region start is assumed to be zero
+ * @size: The size in bytes
+ *
+ * Note that the starting address for the region is always assumed to be zero.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man,
+ u64 start, u64 size)
+{
+ struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
+ struct i915_buddy_mm *mm = &bman->mm;
+ int ret;
+
+ mutex_lock(&bman->lock);
+ ret = i915_buddy_alloc_range(mm, &bman->reserved, start, size);
+ mutex_unlock(&bman->lock);
+
+ return ret;
+}
+
diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
new file mode 100644
index 000000000000..0722d33f3e14
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef __I915_TTM_BUDDY_MANAGER_H__
+#define __I915_TTM_BUDDY_MANAGER_H__
+
+#include <linux/list.h>
+#include <linux/types.h>
+
+#include <drm/ttm/ttm_resource.h>
+
+struct ttm_device;
+struct ttm_resource_manager;
+struct i915_buddy_mm;
+
+/**
+ * struct i915_ttm_buddy_resource
+ *
+ * @base: struct ttm_resource base class we extend
+ * @blocks: the list of struct i915_buddy_block for this resource/allocation
+ * @mm: the struct i915_buddy_mm for this resource
+ *
+ * Extends the struct ttm_resource to manage an address space allocation with
+ * one or more struct i915_buddy_block.
+ */
+struct i915_ttm_buddy_resource {
+ struct ttm_resource base;
+ struct list_head blocks;
+ struct i915_buddy_mm *mm;
+};
+
+/**
+ * to_ttm_buddy_resource
+ *
+ * @res: the resource to upcast
+ *
+ * Upcast the struct ttm_resource object into a struct i915_ttm_buddy_resource.
+ */
+static inline struct i915_ttm_buddy_resource *
+to_ttm_buddy_resource(struct ttm_resource *res)
+{
+ return container_of(res, struct i915_ttm_buddy_resource, base);
+}
+
+int i915_ttm_buddy_man_init(struct ttm_device *bdev,
+ unsigned type, bool use_tt,
+ u64 size, u64 default_page_size, u64 chunk_size);
+int i915_ttm_buddy_man_fini(struct ttm_device *bdev,
+ unsigned int type);
+
+int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man,
+ u64 start, u64 size);
+
+#endif
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 0f227f28b280..4b7fc4647e46 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -34,24 +34,20 @@
#include "gt/intel_gt_requests.h"
#include "i915_drv.h"
-#include "i915_globals.h"
#include "i915_sw_fence_work.h"
#include "i915_trace.h"
#include "i915_vma.h"
-static struct i915_global_vma {
- struct i915_global base;
- struct kmem_cache *slab_vmas;
-} global;
+static struct kmem_cache *slab_vmas;
struct i915_vma *i915_vma_alloc(void)
{
- return kmem_cache_zalloc(global.slab_vmas, GFP_KERNEL);
+ return kmem_cache_zalloc(slab_vmas, GFP_KERNEL);
}
void i915_vma_free(struct i915_vma *vma)
{
- return kmem_cache_free(global.slab_vmas, vma);
+ return kmem_cache_free(slab_vmas, vma);
}
#if IS_ENABLED(CONFIG_DRM_I915_ERRLOG_GEM) && IS_ENABLED(CONFIG_DRM_DEBUG_MM)
@@ -300,14 +296,13 @@ struct i915_vma_work {
unsigned int flags;
};
-static int __vma_bind(struct dma_fence_work *work)
+static void __vma_bind(struct dma_fence_work *work)
{
struct i915_vma_work *vw = container_of(work, typeof(*vw), base);
struct i915_vma *vma = vw->vma;
vma->ops->bind_vma(vw->vm, &vw->stash,
vma, vw->cache_level, vw->flags);
- return 0;
}
static void __vma_release(struct dma_fence_work *work)
@@ -1415,27 +1410,16 @@ void i915_vma_make_purgeable(struct i915_vma *vma)
#include "selftests/i915_vma.c"
#endif
-static void i915_global_vma_shrink(void)
+void i915_vma_module_exit(void)
{
- kmem_cache_shrink(global.slab_vmas);
+ kmem_cache_destroy(slab_vmas);
}
-static void i915_global_vma_exit(void)
-{
- kmem_cache_destroy(global.slab_vmas);
-}
-
-static struct i915_global_vma global = { {
- .shrink = i915_global_vma_shrink,
- .exit = i915_global_vma_exit,
-} };
-
-int __init i915_global_vma_init(void)
+int __init i915_vma_module_init(void)
{
- global.slab_vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN);
- if (!global.slab_vmas)
+ slab_vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN);
+ if (!slab_vmas)
return -ENOMEM;
- i915_global_register(&global.base);
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
index eca452a9851f..ed69f66c7ab0 100644
--- a/drivers/gpu/drm/i915/i915_vma.h
+++ b/drivers/gpu/drm/i915/i915_vma.h
@@ -426,4 +426,7 @@ static inline int i915_vma_sync(struct i915_vma *vma)
return i915_active_wait(&vma->active);
}
+void i915_vma_module_exit(void);
+int i915_vma_module_init(void);
+
#endif
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c
index e0a10f36acc1..305facedd284 100644
--- a/drivers/gpu/drm/i915/intel_device_info.c
+++ b/drivers/gpu/drm/i915/intel_device_info.c
@@ -59,7 +59,6 @@ static const char * const platform_names[] = {
PLATFORM_NAME(GEMINILAKE),
PLATFORM_NAME(COFFEELAKE),
PLATFORM_NAME(COMETLAKE),
- PLATFORM_NAME(CANNONLAKE),
PLATFORM_NAME(ICELAKE),
PLATFORM_NAME(ELKHARTLAKE),
PLATFORM_NAME(JASPERLAKE),
@@ -68,6 +67,8 @@ static const char * const platform_names[] = {
PLATFORM_NAME(DG1),
PLATFORM_NAME(ALDERLAKE_S),
PLATFORM_NAME(ALDERLAKE_P),
+ PLATFORM_NAME(XEHPSDV),
+ PLATFORM_NAME(DG2),
};
#undef PLATFORM_NAME
@@ -96,9 +97,17 @@ static const char *iommu_name(void)
void intel_device_info_print_static(const struct intel_device_info *info,
struct drm_printer *p)
{
- drm_printf(p, "graphics_ver: %u\n", info->graphics_ver);
- drm_printf(p, "media_ver: %u\n", info->media_ver);
- drm_printf(p, "display_ver: %u\n", info->display.ver);
+ if (info->graphics_rel)
+ drm_printf(p, "graphics version: %u.%02u\n", info->graphics_ver, info->graphics_rel);
+ else
+ drm_printf(p, "graphics version: %u\n", info->graphics_ver);
+
+ if (info->media_rel)
+ drm_printf(p, "media version: %u.%02u\n", info->media_ver, info->media_rel);
+ else
+ drm_printf(p, "media version: %u\n", info->media_ver);
+
+ drm_printf(p, "display version: %u\n", info->display.ver);
drm_printf(p, "gt: %d\n", info->gt);
drm_printf(p, "iommu: %s\n", iommu_name());
drm_printf(p, "memory-regions: %x\n", info->memory_regions);
@@ -165,7 +174,6 @@ static const u16 subplatform_ulx_ids[] = {
};
static const u16 subplatform_portf_ids[] = {
- INTEL_CNL_PORT_F_IDS(0),
INTEL_ICL_PORT_F_IDS(0),
};
@@ -253,14 +261,14 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
struct intel_runtime_info *runtime = RUNTIME_INFO(dev_priv);
enum pipe pipe;
- /* Wa_14011765242: adl-s A0 */
- if (IS_ADLS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ /* Wa_14011765242: adl-s A0,A1 */
+ if (IS_ADLS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A2))
for_each_pipe(dev_priv, pipe)
runtime->num_scalers[pipe] = 0;
- else if (GRAPHICS_VER(dev_priv) >= 10) {
+ else if (DISPLAY_VER(dev_priv) >= 11) {
for_each_pipe(dev_priv, pipe)
runtime->num_scalers[pipe] = 2;
- } else if (GRAPHICS_VER(dev_priv) == 9) {
+ } else if (DISPLAY_VER(dev_priv) >= 9) {
runtime->num_scalers[PIPE_A] = 2;
runtime->num_scalers[PIPE_B] = 2;
runtime->num_scalers[PIPE_C] = 1;
@@ -271,10 +279,10 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
for_each_pipe(dev_priv, pipe)
runtime->num_sprites[pipe] = 4;
- else if (GRAPHICS_VER(dev_priv) >= 11)
+ else if (DISPLAY_VER(dev_priv) >= 11)
for_each_pipe(dev_priv, pipe)
runtime->num_sprites[pipe] = 6;
- else if (GRAPHICS_VER(dev_priv) == 10 || IS_GEMINILAKE(dev_priv))
+ else if (DISPLAY_VER(dev_priv) == 10)
for_each_pipe(dev_priv, pipe)
runtime->num_sprites[pipe] = 3;
else if (IS_BROXTON(dev_priv)) {
@@ -293,7 +301,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
for_each_pipe(dev_priv, pipe)
runtime->num_sprites[pipe] = 2;
- } else if (GRAPHICS_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) {
+ } else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) {
for_each_pipe(dev_priv, pipe)
runtime->num_sprites[pipe] = 1;
}
@@ -357,7 +365,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
info->display.has_dmc = 0;
if (DISPLAY_VER(dev_priv) >= 10 &&
- (dfsm & CNL_DFSM_DISPLAY_DSC_DISABLE))
+ (dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE))
info->display.has_dsc = 0;
}
diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h
index b326aff65cd6..d328bb95c49b 100644
--- a/drivers/gpu/drm/i915/intel_device_info.h
+++ b/drivers/gpu/drm/i915/intel_device_info.h
@@ -76,8 +76,6 @@ enum intel_platform {
INTEL_GEMINILAKE,
INTEL_COFFEELAKE,
INTEL_COMETLAKE,
- /* gen10 */
- INTEL_CANNONLAKE,
/* gen11 */
INTEL_ICELAKE,
INTEL_ELKHARTLAKE,
@@ -88,6 +86,8 @@ enum intel_platform {
INTEL_DG1,
INTEL_ALDERLAKE_S,
INTEL_ALDERLAKE_P,
+ INTEL_XEHPSDV,
+ INTEL_DG2,
INTEL_MAX_PLATFORMS
};
@@ -103,9 +103,13 @@ enum intel_platform {
#define INTEL_SUBPLATFORM_ULT (0)
#define INTEL_SUBPLATFORM_ULX (1)
-/* CNL/ICL */
+/* ICL */
#define INTEL_SUBPLATFORM_PORTF (0)
+/* DG2 */
+#define INTEL_SUBPLATFORM_G10 0
+#define INTEL_SUBPLATFORM_G11 1
+
enum intel_ppgtt_type {
INTEL_PPGTT_NONE = I915_GEM_PPGTT_NONE,
INTEL_PPGTT_ALIASING = I915_GEM_PPGTT_ALIASING,
@@ -127,7 +131,7 @@ enum intel_ppgtt_type {
func(has_llc); \
func(has_logical_ring_contexts); \
func(has_logical_ring_elsq); \
- func(has_master_unit_irq); \
+ func(has_mslices); \
func(has_pooled_eu); \
func(has_rc6); \
func(has_rc6p); \
@@ -141,6 +145,7 @@ enum intel_ppgtt_type {
#define DEV_INFO_DISPLAY_FOR_EACH_FLAG(func) \
/* Keep in alphabetical order */ \
func(cursor_needs_physical); \
+ func(has_cdclk_crawl); \
func(has_dmc); \
func(has_ddi); \
func(has_dp_mst); \
@@ -162,9 +167,10 @@ enum intel_ppgtt_type {
struct intel_device_info {
u8 graphics_ver;
+ u8 graphics_rel;
u8 media_ver;
+ u8 media_rel;
- u8 gt; /* GT number, 0 if undefined */
intel_engine_mask_t platform_engine_mask; /* Engines supported by the HW */
enum intel_platform platform;
@@ -180,13 +186,13 @@ struct intel_device_info {
u32 display_mmio_offset;
+ u8 gt; /* GT number, 0 if undefined */
+
u8 pipe_mask;
u8 cpu_transcoder_mask;
u8 abox_mask;
- u8 has_cdclk_crawl; /* does support CDCLK crawling */
-
#define DEFINE_FLAG(name) u8 name:1
DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
#undef DEFINE_FLAG
diff --git a/drivers/gpu/drm/i915/intel_dram.c b/drivers/gpu/drm/i915/intel_dram.c
index 50fdea84ba70..91866520c173 100644
--- a/drivers/gpu/drm/i915/intel_dram.c
+++ b/drivers/gpu/drm/i915/intel_dram.c
@@ -77,21 +77,21 @@ static int skl_get_dimm_ranks(u16 val)
}
/* Returns total Gb for the whole DIMM */
-static int cnl_get_dimm_size(u16 val)
+static int icl_get_dimm_size(u16 val)
{
- return (val & CNL_DRAM_SIZE_MASK) * 8 / 2;
+ return (val & ICL_DRAM_SIZE_MASK) * 8 / 2;
}
-static int cnl_get_dimm_width(u16 val)
+static int icl_get_dimm_width(u16 val)
{
- if (cnl_get_dimm_size(val) == 0)
+ if (icl_get_dimm_size(val) == 0)
return 0;
- switch (val & CNL_DRAM_WIDTH_MASK) {
- case CNL_DRAM_WIDTH_X8:
- case CNL_DRAM_WIDTH_X16:
- case CNL_DRAM_WIDTH_X32:
- val = (val & CNL_DRAM_WIDTH_MASK) >> CNL_DRAM_WIDTH_SHIFT;
+ switch (val & ICL_DRAM_WIDTH_MASK) {
+ case ICL_DRAM_WIDTH_X8:
+ case ICL_DRAM_WIDTH_X16:
+ case ICL_DRAM_WIDTH_X32:
+ val = (val & ICL_DRAM_WIDTH_MASK) >> ICL_DRAM_WIDTH_SHIFT;
return 8 << val;
default:
MISSING_CASE(val);
@@ -99,12 +99,12 @@ static int cnl_get_dimm_width(u16 val)
}
}
-static int cnl_get_dimm_ranks(u16 val)
+static int icl_get_dimm_ranks(u16 val)
{
- if (cnl_get_dimm_size(val) == 0)
+ if (icl_get_dimm_size(val) == 0)
return 0;
- val = (val & CNL_DRAM_RANK_MASK) >> CNL_DRAM_RANK_SHIFT;
+ val = (val & ICL_DRAM_RANK_MASK) >> ICL_DRAM_RANK_SHIFT;
return val + 1;
}
@@ -121,10 +121,10 @@ skl_dram_get_dimm_info(struct drm_i915_private *i915,
struct dram_dimm_info *dimm,
int channel, char dimm_name, u16 val)
{
- if (GRAPHICS_VER(i915) >= 10) {
- dimm->size = cnl_get_dimm_size(val);
- dimm->width = cnl_get_dimm_width(val);
- dimm->ranks = cnl_get_dimm_ranks(val);
+ if (GRAPHICS_VER(i915) >= 11) {
+ dimm->size = icl_get_dimm_size(val);
+ dimm->width = icl_get_dimm_width(val);
+ dimm->ranks = icl_get_dimm_ranks(val);
} else {
dimm->size = skl_get_dimm_size(val);
dimm->width = skl_get_dimm_width(val);
@@ -468,6 +468,7 @@ static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv)
dram_info->num_channels = (val & 0xf0) >> 4;
dram_info->num_qgv_points = (val & 0xf00) >> 8;
+ dram_info->num_psf_gv_points = (val & 0x3000) >> 12;
return 0;
}
@@ -484,8 +485,7 @@ static int gen11_get_dram_info(struct drm_i915_private *i915)
static int gen12_get_dram_info(struct drm_i915_private *i915)
{
- /* Always needed for GEN12+ */
- i915->dram_info.wm_lv_0_adjust_needed = true;
+ i915->dram_info.wm_lv_0_adjust_needed = false;
return icl_pcode_read_mem_global_info(i915);
}
@@ -495,15 +495,15 @@ void intel_dram_detect(struct drm_i915_private *i915)
struct dram_info *dram_info = &i915->dram_info;
int ret;
+ if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915))
+ return;
+
/*
* Assume level 0 watermark latency adjustment is needed until proven
* otherwise, this w/a is not needed by bxt/glk.
*/
dram_info->wm_lv_0_adjust_needed = !IS_GEN9_LP(i915);
- if (GRAPHICS_VER(i915) < 9 || !HAS_DISPLAY(i915))
- return;
-
if (GRAPHICS_VER(i915) >= 12)
ret = gen12_get_dram_info(i915);
else if (GRAPHICS_VER(i915) >= 11)
diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c
index e6024eb7cca4..779eb2fa90b6 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/intel_memory_region.c
@@ -5,6 +5,7 @@
#include "intel_memory_region.h"
#include "i915_drv.h"
+#include "i915_ttm_buddy_manager.h"
static const struct {
u16 class;
@@ -28,11 +29,6 @@ static const struct {
},
};
-struct intel_region_reserve {
- struct list_head link;
- struct ttm_resource *res;
-};
-
struct intel_memory_region *
intel_memory_region_lookup(struct drm_i915_private *i915,
u16 class, u16 instance)
@@ -64,27 +60,6 @@ intel_memory_region_by_type(struct drm_i915_private *i915,
}
/**
- * intel_memory_region_unreserve - Unreserve all previously reserved
- * ranges
- * @mem: The region containing the reserved ranges.
- */
-void intel_memory_region_unreserve(struct intel_memory_region *mem)
-{
- struct intel_region_reserve *reserve, *next;
-
- if (!mem->priv_ops || !mem->priv_ops->free)
- return;
-
- mutex_lock(&mem->mm_lock);
- list_for_each_entry_safe(reserve, next, &mem->reserved, link) {
- list_del(&reserve->link);
- mem->priv_ops->free(mem, reserve->res);
- kfree(reserve);
- }
- mutex_unlock(&mem->mm_lock);
-}
-
-/**
* intel_memory_region_reserve - Reserve a memory range
* @mem: The region for which we want to reserve a range.
* @offset: Start of the range to reserve.
@@ -96,28 +71,11 @@ int intel_memory_region_reserve(struct intel_memory_region *mem,
resource_size_t offset,
resource_size_t size)
{
- int ret;
- struct intel_region_reserve *reserve;
-
- if (!mem->priv_ops || !mem->priv_ops->reserve)
- return -EINVAL;
-
- reserve = kzalloc(sizeof(*reserve), GFP_KERNEL);
- if (!reserve)
- return -ENOMEM;
+ struct ttm_resource_manager *man = mem->region_private;
- reserve->res = mem->priv_ops->reserve(mem, offset, size);
- if (IS_ERR(reserve->res)) {
- ret = PTR_ERR(reserve->res);
- kfree(reserve);
- return ret;
- }
-
- mutex_lock(&mem->mm_lock);
- list_add_tail(&reserve->link, &mem->reserved);
- mutex_unlock(&mem->mm_lock);
+ GEM_BUG_ON(mem->is_range_manager);
- return 0;
+ return i915_ttm_buddy_man_reserve(man, offset, size);
}
struct intel_memory_region *
@@ -149,10 +107,6 @@ intel_memory_region_create(struct drm_i915_private *i915,
mutex_init(&mem->objects.lock);
INIT_LIST_HEAD(&mem->objects.list);
- INIT_LIST_HEAD(&mem->objects.purgeable);
- INIT_LIST_HEAD(&mem->reserved);
-
- mutex_init(&mem->mm_lock);
if (ops->init) {
err = ops->init(mem);
@@ -183,11 +137,9 @@ static void __intel_memory_region_destroy(struct kref *kref)
struct intel_memory_region *mem =
container_of(kref, typeof(*mem), kref);
- intel_memory_region_unreserve(mem);
if (mem->ops->release)
mem->ops->release(mem);
- mutex_destroy(&mem->mm_lock);
mutex_destroy(&mem->objects.lock);
kfree(mem);
}
@@ -221,7 +173,12 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915)
instance = intel_region_map[i].instance;
switch (type) {
case INTEL_MEMORY_SYSTEM:
- mem = i915_gem_shmem_setup(i915, type, instance);
+ if (IS_DGFX(i915))
+ mem = i915_gem_ttm_system_setup(i915, type,
+ instance);
+ else
+ mem = i915_gem_shmem_setup(i915, type,
+ instance);
break;
case INTEL_MEMORY_STOLEN_LOCAL:
mem = i915_gem_stolen_lmem_setup(i915, type, instance);
diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h
index 1f7dac63abb7..1f2b96efa69d 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.h
+++ b/drivers/gpu/drm/i915/intel_memory_region.h
@@ -40,8 +40,7 @@ enum intel_region_id {
#define REGION_STOLEN_SMEM BIT(INTEL_REGION_STOLEN_SMEM)
#define REGION_STOLEN_LMEM BIT(INTEL_REGION_STOLEN_LMEM)
-#define I915_ALLOC_MIN_PAGE_SIZE BIT(0)
-#define I915_ALLOC_CONTIGUOUS BIT(1)
+#define I915_ALLOC_CONTIGUOUS BIT(0)
#define for_each_memory_region(mr, i915, id) \
for (id = 0; id < ARRAY_SIZE((i915)->mm.regions); id++) \
@@ -56,22 +55,14 @@ struct intel_memory_region_ops {
int (*init_object)(struct intel_memory_region *mem,
struct drm_i915_gem_object *obj,
resource_size_t size,
+ resource_size_t page_size,
unsigned int flags);
};
-struct intel_memory_region_private_ops {
- struct ttm_resource *(*reserve)(struct intel_memory_region *mem,
- resource_size_t offset,
- resource_size_t size);
- void (*free)(struct intel_memory_region *mem,
- struct ttm_resource *res);
-};
-
struct intel_memory_region {
struct drm_i915_private *i915;
const struct intel_memory_region_ops *ops;
- const struct intel_memory_region_private_ops *priv_ops;
struct io_mapping iomap;
struct resource region;
@@ -79,8 +70,6 @@ struct intel_memory_region {
/* For fake LMEM */
struct drm_mm_node fake_mappable;
- struct mutex mm_lock;
-
struct kref kref;
resource_size_t io_start;
@@ -94,18 +83,13 @@ struct intel_memory_region {
char name[16];
bool private; /* not for userspace */
- struct list_head reserved;
-
dma_addr_t remap_addr;
struct {
struct mutex lock; /* Protects access to objects */
struct list_head list;
- struct list_head purgeable;
} objects;
- size_t chunk_size;
- unsigned int max_order;
bool is_range_manager;
void *region_private;
@@ -139,9 +123,15 @@ __printf(2, 3) void
intel_memory_region_set_name(struct intel_memory_region *mem,
const char *fmt, ...);
-void intel_memory_region_unreserve(struct intel_memory_region *mem);
-
int intel_memory_region_reserve(struct intel_memory_region *mem,
resource_size_t offset,
resource_size_t size);
+
+struct intel_memory_region *
+i915_gem_ttm_system_setup(struct drm_i915_private *i915,
+ u16 type, u16 instance);
+struct intel_memory_region *
+i915_gem_shmem_setup(struct drm_i915_private *i915,
+ u16 type, u16 instance);
+
#endif
diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c
index 4e92ae19189e..d1d4b97b86f5 100644
--- a/drivers/gpu/drm/i915/intel_pch.c
+++ b/drivers/gpu/drm/i915/intel_pch.c
@@ -81,7 +81,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
case INTEL_PCH_CNP_DEVICE_ID_TYPE:
drm_dbg_kms(&dev_priv->drm, "Found Cannon Lake PCH (CNP)\n");
drm_WARN_ON(&dev_priv->drm,
- !IS_CANNONLAKE(dev_priv) &&
!IS_COFFEELAKE(dev_priv) &&
!IS_COMETLAKE(dev_priv));
return PCH_CNP;
@@ -89,7 +88,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
drm_dbg_kms(&dev_priv->drm,
"Found Cannon Lake LP PCH (CNP-LP)\n");
drm_WARN_ON(&dev_priv->drm,
- !IS_CANNONLAKE(dev_priv) &&
!IS_COFFEELAKE(dev_priv) &&
!IS_COMETLAKE(dev_priv));
return PCH_CNP;
@@ -171,8 +169,7 @@ intel_virt_detect_pch(const struct drm_i915_private *dev_priv,
id = INTEL_PCH_MCC_DEVICE_ID_TYPE;
else if (IS_ICELAKE(dev_priv))
id = INTEL_PCH_ICP_DEVICE_ID_TYPE;
- else if (IS_CANNONLAKE(dev_priv) ||
- IS_COFFEELAKE(dev_priv) ||
+ else if (IS_COFFEELAKE(dev_priv) ||
IS_COMETLAKE(dev_priv))
id = INTEL_PCH_CNP_DEVICE_ID_TYPE;
else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv))
@@ -211,6 +208,9 @@ void intel_detect_pch(struct drm_i915_private *dev_priv)
if (IS_DG1(dev_priv)) {
dev_priv->pch_type = PCH_DG1;
return;
+ } else if (IS_DG2(dev_priv)) {
+ dev_priv->pch_type = PCH_DG2;
+ return;
}
/*
diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h
index e2f3f30c6445..7c0d83d292dc 100644
--- a/drivers/gpu/drm/i915/intel_pch.h
+++ b/drivers/gpu/drm/i915/intel_pch.h
@@ -30,6 +30,7 @@ enum intel_pch {
/* Fake PCHs, functionality handled on the same PCI dev */
PCH_DG1 = 1024,
+ PCH_DG2,
};
#define INTEL_PCH_DEVICE_ID_MASK 0xff80
@@ -62,6 +63,7 @@ enum intel_pch {
#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type)
#define INTEL_PCH_ID(dev_priv) ((dev_priv)->pch_id)
+#define HAS_PCH_DG2(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG2)
#define HAS_PCH_ADP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ADP)
#define HAS_PCH_DG1(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG1)
#define HAS_PCH_JSP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_JSP)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 45fefa0ed160..65bc3709f54c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1370,11 +1370,11 @@ static bool g4x_compute_fbc_en(const struct g4x_wm_state *wm_state,
return true;
}
-static int g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state)
+static int g4x_compute_pipe_wm(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct intel_atomic_state *state =
- to_intel_atomic_state(crtc_state->uapi.state);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
struct g4x_wm_state *wm_state = &crtc_state->wm.g4x.optimal;
int num_active_planes = hweight8(crtc_state->active_planes &
~BIT(PLANE_CURSOR));
@@ -1451,20 +1451,21 @@ static int g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state)
return 0;
}
-static int g4x_compute_intermediate_wm(struct intel_crtc_state *new_crtc_state)
+static int g4x_compute_intermediate_wm(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
struct g4x_wm_state *intermediate = &new_crtc_state->wm.g4x.intermediate;
const struct g4x_wm_state *optimal = &new_crtc_state->wm.g4x.optimal;
- struct intel_atomic_state *intel_state =
- to_intel_atomic_state(new_crtc_state->uapi.state);
- const struct intel_crtc_state *old_crtc_state =
- intel_atomic_get_old_crtc_state(intel_state, crtc);
const struct g4x_wm_state *active = &old_crtc_state->wm.g4x.optimal;
enum plane_id plane_id;
- if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) {
+ if (!new_crtc_state->hw.active ||
+ drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) {
*intermediate = *optimal;
intermediate->cxsr = false;
@@ -1890,12 +1891,12 @@ static bool vlv_raw_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state,
vlv_raw_plane_wm_is_valid(crtc_state, PLANE_CURSOR, level);
}
-static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
+static int vlv_compute_pipe_wm(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct intel_atomic_state *state =
- to_intel_atomic_state(crtc_state->uapi.state);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
const struct vlv_fifo_state *fifo_state =
&crtc_state->wm.vlv.fifo_state;
@@ -2095,19 +2096,20 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
#undef VLV_FIFO
-static int vlv_compute_intermediate_wm(struct intel_crtc_state *new_crtc_state)
+static int vlv_compute_intermediate_wm(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+ struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
struct vlv_wm_state *intermediate = &new_crtc_state->wm.vlv.intermediate;
const struct vlv_wm_state *optimal = &new_crtc_state->wm.vlv.optimal;
- struct intel_atomic_state *intel_state =
- to_intel_atomic_state(new_crtc_state->uapi.state);
- const struct intel_crtc_state *old_crtc_state =
- intel_atomic_get_old_crtc_state(intel_state, crtc);
const struct vlv_wm_state *active = &old_crtc_state->wm.vlv.optimal;
int level;
- if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) {
+ if (!new_crtc_state->hw.active ||
+ drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) {
*intermediate = *optimal;
intermediate->cxsr = false;
@@ -2906,24 +2908,25 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
if (wm[level] == 0) {
for (i = level + 1; i <= max_level; i++)
wm[i] = 0;
+
+ max_level = level - 1;
+
break;
}
}
/*
- * WaWmMemoryReadLatency:skl+,glk
+ * WaWmMemoryReadLatency
*
* punit doesn't take into account the read latency so we need
- * to add 2us to the various latency levels we retrieve from the
- * punit when level 0 response data us 0us.
+ * to add proper adjustement to each valid level we retrieve
+ * from the punit when level 0 response data is 0us.
*/
if (wm[0] == 0) {
- wm[0] += 2;
- for (level = 1; level <= max_level; level++) {
- if (wm[level] == 0)
- break;
- wm[level] += 2;
- }
+ u8 adjust = DISPLAY_VER(dev_priv) >= 12 ? 3 : 2;
+
+ for (level = 0; level <= max_level; level++)
+ wm[level] += adjust;
}
/*
@@ -2934,7 +2937,6 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
*/
if (dev_priv->dram_info.wm_lv_0_adjust_needed)
wm[0] += 1;
-
} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
u64 sskpd = intel_uncore_read64(uncore, MCH_SSKPD);
@@ -3144,10 +3146,12 @@ static bool ilk_validate_pipe_wm(const struct drm_i915_private *dev_priv,
}
/* Compute new watermarks for the pipe */
-static int ilk_compute_pipe_wm(struct intel_crtc_state *crtc_state)
+static int ilk_compute_pipe_wm(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
struct intel_pipe_wm *pipe_wm;
struct intel_plane *plane;
const struct intel_plane_state *plane_state;
@@ -3220,16 +3224,16 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *crtc_state)
* state and the new state. These can be programmed to the hardware
* immediately.
*/
-static int ilk_compute_intermediate_wm(struct intel_crtc_state *newstate)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(newstate->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
- struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate;
- struct intel_atomic_state *intel_state =
- to_intel_atomic_state(newstate->uapi.state);
- const struct intel_crtc_state *oldstate =
- intel_atomic_get_old_crtc_state(intel_state, intel_crtc);
- const struct intel_pipe_wm *b = &oldstate->wm.ilk.optimal;
+static int ilk_compute_intermediate_wm(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+ struct intel_pipe_wm *a = &new_crtc_state->wm.ilk.intermediate;
+ const struct intel_pipe_wm *b = &old_crtc_state->wm.ilk.optimal;
int level, max_level = ilk_wm_max_level(dev_priv);
/*
@@ -3237,9 +3241,10 @@ static int ilk_compute_intermediate_wm(struct intel_crtc_state *newstate)
* currently active watermarks to get values that are safe both before
* and after the vblank.
*/
- *a = newstate->wm.ilk.optimal;
- if (!newstate->hw.active || drm_atomic_crtc_needs_modeset(&newstate->uapi) ||
- intel_state->skip_intermediate_wm)
+ *a = new_crtc_state->wm.ilk.optimal;
+ if (!new_crtc_state->hw.active ||
+ drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi) ||
+ state->skip_intermediate_wm)
return 0;
a->pipe_enabled |= b->pipe_enabled;
@@ -3270,8 +3275,8 @@ static int ilk_compute_intermediate_wm(struct intel_crtc_state *newstate)
* If our intermediate WM are identical to the final WM, then we can
* omit the post-vblank programming; only update if it's different.
*/
- if (memcmp(a, &newstate->wm.ilk.optimal, sizeof(*a)) != 0)
- newstate->wm.need_postvbl_update = true;
+ if (memcmp(a, &new_crtc_state->wm.ilk.optimal, sizeof(*a)) != 0)
+ new_crtc_state->wm.need_postvbl_update = true;
return 0;
}
@@ -3283,12 +3288,12 @@ static void ilk_merge_wm_level(struct drm_i915_private *dev_priv,
int level,
struct intel_wm_level *ret_wm)
{
- const struct intel_crtc *intel_crtc;
+ const struct intel_crtc *crtc;
ret_wm->enable = true;
- for_each_intel_crtc(&dev_priv->drm, intel_crtc) {
- const struct intel_pipe_wm *active = &intel_crtc->wm.active.ilk;
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
+ const struct intel_pipe_wm *active = &crtc->wm.active.ilk;
const struct intel_wm_level *wm = &active->wm[level];
if (!active->pipe_enabled)
@@ -3388,7 +3393,7 @@ static void ilk_compute_wm_results(struct drm_i915_private *dev_priv,
enum intel_ddb_partitioning partitioning,
struct ilk_wm_values *results)
{
- struct intel_crtc *intel_crtc;
+ struct intel_crtc *crtc;
int level, wm_lp;
results->enable_fbc_wm = merged->fbc_wm_enabled;
@@ -3433,9 +3438,9 @@ static void ilk_compute_wm_results(struct drm_i915_private *dev_priv,
}
/* LP0 register values */
- for_each_intel_crtc(&dev_priv->drm, intel_crtc) {
- enum pipe pipe = intel_crtc->pipe;
- const struct intel_pipe_wm *pipe_wm = &intel_crtc->wm.active.ilk;
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
+ enum pipe pipe = crtc->pipe;
+ const struct intel_pipe_wm *pipe_wm = &crtc->wm.active.ilk;
const struct intel_wm_level *r = &pipe_wm->wm[0];
if (drm_WARN_ON(&dev_priv->drm, !r->enable))
@@ -4579,6 +4584,117 @@ static const struct dbuf_slice_conf_entry tgl_allowed_dbufs[] =
{}
};
+static const struct dbuf_slice_conf_entry dg2_allowed_dbufs[] = {
+ {
+ .active_pipes = BIT(PIPE_A),
+ .dbuf_mask = {
+ [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_B),
+ .dbuf_mask = {
+ [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_A) | BIT(PIPE_B),
+ .dbuf_mask = {
+ [PIPE_A] = BIT(DBUF_S1),
+ [PIPE_B] = BIT(DBUF_S2),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_C),
+ .dbuf_mask = {
+ [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_A) | BIT(PIPE_C),
+ .dbuf_mask = {
+ [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2),
+ [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_B) | BIT(PIPE_C),
+ .dbuf_mask = {
+ [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2),
+ [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+ .dbuf_mask = {
+ [PIPE_A] = BIT(DBUF_S1),
+ [PIPE_B] = BIT(DBUF_S2),
+ [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_D),
+ .dbuf_mask = {
+ [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_A) | BIT(PIPE_D),
+ .dbuf_mask = {
+ [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2),
+ [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_B) | BIT(PIPE_D),
+ .dbuf_mask = {
+ [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2),
+ [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D),
+ .dbuf_mask = {
+ [PIPE_A] = BIT(DBUF_S1),
+ [PIPE_B] = BIT(DBUF_S2),
+ [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_C) | BIT(PIPE_D),
+ .dbuf_mask = {
+ [PIPE_C] = BIT(DBUF_S3),
+ [PIPE_D] = BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D),
+ .dbuf_mask = {
+ [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2),
+ [PIPE_C] = BIT(DBUF_S3),
+ [PIPE_D] = BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
+ .dbuf_mask = {
+ [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2),
+ [PIPE_C] = BIT(DBUF_S3),
+ [PIPE_D] = BIT(DBUF_S4),
+ },
+ },
+ {
+ .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
+ .dbuf_mask = {
+ [PIPE_A] = BIT(DBUF_S1),
+ [PIPE_B] = BIT(DBUF_S2),
+ [PIPE_C] = BIT(DBUF_S3),
+ [PIPE_D] = BIT(DBUF_S4),
+ },
+ },
+ {}
+};
+
static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = {
{
.active_pipes = BIT(PIPE_A),
@@ -4754,12 +4870,19 @@ static u32 adlp_compute_dbuf_slices(enum pipe pipe, u32 active_pipes)
return compute_dbuf_slices(pipe, active_pipes, adlp_allowed_dbufs);
}
+static u32 dg2_compute_dbuf_slices(enum pipe pipe, u32 active_pipes)
+{
+ return compute_dbuf_slices(pipe, active_pipes, dg2_allowed_dbufs);
+}
+
static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
- if (IS_ALDERLAKE_P(dev_priv))
+ if (IS_DG2(dev_priv))
+ return dg2_compute_dbuf_slices(pipe, active_pipes);
+ else if (IS_ALDERLAKE_P(dev_priv))
return adlp_compute_dbuf_slices(pipe, active_pipes);
else if (DISPLAY_VER(dev_priv) == 12)
return tgl_compute_dbuf_slices(pipe, active_pipes);
@@ -7340,30 +7463,24 @@ static void icl_init_clock_gating(struct drm_i915_private *dev_priv)
intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN,
ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL);
- /* This is not an Wa. Enable to reduce Sampler power */
- intel_uncore_write(&dev_priv->uncore, GEN10_DFR_RATIO_EN_AND_CHICKEN,
- intel_uncore_read(&dev_priv->uncore, GEN10_DFR_RATIO_EN_AND_CHICKEN) & ~DFR_DISABLE);
-
/*Wa_14010594013:icl, ehl */
intel_uncore_rmw(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1,
- 0, CNL_DELAY_PMRSP);
+ 0, ICL_DELAY_PMRSP);
}
static void gen12lp_init_clock_gating(struct drm_i915_private *dev_priv)
{
- /* Wa_1409120013:tgl,rkl,adl_s,dg1 */
- intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN,
- ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL);
+ /* Wa_1409120013:tgl,rkl,adl-s,dg1 */
+ if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
+ IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv))
+ intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN,
+ ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL);
/* Wa_1409825376:tgl (pre-prod)*/
- if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B1))
+ if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0))
intel_uncore_write(&dev_priv->uncore, GEN9_CLKGATE_DIS_3, intel_uncore_read(&dev_priv->uncore, GEN9_CLKGATE_DIS_3) |
TGL_VRH_GATING_DIS);
- /* Wa_14011059788:tgl,rkl,adl_s,dg1 */
- intel_uncore_rmw(&dev_priv->uncore, GEN10_DFR_RATIO_EN_AND_CHICKEN,
- 0, DFR_DISABLE);
-
/* Wa_14013723622:tgl,rkl,dg1,adl-s */
if (DISPLAY_VER(dev_priv) == 12)
intel_uncore_rmw(&dev_priv->uncore, CLKREQ_POLICY,
@@ -7383,7 +7500,7 @@ static void dg1_init_clock_gating(struct drm_i915_private *dev_priv)
gen12lp_init_clock_gating(dev_priv);
/* Wa_1409836686:dg1[a0] */
- if (IS_DG1_REVID(dev_priv, DG1_REVID_A0, DG1_REVID_A0))
+ if (IS_DG1_GT_STEP(dev_priv, STEP_A0, STEP_B0))
intel_uncore_write(&dev_priv->uncore, GEN9_CLKGATE_DIS_3, intel_uncore_read(&dev_priv->uncore, GEN9_CLKGATE_DIS_3) |
DPT_GATING_DIS);
}
@@ -7398,43 +7515,6 @@ static void cnp_init_clock_gating(struct drm_i915_private *dev_priv)
CNP_PWM_CGE_GATING_DISABLE);
}
-static void cnl_init_clock_gating(struct drm_i915_private *dev_priv)
-{
- u32 val;
- cnp_init_clock_gating(dev_priv);
-
- /* This is not an Wa. Enable for better image quality */
- intel_uncore_write(&dev_priv->uncore, _3D_CHICKEN3,
- _MASKED_BIT_ENABLE(_3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE));
-
- /* WaEnableChickenDCPR:cnl */
- intel_uncore_write(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1,
- intel_uncore_read(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1) | MASK_WAKEMEM);
-
- /*
- * WaFbcWakeMemOn:cnl
- * Display WA #0859: cnl
- */
- intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL) |
- DISP_FBC_MEMORY_WAKE);
-
- val = intel_uncore_read(&dev_priv->uncore, SLICE_UNIT_LEVEL_CLKGATE);
- /* ReadHitWriteOnlyDisable:cnl */
- val |= RCCUNIT_CLKGATE_DIS;
- intel_uncore_write(&dev_priv->uncore, SLICE_UNIT_LEVEL_CLKGATE, val);
-
- /* Wa_2201832410:cnl */
- val = intel_uncore_read(&dev_priv->uncore, SUBSLICE_UNIT_LEVEL_CLKGATE);
- val |= GWUNIT_CLKGATE_DIS;
- intel_uncore_write(&dev_priv->uncore, SUBSLICE_UNIT_LEVEL_CLKGATE, val);
-
- /* WaDisableVFclkgate:cnl */
- /* WaVFUnitClockGatingDisable:cnl */
- val = intel_uncore_read(&dev_priv->uncore, UNSLICE_UNIT_LEVEL_CLKGATE);
- val |= VFUNIT_CLKGATE_DIS;
- intel_uncore_write(&dev_priv->uncore, UNSLICE_UNIT_LEVEL_CLKGATE, val);
-}
-
static void cfl_init_clock_gating(struct drm_i915_private *dev_priv)
{
cnp_init_clock_gating(dev_priv);
@@ -7468,12 +7548,12 @@ static void kbl_init_clock_gating(struct drm_i915_private *dev_priv)
FBC_LLC_FULLY_OPEN);
/* WaDisableSDEUnitClockGating:kbl */
- if (IS_KBL_GT_STEP(dev_priv, 0, STEP_B0))
+ if (IS_KBL_GT_STEP(dev_priv, 0, STEP_C0))
intel_uncore_write(&dev_priv->uncore, GEN8_UCGCTL6, intel_uncore_read(&dev_priv->uncore, GEN8_UCGCTL6) |
GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
/* WaDisableGamClockGating:kbl */
- if (IS_KBL_GT_STEP(dev_priv, 0, STEP_B0))
+ if (IS_KBL_GT_STEP(dev_priv, 0, STEP_C0))
intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL1, intel_uncore_read(&dev_priv->uncore, GEN6_UCGCTL1) |
GEN6_GAMUNIT_CLOCK_GATE_DISABLE);
@@ -7863,8 +7943,6 @@ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv)
dev_priv->display.init_clock_gating = gen12lp_init_clock_gating;
else if (GRAPHICS_VER(dev_priv) == 11)
dev_priv->display.init_clock_gating = icl_init_clock_gating;
- else if (IS_CANNONLAKE(dev_priv))
- dev_priv->display.init_clock_gating = cnl_init_clock_gating;
else if (IS_COFFEELAKE(dev_priv) || IS_COMETLAKE(dev_priv))
dev_priv->display.init_clock_gating = cfl_init_clock_gating;
else if (IS_SKYLAKE(dev_priv))
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
index 82a6727ede46..98c7339bf8ba 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.c
+++ b/drivers/gpu/drm/i915/intel_region_ttm.c
@@ -8,9 +8,11 @@
#include "i915_drv.h"
#include "i915_scatterlist.h"
+#include "i915_ttm_buddy_manager.h"
#include "intel_region_ttm.h"
+#include "gem/i915_gem_ttm.h" /* For the funcs/ops export only */
/**
* DOC: TTM support structure
*
@@ -20,9 +22,6 @@
* i915 GEM regions to TTM memory types and resource managers.
*/
-/* A Zero-initialized driver for now. We don't have a TTM backend yet. */
-static struct ttm_device_funcs i915_ttm_bo_driver;
-
/**
* intel_region_ttm_device_init - Initialize a TTM device
* @dev_priv: Pointer to an i915 device private structure.
@@ -33,7 +32,7 @@ int intel_region_ttm_device_init(struct drm_i915_private *dev_priv)
{
struct drm_device *drm = &dev_priv->drm;
- return ttm_device_init(&dev_priv->bdev, &i915_ttm_bo_driver,
+ return ttm_device_init(&dev_priv->bdev, i915_ttm_driver(),
drm->dev, drm->anon_inode->i_mapping,
drm->vma_offset_manager, false, false);
}
@@ -52,12 +51,16 @@ void intel_region_ttm_device_fini(struct drm_i915_private *dev_priv)
* driver-private types for now, reserving TTM_PL_VRAM for stolen
* memory and TTM_PL_TT for GGTT use if decided to implement this.
*/
-static int intel_region_to_ttm_type(struct intel_memory_region *mem)
+int intel_region_to_ttm_type(const struct intel_memory_region *mem)
{
int type;
GEM_BUG_ON(mem->type != INTEL_MEMORY_LOCAL &&
- mem->type != INTEL_MEMORY_MOCK);
+ mem->type != INTEL_MEMORY_MOCK &&
+ mem->type != INTEL_MEMORY_SYSTEM);
+
+ if (mem->type == INTEL_MEMORY_SYSTEM)
+ return TTM_PL_SYSTEM;
type = mem->instance + TTM_PL_PRIV;
GEM_BUG_ON(type >= TTM_NUM_MEM_TYPES);
@@ -65,72 +68,29 @@ static int intel_region_to_ttm_type(struct intel_memory_region *mem)
return type;
}
-static struct ttm_resource *
-intel_region_ttm_node_reserve(struct intel_memory_region *mem,
- resource_size_t offset,
- resource_size_t size)
-{
- struct ttm_resource_manager *man = mem->region_private;
- struct ttm_place place = {};
- struct ttm_buffer_object mock_bo = {};
- struct ttm_resource *res;
- int ret;
-
- /*
- * Having to use a mock_bo is unfortunate but stems from some
- * drivers having private managers that insist to know what the
- * allocate memory is intended for, using it to send private
- * data to the manager. Also recently the bo has been used to send
- * alignment info to the manager. Assume that apart from the latter,
- * none of the managers we use will ever access the buffer object
- * members, hoping we can pass the alignment info in the
- * struct ttm_place in the future.
- */
-
- place.fpfn = offset >> PAGE_SHIFT;
- place.lpfn = place.fpfn + (size >> PAGE_SHIFT);
- mock_bo.base.size = size;
- ret = man->func->alloc(man, &mock_bo, &place, &res);
- if (ret == -ENOSPC)
- ret = -ENXIO;
-
- return ret ? ERR_PTR(ret) : res;
-}
-
/**
- * intel_region_ttm_node_free - Free a node allocated from a resource manager
- * @mem: The region the node was allocated from.
- * @node: The opaque node representing an allocation.
+ * intel_region_ttm_init - Initialize a memory region for TTM.
+ * @mem: The region to initialize.
+ *
+ * This function initializes a suitable TTM resource manager for the
+ * region, and if it's a LMEM region type, attaches it to the TTM
+ * device. MOCK regions are NOT attached to the TTM device, since we don't
+ * have one for the mock selftests.
+ *
+ * Return: 0 on success, negative error code on failure.
*/
-void intel_region_ttm_node_free(struct intel_memory_region *mem,
- struct ttm_resource *res)
-{
- struct ttm_resource_manager *man = mem->region_private;
-
- man->func->free(man, res);
-}
-
-static const struct intel_memory_region_private_ops priv_ops = {
- .reserve = intel_region_ttm_node_reserve,
- .free = intel_region_ttm_node_free,
-};
-
int intel_region_ttm_init(struct intel_memory_region *mem)
{
struct ttm_device *bdev = &mem->i915->bdev;
int mem_type = intel_region_to_ttm_type(mem);
int ret;
- ret = ttm_range_man_init(bdev, mem_type, false,
- resource_size(&mem->region) >> PAGE_SHIFT);
+ ret = i915_ttm_buddy_man_init(bdev, mem_type, false,
+ resource_size(&mem->region),
+ mem->min_page_size, PAGE_SIZE);
if (ret)
return ret;
- mem->chunk_size = PAGE_SIZE;
- mem->max_order =
- get_order(rounddown_pow_of_two(resource_size(&mem->region)));
- mem->is_range_manager = true;
- mem->priv_ops = &priv_ops;
mem->region_private = ttm_manager_type(bdev, mem_type);
return 0;
@@ -148,17 +108,17 @@ void intel_region_ttm_fini(struct intel_memory_region *mem)
{
int ret;
- ret = ttm_range_man_fini(&mem->i915->bdev,
- intel_region_to_ttm_type(mem));
+ ret = i915_ttm_buddy_man_fini(&mem->i915->bdev,
+ intel_region_to_ttm_type(mem));
GEM_WARN_ON(ret);
mem->region_private = NULL;
}
/**
- * intel_region_ttm_node_to_st - Convert an opaque TTM resource manager node
+ * intel_region_ttm_resource_to_st - Convert an opaque TTM resource manager resource
* to an sg_table.
* @mem: The memory region.
- * @node: The resource manager node obtained from the TTM resource manager.
+ * @res: The resource manager resource obtained from the TTM resource manager.
*
* The gem backends typically use sg-tables for operations on the underlying
* io_memory. So provide a way for the backends to translate the
@@ -166,19 +126,23 @@ void intel_region_ttm_fini(struct intel_memory_region *mem)
*
* Return: A malloced sg_table on success, an error pointer on failure.
*/
-struct sg_table *intel_region_ttm_node_to_st(struct intel_memory_region *mem,
- struct ttm_resource *res)
+struct sg_table *intel_region_ttm_resource_to_st(struct intel_memory_region *mem,
+ struct ttm_resource *res)
{
- struct ttm_range_mgr_node *range_node =
- container_of(res, typeof(*range_node), base);
+ if (mem->is_range_manager) {
+ struct ttm_range_mgr_node *range_node =
+ to_ttm_range_mgr_node(res);
- GEM_WARN_ON(!mem->is_range_manager);
- return i915_sg_from_mm_node(&range_node->mm_nodes[0],
- mem->region.start);
+ return i915_sg_from_mm_node(&range_node->mm_nodes[0],
+ mem->region.start);
+ } else {
+ return i915_sg_from_buddy_resource(res, mem->region.start);
+ }
}
+#ifdef CONFIG_DRM_I915_SELFTEST
/**
- * intel_region_ttm_node_alloc - Allocate memory resources from a region
+ * intel_region_ttm_resource_alloc - Allocate memory resources from a region
* @mem: The memory region,
* @size: The requested size in bytes
* @flags: Allocation flags
@@ -187,15 +151,15 @@ struct sg_table *intel_region_ttm_node_to_st(struct intel_memory_region *mem,
* memory from standalone TTM range managers, without the TTM eviction
* functionality. Don't use if you are not completely sure that's the
* case. The returned opaque node can be converted to an sg_table using
- * intel_region_ttm_node_to_st(), and can be freed using
- * intel_region_ttm_node_free().
+ * intel_region_ttm_resource_to_st(), and can be freed using
+ * intel_region_ttm_resource_free().
*
* Return: A valid pointer on success, an error pointer on failure.
*/
struct ttm_resource *
-intel_region_ttm_node_alloc(struct intel_memory_region *mem,
- resource_size_t size,
- unsigned int flags)
+intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
+ resource_size_t size,
+ unsigned int flags)
{
struct ttm_resource_manager *man = mem->region_private;
struct ttm_place place = {};
@@ -203,24 +167,26 @@ intel_region_ttm_node_alloc(struct intel_memory_region *mem,
struct ttm_resource *res;
int ret;
- /*
- * We ignore the flags for now since we're using the range
- * manager and contigous and min page size would be fulfilled
- * by default if size is min page size aligned.
- */
mock_bo.base.size = size;
-
- if (mem->is_range_manager) {
- if (size >= SZ_1G)
- mock_bo.page_alignment = SZ_1G >> PAGE_SHIFT;
- else if (size >= SZ_2M)
- mock_bo.page_alignment = SZ_2M >> PAGE_SHIFT;
- else if (size >= SZ_64K)
- mock_bo.page_alignment = SZ_64K >> PAGE_SHIFT;
- }
+ place.flags = flags;
ret = man->func->alloc(man, &mock_bo, &place, &res);
if (ret == -ENOSPC)
ret = -ENXIO;
return ret ? ERR_PTR(ret) : res;
}
+
+#endif
+
+/**
+ * intel_region_ttm_resource_free - Free a resource allocated from a resource manager
+ * @mem: The region the resource was allocated from.
+ * @res: The opaque resource representing an allocation.
+ */
+void intel_region_ttm_resource_free(struct intel_memory_region *mem,
+ struct ttm_resource *res)
+{
+ struct ttm_resource_manager *man = mem->region_private;
+
+ man->func->free(man, res);
+}
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.h b/drivers/gpu/drm/i915/intel_region_ttm.h
index 11b0574ab791..6f44075920f2 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.h
+++ b/drivers/gpu/drm/i915/intel_region_ttm.h
@@ -12,6 +12,7 @@
struct drm_i915_private;
struct intel_memory_region;
struct ttm_resource;
+struct ttm_device_funcs;
int intel_region_ttm_device_init(struct drm_i915_private *dev_priv);
@@ -21,14 +22,20 @@ int intel_region_ttm_init(struct intel_memory_region *mem);
void intel_region_ttm_fini(struct intel_memory_region *mem);
-struct sg_table *intel_region_ttm_node_to_st(struct intel_memory_region *mem,
- struct ttm_resource *res);
+struct sg_table *intel_region_ttm_resource_to_st(struct intel_memory_region *mem,
+ struct ttm_resource *res);
-struct ttm_resource *
-intel_region_ttm_node_alloc(struct intel_memory_region *mem,
- resource_size_t size,
- unsigned int flags);
+void intel_region_ttm_resource_free(struct intel_memory_region *mem,
+ struct ttm_resource *res);
+
+int intel_region_to_ttm_type(const struct intel_memory_region *mem);
-void intel_region_ttm_node_free(struct intel_memory_region *mem,
- struct ttm_resource *node);
+struct ttm_device_funcs *i915_ttm_driver(void);
+
+#ifdef CONFIG_DRM_I915_SELFTEST
+struct ttm_resource *
+intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
+ resource_size_t size,
+ unsigned int flags);
+#endif
#endif /* _INTEL_REGION_TTM_H_ */
diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c
index f0a82b37bd1a..e304bf44e1ff 100644
--- a/drivers/gpu/drm/i915/intel_sideband.c
+++ b/drivers/gpu/drm/i915/intel_sideband.c
@@ -556,17 +556,22 @@ out:
#undef COND
}
-void intel_pcode_init(struct drm_i915_private *i915)
+int intel_pcode_init(struct drm_i915_private *i915)
{
- int ret;
+ int ret = 0;
if (!IS_DGFX(i915))
- return;
+ return ret;
ret = skl_pcode_request(i915, DG1_PCODE_STATUS,
DG1_UNCORE_GET_INIT_STATUS,
DG1_UNCORE_INIT_STATUS_COMPLETE,
- DG1_UNCORE_INIT_STATUS_COMPLETE, 50);
+ DG1_UNCORE_INIT_STATUS_COMPLETE, 180000);
+
+ drm_dbg(&i915->drm, "PCODE init status %d\n", ret);
+
if (ret)
drm_err(&i915->drm, "Pcode did not report uncore initialization completion!\n");
+
+ return ret;
}
diff --git a/drivers/gpu/drm/i915/intel_sideband.h b/drivers/gpu/drm/i915/intel_sideband.h
index 094c7b19c5d4..d1d14bcb8f56 100644
--- a/drivers/gpu/drm/i915/intel_sideband.h
+++ b/drivers/gpu/drm/i915/intel_sideband.h
@@ -138,6 +138,6 @@ int sandybridge_pcode_write_timeout(struct drm_i915_private *i915, u32 mbox,
int skl_pcode_request(struct drm_i915_private *i915, u32 mbox, u32 request,
u32 reply_mask, u32 reply, int timeout_base_ms);
-void intel_pcode_init(struct drm_i915_private *i915);
+int intel_pcode_init(struct drm_i915_private *i915);
#endif /* _INTEL_SIDEBAND_H */
diff --git a/drivers/gpu/drm/i915/intel_step.c b/drivers/gpu/drm/i915/intel_step.c
index ba9479a67521..6cf967631395 100644
--- a/drivers/gpu/drm/i915/intel_step.c
+++ b/drivers/gpu/drm/i915/intel_step.c
@@ -7,16 +7,32 @@
#include "intel_step.h"
/*
- * KBL revision ID ordering is bizarre; higher revision ID's map to lower
- * steppings in some cases. So rather than test against the revision ID
- * directly, let's map that into our own range of increasing ID's that we
- * can test against in a regular manner.
+ * Some platforms have unusual ways of mapping PCI revision ID to GT/display
+ * steppings. E.g., in some cases a higher PCI revision may translate to a
+ * lower stepping of the GT and/or display IP. This file provides lookup
+ * tables to map the PCI revision into a standard set of stepping values that
+ * can be compared numerically.
+ *
+ * Also note that some revisions/steppings may have been set aside as
+ * placeholders but never materialized in real hardware; in those cases there
+ * may be jumps in the revision IDs or stepping values in the tables below.
*/
+/*
+ * Some platforms always have the same stepping value for GT and display;
+ * use a macro to define these to make it easier to identify the platforms
+ * where the two steppings can deviate.
+ */
+#define COMMON_STEP(x) .gt_step = STEP_##x, .display_step = STEP_##x
+
+static const struct intel_step_info skl_revids[] = {
+ [0x6] = { COMMON_STEP(G0) },
+ [0x7] = { COMMON_STEP(H0) },
+ [0x9] = { COMMON_STEP(J0) },
+ [0xA] = { COMMON_STEP(I1) },
+};
-/* FIXME: what about REVID_E0 */
static const struct intel_step_info kbl_revids[] = {
- [0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
[1] = { .gt_step = STEP_B0, .display_step = STEP_B0 },
[2] = { .gt_step = STEP_C0, .display_step = STEP_B0 },
[3] = { .gt_step = STEP_D0, .display_step = STEP_B0 },
@@ -26,7 +42,27 @@ static const struct intel_step_info kbl_revids[] = {
[7] = { .gt_step = STEP_G0, .display_step = STEP_C0 },
};
-static const struct intel_step_info tgl_uy_revid_step_tbl[] = {
+static const struct intel_step_info bxt_revids[] = {
+ [0xA] = { COMMON_STEP(C0) },
+ [0xB] = { COMMON_STEP(C0) },
+ [0xC] = { COMMON_STEP(D0) },
+ [0xD] = { COMMON_STEP(E0) },
+};
+
+static const struct intel_step_info glk_revids[] = {
+ [3] = { COMMON_STEP(B0) },
+};
+
+static const struct intel_step_info icl_revids[] = {
+ [7] = { COMMON_STEP(D0) },
+};
+
+static const struct intel_step_info jsl_ehl_revids[] = {
+ [0] = { COMMON_STEP(A0) },
+ [1] = { COMMON_STEP(B0) },
+};
+
+static const struct intel_step_info tgl_uy_revids[] = {
[0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
[1] = { .gt_step = STEP_B0, .display_step = STEP_C0 },
[2] = { .gt_step = STEP_B1, .display_step = STEP_C0 },
@@ -34,12 +70,23 @@ static const struct intel_step_info tgl_uy_revid_step_tbl[] = {
};
/* Same GT stepping between tgl_uy_revids and tgl_revids don't mean the same HW */
-static const struct intel_step_info tgl_revid_step_tbl[] = {
+static const struct intel_step_info tgl_revids[] = {
[0] = { .gt_step = STEP_A0, .display_step = STEP_B0 },
[1] = { .gt_step = STEP_B0, .display_step = STEP_D0 },
};
-static const struct intel_step_info adls_revid_step_tbl[] = {
+static const struct intel_step_info rkl_revids[] = {
+ [0] = { COMMON_STEP(A0) },
+ [1] = { COMMON_STEP(B0) },
+ [4] = { COMMON_STEP(C0) },
+};
+
+static const struct intel_step_info dg1_revids[] = {
+ [0] = { COMMON_STEP(A0) },
+ [1] = { COMMON_STEP(B0) },
+};
+
+static const struct intel_step_info adls_revids[] = {
[0x0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
[0x1] = { .gt_step = STEP_A0, .display_step = STEP_A2 },
[0x4] = { .gt_step = STEP_B0, .display_step = STEP_B0 },
@@ -47,13 +94,33 @@ static const struct intel_step_info adls_revid_step_tbl[] = {
[0xC] = { .gt_step = STEP_D0, .display_step = STEP_C0 },
};
-static const struct intel_step_info adlp_revid_step_tbl[] = {
+static const struct intel_step_info adlp_revids[] = {
[0x0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
[0x4] = { .gt_step = STEP_B0, .display_step = STEP_B0 },
[0x8] = { .gt_step = STEP_C0, .display_step = STEP_C0 },
[0xC] = { .gt_step = STEP_C0, .display_step = STEP_D0 },
};
+static const struct intel_step_info xehpsdv_revids[] = {
+ [0x0] = { .gt_step = STEP_A0 },
+ [0x1] = { .gt_step = STEP_A1 },
+ [0x4] = { .gt_step = STEP_B0 },
+ [0x8] = { .gt_step = STEP_C0 },
+};
+
+static const struct intel_step_info dg2_g10_revid_step_tbl[] = {
+ [0x0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
+ [0x1] = { .gt_step = STEP_A1, .display_step = STEP_A0 },
+ [0x4] = { .gt_step = STEP_B0, .display_step = STEP_B0 },
+ [0x8] = { .gt_step = STEP_C0, .display_step = STEP_C0 },
+};
+
+static const struct intel_step_info dg2_g11_revid_step_tbl[] = {
+ [0x0] = { .gt_step = STEP_A0, .display_step = STEP_B0 },
+ [0x4] = { .gt_step = STEP_B0, .display_step = STEP_C0 },
+ [0x5] = { .gt_step = STEP_B1, .display_step = STEP_C0 },
+};
+
void intel_step_init(struct drm_i915_private *i915)
{
const struct intel_step_info *revids = NULL;
@@ -61,21 +128,51 @@ void intel_step_init(struct drm_i915_private *i915)
int revid = INTEL_REVID(i915);
struct intel_step_info step = {};
- if (IS_ALDERLAKE_P(i915)) {
- revids = adlp_revid_step_tbl;
- size = ARRAY_SIZE(adlp_revid_step_tbl);
+ if (IS_DG2_G10(i915)) {
+ revids = dg2_g10_revid_step_tbl;
+ size = ARRAY_SIZE(dg2_g10_revid_step_tbl);
+ } else if (IS_DG2_G11(i915)) {
+ revids = dg2_g11_revid_step_tbl;
+ size = ARRAY_SIZE(dg2_g11_revid_step_tbl);
+ } else if (IS_XEHPSDV(i915)) {
+ revids = xehpsdv_revids;
+ size = ARRAY_SIZE(xehpsdv_revids);
+ } else if (IS_ALDERLAKE_P(i915)) {
+ revids = adlp_revids;
+ size = ARRAY_SIZE(adlp_revids);
} else if (IS_ALDERLAKE_S(i915)) {
- revids = adls_revid_step_tbl;
- size = ARRAY_SIZE(adls_revid_step_tbl);
+ revids = adls_revids;
+ size = ARRAY_SIZE(adls_revids);
+ } else if (IS_DG1(i915)) {
+ revids = dg1_revids;
+ size = ARRAY_SIZE(dg1_revids);
+ } else if (IS_ROCKETLAKE(i915)) {
+ revids = rkl_revids;
+ size = ARRAY_SIZE(rkl_revids);
} else if (IS_TGL_U(i915) || IS_TGL_Y(i915)) {
- revids = tgl_uy_revid_step_tbl;
- size = ARRAY_SIZE(tgl_uy_revid_step_tbl);
+ revids = tgl_uy_revids;
+ size = ARRAY_SIZE(tgl_uy_revids);
} else if (IS_TIGERLAKE(i915)) {
- revids = tgl_revid_step_tbl;
- size = ARRAY_SIZE(tgl_revid_step_tbl);
+ revids = tgl_revids;
+ size = ARRAY_SIZE(tgl_revids);
+ } else if (IS_JSL_EHL(i915)) {
+ revids = jsl_ehl_revids;
+ size = ARRAY_SIZE(jsl_ehl_revids);
+ } else if (IS_ICELAKE(i915)) {
+ revids = icl_revids;
+ size = ARRAY_SIZE(icl_revids);
+ } else if (IS_GEMINILAKE(i915)) {
+ revids = glk_revids;
+ size = ARRAY_SIZE(glk_revids);
+ } else if (IS_BROXTON(i915)) {
+ revids = bxt_revids;
+ size = ARRAY_SIZE(bxt_revids);
} else if (IS_KABYLAKE(i915)) {
revids = kbl_revids;
size = ARRAY_SIZE(kbl_revids);
+ } else if (IS_SKYLAKE(i915)) {
+ revids = skl_revids;
+ size = ARRAY_SIZE(skl_revids);
}
/* Not using the stepping scheme for the platform yet. */
@@ -114,3 +211,17 @@ void intel_step_init(struct drm_i915_private *i915)
RUNTIME_INFO(i915)->step = step;
}
+
+#define STEP_NAME_CASE(name) \
+ case STEP_##name: \
+ return #name;
+
+const char *intel_step_name(enum intel_step step)
+{
+ switch (step) {
+ STEP_NAME_LIST(STEP_NAME_CASE);
+
+ default:
+ return "**";
+ }
+}
diff --git a/drivers/gpu/drm/i915/intel_step.h b/drivers/gpu/drm/i915/intel_step.h
index 958a8bb5d677..f6641e2a3c77 100644
--- a/drivers/gpu/drm/i915/intel_step.h
+++ b/drivers/gpu/drm/i915/intel_step.h
@@ -15,26 +15,39 @@ struct intel_step_info {
u8 display_step;
};
+#define STEP_ENUM_VAL(name) STEP_##name,
+
+#define STEP_NAME_LIST(func) \
+ func(A0) \
+ func(A1) \
+ func(A2) \
+ func(B0) \
+ func(B1) \
+ func(B2) \
+ func(C0) \
+ func(C1) \
+ func(D0) \
+ func(D1) \
+ func(E0) \
+ func(F0) \
+ func(G0) \
+ func(H0) \
+ func(I0) \
+ func(I1) \
+ func(J0)
+
/*
* Symbolic steppings that do not match the hardware. These are valid both as gt
* and display steppings as symbolic names.
*/
enum intel_step {
STEP_NONE = 0,
- STEP_A0,
- STEP_A2,
- STEP_B0,
- STEP_B1,
- STEP_C0,
- STEP_D0,
- STEP_D1,
- STEP_E0,
- STEP_F0,
- STEP_G0,
+ STEP_NAME_LIST(STEP_ENUM_VAL)
STEP_FUTURE,
STEP_FOREVER,
};
void intel_step_init(struct drm_i915_private *i915);
+const char *intel_step_name(enum intel_step step);
#endif /* __INTEL_STEP_H__ */
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 1bed8f666048..6b38bc2811c1 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -24,6 +24,8 @@
#include <linux/pm_runtime.h>
#include <asm/iosf_mbi.h>
+#include "gt/intel_lrc_reg.h" /* for shadow reg list */
+
#include "i915_drv.h"
#include "i915_trace.h"
#include "i915_vgpu.h"
@@ -68,8 +70,14 @@ static const char * const forcewake_domain_names[] = {
"vdbox1",
"vdbox2",
"vdbox3",
+ "vdbox4",
+ "vdbox5",
+ "vdbox6",
+ "vdbox7",
"vebox0",
"vebox1",
+ "vebox2",
+ "vebox3",
};
const char *
@@ -952,30 +960,80 @@ static const i915_reg_t gen8_shadowed_regs[] = {
};
static const i915_reg_t gen11_shadowed_regs[] = {
- RING_TAIL(RENDER_RING_BASE), /* 0x2000 (base) */
- GEN6_RPNSWREQ, /* 0xA008 */
- GEN6_RC_VIDEO_FREQ, /* 0xA00C */
- RING_TAIL(BLT_RING_BASE), /* 0x22000 (base) */
- RING_TAIL(GEN11_BSD_RING_BASE), /* 0x1C0000 (base) */
- RING_TAIL(GEN11_BSD2_RING_BASE), /* 0x1C4000 (base) */
- RING_TAIL(GEN11_VEBOX_RING_BASE), /* 0x1C8000 (base) */
- RING_TAIL(GEN11_BSD3_RING_BASE), /* 0x1D0000 (base) */
- RING_TAIL(GEN11_BSD4_RING_BASE), /* 0x1D4000 (base) */
- RING_TAIL(GEN11_VEBOX2_RING_BASE), /* 0x1D8000 (base) */
+ RING_TAIL(RENDER_RING_BASE), /* 0x2000 (base) */
+ RING_EXECLIST_CONTROL(RENDER_RING_BASE), /* 0x2550 */
+ GEN6_RPNSWREQ, /* 0xA008 */
+ GEN6_RC_VIDEO_FREQ, /* 0xA00C */
+ RING_TAIL(BLT_RING_BASE), /* 0x22000 (base) */
+ RING_EXECLIST_CONTROL(BLT_RING_BASE), /* 0x22550 */
+ RING_TAIL(GEN11_BSD_RING_BASE), /* 0x1C0000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD_RING_BASE), /* 0x1C0550 */
+ RING_TAIL(GEN11_BSD2_RING_BASE), /* 0x1C4000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD2_RING_BASE), /* 0x1C4550 */
+ RING_TAIL(GEN11_VEBOX_RING_BASE), /* 0x1C8000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_VEBOX_RING_BASE), /* 0x1C8550 */
+ RING_TAIL(GEN11_BSD3_RING_BASE), /* 0x1D0000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD3_RING_BASE), /* 0x1D0550 */
+ RING_TAIL(GEN11_BSD4_RING_BASE), /* 0x1D4000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD4_RING_BASE), /* 0x1D4550 */
+ RING_TAIL(GEN11_VEBOX2_RING_BASE), /* 0x1D8000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_VEBOX2_RING_BASE), /* 0x1D8550 */
/* TODO: Other registers are not yet used */
};
static const i915_reg_t gen12_shadowed_regs[] = {
- RING_TAIL(RENDER_RING_BASE), /* 0x2000 (base) */
- GEN6_RPNSWREQ, /* 0xA008 */
- GEN6_RC_VIDEO_FREQ, /* 0xA00C */
- RING_TAIL(BLT_RING_BASE), /* 0x22000 (base) */
- RING_TAIL(GEN11_BSD_RING_BASE), /* 0x1C0000 (base) */
- RING_TAIL(GEN11_BSD2_RING_BASE), /* 0x1C4000 (base) */
- RING_TAIL(GEN11_VEBOX_RING_BASE), /* 0x1C8000 (base) */
- RING_TAIL(GEN11_BSD3_RING_BASE), /* 0x1D0000 (base) */
- RING_TAIL(GEN11_BSD4_RING_BASE), /* 0x1D4000 (base) */
- RING_TAIL(GEN11_VEBOX2_RING_BASE), /* 0x1D8000 (base) */
+ RING_TAIL(RENDER_RING_BASE), /* 0x2000 (base) */
+ RING_EXECLIST_CONTROL(RENDER_RING_BASE), /* 0x2550 */
+ GEN6_RPNSWREQ, /* 0xA008 */
+ GEN6_RC_VIDEO_FREQ, /* 0xA00C */
+ RING_TAIL(BLT_RING_BASE), /* 0x22000 (base) */
+ RING_EXECLIST_CONTROL(BLT_RING_BASE), /* 0x22550 */
+ RING_TAIL(GEN11_BSD_RING_BASE), /* 0x1C0000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD_RING_BASE), /* 0x1C0550 */
+ RING_TAIL(GEN11_BSD2_RING_BASE), /* 0x1C4000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD2_RING_BASE), /* 0x1C4550 */
+ RING_TAIL(GEN11_VEBOX_RING_BASE), /* 0x1C8000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_VEBOX_RING_BASE), /* 0x1C8550 */
+ RING_TAIL(GEN11_BSD3_RING_BASE), /* 0x1D0000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD3_RING_BASE), /* 0x1D0550 */
+ RING_TAIL(GEN11_BSD4_RING_BASE), /* 0x1D4000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD4_RING_BASE), /* 0x1D4550 */
+ RING_TAIL(GEN11_VEBOX2_RING_BASE), /* 0x1D8000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_VEBOX2_RING_BASE), /* 0x1D8550 */
+ /* TODO: Other registers are not yet used */
+};
+
+static const i915_reg_t xehp_shadowed_regs[] = {
+ RING_TAIL(RENDER_RING_BASE), /* 0x2000 (base) */
+ RING_EXECLIST_CONTROL(RENDER_RING_BASE), /* 0x2550 */
+ GEN6_RPNSWREQ, /* 0xA008 */
+ GEN6_RC_VIDEO_FREQ, /* 0xA00C */
+ RING_TAIL(BLT_RING_BASE), /* 0x22000 (base) */
+ RING_EXECLIST_CONTROL(BLT_RING_BASE), /* 0x22550 */
+ RING_TAIL(GEN11_BSD_RING_BASE), /* 0x1C0000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD_RING_BASE), /* 0x1C0550 */
+ RING_TAIL(GEN11_BSD2_RING_BASE), /* 0x1C4000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD2_RING_BASE), /* 0x1C4550 */
+ RING_TAIL(GEN11_VEBOX_RING_BASE), /* 0x1C8000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_VEBOX_RING_BASE), /* 0x1C8550 */
+ RING_TAIL(GEN11_BSD3_RING_BASE), /* 0x1D0000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD3_RING_BASE), /* 0x1D0550 */
+ RING_TAIL(GEN11_BSD4_RING_BASE), /* 0x1D4000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_BSD4_RING_BASE), /* 0x1D4550 */
+ RING_TAIL(GEN11_VEBOX2_RING_BASE), /* 0x1D8000 (base) */
+ RING_EXECLIST_CONTROL(GEN11_VEBOX2_RING_BASE), /* 0x1D8550 */
+ RING_TAIL(XEHP_BSD5_RING_BASE), /* 0x1E0000 (base) */
+ RING_EXECLIST_CONTROL(XEHP_BSD5_RING_BASE), /* 0x1E0550 */
+ RING_TAIL(XEHP_BSD6_RING_BASE), /* 0x1E4000 (base) */
+ RING_EXECLIST_CONTROL(XEHP_BSD6_RING_BASE), /* 0x1E4550 */
+ RING_TAIL(XEHP_VEBOX3_RING_BASE), /* 0x1E8000 (base) */
+ RING_EXECLIST_CONTROL(XEHP_VEBOX3_RING_BASE), /* 0x1E8550 */
+ RING_TAIL(XEHP_BSD7_RING_BASE), /* 0x1F0000 (base) */
+ RING_EXECLIST_CONTROL(XEHP_BSD7_RING_BASE), /* 0x1F0550 */
+ RING_TAIL(XEHP_BSD8_RING_BASE), /* 0x1F4000 (base) */
+ RING_EXECLIST_CONTROL(XEHP_BSD8_RING_BASE), /* 0x1F4550 */
+ RING_TAIL(XEHP_VEBOX4_RING_BASE), /* 0x1F8000 (base) */
+ RING_EXECLIST_CONTROL(XEHP_VEBOX4_RING_BASE), /* 0x1F8550 */
/* TODO: Other registers are not yet used */
};
@@ -991,17 +1049,18 @@ static int mmio_reg_cmp(u32 key, const i915_reg_t *reg)
return 0;
}
-#define __is_genX_shadowed(x) \
-static bool is_gen##x##_shadowed(u32 offset) \
+#define __is_X_shadowed(x) \
+static bool is_##x##_shadowed(u32 offset) \
{ \
- const i915_reg_t *regs = gen##x##_shadowed_regs; \
- return BSEARCH(offset, regs, ARRAY_SIZE(gen##x##_shadowed_regs), \
+ const i915_reg_t *regs = x##_shadowed_regs; \
+ return BSEARCH(offset, regs, ARRAY_SIZE(x##_shadowed_regs), \
mmio_reg_cmp); \
}
-__is_genX_shadowed(8)
-__is_genX_shadowed(11)
-__is_genX_shadowed(12)
+__is_X_shadowed(gen8)
+__is_X_shadowed(gen11)
+__is_X_shadowed(gen12)
+__is_X_shadowed(xehp)
static enum forcewake_domains
gen6_reg_write_fw_domains(struct intel_uncore *uncore, i915_reg_t reg)
@@ -1065,6 +1124,15 @@ static const struct intel_forcewake_range __chv_fw_ranges[] = {
__fwd; \
})
+#define __xehp_fwtable_reg_write_fw_domains(uncore, offset) \
+({ \
+ enum forcewake_domains __fwd = 0; \
+ const u32 __offset = (offset); \
+ if (!is_xehp_shadowed(__offset)) \
+ __fwd = find_fw_domain(uncore, __offset); \
+ __fwd; \
+})
+
/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */
static const struct intel_forcewake_range __gen9_fw_ranges[] = {
GEN_FW_RANGE(0x0, 0xaff, FORCEWAKE_GT),
@@ -1249,6 +1317,172 @@ static const struct intel_forcewake_range __gen12_fw_ranges[] = {
0x1d3f00 - 0x1d3fff: VD2 */
};
+/*
+ * Graphics IP version 12.55 brings a slight change to the 0xd800 range,
+ * switching it from the GT domain to the render domain.
+ *
+ * *Must* be sorted by offset ranges! See intel_fw_table_check().
+ */
+#define XEHP_FWRANGES(FW_RANGE_D800) \
+ GEN_FW_RANGE(0x0, 0x1fff, 0), /* \
+ 0x0 - 0xaff: reserved \
+ 0xb00 - 0x1fff: always on */ \
+ GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER), \
+ GEN_FW_RANGE(0x2700, 0x4aff, FORCEWAKE_GT), \
+ GEN_FW_RANGE(0x4b00, 0x51ff, 0), /* \
+ 0x4b00 - 0x4fff: reserved \
+ 0x5000 - 0x51ff: always on */ \
+ GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), \
+ GEN_FW_RANGE(0x8000, 0x813f, FORCEWAKE_GT), \
+ GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER), \
+ GEN_FW_RANGE(0x8160, 0x81ff, 0), /* \
+ 0x8160 - 0x817f: reserved \
+ 0x8180 - 0x81ff: always on */ \
+ GEN_FW_RANGE(0x8200, 0x82ff, FORCEWAKE_GT), \
+ GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), \
+ GEN_FW_RANGE(0x8500, 0x8cff, FORCEWAKE_GT), /* \
+ 0x8500 - 0x87ff: gt \
+ 0x8800 - 0x8c7f: reserved \
+ 0x8c80 - 0x8cff: gt (DG2 only) */ \
+ GEN_FW_RANGE(0x8d00, 0x8fff, FORCEWAKE_RENDER), /* \
+ 0x8d00 - 0x8dff: render (DG2 only) \
+ 0x8e00 - 0x8fff: reserved */ \
+ GEN_FW_RANGE(0x9000, 0x94cf, FORCEWAKE_GT), /* \
+ 0x9000 - 0x947f: gt \
+ 0x9480 - 0x94cf: reserved */ \
+ GEN_FW_RANGE(0x94d0, 0x955f, FORCEWAKE_RENDER), \
+ GEN_FW_RANGE(0x9560, 0x967f, 0), /* \
+ 0x9560 - 0x95ff: always on \
+ 0x9600 - 0x967f: reserved */ \
+ GEN_FW_RANGE(0x9680, 0x97ff, FORCEWAKE_RENDER), /* \
+ 0x9680 - 0x96ff: render (DG2 only) \
+ 0x9700 - 0x97ff: reserved */ \
+ GEN_FW_RANGE(0x9800, 0xcfff, FORCEWAKE_GT), /* \
+ 0x9800 - 0xb4ff: gt \
+ 0xb500 - 0xbfff: reserved \
+ 0xc000 - 0xcfff: gt */ \
+ GEN_FW_RANGE(0xd000, 0xd7ff, 0), \
+ GEN_FW_RANGE(0xd800, 0xd87f, FW_RANGE_D800), \
+ GEN_FW_RANGE(0xd880, 0xdbff, FORCEWAKE_GT), \
+ GEN_FW_RANGE(0xdc00, 0xdcff, FORCEWAKE_RENDER), \
+ GEN_FW_RANGE(0xdd00, 0xde7f, FORCEWAKE_GT), /* \
+ 0xdd00 - 0xddff: gt \
+ 0xde00 - 0xde7f: reserved */ \
+ GEN_FW_RANGE(0xde80, 0xe8ff, FORCEWAKE_RENDER), /* \
+ 0xde80 - 0xdfff: render \
+ 0xe000 - 0xe0ff: reserved \
+ 0xe100 - 0xe8ff: render */ \
+ GEN_FW_RANGE(0xe900, 0xffff, FORCEWAKE_GT), /* \
+ 0xe900 - 0xe9ff: gt \
+ 0xea00 - 0xefff: reserved \
+ 0xf000 - 0xffff: gt */ \
+ GEN_FW_RANGE(0x10000, 0x12fff, 0), /* \
+ 0x10000 - 0x11fff: reserved \
+ 0x12000 - 0x127ff: always on \
+ 0x12800 - 0x12fff: reserved */ \
+ GEN_FW_RANGE(0x13000, 0x131ff, FORCEWAKE_MEDIA_VDBOX0), /* DG2 only */ \
+ GEN_FW_RANGE(0x13200, 0x13fff, FORCEWAKE_MEDIA_VDBOX2), /* \
+ 0x13200 - 0x133ff: VD2 (DG2 only) \
+ 0x13400 - 0x13fff: reserved */ \
+ GEN_FW_RANGE(0x14000, 0x141ff, FORCEWAKE_MEDIA_VDBOX0), /* XEHPSDV only */ \
+ GEN_FW_RANGE(0x14200, 0x143ff, FORCEWAKE_MEDIA_VDBOX2), /* XEHPSDV only */ \
+ GEN_FW_RANGE(0x14400, 0x145ff, FORCEWAKE_MEDIA_VDBOX4), /* XEHPSDV only */ \
+ GEN_FW_RANGE(0x14600, 0x147ff, FORCEWAKE_MEDIA_VDBOX6), /* XEHPSDV only */ \
+ GEN_FW_RANGE(0x14800, 0x14fff, FORCEWAKE_RENDER), \
+ GEN_FW_RANGE(0x15000, 0x16dff, FORCEWAKE_GT), /* \
+ 0x15000 - 0x15fff: gt (DG2 only) \
+ 0x16000 - 0x16dff: reserved */ \
+ GEN_FW_RANGE(0x16e00, 0x1ffff, FORCEWAKE_RENDER), \
+ GEN_FW_RANGE(0x20000, 0x21fff, FORCEWAKE_MEDIA_VDBOX0), /* \
+ 0x20000 - 0x20fff: VD0 (XEHPSDV only) \
+ 0x21000 - 0x21fff: reserved */ \
+ GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_GT), \
+ GEN_FW_RANGE(0x24000, 0x2417f, 0), /* \
+ 0x24000 - 0x2407f: always on \
+ 0x24080 - 0x2417f: reserved */ \
+ GEN_FW_RANGE(0x24180, 0x249ff, FORCEWAKE_GT), /* \
+ 0x24180 - 0x241ff: gt \
+ 0x24200 - 0x249ff: reserved */ \
+ GEN_FW_RANGE(0x24a00, 0x251ff, FORCEWAKE_RENDER), /* \
+ 0x24a00 - 0x24a7f: render \
+ 0x24a80 - 0x251ff: reserved */ \
+ GEN_FW_RANGE(0x25200, 0x25fff, FORCEWAKE_GT), /* \
+ 0x25200 - 0x252ff: gt \
+ 0x25300 - 0x25fff: reserved */ \
+ GEN_FW_RANGE(0x26000, 0x2ffff, FORCEWAKE_RENDER), /* \
+ 0x26000 - 0x27fff: render \
+ 0x28000 - 0x29fff: reserved \
+ 0x2a000 - 0x2ffff: undocumented */ \
+ GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_GT), \
+ GEN_FW_RANGE(0x40000, 0x1bffff, 0), \
+ GEN_FW_RANGE(0x1c0000, 0x1c3fff, FORCEWAKE_MEDIA_VDBOX0), /* \
+ 0x1c0000 - 0x1c2bff: VD0 \
+ 0x1c2c00 - 0x1c2cff: reserved \
+ 0x1c2d00 - 0x1c2dff: VD0 \
+ 0x1c2e00 - 0x1c3eff: VD0 (DG2 only) \
+ 0x1c3f00 - 0x1c3fff: VD0 */ \
+ GEN_FW_RANGE(0x1c4000, 0x1c7fff, FORCEWAKE_MEDIA_VDBOX1), /* \
+ 0x1c4000 - 0x1c6bff: VD1 \
+ 0x1c6c00 - 0x1c6cff: reserved \
+ 0x1c6d00 - 0x1c6dff: VD1 \
+ 0x1c6e00 - 0x1c7fff: reserved */ \
+ GEN_FW_RANGE(0x1c8000, 0x1cbfff, FORCEWAKE_MEDIA_VEBOX0), /* \
+ 0x1c8000 - 0x1ca0ff: VE0 \
+ 0x1ca100 - 0x1cbfff: reserved */ \
+ GEN_FW_RANGE(0x1cc000, 0x1ccfff, FORCEWAKE_MEDIA_VDBOX0), \
+ GEN_FW_RANGE(0x1cd000, 0x1cdfff, FORCEWAKE_MEDIA_VDBOX2), \
+ GEN_FW_RANGE(0x1ce000, 0x1cefff, FORCEWAKE_MEDIA_VDBOX4), \
+ GEN_FW_RANGE(0x1cf000, 0x1cffff, FORCEWAKE_MEDIA_VDBOX6), \
+ GEN_FW_RANGE(0x1d0000, 0x1d3fff, FORCEWAKE_MEDIA_VDBOX2), /* \
+ 0x1d0000 - 0x1d2bff: VD2 \
+ 0x1d2c00 - 0x1d2cff: reserved \
+ 0x1d2d00 - 0x1d2dff: VD2 \
+ 0x1d2e00 - 0x1d3dff: VD2 (DG2 only) \
+ 0x1d3e00 - 0x1d3eff: reserved \
+ 0x1d3f00 - 0x1d3fff: VD2 */ \
+ GEN_FW_RANGE(0x1d4000, 0x1d7fff, FORCEWAKE_MEDIA_VDBOX3), /* \
+ 0x1d4000 - 0x1d6bff: VD3 \
+ 0x1d6c00 - 0x1d6cff: reserved \
+ 0x1d6d00 - 0x1d6dff: VD3 \
+ 0x1d6e00 - 0x1d7fff: reserved */ \
+ GEN_FW_RANGE(0x1d8000, 0x1dffff, FORCEWAKE_MEDIA_VEBOX1), /* \
+ 0x1d8000 - 0x1da0ff: VE1 \
+ 0x1da100 - 0x1dffff: reserved */ \
+ GEN_FW_RANGE(0x1e0000, 0x1e3fff, FORCEWAKE_MEDIA_VDBOX4), /* \
+ 0x1e0000 - 0x1e2bff: VD4 \
+ 0x1e2c00 - 0x1e2cff: reserved \
+ 0x1e2d00 - 0x1e2dff: VD4 \
+ 0x1e2e00 - 0x1e3eff: reserved \
+ 0x1e3f00 - 0x1e3fff: VD4 */ \
+ GEN_FW_RANGE(0x1e4000, 0x1e7fff, FORCEWAKE_MEDIA_VDBOX5), /* \
+ 0x1e4000 - 0x1e6bff: VD5 \
+ 0x1e6c00 - 0x1e6cff: reserved \
+ 0x1e6d00 - 0x1e6dff: VD5 \
+ 0x1e6e00 - 0x1e7fff: reserved */ \
+ GEN_FW_RANGE(0x1e8000, 0x1effff, FORCEWAKE_MEDIA_VEBOX2), /* \
+ 0x1e8000 - 0x1ea0ff: VE2 \
+ 0x1ea100 - 0x1effff: reserved */ \
+ GEN_FW_RANGE(0x1f0000, 0x1f3fff, FORCEWAKE_MEDIA_VDBOX6), /* \
+ 0x1f0000 - 0x1f2bff: VD6 \
+ 0x1f2c00 - 0x1f2cff: reserved \
+ 0x1f2d00 - 0x1f2dff: VD6 \
+ 0x1f2e00 - 0x1f3eff: reserved \
+ 0x1f3f00 - 0x1f3fff: VD6 */ \
+ GEN_FW_RANGE(0x1f4000, 0x1f7fff, FORCEWAKE_MEDIA_VDBOX7), /* \
+ 0x1f4000 - 0x1f6bff: VD7 \
+ 0x1f6c00 - 0x1f6cff: reserved \
+ 0x1f6d00 - 0x1f6dff: VD7 \
+ 0x1f6e00 - 0x1f7fff: reserved */ \
+ GEN_FW_RANGE(0x1f8000, 0x1fa0ff, FORCEWAKE_MEDIA_VEBOX3),
+
+static const struct intel_forcewake_range __xehp_fw_ranges[] = {
+ XEHP_FWRANGES(FORCEWAKE_GT)
+};
+
+static const struct intel_forcewake_range __dg2_fw_ranges[] = {
+ XEHP_FWRANGES(FORCEWAKE_RENDER)
+};
+
static void
ilk_dummy_write(struct intel_uncore *uncore)
{
@@ -1502,6 +1736,7 @@ __gen_write(func, 8) \
__gen_write(func, 16) \
__gen_write(func, 32)
+__gen_reg_write_funcs(xehp_fwtable);
__gen_reg_write_funcs(gen12_fwtable);
__gen_reg_write_funcs(gen11_fwtable);
__gen_reg_write_funcs(fwtable);
@@ -1582,8 +1817,14 @@ static int __fw_domain_init(struct intel_uncore *uncore,
BUILD_BUG_ON(FORCEWAKE_MEDIA_VDBOX1 != (1 << FW_DOMAIN_ID_MEDIA_VDBOX1));
BUILD_BUG_ON(FORCEWAKE_MEDIA_VDBOX2 != (1 << FW_DOMAIN_ID_MEDIA_VDBOX2));
BUILD_BUG_ON(FORCEWAKE_MEDIA_VDBOX3 != (1 << FW_DOMAIN_ID_MEDIA_VDBOX3));
+ BUILD_BUG_ON(FORCEWAKE_MEDIA_VDBOX4 != (1 << FW_DOMAIN_ID_MEDIA_VDBOX4));
+ BUILD_BUG_ON(FORCEWAKE_MEDIA_VDBOX5 != (1 << FW_DOMAIN_ID_MEDIA_VDBOX5));
+ BUILD_BUG_ON(FORCEWAKE_MEDIA_VDBOX6 != (1 << FW_DOMAIN_ID_MEDIA_VDBOX6));
+ BUILD_BUG_ON(FORCEWAKE_MEDIA_VDBOX7 != (1 << FW_DOMAIN_ID_MEDIA_VDBOX7));
BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX0 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX0));
BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX1 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX1));
+ BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX2 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX2));
+ BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX3 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX3));
d->mask = BIT(domain_id);
@@ -1870,36 +2111,40 @@ static int uncore_forcewake_init(struct intel_uncore *uncore)
return ret;
forcewake_early_sanitize(uncore, 0);
- if (IS_GRAPHICS_VER(i915, 6, 7)) {
- ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen6);
-
- if (IS_VALLEYVIEW(i915)) {
- ASSIGN_FW_DOMAINS_TABLE(uncore, __vlv_fw_ranges);
- ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable);
- } else {
- ASSIGN_READ_MMIO_VFUNCS(uncore, gen6);
- }
- } else if (GRAPHICS_VER(i915) == 8) {
- if (IS_CHERRYVIEW(i915)) {
- ASSIGN_FW_DOMAINS_TABLE(uncore, __chv_fw_ranges);
- ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
- ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable);
- } else {
- ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen8);
- ASSIGN_READ_MMIO_VFUNCS(uncore, gen6);
- }
- } else if (IS_GRAPHICS_VER(i915, 9, 10)) {
- ASSIGN_FW_DOMAINS_TABLE(uncore, __gen9_fw_ranges);
- ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
- ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable);
- } else if (GRAPHICS_VER(i915) == 11) {
- ASSIGN_FW_DOMAINS_TABLE(uncore, __gen11_fw_ranges);
- ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen11_fwtable);
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) {
+ ASSIGN_FW_DOMAINS_TABLE(uncore, __dg2_fw_ranges);
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, xehp_fwtable);
ASSIGN_READ_MMIO_VFUNCS(uncore, gen11_fwtable);
- } else {
+ } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
+ ASSIGN_FW_DOMAINS_TABLE(uncore, __xehp_fw_ranges);
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, xehp_fwtable);
+ ASSIGN_READ_MMIO_VFUNCS(uncore, gen11_fwtable);
+ } else if (GRAPHICS_VER(i915) >= 12) {
ASSIGN_FW_DOMAINS_TABLE(uncore, __gen12_fw_ranges);
ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen12_fwtable);
ASSIGN_READ_MMIO_VFUNCS(uncore, gen12_fwtable);
+ } else if (GRAPHICS_VER(i915) == 11) {
+ ASSIGN_FW_DOMAINS_TABLE(uncore, __gen11_fw_ranges);
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen11_fwtable);
+ ASSIGN_READ_MMIO_VFUNCS(uncore, gen11_fwtable);
+ } else if (IS_GRAPHICS_VER(i915, 9, 10)) {
+ ASSIGN_FW_DOMAINS_TABLE(uncore, __gen9_fw_ranges);
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
+ ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable);
+ } else if (IS_CHERRYVIEW(i915)) {
+ ASSIGN_FW_DOMAINS_TABLE(uncore, __chv_fw_ranges);
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
+ ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable);
+ } else if (GRAPHICS_VER(i915) == 8) {
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen8);
+ ASSIGN_READ_MMIO_VFUNCS(uncore, gen6);
+ } else if (IS_VALLEYVIEW(i915)) {
+ ASSIGN_FW_DOMAINS_TABLE(uncore, __vlv_fw_ranges);
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen6);
+ ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable);
+ } else if (IS_GRAPHICS_VER(i915, 6, 7)) {
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen6);
+ ASSIGN_READ_MMIO_VFUNCS(uncore, gen6);
}
uncore->pmic_bus_access_nb.notifier_call = i915_pmic_bus_access_notifier;
@@ -1929,7 +2174,7 @@ int intel_uncore_init_mmio(struct intel_uncore *uncore)
return -ENODEV;
}
- if (INTEL_GEN(i915) > 5 && !intel_vgpu_active(i915))
+ if (GRAPHICS_VER(i915) > 5 && !intel_vgpu_active(i915))
uncore->flags |= UNCORE_HAS_FORCEWAKE;
if (!intel_uncore_has_forcewake(uncore)) {
@@ -1988,6 +2233,22 @@ void intel_uncore_prune_engine_fw_domains(struct intel_uncore *uncore,
if (HAS_ENGINE(gt, _VCS(i)))
continue;
+ /*
+ * Starting with XeHP, the power well for an even-numbered
+ * VDBOX is also used for shared units within the
+ * media slice such as SFC. So even if the engine
+ * itself is fused off, we still need to initialize
+ * the forcewake domain if any of the other engines
+ * in the same media slice are present.
+ */
+ if (GRAPHICS_VER_FULL(uncore->i915) >= IP_VER(12, 50) && i % 2 == 0) {
+ if ((i + 1 < I915_MAX_VCS) && HAS_ENGINE(gt, _VCS(i + 1)))
+ continue;
+
+ if (HAS_ENGINE(gt, _VECS(i / 2)))
+ continue;
+ }
+
if (fw_domains & BIT(domain_id))
fw_domain_fini(uncore, domain_id);
}
@@ -2277,6 +2538,61 @@ intel_uncore_forcewake_for_reg(struct intel_uncore *uncore,
return fw_domains;
}
+u32 intel_uncore_read_with_mcr_steering_fw(struct intel_uncore *uncore,
+ i915_reg_t reg,
+ int slice, int subslice)
+{
+ u32 mcr_mask, mcr_ss, mcr, old_mcr, val;
+
+ lockdep_assert_held(&uncore->lock);
+
+ if (GRAPHICS_VER(uncore->i915) >= 11) {
+ mcr_mask = GEN11_MCR_SLICE_MASK | GEN11_MCR_SUBSLICE_MASK;
+ mcr_ss = GEN11_MCR_SLICE(slice) | GEN11_MCR_SUBSLICE(subslice);
+ } else {
+ mcr_mask = GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK;
+ mcr_ss = GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice);
+ }
+
+ old_mcr = mcr = intel_uncore_read_fw(uncore, GEN8_MCR_SELECTOR);
+
+ mcr &= ~mcr_mask;
+ mcr |= mcr_ss;
+ intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr);
+
+ val = intel_uncore_read_fw(uncore, reg);
+
+ mcr &= ~mcr_mask;
+ mcr |= old_mcr & mcr_mask;
+
+ intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr);
+
+ return val;
+}
+
+u32 intel_uncore_read_with_mcr_steering(struct intel_uncore *uncore,
+ i915_reg_t reg, int slice, int subslice)
+{
+ enum forcewake_domains fw_domains;
+ u32 val;
+
+ fw_domains = intel_uncore_forcewake_for_reg(uncore, reg,
+ FW_REG_READ);
+ fw_domains |= intel_uncore_forcewake_for_reg(uncore,
+ GEN8_MCR_SELECTOR,
+ FW_REG_READ | FW_REG_WRITE);
+
+ spin_lock_irq(&uncore->lock);
+ intel_uncore_forcewake_get__locked(uncore, fw_domains);
+
+ val = intel_uncore_read_with_mcr_steering_fw(uncore, reg, slice, subslice);
+
+ intel_uncore_forcewake_put__locked(uncore, fw_domains);
+ spin_unlock_irq(&uncore->lock);
+
+ return val;
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_uncore.c"
#include "selftests/intel_uncore.c"
diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h
index 59f0da8f1fbb..3c0b0a8b5250 100644
--- a/drivers/gpu/drm/i915/intel_uncore.h
+++ b/drivers/gpu/drm/i915/intel_uncore.h
@@ -52,8 +52,14 @@ enum forcewake_domain_id {
FW_DOMAIN_ID_MEDIA_VDBOX1,
FW_DOMAIN_ID_MEDIA_VDBOX2,
FW_DOMAIN_ID_MEDIA_VDBOX3,
+ FW_DOMAIN_ID_MEDIA_VDBOX4,
+ FW_DOMAIN_ID_MEDIA_VDBOX5,
+ FW_DOMAIN_ID_MEDIA_VDBOX6,
+ FW_DOMAIN_ID_MEDIA_VDBOX7,
FW_DOMAIN_ID_MEDIA_VEBOX0,
FW_DOMAIN_ID_MEDIA_VEBOX1,
+ FW_DOMAIN_ID_MEDIA_VEBOX2,
+ FW_DOMAIN_ID_MEDIA_VEBOX3,
FW_DOMAIN_ID_COUNT
};
@@ -66,10 +72,16 @@ enum forcewake_domains {
FORCEWAKE_MEDIA_VDBOX1 = BIT(FW_DOMAIN_ID_MEDIA_VDBOX1),
FORCEWAKE_MEDIA_VDBOX2 = BIT(FW_DOMAIN_ID_MEDIA_VDBOX2),
FORCEWAKE_MEDIA_VDBOX3 = BIT(FW_DOMAIN_ID_MEDIA_VDBOX3),
+ FORCEWAKE_MEDIA_VDBOX4 = BIT(FW_DOMAIN_ID_MEDIA_VDBOX4),
+ FORCEWAKE_MEDIA_VDBOX5 = BIT(FW_DOMAIN_ID_MEDIA_VDBOX5),
+ FORCEWAKE_MEDIA_VDBOX6 = BIT(FW_DOMAIN_ID_MEDIA_VDBOX6),
+ FORCEWAKE_MEDIA_VDBOX7 = BIT(FW_DOMAIN_ID_MEDIA_VDBOX7),
FORCEWAKE_MEDIA_VEBOX0 = BIT(FW_DOMAIN_ID_MEDIA_VEBOX0),
FORCEWAKE_MEDIA_VEBOX1 = BIT(FW_DOMAIN_ID_MEDIA_VEBOX1),
+ FORCEWAKE_MEDIA_VEBOX2 = BIT(FW_DOMAIN_ID_MEDIA_VEBOX2),
+ FORCEWAKE_MEDIA_VEBOX3 = BIT(FW_DOMAIN_ID_MEDIA_VEBOX3),
- FORCEWAKE_ALL = BIT(FW_DOMAIN_ID_COUNT) - 1
+ FORCEWAKE_ALL = BIT(FW_DOMAIN_ID_COUNT) - 1,
};
struct intel_uncore_funcs {
@@ -182,6 +194,12 @@ intel_uncore_has_fifo(const struct intel_uncore *uncore)
return uncore->flags & UNCORE_HAS_FIFO;
}
+u32 intel_uncore_read_with_mcr_steering_fw(struct intel_uncore *uncore,
+ i915_reg_t reg,
+ int slice, int subslice);
+u32 intel_uncore_read_with_mcr_steering(struct intel_uncore *uncore,
+ i915_reg_t reg, int slice, int subslice);
+
void
intel_uncore_mmio_debug_init_early(struct intel_uncore_mmio_debug *mmio_debug);
void intel_uncore_init_early(struct intel_uncore *uncore,
diff --git a/drivers/gpu/drm/i915/intel_wopcm.c b/drivers/gpu/drm/i915/intel_wopcm.c
index 8309455f13ea..5e511bb891f9 100644
--- a/drivers/gpu/drm/i915/intel_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_wopcm.c
@@ -56,8 +56,8 @@
/* 24KB at the end of WOPCM is reserved for RC6 CTX on BXT. */
#define BXT_WOPCM_RC6_CTX_RESERVED (SZ_16K + SZ_8K)
-/* 36KB WOPCM reserved at the end of WOPCM on CNL. */
-#define CNL_WOPCM_HW_CTX_RESERVED (SZ_32K + SZ_4K)
+/* 36KB WOPCM reserved at the end of WOPCM on ICL. */
+#define ICL_WOPCM_HW_CTX_RESERVED (SZ_32K + SZ_4K)
/* 128KB from GUC_WOPCM_RESERVED is reserved for FW on Gen9. */
#define GEN9_GUC_FW_RESERVED SZ_128K
@@ -93,8 +93,8 @@ static u32 context_reserved_size(struct drm_i915_private *i915)
{
if (IS_GEN9_LP(i915))
return BXT_WOPCM_RC6_CTX_RESERVED;
- else if (GRAPHICS_VER(i915) >= 10)
- return CNL_WOPCM_HW_CTX_RESERVED;
+ else if (GRAPHICS_VER(i915) >= 11)
+ return ICL_WOPCM_HW_CTX_RESERVED;
else
return 0;
}
@@ -126,7 +126,7 @@ static bool gen9_check_huc_fw_fits(struct drm_i915_private *i915,
u32 guc_wopcm_size, u32 huc_fw_size)
{
/*
- * On Gen9 & CNL A0, hardware requires the total available GuC WOPCM
+ * On Gen9, hardware requires the total available GuC WOPCM
* size to be larger than or equal to HuC firmware size. Otherwise,
* firmware uploading would fail.
*/
diff --git a/drivers/gpu/drm/i915/selftests/i915_buddy.c b/drivers/gpu/drm/i915/selftests/i915_buddy.c
new file mode 100644
index 000000000000..d61ec9c951bf
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_buddy.c
@@ -0,0 +1,787 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#include <linux/prime_numbers.h>
+
+#include "../i915_selftest.h"
+#include "i915_random.h"
+
+static void __igt_dump_block(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block,
+ bool buddy)
+{
+ pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
+ block->header,
+ i915_buddy_block_state(block),
+ i915_buddy_block_order(block),
+ i915_buddy_block_offset(block),
+ i915_buddy_block_size(mm, block),
+ yesno(!block->parent),
+ yesno(buddy));
+}
+
+static void igt_dump_block(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+ struct i915_buddy_block *buddy;
+
+ __igt_dump_block(mm, block, false);
+
+ buddy = get_buddy(block);
+ if (buddy)
+ __igt_dump_block(mm, buddy, true);
+}
+
+static int igt_check_block(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+ struct i915_buddy_block *buddy;
+ unsigned int block_state;
+ u64 block_size;
+ u64 offset;
+ int err = 0;
+
+ block_state = i915_buddy_block_state(block);
+
+ if (block_state != I915_BUDDY_ALLOCATED &&
+ block_state != I915_BUDDY_FREE &&
+ block_state != I915_BUDDY_SPLIT) {
+ pr_err("block state mismatch\n");
+ err = -EINVAL;
+ }
+
+ block_size = i915_buddy_block_size(mm, block);
+ offset = i915_buddy_block_offset(block);
+
+ if (block_size < mm->chunk_size) {
+ pr_err("block size smaller than min size\n");
+ err = -EINVAL;
+ }
+
+ if (!is_power_of_2(block_size)) {
+ pr_err("block size not power of two\n");
+ err = -EINVAL;
+ }
+
+ if (!IS_ALIGNED(block_size, mm->chunk_size)) {
+ pr_err("block size not aligned to min size\n");
+ err = -EINVAL;
+ }
+
+ if (!IS_ALIGNED(offset, mm->chunk_size)) {
+ pr_err("block offset not aligned to min size\n");
+ err = -EINVAL;
+ }
+
+ if (!IS_ALIGNED(offset, block_size)) {
+ pr_err("block offset not aligned to block size\n");
+ err = -EINVAL;
+ }
+
+ buddy = get_buddy(block);
+
+ if (!buddy && block->parent) {
+ pr_err("buddy has gone fishing\n");
+ err = -EINVAL;
+ }
+
+ if (buddy) {
+ if (i915_buddy_block_offset(buddy) != (offset ^ block_size)) {
+ pr_err("buddy has wrong offset\n");
+ err = -EINVAL;
+ }
+
+ if (i915_buddy_block_size(mm, buddy) != block_size) {
+ pr_err("buddy size mismatch\n");
+ err = -EINVAL;
+ }
+
+ if (i915_buddy_block_state(buddy) == block_state &&
+ block_state == I915_BUDDY_FREE) {
+ pr_err("block and its buddy are free\n");
+ err = -EINVAL;
+ }
+ }
+
+ return err;
+}
+
+static int igt_check_blocks(struct i915_buddy_mm *mm,
+ struct list_head *blocks,
+ u64 expected_size,
+ bool is_contiguous)
+{
+ struct i915_buddy_block *block;
+ struct i915_buddy_block *prev;
+ u64 total;
+ int err = 0;
+
+ block = NULL;
+ prev = NULL;
+ total = 0;
+
+ list_for_each_entry(block, blocks, link) {
+ err = igt_check_block(mm, block);
+
+ if (!i915_buddy_block_is_allocated(block)) {
+ pr_err("block not allocated\n"),
+ err = -EINVAL;
+ }
+
+ if (is_contiguous && prev) {
+ u64 prev_block_size;
+ u64 prev_offset;
+ u64 offset;
+
+ prev_offset = i915_buddy_block_offset(prev);
+ prev_block_size = i915_buddy_block_size(mm, prev);
+ offset = i915_buddy_block_offset(block);
+
+ if (offset != (prev_offset + prev_block_size)) {
+ pr_err("block offset mismatch\n");
+ err = -EINVAL;
+ }
+ }
+
+ if (err)
+ break;
+
+ total += i915_buddy_block_size(mm, block);
+ prev = block;
+ }
+
+ if (!err) {
+ if (total != expected_size) {
+ pr_err("size mismatch, expected=%llx, found=%llx\n",
+ expected_size, total);
+ err = -EINVAL;
+ }
+ return err;
+ }
+
+ if (prev) {
+ pr_err("prev block, dump:\n");
+ igt_dump_block(mm, prev);
+ }
+
+ pr_err("bad block, dump:\n");
+ igt_dump_block(mm, block);
+
+ return err;
+}
+
+static int igt_check_mm(struct i915_buddy_mm *mm)
+{
+ struct i915_buddy_block *root;
+ struct i915_buddy_block *prev;
+ unsigned int i;
+ u64 total;
+ int err = 0;
+
+ if (!mm->n_roots) {
+ pr_err("n_roots is zero\n");
+ return -EINVAL;
+ }
+
+ if (mm->n_roots != hweight64(mm->size)) {
+ pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
+ mm->n_roots, hweight64(mm->size));
+ return -EINVAL;
+ }
+
+ root = NULL;
+ prev = NULL;
+ total = 0;
+
+ for (i = 0; i < mm->n_roots; ++i) {
+ struct i915_buddy_block *block;
+ unsigned int order;
+
+ root = mm->roots[i];
+ if (!root) {
+ pr_err("root(%u) is NULL\n", i);
+ err = -EINVAL;
+ break;
+ }
+
+ err = igt_check_block(mm, root);
+
+ if (!i915_buddy_block_is_free(root)) {
+ pr_err("root not free\n");
+ err = -EINVAL;
+ }
+
+ order = i915_buddy_block_order(root);
+
+ if (!i) {
+ if (order != mm->max_order) {
+ pr_err("max order root missing\n");
+ err = -EINVAL;
+ }
+ }
+
+ if (prev) {
+ u64 prev_block_size;
+ u64 prev_offset;
+ u64 offset;
+
+ prev_offset = i915_buddy_block_offset(prev);
+ prev_block_size = i915_buddy_block_size(mm, prev);
+ offset = i915_buddy_block_offset(root);
+
+ if (offset != (prev_offset + prev_block_size)) {
+ pr_err("root offset mismatch\n");
+ err = -EINVAL;
+ }
+ }
+
+ block = list_first_entry_or_null(&mm->free_list[order],
+ struct i915_buddy_block,
+ link);
+ if (block != root) {
+ pr_err("root mismatch at order=%u\n", order);
+ err = -EINVAL;
+ }
+
+ if (err)
+ break;
+
+ prev = root;
+ total += i915_buddy_block_size(mm, root);
+ }
+
+ if (!err) {
+ if (total != mm->size) {
+ pr_err("expected mm size=%llx, found=%llx\n", mm->size,
+ total);
+ err = -EINVAL;
+ }
+ return err;
+ }
+
+ if (prev) {
+ pr_err("prev root(%u), dump:\n", i - 1);
+ igt_dump_block(mm, prev);
+ }
+
+ if (root) {
+ pr_err("bad root(%u), dump:\n", i);
+ igt_dump_block(mm, root);
+ }
+
+ return err;
+}
+
+static void igt_mm_config(u64 *size, u64 *chunk_size)
+{
+ I915_RND_STATE(prng);
+ u32 s, ms;
+
+ /* Nothing fancy, just try to get an interesting bit pattern */
+
+ prandom_seed_state(&prng, i915_selftest.random_seed);
+
+ /* Let size be a random number of pages up to 8 GB (2M pages) */
+ s = 1 + i915_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
+ /* Let the chunk size be a random power of 2 less than size */
+ ms = BIT(i915_prandom_u32_max_state(ilog2(s), &prng));
+ /* Round size down to the chunk size */
+ s &= -ms;
+
+ /* Convert from pages to bytes */
+ *chunk_size = (u64)ms << 12;
+ *size = (u64)s << 12;
+}
+
+static int igt_buddy_alloc_smoke(void *arg)
+{
+ struct i915_buddy_mm mm;
+ IGT_TIMEOUT(end_time);
+ I915_RND_STATE(prng);
+ u64 chunk_size;
+ u64 mm_size;
+ int *order;
+ int err, i;
+
+ igt_mm_config(&mm_size, &chunk_size);
+
+ pr_info("buddy_init with size=%llx, chunk_size=%llx\n", mm_size, chunk_size);
+
+ err = i915_buddy_init(&mm, mm_size, chunk_size);
+ if (err) {
+ pr_err("buddy_init failed(%d)\n", err);
+ return err;
+ }
+
+ order = i915_random_order(mm.max_order + 1, &prng);
+ if (!order)
+ goto out_fini;
+
+ for (i = 0; i <= mm.max_order; ++i) {
+ struct i915_buddy_block *block;
+ int max_order = order[i];
+ bool timeout = false;
+ LIST_HEAD(blocks);
+ int order;
+ u64 total;
+
+ err = igt_check_mm(&mm);
+ if (err) {
+ pr_err("pre-mm check failed, abort\n");
+ break;
+ }
+
+ pr_info("filling from max_order=%u\n", max_order);
+
+ order = max_order;
+ total = 0;
+
+ do {
+retry:
+ block = i915_buddy_alloc(&mm, order);
+ if (IS_ERR(block)) {
+ err = PTR_ERR(block);
+ if (err == -ENOMEM) {
+ pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+ order);
+ } else {
+ if (order--) {
+ err = 0;
+ goto retry;
+ }
+
+ pr_err("buddy_alloc with order=%d failed(%d)\n",
+ order, err);
+ }
+
+ break;
+ }
+
+ list_add_tail(&block->link, &blocks);
+
+ if (i915_buddy_block_order(block) != order) {
+ pr_err("buddy_alloc order mismatch\n");
+ err = -EINVAL;
+ break;
+ }
+
+ total += i915_buddy_block_size(&mm, block);
+
+ if (__igt_timeout(end_time, NULL)) {
+ timeout = true;
+ break;
+ }
+ } while (total < mm.size);
+
+ if (!err)
+ err = igt_check_blocks(&mm, &blocks, total, false);
+
+ i915_buddy_free_list(&mm, &blocks);
+
+ if (!err) {
+ err = igt_check_mm(&mm);
+ if (err)
+ pr_err("post-mm check failed\n");
+ }
+
+ if (err || timeout)
+ break;
+
+ cond_resched();
+ }
+
+ if (err == -ENOMEM)
+ err = 0;
+
+ kfree(order);
+out_fini:
+ i915_buddy_fini(&mm);
+
+ return err;
+}
+
+static int igt_buddy_alloc_pessimistic(void *arg)
+{
+ const unsigned int max_order = 16;
+ struct i915_buddy_block *block, *bn;
+ struct i915_buddy_mm mm;
+ unsigned int order;
+ LIST_HEAD(blocks);
+ int err;
+
+ /*
+ * Create a pot-sized mm, then allocate one of each possible
+ * order within. This should leave the mm with exactly one
+ * page left.
+ */
+
+ err = i915_buddy_init(&mm, PAGE_SIZE << max_order, PAGE_SIZE);
+ if (err) {
+ pr_err("buddy_init failed(%d)\n", err);
+ return err;
+ }
+ GEM_BUG_ON(mm.max_order != max_order);
+
+ for (order = 0; order < max_order; order++) {
+ block = i915_buddy_alloc(&mm, order);
+ if (IS_ERR(block)) {
+ pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+ order);
+ err = PTR_ERR(block);
+ goto err;
+ }
+
+ list_add_tail(&block->link, &blocks);
+ }
+
+ /* And now the last remaining block available */
+ block = i915_buddy_alloc(&mm, 0);
+ if (IS_ERR(block)) {
+ pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
+ err = PTR_ERR(block);
+ goto err;
+ }
+ list_add_tail(&block->link, &blocks);
+
+ /* Should be completely full! */
+ for (order = max_order; order--; ) {
+ block = i915_buddy_alloc(&mm, order);
+ if (!IS_ERR(block)) {
+ pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+ order);
+ list_add_tail(&block->link, &blocks);
+ err = -EINVAL;
+ goto err;
+ }
+ }
+
+ block = list_last_entry(&blocks, typeof(*block), link);
+ list_del(&block->link);
+ i915_buddy_free(&mm, block);
+
+ /* As we free in increasing size, we make available larger blocks */
+ order = 1;
+ list_for_each_entry_safe(block, bn, &blocks, link) {
+ list_del(&block->link);
+ i915_buddy_free(&mm, block);
+
+ block = i915_buddy_alloc(&mm, order);
+ if (IS_ERR(block)) {
+ pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+ order);
+ err = PTR_ERR(block);
+ goto err;
+ }
+ i915_buddy_free(&mm, block);
+ order++;
+ }
+
+ /* To confirm, now the whole mm should be available */
+ block = i915_buddy_alloc(&mm, max_order);
+ if (IS_ERR(block)) {
+ pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+ max_order);
+ err = PTR_ERR(block);
+ goto err;
+ }
+ i915_buddy_free(&mm, block);
+
+err:
+ i915_buddy_free_list(&mm, &blocks);
+ i915_buddy_fini(&mm);
+ return err;
+}
+
+static int igt_buddy_alloc_optimistic(void *arg)
+{
+ const int max_order = 16;
+ struct i915_buddy_block *block;
+ struct i915_buddy_mm mm;
+ LIST_HEAD(blocks);
+ int order;
+ int err;
+
+ /*
+ * Create a mm with one block of each order available, and
+ * try to allocate them all.
+ */
+
+ err = i915_buddy_init(&mm,
+ PAGE_SIZE * ((1 << (max_order + 1)) - 1),
+ PAGE_SIZE);
+ if (err) {
+ pr_err("buddy_init failed(%d)\n", err);
+ return err;
+ }
+ GEM_BUG_ON(mm.max_order != max_order);
+
+ for (order = 0; order <= max_order; order++) {
+ block = i915_buddy_alloc(&mm, order);
+ if (IS_ERR(block)) {
+ pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+ order);
+ err = PTR_ERR(block);
+ goto err;
+ }
+
+ list_add_tail(&block->link, &blocks);
+ }
+
+ /* Should be completely full! */
+ block = i915_buddy_alloc(&mm, 0);
+ if (!IS_ERR(block)) {
+ pr_info("buddy_alloc unexpectedly succeeded, it should be full!");
+ list_add_tail(&block->link, &blocks);
+ err = -EINVAL;
+ goto err;
+ }
+
+err:
+ i915_buddy_free_list(&mm, &blocks);
+ i915_buddy_fini(&mm);
+ return err;
+}
+
+static int igt_buddy_alloc_pathological(void *arg)
+{
+ const int max_order = 16;
+ struct i915_buddy_block *block;
+ struct i915_buddy_mm mm;
+ LIST_HEAD(blocks);
+ LIST_HEAD(holes);
+ int order, top;
+ int err;
+
+ /*
+ * Create a pot-sized mm, then allocate one of each possible
+ * order within. This should leave the mm with exactly one
+ * page left. Free the largest block, then whittle down again.
+ * Eventually we will have a fully 50% fragmented mm.
+ */
+
+ err = i915_buddy_init(&mm, PAGE_SIZE << max_order, PAGE_SIZE);
+ if (err) {
+ pr_err("buddy_init failed(%d)\n", err);
+ return err;
+ }
+ GEM_BUG_ON(mm.max_order != max_order);
+
+ for (top = max_order; top; top--) {
+ /* Make room by freeing the largest allocated block */
+ block = list_first_entry_or_null(&blocks, typeof(*block), link);
+ if (block) {
+ list_del(&block->link);
+ i915_buddy_free(&mm, block);
+ }
+
+ for (order = top; order--; ) {
+ block = i915_buddy_alloc(&mm, order);
+ if (IS_ERR(block)) {
+ pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
+ order, top);
+ err = PTR_ERR(block);
+ goto err;
+ }
+ list_add_tail(&block->link, &blocks);
+ }
+
+ /* There should be one final page for this sub-allocation */
+ block = i915_buddy_alloc(&mm, 0);
+ if (IS_ERR(block)) {
+ pr_info("buddy_alloc hit -ENOMEM for hole\n");
+ err = PTR_ERR(block);
+ goto err;
+ }
+ list_add_tail(&block->link, &holes);
+
+ block = i915_buddy_alloc(&mm, top);
+ if (!IS_ERR(block)) {
+ pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
+ top, max_order);
+ list_add_tail(&block->link, &blocks);
+ err = -EINVAL;
+ goto err;
+ }
+ }
+
+ i915_buddy_free_list(&mm, &holes);
+
+ /* Nothing larger than blocks of chunk_size now available */
+ for (order = 1; order <= max_order; order++) {
+ block = i915_buddy_alloc(&mm, order);
+ if (!IS_ERR(block)) {
+ pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+ order);
+ list_add_tail(&block->link, &blocks);
+ err = -EINVAL;
+ goto err;
+ }
+ }
+
+err:
+ list_splice_tail(&holes, &blocks);
+ i915_buddy_free_list(&mm, &blocks);
+ i915_buddy_fini(&mm);
+ return err;
+}
+
+static int igt_buddy_alloc_range(void *arg)
+{
+ struct i915_buddy_mm mm;
+ unsigned long page_num;
+ LIST_HEAD(blocks);
+ u64 chunk_size;
+ u64 offset;
+ u64 size;
+ u64 rem;
+ int err;
+
+ igt_mm_config(&size, &chunk_size);
+
+ pr_info("buddy_init with size=%llx, chunk_size=%llx\n", size, chunk_size);
+
+ err = i915_buddy_init(&mm, size, chunk_size);
+ if (err) {
+ pr_err("buddy_init failed(%d)\n", err);
+ return err;
+ }
+
+ err = igt_check_mm(&mm);
+ if (err) {
+ pr_err("pre-mm check failed, abort, abort, abort!\n");
+ goto err_fini;
+ }
+
+ rem = mm.size;
+ offset = 0;
+
+ for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
+ struct i915_buddy_block *block;
+ LIST_HEAD(tmp);
+
+ size = min(page_num * mm.chunk_size, rem);
+
+ err = i915_buddy_alloc_range(&mm, &tmp, offset, size);
+ if (err) {
+ if (err == -ENOMEM) {
+ pr_info("alloc_range hit -ENOMEM with size=%llx\n",
+ size);
+ } else {
+ pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
+ offset, size, err);
+ }
+
+ break;
+ }
+
+ block = list_first_entry_or_null(&tmp,
+ struct i915_buddy_block,
+ link);
+ if (!block) {
+ pr_err("alloc_range has no blocks\n");
+ err = -EINVAL;
+ break;
+ }
+
+ if (i915_buddy_block_offset(block) != offset) {
+ pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
+ i915_buddy_block_offset(block), offset);
+ err = -EINVAL;
+ }
+
+ if (!err)
+ err = igt_check_blocks(&mm, &tmp, size, true);
+
+ list_splice_tail(&tmp, &blocks);
+
+ if (err)
+ break;
+
+ offset += size;
+
+ rem -= size;
+ if (!rem)
+ break;
+
+ cond_resched();
+ }
+
+ if (err == -ENOMEM)
+ err = 0;
+
+ i915_buddy_free_list(&mm, &blocks);
+
+ if (!err) {
+ err = igt_check_mm(&mm);
+ if (err)
+ pr_err("post-mm check failed\n");
+ }
+
+err_fini:
+ i915_buddy_fini(&mm);
+
+ return err;
+}
+
+static int igt_buddy_alloc_limit(void *arg)
+{
+ struct i915_buddy_block *block;
+ struct i915_buddy_mm mm;
+ const u64 size = U64_MAX;
+ int err;
+
+ err = i915_buddy_init(&mm, size, PAGE_SIZE);
+ if (err)
+ return err;
+
+ if (mm.max_order != I915_BUDDY_MAX_ORDER) {
+ pr_err("mm.max_order(%d) != %d\n",
+ mm.max_order, I915_BUDDY_MAX_ORDER);
+ err = -EINVAL;
+ goto out_fini;
+ }
+
+ block = i915_buddy_alloc(&mm, mm.max_order);
+ if (IS_ERR(block)) {
+ err = PTR_ERR(block);
+ goto out_fini;
+ }
+
+ if (i915_buddy_block_order(block) != mm.max_order) {
+ pr_err("block order(%d) != %d\n",
+ i915_buddy_block_order(block), mm.max_order);
+ err = -EINVAL;
+ goto out_free;
+ }
+
+ if (i915_buddy_block_size(&mm, block) !=
+ BIT_ULL(mm.max_order) * PAGE_SIZE) {
+ pr_err("block size(%llu) != %llu\n",
+ i915_buddy_block_size(&mm, block),
+ BIT_ULL(mm.max_order) * PAGE_SIZE);
+ err = -EINVAL;
+ goto out_free;
+ }
+
+out_free:
+ i915_buddy_free(&mm, block);
+out_fini:
+ i915_buddy_fini(&mm);
+ return err;
+}
+
+int i915_buddy_mock_selftests(void)
+{
+ static const struct i915_subtest tests[] = {
+ SUBTEST(igt_buddy_alloc_pessimistic),
+ SUBTEST(igt_buddy_alloc_optimistic),
+ SUBTEST(igt_buddy_alloc_pathological),
+ SUBTEST(igt_buddy_alloc_smoke),
+ SUBTEST(igt_buddy_alloc_range),
+ SUBTEST(igt_buddy_alloc_limit),
+ };
+
+ return i915_subtests(tests, NULL);
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
index a92c0e9b7e6b..cfa5c4165a4f 100644
--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -26,6 +26,7 @@ selftest(gt_mocs, intel_mocs_live_selftests)
selftest(gt_pm, intel_gt_pm_live_selftests)
selftest(gt_heartbeat, intel_heartbeat_live_selftests)
selftest(requests, i915_request_live_selftests)
+selftest(migrate, intel_migrate_live_selftests)
selftest(active, i915_active_live_selftests)
selftest(objects, i915_gem_object_live_selftests)
selftest(mman, i915_gem_mman_live_selftests)
@@ -37,14 +38,14 @@ selftest(gem, i915_gem_live_selftests)
selftest(evict, i915_gem_evict_live_selftests)
selftest(hugepages, i915_gem_huge_page_live_selftests)
selftest(gem_contexts, i915_gem_context_live_selftests)
-selftest(gem_execbuf, i915_gem_execbuffer_live_selftests)
-selftest(blt, i915_gem_object_blt_live_selftests)
selftest(client, i915_gem_client_blt_live_selftests)
+selftest(gem_migrate, i915_gem_migrate_live_selftests)
selftest(reset, intel_reset_live_selftests)
selftest(memory_region, intel_memory_region_live_selftests)
selftest(hangcheck, intel_hangcheck_live_selftests)
selftest(execlists, intel_execlists_live_selftests)
selftest(ring_submission, intel_ring_submission_live_selftests)
selftest(perf, i915_perf_live_selftests)
+selftest(slpc, intel_slpc_live_selftests)
/* Here be dragons: keep last to run last! */
selftest(late_gt_pm, intel_gt_pm_late_selftests)
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
index 34e5caf38093..793fb28a770d 100644
--- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -32,5 +32,5 @@ selftest(vma, i915_vma_mock_selftests)
selftest(evict, i915_gem_evict_mock_selftests)
selftest(gtt, i915_gem_gtt_mock_selftests)
selftest(hugepages, i915_gem_huge_page_mock_selftests)
-selftest(contexts, i915_gem_context_mock_selftests)
selftest(memory_region, intel_memory_region_mock_selftests)
+selftest(buddy, i915_buddy_mock_selftests)
diff --git a/drivers/gpu/drm/i915/selftests/i915_perf_selftests.h b/drivers/gpu/drm/i915/selftests/i915_perf_selftests.h
index c2389f8a257d..058450d351f7 100644
--- a/drivers/gpu/drm/i915/selftests/i915_perf_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_perf_selftests.h
@@ -17,5 +17,5 @@
*/
selftest(engine_cs, intel_engine_cs_perf_selftests)
selftest(request, i915_request_perf_selftests)
-selftest(blt, i915_gem_object_blt_perf_selftests)
+selftest(migrate, intel_migrate_perf_selftests)
selftest(region, intel_memory_region_perf_selftests)
diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
index bd5c96a77ba3..d67710d10615 100644
--- a/drivers/gpu/drm/i915/selftests/i915_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_request.c
@@ -1313,7 +1313,7 @@ static int __live_parallel_engine1(void *arg)
i915_request_add(rq);
err = 0;
- if (i915_request_wait(rq, 0, HZ / 5) < 0)
+ if (i915_request_wait(rq, 0, HZ) < 0)
err = -ETIME;
i915_request_put(rq);
if (err)
@@ -1419,7 +1419,7 @@ static int __live_parallel_spin(void *arg)
}
igt_spinner_end(&spin);
- if (err == 0 && i915_request_wait(rq, 0, HZ / 5) < 0)
+ if (err == 0 && i915_request_wait(rq, 0, HZ) < 0)
err = -EIO;
i915_request_put(rq);
diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c
index 1bc11c09faef..484759c9409c 100644
--- a/drivers/gpu/drm/i915/selftests/i915_selftest.c
+++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c
@@ -187,7 +187,7 @@ int i915_mock_selftests(void)
err = run_selftests(mock, NULL);
if (err) {
i915_selftest.mock = err;
- return err;
+ return 1;
}
if (i915_selftest.mock < 0) {
@@ -430,7 +430,7 @@ module_param_named(st_timeout, i915_selftest.timeout_ms, uint, 0400);
module_param_named(st_filter, i915_selftest.filter, charp, 0400);
module_param_named_unsafe(mock_selftests, i915_selftest.mock, int, 0400);
-MODULE_PARM_DESC(mock_selftests, "Run selftests before loading, using mock hardware (0:disabled [default], 1:run tests then load driver, -1:run tests then exit module)");
+MODULE_PARM_DESC(mock_selftests, "Run selftests before loading, using mock hardware (0:disabled [default], 1:run tests then load driver, -1:run tests then leave dummy module)");
module_param_named_unsafe(live_selftests, i915_selftest.live, int, 0400);
MODULE_PARM_DESC(live_selftests, "Run selftests after driver initialisation on the live system (0:disabled [default], 1:run tests then continue, -1:run tests then exit module)");
diff --git a/drivers/gpu/drm/i915/selftests/igt_flush_test.c b/drivers/gpu/drm/i915/selftests/igt_flush_test.c
index 7b0939e3f007..a6c71fca61aa 100644
--- a/drivers/gpu/drm/i915/selftests/igt_flush_test.c
+++ b/drivers/gpu/drm/i915/selftests/igt_flush_test.c
@@ -19,7 +19,7 @@ int igt_flush_test(struct drm_i915_private *i915)
cond_resched();
- if (intel_gt_wait_for_idle(gt, HZ / 5) == -ETIME) {
+ if (intel_gt_wait_for_idle(gt, HZ) == -ETIME) {
pr_err("%pS timed out, cancelling all further testing.\n",
__builtin_return_address(0));
diff --git a/drivers/gpu/drm/i915/selftests/igt_live_test.c b/drivers/gpu/drm/i915/selftests/igt_live_test.c
index c130010a7033..1c721542e277 100644
--- a/drivers/gpu/drm/i915/selftests/igt_live_test.c
+++ b/drivers/gpu/drm/i915/selftests/igt_live_test.c
@@ -5,7 +5,7 @@
*/
#include "i915_drv.h"
-#include "gt/intel_gt_requests.h"
+#include "gt/intel_gt.h"
#include "../i915_selftest.h"
#include "igt_flush_test.h"
diff --git a/drivers/gpu/drm/i915/selftests/igt_mmap.c b/drivers/gpu/drm/i915/selftests/igt_mmap.c
index 583a4ff8b8c9..e920a461bd36 100644
--- a/drivers/gpu/drm/i915/selftests/igt_mmap.c
+++ b/drivers/gpu/drm/i915/selftests/igt_mmap.c
@@ -9,15 +9,28 @@
#include "i915_drv.h"
#include "igt_mmap.h"
-unsigned long igt_mmap_node(struct drm_i915_private *i915,
- struct drm_vma_offset_node *node,
- unsigned long addr,
- unsigned long prot,
- unsigned long flags)
+unsigned long igt_mmap_offset(struct drm_i915_private *i915,
+ u64 offset,
+ unsigned long size,
+ unsigned long prot,
+ unsigned long flags)
{
+ struct drm_vma_offset_node *node;
struct file *file;
+ unsigned long addr;
int err;
+ /* no need to refcount, we own this object */
+ drm_vma_offset_lock_lookup(i915->drm.vma_offset_manager);
+ node = drm_vma_offset_exact_lookup_locked(i915->drm.vma_offset_manager,
+ offset / PAGE_SIZE, size / PAGE_SIZE);
+ drm_vma_offset_unlock_lookup(i915->drm.vma_offset_manager);
+
+ if (GEM_WARN_ON(!node)) {
+ pr_info("Failed to lookup %llx\n", offset);
+ return -ENOENT;
+ }
+
/* Pretend to open("/dev/dri/card0") */
file = mock_drm_getfile(i915->drm.primary, O_RDWR);
if (IS_ERR(file))
@@ -29,7 +42,7 @@ unsigned long igt_mmap_node(struct drm_i915_private *i915,
goto out_file;
}
- addr = vm_mmap(file, addr, drm_vma_node_size(node) << PAGE_SHIFT,
+ addr = vm_mmap(file, 0, drm_vma_node_size(node) << PAGE_SHIFT,
prot, flags, drm_vma_node_offset_addr(node));
drm_vma_node_revoke(node, file->private_data);
diff --git a/drivers/gpu/drm/i915/selftests/igt_mmap.h b/drivers/gpu/drm/i915/selftests/igt_mmap.h
index 6e716cb59d7e..acbe34d81a6d 100644
--- a/drivers/gpu/drm/i915/selftests/igt_mmap.h
+++ b/drivers/gpu/drm/i915/selftests/igt_mmap.h
@@ -7,13 +7,15 @@
#ifndef IGT_MMAP_H
#define IGT_MMAP_H
+#include <linux/types.h>
+
struct drm_i915_private;
struct drm_vma_offset_node;
-unsigned long igt_mmap_node(struct drm_i915_private *i915,
- struct drm_vma_offset_node *node,
- unsigned long addr,
- unsigned long prot,
- unsigned long flags);
+unsigned long igt_mmap_offset(struct drm_i915_private *i915,
+ u64 offset,
+ unsigned long size,
+ unsigned long prot,
+ unsigned long flags);
#endif /* IGT_MMAP_H */
diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
index c85d516b85cd..418caae84759 100644
--- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
@@ -15,12 +15,15 @@
#include "gem/i915_gem_context.h"
#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
-#include "gem/i915_gem_object_blt.h"
#include "gem/selftests/igt_gem_utils.h"
#include "gem/selftests/mock_context.h"
+#include "gt/intel_engine_pm.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_gt.h"
+#include "i915_buddy.h"
+#include "gt/intel_migrate.h"
#include "i915_memcpy.h"
+#include "i915_ttm_buddy_manager.h"
#include "selftests/igt_flush_test.h"
#include "selftests/i915_random.h"
@@ -57,16 +60,15 @@ static int igt_mock_fill(void *arg)
LIST_HEAD(objects);
int err = 0;
- page_size = mem->chunk_size;
+ page_size = PAGE_SIZE;
+ max_pages = div64_u64(total, page_size);
rem = total;
-retry:
- max_pages = div64_u64(rem, page_size);
for_each_prime_number_from(page_num, 1, max_pages) {
resource_size_t size = page_num * page_size;
struct drm_i915_gem_object *obj;
- obj = i915_gem_object_create_region(mem, size, 0);
+ obj = i915_gem_object_create_region(mem, size, 0, 0);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
break;
@@ -86,11 +88,6 @@ retry:
err = 0;
if (err == -ENXIO) {
if (page_num * page_size <= rem) {
- if (mem->is_range_manager && max_pages > 1) {
- max_pages >>= 1;
- goto retry;
- }
-
pr_err("%s failed, space still left in region\n",
__func__);
err = -EINVAL;
@@ -113,7 +110,7 @@ igt_object_create(struct intel_memory_region *mem,
struct drm_i915_gem_object *obj;
int err;
- obj = i915_gem_object_create_region(mem, size, flags);
+ obj = i915_gem_object_create_region(mem, size, 0, flags);
if (IS_ERR(obj))
return obj;
@@ -157,6 +154,7 @@ static bool is_contiguous(struct drm_i915_gem_object *obj)
static int igt_mock_reserve(void *arg)
{
struct intel_memory_region *mem = arg;
+ struct drm_i915_private *i915 = mem->i915;
resource_size_t avail = resource_size(&mem->region);
struct drm_i915_gem_object *obj;
const u32 chunk_size = SZ_32M;
@@ -166,16 +164,18 @@ static int igt_mock_reserve(void *arg)
LIST_HEAD(objects);
int err = 0;
- if (!list_empty(&mem->reserved)) {
- pr_err("%s region reserved list is not empty\n", __func__);
- return -EINVAL;
- }
-
count = avail / chunk_size;
order = i915_random_order(count, &prng);
if (!order)
return 0;
+ mem = mock_region_create(i915, 0, SZ_2G, I915_GTT_PAGE_SIZE_4K, 0);
+ if (IS_ERR(mem)) {
+ pr_err("failed to create memory region\n");
+ err = PTR_ERR(mem);
+ goto out_free_order;
+ }
+
/* Reserve a bunch of ranges within the region */
for (i = 0; i < count; ++i) {
u64 start = order[i] * chunk_size;
@@ -205,18 +205,12 @@ static int igt_mock_reserve(void *arg)
do {
u32 size = i915_prandom_u32_max_state(cur_avail, &prng);
-retry:
size = max_t(u32, round_up(size, PAGE_SIZE), PAGE_SIZE);
obj = igt_object_create(mem, &objects, size, 0);
if (IS_ERR(obj)) {
- if (PTR_ERR(obj) == -ENXIO) {
- if (mem->is_range_manager &&
- size > mem->chunk_size) {
- size >>= 1;
- goto retry;
- }
+ if (PTR_ERR(obj) == -ENXIO)
break;
- }
+
err = PTR_ERR(obj);
goto out_close;
}
@@ -230,9 +224,10 @@ retry:
}
out_close:
- kfree(order);
close_objects(mem, &objects);
- intel_memory_region_unreserve(mem);
+ intel_memory_region_put(mem);
+out_free_order:
+ kfree(order);
return err;
}
@@ -252,7 +247,7 @@ static int igt_mock_contiguous(void *arg)
total = resource_size(&mem->region);
/* Min size */
- obj = igt_object_create(mem, &objects, mem->chunk_size,
+ obj = igt_object_create(mem, &objects, PAGE_SIZE,
I915_BO_ALLOC_CONTIGUOUS);
if (IS_ERR(obj))
return PTR_ERR(obj);
@@ -333,17 +328,15 @@ static int igt_mock_contiguous(void *arg)
min = target;
target = total >> 1;
- if (!mem->is_range_manager) {
- /* Make sure we can still allocate all the fragmented space */
- obj = igt_object_create(mem, &objects, target, 0);
- if (IS_ERR(obj)) {
- err = PTR_ERR(obj);
- goto err_close_objects;
- }
-
- igt_object_release(obj);
+ /* Make sure we can still allocate all the fragmented space */
+ obj = igt_object_create(mem, &objects, target, 0);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ goto err_close_objects;
}
+ igt_object_release(obj);
+
/*
* Even though we have enough free space, we don't have a big enough
* contiguous block. Make sure that holds true.
@@ -362,7 +355,7 @@ static int igt_mock_contiguous(void *arg)
}
target >>= 1;
- } while (target >= mem->chunk_size);
+ } while (target >= PAGE_SIZE);
err_close_objects:
list_splice_tail(&holes, &objects);
@@ -374,7 +367,9 @@ static int igt_mock_splintered_region(void *arg)
{
struct intel_memory_region *mem = arg;
struct drm_i915_private *i915 = mem->i915;
+ struct i915_ttm_buddy_resource *res;
struct drm_i915_gem_object *obj;
+ struct i915_buddy_mm *mm;
unsigned int expected_order;
LIST_HEAD(objects);
u64 size;
@@ -382,7 +377,7 @@ static int igt_mock_splintered_region(void *arg)
/*
* Sanity check we can still allocate everything even if the
- * max_order != mm.size. i.e our starting address space size is not a
+ * mm.max_order != mm.size. i.e our starting address space size is not a
* power-of-two.
*/
@@ -391,20 +386,29 @@ static int igt_mock_splintered_region(void *arg)
if (IS_ERR(mem))
return PTR_ERR(mem);
- expected_order = get_order(rounddown_pow_of_two(size));
- if (mem->max_order != expected_order) {
- pr_err("%s order mismatch(%u != %u)\n",
- __func__, mem->max_order, expected_order);
- err = -EINVAL;
- goto out_put;
- }
-
obj = igt_object_create(mem, &objects, size, 0);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
goto out_close;
}
+ res = to_ttm_buddy_resource(obj->mm.res);
+ mm = res->mm;
+ if (mm->size != size) {
+ pr_err("%s size mismatch(%llu != %llu)\n",
+ __func__, mm->size, size);
+ err = -EINVAL;
+ goto out_put;
+ }
+
+ expected_order = get_order(rounddown_pow_of_two(size));
+ if (mm->max_order != expected_order) {
+ pr_err("%s order mismatch(%u != %u)\n",
+ __func__, mm->max_order, expected_order);
+ err = -EINVAL;
+ goto out_put;
+ }
+
close_objects(mem, &objects);
/*
@@ -415,15 +419,12 @@ static int igt_mock_splintered_region(void *arg)
* sure that does indeed hold true.
*/
- if (!mem->is_range_manager) {
- obj = igt_object_create(mem, &objects, size,
- I915_BO_ALLOC_CONTIGUOUS);
- if (!IS_ERR(obj)) {
- pr_err("%s too large contiguous allocation was not rejected\n",
- __func__);
- err = -EINVAL;
- goto out_close;
- }
+ obj = igt_object_create(mem, &objects, size, I915_BO_ALLOC_CONTIGUOUS);
+ if (!IS_ERR(obj)) {
+ pr_err("%s too large contiguous allocation was not rejected\n",
+ __func__);
+ err = -EINVAL;
+ goto out_close;
}
obj = igt_object_create(mem, &objects, rounddown_pow_of_two(size),
@@ -442,6 +443,74 @@ out_put:
return err;
}
+#ifndef SZ_8G
+#define SZ_8G BIT_ULL(33)
+#endif
+
+static int igt_mock_max_segment(void *arg)
+{
+ const unsigned int max_segment = rounddown(UINT_MAX, PAGE_SIZE);
+ struct intel_memory_region *mem = arg;
+ struct drm_i915_private *i915 = mem->i915;
+ struct i915_ttm_buddy_resource *res;
+ struct drm_i915_gem_object *obj;
+ struct i915_buddy_block *block;
+ struct i915_buddy_mm *mm;
+ struct list_head *blocks;
+ struct scatterlist *sg;
+ LIST_HEAD(objects);
+ u64 size;
+ int err = 0;
+
+ /*
+ * While we may create very large contiguous blocks, we may need
+ * to break those down for consumption elsewhere. In particular,
+ * dma-mapping with scatterlist elements have an implicit limit of
+ * UINT_MAX on each element.
+ */
+
+ size = SZ_8G;
+ mem = mock_region_create(i915, 0, size, PAGE_SIZE, 0);
+ if (IS_ERR(mem))
+ return PTR_ERR(mem);
+
+ obj = igt_object_create(mem, &objects, size, 0);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ goto out_put;
+ }
+
+ res = to_ttm_buddy_resource(obj->mm.res);
+ blocks = &res->blocks;
+ mm = res->mm;
+ size = 0;
+ list_for_each_entry(block, blocks, link) {
+ if (i915_buddy_block_size(mm, block) > size)
+ size = i915_buddy_block_size(mm, block);
+ }
+ if (size < max_segment) {
+ pr_err("%s: Failed to create a huge contiguous block [> %u], largest block %lld\n",
+ __func__, max_segment, size);
+ err = -EINVAL;
+ goto out_close;
+ }
+
+ for (sg = obj->mm.pages->sgl; sg; sg = sg_next(sg)) {
+ if (sg->length > max_segment) {
+ pr_err("%s: Created an oversized scatterlist entry, %u > %u\n",
+ __func__, sg->length, max_segment);
+ err = -EINVAL;
+ goto out_close;
+ }
+ }
+
+out_close:
+ close_objects(mem, &objects);
+out_put:
+ intel_memory_region_put(mem);
+ return err;
+}
+
static int igt_gpu_write_dw(struct intel_context *ce,
struct i915_vma *vma,
u32 dword,
@@ -579,6 +648,62 @@ out_put:
return err;
}
+static int igt_lmem_create_with_ps(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ int err = 0;
+ u32 ps;
+
+ for (ps = PAGE_SIZE; ps <= SZ_1G; ps <<= 1) {
+ struct drm_i915_gem_object *obj;
+ dma_addr_t daddr;
+
+ obj = __i915_gem_object_create_lmem_with_ps(i915, ps, ps, 0);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ if (err == -ENXIO || err == -E2BIG) {
+ pr_info("%s not enough lmem for ps(%u) err=%d\n",
+ __func__, ps, err);
+ err = 0;
+ }
+
+ break;
+ }
+
+ if (obj->base.size != ps) {
+ pr_err("%s size(%zu) != ps(%u)\n",
+ __func__, obj->base.size, ps);
+ err = -EINVAL;
+ goto out_put;
+ }
+
+ i915_gem_object_lock(obj, NULL);
+ err = i915_gem_object_pin_pages(obj);
+ if (err)
+ goto out_put;
+
+ daddr = i915_gem_object_get_dma_address(obj, 0);
+ if (!IS_ALIGNED(daddr, ps)) {
+ pr_err("%s daddr(%pa) not aligned with ps(%u)\n",
+ __func__, &daddr, ps);
+ err = -EINVAL;
+ goto out_unpin;
+ }
+
+out_unpin:
+ i915_gem_object_unpin_pages(obj);
+ __i915_gem_object_put_pages(obj);
+out_put:
+ i915_gem_object_unlock(obj);
+ i915_gem_object_put(obj);
+
+ if (err)
+ break;
+ }
+
+ return err;
+}
+
static int igt_lmem_create_cleared_cpu(void *arg)
{
struct drm_i915_private *i915 = arg;
@@ -741,6 +866,7 @@ static int igt_lmem_write_cpu(void *arg)
PAGE_SIZE - 64,
};
struct intel_engine_cs *engine;
+ struct i915_request *rq;
u32 *vaddr;
u32 sz;
u32 i;
@@ -767,15 +893,20 @@ static int igt_lmem_write_cpu(void *arg)
goto out_put;
}
+ i915_gem_object_lock(obj, NULL);
/* Put the pages into a known state -- from the gpu for added fun */
intel_engine_pm_get(engine);
- err = i915_gem_object_fill_blt(obj, engine->kernel_context, 0xdeadbeaf);
- intel_engine_pm_put(engine);
- if (err)
- goto out_unpin;
+ err = intel_context_migrate_clear(engine->gt->migrate.context, NULL,
+ obj->mm.pages->sgl, I915_CACHE_NONE,
+ true, 0xdeadbeaf, &rq);
+ if (rq) {
+ dma_resv_add_excl_fence(obj->base.resv, &rq->fence);
+ i915_request_put(rq);
+ }
- i915_gem_object_lock(obj, NULL);
- err = i915_gem_object_set_to_wc_domain(obj, true);
+ intel_engine_pm_put(engine);
+ if (!err)
+ err = i915_gem_object_set_to_wc_domain(obj, true);
i915_gem_object_unlock(obj);
if (err)
goto out_unpin;
@@ -858,7 +989,7 @@ create_region_for_mapping(struct intel_memory_region *mr, u64 size, u32 type,
struct drm_i915_gem_object *obj;
void *addr;
- obj = i915_gem_object_create_region(mr, size, 0);
+ obj = i915_gem_object_create_region(mr, size, 0, 0);
if (IS_ERR(obj)) {
if (PTR_ERR(obj) == -ENOSPC) /* Stolen memory */
return ERR_PTR(-ENODEV);
@@ -1046,6 +1177,7 @@ int intel_memory_region_mock_selftests(void)
SUBTEST(igt_mock_fill),
SUBTEST(igt_mock_contiguous),
SUBTEST(igt_mock_splintered_region),
+ SUBTEST(igt_mock_max_segment),
};
struct intel_memory_region *mem;
struct drm_i915_private *i915;
@@ -1074,6 +1206,7 @@ int intel_memory_region_live_selftests(struct drm_i915_private *i915)
{
static const struct i915_subtest tests[] = {
SUBTEST(igt_lmem_create),
+ SUBTEST(igt_lmem_create_with_ps),
SUBTEST(igt_lmem_create_cleared_cpu),
SUBTEST(igt_lmem_write_cpu),
SUBTEST(igt_lmem_write_gpu),
diff --git a/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c b/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
new file mode 100644
index 000000000000..4b328346b48a
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+//#include "gt/intel_engine_user.h"
+#include "gt/intel_gt.h"
+#include "i915_drv.h"
+#include "i915_selftest.h"
+
+#include "selftests/intel_scheduler_helpers.h"
+
+#define REDUCED_TIMESLICE 5
+#define REDUCED_PREEMPT 10
+#define WAIT_FOR_RESET_TIME 10000
+
+int intel_selftest_modify_policy(struct intel_engine_cs *engine,
+ struct intel_selftest_saved_policy *saved,
+ u32 modify_type)
+
+{
+ int err;
+
+ saved->reset = engine->i915->params.reset;
+ saved->flags = engine->flags;
+ saved->timeslice = engine->props.timeslice_duration_ms;
+ saved->preempt_timeout = engine->props.preempt_timeout_ms;
+
+ switch (modify_type) {
+ case SELFTEST_SCHEDULER_MODIFY_FAST_RESET:
+ /*
+ * Enable force pre-emption on time slice expiration
+ * together with engine reset on pre-emption timeout.
+ * This is required to make the GuC notice and reset
+ * the single hanging context.
+ * Also, reduce the preemption timeout to something
+ * small to speed the test up.
+ */
+ engine->i915->params.reset = 2;
+ engine->flags |= I915_ENGINE_WANT_FORCED_PREEMPTION;
+ engine->props.timeslice_duration_ms = REDUCED_TIMESLICE;
+ engine->props.preempt_timeout_ms = REDUCED_PREEMPT;
+ break;
+
+ case SELFTEST_SCHEDULER_MODIFY_NO_HANGCHECK:
+ engine->props.preempt_timeout_ms = 0;
+ break;
+
+ default:
+ pr_err("Invalid scheduler policy modification type: %d!\n", modify_type);
+ return -EINVAL;
+ }
+
+ if (!intel_engine_uses_guc(engine))
+ return 0;
+
+ err = intel_guc_global_policies_update(&engine->gt->uc.guc);
+ if (err)
+ intel_selftest_restore_policy(engine, saved);
+
+ return err;
+}
+
+int intel_selftest_restore_policy(struct intel_engine_cs *engine,
+ struct intel_selftest_saved_policy *saved)
+{
+ /* Restore the original policies */
+ engine->i915->params.reset = saved->reset;
+ engine->flags = saved->flags;
+ engine->props.timeslice_duration_ms = saved->timeslice;
+ engine->props.preempt_timeout_ms = saved->preempt_timeout;
+
+ if (!intel_engine_uses_guc(engine))
+ return 0;
+
+ return intel_guc_global_policies_update(&engine->gt->uc.guc);
+}
+
+int intel_selftest_wait_for_rq(struct i915_request *rq)
+{
+ long ret;
+
+ ret = i915_request_wait(rq, 0, WAIT_FOR_RESET_TIME);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.h b/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.h
new file mode 100644
index 000000000000..35c098601ac0
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef _INTEL_SELFTEST_SCHEDULER_HELPERS_H_
+#define _INTEL_SELFTEST_SCHEDULER_HELPERS_H_
+
+#include <linux/types.h>
+
+struct i915_request;
+struct intel_engine_cs;
+
+struct intel_selftest_saved_policy {
+ u32 flags;
+ u32 reset;
+ u64 timeslice;
+ u64 preempt_timeout;
+};
+
+enum selftest_scheduler_modify {
+ SELFTEST_SCHEDULER_MODIFY_NO_HANGCHECK = 0,
+ SELFTEST_SCHEDULER_MODIFY_FAST_RESET,
+};
+
+int intel_selftest_modify_policy(struct intel_engine_cs *engine,
+ struct intel_selftest_saved_policy *saved,
+ enum selftest_scheduler_modify modify_type);
+int intel_selftest_restore_policy(struct intel_engine_cs *engine,
+ struct intel_selftest_saved_policy *saved);
+int intel_selftest_wait_for_rq(struct i915_request *rq);
+
+#endif
diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
index 8ef9e6a4ad05..720b60853f8b 100644
--- a/drivers/gpu/drm/i915/selftests/intel_uncore.c
+++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
@@ -68,6 +68,7 @@ static int intel_shadow_table_check(void)
{ gen8_shadowed_regs, ARRAY_SIZE(gen8_shadowed_regs) },
{ gen11_shadowed_regs, ARRAY_SIZE(gen11_shadowed_regs) },
{ gen12_shadowed_regs, ARRAY_SIZE(gen12_shadowed_regs) },
+ { xehp_shadowed_regs, ARRAY_SIZE(xehp_shadowed_regs) },
};
const i915_reg_t *reg;
unsigned int i, j;
@@ -103,6 +104,7 @@ int intel_uncore_mock_selftests(void)
{ __gen9_fw_ranges, ARRAY_SIZE(__gen9_fw_ranges), true },
{ __gen11_fw_ranges, ARRAY_SIZE(__gen11_fw_ranges), true },
{ __gen12_fw_ranges, ARRAY_SIZE(__gen12_fw_ranges), true },
+ { __xehp_fw_ranges, ARRAY_SIZE(__xehp_fw_ranges), true },
};
int err, i;
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index d189c4bd4bef..4f8180146888 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -52,7 +52,8 @@ void mock_device_flush(struct drm_i915_private *i915)
do {
for_each_engine(engine, gt, id)
mock_engine_flush(engine);
- } while (intel_gt_retire_requests_timeout(gt, MAX_SCHEDULE_TIMEOUT));
+ } while (intel_gt_retire_requests_timeout(gt, MAX_SCHEDULE_TIMEOUT,
+ NULL));
}
static void mock_device_release(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c
index 5c7ae40bba63..cc047ec594f9 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c
@@ -73,7 +73,6 @@ struct i915_ppgtt *mock_ppgtt(struct drm_i915_private *i915, const char *name)
ppgtt->vm.gt = &i915->gt;
ppgtt->vm.i915 = i915;
ppgtt->vm.total = round_down(U64_MAX, PAGE_SIZE);
- ppgtt->vm.file = ERR_PTR(-ENODEV);
ppgtt->vm.dma = i915->drm.dev;
i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT);
diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c
index eafc5a04975c..efa86dffe3c6 100644
--- a/drivers/gpu/drm/i915/selftests/mock_region.c
+++ b/drivers/gpu/drm/i915/selftests/mock_region.c
@@ -3,6 +3,7 @@
* Copyright © 2019-2021 Intel Corporation
*/
+#include <drm/ttm/ttm_placement.h>
#include <linux/scatterlist.h>
#include <drm/ttm/ttm_placement.h>
@@ -16,7 +17,7 @@
static void mock_region_put_pages(struct drm_i915_gem_object *obj,
struct sg_table *pages)
{
- intel_region_ttm_node_free(obj->mm.region, obj->mm.st_mm_node);
+ intel_region_ttm_resource_free(obj->mm.region, obj->mm.res);
sg_free_table(pages);
kfree(pages);
}
@@ -25,26 +26,31 @@ static int mock_region_get_pages(struct drm_i915_gem_object *obj)
{
unsigned int flags;
struct sg_table *pages;
+ int err;
- flags = I915_ALLOC_MIN_PAGE_SIZE;
+ flags = 0;
if (obj->flags & I915_BO_ALLOC_CONTIGUOUS)
- flags |= I915_ALLOC_CONTIGUOUS;
+ flags |= TTM_PL_FLAG_CONTIGUOUS;
- obj->mm.st_mm_node = intel_region_ttm_node_alloc(obj->mm.region,
- obj->base.size,
- flags);
- if (IS_ERR(obj->mm.st_mm_node))
- return PTR_ERR(obj->mm.st_mm_node);
+ obj->mm.res = intel_region_ttm_resource_alloc(obj->mm.region,
+ obj->base.size,
+ flags);
+ if (IS_ERR(obj->mm.res))
+ return PTR_ERR(obj->mm.res);
- pages = intel_region_ttm_node_to_st(obj->mm.region, obj->mm.st_mm_node);
+ pages = intel_region_ttm_resource_to_st(obj->mm.region, obj->mm.res);
if (IS_ERR(pages)) {
- intel_region_ttm_node_free(obj->mm.region, obj->mm.st_mm_node);
- return PTR_ERR(pages);
+ err = PTR_ERR(pages);
+ goto err_free_resource;
}
__i915_gem_object_set_pages(obj, pages, i915_sg_dma_sizes(pages->sgl));
return 0;
+
+err_free_resource:
+ intel_region_ttm_resource_free(obj->mm.region, obj->mm.res);
+ return err;
}
static const struct drm_i915_gem_object_ops mock_region_obj_ops = {
@@ -57,6 +63,7 @@ static const struct drm_i915_gem_object_ops mock_region_obj_ops = {
static int mock_object_init(struct intel_memory_region *mem,
struct drm_i915_gem_object *obj,
resource_size_t size,
+ resource_size_t page_size,
unsigned int flags)
{
static struct lock_class_key lock_class;
diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c
index 37ae68a7fba5..9b84df34a6a1 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-kms.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c
@@ -93,11 +93,8 @@ static int dcss_kms_bridge_connector_init(struct dcss_kms_dev *kms)
ret = drm_bridge_attach(encoder, bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
- if (ret < 0) {
- dev_err(ddev->dev, "Unable to attach bridge %pOF\n",
- bridge->of_node);
+ if (ret < 0)
return ret;
- }
kms->connector = drm_bridge_connector_init(ddev, encoder);
if (IS_ERR(kms->connector)) {
@@ -133,8 +130,6 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
if (ret)
goto cleanup_mode_config;
- drm->irq_enabled = true;
-
ret = dcss_kms_bridge_connector_init(kms);
if (ret)
goto cleanup_mode_config;
@@ -178,7 +173,6 @@ void dcss_kms_detach(struct dcss_kms_dev *kms)
drm_kms_helper_poll_fini(drm);
drm_atomic_helper_shutdown(drm);
drm_crtc_vblank_off(&kms->crtc.base);
- drm->irq_enabled = false;
drm_mode_config_cleanup(drm);
dcss_crtc_deinit(&kms->crtc, drm);
drm->dev_private = NULL;
diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c
index 044d3bdf313c..ac45d54acd4e 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-plane.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c
@@ -361,7 +361,6 @@ static void dcss_plane_atomic_disable(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs dcss_plane_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = dcss_plane_atomic_check,
.atomic_update = dcss_plane_atomic_update,
.atomic_disable = dcss_plane_atomic_disable,
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 76819a8ac37f..9558e9e1b431 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -208,17 +208,6 @@ static int imx_drm_bind(struct device *dev)
return PTR_ERR(drm);
/*
- * enable drm irq mode.
- * - with irq_enabled = true, we can use the vblank feature.
- *
- * P.S. note that we wouldn't use drm irq handler but
- * just specific driver own one instead because
- * drm framework supports only one irq handler and
- * drivers can well take care of their interrupts
- */
- drm->irq_enabled = true;
-
- /*
* set max width and height as default value(4096x4096).
* this value would be used to check framebuffer size limitation
* at drm_mode_addfb().
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 53132ddf9587..e5078d03020d 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -465,10 +465,8 @@ static int imx_ldb_register(struct drm_device *drm,
if (imx_ldb_ch->bridge) {
ret = drm_bridge_attach(encoder, imx_ldb_ch->bridge, NULL, 0);
- if (ret) {
- DRM_ERROR("Failed to initialize bridge with drm\n");
+ if (ret)
return ret;
- }
} else {
/*
* We want to add the connector whenever there is no bridge
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index bd1f9f0366d3..846c1aae69c8 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -772,7 +772,6 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = ipu_plane_atomic_check,
.atomic_disable = ipu_plane_atomic_disable,
.atomic_update = ipu_plane_atomic_update,
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index e0412e694fd9..a8aba0141ce7 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -294,11 +294,8 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
if (imxpd->next_bridge) {
ret = drm_bridge_attach(encoder, imxpd->next_bridge, bridge, 0);
- if (ret < 0) {
- dev_err(imxpd->dev, "failed to attach bridge: %d\n",
- ret);
+ if (ret < 0)
return ret;
- }
} else {
drm_connector_helper_add(connector,
&imx_pd_connector_helper_funcs);
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 5244f4763477..a5df1c8d34cd 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -33,7 +33,6 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_managed.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
@@ -702,29 +701,6 @@ static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
}
}
-static void ingenic_drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state)
-{
- /*
- * Just your regular drm_atomic_helper_commit_tail(), but only calls
- * drm_atomic_helper_wait_for_vblanks() if priv->no_vblank.
- */
- struct drm_device *dev = old_state->dev;
- struct ingenic_drm *priv = drm_device_get_priv(dev);
-
- drm_atomic_helper_commit_modeset_disables(dev, old_state);
-
- drm_atomic_helper_commit_planes(dev, old_state, 0);
-
- drm_atomic_helper_commit_modeset_enables(dev, old_state);
-
- drm_atomic_helper_commit_hw_done(old_state);
-
- if (!priv->no_vblank)
- drm_atomic_helper_wait_for_vblanks(dev, old_state);
-
- drm_atomic_helper_cleanup_planes(dev, old_state);
-}
-
static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg)
{
struct ingenic_drm *priv = drm_device_get_priv(arg);
@@ -745,6 +721,9 @@ static int ingenic_drm_enable_vblank(struct drm_crtc *crtc)
{
struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
+ if (priv->no_vblank)
+ return -EINVAL;
+
regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
JZ_LCD_CTRL_EOF_IRQ, JZ_LCD_CTRL_EOF_IRQ);
@@ -799,8 +778,6 @@ static const struct drm_driver ingenic_drm_driver_data = {
.fops = &ingenic_drm_fops,
.gem_create_object = ingenic_drm_gem_create_object,
DRM_GEM_CMA_DRIVER_OPS,
-
- .irq_handler = ingenic_drm_irq_handler,
};
static const struct drm_plane_funcs ingenic_drm_primary_plane_funcs = {
@@ -830,7 +807,6 @@ static const struct drm_plane_helper_funcs ingenic_drm_plane_helper_funcs = {
.atomic_update = ingenic_drm_plane_atomic_update,
.atomic_check = ingenic_drm_plane_atomic_check,
.atomic_disable = ingenic_drm_plane_atomic_disable,
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
};
static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = {
@@ -855,7 +831,7 @@ static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
};
static struct drm_mode_config_helper_funcs ingenic_drm_mode_config_helpers = {
- .atomic_commit_tail = ingenic_drm_atomic_helper_commit_tail,
+ .atomic_commit_tail = drm_atomic_helper_commit_tail,
};
static void ingenic_drm_unbind_all(void *d)
@@ -988,9 +964,6 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
priv->dma_hwdescs->hwdesc_pal.cmd = JZ_LCD_CMD_ENABLE_PAL
| (sizeof(priv->dma_hwdescs->palette) / 4);
- if (soc_info->has_osd)
- priv->ipu_plane = drm_plane_from_index(drm, 0);
-
primary = priv->soc_info->has_osd ? &priv->f1 : &priv->f0;
drm_plane_helper_add(primary, &ingenic_drm_plane_helper_funcs);
@@ -1085,10 +1058,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs);
ret = drm_bridge_attach(encoder, bridge, NULL, 0);
- if (ret) {
- dev_err(dev, "Unable to attach bridge\n");
+ if (ret)
return ret;
- }
}
drm_for_each_encoder(encoder, drm) {
@@ -1099,7 +1070,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
encoder->possible_clones = clone_mask;
}
- ret = drm_irq_install(drm, irq);
+ ret = devm_request_irq(dev, irq, ingenic_drm_irq_handler, 0, drm->driver->name, drm);
if (ret) {
dev_err(dev, "Unable to install IRQ handler\n");
return ret;
diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c
index 61b6d9fdbba1..aeb8a757d213 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -625,7 +625,6 @@ static const struct drm_plane_helper_funcs ingenic_ipu_plane_helper_funcs = {
.atomic_update = ingenic_ipu_plane_atomic_update,
.atomic_check = ingenic_ipu_plane_atomic_check,
.atomic_disable = ingenic_ipu_plane_atomic_disable,
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
};
static int
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index f54392ec4fab..1c2f4799f421 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -17,7 +17,6 @@
#include <drm/drm_drv.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
@@ -413,14 +412,29 @@ static void kmb_irq_reset(struct drm_device *drm)
kmb_write_lcd(to_kmb(drm), LCD_INT_ENABLE, 0);
}
+static int kmb_irq_install(struct drm_device *drm, unsigned int irq)
+{
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ kmb_irq_reset(drm);
+
+ return request_irq(irq, kmb_isr, 0, drm->driver->name, drm);
+}
+
+static void kmb_irq_uninstall(struct drm_device *drm)
+{
+ struct kmb_drm_private *kmb = to_kmb(drm);
+
+ kmb_irq_reset(drm);
+ free_irq(kmb->irq_lcd, drm);
+}
+
DEFINE_DRM_GEM_CMA_FOPS(fops);
static const struct drm_driver kmb_driver = {
.driver_features = DRIVER_GEM |
DRIVER_MODESET | DRIVER_ATOMIC,
- .irq_handler = kmb_isr,
- .irq_preinstall = kmb_irq_reset,
- .irq_uninstall = kmb_irq_reset,
/* GEM Operations */
.fops = &fops,
DRM_GEM_CMA_DRIVER_OPS_VMAP,
@@ -442,7 +456,7 @@ static int kmb_remove(struct platform_device *pdev)
of_node_put(kmb->crtc.port);
kmb->crtc.port = NULL;
pm_runtime_get_sync(drm->dev);
- drm_irq_uninstall(drm);
+ kmb_irq_uninstall(drm);
pm_runtime_put_sync(drm->dev);
pm_runtime_disable(drm->dev);
@@ -532,7 +546,7 @@ static int kmb_probe(struct platform_device *pdev)
if (ret)
goto err_free;
- ret = drm_irq_install(&kmb->drm, kmb->irq_lcd);
+ ret = kmb_irq_install(&kmb->drm, kmb->irq_lcd);
if (ret < 0) {
drm_err(&kmb->drm, "failed to install IRQ handler\n");
goto err_irq;
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 231041b269f5..1793cd31b117 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -1441,7 +1441,6 @@ int kmb_dsi_encoder_init(struct drm_device *dev, struct kmb_dsi *kmb_dsi)
ret = drm_bridge_attach(encoder, adv_bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret) {
- DRM_ERROR("failed to attach bridge to MIPI\n");
drm_encoder_cleanup(encoder);
return ret;
}
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
index ecf3267334ff..dba8329937a3 100644
--- a/drivers/gpu/drm/lima/lima_sched.c
+++ b/drivers/gpu/drm/lima/lima_sched.c
@@ -508,7 +508,8 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
INIT_WORK(&pipe->recover_work, lima_sched_recover_work);
return drm_sched_init(&pipe->base, &lima_sched_ops, 1,
- lima_job_hang_limit, msecs_to_jiffies(timeout),
+ lima_job_hang_limit,
+ msecs_to_jiffies(timeout), NULL,
NULL, name);
}
diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c
index 4ddc55d58f38..ce12a36e2db4 100644
--- a/drivers/gpu/drm/mcde/mcde_display.c
+++ b/drivers/gpu/drm/mcde/mcde_display.c
@@ -1479,7 +1479,6 @@ static struct drm_simple_display_pipe_funcs mcde_display_funcs = {
.update = mcde_display_update,
.enable_vblank = mcde_display_enable_vblank,
.disable_vblank = mcde_display_disable_vblank,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
int mcde_display_init(struct drm_device *drm)
diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
index 34a00d7e9c38..180ebbccbeda 100644
--- a/drivers/gpu/drm/mcde/mcde_dsi.c
+++ b/drivers/gpu/drm/mcde/mcde_dsi.c
@@ -760,7 +760,7 @@ static void mcde_dsi_start(struct mcde_dsi *d)
DSI_MCTL_MAIN_DATA_CTL_BTA_EN |
DSI_MCTL_MAIN_DATA_CTL_READ_EN |
DSI_MCTL_MAIN_DATA_CTL_REG_TE_EN;
- if (!(d->mdsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+ if (!(d->mdsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
val |= DSI_MCTL_MAIN_DATA_CTL_HOST_EOT_GEN;
writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
@@ -1052,7 +1052,6 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge,
{
struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
struct drm_device *drm = bridge->dev;
- int ret;
if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) {
dev_err(d->dev, "we need atomic updates\n");
@@ -1060,13 +1059,7 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge,
}
/* Attach the DSI bridge to the output (panel etc) bridge */
- ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge, flags);
- if (ret) {
- dev_err(d->dev, "failed to attach the DSI bridge\n");
- return ret;
- }
-
- return 0;
+ return drm_bridge_attach(bridge->encoder, d->bridge_out, bridge, flags);
}
static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = {
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index dc54a7a69005..29098d7c8307 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
-mediatek-drm-y := mtk_disp_ccorr.o \
+mediatek-drm-y := mtk_disp_aal.o \
+ mtk_disp_ccorr.o \
mtk_disp_color.o \
mtk_disp_gamma.o \
mtk_disp_ovl.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_aal.c b/drivers/gpu/drm/mediatek/mtk_disp_aal.c
new file mode 100644
index 000000000000..f46d4ab73d6a
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_aal.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+
+#include "mtk_disp_drv.h"
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp_comp.h"
+
+#define DISP_AAL_EN 0x0000
+#define AAL_EN BIT(0)
+#define DISP_AAL_SIZE 0x0030
+#define DISP_AAL_OUTPUT_SIZE 0x04d8
+
+
+struct mtk_disp_aal_data {
+ bool has_gamma;
+};
+
+/**
+ * struct mtk_disp_aal - DISP_AAL driver structure
+ * @ddp_comp - structure containing type enum and hardware resources
+ * @crtc - associated crtc to report irq events to
+ */
+struct mtk_disp_aal {
+ struct clk *clk;
+ void __iomem *regs;
+ struct cmdq_client_reg cmdq_reg;
+ const struct mtk_disp_aal_data *data;
+};
+
+int mtk_aal_clk_enable(struct device *dev)
+{
+ struct mtk_disp_aal *aal = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(aal->clk);
+}
+
+void mtk_aal_clk_disable(struct device *dev)
+{
+ struct mtk_disp_aal *aal = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(aal->clk);
+}
+
+void mtk_aal_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_aal *aal = dev_get_drvdata(dev);
+
+ mtk_ddp_write(cmdq_pkt, w << 16 | h, &aal->cmdq_reg, aal->regs, DISP_AAL_SIZE);
+ mtk_ddp_write(cmdq_pkt, w << 16 | h, &aal->cmdq_reg, aal->regs, DISP_AAL_OUTPUT_SIZE);
+}
+
+void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state)
+{
+ struct mtk_disp_aal *aal = dev_get_drvdata(dev);
+
+ if (aal->data && aal->data->has_gamma)
+ mtk_gamma_set_common(aal->regs, state);
+}
+
+void mtk_aal_start(struct device *dev)
+{
+ struct mtk_disp_aal *aal = dev_get_drvdata(dev);
+
+ writel(AAL_EN, aal->regs + DISP_AAL_EN);
+}
+
+void mtk_aal_stop(struct device *dev)
+{
+ struct mtk_disp_aal *aal = dev_get_drvdata(dev);
+
+ writel_relaxed(0x0, aal->regs + DISP_AAL_EN);
+}
+
+static int mtk_disp_aal_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ return 0;
+}
+
+static void mtk_disp_aal_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+}
+
+static const struct component_ops mtk_disp_aal_component_ops = {
+ .bind = mtk_disp_aal_bind,
+ .unbind = mtk_disp_aal_unbind,
+};
+
+static int mtk_disp_aal_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_disp_aal *priv;
+ struct resource *res;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get aal clk\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->regs)) {
+ dev_err(dev, "failed to ioremap aal\n");
+ return PTR_ERR(priv->regs);
+ }
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+ ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+ if (ret)
+ dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
+#endif
+
+ priv->data = of_device_get_match_data(dev);
+ platform_set_drvdata(pdev, priv);
+
+ ret = component_add(dev, &mtk_disp_aal_component_ops);
+ if (ret)
+ dev_err(dev, "Failed to add component: %d\n", ret);
+
+ return ret;
+}
+
+static int mtk_disp_aal_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &mtk_disp_aal_component_ops);
+
+ return 0;
+}
+
+static const struct mtk_disp_aal_data mt8173_aal_driver_data = {
+ .has_gamma = true,
+};
+
+static const struct of_device_id mtk_disp_aal_driver_dt_match[] = {
+ { .compatible = "mediatek,mt8173-disp-aal",
+ .data = &mt8173_aal_driver_data},
+ { .compatible = "mediatek,mt8183-disp-aal"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_aal_driver_dt_match);
+
+struct platform_driver mtk_disp_aal_driver = {
+ .probe = mtk_disp_aal_probe,
+ .remove = mtk_disp_aal_remove,
+ .driver = {
+ .name = "mediatek-disp-aal",
+ .owner = THIS_MODULE,
+ .of_match_table = mtk_disp_aal_driver_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index cafd9df2d63b..86c3068894b1 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -9,6 +9,15 @@
#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_plane.h"
+int mtk_aal_clk_enable(struct device *dev);
+void mtk_aal_clk_disable(struct device *dev);
+void mtk_aal_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state);
+void mtk_aal_start(struct device *dev);
+void mtk_aal_stop(struct device *dev);
+
void mtk_ccorr_ctm_set(struct device *dev, struct drm_crtc_state *state);
int mtk_ccorr_clk_enable(struct device *dev);
void mtk_ccorr_clk_disable(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 705f28ceb4dd..75d7f45579e2 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -162,10 +162,10 @@ void mtk_rdma_config(struct device *dev, unsigned int width,
/*
* Enable FIFO underflow since DSI and DPI can't be blocked.
* Keep the FIFO pseudo size reset default of 8 KiB. Set the
- * output threshold to 6 microseconds with 7/6 overhead to
- * account for blanking, and with a pixel depth of 4 bytes:
+ * output threshold to 70% of max fifo size to make sure the
+ * threhold will not overflow
*/
- threshold = width * height * vrefresh * 4 * 7 / 1000000;
+ threshold = rdma_fifo_size * 7 / 10;
reg = RDMA_FIFO_UNDERFLOW_EN |
RDMA_FIFO_PSEUDO_SIZE(rdma_fifo_size) |
RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index e94738fe4db8..4554e2de1430 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -718,10 +718,8 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
- if (ret) {
- dev_err(dev, "Failed to attach bridge: %d\n", ret);
+ if (ret)
goto err_cleanup;
- }
dpi->connector = drm_bridge_connector_init(drm_dev, &dpi->encoder);
if (IS_ERR(dpi->connector)) {
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 735efe79f075..5f81489fc60c 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -4,6 +4,8 @@
*/
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/mailbox_controller.h>
#include <linux/pm_runtime.h>
#include <linux/soc/mediatek/mtk-cmdq.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
@@ -50,8 +52,11 @@ struct mtk_drm_crtc {
bool pending_async_planes;
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
- struct cmdq_client *cmdq_client;
+ struct mbox_client cmdq_cl;
+ struct mbox_chan *cmdq_chan;
+ struct cmdq_pkt cmdq_handle;
u32 cmdq_event;
+ u32 cmdq_vblank_cnt;
#endif
struct device *mmsys_dev;
@@ -222,9 +227,79 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
}
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
-static void ddp_cmdq_cb(struct cmdq_cb_data data)
+static int mtk_drm_cmdq_pkt_create(struct mbox_chan *chan, struct cmdq_pkt *pkt,
+ size_t size)
{
- cmdq_pkt_destroy(data.data);
+ struct device *dev;
+ dma_addr_t dma_addr;
+
+ pkt->va_base = kzalloc(size, GFP_KERNEL);
+ if (!pkt->va_base) {
+ kfree(pkt);
+ return -ENOMEM;
+ }
+ pkt->buf_size = size;
+
+ dev = chan->mbox->dev;
+ dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, dma_addr)) {
+ dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
+ kfree(pkt->va_base);
+ kfree(pkt);
+ return -ENOMEM;
+ }
+
+ pkt->pa_base = dma_addr;
+
+ return 0;
+}
+
+static void mtk_drm_cmdq_pkt_destroy(struct mbox_chan *chan, struct cmdq_pkt *pkt)
+{
+ dma_unmap_single(chan->mbox->dev, pkt->pa_base, pkt->buf_size,
+ DMA_TO_DEVICE);
+ kfree(pkt->va_base);
+ kfree(pkt);
+}
+
+static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
+{
+ struct mtk_drm_crtc *mtk_crtc = container_of(cl, struct mtk_drm_crtc, cmdq_cl);
+ struct cmdq_cb_data *data = mssg;
+ struct mtk_crtc_state *state;
+ unsigned int i;
+
+ state = to_mtk_crtc_state(mtk_crtc->base.state);
+
+ state->pending_config = false;
+
+ if (mtk_crtc->pending_planes) {
+ for (i = 0; i < mtk_crtc->layer_nr; i++) {
+ struct drm_plane *plane = &mtk_crtc->planes[i];
+ struct mtk_plane_state *plane_state;
+
+ plane_state = to_mtk_plane_state(plane->state);
+
+ plane_state->pending.config = false;
+ }
+ mtk_crtc->pending_planes = false;
+ }
+
+ if (mtk_crtc->pending_async_planes) {
+ for (i = 0; i < mtk_crtc->layer_nr; i++) {
+ struct drm_plane *plane = &mtk_crtc->planes[i];
+ struct mtk_plane_state *plane_state;
+
+ plane_state = to_mtk_plane_state(plane->state);
+
+ plane_state->pending.async_config = false;
+ }
+ mtk_crtc->pending_async_planes = false;
+ }
+
+ mtk_crtc->cmdq_vblank_cnt = 0;
+ mtk_drm_cmdq_pkt_destroy(mtk_crtc->cmdq_chan, data->pkt);
}
#endif
@@ -378,7 +453,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
state->pending_vrefresh, 0,
cmdq_handle);
- state->pending_config = false;
+ if (!cmdq_handle)
+ state->pending_config = false;
}
if (mtk_crtc->pending_planes) {
@@ -398,9 +474,12 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
mtk_ddp_comp_layer_config(comp, local_layer,
plane_state,
cmdq_handle);
- plane_state->pending.config = false;
+ if (!cmdq_handle)
+ plane_state->pending.config = false;
}
- mtk_crtc->pending_planes = false;
+
+ if (!cmdq_handle)
+ mtk_crtc->pending_planes = false;
}
if (mtk_crtc->pending_async_planes) {
@@ -420,9 +499,12 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
mtk_ddp_comp_layer_config(comp, local_layer,
plane_state,
cmdq_handle);
- plane_state->pending.async_config = false;
+ if (!cmdq_handle)
+ plane_state->pending.async_config = false;
}
- mtk_crtc->pending_async_planes = false;
+
+ if (!cmdq_handle)
+ mtk_crtc->pending_async_planes = false;
}
}
@@ -430,7 +512,7 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
bool needs_vblank)
{
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
- struct cmdq_pkt *cmdq_handle;
+ struct cmdq_pkt *cmdq_handle = &mtk_crtc->cmdq_handle;
#endif
struct drm_crtc *crtc = &mtk_crtc->base;
struct mtk_drm_private *priv = crtc->dev->dev_private;
@@ -468,14 +550,24 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
mtk_mutex_release(mtk_crtc->mutex);
}
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
- if (mtk_crtc->cmdq_client) {
- mbox_flush(mtk_crtc->cmdq_client->chan, 2000);
- cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE);
+ if (mtk_crtc->cmdq_chan) {
+ mbox_flush(mtk_crtc->cmdq_chan, 2000);
+ cmdq_handle->cmd_buf_size = 0;
cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false);
mtk_crtc_ddp_config(crtc, cmdq_handle);
cmdq_pkt_finalize(cmdq_handle);
- cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle);
+ dma_sync_single_for_device(mtk_crtc->cmdq_chan->mbox->dev,
+ cmdq_handle->pa_base,
+ cmdq_handle->cmd_buf_size,
+ DMA_TO_DEVICE);
+ /*
+ * CMDQ command should execute in next vblank,
+ * If it fail to execute in next 2 vblank, timeout happen.
+ */
+ mtk_crtc->cmdq_vblank_cnt = 2;
+ mbox_send_message(mtk_crtc->cmdq_chan, cmdq_handle);
+ mbox_client_txdone(mtk_crtc->cmdq_chan, 0);
}
#endif
mtk_crtc->config_updating = false;
@@ -489,12 +581,15 @@ static void mtk_crtc_ddp_irq(void *data)
struct mtk_drm_private *priv = crtc->dev->dev_private;
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
- if (!priv->data->shadow_register && !mtk_crtc->cmdq_client)
+ if (!priv->data->shadow_register && !mtk_crtc->cmdq_chan)
+ mtk_crtc_ddp_config(crtc, NULL);
+ else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0)
+ DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n",
+ drm_crtc_index(&mtk_crtc->base));
#else
if (!priv->data->shadow_register)
-#endif
mtk_crtc_ddp_config(crtc, NULL);
-
+#endif
mtk_drm_finish_page_flip(mtk_crtc);
}
@@ -752,14 +847,22 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
for (i = 0; i < path_len; i++) {
enum mtk_ddp_comp_id comp_id = path[i];
struct device_node *node;
+ struct mtk_ddp_comp *comp;
node = priv->comp_node[comp_id];
+ comp = &priv->ddp_comp[comp_id];
+
if (!node) {
dev_info(dev,
"Not creating crtc %d because component %d is disabled or missing\n",
pipe, comp_id);
return 0;
}
+
+ if (!comp->dev) {
+ dev_err(dev, "Component %pOF not initialized\n", node);
+ return -ENODEV;
+ }
}
mtk_crtc = devm_kzalloc(dev, sizeof(*mtk_crtc), GFP_KERNEL);
@@ -784,16 +887,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
enum mtk_ddp_comp_id comp_id = path[i];
struct mtk_ddp_comp *comp;
- struct device_node *node;
- node = priv->comp_node[comp_id];
comp = &priv->ddp_comp[comp_id];
- if (!comp) {
- dev_err(dev, "Component %pOF not initialized\n", node);
- ret = -ENODEV;
- return ret;
- }
-
mtk_crtc->ddp_comp[i] = comp;
if (comp->funcs) {
@@ -829,16 +924,20 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
mutex_init(&mtk_crtc->hw_lock);
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
- mtk_crtc->cmdq_client =
- cmdq_mbox_create(mtk_crtc->mmsys_dev,
- drm_crtc_index(&mtk_crtc->base));
- if (IS_ERR(mtk_crtc->cmdq_client)) {
+ mtk_crtc->cmdq_cl.dev = mtk_crtc->mmsys_dev;
+ mtk_crtc->cmdq_cl.tx_block = false;
+ mtk_crtc->cmdq_cl.knows_txdone = true;
+ mtk_crtc->cmdq_cl.rx_callback = ddp_cmdq_cb;
+ mtk_crtc->cmdq_chan =
+ mbox_request_channel(&mtk_crtc->cmdq_cl,
+ drm_crtc_index(&mtk_crtc->base));
+ if (IS_ERR(mtk_crtc->cmdq_chan)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base));
- mtk_crtc->cmdq_client = NULL;
+ mtk_crtc->cmdq_chan = NULL;
}
- if (mtk_crtc->cmdq_client) {
+ if (mtk_crtc->cmdq_chan) {
ret = of_property_read_u32_index(priv->mutex_node,
"mediatek,gce-events",
drm_crtc_index(&mtk_crtc->base),
@@ -846,8 +945,18 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
if (ret) {
dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n",
drm_crtc_index(&mtk_crtc->base));
- cmdq_mbox_destroy(mtk_crtc->cmdq_client);
- mtk_crtc->cmdq_client = NULL;
+ mbox_free_channel(mtk_crtc->cmdq_chan);
+ mtk_crtc->cmdq_chan = NULL;
+ } else {
+ ret = mtk_drm_cmdq_pkt_create(mtk_crtc->cmdq_chan,
+ &mtk_crtc->cmdq_handle,
+ PAGE_SIZE);
+ if (ret) {
+ dev_dbg(dev, "mtk_crtc %d failed to create cmdq packet\n",
+ drm_crtc_index(&mtk_crtc->base));
+ mbox_free_channel(mtk_crtc->cmdq_chan);
+ mtk_crtc->cmdq_chan = NULL;
+ }
}
}
#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 50d20562e612..99cbf44463e4 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -32,10 +32,6 @@
#define DISP_REG_UFO_START 0x0000
-#define DISP_AAL_EN 0x0000
-#define DISP_AAL_SIZE 0x0030
-#define DISP_AAL_OUTPUT_SIZE 0x04d8
-
#define DISP_DITHER_EN 0x0000
#define DITHER_EN BIT(0)
#define DISP_DITHER_CFG 0x0020
@@ -49,8 +45,6 @@
#define UFO_BYPASS BIT(2)
-#define AAL_EN BIT(0)
-
#define DISP_DITHERING BIT(2)
#define DITHER_LSB_ERR_SHIFT_R(x) (((x) & 0x7) << 28)
#define DITHER_OVFLW_BIT_R(x) (((x) & 0x7) << 24)
@@ -191,37 +185,6 @@ static void mtk_ufoe_start(struct device *dev)
writel(UFO_BYPASS, priv->regs + DISP_REG_UFO_START);
}
-static void mtk_aal_config(struct device *dev, unsigned int w,
- unsigned int h, unsigned int vrefresh,
- unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
-{
- struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
-
- mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_SIZE);
- mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_OUTPUT_SIZE);
-}
-
-static void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state)
-{
- struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
-
- mtk_gamma_set_common(priv->regs, state);
-}
-
-static void mtk_aal_start(struct device *dev)
-{
- struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
-
- writel(AAL_EN, priv->regs + DISP_AAL_EN);
-}
-
-static void mtk_aal_stop(struct device *dev)
-{
- struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
-
- writel_relaxed(0x0, priv->regs + DISP_AAL_EN);
-}
-
static void mtk_dither_config(struct device *dev, unsigned int w,
unsigned int h, unsigned int vrefresh,
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
@@ -249,8 +212,8 @@ static void mtk_dither_stop(struct device *dev)
}
static const struct mtk_ddp_comp_funcs ddp_aal = {
- .clk_enable = mtk_ddp_clk_enable,
- .clk_disable = mtk_ddp_clk_disable,
+ .clk_enable = mtk_aal_clk_enable,
+ .clk_disable = mtk_aal_clk_disable,
.gamma_set = mtk_aal_gamma_set,
.config = mtk_aal_config,
.start = mtk_aal_start,
@@ -507,7 +470,8 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
return ret;
}
- if (type == MTK_DISP_BLS ||
+ if (type == MTK_DISP_AAL ||
+ type == MTK_DISP_BLS ||
type == MTK_DISP_CCORR ||
type == MTK_DISP_COLOR ||
type == MTK_DISP_GAMMA ||
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index b46bdb8985da..aec39724ebeb 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -110,6 +110,17 @@ static const enum mtk_ddp_comp_id mt2712_mtk_ddp_third[] = {
DDP_COMPONENT_PWM2,
};
+static enum mtk_ddp_comp_id mt8167_mtk_ddp_main[] = {
+ DDP_COMPONENT_OVL0,
+ DDP_COMPONENT_COLOR0,
+ DDP_COMPONENT_CCORR,
+ DDP_COMPONENT_AAL0,
+ DDP_COMPONENT_GAMMA,
+ DDP_COMPONENT_DITHER,
+ DDP_COMPONENT_RDMA0,
+ DDP_COMPONENT_DSI0,
+};
+
static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0,
DDP_COMPONENT_COLOR0,
@@ -172,6 +183,11 @@ static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
.third_len = ARRAY_SIZE(mt2712_mtk_ddp_third),
};
+static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
+ .main_path = mt8167_mtk_ddp_main,
+ .main_len = ARRAY_SIZE(mt8167_mtk_ddp_main),
+};
+
static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
.main_path = mt8173_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
@@ -270,12 +286,6 @@ static int mtk_drm_kms_init(struct drm_device *drm)
goto err_component_unbind;
}
- /*
- * We don't use the drm_irq_install() helpers provided by the DRM
- * core, so we need to set this manually in order to allow the
- * DRM_IOCTL_WAIT_VBLANK to operate correctly.
- */
- drm->irq_enabled = true;
ret = drm_vblank_init(drm, MAX_CRTC);
if (ret < 0)
goto err_component_unbind;
@@ -300,16 +310,7 @@ static void mtk_drm_kms_deinit(struct drm_device *drm)
component_unbind_all(drm->dev, drm);
}
-static const struct file_operations mtk_drm_fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
- .mmap = mtk_drm_gem_mmap,
- .poll = drm_poll,
- .read = drm_read,
- .compat_ioctl = drm_compat_ioctl,
-};
+DEFINE_DRM_GEM_FOPS(mtk_drm_fops);
/*
* We need to override this because the device used to import the memory is
@@ -332,7 +333,7 @@ static const struct drm_driver mtk_drm_driver = {
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import = mtk_drm_gem_prime_import,
.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
- .gem_prime_mmap = mtk_drm_gem_mmap_buf,
+ .gem_prime_mmap = drm_gem_prime_mmap,
.fops = &mtk_drm_fops,
.name = DRIVER_NAME,
@@ -398,6 +399,8 @@ static const struct component_master_ops mtk_drm_ops = {
static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
{ .compatible = "mediatek,mt2701-disp-ovl",
.data = (void *)MTK_DISP_OVL },
+ { .compatible = "mediatek,mt8167-disp-ovl",
+ .data = (void *)MTK_DISP_OVL },
{ .compatible = "mediatek,mt8173-disp-ovl",
.data = (void *)MTK_DISP_OVL },
{ .compatible = "mediatek,mt8183-disp-ovl",
@@ -406,30 +409,46 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DISP_OVL_2L },
{ .compatible = "mediatek,mt2701-disp-rdma",
.data = (void *)MTK_DISP_RDMA },
+ { .compatible = "mediatek,mt8167-disp-rdma",
+ .data = (void *)MTK_DISP_RDMA },
{ .compatible = "mediatek,mt8173-disp-rdma",
.data = (void *)MTK_DISP_RDMA },
{ .compatible = "mediatek,mt8183-disp-rdma",
.data = (void *)MTK_DISP_RDMA },
{ .compatible = "mediatek,mt8173-disp-wdma",
.data = (void *)MTK_DISP_WDMA },
+ { .compatible = "mediatek,mt8167-disp-ccorr",
+ .data = (void *)MTK_DISP_CCORR },
{ .compatible = "mediatek,mt8183-disp-ccorr",
.data = (void *)MTK_DISP_CCORR },
{ .compatible = "mediatek,mt2701-disp-color",
.data = (void *)MTK_DISP_COLOR },
+ { .compatible = "mediatek,mt8167-disp-color",
+ .data = (void *)MTK_DISP_COLOR },
{ .compatible = "mediatek,mt8173-disp-color",
.data = (void *)MTK_DISP_COLOR },
+ { .compatible = "mediatek,mt8167-disp-aal",
+ .data = (void *)MTK_DISP_AAL},
{ .compatible = "mediatek,mt8173-disp-aal",
.data = (void *)MTK_DISP_AAL},
+ { .compatible = "mediatek,mt8183-disp-aal",
+ .data = (void *)MTK_DISP_AAL},
+ { .compatible = "mediatek,mt8167-disp-gamma",
+ .data = (void *)MTK_DISP_GAMMA, },
{ .compatible = "mediatek,mt8173-disp-gamma",
.data = (void *)MTK_DISP_GAMMA, },
{ .compatible = "mediatek,mt8183-disp-gamma",
.data = (void *)MTK_DISP_GAMMA, },
+ { .compatible = "mediatek,mt8167-disp-dither",
+ .data = (void *)MTK_DISP_DITHER },
{ .compatible = "mediatek,mt8183-disp-dither",
.data = (void *)MTK_DISP_DITHER },
{ .compatible = "mediatek,mt8173-disp-ufoe",
.data = (void *)MTK_DISP_UFOE },
{ .compatible = "mediatek,mt2701-dsi",
.data = (void *)MTK_DSI },
+ { .compatible = "mediatek,mt8167-dsi",
+ .data = (void *)MTK_DSI },
{ .compatible = "mediatek,mt8173-dsi",
.data = (void *)MTK_DSI },
{ .compatible = "mediatek,mt8183-dsi",
@@ -444,12 +463,16 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt2712-disp-mutex",
.data = (void *)MTK_DISP_MUTEX },
+ { .compatible = "mediatek,mt8167-disp-mutex",
+ .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8173-disp-mutex",
.data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8183-disp-mutex",
.data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt2701-disp-pwm",
.data = (void *)MTK_DISP_BLS },
+ { .compatible = "mediatek,mt8167-disp-pwm",
+ .data = (void *)MTK_DISP_PWM },
{ .compatible = "mediatek,mt8173-disp-pwm",
.data = (void *)MTK_DISP_PWM },
{ .compatible = "mediatek,mt8173-disp-od",
@@ -464,6 +487,8 @@ static const struct of_device_id mtk_drm_of_ids[] = {
.data = &mt7623_mmsys_driver_data},
{ .compatible = "mediatek,mt2712-mmsys",
.data = &mt2712_mmsys_driver_data},
+ { .compatible = "mediatek,mt8167-mmsys",
+ .data = &mt8167_mmsys_driver_data},
{ .compatible = "mediatek,mt8173-mmsys",
.data = &mt8173_mmsys_driver_data},
{ .compatible = "mediatek,mt8183-mmsys",
@@ -532,11 +557,12 @@ static int mtk_drm_probe(struct platform_device *pdev)
private->comp_node[comp_id] = of_node_get(node);
/*
- * Currently only the CCORR, COLOR, GAMMA, OVL, RDMA, DSI, and DPI
+ * Currently only the AAL, CCORR, COLOR, GAMMA, OVL, RDMA, DSI, and DPI
* blocks have separate component platform drivers and initialize their own
* DDP component structure. The others are initialized here.
*/
- if (comp_type == MTK_DISP_CCORR ||
+ if (comp_type == MTK_DISP_AAL ||
+ comp_type == MTK_DISP_CCORR ||
comp_type == MTK_DISP_COLOR ||
comp_type == MTK_DISP_GAMMA ||
comp_type == MTK_DISP_OVL ||
@@ -636,6 +662,7 @@ static struct platform_driver mtk_drm_platform_driver = {
};
static struct platform_driver * const mtk_drm_drivers[] = {
+ &mtk_disp_aal_driver,
&mtk_disp_ccorr_driver,
&mtk_disp_color_driver,
&mtk_disp_gamma_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 637f5669e895..3e7d1e6fbe01 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -46,6 +46,7 @@ struct mtk_drm_private {
struct drm_atomic_state *suspend_state;
};
+extern struct platform_driver mtk_disp_aal_driver;
extern struct platform_driver mtk_disp_ccorr_driver;
extern struct platform_driver mtk_disp_color_driver;
extern struct platform_driver mtk_disp_gamma_driver;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
index 280ea0d5e840..d0544962cfc1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
@@ -14,11 +14,14 @@
#include "mtk_drm_drv.h"
#include "mtk_drm_gem.h"
+static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
+
static const struct drm_gem_object_funcs mtk_drm_gem_object_funcs = {
.free = mtk_drm_gem_free_object,
.get_sg_table = mtk_gem_prime_get_sg_table,
.vmap = mtk_drm_gem_prime_vmap,
.vunmap = mtk_drm_gem_prime_vunmap,
+ .mmap = mtk_drm_gem_object_mmap,
.vm_ops = &drm_gem_cma_vm_ops,
};
@@ -146,10 +149,18 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj,
struct mtk_drm_private *priv = obj->dev->dev_private;
/*
+ * Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the
+ * whole buffer from the start.
+ */
+ vma->vm_pgoff = 0;
+
+ /*
* dma_alloc_attrs() allocated a struct page table for mtk_gem, so clear
* VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
*/
- vma->vm_flags &= ~VM_PFNMAP;
+ vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
+ vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+ vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie,
mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs);
@@ -159,37 +170,6 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj,
return ret;
}
-int mtk_drm_gem_mmap_buf(struct drm_gem_object *obj, struct vm_area_struct *vma)
-{
- int ret;
-
- ret = drm_gem_mmap_obj(obj, obj->size, vma);
- if (ret)
- return ret;
-
- return mtk_drm_gem_object_mmap(obj, vma);
-}
-
-int mtk_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct drm_gem_object *obj;
- int ret;
-
- ret = drm_gem_mmap(filp, vma);
- if (ret)
- return ret;
-
- obj = vma->vm_private_data;
-
- /*
- * Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the
- * whole buffer from the start.
- */
- vma->vm_pgoff = 0;
-
- return mtk_drm_gem_object_mmap(obj, vma);
-}
-
/*
* Allocate a sg_table for this GEM object.
* Note: Both the table's contents, and the sg_table itself must be freed by
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.h b/drivers/gpu/drm/mediatek/mtk_drm_gem.h
index 6da5ccb4b933..9a359a06cb73 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.h
@@ -39,9 +39,6 @@ struct mtk_drm_gem_obj *mtk_drm_gem_create(struct drm_device *dev, size_t size,
bool alloc_kmap);
int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
struct drm_mode_create_dumb *args);
-int mtk_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
-int mtk_drm_gem_mmap_buf(struct drm_gem_object *obj,
- struct vm_area_struct *vma);
struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj);
struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
index e6dcb34d3052..734a1fb052df 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
@@ -235,7 +235,6 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = mtk_plane_atomic_check,
.atomic_update = mtk_plane_atomic_update,
.atomic_disable = mtk_plane_atomic_disable,
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index ae403c67cbd9..93b40c245f00 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -404,7 +404,7 @@ static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
tmp_reg |= HSTX_CKLP_EN;
- if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+ if (!(dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
tmp_reg |= DIS_EOT;
writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
@@ -481,7 +481,7 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
timing->da_hs_zero + timing->da_hs_exit + 3;
delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12;
- delta += dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET ? 2 : 0;
+ delta += dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET ? 2 : 0;
horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp;
horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte;
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index c1651a83700d..5838c44cbf6f 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1293,11 +1293,8 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge,
if (hdmi->next_bridge) {
ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
bridge, flags);
- if (ret) {
- dev_err(hdmi->dev,
- "Failed to attach external bridge: %d\n", ret);
+ if (ret)
return ret;
- }
}
mtk_cec_set_hpd_event(hdmi->cec_dev, mtk_hdmi_hpd_event, hdmi->dev);
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index a7388bf7c838..bc0d60df04ae 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -21,7 +21,6 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
@@ -94,9 +93,6 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
static const struct drm_driver meson_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
- /* IRQ */
- .irq_handler = meson_irq,
-
/* CMA Ops */
DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(meson_dumb_create),
@@ -285,7 +281,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
* Remove early framebuffers (ie. simplefb). The framebuffer can be
* located anywhere in RAM
*/
- ret = drm_aperture_remove_framebuffers(false, "meson-drm-fb");
+ ret = drm_aperture_remove_framebuffers(false, &meson_driver);
if (ret)
goto free_drm;
@@ -335,7 +331,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
if (ret)
goto free_drm;
- ret = drm_irq_install(drm, priv->vsync_irq);
+ ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm);
if (ret)
goto free_drm;
@@ -354,7 +350,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
return 0;
uninstall_irq:
- drm_irq_uninstall(drm);
+ free_irq(priv->vsync_irq, drm);
free_drm:
drm_dev_put(drm);
@@ -382,7 +378,7 @@ static void meson_drv_unbind(struct device *dev)
drm_kms_helper_poll_fini(drm);
drm_atomic_helper_shutdown(drm);
component_unbind_all(dev, drm);
- drm_irq_uninstall(drm);
+ free_irq(priv->vsync_irq, drm);
drm_dev_put(drm);
if (priv->afbcd.ops) {
diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
index ed063152aecd..dfef8afcc245 100644
--- a/drivers/gpu/drm/meson/meson_overlay.c
+++ b/drivers/gpu/drm/meson/meson_overlay.c
@@ -747,7 +747,6 @@ static const struct drm_plane_helper_funcs meson_overlay_helper_funcs = {
.atomic_check = meson_overlay_atomic_check,
.atomic_disable = meson_overlay_atomic_disable,
.atomic_update = meson_overlay_atomic_update,
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
};
static bool meson_overlay_format_mod_supported(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index a18510dae4c8..8640a8a8a469 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -422,7 +422,6 @@ static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
.atomic_check = meson_plane_atomic_check,
.atomic_disable = meson_plane_atomic_disable,
.atomic_update = meson_plane_atomic_update,
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
};
static bool meson_plane_format_mod_supported(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c
index 403efc1f1a7c..331c2f0da57a 100644
--- a/drivers/gpu/drm/mga/mga_dma.c
+++ b/drivers/gpu/drm/mga/mga_dma.c
@@ -949,7 +949,7 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
* is freed, it's too late.
*/
if (dev->irq_enabled)
- drm_irq_uninstall(dev);
+ drm_legacy_irq_uninstall(dev);
if (dev->dev_private) {
drm_mga_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h
index 84395d81ab9b..f61401c70b90 100644
--- a/drivers/gpu/drm/mga/mga_drv.h
+++ b/drivers/gpu/drm/mga/mga_drv.h
@@ -38,7 +38,6 @@
#include <drm/drm_device.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
-#include <drm/drm_irq.h>
#include <drm/drm_legacy.h>
#include <drm/drm_print.h>
#include <drm/drm_sarea.h>
diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
index 42fedef53882..d4f766522483 100644
--- a/drivers/gpu/drm/mgag200/Makefile
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-mgag200-y := mgag200_drv.o mgag200_i2c.o mgag200_mm.o mgag200_mode.o
+mgag200-y := mgag200_drv.o mgag200_i2c.o mgag200_mm.o mgag200_mode.o mgag200_pll.o
obj-$(CONFIG_DRM_MGAG200) += mgag200.o
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index a701d9563257..6b9243713b3c 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -262,17 +262,26 @@ static void mgag200_g200se_init_unique_id(struct mga_device *mdev)
mdev->model.g200se.unique_rev_id);
}
-static int mgag200_device_init(struct mga_device *mdev, unsigned long flags)
+static struct mga_device *
+mgag200_device_create(struct pci_dev *pdev, enum mga_type type, unsigned long flags)
{
- struct drm_device *dev = &mdev->base;
+ struct mga_device *mdev;
+ struct drm_device *dev;
int ret;
- mdev->flags = mgag200_flags_from_driver_data(flags);
- mdev->type = mgag200_type_from_driver_data(flags);
+ mdev = devm_drm_dev_alloc(&pdev->dev, &mgag200_driver, struct mga_device, base);
+ if (IS_ERR(mdev))
+ return mdev;
+ dev = &mdev->base;
+
+ pci_set_drvdata(pdev, dev);
+
+ mdev->flags = flags;
+ mdev->type = type;
ret = mgag200_regs_init(mdev);
if (ret)
- return ret;
+ return ERR_PTR(ret);
if (mdev->type == G200_PCI || mdev->type == G200_AGP)
mgag200_g200_init_refclk(mdev);
@@ -281,33 +290,9 @@ static int mgag200_device_init(struct mga_device *mdev, unsigned long flags)
ret = mgag200_mm_init(mdev);
if (ret)
- return ret;
+ return ERR_PTR(ret);
ret = mgag200_modeset_init(mdev);
- if (ret) {
- drm_err(dev, "Fatal error during modeset init: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static struct mga_device *
-mgag200_device_create(struct pci_dev *pdev, unsigned long flags)
-{
- struct drm_device *dev;
- struct mga_device *mdev;
- int ret;
-
- mdev = devm_drm_dev_alloc(&pdev->dev, &mgag200_driver,
- struct mga_device, base);
- if (IS_ERR(mdev))
- return mdev;
- dev = &mdev->base;
-
- pci_set_drvdata(pdev, dev);
-
- ret = mgag200_device_init(mdev, flags);
if (ret)
return ERR_PTR(ret);
@@ -335,14 +320,27 @@ static const struct pci_device_id mgag200_pciidlist[] = {
MODULE_DEVICE_TABLE(pci, mgag200_pciidlist);
+static enum mga_type mgag200_type_from_driver_data(kernel_ulong_t driver_data)
+{
+ return (enum mga_type)(driver_data & MGAG200_TYPE_MASK);
+}
+
+static unsigned long mgag200_flags_from_driver_data(kernel_ulong_t driver_data)
+{
+ return driver_data & MGAG200_FLAG_MASK;
+}
+
static int
mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
+ kernel_ulong_t driver_data = ent->driver_data;
+ enum mga_type type = mgag200_type_from_driver_data(driver_data);
+ unsigned long flags = mgag200_flags_from_driver_data(driver_data);
struct mga_device *mdev;
struct drm_device *dev;
int ret;
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "mgag200drmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &mgag200_driver);
if (ret)
return ret;
@@ -350,12 +348,12 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
- mdev = mgag200_device_create(pdev, ent->driver_data);
+ mdev = mgag200_device_create(pdev, type, flags);
if (IS_ERR(mdev))
return PTR_ERR(mdev);
dev = &mdev->base;
- ret = drm_dev_register(dev, ent->driver_data);
+ ret = drm_dev_register(dev, 0);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 749a075fe9e4..196f74a0834e 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -43,6 +43,22 @@
#define ATTR_INDEX 0x1fc0
#define ATTR_DATA 0x1fc1
+#define WREG_MISC(v) \
+ WREG8(MGA_MISC_OUT, v)
+
+#define RREG_MISC(v) \
+ ((v) = RREG8(MGA_MISC_IN))
+
+#define WREG_MISC_MASKED(v, mask) \
+ do { \
+ u8 misc_; \
+ u8 mask_ = (mask); \
+ RREG_MISC(misc_); \
+ misc_ &= ~mask_; \
+ misc_ |= ((v) & mask_); \
+ WREG_MISC(misc_); \
+ } while (0)
+
#define WREG_ATTR(reg, v) \
do { \
RREG8(0x1fda); \
@@ -110,6 +126,48 @@
#define MGAG200_MAX_FB_HEIGHT 4096
#define MGAG200_MAX_FB_WIDTH 4096
+struct mga_device;
+struct mgag200_pll;
+
+/*
+ * Stores parameters for programming the PLLs
+ *
+ * Fref: reference frequency (A: 25.175 Mhz, B: 28.361, C: XX Mhz)
+ * Fo: output frequency
+ * Fvco = Fref * (N / M)
+ * Fo = Fvco / P
+ *
+ * S = [0..3]
+ */
+struct mgag200_pll_values {
+ unsigned int m;
+ unsigned int n;
+ unsigned int p;
+ unsigned int s;
+};
+
+struct mgag200_pll_funcs {
+ int (*compute)(struct mgag200_pll *pll, long clock, struct mgag200_pll_values *pllc);
+ void (*update)(struct mgag200_pll *pll, const struct mgag200_pll_values *pllc);
+};
+
+struct mgag200_pll {
+ struct mga_device *mdev;
+
+ const struct mgag200_pll_funcs *funcs;
+};
+
+struct mgag200_crtc_state {
+ struct drm_crtc_state base;
+
+ struct mgag200_pll_values pixpllc;
+};
+
+static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_state *base)
+{
+ return container_of(base, struct mgag200_crtc_state, base);
+}
+
#define to_mga_connector(x) container_of(x, struct mga_connector, base)
struct mga_i2c_chan {
@@ -166,8 +224,6 @@ struct mga_device {
enum mga_type type;
- int bpp_shifts[4];
-
int fb_mtrr;
union {
@@ -182,8 +238,8 @@ struct mga_device {
} g200se;
} model;
-
struct mga_connector connector;
+ struct mgag200_pll pixpll;
struct drm_simple_display_pipe display_pipe;
};
@@ -192,18 +248,6 @@ static inline struct mga_device *to_mga_device(struct drm_device *dev)
return container_of(dev, struct mga_device, base);
}
-static inline enum mga_type
-mgag200_type_from_driver_data(kernel_ulong_t driver_data)
-{
- return (enum mga_type)(driver_data & MGAG200_TYPE_MASK);
-}
-
-static inline unsigned long
-mgag200_flags_from_driver_data(kernel_ulong_t driver_data)
-{
- return driver_data & MGAG200_FLAG_MASK;
-}
-
/* mgag200_mode.c */
int mgag200_modeset_init(struct mga_device *mdev);
@@ -214,4 +258,7 @@ void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);
/* mgag200_mm.c */
int mgag200_mm_init(struct mga_device *mdev);
+ /* mgag200_pll.c */
+int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev);
+
#endif /* __MGAG200_DRV_H__ */
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 9d576240faed..fd98e8bbc550 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -110,712 +110,6 @@ static inline void mga_wait_busy(struct mga_device *mdev)
} while ((status & 0x01) && time_before(jiffies, timeout));
}
-/*
- * PLL setup
- */
-
-static int mgag200_g200_set_plls(struct mga_device *mdev, long clock)
-{
- struct drm_device *dev = &mdev->base;
- const int post_div_max = 7;
- const int in_div_min = 1;
- const int in_div_max = 6;
- const int feed_div_min = 7;
- const int feed_div_max = 127;
- u8 testm, testn;
- u8 n = 0, m = 0, p, s;
- long f_vco;
- long computed;
- long delta, tmp_delta;
- long ref_clk = mdev->model.g200.ref_clk;
- long p_clk_min = mdev->model.g200.pclk_min;
- long p_clk_max = mdev->model.g200.pclk_max;
-
- if (clock > p_clk_max) {
- drm_err(dev, "Pixel Clock %ld too high\n", clock);
- return 1;
- }
-
- if (clock < p_clk_min >> 3)
- clock = p_clk_min >> 3;
-
- f_vco = clock;
- for (p = 0;
- p <= post_div_max && f_vco < p_clk_min;
- p = (p << 1) + 1, f_vco <<= 1)
- ;
-
- delta = clock;
-
- for (testm = in_div_min; testm <= in_div_max; testm++) {
- for (testn = feed_div_min; testn <= feed_div_max; testn++) {
- computed = ref_clk * (testn + 1) / (testm + 1);
- if (computed < f_vco)
- tmp_delta = f_vco - computed;
- else
- tmp_delta = computed - f_vco;
- if (tmp_delta < delta) {
- delta = tmp_delta;
- m = testm;
- n = testn;
- }
- }
- }
- f_vco = ref_clk * (n + 1) / (m + 1);
- if (f_vco < 100000)
- s = 0;
- else if (f_vco < 140000)
- s = 1;
- else if (f_vco < 180000)
- s = 2;
- else
- s = 3;
-
- drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
- clock, f_vco, m, n, p, s);
-
- WREG_DAC(MGA1064_PIX_PLLC_M, m);
- WREG_DAC(MGA1064_PIX_PLLC_N, n);
- WREG_DAC(MGA1064_PIX_PLLC_P, (p | (s << 3)));
-
- return 0;
-}
-
-#define P_ARRAY_SIZE 9
-
-static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
-{
- u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
- unsigned int vcomax, vcomin, pllreffreq;
- unsigned int delta, tmpdelta, permitteddelta;
- unsigned int testp, testm, testn;
- unsigned int p, m, n;
- unsigned int computed;
- unsigned int pvalues_e4[P_ARRAY_SIZE] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
- unsigned int fvv;
- unsigned int i;
-
- if (unique_rev_id <= 0x03) {
-
- m = n = p = 0;
- vcomax = 320000;
- vcomin = 160000;
- pllreffreq = 25000;
-
- delta = 0xffffffff;
- permitteddelta = clock * 5 / 1000;
-
- for (testp = 8; testp > 0; testp /= 2) {
- if (clock * testp > vcomax)
- continue;
- if (clock * testp < vcomin)
- continue;
-
- for (testn = 17; testn < 256; testn++) {
- for (testm = 1; testm < 32; testm++) {
- computed = (pllreffreq * testn) /
- (testm * testp);
- if (computed > clock)
- tmpdelta = computed - clock;
- else
- tmpdelta = clock - computed;
- if (tmpdelta < delta) {
- delta = tmpdelta;
- m = testm - 1;
- n = testn - 1;
- p = testp - 1;
- }
- }
- }
- }
- } else {
-
-
- m = n = p = 0;
- vcomax = 1600000;
- vcomin = 800000;
- pllreffreq = 25000;
-
- if (clock < 25000)
- clock = 25000;
-
- clock = clock * 2;
-
- delta = 0xFFFFFFFF;
- /* Permited delta is 0.5% as VESA Specification */
- permitteddelta = clock * 5 / 1000;
-
- for (i = 0 ; i < P_ARRAY_SIZE ; i++) {
- testp = pvalues_e4[i];
-
- if ((clock * testp) > vcomax)
- continue;
- if ((clock * testp) < vcomin)
- continue;
-
- for (testn = 50; testn <= 256; testn++) {
- for (testm = 1; testm <= 32; testm++) {
- computed = (pllreffreq * testn) /
- (testm * testp);
- if (computed > clock)
- tmpdelta = computed - clock;
- else
- tmpdelta = clock - computed;
-
- if (tmpdelta < delta) {
- delta = tmpdelta;
- m = testm - 1;
- n = testn - 1;
- p = testp - 1;
- }
- }
- }
- }
-
- fvv = pllreffreq * (n + 1) / (m + 1);
- fvv = (fvv - 800000) / 50000;
-
- if (fvv > 15)
- fvv = 15;
-
- p |= (fvv << 4);
- m |= 0x80;
-
- clock = clock / 2;
- }
-
- if (delta > permitteddelta) {
- pr_warn("PLL delta too large\n");
- return 1;
- }
-
- WREG_DAC(MGA1064_PIX_PLLC_M, m);
- WREG_DAC(MGA1064_PIX_PLLC_N, n);
- WREG_DAC(MGA1064_PIX_PLLC_P, p);
-
- if (unique_rev_id >= 0x04) {
- WREG_DAC(0x1a, 0x09);
- msleep(20);
- WREG_DAC(0x1a, 0x01);
-
- }
-
- return 0;
-}
-
-static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
-{
- unsigned int vcomax, vcomin, pllreffreq;
- unsigned int delta, tmpdelta;
- unsigned int testp, testm, testn, testp2;
- unsigned int p, m, n;
- unsigned int computed;
- int i, j, tmpcount, vcount;
- bool pll_locked = false;
- u8 tmp;
-
- m = n = p = 0;
-
- delta = 0xffffffff;
-
- if (mdev->type == G200_EW3) {
-
- vcomax = 800000;
- vcomin = 400000;
- pllreffreq = 25000;
-
- for (testp = 1; testp < 8; testp++) {
- for (testp2 = 1; testp2 < 8; testp2++) {
- if (testp < testp2)
- continue;
- if ((clock * testp * testp2) > vcomax)
- continue;
- if ((clock * testp * testp2) < vcomin)
- continue;
- for (testm = 1; testm < 26; testm++) {
- for (testn = 32; testn < 2048 ; testn++) {
- computed = (pllreffreq * testn) /
- (testm * testp * testp2);
- if (computed > clock)
- tmpdelta = computed - clock;
- else
- tmpdelta = clock - computed;
- if (tmpdelta < delta) {
- delta = tmpdelta;
- m = ((testn & 0x100) >> 1) |
- (testm);
- n = (testn & 0xFF);
- p = ((testn & 0x600) >> 3) |
- (testp2 << 3) |
- (testp);
- }
- }
- }
- }
- }
- } else {
-
- vcomax = 550000;
- vcomin = 150000;
- pllreffreq = 48000;
-
- for (testp = 1; testp < 9; testp++) {
- if (clock * testp > vcomax)
- continue;
- if (clock * testp < vcomin)
- continue;
-
- for (testm = 1; testm < 17; testm++) {
- for (testn = 1; testn < 151; testn++) {
- computed = (pllreffreq * testn) /
- (testm * testp);
- if (computed > clock)
- tmpdelta = computed - clock;
- else
- tmpdelta = clock - computed;
- if (tmpdelta < delta) {
- delta = tmpdelta;
- n = testn - 1;
- m = (testm - 1) |
- ((n >> 1) & 0x80);
- p = testp - 1;
- }
- }
- }
- }
- }
-
- for (i = 0; i <= 32 && pll_locked == false; i++) {
- if (i > 0) {
- WREG8(MGAREG_CRTC_INDEX, 0x1e);
- tmp = RREG8(MGAREG_CRTC_DATA);
- if (tmp < 0xff)
- WREG8(MGAREG_CRTC_DATA, tmp+1);
- }
-
- /* set pixclkdis to 1 */
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
- WREG8(DAC_DATA, tmp);
-
- WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_REMHEADCTL_CLKDIS;
- WREG8(DAC_DATA, tmp);
-
- /* select PLL Set C */
- tmp = RREG8(MGAREG_MEM_MISC_READ);
- tmp |= 0x3 << 2;
- WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
- WREG8(DAC_DATA, tmp);
-
- udelay(500);
-
- /* reset the PLL */
- WREG8(DAC_INDEX, MGA1064_VREF_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~0x04;
- WREG8(DAC_DATA, tmp);
-
- udelay(50);
-
- /* program pixel pll register */
- WREG_DAC(MGA1064_WB_PIX_PLLC_N, n);
- WREG_DAC(MGA1064_WB_PIX_PLLC_M, m);
- WREG_DAC(MGA1064_WB_PIX_PLLC_P, p);
-
- udelay(50);
-
- /* turn pll on */
- WREG8(DAC_INDEX, MGA1064_VREF_CTL);
- tmp = RREG8(DAC_DATA);
- tmp |= 0x04;
- WREG_DAC(MGA1064_VREF_CTL, tmp);
-
- udelay(500);
-
- /* select the pixel pll */
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
- tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
- WREG8(DAC_DATA, tmp);
-
- WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
- tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
- WREG8(DAC_DATA, tmp);
-
- /* reset dotclock rate bit */
- WREG8(MGAREG_SEQ_INDEX, 1);
- tmp = RREG8(MGAREG_SEQ_DATA);
- tmp &= ~0x8;
- WREG8(MGAREG_SEQ_DATA, tmp);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
- WREG8(DAC_DATA, tmp);
-
- vcount = RREG8(MGAREG_VCOUNT);
-
- for (j = 0; j < 30 && pll_locked == false; j++) {
- tmpcount = RREG8(MGAREG_VCOUNT);
- if (tmpcount < vcount)
- vcount = 0;
- if ((tmpcount - vcount) > 2)
- pll_locked = true;
- else
- udelay(5);
- }
- }
- WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
- WREG_DAC(MGA1064_REMHEADCTL, tmp);
- return 0;
-}
-
-static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
-{
- unsigned int vcomax, vcomin, pllreffreq;
- unsigned int delta, tmpdelta;
- unsigned int testp, testm, testn;
- unsigned int p, m, n;
- unsigned int computed;
- u8 tmp;
-
- m = n = p = 0;
- vcomax = 550000;
- vcomin = 150000;
- pllreffreq = 50000;
-
- delta = 0xffffffff;
-
- for (testp = 16; testp > 0; testp--) {
- if (clock * testp > vcomax)
- continue;
- if (clock * testp < vcomin)
- continue;
-
- for (testn = 1; testn < 257; testn++) {
- for (testm = 1; testm < 17; testm++) {
- computed = (pllreffreq * testn) /
- (testm * testp);
- if (computed > clock)
- tmpdelta = computed - clock;
- else
- tmpdelta = clock - computed;
- if (tmpdelta < delta) {
- delta = tmpdelta;
- n = testn - 1;
- m = testm - 1;
- p = testp - 1;
- }
- }
- }
- }
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
- WREG8(DAC_DATA, tmp);
-
- tmp = RREG8(MGAREG_MEM_MISC_READ);
- tmp |= 0x3 << 2;
- WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
- WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
- tmp = RREG8(DAC_DATA);
- WREG8(DAC_DATA, tmp & ~0x40);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
- WREG8(DAC_DATA, tmp);
-
- WREG_DAC(MGA1064_EV_PIX_PLLC_M, m);
- WREG_DAC(MGA1064_EV_PIX_PLLC_N, n);
- WREG_DAC(MGA1064_EV_PIX_PLLC_P, p);
-
- udelay(50);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
- WREG8(DAC_DATA, tmp);
-
- udelay(500);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
- tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
- WREG8(DAC_DATA, tmp);
-
- WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
- tmp = RREG8(DAC_DATA);
- WREG8(DAC_DATA, tmp | 0x40);
-
- tmp = RREG8(MGAREG_MEM_MISC_READ);
- tmp |= (0x3 << 2);
- WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
- WREG8(DAC_DATA, tmp);
-
- return 0;
-}
-
-static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
-{
- unsigned int vcomax, vcomin, pllreffreq;
- unsigned int delta, tmpdelta;
- unsigned int testp, testm, testn;
- unsigned int p, m, n;
- unsigned int computed;
- int i, j, tmpcount, vcount;
- u8 tmp;
- bool pll_locked = false;
-
- m = n = p = 0;
-
- if (mdev->type == G200_EH3) {
- vcomax = 3000000;
- vcomin = 1500000;
- pllreffreq = 25000;
-
- delta = 0xffffffff;
-
- testp = 0;
-
- for (testm = 150; testm >= 6; testm--) {
- if (clock * testm > vcomax)
- continue;
- if (clock * testm < vcomin)
- continue;
- for (testn = 120; testn >= 60; testn--) {
- computed = (pllreffreq * testn) / testm;
- if (computed > clock)
- tmpdelta = computed - clock;
- else
- tmpdelta = clock - computed;
- if (tmpdelta < delta) {
- delta = tmpdelta;
- n = testn;
- m = testm;
- p = testp;
- }
- if (delta == 0)
- break;
- }
- if (delta == 0)
- break;
- }
- } else {
-
- vcomax = 800000;
- vcomin = 400000;
- pllreffreq = 33333;
-
- delta = 0xffffffff;
-
- for (testp = 16; testp > 0; testp >>= 1) {
- if (clock * testp > vcomax)
- continue;
- if (clock * testp < vcomin)
- continue;
-
- for (testm = 1; testm < 33; testm++) {
- for (testn = 17; testn < 257; testn++) {
- computed = (pllreffreq * testn) /
- (testm * testp);
- if (computed > clock)
- tmpdelta = computed - clock;
- else
- tmpdelta = clock - computed;
- if (tmpdelta < delta) {
- delta = tmpdelta;
- n = testn - 1;
- m = (testm - 1);
- p = testp - 1;
- }
- if ((clock * testp) >= 600000)
- p |= 0x80;
- }
- }
- }
- }
- for (i = 0; i <= 32 && pll_locked == false; i++) {
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
- WREG8(DAC_DATA, tmp);
-
- tmp = RREG8(MGAREG_MEM_MISC_READ);
- tmp |= 0x3 << 2;
- WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
- WREG8(DAC_DATA, tmp);
-
- udelay(500);
-
- WREG_DAC(MGA1064_EH_PIX_PLLC_M, m);
- WREG_DAC(MGA1064_EH_PIX_PLLC_N, n);
- WREG_DAC(MGA1064_EH_PIX_PLLC_P, p);
-
- udelay(500);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
- tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
- WREG8(DAC_DATA, tmp);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
- tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
- WREG8(DAC_DATA, tmp);
-
- vcount = RREG8(MGAREG_VCOUNT);
-
- for (j = 0; j < 30 && pll_locked == false; j++) {
- tmpcount = RREG8(MGAREG_VCOUNT);
- if (tmpcount < vcount)
- vcount = 0;
- if ((tmpcount - vcount) > 2)
- pll_locked = true;
- else
- udelay(5);
- }
- }
-
- return 0;
-}
-
-static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
-{
- static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
- unsigned int vcomax, vcomin, pllreffreq;
- unsigned int delta, tmpdelta;
- int testr, testn, testm, testo;
- unsigned int p, m, n;
- unsigned int computed, vco;
- int tmp;
-
- m = n = p = 0;
- vcomax = 1488000;
- vcomin = 1056000;
- pllreffreq = 48000;
-
- delta = 0xffffffff;
-
- for (testr = 0; testr < 4; testr++) {
- if (delta == 0)
- break;
- for (testn = 5; testn < 129; testn++) {
- if (delta == 0)
- break;
- for (testm = 3; testm >= 0; testm--) {
- if (delta == 0)
- break;
- for (testo = 5; testo < 33; testo++) {
- vco = pllreffreq * (testn + 1) /
- (testr + 1);
- if (vco < vcomin)
- continue;
- if (vco > vcomax)
- continue;
- computed = vco / (m_div_val[testm] * (testo + 1));
- if (computed > clock)
- tmpdelta = computed - clock;
- else
- tmpdelta = clock - computed;
- if (tmpdelta < delta) {
- delta = tmpdelta;
- m = testm | (testo << 3);
- n = testn;
- p = testr | (testr << 3);
- }
- }
- }
- }
- }
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
- WREG8(DAC_DATA, tmp);
-
- WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
- tmp = RREG8(DAC_DATA);
- tmp |= MGA1064_REMHEADCTL_CLKDIS;
- WREG8(DAC_DATA, tmp);
-
- tmp = RREG8(MGAREG_MEM_MISC_READ);
- tmp |= (0x3<<2) | 0xc0;
- WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
- WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
- tmp = RREG8(DAC_DATA);
- tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
- tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
- WREG8(DAC_DATA, tmp);
-
- udelay(500);
-
- WREG_DAC(MGA1064_ER_PIX_PLLC_N, n);
- WREG_DAC(MGA1064_ER_PIX_PLLC_M, m);
- WREG_DAC(MGA1064_ER_PIX_PLLC_P, p);
-
- udelay(50);
-
- return 0;
-}
-
-static int mgag200_crtc_set_plls(struct mga_device *mdev, long clock)
-{
- u8 misc;
-
- switch(mdev->type) {
- case G200_PCI:
- case G200_AGP:
- return mgag200_g200_set_plls(mdev, clock);
- case G200_SE_A:
- case G200_SE_B:
- return mga_g200se_set_plls(mdev, clock);
- case G200_WB:
- case G200_EW3:
- return mga_g200wb_set_plls(mdev, clock);
- case G200_EV:
- return mga_g200ev_set_plls(mdev, clock);
- case G200_EH:
- case G200_EH3:
- return mga_g200eh_set_plls(mdev, clock);
- case G200_ER:
- return mga_g200er_set_plls(mdev, clock);
- }
-
- misc = RREG8(MGA_MISC_IN);
- misc &= ~MGAREG_MISC_CLK_SEL_MASK;
- misc |= MGAREG_MISC_CLK_SEL_MGA_MSK;
- WREG8(MGA_MISC_OUT, misc);
-
- return 0;
-}
-
static void mgag200_g200wb_hold_bmc(struct mga_device *mdev)
{
u8 tmp;
@@ -1137,10 +431,11 @@ static void mgag200_set_mode_regs(struct mga_device *mdev,
WREG8(MGA_MISC_OUT, misc);
}
-static u8 mgag200_get_bpp_shift(struct mga_device *mdev,
- const struct drm_format_info *format)
+static u8 mgag200_get_bpp_shift(const struct drm_format_info *format)
{
- return mdev->bpp_shifts[format->cpp[0] - 1];
+ static const u8 bpp_shift[] = {0, 1, 0, 2};
+
+ return bpp_shift[format->cpp[0] - 1];
}
/*
@@ -1152,7 +447,7 @@ static u32 mgag200_calculate_offset(struct mga_device *mdev,
const struct drm_framebuffer *fb)
{
u32 offset = fb->pitches[0] / fb->format->cpp[0];
- u8 bppshift = mgag200_get_bpp_shift(mdev, fb->format);
+ u8 bppshift = mgag200_get_bpp_shift(fb->format);
if (fb->format->cpp[0] * 8 == 24)
offset = (offset * 3) >> (4 - bppshift);
@@ -1189,7 +484,7 @@ static void mgag200_set_format_regs(struct mga_device *mdev,
bpp = format->cpp[0] * 8;
- bppshift = mgag200_get_bpp_shift(mdev, format);
+ bppshift = mgag200_get_bpp_shift(format);
switch (bpp) {
case 24:
scale = ((1 << bppshift) * 3) - 1;
@@ -1569,7 +864,9 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *dev = crtc->dev;
struct mga_device *mdev = to_mga_device(dev);
+ struct mgag200_pll *pixpll = &mdev->pixpll;
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+ struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
struct drm_framebuffer *fb = plane_state->fb;
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_rect fullscreen = {
@@ -1584,7 +881,8 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
mgag200_set_format_regs(mdev, fb);
mgag200_set_mode_regs(mdev, adjusted_mode);
- mgag200_crtc_set_plls(mdev, adjusted_mode->clock);
+
+ pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc);
if (mdev->type == G200_ER)
mgag200_g200er_reset_tagfifo(mdev);
@@ -1600,7 +898,7 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
mga_crtc_load_lut(crtc);
mgag200_enable_display(mdev);
- mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->map[0]);
+ mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]);
}
static void
@@ -1618,8 +916,13 @@ mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
struct drm_crtc_state *crtc_state)
{
struct drm_plane *plane = plane_state->plane;
+ struct drm_device *dev = plane->dev;
+ struct mga_device *mdev = to_mga_device(dev);
+ struct mgag200_pll *pixpll = &mdev->pixpll;
+ struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
struct drm_framebuffer *new_fb = plane_state->fb;
struct drm_framebuffer *fb = NULL;
+ int ret;
if (!new_fb)
return 0;
@@ -1630,6 +933,13 @@ mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
if (!fb || (fb->format != new_fb->format))
crtc_state->mode_changed = true; /* update PLL settings */
+ if (crtc_state->mode_changed) {
+ ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock,
+ &mgag200_crtc_state->pixpllc);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -1649,7 +959,54 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
return;
if (drm_atomic_helper_damage_merged(old_state, state, &damage))
- mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->map[0]);
+ mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]);
+}
+
+static struct drm_crtc_state *
+mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe *pipe)
+{
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct drm_crtc_state *crtc_state = crtc->state;
+ struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+ struct mgag200_crtc_state *new_mgag200_crtc_state;
+
+ if (!crtc_state)
+ return NULL;
+
+ new_mgag200_crtc_state = kzalloc(sizeof(*new_mgag200_crtc_state), GFP_KERNEL);
+ if (!new_mgag200_crtc_state)
+ return NULL;
+ __drm_atomic_helper_crtc_duplicate_state(crtc, &new_mgag200_crtc_state->base);
+
+ memcpy(&new_mgag200_crtc_state->pixpllc, &mgag200_crtc_state->pixpllc,
+ sizeof(new_mgag200_crtc_state->pixpllc));
+
+ return &new_mgag200_crtc_state->base;
+}
+
+static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_display_pipe *pipe,
+ struct drm_crtc_state *crtc_state)
+{
+ struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+
+ __drm_atomic_helper_crtc_destroy_state(&mgag200_crtc_state->base);
+ kfree(mgag200_crtc_state);
+}
+
+static void mgag200_simple_display_pipe_reset_crtc(struct drm_simple_display_pipe *pipe)
+{
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct mgag200_crtc_state *mgag200_crtc_state;
+
+ if (crtc->state) {
+ mgag200_simple_display_pipe_destroy_crtc_state(pipe, crtc->state);
+ crtc->state = NULL; /* must be set to NULL here */
+ }
+
+ mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL);
+ if (!mgag200_crtc_state)
+ return;
+ __drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base);
}
static const struct drm_simple_display_pipe_funcs
@@ -1659,6 +1016,9 @@ mgag200_simple_display_pipe_funcs = {
.disable = mgag200_simple_display_pipe_disable,
.check = mgag200_simple_display_pipe_check,
.update = mgag200_simple_display_pipe_update,
+ .reset_crtc = mgag200_simple_display_pipe_reset_crtc,
+ .duplicate_crtc_state = mgag200_simple_display_pipe_duplicate_crtc_state,
+ .destroy_crtc_state = mgag200_simple_display_pipe_destroy_crtc_state,
DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
};
@@ -1699,11 +1059,6 @@ int mgag200_modeset_init(struct mga_device *mdev)
size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats);
int ret;
- mdev->bpp_shifts[0] = 0;
- mdev->bpp_shifts[1] = 1;
- mdev->bpp_shifts[2] = 0;
- mdev->bpp_shifts[3] = 2;
-
mgag200_init_regs(mdev);
ret = drmm_mode_config_init(dev);
@@ -1730,6 +1085,10 @@ int mgag200_modeset_init(struct mga_device *mdev)
return ret;
}
+ ret = mgag200_pixpll_init(&mdev->pixpll, mdev);
+ if (ret)
+ return ret;
+
ret = drm_simple_display_pipe_init(dev, pipe,
&mgag200_simple_display_pipe_funcs,
mgag200_simple_display_pipe_formats,
diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c
new file mode 100644
index 000000000000..7c903cf19c0d
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_pll.c
@@ -0,0 +1,992 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/delay.h>
+
+#include "mgag200_drv.h"
+
+/*
+ * G200
+ */
+
+static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ struct mga_device *mdev = pixpll->mdev;
+ struct drm_device *dev = &mdev->base;
+ const int post_div_max = 7;
+ const int in_div_min = 1;
+ const int in_div_max = 6;
+ const int feed_div_min = 7;
+ const int feed_div_max = 127;
+ u8 testp, testm, testn;
+ u8 n = 0, m = 0, p, s;
+ long f_vco;
+ long computed;
+ long delta, tmp_delta;
+ long ref_clk = mdev->model.g200.ref_clk;
+ long p_clk_min = mdev->model.g200.pclk_min;
+ long p_clk_max = mdev->model.g200.pclk_max;
+
+ if (clock > p_clk_max) {
+ drm_err(dev, "Pixel Clock %ld too high\n", clock);
+ return -EINVAL;
+ }
+
+ if (clock < p_clk_min >> 3)
+ clock = p_clk_min >> 3;
+
+ f_vco = clock;
+ for (testp = 0;
+ testp <= post_div_max && f_vco < p_clk_min;
+ testp = (testp << 1) + 1, f_vco <<= 1)
+ ;
+ p = testp + 1;
+
+ delta = clock;
+
+ for (testm = in_div_min; testm <= in_div_max; testm++) {
+ for (testn = feed_div_min; testn <= feed_div_max; testn++) {
+ computed = ref_clk * (testn + 1) / (testm + 1);
+ if (computed < f_vco)
+ tmp_delta = f_vco - computed;
+ else
+ tmp_delta = computed - f_vco;
+ if (tmp_delta < delta) {
+ delta = tmp_delta;
+ m = testm + 1;
+ n = testn + 1;
+ }
+ }
+ }
+ f_vco = ref_clk * n / m;
+ if (f_vco < 100000)
+ s = 0;
+ else if (f_vco < 140000)
+ s = 1;
+ else if (f_vco < 180000)
+ s = 2;
+ else
+ s = 3;
+
+ drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
+ clock, f_vco, m, n, p, s);
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static void
+mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
+{
+ struct mga_device *mdev = pixpll->mdev;
+ unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+ u8 xpixpllcm, xpixpllcn, xpixpllcp;
+
+ pixpllcm = pixpllc->m - 1;
+ pixpllcn = pixpllc->n - 1;
+ pixpllcp = pixpllc->p - 1;
+ pixpllcs = pixpllc->s;
+
+ xpixpllcm = pixpllcm;
+ xpixpllcn = pixpllcn;
+ xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+ WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+ WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+ WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+ WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+}
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = {
+ .compute = mgag200_pixpll_compute_g200,
+ .update = mgag200_pixpll_update_g200,
+};
+
+/*
+ * G200SE
+ */
+
+static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ static const unsigned int vcomax = 320000;
+ static const unsigned int vcomin = 160000;
+ static const unsigned int pllreffreq = 25000;
+
+ unsigned int delta, tmpdelta, permitteddelta;
+ unsigned int testp, testm, testn;
+ unsigned int p, m, n, s;
+ unsigned int computed;
+
+ m = n = p = s = 0;
+ permitteddelta = clock * 5 / 1000;
+
+ for (testp = 8; testp > 0; testp /= 2) {
+ if (clock * testp > vcomax)
+ continue;
+ if (clock * testp < vcomin)
+ continue;
+
+ for (testn = 17; testn < 256; testn++) {
+ for (testm = 1; testm < 32; testm++) {
+ computed = (pllreffreq * testn) / (testm * testp);
+ if (computed > clock)
+ tmpdelta = computed - clock;
+ else
+ tmpdelta = clock - computed;
+ if (tmpdelta < delta) {
+ delta = tmpdelta;
+ m = testm;
+ n = testn;
+ p = testp;
+ }
+ }
+ }
+ }
+
+ if (delta > permitteddelta) {
+ pr_warn("PLL delta too large\n");
+ return -EINVAL;
+ }
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll,
+ const struct mgag200_pll_values *pixpllc)
+{
+ unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+ u8 xpixpllcm, xpixpllcn, xpixpllcp;
+ struct mga_device *mdev = pixpll->mdev;
+
+ pixpllcm = pixpllc->m - 1;
+ pixpllcn = pixpllc->n - 1;
+ pixpllcp = pixpllc->p - 1;
+ pixpllcs = pixpllc->s;
+
+ xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
+ xpixpllcn = pixpllcn;
+ xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+ WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+ WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+ WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+ WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+}
+
+static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ static const unsigned int vcomax = 1600000;
+ static const unsigned int vcomin = 800000;
+ static const unsigned int pllreffreq = 25000;
+ static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
+
+ unsigned int delta, tmpdelta, permitteddelta;
+ unsigned int testp, testm, testn;
+ unsigned int p, m, n, s;
+ unsigned int computed;
+ unsigned int fvv;
+ unsigned int i;
+
+ m = n = p = s = 0;
+ delta = 0xffffffff;
+
+ if (clock < 25000)
+ clock = 25000;
+ clock = clock * 2;
+
+ /* Permited delta is 0.5% as VESA Specification */
+ permitteddelta = clock * 5 / 1000;
+
+ for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
+ testp = pvalues_e4[i];
+
+ if ((clock * testp) > vcomax)
+ continue;
+ if ((clock * testp) < vcomin)
+ continue;
+
+ for (testn = 50; testn <= 256; testn++) {
+ for (testm = 1; testm <= 32; testm++) {
+ computed = (pllreffreq * testn) / (testm * testp);
+ if (computed > clock)
+ tmpdelta = computed - clock;
+ else
+ tmpdelta = clock - computed;
+
+ if (tmpdelta < delta) {
+ delta = tmpdelta;
+ m = testm;
+ n = testn;
+ p = testp;
+ }
+ }
+ }
+ }
+
+ fvv = pllreffreq * n / m;
+ fvv = (fvv - 800000) / 50000;
+ if (fvv > 15)
+ fvv = 15;
+ s = fvv << 1;
+
+ if (delta > permitteddelta) {
+ pr_warn("PLL delta too large\n");
+ return -EINVAL;
+ }
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll,
+ const struct mgag200_pll_values *pixpllc)
+{
+ unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+ u8 xpixpllcm, xpixpllcn, xpixpllcp;
+ struct mga_device *mdev = pixpll->mdev;
+
+ pixpllcm = pixpllc->m - 1;
+ pixpllcn = pixpllc->n - 1;
+ pixpllcp = pixpllc->p - 1;
+ pixpllcs = pixpllc->s;
+
+ xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
+ xpixpllcn = pixpllcn;
+ xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+ WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+ WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+ WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+ WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+
+ WREG_DAC(0x1a, 0x09);
+ msleep(20);
+ WREG_DAC(0x1a, 0x01);
+}
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = {
+ .compute = mgag200_pixpll_compute_g200se_00,
+ .update = mgag200_pixpll_update_g200se_00,
+};
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = {
+ .compute = mgag200_pixpll_compute_g200se_04,
+ .update = mgag200_pixpll_update_g200se_04,
+};
+
+/*
+ * G200WB
+ */
+
+static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ static const unsigned int vcomax = 550000;
+ static const unsigned int vcomin = 150000;
+ static const unsigned int pllreffreq = 48000;
+
+ unsigned int delta, tmpdelta;
+ unsigned int testp, testm, testn;
+ unsigned int p, m, n, s;
+ unsigned int computed;
+
+ m = n = p = s = 0;
+ delta = 0xffffffff;
+
+ for (testp = 1; testp < 9; testp++) {
+ if (clock * testp > vcomax)
+ continue;
+ if (clock * testp < vcomin)
+ continue;
+
+ for (testm = 1; testm < 17; testm++) {
+ for (testn = 1; testn < 151; testn++) {
+ computed = (pllreffreq * testn) / (testm * testp);
+ if (computed > clock)
+ tmpdelta = computed - clock;
+ else
+ tmpdelta = clock - computed;
+ if (tmpdelta < delta) {
+ delta = tmpdelta;
+ n = testn;
+ m = testm;
+ p = testp;
+ s = 0;
+ }
+ }
+ }
+ }
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static void
+mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
+{
+ unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+ u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+ int i, j, tmpcount, vcount;
+ struct mga_device *mdev = pixpll->mdev;
+ bool pll_locked = false;
+
+ pixpllcm = pixpllc->m - 1;
+ pixpllcn = pixpllc->n - 1;
+ pixpllcp = pixpllc->p - 1;
+ pixpllcs = pixpllc->s;
+
+ xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
+ xpixpllcn = pixpllcn;
+ xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
+
+ WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+ for (i = 0; i <= 32 && pll_locked == false; i++) {
+ if (i > 0) {
+ WREG8(MGAREG_CRTC_INDEX, 0x1e);
+ tmp = RREG8(MGAREG_CRTC_DATA);
+ if (tmp < 0xff)
+ WREG8(MGAREG_CRTC_DATA, tmp+1);
+ }
+
+ /* set pixclkdis to 1 */
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ WREG8(DAC_DATA, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_REMHEADCTL_CLKDIS;
+ WREG8(DAC_DATA, tmp);
+
+ /* select PLL Set C */
+ tmp = RREG8(MGAREG_MEM_MISC_READ);
+ tmp |= 0x3 << 2;
+ WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
+ WREG8(DAC_DATA, tmp);
+
+ udelay(500);
+
+ /* reset the PLL */
+ WREG8(DAC_INDEX, MGA1064_VREF_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~0x04;
+ WREG8(DAC_DATA, tmp);
+
+ udelay(50);
+
+ /* program pixel pll register */
+ WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+ WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+ WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+
+ udelay(50);
+
+ /* turn pll on */
+ WREG8(DAC_INDEX, MGA1064_VREF_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= 0x04;
+ WREG_DAC(MGA1064_VREF_CTL, tmp);
+
+ udelay(500);
+
+ /* select the pixel pll */
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+ tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+ WREG8(DAC_DATA, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
+ tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
+ WREG8(DAC_DATA, tmp);
+
+ /* reset dotclock rate bit */
+ WREG8(MGAREG_SEQ_INDEX, 1);
+ tmp = RREG8(MGAREG_SEQ_DATA);
+ tmp &= ~0x8;
+ WREG8(MGAREG_SEQ_DATA, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ WREG8(DAC_DATA, tmp);
+
+ vcount = RREG8(MGAREG_VCOUNT);
+
+ for (j = 0; j < 30 && pll_locked == false; j++) {
+ tmpcount = RREG8(MGAREG_VCOUNT);
+ if (tmpcount < vcount)
+ vcount = 0;
+ if ((tmpcount - vcount) > 2)
+ pll_locked = true;
+ else
+ udelay(5);
+ }
+ }
+
+ WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
+ WREG_DAC(MGA1064_REMHEADCTL, tmp);
+}
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = {
+ .compute = mgag200_pixpll_compute_g200wb,
+ .update = mgag200_pixpll_update_g200wb,
+};
+
+/*
+ * G200EV
+ */
+
+static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ static const unsigned int vcomax = 550000;
+ static const unsigned int vcomin = 150000;
+ static const unsigned int pllreffreq = 50000;
+
+ unsigned int delta, tmpdelta;
+ unsigned int testp, testm, testn;
+ unsigned int p, m, n, s;
+ unsigned int computed;
+
+ m = n = p = s = 0;
+ delta = 0xffffffff;
+
+ for (testp = 16; testp > 0; testp--) {
+ if (clock * testp > vcomax)
+ continue;
+ if (clock * testp < vcomin)
+ continue;
+
+ for (testn = 1; testn < 257; testn++) {
+ for (testm = 1; testm < 17; testm++) {
+ computed = (pllreffreq * testn) /
+ (testm * testp);
+ if (computed > clock)
+ tmpdelta = computed - clock;
+ else
+ tmpdelta = clock - computed;
+ if (tmpdelta < delta) {
+ delta = tmpdelta;
+ n = testn;
+ m = testm;
+ p = testp;
+ }
+ }
+ }
+ }
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static void
+mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
+{
+ unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+ u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+ struct mga_device *mdev = pixpll->mdev;
+
+ pixpllcm = pixpllc->m - 1;
+ pixpllcn = pixpllc->n - 1;
+ pixpllcp = pixpllc->p - 1;
+ pixpllcs = pixpllc->s;
+
+ xpixpllcm = pixpllcm;
+ xpixpllcn = pixpllcn;
+ xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+ WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ WREG8(DAC_DATA, tmp);
+
+ tmp = RREG8(MGAREG_MEM_MISC_READ);
+ tmp |= 0x3 << 2;
+ WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
+ tmp = RREG8(DAC_DATA);
+ WREG8(DAC_DATA, tmp & ~0x40);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ WREG8(DAC_DATA, tmp);
+
+ WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm);
+ WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn);
+ WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp);
+
+ udelay(50);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ WREG8(DAC_DATA, tmp);
+
+ udelay(500);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+ tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+ WREG8(DAC_DATA, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
+ tmp = RREG8(DAC_DATA);
+ WREG8(DAC_DATA, tmp | 0x40);
+
+ tmp = RREG8(MGAREG_MEM_MISC_READ);
+ tmp |= (0x3 << 2);
+ WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ WREG8(DAC_DATA, tmp);
+}
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = {
+ .compute = mgag200_pixpll_compute_g200ev,
+ .update = mgag200_pixpll_update_g200ev,
+};
+
+/*
+ * G200EH
+ */
+
+static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ static const unsigned int vcomax = 800000;
+ static const unsigned int vcomin = 400000;
+ static const unsigned int pllreffreq = 33333;
+
+ unsigned int delta, tmpdelta;
+ unsigned int testp, testm, testn;
+ unsigned int p, m, n, s;
+ unsigned int computed;
+
+ m = n = p = s = 0;
+ delta = 0xffffffff;
+
+ for (testp = 16; testp > 0; testp >>= 1) {
+ if (clock * testp > vcomax)
+ continue;
+ if (clock * testp < vcomin)
+ continue;
+
+ for (testm = 1; testm < 33; testm++) {
+ for (testn = 17; testn < 257; testn++) {
+ computed = (pllreffreq * testn) / (testm * testp);
+ if (computed > clock)
+ tmpdelta = computed - clock;
+ else
+ tmpdelta = clock - computed;
+ if (tmpdelta < delta) {
+ delta = tmpdelta;
+ n = testn;
+ m = testm;
+ p = testp;
+ }
+ }
+ }
+ }
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static void
+mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
+{
+ unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+ u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+ int i, j, tmpcount, vcount;
+ struct mga_device *mdev = pixpll->mdev;
+ bool pll_locked = false;
+
+ pixpllcm = pixpllc->m - 1;
+ pixpllcn = pixpllc->n - 1;
+ pixpllcp = pixpllc->p - 1;
+ pixpllcs = pixpllc->s;
+
+ xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
+ xpixpllcn = pixpllcn;
+ xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+ WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+ for (i = 0; i <= 32 && pll_locked == false; i++) {
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ WREG8(DAC_DATA, tmp);
+
+ tmp = RREG8(MGAREG_MEM_MISC_READ);
+ tmp |= 0x3 << 2;
+ WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ WREG8(DAC_DATA, tmp);
+
+ udelay(500);
+
+ WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm);
+ WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn);
+ WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp);
+
+ udelay(500);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+ tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+ WREG8(DAC_DATA, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ WREG8(DAC_DATA, tmp);
+
+ vcount = RREG8(MGAREG_VCOUNT);
+
+ for (j = 0; j < 30 && pll_locked == false; j++) {
+ tmpcount = RREG8(MGAREG_VCOUNT);
+ if (tmpcount < vcount)
+ vcount = 0;
+ if ((tmpcount - vcount) > 2)
+ pll_locked = true;
+ else
+ udelay(5);
+ }
+ }
+}
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = {
+ .compute = mgag200_pixpll_compute_g200eh,
+ .update = mgag200_pixpll_update_g200eh,
+};
+
+/*
+ * G200EH3
+ */
+
+static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ static const unsigned int vcomax = 3000000;
+ static const unsigned int vcomin = 1500000;
+ static const unsigned int pllreffreq = 25000;
+
+ unsigned int delta, tmpdelta;
+ unsigned int testp, testm, testn;
+ unsigned int p, m, n, s;
+ unsigned int computed;
+
+ m = n = p = s = 0;
+ delta = 0xffffffff;
+ testp = 0;
+
+ for (testm = 150; testm >= 6; testm--) {
+ if (clock * testm > vcomax)
+ continue;
+ if (clock * testm < vcomin)
+ continue;
+ for (testn = 120; testn >= 60; testn--) {
+ computed = (pllreffreq * testn) / testm;
+ if (computed > clock)
+ tmpdelta = computed - clock;
+ else
+ tmpdelta = clock - computed;
+ if (tmpdelta < delta) {
+ delta = tmpdelta;
+ n = testn + 1;
+ m = testm + 1;
+ p = testp + 1;
+ }
+ if (delta == 0)
+ break;
+ }
+ if (delta == 0)
+ break;
+ }
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = {
+ .compute = mgag200_pixpll_compute_g200eh3,
+ .update = mgag200_pixpll_update_g200eh, // same as G200EH
+};
+
+/*
+ * G200ER
+ */
+
+static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ static const unsigned int vcomax = 1488000;
+ static const unsigned int vcomin = 1056000;
+ static const unsigned int pllreffreq = 48000;
+ static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
+
+ unsigned int delta, tmpdelta;
+ int testr, testn, testm, testo;
+ unsigned int p, m, n, s;
+ unsigned int computed, vco;
+
+ m = n = p = s = 0;
+ delta = 0xffffffff;
+
+ for (testr = 0; testr < 4; testr++) {
+ if (delta == 0)
+ break;
+ for (testn = 5; testn < 129; testn++) {
+ if (delta == 0)
+ break;
+ for (testm = 3; testm >= 0; testm--) {
+ if (delta == 0)
+ break;
+ for (testo = 5; testo < 33; testo++) {
+ vco = pllreffreq * (testn + 1) /
+ (testr + 1);
+ if (vco < vcomin)
+ continue;
+ if (vco > vcomax)
+ continue;
+ computed = vco / (m_div_val[testm] * (testo + 1));
+ if (computed > clock)
+ tmpdelta = computed - clock;
+ else
+ tmpdelta = clock - computed;
+ if (tmpdelta < delta) {
+ delta = tmpdelta;
+ m = (testm | (testo << 3)) + 1;
+ n = testn + 1;
+ p = testr + 1;
+ s = testr;
+ }
+ }
+ }
+ }
+ }
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static void
+mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
+{
+ unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+ u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+ struct mga_device *mdev = pixpll->mdev;
+
+ pixpllcm = pixpllc->m - 1;
+ pixpllcn = pixpllc->n - 1;
+ pixpllcp = pixpllc->p - 1;
+ pixpllcs = pixpllc->s;
+
+ xpixpllcm = pixpllcm;
+ xpixpllcn = pixpllcn;
+ xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+ WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ WREG8(DAC_DATA, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+ tmp = RREG8(DAC_DATA);
+ tmp |= MGA1064_REMHEADCTL_CLKDIS;
+ WREG8(DAC_DATA, tmp);
+
+ tmp = RREG8(MGAREG_MEM_MISC_READ);
+ tmp |= (0x3<<2) | 0xc0;
+ WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+ WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+ tmp = RREG8(DAC_DATA);
+ tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ WREG8(DAC_DATA, tmp);
+
+ udelay(500);
+
+ WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn);
+ WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm);
+ WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp);
+
+ udelay(50);
+}
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = {
+ .compute = mgag200_pixpll_compute_g200er,
+ .update = mgag200_pixpll_update_g200er,
+};
+
+/*
+ * G200EW3
+ */
+
+static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock,
+ struct mgag200_pll_values *pixpllc)
+{
+ static const unsigned int vcomax = 800000;
+ static const unsigned int vcomin = 400000;
+ static const unsigned int pllreffreq = 25000;
+
+ unsigned int delta, tmpdelta;
+ unsigned int testp, testm, testn, testp2;
+ unsigned int p, m, n, s;
+ unsigned int computed;
+
+ m = n = p = s = 0;
+ delta = 0xffffffff;
+
+ for (testp = 1; testp < 8; testp++) {
+ for (testp2 = 1; testp2 < 8; testp2++) {
+ if (testp < testp2)
+ continue;
+ if ((clock * testp * testp2) > vcomax)
+ continue;
+ if ((clock * testp * testp2) < vcomin)
+ continue;
+ for (testm = 1; testm < 26; testm++) {
+ for (testn = 32; testn < 2048 ; testn++) {
+ computed = (pllreffreq * testn) / (testm * testp * testp2);
+ if (computed > clock)
+ tmpdelta = computed - clock;
+ else
+ tmpdelta = clock - computed;
+ if (tmpdelta < delta) {
+ delta = tmpdelta;
+ m = testm + 1;
+ n = testn + 1;
+ p = testp + 1;
+ s = testp2;
+ }
+ }
+ }
+ }
+ }
+
+ pixpllc->m = m;
+ pixpllc->n = n;
+ pixpllc->p = p;
+ pixpllc->s = s;
+
+ return 0;
+}
+
+static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = {
+ .compute = mgag200_pixpll_compute_g200ew3,
+ .update = mgag200_pixpll_update_g200wb, // same as G200WB
+};
+
+/*
+ * PLL initialization
+ */
+
+int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev)
+{
+ struct drm_device *dev = &mdev->base;
+
+ pixpll->mdev = mdev;
+
+ switch (mdev->type) {
+ case G200_PCI:
+ case G200_AGP:
+ pixpll->funcs = &mgag200_pixpll_funcs_g200;
+ break;
+ case G200_SE_A:
+ case G200_SE_B:
+ if (mdev->model.g200se.unique_rev_id >= 0x04)
+ pixpll->funcs = &mgag200_pixpll_funcs_g200se_04;
+ else
+ pixpll->funcs = &mgag200_pixpll_funcs_g200se_00;
+ break;
+ case G200_WB:
+ pixpll->funcs = &mgag200_pixpll_funcs_g200wb;
+ break;
+ case G200_EV:
+ pixpll->funcs = &mgag200_pixpll_funcs_g200ev;
+ break;
+ case G200_EH:
+ pixpll->funcs = &mgag200_pixpll_funcs_g200eh;
+ break;
+ case G200_EH3:
+ pixpll->funcs = &mgag200_pixpll_funcs_g200eh3;
+ break;
+ case G200_ER:
+ pixpll->funcs = &mgag200_pixpll_funcs_g200er;
+ break;
+ case G200_EW3:
+ pixpll->funcs = &mgag200_pixpll_funcs_g200ew3;
+ break;
+ default:
+ drm_err(dev, "unknown device type %d\n", mdev->type);
+ return -ENODEV;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h
index 977be0565c06..60e705283fe8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_reg.h
+++ b/drivers/gpu/drm/mgag200/mgag200_reg.h
@@ -222,11 +222,10 @@
#define MGAREG_MISC_IOADSEL (0x1 << 0)
#define MGAREG_MISC_RAMMAPEN (0x1 << 1)
-#define MGAREG_MISC_CLK_SEL_MASK GENMASK(3, 2)
-#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2)
-#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2)
-#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2)
-#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2)
+#define MGAREG_MISC_CLKSEL_MASK GENMASK(3, 2)
+#define MGAREG_MISC_CLKSEL_VGA25 (0x0 << 2)
+#define MGAREG_MISC_CLKSEL_VGA28 (0x1 << 2)
+#define MGAREG_MISC_CLKSEL_MGA (0x3 << 2)
#define MGAREG_MISC_VIDEO_DIS (0x1 << 4)
#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5)
#define MGAREG_MISC_HSYNCPOL BIT(6)
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 52536e7adb95..e9c6af78b1d7 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -14,6 +14,7 @@ config DRM_MSM
select REGULATOR
select DRM_KMS_HELPER
select DRM_PANEL
+ select DRM_SCHED
select SHMEM
select TMPFS
select QCOM_SCM if ARCH_QCOM
@@ -115,9 +116,9 @@ config DRM_MSM_DSI_10NM_PHY
Choose this option if DSI PHY on SDM845 is used on the platform.
config DRM_MSM_DSI_7NM_PHY
- bool "Enable DSI 7nm PHY driver in MSM DRM (used by SM8150/SM8250)"
+ bool "Enable DSI 7nm PHY driver in MSM DRM"
depends on DRM_MSM_DSI
default y
help
- Choose this option if DSI PHY on SM8150/SM8250 is used on the
- platform.
+ Choose this option if DSI PHY on SM8150/SM8250/SC7280 is used on
+ the platform.
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 2c00aa70b708..904535eda0c4 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -90,6 +90,7 @@ msm-y := \
msm_gem_submit.o \
msm_gem_vma.o \
msm_gpu.o \
+ msm_gpu_devfreq.o \
msm_iommu.o \
msm_perf.o \
msm_rd.o \
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
index fc2c905b6c9e..c9d11d57aed6 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
@@ -117,13 +117,13 @@ reset_set(void *data, u64 val)
if (a5xx_gpu->pm4_bo) {
msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->aspace);
- drm_gem_object_put_locked(a5xx_gpu->pm4_bo);
+ drm_gem_object_put(a5xx_gpu->pm4_bo);
a5xx_gpu->pm4_bo = NULL;
}
if (a5xx_gpu->pfp_bo) {
msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->aspace);
- drm_gem_object_put_locked(a5xx_gpu->pfp_bo);
+ drm_gem_object_put(a5xx_gpu->pfp_bo);
a5xx_gpu->pfp_bo = NULL;
}
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 7a271de9a212..5e2750eb3810 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -18,6 +18,18 @@ static void a5xx_dump(struct msm_gpu *gpu);
#define GPU_PAS_ID 13
+static void update_shadow_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+
+ if (a5xx_gpu->has_whereami) {
+ OUT_PKT7(ring, CP_WHERE_AM_I, 2);
+ OUT_RING(ring, lower_32_bits(shadowptr(a5xx_gpu, ring)));
+ OUT_RING(ring, upper_32_bits(shadowptr(a5xx_gpu, ring)));
+ }
+}
+
void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
bool sync)
{
@@ -30,11 +42,8 @@ void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
* Most flush operations need to issue a WHERE_AM_I opcode to sync up
* the rptr shadow
*/
- if (a5xx_gpu->has_whereami && sync) {
- OUT_PKT7(ring, CP_WHERE_AM_I, 2);
- OUT_RING(ring, lower_32_bits(shadowptr(a5xx_gpu, ring)));
- OUT_RING(ring, upper_32_bits(shadowptr(a5xx_gpu, ring)));
- }
+ if (sync)
+ update_shadow_rptr(gpu, ring);
spin_lock_irqsave(&ring->preempt_lock, flags);
@@ -168,6 +177,16 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
ibs++;
break;
}
+
+ /*
+ * Periodically update shadow-wptr if needed, so that we
+ * can see partial progress of submits with large # of
+ * cmds.. otherwise we could needlessly stall waiting for
+ * ringbuffer state, simply due to looking at a shadow
+ * rptr value that has not been updated
+ */
+ if ((ibs % 32) == 0)
+ update_shadow_rptr(gpu, ring);
}
/*
@@ -1415,7 +1434,7 @@ struct a5xx_gpu_state {
static int a5xx_crashdumper_init(struct msm_gpu *gpu,
struct a5xx_crashdumper *dumper)
{
- dumper->ptr = msm_gem_kernel_new_locked(gpu->dev,
+ dumper->ptr = msm_gem_kernel_new(gpu->dev,
SZ_1M, MSM_BO_WC, gpu->aspace,
&dumper->bo, &dumper->iova);
@@ -1517,7 +1536,7 @@ static void a5xx_gpu_state_get_hlsq_regs(struct msm_gpu *gpu,
if (a5xx_crashdumper_run(gpu, &dumper)) {
kfree(a5xx_state->hlsqregs);
- msm_gem_kernel_put(dumper.bo, gpu->aspace, true);
+ msm_gem_kernel_put(dumper.bo, gpu->aspace);
return;
}
@@ -1525,7 +1544,7 @@ static void a5xx_gpu_state_get_hlsq_regs(struct msm_gpu *gpu,
memcpy(a5xx_state->hlsqregs, dumper.ptr + (256 * SZ_1K),
count * sizeof(u32));
- msm_gem_kernel_put(dumper.bo, gpu->aspace, true);
+ msm_gem_kernel_put(dumper.bo, gpu->aspace);
}
static struct msm_gpu_state *a5xx_gpu_state_get(struct msm_gpu *gpu)
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c
index cdb165236a88..0e63a1429189 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_power.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c
@@ -362,7 +362,7 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
*/
bosize = (cmds_size + (cmds_size / TYPE4_MAX_PAYLOAD) + 1) << 2;
- ptr = msm_gem_kernel_new_locked(drm, bosize,
+ ptr = msm_gem_kernel_new(drm, bosize,
MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace,
&a5xx_gpu->gpmu_bo, &a5xx_gpu->gpmu_iova);
if (IS_ERR(ptr))
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
index ee72510ff8ce..8abc9a2b114a 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
@@ -240,7 +240,7 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu,
A5XX_PREEMPT_COUNTER_SIZE,
MSM_BO_WC, gpu->aspace, &counters_bo, &counters_iova);
if (IS_ERR(counters)) {
- msm_gem_kernel_put(bo, gpu->aspace, true);
+ msm_gem_kernel_put(bo, gpu->aspace);
return PTR_ERR(counters);
}
@@ -272,9 +272,8 @@ void a5xx_preempt_fini(struct msm_gpu *gpu)
int i;
for (i = 0; i < gpu->nr_rings; i++) {
- msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->aspace, true);
- msm_gem_kernel_put(a5xx_gpu->preempt_counters_bo[i],
- gpu->aspace, true);
+ msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->aspace);
+ msm_gem_kernel_put(a5xx_gpu->preempt_counters_bo[i], gpu->aspace);
}
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index b349692219b7..a7c58018959f 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -519,9 +519,9 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
if (!pdcptr)
goto err;
- if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu))
+ if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu))
pdc_in_aop = true;
- else if (adreno_is_a618(adreno_gpu) || adreno_is_a640(adreno_gpu))
+ else if (adreno_is_a618(adreno_gpu) || adreno_is_a640_family(adreno_gpu))
pdc_address_offset = 0x30090;
else
pdc_address_offset = 0x30080;
@@ -933,6 +933,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
/* Use a known rate to bring up the GMU */
clk_set_rate(gmu->core_clk, 200000000);
+ clk_set_rate(gmu->hub_clk, 150000000);
ret = clk_bulk_prepare_enable(gmu->nr_clocks, gmu->clocks);
if (ret) {
pm_runtime_put(gmu->gxpd);
@@ -1129,12 +1130,12 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu)
{
- msm_gem_kernel_put(gmu->hfi.obj, gmu->aspace, false);
- msm_gem_kernel_put(gmu->debug.obj, gmu->aspace, false);
- msm_gem_kernel_put(gmu->icache.obj, gmu->aspace, false);
- msm_gem_kernel_put(gmu->dcache.obj, gmu->aspace, false);
- msm_gem_kernel_put(gmu->dummy.obj, gmu->aspace, false);
- msm_gem_kernel_put(gmu->log.obj, gmu->aspace, false);
+ msm_gem_kernel_put(gmu->hfi.obj, gmu->aspace);
+ msm_gem_kernel_put(gmu->debug.obj, gmu->aspace);
+ msm_gem_kernel_put(gmu->icache.obj, gmu->aspace);
+ msm_gem_kernel_put(gmu->dcache.obj, gmu->aspace);
+ msm_gem_kernel_put(gmu->dummy.obj, gmu->aspace);
+ msm_gem_kernel_put(gmu->log.obj, gmu->aspace);
gmu->aspace->mmu->funcs->detach(gmu->aspace->mmu);
msm_gem_address_space_put(gmu->aspace);
@@ -1393,6 +1394,9 @@ static int a6xx_gmu_clocks_probe(struct a6xx_gmu *gmu)
gmu->core_clk = msm_clk_bulk_get_clock(gmu->clocks,
gmu->nr_clocks, "gmu");
+ gmu->hub_clk = msm_clk_bulk_get_clock(gmu->clocks,
+ gmu->nr_clocks, "hub");
+
return 0;
}
@@ -1504,7 +1508,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
* are otherwise unused by a660.
*/
gmu->dummy.size = SZ_4K;
- if (adreno_is_a660(adreno_gpu)) {
+ if (adreno_is_a660_family(adreno_gpu)) {
ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_4K * 7, 0x60400000);
if (ret)
goto err_memory;
@@ -1522,7 +1526,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
SZ_16M - SZ_16K, 0x04000);
if (ret)
goto err_memory;
- } else if (adreno_is_a640(adreno_gpu)) {
+ } else if (adreno_is_a640_family(adreno_gpu)) {
ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache,
SZ_256K - SZ_16K, 0x04000);
if (ret)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 71dfa60070cc..3c74f64e3126 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -66,6 +66,7 @@ struct a6xx_gmu {
int nr_clocks;
struct clk_bulk_data *clocks;
struct clk *core_clk;
+ struct clk *hub_clk;
/* current performance index set externally */
int current_perf_index;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 9c5e4618aa0a..40c9fef457a4 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -52,21 +52,25 @@ static bool a6xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
return true;
}
-static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+static void update_shadow_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
- uint32_t wptr;
- unsigned long flags;
/* Expanded APRIV doesn't need to issue the WHERE_AM_I opcode */
if (a6xx_gpu->has_whereami && !adreno_gpu->base.hw_apriv) {
- struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
-
OUT_PKT7(ring, CP_WHERE_AM_I, 2);
OUT_RING(ring, lower_32_bits(shadowptr(a6xx_gpu, ring)));
OUT_RING(ring, upper_32_bits(shadowptr(a6xx_gpu, ring)));
}
+}
+
+static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+{
+ uint32_t wptr;
+ unsigned long flags;
+
+ update_shadow_rptr(gpu, ring);
spin_lock_irqsave(&ring->preempt_lock, flags);
@@ -145,7 +149,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct msm_ringbuffer *ring = submit->ring;
- unsigned int i;
+ unsigned int i, ibs = 0;
a6xx_set_pagetable(a6xx_gpu, ring, submit->queue->ctx);
@@ -181,8 +185,19 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
OUT_RING(ring, upper_32_bits(submit->cmd[i].iova));
OUT_RING(ring, submit->cmd[i].size);
+ ibs++;
break;
}
+
+ /*
+ * Periodically update shadow-wptr if needed, so that we
+ * can see partial progress of submits with large # of
+ * cmds.. otherwise we could needlessly stall waiting for
+ * ringbuffer state, simply due to looking at a shadow
+ * rptr value that has not been updated
+ */
+ if ((ibs % 32) == 0)
+ update_shadow_rptr(gpu, ring);
}
get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
@@ -652,7 +667,7 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
regs = a650_protect;
count = ARRAY_SIZE(a650_protect);
count_max = 48;
- } else if (adreno_is_a660(adreno_gpu)) {
+ } else if (adreno_is_a660_family(adreno_gpu)) {
regs = a660_protect;
count = ARRAY_SIZE(a660_protect);
count_max = 48;
@@ -683,7 +698,7 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
if (adreno_is_a618(adreno_gpu))
return;
- if (adreno_is_a640(adreno_gpu))
+ if (adreno_is_a640_family(adreno_gpu))
amsbc = 1;
if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu)) {
@@ -694,6 +709,13 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
uavflagprd_inv = 2;
}
+ if (adreno_is_7c3(adreno_gpu)) {
+ lower_bit = 1;
+ amsbc = 1;
+ rgb565_predicator = 1;
+ uavflagprd_inv = 2;
+ }
+
gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL,
rgb565_predicator << 11 | amsbc << 4 | lower_bit << 1);
gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, lower_bit << 1);
@@ -740,6 +762,7 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
{
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
+ const char *sqe_name = adreno_gpu->info->fw[ADRENO_FW_SQE];
u32 *buf = msm_gem_get_vaddr(obj);
bool ret = false;
@@ -756,8 +779,7 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
*
* a660 targets have all the critical security fixes from the start
*/
- if (adreno_is_a618(adreno_gpu) || adreno_is_a630(adreno_gpu) ||
- adreno_is_a640(adreno_gpu)) {
+ if (!strcmp(sqe_name, "a630_sqe.fw")) {
/*
* If the lowest nibble is 0xa that is an indication that this
* microcode has been patched. The actual version is in dword
@@ -778,7 +800,7 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
DRM_DEV_ERROR(&gpu->pdev->dev,
"a630 SQE ucode is too old. Have version %x need at least %x\n",
buf[0] & 0xfff, 0x190);
- } else if (adreno_is_a650(adreno_gpu)) {
+ } else if (!strcmp(sqe_name, "a650_sqe.fw")) {
if ((buf[0] & 0xfff) >= 0x095) {
ret = true;
goto out;
@@ -787,7 +809,7 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
DRM_DEV_ERROR(&gpu->pdev->dev,
"a650 SQE ucode is too old. Have version %x need at least %x\n",
buf[0] & 0xfff, 0x095);
- } else if (adreno_is_a660(adreno_gpu)) {
+ } else if (!strcmp(sqe_name, "a660_sqe.fw")) {
ret = true;
} else {
DRM_DEV_ERROR(&gpu->pdev->dev,
@@ -897,7 +919,8 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
a6xx_set_hwcg(gpu, true);
/* VBIF/GBIF start*/
- if (adreno_is_a640(adreno_gpu) || adreno_is_a650_family(adreno_gpu)) {
+ if (adreno_is_a640_family(adreno_gpu) ||
+ adreno_is_a650_family(adreno_gpu)) {
gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620);
gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620);
gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620);
@@ -935,13 +958,14 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804);
gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4);
- if (adreno_is_a640(adreno_gpu) || adreno_is_a650_family(adreno_gpu))
+ if (adreno_is_a640_family(adreno_gpu) ||
+ adreno_is_a650_family(adreno_gpu))
gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140);
else
gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0);
gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);
- if (adreno_is_a660(adreno_gpu))
+ if (adreno_is_a660_family(adreno_gpu))
gpu_write(gpu, REG_A6XX_CP_LPAC_PROG_FIFO_SIZE, 0x00000020);
/* Setting the mem pool size */
@@ -952,8 +976,10 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
*/
if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu))
gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300200);
- else if (adreno_is_a640(adreno_gpu))
+ else if (adreno_is_a640_family(adreno_gpu) || adreno_is_7c3(adreno_gpu))
gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200200);
+ else if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu))
+ gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300200);
else
gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00180000);
@@ -990,13 +1016,15 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
/* Protect registers from the CP */
a6xx_set_cp_protect(gpu);
- if (adreno_is_a660(adreno_gpu)) {
+ if (adreno_is_a660_family(adreno_gpu)) {
gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, 0x1);
gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x0);
- /* Set dualQ + disable afull for A660 GPU but not for A635 */
- gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x66906);
}
+ /* Set dualQ + disable afull for A660 GPU */
+ if (adreno_is_a660(adreno_gpu))
+ gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x66906);
+
/* Enable expanded apriv for targets that support it */
if (gpu->hw_apriv) {
gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL,
@@ -1035,7 +1063,7 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami) {
if (!a6xx_gpu->shadow_bo) {
- a6xx_gpu->shadow = msm_gem_kernel_new_locked(gpu->dev,
+ a6xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
sizeof(u32) * gpu->nr_rings,
MSM_BO_WC | MSM_BO_MAP_PRIV,
gpu->aspace, &a6xx_gpu->shadow_bo,
@@ -1383,13 +1411,13 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
{
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
- u32 cntl1_regval = 0;
+ u32 gpu_scid, cntl1_regval = 0;
if (IS_ERR(a6xx_gpu->llc_mmio))
return;
if (!llcc_slice_activate(a6xx_gpu->llc_slice)) {
- u32 gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice);
+ gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice);
gpu_scid &= 0x1f;
cntl1_regval = (gpu_scid << 0) | (gpu_scid << 5) | (gpu_scid << 10) |
@@ -1409,26 +1437,34 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
}
}
- if (cntl1_regval) {
+ if (!cntl1_regval)
+ return;
+
+ /*
+ * Program the slice IDs for the various GPU blocks and GPU MMU
+ * pagetables
+ */
+ if (!a6xx_gpu->have_mmu500) {
+ a6xx_llc_write(a6xx_gpu,
+ REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1, cntl1_regval);
+
/*
- * Program the slice IDs for the various GPU blocks and GPU MMU
- * pagetables
+ * Program cacheability overrides to not allocate cache
+ * lines on a write miss
*/
- if (a6xx_gpu->have_mmu500)
- gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0),
- cntl1_regval);
- else {
- a6xx_llc_write(a6xx_gpu,
- REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1, cntl1_regval);
-
- /*
- * Program cacheability overrides to not allocate cache
- * lines on a write miss
- */
- a6xx_llc_rmw(a6xx_gpu,
- REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0, 0xF, 0x03);
- }
+ a6xx_llc_rmw(a6xx_gpu,
+ REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0, 0xF, 0x03);
+ return;
}
+
+ gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0), cntl1_regval);
+
+ /* On A660, the SCID programming for UCHE traffic is done in
+ * A6XX_GBIF_SCACHE_CNTL0[14:10]
+ */
+ if (adreno_is_a660_family(adreno_gpu))
+ gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) |
+ (1 << 8), (gpu_scid << 10) | (1 << 8));
}
static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu)
@@ -1477,7 +1513,7 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
if (ret)
return ret;
- msm_gpu_resume_devfreq(gpu);
+ msm_devfreq_resume(gpu);
a6xx_llc_activate(a6xx_gpu);
@@ -1494,7 +1530,7 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
a6xx_llc_deactivate(a6xx_gpu);
- devfreq_suspend_device(gpu->devfreq.devfreq);
+ msm_devfreq_suspend(gpu);
ret = a6xx_gmu_stop(a6xx_gpu);
if (ret)
@@ -1667,11 +1703,11 @@ static u32 a618_get_speed_bin(u32 fuse)
return UINT_MAX;
}
-static u32 fuse_to_supp_hw(struct device *dev, u32 revn, u32 fuse)
+static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse)
{
u32 val = UINT_MAX;
- if (revn == 618)
+ if (adreno_cmp_rev(ADRENO_REV(6, 1, 8, ANY_ID), rev))
val = a618_get_speed_bin(fuse);
if (val == UINT_MAX) {
@@ -1684,14 +1720,13 @@ static u32 fuse_to_supp_hw(struct device *dev, u32 revn, u32 fuse)
return (1 << val);
}
-static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu *a6xx_gpu,
- u32 revn)
+static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev)
{
u32 supp_hw = UINT_MAX;
- u16 speedbin;
+ u32 speedbin;
int ret;
- ret = nvmem_cell_read_u16(dev, "speed_bin", &speedbin);
+ ret = nvmem_cell_read_variable_le_u32(dev, "speed_bin", &speedbin);
/*
* -ENOENT means that the platform doesn't support speedbin which is
* fine
@@ -1704,9 +1739,8 @@ static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu *a6xx_gpu,
ret);
goto done;
}
- speedbin = le16_to_cpu(speedbin);
- supp_hw = fuse_to_supp_hw(dev, revn, speedbin);
+ supp_hw = fuse_to_supp_hw(dev, rev, speedbin);
done:
ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1);
@@ -1772,12 +1806,13 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
*/
info = adreno_info(config->rev);
- if (info && (info->revn == 650 || info->revn == 660))
+ if (info && (info->revn == 650 || info->revn == 660 ||
+ adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), info->rev)))
adreno_gpu->base.hw_apriv = true;
a6xx_llc_slices_init(pdev, a6xx_gpu);
- ret = a6xx_set_supported_hw(&pdev->dev, a6xx_gpu, info->revn);
+ ret = a6xx_set_supported_hw(&pdev->dev, config->rev);
if (ret) {
a6xx_destroy(&(a6xx_gpu->base.base));
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index ad4ea0ed5d99..e8f65cd8eca6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -112,7 +112,7 @@ static void *state_kmemdup(struct a6xx_gpu_state *a6xx_state, void *src,
static int a6xx_crashdumper_init(struct msm_gpu *gpu,
struct a6xx_crashdumper *dumper)
{
- dumper->ptr = msm_gem_kernel_new_locked(gpu->dev,
+ dumper->ptr = msm_gem_kernel_new(gpu->dev,
SZ_1M, MSM_BO_WC, gpu->aspace,
&dumper->bo, &dumper->iova);
@@ -961,7 +961,7 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)
a6xx_get_clusters(gpu, a6xx_state, dumper);
a6xx_get_dbgahb_clusters(gpu, a6xx_state, dumper);
- msm_gem_kernel_put(dumper->bo, gpu->aspace, true);
+ msm_gem_kernel_put(dumper->bo, gpu->aspace);
}
if (snapshot_debugbus)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index 919433732b43..d4c65bf0a1b7 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -382,6 +382,36 @@ static void a660_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
msg->cnoc_cmds_data[1][0] = 0x60000001;
}
+static void adreno_7c3_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
+{
+ /*
+ * Send a single "off" entry just to get things running
+ * TODO: bus scaling
+ */
+ msg->bw_level_num = 1;
+
+ msg->ddr_cmds_num = 3;
+ msg->ddr_wait_bitmask = 0x07;
+
+ msg->ddr_cmds_addrs[0] = 0x50004;
+ msg->ddr_cmds_addrs[1] = 0x50000;
+ msg->ddr_cmds_addrs[2] = 0x50088;
+
+ msg->ddr_cmds_data[0][0] = 0x40000000;
+ msg->ddr_cmds_data[0][1] = 0x40000000;
+ msg->ddr_cmds_data[0][2] = 0x40000000;
+
+ /*
+ * These are the CX (CNOC) votes - these are used by the GMU but the
+ * votes are known and fixed for the target
+ */
+ msg->cnoc_cmds_num = 1;
+ msg->cnoc_wait_bitmask = 0x01;
+
+ msg->cnoc_cmds_addrs[0] = 0x5006c;
+ msg->cnoc_cmds_data[0][0] = 0x40000000;
+ msg->cnoc_cmds_data[1][0] = 0x60000001;
+}
static void a6xx_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
{
/* Send a single "off" entry since the 630 GMU doesn't do bus scaling */
@@ -428,10 +458,12 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
if (adreno_is_a618(adreno_gpu))
a618_build_bw_table(&msg);
- else if (adreno_is_a640(adreno_gpu))
+ else if (adreno_is_a640_family(adreno_gpu))
a640_build_bw_table(&msg);
else if (adreno_is_a650(adreno_gpu))
a650_build_bw_table(&msg);
+ else if (adreno_is_7c3(adreno_gpu))
+ adreno_7c3_build_bw_table(&msg);
else if (adreno_is_a660(adreno_gpu))
a660_build_bw_table(&msg);
else
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 6dad8015c9a1..2a6ce76656aa 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -8,8 +8,6 @@
#include "adreno_gpu.h"
-#define ANY_ID 0xff
-
bool hang_debug = false;
MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
module_param_named(hang_debug, hang_debug, bool, 0600);
@@ -300,6 +298,30 @@ static const struct adreno_info gpulist[] = {
.init = a6xx_gpu_init,
.zapfw = "a660_zap.mdt",
.hwcg = a660_hwcg,
+ }, {
+ .rev = ADRENO_REV(6, 3, 5, ANY_ID),
+ .name = "Adreno 7c Gen 3",
+ .fw = {
+ [ADRENO_FW_SQE] = "a660_sqe.fw",
+ [ADRENO_FW_GMU] = "a660_gmu.bin",
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a6xx_gpu_init,
+ .hwcg = a660_hwcg,
+ }, {
+ .rev = ADRENO_REV(6, 8, 0, ANY_ID),
+ .revn = 680,
+ .name = "A680",
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ [ADRENO_FW_GMU] = "a640_gmu.bin",
+ },
+ .gmem = SZ_2M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a6xx_gpu_init,
+ .zapfw = "a640_zap.mdt",
+ .hwcg = a640_hwcg,
},
};
@@ -325,6 +347,15 @@ static inline bool _rev_match(uint8_t entry, uint8_t id)
return (entry == ANY_ID) || (entry == id);
}
+bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2)
+{
+
+ return _rev_match(rev1.core, rev2.core) &&
+ _rev_match(rev1.major, rev2.major) &&
+ _rev_match(rev1.minor, rev2.minor) &&
+ _rev_match(rev1.patchid, rev2.patchid);
+}
+
const struct adreno_info *adreno_info(struct adreno_rev rev)
{
int i;
@@ -332,10 +363,7 @@ const struct adreno_info *adreno_info(struct adreno_rev rev)
/* identify gpu: */
for (i = 0; i < ARRAY_SIZE(gpulist); i++) {
const struct adreno_info *info = &gpulist[i];
- if (_rev_match(info->rev.core, rev.core) &&
- _rev_match(info->rev.major, rev.major) &&
- _rev_match(info->rev.minor, rev.minor) &&
- _rev_match(info->rev.patchid, rev.patchid))
+ if (adreno_cmp_rev(info->rev, rev))
return info;
}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 9f5a30234b33..748665232d29 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -261,8 +261,8 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
return ret;
}
return -EINVAL;
- case MSM_PARAM_NR_RINGS:
- *value = gpu->nr_rings;
+ case MSM_PARAM_PRIORITIES:
+ *value = gpu->nr_rings * NR_SCHED_PRIORITIES;
return 0;
case MSM_PARAM_PP_PGTABLE:
*value = 0;
@@ -390,7 +390,7 @@ struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu,
struct drm_gem_object *bo;
void *ptr;
- ptr = msm_gem_kernel_new_locked(gpu->dev, fw->size - 4,
+ ptr = msm_gem_kernel_new(gpu->dev, fw->size - 4,
MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace, &bo, iova);
if (IS_ERR(ptr))
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 8dbe0d157520..225c277a6223 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -42,6 +42,8 @@ struct adreno_rev {
uint8_t patchid;
};
+#define ANY_ID 0xff
+
#define ADRENO_REV(core, major, minor, patchid) \
((struct adreno_rev){ core, major, minor, patchid })
@@ -141,6 +143,8 @@ struct adreno_platform_config {
__ret; \
})
+bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2);
+
static inline bool adreno_is_a2xx(struct adreno_gpu *gpu)
{
return (gpu->revn < 300);
@@ -237,9 +241,9 @@ static inline int adreno_is_a630(struct adreno_gpu *gpu)
return gpu->revn == 630;
}
-static inline int adreno_is_a640(struct adreno_gpu *gpu)
+static inline int adreno_is_a640_family(struct adreno_gpu *gpu)
{
- return gpu->revn == 640;
+ return (gpu->revn == 640) || (gpu->revn == 680);
}
static inline int adreno_is_a650(struct adreno_gpu *gpu)
@@ -247,15 +251,27 @@ static inline int adreno_is_a650(struct adreno_gpu *gpu)
return gpu->revn == 650;
}
+static inline int adreno_is_7c3(struct adreno_gpu *gpu)
+{
+ /* The order of args is important here to handle ANY_ID correctly */
+ return adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), gpu->rev);
+}
+
static inline int adreno_is_a660(struct adreno_gpu *gpu)
{
return gpu->revn == 660;
}
+static inline int adreno_is_a660_family(struct adreno_gpu *gpu)
+{
+ return adreno_is_a660(gpu) || adreno_is_7c3(gpu);
+}
+
/* check for a650, a660, or any derivatives */
static inline int adreno_is_a650_family(struct adreno_gpu *gpu)
{
- return gpu->revn == 650 || gpu->revn == 620 || gpu->revn == 660;
+ return gpu->revn == 650 || gpu->revn == 620 ||
+ adreno_is_a660_family(gpu);
}
int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 9a5c70c87cc8..768012243b44 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -30,12 +30,6 @@
#include "dpu_core_perf.h"
#include "dpu_trace.h"
-#define DPU_DRM_BLEND_OP_NOT_DEFINED 0
-#define DPU_DRM_BLEND_OP_OPAQUE 1
-#define DPU_DRM_BLEND_OP_PREMULTIPLIED 2
-#define DPU_DRM_BLEND_OP_COVERAGE 3
-#define DPU_DRM_BLEND_OP_MAX 4
-
/* layer mixer index on dpu_crtc */
#define LEFT_MIXER 0
#define RIGHT_MIXER 1
@@ -146,20 +140,43 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer,
{
struct dpu_hw_mixer *lm = mixer->hw_lm;
uint32_t blend_op;
+ uint32_t fg_alpha, bg_alpha;
- /* default to opaque blending */
- blend_op = DPU_BLEND_FG_ALPHA_FG_CONST |
- DPU_BLEND_BG_ALPHA_BG_CONST;
+ fg_alpha = pstate->base.alpha >> 8;
+ bg_alpha = 0xff - fg_alpha;
- if (format->alpha_enable) {
+ /* default to opaque blending */
+ if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE ||
+ !format->alpha_enable) {
+ blend_op = DPU_BLEND_FG_ALPHA_FG_CONST |
+ DPU_BLEND_BG_ALPHA_BG_CONST;
+ } else if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) {
+ blend_op = DPU_BLEND_FG_ALPHA_FG_CONST |
+ DPU_BLEND_BG_ALPHA_FG_PIXEL;
+ if (fg_alpha != 0xff) {
+ bg_alpha = fg_alpha;
+ blend_op |= DPU_BLEND_BG_MOD_ALPHA |
+ DPU_BLEND_BG_INV_MOD_ALPHA;
+ } else {
+ blend_op |= DPU_BLEND_BG_INV_ALPHA;
+ }
+ } else {
/* coverage blending */
blend_op = DPU_BLEND_FG_ALPHA_FG_PIXEL |
- DPU_BLEND_BG_ALPHA_FG_PIXEL |
- DPU_BLEND_BG_INV_ALPHA;
+ DPU_BLEND_BG_ALPHA_FG_PIXEL;
+ if (fg_alpha != 0xff) {
+ bg_alpha = fg_alpha;
+ blend_op |= DPU_BLEND_FG_MOD_ALPHA |
+ DPU_BLEND_FG_INV_MOD_ALPHA |
+ DPU_BLEND_BG_MOD_ALPHA |
+ DPU_BLEND_BG_INV_MOD_ALPHA;
+ } else {
+ blend_op |= DPU_BLEND_BG_INV_ALPHA;
+ }
}
lm->ops.setup_blend_config(lm, pstate->stage,
- 0xFF, 0, blend_op);
+ fg_alpha, bg_alpha, blend_op);
DRM_DEBUG_ATOMIC("format:%p4cc, alpha_en:%u blend_op:0x%x\n",
&format->base.pixel_format, format->alpha_enable, blend_op);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1c04b7cce43e..0e9d3fa1544b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -274,20 +274,20 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
/* return EWOULDBLOCK since we know the wait isn't necessary */
if (phys_enc->enable_state == DPU_ENC_DISABLED) {
- DRM_ERROR("encoder is disabled id=%u, intr=%d, irq=%d",
+ DRM_ERROR("encoder is disabled id=%u, intr=%d, irq=%d\n",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx);
return -EWOULDBLOCK;
}
if (irq->irq_idx < 0) {
- DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d, irq=%s",
+ DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d, irq=%s\n",
DRMID(phys_enc->parent), intr_idx,
irq->name);
return 0;
}
- DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d",
+ DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d\n",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx, phys_enc->hw_pp->idx - PINGPONG_0,
atomic_read(wait_info->atomic_cnt));
@@ -303,8 +303,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
if (irq_status) {
unsigned long flags;
- DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, "
- "irq=%d, pp=%d, atomic_cnt=%d",
+ DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx,
phys_enc->hw_pp->idx - PINGPONG_0,
@@ -315,8 +314,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
ret = 0;
} else {
ret = -ETIMEDOUT;
- DRM_DEBUG_KMS("irq timeout id=%u, intr=%d, "
- "irq=%d, pp=%d, atomic_cnt=%d",
+ DRM_DEBUG_KMS("irq timeout id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx,
phys_enc->hw_pp->idx - PINGPONG_0,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 704dace895cb..b131fd376192 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -974,6 +974,7 @@ static const struct dpu_perf_cfg sdm845_perf_data = {
.amortizable_threshold = 25,
.min_prefill_lines = 24,
.danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfff0, 0xf000, 0xffff},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(sdm845_qos_linear),
.entries = sdm845_qos_linear
@@ -1001,6 +1002,7 @@ static const struct dpu_perf_cfg sc7180_perf_data = {
.min_dram_ib = 1600000,
.min_prefill_lines = 24,
.danger_lut_tbl = {0xff, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfff0, 0xff00, 0xffff},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(sc7180_qos_linear),
.entries = sc7180_qos_linear
@@ -1028,6 +1030,7 @@ static const struct dpu_perf_cfg sm8150_perf_data = {
.min_dram_ib = 800000,
.min_prefill_lines = 24,
.danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfff8, 0xf000, 0xffff},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(sm8150_qos_linear),
.entries = sm8150_qos_linear
@@ -1056,6 +1059,7 @@ static const struct dpu_perf_cfg sm8250_perf_data = {
.min_dram_ib = 800000,
.min_prefill_lines = 35,
.danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfff0, 0xff00, 0xffff},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(sc7180_qos_linear),
.entries = sc7180_qos_linear
@@ -1084,6 +1088,7 @@ static const struct dpu_perf_cfg sc7280_perf_data = {
.min_dram_ib = 1600000,
.min_prefill_lines = 24,
.danger_lut_tbl = {0xffff, 0xffff, 0x0},
+ .safe_lut_tbl = {0xff00, 0xff00, 0xffff},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(sc7180_qos_macrotile),
.entries = sc7180_qos_macrotile
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index f8a74f6cdc4c..64740ddb983e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -345,10 +345,12 @@ static void dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl *ctx)
int i;
for (i = 0; i < ctx->mixer_count; i++) {
- DPU_REG_WRITE(c, CTL_LAYER(LM_0 + i), 0);
- DPU_REG_WRITE(c, CTL_LAYER_EXT(LM_0 + i), 0);
- DPU_REG_WRITE(c, CTL_LAYER_EXT2(LM_0 + i), 0);
- DPU_REG_WRITE(c, CTL_LAYER_EXT3(LM_0 + i), 0);
+ enum dpu_lm mixer_id = ctx->mixer_hw_caps[i].id;
+
+ DPU_REG_WRITE(c, CTL_LAYER(mixer_id), 0);
+ DPU_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);
+ DPU_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);
+ DPU_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);
}
DPU_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 4fd913522931..ae48f41821cf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -471,30 +471,68 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
struct dpu_kms *dpu_kms)
{
struct drm_encoder *encoder = NULL;
+ struct msm_display_info info;
int i, rc = 0;
if (!(priv->dsi[0] || priv->dsi[1]))
return rc;
- /*TODO: Support two independent DSI connectors */
- encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
- if (IS_ERR(encoder)) {
- DPU_ERROR("encoder init failed for dsi display\n");
- return PTR_ERR(encoder);
- }
-
- priv->encoders[priv->num_encoders++] = encoder;
-
+ /*
+ * We support following confiurations:
+ * - Single DSI host (dsi0 or dsi1)
+ * - Two independent DSI hosts
+ * - Bonded DSI0 and DSI1 hosts
+ *
+ * TODO: Support swapping DSI0 and DSI1 in the bonded setup.
+ */
for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
+ int other = (i + 1) % 2;
+
if (!priv->dsi[i])
continue;
+ if (msm_dsi_is_bonded_dsi(priv->dsi[i]) &&
+ !msm_dsi_is_master_dsi(priv->dsi[i]))
+ continue;
+
+ encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
+ if (IS_ERR(encoder)) {
+ DPU_ERROR("encoder init failed for dsi display\n");
+ return PTR_ERR(encoder);
+ }
+
+ priv->encoders[priv->num_encoders++] = encoder;
+
+ memset(&info, 0, sizeof(info));
+ info.intf_type = encoder->encoder_type;
+
rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n",
i, rc);
break;
}
+
+ info.h_tile_instance[info.num_of_h_tiles++] = i;
+ info.capabilities = msm_dsi_is_cmd_mode(priv->dsi[i]) ?
+ MSM_DISPLAY_CAP_CMD_MODE :
+ MSM_DISPLAY_CAP_VID_MODE;
+
+ if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) {
+ rc = msm_dsi_modeset_init(priv->dsi[other], dev, encoder);
+ if (rc) {
+ DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n",
+ other, rc);
+ break;
+ }
+
+ info.h_tile_instance[info.num_of_h_tiles++] = other;
+ }
+
+ rc = dpu_encoder_setup(dev, encoder, &info);
+ if (rc)
+ DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n",
+ encoder->base.id, rc);
}
return rc;
@@ -505,6 +543,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev,
struct dpu_kms *dpu_kms)
{
struct drm_encoder *encoder = NULL;
+ struct msm_display_info info;
int rc = 0;
if (!priv->dp)
@@ -516,6 +555,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev,
return PTR_ERR(encoder);
}
+ memset(&info, 0, sizeof(info));
rc = msm_dp_modeset_init(priv->dp, dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
@@ -524,6 +564,14 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev,
}
priv->encoders[priv->num_encoders++] = encoder;
+
+ info.num_of_h_tiles = 1;
+ info.capabilities = MSM_DISPLAY_CAP_VID_MODE;
+ info.intf_type = encoder->encoder_type;
+ rc = dpu_encoder_setup(dev, encoder, &info);
+ if (rc)
+ DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n",
+ encoder->base.id, rc);
return rc;
}
@@ -726,41 +774,6 @@ static void dpu_kms_destroy(struct msm_kms *kms)
msm_kms_destroy(&dpu_kms->base);
}
-static void _dpu_kms_set_encoder_mode(struct msm_kms *kms,
- struct drm_encoder *encoder,
- bool cmd_mode)
-{
- struct msm_display_info info;
- struct msm_drm_private *priv = encoder->dev->dev_private;
- int i, rc = 0;
-
- memset(&info, 0, sizeof(info));
-
- info.intf_type = encoder->encoder_type;
- info.capabilities = cmd_mode ? MSM_DISPLAY_CAP_CMD_MODE :
- MSM_DISPLAY_CAP_VID_MODE;
-
- switch (info.intf_type) {
- case DRM_MODE_ENCODER_DSI:
- /* TODO: No support for DSI swap */
- for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
- if (priv->dsi[i]) {
- info.h_tile_instance[info.num_of_h_tiles] = i;
- info.num_of_h_tiles++;
- }
- }
- break;
- case DRM_MODE_ENCODER_TMDS:
- info.num_of_h_tiles = 1;
- break;
- }
-
- rc = dpu_encoder_setup(encoder->dev, encoder, &info);
- if (rc)
- DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n",
- encoder->base.id, rc);
-}
-
static irqreturn_t dpu_irq(struct msm_kms *kms)
{
struct dpu_kms *dpu_kms = to_dpu_kms(kms);
@@ -863,7 +876,6 @@ static const struct msm_kms_funcs kms_funcs = {
.get_format = dpu_get_msm_format,
.round_pixclk = dpu_kms_round_pixclk,
.destroy = dpu_kms_destroy,
- .set_encoder_mode = _dpu_kms_set_encoder_mode,
.snapshot = dpu_kms_mdp_snapshot,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = dpu_kms_debugfs_init,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index ec4a6f04394a..c989621209aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1339,9 +1339,7 @@ static void dpu_plane_reset(struct drm_plane *plane)
return;
}
- pstate->base.plane = plane;
-
- plane->state = &pstate->base;
+ __drm_atomic_helper_plane_reset(plane, &pstate->base);
}
#ifdef CONFIG_DEBUG_FS
@@ -1647,6 +1645,12 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
if (ret)
DPU_ERROR("failed to install zpos property, rc = %d\n", ret);
+ drm_plane_create_alpha_property(plane);
+ drm_plane_create_blend_mode_property(plane,
+ BIT(DRM_MODE_BLEND_PIXEL_NONE) |
+ BIT(DRM_MODE_BLEND_PREMULTI) |
+ BIT(DRM_MODE_BLEND_COVERAGE));
+
drm_plane_create_rotation_property(plane,
DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 |
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index 4a5b518288b0..cdcaf470f148 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -19,30 +19,12 @@ static int mdp4_hw_init(struct msm_kms *kms)
{
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
struct drm_device *dev = mdp4_kms->dev;
- uint32_t version, major, minor, dmap_cfg, vg_cfg;
+ u32 dmap_cfg, vg_cfg;
unsigned long clk;
int ret = 0;
pm_runtime_get_sync(dev->dev);
- mdp4_enable(mdp4_kms);
- version = mdp4_read(mdp4_kms, REG_MDP4_VERSION);
- mdp4_disable(mdp4_kms);
-
- major = FIELD(version, MDP4_VERSION_MAJOR);
- minor = FIELD(version, MDP4_VERSION_MINOR);
-
- DBG("found MDP4 version v%d.%d", major, minor);
-
- if (major != 4) {
- DRM_DEV_ERROR(dev->dev, "unexpected MDP version: v%d.%d\n",
- major, minor);
- ret = -ENXIO;
- goto out;
- }
-
- mdp4_kms->rev = minor;
-
if (mdp4_kms->rev > 1) {
mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER0, 0x0707ffff);
mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER1, 0x03073f3f);
@@ -88,7 +70,6 @@ static int mdp4_hw_init(struct msm_kms *kms)
if (mdp4_kms->rev > 1)
mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1);
-out:
pm_runtime_put_sync(dev->dev);
return ret;
@@ -108,13 +89,6 @@ static void mdp4_disable_commit(struct msm_kms *kms)
static void mdp4_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
{
- int i;
- struct drm_crtc *crtc;
- struct drm_crtc_state *crtc_state;
-
- /* see 119ecb7fd */
- for_each_new_crtc_in_state(state, crtc, crtc_state, i)
- drm_crtc_vblank_get(crtc);
}
static void mdp4_flush_commit(struct msm_kms *kms, unsigned crtc_mask)
@@ -133,12 +107,6 @@ static void mdp4_wait_flush(struct msm_kms *kms, unsigned crtc_mask)
static void mdp4_complete_commit(struct msm_kms *kms, unsigned crtc_mask)
{
- struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
- struct drm_crtc *crtc;
-
- /* see 119ecb7fd */
- for_each_crtc_mask(mdp4_kms->dev, crtc, crtc_mask)
- drm_crtc_vblank_put(crtc);
}
static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
@@ -411,14 +379,32 @@ fail:
return ret;
}
+static void read_mdp_hw_revision(struct mdp4_kms *mdp4_kms,
+ u32 *major, u32 *minor)
+{
+ struct drm_device *dev = mdp4_kms->dev;
+ u32 version;
+
+ mdp4_enable(mdp4_kms);
+ version = mdp4_read(mdp4_kms, REG_MDP4_VERSION);
+ mdp4_disable(mdp4_kms);
+
+ *major = FIELD(version, MDP4_VERSION_MAJOR);
+ *minor = FIELD(version, MDP4_VERSION_MINOR);
+
+ DRM_DEV_INFO(dev->dev, "MDP4 version v%d.%d", *major, *minor);
+}
+
struct msm_kms *mdp4_kms_init(struct drm_device *dev)
{
struct platform_device *pdev = to_platform_device(dev->dev);
struct mdp4_platform_config *config = mdp4_get_config(pdev);
+ struct msm_drm_private *priv = dev->dev_private;
struct mdp4_kms *mdp4_kms;
struct msm_kms *kms = NULL;
struct msm_gem_address_space *aspace;
int irq, ret;
+ u32 major, minor;
mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
if (!mdp4_kms) {
@@ -433,7 +419,8 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
goto fail;
}
- kms = &mdp4_kms->base.base;
+ priv->kms = &mdp4_kms->base.base;
+ kms = priv->kms;
mdp4_kms->dev = dev;
@@ -479,15 +466,6 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
if (IS_ERR(mdp4_kms->pclk))
mdp4_kms->pclk = NULL;
- if (mdp4_kms->rev >= 2) {
- mdp4_kms->lut_clk = devm_clk_get(&pdev->dev, "lut_clk");
- if (IS_ERR(mdp4_kms->lut_clk)) {
- DRM_DEV_ERROR(dev->dev, "failed to get lut_clk\n");
- ret = PTR_ERR(mdp4_kms->lut_clk);
- goto fail;
- }
- }
-
mdp4_kms->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(mdp4_kms->axi_clk)) {
DRM_DEV_ERROR(dev->dev, "failed to get axi_clk\n");
@@ -496,8 +474,27 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
}
clk_set_rate(mdp4_kms->clk, config->max_clk);
- if (mdp4_kms->lut_clk)
+
+ read_mdp_hw_revision(mdp4_kms, &major, &minor);
+
+ if (major != 4) {
+ DRM_DEV_ERROR(dev->dev, "unexpected MDP version: v%d.%d\n",
+ major, minor);
+ ret = -ENXIO;
+ goto fail;
+ }
+
+ mdp4_kms->rev = minor;
+
+ if (mdp4_kms->rev >= 2) {
+ mdp4_kms->lut_clk = devm_clk_get(&pdev->dev, "lut_clk");
+ if (IS_ERR(mdp4_kms->lut_clk)) {
+ DRM_DEV_ERROR(dev->dev, "failed to get lut_clk\n");
+ ret = PTR_ERR(mdp4_kms->lut_clk);
+ goto fail;
+ }
clk_set_rate(mdp4_kms->lut_clk, config->max_clk);
+ }
pm_runtime_enable(dev->dev);
mdp4_kms->rpm_enabled = true;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
index 81b0c7cf954e..1220f2b20e05 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
@@ -737,7 +737,7 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
}
/*
- * In Dual DSI case, CTL0 and CTL1 are always assigned to two DSI
+ * In bonded DSI case, CTL0 and CTL1 are always assigned to two DSI
* interfaces to support single FLUSH feature (Flush CTL0 and CTL1 when
* only write into CTL0's FLUSH register) to keep two DSI pipes in sync.
* Single FLUSH is supported from hw rev v3.0.
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 15aed45022bc..b3b42672b2d4 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -209,13 +209,6 @@ static int mdp5_set_split_display(struct msm_kms *kms,
slave_encoder);
}
-static void mdp5_set_encoder_mode(struct msm_kms *kms,
- struct drm_encoder *encoder,
- bool cmd_mode)
-{
- mdp5_encoder_set_intf_mode(encoder, cmd_mode);
-}
-
static void mdp5_kms_destroy(struct msm_kms *kms)
{
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
@@ -287,7 +280,6 @@ static const struct mdp_kms_funcs kms_funcs = {
.get_format = mdp_get_format,
.round_pixclk = mdp5_round_pixclk,
.set_split_display = mdp5_set_split_display,
- .set_encoder_mode = mdp5_set_encoder_mode,
.destroy = mdp5_kms_destroy,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = mdp5_kms_debugfs_init,
@@ -448,6 +440,9 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms,
}
ret = msm_dsi_modeset_init(priv->dsi[dsi_id], dev, encoder);
+ if (!ret)
+ mdp5_encoder_set_intf_mode(encoder, msm_dsi_is_cmd_mode(priv->dsi[dsi_id]));
+
break;
}
default:
diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.h b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.h
index c92a9508c8d3..4c619307612c 100644
--- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.h
+++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.h
@@ -16,7 +16,6 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/ktime.h>
-#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/dma-buf.h>
#include <linux/slab.h>
@@ -25,7 +24,6 @@
#include <linux/pm_runtime.h>
#include <linux/kthread.h>
#include <linux/devcoredump.h>
-#include <stdarg.h>
#include "msm_kms.h"
#define MSM_DISP_SNAPSHOT_MAX_BLKS 10
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 4a3293b590b0..eb40d8413bca 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -353,6 +353,9 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
if (!(aux->retry_cnt % MAX_AUX_RETRIES))
dp_catalog_aux_update_cfg(aux->catalog);
}
+ /* reset aux if link is in connected state */
+ if (dp_catalog_link_is_connected(aux->catalog))
+ dp_catalog_aux_reset(aux->catalog);
} else {
aux->retry_cnt = 0;
switch (aux->aux_error_num) {
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index c0423e76eed7..cc2bb8295329 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -372,6 +372,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
struct dp_catalog_private *catalog = container_of(dp_catalog,
struct dp_catalog_private, dp_catalog);
+ DRM_DEBUG_DP("enable=%d\n", enable);
if (enable) {
/*
* To make sure link reg writes happens before other operation,
@@ -580,6 +581,7 @@ void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog,
config = (en ? config | intr_mask : config & ~intr_mask);
+ DRM_DEBUG_DP("intr_mask=%#x config=%#x\n", intr_mask, config);
dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK,
config & DP_DP_HPD_INT_MASK);
}
@@ -610,6 +612,7 @@ u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
u32 status;
status = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
+ DRM_DEBUG_DP("aux status: %#x\n", status);
status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT;
status &= DP_DP_HPD_STATE_STATUS_BITS_MASK;
@@ -685,6 +688,7 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog,
/* Make sure to clear the current pattern before starting a new one */
dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0);
+ DRM_DEBUG_DP("pattern: %#x\n", pattern);
switch (pattern) {
case DP_PHY_TEST_PATTERN_D10_2:
dp_write_link(catalog, REG_DP_STATE_CTRL,
@@ -745,7 +749,7 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog,
DP_STATE_CTRL_LINK_TRAINING_PATTERN4);
break;
default:
- DRM_DEBUG_DP("No valid test pattern requested:0x%x\n", pattern);
+ DRM_DEBUG_DP("No valid test pattern requested: %#x\n", pattern);
break;
}
}
@@ -929,7 +933,7 @@ void dp_catalog_audio_config_acr(struct dp_catalog *dp_catalog)
select = dp_catalog->audio_data;
acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14);
- DRM_DEBUG_DP("select = 0x%x, acr_ctrl = 0x%x\n", select, acr_ctrl);
+ DRM_DEBUG_DP("select: %#x, acr_ctrl: %#x\n", select, acr_ctrl);
dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl);
}
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index eaddfd739885..62e75dc8afc6 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -81,13 +81,6 @@ struct dp_ctrl_private {
struct completion video_comp;
};
-struct dp_cr_status {
- u8 lane_0_1;
- u8 lane_2_3;
-};
-
-#define DP_LANE0_1_CR_DONE 0x11
-
static int dp_aux_link_configure(struct drm_dp_aux *aux,
struct dp_link_info *link)
{
@@ -120,7 +113,7 @@ void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl)
IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES))
pr_warn("PUSH_IDLE pattern timedout\n");
- pr_debug("mainlink off done\n");
+ DRM_DEBUG_DP("mainlink off done\n");
}
static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
@@ -1011,6 +1004,8 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)
u32 voltage_swing_level = link->phy_params.v_level;
u32 pre_emphasis_level = link->phy_params.p_level;
+ DRM_DEBUG_DP("voltage level: %d emphasis level: %d\n", voltage_swing_level,
+ pre_emphasis_level);
ret = dp_catalog_ctrl_update_vx_px(ctrl->catalog,
voltage_swing_level, pre_emphasis_level);
@@ -1078,7 +1073,7 @@ static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl,
}
static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
- struct dp_cr_status *cr, int *training_step)
+ int *training_step)
{
int tries, old_v_level, ret = 0;
u8 link_status[DP_LINK_STATUS_SIZE];
@@ -1107,9 +1102,6 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
if (ret)
return ret;
- cr->lane_0_1 = link_status[0];
- cr->lane_2_3 = link_status[1];
-
if (drm_dp_clock_recovery_ok(link_status,
ctrl->link->link_params.num_lanes)) {
return 0;
@@ -1186,7 +1178,7 @@ static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl)
}
static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
- struct dp_cr_status *cr, int *training_step)
+ int *training_step)
{
int tries = 0, ret = 0;
char pattern;
@@ -1202,10 +1194,6 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
else
pattern = DP_TRAINING_PATTERN_2;
- ret = dp_ctrl_update_vx_px(ctrl);
- if (ret)
- return ret;
-
ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, pattern);
if (ret)
return ret;
@@ -1218,8 +1206,6 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
ret = dp_ctrl_read_link_status(ctrl, link_status);
if (ret)
return ret;
- cr->lane_0_1 = link_status[0];
- cr->lane_2_3 = link_status[1];
if (drm_dp_channel_eq_ok(link_status,
ctrl->link->link_params.num_lanes)) {
@@ -1239,7 +1225,7 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl);
static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
- struct dp_cr_status *cr, int *training_step)
+ int *training_step)
{
int ret = 0;
u8 encoding = DP_SET_ANSI_8B10B;
@@ -1255,7 +1241,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
drm_dp_dpcd_write(ctrl->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
&encoding, 1);
- ret = dp_ctrl_link_train_1(ctrl, cr, training_step);
+ ret = dp_ctrl_link_train_1(ctrl, training_step);
if (ret) {
DRM_ERROR("link training #1 failed. ret=%d\n", ret);
goto end;
@@ -1264,7 +1250,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
/* print success info as this is a result of user initiated action */
DRM_DEBUG_DP("link training #1 successful\n");
- ret = dp_ctrl_link_train_2(ctrl, cr, training_step);
+ ret = dp_ctrl_link_train_2(ctrl, training_step);
if (ret) {
DRM_ERROR("link training #2 failed. ret=%d\n", ret);
goto end;
@@ -1280,7 +1266,7 @@ end:
}
static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl,
- struct dp_cr_status *cr, int *training_step)
+ int *training_step)
{
int ret = 0;
@@ -1295,7 +1281,7 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl,
* a link training pattern, we have to first do soft reset.
*/
- ret = dp_ctrl_link_train(ctrl, cr, training_step);
+ ret = dp_ctrl_link_train(ctrl, training_step);
return ret;
}
@@ -1382,6 +1368,7 @@ int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset)
if (reset)
dp_catalog_ctrl_reset(ctrl->catalog);
+ DRM_DEBUG_DP("flip=%d\n", flip);
dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_init(phy);
dp_catalog_ctrl_enable_irq(ctrl->catalog, true);
@@ -1492,14 +1479,16 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl)
static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl)
{
int ret = 0;
- struct dp_cr_status cr;
int training_step = DP_TRAINING_NONE;
dp_ctrl_push_idle(&ctrl->dp_ctrl);
+ ctrl->link->phy_params.p_level = 0;
+ ctrl->link->phy_params.v_level = 0;
+
ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
- ret = dp_ctrl_setup_main_link(ctrl, &cr, &training_step);
+ ret = dp_ctrl_setup_main_link(ctrl, &training_step);
if (ret)
goto end;
@@ -1630,6 +1619,35 @@ void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl)
}
}
+static bool dp_ctrl_clock_recovery_any_ok(
+ const u8 link_status[DP_LINK_STATUS_SIZE],
+ int lane_count)
+{
+ int reduced_cnt;
+
+ if (lane_count <= 1)
+ return false;
+
+ /*
+ * only interested in the lane number after reduced
+ * lane_count = 4, then only interested in 2 lanes
+ * lane_count = 2, then only interested in 1 lane
+ */
+ reduced_cnt = lane_count >> 1;
+
+ return drm_dp_clock_recovery_ok(link_status, reduced_cnt);
+}
+
+static bool dp_ctrl_channel_eq_ok(struct dp_ctrl_private *ctrl)
+{
+ u8 link_status[DP_LINK_STATUS_SIZE];
+ int num_lanes = ctrl->link->link_params.num_lanes;
+
+ dp_ctrl_read_link_status(ctrl, link_status);
+
+ return drm_dp_channel_eq_ok(link_status, num_lanes);
+}
+
int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
{
int rc = 0;
@@ -1637,7 +1655,7 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
u32 rate = 0;
int link_train_max_retries = 5;
u32 const phy_cts_pixel_clk_khz = 148500;
- struct dp_cr_status cr;
+ u8 link_status[DP_LINK_STATUS_SIZE];
unsigned int training_step;
if (!dp_ctrl)
@@ -1664,6 +1682,9 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
ctrl->link->link_params.rate,
ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate);
+ ctrl->link->phy_params.p_level = 0;
+ ctrl->link->phy_params.v_level = 0;
+
rc = dp_ctrl_enable_mainlink_clocks(ctrl);
if (rc)
return rc;
@@ -1677,19 +1698,21 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
}
training_step = DP_TRAINING_NONE;
- rc = dp_ctrl_setup_main_link(ctrl, &cr, &training_step);
+ rc = dp_ctrl_setup_main_link(ctrl, &training_step);
if (rc == 0) {
/* training completed successfully */
break;
} else if (training_step == DP_TRAINING_1) {
/* link train_1 failed */
- if (!dp_catalog_link_is_connected(ctrl->catalog)) {
+ if (!dp_catalog_link_is_connected(ctrl->catalog))
break;
- }
+
+ dp_ctrl_read_link_status(ctrl, link_status);
rc = dp_ctrl_link_rate_down_shift(ctrl);
if (rc < 0) { /* already in RBR = 1.6G */
- if (cr.lane_0_1 & DP_LANE0_1_CR_DONE) {
+ if (dp_ctrl_clock_recovery_any_ok(link_status,
+ ctrl->link->link_params.num_lanes)) {
/*
* some lanes are ready,
* reduce lane number
@@ -1705,12 +1728,18 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
}
}
} else if (training_step == DP_TRAINING_2) {
- /* link train_2 failed, lower lane rate */
- if (!dp_catalog_link_is_connected(ctrl->catalog)) {
+ /* link train_2 failed */
+ if (!dp_catalog_link_is_connected(ctrl->catalog))
break;
- }
- rc = dp_ctrl_link_lane_down_shift(ctrl);
+ dp_ctrl_read_link_status(ctrl, link_status);
+
+ if (!drm_dp_clock_recovery_ok(link_status,
+ ctrl->link->link_params.num_lanes))
+ rc = dp_ctrl_link_rate_down_shift(ctrl);
+ else
+ rc = dp_ctrl_link_lane_down_shift(ctrl);
+
if (rc < 0) {
/* end with failure */
break; /* lane == 1 already */
@@ -1721,17 +1750,19 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
return rc;
- /* stop txing train pattern */
- dp_ctrl_clear_training_pattern(ctrl);
+ if (rc == 0) { /* link train successfully */
+ /*
+ * do not stop train pattern here
+ * stop link training at on_stream
+ * to pass compliance test
+ */
+ } else {
+ /*
+ * link training failed
+ * end txing train pattern here
+ */
+ dp_ctrl_clear_training_pattern(ctrl);
- /*
- * keep transmitting idle pattern until video ready
- * to avoid main link from loss of sync
- */
- if (rc == 0) /* link train successfully */
- dp_ctrl_push_idle(dp_ctrl);
- else {
- /* link training failed */
dp_ctrl_deinitialize_mainlink(ctrl);
rc = -ECONNRESET;
}
@@ -1739,9 +1770,15 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
return rc;
}
+static int dp_ctrl_link_retrain(struct dp_ctrl_private *ctrl)
+{
+ int training_step = DP_TRAINING_NONE;
+
+ return dp_ctrl_setup_main_link(ctrl, &training_step);
+}
+
int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
{
- u32 rate = 0;
int ret = 0;
bool mainlink_ready = false;
struct dp_ctrl_private *ctrl;
@@ -1751,10 +1788,6 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
- rate = ctrl->panel->link_info.rate;
-
- ctrl->link->link_params.rate = rate;
- ctrl->link->link_params.num_lanes = ctrl->panel->link_info.num_lanes;
ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
DRM_DEBUG_DP("rate=%d, num_lanes=%d, pixel_rate=%d\n",
@@ -1769,6 +1802,12 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
}
}
+ if (!dp_ctrl_channel_eq_ok(ctrl))
+ dp_ctrl_link_retrain(ctrl);
+
+ /* stop txing train pattern to end link training */
+ dp_ctrl_clear_training_pattern(ctrl);
+
ret = dp_ctrl_enable_stream_clocks(ctrl);
if (ret) {
DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 867388a399ad..fbe4c2cd52a3 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -55,7 +55,6 @@ enum {
EV_HPD_INIT_SETUP,
EV_HPD_PLUG_INT,
EV_IRQ_HPD_INT,
- EV_HPD_REPLUG_INT,
EV_HPD_UNPLUG_INT,
EV_USER_NOTIFICATION,
EV_CONNECT_PENDING_TIMEOUT,
@@ -102,8 +101,6 @@ struct dp_display_private {
struct dp_display_mode dp_mode;
struct msm_dp dp_display;
- bool encoder_mode_set;
-
/* wait for audio signaling */
struct completion audio_comp;
@@ -268,6 +265,8 @@ static bool dp_display_is_ds_bridge(struct dp_panel *panel)
static bool dp_display_is_sink_count_zero(struct dp_display_private *dp)
{
+ DRM_DEBUG_DP("present=%#x sink_count=%d\n", dp->panel->dpcd[DP_DOWNSTREAMPORT_PRESENT],
+ dp->link->sink_count);
return dp_display_is_ds_bridge(dp->panel) &&
(dp->link->sink_count == 0);
}
@@ -284,20 +283,6 @@ static void dp_display_send_hpd_event(struct msm_dp *dp_display)
}
-static void dp_display_set_encoder_mode(struct dp_display_private *dp)
-{
- struct msm_drm_private *priv = dp->dp_display.drm_dev->dev_private;
- struct msm_kms *kms = priv->kms;
-
- if (!dp->encoder_mode_set && dp->dp_display.encoder &&
- kms->funcs->set_encoder_mode) {
- kms->funcs->set_encoder_mode(kms,
- dp->dp_display.encoder, false);
-
- dp->encoder_mode_set = true;
- }
-}
-
static int dp_display_send_hpd_notification(struct dp_display_private *dp,
bool hpd)
{
@@ -313,6 +298,7 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp,
dp->dp_display.is_connected = hpd;
+ DRM_DEBUG_DP("hpd=%d\n", hpd);
dp_display_send_hpd_event(&dp->dp_display);
return 0;
@@ -362,6 +348,7 @@ static void dp_display_host_init(struct dp_display_private *dp, int reset)
{
bool flip = false;
+ DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized);
if (dp->core_initialized) {
DRM_DEBUG_DP("DP core already initialized\n");
return;
@@ -370,8 +357,6 @@ static void dp_display_host_init(struct dp_display_private *dp, int reset)
if (dp->usbpd->orientation == ORIENTATION_CC2)
flip = true;
- dp_display_set_encoder_mode(dp);
-
dp_power_init(dp->power, flip);
dp_ctrl_host_init(dp->ctrl, flip, reset);
dp_aux_init(dp->aux);
@@ -466,8 +451,10 @@ static int dp_display_handle_irq_hpd(struct dp_display_private *dp)
{
u32 sink_request = dp->link->sink_request;
+ DRM_DEBUG_DP("%d\n", sink_request);
if (dp->hpd_state == ST_DISCONNECTED) {
if (sink_request & DP_LINK_STATUS_UPDATED) {
+ DRM_DEBUG_DP("Disconnected sink_request: %d\n", sink_request);
DRM_ERROR("Disconnected, no DP_LINK_STATUS_UPDATED\n");
return -EINVAL;
}
@@ -499,6 +486,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev)
rc = dp_link_process_request(dp->link);
if (!rc) {
sink_request = dp->link->sink_request;
+ DRM_DEBUG_DP("hpd_state=%d sink_request=%d\n", dp->hpd_state, sink_request);
if (sink_request & DS_PORT_STATUS_CHANGED)
rc = dp_display_handle_port_ststus_changed(dp);
else
@@ -521,6 +509,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
+ DRM_DEBUG_DP("hpd_state=%d\n", state);
if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) {
mutex_unlock(&dp->event_mutex);
return 0;
@@ -656,6 +645,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
/* start sentinel checking in case of missing uevent */
dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
+ DRM_DEBUG_DP("hpd_state=%d\n", state);
/* signal the disconnect event early to ensure proper teardown */
dp_display_handle_plugged_change(g_dp_display, false);
@@ -714,6 +704,7 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
if (ret == -ECONNRESET) { /* cable unplugged */
dp->core_initialized = false;
}
+ DRM_DEBUG_DP("hpd_state=%d\n", state);
mutex_unlock(&dp->event_mutex);
@@ -855,6 +846,7 @@ static int dp_display_enable(struct dp_display_private *dp, u32 data)
dp_display = g_dp_display;
+ DRM_DEBUG_DP("sink_count=%d\n", dp->link->sink_count);
if (dp_display->power_on) {
DRM_DEBUG_DP("Link already setup, return\n");
return 0;
@@ -916,6 +908,7 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data)
dp_display->power_on = false;
+ DRM_DEBUG_DP("sink count: %d\n", dp->link->sink_count);
return 0;
}
@@ -1015,10 +1008,8 @@ int dp_display_get_test_bpp(struct msm_dp *dp)
void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp)
{
struct dp_display_private *dp_display;
- struct drm_device *drm;
dp_display = container_of(dp, struct dp_display_private, dp_display);
- drm = dp->drm_dev;
/*
* if we are reading registers we need the link clocks to be on
@@ -1119,9 +1110,6 @@ static int hpd_event_thread(void *data)
case EV_IRQ_HPD_INT:
dp_irq_hpd_handle(dp_priv, todo->data);
break;
- case EV_HPD_REPLUG_INT:
- /* do nothing */
- break;
case EV_USER_NOTIFICATION:
dp_display_send_hpd_notification(dp_priv,
todo->data);
@@ -1163,12 +1151,11 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
hpd_isr_status = dp_catalog_hpd_get_intr_status(dp->catalog);
+ DRM_DEBUG_DP("hpd isr status=%#x\n", hpd_isr_status);
if (hpd_isr_status & 0x0F) {
/* hpd related interrupts */
- if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK ||
- hpd_isr_status & DP_DP_HPD_REPLUG_INT_MASK) {
+ if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK)
dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0);
- }
if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) {
/* stop sentinel connect pending checking */
@@ -1176,8 +1163,10 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
dp_add_event(dp, EV_IRQ_HPD_INT, 0, 0);
}
- if (hpd_isr_status & DP_DP_HPD_REPLUG_INT_MASK)
- dp_add_event(dp, EV_HPD_REPLUG_INT, 0, 0);
+ if (hpd_isr_status & DP_DP_HPD_REPLUG_INT_MASK) {
+ dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
+ dp_add_event(dp, EV_HPD_PLUG_INT, 0, 3);
+ }
if (hpd_isr_status & DP_DP_HPD_UNPLUG_INT_MASK)
dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
@@ -1286,12 +1275,15 @@ static int dp_pm_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct msm_dp *dp_display = platform_get_drvdata(pdev);
struct dp_display_private *dp;
- u32 status;
+ int sink_count = 0;
dp = container_of(dp_display, struct dp_display_private, dp_display);
mutex_lock(&dp->event_mutex);
+ DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n",
+ dp->core_initialized, dp_display->power_on);
+
/* start from disconnected state */
dp->hpd_state = ST_DISCONNECTED;
@@ -1300,14 +1292,25 @@ static int dp_pm_resume(struct device *dev)
dp_catalog_ctrl_hpd_config(dp->catalog);
- status = dp_catalog_link_is_connected(dp->catalog);
+ /*
+ * set sink to normal operation mode -- D0
+ * before dpcd read
+ */
+ dp_link_psm_config(dp->link, &dp->panel->link_info, false);
+
+ if (dp_catalog_link_is_connected(dp->catalog)) {
+ sink_count = drm_dp_read_sink_count(dp->aux);
+ if (sink_count < 0)
+ sink_count = 0;
+ }
+ dp->link->sink_count = sink_count;
/*
* can not declared display is connected unless
* HDMI cable is plugged in and sink_count of
* dongle become 1
*/
- if (status && dp->link->sink_count)
+ if (dp->link->sink_count)
dp->dp_display.is_connected = true;
else
dp->dp_display.is_connected = false;
@@ -1315,6 +1318,9 @@ static int dp_pm_resume(struct device *dev)
dp_display_handle_plugged_change(g_dp_display,
dp->dp_display.is_connected);
+ DRM_DEBUG_DP("After, sink_count=%d is_connected=%d core_inited=%d power_on=%d\n",
+ dp->link->sink_count, dp->dp_display.is_connected,
+ dp->core_initialized, dp_display->power_on);
mutex_unlock(&dp->event_mutex);
@@ -1331,6 +1337,9 @@ static int dp_pm_suspend(struct device *dev)
mutex_lock(&dp->event_mutex);
+ DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n",
+ dp->core_initialized, dp_display->power_on);
+
if (dp->core_initialized == true) {
/* mainlink enabled */
if (dp_power_clk_status(dp->power, DP_CTRL_PM))
@@ -1344,6 +1353,9 @@ static int dp_pm_suspend(struct device *dev)
/* host_init will be called at pm_resume */
dp->core_initialized = false;
+ DRM_DEBUG_DP("After, core_inited=%d power_on=%d\n",
+ dp->core_initialized, dp_display->power_on);
+
mutex_unlock(&dp->event_mutex);
return 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
index 1195044a7a3b..a5bdfc5029de 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.c
+++ b/drivers/gpu/drm/msm/dp/dp_link.c
@@ -1027,43 +1027,29 @@ int dp_link_process_request(struct dp_link *dp_link)
if (link->request.test_requested == DP_TEST_LINK_EDID_READ) {
dp_link->sink_request |= DP_TEST_LINK_EDID_READ;
- return ret;
- }
-
- ret = dp_link_process_ds_port_status_change(link);
- if (!ret) {
+ } else if (!dp_link_process_ds_port_status_change(link)) {
dp_link->sink_request |= DS_PORT_STATUS_CHANGED;
- return ret;
- }
-
- ret = dp_link_process_link_training_request(link);
- if (!ret) {
+ } else if (!dp_link_process_link_training_request(link)) {
dp_link->sink_request |= DP_TEST_LINK_TRAINING;
- return ret;
- }
-
- ret = dp_link_process_phy_test_pattern_request(link);
- if (!ret) {
+ } else if (!dp_link_process_phy_test_pattern_request(link)) {
dp_link->sink_request |= DP_TEST_LINK_PHY_TEST_PATTERN;
- return ret;
- }
-
- ret = dp_link_process_link_status_update(link);
- if (!ret) {
- dp_link->sink_request |= DP_LINK_STATUS_UPDATED;
- return ret;
- }
-
- if (dp_link_is_video_pattern_requested(link)) {
- ret = 0;
- dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN;
- }
-
- if (dp_link_is_audio_pattern_requested(link)) {
- dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
- return -EINVAL;
+ } else {
+ ret = dp_link_process_link_status_update(link);
+ if (!ret) {
+ dp_link->sink_request |= DP_LINK_STATUS_UPDATED;
+ } else {
+ if (dp_link_is_video_pattern_requested(link)) {
+ ret = 0;
+ dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN;
+ }
+ if (dp_link_is_audio_pattern_requested(link)) {
+ dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
+ ret = -EINVAL;
+ }
+ }
}
+ DRM_DEBUG_DP("sink request=%#x", dp_link->sink_request);
return ret;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 440b32753430..2181b60e1d1d 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -271,7 +271,7 @@ static u8 dp_panel_get_edid_checksum(struct edid *edid)
{
struct edid *last_block;
u8 *raw_edid;
- bool is_edid_corrupt;
+ bool is_edid_corrupt = false;
if (!edid) {
DRM_ERROR("invalid edid input\n");
@@ -303,7 +303,12 @@ void dp_panel_handle_sink_request(struct dp_panel *dp_panel)
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) {
- u8 checksum = dp_panel_get_edid_checksum(dp_panel->edid);
+ u8 checksum;
+
+ if (dp_panel->edid)
+ checksum = dp_panel_get_edid_checksum(dp_panel->edid);
+ else
+ checksum = dp_panel->connector->real_edid_checksum;
dp_link_send_edid_checksum(panel->link, checksum);
dp_link_send_test_response(panel->link);
diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c
index 3961ba4efc3c..b48b45e92bfa 100644
--- a/drivers/gpu/drm/msm/dp/dp_power.c
+++ b/drivers/gpu/drm/msm/dp/dp_power.c
@@ -208,6 +208,9 @@ static int dp_power_clk_set_rate(struct dp_power_private *power,
int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type)
{
+ DRM_DEBUG_DP("core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n",
+ dp_power->core_clks_on, dp_power->link_clks_on, dp_power->stream_clks_on);
+
if (pm_type == DP_CORE_PM)
return dp_power->core_clks_on;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 75afc12a7b25..614dc7f26f2c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -13,6 +13,13 @@ struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
return msm_dsi->encoder;
}
+bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi)
+{
+ unsigned long host_flags = msm_dsi_host_get_mode_flags(msm_dsi->host);
+
+ return !(host_flags & MIPI_DSI_MODE_VIDEO);
+}
+
static int dsi_get_phy(struct msm_dsi *msm_dsi)
{
struct platform_device *pdev = msm_dsi->pdev;
@@ -26,8 +33,10 @@ static int dsi_get_phy(struct msm_dsi *msm_dsi)
}
phy_pdev = of_find_device_by_node(phy_node);
- if (phy_pdev)
+ if (phy_pdev) {
msm_dsi->phy = platform_get_drvdata(phy_pdev);
+ msm_dsi->phy_dev = &phy_pdev->dev;
+ }
of_node_put(phy_node);
@@ -36,8 +45,6 @@ static int dsi_get_phy(struct msm_dsi *msm_dsi)
return -EPROBE_DEFER;
}
- msm_dsi->phy_dev = get_device(&phy_pdev->dev);
-
return 0;
}
@@ -244,8 +251,6 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
goto fail;
}
- msm_dsi_manager_setup_encoder(msm_dsi->id);
-
priv->bridges[priv->num_bridges++] = msm_dsi->bridge;
priv->connectors[priv->num_connectors++] = msm_dsi->connector;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 9b8e9b07eced..b50db91cb8a7 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -80,10 +80,10 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id);
struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id);
int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
-void msm_dsi_manager_setup_encoder(int id);
int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
bool msm_dsi_manager_validate_current_config(u8 id);
+void msm_dsi_manager_tpg_enable(void);
/* msm dsi */
static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
@@ -109,7 +109,7 @@ int msm_dsi_host_enable(struct mipi_dsi_host *host);
int msm_dsi_host_disable(struct mipi_dsi_host *host);
int msm_dsi_host_power_on(struct mipi_dsi_host *host,
struct msm_dsi_phy_shared_timings *phy_shared_timings,
- bool is_dual_dsi);
+ bool is_bonded_dsi, struct msm_dsi_phy *phy);
int msm_dsi_host_power_off(struct mipi_dsi_host *host);
int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
const struct drm_display_mode *mode);
@@ -123,7 +123,7 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
void msm_dsi_host_reset_phy(struct mipi_dsi_host *host);
void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
struct msm_dsi_phy_clk_request *clk_req,
- bool is_dual_dsi);
+ bool is_bonded_dsi);
void msm_dsi_host_destroy(struct mipi_dsi_host *host);
int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
struct drm_device *dev);
@@ -145,9 +145,11 @@ int dsi_dma_base_get_6g(struct msm_dsi_host *msm_host, uint64_t *iova);
int dsi_dma_base_get_v2(struct msm_dsi_host *msm_host, uint64_t *iova);
int dsi_clk_init_v2(struct msm_dsi_host *msm_host);
int dsi_clk_init_6g_v2(struct msm_dsi_host *msm_host);
-int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_dual_dsi);
-int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_dual_dsi);
+int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi);
+int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi);
void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct mipi_dsi_host *host);
+void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host);
+
/* dsi phy */
struct msm_dsi_phy;
struct msm_dsi_phy_shared_timings {
@@ -164,10 +166,9 @@ struct msm_dsi_phy_clk_request {
void msm_dsi_phy_driver_register(void);
void msm_dsi_phy_driver_unregister(void);
int msm_dsi_phy_enable(struct msm_dsi_phy *phy,
- struct msm_dsi_phy_clk_request *clk_req);
+ struct msm_dsi_phy_clk_request *clk_req,
+ struct msm_dsi_phy_shared_timings *shared_timings);
void msm_dsi_phy_disable(struct msm_dsi_phy *phy);
-void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
- struct msm_dsi_phy_shared_timings *shared_timing);
void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
enum msm_dsi_phy_usecase uc);
int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy,
@@ -175,6 +176,7 @@ int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy,
void msm_dsi_phy_pll_save_state(struct msm_dsi_phy *phy);
int msm_dsi_phy_pll_restore_state(struct msm_dsi_phy *phy);
void msm_dsi_phy_snapshot(struct msm_disp_state *disp_state, struct msm_dsi_phy *phy);
+bool msm_dsi_phy_set_continuous_clock(struct msm_dsi_phy *phy, bool enable);
#endif /* __DSI_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index eadbcc78fd72..49b551ad1bff 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -105,6 +105,32 @@ enum dsi_lane_swap {
LANE_SWAP_3210 = 7,
};
+enum video_config_bpp {
+ VIDEO_CONFIG_18BPP = 0,
+ VIDEO_CONFIG_24BPP = 1,
+};
+
+enum video_pattern_sel {
+ VID_PRBS = 0,
+ VID_INCREMENTAL = 1,
+ VID_FIXED = 2,
+ VID_MDSS_GENERAL_PATTERN = 3,
+};
+
+enum cmd_mdp_stream0_pattern_sel {
+ CMD_MDP_PRBS = 0,
+ CMD_MDP_INCREMENTAL = 1,
+ CMD_MDP_FIXED = 2,
+ CMD_MDP_MDSS_GENERAL_PATTERN = 3,
+};
+
+enum cmd_dma_pattern_sel {
+ CMD_DMA_PRBS = 0,
+ CMD_DMA_INCREMENTAL = 1,
+ CMD_DMA_FIXED = 2,
+ CMD_DMA_CUSTOM_PATTERN_DMA_FIFO = 3,
+};
+
#define DSI_IRQ_CMD_DMA_DONE 0x00000001
#define DSI_IRQ_MASK_CMD_DMA_DONE 0x00000002
#define DSI_IRQ_CMD_MDP_DONE 0x00000100
@@ -518,6 +544,7 @@ static inline uint32_t DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(uint32_t val)
#define DSI_LANE_STATUS_DLN0_DIRECTION 0x00010000
#define REG_DSI_LANE_CTRL 0x000000a8
+#define DSI_LANE_CTRL_HS_REQ_SEL_PHY 0x01000000
#define DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST 0x10000000
#define REG_DSI_LANE_SWAP_CTRL 0x000000ac
@@ -564,6 +591,53 @@ static inline uint32_t DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(enum dsi_lane_swap val)
#define REG_DSI_PHY_RESET 0x00000128
#define DSI_PHY_RESET_RESET 0x00000001
+#define REG_DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL 0x00000160
+
+#define REG_DSI_TPG_MAIN_CONTROL 0x00000198
+#define DSI_TPG_MAIN_CONTROL_CHECKERED_RECTANGLE_PATTERN 0x00000100
+
+#define REG_DSI_TPG_VIDEO_CONFIG 0x000001a0
+#define DSI_TPG_VIDEO_CONFIG_BPP__MASK 0x00000003
+#define DSI_TPG_VIDEO_CONFIG_BPP__SHIFT 0
+static inline uint32_t DSI_TPG_VIDEO_CONFIG_BPP(enum video_config_bpp val)
+{
+ return ((val) << DSI_TPG_VIDEO_CONFIG_BPP__SHIFT) & DSI_TPG_VIDEO_CONFIG_BPP__MASK;
+}
+#define DSI_TPG_VIDEO_CONFIG_RGB 0x00000004
+
+#define REG_DSI_TEST_PATTERN_GEN_CTRL 0x00000158
+#define DSI_TEST_PATTERN_GEN_CTRL_CMD_DMA_PATTERN_SEL__MASK 0x00030000
+#define DSI_TEST_PATTERN_GEN_CTRL_CMD_DMA_PATTERN_SEL__SHIFT 16
+static inline uint32_t DSI_TEST_PATTERN_GEN_CTRL_CMD_DMA_PATTERN_SEL(enum cmd_dma_pattern_sel val)
+{
+ return ((val) << DSI_TEST_PATTERN_GEN_CTRL_CMD_DMA_PATTERN_SEL__SHIFT) & DSI_TEST_PATTERN_GEN_CTRL_CMD_DMA_PATTERN_SEL__MASK;
+}
+#define DSI_TEST_PATTERN_GEN_CTRL_CMD_MDP_STREAM0_PATTERN_SEL__MASK 0x00000300
+#define DSI_TEST_PATTERN_GEN_CTRL_CMD_MDP_STREAM0_PATTERN_SEL__SHIFT 8
+static inline uint32_t DSI_TEST_PATTERN_GEN_CTRL_CMD_MDP_STREAM0_PATTERN_SEL(enum cmd_mdp_stream0_pattern_sel val)
+{
+ return ((val) << DSI_TEST_PATTERN_GEN_CTRL_CMD_MDP_STREAM0_PATTERN_SEL__SHIFT) & DSI_TEST_PATTERN_GEN_CTRL_CMD_MDP_STREAM0_PATTERN_SEL__MASK;
+}
+#define DSI_TEST_PATTERN_GEN_CTRL_VIDEO_PATTERN_SEL__MASK 0x00000030
+#define DSI_TEST_PATTERN_GEN_CTRL_VIDEO_PATTERN_SEL__SHIFT 4
+static inline uint32_t DSI_TEST_PATTERN_GEN_CTRL_VIDEO_PATTERN_SEL(enum video_pattern_sel val)
+{
+ return ((val) << DSI_TEST_PATTERN_GEN_CTRL_VIDEO_PATTERN_SEL__SHIFT) & DSI_TEST_PATTERN_GEN_CTRL_VIDEO_PATTERN_SEL__MASK;
+}
+#define DSI_TEST_PATTERN_GEN_CTRL_TPG_DMA_FIFO_MODE 0x00000004
+#define DSI_TEST_PATTERN_GEN_CTRL_CMD_DMA_TPG_EN 0x00000002
+#define DSI_TEST_PATTERN_GEN_CTRL_EN 0x00000001
+
+#define REG_DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0 0x00000168
+
+#define REG_DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER 0x00000180
+#define DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER_SW_TRIGGER 0x00000001
+
+#define REG_DSI_TPG_MAIN_CONTROL2 0x0000019c
+#define DSI_TPG_MAIN_CONTROL2_CMD_MDP0_CHECKERED_RECTANGLE_PATTERN 0x00000080
+#define DSI_TPG_MAIN_CONTROL2_CMD_MDP1_CHECKERED_RECTANGLE_PATTERN 0x00010000
+#define DSI_TPG_MAIN_CONTROL2_CMD_MDP2_CHECKERED_RECTANGLE_PATTERN 0x02000000
+
#define REG_DSI_T_CLK_PRE_EXTEND 0x0000017c
#define DSI_T_CLK_PRE_EXTEND_INC_BY_2_BYTECLK 0x00000001
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index f3f1c03c7db9..96bbc8b6d009 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -32,9 +32,8 @@ static const char * const dsi_6g_bus_clk_names[] = {
static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
.io_offset = DSI_6G_REG_SHIFT,
.reg_cfg = {
- .num = 4,
+ .num = 3,
.regs = {
- {"gdsc", -1, -1},
{"vdd", 150000, 100}, /* 3.0 V */
{"vdda", 100000, 100}, /* 1.2 V */
{"vddio", 100000, 100}, /* 1.8 V */
@@ -53,9 +52,8 @@ static const char * const dsi_8916_bus_clk_names[] = {
static const struct msm_dsi_config msm8916_dsi_cfg = {
.io_offset = DSI_6G_REG_SHIFT,
.reg_cfg = {
- .num = 3,
+ .num = 2,
.regs = {
- {"gdsc", -1, -1},
{"vdda", 100000, 100}, /* 1.2 V */
{"vddio", 100000, 100}, /* 1.8 V */
},
@@ -73,9 +71,8 @@ static const char * const dsi_8976_bus_clk_names[] = {
static const struct msm_dsi_config msm8976_dsi_cfg = {
.io_offset = DSI_6G_REG_SHIFT,
.reg_cfg = {
- .num = 3,
+ .num = 2,
.regs = {
- {"gdsc", -1, -1},
{"vdda", 100000, 100}, /* 1.2 V */
{"vddio", 100000, 100}, /* 1.8 V */
},
@@ -89,9 +86,8 @@ static const struct msm_dsi_config msm8976_dsi_cfg = {
static const struct msm_dsi_config msm8994_dsi_cfg = {
.io_offset = DSI_6G_REG_SHIFT,
.reg_cfg = {
- .num = 7,
+ .num = 6,
.regs = {
- {"gdsc", -1, -1},
{"vdda", 100000, 100}, /* 1.25 V */
{"vddio", 100000, 100}, /* 1.8 V */
{"vcca", 10000, 100}, /* 1.0 V */
@@ -154,7 +150,6 @@ static const struct msm_dsi_config sdm660_dsi_cfg = {
.reg_cfg = {
.num = 2,
.regs = {
- {"vdd", 73400, 32 }, /* 0.9 V */
{"vdda", 12560, 4 }, /* 1.2 V */
},
},
@@ -200,6 +195,24 @@ static const struct msm_dsi_config sc7180_dsi_cfg = {
.num_dsi = 1,
};
+static const char * const dsi_sc7280_bus_clk_names[] = {
+ "iface", "bus",
+};
+
+static const struct msm_dsi_config sc7280_dsi_cfg = {
+ .io_offset = DSI_6G_REG_SHIFT,
+ .reg_cfg = {
+ .num = 1,
+ .regs = {
+ {"vdda", 8350, 0 }, /* 1.2 V */
+ },
+ },
+ .bus_clk_names = dsi_sc7280_bus_clk_names,
+ .num_bus_clks = ARRAY_SIZE(dsi_sc7280_bus_clk_names),
+ .io_start = { 0xae94000 },
+ .num_dsi = 1,
+};
+
static const struct msm_dsi_host_cfg_ops msm_dsi_v2_host_ops = {
.link_clk_set_rate = dsi_link_clk_set_rate_v2,
.link_clk_enable = dsi_link_clk_enable_v2,
@@ -267,6 +280,8 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
&sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_4_1,
&sc7180_dsi_cfg, &msm_dsi_6g_v2_host_ops},
+ {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_5_0,
+ &sc7280_dsi_cfg, &msm_dsi_6g_v2_host_ops},
};
const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index ade9b609c7d9..41e99a9fb5de 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -24,6 +24,7 @@
#define MSM_DSI_6G_VER_MINOR_V2_3_0 0x20030000
#define MSM_DSI_6G_VER_MINOR_V2_4_0 0x20040000
#define MSM_DSI_6G_VER_MINOR_V2_4_1 0x20040001
+#define MSM_DSI_6G_VER_MINOR_V2_5_0 0x20050000
#define MSM_DSI_V2_VER_MINOR_8064 0x0
@@ -47,7 +48,7 @@ struct msm_dsi_host_cfg_ops {
void* (*tx_buf_get)(struct msm_dsi_host *msm_host);
void (*tx_buf_put)(struct msm_dsi_host *msm_host);
int (*dma_base_get)(struct msm_dsi_host *msm_host, uint64_t *iova);
- int (*calc_clk_rate)(struct msm_dsi_host *msm_host, bool is_dual_dsi);
+ int (*calc_clk_rate)(struct msm_dsi_host *msm_host, bool is_bonded_dsi);
};
struct msm_dsi_cfg_handler {
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index ed504fe5074f..e269df285136 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -27,6 +27,7 @@
#include "dsi_cfg.h"
#include "msm_kms.h"
#include "msm_gem.h"
+#include "phy/dsi_phy.h"
#define DSI_RESET_TOGGLE_DELAY_MS 20
@@ -167,6 +168,9 @@ struct msm_dsi_host {
int dlane_swap;
int num_data_lanes;
+ /* from phy DT */
+ bool cphy_mode;
+
u32 dma_cmd_ctrl_restore;
bool registered;
@@ -203,35 +207,22 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
{
const struct msm_dsi_cfg_handler *cfg_hnd = NULL;
struct device *dev = &msm_host->pdev->dev;
- struct regulator *gdsc_reg;
struct clk *ahb_clk;
int ret;
u32 major = 0, minor = 0;
- gdsc_reg = regulator_get(dev, "gdsc");
- if (IS_ERR(gdsc_reg)) {
- pr_err("%s: cannot get gdsc\n", __func__);
- goto exit;
- }
-
ahb_clk = msm_clk_get(msm_host->pdev, "iface");
if (IS_ERR(ahb_clk)) {
pr_err("%s: cannot get interface clock\n", __func__);
- goto put_gdsc;
+ goto exit;
}
pm_runtime_get_sync(dev);
- ret = regulator_enable(gdsc_reg);
- if (ret) {
- pr_err("%s: unable to enable gdsc\n", __func__);
- goto put_gdsc;
- }
-
ret = clk_prepare_enable(ahb_clk);
if (ret) {
pr_err("%s: unable to enable ahb_clk\n", __func__);
- goto disable_gdsc;
+ goto runtime_put;
}
ret = dsi_get_version(msm_host->ctrl_base, &major, &minor);
@@ -246,11 +237,8 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
disable_clks:
clk_disable_unprepare(ahb_clk);
-disable_gdsc:
- regulator_disable(gdsc_reg);
+runtime_put:
pm_runtime_put_sync(dev);
-put_gdsc:
- regulator_put(gdsc_reg);
exit:
return cfg_hnd;
}
@@ -510,6 +498,7 @@ int msm_dsi_runtime_resume(struct device *dev)
int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host)
{
+ u32 byte_intf_rate;
int ret;
DBG("Set clk rates: pclk=%d, byteclk=%d",
@@ -529,8 +518,13 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host)
}
if (msm_host->byte_intf_clk) {
- ret = clk_set_rate(msm_host->byte_intf_clk,
- msm_host->byte_clk_rate / 2);
+ /* For CPHY, byte_intf_clk is same as byte_clk */
+ if (msm_host->cphy_mode)
+ byte_intf_rate = msm_host->byte_clk_rate;
+ else
+ byte_intf_rate = msm_host->byte_clk_rate / 2;
+
+ ret = clk_set_rate(msm_host->byte_intf_clk, byte_intf_rate);
if (ret) {
pr_err("%s: Failed to set rate byte intf clk, %d\n",
__func__, ret);
@@ -679,7 +673,7 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host)
clk_disable_unprepare(msm_host->byte_clk);
}
-static u32 dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi)
+static u32 dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
{
struct drm_display_mode *mode = msm_host->mode;
u32 pclk_rate;
@@ -687,22 +681,22 @@ static u32 dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi)
pclk_rate = mode->clock * 1000;
/*
- * For dual DSI mode, the current DRM mode has the complete width of the
+ * For bonded DSI mode, the current DRM mode has the complete width of the
* panel. Since, the complete panel is driven by two DSI controllers,
* the clock rates have to be split between the two dsi controllers.
* Adjust the byte and pixel clock rates for each dsi host accordingly.
*/
- if (is_dual_dsi)
+ if (is_bonded_dsi)
pclk_rate /= 2;
return pclk_rate;
}
-static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_dual_dsi)
+static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
{
u8 lanes = msm_host->lanes;
u32 bpp = dsi_get_bpp(msm_host->format);
- u32 pclk_rate = dsi_get_pclk_rate(msm_host, is_dual_dsi);
+ u32 pclk_rate = dsi_get_pclk_rate(msm_host, is_bonded_dsi);
u64 pclk_bpp = (u64)pclk_rate * bpp;
if (lanes == 0) {
@@ -710,7 +704,11 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_dual_dsi)
lanes = 1;
}
- do_div(pclk_bpp, (8 * lanes));
+ /* CPHY "byte_clk" is in units of 16 bits */
+ if (msm_host->cphy_mode)
+ do_div(pclk_bpp, (16 * lanes));
+ else
+ do_div(pclk_bpp, (8 * lanes));
msm_host->pixel_clk_rate = pclk_rate;
msm_host->byte_clk_rate = pclk_bpp;
@@ -720,28 +718,28 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_dual_dsi)
}
-int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_dual_dsi)
+int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
{
if (!msm_host->mode) {
pr_err("%s: mode not set\n", __func__);
return -EINVAL;
}
- dsi_calc_pclk(msm_host, is_dual_dsi);
+ dsi_calc_pclk(msm_host, is_bonded_dsi);
msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk);
return 0;
}
-int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_dual_dsi)
+int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
{
u32 bpp = dsi_get_bpp(msm_host->format);
u64 pclk_bpp;
unsigned int esc_mhz, esc_div;
unsigned long byte_mhz;
- dsi_calc_pclk(msm_host, is_dual_dsi);
+ dsi_calc_pclk(msm_host, is_bonded_dsi);
- pclk_bpp = (u64)dsi_get_pclk_rate(msm_host, is_dual_dsi) * bpp;
+ pclk_bpp = (u64)dsi_get_pclk_rate(msm_host, is_bonded_dsi) * bpp;
do_div(pclk_bpp, 8);
msm_host->src_clk_rate = pclk_bpp;
@@ -834,7 +832,7 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt(
}
static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
- struct msm_dsi_phy_shared_timings *phy_shared_timings)
+ struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy *phy)
{
u32 flags = msm_host->mode_flags;
enum mipi_dsi_pixel_format mipi_fmt = msm_host->format;
@@ -849,11 +847,11 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
if (flags & MIPI_DSI_MODE_VIDEO) {
if (flags & MIPI_DSI_MODE_VIDEO_HSE)
data |= DSI_VID_CFG0_PULSE_MODE_HSA_HE;
- if (flags & MIPI_DSI_MODE_VIDEO_HFP)
+ if (flags & MIPI_DSI_MODE_VIDEO_NO_HFP)
data |= DSI_VID_CFG0_HFP_POWER_STOP;
- if (flags & MIPI_DSI_MODE_VIDEO_HBP)
+ if (flags & MIPI_DSI_MODE_VIDEO_NO_HBP)
data |= DSI_VID_CFG0_HBP_POWER_STOP;
- if (flags & MIPI_DSI_MODE_VIDEO_HSA)
+ if (flags & MIPI_DSI_MODE_VIDEO_NO_HSA)
data |= DSI_VID_CFG0_HSA_POWER_STOP;
/* Always set low power stop mode for BLLP
* to let command engine send packets
@@ -908,7 +906,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
DSI_T_CLK_PRE_EXTEND_INC_BY_2_BYTECLK);
data = 0;
- if (!(flags & MIPI_DSI_MODE_EOT_PACKET))
+ if (!(flags & MIPI_DSI_MODE_NO_EOT_PACKET))
data |= DSI_EOT_PACKET_CTRL_TX_EOT_APPEND;
dsi_write(msm_host, REG_DSI_EOT_PACKET_CTRL, data);
@@ -929,6 +927,10 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) {
lane_ctrl = dsi_read(msm_host, REG_DSI_LANE_CTRL);
+
+ if (msm_dsi_phy_set_continuous_clock(phy, enable))
+ lane_ctrl &= ~DSI_LANE_CTRL_HS_REQ_SEL_PHY;
+
dsi_write(msm_host, REG_DSI_LANE_CTRL,
lane_ctrl | DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST);
}
@@ -936,9 +938,12 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
data |= DSI_CTRL_ENABLE;
dsi_write(msm_host, REG_DSI_CTRL, data);
+
+ if (msm_host->cphy_mode)
+ dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0));
}
-static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)
+static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
{
struct drm_display_mode *mode = msm_host->mode;
u32 hs_start = 0, vs_start = 0; /* take sync start as 0 */
@@ -956,13 +961,13 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)
DBG("");
/*
- * For dual DSI mode, the current DRM mode has
+ * For bonded DSI mode, the current DRM mode has
* the complete width of the panel. Since, the complete
* panel is driven by two DSI controllers, the horizontal
* timings have to be split between the two dsi controllers.
* Adjust the DSI host timing values accordingly.
*/
- if (is_dual_dsi) {
+ if (is_bonded_dsi) {
h_total /= 2;
hs_end /= 2;
ha_start /= 2;
@@ -2226,6 +2231,8 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
struct clk *byte_clk_provider, *pixel_clk_provider;
int ret;
+ msm_host->cphy_mode = src_phy->cphy_mode;
+
ret = msm_dsi_phy_get_clk_provider(src_phy,
&byte_clk_provider, &pixel_clk_provider);
if (ret) {
@@ -2285,19 +2292,26 @@ void msm_dsi_host_reset_phy(struct mipi_dsi_host *host)
void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
struct msm_dsi_phy_clk_request *clk_req,
- bool is_dual_dsi)
+ bool is_bonded_dsi)
{
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
int ret;
- ret = cfg_hnd->ops->calc_clk_rate(msm_host, is_dual_dsi);
+ ret = cfg_hnd->ops->calc_clk_rate(msm_host, is_bonded_dsi);
if (ret) {
pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
return;
}
- clk_req->bitclk_rate = msm_host->byte_clk_rate * 8;
+ /* CPHY transmits 16 bits over 7 clock cycles
+ * "byte_clk" is in units of 16-bits (see dsi_calc_pclk),
+ * so multiply by 7 to get the "bitclk rate"
+ */
+ if (msm_host->cphy_mode)
+ clk_req->bitclk_rate = msm_host->byte_clk_rate * 7;
+ else
+ clk_req->bitclk_rate = msm_host->byte_clk_rate * 8;
clk_req->escclk_rate = msm_host->esc_clk_rate;
}
@@ -2354,7 +2368,7 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)
int msm_dsi_host_power_on(struct mipi_dsi_host *host,
struct msm_dsi_phy_shared_timings *phy_shared_timings,
- bool is_dual_dsi)
+ bool is_bonded_dsi, struct msm_dsi_phy *phy)
{
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
@@ -2392,9 +2406,9 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
goto fail_disable_clk;
}
- dsi_timing_setup(msm_host, is_dual_dsi);
+ dsi_timing_setup(msm_host, is_bonded_dsi);
dsi_sw_reset(msm_host);
- dsi_ctrl_config(msm_host, true, phy_shared_timings);
+ dsi_ctrl_config(msm_host, true, phy_shared_timings, phy);
if (msm_host->disp_en_gpio)
gpiod_set_value(msm_host->disp_en_gpio, 1);
@@ -2425,7 +2439,7 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
goto unlock_ret;
}
- dsi_ctrl_config(msm_host, false, NULL);
+ dsi_ctrl_config(msm_host, false, NULL, NULL);
if (msm_host->disp_en_gpio)
gpiod_set_value(msm_host->disp_en_gpio, 0);
@@ -2495,3 +2509,64 @@ void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct mipi_dsi_ho
pm_runtime_put_sync(&msm_host->pdev->dev);
}
+
+static void msm_dsi_host_video_test_pattern_setup(struct msm_dsi_host *msm_host)
+{
+ u32 reg;
+
+ reg = dsi_read(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL);
+
+ dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL, 0xff);
+ /* draw checkered rectangle pattern */
+ dsi_write(msm_host, REG_DSI_TPG_MAIN_CONTROL,
+ DSI_TPG_MAIN_CONTROL_CHECKERED_RECTANGLE_PATTERN);
+ /* use 24-bit RGB test pttern */
+ dsi_write(msm_host, REG_DSI_TPG_VIDEO_CONFIG,
+ DSI_TPG_VIDEO_CONFIG_BPP(VIDEO_CONFIG_24BPP) |
+ DSI_TPG_VIDEO_CONFIG_RGB);
+
+ reg |= DSI_TEST_PATTERN_GEN_CTRL_VIDEO_PATTERN_SEL(VID_MDSS_GENERAL_PATTERN);
+ dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL, reg);
+
+ DBG("Video test pattern setup done\n");
+}
+
+static void msm_dsi_host_cmd_test_pattern_setup(struct msm_dsi_host *msm_host)
+{
+ u32 reg;
+
+ reg = dsi_read(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL);
+
+ /* initial value for test pattern */
+ dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0, 0xff);
+
+ reg |= DSI_TEST_PATTERN_GEN_CTRL_CMD_MDP_STREAM0_PATTERN_SEL(CMD_MDP_MDSS_GENERAL_PATTERN);
+
+ dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL, reg);
+ /* draw checkered rectangle pattern */
+ dsi_write(msm_host, REG_DSI_TPG_MAIN_CONTROL2,
+ DSI_TPG_MAIN_CONTROL2_CMD_MDP0_CHECKERED_RECTANGLE_PATTERN);
+
+ DBG("Cmd test pattern setup done\n");
+}
+
+void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host)
+{
+ struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+ bool is_video_mode = !!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO);
+ u32 reg;
+
+ if (is_video_mode)
+ msm_dsi_host_video_test_pattern_setup(msm_host);
+ else
+ msm_dsi_host_cmd_test_pattern_setup(msm_host);
+
+ reg = dsi_read(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL);
+ /* enable the test pattern generator */
+ dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL, (reg | DSI_TEST_PATTERN_GEN_CTRL_EN));
+
+ /* for command mode need to trigger one frame from tpg */
+ if (!is_video_mode)
+ dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER,
+ DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER_SW_TRIGGER);
+}
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 4ebfedc4a9ac..c41d39f5b7cf 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -21,14 +21,14 @@
struct msm_dsi_manager {
struct msm_dsi *dsi[DSI_MAX];
- bool is_dual_dsi;
+ bool is_bonded_dsi;
bool is_sync_needed;
int master_dsi_link_id;
};
static struct msm_dsi_manager msm_dsim_glb;
-#define IS_DUAL_DSI() (msm_dsim_glb.is_dual_dsi)
+#define IS_BONDED_DSI() (msm_dsim_glb.is_bonded_dsi)
#define IS_SYNC_NEEDED() (msm_dsim_glb.is_sync_needed)
#define IS_MASTER_DSI_LINK(id) (msm_dsim_glb.master_dsi_link_id == id)
@@ -42,18 +42,17 @@ static inline struct msm_dsi *dsi_mgr_get_other_dsi(int id)
return msm_dsim_glb.dsi[(id + 1) % DSI_MAX];
}
-static int dsi_mgr_parse_dual_dsi(struct device_node *np, int id)
+static int dsi_mgr_parse_of(struct device_node *np, int id)
{
struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
- /* We assume 2 dsi nodes have the same information of dual-dsi and
- * sync-mode, and only one node specifies master in case of dual mode.
+ /* We assume 2 dsi nodes have the same information of bonded dsi and
+ * sync-mode, and only one node specifies master in case of bonded mode.
*/
- if (!msm_dsim->is_dual_dsi)
- msm_dsim->is_dual_dsi = of_property_read_bool(
- np, "qcom,dual-dsi-mode");
+ if (!msm_dsim->is_bonded_dsi)
+ msm_dsim->is_bonded_dsi = of_property_read_bool(np, "qcom,dual-dsi-mode");
- if (msm_dsim->is_dual_dsi) {
+ if (msm_dsim->is_bonded_dsi) {
if (of_property_read_bool(np, "qcom,master-dsi"))
msm_dsim->master_dsi_link_id = id;
if (!msm_dsim->is_sync_needed)
@@ -72,7 +71,7 @@ static int dsi_mgr_setup_components(int id)
struct msm_dsi *clk_slave_dsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
int ret;
- if (!IS_DUAL_DSI()) {
+ if (!IS_BONDED_DSI()) {
ret = msm_dsi_host_register(msm_dsi->host, true);
if (ret)
return ret;
@@ -100,7 +99,7 @@ static int dsi_mgr_setup_components(int id)
if (ret)
return ret;
- /* PLL0 is to drive both 2 DSI link clocks in Dual DSI mode. */
+ /* PLL0 is to drive both 2 DSI link clocks in bonded DSI mode. */
msm_dsi_phy_set_usecase(clk_master_dsi->phy,
MSM_DSI_PHY_MASTER);
msm_dsi_phy_set_usecase(clk_slave_dsi->phy,
@@ -119,12 +118,11 @@ static int enable_phy(struct msm_dsi *msm_dsi,
{
struct msm_dsi_phy_clk_request clk_req;
int ret;
- bool is_dual_dsi = IS_DUAL_DSI();
+ bool is_bonded_dsi = IS_BONDED_DSI();
- msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_dual_dsi);
+ msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_bonded_dsi);
- ret = msm_dsi_phy_enable(msm_dsi->phy, &clk_req);
- msm_dsi_phy_get_shared_timings(msm_dsi->phy, shared_timings);
+ ret = msm_dsi_phy_enable(msm_dsi->phy, &clk_req, shared_timings);
return ret;
}
@@ -138,12 +136,12 @@ dsi_mgr_phy_enable(int id,
struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
int ret;
- /* In case of dual DSI, some registers in PHY1 have been programmed
+ /* In case of bonded DSI, some registers in PHY1 have been programmed
* during PLL0 clock's set_rate. The PHY1 reset called by host1 here
* will silently reset those PHY1 registers. Therefore we need to reset
* and enable both PHYs before any PLL clock operation.
*/
- if (IS_DUAL_DSI() && mdsi && sdsi) {
+ if (IS_BONDED_DSI() && mdsi && sdsi) {
if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
msm_dsi_host_reset_phy(mdsi->host);
msm_dsi_host_reset_phy(sdsi->host);
@@ -178,11 +176,11 @@ static void dsi_mgr_phy_disable(int id)
struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
/* disable DSI phy
- * In dual-dsi configuration, the phy should be disabled for the
+ * In bonded dsi configuration, the phy should be disabled for the
* first controller only when the second controller is disabled.
*/
msm_dsi->phy_enabled = false;
- if (IS_DUAL_DSI() && mdsi && sdsi) {
+ if (IS_BONDED_DSI() && mdsi && sdsi) {
if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
msm_dsi_phy_disable(sdsi->phy);
msm_dsi_phy_disable(mdsi->phy);
@@ -217,24 +215,6 @@ static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge)
return dsi_bridge->id;
}
-static bool dsi_mgr_is_cmd_mode(struct msm_dsi *msm_dsi)
-{
- unsigned long host_flags = msm_dsi_host_get_mode_flags(msm_dsi->host);
- return !(host_flags & MIPI_DSI_MODE_VIDEO);
-}
-
-void msm_dsi_manager_setup_encoder(int id)
-{
- struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
- struct msm_drm_private *priv = msm_dsi->dev->dev_private;
- struct msm_kms *kms = priv->kms;
- struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi);
-
- if (encoder && kms->funcs->set_encoder_mode)
- kms->funcs->set_encoder_mode(kms, encoder,
- dsi_mgr_is_cmd_mode(msm_dsi));
-}
-
static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id)
{
struct msm_drm_private *priv = conn->dev->dev_private;
@@ -244,7 +224,7 @@ static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id)
struct msm_dsi *master_dsi, *slave_dsi;
struct drm_panel *panel;
- if (IS_DUAL_DSI() && !IS_MASTER_DSI_LINK(id)) {
+ if (IS_BONDED_DSI() && !IS_MASTER_DSI_LINK(id)) {
master_dsi = other_dsi;
slave_dsi = msm_dsi;
} else {
@@ -253,7 +233,7 @@ static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id)
}
/*
- * There is only 1 panel in the global panel list for dual DSI mode.
+ * There is only 1 panel in the global panel list for bonded DSI mode.
* Therefore slave dsi should get the drm_panel instance from master
* dsi.
*/
@@ -264,20 +244,20 @@ static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id)
return PTR_ERR(panel);
}
- if (!panel || !IS_DUAL_DSI())
+ if (!panel || !IS_BONDED_DSI())
goto out;
drm_object_attach_property(&conn->base,
conn->dev->mode_config.tile_property, 0);
/*
- * Set split display info to kms once dual DSI panel is connected to
+ * Set split display info to kms once bonded DSI panel is connected to
* both hosts.
*/
if (other_dsi && other_dsi->panel && kms->funcs->set_split_display) {
kms->funcs->set_split_display(kms, master_dsi->encoder,
slave_dsi->encoder,
- dsi_mgr_is_cmd_mode(msm_dsi));
+ msm_dsi_is_cmd_mode(msm_dsi));
}
out:
@@ -317,7 +297,7 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
return 0;
/*
- * In dual DSI mode, we have one connector that can be
+ * In bonded DSI mode, we have one connector that can be
* attached to the drm_panel.
*/
num = drm_panel_get_modes(panel, connector);
@@ -366,30 +346,30 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
struct mipi_dsi_host *host = msm_dsi->host;
struct drm_panel *panel = msm_dsi->panel;
struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
- bool is_dual_dsi = IS_DUAL_DSI();
+ bool is_bonded_dsi = IS_BONDED_DSI();
int ret;
DBG("id=%d", id);
if (!msm_dsi_device_connected(msm_dsi))
return;
- /* Do nothing with the host if it is slave-DSI in case of dual DSI */
- if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
+ /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
+ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
return;
ret = dsi_mgr_phy_enable(id, phy_shared_timings);
if (ret)
goto phy_en_fail;
- ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi);
+ ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_bonded_dsi, msm_dsi->phy);
if (ret) {
pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
goto host_on_fail;
}
- if (is_dual_dsi && msm_dsi1) {
+ if (is_bonded_dsi && msm_dsi1) {
ret = msm_dsi_host_power_on(msm_dsi1->host,
- &phy_shared_timings[DSI_1], is_dual_dsi);
+ &phy_shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy);
if (ret) {
pr_err("%s: power on host1 failed, %d\n",
__func__, ret);
@@ -415,7 +395,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
goto host_en_fail;
}
- if (is_dual_dsi && msm_dsi1) {
+ if (is_bonded_dsi && msm_dsi1) {
ret = msm_dsi_host_enable(msm_dsi1->host);
if (ret) {
pr_err("%s: enable host1 failed, %d\n", __func__, ret);
@@ -431,7 +411,7 @@ host_en_fail:
if (panel)
drm_panel_unprepare(panel);
panel_prep_fail:
- if (is_dual_dsi && msm_dsi1)
+ if (is_bonded_dsi && msm_dsi1)
msm_dsi_host_power_off(msm_dsi1->host);
host1_on_fail:
msm_dsi_host_power_off(host);
@@ -441,20 +421,33 @@ phy_en_fail:
return;
}
+void msm_dsi_manager_tpg_enable(void)
+{
+ struct msm_dsi *m_dsi = dsi_mgr_get_dsi(DSI_0);
+ struct msm_dsi *s_dsi = dsi_mgr_get_dsi(DSI_1);
+
+ /* if dual dsi, trigger tpg on master first then slave */
+ if (m_dsi) {
+ msm_dsi_host_test_pattern_en(m_dsi->host);
+ if (IS_BONDED_DSI() && s_dsi)
+ msm_dsi_host_test_pattern_en(s_dsi->host);
+ }
+}
+
static void dsi_mgr_bridge_enable(struct drm_bridge *bridge)
{
int id = dsi_mgr_bridge_get_id(bridge);
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct drm_panel *panel = msm_dsi->panel;
- bool is_dual_dsi = IS_DUAL_DSI();
+ bool is_bonded_dsi = IS_BONDED_DSI();
int ret;
DBG("id=%d", id);
if (!msm_dsi_device_connected(msm_dsi))
return;
- /* Do nothing with the host if it is slave-DSI in case of dual DSI */
- if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
+ /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
+ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
return;
if (panel) {
@@ -471,15 +464,15 @@ static void dsi_mgr_bridge_disable(struct drm_bridge *bridge)
int id = dsi_mgr_bridge_get_id(bridge);
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct drm_panel *panel = msm_dsi->panel;
- bool is_dual_dsi = IS_DUAL_DSI();
+ bool is_bonded_dsi = IS_BONDED_DSI();
int ret;
DBG("id=%d", id);
if (!msm_dsi_device_connected(msm_dsi))
return;
- /* Do nothing with the host if it is slave-DSI in case of dual DSI */
- if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
+ /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
+ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
return;
if (panel) {
@@ -497,7 +490,7 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
struct mipi_dsi_host *host = msm_dsi->host;
struct drm_panel *panel = msm_dsi->panel;
- bool is_dual_dsi = IS_DUAL_DSI();
+ bool is_bonded_dsi = IS_BONDED_DSI();
int ret;
DBG("id=%d", id);
@@ -506,18 +499,18 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
return;
/*
- * Do nothing with the host if it is slave-DSI in case of dual DSI.
+ * Do nothing with the host if it is slave-DSI in case of bonded DSI.
* It is safe to call dsi_mgr_phy_disable() here because a single PHY
* won't be diabled until both PHYs request disable.
*/
- if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
+ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
goto disable_phy;
ret = msm_dsi_host_disable(host);
if (ret)
pr_err("%s: host %d disable failed, %d\n", __func__, id, ret);
- if (is_dual_dsi && msm_dsi1) {
+ if (is_bonded_dsi && msm_dsi1) {
ret = msm_dsi_host_disable(msm_dsi1->host);
if (ret)
pr_err("%s: host1 disable failed, %d\n", __func__, ret);
@@ -537,7 +530,7 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
if (ret)
pr_err("%s: host %d power off failed,%d\n", __func__, id, ret);
- if (is_dual_dsi && msm_dsi1) {
+ if (is_bonded_dsi && msm_dsi1) {
ret = msm_dsi_host_power_off(msm_dsi1->host);
if (ret)
pr_err("%s: host1 power off failed, %d\n",
@@ -556,15 +549,15 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
struct mipi_dsi_host *host = msm_dsi->host;
- bool is_dual_dsi = IS_DUAL_DSI();
+ bool is_bonded_dsi = IS_BONDED_DSI();
DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
- if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
+ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
return;
msm_dsi_host_set_display_mode(host, adjusted_mode);
- if (is_dual_dsi && other_dsi)
+ if (is_bonded_dsi && other_dsi)
msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
}
@@ -640,15 +633,15 @@ fail:
bool msm_dsi_manager_validate_current_config(u8 id)
{
- bool is_dual_dsi = IS_DUAL_DSI();
+ bool is_bonded_dsi = IS_BONDED_DSI();
/*
- * For dual DSI, we only have one drm panel. For this
+ * For bonded DSI, we only have one drm panel. For this
* use case, we register only one bridge/connector.
* Skip bridge/connector initialisation if it is
- * slave-DSI for dual DSI configuration.
+ * slave-DSI for bonded DSI configuration.
*/
- if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) {
+ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id)) {
DBG("Skip bridge registration for slave DSI->id: %d\n", id);
return false;
}
@@ -740,7 +733,7 @@ int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg)
if (!msg->tx_buf || !msg->tx_len)
return 0;
- /* In dual master case, panel requires the same commands sent to
+ /* In bonded master case, panel requires the same commands sent to
* both DSI links. Host issues the command trigger to both links
* when DSI_1 calls the cmd transfer function, no matter it happens
* before or after DSI_0 cmd transfer.
@@ -809,9 +802,9 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
msm_dsim->dsi[id] = msm_dsi;
- ret = dsi_mgr_parse_dual_dsi(msm_dsi->pdev->dev.of_node, id);
+ ret = dsi_mgr_parse_of(msm_dsi->pdev->dev.of_node, id);
if (ret) {
- pr_err("%s: failed to parse dual DSI info\n", __func__);
+ pr_err("%s: failed to parse OF DSI info\n", __func__);
goto fail;
}
@@ -840,3 +833,12 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi)
msm_dsim->dsi[msm_dsi->id] = NULL;
}
+bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi)
+{
+ return IS_BONDED_DSI();
+}
+
+bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi)
+{
+ return IS_MASTER_DSI_LINK(msm_dsi->id);
+}
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 6ca6bfd4809b..8c65ef6968ca 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -5,6 +5,7 @@
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
+#include <dt-bindings/phy/phy.h>
#include "dsi_phy.h"
@@ -461,6 +462,51 @@ int msm_dsi_dphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
return 0;
}
+int msm_dsi_cphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
+ struct msm_dsi_phy_clk_request *clk_req)
+{
+ const unsigned long bit_rate = clk_req->bitclk_rate;
+ const unsigned long esc_rate = clk_req->escclk_rate;
+ s32 ui, ui_x7;
+ s32 tmax, tmin;
+ s32 coeff = 1000; /* Precision, should avoid overflow */
+ s32 temp;
+
+ if (!bit_rate || !esc_rate)
+ return -EINVAL;
+
+ ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
+ ui_x7 = ui * 7;
+
+ temp = S_DIV_ROUND_UP(38 * coeff, ui_x7);
+ tmin = max_t(s32, temp, 0);
+ temp = (95 * coeff) / ui_x7;
+ tmax = max_t(s32, temp, 0);
+ timing->clk_prepare = linear_inter(tmax, tmin, 50, 0, false);
+
+ tmin = DIV_ROUND_UP(50 * coeff, ui_x7);
+ tmax = 255;
+ timing->hs_rqst = linear_inter(tmax, tmin, 1, 0, false);
+
+ tmin = DIV_ROUND_UP(100 * coeff, ui_x7) - 1;
+ tmax = 255;
+ timing->hs_exit = linear_inter(tmax, tmin, 10, 0, false);
+
+ tmin = 1;
+ tmax = 32;
+ timing->shared_timings.clk_post = linear_inter(tmax, tmin, 80, 0, false);
+
+ tmin = min_t(s32, 64, S_DIV_ROUND_UP(262 * coeff, ui_x7) - 1);
+ tmax = 64;
+ timing->shared_timings.clk_pre = linear_inter(tmax, tmin, 20, 0, false);
+
+ DBG("%d, %d, %d, %d, %d",
+ timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
+ timing->clk_prepare, timing->hs_exit, timing->hs_rqst);
+
+ return 0;
+}
+
static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
{
struct regulator_bulk_data *s = phy->supplies;
@@ -593,6 +639,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
.data = &dsi_phy_7nm_cfgs },
{ .compatible = "qcom,dsi-phy-7nm-8150",
.data = &dsi_phy_7nm_8150_cfgs },
+ { .compatible = "qcom,sc7280-dsi-phy-7nm",
+ .data = &dsi_phy_7nm_7280_cfgs },
#endif
{}
};
@@ -625,17 +673,13 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
{
struct msm_dsi_phy *phy;
struct device *dev = &pdev->dev;
- const struct of_device_id *match;
+ u32 phy_type;
int ret;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
- match = of_match_node(dsi_phy_dt_match, dev->of_node);
- if (!match)
- return -ENODEV;
-
phy->provided_clocks = devm_kzalloc(dev,
struct_size(phy->provided_clocks, hws, NUM_PROVIDED_CLKS),
GFP_KERNEL);
@@ -644,7 +688,10 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
phy->provided_clocks->num = NUM_PROVIDED_CLKS;
- phy->cfg = match->data;
+ phy->cfg = of_device_get_match_data(&pdev->dev);
+ if (!phy->cfg)
+ return -ENODEV;
+
phy->pdev = pdev;
phy->id = dsi_phy_get_id(phy);
@@ -657,6 +704,8 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
phy->regulator_ldo_mode = of_property_read_bool(dev->of_node,
"qcom,dsi-phy-regulator-ldo-mode");
+ if (!of_property_read_u32(dev->of_node, "phy-type", &phy_type))
+ phy->cphy_mode = (phy_type == PHY_TYPE_CPHY);
phy->base = msm_ioremap_size(pdev, "dsi_phy", "DSI_PHY", &phy->base_size);
if (IS_ERR(phy->base)) {
@@ -754,7 +803,8 @@ void __exit msm_dsi_phy_driver_unregister(void)
}
int msm_dsi_phy_enable(struct msm_dsi_phy *phy,
- struct msm_dsi_phy_clk_request *clk_req)
+ struct msm_dsi_phy_clk_request *clk_req,
+ struct msm_dsi_phy_shared_timings *shared_timings)
{
struct device *dev = &phy->pdev->dev;
int ret;
@@ -782,6 +832,9 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy,
goto phy_en_fail;
}
+ memcpy(shared_timings, &phy->timing.shared_timings,
+ sizeof(*shared_timings));
+
/*
* Resetting DSI PHY silently changes its PLL registers to reset status,
* which will confuse clock driver and result in wrong output rate of
@@ -821,13 +874,6 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
dsi_phy_disable_resource(phy);
}
-void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
- struct msm_dsi_phy_shared_timings *shared_timings)
-{
- memcpy(shared_timings, &phy->timing.shared_timings,
- sizeof(*shared_timings));
-}
-
void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
enum msm_dsi_phy_usecase uc)
{
@@ -835,6 +881,15 @@ void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
phy->usecase = uc;
}
+/* Returns true if we have to clear DSI_LANE_CTRL.HS_REQ_SEL_PHY */
+bool msm_dsi_phy_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
+{
+ if (!phy || !phy->cfg->ops.set_continuous_clock)
+ return false;
+
+ return phy->cfg->ops.set_continuous_clock(phy, enable);
+}
+
int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy,
struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
{
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 5b0feef87127..b91303ada74f 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -24,6 +24,7 @@ struct msm_dsi_phy_ops {
void (*disable)(struct msm_dsi_phy *phy);
void (*save_pll_state)(struct msm_dsi_phy *phy);
int (*restore_pll_state)(struct msm_dsi_phy *phy);
+ bool (*set_continuous_clock)(struct msm_dsi_phy *phy, bool enable);
};
struct msm_dsi_phy_cfg {
@@ -51,6 +52,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs;
struct msm_dsi_dphy_timing {
u32 clk_zero;
@@ -99,6 +101,7 @@ struct msm_dsi_phy {
enum msm_dsi_phy_usecase usecase;
bool regulator_ldo_mode;
+ bool cphy_mode;
struct clk_hw *vco_hw;
bool pll_on;
@@ -119,5 +122,7 @@ int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
struct msm_dsi_phy_clk_request *clk_req);
int msm_dsi_dphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
struct msm_dsi_phy_clk_request *clk_req);
+int msm_dsi_cphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
+ struct msm_dsi_phy_clk_request *clk_req);
#endif /* __DSI_PHY_H__ */
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
index e46b10fc793a..d8128f50b0dd 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
@@ -84,7 +84,7 @@ struct dsi_pll_10nm {
#define to_pll_10nm(x) container_of(x, struct dsi_pll_10nm, clk_hw)
/*
- * Global list of private DSI PLL struct pointers. We need this for Dual DSI
+ * Global list of private DSI PLL struct pointers. We need this for bonded DSI
* mode, where the master PLL's clk_ops needs access the slave's private data
*/
static struct dsi_pll_10nm *pll_10nm_list[DSI_MAX];
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
index a34cf151c517..d13552b2213b 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
@@ -86,7 +86,7 @@ struct dsi_pll_14nm {
/*
* Private struct for N1/N2 post-divider clocks. These clocks are similar to
* the generic clk_divider class of clocks. The only difference is that it
- * also sets the slave DSI PLL's post-dividers if in Dual DSI mode
+ * also sets the slave DSI PLL's post-dividers if in bonded DSI mode
*/
struct dsi_pll_14nm_postdiv {
struct clk_hw hw;
@@ -102,7 +102,7 @@ struct dsi_pll_14nm_postdiv {
#define to_pll_14nm_postdiv(_hw) container_of(_hw, struct dsi_pll_14nm_postdiv, hw)
/*
- * Global list of private DSI PLL struct pointers. We need this for Dual DSI
+ * Global list of private DSI PLL struct pointers. We need this for bonded DSI
* mode, where the master PLL's clk_ops needs access the slave's private data
*/
static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX];
@@ -658,7 +658,7 @@ static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
val |= value << shift;
dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val);
- /* If we're master in dual DSI mode, then the slave PLL's post-dividers
+ /* If we're master in bonded DSI mode, then the slave PLL's post-dividers
* follow the master's post dividers
*/
if (pll_14nm->phy->usecase == MSM_DSI_PHY_MASTER) {
@@ -1050,7 +1050,7 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs = {
.reg_cfg = {
.num = 1,
.regs = {
- {"vcca", 17000, 32},
+ {"vcca", 73400, 32},
},
},
.ops = {
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index 7c23d4c47338..cb297b08458e 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -83,7 +83,7 @@ struct dsi_pll_7nm {
#define to_pll_7nm(x) container_of(x, struct dsi_pll_7nm, clk_hw)
/*
- * Global list of private DSI PLL struct pointers. We need this for Dual DSI
+ * Global list of private DSI PLL struct pointers. We need this for bonded DSI
* mode, where the master PLL's clk_ops needs access the slave's private data
*/
static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX];
@@ -256,7 +256,7 @@ static void dsi_pll_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *confi
(config->frac_div_start & 0x30000) >> 16);
dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, 0x40);
dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
- dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 for CPHY */
+ dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, pll->phy->cphy_mode ? 0x00 : 0x10);
dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, config->pll_clock_inverters);
}
@@ -642,7 +642,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */
hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent,
- CLK_SET_RATE_PARENT, 1, 8);
+ CLK_SET_RATE_PARENT, 1,
+ pll_7nm->phy->cphy_mode ? 7 : 8);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
goto fail;
@@ -663,32 +664,47 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
- hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent,
- 0, 1, 4);
+ if (pll_7nm->phy->cphy_mode)
+ hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 2, 7);
+ else
+ hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 4);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
goto fail;
}
- snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
- snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id);
- snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id);
- snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
- snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
-
- hw = devm_clk_hw_register_mux(dev, clk_name,
- ((const char *[]){
- parent, parent2, parent3, parent4
- }), 4, 0, pll_7nm->phy->base +
- REG_DSI_7nm_PHY_CMN_CLK_CFG1,
- 0, 2, 0, NULL);
- if (IS_ERR(hw)) {
- ret = PTR_ERR(hw);
- goto fail;
+ /* in CPHY mode, pclk_mux will always have post_out_div as parent
+ * don't register a pclk_mux clock and just use post_out_div instead
+ */
+ if (pll_7nm->phy->cphy_mode) {
+ u32 data;
+
+ data = dsi_phy_read(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+ dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data | 3);
+
+ snprintf(parent, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
+ } else {
+ snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
+ snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id);
+ snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id);
+ snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
+ snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
+
+ hw = devm_clk_hw_register_mux(dev, clk_name,
+ ((const char *[]){
+ parent, parent2, parent3, parent4
+ }), 4, 0, pll_7nm->phy->base +
+ REG_DSI_7nm_PHY_CMN_CLK_CFG1,
+ 0, 2, 0, NULL);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto fail;
+ }
+
+ snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
}
snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->phy->id);
- snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
/* PIX CLK DIV : DIV_CTRL_7_4*/
hw = devm_clk_hw_register_divider(dev, clk_name, parent,
@@ -813,15 +829,21 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
struct msm_dsi_dphy_timing *timing = &phy->timing;
void __iomem *base = phy->base;
bool less_than_1500_mhz;
- u32 vreg_ctrl_0, glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0;
+ u32 vreg_ctrl_0, vreg_ctrl_1, lane_ctrl0;
+ u32 glbl_pemph_ctrl_0;
+ u32 glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0;
u32 glbl_rescode_top_ctrl, glbl_rescode_bot_ctrl;
u32 data;
DBG("");
- if (msm_dsi_dphy_timing_calc_v4(timing, clk_req)) {
+ if (phy->cphy_mode)
+ ret = msm_dsi_cphy_timing_calc_v4(timing, clk_req);
+ else
+ ret = msm_dsi_dphy_timing_calc_v4(timing, clk_req);
+ if (ret) {
DRM_DEV_ERROR(&phy->pdev->dev,
- "%s: D-PHY timing calculation failed\n", __func__);
+ "%s: PHY timing calculation failed\n", __func__);
return -EINVAL;
}
@@ -842,6 +864,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
/* Alter PHY configurations if data rate less than 1.5GHZ*/
less_than_1500_mhz = (clk_req->bitclk_rate <= 1500000000);
+ /* For C-PHY, no low power settings for lower clk rate */
+ if (phy->cphy_mode)
+ less_than_1500_mhz = false;
+
if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) {
vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52;
glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00;
@@ -856,6 +882,17 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
glbl_rescode_bot_ctrl = 0x3c;
}
+ if (phy->cphy_mode) {
+ vreg_ctrl_0 = 0x51;
+ vreg_ctrl_1 = 0x55;
+ glbl_pemph_ctrl_0 = 0x11;
+ lane_ctrl0 = 0x17;
+ } else {
+ vreg_ctrl_1 = 0x5c;
+ glbl_pemph_ctrl_0 = 0x00;
+ lane_ctrl0 = 0x1f;
+ }
+
/* de-assert digital and pll power down */
data = BIT(6) | BIT(5);
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, data);
@@ -876,15 +913,22 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG0, 0x21);
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG1, 0x84);
+ if (phy->cphy_mode)
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_CTRL, BIT(6));
+
/* Enable LDO */
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_0, vreg_ctrl_0);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_1, 0x5c);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_1, vreg_ctrl_1);
+
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x00);
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL,
glbl_str_swi_cal_sel_ctrl);
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_HSTX_STR_CTRL_0,
glbl_hstx_str_ctrl_0);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0, 0x00);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0,
+ glbl_pemph_ctrl_0);
+ if (phy->cphy_mode)
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_1, 0x01);
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_TOP_CTRL,
glbl_rescode_top_ctrl);
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_BOT_CTRL,
@@ -894,10 +938,11 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
/* Remove power down from all blocks */
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, 0x7f);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, 0x1f);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, lane_ctrl0);
/* Select full-rate mode */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_2, 0x40);
+ if (!phy->cphy_mode)
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_2, 0x40);
ret = dsi_7nm_set_usecase(phy);
if (ret) {
@@ -907,22 +952,36 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
}
/* DSI PHY timings */
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1, timing->clk_zero);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2, timing->clk_prepare);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3, timing->clk_trail);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5, timing->hs_zero);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->hs_prepare);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7, timing->hs_trail);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12,
- timing->shared_timings.clk_pre);
- dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13,
- timing->shared_timings.clk_post);
+ if (phy->cphy_mode) {
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5,
+ timing->shared_timings.clk_pre);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->clk_prepare);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7,
+ timing->shared_timings.clk_post);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
+ } else {
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1, timing->clk_zero);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2, timing->clk_prepare);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3, timing->clk_trail);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5, timing->hs_zero);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->hs_prepare);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7, timing->hs_trail);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12,
+ timing->shared_timings.clk_pre);
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13,
+ timing->shared_timings.clk_post);
+ }
/* DSI lane settings */
dsi_phy_hw_v4_0_lane_settings(phy);
@@ -932,6 +991,21 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
return 0;
}
+static bool dsi_7nm_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
+{
+ void __iomem *base = phy->base;
+ u32 data;
+
+ data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1);
+ if (enable)
+ data |= BIT(5) | BIT(6);
+ else
+ data &= ~(BIT(5) | BIT(6));
+ dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1, data);
+
+ return enable;
+}
+
static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
{
void __iomem *base = phy->base;
@@ -972,6 +1046,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = {
.pll_init = dsi_pll_7nm_init,
.save_pll_state = dsi_7nm_pll_save_state,
.restore_pll_state = dsi_7nm_pll_restore_state,
+ .set_continuous_clock = dsi_7nm_set_continuous_clock,
},
.min_pll_rate = 600000000UL,
#ifdef CONFIG_64BIT
@@ -998,9 +1073,36 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = {
.pll_init = dsi_pll_7nm_init,
.save_pll_state = dsi_7nm_pll_save_state,
.restore_pll_state = dsi_7nm_pll_restore_state,
+ .set_continuous_clock = dsi_7nm_set_continuous_clock,
},
.min_pll_rate = 1000000000UL,
.max_pll_rate = 3500000000UL,
.io_start = { 0xae94400, 0xae96400 },
.num_dsi_phy = 2,
};
+
+const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs = {
+ .has_phy_lane = true,
+ .reg_cfg = {
+ .num = 1,
+ .regs = {
+ {"vdds", 37550, 0},
+ },
+ },
+ .ops = {
+ .enable = dsi_7nm_phy_enable,
+ .disable = dsi_7nm_phy_disable,
+ .pll_init = dsi_pll_7nm_init,
+ .save_pll_state = dsi_7nm_pll_save_state,
+ .restore_pll_state = dsi_7nm_pll_restore_state,
+ },
+ .min_pll_rate = 600000000UL,
+#ifdef CONFIG_64BIT
+ .max_pll_rate = 5000000000ULL,
+#else
+ .max_pll_rate = ULONG_MAX,
+#endif
+ .io_start = { 0xae94400 },
+ .num_dsi_phy = 1,
+ .quirks = DSI_PHY_7NM_QUIRK_V4_1,
+};
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 9b8fa2ad0d84..2e6fc185e54d 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -14,7 +14,6 @@
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
-#include <drm/drm_irq.h>
#include <drm/drm_prime.h>
#include <drm/drm_of.h>
#include <drm/drm_vblank.h>
@@ -201,6 +200,71 @@ void msm_rmw(void __iomem *addr, u32 mask, u32 or)
msm_writel(val | or, addr);
}
+static irqreturn_t msm_irq(int irq, void *arg)
+{
+ struct drm_device *dev = arg;
+ struct msm_drm_private *priv = dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+
+ BUG_ON(!kms);
+
+ return kms->funcs->irq(kms);
+}
+
+static void msm_irq_preinstall(struct drm_device *dev)
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+
+ BUG_ON(!kms);
+
+ kms->funcs->irq_preinstall(kms);
+}
+
+static int msm_irq_postinstall(struct drm_device *dev)
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+
+ BUG_ON(!kms);
+
+ if (kms->funcs->irq_postinstall)
+ return kms->funcs->irq_postinstall(kms);
+
+ return 0;
+}
+
+static int msm_irq_install(struct drm_device *dev, unsigned int irq)
+{
+ int ret;
+
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ msm_irq_preinstall(dev);
+
+ ret = request_irq(irq, msm_irq, 0, dev->driver->name, dev);
+ if (ret)
+ return ret;
+
+ ret = msm_irq_postinstall(dev);
+ if (ret) {
+ free_irq(irq, dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void msm_irq_uninstall(struct drm_device *dev)
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+
+ kms->funcs->irq_uninstall(kms);
+ free_irq(kms->irq, dev);
+}
+
struct msm_vblank_work {
struct work_struct work;
int crtc_id;
@@ -265,7 +329,7 @@ static int msm_drm_uninit(struct device *dev)
}
/* We must cancel and cleanup any pending vblank enable/disable
- * work before drm_irq_uninstall() to avoid work re-enabling an
+ * work before msm_irq_uninstall() to avoid work re-enabling an
* irq after uninstall has disabled it.
*/
@@ -294,7 +358,7 @@ static int msm_drm_uninit(struct device *dev)
drm_mode_config_cleanup(ddev);
pm_runtime_get_sync(dev);
- drm_irq_uninstall(ddev);
+ msm_irq_uninstall(ddev);
pm_runtime_put_sync(dev);
if (kms && kms->funcs)
@@ -539,6 +603,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
if (IS_ERR(priv->event_thread[i].worker)) {
ret = PTR_ERR(priv->event_thread[i].worker);
DRM_DEV_ERROR(dev, "failed to create crtc_event kthread\n");
+ ret = PTR_ERR(priv->event_thread[i].worker);
goto err_msm_uninit;
}
@@ -553,7 +618,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
if (kms) {
pm_runtime_get_sync(dev);
- ret = drm_irq_install(ddev, kms->irq);
+ ret = msm_irq_install(ddev, kms->irq);
pm_runtime_put_sync(dev);
if (ret < 0) {
DRM_DEV_ERROR(dev, "failed to install IRQ handler\n");
@@ -662,43 +727,6 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file)
context_close(ctx);
}
-static irqreturn_t msm_irq(int irq, void *arg)
-{
- struct drm_device *dev = arg;
- struct msm_drm_private *priv = dev->dev_private;
- struct msm_kms *kms = priv->kms;
- BUG_ON(!kms);
- return kms->funcs->irq(kms);
-}
-
-static void msm_irq_preinstall(struct drm_device *dev)
-{
- struct msm_drm_private *priv = dev->dev_private;
- struct msm_kms *kms = priv->kms;
- BUG_ON(!kms);
- kms->funcs->irq_preinstall(kms);
-}
-
-static int msm_irq_postinstall(struct drm_device *dev)
-{
- struct msm_drm_private *priv = dev->dev_private;
- struct msm_kms *kms = priv->kms;
- BUG_ON(!kms);
-
- if (kms->funcs->irq_postinstall)
- return kms->funcs->irq_postinstall(kms);
-
- return 0;
-}
-
-static void msm_irq_uninstall(struct drm_device *dev)
-{
- struct msm_drm_private *priv = dev->dev_private;
- struct msm_kms *kms = priv->kms;
- BUG_ON(!kms);
- kms->funcs->irq_uninstall(kms);
-}
-
int msm_crtc_enable_vblank(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -911,6 +939,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
ktime_t timeout = to_ktime(args->timeout);
struct msm_gpu_submitqueue *queue;
struct msm_gpu *gpu = priv->gpu;
+ struct dma_fence *fence;
int ret;
if (args->pad) {
@@ -925,10 +954,35 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
if (!queue)
return -ENOENT;
- ret = msm_wait_fence(gpu->rb[queue->prio]->fctx, args->fence, &timeout,
- true);
+ /*
+ * Map submitqueue scoped "seqno" (which is actually an idr key)
+ * back to underlying dma-fence
+ *
+ * The fence is removed from the fence_idr when the submit is
+ * retired, so if the fence is not found it means there is nothing
+ * to wait for
+ */
+ ret = mutex_lock_interruptible(&queue->lock);
+ if (ret)
+ return ret;
+ fence = idr_find(&queue->fence_idr, args->fence);
+ if (fence)
+ fence = dma_fence_get_rcu(fence);
+ mutex_unlock(&queue->lock);
+
+ if (!fence)
+ return 0;
+
+ ret = dma_fence_wait_timeout(fence, true, timeout_to_jiffies(&timeout));
+ if (ret == 0) {
+ ret = -ETIMEDOUT;
+ } else if (ret != -ERESTARTSYS) {
+ ret = 0;
+ }
+ dma_fence_put(fence);
msm_submitqueue_put(queue);
+
return ret;
}
@@ -1004,17 +1058,7 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
};
-static const struct file_operations fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
- .compat_ioctl = drm_compat_ioctl,
- .poll = drm_poll,
- .read = drm_read,
- .llseek = no_llseek,
- .mmap = msm_gem_mmap,
-};
+DEFINE_DRM_GEM_FOPS(fops);
static const struct drm_driver msm_driver = {
.driver_features = DRIVER_GEM |
@@ -1025,16 +1069,12 @@ static const struct drm_driver msm_driver = {
.open = msm_open,
.postclose = msm_postclose,
.lastclose = drm_fb_helper_lastclose,
- .irq_handler = msm_irq,
- .irq_preinstall = msm_irq_preinstall,
- .irq_postinstall = msm_irq_postinstall,
- .irq_uninstall = msm_irq_uninstall,
.dumb_create = msm_gem_dumb_create,
.dumb_map_offset = msm_gem_dumb_map_offset,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import_sg_table = msm_gem_prime_import_sg_table,
- .gem_prime_mmap = msm_gem_prime_mmap,
+ .gem_prime_mmap = drm_gem_prime_mmap,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = msm_debugfs_init,
#endif
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 1a48a709ffb3..8b005d1ac899 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -309,7 +309,6 @@ void msm_gem_shrinker_cleanup(struct drm_device *dev);
struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
int msm_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map);
-int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg);
int msm_gem_prime_pin(struct drm_gem_object *obj);
@@ -350,7 +349,9 @@ void __exit msm_dsi_unregister(void);
int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
struct drm_encoder *encoder);
void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi);
-
+bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi);
+bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi);
+bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi);
#else
static inline void __init msm_dsi_register(void)
{
@@ -367,7 +368,18 @@ static inline int msm_dsi_modeset_init(struct msm_dsi *msm_dsi,
static inline void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi)
{
}
-
+static inline bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi)
+{
+ return false;
+}
+static inline bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi)
+{
+ return false;
+}
+static inline bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi)
+{
+ return false;
+}
#endif
#ifdef CONFIG_DRM_MSM_DP
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 227404077e39..0daaeb54ff6f 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -8,13 +8,12 @@
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_prime.h>
#include "msm_drv.h"
#include "msm_gem.h"
#include "msm_kms.h"
-extern int msm_gem_mmap_obj(struct drm_gem_object *obj,
- struct vm_area_struct *vma);
static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma);
/*
@@ -48,15 +47,8 @@ static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
struct msm_fbdev *fbdev = to_msm_fbdev(helper);
struct drm_gem_object *bo = msm_framebuffer_bo(fbdev->fb, 0);
- int ret = 0;
- ret = drm_gem_mmap_obj(bo, bo->size, vma);
- if (ret) {
- pr_err("%s:drm_gem_mmap_obj fail\n", __func__);
- return ret;
- }
-
- return msm_gem_mmap_obj(bo, vma);
+ return drm_gem_prime_mmap(bo, vma);
}
static int msm_fbdev_create(struct drm_fb_helper *helper,
@@ -169,7 +161,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
}
/* the fw fb could be anywhere in memory */
- ret = drm_aperture_remove_framebuffers(false, "msm");
+ ret = drm_aperture_remove_framebuffers(false, dev->driver);
if (ret)
goto fini;
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index cd59a5918038..f2cece542c3f 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -11,7 +11,8 @@
struct msm_fence_context *
-msm_fence_context_alloc(struct drm_device *dev, const char *name)
+msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr,
+ const char *name)
{
struct msm_fence_context *fctx;
@@ -22,7 +23,7 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name)
fctx->dev = dev;
strncpy(fctx->name, name, sizeof(fctx->name));
fctx->context = dma_fence_context_alloc(1);
- init_waitqueue_head(&fctx->event);
+ fctx->fenceptr = fenceptr;
spin_lock_init(&fctx->spinlock);
return fctx;
@@ -35,46 +36,12 @@ void msm_fence_context_free(struct msm_fence_context *fctx)
static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fence)
{
- return (int32_t)(fctx->completed_fence - fence) >= 0;
-}
-
-/* legacy path for WAIT_FENCE ioctl: */
-int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
- ktime_t *timeout, bool interruptible)
-{
- int ret;
-
- if (fence > fctx->last_fence) {
- DRM_ERROR_RATELIMITED("%s: waiting on invalid fence: %u (of %u)\n",
- fctx->name, fence, fctx->last_fence);
- return -EINVAL;
- }
-
- if (!timeout) {
- /* no-wait: */
- ret = fence_completed(fctx, fence) ? 0 : -EBUSY;
- } else {
- unsigned long remaining_jiffies = timeout_to_jiffies(timeout);
-
- if (interruptible)
- ret = wait_event_interruptible_timeout(fctx->event,
- fence_completed(fctx, fence),
- remaining_jiffies);
- else
- ret = wait_event_timeout(fctx->event,
- fence_completed(fctx, fence),
- remaining_jiffies);
-
- if (ret == 0) {
- DBG("timeout waiting for fence: %u (completed: %u)",
- fence, fctx->completed_fence);
- ret = -ETIMEDOUT;
- } else if (ret != -ERESTARTSYS) {
- ret = 0;
- }
- }
-
- return ret;
+ /*
+ * Note: Check completed_fence first, as fenceptr is in a write-combine
+ * mapping, so it will be more expensive to read.
+ */
+ return (int32_t)(fctx->completed_fence - fence) >= 0 ||
+ (int32_t)(*fctx->fenceptr - fence) >= 0;
}
/* called from workqueue */
@@ -83,8 +50,6 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
spin_lock(&fctx->spinlock);
fctx->completed_fence = max(fence, fctx->completed_fence);
spin_unlock(&fctx->spinlock);
-
- wake_up_all(&fctx->event);
}
struct msm_fence {
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
index 2d9af66dcca5..4783db528bcc 100644
--- a/drivers/gpu/drm/msm/msm_fence.h
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -9,23 +9,53 @@
#include "msm_drv.h"
+/**
+ * struct msm_fence_context - fence context for gpu
+ *
+ * Each ringbuffer has a single fence context, with the GPU writing an
+ * incrementing fence seqno at the end of each submit
+ */
struct msm_fence_context {
struct drm_device *dev;
+ /** name: human readable name for fence timeline */
char name[32];
+ /** context: see dma_fence_context_alloc() */
unsigned context;
- /* last_fence == completed_fence --> no pending work */
- uint32_t last_fence; /* last assigned fence */
- uint32_t completed_fence; /* last completed fence */
- wait_queue_head_t event;
+
+ /**
+ * last_fence:
+ *
+ * Last assigned fence, incremented each time a fence is created
+ * on this fence context. If last_fence == completed_fence,
+ * there is no remaining pending work
+ */
+ uint32_t last_fence;
+
+ /**
+ * completed_fence:
+ *
+ * The last completed fence, updated from the CPU after interrupt
+ * from GPU
+ */
+ uint32_t completed_fence;
+
+ /**
+ * fenceptr:
+ *
+ * The address that the GPU directly writes with completed fence
+ * seqno. This can be ahead of completed_fence. We can peek at
+ * this to see if a fence has already signaled but the CPU hasn't
+ * gotten around to handling the irq and updating completed_fence
+ */
+ volatile uint32_t *fenceptr;
+
spinlock_t spinlock;
};
struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
- const char *name);
+ volatile uint32_t *fenceptr, const char *name);
void msm_fence_context_free(struct msm_fence_context *fctx);
-int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
- ktime_t *timeout, bool interruptible);
void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
struct dma_fence * msm_fence_alloc(struct msm_fence_context *fctx);
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 1e8a971a86f2..22308a1b66fc 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -131,7 +131,6 @@ static struct page **get_pages(struct drm_gem_object *obj)
if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED))
sync_for_device(msm_obj);
- GEM_WARN_ON(msm_obj->active_count);
update_inactive(msm_obj);
}
@@ -218,31 +217,6 @@ static pgprot_t msm_gem_pgprot(struct msm_gem_object *msm_obj, pgprot_t prot)
return prot;
}
-int msm_gem_mmap_obj(struct drm_gem_object *obj,
- struct vm_area_struct *vma)
-{
- struct msm_gem_object *msm_obj = to_msm_bo(obj);
-
- vma->vm_flags &= ~VM_PFNMAP;
- vma->vm_flags |= VM_MIXEDMAP;
- vma->vm_page_prot = msm_gem_pgprot(msm_obj, vm_get_page_prot(vma->vm_flags));
-
- return 0;
-}
-
-int msm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- int ret;
-
- ret = drm_gem_mmap(filp, vma);
- if (ret) {
- DBG("mmap failed: %d", ret);
- return ret;
- }
-
- return msm_gem_mmap_obj(vma->vm_private_data, vma);
-}
-
static vm_fault_t msm_gem_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
@@ -804,41 +778,6 @@ void msm_gem_vunmap(struct drm_gem_object *obj)
msm_obj->vaddr = NULL;
}
-/* must be called before _move_to_active().. */
-int msm_gem_sync_object(struct drm_gem_object *obj,
- struct msm_fence_context *fctx, bool exclusive)
-{
- struct dma_resv_list *fobj;
- struct dma_fence *fence;
- int i, ret;
-
- fobj = dma_resv_shared_list(obj->resv);
- if (!fobj || (fobj->shared_count == 0)) {
- fence = dma_resv_excl_fence(obj->resv);
- /* don't need to wait on our own fences, since ring is fifo */
- if (fence && (fence->context != fctx->context)) {
- ret = dma_fence_wait(fence, true);
- if (ret)
- return ret;
- }
- }
-
- if (!exclusive || !fobj)
- return 0;
-
- for (i = 0; i < fobj->shared_count; i++) {
- fence = rcu_dereference_protected(fobj->shared[i],
- dma_resv_held(obj->resv));
- if (fence->context != fctx->context) {
- ret = dma_fence_wait(fence, true);
- if (ret)
- return ret;
- }
- }
-
- return 0;
-}
-
void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -848,14 +787,12 @@ void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu)
GEM_WARN_ON(!msm_gem_is_locked(obj));
GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED);
GEM_WARN_ON(msm_obj->dontneed);
- GEM_WARN_ON(!msm_obj->sgt);
if (msm_obj->active_count++ == 0) {
mutex_lock(&priv->mm_lock);
if (msm_obj->evictable)
mark_unevictable(msm_obj);
- list_del(&msm_obj->mm_list);
- list_add_tail(&msm_obj->mm_list, &gpu->active_list);
+ list_move_tail(&msm_obj->mm_list, &gpu->active_list);
mutex_unlock(&priv->mm_lock);
}
}
@@ -1062,7 +999,7 @@ void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
}
#endif
-/* don't call directly! Use drm_gem_object_put_locked() and friends */
+/* don't call directly! Use drm_gem_object_put() */
void msm_gem_free_object(struct drm_gem_object *obj)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -1114,6 +1051,17 @@ void msm_gem_free_object(struct drm_gem_object *obj)
kfree(msm_obj);
}
+static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
+{
+ struct msm_gem_object *msm_obj = to_msm_bo(obj);
+
+ vma->vm_flags &= ~VM_PFNMAP;
+ vma->vm_flags |= VM_MIXEDMAP | VM_DONTEXPAND;
+ vma->vm_page_prot = msm_gem_pgprot(msm_obj, vm_get_page_prot(vma->vm_flags));
+
+ return 0;
+}
+
/* convenience method to construct a GEM buffer object, and userspace handle */
int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
uint32_t size, uint32_t flags, uint32_t *handle,
@@ -1151,6 +1099,7 @@ static const struct drm_gem_object_funcs msm_gem_object_funcs = {
.get_sg_table = msm_gem_prime_get_sg_table,
.vmap = msm_gem_prime_vmap,
.vunmap = msm_gem_prime_vunmap,
+ .mmap = msm_gem_object_mmap,
.vm_ops = &vm_ops,
};
@@ -1183,7 +1132,6 @@ static int msm_gem_new_impl(struct drm_device *dev,
msm_obj->flags = flags;
msm_obj->madv = MSM_MADV_WILLNEED;
- INIT_LIST_HEAD(&msm_obj->submit_entry);
INIT_LIST_HEAD(&msm_obj->vmas);
*obj = &msm_obj->base;
@@ -1192,8 +1140,7 @@ static int msm_gem_new_impl(struct drm_device *dev,
return 0;
}
-static struct drm_gem_object *_msm_gem_new(struct drm_device *dev,
- uint32_t size, uint32_t flags, bool struct_mutex_locked)
+struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags)
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_gem_object *msm_obj;
@@ -1280,26 +1227,10 @@ static struct drm_gem_object *_msm_gem_new(struct drm_device *dev,
return obj;
fail:
- if (struct_mutex_locked) {
- drm_gem_object_put_locked(obj);
- } else {
- drm_gem_object_put(obj);
- }
+ drm_gem_object_put(obj);
return ERR_PTR(ret);
}
-struct drm_gem_object *msm_gem_new_locked(struct drm_device *dev,
- uint32_t size, uint32_t flags)
-{
- return _msm_gem_new(dev, size, flags, true);
-}
-
-struct drm_gem_object *msm_gem_new(struct drm_device *dev,
- uint32_t size, uint32_t flags)
-{
- return _msm_gem_new(dev, size, flags, false);
-}
-
struct drm_gem_object *msm_gem_import(struct drm_device *dev,
struct dma_buf *dmabuf, struct sg_table *sgt)
{
@@ -1358,12 +1289,12 @@ fail:
return ERR_PTR(ret);
}
-static void *_msm_gem_kernel_new(struct drm_device *dev, uint32_t size,
+void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size,
uint32_t flags, struct msm_gem_address_space *aspace,
- struct drm_gem_object **bo, uint64_t *iova, bool locked)
+ struct drm_gem_object **bo, uint64_t *iova)
{
void *vaddr;
- struct drm_gem_object *obj = _msm_gem_new(dev, size, flags, locked);
+ struct drm_gem_object *obj = msm_gem_new(dev, size, flags);
int ret;
if (IS_ERR(obj))
@@ -1387,42 +1318,21 @@ static void *_msm_gem_kernel_new(struct drm_device *dev, uint32_t size,
return vaddr;
err:
- if (locked)
- drm_gem_object_put_locked(obj);
- else
- drm_gem_object_put(obj);
+ drm_gem_object_put(obj);
return ERR_PTR(ret);
}
-void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size,
- uint32_t flags, struct msm_gem_address_space *aspace,
- struct drm_gem_object **bo, uint64_t *iova)
-{
- return _msm_gem_kernel_new(dev, size, flags, aspace, bo, iova, false);
-}
-
-void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size,
- uint32_t flags, struct msm_gem_address_space *aspace,
- struct drm_gem_object **bo, uint64_t *iova)
-{
- return _msm_gem_kernel_new(dev, size, flags, aspace, bo, iova, true);
-}
-
void msm_gem_kernel_put(struct drm_gem_object *bo,
- struct msm_gem_address_space *aspace, bool locked)
+ struct msm_gem_address_space *aspace)
{
if (IS_ERR_OR_NULL(bo))
return;
msm_gem_put_vaddr(bo);
msm_gem_unpin_iova(bo, aspace);
-
- if (locked)
- drm_gem_object_put_locked(bo);
- else
- drm_gem_object_put(bo);
+ drm_gem_object_put(bo);
}
void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...)
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 405f8411e395..e39a8e7ad843 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -9,6 +9,7 @@
#include <linux/kref.h>
#include <linux/dma-resv.h>
+#include "drm/gpu_scheduler.h"
#include "msm_drv.h"
/* Make all GEM related WARN_ON()s ratelimited.. when things go wrong they
@@ -87,13 +88,6 @@ struct msm_gem_object {
*/
struct list_head mm_list;
- /* Transiently in the process of submit ioctl, objects associated
- * with the submit are on submit->bo_list.. this only lasts for
- * the duration of the ioctl, so one bo can never be on multiple
- * submit lists.
- */
- struct list_head submit_entry;
-
struct page **pages;
struct sg_table *sgt;
void *vaddr;
@@ -112,9 +106,6 @@ struct msm_gem_object {
};
#define to_msm_bo(x) container_of(x, struct msm_gem_object, base)
-int msm_gem_mmap_obj(struct drm_gem_object *obj,
- struct vm_area_struct *vma);
-int msm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj);
int msm_gem_get_iova(struct drm_gem_object *obj,
struct msm_gem_address_space *aspace, uint64_t *iova);
@@ -143,8 +134,6 @@ void *msm_gem_get_vaddr_active(struct drm_gem_object *obj);
void msm_gem_put_vaddr_locked(struct drm_gem_object *obj);
void msm_gem_put_vaddr(struct drm_gem_object *obj);
int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv);
-int msm_gem_sync_object(struct drm_gem_object *obj,
- struct msm_fence_context *fctx, bool exclusive);
void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu);
void msm_gem_active_put(struct drm_gem_object *obj);
int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
@@ -154,16 +143,11 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
uint32_t size, uint32_t flags, uint32_t *handle, char *name);
struct drm_gem_object *msm_gem_new(struct drm_device *dev,
uint32_t size, uint32_t flags);
-struct drm_gem_object *msm_gem_new_locked(struct drm_device *dev,
- uint32_t size, uint32_t flags);
void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size,
uint32_t flags, struct msm_gem_address_space *aspace,
struct drm_gem_object **bo, uint64_t *iova);
-void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size,
- uint32_t flags, struct msm_gem_address_space *aspace,
- struct drm_gem_object **bo, uint64_t *iova);
void msm_gem_kernel_put(struct drm_gem_object *bo,
- struct msm_gem_address_space *aspace, bool locked);
+ struct msm_gem_address_space *aspace);
struct drm_gem_object *msm_gem_import(struct drm_device *dev,
struct dma_buf *dmabuf, struct sg_table *sgt);
__printf(2, 3)
@@ -313,19 +297,34 @@ void msm_gem_vunmap(struct drm_gem_object *obj);
/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
* associated with the cmdstream submission for synchronization (and
- * make it easier to unwind when things go wrong, etc). This only
- * lasts for the duration of the submit-ioctl.
+ * make it easier to unwind when things go wrong, etc).
*/
struct msm_gem_submit {
+ struct drm_sched_job base;
struct kref ref;
struct drm_device *dev;
struct msm_gpu *gpu;
struct msm_gem_address_space *aspace;
struct list_head node; /* node in ring submit list */
- struct list_head bo_list;
struct ww_acquire_ctx ticket;
uint32_t seqno; /* Sequence number of the submit on the ring */
- struct dma_fence *fence;
+
+ /* Array of struct dma_fence * to block on before submitting this job.
+ */
+ struct xarray deps;
+ unsigned long last_dep;
+
+ /* Hw fence, which is created when the scheduler executes the job, and
+ * is signaled when the hw finishes (via seqno write from cmdstream)
+ */
+ struct dma_fence *hw_fence;
+
+ /* Userspace visible fence, which is signaled by the scheduler after
+ * the hw_fence is signaled.
+ */
+ struct dma_fence *user_fence;
+
+ int fence_id; /* key into queue->fence_idr */
struct msm_gpu_submitqueue *queue;
struct pid *pid; /* submitting process */
bool fault_dumped; /* Limit devcoredump dumping to one per submit */
@@ -355,6 +354,11 @@ struct msm_gem_submit {
} bos[];
};
+static inline struct msm_gem_submit *to_msm_submit(struct drm_sched_job *job)
+{
+ return container_of(job, struct msm_gem_submit, base);
+}
+
void __msm_gem_submit_destroy(struct kref *kref);
static inline void msm_gem_submit_get(struct msm_gem_submit *submit)
@@ -367,6 +371,8 @@ static inline void msm_gem_submit_put(struct msm_gem_submit *submit)
kref_put(&submit->ref, __msm_gem_submit_destroy);
}
+void msm_submit_retire(struct msm_gem_submit *submit);
+
/* helper to determine of a buffer in submit should be dumped, used for both
* devcoredump and debugfs cmdstream dumping:
*/
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index 9880348a4dc7..fc94e061d6a7 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -39,17 +39,6 @@ void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map)
msm_gem_put_vaddr(obj);
}
-int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
-{
- int ret;
-
- ret = drm_gem_mmap_obj(obj, obj->size, vma);
- if (ret < 0)
- return ret;
-
- return msm_gem_mmap_obj(vma->vm_private_data, vma);
-}
-
struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg)
{
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 44f84bfd0c0e..fdc5367aecaa 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -23,8 +23,9 @@
/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */
#define BO_VALID 0x8000 /* is current addr in cmdstream correct/valid? */
-#define BO_LOCKED 0x4000
-#define BO_PINNED 0x2000
+#define BO_LOCKED 0x4000 /* obj lock is held */
+#define BO_ACTIVE 0x2000 /* active refcnt is held */
+#define BO_PINNED 0x1000 /* obj is pinned and on active list */
static struct msm_gem_submit *submit_create(struct drm_device *dev,
struct msm_gpu *gpu,
@@ -32,32 +33,37 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
uint32_t nr_cmds)
{
struct msm_gem_submit *submit;
- uint64_t sz = struct_size(submit, bos, nr_bos) +
- ((u64)nr_cmds * sizeof(submit->cmd[0]));
+ uint64_t sz;
+ int ret;
+
+ sz = struct_size(submit, bos, nr_bos) +
+ ((u64)nr_cmds * sizeof(submit->cmd[0]));
if (sz > SIZE_MAX)
- return NULL;
+ return ERR_PTR(-ENOMEM);
- submit = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+ submit = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
if (!submit)
- return NULL;
+ return ERR_PTR(-ENOMEM);
+
+ ret = drm_sched_job_init(&submit->base, &queue->entity, queue);
+ if (ret) {
+ kfree(submit);
+ return ERR_PTR(ret);
+ }
+
+ xa_init_flags(&submit->deps, XA_FLAGS_ALLOC);
kref_init(&submit->ref);
submit->dev = dev;
submit->aspace = queue->ctx->aspace;
submit->gpu = gpu;
- submit->fence = NULL;
submit->cmd = (void *)&submit->bos[nr_bos];
submit->queue = queue;
- submit->ring = gpu->rb[queue->prio];
+ submit->ring = gpu->rb[queue->ring_nr];
submit->fault_dumped = false;
- /* initially, until copy_from_user() and bo lookup succeeds: */
- submit->nr_bos = 0;
- submit->nr_cmds = 0;
-
INIT_LIST_HEAD(&submit->node);
- INIT_LIST_HEAD(&submit->bo_list);
return submit;
}
@@ -66,9 +72,25 @@ void __msm_gem_submit_destroy(struct kref *kref)
{
struct msm_gem_submit *submit =
container_of(kref, struct msm_gem_submit, ref);
+ unsigned long index;
+ struct dma_fence *fence;
unsigned i;
- dma_fence_put(submit->fence);
+ if (submit->fence_id) {
+ mutex_lock(&submit->queue->lock);
+ idr_remove(&submit->queue->fence_idr, submit->fence_id);
+ mutex_unlock(&submit->queue->lock);
+ }
+
+ xa_for_each (&submit->deps, index, fence) {
+ dma_fence_put(fence);
+ }
+
+ xa_destroy(&submit->deps);
+
+ dma_fence_put(submit->user_fence);
+ dma_fence_put(submit->hw_fence);
+
put_pid(submit->pid);
msm_submitqueue_put(submit->queue);
@@ -121,7 +143,6 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
for (i = 0; i < args->nr_bos; i++) {
struct drm_gem_object *obj;
- struct msm_gem_object *msm_obj;
/* normally use drm_gem_object_lookup(), but for bulk lookup
* all under single table_lock just hit object_idr directly:
@@ -133,20 +154,9 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
goto out_unlock;
}
- msm_obj = to_msm_bo(obj);
-
- if (!list_empty(&msm_obj->submit_entry)) {
- DRM_ERROR("handle %u at index %u already on submit list\n",
- submit->bos[i].handle, i);
- ret = -EINVAL;
- goto out_unlock;
- }
-
drm_gem_object_get(obj);
- submit->bos[i].obj = msm_obj;
-
- list_add_tail(&msm_obj->submit_entry, &submit->bo_list);
+ submit->bos[i].obj = to_msm_bo(obj);
}
out_unlock:
@@ -220,21 +230,34 @@ out:
return ret;
}
-static void submit_unlock_unpin_bo(struct msm_gem_submit *submit,
- int i, bool backoff)
+/* Unwind bo state, according to cleanup_flags. In the success case, only
+ * the lock is dropped at the end of the submit (and active/pin ref is dropped
+ * later when the submit is retired).
+ */
+static void submit_cleanup_bo(struct msm_gem_submit *submit, int i,
+ unsigned cleanup_flags)
{
- struct msm_gem_object *msm_obj = submit->bos[i].obj;
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
+ unsigned flags = submit->bos[i].flags & cleanup_flags;
- if (submit->bos[i].flags & BO_PINNED)
- msm_gem_unpin_iova_locked(&msm_obj->base, submit->aspace);
+ if (flags & BO_PINNED)
+ msm_gem_unpin_iova_locked(obj, submit->aspace);
- if (submit->bos[i].flags & BO_LOCKED)
- dma_resv_unlock(msm_obj->base.resv);
+ if (flags & BO_ACTIVE)
+ msm_gem_active_put(obj);
- if (backoff && !(submit->bos[i].flags & BO_VALID))
- submit->bos[i].iova = 0;
+ if (flags & BO_LOCKED)
+ dma_resv_unlock(obj->resv);
- submit->bos[i].flags &= ~(BO_LOCKED | BO_PINNED);
+ submit->bos[i].flags &= ~cleanup_flags;
+}
+
+static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, int i)
+{
+ submit_cleanup_bo(submit, i, BO_PINNED | BO_ACTIVE | BO_LOCKED);
+
+ if (!(submit->bos[i].flags & BO_VALID))
+ submit->bos[i].iova = 0;
}
/* This is where we make sure all the bo's are reserved and pin'd: */
@@ -265,11 +288,17 @@ retry:
return 0;
fail:
+ if (ret == -EALREADY) {
+ DRM_ERROR("handle %u at index %u already on submit list\n",
+ submit->bos[i].handle, i);
+ ret = -EINVAL;
+ }
+
for (; i >= 0; i--)
- submit_unlock_unpin_bo(submit, i, true);
+ submit_unlock_unpin_bo(submit, i);
if (slow_locked > 0)
- submit_unlock_unpin_bo(submit, slow_locked, true);
+ submit_unlock_unpin_bo(submit, slow_locked);
if (ret == -EDEADLK) {
struct msm_gem_object *msm_obj = submit->bos[contended].obj;
@@ -281,6 +310,12 @@ fail:
slow_locked = contended;
goto retry;
}
+
+ /* Not expecting -EALREADY here, if the bo was already
+ * locked, we should have gotten -EALREADY already from
+ * the dma_resv_lock_interruptable() call.
+ */
+ WARN_ON_ONCE(ret == -EALREADY);
}
return ret;
@@ -291,7 +326,7 @@ static int submit_fence_sync(struct msm_gem_submit *submit, bool no_implicit)
int i, ret = 0;
for (i = 0; i < submit->nr_bos; i++) {
- struct msm_gem_object *msm_obj = submit->bos[i].obj;
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
bool write = submit->bos[i].flags & MSM_SUBMIT_BO_WRITE;
if (!write) {
@@ -300,8 +335,7 @@ static int submit_fence_sync(struct msm_gem_submit *submit, bool no_implicit)
* strange place to call it. OTOH this is a
* convenient can-fail point to hook it in.
*/
- ret = dma_resv_reserve_shared(msm_obj->base.resv,
- 1);
+ ret = dma_resv_reserve_shared(obj->resv, 1);
if (ret)
return ret;
}
@@ -309,7 +343,7 @@ static int submit_fence_sync(struct msm_gem_submit *submit, bool no_implicit)
if (no_implicit)
continue;
- ret = msm_gem_sync_object(&msm_obj->base, submit->ring->fctx,
+ ret = drm_gem_fence_array_add_implicit(&submit->deps, obj,
write);
if (ret)
break;
@@ -324,12 +358,24 @@ static int submit_pin_objects(struct msm_gem_submit *submit)
submit->valid = true;
+ /*
+ * Increment active_count first, so if under memory pressure, we
+ * don't inadvertently evict a bo needed by the submit in order
+ * to pin an earlier bo in the same submit.
+ */
for (i = 0; i < submit->nr_bos; i++) {
- struct msm_gem_object *msm_obj = submit->bos[i].obj;
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
+
+ msm_gem_active_get(obj, submit->gpu);
+ submit->bos[i].flags |= BO_ACTIVE;
+ }
+
+ for (i = 0; i < submit->nr_bos; i++) {
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
uint64_t iova;
/* if locking succeeded, pin bo: */
- ret = msm_gem_get_and_pin_iova_locked(&msm_obj->base,
+ ret = msm_gem_get_and_pin_iova_locked(obj,
submit->aspace, &iova);
if (ret)
@@ -350,6 +396,20 @@ static int submit_pin_objects(struct msm_gem_submit *submit)
return ret;
}
+static void submit_attach_object_fences(struct msm_gem_submit *submit)
+{
+ int i;
+
+ for (i = 0; i < submit->nr_bos; i++) {
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
+
+ if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
+ dma_resv_add_excl_fence(obj->resv, submit->user_fence);
+ else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
+ dma_resv_add_shared_fence(obj->resv, submit->user_fence);
+ }
+}
+
static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
struct msm_gem_object **obj, uint64_t *iova, bool *valid)
{
@@ -444,18 +504,39 @@ out:
return ret;
}
-static void submit_cleanup(struct msm_gem_submit *submit)
+/* Cleanup submit at end of ioctl. In the error case, this also drops
+ * references, unpins, and drops active refcnt. In the non-error case,
+ * this is done when the submit is retired.
+ */
+static void submit_cleanup(struct msm_gem_submit *submit, bool error)
{
+ unsigned cleanup_flags = BO_LOCKED;
unsigned i;
+ if (error)
+ cleanup_flags |= BO_PINNED | BO_ACTIVE;
+
for (i = 0; i < submit->nr_bos; i++) {
struct msm_gem_object *msm_obj = submit->bos[i].obj;
- submit_unlock_unpin_bo(submit, i, false);
- list_del_init(&msm_obj->submit_entry);
- drm_gem_object_put_locked(&msm_obj->base);
+ submit_cleanup_bo(submit, i, cleanup_flags);
+ if (error)
+ drm_gem_object_put(&msm_obj->base);
}
}
+void msm_submit_retire(struct msm_gem_submit *submit)
+{
+ int i;
+
+ for (i = 0; i < submit->nr_bos; i++) {
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
+
+ msm_gem_lock(obj);
+ submit_cleanup_bo(submit, i, BO_PINNED | BO_ACTIVE);
+ msm_gem_unlock(obj);
+ drm_gem_object_put(obj);
+ }
+}
struct msm_submit_post_dep {
struct drm_syncobj *syncobj;
@@ -463,12 +544,12 @@ struct msm_submit_post_dep {
struct dma_fence_chain *chain;
};
-static struct drm_syncobj **msm_wait_deps(struct drm_device *dev,
- struct drm_file *file,
- uint64_t in_syncobjs_addr,
- uint32_t nr_in_syncobjs,
- size_t syncobj_stride,
- struct msm_ringbuffer *ring)
+static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit,
+ struct drm_file *file,
+ uint64_t in_syncobjs_addr,
+ uint32_t nr_in_syncobjs,
+ size_t syncobj_stride,
+ struct msm_ringbuffer *ring)
{
struct drm_syncobj **syncobjs = NULL;
struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
@@ -492,7 +573,7 @@ static struct drm_syncobj **msm_wait_deps(struct drm_device *dev,
}
if (syncobj_desc.point &&
- !drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) {
+ !drm_core_check_feature(submit->dev, DRIVER_SYNCOBJ_TIMELINE)) {
ret = -EOPNOTSUPP;
break;
}
@@ -507,10 +588,7 @@ static struct drm_syncobj **msm_wait_deps(struct drm_device *dev,
if (ret)
break;
- if (!dma_fence_match_context(fence, ring->fctx->context))
- ret = dma_fence_wait(fence, true);
-
- dma_fence_put(fence);
+ ret = drm_gem_fence_array_add(&submit->deps, fence);
if (ret)
break;
@@ -587,9 +665,7 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,
break;
}
- post_deps[i].chain =
- kmalloc(sizeof(*post_deps[i].chain),
- GFP_KERNEL);
+ post_deps[i].chain = dma_fence_chain_alloc();
if (!post_deps[i].chain) {
ret = -ENOMEM;
break;
@@ -606,7 +682,7 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,
if (ret) {
for (j = 0; j <= i; ++j) {
- kfree(post_deps[j].chain);
+ dma_fence_chain_free(post_deps[j].chain);
if (post_deps[j].syncobj)
drm_syncobj_put(post_deps[j].syncobj);
}
@@ -643,9 +719,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
struct msm_drm_private *priv = dev->dev_private;
struct drm_msm_gem_submit *args = data;
struct msm_file_private *ctx = file->driver_priv;
- struct msm_gem_submit *submit;
+ struct msm_gem_submit *submit = NULL;
struct msm_gpu *gpu = priv->gpu;
- struct sync_file *sync_file = NULL;
struct msm_gpu_submitqueue *queue;
struct msm_ringbuffer *ring;
struct msm_submit_post_dep *post_deps = NULL;
@@ -655,6 +730,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
bool has_ww_ticket = false;
unsigned i;
int ret, submitid;
+
if (!gpu)
return -ENXIO;
@@ -683,38 +759,59 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
/* Get a unique identifier for the submission for logging purposes */
submitid = atomic_inc_return(&ident) - 1;
- ring = gpu->rb[queue->prio];
+ ring = gpu->rb[queue->ring_nr];
trace_msm_gpu_submit(pid_nr(pid), ring->id, submitid,
args->nr_bos, args->nr_cmds);
+ ret = mutex_lock_interruptible(&queue->lock);
+ if (ret)
+ goto out_post_unlock;
+
+ if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
+ out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
+ if (out_fence_fd < 0) {
+ ret = out_fence_fd;
+ goto out_unlock;
+ }
+ }
+
+ submit = submit_create(dev, gpu, queue, args->nr_bos,
+ args->nr_cmds);
+ if (IS_ERR(submit)) {
+ ret = PTR_ERR(submit);
+ goto out_unlock;
+ }
+
+ submit->pid = pid;
+ submit->ident = submitid;
+
+ if (args->flags & MSM_SUBMIT_SUDO)
+ submit->in_rb = true;
+
if (args->flags & MSM_SUBMIT_FENCE_FD_IN) {
struct dma_fence *in_fence;
in_fence = sync_file_get_fence(args->fence_fd);
- if (!in_fence)
- return -EINVAL;
-
- /*
- * Wait if the fence is from a foreign context, or if the fence
- * array contains any fence from a foreign context.
- */
- ret = 0;
- if (!dma_fence_match_context(in_fence, ring->fctx->context))
- ret = dma_fence_wait(in_fence, true);
+ if (!in_fence) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
- dma_fence_put(in_fence);
+ ret = drm_gem_fence_array_add(&submit->deps, in_fence);
if (ret)
- return ret;
+ goto out_unlock;
}
if (args->flags & MSM_SUBMIT_SYNCOBJ_IN) {
- syncobjs_to_reset = msm_wait_deps(dev, file,
- args->in_syncobjs,
- args->nr_in_syncobjs,
- args->syncobj_stride, ring);
- if (IS_ERR(syncobjs_to_reset))
- return PTR_ERR(syncobjs_to_reset);
+ syncobjs_to_reset = msm_parse_deps(submit, file,
+ args->in_syncobjs,
+ args->nr_in_syncobjs,
+ args->syncobj_stride, ring);
+ if (IS_ERR(syncobjs_to_reset)) {
+ ret = PTR_ERR(syncobjs_to_reset);
+ goto out_unlock;
+ }
}
if (args->flags & MSM_SUBMIT_SYNCOBJ_OUT) {
@@ -724,51 +821,17 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
args->syncobj_stride);
if (IS_ERR(post_deps)) {
ret = PTR_ERR(post_deps);
- goto out_post_unlock;
- }
- }
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- goto out_post_unlock;
-
- if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
- out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
- if (out_fence_fd < 0) {
- ret = out_fence_fd;
goto out_unlock;
}
}
- submit = submit_create(dev, gpu, queue, args->nr_bos,
- args->nr_cmds);
- if (!submit) {
- ret = -ENOMEM;
- goto out_unlock;
- }
-
- submit->pid = pid;
- submit->ident = submitid;
-
- if (args->flags & MSM_SUBMIT_SUDO)
- submit->in_rb = true;
-
ret = submit_lookup_objects(submit, args, file);
if (ret)
- goto out_pre_pm;
+ goto out;
ret = submit_lookup_cmds(submit, args, file);
if (ret)
- goto out_pre_pm;
-
- /*
- * Thanks to dev_pm_opp opp_table_lock interactions with mm->mmap_sem
- * in the resume path, we need to to rpm get before we lock objs.
- * Which unfortunately might involve powering up the GPU sooner than
- * is necessary. But at least in the explicit fencing case, we will
- * have already done all the fence waiting.
- */
- pm_runtime_get_sync(&gpu->pdev->dev);
+ goto out;
/* copy_*_user while holding a ww ticket upsets lockdep */
ww_acquire_init(&submit->ticket, &reservation_ww_class);
@@ -815,47 +878,54 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
submit->nr_cmds = i;
- submit->fence = msm_fence_alloc(ring->fctx);
- if (IS_ERR(submit->fence)) {
- ret = PTR_ERR(submit->fence);
- submit->fence = NULL;
+ submit->user_fence = dma_fence_get(&submit->base.s_fence->finished);
+
+ /*
+ * Allocate an id which can be used by WAIT_FENCE ioctl to map back
+ * to the underlying fence.
+ */
+ submit->fence_id = idr_alloc_cyclic(&queue->fence_idr,
+ submit->user_fence, 0, INT_MAX, GFP_KERNEL);
+ if (submit->fence_id < 0) {
+ ret = submit->fence_id = 0;
+ submit->fence_id = 0;
goto out;
}
if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
- sync_file = sync_file_create(submit->fence);
+ struct sync_file *sync_file = sync_file_create(submit->user_fence);
if (!sync_file) {
ret = -ENOMEM;
goto out;
}
+ fd_install(out_fence_fd, sync_file->file);
+ args->fence_fd = out_fence_fd;
}
- msm_gpu_submit(gpu, submit);
+ submit_attach_object_fences(submit);
- args->fence = submit->fence->seqno;
+ /* The scheduler owns a ref now: */
+ msm_gem_submit_get(submit);
- if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
- fd_install(out_fence_fd, sync_file->file);
- args->fence_fd = out_fence_fd;
- }
+ drm_sched_entity_push_job(&submit->base, &queue->entity);
+
+ args->fence = submit->fence_id;
msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs);
msm_process_post_deps(post_deps, args->nr_out_syncobjs,
- submit->fence);
+ submit->user_fence);
out:
- pm_runtime_put(&gpu->pdev->dev);
-out_pre_pm:
- submit_cleanup(submit);
+ submit_cleanup(submit, !!ret);
if (has_ww_ticket)
ww_acquire_fini(&submit->ticket);
- msm_gem_submit_put(submit);
out_unlock:
if (ret && (out_fence_fd >= 0))
put_unused_fd(out_fence_fd);
- mutex_unlock(&dev->struct_mutex);
-
+ mutex_unlock(&queue->lock);
+ if (submit)
+ msm_gem_submit_put(submit);
out_post_unlock:
if (!IS_ERR_OR_NULL(post_deps)) {
for (i = 0; i < args->nr_out_syncobjs; ++i) {
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 0ebf7bc6ad09..8a3a592da3a4 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -13,8 +13,6 @@
#include <generated/utsrelease.h>
#include <linux/string_helpers.h>
-#include <linux/devfreq.h>
-#include <linux/devfreq_cooling.h>
#include <linux/devcoredump.h>
#include <linux/sched/task.h>
@@ -22,106 +20,6 @@
* Power Management:
*/
-static int msm_devfreq_target(struct device *dev, unsigned long *freq,
- u32 flags)
-{
- struct msm_gpu *gpu = dev_to_gpu(dev);
- struct dev_pm_opp *opp;
-
- opp = devfreq_recommended_opp(dev, freq, flags);
-
- if (IS_ERR(opp))
- return PTR_ERR(opp);
-
- trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp));
-
- if (gpu->funcs->gpu_set_freq)
- gpu->funcs->gpu_set_freq(gpu, opp);
- else
- clk_set_rate(gpu->core_clk, *freq);
-
- dev_pm_opp_put(opp);
-
- return 0;
-}
-
-static int msm_devfreq_get_dev_status(struct device *dev,
- struct devfreq_dev_status *status)
-{
- struct msm_gpu *gpu = dev_to_gpu(dev);
- ktime_t time;
-
- if (gpu->funcs->gpu_get_freq)
- status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
- else
- status->current_frequency = clk_get_rate(gpu->core_clk);
-
- status->busy_time = gpu->funcs->gpu_busy(gpu);
-
- time = ktime_get();
- status->total_time = ktime_us_delta(time, gpu->devfreq.time);
- gpu->devfreq.time = time;
-
- return 0;
-}
-
-static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
-{
- struct msm_gpu *gpu = dev_to_gpu(dev);
-
- if (gpu->funcs->gpu_get_freq)
- *freq = gpu->funcs->gpu_get_freq(gpu);
- else
- *freq = clk_get_rate(gpu->core_clk);
-
- return 0;
-}
-
-static struct devfreq_dev_profile msm_devfreq_profile = {
- .polling_ms = 10,
- .target = msm_devfreq_target,
- .get_dev_status = msm_devfreq_get_dev_status,
- .get_cur_freq = msm_devfreq_get_cur_freq,
-};
-
-static void msm_devfreq_init(struct msm_gpu *gpu)
-{
- /* We need target support to do devfreq */
- if (!gpu->funcs->gpu_busy)
- return;
-
- msm_devfreq_profile.initial_freq = gpu->fast_rate;
-
- /*
- * Don't set the freq_table or max_state and let devfreq build the table
- * from OPP
- * After a deferred probe, these may have be left to non-zero values,
- * so set them back to zero before creating the devfreq device
- */
- msm_devfreq_profile.freq_table = NULL;
- msm_devfreq_profile.max_state = 0;
-
- gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
- &msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
- NULL);
-
- if (IS_ERR(gpu->devfreq.devfreq)) {
- DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
- gpu->devfreq.devfreq = NULL;
- return;
- }
-
- devfreq_suspend_device(gpu->devfreq.devfreq);
-
- gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node,
- gpu->devfreq.devfreq);
- if (IS_ERR(gpu->cooling)) {
- DRM_DEV_ERROR(&gpu->pdev->dev,
- "Couldn't register GPU cooling device\n");
- gpu->cooling = NULL;
- }
-}
-
static int enable_pwrrail(struct msm_gpu *gpu)
{
struct drm_device *dev = gpu->dev;
@@ -196,14 +94,6 @@ static int disable_axi(struct msm_gpu *gpu)
return 0;
}
-void msm_gpu_resume_devfreq(struct msm_gpu *gpu)
-{
- gpu->devfreq.busy_cycles = 0;
- gpu->devfreq.time = ktime_get();
-
- devfreq_resume_device(gpu->devfreq.devfreq);
-}
-
int msm_gpu_pm_resume(struct msm_gpu *gpu)
{
int ret;
@@ -223,7 +113,7 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
if (ret)
return ret;
- msm_gpu_resume_devfreq(gpu);
+ msm_devfreq_resume(gpu);
gpu->needs_hw_init = true;
@@ -237,7 +127,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
DBG("%s", gpu->name);
trace_msm_gpu_suspend(0);
- devfreq_suspend_device(gpu->devfreq.devfreq);
+ msm_devfreq_suspend(gpu);
ret = disable_axi(gpu);
if (ret)
@@ -278,16 +168,18 @@ static void update_fences(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
uint32_t fence)
{
struct msm_gem_submit *submit;
+ unsigned long flags;
- spin_lock(&ring->submit_lock);
+ spin_lock_irqsave(&ring->submit_lock, flags);
list_for_each_entry(submit, &ring->submits, node) {
if (submit->seqno > fence)
break;
msm_update_fence(submit->ring->fctx,
- submit->fence->seqno);
+ submit->hw_fence->seqno);
+ dma_fence_signal(submit->hw_fence);
}
- spin_unlock(&ring->submit_lock);
+ spin_unlock_irqrestore(&ring->submit_lock, flags);
}
#ifdef CONFIG_DEV_COREDUMP
@@ -443,15 +335,16 @@ static struct msm_gem_submit *
find_submit(struct msm_ringbuffer *ring, uint32_t fence)
{
struct msm_gem_submit *submit;
+ unsigned long flags;
- spin_lock(&ring->submit_lock);
+ spin_lock_irqsave(&ring->submit_lock, flags);
list_for_each_entry(submit, &ring->submits, node) {
if (submit->seqno == fence) {
- spin_unlock(&ring->submit_lock);
+ spin_unlock_irqrestore(&ring->submit_lock, flags);
return submit;
}
}
- spin_unlock(&ring->submit_lock);
+ spin_unlock_irqrestore(&ring->submit_lock, flags);
return NULL;
}
@@ -487,10 +380,6 @@ static void recover_worker(struct kthread_work *work)
put_task_struct(task);
}
- /* msm_rd_dump_submit() needs bo locked to dump: */
- for (i = 0; i < submit->nr_bos; i++)
- msm_gem_lock(&submit->bos[i].obj->base);
-
if (comm && cmd) {
DRM_DEV_ERROR(dev->dev, "%s: offending task: %s (%s)\n",
gpu->name, comm, cmd);
@@ -500,9 +389,6 @@ static void recover_worker(struct kthread_work *work)
} else {
msm_rd_dump_submit(priv->hangrd, submit, NULL);
}
-
- for (i = 0; i < submit->nr_bos; i++)
- msm_gem_unlock(&submit->bos[i].obj->base);
}
/* Record the crash state */
@@ -547,11 +433,12 @@ static void recover_worker(struct kthread_work *work)
*/
for (i = 0; i < gpu->nr_rings; i++) {
struct msm_ringbuffer *ring = gpu->rb[i];
+ unsigned long flags;
- spin_lock(&ring->submit_lock);
+ spin_lock_irqsave(&ring->submit_lock, flags);
list_for_each_entry(submit, &ring->submits, node)
gpu->funcs->submit(gpu, submit);
- spin_unlock(&ring->submit_lock);
+ spin_unlock_irqrestore(&ring->submit_lock, flags);
}
}
@@ -641,7 +528,7 @@ static void hangcheck_handler(struct timer_list *t)
hangcheck_timer_reset(gpu);
/* workaround for missing irq: */
- kthread_queue_work(gpu->worker, &gpu->retire_work);
+ msm_gpu_retire(gpu);
}
/*
@@ -752,7 +639,7 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT;
volatile struct msm_gpu_submit_stats *stats;
u64 elapsed, clock = 0;
- int i;
+ unsigned long flags;
stats = &ring->memptrs->stats[index];
/* Convert 19.2Mhz alwayson ticks to nanoseconds for elapsed time */
@@ -768,22 +655,22 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
trace_msm_gpu_submit_retired(submit, elapsed, clock,
stats->alwayson_start, stats->alwayson_end);
- for (i = 0; i < submit->nr_bos; i++) {
- struct drm_gem_object *obj = &submit->bos[i].obj->base;
-
- msm_gem_lock(obj);
- msm_gem_active_put(obj);
- msm_gem_unpin_iova_locked(obj, submit->aspace);
- msm_gem_unlock(obj);
- drm_gem_object_put(obj);
- }
+ msm_submit_retire(submit);
pm_runtime_mark_last_busy(&gpu->pdev->dev);
pm_runtime_put_autosuspend(&gpu->pdev->dev);
- spin_lock(&ring->submit_lock);
+ spin_lock_irqsave(&ring->submit_lock, flags);
list_del(&submit->node);
- spin_unlock(&ring->submit_lock);
+ spin_unlock_irqrestore(&ring->submit_lock, flags);
+
+ /* Update devfreq on transition from active->idle: */
+ mutex_lock(&gpu->active_lock);
+ gpu->active_submits--;
+ WARN_ON(gpu->active_submits < 0);
+ if (!gpu->active_submits)
+ msm_devfreq_idle(gpu);
+ mutex_unlock(&gpu->active_lock);
msm_gem_submit_put(submit);
}
@@ -798,18 +685,19 @@ static void retire_submits(struct msm_gpu *gpu)
while (true) {
struct msm_gem_submit *submit = NULL;
+ unsigned long flags;
- spin_lock(&ring->submit_lock);
+ spin_lock_irqsave(&ring->submit_lock, flags);
submit = list_first_entry_or_null(&ring->submits,
struct msm_gem_submit, node);
- spin_unlock(&ring->submit_lock);
+ spin_unlock_irqrestore(&ring->submit_lock, flags);
/*
* If no submit, we are done. If submit->fence hasn't
* been signalled, then later submits are not signalled
* either, so we are also done.
*/
- if (submit && dma_fence_is_signaled(submit->fence)) {
+ if (submit && dma_fence_is_signaled(submit->hw_fence)) {
retire_submit(gpu, ring, submit);
} else {
break;
@@ -821,10 +709,6 @@ static void retire_submits(struct msm_gpu *gpu)
static void retire_worker(struct kthread_work *work)
{
struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work);
- int i;
-
- for (i = 0; i < gpu->nr_rings; i++)
- update_fences(gpu, gpu->rb[i], gpu->rb[i]->memptrs->fence);
retire_submits(gpu);
}
@@ -832,6 +716,11 @@ static void retire_worker(struct kthread_work *work)
/* call from irq handler to schedule work to retire bo's */
void msm_gpu_retire(struct msm_gpu *gpu)
{
+ int i;
+
+ for (i = 0; i < gpu->nr_rings; i++)
+ update_fences(gpu, gpu->rb[i], gpu->rb[i]->memptrs->fence);
+
kthread_queue_work(gpu->worker, &gpu->retire_work);
update_sw_cntrs(gpu);
}
@@ -842,7 +731,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
struct drm_device *dev = gpu->dev;
struct msm_drm_private *priv = dev->dev_private;
struct msm_ringbuffer *ring = submit->ring;
- int i;
+ unsigned long flags;
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -856,32 +745,22 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
update_sw_cntrs(gpu);
- for (i = 0; i < submit->nr_bos; i++) {
- struct msm_gem_object *msm_obj = submit->bos[i].obj;
- struct drm_gem_object *drm_obj = &msm_obj->base;
- uint64_t iova;
-
- /* submit takes a reference to the bo and iova until retired: */
- drm_gem_object_get(&msm_obj->base);
- msm_gem_get_and_pin_iova_locked(&msm_obj->base, submit->aspace, &iova);
-
- if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
- dma_resv_add_excl_fence(drm_obj->resv, submit->fence);
- else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
- dma_resv_add_shared_fence(drm_obj->resv, submit->fence);
-
- msm_gem_active_get(drm_obj, gpu);
- }
-
/*
* ring->submits holds a ref to the submit, to deal with the case
* that a submit completes before msm_ioctl_gem_submit() returns.
*/
msm_gem_submit_get(submit);
- spin_lock(&ring->submit_lock);
+ spin_lock_irqsave(&ring->submit_lock, flags);
list_add_tail(&submit->node, &ring->submits);
- spin_unlock(&ring->submit_lock);
+ spin_unlock_irqrestore(&ring->submit_lock, flags);
+
+ /* Update devfreq on transition from idle->active: */
+ mutex_lock(&gpu->active_lock);
+ if (!gpu->active_submits)
+ msm_devfreq_active(gpu);
+ gpu->active_submits++;
+ mutex_unlock(&gpu->active_lock);
gpu->funcs->submit(gpu, submit);
priv->lastctx = submit->queue->ctx;
@@ -968,6 +847,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
sched_set_fifo_low(gpu->worker->task);
INIT_LIST_HEAD(&gpu->active_list);
+ mutex_init(&gpu->active_lock);
kthread_init_work(&gpu->retire_work, retire_worker);
kthread_init_work(&gpu->recover_work, recover_worker);
kthread_init_work(&gpu->fault_work, fault_worker);
@@ -1078,7 +958,7 @@ fail:
gpu->rb[i] = NULL;
}
- msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace, false);
+ msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace);
platform_set_drvdata(pdev, NULL);
return ret;
@@ -1097,7 +977,7 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
gpu->rb[i] = NULL;
}
- msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace, false);
+ msm_gem_kernel_put(gpu->memptrs_bo, gpu->aspace);
if (!IS_ERR_OR_NULL(gpu->aspace)) {
gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu);
@@ -1108,5 +988,5 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
kthread_destroy_worker(gpu->worker);
}
- devfreq_cooling_unregister(gpu->cooling);
+ msm_devfreq_cleanup(gpu);
}
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index ef41ec09f59c..0e4b45bff2e6 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -80,6 +80,40 @@ struct msm_gpu_fault_info {
const char *block;
};
+/**
+ * struct msm_gpu_devfreq - devfreq related state
+ */
+struct msm_gpu_devfreq {
+ /** devfreq: devfreq instance */
+ struct devfreq *devfreq;
+
+ /**
+ * busy_cycles:
+ *
+ * Used by implementation of gpu->gpu_busy() to track the last
+ * busy counter value, for calculating elapsed busy cycles since
+ * last sampling period.
+ */
+ u64 busy_cycles;
+
+ /** time: Time of last sampling period. */
+ ktime_t time;
+
+ /** idle_time: Time of last transition to idle: */
+ ktime_t idle_time;
+
+ /**
+ * idle_freq:
+ *
+ * Shadow frequency used while the GPU is idle. From the PoV of
+ * the devfreq governor, we are continuing to sample busyness and
+ * adjust frequency while the GPU is idle, but we use this shadow
+ * value as the GPU is actually clamped to minimum frequency while
+ * it is inactive.
+ */
+ unsigned long idle_freq;
+};
+
struct msm_gpu {
const char *name;
struct drm_device *dev;
@@ -109,6 +143,19 @@ struct msm_gpu {
*/
struct list_head active_list;
+ /**
+ * active_submits:
+ *
+ * The number of submitted but not yet retired submits, used to
+ * determine transitions between active and idle.
+ *
+ * Protected by lock
+ */
+ int active_submits;
+
+ /** lock: protects active_submits and idle/active transitions */
+ struct mutex active_lock;
+
/* does gpu need hw_init? */
bool needs_hw_init;
@@ -151,11 +198,7 @@ struct msm_gpu {
struct drm_gem_object *memptrs_bo;
- struct {
- struct devfreq *devfreq;
- u64 busy_cycles;
- ktime_t time;
- } devfreq;
+ struct msm_gpu_devfreq devfreq;
uint32_t suspend_count;
@@ -207,14 +250,90 @@ struct msm_gpu_perfcntr {
const char *name;
};
+/*
+ * The number of priority levels provided by drm gpu scheduler. The
+ * DRM_SCHED_PRIORITY_KERNEL priority level is treated specially in some
+ * cases, so we don't use it (no need for kernel generated jobs).
+ */
+#define NR_SCHED_PRIORITIES (1 + DRM_SCHED_PRIORITY_HIGH - DRM_SCHED_PRIORITY_MIN)
+
+/**
+ * msm_gpu_convert_priority - Map userspace priority to ring # and sched priority
+ *
+ * @gpu: the gpu instance
+ * @prio: the userspace priority level
+ * @ring_nr: [out] the ringbuffer the userspace priority maps to
+ * @sched_prio: [out] the gpu scheduler priority level which the userspace
+ * priority maps to
+ *
+ * With drm/scheduler providing it's own level of prioritization, our total
+ * number of available priority levels is (nr_rings * NR_SCHED_PRIORITIES).
+ * Each ring is associated with it's own scheduler instance. However, our
+ * UABI is that lower numerical values are higher priority. So mapping the
+ * single userspace priority level into ring_nr and sched_prio takes some
+ * care. The userspace provided priority (when a submitqueue is created)
+ * is mapped to ring nr and scheduler priority as such:
+ *
+ * ring_nr = userspace_prio / NR_SCHED_PRIORITIES
+ * sched_prio = NR_SCHED_PRIORITIES -
+ * (userspace_prio % NR_SCHED_PRIORITIES) - 1
+ *
+ * This allows generations without preemption (nr_rings==1) to have some
+ * amount of prioritization, and provides more priority levels for gens
+ * that do have preemption.
+ */
+static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
+ unsigned *ring_nr, enum drm_sched_priority *sched_prio)
+{
+ unsigned rn, sp;
+
+ rn = div_u64_rem(prio, NR_SCHED_PRIORITIES, &sp);
+
+ /* invert sched priority to map to higher-numeric-is-higher-
+ * priority convention
+ */
+ sp = NR_SCHED_PRIORITIES - sp - 1;
+
+ if (rn >= gpu->nr_rings)
+ return -EINVAL;
+
+ *ring_nr = rn;
+ *sched_prio = sp;
+
+ return 0;
+}
+
+/**
+ * A submitqueue is associated with a gl context or vk queue (or equiv)
+ * in userspace.
+ *
+ * @id: userspace id for the submitqueue, unique within the drm_file
+ * @flags: userspace flags for the submitqueue, specified at creation
+ * (currently unusued)
+ * @ring_nr: the ringbuffer used by this submitqueue, which is determined
+ * by the submitqueue's priority
+ * @faults: the number of GPU hangs associated with this submitqueue
+ * @ctx: the per-drm_file context associated with the submitqueue (ie.
+ * which set of pgtables do submits jobs associated with the
+ * submitqueue use)
+ * @node: node in the context's list of submitqueues
+ * @fence_idr: maps fence-id to dma_fence for userspace visible fence
+ * seqno, protected by submitqueue lock
+ * @lock: submitqueue lock
+ * @ref: reference count
+ * @entity: the submit job-queue
+ */
struct msm_gpu_submitqueue {
int id;
u32 flags;
- u32 prio;
+ u32 ring_nr;
int faults;
struct msm_file_private *ctx;
struct list_head node;
+ struct idr fence_idr;
+ struct mutex lock;
struct kref ref;
+ struct drm_sched_entity entity;
};
struct msm_gpu_state_bo {
@@ -301,7 +420,13 @@ static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
int msm_gpu_pm_suspend(struct msm_gpu *gpu);
int msm_gpu_pm_resume(struct msm_gpu *gpu);
-void msm_gpu_resume_devfreq(struct msm_gpu *gpu);
+
+void msm_devfreq_init(struct msm_gpu *gpu);
+void msm_devfreq_cleanup(struct msm_gpu *gpu);
+void msm_devfreq_resume(struct msm_gpu *gpu);
+void msm_devfreq_suspend(struct msm_gpu *gpu);
+void msm_devfreq_active(struct msm_gpu *gpu);
+void msm_devfreq_idle(struct msm_gpu *gpu);
int msm_gpu_hw_init(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
new file mode 100644
index 000000000000..0a1ee20296a2
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ */
+
+#include "msm_gpu.h"
+#include "msm_gpu_trace.h"
+
+#include <linux/devfreq.h>
+#include <linux/devfreq_cooling.h>
+
+/*
+ * Power Management:
+ */
+
+static int msm_devfreq_target(struct device *dev, unsigned long *freq,
+ u32 flags)
+{
+ struct msm_gpu *gpu = dev_to_gpu(dev);
+ struct dev_pm_opp *opp;
+
+ opp = devfreq_recommended_opp(dev, freq, flags);
+
+ /*
+ * If the GPU is idle, devfreq is not aware, so just ignore
+ * it's requests
+ */
+ if (gpu->devfreq.idle_freq) {
+ gpu->devfreq.idle_freq = *freq;
+ return 0;
+ }
+
+ if (IS_ERR(opp))
+ return PTR_ERR(opp);
+
+ trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp));
+
+ if (gpu->funcs->gpu_set_freq)
+ gpu->funcs->gpu_set_freq(gpu, opp);
+ else
+ clk_set_rate(gpu->core_clk, *freq);
+
+ dev_pm_opp_put(opp);
+
+ return 0;
+}
+
+static unsigned long get_freq(struct msm_gpu *gpu)
+{
+ if (gpu->devfreq.idle_freq)
+ return gpu->devfreq.idle_freq;
+
+ if (gpu->funcs->gpu_get_freq)
+ return gpu->funcs->gpu_get_freq(gpu);
+
+ return clk_get_rate(gpu->core_clk);
+}
+
+static int msm_devfreq_get_dev_status(struct device *dev,
+ struct devfreq_dev_status *status)
+{
+ struct msm_gpu *gpu = dev_to_gpu(dev);
+ ktime_t time;
+
+ status->current_frequency = get_freq(gpu);
+ status->busy_time = gpu->funcs->gpu_busy(gpu);
+
+ time = ktime_get();
+ status->total_time = ktime_us_delta(time, gpu->devfreq.time);
+ gpu->devfreq.time = time;
+
+ return 0;
+}
+
+static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+ *freq = get_freq(dev_to_gpu(dev));
+
+ return 0;
+}
+
+static struct devfreq_dev_profile msm_devfreq_profile = {
+ .timer = DEVFREQ_TIMER_DELAYED,
+ .polling_ms = 50,
+ .target = msm_devfreq_target,
+ .get_dev_status = msm_devfreq_get_dev_status,
+ .get_cur_freq = msm_devfreq_get_cur_freq,
+};
+
+void msm_devfreq_init(struct msm_gpu *gpu)
+{
+ /* We need target support to do devfreq */
+ if (!gpu->funcs->gpu_busy)
+ return;
+
+ msm_devfreq_profile.initial_freq = gpu->fast_rate;
+
+ /*
+ * Don't set the freq_table or max_state and let devfreq build the table
+ * from OPP
+ * After a deferred probe, these may have be left to non-zero values,
+ * so set them back to zero before creating the devfreq device
+ */
+ msm_devfreq_profile.freq_table = NULL;
+ msm_devfreq_profile.max_state = 0;
+
+ gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
+ &msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
+ NULL);
+
+ if (IS_ERR(gpu->devfreq.devfreq)) {
+ DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
+ gpu->devfreq.devfreq = NULL;
+ return;
+ }
+
+ devfreq_suspend_device(gpu->devfreq.devfreq);
+
+ gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node,
+ gpu->devfreq.devfreq);
+ if (IS_ERR(gpu->cooling)) {
+ DRM_DEV_ERROR(&gpu->pdev->dev,
+ "Couldn't register GPU cooling device\n");
+ gpu->cooling = NULL;
+ }
+}
+
+void msm_devfreq_cleanup(struct msm_gpu *gpu)
+{
+ devfreq_cooling_unregister(gpu->cooling);
+}
+
+void msm_devfreq_resume(struct msm_gpu *gpu)
+{
+ gpu->devfreq.busy_cycles = 0;
+ gpu->devfreq.time = ktime_get();
+
+ devfreq_resume_device(gpu->devfreq.devfreq);
+}
+
+void msm_devfreq_suspend(struct msm_gpu *gpu)
+{
+ devfreq_suspend_device(gpu->devfreq.devfreq);
+}
+
+void msm_devfreq_active(struct msm_gpu *gpu)
+{
+ struct msm_gpu_devfreq *df = &gpu->devfreq;
+ struct devfreq_dev_status status;
+ unsigned int idle_time;
+ unsigned long target_freq = df->idle_freq;
+
+ /*
+ * Hold devfreq lock to synchronize with get_dev_status()/
+ * target() callbacks
+ */
+ mutex_lock(&df->devfreq->lock);
+
+ idle_time = ktime_to_ms(ktime_sub(ktime_get(), df->idle_time));
+
+ /*
+ * If we've been idle for a significant fraction of a polling
+ * interval, then we won't meet the threshold of busyness for
+ * the governor to ramp up the freq.. so give some boost
+ */
+ if (idle_time > msm_devfreq_profile.polling_ms/2) {
+ target_freq *= 2;
+ }
+
+ df->idle_freq = 0;
+
+ msm_devfreq_target(&gpu->pdev->dev, &target_freq, 0);
+
+ /*
+ * Reset the polling interval so we aren't inconsistent
+ * about freq vs busy/total cycles
+ */
+ msm_devfreq_get_dev_status(&gpu->pdev->dev, &status);
+
+ mutex_unlock(&df->devfreq->lock);
+}
+
+void msm_devfreq_idle(struct msm_gpu *gpu)
+{
+ struct msm_gpu_devfreq *df = &gpu->devfreq;
+ unsigned long idle_freq, target_freq = 0;
+
+ /*
+ * Hold devfreq lock to synchronize with get_dev_status()/
+ * target() callbacks
+ */
+ mutex_lock(&df->devfreq->lock);
+
+ idle_freq = get_freq(gpu);
+
+ msm_devfreq_target(&gpu->pdev->dev, &target_freq, 0);
+
+ df->idle_time = ktime_get();
+ df->idle_freq = idle_freq;
+
+ mutex_unlock(&df->devfreq->lock);
+}
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 086a2d59b8c8..de2bc3467bb5 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -117,9 +117,6 @@ struct msm_kms_funcs {
struct drm_encoder *encoder,
struct drm_encoder *slave_encoder,
bool is_cmd_mode);
- void (*set_encoder_mode)(struct msm_kms *kms,
- struct drm_encoder *encoder,
- bool cmd_mode);
/* cleanup: */
void (*destroy)(struct msm_kms *kms);
@@ -150,7 +147,7 @@ struct msm_kms {
const struct msm_kms_funcs *funcs;
struct drm_device *dev;
- /* irq number to be passed on to drm_irq_install */
+ /* irq number to be passed on to msm_irq_install */
int irq;
/* mapper-id used to request GEM buffer mapped for scanout: */
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 659e5cc4b40a..b55398a34fa4 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -325,15 +325,19 @@ static void snapshot_buf(struct msm_rd_state *rd,
if (!(submit->bos[idx].flags & MSM_SUBMIT_BO_READ))
return;
+ msm_gem_lock(&obj->base);
buf = msm_gem_get_vaddr_active(&obj->base);
if (IS_ERR(buf))
- return;
+ goto out_unlock;
buf += offset;
rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size);
msm_gem_put_vaddr_locked(&obj->base);
+
+out_unlock:
+ msm_gem_unlock(&obj->base);
}
/* called under struct_mutex */
diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c
index 4d2a2a4abef8..bd54c1412649 100644
--- a/drivers/gpu/drm/msm/msm_ringbuffer.c
+++ b/drivers/gpu/drm/msm/msm_ringbuffer.c
@@ -7,10 +7,61 @@
#include "msm_ringbuffer.h"
#include "msm_gpu.h"
+static uint num_hw_submissions = 8;
+MODULE_PARM_DESC(num_hw_submissions, "The max # of jobs to write into ringbuffer (default 8)");
+module_param(num_hw_submissions, uint, 0600);
+
+static struct dma_fence *msm_job_dependency(struct drm_sched_job *job,
+ struct drm_sched_entity *s_entity)
+{
+ struct msm_gem_submit *submit = to_msm_submit(job);
+
+ if (!xa_empty(&submit->deps))
+ return xa_erase(&submit->deps, submit->last_dep++);
+
+ return NULL;
+}
+
+static struct dma_fence *msm_job_run(struct drm_sched_job *job)
+{
+ struct msm_gem_submit *submit = to_msm_submit(job);
+ struct msm_gpu *gpu = submit->gpu;
+
+ submit->hw_fence = msm_fence_alloc(submit->ring->fctx);
+
+ pm_runtime_get_sync(&gpu->pdev->dev);
+
+ /* TODO move submit path over to using a per-ring lock.. */
+ mutex_lock(&gpu->dev->struct_mutex);
+
+ msm_gpu_submit(gpu, submit);
+
+ mutex_unlock(&gpu->dev->struct_mutex);
+
+ pm_runtime_put(&gpu->pdev->dev);
+
+ return dma_fence_get(submit->hw_fence);
+}
+
+static void msm_job_free(struct drm_sched_job *job)
+{
+ struct msm_gem_submit *submit = to_msm_submit(job);
+
+ drm_sched_job_cleanup(job);
+ msm_gem_submit_put(submit);
+}
+
+const struct drm_sched_backend_ops msm_sched_ops = {
+ .dependency = msm_job_dependency,
+ .run_job = msm_job_run,
+ .free_job = msm_job_free
+};
+
struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
void *memptrs, uint64_t memptrs_iova)
{
struct msm_ringbuffer *ring;
+ long sched_timeout;
char name[32];
int ret;
@@ -32,7 +83,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
if (IS_ERR(ring->start)) {
ret = PTR_ERR(ring->start);
- ring->start = 0;
+ ring->start = NULL;
goto fail;
}
@@ -45,13 +96,23 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
ring->memptrs = memptrs;
ring->memptrs_iova = memptrs_iova;
+ /* currently managing hangcheck ourselves: */
+ sched_timeout = MAX_SCHEDULE_TIMEOUT;
+
+ ret = drm_sched_init(&ring->sched, &msm_sched_ops,
+ num_hw_submissions, 0, sched_timeout,
+ NULL, NULL, to_msm_bo(ring->bo)->name);
+ if (ret) {
+ goto fail;
+ }
+
INIT_LIST_HEAD(&ring->submits);
spin_lock_init(&ring->submit_lock);
spin_lock_init(&ring->preempt_lock);
snprintf(name, sizeof(name), "gpu-ring-%d", ring->id);
- ring->fctx = msm_fence_context_alloc(gpu->dev, name);
+ ring->fctx = msm_fence_context_alloc(gpu->dev, &ring->memptrs->fence, name);
return ring;
@@ -65,9 +126,11 @@ void msm_ringbuffer_destroy(struct msm_ringbuffer *ring)
if (IS_ERR_OR_NULL(ring))
return;
+ drm_sched_fini(&ring->sched);
+
msm_fence_context_free(ring->fctx);
- msm_gem_kernel_put(ring->bo, ring->gpu->aspace, false);
+ msm_gem_kernel_put(ring->bo, ring->gpu->aspace);
kfree(ring);
}
diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h
index fe55d4a1aa16..d8c63df4e9ca 100644
--- a/drivers/gpu/drm/msm/msm_ringbuffer.h
+++ b/drivers/gpu/drm/msm/msm_ringbuffer.h
@@ -7,6 +7,7 @@
#ifndef __MSM_RINGBUFFER_H__
#define __MSM_RINGBUFFER_H__
+#include "drm/gpu_scheduler.h"
#include "msm_drv.h"
#define rbmemptr(ring, member) \
@@ -41,7 +42,18 @@ struct msm_ringbuffer {
uint32_t *start, *end, *cur, *next;
/*
+ * The job scheduler for this ring.
+ */
+ struct drm_gpu_scheduler sched;
+
+ /*
* List of in-flight submits on this ring. Protected by submit_lock.
+ *
+ * Currently just submits that are already written into the ring, not
+ * submits that are still in drm_gpu_scheduler's queues. At a later
+ * step we could probably move to letting drm_gpu_scheduler manage
+ * hangcheck detection and keep track of submit jobs that are in-
+ * flight.
*/
struct list_head submits;
spinlock_t submit_lock;
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
index c3d206105d28..32a55d81b58b 100644
--- a/drivers/gpu/drm/msm/msm_submitqueue.c
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -12,6 +12,10 @@ void msm_submitqueue_destroy(struct kref *kref)
struct msm_gpu_submitqueue *queue = container_of(kref,
struct msm_gpu_submitqueue, ref);
+ idr_destroy(&queue->fence_idr);
+
+ drm_sched_entity_destroy(&queue->entity);
+
msm_file_private_put(queue->ctx);
kfree(queue);
@@ -62,10 +66,22 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
{
struct msm_drm_private *priv = drm->dev_private;
struct msm_gpu_submitqueue *queue;
+ struct msm_ringbuffer *ring;
+ struct drm_gpu_scheduler *sched;
+ enum drm_sched_priority sched_prio;
+ unsigned ring_nr;
+ int ret;
if (!ctx)
return -ENODEV;
+ if (!priv->gpu)
+ return -ENODEV;
+
+ ret = msm_gpu_convert_priority(priv->gpu, prio, &ring_nr, &sched_prio);
+ if (ret)
+ return ret;
+
queue = kzalloc(sizeof(*queue), GFP_KERNEL);
if (!queue)
@@ -73,14 +89,16 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
kref_init(&queue->ref);
queue->flags = flags;
+ queue->ring_nr = ring_nr;
- if (priv->gpu) {
- if (prio >= priv->gpu->nr_rings) {
- kfree(queue);
- return -EINVAL;
- }
+ ring = priv->gpu->rb[ring_nr];
+ sched = &ring->sched;
- queue->prio = prio;
+ ret = drm_sched_entity_init(&queue->entity,
+ sched_prio, &sched, 1, NULL);
+ if (ret) {
+ kfree(queue);
+ return ret;
}
write_lock(&ctx->queuelock);
@@ -91,6 +109,9 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
if (id)
*id = queue->id;
+ idr_init(&queue->fence_idr);
+ mutex_init(&queue->lock);
+
list_add_tail(&queue->node, &ctx->submitqueues);
write_unlock(&ctx->queuelock);
@@ -98,20 +119,26 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
return 0;
}
+/*
+ * Create the default submit-queue (id==0), used for backwards compatibility
+ * for userspace that pre-dates the introduction of submitqueues.
+ */
int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx)
{
struct msm_drm_private *priv = drm->dev_private;
- int default_prio;
+ int default_prio, max_priority;
- if (!ctx)
- return 0;
+ if (!priv->gpu)
+ return -ENODEV;
+
+ max_priority = (priv->gpu->nr_rings * NR_SCHED_PRIORITIES) - 1;
/*
- * Select priority 2 as the "default priority" unless nr_rings is less
- * than 2 and then pick the lowest pirority
+ * Pick a medium priority level as default. Lower numeric value is
+ * higher priority, so round-up to pick a priority that is not higher
+ * than the middle priority level.
*/
- default_prio = priv->gpu ?
- clamp_t(uint32_t, 2, 0, priv->gpu->nr_rings - 1) : 0;
+ default_prio = DIV_ROUND_UP(max_priority, 2);
INIT_LIST_HEAD(&ctx->submitqueues);
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 6da93551e2e5..ec0432fe1bdf 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -24,7 +24,6 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_mode_config.h>
#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
@@ -51,6 +50,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
.hs_wdth_mask = 0xff,
.hs_wdth_shift = 24,
.has_overlay = false,
+ .has_ctrl2 = false,
},
[MXSFB_V4] = {
.transfer_count = LCDC_V4_TRANSFER_COUNT,
@@ -59,6 +59,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
.hs_wdth_mask = 0x3fff,
.hs_wdth_shift = 18,
.has_overlay = false,
+ .has_ctrl2 = true,
},
[MXSFB_V6] = {
.transfer_count = LCDC_V4_TRANSFER_COUNT,
@@ -67,6 +68,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
.hs_wdth_mask = 0x3fff,
.hs_wdth_shift = 18,
.has_overlay = true,
+ .has_ctrl2 = true,
},
};
@@ -150,6 +152,49 @@ static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb)
return 0;
}
+static irqreturn_t mxsfb_irq_handler(int irq, void *data)
+{
+ struct drm_device *drm = data;
+ struct mxsfb_drm_private *mxsfb = drm->dev_private;
+ u32 reg;
+
+ reg = readl(mxsfb->base + LCDC_CTRL1);
+
+ if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
+ drm_crtc_handle_vblank(&mxsfb->crtc);
+
+ writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+
+ return IRQ_HANDLED;
+}
+
+static void mxsfb_irq_disable(struct drm_device *drm)
+{
+ struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+ mxsfb_enable_axi_clk(mxsfb);
+ mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc);
+ mxsfb_disable_axi_clk(mxsfb);
+}
+
+static int mxsfb_irq_install(struct drm_device *dev, int irq)
+{
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ mxsfb_irq_disable(dev);
+
+ return request_irq(irq, mxsfb_irq_handler, 0, dev->driver->name, dev);
+}
+
+static void mxsfb_irq_uninstall(struct drm_device *dev)
+{
+ struct mxsfb_drm_private *mxsfb = dev->dev_private;
+
+ mxsfb_irq_disable(dev);
+ free_irq(mxsfb->irq, dev);
+}
+
static int mxsfb_load(struct drm_device *drm,
const struct mxsfb_devdata *devdata)
{
@@ -223,8 +268,13 @@ static int mxsfb_load(struct drm_device *drm,
drm_mode_config_reset(drm);
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ goto err_vblank;
+ mxsfb->irq = ret;
+
pm_runtime_get_sync(drm->dev);
- ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
+ ret = mxsfb_irq_install(drm, mxsfb->irq);
pm_runtime_put_sync(drm->dev);
if (ret < 0) {
@@ -252,7 +302,7 @@ static void mxsfb_unload(struct drm_device *drm)
drm_mode_config_cleanup(drm);
pm_runtime_get_sync(drm->dev);
- drm_irq_uninstall(drm);
+ mxsfb_irq_uninstall(drm);
pm_runtime_put_sync(drm->dev);
drm->dev_private = NULL;
@@ -260,38 +310,10 @@ static void mxsfb_unload(struct drm_device *drm)
pm_runtime_disable(drm->dev);
}
-static void mxsfb_irq_disable(struct drm_device *drm)
-{
- struct mxsfb_drm_private *mxsfb = drm->dev_private;
-
- mxsfb_enable_axi_clk(mxsfb);
- mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc);
- mxsfb_disable_axi_clk(mxsfb);
-}
-
-static irqreturn_t mxsfb_irq_handler(int irq, void *data)
-{
- struct drm_device *drm = data;
- struct mxsfb_drm_private *mxsfb = drm->dev_private;
- u32 reg;
-
- reg = readl(mxsfb->base + LCDC_CTRL1);
-
- if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
- drm_crtc_handle_vblank(&mxsfb->crtc);
-
- writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-
- return IRQ_HANDLED;
-}
-
DEFINE_DRM_GEM_CMA_FOPS(fops);
static const struct drm_driver mxsfb_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
- .irq_handler = mxsfb_irq_handler,
- .irq_preinstall = mxsfb_irq_disable,
- .irq_uninstall = mxsfb_irq_disable,
DRM_GEM_CMA_DRIVER_OPS,
.fops = &fops,
.name = "mxsfb-drm",
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 399d23e91ed1..ddb5b0417a82 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -22,6 +22,7 @@ struct mxsfb_devdata {
unsigned int hs_wdth_mask;
unsigned int hs_wdth_shift;
bool has_overlay;
+ bool has_ctrl2;
};
struct mxsfb_drm_private {
@@ -32,6 +33,8 @@ struct mxsfb_drm_private {
struct clk *clk_axi;
struct clk *clk_disp_axi;
+ unsigned int irq;
+
struct drm_device *drm;
struct {
struct drm_plane primary;
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 300e7bab0f43..89dd618d78f3 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -47,16 +47,13 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
* Setup the MXSFB registers for decoding the pixels out of the framebuffer and
* outputting them on the bus.
*/
-static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb)
+static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb,
+ const u32 bus_format)
{
struct drm_device *drm = mxsfb->drm;
const u32 format = mxsfb->crtc.primary->state->fb->format->format;
- u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
u32 ctrl, ctrl1;
- if (mxsfb->connector->display_info.num_bus_formats)
- bus_format = mxsfb->connector->display_info.bus_formats[0];
-
DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
bus_format);
@@ -107,6 +104,14 @@ static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
+ /* Increase number of outstanding requests on all supported IPs */
+ if (mxsfb->devdata->has_ctrl2) {
+ reg = readl(mxsfb->base + LCDC_V4_CTRL2);
+ reg &= ~CTRL2_SET_OUTSTANDING_REQS_MASK;
+ reg |= CTRL2_SET_OUTSTANDING_REQS_16;
+ writel(reg, mxsfb->base + LCDC_V4_CTRL2);
+ }
+
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
@@ -115,6 +120,35 @@ static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
reg |= VDCTRL4_SYNC_SIGNALS_ON;
writel(reg, mxsfb->base + LCDC_VDCTRL4);
+ /*
+ * Enable recovery on underflow.
+ *
+ * There is some sort of corner case behavior of the controller,
+ * which could rarely be triggered at least on i.MX6SX connected
+ * to 800x480 DPI panel and i.MX8MM connected to DPI->DSI->LVDS
+ * bridged 1920x1080 panel (and likely on other setups too), where
+ * the image on the panel shifts to the right and wraps around.
+ * This happens either when the controller is enabled on boot or
+ * even later during run time. The condition does not correct
+ * itself automatically, i.e. the display image remains shifted.
+ *
+ * It seems this problem is known and is due to sporadic underflows
+ * of the LCDIF FIFO. While the LCDIF IP does have underflow/overflow
+ * IRQs, neither of the IRQs trigger and neither IRQ status bit is
+ * asserted when this condition occurs.
+ *
+ * All known revisions of the LCDIF IP have CTRL1 RECOVER_ON_UNDERFLOW
+ * bit, which is described in the reference manual since i.MX23 as
+ * "
+ * Set this bit to enable the LCDIF block to recover in the next
+ * field/frame if there was an underflow in the current field/frame.
+ * "
+ * Enable this bit to mitigate the sporadic underflows.
+ */
+ reg = readl(mxsfb->base + LCDC_CTRL1);
+ reg |= CTRL1_RECOVER_ON_UNDERFLOW;
+ writel(reg, mxsfb->base + LCDC_CTRL1);
+
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
}
@@ -185,7 +219,8 @@ static dma_addr_t mxsfb_get_fb_paddr(struct drm_plane *plane)
return gem->paddr;
}
-static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
+static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb,
+ const u32 bus_format)
{
struct drm_device *drm = mxsfb->crtc.dev;
struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode;
@@ -206,11 +241,14 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
/* Clear the FIFOs */
writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
+ readl(mxsfb->base + LCDC_CTRL1);
+ writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+ readl(mxsfb->base + LCDC_CTRL1);
if (mxsfb->devdata->has_overlay)
writel(0, mxsfb->base + LCDC_AS_CTRL);
- mxsfb_set_formats(mxsfb);
+ mxsfb_set_formats(mxsfb, bus_format);
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
@@ -308,7 +346,9 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
+ struct drm_bridge_state *bridge_state;
struct drm_device *drm = mxsfb->drm;
+ u32 bus_format = 0;
dma_addr_t paddr;
pm_runtime_get_sync(drm->dev);
@@ -316,7 +356,23 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
drm_crtc_vblank_on(crtc);
- mxsfb_crtc_mode_set_nofb(mxsfb);
+ /* If there is a bridge attached to the LCDIF, use its bus format */
+ if (mxsfb->bridge) {
+ bridge_state =
+ drm_atomic_get_new_bridge_state(state,
+ mxsfb->bridge);
+ bus_format = bridge_state->input_bus_cfg.format;
+ }
+
+ /* If there is no bridge, use bus format from connector */
+ if (!bus_format && mxsfb->connector->display_info.num_bus_formats)
+ bus_format = mxsfb->connector->display_info.bus_formats[0];
+
+ /* If all else fails, default to RGB888_1X24 */
+ if (!bus_format)
+ bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+
+ mxsfb_crtc_mode_set_nofb(mxsfb, bus_format);
/* Write cur_buf as well to avoid an initial corrupt frame */
paddr = mxsfb_get_fb_paddr(crtc->primary);
@@ -500,13 +556,11 @@ static bool mxsfb_format_mod_supported(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = mxsfb_plane_atomic_check,
.atomic_update = mxsfb_plane_primary_atomic_update,
};
static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = mxsfb_plane_atomic_check,
.atomic_update = mxsfb_plane_overlay_atomic_update,
};
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 55d28a27f912..694fea13e893 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -15,6 +15,7 @@
#define LCDC_CTRL 0x00
#define LCDC_CTRL1 0x10
#define LCDC_V3_TRANSFER_COUNT 0x20
+#define LCDC_V4_CTRL2 0x20
#define LCDC_V4_TRANSFER_COUNT 0x30
#define LCDC_V4_CUR_BUF 0x40
#define LCDC_V4_NEXT_BUF 0x50
@@ -54,12 +55,20 @@
#define CTRL_DF24 BIT(1)
#define CTRL_RUN BIT(0)
+#define CTRL1_RECOVER_ON_UNDERFLOW BIT(24)
#define CTRL1_FIFO_CLEAR BIT(21)
#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
#define CTRL1_CUR_FRAME_DONE_IRQ_EN BIT(13)
#define CTRL1_CUR_FRAME_DONE_IRQ BIT(9)
+#define CTRL2_SET_OUTSTANDING_REQS_1 0
+#define CTRL2_SET_OUTSTANDING_REQS_2 (0x1 << 21)
+#define CTRL2_SET_OUTSTANDING_REQS_4 (0x2 << 21)
+#define CTRL2_SET_OUTSTANDING_REQS_8 (0x3 << 21)
+#define CTRL2_SET_OUTSTANDING_REQS_16 (0x4 << 21)
+#define CTRL2_SET_OUTSTANDING_REQS_MASK (0x7 << 21)
+
#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index bcb0310a41b6..d7b9f7f8c9e3 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -31,6 +31,7 @@
#include <linux/dma-mapping.h>
#include <linux/hdmi.h>
#include <linux/component.h>
+#include <linux/iopoll.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
@@ -1649,17 +1650,36 @@ nv50_sor_update(struct nouveau_encoder *nv_encoder, u8 head,
core->func->sor->ctrl(core, nv_encoder->or, nv_encoder->ctrl, asyh);
}
+/* TODO: Should we extend this to PWM-only backlights?
+ * As well, should we add a DRM helper for waiting for the backlight to acknowledge
+ * the panel backlight has been shut off? Intel doesn't seem to do this, and uses a
+ * fixed time delay from the vbios…
+ */
static void
nv50_sor_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *state)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
struct nouveau_connector *nv_connector = nv50_outp_get_old_connector(state, nv_encoder);
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+ struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
+ struct nouveau_backlight *backlight = nv_connector->backlight;
+#endif
struct drm_dp_aux *aux = &nv_connector->aux;
+ int ret;
u8 pwr;
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+ if (backlight && backlight->uses_dpcd) {
+ ret = drm_edp_backlight_disable(aux, &backlight->edp_info);
+ if (ret < 0)
+ NV_ERROR(drm, "Failed to disable backlight on [CONNECTOR:%d:%s]: %d\n",
+ nv_connector->base.base.id, nv_connector->base.name, ret);
+ }
+#endif
+
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
- int ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr);
+ ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr);
if (ret == 0) {
pwr &= ~DP_SET_POWER_MASK;
@@ -1696,6 +1716,9 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_connector *nv_connector;
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+ struct nouveau_backlight *backlight;
+#endif
struct nvbios *bios = &drm->vbios;
bool hda = false;
u8 proto = NV507D_SOR_SET_CONTROL_PROTOCOL_CUSTOM;
@@ -1770,6 +1793,14 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
proto = NV887D_SOR_SET_CONTROL_PROTOCOL_DP_B;
nv50_audio_enable(encoder, nv_crtc, nv_connector, state, mode);
+
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+ backlight = nv_connector->backlight;
+ if (backlight && backlight->uses_dpcd)
+ drm_edp_backlight_enable(&nv_connector->aux, &backlight->edp_info,
+ (u16)backlight->dev->props.brightness);
+#endif
+
break;
default:
BUG();
@@ -2322,6 +2353,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
nv50_crc_atomic_start_reporting(state);
if (!flushed)
nv50_crc_atomic_release_notifier_contexts(state);
+
drm_atomic_helper_commit_hw_done(state);
drm_atomic_helper_cleanup_planes(dev, state);
drm_atomic_helper_commit_cleanup_done(state);
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 72f35a2babcb..1cbd71abc80a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -42,11 +42,6 @@
static struct ida bl_ida;
#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
-struct nouveau_backlight {
- struct backlight_device *dev;
- int id;
-};
-
static bool
nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
struct nouveau_backlight *bl)
@@ -148,6 +143,98 @@ static const struct backlight_ops nv50_bl_ops = {
.update_status = nv50_set_intensity,
};
+/*
+ * eDP brightness callbacks need to happen under lock, since we need to
+ * enable/disable the backlight ourselves for modesets
+ */
+static int
+nv50_edp_get_brightness(struct backlight_device *bd)
+{
+ struct drm_connector *connector = dev_get_drvdata(bd->dev.parent);
+ struct drm_device *dev = connector->dev;
+ struct drm_crtc *crtc;
+ struct drm_modeset_acquire_ctx ctx;
+ int ret = 0;
+
+ drm_modeset_acquire_init(&ctx, 0);
+
+retry:
+ ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
+ if (ret == -EDEADLK)
+ goto deadlock;
+ else if (ret < 0)
+ goto out;
+
+ crtc = connector->state->crtc;
+ if (!crtc)
+ goto out;
+
+ ret = drm_modeset_lock(&crtc->mutex, &ctx);
+ if (ret == -EDEADLK)
+ goto deadlock;
+ else if (ret < 0)
+ goto out;
+
+ if (!crtc->state->active)
+ goto out;
+
+ ret = bd->props.brightness;
+out:
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+ return ret;
+deadlock:
+ drm_modeset_backoff(&ctx);
+ goto retry;
+}
+
+static int
+nv50_edp_set_brightness(struct backlight_device *bd)
+{
+ struct drm_connector *connector = dev_get_drvdata(bd->dev.parent);
+ struct nouveau_connector *nv_connector = nouveau_connector(connector);
+ struct drm_device *dev = connector->dev;
+ struct drm_crtc *crtc;
+ struct drm_dp_aux *aux = &nv_connector->aux;
+ struct nouveau_backlight *nv_bl = nv_connector->backlight;
+ struct drm_modeset_acquire_ctx ctx;
+ int ret = 0;
+
+ drm_modeset_acquire_init(&ctx, 0);
+retry:
+ ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
+ if (ret == -EDEADLK)
+ goto deadlock;
+ else if (ret < 0)
+ goto out;
+
+ crtc = connector->state->crtc;
+ if (!crtc)
+ goto out;
+
+ ret = drm_modeset_lock(&crtc->mutex, &ctx);
+ if (ret == -EDEADLK)
+ goto deadlock;
+ else if (ret < 0)
+ goto out;
+
+ if (crtc->state->active)
+ ret = drm_edp_backlight_set_level(aux, &nv_bl->edp_info, bd->props.brightness);
+
+out:
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+ return ret;
+deadlock:
+ drm_modeset_backoff(&ctx);
+ goto retry;
+}
+
+static const struct backlight_ops nv50_edp_bl_ops = {
+ .get_brightness = nv50_edp_get_brightness,
+ .update_status = nv50_edp_set_brightness,
+};
+
static int
nva3_get_intensity(struct backlight_device *bd)
{
@@ -194,8 +281,13 @@ static const struct backlight_ops nva3_bl_ops = {
.update_status = nva3_set_intensity,
};
+/* FIXME: perform backlight probing for eDP _before_ this, this only gets called after connector
+ * registration which happens after the initial modeset
+ */
static int
-nv50_backlight_init(struct nouveau_encoder *nv_encoder,
+nv50_backlight_init(struct nouveau_backlight *bl,
+ struct nouveau_connector *nv_conn,
+ struct nouveau_encoder *nv_encoder,
struct backlight_properties *props,
const struct backlight_ops **ops)
{
@@ -205,6 +297,41 @@ nv50_backlight_init(struct nouveau_encoder *nv_encoder,
if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)))
return -ENODEV;
+ if (nv_conn->type == DCB_CONNECTOR_eDP) {
+ int ret;
+ u16 current_level;
+ u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
+ u8 current_mode;
+
+ ret = drm_dp_dpcd_read(&nv_conn->aux, DP_EDP_DPCD_REV, edp_dpcd,
+ EDP_DISPLAY_CTL_CAP_SIZE);
+ if (ret < 0)
+ return ret;
+
+ if (drm_edp_backlight_supported(edp_dpcd)) {
+ NV_DEBUG(drm, "DPCD backlight controls supported on %s\n",
+ nv_conn->base.name);
+
+ ret = drm_edp_backlight_init(&nv_conn->aux, &bl->edp_info, 0, edp_dpcd,
+ &current_level, &current_mode);
+ if (ret < 0)
+ return ret;
+
+ ret = drm_edp_backlight_enable(&nv_conn->aux, &bl->edp_info, current_level);
+ if (ret < 0) {
+ NV_ERROR(drm, "Failed to enable backlight on %s: %d\n",
+ nv_conn->base.name, ret);
+ return ret;
+ }
+
+ *ops = &nv50_edp_bl_ops;
+ props->brightness = current_level;
+ props->max_brightness = bl->edp_info.max;
+ bl->uses_dpcd = true;
+ return 0;
+ }
+ }
+
if (drm->client.device.info.chipset <= 0xa0 ||
drm->client.device.info.chipset == 0xaa ||
drm->client.device.info.chipset == 0xac)
@@ -245,6 +372,10 @@ nouveau_backlight_init(struct drm_connector *connector)
if (!nv_encoder)
return 0;
+ bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+ if (!bl)
+ return -ENOMEM;
+
switch (device->info.family) {
case NV_DEVICE_INFO_V0_CURIE:
ret = nv40_backlight_init(nv_encoder, &props, &ops);
@@ -257,20 +388,19 @@ nouveau_backlight_init(struct drm_connector *connector)
case NV_DEVICE_INFO_V0_VOLTA:
case NV_DEVICE_INFO_V0_TURING:
case NV_DEVICE_INFO_V0_AMPERE: //XXX: not confirmed
- ret = nv50_backlight_init(nv_encoder, &props, &ops);
+ ret = nv50_backlight_init(bl, nouveau_connector(connector),
+ nv_encoder, &props, &ops);
break;
default:
- return 0;
+ ret = 0;
+ goto fail_alloc;
}
- if (ret == -ENODEV)
- return 0;
- else if (ret)
- return ret;
-
- bl = kzalloc(sizeof(*bl), GFP_KERNEL);
- if (!bl)
- return -ENOMEM;
+ if (ret) {
+ if (ret == -ENODEV)
+ ret = 0;
+ goto fail_alloc;
+ }
if (!nouveau_get_backlight_name(backlight_name, bl)) {
NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
@@ -287,7 +417,9 @@ nouveau_backlight_init(struct drm_connector *connector)
}
nouveau_connector(connector)->backlight = bl;
- bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev);
+ if (!bl->dev->props.brightness)
+ bl->dev->props.brightness =
+ bl->dev->ops->get_brightness(bl->dev);
backlight_update_status(bl->dev);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index d0b859c4a80e..40f90e353540 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -46,7 +46,14 @@ struct nvkm_i2c_port;
struct dcb_output;
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-struct nouveau_backlight;
+struct nouveau_backlight {
+ struct backlight_device *dev;
+
+ struct drm_edp_backlight_info edp_info;
+ bool uses_dpcd : 1;
+
+ int id;
+};
#endif
#define nouveau_conn_atom(p) \
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index ba4cd5f83725..1f828c9f691c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -554,8 +554,6 @@ nouveau_drm_device_init(struct drm_device *dev)
if (ret)
goto fail_master;
- dev->irq_enabled = true;
-
nvxx_client(&drm->client.base)->debug =
nvkm_dbgopt(nouveau_debug, "DRM");
@@ -739,7 +737,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
nvkm_device_del(&device);
/* Remove conflicting drivers (vesafb, efifb etc). */
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "nouveaufb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver_pci);
if (ret)
return ret;
@@ -796,7 +794,6 @@ nouveau_drm_device_remove(struct drm_device *dev)
drm_dev_unregister(dev);
- dev->irq_enabled = false;
client = nvxx_client(&drm->client.base);
device = nvkm_device_find(client->device);
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index 1ffcc0a491fd..77c2fed76e8b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -30,6 +30,7 @@
#include <subdev/bios/dcb.h>
#include <drm/drm_encoder_slave.h>
+#include <drm/drm_dp_helper.h>
#include <drm/drm_dp_mst_helper.h>
#include "dispnv04/disp.h"
struct nv50_head_atom;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 6b43918035df..05d0b3eb3690 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -358,7 +358,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
fobj = dma_resv_shared_list(resv);
fence = dma_resv_excl_fence(resv);
- if (fence && (!exclusive || !fobj || !fobj->shared_count)) {
+ if (fence) {
struct nouveau_channel *prev = NULL;
bool must_wait = true;
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index f4c2e46b6fe1..2ca9d9a9e5d5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -276,7 +276,7 @@ nouveau_ttm_init(struct nouveau_drm *drm)
}
#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86)
- need_swiotlb = is_swiotlb_active();
+ need_swiotlb = is_swiotlb_active(dev->dev);
#endif
ret = ttm_device_init(&drm->ttm.bdev, &nouveau_bo_driver, drm->dev->dev,
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 7c4b374b3eca..60cd8c0463df 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -11,9 +11,9 @@
#include "nouveau_vga.h"
static unsigned int
-nouveau_vga_set_decode(void *priv, bool state)
+nouveau_vga_set_decode(struct pci_dev *pdev, bool state)
{
- struct nouveau_drm *drm = nouveau_drm(priv);
+ struct nouveau_drm *drm = nouveau_drm(pci_get_drvdata(pdev));
struct nvif_object *device = &drm->client.device.object;
if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE &&
@@ -94,7 +94,7 @@ nouveau_vga_init(struct nouveau_drm *drm)
return;
pdev = to_pci_dev(dev->dev);
- vga_client_register(pdev, dev, NULL, nouveau_vga_set_decode);
+ vga_client_register(pdev, nouveau_vga_set_decode);
/* don't register Thunderbolt eGPU with vga_switcheroo */
if (pci_is_thunderbolt_attached(pdev))
@@ -118,7 +118,7 @@ nouveau_vga_fini(struct nouveau_drm *drm)
return;
pdev = to_pci_dev(dev->dev);
- vga_client_register(pdev, NULL, NULL, NULL);
+ vga_client_unregister(pdev);
if (pci_is_thunderbolt_attached(pdev))
return;
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 8632139e0f01..f86e20578143 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -290,12 +290,8 @@ static int omap_modeset_init(struct drm_device *dev)
ret = drm_bridge_attach(pipe->encoder,
pipe->output->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
- if (ret < 0) {
- dev_err(priv->dev,
- "unable to attach bridge %pOF\n",
- pipe->output->bridge->of_node);
+ if (ret < 0)
return ret;
- }
}
id = omap_display_id(pipe->output);
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index d6f136984da9..591d4c273f02 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -48,6 +48,8 @@ struct omap_drm_private {
struct dss_device *dss;
struct dispc_device *dispc;
+ bool irq_enabled;
+
unsigned int num_pipes;
struct omap_drm_pipeline pipes[8];
struct omap_drm_pipeline *channels[8];
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 15148d4b35b5..4aca14dab927 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -253,13 +253,6 @@ static const u32 omap_underflow_irqs[] = {
[OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
};
-/*
- * We need a special version, instead of just using drm_irq_install(),
- * because we need to register the irq via omapdss. Once omapdss and
- * omapdrm are merged together we can assign the dispc hwmod data to
- * ourselves and drop these and just use drm_irq_{install,uninstall}()
- */
-
int omap_drm_irq_install(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
@@ -291,7 +284,7 @@ int omap_drm_irq_install(struct drm_device *dev)
if (ret < 0)
return ret;
- dev->irq_enabled = true;
+ priv->irq_enabled = true;
return 0;
}
@@ -300,10 +293,10 @@ void omap_drm_irq_uninstall(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
- if (!dev->irq_enabled)
+ if (!priv->irq_enabled)
return;
- dev->irq_enabled = false;
+ priv->irq_enabled = false;
dispc_free_irq(priv->dispc, dev);
}
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 801da917507d..512af976b7e9 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -6,6 +6,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include "omap_dmm_tiler.h"
@@ -29,6 +30,8 @@ static int omap_plane_prepare_fb(struct drm_plane *plane,
if (!new_state->fb)
return 0;
+ drm_gem_plane_helper_prepare_fb(plane, new_state);
+
return omap_framebuffer_pin(new_state->fb);
}
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index ef87d92cdf49..beb581b96ecd 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -82,6 +82,7 @@ config DRM_PANEL_SIMPLE
depends on BACKLIGHT_CLASS_DEVICE
depends on PM
select VIDEOMODE_HELPERS
+ select DRM_DP_AUX_BUS
help
DRM panel driver for dumb panels that need at most a regulator and
a GPIO to be powered up. Optionally a backlight can be attached so
@@ -124,6 +125,18 @@ config DRM_PANEL_ILITEK_IL9322
Say Y here if you want to enable support for Ilitek IL9322
QVGA (320x240) RGB, YUV and ITU-T BT.656 panels.
+config DRM_PANEL_ILITEK_ILI9341
+ tristate "Ilitek ILI9341 240x320 QVGA panels"
+ depends on OF && SPI
+ depends on DRM_KMS_HELPER
+ depends on DRM_KMS_CMA_HELPER
+ depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_MIPI_DBI
+ help
+ Say Y here if you want to enable support for Ilitek IL9341
+ QVGA (240x320) RGB panels. support serial & parallel rgb
+ interface.
+
config DRM_PANEL_ILITEK_ILI9881C
tristate "Ilitek ILI9881C-based panels"
depends on OF
@@ -133,6 +146,15 @@ config DRM_PANEL_ILITEK_ILI9881C
Say Y if you want to enable support for panels based on the
Ilitek ILI9881c controller.
+config DRM_PANEL_INNOLUX_EJ030NA
+ tristate "Innolux EJ030NA 320x480 LCD panel"
+ depends on OF && SPI
+ select REGMAP_SPI
+ help
+ Say Y here to enable support for the Innolux/Chimei EJ030NA
+ 320x480 3.0" panel as found in the RS97 V2.1, RG300(non-ips)
+ and LDK handheld gaming consoles.
+
config DRM_PANEL_INNOLUX_P079ZCA
tristate "Innolux P079ZCA panel"
depends on OF
@@ -343,6 +365,27 @@ config DRM_PANEL_RONBO_RB070D30
Say Y here if you want to enable support for Ronbo Electronics
RB070D30 1024x600 DSI panel.
+config DRM_PANEL_SAMSUNG_ATNA33XC20
+ tristate "Samsung ATNA33XC20 eDP panel"
+ depends on OF
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on PM
+ select DRM_DP_AUX_BUS
+ help
+ DRM panel driver for the Samsung ATNA33XC20 panel. This panel can't
+ be handled by the DRM_PANEL_SIMPLE driver because its power
+ sequencing is non-standard.
+
+config DRM_PANEL_SAMSUNG_DB7430
+ tristate "Samsung DB7430-based DPI panels"
+ depends on OF && SPI && GPIOLIB
+ depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_MIPI_DBI
+ help
+ Say Y here if you want to enable support for the Samsung
+ DB7430 DPI display controller used in such devices as the
+ LMS397KF04 480x800 DPI panel.
+
config DRM_PANEL_SAMSUNG_S6D16D0
tristate "Samsung S6D16D0 DSI video mode panel"
depends on OF
@@ -377,6 +420,7 @@ config DRM_PANEL_SAMSUNG_S6E63M0_SPI
depends on SPI
depends on DRM_PANEL_SAMSUNG_S6E63M0
default DRM_PANEL_SAMSUNG_S6E63M0
+ select DRM_MIPI_DBI
help
Say Y here if you want to be able to access the Samsung
S6E63M0 panel using SPI.
@@ -553,6 +597,16 @@ config DRM_PANEL_VISIONOX_RM69299
Say Y here if you want to enable support for Visionox
RM69299 DSI Video Mode panel.
+config DRM_PANEL_WIDECHIPS_WS2401
+ tristate "Widechips WS2401 DPI panel driver"
+ depends on SPI && GPIOLIB
+ depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_MIPI_DBI
+ help
+ Say Y here if you want to enable support for the Widechips WS2401 DPI
+ 480x800 display controller used in panels such as Samsung LMS380KF01.
+ This display is used in the Samsung Galaxy Ace 2 GT-I8160 (Codina).
+
config DRM_PANEL_XINPENG_XPP055C272
tristate "Xinpeng XPP055C272 panel driver"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index cae4d976c069..c8132050bcec 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -11,7 +11,9 @@ obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o
obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
+obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
+obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o
obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o
@@ -33,6 +35,8 @@ obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen
obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o
obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
@@ -58,4 +62,5 @@ obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
+obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o
obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
diff --git a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
index e95bc9f60b3f..44674ebedf59 100644
--- a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
+++ b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
@@ -302,7 +302,7 @@ static int tm5p5_nt35596_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
- MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
+ MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_NO_EOT_PACKET |
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
drm_panel_init(&ctx->panel, dev, &tm5p5_nt35596_panel_funcs,
diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c b/drivers/gpu/drm/panel/panel-dsi-cm.c
index 5fbfb71ca3d9..da4a69067e18 100644
--- a/drivers/gpu/drm/panel/panel-dsi-cm.c
+++ b/drivers/gpu/drm/panel/panel-dsi-cm.c
@@ -574,7 +574,7 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 2;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
- MIPI_DSI_MODE_EOT_PACKET;
+ MIPI_DSI_MODE_NO_EOT_PACKET;
dsi->hs_rate = ddata->panel_data->max_hs_rate;
dsi->lp_rate = ddata->panel_data->max_lp_rate;
diff --git a/drivers/gpu/drm/panel/panel-elida-kd35t133.c b/drivers/gpu/drm/panel/panel-elida-kd35t133.c
index 4787f0833264..80227617a4d6 100644
--- a/drivers/gpu/drm/panel/panel-elida-kd35t133.c
+++ b/drivers/gpu/drm/panel/panel-elida-kd35t133.c
@@ -273,7 +273,7 @@ static int kd35t133_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 1;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
- MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET |
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET |
MIPI_DSI_CLOCK_NON_CONTINUOUS;
drm_panel_init(&ctx->panel, &dsi->dev, &kd35t133_funcs,
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
new file mode 100644
index 000000000000..2c3378a259b1
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
@@ -0,0 +1,792 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Ilitek ILI9341 TFT LCD drm_panel driver.
+ *
+ * This panel can be configured to support:
+ * - 16-bit parallel RGB interface
+ * - 18-bit parallel RGB interface
+ * - 4-line serial spi interface
+ *
+ * Copyright (C) 2021 Dillon Min <dillon.minfei@gmail.com>
+ *
+ * For dbi+dpi part:
+ * Derived from drivers/drm/gpu/panel/panel-ilitek-ili9322.c
+ * the reuse of DBI abstraction part referred from Linus's patch
+ * "drm/panel: s6e63m0: Switch to DBI abstraction for SPI"
+ *
+ * For only-dbi part, copy from David's code (drm/tiny/ili9341.c)
+ * Copyright 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#define ILI9341_RGB_INTERFACE 0xb0 /* RGB Interface Signal Control */
+#define ILI9341_FRC 0xb1 /* Frame Rate Control register */
+#define ILI9341_DFC 0xb6 /* Display Function Control register */
+#define ILI9341_POWER1 0xc0 /* Power Control 1 register */
+#define ILI9341_POWER2 0xc1 /* Power Control 2 register */
+#define ILI9341_VCOM1 0xc5 /* VCOM Control 1 register */
+#define ILI9341_VCOM2 0xc7 /* VCOM Control 2 register */
+#define ILI9341_POWERA 0xcb /* Power control A register */
+#define ILI9341_POWERB 0xcf /* Power control B register */
+#define ILI9341_PGAMMA 0xe0 /* Positive Gamma Correction register */
+#define ILI9341_NGAMMA 0xe1 /* Negative Gamma Correction register */
+#define ILI9341_DTCA 0xe8 /* Driver timing control A */
+#define ILI9341_DTCB 0xea /* Driver timing control B */
+#define ILI9341_POWER_SEQ 0xed /* Power on sequence register */
+#define ILI9341_3GAMMA_EN 0xf2 /* 3 Gamma enable register */
+#define ILI9341_INTERFACE 0xf6 /* Interface control register */
+#define ILI9341_PRC 0xf7 /* Pump ratio control register */
+#define ILI9341_ETMOD 0xb7 /* Entry mode set */
+
+#define ILI9341_MADCTL_BGR BIT(3)
+#define ILI9341_MADCTL_MV BIT(5)
+#define ILI9341_MADCTL_MX BIT(6)
+#define ILI9341_MADCTL_MY BIT(7)
+
+#define ILI9341_POWER_B_LEN 3
+#define ILI9341_POWER_SEQ_LEN 4
+#define ILI9341_DTCA_LEN 3
+#define ILI9341_DTCB_LEN 2
+#define ILI9341_POWER_A_LEN 5
+#define ILI9341_DFC_1_LEN 2
+#define ILI9341_FRC_LEN 2
+#define ILI9341_VCOM_1_LEN 2
+#define ILI9341_DFC_2_LEN 4
+#define ILI9341_COLUMN_ADDR_LEN 4
+#define ILI9341_PAGE_ADDR_LEN 4
+#define ILI9341_INTERFACE_LEN 3
+#define ILI9341_PGAMMA_LEN 15
+#define ILI9341_NGAMMA_LEN 15
+#define ILI9341_CA_LEN 3
+
+#define ILI9341_PIXEL_DPI_16_BITS (BIT(6) | BIT(4))
+#define ILI9341_PIXEL_DPI_18_BITS (BIT(6) | BIT(5))
+#define ILI9341_GAMMA_CURVE_1 BIT(0)
+#define ILI9341_IF_WE_MODE BIT(0)
+#define ILI9341_IF_BIG_ENDIAN 0x00
+#define ILI9341_IF_DM_RGB BIT(2)
+#define ILI9341_IF_DM_INTERNAL 0x00
+#define ILI9341_IF_DM_VSYNC BIT(3)
+#define ILI9341_IF_RM_RGB BIT(1)
+#define ILI9341_IF_RIM_RGB 0x00
+
+#define ILI9341_COLUMN_ADDR 0x00ef
+#define ILI9341_PAGE_ADDR 0x013f
+
+#define ILI9341_RGB_EPL BIT(0)
+#define ILI9341_RGB_DPL BIT(1)
+#define ILI9341_RGB_HSPL BIT(2)
+#define ILI9341_RGB_VSPL BIT(3)
+#define ILI9341_RGB_DE_MODE BIT(6)
+#define ILI9341_RGB_DISP_PATH_MEM BIT(7)
+
+#define ILI9341_DBI_VCOMH_4P6V 0x23
+#define ILI9341_DBI_PWR_2_DEFAULT 0x10
+#define ILI9341_DBI_PRC_NORMAL 0x20
+#define ILI9341_DBI_VCOM_1_VMH_4P25V 0x3e
+#define ILI9341_DBI_VCOM_1_VML_1P5V 0x28
+#define ILI9341_DBI_VCOM_2_DEC_58 0x86
+#define ILI9341_DBI_FRC_DIVA 0x00
+#define ILI9341_DBI_FRC_RTNA 0x1b
+#define ILI9341_DBI_EMS_GAS BIT(0)
+#define ILI9341_DBI_EMS_DTS BIT(1)
+#define ILI9341_DBI_EMS_GON BIT(2)
+
+/* struct ili9341_config - the system specific ILI9341 configuration */
+struct ili9341_config {
+ u32 max_spi_speed;
+ /* mode: the drm display mode */
+ const struct drm_display_mode mode;
+ /* ca: TODO: need comments for this register */
+ u8 ca[ILI9341_CA_LEN];
+ /* power_b: TODO: need comments for this register */
+ u8 power_b[ILI9341_POWER_B_LEN];
+ /* power_seq: TODO: need comments for this register */
+ u8 power_seq[ILI9341_POWER_SEQ_LEN];
+ /* dtca: TODO: need comments for this register */
+ u8 dtca[ILI9341_DTCA_LEN];
+ /* dtcb: TODO: need comments for this register */
+ u8 dtcb[ILI9341_DTCB_LEN];
+ /* power_a: TODO: need comments for this register */
+ u8 power_a[ILI9341_POWER_A_LEN];
+ /* frc: Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
+ u8 frc[ILI9341_FRC_LEN];
+ /* prc: TODO: need comments for this register */
+ u8 prc;
+ /* dfc_1: B6h DISCTRL (Display Function Control) */
+ u8 dfc_1[ILI9341_DFC_1_LEN];
+ /* power_1: Power Control 1 (C0h) */
+ u8 power_1;
+ /* power_2: Power Control 2 (C1h) */
+ u8 power_2;
+ /* vcom_1: VCOM Control 1(C5h) */
+ u8 vcom_1[ILI9341_VCOM_1_LEN];
+ /* vcom_2: VCOM Control 2(C7h) */
+ u8 vcom_2;
+ /* address_mode: Memory Access Control (36h) */
+ u8 address_mode;
+ /* g3amma_en: TODO: need comments for this register */
+ u8 g3amma_en;
+ /* rgb_interface: RGB Interface Signal Control (B0h) */
+ u8 rgb_interface;
+ /* dfc_2: refer to dfc_1 */
+ u8 dfc_2[ILI9341_DFC_2_LEN];
+ /* column_addr: Column Address Set (2Ah) */
+ u8 column_addr[ILI9341_COLUMN_ADDR_LEN];
+ /* page_addr: Page Address Set (2Bh) */
+ u8 page_addr[ILI9341_PAGE_ADDR_LEN];
+ /* interface: Interface Control (F6h) */
+ u8 interface[ILI9341_INTERFACE_LEN];
+ /*
+ * pixel_format: This command sets the pixel format for the RGB
+ * image data used by
+ */
+ u8 pixel_format;
+ /*
+ * gamma_curve: This command is used to select the desired Gamma
+ * curve for the
+ */
+ u8 gamma_curve;
+ /* pgamma: Positive Gamma Correction (E0h) */
+ u8 pgamma[ILI9341_PGAMMA_LEN];
+ /* ngamma: Negative Gamma Correction (E1h) */
+ u8 ngamma[ILI9341_NGAMMA_LEN];
+};
+
+struct ili9341 {
+ struct device *dev;
+ const struct ili9341_config *conf;
+ struct drm_panel panel;
+ struct gpio_desc *reset_gpio;
+ struct gpio_desc *dc_gpio;
+ struct mipi_dbi *dbi;
+ u32 max_spi_speed;
+ struct regulator_bulk_data supplies[3];
+};
+
+/*
+ * The Stm32f429-disco board has a panel ili9341 connected to ltdc controller
+ */
+static const struct ili9341_config ili9341_stm32f429_disco_data = {
+ .max_spi_speed = 10000000,
+ .mode = {
+ .clock = 6100,
+ .hdisplay = 240,
+ .hsync_start = 240 + 10,/* hfp 10 */
+ .hsync_end = 240 + 10 + 10,/* hsync 10 */
+ .htotal = 240 + 10 + 10 + 20,/* hbp 20 */
+ .vdisplay = 320,
+ .vsync_start = 320 + 4,/* vfp 4 */
+ .vsync_end = 320 + 4 + 2,/* vsync 2 */
+ .vtotal = 320 + 4 + 2 + 2,/* vbp 2 */
+ .flags = 0,
+ .width_mm = 65,
+ .height_mm = 50,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ },
+ .ca = {0xc3, 0x08, 0x50},
+ .power_b = {0x00, 0xc1, 0x30},
+ .power_seq = {0x64, 0x03, 0x12, 0x81},
+ .dtca = {0x85, 0x00, 0x78},
+ .power_a = {0x39, 0x2c, 0x00, 0x34, 0x02},
+ .prc = 0x20,
+ .dtcb = {0x00, 0x00},
+ /* 0x00 fosc, 0x1b 70hz */
+ .frc = {0x00, 0x1b},
+ /*
+ * 0x0a Interval scan, AGND AGND AGND AGND
+ * 0xa2 Normally white, G1 -> G320, S720 -> S1,
+ * Scan Cycle 5 frames,85ms
+ */
+ .dfc_1 = {0x0a, 0xa2},
+ /* 0x10 3.65v */
+ .power_1 = 0x10,
+ /* 0x10 AVDD=vci*2, VGH=vci*7, VGL=-vci*4 */
+ .power_2 = 0x10,
+ /* 0x45 VCOMH 4.425v, 0x15 VCOML -1.975*/
+ .vcom_1 = {0x45, 0x15},
+ /* 0x90 offset voltage, VMH-48, VML-48 */
+ .vcom_2 = 0x90,
+ /*
+ * 0xc8 Row Address Order, Column Address Order
+ * BGR 1
+ */
+ .address_mode = 0xc8,
+ .g3amma_en = 0x00,
+ /*
+ * 0xc2
+ * Display Data Path: Memory
+ * RGB: DE mode
+ * DOTCLK polarity set (data fetched at the falling time)
+ */
+ .rgb_interface = ILI9341_RGB_DISP_PATH_MEM |
+ ILI9341_RGB_DE_MODE |
+ ILI9341_RGB_DPL,
+ /*
+ * 0x0a
+ * Gate outputs in non-display area: Interval scan
+ * Determine source/VCOM output in a non-display area in the partial
+ * display mode: AGND AGND AGND AGND
+ *
+ * 0xa7
+ * Scan Cycle: 15 frames
+ * fFLM = 60Hz: 255ms
+ * Liquid crystal type: Normally white
+ * Gate Output Scan Direction: G1 -> G320
+ * Source Output Scan Direction: S720 -> S1
+ *
+ * 0x27
+ * LCD Driver Line: 320 lines
+ *
+ * 0x04
+ * PCDIV: 4
+ */
+ .dfc_2 = {0x0a, 0xa7, 0x27, 0x04},
+ /* column address: 240 */
+ .column_addr = {0x00, 0x00, (ILI9341_COLUMN_ADDR >> 4) & 0xff,
+ ILI9341_COLUMN_ADDR & 0xff},
+ /* page address: 320 */
+ .page_addr = {0x00, 0x00, (ILI9341_PAGE_ADDR >> 4) & 0xff,
+ ILI9341_PAGE_ADDR & 0xff},
+ /*
+ * Memory write control: When the transfer number of data exceeds
+ * (EC-SC+1)*(EP-SP+1), the column and page number will be
+ * reset, and the exceeding data will be written into the following
+ * column and page.
+ * Display Operation Mode: RGB Interface Mode
+ * Interface for RAM Access: RGB interface
+ * 16- bit RGB interface (1 transfer/pixel)
+ */
+ .interface = {ILI9341_IF_WE_MODE, 0x00,
+ ILI9341_IF_DM_RGB | ILI9341_IF_RM_RGB},
+ /* DPI: 16 bits / pixel */
+ .pixel_format = ILI9341_PIXEL_DPI_16_BITS,
+ /* Curve Selected: Gamma curve 1 (G2.2) */
+ .gamma_curve = ILI9341_GAMMA_CURVE_1,
+ .pgamma = {0x0f, 0x29, 0x24, 0x0c, 0x0e,
+ 0x09, 0x4e, 0x78, 0x3c, 0x09,
+ 0x13, 0x05, 0x17, 0x11, 0x00},
+ .ngamma = {0x00, 0x16, 0x1b, 0x04, 0x11,
+ 0x07, 0x31, 0x33, 0x42, 0x05,
+ 0x0c, 0x0a, 0x28, 0x2f, 0x0f},
+};
+
+static inline struct ili9341 *panel_to_ili9341(struct drm_panel *panel)
+{
+ return container_of(panel, struct ili9341, panel);
+}
+
+static void ili9341_dpi_init(struct ili9341 *ili)
+{
+ struct device *dev = (&ili->panel)->dev;
+ struct mipi_dbi *dbi = ili->dbi;
+ struct ili9341_config *cfg = (struct ili9341_config *)ili->conf;
+
+ /* Power Control */
+ mipi_dbi_command_stackbuf(dbi, 0xca, cfg->ca, ILI9341_CA_LEN);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_POWERB, cfg->power_b,
+ ILI9341_POWER_B_LEN);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_POWER_SEQ, cfg->power_seq,
+ ILI9341_POWER_SEQ_LEN);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_DTCA, cfg->dtca,
+ ILI9341_DTCA_LEN);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_POWERA, cfg->power_a,
+ ILI9341_POWER_A_LEN);
+ mipi_dbi_command(ili->dbi, ILI9341_PRC, cfg->prc);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_DTCB, cfg->dtcb,
+ ILI9341_DTCB_LEN);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_FRC, cfg->frc, ILI9341_FRC_LEN);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_DFC, cfg->dfc_1,
+ ILI9341_DFC_1_LEN);
+ mipi_dbi_command(dbi, ILI9341_POWER1, cfg->power_1);
+ mipi_dbi_command(dbi, ILI9341_POWER2, cfg->power_2);
+
+ /* VCOM */
+ mipi_dbi_command_stackbuf(dbi, ILI9341_VCOM1, cfg->vcom_1,
+ ILI9341_VCOM_1_LEN);
+ mipi_dbi_command(dbi, ILI9341_VCOM2, cfg->vcom_2);
+ mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, cfg->address_mode);
+
+ /* Gamma */
+ mipi_dbi_command(dbi, ILI9341_3GAMMA_EN, cfg->g3amma_en);
+ mipi_dbi_command(dbi, ILI9341_RGB_INTERFACE, cfg->rgb_interface);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_DFC, cfg->dfc_2,
+ ILI9341_DFC_2_LEN);
+
+ /* Colomn address set */
+ mipi_dbi_command_stackbuf(dbi, MIPI_DCS_SET_COLUMN_ADDRESS,
+ cfg->column_addr, ILI9341_COLUMN_ADDR_LEN);
+
+ /* Page address set */
+ mipi_dbi_command_stackbuf(dbi, MIPI_DCS_SET_PAGE_ADDRESS,
+ cfg->page_addr, ILI9341_PAGE_ADDR_LEN);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_INTERFACE, cfg->interface,
+ ILI9341_INTERFACE_LEN);
+
+ /* Format */
+ mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, cfg->pixel_format);
+ mipi_dbi_command(dbi, MIPI_DCS_WRITE_MEMORY_START);
+ msleep(200);
+ mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, cfg->gamma_curve);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_PGAMMA, cfg->pgamma,
+ ILI9341_PGAMMA_LEN);
+ mipi_dbi_command_stackbuf(dbi, ILI9341_NGAMMA, cfg->ngamma,
+ ILI9341_NGAMMA_LEN);
+ mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+ msleep(200);
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+ mipi_dbi_command(dbi, MIPI_DCS_WRITE_MEMORY_START);
+
+ dev_info(dev, "Initialized display rgb interface\n");
+}
+
+static int ili9341_dpi_power_on(struct ili9341 *ili)
+{
+ struct device *dev = (&ili->panel)->dev;
+ int ret = 0;
+
+ /* Assert RESET */
+ gpiod_set_value(ili->reset_gpio, 1);
+
+ /* Enable power */
+ ret = regulator_bulk_enable(ARRAY_SIZE(ili->supplies),
+ ili->supplies);
+ if (ret < 0) {
+ dev_err(dev, "unable to enable vcc\n");
+ return ret;
+ }
+ msleep(20);
+
+ /* De-assert RESET */
+ gpiod_set_value(ili->reset_gpio, 0);
+ msleep(20);
+
+ return 0;
+}
+
+static int ili9341_dpi_power_off(struct ili9341 *ili)
+{
+ /* Assert RESET */
+ gpiod_set_value(ili->reset_gpio, 1);
+
+ /* Disable power */
+ return regulator_bulk_disable(ARRAY_SIZE(ili->supplies),
+ ili->supplies);
+}
+
+static int ili9341_dpi_disable(struct drm_panel *panel)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+
+ mipi_dbi_command(ili->dbi, MIPI_DCS_SET_DISPLAY_OFF);
+ return 0;
+}
+
+static int ili9341_dpi_unprepare(struct drm_panel *panel)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+
+ return ili9341_dpi_power_off(ili);
+}
+
+static int ili9341_dpi_prepare(struct drm_panel *panel)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+ int ret;
+
+ ret = ili9341_dpi_power_on(ili);
+ if (ret < 0)
+ return ret;
+
+ ili9341_dpi_init(ili);
+
+ return ret;
+}
+
+static int ili9341_dpi_enable(struct drm_panel *panel)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+
+ mipi_dbi_command(ili->dbi, MIPI_DCS_SET_DISPLAY_ON);
+ return 0;
+}
+
+static int ili9341_dpi_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+ struct drm_device *drm = connector->dev;
+ struct drm_display_mode *mode;
+ struct drm_display_info *info;
+
+ info = &connector->display_info;
+ info->width_mm = ili->conf->mode.width_mm;
+ info->height_mm = ili->conf->mode.height_mm;
+
+ if (ili->conf->rgb_interface & ILI9341_RGB_DPL)
+ info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
+ else
+ info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
+
+ if (ili->conf->rgb_interface & ILI9341_RGB_EPL)
+ info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
+ else
+ info->bus_flags |= DRM_BUS_FLAG_DE_HIGH;
+
+ mode = drm_mode_duplicate(drm, &ili->conf->mode);
+ if (!mode) {
+ drm_err(drm, "bad mode or failed to add mode\n");
+ return -EINVAL;
+ }
+ drm_mode_set_name(mode);
+
+ /* Set up the polarity */
+ if (ili->conf->rgb_interface & ILI9341_RGB_HSPL)
+ mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ else
+ mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+ if (ili->conf->rgb_interface & ILI9341_RGB_VSPL)
+ mode->flags |= DRM_MODE_FLAG_PVSYNC;
+ else
+ mode->flags |= DRM_MODE_FLAG_NVSYNC;
+
+ drm_mode_probed_add(connector, mode);
+
+ return 1; /* Number of modes */
+}
+
+static const struct drm_panel_funcs ili9341_dpi_funcs = {
+ .disable = ili9341_dpi_disable,
+ .unprepare = ili9341_dpi_unprepare,
+ .prepare = ili9341_dpi_prepare,
+ .enable = ili9341_dpi_enable,
+ .get_modes = ili9341_dpi_get_modes,
+};
+
+static void ili9341_dbi_enable(struct drm_simple_display_pipe *pipe,
+ struct drm_crtc_state *crtc_state,
+ struct drm_plane_state *plane_state)
+{
+ struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ struct mipi_dbi *dbi = &dbidev->dbi;
+ u8 addr_mode;
+ int ret, idx;
+
+ if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ return;
+
+ ret = mipi_dbi_poweron_conditional_reset(dbidev);
+ if (ret < 0)
+ goto out_exit;
+ if (ret == 1)
+ goto out_enable;
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
+
+ mipi_dbi_command(dbi, ILI9341_POWERB, 0x00, 0xc1, 0x30);
+ mipi_dbi_command(dbi, ILI9341_POWER_SEQ, 0x64, 0x03, 0x12, 0x81);
+ mipi_dbi_command(dbi, ILI9341_DTCA, 0x85, 0x00, 0x78);
+ mipi_dbi_command(dbi, ILI9341_POWERA, 0x39, 0x2c, 0x00, 0x34, 0x02);
+ mipi_dbi_command(dbi, ILI9341_PRC, ILI9341_DBI_PRC_NORMAL);
+ mipi_dbi_command(dbi, ILI9341_DTCB, 0x00, 0x00);
+
+ /* Power Control */
+ mipi_dbi_command(dbi, ILI9341_POWER1, ILI9341_DBI_VCOMH_4P6V);
+ mipi_dbi_command(dbi, ILI9341_POWER2, ILI9341_DBI_PWR_2_DEFAULT);
+ /* VCOM */
+ mipi_dbi_command(dbi, ILI9341_VCOM1, ILI9341_DBI_VCOM_1_VMH_4P25V,
+ ILI9341_DBI_VCOM_1_VML_1P5V);
+ mipi_dbi_command(dbi, ILI9341_VCOM2, ILI9341_DBI_VCOM_2_DEC_58);
+
+ /* Memory Access Control */
+ mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT,
+ MIPI_DCS_PIXEL_FMT_16BIT);
+
+ /* Frame Rate */
+ mipi_dbi_command(dbi, ILI9341_FRC, ILI9341_DBI_FRC_DIVA & 0x03,
+ ILI9341_DBI_FRC_RTNA & 0x1f);
+
+ /* Gamma */
+ mipi_dbi_command(dbi, ILI9341_3GAMMA_EN, 0x00);
+ mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, ILI9341_GAMMA_CURVE_1);
+ mipi_dbi_command(dbi, ILI9341_PGAMMA,
+ 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1,
+ 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00);
+ mipi_dbi_command(dbi, ILI9341_NGAMMA,
+ 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1,
+ 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f);
+
+ /* DDRAM */
+ mipi_dbi_command(dbi, ILI9341_ETMOD, ILI9341_DBI_EMS_GAS |
+ ILI9341_DBI_EMS_DTS |
+ ILI9341_DBI_EMS_GON);
+
+ /* Display */
+ mipi_dbi_command(dbi, ILI9341_DFC, 0x08, 0x82, 0x27, 0x00);
+ mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+ msleep(100);
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+ msleep(100);
+
+out_enable:
+ switch (dbidev->rotation) {
+ default:
+ addr_mode = ILI9341_MADCTL_MX;
+ break;
+ case 90:
+ addr_mode = ILI9341_MADCTL_MV;
+ break;
+ case 180:
+ addr_mode = ILI9341_MADCTL_MY;
+ break;
+ case 270:
+ addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
+ ILI9341_MADCTL_MX;
+ break;
+ }
+
+ addr_mode |= ILI9341_MADCTL_BGR;
+ mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
+ mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+ drm_info(&dbidev->drm, "Initialized display serial interface\n");
+out_exit:
+ drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = {
+ .enable = ili9341_dbi_enable,
+ .disable = mipi_dbi_pipe_disable,
+ .update = mipi_dbi_pipe_update,
+ .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode ili9341_dbi_mode = {
+ DRM_SIMPLE_MODE(240, 320, 37, 49),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(ili9341_dbi_fops);
+
+static struct drm_driver ili9341_dbi_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ .fops = &ili9341_dbi_fops,
+ DRM_GEM_CMA_DRIVER_OPS_VMAP,
+ .debugfs_init = mipi_dbi_debugfs_init,
+ .name = "ili9341",
+ .desc = "Ilitek ILI9341",
+ .date = "20210716",
+ .major = 1,
+ .minor = 0,
+};
+
+static int ili9341_dbi_probe(struct spi_device *spi, struct gpio_desc *dc,
+ struct gpio_desc *reset)
+{
+ struct device *dev = &spi->dev;
+ struct mipi_dbi_dev *dbidev;
+ struct mipi_dbi *dbi;
+ struct drm_device *drm;
+ struct regulator *vcc;
+ u32 rotation = 0;
+ int ret;
+
+ vcc = devm_regulator_get_optional(dev, "vcc");
+ if (IS_ERR(vcc))
+ dev_err(dev, "get optional vcc failed\n");
+
+ dbidev = devm_drm_dev_alloc(dev, &ili9341_dbi_driver,
+ struct mipi_dbi_dev, drm);
+ if (IS_ERR(dbidev))
+ return PTR_ERR(dbidev);
+
+ dbi = &dbidev->dbi;
+ drm = &dbidev->drm;
+ dbi->reset = reset;
+ dbidev->regulator = vcc;
+
+ drm_mode_config_init(drm);
+
+ dbidev->backlight = devm_of_find_backlight(dev);
+ if (IS_ERR(dbidev->backlight))
+ return PTR_ERR(dbidev->backlight);
+
+ device_property_read_u32(dev, "rotation", &rotation);
+
+ ret = mipi_dbi_spi_init(spi, dbi, dc);
+ if (ret)
+ return ret;
+
+ ret = mipi_dbi_dev_init(dbidev, &ili9341_dbi_funcs,
+ &ili9341_dbi_mode, rotation);
+ if (ret)
+ return ret;
+
+ drm_mode_config_reset(drm);
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ return ret;
+
+ spi_set_drvdata(spi, drm);
+
+ drm_fbdev_generic_setup(drm, 0);
+
+ return 0;
+}
+
+static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc,
+ struct gpio_desc *reset)
+{
+ struct device *dev = &spi->dev;
+ struct ili9341 *ili;
+ int ret;
+
+ ili = devm_kzalloc(dev, sizeof(struct ili9341), GFP_KERNEL);
+ if (!ili)
+ return -ENOMEM;
+
+ ili->dbi = devm_kzalloc(dev, sizeof(struct mipi_dbi),
+ GFP_KERNEL);
+ if (!ili->dbi)
+ return -ENOMEM;
+
+ ili->supplies[0].supply = "vci";
+ ili->supplies[1].supply = "vddi";
+ ili->supplies[2].supply = "vddi-led";
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ili->supplies),
+ ili->supplies);
+ if (ret < 0) {
+ dev_err(dev, "failed to get regulators: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dbi_spi_init(spi, ili->dbi, dc);
+ if (ret)
+ return ret;
+
+ spi_set_drvdata(spi, ili);
+ ili->reset_gpio = reset;
+ /*
+ * Every new incarnation of this display must have a unique
+ * data entry for the system in this driver.
+ */
+ ili->conf = of_device_get_match_data(dev);
+ if (!ili->conf) {
+ dev_err(dev, "missing device configuration\n");
+ return -ENODEV;
+ }
+
+ ili->max_spi_speed = ili->conf->max_spi_speed;
+ drm_panel_init(&ili->panel, dev, &ili9341_dpi_funcs,
+ DRM_MODE_CONNECTOR_DPI);
+ drm_panel_add(&ili->panel);
+
+ return 0;
+}
+
+static int ili9341_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct gpio_desc *dc;
+ struct gpio_desc *reset;
+ const struct spi_device_id *id = spi_get_device_id(spi);
+
+ reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(reset))
+ dev_err(dev, "Failed to get gpio 'reset'\n");
+
+ dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
+ if (IS_ERR(dc))
+ dev_err(dev, "Failed to get gpio 'dc'\n");
+
+ if (!strcmp(id->name, "sf-tc240t-9370-t"))
+ return ili9341_dpi_probe(spi, dc, reset);
+ else if (!strcmp(id->name, "yx240qv29"))
+ return ili9341_dbi_probe(spi, dc, reset);
+
+ return -1;
+}
+
+static int ili9341_remove(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+ struct ili9341 *ili = spi_get_drvdata(spi);
+ struct drm_device *drm = spi_get_drvdata(spi);
+
+ if (!strcmp(id->name, "sf-tc240t-9370-t")) {
+ ili9341_dpi_power_off(ili);
+ drm_panel_remove(&ili->panel);
+ } else if (!strcmp(id->name, "yx240qv29")) {
+ drm_dev_unplug(drm);
+ drm_atomic_helper_shutdown(drm);
+ }
+ return 0;
+}
+
+static void ili9341_shutdown(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+
+ if (!strcmp(id->name, "yx240qv29"))
+ drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static const struct of_device_id ili9341_of_match[] = {
+ {
+ .compatible = "st,sf-tc240t-9370-t",
+ .data = &ili9341_stm32f429_disco_data,
+ },
+ {
+ /* porting from tiny/ili9341.c
+ * for original mipi dbi compitable
+ */
+ .compatible = "adafruit,yx240qv29",
+ .data = NULL,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ili9341_of_match);
+
+static const struct spi_device_id ili9341_id[] = {
+ { "yx240qv29", 0 },
+ { "sf-tc240t-9370-t", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ili9341_id);
+
+static struct spi_driver ili9341_driver = {
+ .probe = ili9341_probe,
+ .remove = ili9341_remove,
+ .shutdown = ili9341_shutdown,
+ .id_table = ili9341_id,
+ .driver = {
+ .name = "panel-ilitek-ili9341",
+ .of_match_table = ili9341_of_match,
+ },
+};
+module_spi_driver(ili9341_driver);
+
+MODULE_AUTHOR("Dillon Min <dillon.minfei@gmail.com>");
+MODULE_DESCRIPTION("ILI9341 LCD panel driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-innolux-ej030na.c b/drivers/gpu/drm/panel/panel-innolux-ej030na.c
new file mode 100644
index 000000000000..34b98f70bd22
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-innolux-ej030na.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Innolux/Chimei EJ030NA TFT LCD panel driver
+ *
+ * Copyright (C) 2020, Paul Cercueil <paul@crapouillou.net>
+ * Copyright (C) 2020, Christophe Branchereau <cbranchereau@gmail.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/media-bus-format.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct ej030na_info {
+ const struct drm_display_mode *display_modes;
+ unsigned int num_modes;
+ u16 width_mm, height_mm;
+ u32 bus_format, bus_flags;
+};
+
+struct ej030na {
+ struct drm_panel panel;
+ struct spi_device *spi;
+ struct regmap *map;
+
+ const struct ej030na_info *panel_info;
+
+ struct regulator *supply;
+ struct gpio_desc *reset_gpio;
+};
+
+static inline struct ej030na *to_ej030na(struct drm_panel *panel)
+{
+ return container_of(panel, struct ej030na, panel);
+}
+
+static const struct reg_sequence ej030na_init_sequence[] = {
+ { 0x05, 0x1e },
+ { 0x05, 0x5c },
+ { 0x02, 0x14 },
+ { 0x03, 0x40 },
+ { 0x04, 0x07 },
+ { 0x06, 0x12 },
+ { 0x07, 0xd2 },
+ { 0x0c, 0x06 },
+ { 0x0d, 0x40 },
+ { 0x0e, 0x40 },
+ { 0x0f, 0x40 },
+ { 0x10, 0x40 },
+ { 0x11, 0x40 },
+ { 0x2f, 0x40 },
+ { 0x5a, 0x02 },
+
+ { 0x30, 0x07 },
+ { 0x31, 0x57 },
+ { 0x32, 0x53 },
+ { 0x33, 0x77 },
+ { 0x34, 0xb8 },
+ { 0x35, 0xbd },
+ { 0x36, 0xb8 },
+ { 0x37, 0xe7 },
+ { 0x38, 0x04 },
+ { 0x39, 0xff },
+
+ { 0x40, 0x0b },
+ { 0x41, 0xb8 },
+ { 0x42, 0xab },
+ { 0x43, 0xb9 },
+ { 0x44, 0x6a },
+ { 0x45, 0x56 },
+ { 0x46, 0x61 },
+ { 0x47, 0x08 },
+ { 0x48, 0x0f },
+ { 0x49, 0x0f },
+
+ { 0x2b, 0x01 },
+};
+
+static int ej030na_prepare(struct drm_panel *panel)
+{
+ struct ej030na *priv = to_ej030na(panel);
+ struct device *dev = &priv->spi->dev;
+ int err;
+
+ err = regulator_enable(priv->supply);
+ if (err) {
+ dev_err(dev, "Failed to enable power supply: %d\n", err);
+ return err;
+ }
+
+ /* Reset the chip */
+ gpiod_set_value_cansleep(priv->reset_gpio, 1);
+ usleep_range(50, 150);
+ gpiod_set_value_cansleep(priv->reset_gpio, 0);
+ usleep_range(50, 150);
+
+ err = regmap_multi_reg_write(priv->map, ej030na_init_sequence,
+ ARRAY_SIZE(ej030na_init_sequence));
+ if (err) {
+ dev_err(dev, "Failed to init registers: %d\n", err);
+ goto err_disable_regulator;
+ }
+
+ msleep(120);
+
+ return 0;
+
+err_disable_regulator:
+ regulator_disable(priv->supply);
+ return err;
+}
+
+static int ej030na_unprepare(struct drm_panel *panel)
+{
+ struct ej030na *priv = to_ej030na(panel);
+
+ gpiod_set_value_cansleep(priv->reset_gpio, 1);
+ regulator_disable(priv->supply);
+
+ return 0;
+}
+
+static int ej030na_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct ej030na *priv = to_ej030na(panel);
+ const struct ej030na_info *panel_info = priv->panel_info;
+ struct drm_display_mode *mode;
+ unsigned int i;
+
+ for (i = 0; i < panel_info->num_modes; i++) {
+ mode = drm_mode_duplicate(connector->dev,
+ &panel_info->display_modes[i]);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER;
+ if (panel_info->num_modes == 1)
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_probed_add(connector, mode);
+ }
+
+ connector->display_info.bpc = 8;
+ connector->display_info.width_mm = panel_info->width_mm;
+ connector->display_info.height_mm = panel_info->height_mm;
+
+ drm_display_info_set_bus_formats(&connector->display_info,
+ &panel_info->bus_format, 1);
+ connector->display_info.bus_flags = panel_info->bus_flags;
+
+ return panel_info->num_modes;
+}
+
+static const struct drm_panel_funcs ej030na_funcs = {
+ .prepare = ej030na_prepare,
+ .unprepare = ej030na_unprepare,
+ .get_modes = ej030na_get_modes,
+};
+
+static const struct regmap_config ej030na_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x5a,
+};
+
+static int ej030na_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct ej030na *priv;
+ int err;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->spi = spi;
+ spi_set_drvdata(spi, priv);
+
+ priv->map = devm_regmap_init_spi(spi, &ej030na_regmap_config);
+ if (IS_ERR(priv->map)) {
+ dev_err(dev, "Unable to init regmap\n");
+ return PTR_ERR(priv->map);
+ }
+
+ priv->panel_info = of_device_get_match_data(dev);
+ if (!priv->panel_info)
+ return -EINVAL;
+
+ priv->supply = devm_regulator_get(dev, "power");
+ if (IS_ERR(priv->supply)) {
+ dev_err(dev, "Failed to get power supply\n");
+ return PTR_ERR(priv->supply);
+ }
+
+ priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset_gpio)) {
+ dev_err(dev, "Failed to get reset GPIO\n");
+ return PTR_ERR(priv->reset_gpio);
+ }
+
+ drm_panel_init(&priv->panel, dev, &ej030na_funcs,
+ DRM_MODE_CONNECTOR_DPI);
+
+ err = drm_panel_of_backlight(&priv->panel);
+ if (err)
+ return err;
+
+ drm_panel_add(&priv->panel);
+
+ return 0;
+}
+
+static int ej030na_remove(struct spi_device *spi)
+{
+ struct ej030na *priv = spi_get_drvdata(spi);
+
+ drm_panel_remove(&priv->panel);
+ drm_panel_disable(&priv->panel);
+ drm_panel_unprepare(&priv->panel);
+
+ return 0;
+}
+
+static const struct drm_display_mode ej030na_modes[] = {
+ { /* 60 Hz */
+ .clock = 14400,
+ .hdisplay = 320,
+ .hsync_start = 320 + 10,
+ .hsync_end = 320 + 10 + 37,
+ .htotal = 320 + 10 + 37 + 33,
+ .vdisplay = 480,
+ .vsync_start = 480 + 102,
+ .vsync_end = 480 + 102 + 9 + 9,
+ .vtotal = 480 + 102 + 9 + 9,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ },
+ { /* 50 Hz */
+ .clock = 12000,
+ .hdisplay = 320,
+ .hsync_start = 320 + 10,
+ .hsync_end = 320 + 10 + 37,
+ .htotal = 320 + 10 + 37 + 33,
+ .vdisplay = 480,
+ .vsync_start = 480 + 102,
+ .vsync_end = 480 + 102 + 9,
+ .vtotal = 480 + 102 + 9 + 9,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ },
+};
+
+static const struct ej030na_info ej030na_info = {
+ .display_modes = ej030na_modes,
+ .num_modes = ARRAY_SIZE(ej030na_modes),
+ .width_mm = 70,
+ .height_mm = 51,
+ .bus_format = MEDIA_BUS_FMT_RGB888_3X8_DELTA,
+ .bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE | DRM_BUS_FLAG_DE_LOW,
+};
+
+static const struct of_device_id ej030na_of_match[] = {
+ { .compatible = "innolux,ej030na", .data = &ej030na_info },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ej030na_of_match);
+
+static struct spi_driver ej030na_driver = {
+ .driver = {
+ .name = "panel-innolux-ej030na",
+ .of_match_table = ej030na_of_match,
+ },
+ .probe = ej030na_probe,
+ .remove = ej030na_remove,
+};
+module_spi_driver(ej030na_driver);
+
+MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
+MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-khadas-ts050.c b/drivers/gpu/drm/panel/panel-khadas-ts050.c
index 8f6ac1a40c31..a3ec4cbdbf7a 100644
--- a/drivers/gpu/drm/panel/panel-khadas-ts050.c
+++ b/drivers/gpu/drm/panel/panel-khadas-ts050.c
@@ -809,7 +809,7 @@ static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
- MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
khadas_ts050 = devm_kzalloc(&dsi->dev, sizeof(*khadas_ts050),
GFP_KERNEL);
diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
index ed0d5f959037..a5a414920430 100644
--- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
+++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
@@ -593,7 +593,7 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
- MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
drm_panel_init(&ctx->panel, &dsi->dev, &ltk050h3146w_funcs,
DRM_MODE_CONNECTOR_DSI);
diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c
index 3c00e4f8f803..21e48923836d 100644
--- a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c
+++ b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c
@@ -442,7 +442,7 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
- MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
drm_panel_init(&ctx->panel, &dsi->dev, &ltk500hd1829_funcs,
DRM_MODE_CONNECTOR_DSI);
diff --git a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
index 45b975dee587..198493a6eb6a 100644
--- a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
+++ b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
@@ -184,7 +184,7 @@ static int osd101t2587_panel_probe(struct mipi_dsi_device *dsi)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_EOT_PACKET;
+ MIPI_DSI_MODE_NO_EOT_PACKET;
osd101t2587 = devm_kzalloc(&dsi->dev, sizeof(*osd101t2587), GFP_KERNEL);
if (!osd101t2587)
diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
new file mode 100644
index 000000000000..221db6512859
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Panel driver for the Samsung ATNA33XC20 panel. This panel can't be handled
+ * by the DRM_PANEL_SIMPLE driver because its power sequencing is non-standard.
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_dp_aux_bus.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_panel.h>
+
+struct atana33xc20_panel {
+ struct drm_panel base;
+ bool prepared;
+ bool enabled;
+ bool el3_was_on;
+
+ bool no_hpd;
+ struct gpio_desc *hpd_gpio;
+
+ struct regulator *supply;
+ struct gpio_desc *el_on3_gpio;
+
+ struct edid *edid;
+
+ ktime_t powered_off_time;
+ ktime_t powered_on_time;
+ ktime_t el_on3_off_time;
+};
+
+static inline struct atana33xc20_panel *to_atana33xc20(struct drm_panel *panel)
+{
+ return container_of(panel, struct atana33xc20_panel, base);
+}
+
+static void atana33xc20_wait(ktime_t start_ktime, unsigned int min_ms)
+{
+ ktime_t now_ktime, min_ktime;
+
+ min_ktime = ktime_add(start_ktime, ms_to_ktime(min_ms));
+ now_ktime = ktime_get();
+
+ if (ktime_before(now_ktime, min_ktime))
+ msleep(ktime_to_ms(ktime_sub(min_ktime, now_ktime)) + 1);
+}
+
+static int atana33xc20_suspend(struct device *dev)
+{
+ struct atana33xc20_panel *p = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * Note 3 (Example of power off sequence in detail) in spec
+ * specifies to wait 150 ms after deasserting EL3_ON before
+ * powering off.
+ */
+ if (p->el3_was_on)
+ atana33xc20_wait(p->el_on3_off_time, 150);
+
+ ret = regulator_disable(p->supply);
+ if (ret)
+ return ret;
+ p->powered_off_time = ktime_get();
+ p->el3_was_on = false;
+
+ return 0;
+}
+
+static int atana33xc20_resume(struct device *dev)
+{
+ struct atana33xc20_panel *p = dev_get_drvdata(dev);
+ bool hpd_asserted = false;
+ int ret;
+
+ /* T12 (Power off time) is min 500 ms */
+ atana33xc20_wait(p->powered_off_time, 500);
+
+ ret = regulator_enable(p->supply);
+ if (ret)
+ return ret;
+ p->powered_on_time = ktime_get();
+
+ /*
+ * Handle HPD. Note: if HPD is hooked up to a dedicated pin on the
+ * eDP controller then "no_hpd" will be false _and_ "hpd_gpio" will be
+ * NULL. It's up to the controller driver to wait for HPD after
+ * preparing the panel in that case.
+ */
+ if (p->no_hpd) {
+ /* T3 VCC to HPD high is max 200 ms */
+ msleep(200);
+ } else if (p->hpd_gpio) {
+ ret = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio,
+ hpd_asserted, hpd_asserted,
+ 1000, 200000);
+ if (!hpd_asserted)
+ dev_warn(dev, "Timeout waiting for HPD\n");
+ }
+
+ return 0;
+}
+
+static int atana33xc20_disable(struct drm_panel *panel)
+{
+ struct atana33xc20_panel *p = to_atana33xc20(panel);
+
+ /* Disabling when already disabled is a no-op */
+ if (!p->enabled)
+ return 0;
+
+ gpiod_set_value_cansleep(p->el_on3_gpio, 0);
+ p->el_on3_off_time = ktime_get();
+ p->enabled = false;
+
+ /*
+ * Keep track of the fact that EL_ON3 was on but we haven't power
+ * cycled yet. This lets us know that "el_on3_off_time" is recent (we
+ * don't need to worry about ktime wraparounds) and also makes it
+ * obvious if we try to enable again without a power cycle (see the
+ * warning in atana33xc20_enable()).
+ */
+ p->el3_was_on = true;
+
+ /*
+ * Sleeping 20 ms here (after setting the GPIO) avoids a glitch when
+ * powering off.
+ */
+ msleep(20);
+
+ return 0;
+}
+
+static int atana33xc20_enable(struct drm_panel *panel)
+{
+ struct atana33xc20_panel *p = to_atana33xc20(panel);
+
+ /* Enabling when already enabled is a no-op */
+ if (p->enabled)
+ return 0;
+
+ /*
+ * Once EL_ON3 drops we absolutely need a power cycle before the next
+ * enable or the backlight will never come on again. The code ensures
+ * this because disable() is _always_ followed by unprepare() and
+ * unprepare() forces a suspend with pm_runtime_put_sync_suspend(),
+ * but let's track just to make sure since the requirement is so
+ * non-obvious.
+ */
+ if (WARN_ON(p->el3_was_on))
+ return -EIO;
+
+ /*
+ * Note 2 (Example of power on sequence in detail) in spec specifies
+ * to wait 400 ms after powering on before asserting EL3_on.
+ */
+ atana33xc20_wait(p->powered_on_time, 400);
+
+ gpiod_set_value_cansleep(p->el_on3_gpio, 1);
+ p->enabled = true;
+
+ return 0;
+}
+
+static int atana33xc20_unprepare(struct drm_panel *panel)
+{
+ struct atana33xc20_panel *p = to_atana33xc20(panel);
+ int ret;
+
+ /* Unpreparing when already unprepared is a no-op */
+ if (!p->prepared)
+ return 0;
+
+ /*
+ * Purposely do a put_sync, don't use autosuspend. The panel's tcon
+ * seems to sometimes crash when you stop giving it data and this is
+ * the best way to ensure it will come back.
+ *
+ * NOTE: we still want autosuspend for cases where we only turn on
+ * to get the EDID or otherwise send DP AUX commands to the panel.
+ */
+ ret = pm_runtime_put_sync_suspend(panel->dev);
+ if (ret < 0)
+ return ret;
+ p->prepared = false;
+
+ return 0;
+}
+
+static int atana33xc20_prepare(struct drm_panel *panel)
+{
+ struct atana33xc20_panel *p = to_atana33xc20(panel);
+ int ret;
+
+ /* Preparing when already prepared is a no-op */
+ if (p->prepared)
+ return 0;
+
+ ret = pm_runtime_get_sync(panel->dev);
+ if (ret < 0) {
+ pm_runtime_put_autosuspend(panel->dev);
+ return ret;
+ }
+ p->prepared = true;
+
+ return 0;
+}
+
+static int atana33xc20_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct atana33xc20_panel *p = to_atana33xc20(panel);
+ struct dp_aux_ep_device *aux_ep = to_dp_aux_ep_dev(panel->dev);
+ int num = 0;
+
+ pm_runtime_get_sync(panel->dev);
+
+ if (!p->edid)
+ p->edid = drm_get_edid(connector, &aux_ep->aux->ddc);
+ num = drm_add_edid_modes(connector, p->edid);
+
+ pm_runtime_mark_last_busy(panel->dev);
+ pm_runtime_put_autosuspend(panel->dev);
+
+ return num;
+}
+
+static const struct drm_panel_funcs atana33xc20_funcs = {
+ .disable = atana33xc20_disable,
+ .enable = atana33xc20_enable,
+ .unprepare = atana33xc20_unprepare,
+ .prepare = atana33xc20_prepare,
+ .get_modes = atana33xc20_get_modes,
+};
+
+static void atana33xc20_runtime_disable(void *data)
+{
+ pm_runtime_disable(data);
+}
+
+static void atana33xc20_dont_use_autosuspend(void *data)
+{
+ pm_runtime_dont_use_autosuspend(data);
+}
+
+static int atana33xc20_probe(struct dp_aux_ep_device *aux_ep)
+{
+ struct atana33xc20_panel *panel;
+ struct device *dev = &aux_ep->dev;
+ int ret;
+
+ panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
+ if (!panel)
+ return -ENOMEM;
+ dev_set_drvdata(dev, panel);
+
+ panel->supply = devm_regulator_get(dev, "power");
+ if (IS_ERR(panel->supply))
+ return dev_err_probe(dev, PTR_ERR(panel->supply),
+ "Failed to get power supply\n");
+
+ panel->el_on3_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(panel->el_on3_gpio))
+ return dev_err_probe(dev, PTR_ERR(panel->el_on3_gpio),
+ "Failed to get enable GPIO\n");
+
+ panel->no_hpd = of_property_read_bool(dev->of_node, "no-hpd");
+ if (!panel->no_hpd) {
+ panel->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);
+ if (IS_ERR(panel->hpd_gpio))
+ return dev_err_probe(dev, PTR_ERR(panel->hpd_gpio),
+ "Failed to get HPD GPIO\n");
+ }
+
+ pm_runtime_enable(dev);
+ ret = devm_add_action_or_reset(dev, atana33xc20_runtime_disable, dev);
+ if (ret)
+ return ret;
+ pm_runtime_set_autosuspend_delay(dev, 1000);
+ pm_runtime_use_autosuspend(dev);
+ ret = devm_add_action_or_reset(dev, atana33xc20_dont_use_autosuspend, dev);
+ if (ret)
+ return ret;
+
+ drm_panel_init(&panel->base, dev, &atana33xc20_funcs, DRM_MODE_CONNECTOR_eDP);
+
+ pm_runtime_get_sync(dev);
+ ret = drm_panel_dp_aux_backlight(&panel->base, aux_ep->aux);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to register dp aux backlight\n");
+
+ drm_panel_add(&panel->base);
+
+ return 0;
+}
+
+static void atana33xc20_remove(struct dp_aux_ep_device *aux_ep)
+{
+ struct device *dev = &aux_ep->dev;
+ struct atana33xc20_panel *panel = dev_get_drvdata(dev);
+
+ drm_panel_remove(&panel->base);
+ drm_panel_disable(&panel->base);
+ drm_panel_unprepare(&panel->base);
+
+ kfree(panel->edid);
+}
+
+static void atana33xc20_shutdown(struct dp_aux_ep_device *aux_ep)
+{
+ struct device *dev = &aux_ep->dev;
+ struct atana33xc20_panel *panel = dev_get_drvdata(dev);
+
+ drm_panel_disable(&panel->base);
+ drm_panel_unprepare(&panel->base);
+}
+
+static const struct of_device_id atana33xc20_dt_match[] = {
+ { .compatible = "samsung,atna33xc20", },
+ { /* sentinal */ }
+};
+MODULE_DEVICE_TABLE(of, atana33xc20_dt_match);
+
+static const struct dev_pm_ops atana33xc20_pm_ops = {
+ SET_RUNTIME_PM_OPS(atana33xc20_suspend, atana33xc20_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+};
+
+static struct dp_aux_ep_driver atana33xc20_driver = {
+ .driver = {
+ .name = "samsung_atana33xc20",
+ .of_match_table = atana33xc20_dt_match,
+ .pm = &atana33xc20_pm_ops,
+ },
+ .probe = atana33xc20_probe,
+ .remove = atana33xc20_remove,
+ .shutdown = atana33xc20_shutdown,
+};
+
+static int __init atana33xc20_init(void)
+{
+ return dp_aux_dp_driver_register(&atana33xc20_driver);
+}
+module_init(atana33xc20_init);
+
+static void __exit atana33xc20_exit(void)
+{
+ dp_aux_dp_driver_unregister(&atana33xc20_driver);
+}
+module_exit(atana33xc20_exit);
+
+MODULE_DESCRIPTION("Samsung ATANA33XC20 Panel Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-samsung-db7430.c b/drivers/gpu/drm/panel/panel-samsung-db7430.c
new file mode 100644
index 000000000000..ead479719f00
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-db7430.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Panel driver for the Samsung LMS397KF04 480x800 DPI RGB panel.
+ * According to the data sheet the display controller is called DB7430.
+ * Found in the Samsung Galaxy Beam GT-I8350 mobile phone.
+ * Linus Walleij <linus.walleij@linaro.org>
+ */
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/media-bus-format.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <video/mipi_display.h>
+
+#define DB7430_ACCESS_PROT_OFF 0xb0
+#define DB7430_UNKNOWN_B4 0xb4
+#define DB7430_USER_SELECT 0xb5
+#define DB7430_UNKNOWN_B7 0xb7
+#define DB7430_UNKNOWN_B8 0xb8
+#define DB7430_PANEL_DRIVING 0xc0
+#define DB7430_SOURCE_CONTROL 0xc1
+#define DB7430_GATE_INTERFACE 0xc4
+#define DB7430_DISPLAY_H_TIMING 0xc5
+#define DB7430_RGB_SYNC_OPTION 0xc6
+#define DB7430_GAMMA_SET_RED 0xc8
+#define DB7430_GAMMA_SET_GREEN 0xc9
+#define DB7430_GAMMA_SET_BLUE 0xca
+#define DB7430_BIAS_CURRENT_CTRL 0xd1
+#define DB7430_DDV_CTRL 0xd2
+#define DB7430_GAMMA_CTRL_REF 0xd3
+#define DB7430_UNKNOWN_D4 0xd4
+#define DB7430_DCDC_CTRL 0xd5
+#define DB7430_VCL_CTRL 0xd6
+#define DB7430_UNKNOWN_F8 0xf8
+#define DB7430_UNKNOWN_FC 0xfc
+
+#define DATA_MASK 0x100
+
+/**
+ * struct db7430 - state container for a panel controlled by the DB7430
+ * controller
+ */
+struct db7430 {
+ /** @dev: the container device */
+ struct device *dev;
+ /** @dbi: the DBI bus abstraction handle */
+ struct mipi_dbi dbi;
+ /** @panel: the DRM panel instance for this device */
+ struct drm_panel panel;
+ /** @width: the width of this panel in mm */
+ u32 width;
+ /** @height: the height of this panel in mm */
+ u32 height;
+ /** @reset: reset GPIO line */
+ struct gpio_desc *reset;
+ /** @regulators: VCCIO and VIO supply regulators */
+ struct regulator_bulk_data regulators[2];
+};
+
+static const struct drm_display_mode db7430_480_800_mode = {
+ /*
+ * 31 ns period min (htotal*vtotal*vrefresh)/1000
+ * gives a Vrefresh of ~71 Hz.
+ */
+ .clock = 32258,
+ .hdisplay = 480,
+ .hsync_start = 480 + 10,
+ .hsync_end = 480 + 10 + 4,
+ .htotal = 480 + 10 + 4 + 40,
+ .vdisplay = 800,
+ .vsync_start = 800 + 6,
+ .vsync_end = 800 + 6 + 1,
+ .vtotal = 800 + 6 + 1 + 7,
+ .width_mm = 53,
+ .height_mm = 87,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static inline struct db7430 *to_db7430(struct drm_panel *panel)
+{
+ return container_of(panel, struct db7430, panel);
+}
+
+static int db7430_power_on(struct db7430 *db)
+{
+ struct mipi_dbi *dbi = &db->dbi;
+ int ret;
+
+ /* Power up */
+ ret = regulator_bulk_enable(ARRAY_SIZE(db->regulators),
+ db->regulators);
+ if (ret) {
+ dev_err(db->dev, "failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+ msleep(50);
+
+ /* Assert reset >=1 ms */
+ gpiod_set_value_cansleep(db->reset, 1);
+ usleep_range(1000, 5000);
+ /* De-assert reset */
+ gpiod_set_value_cansleep(db->reset, 0);
+ /* Wait >= 10 ms */
+ msleep(10);
+ dev_dbg(db->dev, "de-asserted RESET\n");
+
+ /*
+ * This is set to 0x0a (RGB/BGR order + horizontal flip) in order
+ * to make the display behave normally. If this is not set the displays
+ * normal output behaviour is horizontally flipped and BGR ordered. Do
+ * it twice because the first message doesn't always "take".
+ */
+ mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, 0x0a);
+ mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, 0x0a);
+ mipi_dbi_command(dbi, DB7430_ACCESS_PROT_OFF, 0x00);
+ mipi_dbi_command(dbi, DB7430_PANEL_DRIVING, 0x28, 0x08);
+ mipi_dbi_command(dbi, DB7430_SOURCE_CONTROL,
+ 0x01, 0x30, 0x15, 0x05, 0x22);
+ mipi_dbi_command(dbi, DB7430_GATE_INTERFACE,
+ 0x10, 0x01, 0x00);
+ mipi_dbi_command(dbi, DB7430_DISPLAY_H_TIMING,
+ 0x06, 0x55, 0x03, 0x07, 0x0b,
+ 0x33, 0x00, 0x01, 0x03);
+ /*
+ * 0x00 in datasheet 0x01 in vendor code 0x00, it seems 0x01 means
+ * DE active high and 0x00 means DE active low.
+ */
+ mipi_dbi_command(dbi, DB7430_RGB_SYNC_OPTION, 0x01);
+ mipi_dbi_command(dbi, DB7430_GAMMA_SET_RED,
+ /* R positive gamma */ 0x00,
+ 0x0A, 0x31, 0x3B, 0x4E, 0x58, 0x59, 0x5B, 0x58, 0x5E, 0x62,
+ 0x60, 0x61, 0x5E, 0x62, 0x55, 0x55, 0x7F, 0x08,
+ /* R negative gamma */ 0x00,
+ 0x0A, 0x31, 0x3B, 0x4E, 0x58, 0x59, 0x5B, 0x58, 0x5E, 0x62,
+ 0x60, 0x61, 0x5E, 0x62, 0x55, 0x55, 0x7F, 0x08);
+ mipi_dbi_command(dbi, DB7430_GAMMA_SET_GREEN,
+ /* G positive gamma */ 0x00,
+ 0x25, 0x15, 0x28, 0x3D, 0x4A, 0x48, 0x4C, 0x4A, 0x52, 0x59,
+ 0x59, 0x5B, 0x56, 0x60, 0x5D, 0x55, 0x7F, 0x0A,
+ /* G negative gamma */ 0x00,
+ 0x25, 0x15, 0x28, 0x3D, 0x4A, 0x48, 0x4C, 0x4A, 0x52, 0x59,
+ 0x59, 0x5B, 0x56, 0x60, 0x5D, 0x55, 0x7F, 0x0A);
+ mipi_dbi_command(dbi, DB7430_GAMMA_SET_BLUE,
+ /* B positive gamma */ 0x00,
+ 0x48, 0x10, 0x1F, 0x2F, 0x35, 0x38, 0x3D, 0x3C, 0x45, 0x4D,
+ 0x4E, 0x52, 0x51, 0x60, 0x7F, 0x7E, 0x7F, 0x0C,
+ /* B negative gamma */ 0x00,
+ 0x48, 0x10, 0x1F, 0x2F, 0x35, 0x38, 0x3D, 0x3C, 0x45, 0x4D,
+ 0x4E, 0x52, 0x51, 0x60, 0x7F, 0x7E, 0x7F, 0x0C);
+ mipi_dbi_command(dbi, DB7430_BIAS_CURRENT_CTRL, 0x33, 0x13);
+ mipi_dbi_command(dbi, DB7430_DDV_CTRL, 0x11, 0x00, 0x00);
+ mipi_dbi_command(dbi, DB7430_GAMMA_CTRL_REF, 0x50, 0x50);
+ mipi_dbi_command(dbi, DB7430_DCDC_CTRL, 0x2f, 0x11, 0x1e, 0x46);
+ mipi_dbi_command(dbi, DB7430_VCL_CTRL, 0x11, 0x0a);
+
+ return 0;
+}
+
+static int db7430_power_off(struct db7430 *db)
+{
+ /* Go into RESET and disable regulators */
+ gpiod_set_value_cansleep(db->reset, 1);
+ return regulator_bulk_disable(ARRAY_SIZE(db->regulators),
+ db->regulators);
+}
+
+static int db7430_unprepare(struct drm_panel *panel)
+{
+ return db7430_power_off(to_db7430(panel));
+}
+
+static int db7430_disable(struct drm_panel *panel)
+{
+ struct db7430 *db = to_db7430(panel);
+ struct mipi_dbi *dbi = &db->dbi;
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
+ msleep(25);
+ mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE);
+ msleep(120);
+
+ return 0;
+}
+
+static int db7430_prepare(struct drm_panel *panel)
+{
+ return db7430_power_on(to_db7430(panel));
+}
+
+static int db7430_enable(struct drm_panel *panel)
+{
+ struct db7430 *db = to_db7430(panel);
+ struct mipi_dbi *dbi = &db->dbi;
+
+ /* Exit sleep mode */
+ mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+ msleep(20);
+
+ /* NVM (non-volatile memory) load sequence */
+ mipi_dbi_command(dbi, DB7430_UNKNOWN_D4, 0x52, 0x5e);
+ mipi_dbi_command(dbi, DB7430_UNKNOWN_F8, 0x01, 0xf5, 0xf2, 0x71, 0x44);
+ mipi_dbi_command(dbi, DB7430_UNKNOWN_FC, 0x00, 0x08);
+ msleep(150);
+
+ /* CABC turn on sequence (BC = backlight control) */
+ mipi_dbi_command(dbi, DB7430_UNKNOWN_B4, 0x0f, 0x00, 0x50);
+ mipi_dbi_command(dbi, DB7430_USER_SELECT, 0x80);
+ mipi_dbi_command(dbi, DB7430_UNKNOWN_B7, 0x24);
+ mipi_dbi_command(dbi, DB7430_UNKNOWN_B8, 0x01);
+
+ /* Turn on display */
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+
+ return 0;
+}
+
+/**
+ * db7430_get_modes() - return the mode
+ * @panel: the panel to get the mode for
+ * @connector: reference to the central DRM connector control structure
+ */
+static int db7430_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct db7430 *db = to_db7430(panel);
+ struct drm_display_mode *mode;
+ static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+
+ mode = drm_mode_duplicate(connector->dev, &db7430_480_800_mode);
+ if (!mode) {
+ dev_err(db->dev, "failed to add mode\n");
+ return -ENOMEM;
+ }
+
+ connector->display_info.bpc = 8;
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ connector->display_info.bus_flags =
+ DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
+ drm_display_info_set_bus_formats(&connector->display_info,
+ &bus_format, 1);
+
+ drm_mode_set_name(mode);
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs db7430_drm_funcs = {
+ .disable = db7430_disable,
+ .unprepare = db7430_unprepare,
+ .prepare = db7430_prepare,
+ .enable = db7430_enable,
+ .get_modes = db7430_get_modes,
+};
+
+static int db7430_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct db7430 *db;
+ int ret;
+
+ db = devm_kzalloc(dev, sizeof(*db), GFP_KERNEL);
+ if (!db)
+ return -ENOMEM;
+ db->dev = dev;
+
+ /*
+ * VCI is the analog voltage supply
+ * VCCIO is the digital I/O voltage supply
+ */
+ db->regulators[0].supply = "vci";
+ db->regulators[1].supply = "vccio";
+ ret = devm_regulator_bulk_get(dev,
+ ARRAY_SIZE(db->regulators),
+ db->regulators);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get regulators\n");
+
+ db->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(db->reset)) {
+ ret = PTR_ERR(db->reset);
+ return dev_err_probe(dev, ret, "no RESET GPIO\n");
+ }
+
+ ret = mipi_dbi_spi_init(spi, &db->dbi, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
+
+ drm_panel_init(&db->panel, dev, &db7430_drm_funcs,
+ DRM_MODE_CONNECTOR_DPI);
+
+ /* FIXME: if no external backlight, use internal backlight */
+ ret = drm_panel_of_backlight(&db->panel);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add backlight\n");
+
+ spi_set_drvdata(spi, db);
+
+ drm_panel_add(&db->panel);
+ dev_dbg(dev, "added panel\n");
+
+ return 0;
+}
+
+static int db7430_remove(struct spi_device *spi)
+{
+ struct db7430 *db = spi_get_drvdata(spi);
+
+ drm_panel_remove(&db->panel);
+ return 0;
+}
+
+/*
+ * The DB7430 display controller may be used in several display products,
+ * so list the different variants here and add per-variant data if needed.
+ */
+static const struct of_device_id db7430_match[] = {
+ { .compatible = "samsung,lms397kf04", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, db7430_match);
+
+static struct spi_driver db7430_driver = {
+ .probe = db7430_probe,
+ .remove = db7430_remove,
+ .driver = {
+ .name = "db7430-panel",
+ .of_match_table = db7430_match,
+ },
+};
+module_spi_driver(db7430_driver);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("Samsung DB7430 panel driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c
index b962c817fb30..ccc8ed6fe3ae 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c
@@ -446,7 +446,7 @@ static int s6e63j0x03_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 1;
dsi->format = MIPI_DSI_FMT_RGB888;
- dsi->mode_flags = MIPI_DSI_MODE_EOT_PACKET;
+ dsi->mode_flags = MIPI_DSI_MODE_NO_EOT_PACKET;
ctx->supplies[0].supply = "vdd3";
ctx->supplies[1].supply = "vci";
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c
index 07a48f621289..e0b1a7e354f3 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c
@@ -16,7 +16,8 @@
#define MCS_GLOBAL_PARAM 0xb0
#define S6E63M0_DSI_MAX_CHUNK 15 /* CMD + 15 bytes max */
-static int s6e63m0_dsi_dcs_read(struct device *dev, const u8 cmd, u8 *data)
+static int s6e63m0_dsi_dcs_read(struct device *dev, void *trsp,
+ const u8 cmd, u8 *data)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
int ret;
@@ -32,7 +33,8 @@ static int s6e63m0_dsi_dcs_read(struct device *dev, const u8 cmd, u8 *data)
return 0;
}
-static int s6e63m0_dsi_dcs_write(struct device *dev, const u8 *data, size_t len)
+static int s6e63m0_dsi_dcs_write(struct device *dev, void *trsp,
+ const u8 *data, size_t len)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
const u8 *seqp = data;
@@ -99,8 +101,8 @@ static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_BURST;
- ret = s6e63m0_probe(dev, s6e63m0_dsi_dcs_read, s6e63m0_dsi_dcs_write,
- true);
+ ret = s6e63m0_probe(dev, NULL, s6e63m0_dsi_dcs_read,
+ s6e63m0_dsi_dcs_write, true);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
index 326deb3177b6..3669cc3719ce 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
@@ -5,62 +5,38 @@
#include <linux/spi/spi.h>
#include <linux/delay.h>
+#include <drm/drm_mipi_dbi.h>
#include <drm/drm_print.h>
#include "panel-samsung-s6e63m0.h"
-#define DATA_MASK 0x100
+static const u8 s6e63m0_dbi_read_commands[] = {
+ MCS_READ_ID1,
+ MCS_READ_ID2,
+ MCS_READ_ID3,
+ 0, /* sentinel */
+};
-static int s6e63m0_spi_dcs_read(struct device *dev, const u8 cmd, u8 *data)
+static int s6e63m0_spi_dcs_read(struct device *dev, void *trsp,
+ const u8 cmd, u8 *data)
{
- struct spi_device *spi = to_spi_device(dev);
- u16 buf[1];
- u16 rbuf[1];
+ struct mipi_dbi *dbi = trsp;
int ret;
- /* SPI buffers are always in CPU order */
- buf[0] = (u16)cmd;
- ret = spi_write_then_read(spi, buf, 2, rbuf, 2);
- dev_dbg(dev, "READ CMD: %04x RET: %04x\n", buf[0], rbuf[0]);
- if (!ret)
- /* These high 8 bits of the 9 contains the readout */
- *data = (rbuf[0] & 0x1ff) >> 1;
+ ret = mipi_dbi_command_read(dbi, cmd, data);
+ if (ret)
+ dev_err(dev, "error on DBI read command %02x\n", cmd);
return ret;
}
-static int s6e63m0_spi_write_word(struct device *dev, u16 data)
-{
- struct spi_device *spi = to_spi_device(dev);
-
- /* SPI buffers are always in CPU order */
- return spi_write(spi, &data, 2);
-}
-
-static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len)
+static int s6e63m0_spi_dcs_write(struct device *dev, void *trsp,
+ const u8 *data, size_t len)
{
- int ret = 0;
-
- dev_dbg(dev, "SPI writing dcs seq: %*ph\n", (int)len, data);
-
- /*
- * This sends 9 bits with the first bit (bit 8) set to 0
- * This indicates that this is a command. Anything after the
- * command is data.
- */
- ret = s6e63m0_spi_write_word(dev, *data);
-
- while (!ret && --len) {
- ++data;
- /* This sends 9 bits with the first bit (bit 8) set to 1 */
- ret = s6e63m0_spi_write_word(dev, *data | DATA_MASK);
- }
-
- if (ret) {
- dev_err(dev, "SPI error %d writing dcs seq: %*ph\n", ret,
- (int)len, data);
- }
+ struct mipi_dbi *dbi = trsp;
+ int ret;
+ ret = mipi_dbi_command_stackbuf(dbi, data[0], (data + 1), (len - 1));
usleep_range(300, 310);
return ret;
@@ -69,18 +45,21 @@ static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len)
static int s6e63m0_spi_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ struct mipi_dbi *dbi;
int ret;
- spi->bits_per_word = 9;
- /* Preserve e.g. SPI_3WIRE setting */
- spi->mode |= SPI_MODE_3;
- ret = spi_setup(spi);
- if (ret < 0) {
- dev_err(dev, "spi setup failed.\n");
- return ret;
- }
- return s6e63m0_probe(dev, s6e63m0_spi_dcs_read, s6e63m0_spi_dcs_write,
- false);
+ dbi = devm_kzalloc(dev, sizeof(*dbi), GFP_KERNEL);
+ if (!dbi)
+ return -ENOMEM;
+
+ ret = mipi_dbi_spi_init(spi, dbi, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
+ /* Register our custom MCS read commands */
+ dbi->read_commands = s6e63m0_dbi_read_commands;
+
+ return s6e63m0_probe(dev, dbi, s6e63m0_spi_dcs_read,
+ s6e63m0_spi_dcs_write, false);
}
static int s6e63m0_spi_remove(struct spi_device *spi)
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
index 603c5dfe8768..35d72ac663d6 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
@@ -22,31 +22,6 @@
#include "panel-samsung-s6e63m0.h"
-/* Manufacturer Command Set */
-#define MCS_ELVSS_ON 0xb1
-#define MCS_TEMP_SWIRE 0xb2
-#define MCS_PENTILE_1 0xb3
-#define MCS_PENTILE_2 0xb4
-#define MCS_GAMMA_DELTA_Y_RED 0xb5
-#define MCS_GAMMA_DELTA_X_RED 0xb6
-#define MCS_GAMMA_DELTA_Y_GREEN 0xb7
-#define MCS_GAMMA_DELTA_X_GREEN 0xb8
-#define MCS_GAMMA_DELTA_Y_BLUE 0xb9
-#define MCS_GAMMA_DELTA_X_BLUE 0xba
-#define MCS_MIECTL1 0xc0
-#define MCS_BCMODE 0xc1
-#define MCS_ERROR_CHECK 0xd5
-#define MCS_READ_ID1 0xda
-#define MCS_READ_ID2 0xdb
-#define MCS_READ_ID3 0xdc
-#define MCS_LEVEL_2_KEY 0xf0
-#define MCS_MTP_KEY 0xf1
-#define MCS_DISCTL 0xf2
-#define MCS_SRCCTL 0xf6
-#define MCS_IFCTL 0xf7
-#define MCS_PANELCTL 0xf8
-#define MCS_PGAMMACTL 0xfa
-
#define S6E63M0_LCD_ID_VALUE_M2 0xA4
#define S6E63M0_LCD_ID_VALUE_SM2 0xB4
#define S6E63M0_LCD_ID_VALUE_SM2_1 0xB6
@@ -283,8 +258,9 @@ static u8 const s6e63m0_elvss_per_gamma[NUM_GAMMA_LEVELS] = {
struct s6e63m0 {
struct device *dev;
- int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val);
- int (*dcs_write)(struct device *dev, const u8 *data, size_t len);
+ void *transport_data;
+ int (*dcs_read)(struct device *dev, void *trsp, const u8 cmd, u8 *val);
+ int (*dcs_write)(struct device *dev, void *trsp, const u8 *data, size_t len);
struct drm_panel panel;
struct backlight_device *bl_dev;
u8 lcd_type;
@@ -340,7 +316,7 @@ static void s6e63m0_dcs_read(struct s6e63m0 *ctx, const u8 cmd, u8 *data)
if (ctx->error < 0)
return;
- ctx->error = ctx->dcs_read(ctx->dev, cmd, data);
+ ctx->error = ctx->dcs_read(ctx->dev, ctx->transport_data, cmd, data);
}
static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
@@ -348,7 +324,7 @@ static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
if (ctx->error < 0 || len == 0)
return;
- ctx->error = ctx->dcs_write(ctx->dev, data, len);
+ ctx->error = ctx->dcs_write(ctx->dev, ctx->transport_data, data, len);
}
#define s6e63m0_dcs_write_seq_static(ctx, seq ...) \
@@ -713,9 +689,9 @@ static int s6e63m0_backlight_register(struct s6e63m0 *ctx, u32 max_brightness)
return ret;
}
-int s6e63m0_probe(struct device *dev,
- int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val),
- int (*dcs_write)(struct device *dev, const u8 *data, size_t len),
+int s6e63m0_probe(struct device *dev, void *trsp,
+ int (*dcs_read)(struct device *dev, void *trsp, const u8 cmd, u8 *val),
+ int (*dcs_write)(struct device *dev, void *trsp, const u8 *data, size_t len),
bool dsi_mode)
{
struct s6e63m0 *ctx;
@@ -726,6 +702,7 @@ int s6e63m0_probe(struct device *dev,
if (!ctx)
return -ENOMEM;
+ ctx->transport_data = trsp;
ctx->dsi_mode = dsi_mode;
ctx->dcs_read = dcs_read;
ctx->dcs_write = dcs_write;
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h
index c669fec91763..306605ed1117 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h
@@ -3,9 +3,36 @@
#ifndef _PANEL_SAMSUNG_S6E63M0_H
#define _PANEL_SAMSUNG_S6E63M0_H
-int s6e63m0_probe(struct device *dev,
- int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val),
- int (*dcs_write)(struct device *dev, const u8 *data,
+/* Manufacturer Command Set */
+#define MCS_ELVSS_ON 0xb1
+#define MCS_TEMP_SWIRE 0xb2
+#define MCS_PENTILE_1 0xb3
+#define MCS_PENTILE_2 0xb4
+#define MCS_GAMMA_DELTA_Y_RED 0xb5
+#define MCS_GAMMA_DELTA_X_RED 0xb6
+#define MCS_GAMMA_DELTA_Y_GREEN 0xb7
+#define MCS_GAMMA_DELTA_X_GREEN 0xb8
+#define MCS_GAMMA_DELTA_Y_BLUE 0xb9
+#define MCS_GAMMA_DELTA_X_BLUE 0xba
+#define MCS_MIECTL1 0xc0
+#define MCS_BCMODE 0xc1
+#define MCS_ERROR_CHECK 0xd5
+#define MCS_READ_ID1 0xda
+#define MCS_READ_ID2 0xdb
+#define MCS_READ_ID3 0xdc
+#define MCS_LEVEL_2_KEY 0xf0
+#define MCS_MTP_KEY 0xf1
+#define MCS_DISCTL 0xf2
+#define MCS_SRCCTL 0xf6
+#define MCS_IFCTL 0xf7
+#define MCS_PANELCTL 0xf8
+#define MCS_PGAMMACTL 0xfa
+
+int s6e63m0_probe(struct device *dev, void *trsp,
+ int (*dcs_read)(struct device *dev, void *trsp,
+ const u8 cmd, u8 *val),
+ int (*dcs_write)(struct device *dev, void *trsp,
+ const u8 *data,
size_t len),
bool dsi_mode);
int s6e63m0_remove(struct device *dev);
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
index 527371120266..9b3599d6d2de 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
@@ -990,8 +990,8 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
- | MIPI_DSI_MODE_VIDEO_HFP | MIPI_DSI_MODE_VIDEO_HBP
- | MIPI_DSI_MODE_VIDEO_HSA | MIPI_DSI_MODE_EOT_PACKET
+ | MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP
+ | MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_NO_EOT_PACKET
| MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT;
ret = s6e8aa0_parse_dt(ctx);
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index 16dbf0f353ed..b937e24dac8e 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -282,7 +282,7 @@ static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_HSE |
MIPI_DSI_CLOCK_NON_CONTINUOUS |
- MIPI_DSI_MODE_EOT_PACKET;
+ MIPI_DSI_MODE_NO_EOT_PACKET;
sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL);
if (!sharp_nt)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 1b80290c2b53..9b6c4e6c38a1 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -36,6 +36,8 @@
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
+#include <drm/drm_dp_aux_bus.h>
+#include <drm/drm_dp_helper.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_panel.h>
@@ -185,6 +187,7 @@ struct panel_simple {
struct regulator *supply;
struct i2c_adapter *ddc;
+ struct drm_dp_aux *aux;
struct gpio_desc *enable_gpio;
struct gpio_desc *hpd_gpio;
@@ -657,7 +660,8 @@ static void panel_simple_parse_panel_timing_node(struct device *dev,
dev_err(dev, "Reject override mode: No display_timing found\n");
}
-static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
+static int panel_simple_probe(struct device *dev, const struct panel_desc *desc,
+ struct drm_dp_aux *aux)
{
struct panel_simple *panel;
struct display_timing dt;
@@ -673,6 +677,7 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
panel->enabled = false;
panel->prepared_time = 0;
panel->desc = desc;
+ panel->aux = aux;
panel->no_hpd = of_property_read_bool(dev->of_node, "no-hpd");
if (!panel->no_hpd) {
@@ -707,6 +712,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
if (!panel->ddc)
return -EPROBE_DEFER;
+ } else if (aux) {
+ panel->ddc = &aux->ddc;
}
if (desc == &panel_dpi) {
@@ -742,10 +749,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
desc->bpc != 8);
break;
case DRM_MODE_CONNECTOR_eDP:
- if (desc->bus_format == 0)
- dev_warn(dev, "Specify missing bus_format\n");
- if (desc->bpc != 6 && desc->bpc != 8)
- dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc);
+ if (desc->bpc != 6 && desc->bpc != 8 && desc->bpc != 10)
+ dev_warn(dev, "Expected bpc in {6,8,10} but got: %u\n", desc->bpc);
break;
case DRM_MODE_CONNECTOR_DSI:
if (desc->bpc != 6 && desc->bpc != 8)
@@ -793,6 +798,15 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
if (err)
goto disable_pm_runtime;
+ if (!panel->base.backlight && panel->aux) {
+ pm_runtime_get_sync(dev);
+ err = drm_panel_dp_aux_backlight(&panel->base, panel->aux);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ if (err)
+ goto disable_pm_runtime;
+ }
+
drm_panel_add(&panel->base);
return 0;
@@ -801,7 +815,7 @@ disable_pm_runtime:
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
free_ddc:
- if (panel->ddc)
+ if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc))
put_device(&panel->ddc->dev);
return err;
@@ -817,7 +831,7 @@ static int panel_simple_remove(struct device *dev)
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
- if (panel->ddc)
+ if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc))
put_device(&panel->ddc->dev);
return 0;
@@ -1080,6 +1094,36 @@ static const struct panel_desc auo_b133xtn01 = {
},
};
+static const struct drm_display_mode auo_b133han05_mode = {
+ .clock = 142600,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 58,
+ .hsync_end = 1920 + 58 + 42,
+ .htotal = 1920 + 58 + 42 + 60,
+ .vdisplay = 1080,
+ .vsync_start = 1080 + 3,
+ .vsync_end = 1080 + 3 + 5,
+ .vtotal = 1080 + 3 + 5 + 54,
+};
+
+static const struct panel_desc auo_b133han05 = {
+ .modes = &auo_b133han05_mode,
+ .num_modes = 1,
+ .bpc = 8,
+ .size = {
+ .width = 293,
+ .height = 165,
+ },
+ .delay = {
+ .prepare = 100,
+ .enable = 20,
+ .unprepare = 50,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB,
+ .connector_type = DRM_MODE_CONNECTOR_eDP,
+};
+
static const struct drm_display_mode auo_b133htn01_mode = {
.clock = 150660,
.hdisplay = 1920,
@@ -1107,6 +1151,36 @@ static const struct panel_desc auo_b133htn01 = {
},
};
+static const struct drm_display_mode auo_b140han06_mode = {
+ .clock = 141000,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 16,
+ .hsync_end = 1920 + 16 + 16,
+ .htotal = 1920 + 16 + 16 + 152,
+ .vdisplay = 1080,
+ .vsync_start = 1080 + 3,
+ .vsync_end = 1080 + 3 + 14,
+ .vtotal = 1080 + 3 + 14 + 19,
+};
+
+static const struct panel_desc auo_b140han06 = {
+ .modes = &auo_b140han06_mode,
+ .num_modes = 1,
+ .bpc = 8,
+ .size = {
+ .width = 309,
+ .height = 174,
+ },
+ .delay = {
+ .prepare = 100,
+ .enable = 20,
+ .unprepare = 50,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB,
+ .connector_type = DRM_MODE_CONNECTOR_eDP,
+};
+
static const struct display_timing auo_g070vvn01_timings = {
.pixelclock = { 33300000, 34209000, 45000000 },
.hactive = { 800, 800, 800 },
@@ -1179,6 +1253,8 @@ static const struct panel_desc auo_g104sn02 = {
.width = 211,
.height = 158,
},
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
};
static const struct drm_display_mode auo_g121ean01_mode = {
@@ -1929,6 +2005,32 @@ static const struct panel_desc edt_et035012dm6 = {
.bus_flags = DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
};
+static const struct drm_display_mode edt_etm0350g0dh6_mode = {
+ .clock = 6520,
+ .hdisplay = 320,
+ .hsync_start = 320 + 20,
+ .hsync_end = 320 + 20 + 68,
+ .htotal = 320 + 20 + 68,
+ .vdisplay = 240,
+ .vsync_start = 240 + 4,
+ .vsync_end = 240 + 4 + 18,
+ .vtotal = 240 + 4 + 18,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc edt_etm0350g0dh6 = {
+ .modes = &edt_etm0350g0dh6_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 70,
+ .height = 53,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
static const struct drm_display_mode edt_etm043080dh6gp_mode = {
.clock = 10870,
.hdisplay = 480,
@@ -1980,6 +2082,9 @@ static const struct panel_desc edt_etm0430g0dh6 = {
.width = 95,
.height = 54,
},
+ .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
};
static const struct drm_display_mode edt_et057090dhu_mode = {
@@ -2044,6 +2149,60 @@ static const struct panel_desc edt_etm0700g0bdh6 = {
},
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
+static const struct drm_display_mode edt_etmv570g2dhu_mode = {
+ .clock = 25175,
+ .hdisplay = 640,
+ .hsync_start = 640,
+ .hsync_end = 640 + 16,
+ .htotal = 640 + 16 + 30 + 114,
+ .vdisplay = 480,
+ .vsync_start = 480 + 10,
+ .vsync_end = 480 + 10 + 3,
+ .vtotal = 480 + 10 + 3 + 35,
+ .flags = DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_PHSYNC,
+};
+
+static const struct panel_desc edt_etmv570g2dhu = {
+ .modes = &edt_etmv570g2dhu_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 115,
+ .height = 86,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
+static const struct display_timing eink_vb3300_kca_timing = {
+ .pixelclock = { 40000000, 40000000, 40000000 },
+ .hactive = { 334, 334, 334 },
+ .hfront_porch = { 1, 1, 1 },
+ .hback_porch = { 1, 1, 1 },
+ .hsync_len = { 1, 1, 1 },
+ .vactive = { 1405, 1405, 1405 },
+ .vfront_porch = { 1, 1, 1 },
+ .vback_porch = { 1, 1, 1 },
+ .vsync_len = { 1, 1, 1 },
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE,
+};
+
+static const struct panel_desc eink_vb3300_kca = {
+ .timings = &eink_vb3300_kca_timing,
+ .num_timings = 1,
+ .bpc = 6,
+ .size = {
+ .width = 157,
+ .height = 209,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
};
static const struct display_timing evervision_vgg804821_timing = {
@@ -2967,6 +3126,38 @@ static const struct panel_desc logictechno_lt170410_2whc = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
+static const struct drm_display_mode logictechno_lttd800480070_l6wh_rt_mode = {
+ .clock = 33000,
+ .hdisplay = 800,
+ .hsync_start = 800 + 154,
+ .hsync_end = 800 + 154 + 3,
+ .htotal = 800 + 154 + 3 + 43,
+ .vdisplay = 480,
+ .vsync_start = 480 + 47,
+ .vsync_end = 480 + 47 + 3,
+ .vtotal = 480 + 47 + 3 + 20,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc logictechno_lttd800480070_l6wh_rt = {
+ .modes = &logictechno_lttd800480070_l6wh_rt_mode,
+ .num_modes = 1,
+ .bpc = 8,
+ .size = {
+ .width = 154,
+ .height = 86,
+ },
+ .delay = {
+ .prepare = 45,
+ .enable = 100,
+ .disable = 100,
+ .unprepare = 45
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
.clock = 30400,
.hdisplay = 800,
@@ -3033,6 +3224,37 @@ static const struct panel_desc mitsubishi_aa070mc01 = {
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
};
+static const struct display_timing multi_inno_mi1010ait_1cp_timing = {
+ .pixelclock = { 68900000, 70000000, 73400000 },
+ .hactive = { 1280, 1280, 1280 },
+ .hfront_porch = { 30, 60, 71 },
+ .hback_porch = { 30, 60, 71 },
+ .hsync_len = { 10, 10, 48 },
+ .vactive = { 800, 800, 800 },
+ .vfront_porch = { 5, 10, 10 },
+ .vback_porch = { 5, 10, 10 },
+ .vsync_len = { 5, 6, 13 },
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH,
+};
+
+static const struct panel_desc multi_inno_mi1010ait_1cp = {
+ .timings = &multi_inno_mi1010ait_1cp_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 217,
+ .height = 136,
+ },
+ .delay = {
+ .enable = 50,
+ .disable = 50,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct display_timing nec_nl12880bc20_05_timing = {
.pixelclock = { 67000000, 71000000, 75000000 },
.hactive = { 1280, 1280, 1280 },
@@ -3463,6 +3685,46 @@ static const struct panel_desc qd43003c0_40 = {
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
};
+static const struct drm_display_mode qishenglong_gopher2b_lcd_modes[] = {
+ { /* 60 Hz */
+ .clock = 10800,
+ .hdisplay = 480,
+ .hsync_start = 480 + 77,
+ .hsync_end = 480 + 77 + 41,
+ .htotal = 480 + 77 + 41 + 2,
+ .vdisplay = 272,
+ .vsync_start = 272 + 16,
+ .vsync_end = 272 + 16 + 10,
+ .vtotal = 272 + 16 + 10 + 2,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+ },
+ { /* 50 Hz */
+ .clock = 10800,
+ .hdisplay = 480,
+ .hsync_start = 480 + 17,
+ .hsync_end = 480 + 17 + 41,
+ .htotal = 480 + 17 + 41 + 2,
+ .vdisplay = 272,
+ .vsync_start = 272 + 116,
+ .vsync_end = 272 + 116 + 10,
+ .vtotal = 272 + 116 + 10 + 2,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+ },
+};
+
+static const struct panel_desc qishenglong_gopher2b_lcd = {
+ .modes = qishenglong_gopher2b_lcd_modes,
+ .num_modes = ARRAY_SIZE(qishenglong_gopher2b_lcd_modes),
+ .bpc = 8,
+ .size = {
+ .width = 95,
+ .height = 54,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
static const struct display_timing rocktech_rk070er9427_timing = {
.pixelclock = { 26400000, 33300000, 46800000 },
.hactive = { 800, 800, 800 },
@@ -4234,9 +4496,15 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "auo,b116xw03",
.data = &auo_b116xw03,
}, {
+ .compatible = "auo,b133han05",
+ .data = &auo_b133han05,
+ }, {
.compatible = "auo,b133htn01",
.data = &auo_b133htn01,
}, {
+ .compatible = "auo,b140han06",
+ .data = &auo_b140han06,
+ }, {
.compatible = "auo,b133xtn01",
.data = &auo_b133xtn01,
}, {
@@ -4330,6 +4598,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "edt,et035012dm6",
.data = &edt_et035012dm6,
}, {
+ .compatible = "edt,etm0350g0dh6",
+ .data = &edt_etm0350g0dh6,
+ }, {
.compatible = "edt,etm043080dh6gp",
.data = &edt_etm043080dh6gp,
}, {
@@ -4351,6 +4622,12 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "edt,etm0700g0edh6",
.data = &edt_etm0700g0bdh6,
}, {
+ .compatible = "edt,etmv570g2dhu",
+ .data = &edt_etmv570g2dhu,
+ }, {
+ .compatible = "eink,vb3300-kca",
+ .data = &eink_vb3300_kca,
+ }, {
.compatible = "evervision,vgg804821",
.data = &evervision_vgg804821,
}, {
@@ -4462,9 +4739,15 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "logictechno,lt170410-2whc",
.data = &logictechno_lt170410_2whc,
}, {
+ .compatible = "logictechno,lttd800480070-l6wh-rt",
+ .data = &logictechno_lttd800480070_l6wh_rt,
+ }, {
.compatible = "mitsubishi,aa070mc01-ca1",
.data = &mitsubishi_aa070mc01,
}, {
+ .compatible = "multi-inno,mi1010ait-1cp",
+ .data = &multi_inno_mi1010ait_1cp,
+ }, {
.compatible = "nec,nl12880bc20-05",
.data = &nec_nl12880bc20_05,
}, {
@@ -4516,6 +4799,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "qiaodian,qd43003c0-40",
.data = &qd43003c0_40,
}, {
+ .compatible = "qishenglong,gopher2b-lcd",
+ .data = &qishenglong_gopher2b_lcd,
+ }, {
.compatible = "rocktech,rk070er9427",
.data = &rocktech_rk070er9427,
}, {
@@ -4632,7 +4918,7 @@ static int panel_simple_platform_probe(struct platform_device *pdev)
if (!id)
return -ENODEV;
- return panel_simple_probe(&pdev->dev, id->data);
+ return panel_simple_probe(&pdev->dev, id->data, NULL);
}
static int panel_simple_platform_remove(struct platform_device *pdev)
@@ -4867,7 +5153,7 @@ static const struct panel_desc_dsi osd101t2045_53ts = {
},
.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_EOT_PACKET,
+ MIPI_DSI_MODE_NO_EOT_PACKET,
.format = MIPI_DSI_FMT_RGB888,
.lanes = 4,
};
@@ -4912,7 +5198,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
desc = id->data;
- err = panel_simple_probe(&dsi->dev, &desc->desc);
+ err = panel_simple_probe(&dsi->dev, &desc->desc, NULL);
if (err < 0)
return err;
@@ -4957,6 +5243,38 @@ static struct mipi_dsi_driver panel_simple_dsi_driver = {
.shutdown = panel_simple_dsi_shutdown,
};
+static int panel_simple_dp_aux_ep_probe(struct dp_aux_ep_device *aux_ep)
+{
+ const struct of_device_id *id;
+
+ id = of_match_node(platform_of_match, aux_ep->dev.of_node);
+ if (!id)
+ return -ENODEV;
+
+ return panel_simple_probe(&aux_ep->dev, id->data, aux_ep->aux);
+}
+
+static void panel_simple_dp_aux_ep_remove(struct dp_aux_ep_device *aux_ep)
+{
+ panel_simple_remove(&aux_ep->dev);
+}
+
+static void panel_simple_dp_aux_ep_shutdown(struct dp_aux_ep_device *aux_ep)
+{
+ panel_simple_shutdown(&aux_ep->dev);
+}
+
+static struct dp_aux_ep_driver panel_simple_dp_aux_ep_driver = {
+ .driver = {
+ .name = "panel-simple-dp-aux",
+ .of_match_table = platform_of_match, /* Same as platform one! */
+ .pm = &panel_simple_pm_ops,
+ },
+ .probe = panel_simple_dp_aux_ep_probe,
+ .remove = panel_simple_dp_aux_ep_remove,
+ .shutdown = panel_simple_dp_aux_ep_shutdown,
+};
+
static int __init panel_simple_init(void)
{
int err;
@@ -4965,15 +5283,25 @@ static int __init panel_simple_init(void)
if (err < 0)
return err;
+ err = dp_aux_dp_driver_register(&panel_simple_dp_aux_ep_driver);
+ if (err < 0)
+ goto err_did_platform_register;
+
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
err = mipi_dsi_driver_register(&panel_simple_dsi_driver);
- if (err < 0) {
- platform_driver_unregister(&panel_simple_platform_driver);
- return err;
- }
+ if (err < 0)
+ goto err_did_aux_ep_register;
}
return 0;
+
+err_did_aux_ep_register:
+ dp_aux_dp_driver_unregister(&panel_simple_dp_aux_ep_driver);
+
+err_did_platform_register:
+ platform_driver_unregister(&panel_simple_platform_driver);
+
+ return err;
}
module_init(panel_simple_init);
@@ -4982,6 +5310,7 @@ static void __exit panel_simple_exit(void)
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
mipi_dsi_driver_unregister(&panel_simple_dsi_driver);
+ dp_aux_dp_driver_unregister(&panel_simple_dp_aux_ep_driver);
platform_driver_unregister(&panel_simple_platform_driver);
}
module_exit(panel_simple_exit);
diff --git a/drivers/gpu/drm/panel/panel-sony-acx424akp.c b/drivers/gpu/drm/panel/panel-sony-acx424akp.c
index 95659a4d15e9..9536d56a94a5 100644
--- a/drivers/gpu/drm/panel/panel-sony-acx424akp.c
+++ b/drivers/gpu/drm/panel/panel-sony-acx424akp.c
@@ -40,7 +40,6 @@
struct acx424akp {
struct drm_panel panel;
struct device *dev;
- struct backlight_device *bl;
struct regulator *supply;
struct gpio_desc *reset_gpio;
bool video_mode;
@@ -102,6 +101,18 @@ static int acx424akp_set_brightness(struct backlight_device *bl)
u8 par;
int ret;
+ if (backlight_is_blank(bl)) {
+ /* Disable backlight */
+ par = 0x00;
+ ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
+ &par, 1);
+ if (ret) {
+ dev_err(acx->dev, "failed to disable display backlight (%d)\n", ret);
+ return ret;
+ }
+ return 0;
+ }
+
/* Calculate the PWM duty cycle in n/256's */
pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1);
pwm_div = max(1,
@@ -172,6 +183,12 @@ static const struct backlight_ops acx424akp_bl_ops = {
.update_status = acx424akp_set_brightness,
};
+static const struct backlight_properties acx424akp_bl_props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 512,
+ .max_brightness = 1023,
+};
+
static int acx424akp_read_id(struct acx424akp *acx)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
@@ -310,8 +327,6 @@ static int acx424akp_prepare(struct drm_panel *panel)
}
}
- acx->bl->props.power = FB_BLANK_NORMAL;
-
return 0;
err_power_off:
@@ -323,18 +338,8 @@ static int acx424akp_unprepare(struct drm_panel *panel)
{
struct acx424akp *acx = panel_to_acx424akp(panel);
struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
- u8 par;
int ret;
- /* Disable backlight */
- par = 0x00;
- ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
- &par, 1);
- if (ret) {
- dev_err(acx->dev, "failed to disable display backlight (%d)\n", ret);
- return ret;
- }
-
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret) {
dev_err(acx->dev, "failed to turn display off (%d)\n", ret);
@@ -350,36 +355,10 @@ static int acx424akp_unprepare(struct drm_panel *panel)
msleep(85);
acx424akp_power_off(acx);
- acx->bl->props.power = FB_BLANK_POWERDOWN;
-
- return 0;
-}
-
-static int acx424akp_enable(struct drm_panel *panel)
-{
- struct acx424akp *acx = panel_to_acx424akp(panel);
-
- /*
- * The backlight is on as long as the display is on
- * so no use to call backlight_enable() here.
- */
- acx->bl->props.power = FB_BLANK_UNBLANK;
return 0;
}
-static int acx424akp_disable(struct drm_panel *panel)
-{
- struct acx424akp *acx = panel_to_acx424akp(panel);
-
- /*
- * The backlight is on as long as the display is on
- * so no use to call backlight_disable() here.
- */
- acx->bl->props.power = FB_BLANK_NORMAL;
-
- return 0;
-}
static int acx424akp_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
@@ -409,10 +388,8 @@ static int acx424akp_get_modes(struct drm_panel *panel,
}
static const struct drm_panel_funcs acx424akp_drm_funcs = {
- .disable = acx424akp_disable,
.unprepare = acx424akp_unprepare,
.prepare = acx424akp_prepare,
- .enable = acx424akp_enable,
.get_modes = acx424akp_get_modes,
};
@@ -458,25 +435,18 @@ static int acx424akp_probe(struct mipi_dsi_device *dsi)
/* This asserts RESET by default */
acx->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
- if (IS_ERR(acx->reset_gpio)) {
- ret = PTR_ERR(acx->reset_gpio);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "failed to request GPIO (%d)\n", ret);
- return ret;
- }
+ if (IS_ERR(acx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(acx->reset_gpio),
+ "failed to request GPIO\n");
drm_panel_init(&acx->panel, dev, &acx424akp_drm_funcs,
DRM_MODE_CONNECTOR_DSI);
- acx->bl = devm_backlight_device_register(dev, "acx424akp", dev, acx,
- &acx424akp_bl_ops, NULL);
- if (IS_ERR(acx->bl)) {
- dev_err(dev, "failed to register backlight device\n");
- return PTR_ERR(acx->bl);
- }
- acx->bl->props.max_brightness = 1023;
- acx->bl->props.brightness = 512;
- acx->bl->props.power = FB_BLANK_POWERDOWN;
+ acx->panel.backlight = devm_backlight_device_register(dev, "acx424akp", dev, acx,
+ &acx424akp_bl_ops, &acx424akp_bl_props);
+ if (IS_ERR(acx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(acx->panel.backlight),
+ "failed to register backlight device\n");
drm_panel_add(&acx->panel);
diff --git a/drivers/gpu/drm/panel/panel-widechips-ws2401.c b/drivers/gpu/drm/panel/panel-widechips-ws2401.c
new file mode 100644
index 000000000000..8bc976f54b80
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-widechips-ws2401.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Panel driver for the WideChips WS2401 480x800 DPI RGB panel, used in
+ * the Samsung Mobile Display (SMD) LMS380KF01.
+ * Found in the Samsung Galaxy Ace 2 GT-I8160 mobile phone.
+ * Linus Walleij <linus.walleij@linaro.org>
+ * Inspired by code and know-how in the vendor driver by Gareth Phillips.
+ */
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/media-bus-format.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <video/mipi_display.h>
+
+#define WS2401_RESCTL 0xb8 /* Resolution select control */
+#define WS2401_PSMPS 0xbd /* SMPS positive control */
+#define WS2401_NSMPS 0xbe /* SMPS negative control */
+#define WS2401_SMPS 0xbf
+#define WS2401_BCMODE 0xc1 /* Backlight control mode */
+#define WS2401_WRBLCTL 0xc3 /* Backlight control */
+#define WS2401_WRDISBV 0xc4 /* Write manual brightness */
+#define WS2401_WRCTRLD 0xc6 /* Write BL control */
+#define WS2401_WRMIE 0xc7 /* Write MIE mode */
+#define WS2401_READ_ID1 0xda /* Read panel ID 1 */
+#define WS2401_READ_ID2 0xdb /* Read panel ID 2 */
+#define WS2401_READ_ID3 0xdc /* Read panel ID 3 */
+#define WS2401_GAMMA_R1 0xe7 /* Gamma red 1 */
+#define WS2401_GAMMA_G1 0xe8 /* Gamma green 1 */
+#define WS2401_GAMMA_B1 0xe9 /* Gamma blue 1 */
+#define WS2401_GAMMA_R2 0xea /* Gamma red 2 */
+#define WS2401_GAMMA_G2 0xeb /* Gamma green 2 */
+#define WS2401_GAMMA_B2 0xec /* Gamma blue 2 */
+#define WS2401_PASSWD1 0xf0 /* Password command for level 2 */
+#define WS2401_DISCTL 0xf2 /* Display control */
+#define WS2401_PWRCTL 0xf3 /* Power control */
+#define WS2401_VCOMCTL 0xf4 /* VCOM control */
+#define WS2401_SRCCTL 0xf5 /* Source control */
+#define WS2401_PANELCTL 0xf6 /* Panel control */
+
+static const u8 ws2401_dbi_read_commands[] = {
+ WS2401_READ_ID1,
+ WS2401_READ_ID2,
+ WS2401_READ_ID3,
+ 0, /* sentinel */
+};
+
+/**
+ * struct ws2401 - state container for a panel controlled by the WS2401
+ * controller
+ */
+struct ws2401 {
+ /** @dev: the container device */
+ struct device *dev;
+ /** @dbi: the DBI bus abstraction handle */
+ struct mipi_dbi dbi;
+ /** @panel: the DRM panel instance for this device */
+ struct drm_panel panel;
+ /** @width: the width of this panel in mm */
+ u32 width;
+ /** @height: the height of this panel in mm */
+ u32 height;
+ /** @reset: reset GPIO line */
+ struct gpio_desc *reset;
+ /** @regulators: VCCIO and VIO supply regulators */
+ struct regulator_bulk_data regulators[2];
+ /** @internal_bl: If using internal backlight */
+ bool internal_bl;
+};
+
+static const struct drm_display_mode lms380kf01_480_800_mode = {
+ /*
+ * The vendor driver states that the "SMD panel" has a clock
+ * frequency of 49920000 Hz / 2 = 24960000 Hz.
+ */
+ .clock = 24960,
+ .hdisplay = 480,
+ .hsync_start = 480 + 8,
+ .hsync_end = 480 + 8 + 10,
+ .htotal = 480 + 8 + 10 + 8,
+ .vdisplay = 800,
+ .vsync_start = 800 + 8,
+ .vsync_end = 800 + 8 + 2,
+ .vtotal = 800 + 8 + 2 + 18,
+ .width_mm = 50,
+ .height_mm = 84,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static inline struct ws2401 *to_ws2401(struct drm_panel *panel)
+{
+ return container_of(panel, struct ws2401, panel);
+}
+
+static void ws2401_read_mtp_id(struct ws2401 *ws)
+{
+ struct mipi_dbi *dbi = &ws->dbi;
+ u8 id1, id2, id3;
+ int ret;
+
+ ret = mipi_dbi_command_read(dbi, WS2401_READ_ID1, &id1);
+ if (ret) {
+ dev_err(ws->dev, "unable to read MTP ID 1\n");
+ return;
+ }
+ ret = mipi_dbi_command_read(dbi, WS2401_READ_ID2, &id2);
+ if (ret) {
+ dev_err(ws->dev, "unable to read MTP ID 2\n");
+ return;
+ }
+ ret = mipi_dbi_command_read(dbi, WS2401_READ_ID3, &id3);
+ if (ret) {
+ dev_err(ws->dev, "unable to read MTP ID 3\n");
+ return;
+ }
+ dev_info(ws->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3);
+}
+
+static int ws2401_power_on(struct ws2401 *ws)
+{
+ struct mipi_dbi *dbi = &ws->dbi;
+ int ret;
+
+ /* Power up */
+ ret = regulator_bulk_enable(ARRAY_SIZE(ws->regulators),
+ ws->regulators);
+ if (ret) {
+ dev_err(ws->dev, "failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+ msleep(10);
+
+ /* Assert reset >=1 ms */
+ gpiod_set_value_cansleep(ws->reset, 1);
+ usleep_range(1000, 5000);
+ /* De-assert reset */
+ gpiod_set_value_cansleep(ws->reset, 0);
+ /* Wait >= 10 ms */
+ msleep(10);
+ dev_dbg(ws->dev, "de-asserted RESET\n");
+
+ /*
+ * Exit sleep mode and initialize display - some hammering is
+ * necessary.
+ */
+ mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+ mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+ msleep(50);
+
+ /* Magic to unlock level 2 control of the display */
+ mipi_dbi_command(dbi, WS2401_PASSWD1, 0x5a, 0x5a);
+ /* Configure resolution to 480RGBx800 */
+ mipi_dbi_command(dbi, WS2401_RESCTL, 0x12);
+ /* Set addressing mode Flip V(d0), Flip H(d1) RGB/BGR(d3) */
+ mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, 0x01);
+ /* Set pixel format: 24 bpp */
+ mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, 0x70);
+ mipi_dbi_command(dbi, WS2401_SMPS, 0x00, 0x0f);
+ mipi_dbi_command(dbi, WS2401_PSMPS, 0x06, 0x03, /* DDVDH: 4.6v */
+ 0x7e, 0x03, 0x12, 0x37);
+ mipi_dbi_command(dbi, WS2401_NSMPS, 0x06, 0x03, /* DDVDH: -4.6v */
+ 0x7e, 0x02, 0x15, 0x37);
+ mipi_dbi_command(dbi, WS2401_SMPS, 0x02, 0x0f);
+ mipi_dbi_command(dbi, WS2401_PWRCTL, 0x10, 0xA9, 0x00, 0x01, 0x44,
+ 0xb4, /* VGH:16.1v, VGL:-13.8v */
+ 0x50, /* GREFP:4.2v (default) */
+ 0x50, /* GREFN:-4.2v (default) */
+ 0x00,
+ 0x44); /* VOUTL:-10v (default) */
+ mipi_dbi_command(dbi, WS2401_DISCTL, 0x01, 0x00, 0x00, 0x00, 0x14,
+ 0x16);
+ mipi_dbi_command(dbi, WS2401_VCOMCTL, 0x30, 0x53, 0x53);
+ mipi_dbi_command(dbi, WS2401_SRCCTL, 0x03, 0x0C, 0x00, 0x00, 0x00,
+ 0x01, /* 2 dot inversion */
+ 0x01, 0x06, 0x03);
+ mipi_dbi_command(dbi, WS2401_PANELCTL, 0x14, 0x00, 0x80, 0x00);
+ mipi_dbi_command(dbi, WS2401_WRMIE, 0x01);
+
+ /* Set up gamma, probably these are P-gamma and N-gamma for each color */
+ mipi_dbi_command(dbi, WS2401_GAMMA_R1, 0x00,
+ 0x5b, 0x42, 0x41, 0x3f, 0x42, 0x3d, 0x38, 0x2e,
+ 0x2b, 0x2a, 0x27, 0x22, 0x27, 0x0f, 0x00, 0x00);
+ mipi_dbi_command(dbi, WS2401_GAMMA_R2, 0x00,
+ 0x5b, 0x42, 0x41, 0x3f, 0x42, 0x3d, 0x38, 0x2e,
+ 0x2b, 0x2a, 0x27, 0x22, 0x27, 0x0f, 0x00, 0x00);
+ mipi_dbi_command(dbi, WS2401_GAMMA_G1, 0x00,
+ 0x59, 0x40, 0x3f, 0x3e, 0x41, 0x3d, 0x39, 0x2f,
+ 0x2c, 0x2b, 0x29, 0x25, 0x29, 0x19, 0x08, 0x00);
+ mipi_dbi_command(dbi, WS2401_GAMMA_G2, 0x00,
+ 0x59, 0x40, 0x3f, 0x3e, 0x41, 0x3d, 0x39, 0x2f,
+ 0x2c, 0x2b, 0x29, 0x25, 0x29, 0x19, 0x08, 0x00);
+ mipi_dbi_command(dbi, WS2401_GAMMA_B1, 0x00,
+ 0x57, 0x3b, 0x3a, 0x3b, 0x3f, 0x3b, 0x38, 0x27,
+ 0x38, 0x2a, 0x26, 0x22, 0x34, 0x0c, 0x09, 0x00);
+ mipi_dbi_command(dbi, WS2401_GAMMA_B2, 0x00,
+ 0x57, 0x3b, 0x3a, 0x3b, 0x3f, 0x3b, 0x38, 0x27,
+ 0x38, 0x2a, 0x26, 0x22, 0x34, 0x0c, 0x09, 0x00);
+
+ if (ws->internal_bl) {
+ mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x2c);
+ } else {
+ mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x00);
+ /*
+ * When not using internal backlight we do not need any further
+ * L2 accesses to the panel so we close the door on our way out.
+ * Otherwise we need to leave the L2 door open.
+ */
+ mipi_dbi_command(dbi, WS2401_PASSWD1, 0xa5, 0xa5);
+ }
+
+ return 0;
+}
+
+static int ws2401_power_off(struct ws2401 *ws)
+{
+ /* Go into RESET and disable regulators */
+ gpiod_set_value_cansleep(ws->reset, 1);
+ return regulator_bulk_disable(ARRAY_SIZE(ws->regulators),
+ ws->regulators);
+}
+
+static int ws2401_unprepare(struct drm_panel *panel)
+{
+ struct ws2401 *ws = to_ws2401(panel);
+ struct mipi_dbi *dbi = &ws->dbi;
+
+ /* Make sure we disable backlight, if any */
+ if (ws->internal_bl)
+ mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x00);
+ mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE);
+ msleep(120);
+ return ws2401_power_off(to_ws2401(panel));
+}
+
+static int ws2401_disable(struct drm_panel *panel)
+{
+ struct ws2401 *ws = to_ws2401(panel);
+ struct mipi_dbi *dbi = &ws->dbi;
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
+ msleep(25);
+
+ return 0;
+}
+
+static int ws2401_prepare(struct drm_panel *panel)
+{
+ return ws2401_power_on(to_ws2401(panel));
+}
+
+static int ws2401_enable(struct drm_panel *panel)
+{
+ struct ws2401 *ws = to_ws2401(panel);
+ struct mipi_dbi *dbi = &ws->dbi;
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+
+ return 0;
+}
+
+/**
+ * ws2401_get_modes() - return the mode
+ * @panel: the panel to get the mode for
+ * @connector: reference to the central DRM connector control structure
+ */
+static int ws2401_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct ws2401 *ws = to_ws2401(panel);
+ struct drm_display_mode *mode;
+ static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+
+ /*
+ * We just support the LMS380KF01 so far, if we implement more panels
+ * this mode, the following connector display_info settings and
+ * probably the custom DCS sequences needs to selected based on what
+ * the target panel needs.
+ */
+ mode = drm_mode_duplicate(connector->dev, &lms380kf01_480_800_mode);
+ if (!mode) {
+ dev_err(ws->dev, "failed to add mode\n");
+ return -ENOMEM;
+ }
+
+ connector->display_info.bpc = 8;
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ connector->display_info.bus_flags =
+ DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
+ drm_display_info_set_bus_formats(&connector->display_info,
+ &bus_format, 1);
+
+ drm_mode_set_name(mode);
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs ws2401_drm_funcs = {
+ .disable = ws2401_disable,
+ .unprepare = ws2401_unprepare,
+ .prepare = ws2401_prepare,
+ .enable = ws2401_enable,
+ .get_modes = ws2401_get_modes,
+};
+
+static int ws2401_set_brightness(struct backlight_device *bl)
+{
+ struct ws2401 *ws = bl_get_data(bl);
+ struct mipi_dbi *dbi = &ws->dbi;
+ u8 brightness = backlight_get_brightness(bl);
+
+ if (backlight_is_blank(bl)) {
+ mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x00);
+ } else {
+ mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x2c);
+ mipi_dbi_command(dbi, WS2401_WRDISBV, brightness);
+ }
+
+ return 0;
+}
+
+static const struct backlight_ops ws2401_bl_ops = {
+ .update_status = ws2401_set_brightness,
+};
+
+static const struct backlight_properties ws2401_bl_props = {
+ .type = BACKLIGHT_PLATFORM,
+ .brightness = 120,
+ .max_brightness = U8_MAX,
+};
+
+static int ws2401_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct ws2401 *ws;
+ int ret;
+
+ ws = devm_kzalloc(dev, sizeof(*ws), GFP_KERNEL);
+ if (!ws)
+ return -ENOMEM;
+ ws->dev = dev;
+
+ /*
+ * VCI is the analog voltage supply
+ * VCCIO is the digital I/O voltage supply
+ */
+ ws->regulators[0].supply = "vci";
+ ws->regulators[1].supply = "vccio";
+ ret = devm_regulator_bulk_get(dev,
+ ARRAY_SIZE(ws->regulators),
+ ws->regulators);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get regulators\n");
+
+ ws->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ws->reset)) {
+ ret = PTR_ERR(ws->reset);
+ return dev_err_probe(dev, ret, "no RESET GPIO\n");
+ }
+
+ ret = mipi_dbi_spi_init(spi, &ws->dbi, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
+ ws->dbi.read_commands = ws2401_dbi_read_commands;
+
+ ws2401_power_on(ws);
+ ws2401_read_mtp_id(ws);
+ ws2401_power_off(ws);
+
+ drm_panel_init(&ws->panel, dev, &ws2401_drm_funcs,
+ DRM_MODE_CONNECTOR_DPI);
+
+ ret = drm_panel_of_backlight(&ws->panel);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get external backlight device\n");
+
+ if (!ws->panel.backlight) {
+ dev_dbg(dev, "no external backlight, using internal backlight\n");
+ ws->panel.backlight =
+ devm_backlight_device_register(dev, "ws2401", dev, ws,
+ &ws2401_bl_ops, &ws2401_bl_props);
+ if (IS_ERR(ws->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ws->panel.backlight),
+ "failed to register backlight device\n");
+ } else {
+ dev_dbg(dev, "using external backlight\n");
+ }
+
+ spi_set_drvdata(spi, ws);
+
+ drm_panel_add(&ws->panel);
+ dev_dbg(dev, "added panel\n");
+
+ return 0;
+}
+
+static int ws2401_remove(struct spi_device *spi)
+{
+ struct ws2401 *ws = spi_get_drvdata(spi);
+
+ drm_panel_remove(&ws->panel);
+ return 0;
+}
+
+/*
+ * Samsung LMS380KF01 is the one instance of this display controller that we
+ * know about, but if more are found, the controller can be parameterized
+ * here and used for other configurations.
+ */
+static const struct of_device_id ws2401_match[] = {
+ { .compatible = "samsung,lms380kf01", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ws2401_match);
+
+static struct spi_driver ws2401_driver = {
+ .probe = ws2401_probe,
+ .remove = ws2401_remove,
+ .driver = {
+ .name = "ws2401-panel",
+ .of_match_table = ws2401_match,
+ },
+};
+module_spi_driver(ws2401_driver);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("Samsung WS2401 panel driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
index 55172d63a922..d17aae8b71d7 100644
--- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
+++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
@@ -311,7 +311,7 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
- MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
drm_panel_init(&ctx->panel, &dsi->dev, &xpp055c272_funcs,
DRM_MODE_CONNECTOR_DSI);
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
index 3644652f726f..194af7f607a6 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
@@ -106,7 +106,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
if (ret) {
/* Continue if the optional regulator is missing */
if (ret != -ENODEV) {
- DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n");
+ if (ret != -EPROBE_DEFER)
+ DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n");
return ret;
}
}
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
index 125ed973feaa..bd9b7be63b0f 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
@@ -54,7 +54,8 @@ static int panfrost_clk_init(struct panfrost_device *pfdev)
if (IS_ERR(pfdev->bus_clock)) {
dev_err(pfdev->dev, "get bus_clock failed %ld\n",
PTR_ERR(pfdev->bus_clock));
- return PTR_ERR(pfdev->bus_clock);
+ err = PTR_ERR(pfdev->bus_clock);
+ goto disable_clock;
}
if (pfdev->bus_clock) {
@@ -291,55 +292,100 @@ void panfrost_device_fini(struct panfrost_device *pfdev)
panfrost_clk_fini(pfdev);
}
-const char *panfrost_exception_name(struct panfrost_device *pfdev, u32 exception_code)
-{
- switch (exception_code) {
- /* Non-Fault Status code */
- case 0x00: return "NOT_STARTED/IDLE/OK";
- case 0x01: return "DONE";
- case 0x02: return "INTERRUPTED";
- case 0x03: return "STOPPED";
- case 0x04: return "TERMINATED";
- case 0x08: return "ACTIVE";
- /* Job exceptions */
- case 0x40: return "JOB_CONFIG_FAULT";
- case 0x41: return "JOB_POWER_FAULT";
- case 0x42: return "JOB_READ_FAULT";
- case 0x43: return "JOB_WRITE_FAULT";
- case 0x44: return "JOB_AFFINITY_FAULT";
- case 0x48: return "JOB_BUS_FAULT";
- case 0x50: return "INSTR_INVALID_PC";
- case 0x51: return "INSTR_INVALID_ENC";
- case 0x52: return "INSTR_TYPE_MISMATCH";
- case 0x53: return "INSTR_OPERAND_FAULT";
- case 0x54: return "INSTR_TLS_FAULT";
- case 0x55: return "INSTR_BARRIER_FAULT";
- case 0x56: return "INSTR_ALIGN_FAULT";
- case 0x58: return "DATA_INVALID_FAULT";
- case 0x59: return "TILE_RANGE_FAULT";
- case 0x5A: return "ADDR_RANGE_FAULT";
- case 0x60: return "OUT_OF_MEMORY";
- /* GPU exceptions */
- case 0x80: return "DELAYED_BUS_FAULT";
- case 0x88: return "SHAREABILITY_FAULT";
- /* MMU exceptions */
- case 0xC1: return "TRANSLATION_FAULT_LEVEL1";
- case 0xC2: return "TRANSLATION_FAULT_LEVEL2";
- case 0xC3: return "TRANSLATION_FAULT_LEVEL3";
- case 0xC4: return "TRANSLATION_FAULT_LEVEL4";
- case 0xC8: return "PERMISSION_FAULT";
- case 0xC9 ... 0xCF: return "PERMISSION_FAULT";
- case 0xD1: return "TRANSTAB_BUS_FAULT_LEVEL1";
- case 0xD2: return "TRANSTAB_BUS_FAULT_LEVEL2";
- case 0xD3: return "TRANSTAB_BUS_FAULT_LEVEL3";
- case 0xD4: return "TRANSTAB_BUS_FAULT_LEVEL4";
- case 0xD8: return "ACCESS_FLAG";
- case 0xD9 ... 0xDF: return "ACCESS_FLAG";
- case 0xE0 ... 0xE7: return "ADDRESS_SIZE_FAULT";
- case 0xE8 ... 0xEF: return "MEMORY_ATTRIBUTES_FAULT";
+#define PANFROST_EXCEPTION(id) \
+ [DRM_PANFROST_EXCEPTION_ ## id] = { \
+ .name = #id, \
}
- return "UNKNOWN";
+struct panfrost_exception_info {
+ const char *name;
+};
+
+static const struct panfrost_exception_info panfrost_exception_infos[] = {
+ PANFROST_EXCEPTION(OK),
+ PANFROST_EXCEPTION(DONE),
+ PANFROST_EXCEPTION(INTERRUPTED),
+ PANFROST_EXCEPTION(STOPPED),
+ PANFROST_EXCEPTION(TERMINATED),
+ PANFROST_EXCEPTION(KABOOM),
+ PANFROST_EXCEPTION(EUREKA),
+ PANFROST_EXCEPTION(ACTIVE),
+ PANFROST_EXCEPTION(JOB_CONFIG_FAULT),
+ PANFROST_EXCEPTION(JOB_POWER_FAULT),
+ PANFROST_EXCEPTION(JOB_READ_FAULT),
+ PANFROST_EXCEPTION(JOB_WRITE_FAULT),
+ PANFROST_EXCEPTION(JOB_AFFINITY_FAULT),
+ PANFROST_EXCEPTION(JOB_BUS_FAULT),
+ PANFROST_EXCEPTION(INSTR_INVALID_PC),
+ PANFROST_EXCEPTION(INSTR_INVALID_ENC),
+ PANFROST_EXCEPTION(INSTR_TYPE_MISMATCH),
+ PANFROST_EXCEPTION(INSTR_OPERAND_FAULT),
+ PANFROST_EXCEPTION(INSTR_TLS_FAULT),
+ PANFROST_EXCEPTION(INSTR_BARRIER_FAULT),
+ PANFROST_EXCEPTION(INSTR_ALIGN_FAULT),
+ PANFROST_EXCEPTION(DATA_INVALID_FAULT),
+ PANFROST_EXCEPTION(TILE_RANGE_FAULT),
+ PANFROST_EXCEPTION(ADDR_RANGE_FAULT),
+ PANFROST_EXCEPTION(IMPRECISE_FAULT),
+ PANFROST_EXCEPTION(OOM),
+ PANFROST_EXCEPTION(OOM_AFBC),
+ PANFROST_EXCEPTION(UNKNOWN),
+ PANFROST_EXCEPTION(DELAYED_BUS_FAULT),
+ PANFROST_EXCEPTION(GPU_SHAREABILITY_FAULT),
+ PANFROST_EXCEPTION(SYS_SHAREABILITY_FAULT),
+ PANFROST_EXCEPTION(GPU_CACHEABILITY_FAULT),
+ PANFROST_EXCEPTION(TRANSLATION_FAULT_0),
+ PANFROST_EXCEPTION(TRANSLATION_FAULT_1),
+ PANFROST_EXCEPTION(TRANSLATION_FAULT_2),
+ PANFROST_EXCEPTION(TRANSLATION_FAULT_3),
+ PANFROST_EXCEPTION(TRANSLATION_FAULT_4),
+ PANFROST_EXCEPTION(TRANSLATION_FAULT_IDENTITY),
+ PANFROST_EXCEPTION(PERM_FAULT_0),
+ PANFROST_EXCEPTION(PERM_FAULT_1),
+ PANFROST_EXCEPTION(PERM_FAULT_2),
+ PANFROST_EXCEPTION(PERM_FAULT_3),
+ PANFROST_EXCEPTION(TRANSTAB_BUS_FAULT_0),
+ PANFROST_EXCEPTION(TRANSTAB_BUS_FAULT_1),
+ PANFROST_EXCEPTION(TRANSTAB_BUS_FAULT_2),
+ PANFROST_EXCEPTION(TRANSTAB_BUS_FAULT_3),
+ PANFROST_EXCEPTION(ACCESS_FLAG_0),
+ PANFROST_EXCEPTION(ACCESS_FLAG_1),
+ PANFROST_EXCEPTION(ACCESS_FLAG_2),
+ PANFROST_EXCEPTION(ACCESS_FLAG_3),
+ PANFROST_EXCEPTION(ADDR_SIZE_FAULT_IN0),
+ PANFROST_EXCEPTION(ADDR_SIZE_FAULT_IN1),
+ PANFROST_EXCEPTION(ADDR_SIZE_FAULT_IN2),
+ PANFROST_EXCEPTION(ADDR_SIZE_FAULT_IN3),
+ PANFROST_EXCEPTION(ADDR_SIZE_FAULT_OUT0),
+ PANFROST_EXCEPTION(ADDR_SIZE_FAULT_OUT1),
+ PANFROST_EXCEPTION(ADDR_SIZE_FAULT_OUT2),
+ PANFROST_EXCEPTION(ADDR_SIZE_FAULT_OUT3),
+ PANFROST_EXCEPTION(MEM_ATTR_FAULT_0),
+ PANFROST_EXCEPTION(MEM_ATTR_FAULT_1),
+ PANFROST_EXCEPTION(MEM_ATTR_FAULT_2),
+ PANFROST_EXCEPTION(MEM_ATTR_FAULT_3),
+ PANFROST_EXCEPTION(MEM_ATTR_NONCACHE_0),
+ PANFROST_EXCEPTION(MEM_ATTR_NONCACHE_1),
+ PANFROST_EXCEPTION(MEM_ATTR_NONCACHE_2),
+ PANFROST_EXCEPTION(MEM_ATTR_NONCACHE_3),
+};
+
+const char *panfrost_exception_name(u32 exception_code)
+{
+ if (WARN_ON(exception_code >= ARRAY_SIZE(panfrost_exception_infos) ||
+ !panfrost_exception_infos[exception_code].name))
+ return "Unknown exception type";
+
+ return panfrost_exception_infos[exception_code].name;
+}
+
+bool panfrost_exception_needs_reset(const struct panfrost_device *pfdev,
+ u32 exception_code)
+{
+ /* Right now, none of the GPU we support need a reset, but this
+ * might change.
+ */
+ return false;
}
void panfrost_device_reset(struct panfrost_device *pfdev)
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
index f614e98771e4..8b25278f34c8 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
@@ -97,11 +97,12 @@ struct panfrost_device {
spinlock_t as_lock;
unsigned long as_in_use_mask;
unsigned long as_alloc_mask;
+ unsigned long as_faulty_mask;
struct list_head as_lru_list;
struct panfrost_job_slot *js;
- struct panfrost_job *jobs[NUM_JOB_SLOTS];
+ struct panfrost_job *jobs[NUM_JOB_SLOTS][2];
struct list_head scheduled_jobs;
struct panfrost_perfcnt *perfcnt;
@@ -109,6 +110,7 @@ struct panfrost_device {
struct mutex sched_lock;
struct {
+ struct workqueue_struct *wq;
struct work_struct work;
atomic_t pending;
} reset;
@@ -121,8 +123,12 @@ struct panfrost_device {
};
struct panfrost_mmu {
+ struct panfrost_device *pfdev;
+ struct kref refcount;
struct io_pgtable_cfg pgtbl_cfg;
struct io_pgtable_ops *pgtbl_ops;
+ struct drm_mm mm;
+ spinlock_t mm_lock;
int as;
atomic_t as_count;
struct list_head list;
@@ -133,9 +139,7 @@ struct panfrost_file_priv {
struct drm_sched_entity sched_entity[NUM_JOB_SLOTS];
- struct panfrost_mmu mmu;
- struct drm_mm mm;
- spinlock_t mm_lock;
+ struct panfrost_mmu *mmu;
};
static inline struct panfrost_device *to_panfrost_device(struct drm_device *ddev)
@@ -171,6 +175,91 @@ void panfrost_device_reset(struct panfrost_device *pfdev);
int panfrost_device_resume(struct device *dev);
int panfrost_device_suspend(struct device *dev);
-const char *panfrost_exception_name(struct panfrost_device *pfdev, u32 exception_code);
+enum drm_panfrost_exception_type {
+ DRM_PANFROST_EXCEPTION_OK = 0x00,
+ DRM_PANFROST_EXCEPTION_DONE = 0x01,
+ DRM_PANFROST_EXCEPTION_INTERRUPTED = 0x02,
+ DRM_PANFROST_EXCEPTION_STOPPED = 0x03,
+ DRM_PANFROST_EXCEPTION_TERMINATED = 0x04,
+ DRM_PANFROST_EXCEPTION_KABOOM = 0x05,
+ DRM_PANFROST_EXCEPTION_EUREKA = 0x06,
+ DRM_PANFROST_EXCEPTION_ACTIVE = 0x08,
+ DRM_PANFROST_EXCEPTION_MAX_NON_FAULT = 0x3f,
+ DRM_PANFROST_EXCEPTION_JOB_CONFIG_FAULT = 0x40,
+ DRM_PANFROST_EXCEPTION_JOB_POWER_FAULT = 0x41,
+ DRM_PANFROST_EXCEPTION_JOB_READ_FAULT = 0x42,
+ DRM_PANFROST_EXCEPTION_JOB_WRITE_FAULT = 0x43,
+ DRM_PANFROST_EXCEPTION_JOB_AFFINITY_FAULT = 0x44,
+ DRM_PANFROST_EXCEPTION_JOB_BUS_FAULT = 0x48,
+ DRM_PANFROST_EXCEPTION_INSTR_INVALID_PC = 0x50,
+ DRM_PANFROST_EXCEPTION_INSTR_INVALID_ENC = 0x51,
+ DRM_PANFROST_EXCEPTION_INSTR_TYPE_MISMATCH = 0x52,
+ DRM_PANFROST_EXCEPTION_INSTR_OPERAND_FAULT = 0x53,
+ DRM_PANFROST_EXCEPTION_INSTR_TLS_FAULT = 0x54,
+ DRM_PANFROST_EXCEPTION_INSTR_BARRIER_FAULT = 0x55,
+ DRM_PANFROST_EXCEPTION_INSTR_ALIGN_FAULT = 0x56,
+ DRM_PANFROST_EXCEPTION_DATA_INVALID_FAULT = 0x58,
+ DRM_PANFROST_EXCEPTION_TILE_RANGE_FAULT = 0x59,
+ DRM_PANFROST_EXCEPTION_ADDR_RANGE_FAULT = 0x5a,
+ DRM_PANFROST_EXCEPTION_IMPRECISE_FAULT = 0x5b,
+ DRM_PANFROST_EXCEPTION_OOM = 0x60,
+ DRM_PANFROST_EXCEPTION_OOM_AFBC = 0x61,
+ DRM_PANFROST_EXCEPTION_UNKNOWN = 0x7f,
+ DRM_PANFROST_EXCEPTION_DELAYED_BUS_FAULT = 0x80,
+ DRM_PANFROST_EXCEPTION_GPU_SHAREABILITY_FAULT = 0x88,
+ DRM_PANFROST_EXCEPTION_SYS_SHAREABILITY_FAULT = 0x89,
+ DRM_PANFROST_EXCEPTION_GPU_CACHEABILITY_FAULT = 0x8a,
+ DRM_PANFROST_EXCEPTION_TRANSLATION_FAULT_0 = 0xc0,
+ DRM_PANFROST_EXCEPTION_TRANSLATION_FAULT_1 = 0xc1,
+ DRM_PANFROST_EXCEPTION_TRANSLATION_FAULT_2 = 0xc2,
+ DRM_PANFROST_EXCEPTION_TRANSLATION_FAULT_3 = 0xc3,
+ DRM_PANFROST_EXCEPTION_TRANSLATION_FAULT_4 = 0xc4,
+ DRM_PANFROST_EXCEPTION_TRANSLATION_FAULT_IDENTITY = 0xc7,
+ DRM_PANFROST_EXCEPTION_PERM_FAULT_0 = 0xc8,
+ DRM_PANFROST_EXCEPTION_PERM_FAULT_1 = 0xc9,
+ DRM_PANFROST_EXCEPTION_PERM_FAULT_2 = 0xca,
+ DRM_PANFROST_EXCEPTION_PERM_FAULT_3 = 0xcb,
+ DRM_PANFROST_EXCEPTION_TRANSTAB_BUS_FAULT_0 = 0xd0,
+ DRM_PANFROST_EXCEPTION_TRANSTAB_BUS_FAULT_1 = 0xd1,
+ DRM_PANFROST_EXCEPTION_TRANSTAB_BUS_FAULT_2 = 0xd2,
+ DRM_PANFROST_EXCEPTION_TRANSTAB_BUS_FAULT_3 = 0xd3,
+ DRM_PANFROST_EXCEPTION_ACCESS_FLAG_0 = 0xd8,
+ DRM_PANFROST_EXCEPTION_ACCESS_FLAG_1 = 0xd9,
+ DRM_PANFROST_EXCEPTION_ACCESS_FLAG_2 = 0xda,
+ DRM_PANFROST_EXCEPTION_ACCESS_FLAG_3 = 0xdb,
+ DRM_PANFROST_EXCEPTION_ADDR_SIZE_FAULT_IN0 = 0xe0,
+ DRM_PANFROST_EXCEPTION_ADDR_SIZE_FAULT_IN1 = 0xe1,
+ DRM_PANFROST_EXCEPTION_ADDR_SIZE_FAULT_IN2 = 0xe2,
+ DRM_PANFROST_EXCEPTION_ADDR_SIZE_FAULT_IN3 = 0xe3,
+ DRM_PANFROST_EXCEPTION_ADDR_SIZE_FAULT_OUT0 = 0xe4,
+ DRM_PANFROST_EXCEPTION_ADDR_SIZE_FAULT_OUT1 = 0xe5,
+ DRM_PANFROST_EXCEPTION_ADDR_SIZE_FAULT_OUT2 = 0xe6,
+ DRM_PANFROST_EXCEPTION_ADDR_SIZE_FAULT_OUT3 = 0xe7,
+ DRM_PANFROST_EXCEPTION_MEM_ATTR_FAULT_0 = 0xe8,
+ DRM_PANFROST_EXCEPTION_MEM_ATTR_FAULT_1 = 0xe9,
+ DRM_PANFROST_EXCEPTION_MEM_ATTR_FAULT_2 = 0xea,
+ DRM_PANFROST_EXCEPTION_MEM_ATTR_FAULT_3 = 0xeb,
+ DRM_PANFROST_EXCEPTION_MEM_ATTR_NONCACHE_0 = 0xec,
+ DRM_PANFROST_EXCEPTION_MEM_ATTR_NONCACHE_1 = 0xed,
+ DRM_PANFROST_EXCEPTION_MEM_ATTR_NONCACHE_2 = 0xee,
+ DRM_PANFROST_EXCEPTION_MEM_ATTR_NONCACHE_3 = 0xef,
+};
+
+static inline bool
+panfrost_exception_is_fault(u32 exception_code)
+{
+ return exception_code > DRM_PANFROST_EXCEPTION_MAX_NON_FAULT;
+}
+
+const char *panfrost_exception_name(u32 exception_code);
+bool panfrost_exception_needs_reset(const struct panfrost_device *pfdev,
+ u32 exception_code);
+
+static inline void
+panfrost_device_schedule_reset(struct panfrost_device *pfdev)
+{
+ atomic_set(&pfdev->reset.pending, 1);
+ queue_work(pfdev->reset.wq, &pfdev->reset.work);
+}
#endif
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 075ec0ef746c..1ffaef5ec5ff 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -138,12 +138,6 @@ panfrost_lookup_bos(struct drm_device *dev,
if (!job->bo_count)
return 0;
- job->implicit_fences = kvmalloc_array(job->bo_count,
- sizeof(struct dma_fence *),
- GFP_KERNEL | __GFP_ZERO);
- if (!job->implicit_fences)
- return -ENOMEM;
-
ret = drm_gem_objects_lookup(file_priv,
(void __user *)(uintptr_t)args->bo_handles,
job->bo_count, &job->bos);
@@ -174,7 +168,7 @@ panfrost_lookup_bos(struct drm_device *dev,
}
/**
- * panfrost_copy_in_sync() - Sets up job->in_fences[] with the sync objects
+ * panfrost_copy_in_sync() - Sets up job->deps with the sync objects
* referenced by the job.
* @dev: DRM device
* @file_priv: DRM file for this fd
@@ -194,22 +188,14 @@ panfrost_copy_in_sync(struct drm_device *dev,
{
u32 *handles;
int ret = 0;
- int i;
+ int i, in_fence_count;
- job->in_fence_count = args->in_sync_count;
+ in_fence_count = args->in_sync_count;
- if (!job->in_fence_count)
+ if (!in_fence_count)
return 0;
- job->in_fences = kvmalloc_array(job->in_fence_count,
- sizeof(struct dma_fence *),
- GFP_KERNEL | __GFP_ZERO);
- if (!job->in_fences) {
- DRM_DEBUG("Failed to allocate job in fences\n");
- return -ENOMEM;
- }
-
- handles = kvmalloc_array(job->in_fence_count, sizeof(u32), GFP_KERNEL);
+ handles = kvmalloc_array(in_fence_count, sizeof(u32), GFP_KERNEL);
if (!handles) {
ret = -ENOMEM;
DRM_DEBUG("Failed to allocate incoming syncobj handles\n");
@@ -218,16 +204,23 @@ panfrost_copy_in_sync(struct drm_device *dev,
if (copy_from_user(handles,
(void __user *)(uintptr_t)args->in_syncs,
- job->in_fence_count * sizeof(u32))) {
+ in_fence_count * sizeof(u32))) {
ret = -EFAULT;
DRM_DEBUG("Failed to copy in syncobj handles\n");
goto fail;
}
- for (i = 0; i < job->in_fence_count; i++) {
+ for (i = 0; i < in_fence_count; i++) {
+ struct dma_fence *fence;
+
ret = drm_syncobj_find_fence(file_priv, handles[i], 0, 0,
- &job->in_fences[i]);
- if (ret == -EINVAL)
+ &fence);
+ if (ret)
+ goto fail;
+
+ ret = drm_gem_fence_array_add(&job->deps, fence);
+
+ if (ret)
goto fail;
}
@@ -265,6 +258,8 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data,
kref_init(&job->refcount);
+ xa_init_flags(&job->deps, XA_FLAGS_ALLOC);
+
job->pfdev = pfdev;
job->jc = args->jc;
job->requirements = args->requirements;
@@ -417,7 +412,7 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
* anyway, so let's not bother.
*/
if (!list_is_singular(&bo->mappings.list) ||
- WARN_ON_ONCE(first->mmu != &priv->mmu)) {
+ WARN_ON_ONCE(first->mmu != priv->mmu)) {
ret = -EINVAL;
goto out_unlock_mappings;
}
@@ -449,32 +444,6 @@ int panfrost_unstable_ioctl_check(void)
return 0;
}
-#define PFN_4G (SZ_4G >> PAGE_SHIFT)
-#define PFN_4G_MASK (PFN_4G - 1)
-#define PFN_16M (SZ_16M >> PAGE_SHIFT)
-
-static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node,
- unsigned long color,
- u64 *start, u64 *end)
-{
- /* Executable buffers can't start or end on a 4GB boundary */
- if (!(color & PANFROST_BO_NOEXEC)) {
- u64 next_seg;
-
- if ((*start & PFN_4G_MASK) == 0)
- (*start)++;
-
- if ((*end & PFN_4G_MASK) == 0)
- (*end)--;
-
- next_seg = ALIGN(*start, PFN_4G);
- if (next_seg - *start <= PFN_16M)
- *start = next_seg + 1;
-
- *end = min(*end, ALIGN(*start, PFN_4G) - 1);
- }
-}
-
static int
panfrost_open(struct drm_device *dev, struct drm_file *file)
{
@@ -489,15 +458,11 @@ panfrost_open(struct drm_device *dev, struct drm_file *file)
panfrost_priv->pfdev = pfdev;
file->driver_priv = panfrost_priv;
- spin_lock_init(&panfrost_priv->mm_lock);
-
- /* 4G enough for now. can be 48-bit */
- drm_mm_init(&panfrost_priv->mm, SZ_32M >> PAGE_SHIFT, (SZ_4G - SZ_32M) >> PAGE_SHIFT);
- panfrost_priv->mm.color_adjust = panfrost_drm_mm_color_adjust;
-
- ret = panfrost_mmu_pgtable_alloc(panfrost_priv);
- if (ret)
- goto err_pgtable;
+ panfrost_priv->mmu = panfrost_mmu_ctx_create(pfdev);
+ if (IS_ERR(panfrost_priv->mmu)) {
+ ret = PTR_ERR(panfrost_priv->mmu);
+ goto err_free;
+ }
ret = panfrost_job_open(panfrost_priv);
if (ret)
@@ -506,9 +471,8 @@ panfrost_open(struct drm_device *dev, struct drm_file *file)
return 0;
err_job:
- panfrost_mmu_pgtable_free(panfrost_priv);
-err_pgtable:
- drm_mm_takedown(&panfrost_priv->mm);
+ panfrost_mmu_ctx_put(panfrost_priv->mmu);
+err_free:
kfree(panfrost_priv);
return ret;
}
@@ -521,8 +485,7 @@ panfrost_postclose(struct drm_device *dev, struct drm_file *file)
panfrost_perfcnt_close(file);
panfrost_job_close(panfrost_priv);
- panfrost_mmu_pgtable_free(panfrost_priv);
- drm_mm_takedown(&panfrost_priv->mm);
+ panfrost_mmu_ctx_put(panfrost_priv->mmu);
kfree(panfrost_priv);
}
diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c
index 3e0723bc36bd..23377481f4e3 100644
--- a/drivers/gpu/drm/panfrost/panfrost_gem.c
+++ b/drivers/gpu/drm/panfrost/panfrost_gem.c
@@ -60,7 +60,7 @@ panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
mutex_lock(&bo->mappings.lock);
list_for_each_entry(iter, &bo->mappings.list, node) {
- if (iter->mmu == &priv->mmu) {
+ if (iter->mmu == priv->mmu) {
kref_get(&iter->refcount);
mapping = iter;
break;
@@ -74,16 +74,13 @@ panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
static void
panfrost_gem_teardown_mapping(struct panfrost_gem_mapping *mapping)
{
- struct panfrost_file_priv *priv;
-
if (mapping->active)
panfrost_mmu_unmap(mapping);
- priv = container_of(mapping->mmu, struct panfrost_file_priv, mmu);
- spin_lock(&priv->mm_lock);
+ spin_lock(&mapping->mmu->mm_lock);
if (drm_mm_node_allocated(&mapping->mmnode))
drm_mm_remove_node(&mapping->mmnode);
- spin_unlock(&priv->mm_lock);
+ spin_unlock(&mapping->mmu->mm_lock);
}
static void panfrost_gem_mapping_release(struct kref *kref)
@@ -94,6 +91,7 @@ static void panfrost_gem_mapping_release(struct kref *kref)
panfrost_gem_teardown_mapping(mapping);
drm_gem_object_put(&mapping->obj->base.base);
+ panfrost_mmu_ctx_put(mapping->mmu);
kfree(mapping);
}
@@ -143,11 +141,11 @@ int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
else
align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0;
- mapping->mmu = &priv->mmu;
- spin_lock(&priv->mm_lock);
- ret = drm_mm_insert_node_generic(&priv->mm, &mapping->mmnode,
+ mapping->mmu = panfrost_mmu_ctx_get(priv->mmu);
+ spin_lock(&mapping->mmu->mm_lock);
+ ret = drm_mm_insert_node_generic(&mapping->mmu->mm, &mapping->mmnode,
size >> PAGE_SHIFT, align, color, 0);
- spin_unlock(&priv->mm_lock);
+ spin_unlock(&mapping->mmu->mm_lock);
if (ret)
goto err;
@@ -176,7 +174,7 @@ void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
mutex_lock(&bo->mappings.lock);
list_for_each_entry(iter, &bo->mappings.list, node) {
- if (iter->mmu == &priv->mmu) {
+ if (iter->mmu == priv->mmu) {
mapping = iter;
list_del(&iter->node);
break;
diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c
index 0e70e27fd8c3..bbe628b306ee 100644
--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c
@@ -33,7 +33,7 @@ static irqreturn_t panfrost_gpu_irq_handler(int irq, void *data)
address |= gpu_read(pfdev, GPU_FAULT_ADDRESS_LO);
dev_warn(pfdev->dev, "GPU Fault 0x%08x (%s) at 0x%016llx\n",
- fault_status & 0xFF, panfrost_exception_name(pfdev, fault_status),
+ fault_status, panfrost_exception_name(fault_status & 0xFF),
address);
if (state & GPU_IRQ_MULTIPLE_FAULT)
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
index 2df3e999a38d..71a72fb50e6b 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.c
+++ b/drivers/gpu/drm/panfrost/panfrost_job.c
@@ -4,6 +4,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/dma-resv.h>
@@ -25,17 +26,8 @@
#define job_write(dev, reg, data) writel(data, dev->iomem + (reg))
#define job_read(dev, reg) readl(dev->iomem + (reg))
-enum panfrost_queue_status {
- PANFROST_QUEUE_STATUS_ACTIVE,
- PANFROST_QUEUE_STATUS_STOPPED,
- PANFROST_QUEUE_STATUS_STARTING,
- PANFROST_QUEUE_STATUS_FAULT_PENDING,
-};
-
struct panfrost_queue_state {
struct drm_gpu_scheduler sched;
- atomic_t status;
- struct mutex lock;
u64 fence_context;
u64 emit_seqno;
};
@@ -43,6 +35,7 @@ struct panfrost_queue_state {
struct panfrost_job_slot {
struct panfrost_queue_state queue[NUM_JOB_SLOTS];
spinlock_t job_lock;
+ int irq;
};
static struct panfrost_job *
@@ -148,9 +141,52 @@ static void panfrost_job_write_affinity(struct panfrost_device *pfdev,
job_write(pfdev, JS_AFFINITY_NEXT_HI(js), affinity >> 32);
}
+static u32
+panfrost_get_job_chain_flag(const struct panfrost_job *job)
+{
+ struct panfrost_fence *f = to_panfrost_fence(job->done_fence);
+
+ if (!panfrost_has_hw_feature(job->pfdev, HW_FEATURE_JOBCHAIN_DISAMBIGUATION))
+ return 0;
+
+ return (f->seqno & 1) ? JS_CONFIG_JOB_CHAIN_FLAG : 0;
+}
+
+static struct panfrost_job *
+panfrost_dequeue_job(struct panfrost_device *pfdev, int slot)
+{
+ struct panfrost_job *job = pfdev->jobs[slot][0];
+
+ WARN_ON(!job);
+ pfdev->jobs[slot][0] = pfdev->jobs[slot][1];
+ pfdev->jobs[slot][1] = NULL;
+
+ return job;
+}
+
+static unsigned int
+panfrost_enqueue_job(struct panfrost_device *pfdev, int slot,
+ struct panfrost_job *job)
+{
+ if (WARN_ON(!job))
+ return 0;
+
+ if (!pfdev->jobs[slot][0]) {
+ pfdev->jobs[slot][0] = job;
+ return 0;
+ }
+
+ WARN_ON(pfdev->jobs[slot][1]);
+ pfdev->jobs[slot][1] = job;
+ WARN_ON(panfrost_get_job_chain_flag(job) ==
+ panfrost_get_job_chain_flag(pfdev->jobs[slot][0]));
+ return 1;
+}
+
static void panfrost_job_hw_submit(struct panfrost_job *job, int js)
{
struct panfrost_device *pfdev = job->pfdev;
+ unsigned int subslot;
u32 cfg;
u64 jc_head = job->jc;
int ret;
@@ -165,7 +201,7 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js)
return;
}
- cfg = panfrost_mmu_as_get(pfdev, &job->file_priv->mmu);
+ cfg = panfrost_mmu_as_get(pfdev, job->file_priv->mmu);
job_write(pfdev, JS_HEAD_NEXT_LO(js), jc_head & 0xFFFFFFFF);
job_write(pfdev, JS_HEAD_NEXT_HI(js), jc_head >> 32);
@@ -176,7 +212,8 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js)
* start */
cfg |= JS_CONFIG_THREAD_PRI(8) |
JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE |
- JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE;
+ JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE |
+ panfrost_get_job_chain_flag(job);
if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION))
cfg |= JS_CONFIG_ENABLE_FLUSH_REDUCTION;
@@ -190,20 +227,33 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js)
job_write(pfdev, JS_FLUSH_ID_NEXT(js), job->flush_id);
/* GO ! */
- dev_dbg(pfdev->dev, "JS: Submitting atom %p to js[%d] with head=0x%llx",
- job, js, jc_head);
- job_write(pfdev, JS_COMMAND_NEXT(js), JS_COMMAND_START);
+ spin_lock(&pfdev->js->job_lock);
+ subslot = panfrost_enqueue_job(pfdev, js, job);
+ /* Don't queue the job if a reset is in progress */
+ if (!atomic_read(&pfdev->reset.pending)) {
+ job_write(pfdev, JS_COMMAND_NEXT(js), JS_COMMAND_START);
+ dev_dbg(pfdev->dev,
+ "JS: Submitting atom %p to js[%d][%d] with head=0x%llx AS %d",
+ job, js, subslot, jc_head, cfg & 0xf);
+ }
+ spin_unlock(&pfdev->js->job_lock);
}
-static void panfrost_acquire_object_fences(struct drm_gem_object **bos,
- int bo_count,
- struct dma_fence **implicit_fences)
+static int panfrost_acquire_object_fences(struct drm_gem_object **bos,
+ int bo_count,
+ struct xarray *deps)
{
- int i;
+ int i, ret;
- for (i = 0; i < bo_count; i++)
- implicit_fences[i] = dma_resv_get_excl_unlocked(bos[i]->resv);
+ for (i = 0; i < bo_count; i++) {
+ /* panfrost always uses write mode in its current uapi */
+ ret = drm_gem_fence_array_add_implicit(deps, bos[i], true);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static void panfrost_attach_object_fences(struct drm_gem_object **bos,
@@ -224,14 +274,13 @@ int panfrost_job_push(struct panfrost_job *job)
struct ww_acquire_ctx acquire_ctx;
int ret = 0;
- mutex_lock(&pfdev->sched_lock);
ret = drm_gem_lock_reservations(job->bos, job->bo_count,
&acquire_ctx);
- if (ret) {
- mutex_unlock(&pfdev->sched_lock);
+ if (ret)
return ret;
- }
+
+ mutex_lock(&pfdev->sched_lock);
ret = drm_sched_job_init(&job->base, entity, NULL);
if (ret) {
@@ -241,10 +290,14 @@ int panfrost_job_push(struct panfrost_job *job)
job->render_done_fence = dma_fence_get(&job->base.s_fence->finished);
- kref_get(&job->refcount); /* put by scheduler job completion */
+ ret = panfrost_acquire_object_fences(job->bos, job->bo_count,
+ &job->deps);
+ if (ret) {
+ mutex_unlock(&pfdev->sched_lock);
+ goto unlock;
+ }
- panfrost_acquire_object_fences(job->bos, job->bo_count,
- job->implicit_fences);
+ kref_get(&job->refcount); /* put by scheduler job completion */
drm_sched_entity_push_job(&job->base, entity);
@@ -263,18 +316,15 @@ static void panfrost_job_cleanup(struct kref *ref)
{
struct panfrost_job *job = container_of(ref, struct panfrost_job,
refcount);
+ struct dma_fence *fence;
+ unsigned long index;
unsigned int i;
- if (job->in_fences) {
- for (i = 0; i < job->in_fence_count; i++)
- dma_fence_put(job->in_fences[i]);
- kvfree(job->in_fences);
- }
- if (job->implicit_fences) {
- for (i = 0; i < job->bo_count; i++)
- dma_fence_put(job->implicit_fences[i]);
- kvfree(job->implicit_fences);
+ xa_for_each(&job->deps, index, fence) {
+ dma_fence_put(fence);
}
+ xa_destroy(&job->deps);
+
dma_fence_put(job->done_fence);
dma_fence_put(job->render_done_fence);
@@ -317,26 +367,9 @@ static struct dma_fence *panfrost_job_dependency(struct drm_sched_job *sched_job
struct drm_sched_entity *s_entity)
{
struct panfrost_job *job = to_panfrost_job(sched_job);
- struct dma_fence *fence;
- unsigned int i;
- /* Explicit fences */
- for (i = 0; i < job->in_fence_count; i++) {
- if (job->in_fences[i]) {
- fence = job->in_fences[i];
- job->in_fences[i] = NULL;
- return fence;
- }
- }
-
- /* Implicit fences, max. one per BO */
- for (i = 0; i < job->bo_count; i++) {
- if (job->implicit_fences[i]) {
- fence = job->implicit_fences[i];
- job->implicit_fences[i] = NULL;
- return fence;
- }
- }
+ if (!xa_empty(&job->deps))
+ return xa_erase(&job->deps, job->last_dep++);
return NULL;
}
@@ -351,11 +384,15 @@ static struct dma_fence *panfrost_job_run(struct drm_sched_job *sched_job)
if (unlikely(job->base.s_fence->finished.error))
return NULL;
- pfdev->jobs[slot] = job;
+ /* Nothing to execute: can happen if the job has finished while
+ * we were resetting the GPU.
+ */
+ if (!job->jc)
+ return NULL;
fence = panfrost_fence_create(pfdev, slot);
if (IS_ERR(fence))
- return NULL;
+ return fence;
if (job->done_fence)
dma_fence_put(job->done_fence);
@@ -379,57 +416,314 @@ void panfrost_job_enable_interrupts(struct panfrost_device *pfdev)
job_write(pfdev, JOB_INT_MASK, irq_mask);
}
-static bool panfrost_scheduler_stop(struct panfrost_queue_state *queue,
- struct drm_sched_job *bad)
+static void panfrost_job_handle_err(struct panfrost_device *pfdev,
+ struct panfrost_job *job,
+ unsigned int js)
{
- enum panfrost_queue_status old_status;
- bool stopped = false;
+ u32 js_status = job_read(pfdev, JS_STATUS(js));
+ const char *exception_name = panfrost_exception_name(js_status);
+ bool signal_fence = true;
+
+ if (!panfrost_exception_is_fault(js_status)) {
+ dev_dbg(pfdev->dev, "js event, js=%d, status=%s, head=0x%x, tail=0x%x",
+ js, exception_name,
+ job_read(pfdev, JS_HEAD_LO(js)),
+ job_read(pfdev, JS_TAIL_LO(js)));
+ } else {
+ dev_err(pfdev->dev, "js fault, js=%d, status=%s, head=0x%x, tail=0x%x",
+ js, exception_name,
+ job_read(pfdev, JS_HEAD_LO(js)),
+ job_read(pfdev, JS_TAIL_LO(js)));
+ }
- mutex_lock(&queue->lock);
- old_status = atomic_xchg(&queue->status,
- PANFROST_QUEUE_STATUS_STOPPED);
- if (old_status == PANFROST_QUEUE_STATUS_STOPPED)
- goto out;
+ if (js_status == DRM_PANFROST_EXCEPTION_STOPPED) {
+ /* Update the job head so we can resume */
+ job->jc = job_read(pfdev, JS_TAIL_LO(js)) |
+ ((u64)job_read(pfdev, JS_TAIL_HI(js)) << 32);
+
+ /* The job will be resumed, don't signal the fence */
+ signal_fence = false;
+ } else if (js_status == DRM_PANFROST_EXCEPTION_TERMINATED) {
+ /* Job has been hard-stopped, flag it as canceled */
+ dma_fence_set_error(job->done_fence, -ECANCELED);
+ job->jc = 0;
+ } else if (panfrost_exception_is_fault(js_status)) {
+ /* We might want to provide finer-grained error code based on
+ * the exception type, but unconditionally setting to EINVAL
+ * is good enough for now.
+ */
+ dma_fence_set_error(job->done_fence, -EINVAL);
+ job->jc = 0;
+ }
- WARN_ON(old_status != PANFROST_QUEUE_STATUS_ACTIVE);
- drm_sched_stop(&queue->sched, bad);
- if (bad)
- drm_sched_increase_karma(bad);
+ panfrost_mmu_as_put(pfdev, job->file_priv->mmu);
+ panfrost_devfreq_record_idle(&pfdev->pfdevfreq);
- stopped = true;
+ if (signal_fence)
+ dma_fence_signal_locked(job->done_fence);
- /*
- * Set the timeout to max so the timer doesn't get started
- * when we return from the timeout handler (restored in
- * panfrost_scheduler_start()).
+ pm_runtime_put_autosuspend(pfdev->dev);
+
+ if (panfrost_exception_needs_reset(pfdev, js_status)) {
+ atomic_set(&pfdev->reset.pending, 1);
+ drm_sched_fault(&pfdev->js->queue[js].sched);
+ }
+}
+
+static void panfrost_job_handle_done(struct panfrost_device *pfdev,
+ struct panfrost_job *job)
+{
+ /* Set ->jc to 0 to avoid re-submitting an already finished job (can
+ * happen when we receive the DONE interrupt while doing a GPU reset).
+ */
+ job->jc = 0;
+ panfrost_mmu_as_put(pfdev, job->file_priv->mmu);
+ panfrost_devfreq_record_idle(&pfdev->pfdevfreq);
+
+ dma_fence_signal_locked(job->done_fence);
+ pm_runtime_put_autosuspend(pfdev->dev);
+}
+
+static void panfrost_job_handle_irq(struct panfrost_device *pfdev, u32 status)
+{
+ struct panfrost_job *done[NUM_JOB_SLOTS][2] = {};
+ struct panfrost_job *failed[NUM_JOB_SLOTS] = {};
+ u32 js_state = 0, js_events = 0;
+ unsigned int i, j;
+
+ /* First we collect all failed/done jobs. */
+ while (status) {
+ u32 js_state_mask = 0;
+
+ for (j = 0; j < NUM_JOB_SLOTS; j++) {
+ if (status & MK_JS_MASK(j))
+ js_state_mask |= MK_JS_MASK(j);
+
+ if (status & JOB_INT_MASK_DONE(j)) {
+ if (done[j][0])
+ done[j][1] = panfrost_dequeue_job(pfdev, j);
+ else
+ done[j][0] = panfrost_dequeue_job(pfdev, j);
+ }
+
+ if (status & JOB_INT_MASK_ERR(j)) {
+ /* Cancel the next submission. Will be submitted
+ * after we're done handling this failure if
+ * there's no reset pending.
+ */
+ job_write(pfdev, JS_COMMAND_NEXT(j), JS_COMMAND_NOP);
+ failed[j] = panfrost_dequeue_job(pfdev, j);
+ }
+ }
+
+ /* JS_STATE is sampled when JOB_INT_CLEAR is written.
+ * For each BIT(slot) or BIT(slot + 16) bit written to
+ * JOB_INT_CLEAR, the corresponding bits in JS_STATE
+ * (BIT(slot) and BIT(slot + 16)) are updated, but this
+ * is racy. If we only have one job done at the time we
+ * read JOB_INT_RAWSTAT but the second job fails before we
+ * clear the status, we end up with a status containing
+ * only the DONE bit and consider both jobs as DONE since
+ * JS_STATE reports both NEXT and CURRENT as inactive.
+ * To prevent that, let's repeat this clear+read steps
+ * until status is 0.
+ */
+ job_write(pfdev, JOB_INT_CLEAR, status);
+ js_state &= ~js_state_mask;
+ js_state |= job_read(pfdev, JOB_INT_JS_STATE) & js_state_mask;
+ js_events |= status;
+ status = job_read(pfdev, JOB_INT_RAWSTAT);
+ }
+
+ /* Then we handle the dequeued jobs. */
+ for (j = 0; j < NUM_JOB_SLOTS; j++) {
+ if (!(js_events & MK_JS_MASK(j)))
+ continue;
+
+ if (failed[j]) {
+ panfrost_job_handle_err(pfdev, failed[j], j);
+ } else if (pfdev->jobs[j][0] && !(js_state & MK_JS_MASK(j))) {
+ /* When the current job doesn't fail, the JM dequeues
+ * the next job without waiting for an ACK, this means
+ * we can have 2 jobs dequeued and only catch the
+ * interrupt when the second one is done. If both slots
+ * are inactive, but one job remains in pfdev->jobs[j],
+ * consider it done. Of course that doesn't apply if a
+ * failure happened since we cancelled execution of the
+ * job in _NEXT (see above).
+ */
+ if (WARN_ON(!done[j][0]))
+ done[j][0] = panfrost_dequeue_job(pfdev, j);
+ else
+ done[j][1] = panfrost_dequeue_job(pfdev, j);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(done[0]) && done[j][i]; i++)
+ panfrost_job_handle_done(pfdev, done[j][i]);
+ }
+
+ /* And finally we requeue jobs that were waiting in the second slot
+ * and have been stopped if we detected a failure on the first slot.
*/
- queue->sched.timeout = MAX_SCHEDULE_TIMEOUT;
+ for (j = 0; j < NUM_JOB_SLOTS; j++) {
+ if (!(js_events & MK_JS_MASK(j)))
+ continue;
+
+ if (!failed[j] || !pfdev->jobs[j][0])
+ continue;
+
+ if (pfdev->jobs[j][0]->jc == 0) {
+ /* The job was cancelled, signal the fence now */
+ struct panfrost_job *canceled = panfrost_dequeue_job(pfdev, j);
+
+ dma_fence_set_error(canceled->done_fence, -ECANCELED);
+ panfrost_job_handle_done(pfdev, canceled);
+ } else if (!atomic_read(&pfdev->reset.pending)) {
+ /* Requeue the job we removed if no reset is pending */
+ job_write(pfdev, JS_COMMAND_NEXT(j), JS_COMMAND_START);
+ }
+ }
+}
-out:
- mutex_unlock(&queue->lock);
+static void panfrost_job_handle_irqs(struct panfrost_device *pfdev)
+{
+ u32 status = job_read(pfdev, JOB_INT_RAWSTAT);
+
+ while (status) {
+ pm_runtime_mark_last_busy(pfdev->dev);
- return stopped;
+ spin_lock(&pfdev->js->job_lock);
+ panfrost_job_handle_irq(pfdev, status);
+ spin_unlock(&pfdev->js->job_lock);
+ status = job_read(pfdev, JOB_INT_RAWSTAT);
+ }
}
-static void panfrost_scheduler_start(struct panfrost_queue_state *queue)
+static u32 panfrost_active_slots(struct panfrost_device *pfdev,
+ u32 *js_state_mask, u32 js_state)
{
- enum panfrost_queue_status old_status;
+ u32 rawstat;
- mutex_lock(&queue->lock);
- old_status = atomic_xchg(&queue->status,
- PANFROST_QUEUE_STATUS_STARTING);
- WARN_ON(old_status != PANFROST_QUEUE_STATUS_STOPPED);
+ if (!(js_state & *js_state_mask))
+ return 0;
- /* Restore the original timeout before starting the scheduler. */
- queue->sched.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS);
- drm_sched_resubmit_jobs(&queue->sched);
- drm_sched_start(&queue->sched, true);
- old_status = atomic_xchg(&queue->status,
- PANFROST_QUEUE_STATUS_ACTIVE);
- if (old_status == PANFROST_QUEUE_STATUS_FAULT_PENDING)
- drm_sched_fault(&queue->sched);
+ rawstat = job_read(pfdev, JOB_INT_RAWSTAT);
+ if (rawstat) {
+ unsigned int i;
+
+ for (i = 0; i < NUM_JOB_SLOTS; i++) {
+ if (rawstat & MK_JS_MASK(i))
+ *js_state_mask &= ~MK_JS_MASK(i);
+ }
+ }
- mutex_unlock(&queue->lock);
+ return js_state & *js_state_mask;
+}
+
+static void
+panfrost_reset(struct panfrost_device *pfdev,
+ struct drm_sched_job *bad)
+{
+ u32 js_state, js_state_mask = 0xffffffff;
+ unsigned int i, j;
+ bool cookie;
+ int ret;
+
+ if (!atomic_read(&pfdev->reset.pending))
+ return;
+
+ /* Stop the schedulers.
+ *
+ * FIXME: We temporarily get out of the dma_fence_signalling section
+ * because the cleanup path generate lockdep splats when taking locks
+ * to release job resources. We should rework the code to follow this
+ * pattern:
+ *
+ * try_lock
+ * if (locked)
+ * release
+ * else
+ * schedule_work_to_release_later
+ */
+ for (i = 0; i < NUM_JOB_SLOTS; i++)
+ drm_sched_stop(&pfdev->js->queue[i].sched, bad);
+
+ cookie = dma_fence_begin_signalling();
+
+ if (bad)
+ drm_sched_increase_karma(bad);
+
+ /* Mask job interrupts and synchronize to make sure we won't be
+ * interrupted during our reset.
+ */
+ job_write(pfdev, JOB_INT_MASK, 0);
+ synchronize_irq(pfdev->js->irq);
+
+ for (i = 0; i < NUM_JOB_SLOTS; i++) {
+ /* Cancel the next job and soft-stop the running job. */
+ job_write(pfdev, JS_COMMAND_NEXT(i), JS_COMMAND_NOP);
+ job_write(pfdev, JS_COMMAND(i), JS_COMMAND_SOFT_STOP);
+ }
+
+ /* Wait at most 10ms for soft-stops to complete */
+ ret = readl_poll_timeout(pfdev->iomem + JOB_INT_JS_STATE, js_state,
+ !panfrost_active_slots(pfdev, &js_state_mask, js_state),
+ 10, 10000);
+
+ if (ret)
+ dev_err(pfdev->dev, "Soft-stop failed\n");
+
+ /* Handle the remaining interrupts before we reset. */
+ panfrost_job_handle_irqs(pfdev);
+
+ /* Remaining interrupts have been handled, but we might still have
+ * stuck jobs. Let's make sure the PM counters stay balanced by
+ * manually calling pm_runtime_put_noidle() and
+ * panfrost_devfreq_record_idle() for each stuck job.
+ */
+ spin_lock(&pfdev->js->job_lock);
+ for (i = 0; i < NUM_JOB_SLOTS; i++) {
+ for (j = 0; j < ARRAY_SIZE(pfdev->jobs[0]) && pfdev->jobs[i][j]; j++) {
+ pm_runtime_put_noidle(pfdev->dev);
+ panfrost_devfreq_record_idle(&pfdev->pfdevfreq);
+ }
+ }
+ memset(pfdev->jobs, 0, sizeof(pfdev->jobs));
+ spin_unlock(&pfdev->js->job_lock);
+
+ /* Proceed with reset now. */
+ panfrost_device_reset(pfdev);
+
+ /* panfrost_device_reset() unmasks job interrupts, but we want to
+ * keep them masked a bit longer.
+ */
+ job_write(pfdev, JOB_INT_MASK, 0);
+
+ /* GPU has been reset, we can clear the reset pending bit. */
+ atomic_set(&pfdev->reset.pending, 0);
+
+ /* Now resubmit jobs that were previously queued but didn't have a
+ * chance to finish.
+ * FIXME: We temporarily get out of the DMA fence signalling section
+ * while resubmitting jobs because the job submission logic will
+ * allocate memory with the GFP_KERNEL flag which can trigger memory
+ * reclaim and exposes a lock ordering issue.
+ */
+ dma_fence_end_signalling(cookie);
+ for (i = 0; i < NUM_JOB_SLOTS; i++)
+ drm_sched_resubmit_jobs(&pfdev->js->queue[i].sched);
+ cookie = dma_fence_begin_signalling();
+
+ /* Restart the schedulers */
+ for (i = 0; i < NUM_JOB_SLOTS; i++)
+ drm_sched_start(&pfdev->js->queue[i].sched, true);
+
+ /* Re-enable job interrupts now that everything has been restarted. */
+ job_write(pfdev, JOB_INT_MASK,
+ GENMASK(16 + NUM_JOB_SLOTS - 1, 16) |
+ GENMASK(NUM_JOB_SLOTS - 1, 0));
+
+ dma_fence_end_signalling(cookie);
}
static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
@@ -454,17 +748,20 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
job_read(pfdev, JS_TAIL_LO(js)),
sched_job);
- /* Scheduler is already stopped, nothing to do. */
- if (!panfrost_scheduler_stop(&pfdev->js->queue[js], sched_job))
- return DRM_GPU_SCHED_STAT_NOMINAL;
-
- /* Schedule a reset if there's no reset in progress. */
- if (!atomic_xchg(&pfdev->reset.pending, 1))
- schedule_work(&pfdev->reset.work);
+ atomic_set(&pfdev->reset.pending, 1);
+ panfrost_reset(pfdev, sched_job);
return DRM_GPU_SCHED_STAT_NOMINAL;
}
+static void panfrost_reset_work(struct work_struct *work)
+{
+ struct panfrost_device *pfdev;
+
+ pfdev = container_of(work, struct panfrost_device, reset.work);
+ panfrost_reset(pfdev, NULL);
+}
+
static const struct drm_sched_backend_ops panfrost_sched_ops = {
.dependency = panfrost_job_dependency,
.run_job = panfrost_job_run,
@@ -472,161 +769,75 @@ static const struct drm_sched_backend_ops panfrost_sched_ops = {
.free_job = panfrost_job_free
};
-static irqreturn_t panfrost_job_irq_handler(int irq, void *data)
+static irqreturn_t panfrost_job_irq_handler_thread(int irq, void *data)
{
struct panfrost_device *pfdev = data;
- u32 status = job_read(pfdev, JOB_INT_STAT);
- int j;
-
- dev_dbg(pfdev->dev, "jobslot irq status=%x\n", status);
-
- if (!status)
- return IRQ_NONE;
-
- pm_runtime_mark_last_busy(pfdev->dev);
-
- for (j = 0; status; j++) {
- u32 mask = MK_JS_MASK(j);
-
- if (!(status & mask))
- continue;
-
- job_write(pfdev, JOB_INT_CLEAR, mask);
-
- if (status & JOB_INT_MASK_ERR(j)) {
- enum panfrost_queue_status old_status;
-
- job_write(pfdev, JS_COMMAND_NEXT(j), JS_COMMAND_NOP);
-
- dev_err(pfdev->dev, "js fault, js=%d, status=%s, head=0x%x, tail=0x%x",
- j,
- panfrost_exception_name(pfdev, job_read(pfdev, JS_STATUS(j))),
- job_read(pfdev, JS_HEAD_LO(j)),
- job_read(pfdev, JS_TAIL_LO(j)));
-
- /*
- * When the queue is being restarted we don't report
- * faults directly to avoid races between the timeout
- * and reset handlers. panfrost_scheduler_start() will
- * call drm_sched_fault() after the queue has been
- * started if status == FAULT_PENDING.
- */
- old_status = atomic_cmpxchg(&pfdev->js->queue[j].status,
- PANFROST_QUEUE_STATUS_STARTING,
- PANFROST_QUEUE_STATUS_FAULT_PENDING);
- if (old_status == PANFROST_QUEUE_STATUS_ACTIVE)
- drm_sched_fault(&pfdev->js->queue[j].sched);
- }
-
- if (status & JOB_INT_MASK_DONE(j)) {
- struct panfrost_job *job;
-
- spin_lock(&pfdev->js->job_lock);
- job = pfdev->jobs[j];
- /* Only NULL if job timeout occurred */
- if (job) {
- pfdev->jobs[j] = NULL;
-
- panfrost_mmu_as_put(pfdev, &job->file_priv->mmu);
- panfrost_devfreq_record_idle(&pfdev->pfdevfreq);
-
- dma_fence_signal_locked(job->done_fence);
- pm_runtime_put_autosuspend(pfdev->dev);
- }
- spin_unlock(&pfdev->js->job_lock);
- }
-
- status &= ~mask;
- }
+ panfrost_job_handle_irqs(pfdev);
+ job_write(pfdev, JOB_INT_MASK,
+ GENMASK(16 + NUM_JOB_SLOTS - 1, 16) |
+ GENMASK(NUM_JOB_SLOTS - 1, 0));
return IRQ_HANDLED;
}
-static void panfrost_reset(struct work_struct *work)
+static irqreturn_t panfrost_job_irq_handler(int irq, void *data)
{
- struct panfrost_device *pfdev = container_of(work,
- struct panfrost_device,
- reset.work);
- unsigned long flags;
- unsigned int i;
- bool cookie;
-
- cookie = dma_fence_begin_signalling();
- for (i = 0; i < NUM_JOB_SLOTS; i++) {
- /*
- * We want pending timeouts to be handled before we attempt
- * to stop the scheduler. If we don't do that and the timeout
- * handler is in flight, it might have removed the bad job
- * from the list, and we'll lose this job if the reset handler
- * enters the critical section in panfrost_scheduler_stop()
- * before the timeout handler.
- *
- * Timeout is set to MAX_SCHEDULE_TIMEOUT - 1 because we need
- * something big enough to make sure the timer will not expire
- * before we manage to stop the scheduler, but we can't use
- * MAX_SCHEDULE_TIMEOUT because drm_sched_get_cleanup_job()
- * considers that as 'timer is not running' and will dequeue
- * the job without making sure the timeout handler is not
- * running.
- */
- pfdev->js->queue[i].sched.timeout = MAX_SCHEDULE_TIMEOUT - 1;
- cancel_delayed_work_sync(&pfdev->js->queue[i].sched.work_tdr);
- panfrost_scheduler_stop(&pfdev->js->queue[i], NULL);
- }
-
- /* All timers have been stopped, we can safely reset the pending state. */
- atomic_set(&pfdev->reset.pending, 0);
-
- spin_lock_irqsave(&pfdev->js->job_lock, flags);
- for (i = 0; i < NUM_JOB_SLOTS; i++) {
- if (pfdev->jobs[i]) {
- pm_runtime_put_noidle(pfdev->dev);
- panfrost_devfreq_record_idle(&pfdev->pfdevfreq);
- pfdev->jobs[i] = NULL;
- }
- }
- spin_unlock_irqrestore(&pfdev->js->job_lock, flags);
-
- panfrost_device_reset(pfdev);
+ struct panfrost_device *pfdev = data;
+ u32 status = job_read(pfdev, JOB_INT_STAT);
- for (i = 0; i < NUM_JOB_SLOTS; i++)
- panfrost_scheduler_start(&pfdev->js->queue[i]);
+ if (!status)
+ return IRQ_NONE;
- dma_fence_end_signalling(cookie);
+ job_write(pfdev, JOB_INT_MASK, 0);
+ return IRQ_WAKE_THREAD;
}
int panfrost_job_init(struct panfrost_device *pfdev)
{
struct panfrost_job_slot *js;
- int ret, j, irq;
+ unsigned int nentries = 2;
+ int ret, j;
- INIT_WORK(&pfdev->reset.work, panfrost_reset);
+ /* All GPUs have two entries per queue, but without jobchain
+ * disambiguation stopping the right job in the close path is tricky,
+ * so let's just advertise one entry in that case.
+ */
+ if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_JOBCHAIN_DISAMBIGUATION))
+ nentries = 1;
pfdev->js = js = devm_kzalloc(pfdev->dev, sizeof(*js), GFP_KERNEL);
if (!js)
return -ENOMEM;
+ INIT_WORK(&pfdev->reset.work, panfrost_reset_work);
spin_lock_init(&js->job_lock);
- irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "job");
- if (irq <= 0)
+ js->irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "job");
+ if (js->irq <= 0)
return -ENODEV;
- ret = devm_request_irq(pfdev->dev, irq, panfrost_job_irq_handler,
- IRQF_SHARED, KBUILD_MODNAME "-job", pfdev);
+ ret = devm_request_threaded_irq(pfdev->dev, js->irq,
+ panfrost_job_irq_handler,
+ panfrost_job_irq_handler_thread,
+ IRQF_SHARED, KBUILD_MODNAME "-job",
+ pfdev);
if (ret) {
dev_err(pfdev->dev, "failed to request job irq");
return ret;
}
- for (j = 0; j < NUM_JOB_SLOTS; j++) {
- mutex_init(&js->queue[j].lock);
+ pfdev->reset.wq = alloc_ordered_workqueue("panfrost-reset", 0);
+ if (!pfdev->reset.wq)
+ return -ENOMEM;
+ for (j = 0; j < NUM_JOB_SLOTS; j++) {
js->queue[j].fence_context = dma_fence_context_alloc(1);
ret = drm_sched_init(&js->queue[j].sched,
&panfrost_sched_ops,
- 1, 0, msecs_to_jiffies(JOB_TIMEOUT_MS),
+ nentries, 0,
+ msecs_to_jiffies(JOB_TIMEOUT_MS),
+ pfdev->reset.wq,
NULL, "pan_js");
if (ret) {
dev_err(pfdev->dev, "Failed to create scheduler: %d.", ret);
@@ -642,6 +853,7 @@ err_sched:
for (j--; j >= 0; j--)
drm_sched_fini(&js->queue[j].sched);
+ destroy_workqueue(pfdev->reset.wq);
return ret;
}
@@ -654,9 +866,10 @@ void panfrost_job_fini(struct panfrost_device *pfdev)
for (j = 0; j < NUM_JOB_SLOTS; j++) {
drm_sched_fini(&js->queue[j].sched);
- mutex_destroy(&js->queue[j].lock);
}
+ cancel_work_sync(&pfdev->reset.work);
+ destroy_workqueue(pfdev->reset.wq);
}
int panfrost_job_open(struct panfrost_file_priv *panfrost_priv)
@@ -679,10 +892,46 @@ int panfrost_job_open(struct panfrost_file_priv *panfrost_priv)
void panfrost_job_close(struct panfrost_file_priv *panfrost_priv)
{
+ struct panfrost_device *pfdev = panfrost_priv->pfdev;
int i;
for (i = 0; i < NUM_JOB_SLOTS; i++)
drm_sched_entity_destroy(&panfrost_priv->sched_entity[i]);
+
+ /* Kill in-flight jobs */
+ spin_lock(&pfdev->js->job_lock);
+ for (i = 0; i < NUM_JOB_SLOTS; i++) {
+ struct drm_sched_entity *entity = &panfrost_priv->sched_entity[i];
+ int j;
+
+ for (j = ARRAY_SIZE(pfdev->jobs[0]) - 1; j >= 0; j--) {
+ struct panfrost_job *job = pfdev->jobs[i][j];
+ u32 cmd;
+
+ if (!job || job->base.entity != entity)
+ continue;
+
+ if (j == 1) {
+ /* Try to cancel the job before it starts */
+ job_write(pfdev, JS_COMMAND_NEXT(i), JS_COMMAND_NOP);
+ /* Reset the job head so it doesn't get restarted if
+ * the job in the first slot failed.
+ */
+ job->jc = 0;
+ }
+
+ if (panfrost_has_hw_feature(pfdev, HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) {
+ cmd = panfrost_get_job_chain_flag(job) ?
+ JS_COMMAND_HARD_STOP_1 :
+ JS_COMMAND_HARD_STOP_0;
+ } else {
+ cmd = JS_COMMAND_HARD_STOP;
+ }
+
+ job_write(pfdev, JS_COMMAND(i), cmd);
+ }
+ }
+ spin_unlock(&pfdev->js->job_lock);
}
int panfrost_job_is_idle(struct panfrost_device *pfdev)
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.h b/drivers/gpu/drm/panfrost/panfrost_job.h
index bbd3ba97ff67..82306a03b57e 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.h
+++ b/drivers/gpu/drm/panfrost/panfrost_job.h
@@ -19,9 +19,9 @@ struct panfrost_job {
struct panfrost_device *pfdev;
struct panfrost_file_priv *file_priv;
- /* Optional fences userspace can pass in for the job to depend on. */
- struct dma_fence **in_fences;
- u32 in_fence_count;
+ /* Contains both explicit and implicit fences */
+ struct xarray deps;
+ unsigned long last_dep;
/* Fence to be signaled by IRQ handler when the job is complete. */
struct dma_fence *done_fence;
@@ -30,8 +30,6 @@ struct panfrost_job {
__u32 requirements;
__u32 flush_id;
- /* Exclusive fences we have taken from the BOs to wait for */
- struct dma_fence **implicit_fences;
struct panfrost_gem_mapping **mappings;
struct drm_gem_object **bos;
u32 bo_count;
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 0581186ebfb3..0da5b3100ab1 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -1,5 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
+
+#include <drm/panfrost_drm.h>
+
#include <linux/atomic.h>
#include <linux/bitfield.h>
#include <linux/delay.h>
@@ -31,10 +34,13 @@ static int wait_ready(struct panfrost_device *pfdev, u32 as_nr)
/* Wait for the MMU status to indicate there is no active command, in
* case one is pending. */
ret = readl_relaxed_poll_timeout_atomic(pfdev->iomem + AS_STATUS(as_nr),
- val, !(val & AS_STATUS_AS_ACTIVE), 10, 1000);
+ val, !(val & AS_STATUS_AS_ACTIVE), 10, 100000);
- if (ret)
+ if (ret) {
+ /* The GPU hung, let's trigger a reset */
+ panfrost_device_schedule_reset(pfdev);
dev_err(pfdev->dev, "AS_ACTIVE bit stuck\n");
+ }
return ret;
}
@@ -151,6 +157,7 @@ u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
as = mmu->as;
if (as >= 0) {
int en = atomic_inc_return(&mmu->as_count);
+ u32 mask = BIT(as) | BIT(16 + as);
/*
* AS can be retained by active jobs or a perfcnt context,
@@ -159,6 +166,18 @@ u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
WARN_ON(en >= (NUM_JOB_SLOTS + 1));
list_move(&mmu->list, &pfdev->as_lru_list);
+
+ if (pfdev->as_faulty_mask & mask) {
+ /* Unhandled pagefault on this AS, the MMU was
+ * disabled. We need to re-enable the MMU after
+ * clearing+unmasking the AS interrupts.
+ */
+ mmu_write(pfdev, MMU_INT_CLEAR, mask);
+ mmu_write(pfdev, MMU_INT_MASK, ~pfdev->as_faulty_mask);
+ pfdev->as_faulty_mask &= ~mask;
+ panfrost_mmu_enable(pfdev, mmu);
+ }
+
goto out;
}
@@ -208,6 +227,7 @@ void panfrost_mmu_reset(struct panfrost_device *pfdev)
spin_lock(&pfdev->as_lock);
pfdev->as_alloc_mask = 0;
+ pfdev->as_faulty_mask = 0;
list_for_each_entry_safe(mmu, mmu_tmp, &pfdev->as_lru_list, list) {
mmu->as = -1;
@@ -337,7 +357,7 @@ static void mmu_tlb_inv_context_s1(void *cookie)
static void mmu_tlb_sync_context(void *cookie)
{
- //struct panfrost_device *pfdev = cookie;
+ //struct panfrost_mmu *mmu = cookie;
// TODO: Wait 1000 GPU cycles for HW_ISSUE_6367/T60X
}
@@ -352,57 +372,10 @@ static const struct iommu_flush_ops mmu_tlb_ops = {
.tlb_flush_walk = mmu_tlb_flush_walk,
};
-int panfrost_mmu_pgtable_alloc(struct panfrost_file_priv *priv)
-{
- struct panfrost_mmu *mmu = &priv->mmu;
- struct panfrost_device *pfdev = priv->pfdev;
-
- INIT_LIST_HEAD(&mmu->list);
- mmu->as = -1;
-
- mmu->pgtbl_cfg = (struct io_pgtable_cfg) {
- .pgsize_bitmap = SZ_4K | SZ_2M,
- .ias = FIELD_GET(0xff, pfdev->features.mmu_features),
- .oas = FIELD_GET(0xff00, pfdev->features.mmu_features),
- .coherent_walk = pfdev->coherent,
- .tlb = &mmu_tlb_ops,
- .iommu_dev = pfdev->dev,
- };
-
- mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
- priv);
- if (!mmu->pgtbl_ops)
- return -EINVAL;
-
- return 0;
-}
-
-void panfrost_mmu_pgtable_free(struct panfrost_file_priv *priv)
-{
- struct panfrost_device *pfdev = priv->pfdev;
- struct panfrost_mmu *mmu = &priv->mmu;
-
- spin_lock(&pfdev->as_lock);
- if (mmu->as >= 0) {
- pm_runtime_get_noresume(pfdev->dev);
- if (pm_runtime_active(pfdev->dev))
- panfrost_mmu_disable(pfdev, mmu->as);
- pm_runtime_put_autosuspend(pfdev->dev);
-
- clear_bit(mmu->as, &pfdev->as_alloc_mask);
- clear_bit(mmu->as, &pfdev->as_in_use_mask);
- list_del(&mmu->list);
- }
- spin_unlock(&pfdev->as_lock);
-
- free_io_pgtable_ops(mmu->pgtbl_ops);
-}
-
static struct panfrost_gem_mapping *
addr_to_mapping(struct panfrost_device *pfdev, int as, u64 addr)
{
struct panfrost_gem_mapping *mapping = NULL;
- struct panfrost_file_priv *priv;
struct drm_mm_node *node;
u64 offset = addr >> PAGE_SHIFT;
struct panfrost_mmu *mmu;
@@ -415,11 +388,10 @@ addr_to_mapping(struct panfrost_device *pfdev, int as, u64 addr)
goto out;
found_mmu:
- priv = container_of(mmu, struct panfrost_file_priv, mmu);
- spin_lock(&priv->mm_lock);
+ spin_lock(&mmu->mm_lock);
- drm_mm_for_each_node(node, &priv->mm) {
+ drm_mm_for_each_node(node, &mmu->mm) {
if (offset >= node->start &&
offset < (node->start + node->size)) {
mapping = drm_mm_node_to_panfrost_mapping(node);
@@ -429,7 +401,7 @@ found_mmu:
}
}
- spin_unlock(&priv->mm_lock);
+ spin_unlock(&mmu->mm_lock);
out:
spin_unlock(&pfdev->as_lock);
return mapping;
@@ -542,6 +514,107 @@ err_bo:
return ret;
}
+static void panfrost_mmu_release_ctx(struct kref *kref)
+{
+ struct panfrost_mmu *mmu = container_of(kref, struct panfrost_mmu,
+ refcount);
+ struct panfrost_device *pfdev = mmu->pfdev;
+
+ spin_lock(&pfdev->as_lock);
+ if (mmu->as >= 0) {
+ pm_runtime_get_noresume(pfdev->dev);
+ if (pm_runtime_active(pfdev->dev))
+ panfrost_mmu_disable(pfdev, mmu->as);
+ pm_runtime_put_autosuspend(pfdev->dev);
+
+ clear_bit(mmu->as, &pfdev->as_alloc_mask);
+ clear_bit(mmu->as, &pfdev->as_in_use_mask);
+ list_del(&mmu->list);
+ }
+ spin_unlock(&pfdev->as_lock);
+
+ free_io_pgtable_ops(mmu->pgtbl_ops);
+ drm_mm_takedown(&mmu->mm);
+ kfree(mmu);
+}
+
+void panfrost_mmu_ctx_put(struct panfrost_mmu *mmu)
+{
+ kref_put(&mmu->refcount, panfrost_mmu_release_ctx);
+}
+
+struct panfrost_mmu *panfrost_mmu_ctx_get(struct panfrost_mmu *mmu)
+{
+ kref_get(&mmu->refcount);
+
+ return mmu;
+}
+
+#define PFN_4G (SZ_4G >> PAGE_SHIFT)
+#define PFN_4G_MASK (PFN_4G - 1)
+#define PFN_16M (SZ_16M >> PAGE_SHIFT)
+
+static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node,
+ unsigned long color,
+ u64 *start, u64 *end)
+{
+ /* Executable buffers can't start or end on a 4GB boundary */
+ if (!(color & PANFROST_BO_NOEXEC)) {
+ u64 next_seg;
+
+ if ((*start & PFN_4G_MASK) == 0)
+ (*start)++;
+
+ if ((*end & PFN_4G_MASK) == 0)
+ (*end)--;
+
+ next_seg = ALIGN(*start, PFN_4G);
+ if (next_seg - *start <= PFN_16M)
+ *start = next_seg + 1;
+
+ *end = min(*end, ALIGN(*start, PFN_4G) - 1);
+ }
+}
+
+struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev)
+{
+ struct panfrost_mmu *mmu;
+
+ mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
+ if (!mmu)
+ return ERR_PTR(-ENOMEM);
+
+ mmu->pfdev = pfdev;
+ spin_lock_init(&mmu->mm_lock);
+
+ /* 4G enough for now. can be 48-bit */
+ drm_mm_init(&mmu->mm, SZ_32M >> PAGE_SHIFT, (SZ_4G - SZ_32M) >> PAGE_SHIFT);
+ mmu->mm.color_adjust = panfrost_drm_mm_color_adjust;
+
+ INIT_LIST_HEAD(&mmu->list);
+ mmu->as = -1;
+
+ mmu->pgtbl_cfg = (struct io_pgtable_cfg) {
+ .pgsize_bitmap = SZ_4K | SZ_2M,
+ .ias = FIELD_GET(0xff, pfdev->features.mmu_features),
+ .oas = FIELD_GET(0xff00, pfdev->features.mmu_features),
+ .coherent_walk = pfdev->coherent,
+ .tlb = &mmu_tlb_ops,
+ .iommu_dev = pfdev->dev,
+ };
+
+ mmu->pgtbl_ops = alloc_io_pgtable_ops(ARM_MALI_LPAE, &mmu->pgtbl_cfg,
+ mmu);
+ if (!mmu->pgtbl_ops) {
+ kfree(mmu);
+ return ERR_PTR(-EINVAL);
+ }
+
+ kref_init(&mmu->refcount);
+
+ return mmu;
+}
+
static const char *access_type_name(struct panfrost_device *pfdev,
u32 fault_status)
{
@@ -605,7 +678,7 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
if ((status & mask) == BIT(as) && (exception_type & 0xF8) == 0xC0)
ret = panfrost_mmu_map_fault_addr(pfdev, as, addr);
- if (ret)
+ if (ret) {
/* terminal fault, print info about the fault */
dev_err(pfdev->dev,
"Unhandled Page fault in AS%d at VA 0x%016llX\n"
@@ -619,18 +692,32 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
"TODO",
fault_status,
(fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
- exception_type, panfrost_exception_name(pfdev, exception_type),
+ exception_type, panfrost_exception_name(exception_type),
access_type, access_type_name(pfdev, fault_status),
source_id);
+ spin_lock(&pfdev->as_lock);
+ /* Ignore MMU interrupts on this AS until it's been
+ * re-enabled.
+ */
+ pfdev->as_faulty_mask |= mask;
+
+ /* Disable the MMU to kill jobs on this AS. */
+ panfrost_mmu_disable(pfdev, as);
+ spin_unlock(&pfdev->as_lock);
+ }
+
status &= ~mask;
/* If we received new MMU interrupts, process them before returning. */
if (!status)
- status = mmu_read(pfdev, MMU_INT_RAWSTAT);
+ status = mmu_read(pfdev, MMU_INT_RAWSTAT) & ~pfdev->as_faulty_mask;
}
- mmu_write(pfdev, MMU_INT_MASK, ~0);
+ spin_lock(&pfdev->as_lock);
+ mmu_write(pfdev, MMU_INT_MASK, ~pfdev->as_faulty_mask);
+ spin_unlock(&pfdev->as_lock);
+
return IRQ_HANDLED;
};
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.h b/drivers/gpu/drm/panfrost/panfrost_mmu.h
index 44fc2edf63ce..cc2a0d307feb 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.h
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.h
@@ -18,7 +18,8 @@ void panfrost_mmu_reset(struct panfrost_device *pfdev);
u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu);
void panfrost_mmu_as_put(struct panfrost_device *pfdev, struct panfrost_mmu *mmu);
-int panfrost_mmu_pgtable_alloc(struct panfrost_file_priv *priv);
-void panfrost_mmu_pgtable_free(struct panfrost_file_priv *priv);
+struct panfrost_mmu *panfrost_mmu_ctx_get(struct panfrost_mmu *mmu);
+void panfrost_mmu_ctx_put(struct panfrost_mmu *mmu);
+struct panfrost_mmu *panfrost_mmu_ctx_create(struct panfrost_device *pfdev);
#endif
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h
index dc9df5457f1c..1940ff86e49a 100644
--- a/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ b/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -262,9 +262,6 @@
#define JS_COMMAND_SOFT_STOP_1 0x06 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 1 */
#define JS_COMMAND_HARD_STOP_1 0x07 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 1 */
-#define JS_STATUS_EVENT_ACTIVE 0x08
-
-
/* MMU regs */
#define MMU_INT_RAWSTAT 0x2000
#define MMU_INT_CLEAR 0x2004
diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c
index 6fd7f13f1aca..443e3b932322 100644
--- a/drivers/gpu/drm/pl111/pl111_display.c
+++ b/drivers/gpu/drm/pl111/pl111_display.c
@@ -11,7 +11,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
-#include <linux/version.h>
#include <linux/dma-buf.h>
#include <linux/of_graph.h>
@@ -440,7 +439,6 @@ static struct drm_simple_display_pipe_funcs pl111_display_funcs = {
.enable = pl111_display_enable,
.disable = pl111_display_disable,
.update = pl111_display_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static int pl111_clk_div_choose_div(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index fa0a737e9dea..520301b405f1 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -44,7 +44,6 @@
#include <linux/of_reserved_mem.h>
#include <linux/shmem_fs.h>
#include <linux/slab.h>
-#include <linux/version.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 854e6c5a563f..fc47b0deb021 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -95,7 +95,7 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "qxl");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &qxl_driver);
if (ret)
goto disable_pci;
@@ -281,10 +281,8 @@ static struct drm_driver qxl_driver = {
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import_sg_table = qxl_gem_prime_import_sg_table,
- .gem_prime_mmap = qxl_gem_prime_mmap,
.fops = &qxl_fops,
.ioctls = qxl_ioctls,
- .irq_handler = qxl_irq_handler,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index dd6abee55f56..359266d9e860 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -434,12 +434,9 @@ struct drm_gem_object *qxl_gem_prime_import_sg_table(
int qxl_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
void qxl_gem_prime_vunmap(struct drm_gem_object *obj,
struct dma_buf_map *map);
-int qxl_gem_prime_mmap(struct drm_gem_object *obj,
- struct vm_area_struct *vma);
/* qxl_irq.c */
int qxl_irq_init(struct qxl_device *qdev);
-irqreturn_t qxl_irq_handler(int irq, void *arg);
void qxl_debugfs_add_files(struct qxl_device *qdev,
struct drm_info_list *files,
diff --git a/drivers/gpu/drm/qxl/qxl_irq.c b/drivers/gpu/drm/qxl/qxl_irq.c
index d312322cacd1..665278ee3b6d 100644
--- a/drivers/gpu/drm/qxl/qxl_irq.c
+++ b/drivers/gpu/drm/qxl/qxl_irq.c
@@ -25,11 +25,11 @@
#include <linux/pci.h>
-#include <drm/drm_irq.h>
+#include <drm/drm_drv.h>
#include "qxl_drv.h"
-irqreturn_t qxl_irq_handler(int irq, void *arg)
+static irqreturn_t qxl_irq_handler(int irq, void *arg)
{
struct drm_device *dev = (struct drm_device *) arg;
struct qxl_device *qdev = to_qxl(dev);
@@ -81,7 +81,8 @@ static void qxl_client_monitors_config_work_func(struct work_struct *work)
int qxl_irq_init(struct qxl_device *qdev)
{
- struct pci_dev *pdev = to_pci_dev(qdev->ddev.dev);
+ struct drm_device *ddev = &qdev->ddev;
+ struct pci_dev *pdev = to_pci_dev(ddev->dev);
int ret;
init_waitqueue_head(&qdev->display_event);
@@ -95,7 +96,7 @@ int qxl_irq_init(struct qxl_device *qdev)
atomic_set(&qdev->irq_received_cursor, 0);
atomic_set(&qdev->irq_received_io_cmd, 0);
qdev->irq_received_error = 0;
- ret = drm_irq_install(&qdev->ddev, pdev->irq);
+ ret = request_irq(pdev->irq, qxl_irq_handler, IRQF_SHARED, ddev->driver->name, ddev);
qdev->ram_header->int_mask = QXL_INTERRUPT_MASK;
if (unlikely(ret != 0)) {
DRM_ERROR("Failed installing irq: %d\n", ret);
diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c
index 0628d1cc91fe..4a10cb0a413b 100644
--- a/drivers/gpu/drm/qxl/qxl_prime.c
+++ b/drivers/gpu/drm/qxl/qxl_prime.c
@@ -73,9 +73,3 @@ void qxl_gem_prime_vunmap(struct drm_gem_object *obj,
qxl_bo_vunmap(bo);
}
-
-int qxl_gem_prime_mmap(struct drm_gem_object *obj,
- struct vm_area_struct *area)
-{
- return -ENOSYS;
-}
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
index 2a2933c16308..c04d84a69dd2 100644
--- a/drivers/gpu/drm/r128/r128_cce.c
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -39,7 +39,6 @@
#include <drm/drm_device.h>
#include <drm/drm_file.h>
-#include <drm/drm_irq.h>
#include <drm/drm_legacy.h>
#include <drm/drm_print.h>
#include <drm/r128_drm.h>
@@ -603,7 +602,7 @@ int r128_do_cleanup_cce(struct drm_device *dev)
* is freed, it's too late.
*/
if (dev->irq_enabled)
- drm_irq_uninstall(dev);
+ drm_legacy_irq_uninstall(dev);
if (dev->dev_private) {
drm_r128_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h
index 4b86e8b45009..83e8b8547f9b 100644
--- a/drivers/gpu/drm/radeon/atombios.h
+++ b/drivers/gpu/drm/radeon/atombios.h
@@ -2802,8 +2802,8 @@ ucMaxNBVoltageHigh: Voltage regulator dependent PWM value. High 8 bits of t
ucMinNBVoltageHigh: Voltage regulator dependent PWM value. High 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all.
-usInterNBVoltageLow: Voltage regulator dependent PWM value. The value makes the the voltage >=Min NB voltage but <=InterNBVoltageHigh. Set this to 0x0000 if VC without PWM or no VC at all.
-usInterNBVoltageHigh: Voltage regulator dependent PWM value. The value makes the the voltage >=InterNBVoltageLow but <=Max NB voltage.Set this to 0x0000 if VC without PWM or no VC at all.
+usInterNBVoltageLow: Voltage regulator dependent PWM value. The value makes the voltage >=Min NB voltage but <=InterNBVoltageHigh. Set this to 0x0000 if VC without PWM or no VC at all.
+usInterNBVoltageHigh: Voltage regulator dependent PWM value. The value makes the voltage >=InterNBVoltageLow but <=Max NB voltage.Set this to 0x0000 if VC without PWM or no VC at all.
*/
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 36a888e1b179..eeb590d2dec2 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -28,6 +28,7 @@
#include <drm/drm_vblank.h>
#include <drm/radeon_drm.h>
+#include <drm/drm_fourcc.h>
#include "atom.h"
#include "avivod.h"
@@ -1414,10 +1415,15 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base,
bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+ struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
- /* update the scanout addresses */
+ /* flip at hsync for async, default is vsync */
WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
async ? EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
+ /* update pitch */
+ WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset,
+ fb->pitches[0] / fb->format->cpp[0]);
+ /* update the scanout addresses */
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(crtc_base));
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index ba724198b72e..2dd85ba1faa2 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -162,6 +162,8 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+ uint32_t crtc_pitch, pitch_pixels;
+ struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
int i;
@@ -169,6 +171,13 @@ void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool
/* update the scanout addresses */
WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
+ /* update pitch */
+ pitch_pixels = fb->pitches[0] / fb->format->cpp[0];
+ crtc_pitch = DIV_ROUND_UP(pitch_pixels * fb->format->cpp[0] * 8,
+ fb->format->cpp[0] * 8 * 8);
+ crtc_pitch |= crtc_pitch << 16;
+ WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
+
/* Wait for update_pending to go high. */
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h
index 00c0d2ba22d3..60d5413bafa1 100644
--- a/drivers/gpu/drm/radeon/r300_reg.h
+++ b/drivers/gpu/drm/radeon/r300_reg.h
@@ -353,7 +353,7 @@
# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0
# define R300_PVS_CNTL_1_POS_END_SHIFT 10
# define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20
-/* Addresses are relative the the vertex program parameters area. */
+/* Addresses are relative the vertex program parameters area. */
#define R300_VAP_PVS_CNTL_2 0x22D4
# define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
# define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 46eea01950cb..4f0fbf667431 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -406,7 +406,7 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell)
/*
* radeon_wb_*()
- * Writeback is the the method by which the the GPU updates special pages
+ * Writeback is the method by which the GPU updates special pages
* in memory with the status of certain GPU events (fences, ring pointers,
* etc.).
*/
@@ -785,7 +785,7 @@ int radeon_dummy_page_init(struct radeon_device *rdev)
if (rdev->dummy_page.page == NULL)
return -ENOMEM;
rdev->dummy_page.addr = dma_map_page(&rdev->pdev->dev, rdev->dummy_page.page,
- 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
if (dma_mapping_error(&rdev->pdev->dev, rdev->dummy_page.addr)) {
dev_err(&rdev->pdev->dev, "Failed to DMA MAP the dummy page\n");
__free_page(rdev->dummy_page.page);
@@ -808,8 +808,8 @@ void radeon_dummy_page_fini(struct radeon_device *rdev)
{
if (rdev->dummy_page.page == NULL)
return;
- pci_unmap_page(rdev->pdev, rdev->dummy_page.addr,
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_page(&rdev->pdev->dev, rdev->dummy_page.addr, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
__free_page(rdev->dummy_page.page);
rdev->dummy_page.page = NULL;
}
@@ -1067,15 +1067,16 @@ void radeon_combios_fini(struct radeon_device *rdev)
/**
* radeon_vga_set_decode - enable/disable vga decode
*
- * @cookie: radeon_device pointer
+ * @pdev: PCI device
* @state: enable/disable vga decode
*
* Enable/disable vga decode (all asics).
* Returns VGA resource flags.
*/
-static unsigned int radeon_vga_set_decode(void *cookie, bool state)
+static unsigned int radeon_vga_set_decode(struct pci_dev *pdev, bool state)
{
- struct radeon_device *rdev = cookie;
+ struct drm_device *dev = pci_get_drvdata(pdev);
+ struct radeon_device *rdev = dev->dev_private;
radeon_vga_set_state(rdev, state);
if (state)
return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
@@ -1434,7 +1435,7 @@ int radeon_device_init(struct radeon_device *rdev,
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
/* this will fail for cards that aren't VGA class devices, just
* ignore it */
- vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
+ vga_client_register(rdev->pdev, radeon_vga_set_decode);
if (rdev->flags & RADEON_IS_PX)
runtime = true;
@@ -1530,7 +1531,7 @@ void radeon_device_fini(struct radeon_device *rdev)
vga_switcheroo_unregister_client(rdev->pdev);
if (rdev->flags & RADEON_IS_PX)
vga_switcheroo_fini_domain_pm_ops(rdev->dev);
- vga_client_register(rdev->pdev, NULL, NULL, NULL);
+ vga_client_unregister(rdev->pdev);
if (rdev->rio_mem)
pci_iounmap(rdev->pdev, rdev->rio_mem);
rdev->rio_mem = NULL;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 5c23b77cb81a..b74cebca1f89 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -330,7 +330,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
return -EPROBE_DEFER;
/* Get rid of things like offb */
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "radeondrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &kms_driver);
if (ret)
return ret;
@@ -607,10 +607,6 @@ static const struct drm_driver kms_driver = {
.postclose = radeon_driver_postclose_kms,
.lastclose = radeon_driver_lastclose_kms,
.unload = radeon_driver_unload_kms,
- .irq_preinstall = radeon_driver_irq_preinstall_kms,
- .irq_postinstall = radeon_driver_irq_postinstall_kms,
- .irq_uninstall = radeon_driver_irq_uninstall_kms,
- .irq_handler = radeon_driver_irq_handler_kms,
.ioctls = radeon_ioctls_kms,
.num_ioctls = ARRAY_SIZE(radeon_ioctls_kms),
.dumb_create = radeon_mode_dumb_create,
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 0b206b052972..ca382fbf7a86 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -54,6 +54,7 @@ radeonfb_open(struct fb_info *info, int user)
struct radeon_fbdev *rfbdev = info->par;
struct radeon_device *rdev = rfbdev->rdev;
int ret = pm_runtime_get_sync(rdev->ddev->dev);
+
if (ret < 0 && ret != -EACCES) {
pm_runtime_mark_last_busy(rdev->ddev->dev);
pm_runtime_put_autosuspend(rdev->ddev->dev);
@@ -167,6 +168,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
break;
case 2:
tiling_flags |= RADEON_TILING_SWAP_16BIT;
+ break;
default:
break;
}
@@ -196,9 +198,8 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
radeon_bo_check_tiling(rbo, 0, 0);
ret = radeon_bo_kmap(rbo, NULL);
radeon_bo_unreserve(rbo);
- if (ret) {
+ if (ret)
goto out_unref;
- }
*gobj_p = gobj;
return 0;
@@ -294,9 +295,6 @@ static int radeonfb_create(struct drm_fb_helper *helper,
return 0;
out:
- if (rbo) {
-
- }
if (fb && ret) {
drm_gem_object_put(gobj);
drm_framebuffer_unregister_private(fb);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index b2ce642ca4fa..e9c47ec28ade 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -50,7 +50,7 @@
* for GPU/CPU synchronization. When the fence is written,
* it is expected that all buffers associated with that fence
* are no longer in use by the associated ring on the GPU and
- * that the the relevant GPU caches have been flushed. Whether
+ * that the relevant GPU caches have been flushed. Whether
* we use a scratch register or memory location depends on the asic
* and whether writeback is enabled.
*/
@@ -288,7 +288,7 @@ static void radeon_fence_check_lockup(struct work_struct *work)
return;
}
- if (fence_drv->delayed_irq && rdev->ddev->irq_enabled) {
+ if (fence_drv->delayed_irq && rdev->irq.installed) {
unsigned long irqflags;
fence_drv->delayed_irq = false;
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 84d0b1a3355f..3907785d0798 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -31,7 +31,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_device.h>
-#include <drm/drm_irq.h>
+#include <drm/drm_drv.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
#include <drm/radeon_drm.h>
@@ -51,7 +51,7 @@
* radeon_irq_process is a macro that points to the per-asic
* irq handler callback.
*/
-irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
+static irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
{
struct drm_device *dev = (struct drm_device *) arg;
struct radeon_device *rdev = dev->dev_private;
@@ -118,7 +118,7 @@ static void radeon_dp_work_func(struct work_struct *work)
* Gets the hw ready to enable irqs (all asics).
* This function disables all interrupt sources on the GPU.
*/
-void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
+static void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
unsigned long irqflags;
@@ -150,7 +150,7 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
* Handles stuff to be done after enabling irqs (all asics).
* Returns 0 on success.
*/
-int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
+static int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
@@ -169,7 +169,7 @@ int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
*
* This function disables all interrupt sources on the GPU (all asics).
*/
-void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
+static void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
unsigned long irqflags;
@@ -194,6 +194,36 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
}
+static int radeon_irq_install(struct radeon_device *rdev, int irq)
+{
+ struct drm_device *dev = rdev->ddev;
+ int ret;
+
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ radeon_driver_irq_preinstall_kms(dev);
+
+ /* PCI devices require shared interrupts. */
+ ret = request_irq(irq, radeon_driver_irq_handler_kms,
+ IRQF_SHARED, dev->driver->name, dev);
+ if (ret)
+ return ret;
+
+ radeon_driver_irq_postinstall_kms(dev);
+
+ return 0;
+}
+
+static void radeon_irq_uninstall(struct radeon_device *rdev)
+{
+ struct drm_device *dev = rdev->ddev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+ radeon_driver_irq_uninstall_kms(dev);
+ free_irq(pdev->irq, dev);
+}
+
/**
* radeon_msi_ok - asic specific msi checks
*
@@ -314,7 +344,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
rdev->irq.installed = true;
- r = drm_irq_install(rdev->ddev, rdev->pdev->irq);
+ r = radeon_irq_install(rdev, rdev->pdev->irq);
if (r) {
rdev->irq.installed = false;
flush_delayed_work(&rdev->hotplug_work);
@@ -335,7 +365,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
void radeon_irq_kms_fini(struct radeon_device *rdev)
{
if (rdev->irq.installed) {
- drm_irq_uninstall(rdev->ddev);
+ radeon_irq_uninstall(rdev);
rdev->irq.installed = false;
if (rdev->msi_enabled)
pci_disable_msi(rdev->pdev);
@@ -357,7 +387,7 @@ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
{
unsigned long irqflags;
- if (!rdev->ddev->irq_enabled)
+ if (!rdev->irq.installed)
return;
if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
@@ -396,7 +426,7 @@ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
{
unsigned long irqflags;
- if (!rdev->ddev->irq_enabled)
+ if (!rdev->irq.installed)
return;
if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
@@ -422,7 +452,7 @@ void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc)
if (crtc < 0 || crtc >= rdev->num_crtc)
return;
- if (!rdev->ddev->irq_enabled)
+ if (!rdev->irq.installed)
return;
if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) {
@@ -448,7 +478,7 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc)
if (crtc < 0 || crtc >= rdev->num_crtc)
return;
- if (!rdev->ddev->irq_enabled)
+ if (!rdev->irq.installed)
return;
if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) {
@@ -470,7 +500,7 @@ void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block)
{
unsigned long irqflags;
- if (!rdev->ddev->irq_enabled)
+ if (!rdev->irq.installed)
return;
spin_lock_irqsave(&rdev->irq.lock, irqflags);
@@ -492,7 +522,7 @@ void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block)
{
unsigned long irqflags;
- if (!rdev->ddev->irq_enabled)
+ if (!rdev->irq.installed)
return;
spin_lock_irqsave(&rdev->irq.lock, irqflags);
@@ -514,7 +544,7 @@ void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
unsigned long irqflags;
int i;
- if (!rdev->ddev->irq_enabled)
+ if (!rdev->irq.installed)
return;
spin_lock_irqsave(&rdev->irq.lock, irqflags);
@@ -537,7 +567,7 @@ void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
unsigned long irqflags;
int i;
- if (!rdev->ddev->irq_enabled)
+ if (!rdev->irq.installed)
return;
spin_lock_irqsave(&rdev->irq.lock, irqflags);
diff --git a/drivers/gpu/drm/radeon/radeon_kms.h b/drivers/gpu/drm/radeon/radeon_kms.h
index 9b97bf38acd4..36e73cea9215 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.h
+++ b/drivers/gpu/drm/radeon/radeon_kms.h
@@ -31,9 +31,5 @@
u32 radeon_get_vblank_counter_kms(struct drm_crtc *crtc);
int radeon_enable_vblank_kms(struct drm_crtc *crtc);
void radeon_disable_vblank_kms(struct drm_crtc *crtc);
-irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg);
-void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
-int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
-void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
#endif /* __RADEON_KMS_H__ */
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c
index 36a38adaaea9..bb53016f3138 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -41,7 +41,7 @@
* (uncached system pages).
* Each VM has an ID associated with it and there is a page table
* associated with each VMID. When execting a command buffer,
- * the kernel tells the the ring what VMID to use for that command
+ * the kernel tells the ring what VMID to use for that command
* buffer. VMIDs are allocated dynamically as commands are submitted.
* The userspace drivers maintain their own address space and the kernel
* sets up their pages tables accordingly when they submit their
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index b2d22e25eee1..b87dd551e939 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -41,6 +41,7 @@
#include <drm/drm_device.h>
#include <drm/drm_vblank.h>
+#include <drm/drm_fourcc.h>
#include "atom.h"
#include "radeon.h"
@@ -118,6 +119,7 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc)
void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+ struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
int i;
@@ -125,9 +127,13 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, boo
tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
- /* update the scanout addresses */
+ /* flip at hsync for async, default is vsync */
WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
+ /* update pitch */
+ WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset,
+ fb->pitches[0] / fb->format->cpp[0]);
+ /* update the scanout addresses */
WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
(u32)crtc_base);
WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 74499307285b..e592e57be1bb 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -32,6 +32,7 @@
#include <drm/drm_device.h>
#include <drm/radeon_drm.h>
+#include <drm/drm_fourcc.h>
#include "atom.h"
#include "avivod.h"
@@ -809,6 +810,7 @@ u32 rv770_get_xclk(struct radeon_device *rdev)
void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
+ struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
int i;
@@ -816,9 +818,13 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, boo
tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
- /* update the scanout addresses */
+ /* flip at hsync for async, default is vsync */
WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
+ /* update pitch */
+ WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset,
+ fb->pitches[0] / fb->format->cpp[0]);
+ /* update the scanout addresses */
if (radeon_crtc->crtc_id) {
WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index bfbff90588cb..4ac26d08ebb4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -553,14 +553,20 @@ static int rcar_du_remove(struct platform_device *pdev)
struct drm_device *ddev = &rcdu->ddev;
drm_dev_unregister(ddev);
+ drm_atomic_helper_shutdown(ddev);
drm_kms_helper_poll_fini(ddev);
- drm_dev_put(ddev);
-
return 0;
}
+static void rcar_du_shutdown(struct platform_device *pdev)
+{
+ struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
+
+ drm_atomic_helper_shutdown(&rcdu->ddev);
+}
+
static int rcar_du_probe(struct platform_device *pdev)
{
struct rcar_du_device *rcdu;
@@ -593,8 +599,6 @@ static int rcar_du_probe(struct platform_device *pdev)
goto error;
}
- rcdu->ddev.irq_enabled = 1;
-
/*
* Register the DRM device with the core and the connectors with
* sysfs.
@@ -617,6 +621,7 @@ error:
static struct platform_driver rcar_du_platform_driver = {
.probe = rcar_du_probe,
.remove = rcar_du_remove,
+ .shutdown = rcar_du_shutdown,
.driver = {
.name = "rcar-du",
.pm = &rcar_du_pm_ops,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index ca3761772211..0daa8bba50f5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h>
@@ -53,7 +54,9 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
struct device_node *enc_node)
{
struct rcar_du_encoder *renc;
+ struct drm_connector *connector;
struct drm_bridge *bridge;
+ int ret;
/*
* Locate the DRM bridge from the DT node. For the DPAD outputs, if the
@@ -103,9 +106,22 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
renc->output = output;
- /*
- * Attach the bridge to the encoder. The bridge will create the
- * connector.
- */
- return drm_bridge_attach(&renc->base, bridge, NULL, 0);
+ /* Attach the bridge to the encoder. */
+ ret = drm_bridge_attach(&renc->base, bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret) {
+ dev_err(rcdu->dev, "failed to attach bridge for output %u\n",
+ output);
+ return ret;
+ }
+
+ /* Create the connector for the chain of bridges. */
+ connector = drm_bridge_connector_init(&rcdu->ddev, &renc->base);
+ if (IS_ERR(connector)) {
+ dev_err(rcdu->dev,
+ "failed to created connector for output %u\n", output);
+ return PTR_ERR(connector);
+ }
+
+ return drm_connector_attach_encoder(connector, &renc->base);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
index 7b8ec8310699..18ed14911b98 100644
--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
+++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
@@ -75,6 +75,7 @@ static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data,
}
static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = {
+ .output_port = 1,
.mode_valid = rcar_hdmi_mode_valid,
.configure_phy = rcar_hdmi_phy_configure,
};
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 70dbbe44bb23..d061b8de748f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -63,7 +63,6 @@ struct rcar_lvds {
struct drm_bridge bridge;
struct drm_bridge *next_bridge;
- struct drm_connector connector;
struct drm_panel *panel;
void __iomem *mmio;
@@ -80,74 +79,12 @@ struct rcar_lvds {
#define bridge_to_rcar_lvds(b) \
container_of(b, struct rcar_lvds, bridge)
-#define connector_to_rcar_lvds(c) \
- container_of(c, struct rcar_lvds, connector)
-
static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data)
{
iowrite32(data, lvds->mmio + reg);
}
/* -----------------------------------------------------------------------------
- * Connector & Panel
- */
-
-static int rcar_lvds_connector_get_modes(struct drm_connector *connector)
-{
- struct rcar_lvds *lvds = connector_to_rcar_lvds(connector);
-
- return drm_panel_get_modes(lvds->panel, connector);
-}
-
-static int rcar_lvds_connector_atomic_check(struct drm_connector *connector,
- struct drm_atomic_state *state)
-{
- struct rcar_lvds *lvds = connector_to_rcar_lvds(connector);
- const struct drm_display_mode *panel_mode;
- struct drm_connector_state *conn_state;
- struct drm_crtc_state *crtc_state;
-
- conn_state = drm_atomic_get_new_connector_state(state, connector);
- if (!conn_state->crtc)
- return 0;
-
- if (list_empty(&connector->modes)) {
- dev_dbg(lvds->dev, "connector: empty modes list\n");
- return -EINVAL;
- }
-
- panel_mode = list_first_entry(&connector->modes,
- struct drm_display_mode, head);
-
- /* We're not allowed to modify the resolution. */
- crtc_state = drm_atomic_get_crtc_state(state, conn_state->crtc);
- if (IS_ERR(crtc_state))
- return PTR_ERR(crtc_state);
-
- if (crtc_state->mode.hdisplay != panel_mode->hdisplay ||
- crtc_state->mode.vdisplay != panel_mode->vdisplay)
- return -EINVAL;
-
- /* The flat panel mode is fixed, just copy it to the adjusted mode. */
- drm_mode_copy(&crtc_state->adjusted_mode, panel_mode);
-
- return 0;
-}
-
-static const struct drm_connector_helper_funcs rcar_lvds_conn_helper_funcs = {
- .get_modes = rcar_lvds_connector_get_modes,
- .atomic_check = rcar_lvds_connector_atomic_check,
-};
-
-static const struct drm_connector_funcs rcar_lvds_conn_funcs = {
- .reset = drm_atomic_helper_connector_reset,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-/* -----------------------------------------------------------------------------
* PLL Setup
*/
@@ -583,11 +520,6 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
/* Turn the output on. */
lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
-
- if (lvds->panel) {
- drm_panel_prepare(lvds->panel);
- drm_panel_enable(lvds->panel);
- }
}
static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
@@ -609,11 +541,6 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
- if (lvds->panel) {
- drm_panel_disable(lvds->panel);
- drm_panel_unprepare(lvds->panel);
- }
-
rcar_lvds_write(lvds, LVDCR0, 0);
rcar_lvds_write(lvds, LVDCR1, 0);
rcar_lvds_write(lvds, LVDPLLCR, 0);
@@ -648,45 +575,13 @@ static int rcar_lvds_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
- struct drm_connector *connector = &lvds->connector;
- struct drm_encoder *encoder = bridge->encoder;
- int ret;
-
- /* If we have a next bridge just attach it. */
- if (lvds->next_bridge)
- return drm_bridge_attach(bridge->encoder, lvds->next_bridge,
- bridge, flags);
-
- if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
- DRM_ERROR("Fix bridge driver to make connector optional!");
- return -EINVAL;
- }
-
- /* Otherwise if we have a panel, create a connector. */
- if (!lvds->panel)
- return 0;
-
- ret = drm_connector_init(bridge->dev, connector, &rcar_lvds_conn_funcs,
- DRM_MODE_CONNECTOR_LVDS);
- if (ret < 0)
- return ret;
-
- drm_connector_helper_add(connector, &rcar_lvds_conn_helper_funcs);
-
- ret = drm_connector_attach_encoder(connector, encoder);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-static void rcar_lvds_detach(struct drm_bridge *bridge)
-{
+ return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge,
+ flags);
}
static const struct drm_bridge_funcs rcar_lvds_bridge_ops = {
.attach = rcar_lvds_attach,
- .detach = rcar_lvds_detach,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
@@ -759,7 +654,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
* that we are expected to generate even pixels from the primary
* encoder, and odd pixels from the companion encoder.
*/
- if (lvds->next_bridge && lvds->next_bridge->timings &&
+ if (lvds->next_bridge->timings &&
lvds->next_bridge->timings->dual_link)
lvds->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
else
@@ -811,6 +706,15 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
if (ret)
goto done;
+ if (lvds->panel) {
+ lvds->next_bridge = devm_drm_panel_bridge_add(lvds->dev,
+ lvds->panel);
+ if (IS_ERR_OR_NULL(lvds->next_bridge)) {
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+
if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
ret = rcar_lvds_parse_dt_companion(lvds);
@@ -839,9 +743,8 @@ static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
if (PTR_ERR(clk) == -ENOENT && optional)
return NULL;
- if (PTR_ERR(clk) != -EPROBE_DEFER)
- dev_err(lvds->dev, "failed to get %s clock\n",
- name ? name : "module");
+ dev_err_probe(lvds->dev, PTR_ERR(clk), "failed to get %s clock\n",
+ name ? name : "module");
return clk;
}
@@ -919,7 +822,6 @@ static int rcar_lvds_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- lvds->bridge.driver_private = lvds;
lvds->bridge.funcs = &rcar_lvds_bridge_ops;
lvds->bridge.of_node = pdev->dev.of_node;
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index cb25c0e8fc9b..558f1b58bd69 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -10,6 +10,8 @@ config DRM_ROCKCHIP
select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
select DRM_RGB if ROCKCHIP_RGB
+ select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
+ select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI
select SND_SOC_HDMI_CODEC if ROCKCHIP_CDN_DP && SND_SOC
help
Choose this option if you have a Rockchip soc chipset.
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
index ec7729d18cb8..a2262bee5aa4 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -14,6 +14,7 @@
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/pm_runtime.h>
+#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <video/mipi_display.h>
@@ -125,7 +126,9 @@
#define BANDGAP_AND_BIAS_CONTROL 0x20
#define TERMINATION_RESISTER_CONTROL 0x21
#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY 0x22
+#define HS_RX_CONTROL_OF_LANE_CLK 0x34
#define HS_RX_CONTROL_OF_LANE_0 0x44
+#define HS_RX_CONTROL_OF_LANE_1 0x54
#define HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL 0x60
#define HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL 0x61
#define HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL 0x62
@@ -137,6 +140,9 @@
#define HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL 0x72
#define HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL 0x73
#define HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL 0x74
+#define HS_RX_DATA_LANE_THS_SETTLE_CONTROL 0x75
+#define HS_RX_CONTROL_OF_LANE_2 0x84
+#define HS_RX_CONTROL_OF_LANE_3 0x94
#define DW_MIPI_NEEDS_PHY_CFG_CLK BIT(0)
#define DW_MIPI_NEEDS_GRF_CLK BIT(1)
@@ -171,12 +177,20 @@
#define RK3399_TXRX_MASTERSLAVEZ BIT(7)
#define RK3399_TXRX_ENABLECLK BIT(6)
#define RK3399_TXRX_BASEDIR BIT(5)
+#define RK3399_TXRX_SRC_SEL_ISP0 BIT(4)
+#define RK3399_TXRX_TURNREQUEST GENMASK(3, 0)
#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
#define to_dsi(nm) container_of(nm, struct dw_mipi_dsi_rockchip, nm)
enum {
+ DW_DSI_USAGE_IDLE,
+ DW_DSI_USAGE_DSI,
+ DW_DSI_USAGE_PHY,
+};
+
+enum {
BANDGAP_97_07,
BANDGAP_98_05,
BANDGAP_99_02,
@@ -213,6 +227,10 @@ struct rockchip_dw_dsi_chip_data {
u32 lanecfg2_grf_reg;
u32 lanecfg2;
+ int (*dphy_rx_init)(struct phy *phy);
+ int (*dphy_rx_power_on)(struct phy *phy);
+ int (*dphy_rx_power_off)(struct phy *phy);
+
unsigned int flags;
unsigned int max_data_lanes;
};
@@ -223,6 +241,7 @@ struct dw_mipi_dsi_rockchip {
void __iomem *base;
struct regmap *grf_regmap;
+ struct clk *pclk;
struct clk *pllref_clk;
struct clk *grf_clk;
struct clk *phy_cfg_clk;
@@ -235,6 +254,12 @@ struct dw_mipi_dsi_rockchip {
struct phy *phy;
union phy_configure_opts phy_opts;
+ /* being a phy for other mipi hosts */
+ unsigned int usage_mode;
+ struct mutex usage_mutex;
+ struct phy *dphy;
+ struct phy_configure_opts_mipi_dphy dphy_config;
+
unsigned int lane_mbps; /* per lane */
u16 input_div;
u16 feedback_div;
@@ -978,6 +1003,17 @@ static int dw_mipi_dsi_rockchip_host_attach(void *priv_data,
struct device *second;
int ret;
+ mutex_lock(&dsi->usage_mutex);
+
+ if (dsi->usage_mode != DW_DSI_USAGE_IDLE) {
+ DRM_DEV_ERROR(dsi->dev, "dsi controller already in use\n");
+ mutex_unlock(&dsi->usage_mutex);
+ return -EBUSY;
+ }
+
+ dsi->usage_mode = DW_DSI_USAGE_DSI;
+ mutex_unlock(&dsi->usage_mutex);
+
ret = component_add(dsi->dev, &dw_mipi_dsi_rockchip_ops);
if (ret) {
DRM_DEV_ERROR(dsi->dev, "Failed to register component: %d\n",
@@ -1013,6 +1049,10 @@ static int dw_mipi_dsi_rockchip_host_detach(void *priv_data,
component_del(dsi->dev, &dw_mipi_dsi_rockchip_ops);
+ mutex_lock(&dsi->usage_mutex);
+ dsi->usage_mode = DW_DSI_USAGE_IDLE;
+ mutex_unlock(&dsi->usage_mutex);
+
return 0;
}
@@ -1021,11 +1061,227 @@ static const struct dw_mipi_dsi_host_ops dw_mipi_dsi_rockchip_host_ops = {
.detach = dw_mipi_dsi_rockchip_host_detach,
};
+static int dw_mipi_dsi_rockchip_dphy_bind(struct device *dev,
+ struct device *master,
+ void *data)
+{
+ /*
+ * Nothing to do when used as a dphy.
+ * Just make the rest of Rockchip-DRM happy
+ * by being here.
+ */
+
+ return 0;
+}
+
+static void dw_mipi_dsi_rockchip_dphy_unbind(struct device *dev,
+ struct device *master,
+ void *data)
+{
+ /* Nothing to do when used as a dphy. */
+}
+
+static const struct component_ops dw_mipi_dsi_rockchip_dphy_ops = {
+ .bind = dw_mipi_dsi_rockchip_dphy_bind,
+ .unbind = dw_mipi_dsi_rockchip_dphy_unbind,
+};
+
+static int dw_mipi_dsi_dphy_init(struct phy *phy)
+{
+ struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
+ int ret;
+
+ mutex_lock(&dsi->usage_mutex);
+
+ if (dsi->usage_mode != DW_DSI_USAGE_IDLE) {
+ DRM_DEV_ERROR(dsi->dev, "dsi controller already in use\n");
+ mutex_unlock(&dsi->usage_mutex);
+ return -EBUSY;
+ }
+
+ dsi->usage_mode = DW_DSI_USAGE_PHY;
+ mutex_unlock(&dsi->usage_mutex);
+
+ ret = component_add(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
+ if (ret < 0)
+ goto err_graph;
+
+ if (dsi->cdata->dphy_rx_init) {
+ ret = clk_prepare_enable(dsi->pclk);
+ if (ret < 0)
+ goto err_init;
+
+ ret = clk_prepare_enable(dsi->grf_clk);
+ if (ret) {
+ clk_disable_unprepare(dsi->pclk);
+ goto err_init;
+ }
+
+ ret = dsi->cdata->dphy_rx_init(phy);
+ clk_disable_unprepare(dsi->grf_clk);
+ clk_disable_unprepare(dsi->pclk);
+ if (ret < 0)
+ goto err_init;
+ }
+
+ return 0;
+
+err_init:
+ component_del(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
+err_graph:
+ mutex_lock(&dsi->usage_mutex);
+ dsi->usage_mode = DW_DSI_USAGE_IDLE;
+ mutex_unlock(&dsi->usage_mutex);
+
+ return ret;
+}
+
+static int dw_mipi_dsi_dphy_exit(struct phy *phy)
+{
+ struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
+
+ component_del(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
+
+ mutex_lock(&dsi->usage_mutex);
+ dsi->usage_mode = DW_DSI_USAGE_IDLE;
+ mutex_unlock(&dsi->usage_mutex);
+
+ return 0;
+}
+
+static int dw_mipi_dsi_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+ struct phy_configure_opts_mipi_dphy *config = &opts->mipi_dphy;
+ struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
+ int ret;
+
+ ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
+ if (ret)
+ return ret;
+
+ dsi->dphy_config = *config;
+ dsi->lane_mbps = div_u64(config->hs_clk_rate, 1000 * 1000 * 1);
+
+ return 0;
+}
+
+static int dw_mipi_dsi_dphy_power_on(struct phy *phy)
+{
+ struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
+ int i, ret;
+
+ DRM_DEV_DEBUG(dsi->dev, "lanes %d - data_rate_mbps %u\n",
+ dsi->dphy_config.lanes, dsi->lane_mbps);
+
+ i = max_mbps_to_parameter(dsi->lane_mbps);
+ if (i < 0) {
+ DRM_DEV_ERROR(dsi->dev, "failed to get parameter for %dmbps clock\n",
+ dsi->lane_mbps);
+ return i;
+ }
+
+ ret = pm_runtime_get_sync(dsi->dev);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dsi->dev, "failed to enable device: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(dsi->pclk);
+ if (ret) {
+ DRM_DEV_ERROR(dsi->dev, "Failed to enable pclk: %d\n", ret);
+ goto err_pclk;
+ }
+
+ ret = clk_prepare_enable(dsi->grf_clk);
+ if (ret) {
+ DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
+ goto err_grf_clk;
+ }
+
+ ret = clk_prepare_enable(dsi->phy_cfg_clk);
+ if (ret) {
+ DRM_DEV_ERROR(dsi->dev, "Failed to enable phy_cfg_clk: %d\n", ret);
+ goto err_phy_cfg_clk;
+ }
+
+ /* do soc-variant specific init */
+ if (dsi->cdata->dphy_rx_power_on) {
+ ret = dsi->cdata->dphy_rx_power_on(phy);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dsi->dev, "hardware-specific phy bringup failed: %d\n", ret);
+ goto err_pwr_on;
+ }
+ }
+
+ /*
+ * Configure hsfreqrange according to frequency values
+ * Set clock lane and hsfreqrange by lane0(test code 0x44)
+ */
+ dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_CLK, 0);
+ dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_0,
+ HSFREQRANGE_SEL(dppa_map[i].hsfreqrange));
+ dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_1, 0);
+ dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_2, 0);
+ dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_3, 0);
+
+ /* Normal operation */
+ dw_mipi_dsi_phy_write(dsi, 0x0, 0);
+
+ clk_disable_unprepare(dsi->phy_cfg_clk);
+ clk_disable_unprepare(dsi->grf_clk);
+
+ return ret;
+
+err_pwr_on:
+ clk_disable_unprepare(dsi->phy_cfg_clk);
+err_phy_cfg_clk:
+ clk_disable_unprepare(dsi->grf_clk);
+err_grf_clk:
+ clk_disable_unprepare(dsi->pclk);
+err_pclk:
+ pm_runtime_put(dsi->dev);
+ return ret;
+}
+
+static int dw_mipi_dsi_dphy_power_off(struct phy *phy)
+{
+ struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
+ int ret;
+
+ ret = clk_prepare_enable(dsi->grf_clk);
+ if (ret) {
+ DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
+ return ret;
+ }
+
+ if (dsi->cdata->dphy_rx_power_off) {
+ ret = dsi->cdata->dphy_rx_power_off(phy);
+ if (ret < 0)
+ DRM_DEV_ERROR(dsi->dev, "hardware-specific phy shutdown failed: %d\n", ret);
+ }
+
+ clk_disable_unprepare(dsi->grf_clk);
+ clk_disable_unprepare(dsi->pclk);
+
+ pm_runtime_put(dsi->dev);
+
+ return ret;
+}
+
+static const struct phy_ops dw_mipi_dsi_dphy_ops = {
+ .configure = dw_mipi_dsi_dphy_configure,
+ .power_on = dw_mipi_dsi_dphy_power_on,
+ .power_off = dw_mipi_dsi_dphy_power_off,
+ .init = dw_mipi_dsi_dphy_init,
+ .exit = dw_mipi_dsi_dphy_exit,
+};
+
static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct dw_mipi_dsi_rockchip *dsi;
+ struct phy_provider *phy_provider;
struct resource *res;
const struct rockchip_dw_dsi_chip_data *cdata =
of_device_get_match_data(dev);
@@ -1065,6 +1321,13 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
return ret;
}
+ dsi->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(dsi->pclk)) {
+ ret = PTR_ERR(dsi->pclk);
+ DRM_DEV_ERROR(dev, "Unable to get pclk: %d\n", ret);
+ return ret;
+ }
+
dsi->pllref_clk = devm_clk_get(dev, "ref");
if (IS_ERR(dsi->pllref_clk)) {
if (dsi->phy) {
@@ -1115,6 +1378,19 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
dsi->pdata.priv_data = dsi;
platform_set_drvdata(pdev, dsi);
+ mutex_init(&dsi->usage_mutex);
+
+ dsi->dphy = devm_phy_create(dev, NULL, &dw_mipi_dsi_dphy_ops);
+ if (IS_ERR(dsi->dphy)) {
+ DRM_DEV_ERROR(&pdev->dev, "failed to create PHY\n");
+ return PTR_ERR(dsi->dphy);
+ }
+
+ phy_set_drvdata(dsi->dphy, dsi);
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
dsi->dmd = dw_mipi_dsi_probe(pdev, &dsi->pdata);
if (IS_ERR(dsi->dmd)) {
ret = PTR_ERR(dsi->dmd);
@@ -1178,6 +1454,75 @@ static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = {
{ /* sentinel */ }
};
+static int rk3399_dphy_tx1rx1_init(struct phy *phy)
+{
+ struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
+
+ /*
+ * Set TX1RX1 source to isp1.
+ * Assume ISP0 is supplied by the RX0 dphy.
+ */
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
+ HIWORD_UPDATE(0, RK3399_TXRX_SRC_SEL_ISP0));
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
+ HIWORD_UPDATE(0, RK3399_TXRX_MASTERSLAVEZ));
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
+ HIWORD_UPDATE(0, RK3399_TXRX_BASEDIR));
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
+ HIWORD_UPDATE(0, RK3399_DSI1_ENABLE));
+
+ return 0;
+}
+
+static int rk3399_dphy_tx1rx1_power_on(struct phy *phy)
+{
+ struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
+
+ /* tester reset pulse */
+ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_TESTCLR);
+ usleep_range(100, 150);
+
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
+ HIWORD_UPDATE(0, RK3399_TXRX_MASTERSLAVEZ));
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
+ HIWORD_UPDATE(RK3399_TXRX_BASEDIR, RK3399_TXRX_BASEDIR));
+
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
+ HIWORD_UPDATE(0, RK3399_DSI1_FORCERXMODE));
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
+ HIWORD_UPDATE(0, RK3399_DSI1_FORCETXSTOPMODE));
+
+ /* Disable lane turn around, which is ignored in receive mode */
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
+ HIWORD_UPDATE(0, RK3399_TXRX_TURNREQUEST));
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
+ HIWORD_UPDATE(RK3399_DSI1_TURNDISABLE,
+ RK3399_DSI1_TURNDISABLE));
+ usleep_range(100, 150);
+
+ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
+ usleep_range(100, 150);
+
+ /* Enable dphy lanes */
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
+ HIWORD_UPDATE(GENMASK(dsi->dphy_config.lanes - 1, 0),
+ RK3399_DSI1_ENABLE));
+
+ usleep_range(100, 150);
+
+ return 0;
+}
+
+static int rk3399_dphy_tx1rx1_power_off(struct phy *phy)
+{
+ struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
+
+ regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
+ HIWORD_UPDATE(0, RK3399_DSI1_ENABLE));
+
+ return 0;
+}
+
static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
{
.reg = 0xff960000,
@@ -1220,6 +1565,10 @@ static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
.max_data_lanes = 4,
+
+ .dphy_rx_init = rk3399_dphy_tx1rx1_init,
+ .dphy_rx_power_on = rk3399_dphy_tx1rx1_power_on,
+ .dphy_rx_power_off = rk3399_dphy_tx1rx1_power_off,
},
{ /* sentinel */ }
};
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index b730b8d5d949..bfba9793d238 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -116,7 +116,7 @@ static int rockchip_drm_bind(struct device *dev)
int ret;
/* Remove existing drivers that may own the framebuffer memory. */
- ret = drm_aperture_remove_framebuffers(false, "rockchip-drm-fb");
+ ret = drm_aperture_remove_framebuffers(false, &rockchip_drm_driver);
if (ret) {
DRM_DEV_ERROR(dev,
"Failed to remove existing framebuffers - %d.\n",
@@ -162,12 +162,6 @@ static int rockchip_drm_bind(struct device *dev)
drm_mode_config_reset(drm_dev);
- /*
- * enable drm irq mode.
- * - with irq_enabled = true, we can use the vblank feature.
- */
- drm_dev->irq_enabled = true;
-
ret = rockchip_drm_fbdev_init(drm_dev);
if (ret)
goto err_unbind_all;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index f5b9028a16a3..ba9e14da41b4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1110,7 +1110,6 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = {
.atomic_disable = vop_plane_atomic_disable,
.atomic_async_check = vop_plane_atomic_async_check,
.atomic_async_update = vop_plane_atomic_async_update,
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
};
static const struct drm_plane_funcs vop_plane_funcs = {
diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 489d63c05c0d..551653940e39 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -636,11 +636,8 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
}
} else {
ret = drm_bridge_attach(encoder, lvds->bridge, NULL, 0);
- if (ret) {
- DRM_DEV_ERROR(drm_dev->dev,
- "failed to attach bridge: %d\n", ret);
+ if (ret)
goto err_free_encoder;
- }
}
pm_runtime_enable(dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c
index c079714477d8..d691d9bef8e7 100644
--- a/drivers/gpu/drm/rockchip/rockchip_rgb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c
@@ -143,11 +143,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
rgb->bridge = bridge;
ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0);
- if (ret) {
- DRM_DEV_ERROR(drm_dev->dev,
- "failed to attach bridge: %d\n", ret);
+ if (ret)
goto err_free_encoder;
- }
return rgb;
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index a2a953693b45..67382621b429 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -232,7 +232,7 @@ static void drm_sched_start_timeout(struct drm_gpu_scheduler *sched)
{
if (sched->timeout != MAX_SCHEDULE_TIMEOUT &&
!list_empty(&sched->pending_list))
- schedule_delayed_work(&sched->work_tdr, sched->timeout);
+ queue_delayed_work(sched->timeout_wq, &sched->work_tdr, sched->timeout);
}
/**
@@ -244,7 +244,7 @@ static void drm_sched_start_timeout(struct drm_gpu_scheduler *sched)
*/
void drm_sched_fault(struct drm_gpu_scheduler *sched)
{
- mod_delayed_work(system_wq, &sched->work_tdr, 0);
+ mod_delayed_work(sched->timeout_wq, &sched->work_tdr, 0);
}
EXPORT_SYMBOL(drm_sched_fault);
@@ -270,7 +270,7 @@ unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched)
* Modify the timeout to an arbitrarily large value. This also prevents
* the timeout to be restarted when new submissions arrive
*/
- if (mod_delayed_work(system_wq, &sched->work_tdr, MAX_SCHEDULE_TIMEOUT)
+ if (mod_delayed_work(sched->timeout_wq, &sched->work_tdr, MAX_SCHEDULE_TIMEOUT)
&& time_after(sched_timeout, now))
return sched_timeout - now;
else
@@ -294,7 +294,7 @@ void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched,
if (list_empty(&sched->pending_list))
cancel_delayed_work(&sched->work_tdr);
else
- mod_delayed_work(system_wq, &sched->work_tdr, remaining);
+ mod_delayed_work(sched->timeout_wq, &sched->work_tdr, remaining);
spin_unlock(&sched->job_list_lock);
}
@@ -802,10 +802,10 @@ static int drm_sched_main(void *param)
sched_job = drm_sched_entity_pop_job(entity);
- complete(&entity->entity_idle);
-
- if (!sched_job)
+ if (!sched_job) {
+ complete(&entity->entity_idle);
continue;
+ }
s_fence = sched_job->s_fence;
@@ -814,6 +814,7 @@ static int drm_sched_main(void *param)
trace_drm_run_job(sched_job, entity);
fence = sched->ops->run_job(sched_job);
+ complete(&entity->entity_idle);
drm_sched_fence_scheduled(s_fence);
if (!IS_ERR_OR_NULL(fence)) {
@@ -846,6 +847,8 @@ static int drm_sched_main(void *param)
* @hw_submission: number of hw submissions that can be in flight
* @hang_limit: number of times to allow a job to hang before dropping it
* @timeout: timeout value in jiffies for the scheduler
+ * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is
+ * used
* @score: optional score atomic shared with other schedulers
* @name: name used for debugging
*
@@ -853,7 +856,8 @@ static int drm_sched_main(void *param)
*/
int drm_sched_init(struct drm_gpu_scheduler *sched,
const struct drm_sched_backend_ops *ops,
- unsigned hw_submission, unsigned hang_limit, long timeout,
+ unsigned hw_submission, unsigned hang_limit,
+ long timeout, struct workqueue_struct *timeout_wq,
atomic_t *score, const char *name)
{
int i, ret;
@@ -861,6 +865,7 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
sched->hw_submission_limit = hw_submission;
sched->name = name;
sched->timeout = timeout;
+ sched->timeout_wq = timeout_wq ? : system_wq;
sched->hang_limit = hang_limit;
sched->score = score ? score : &sched->_score;
for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_COUNT; i++)
diff --git a/drivers/gpu/drm/selftests/test-drm_damage_helper.c b/drivers/gpu/drm/selftests/test-drm_damage_helper.c
index 9d2bcdf8bc29..1c19a5d3eefb 100644
--- a/drivers/gpu/drm/selftests/test-drm_damage_helper.c
+++ b/drivers/gpu/drm/selftests/test-drm_damage_helper.c
@@ -6,9 +6,37 @@
#define pr_fmt(fmt) "drm_damage_helper: " fmt
#include <drm/drm_damage_helper.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_drv.h>
#include "test-drm_modeset_common.h"
+struct drm_driver mock_driver;
+static struct drm_device mock_device;
+static struct drm_object_properties mock_obj_props;
+static struct drm_plane mock_plane;
+static struct drm_property mock_prop;
+
+static void mock_setup(struct drm_plane_state *state)
+{
+ static bool setup_done = false;
+
+ state->plane = &mock_plane;
+
+ if (setup_done)
+ return;
+
+ /* just enough so that drm_plane_enable_fb_damage_clips() works */
+ mock_device.driver = &mock_driver;
+ mock_device.mode_config.prop_fb_damage_clips = &mock_prop;
+ mock_plane.dev = &mock_device;
+ mock_plane.base.properties = &mock_obj_props;
+ mock_prop.base.id = 1; /* 0 is an invalid id */
+ mock_prop.dev = &mock_device;
+
+ drm_plane_enable_fb_damage_clips(&mock_plane);
+}
+
static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2,
int y2)
{
@@ -70,23 +98,29 @@ static bool check_damage_clip(struct drm_plane_state *state, struct drm_rect *r,
return true;
}
+const struct drm_framebuffer fb = {
+ .width = 2048,
+ .height = 2048
+};
+
+/* common mocked structs many tests need */
+#define MOCK_VARIABLES() \
+ struct drm_plane_state old_state; \
+ struct drm_plane_state state = { \
+ .crtc = ZERO_SIZE_PTR, \
+ .fb = (struct drm_framebuffer *) &fb, \
+ .visible = true, \
+ }; \
+ mock_setup(&old_state); \
+ mock_setup(&state);
+
int igt_damage_iter_no_damage(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src same as fb size. */
set_plane_src(&old_state, 0, 0, fb.width << 16, fb.height << 16);
@@ -104,20 +138,10 @@ int igt_damage_iter_no_damage(void *ignored)
int igt_damage_iter_no_damage_fractional_src(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src has fractional part. */
set_plane_src(&old_state, 0x3fffe, 0x3fffe,
@@ -137,20 +161,10 @@ int igt_damage_iter_no_damage_fractional_src(void *ignored)
int igt_damage_iter_no_damage_src_moved(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src moved since old plane state. */
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
@@ -169,20 +183,10 @@ int igt_damage_iter_no_damage_src_moved(void *ignored)
int igt_damage_iter_no_damage_fractional_src_moved(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src has fractional part and it moved since old plane state. */
set_plane_src(&old_state, 0x3fffe, 0x3fffe,
@@ -202,20 +206,14 @@ int igt_damage_iter_no_damage_fractional_src_moved(void *ignored)
int igt_damage_iter_no_damage_not_visible(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
+ MOCK_VARIABLES();
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = false,
- };
+ state.visible = false;
+
+ mock_setup(&old_state);
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
@@ -231,19 +229,12 @@ int igt_damage_iter_no_damage_not_visible(void *ignored)
int igt_damage_iter_no_damage_no_crtc(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
+ MOCK_VARIABLES();
- struct drm_plane_state state = {
- .crtc = 0,
- .fb = &fb,
- };
+ state.crtc = NULL;
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
@@ -268,6 +259,8 @@ int igt_damage_iter_no_damage_no_fb(void *ignored)
.fb = 0,
};
+ mock_setup(&old_state);
+
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
@@ -282,22 +275,12 @@ int igt_damage_iter_no_damage_no_fb(void *ignored)
int igt_damage_iter_simple_damage(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
@@ -318,22 +301,12 @@ int igt_damage_iter_simple_damage(void *ignored)
int igt_damage_iter_single_damage(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
@@ -353,22 +326,12 @@ int igt_damage_iter_single_damage(void *ignored)
int igt_damage_iter_single_damage_intersect_src(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
@@ -389,22 +352,12 @@ int igt_damage_iter_single_damage_intersect_src(void *ignored)
int igt_damage_iter_single_damage_outside_src(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
@@ -424,22 +377,12 @@ int igt_damage_iter_single_damage_outside_src(void *ignored)
int igt_damage_iter_single_damage_fractional_src(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src has fractional part. */
set_plane_src(&old_state, 0x40002, 0x40002,
@@ -462,22 +405,12 @@ int igt_damage_iter_single_damage_fractional_src(void *ignored)
int igt_damage_iter_single_damage_intersect_fractional_src(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src has fractional part. */
set_plane_src(&old_state, 0x40002, 0x40002,
@@ -501,22 +434,12 @@ int igt_damage_iter_single_damage_intersect_fractional_src(void *ignored)
int igt_damage_iter_single_damage_outside_fractional_src(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src has fractional part. */
set_plane_src(&old_state, 0x40002, 0x40002,
@@ -539,22 +462,12 @@ int igt_damage_iter_single_damage_outside_fractional_src(void *ignored)
int igt_damage_iter_single_damage_src_moved(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src moved since old plane state. */
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
@@ -576,22 +489,12 @@ int igt_damage_iter_single_damage_src_moved(void *ignored)
int igt_damage_iter_single_damage_fractional_src_moved(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage;
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
/* Plane src with fractional part moved since old plane state. */
set_plane_src(&old_state, 0x3fffe, 0x3fffe,
@@ -615,22 +518,12 @@ int igt_damage_iter_single_damage_fractional_src_moved(void *ignored)
int igt_damage_iter_damage(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage[2];
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
@@ -656,22 +549,12 @@ int igt_damage_iter_damage(void *ignored)
int igt_damage_iter_damage_one_intersect(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage[2];
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
set_plane_src(&old_state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
@@ -699,22 +582,12 @@ int igt_damage_iter_damage_one_intersect(void *ignored)
int igt_damage_iter_damage_one_outside(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage[2];
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
@@ -736,22 +609,12 @@ int igt_damage_iter_damage_one_outside(void *ignored)
int igt_damage_iter_damage_src_moved(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage[2];
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
-
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = true,
- };
+ MOCK_VARIABLES();
set_plane_src(&old_state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
@@ -775,22 +638,14 @@ int igt_damage_iter_damage_src_moved(void *ignored)
int igt_damage_iter_damage_not_visible(void *ignored)
{
struct drm_atomic_helper_damage_iter iter;
- struct drm_plane_state old_state;
struct drm_property_blob damage_blob;
struct drm_mode_rect damage[2];
struct drm_rect clip;
uint32_t num_hits = 0;
- struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
+ MOCK_VARIABLES();
- struct drm_plane_state state = {
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .visible = false,
- };
+ state.visible = false;
set_plane_src(&old_state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
index 0a02b7092c04..7db01904d18d 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
@@ -18,7 +18,6 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
@@ -130,7 +129,6 @@ DEFINE_DRM_GEM_CMA_FOPS(shmob_drm_fops);
static const struct drm_driver shmob_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET,
- .irq_handler = shmob_drm_irq,
DRM_GEM_CMA_DRIVER_OPS,
.fops = &shmob_drm_fops,
.name = "shmob-drm",
@@ -183,7 +181,7 @@ static int shmob_drm_remove(struct platform_device *pdev)
drm_dev_unregister(ddev);
drm_kms_helper_poll_fini(ddev);
- drm_irq_uninstall(ddev);
+ free_irq(sdev->irq, ddev);
drm_dev_put(ddev);
return 0;
@@ -258,7 +256,13 @@ static int shmob_drm_probe(struct platform_device *pdev)
goto err_modeset_cleanup;
}
- ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ goto err_modeset_cleanup;
+ sdev->irq = ret;
+
+ ret = request_irq(sdev->irq, shmob_drm_irq, 0, ddev->driver->name,
+ ddev);
if (ret < 0) {
dev_err(&pdev->dev, "failed to install IRQ handler\n");
goto err_modeset_cleanup;
@@ -275,7 +279,7 @@ static int shmob_drm_probe(struct platform_device *pdev)
return 0;
err_irq_uninstall:
- drm_irq_uninstall(ddev);
+ free_irq(sdev->irq, ddev);
err_modeset_cleanup:
drm_kms_helper_poll_fini(ddev);
err_free_drm_dev:
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.h b/drivers/gpu/drm/shmobile/shmob_drm_drv.h
index 80dc4b1020aa..4964ddd5ab74 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.h
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.h
@@ -29,6 +29,7 @@ struct shmob_drm_device {
u32 lddckr;
u32 ldmt1r;
+ unsigned int irq;
spinlock_t irq_lock; /* Protects hardware LDINTR register */
struct drm_device *ddev;
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index 319962a2c17b..9caaf3ccfabe 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -145,8 +145,6 @@ static int sti_compositor_bind(struct device *dev,
}
drm_vblank_init(drm_dev, crtc_id);
- /* Allow usage of vblank without having to call drm_irq_install */
- drm_dev->irq_enabled = 1;
return 0;
}
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index ddb4184f0726..b6ee8a82e656 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -463,10 +463,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
drm_bridge_add(bridge);
err = drm_bridge_attach(encoder, bridge, NULL, 0);
- if (err) {
- DRM_ERROR("Failed to attach bridge\n");
+ if (err)
return err;
- }
dvo->bridge = bridge;
connector->encoder = encoder;
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
index 8399d337589d..32cb41b2202f 100644
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
@@ -309,14 +309,23 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
return 0;
}
+#define DSI_PHY_DELAY(fp, vp, mbps) DIV_ROUND_UP((fp) * (mbps) + 1000 * (vp), 8000)
+
static int
dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
struct dw_mipi_dsi_dphy_timing *timing)
{
- timing->clk_hs2lp = 0x40;
- timing->clk_lp2hs = 0x40;
- timing->data_hs2lp = 0x40;
- timing->data_lp2hs = 0x40;
+ /*
+ * From STM32MP157 datasheet, valid for STM32F469, STM32F7x9, STM32H747
+ * phy_clkhs2lp_time = (272+136*UI)/(8*UI)
+ * phy_clklp2hs_time = (512+40*UI)/(8*UI)
+ * phy_hs2lp_time = (192+64*UI)/(8*UI)
+ * phy_lp2hs_time = (256+32*UI)/(8*UI)
+ */
+ timing->clk_hs2lp = DSI_PHY_DELAY(272, 136, lane_mbps);
+ timing->clk_lp2hs = DSI_PHY_DELAY(512, 40, lane_mbps);
+ timing->data_hs2lp = DSI_PHY_DELAY(192, 64, lane_mbps);
+ timing->data_lp2hs = DSI_PHY_DELAY(256, 32, lane_mbps);
return 0;
}
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 08b71248044d..195de30eb90c 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -947,7 +947,6 @@ static const struct drm_plane_funcs ltdc_plane_funcs = {
};
static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = ltdc_plane_atomic_check,
.atomic_update = ltdc_plane_atomic_update,
.atomic_disable = ltdc_plane_atomic_disable,
@@ -1122,8 +1121,9 @@ static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
ret = drm_bridge_attach(encoder, bridge, NULL, 0);
if (ret) {
- drm_encoder_cleanup(encoder);
- return -EINVAL;
+ if (ret != -EPROBE_DEFER)
+ drm_encoder_cleanup(encoder);
+ return ret;
}
DRM_DEBUG_DRIVER("Bridge encoder:%d created\n", encoder->base.id);
@@ -1266,7 +1266,8 @@ int ltdc_load(struct drm_device *ddev)
if (bridge) {
ret = ltdc_encoder_init(ddev, bridge);
if (ret) {
- DRM_ERROR("init encoder endpoint %d\n", i);
+ if (ret != -EPROBE_DEFER)
+ DRM_ERROR("init encoder endpoint %d\n", i);
goto err;
}
}
@@ -1339,9 +1340,6 @@ int ltdc_load(struct drm_device *ddev)
goto err;
}
- /* Allow usage of vblank without having to call drm_irq_install */
- ddev->irq_enabled = 1;
-
clk_disable_unprepare(ldev->pixel_clk);
pinctrl_pm_select_sleep_state(ddev->dev);
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index af335f58bdfc..54dd562e294c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -97,10 +97,8 @@ static int sun4i_drv_bind(struct device *dev)
if (ret)
goto cleanup_mode_config;
- drm->irq_enabled = true;
-
/* Remove early framebuffers (ie. simplefb) */
- ret = drm_aperture_remove_framebuffers(false, "sun4i-drm-fb");
+ ret = drm_aperture_remove_framebuffers(false, &sun4i_drv_driver);
if (ret)
goto cleanup_mode_config;
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 11771bdd6e7c..929e95f86b5b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -127,7 +127,6 @@ static bool sun4i_layer_format_mod_supported(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_disable = sun4i_backend_layer_atomic_disable,
.atomic_update = sun4i_backend_layer_atomic_update,
};
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
index ac570437172e..6716e895ae8a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_lvds.c
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -142,10 +142,8 @@ int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
if (bridge) {
ret = drm_bridge_attach(encoder, bridge, NULL, 0);
- if (ret) {
- dev_err(drm->dev, "Couldn't attach our bridge\n");
+ if (ret)
goto err_cleanup_connector;
- }
}
return 0;
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index e172426eb7e9..dfb6acc42f02 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -234,10 +234,8 @@ int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon)
if (rgb->bridge) {
ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0);
- if (ret) {
- dev_err(drm->dev, "Couldn't attach our bridge\n");
+ if (ret)
goto err_cleanup_connector;
- }
}
return 0;
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index e779855bcd6e..7845c2a53a7f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -332,7 +332,6 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = sun8i_ui_layer_atomic_check,
.atomic_disable = sun8i_ui_layer_atomic_disable,
.atomic_update = sun8i_ui_layer_atomic_update,
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 1c86c2dd0bbf..bb7c43036dfa 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -436,7 +436,6 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = sun8i_vi_layer_atomic_check,
.atomic_disable = sun8i_vi_layer_atomic_disable,
.atomic_update = sun8i_vi_layer_atomic_update,
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index 5043dcaf1cf9..1650a448eabd 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -9,6 +9,7 @@ config DRM_TEGRA
select DRM_MIPI_DSI
select DRM_PANEL
select TEGRA_HOST1X
+ select INTERCONNECT
select IOMMU_IOVA
select CEC_CORE if CEC_NOTIFIER
help
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index d6cf202414f0..d801909182cf 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -3,6 +3,9 @@ ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
tegra-drm-y := \
drm.o \
+ uapi.o \
+ submit.o \
+ firewall.o \
gem.o \
fb.o \
dp.o \
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 51bbbc42a144..16c7aabb94d3 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -8,6 +8,7 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/iommu.h>
+#include <linux/interconnect.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
@@ -618,9 +619,14 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
struct tegra_dc *dc = to_tegra_dc(new_plane_state->crtc);
int err;
+ plane_state->peak_memory_bandwidth = 0;
+ plane_state->avg_memory_bandwidth = 0;
+
/* no need for further checks if the plane is being disabled */
- if (!new_plane_state->crtc)
+ if (!new_plane_state->crtc) {
+ plane_state->total_peak_memory_bandwidth = 0;
return 0;
+ }
err = tegra_plane_format(new_plane_state->fb->format->format,
&plane_state->format,
@@ -808,6 +814,12 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
formats = dc->soc->primary_formats;
modifiers = dc->soc->modifiers;
+ err = tegra_plane_interconnect_init(plane);
+ if (err) {
+ kfree(plane);
+ return ERR_PTR(err);
+ }
+
err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
&tegra_plane_funcs, formats,
num_formats, modifiers, type, NULL);
@@ -845,12 +857,18 @@ static int tegra_cursor_atomic_check(struct drm_plane *plane,
{
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
plane);
+ struct tegra_plane_state *plane_state = to_tegra_plane_state(new_plane_state);
struct tegra_plane *tegra = to_tegra_plane(plane);
int err;
+ plane_state->peak_memory_bandwidth = 0;
+ plane_state->avg_memory_bandwidth = 0;
+
/* no need for further checks if the plane is being disabled */
- if (!new_plane_state->crtc)
+ if (!new_plane_state->crtc) {
+ plane_state->total_peak_memory_bandwidth = 0;
return 0;
+ }
/* scaling not supported for cursor */
if ((new_plane_state->src_w >> 16 != new_plane_state->crtc_w) ||
@@ -1030,6 +1048,12 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
if (!dc->soc->has_nvdisplay) {
num_formats = ARRAY_SIZE(tegra_legacy_cursor_plane_formats);
formats = tegra_legacy_cursor_plane_formats;
+
+ err = tegra_plane_interconnect_init(plane);
+ if (err) {
+ kfree(plane);
+ return ERR_PTR(err);
+ }
} else {
num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
formats = tegra_cursor_plane_formats;
@@ -1149,6 +1173,12 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
num_formats = dc->soc->num_overlay_formats;
formats = dc->soc->overlay_formats;
+ err = tegra_plane_interconnect_init(plane);
+ if (err) {
+ kfree(plane);
+ return ERR_PTR(err);
+ }
+
if (!cursor)
type = DRM_PLANE_TYPE_OVERLAY;
else
@@ -1572,6 +1602,11 @@ static int tegra_dc_show_stats(struct seq_file *s, void *data)
seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
+ seq_printf(s, "frames total: %lu\n", dc->stats.frames_total);
+ seq_printf(s, "vblank total: %lu\n", dc->stats.vblank_total);
+ seq_printf(s, "underflow total: %lu\n", dc->stats.underflow_total);
+ seq_printf(s, "overflow total: %lu\n", dc->stats.overflow_total);
+
return 0;
}
@@ -1804,6 +1839,106 @@ static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout)
return -ETIMEDOUT;
}
+static void
+tegra_crtc_update_memory_bandwidth(struct drm_crtc *crtc,
+ struct drm_atomic_state *state,
+ bool prepare_bandwidth_transition)
+{
+ const struct tegra_plane_state *old_tegra_state, *new_tegra_state;
+ const struct tegra_dc_state *old_dc_state, *new_dc_state;
+ u32 i, new_avg_bw, old_avg_bw, new_peak_bw, old_peak_bw;
+ const struct drm_plane_state *old_plane_state;
+ const struct drm_crtc_state *old_crtc_state;
+ struct tegra_dc_window window, old_window;
+ struct tegra_dc *dc = to_tegra_dc(crtc);
+ struct tegra_plane *tegra;
+ struct drm_plane *plane;
+
+ if (dc->soc->has_nvdisplay)
+ return;
+
+ old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
+ old_dc_state = to_const_dc_state(old_crtc_state);
+ new_dc_state = to_const_dc_state(crtc->state);
+
+ if (!crtc->state->active) {
+ if (!old_crtc_state->active)
+ return;
+
+ /*
+ * When CRTC is disabled on DPMS, the state of attached planes
+ * is kept unchanged. Hence we need to enforce removal of the
+ * bandwidths from the ICC paths.
+ */
+ drm_atomic_crtc_for_each_plane(plane, crtc) {
+ tegra = to_tegra_plane(plane);
+
+ icc_set_bw(tegra->icc_mem, 0, 0);
+ icc_set_bw(tegra->icc_mem_vfilter, 0, 0);
+ }
+
+ return;
+ }
+
+ for_each_old_plane_in_state(old_crtc_state->state, plane,
+ old_plane_state, i) {
+ old_tegra_state = to_const_tegra_plane_state(old_plane_state);
+ new_tegra_state = to_const_tegra_plane_state(plane->state);
+ tegra = to_tegra_plane(plane);
+
+ /*
+ * We're iterating over the global atomic state and it contains
+ * planes from another CRTC, hence we need to filter out the
+ * planes unrelated to this CRTC.
+ */
+ if (tegra->dc != dc)
+ continue;
+
+ new_avg_bw = new_tegra_state->avg_memory_bandwidth;
+ old_avg_bw = old_tegra_state->avg_memory_bandwidth;
+
+ new_peak_bw = new_tegra_state->total_peak_memory_bandwidth;
+ old_peak_bw = old_tegra_state->total_peak_memory_bandwidth;
+
+ /*
+ * See the comment related to !crtc->state->active above,
+ * which explains why bandwidths need to be updated when
+ * CRTC is turning ON.
+ */
+ if (new_avg_bw == old_avg_bw && new_peak_bw == old_peak_bw &&
+ old_crtc_state->active)
+ continue;
+
+ window.src.h = drm_rect_height(&plane->state->src) >> 16;
+ window.dst.h = drm_rect_height(&plane->state->dst);
+
+ old_window.src.h = drm_rect_height(&old_plane_state->src) >> 16;
+ old_window.dst.h = drm_rect_height(&old_plane_state->dst);
+
+ /*
+ * During the preparation phase (atomic_begin), the memory
+ * freq should go high before the DC changes are committed
+ * if bandwidth requirement goes up, otherwise memory freq
+ * should to stay high if BW requirement goes down. The
+ * opposite applies to the completion phase (post_commit).
+ */
+ if (prepare_bandwidth_transition) {
+ new_avg_bw = max(old_avg_bw, new_avg_bw);
+ new_peak_bw = max(old_peak_bw, new_peak_bw);
+
+ if (tegra_plane_use_vertical_filtering(tegra, &old_window))
+ window = old_window;
+ }
+
+ icc_set_bw(tegra->icc_mem, new_avg_bw, new_peak_bw);
+
+ if (tegra_plane_use_vertical_filtering(tegra, &window))
+ icc_set_bw(tegra->icc_mem_vfilter, new_avg_bw, new_peak_bw);
+ else
+ icc_set_bw(tegra->icc_mem_vfilter, 0, 0);
+ }
+}
+
static void tegra_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@@ -1985,6 +2120,8 @@ static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
{
unsigned long flags;
+ tegra_crtc_update_memory_bandwidth(crtc, state, true);
+
if (crtc->state->event) {
spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -2017,7 +2154,207 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
}
+static bool tegra_plane_is_cursor(const struct drm_plane_state *state)
+{
+ const struct tegra_dc_soc_info *soc = to_tegra_dc(state->crtc)->soc;
+ const struct drm_format_info *fmt = state->fb->format;
+ unsigned int src_w = drm_rect_width(&state->src) >> 16;
+ unsigned int dst_w = drm_rect_width(&state->dst);
+
+ if (state->plane->type != DRM_PLANE_TYPE_CURSOR)
+ return false;
+
+ if (soc->supports_cursor)
+ return true;
+
+ if (src_w != dst_w || fmt->num_planes != 1 || src_w * fmt->cpp[0] > 256)
+ return false;
+
+ return true;
+}
+
+static unsigned long
+tegra_plane_overlap_mask(struct drm_crtc_state *state,
+ const struct drm_plane_state *plane_state)
+{
+ const struct drm_plane_state *other_state;
+ const struct tegra_plane *tegra;
+ unsigned long overlap_mask = 0;
+ struct drm_plane *plane;
+ struct drm_rect rect;
+
+ if (!plane_state->visible || !plane_state->fb)
+ return 0;
+
+ /*
+ * Data-prefetch FIFO will easily help to overcome temporal memory
+ * pressure if other plane overlaps with the cursor plane.
+ */
+ if (tegra_plane_is_cursor(plane_state))
+ return 0;
+
+ drm_atomic_crtc_state_for_each_plane_state(plane, other_state, state) {
+ rect = plane_state->dst;
+
+ tegra = to_tegra_plane(other_state->plane);
+
+ if (!other_state->visible || !other_state->fb)
+ continue;
+
+ /*
+ * Ignore cursor plane overlaps because it's not practical to
+ * assume that it contributes to the bandwidth in overlapping
+ * area if window width is small.
+ */
+ if (tegra_plane_is_cursor(other_state))
+ continue;
+
+ if (drm_rect_intersect(&rect, &other_state->dst))
+ overlap_mask |= BIT(tegra->index);
+ }
+
+ return overlap_mask;
+}
+
+static int tegra_crtc_calculate_memory_bandwidth(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ ulong overlap_mask[TEGRA_DC_LEGACY_PLANES_NUM] = {}, mask;
+ u32 plane_peak_bw[TEGRA_DC_LEGACY_PLANES_NUM] = {};
+ bool all_planes_overlap_simultaneously = true;
+ const struct tegra_plane_state *tegra_state;
+ const struct drm_plane_state *plane_state;
+ struct tegra_dc *dc = to_tegra_dc(crtc);
+ const struct drm_crtc_state *old_state;
+ struct drm_crtc_state *new_state;
+ struct tegra_plane *tegra;
+ struct drm_plane *plane;
+
+ /*
+ * The nv-display uses shared planes. The algorithm below assumes
+ * maximum 3 planes per-CRTC, this assumption isn't applicable to
+ * the nv-display. Note that T124 support has additional windows,
+ * but currently they aren't supported by the driver.
+ */
+ if (dc->soc->has_nvdisplay)
+ return 0;
+
+ new_state = drm_atomic_get_new_crtc_state(state, crtc);
+ old_state = drm_atomic_get_old_crtc_state(state, crtc);
+
+ /*
+ * For overlapping planes pixel's data is fetched for each plane at
+ * the same time, hence bandwidths are accumulated in this case.
+ * This needs to be taken into account for calculating total bandwidth
+ * consumed by all planes.
+ *
+ * Here we get the overlapping state of each plane, which is a
+ * bitmask of plane indices telling with what planes there is an
+ * overlap. Note that bitmask[plane] includes BIT(plane) in order
+ * to make further code nicer and simpler.
+ */
+ drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, new_state) {
+ tegra_state = to_const_tegra_plane_state(plane_state);
+ tegra = to_tegra_plane(plane);
+
+ if (WARN_ON_ONCE(tegra->index >= TEGRA_DC_LEGACY_PLANES_NUM))
+ return -EINVAL;
+
+ plane_peak_bw[tegra->index] = tegra_state->peak_memory_bandwidth;
+ mask = tegra_plane_overlap_mask(new_state, plane_state);
+ overlap_mask[tegra->index] = mask;
+
+ if (hweight_long(mask) != 3)
+ all_planes_overlap_simultaneously = false;
+ }
+
+ /*
+ * Then we calculate maximum bandwidth of each plane state.
+ * The bandwidth includes the plane BW + BW of the "simultaneously"
+ * overlapping planes, where "simultaneously" means areas where DC
+ * fetches from the planes simultaneously during of scan-out process.
+ *
+ * For example, if plane A overlaps with planes B and C, but B and C
+ * don't overlap, then the peak bandwidth will be either in area where
+ * A-and-B or A-and-C planes overlap.
+ *
+ * The plane_peak_bw[] contains peak memory bandwidth values of
+ * each plane, this information is needed by interconnect provider
+ * in order to set up latency allowance based on the peak BW, see
+ * tegra_crtc_update_memory_bandwidth().
+ */
+ drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, new_state) {
+ u32 i, old_peak_bw, new_peak_bw, overlap_bw = 0;
+
+ /*
+ * Note that plane's atomic check doesn't touch the
+ * total_peak_memory_bandwidth of enabled plane, hence the
+ * current state contains the old bandwidth state from the
+ * previous CRTC commit.
+ */
+ tegra_state = to_const_tegra_plane_state(plane_state);
+ tegra = to_tegra_plane(plane);
+
+ for_each_set_bit(i, &overlap_mask[tegra->index], 3) {
+ if (i == tegra->index)
+ continue;
+
+ if (all_planes_overlap_simultaneously)
+ overlap_bw += plane_peak_bw[i];
+ else
+ overlap_bw = max(overlap_bw, plane_peak_bw[i]);
+ }
+
+ new_peak_bw = plane_peak_bw[tegra->index] + overlap_bw;
+ old_peak_bw = tegra_state->total_peak_memory_bandwidth;
+
+ /*
+ * If plane's peak bandwidth changed (for example plane isn't
+ * overlapped anymore) and plane isn't in the atomic state,
+ * then add plane to the state in order to have the bandwidth
+ * updated.
+ */
+ if (old_peak_bw != new_peak_bw) {
+ struct tegra_plane_state *new_tegra_state;
+ struct drm_plane_state *new_plane_state;
+
+ new_plane_state = drm_atomic_get_plane_state(state, plane);
+ if (IS_ERR(new_plane_state))
+ return PTR_ERR(new_plane_state);
+
+ new_tegra_state = to_tegra_plane_state(new_plane_state);
+ new_tegra_state->total_peak_memory_bandwidth = new_peak_bw;
+ }
+ }
+
+ return 0;
+}
+
+static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ int err;
+
+ err = tegra_crtc_calculate_memory_bandwidth(crtc, state);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+void tegra_crtc_atomic_post_commit(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ /*
+ * Display bandwidth is allowed to go down only once hardware state
+ * is known to be armed, i.e. state was committed and VBLANK event
+ * received.
+ */
+ tegra_crtc_update_memory_bandwidth(crtc, state, false);
+}
+
static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
+ .atomic_check = tegra_crtc_atomic_check,
.atomic_begin = tegra_crtc_atomic_begin,
.atomic_flush = tegra_crtc_atomic_flush,
.atomic_enable = tegra_crtc_atomic_enable,
@@ -2036,6 +2373,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
/*
dev_dbg(dc->dev, "%s(): frame end\n", __func__);
*/
+ dc->stats.frames_total++;
dc->stats.frames++;
}
@@ -2044,6 +2382,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
*/
drm_crtc_handle_vblank(&dc->base);
+ dc->stats.vblank_total++;
dc->stats.vblank++;
}
@@ -2051,6 +2390,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
/*
dev_dbg(dc->dev, "%s(): underflow\n", __func__);
*/
+ dc->stats.underflow_total++;
dc->stats.underflow++;
}
@@ -2058,11 +2398,13 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
/*
dev_dbg(dc->dev, "%s(): overflow\n", __func__);
*/
+ dc->stats.overflow_total++;
dc->stats.overflow++;
}
if (status & HEAD_UF_INT) {
dev_dbg_ratelimited(dc->dev, "%s(): head underflow\n", __func__);
+ dc->stats.underflow_total++;
dc->stats.underflow++;
}
@@ -2343,7 +2685,9 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
.overlay_formats = tegra20_overlay_formats,
.modifiers = tegra20_modifiers,
.has_win_a_without_filters = true,
+ .has_win_b_vfilter_mem_client = true,
.has_win_c_without_vert_filter = true,
+ .plane_tiled_memory_bandwidth_x2 = false,
};
static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -2363,7 +2707,9 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
.overlay_formats = tegra20_overlay_formats,
.modifiers = tegra20_modifiers,
.has_win_a_without_filters = false,
+ .has_win_b_vfilter_mem_client = true,
.has_win_c_without_vert_filter = false,
+ .plane_tiled_memory_bandwidth_x2 = true,
};
static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -2383,7 +2729,9 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
.overlay_formats = tegra114_overlay_formats,
.modifiers = tegra20_modifiers,
.has_win_a_without_filters = false,
+ .has_win_b_vfilter_mem_client = false,
.has_win_c_without_vert_filter = false,
+ .plane_tiled_memory_bandwidth_x2 = true,
};
static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -2403,7 +2751,9 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
.overlay_formats = tegra124_overlay_formats,
.modifiers = tegra124_modifiers,
.has_win_a_without_filters = false,
+ .has_win_b_vfilter_mem_client = false,
.has_win_c_without_vert_filter = false,
+ .plane_tiled_memory_bandwidth_x2 = false,
};
static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
@@ -2423,7 +2773,9 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
.overlay_formats = tegra114_overlay_formats,
.modifiers = tegra124_modifiers,
.has_win_a_without_filters = false,
+ .has_win_b_vfilter_mem_client = false,
.has_win_c_without_vert_filter = false,
+ .plane_tiled_memory_bandwidth_x2 = false,
};
static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
@@ -2473,6 +2825,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
.has_nvdisplay = true,
.wgrps = tegra186_dc_wgrps,
.num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps),
+ .plane_tiled_memory_bandwidth_x2 = false,
};
static const struct tegra_windowgroup_soc tegra194_dc_wgrps[] = {
@@ -2522,6 +2875,7 @@ static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
.has_nvdisplay = true,
.wgrps = tegra194_dc_wgrps,
.num_wgrps = ARRAY_SIZE(tegra194_dc_wgrps),
+ .plane_tiled_memory_bandwidth_x2 = false,
};
static const struct of_device_id tegra_dc_of_match[] = {
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 5e13f1cfd749..f0cb691852a1 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -15,6 +15,8 @@
struct tegra_output;
+#define TEGRA_DC_LEGACY_PLANES_NUM 7
+
struct tegra_dc_state {
struct drm_crtc_state base;
@@ -33,11 +35,22 @@ static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)
return NULL;
}
+static inline const struct tegra_dc_state *
+to_const_dc_state(const struct drm_crtc_state *state)
+{
+ return to_dc_state((struct drm_crtc_state *)state);
+}
+
struct tegra_dc_stats {
unsigned long frames;
unsigned long vblank;
unsigned long underflow;
unsigned long overflow;
+
+ unsigned long frames_total;
+ unsigned long vblank_total;
+ unsigned long underflow_total;
+ unsigned long overflow_total;
};
struct tegra_windowgroup_soc {
@@ -66,7 +79,9 @@ struct tegra_dc_soc_info {
unsigned int num_overlay_formats;
const u64 *modifiers;
bool has_win_a_without_filters;
+ bool has_win_b_vfilter_mem_client;
bool has_win_c_without_vert_filter;
+ bool plane_tiled_memory_bandwidth_x2;
};
struct tegra_dc {
@@ -152,6 +167,8 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
struct drm_crtc_state *crtc_state,
struct clk *clk, unsigned long pclk,
unsigned int div);
+void tegra_crtc_atomic_post_commit(struct drm_crtc *crtc,
+ struct drm_atomic_state *state);
/* from rgb.c */
int tegra_dc_rgb_probe(struct tegra_dc *dc);
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index f96c237b2242..8d37d6b00562 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -21,24 +21,21 @@
#include <drm/drm_prime.h>
#include <drm/drm_vblank.h>
+#include "dc.h"
#include "drm.h"
#include "gem.h"
+#include "uapi.h"
#define DRIVER_NAME "tegra"
#define DRIVER_DESC "NVIDIA Tegra graphics"
#define DRIVER_DATE "20120330"
-#define DRIVER_MAJOR 0
+#define DRIVER_MAJOR 1
#define DRIVER_MINOR 0
#define DRIVER_PATCHLEVEL 0
#define CARVEOUT_SZ SZ_64M
#define CDMA_GATHER_FETCHES_MAX_NB 16383
-struct tegra_drm_file {
- struct idr contexts;
- struct mutex lock;
-};
-
static int tegra_atomic_check(struct drm_device *drm,
struct drm_atomic_state *state)
{
@@ -60,6 +57,17 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
.atomic_commit = drm_atomic_helper_commit,
};
+static void tegra_atomic_post_commit(struct drm_device *drm,
+ struct drm_atomic_state *old_state)
+{
+ struct drm_crtc_state *old_crtc_state __maybe_unused;
+ struct drm_crtc *crtc;
+ unsigned int i;
+
+ for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i)
+ tegra_crtc_atomic_post_commit(crtc, old_state);
+}
+
static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
{
struct drm_device *drm = old_state->dev;
@@ -79,6 +87,8 @@ static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
} else {
drm_atomic_helper_commit_tail_rpm(old_state);
}
+
+ tegra_atomic_post_commit(drm, old_state);
}
static const struct drm_mode_config_helper_funcs
@@ -94,7 +104,9 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
if (!fpriv)
return -ENOMEM;
- idr_init_base(&fpriv->contexts, 1);
+ idr_init_base(&fpriv->legacy_contexts, 1);
+ xa_init_flags(&fpriv->contexts, XA_FLAGS_ALLOC1);
+ xa_init(&fpriv->syncpoints);
mutex_init(&fpriv->lock);
filp->driver_priv = fpriv;
@@ -107,20 +119,6 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
kfree(context);
}
-static struct host1x_bo *
-host1x_bo_lookup(struct drm_file *file, u32 handle)
-{
- struct drm_gem_object *gem;
- struct tegra_bo *bo;
-
- gem = drm_gem_object_lookup(file, handle);
- if (!gem)
- return NULL;
-
- bo = to_tegra_bo(gem);
- return &bo->base;
-}
-
static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
struct drm_tegra_reloc __user *src,
struct drm_device *drm,
@@ -151,11 +149,11 @@ static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
dest->flags = HOST1X_RELOC_READ | HOST1X_RELOC_WRITE;
- dest->cmdbuf.bo = host1x_bo_lookup(file, cmdbuf);
+ dest->cmdbuf.bo = tegra_gem_lookup(file, cmdbuf);
if (!dest->cmdbuf.bo)
return -ENOENT;
- dest->target.bo = host1x_bo_lookup(file, target);
+ dest->target.bo = tegra_gem_lookup(file, target);
if (!dest->target.bo)
return -ENOENT;
@@ -193,7 +191,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
return -EINVAL;
job = host1x_job_alloc(context->channel, args->num_cmdbufs,
- args->num_relocs);
+ args->num_relocs, false);
if (!job)
return -ENOMEM;
@@ -201,6 +199,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
job->client = client;
job->class = client->class;
job->serialize = true;
+ job->syncpt_recovery = true;
/*
* Track referenced BOs so that they can be unreferenced after the
@@ -237,7 +236,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
goto fail;
}
- bo = host1x_bo_lookup(file, cmdbuf.handle);
+ bo = tegra_gem_lookup(file, cmdbuf.handle);
if (!bo) {
err = -ENOENT;
goto fail;
@@ -432,7 +431,7 @@ static int tegra_client_open(struct tegra_drm_file *fpriv,
if (err < 0)
return err;
- err = idr_alloc(&fpriv->contexts, context, 1, 0, GFP_KERNEL);
+ err = idr_alloc(&fpriv->legacy_contexts, context, 1, 0, GFP_KERNEL);
if (err < 0) {
client->ops->close_channel(context);
return err;
@@ -487,13 +486,13 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
mutex_lock(&fpriv->lock);
- context = idr_find(&fpriv->contexts, args->context);
+ context = idr_find(&fpriv->legacy_contexts, args->context);
if (!context) {
err = -EINVAL;
goto unlock;
}
- idr_remove(&fpriv->contexts, context->id);
+ idr_remove(&fpriv->legacy_contexts, context->id);
tegra_drm_context_free(context);
unlock:
@@ -512,7 +511,7 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
mutex_lock(&fpriv->lock);
- context = idr_find(&fpriv->contexts, args->context);
+ context = idr_find(&fpriv->legacy_contexts, args->context);
if (!context) {
err = -ENODEV;
goto unlock;
@@ -541,7 +540,7 @@ static int tegra_submit(struct drm_device *drm, void *data,
mutex_lock(&fpriv->lock);
- context = idr_find(&fpriv->contexts, args->context);
+ context = idr_find(&fpriv->legacy_contexts, args->context);
if (!context) {
err = -ENODEV;
goto unlock;
@@ -566,7 +565,7 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
mutex_lock(&fpriv->lock);
- context = idr_find(&fpriv->contexts, args->context);
+ context = idr_find(&fpriv->legacy_contexts, args->context);
if (!context) {
err = -ENODEV;
goto unlock;
@@ -735,10 +734,25 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
#ifdef CONFIG_DRM_TEGRA_STAGING
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create,
+ DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_OPEN, tegra_drm_ioctl_channel_open,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_CLOSE, tegra_drm_ioctl_channel_close,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_MAP, tegra_drm_ioctl_channel_map,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_UNMAP, tegra_drm_ioctl_channel_unmap,
DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap,
+ DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_SUBMIT, tegra_drm_ioctl_channel_submit,
DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_ALLOCATE, tegra_drm_ioctl_syncpoint_allocate,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_FREE, tegra_drm_ioctl_syncpoint_free,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_WAIT, tegra_drm_ioctl_syncpoint_wait,
+ DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read,
DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr,
@@ -792,10 +806,11 @@ static void tegra_drm_postclose(struct drm_device *drm, struct drm_file *file)
struct tegra_drm_file *fpriv = file->driver_priv;
mutex_lock(&fpriv->lock);
- idr_for_each(&fpriv->contexts, tegra_drm_context_cleanup, NULL);
+ idr_for_each(&fpriv->legacy_contexts, tegra_drm_context_cleanup, NULL);
+ tegra_drm_uapi_close_file(fpriv);
mutex_unlock(&fpriv->lock);
- idr_destroy(&fpriv->contexts);
+ idr_destroy(&fpriv->legacy_contexts);
mutex_destroy(&fpriv->lock);
kfree(fpriv);
}
@@ -853,7 +868,7 @@ static void tegra_debugfs_init(struct drm_minor *minor)
static const struct drm_driver tegra_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM |
- DRIVER_ATOMIC | DRIVER_RENDER,
+ DRIVER_ATOMIC | DRIVER_RENDER | DRIVER_SYNCOBJ,
.open = tegra_drm_open,
.postclose = tegra_drm_postclose,
.lastclose = drm_fb_helper_lastclose,
@@ -883,6 +898,14 @@ static const struct drm_driver tegra_drm_driver = {
int tegra_drm_register_client(struct tegra_drm *tegra,
struct tegra_drm_client *client)
{
+ /*
+ * When MLOCKs are implemented, change to allocate a shared channel
+ * only when MLOCKs are disabled.
+ */
+ client->shared_channel = host1x_channel_request(&client->base);
+ if (!client->shared_channel)
+ return -EBUSY;
+
mutex_lock(&tegra->clients_lock);
list_add_tail(&client->list, &tegra->clients);
client->drm = tegra;
@@ -899,6 +922,9 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
client->drm = NULL;
mutex_unlock(&tegra->clients_lock);
+ if (client->shared_channel)
+ host1x_channel_put(client->shared_channel);
+
return 0;
}
@@ -1188,13 +1214,6 @@ static int host1x_drm_probe(struct host1x_device *dev)
goto device;
}
- /*
- * We don't use the drm_irq_install() helpers provided by the DRM
- * core, so we need to set this manually in order to allow the
- * DRM_IOCTL_WAIT_VBLANK to operate correctly.
- */
- drm->irq_enabled = true;
-
/* syncpoints are used for full 32-bit hardware VBLANK counters */
drm->max_vblank_count = 0xffffffff;
@@ -1204,7 +1223,7 @@ static int host1x_drm_probe(struct host1x_device *dev)
drm_mode_config_reset(drm);
- err = drm_aperture_remove_framebuffers(false, "tegradrmfb");
+ err = drm_aperture_remove_framebuffers(false, &tegra_drm_driver);
if (err < 0)
goto hub;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 0cb868065348..8b28327c931c 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -64,12 +64,22 @@ struct tegra_drm {
struct tegra_display_hub *hub;
};
+static inline struct host1x *tegra_drm_to_host1x(struct tegra_drm *tegra)
+{
+ return dev_get_drvdata(tegra->drm->dev->parent);
+}
+
struct tegra_drm_client;
struct tegra_drm_context {
struct tegra_drm_client *client;
struct host1x_channel *channel;
+
+ /* Only used by legacy UAPI. */
unsigned int id;
+
+ /* Only used by new UAPI. */
+ struct xarray mappings;
};
struct tegra_drm_client_ops {
@@ -91,7 +101,9 @@ struct tegra_drm_client {
struct host1x_client base;
struct list_head list;
struct tegra_drm *drm;
+ struct host1x_channel *shared_channel;
+ /* Set by driver */
unsigned int version;
const struct tegra_drm_client_ops *ops;
};
diff --git a/drivers/gpu/drm/tegra/firewall.c b/drivers/gpu/drm/tegra/firewall.c
new file mode 100644
index 000000000000..1824d2db0e2c
--- /dev/null
+++ b/drivers/gpu/drm/tegra/firewall.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2010-2020 NVIDIA Corporation */
+
+#include "drm.h"
+#include "submit.h"
+#include "uapi.h"
+
+struct tegra_drm_firewall {
+ struct tegra_drm_submit_data *submit;
+ struct tegra_drm_client *client;
+ u32 *data;
+ u32 pos;
+ u32 end;
+ u32 class;
+};
+
+static int fw_next(struct tegra_drm_firewall *fw, u32 *word)
+{
+ if (fw->pos == fw->end)
+ return -EINVAL;
+
+ *word = fw->data[fw->pos++];
+
+ return 0;
+}
+
+static bool fw_check_addr_valid(struct tegra_drm_firewall *fw, u32 offset)
+{
+ u32 i;
+
+ for (i = 0; i < fw->submit->num_used_mappings; i++) {
+ struct tegra_drm_mapping *m = fw->submit->used_mappings[i].mapping;
+
+ if (offset >= m->iova && offset <= m->iova_end)
+ return true;
+ }
+
+ return false;
+}
+
+static int fw_check_reg(struct tegra_drm_firewall *fw, u32 offset)
+{
+ bool is_addr;
+ u32 word;
+ int err;
+
+ err = fw_next(fw, &word);
+ if (err)
+ return err;
+
+ if (!fw->client->ops->is_addr_reg)
+ return 0;
+
+ is_addr = fw->client->ops->is_addr_reg(fw->client->base.dev, fw->class,
+ offset);
+
+ if (!is_addr)
+ return 0;
+
+ if (!fw_check_addr_valid(fw, word))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int fw_check_regs_seq(struct tegra_drm_firewall *fw, u32 offset,
+ u32 count, bool incr)
+{
+ u32 i;
+
+ for (i = 0; i < count; i++) {
+ if (fw_check_reg(fw, offset))
+ return -EINVAL;
+
+ if (incr)
+ offset++;
+ }
+
+ return 0;
+}
+
+static int fw_check_regs_mask(struct tegra_drm_firewall *fw, u32 offset,
+ u16 mask)
+{
+ unsigned long bmask = mask;
+ unsigned int bit;
+
+ for_each_set_bit(bit, &bmask, 16) {
+ if (fw_check_reg(fw, offset+bit))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fw_check_regs_imm(struct tegra_drm_firewall *fw, u32 offset)
+{
+ bool is_addr;
+
+ is_addr = fw->client->ops->is_addr_reg(fw->client->base.dev, fw->class,
+ offset);
+ if (is_addr)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int fw_check_class(struct tegra_drm_firewall *fw, u32 class)
+{
+ if (!fw->client->ops->is_valid_class) {
+ if (class == fw->client->base.class)
+ return 0;
+ else
+ return -EINVAL;
+ }
+
+ if (!fw->client->ops->is_valid_class(class))
+ return -EINVAL;
+
+ return 0;
+}
+
+enum {
+ HOST1X_OPCODE_SETCLASS = 0x00,
+ HOST1X_OPCODE_INCR = 0x01,
+ HOST1X_OPCODE_NONINCR = 0x02,
+ HOST1X_OPCODE_MASK = 0x03,
+ HOST1X_OPCODE_IMM = 0x04,
+ HOST1X_OPCODE_RESTART = 0x05,
+ HOST1X_OPCODE_GATHER = 0x06,
+ HOST1X_OPCODE_SETSTRMID = 0x07,
+ HOST1X_OPCODE_SETAPPID = 0x08,
+ HOST1X_OPCODE_SETPYLD = 0x09,
+ HOST1X_OPCODE_INCR_W = 0x0a,
+ HOST1X_OPCODE_NONINCR_W = 0x0b,
+ HOST1X_OPCODE_GATHER_W = 0x0c,
+ HOST1X_OPCODE_RESTART_W = 0x0d,
+ HOST1X_OPCODE_EXTEND = 0x0e,
+};
+
+int tegra_drm_fw_validate(struct tegra_drm_client *client, u32 *data, u32 start,
+ u32 words, struct tegra_drm_submit_data *submit,
+ u32 *job_class)
+{
+ struct tegra_drm_firewall fw = {
+ .submit = submit,
+ .client = client,
+ .data = data,
+ .pos = start,
+ .end = start+words,
+ .class = *job_class,
+ };
+ bool payload_valid = false;
+ u32 payload;
+ int err;
+
+ while (fw.pos != fw.end) {
+ u32 word, opcode, offset, count, mask, class;
+
+ err = fw_next(&fw, &word);
+ if (err)
+ return err;
+
+ opcode = (word & 0xf0000000) >> 28;
+
+ switch (opcode) {
+ case HOST1X_OPCODE_SETCLASS:
+ offset = word >> 16 & 0xfff;
+ mask = word & 0x3f;
+ class = (word >> 6) & 0x3ff;
+ err = fw_check_class(&fw, class);
+ fw.class = class;
+ *job_class = class;
+ if (!err)
+ err = fw_check_regs_mask(&fw, offset, mask);
+ if (err)
+ dev_warn(client->base.dev,
+ "illegal SETCLASS(offset=0x%x, mask=0x%x, class=0x%x) at word %u",
+ offset, mask, class, fw.pos-1);
+ break;
+ case HOST1X_OPCODE_INCR:
+ offset = (word >> 16) & 0xfff;
+ count = word & 0xffff;
+ err = fw_check_regs_seq(&fw, offset, count, true);
+ if (err)
+ dev_warn(client->base.dev,
+ "illegal INCR(offset=0x%x, count=%u) in class 0x%x at word %u",
+ offset, count, fw.class, fw.pos-1);
+ break;
+ case HOST1X_OPCODE_NONINCR:
+ offset = (word >> 16) & 0xfff;
+ count = word & 0xffff;
+ err = fw_check_regs_seq(&fw, offset, count, false);
+ if (err)
+ dev_warn(client->base.dev,
+ "illegal NONINCR(offset=0x%x, count=%u) in class 0x%x at word %u",
+ offset, count, fw.class, fw.pos-1);
+ break;
+ case HOST1X_OPCODE_MASK:
+ offset = (word >> 16) & 0xfff;
+ mask = word & 0xffff;
+ err = fw_check_regs_mask(&fw, offset, mask);
+ if (err)
+ dev_warn(client->base.dev,
+ "illegal MASK(offset=0x%x, mask=0x%x) in class 0x%x at word %u",
+ offset, mask, fw.class, fw.pos-1);
+ break;
+ case HOST1X_OPCODE_IMM:
+ /* IMM cannot reasonably be used to write a pointer */
+ offset = (word >> 16) & 0xfff;
+ err = fw_check_regs_imm(&fw, offset);
+ if (err)
+ dev_warn(client->base.dev,
+ "illegal IMM(offset=0x%x) in class 0x%x at word %u",
+ offset, fw.class, fw.pos-1);
+ break;
+ case HOST1X_OPCODE_SETPYLD:
+ payload = word & 0xffff;
+ payload_valid = true;
+ break;
+ case HOST1X_OPCODE_INCR_W:
+ if (!payload_valid)
+ return -EINVAL;
+
+ offset = word & 0x3fffff;
+ err = fw_check_regs_seq(&fw, offset, payload, true);
+ if (err)
+ dev_warn(client->base.dev,
+ "illegal INCR_W(offset=0x%x) in class 0x%x at word %u",
+ offset, fw.class, fw.pos-1);
+ break;
+ case HOST1X_OPCODE_NONINCR_W:
+ if (!payload_valid)
+ return -EINVAL;
+
+ offset = word & 0x3fffff;
+ err = fw_check_regs_seq(&fw, offset, payload, false);
+ if (err)
+ dev_warn(client->base.dev,
+ "illegal NONINCR(offset=0x%x) in class 0x%x at word %u",
+ offset, fw.class, fw.pos-1);
+ break;
+ default:
+ dev_warn(client->base.dev, "illegal opcode at word %u",
+ fw.pos-1);
+ return -EINVAL;
+ }
+
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 26af8daa9a16..6ec598f5d5b3 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -707,3 +707,16 @@ struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
return &bo->gem;
}
+
+struct host1x_bo *tegra_gem_lookup(struct drm_file *file, u32 handle)
+{
+ struct drm_gem_object *gem;
+ struct tegra_bo *bo;
+
+ gem = drm_gem_object_lookup(file, handle);
+ if (!gem)
+ return NULL;
+
+ bo = to_tegra_bo(gem);
+ return &bo->base;
+}
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h
index c15fd99d6cb2..cb5146a67668 100644
--- a/drivers/gpu/drm/tegra/gem.h
+++ b/drivers/gpu/drm/tegra/gem.h
@@ -80,4 +80,6 @@ struct dma_buf *tegra_gem_prime_export(struct drm_gem_object *gem,
struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
struct dma_buf *buf);
+struct host1x_bo *tegra_gem_lookup(struct drm_file *file, u32 handle);
+
#endif
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index 2e65b4075ce6..e00ec3f40ec8 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -4,6 +4,7 @@
*/
#include <linux/iommu.h>
+#include <linux/interconnect.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
@@ -64,6 +65,9 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
copy->reflect_x = state->reflect_x;
copy->reflect_y = state->reflect_y;
copy->opaque = state->opaque;
+ copy->total_peak_memory_bandwidth = state->total_peak_memory_bandwidth;
+ copy->peak_memory_bandwidth = state->peak_memory_bandwidth;
+ copy->avg_memory_bandwidth = state->avg_memory_bandwidth;
for (i = 0; i < 2; i++)
copy->blending[i] = state->blending[i];
@@ -244,6 +248,78 @@ void tegra_plane_cleanup_fb(struct drm_plane *plane,
tegra_dc_unpin(dc, to_tegra_plane_state(state));
}
+static int tegra_plane_calculate_memory_bandwidth(struct drm_plane_state *state)
+{
+ struct tegra_plane_state *tegra_state = to_tegra_plane_state(state);
+ unsigned int i, bpp, dst_w, dst_h, src_w, src_h, mul;
+ const struct tegra_dc_soc_info *soc;
+ const struct drm_format_info *fmt;
+ struct drm_crtc_state *crtc_state;
+ u64 avg_bandwidth, peak_bandwidth;
+
+ if (!state->visible)
+ return 0;
+
+ crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
+ if (!crtc_state)
+ return -EINVAL;
+
+ src_w = drm_rect_width(&state->src) >> 16;
+ src_h = drm_rect_height(&state->src) >> 16;
+ dst_w = drm_rect_width(&state->dst);
+ dst_h = drm_rect_height(&state->dst);
+
+ fmt = state->fb->format;
+ soc = to_tegra_dc(state->crtc)->soc;
+
+ /*
+ * Note that real memory bandwidth vary depending on format and
+ * memory layout, we are not taking that into account because small
+ * estimation error isn't important since bandwidth is rounded up
+ * anyway.
+ */
+ for (i = 0, bpp = 0; i < fmt->num_planes; i++) {
+ unsigned int bpp_plane = fmt->cpp[i] * 8;
+
+ /*
+ * Sub-sampling is relevant for chroma planes only and vertical
+ * readouts are not cached, hence only horizontal sub-sampling
+ * matters.
+ */
+ if (i > 0)
+ bpp_plane /= fmt->hsub;
+
+ bpp += bpp_plane;
+ }
+
+ /* average bandwidth in kbytes/sec */
+ avg_bandwidth = min(src_w, dst_w) * min(src_h, dst_h);
+ avg_bandwidth *= drm_mode_vrefresh(&crtc_state->adjusted_mode);
+ avg_bandwidth = DIV_ROUND_UP(avg_bandwidth * bpp, 8) + 999;
+ do_div(avg_bandwidth, 1000);
+
+ /* mode.clock in kHz, peak bandwidth in kbytes/sec */
+ peak_bandwidth = DIV_ROUND_UP(crtc_state->adjusted_mode.clock * bpp, 8);
+
+ /*
+ * Tegra30/114 Memory Controller can't interleave DC memory requests
+ * for the tiled windows because DC uses 16-bytes atom, while DDR3
+ * uses 32-bytes atom. Hence there is x2 memory overfetch for tiled
+ * framebuffer and DDR3 on these SoCs.
+ */
+ if (soc->plane_tiled_memory_bandwidth_x2 &&
+ tegra_state->tiling.mode == TEGRA_BO_TILING_MODE_TILED)
+ mul = 2;
+ else
+ mul = 1;
+
+ /* ICC bandwidth in kbytes/sec */
+ tegra_state->peak_memory_bandwidth = kBps_to_icc(peak_bandwidth) * mul;
+ tegra_state->avg_memory_bandwidth = kBps_to_icc(avg_bandwidth) * mul;
+
+ return 0;
+}
+
int tegra_plane_state_add(struct tegra_plane *plane,
struct drm_plane_state *state)
{
@@ -262,6 +338,10 @@ int tegra_plane_state_add(struct tegra_plane *plane,
if (err < 0)
return err;
+ err = tegra_plane_calculate_memory_bandwidth(state);
+ if (err < 0)
+ return err;
+
tegra = to_dc_state(crtc_state);
tegra->planes |= WIN_A_ACT_REQ << plane->index;
@@ -646,3 +726,40 @@ int tegra_plane_setup_legacy_state(struct tegra_plane *tegra,
return 0;
}
+
+static const char * const tegra_plane_icc_names[TEGRA_DC_LEGACY_PLANES_NUM] = {
+ "wina", "winb", "winc", NULL, NULL, NULL, "cursor",
+};
+
+int tegra_plane_interconnect_init(struct tegra_plane *plane)
+{
+ const char *icc_name = tegra_plane_icc_names[plane->index];
+ struct device *dev = plane->dc->dev;
+ struct tegra_dc *dc = plane->dc;
+ int err;
+
+ if (WARN_ON(plane->index >= TEGRA_DC_LEGACY_PLANES_NUM) ||
+ WARN_ON(!tegra_plane_icc_names[plane->index]))
+ return -EINVAL;
+
+ plane->icc_mem = devm_of_icc_get(dev, icc_name);
+ err = PTR_ERR_OR_ZERO(plane->icc_mem);
+ if (err) {
+ dev_err_probe(dev, err, "failed to get %s interconnect\n",
+ icc_name);
+ return err;
+ }
+
+ /* plane B on T20/30 has a dedicated memory client for a 6-tap vertical filter */
+ if (plane->index == 1 && dc->soc->has_win_b_vfilter_mem_client) {
+ plane->icc_mem_vfilter = devm_of_icc_get(dev, "winb-vfilter");
+ err = PTR_ERR_OR_ZERO(plane->icc_mem_vfilter);
+ if (err) {
+ dev_err_probe(dev, err, "failed to get %s interconnect\n",
+ "winb-vfilter");
+ return err;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
index 1785c1559c0c..d9470780c803 100644
--- a/drivers/gpu/drm/tegra/plane.h
+++ b/drivers/gpu/drm/tegra/plane.h
@@ -8,6 +8,7 @@
#include <drm/drm_plane.h>
+struct icc_path;
struct tegra_bo;
struct tegra_dc;
@@ -16,6 +17,9 @@ struct tegra_plane {
struct tegra_dc *dc;
unsigned int offset;
unsigned int index;
+
+ struct icc_path *icc_mem;
+ struct icc_path *icc_mem_vfilter;
};
struct tegra_cursor {
@@ -52,6 +56,11 @@ struct tegra_plane_state {
/* used for legacy blending support only */
struct tegra_plane_legacy_blending_state blending[2];
bool opaque;
+
+ /* bandwidths are in ICC units, i.e. kbytes/sec */
+ u32 total_peak_memory_bandwidth;
+ u32 peak_memory_bandwidth;
+ u32 avg_memory_bandwidth;
};
static inline struct tegra_plane_state *
@@ -63,6 +72,12 @@ to_tegra_plane_state(struct drm_plane_state *state)
return NULL;
}
+static inline const struct tegra_plane_state *
+to_const_tegra_plane_state(const struct drm_plane_state *state)
+{
+ return to_tegra_plane_state((struct drm_plane_state *)state);
+}
+
extern const struct drm_plane_funcs tegra_plane_funcs;
int tegra_plane_prepare_fb(struct drm_plane *plane,
@@ -78,5 +93,6 @@ bool tegra_plane_format_is_indexed(unsigned int format);
bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *bpc);
int tegra_plane_setup_legacy_state(struct tegra_plane *tegra,
struct tegra_plane_state *state);
+int tegra_plane_interconnect_init(struct tegra_plane *plane);
#endif /* TEGRA_PLANE_H */
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index 4142a56ca764..606c78a2b988 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -275,11 +275,8 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
if (output->bridge) {
err = drm_bridge_attach(&output->encoder, output->bridge,
NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
- if (err) {
- dev_err(output->dev, "failed to attach bridge: %d\n",
- err);
+ if (err)
return err;
- }
connector = drm_bridge_connector_init(drm, &output->encoder);
if (IS_ERR(connector)) {
diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c
new file mode 100644
index 000000000000..776f825df52f
--- /dev/null
+++ b/drivers/gpu/drm/tegra/submit.c
@@ -0,0 +1,625 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2020 NVIDIA Corporation */
+
+#include <linux/dma-fence-array.h>
+#include <linux/dma-mapping.h>
+#include <linux/file.h>
+#include <linux/host1x.h>
+#include <linux/iommu.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/nospec.h>
+#include <linux/pm_runtime.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/sync_file.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_syncobj.h>
+
+#include "drm.h"
+#include "gem.h"
+#include "submit.h"
+#include "uapi.h"
+
+#define SUBMIT_ERR(context, fmt, ...) \
+ dev_err_ratelimited(context->client->base.dev, \
+ "%s: job submission failed: " fmt "\n", \
+ current->comm, ##__VA_ARGS__)
+
+struct gather_bo {
+ struct host1x_bo base;
+
+ struct kref ref;
+
+ struct device *dev;
+ u32 *gather_data;
+ dma_addr_t gather_data_dma;
+ size_t gather_data_words;
+};
+
+static struct host1x_bo *gather_bo_get(struct host1x_bo *host_bo)
+{
+ struct gather_bo *bo = container_of(host_bo, struct gather_bo, base);
+
+ kref_get(&bo->ref);
+
+ return host_bo;
+}
+
+static void gather_bo_release(struct kref *ref)
+{
+ struct gather_bo *bo = container_of(ref, struct gather_bo, ref);
+
+ dma_free_attrs(bo->dev, bo->gather_data_words * 4, bo->gather_data, bo->gather_data_dma,
+ 0);
+ kfree(bo);
+}
+
+static void gather_bo_put(struct host1x_bo *host_bo)
+{
+ struct gather_bo *bo = container_of(host_bo, struct gather_bo, base);
+
+ kref_put(&bo->ref, gather_bo_release);
+}
+
+static struct sg_table *
+gather_bo_pin(struct device *dev, struct host1x_bo *host_bo, dma_addr_t *phys)
+{
+ struct gather_bo *bo = container_of(host_bo, struct gather_bo, base);
+ struct sg_table *sgt;
+ int err;
+
+ sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+ if (!sgt)
+ return ERR_PTR(-ENOMEM);
+
+ err = dma_get_sgtable(bo->dev, sgt, bo->gather_data, bo->gather_data_dma,
+ bo->gather_data_words * 4);
+ if (err) {
+ kfree(sgt);
+ return ERR_PTR(err);
+ }
+
+ return sgt;
+}
+
+static void gather_bo_unpin(struct device *dev, struct sg_table *sgt)
+{
+ if (sgt) {
+ sg_free_table(sgt);
+ kfree(sgt);
+ }
+}
+
+static void *gather_bo_mmap(struct host1x_bo *host_bo)
+{
+ struct gather_bo *bo = container_of(host_bo, struct gather_bo, base);
+
+ return bo->gather_data;
+}
+
+static void gather_bo_munmap(struct host1x_bo *host_bo, void *addr)
+{
+}
+
+const struct host1x_bo_ops gather_bo_ops = {
+ .get = gather_bo_get,
+ .put = gather_bo_put,
+ .pin = gather_bo_pin,
+ .unpin = gather_bo_unpin,
+ .mmap = gather_bo_mmap,
+ .munmap = gather_bo_munmap,
+};
+
+static struct tegra_drm_mapping *
+tegra_drm_mapping_get(struct tegra_drm_context *context, u32 id)
+{
+ struct tegra_drm_mapping *mapping;
+
+ xa_lock(&context->mappings);
+
+ mapping = xa_load(&context->mappings, id);
+ if (mapping)
+ kref_get(&mapping->ref);
+
+ xa_unlock(&context->mappings);
+
+ return mapping;
+}
+
+static void *alloc_copy_user_array(void __user *from, size_t count, size_t size)
+{
+ size_t copy_len;
+ void *data;
+
+ if (check_mul_overflow(count, size, &copy_len))
+ return ERR_PTR(-EINVAL);
+
+ if (copy_len > 0x4000)
+ return ERR_PTR(-E2BIG);
+
+ data = kvmalloc(copy_len, GFP_KERNEL);
+ if (!data)
+ return ERR_PTR(-ENOMEM);
+
+ if (copy_from_user(data, from, copy_len)) {
+ kvfree(data);
+ return ERR_PTR(-EFAULT);
+ }
+
+ return data;
+}
+
+static int submit_copy_gather_data(struct gather_bo **pbo, struct device *dev,
+ struct tegra_drm_context *context,
+ struct drm_tegra_channel_submit *args)
+{
+ struct gather_bo *bo;
+ size_t copy_len;
+
+ if (args->gather_data_words == 0) {
+ SUBMIT_ERR(context, "gather_data_words cannot be zero");
+ return -EINVAL;
+ }
+
+ if (check_mul_overflow((size_t)args->gather_data_words, (size_t)4, &copy_len)) {
+ SUBMIT_ERR(context, "gather_data_words is too large");
+ return -EINVAL;
+ }
+
+ bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+ if (!bo) {
+ SUBMIT_ERR(context, "failed to allocate memory for bo info");
+ return -ENOMEM;
+ }
+
+ host1x_bo_init(&bo->base, &gather_bo_ops);
+ kref_init(&bo->ref);
+ bo->dev = dev;
+
+ bo->gather_data = dma_alloc_attrs(dev, copy_len, &bo->gather_data_dma,
+ GFP_KERNEL | __GFP_NOWARN, 0);
+ if (!bo->gather_data) {
+ SUBMIT_ERR(context, "failed to allocate memory for gather data");
+ kfree(bo);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(bo->gather_data, u64_to_user_ptr(args->gather_data_ptr), copy_len)) {
+ SUBMIT_ERR(context, "failed to copy gather data from userspace");
+ dma_free_attrs(dev, copy_len, bo->gather_data, bo->gather_data_dma, 0);
+ kfree(bo);
+ return -EFAULT;
+ }
+
+ bo->gather_data_words = args->gather_data_words;
+
+ *pbo = bo;
+
+ return 0;
+}
+
+static int submit_write_reloc(struct tegra_drm_context *context, struct gather_bo *bo,
+ struct drm_tegra_submit_buf *buf, struct tegra_drm_mapping *mapping)
+{
+ /* TODO check that target_offset is within bounds */
+ dma_addr_t iova = mapping->iova + buf->reloc.target_offset;
+ u32 written_ptr;
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ if (buf->flags & DRM_TEGRA_SUBMIT_RELOC_SECTOR_LAYOUT)
+ iova |= BIT_ULL(39);
+#endif
+
+ written_ptr = iova >> buf->reloc.shift;
+
+ if (buf->reloc.gather_offset_words >= bo->gather_data_words) {
+ SUBMIT_ERR(context,
+ "relocation has too large gather offset (%u vs gather length %zu)",
+ buf->reloc.gather_offset_words, bo->gather_data_words);
+ return -EINVAL;
+ }
+
+ buf->reloc.gather_offset_words = array_index_nospec(buf->reloc.gather_offset_words,
+ bo->gather_data_words);
+
+ bo->gather_data[buf->reloc.gather_offset_words] = written_ptr;
+
+ return 0;
+}
+
+static int submit_process_bufs(struct tegra_drm_context *context, struct gather_bo *bo,
+ struct drm_tegra_channel_submit *args,
+ struct tegra_drm_submit_data *job_data)
+{
+ struct tegra_drm_used_mapping *mappings;
+ struct drm_tegra_submit_buf *bufs;
+ int err;
+ u32 i;
+
+ bufs = alloc_copy_user_array(u64_to_user_ptr(args->bufs_ptr), args->num_bufs,
+ sizeof(*bufs));
+ if (IS_ERR(bufs)) {
+ SUBMIT_ERR(context, "failed to copy bufs array from userspace");
+ return PTR_ERR(bufs);
+ }
+
+ mappings = kcalloc(args->num_bufs, sizeof(*mappings), GFP_KERNEL);
+ if (!mappings) {
+ SUBMIT_ERR(context, "failed to allocate memory for mapping info");
+ err = -ENOMEM;
+ goto done;
+ }
+
+ for (i = 0; i < args->num_bufs; i++) {
+ struct drm_tegra_submit_buf *buf = &bufs[i];
+ struct tegra_drm_mapping *mapping;
+
+ if (buf->flags & ~DRM_TEGRA_SUBMIT_RELOC_SECTOR_LAYOUT) {
+ SUBMIT_ERR(context, "invalid flag specified for buffer");
+ err = -EINVAL;
+ goto drop_refs;
+ }
+
+ mapping = tegra_drm_mapping_get(context, buf->mapping);
+ if (!mapping) {
+ SUBMIT_ERR(context, "invalid mapping ID '%u' for buffer", buf->mapping);
+ err = -EINVAL;
+ goto drop_refs;
+ }
+
+ err = submit_write_reloc(context, bo, buf, mapping);
+ if (err) {
+ tegra_drm_mapping_put(mapping);
+ goto drop_refs;
+ }
+
+ mappings[i].mapping = mapping;
+ mappings[i].flags = buf->flags;
+ }
+
+ job_data->used_mappings = mappings;
+ job_data->num_used_mappings = i;
+
+ err = 0;
+
+ goto done;
+
+drop_refs:
+ while (i--)
+ tegra_drm_mapping_put(mappings[i].mapping);
+
+ kfree(mappings);
+ job_data->used_mappings = NULL;
+
+done:
+ kvfree(bufs);
+
+ return err;
+}
+
+static int submit_get_syncpt(struct tegra_drm_context *context, struct host1x_job *job,
+ struct xarray *syncpoints, struct drm_tegra_channel_submit *args)
+{
+ struct host1x_syncpt *sp;
+
+ if (args->syncpt.flags) {
+ SUBMIT_ERR(context, "invalid flag specified for syncpt");
+ return -EINVAL;
+ }
+
+ /* Syncpt ref will be dropped on job release */
+ sp = xa_load(syncpoints, args->syncpt.id);
+ if (!sp) {
+ SUBMIT_ERR(context, "syncpoint specified in syncpt was not allocated");
+ return -EINVAL;
+ }
+
+ job->syncpt = host1x_syncpt_get(sp);
+ job->syncpt_incrs = args->syncpt.increments;
+
+ return 0;
+}
+
+static int submit_job_add_gather(struct host1x_job *job, struct tegra_drm_context *context,
+ struct drm_tegra_submit_cmd_gather_uptr *cmd,
+ struct gather_bo *bo, u32 *offset,
+ struct tegra_drm_submit_data *job_data,
+ u32 *class)
+{
+ u32 next_offset;
+
+ if (cmd->reserved[0] || cmd->reserved[1] || cmd->reserved[2]) {
+ SUBMIT_ERR(context, "non-zero reserved field in GATHER_UPTR command");
+ return -EINVAL;
+ }
+
+ /* Check for maximum gather size */
+ if (cmd->words > 16383) {
+ SUBMIT_ERR(context, "too many words in GATHER_UPTR command");
+ return -EINVAL;
+ }
+
+ if (check_add_overflow(*offset, cmd->words, &next_offset)) {
+ SUBMIT_ERR(context, "too many total words in job");
+ return -EINVAL;
+ }
+
+ if (next_offset > bo->gather_data_words) {
+ SUBMIT_ERR(context, "GATHER_UPTR command overflows gather data");
+ return -EINVAL;
+ }
+
+ if (tegra_drm_fw_validate(context->client, bo->gather_data, *offset,
+ cmd->words, job_data, class)) {
+ SUBMIT_ERR(context, "job was rejected by firewall");
+ return -EINVAL;
+ }
+
+ host1x_job_add_gather(job, &bo->base, cmd->words, *offset * 4);
+
+ *offset = next_offset;
+
+ return 0;
+}
+
+static struct host1x_job *
+submit_create_job(struct tegra_drm_context *context, struct gather_bo *bo,
+ struct drm_tegra_channel_submit *args, struct tegra_drm_submit_data *job_data,
+ struct xarray *syncpoints)
+{
+ struct drm_tegra_submit_cmd *cmds;
+ u32 i, gather_offset = 0, class;
+ struct host1x_job *job;
+ int err;
+
+ /* Set initial class for firewall. */
+ class = context->client->base.class;
+
+ cmds = alloc_copy_user_array(u64_to_user_ptr(args->cmds_ptr), args->num_cmds,
+ sizeof(*cmds));
+ if (IS_ERR(cmds)) {
+ SUBMIT_ERR(context, "failed to copy cmds array from userspace");
+ return ERR_CAST(cmds);
+ }
+
+ job = host1x_job_alloc(context->channel, args->num_cmds, 0, true);
+ if (!job) {
+ SUBMIT_ERR(context, "failed to allocate memory for job");
+ job = ERR_PTR(-ENOMEM);
+ goto done;
+ }
+
+ err = submit_get_syncpt(context, job, syncpoints, args);
+ if (err < 0)
+ goto free_job;
+
+ job->client = &context->client->base;
+ job->class = context->client->base.class;
+ job->serialize = true;
+
+ for (i = 0; i < args->num_cmds; i++) {
+ struct drm_tegra_submit_cmd *cmd = &cmds[i];
+
+ if (cmd->flags) {
+ SUBMIT_ERR(context, "unknown flags given for cmd");
+ err = -EINVAL;
+ goto free_job;
+ }
+
+ if (cmd->type == DRM_TEGRA_SUBMIT_CMD_GATHER_UPTR) {
+ err = submit_job_add_gather(job, context, &cmd->gather_uptr, bo,
+ &gather_offset, job_data, &class);
+ if (err)
+ goto free_job;
+ } else if (cmd->type == DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT) {
+ if (cmd->wait_syncpt.reserved[0] || cmd->wait_syncpt.reserved[1]) {
+ SUBMIT_ERR(context, "non-zero reserved value");
+ err = -EINVAL;
+ goto free_job;
+ }
+
+ host1x_job_add_wait(job, cmd->wait_syncpt.id, cmd->wait_syncpt.value,
+ false, class);
+ } else if (cmd->type == DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT_RELATIVE) {
+ if (cmd->wait_syncpt.reserved[0] || cmd->wait_syncpt.reserved[1]) {
+ SUBMIT_ERR(context, "non-zero reserved value");
+ err = -EINVAL;
+ goto free_job;
+ }
+
+ if (cmd->wait_syncpt.id != args->syncpt.id) {
+ SUBMIT_ERR(context, "syncpoint ID in CMD_WAIT_SYNCPT_RELATIVE is not used by the job");
+ err = -EINVAL;
+ goto free_job;
+ }
+
+ host1x_job_add_wait(job, cmd->wait_syncpt.id, cmd->wait_syncpt.value,
+ true, class);
+ } else {
+ SUBMIT_ERR(context, "unknown cmd type");
+ err = -EINVAL;
+ goto free_job;
+ }
+ }
+
+ if (gather_offset == 0) {
+ SUBMIT_ERR(context, "job must have at least one gather");
+ err = -EINVAL;
+ goto free_job;
+ }
+
+ goto done;
+
+free_job:
+ host1x_job_put(job);
+ job = ERR_PTR(err);
+
+done:
+ kvfree(cmds);
+
+ return job;
+}
+
+static void release_job(struct host1x_job *job)
+{
+ struct tegra_drm_client *client = container_of(job->client, struct tegra_drm_client, base);
+ struct tegra_drm_submit_data *job_data = job->user_data;
+ u32 i;
+
+ for (i = 0; i < job_data->num_used_mappings; i++)
+ tegra_drm_mapping_put(job_data->used_mappings[i].mapping);
+
+ kfree(job_data->used_mappings);
+ kfree(job_data);
+
+ if (pm_runtime_enabled(client->base.dev))
+ pm_runtime_put_autosuspend(client->base.dev);
+}
+
+int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct tegra_drm_file *fpriv = file->driver_priv;
+ struct drm_tegra_channel_submit *args = data;
+ struct tegra_drm_submit_data *job_data;
+ struct drm_syncobj *syncobj = NULL;
+ struct tegra_drm_context *context;
+ struct host1x_job *job;
+ struct gather_bo *bo;
+ u32 i;
+ int err;
+
+ mutex_lock(&fpriv->lock);
+
+ context = xa_load(&fpriv->contexts, args->context);
+ if (!context) {
+ mutex_unlock(&fpriv->lock);
+ pr_err_ratelimited("%s: %s: invalid channel context '%#x'", __func__,
+ current->comm, args->context);
+ return -EINVAL;
+ }
+
+ if (args->syncobj_in) {
+ struct dma_fence *fence;
+
+ err = drm_syncobj_find_fence(file, args->syncobj_in, 0, 0, &fence);
+ if (err) {
+ SUBMIT_ERR(context, "invalid syncobj_in '%#x'", args->syncobj_in);
+ goto unlock;
+ }
+
+ err = dma_fence_wait_timeout(fence, true, msecs_to_jiffies(10000));
+ dma_fence_put(fence);
+ if (err) {
+ SUBMIT_ERR(context, "wait for syncobj_in timed out");
+ goto unlock;
+ }
+ }
+
+ if (args->syncobj_out) {
+ syncobj = drm_syncobj_find(file, args->syncobj_out);
+ if (!syncobj) {
+ SUBMIT_ERR(context, "invalid syncobj_out '%#x'", args->syncobj_out);
+ err = -ENOENT;
+ goto unlock;
+ }
+ }
+
+ /* Allocate gather BO and copy gather words in. */
+ err = submit_copy_gather_data(&bo, drm->dev, context, args);
+ if (err)
+ goto unlock;
+
+ job_data = kzalloc(sizeof(*job_data), GFP_KERNEL);
+ if (!job_data) {
+ SUBMIT_ERR(context, "failed to allocate memory for job data");
+ err = -ENOMEM;
+ goto put_bo;
+ }
+
+ /* Get data buffer mappings and do relocation patching. */
+ err = submit_process_bufs(context, bo, args, job_data);
+ if (err)
+ goto free_job_data;
+
+ /* Allocate host1x_job and add gathers and waits to it. */
+ job = submit_create_job(context, bo, args, job_data, &fpriv->syncpoints);
+ if (IS_ERR(job)) {
+ err = PTR_ERR(job);
+ goto free_job_data;
+ }
+
+ /* Map gather data for Host1x. */
+ err = host1x_job_pin(job, context->client->base.dev);
+ if (err) {
+ SUBMIT_ERR(context, "failed to pin job: %d", err);
+ goto put_job;
+ }
+
+ /* Boot engine. */
+ if (pm_runtime_enabled(context->client->base.dev)) {
+ err = pm_runtime_resume_and_get(context->client->base.dev);
+ if (err < 0) {
+ SUBMIT_ERR(context, "could not power up engine: %d", err);
+ goto unpin_job;
+ }
+ }
+
+ job->user_data = job_data;
+ job->release = release_job;
+ job->timeout = 10000;
+
+ /*
+ * job_data is now part of job reference counting, so don't release
+ * it from here.
+ */
+ job_data = NULL;
+
+ /* Submit job to hardware. */
+ err = host1x_job_submit(job);
+ if (err) {
+ SUBMIT_ERR(context, "host1x job submission failed: %d", err);
+ goto unpin_job;
+ }
+
+ /* Return postfences to userspace and add fences to DMA reservations. */
+ args->syncpt.value = job->syncpt_end;
+
+ if (syncobj) {
+ struct dma_fence *fence = host1x_fence_create(job->syncpt, job->syncpt_end);
+ if (IS_ERR(fence)) {
+ err = PTR_ERR(fence);
+ SUBMIT_ERR(context, "failed to create postfence: %d", err);
+ }
+
+ drm_syncobj_replace_fence(syncobj, fence);
+ }
+
+ goto put_job;
+
+unpin_job:
+ host1x_job_unpin(job);
+put_job:
+ host1x_job_put(job);
+free_job_data:
+ if (job_data && job_data->used_mappings) {
+ for (i = 0; i < job_data->num_used_mappings; i++)
+ tegra_drm_mapping_put(job_data->used_mappings[i].mapping);
+
+ kfree(job_data->used_mappings);
+ }
+
+ if (job_data)
+ kfree(job_data);
+put_bo:
+ gather_bo_put(&bo->base);
+unlock:
+ if (syncobj)
+ drm_syncobj_put(syncobj);
+
+ mutex_unlock(&fpriv->lock);
+ return err;
+}
diff --git a/drivers/gpu/drm/tegra/submit.h b/drivers/gpu/drm/tegra/submit.h
new file mode 100644
index 000000000000..cf6a2f0a29fc
--- /dev/null
+++ b/drivers/gpu/drm/tegra/submit.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020 NVIDIA Corporation */
+
+#ifndef _TEGRA_DRM_UAPI_SUBMIT_H
+#define _TEGRA_DRM_UAPI_SUBMIT_H
+
+struct tegra_drm_used_mapping {
+ struct tegra_drm_mapping *mapping;
+ u32 flags;
+};
+
+struct tegra_drm_submit_data {
+ struct tegra_drm_used_mapping *used_mappings;
+ u32 num_used_mappings;
+};
+
+int tegra_drm_fw_validate(struct tegra_drm_client *client, u32 *data, u32 start,
+ u32 words, struct tegra_drm_submit_data *submit,
+ u32 *job_class);
+
+#endif
diff --git a/drivers/gpu/drm/tegra/uapi.c b/drivers/gpu/drm/tegra/uapi.c
new file mode 100644
index 000000000000..dc16a24f4dbe
--- /dev/null
+++ b/drivers/gpu/drm/tegra/uapi.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2020 NVIDIA Corporation */
+
+#include <linux/host1x.h>
+#include <linux/iommu.h>
+#include <linux/list.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_utils.h>
+
+#include "drm.h"
+#include "uapi.h"
+
+static void tegra_drm_mapping_release(struct kref *ref)
+{
+ struct tegra_drm_mapping *mapping =
+ container_of(ref, struct tegra_drm_mapping, ref);
+
+ if (mapping->sgt)
+ dma_unmap_sgtable(mapping->dev, mapping->sgt, mapping->direction,
+ DMA_ATTR_SKIP_CPU_SYNC);
+
+ host1x_bo_unpin(mapping->dev, mapping->bo, mapping->sgt);
+ host1x_bo_put(mapping->bo);
+
+ kfree(mapping);
+}
+
+void tegra_drm_mapping_put(struct tegra_drm_mapping *mapping)
+{
+ kref_put(&mapping->ref, tegra_drm_mapping_release);
+}
+
+static void tegra_drm_channel_context_close(struct tegra_drm_context *context)
+{
+ struct tegra_drm_mapping *mapping;
+ unsigned long id;
+
+ xa_for_each(&context->mappings, id, mapping)
+ tegra_drm_mapping_put(mapping);
+
+ xa_destroy(&context->mappings);
+
+ host1x_channel_put(context->channel);
+
+ kfree(context);
+}
+
+void tegra_drm_uapi_close_file(struct tegra_drm_file *file)
+{
+ struct tegra_drm_context *context;
+ struct host1x_syncpt *sp;
+ unsigned long id;
+
+ xa_for_each(&file->contexts, id, context)
+ tegra_drm_channel_context_close(context);
+
+ xa_for_each(&file->syncpoints, id, sp)
+ host1x_syncpt_put(sp);
+
+ xa_destroy(&file->contexts);
+ xa_destroy(&file->syncpoints);
+}
+
+static struct tegra_drm_client *tegra_drm_find_client(struct tegra_drm *tegra, u32 class)
+{
+ struct tegra_drm_client *client;
+
+ list_for_each_entry(client, &tegra->clients, list)
+ if (client->base.class == class)
+ return client;
+
+ return NULL;
+}
+
+int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data, struct drm_file *file)
+{
+ struct tegra_drm_file *fpriv = file->driver_priv;
+ struct tegra_drm *tegra = drm->dev_private;
+ struct drm_tegra_channel_open *args = data;
+ struct tegra_drm_client *client = NULL;
+ struct tegra_drm_context *context;
+ int err;
+
+ if (args->flags)
+ return -EINVAL;
+
+ context = kzalloc(sizeof(*context), GFP_KERNEL);
+ if (!context)
+ return -ENOMEM;
+
+ client = tegra_drm_find_client(tegra, args->host1x_class);
+ if (!client) {
+ err = -ENODEV;
+ goto free;
+ }
+
+ if (client->shared_channel) {
+ context->channel = host1x_channel_get(client->shared_channel);
+ } else {
+ context->channel = host1x_channel_request(&client->base);
+ if (!context->channel) {
+ err = -EBUSY;
+ goto free;
+ }
+ }
+
+ err = xa_alloc(&fpriv->contexts, &args->context, context, XA_LIMIT(1, U32_MAX),
+ GFP_KERNEL);
+ if (err < 0)
+ goto put_channel;
+
+ context->client = client;
+ xa_init_flags(&context->mappings, XA_FLAGS_ALLOC1);
+
+ args->version = client->version;
+ args->capabilities = 0;
+
+ if (device_get_dma_attr(client->base.dev) == DEV_DMA_COHERENT)
+ args->capabilities |= DRM_TEGRA_CHANNEL_CAP_CACHE_COHERENT;
+
+ return 0;
+
+put_channel:
+ host1x_channel_put(context->channel);
+free:
+ kfree(context);
+
+ return err;
+}
+
+int tegra_drm_ioctl_channel_close(struct drm_device *drm, void *data, struct drm_file *file)
+{
+ struct tegra_drm_file *fpriv = file->driver_priv;
+ struct drm_tegra_channel_close *args = data;
+ struct tegra_drm_context *context;
+
+ mutex_lock(&fpriv->lock);
+
+ context = xa_load(&fpriv->contexts, args->context);
+ if (!context) {
+ mutex_unlock(&fpriv->lock);
+ return -EINVAL;
+ }
+
+ xa_erase(&fpriv->contexts, args->context);
+
+ mutex_unlock(&fpriv->lock);
+
+ tegra_drm_channel_context_close(context);
+
+ return 0;
+}
+
+int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data, struct drm_file *file)
+{
+ struct tegra_drm_file *fpriv = file->driver_priv;
+ struct drm_tegra_channel_map *args = data;
+ struct tegra_drm_mapping *mapping;
+ struct tegra_drm_context *context;
+ int err = 0;
+
+ if (args->flags & ~DRM_TEGRA_CHANNEL_MAP_READ_WRITE)
+ return -EINVAL;
+
+ mutex_lock(&fpriv->lock);
+
+ context = xa_load(&fpriv->contexts, args->context);
+ if (!context) {
+ mutex_unlock(&fpriv->lock);
+ return -EINVAL;
+ }
+
+ mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+ if (!mapping) {
+ err = -ENOMEM;
+ goto unlock;
+ }
+
+ kref_init(&mapping->ref);
+
+ mapping->dev = context->client->base.dev;
+ mapping->bo = tegra_gem_lookup(file, args->handle);
+ if (!mapping->bo) {
+ err = -EINVAL;
+ goto unlock;
+ }
+
+ if (context->client->base.group) {
+ /* IOMMU domain managed directly using IOMMU API */
+ host1x_bo_pin(mapping->dev, mapping->bo, &mapping->iova);
+ } else {
+ switch (args->flags & DRM_TEGRA_CHANNEL_MAP_READ_WRITE) {
+ case DRM_TEGRA_CHANNEL_MAP_READ_WRITE:
+ mapping->direction = DMA_BIDIRECTIONAL;
+ break;
+
+ case DRM_TEGRA_CHANNEL_MAP_WRITE:
+ mapping->direction = DMA_FROM_DEVICE;
+ break;
+
+ case DRM_TEGRA_CHANNEL_MAP_READ:
+ mapping->direction = DMA_TO_DEVICE;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ mapping->sgt = host1x_bo_pin(mapping->dev, mapping->bo, NULL);
+ if (IS_ERR(mapping->sgt)) {
+ err = PTR_ERR(mapping->sgt);
+ goto put_gem;
+ }
+
+ err = dma_map_sgtable(mapping->dev, mapping->sgt, mapping->direction,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ if (err)
+ goto unpin;
+
+ mapping->iova = sg_dma_address(mapping->sgt->sgl);
+ }
+
+ mapping->iova_end = mapping->iova + host1x_to_tegra_bo(mapping->bo)->size;
+
+ err = xa_alloc(&context->mappings, &args->mapping, mapping, XA_LIMIT(1, U32_MAX),
+ GFP_KERNEL);
+ if (err < 0)
+ goto unmap;
+
+ mutex_unlock(&fpriv->lock);
+
+ return 0;
+
+unmap:
+ if (mapping->sgt) {
+ dma_unmap_sgtable(mapping->dev, mapping->sgt, mapping->direction,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ }
+unpin:
+ host1x_bo_unpin(mapping->dev, mapping->bo, mapping->sgt);
+put_gem:
+ host1x_bo_put(mapping->bo);
+ kfree(mapping);
+unlock:
+ mutex_unlock(&fpriv->lock);
+ return err;
+}
+
+int tegra_drm_ioctl_channel_unmap(struct drm_device *drm, void *data, struct drm_file *file)
+{
+ struct tegra_drm_file *fpriv = file->driver_priv;
+ struct drm_tegra_channel_unmap *args = data;
+ struct tegra_drm_mapping *mapping;
+ struct tegra_drm_context *context;
+
+ mutex_lock(&fpriv->lock);
+
+ context = xa_load(&fpriv->contexts, args->context);
+ if (!context) {
+ mutex_unlock(&fpriv->lock);
+ return -EINVAL;
+ }
+
+ mapping = xa_erase(&context->mappings, args->mapping);
+
+ mutex_unlock(&fpriv->lock);
+
+ if (!mapping)
+ return -EINVAL;
+
+ tegra_drm_mapping_put(mapping);
+ return 0;
+}
+
+int tegra_drm_ioctl_syncpoint_allocate(struct drm_device *drm, void *data, struct drm_file *file)
+{
+ struct host1x *host1x = tegra_drm_to_host1x(drm->dev_private);
+ struct tegra_drm_file *fpriv = file->driver_priv;
+ struct drm_tegra_syncpoint_allocate *args = data;
+ struct host1x_syncpt *sp;
+ int err;
+
+ if (args->id)
+ return -EINVAL;
+
+ sp = host1x_syncpt_alloc(host1x, HOST1X_SYNCPT_CLIENT_MANAGED, current->comm);
+ if (!sp)
+ return -EBUSY;
+
+ args->id = host1x_syncpt_id(sp);
+
+ err = xa_insert(&fpriv->syncpoints, args->id, sp, GFP_KERNEL);
+ if (err) {
+ host1x_syncpt_put(sp);
+ return err;
+ }
+
+ return 0;
+}
+
+int tegra_drm_ioctl_syncpoint_free(struct drm_device *drm, void *data, struct drm_file *file)
+{
+ struct tegra_drm_file *fpriv = file->driver_priv;
+ struct drm_tegra_syncpoint_allocate *args = data;
+ struct host1x_syncpt *sp;
+
+ mutex_lock(&fpriv->lock);
+ sp = xa_erase(&fpriv->syncpoints, args->id);
+ mutex_unlock(&fpriv->lock);
+
+ if (!sp)
+ return -EINVAL;
+
+ host1x_syncpt_put(sp);
+
+ return 0;
+}
+
+int tegra_drm_ioctl_syncpoint_wait(struct drm_device *drm, void *data, struct drm_file *file)
+{
+ struct host1x *host1x = tegra_drm_to_host1x(drm->dev_private);
+ struct drm_tegra_syncpoint_wait *args = data;
+ signed long timeout_jiffies;
+ struct host1x_syncpt *sp;
+
+ if (args->padding != 0)
+ return -EINVAL;
+
+ sp = host1x_syncpt_get_by_id_noref(host1x, args->id);
+ if (!sp)
+ return -EINVAL;
+
+ timeout_jiffies = drm_timeout_abs_to_jiffies(args->timeout_ns);
+
+ return host1x_syncpt_wait(sp, args->threshold, timeout_jiffies, &args->value);
+}
diff --git a/drivers/gpu/drm/tegra/uapi.h b/drivers/gpu/drm/tegra/uapi.h
new file mode 100644
index 000000000000..12adad770ad3
--- /dev/null
+++ b/drivers/gpu/drm/tegra/uapi.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020 NVIDIA Corporation */
+
+#ifndef _TEGRA_DRM_UAPI_H
+#define _TEGRA_DRM_UAPI_H
+
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <linux/kref.h>
+#include <linux/xarray.h>
+
+#include <drm/drm.h>
+
+struct drm_file;
+struct drm_device;
+
+struct tegra_drm_file {
+ /* Legacy UAPI state */
+ struct idr legacy_contexts;
+ struct mutex lock;
+
+ /* New UAPI state */
+ struct xarray contexts;
+ struct xarray syncpoints;
+};
+
+struct tegra_drm_mapping {
+ struct kref ref;
+
+ struct device *dev;
+ struct host1x_bo *bo;
+ struct sg_table *sgt;
+ enum dma_data_direction direction;
+ dma_addr_t iova;
+ dma_addr_t iova_end;
+};
+
+int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
+ struct drm_file *file);
+int tegra_drm_ioctl_channel_close(struct drm_device *drm, void *data,
+ struct drm_file *file);
+int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data,
+ struct drm_file *file);
+int tegra_drm_ioctl_channel_unmap(struct drm_device *drm, void *data,
+ struct drm_file *file);
+int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
+ struct drm_file *file);
+int tegra_drm_ioctl_syncpoint_allocate(struct drm_device *drm, void *data,
+ struct drm_file *file);
+int tegra_drm_ioctl_syncpoint_free(struct drm_device *drm, void *data,
+ struct drm_file *file);
+int tegra_drm_ioctl_syncpoint_wait(struct drm_device *drm, void *data,
+ struct drm_file *file);
+
+void tegra_drm_uapi_close_file(struct tegra_drm_file *file);
+void tegra_drm_mapping_put(struct tegra_drm_mapping *mapping);
+
+#endif
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index c9d55a9a3180..c02010ff2b7f 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -29,7 +29,6 @@ struct vic_config {
struct vic {
struct falcon falcon;
- bool booted;
void __iomem *regs;
struct tegra_drm_client client;
@@ -52,48 +51,6 @@ static void vic_writel(struct vic *vic, u32 value, unsigned int offset)
writel(value, vic->regs + offset);
}
-static int vic_runtime_resume(struct device *dev)
-{
- struct vic *vic = dev_get_drvdata(dev);
- int err;
-
- err = clk_prepare_enable(vic->clk);
- if (err < 0)
- return err;
-
- usleep_range(10, 20);
-
- err = reset_control_deassert(vic->rst);
- if (err < 0)
- goto disable;
-
- usleep_range(10, 20);
-
- return 0;
-
-disable:
- clk_disable_unprepare(vic->clk);
- return err;
-}
-
-static int vic_runtime_suspend(struct device *dev)
-{
- struct vic *vic = dev_get_drvdata(dev);
- int err;
-
- err = reset_control_assert(vic->rst);
- if (err < 0)
- return err;
-
- usleep_range(2000, 4000);
-
- clk_disable_unprepare(vic->clk);
-
- vic->booted = false;
-
- return 0;
-}
-
static int vic_boot(struct vic *vic)
{
#ifdef CONFIG_IOMMU_API
@@ -103,9 +60,6 @@ static int vic_boot(struct vic *vic)
void *hdr;
int err = 0;
- if (vic->booted)
- return 0;
-
#ifdef CONFIG_IOMMU_API
if (vic->config->supports_sid && spec) {
u32 value;
@@ -168,8 +122,6 @@ static int vic_boot(struct vic *vic)
return err;
}
- vic->booted = true;
-
return 0;
}
@@ -323,35 +275,74 @@ cleanup:
return err;
}
-static int vic_open_channel(struct tegra_drm_client *client,
- struct tegra_drm_context *context)
+
+static int vic_runtime_resume(struct device *dev)
{
- struct vic *vic = to_vic(client);
+ struct vic *vic = dev_get_drvdata(dev);
int err;
- err = pm_runtime_resume_and_get(vic->dev);
+ err = clk_prepare_enable(vic->clk);
if (err < 0)
return err;
+ usleep_range(10, 20);
+
+ err = reset_control_deassert(vic->rst);
+ if (err < 0)
+ goto disable;
+
+ usleep_range(10, 20);
+
err = vic_load_firmware(vic);
if (err < 0)
- goto rpm_put;
+ goto assert;
err = vic_boot(vic);
if (err < 0)
- goto rpm_put;
+ goto assert;
+
+ return 0;
+
+assert:
+ reset_control_assert(vic->rst);
+disable:
+ clk_disable_unprepare(vic->clk);
+ return err;
+}
+
+static int vic_runtime_suspend(struct device *dev)
+{
+ struct vic *vic = dev_get_drvdata(dev);
+ int err;
+
+ err = reset_control_assert(vic->rst);
+ if (err < 0)
+ return err;
+
+ usleep_range(2000, 4000);
+
+ clk_disable_unprepare(vic->clk);
+
+ return 0;
+}
+
+static int vic_open_channel(struct tegra_drm_client *client,
+ struct tegra_drm_context *context)
+{
+ struct vic *vic = to_vic(client);
+ int err;
+
+ err = pm_runtime_resume_and_get(vic->dev);
+ if (err < 0)
+ return err;
context->channel = host1x_channel_get(vic->channel);
if (!context->channel) {
- err = -ENOMEM;
- goto rpm_put;
+ pm_runtime_put(vic->dev);
+ return -ENOMEM;
}
return 0;
-
-rpm_put:
- pm_runtime_put(vic->dev);
- return err;
}
static void vic_close_channel(struct tegra_drm_context *context)
@@ -359,7 +350,6 @@ static void vic_close_channel(struct tegra_drm_context *context)
struct vic *vic = to_vic(context->client);
host1x_channel_put(context->channel);
-
pm_runtime_put(vic->dev);
}
diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c
index 66e3c86eb5c7..d620f35688da 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.c
+++ b/drivers/gpu/drm/tidss/tidss_drv.c
@@ -16,7 +16,6 @@
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
@@ -118,11 +117,6 @@ static const struct drm_driver tidss_driver = {
.date = "20180215",
.major = 1,
.minor = 0,
-
- .irq_preinstall = tidss_irq_preinstall,
- .irq_postinstall = tidss_irq_postinstall,
- .irq_handler = tidss_irq_handler,
- .irq_uninstall = tidss_irq_uninstall,
};
static int tidss_probe(struct platform_device *pdev)
@@ -172,10 +166,11 @@ static int tidss_probe(struct platform_device *pdev)
ret = irq;
goto err_runtime_suspend;
}
+ tidss->irq = irq;
- ret = drm_irq_install(ddev, irq);
+ ret = tidss_irq_install(ddev, irq);
if (ret) {
- dev_err(dev, "drm_irq_install failed: %d\n", ret);
+ dev_err(dev, "tidss_irq_install failed: %d\n", ret);
goto err_runtime_suspend;
}
@@ -196,7 +191,7 @@ static int tidss_probe(struct platform_device *pdev)
return 0;
err_irq_uninstall:
- drm_irq_uninstall(ddev);
+ tidss_irq_uninstall(ddev);
err_runtime_suspend:
#ifndef CONFIG_PM
@@ -219,7 +214,7 @@ static int tidss_remove(struct platform_device *pdev)
drm_atomic_helper_shutdown(ddev);
- drm_irq_uninstall(ddev);
+ tidss_irq_uninstall(ddev);
#ifndef CONFIG_PM
/* If we don't have PM, we need to call suspend manually */
diff --git a/drivers/gpu/drm/tidss/tidss_drv.h b/drivers/gpu/drm/tidss/tidss_drv.h
index 7de4bba52e6f..d7f27b0b0315 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.h
+++ b/drivers/gpu/drm/tidss/tidss_drv.h
@@ -27,6 +27,8 @@ struct tidss_device {
unsigned int num_planes;
struct drm_plane *planes[TIDSS_MAX_PLANES];
+ unsigned int irq;
+
spinlock_t wait_lock; /* protects the irq masks */
dispc_irq_t irq_mask; /* enabled irqs in addition to wait_list */
};
diff --git a/drivers/gpu/drm/tidss/tidss_irq.c b/drivers/gpu/drm/tidss/tidss_irq.c
index a5ec7931ef6b..0c681c7600bc 100644
--- a/drivers/gpu/drm/tidss/tidss_irq.c
+++ b/drivers/gpu/drm/tidss/tidss_irq.c
@@ -4,6 +4,9 @@
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
*/
+#include <linux/platform_device.h>
+
+#include <drm/drm_drv.h>
#include <drm/drm_print.h>
#include "tidss_crtc.h"
@@ -50,16 +53,13 @@ void tidss_irq_disable_vblank(struct drm_crtc *crtc)
spin_unlock_irqrestore(&tidss->wait_lock, flags);
}
-irqreturn_t tidss_irq_handler(int irq, void *arg)
+static irqreturn_t tidss_irq_handler(int irq, void *arg)
{
struct drm_device *ddev = (struct drm_device *)arg;
struct tidss_device *tidss = to_tidss(ddev);
unsigned int id;
dispc_irq_t irqstatus;
- if (WARN_ON(!ddev->irq_enabled))
- return IRQ_NONE;
-
irqstatus = dispc_read_and_clear_irqstatus(tidss->dispc);
for (id = 0; id < tidss->num_crtcs; id++) {
@@ -93,7 +93,7 @@ void tidss_irq_resume(struct tidss_device *tidss)
spin_unlock_irqrestore(&tidss->wait_lock, flags);
}
-void tidss_irq_preinstall(struct drm_device *ddev)
+static void tidss_irq_preinstall(struct drm_device *ddev)
{
struct tidss_device *tidss = to_tidss(ddev);
@@ -107,7 +107,7 @@ void tidss_irq_preinstall(struct drm_device *ddev)
tidss_runtime_put(tidss);
}
-int tidss_irq_postinstall(struct drm_device *ddev)
+static void tidss_irq_postinstall(struct drm_device *ddev)
{
struct tidss_device *tidss = to_tidss(ddev);
unsigned long flags;
@@ -132,6 +132,22 @@ int tidss_irq_postinstall(struct drm_device *ddev)
spin_unlock_irqrestore(&tidss->wait_lock, flags);
tidss_runtime_put(tidss);
+}
+
+int tidss_irq_install(struct drm_device *ddev, unsigned int irq)
+{
+ int ret;
+
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ tidss_irq_preinstall(ddev);
+
+ ret = request_irq(irq, tidss_irq_handler, 0, ddev->driver->name, ddev);
+ if (ret)
+ return ret;
+
+ tidss_irq_postinstall(ddev);
return 0;
}
@@ -143,4 +159,6 @@ void tidss_irq_uninstall(struct drm_device *ddev)
tidss_runtime_get(tidss);
dispc_set_irqenable(tidss->dispc, 0);
tidss_runtime_put(tidss);
+
+ free_irq(tidss->irq, ddev);
}
diff --git a/drivers/gpu/drm/tidss/tidss_irq.h b/drivers/gpu/drm/tidss/tidss_irq.h
index 4aaad5dfd7c2..b512614d5863 100644
--- a/drivers/gpu/drm/tidss/tidss_irq.h
+++ b/drivers/gpu/drm/tidss/tidss_irq.h
@@ -67,10 +67,8 @@ struct tidss_device;
void tidss_irq_enable_vblank(struct drm_crtc *crtc);
void tidss_irq_disable_vblank(struct drm_crtc *crtc);
-void tidss_irq_preinstall(struct drm_device *ddev);
-int tidss_irq_postinstall(struct drm_device *ddev);
+int tidss_irq_install(struct drm_device *ddev, unsigned int irq);
void tidss_irq_uninstall(struct drm_device *ddev);
-irqreturn_t tidss_irq_handler(int irq, void *arg);
void tidss_irq_resume(struct tidss_device *tidss);
diff --git a/drivers/gpu/drm/tidss/tidss_kms.c b/drivers/gpu/drm/tidss/tidss_kms.c
index 95f8e0f78e32..666e527a0acf 100644
--- a/drivers/gpu/drm/tidss/tidss_kms.c
+++ b/drivers/gpu/drm/tidss/tidss_kms.c
@@ -227,10 +227,8 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
}
ret = drm_bridge_attach(enc, pipes[i].bridge, NULL, 0);
- if (ret) {
- dev_err(tidss->dev, "bridge attach failed: %d\n", ret);
+ if (ret)
return ret;
- }
}
/* create overlay planes of the leftover planes */
diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
index 1acd15aa4193..217415ec8eea 100644
--- a/drivers/gpu/drm/tidss/tidss_plane.c
+++ b/drivers/gpu/drm/tidss/tidss_plane.c
@@ -158,7 +158,6 @@ static void drm_plane_destroy(struct drm_plane *plane)
}
static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = {
- .prepare_fb = drm_gem_plane_helper_prepare_fb,
.atomic_check = tidss_plane_atomic_check,
.atomic_update = tidss_plane_atomic_update,
.atomic_disable = tidss_plane_atomic_disable,
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index f1d3a9f919fd..6b03f89a98d4 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -20,7 +20,6 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_irq.h>
#include <drm/drm_mm.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
@@ -124,6 +123,39 @@ static int cpufreq_transition(struct notifier_block *nb,
}
#endif
+static irqreturn_t tilcdc_irq(int irq, void *arg)
+{
+ struct drm_device *dev = arg;
+ struct tilcdc_drm_private *priv = dev->dev_private;
+
+ return tilcdc_crtc_irq(priv->crtc);
+}
+
+static int tilcdc_irq_install(struct drm_device *dev, unsigned int irq)
+{
+ struct tilcdc_drm_private *priv = dev->dev_private;
+ int ret;
+
+ ret = request_irq(irq, tilcdc_irq, 0, dev->driver->name, dev);
+ if (ret)
+ return ret;
+
+ priv->irq_enabled = false;
+
+ return 0;
+}
+
+static void tilcdc_irq_uninstall(struct drm_device *dev)
+{
+ struct tilcdc_drm_private *priv = dev->dev_private;
+
+ if (!priv->irq_enabled)
+ return;
+
+ free_irq(priv->irq, dev);
+ priv->irq_enabled = false;
+}
+
/*
* DRM operations:
*/
@@ -145,7 +177,7 @@ static void tilcdc_fini(struct drm_device *dev)
drm_dev_unregister(dev);
drm_kms_helper_poll_fini(dev);
- drm_irq_uninstall(dev);
+ tilcdc_irq_uninstall(dev);
drm_mode_config_cleanup(dev);
if (priv->clk)
@@ -336,7 +368,12 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
goto init_failed;
}
- ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ goto init_failed;
+ priv->irq = ret;
+
+ ret = tilcdc_irq_install(ddev, priv->irq);
if (ret < 0) {
dev_err(dev, "failed to install IRQ handler\n");
goto init_failed;
@@ -360,13 +397,6 @@ init_failed:
return ret;
}
-static irqreturn_t tilcdc_irq(int irq, void *arg)
-{
- struct drm_device *dev = arg;
- struct tilcdc_drm_private *priv = dev->dev_private;
- return tilcdc_crtc_irq(priv->crtc);
-}
-
#if defined(CONFIG_DEBUG_FS)
static const struct {
const char *name;
@@ -454,7 +484,6 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
static const struct drm_driver tilcdc_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
- .irq_handler = tilcdc_irq,
DRM_GEM_CMA_DRIVER_OPS,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = tilcdc_debugfs_init,
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
index d29806ca8817..b818448c83f6 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -46,6 +46,8 @@ struct tilcdc_drm_private {
struct clk *clk; /* functional clock */
int rev; /* IP revision */
+ unsigned int irq;
+
/* don't attempt resolutions w/ higher W * H * Hz: */
uint32_t max_bandwidth;
/*
@@ -82,6 +84,7 @@ struct tilcdc_drm_private {
bool is_registered;
bool is_componentized;
+ bool irq_enabled;
};
/* Sub-module for display. Since we don't know at compile time what panels
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
index b177525588c1..7594cf6e186e 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -93,10 +93,8 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
priv->external_encoder->possible_crtcs = BIT(0);
ret = drm_bridge_attach(priv->external_encoder, bridge, NULL, 0);
- if (ret) {
- dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret);
+ if (ret)
return ret;
- }
tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default);
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index d46f95d9196d..d31be274a2bd 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -10,6 +10,19 @@ config DRM_ARCPGU
If M is selected the module will be called arcpgu.
+config DRM_BOCHS
+ tristate "DRM Support for bochs dispi vga interface (qemu stdvga)"
+ depends on DRM && PCI && MMU
+ select DRM_KMS_HELPER
+ select DRM_VRAM_HELPER
+ select DRM_TTM
+ select DRM_TTM_HELPER
+ help
+ This is a KMS driver for qemu's stdvga output. Choose this option
+ for qemu.
+
+ If M is selected the module will be called bochs.
+
config DRM_CIRRUS_QEMU
tristate "Cirrus driver for QEMU emulated device"
depends on DRM && PCI && MMU
@@ -51,8 +64,8 @@ config DRM_SIMPLEDRM
buffer, size, and display format must be provided via device tree,
UEFI, VESA, etc.
- On x86 and compatible, you should also select CONFIG_X86_SYSFB to
- use UEFI and VESA framebuffers.
+ On x86 BIOS or UEFI systems, you should also select SYSFB_SIMPLEFB
+ to use UEFI and VESA framebuffers.
config TINYDRM_HX8357D
tristate "DRM support for HX8357D display panels"
diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile
index 9cc847e756da..e09942895c77 100644
--- a/drivers/gpu/drm/tiny/Makefile
+++ b/drivers/gpu/drm/tiny/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
+obj-$(CONFIG_DRM_BOCHS) += bochs.o
obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
obj-$(CONFIG_DRM_GM12U320) += gm12u320.o
obj-$(CONFIG_DRM_SIMPLEDRM) += simpledrm.o
diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c
new file mode 100644
index 000000000000..73415fa9ae0f
--- /dev/null
+++ b/drivers/gpu/drm/tiny/bochs.c
@@ -0,0 +1,733 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/console.h>
+#include <linux/pci.h>
+
+#include <drm/drm_aperture.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include <video/vga.h>
+
+/* ---------------------------------------------------------------------- */
+
+#define VBE_DISPI_IOPORT_INDEX 0x01CE
+#define VBE_DISPI_IOPORT_DATA 0x01CF
+
+#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_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
+
+static int bochs_modeset = -1;
+static int defx = 1024;
+static int defy = 768;
+
+module_param_named(modeset, bochs_modeset, int, 0444);
+MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
+
+module_param(defx, int, 0444);
+module_param(defy, int, 0444);
+MODULE_PARM_DESC(defx, "default x resolution");
+MODULE_PARM_DESC(defy, "default y resolution");
+
+/* ---------------------------------------------------------------------- */
+
+enum bochs_types {
+ BOCHS_QEMU_STDVGA,
+ BOCHS_UNKNOWN,
+};
+
+struct bochs_device {
+ /* hw */
+ void __iomem *mmio;
+ int ioports;
+ void __iomem *fb_map;
+ unsigned long fb_base;
+ unsigned long fb_size;
+ unsigned long qext_size;
+
+ /* mode */
+ u16 xres;
+ u16 yres;
+ u16 yres_virtual;
+ u32 stride;
+ u32 bpp;
+ struct edid *edid;
+
+ /* drm */
+ struct drm_device *dev;
+ struct drm_simple_display_pipe pipe;
+ struct drm_connector connector;
+};
+
+/* ---------------------------------------------------------------------- */
+
+static void bochs_vga_writeb(struct bochs_device *bochs, u16 ioport, u8 val)
+{
+ if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
+ return;
+
+ if (bochs->mmio) {
+ int offset = ioport - 0x3c0 + 0x400;
+
+ writeb(val, bochs->mmio + offset);
+ } else {
+ outb(val, ioport);
+ }
+}
+
+static u8 bochs_vga_readb(struct bochs_device *bochs, u16 ioport)
+{
+ if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
+ return 0xff;
+
+ if (bochs->mmio) {
+ int offset = ioport - 0x3c0 + 0x400;
+
+ return readb(bochs->mmio + offset);
+ } else {
+ return inb(ioport);
+ }
+}
+
+static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
+{
+ u16 ret = 0;
+
+ if (bochs->mmio) {
+ int offset = 0x500 + (reg << 1);
+
+ ret = readw(bochs->mmio + offset);
+ } else {
+ outw(reg, VBE_DISPI_IOPORT_INDEX);
+ ret = inw(VBE_DISPI_IOPORT_DATA);
+ }
+ return ret;
+}
+
+static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
+{
+ if (bochs->mmio) {
+ int offset = 0x500 + (reg << 1);
+
+ writew(val, bochs->mmio + offset);
+ } else {
+ outw(reg, VBE_DISPI_IOPORT_INDEX);
+ outw(val, VBE_DISPI_IOPORT_DATA);
+ }
+}
+
+static void bochs_hw_set_big_endian(struct bochs_device *bochs)
+{
+ if (bochs->qext_size < 8)
+ return;
+
+ writel(0xbebebebe, bochs->mmio + 0x604);
+}
+
+static void bochs_hw_set_little_endian(struct bochs_device *bochs)
+{
+ if (bochs->qext_size < 8)
+ return;
+
+ writel(0x1e1e1e1e, bochs->mmio + 0x604);
+}
+
+#ifdef __BIG_ENDIAN
+#define bochs_hw_set_native_endian(_b) bochs_hw_set_big_endian(_b)
+#else
+#define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b)
+#endif
+
+static int bochs_get_edid_block(void *data, u8 *buf,
+ unsigned int block, size_t len)
+{
+ struct bochs_device *bochs = data;
+ size_t i, start = block * EDID_LENGTH;
+
+ if (start + len > 0x400 /* vga register offset */)
+ return -1;
+
+ for (i = 0; i < len; i++)
+ buf[i] = readb(bochs->mmio + start + i);
+
+ return 0;
+}
+
+static int bochs_hw_load_edid(struct bochs_device *bochs)
+{
+ u8 header[8];
+
+ if (!bochs->mmio)
+ return -1;
+
+ /* check header to detect whenever edid support is enabled in qemu */
+ bochs_get_edid_block(bochs, header, 0, ARRAY_SIZE(header));
+ if (drm_edid_header_is_valid(header) != 8)
+ return -1;
+
+ kfree(bochs->edid);
+ bochs->edid = drm_do_get_edid(&bochs->connector,
+ bochs_get_edid_block, bochs);
+ if (bochs->edid == NULL)
+ return -1;
+
+ return 0;
+}
+
+static int bochs_hw_init(struct drm_device *dev)
+{
+ struct bochs_device *bochs = dev->dev_private;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ unsigned long addr, size, mem, ioaddr, iosize;
+ u16 id;
+
+ if (pdev->resource[2].flags & IORESOURCE_MEM) {
+ /* mmio bar with vga and bochs registers present */
+ if (pci_request_region(pdev, 2, "bochs-drm") != 0) {
+ DRM_ERROR("Cannot request mmio region\n");
+ return -EBUSY;
+ }
+ ioaddr = pci_resource_start(pdev, 2);
+ iosize = pci_resource_len(pdev, 2);
+ bochs->mmio = ioremap(ioaddr, iosize);
+ if (bochs->mmio == NULL) {
+ DRM_ERROR("Cannot map mmio region\n");
+ return -ENOMEM;
+ }
+ } else {
+ ioaddr = VBE_DISPI_IOPORT_INDEX;
+ iosize = 2;
+ if (!request_region(ioaddr, iosize, "bochs-drm")) {
+ DRM_ERROR("Cannot request ioports\n");
+ return -EBUSY;
+ }
+ bochs->ioports = 1;
+ }
+
+ id = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID);
+ mem = bochs_dispi_read(bochs, VBE_DISPI_INDEX_VIDEO_MEMORY_64K)
+ * 64 * 1024;
+ if ((id & 0xfff0) != VBE_DISPI_ID0) {
+ DRM_ERROR("ID mismatch\n");
+ return -ENODEV;
+ }
+
+ if ((pdev->resource[0].flags & IORESOURCE_MEM) == 0)
+ return -ENODEV;
+ addr = pci_resource_start(pdev, 0);
+ size = pci_resource_len(pdev, 0);
+ if (addr == 0)
+ return -ENODEV;
+ if (size != mem) {
+ DRM_ERROR("Size mismatch: pci=%ld, bochs=%ld\n",
+ size, mem);
+ size = min(size, mem);
+ }
+
+ if (pci_request_region(pdev, 0, "bochs-drm") != 0)
+ DRM_WARN("Cannot request framebuffer, boot fb still active?\n");
+
+ bochs->fb_map = ioremap(addr, size);
+ if (bochs->fb_map == NULL) {
+ DRM_ERROR("Cannot map framebuffer\n");
+ return -ENOMEM;
+ }
+ bochs->fb_base = addr;
+ bochs->fb_size = size;
+
+ DRM_INFO("Found bochs VGA, ID 0x%x.\n", id);
+ DRM_INFO("Framebuffer size %ld kB @ 0x%lx, %s @ 0x%lx.\n",
+ size / 1024, addr,
+ bochs->ioports ? "ioports" : "mmio",
+ ioaddr);
+
+ if (bochs->mmio && pdev->revision >= 2) {
+ bochs->qext_size = readl(bochs->mmio + 0x600);
+ if (bochs->qext_size < 4 || bochs->qext_size > iosize) {
+ bochs->qext_size = 0;
+ goto noext;
+ }
+ DRM_DEBUG("Found qemu ext regs, size %ld\n",
+ bochs->qext_size);
+ bochs_hw_set_native_endian(bochs);
+ }
+
+noext:
+ return 0;
+}
+
+static void bochs_hw_fini(struct drm_device *dev)
+{
+ struct bochs_device *bochs = dev->dev_private;
+
+ /* TODO: shot down existing vram mappings */
+
+ if (bochs->mmio)
+ iounmap(bochs->mmio);
+ if (bochs->ioports)
+ release_region(VBE_DISPI_IOPORT_INDEX, 2);
+ if (bochs->fb_map)
+ iounmap(bochs->fb_map);
+ pci_release_regions(to_pci_dev(dev->dev));
+ kfree(bochs->edid);
+}
+
+static void bochs_hw_blank(struct bochs_device *bochs, bool blank)
+{
+ DRM_DEBUG_DRIVER("hw_blank %d\n", blank);
+ /* discard ar_flip_flop */
+ (void)bochs_vga_readb(bochs, VGA_IS1_RC);
+ /* blank or unblank; we need only update index and set 0x20 */
+ bochs_vga_writeb(bochs, VGA_ATT_W, blank ? 0 : 0x20);
+}
+
+static void bochs_hw_setmode(struct bochs_device *bochs, struct drm_display_mode *mode)
+{
+ int idx;
+
+ if (!drm_dev_enter(bochs->dev, &idx))
+ return;
+
+ bochs->xres = mode->hdisplay;
+ bochs->yres = mode->vdisplay;
+ bochs->bpp = 32;
+ bochs->stride = mode->hdisplay * (bochs->bpp / 8);
+ bochs->yres_virtual = bochs->fb_size / bochs->stride;
+
+ DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n",
+ bochs->xres, bochs->yres, bochs->bpp,
+ bochs->yres_virtual);
+
+ bochs_hw_blank(bochs, false);
+
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE, 0);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_BPP, bochs->bpp);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_XRES, bochs->xres);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_YRES, bochs->yres);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_BANK, 0);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH, bochs->xres);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_HEIGHT,
+ bochs->yres_virtual);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, 0);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, 0);
+
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
+ VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+
+ drm_dev_exit(idx);
+}
+
+static void bochs_hw_setformat(struct bochs_device *bochs, const struct drm_format_info *format)
+{
+ int idx;
+
+ if (!drm_dev_enter(bochs->dev, &idx))
+ return;
+
+ DRM_DEBUG_DRIVER("format %c%c%c%c\n",
+ (format->format >> 0) & 0xff,
+ (format->format >> 8) & 0xff,
+ (format->format >> 16) & 0xff,
+ (format->format >> 24) & 0xff);
+
+ switch (format->format) {
+ case DRM_FORMAT_XRGB8888:
+ bochs_hw_set_little_endian(bochs);
+ break;
+ case DRM_FORMAT_BGRX8888:
+ bochs_hw_set_big_endian(bochs);
+ break;
+ default:
+ /* should not happen */
+ DRM_ERROR("%s: Huh? Got framebuffer format 0x%x",
+ __func__, format->format);
+ break;
+ }
+
+ drm_dev_exit(idx);
+}
+
+static void bochs_hw_setbase(struct bochs_device *bochs, int x, int y, int stride, u64 addr)
+{
+ unsigned long offset;
+ unsigned int vx, vy, vwidth, idx;
+
+ if (!drm_dev_enter(bochs->dev, &idx))
+ return;
+
+ bochs->stride = stride;
+ offset = (unsigned long)addr +
+ y * bochs->stride +
+ x * (bochs->bpp / 8);
+ vy = offset / bochs->stride;
+ vx = (offset % bochs->stride) * 8 / bochs->bpp;
+ vwidth = stride * 8 / bochs->bpp;
+
+ DRM_DEBUG_DRIVER("x %d, y %d, addr %llx -> offset %lx, vx %d, vy %d\n",
+ x, y, addr, offset, vx, vy);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH, vwidth);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, vx);
+ bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, vy);
+
+ drm_dev_exit(idx);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static const uint32_t bochs_formats[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_BGRX8888,
+};
+
+static void bochs_plane_update(struct bochs_device *bochs, struct drm_plane_state *state)
+{
+ struct drm_gem_vram_object *gbo;
+ s64 gpu_addr;
+
+ if (!state->fb || !bochs->stride)
+ return;
+
+ gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
+ gpu_addr = drm_gem_vram_offset(gbo);
+ if (WARN_ON_ONCE(gpu_addr < 0))
+ return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
+
+ bochs_hw_setbase(bochs,
+ state->crtc_x,
+ state->crtc_y,
+ state->fb->pitches[0],
+ state->fb->offsets[0] + gpu_addr);
+ bochs_hw_setformat(bochs, state->fb->format);
+}
+
+static void bochs_pipe_enable(struct drm_simple_display_pipe *pipe,
+ struct drm_crtc_state *crtc_state,
+ struct drm_plane_state *plane_state)
+{
+ struct bochs_device *bochs = pipe->crtc.dev->dev_private;
+
+ bochs_hw_setmode(bochs, &crtc_state->mode);
+ bochs_plane_update(bochs, plane_state);
+}
+
+static void bochs_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+ struct bochs_device *bochs = pipe->crtc.dev->dev_private;
+
+ bochs_hw_blank(bochs, true);
+}
+
+static void bochs_pipe_update(struct drm_simple_display_pipe *pipe,
+ struct drm_plane_state *old_state)
+{
+ struct bochs_device *bochs = pipe->crtc.dev->dev_private;
+
+ bochs_plane_update(bochs, pipe->plane.state);
+}
+
+static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {
+ .enable = bochs_pipe_enable,
+ .disable = bochs_pipe_disable,
+ .update = bochs_pipe_update,
+ .prepare_fb = drm_gem_vram_simple_display_pipe_prepare_fb,
+ .cleanup_fb = drm_gem_vram_simple_display_pipe_cleanup_fb,
+};
+
+static int bochs_connector_get_modes(struct drm_connector *connector)
+{
+ struct bochs_device *bochs =
+ container_of(connector, struct bochs_device, connector);
+ int count = 0;
+
+ if (bochs->edid)
+ count = drm_add_edid_modes(connector, bochs->edid);
+
+ if (!count) {
+ count = drm_add_modes_noedid(connector, 8192, 8192);
+ drm_set_preferred_mode(connector, defx, defy);
+ }
+ return count;
+}
+
+static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
+ .get_modes = bochs_connector_get_modes,
+};
+
+static const struct drm_connector_funcs bochs_connector_connector_funcs = {
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static void bochs_connector_init(struct drm_device *dev)
+{
+ struct bochs_device *bochs = dev->dev_private;
+ struct drm_connector *connector = &bochs->connector;
+
+ drm_connector_init(dev, connector, &bochs_connector_connector_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL);
+ drm_connector_helper_add(connector, &bochs_connector_connector_helper_funcs);
+
+ bochs_hw_load_edid(bochs);
+ if (bochs->edid) {
+ DRM_INFO("Found EDID data blob.\n");
+ drm_connector_attach_edid_property(connector);
+ drm_connector_update_edid_property(connector, bochs->edid);
+ }
+}
+
+static struct drm_framebuffer *
+bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
+ mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
+ return ERR_PTR(-EINVAL);
+
+ return drm_gem_fb_create(dev, file, mode_cmd);
+}
+
+static const struct drm_mode_config_funcs bochs_mode_funcs = {
+ .fb_create = bochs_gem_fb_create,
+ .mode_valid = drm_vram_helper_mode_valid,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+static int bochs_kms_init(struct bochs_device *bochs)
+{
+ int ret;
+
+ ret = drmm_mode_config_init(bochs->dev);
+ if (ret)
+ return ret;
+
+ bochs->dev->mode_config.max_width = 8192;
+ bochs->dev->mode_config.max_height = 8192;
+
+ bochs->dev->mode_config.fb_base = bochs->fb_base;
+ bochs->dev->mode_config.preferred_depth = 24;
+ bochs->dev->mode_config.prefer_shadow = 0;
+ bochs->dev->mode_config.prefer_shadow_fbdev = 1;
+ bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
+
+ bochs->dev->mode_config.funcs = &bochs_mode_funcs;
+
+ bochs_connector_init(bochs->dev);
+ drm_simple_display_pipe_init(bochs->dev,
+ &bochs->pipe,
+ &bochs_pipe_funcs,
+ bochs_formats,
+ ARRAY_SIZE(bochs_formats),
+ NULL,
+ &bochs->connector);
+
+ drm_mode_config_reset(bochs->dev);
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* drm interface */
+
+static int bochs_load(struct drm_device *dev)
+{
+ struct bochs_device *bochs;
+ int ret;
+
+ bochs = drmm_kzalloc(dev, sizeof(*bochs), GFP_KERNEL);
+ if (bochs == NULL)
+ return -ENOMEM;
+ dev->dev_private = bochs;
+ bochs->dev = dev;
+
+ ret = bochs_hw_init(dev);
+ if (ret)
+ return ret;
+
+ ret = drmm_vram_helper_init(dev, bochs->fb_base, bochs->fb_size);
+ if (ret)
+ return ret;
+
+ ret = bochs_kms_init(bochs);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+DEFINE_DRM_GEM_FOPS(bochs_fops);
+
+static const struct drm_driver bochs_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ .fops = &bochs_fops,
+ .name = "bochs-drm",
+ .desc = "bochs dispi vga interface (qemu stdvga)",
+ .date = "20130925",
+ .major = 1,
+ .minor = 0,
+ DRM_GEM_VRAM_DRIVER,
+};
+
+/* ---------------------------------------------------------------------- */
+/* pm interface */
+
+#ifdef CONFIG_PM_SLEEP
+static int bochs_pm_suspend(struct device *dev)
+{
+ struct drm_device *drm_dev = dev_get_drvdata(dev);
+
+ return drm_mode_config_helper_suspend(drm_dev);
+}
+
+static int bochs_pm_resume(struct device *dev)
+{
+ struct drm_device *drm_dev = dev_get_drvdata(dev);
+
+ return drm_mode_config_helper_resume(drm_dev);
+}
+#endif
+
+static const struct dev_pm_ops bochs_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
+ bochs_pm_resume)
+};
+
+/* ---------------------------------------------------------------------- */
+/* pci interface */
+
+static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct drm_device *dev;
+ unsigned long fbsize;
+ int ret;
+
+ fbsize = pci_resource_len(pdev, 0);
+ if (fbsize < 4 * 1024 * 1024) {
+ DRM_ERROR("less than 4 MB video memory, ignoring device\n");
+ return -ENOMEM;
+ }
+
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &bochs_driver);
+ if (ret)
+ return ret;
+
+ dev = drm_dev_alloc(&bochs_driver, &pdev->dev);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
+
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ goto err_free_dev;
+
+ pci_set_drvdata(pdev, dev);
+
+ ret = bochs_load(dev);
+ if (ret)
+ goto err_free_dev;
+
+ ret = drm_dev_register(dev, 0);
+ if (ret)
+ goto err_free_dev;
+
+ drm_fbdev_generic_setup(dev, 32);
+ return ret;
+
+err_free_dev:
+ drm_dev_put(dev);
+ return ret;
+}
+
+static void bochs_pci_remove(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ drm_dev_unplug(dev);
+ drm_atomic_helper_shutdown(dev);
+ bochs_hw_fini(dev);
+ drm_dev_put(dev);
+}
+
+static const struct pci_device_id bochs_pci_tbl[] = {
+ {
+ .vendor = 0x1234,
+ .device = 0x1111,
+ .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
+ .subdevice = PCI_SUBDEVICE_ID_QEMU,
+ .driver_data = BOCHS_QEMU_STDVGA,
+ },
+ {
+ .vendor = 0x1234,
+ .device = 0x1111,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = BOCHS_UNKNOWN,
+ },
+ { /* end of list */ }
+};
+
+static struct pci_driver bochs_pci_driver = {
+ .name = "bochs-drm",
+ .id_table = bochs_pci_tbl,
+ .probe = bochs_pci_probe,
+ .remove = bochs_pci_remove,
+ .driver.pm = &bochs_pm_ops,
+};
+
+/* ---------------------------------------------------------------------- */
+/* module init/exit */
+
+static int __init bochs_init(void)
+{
+ if (vgacon_text_force() && bochs_modeset == -1)
+ return -EINVAL;
+
+ if (bochs_modeset == 0)
+ return -EINVAL;
+
+ return pci_register_driver(&bochs_pci_driver);
+}
+
+static void __exit bochs_exit(void)
+{
+ pci_unregister_driver(&bochs_pci_driver);
+}
+
+module_init(bochs_init);
+module_exit(bochs_exit);
+
+MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
+MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c
index 42611dacde88..4611ec408506 100644
--- a/drivers/gpu/drm/tiny/cirrus.c
+++ b/drivers/gpu/drm/tiny/cirrus.c
@@ -435,7 +435,7 @@ static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb);
- cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->map[0]);
+ cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->data[0]);
}
static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -451,7 +451,7 @@ static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
cirrus_mode_set(cirrus, &crtc->mode, state->fb);
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
- cirrus_fb_blit_rect(state->fb, &shadow_plane_state->map[0], &rect);
+ cirrus_fb_blit_rect(state->fb, &shadow_plane_state->data[0], &rect);
}
static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
@@ -550,7 +550,7 @@ static int cirrus_pci_probe(struct pci_dev *pdev,
struct cirrus_device *cirrus;
int ret;
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "cirrusdrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &cirrus_driver);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
index a233c86d428b..6bc0c298739c 100644
--- a/drivers/gpu/drm/tiny/gm12u320.c
+++ b/drivers/gpu/drm/tiny/gm12u320.c
@@ -3,7 +3,6 @@
* Copyright 2019 Hans de Goede <hdegoede@redhat.com>
*/
-#include <linux/dma-buf.h>
#include <linux/module.h>
#include <linux/usb.h>
@@ -268,13 +267,10 @@ static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
y2 = gm12u320->fb_update.rect.y2;
vaddr = gm12u320->fb_update.src_map.vaddr; /* TODO: Use mapping abstraction properly */
- if (fb->obj[0]->import_attach) {
- ret = dma_buf_begin_cpu_access(
- fb->obj[0]->import_attach->dmabuf, DMA_FROM_DEVICE);
- if (ret) {
- GM12U320_ERR("dma_buf_begin_cpu_access err: %d\n", ret);
- goto put_fb;
- }
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret) {
+ GM12U320_ERR("drm_gem_fb_begin_cpu_access err: %d\n", ret);
+ goto put_fb;
}
src = vaddr + y1 * fb->pitches[0] + x1 * 4;
@@ -311,12 +307,7 @@ static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
src += fb->pitches[0];
}
- if (fb->obj[0]->import_attach) {
- ret = dma_buf_end_cpu_access(fb->obj[0]->import_attach->dmabuf,
- DMA_FROM_DEVICE);
- if (ret)
- GM12U320_ERR("dma_buf_end_cpu_access err: %d\n", ret);
- }
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
put_fb:
drm_framebuffer_put(fb);
gm12u320->fb_update.fb = NULL;
@@ -563,7 +554,7 @@ static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT;
- gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->map[0], &rect);
+ gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->data[0], &rect);
}
static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe)
@@ -581,7 +572,7 @@ static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_rect rect;
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
- gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->map[0], &rect);
+ gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect);
}
static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = {
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index da5df93450de..9b33c05732aa 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -184,7 +184,6 @@ static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = {
.enable = yx240qv29_enable,
.disable = mipi_dbi_pipe_disable,
.update = mipi_dbi_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static const struct drm_display_mode yx350hv15_mode = {
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
index 69265d8a3beb..976d3209f164 100644
--- a/drivers/gpu/drm/tiny/ili9225.c
+++ b/drivers/gpu/drm/tiny/ili9225.c
@@ -328,7 +328,6 @@ static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = {
.enable = ili9225_pipe_enable,
.disable = ili9225_pipe_disable,
.update = ili9225_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static const struct drm_display_mode ili9225_mode = {
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index ad9ce7b4f76f..37e0c33399c8 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -140,7 +140,6 @@ static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = {
.enable = yx240qv29_enable,
.disable = mipi_dbi_pipe_disable,
.update = mipi_dbi_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static const struct drm_display_mode yx240qv29_mode = {
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index 75aa1476c66c..e9a63f4b2993 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -153,7 +153,6 @@ static const struct drm_simple_display_pipe_funcs waveshare_pipe_funcs = {
.enable = waveshare_enable,
.disable = mipi_dbi_pipe_disable,
.update = mipi_dbi_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static const struct drm_display_mode waveshare_mode = {
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index 82fd1ad3413f..023de49e7a8e 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -144,7 +144,6 @@ static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = {
.enable = mi0283qt_enable,
.disable = mipi_dbi_pipe_disable,
.update = mipi_dbi_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static const struct drm_display_mode mi0283qt_mode = {
diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c
index 2cee07a2e00b..4d07b21a16e6 100644
--- a/drivers/gpu/drm/tiny/repaper.c
+++ b/drivers/gpu/drm/tiny/repaper.c
@@ -14,7 +14,6 @@
*/
#include <linux/delay.h>
-#include <linux/dma-buf.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/property.h>
@@ -532,7 +531,6 @@ static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height)
static int repaper_fb_dirty(struct drm_framebuffer *fb)
{
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
- struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
struct repaper_epd *epd = drm_to_epd(fb->dev);
struct drm_rect clip;
int idx, ret = 0;
@@ -558,21 +556,13 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb)
goto out_exit;
}
- if (import_attach) {
- ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
- DMA_FROM_DEVICE);
- if (ret)
- goto out_free;
- }
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret)
+ goto out_free;
drm_fb_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip);
- if (import_attach) {
- ret = dma_buf_end_cpu_access(import_attach->dmabuf,
- DMA_FROM_DEVICE);
- if (ret)
- goto out_free;
- }
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
repaper_gray8_to_mono_reversed(buf, fb->width, fb->height);
@@ -861,7 +851,6 @@ static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = {
.enable = repaper_pipe_enable,
.disable = repaper_pipe_disable,
.update = repaper_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static int repaper_connector_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 08ae66b1e6f5..481b48bde047 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -639,7 +639,7 @@ simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */
+ void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */
struct drm_device *dev = &sdev->dev;
int idx;
@@ -677,7 +677,7 @@ simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
struct drm_plane_state *plane_state = pipe->plane.state;
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
- void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */
+ void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */
struct drm_framebuffer *fb = plane_state->fb;
struct drm_device *dev = &sdev->dev;
struct drm_rect clip;
diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c
index 05db980cc047..ad0faa8723c2 100644
--- a/drivers/gpu/drm/tiny/st7586.c
+++ b/drivers/gpu/drm/tiny/st7586.c
@@ -6,7 +6,6 @@
*/
#include <linux/delay.h>
-#include <linux/dma-buf.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/property.h>
@@ -21,6 +20,7 @@
#include <drm/drm_format_helper.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_mipi_dbi.h>
#include <drm/drm_rect.h>
@@ -92,24 +92,18 @@ static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
struct drm_rect *clip)
{
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
- struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
void *src = cma_obj->vaddr;
int ret = 0;
- if (import_attach) {
- ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
- DMA_FROM_DEVICE);
- if (ret)
- return ret;
- }
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret)
+ return ret;
st7586_xrgb8888_to_gray332(dst, src, fb, clip);
- if (import_attach)
- ret = dma_buf_end_cpu_access(import_attach->dmabuf,
- DMA_FROM_DEVICE);
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
- return ret;
+ return 0;
}
static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
@@ -268,7 +262,6 @@ static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = {
.enable = st7586_pipe_enable,
.disable = st7586_pipe_disable,
.update = st7586_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static const struct drm_display_mode st7586_mode = {
diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c
index e8b7815d8cae..fc40dd10efa8 100644
--- a/drivers/gpu/drm/tiny/st7735r.c
+++ b/drivers/gpu/drm/tiny/st7735r.c
@@ -136,7 +136,6 @@ static const struct drm_simple_display_pipe_funcs st7735r_pipe_funcs = {
.enable = st7735r_pipe_enable,
.disable = mipi_dbi_pipe_disable,
.update = mipi_dbi_pipe_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
};
static const struct st7735r_cfg jd_t18003_t01_cfg = {
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 8d7fd65ccced..ea4add2b9717 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -488,6 +488,31 @@ void ttm_bo_unlock_delayed_workqueue(struct ttm_device *bdev, int resched)
}
EXPORT_SYMBOL(ttm_bo_unlock_delayed_workqueue);
+static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo,
+ struct ttm_resource **mem,
+ struct ttm_operation_ctx *ctx,
+ struct ttm_place *hop)
+{
+ struct ttm_placement hop_placement;
+ struct ttm_resource *hop_mem;
+ int ret;
+
+ hop_placement.num_placement = hop_placement.num_busy_placement = 1;
+ hop_placement.placement = hop_placement.busy_placement = hop;
+
+ /* find space in the bounce domain */
+ ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx);
+ if (ret)
+ return ret;
+ /* move to the bounce domain */
+ ret = ttm_bo_handle_move_mem(bo, hop_mem, false, ctx, NULL);
+ if (ret) {
+ ttm_resource_free(bo, &hop_mem);
+ return ret;
+ }
+ return 0;
+}
+
static int ttm_bo_evict(struct ttm_buffer_object *bo,
struct ttm_operation_ctx *ctx)
{
@@ -527,12 +552,17 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
goto out;
}
+bounce:
ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop);
- if (unlikely(ret)) {
- WARN(ret == -EMULTIHOP, "Unexpected multihop in eviction - likely driver bug\n");
- if (ret != -ERESTARTSYS)
+ if (ret == -EMULTIHOP) {
+ ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop);
+ if (ret) {
pr_err("Buffer eviction failed\n");
- ttm_resource_free(bo, &evict_mem);
+ ttm_resource_free(bo, &evict_mem);
+ goto out;
+ }
+ /* try and move to final place now. */
+ goto bounce;
}
out:
return ret;
@@ -847,31 +877,6 @@ error:
}
EXPORT_SYMBOL(ttm_bo_mem_space);
-static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo,
- struct ttm_resource **mem,
- struct ttm_operation_ctx *ctx,
- struct ttm_place *hop)
-{
- struct ttm_placement hop_placement;
- struct ttm_resource *hop_mem;
- int ret;
-
- hop_placement.num_placement = hop_placement.num_busy_placement = 1;
- hop_placement.placement = hop_placement.busy_placement = hop;
-
- /* find space in the bounce domain */
- ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx);
- if (ret)
- return ret;
- /* move to the bounce domain */
- ret = ttm_bo_handle_move_mem(bo, hop_mem, false, ctx, NULL);
- if (ret) {
- ttm_resource_free(bo, &hop_mem);
- return ret;
- }
- return 0;
-}
-
static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
struct ttm_placement *placement,
struct ttm_operation_ctx *ctx)
@@ -916,6 +921,9 @@ static bool ttm_bo_places_compat(const struct ttm_place *places,
{
unsigned i;
+ if (mem->placement & TTM_PL_FLAG_TEMPORARY)
+ return false;
+
for (i = 0; i < num_placement; i++) {
const struct ttm_place *heap = &places[i];
diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c
index 50e1fb71869f..17b8c8dd169d 100644
--- a/drivers/gpu/drm/tve200/tve200_display.c
+++ b/drivers/gpu/drm/tve200/tve200_display.c
@@ -316,7 +316,6 @@ static const struct drm_simple_display_pipe_funcs tve200_display_funcs = {
.enable = tve200_display_enable,
.disable = tve200_display_disable,
.update = tve200_display_update,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
.enable_vblank = tve200_display_enable_vblank,
.disable_vblank = tve200_display_disable_vblank,
};
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 8d98bf69d075..32232228dae9 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -6,11 +6,8 @@
* Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
* Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
* Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
-
*/
-#include <linux/dma-buf.h>
-
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
@@ -271,9 +268,8 @@ static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_ma
int x, int y, int width, int height)
{
struct drm_device *dev = fb->dev;
- struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach;
void *vaddr = map->vaddr; /* TODO: Use mapping abstraction properly */
- int i, ret, tmp_ret;
+ int i, ret;
char *cmd;
struct urb *urb;
struct drm_rect clip;
@@ -290,17 +286,14 @@ static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_ma
else if ((clip.x2 > fb->width) || (clip.y2 > fb->height))
return -EINVAL;
- if (import_attach) {
- ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
- DMA_FROM_DEVICE);
- if (ret)
- return ret;
- }
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret)
+ return ret;
urb = udl_get_urb(dev);
if (!urb) {
ret = -ENOMEM;
- goto out_dma_buf_end_cpu_access;
+ goto out_drm_gem_fb_end_cpu_access;
}
cmd = urb->transfer_buffer;
@@ -313,7 +306,7 @@ static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_ma
&cmd, byte_offset, dev_byte_offset,
byte_width);
if (ret)
- goto out_dma_buf_end_cpu_access;
+ goto out_drm_gem_fb_end_cpu_access;
}
if (cmd > (char *)urb->transfer_buffer) {
@@ -329,14 +322,8 @@ static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_ma
ret = 0;
-out_dma_buf_end_cpu_access:
- if (import_attach) {
- tmp_ret = dma_buf_end_cpu_access(import_attach->dmabuf,
- DMA_FROM_DEVICE);
- if (tmp_ret && !ret)
- ret = tmp_ret; /* only update ret if not set yet */
- }
-
+out_drm_gem_fb_end_cpu_access:
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
return ret;
}
@@ -392,7 +379,7 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
udl->mode_buf_len = wrptr - buf;
- udl_handle_damage(fb, &shadow_plane_state->map[0], 0, 0, fb->width, fb->height);
+ udl_handle_damage(fb, &shadow_plane_state->data[0], 0, 0, fb->width, fb->height);
if (!crtc_state->mode_changed)
return;
@@ -435,7 +422,7 @@ udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
return;
if (drm_atomic_helper_damage_merged(old_plane_state, state, &rect))
- udl_handle_damage(fb, &shadow_plane_state->map[0], rect.x1, rect.y1,
+ udl_handle_damage(fb, &shadow_plane_state->data[0], rect.x1, rect.y1,
rect.x2 - rect.x1, rect.y2 - rect.y1);
}
diff --git a/drivers/gpu/drm/v3d/Makefile b/drivers/gpu/drm/v3d/Makefile
index db4cfc155821..e8b314137020 100644
--- a/drivers/gpu/drm/v3d/Makefile
+++ b/drivers/gpu/drm/v3d/Makefile
@@ -9,6 +9,7 @@ v3d-y := \
v3d_gem.o \
v3d_irq.o \
v3d_mmu.o \
+ v3d_perfmon.o \
v3d_trace_points.o \
v3d_sched.o
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index 99e22beea90b..9403c3b36aca 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -94,6 +94,9 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
case DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH:
args->value = 1;
return 0;
+ case DRM_V3D_PARAM_SUPPORTS_PERFMON:
+ args->value = (v3d->ver >= 40);
+ return 0;
default:
DRM_DEBUG("Unknown parameter %d\n", args->param);
return -EINVAL;
@@ -121,6 +124,7 @@ v3d_open(struct drm_device *dev, struct drm_file *file)
1, NULL);
}
+ v3d_perfmon_open_file(v3d_priv);
file->driver_priv = v3d_priv;
return 0;
@@ -136,6 +140,7 @@ v3d_postclose(struct drm_device *dev, struct drm_file *file)
drm_sched_entity_destroy(&v3d_priv->sched_entity[q]);
}
+ v3d_perfmon_close_file(v3d_priv);
kfree(v3d_priv);
}
@@ -156,6 +161,9 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CSD, v3d_submit_csd_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(V3D_PERFMON_CREATE, v3d_perfmon_create_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(V3D_PERFMON_DESTROY, v3d_perfmon_destroy_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),
};
static const struct drm_driver v3d_drm_driver = {
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index 8a390738d65b..270134779073 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -37,6 +37,40 @@ struct v3d_queue_state {
u64 emit_seqno;
};
+/* Performance monitor object. The perform lifetime is controlled by userspace
+ * using perfmon related ioctls. A perfmon can be attached to a submit_cl
+ * request, and when this is the case, HW perf counters will be activated just
+ * before the submit_cl is submitted to the GPU and disabled when the job is
+ * done. This way, only events related to a specific job will be counted.
+ */
+struct v3d_perfmon {
+ /* Tracks the number of users of the perfmon, when this counter reaches
+ * zero the perfmon is destroyed.
+ */
+ refcount_t refcnt;
+
+ /* Protects perfmon stop, as it can be invoked from multiple places. */
+ struct mutex lock;
+
+ /* Number of counters activated in this perfmon instance
+ * (should be less than DRM_V3D_MAX_PERF_COUNTERS).
+ */
+ u8 ncounters;
+
+ /* Events counted by the HW perf counters. */
+ u8 counters[DRM_V3D_MAX_PERF_COUNTERS];
+
+ /* Storage for counter values. Counters are incremented by the
+ * HW perf counter values every time the perfmon is attached
+ * to a GPU job. This way, perfmon users don't have to
+ * retrieve the results after each job if they want to track
+ * events covering several submissions. Note that counter
+ * values can't be reset, but you can fake a reset by
+ * destroying the perfmon and creating a new one.
+ */
+ u64 values[];
+};
+
struct v3d_dev {
struct drm_device drm;
@@ -89,6 +123,9 @@ struct v3d_dev {
*/
spinlock_t job_lock;
+ /* Used to track the active perfmon if any. */
+ struct v3d_perfmon *active_perfmon;
+
/* Protects bo_stats */
struct mutex bo_lock;
@@ -133,6 +170,11 @@ v3d_has_csd(struct v3d_dev *v3d)
struct v3d_file_priv {
struct v3d_dev *v3d;
+ struct {
+ struct idr idr;
+ struct mutex lock;
+ } perfmon;
+
struct drm_sched_entity sched_entity[V3D_MAX_QUEUES];
};
@@ -205,6 +247,11 @@ struct v3d_job {
*/
struct dma_fence *done_fence;
+ /* Pointer to a performance monitor object if the user requested it,
+ * NULL otherwise.
+ */
+ struct v3d_perfmon *perfmon;
+
/* Callback for the freeing of the job on refcount going to 0. */
void (*free)(struct kref *ref);
};
@@ -353,3 +400,19 @@ void v3d_mmu_remove_ptes(struct v3d_bo *bo);
/* v3d_sched.c */
int v3d_sched_init(struct v3d_dev *v3d);
void v3d_sched_fini(struct v3d_dev *v3d);
+
+/* v3d_perfmon.c */
+void v3d_perfmon_get(struct v3d_perfmon *perfmon);
+void v3d_perfmon_put(struct v3d_perfmon *perfmon);
+void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon);
+void v3d_perfmon_stop(struct v3d_dev *v3d, struct v3d_perfmon *perfmon,
+ bool capture);
+struct v3d_perfmon *v3d_perfmon_find(struct v3d_file_priv *v3d_priv, int id);
+void v3d_perfmon_open_file(struct v3d_file_priv *v3d_priv);
+void v3d_perfmon_close_file(struct v3d_file_priv *v3d_priv);
+int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
index 4eb354226972..5689da118197 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -126,6 +126,8 @@ v3d_reset(struct v3d_dev *v3d)
v3d_mmu_set_page_table(v3d);
v3d_irq_reset(v3d);
+ v3d_perfmon_stop(v3d, v3d->active_perfmon, false);
+
trace_v3d_reset_end(dev);
}
@@ -375,6 +377,9 @@ v3d_job_free(struct kref *ref)
pm_runtime_mark_last_busy(job->v3d->drm.dev);
pm_runtime_put_autosuspend(job->v3d->drm.dev);
+ if (job->perfmon)
+ v3d_perfmon_put(job->perfmon);
+
kfree(job);
}
@@ -539,6 +544,9 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
+ if (args->pad != 0)
+ return -EINVAL;
+
if (args->flags != 0 &&
args->flags != DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
DRM_INFO("invalid flags: %d\n", args->flags);
@@ -611,8 +619,20 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
if (ret)
goto fail;
+ if (args->perfmon_id) {
+ render->base.perfmon = v3d_perfmon_find(v3d_priv,
+ args->perfmon_id);
+
+ if (!render->base.perfmon) {
+ ret = -ENOENT;
+ goto fail;
+ }
+ }
+
mutex_lock(&v3d->sched_lock);
if (bin) {
+ bin->base.perfmon = render->base.perfmon;
+ v3d_perfmon_get(bin->base.perfmon);
ret = v3d_push_job(v3d_priv, &bin->base, V3D_BIN);
if (ret)
goto fail_unreserve;
@@ -633,6 +653,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
ret = drm_gem_fence_array_add(&clean_job->deps, render_fence);
if (ret)
goto fail_unreserve;
+ clean_job->perfmon = render->base.perfmon;
+ v3d_perfmon_get(clean_job->perfmon);
ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
if (ret)
goto fail_unreserve;
@@ -827,6 +849,15 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
if (ret)
goto fail;
+ if (args->perfmon_id) {
+ job->base.perfmon = v3d_perfmon_find(v3d_priv,
+ args->perfmon_id);
+ if (!job->base.perfmon) {
+ ret = -ENOENT;
+ goto fail;
+ }
+ }
+
mutex_lock(&v3d->sched_lock);
ret = v3d_push_job(v3d_priv, &job->base, V3D_CSD);
if (ret)
diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c
new file mode 100644
index 000000000000..0288ef063513
--- /dev/null
+++ b/drivers/gpu/drm/v3d/v3d_perfmon.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Raspberry Pi
+ */
+
+#include "v3d_drv.h"
+#include "v3d_regs.h"
+
+#define V3D_PERFMONID_MIN 1
+#define V3D_PERFMONID_MAX U32_MAX
+
+void v3d_perfmon_get(struct v3d_perfmon *perfmon)
+{
+ if (perfmon)
+ refcount_inc(&perfmon->refcnt);
+}
+
+void v3d_perfmon_put(struct v3d_perfmon *perfmon)
+{
+ if (perfmon && refcount_dec_and_test(&perfmon->refcnt))
+ kfree(perfmon);
+}
+
+void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon)
+{
+ unsigned int i;
+ u32 mask;
+ u8 ncounters = perfmon->ncounters;
+
+ if (WARN_ON_ONCE(!perfmon || v3d->active_perfmon))
+ return;
+
+ mask = GENMASK(ncounters - 1, 0);
+
+ for (i = 0; i < ncounters; i++) {
+ u32 source = i / 4;
+ u32 channel = V3D_SET_FIELD(perfmon->counters[i], V3D_PCTR_S0);
+
+ i++;
+ channel |= V3D_SET_FIELD(i < ncounters ? perfmon->counters[i] : 0,
+ V3D_PCTR_S1);
+ i++;
+ channel |= V3D_SET_FIELD(i < ncounters ? perfmon->counters[i] : 0,
+ V3D_PCTR_S2);
+ i++;
+ channel |= V3D_SET_FIELD(i < ncounters ? perfmon->counters[i] : 0,
+ V3D_PCTR_S3);
+ V3D_CORE_WRITE(0, V3D_V4_PCTR_0_SRC_X(source), channel);
+ }
+
+ V3D_CORE_WRITE(0, V3D_V4_PCTR_0_CLR, mask);
+ V3D_CORE_WRITE(0, V3D_PCTR_0_OVERFLOW, mask);
+ V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
+
+ v3d->active_perfmon = perfmon;
+}
+
+void v3d_perfmon_stop(struct v3d_dev *v3d, struct v3d_perfmon *perfmon,
+ bool capture)
+{
+ unsigned int i;
+
+ if (!perfmon || !v3d->active_perfmon)
+ return;
+
+ mutex_lock(&perfmon->lock);
+ if (perfmon != v3d->active_perfmon) {
+ mutex_unlock(&perfmon->lock);
+ return;
+ }
+
+ if (capture)
+ for (i = 0; i < perfmon->ncounters; i++)
+ perfmon->values[i] += V3D_CORE_READ(0, V3D_PCTR_0_PCTRX(i));
+
+ V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, 0);
+
+ v3d->active_perfmon = NULL;
+ mutex_unlock(&perfmon->lock);
+}
+
+struct v3d_perfmon *v3d_perfmon_find(struct v3d_file_priv *v3d_priv, int id)
+{
+ struct v3d_perfmon *perfmon;
+
+ mutex_lock(&v3d_priv->perfmon.lock);
+ perfmon = idr_find(&v3d_priv->perfmon.idr, id);
+ v3d_perfmon_get(perfmon);
+ mutex_unlock(&v3d_priv->perfmon.lock);
+
+ return perfmon;
+}
+
+void v3d_perfmon_open_file(struct v3d_file_priv *v3d_priv)
+{
+ mutex_init(&v3d_priv->perfmon.lock);
+ idr_init(&v3d_priv->perfmon.idr);
+}
+
+static int v3d_perfmon_idr_del(int id, void *elem, void *data)
+{
+ struct v3d_perfmon *perfmon = elem;
+
+ v3d_perfmon_put(perfmon);
+
+ return 0;
+}
+
+void v3d_perfmon_close_file(struct v3d_file_priv *v3d_priv)
+{
+ mutex_lock(&v3d_priv->perfmon.lock);
+ idr_for_each(&v3d_priv->perfmon.idr, v3d_perfmon_idr_del, NULL);
+ idr_destroy(&v3d_priv->perfmon.idr);
+ mutex_unlock(&v3d_priv->perfmon.lock);
+}
+
+int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
+ struct drm_v3d_perfmon_create *req = data;
+ struct v3d_perfmon *perfmon;
+ unsigned int i;
+ int ret;
+
+ /* Number of monitored counters cannot exceed HW limits. */
+ if (req->ncounters > DRM_V3D_MAX_PERF_COUNTERS ||
+ !req->ncounters)
+ return -EINVAL;
+
+ /* Make sure all counters are valid. */
+ for (i = 0; i < req->ncounters; i++) {
+ if (req->counters[i] >= V3D_PERFCNT_NUM)
+ return -EINVAL;
+ }
+
+ perfmon = kzalloc(struct_size(perfmon, values, req->ncounters),
+ GFP_KERNEL);
+ if (!perfmon)
+ return -ENOMEM;
+
+ for (i = 0; i < req->ncounters; i++)
+ perfmon->counters[i] = req->counters[i];
+
+ perfmon->ncounters = req->ncounters;
+
+ refcount_set(&perfmon->refcnt, 1);
+ mutex_init(&perfmon->lock);
+
+ mutex_lock(&v3d_priv->perfmon.lock);
+ ret = idr_alloc(&v3d_priv->perfmon.idr, perfmon, V3D_PERFMONID_MIN,
+ V3D_PERFMONID_MAX, GFP_KERNEL);
+ mutex_unlock(&v3d_priv->perfmon.lock);
+
+ if (ret < 0) {
+ kfree(perfmon);
+ return ret;
+ }
+
+ req->id = ret;
+
+ return 0;
+}
+
+int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
+ struct drm_v3d_perfmon_destroy *req = data;
+ struct v3d_perfmon *perfmon;
+
+ mutex_lock(&v3d_priv->perfmon.lock);
+ perfmon = idr_remove(&v3d_priv->perfmon.idr, req->id);
+ mutex_unlock(&v3d_priv->perfmon.lock);
+
+ if (!perfmon)
+ return -EINVAL;
+
+ v3d_perfmon_put(perfmon);
+
+ return 0;
+}
+
+int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct v3d_dev *v3d = to_v3d_dev(dev);
+ struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
+ struct drm_v3d_perfmon_get_values *req = data;
+ struct v3d_perfmon *perfmon;
+ int ret = 0;
+
+ if (req->pad != 0)
+ return -EINVAL;
+
+ mutex_lock(&v3d_priv->perfmon.lock);
+ perfmon = idr_find(&v3d_priv->perfmon.idr, req->id);
+ v3d_perfmon_get(perfmon);
+ mutex_unlock(&v3d_priv->perfmon.lock);
+
+ if (!perfmon)
+ return -EINVAL;
+
+ v3d_perfmon_stop(v3d, perfmon, true);
+
+ if (copy_to_user(u64_to_user_ptr(req->values_ptr), perfmon->values,
+ perfmon->ncounters * sizeof(u64)))
+ ret = -EFAULT;
+
+ v3d_perfmon_put(perfmon);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h
index 9bcb57781d31..3663e0d6bf76 100644
--- a/drivers/gpu/drm/v3d/v3d_regs.h
+++ b/drivers/gpu/drm/v3d/v3d_regs.h
@@ -347,6 +347,8 @@
/* Each src reg muxes four counters each. */
#define V3D_V4_PCTR_0_SRC_0_3 0x00660
#define V3D_V4_PCTR_0_SRC_28_31 0x0067c
+#define V3D_V4_PCTR_0_SRC_X(x) (V3D_V4_PCTR_0_SRC_0_3 + \
+ 4 * (x))
# define V3D_PCTR_S0_MASK V3D_MASK(6, 0)
# define V3D_PCTR_S0_SHIFT 0
# define V3D_PCTR_S1_MASK V3D_MASK(14, 8)
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index 8992480c88fa..dd7fcc36d726 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -63,6 +63,16 @@ v3d_job_free(struct drm_sched_job *sched_job)
v3d_job_put(job);
}
+static void
+v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job)
+{
+ if (job->perfmon != v3d->active_perfmon)
+ v3d_perfmon_stop(v3d, v3d->active_perfmon, true);
+
+ if (job->perfmon && v3d->active_perfmon != job->perfmon)
+ v3d_perfmon_start(v3d, job->perfmon);
+}
+
/*
* Returns the fences that the job depends on, one by one.
*
@@ -120,6 +130,8 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno,
job->start, job->end);
+ v3d_switch_perfmon(v3d, &job->base);
+
/* Set the current and end address of the control list.
* Writing the end register is what starts the job.
*/
@@ -169,6 +181,8 @@ static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno,
job->start, job->end);
+ v3d_switch_perfmon(v3d, &job->base);
+
/* XXX: Set the QCFG */
/* Set the current and end address of the control list.
@@ -240,6 +254,8 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno);
+ v3d_switch_perfmon(v3d, &job->base);
+
for (i = 1; i <= 6; i++)
V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0 + 4 * i, job->args.cfg[i]);
/* CFG0 write kicks off the job. */
@@ -402,7 +418,7 @@ v3d_sched_init(struct v3d_dev *v3d)
ret = drm_sched_init(&v3d->queue[V3D_BIN].sched,
&v3d_bin_sched_ops,
hw_jobs_limit, job_hang_limit,
- msecs_to_jiffies(hang_limit_ms),
+ msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_bin");
if (ret) {
dev_err(v3d->drm.dev, "Failed to create bin scheduler: %d.", ret);
@@ -412,7 +428,7 @@ v3d_sched_init(struct v3d_dev *v3d)
ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,
&v3d_render_sched_ops,
hw_jobs_limit, job_hang_limit,
- msecs_to_jiffies(hang_limit_ms),
+ msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_render");
if (ret) {
dev_err(v3d->drm.dev, "Failed to create render scheduler: %d.",
@@ -424,7 +440,7 @@ v3d_sched_init(struct v3d_dev *v3d)
ret = drm_sched_init(&v3d->queue[V3D_TFU].sched,
&v3d_tfu_sched_ops,
hw_jobs_limit, job_hang_limit,
- msecs_to_jiffies(hang_limit_ms),
+ msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_tfu");
if (ret) {
dev_err(v3d->drm.dev, "Failed to create TFU scheduler: %d.",
@@ -437,7 +453,7 @@ v3d_sched_init(struct v3d_dev *v3d)
ret = drm_sched_init(&v3d->queue[V3D_CSD].sched,
&v3d_csd_sched_ops,
hw_jobs_limit, job_hang_limit,
- msecs_to_jiffies(hang_limit_ms),
+ msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_csd");
if (ret) {
dev_err(v3d->drm.dev, "Failed to create CSD scheduler: %d.",
@@ -449,7 +465,7 @@ v3d_sched_init(struct v3d_dev *v3d)
ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched,
&v3d_cache_clean_sched_ops,
hw_jobs_limit, job_hang_limit,
- msecs_to_jiffies(hang_limit_ms),
+ msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_cache_clean");
if (ret) {
dev_err(v3d->drm.dev, "Failed to create CACHE_CLEAN scheduler: %d.",
diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c
index 6d4b32da9866..2b81cb259d23 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_drv.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c
@@ -43,7 +43,7 @@ static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!vbox_check_supported(VBE_DISPI_ID_HGSMI))
return -ENODEV;
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "vboxvideodrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver);
if (ret)
return ret;
@@ -184,7 +184,6 @@ static const struct drm_driver driver = {
.lastclose = drm_fb_helper_lastclose,
.fops = &vbox_fops,
- .irq_handler = vbox_irq_handler,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.h b/drivers/gpu/drm/vboxvideo/vbox_drv.h
index ac7c2effc46f..4903b91d7fe4 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_drv.h
+++ b/drivers/gpu/drm/vboxvideo/vbox_drv.h
@@ -145,7 +145,6 @@ void vbox_mm_fini(struct vbox_private *vbox);
int vbox_irq_init(struct vbox_private *vbox);
void vbox_irq_fini(struct vbox_private *vbox);
void vbox_report_hotplug(struct vbox_private *vbox);
-irqreturn_t vbox_irq_handler(int irq, void *arg);
/* vbox_hgsmi.c */
void *hgsmi_buffer_alloc(struct gen_pool *guest_pool, size_t size,
diff --git a/drivers/gpu/drm/vboxvideo/vbox_irq.c b/drivers/gpu/drm/vboxvideo/vbox_irq.c
index b3ded68603ba..903a6c48ee8b 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_irq.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_irq.c
@@ -10,7 +10,8 @@
*/
#include <linux/pci.h>
-#include <drm/drm_irq.h>
+
+#include <drm/drm_drv.h>
#include <drm/drm_probe_helper.h>
#include "vbox_drv.h"
@@ -31,7 +32,7 @@ void vbox_report_hotplug(struct vbox_private *vbox)
schedule_work(&vbox->hotplug_work);
}
-irqreturn_t vbox_irq_handler(int irq, void *arg)
+static irqreturn_t vbox_irq_handler(int irq, void *arg)
{
struct drm_device *dev = (struct drm_device *)arg;
struct vbox_private *vbox = to_vbox_dev(dev);
@@ -170,16 +171,21 @@ static void vbox_hotplug_worker(struct work_struct *work)
int vbox_irq_init(struct vbox_private *vbox)
{
- struct pci_dev *pdev = to_pci_dev(vbox->ddev.dev);
+ struct drm_device *dev = &vbox->ddev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
INIT_WORK(&vbox->hotplug_work, vbox_hotplug_worker);
vbox_update_mode_hints(vbox);
- return drm_irq_install(&vbox->ddev, pdev->irq);
+ /* PCI devices require shared interrupts. */
+ return request_irq(pdev->irq, vbox_irq_handler, IRQF_SHARED, dev->driver->name, dev);
}
void vbox_irq_fini(struct vbox_private *vbox)
{
- drm_irq_uninstall(&vbox->ddev);
+ struct drm_device *dev = &vbox->ddev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+ free_irq(pdev->irq, dev);
flush_work(&vbox->hotplug_work);
}
diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c
index 964381d55fc1..4227a915b06a 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_mode.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c
@@ -398,7 +398,7 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane,
u32 height = new_state->crtc_h;
struct drm_shadow_plane_state *shadow_plane_state =
to_drm_shadow_plane_state(new_state);
- struct dma_buf_map map = shadow_plane_state->map[0];
+ struct dma_buf_map map = shadow_plane_state->data[0];
u8 *src = map.vaddr; /* TODO: Use mapping abstraction properly */
size_t data_size, mask_size;
u32 flags;
@@ -488,8 +488,7 @@ static const struct drm_plane_helper_funcs vbox_primary_helper_funcs = {
.atomic_check = vbox_primary_atomic_check,
.atomic_update = vbox_primary_atomic_update,
.atomic_disable = vbox_primary_atomic_disable,
- .prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
- .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
+ DRM_GEM_VRAM_PLANE_HELPER_FUNCS,
};
static const struct drm_plane_funcs vbox_primary_plane_funcs = {
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
index 118e8a426b1a..345a5570a3da 100644
--- a/drivers/gpu/drm/vc4/Kconfig
+++ b/drivers/gpu/drm/vc4/Kconfig
@@ -12,6 +12,7 @@ config DRM_VC4
select SND_PCM
select SND_PCM_ELD
select SND_SOC_GENERIC_DMAENGINE_PCM
+ select SND_SOC_HDMI_CODEC
select DRM_MIPI_DSI
help
Choose this option if you have a system that has a Broadcom
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 8a60fb8ad370..f6c16c5aee68 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -168,10 +168,6 @@ static struct drm_driver vc4_drm_driver = {
DRIVER_SYNCOBJ),
.open = vc4_open,
.postclose = vc4_close,
- .irq_handler = vc4_irq,
- .irq_preinstall = vc4_irq_preinstall,
- .irq_postinstall = vc4_irq_postinstall,
- .irq_uninstall = vc4_irq_uninstall,
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = vc4_debugfs_init,
@@ -265,7 +261,7 @@ static int vc4_drm_bind(struct device *dev)
if (ret)
goto unbind_all;
- ret = drm_aperture_remove_framebuffers(false, "vc4drmfb");
+ ret = drm_aperture_remove_framebuffers(false, &vc4_drm_driver);
if (ret)
goto unbind_all;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 5dceadc61600..ef73e0aaf726 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -74,6 +74,8 @@ struct vc4_perfmon {
struct vc4_dev {
struct drm_device base;
+ unsigned int irq;
+
struct vc4_hvs *hvs;
struct vc4_v3d *v3d;
struct vc4_dpi *dpi;
@@ -895,9 +897,9 @@ extern struct platform_driver vc4_vec_driver;
extern struct platform_driver vc4_txp_driver;
/* vc4_irq.c */
-irqreturn_t vc4_irq(int irq, void *arg);
-void vc4_irq_preinstall(struct drm_device *dev);
-int vc4_irq_postinstall(struct drm_device *dev);
+void vc4_irq_enable(struct drm_device *dev);
+void vc4_irq_disable(struct drm_device *dev);
+int vc4_irq_install(struct drm_device *dev, int irq);
void vc4_irq_uninstall(struct drm_device *dev);
void vc4_irq_reset(struct drm_device *dev);
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index a55256ed0955..a185027911ce 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -1646,10 +1646,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0);
- if (ret) {
- dev_err(dev, "bridge attach failed: %d\n", ret);
+ if (ret)
return ret;
- }
/* Disable the atomic helper calls into the bridge. We
* manually call the bridge pre_enable / enable / etc. calls
* from our driver, since we need to sequence them within the
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c2876731ee2d..b7dc32a0c9bb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -46,6 +46,7 @@
#include <linux/rational.h>
#include <linux/reset.h>
#include <sound/dmaengine_pcm.h>
+#include <sound/hdmi-codec.h>
#include <sound/pcm_drm_eld.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -435,7 +436,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
struct drm_connector *connector = &vc4_hdmi->connector;
struct drm_connector_state *cstate = connector->state;
- struct drm_crtc *crtc = encoder->crtc;
+ struct drm_crtc *crtc = cstate->crtc;
const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
union hdmi_infoframe frame;
int ret;
@@ -477,15 +478,10 @@ static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+ struct hdmi_audio_infoframe *audio = &vc4_hdmi->audio.infoframe;
union hdmi_infoframe frame;
- hdmi_audio_infoframe_init(&frame.audio);
-
- frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
- frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
- frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
- frame.audio.channels = vc4_hdmi->audio.channels;
-
+ memcpy(&frame.audio, audio, sizeof(*audio));
vc4_hdmi_write_infoframe(encoder, &frame);
}
@@ -545,8 +541,11 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder,
static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
{
- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+ struct drm_connector *connector = &vc4_hdmi->connector;
+ struct drm_connector_state *cstate = connector->state;
+ struct drm_crtc *crtc = cstate->crtc;
+ struct drm_display_mode *mode = &crtc->state->adjusted_mode;
if (!vc4_hdmi_supports_scrambling(encoder, mode))
return;
@@ -567,17 +566,18 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct drm_crtc *crtc = encoder->crtc;
+ struct drm_connector *connector = &vc4_hdmi->connector;
+ struct drm_connector_state *cstate = connector->state;
/*
- * At boot, encoder->crtc will be NULL. Since we don't know the
+ * At boot, connector->state will be NULL. Since we don't know the
* state of the scrambler and in order to avoid any
* inconsistency, let's disable it all the time.
*/
- if (crtc && !vc4_hdmi_supports_scrambling(encoder, &crtc->mode))
+ if (cstate && !vc4_hdmi_supports_scrambling(encoder, &cstate->crtc->mode))
return;
- if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode))
+ if (cstate && !vc4_hdmi_mode_needs_scrambling(&cstate->crtc->mode))
return;
if (delayed_work_pending(&vc4_hdmi->scrambling_work))
@@ -613,12 +613,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
- HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) |
- VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC);
+ HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB);
- HDMI_WRITE(HDMI_VID_CTL,
- HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
+ mdelay(1);
+ HDMI_WRITE(HDMI_VID_CTL,
+ HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
vc4_hdmi_disable_scrambling(encoder);
}
@@ -628,12 +628,12 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
int ret;
+ HDMI_WRITE(HDMI_VID_CTL,
+ HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
+
if (vc4_hdmi->variant->phy_disable)
vc4_hdmi->variant->phy_disable(vc4_hdmi);
- HDMI_WRITE(HDMI_VID_CTL,
- HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
-
clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock);
clk_disable_unprepare(vc4_hdmi->pixel_clock);
@@ -898,7 +898,9 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
vc4_hdmi_encoder_get_connector_state(encoder, state);
struct vc4_hdmi_connector_state *vc4_conn_state =
conn_state_to_vc4_hdmi_conn_state(conn_state);
- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+ struct drm_crtc_state *crtc_state =
+ drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+ struct drm_display_mode *mode = &crtc_state->adjusted_mode;
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
unsigned long bvb_rate, pixel_rate, hsm_rate;
int ret;
@@ -983,7 +985,11 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+ struct drm_connector_state *conn_state =
+ vc4_hdmi_encoder_get_connector_state(encoder, state);
+ struct drm_crtc_state *crtc_state =
+ drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+ struct drm_display_mode *mode = &crtc_state->adjusted_mode;
struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
@@ -1006,7 +1012,11 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+ struct drm_connector_state *conn_state =
+ vc4_hdmi_encoder_get_connector_state(encoder, state);
+ struct drm_crtc_state *crtc_state =
+ drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+ struct drm_display_mode *mode = &crtc_state->adjusted_mode;
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -1015,6 +1025,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
HDMI_WRITE(HDMI_VID_CTL,
VC4_HD_VID_CTL_ENABLE |
+ VC4_HD_VID_CTL_CLRRGB |
VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
(vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
@@ -1173,12 +1184,13 @@ static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
}
/* HDMI audio codec callbacks */
-static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
+static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi,
+ unsigned int samplerate)
{
u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
unsigned long n, m;
- rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
+ rational_best_approximation(hsm_clock, samplerate,
VC4_HD_MAI_SMP_N_MASK >>
VC4_HD_MAI_SMP_N_SHIFT,
(VC4_HD_MAI_SMP_M_MASK >>
@@ -1190,12 +1202,11 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
}
-static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
+static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate)
{
- struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
- struct drm_crtc *crtc = encoder->crtc;
+ struct drm_connector *connector = &vc4_hdmi->connector;
+ struct drm_crtc *crtc = connector->state->crtc;
const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
- u32 samplerate = vc4_hdmi->audio.samplerate;
u32 n, cts;
u64 tmp;
@@ -1224,36 +1235,31 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
return snd_soc_card_get_drvdata(card);
}
-static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int vc4_hdmi_audio_startup(struct device *dev, void *data)
{
- struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
- struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
struct drm_connector *connector = &vc4_hdmi->connector;
- int ret;
-
- if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
- return -EINVAL;
-
- vc4_hdmi->audio.substream = substream;
/*
* If the HDMI encoder hasn't probed, or the encoder is
* currently in DVI mode, treat the codec dai as missing.
*/
- if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
+ if (!connector->state || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
VC4_HDMI_RAM_PACKET_ENABLE))
return -ENODEV;
- ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
- if (ret)
- return ret;
+ vc4_hdmi->audio.streaming = true;
- return 0;
-}
+ HDMI_WRITE(HDMI_MAI_CTL,
+ VC4_HD_MAI_CTL_RESET |
+ VC4_HD_MAI_CTL_FLUSH |
+ VC4_HD_MAI_CTL_DLATE |
+ VC4_HD_MAI_CTL_ERRORE |
+ VC4_HD_MAI_CTL_ERRORF);
+
+ if (vc4_hdmi->variant->phy_rng_enable)
+ vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
-static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-{
return 0;
}
@@ -1273,48 +1279,96 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
}
-static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void vc4_hdmi_audio_shutdown(struct device *dev, void *data)
{
- struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
- if (substream != vc4_hdmi->audio.substream)
- return;
+ HDMI_WRITE(HDMI_MAI_CTL,
+ VC4_HD_MAI_CTL_DLATE |
+ VC4_HD_MAI_CTL_ERRORE |
+ VC4_HD_MAI_CTL_ERRORF);
+
+ if (vc4_hdmi->variant->phy_rng_disable)
+ vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
+ vc4_hdmi->audio.streaming = false;
vc4_hdmi_audio_reset(vc4_hdmi);
+}
- vc4_hdmi->audio.substream = NULL;
+static int sample_rate_to_mai_fmt(int samplerate)
+{
+ switch (samplerate) {
+ case 8000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_8000;
+ case 11025:
+ return VC4_HDMI_MAI_SAMPLE_RATE_11025;
+ case 12000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_12000;
+ case 16000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_16000;
+ case 22050:
+ return VC4_HDMI_MAI_SAMPLE_RATE_22050;
+ case 24000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_24000;
+ case 32000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_32000;
+ case 44100:
+ return VC4_HDMI_MAI_SAMPLE_RATE_44100;
+ case 48000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_48000;
+ case 64000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_64000;
+ case 88200:
+ return VC4_HDMI_MAI_SAMPLE_RATE_88200;
+ case 96000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_96000;
+ case 128000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_128000;
+ case 176400:
+ return VC4_HDMI_MAI_SAMPLE_RATE_176400;
+ case 192000:
+ return VC4_HDMI_MAI_SAMPLE_RATE_192000;
+ default:
+ return VC4_HDMI_MAI_SAMPLE_RATE_NOT_INDICATED;
+ }
}
/* HDMI audio codec callbacks */
-static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
+ struct hdmi_codec_daifmt *daifmt,
+ struct hdmi_codec_params *params)
{
- struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
- struct device *dev = &vc4_hdmi->pdev->dev;
+ unsigned int sample_rate = params->sample_rate;
+ unsigned int channels = params->channels;
u32 audio_packet_config, channel_mask;
u32 channel_map;
-
- if (substream != vc4_hdmi->audio.substream)
- return -EINVAL;
+ u32 mai_audio_format;
+ u32 mai_sample_rate;
dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
- params_rate(params), params_width(params),
- params_channels(params));
-
- vc4_hdmi->audio.channels = params_channels(params);
- vc4_hdmi->audio.samplerate = params_rate(params);
+ sample_rate, params->sample_width, channels);
HDMI_WRITE(HDMI_MAI_CTL,
- VC4_HD_MAI_CTL_RESET |
- VC4_HD_MAI_CTL_FLUSH |
- VC4_HD_MAI_CTL_DLATE |
- VC4_HD_MAI_CTL_ERRORE |
- VC4_HD_MAI_CTL_ERRORF);
+ VC4_SET_FIELD(channels, VC4_HD_MAI_CTL_CHNUM) |
+ VC4_HD_MAI_CTL_WHOLSMP |
+ VC4_HD_MAI_CTL_CHALIGN |
+ VC4_HD_MAI_CTL_ENABLE);
+
+ vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate);
- vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
+ mai_sample_rate = sample_rate_to_mai_fmt(sample_rate);
+ if (params->iec.status[0] & IEC958_AES0_NONAUDIO &&
+ params->channels == 8)
+ mai_audio_format = VC4_HDMI_MAI_FORMAT_HBR;
+ else
+ mai_audio_format = VC4_HDMI_MAI_FORMAT_PCM;
+ HDMI_WRITE(HDMI_MAI_FMT,
+ VC4_SET_FIELD(mai_sample_rate,
+ VC4_HDMI_MAI_FORMAT_SAMPLE_RATE) |
+ VC4_SET_FIELD(mai_audio_format,
+ VC4_HDMI_MAI_FORMAT_AUDIO_FORMAT));
/* The B frame identifier should match the value used by alsa-lib (8) */
audio_packet_config =
@@ -1322,122 +1376,33 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
- channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
+ channel_mask = GENMASK(channels - 1, 0);
audio_packet_config |= VC4_SET_FIELD(channel_mask,
VC4_HDMI_AUDIO_PACKET_CEA_MASK);
- /* Set the MAI threshold. This logic mimics the firmware's. */
- if (vc4_hdmi->audio.samplerate > 96000) {
- HDMI_WRITE(HDMI_MAI_THR,
- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
- } else if (vc4_hdmi->audio.samplerate > 48000) {
- HDMI_WRITE(HDMI_MAI_THR,
- VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
- } else {
- HDMI_WRITE(HDMI_MAI_THR,
- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
- }
+ /* Set the MAI threshold */
+ HDMI_WRITE(HDMI_MAI_THR,
+ VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
+ VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
+ VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
+ VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
HDMI_WRITE(HDMI_MAI_CONFIG,
VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
+ VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE |
VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
- vc4_hdmi_set_n_cts(vc4_hdmi);
+ vc4_hdmi_set_n_cts(vc4_hdmi, sample_rate);
+ memcpy(&vc4_hdmi->audio.infoframe, &params->cea, sizeof(params->cea));
vc4_hdmi_set_audio_infoframe(encoder);
return 0;
}
-static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- vc4_hdmi->audio.streaming = true;
-
- if (vc4_hdmi->variant->phy_rng_enable)
- vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
-
- HDMI_WRITE(HDMI_MAI_CTL,
- VC4_SET_FIELD(vc4_hdmi->audio.channels,
- VC4_HD_MAI_CTL_CHNUM) |
- VC4_HD_MAI_CTL_ENABLE);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- HDMI_WRITE(HDMI_MAI_CTL,
- VC4_HD_MAI_CTL_DLATE |
- VC4_HD_MAI_CTL_ERRORE |
- VC4_HD_MAI_CTL_ERRORF);
-
- if (vc4_hdmi->variant->phy_rng_disable)
- vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
-
- vc4_hdmi->audio.streaming = false;
-
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static inline struct vc4_hdmi *
-snd_component_to_hdmi(struct snd_soc_component *component)
-{
- struct snd_soc_card *card = snd_soc_component_get_drvdata(component);
-
- return snd_soc_card_get_drvdata(card);
-}
-
-static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
- struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
- struct drm_connector *connector = &vc4_hdmi->connector;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- uinfo->count = sizeof(connector->eld);
-
- return 0;
-}
-
-static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
- struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
- struct drm_connector *connector = &vc4_hdmi->connector;
-
- memcpy(ucontrol->value.bytes.data, connector->eld,
- sizeof(connector->eld));
-
- return 0;
-}
-
-static const struct snd_kcontrol_new vc4_hdmi_audio_controls[] = {
- {
- .access = SNDRV_CTL_ELEM_ACCESS_READ |
- SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "ELD",
- .info = vc4_hdmi_audio_eld_ctl_info,
- .get = vc4_hdmi_audio_eld_ctl_get,
- },
-};
-
static const struct snd_soc_dapm_widget vc4_hdmi_audio_widgets[] = {
SND_SOC_DAPM_OUTPUT("TX"),
};
@@ -1446,42 +1411,6 @@ static const struct snd_soc_dapm_route vc4_hdmi_audio_routes[] = {
{ "TX", NULL, "Playback" },
};
-static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = {
- .name = "vc4-hdmi-codec-dai-component",
- .controls = vc4_hdmi_audio_controls,
- .num_controls = ARRAY_SIZE(vc4_hdmi_audio_controls),
- .dapm_widgets = vc4_hdmi_audio_widgets,
- .num_dapm_widgets = ARRAY_SIZE(vc4_hdmi_audio_widgets),
- .dapm_routes = vc4_hdmi_audio_routes,
- .num_dapm_routes = ARRAY_SIZE(vc4_hdmi_audio_routes),
- .idle_bias_on = 1,
- .use_pmdown_time = 1,
- .endianness = 1,
- .non_legacy_dai_naming = 1,
-};
-
-static const struct snd_soc_dai_ops vc4_hdmi_audio_dai_ops = {
- .startup = vc4_hdmi_audio_startup,
- .shutdown = vc4_hdmi_audio_shutdown,
- .hw_params = vc4_hdmi_audio_hw_params,
- .set_fmt = vc4_hdmi_audio_set_fmt,
- .trigger = vc4_hdmi_audio_trigger,
-};
-
-static struct snd_soc_dai_driver vc4_hdmi_audio_codec_dai_drv = {
- .name = "vc4-hdmi-hifi",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 2,
- .channels_max = 8,
- .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
- SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
- SNDRV_PCM_RATE_192000,
- .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
- },
-};
-
static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = {
.name = "vc4-hdmi-cpu-dai-component",
};
@@ -1508,7 +1437,6 @@ static struct snd_soc_dai_driver vc4_hdmi_audio_cpu_dai_drv = {
SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
},
- .ops = &vc4_hdmi_audio_dai_ops,
};
static const struct snd_dmaengine_pcm_config pcm_conf = {
@@ -1516,6 +1444,30 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
};
+static int vc4_hdmi_audio_get_eld(struct device *dev, void *data,
+ uint8_t *buf, size_t len)
+{
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
+ struct drm_connector *connector = &vc4_hdmi->connector;
+
+ memcpy(buf, connector->eld, min(sizeof(connector->eld), len));
+
+ return 0;
+}
+
+static const struct hdmi_codec_ops vc4_hdmi_codec_ops = {
+ .get_eld = vc4_hdmi_audio_get_eld,
+ .prepare = vc4_hdmi_audio_prepare,
+ .audio_shutdown = vc4_hdmi_audio_shutdown,
+ .audio_startup = vc4_hdmi_audio_startup,
+};
+
+struct hdmi_codec_pdata vc4_hdmi_codec_pdata = {
+ .ops = &vc4_hdmi_codec_ops,
+ .max_i2s_channels = 8,
+ .i2s = 1,
+};
+
static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
{
const struct vc4_hdmi_register *mai_data =
@@ -1523,6 +1475,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
struct snd_soc_card *card = &vc4_hdmi->audio.card;
struct device *dev = &vc4_hdmi->pdev->dev;
+ struct platform_device *codec_pdev;
const __be32 *addr;
int index;
int ret;
@@ -1569,12 +1522,13 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
return ret;
}
- /* register component and codec dai */
- ret = devm_snd_soc_register_component(dev, &vc4_hdmi_audio_component_drv,
- &vc4_hdmi_audio_codec_dai_drv, 1);
- if (ret) {
- dev_err(dev, "Could not register component: %d\n", ret);
- return ret;
+ codec_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
+ PLATFORM_DEVID_AUTO,
+ &vc4_hdmi_codec_pdata,
+ sizeof(vc4_hdmi_codec_pdata));
+ if (IS_ERR(codec_pdev)) {
+ dev_err(dev, "Couldn't register the HDMI codec: %ld\n", PTR_ERR(codec_pdev));
+ return PTR_ERR(codec_pdev);
}
dai_link->cpus = &vc4_hdmi->audio.cpu;
@@ -1587,9 +1541,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
dai_link->name = "MAI";
dai_link->stream_name = "MAI PCM";
- dai_link->codecs->dai_name = vc4_hdmi_audio_codec_dai_drv.name;
+ dai_link->codecs->dai_name = "i2s-hifi";
dai_link->cpus->dai_name = dev_name(dev);
- dai_link->codecs->name = dev_name(dev);
+ dai_link->codecs->name = dev_name(&codec_pdev->dev);
dai_link->platforms->name = dev_name(dev);
card->dai_link = dai_link;
@@ -1609,12 +1563,65 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
snd_soc_card_set_drvdata(card, vc4_hdmi);
ret = devm_snd_soc_register_card(dev, card);
if (ret)
- dev_err(dev, "Could not register sound card: %d\n", ret);
+ dev_err_probe(dev, ret, "Could not register sound card\n");
return ret;
}
+static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv)
+{
+ struct vc4_hdmi *vc4_hdmi = priv;
+ struct drm_device *dev = vc4_hdmi->connector.dev;
+
+ if (dev && dev->registered)
+ drm_kms_helper_hotplug_event(dev);
+
+ return IRQ_HANDLED;
+}
+
+static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi)
+{
+ struct drm_connector *connector = &vc4_hdmi->connector;
+ struct platform_device *pdev = vc4_hdmi->pdev;
+ int ret;
+
+ if (vc4_hdmi->variant->external_irq_controller) {
+ unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected");
+ unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed");
+
+ ret = request_threaded_irq(hpd_con,
+ NULL,
+ vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
+ "vc4 hdmi hpd connected", vc4_hdmi);
+ if (ret)
+ return ret;
+
+ ret = request_threaded_irq(hpd_rm,
+ NULL,
+ vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
+ "vc4 hdmi hpd disconnected", vc4_hdmi);
+ if (ret) {
+ free_irq(hpd_con, vc4_hdmi);
+ return ret;
+ }
+
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+ }
+
+ return 0;
+}
+
+static void vc4_hdmi_hotplug_exit(struct vc4_hdmi *vc4_hdmi)
+{
+ struct platform_device *pdev = vc4_hdmi->pdev;
+
+ if (vc4_hdmi->variant->external_irq_controller) {
+ free_irq(platform_get_irq_byname(pdev, "hpd-connected"), vc4_hdmi);
+ free_irq(platform_get_irq_byname(pdev, "hpd-removed"), vc4_hdmi);
+ }
+}
+
#ifdef CONFIG_DRM_VC4_HDMI_CEC
static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv)
{
@@ -2213,10 +2220,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
if (ret)
goto err_destroy_encoder;
- ret = vc4_hdmi_cec_init(vc4_hdmi);
+ ret = vc4_hdmi_hotplug_init(vc4_hdmi);
if (ret)
goto err_destroy_conn;
+ ret = vc4_hdmi_cec_init(vc4_hdmi);
+ if (ret)
+ goto err_free_hotplug;
+
ret = vc4_hdmi_audio_init(vc4_hdmi);
if (ret)
goto err_free_cec;
@@ -2229,6 +2240,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
err_free_cec:
vc4_hdmi_cec_exit(vc4_hdmi);
+err_free_hotplug:
+ vc4_hdmi_hotplug_exit(vc4_hdmi);
err_destroy_conn:
vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
err_destroy_encoder:
@@ -2270,6 +2283,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
kfree(vc4_hdmi->hd_regset.regs);
vc4_hdmi_cec_exit(vc4_hdmi);
+ vc4_hdmi_hotplug_exit(vc4_hdmi);
vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 884d245507a9..33e9f665ab8e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -111,11 +111,8 @@ struct vc4_hdmi_audio {
struct snd_soc_dai_link_component cpu;
struct snd_soc_dai_link_component codec;
struct snd_soc_dai_link_component platform;
- int samplerate;
- int channels;
struct snd_dmaengine_dai_dma_data dma_data;
- struct snd_pcm_substream *substream;
-
+ struct hdmi_audio_infoframe infoframe;
bool streaming;
};
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index e226c24e543f..20fa8e34c20b 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -45,6 +45,10 @@
* current job can make progress.
*/
+#include <linux/platform_device.h>
+
+#include <drm/drm_drv.h>
+
#include "vc4_drv.h"
#include "vc4_regs.h"
@@ -192,7 +196,7 @@ vc4_irq_finish_render_job(struct drm_device *dev)
schedule_work(&vc4->job_done_work);
}
-irqreturn_t
+static irqreturn_t
vc4_irq(int irq, void *arg)
{
struct drm_device *dev = arg;
@@ -234,8 +238,8 @@ vc4_irq(int irq, void *arg)
return status;
}
-void
-vc4_irq_preinstall(struct drm_device *dev)
+static void
+vc4_irq_prepare(struct drm_device *dev)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -251,24 +255,22 @@ vc4_irq_preinstall(struct drm_device *dev)
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
}
-int
-vc4_irq_postinstall(struct drm_device *dev)
+void
+vc4_irq_enable(struct drm_device *dev)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
if (!vc4->v3d)
- return 0;
+ return;
/* Enable the render done interrupts. The out-of-memory interrupt is
* enabled as soon as we have a binner BO allocated.
*/
V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE);
-
- return 0;
}
void
-vc4_irq_uninstall(struct drm_device *dev)
+vc4_irq_disable(struct drm_device *dev)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -282,11 +284,37 @@ vc4_irq_uninstall(struct drm_device *dev)
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
/* Finish any interrupt handler still in flight. */
- disable_irq(dev->irq);
+ disable_irq(vc4->irq);
cancel_work_sync(&vc4->overflow_mem_work);
}
+int vc4_irq_install(struct drm_device *dev, int irq)
+{
+ int ret;
+
+ if (irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ vc4_irq_prepare(dev);
+
+ ret = request_irq(irq, vc4_irq, 0, dev->driver->name, dev);
+ if (ret)
+ return ret;
+
+ vc4_irq_enable(dev);
+
+ return 0;
+}
+
+void vc4_irq_uninstall(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ vc4_irq_disable(dev);
+ free_irq(vc4->irq, dev);
+}
+
/** Reinitializes interrupt registers when a GPU reset is performed. */
void vc4_irq_reset(struct drm_device *dev)
{
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 6a1a9e1d72ce..f0b3e4cf5bce 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -880,7 +880,6 @@ int vc4_kms_load(struct drm_device *dev)
/* Set support for vblank irq fast disable, before drm_vblank_init() */
dev->vblank_disable_immediate = true;
- dev->irq_enabled = true;
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret < 0) {
dev_err(dev->dev, "failed to initialize vblank\n");
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index be2c32a519b3..489f921ef44d 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -516,6 +516,36 @@
# define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK VC4_MASK(7, 0)
# define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT 0
+# define VC4_HDMI_MAI_FORMAT_AUDIO_FORMAT_MASK VC4_MASK(23, 16)
+# define VC4_HDMI_MAI_FORMAT_AUDIO_FORMAT_SHIFT 16
+
+enum {
+ VC4_HDMI_MAI_FORMAT_PCM = 2,
+ VC4_HDMI_MAI_FORMAT_HBR = 200,
+};
+
+# define VC4_HDMI_MAI_FORMAT_SAMPLE_RATE_MASK VC4_MASK(15, 8)
+# define VC4_HDMI_MAI_FORMAT_SAMPLE_RATE_SHIFT 8
+
+enum {
+ VC4_HDMI_MAI_SAMPLE_RATE_NOT_INDICATED = 0,
+ VC4_HDMI_MAI_SAMPLE_RATE_8000 = 1,
+ VC4_HDMI_MAI_SAMPLE_RATE_11025 = 2,
+ VC4_HDMI_MAI_SAMPLE_RATE_12000 = 3,
+ VC4_HDMI_MAI_SAMPLE_RATE_16000 = 4,
+ VC4_HDMI_MAI_SAMPLE_RATE_22050 = 5,
+ VC4_HDMI_MAI_SAMPLE_RATE_24000 = 6,
+ VC4_HDMI_MAI_SAMPLE_RATE_32000 = 7,
+ VC4_HDMI_MAI_SAMPLE_RATE_44100 = 8,
+ VC4_HDMI_MAI_SAMPLE_RATE_48000 = 9,
+ VC4_HDMI_MAI_SAMPLE_RATE_64000 = 10,
+ VC4_HDMI_MAI_SAMPLE_RATE_88200 = 11,
+ VC4_HDMI_MAI_SAMPLE_RATE_96000 = 12,
+ VC4_HDMI_MAI_SAMPLE_RATE_128000 = 13,
+ VC4_HDMI_MAI_SAMPLE_RATE_176400 = 14,
+ VC4_HDMI_MAI_SAMPLE_RATE_192000 = 15,
+};
+
# define VC4_HDMI_RAM_PACKET_ENABLE BIT(16)
/* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
index 73d63d72575b..7bb3067f8425 100644
--- a/drivers/gpu/drm/vc4/vc4_v3d.c
+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -10,8 +10,6 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <drm/drm_irq.h>
-
#include "vc4_drv.h"
#include "vc4_regs.h"
@@ -361,7 +359,7 @@ static int vc4_v3d_runtime_suspend(struct device *dev)
struct vc4_v3d *v3d = dev_get_drvdata(dev);
struct vc4_dev *vc4 = v3d->vc4;
- vc4_irq_uninstall(&vc4->base);
+ vc4_irq_disable(&vc4->base);
clk_disable_unprepare(v3d->clk);
@@ -381,8 +379,8 @@ static int vc4_v3d_runtime_resume(struct device *dev)
vc4_v3d_init_hw(&vc4->base);
/* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */
- enable_irq(vc4->base.irq);
- vc4_irq_postinstall(&vc4->base);
+ enable_irq(vc4->irq);
+ vc4_irq_enable(&vc4->base);
return 0;
}
@@ -448,7 +446,12 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
vc4_v3d_init_hw(drm);
- ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ return ret;
+ vc4->irq = ret;
+
+ ret = vc4_irq_install(drm, vc4->irq);
if (ret) {
DRM_ERROR("Failed to install IRQ handler\n");
return ret;
@@ -473,7 +476,7 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
pm_runtime_disable(dev);
- drm_irq_uninstall(drm);
+ vc4_irq_uninstall(drm);
/* Disable the binner's overflow memory address, so the next
* driver probe (if any) doesn't try to reuse our old
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c
index dae1bacd86c1..c9afa1a51f23 100644
--- a/drivers/gpu/drm/via/via_mm.c
+++ b/drivers/gpu/drm/via/via_mm.c
@@ -29,7 +29,6 @@
#include <drm/drm_device.h>
#include <drm/drm_file.h>
-#include <drm/drm_irq.h>
#include <drm/via_drm.h>
#include "via_drv.h"
@@ -86,7 +85,7 @@ int via_final_context(struct drm_device *dev, int context)
/* Last context, perform cleanup */
if (list_is_singular(&dev->ctxlist)) {
DRM_DEBUG("Last Context\n");
- drm_irq_uninstall(dev);
+ drm_legacy_irq_uninstall(dev);
via_cleanup_futex(dev_priv);
via_do_cleanup_map(dev);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index ca77edbc5ea0..ed85a7863256 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -57,7 +57,7 @@ static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vd
vga ? "virtio-vga" : "virtio-gpu-pci",
pname);
if (vga) {
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "virtiodrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver);
if (ret)
return ret;
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index d9dbc4f258f3..d4e610a44e12 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -315,7 +315,9 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev,
uint32_t resource_id,
uint32_t x, uint32_t y,
- uint32_t width, uint32_t height);
+ uint32_t width, uint32_t height,
+ struct virtio_gpu_object_array *objs,
+ struct virtio_gpu_fence *fence);
void virtio_gpu_cmd_set_scanout(struct virtio_gpu_device *vgdev,
uint32_t scanout_id, uint32_t resource_id,
uint32_t width, uint32_t height,
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index 4e1b17548007..a49fd9480381 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -129,6 +129,40 @@ static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev,
objs, NULL);
}
+static void virtio_gpu_resource_flush(struct drm_plane *plane,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
+{
+ struct drm_device *dev = plane->dev;
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_framebuffer *vgfb;
+ struct virtio_gpu_object *bo;
+
+ vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
+ bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
+ if (vgfb->fence) {
+ struct virtio_gpu_object_array *objs;
+
+ objs = virtio_gpu_array_alloc(1);
+ if (!objs)
+ return;
+ virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]);
+ virtio_gpu_array_lock_resv(objs);
+ virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, x, y,
+ width, height, objs, vgfb->fence);
+ virtio_gpu_notify(vgdev);
+
+ dma_fence_wait_timeout(&vgfb->fence->f, true,
+ msecs_to_jiffies(50));
+ dma_fence_put(&vgfb->fence->f);
+ vgfb->fence = NULL;
+ } else {
+ virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, x, y,
+ width, height, NULL, NULL);
+ virtio_gpu_notify(vgdev);
+ }
+}
+
static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
struct drm_atomic_state *state)
{
@@ -198,16 +232,15 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
}
}
- virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle,
- rect.x1,
- rect.y1,
- rect.x2 - rect.x1,
- rect.y2 - rect.y1);
- virtio_gpu_notify(vgdev);
+ virtio_gpu_resource_flush(plane,
+ rect.x1,
+ rect.y1,
+ rect.x2 - rect.x1,
+ rect.y2 - rect.y1);
}
-static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *new_state)
+static int virtio_gpu_plane_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
{
struct drm_device *dev = plane->dev;
struct virtio_gpu_device *vgdev = dev->dev_private;
@@ -219,7 +252,10 @@ static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane,
vgfb = to_virtio_gpu_framebuffer(new_state->fb);
bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
- if (bo && bo->dumb && (plane->state->fb != new_state->fb)) {
+ if (!bo || (plane->type == DRM_PLANE_TYPE_PRIMARY && !bo->guest_blob))
+ return 0;
+
+ if (bo->dumb && (plane->state->fb != new_state->fb)) {
vgfb->fence = virtio_gpu_fence_alloc(vgdev);
if (!vgfb->fence)
return -ENOMEM;
@@ -228,8 +264,8 @@ static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane,
return 0;
}
-static void virtio_gpu_cursor_cleanup_fb(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+static void virtio_gpu_plane_cleanup_fb(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
{
struct virtio_gpu_framebuffer *vgfb;
@@ -321,13 +357,15 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs virtio_gpu_primary_helper_funcs = {
+ .prepare_fb = virtio_gpu_plane_prepare_fb,
+ .cleanup_fb = virtio_gpu_plane_cleanup_fb,
.atomic_check = virtio_gpu_plane_atomic_check,
.atomic_update = virtio_gpu_primary_plane_update,
};
static const struct drm_plane_helper_funcs virtio_gpu_cursor_helper_funcs = {
- .prepare_fb = virtio_gpu_cursor_prepare_fb,
- .cleanup_fb = virtio_gpu_cursor_cleanup_fb,
+ .prepare_fb = virtio_gpu_plane_prepare_fb,
+ .cleanup_fb = virtio_gpu_plane_cleanup_fb,
.atomic_check = virtio_gpu_plane_atomic_check,
.atomic_update = virtio_gpu_cursor_plane_update,
};
diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c
index 807a27a16365..e45dbf14b307 100644
--- a/drivers/gpu/drm/virtio/virtgpu_prime.c
+++ b/drivers/gpu/drm/virtio/virtgpu_prime.c
@@ -98,6 +98,8 @@ struct dma_buf *virtgpu_gem_prime_export(struct drm_gem_object *obj,
} else {
bo->uuid_state = STATE_ERR;
}
+ } else if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)) {
+ bo->uuid_state = STATE_ERR;
}
exp_info.ops = &virtgpu_dmabuf_ops.ops;
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index cf84d382dd41..2e71e91278b4 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -576,13 +576,16 @@ void virtio_gpu_cmd_set_scanout(struct virtio_gpu_device *vgdev,
void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev,
uint32_t resource_id,
uint32_t x, uint32_t y,
- uint32_t width, uint32_t height)
+ uint32_t width, uint32_t height,
+ struct virtio_gpu_object_array *objs,
+ struct virtio_gpu_fence *fence)
{
struct virtio_gpu_resource_flush *cmd_p;
struct virtio_gpu_vbuffer *vbuf;
cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
memset(cmd_p, 0, sizeof(*cmd_p));
+ vbuf->objs = objs;
cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_FLUSH);
cmd_p->resource_id = cpu_to_le32(resource_id);
@@ -591,7 +594,7 @@ void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev,
cmd_p->r.x = cpu_to_le32(x);
cmd_p->r.y = cpu_to_le32(y);
- virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+ virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, fence);
}
void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index e49523866e1d..9e8204be9a14 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -6,7 +6,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_vblank.h>
#include "vkms_drv.h"
@@ -154,24 +153,21 @@ static void compose_plane(struct vkms_composer *primary_composer,
struct vkms_composer *plane_composer,
void *vaddr_out)
{
- struct drm_gem_object *plane_obj;
- struct drm_gem_shmem_object *plane_shmem_obj;
struct drm_framebuffer *fb = &plane_composer->fb;
+ void *vaddr;
void (*pixel_blend)(const u8 *p_src, u8 *p_dst);
- plane_obj = drm_gem_fb_get_obj(&plane_composer->fb, 0);
- plane_shmem_obj = to_drm_gem_shmem_obj(plane_obj);
-
- if (WARN_ON(!plane_shmem_obj->vaddr))
+ if (WARN_ON(dma_buf_map_is_null(&primary_composer->map[0])))
return;
+ vaddr = plane_composer->map[0].vaddr;
+
if (fb->format->format == DRM_FORMAT_ARGB8888)
pixel_blend = &alpha_blend;
else
pixel_blend = &x_blend;
- blend(vaddr_out, plane_shmem_obj->vaddr, primary_composer,
- plane_composer, pixel_blend);
+ blend(vaddr_out, vaddr, primary_composer, plane_composer, pixel_blend);
}
static int compose_active_planes(void **vaddr_out,
@@ -180,21 +176,23 @@ static int compose_active_planes(void **vaddr_out,
{
struct drm_framebuffer *fb = &primary_composer->fb;
struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
- struct drm_gem_shmem_object *shmem_obj = to_drm_gem_shmem_obj(gem_obj);
+ const void *vaddr;
int i;
if (!*vaddr_out) {
- *vaddr_out = kzalloc(shmem_obj->base.size, GFP_KERNEL);
+ *vaddr_out = kzalloc(gem_obj->size, GFP_KERNEL);
if (!*vaddr_out) {
DRM_ERROR("Cannot allocate memory for output frame.");
return -ENOMEM;
}
}
- if (WARN_ON(!shmem_obj->vaddr))
+ if (WARN_ON(dma_buf_map_is_null(&primary_composer->map[0])))
return -EINVAL;
- memcpy(*vaddr_out, shmem_obj->vaddr, shmem_obj->base.size);
+ vaddr = primary_composer->map[0].vaddr;
+
+ memcpy(*vaddr_out, vaddr, gem_obj->size);
/* If there are other planes besides primary, we consider the active
* planes should be in z-order and compose them associatively:
@@ -251,7 +249,7 @@ void vkms_composer_worker(struct work_struct *work)
if (crtc_state->num_active_planes >= 1) {
act_plane = crtc_state->active_planes[0];
- if (act_plane->base.plane->type == DRM_PLANE_TYPE_PRIMARY)
+ if (act_plane->base.base.plane->type == DRM_PLANE_TYPE_PRIMARY)
primary_composer = act_plane->composer;
}
@@ -259,7 +257,7 @@ void vkms_composer_worker(struct work_struct *work)
return;
if (wb_pending)
- vaddr_out = crtc_state->active_writeback;
+ vaddr_out = crtc_state->active_writeback->data[0].vaddr;
ret = compose_active_planes(&vaddr_out, primary_composer,
crtc_state);
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 027ffe759440..0ffe5f0e33f7 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -28,6 +28,9 @@
#include "vkms_drv.h"
+#include <drm/drm_print.h>
+#include <drm/drm_debugfs.h>
+
#define DRIVER_NAME "vkms"
#define DRIVER_DESC "Virtual Kernel Mode Setting"
#define DRIVER_DATE "20180514"
@@ -52,7 +55,7 @@ DEFINE_DRM_GEM_FOPS(vkms_driver_fops);
static void vkms_release(struct drm_device *dev)
{
- struct vkms_device *vkms = container_of(dev, struct vkms_device, drm);
+ struct vkms_device *vkms = drm_device_to_vkms_device(dev);
destroy_workqueue(vkms->output.composer_workq);
}
@@ -86,12 +89,37 @@ static void vkms_atomic_commit_tail(struct drm_atomic_state *old_state)
drm_atomic_helper_cleanup_planes(dev, old_state);
}
+static int vkms_config_show(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev);
+
+ seq_printf(m, "writeback=%d\n", vkmsdev->config->writeback);
+ seq_printf(m, "cursor=%d\n", vkmsdev->config->cursor);
+ seq_printf(m, "overlay=%d\n", vkmsdev->config->overlay);
+
+ return 0;
+}
+
+static const struct drm_info_list vkms_config_debugfs_list[] = {
+ { "vkms_config", vkms_config_show, 0 },
+};
+
+static void vkms_config_debugfs_init(struct drm_minor *minor)
+{
+ drm_debugfs_create_files(vkms_config_debugfs_list, ARRAY_SIZE(vkms_config_debugfs_list),
+ minor->debugfs_root, minor);
+}
+
static const struct drm_driver vkms_driver = {
.driver_features = DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM,
.release = vkms_release,
.fops = &vkms_driver_fops,
DRM_GEM_SHMEM_DRIVER_OPS,
+ .debugfs_init = vkms_config_debugfs_init,
+
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
@@ -163,8 +191,6 @@ static int vkms_create(struct vkms_config *config)
goto out_devres;
}
- vkms_device->drm.irq_enabled = true;
-
ret = drm_vblank_init(&vkms_device->drm, 1);
if (ret) {
DRM_ERROR("Failed to vblank\n");
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index ac8c9c2fa4ed..d48c23d40ce5 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -7,6 +7,7 @@
#include <drm/drm.h>
#include <drm/drm_gem.h>
+#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_encoder.h>
#include <drm/drm_writeback.h>
@@ -19,9 +20,15 @@
#define XRES_MAX 8192
#define YRES_MAX 8192
+struct vkms_writeback_job {
+ struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];
+ struct dma_buf_map data[DRM_FORMAT_MAX_PLANES];
+};
+
struct vkms_composer {
struct drm_framebuffer fb;
struct drm_rect src, dst;
+ struct dma_buf_map map[4];
unsigned int offset;
unsigned int pitch;
unsigned int cpp;
@@ -33,7 +40,7 @@ struct vkms_composer {
* @composer: data required for composing computation
*/
struct vkms_plane_state {
- struct drm_plane_state base;
+ struct drm_shadow_plane_state base;
struct vkms_composer *composer;
};
@@ -55,7 +62,7 @@ struct vkms_crtc_state {
int num_active_planes;
/* stack of active planes for crc computation, should be in z order */
struct vkms_plane_state **active_planes;
- void *active_writeback;
+ struct vkms_writeback_job *active_writeback;
/* below four are protected by vkms_output.composer_lock */
bool crc_pending;
@@ -111,7 +118,7 @@ struct vkms_device {
container_of(target, struct vkms_crtc_state, base)
#define to_vkms_plane_state(target)\
- container_of(target, struct vkms_plane_state, base)
+ container_of(target, struct vkms_plane_state, base.base)
/* CRTC */
int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 107521ace597..32409e15244b 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -8,7 +8,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane_helper.h>
-#include <drm/drm_gem_shmem_helper.h>
#include "vkms_drv.h"
@@ -40,17 +39,16 @@ vkms_plane_duplicate_state(struct drm_plane *plane)
vkms_state->composer = composer;
- __drm_atomic_helper_plane_duplicate_state(plane,
- &vkms_state->base);
+ __drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base);
- return &vkms_state->base;
+ return &vkms_state->base.base;
}
static void vkms_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);
- struct drm_crtc *crtc = vkms_state->base.crtc;
+ struct drm_crtc *crtc = vkms_state->base.base.crtc;
if (crtc) {
/* dropping the reference we acquired in
@@ -63,7 +61,7 @@ static void vkms_plane_destroy_state(struct drm_plane *plane,
kfree(vkms_state->composer);
vkms_state->composer = NULL;
- __drm_atomic_helper_plane_destroy_state(old_state);
+ __drm_gem_destroy_shadow_plane_state(&vkms_state->base);
kfree(vkms_state);
}
@@ -71,8 +69,10 @@ static void vkms_plane_reset(struct drm_plane *plane)
{
struct vkms_plane_state *vkms_state;
- if (plane->state)
+ if (plane->state) {
vkms_plane_destroy_state(plane, plane->state);
+ plane->state = NULL; /* must be set to NULL here */
+ }
vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
if (!vkms_state) {
@@ -80,8 +80,7 @@ static void vkms_plane_reset(struct drm_plane *plane)
return;
}
- plane->state = &vkms_state->base;
- plane->state->plane = plane;
+ __drm_gem_reset_shadow_plane(plane, &vkms_state->base);
}
static const struct drm_plane_funcs vkms_plane_funcs = {
@@ -98,6 +97,7 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
plane);
struct vkms_plane_state *vkms_plane_state;
+ struct drm_shadow_plane_state *shadow_plane_state;
struct drm_framebuffer *fb = new_state->fb;
struct vkms_composer *composer;
@@ -105,11 +105,13 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,
return;
vkms_plane_state = to_vkms_plane_state(new_state);
+ shadow_plane_state = &vkms_plane_state->base;
composer = vkms_plane_state->composer;
memcpy(&composer->src, &new_state->src, sizeof(struct drm_rect));
memcpy(&composer->dst, &new_state->dst, sizeof(struct drm_rect));
memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer));
+ memcpy(&composer->map, &shadow_plane_state->data, sizeof(composer->map));
drm_framebuffer_get(&composer->fb);
composer->offset = fb->offsets[0];
composer->pitch = fb->pitches[0];
@@ -150,45 +152,10 @@ static int vkms_plane_atomic_check(struct drm_plane *plane,
return 0;
}
-static int vkms_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *state)
-{
- struct drm_gem_object *gem_obj;
- struct dma_buf_map map;
- int ret;
-
- if (!state->fb)
- return 0;
-
- gem_obj = drm_gem_fb_get_obj(state->fb, 0);
- ret = drm_gem_shmem_vmap(gem_obj, &map);
- if (ret)
- DRM_ERROR("vmap failed: %d\n", ret);
-
- return drm_gem_plane_helper_prepare_fb(plane, state);
-}
-
-static void vkms_cleanup_fb(struct drm_plane *plane,
- struct drm_plane_state *old_state)
-{
- struct drm_gem_object *gem_obj;
- struct drm_gem_shmem_object *shmem_obj;
- struct dma_buf_map map;
-
- if (!old_state->fb)
- return;
-
- gem_obj = drm_gem_fb_get_obj(old_state->fb, 0);
- shmem_obj = to_drm_gem_shmem_obj(drm_gem_fb_get_obj(old_state->fb, 0));
- dma_buf_map_set_vaddr(&map, shmem_obj->vaddr);
- drm_gem_shmem_vunmap(gem_obj, &map);
-}
-
static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
.atomic_update = vkms_plane_atomic_update,
.atomic_check = vkms_plane_atomic_check,
- .prepare_fb = vkms_prepare_fb,
- .cleanup_fb = vkms_cleanup_fb,
+ DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
};
struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c
index 0935686475a0..8694227f555f 100644
--- a/drivers/gpu/drm/vkms/vkms_writeback.c
+++ b/drivers/gpu/drm/vkms/vkms_writeback.c
@@ -65,41 +65,45 @@ static int vkms_wb_connector_get_modes(struct drm_connector *connector)
static int vkms_wb_prepare_job(struct drm_writeback_connector *wb_connector,
struct drm_writeback_job *job)
{
- struct drm_gem_object *gem_obj;
- struct dma_buf_map map;
+ struct vkms_writeback_job *vkmsjob;
int ret;
if (!job->fb)
return 0;
- gem_obj = drm_gem_fb_get_obj(job->fb, 0);
- ret = drm_gem_shmem_vmap(gem_obj, &map);
+ vkmsjob = kzalloc(sizeof(*vkmsjob), GFP_KERNEL);
+ if (!vkmsjob)
+ return -ENOMEM;
+
+ ret = drm_gem_fb_vmap(job->fb, vkmsjob->map, vkmsjob->data);
if (ret) {
DRM_ERROR("vmap failed: %d\n", ret);
- return ret;
+ goto err_kfree;
}
- job->priv = map.vaddr;
+ job->priv = vkmsjob;
return 0;
+
+err_kfree:
+ kfree(vkmsjob);
+ return ret;
}
static void vkms_wb_cleanup_job(struct drm_writeback_connector *connector,
struct drm_writeback_job *job)
{
- struct drm_gem_object *gem_obj;
+ struct vkms_writeback_job *vkmsjob = job->priv;
struct vkms_device *vkmsdev;
- struct dma_buf_map map;
if (!job->fb)
return;
- gem_obj = drm_gem_fb_get_obj(job->fb, 0);
- dma_buf_map_set_vaddr(&map, job->priv);
- drm_gem_shmem_vunmap(gem_obj, &map);
+ drm_gem_fb_vunmap(job->fb, vkmsjob->map);
- vkmsdev = drm_device_to_vkms_device(gem_obj->dev);
+ vkmsdev = drm_device_to_vkms_device(job->fb->dev);
vkms_set_composer(&vkmsdev->output, false);
+ kfree(vkmsjob);
}
static void vkms_wb_atomic_commit(struct drm_connector *conn,
diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig
index 0060ef842b5a..c9ce47c448e0 100644
--- a/drivers/gpu/drm/vmwgfx/Kconfig
+++ b/drivers/gpu/drm/vmwgfx/Kconfig
@@ -22,3 +22,11 @@ config DRM_VMWGFX_FBCON
Choose this option if you are shipping a new vmwgfx
userspace driver that supports using the kernel driver.
+config DRM_VMWGFX_MKSSTATS
+ bool "Enable mksGuestStats instrumentation of vmwgfx by default"
+ depends on DRM_VMWGFX
+ depends on X86
+ default n
+ help
+ Choose this option to instrument the kernel driver for mksGuestStats.
+
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
index 09f6dcac768b..bc323f7d4032 100644
--- a/drivers/gpu/drm/vmwgfx/Makefile
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -9,7 +9,7 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \
vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \
vmwgfx_validation.o vmwgfx_page_dirty.o vmwgfx_streamoutput.o \
- ttm_object.o ttm_memory.o
+ vmwgfx_devcaps.o ttm_object.o ttm_memory.o
vmwgfx-$(CONFIG_DRM_FBDEV_EMULATION) += vmwgfx_fb.o
vmwgfx-$(CONFIG_TRANSPARENT_HUGEPAGE) += vmwgfx_thp.o
diff --git a/drivers/gpu/drm/vmwgfx/device_include/includeCheck.h b/drivers/gpu/drm/vmwgfx/device_include/includeCheck.h
deleted file mode 100644
index 8cce7f15b6eb..000000000000
--- a/drivers/gpu/drm/vmwgfx/device_include/includeCheck.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * Intentionally empty file.
- */
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_caps.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_caps.h
deleted file mode 100644
index 69c4253fbfbb..000000000000
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_caps.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
-/**********************************************************
- * Copyright 2007-2015 VMware, Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE 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.
- *
- **********************************************************/
-
-/*
- * svga3d_caps.h --
- *
- * Definitions for SVGA3D hardware capabilities. Capabilities
- * are used to query for optional rendering features during
- * driver initialization. The capability data is stored as very
- * basic key/value dictionary within the "FIFO register" memory
- * area at the beginning of BAR2.
- *
- * Note that these definitions are only for 3D capabilities.
- * The SVGA device also has "device capabilities" and "FIFO
- * capabilities", which are non-3D-specific and are stored as
- * bitfields rather than key/value pairs.
- */
-
-#ifndef _SVGA3D_CAPS_H_
-#define _SVGA3D_CAPS_H_
-
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_USERLEVEL
-
-#include "includeCheck.h"
-
-#include "svga_reg.h"
-
-#define SVGA_FIFO_3D_CAPS_SIZE (SVGA_FIFO_3D_CAPS_LAST - \
- SVGA_FIFO_3D_CAPS + 1)
-
-
-/*
- * SVGA3dCapsRecordType
- *
- * Record types that can be found in the caps block.
- * Related record types are grouped together numerically so that
- * SVGA3dCaps_FindRecord() can be applied on a range of record
- * types.
- */
-
-typedef enum {
- SVGA3DCAPS_RECORD_UNKNOWN = 0,
- SVGA3DCAPS_RECORD_DEVCAPS_MIN = 0x100,
- SVGA3DCAPS_RECORD_DEVCAPS = 0x100,
- SVGA3DCAPS_RECORD_DEVCAPS_MAX = 0x1ff,
-} SVGA3dCapsRecordType;
-
-
-/*
- * SVGA3dCapsRecordHeader
- *
- * Header field leading each caps block record. Contains the offset (in
- * register words, NOT bytes) to the next caps block record (or the end
- * of caps block records which will be a zero word) and the record type
- * as defined above.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCapsRecordHeader {
- uint32 length;
- SVGA3dCapsRecordType type;
-}
-#include "vmware_pack_end.h"
-SVGA3dCapsRecordHeader;
-
-
-/*
- * SVGA3dCapsRecord
- *
- * Caps block record; "data" is a placeholder for the actual data structure
- * contained within the record;
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCapsRecord {
- SVGA3dCapsRecordHeader header;
- uint32 data[1];
-}
-#include "vmware_pack_end.h"
-SVGA3dCapsRecord;
-
-
-typedef uint32 SVGA3dCapPair[2];
-
-#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_cmd.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_cmd.h
index 799bc0963f7a..945c84b27e81 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_cmd.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_cmd.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
- * Copyright 1998-2020 VMware, Inc.
+ * Copyright 2012-2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -27,2249 +27,1487 @@
/*
* svga3d_cmd.h --
*
- * SVGA 3d hardware cmd definitions
+ * SVGA 3d hardware cmd definitions
*/
+
+
#ifndef _SVGA3D_CMD_H_
#define _SVGA3D_CMD_H_
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-
-#include "includeCheck.h"
#include "svga3d_types.h"
-
-/*
- * Identifiers for commands in the command FIFO.
- *
- * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of
- * the SVGA3D protocol and remain reserved; they should not be used in the
- * future.
- *
- * IDs between 1040 and 2999 (inclusive) are available for use by the
- * current SVGA3D protocol.
- *
- * FIFO clients other than SVGA3D should stay below 1000, or at 3000
- * and up.
- */
-
-typedef enum {
- SVGA_3D_CMD_LEGACY_BASE = 1000,
- SVGA_3D_CMD_BASE = 1040,
-
- SVGA_3D_CMD_SURFACE_DEFINE = 1040,
- SVGA_3D_CMD_SURFACE_DESTROY = 1041,
- SVGA_3D_CMD_SURFACE_COPY = 1042,
- SVGA_3D_CMD_SURFACE_STRETCHBLT = 1043,
- SVGA_3D_CMD_SURFACE_DMA = 1044,
- SVGA_3D_CMD_CONTEXT_DEFINE = 1045,
- SVGA_3D_CMD_CONTEXT_DESTROY = 1046,
- SVGA_3D_CMD_SETTRANSFORM = 1047,
- SVGA_3D_CMD_SETZRANGE = 1048,
- SVGA_3D_CMD_SETRENDERSTATE = 1049,
- SVGA_3D_CMD_SETRENDERTARGET = 1050,
- SVGA_3D_CMD_SETTEXTURESTATE = 1051,
- SVGA_3D_CMD_SETMATERIAL = 1052,
- SVGA_3D_CMD_SETLIGHTDATA = 1053,
- SVGA_3D_CMD_SETLIGHTENABLED = 1054,
- SVGA_3D_CMD_SETVIEWPORT = 1055,
- SVGA_3D_CMD_SETCLIPPLANE = 1056,
- SVGA_3D_CMD_CLEAR = 1057,
- SVGA_3D_CMD_PRESENT = 1058,
- SVGA_3D_CMD_SHADER_DEFINE = 1059,
- SVGA_3D_CMD_SHADER_DESTROY = 1060,
- SVGA_3D_CMD_SET_SHADER = 1061,
- SVGA_3D_CMD_SET_SHADER_CONST = 1062,
- SVGA_3D_CMD_DRAW_PRIMITIVES = 1063,
- SVGA_3D_CMD_SETSCISSORRECT = 1064,
- SVGA_3D_CMD_BEGIN_QUERY = 1065,
- SVGA_3D_CMD_END_QUERY = 1066,
- SVGA_3D_CMD_WAIT_FOR_QUERY = 1067,
- SVGA_3D_CMD_PRESENT_READBACK = 1068,
- SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN = 1069,
- SVGA_3D_CMD_SURFACE_DEFINE_V2 = 1070,
- SVGA_3D_CMD_GENERATE_MIPMAPS = 1071,
- SVGA_3D_CMD_DEAD4 = 1072,
- SVGA_3D_CMD_DEAD5 = 1073,
- SVGA_3D_CMD_DEAD6 = 1074,
- SVGA_3D_CMD_DEAD7 = 1075,
- SVGA_3D_CMD_DEAD8 = 1076,
- SVGA_3D_CMD_DEAD9 = 1077,
- SVGA_3D_CMD_DEAD10 = 1078,
- SVGA_3D_CMD_DEAD11 = 1079,
- SVGA_3D_CMD_ACTIVATE_SURFACE = 1080,
- SVGA_3D_CMD_DEACTIVATE_SURFACE = 1081,
- SVGA_3D_CMD_SCREEN_DMA = 1082,
- SVGA_3D_CMD_DEAD1 = 1083,
- SVGA_3D_CMD_DEAD2 = 1084,
-
- SVGA_3D_CMD_DEAD12 = 1085,
- SVGA_3D_CMD_DEAD13 = 1086,
- SVGA_3D_CMD_DEAD14 = 1087,
- SVGA_3D_CMD_DEAD15 = 1088,
- SVGA_3D_CMD_DEAD16 = 1089,
- SVGA_3D_CMD_DEAD17 = 1090,
-
- SVGA_3D_CMD_SET_OTABLE_BASE = 1091,
- SVGA_3D_CMD_READBACK_OTABLE = 1092,
-
- SVGA_3D_CMD_DEFINE_GB_MOB = 1093,
- SVGA_3D_CMD_DESTROY_GB_MOB = 1094,
- SVGA_3D_CMD_DEAD3 = 1095,
- SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING = 1096,
-
- SVGA_3D_CMD_DEFINE_GB_SURFACE = 1097,
- SVGA_3D_CMD_DESTROY_GB_SURFACE = 1098,
- SVGA_3D_CMD_BIND_GB_SURFACE = 1099,
- SVGA_3D_CMD_COND_BIND_GB_SURFACE = 1100,
- SVGA_3D_CMD_UPDATE_GB_IMAGE = 1101,
- SVGA_3D_CMD_UPDATE_GB_SURFACE = 1102,
- SVGA_3D_CMD_READBACK_GB_IMAGE = 1103,
- SVGA_3D_CMD_READBACK_GB_SURFACE = 1104,
- SVGA_3D_CMD_INVALIDATE_GB_IMAGE = 1105,
- SVGA_3D_CMD_INVALIDATE_GB_SURFACE = 1106,
-
- SVGA_3D_CMD_DEFINE_GB_CONTEXT = 1107,
- SVGA_3D_CMD_DESTROY_GB_CONTEXT = 1108,
- SVGA_3D_CMD_BIND_GB_CONTEXT = 1109,
- SVGA_3D_CMD_READBACK_GB_CONTEXT = 1110,
- SVGA_3D_CMD_INVALIDATE_GB_CONTEXT = 1111,
-
- SVGA_3D_CMD_DEFINE_GB_SHADER = 1112,
- SVGA_3D_CMD_DESTROY_GB_SHADER = 1113,
- SVGA_3D_CMD_BIND_GB_SHADER = 1114,
-
- SVGA_3D_CMD_SET_OTABLE_BASE64 = 1115,
-
- SVGA_3D_CMD_BEGIN_GB_QUERY = 1116,
- SVGA_3D_CMD_END_GB_QUERY = 1117,
- SVGA_3D_CMD_WAIT_FOR_GB_QUERY = 1118,
-
- SVGA_3D_CMD_NOP = 1119,
-
- SVGA_3D_CMD_ENABLE_GART = 1120,
- SVGA_3D_CMD_DISABLE_GART = 1121,
- SVGA_3D_CMD_MAP_MOB_INTO_GART = 1122,
- SVGA_3D_CMD_UNMAP_GART_RANGE = 1123,
-
- SVGA_3D_CMD_DEFINE_GB_SCREENTARGET = 1124,
- SVGA_3D_CMD_DESTROY_GB_SCREENTARGET = 1125,
- SVGA_3D_CMD_BIND_GB_SCREENTARGET = 1126,
- SVGA_3D_CMD_UPDATE_GB_SCREENTARGET = 1127,
-
- SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL = 1128,
- SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL = 1129,
-
- SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE = 1130,
-
- SVGA_3D_CMD_GB_SCREEN_DMA = 1131,
- SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH = 1132,
- SVGA_3D_CMD_GB_MOB_FENCE = 1133,
- SVGA_3D_CMD_DEFINE_GB_SURFACE_V2 = 1134,
- SVGA_3D_CMD_DEFINE_GB_MOB64 = 1135,
- SVGA_3D_CMD_REDEFINE_GB_MOB64 = 1136,
- SVGA_3D_CMD_NOP_ERROR = 1137,
-
- SVGA_3D_CMD_SET_VERTEX_STREAMS = 1138,
- SVGA_3D_CMD_SET_VERTEX_DECLS = 1139,
- SVGA_3D_CMD_SET_VERTEX_DIVISORS = 1140,
- SVGA_3D_CMD_DRAW = 1141,
- SVGA_3D_CMD_DRAW_INDEXED = 1142,
-
- /*
- * DX10 Commands
- */
- SVGA_3D_CMD_DX_MIN = 1143,
- SVGA_3D_CMD_DX_DEFINE_CONTEXT = 1143,
- SVGA_3D_CMD_DX_DESTROY_CONTEXT = 1144,
- SVGA_3D_CMD_DX_BIND_CONTEXT = 1145,
- SVGA_3D_CMD_DX_READBACK_CONTEXT = 1146,
- SVGA_3D_CMD_DX_INVALIDATE_CONTEXT = 1147,
- SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER = 1148,
- SVGA_3D_CMD_DX_SET_SHADER_RESOURCES = 1149,
- SVGA_3D_CMD_DX_SET_SHADER = 1150,
- SVGA_3D_CMD_DX_SET_SAMPLERS = 1151,
- SVGA_3D_CMD_DX_DRAW = 1152,
- SVGA_3D_CMD_DX_DRAW_INDEXED = 1153,
- SVGA_3D_CMD_DX_DRAW_INSTANCED = 1154,
- SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED = 1155,
- SVGA_3D_CMD_DX_DRAW_AUTO = 1156,
- SVGA_3D_CMD_DX_SET_INPUT_LAYOUT = 1157,
- SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS = 1158,
- SVGA_3D_CMD_DX_SET_INDEX_BUFFER = 1159,
- SVGA_3D_CMD_DX_SET_TOPOLOGY = 1160,
- SVGA_3D_CMD_DX_SET_RENDERTARGETS = 1161,
- SVGA_3D_CMD_DX_SET_BLEND_STATE = 1162,
- SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE = 1163,
- SVGA_3D_CMD_DX_SET_RASTERIZER_STATE = 1164,
- SVGA_3D_CMD_DX_DEFINE_QUERY = 1165,
- SVGA_3D_CMD_DX_DESTROY_QUERY = 1166,
- SVGA_3D_CMD_DX_BIND_QUERY = 1167,
- SVGA_3D_CMD_DX_SET_QUERY_OFFSET = 1168,
- SVGA_3D_CMD_DX_BEGIN_QUERY = 1169,
- SVGA_3D_CMD_DX_END_QUERY = 1170,
- SVGA_3D_CMD_DX_READBACK_QUERY = 1171,
- SVGA_3D_CMD_DX_SET_PREDICATION = 1172,
- SVGA_3D_CMD_DX_SET_SOTARGETS = 1173,
- SVGA_3D_CMD_DX_SET_VIEWPORTS = 1174,
- SVGA_3D_CMD_DX_SET_SCISSORRECTS = 1175,
- SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW = 1176,
- SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW = 1177,
- SVGA_3D_CMD_DX_PRED_COPY_REGION = 1178,
- SVGA_3D_CMD_DX_PRED_COPY = 1179,
- SVGA_3D_CMD_DX_PRESENTBLT = 1180,
- SVGA_3D_CMD_DX_GENMIPS = 1181,
- SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE = 1182,
- SVGA_3D_CMD_DX_READBACK_SUBRESOURCE = 1183,
- SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE = 1184,
- SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW = 1185,
- SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW = 1186,
- SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW = 1187,
- SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW = 1188,
- SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW = 1189,
- SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW = 1190,
- SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT = 1191,
- SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT = 1192,
- SVGA_3D_CMD_DX_DEFINE_BLEND_STATE = 1193,
- SVGA_3D_CMD_DX_DESTROY_BLEND_STATE = 1194,
- SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE = 1195,
- SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE = 1196,
- SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE = 1197,
- SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE = 1198,
- SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE = 1199,
- SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE = 1200,
- SVGA_3D_CMD_DX_DEFINE_SHADER = 1201,
- SVGA_3D_CMD_DX_DESTROY_SHADER = 1202,
- SVGA_3D_CMD_DX_BIND_SHADER = 1203,
- SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT = 1204,
- SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT = 1205,
- SVGA_3D_CMD_DX_SET_STREAMOUTPUT = 1206,
- SVGA_3D_CMD_DX_SET_COTABLE = 1207,
- SVGA_3D_CMD_DX_READBACK_COTABLE = 1208,
- SVGA_3D_CMD_DX_BUFFER_COPY = 1209,
- SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER = 1210,
- SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK = 1211,
- SVGA_3D_CMD_DX_MOVE_QUERY = 1212,
- SVGA_3D_CMD_DX_BIND_ALL_QUERY = 1213,
- SVGA_3D_CMD_DX_READBACK_ALL_QUERY = 1214,
- SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER = 1215,
- SVGA_3D_CMD_DX_MOB_FENCE_64 = 1216,
- SVGA_3D_CMD_DX_BIND_ALL_SHADER = 1217,
- SVGA_3D_CMD_DX_HINT = 1218,
- SVGA_3D_CMD_DX_BUFFER_UPDATE = 1219,
- SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET = 1220,
- SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET = 1221,
- SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET = 1222,
- SVGA_3D_CMD_DX_SET_HS_CONSTANT_BUFFER_OFFSET = 1223,
- SVGA_3D_CMD_DX_SET_DS_CONSTANT_BUFFER_OFFSET = 1224,
- SVGA_3D_CMD_DX_SET_CS_CONSTANT_BUFFER_OFFSET = 1225,
-
- SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER = 1226,
- SVGA_3D_CMD_DX_MAX = 1227,
-
- SVGA_3D_CMD_SCREEN_COPY = 1227,
-
- SVGA_3D_CMD_RESERVED1 = 1228,
- SVGA_3D_CMD_RESERVED2 = 1229,
- SVGA_3D_CMD_RESERVED3 = 1230,
- SVGA_3D_CMD_RESERVED4 = 1231,
- SVGA_3D_CMD_RESERVED5 = 1232,
- SVGA_3D_CMD_RESERVED6 = 1233,
- SVGA_3D_CMD_RESERVED7 = 1234,
- SVGA_3D_CMD_RESERVED8 = 1235,
-
- SVGA_3D_CMD_GROW_OTABLE = 1236,
- SVGA_3D_CMD_DX_GROW_COTABLE = 1237,
- SVGA_3D_CMD_INTRA_SURFACE_COPY = 1238,
-
- SVGA_3D_CMD_DEFINE_GB_SURFACE_V3 = 1239,
-
- SVGA_3D_CMD_DX_RESOLVE_COPY = 1240,
- SVGA_3D_CMD_DX_PRED_RESOLVE_COPY = 1241,
- SVGA_3D_CMD_DX_PRED_CONVERT_REGION = 1242,
- SVGA_3D_CMD_DX_PRED_CONVERT = 1243,
- SVGA_3D_CMD_WHOLE_SURFACE_COPY = 1244,
-
- SVGA_3D_CMD_DX_DEFINE_UA_VIEW = 1245,
- SVGA_3D_CMD_DX_DESTROY_UA_VIEW = 1246,
- SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT = 1247,
- SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT = 1248,
- SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT = 1249,
- SVGA_3D_CMD_DX_SET_UA_VIEWS = 1250,
-
- SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT = 1251,
- SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT = 1252,
- SVGA_3D_CMD_DX_DISPATCH = 1253,
- SVGA_3D_CMD_DX_DISPATCH_INDIRECT = 1254,
-
- SVGA_3D_CMD_WRITE_ZERO_SURFACE = 1255,
- SVGA_3D_CMD_HINT_ZERO_SURFACE = 1256,
- SVGA_3D_CMD_DX_TRANSFER_TO_BUFFER = 1257,
- SVGA_3D_CMD_DX_SET_STRUCTURE_COUNT = 1258,
-
- SVGA_3D_CMD_LOGICOPS_BITBLT = 1259,
- SVGA_3D_CMD_LOGICOPS_TRANSBLT = 1260,
- SVGA_3D_CMD_LOGICOPS_STRETCHBLT = 1261,
- SVGA_3D_CMD_LOGICOPS_COLORFILL = 1262,
- SVGA_3D_CMD_LOGICOPS_ALPHABLEND = 1263,
- SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND = 1264,
-
- SVGA_3D_CMD_RESERVED2_1 = 1265,
-
- SVGA_3D_CMD_RESERVED2_2 = 1266,
- SVGA_3D_CMD_DEFINE_GB_SURFACE_V4 = 1267,
- SVGA_3D_CMD_DX_SET_CS_UA_VIEWS = 1268,
- SVGA_3D_CMD_DX_SET_MIN_LOD = 1269,
- SVGA_3D_CMD_RESERVED2_3 = 1270,
- SVGA_3D_CMD_RESERVED2_4 = 1271,
- SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2 = 1272,
- SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB = 1273,
- SVGA_3D_CMD_DX_SET_SHADER_IFACE = 1274,
- SVGA_3D_CMD_DX_BIND_STREAMOUTPUT = 1275,
- SVGA_3D_CMD_SURFACE_STRETCHBLT_NON_MS_TO_MS = 1276,
- SVGA_3D_CMD_DX_BIND_SHADER_IFACE = 1277,
-
- SVGA_3D_CMD_MAX = 1278,
- SVGA_3D_CMD_FUTURE_MAX = 3000
+#include "svga3d_limits.h"
+#include "svga_reg.h"
+
+typedef enum SVGAFifo3dCmdId {
+ SVGA_3D_CMD_LEGACY_BASE = 1000,
+ SVGA_3D_CMD_BASE = 1040,
+
+ SVGA_3D_CMD_SURFACE_DEFINE = 1040,
+ SVGA_3D_CMD_SURFACE_DESTROY = 1041,
+ SVGA_3D_CMD_SURFACE_COPY = 1042,
+ SVGA_3D_CMD_SURFACE_STRETCHBLT = 1043,
+ SVGA_3D_CMD_SURFACE_DMA = 1044,
+ SVGA_3D_CMD_CONTEXT_DEFINE = 1045,
+ SVGA_3D_CMD_CONTEXT_DESTROY = 1046,
+ SVGA_3D_CMD_SETTRANSFORM = 1047,
+ SVGA_3D_CMD_SETZRANGE = 1048,
+ SVGA_3D_CMD_SETRENDERSTATE = 1049,
+ SVGA_3D_CMD_SETRENDERTARGET = 1050,
+ SVGA_3D_CMD_SETTEXTURESTATE = 1051,
+ SVGA_3D_CMD_SETMATERIAL = 1052,
+ SVGA_3D_CMD_SETLIGHTDATA = 1053,
+ SVGA_3D_CMD_SETLIGHTENABLED = 1054,
+ SVGA_3D_CMD_SETVIEWPORT = 1055,
+ SVGA_3D_CMD_SETCLIPPLANE = 1056,
+ SVGA_3D_CMD_CLEAR = 1057,
+ SVGA_3D_CMD_PRESENT = 1058,
+ SVGA_3D_CMD_SHADER_DEFINE = 1059,
+ SVGA_3D_CMD_SHADER_DESTROY = 1060,
+ SVGA_3D_CMD_SET_SHADER = 1061,
+ SVGA_3D_CMD_SET_SHADER_CONST = 1062,
+ SVGA_3D_CMD_DRAW_PRIMITIVES = 1063,
+ SVGA_3D_CMD_SETSCISSORRECT = 1064,
+ SVGA_3D_CMD_BEGIN_QUERY = 1065,
+ SVGA_3D_CMD_END_QUERY = 1066,
+ SVGA_3D_CMD_WAIT_FOR_QUERY = 1067,
+ SVGA_3D_CMD_PRESENT_READBACK = 1068,
+ SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN = 1069,
+ SVGA_3D_CMD_SURFACE_DEFINE_V2 = 1070,
+ SVGA_3D_CMD_GENERATE_MIPMAPS = 1071,
+ SVGA_3D_CMD_DEAD4 = 1072,
+ SVGA_3D_CMD_DEAD5 = 1073,
+ SVGA_3D_CMD_DEAD6 = 1074,
+ SVGA_3D_CMD_DEAD7 = 1075,
+ SVGA_3D_CMD_DEAD8 = 1076,
+ SVGA_3D_CMD_DEAD9 = 1077,
+ SVGA_3D_CMD_DEAD10 = 1078,
+ SVGA_3D_CMD_DEAD11 = 1079,
+ SVGA_3D_CMD_ACTIVATE_SURFACE = 1080,
+ SVGA_3D_CMD_DEACTIVATE_SURFACE = 1081,
+ SVGA_3D_CMD_SCREEN_DMA = 1082,
+ SVGA_3D_CMD_DEAD1 = 1083,
+ SVGA_3D_CMD_DEAD2 = 1084,
+
+ SVGA_3D_CMD_DEAD12 = 1085,
+ SVGA_3D_CMD_DEAD13 = 1086,
+ SVGA_3D_CMD_DEAD14 = 1087,
+ SVGA_3D_CMD_DEAD15 = 1088,
+ SVGA_3D_CMD_DEAD16 = 1089,
+ SVGA_3D_CMD_DEAD17 = 1090,
+
+ SVGA_3D_CMD_SET_OTABLE_BASE = 1091,
+ SVGA_3D_CMD_READBACK_OTABLE = 1092,
+
+ SVGA_3D_CMD_DEFINE_GB_MOB = 1093,
+ SVGA_3D_CMD_DESTROY_GB_MOB = 1094,
+ SVGA_3D_CMD_DEAD3 = 1095,
+ SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING = 1096,
+
+ SVGA_3D_CMD_DEFINE_GB_SURFACE = 1097,
+ SVGA_3D_CMD_DESTROY_GB_SURFACE = 1098,
+ SVGA_3D_CMD_BIND_GB_SURFACE = 1099,
+ SVGA_3D_CMD_COND_BIND_GB_SURFACE = 1100,
+ SVGA_3D_CMD_UPDATE_GB_IMAGE = 1101,
+ SVGA_3D_CMD_UPDATE_GB_SURFACE = 1102,
+ SVGA_3D_CMD_READBACK_GB_IMAGE = 1103,
+ SVGA_3D_CMD_READBACK_GB_SURFACE = 1104,
+ SVGA_3D_CMD_INVALIDATE_GB_IMAGE = 1105,
+ SVGA_3D_CMD_INVALIDATE_GB_SURFACE = 1106,
+
+ SVGA_3D_CMD_DEFINE_GB_CONTEXT = 1107,
+ SVGA_3D_CMD_DESTROY_GB_CONTEXT = 1108,
+ SVGA_3D_CMD_BIND_GB_CONTEXT = 1109,
+ SVGA_3D_CMD_READBACK_GB_CONTEXT = 1110,
+ SVGA_3D_CMD_INVALIDATE_GB_CONTEXT = 1111,
+
+ SVGA_3D_CMD_DEFINE_GB_SHADER = 1112,
+ SVGA_3D_CMD_DESTROY_GB_SHADER = 1113,
+ SVGA_3D_CMD_BIND_GB_SHADER = 1114,
+
+ SVGA_3D_CMD_SET_OTABLE_BASE64 = 1115,
+
+ SVGA_3D_CMD_BEGIN_GB_QUERY = 1116,
+ SVGA_3D_CMD_END_GB_QUERY = 1117,
+ SVGA_3D_CMD_WAIT_FOR_GB_QUERY = 1118,
+
+ SVGA_3D_CMD_NOP = 1119,
+
+ SVGA_3D_CMD_ENABLE_GART = 1120,
+ SVGA_3D_CMD_DISABLE_GART = 1121,
+ SVGA_3D_CMD_MAP_MOB_INTO_GART = 1122,
+ SVGA_3D_CMD_UNMAP_GART_RANGE = 1123,
+
+ SVGA_3D_CMD_DEFINE_GB_SCREENTARGET = 1124,
+ SVGA_3D_CMD_DESTROY_GB_SCREENTARGET = 1125,
+ SVGA_3D_CMD_BIND_GB_SCREENTARGET = 1126,
+ SVGA_3D_CMD_UPDATE_GB_SCREENTARGET = 1127,
+
+ SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL = 1128,
+ SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL = 1129,
+
+ SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE = 1130,
+
+ SVGA_3D_CMD_GB_SCREEN_DMA = 1131,
+ SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH = 1132,
+ SVGA_3D_CMD_GB_MOB_FENCE = 1133,
+ SVGA_3D_CMD_DEFINE_GB_SURFACE_V2 = 1134,
+ SVGA_3D_CMD_DEFINE_GB_MOB64 = 1135,
+ SVGA_3D_CMD_REDEFINE_GB_MOB64 = 1136,
+ SVGA_3D_CMD_NOP_ERROR = 1137,
+
+ SVGA_3D_CMD_SET_VERTEX_STREAMS = 1138,
+ SVGA_3D_CMD_SET_VERTEX_DECLS = 1139,
+ SVGA_3D_CMD_SET_VERTEX_DIVISORS = 1140,
+ SVGA_3D_CMD_DRAW = 1141,
+ SVGA_3D_CMD_DRAW_INDEXED = 1142,
+
+ SVGA_3D_CMD_DX_MIN = 1143,
+ SVGA_3D_CMD_DX_DEFINE_CONTEXT = 1143,
+ SVGA_3D_CMD_DX_DESTROY_CONTEXT = 1144,
+ SVGA_3D_CMD_DX_BIND_CONTEXT = 1145,
+ SVGA_3D_CMD_DX_READBACK_CONTEXT = 1146,
+ SVGA_3D_CMD_DX_INVALIDATE_CONTEXT = 1147,
+ SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER = 1148,
+ SVGA_3D_CMD_DX_SET_SHADER_RESOURCES = 1149,
+ SVGA_3D_CMD_DX_SET_SHADER = 1150,
+ SVGA_3D_CMD_DX_SET_SAMPLERS = 1151,
+ SVGA_3D_CMD_DX_DRAW = 1152,
+ SVGA_3D_CMD_DX_DRAW_INDEXED = 1153,
+ SVGA_3D_CMD_DX_DRAW_INSTANCED = 1154,
+ SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED = 1155,
+ SVGA_3D_CMD_DX_DRAW_AUTO = 1156,
+ SVGA_3D_CMD_DX_SET_INPUT_LAYOUT = 1157,
+ SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS = 1158,
+ SVGA_3D_CMD_DX_SET_INDEX_BUFFER = 1159,
+ SVGA_3D_CMD_DX_SET_TOPOLOGY = 1160,
+ SVGA_3D_CMD_DX_SET_RENDERTARGETS = 1161,
+ SVGA_3D_CMD_DX_SET_BLEND_STATE = 1162,
+ SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE = 1163,
+ SVGA_3D_CMD_DX_SET_RASTERIZER_STATE = 1164,
+ SVGA_3D_CMD_DX_DEFINE_QUERY = 1165,
+ SVGA_3D_CMD_DX_DESTROY_QUERY = 1166,
+ SVGA_3D_CMD_DX_BIND_QUERY = 1167,
+ SVGA_3D_CMD_DX_SET_QUERY_OFFSET = 1168,
+ SVGA_3D_CMD_DX_BEGIN_QUERY = 1169,
+ SVGA_3D_CMD_DX_END_QUERY = 1170,
+ SVGA_3D_CMD_DX_READBACK_QUERY = 1171,
+ SVGA_3D_CMD_DX_SET_PREDICATION = 1172,
+ SVGA_3D_CMD_DX_SET_SOTARGETS = 1173,
+ SVGA_3D_CMD_DX_SET_VIEWPORTS = 1174,
+ SVGA_3D_CMD_DX_SET_SCISSORRECTS = 1175,
+ SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW = 1176,
+ SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW = 1177,
+ SVGA_3D_CMD_DX_PRED_COPY_REGION = 1178,
+ SVGA_3D_CMD_DX_PRED_COPY = 1179,
+ SVGA_3D_CMD_DX_PRESENTBLT = 1180,
+ SVGA_3D_CMD_DX_GENMIPS = 1181,
+ SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE = 1182,
+ SVGA_3D_CMD_DX_READBACK_SUBRESOURCE = 1183,
+ SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE = 1184,
+ SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW = 1185,
+ SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW = 1186,
+ SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW = 1187,
+ SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW = 1188,
+ SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW = 1189,
+ SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW = 1190,
+ SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT = 1191,
+ SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT = 1192,
+ SVGA_3D_CMD_DX_DEFINE_BLEND_STATE = 1193,
+ SVGA_3D_CMD_DX_DESTROY_BLEND_STATE = 1194,
+ SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE = 1195,
+ SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE = 1196,
+ SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE = 1197,
+ SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE = 1198,
+ SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE = 1199,
+ SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE = 1200,
+ SVGA_3D_CMD_DX_DEFINE_SHADER = 1201,
+ SVGA_3D_CMD_DX_DESTROY_SHADER = 1202,
+ SVGA_3D_CMD_DX_BIND_SHADER = 1203,
+ SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT = 1204,
+ SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT = 1205,
+ SVGA_3D_CMD_DX_SET_STREAMOUTPUT = 1206,
+ SVGA_3D_CMD_DX_SET_COTABLE = 1207,
+ SVGA_3D_CMD_DX_READBACK_COTABLE = 1208,
+ SVGA_3D_CMD_DX_BUFFER_COPY = 1209,
+ SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER = 1210,
+ SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK = 1211,
+ SVGA_3D_CMD_DX_MOVE_QUERY = 1212,
+ SVGA_3D_CMD_DX_BIND_ALL_QUERY = 1213,
+ SVGA_3D_CMD_DX_READBACK_ALL_QUERY = 1214,
+ SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER = 1215,
+ SVGA_3D_CMD_DX_MOB_FENCE_64 = 1216,
+ SVGA_3D_CMD_DX_BIND_ALL_SHADER = 1217,
+ SVGA_3D_CMD_DX_HINT = 1218,
+ SVGA_3D_CMD_DX_BUFFER_UPDATE = 1219,
+ SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET = 1220,
+ SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET = 1221,
+ SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET = 1222,
+ SVGA_3D_CMD_DX_SET_HS_CONSTANT_BUFFER_OFFSET = 1223,
+ SVGA_3D_CMD_DX_SET_DS_CONSTANT_BUFFER_OFFSET = 1224,
+ SVGA_3D_CMD_DX_SET_CS_CONSTANT_BUFFER_OFFSET = 1225,
+
+ SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER = 1226,
+ SVGA_3D_CMD_DX_MAX = 1227,
+
+ SVGA_3D_CMD_SCREEN_COPY = 1227,
+
+ SVGA_3D_CMD_RESERVED1 = 1228,
+ SVGA_3D_CMD_RESERVED2 = 1229,
+ SVGA_3D_CMD_RESERVED3 = 1230,
+ SVGA_3D_CMD_RESERVED4 = 1231,
+ SVGA_3D_CMD_RESERVED5 = 1232,
+ SVGA_3D_CMD_RESERVED6 = 1233,
+ SVGA_3D_CMD_RESERVED7 = 1234,
+ SVGA_3D_CMD_RESERVED8 = 1235,
+
+ SVGA_3D_CMD_GROW_OTABLE = 1236,
+ SVGA_3D_CMD_DX_GROW_COTABLE = 1237,
+ SVGA_3D_CMD_INTRA_SURFACE_COPY = 1238,
+
+ SVGA_3D_CMD_DEFINE_GB_SURFACE_V3 = 1239,
+
+ SVGA_3D_CMD_DX_RESOLVE_COPY = 1240,
+ SVGA_3D_CMD_DX_PRED_RESOLVE_COPY = 1241,
+ SVGA_3D_CMD_DX_PRED_CONVERT_REGION = 1242,
+ SVGA_3D_CMD_DX_PRED_CONVERT = 1243,
+ SVGA_3D_CMD_WHOLE_SURFACE_COPY = 1244,
+
+ SVGA_3D_CMD_DX_DEFINE_UA_VIEW = 1245,
+ SVGA_3D_CMD_DX_DESTROY_UA_VIEW = 1246,
+ SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT = 1247,
+ SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT = 1248,
+ SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT = 1249,
+ SVGA_3D_CMD_DX_SET_UA_VIEWS = 1250,
+
+ SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT = 1251,
+ SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT = 1252,
+ SVGA_3D_CMD_DX_DISPATCH = 1253,
+ SVGA_3D_CMD_DX_DISPATCH_INDIRECT = 1254,
+
+ SVGA_3D_CMD_WRITE_ZERO_SURFACE = 1255,
+ SVGA_3D_CMD_UPDATE_ZERO_SURFACE = 1256,
+ SVGA_3D_CMD_DX_TRANSFER_TO_BUFFER = 1257,
+ SVGA_3D_CMD_DX_SET_STRUCTURE_COUNT = 1258,
+
+ SVGA_3D_CMD_LOGICOPS_BITBLT = 1259,
+ SVGA_3D_CMD_LOGICOPS_TRANSBLT = 1260,
+ SVGA_3D_CMD_LOGICOPS_STRETCHBLT = 1261,
+ SVGA_3D_CMD_LOGICOPS_COLORFILL = 1262,
+ SVGA_3D_CMD_LOGICOPS_ALPHABLEND = 1263,
+ SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND = 1264,
+
+ SVGA_3D_CMD_DX_COPY_COTABLE_INTO_MOB = 1265,
+
+ SVGA_3D_CMD_UPDATE_GB_SCREENTARGET_V2 = 1266,
+
+ SVGA_3D_CMD_DEFINE_GB_SURFACE_V4 = 1267,
+ SVGA_3D_CMD_DX_SET_CS_UA_VIEWS = 1268,
+ SVGA_3D_CMD_DX_SET_MIN_LOD = 1269,
+
+ SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2 = 1272,
+ SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB = 1273,
+ SVGA_3D_CMD_DX_SET_SHADER_IFACE = 1274,
+ SVGA_3D_CMD_DX_BIND_STREAMOUTPUT = 1275,
+ SVGA_3D_CMD_SURFACE_STRETCHBLT_NON_MS_TO_MS = 1276,
+ SVGA_3D_CMD_DX_BIND_SHADER_IFACE = 1277,
+
+ SVGA_3D_CMD_UPDATE_GB_SCREENTARGET_MOVE = 1278,
+
+ SVGA_3D_CMD_DX_PRED_STAGING_COPY = 1281,
+ SVGA_3D_CMD_DX_STAGING_COPY = 1282,
+ SVGA_3D_CMD_DX_PRED_STAGING_COPY_REGION = 1283,
+ SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS_V2 = 1284,
+ SVGA_3D_CMD_DX_SET_INDEX_BUFFER_V2 = 1285,
+ SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS_OFFSET_AND_SIZE = 1286,
+ SVGA_3D_CMD_DX_SET_INDEX_BUFFER_OFFSET_AND_SIZE = 1287,
+ SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE_V2 = 1288,
+ SVGA_3D_CMD_DX_PRED_STAGING_CONVERT_REGION = 1289,
+ SVGA_3D_CMD_DX_PRED_STAGING_CONVERT = 1290,
+ SVGA_3D_CMD_DX_STAGING_BUFFER_COPY = 1291,
+
+ SVGA_3D_CMD_MAX = 1303,
+ SVGA_3D_CMD_FUTURE_MAX = 3000
} SVGAFifo3dCmdId;
#define SVGA_NUM_3D_CMD (SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE)
-/*
- * FIFO command format definitions:
- */
-
-/*
- * The data size header following cmdNum for every 3d command
- */
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 id;
- uint32 size;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdHeader;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 numMipLevels;
-}
-#include "vmware_pack_end.h"
-SVGA3dSurfaceFace;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
- SVGA3dSurface1Flags surfaceFlags;
- SVGA3dSurfaceFormat format;
-
- /*
- * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace
- * structures must have the same value of numMipLevels field.
- * Otherwise, all but the first SVGA3dSurfaceFace structures must have the
- * numMipLevels set to 0.
- */
- SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES];
-
- /*
- * Followed by an SVGA3dSize structure for each mip level in each face.
- *
- * A note on surface sizes: Sizes are always specified in pixels,
- * even if the true surface size is not a multiple of the minimum
- * block size of the surface's format. For example, a 3x3x1 DXT1
- * compressed texture would actually be stored as a 4x4x1 image in
- * memory.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineSurface; /* SVGA_3D_CMD_SURFACE_DEFINE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
- SVGA3dSurface1Flags surfaceFlags;
- SVGA3dSurfaceFormat format;
-
- /*
- * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace
- * structures must have the same value of numMipLevels field.
- * Otherwise, all but the first SVGA3dSurfaceFace structures must have the
- * numMipLevels set to 0.
- */
- SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES];
- uint32 multisampleCount;
- SVGA3dTextureFilter autogenFilter;
-
- /*
- * Followed by an SVGA3dSize structure for each mip level in each face.
- *
- * A note on surface sizes: Sizes are always specified in pixels,
- * even if the true surface size is not a multiple of the minimum
- * block size of the surface's format. For example, a 3x3x1 DXT1
- * compressed texture would actually be stored as a 4x4x1 image in
- * memory.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineSurface_v2; /* SVGA_3D_CMD_SURFACE_DEFINE_V2 */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDestroySurface; /* SVGA_3D_CMD_SURFACE_DESTROY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineContext; /* SVGA_3D_CMD_CONTEXT_DEFINE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDestroyContext; /* SVGA_3D_CMD_CONTEXT_DESTROY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dClearFlag clearFlag;
- uint32 color;
- float depth;
- uint32 stencil;
- /* Followed by variable number of SVGA3dRect structures */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdClear; /* SVGA_3D_CMD_CLEAR */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dLightType type;
- SVGA3dBool inWorldSpace;
- float diffuse[4];
- float specular[4];
- float ambient[4];
- float position[4];
- float direction[4];
- float range;
- float falloff;
- float attenuation0;
- float attenuation1;
- float attenuation2;
- float theta;
- float phi;
-}
-#include "vmware_pack_end.h"
-SVGA3dLightData;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
- /* Followed by variable number of SVGA3dCopyRect structures */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdPresent; /* SVGA_3D_CMD_PRESENT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dRenderStateName state;
- union {
- uint32 uintValue;
- float floatValue;
- };
-}
-#include "vmware_pack_end.h"
-SVGA3dRenderState;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- /* Followed by variable number of SVGA3dRenderState structures */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetRenderState; /* SVGA_3D_CMD_SETRENDERSTATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dRenderTargetType type;
- SVGA3dSurfaceImageId target;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetRenderTarget; /* SVGA_3D_CMD_SETRENDERTARGET */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceImageId src;
- SVGA3dSurfaceImageId dest;
- /* Followed by variable number of SVGA3dCopyBox structures */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSurfaceCopy; /* SVGA_3D_CMD_SURFACE_COPY */
+#pragma pack(push, 1)
+typedef struct {
+ uint32 id;
+ uint32 size;
+} SVGA3dCmdHeader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 numMipLevels;
+} SVGA3dSurfaceFace;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+ SVGA3dSurface1Flags surfaceFlags;
+ SVGA3dSurfaceFormat format;
+
+ SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES];
+
+} SVGA3dCmdDefineSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+ SVGA3dSurface1Flags surfaceFlags;
+ SVGA3dSurfaceFormat format;
+
+ SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES];
+ uint32 multisampleCount;
+ SVGA3dTextureFilter autogenFilter;
+
+} SVGA3dCmdDefineSurface_v2;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+} SVGA3dCmdDestroySurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+} SVGA3dCmdDefineContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+} SVGA3dCmdDestroyContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dClearFlag clearFlag;
+ uint32 color;
+ float depth;
+ uint32 stencil;
+
+} SVGA3dCmdClear;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dLightType type;
+ SVGA3dBool inWorldSpace;
+ float diffuse[4];
+ float specular[4];
+ float ambient[4];
+ float position[4];
+ float direction[4];
+ float range;
+ float falloff;
+ float attenuation0;
+ float attenuation1;
+ float attenuation2;
+ float theta;
+ float phi;
+} SVGA3dLightData;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+
+} SVGA3dCmdPresent;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dRenderStateName state;
+ union {
+ uint32 uintValue;
+ float floatValue;
+ };
+} SVGA3dRenderState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+
+} SVGA3dCmdSetRenderState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dRenderTargetType type;
+ SVGA3dSurfaceImageId target;
+} SVGA3dCmdSetRenderTarget;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceImageId src;
+ SVGA3dSurfaceImageId dest;
+
+} SVGA3dCmdSurfaceCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceImageId surface;
+ SVGA3dCopyBox box;
+} SVGA3dCmdIntraSurfaceCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 srcSid;
+ uint32 destSid;
+} SVGA3dCmdWholeSurfaceCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceImageId src;
+ SVGA3dSurfaceImageId dest;
+ SVGA3dBox boxSrc;
+ SVGA3dBox boxDest;
+} SVGA3dCmdSurfaceStretchBltNonMSToMS;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceImageId src;
+ SVGA3dSurfaceImageId dest;
+ SVGA3dBox boxSrc;
+ SVGA3dBox boxDest;
+ SVGA3dStretchBltMode mode;
+} SVGA3dCmdSurfaceStretchBlt;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 discard : 1;
+
+ uint32 unsynchronized : 1;
+
+ uint32 reserved : 30;
+} SVGA3dSurfaceDMAFlags;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAGuestImage guest;
+ SVGA3dSurfaceImageId host;
+ SVGA3dTransferType transfer;
+
+} SVGA3dCmdSurfaceDMA;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 suffixSize;
+
+ uint32 maximumOffset;
+
+ SVGA3dSurfaceDMAFlags flags;
+} SVGA3dCmdSurfaceDMASuffix;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 first;
+ uint32 last;
+} SVGA3dArrayRangeHint;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 surfaceId;
+ uint32 offset;
+ uint32 stride;
+} SVGA3dArray;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dDeclType type;
+ SVGA3dDeclMethod method;
+ SVGA3dDeclUsage usage;
+ uint32 usageIndex;
+} SVGA3dVertexArrayIdentity;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dVertexDecl {
+ SVGA3dVertexArrayIdentity identity;
+ SVGA3dArray array;
+ SVGA3dArrayRangeHint rangeHint;
+} SVGA3dVertexDecl;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dPrimitiveRange {
+ SVGA3dPrimitiveType primType;
+ uint32 primitiveCount;
+
+ SVGA3dArray indexArray;
+ uint32 indexWidth;
+
+ int32 indexBias;
+} SVGA3dPrimitiveRange;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 numVertexDecls;
+ uint32 numRanges;
+
+} SVGA3dCmdDrawPrimitives;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+
+ uint32 primitiveCount;
+ uint32 startVertexLocation;
+
+ uint8 primitiveType;
+ uint8 padding[3];
+} SVGA3dCmdDraw;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+
+ uint8 primitiveType;
+
+ uint32 indexBufferSid;
+ uint32 indexBufferOffset;
+
+ uint8 indexBufferStride;
+
+ int32 baseVertexLocation;
+
+ uint32 primitiveCount;
+ uint32 pad0;
+ uint16 pad1;
+} SVGA3dCmdDrawIndexed;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint16 streamOffset;
+ uint8 stream;
+ uint8 type;
+ uint8 method;
+ uint8 usage;
+ uint8 usageIndex;
+ uint8 padding;
+
+} SVGA3dVertexElement;
+#pragma pack(pop)
-/*
- * Perform a surface copy within the same image.
- * The src/dest boxes are allowed to overlap.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceImageId surface;
- SVGA3dCopyBox box;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdIntraSurfaceCopy; /* SVGA_3D_CMD_INTRA_SURFACE_COPY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 srcSid;
- uint32 destSid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdWholeSurfaceCopy; /* SVGA_3D_CMD_WHOLE_SURFACE_COPY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceImageId src;
- SVGA3dSurfaceImageId dest;
- SVGA3dBox boxSrc;
- SVGA3dBox boxDest;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSurfaceStretchBltNonMSToMS;
-/* SVGA_3D_CMD_SURFACE_STRETCHBLT_NON_MS_TO_MS */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceImageId src;
- SVGA3dSurfaceImageId dest;
- SVGA3dBox boxSrc;
- SVGA3dBox boxDest;
- SVGA3dStretchBltMode mode;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSurfaceStretchBlt; /* SVGA_3D_CMD_SURFACE_STRETCHBLT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- /*
- * If the discard flag is present in a surface DMA operation, the host may
- * discard the contents of the current mipmap level and face of the target
- * surface before applying the surface DMA contents.
- */
- uint32 discard : 1;
-
- /*
- * If the unsynchronized flag is present, the host may perform this upload
- * without syncing to pending reads on this surface.
- */
- uint32 unsynchronized : 1;
-
- /*
- * Guests *MUST* set the reserved bits to 0 before submitting the command
- * suffix as future flags may occupy these bits.
- */
- uint32 reserved : 30;
-}
-#include "vmware_pack_end.h"
-SVGA3dSurfaceDMAFlags;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAGuestImage guest;
- SVGA3dSurfaceImageId host;
- SVGA3dTransferType transfer;
-
- /*
- * Followed by variable number of SVGA3dCopyBox structures. For consistency
- * in all clipping logic and coordinate translation, we define the
- * "source" in each copyBox as the guest image and the
- * "destination" as the host image, regardless of transfer
- * direction.
- *
- * For efficiency, the SVGA3D device is free to copy more data than
- * specified. For example, it may round copy boxes outwards such
- * that they lie on particular alignment boundaries.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSurfaceDMA; /* SVGA_3D_CMD_SURFACE_DMA */
-
-/*
- * SVGA3dCmdSurfaceDMASuffix --
- *
- * This is a command suffix that will appear after a SurfaceDMA command in
- * the FIFO. It contains some extra information that hosts may use to
- * optimize performance or protect the guest. This suffix exists to preserve
- * backwards compatibility while also allowing for new functionality to be
- * implemented.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 suffixSize;
-
- /*
- * The maximum offset is used to determine the maximum offset from the
- * guestPtr base address that will be accessed or written to during this
- * surfaceDMA. If the suffix is supported, the host will respect this
- * boundary while performing surface DMAs.
- *
- * Defaults to MAX_UINT32
- */
- uint32 maximumOffset;
-
- /*
- * A set of flags that describes optimizations that the host may perform
- * while performing this surface DMA operation. The guest should never rely
- * on behaviour that is different when these flags are set for correctness.
- *
- * Defaults to 0
- */
- SVGA3dSurfaceDMAFlags flags;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSurfaceDMASuffix;
-
-/*
- * SVGA_3D_CMD_DRAW_PRIMITIVES --
- *
- * This command is the SVGA3D device's generic drawing entry point.
- * It can draw multiple ranges of primitives, optionally using an
- * index buffer, using an arbitrary collection of vertex buffers.
- *
- * Each SVGA3dVertexDecl defines a distinct vertex array to bind
- * during this draw call. The declarations specify which surface
- * the vertex data lives in, what that vertex data is used for,
- * and how to interpret it.
- *
- * Each SVGA3dPrimitiveRange defines a collection of primitives
- * to render using the same vertex arrays. An index buffer is
- * optional.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- /*
- * A range hint is an optional specification for the range of indices
- * in an SVGA3dArray that will be used. If 'last' is zero, it is assumed
- * that the entire array will be used.
- *
- * These are only hints. The SVGA3D device may use them for
- * performance optimization if possible, but it's also allowed to
- * ignore these values.
- */
- uint32 first;
- uint32 last;
-}
-#include "vmware_pack_end.h"
-SVGA3dArrayRangeHint;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- /*
- * Define the origin and shape of a vertex or index array. Both
- * 'offset' and 'stride' are in bytes. The provided surface will be
- * reinterpreted as a flat array of bytes in the same format used
- * by surface DMA operations. To avoid unnecessary conversions, the
- * surface should be created with the SVGA3D_BUFFER format.
- *
- * Index 0 in the array starts 'offset' bytes into the surface.
- * Index 1 begins at byte 'offset + stride', etc. Array indices may
- * not be negative.
- */
- uint32 surfaceId;
- uint32 offset;
- uint32 stride;
-}
-#include "vmware_pack_end.h"
-SVGA3dArray;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- /*
- * Describe a vertex array's data type, and define how it is to be
- * used by the fixed function pipeline or the vertex shader. It
- * isn't useful to have two VertexDecls with the same
- * VertexArrayIdentity in one draw call.
- */
- SVGA3dDeclType type;
- SVGA3dDeclMethod method;
- SVGA3dDeclUsage usage;
- uint32 usageIndex;
-}
-#include "vmware_pack_end.h"
-SVGA3dVertexArrayIdentity;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dVertexDecl {
- SVGA3dVertexArrayIdentity identity;
- SVGA3dArray array;
- SVGA3dArrayRangeHint rangeHint;
-}
-#include "vmware_pack_end.h"
-SVGA3dVertexDecl;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dPrimitiveRange {
- /*
- * Define a group of primitives to render, from sequential indices.
- *
- * The value of 'primitiveType' and 'primitiveCount' imply the
- * total number of vertices that will be rendered.
- */
- SVGA3dPrimitiveType primType;
- uint32 primitiveCount;
-
- /*
- * Optional index buffer. If indexArray.surfaceId is
- * SVGA3D_INVALID_ID, we render without an index buffer. Rendering
- * without an index buffer is identical to rendering with an index
- * buffer containing the sequence [0, 1, 2, 3, ...].
- *
- * If an index buffer is in use, indexWidth specifies the width in
- * bytes of each index value. It must be less than or equal to
- * indexArray.stride.
- *
- * (Currently, the SVGA3D device requires index buffers to be tightly
- * packed. In other words, indexWidth == indexArray.stride)
- */
- SVGA3dArray indexArray;
- uint32 indexWidth;
-
- /*
- * Optional index bias. This number is added to all indices from
- * indexArray before they are used as vertex array indices. This
- * can be used in multiple ways:
- *
- * - When not using an indexArray, this bias can be used to
- * specify where in the vertex arrays to begin rendering.
- *
- * - A positive number here is equivalent to increasing the
- * offset in each vertex array.
- *
- * - A negative number can be used to render using a small
- * vertex array and an index buffer that contains large
- * values. This may be used by some applications that
- * crop a vertex buffer without modifying their index
- * buffer.
- *
- * Note that rendering with a negative bias value may be slower and
- * use more memory than rendering with a positive or zero bias.
- */
- int32 indexBias;
-}
-#include "vmware_pack_end.h"
-SVGA3dPrimitiveRange;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 numVertexDecls;
- uint32 numRanges;
-
- /*
- * There are two variable size arrays after the
- * SVGA3dCmdDrawPrimitives structure. In order,
- * they are:
- *
- * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than
- * SVGA3D_MAX_VERTEX_ARRAYS;
- * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than
- * SVGA3D_MAX_DRAW_PRIMITIVE_RANGES;
- * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains
- * the frequency divisor for the corresponding vertex decl).
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDrawPrimitives; /* SVGA_3D_CMD_DRAWPRIMITIVES */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
-
- uint32 primitiveCount; /* How many primitives to render */
- uint32 startVertexLocation; /* Which vertex do we start rendering at. */
-
- uint8 primitiveType; /* SVGA3dPrimitiveType */
- uint8 padding[3];
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDraw;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
-
- uint8 primitiveType; /* SVGA3dPrimitiveType */
-
- uint32 indexBufferSid; /* Valid index buffer sid. */
- uint32 indexBufferOffset; /* Byte offset into the vertex buffer, almost */
- /* always 0 for pre SM guests, non-zero for OpenGL */
- /* guests. We can't represent non-multiple of */
- /* stride offsets in D3D9Renderer... */
- uint8 indexBufferStride; /* Allowable values = 1, 2, or 4 */
-
- int32 baseVertexLocation; /* Bias applied to the index when selecting a */
- /* vertex from the streams, may be negative */
-
- uint32 primitiveCount; /* How many primitives to render */
- uint32 pad0;
- uint16 pad1;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDrawIndexed;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- /*
- * Describe a vertex array's data type, and define how it is to be
- * used by the fixed function pipeline or the vertex shader. It
- * isn't useful to have two VertexDecls with the same
- * VertexArrayIdentity in one draw call.
- */
- uint16 streamOffset;
- uint8 stream;
- uint8 type; /* SVGA3dDeclType */
- uint8 method; /* SVGA3dDeclMethod */
- uint8 usage; /* SVGA3dDeclUsage */
- uint8 usageIndex;
- uint8 padding;
-
-}
-#include "vmware_pack_end.h"
-SVGA3dVertexElement;
-
-/*
- * Should the vertex element respect the stream value? The high bit of the
- * stream should be set to indicate that the stream should be respected. If
- * the high bit is not set, the stream will be ignored and replaced by the index
- * of the position of the currently considered vertex element.
- *
- * All guests should set this bit and correctly specify the stream going
- * forward.
- */
#define SVGA3D_VERTEX_ELEMENT_RESPECT_STREAM (1 << 7)
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
-
- uint32 numElements;
-
- /*
- * Followed by numElements SVGA3dVertexElement structures.
- *
- * If numElements < SVGA3D_MAX_VERTEX_ARRAYS, the remaining elements
- * are cleared and will not be used by following draws.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetVertexDecls;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
- uint32 stride;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGA3dVertexStream;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
-
- uint32 numStreams;
- /*
- * Followed by numStream SVGA3dVertexStream structures.
- *
- * If numStreams < SVGA3D_MAX_VERTEX_ARRAYS, the remaining streams
- * are cleared and will not be used by following draws.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetVertexStreams;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 numDivisors;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetVertexDivisors;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 stage;
- SVGA3dTextureStateName name;
- union {
- uint32 value;
- float floatValue;
- };
-}
-#include "vmware_pack_end.h"
-SVGA3dTextureState;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- /* Followed by variable number of SVGA3dTextureState structures */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetTextureState; /* SVGA_3D_CMD_SETTEXTURESTATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dTransformType type;
- float matrix[16];
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetTransform; /* SVGA_3D_CMD_SETTRANSFORM */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- float min;
- float max;
-}
-#include "vmware_pack_end.h"
-SVGA3dZRange;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dZRange zRange;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetZRange; /* SVGA_3D_CMD_SETZRANGE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- float diffuse[4];
- float ambient[4];
- float specular[4];
- float emissive[4];
- float shininess;
-}
-#include "vmware_pack_end.h"
-SVGA3dMaterial;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dFace face;
- SVGA3dMaterial material;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetMaterial; /* SVGA_3D_CMD_SETMATERIAL */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 index;
- SVGA3dLightData data;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetLightData; /* SVGA_3D_CMD_SETLIGHTDATA */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 index;
- uint32 enabled;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetLightEnabled; /* SVGA_3D_CMD_SETLIGHTENABLED */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dRect rect;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetViewport; /* SVGA_3D_CMD_SETVIEWPORT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dRect rect;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetScissorRect; /* SVGA_3D_CMD_SETSCISSORRECT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 index;
- float plane[4];
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetClipPlane; /* SVGA_3D_CMD_SETCLIPPLANE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 shid;
- SVGA3dShaderType type;
- /* Followed by variable number of DWORDs for shader bycode */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineShader; /* SVGA_3D_CMD_SHADER_DEFINE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 shid;
- SVGA3dShaderType type;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDestroyShader; /* SVGA_3D_CMD_SHADER_DESTROY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 reg; /* register number */
- SVGA3dShaderType type;
- SVGA3dShaderConstType ctype;
- uint32 values[4];
-
- /*
- * Followed by a variable number of additional values.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetShaderConst; /* SVGA_3D_CMD_SET_SHADER_CONST */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dShaderType type;
- uint32 shid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetShader; /* SVGA_3D_CMD_SET_SHADER */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dQueryType type;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdBeginQuery; /* SVGA_3D_CMD_BEGIN_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dQueryType type;
- SVGAGuestPtr guestResult; /* Points to an SVGA3dQueryResult structure */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdEndQuery; /* SVGA_3D_CMD_END_QUERY */
-
-
-/*
- * SVGA3D_CMD_WAIT_FOR_QUERY --
- *
- * Will read the SVGA3dQueryResult structure pointed to by guestResult,
- * and if the state member is set to anything else than
- * SVGA3D_QUERYSTATE_PENDING, this command will always be a no-op.
- *
- * Otherwise, in addition to the query explicitly waited for,
- * All queries with the same type and issued with the same cid, for which
- * an SVGA_3D_CMD_END_QUERY command has previously been sent, will
- * be finished after execution of this command.
- *
- * A query will be identified by the gmrId and offset of the guestResult
- * member. If the device can't find an SVGA_3D_CMD_END_QUERY that has
- * been sent previously with an indentical gmrId and offset, it will
- * effectively end all queries with an identical type issued with the
- * same cid, and the SVGA3dQueryResult structure pointed to by
- * guestResult will not be written to. This property can be used to
- * implement a query barrier for a given cid and query type.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid; /* Same parameters passed to END_QUERY */
- SVGA3dQueryType type;
- SVGAGuestPtr guestResult;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdWaitForQuery; /* SVGA_3D_CMD_WAIT_FOR_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 totalSize; /* Set by guest before query is ended. */
- SVGA3dQueryState state; /* Set by host or guest. See SVGA3dQueryState. */
- union { /* Set by host on exit from PENDING state */
- uint32 result32;
- uint32 queryCookie; /* May be used to identify which QueryGetData this
- result corresponds to. */
- };
-}
-#include "vmware_pack_end.h"
-SVGA3dQueryResult;
-
-
-/*
- * SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN --
- *
- * This is a blit from an SVGA3D surface to a Screen Object.
- * This blit must be directed at a specific screen.
- *
- * The blit copies from a rectangular region of an SVGA3D surface
- * image to a rectangular region of a screen.
- *
- * This command takes an optional variable-length list of clipping
- * rectangles after the body of the command. If no rectangles are
- * specified, there is no clipping region. The entire destRect is
- * drawn to. If one or more rectangles are included, they describe
- * a clipping region. The clip rectangle coordinates are measured
- * relative to the top-left corner of destRect.
- *
- * The srcImage must be from mip=0 face=0.
- *
- * This supports scaling if the src and dest are of different sizes.
- *
- * Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceImageId srcImage;
- SVGASignedRect srcRect;
- uint32 destScreenId; /* Screen Object ID */
- SVGASignedRect destRect;
- /* Clipping: zero or more SVGASignedRects follow */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdBlitSurfaceToScreen; /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
- SVGA3dTextureFilter filter;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdGenerateMipmaps; /* SVGA_3D_CMD_GENERATE_MIPMAPS */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdActivateSurface; /* SVGA_3D_CMD_ACTIVATE_SURFACE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDeactivateSurface; /* SVGA_3D_CMD_DEACTIVATE_SURFACE */
-
-/*
- * Screen DMA command
- *
- * Available with SVGA_FIFO_CAP_SCREEN_OBJECT_2. The SVGA_CAP_3D device
- * cap bit is not required.
- *
- * - refBuffer and destBuffer are 32bit BGRX; refBuffer and destBuffer could
- * be different, but it is required that guest makes sure refBuffer has
- * exactly the same contents that were written to when last time screen DMA
- * command is received by host.
- *
- * - changemap is generated by lib/blit, and it has the changes from last
- * received screen DMA or more.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdScreenDMA {
- uint32 screenId;
- SVGAGuestImage refBuffer;
- SVGAGuestImage destBuffer;
- SVGAGuestImage changeMap;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdScreenDMA; /* SVGA_3D_CMD_SCREEN_DMA */
-
-/*
- * Logic ops
- */
-
-#define SVGA3D_LOTRANSBLT_HONORALPHA (0x01)
-#define SVGA3D_LOSTRETCHBLT_MIRRORX (0x01)
-#define SVGA3D_LOSTRETCHBLT_MIRRORY (0x02)
-#define SVGA3D_LOALPHABLEND_SRCHASALPHA (0x01)
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdLogicOpsBitBlt {
- /*
- * All LogicOps surfaces are one-level
- * surfaces so mipmap & face should always
- * be zero.
- */
- SVGA3dSurfaceImageId src;
- SVGA3dSurfaceImageId dst;
- SVGA3dLogicOp logicOp;
- SVGA3dLogicOpRop3 logicOpRop3;
- /* Followed by variable number of SVGA3dCopyBox structures */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdLogicOpsBitBlt; /* SVGA_3D_CMD_LOGICOPS_BITBLT */
-
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdLogicOpsTransBlt {
- /*
- * All LogicOps surfaces are one-level
- * surfaces so mipmap & face should always
- * be zero.
- */
- SVGA3dSurfaceImageId src;
- SVGA3dSurfaceImageId dst;
- uint32 color;
- uint32 flags;
- SVGA3dBox srcBox;
- SVGA3dSignedBox dstBox;
- SVGA3dBox clipBox;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdLogicOpsTransBlt; /* SVGA_3D_CMD_LOGICOPS_TRANSBLT */
-
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdLogicOpsStretchBlt {
- /*
- * All LogicOps surfaces are one-level
- * surfaces so mipmap & face should always
- * be zero.
- */
- SVGA3dSurfaceImageId src;
- SVGA3dSurfaceImageId dst;
- uint16 mode;
- uint16 flags;
- SVGA3dBox srcBox;
- SVGA3dSignedBox dstBox;
- SVGA3dBox clipBox;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdLogicOpsStretchBlt; /* SVGA_3D_CMD_LOGICOPS_STRETCHBLT */
-
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdLogicOpsColorFill {
- /*
- * All LogicOps surfaces are one-level
- * surfaces so mipmap & face should always
- * be zero.
- */
- SVGA3dSurfaceImageId dst;
- uint32 color;
- SVGA3dLogicOp logicOp;
- SVGA3dLogicOpRop3 logicOpRop3;
- /* Followed by variable number of SVGA3dRect structures. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdLogicOpsColorFill; /* SVGA_3D_CMD_LOGICOPS_COLORFILL */
-
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdLogicOpsAlphaBlend {
- /*
- * All LogicOps surfaces are one-level
- * surfaces so mipmap & face should always
- * be zero.
- */
- SVGA3dSurfaceImageId src;
- SVGA3dSurfaceImageId dst;
- uint32 alphaVal;
- uint32 flags;
- SVGA3dBox srcBox;
- SVGA3dSignedBox dstBox;
- SVGA3dBox clipBox;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdLogicOpsAlphaBlend; /* SVGA_3D_CMD_LOGICOPS_ALPHABLEND */
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+
+ uint32 numElements;
+
+} SVGA3dCmdSetVertexDecls;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+ uint32 stride;
+ uint32 offset;
+} SVGA3dVertexStream;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+
+ uint32 numStreams;
+
+} SVGA3dCmdSetVertexStreams;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 numDivisors;
+} SVGA3dCmdSetVertexDivisors;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 stage;
+ SVGA3dTextureStateName name;
+ union {
+ uint32 value;
+ float floatValue;
+ };
+} SVGA3dTextureState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+
+} SVGA3dCmdSetTextureState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dTransformType type;
+ float matrix[16];
+} SVGA3dCmdSetTransform;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ float min;
+ float max;
+} SVGA3dZRange;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dZRange zRange;
+} SVGA3dCmdSetZRange;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ float diffuse[4];
+ float ambient[4];
+ float specular[4];
+ float emissive[4];
+ float shininess;
+} SVGA3dMaterial;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dFace face;
+ SVGA3dMaterial material;
+} SVGA3dCmdSetMaterial;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 index;
+ SVGA3dLightData data;
+} SVGA3dCmdSetLightData;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 index;
+ uint32 enabled;
+} SVGA3dCmdSetLightEnabled;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dRect rect;
+} SVGA3dCmdSetViewport;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dRect rect;
+} SVGA3dCmdSetScissorRect;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 index;
+ float plane[4];
+} SVGA3dCmdSetClipPlane;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 shid;
+ SVGA3dShaderType type;
+
+} SVGA3dCmdDefineShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 shid;
+ SVGA3dShaderType type;
+} SVGA3dCmdDestroyShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 reg;
+ SVGA3dShaderType type;
+ SVGA3dShaderConstType ctype;
+ uint32 values[4];
+
+} SVGA3dCmdSetShaderConst;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dShaderType type;
+ uint32 shid;
+} SVGA3dCmdSetShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dQueryType type;
+} SVGA3dCmdBeginQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dQueryType type;
+ SVGAGuestPtr guestResult;
+} SVGA3dCmdEndQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dQueryType type;
+ SVGAGuestPtr guestResult;
+} SVGA3dCmdWaitForQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 totalSize;
+ SVGA3dQueryState state;
+ union {
+ uint32 result32;
+ uint32 queryCookie;
+ };
+} SVGA3dQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceImageId srcImage;
+ SVGASignedRect srcRect;
+ uint32 destScreenId;
+ SVGASignedRect destRect;
+
+} SVGA3dCmdBlitSurfaceToScreen;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+ SVGA3dTextureFilter filter;
+} SVGA3dCmdGenerateMipmaps;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+} SVGA3dCmdActivateSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+} SVGA3dCmdDeactivateSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdScreenDMA {
+ uint32 screenId;
+ SVGAGuestImage refBuffer;
+ SVGAGuestImage destBuffer;
+ SVGAGuestImage changeMap;
+} SVGA3dCmdScreenDMA;
+#pragma pack(pop)
+
+#define SVGA3D_LOTRANSBLT_HONORALPHA (0x01)
+#define SVGA3D_LOSTRETCHBLT_MIRRORX (0x01)
+#define SVGA3D_LOSTRETCHBLT_MIRRORY (0x02)
+#define SVGA3D_LOALPHABLEND_SRCHASALPHA (0x01)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdLogicOpsBitBlt {
+ SVGA3dSurfaceImageId src;
+ SVGA3dSurfaceImageId dst;
+ SVGA3dLogicOp logicOp;
+ SVGA3dLogicOpRop3 logicOpRop3;
+
+} SVGA3dCmdLogicOpsBitBlt;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdLogicOpsTransBlt {
+ SVGA3dSurfaceImageId src;
+ SVGA3dSurfaceImageId dst;
+ uint32 color;
+ uint32 flags;
+ SVGA3dBox srcBox;
+ SVGA3dSignedBox dstBox;
+ SVGA3dBox clipBox;
+} SVGA3dCmdLogicOpsTransBlt;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdLogicOpsStretchBlt {
+ SVGA3dSurfaceImageId src;
+ SVGA3dSurfaceImageId dst;
+ uint16 mode;
+ uint16 flags;
+ SVGA3dBox srcBox;
+ SVGA3dSignedBox dstBox;
+ SVGA3dBox clipBox;
+} SVGA3dCmdLogicOpsStretchBlt;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdLogicOpsColorFill {
+ SVGA3dSurfaceImageId dst;
+ uint32 color;
+ SVGA3dLogicOp logicOp;
+ SVGA3dLogicOpRop3 logicOpRop3;
+
+} SVGA3dCmdLogicOpsColorFill;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdLogicOpsAlphaBlend {
+ SVGA3dSurfaceImageId src;
+ SVGA3dSurfaceImageId dst;
+ uint32 alphaVal;
+ uint32 flags;
+ SVGA3dBox srcBox;
+ SVGA3dSignedBox dstBox;
+ SVGA3dBox clipBox;
+} SVGA3dCmdLogicOpsAlphaBlend;
+#pragma pack(pop)
#define SVGA3D_CLEARTYPE_INVALID_GAMMA_INDEX 0xFFFFFFFF
-#define SVGA3D_CLEARTYPE_GAMMA_WIDTH 512
+#define SVGA3D_CLEARTYPE_GAMMA_WIDTH 512
#define SVGA3D_CLEARTYPE_GAMMA_HEIGHT 16
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdLogicOpsClearTypeBlend {
- /*
- * All LogicOps surfaces are one-level
- * surfaces so mipmap & face should always
- * be zero.
- */
- SVGA3dSurfaceImageId tmp;
- SVGA3dSurfaceImageId dst;
- SVGA3dSurfaceImageId gammaSurf;
- SVGA3dSurfaceImageId alphaSurf;
- uint32 gamma;
- uint32 color;
- uint32 color2;
- int32 alphaOffsetX;
- int32 alphaOffsetY;
- /* Followed by variable number of SVGA3dBox structures */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdLogicOpsClearTypeBlend; /* SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND */
-
-
-/*
- * Guest-backed objects definitions.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAMobFormat ptDepth;
- uint32 sizeInBytes;
- PPN64 base;
-}
-#include "vmware_pack_end.h"
-SVGAOTableMobEntry;
-#define SVGA3D_OTABLE_MOB_ENTRY_SIZE (sizeof(SVGAOTableMobEntry))
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceFormat format;
- SVGA3dSurface1Flags surface1Flags;
- uint32 numMipLevels;
- uint32 multisampleCount;
- SVGA3dTextureFilter autogenFilter;
- SVGA3dSize size;
- SVGAMobId mobid;
- uint32 arraySize;
- uint32 mobPitch;
- SVGA3dSurface2Flags surface2Flags;
- uint8 multisamplePattern;
- uint8 qualityLevel;
- uint16 bufferByteStride;
- float minLOD;
- uint32 pad0[2];
-}
-#include "vmware_pack_end.h"
-SVGAOTableSurfaceEntry;
-#define SVGA3D_OTABLE_SURFACE_ENTRY_SIZE (sizeof(SVGAOTableSurfaceEntry))
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGAOTableContextEntry;
-#define SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE (sizeof(SVGAOTableContextEntry))
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dShaderType type;
- uint32 sizeInBytes;
- uint32 offsetInBytes;
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGAOTableShaderEntry;
-#define SVGA3D_OTABLE_SHADER_ENTRY_SIZE (sizeof(SVGAOTableShaderEntry))
-
-#define SVGA_STFLAG_PRIMARY (1 << 0)
-#define SVGA_STFLAG_RESERVED (1 << 1) /* Added with cap SVGA_CAP_HP_CMD_QUEUE */
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdLogicOpsClearTypeBlend {
+ SVGA3dSurfaceImageId tmp;
+ SVGA3dSurfaceImageId dst;
+ SVGA3dSurfaceImageId gammaSurf;
+ SVGA3dSurfaceImageId alphaSurf;
+ uint32 gamma;
+ uint32 color;
+ uint32 color2;
+ int32 alphaOffsetX;
+ int32 alphaOffsetY;
+
+} SVGA3dCmdLogicOpsClearTypeBlend;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAMobFormat ptDepth;
+ uint32 sizeInBytes;
+ PPN64 base;
+} SVGAOTableMobEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceFormat format;
+ SVGA3dSurface1Flags surface1Flags;
+ uint32 numMipLevels;
+ uint32 multisampleCount;
+ SVGA3dTextureFilter autogenFilter;
+ SVGA3dSize size;
+ SVGAMobId mobid;
+ uint32 arraySize;
+ uint32 mobPitch;
+ SVGA3dSurface2Flags surface2Flags;
+ uint8 multisamplePattern;
+ uint8 qualityLevel;
+ uint16 bufferByteStride;
+ float minLOD;
+ uint32 pad0[2];
+} SVGAOTableSurfaceEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGAMobId mobid;
+} SVGAOTableContextEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dShaderType type;
+ uint32 sizeInBytes;
+ uint32 offsetInBytes;
+ SVGAMobId mobid;
+} SVGAOTableShaderEntry;
+#pragma pack(pop)
+
+#define SVGA_STFLAG_PRIMARY (1 << 0)
+#define SVGA_STFLAG_RESERVED (1 << 1)
typedef uint32 SVGAScreenTargetFlags;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceImageId image;
- uint32 width;
- uint32 height;
- int32 xRoot;
- int32 yRoot;
- SVGAScreenTargetFlags flags;
- uint32 dpi;
- uint32 pad[7];
-}
-#include "vmware_pack_end.h"
-SVGAOTableScreenTargetEntry;
-#define SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE \
- (sizeof(SVGAOTableScreenTargetEntry))
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- float value[4];
-}
-#include "vmware_pack_end.h"
-SVGA3dShaderConstFloat;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- int32 value[4];
-}
-#include "vmware_pack_end.h"
-SVGA3dShaderConstInt;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 value;
-}
-#include "vmware_pack_end.h"
-SVGA3dShaderConstBool;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint16 streamOffset;
- uint8 stream;
- uint8 type;
- uint8 methodUsage;
- uint8 usageIndex;
-}
-#include "vmware_pack_end.h"
-SVGAGBVertexElement;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
- uint16 stride;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGAGBVertexStream;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dRect viewport;
- SVGA3dRect scissorRect;
- SVGA3dZRange zRange;
-
- SVGA3dSurfaceImageId renderTargets[SVGA3D_RT_MAX];
- SVGAGBVertexElement decl1[4];
-
- uint32 renderStates[SVGA3D_RS_MAX];
- SVGAGBVertexElement decl2[18];
- uint32 pad0[2];
-
- struct {
- SVGA3dFace face;
- SVGA3dMaterial material;
- } material;
-
- float clipPlanes[SVGA3D_NUM_CLIPPLANES][4];
- float matrices[SVGA3D_TRANSFORM_MAX][16];
-
- SVGA3dBool lightEnabled[SVGA3D_NUM_LIGHTS];
- SVGA3dLightData lightData[SVGA3D_NUM_LIGHTS];
-
- /*
- * Shaders currently bound
- */
- uint32 shaders[SVGA3D_NUM_SHADERTYPE_PREDX];
- SVGAGBVertexElement decl3[10];
- uint32 pad1[3];
-
- uint32 occQueryActive;
- uint32 occQueryValue;
-
- /*
- * Int/Bool Shader constants
- */
- SVGA3dShaderConstInt pShaderIValues[SVGA3D_CONSTINTREG_MAX];
- SVGA3dShaderConstInt vShaderIValues[SVGA3D_CONSTINTREG_MAX];
- uint16 pShaderBValues;
- uint16 vShaderBValues;
-
-
- SVGAGBVertexStream streams[SVGA3D_MAX_VERTEX_ARRAYS];
- SVGA3dVertexDivisor divisors[SVGA3D_MAX_VERTEX_ARRAYS];
- uint32 numVertexDecls;
- uint32 numVertexStreams;
- uint32 numVertexDivisors;
- uint32 pad2[30];
-
- /*
- * Texture Stages
- *
- * SVGA3D_TS_INVALID through SVGA3D_TS_CONSTANT are in the
- * textureStages array.
- * SVGA3D_TS_COLOR_KEY is in tsColorKey.
- */
- uint32 tsColorKey[SVGA3D_NUM_TEXTURE_UNITS];
- uint32 textureStages[SVGA3D_NUM_TEXTURE_UNITS][SVGA3D_TS_CONSTANT + 1];
- uint32 tsColorKeyEnable[SVGA3D_NUM_TEXTURE_UNITS];
-
- /*
- * Float Shader constants.
- */
- SVGA3dShaderConstFloat pShaderFValues[SVGA3D_CONSTREG_MAX];
- SVGA3dShaderConstFloat vShaderFValues[SVGA3D_CONSTREG_MAX];
-}
-#include "vmware_pack_end.h"
-SVGAGBContextData;
-#define SVGA3D_CONTEXT_DATA_SIZE (sizeof(SVGAGBContextData))
-
-/*
- * SVGA3dCmdSetOTableBase --
- *
- * This command allows the guest to specify the base PPN of the
- * specified object table.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAOTableType type;
- PPN32 baseAddress;
- uint32 sizeInBytes;
- uint32 validSizeInBytes;
- SVGAMobFormat ptDepth;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetOTableBase; /* SVGA_3D_CMD_SET_OTABLE_BASE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAOTableType type;
- PPN64 baseAddress;
- uint32 sizeInBytes;
- uint32 validSizeInBytes;
- SVGAMobFormat ptDepth;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetOTableBase64; /* SVGA_3D_CMD_SET_OTABLE_BASE64 */
-
-/*
- * Guests using SVGA_3D_CMD_GROW_OTABLE are promising that
- * the new OTable contains the same contents as the old one, except possibly
- * for some new invalid entries at the end.
- *
- * (Otherwise, guests should use one of the SetOTableBase commands.)
- */
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAOTableType type;
- PPN64 baseAddress;
- uint32 sizeInBytes;
- uint32 validSizeInBytes;
- SVGAMobFormat ptDepth;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdGrowOTable; /* SVGA_3D_CMD_GROW_OTABLE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAOTableType type;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdReadbackOTable; /* SVGA_3D_CMD_READBACK_OTABLE */
-
-/*
- * Define a memory object (Mob) in the OTable.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDefineGBMob {
- SVGAMobId mobid;
- SVGAMobFormat ptDepth;
- PPN32 base;
- uint32 sizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBMob; /* SVGA_3D_CMD_DEFINE_GB_MOB */
-
-
-/*
- * Destroys an object in the OTable.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDestroyGBMob {
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDestroyGBMob; /* SVGA_3D_CMD_DESTROY_GB_MOB */
-
-/*
- * Define a memory object (Mob) in the OTable with a PPN64 base.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDefineGBMob64 {
- SVGAMobId mobid;
- SVGAMobFormat ptDepth;
- PPN64 base;
- uint32 sizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBMob64; /* SVGA_3D_CMD_DEFINE_GB_MOB64 */
-
-/*
- * Redefine an object in the OTable with PPN64 base.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdRedefineGBMob64 {
- SVGAMobId mobid;
- SVGAMobFormat ptDepth;
- PPN64 base;
- uint32 sizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdRedefineGBMob64; /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */
-
-/*
- * Notification that the page tables have been modified.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdUpdateGBMobMapping {
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdUpdateGBMobMapping; /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */
-
-/*
- * Define a guest-backed surface.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDefineGBSurface {
- uint32 sid;
- SVGA3dSurface1Flags surfaceFlags;
- SVGA3dSurfaceFormat format;
- uint32 numMipLevels;
- uint32 multisampleCount;
- SVGA3dTextureFilter autogenFilter;
- SVGA3dSize size;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBSurface; /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
-
-/*
- * Defines a guest-backed surface, adding the arraySize field.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDefineGBSurface_v2 {
- uint32 sid;
- SVGA3dSurface1Flags surfaceFlags;
- SVGA3dSurfaceFormat format;
- uint32 numMipLevels;
- uint32 multisampleCount;
- SVGA3dTextureFilter autogenFilter;
- SVGA3dSize size;
- uint32 arraySize;
- uint32 pad;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBSurface_v2; /* SVGA_3D_CMD_DEFINE_GB_SURFACE_V2 */
-
-/*
- * Defines a guest-backed surface, adding the larger flags.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDefineGBSurface_v3 {
- uint32 sid;
- SVGA3dSurfaceAllFlags surfaceFlags;
- SVGA3dSurfaceFormat format;
- uint32 numMipLevels;
- uint32 multisampleCount;
- SVGA3dMSPattern multisamplePattern;
- SVGA3dMSQualityLevel qualityLevel;
- SVGA3dTextureFilter autogenFilter;
- SVGA3dSize size;
- uint32 arraySize;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBSurface_v3; /* SVGA_3D_CMD_DEFINE_GB_SURFACE_V3 */
-
-/*
- * Defines a guest-backed surface, adding buffer byte stride.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDefineGBSurface_v4 {
- uint32 sid;
- SVGA3dSurfaceAllFlags surfaceFlags;
- SVGA3dSurfaceFormat format;
- uint32 numMipLevels;
- uint32 multisampleCount;
- SVGA3dMSPattern multisamplePattern;
- SVGA3dMSQualityLevel qualityLevel;
- SVGA3dTextureFilter autogenFilter;
- SVGA3dSize size;
- uint32 arraySize;
- uint32 bufferByteStride;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBSurface_v4; /* SVGA_3D_CMD_DEFINE_GB_SURFACE_V4 */
-
-/*
- * Destroy a guest-backed surface.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDestroyGBSurface {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDestroyGBSurface; /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
-
-/*
- * Bind a guest-backed surface to a mob.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdBindGBSurface {
- uint32 sid;
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdBindGBSurface; /* SVGA_3D_CMD_BIND_GB_SURFACE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdBindGBSurfaceWithPitch {
- uint32 sid;
- SVGAMobId mobid;
- uint32 baseLevelPitch;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdBindGBSurfaceWithPitch; /* SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH */
-
-/*
- * Conditionally bind a mob to a guest-backed surface if testMobid
- * matches the currently bound mob. Optionally issue a
- * readback/update on the surface while it is still bound to the old
- * mobid if the mobid is changed by this command.
- */
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceImageId image;
+ uint32 width;
+ uint32 height;
+ int32 xRoot;
+ int32 yRoot;
+ SVGAScreenTargetFlags flags;
+ uint32 dpi;
+ uint32 pad[7];
+} SVGAOTableScreenTargetEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ float value[4];
+} SVGA3dShaderConstFloat;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ int32 value[4];
+} SVGA3dShaderConstInt;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 value;
+} SVGA3dShaderConstBool;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint16 streamOffset;
+ uint8 stream;
+ uint8 type;
+ uint8 methodUsage;
+ uint8 usageIndex;
+} SVGAGBVertexElement;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+ uint16 stride;
+ uint32 offset;
+} SVGAGBVertexStream;
+#pragma pack(pop)
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dRect viewport;
+ SVGA3dRect scissorRect;
+ SVGA3dZRange zRange;
+
+ SVGA3dSurfaceImageId renderTargets[SVGA3D_RT_MAX];
+ SVGAGBVertexElement decl1[4];
+
+ uint32 renderStates[SVGA3D_RS_MAX];
+ SVGAGBVertexElement decl2[18];
+ uint32 pad0[2];
+
+ struct {
+ SVGA3dFace face;
+ SVGA3dMaterial material;
+ } material;
+
+ float clipPlanes[SVGA3D_MAX_CLIP_PLANES][4];
+ float matrices[SVGA3D_TRANSFORM_MAX][16];
+
+ SVGA3dBool lightEnabled[SVGA3D_NUM_LIGHTS];
+ SVGA3dLightData lightData[SVGA3D_NUM_LIGHTS];
+
+ uint32 shaders[SVGA3D_NUM_SHADERTYPE_PREDX];
+ SVGAGBVertexElement decl3[10];
+ uint32 pad1[3];
+
+ uint32 occQueryActive;
+ uint32 occQueryValue;
+
+ SVGA3dShaderConstInt pShaderIValues[SVGA3D_CONSTINTREG_MAX];
+ SVGA3dShaderConstInt vShaderIValues[SVGA3D_CONSTINTREG_MAX];
+ uint16 pShaderBValues;
+ uint16 vShaderBValues;
+
+ SVGAGBVertexStream streams[SVGA3D_MAX_VERTEX_ARRAYS];
+ SVGA3dVertexDivisor divisors[SVGA3D_MAX_VERTEX_ARRAYS];
+ uint32 numVertexDecls;
+ uint32 numVertexStreams;
+ uint32 numVertexDivisors;
+ uint32 pad2[30];
+
+ uint32 tsColorKey[SVGA3D_NUM_TEXTURE_UNITS];
+ uint32 textureStages[SVGA3D_NUM_TEXTURE_UNITS][SVGA3D_TS_CONSTANT + 1];
+ uint32 tsColorKeyEnable[SVGA3D_NUM_TEXTURE_UNITS];
+
+ SVGA3dShaderConstFloat pShaderFValues[SVGA3D_CONSTREG_MAX];
+ SVGA3dShaderConstFloat vShaderFValues[SVGA3D_CONSTREG_MAX];
+} SVGAGBContextData;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAOTableType type;
+ PPN32 baseAddress;
+ uint32 sizeInBytes;
+ uint32 validSizeInBytes;
+ SVGAMobFormat ptDepth;
+} SVGA3dCmdSetOTableBase;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAOTableType type;
+ PPN64 baseAddress;
+ uint32 sizeInBytes;
+ uint32 validSizeInBytes;
+ SVGAMobFormat ptDepth;
+} SVGA3dCmdSetOTableBase64;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAOTableType type;
+ PPN64 baseAddress;
+ uint32 sizeInBytes;
+ uint32 validSizeInBytes;
+ SVGAMobFormat ptDepth;
+} SVGA3dCmdGrowOTable;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAOTableType type;
+} SVGA3dCmdReadbackOTable;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDefineGBMob {
+ SVGAMobId mobid;
+ SVGAMobFormat ptDepth;
+ PPN32 base;
+ uint32 sizeInBytes;
+} SVGA3dCmdDefineGBMob;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDestroyGBMob {
+ SVGAMobId mobid;
+} SVGA3dCmdDestroyGBMob;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDefineGBMob64 {
+ SVGAMobId mobid;
+ SVGAMobFormat ptDepth;
+ PPN64 base;
+ uint32 sizeInBytes;
+} SVGA3dCmdDefineGBMob64;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdRedefineGBMob64 {
+ SVGAMobId mobid;
+ SVGAMobFormat ptDepth;
+ PPN64 base;
+ uint32 sizeInBytes;
+} SVGA3dCmdRedefineGBMob64;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdUpdateGBMobMapping {
+ SVGAMobId mobid;
+} SVGA3dCmdUpdateGBMobMapping;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDefineGBSurface {
+ uint32 sid;
+ SVGA3dSurface1Flags surfaceFlags;
+ SVGA3dSurfaceFormat format;
+ uint32 numMipLevels;
+ uint32 multisampleCount;
+ SVGA3dTextureFilter autogenFilter;
+ SVGA3dSize size;
+} SVGA3dCmdDefineGBSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDefineGBSurface_v2 {
+ uint32 sid;
+ SVGA3dSurface1Flags surfaceFlags;
+ SVGA3dSurfaceFormat format;
+ uint32 numMipLevels;
+ uint32 multisampleCount;
+ SVGA3dTextureFilter autogenFilter;
+ SVGA3dSize size;
+ uint32 arraySize;
+ uint32 pad;
+} SVGA3dCmdDefineGBSurface_v2;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDefineGBSurface_v3 {
+ uint32 sid;
+ SVGA3dSurfaceAllFlags surfaceFlags;
+ SVGA3dSurfaceFormat format;
+ uint32 numMipLevels;
+ uint32 multisampleCount;
+ SVGA3dMSPattern multisamplePattern;
+ SVGA3dMSQualityLevel qualityLevel;
+ SVGA3dTextureFilter autogenFilter;
+ SVGA3dSize size;
+ uint32 arraySize;
+} SVGA3dCmdDefineGBSurface_v3;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDefineGBSurface_v4 {
+ uint32 sid;
+ SVGA3dSurfaceAllFlags surfaceFlags;
+ SVGA3dSurfaceFormat format;
+ uint32 numMipLevels;
+ uint32 multisampleCount;
+ SVGA3dMSPattern multisamplePattern;
+ SVGA3dMSQualityLevel qualityLevel;
+ SVGA3dTextureFilter autogenFilter;
+ SVGA3dSize size;
+ uint32 arraySize;
+ uint32 bufferByteStride;
+} SVGA3dCmdDefineGBSurface_v4;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDestroyGBSurface {
+ uint32 sid;
+} SVGA3dCmdDestroyGBSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdBindGBSurface {
+ uint32 sid;
+ SVGAMobId mobid;
+} SVGA3dCmdBindGBSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdBindGBSurfaceWithPitch {
+ uint32 sid;
+ SVGAMobId mobid;
+ uint32 baseLevelPitch;
+} SVGA3dCmdBindGBSurfaceWithPitch;
+#pragma pack(pop)
#define SVGA3D_COND_BIND_GB_SURFACE_FLAG_READBACK (1 << 0)
-#define SVGA3D_COND_BIND_GB_SURFACE_FLAG_UPDATE (1 << 1)
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdCondBindGBSurface {
- uint32 sid;
- SVGAMobId testMobid;
- SVGAMobId mobid;
- uint32 flags;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdCondBindGBSurface; /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */
-
-/*
- * Update an image in a guest-backed surface.
- * (Inform the device that the guest-contents have been updated.)
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdUpdateGBImage {
- SVGA3dSurfaceImageId image;
- SVGA3dBox box;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdUpdateGBImage; /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
-
-/*
- * Update an entire guest-backed surface.
- * (Inform the device that the guest-contents have been updated.)
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdUpdateGBSurface {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdUpdateGBSurface; /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
-
-/*
- * Readback an image in a guest-backed surface.
- * (Request the device to flush the dirty contents into the guest.)
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdReadbackGBImage {
- SVGA3dSurfaceImageId image;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdReadbackGBImage; /* SVGA_3D_CMD_READBACK_GB_IMAGE */
-
-/*
- * Readback an entire guest-backed surface.
- * (Request the device to flush the dirty contents into the guest.)
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdReadbackGBSurface {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdReadbackGBSurface; /* SVGA_3D_CMD_READBACK_GB_SURFACE */
-
-/*
- * Readback a sub rect of an image in a guest-backed surface. After
- * issuing this command the driver is required to issue an update call
- * of the same region before issuing any other commands that reference
- * this surface or rendering is not guaranteed.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdReadbackGBImagePartial {
- SVGA3dSurfaceImageId image;
- SVGA3dBox box;
- uint32 invertBox;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */
-
-
-/*
- * Invalidate an image in a guest-backed surface.
- * (Notify the device that the contents can be lost.)
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdInvalidateGBImage {
- SVGA3dSurfaceImageId image;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdInvalidateGBImage; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
-
-/*
- * Invalidate an entire guest-backed surface.
- * (Notify the device that the contents if all images can be lost.)
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdInvalidateGBSurface {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
-
-/*
- * Invalidate a sub rect of an image in a guest-backed surface. After
- * issuing this command the driver is required to issue an update call
- * of the same region before issuing any other commands that reference
- * this surface or rendering is not guaranteed.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdInvalidateGBImagePartial {
- SVGA3dSurfaceImageId image;
- SVGA3dBox box;
- uint32 invertBox;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */
-
-
-/*
- * Define a guest-backed context.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDefineGBContext {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBContext; /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
-
-/*
- * Destroy a guest-backed context.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDestroyGBContext {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDestroyGBContext; /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
-
-/*
- * Bind a guest-backed context.
- *
- * validContents should be set to 0 for new contexts,
- * and 1 if this is an old context which is getting paged
- * back on to the device.
- *
- * For new contexts, it is recommended that the driver
- * issue commands to initialize all interesting state
- * prior to rendering.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdBindGBContext {
- uint32 cid;
- SVGAMobId mobid;
- uint32 validContents;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdBindGBContext; /* SVGA_3D_CMD_BIND_GB_CONTEXT */
-
-/*
- * Readback a guest-backed context.
- * (Request that the device flush the contents back into guest memory.)
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdReadbackGBContext {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdReadbackGBContext; /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
-
-/*
- * Invalidate a guest-backed context.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdInvalidateGBContext {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdInvalidateGBContext; /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
-
-/*
- * Define a guest-backed shader.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDefineGBShader {
- uint32 shid;
- SVGA3dShaderType type;
- uint32 sizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBShader; /* SVGA_3D_CMD_DEFINE_GB_SHADER */
-
-/*
- * Bind a guest-backed shader.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdBindGBShader {
- uint32 shid;
- SVGAMobId mobid;
- uint32 offsetInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdBindGBShader; /* SVGA_3D_CMD_BIND_GB_SHADER */
-
-/*
- * Destroy a guest-backed shader.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDestroyGBShader {
- uint32 shid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDestroyGBShader; /* SVGA_3D_CMD_DESTROY_GB_SHADER */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- uint32 regStart;
- SVGA3dShaderType shaderType;
- SVGA3dShaderConstType constType;
-
- /*
- * Followed by a variable number of shader constants.
- *
- * Note that FLOAT and INT constants are 4-dwords in length, while
- * BOOL constants are 1-dword in length.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdSetGBShaderConstInline; /* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */
-
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dQueryType type;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdBeginGBQuery; /* SVGA_3D_CMD_BEGIN_GB_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dQueryType type;
- SVGAMobId mobid;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdEndGBQuery; /* SVGA_3D_CMD_END_GB_QUERY */
-
-
-/*
- * SVGA_3D_CMD_WAIT_FOR_GB_QUERY --
- *
- * The semantics of this command are identical to the
- * SVGA_3D_CMD_WAIT_FOR_QUERY except that the results are written
- * to a Mob instead of a GMR.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGA3dQueryType type;
- SVGAMobId mobid;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdWaitForGBQuery; /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
-
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAMobId mobid;
- uint32 mustBeZero;
- uint32 initialized;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdEnableGart; /* SVGA_3D_CMD_ENABLE_GART */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAMobId mobid;
- uint32 gartOffset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdMapMobIntoGart; /* SVGA_3D_CMD_MAP_MOB_INTO_GART */
-
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 gartOffset;
- uint32 numPages;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdUnmapGartRange; /* SVGA_3D_CMD_UNMAP_GART_RANGE */
-
-
-/*
- * Screen Targets
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 stid;
- uint32 width;
- uint32 height;
- int32 xRoot;
- int32 yRoot;
- SVGAScreenTargetFlags flags;
-
- /*
- * The physical DPI that the guest expects this screen displayed at.
- *
- * Guests which are not DPI-aware should set this to zero.
- */
- uint32 dpi;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDefineGBScreenTarget; /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 stid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDestroyGBScreenTarget; /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 stid;
- SVGA3dSurfaceImageId image;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdBindGBScreenTarget; /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 stid;
- SVGA3dRect rect;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdUpdateGBScreenTarget; /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdGBScreenDMA {
- uint32 screenId;
- uint32 dead;
- SVGAMobId destMobID;
- uint32 destPitch;
- SVGAMobId changeMapMobID;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdGBScreenDMA; /* SVGA_3D_CMD_GB_SCREEN_DMA */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 value;
- uint32 mobId;
- uint32 mobOffset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdGBMobFence; /* SVGA_3D_CMD_GB_MOB_FENCE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 stid;
- SVGA3dSurfaceImageId dest;
-
- uint32 statusMobId;
- uint32 statusMobOffset;
-
- /* Reserved fields */
- uint32 mustBeInvalidId;
- uint32 mustBeZero;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdScreenCopy; /* SVGA_3D_CMD_SCREEN_COPY */
+#define SVGA3D_COND_BIND_GB_SURFACE_FLAG_UPDATE (1 << 1)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdCondBindGBSurface {
+ uint32 sid;
+ SVGAMobId testMobid;
+ SVGAMobId mobid;
+ uint32 flags;
+} SVGA3dCmdCondBindGBSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdUpdateGBImage {
+ SVGA3dSurfaceImageId image;
+ SVGA3dBox box;
+} SVGA3dCmdUpdateGBImage;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdUpdateGBSurface {
+ uint32 sid;
+} SVGA3dCmdUpdateGBSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdReadbackGBImage {
+ SVGA3dSurfaceImageId image;
+} SVGA3dCmdReadbackGBImage;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdReadbackGBSurface {
+ uint32 sid;
+} SVGA3dCmdReadbackGBSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdReadbackGBImagePartial {
+ SVGA3dSurfaceImageId image;
+ SVGA3dBox box;
+ uint32 invertBox;
+} SVGA3dCmdReadbackGBImagePartial;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdInvalidateGBImage {
+ SVGA3dSurfaceImageId image;
+} SVGA3dCmdInvalidateGBImage;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdInvalidateGBSurface {
+ uint32 sid;
+} SVGA3dCmdInvalidateGBSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdInvalidateGBImagePartial {
+ SVGA3dSurfaceImageId image;
+ SVGA3dBox box;
+ uint32 invertBox;
+} SVGA3dCmdInvalidateGBImagePartial;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDefineGBContext {
+ uint32 cid;
+} SVGA3dCmdDefineGBContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDestroyGBContext {
+ uint32 cid;
+} SVGA3dCmdDestroyGBContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdBindGBContext {
+ uint32 cid;
+ SVGAMobId mobid;
+ uint32 validContents;
+} SVGA3dCmdBindGBContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdReadbackGBContext {
+ uint32 cid;
+} SVGA3dCmdReadbackGBContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdInvalidateGBContext {
+ uint32 cid;
+} SVGA3dCmdInvalidateGBContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDefineGBShader {
+ uint32 shid;
+ SVGA3dShaderType type;
+ uint32 sizeInBytes;
+} SVGA3dCmdDefineGBShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdBindGBShader {
+ uint32 shid;
+ SVGAMobId mobid;
+ uint32 offsetInBytes;
+} SVGA3dCmdBindGBShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDestroyGBShader {
+ uint32 shid;
+} SVGA3dCmdDestroyGBShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ uint32 regStart;
+ SVGA3dShaderType shaderType;
+ SVGA3dShaderConstType constType;
+
+} SVGA3dCmdSetGBShaderConstInline;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dQueryType type;
+} SVGA3dCmdBeginGBQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dQueryType type;
+ SVGAMobId mobid;
+ uint32 offset;
+} SVGA3dCmdEndGBQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGA3dQueryType type;
+ SVGAMobId mobid;
+ uint32 offset;
+} SVGA3dCmdWaitForGBQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAMobId mobid;
+ uint32 mustBeZero;
+ uint32 initialized;
+} SVGA3dCmdEnableGart;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAMobId mobid;
+ uint32 gartOffset;
+} SVGA3dCmdMapMobIntoGart;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 gartOffset;
+ uint32 numPages;
+} SVGA3dCmdUnmapGartRange;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 stid;
+ uint32 width;
+ uint32 height;
+ int32 xRoot;
+ int32 yRoot;
+ SVGAScreenTargetFlags flags;
+
+ uint32 dpi;
+} SVGA3dCmdDefineGBScreenTarget;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 stid;
+} SVGA3dCmdDestroyGBScreenTarget;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 stid;
+ SVGA3dSurfaceImageId image;
+} SVGA3dCmdBindGBScreenTarget;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 stid;
+ SVGA3dRect rect;
+} SVGA3dCmdUpdateGBScreenTarget;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 stid;
+ SVGA3dRect rect;
+ SVGA3dFrameUpdateType type;
+} SVGA3dCmdUpdateGBScreenTarget_v2;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 stid;
+ SVGA3dRect rect;
+ SVGA3dFrameUpdateType type;
+ SVGAUnsignedPoint srcPoint;
+} SVGA3dCmdUpdateGBScreenTargetMove;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdGBScreenDMA {
+ uint32 screenId;
+ uint32 dead;
+ SVGAMobId destMobID;
+ uint32 destPitch;
+ SVGAMobId changeMapMobID;
+} SVGA3dCmdGBScreenDMA;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 value;
+ uint32 mobId;
+ uint32 mobOffset;
+} SVGA3dCmdGBMobFence;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 stid;
+ SVGA3dSurfaceImageId dest;
+
+ uint32 statusMobId;
+ uint32 statusMobOffset;
+
+ uint32 mustBeInvalidId;
+ uint32 mustBeZero;
+} SVGA3dCmdScreenCopy;
+#pragma pack(pop)
#define SVGA_SCREEN_COPY_STATUS_FAILURE 0x00
#define SVGA_SCREEN_COPY_STATUS_SUCCESS 0x01
#define SVGA_SCREEN_COPY_STATUS_INVALID 0xFFFFFFFF
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdWriteZeroSurface; /* SVGA_3D_CMD_WRITE_ZERO_SURFACE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 sid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdHintZeroSurface; /* SVGA_3D_CMD_HINT_ZERO_SURFACE */
-
-#endif /* _SVGA3D_CMD_H_ */
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+} SVGA3dCmdWriteZeroSurface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 sid;
+} SVGA3dCmdUpdateZeroSurface;
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_devcaps.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_devcaps.h
index 617b468c626c..379ec15c7758 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_devcaps.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_devcaps.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
- * Copyright 1998-2019 VMware, Inc.
+ * Copyright 1998-2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -27,484 +27,345 @@
/*
* svga3d_devcaps.h --
*
- * SVGA 3d caps definitions
+ * SVGA 3d caps definitions
*/
-#ifndef _SVGA3D_DEVCAPS_H_
-#define _SVGA3D_DEVCAPS_H_
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-#include "includeCheck.h"
+#ifndef _SVGA3D_DEVCAPS_H_
+#define _SVGA3D_DEVCAPS_H_
#include "svga3d_types.h"
-/*
- * 3D Hardware Version
- *
- * The hardware version is stored in the SVGA_FIFO_3D_HWVERSION fifo
- * register. Is set by the host and read by the guest. This lets
- * us make new guest drivers which are backwards-compatible with old
- * SVGA hardware revisions. It does not let us support old guest
- * drivers. Good enough for now.
- *
- */
-
-#define SVGA3D_MAKE_HWVERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
-#define SVGA3D_MAJOR_HWVERSION(version) ((version) >> 16)
-#define SVGA3D_MINOR_HWVERSION(version) ((version) & 0xFF)
+#define SVGA3D_MAKE_HWVERSION(major, minor) (((major) << 16) | ((minor)&0xFF))
+#define SVGA3D_MAJOR_HWVERSION(version) ((version) >> 16)
+#define SVGA3D_MINOR_HWVERSION(version) ((version)&0xFF)
typedef enum {
- SVGA3D_HWVERSION_WS5_RC1 = SVGA3D_MAKE_HWVERSION(0, 1),
- SVGA3D_HWVERSION_WS5_RC2 = SVGA3D_MAKE_HWVERSION(0, 2),
- SVGA3D_HWVERSION_WS51_RC1 = SVGA3D_MAKE_HWVERSION(0, 3),
- SVGA3D_HWVERSION_WS6_B1 = SVGA3D_MAKE_HWVERSION(1, 1),
- SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
- SVGA3D_HWVERSION_WS65_B1 = SVGA3D_MAKE_HWVERSION(2, 0),
- SVGA3D_HWVERSION_WS8_B1 = SVGA3D_MAKE_HWVERSION(2, 1),
- SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS8_B1,
+ SVGA3D_HWVERSION_WS5_RC1 = SVGA3D_MAKE_HWVERSION(0, 1),
+ SVGA3D_HWVERSION_WS5_RC2 = SVGA3D_MAKE_HWVERSION(0, 2),
+ SVGA3D_HWVERSION_WS51_RC1 = SVGA3D_MAKE_HWVERSION(0, 3),
+ SVGA3D_HWVERSION_WS6_B1 = SVGA3D_MAKE_HWVERSION(1, 1),
+ SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
+ SVGA3D_HWVERSION_WS65_B1 = SVGA3D_MAKE_HWVERSION(2, 0),
+ SVGA3D_HWVERSION_WS8_B1 = SVGA3D_MAKE_HWVERSION(2, 1),
+ SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS8_B1,
} SVGA3dHardwareVersion;
-/*
- * DevCap indexes.
- */
-
typedef uint32 SVGA3dDevCapIndex;
-#define SVGA3D_DEVCAP_INVALID ((uint32)-1)
-#define SVGA3D_DEVCAP_3D 0
-#define SVGA3D_DEVCAP_MAX_LIGHTS 1
-
-/*
- * SVGA3D_DEVCAP_MAX_TEXTURES reflects the maximum number of
- * fixed-function texture units available. Each of these units
- * work in both FFP and Shader modes, and they support texture
- * transforms and texture coordinates. The host may have additional
- * texture image units that are only usable with shaders.
- */
-#define SVGA3D_DEVCAP_MAX_TEXTURES 2
-#define SVGA3D_DEVCAP_MAX_CLIP_PLANES 3
-#define SVGA3D_DEVCAP_VERTEX_SHADER_VERSION 4
-#define SVGA3D_DEVCAP_VERTEX_SHADER 5
-#define SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION 6
-#define SVGA3D_DEVCAP_FRAGMENT_SHADER 7
-#define SVGA3D_DEVCAP_MAX_RENDER_TARGETS 8
-#define SVGA3D_DEVCAP_S23E8_TEXTURES 9
-#define SVGA3D_DEVCAP_S10E5_TEXTURES 10
-#define SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND 11
-#define SVGA3D_DEVCAP_D16_BUFFER_FORMAT 12
-#define SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT 13
-#define SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT 14
-#define SVGA3D_DEVCAP_QUERY_TYPES 15
-#define SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING 16
-#define SVGA3D_DEVCAP_MAX_POINT_SIZE 17
-#define SVGA3D_DEVCAP_MAX_SHADER_TEXTURES 18
-#define SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH 19
-#define SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT 20
-#define SVGA3D_DEVCAP_MAX_VOLUME_EXTENT 21
-#define SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT 22
-#define SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO 23
-#define SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY 24
-#define SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT 25
-#define SVGA3D_DEVCAP_MAX_VERTEX_INDEX 26
-#define SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS 27
-#define SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS 28
-#define SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS 29
-#define SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS 30
-#define SVGA3D_DEVCAP_TEXTURE_OPS 31
-#define SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 32
-#define SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 33
-#define SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 34
-#define SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 35
-#define SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 36
-#define SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 37
-#define SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 38
-#define SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 39
-#define SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 40
-#define SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 41
-#define SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 42
-#define SVGA3D_DEVCAP_SURFACEFMT_Z_D16 43
-#define SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 44
-#define SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 45
-#define SVGA3D_DEVCAP_SURFACEFMT_DXT1 46
-#define SVGA3D_DEVCAP_SURFACEFMT_DXT2 47
-#define SVGA3D_DEVCAP_SURFACEFMT_DXT3 48
-#define SVGA3D_DEVCAP_SURFACEFMT_DXT4 49
-#define SVGA3D_DEVCAP_SURFACEFMT_DXT5 50
-#define SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 51
-#define SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 52
-#define SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 53
-#define SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 54
-#define SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 55
-#define SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 56
-#define SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 57
-#define SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 58
-#define SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 59
-#define SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 60
-#define SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 61
-
-/*
- * There is a hole in our devcap definitions for
- * historical reasons.
- *
- * Define a constant just for completeness.
- */
-#define SVGA3D_DEVCAP_MISSING62 62
-
-#define SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES 63
-
-/*
- * Note that MAX_SIMULTANEOUS_RENDER_TARGETS is a maximum count of color
- * render targets. This does not include the depth or stencil targets.
- */
-#define SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS 64
-
-#define SVGA3D_DEVCAP_SURFACEFMT_V16U16 65
-#define SVGA3D_DEVCAP_SURFACEFMT_G16R16 66
-#define SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 67
-#define SVGA3D_DEVCAP_SURFACEFMT_UYVY 68
-#define SVGA3D_DEVCAP_SURFACEFMT_YUY2 69
-
-/*
- * Deprecated.
- */
-#define SVGA3D_DEVCAP_DEAD4 70
-#define SVGA3D_DEVCAP_DEAD5 71
-#define SVGA3D_DEVCAP_DEAD7 72
-#define SVGA3D_DEVCAP_DEAD6 73
-
-#define SVGA3D_DEVCAP_AUTOGENMIPMAPS 74
-#define SVGA3D_DEVCAP_SURFACEFMT_NV12 75
-#define SVGA3D_DEVCAP_DEAD10 76
-
-/*
- * This is the maximum number of SVGA context IDs that the guest
- * can define using SVGA_3D_CMD_CONTEXT_DEFINE.
- */
-#define SVGA3D_DEVCAP_MAX_CONTEXT_IDS 77
-
-/*
- * This is the maximum number of SVGA surface IDs that the guest
- * can define using SVGA_3D_CMD_SURFACE_DEFINE*.
- */
-#define SVGA3D_DEVCAP_MAX_SURFACE_IDS 78
-
-#define SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 79
-#define SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 80
-#define SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT 81
-
-#define SVGA3D_DEVCAP_SURFACEFMT_ATI1 82
-#define SVGA3D_DEVCAP_SURFACEFMT_ATI2 83
-
-/*
- * Deprecated.
- */
-#define SVGA3D_DEVCAP_DEAD1 84
-#define SVGA3D_DEVCAP_DEAD8 85
-#define SVGA3D_DEVCAP_DEAD9 86
-
-#define SVGA3D_DEVCAP_LINE_AA 87 /* boolean */
-#define SVGA3D_DEVCAP_LINE_STIPPLE 88 /* boolean */
-#define SVGA3D_DEVCAP_MAX_LINE_WIDTH 89 /* float */
-#define SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH 90 /* float */
-
-#define SVGA3D_DEVCAP_SURFACEFMT_YV12 91
-
-/*
- * Deprecated.
- */
-#define SVGA3D_DEVCAP_DEAD3 92
-
-/*
- * Are TS_CONSTANT, TS_COLOR_KEY, and TS_COLOR_KEY_ENABLE supported?
- */
-#define SVGA3D_DEVCAP_TS_COLOR_KEY 93 /* boolean */
-
-/*
- * Deprecated.
- */
-#define SVGA3D_DEVCAP_DEAD2 94
-
-/*
- * Does the device support DXContexts?
- */
-#define SVGA3D_DEVCAP_DXCONTEXT 95
-
-/*
- * Deprecated.
- */
-#define SVGA3D_DEVCAP_DEAD11 96
-
-/*
- * What is the maximum number of vertex buffers or vertex input registers
- * that can be expected to work correctly with a DXContext?
- *
- * The guest is allowed to set up to SVGA3D_DX_MAX_VERTEXBUFFERS, but
- * anything in excess of this cap is not guaranteed to render correctly.
- *
- * Similarly, the guest can set up to SVGA3D_DX_MAX_VERTEXINPUTREGISTERS
- * input registers without the SVGA3D_DEVCAP_SM4_1 cap, or
- * SVGA3D_DX_SM41_MAX_VERTEXINPUTREGISTERS with the SVGA3D_DEVCAP_SM4_1,
- * but only the registers up to this cap value are guaranteed to render
- * correctly.
- *
- * If guest-drivers are able to expose a lower-limit, it's recommended
- * that they clamp to this value. Otherwise, the host will make a
- * best-effort on case-by-case basis if guests exceed this.
- */
-#define SVGA3D_DEVCAP_DX_MAX_VERTEXBUFFERS 97
-
-/*
- * What is the maximum number of constant buffers that can be expected to
- * work correctly with a DX context?
- *
- * The guest is allowed to set up to SVGA3D_DX_MAX_CONSTBUFFERS, but
- * anything in excess of this cap is not guaranteed to render correctly.
- *
- * If guest-drivers are able to expose a lower-limit, it's recommended
- * that they clamp to this value. Otherwise, the host will make a
- * best-effort on case-by-case basis if guests exceed this.
- */
-#define SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS 98
-
-/*
- * Does the device support provoking vertex control?
- *
- * If this cap is present, the provokingVertexLast field in the
- * rasterizer state is enabled. (Guests can then set it to FALSE,
- * meaning that the first vertex is the provoking vertex, or TRUE,
- * meaning that the last verteix is the provoking vertex.)
- *
- * If this cap is FALSE, then guests should set the provokingVertexLast
- * to FALSE, otherwise rendering behavior is undefined.
- */
-#define SVGA3D_DEVCAP_DX_PROVOKING_VERTEX 99
-
-#define SVGA3D_DEVCAP_DXFMT_X8R8G8B8 100
-#define SVGA3D_DEVCAP_DXFMT_A8R8G8B8 101
-#define SVGA3D_DEVCAP_DXFMT_R5G6B5 102
-#define SVGA3D_DEVCAP_DXFMT_X1R5G5B5 103
-#define SVGA3D_DEVCAP_DXFMT_A1R5G5B5 104
-#define SVGA3D_DEVCAP_DXFMT_A4R4G4B4 105
-#define SVGA3D_DEVCAP_DXFMT_Z_D32 106
-#define SVGA3D_DEVCAP_DXFMT_Z_D16 107
-#define SVGA3D_DEVCAP_DXFMT_Z_D24S8 108
-#define SVGA3D_DEVCAP_DXFMT_Z_D15S1 109
-#define SVGA3D_DEVCAP_DXFMT_LUMINANCE8 110
-#define SVGA3D_DEVCAP_DXFMT_LUMINANCE4_ALPHA4 111
-#define SVGA3D_DEVCAP_DXFMT_LUMINANCE16 112
-#define SVGA3D_DEVCAP_DXFMT_LUMINANCE8_ALPHA8 113
-#define SVGA3D_DEVCAP_DXFMT_DXT1 114
-#define SVGA3D_DEVCAP_DXFMT_DXT2 115
-#define SVGA3D_DEVCAP_DXFMT_DXT3 116
-#define SVGA3D_DEVCAP_DXFMT_DXT4 117
-#define SVGA3D_DEVCAP_DXFMT_DXT5 118
-#define SVGA3D_DEVCAP_DXFMT_BUMPU8V8 119
-#define SVGA3D_DEVCAP_DXFMT_BUMPL6V5U5 120
-#define SVGA3D_DEVCAP_DXFMT_BUMPX8L8V8U8 121
-#define SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD1 122
-#define SVGA3D_DEVCAP_DXFMT_ARGB_S10E5 123
-#define SVGA3D_DEVCAP_DXFMT_ARGB_S23E8 124
-#define SVGA3D_DEVCAP_DXFMT_A2R10G10B10 125
-#define SVGA3D_DEVCAP_DXFMT_V8U8 126
-#define SVGA3D_DEVCAP_DXFMT_Q8W8V8U8 127
-#define SVGA3D_DEVCAP_DXFMT_CxV8U8 128
-#define SVGA3D_DEVCAP_DXFMT_X8L8V8U8 129
-#define SVGA3D_DEVCAP_DXFMT_A2W10V10U10 130
-#define SVGA3D_DEVCAP_DXFMT_ALPHA8 131
-#define SVGA3D_DEVCAP_DXFMT_R_S10E5 132
-#define SVGA3D_DEVCAP_DXFMT_R_S23E8 133
-#define SVGA3D_DEVCAP_DXFMT_RG_S10E5 134
-#define SVGA3D_DEVCAP_DXFMT_RG_S23E8 135
-#define SVGA3D_DEVCAP_DXFMT_BUFFER 136
-#define SVGA3D_DEVCAP_DXFMT_Z_D24X8 137
-#define SVGA3D_DEVCAP_DXFMT_V16U16 138
-#define SVGA3D_DEVCAP_DXFMT_G16R16 139
-#define SVGA3D_DEVCAP_DXFMT_A16B16G16R16 140
-#define SVGA3D_DEVCAP_DXFMT_UYVY 141
-#define SVGA3D_DEVCAP_DXFMT_YUY2 142
-#define SVGA3D_DEVCAP_DXFMT_NV12 143
-#define SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD2 144
-#define SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS 145
-#define SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT 146
-#define SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT 147
-#define SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS 148
-#define SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT 149
-#define SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT 150
-#define SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT 151
-#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS 152
-#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT 153
-#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM 154
-#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT 155
-#define SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS 156
-#define SVGA3D_DEVCAP_DXFMT_R32G32_UINT 157
-#define SVGA3D_DEVCAP_DXFMT_R32G32_SINT 158
-#define SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS 159
-#define SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT 160
-#define SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24 161
-#define SVGA3D_DEVCAP_DXFMT_X32_G8X24_UINT 162
-#define SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS 163
-#define SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT 164
-#define SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT 165
-#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS 166
-#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM 167
-#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB 168
-#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT 169
-#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT 170
-#define SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS 171
-#define SVGA3D_DEVCAP_DXFMT_R16G16_UINT 172
-#define SVGA3D_DEVCAP_DXFMT_R16G16_SINT 173
-#define SVGA3D_DEVCAP_DXFMT_R32_TYPELESS 174
-#define SVGA3D_DEVCAP_DXFMT_D32_FLOAT 175
-#define SVGA3D_DEVCAP_DXFMT_R32_UINT 176
-#define SVGA3D_DEVCAP_DXFMT_R32_SINT 177
-#define SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS 178
-#define SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT 179
-#define SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8 180
-#define SVGA3D_DEVCAP_DXFMT_X24_G8_UINT 181
-#define SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS 182
-#define SVGA3D_DEVCAP_DXFMT_R8G8_UNORM 183
-#define SVGA3D_DEVCAP_DXFMT_R8G8_UINT 184
-#define SVGA3D_DEVCAP_DXFMT_R8G8_SINT 185
-#define SVGA3D_DEVCAP_DXFMT_R16_TYPELESS 186
-#define SVGA3D_DEVCAP_DXFMT_R16_UNORM 187
-#define SVGA3D_DEVCAP_DXFMT_R16_UINT 188
-#define SVGA3D_DEVCAP_DXFMT_R16_SNORM 189
-#define SVGA3D_DEVCAP_DXFMT_R16_SINT 190
-#define SVGA3D_DEVCAP_DXFMT_R8_TYPELESS 191
-#define SVGA3D_DEVCAP_DXFMT_R8_UNORM 192
-#define SVGA3D_DEVCAP_DXFMT_R8_UINT 193
-#define SVGA3D_DEVCAP_DXFMT_R8_SNORM 194
-#define SVGA3D_DEVCAP_DXFMT_R8_SINT 195
-#define SVGA3D_DEVCAP_DXFMT_P8 196
-#define SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP 197
-#define SVGA3D_DEVCAP_DXFMT_R8G8_B8G8_UNORM 198
-#define SVGA3D_DEVCAP_DXFMT_G8R8_G8B8_UNORM 199
-#define SVGA3D_DEVCAP_DXFMT_BC1_TYPELESS 200
-#define SVGA3D_DEVCAP_DXFMT_BC1_UNORM_SRGB 201
-#define SVGA3D_DEVCAP_DXFMT_BC2_TYPELESS 202
-#define SVGA3D_DEVCAP_DXFMT_BC2_UNORM_SRGB 203
-#define SVGA3D_DEVCAP_DXFMT_BC3_TYPELESS 204
-#define SVGA3D_DEVCAP_DXFMT_BC3_UNORM_SRGB 205
-#define SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS 206
-#define SVGA3D_DEVCAP_DXFMT_ATI1 207
-#define SVGA3D_DEVCAP_DXFMT_BC4_SNORM 208
-#define SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS 209
-#define SVGA3D_DEVCAP_DXFMT_ATI2 210
-#define SVGA3D_DEVCAP_DXFMT_BC5_SNORM 211
-#define SVGA3D_DEVCAP_DXFMT_R10G10B10_XR_BIAS_A2_UNORM 212
-#define SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS 213
-#define SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB 214
-#define SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS 215
-#define SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB 216
-#define SVGA3D_DEVCAP_DXFMT_Z_DF16 217
-#define SVGA3D_DEVCAP_DXFMT_Z_DF24 218
-#define SVGA3D_DEVCAP_DXFMT_Z_D24S8_INT 219
-#define SVGA3D_DEVCAP_DXFMT_YV12 220
-#define SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT 221
-#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT 222
-#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM 223
-#define SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT 224
-#define SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM 225
-#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM 226
-#define SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT 227
-#define SVGA3D_DEVCAP_DXFMT_R16G16_UNORM 228
-#define SVGA3D_DEVCAP_DXFMT_R16G16_SNORM 229
-#define SVGA3D_DEVCAP_DXFMT_R32_FLOAT 230
-#define SVGA3D_DEVCAP_DXFMT_R8G8_SNORM 231
-#define SVGA3D_DEVCAP_DXFMT_R16_FLOAT 232
-#define SVGA3D_DEVCAP_DXFMT_D16_UNORM 233
-#define SVGA3D_DEVCAP_DXFMT_A8_UNORM 234
-#define SVGA3D_DEVCAP_DXFMT_BC1_UNORM 235
-#define SVGA3D_DEVCAP_DXFMT_BC2_UNORM 236
-#define SVGA3D_DEVCAP_DXFMT_BC3_UNORM 237
-#define SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM 238
-#define SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM 239
-#define SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM 240
-#define SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM 241
-#define SVGA3D_DEVCAP_DXFMT_BC4_UNORM 242
-#define SVGA3D_DEVCAP_DXFMT_BC5_UNORM 243
-
-/*
- * Advertises shaderModel 4.1 support, independent blend-states,
- * cube-map arrays, and a higher vertex input registers limit.
- *
- * (See documentation on SVGA3D_DEVCAP_DX_MAX_VERTEXBUFFERS.)
- */
-#define SVGA3D_DEVCAP_SM41 244
-#define SVGA3D_DEVCAP_MULTISAMPLE_2X 245
-#define SVGA3D_DEVCAP_MULTISAMPLE_4X 246
-
-/*
- * Indicates that the device has rendering support for
- * the full multisample quality. If this cap is not present,
- * the host may or may not support full quality rendering.
- *
- * See also SVGA_REG_MS_HINT_RESOLVED.
- */
-#define SVGA3D_DEVCAP_MS_FULL_QUALITY 247
-
-/*
- * Advertises support for the SVGA3D LogicOps commands.
- */
-#define SVGA3D_DEVCAP_LOGICOPS 248
-
-/*
- * Advertises support for using logicOps in the DXBlendStates.
- */
-#define SVGA3D_DEVCAP_LOGIC_BLENDOPS 249
-
-/*
-* Note DXFMT range is now non-contiguous.
-*/
-#define SVGA3D_DEVCAP_RESERVED_1 250
-#define SVGA3D_DEVCAP_DXFMT_BC6H_TYPELESS 251
-#define SVGA3D_DEVCAP_DXFMT_BC6H_UF16 252
-#define SVGA3D_DEVCAP_DXFMT_BC6H_SF16 253
-#define SVGA3D_DEVCAP_DXFMT_BC7_TYPELESS 254
-#define SVGA3D_DEVCAP_DXFMT_BC7_UNORM 255
-#define SVGA3D_DEVCAP_DXFMT_BC7_UNORM_SRGB 256
-#define SVGA3D_DEVCAP_RESERVED_2 257
-
-#define SVGA3D_DEVCAP_SM5 258
-#define SVGA3D_DEVCAP_MULTISAMPLE_8X 259
-
-/* This must be the last index. */
-#define SVGA3D_DEVCAP_MAX 260
-
-/*
- * Bit definitions for DXFMT devcaps
- *
- *
- * SUPPORTED: Can the format be defined?
- * SHADER_SAMPLE: Can the format be sampled from a shader?
- * COLOR_RENDERTARGET: Can the format be a color render target?
- * DEPTH_RENDERTARGET: Can the format be a depth render target?
- * BLENDABLE: Is the format blendable?
- * MIPS: Does the format support mip levels?
- * ARRAY: Does the format support texture arrays?
- * VOLUME: Does the format support having volume?
- * MULTISAMPLE: Does the format support multisample?
- */
-#define SVGA3D_DXFMT_SUPPORTED (1 << 0)
-#define SVGA3D_DXFMT_SHADER_SAMPLE (1 << 1)
-#define SVGA3D_DXFMT_COLOR_RENDERTARGET (1 << 2)
-#define SVGA3D_DXFMT_DEPTH_RENDERTARGET (1 << 3)
-#define SVGA3D_DXFMT_BLENDABLE (1 << 4)
-#define SVGA3D_DXFMT_MIPS (1 << 5)
-#define SVGA3D_DXFMT_ARRAY (1 << 6)
-#define SVGA3D_DXFMT_VOLUME (1 << 7)
-#define SVGA3D_DXFMT_DX_VERTEX_BUFFER (1 << 8)
-#define SVGA3D_DXFMT_MULTISAMPLE (1 << 9)
-#define SVGA3D_DXFMT_MAX (1 << 10)
+#define SVGA3D_DEVCAP_INVALID ((uint32)-1)
+#define SVGA3D_DEVCAP_3D 0
+#define SVGA3D_DEVCAP_MAX_LIGHTS 1
+
+#define SVGA3D_DEVCAP_MAX_TEXTURES 2
+#define SVGA3D_DEVCAP_MAX_CLIP_PLANES 3
+#define SVGA3D_DEVCAP_VERTEX_SHADER_VERSION 4
+#define SVGA3D_DEVCAP_VERTEX_SHADER 5
+#define SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION 6
+#define SVGA3D_DEVCAP_FRAGMENT_SHADER 7
+#define SVGA3D_DEVCAP_MAX_RENDER_TARGETS 8
+#define SVGA3D_DEVCAP_S23E8_TEXTURES 9
+#define SVGA3D_DEVCAP_S10E5_TEXTURES 10
+#define SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND 11
+#define SVGA3D_DEVCAP_D16_BUFFER_FORMAT 12
+#define SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT 13
+#define SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT 14
+#define SVGA3D_DEVCAP_QUERY_TYPES 15
+#define SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING 16
+#define SVGA3D_DEVCAP_MAX_POINT_SIZE 17
+#define SVGA3D_DEVCAP_MAX_SHADER_TEXTURES 18
+#define SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH 19
+#define SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT 20
+#define SVGA3D_DEVCAP_MAX_VOLUME_EXTENT 21
+#define SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT 22
+#define SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO 23
+#define SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY 24
+#define SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT 25
+#define SVGA3D_DEVCAP_MAX_VERTEX_INDEX 26
+#define SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS 27
+#define SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS 28
+#define SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS 29
+#define SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS 30
+#define SVGA3D_DEVCAP_TEXTURE_OPS 31
+#define SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 32
+#define SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 33
+#define SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 34
+#define SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 35
+#define SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 36
+#define SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 37
+#define SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 38
+#define SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 39
+#define SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 40
+#define SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 41
+#define SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 42
+#define SVGA3D_DEVCAP_SURFACEFMT_Z_D16 43
+#define SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 44
+#define SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 45
+#define SVGA3D_DEVCAP_SURFACEFMT_DXT1 46
+#define SVGA3D_DEVCAP_SURFACEFMT_DXT2 47
+#define SVGA3D_DEVCAP_SURFACEFMT_DXT3 48
+#define SVGA3D_DEVCAP_SURFACEFMT_DXT4 49
+#define SVGA3D_DEVCAP_SURFACEFMT_DXT5 50
+#define SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 51
+#define SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 52
+#define SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 53
+#define SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 54
+#define SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 55
+#define SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 56
+#define SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 57
+#define SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 58
+#define SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 59
+#define SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 60
+#define SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 61
+
+#define SVGA3D_DEVCAP_MISSING62 62
+
+#define SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES 63
+
+#define SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS 64
+
+#define SVGA3D_DEVCAP_SURFACEFMT_V16U16 65
+#define SVGA3D_DEVCAP_SURFACEFMT_G16R16 66
+#define SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 67
+#define SVGA3D_DEVCAP_SURFACEFMT_UYVY 68
+#define SVGA3D_DEVCAP_SURFACEFMT_YUY2 69
+
+#define SVGA3D_DEVCAP_DEAD4 70
+#define SVGA3D_DEVCAP_DEAD5 71
+#define SVGA3D_DEVCAP_DEAD7 72
+#define SVGA3D_DEVCAP_DEAD6 73
+
+#define SVGA3D_DEVCAP_AUTOGENMIPMAPS 74
+#define SVGA3D_DEVCAP_SURFACEFMT_NV12 75
+#define SVGA3D_DEVCAP_DEAD10 76
+
+#define SVGA3D_DEVCAP_MAX_CONTEXT_IDS 77
+
+#define SVGA3D_DEVCAP_MAX_SURFACE_IDS 78
+
+#define SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 79
+#define SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 80
+#define SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT 81
+
+#define SVGA3D_DEVCAP_SURFACEFMT_ATI1 82
+#define SVGA3D_DEVCAP_SURFACEFMT_ATI2 83
+
+#define SVGA3D_DEVCAP_DEAD1 84
+#define SVGA3D_DEVCAP_DEAD8 85
+#define SVGA3D_DEVCAP_DEAD9 86
+
+#define SVGA3D_DEVCAP_LINE_AA 87
+#define SVGA3D_DEVCAP_LINE_STIPPLE 88
+#define SVGA3D_DEVCAP_MAX_LINE_WIDTH 89
+#define SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH 90
+
+#define SVGA3D_DEVCAP_SURFACEFMT_YV12 91
+
+#define SVGA3D_DEVCAP_DEAD3 92
+
+#define SVGA3D_DEVCAP_TS_COLOR_KEY 93
+
+#define SVGA3D_DEVCAP_DEAD2 94
+
+#define SVGA3D_DEVCAP_DXCONTEXT 95
+
+#define SVGA3D_DEVCAP_DEAD11 96
+
+#define SVGA3D_DEVCAP_DX_MAX_VERTEXBUFFERS 97
+
+#define SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS 98
+
+#define SVGA3D_DEVCAP_DX_PROVOKING_VERTEX 99
+
+#define SVGA3D_DEVCAP_DXFMT_X8R8G8B8 100
+#define SVGA3D_DEVCAP_DXFMT_A8R8G8B8 101
+#define SVGA3D_DEVCAP_DXFMT_R5G6B5 102
+#define SVGA3D_DEVCAP_DXFMT_X1R5G5B5 103
+#define SVGA3D_DEVCAP_DXFMT_A1R5G5B5 104
+#define SVGA3D_DEVCAP_DXFMT_A4R4G4B4 105
+#define SVGA3D_DEVCAP_DXFMT_Z_D32 106
+#define SVGA3D_DEVCAP_DXFMT_Z_D16 107
+#define SVGA3D_DEVCAP_DXFMT_Z_D24S8 108
+#define SVGA3D_DEVCAP_DXFMT_Z_D15S1 109
+#define SVGA3D_DEVCAP_DXFMT_LUMINANCE8 110
+#define SVGA3D_DEVCAP_DXFMT_LUMINANCE4_ALPHA4 111
+#define SVGA3D_DEVCAP_DXFMT_LUMINANCE16 112
+#define SVGA3D_DEVCAP_DXFMT_LUMINANCE8_ALPHA8 113
+#define SVGA3D_DEVCAP_DXFMT_DXT1 114
+#define SVGA3D_DEVCAP_DXFMT_DXT2 115
+#define SVGA3D_DEVCAP_DXFMT_DXT3 116
+#define SVGA3D_DEVCAP_DXFMT_DXT4 117
+#define SVGA3D_DEVCAP_DXFMT_DXT5 118
+#define SVGA3D_DEVCAP_DXFMT_BUMPU8V8 119
+#define SVGA3D_DEVCAP_DXFMT_BUMPL6V5U5 120
+#define SVGA3D_DEVCAP_DXFMT_BUMPX8L8V8U8 121
+#define SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD1 122
+#define SVGA3D_DEVCAP_DXFMT_ARGB_S10E5 123
+#define SVGA3D_DEVCAP_DXFMT_ARGB_S23E8 124
+#define SVGA3D_DEVCAP_DXFMT_A2R10G10B10 125
+#define SVGA3D_DEVCAP_DXFMT_V8U8 126
+#define SVGA3D_DEVCAP_DXFMT_Q8W8V8U8 127
+#define SVGA3D_DEVCAP_DXFMT_CxV8U8 128
+#define SVGA3D_DEVCAP_DXFMT_X8L8V8U8 129
+#define SVGA3D_DEVCAP_DXFMT_A2W10V10U10 130
+#define SVGA3D_DEVCAP_DXFMT_ALPHA8 131
+#define SVGA3D_DEVCAP_DXFMT_R_S10E5 132
+#define SVGA3D_DEVCAP_DXFMT_R_S23E8 133
+#define SVGA3D_DEVCAP_DXFMT_RG_S10E5 134
+#define SVGA3D_DEVCAP_DXFMT_RG_S23E8 135
+#define SVGA3D_DEVCAP_DXFMT_BUFFER 136
+#define SVGA3D_DEVCAP_DXFMT_Z_D24X8 137
+#define SVGA3D_DEVCAP_DXFMT_V16U16 138
+#define SVGA3D_DEVCAP_DXFMT_G16R16 139
+#define SVGA3D_DEVCAP_DXFMT_A16B16G16R16 140
+#define SVGA3D_DEVCAP_DXFMT_UYVY 141
+#define SVGA3D_DEVCAP_DXFMT_YUY2 142
+#define SVGA3D_DEVCAP_DXFMT_NV12 143
+#define SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD2 144
+#define SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS 145
+#define SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT 146
+#define SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT 147
+#define SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS 148
+#define SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT 149
+#define SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT 150
+#define SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT 151
+#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS 152
+#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT 153
+#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM 154
+#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT 155
+#define SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS 156
+#define SVGA3D_DEVCAP_DXFMT_R32G32_UINT 157
+#define SVGA3D_DEVCAP_DXFMT_R32G32_SINT 158
+#define SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS 159
+#define SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT 160
+#define SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24 161
+#define SVGA3D_DEVCAP_DXFMT_X32_G8X24_UINT 162
+#define SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS 163
+#define SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT 164
+#define SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT 165
+#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS 166
+#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM 167
+#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB 168
+#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT 169
+#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT 170
+#define SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS 171
+#define SVGA3D_DEVCAP_DXFMT_R16G16_UINT 172
+#define SVGA3D_DEVCAP_DXFMT_R16G16_SINT 173
+#define SVGA3D_DEVCAP_DXFMT_R32_TYPELESS 174
+#define SVGA3D_DEVCAP_DXFMT_D32_FLOAT 175
+#define SVGA3D_DEVCAP_DXFMT_R32_UINT 176
+#define SVGA3D_DEVCAP_DXFMT_R32_SINT 177
+#define SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS 178
+#define SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT 179
+#define SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8 180
+#define SVGA3D_DEVCAP_DXFMT_X24_G8_UINT 181
+#define SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS 182
+#define SVGA3D_DEVCAP_DXFMT_R8G8_UNORM 183
+#define SVGA3D_DEVCAP_DXFMT_R8G8_UINT 184
+#define SVGA3D_DEVCAP_DXFMT_R8G8_SINT 185
+#define SVGA3D_DEVCAP_DXFMT_R16_TYPELESS 186
+#define SVGA3D_DEVCAP_DXFMT_R16_UNORM 187
+#define SVGA3D_DEVCAP_DXFMT_R16_UINT 188
+#define SVGA3D_DEVCAP_DXFMT_R16_SNORM 189
+#define SVGA3D_DEVCAP_DXFMT_R16_SINT 190
+#define SVGA3D_DEVCAP_DXFMT_R8_TYPELESS 191
+#define SVGA3D_DEVCAP_DXFMT_R8_UNORM 192
+#define SVGA3D_DEVCAP_DXFMT_R8_UINT 193
+#define SVGA3D_DEVCAP_DXFMT_R8_SNORM 194
+#define SVGA3D_DEVCAP_DXFMT_R8_SINT 195
+#define SVGA3D_DEVCAP_DXFMT_P8 196
+#define SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP 197
+#define SVGA3D_DEVCAP_DXFMT_R8G8_B8G8_UNORM 198
+#define SVGA3D_DEVCAP_DXFMT_G8R8_G8B8_UNORM 199
+#define SVGA3D_DEVCAP_DXFMT_BC1_TYPELESS 200
+#define SVGA3D_DEVCAP_DXFMT_BC1_UNORM_SRGB 201
+#define SVGA3D_DEVCAP_DXFMT_BC2_TYPELESS 202
+#define SVGA3D_DEVCAP_DXFMT_BC2_UNORM_SRGB 203
+#define SVGA3D_DEVCAP_DXFMT_BC3_TYPELESS 204
+#define SVGA3D_DEVCAP_DXFMT_BC3_UNORM_SRGB 205
+#define SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS 206
+#define SVGA3D_DEVCAP_DXFMT_ATI1 207
+#define SVGA3D_DEVCAP_DXFMT_BC4_SNORM 208
+#define SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS 209
+#define SVGA3D_DEVCAP_DXFMT_ATI2 210
+#define SVGA3D_DEVCAP_DXFMT_BC5_SNORM 211
+#define SVGA3D_DEVCAP_DXFMT_R10G10B10_XR_BIAS_A2_UNORM 212
+#define SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS 213
+#define SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB 214
+#define SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS 215
+#define SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB 216
+#define SVGA3D_DEVCAP_DXFMT_Z_DF16 217
+#define SVGA3D_DEVCAP_DXFMT_Z_DF24 218
+#define SVGA3D_DEVCAP_DXFMT_Z_D24S8_INT 219
+#define SVGA3D_DEVCAP_DXFMT_YV12 220
+#define SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT 221
+#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT 222
+#define SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM 223
+#define SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT 224
+#define SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM 225
+#define SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM 226
+#define SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT 227
+#define SVGA3D_DEVCAP_DXFMT_R16G16_UNORM 228
+#define SVGA3D_DEVCAP_DXFMT_R16G16_SNORM 229
+#define SVGA3D_DEVCAP_DXFMT_R32_FLOAT 230
+#define SVGA3D_DEVCAP_DXFMT_R8G8_SNORM 231
+#define SVGA3D_DEVCAP_DXFMT_R16_FLOAT 232
+#define SVGA3D_DEVCAP_DXFMT_D16_UNORM 233
+#define SVGA3D_DEVCAP_DXFMT_A8_UNORM 234
+#define SVGA3D_DEVCAP_DXFMT_BC1_UNORM 235
+#define SVGA3D_DEVCAP_DXFMT_BC2_UNORM 236
+#define SVGA3D_DEVCAP_DXFMT_BC3_UNORM 237
+#define SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM 238
+#define SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM 239
+#define SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM 240
+#define SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM 241
+#define SVGA3D_DEVCAP_DXFMT_BC4_UNORM 242
+#define SVGA3D_DEVCAP_DXFMT_BC5_UNORM 243
+
+#define SVGA3D_DEVCAP_SM41 244
+#define SVGA3D_DEVCAP_MULTISAMPLE_2X 245
+#define SVGA3D_DEVCAP_MULTISAMPLE_4X 246
+
+#define SVGA3D_DEVCAP_MS_FULL_QUALITY 247
+
+#define SVGA3D_DEVCAP_LOGICOPS 248
+
+#define SVGA3D_DEVCAP_LOGIC_BLENDOPS 249
+
+#define SVGA3D_DEVCAP_DEAD12 250
+
+#define SVGA3D_DEVCAP_DXFMT_BC6H_TYPELESS 251
+#define SVGA3D_DEVCAP_DXFMT_BC6H_UF16 252
+#define SVGA3D_DEVCAP_DXFMT_BC6H_SF16 253
+#define SVGA3D_DEVCAP_DXFMT_BC7_TYPELESS 254
+#define SVGA3D_DEVCAP_DXFMT_BC7_UNORM 255
+#define SVGA3D_DEVCAP_DXFMT_BC7_UNORM_SRGB 256
+
+#define SVGA3D_DEVCAP_DEAD13 257
+
+#define SVGA3D_DEVCAP_SM5 258
+#define SVGA3D_DEVCAP_MULTISAMPLE_8X 259
+
+#define SVGA3D_DEVCAP_MAX 262
+
+#define SVGA3D_DXFMT_SUPPORTED (1 << 0)
+#define SVGA3D_DXFMT_SHADER_SAMPLE (1 << 1)
+#define SVGA3D_DXFMT_COLOR_RENDERTARGET (1 << 2)
+#define SVGA3D_DXFMT_DEPTH_RENDERTARGET (1 << 3)
+#define SVGA3D_DXFMT_BLENDABLE (1 << 4)
+#define SVGA3D_DXFMT_MIPS (1 << 5)
+#define SVGA3D_DXFMT_ARRAY (1 << 6)
+#define SVGA3D_DXFMT_VOLUME (1 << 7)
+#define SVGA3D_DXFMT_DX_VERTEX_BUFFER (1 << 8)
+#define SVGA3D_DXFMT_MULTISAMPLE (1 << 9)
+#define SVGA3D_DXFMT_MAX (1 << 10)
typedef union {
- SVGA3dBool b;
- uint32 u;
- int32 i;
- float f;
+ SVGA3dBool b;
+ uint32 u;
+ int32 i;
+ float f;
} SVGA3dDevCapResult;
-#endif /* _SVGA3D_DEVCAPS_H_ */
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_dx.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_dx.h
index f703ac2b1768..5af442dad542 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_dx.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_dx.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
- * Copyright 2012-2019 VMware, Inc.
+ * Copyright 2012-2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -27,88 +27,70 @@
/*
* svga3d_dx.h --
*
- * SVGA 3d hardware definitions for DX10 support.
+ * SVGA 3d hardware definitions for DX10 support.
*/
+
+
#ifndef _SVGA3D_DX_H_
#define _SVGA3D_DX_H_
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-#include "includeCheck.h"
-
+#include "svga_reg.h"
#include "svga3d_limits.h"
+#include "svga3d_types.h"
-#define SVGA3D_INPUT_MIN 0
-#define SVGA3D_INPUT_PER_VERTEX_DATA 0
+#define SVGA3D_INPUT_MIN 0
+#define SVGA3D_INPUT_PER_VERTEX_DATA 0
#define SVGA3D_INPUT_PER_INSTANCE_DATA 1
-#define SVGA3D_INPUT_MAX 2
+#define SVGA3D_INPUT_MAX 2
typedef uint32 SVGA3dInputClassification;
-#define SVGA3D_RESOURCE_TYPE_MIN 1
-#define SVGA3D_RESOURCE_BUFFER 1
-#define SVGA3D_RESOURCE_TEXTURE1D 2
-#define SVGA3D_RESOURCE_TEXTURE2D 3
-#define SVGA3D_RESOURCE_TEXTURE3D 4
-#define SVGA3D_RESOURCE_TEXTURECUBE 5
-#define SVGA3D_RESOURCE_TYPE_DX10_MAX 6
-#define SVGA3D_RESOURCE_BUFFEREX 6
-#define SVGA3D_RESOURCE_TYPE_MAX 7
-typedef uint32 SVGA3dResourceType;
-
-#define SVGA3D_COLOR_WRITE_ENABLE_RED (1 << 0)
-#define SVGA3D_COLOR_WRITE_ENABLE_GREEN (1 << 1)
-#define SVGA3D_COLOR_WRITE_ENABLE_BLUE (1 << 2)
-#define SVGA3D_COLOR_WRITE_ENABLE_ALPHA (1 << 3)
-#define SVGA3D_COLOR_WRITE_ENABLE_ALL (SVGA3D_COLOR_WRITE_ENABLE_RED | \
- SVGA3D_COLOR_WRITE_ENABLE_GREEN | \
- SVGA3D_COLOR_WRITE_ENABLE_BLUE | \
- SVGA3D_COLOR_WRITE_ENABLE_ALPHA)
+#define SVGA3D_COLOR_WRITE_ENABLE_RED (1 << 0)
+#define SVGA3D_COLOR_WRITE_ENABLE_GREEN (1 << 1)
+#define SVGA3D_COLOR_WRITE_ENABLE_BLUE (1 << 2)
+#define SVGA3D_COLOR_WRITE_ENABLE_ALPHA (1 << 3)
+#define SVGA3D_COLOR_WRITE_ENABLE_ALL \
+ (SVGA3D_COLOR_WRITE_ENABLE_RED | SVGA3D_COLOR_WRITE_ENABLE_GREEN | \
+ SVGA3D_COLOR_WRITE_ENABLE_BLUE | SVGA3D_COLOR_WRITE_ENABLE_ALPHA)
typedef uint8 SVGA3dColorWriteEnable;
-#define SVGA3D_DEPTH_WRITE_MASK_ZERO 0
-#define SVGA3D_DEPTH_WRITE_MASK_ALL 1
+#define SVGA3D_DEPTH_WRITE_MASK_ZERO 0
+#define SVGA3D_DEPTH_WRITE_MASK_ALL 1
typedef uint8 SVGA3dDepthWriteMask;
-#define SVGA3D_FILTER_MIP_LINEAR (1 << 0)
-#define SVGA3D_FILTER_MAG_LINEAR (1 << 2)
-#define SVGA3D_FILTER_MIN_LINEAR (1 << 4)
+#define SVGA3D_FILTER_MIP_LINEAR (1 << 0)
+#define SVGA3D_FILTER_MAG_LINEAR (1 << 2)
+#define SVGA3D_FILTER_MIN_LINEAR (1 << 4)
#define SVGA3D_FILTER_ANISOTROPIC (1 << 6)
-#define SVGA3D_FILTER_COMPARE (1 << 7)
+#define SVGA3D_FILTER_COMPARE (1 << 7)
typedef uint32 SVGA3dFilter;
#define SVGA3D_CULL_INVALID 0
-#define SVGA3D_CULL_MIN 1
-#define SVGA3D_CULL_NONE 1
-#define SVGA3D_CULL_FRONT 2
-#define SVGA3D_CULL_BACK 3
-#define SVGA3D_CULL_MAX 4
+#define SVGA3D_CULL_MIN 1
+#define SVGA3D_CULL_NONE 1
+#define SVGA3D_CULL_FRONT 2
+#define SVGA3D_CULL_BACK 3
+#define SVGA3D_CULL_MAX 4
typedef uint8 SVGA3dCullMode;
-#define SVGA3D_COMPARISON_INVALID 0
-#define SVGA3D_COMPARISON_MIN 1
-#define SVGA3D_COMPARISON_NEVER 1
-#define SVGA3D_COMPARISON_LESS 2
-#define SVGA3D_COMPARISON_EQUAL 3
-#define SVGA3D_COMPARISON_LESS_EQUAL 4
-#define SVGA3D_COMPARISON_GREATER 5
-#define SVGA3D_COMPARISON_NOT_EQUAL 6
-#define SVGA3D_COMPARISON_GREATER_EQUAL 7
-#define SVGA3D_COMPARISON_ALWAYS 8
-#define SVGA3D_COMPARISON_MAX 9
+#define SVGA3D_COMPARISON_INVALID 0
+#define SVGA3D_COMPARISON_MIN 1
+#define SVGA3D_COMPARISON_NEVER 1
+#define SVGA3D_COMPARISON_LESS 2
+#define SVGA3D_COMPARISON_EQUAL 3
+#define SVGA3D_COMPARISON_LESS_EQUAL 4
+#define SVGA3D_COMPARISON_GREATER 5
+#define SVGA3D_COMPARISON_NOT_EQUAL 6
+#define SVGA3D_COMPARISON_GREATER_EQUAL 7
+#define SVGA3D_COMPARISON_ALWAYS 8
+#define SVGA3D_COMPARISON_MAX 9
typedef uint8 SVGA3dComparisonFunc;
-/*
- * SVGA3D_MULTISAMPLE_RAST_DISABLE disables MSAA for all primitives.
- * SVGA3D_MULTISAMPLE_RAST_DISABLE_LINE, which is supported in SM41,
- * disables MSAA for lines only.
- */
-#define SVGA3D_MULTISAMPLE_RAST_DISABLE 0
-#define SVGA3D_MULTISAMPLE_RAST_ENABLE 1
-#define SVGA3D_MULTISAMPLE_RAST_DX_MAX 1
-#define SVGA3D_MULTISAMPLE_RAST_DISABLE_LINE 2
-#define SVGA3D_MULTISAMPLE_RAST_MAX 2
+#define SVGA3D_MULTISAMPLE_RAST_DISABLE 0
+#define SVGA3D_MULTISAMPLE_RAST_ENABLE 1
+#define SVGA3D_MULTISAMPLE_RAST_DX_MAX 1
+#define SVGA3D_MULTISAMPLE_RAST_DISABLE_LINE 2
+#define SVGA3D_MULTISAMPLE_RAST_MAX 2
typedef uint8 SVGA3dMultisampleRastEnable;
#define SVGA3D_DX_MAX_VERTEXBUFFERS 32
@@ -137,1531 +119,1273 @@ typedef uint32 SVGA3dQueryId;
typedef uint32 SVGA3dStreamOutputId;
typedef union {
- struct {
- float r;
- float g;
- float b;
- float a;
- };
-
- float value[4];
-} SVGA3dRGBAFloat;
-
-typedef union {
- struct {
- uint32 r;
- uint32 g;
- uint32 b;
- uint32 a;
- };
-
- uint32 value[4];
+ struct {
+ uint32 r;
+ uint32 g;
+ uint32 b;
+ uint32 a;
+ };
+
+ uint32 value[4];
} SVGA3dRGBAUint32;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 cid;
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGAOTableDXContextEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineContext {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineContext; /* SVGA_3D_CMD_DX_DEFINE_CONTEXT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyContext {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyContext; /* SVGA_3D_CMD_DX_DESTROY_CONTEXT */
-
-/*
- * Bind a DX context.
- *
- * validContents should be set to 0 for new contexts,
- * and 1 if this is an old context which is getting paged
- * back on to the device.
- *
- * For new contexts, it is recommended that the driver
- * issue commands to initialize all interesting state
- * prior to rendering.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBindContext {
- uint32 cid;
- SVGAMobId mobid;
- uint32 validContents;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBindContext; /* SVGA_3D_CMD_DX_BIND_CONTEXT */
-
-/*
- * Readback a DX context.
- * (Request that the device flush the contents back into guest memory.)
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXReadbackContext {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXReadbackContext; /* SVGA_3D_CMD_DX_READBACK_CONTEXT */
-
-/*
- * Invalidate a guest-backed context.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXInvalidateContext {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXInvalidateContext; /* SVGA_3D_CMD_DX_INVALIDATE_CONTEXT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetSingleConstantBuffer {
- uint32 slot;
- SVGA3dShaderType type;
- SVGA3dSurfaceId sid;
- uint32 offsetInBytes;
- uint32 sizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetSingleConstantBuffer;
-/* SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetShaderResources {
- uint32 startView;
- SVGA3dShaderType type;
-
- /*
- * Followed by a variable number of SVGA3dShaderResourceViewId's.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetShaderResources; /* SVGA_3D_CMD_DX_SET_SHADER_RESOURCES */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetShader {
- SVGA3dShaderId shaderId;
- SVGA3dShaderType type;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetShader; /* SVGA_3D_CMD_DX_SET_SHADER */
+#pragma pack(push, 1)
+typedef struct {
+ uint32 cid;
+ SVGAMobId mobid;
+} SVGAOTableDXContextEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineContext {
+ uint32 cid;
+} SVGA3dCmdDXDefineContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyContext {
+ uint32 cid;
+} SVGA3dCmdDXDestroyContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBindContext {
+ uint32 cid;
+ SVGAMobId mobid;
+ uint32 validContents;
+} SVGA3dCmdDXBindContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXReadbackContext {
+ uint32 cid;
+} SVGA3dCmdDXReadbackContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXInvalidateContext {
+ uint32 cid;
+} SVGA3dCmdDXInvalidateContext;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetSingleConstantBuffer {
+ uint32 slot;
+ SVGA3dShaderType type;
+ SVGA3dSurfaceId sid;
+ uint32 offsetInBytes;
+ uint32 sizeInBytes;
+} SVGA3dCmdDXSetSingleConstantBuffer;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetShaderResources {
+ uint32 startView;
+ SVGA3dShaderType type;
+
+} SVGA3dCmdDXSetShaderResources;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetShader {
+ SVGA3dShaderId shaderId;
+ SVGA3dShaderType type;
+} SVGA3dCmdDXSetShader;
+#pragma pack(pop)
typedef union {
- struct {
- uint32 cbOffset : 12;
- uint32 cbId : 4;
- uint32 baseSamp : 4;
- uint32 baseTex : 7;
- uint32 reserved : 5;
- };
- uint32 value;
+ struct {
+ uint32 cbOffset : 12;
+ uint32 cbId : 4;
+ uint32 baseSamp : 4;
+ uint32 baseTex : 7;
+ uint32 reserved : 5;
+ };
+ uint32 value;
} SVGA3dIfaceData;
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetShaderIface {
- SVGA3dShaderType type;
- uint32 numClassInstances;
- uint32 index;
- uint32 iface;
- SVGA3dIfaceData data;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetShaderIface; /* SVGA_3D_CMD_DX_SET_SHADER_IFACE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBindShaderIface {
- uint32 cid;
- SVGAMobId mobid;
- uint32 offsetInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBindShaderIface; /* SVGA_3D_CMD_DX_BIND_SHADER_IFACE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetSamplers {
- uint32 startSampler;
- SVGA3dShaderType type;
-
- /*
- * Followed by a variable number of SVGA3dSamplerId's.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetSamplers; /* SVGA_3D_CMD_DX_SET_SAMPLERS */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDraw {
- uint32 vertexCount;
- uint32 startVertexLocation;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDraw; /* SVGA_3D_CMD_DX_DRAW */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDrawIndexed {
- uint32 indexCount;
- uint32 startIndexLocation;
- int32 baseVertexLocation;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDrawIndexed; /* SVGA_3D_CMD_DX_DRAW_INDEXED */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDrawInstanced {
- uint32 vertexCountPerInstance;
- uint32 instanceCount;
- uint32 startVertexLocation;
- uint32 startInstanceLocation;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDrawInstanced; /* SVGA_3D_CMD_DX_DRAW_INSTANCED */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDrawIndexedInstanced {
- uint32 indexCountPerInstance;
- uint32 instanceCount;
- uint32 startIndexLocation;
- int32 baseVertexLocation;
- uint32 startInstanceLocation;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDrawIndexedInstanced; /* SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDrawIndexedInstancedIndirect {
- SVGA3dSurfaceId argsBufferSid;
- uint32 byteOffsetForArgs;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDrawIndexedInstancedIndirect;
-/* SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDrawInstancedIndirect {
- SVGA3dSurfaceId argsBufferSid;
- uint32 byteOffsetForArgs;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDrawInstancedIndirect;
-/* SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDrawAuto {
- uint32 pad0;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDrawAuto; /* SVGA_3D_CMD_DX_DRAW_AUTO */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDispatch {
- uint32 threadGroupCountX;
- uint32 threadGroupCountY;
- uint32 threadGroupCountZ;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDispatch;
-/* SVGA_3D_CMD_DX_DISPATCH */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDispatchIndirect {
- SVGA3dSurfaceId argsBufferSid;
- uint32 byteOffsetForArgs;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDispatchIndirect;
-/* SVGA_3D_CMD_DX_DISPATCH_INDIRECT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetInputLayout {
- SVGA3dElementLayoutId elementLayoutId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetInputLayout; /* SVGA_3D_CMD_DX_SET_INPUT_LAYOUT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dVertexBuffer {
- SVGA3dSurfaceId sid;
- uint32 stride;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGA3dVertexBuffer;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetVertexBuffers {
- uint32 startBuffer;
- /* Followed by a variable number of SVGA3dVertexBuffer's. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetVertexBuffers; /* SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetIndexBuffer {
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetIndexBuffer; /* SVGA_3D_CMD_DX_SET_INDEX_BUFFER */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetTopology {
- SVGA3dPrimitiveType topology;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetTopology; /* SVGA_3D_CMD_DX_SET_TOPOLOGY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetRenderTargets {
- SVGA3dDepthStencilViewId depthStencilViewId;
- /* Followed by a variable number of SVGA3dRenderTargetViewId's. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetRenderTargets; /* SVGA_3D_CMD_DX_SET_RENDERTARGETS */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetBlendState {
- SVGA3dBlendStateId blendId;
- float blendFactor[4];
- uint32 sampleMask;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetBlendState; /* SVGA_3D_CMD_DX_SET_BLEND_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetDepthStencilState {
- SVGA3dDepthStencilStateId depthStencilId;
- uint32 stencilRef;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetDepthStencilState; /* SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetRasterizerState {
- SVGA3dRasterizerStateId rasterizerId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetRasterizerState; /* SVGA_3D_CMD_DX_SET_RASTERIZER_STATE */
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetShaderIface {
+ SVGA3dShaderType type;
+ uint32 numClassInstances;
+ uint32 index;
+ uint32 iface;
+ SVGA3dIfaceData data;
+} SVGA3dCmdDXSetShaderIface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBindShaderIface {
+ uint32 cid;
+ SVGAMobId mobid;
+ uint32 offsetInBytes;
+} SVGA3dCmdDXBindShaderIface;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetSamplers {
+ uint32 startSampler;
+ SVGA3dShaderType type;
+
+} SVGA3dCmdDXSetSamplers;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDraw {
+ uint32 vertexCount;
+ uint32 startVertexLocation;
+} SVGA3dCmdDXDraw;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDrawIndexed {
+ uint32 indexCount;
+ uint32 startIndexLocation;
+ int32 baseVertexLocation;
+} SVGA3dCmdDXDrawIndexed;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDrawInstanced {
+ uint32 vertexCountPerInstance;
+ uint32 instanceCount;
+ uint32 startVertexLocation;
+ uint32 startInstanceLocation;
+} SVGA3dCmdDXDrawInstanced;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDrawIndexedInstanced {
+ uint32 indexCountPerInstance;
+ uint32 instanceCount;
+ uint32 startIndexLocation;
+ int32 baseVertexLocation;
+ uint32 startInstanceLocation;
+} SVGA3dCmdDXDrawIndexedInstanced;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDrawIndexedInstancedIndirect {
+ SVGA3dSurfaceId argsBufferSid;
+ uint32 byteOffsetForArgs;
+} SVGA3dCmdDXDrawIndexedInstancedIndirect;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDrawInstancedIndirect {
+ SVGA3dSurfaceId argsBufferSid;
+ uint32 byteOffsetForArgs;
+} SVGA3dCmdDXDrawInstancedIndirect;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDrawAuto {
+ uint32 pad0;
+} SVGA3dCmdDXDrawAuto;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDispatch {
+ uint32 threadGroupCountX;
+ uint32 threadGroupCountY;
+ uint32 threadGroupCountZ;
+} SVGA3dCmdDXDispatch;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDispatchIndirect {
+ SVGA3dSurfaceId argsBufferSid;
+ uint32 byteOffsetForArgs;
+} SVGA3dCmdDXDispatchIndirect;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetInputLayout {
+ SVGA3dElementLayoutId elementLayoutId;
+} SVGA3dCmdDXSetInputLayout;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dVertexBuffer {
+ SVGA3dSurfaceId sid;
+ uint32 stride;
+ uint32 offset;
+} SVGA3dVertexBuffer;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetVertexBuffers {
+ uint32 startBuffer;
+
+} SVGA3dCmdDXSetVertexBuffers;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dVertexBuffer_v2 {
+ SVGA3dSurfaceId sid;
+ uint32 stride;
+ uint32 offset;
+ uint32 sizeInBytes;
+} SVGA3dVertexBuffer_v2;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetVertexBuffers_v2 {
+ uint32 startBuffer;
+
+} SVGA3dCmdDXSetVertexBuffers_v2;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dVertexBufferOffsetAndSize {
+ uint32 stride;
+ uint32 offset;
+ uint32 sizeInBytes;
+} SVGA3dVertexBufferOffsetAndSize;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetVertexBuffersOffsetAndSize {
+ uint32 startBuffer;
+
+} SVGA3dCmdDXSetVertexBuffersOffsetAndSize;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetIndexBuffer {
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ uint32 offset;
+} SVGA3dCmdDXSetIndexBuffer;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetIndexBuffer_v2 {
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ uint32 offset;
+ uint32 sizeInBytes;
+} SVGA3dCmdDXSetIndexBuffer_v2;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetIndexBufferOffsetAndSize {
+ SVGA3dSurfaceFormat format;
+ uint32 offset;
+ uint32 sizeInBytes;
+} SVGA3dCmdDXSetIndexBufferOffsetAndSize;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetTopology {
+ SVGA3dPrimitiveType topology;
+} SVGA3dCmdDXSetTopology;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetRenderTargets {
+ SVGA3dDepthStencilViewId depthStencilViewId;
+
+} SVGA3dCmdDXSetRenderTargets;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetBlendState {
+ SVGA3dBlendStateId blendId;
+ float blendFactor[4];
+ uint32 sampleMask;
+} SVGA3dCmdDXSetBlendState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetDepthStencilState {
+ SVGA3dDepthStencilStateId depthStencilId;
+ uint32 stencilRef;
+} SVGA3dCmdDXSetDepthStencilState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetRasterizerState {
+ SVGA3dRasterizerStateId rasterizerId;
+} SVGA3dCmdDXSetRasterizerState;
+#pragma pack(pop)
#define SVGA3D_DXQUERY_FLAG_PREDICATEHINT (1 << 0)
typedef uint32 SVGA3dDXQueryFlags;
-/*
- * The SVGADXQueryDeviceState and SVGADXQueryDeviceBits are used by the device
- * to track query state transitions, but are not intended to be used by the
- * driver.
- */
-#define SVGADX_QDSTATE_INVALID ((uint8)-1) /* Query has no state */
-#define SVGADX_QDSTATE_MIN 0
-#define SVGADX_QDSTATE_IDLE 0 /* Query hasn't started yet */
-#define SVGADX_QDSTATE_ACTIVE 1 /* Query is actively gathering data */
-#define SVGADX_QDSTATE_PENDING 2 /* Query is waiting for results */
-#define SVGADX_QDSTATE_FINISHED 3 /* Query has completed */
-#define SVGADX_QDSTATE_MAX 4
+#define SVGADX_QDSTATE_INVALID ((uint8)-1)
+#define SVGADX_QDSTATE_MIN 0
+#define SVGADX_QDSTATE_IDLE 0
+#define SVGADX_QDSTATE_ACTIVE 1
+#define SVGADX_QDSTATE_PENDING 2
+#define SVGADX_QDSTATE_FINISHED 3
+#define SVGADX_QDSTATE_MAX 4
typedef uint8 SVGADXQueryDeviceState;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dQueryTypeUint8 type;
- uint16 pad0;
- SVGADXQueryDeviceState state;
- SVGA3dDXQueryFlags flags;
- SVGAMobId mobid;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXQueryEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineQuery {
- SVGA3dQueryId queryId;
- SVGA3dQueryType type;
- SVGA3dDXQueryFlags flags;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineQuery; /* SVGA_3D_CMD_DX_DEFINE_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyQuery {
- SVGA3dQueryId queryId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyQuery; /* SVGA_3D_CMD_DX_DESTROY_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBindQuery {
- SVGA3dQueryId queryId;
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBindQuery; /* SVGA_3D_CMD_DX_BIND_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetQueryOffset {
- SVGA3dQueryId queryId;
- uint32 mobOffset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetQueryOffset; /* SVGA_3D_CMD_DX_SET_QUERY_OFFSET */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBeginQuery {
- SVGA3dQueryId queryId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBeginQuery; /* SVGA_3D_CMD_DX_QUERY_BEGIN */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXEndQuery {
- SVGA3dQueryId queryId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXEndQuery; /* SVGA_3D_CMD_DX_QUERY_END */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXReadbackQuery {
- SVGA3dQueryId queryId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXReadbackQuery; /* SVGA_3D_CMD_DX_READBACK_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXMoveQuery {
- SVGA3dQueryId queryId;
- SVGAMobId mobid;
- uint32 mobOffset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXMoveQuery; /* SVGA_3D_CMD_DX_MOVE_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBindAllQuery {
- uint32 cid;
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBindAllQuery; /* SVGA_3D_CMD_DX_BIND_ALL_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXReadbackAllQuery {
- uint32 cid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXReadbackAllQuery; /* SVGA_3D_CMD_DX_READBACK_ALL_QUERY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetPredication {
- SVGA3dQueryId queryId;
- uint32 predicateValue;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetPredication; /* SVGA_3D_CMD_DX_SET_PREDICATION */
-
-typedef
-#include "vmware_pack_begin.h"
-struct MKS3dDXSOState {
- uint32 offset; /* Starting offset */
- uint32 intOffset; /* Internal offset */
- uint32 vertexCount; /* vertices written */
- uint32 dead;
-}
-#include "vmware_pack_end.h"
-SVGA3dDXSOState;
-
-/* Set the offset field to this value to append SO values to the buffer */
-#define SVGA3D_DX_SO_OFFSET_APPEND ((uint32) ~0u)
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dSoTarget {
- SVGA3dSurfaceId sid;
- uint32 offset;
- uint32 sizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dSoTarget;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetSOTargets {
- uint32 pad0;
- /* Followed by a variable number of SVGA3dSOTarget's. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetSOTargets; /* SVGA_3D_CMD_DX_SET_SOTARGETS */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dViewport
-{
- float x;
- float y;
- float width;
- float height;
- float minDepth;
- float maxDepth;
-}
-#include "vmware_pack_end.h"
-SVGA3dViewport;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetViewports {
- uint32 pad0;
- /* Followed by a variable number of SVGA3dViewport's. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetViewports; /* SVGA_3D_CMD_DX_SET_VIEWPORTS */
-
-#define SVGA3D_DX_MAX_VIEWPORTS 16
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetScissorRects {
- uint32 pad0;
- /* Followed by a variable number of SVGASignedRect's. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetScissorRects; /* SVGA_3D_CMD_DX_SET_SCISSORRECTS */
-
-#define SVGA3D_DX_MAX_SCISSORRECTS 16
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXClearRenderTargetView {
- SVGA3dRenderTargetViewId renderTargetViewId;
- SVGA3dRGBAFloat rgba;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXClearRenderTargetView; /* SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXClearDepthStencilView {
- uint16 flags;
- uint16 stencil;
- SVGA3dDepthStencilViewId depthStencilViewId;
- float depth;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXClearDepthStencilView; /* SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXPredCopyRegion {
- SVGA3dSurfaceId dstSid;
- uint32 dstSubResource;
- SVGA3dSurfaceId srcSid;
- uint32 srcSubResource;
- SVGA3dCopyBox box;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXPredCopyRegion;
-/* SVGA_3D_CMD_DX_PRED_COPY_REGION */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXPredCopy {
- SVGA3dSurfaceId dstSid;
- SVGA3dSurfaceId srcSid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXPredCopy; /* SVGA_3D_CMD_DX_PRED_COPY */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXPredConvertRegion {
- SVGA3dSurfaceId dstSid;
- uint32 dstSubResource;
- SVGA3dBox destBox;
- SVGA3dSurfaceId srcSid;
- uint32 srcSubResource;
- SVGA3dBox srcBox;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXPredConvertRegion; /* SVGA_3D_CMD_DX_PRED_CONVERT_REGION */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXPredConvert {
- SVGA3dSurfaceId dstSid;
- SVGA3dSurfaceId srcSid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXPredConvert; /* SVGA_3D_CMD_DX_PRED_CONVERT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBufferCopy {
- SVGA3dSurfaceId dest;
- SVGA3dSurfaceId src;
- uint32 destX;
- uint32 srcX;
- uint32 width;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBufferCopy;
-/* SVGA_3D_CMD_DX_BUFFER_COPY */
-
-/*
- * Perform a surface copy between a multisample, and a non-multisampled
- * surface.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceId dstSid;
- uint32 dstSubResource;
- SVGA3dSurfaceId srcSid;
- uint32 srcSubResource;
- SVGA3dSurfaceFormat copyFormat;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXResolveCopy; /* SVGA_3D_CMD_DX_RESOLVE_COPY */
-
-/*
- * Perform a predicated surface copy between a multisample, and a
- * non-multisampled surface.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceId dstSid;
- uint32 dstSubResource;
- SVGA3dSurfaceId srcSid;
- uint32 srcSubResource;
- SVGA3dSurfaceFormat copyFormat;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXPredResolveCopy; /* SVGA_3D_CMD_DX_PRED_RESOLVE_COPY */
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dQueryTypeUint8 type;
+ uint16 pad0;
+ SVGADXQueryDeviceState state;
+ SVGA3dDXQueryFlags flags;
+ SVGAMobId mobid;
+ uint32 offset;
+} SVGACOTableDXQueryEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineQuery {
+ SVGA3dQueryId queryId;
+ SVGA3dQueryType type;
+ SVGA3dDXQueryFlags flags;
+} SVGA3dCmdDXDefineQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyQuery {
+ SVGA3dQueryId queryId;
+} SVGA3dCmdDXDestroyQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBindQuery {
+ SVGA3dQueryId queryId;
+ SVGAMobId mobid;
+} SVGA3dCmdDXBindQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetQueryOffset {
+ SVGA3dQueryId queryId;
+ uint32 mobOffset;
+} SVGA3dCmdDXSetQueryOffset;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBeginQuery {
+ SVGA3dQueryId queryId;
+} SVGA3dCmdDXBeginQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXEndQuery {
+ SVGA3dQueryId queryId;
+} SVGA3dCmdDXEndQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXReadbackQuery {
+ SVGA3dQueryId queryId;
+} SVGA3dCmdDXReadbackQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXMoveQuery {
+ SVGA3dQueryId queryId;
+ SVGAMobId mobid;
+ uint32 mobOffset;
+} SVGA3dCmdDXMoveQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBindAllQuery {
+ uint32 cid;
+ SVGAMobId mobid;
+} SVGA3dCmdDXBindAllQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXReadbackAllQuery {
+ uint32 cid;
+} SVGA3dCmdDXReadbackAllQuery;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetPredication {
+ SVGA3dQueryId queryId;
+ uint32 predicateValue;
+} SVGA3dCmdDXSetPredication;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct MKS3dDXSOState {
+ uint32 offset;
+ uint32 intOffset;
+ uint32 vertexCount;
+ uint32 dead;
+} SVGA3dDXSOState;
+#pragma pack(pop)
+
+#define SVGA3D_DX_SO_OFFSET_APPEND ((uint32)~0u)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dSoTarget {
+ SVGA3dSurfaceId sid;
+ uint32 offset;
+ uint32 sizeInBytes;
+} SVGA3dSoTarget;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetSOTargets {
+ uint32 pad0;
+
+} SVGA3dCmdDXSetSOTargets;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dViewport {
+ float x;
+ float y;
+ float width;
+ float height;
+ float minDepth;
+ float maxDepth;
+} SVGA3dViewport;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetViewports {
+ uint32 pad0;
+
+} SVGA3dCmdDXSetViewports;
+#pragma pack(pop)
+
+#define SVGA3D_DX_MAX_VIEWPORTS 16
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetScissorRects {
+ uint32 pad0;
+
+} SVGA3dCmdDXSetScissorRects;
+#pragma pack(pop)
+
+#define SVGA3D_DX_MAX_SCISSORRECTS 16
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXClearRenderTargetView {
+ SVGA3dRenderTargetViewId renderTargetViewId;
+ SVGA3dRGBAFloat rgba;
+} SVGA3dCmdDXClearRenderTargetView;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXClearDepthStencilView {
+ uint16 flags;
+ uint16 stencil;
+ SVGA3dDepthStencilViewId depthStencilViewId;
+ float depth;
+} SVGA3dCmdDXClearDepthStencilView;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredCopyRegion {
+ SVGA3dSurfaceId dstSid;
+ uint32 dstSubResource;
+ SVGA3dSurfaceId srcSid;
+ uint32 srcSubResource;
+ SVGA3dCopyBox box;
+} SVGA3dCmdDXPredCopyRegion;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredStagingCopyRegion {
+ SVGA3dSurfaceId dstSid;
+ uint32 dstSubResource;
+ SVGA3dSurfaceId srcSid;
+ uint32 srcSubResource;
+ SVGA3dCopyBox box;
+ uint8 readback;
+ uint8 unsynchronized;
+ uint8 mustBeZero[2];
+} SVGA3dCmdDXPredStagingCopyRegion;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredCopy {
+ SVGA3dSurfaceId dstSid;
+ SVGA3dSurfaceId srcSid;
+} SVGA3dCmdDXPredCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredConvertRegion {
+ SVGA3dSurfaceId dstSid;
+ uint32 dstSubResource;
+ SVGA3dBox destBox;
+ SVGA3dSurfaceId srcSid;
+ uint32 srcSubResource;
+ SVGA3dBox srcBox;
+} SVGA3dCmdDXPredConvertRegion;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredStagingConvertRegion {
+ SVGA3dSurfaceId dstSid;
+ uint32 dstSubResource;
+ SVGA3dBox destBox;
+ SVGA3dSurfaceId srcSid;
+ uint32 srcSubResource;
+ SVGA3dBox srcBox;
+ uint8 readback;
+ uint8 unsynchronized;
+ uint8 mustBeZero[2];
+} SVGA3dCmdDXPredStagingConvertRegion;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredConvert {
+ SVGA3dSurfaceId dstSid;
+ SVGA3dSurfaceId srcSid;
+} SVGA3dCmdDXPredConvert;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredStagingConvert {
+ SVGA3dSurfaceId dstSid;
+ SVGA3dSurfaceId srcSid;
+ uint8 readback;
+ uint8 unsynchronized;
+ uint8 mustBeZero[2];
+} SVGA3dCmdDXPredStagingConvert;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBufferCopy {
+ SVGA3dSurfaceId dest;
+ SVGA3dSurfaceId src;
+ uint32 destX;
+ uint32 srcX;
+ uint32 width;
+} SVGA3dCmdDXBufferCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXStagingBufferCopy {
+ SVGA3dSurfaceId dest;
+ SVGA3dSurfaceId src;
+ uint32 destX;
+ uint32 srcX;
+ uint32 width;
+ uint8 readback;
+ uint8 unsynchronized;
+ uint8 mustBeZero[2];
+} SVGA3dCmdDXStagingBufferCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceId dstSid;
+ uint32 dstSubResource;
+ SVGA3dSurfaceId srcSid;
+ uint32 srcSubResource;
+ SVGA3dSurfaceFormat copyFormat;
+} SVGA3dCmdDXResolveCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceId dstSid;
+ uint32 dstSubResource;
+ SVGA3dSurfaceId srcSid;
+ uint32 srcSubResource;
+ SVGA3dSurfaceFormat copyFormat;
+} SVGA3dCmdDXPredResolveCopy;
+#pragma pack(pop)
typedef uint32 SVGA3dDXPresentBltMode;
-#define SVGADX_PRESENTBLT_LINEAR (1 << 0)
-#define SVGADX_PRESENTBLT_FORCE_SRC_SRGB (1 << 1)
+#define SVGADX_PRESENTBLT_LINEAR (1 << 0)
+#define SVGADX_PRESENTBLT_FORCE_SRC_SRGB (1 << 1)
#define SVGADX_PRESENTBLT_FORCE_SRC_XRBIAS (1 << 2)
-#define SVGADX_PRESENTBLT_MODE_MAX (1 << 3)
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXPresentBlt {
- SVGA3dSurfaceId srcSid;
- uint32 srcSubResource;
- SVGA3dSurfaceId dstSid;
- uint32 destSubResource;
- SVGA3dBox boxSrc;
- SVGA3dBox boxDest;
- SVGA3dDXPresentBltMode mode;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXPresentBlt; /* SVGA_3D_CMD_DX_PRESENTBLT*/
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXGenMips {
- SVGA3dShaderResourceViewId shaderResourceViewId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXGenMips; /* SVGA_3D_CMD_DX_GENMIPS */
-
-/*
- * Update a sub-resource in a guest-backed resource.
- * (Inform the device that the guest-contents have been updated.)
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXUpdateSubResource {
- SVGA3dSurfaceId sid;
- uint32 subResource;
- SVGA3dBox box;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXUpdateSubResource; /* SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE */
-
-/*
- * Readback a subresource in a guest-backed resource.
- * (Request the device to flush the dirty contents into the guest.)
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXReadbackSubResource {
- SVGA3dSurfaceId sid;
- uint32 subResource;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXReadbackSubResource; /* SVGA_3D_CMD_DX_READBACK_SUBRESOURCE */
-
-/*
- * Invalidate an image in a guest-backed surface.
- * (Notify the device that the contents can be lost.)
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXInvalidateSubResource {
- SVGA3dSurfaceId sid;
- uint32 subResource;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXInvalidateSubResource; /* SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE */
-
-
-/*
- * Raw byte wise transfer from a buffer surface into another surface
- * of the requested box. Supported if 3d is enabled and SVGA_CAP_DX
- * is set. This command does not take a context.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXTransferFromBuffer {
- SVGA3dSurfaceId srcSid;
- uint32 srcOffset;
- uint32 srcPitch;
- uint32 srcSlicePitch;
- SVGA3dSurfaceId destSid;
- uint32 destSubResource;
- SVGA3dBox destBox;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXTransferFromBuffer; /* SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER */
-
-
-#define SVGA3D_TRANSFER_TO_BUFFER_READBACK (1 << 0)
+#define SVGADX_PRESENTBLT_MODE_MAX (1 << 3)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPresentBlt {
+ SVGA3dSurfaceId srcSid;
+ uint32 srcSubResource;
+ SVGA3dSurfaceId dstSid;
+ uint32 destSubResource;
+ SVGA3dBox boxSrc;
+ SVGA3dBox boxDest;
+ SVGA3dDXPresentBltMode mode;
+} SVGA3dCmdDXPresentBlt;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXGenMips {
+ SVGA3dShaderResourceViewId shaderResourceViewId;
+} SVGA3dCmdDXGenMips;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXUpdateSubResource {
+ SVGA3dSurfaceId sid;
+ uint32 subResource;
+ SVGA3dBox box;
+} SVGA3dCmdDXUpdateSubResource;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXReadbackSubResource {
+ SVGA3dSurfaceId sid;
+ uint32 subResource;
+} SVGA3dCmdDXReadbackSubResource;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXInvalidateSubResource {
+ SVGA3dSurfaceId sid;
+ uint32 subResource;
+} SVGA3dCmdDXInvalidateSubResource;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXTransferFromBuffer {
+ SVGA3dSurfaceId srcSid;
+ uint32 srcOffset;
+ uint32 srcPitch;
+ uint32 srcSlicePitch;
+ SVGA3dSurfaceId destSid;
+ uint32 destSubResource;
+ SVGA3dBox destBox;
+} SVGA3dCmdDXTransferFromBuffer;
+#pragma pack(pop)
+
+#define SVGA3D_TRANSFER_TO_BUFFER_READBACK (1 << 0)
#define SVGA3D_TRANSFER_TO_BUFFER_FLAGS_MASK (1 << 0)
typedef uint32 SVGA3dTransferToBufferFlags;
-/*
- * Raw byte wise transfer to a buffer surface from another surface
- * of the requested box. Supported if SVGA_CAP_DX2 is set. This
- * command does not take a context.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXTransferToBuffer {
- SVGA3dSurfaceId srcSid;
- uint32 srcSubResource;
- SVGA3dBox srcBox;
- SVGA3dSurfaceId destSid;
- uint32 destOffset;
- uint32 destPitch;
- uint32 destSlicePitch;
- SVGA3dTransferToBufferFlags flags;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXTransferToBuffer; /* SVGA_3D_CMD_DX_TRANSFER_TO_BUFFER */
-
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXTransferToBuffer {
+ SVGA3dSurfaceId srcSid;
+ uint32 srcSubResource;
+ SVGA3dBox srcBox;
+ SVGA3dSurfaceId destSid;
+ uint32 destOffset;
+ uint32 destPitch;
+ uint32 destSlicePitch;
+ SVGA3dTransferToBufferFlags flags;
+} SVGA3dCmdDXTransferToBuffer;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredTransferFromBuffer {
+ SVGA3dSurfaceId srcSid;
+ uint32 srcOffset;
+ uint32 srcPitch;
+ uint32 srcSlicePitch;
+ SVGA3dSurfaceId destSid;
+ uint32 destSubResource;
+ SVGA3dBox destBox;
+} SVGA3dCmdDXPredTransferFromBuffer;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSurfaceCopyAndReadback {
+ SVGA3dSurfaceId srcSid;
+ SVGA3dSurfaceId destSid;
+ SVGA3dCopyBox box;
+} SVGA3dCmdDXSurfaceCopyAndReadback;
+#pragma pack(pop)
-/*
- * Raw byte wise transfer from a buffer surface into another surface
- * of the requested box. Supported if SVGA3D_DEVCAP_DXCONTEXT is set.
- * The context is implied from the command buffer header.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXPredTransferFromBuffer {
- SVGA3dSurfaceId srcSid;
- uint32 srcOffset;
- uint32 srcPitch;
- uint32 srcSlicePitch;
- SVGA3dSurfaceId destSid;
- uint32 destSubResource;
- SVGA3dBox destBox;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXPredTransferFromBuffer;
-/* SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER */
-
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSurfaceCopyAndReadback {
- SVGA3dSurfaceId srcSid;
- SVGA3dSurfaceId destSid;
- SVGA3dCopyBox box;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSurfaceCopyAndReadback;
-/* SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK */
-
-/*
- * SVGA_DX_HINT_NONE: Does nothing.
- *
- * SVGA_DX_HINT_PREFETCH_OBJECT:
- * SVGA_DX_HINT_PREEVICT_OBJECT:
- * Consumes a SVGAObjectRef, and hints that the host should consider
- * fetching/evicting the specified object.
- *
- * An id of SVGA3D_INVALID_ID can be used if the guest isn't sure
- * what object was affected. (For instance, if the guest knows that
- * it is about to evict a DXShader, but doesn't know precisely which one,
- * the device can still use this to help limit it's search, or track
- * how many page-outs have happened.)
- *
- * SVGA_DX_HINT_PREFETCH_COBJECT:
- * SVGA_DX_HINT_PREEVICT_COBJECT:
- * Same as the above, except they consume an SVGACObjectRef.
- */
typedef uint32 SVGADXHintId;
-#define SVGA_DX_HINT_NONE 0
-#define SVGA_DX_HINT_PREFETCH_OBJECT 1
-#define SVGA_DX_HINT_PREEVICT_OBJECT 2
-#define SVGA_DX_HINT_PREFETCH_COBJECT 3
-#define SVGA_DX_HINT_PREEVICT_COBJECT 4
-#define SVGA_DX_HINT_MAX 5
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGAObjectRef {
- SVGAOTableType type;
- uint32 id;
-}
-#include "vmware_pack_end.h"
-SVGAObjectRef;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGACObjectRef {
- SVGACOTableType type;
- uint32 cid;
- uint32 id;
-}
-#include "vmware_pack_end.h"
-SVGACObjectRef;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXHint {
- SVGADXHintId hintId;
-
- /*
- * Followed by variable sized data depending on the hintId.
- */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXHint;
-/* SVGA_3D_CMD_DX_HINT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBufferUpdate {
- SVGA3dSurfaceId sid;
- uint32 x;
- uint32 width;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBufferUpdate;
-/* SVGA_3D_CMD_DX_BUFFER_UPDATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetConstantBufferOffset {
- uint32 slot;
- uint32 offsetInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetConstantBufferOffset;
+#define SVGA_DX_HINT_NONE 0
+#define SVGA_DX_HINT_PREFETCH_OBJECT 1
+#define SVGA_DX_HINT_PREEVICT_OBJECT 2
+#define SVGA_DX_HINT_PREFETCH_COBJECT 3
+#define SVGA_DX_HINT_PREEVICT_COBJECT 4
+#define SVGA_DX_HINT_MAX 5
+
+#pragma pack(push, 1)
+typedef struct SVGAObjectRef {
+ SVGAOTableType type;
+ uint32 id;
+} SVGAObjectRef;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGACObjectRef {
+ SVGACOTableType type;
+ uint32 cid;
+ uint32 id;
+} SVGACObjectRef;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXHint {
+ SVGADXHintId hintId;
+
+} SVGA3dCmdDXHint;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBufferUpdate {
+ SVGA3dSurfaceId sid;
+ uint32 x;
+ uint32 width;
+} SVGA3dCmdDXBufferUpdate;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetConstantBufferOffset {
+ uint32 slot;
+ uint32 offsetInBytes;
+} SVGA3dCmdDXSetConstantBufferOffset;
+#pragma pack(pop)
typedef SVGA3dCmdDXSetConstantBufferOffset SVGA3dCmdDXSetVSConstantBufferOffset;
-/* SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET */
typedef SVGA3dCmdDXSetConstantBufferOffset SVGA3dCmdDXSetPSConstantBufferOffset;
-/* SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET */
typedef SVGA3dCmdDXSetConstantBufferOffset SVGA3dCmdDXSetGSConstantBufferOffset;
-/* SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET */
typedef SVGA3dCmdDXSetConstantBufferOffset SVGA3dCmdDXSetHSConstantBufferOffset;
-/* SVGA_3D_CMD_DX_SET_HS_CONSTANT_BUFFER_OFFSET */
typedef SVGA3dCmdDXSetConstantBufferOffset SVGA3dCmdDXSetDSConstantBufferOffset;
-/* SVGA_3D_CMD_DX_SET_DS_CONSTANT_BUFFER_OFFSET */
typedef SVGA3dCmdDXSetConstantBufferOffset SVGA3dCmdDXSetCSConstantBufferOffset;
-/* SVGA_3D_CMD_DX_SET_CS_CONSTANT_BUFFER_OFFSET */
-
-#define SVGA3D_BUFFEREX_SRV_RAW (1 << 0)
-#define SVGA3D_BUFFEREX_SRV_FLAGS_MAX (1 << 1)
+#define SVGA3D_BUFFEREX_SRV_RAW (1 << 0)
+#define SVGA3D_BUFFEREX_SRV_FLAGS_MAX (1 << 1)
#define SVGA3D_BUFFEREX_SRV_FLAGS_MASK (SVGA3D_BUFFEREX_SRV_FLAGS_MAX - 1)
typedef uint32 SVGA3dBufferExFlags;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- union {
- struct {
- uint32 firstElement;
- uint32 numElements;
- uint32 pad0;
- uint32 pad1;
- } buffer;
- struct {
- uint32 mostDetailedMip;
- uint32 firstArraySlice;
- uint32 mipLevels;
- uint32 arraySize;
- } tex; /* 1d, 2d, 3d, cube */
- struct {
- uint32 firstElement;
- uint32 numElements;
- SVGA3dBufferExFlags flags;
- uint32 pad0;
- } bufferex;
- };
-}
-#include "vmware_pack_end.h"
-SVGA3dShaderResourceViewDesc;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
- SVGA3dShaderResourceViewDesc desc;
- uint32 pad;
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXSRViewEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineShaderResourceView {
- SVGA3dShaderResourceViewId shaderResourceViewId;
-
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
-
- SVGA3dShaderResourceViewDesc desc;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineShaderResourceView;
-/* SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyShaderResourceView {
- SVGA3dShaderResourceViewId shaderResourceViewId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyShaderResourceView;
-/* SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dRenderTargetViewDesc {
- union {
- struct {
- uint32 firstElement;
- uint32 numElements;
- uint32 padding0;
- } buffer;
- struct {
- uint32 mipSlice;
- uint32 firstArraySlice;
- uint32 arraySize;
- } tex; /* 1d, 2d, cube */
- struct {
- uint32 mipSlice;
- uint32 firstW;
- uint32 wSize;
- } tex3D;
- };
-}
-#include "vmware_pack_end.h"
-SVGA3dRenderTargetViewDesc;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
- SVGA3dRenderTargetViewDesc desc;
- uint32 pad[2];
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXRTViewEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineRenderTargetView {
- SVGA3dRenderTargetViewId renderTargetViewId;
-
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
-
- SVGA3dRenderTargetViewDesc desc;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineRenderTargetView;
-/* SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyRenderTargetView {
- SVGA3dRenderTargetViewId renderTargetViewId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyRenderTargetView;
-/* SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW */
-
-/*
- */
-#define SVGA3D_DXDSVIEW_CREATE_READ_ONLY_DEPTH 0x01
+#pragma pack(push, 1)
+typedef struct {
+ union {
+ struct {
+ uint32 firstElement;
+ uint32 numElements;
+ uint32 pad0;
+ uint32 pad1;
+ } buffer;
+ struct {
+ uint32 mostDetailedMip;
+ uint32 firstArraySlice;
+ uint32 mipLevels;
+ uint32 arraySize;
+ } tex;
+ struct {
+ uint32 firstElement;
+ uint32 numElements;
+ SVGA3dBufferExFlags flags;
+ uint32 pad0;
+ } bufferex;
+ };
+} SVGA3dShaderResourceViewDesc;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+ SVGA3dShaderResourceViewDesc desc;
+ uint32 pad;
+} SVGACOTableDXSRViewEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineShaderResourceView {
+ SVGA3dShaderResourceViewId shaderResourceViewId;
+
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+
+ SVGA3dShaderResourceViewDesc desc;
+} SVGA3dCmdDXDefineShaderResourceView;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyShaderResourceView {
+ SVGA3dShaderResourceViewId shaderResourceViewId;
+} SVGA3dCmdDXDestroyShaderResourceView;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dRenderTargetViewDesc {
+ union {
+ struct {
+ uint32 firstElement;
+ uint32 numElements;
+ uint32 padding0;
+ } buffer;
+ struct {
+ uint32 mipSlice;
+ uint32 firstArraySlice;
+ uint32 arraySize;
+ } tex;
+ struct {
+ uint32 mipSlice;
+ uint32 firstW;
+ uint32 wSize;
+ } tex3D;
+ };
+} SVGA3dRenderTargetViewDesc;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+ SVGA3dRenderTargetViewDesc desc;
+ uint32 pad[2];
+} SVGACOTableDXRTViewEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineRenderTargetView {
+ SVGA3dRenderTargetViewId renderTargetViewId;
+
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+
+ SVGA3dRenderTargetViewDesc desc;
+} SVGA3dCmdDXDefineRenderTargetView;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyRenderTargetView {
+ SVGA3dRenderTargetViewId renderTargetViewId;
+} SVGA3dCmdDXDestroyRenderTargetView;
+#pragma pack(pop)
+
+#define SVGA3D_DXDSVIEW_CREATE_READ_ONLY_DEPTH 0x01
#define SVGA3D_DXDSVIEW_CREATE_READ_ONLY_STENCIL 0x02
-#define SVGA3D_DXDSVIEW_CREATE_FLAG_MASK 0x03
+#define SVGA3D_DXDSVIEW_CREATE_FLAG_MASK 0x03
typedef uint8 SVGA3DCreateDSViewFlags;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
- uint32 mipSlice;
- uint32 firstArraySlice;
- uint32 arraySize;
- SVGA3DCreateDSViewFlags flags;
- uint8 pad0;
- uint16 pad1;
- uint32 pad2;
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXDSViewEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineDepthStencilView {
- SVGA3dDepthStencilViewId depthStencilViewId;
-
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
- uint32 mipSlice;
- uint32 firstArraySlice;
- uint32 arraySize;
- SVGA3DCreateDSViewFlags flags;
- uint8 pad0;
- uint16 pad1;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineDepthStencilView;
-/* SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW */
-
-/*
- * Version 2 needed in order to start validating and using the flags
- * field. Unfortunately the device wasn't validating or using the
- * flags field and the driver wasn't initializing it in shipped code,
- * so a new version of the command is needed to allow that code to
- * continue to work.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineDepthStencilView_v2 {
- SVGA3dDepthStencilViewId depthStencilViewId;
-
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
- uint32 mipSlice;
- uint32 firstArraySlice;
- uint32 arraySize;
- SVGA3DCreateDSViewFlags flags;
- uint8 pad0;
- uint16 pad1;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineDepthStencilView_v2;
-/* SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW_V2 */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyDepthStencilView {
- SVGA3dDepthStencilViewId depthStencilViewId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyDepthStencilView;
-/* SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW */
-
-
-#define SVGA3D_UABUFFER_RAW (1 << 0)
-#define SVGA3D_UABUFFER_APPEND (1 << 1)
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+ uint32 mipSlice;
+ uint32 firstArraySlice;
+ uint32 arraySize;
+ SVGA3DCreateDSViewFlags flags;
+ uint8 pad0;
+ uint16 pad1;
+ uint32 pad2;
+} SVGACOTableDXDSViewEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineDepthStencilView {
+ SVGA3dDepthStencilViewId depthStencilViewId;
+
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+ uint32 mipSlice;
+ uint32 firstArraySlice;
+ uint32 arraySize;
+ SVGA3DCreateDSViewFlags flags;
+ uint8 pad0;
+ uint16 pad1;
+} SVGA3dCmdDXDefineDepthStencilView;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineDepthStencilView_v2 {
+ SVGA3dDepthStencilViewId depthStencilViewId;
+
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+ uint32 mipSlice;
+ uint32 firstArraySlice;
+ uint32 arraySize;
+ SVGA3DCreateDSViewFlags flags;
+ uint8 pad0;
+ uint16 pad1;
+} SVGA3dCmdDXDefineDepthStencilView_v2;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyDepthStencilView {
+ SVGA3dDepthStencilViewId depthStencilViewId;
+} SVGA3dCmdDXDestroyDepthStencilView;
+#pragma pack(pop)
+
+#define SVGA3D_UABUFFER_RAW (1 << 0)
+#define SVGA3D_UABUFFER_APPEND (1 << 1)
#define SVGA3D_UABUFFER_COUNTER (1 << 2)
typedef uint32 SVGA3dUABufferFlags;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- union {
- struct {
- uint32 firstElement;
- uint32 numElements;
- SVGA3dUABufferFlags flags;
- uint32 padding0;
- uint32 padding1;
- } buffer;
- struct {
- uint32 mipSlice;
- uint32 firstArraySlice;
- uint32 arraySize;
- uint32 padding0;
- uint32 padding1;
- } tex; /* 1d, 2d */
- struct {
- uint32 mipSlice;
- uint32 firstW;
- uint32 wSize;
- uint32 padding0;
- uint32 padding1;
- } tex3D;
- };
-}
-#include "vmware_pack_end.h"
-SVGA3dUAViewDesc;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
- SVGA3dUAViewDesc desc;
- uint32 structureCount;
- uint32 pad[7];
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXUAViewEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineUAView {
- SVGA3dUAViewId uaViewId;
-
- SVGA3dSurfaceId sid;
- SVGA3dSurfaceFormat format;
- SVGA3dResourceType resourceDimension;
-
- SVGA3dUAViewDesc desc;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineUAView;
-/* SVGA_3D_CMD_DX_DEFINE_UA_VIEW */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyUAView {
- SVGA3dUAViewId uaViewId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyUAView;
-/* SVGA_3D_CMD_DX_DESTROY_UA_VIEW */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXClearUAViewUint {
- SVGA3dUAViewId uaViewId;
- SVGA3dRGBAUint32 value;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXClearUAViewUint;
-/* SVGA_3D_CMD_DX_CLEAR_UA_VIEW_UINT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXClearUAViewFloat {
- SVGA3dUAViewId uaViewId;
- SVGA3dRGBAFloat value;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXClearUAViewFloat;
-/* SVGA_3D_CMD_DX_CLEAR_UA_VIEW_FLOAT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXCopyStructureCount {
- SVGA3dUAViewId srcUAViewId;
- SVGA3dSurfaceId destSid;
- uint32 destByteOffset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXCopyStructureCount;
-/* SVGA_3D_CMD_DX_COPY_STRUCTURE_COUNT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetStructureCount {
- SVGA3dUAViewId uaViewId;
- uint32 structureCount;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetStructureCount;
-/* SVGA_3D_CMD_DX_SET_STRUCTURE_COUNT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetUAViews {
- uint32 uavSpliceIndex;
- /* Followed by a variable number of SVGA3dUAViewId's. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetUAViews; /* SVGA_3D_CMD_DX_SET_UA_VIEWS */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetCSUAViews {
- uint32 startIndex;
- /* Followed by a variable number of SVGA3dUAViewId's. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetCSUAViews; /* SVGA_3D_CMD_DX_SET_CS_UA_VIEWS */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dInputElementDesc {
- uint32 inputSlot;
- uint32 alignedByteOffset;
- SVGA3dSurfaceFormat format;
- SVGA3dInputClassification inputSlotClass;
- uint32 instanceDataStepRate;
- uint32 inputRegister;
-}
-#include "vmware_pack_end.h"
-SVGA3dInputElementDesc;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 elid;
- uint32 numDescs;
- SVGA3dInputElementDesc descs[32];
- uint32 pad[62];
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXElementLayoutEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineElementLayout {
- SVGA3dElementLayoutId elementLayoutId;
- /* Followed by a variable number of SVGA3dInputElementDesc's. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineElementLayout;
-/* SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyElementLayout {
- SVGA3dElementLayoutId elementLayoutId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyElementLayout;
-/* SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT */
-
+#pragma pack(push, 1)
+typedef struct {
+ union {
+ struct {
+ uint32 firstElement;
+ uint32 numElements;
+ SVGA3dUABufferFlags flags;
+ uint32 padding0;
+ uint32 padding1;
+ } buffer;
+ struct {
+ uint32 mipSlice;
+ uint32 firstArraySlice;
+ uint32 arraySize;
+ uint32 padding0;
+ uint32 padding1;
+ } tex;
+ struct {
+ uint32 mipSlice;
+ uint32 firstW;
+ uint32 wSize;
+ uint32 padding0;
+ uint32 padding1;
+ } tex3D;
+ };
+} SVGA3dUAViewDesc;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+ SVGA3dUAViewDesc desc;
+ uint32 structureCount;
+ uint32 pad[7];
+} SVGACOTableDXUAViewEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineUAView {
+ SVGA3dUAViewId uaViewId;
+
+ SVGA3dSurfaceId sid;
+ SVGA3dSurfaceFormat format;
+ SVGA3dResourceType resourceDimension;
+
+ SVGA3dUAViewDesc desc;
+} SVGA3dCmdDXDefineUAView;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyUAView {
+ SVGA3dUAViewId uaViewId;
+} SVGA3dCmdDXDestroyUAView;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXClearUAViewUint {
+ SVGA3dUAViewId uaViewId;
+ SVGA3dRGBAUint32 value;
+} SVGA3dCmdDXClearUAViewUint;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXClearUAViewFloat {
+ SVGA3dUAViewId uaViewId;
+ SVGA3dRGBAFloat value;
+} SVGA3dCmdDXClearUAViewFloat;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXCopyStructureCount {
+ SVGA3dUAViewId srcUAViewId;
+ SVGA3dSurfaceId destSid;
+ uint32 destByteOffset;
+} SVGA3dCmdDXCopyStructureCount;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetStructureCount {
+ SVGA3dUAViewId uaViewId;
+ uint32 structureCount;
+} SVGA3dCmdDXSetStructureCount;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetUAViews {
+ uint32 uavSpliceIndex;
+
+} SVGA3dCmdDXSetUAViews;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetCSUAViews {
+ uint32 startIndex;
+
+} SVGA3dCmdDXSetCSUAViews;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dInputElementDesc {
+ uint32 inputSlot;
+ uint32 alignedByteOffset;
+ SVGA3dSurfaceFormat format;
+ SVGA3dInputClassification inputSlotClass;
+ uint32 instanceDataStepRate;
+ uint32 inputRegister;
+} SVGA3dInputElementDesc;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 elid;
+ uint32 numDescs;
+ SVGA3dInputElementDesc descs[32];
+ uint32 pad[62];
+} SVGACOTableDXElementLayoutEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineElementLayout {
+ SVGA3dElementLayoutId elementLayoutId;
+
+} SVGA3dCmdDXDefineElementLayout;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyElementLayout {
+ SVGA3dElementLayoutId elementLayoutId;
+} SVGA3dCmdDXDestroyElementLayout;
+#pragma pack(pop)
#define SVGA3D_DX_MAX_RENDER_TARGETS 8
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dDXBlendStatePerRT {
- uint8 blendEnable;
- uint8 srcBlend;
- uint8 destBlend;
- uint8 blendOp;
- uint8 srcBlendAlpha;
- uint8 destBlendAlpha;
- uint8 blendOpAlpha;
- SVGA3dColorWriteEnable renderTargetWriteMask;
- uint8 logicOpEnable;
- uint8 logicOp;
- uint16 pad0;
-}
-#include "vmware_pack_end.h"
-SVGA3dDXBlendStatePerRT;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint8 alphaToCoverageEnable;
- uint8 independentBlendEnable;
- uint16 pad0;
- SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
- uint32 pad1[7];
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXBlendStateEntry;
-
-/*
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineBlendState {
- SVGA3dBlendStateId blendId;
- uint8 alphaToCoverageEnable;
- uint8 independentBlendEnable;
- uint16 pad0;
- SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineBlendState; /* SVGA_3D_CMD_DX_DEFINE_BLEND_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyBlendState {
- SVGA3dBlendStateId blendId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyBlendState; /* SVGA_3D_CMD_DX_DESTROY_BLEND_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint8 depthEnable;
- SVGA3dDepthWriteMask depthWriteMask;
- SVGA3dComparisonFunc depthFunc;
- uint8 stencilEnable;
- uint8 frontEnable;
- uint8 backEnable;
- uint8 stencilReadMask;
- uint8 stencilWriteMask;
-
- uint8 frontStencilFailOp;
- uint8 frontStencilDepthFailOp;
- uint8 frontStencilPassOp;
- SVGA3dComparisonFunc frontStencilFunc;
-
- uint8 backStencilFailOp;
- uint8 backStencilDepthFailOp;
- uint8 backStencilPassOp;
- SVGA3dComparisonFunc backStencilFunc;
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXDepthStencilEntry;
-
-/*
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineDepthStencilState {
- SVGA3dDepthStencilStateId depthStencilId;
-
- uint8 depthEnable;
- SVGA3dDepthWriteMask depthWriteMask;
- SVGA3dComparisonFunc depthFunc;
- uint8 stencilEnable;
- uint8 frontEnable;
- uint8 backEnable;
- uint8 stencilReadMask;
- uint8 stencilWriteMask;
-
- uint8 frontStencilFailOp;
- uint8 frontStencilDepthFailOp;
- uint8 frontStencilPassOp;
- SVGA3dComparisonFunc frontStencilFunc;
-
- uint8 backStencilFailOp;
- uint8 backStencilDepthFailOp;
- uint8 backStencilPassOp;
- SVGA3dComparisonFunc backStencilFunc;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineDepthStencilState;
-/* SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyDepthStencilState {
- SVGA3dDepthStencilStateId depthStencilId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyDepthStencilState;
-/* SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint8 fillMode;
- SVGA3dCullMode cullMode;
- uint8 frontCounterClockwise;
- uint8 provokingVertexLast;
- int32 depthBias;
- float depthBiasClamp;
- float slopeScaledDepthBias;
- uint8 depthClipEnable;
- uint8 scissorEnable;
- SVGA3dMultisampleRastEnable multisampleEnable;
- uint8 antialiasedLineEnable;
- float lineWidth;
- uint8 lineStippleEnable;
- uint8 lineStippleFactor;
- uint16 lineStipplePattern;
- uint8 forcedSampleCount;
- uint8 mustBeZero[3];
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXRasterizerStateEntry;
-
-/*
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineRasterizerState {
- SVGA3dRasterizerStateId rasterizerId;
-
- uint8 fillMode;
- SVGA3dCullMode cullMode;
- uint8 frontCounterClockwise;
- uint8 provokingVertexLast;
- int32 depthBias;
- float depthBiasClamp;
- float slopeScaledDepthBias;
- uint8 depthClipEnable;
- uint8 scissorEnable;
- SVGA3dMultisampleRastEnable multisampleEnable;
- uint8 antialiasedLineEnable;
- float lineWidth;
- uint8 lineStippleEnable;
- uint8 lineStippleFactor;
- uint16 lineStipplePattern;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineRasterizerState;
-/* SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyRasterizerState {
- SVGA3dRasterizerStateId rasterizerId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyRasterizerState;
-/* SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGA3dFilter filter;
- uint8 addressU;
- uint8 addressV;
- uint8 addressW;
- uint8 pad0;
- float mipLODBias;
- uint8 maxAnisotropy;
- SVGA3dComparisonFunc comparisonFunc;
- uint16 pad1;
- SVGA3dRGBAFloat borderColor;
- float minLOD;
- float maxLOD;
- uint32 pad2[6];
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXSamplerEntry;
-
-/*
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineSamplerState {
- SVGA3dSamplerId samplerId;
- SVGA3dFilter filter;
- uint8 addressU;
- uint8 addressV;
- uint8 addressW;
- uint8 pad0;
- float mipLODBias;
- uint8 maxAnisotropy;
- SVGA3dComparisonFunc comparisonFunc;
- uint16 pad1;
- SVGA3dRGBAFloat borderColor;
- float minLOD;
- float maxLOD;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineSamplerState; /* SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroySamplerState {
- SVGA3dSamplerId samplerId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroySamplerState; /* SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE */
-
-
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED 0
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_POSITION 1
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_CLIP_DISTANCE 2
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_CULL_DISTANCE 3
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_RENDER_TARGET_ARRAY_INDEX 4
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_VIEWPORT_ARRAY_INDEX 5
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_VERTEX_ID 6
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_PRIMITIVE_ID 7
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_INSTANCE_ID 8
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_IS_FRONT_FACE 9
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_SAMPLE_INDEX 10
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR 11
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR 12
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR 13
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR 14
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR 15
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR 16
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR 17
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR 18
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR 19
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_INSIDE_TESSFACTOR 20
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DETAIL_TESSFACTOR 21
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DENSITY_TESSFACTOR 22
-#define SVGADX_SIGNATURE_SEMANTIC_NAME_MAX 23
+#pragma pack(push, 1)
+typedef struct SVGA3dDXBlendStatePerRT {
+ uint8 blendEnable;
+ uint8 srcBlend;
+ uint8 destBlend;
+ uint8 blendOp;
+ uint8 srcBlendAlpha;
+ uint8 destBlendAlpha;
+ uint8 blendOpAlpha;
+ SVGA3dColorWriteEnable renderTargetWriteMask;
+ uint8 logicOpEnable;
+ uint8 logicOp;
+ uint16 pad0;
+} SVGA3dDXBlendStatePerRT;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint8 alphaToCoverageEnable;
+ uint8 independentBlendEnable;
+ uint16 pad0;
+ SVGA3dDXBlendStatePerRT perRT[SVGA3D_DX_MAX_RENDER_TARGETS];
+ uint32 pad1[7];
+} SVGACOTableDXBlendStateEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineBlendState {
+ SVGA3dBlendStateId blendId;
+ uint8 alphaToCoverageEnable;
+ uint8 independentBlendEnable;
+ uint16 pad0;
+ SVGA3dDXBlendStatePerRT perRT[SVGA3D_DX_MAX_RENDER_TARGETS];
+} SVGA3dCmdDXDefineBlendState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyBlendState {
+ SVGA3dBlendStateId blendId;
+} SVGA3dCmdDXDestroyBlendState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint8 depthEnable;
+ SVGA3dDepthWriteMask depthWriteMask;
+ SVGA3dComparisonFunc depthFunc;
+ uint8 stencilEnable;
+ uint8 frontEnable;
+ uint8 backEnable;
+ uint8 stencilReadMask;
+ uint8 stencilWriteMask;
+
+ uint8 frontStencilFailOp;
+ uint8 frontStencilDepthFailOp;
+ uint8 frontStencilPassOp;
+ SVGA3dComparisonFunc frontStencilFunc;
+
+ uint8 backStencilFailOp;
+ uint8 backStencilDepthFailOp;
+ uint8 backStencilPassOp;
+ SVGA3dComparisonFunc backStencilFunc;
+} SVGACOTableDXDepthStencilEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineDepthStencilState {
+ SVGA3dDepthStencilStateId depthStencilId;
+
+ uint8 depthEnable;
+ SVGA3dDepthWriteMask depthWriteMask;
+ SVGA3dComparisonFunc depthFunc;
+ uint8 stencilEnable;
+ uint8 frontEnable;
+ uint8 backEnable;
+ uint8 stencilReadMask;
+ uint8 stencilWriteMask;
+
+ uint8 frontStencilFailOp;
+ uint8 frontStencilDepthFailOp;
+ uint8 frontStencilPassOp;
+ SVGA3dComparisonFunc frontStencilFunc;
+
+ uint8 backStencilFailOp;
+ uint8 backStencilDepthFailOp;
+ uint8 backStencilPassOp;
+ SVGA3dComparisonFunc backStencilFunc;
+} SVGA3dCmdDXDefineDepthStencilState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyDepthStencilState {
+ SVGA3dDepthStencilStateId depthStencilId;
+} SVGA3dCmdDXDestroyDepthStencilState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint8 fillMode;
+ SVGA3dCullMode cullMode;
+ uint8 frontCounterClockwise;
+ uint8 provokingVertexLast;
+ int32 depthBias;
+ float depthBiasClamp;
+ float slopeScaledDepthBias;
+ uint8 depthClipEnable;
+ uint8 scissorEnable;
+ SVGA3dMultisampleRastEnable multisampleEnable;
+ uint8 antialiasedLineEnable;
+ float lineWidth;
+ uint8 lineStippleEnable;
+ uint8 lineStippleFactor;
+ uint16 lineStipplePattern;
+ uint8 forcedSampleCount;
+ uint8 mustBeZero[3];
+} SVGACOTableDXRasterizerStateEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineRasterizerState {
+ SVGA3dRasterizerStateId rasterizerId;
+
+ uint8 fillMode;
+ SVGA3dCullMode cullMode;
+ uint8 frontCounterClockwise;
+ uint8 provokingVertexLast;
+ int32 depthBias;
+ float depthBiasClamp;
+ float slopeScaledDepthBias;
+ uint8 depthClipEnable;
+ uint8 scissorEnable;
+ SVGA3dMultisampleRastEnable multisampleEnable;
+ uint8 antialiasedLineEnable;
+ float lineWidth;
+ uint8 lineStippleEnable;
+ uint8 lineStippleFactor;
+ uint16 lineStipplePattern;
+} SVGA3dCmdDXDefineRasterizerState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineRasterizerState_v2 {
+ SVGA3dRasterizerStateId rasterizerId;
+
+ uint8 fillMode;
+ SVGA3dCullMode cullMode;
+ uint8 frontCounterClockwise;
+ uint8 provokingVertexLast;
+ int32 depthBias;
+ float depthBiasClamp;
+ float slopeScaledDepthBias;
+ uint8 depthClipEnable;
+ uint8 scissorEnable;
+ SVGA3dMultisampleRastEnable multisampleEnable;
+ uint8 antialiasedLineEnable;
+ float lineWidth;
+ uint8 lineStippleEnable;
+ uint8 lineStippleFactor;
+ uint16 lineStipplePattern;
+ uint32 forcedSampleCount;
+} SVGA3dCmdDXDefineRasterizerState_v2;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyRasterizerState {
+ SVGA3dRasterizerStateId rasterizerId;
+} SVGA3dCmdDXDestroyRasterizerState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGA3dFilter filter;
+ uint8 addressU;
+ uint8 addressV;
+ uint8 addressW;
+ uint8 pad0;
+ float mipLODBias;
+ uint8 maxAnisotropy;
+ SVGA3dComparisonFunc comparisonFunc;
+ uint16 pad1;
+ SVGA3dRGBAFloat borderColor;
+ float minLOD;
+ float maxLOD;
+ uint32 pad2[6];
+} SVGACOTableDXSamplerEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineSamplerState {
+ SVGA3dSamplerId samplerId;
+ SVGA3dFilter filter;
+ uint8 addressU;
+ uint8 addressV;
+ uint8 addressW;
+ uint8 pad0;
+ float mipLODBias;
+ uint8 maxAnisotropy;
+ SVGA3dComparisonFunc comparisonFunc;
+ uint16 pad1;
+ SVGA3dRGBAFloat borderColor;
+ float minLOD;
+ float maxLOD;
+} SVGA3dCmdDXDefineSamplerState;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroySamplerState {
+ SVGA3dSamplerId samplerId;
+} SVGA3dCmdDXDestroySamplerState;
+#pragma pack(pop)
+
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_UNDEFINED 0
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_POSITION 1
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_CLIP_DISTANCE 2
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_CULL_DISTANCE 3
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_RENDER_TARGET_ARRAY_INDEX 4
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_VIEWPORT_ARRAY_INDEX 5
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_VERTEX_ID 6
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_PRIMITIVE_ID 7
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_INSTANCE_ID 8
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_IS_FRONT_FACE 9
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_SAMPLE_INDEX 10
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR 11
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR 12
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR 13
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR 14
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR 15
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR 16
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR 17
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR 18
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR 19
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_TRI_INSIDE_TESSFACTOR 20
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DETAIL_TESSFACTOR 21
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_FINAL_LINE_DENSITY_TESSFACTOR 22
+#define SVGADX_SIGNATURE_SEMANTIC_NAME_MAX 23
typedef uint32 SVGA3dDXSignatureSemanticName;
#define SVGADX_SIGNATURE_REGISTER_COMPONENT_UNKNOWN 0
@@ -1670,398 +1394,331 @@ typedef uint32 SVGA3dDXSignatureRegisterComponentType;
#define SVGADX_SIGNATURE_MIN_PRECISION_DEFAULT 0
typedef uint32 SVGA3dDXSignatureMinPrecision;
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dDXSignatureEntry {
- uint32 registerIndex;
- SVGA3dDXSignatureSemanticName semanticName;
- uint32 mask; /* Lower 4 bits represent X, Y, Z, W channels */
- SVGA3dDXSignatureRegisterComponentType componentType;
- SVGA3dDXSignatureMinPrecision minPrecision;
-}
-#include "vmware_pack_end.h"
-SVGA3dDXShaderSignatureEntry;
+#pragma pack(push, 1)
+typedef struct SVGA3dDXSignatureEntry {
+ uint32 registerIndex;
+ SVGA3dDXSignatureSemanticName semanticName;
+ uint32 mask;
+ SVGA3dDXSignatureRegisterComponentType componentType;
+ SVGA3dDXSignatureMinPrecision minPrecision;
+} SVGA3dDXShaderSignatureEntry;
+#pragma pack(pop)
#define SVGADX_SIGNATURE_HEADER_VERSION_0 0x08a92d12
-/*
- * The SVGA3dDXSignatureHeader structure is added after the shader
- * body in the mob that is bound to the shader. It is followed by the
- * specified number of SVGA3dDXSignatureEntry structures for each of
- * the three types of signatures in the order (input, output, patch
- * constants).
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dDXSignatureHeader {
- uint32 headerVersion;
- uint32 numInputSignatures;
- uint32 numOutputSignatures;
- uint32 numPatchConstantSignatures;
-}
-#include "vmware_pack_end.h"
-SVGA3dDXShaderSignatureHeader;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineShader {
- SVGA3dShaderId shaderId;
- SVGA3dShaderType type;
- uint32 sizeInBytes; /* Number of bytes of shader text. */
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineShader; /* SVGA_3D_CMD_DX_DEFINE_SHADER */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGACOTableDXShaderEntry {
- SVGA3dShaderType type;
- uint32 sizeInBytes;
- uint32 offsetInBytes;
- SVGAMobId mobid;
- uint32 pad[4];
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXShaderEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyShader {
- SVGA3dShaderId shaderId;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyShader; /* SVGA_3D_CMD_DX_DESTROY_SHADER */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBindShader {
- uint32 cid;
- uint32 shid;
- SVGAMobId mobid;
- uint32 offsetInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBindShader; /* SVGA_3D_CMD_DX_BIND_SHADER */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBindAllShader {
- uint32 cid;
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBindAllShader; /* SVGA_3D_CMD_DX_BIND_ALL_SHADER */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXCondBindAllShader {
- uint32 cid;
- SVGAMobId testMobid;
- SVGAMobId mobid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXCondBindAllShader; /* SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER */
+#pragma pack(push, 1)
+typedef struct SVGA3dDXSignatureHeader {
+ uint32 headerVersion;
+ uint32 numInputSignatures;
+ uint32 numOutputSignatures;
+ uint32 numPatchConstantSignatures;
+} SVGA3dDXShaderSignatureHeader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineShader {
+ SVGA3dShaderId shaderId;
+ SVGA3dShaderType type;
+ uint32 sizeInBytes;
+} SVGA3dCmdDXDefineShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGACOTableDXShaderEntry {
+ SVGA3dShaderType type;
+ uint32 sizeInBytes;
+ uint32 offsetInBytes;
+ SVGAMobId mobid;
+ uint32 pad[4];
+} SVGACOTableDXShaderEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyShader {
+ SVGA3dShaderId shaderId;
+} SVGA3dCmdDXDestroyShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBindShader {
+ uint32 cid;
+ uint32 shid;
+ SVGAMobId mobid;
+ uint32 offsetInBytes;
+} SVGA3dCmdDXBindShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBindAllShader {
+ uint32 cid;
+ SVGAMobId mobid;
+} SVGA3dCmdDXBindAllShader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXCondBindAllShader {
+ uint32 cid;
+ SVGAMobId testMobid;
+ SVGAMobId mobid;
+} SVGA3dCmdDXCondBindAllShader;
+#pragma pack(pop)
-/*
- * The maximum number of streamout decl's in each streamout entry.
- */
#define SVGA3D_MAX_DX10_STREAMOUT_DECLS 64
#define SVGA3D_MAX_STREAMOUT_DECLS 512
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dStreamOutputDeclarationEntry {
- uint32 outputSlot;
- uint32 registerIndex;
- uint8 registerMask;
- uint8 pad0;
- uint16 pad1;
- uint32 stream;
-}
-#include "vmware_pack_end.h"
-SVGA3dStreamOutputDeclarationEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGAOTableStreamOutputEntry {
- uint32 numOutputStreamEntries;
- SVGA3dStreamOutputDeclarationEntry decl[SVGA3D_MAX_DX10_STREAMOUT_DECLS];
- uint32 streamOutputStrideInBytes[SVGA3D_DX_MAX_SOTARGETS];
- uint32 rasterizedStream;
- uint32 numOutputStreamStrides;
- uint32 mobid;
- uint32 offsetInBytes;
- uint8 usesMob;
- uint8 pad0;
- uint16 pad1;
- uint32 pad2[246];
-}
-#include "vmware_pack_end.h"
-SVGACOTableDXStreamOutputEntry;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineStreamOutput {
- SVGA3dStreamOutputId soid;
- uint32 numOutputStreamEntries;
- SVGA3dStreamOutputDeclarationEntry decl[SVGA3D_MAX_DX10_STREAMOUT_DECLS];
- uint32 streamOutputStrideInBytes[SVGA3D_DX_MAX_SOTARGETS];
- uint32 rasterizedStream;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineStreamOutput; /* SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT */
-
-/*
- * Version 2 needed in order to start validating and using the
- * rasterizedStream field. Unfortunately the device wasn't validating
- * or using this field and the driver wasn't initializing it in shipped
- * code, so a new version of the command is needed to allow that code
- * to continue to work. Also added new numOutputStreamStrides field.
- */
+#pragma pack(push, 1)
+typedef struct SVGA3dStreamOutputDeclarationEntry {
+ uint32 outputSlot;
+ uint32 registerIndex;
+ uint8 registerMask;
+ uint8 pad0;
+ uint16 pad1;
+ uint32 stream;
+} SVGA3dStreamOutputDeclarationEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGAOTableStreamOutputEntry {
+ uint32 numOutputStreamEntries;
+ SVGA3dStreamOutputDeclarationEntry decl[SVGA3D_MAX_DX10_STREAMOUT_DECLS];
+ uint32 streamOutputStrideInBytes[SVGA3D_DX_MAX_SOTARGETS];
+ uint32 rasterizedStream;
+ uint32 numOutputStreamStrides;
+ uint32 mobid;
+ uint32 offsetInBytes;
+ uint8 usesMob;
+ uint8 pad0;
+ uint16 pad1;
+ uint32 pad2[246];
+} SVGACOTableDXStreamOutputEntry;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineStreamOutput {
+ SVGA3dStreamOutputId soid;
+ uint32 numOutputStreamEntries;
+ SVGA3dStreamOutputDeclarationEntry decl[SVGA3D_MAX_DX10_STREAMOUT_DECLS];
+ uint32 streamOutputStrideInBytes[SVGA3D_DX_MAX_SOTARGETS];
+ uint32 rasterizedStream;
+} SVGA3dCmdDXDefineStreamOutput;
+#pragma pack(pop)
#define SVGA3D_DX_SO_NO_RASTERIZED_STREAM 0xFFFFFFFF
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDefineStreamOutputWithMob {
- SVGA3dStreamOutputId soid;
- uint32 numOutputStreamEntries;
- uint32 numOutputStreamStrides;
- uint32 streamOutputStrideInBytes[SVGA3D_DX_MAX_SOTARGETS];
- uint32 rasterizedStream;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDefineStreamOutputWithMob;
-/* SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXBindStreamOutput {
- SVGA3dStreamOutputId soid;
- uint32 mobid;
- uint32 offsetInBytes;
- uint32 sizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXBindStreamOutput; /* SVGA_3D_CMD_DX_BIND_STREAMOUTPUT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXDestroyStreamOutput {
- SVGA3dStreamOutputId soid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXDestroyStreamOutput; /* SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetStreamOutput {
- SVGA3dStreamOutputId soid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetStreamOutput; /* SVGA_3D_CMD_DX_SET_STREAMOUTPUT */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetMinLOD {
- SVGA3dSurfaceId sid;
- float minLOD;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetMinLOD; /* SVGA_3D_CMD_DX_SET_MIN_LOD */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint64 value;
- uint32 mobId;
- uint32 mobOffset;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXMobFence64; /* SVGA_3D_CMD_DX_MOB_FENCE_64 */
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDefineStreamOutputWithMob {
+ SVGA3dStreamOutputId soid;
+ uint32 numOutputStreamEntries;
+ uint32 numOutputStreamStrides;
+ uint32 streamOutputStrideInBytes[SVGA3D_DX_MAX_SOTARGETS];
+ uint32 rasterizedStream;
+} SVGA3dCmdDXDefineStreamOutputWithMob;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXBindStreamOutput {
+ SVGA3dStreamOutputId soid;
+ uint32 mobid;
+ uint32 offsetInBytes;
+ uint32 sizeInBytes;
+} SVGA3dCmdDXBindStreamOutput;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXDestroyStreamOutput {
+ SVGA3dStreamOutputId soid;
+} SVGA3dCmdDXDestroyStreamOutput;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetStreamOutput {
+ SVGA3dStreamOutputId soid;
+} SVGA3dCmdDXSetStreamOutput;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetMinLOD {
+ SVGA3dSurfaceId sid;
+ float minLOD;
+} SVGA3dCmdDXSetMinLOD;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint64 value;
+ uint32 mobId;
+ uint32 mobOffset;
+} SVGA3dCmdDXMobFence64;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXSetCOTable {
+ uint32 cid;
+ uint32 mobid;
+ SVGACOTableType type;
+ uint32 validSizeInBytes;
+} SVGA3dCmdDXSetCOTable;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXGrowCOTable {
+ uint32 cid;
+ uint32 mobid;
+ SVGACOTableType type;
+ uint32 validSizeInBytes;
+} SVGA3dCmdDXGrowCOTable;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXReadbackCOTable {
+ uint32 cid;
+ SVGACOTableType type;
+} SVGA3dCmdDXReadbackCOTable;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXCopyCOTableIntoMob {
+ uint32 cid;
+ SVGACOTableType type;
+ uint32 mobid;
+} SVGA3dCmdDXCopyCOTableIntoMob;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXPredStagingCopy {
+ SVGA3dSurfaceId dstSid;
+ SVGA3dSurfaceId srcSid;
+ uint8 readback;
+ uint8 unsynchronized;
+ uint8 mustBeZero[2];
+
+} SVGA3dCmdDXPredStagingCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCmdDXStagingCopy {
+ SVGA3dSurfaceId dstSid;
+ SVGA3dSurfaceId srcSid;
+ uint8 readback;
+ uint8 unsynchronized;
+ uint8 mustBeZero[2];
+
+} SVGA3dCmdDXStagingCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCOTableData {
+ uint32 mobid;
+} SVGA3dCOTableData;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dBufferBinding {
+ uint32 bufferId;
+ uint32 stride;
+ uint32 offset;
+} SVGA3dBufferBinding;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dConstantBufferBinding {
+ uint32 sid;
+ uint32 offsetInBytes;
+ uint32 sizeInBytes;
+} SVGA3dConstantBufferBinding;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGADXInputAssemblyMobFormat {
+ uint32 layoutId;
+ SVGA3dBufferBinding vertexBuffers[SVGA3D_DX_MAX_VERTEXBUFFERS];
+ uint32 indexBufferSid;
+ uint32 pad;
+ uint32 indexBufferOffset;
+ uint32 indexBufferFormat;
+ uint32 topology;
+} SVGADXInputAssemblyMobFormat;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGADXContextMobFormat {
+ SVGADXInputAssemblyMobFormat inputAssembly;
+
+ struct {
+ uint32 blendStateId;
+ uint32 blendFactor[4];
+ uint32 sampleMask;
+ uint32 depthStencilStateId;
+ uint32 stencilRef;
+ uint32 rasterizerStateId;
+ uint32 depthStencilViewId;
+ uint32 renderTargetViewIds[SVGA3D_DX_MAX_RENDER_TARGETS];
+ } renderState;
+
+ uint32 pad0[8];
+
+ struct {
+ uint32 targets[SVGA3D_DX_MAX_SOTARGETS];
+ uint32 soid;
+ } streamOut;
+
+ uint32 pad1[10];
+
+ uint32 uavSpliceIndex;
+
+ uint8 numViewports;
+ uint8 numScissorRects;
+ uint16 pad2[1];
+
+ uint32 pad3[3];
+
+ SVGA3dViewport viewports[SVGA3D_DX_MAX_VIEWPORTS];
+ uint32 pad4[32];
+
+ SVGASignedRect scissorRects[SVGA3D_DX_MAX_SCISSORRECTS];
+ uint32 pad5[64];
+
+ struct {
+ uint32 queryID;
+ uint32 value;
+ } predication;
+
+ SVGAMobId shaderIfaceMobid;
+ uint32 shaderIfaceOffset;
+ struct {
+ uint32 shaderId;
+ SVGA3dConstantBufferBinding
+ constantBuffers[SVGA3D_DX_MAX_CONSTBUFFERS];
+ uint32 shaderResources[SVGA3D_DX_MAX_SRVIEWS];
+ uint32 samplers[SVGA3D_DX_MAX_SAMPLERS];
+ } shaderState[SVGA3D_NUM_SHADERTYPE];
+ uint32 pad6[26];
+
+ SVGA3dQueryId queryID[SVGA3D_MAX_QUERY];
+
+ SVGA3dCOTableData cotables[SVGA_COTABLE_MAX];
+
+ uint32 pad7[64];
+
+ uint32 uaViewIds[SVGA3D_DX11_1_MAX_UAVIEWS];
+ uint32 csuaViewIds[SVGA3D_DX11_1_MAX_UAVIEWS];
+
+ uint32 pad8[188];
+} SVGADXContextMobFormat;
+#pragma pack(pop)
-/*
- * SVGA3dCmdSetCOTable --
- *
- * This command allows the guest to bind a mob to a context-object table.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXSetCOTable {
- uint32 cid;
- uint32 mobid;
- SVGACOTableType type;
- uint32 validSizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXSetCOTable; /* SVGA_3D_CMD_DX_SET_COTABLE */
+#define SVGA3D_DX_MAX_CLASS_INSTANCES_PADDED 256
-/*
- * Guests using SVGA_3D_CMD_DX_GROW_COTABLE are promising that
- * the new COTable contains the same contents as the old one, except possibly
- * for some new invalid entries at the end.
- *
- * If there is an old cotable mob bound, it also has to still be valid.
- *
- * (Otherwise, guests should use the DXSetCOTableBase command.)
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXGrowCOTable {
- uint32 cid;
- uint32 mobid;
- SVGACOTableType type;
- uint32 validSizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXGrowCOTable; /* SVGA_3D_CMD_DX_GROW_COTABLE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXReadbackCOTable {
- uint32 cid;
- SVGACOTableType type;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXReadbackCOTable; /* SVGA_3D_CMD_DX_READBACK_COTABLE */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCOTableData {
- uint32 mobid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCOTableData;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dBufferBinding {
- uint32 bufferId;
- uint32 stride;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGA3dBufferBinding;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dConstantBufferBinding {
- uint32 sid;
- uint32 offsetInBytes;
- uint32 sizeInBytes;
-}
-#include "vmware_pack_end.h"
-SVGA3dConstantBufferBinding;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGADXInputAssemblyMobFormat {
- uint32 layoutId;
- SVGA3dBufferBinding vertexBuffers[SVGA3D_DX_MAX_VERTEXBUFFERS];
- uint32 indexBufferSid;
- uint32 pad;
- uint32 indexBufferOffset;
- uint32 indexBufferFormat;
- uint32 topology;
-}
-#include "vmware_pack_end.h"
-SVGADXInputAssemblyMobFormat;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGADXContextMobFormat {
- SVGADXInputAssemblyMobFormat inputAssembly;
-
- struct {
- uint32 blendStateId;
- uint32 blendFactor[4];
- uint32 sampleMask;
- uint32 depthStencilStateId;
- uint32 stencilRef;
- uint32 rasterizerStateId;
- uint32 depthStencilViewId;
- uint32 renderTargetViewIds[SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS];
- } renderState;
-
- uint32 pad0[8];
-
- struct {
- uint32 targets[SVGA3D_DX_MAX_SOTARGETS];
- uint32 soid;
- } streamOut;
-
- uint32 pad1[10];
-
- uint32 uavSpliceIndex;
-
- uint8 numViewports;
- uint8 numScissorRects;
- uint16 pad2[1];
-
- uint32 pad3[3];
-
- SVGA3dViewport viewports[SVGA3D_DX_MAX_VIEWPORTS];
- uint32 pad4[32];
-
- SVGASignedRect scissorRects[SVGA3D_DX_MAX_SCISSORRECTS];
- uint32 pad5[64];
-
- struct {
- uint32 queryID;
- uint32 value;
- } predication;
-
- SVGAMobId shaderIfaceMobid;
- uint32 shaderIfaceOffset;
- struct {
- uint32 shaderId;
- SVGA3dConstantBufferBinding constantBuffers[SVGA3D_DX_MAX_CONSTBUFFERS];
- uint32 shaderResources[SVGA3D_DX_MAX_SRVIEWS];
- uint32 samplers[SVGA3D_DX_MAX_SAMPLERS];
- } shaderState[SVGA3D_NUM_SHADERTYPE];
- uint32 pad6[26];
-
- SVGA3dQueryId queryID[SVGA3D_MAX_QUERY];
-
- SVGA3dCOTableData cotables[SVGA_COTABLE_MAX];
-
- uint32 pad7[64];
-
- uint32 uaViewIds[SVGA3D_DX11_1_MAX_UAVIEWS];
- uint32 csuaViewIds[SVGA3D_DX11_1_MAX_UAVIEWS];
-
- uint32 pad8[188];
-}
-#include "vmware_pack_end.h"
-SVGADXContextMobFormat;
+#pragma pack(push, 1)
+typedef struct SVGADXShaderIfaceMobFormat {
+ struct {
+ uint32 numClassInstances;
+ uint32 iface[SVGA3D_DX_MAX_CLASS_INSTANCES_PADDED];
+ SVGA3dIfaceData data[SVGA3D_DX_MAX_CLASS_INSTANCES_PADDED];
+ } shaderIfaceState[SVGA3D_NUM_SHADERTYPE];
-/*
- * There is conflicting documentation on max class instances (253 vs 256). The
- * lower value is the one used throughout the device, but since mob format is
- * more involved to increase if needed, conservatively use the higher one here.
- */
-#define SVGA3D_DX_MAX_CLASS_INSTANCES_PADDED 256
+ uint32 pad0[1018];
+} SVGADXShaderIfaceMobFormat;
+#pragma pack(pop)
-typedef
-#include "vmware_pack_begin.h"
-struct SVGADXShaderIfaceMobFormat {
- struct {
- uint32 numClassInstances;
- uint32 iface[SVGA3D_DX_MAX_CLASS_INSTANCES_PADDED];
- SVGA3dIfaceData data[SVGA3D_DX_MAX_CLASS_INSTANCES_PADDED];
- } shaderIfaceState[SVGA3D_NUM_SHADERTYPE];
-
- uint32 pad0[1018];
-}
-#include "vmware_pack_end.h"
-SVGADXShaderIfaceMobFormat;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCmdDXTempSetContext {
- uint32 dxcid;
-}
-#include "vmware_pack_end.h"
-SVGA3dCmdDXTempSetContext; /* SVGA_3D_CMD_DX_TEMP_SET_CONTEXT */
-
-#endif /* _SVGA3D_DX_H_ */
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_limits.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_limits.h
index f4375a41b3aa..35494a728c7a 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_limits.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_limits.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
- * Copyright 2007-2019 VMware, Inc.
+ * Copyright 2012-2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -27,104 +27,59 @@
/*
* svga3d_limits.h --
*
- * SVGA 3d hardware limits
+ * SVGA 3d hardware limits
*/
-#ifndef _SVGA3D_LIMITS_H_
-#define _SVGA3D_LIMITS_H_
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-#include "includeCheck.h"
+#ifndef _SVGA3D_LIMITS_H_
+#define _SVGA3D_LIMITS_H_
-#define SVGA3D_NUM_CLIPPLANES 6
-#define SVGA3D_MAX_CONTEXT_IDS 256
-#define SVGA3D_MAX_SURFACE_IDS (32 * 1024)
+#define SVGA3D_HB_MAX_CONTEXT_IDS 256
+#define SVGA3D_HB_MAX_SURFACE_IDS (32 * 1024)
-/*
- * While there are separate bind-points for RenderTargetViews and
- * UnorderedAccessViews in a DXContext, there is in fact one shared
- * semantic space that the guest-driver can use on any given draw call.
- * So there are really only 8 slots that can be spilt up between them, with the
- * spliceIndex controlling where the UAV's sit in the collapsed array.
- */
-#define SVGA3D_MAX_RENDER_TARGETS 8
-#define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS (SVGA3D_MAX_RENDER_TARGETS)
-#define SVGA3D_MAX_UAVIEWS 8
-#define SVGA3D_DX11_1_MAX_UAVIEWS 64
+#define SVGA3D_DX_MAX_RENDER_TARGETS 8
+#define SVGA3D_DX11_MAX_UAVIEWS 8
+#define SVGA3D_DX11_1_MAX_UAVIEWS 64
+#define SVGA3D_MAX_UAVIEWS (SVGA3D_DX11_1_MAX_UAVIEWS)
+#define SVGA3D_DX11_MAX_SIMULTANEOUS_RTUAV (SVGA3D_DX11_MAX_UAVIEWS)
+#define SVGA3D_DX11_1_MAX_SIMULTANEOUS_RTUAV (SVGA3D_DX11_1_MAX_UAVIEWS)
+#define SVGA3D_MAX_SIMULTANEOUS_RTUAV (SVGA3D_MAX_UAVIEWS)
-/*
- * Maximum canonical size of a surface in host-backed mode (pre-GBObjects).
- */
#define SVGA3D_HB_MAX_SURFACE_SIZE MBYTES_2_BYTES(128)
-/*
- * Maximum ID a shader can be assigned on a given context.
- */
-#define SVGA3D_MAX_SHADERIDS 5000
-/*
- * Maximum number of shaders of a given type that can be defined
- * (including all contexts).
- */
-#define SVGA3D_MAX_SIMULTANEOUS_SHADERS 20000
+#define SVGA3D_MAX_SHADERIDS 5000
-#define SVGA3D_NUM_TEXTURE_UNITS 32
-#define SVGA3D_NUM_LIGHTS 8
+#define SVGA3D_MAX_SIMULTANEOUS_SHADERS 20000
-#define SVGA3D_MAX_VIDEOPROCESSOR_SAMPLERS 32
+#define SVGA3D_NUM_TEXTURE_UNITS 32
+#define SVGA3D_NUM_LIGHTS 8
+
+#define SVGA3D_MAX_VIDEOPROCESSOR_SAMPLERS 32
-/*
- * Maximum size in dwords of shader text the SVGA device will allow.
- * Currently 8 MB.
- */
#define SVGA3D_MAX_SHADER_MEMORY_BYTES (8 * 1024 * 1024)
-#define SVGA3D_MAX_SHADER_MEMORY (SVGA3D_MAX_SHADER_MEMORY_BYTES / \
- sizeof(uint32))
+#define SVGA3D_MAX_SHADER_MEMORY \
+ (SVGA3D_MAX_SHADER_MEMORY_BYTES / sizeof(uint32))
-/*
- * The maximum value of threadGroupCount in each dimension
- */
#define SVGA3D_MAX_SHADER_THREAD_GROUPS 65535
-#define SVGA3D_MAX_CLIP_PLANES 6
+#define SVGA3D_MAX_CLIP_PLANES 6
-/*
- * This is the limit to the number of fixed-function texture
- * transforms and texture coordinates we can support. It does *not*
- * correspond to the number of texture image units (samplers) we
- * support!
- */
#define SVGA3D_MAX_TEXTURE_COORDS 8
-/*
- * Number of faces in a cubemap.
- */
#define SVGA3D_MAX_SURFACE_FACES 6
-/*
- * Maximum number of array indexes in a GB surface (with DX enabled).
- */
#define SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE 512
#define SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE 2048
#define SVGA3D_MAX_SURFACE_ARRAYSIZE SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE
-/*
- * The maximum number of vertex arrays we're guaranteed to support in
- * SVGA_3D_CMD_DRAWPRIMITIVES.
- */
-#define SVGA3D_MAX_VERTEX_ARRAYS 32
+#define SVGA3D_MAX_VERTEX_ARRAYS 32
-/*
- * The maximum number of primitive ranges we're guaranteed to support
- * in SVGA_3D_CMD_DRAWPRIMITIVES.
- */
#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32
-/*
- * The maximum number of samples that can be contained in a surface.
- */
#define SVGA3D_MAX_SAMPLES 8
-#endif /* _SVGA3D_LIMITS_H_ */
+#define SVGA3D_MIN_SBX_DATA_SIZE (GBYTES_2_BYTES(1))
+#define SVGA3D_MAX_SBX_DATA_SIZE (GBYTES_2_BYTES(4))
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_reg.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_reg.h
index bdfc404c91e3..988d8509c472 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_reg.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_reg.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
* Copyright 1998-2015 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -27,17 +27,13 @@
/*
* svga3d_reg.h --
*
- * SVGA 3d hardware definitions
+ * SVGA 3d hardware definitions
*/
-#ifndef _SVGA3D_REG_H_
-#define _SVGA3D_REG_H_
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-#include "includeCheck.h"
+#ifndef _SVGA3D_REG_H_
+#define _SVGA3D_REG_H_
#include "svga_reg.h"
@@ -47,5 +43,4 @@
#include "svga3d_dx.h"
#include "svga3d_devcaps.h"
-
-#endif /* _SVGA3D_REG_H_ */
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h
index 127eaf0a0a58..7d98fc48414e 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h
@@ -1,1667 +1,1561 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
-/**************************************************************************
+/**********************************************************
+ * Copyright 2008-2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
- * Copyright 2008-2015 VMware, Inc., Palo Alto, CA., USA
+ * 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:
*
- * 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, sub license, 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 above copyright notice and this permission notice (including the
- * next paragraph) 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.
*
- * 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
- *
- **************************************************************************/
+ **********************************************************/
/*
* svga3d_surfacedefs.h --
*
- * Surface definitions and inlineable utilities for SVGA3d.
+ * Surface definitions for SVGA3d.
*/
+
+
#ifndef _SVGA3D_SURFACEDEFS_H_
#define _SVGA3D_SURFACEDEFS_H_
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_MODULE
-#include "includeCheck.h"
+#include "svga3d_types.h"
-#include <linux/kernel.h>
-#include <drm/vmwgfx_drm.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
-#include "svga3d_reg.h"
+struct SVGAUseCaps;
-#define surf_size_struct struct drm_vmw_size
+#if defined(_WIN32) && !defined(__GNUC__)
-/*
- * enum svga3d_block_desc - describes generic properties about formats.
- */
-enum svga3d_block_desc {
- /* Nothing special can be said about this format. */
- SVGA3DBLOCKDESC_NONE = 0,
+#define STATIC_CONST __declspec(selectany) extern const
+#else
+#define STATIC_CONST static const
+#endif
+
+typedef enum SVGA3dBlockDesc {
- /* Format contains Blue/U data */
- SVGA3DBLOCKDESC_BLUE = 1 << 0,
- SVGA3DBLOCKDESC_W = 1 << 0,
- SVGA3DBLOCKDESC_BUMP_L = 1 << 0,
+ SVGA3DBLOCKDESC_NONE = 0,
- /* Format contains Green/V data */
- SVGA3DBLOCKDESC_GREEN = 1 << 1,
- SVGA3DBLOCKDESC_V = 1 << 1,
+ SVGA3DBLOCKDESC_BLUE = 1 << 0,
+ SVGA3DBLOCKDESC_W = 1 << 0,
+ SVGA3DBLOCKDESC_BUMP_L = 1 << 0,
- /* Format contains Red/W/Luminance data */
- SVGA3DBLOCKDESC_RED = 1 << 2,
- SVGA3DBLOCKDESC_U = 1 << 2,
- SVGA3DBLOCKDESC_LUMINANCE = 1 << 2,
+ SVGA3DBLOCKDESC_GREEN = 1 << 1,
+ SVGA3DBLOCKDESC_V = 1 << 1,
- /* Format contains Alpha/Q data */
- SVGA3DBLOCKDESC_ALPHA = 1 << 3,
- SVGA3DBLOCKDESC_Q = 1 << 3,
+ SVGA3DBLOCKDESC_RED = 1 << 2,
+ SVGA3DBLOCKDESC_U = 1 << 2,
+ SVGA3DBLOCKDESC_LUMINANCE = 1 << 2,
- /* Format is a buffer */
- SVGA3DBLOCKDESC_BUFFER = 1 << 4,
+ SVGA3DBLOCKDESC_ALPHA = 1 << 3,
+ SVGA3DBLOCKDESC_Q = 1 << 3,
- /* Format is compressed */
- SVGA3DBLOCKDESC_COMPRESSED = 1 << 5,
+ SVGA3DBLOCKDESC_BUFFER = 1 << 4,
- /* Format uses IEEE floating point */
- SVGA3DBLOCKDESC_FP = 1 << 6,
+ SVGA3DBLOCKDESC_COMPRESSED = 1 << 5,
- /* Three separate blocks store data. */
- SVGA3DBLOCKDESC_PLANAR_YUV = 1 << 7,
+ SVGA3DBLOCKDESC_FP = 1 << 6,
+
+ SVGA3DBLOCKDESC_PLANAR_YUV = 1 << 7,
- /* 2 planes of Y, UV, e.g., NV12. */
SVGA3DBLOCKDESC_2PLANAR_YUV = 1 << 8,
- /* 3 planes of separate Y, U, V, e.g., YV12. */
SVGA3DBLOCKDESC_3PLANAR_YUV = 1 << 9,
- /* Block with a stencil channel */
- SVGA3DBLOCKDESC_STENCIL = 1 << 11,
-
- /* Typeless format */
- SVGA3DBLOCKDESC_TYPELESS = 1 << 12,
-
- /* Channels are signed integers */
- SVGA3DBLOCKDESC_SINT = 1 << 13,
-
- /* Channels are unsigned integers */
- SVGA3DBLOCKDESC_UINT = 1 << 14,
-
- /* Channels are normalized (when sampling) */
- SVGA3DBLOCKDESC_NORM = 1 << 15,
-
- /* Channels are in SRGB */
- SVGA3DBLOCKDESC_SRGB = 1 << 16,
-
- /* Shared exponent */
- SVGA3DBLOCKDESC_EXP = 1 << 17,
-
- /* Format contains color data. */
- SVGA3DBLOCKDESC_COLOR = 1 << 18,
- /* Format contains depth data. */
- SVGA3DBLOCKDESC_DEPTH = 1 << 19,
- /* Format contains bump data. */
- SVGA3DBLOCKDESC_BUMP = 1 << 20,
-
- /* Format contains YUV video data. */
- SVGA3DBLOCKDESC_YUV_VIDEO = 1 << 21,
-
- /* For mixed unsigned/signed formats. */
- SVGA3DBLOCKDESC_MIXED = 1 << 22,
-
- /* For distingushing CxV8U8. */
- SVGA3DBLOCKDESC_CX = 1 << 23,
-
- /* Different compressed format groups. */
- SVGA3DBLOCKDESC_BC1 = 1 << 24,
- SVGA3DBLOCKDESC_BC2 = 1 << 25,
- SVGA3DBLOCKDESC_BC3 = 1 << 26,
- SVGA3DBLOCKDESC_BC4 = 1 << 27,
- SVGA3DBLOCKDESC_BC5 = 1 << 28,
- SVGA3DBLOCKDESC_BC6H = 1 << 29,
- SVGA3DBLOCKDESC_BC7 = 1 << 30,
-
- SVGA3DBLOCKDESC_A_UINT = SVGA3DBLOCKDESC_ALPHA |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_A_UNORM = SVGA3DBLOCKDESC_A_UINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_R_UINT = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_R_UNORM = SVGA3DBLOCKDESC_R_UINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_R_SINT = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_SINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_R_SNORM = SVGA3DBLOCKDESC_R_SINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_G_UINT = SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RG_UINT = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RG_UNORM = SVGA3DBLOCKDESC_RG_UINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_RG_SINT = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_SINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RG_SNORM = SVGA3DBLOCKDESC_RG_SINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_RGB_UINT = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_BLUE |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RGB_SINT = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_BLUE |
- SVGA3DBLOCKDESC_SINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RGB_UNORM = SVGA3DBLOCKDESC_RGB_UINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_RGB_UNORM_SRGB = SVGA3DBLOCKDESC_RGB_UNORM |
- SVGA3DBLOCKDESC_SRGB,
- SVGA3DBLOCKDESC_RGBA_UINT = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_BLUE |
- SVGA3DBLOCKDESC_ALPHA |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RGBA_UNORM = SVGA3DBLOCKDESC_RGBA_UINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_RGBA_UNORM_SRGB = SVGA3DBLOCKDESC_RGBA_UNORM |
- SVGA3DBLOCKDESC_SRGB,
- SVGA3DBLOCKDESC_RGBA_SINT = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_BLUE |
- SVGA3DBLOCKDESC_ALPHA |
- SVGA3DBLOCKDESC_SINT |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RGBA_SNORM = SVGA3DBLOCKDESC_RGBA_SINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_RGBA_FP = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_BLUE |
- SVGA3DBLOCKDESC_ALPHA |
- SVGA3DBLOCKDESC_FP |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_UV = SVGA3DBLOCKDESC_U |
- SVGA3DBLOCKDESC_V |
- SVGA3DBLOCKDESC_BUMP,
- SVGA3DBLOCKDESC_UVL = SVGA3DBLOCKDESC_UV |
- SVGA3DBLOCKDESC_BUMP_L |
- SVGA3DBLOCKDESC_MIXED |
- SVGA3DBLOCKDESC_BUMP,
- SVGA3DBLOCKDESC_UVW = SVGA3DBLOCKDESC_UV |
- SVGA3DBLOCKDESC_W |
- SVGA3DBLOCKDESC_BUMP,
- SVGA3DBLOCKDESC_UVWA = SVGA3DBLOCKDESC_UVW |
- SVGA3DBLOCKDESC_ALPHA |
- SVGA3DBLOCKDESC_MIXED |
- SVGA3DBLOCKDESC_BUMP,
- SVGA3DBLOCKDESC_UVWQ = SVGA3DBLOCKDESC_U |
- SVGA3DBLOCKDESC_V |
- SVGA3DBLOCKDESC_W |
- SVGA3DBLOCKDESC_Q |
- SVGA3DBLOCKDESC_BUMP,
- SVGA3DBLOCKDESC_L_UNORM = SVGA3DBLOCKDESC_LUMINANCE |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_NORM |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_LA_UNORM = SVGA3DBLOCKDESC_LUMINANCE |
- SVGA3DBLOCKDESC_ALPHA |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_NORM |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_R_FP = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_FP |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RG_FP = SVGA3DBLOCKDESC_R_FP |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RGB_FP = SVGA3DBLOCKDESC_RG_FP |
- SVGA3DBLOCKDESC_BLUE |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_YUV = SVGA3DBLOCKDESC_YUV_VIDEO |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_AYUV = SVGA3DBLOCKDESC_ALPHA |
- SVGA3DBLOCKDESC_YUV_VIDEO |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_RGB_EXP = SVGA3DBLOCKDESC_RED |
- SVGA3DBLOCKDESC_GREEN |
- SVGA3DBLOCKDESC_BLUE |
- SVGA3DBLOCKDESC_EXP |
- SVGA3DBLOCKDESC_COLOR,
-
- SVGA3DBLOCKDESC_COMP_TYPELESS = SVGA3DBLOCKDESC_COMPRESSED |
- SVGA3DBLOCKDESC_TYPELESS,
- SVGA3DBLOCKDESC_COMP_UNORM = SVGA3DBLOCKDESC_COMPRESSED |
- SVGA3DBLOCKDESC_UINT |
- SVGA3DBLOCKDESC_NORM |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_COMP_SNORM = SVGA3DBLOCKDESC_COMPRESSED |
- SVGA3DBLOCKDESC_SINT |
- SVGA3DBLOCKDESC_NORM |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_COMP_UNORM_SRGB = SVGA3DBLOCKDESC_COMP_UNORM |
- SVGA3DBLOCKDESC_SRGB,
- SVGA3DBLOCKDESC_BC1_COMP_TYPELESS = SVGA3DBLOCKDESC_BC1 |
- SVGA3DBLOCKDESC_COMP_TYPELESS,
- SVGA3DBLOCKDESC_BC1_COMP_UNORM = SVGA3DBLOCKDESC_BC1 |
- SVGA3DBLOCKDESC_COMP_UNORM,
- SVGA3DBLOCKDESC_BC1_COMP_UNORM_SRGB = SVGA3DBLOCKDESC_BC1_COMP_UNORM |
- SVGA3DBLOCKDESC_SRGB,
- SVGA3DBLOCKDESC_BC2_COMP_TYPELESS = SVGA3DBLOCKDESC_BC2 |
- SVGA3DBLOCKDESC_COMP_TYPELESS,
- SVGA3DBLOCKDESC_BC2_COMP_UNORM = SVGA3DBLOCKDESC_BC2 |
- SVGA3DBLOCKDESC_COMP_UNORM,
- SVGA3DBLOCKDESC_BC2_COMP_UNORM_SRGB = SVGA3DBLOCKDESC_BC2_COMP_UNORM |
- SVGA3DBLOCKDESC_SRGB,
- SVGA3DBLOCKDESC_BC3_COMP_TYPELESS = SVGA3DBLOCKDESC_BC3 |
- SVGA3DBLOCKDESC_COMP_TYPELESS,
- SVGA3DBLOCKDESC_BC3_COMP_UNORM = SVGA3DBLOCKDESC_BC3 |
- SVGA3DBLOCKDESC_COMP_UNORM,
- SVGA3DBLOCKDESC_BC3_COMP_UNORM_SRGB = SVGA3DBLOCKDESC_BC3_COMP_UNORM |
- SVGA3DBLOCKDESC_SRGB,
- SVGA3DBLOCKDESC_BC4_COMP_TYPELESS = SVGA3DBLOCKDESC_BC4 |
- SVGA3DBLOCKDESC_COMP_TYPELESS,
- SVGA3DBLOCKDESC_BC4_COMP_UNORM = SVGA3DBLOCKDESC_BC4 |
- SVGA3DBLOCKDESC_COMP_UNORM,
- SVGA3DBLOCKDESC_BC4_COMP_SNORM = SVGA3DBLOCKDESC_BC4 |
- SVGA3DBLOCKDESC_COMP_SNORM,
- SVGA3DBLOCKDESC_BC5_COMP_TYPELESS = SVGA3DBLOCKDESC_BC5 |
- SVGA3DBLOCKDESC_COMP_TYPELESS,
- SVGA3DBLOCKDESC_BC5_COMP_UNORM = SVGA3DBLOCKDESC_BC5 |
- SVGA3DBLOCKDESC_COMP_UNORM,
- SVGA3DBLOCKDESC_BC5_COMP_SNORM = SVGA3DBLOCKDESC_BC5 |
- SVGA3DBLOCKDESC_COMP_SNORM,
- SVGA3DBLOCKDESC_BC6H_COMP_TYPELESS = SVGA3DBLOCKDESC_BC6H |
- SVGA3DBLOCKDESC_COMP_TYPELESS,
- SVGA3DBLOCKDESC_BC6H_COMP_UF16 = SVGA3DBLOCKDESC_BC6H |
- SVGA3DBLOCKDESC_COMPRESSED,
- SVGA3DBLOCKDESC_BC6H_COMP_SF16 = SVGA3DBLOCKDESC_BC6H |
- SVGA3DBLOCKDESC_COMPRESSED,
- SVGA3DBLOCKDESC_BC7_COMP_TYPELESS = SVGA3DBLOCKDESC_BC7 |
- SVGA3DBLOCKDESC_COMP_TYPELESS,
- SVGA3DBLOCKDESC_BC7_COMP_UNORM = SVGA3DBLOCKDESC_BC7 |
- SVGA3DBLOCKDESC_COMP_UNORM,
- SVGA3DBLOCKDESC_BC7_COMP_UNORM_SRGB = SVGA3DBLOCKDESC_BC7_COMP_UNORM |
- SVGA3DBLOCKDESC_SRGB,
-
- SVGA3DBLOCKDESC_NV12 = SVGA3DBLOCKDESC_YUV_VIDEO |
- SVGA3DBLOCKDESC_PLANAR_YUV |
- SVGA3DBLOCKDESC_2PLANAR_YUV |
- SVGA3DBLOCKDESC_COLOR,
- SVGA3DBLOCKDESC_YV12 = SVGA3DBLOCKDESC_YUV_VIDEO |
- SVGA3DBLOCKDESC_PLANAR_YUV |
- SVGA3DBLOCKDESC_3PLANAR_YUV |
- SVGA3DBLOCKDESC_COLOR,
-
- SVGA3DBLOCKDESC_DEPTH_UINT = SVGA3DBLOCKDESC_DEPTH |
- SVGA3DBLOCKDESC_UINT,
- SVGA3DBLOCKDESC_DEPTH_UNORM = SVGA3DBLOCKDESC_DEPTH_UINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_DS = SVGA3DBLOCKDESC_DEPTH |
- SVGA3DBLOCKDESC_STENCIL,
- SVGA3DBLOCKDESC_DS_UINT = SVGA3DBLOCKDESC_DEPTH |
- SVGA3DBLOCKDESC_STENCIL |
- SVGA3DBLOCKDESC_UINT,
- SVGA3DBLOCKDESC_DS_UNORM = SVGA3DBLOCKDESC_DS_UINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_DEPTH_FP = SVGA3DBLOCKDESC_DEPTH |
- SVGA3DBLOCKDESC_FP,
-
- SVGA3DBLOCKDESC_UV_UINT = SVGA3DBLOCKDESC_UV |
- SVGA3DBLOCKDESC_UINT,
- SVGA3DBLOCKDESC_UV_SNORM = SVGA3DBLOCKDESC_UV |
- SVGA3DBLOCKDESC_SINT |
- SVGA3DBLOCKDESC_NORM,
- SVGA3DBLOCKDESC_UVCX_SNORM = SVGA3DBLOCKDESC_UV_SNORM |
- SVGA3DBLOCKDESC_CX,
+ SVGA3DBLOCKDESC_STENCIL = 1 << 11,
+
+ SVGA3DBLOCKDESC_TYPELESS = 1 << 12,
+
+ SVGA3DBLOCKDESC_SINT = 1 << 13,
+
+ SVGA3DBLOCKDESC_UINT = 1 << 14,
+
+ SVGA3DBLOCKDESC_NORM = 1 << 15,
+
+ SVGA3DBLOCKDESC_SRGB = 1 << 16,
+
+ SVGA3DBLOCKDESC_EXP = 1 << 17,
+
+ SVGA3DBLOCKDESC_COLOR = 1 << 18,
+
+ SVGA3DBLOCKDESC_DEPTH = 1 << 19,
+
+ SVGA3DBLOCKDESC_BUMP = 1 << 20,
+
+ SVGA3DBLOCKDESC_YUV_VIDEO = 1 << 21,
+
+ SVGA3DBLOCKDESC_MIXED = 1 << 22,
+
+ SVGA3DBLOCKDESC_CX = 1 << 23,
+
+ SVGA3DBLOCKDESC_BC1 = 1 << 24,
+ SVGA3DBLOCKDESC_BC2 = 1 << 25,
+ SVGA3DBLOCKDESC_BC3 = 1 << 26,
+ SVGA3DBLOCKDESC_BC4 = 1 << 27,
+ SVGA3DBLOCKDESC_BC5 = 1 << 28,
+ SVGA3DBLOCKDESC_BC6H = 1 << 29,
+ SVGA3DBLOCKDESC_BC7 = 1 << 30,
+ SVGA3DBLOCKDESC_COMPRESSED_MASK =
+ SVGA3DBLOCKDESC_BC1 | SVGA3DBLOCKDESC_BC2 |
+ SVGA3DBLOCKDESC_BC3 | SVGA3DBLOCKDESC_BC4 |
+ SVGA3DBLOCKDESC_BC5 | SVGA3DBLOCKDESC_BC6H |
+ SVGA3DBLOCKDESC_BC7,
+
+ SVGA3DBLOCKDESC_A_UINT = SVGA3DBLOCKDESC_ALPHA | SVGA3DBLOCKDESC_UINT |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_A_UNORM = SVGA3DBLOCKDESC_A_UINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_R_UINT = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_UINT |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_R_UNORM = SVGA3DBLOCKDESC_R_UINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_R_SINT = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_SINT |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_R_SNORM = SVGA3DBLOCKDESC_R_SINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_G_UINT = SVGA3DBLOCKDESC_GREEN | SVGA3DBLOCKDESC_UINT |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RG_UINT = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_UINT | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RG_UNORM =
+ SVGA3DBLOCKDESC_RG_UINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_RG_SINT = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_SINT | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RG_SNORM =
+ SVGA3DBLOCKDESC_RG_SINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_RGB_UINT = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_BLUE | SVGA3DBLOCKDESC_UINT |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RGB_SINT = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_BLUE | SVGA3DBLOCKDESC_SINT |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RGB_UNORM =
+ SVGA3DBLOCKDESC_RGB_UINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_RGB_UNORM_SRGB =
+ SVGA3DBLOCKDESC_RGB_UNORM | SVGA3DBLOCKDESC_SRGB,
+ SVGA3DBLOCKDESC_RGBA_UINT =
+ SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_BLUE | SVGA3DBLOCKDESC_ALPHA |
+ SVGA3DBLOCKDESC_UINT | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RGBA_UNORM =
+ SVGA3DBLOCKDESC_RGBA_UINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_RGBA_UNORM_SRGB =
+ SVGA3DBLOCKDESC_RGBA_UNORM | SVGA3DBLOCKDESC_SRGB,
+ SVGA3DBLOCKDESC_RGBA_SINT =
+ SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_BLUE | SVGA3DBLOCKDESC_ALPHA |
+ SVGA3DBLOCKDESC_SINT | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RGBA_SNORM =
+ SVGA3DBLOCKDESC_RGBA_SINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_RGBA_FP = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_BLUE | SVGA3DBLOCKDESC_ALPHA |
+ SVGA3DBLOCKDESC_FP | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_UV =
+ SVGA3DBLOCKDESC_U | SVGA3DBLOCKDESC_V | SVGA3DBLOCKDESC_BUMP,
+ SVGA3DBLOCKDESC_UVL = SVGA3DBLOCKDESC_UV | SVGA3DBLOCKDESC_BUMP_L |
+ SVGA3DBLOCKDESC_MIXED | SVGA3DBLOCKDESC_BUMP,
+ SVGA3DBLOCKDESC_UVW =
+ SVGA3DBLOCKDESC_UV | SVGA3DBLOCKDESC_W | SVGA3DBLOCKDESC_BUMP,
+ SVGA3DBLOCKDESC_UVWA = SVGA3DBLOCKDESC_UVW | SVGA3DBLOCKDESC_ALPHA |
+ SVGA3DBLOCKDESC_MIXED | SVGA3DBLOCKDESC_BUMP,
+ SVGA3DBLOCKDESC_UVWQ = SVGA3DBLOCKDESC_U | SVGA3DBLOCKDESC_V |
+ SVGA3DBLOCKDESC_W | SVGA3DBLOCKDESC_Q |
+ SVGA3DBLOCKDESC_BUMP,
+ SVGA3DBLOCKDESC_L_UNORM = SVGA3DBLOCKDESC_LUMINANCE |
+ SVGA3DBLOCKDESC_UINT | SVGA3DBLOCKDESC_NORM |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_LA_UNORM = SVGA3DBLOCKDESC_LUMINANCE |
+ SVGA3DBLOCKDESC_ALPHA |
+ SVGA3DBLOCKDESC_UINT | SVGA3DBLOCKDESC_NORM |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_R_FP = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_FP |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RG_FP = SVGA3DBLOCKDESC_R_FP | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RGB_FP = SVGA3DBLOCKDESC_RG_FP | SVGA3DBLOCKDESC_BLUE |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_YUV = SVGA3DBLOCKDESC_YUV_VIDEO | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_AYUV = SVGA3DBLOCKDESC_ALPHA |
+ SVGA3DBLOCKDESC_YUV_VIDEO |
+ SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_RGB_EXP = SVGA3DBLOCKDESC_RED | SVGA3DBLOCKDESC_GREEN |
+ SVGA3DBLOCKDESC_BLUE | SVGA3DBLOCKDESC_EXP |
+ SVGA3DBLOCKDESC_COLOR,
+
+ SVGA3DBLOCKDESC_COMP_TYPELESS =
+ SVGA3DBLOCKDESC_COMPRESSED | SVGA3DBLOCKDESC_TYPELESS,
+ SVGA3DBLOCKDESC_COMP_UNORM =
+ SVGA3DBLOCKDESC_COMPRESSED | SVGA3DBLOCKDESC_UINT |
+ SVGA3DBLOCKDESC_NORM | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_COMP_SNORM =
+ SVGA3DBLOCKDESC_COMPRESSED | SVGA3DBLOCKDESC_SINT |
+ SVGA3DBLOCKDESC_NORM | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_COMP_UNORM_SRGB =
+ SVGA3DBLOCKDESC_COMP_UNORM | SVGA3DBLOCKDESC_SRGB,
+ SVGA3DBLOCKDESC_BC1_COMP_TYPELESS =
+ SVGA3DBLOCKDESC_BC1 | SVGA3DBLOCKDESC_COMP_TYPELESS,
+ SVGA3DBLOCKDESC_BC1_COMP_UNORM =
+ SVGA3DBLOCKDESC_BC1 | SVGA3DBLOCKDESC_COMP_UNORM,
+ SVGA3DBLOCKDESC_BC1_COMP_UNORM_SRGB =
+ SVGA3DBLOCKDESC_BC1_COMP_UNORM | SVGA3DBLOCKDESC_SRGB,
+ SVGA3DBLOCKDESC_BC2_COMP_TYPELESS =
+ SVGA3DBLOCKDESC_BC2 | SVGA3DBLOCKDESC_COMP_TYPELESS,
+ SVGA3DBLOCKDESC_BC2_COMP_UNORM =
+ SVGA3DBLOCKDESC_BC2 | SVGA3DBLOCKDESC_COMP_UNORM,
+ SVGA3DBLOCKDESC_BC2_COMP_UNORM_SRGB =
+ SVGA3DBLOCKDESC_BC2_COMP_UNORM | SVGA3DBLOCKDESC_SRGB,
+ SVGA3DBLOCKDESC_BC3_COMP_TYPELESS =
+ SVGA3DBLOCKDESC_BC3 | SVGA3DBLOCKDESC_COMP_TYPELESS,
+ SVGA3DBLOCKDESC_BC3_COMP_UNORM =
+ SVGA3DBLOCKDESC_BC3 | SVGA3DBLOCKDESC_COMP_UNORM,
+ SVGA3DBLOCKDESC_BC3_COMP_UNORM_SRGB =
+ SVGA3DBLOCKDESC_BC3_COMP_UNORM | SVGA3DBLOCKDESC_SRGB,
+ SVGA3DBLOCKDESC_BC4_COMP_TYPELESS =
+ SVGA3DBLOCKDESC_BC4 | SVGA3DBLOCKDESC_COMP_TYPELESS,
+ SVGA3DBLOCKDESC_BC4_COMP_UNORM =
+ SVGA3DBLOCKDESC_BC4 | SVGA3DBLOCKDESC_COMP_UNORM,
+ SVGA3DBLOCKDESC_BC4_COMP_SNORM =
+ SVGA3DBLOCKDESC_BC4 | SVGA3DBLOCKDESC_COMP_SNORM,
+ SVGA3DBLOCKDESC_BC5_COMP_TYPELESS =
+ SVGA3DBLOCKDESC_BC5 | SVGA3DBLOCKDESC_COMP_TYPELESS,
+ SVGA3DBLOCKDESC_BC5_COMP_UNORM =
+ SVGA3DBLOCKDESC_BC5 | SVGA3DBLOCKDESC_COMP_UNORM,
+ SVGA3DBLOCKDESC_BC5_COMP_SNORM =
+ SVGA3DBLOCKDESC_BC5 | SVGA3DBLOCKDESC_COMP_SNORM,
+ SVGA3DBLOCKDESC_BC6H_COMP_TYPELESS =
+ SVGA3DBLOCKDESC_BC6H | SVGA3DBLOCKDESC_COMP_TYPELESS,
+ SVGA3DBLOCKDESC_BC6H_COMP_UF16 =
+ SVGA3DBLOCKDESC_BC6H | SVGA3DBLOCKDESC_COMPRESSED,
+ SVGA3DBLOCKDESC_BC6H_COMP_SF16 =
+ SVGA3DBLOCKDESC_BC6H | SVGA3DBLOCKDESC_COMPRESSED,
+ SVGA3DBLOCKDESC_BC7_COMP_TYPELESS =
+ SVGA3DBLOCKDESC_BC7 | SVGA3DBLOCKDESC_COMP_TYPELESS,
+ SVGA3DBLOCKDESC_BC7_COMP_UNORM =
+ SVGA3DBLOCKDESC_BC7 | SVGA3DBLOCKDESC_COMP_UNORM,
+ SVGA3DBLOCKDESC_BC7_COMP_UNORM_SRGB =
+ SVGA3DBLOCKDESC_BC7_COMP_UNORM | SVGA3DBLOCKDESC_SRGB,
+
+ SVGA3DBLOCKDESC_NV12 =
+ SVGA3DBLOCKDESC_YUV_VIDEO | SVGA3DBLOCKDESC_PLANAR_YUV |
+ SVGA3DBLOCKDESC_2PLANAR_YUV | SVGA3DBLOCKDESC_COLOR,
+ SVGA3DBLOCKDESC_YV12 =
+ SVGA3DBLOCKDESC_YUV_VIDEO | SVGA3DBLOCKDESC_PLANAR_YUV |
+ SVGA3DBLOCKDESC_3PLANAR_YUV | SVGA3DBLOCKDESC_COLOR,
+
+ SVGA3DBLOCKDESC_DEPTH_UINT =
+ SVGA3DBLOCKDESC_DEPTH | SVGA3DBLOCKDESC_UINT,
+ SVGA3DBLOCKDESC_DEPTH_UNORM =
+ SVGA3DBLOCKDESC_DEPTH_UINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_DS = SVGA3DBLOCKDESC_DEPTH | SVGA3DBLOCKDESC_STENCIL,
+ SVGA3DBLOCKDESC_DS_UINT = SVGA3DBLOCKDESC_DEPTH |
+ SVGA3DBLOCKDESC_STENCIL |
+ SVGA3DBLOCKDESC_UINT,
+ SVGA3DBLOCKDESC_DS_UNORM =
+ SVGA3DBLOCKDESC_DS_UINT | SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_DEPTH_FP = SVGA3DBLOCKDESC_DEPTH | SVGA3DBLOCKDESC_FP,
+
+ SVGA3DBLOCKDESC_UV_UINT = SVGA3DBLOCKDESC_UV | SVGA3DBLOCKDESC_UINT,
+ SVGA3DBLOCKDESC_UV_SNORM = SVGA3DBLOCKDESC_UV | SVGA3DBLOCKDESC_SINT |
+ SVGA3DBLOCKDESC_NORM,
+ SVGA3DBLOCKDESC_UVCX_SNORM =
+ SVGA3DBLOCKDESC_UV_SNORM | SVGA3DBLOCKDESC_CX,
SVGA3DBLOCKDESC_UVWQ_SNORM = SVGA3DBLOCKDESC_UVWQ |
SVGA3DBLOCKDESC_SINT |
SVGA3DBLOCKDESC_NORM,
-};
+} SVGA3dBlockDesc;
-struct svga3d_channel_def {
+typedef struct SVGA3dChannelDef {
union {
- u8 blue;
- u8 w_bump;
- u8 l_bump;
- u8 uv_video;
- u8 u_video;
+ uint8 blue;
+ uint8 w_bump;
+ uint8 l_bump;
+ uint8 uv_video;
+ uint8 u_video;
};
union {
- u8 green;
- u8 stencil;
- u8 v_bump;
- u8 v_video;
+ uint8 green;
+ uint8 stencil;
+ uint8 v_bump;
+ uint8 v_video;
};
union {
- u8 red;
- u8 u_bump;
- u8 luminance;
- u8 y_video;
- u8 depth;
- u8 data;
+ uint8 red;
+ uint8 u_bump;
+ uint8 luminance;
+ uint8 y_video;
+ uint8 depth;
+ uint8 data;
};
union {
- u8 alpha;
- u8 q_bump;
- u8 exp;
+ uint8 alpha;
+ uint8 q_bump;
+ uint8 exp;
};
-};
+} SVGA3dChannelDef;
-/*
- * struct svga3d_surface_desc - describes the actual pixel data.
- *
- * @format: Format
- * @block_desc: Block description
- * @block_size: Dimensions in pixels of a block
- * @bytes_per_block: Size of block in bytes
- * @pitch_bytes_per_block: Size of a block in bytes for purposes of pitch
- * @bit_depth: Channel bit depths
- * @bit_offset: Channel bit masks (in bits offset from the start of the pointer)
- */
-struct svga3d_surface_desc {
+typedef struct SVGA3dSurfaceDesc {
SVGA3dSurfaceFormat format;
- enum svga3d_block_desc block_desc;
-
- surf_size_struct block_size;
- u32 bytes_per_block;
- u32 pitch_bytes_per_block;
-
- struct svga3d_channel_def bit_depth;
- struct svga3d_channel_def bit_offset;
-};
-
-static const struct svga3d_surface_desc svga3d_surface_descs[] = {
- {SVGA3D_FORMAT_INVALID, SVGA3DBLOCKDESC_NONE,
- {1, 1, 1}, 0, 0,
- {{0}, {0}, {0}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_X8R8G8B8, SVGA3DBLOCKDESC_RGB_UNORM,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {0}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_A8R8G8B8, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_R5G6B5, SVGA3DBLOCKDESC_RGB_UNORM,
- {1, 1, 1}, 2, 2,
- {{5}, {6}, {5}, {0}},
- {{0}, {5}, {11}, {0}}},
-
- {SVGA3D_X1R5G5B5, SVGA3DBLOCKDESC_RGB_UNORM,
- {1, 1, 1}, 2, 2,
- {{5}, {5}, {5}, {0}},
- {{0}, {5}, {10}, {0}}},
-
- {SVGA3D_A1R5G5B5, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 2, 2,
- {{5}, {5}, {5}, {1}},
- {{0}, {5}, {10}, {15}}},
-
- {SVGA3D_A4R4G4B4, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 2, 2,
- {{4}, {4}, {4}, {4}},
- {{0}, {4}, {8}, {12}}},
-
- {SVGA3D_Z_D32, SVGA3DBLOCKDESC_DEPTH_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {32}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_Z_D16, SVGA3DBLOCKDESC_DEPTH_UNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_Z_D24S8, SVGA3DBLOCKDESC_DS_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {8}, {24}, {0}},
- {{0}, {0}, {8}, {0}}},
-
- {SVGA3D_Z_D15S1, SVGA3DBLOCKDESC_DS_UNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {1}, {15}, {0}},
- {{0}, {0}, {1}, {0}}},
-
- {SVGA3D_LUMINANCE8, SVGA3DBLOCKDESC_L_UNORM,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {8}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_LUMINANCE4_ALPHA4, SVGA3DBLOCKDESC_LA_UNORM,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {4}, {4}},
- {{0}, {0}, {0}, {4}}},
-
- {SVGA3D_LUMINANCE16, SVGA3DBLOCKDESC_L_UNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_LUMINANCE8_ALPHA8, SVGA3DBLOCKDESC_LA_UNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {8}, {8}},
- {{0}, {0}, {0}, {8}}},
-
- {SVGA3D_DXT1, SVGA3DBLOCKDESC_BC1_COMP_UNORM,
- {4, 4, 1}, 8, 8,
- {{0}, {0}, {64}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_DXT2, SVGA3DBLOCKDESC_BC2_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_DXT3, SVGA3DBLOCKDESC_BC2_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_DXT4, SVGA3DBLOCKDESC_BC3_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_DXT5, SVGA3DBLOCKDESC_BC3_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BUMPU8V8, SVGA3DBLOCKDESC_UV_SNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_BUMPL6V5U5, SVGA3DBLOCKDESC_UVL,
- {1, 1, 1}, 2, 2,
- {{6}, {5}, {5}, {0}},
- {{10}, {5}, {0}, {0}}},
-
- {SVGA3D_BUMPX8L8V8U8, SVGA3DBLOCKDESC_UVL,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {0}},
- {{16}, {8}, {0}, {0}}},
-
- {SVGA3D_FORMAT_DEAD1, SVGA3DBLOCKDESC_NONE,
- {1, 1, 1}, 3, 3,
- {{8}, {8}, {8}, {0}},
- {{16}, {8}, {0}, {0}}},
-
- {SVGA3D_ARGB_S10E5, SVGA3DBLOCKDESC_RGBA_FP,
- {1, 1, 1}, 8, 8,
- {{16}, {16}, {16}, {16}},
- {{32}, {16}, {0}, {48}}},
-
- {SVGA3D_ARGB_S23E8, SVGA3DBLOCKDESC_RGBA_FP,
- {1, 1, 1}, 16, 16,
- {{32}, {32}, {32}, {32}},
- {{64}, {32}, {0}, {96}}},
-
- {SVGA3D_A2R10G10B10, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 4, 4,
- {{10}, {10}, {10}, {2}},
- {{0}, {10}, {20}, {30}}},
-
- {SVGA3D_V8U8, SVGA3DBLOCKDESC_UV_SNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_Q8W8V8U8, SVGA3DBLOCKDESC_UVWQ_SNORM,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{16}, {8}, {0}, {24}}},
-
- {SVGA3D_CxV8U8, SVGA3DBLOCKDESC_UVCX_SNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_X8L8V8U8, SVGA3DBLOCKDESC_UVL,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {0}},
- {{16}, {8}, {0}, {0}}},
-
- {SVGA3D_A2W10V10U10, SVGA3DBLOCKDESC_UVWA,
- {1, 1, 1}, 4, 4,
- {{10}, {10}, {10}, {2}},
- {{20}, {10}, {0}, {30}}},
-
- {SVGA3D_ALPHA8, SVGA3DBLOCKDESC_A_UNORM,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {0}, {8}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R_S10E5, SVGA3DBLOCKDESC_R_FP,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R_S23E8, SVGA3DBLOCKDESC_R_FP,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {32}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_RG_S10E5, SVGA3DBLOCKDESC_RG_FP,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_RG_S23E8, SVGA3DBLOCKDESC_RG_FP,
- {1, 1, 1}, 8, 8,
- {{0}, {32}, {32}, {0}},
- {{0}, {32}, {0}, {0}}},
-
- {SVGA3D_BUFFER, SVGA3DBLOCKDESC_BUFFER,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {8}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_Z_D24X8, SVGA3DBLOCKDESC_DEPTH_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {24}, {0}},
- {{0}, {0}, {8}, {0}}},
-
- {SVGA3D_V16U16, SVGA3DBLOCKDESC_UV_SNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_G16R16, SVGA3DBLOCKDESC_RG_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_A16B16G16R16, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 8, 8,
- {{16}, {16}, {16}, {16}},
- {{32}, {16}, {0}, {48}}},
-
- {SVGA3D_UYVY, SVGA3DBLOCKDESC_YUV,
- {2, 1, 1}, 4, 4,
- {{8}, {0}, {8}, {0}},
- {{0}, {0}, {8}, {0}}},
-
- {SVGA3D_YUY2, SVGA3DBLOCKDESC_YUV,
- {2, 1, 1}, 4, 4,
- {{8}, {0}, {8}, {0}},
- {{8}, {0}, {0}, {0}}},
-
- {SVGA3D_NV12, SVGA3DBLOCKDESC_NV12,
- {2, 2, 1}, 6, 2,
- {{0}, {0}, {48}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_FORMAT_DEAD2, SVGA3DBLOCKDESC_NONE,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_R32G32B32A32_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 16, 16,
- {{32}, {32}, {32}, {32}},
- {{64}, {32}, {0}, {96}}},
-
- {SVGA3D_R32G32B32A32_UINT, SVGA3DBLOCKDESC_RGBA_UINT,
- {1, 1, 1}, 16, 16,
- {{32}, {32}, {32}, {32}},
- {{64}, {32}, {0}, {96}}},
-
- {SVGA3D_R32G32B32A32_SINT, SVGA3DBLOCKDESC_RGBA_SINT,
- {1, 1, 1}, 16, 16,
- {{32}, {32}, {32}, {32}},
- {{64}, {32}, {0}, {96}}},
-
- {SVGA3D_R32G32B32_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 12, 12,
- {{32}, {32}, {32}, {0}},
- {{64}, {32}, {0}, {0}}},
-
- {SVGA3D_R32G32B32_FLOAT, SVGA3DBLOCKDESC_RGB_FP,
- {1, 1, 1}, 12, 12,
- {{32}, {32}, {32}, {0}},
- {{64}, {32}, {0}, {0}}},
-
- {SVGA3D_R32G32B32_UINT, SVGA3DBLOCKDESC_RGB_UINT,
- {1, 1, 1}, 12, 12,
- {{32}, {32}, {32}, {0}},
- {{64}, {32}, {0}, {0}}},
-
- {SVGA3D_R32G32B32_SINT, SVGA3DBLOCKDESC_RGB_SINT,
- {1, 1, 1}, 12, 12,
- {{32}, {32}, {32}, {0}},
- {{64}, {32}, {0}, {0}}},
-
- {SVGA3D_R16G16B16A16_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 8, 8,
- {{16}, {16}, {16}, {16}},
- {{32}, {16}, {0}, {48}}},
-
- {SVGA3D_R16G16B16A16_UINT, SVGA3DBLOCKDESC_RGBA_UINT,
- {1, 1, 1}, 8, 8,
- {{16}, {16}, {16}, {16}},
- {{32}, {16}, {0}, {48}}},
-
- {SVGA3D_R16G16B16A16_SNORM, SVGA3DBLOCKDESC_RGBA_SNORM,
- {1, 1, 1}, 8, 8,
- {{16}, {16}, {16}, {16}},
- {{32}, {16}, {0}, {48}}},
-
- {SVGA3D_R16G16B16A16_SINT, SVGA3DBLOCKDESC_RGBA_SINT,
- {1, 1, 1}, 8, 8,
- {{16}, {16}, {16}, {16}},
- {{32}, {16}, {0}, {48}}},
-
- {SVGA3D_R32G32_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 8, 8,
- {{0}, {32}, {32}, {0}},
- {{0}, {32}, {0}, {0}}},
-
- {SVGA3D_R32G32_UINT, SVGA3DBLOCKDESC_RG_UINT,
- {1, 1, 1}, 8, 8,
- {{0}, {32}, {32}, {0}},
- {{0}, {32}, {0}, {0}}},
-
- {SVGA3D_R32G32_SINT, SVGA3DBLOCKDESC_RG_SINT,
- {1, 1, 1}, 8, 8,
- {{0}, {32}, {32}, {0}},
- {{0}, {32}, {0}, {0}}},
-
- {SVGA3D_R32G8X24_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 8, 8,
- {{0}, {8}, {32}, {0}},
- {{0}, {32}, {0}, {0}}},
-
- {SVGA3D_D32_FLOAT_S8X24_UINT, SVGA3DBLOCKDESC_DS,
- {1, 1, 1}, 8, 8,
- {{0}, {8}, {32}, {0}},
- {{0}, {32}, {0}, {0}}},
-
- {SVGA3D_R32_FLOAT_X8X24, SVGA3DBLOCKDESC_R_FP,
- {1, 1, 1}, 8, 8,
- {{0}, {0}, {32}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_X32_G8X24_UINT, SVGA3DBLOCKDESC_G_UINT,
- {1, 1, 1}, 8, 8,
- {{0}, {8}, {0}, {0}},
- {{0}, {32}, {0}, {0}}},
-
- {SVGA3D_R10G10B10A2_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 4, 4,
- {{10}, {10}, {10}, {2}},
- {{20}, {10}, {0}, {30}}},
-
- {SVGA3D_R10G10B10A2_UINT, SVGA3DBLOCKDESC_RGBA_UINT,
- {1, 1, 1}, 4, 4,
- {{10}, {10}, {10}, {2}},
- {{20}, {10}, {0}, {30}}},
-
- {SVGA3D_R11G11B10_FLOAT, SVGA3DBLOCKDESC_RGB_FP,
- {1, 1, 1}, 4, 4,
- {{10}, {11}, {11}, {0}},
- {{22}, {11}, {0}, {0}}},
-
- {SVGA3D_R8G8B8A8_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{16}, {8}, {0}, {24}}},
-
- {SVGA3D_R8G8B8A8_UNORM, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{16}, {8}, {0}, {24}}},
-
- {SVGA3D_R8G8B8A8_UNORM_SRGB, SVGA3DBLOCKDESC_RGBA_UNORM_SRGB,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{16}, {8}, {0}, {24}}},
-
- {SVGA3D_R8G8B8A8_UINT, SVGA3DBLOCKDESC_RGBA_UINT,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{16}, {8}, {0}, {24}}},
-
- {SVGA3D_R8G8B8A8_SINT, SVGA3DBLOCKDESC_RGBA_SINT,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{16}, {8}, {0}, {24}}},
-
- {SVGA3D_R16G16_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_R16G16_UINT, SVGA3DBLOCKDESC_RG_UINT,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_R16G16_SINT, SVGA3DBLOCKDESC_RG_SINT,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_R32_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {32}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_D32_FLOAT, SVGA3DBLOCKDESC_DEPTH_FP,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {32}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R32_UINT, SVGA3DBLOCKDESC_R_UINT,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {32}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R32_SINT, SVGA3DBLOCKDESC_R_SINT,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {32}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R24G8_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 4, 4,
- {{0}, {8}, {24}, {0}},
- {{0}, {24}, {0}, {0}}},
-
- {SVGA3D_D24_UNORM_S8_UINT, SVGA3DBLOCKDESC_DS_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {8}, {24}, {0}},
- {{0}, {24}, {0}, {0}}},
-
- {SVGA3D_R24_UNORM_X8, SVGA3DBLOCKDESC_R_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {24}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_X24_G8_UINT, SVGA3DBLOCKDESC_G_UINT,
- {1, 1, 1}, 4, 4,
- {{0}, {8}, {0}, {0}},
- {{0}, {24}, {0}, {0}}},
-
- {SVGA3D_R8G8_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 2, 2,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_R8G8_UNORM, SVGA3DBLOCKDESC_RG_UNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_R8G8_UINT, SVGA3DBLOCKDESC_RG_UINT,
- {1, 1, 1}, 2, 2,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_R8G8_SINT, SVGA3DBLOCKDESC_RG_SINT,
- {1, 1, 1}, 2, 2,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_R16_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R16_UNORM, SVGA3DBLOCKDESC_R_UNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R16_UINT, SVGA3DBLOCKDESC_R_UINT,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R16_SNORM, SVGA3DBLOCKDESC_R_SNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R16_SINT, SVGA3DBLOCKDESC_R_SINT,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R8_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {8}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R8_UNORM, SVGA3DBLOCKDESC_R_UNORM,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {8}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R8_UINT, SVGA3DBLOCKDESC_R_UINT,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {8}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R8_SNORM, SVGA3DBLOCKDESC_R_SNORM,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {8}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R8_SINT, SVGA3DBLOCKDESC_R_SINT,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {8}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_P8, SVGA3DBLOCKDESC_NONE,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {8}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R9G9B9E5_SHAREDEXP, SVGA3DBLOCKDESC_RGB_EXP,
- {1, 1, 1}, 4, 4,
- {{9}, {9}, {9}, {5}},
- {{18}, {9}, {0}, {27}}},
-
- {SVGA3D_R8G8_B8G8_UNORM, SVGA3DBLOCKDESC_NONE,
- {2, 1, 1}, 4, 4,
- {{0}, {8}, {8}, {0}},
- {{0}, {0}, {8}, {0}}},
-
- {SVGA3D_G8R8_G8B8_UNORM, SVGA3DBLOCKDESC_NONE,
- {2, 1, 1}, 4, 4,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_BC1_TYPELESS, SVGA3DBLOCKDESC_BC1_COMP_TYPELESS,
- {4, 4, 1}, 8, 8,
- {{0}, {0}, {64}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC1_UNORM_SRGB, SVGA3DBLOCKDESC_BC1_COMP_UNORM_SRGB,
- {4, 4, 1}, 8, 8,
- {{0}, {0}, {64}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC2_TYPELESS, SVGA3DBLOCKDESC_BC2_COMP_TYPELESS,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC2_UNORM_SRGB, SVGA3DBLOCKDESC_BC2_COMP_UNORM_SRGB,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC3_TYPELESS, SVGA3DBLOCKDESC_BC3_COMP_TYPELESS,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC3_UNORM_SRGB, SVGA3DBLOCKDESC_BC3_COMP_UNORM_SRGB,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC4_TYPELESS, SVGA3DBLOCKDESC_BC4_COMP_TYPELESS,
- {4, 4, 1}, 8, 8,
- {{0}, {0}, {64}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_ATI1, SVGA3DBLOCKDESC_BC4_COMP_UNORM,
- {4, 4, 1}, 8, 8,
- {{0}, {0}, {64}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC4_SNORM, SVGA3DBLOCKDESC_BC4_COMP_SNORM,
- {4, 4, 1}, 8, 8,
- {{0}, {0}, {64}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC5_TYPELESS, SVGA3DBLOCKDESC_BC5_COMP_TYPELESS,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_ATI2, SVGA3DBLOCKDESC_BC5_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC5_SNORM, SVGA3DBLOCKDESC_BC5_COMP_SNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R10G10B10_XR_BIAS_A2_UNORM, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 4, 4,
- {{10}, {10}, {10}, {2}},
- {{20}, {10}, {0}, {30}}},
-
- {SVGA3D_B8G8R8A8_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_B8G8R8A8_UNORM_SRGB, SVGA3DBLOCKDESC_RGBA_UNORM_SRGB,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_B8G8R8X8_TYPELESS, SVGA3DBLOCKDESC_TYPELESS,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {0}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_B8G8R8X8_UNORM_SRGB, SVGA3DBLOCKDESC_RGB_UNORM_SRGB,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {0}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_Z_DF16, SVGA3DBLOCKDESC_DEPTH_UNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_Z_DF24, SVGA3DBLOCKDESC_DEPTH_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {24}, {0}},
- {{0}, {0}, {8}, {0}}},
-
- {SVGA3D_Z_D24S8_INT, SVGA3DBLOCKDESC_DS_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {8}, {24}, {0}},
- {{0}, {0}, {8}, {0}}},
-
- {SVGA3D_YV12, SVGA3DBLOCKDESC_YV12,
- {2, 2, 1}, 6, 2,
- {{0}, {0}, {48}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R32G32B32A32_FLOAT, SVGA3DBLOCKDESC_RGBA_FP,
- {1, 1, 1}, 16, 16,
- {{32}, {32}, {32}, {32}},
- {{64}, {32}, {0}, {96}}},
-
- {SVGA3D_R16G16B16A16_FLOAT, SVGA3DBLOCKDESC_RGBA_FP,
- {1, 1, 1}, 8, 8,
- {{16}, {16}, {16}, {16}},
- {{32}, {16}, {0}, {48}}},
-
- {SVGA3D_R16G16B16A16_UNORM, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 8, 8,
- {{16}, {16}, {16}, {16}},
- {{32}, {16}, {0}, {48}}},
-
- {SVGA3D_R32G32_FLOAT, SVGA3DBLOCKDESC_RG_FP,
- {1, 1, 1}, 8, 8,
- {{0}, {32}, {32}, {0}},
- {{0}, {32}, {0}, {0}}},
-
- {SVGA3D_R10G10B10A2_UNORM, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 4, 4,
- {{10}, {10}, {10}, {2}},
- {{20}, {10}, {0}, {30}}},
-
- {SVGA3D_R8G8B8A8_SNORM, SVGA3DBLOCKDESC_RGBA_SNORM,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{16}, {8}, {0}, {24}}},
-
- {SVGA3D_R16G16_FLOAT, SVGA3DBLOCKDESC_RG_FP,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_R16G16_UNORM, SVGA3DBLOCKDESC_RG_UNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_R16G16_SNORM, SVGA3DBLOCKDESC_RG_SNORM,
- {1, 1, 1}, 4, 4,
- {{0}, {16}, {16}, {0}},
- {{0}, {16}, {0}, {0}}},
-
- {SVGA3D_R32_FLOAT, SVGA3DBLOCKDESC_R_FP,
- {1, 1, 1}, 4, 4,
- {{0}, {0}, {32}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_R8G8_SNORM, SVGA3DBLOCKDESC_RG_SNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {8}, {8}, {0}},
- {{0}, {8}, {0}, {0}}},
-
- {SVGA3D_R16_FLOAT, SVGA3DBLOCKDESC_R_FP,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_D16_UNORM, SVGA3DBLOCKDESC_DEPTH_UNORM,
- {1, 1, 1}, 2, 2,
- {{0}, {0}, {16}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_A8_UNORM, SVGA3DBLOCKDESC_A_UNORM,
- {1, 1, 1}, 1, 1,
- {{0}, {0}, {0}, {8}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC1_UNORM, SVGA3DBLOCKDESC_BC1_COMP_UNORM,
- {4, 4, 1}, 8, 8,
- {{0}, {0}, {64}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC2_UNORM, SVGA3DBLOCKDESC_BC2_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC3_UNORM, SVGA3DBLOCKDESC_BC3_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_B5G6R5_UNORM, SVGA3DBLOCKDESC_RGB_UNORM,
- {1, 1, 1}, 2, 2,
- {{5}, {6}, {5}, {0}},
- {{0}, {5}, {11}, {0}}},
-
- {SVGA3D_B5G5R5A1_UNORM, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 2, 2,
- {{5}, {5}, {5}, {1}},
- {{0}, {5}, {10}, {15}}},
-
- {SVGA3D_B8G8R8A8_UNORM, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_B8G8R8X8_UNORM, SVGA3DBLOCKDESC_RGB_UNORM,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {0}},
- {{0}, {8}, {16}, {24}}},
-
- {SVGA3D_BC4_UNORM, SVGA3DBLOCKDESC_BC4_COMP_UNORM,
- {4, 4, 1}, 8, 8,
- {{0}, {0}, {64}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC5_UNORM, SVGA3DBLOCKDESC_BC5_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_B4G4R4A4_UNORM, SVGA3DBLOCKDESC_RGBA_UNORM,
- {1, 1, 1}, 2, 2,
- {{4}, {4}, {4}, {4}},
- {{0}, {4}, {8}, {12}}},
-
- {SVGA3D_BC6H_TYPELESS, SVGA3DBLOCKDESC_BC6H_COMP_TYPELESS,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC6H_UF16, SVGA3DBLOCKDESC_BC6H_COMP_UF16,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC6H_SF16, SVGA3DBLOCKDESC_BC6H_COMP_SF16,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC7_TYPELESS, SVGA3DBLOCKDESC_BC7_COMP_TYPELESS,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC7_UNORM, SVGA3DBLOCKDESC_BC7_COMP_UNORM,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_BC7_UNORM_SRGB, SVGA3DBLOCKDESC_BC7_COMP_UNORM_SRGB,
- {4, 4, 1}, 16, 16,
- {{0}, {0}, {128}, {0}},
- {{0}, {0}, {0}, {0}}},
-
- {SVGA3D_AYUV, SVGA3DBLOCKDESC_AYUV,
- {1, 1, 1}, 4, 4,
- {{8}, {8}, {8}, {8}},
- {{0}, {8}, {16}, {24}}},
-};
-
-static inline u32 clamped_umul32(u32 a, u32 b)
-{
- uint64_t tmp = (uint64_t) a*b;
- return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp;
-}
-
-/**
- * svga3dsurface_get_desc - Look up the appropriate SVGA3dSurfaceDesc for the
- * given format.
- */
-static inline const struct svga3d_surface_desc *
-svga3dsurface_get_desc(SVGA3dSurfaceFormat format)
-{
- if (format < ARRAY_SIZE(svga3d_surface_descs))
- return &svga3d_surface_descs[format];
-
- return &svga3d_surface_descs[SVGA3D_FORMAT_INVALID];
-}
-
-/**
- * svga3dsurface_get_mip_size - Given a base level size and the mip level,
- * compute the size of the mip level.
- */
-static inline surf_size_struct
-svga3dsurface_get_mip_size(surf_size_struct base_level, u32 mip_level)
-{
- surf_size_struct size;
-
- size.width = max_t(u32, base_level.width >> mip_level, 1);
- size.height = max_t(u32, base_level.height >> mip_level, 1);
- size.depth = max_t(u32, base_level.depth >> mip_level, 1);
- size.pad64 = 0;
-
- return size;
-}
-
-static inline void
-svga3dsurface_get_size_in_blocks(const struct svga3d_surface_desc *desc,
- const surf_size_struct *pixel_size,
- surf_size_struct *block_size)
-{
- block_size->width = __KERNEL_DIV_ROUND_UP(pixel_size->width,
- desc->block_size.width);
- block_size->height = __KERNEL_DIV_ROUND_UP(pixel_size->height,
- desc->block_size.height);
- block_size->depth = __KERNEL_DIV_ROUND_UP(pixel_size->depth,
- desc->block_size.depth);
-}
-
-static inline bool
-svga3dsurface_is_planar_surface(const struct svga3d_surface_desc *desc)
-{
- return (desc->block_desc & SVGA3DBLOCKDESC_PLANAR_YUV) != 0;
-}
-
-static inline u32
-svga3dsurface_calculate_pitch(const struct svga3d_surface_desc *desc,
- const surf_size_struct *size)
-{
- u32 pitch;
- surf_size_struct blocks;
-
- svga3dsurface_get_size_in_blocks(desc, size, &blocks);
-
- pitch = blocks.width * desc->pitch_bytes_per_block;
-
- return pitch;
-}
-
-/**
- * svga3dsurface_get_image_buffer_size - Calculates image buffer size.
- *
- * Return the number of bytes of buffer space required to store one image of a
- * surface, optionally using the specified pitch.
- *
- * If pitch is zero, it is assumed that rows are tightly packed.
- *
- * This function is overflow-safe. If the result would have overflowed, instead
- * we return MAX_UINT32.
- */
-static inline u32
-svga3dsurface_get_image_buffer_size(const struct svga3d_surface_desc *desc,
- const surf_size_struct *size,
- u32 pitch)
-{
- surf_size_struct image_blocks;
- u32 slice_size, total_size;
-
- svga3dsurface_get_size_in_blocks(desc, size, &image_blocks);
-
- if (svga3dsurface_is_planar_surface(desc)) {
- total_size = clamped_umul32(image_blocks.width,
- image_blocks.height);
- total_size = clamped_umul32(total_size, image_blocks.depth);
- total_size = clamped_umul32(total_size, desc->bytes_per_block);
- return total_size;
- }
-
- if (pitch == 0)
- pitch = svga3dsurface_calculate_pitch(desc, size);
-
- slice_size = clamped_umul32(image_blocks.height, pitch);
- total_size = clamped_umul32(slice_size, image_blocks.depth);
-
- return total_size;
-}
-
-/**
- * svga3dsurface_get_serialized_size - Get the serialized size for the image.
- */
-static inline u32
-svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format,
- surf_size_struct base_level_size,
- u32 num_mip_levels,
- u32 num_layers)
-{
- const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
- u32 total_size = 0;
- u32 mip;
-
- for (mip = 0; mip < num_mip_levels; mip++) {
- surf_size_struct size =
- svga3dsurface_get_mip_size(base_level_size, mip);
- total_size += svga3dsurface_get_image_buffer_size(desc,
- &size, 0);
- }
-
- return total_size * num_layers;
-}
-
-/**
- * svga3dsurface_get_serialized_size_extended - Returns the number of bytes
- * required for a surface with given parameters. Support for sample count.
- */
-static inline u32
-svga3dsurface_get_serialized_size_extended(SVGA3dSurfaceFormat format,
- surf_size_struct base_level_size,
- u32 num_mip_levels,
- u32 num_layers,
- u32 num_samples)
-{
- uint64_t total_size =
- svga3dsurface_get_serialized_size(format,
- base_level_size,
- num_mip_levels,
- num_layers);
- total_size *= max_t(u32, 1, num_samples);
-
- return min_t(uint64_t, total_size, (uint64_t)U32_MAX);
-}
-
-/**
- * svga3dsurface_get_pixel_offset - Compute the offset (in bytes) to a pixel
- * in an image (or volume).
- *
- * @width: The image width in pixels.
- * @height: The image height in pixels
- */
-static inline u32
-svga3dsurface_get_pixel_offset(SVGA3dSurfaceFormat format,
- u32 width, u32 height,
- u32 x, u32 y, u32 z)
-{
- const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
- const u32 bw = desc->block_size.width, bh = desc->block_size.height;
- const u32 bd = desc->block_size.depth;
- const u32 rowstride = __KERNEL_DIV_ROUND_UP(width, bw) *
- desc->bytes_per_block;
- const u32 imgstride = __KERNEL_DIV_ROUND_UP(height, bh) * rowstride;
- const u32 offset = (z / bd * imgstride +
- y / bh * rowstride +
- x / bw * desc->bytes_per_block);
- return offset;
-}
-
-static inline u32
-svga3dsurface_get_image_offset(SVGA3dSurfaceFormat format,
- surf_size_struct baseLevelSize,
- u32 numMipLevels,
- u32 face,
- u32 mip)
-
-{
- u32 offset;
- u32 mipChainBytes;
- u32 mipChainBytesToLevel;
- u32 i;
- const struct svga3d_surface_desc *desc;
- surf_size_struct mipSize;
- u32 bytes;
-
- desc = svga3dsurface_get_desc(format);
-
- mipChainBytes = 0;
- mipChainBytesToLevel = 0;
- for (i = 0; i < numMipLevels; i++) {
- mipSize = svga3dsurface_get_mip_size(baseLevelSize, i);
- bytes = svga3dsurface_get_image_buffer_size(desc, &mipSize, 0);
- mipChainBytes += bytes;
- if (i < mip)
- mipChainBytesToLevel += bytes;
- }
-
- offset = mipChainBytes * face + mipChainBytesToLevel;
-
- return offset;
-}
-
-
-/**
- * svga3dsurface_is_gb_screen_target_format - Is the specified format usable as
- * a ScreenTarget?
- * (with just the GBObjects cap-bit
- * set)
- * @format: format to queried
- *
- * RETURNS:
- * true if queried format is valid for screen targets
- */
-static inline bool
-svga3dsurface_is_gb_screen_target_format(SVGA3dSurfaceFormat format)
-{
- return (format == SVGA3D_X8R8G8B8 ||
- format == SVGA3D_A8R8G8B8 ||
- format == SVGA3D_R5G6B5 ||
- format == SVGA3D_X1R5G5B5 ||
- format == SVGA3D_A1R5G5B5 ||
- format == SVGA3D_P8);
-}
-
-
-/**
- * svga3dsurface_is_dx_screen_target_format - Is the specified format usable as
- * a ScreenTarget?
- * (with DX10 enabled)
- *
- * @format: format to queried
- *
- * Results:
- * true if queried format is valid for screen targets
- */
-static inline bool
-svga3dsurface_is_dx_screen_target_format(SVGA3dSurfaceFormat format)
-{
- return (format == SVGA3D_R8G8B8A8_UNORM ||
- format == SVGA3D_B8G8R8A8_UNORM ||
- format == SVGA3D_B8G8R8X8_UNORM);
-}
-
-
-/**
- * svga3dsurface_is_screen_target_format - Is the specified format usable as a
- * ScreenTarget?
- * (for some combination of caps)
- *
- * @format: format to queried
- *
- * Results:
- * true if queried format is valid for screen targets
- */
-static inline bool
-svga3dsurface_is_screen_target_format(SVGA3dSurfaceFormat format)
-{
- if (svga3dsurface_is_gb_screen_target_format(format)) {
- return true;
- }
- return svga3dsurface_is_dx_screen_target_format(format);
-}
-
-/**
- * struct svga3dsurface_mip - Mimpmap level information
- * @bytes: Bytes required in the backing store of this mipmap level.
- * @img_stride: Byte stride per image.
- * @row_stride: Byte stride per block row.
- * @size: The size of the mipmap.
- */
-struct svga3dsurface_mip {
- size_t bytes;
- size_t img_stride;
- size_t row_stride;
- struct drm_vmw_size size;
-
-};
-
-/**
- * struct svga3dsurface_cache - Cached surface information
- * @desc: Pointer to the surface descriptor
- * @mip: Array of mipmap level information. Valid size is @num_mip_levels.
- * @mip_chain_bytes: Bytes required in the backing store for the whole chain
- * of mip levels.
- * @sheet_bytes: Bytes required in the backing store for a sheet
- * representing a single sample.
- * @num_mip_levels: Valid size of the @mip array. Number of mipmap levels in
- * a chain.
- * @num_layers: Number of slices in an array texture or number of faces in
- * a cubemap texture.
- */
-struct svga3dsurface_cache {
- const struct svga3d_surface_desc *desc;
- struct svga3dsurface_mip mip[DRM_VMW_MAX_MIP_LEVELS];
- size_t mip_chain_bytes;
- size_t sheet_bytes;
- u32 num_mip_levels;
- u32 num_layers;
-};
-
-/**
- * struct svga3dsurface_loc - Surface location
- * @sheet: The multisample sheet.
- * @sub_resource: Surface subresource. Defined as layer * num_mip_levels +
- * mip_level.
- * @x: X coordinate.
- * @y: Y coordinate.
- * @z: Z coordinate.
- */
-struct svga3dsurface_loc {
- u32 sheet;
- u32 sub_resource;
- u32 x, y, z;
+ SVGA3dBlockDesc blockDesc;
+
+ SVGA3dSize blockSize;
+ uint32 bytesPerBlock;
+ uint32 pitchBytesPerBlock;
+
+ SVGA3dChannelDef bitDepth;
+ SVGA3dChannelDef bitOffset;
+} SVGA3dSurfaceDesc;
+
+STATIC_CONST SVGA3dSurfaceDesc g_SVGA3dSurfaceDescs[] = {
+ { SVGA3D_FORMAT_INVALID,
+ SVGA3DBLOCKDESC_NONE,
+ { 1, 1, 1 },
+ 0,
+ 0,
+ { { 0 }, { 0 }, { 0 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_X8R8G8B8,
+ SVGA3DBLOCKDESC_RGB_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_A8R8G8B8,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_R5G6B5,
+ SVGA3DBLOCKDESC_RGB_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 5 }, { 6 }, { 5 }, { 0 } },
+ { { 0 }, { 5 }, { 11 }, { 0 } } },
+
+ { SVGA3D_X1R5G5B5,
+ SVGA3DBLOCKDESC_RGB_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 5 }, { 5 }, { 5 }, { 0 } },
+ { { 0 }, { 5 }, { 10 }, { 0 } } },
+
+ { SVGA3D_A1R5G5B5,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 5 }, { 5 }, { 5 }, { 1 } },
+ { { 0 }, { 5 }, { 10 }, { 15 } } },
+
+ { SVGA3D_A4R4G4B4,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 4 }, { 4 }, { 4 }, { 4 } },
+ { { 0 }, { 4 }, { 8 }, { 12 } } },
+
+ { SVGA3D_Z_D32,
+ SVGA3DBLOCKDESC_DEPTH_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 32 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_Z_D16,
+ SVGA3DBLOCKDESC_DEPTH_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_Z_D24S8,
+ SVGA3DBLOCKDESC_DS_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 8 }, { 24 }, { 0 } },
+ { { 0 }, { 0 }, { 8 }, { 0 } } },
+
+ { SVGA3D_Z_D15S1,
+ SVGA3DBLOCKDESC_DS_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 1 }, { 15 }, { 0 } },
+ { { 0 }, { 0 }, { 1 }, { 0 } } },
+
+ { SVGA3D_LUMINANCE8,
+ SVGA3DBLOCKDESC_L_UNORM,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_LUMINANCE4_ALPHA4,
+ SVGA3DBLOCKDESC_LA_UNORM,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 4 }, { 4 } },
+ { { 0 }, { 0 }, { 0 }, { 4 } } },
+
+ { SVGA3D_LUMINANCE16,
+ SVGA3DBLOCKDESC_L_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_LUMINANCE8_ALPHA8,
+ SVGA3DBLOCKDESC_LA_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 8 }, { 8 } },
+ { { 0 }, { 0 }, { 0 }, { 8 } } },
+
+ { SVGA3D_DXT1,
+ SVGA3DBLOCKDESC_BC1_COMP_UNORM,
+ { 4, 4, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 64 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_DXT2,
+ SVGA3DBLOCKDESC_BC2_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_DXT3,
+ SVGA3DBLOCKDESC_BC2_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_DXT4,
+ SVGA3DBLOCKDESC_BC3_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_DXT5,
+ SVGA3DBLOCKDESC_BC3_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BUMPU8V8,
+ SVGA3DBLOCKDESC_UV_SNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BUMPL6V5U5,
+ SVGA3DBLOCKDESC_UVL,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 6 }, { 5 }, { 5 }, { 0 } },
+ { { 10 }, { 5 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BUMPX8L8V8U8,
+ SVGA3DBLOCKDESC_UVL,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 0 } },
+ { { 16 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_FORMAT_DEAD1,
+ SVGA3DBLOCKDESC_NONE,
+ { 1, 1, 1 },
+ 3,
+ 3,
+ { { 8 }, { 8 }, { 8 }, { 0 } },
+ { { 16 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_ARGB_S10E5,
+ SVGA3DBLOCKDESC_RGBA_FP,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 16 }, { 16 }, { 16 }, { 16 } },
+ { { 32 }, { 16 }, { 0 }, { 48 } } },
+
+ { SVGA3D_ARGB_S23E8,
+ SVGA3DBLOCKDESC_RGBA_FP,
+ { 1, 1, 1 },
+ 16,
+ 16,
+ { { 32 }, { 32 }, { 32 }, { 32 } },
+ { { 64 }, { 32 }, { 0 }, { 96 } } },
+
+ { SVGA3D_A2R10G10B10,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 10 }, { 10 }, { 10 }, { 2 } },
+ { { 0 }, { 10 }, { 20 }, { 30 } } },
+
+ { SVGA3D_V8U8,
+ SVGA3DBLOCKDESC_UV_SNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_Q8W8V8U8,
+ SVGA3DBLOCKDESC_UVWQ_SNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 16 }, { 8 }, { 0 }, { 24 } } },
+
+ { SVGA3D_CxV8U8,
+ SVGA3DBLOCKDESC_UVCX_SNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_X8L8V8U8,
+ SVGA3DBLOCKDESC_UVL,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 0 } },
+ { { 16 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_A2W10V10U10,
+ SVGA3DBLOCKDESC_UVWA,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 10 }, { 10 }, { 10 }, { 2 } },
+ { { 20 }, { 10 }, { 0 }, { 30 } } },
+
+ { SVGA3D_ALPHA8,
+ SVGA3DBLOCKDESC_A_UNORM,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 0 }, { 8 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R_S10E5,
+ SVGA3DBLOCKDESC_R_FP,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R_S23E8,
+ SVGA3DBLOCKDESC_R_FP,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 32 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_RG_S10E5,
+ SVGA3DBLOCKDESC_RG_FP,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_RG_S23E8,
+ SVGA3DBLOCKDESC_RG_FP,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 32 }, { 32 }, { 0 } },
+ { { 0 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BUFFER,
+ SVGA3DBLOCKDESC_BUFFER,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_Z_D24X8,
+ SVGA3DBLOCKDESC_DEPTH_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 24 }, { 0 } },
+ { { 0 }, { 0 }, { 8 }, { 0 } } },
+
+ { SVGA3D_V16U16,
+ SVGA3DBLOCKDESC_UV_SNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_G16R16,
+ SVGA3DBLOCKDESC_RG_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_A16B16G16R16,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 16 }, { 16 }, { 16 }, { 16 } },
+ { { 32 }, { 16 }, { 0 }, { 48 } } },
+
+ { SVGA3D_UYVY,
+ SVGA3DBLOCKDESC_YUV,
+ { 2, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 8 }, { 0 } } },
+
+ { SVGA3D_YUY2,
+ SVGA3DBLOCKDESC_YUV,
+ { 2, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 0 }, { 8 }, { 0 } },
+ { { 8 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_NV12,
+ SVGA3DBLOCKDESC_NV12,
+ { 2, 2, 1 },
+ 6,
+ 2,
+ { { 0 }, { 0 }, { 48 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_FORMAT_DEAD2,
+ SVGA3DBLOCKDESC_NONE,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_R32G32B32A32_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 16,
+ 16,
+ { { 32 }, { 32 }, { 32 }, { 32 } },
+ { { 64 }, { 32 }, { 0 }, { 96 } } },
+
+ { SVGA3D_R32G32B32A32_UINT,
+ SVGA3DBLOCKDESC_RGBA_UINT,
+ { 1, 1, 1 },
+ 16,
+ 16,
+ { { 32 }, { 32 }, { 32 }, { 32 } },
+ { { 64 }, { 32 }, { 0 }, { 96 } } },
+
+ { SVGA3D_R32G32B32A32_SINT,
+ SVGA3DBLOCKDESC_RGBA_SINT,
+ { 1, 1, 1 },
+ 16,
+ 16,
+ { { 32 }, { 32 }, { 32 }, { 32 } },
+ { { 64 }, { 32 }, { 0 }, { 96 } } },
+
+ { SVGA3D_R32G32B32_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 12,
+ 12,
+ { { 32 }, { 32 }, { 32 }, { 0 } },
+ { { 64 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32G32B32_FLOAT,
+ SVGA3DBLOCKDESC_RGB_FP,
+ { 1, 1, 1 },
+ 12,
+ 12,
+ { { 32 }, { 32 }, { 32 }, { 0 } },
+ { { 64 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32G32B32_UINT,
+ SVGA3DBLOCKDESC_RGB_UINT,
+ { 1, 1, 1 },
+ 12,
+ 12,
+ { { 32 }, { 32 }, { 32 }, { 0 } },
+ { { 64 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32G32B32_SINT,
+ SVGA3DBLOCKDESC_RGB_SINT,
+ { 1, 1, 1 },
+ 12,
+ 12,
+ { { 32 }, { 32 }, { 32 }, { 0 } },
+ { { 64 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16G16B16A16_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 16 }, { 16 }, { 16 }, { 16 } },
+ { { 32 }, { 16 }, { 0 }, { 48 } } },
+
+ { SVGA3D_R16G16B16A16_UINT,
+ SVGA3DBLOCKDESC_RGBA_UINT,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 16 }, { 16 }, { 16 }, { 16 } },
+ { { 32 }, { 16 }, { 0 }, { 48 } } },
+
+ { SVGA3D_R16G16B16A16_SNORM,
+ SVGA3DBLOCKDESC_RGBA_SNORM,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 16 }, { 16 }, { 16 }, { 16 } },
+ { { 32 }, { 16 }, { 0 }, { 48 } } },
+
+ { SVGA3D_R16G16B16A16_SINT,
+ SVGA3DBLOCKDESC_RGBA_SINT,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 16 }, { 16 }, { 16 }, { 16 } },
+ { { 32 }, { 16 }, { 0 }, { 48 } } },
+
+ { SVGA3D_R32G32_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 32 }, { 32 }, { 0 } },
+ { { 0 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32G32_UINT,
+ SVGA3DBLOCKDESC_RG_UINT,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 32 }, { 32 }, { 0 } },
+ { { 0 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32G32_SINT,
+ SVGA3DBLOCKDESC_RG_SINT,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 32 }, { 32 }, { 0 } },
+ { { 0 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32G8X24_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 8 }, { 32 }, { 0 } },
+ { { 0 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_D32_FLOAT_S8X24_UINT,
+ SVGA3DBLOCKDESC_DS,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 8 }, { 32 }, { 0 } },
+ { { 0 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32_FLOAT_X8X24,
+ SVGA3DBLOCKDESC_R_FP,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 32 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_X32_G8X24_UINT,
+ SVGA3DBLOCKDESC_G_UINT,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 8 }, { 0 }, { 0 } },
+ { { 0 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R10G10B10A2_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 10 }, { 10 }, { 10 }, { 2 } },
+ { { 20 }, { 10 }, { 0 }, { 30 } } },
+
+ { SVGA3D_R10G10B10A2_UINT,
+ SVGA3DBLOCKDESC_RGBA_UINT,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 10 }, { 10 }, { 10 }, { 2 } },
+ { { 20 }, { 10 }, { 0 }, { 30 } } },
+
+ { SVGA3D_R11G11B10_FLOAT,
+ SVGA3DBLOCKDESC_RGB_FP,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 10 }, { 11 }, { 11 }, { 0 } },
+ { { 22 }, { 11 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8G8B8A8_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 16 }, { 8 }, { 0 }, { 24 } } },
+
+ { SVGA3D_R8G8B8A8_UNORM,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 16 }, { 8 }, { 0 }, { 24 } } },
+
+ { SVGA3D_R8G8B8A8_UNORM_SRGB,
+ SVGA3DBLOCKDESC_RGBA_UNORM_SRGB,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 16 }, { 8 }, { 0 }, { 24 } } },
+
+ { SVGA3D_R8G8B8A8_UINT,
+ SVGA3DBLOCKDESC_RGBA_UINT,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 16 }, { 8 }, { 0 }, { 24 } } },
+
+ { SVGA3D_R8G8B8A8_SINT,
+ SVGA3DBLOCKDESC_RGBA_SINT,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 16 }, { 8 }, { 0 }, { 24 } } },
+
+ { SVGA3D_R16G16_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16G16_UINT,
+ SVGA3DBLOCKDESC_RG_UINT,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16G16_SINT,
+ SVGA3DBLOCKDESC_RG_SINT,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 32 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_D32_FLOAT,
+ SVGA3DBLOCKDESC_DEPTH_FP,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 32 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32_UINT,
+ SVGA3DBLOCKDESC_R_UINT,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 32 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32_SINT,
+ SVGA3DBLOCKDESC_R_SINT,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 32 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R24G8_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 8 }, { 24 }, { 0 } },
+ { { 0 }, { 24 }, { 0 }, { 0 } } },
+
+ { SVGA3D_D24_UNORM_S8_UINT,
+ SVGA3DBLOCKDESC_DS_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 8 }, { 24 }, { 0 } },
+ { { 0 }, { 24 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R24_UNORM_X8,
+ SVGA3DBLOCKDESC_R_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 24 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_X24_G8_UINT,
+ SVGA3DBLOCKDESC_G_UINT,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 8 }, { 0 }, { 0 } },
+ { { 0 }, { 24 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8G8_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8G8_UNORM,
+ SVGA3DBLOCKDESC_RG_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8G8_UINT,
+ SVGA3DBLOCKDESC_RG_UINT,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8G8_SINT,
+ SVGA3DBLOCKDESC_RG_SINT,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16_UNORM,
+ SVGA3DBLOCKDESC_R_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16_UINT,
+ SVGA3DBLOCKDESC_R_UINT,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16_SNORM,
+ SVGA3DBLOCKDESC_R_SNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16_SINT,
+ SVGA3DBLOCKDESC_R_SINT,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8_UNORM,
+ SVGA3DBLOCKDESC_R_UNORM,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8_UINT,
+ SVGA3DBLOCKDESC_R_UINT,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8_SNORM,
+ SVGA3DBLOCKDESC_R_SNORM,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8_SINT,
+ SVGA3DBLOCKDESC_R_SINT,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_P8,
+ SVGA3DBLOCKDESC_NONE,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R9G9B9E5_SHAREDEXP,
+ SVGA3DBLOCKDESC_RGB_EXP,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 9 }, { 9 }, { 9 }, { 5 } },
+ { { 18 }, { 9 }, { 0 }, { 27 } } },
+
+ { SVGA3D_R8G8_B8G8_UNORM,
+ SVGA3DBLOCKDESC_NONE,
+ { 2, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 0 }, { 8 }, { 0 } } },
+
+ { SVGA3D_G8R8_G8B8_UNORM,
+ SVGA3DBLOCKDESC_NONE,
+ { 2, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC1_TYPELESS,
+ SVGA3DBLOCKDESC_BC1_COMP_TYPELESS,
+ { 4, 4, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 64 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC1_UNORM_SRGB,
+ SVGA3DBLOCKDESC_BC1_COMP_UNORM_SRGB,
+ { 4, 4, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 64 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC2_TYPELESS,
+ SVGA3DBLOCKDESC_BC2_COMP_TYPELESS,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC2_UNORM_SRGB,
+ SVGA3DBLOCKDESC_BC2_COMP_UNORM_SRGB,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC3_TYPELESS,
+ SVGA3DBLOCKDESC_BC3_COMP_TYPELESS,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC3_UNORM_SRGB,
+ SVGA3DBLOCKDESC_BC3_COMP_UNORM_SRGB,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC4_TYPELESS,
+ SVGA3DBLOCKDESC_BC4_COMP_TYPELESS,
+ { 4, 4, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 64 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_ATI1,
+ SVGA3DBLOCKDESC_BC4_COMP_UNORM,
+ { 4, 4, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 64 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC4_SNORM,
+ SVGA3DBLOCKDESC_BC4_COMP_SNORM,
+ { 4, 4, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 64 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC5_TYPELESS,
+ SVGA3DBLOCKDESC_BC5_COMP_TYPELESS,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_ATI2,
+ SVGA3DBLOCKDESC_BC5_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC5_SNORM,
+ SVGA3DBLOCKDESC_BC5_COMP_SNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R10G10B10_XR_BIAS_A2_UNORM,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 10 }, { 10 }, { 10 }, { 2 } },
+ { { 20 }, { 10 }, { 0 }, { 30 } } },
+
+ { SVGA3D_B8G8R8A8_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_B8G8R8A8_UNORM_SRGB,
+ SVGA3DBLOCKDESC_RGBA_UNORM_SRGB,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_B8G8R8X8_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_B8G8R8X8_UNORM_SRGB,
+ SVGA3DBLOCKDESC_RGB_UNORM_SRGB,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_Z_DF16,
+ SVGA3DBLOCKDESC_DEPTH_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_Z_DF24,
+ SVGA3DBLOCKDESC_DEPTH_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 24 }, { 0 } },
+ { { 0 }, { 0 }, { 8 }, { 0 } } },
+
+ { SVGA3D_Z_D24S8_INT,
+ SVGA3DBLOCKDESC_DS_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 8 }, { 24 }, { 0 } },
+ { { 0 }, { 0 }, { 8 }, { 0 } } },
+
+ { SVGA3D_YV12,
+ SVGA3DBLOCKDESC_YV12,
+ { 2, 2, 1 },
+ 6,
+ 2,
+ { { 0 }, { 0 }, { 48 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32G32B32A32_FLOAT,
+ SVGA3DBLOCKDESC_RGBA_FP,
+ { 1, 1, 1 },
+ 16,
+ 16,
+ { { 32 }, { 32 }, { 32 }, { 32 } },
+ { { 64 }, { 32 }, { 0 }, { 96 } } },
+
+ { SVGA3D_R16G16B16A16_FLOAT,
+ SVGA3DBLOCKDESC_RGBA_FP,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 16 }, { 16 }, { 16 }, { 16 } },
+ { { 32 }, { 16 }, { 0 }, { 48 } } },
+
+ { SVGA3D_R16G16B16A16_UNORM,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 16 }, { 16 }, { 16 }, { 16 } },
+ { { 32 }, { 16 }, { 0 }, { 48 } } },
+
+ { SVGA3D_R32G32_FLOAT,
+ SVGA3DBLOCKDESC_RG_FP,
+ { 1, 1, 1 },
+ 8,
+ 8,
+ { { 0 }, { 32 }, { 32 }, { 0 } },
+ { { 0 }, { 32 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R10G10B10A2_UNORM,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 10 }, { 10 }, { 10 }, { 2 } },
+ { { 20 }, { 10 }, { 0 }, { 30 } } },
+
+ { SVGA3D_R8G8B8A8_SNORM,
+ SVGA3DBLOCKDESC_RGBA_SNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 16 }, { 8 }, { 0 }, { 24 } } },
+
+ { SVGA3D_R16G16_FLOAT,
+ SVGA3DBLOCKDESC_RG_FP,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16G16_UNORM,
+ SVGA3DBLOCKDESC_RG_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16G16_SNORM,
+ SVGA3DBLOCKDESC_RG_SNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 16 }, { 16 }, { 0 } },
+ { { 0 }, { 16 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R32_FLOAT,
+ SVGA3DBLOCKDESC_R_FP,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 0 }, { 0 }, { 32 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R8G8_SNORM,
+ SVGA3DBLOCKDESC_RG_SNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 0 }, { 0 } } },
+
+ { SVGA3D_R16_FLOAT,
+ SVGA3DBLOCKDESC_R_FP,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_D16_UNORM,
+ SVGA3DBLOCKDESC_DEPTH_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 0 }, { 0 }, { 16 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_A8_UNORM,
+ SVGA3DBLOCKDESC_A_UNORM,
+ { 1, 1, 1 },
+ 1,
+ 1,
+ { { 0 }, { 0 }, { 0 }, { 8 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC1_UNORM,
+ SVGA3DBLOCKDESC_BC1_COMP_UNORM,
+ { 4, 4, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 64 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC2_UNORM,
+ SVGA3DBLOCKDESC_BC2_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC3_UNORM,
+ SVGA3DBLOCKDESC_BC3_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_B5G6R5_UNORM,
+ SVGA3DBLOCKDESC_RGB_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 5 }, { 6 }, { 5 }, { 0 } },
+ { { 0 }, { 5 }, { 11 }, { 0 } } },
+
+ { SVGA3D_B5G5R5A1_UNORM,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 5 }, { 5 }, { 5 }, { 1 } },
+ { { 0 }, { 5 }, { 10 }, { 15 } } },
+
+ { SVGA3D_B8G8R8A8_UNORM,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_B8G8R8X8_UNORM,
+ SVGA3DBLOCKDESC_RGB_UNORM,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 0 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_BC4_UNORM,
+ SVGA3DBLOCKDESC_BC4_COMP_UNORM,
+ { 4, 4, 1 },
+ 8,
+ 8,
+ { { 0 }, { 0 }, { 64 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC5_UNORM,
+ SVGA3DBLOCKDESC_BC5_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_B4G4R4A4_UNORM,
+ SVGA3DBLOCKDESC_RGBA_UNORM,
+ { 1, 1, 1 },
+ 2,
+ 2,
+ { { 4 }, { 4 }, { 4 }, { 4 } },
+ { { 0 }, { 4 }, { 8 }, { 12 } } },
+
+ { SVGA3D_BC6H_TYPELESS,
+ SVGA3DBLOCKDESC_BC6H_COMP_TYPELESS,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC6H_UF16,
+ SVGA3DBLOCKDESC_BC6H_COMP_UF16,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC6H_SF16,
+ SVGA3DBLOCKDESC_BC6H_COMP_SF16,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC7_TYPELESS,
+ SVGA3DBLOCKDESC_BC7_COMP_TYPELESS,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC7_UNORM,
+ SVGA3DBLOCKDESC_BC7_COMP_UNORM,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_BC7_UNORM_SRGB,
+ SVGA3DBLOCKDESC_BC7_COMP_UNORM_SRGB,
+ { 4, 4, 1 },
+ 16,
+ 16,
+ { { 0 }, { 0 }, { 128 }, { 0 } },
+ { { 0 }, { 0 }, { 0 }, { 0 } } },
+
+ { SVGA3D_AYUV,
+ SVGA3DBLOCKDESC_AYUV,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 8 }, { 8 }, { 8 }, { 8 } },
+ { { 0 }, { 8 }, { 16 }, { 24 } } },
+
+ { SVGA3D_R11G11B10_TYPELESS,
+ SVGA3DBLOCKDESC_TYPELESS,
+ { 1, 1, 1 },
+ 4,
+ 4,
+ { { 10 }, { 11 }, { 11 }, { 0 } },
+ { { 22 }, { 11 }, { 0 }, { 0 } } },
};
-/**
- * svga3dsurface_subres - Compute the subresource from layer and mipmap.
- * @cache: Surface layout data.
- * @mip_level: The mipmap level.
- * @layer: The surface layer (face or array slice).
- *
- * Return: The subresource.
- */
-static inline u32 svga3dsurface_subres(const struct svga3dsurface_cache *cache,
- u32 mip_level, u32 layer)
-{
- return cache->num_mip_levels * layer + mip_level;
-}
-
-/**
- * svga3dsurface_setup_cache - Build a surface cache entry
- * @size: The surface base level dimensions.
- * @format: The surface format.
- * @num_mip_levels: Number of mipmap levels.
- * @num_layers: Number of layers.
- * @cache: Pointer to a struct svga3dsurface_cach object to be filled in.
- *
- * Return: Zero on success, -EINVAL on invalid surface layout.
- */
-static inline int svga3dsurface_setup_cache(const struct drm_vmw_size *size,
- SVGA3dSurfaceFormat format,
- u32 num_mip_levels,
- u32 num_layers,
- u32 num_samples,
- struct svga3dsurface_cache *cache)
-{
- const struct svga3d_surface_desc *desc;
- u32 i;
-
- memset(cache, 0, sizeof(*cache));
- cache->desc = desc = svga3dsurface_get_desc(format);
- cache->num_mip_levels = num_mip_levels;
- cache->num_layers = num_layers;
- for (i = 0; i < cache->num_mip_levels; i++) {
- struct svga3dsurface_mip *mip = &cache->mip[i];
-
- mip->size = svga3dsurface_get_mip_size(*size, i);
- mip->bytes = svga3dsurface_get_image_buffer_size
- (desc, &mip->size, 0);
- mip->row_stride =
- __KERNEL_DIV_ROUND_UP(mip->size.width,
- desc->block_size.width) *
- desc->bytes_per_block * num_samples;
- if (!mip->row_stride)
- goto invalid_dim;
-
- mip->img_stride =
- __KERNEL_DIV_ROUND_UP(mip->size.height,
- desc->block_size.height) *
- mip->row_stride;
- if (!mip->img_stride)
- goto invalid_dim;
-
- cache->mip_chain_bytes += mip->bytes;
- }
- cache->sheet_bytes = cache->mip_chain_bytes * num_layers;
- if (!cache->sheet_bytes)
- goto invalid_dim;
-
- return 0;
-
-invalid_dim:
- VMW_DEBUG_USER("Invalid surface layout for dirty tracking.\n");
- return -EINVAL;
-}
-
-/**
- * svga3dsurface_get_loc - Get a surface location from an offset into the
- * backing store
- * @cache: Surface layout data.
- * @loc: Pointer to a struct svga3dsurface_loc to be filled in.
- * @offset: Offset into the surface backing store.
- */
-static inline void
-svga3dsurface_get_loc(const struct svga3dsurface_cache *cache,
- struct svga3dsurface_loc *loc,
- size_t offset)
-{
- const struct svga3dsurface_mip *mip = &cache->mip[0];
- const struct svga3d_surface_desc *desc = cache->desc;
- u32 layer;
- int i;
-
- loc->sheet = offset / cache->sheet_bytes;
- offset -= loc->sheet * cache->sheet_bytes;
-
- layer = offset / cache->mip_chain_bytes;
- offset -= layer * cache->mip_chain_bytes;
- for (i = 0; i < cache->num_mip_levels; ++i, ++mip) {
- if (mip->bytes > offset)
- break;
- offset -= mip->bytes;
- }
-
- loc->sub_resource = svga3dsurface_subres(cache, i, layer);
- loc->z = offset / mip->img_stride;
- offset -= loc->z * mip->img_stride;
- loc->z *= desc->block_size.depth;
- loc->y = offset / mip->row_stride;
- offset -= loc->y * mip->row_stride;
- loc->y *= desc->block_size.height;
- loc->x = offset / desc->bytes_per_block;
- loc->x *= desc->block_size.width;
-}
-
-/**
- * svga3dsurface_inc_loc - Clamp increment a surface location with one block
- * size
- * in each dimension.
- * @loc: Pointer to a struct svga3dsurface_loc to be incremented.
- *
- * When computing the size of a range as size = end - start, the range does not
- * include the end element. However a location representing the last byte
- * of a touched region in the backing store *is* included in the range.
- * This function modifies such a location to match the end definition
- * given as start + size which is the one used in a SVGA3dBox.
- */
-static inline void
-svga3dsurface_inc_loc(const struct svga3dsurface_cache *cache,
- struct svga3dsurface_loc *loc)
-{
- const struct svga3d_surface_desc *desc = cache->desc;
- u32 mip = loc->sub_resource % cache->num_mip_levels;
- const struct drm_vmw_size *size = &cache->mip[mip].size;
-
- loc->sub_resource++;
- loc->x += desc->block_size.width;
- if (loc->x > size->width)
- loc->x = size->width;
- loc->y += desc->block_size.height;
- if (loc->y > size->height)
- loc->y = size->height;
- loc->z += desc->block_size.depth;
- if (loc->z > size->depth)
- loc->z = size->depth;
-}
-
-/**
- * svga3dsurface_min_loc - The start location in a subresource
- * @cache: Surface layout data.
- * @sub_resource: The subresource.
- * @loc: Pointer to a struct svga3dsurface_loc to be filled in.
- */
-static inline void
-svga3dsurface_min_loc(const struct svga3dsurface_cache *cache,
- u32 sub_resource,
- struct svga3dsurface_loc *loc)
-{
- loc->sheet = 0;
- loc->sub_resource = sub_resource;
- loc->x = loc->y = loc->z = 0;
-}
-
-/**
- * svga3dsurface_min_loc - The end location in a subresource
- * @cache: Surface layout data.
- * @sub_resource: The subresource.
- * @loc: Pointer to a struct svga3dsurface_loc to be filled in.
- *
- * Following the end definition given in svga3dsurface_inc_loc(),
- * Compute the end location of a surface subresource.
- */
-static inline void
-svga3dsurface_max_loc(const struct svga3dsurface_cache *cache,
- u32 sub_resource,
- struct svga3dsurface_loc *loc)
-{
- const struct drm_vmw_size *size;
- u32 mip;
-
- loc->sheet = 0;
- loc->sub_resource = sub_resource + 1;
- mip = sub_resource % cache->num_mip_levels;
- size = &cache->mip[mip].size;
- loc->x = size->width;
- loc->y = size->height;
- loc->z = size->depth;
+#ifdef __cplusplus
}
+#endif
-#endif /* _SVGA3D_SURFACEDEFS_H_ */
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_types.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_types.h
index 77e338a65791..70b88ee16cf6 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_types.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_types.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
- * Copyright 2012-2015 VMware, Inc.
+ * Copyright 2012-2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -27,1974 +27,1530 @@
/*
* svga3d_types.h --
*
- * SVGA 3d hardware definitions for basic types
+ * SVGA 3d hardware definitions for basic types
*/
+
+
#ifndef _SVGA3D_TYPES_H_
#define _SVGA3D_TYPES_H_
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-
-#include "includeCheck.h"
+#include "vm_basic_types.h"
-/*
- * Generic Types
- */
+#define SVGA3D_INVALID_ID ((uint32)-1)
-#define SVGA3D_INVALID_ID ((uint32)-1)
+#define SVGA3D_RESOURCE_TYPE_MIN 1
+#define SVGA3D_RESOURCE_BUFFER 1
+#define SVGA3D_RESOURCE_TEXTURE1D 2
+#define SVGA3D_RESOURCE_TEXTURE2D 3
+#define SVGA3D_RESOURCE_TEXTURE3D 4
+#define SVGA3D_RESOURCE_TEXTURECUBE 5
+#define SVGA3D_RESOURCE_TYPE_DX10_MAX 6
+#define SVGA3D_RESOURCE_BUFFEREX 6
+#define SVGA3D_RESOURCE_TYPE_MAX 7
+typedef uint32 SVGA3dResourceType;
-typedef uint8 SVGABool8; /* 8-bit Bool definition */
-typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
-typedef uint32 SVGA3dColor; /* a, r, g, b */
+typedef uint8 SVGABool8;
+typedef uint32 SVGA3dBool;
+typedef uint32 SVGA3dColor;
typedef uint32 SVGA3dSurfaceId;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 numerator;
- uint32 denominator;
-}
-#include "vmware_pack_end.h"
-SVGA3dFraction64;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCopyRect {
- uint32 x;
- uint32 y;
- uint32 w;
- uint32 h;
- uint32 srcx;
- uint32 srcy;
-}
-#include "vmware_pack_end.h"
-SVGA3dCopyRect;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dCopyBox {
- uint32 x;
- uint32 y;
- uint32 z;
- uint32 w;
- uint32 h;
- uint32 d;
- uint32 srcx;
- uint32 srcy;
- uint32 srcz;
-}
-#include "vmware_pack_end.h"
-SVGA3dCopyBox;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dRect {
- uint32 x;
- uint32 y;
- uint32 w;
- uint32 h;
-}
-#include "vmware_pack_end.h"
-SVGA3dRect;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 x;
- uint32 y;
- uint32 z;
- uint32 w;
- uint32 h;
- uint32 d;
-}
-#include "vmware_pack_end.h"
-SVGA3dBox;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- int32 x;
- int32 y;
- int32 z;
- int32 w;
- int32 h;
- int32 d;
-}
-#include "vmware_pack_end.h"
-SVGA3dSignedBox;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 x;
- uint32 y;
- uint32 z;
-}
-#include "vmware_pack_end.h"
-SVGA3dPoint;
+#pragma pack(push, 1)
+typedef struct {
+ uint32 numerator;
+ uint32 denominator;
+} SVGA3dFraction64;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCopyRect {
+ uint32 x;
+ uint32 y;
+ uint32 w;
+ uint32 h;
+ uint32 srcx;
+ uint32 srcy;
+} SVGA3dCopyRect;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dCopyBox {
+ uint32 x;
+ uint32 y;
+ uint32 z;
+ uint32 w;
+ uint32 h;
+ uint32 d;
+ uint32 srcx;
+ uint32 srcy;
+ uint32 srcz;
+} SVGA3dCopyBox;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dRect {
+ uint32 x;
+ uint32 y;
+ uint32 w;
+ uint32 h;
+} SVGA3dRect;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 x;
+ uint32 y;
+ uint32 z;
+ uint32 w;
+ uint32 h;
+ uint32 d;
+} SVGA3dBox;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ int32 x;
+ int32 y;
+ int32 z;
+ int32 w;
+ int32 h;
+ int32 d;
+} SVGA3dSignedBox;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 x;
+ uint32 y;
+ uint32 z;
+} SVGA3dPoint;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef union {
+ struct {
+ float r;
+ float g;
+ float b;
+ float a;
+ };
+
+ float value[4];
+} SVGA3dRGBAFloat;
+#pragma pack(pop)
-/*
- * Surface formats.
- */
typedef enum SVGA3dSurfaceFormat {
- SVGA3D_FORMAT_INVALID = 0,
-
- SVGA3D_X8R8G8B8 = 1,
- SVGA3D_FORMAT_MIN = 1,
-
- SVGA3D_A8R8G8B8 = 2,
-
- SVGA3D_R5G6B5 = 3,
- SVGA3D_X1R5G5B5 = 4,
- SVGA3D_A1R5G5B5 = 5,
- SVGA3D_A4R4G4B4 = 6,
-
- SVGA3D_Z_D32 = 7,
- SVGA3D_Z_D16 = 8,
- SVGA3D_Z_D24S8 = 9,
- SVGA3D_Z_D15S1 = 10,
-
- SVGA3D_LUMINANCE8 = 11,
- SVGA3D_LUMINANCE4_ALPHA4 = 12,
- SVGA3D_LUMINANCE16 = 13,
- SVGA3D_LUMINANCE8_ALPHA8 = 14,
-
- SVGA3D_DXT1 = 15,
- SVGA3D_DXT2 = 16,
- SVGA3D_DXT3 = 17,
- SVGA3D_DXT4 = 18,
- SVGA3D_DXT5 = 19,
-
- SVGA3D_BUMPU8V8 = 20,
- SVGA3D_BUMPL6V5U5 = 21,
- SVGA3D_BUMPX8L8V8U8 = 22,
- SVGA3D_FORMAT_DEAD1 = 23,
-
- SVGA3D_ARGB_S10E5 = 24, /* 16-bit floating-point ARGB */
- SVGA3D_ARGB_S23E8 = 25, /* 32-bit floating-point ARGB */
-
- SVGA3D_A2R10G10B10 = 26,
-
- /* signed formats */
- SVGA3D_V8U8 = 27,
- SVGA3D_Q8W8V8U8 = 28,
- SVGA3D_CxV8U8 = 29,
-
- /* mixed formats */
- SVGA3D_X8L8V8U8 = 30,
- SVGA3D_A2W10V10U10 = 31,
-
- SVGA3D_ALPHA8 = 32,
-
- /* Single- and dual-component floating point formats */
- SVGA3D_R_S10E5 = 33,
- SVGA3D_R_S23E8 = 34,
- SVGA3D_RG_S10E5 = 35,
- SVGA3D_RG_S23E8 = 36,
-
- SVGA3D_BUFFER = 37,
-
- SVGA3D_Z_D24X8 = 38,
-
- SVGA3D_V16U16 = 39,
-
- SVGA3D_G16R16 = 40,
- SVGA3D_A16B16G16R16 = 41,
-
- /* Packed Video formats */
- SVGA3D_UYVY = 42,
- SVGA3D_YUY2 = 43,
-
- /* Planar video formats */
- SVGA3D_NV12 = 44,
-
- SVGA3D_FORMAT_DEAD2 = 45,
-
- SVGA3D_R32G32B32A32_TYPELESS = 46,
- SVGA3D_R32G32B32A32_UINT = 47,
- SVGA3D_R32G32B32A32_SINT = 48,
- SVGA3D_R32G32B32_TYPELESS = 49,
- SVGA3D_R32G32B32_FLOAT = 50,
- SVGA3D_R32G32B32_UINT = 51,
- SVGA3D_R32G32B32_SINT = 52,
- SVGA3D_R16G16B16A16_TYPELESS = 53,
- SVGA3D_R16G16B16A16_UINT = 54,
- SVGA3D_R16G16B16A16_SNORM = 55,
- SVGA3D_R16G16B16A16_SINT = 56,
- SVGA3D_R32G32_TYPELESS = 57,
- SVGA3D_R32G32_UINT = 58,
- SVGA3D_R32G32_SINT = 59,
- SVGA3D_R32G8X24_TYPELESS = 60,
- SVGA3D_D32_FLOAT_S8X24_UINT = 61,
- SVGA3D_R32_FLOAT_X8X24 = 62,
- SVGA3D_X32_G8X24_UINT = 63,
- SVGA3D_R10G10B10A2_TYPELESS = 64,
- SVGA3D_R10G10B10A2_UINT = 65,
- SVGA3D_R11G11B10_FLOAT = 66,
- SVGA3D_R8G8B8A8_TYPELESS = 67,
- SVGA3D_R8G8B8A8_UNORM = 68,
- SVGA3D_R8G8B8A8_UNORM_SRGB = 69,
- SVGA3D_R8G8B8A8_UINT = 70,
- SVGA3D_R8G8B8A8_SINT = 71,
- SVGA3D_R16G16_TYPELESS = 72,
- SVGA3D_R16G16_UINT = 73,
- SVGA3D_R16G16_SINT = 74,
- SVGA3D_R32_TYPELESS = 75,
- SVGA3D_D32_FLOAT = 76,
- SVGA3D_R32_UINT = 77,
- SVGA3D_R32_SINT = 78,
- SVGA3D_R24G8_TYPELESS = 79,
- SVGA3D_D24_UNORM_S8_UINT = 80,
- SVGA3D_R24_UNORM_X8 = 81,
- SVGA3D_X24_G8_UINT = 82,
- SVGA3D_R8G8_TYPELESS = 83,
- SVGA3D_R8G8_UNORM = 84,
- SVGA3D_R8G8_UINT = 85,
- SVGA3D_R8G8_SINT = 86,
- SVGA3D_R16_TYPELESS = 87,
- SVGA3D_R16_UNORM = 88,
- SVGA3D_R16_UINT = 89,
- SVGA3D_R16_SNORM = 90,
- SVGA3D_R16_SINT = 91,
- SVGA3D_R8_TYPELESS = 92,
- SVGA3D_R8_UNORM = 93,
- SVGA3D_R8_UINT = 94,
- SVGA3D_R8_SNORM = 95,
- SVGA3D_R8_SINT = 96,
- SVGA3D_P8 = 97,
- SVGA3D_R9G9B9E5_SHAREDEXP = 98,
- SVGA3D_R8G8_B8G8_UNORM = 99,
- SVGA3D_G8R8_G8B8_UNORM = 100,
- SVGA3D_BC1_TYPELESS = 101,
- SVGA3D_BC1_UNORM_SRGB = 102,
- SVGA3D_BC2_TYPELESS = 103,
- SVGA3D_BC2_UNORM_SRGB = 104,
- SVGA3D_BC3_TYPELESS = 105,
- SVGA3D_BC3_UNORM_SRGB = 106,
- SVGA3D_BC4_TYPELESS = 107,
- SVGA3D_ATI1 = 108, /* DX9-specific BC4_UNORM */
- SVGA3D_BC4_SNORM = 109,
- SVGA3D_BC5_TYPELESS = 110,
- SVGA3D_ATI2 = 111, /* DX9-specific BC5_UNORM */
- SVGA3D_BC5_SNORM = 112,
- SVGA3D_R10G10B10_XR_BIAS_A2_UNORM = 113,
- SVGA3D_B8G8R8A8_TYPELESS = 114,
- SVGA3D_B8G8R8A8_UNORM_SRGB = 115,
- SVGA3D_B8G8R8X8_TYPELESS = 116,
- SVGA3D_B8G8R8X8_UNORM_SRGB = 117,
-
- /* Advanced depth formats. */
- SVGA3D_Z_DF16 = 118,
- SVGA3D_Z_DF24 = 119,
- SVGA3D_Z_D24S8_INT = 120,
-
- /* Planar video formats. */
- SVGA3D_YV12 = 121,
-
- SVGA3D_R32G32B32A32_FLOAT = 122,
- SVGA3D_R16G16B16A16_FLOAT = 123,
- SVGA3D_R16G16B16A16_UNORM = 124,
- SVGA3D_R32G32_FLOAT = 125,
- SVGA3D_R10G10B10A2_UNORM = 126,
- SVGA3D_R8G8B8A8_SNORM = 127,
- SVGA3D_R16G16_FLOAT = 128,
- SVGA3D_R16G16_UNORM = 129,
- SVGA3D_R16G16_SNORM = 130,
- SVGA3D_R32_FLOAT = 131,
- SVGA3D_R8G8_SNORM = 132,
- SVGA3D_R16_FLOAT = 133,
- SVGA3D_D16_UNORM = 134,
- SVGA3D_A8_UNORM = 135,
- SVGA3D_BC1_UNORM = 136,
- SVGA3D_BC2_UNORM = 137,
- SVGA3D_BC3_UNORM = 138,
- SVGA3D_B5G6R5_UNORM = 139,
- SVGA3D_B5G5R5A1_UNORM = 140,
- SVGA3D_B8G8R8A8_UNORM = 141,
- SVGA3D_B8G8R8X8_UNORM = 142,
- SVGA3D_BC4_UNORM = 143,
- SVGA3D_BC5_UNORM = 144,
- SVGA3D_B4G4R4A4_UNORM = 145,
-
- /* DX11 compressed formats */
- SVGA3D_BC6H_TYPELESS = 146,
- SVGA3D_BC6H_UF16 = 147,
- SVGA3D_BC6H_SF16 = 148,
- SVGA3D_BC7_TYPELESS = 149,
- SVGA3D_BC7_UNORM = 150,
- SVGA3D_BC7_UNORM_SRGB = 151,
-
- /* Video format with alpha */
- SVGA3D_AYUV = 152,
-
- SVGA3D_FORMAT_MAX
+ SVGA3D_FORMAT_INVALID = 0,
+
+ SVGA3D_X8R8G8B8 = 1,
+ SVGA3D_FORMAT_MIN = 1,
+
+ SVGA3D_A8R8G8B8 = 2,
+
+ SVGA3D_R5G6B5 = 3,
+ SVGA3D_X1R5G5B5 = 4,
+ SVGA3D_A1R5G5B5 = 5,
+ SVGA3D_A4R4G4B4 = 6,
+
+ SVGA3D_Z_D32 = 7,
+ SVGA3D_Z_D16 = 8,
+ SVGA3D_Z_D24S8 = 9,
+ SVGA3D_Z_D15S1 = 10,
+
+ SVGA3D_LUMINANCE8 = 11,
+ SVGA3D_LUMINANCE4_ALPHA4 = 12,
+ SVGA3D_LUMINANCE16 = 13,
+ SVGA3D_LUMINANCE8_ALPHA8 = 14,
+
+ SVGA3D_DXT1 = 15,
+ SVGA3D_DXT2 = 16,
+ SVGA3D_DXT3 = 17,
+ SVGA3D_DXT4 = 18,
+ SVGA3D_DXT5 = 19,
+
+ SVGA3D_BUMPU8V8 = 20,
+ SVGA3D_BUMPL6V5U5 = 21,
+ SVGA3D_BUMPX8L8V8U8 = 22,
+ SVGA3D_FORMAT_DEAD1 = 23,
+
+ SVGA3D_ARGB_S10E5 = 24,
+ SVGA3D_ARGB_S23E8 = 25,
+
+ SVGA3D_A2R10G10B10 = 26,
+
+ SVGA3D_V8U8 = 27,
+ SVGA3D_Q8W8V8U8 = 28,
+ SVGA3D_CxV8U8 = 29,
+
+ SVGA3D_X8L8V8U8 = 30,
+ SVGA3D_A2W10V10U10 = 31,
+
+ SVGA3D_ALPHA8 = 32,
+
+ SVGA3D_R_S10E5 = 33,
+ SVGA3D_R_S23E8 = 34,
+ SVGA3D_RG_S10E5 = 35,
+ SVGA3D_RG_S23E8 = 36,
+
+ SVGA3D_BUFFER = 37,
+
+ SVGA3D_Z_D24X8 = 38,
+
+ SVGA3D_V16U16 = 39,
+
+ SVGA3D_G16R16 = 40,
+ SVGA3D_A16B16G16R16 = 41,
+
+ SVGA3D_UYVY = 42,
+ SVGA3D_YUY2 = 43,
+
+ SVGA3D_NV12 = 44,
+
+ SVGA3D_FORMAT_DEAD2 = 45,
+
+ SVGA3D_R32G32B32A32_TYPELESS = 46,
+ SVGA3D_R32G32B32A32_UINT = 47,
+ SVGA3D_R32G32B32A32_SINT = 48,
+ SVGA3D_R32G32B32_TYPELESS = 49,
+ SVGA3D_R32G32B32_FLOAT = 50,
+ SVGA3D_R32G32B32_UINT = 51,
+ SVGA3D_R32G32B32_SINT = 52,
+ SVGA3D_R16G16B16A16_TYPELESS = 53,
+ SVGA3D_R16G16B16A16_UINT = 54,
+ SVGA3D_R16G16B16A16_SNORM = 55,
+ SVGA3D_R16G16B16A16_SINT = 56,
+ SVGA3D_R32G32_TYPELESS = 57,
+ SVGA3D_R32G32_UINT = 58,
+ SVGA3D_R32G32_SINT = 59,
+ SVGA3D_R32G8X24_TYPELESS = 60,
+ SVGA3D_D32_FLOAT_S8X24_UINT = 61,
+ SVGA3D_R32_FLOAT_X8X24 = 62,
+ SVGA3D_X32_G8X24_UINT = 63,
+ SVGA3D_R10G10B10A2_TYPELESS = 64,
+ SVGA3D_R10G10B10A2_UINT = 65,
+ SVGA3D_R11G11B10_FLOAT = 66,
+ SVGA3D_R8G8B8A8_TYPELESS = 67,
+ SVGA3D_R8G8B8A8_UNORM = 68,
+ SVGA3D_R8G8B8A8_UNORM_SRGB = 69,
+ SVGA3D_R8G8B8A8_UINT = 70,
+ SVGA3D_R8G8B8A8_SINT = 71,
+ SVGA3D_R16G16_TYPELESS = 72,
+ SVGA3D_R16G16_UINT = 73,
+ SVGA3D_R16G16_SINT = 74,
+ SVGA3D_R32_TYPELESS = 75,
+ SVGA3D_D32_FLOAT = 76,
+ SVGA3D_R32_UINT = 77,
+ SVGA3D_R32_SINT = 78,
+ SVGA3D_R24G8_TYPELESS = 79,
+ SVGA3D_D24_UNORM_S8_UINT = 80,
+ SVGA3D_R24_UNORM_X8 = 81,
+ SVGA3D_X24_G8_UINT = 82,
+ SVGA3D_R8G8_TYPELESS = 83,
+ SVGA3D_R8G8_UNORM = 84,
+ SVGA3D_R8G8_UINT = 85,
+ SVGA3D_R8G8_SINT = 86,
+ SVGA3D_R16_TYPELESS = 87,
+ SVGA3D_R16_UNORM = 88,
+ SVGA3D_R16_UINT = 89,
+ SVGA3D_R16_SNORM = 90,
+ SVGA3D_R16_SINT = 91,
+ SVGA3D_R8_TYPELESS = 92,
+ SVGA3D_R8_UNORM = 93,
+ SVGA3D_R8_UINT = 94,
+ SVGA3D_R8_SNORM = 95,
+ SVGA3D_R8_SINT = 96,
+ SVGA3D_P8 = 97,
+ SVGA3D_R9G9B9E5_SHAREDEXP = 98,
+ SVGA3D_R8G8_B8G8_UNORM = 99,
+ SVGA3D_G8R8_G8B8_UNORM = 100,
+ SVGA3D_BC1_TYPELESS = 101,
+ SVGA3D_BC1_UNORM_SRGB = 102,
+ SVGA3D_BC2_TYPELESS = 103,
+ SVGA3D_BC2_UNORM_SRGB = 104,
+ SVGA3D_BC3_TYPELESS = 105,
+ SVGA3D_BC3_UNORM_SRGB = 106,
+ SVGA3D_BC4_TYPELESS = 107,
+ SVGA3D_ATI1 = 108,
+ SVGA3D_BC4_SNORM = 109,
+ SVGA3D_BC5_TYPELESS = 110,
+ SVGA3D_ATI2 = 111,
+ SVGA3D_BC5_SNORM = 112,
+ SVGA3D_R10G10B10_XR_BIAS_A2_UNORM = 113,
+ SVGA3D_B8G8R8A8_TYPELESS = 114,
+ SVGA3D_B8G8R8A8_UNORM_SRGB = 115,
+ SVGA3D_B8G8R8X8_TYPELESS = 116,
+ SVGA3D_B8G8R8X8_UNORM_SRGB = 117,
+
+ SVGA3D_Z_DF16 = 118,
+ SVGA3D_Z_DF24 = 119,
+ SVGA3D_Z_D24S8_INT = 120,
+
+ SVGA3D_YV12 = 121,
+
+ SVGA3D_R32G32B32A32_FLOAT = 122,
+ SVGA3D_R16G16B16A16_FLOAT = 123,
+ SVGA3D_R16G16B16A16_UNORM = 124,
+ SVGA3D_R32G32_FLOAT = 125,
+ SVGA3D_R10G10B10A2_UNORM = 126,
+ SVGA3D_R8G8B8A8_SNORM = 127,
+ SVGA3D_R16G16_FLOAT = 128,
+ SVGA3D_R16G16_UNORM = 129,
+ SVGA3D_R16G16_SNORM = 130,
+ SVGA3D_R32_FLOAT = 131,
+ SVGA3D_R8G8_SNORM = 132,
+ SVGA3D_R16_FLOAT = 133,
+ SVGA3D_D16_UNORM = 134,
+ SVGA3D_A8_UNORM = 135,
+ SVGA3D_BC1_UNORM = 136,
+ SVGA3D_BC2_UNORM = 137,
+ SVGA3D_BC3_UNORM = 138,
+ SVGA3D_B5G6R5_UNORM = 139,
+ SVGA3D_B5G5R5A1_UNORM = 140,
+ SVGA3D_B8G8R8A8_UNORM = 141,
+ SVGA3D_B8G8R8X8_UNORM = 142,
+ SVGA3D_BC4_UNORM = 143,
+ SVGA3D_BC5_UNORM = 144,
+ SVGA3D_B4G4R4A4_UNORM = 145,
+
+ SVGA3D_BC6H_TYPELESS = 146,
+ SVGA3D_BC6H_UF16 = 147,
+ SVGA3D_BC6H_SF16 = 148,
+ SVGA3D_BC7_TYPELESS = 149,
+ SVGA3D_BC7_UNORM = 150,
+ SVGA3D_BC7_UNORM_SRGB = 151,
+
+ SVGA3D_AYUV = 152,
+
+ SVGA3D_R11G11B10_TYPELESS = 153,
+
+ SVGA3D_FORMAT_MAX
} SVGA3dSurfaceFormat;
-/*
- * SVGA3d Surface Flags --
- */
-#define SVGA3D_SURFACE_CUBEMAP (1 << 0)
+#define SVGA3D_SURFACE_CUBEMAP (1 << 0)
-/*
- * HINT flags are not enforced by the device but are useful for
- * performance.
- */
-#define SVGA3D_SURFACE_HINT_STATIC (CONST64U(1) << 1)
-#define SVGA3D_SURFACE_HINT_DYNAMIC (CONST64U(1) << 2)
-#define SVGA3D_SURFACE_HINT_INDEXBUFFER (CONST64U(1) << 3)
-#define SVGA3D_SURFACE_HINT_VERTEXBUFFER (CONST64U(1) << 4)
-#define SVGA3D_SURFACE_HINT_TEXTURE (CONST64U(1) << 5)
-#define SVGA3D_SURFACE_HINT_RENDERTARGET (CONST64U(1) << 6)
-#define SVGA3D_SURFACE_HINT_DEPTHSTENCIL (CONST64U(1) << 7)
-#define SVGA3D_SURFACE_HINT_WRITEONLY (CONST64U(1) << 8)
-#define SVGA3D_SURFACE_DEAD2 (CONST64U(1) << 9)
-#define SVGA3D_SURFACE_AUTOGENMIPMAPS (CONST64U(1) << 10)
-
-#define SVGA3D_SURFACE_DEAD1 (CONST64U(1) << 11)
+#define SVGA3D_SURFACE_HINT_STATIC (CONST64U(1) << 1)
+#define SVGA3D_SURFACE_HINT_DYNAMIC (CONST64U(1) << 2)
+#define SVGA3D_SURFACE_HINT_INDEXBUFFER (CONST64U(1) << 3)
+#define SVGA3D_SURFACE_HINT_VERTEXBUFFER (CONST64U(1) << 4)
+#define SVGA3D_SURFACE_HINT_TEXTURE (CONST64U(1) << 5)
+#define SVGA3D_SURFACE_HINT_RENDERTARGET (CONST64U(1) << 6)
+#define SVGA3D_SURFACE_HINT_DEPTHSTENCIL (CONST64U(1) << 7)
+#define SVGA3D_SURFACE_HINT_WRITEONLY (CONST64U(1) << 8)
+#define SVGA3D_SURFACE_DEAD2 (CONST64U(1) << 9)
+#define SVGA3D_SURFACE_AUTOGENMIPMAPS (CONST64U(1) << 10)
-/*
- * Is this surface using a base-level pitch for it's mob backing?
- *
- * This flag is not intended to be set by guest-drivers, but is instead
- * set by the device when the surface is bound to a mob with a specified
- * pitch.
- */
-#define SVGA3D_SURFACE_MOB_PITCH (CONST64U(1) << 12)
+#define SVGA3D_SURFACE_DEAD1 (CONST64U(1) << 11)
-#define SVGA3D_SURFACE_INACTIVE (CONST64U(1) << 13)
-#define SVGA3D_SURFACE_HINT_RT_LOCKABLE (CONST64U(1) << 14)
-#define SVGA3D_SURFACE_VOLUME (CONST64U(1) << 15)
+#define SVGA3D_SURFACE_MOB_PITCH (CONST64U(1) << 12)
-/*
- * Required to be set on a surface to bind it to a screen target.
- */
-#define SVGA3D_SURFACE_SCREENTARGET (CONST64U(1) << 16)
+#define SVGA3D_SURFACE_INACTIVE (CONST64U(1) << 13)
+#define SVGA3D_SURFACE_HINT_RT_LOCKABLE (CONST64U(1) << 14)
+#define SVGA3D_SURFACE_VOLUME (CONST64U(1) << 15)
-/*
- * Align images in the guest-backing mob to 16-bytes.
- */
-#define SVGA3D_SURFACE_ALIGN16 (CONST64U(1) << 17)
+#define SVGA3D_SURFACE_SCREENTARGET (CONST64U(1) << 16)
-#define SVGA3D_SURFACE_1D (CONST64U(1) << 18)
-#define SVGA3D_SURFACE_ARRAY (CONST64U(1) << 19)
+#define SVGA3D_SURFACE_ALIGN16 (CONST64U(1) << 17)
-/*
- * Bind flags.
- * These are enforced for any surface defined with DefineGBSurface_v2.
- */
-#define SVGA3D_SURFACE_BIND_VERTEX_BUFFER (CONST64U(1) << 20)
-#define SVGA3D_SURFACE_BIND_INDEX_BUFFER (CONST64U(1) << 21)
-#define SVGA3D_SURFACE_BIND_CONSTANT_BUFFER (CONST64U(1) << 22)
-#define SVGA3D_SURFACE_BIND_SHADER_RESOURCE (CONST64U(1) << 23)
-#define SVGA3D_SURFACE_BIND_RENDER_TARGET (CONST64U(1) << 24)
-#define SVGA3D_SURFACE_BIND_DEPTH_STENCIL (CONST64U(1) << 25)
-#define SVGA3D_SURFACE_BIND_STREAM_OUTPUT (CONST64U(1) << 26)
+#define SVGA3D_SURFACE_1D (CONST64U(1) << 18)
+#define SVGA3D_SURFACE_ARRAY (CONST64U(1) << 19)
-/*
- * The STAGING flags notes that the surface will not be used directly by the
- * drawing pipeline, i.e. that it will not be bound to any bind point.
- * Staging surfaces may be used by copy operations to move data in and out
- * of other surfaces. No bind flags may be set on surfaces with this flag.
- *
- * The HINT_INDIRECT_UPDATE flag suggests that the surface will receive
- * updates indirectly, i.e. the surface will not be updated directly, but
- * will receive copies from staging surfaces.
- */
-#define SVGA3D_SURFACE_STAGING_UPLOAD (CONST64U(1) << 27)
-#define SVGA3D_SURFACE_STAGING_DOWNLOAD (CONST64U(1) << 28)
-#define SVGA3D_SURFACE_HINT_INDIRECT_UPDATE (CONST64U(1) << 29)
+#define SVGA3D_SURFACE_BIND_VERTEX_BUFFER (CONST64U(1) << 20)
+#define SVGA3D_SURFACE_BIND_INDEX_BUFFER (CONST64U(1) << 21)
+#define SVGA3D_SURFACE_BIND_CONSTANT_BUFFER (CONST64U(1) << 22)
+#define SVGA3D_SURFACE_BIND_SHADER_RESOURCE (CONST64U(1) << 23)
+#define SVGA3D_SURFACE_BIND_RENDER_TARGET (CONST64U(1) << 24)
+#define SVGA3D_SURFACE_BIND_DEPTH_STENCIL (CONST64U(1) << 25)
+#define SVGA3D_SURFACE_BIND_STREAM_OUTPUT (CONST64U(1) << 26)
-/*
- * Setting this flag allow this surface to be used with the
- * SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER command. It is only valid for
- * buffer surfaces, and no bind flags are allowed to be set on surfaces
- * with this flag except SVGA3D_SURFACE_TRANSFER_TO_BUFFER.
- */
-#define SVGA3D_SURFACE_TRANSFER_FROM_BUFFER (CONST64U(1) << 30)
+#define SVGA3D_SURFACE_STAGING_UPLOAD (CONST64U(1) << 27)
+#define SVGA3D_SURFACE_STAGING_DOWNLOAD (CONST64U(1) << 28)
+#define SVGA3D_SURFACE_HINT_INDIRECT_UPDATE (CONST64U(1) << 29)
-/*
- * Reserved for video operations.
- */
-#define SVGA3D_SURFACE_RESERVED1 (CONST64U(1) << 31)
+#define SVGA3D_SURFACE_TRANSFER_FROM_BUFFER (CONST64U(1) << 30)
-/*
- * Specifies that a surface is multisample, and therefore requires the full
- * mob-backing to store all the samples.
- */
-#define SVGA3D_SURFACE_MULTISAMPLE (CONST64U(1) << 32)
+#define SVGA3D_SURFACE_RESERVED1 (CONST64U(1) << 31)
+#define SVGA3D_SURFACE_VADECODE SVGA3D_SURFACE_RESERVED1
-/*
- * Specified that the surface is allowed to be bound to a UAView.
- */
-#define SVGA3D_SURFACE_BIND_UAVIEW (CONST64U(1) << 33)
+#define SVGA3D_SURFACE_MULTISAMPLE (CONST64U(1) << 32)
-/*
- * Setting this flag allow this surface to be used with the
- * SVGA_3D_CMD_DX_TRANSFER_TO_BUFFER command. It is only valid for
- * buffer surfaces, and no bind flags are allowed to be set on surfaces
- * with this flag except SVGA3D_SURFACE_TRANSFER_FROM_BUFFER.
- */
-#define SVGA3D_SURFACE_TRANSFER_TO_BUFFER (CONST64U(1) << 34)
+#define SVGA3D_SURFACE_BIND_UAVIEW (CONST64U(1) << 33)
-#define SVGA3D_SURFACE_BIND_LOGICOPS (CONST64U(1) << 35)
+#define SVGA3D_SURFACE_TRANSFER_TO_BUFFER (CONST64U(1) << 34)
-/*
- * Optional flags for use with SVGA3D_SURFACE_BIND_UAVIEW
- */
-#define SVGA3D_SURFACE_BIND_RAW_VIEWS (CONST64U(1) << 36)
-#define SVGA3D_SURFACE_BUFFER_STRUCTURED (CONST64U(1) << 37)
+#define SVGA3D_SURFACE_BIND_LOGICOPS (CONST64U(1) << 35)
-#define SVGA3D_SURFACE_DRAWINDIRECT_ARGS (CONST64U(1) << 38)
-#define SVGA3D_SURFACE_RESOURCE_CLAMP (CONST64U(1) << 39)
+#define SVGA3D_SURFACE_BIND_RAW_VIEWS (CONST64U(1) << 36)
+#define SVGA3D_SURFACE_BUFFER_STRUCTURED (CONST64U(1) << 37)
-#define SVGA3D_SURFACE_FLAG_MAX (CONST64U(1) << 40)
+#define SVGA3D_SURFACE_DRAWINDIRECT_ARGS (CONST64U(1) << 38)
+#define SVGA3D_SURFACE_RESOURCE_CLAMP (CONST64U(1) << 39)
+
+#define SVGA3D_SURFACE_STAGING_COPY (CONST64U(1) << 40)
+
+#define SVGA3D_SURFACE_FLAG_MAX (CONST64U(1) << 44)
-/*
- * Surface flags types:
- *
- * SVGA3dSurface1Flags: Lower 32-bits of flags.
- * SVGA3dSurface2Flags: Upper 32-bits of flags.
- * SVGA3dSurfaceAllFlags: Full 64-bits of flags.
- */
typedef uint32 SVGA3dSurface1Flags;
typedef uint32 SVGA3dSurface2Flags;
typedef uint64 SVGA3dSurfaceAllFlags;
-#define SVGA3D_SURFACE_FLAGS1_MASK ((uint64_t)MAX_UINT32)
+#define SVGA3D_SURFACE_FLAGS1_MASK ((uint64)MAX_UINT32)
#define SVGA3D_SURFACE_FLAGS2_MASK (MAX_UINT64 & ~SVGA3D_SURFACE_FLAGS1_MASK)
-#define SVGA3D_SURFACE_HB_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_MOB_PITCH | \
- SVGA3D_SURFACE_SCREENTARGET | \
- SVGA3D_SURFACE_ALIGN16 | \
- SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
- SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_STAGING_UPLOAD | \
- SVGA3D_SURFACE_STAGING_DOWNLOAD | \
- SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_RESERVED1 | \
- SVGA3D_SURFACE_MULTISAMPLE | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
- SVGA3D_SURFACE_BIND_LOGICOPS | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS | \
- SVGA3D_SURFACE_BUFFER_STRUCTURED | \
- SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
- SVGA3D_SURFACE_RESOURCE_CLAMP \
- )
-
-#define SVGA3D_SURFACE_HB_PRESENT_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_RESERVED1 | \
- SVGA3D_SURFACE_MULTISAMPLE \
- )
-
-#define SVGA3D_SURFACE_2D_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_CUBEMAP | \
- SVGA3D_SURFACE_AUTOGENMIPMAPS | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
- SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
- SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
- SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
- SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_RESERVED1 | \
- SVGA3D_SURFACE_MULTISAMPLE | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS | \
- SVGA3D_SURFACE_BUFFER_STRUCTURED | \
- SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
- SVGA3D_SURFACE_RESOURCE_CLAMP \
- )
-
-#define SVGA3D_SURFACE_BASICOPS_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_CUBEMAP | \
- SVGA3D_SURFACE_AUTOGENMIPMAPS | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_RESERVED1 | \
- SVGA3D_SURFACE_MULTISAMPLE \
- )
-
-#define SVGA3D_SURFACE_SCREENTARGET_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_CUBEMAP | \
- SVGA3D_SURFACE_AUTOGENMIPMAPS | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
- SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
- SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
- SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
- SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_INACTIVE | \
- SVGA3D_SURFACE_STAGING_UPLOAD | \
- SVGA3D_SURFACE_STAGING_DOWNLOAD | \
- SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_RESERVED1 | \
- SVGA3D_SURFACE_MULTISAMPLE | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS | \
- SVGA3D_SURFACE_BUFFER_STRUCTURED | \
- SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
- SVGA3D_SURFACE_RESOURCE_CLAMP \
- )
-
-#define SVGA3D_SURFACE_BUFFER_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_CUBEMAP | \
- SVGA3D_SURFACE_AUTOGENMIPMAPS | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_DEAD2 | \
- SVGA3D_SURFACE_ARRAY | \
- SVGA3D_SURFACE_MULTISAMPLE | \
- SVGA3D_SURFACE_MOB_PITCH | \
- SVGA3D_SURFACE_RESOURCE_CLAMP \
- )
-
-#define SVGA3D_SURFACE_MULTISAMPLE_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_CUBEMAP | \
- SVGA3D_SURFACE_AUTOGENMIPMAPS | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_SCREENTARGET | \
- SVGA3D_SURFACE_MOB_PITCH | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_RESERVED1 | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
- SVGA3D_SURFACE_BIND_LOGICOPS | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS | \
- SVGA3D_SURFACE_BUFFER_STRUCTURED | \
- SVGA3D_SURFACE_DRAWINDIRECT_ARGS \
- )
-
-#define SVGA3D_SURFACE_DX_ONLY_MASK \
- ( SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_STAGING_UPLOAD | \
- SVGA3D_SURFACE_STAGING_DOWNLOAD | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER \
- )
-
-#define SVGA3D_SURFACE_STAGING_MASK \
- ( SVGA3D_SURFACE_STAGING_UPLOAD | \
- SVGA3D_SURFACE_STAGING_DOWNLOAD \
- )
-
-#define SVGA3D_SURFACE_BIND_MASK \
- ( SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
- SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
- SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
- SVGA3D_SURFACE_BIND_SHADER_RESOURCE | \
- SVGA3D_SURFACE_BIND_RENDER_TARGET | \
- SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
- SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_BIND_LOGICOPS | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS \
- )
-
-#define SVGA3D_SURFACE_VADECODE_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_CUBEMAP | \
- SVGA3D_SURFACE_HINT_STATIC | \
- SVGA3D_SURFACE_HINT_DYNAMIC | \
- SVGA3D_SURFACE_HINT_INDEXBUFFER | \
- SVGA3D_SURFACE_HINT_VERTEXBUFFER | \
- SVGA3D_SURFACE_HINT_TEXTURE | \
- SVGA3D_SURFACE_HINT_RENDERTARGET | \
- SVGA3D_SURFACE_HINT_DEPTHSTENCIL | \
- SVGA3D_SURFACE_HINT_WRITEONLY | \
- SVGA3D_SURFACE_DEAD2 | \
- SVGA3D_SURFACE_AUTOGENMIPMAPS | \
- SVGA3D_SURFACE_HINT_RT_LOCKABLE | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_SCREENTARGET | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
- SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
- SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
- SVGA3D_SURFACE_BIND_RENDER_TARGET | \
- SVGA3D_SURFACE_BIND_SHADER_RESOURCE | \
- SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
- SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_INACTIVE | \
- SVGA3D_SURFACE_STAGING_UPLOAD | \
- SVGA3D_SURFACE_STAGING_DOWNLOAD | \
- SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_MULTISAMPLE | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
- SVGA3D_SURFACE_BIND_LOGICOPS | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS | \
- SVGA3D_SURFACE_BUFFER_STRUCTURED | \
- SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
- SVGA3D_SURFACE_RESOURCE_CLAMP \
- )
-
-#define SVGA3D_SURFACE_VAPROCESSFRAME_OUTPUT_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_HINT_INDEXBUFFER | \
- SVGA3D_SURFACE_HINT_VERTEXBUFFER | \
- SVGA3D_SURFACE_HINT_DEPTHSTENCIL | \
- SVGA3D_SURFACE_DEAD2 | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
- SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
- SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
- SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
- SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_INACTIVE | \
- SVGA3D_SURFACE_STAGING_UPLOAD | \
- SVGA3D_SURFACE_STAGING_DOWNLOAD | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_VADECODE | \
- SVGA3D_SURFACE_MULTISAMPLE | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
- SVGA3D_SURFACE_BIND_LOGICOPS | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS | \
- SVGA3D_SURFACE_BUFFER_STRUCTURED | \
- SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
- SVGA3D_SURFACE_RESOURCE_CLAMP \
- )
-
-#define SVGA3D_SURFACE_VAPROCESSFRAME_INPUT_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_CUBEMAP | \
- SVGA3D_SURFACE_HINT_INDEXBUFFER | \
- SVGA3D_SURFACE_HINT_VERTEXBUFFER | \
- SVGA3D_SURFACE_HINT_DEPTHSTENCIL | \
- SVGA3D_SURFACE_DEAD2 | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_SCREENTARGET | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
- SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
- SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
- SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
- SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_STAGING_UPLOAD | \
- SVGA3D_SURFACE_STAGING_DOWNLOAD | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_MULTISAMPLE | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
- SVGA3D_SURFACE_BIND_LOGICOPS | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS | \
- SVGA3D_SURFACE_BUFFER_STRUCTURED | \
- SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
- SVGA3D_SURFACE_RESOURCE_CLAMP \
- )
-
-#define SVGA3D_SURFACE_LOGICOPS_DISALLOWED_MASK \
- ( SVGA3D_SURFACE_CUBEMAP | \
- SVGA3D_SURFACE_DEAD2 | \
- SVGA3D_SURFACE_AUTOGENMIPMAPS | \
- SVGA3D_SURFACE_VOLUME | \
- SVGA3D_SURFACE_1D | \
- SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
- SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
- SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
- SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
- SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
- SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
- SVGA3D_SURFACE_VADECODE | \
- SVGA3D_SURFACE_MULTISAMPLE | \
- SVGA3D_SURFACE_BIND_UAVIEW | \
- SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
- SVGA3D_SURFACE_BIND_RAW_VIEWS | \
- SVGA3D_SURFACE_BUFFER_STRUCTURED | \
- SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
- SVGA3D_SURFACE_RESOURCE_CLAMP \
- )
+#define SVGA3D_SURFACE_HB_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_MOB_PITCH | SVGA3D_SURFACE_SCREENTARGET | \
+ SVGA3D_SURFACE_ALIGN16 | SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
+ SVGA3D_SURFACE_BIND_STREAM_OUTPUT | SVGA3D_SURFACE_STAGING_UPLOAD | \
+ SVGA3D_SURFACE_STAGING_DOWNLOAD | \
+ SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \
+ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | SVGA3D_SURFACE_MULTISAMPLE | \
+ SVGA3D_SURFACE_BIND_UAVIEW | SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
+ SVGA3D_SURFACE_BIND_LOGICOPS | SVGA3D_SURFACE_BIND_RAW_VIEWS | \
+ SVGA3D_SURFACE_BUFFER_STRUCTURED | SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
+ SVGA3D_SURFACE_RESOURCE_CLAMP | SVGA3D_SURFACE_STAGING_COPY | \
+ SVGA3D_SURFACE_RESTRICT_UPDATE | SVGA3D_SURFACE_BIND_TENSOR | \
+ SVGA3D_SURFACE_LO_STAGING)
+
+#define SVGA3D_SURFACE_HB_PRESENT_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_1D | SVGA3D_SURFACE_MULTISAMPLE | \
+ SVGA3D_SURFACE_STAGING_COPY)
+
+#define SVGA3D_SURFACE_2D_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_AUTOGENMIPMAPS | \
+ SVGA3D_SURFACE_VOLUME | SVGA3D_SURFACE_1D | \
+ SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
+ SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
+ SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
+ SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
+ SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
+ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | SVGA3D_SURFACE_MULTISAMPLE | \
+ SVGA3D_SURFACE_BIND_UAVIEW | SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
+ SVGA3D_SURFACE_BIND_RAW_VIEWS | SVGA3D_SURFACE_BUFFER_STRUCTURED | \
+ SVGA3D_SURFACE_DRAWINDIRECT_ARGS | SVGA3D_SURFACE_RESOURCE_CLAMP | \
+ SVGA3D_SURFACE_BIND_TENSOR)
+
+#define SVGA3D_SURFACE_BASICOPS_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_AUTOGENMIPMAPS | \
+ SVGA3D_SURFACE_VOLUME | SVGA3D_SURFACE_1D | \
+ SVGA3D_SURFACE_MULTISAMPLE)
+
+#define SVGA3D_SURFACE_SCREENTARGET_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_AUTOGENMIPMAPS | \
+ SVGA3D_SURFACE_VOLUME | SVGA3D_SURFACE_1D | \
+ SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
+ SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
+ SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
+ SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
+ SVGA3D_SURFACE_BIND_STREAM_OUTPUT | SVGA3D_SURFACE_INACTIVE | \
+ SVGA3D_SURFACE_STAGING_UPLOAD | SVGA3D_SURFACE_STAGING_DOWNLOAD | \
+ SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \
+ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | SVGA3D_SURFACE_MULTISAMPLE | \
+ SVGA3D_SURFACE_TRANSFER_TO_BUFFER | SVGA3D_SURFACE_BIND_RAW_VIEWS | \
+ SVGA3D_SURFACE_BUFFER_STRUCTURED | SVGA3D_SURFACE_DRAWINDIRECT_ARGS | \
+ SVGA3D_SURFACE_RESOURCE_CLAMP | SVGA3D_SURFACE_STAGING_COPY | \
+ SVGA3D_SURFACE_BIND_TENSOR | SVGA3D_SURFACE_LO_STAGING)
+
+#define SVGA3D_SURFACE_BUFFER_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_AUTOGENMIPMAPS | \
+ SVGA3D_SURFACE_VOLUME | SVGA3D_SURFACE_1D | SVGA3D_SURFACE_DEAD2 | \
+ SVGA3D_SURFACE_ARRAY | SVGA3D_SURFACE_MULTISAMPLE | \
+ SVGA3D_SURFACE_MOB_PITCH | SVGA3D_SURFACE_RESOURCE_CLAMP)
+
+#define SVGA3D_SURFACE_MULTISAMPLE_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_AUTOGENMIPMAPS | \
+ SVGA3D_SURFACE_VOLUME | SVGA3D_SURFACE_1D | \
+ SVGA3D_SURFACE_SCREENTARGET | SVGA3D_SURFACE_MOB_PITCH | \
+ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | SVGA3D_SURFACE_BIND_UAVIEW | \
+ SVGA3D_SURFACE_TRANSFER_TO_BUFFER | SVGA3D_SURFACE_BIND_LOGICOPS | \
+ SVGA3D_SURFACE_BIND_RAW_VIEWS | SVGA3D_SURFACE_BUFFER_STRUCTURED | \
+ SVGA3D_SURFACE_DRAWINDIRECT_ARGS | SVGA3D_SURFACE_STAGING_COPY)
+
+#define SVGA3D_SURFACE_DX_ONLY_MASK \
+ (SVGA3D_SURFACE_BIND_STREAM_OUTPUT | SVGA3D_SURFACE_STAGING_UPLOAD | \
+ SVGA3D_SURFACE_STAGING_DOWNLOAD | \
+ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
+ SVGA3D_SURFACE_TRANSFER_TO_BUFFER)
+
+#define SVGA3D_SURFACE_ANY_STAGING_MASK \
+ (SVGA3D_SURFACE_STAGING_UPLOAD | SVGA3D_SURFACE_STAGING_DOWNLOAD | \
+ SVGA3D_SURFACE_STAGING_COPY | SVGA3D_SURFACE_LO_STAGING)
+
+#define SVGA3D_SURFACE_ANY_NONHINT_STAGING_MASK \
+ (SVGA3D_SURFACE_ANY_STAGING_MASK & ~(SVGA3D_SURFACE_LO_STAGING))
+
+#define SVGA3D_SURFACE_BIND_MASK \
+ (SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
+ SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
+ SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
+ SVGA3D_SURFACE_BIND_SHADER_RESOURCE | \
+ SVGA3D_SURFACE_BIND_RENDER_TARGET | \
+ SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
+ SVGA3D_SURFACE_BIND_STREAM_OUTPUT | SVGA3D_SURFACE_BIND_UAVIEW | \
+ SVGA3D_SURFACE_BIND_LOGICOPS | SVGA3D_SURFACE_BIND_RAW_VIEWS | \
+ SVGA3D_SURFACE_BIND_TENSOR)
+
+#define SVGA3D_SURFACE_STAGING_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_BIND_MASK | SVGA3D_SURFACE_AUTOGENMIPMAPS | \
+ SVGA3D_SURFACE_SCREENTARGET | SVGA3D_SURFACE_HINT_RENDERTARGET | \
+ SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | SVGA3D_SURFACE_MULTISAMPLE | \
+ SVGA3D_SURFACE_DRAWINDIRECT_ARGS | SVGA3D_SURFACE_RESOURCE_CLAMP | \
+ SVGA3D_SURFACE_BIND_TENSOR)
+
+#define SVGA3D_SURFACE_STAGING_COPY_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_STAGING_DISALLOWED_MASK | \
+ SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
+ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER)
+
+#define SVGA3D_SURFACE_LOGICOPS_DISALLOWED_MASK \
+ (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_DEAD2 | \
+ SVGA3D_SURFACE_AUTOGENMIPMAPS | SVGA3D_SURFACE_VOLUME | \
+ SVGA3D_SURFACE_1D | SVGA3D_SURFACE_BIND_VERTEX_BUFFER | \
+ SVGA3D_SURFACE_BIND_INDEX_BUFFER | \
+ SVGA3D_SURFACE_BIND_CONSTANT_BUFFER | \
+ SVGA3D_SURFACE_BIND_DEPTH_STENCIL | \
+ SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
+ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | SVGA3D_SURFACE_MULTISAMPLE | \
+ SVGA3D_SURFACE_BIND_UAVIEW | SVGA3D_SURFACE_TRANSFER_TO_BUFFER | \
+ SVGA3D_SURFACE_BIND_RAW_VIEWS | SVGA3D_SURFACE_BUFFER_STRUCTURED | \
+ SVGA3D_SURFACE_DRAWINDIRECT_ARGS | SVGA3D_SURFACE_RESOURCE_CLAMP | \
+ SVGA3D_SURFACE_STAGING_COPY)
+
+#define SVGA3D_SURFACE_SM5_MASK \
+ (SVGA3D_SURFACE_DRAWINDIRECT_ARGS | SVGA3D_SURFACE_BUFFER_STRUCTURED | \
+ SVGA3D_SURFACE_BIND_RAW_VIEWS | SVGA3D_SURFACE_BIND_UAVIEW | \
+ SVGA3D_SURFACE_RESOURCE_CLAMP)
#define SVGA3D_BUFFER_STRUCTURED_STRIDE_MAX 2048
-
-/*
- * These are really the D3DFORMAT_OP defines from the wdk. We need
- * them so that we can query the host for what the supported surface
- * operations are (when we're using the D3D backend, in particular),
- * and so we can send those operations to the guest.
- */
typedef enum {
- SVGA3DFORMAT_OP_TEXTURE = 0x00000001,
- SVGA3DFORMAT_OP_VOLUMETEXTURE = 0x00000002,
- SVGA3DFORMAT_OP_CUBETEXTURE = 0x00000004,
- SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET = 0x00000008,
- SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET = 0x00000010,
- SVGA3DFORMAT_OP_ZSTENCIL = 0x00000040,
- SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH = 0x00000080,
+ SVGA3DFORMAT_OP_TEXTURE = 0x00000001,
+ SVGA3DFORMAT_OP_VOLUMETEXTURE = 0x00000002,
+ SVGA3DFORMAT_OP_CUBETEXTURE = 0x00000004,
+ SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET = 0x00000008,
+ SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET = 0x00000010,
+ SVGA3DFORMAT_OP_ZSTENCIL = 0x00000040,
+ SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH = 0x00000080,
-/*
- * This format can be used as a render target if the current display mode
- * is the same depth if the alpha channel is ignored. e.g. if the device
- * can render to A8R8G8B8 when the display mode is X8R8G8B8, then the
- * format op list entry for A8R8G8B8 should have this cap.
- */
- SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET = 0x00000100,
+ SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET = 0x00000100,
-/*
- * This format contains DirectDraw support (including Flip). This flag
- * should not to be set on alpha formats.
- */
- SVGA3DFORMAT_OP_DISPLAYMODE = 0x00000400,
+ SVGA3DFORMAT_OP_DISPLAYMODE = 0x00000400,
-/*
- * The rasterizer can support some level of Direct3D support in this format
- * and implies that the driver can create a Context in this mode (for some
- * render target format). When this flag is set, the SVGA3DFORMAT_OP_DISPLAYMODE
- * flag must also be set.
- */
- SVGA3DFORMAT_OP_3DACCELERATION = 0x00000800,
+ SVGA3DFORMAT_OP_3DACCELERATION = 0x00000800,
-/*
- * This is set for a private format when the driver has put the bpp in
- * the structure.
- */
- SVGA3DFORMAT_OP_PIXELSIZE = 0x00001000,
+ SVGA3DFORMAT_OP_PIXELSIZE = 0x00001000,
-/*
- * Indicates that this format can be converted to any RGB format for which
- * SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB is specified.
- */
- SVGA3DFORMAT_OP_CONVERT_TO_ARGB = 0x00002000,
+ SVGA3DFORMAT_OP_CONVERT_TO_ARGB = 0x00002000,
-/*
- * Indicates that this format can be used to create offscreen plain surfaces.
- */
- SVGA3DFORMAT_OP_OFFSCREENPLAIN = 0x00004000,
+ SVGA3DFORMAT_OP_OFFSCREENPLAIN = 0x00004000,
-/*
- * Indicated that this format can be read as an SRGB texture (meaning that the
- * sampler will linearize the looked up data).
- */
- SVGA3DFORMAT_OP_SRGBREAD = 0x00008000,
+ SVGA3DFORMAT_OP_SRGBREAD = 0x00008000,
-/*
- * Indicates that this format can be used in the bumpmap instructions.
- */
- SVGA3DFORMAT_OP_BUMPMAP = 0x00010000,
+ SVGA3DFORMAT_OP_BUMPMAP = 0x00010000,
-/*
- * Indicates that this format can be sampled by the displacement map sampler.
- */
- SVGA3DFORMAT_OP_DMAP = 0x00020000,
+ SVGA3DFORMAT_OP_DMAP = 0x00020000,
-/*
- * Indicates that this format cannot be used with texture filtering.
- */
- SVGA3DFORMAT_OP_NOFILTER = 0x00040000,
+ SVGA3DFORMAT_OP_NOFILTER = 0x00040000,
-/*
- * Indicates that format conversions are supported to this RGB format if
- * SVGA3DFORMAT_OP_CONVERT_TO_ARGB is specified in the source format.
- */
- SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB = 0x00080000,
+ SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB = 0x00080000,
-/*
- * Indicated that this format can be written as an SRGB target
- * (meaning that the pixel pipe will DE-linearize data on output to format)
- */
- SVGA3DFORMAT_OP_SRGBWRITE = 0x00100000,
+ SVGA3DFORMAT_OP_SRGBWRITE = 0x00100000,
-/*
- * Indicates that this format cannot be used with alpha blending.
- */
- SVGA3DFORMAT_OP_NOALPHABLEND = 0x00200000,
+ SVGA3DFORMAT_OP_NOALPHABLEND = 0x00200000,
-/*
- * Indicates that the device can auto-generated sublevels for resources
- * of this format.
- */
- SVGA3DFORMAT_OP_AUTOGENMIPMAP = 0x00400000,
+ SVGA3DFORMAT_OP_AUTOGENMIPMAP = 0x00400000,
-/*
- * Indicates that this format can be used by vertex texture sampler.
- */
- SVGA3DFORMAT_OP_VERTEXTEXTURE = 0x00800000,
+ SVGA3DFORMAT_OP_VERTEXTEXTURE = 0x00800000,
-/*
- * Indicates that this format supports neither texture coordinate
- * wrap modes, nor mipmapping.
- */
- SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP = 0x01000000
+ SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP = 0x01000000
} SVGA3dFormatOp;
-#define SVGA3D_FORMAT_POSITIVE \
- (SVGA3DFORMAT_OP_TEXTURE | \
- SVGA3DFORMAT_OP_VOLUMETEXTURE | \
- SVGA3DFORMAT_OP_CUBETEXTURE | \
- SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET | \
- SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET | \
- SVGA3DFORMAT_OP_ZSTENCIL | \
- SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH | \
- SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET | \
- SVGA3DFORMAT_OP_DISPLAYMODE | \
- SVGA3DFORMAT_OP_3DACCELERATION | \
- SVGA3DFORMAT_OP_PIXELSIZE | \
- SVGA3DFORMAT_OP_CONVERT_TO_ARGB | \
- SVGA3DFORMAT_OP_OFFSCREENPLAIN | \
- SVGA3DFORMAT_OP_SRGBREAD | \
- SVGA3DFORMAT_OP_BUMPMAP | \
- SVGA3DFORMAT_OP_DMAP | \
- SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB | \
- SVGA3DFORMAT_OP_SRGBWRITE | \
- SVGA3DFORMAT_OP_AUTOGENMIPMAP | \
- SVGA3DFORMAT_OP_VERTEXTEXTURE)
-
-#define SVGA3D_FORMAT_NEGATIVE \
- (SVGA3DFORMAT_OP_NOFILTER | \
- SVGA3DFORMAT_OP_NOALPHABLEND | \
- SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP)
+#define SVGA3D_FORMAT_POSITIVE \
+ (SVGA3DFORMAT_OP_TEXTURE | SVGA3DFORMAT_OP_VOLUMETEXTURE | \
+ SVGA3DFORMAT_OP_CUBETEXTURE | \
+ SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET | \
+ SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET | SVGA3DFORMAT_OP_ZSTENCIL | \
+ SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH | \
+ SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET | \
+ SVGA3DFORMAT_OP_DISPLAYMODE | SVGA3DFORMAT_OP_3DACCELERATION | \
+ SVGA3DFORMAT_OP_PIXELSIZE | SVGA3DFORMAT_OP_CONVERT_TO_ARGB | \
+ SVGA3DFORMAT_OP_OFFSCREENPLAIN | SVGA3DFORMAT_OP_SRGBREAD | \
+ SVGA3DFORMAT_OP_BUMPMAP | SVGA3DFORMAT_OP_DMAP | \
+ SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB | SVGA3DFORMAT_OP_SRGBWRITE | \
+ SVGA3DFORMAT_OP_AUTOGENMIPMAP | SVGA3DFORMAT_OP_VERTEXTEXTURE)
+
+#define SVGA3D_FORMAT_NEGATIVE \
+ (SVGA3DFORMAT_OP_NOFILTER | SVGA3DFORMAT_OP_NOALPHABLEND | \
+ SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP)
-/*
- * This structure is a conversion of SVGA3DFORMAT_OP_*
- * Entries must be located at the same position.
- */
typedef union {
- uint32 value;
- struct {
- uint32 texture : 1;
- uint32 volumeTexture : 1;
- uint32 cubeTexture : 1;
- uint32 offscreenRenderTarget : 1;
- uint32 sameFormatRenderTarget : 1;
- uint32 unknown1 : 1;
- uint32 zStencil : 1;
- uint32 zStencilArbitraryDepth : 1;
- uint32 sameFormatUpToAlpha : 1;
- uint32 unknown2 : 1;
- uint32 displayMode : 1;
- uint32 acceleration3d : 1;
- uint32 pixelSize : 1;
- uint32 convertToARGB : 1;
- uint32 offscreenPlain : 1;
- uint32 sRGBRead : 1;
- uint32 bumpMap : 1;
- uint32 dmap : 1;
- uint32 noFilter : 1;
- uint32 memberOfGroupARGB : 1;
- uint32 sRGBWrite : 1;
- uint32 noAlphaBlend : 1;
- uint32 autoGenMipMap : 1;
- uint32 vertexTexture : 1;
- uint32 noTexCoordWrapNorMip : 1;
- };
+ uint32 value;
+ struct {
+ uint32 texture : 1;
+ uint32 volumeTexture : 1;
+ uint32 cubeTexture : 1;
+ uint32 offscreenRenderTarget : 1;
+ uint32 sameFormatRenderTarget : 1;
+ uint32 unknown1 : 1;
+ uint32 zStencil : 1;
+ uint32 zStencilArbitraryDepth : 1;
+ uint32 sameFormatUpToAlpha : 1;
+ uint32 unknown2 : 1;
+ uint32 displayMode : 1;
+ uint32 acceleration3d : 1;
+ uint32 pixelSize : 1;
+ uint32 convertToARGB : 1;
+ uint32 offscreenPlain : 1;
+ uint32 sRGBRead : 1;
+ uint32 bumpMap : 1;
+ uint32 dmap : 1;
+ uint32 noFilter : 1;
+ uint32 memberOfGroupARGB : 1;
+ uint32 sRGBWrite : 1;
+ uint32 noAlphaBlend : 1;
+ uint32 autoGenMipMap : 1;
+ uint32 vertexTexture : 1;
+ uint32 noTexCoordWrapNorMip : 1;
+ };
} SVGA3dSurfaceFormatCaps;
-/*
- * SVGA_3D_CMD_SETRENDERSTATE Types. All value types
- * must fit in a uint32.
- */
-
typedef enum {
- SVGA3D_RS_INVALID = 0,
- SVGA3D_RS_MIN = 1,
- SVGA3D_RS_ZENABLE = 1, /* SVGA3dBool */
- SVGA3D_RS_ZWRITEENABLE = 2, /* SVGA3dBool */
- SVGA3D_RS_ALPHATESTENABLE = 3, /* SVGA3dBool */
- SVGA3D_RS_DITHERENABLE = 4, /* SVGA3dBool */
- SVGA3D_RS_BLENDENABLE = 5, /* SVGA3dBool */
- SVGA3D_RS_FOGENABLE = 6, /* SVGA3dBool */
- SVGA3D_RS_SPECULARENABLE = 7, /* SVGA3dBool */
- SVGA3D_RS_STENCILENABLE = 8, /* SVGA3dBool */
- SVGA3D_RS_LIGHTINGENABLE = 9, /* SVGA3dBool */
- SVGA3D_RS_NORMALIZENORMALS = 10, /* SVGA3dBool */
- SVGA3D_RS_POINTSPRITEENABLE = 11, /* SVGA3dBool */
- SVGA3D_RS_POINTSCALEENABLE = 12, /* SVGA3dBool */
- SVGA3D_RS_STENCILREF = 13, /* uint32 */
- SVGA3D_RS_STENCILMASK = 14, /* uint32 */
- SVGA3D_RS_STENCILWRITEMASK = 15, /* uint32 */
- SVGA3D_RS_FOGSTART = 16, /* float */
- SVGA3D_RS_FOGEND = 17, /* float */
- SVGA3D_RS_FOGDENSITY = 18, /* float */
- SVGA3D_RS_POINTSIZE = 19, /* float */
- SVGA3D_RS_POINTSIZEMIN = 20, /* float */
- SVGA3D_RS_POINTSIZEMAX = 21, /* float */
- SVGA3D_RS_POINTSCALE_A = 22, /* float */
- SVGA3D_RS_POINTSCALE_B = 23, /* float */
- SVGA3D_RS_POINTSCALE_C = 24, /* float */
- SVGA3D_RS_FOGCOLOR = 25, /* SVGA3dColor */
- SVGA3D_RS_AMBIENT = 26, /* SVGA3dColor */
- SVGA3D_RS_CLIPPLANEENABLE = 27, /* SVGA3dClipPlanes */
- SVGA3D_RS_FOGMODE = 28, /* SVGA3dFogMode */
- SVGA3D_RS_FILLMODE = 29, /* SVGA3dFillMode */
- SVGA3D_RS_SHADEMODE = 30, /* SVGA3dShadeMode */
- SVGA3D_RS_LINEPATTERN = 31, /* SVGA3dLinePattern */
- SVGA3D_RS_SRCBLEND = 32, /* SVGA3dBlendOp */
- SVGA3D_RS_DSTBLEND = 33, /* SVGA3dBlendOp */
- SVGA3D_RS_BLENDEQUATION = 34, /* SVGA3dBlendEquation */
- SVGA3D_RS_CULLMODE = 35, /* SVGA3dFace */
- SVGA3D_RS_ZFUNC = 36, /* SVGA3dCmpFunc */
- SVGA3D_RS_ALPHAFUNC = 37, /* SVGA3dCmpFunc */
- SVGA3D_RS_STENCILFUNC = 38, /* SVGA3dCmpFunc */
- SVGA3D_RS_STENCILFAIL = 39, /* SVGA3dStencilOp */
- SVGA3D_RS_STENCILZFAIL = 40, /* SVGA3dStencilOp */
- SVGA3D_RS_STENCILPASS = 41, /* SVGA3dStencilOp */
- SVGA3D_RS_ALPHAREF = 42, /* float (0.0 .. 1.0) */
- SVGA3D_RS_FRONTWINDING = 43, /* SVGA3dFrontWinding */
- SVGA3D_RS_COORDINATETYPE = 44, /* SVGA3dCoordinateType */
- SVGA3D_RS_ZBIAS = 45, /* float */
- SVGA3D_RS_RANGEFOGENABLE = 46, /* SVGA3dBool */
- SVGA3D_RS_COLORWRITEENABLE = 47, /* SVGA3dColorMask */
- SVGA3D_RS_VERTEXMATERIALENABLE = 48, /* SVGA3dBool */
- SVGA3D_RS_DIFFUSEMATERIALSOURCE = 49, /* SVGA3dVertexMaterial */
- SVGA3D_RS_SPECULARMATERIALSOURCE = 50, /* SVGA3dVertexMaterial */
- SVGA3D_RS_AMBIENTMATERIALSOURCE = 51, /* SVGA3dVertexMaterial */
- SVGA3D_RS_EMISSIVEMATERIALSOURCE = 52, /* SVGA3dVertexMaterial */
- SVGA3D_RS_TEXTUREFACTOR = 53, /* SVGA3dColor */
- SVGA3D_RS_LOCALVIEWER = 54, /* SVGA3dBool */
- SVGA3D_RS_SCISSORTESTENABLE = 55, /* SVGA3dBool */
- SVGA3D_RS_BLENDCOLOR = 56, /* SVGA3dColor */
- SVGA3D_RS_STENCILENABLE2SIDED = 57, /* SVGA3dBool */
- SVGA3D_RS_CCWSTENCILFUNC = 58, /* SVGA3dCmpFunc */
- SVGA3D_RS_CCWSTENCILFAIL = 59, /* SVGA3dStencilOp */
- SVGA3D_RS_CCWSTENCILZFAIL = 60, /* SVGA3dStencilOp */
- SVGA3D_RS_CCWSTENCILPASS = 61, /* SVGA3dStencilOp */
- SVGA3D_RS_VERTEXBLEND = 62, /* SVGA3dVertexBlendFlags */
- SVGA3D_RS_SLOPESCALEDEPTHBIAS = 63, /* float */
- SVGA3D_RS_DEPTHBIAS = 64, /* float */
-
-
- /*
- * Output Gamma Level
- *
- * Output gamma effects the gamma curve of colors that are output from the
- * rendering pipeline. A value of 1.0 specifies a linear color space. If the
- * value is <= 0.0, gamma correction is ignored and linear color space is
- * used.
- */
-
- SVGA3D_RS_OUTPUTGAMMA = 65, /* float */
- SVGA3D_RS_ZVISIBLE = 66, /* SVGA3dBool */
- SVGA3D_RS_LASTPIXEL = 67, /* SVGA3dBool */
- SVGA3D_RS_CLIPPING = 68, /* SVGA3dBool */
- SVGA3D_RS_WRAP0 = 69, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP1 = 70, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP2 = 71, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP3 = 72, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP4 = 73, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP5 = 74, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP6 = 75, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP7 = 76, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP8 = 77, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP9 = 78, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP10 = 79, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP11 = 80, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP12 = 81, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP13 = 82, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP14 = 83, /* SVGA3dWrapFlags */
- SVGA3D_RS_WRAP15 = 84, /* SVGA3dWrapFlags */
- SVGA3D_RS_MULTISAMPLEANTIALIAS = 85, /* SVGA3dBool */
- SVGA3D_RS_MULTISAMPLEMASK = 86, /* uint32 */
- SVGA3D_RS_INDEXEDVERTEXBLENDENABLE = 87, /* SVGA3dBool */
- SVGA3D_RS_TWEENFACTOR = 88, /* float */
- SVGA3D_RS_ANTIALIASEDLINEENABLE = 89, /* SVGA3dBool */
- SVGA3D_RS_COLORWRITEENABLE1 = 90, /* SVGA3dColorMask */
- SVGA3D_RS_COLORWRITEENABLE2 = 91, /* SVGA3dColorMask */
- SVGA3D_RS_COLORWRITEENABLE3 = 92, /* SVGA3dColorMask */
- SVGA3D_RS_SEPARATEALPHABLENDENABLE = 93, /* SVGA3dBool */
- SVGA3D_RS_SRCBLENDALPHA = 94, /* SVGA3dBlendOp */
- SVGA3D_RS_DSTBLENDALPHA = 95, /* SVGA3dBlendOp */
- SVGA3D_RS_BLENDEQUATIONALPHA = 96, /* SVGA3dBlendEquation */
- SVGA3D_RS_TRANSPARENCYANTIALIAS = 97, /* SVGA3dTransparencyAntialiasType */
- SVGA3D_RS_LINEWIDTH = 98, /* float */
- SVGA3D_RS_MAX
+ SVGA3D_RS_INVALID = 0,
+ SVGA3D_RS_MIN = 1,
+ SVGA3D_RS_ZENABLE = 1,
+ SVGA3D_RS_ZWRITEENABLE = 2,
+ SVGA3D_RS_ALPHATESTENABLE = 3,
+ SVGA3D_RS_DITHERENABLE = 4,
+ SVGA3D_RS_BLENDENABLE = 5,
+ SVGA3D_RS_FOGENABLE = 6,
+ SVGA3D_RS_SPECULARENABLE = 7,
+ SVGA3D_RS_STENCILENABLE = 8,
+ SVGA3D_RS_LIGHTINGENABLE = 9,
+ SVGA3D_RS_NORMALIZENORMALS = 10,
+ SVGA3D_RS_POINTSPRITEENABLE = 11,
+ SVGA3D_RS_POINTSCALEENABLE = 12,
+ SVGA3D_RS_STENCILREF = 13,
+ SVGA3D_RS_STENCILMASK = 14,
+ SVGA3D_RS_STENCILWRITEMASK = 15,
+ SVGA3D_RS_FOGSTART = 16,
+ SVGA3D_RS_FOGEND = 17,
+ SVGA3D_RS_FOGDENSITY = 18,
+ SVGA3D_RS_POINTSIZE = 19,
+ SVGA3D_RS_POINTSIZEMIN = 20,
+ SVGA3D_RS_POINTSIZEMAX = 21,
+ SVGA3D_RS_POINTSCALE_A = 22,
+ SVGA3D_RS_POINTSCALE_B = 23,
+ SVGA3D_RS_POINTSCALE_C = 24,
+ SVGA3D_RS_FOGCOLOR = 25,
+ SVGA3D_RS_AMBIENT = 26,
+ SVGA3D_RS_CLIPPLANEENABLE = 27,
+ SVGA3D_RS_FOGMODE = 28,
+ SVGA3D_RS_FILLMODE = 29,
+ SVGA3D_RS_SHADEMODE = 30,
+ SVGA3D_RS_LINEPATTERN = 31,
+ SVGA3D_RS_SRCBLEND = 32,
+ SVGA3D_RS_DSTBLEND = 33,
+ SVGA3D_RS_BLENDEQUATION = 34,
+ SVGA3D_RS_CULLMODE = 35,
+ SVGA3D_RS_ZFUNC = 36,
+ SVGA3D_RS_ALPHAFUNC = 37,
+ SVGA3D_RS_STENCILFUNC = 38,
+ SVGA3D_RS_STENCILFAIL = 39,
+ SVGA3D_RS_STENCILZFAIL = 40,
+ SVGA3D_RS_STENCILPASS = 41,
+ SVGA3D_RS_ALPHAREF = 42,
+ SVGA3D_RS_FRONTWINDING = 43,
+ SVGA3D_RS_COORDINATETYPE = 44,
+ SVGA3D_RS_ZBIAS = 45,
+ SVGA3D_RS_RANGEFOGENABLE = 46,
+ SVGA3D_RS_COLORWRITEENABLE = 47,
+ SVGA3D_RS_VERTEXMATERIALENABLE = 48,
+ SVGA3D_RS_DIFFUSEMATERIALSOURCE = 49,
+ SVGA3D_RS_SPECULARMATERIALSOURCE = 50,
+ SVGA3D_RS_AMBIENTMATERIALSOURCE = 51,
+ SVGA3D_RS_EMISSIVEMATERIALSOURCE = 52,
+ SVGA3D_RS_TEXTUREFACTOR = 53,
+ SVGA3D_RS_LOCALVIEWER = 54,
+ SVGA3D_RS_SCISSORTESTENABLE = 55,
+ SVGA3D_RS_BLENDCOLOR = 56,
+ SVGA3D_RS_STENCILENABLE2SIDED = 57,
+ SVGA3D_RS_CCWSTENCILFUNC = 58,
+ SVGA3D_RS_CCWSTENCILFAIL = 59,
+ SVGA3D_RS_CCWSTENCILZFAIL = 60,
+ SVGA3D_RS_CCWSTENCILPASS = 61,
+ SVGA3D_RS_VERTEXBLEND = 62,
+ SVGA3D_RS_SLOPESCALEDEPTHBIAS = 63,
+ SVGA3D_RS_DEPTHBIAS = 64,
+
+ SVGA3D_RS_OUTPUTGAMMA = 65,
+ SVGA3D_RS_ZVISIBLE = 66,
+ SVGA3D_RS_LASTPIXEL = 67,
+ SVGA3D_RS_CLIPPING = 68,
+ SVGA3D_RS_WRAP0 = 69,
+ SVGA3D_RS_WRAP1 = 70,
+ SVGA3D_RS_WRAP2 = 71,
+ SVGA3D_RS_WRAP3 = 72,
+ SVGA3D_RS_WRAP4 = 73,
+ SVGA3D_RS_WRAP5 = 74,
+ SVGA3D_RS_WRAP6 = 75,
+ SVGA3D_RS_WRAP7 = 76,
+ SVGA3D_RS_WRAP8 = 77,
+ SVGA3D_RS_WRAP9 = 78,
+ SVGA3D_RS_WRAP10 = 79,
+ SVGA3D_RS_WRAP11 = 80,
+ SVGA3D_RS_WRAP12 = 81,
+ SVGA3D_RS_WRAP13 = 82,
+ SVGA3D_RS_WRAP14 = 83,
+ SVGA3D_RS_WRAP15 = 84,
+ SVGA3D_RS_MULTISAMPLEANTIALIAS = 85,
+ SVGA3D_RS_MULTISAMPLEMASK = 86,
+ SVGA3D_RS_INDEXEDVERTEXBLENDENABLE = 87,
+ SVGA3D_RS_TWEENFACTOR = 88,
+ SVGA3D_RS_ANTIALIASEDLINEENABLE = 89,
+ SVGA3D_RS_COLORWRITEENABLE1 = 90,
+ SVGA3D_RS_COLORWRITEENABLE2 = 91,
+ SVGA3D_RS_COLORWRITEENABLE3 = 92,
+ SVGA3D_RS_SEPARATEALPHABLENDENABLE = 93,
+ SVGA3D_RS_SRCBLENDALPHA = 94,
+ SVGA3D_RS_DSTBLENDALPHA = 95,
+ SVGA3D_RS_BLENDEQUATIONALPHA = 96,
+ SVGA3D_RS_TRANSPARENCYANTIALIAS = 97,
+ SVGA3D_RS_LINEWIDTH = 98,
+ SVGA3D_RS_MAX
} SVGA3dRenderStateName;
typedef enum {
- SVGA3D_TRANSPARENCYANTIALIAS_NORMAL = 0,
- SVGA3D_TRANSPARENCYANTIALIAS_ALPHATOCOVERAGE = 1,
- SVGA3D_TRANSPARENCYANTIALIAS_SUPERSAMPLE = 2,
- SVGA3D_TRANSPARENCYANTIALIAS_MAX
+ SVGA3D_TRANSPARENCYANTIALIAS_NORMAL = 0,
+ SVGA3D_TRANSPARENCYANTIALIAS_ALPHATOCOVERAGE = 1,
+ SVGA3D_TRANSPARENCYANTIALIAS_SUPERSAMPLE = 2,
+ SVGA3D_TRANSPARENCYANTIALIAS_MAX
} SVGA3dTransparencyAntialiasType;
typedef enum {
- SVGA3D_VERTEXMATERIAL_NONE = 0, /* Use the value in the current material */
- SVGA3D_VERTEXMATERIAL_DIFFUSE = 1, /* Use the value in the diffuse component */
- SVGA3D_VERTEXMATERIAL_SPECULAR = 2, /* Use the value in the specular component */
- SVGA3D_VERTEXMATERIAL_MAX = 3,
+ SVGA3D_VERTEXMATERIAL_NONE = 0,
+ SVGA3D_VERTEXMATERIAL_DIFFUSE = 1,
+ SVGA3D_VERTEXMATERIAL_SPECULAR = 2,
+ SVGA3D_VERTEXMATERIAL_MAX = 3,
} SVGA3dVertexMaterial;
typedef enum {
- SVGA3D_FILLMODE_INVALID = 0,
- SVGA3D_FILLMODE_MIN = 1,
- SVGA3D_FILLMODE_POINT = 1,
- SVGA3D_FILLMODE_LINE = 2,
- SVGA3D_FILLMODE_FILL = 3,
- SVGA3D_FILLMODE_MAX
+ SVGA3D_FILLMODE_INVALID = 0,
+ SVGA3D_FILLMODE_MIN = 1,
+ SVGA3D_FILLMODE_POINT = 1,
+ SVGA3D_FILLMODE_LINE = 2,
+ SVGA3D_FILLMODE_FILL = 3,
+ SVGA3D_FILLMODE_MAX
} SVGA3dFillModeType;
-
-typedef
-#include "vmware_pack_begin.h"
-union {
- struct {
- uint16 mode; /* SVGA3dFillModeType */
- uint16 face; /* SVGA3dFace */
- };
- uint32 uintValue;
-}
-#include "vmware_pack_end.h"
-SVGA3dFillMode;
+#pragma pack(push, 1)
+typedef union {
+ struct {
+ uint16 mode;
+ uint16 face;
+ };
+ uint32 uintValue;
+} SVGA3dFillMode;
+#pragma pack(pop)
typedef enum {
- SVGA3D_SHADEMODE_INVALID = 0,
- SVGA3D_SHADEMODE_FLAT = 1,
- SVGA3D_SHADEMODE_SMOOTH = 2,
- SVGA3D_SHADEMODE_PHONG = 3, /* Not supported */
- SVGA3D_SHADEMODE_MAX
+ SVGA3D_SHADEMODE_INVALID = 0,
+ SVGA3D_SHADEMODE_FLAT = 1,
+ SVGA3D_SHADEMODE_SMOOTH = 2,
+ SVGA3D_SHADEMODE_PHONG = 3,
+ SVGA3D_SHADEMODE_MAX
} SVGA3dShadeMode;
-typedef
-#include "vmware_pack_begin.h"
-union {
- struct {
- uint16 repeat;
- uint16 pattern;
- };
- uint32 uintValue;
-}
-#include "vmware_pack_end.h"
-SVGA3dLinePattern;
+#pragma pack(push, 1)
+typedef union {
+ struct {
+ uint16 repeat;
+ uint16 pattern;
+ };
+ uint32 uintValue;
+} SVGA3dLinePattern;
+#pragma pack(pop)
typedef enum {
- SVGA3D_BLENDOP_INVALID = 0,
- SVGA3D_BLENDOP_MIN = 1,
- SVGA3D_BLENDOP_ZERO = 1,
- SVGA3D_BLENDOP_ONE = 2,
- SVGA3D_BLENDOP_SRCCOLOR = 3,
- SVGA3D_BLENDOP_INVSRCCOLOR = 4,
- SVGA3D_BLENDOP_SRCALPHA = 5,
- SVGA3D_BLENDOP_INVSRCALPHA = 6,
- SVGA3D_BLENDOP_DESTALPHA = 7,
- SVGA3D_BLENDOP_INVDESTALPHA = 8,
- SVGA3D_BLENDOP_DESTCOLOR = 9,
- SVGA3D_BLENDOP_INVDESTCOLOR = 10,
- SVGA3D_BLENDOP_SRCALPHASAT = 11,
- SVGA3D_BLENDOP_BLENDFACTOR = 12,
- SVGA3D_BLENDOP_INVBLENDFACTOR = 13,
- SVGA3D_BLENDOP_SRC1COLOR = 14,
- SVGA3D_BLENDOP_INVSRC1COLOR = 15,
- SVGA3D_BLENDOP_SRC1ALPHA = 16,
- SVGA3D_BLENDOP_INVSRC1ALPHA = 17,
- SVGA3D_BLENDOP_BLENDFACTORALPHA = 18,
- SVGA3D_BLENDOP_INVBLENDFACTORALPHA = 19,
- SVGA3D_BLENDOP_MAX
+ SVGA3D_BLENDOP_INVALID = 0,
+ SVGA3D_BLENDOP_MIN = 1,
+ SVGA3D_BLENDOP_ZERO = 1,
+ SVGA3D_BLENDOP_ONE = 2,
+ SVGA3D_BLENDOP_SRCCOLOR = 3,
+ SVGA3D_BLENDOP_INVSRCCOLOR = 4,
+ SVGA3D_BLENDOP_SRCALPHA = 5,
+ SVGA3D_BLENDOP_INVSRCALPHA = 6,
+ SVGA3D_BLENDOP_DESTALPHA = 7,
+ SVGA3D_BLENDOP_INVDESTALPHA = 8,
+ SVGA3D_BLENDOP_DESTCOLOR = 9,
+ SVGA3D_BLENDOP_INVDESTCOLOR = 10,
+ SVGA3D_BLENDOP_SRCALPHASAT = 11,
+ SVGA3D_BLENDOP_BLENDFACTOR = 12,
+ SVGA3D_BLENDOP_INVBLENDFACTOR = 13,
+ SVGA3D_BLENDOP_SRC1COLOR = 14,
+ SVGA3D_BLENDOP_INVSRC1COLOR = 15,
+ SVGA3D_BLENDOP_SRC1ALPHA = 16,
+ SVGA3D_BLENDOP_INVSRC1ALPHA = 17,
+ SVGA3D_BLENDOP_BLENDFACTORALPHA = 18,
+ SVGA3D_BLENDOP_INVBLENDFACTORALPHA = 19,
+ SVGA3D_BLENDOP_MAX
} SVGA3dBlendOp;
typedef enum {
- SVGA3D_BLENDEQ_INVALID = 0,
- SVGA3D_BLENDEQ_MIN = 1,
- SVGA3D_BLENDEQ_ADD = 1,
- SVGA3D_BLENDEQ_SUBTRACT = 2,
- SVGA3D_BLENDEQ_REVSUBTRACT = 3,
- SVGA3D_BLENDEQ_MINIMUM = 4,
- SVGA3D_BLENDEQ_MAXIMUM = 5,
- SVGA3D_BLENDEQ_MAX
+ SVGA3D_BLENDEQ_INVALID = 0,
+ SVGA3D_BLENDEQ_MIN = 1,
+ SVGA3D_BLENDEQ_ADD = 1,
+ SVGA3D_BLENDEQ_SUBTRACT = 2,
+ SVGA3D_BLENDEQ_REVSUBTRACT = 3,
+ SVGA3D_BLENDEQ_MINIMUM = 4,
+ SVGA3D_BLENDEQ_MAXIMUM = 5,
+ SVGA3D_BLENDEQ_MAX
} SVGA3dBlendEquation;
typedef enum {
- SVGA3D_DX11_LOGICOP_MIN = 0,
- SVGA3D_DX11_LOGICOP_CLEAR = 0,
- SVGA3D_DX11_LOGICOP_SET = 1,
- SVGA3D_DX11_LOGICOP_COPY = 2,
- SVGA3D_DX11_LOGICOP_COPY_INVERTED = 3,
- SVGA3D_DX11_LOGICOP_NOOP = 4,
- SVGA3D_DX11_LOGICOP_INVERT = 5,
- SVGA3D_DX11_LOGICOP_AND = 6,
- SVGA3D_DX11_LOGICOP_NAND = 7,
- SVGA3D_DX11_LOGICOP_OR = 8,
- SVGA3D_DX11_LOGICOP_NOR = 9,
- SVGA3D_DX11_LOGICOP_XOR = 10,
- SVGA3D_DX11_LOGICOP_EQUIV = 11,
- SVGA3D_DX11_LOGICOP_AND_REVERSE = 12,
- SVGA3D_DX11_LOGICOP_AND_INVERTED = 13,
- SVGA3D_DX11_LOGICOP_OR_REVERSE = 14,
- SVGA3D_DX11_LOGICOP_OR_INVERTED = 15,
- SVGA3D_DX11_LOGICOP_MAX
+ SVGA3D_DX11_LOGICOP_MIN = 0,
+ SVGA3D_DX11_LOGICOP_CLEAR = 0,
+ SVGA3D_DX11_LOGICOP_SET = 1,
+ SVGA3D_DX11_LOGICOP_COPY = 2,
+ SVGA3D_DX11_LOGICOP_COPY_INVERTED = 3,
+ SVGA3D_DX11_LOGICOP_NOOP = 4,
+ SVGA3D_DX11_LOGICOP_INVERT = 5,
+ SVGA3D_DX11_LOGICOP_AND = 6,
+ SVGA3D_DX11_LOGICOP_NAND = 7,
+ SVGA3D_DX11_LOGICOP_OR = 8,
+ SVGA3D_DX11_LOGICOP_NOR = 9,
+ SVGA3D_DX11_LOGICOP_XOR = 10,
+ SVGA3D_DX11_LOGICOP_EQUIV = 11,
+ SVGA3D_DX11_LOGICOP_AND_REVERSE = 12,
+ SVGA3D_DX11_LOGICOP_AND_INVERTED = 13,
+ SVGA3D_DX11_LOGICOP_OR_REVERSE = 14,
+ SVGA3D_DX11_LOGICOP_OR_INVERTED = 15,
+ SVGA3D_DX11_LOGICOP_MAX
} SVGA3dDX11LogicOp;
typedef enum {
- SVGA3D_FRONTWINDING_INVALID = 0,
- SVGA3D_FRONTWINDING_CW = 1,
- SVGA3D_FRONTWINDING_CCW = 2,
- SVGA3D_FRONTWINDING_MAX
+ SVGA3D_FRONTWINDING_INVALID = 0,
+ SVGA3D_FRONTWINDING_CW = 1,
+ SVGA3D_FRONTWINDING_MIN = 1,
+ SVGA3D_FRONTWINDING_CCW = 2,
+ SVGA3D_FRONTWINDING_MAX
} SVGA3dFrontWinding;
typedef enum {
- SVGA3D_FACE_INVALID = 0,
- SVGA3D_FACE_NONE = 1,
- SVGA3D_FACE_MIN = 1,
- SVGA3D_FACE_FRONT = 2,
- SVGA3D_FACE_BACK = 3,
- SVGA3D_FACE_FRONT_BACK = 4,
- SVGA3D_FACE_MAX
+ SVGA3D_FACE_INVALID = 0,
+ SVGA3D_FACE_NONE = 1,
+ SVGA3D_FACE_MIN = 1,
+ SVGA3D_FACE_FRONT = 2,
+ SVGA3D_FACE_BACK = 3,
+ SVGA3D_FACE_FRONT_BACK = 4,
+ SVGA3D_FACE_MAX
} SVGA3dFace;
-/*
- * The order and the values should not be changed
- */
-
typedef enum {
- SVGA3D_CMP_INVALID = 0,
- SVGA3D_CMP_NEVER = 1,
- SVGA3D_CMP_LESS = 2,
- SVGA3D_CMP_EQUAL = 3,
- SVGA3D_CMP_LESSEQUAL = 4,
- SVGA3D_CMP_GREATER = 5,
- SVGA3D_CMP_NOTEQUAL = 6,
- SVGA3D_CMP_GREATEREQUAL = 7,
- SVGA3D_CMP_ALWAYS = 8,
- SVGA3D_CMP_MAX
+ SVGA3D_CMP_INVALID = 0,
+ SVGA3D_CMP_NEVER = 1,
+ SVGA3D_CMP_LESS = 2,
+ SVGA3D_CMP_EQUAL = 3,
+ SVGA3D_CMP_LESSEQUAL = 4,
+ SVGA3D_CMP_GREATER = 5,
+ SVGA3D_CMP_NOTEQUAL = 6,
+ SVGA3D_CMP_GREATEREQUAL = 7,
+ SVGA3D_CMP_ALWAYS = 8,
+ SVGA3D_CMP_MAX
} SVGA3dCmpFunc;
-/*
- * SVGA3D_FOGFUNC_* specifies the fog equation, or PER_VERTEX which allows
- * the fog factor to be specified in the alpha component of the specular
- * (a.k.a. secondary) vertex color.
- */
typedef enum {
- SVGA3D_FOGFUNC_INVALID = 0,
- SVGA3D_FOGFUNC_EXP = 1,
- SVGA3D_FOGFUNC_EXP2 = 2,
- SVGA3D_FOGFUNC_LINEAR = 3,
- SVGA3D_FOGFUNC_PER_VERTEX = 4
+ SVGA3D_FOGFUNC_INVALID = 0,
+ SVGA3D_FOGFUNC_EXP = 1,
+ SVGA3D_FOGFUNC_EXP2 = 2,
+ SVGA3D_FOGFUNC_LINEAR = 3,
+ SVGA3D_FOGFUNC_PER_VERTEX = 4
} SVGA3dFogFunction;
-/*
- * SVGA3D_FOGTYPE_* specifies if fog factors are computed on a per-vertex
- * or per-pixel basis.
- */
typedef enum {
- SVGA3D_FOGTYPE_INVALID = 0,
- SVGA3D_FOGTYPE_VERTEX = 1,
- SVGA3D_FOGTYPE_PIXEL = 2,
- SVGA3D_FOGTYPE_MAX = 3
+ SVGA3D_FOGTYPE_INVALID = 0,
+ SVGA3D_FOGTYPE_VERTEX = 1,
+ SVGA3D_FOGTYPE_PIXEL = 2,
+ SVGA3D_FOGTYPE_MAX = 3
} SVGA3dFogType;
-/*
- * SVGA3D_FOGBASE_* selects depth or range-based fog. Depth-based fog is
- * computed using the eye Z value of each pixel (or vertex), whereas range-
- * based fog is computed using the actual distance (range) to the eye.
- */
typedef enum {
- SVGA3D_FOGBASE_INVALID = 0,
- SVGA3D_FOGBASE_DEPTHBASED = 1,
- SVGA3D_FOGBASE_RANGEBASED = 2,
- SVGA3D_FOGBASE_MAX = 3
+ SVGA3D_FOGBASE_INVALID = 0,
+ SVGA3D_FOGBASE_DEPTHBASED = 1,
+ SVGA3D_FOGBASE_RANGEBASED = 2,
+ SVGA3D_FOGBASE_MAX = 3
} SVGA3dFogBase;
typedef enum {
- SVGA3D_STENCILOP_INVALID = 0,
- SVGA3D_STENCILOP_MIN = 1,
- SVGA3D_STENCILOP_KEEP = 1,
- SVGA3D_STENCILOP_ZERO = 2,
- SVGA3D_STENCILOP_REPLACE = 3,
- SVGA3D_STENCILOP_INCRSAT = 4,
- SVGA3D_STENCILOP_DECRSAT = 5,
- SVGA3D_STENCILOP_INVERT = 6,
- SVGA3D_STENCILOP_INCR = 7,
- SVGA3D_STENCILOP_DECR = 8,
- SVGA3D_STENCILOP_MAX
+ SVGA3D_STENCILOP_INVALID = 0,
+ SVGA3D_STENCILOP_MIN = 1,
+ SVGA3D_STENCILOP_KEEP = 1,
+ SVGA3D_STENCILOP_ZERO = 2,
+ SVGA3D_STENCILOP_REPLACE = 3,
+ SVGA3D_STENCILOP_INCRSAT = 4,
+ SVGA3D_STENCILOP_DECRSAT = 5,
+ SVGA3D_STENCILOP_INVERT = 6,
+ SVGA3D_STENCILOP_INCR = 7,
+ SVGA3D_STENCILOP_DECR = 8,
+ SVGA3D_STENCILOP_MAX
} SVGA3dStencilOp;
typedef enum {
- SVGA3D_CLIPPLANE_0 = (1 << 0),
- SVGA3D_CLIPPLANE_1 = (1 << 1),
- SVGA3D_CLIPPLANE_2 = (1 << 2),
- SVGA3D_CLIPPLANE_3 = (1 << 3),
- SVGA3D_CLIPPLANE_4 = (1 << 4),
- SVGA3D_CLIPPLANE_5 = (1 << 5),
+ SVGA3D_CLIPPLANE_0 = (1 << 0),
+ SVGA3D_CLIPPLANE_1 = (1 << 1),
+ SVGA3D_CLIPPLANE_2 = (1 << 2),
+ SVGA3D_CLIPPLANE_3 = (1 << 3),
+ SVGA3D_CLIPPLANE_4 = (1 << 4),
+ SVGA3D_CLIPPLANE_5 = (1 << 5),
} SVGA3dClipPlanes;
typedef enum {
- SVGA3D_CLEAR_COLOR = 0x1,
- SVGA3D_CLEAR_DEPTH = 0x2,
- SVGA3D_CLEAR_STENCIL = 0x4,
-
- /*
- * Hint only, must be used together with SVGA3D_CLEAR_COLOR. If
- * SVGA3D_CLEAR_DEPTH or SVGA3D_CLEAR_STENCIL bit is set, this
- * bit will be ignored.
- */
- SVGA3D_CLEAR_COLORFILL = 0x8
+ SVGA3D_CLEAR_COLOR = 0x1,
+ SVGA3D_CLEAR_DEPTH = 0x2,
+ SVGA3D_CLEAR_STENCIL = 0x4,
+
+ SVGA3D_CLEAR_COLORFILL = 0x8
} SVGA3dClearFlag;
typedef enum {
- SVGA3D_RT_DEPTH = 0,
- SVGA3D_RT_MIN = 0,
- SVGA3D_RT_STENCIL = 1,
- SVGA3D_RT_COLOR0 = 2,
- SVGA3D_RT_COLOR1 = 3,
- SVGA3D_RT_COLOR2 = 4,
- SVGA3D_RT_COLOR3 = 5,
- SVGA3D_RT_COLOR4 = 6,
- SVGA3D_RT_COLOR5 = 7,
- SVGA3D_RT_COLOR6 = 8,
- SVGA3D_RT_COLOR7 = 9,
- SVGA3D_RT_MAX,
- SVGA3D_RT_INVALID = ((uint32)-1),
+ SVGA3D_RT_DEPTH = 0,
+ SVGA3D_RT_MIN = 0,
+ SVGA3D_RT_STENCIL = 1,
+ SVGA3D_RT_COLOR0 = 2,
+ SVGA3D_RT_COLOR1 = 3,
+ SVGA3D_RT_COLOR2 = 4,
+ SVGA3D_RT_COLOR3 = 5,
+ SVGA3D_RT_COLOR4 = 6,
+ SVGA3D_RT_COLOR5 = 7,
+ SVGA3D_RT_COLOR6 = 8,
+ SVGA3D_RT_COLOR7 = 9,
+ SVGA3D_RT_MAX,
+ SVGA3D_RT_INVALID = ((uint32)-1),
} SVGA3dRenderTargetType;
#define SVGA3D_MAX_RT_COLOR (SVGA3D_RT_COLOR7 - SVGA3D_RT_COLOR0 + 1)
-typedef
-#include "vmware_pack_begin.h"
-union {
- struct {
- uint32 red : 1;
- uint32 green : 1;
- uint32 blue : 1;
- uint32 alpha : 1;
- };
- uint32 uintValue;
-}
-#include "vmware_pack_end.h"
-SVGA3dColorMask;
+#pragma pack(push, 1)
+typedef union {
+ struct {
+ uint32 red : 1;
+ uint32 green : 1;
+ uint32 blue : 1;
+ uint32 alpha : 1;
+ };
+ uint32 uintValue;
+} SVGA3dColorMask;
+#pragma pack(pop)
typedef enum {
- SVGA3D_VBLEND_DISABLE = 0,
- SVGA3D_VBLEND_1WEIGHT = 1,
- SVGA3D_VBLEND_2WEIGHT = 2,
- SVGA3D_VBLEND_3WEIGHT = 3,
- SVGA3D_VBLEND_MAX = 4,
+ SVGA3D_VBLEND_DISABLE = 0,
+ SVGA3D_VBLEND_1WEIGHT = 1,
+ SVGA3D_VBLEND_2WEIGHT = 2,
+ SVGA3D_VBLEND_3WEIGHT = 3,
+ SVGA3D_VBLEND_MAX = 4,
} SVGA3dVertexBlendFlags;
typedef enum {
- SVGA3D_WRAPCOORD_0 = 1 << 0,
- SVGA3D_WRAPCOORD_1 = 1 << 1,
- SVGA3D_WRAPCOORD_2 = 1 << 2,
- SVGA3D_WRAPCOORD_3 = 1 << 3,
- SVGA3D_WRAPCOORD_ALL = 0xF,
+ SVGA3D_WRAPCOORD_0 = 1 << 0,
+ SVGA3D_WRAPCOORD_1 = 1 << 1,
+ SVGA3D_WRAPCOORD_2 = 1 << 2,
+ SVGA3D_WRAPCOORD_3 = 1 << 3,
+ SVGA3D_WRAPCOORD_ALL = 0xF,
} SVGA3dWrapFlags;
-/*
- * SVGA_3D_CMD_TEXTURESTATE Types. All value types
- * must fit in a uint32.
- */
-
typedef enum {
- SVGA3D_TS_INVALID = 0,
- SVGA3D_TS_MIN = 1,
- SVGA3D_TS_BIND_TEXTURE = 1, /* SVGA3dSurfaceId */
- SVGA3D_TS_COLOROP = 2, /* SVGA3dTextureCombiner */
- SVGA3D_TS_COLORARG1 = 3, /* SVGA3dTextureArgData */
- SVGA3D_TS_COLORARG2 = 4, /* SVGA3dTextureArgData */
- SVGA3D_TS_ALPHAOP = 5, /* SVGA3dTextureCombiner */
- SVGA3D_TS_ALPHAARG1 = 6, /* SVGA3dTextureArgData */
- SVGA3D_TS_ALPHAARG2 = 7, /* SVGA3dTextureArgData */
- SVGA3D_TS_ADDRESSU = 8, /* SVGA3dTextureAddress */
- SVGA3D_TS_ADDRESSV = 9, /* SVGA3dTextureAddress */
- SVGA3D_TS_MIPFILTER = 10, /* SVGA3dTextureFilter */
- SVGA3D_TS_MAGFILTER = 11, /* SVGA3dTextureFilter */
- SVGA3D_TS_MINFILTER = 12, /* SVGA3dTextureFilter */
- SVGA3D_TS_BORDERCOLOR = 13, /* SVGA3dColor */
- SVGA3D_TS_TEXCOORDINDEX = 14, /* uint32 */
- SVGA3D_TS_TEXTURETRANSFORMFLAGS = 15, /* SVGA3dTexTransformFlags */
- SVGA3D_TS_TEXCOORDGEN = 16, /* SVGA3dTextureCoordGen */
- SVGA3D_TS_BUMPENVMAT00 = 17, /* float */
- SVGA3D_TS_BUMPENVMAT01 = 18, /* float */
- SVGA3D_TS_BUMPENVMAT10 = 19, /* float */
- SVGA3D_TS_BUMPENVMAT11 = 20, /* float */
- SVGA3D_TS_TEXTURE_MIPMAP_LEVEL = 21, /* uint32 */
- SVGA3D_TS_TEXTURE_LOD_BIAS = 22, /* float */
- SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL = 23, /* uint32 */
- SVGA3D_TS_ADDRESSW = 24, /* SVGA3dTextureAddress */
-
-
- /*
- * Sampler Gamma Level
- *
- * Sampler gamma effects the color of samples taken from the sampler. A
- * value of 1.0 will produce linear samples. If the value is <= 0.0 the
- * gamma value is ignored and a linear space is used.
- */
-
- SVGA3D_TS_GAMMA = 25, /* float */
- SVGA3D_TS_BUMPENVLSCALE = 26, /* float */
- SVGA3D_TS_BUMPENVLOFFSET = 27, /* float */
- SVGA3D_TS_COLORARG0 = 28, /* SVGA3dTextureArgData */
- SVGA3D_TS_ALPHAARG0 = 29, /* SVGA3dTextureArgData */
- SVGA3D_TS_PREGB_MAX = 30, /* Max value before GBObjects */
- SVGA3D_TS_CONSTANT = 30, /* SVGA3dColor */
- SVGA3D_TS_COLOR_KEY_ENABLE = 31, /* SVGA3dBool */
- SVGA3D_TS_COLOR_KEY = 32, /* SVGA3dColor */
- SVGA3D_TS_MAX
+ SVGA3D_TS_INVALID = 0,
+ SVGA3D_TS_MIN = 1,
+ SVGA3D_TS_BIND_TEXTURE = 1,
+ SVGA3D_TS_COLOROP = 2,
+ SVGA3D_TS_COLORARG1 = 3,
+ SVGA3D_TS_COLORARG2 = 4,
+ SVGA3D_TS_ALPHAOP = 5,
+ SVGA3D_TS_ALPHAARG1 = 6,
+ SVGA3D_TS_ALPHAARG2 = 7,
+ SVGA3D_TS_ADDRESSU = 8,
+ SVGA3D_TS_ADDRESSV = 9,
+ SVGA3D_TS_MIPFILTER = 10,
+ SVGA3D_TS_MAGFILTER = 11,
+ SVGA3D_TS_MINFILTER = 12,
+ SVGA3D_TS_BORDERCOLOR = 13,
+ SVGA3D_TS_TEXCOORDINDEX = 14,
+ SVGA3D_TS_TEXTURETRANSFORMFLAGS = 15,
+ SVGA3D_TS_TEXCOORDGEN = 16,
+ SVGA3D_TS_BUMPENVMAT00 = 17,
+ SVGA3D_TS_BUMPENVMAT01 = 18,
+ SVGA3D_TS_BUMPENVMAT10 = 19,
+ SVGA3D_TS_BUMPENVMAT11 = 20,
+ SVGA3D_TS_TEXTURE_MIPMAP_LEVEL = 21,
+ SVGA3D_TS_TEXTURE_LOD_BIAS = 22,
+ SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL = 23,
+ SVGA3D_TS_ADDRESSW = 24,
+
+ SVGA3D_TS_GAMMA = 25,
+ SVGA3D_TS_BUMPENVLSCALE = 26,
+ SVGA3D_TS_BUMPENVLOFFSET = 27,
+ SVGA3D_TS_COLORARG0 = 28,
+ SVGA3D_TS_ALPHAARG0 = 29,
+ SVGA3D_TS_PREGB_MAX = 30,
+ SVGA3D_TS_CONSTANT = 30,
+ SVGA3D_TS_COLOR_KEY_ENABLE = 31,
+ SVGA3D_TS_COLOR_KEY = 32,
+ SVGA3D_TS_MAX
} SVGA3dTextureStateName;
typedef enum {
- SVGA3D_TC_INVALID = 0,
- SVGA3D_TC_DISABLE = 1,
- SVGA3D_TC_SELECTARG1 = 2,
- SVGA3D_TC_SELECTARG2 = 3,
- SVGA3D_TC_MODULATE = 4,
- SVGA3D_TC_ADD = 5,
- SVGA3D_TC_ADDSIGNED = 6,
- SVGA3D_TC_SUBTRACT = 7,
- SVGA3D_TC_BLENDTEXTUREALPHA = 8,
- SVGA3D_TC_BLENDDIFFUSEALPHA = 9,
- SVGA3D_TC_BLENDCURRENTALPHA = 10,
- SVGA3D_TC_BLENDFACTORALPHA = 11,
- SVGA3D_TC_MODULATE2X = 12,
- SVGA3D_TC_MODULATE4X = 13,
- SVGA3D_TC_DSDT = 14,
- SVGA3D_TC_DOTPRODUCT3 = 15,
- SVGA3D_TC_BLENDTEXTUREALPHAPM = 16,
- SVGA3D_TC_ADDSIGNED2X = 17,
- SVGA3D_TC_ADDSMOOTH = 18,
- SVGA3D_TC_PREMODULATE = 19,
- SVGA3D_TC_MODULATEALPHA_ADDCOLOR = 20,
- SVGA3D_TC_MODULATECOLOR_ADDALPHA = 21,
- SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR = 22,
- SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA = 23,
- SVGA3D_TC_BUMPENVMAPLUMINANCE = 24,
- SVGA3D_TC_MULTIPLYADD = 25,
- SVGA3D_TC_LERP = 26,
- SVGA3D_TC_MAX
+ SVGA3D_TC_INVALID = 0,
+ SVGA3D_TC_DISABLE = 1,
+ SVGA3D_TC_SELECTARG1 = 2,
+ SVGA3D_TC_SELECTARG2 = 3,
+ SVGA3D_TC_MODULATE = 4,
+ SVGA3D_TC_ADD = 5,
+ SVGA3D_TC_ADDSIGNED = 6,
+ SVGA3D_TC_SUBTRACT = 7,
+ SVGA3D_TC_BLENDTEXTUREALPHA = 8,
+ SVGA3D_TC_BLENDDIFFUSEALPHA = 9,
+ SVGA3D_TC_BLENDCURRENTALPHA = 10,
+ SVGA3D_TC_BLENDFACTORALPHA = 11,
+ SVGA3D_TC_MODULATE2X = 12,
+ SVGA3D_TC_MODULATE4X = 13,
+ SVGA3D_TC_DSDT = 14,
+ SVGA3D_TC_DOTPRODUCT3 = 15,
+ SVGA3D_TC_BLENDTEXTUREALPHAPM = 16,
+ SVGA3D_TC_ADDSIGNED2X = 17,
+ SVGA3D_TC_ADDSMOOTH = 18,
+ SVGA3D_TC_PREMODULATE = 19,
+ SVGA3D_TC_MODULATEALPHA_ADDCOLOR = 20,
+ SVGA3D_TC_MODULATECOLOR_ADDALPHA = 21,
+ SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR = 22,
+ SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA = 23,
+ SVGA3D_TC_BUMPENVMAPLUMINANCE = 24,
+ SVGA3D_TC_MULTIPLYADD = 25,
+ SVGA3D_TC_LERP = 26,
+ SVGA3D_TC_MAX
} SVGA3dTextureCombiner;
-#define SVGA3D_TC_CAP_BIT(svga3d_tc_op) (svga3d_tc_op ? (1 << (svga3d_tc_op - 1)) : 0)
+#define SVGA3D_TC_CAP_BIT(svga3d_tc_op) \
+ (svga3d_tc_op ? (1 << (svga3d_tc_op - 1)) : 0)
typedef enum {
- SVGA3D_TEX_ADDRESS_INVALID = 0,
- SVGA3D_TEX_ADDRESS_MIN = 1,
- SVGA3D_TEX_ADDRESS_WRAP = 1,
- SVGA3D_TEX_ADDRESS_MIRROR = 2,
- SVGA3D_TEX_ADDRESS_CLAMP = 3,
- SVGA3D_TEX_ADDRESS_BORDER = 4,
- SVGA3D_TEX_ADDRESS_MIRRORONCE = 5,
- SVGA3D_TEX_ADDRESS_EDGE = 6,
- SVGA3D_TEX_ADDRESS_MAX
+ SVGA3D_TEX_ADDRESS_INVALID = 0,
+ SVGA3D_TEX_ADDRESS_MIN = 1,
+ SVGA3D_TEX_ADDRESS_WRAP = 1,
+ SVGA3D_TEX_ADDRESS_MIRROR = 2,
+ SVGA3D_TEX_ADDRESS_CLAMP = 3,
+ SVGA3D_TEX_ADDRESS_BORDER = 4,
+ SVGA3D_TEX_ADDRESS_MIRRORONCE = 5,
+ SVGA3D_TEX_ADDRESS_EDGE = 6,
+ SVGA3D_TEX_ADDRESS_MAX
} SVGA3dTextureAddress;
-/*
- * SVGA3D_TEX_FILTER_NONE as the minification filter means mipmapping is
- * disabled, and the rasterizer should use the magnification filter instead.
- */
typedef enum {
- SVGA3D_TEX_FILTER_NONE = 0,
- SVGA3D_TEX_FILTER_MIN = 0,
- SVGA3D_TEX_FILTER_NEAREST = 1,
- SVGA3D_TEX_FILTER_LINEAR = 2,
- SVGA3D_TEX_FILTER_ANISOTROPIC = 3,
- SVGA3D_TEX_FILTER_FLATCUBIC = 4, /* Deprecated, not implemented */
- SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5, /* Deprecated, not implemented */
- SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6, /* Not currently implemented */
- SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7, /* Not currently implemented */
- SVGA3D_TEX_FILTER_MAX
+ SVGA3D_TEX_FILTER_NONE = 0,
+ SVGA3D_TEX_FILTER_MIN = 0,
+ SVGA3D_TEX_FILTER_NEAREST = 1,
+ SVGA3D_TEX_FILTER_LINEAR = 2,
+ SVGA3D_TEX_FILTER_ANISOTROPIC = 3,
+ SVGA3D_TEX_FILTER_FLATCUBIC = 4,
+ SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5,
+ SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6,
+ SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7,
+ SVGA3D_TEX_FILTER_MAX
} SVGA3dTextureFilter;
typedef enum {
- SVGA3D_TEX_TRANSFORM_OFF = 0,
- SVGA3D_TEX_TRANSFORM_S = (1 << 0),
- SVGA3D_TEX_TRANSFORM_T = (1 << 1),
- SVGA3D_TEX_TRANSFORM_R = (1 << 2),
- SVGA3D_TEX_TRANSFORM_Q = (1 << 3),
- SVGA3D_TEX_PROJECTED = (1 << 15),
+ SVGA3D_TEX_TRANSFORM_OFF = 0,
+ SVGA3D_TEX_TRANSFORM_S = (1 << 0),
+ SVGA3D_TEX_TRANSFORM_T = (1 << 1),
+ SVGA3D_TEX_TRANSFORM_R = (1 << 2),
+ SVGA3D_TEX_TRANSFORM_Q = (1 << 3),
+ SVGA3D_TEX_PROJECTED = (1 << 15),
} SVGA3dTexTransformFlags;
typedef enum {
- SVGA3D_TEXCOORD_GEN_OFF = 0,
- SVGA3D_TEXCOORD_GEN_EYE_POSITION = 1,
- SVGA3D_TEXCOORD_GEN_EYE_NORMAL = 2,
- SVGA3D_TEXCOORD_GEN_REFLECTIONVECTOR = 3,
- SVGA3D_TEXCOORD_GEN_SPHERE = 4,
- SVGA3D_TEXCOORD_GEN_MAX
+ SVGA3D_TEXCOORD_GEN_OFF = 0,
+ SVGA3D_TEXCOORD_GEN_EYE_POSITION = 1,
+ SVGA3D_TEXCOORD_GEN_EYE_NORMAL = 2,
+ SVGA3D_TEXCOORD_GEN_REFLECTIONVECTOR = 3,
+ SVGA3D_TEXCOORD_GEN_SPHERE = 4,
+ SVGA3D_TEXCOORD_GEN_MAX
} SVGA3dTextureCoordGen;
-/*
- * Texture argument constants for texture combiner
- */
typedef enum {
- SVGA3D_TA_INVALID = 0,
- SVGA3D_TA_TFACTOR = 1,
- SVGA3D_TA_PREVIOUS = 2,
- SVGA3D_TA_DIFFUSE = 3,
- SVGA3D_TA_TEXTURE = 4,
- SVGA3D_TA_SPECULAR = 5,
- SVGA3D_TA_CONSTANT = 6,
- SVGA3D_TA_MAX
+ SVGA3D_TA_INVALID = 0,
+ SVGA3D_TA_TFACTOR = 1,
+ SVGA3D_TA_PREVIOUS = 2,
+ SVGA3D_TA_DIFFUSE = 3,
+ SVGA3D_TA_TEXTURE = 4,
+ SVGA3D_TA_SPECULAR = 5,
+ SVGA3D_TA_CONSTANT = 6,
+ SVGA3D_TA_MAX
} SVGA3dTextureArgData;
#define SVGA3D_TM_MASK_LEN 4
-/* Modifiers for texture argument constants defined above. */
typedef enum {
- SVGA3D_TM_NONE = 0,
- SVGA3D_TM_ALPHA = (1 << SVGA3D_TM_MASK_LEN),
- SVGA3D_TM_ONE_MINUS = (2 << SVGA3D_TM_MASK_LEN),
+ SVGA3D_TM_NONE = 0,
+ SVGA3D_TM_ALPHA = (1 << SVGA3D_TM_MASK_LEN),
+ SVGA3D_TM_ONE_MINUS = (2 << SVGA3D_TM_MASK_LEN),
} SVGA3dTextureArgModifier;
-/*
- * Vertex declarations
- *
- * Notes:
- *
- * SVGA3D_DECLUSAGE_POSITIONT is for pre-transformed vertices. If you
- * draw with any POSITIONT vertex arrays, the programmable vertex
- * pipeline will be implicitly disabled. Drawing will take place as if
- * no vertex shader was bound.
- */
-
typedef enum {
- SVGA3D_DECLUSAGE_POSITION = 0,
- SVGA3D_DECLUSAGE_BLENDWEIGHT,
- SVGA3D_DECLUSAGE_BLENDINDICES,
- SVGA3D_DECLUSAGE_NORMAL,
- SVGA3D_DECLUSAGE_PSIZE,
- SVGA3D_DECLUSAGE_TEXCOORD,
- SVGA3D_DECLUSAGE_TANGENT,
- SVGA3D_DECLUSAGE_BINORMAL,
- SVGA3D_DECLUSAGE_TESSFACTOR,
- SVGA3D_DECLUSAGE_POSITIONT,
- SVGA3D_DECLUSAGE_COLOR,
- SVGA3D_DECLUSAGE_FOG,
- SVGA3D_DECLUSAGE_DEPTH,
- SVGA3D_DECLUSAGE_SAMPLE,
- SVGA3D_DECLUSAGE_MAX
+ SVGA3D_DECLUSAGE_POSITION = 0,
+ SVGA3D_DECLUSAGE_BLENDWEIGHT,
+ SVGA3D_DECLUSAGE_BLENDINDICES,
+ SVGA3D_DECLUSAGE_NORMAL,
+ SVGA3D_DECLUSAGE_PSIZE,
+ SVGA3D_DECLUSAGE_TEXCOORD,
+ SVGA3D_DECLUSAGE_TANGENT,
+ SVGA3D_DECLUSAGE_BINORMAL,
+ SVGA3D_DECLUSAGE_TESSFACTOR,
+ SVGA3D_DECLUSAGE_POSITIONT,
+ SVGA3D_DECLUSAGE_COLOR,
+ SVGA3D_DECLUSAGE_FOG,
+ SVGA3D_DECLUSAGE_DEPTH,
+ SVGA3D_DECLUSAGE_SAMPLE,
+ SVGA3D_DECLUSAGE_MAX
} SVGA3dDeclUsage;
typedef enum {
- SVGA3D_DECLMETHOD_DEFAULT = 0,
- SVGA3D_DECLMETHOD_PARTIALU,
- SVGA3D_DECLMETHOD_PARTIALV,
- SVGA3D_DECLMETHOD_CROSSUV, /* Normal */
- SVGA3D_DECLMETHOD_UV,
- SVGA3D_DECLMETHOD_LOOKUP, /* Lookup a displacement map */
- SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, /* Lookup a pre-sampled displacement */
- /* map */
+ SVGA3D_DECLMETHOD_DEFAULT = 0,
+ SVGA3D_DECLMETHOD_PARTIALU,
+ SVGA3D_DECLMETHOD_PARTIALV,
+ SVGA3D_DECLMETHOD_CROSSUV,
+ SVGA3D_DECLMETHOD_UV,
+ SVGA3D_DECLMETHOD_LOOKUP,
+ SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED,
} SVGA3dDeclMethod;
typedef enum {
- SVGA3D_DECLTYPE_FLOAT1 = 0,
- SVGA3D_DECLTYPE_FLOAT2 = 1,
- SVGA3D_DECLTYPE_FLOAT3 = 2,
- SVGA3D_DECLTYPE_FLOAT4 = 3,
- SVGA3D_DECLTYPE_D3DCOLOR = 4,
- SVGA3D_DECLTYPE_UBYTE4 = 5,
- SVGA3D_DECLTYPE_SHORT2 = 6,
- SVGA3D_DECLTYPE_SHORT4 = 7,
- SVGA3D_DECLTYPE_UBYTE4N = 8,
- SVGA3D_DECLTYPE_SHORT2N = 9,
- SVGA3D_DECLTYPE_SHORT4N = 10,
- SVGA3D_DECLTYPE_USHORT2N = 11,
- SVGA3D_DECLTYPE_USHORT4N = 12,
- SVGA3D_DECLTYPE_UDEC3 = 13,
- SVGA3D_DECLTYPE_DEC3N = 14,
- SVGA3D_DECLTYPE_FLOAT16_2 = 15,
- SVGA3D_DECLTYPE_FLOAT16_4 = 16,
- SVGA3D_DECLTYPE_MAX,
+ SVGA3D_DECLTYPE_FLOAT1 = 0,
+ SVGA3D_DECLTYPE_FLOAT2 = 1,
+ SVGA3D_DECLTYPE_FLOAT3 = 2,
+ SVGA3D_DECLTYPE_FLOAT4 = 3,
+ SVGA3D_DECLTYPE_D3DCOLOR = 4,
+ SVGA3D_DECLTYPE_UBYTE4 = 5,
+ SVGA3D_DECLTYPE_SHORT2 = 6,
+ SVGA3D_DECLTYPE_SHORT4 = 7,
+ SVGA3D_DECLTYPE_UBYTE4N = 8,
+ SVGA3D_DECLTYPE_SHORT2N = 9,
+ SVGA3D_DECLTYPE_SHORT4N = 10,
+ SVGA3D_DECLTYPE_USHORT2N = 11,
+ SVGA3D_DECLTYPE_USHORT4N = 12,
+ SVGA3D_DECLTYPE_UDEC3 = 13,
+ SVGA3D_DECLTYPE_DEC3N = 14,
+ SVGA3D_DECLTYPE_FLOAT16_2 = 15,
+ SVGA3D_DECLTYPE_FLOAT16_4 = 16,
+ SVGA3D_DECLTYPE_MAX,
} SVGA3dDeclType;
-/*
- * This structure is used for the divisor for geometry instancing;
- * it's a direct translation of the Direct3D equivalent.
- */
typedef union {
- struct {
- /*
- * For index data, this number represents the number of instances to draw.
- * For instance data, this number represents the number of
- * instances/vertex in this stream
- */
- uint32 count : 30;
-
- /*
- * This is 1 if this is supposed to be the data that is repeated for
- * every instance.
- */
- uint32 indexedData : 1;
-
- /*
- * This is 1 if this is supposed to be the per-instance data.
- */
- uint32 instanceData : 1;
- };
-
- uint32 value;
+ struct {
+ uint32 count : 30;
+
+ uint32 indexedData : 1;
+
+ uint32 instanceData : 1;
+ };
+
+ uint32 value;
} SVGA3dVertexDivisor;
typedef enum {
- /*
- * SVGA3D_PRIMITIVE_INVALID is a valid primitive type.
- *
- * List MIN second so debuggers will think INVALID is
- * the correct name.
- */
- SVGA3D_PRIMITIVE_INVALID = 0,
- SVGA3D_PRIMITIVE_MIN = 0,
- SVGA3D_PRIMITIVE_TRIANGLELIST = 1,
- SVGA3D_PRIMITIVE_POINTLIST = 2,
- SVGA3D_PRIMITIVE_LINELIST = 3,
- SVGA3D_PRIMITIVE_LINESTRIP = 4,
- SVGA3D_PRIMITIVE_TRIANGLESTRIP = 5,
- SVGA3D_PRIMITIVE_TRIANGLEFAN = 6,
- SVGA3D_PRIMITIVE_LINELIST_ADJ = 7,
- SVGA3D_PRIMITIVE_PREDX_MAX = 7,
- SVGA3D_PRIMITIVE_LINESTRIP_ADJ = 8,
- SVGA3D_PRIMITIVE_TRIANGLELIST_ADJ = 9,
- SVGA3D_PRIMITIVE_TRIANGLESTRIP_ADJ = 10,
- SVGA3D_PRIMITIVE_DX10_MAX = 11,
- SVGA3D_PRIMITIVE_1_CONTROL_POINT_PATCH = 11,
- SVGA3D_PRIMITIVE_2_CONTROL_POINT_PATCH = 12,
- SVGA3D_PRIMITIVE_3_CONTROL_POINT_PATCH = 13,
- SVGA3D_PRIMITIVE_4_CONTROL_POINT_PATCH = 14,
- SVGA3D_PRIMITIVE_5_CONTROL_POINT_PATCH = 15,
- SVGA3D_PRIMITIVE_6_CONTROL_POINT_PATCH = 16,
- SVGA3D_PRIMITIVE_7_CONTROL_POINT_PATCH = 17,
- SVGA3D_PRIMITIVE_8_CONTROL_POINT_PATCH = 18,
- SVGA3D_PRIMITIVE_9_CONTROL_POINT_PATCH = 19,
- SVGA3D_PRIMITIVE_10_CONTROL_POINT_PATCH = 20,
- SVGA3D_PRIMITIVE_11_CONTROL_POINT_PATCH = 21,
- SVGA3D_PRIMITIVE_12_CONTROL_POINT_PATCH = 22,
- SVGA3D_PRIMITIVE_13_CONTROL_POINT_PATCH = 23,
- SVGA3D_PRIMITIVE_14_CONTROL_POINT_PATCH = 24,
- SVGA3D_PRIMITIVE_15_CONTROL_POINT_PATCH = 25,
- SVGA3D_PRIMITIVE_16_CONTROL_POINT_PATCH = 26,
- SVGA3D_PRIMITIVE_17_CONTROL_POINT_PATCH = 27,
- SVGA3D_PRIMITIVE_18_CONTROL_POINT_PATCH = 28,
- SVGA3D_PRIMITIVE_19_CONTROL_POINT_PATCH = 29,
- SVGA3D_PRIMITIVE_20_CONTROL_POINT_PATCH = 30,
- SVGA3D_PRIMITIVE_21_CONTROL_POINT_PATCH = 31,
- SVGA3D_PRIMITIVE_22_CONTROL_POINT_PATCH = 32,
- SVGA3D_PRIMITIVE_23_CONTROL_POINT_PATCH = 33,
- SVGA3D_PRIMITIVE_24_CONTROL_POINT_PATCH = 34,
- SVGA3D_PRIMITIVE_25_CONTROL_POINT_PATCH = 35,
- SVGA3D_PRIMITIVE_26_CONTROL_POINT_PATCH = 36,
- SVGA3D_PRIMITIVE_27_CONTROL_POINT_PATCH = 37,
- SVGA3D_PRIMITIVE_28_CONTROL_POINT_PATCH = 38,
- SVGA3D_PRIMITIVE_29_CONTROL_POINT_PATCH = 39,
- SVGA3D_PRIMITIVE_30_CONTROL_POINT_PATCH = 40,
- SVGA3D_PRIMITIVE_31_CONTROL_POINT_PATCH = 41,
- SVGA3D_PRIMITIVE_32_CONTROL_POINT_PATCH = 42,
- SVGA3D_PRIMITIVE_MAX = 43
+
+ SVGA3D_PRIMITIVE_INVALID = 0,
+ SVGA3D_PRIMITIVE_MIN = 0,
+ SVGA3D_PRIMITIVE_TRIANGLELIST = 1,
+ SVGA3D_PRIMITIVE_POINTLIST = 2,
+ SVGA3D_PRIMITIVE_LINELIST = 3,
+ SVGA3D_PRIMITIVE_LINESTRIP = 4,
+ SVGA3D_PRIMITIVE_TRIANGLESTRIP = 5,
+ SVGA3D_PRIMITIVE_TRIANGLEFAN = 6,
+ SVGA3D_PRIMITIVE_LINELIST_ADJ = 7,
+ SVGA3D_PRIMITIVE_PREDX_MAX = 7,
+ SVGA3D_PRIMITIVE_LINESTRIP_ADJ = 8,
+ SVGA3D_PRIMITIVE_TRIANGLELIST_ADJ = 9,
+ SVGA3D_PRIMITIVE_TRIANGLESTRIP_ADJ = 10,
+ SVGA3D_PRIMITIVE_DX10_MAX = 11,
+ SVGA3D_PRIMITIVE_1_CONTROL_POINT_PATCH = 11,
+ SVGA3D_PRIMITIVE_2_CONTROL_POINT_PATCH = 12,
+ SVGA3D_PRIMITIVE_3_CONTROL_POINT_PATCH = 13,
+ SVGA3D_PRIMITIVE_4_CONTROL_POINT_PATCH = 14,
+ SVGA3D_PRIMITIVE_5_CONTROL_POINT_PATCH = 15,
+ SVGA3D_PRIMITIVE_6_CONTROL_POINT_PATCH = 16,
+ SVGA3D_PRIMITIVE_7_CONTROL_POINT_PATCH = 17,
+ SVGA3D_PRIMITIVE_8_CONTROL_POINT_PATCH = 18,
+ SVGA3D_PRIMITIVE_9_CONTROL_POINT_PATCH = 19,
+ SVGA3D_PRIMITIVE_10_CONTROL_POINT_PATCH = 20,
+ SVGA3D_PRIMITIVE_11_CONTROL_POINT_PATCH = 21,
+ SVGA3D_PRIMITIVE_12_CONTROL_POINT_PATCH = 22,
+ SVGA3D_PRIMITIVE_13_CONTROL_POINT_PATCH = 23,
+ SVGA3D_PRIMITIVE_14_CONTROL_POINT_PATCH = 24,
+ SVGA3D_PRIMITIVE_15_CONTROL_POINT_PATCH = 25,
+ SVGA3D_PRIMITIVE_16_CONTROL_POINT_PATCH = 26,
+ SVGA3D_PRIMITIVE_17_CONTROL_POINT_PATCH = 27,
+ SVGA3D_PRIMITIVE_18_CONTROL_POINT_PATCH = 28,
+ SVGA3D_PRIMITIVE_19_CONTROL_POINT_PATCH = 29,
+ SVGA3D_PRIMITIVE_20_CONTROL_POINT_PATCH = 30,
+ SVGA3D_PRIMITIVE_21_CONTROL_POINT_PATCH = 31,
+ SVGA3D_PRIMITIVE_22_CONTROL_POINT_PATCH = 32,
+ SVGA3D_PRIMITIVE_23_CONTROL_POINT_PATCH = 33,
+ SVGA3D_PRIMITIVE_24_CONTROL_POINT_PATCH = 34,
+ SVGA3D_PRIMITIVE_25_CONTROL_POINT_PATCH = 35,
+ SVGA3D_PRIMITIVE_26_CONTROL_POINT_PATCH = 36,
+ SVGA3D_PRIMITIVE_27_CONTROL_POINT_PATCH = 37,
+ SVGA3D_PRIMITIVE_28_CONTROL_POINT_PATCH = 38,
+ SVGA3D_PRIMITIVE_29_CONTROL_POINT_PATCH = 39,
+ SVGA3D_PRIMITIVE_30_CONTROL_POINT_PATCH = 40,
+ SVGA3D_PRIMITIVE_31_CONTROL_POINT_PATCH = 41,
+ SVGA3D_PRIMITIVE_32_CONTROL_POINT_PATCH = 42,
+ SVGA3D_PRIMITIVE_MAX = 43
} SVGA3dPrimitiveType;
typedef enum {
- SVGA3D_COORDINATE_INVALID = 0,
- SVGA3D_COORDINATE_LEFTHANDED = 1,
- SVGA3D_COORDINATE_RIGHTHANDED = 2,
- SVGA3D_COORDINATE_MAX
+ SVGA3D_COORDINATE_INVALID = 0,
+ SVGA3D_COORDINATE_LEFTHANDED = 1,
+ SVGA3D_COORDINATE_RIGHTHANDED = 2,
+ SVGA3D_COORDINATE_MAX
} SVGA3dCoordinateType;
typedef enum {
- SVGA3D_TRANSFORM_INVALID = 0,
- SVGA3D_TRANSFORM_WORLD = 1,
- SVGA3D_TRANSFORM_MIN = 1,
- SVGA3D_TRANSFORM_VIEW = 2,
- SVGA3D_TRANSFORM_PROJECTION = 3,
- SVGA3D_TRANSFORM_TEXTURE0 = 4,
- SVGA3D_TRANSFORM_TEXTURE1 = 5,
- SVGA3D_TRANSFORM_TEXTURE2 = 6,
- SVGA3D_TRANSFORM_TEXTURE3 = 7,
- SVGA3D_TRANSFORM_TEXTURE4 = 8,
- SVGA3D_TRANSFORM_TEXTURE5 = 9,
- SVGA3D_TRANSFORM_TEXTURE6 = 10,
- SVGA3D_TRANSFORM_TEXTURE7 = 11,
- SVGA3D_TRANSFORM_WORLD1 = 12,
- SVGA3D_TRANSFORM_WORLD2 = 13,
- SVGA3D_TRANSFORM_WORLD3 = 14,
- SVGA3D_TRANSFORM_MAX
+ SVGA3D_TRANSFORM_INVALID = 0,
+ SVGA3D_TRANSFORM_WORLD = 1,
+ SVGA3D_TRANSFORM_MIN = 1,
+ SVGA3D_TRANSFORM_VIEW = 2,
+ SVGA3D_TRANSFORM_PROJECTION = 3,
+ SVGA3D_TRANSFORM_TEXTURE0 = 4,
+ SVGA3D_TRANSFORM_TEXTURE1 = 5,
+ SVGA3D_TRANSFORM_TEXTURE2 = 6,
+ SVGA3D_TRANSFORM_TEXTURE3 = 7,
+ SVGA3D_TRANSFORM_TEXTURE4 = 8,
+ SVGA3D_TRANSFORM_TEXTURE5 = 9,
+ SVGA3D_TRANSFORM_TEXTURE6 = 10,
+ SVGA3D_TRANSFORM_TEXTURE7 = 11,
+ SVGA3D_TRANSFORM_WORLD1 = 12,
+ SVGA3D_TRANSFORM_WORLD2 = 13,
+ SVGA3D_TRANSFORM_WORLD3 = 14,
+ SVGA3D_TRANSFORM_MAX
} SVGA3dTransformType;
typedef enum {
- SVGA3D_LIGHTTYPE_INVALID = 0,
- SVGA3D_LIGHTTYPE_MIN = 1,
- SVGA3D_LIGHTTYPE_POINT = 1,
- SVGA3D_LIGHTTYPE_SPOT1 = 2, /* 1-cone, in degrees */
- SVGA3D_LIGHTTYPE_SPOT2 = 3, /* 2-cone, in radians */
- SVGA3D_LIGHTTYPE_DIRECTIONAL = 4,
- SVGA3D_LIGHTTYPE_MAX
+ SVGA3D_LIGHTTYPE_INVALID = 0,
+ SVGA3D_LIGHTTYPE_MIN = 1,
+ SVGA3D_LIGHTTYPE_POINT = 1,
+ SVGA3D_LIGHTTYPE_SPOT1 = 2,
+ SVGA3D_LIGHTTYPE_SPOT2 = 3,
+ SVGA3D_LIGHTTYPE_DIRECTIONAL = 4,
+ SVGA3D_LIGHTTYPE_MAX
} SVGA3dLightType;
typedef enum {
- SVGA3D_CUBEFACE_POSX = 0,
- SVGA3D_CUBEFACE_NEGX = 1,
- SVGA3D_CUBEFACE_POSY = 2,
- SVGA3D_CUBEFACE_NEGY = 3,
- SVGA3D_CUBEFACE_POSZ = 4,
- SVGA3D_CUBEFACE_NEGZ = 5,
+ SVGA3D_CUBEFACE_POSX = 0,
+ SVGA3D_CUBEFACE_NEGX = 1,
+ SVGA3D_CUBEFACE_POSY = 2,
+ SVGA3D_CUBEFACE_NEGY = 3,
+ SVGA3D_CUBEFACE_POSZ = 4,
+ SVGA3D_CUBEFACE_NEGZ = 5,
} SVGA3dCubeFace;
typedef enum {
- SVGA3D_SHADERTYPE_INVALID = 0,
- SVGA3D_SHADERTYPE_MIN = 1,
- SVGA3D_SHADERTYPE_VS = 1,
- SVGA3D_SHADERTYPE_PS = 2,
- SVGA3D_SHADERTYPE_PREDX_MAX = 3,
- SVGA3D_SHADERTYPE_GS = 3,
- SVGA3D_SHADERTYPE_DX10_MAX = 4,
- SVGA3D_SHADERTYPE_HS = 4,
- SVGA3D_SHADERTYPE_DS = 5,
- SVGA3D_SHADERTYPE_CS = 6,
- SVGA3D_SHADERTYPE_MAX = 7
+ SVGA3D_SHADERTYPE_INVALID = 0,
+ SVGA3D_SHADERTYPE_MIN = 1,
+ SVGA3D_SHADERTYPE_VS = 1,
+ SVGA3D_SHADERTYPE_PS = 2,
+ SVGA3D_SHADERTYPE_PREDX_MAX = 3,
+ SVGA3D_SHADERTYPE_GS = 3,
+ SVGA3D_SHADERTYPE_DX10_MAX = 4,
+ SVGA3D_SHADERTYPE_HS = 4,
+ SVGA3D_SHADERTYPE_DS = 5,
+ SVGA3D_SHADERTYPE_CS = 6,
+ SVGA3D_SHADERTYPE_MAX = 7
} SVGA3dShaderType;
-#define SVGA3D_NUM_SHADERTYPE_PREDX \
- (SVGA3D_SHADERTYPE_PREDX_MAX - SVGA3D_SHADERTYPE_MIN)
+#define SVGA3D_NUM_SHADERTYPE_PREDX \
+ (SVGA3D_SHADERTYPE_PREDX_MAX - SVGA3D_SHADERTYPE_MIN)
-#define SVGA3D_NUM_SHADERTYPE_DX10 \
- (SVGA3D_SHADERTYPE_DX10_MAX - SVGA3D_SHADERTYPE_MIN)
+#define SVGA3D_NUM_SHADERTYPE_DX10 \
+ (SVGA3D_SHADERTYPE_DX10_MAX - SVGA3D_SHADERTYPE_MIN)
-#define SVGA3D_NUM_SHADERTYPE \
- (SVGA3D_SHADERTYPE_MAX - SVGA3D_SHADERTYPE_MIN)
+#define SVGA3D_NUM_SHADERTYPE (SVGA3D_SHADERTYPE_MAX - SVGA3D_SHADERTYPE_MIN)
typedef enum {
- SVGA3D_CONST_TYPE_MIN = 0,
- SVGA3D_CONST_TYPE_FLOAT = 0,
- SVGA3D_CONST_TYPE_INT = 1,
- SVGA3D_CONST_TYPE_BOOL = 2,
- SVGA3D_CONST_TYPE_MAX = 3,
+ SVGA3D_CONST_TYPE_MIN = 0,
+ SVGA3D_CONST_TYPE_FLOAT = 0,
+ SVGA3D_CONST_TYPE_INT = 1,
+ SVGA3D_CONST_TYPE_BOOL = 2,
+ SVGA3D_CONST_TYPE_MAX = 3,
} SVGA3dShaderConstType;
-/*
- * Register limits for shader consts.
- */
-#define SVGA3D_CONSTREG_MAX 256
-#define SVGA3D_CONSTINTREG_MAX 16
-#define SVGA3D_CONSTBOOLREG_MAX 16
+#define SVGA3D_CONSTREG_MAX 256
+#define SVGA3D_CONSTINTREG_MAX 16
+#define SVGA3D_CONSTBOOLREG_MAX 16
typedef enum {
- SVGA3D_STRETCH_BLT_POINT = 0,
- SVGA3D_STRETCH_BLT_LINEAR = 1,
- SVGA3D_STRETCH_BLT_MAX
+ SVGA3D_STRETCH_BLT_POINT = 0,
+ SVGA3D_STRETCH_BLT_LINEAR = 1,
+ SVGA3D_STRETCH_BLT_MAX
} SVGA3dStretchBltMode;
typedef enum {
- SVGA3D_QUERYTYPE_INVALID = ((uint8)-1),
- SVGA3D_QUERYTYPE_MIN = 0,
- SVGA3D_QUERYTYPE_OCCLUSION = 0,
- SVGA3D_QUERYTYPE_TIMESTAMP = 1,
- SVGA3D_QUERYTYPE_TIMESTAMPDISJOINT = 2,
- SVGA3D_QUERYTYPE_PIPELINESTATS = 3,
- SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE = 4,
- SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS = 5,
- SVGA3D_QUERYTYPE_STREAMOVERFLOWPREDICATE = 6,
- SVGA3D_QUERYTYPE_OCCLUSION64 = 7,
- SVGA3D_QUERYTYPE_DX10_MAX = 8,
- SVGA3D_QUERYTYPE_SOSTATS_STREAM0 = 8,
- SVGA3D_QUERYTYPE_SOSTATS_STREAM1 = 9,
- SVGA3D_QUERYTYPE_SOSTATS_STREAM2 = 10,
- SVGA3D_QUERYTYPE_SOSTATS_STREAM3 = 11,
- SVGA3D_QUERYTYPE_SOP_STREAM0 = 12,
- SVGA3D_QUERYTYPE_SOP_STREAM1 = 13,
- SVGA3D_QUERYTYPE_SOP_STREAM2 = 14,
- SVGA3D_QUERYTYPE_SOP_STREAM3 = 15,
- SVGA3D_QUERYTYPE_MAX
+ SVGA3D_QUERYTYPE_INVALID = ((uint8)-1),
+ SVGA3D_QUERYTYPE_MIN = 0,
+ SVGA3D_QUERYTYPE_OCCLUSION = 0,
+ SVGA3D_QUERYTYPE_TIMESTAMP = 1,
+ SVGA3D_QUERYTYPE_TIMESTAMPDISJOINT = 2,
+ SVGA3D_QUERYTYPE_PIPELINESTATS = 3,
+ SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE = 4,
+ SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS = 5,
+ SVGA3D_QUERYTYPE_STREAMOVERFLOWPREDICATE = 6,
+ SVGA3D_QUERYTYPE_OCCLUSION64 = 7,
+ SVGA3D_QUERYTYPE_DX10_MAX = 8,
+ SVGA3D_QUERYTYPE_SOSTATS_STREAM0 = 8,
+ SVGA3D_QUERYTYPE_SOSTATS_STREAM1 = 9,
+ SVGA3D_QUERYTYPE_SOSTATS_STREAM2 = 10,
+ SVGA3D_QUERYTYPE_SOSTATS_STREAM3 = 11,
+ SVGA3D_QUERYTYPE_SOP_STREAM0 = 12,
+ SVGA3D_QUERYTYPE_SOP_STREAM1 = 13,
+ SVGA3D_QUERYTYPE_SOP_STREAM2 = 14,
+ SVGA3D_QUERYTYPE_SOP_STREAM3 = 15,
+ SVGA3D_QUERYTYPE_MAX
} SVGA3dQueryType;
typedef uint8 SVGA3dQueryTypeUint8;
-#define SVGA3D_NUM_QUERYTYPE (SVGA3D_QUERYTYPE_MAX - SVGA3D_QUERYTYPE_MIN)
+#define SVGA3D_NUM_QUERYTYPE (SVGA3D_QUERYTYPE_MAX - SVGA3D_QUERYTYPE_MIN)
-/*
- * This is the maximum number of queries per context that can be active
- * simultaneously between a beginQuery and endQuery.
- */
#define SVGA3D_MAX_QUERY 64
-/*
- * Query result buffer formats
- */
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 samplesRendered;
-}
-#include "vmware_pack_end.h"
-SVGADXOcclusionQueryResult;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 passed;
-}
-#include "vmware_pack_end.h"
-SVGADXEventQueryResult;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint64 timestamp;
-}
-#include "vmware_pack_end.h"
-SVGADXTimestampQueryResult;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint64 realFrequency;
- uint32 disjoint;
-}
-#include "vmware_pack_end.h"
-SVGADXTimestampDisjointQueryResult;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint64 inputAssemblyVertices;
- uint64 inputAssemblyPrimitives;
- uint64 vertexShaderInvocations;
- uint64 geometryShaderInvocations;
- uint64 geometryShaderPrimitives;
- uint64 clipperInvocations;
- uint64 clipperPrimitives;
- uint64 pixelShaderInvocations;
- uint64 hullShaderInvocations;
- uint64 domainShaderInvocations;
- uint64 computeShaderInvocations;
-}
-#include "vmware_pack_end.h"
-SVGADXPipelineStatisticsQueryResult;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 anySamplesRendered;
-}
-#include "vmware_pack_end.h"
-SVGADXOcclusionPredicateQueryResult;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint64 numPrimitivesWritten;
- uint64 numPrimitivesRequired;
-}
-#include "vmware_pack_end.h"
-SVGADXStreamOutStatisticsQueryResult;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 overflowed;
-}
-#include "vmware_pack_end.h"
-SVGADXStreamOutPredicateQueryResult;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint64 samplesRendered;
-}
-#include "vmware_pack_end.h"
-SVGADXOcclusion64QueryResult;
-
-/*
- * SVGADXQueryResultUnion is not intended for use in the protocol, but is
- * very helpful when working with queries generically.
- */
-typedef
-#include "vmware_pack_begin.h"
-union SVGADXQueryResultUnion {
- SVGADXOcclusionQueryResult occ;
- SVGADXEventQueryResult event;
- SVGADXTimestampQueryResult ts;
- SVGADXTimestampDisjointQueryResult tsDisjoint;
- SVGADXPipelineStatisticsQueryResult pipelineStats;
- SVGADXOcclusionPredicateQueryResult occPred;
- SVGADXStreamOutStatisticsQueryResult soStats;
- SVGADXStreamOutPredicateQueryResult soPred;
- SVGADXOcclusion64QueryResult occ64;
-}
-#include "vmware_pack_end.h"
-SVGADXQueryResultUnion;
+#pragma pack(push, 1)
+typedef struct {
+ uint32 samplesRendered;
+} SVGADXOcclusionQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 passed;
+} SVGADXEventQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint64 timestamp;
+} SVGADXTimestampQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint64 realFrequency;
+ uint32 disjoint;
+} SVGADXTimestampDisjointQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint64 inputAssemblyVertices;
+ uint64 inputAssemblyPrimitives;
+ uint64 vertexShaderInvocations;
+ uint64 geometryShaderInvocations;
+ uint64 geometryShaderPrimitives;
+ uint64 clipperInvocations;
+ uint64 clipperPrimitives;
+ uint64 pixelShaderInvocations;
+ uint64 hullShaderInvocations;
+ uint64 domainShaderInvocations;
+ uint64 computeShaderInvocations;
+} SVGADXPipelineStatisticsQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 anySamplesRendered;
+} SVGADXOcclusionPredicateQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint64 numPrimitivesWritten;
+ uint64 numPrimitivesRequired;
+} SVGADXStreamOutStatisticsQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 overflowed;
+} SVGADXStreamOutPredicateQueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint64 samplesRendered;
+} SVGADXOcclusion64QueryResult;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef union SVGADXQueryResultUnion {
+ SVGADXOcclusionQueryResult occ;
+ SVGADXEventQueryResult event;
+ SVGADXTimestampQueryResult ts;
+ SVGADXTimestampDisjointQueryResult tsDisjoint;
+ SVGADXPipelineStatisticsQueryResult pipelineStats;
+ SVGADXOcclusionPredicateQueryResult occPred;
+ SVGADXStreamOutStatisticsQueryResult soStats;
+ SVGADXStreamOutPredicateQueryResult soPred;
+ SVGADXOcclusion64QueryResult occ64;
+} SVGADXQueryResultUnion;
+#pragma pack(pop)
typedef enum {
- SVGA3D_QUERYSTATE_PENDING = 0, /* Query is not finished yet */
- SVGA3D_QUERYSTATE_SUCCEEDED = 1, /* Completed successfully */
- SVGA3D_QUERYSTATE_FAILED = 2, /* Completed unsuccessfully */
- SVGA3D_QUERYSTATE_NEW = 3, /* Never submitted (guest only) */
+ SVGA3D_QUERYSTATE_PENDING = 0,
+ SVGA3D_QUERYSTATE_SUCCEEDED = 1,
+ SVGA3D_QUERYSTATE_FAILED = 2,
+ SVGA3D_QUERYSTATE_NEW = 3,
} SVGA3dQueryState;
typedef enum {
- SVGA3D_WRITE_HOST_VRAM = 1,
- SVGA3D_READ_HOST_VRAM = 2,
+ SVGA3D_WRITE_HOST_VRAM = 1,
+ SVGA3D_READ_HOST_VRAM = 2,
} SVGA3dTransferType;
-#define SVGA3D_LOGICOP_INVALID 0
-#define SVGA3D_LOGICOP_MIN 1
-#define SVGA3D_LOGICOP_COPY 1
-#define SVGA3D_LOGICOP_NOT 2
-#define SVGA3D_LOGICOP_AND 3
-#define SVGA3D_LOGICOP_OR 4
-#define SVGA3D_LOGICOP_XOR 5
-#define SVGA3D_LOGICOP_NXOR 6
-#define SVGA3D_LOGICOP_ROP3 7
-#define SVGA3D_LOGICOP_MAX 8
+#define SVGA3D_LOGICOP_INVALID 0
+#define SVGA3D_LOGICOP_COPY 1
+
+#define SVGA3D_LOGICOP_MIN 1
+#define SVGA3D_LOGICOP_NOT 2
+#define SVGA3D_LOGICOP_AND 3
+#define SVGA3D_LOGICOP_OR 4
+#define SVGA3D_LOGICOP_XOR 5
+#define SVGA3D_LOGICOP_NXOR 6
+#define SVGA3D_LOGICOP_ROP3 7
+
+#define SVGA3D_LOGICOP_MAX 8
typedef uint16 SVGA3dLogicOp;
-#define SVGA3D_LOGICOP_ROP3_INVALID ((uint16) -1)
-#define SVGA3D_LOGICOP_ROP3_MIN 0
-#define SVGA3D_LOGICOP_ROP3_MAX 256
+#define SVGA3D_LOGICOP_ROP3_INVALID ((uint16)-1)
+#define SVGA3D_LOGICOP_ROP3_MIN 0
+#define SVGA3D_LOGICOP_ROP3_MAX 256
typedef uint16 SVGA3dLogicOpRop3;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- union {
- struct {
- uint16 function; // SVGA3dFogFunction
- uint8 type; // SVGA3dFogType
- uint8 base; // SVGA3dFogBase
- };
- uint32 uintValue;
- };
-}
-#include "vmware_pack_end.h"
-SVGA3dFogMode;
-
-/*
- * Uniquely identify one image (a 1D/2D/3D array) from a surface. This
- * is a surface ID as well as face/mipmap indices.
- */
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dSurfaceImageId {
- uint32 sid;
- uint32 face;
- uint32 mipmap;
-}
-#include "vmware_pack_end.h"
-SVGA3dSurfaceImageId;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGA3dSubSurfaceId {
- uint32 sid;
- uint32 subResourceId;
-}
-#include "vmware_pack_end.h"
-SVGA3dSubSurfaceId;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 width;
- uint32 height;
- uint32 depth;
-}
-#include "vmware_pack_end.h"
-SVGA3dSize;
+#pragma pack(push, 1)
+typedef struct {
+ union {
+ struct {
+ uint16 function;
+ uint8 type;
+ uint8 base;
+ };
+ uint32 uintValue;
+ };
+} SVGA3dFogMode;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dSurfaceImageId {
+ uint32 sid;
+ uint32 face;
+ uint32 mipmap;
+} SVGA3dSurfaceImageId;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGA3dSubSurfaceId {
+ uint32 sid;
+ uint32 subResourceId;
+} SVGA3dSubSurfaceId;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 width;
+ uint32 height;
+ uint32 depth;
+} SVGA3dSize;
+#pragma pack(pop)
-/*
- * Guest-backed objects definitions.
- */
typedef enum {
- SVGA_OTABLE_MOB = 0,
- SVGA_OTABLE_MIN = 0,
- SVGA_OTABLE_SURFACE = 1,
- SVGA_OTABLE_CONTEXT = 2,
- SVGA_OTABLE_SHADER = 3,
- SVGA_OTABLE_SCREENTARGET = 4,
-
- SVGA_OTABLE_DX9_MAX = 5,
-
- SVGA_OTABLE_DXCONTEXT = 5,
- SVGA_OTABLE_DX_MAX = 6,
-
- SVGA_OTABLE_RESERVED1 = 6,
- SVGA_OTABLE_RESERVED2 = 7,
-
- /*
- * Additions to this table need to be tied to HW-version features and
- * checkpointed accordingly.
- */
- SVGA_OTABLE_DEVEL_MAX = 8,
- SVGA_OTABLE_MAX = 8
+ SVGA_OTABLE_MOB = 0,
+ SVGA_OTABLE_MIN = 0,
+ SVGA_OTABLE_SURFACE = 1,
+ SVGA_OTABLE_CONTEXT = 2,
+ SVGA_OTABLE_SHADER = 3,
+ SVGA_OTABLE_SCREENTARGET = 4,
+
+ SVGA_OTABLE_DX9_MAX = 5,
+
+ SVGA_OTABLE_DXCONTEXT = 5,
+ SVGA_OTABLE_DX_MAX = 6,
+
+ SVGA_OTABLE_DEVEL_MAX = 6,
+ SVGA_OTABLE_MAX = 6,
+
+ SVGA_OTABLE_RESERVED1 = 6,
+ SVGA_OTABLE_RESERVED2 = 7,
+ SVGA_OTABLE_BUG_1952836_MAX = 8,
} SVGAOTableType;
typedef enum {
- SVGA_COTABLE_MIN = 0,
- SVGA_COTABLE_RTVIEW = 0,
- SVGA_COTABLE_DSVIEW = 1,
- SVGA_COTABLE_SRVIEW = 2,
- SVGA_COTABLE_ELEMENTLAYOUT = 3,
- SVGA_COTABLE_BLENDSTATE = 4,
- SVGA_COTABLE_DEPTHSTENCIL = 5,
- SVGA_COTABLE_RASTERIZERSTATE = 6,
- SVGA_COTABLE_SAMPLER = 7,
- SVGA_COTABLE_STREAMOUTPUT = 8,
- SVGA_COTABLE_DXQUERY = 9,
- SVGA_COTABLE_DXSHADER = 10,
- SVGA_COTABLE_DX10_MAX = 11,
- SVGA_COTABLE_UAVIEW = 11,
- SVGA_COTABLE_MAX = 12,
+ SVGA_COTABLE_MIN = 0,
+ SVGA_COTABLE_RTVIEW = 0,
+ SVGA_COTABLE_DSVIEW = 1,
+ SVGA_COTABLE_SRVIEW = 2,
+ SVGA_COTABLE_ELEMENTLAYOUT = 3,
+ SVGA_COTABLE_BLENDSTATE = 4,
+ SVGA_COTABLE_DEPTHSTENCIL = 5,
+ SVGA_COTABLE_RASTERIZERSTATE = 6,
+ SVGA_COTABLE_SAMPLER = 7,
+ SVGA_COTABLE_STREAMOUTPUT = 8,
+ SVGA_COTABLE_DXQUERY = 9,
+ SVGA_COTABLE_DXSHADER = 10,
+ SVGA_COTABLE_DX10_MAX = 11,
+ SVGA_COTABLE_UAVIEW = 11,
+ SVGA_COTABLE_MAX = 12,
} SVGACOTableType;
-/*
- * The largest size (number of entries) allowed in a COTable.
- */
#define SVGA_COTABLE_MAX_IDS (MAX_UINT16 - 2)
typedef enum SVGAMobFormat {
- SVGA3D_MOBFMT_INVALID = SVGA3D_INVALID_ID,
- SVGA3D_MOBFMT_PTDEPTH_0 = 0,
- SVGA3D_MOBFMT_MIN = 0,
- SVGA3D_MOBFMT_PTDEPTH_1 = 1,
- SVGA3D_MOBFMT_PTDEPTH_2 = 2,
- SVGA3D_MOBFMT_RANGE = 3,
- SVGA3D_MOBFMT_PTDEPTH64_0 = 4,
- SVGA3D_MOBFMT_PTDEPTH64_1 = 5,
- SVGA3D_MOBFMT_PTDEPTH64_2 = 6,
- SVGA3D_MOBFMT_PREDX_MAX = 7,
- SVGA3D_MOBFMT_EMPTY = 7,
- SVGA3D_MOBFMT_MAX,
-
- /*
- * This isn't actually used by the guest, but is a mob-format used
- * internally by the SVGA device (and is therefore not binary compatible).
- */
- SVGA3D_MOBFMT_HB,
+ SVGA3D_MOBFMT_INVALID = SVGA3D_INVALID_ID,
+ SVGA3D_MOBFMT_PT_0 = 0,
+ SVGA3D_MOBFMT_MIN = 0,
+ SVGA3D_MOBFMT_PT_1 = 1,
+ SVGA3D_MOBFMT_PT_2 = 2,
+ SVGA3D_MOBFMT_RANGE = 3,
+ SVGA3D_MOBFMT_PT64_0 = 4,
+ SVGA3D_MOBFMT_PT64_1 = 5,
+ SVGA3D_MOBFMT_PT64_2 = 6,
+ SVGA3D_MOBFMT_PREDX_MAX = 7,
+ SVGA3D_MOBFMT_EMPTY = 7,
+
+ SVGA3D_MOBFMT_MAX,
+
+ SVGA3D_MOBFMT_HB,
} SVGAMobFormat;
#define SVGA3D_MOB_EMPTY_BASE 1
-/*
- * Multisample pattern types.
- */
-
typedef enum SVGA3dMSPattern {
- SVGA3D_MS_PATTERN_NONE = 0,
- SVGA3D_MS_PATTERN_MIN = 0,
- SVGA3D_MS_PATTERN_STANDARD = 1,
- SVGA3D_MS_PATTERN_CENTER = 2,
- SVGA3D_MS_PATTERN_MAX = 3,
+ SVGA3D_MS_PATTERN_NONE = 0,
+ SVGA3D_MS_PATTERN_MIN = 0,
+ SVGA3D_MS_PATTERN_STANDARD = 1,
+ SVGA3D_MS_PATTERN_CENTER = 2,
+ SVGA3D_MS_PATTERN_MAX = 3,
} SVGA3dMSPattern;
-/*
- * Precision settings for each sample.
- */
-
typedef enum SVGA3dMSQualityLevel {
- SVGA3D_MS_QUALITY_NONE = 0,
- SVGA3D_MS_QUALITY_MIN = 0,
- SVGA3D_MS_QUALITY_FULL = 1,
- SVGA3D_MS_QUALITY_MAX = 2,
+ SVGA3D_MS_QUALITY_NONE = 0,
+ SVGA3D_MS_QUALITY_MIN = 0,
+ SVGA3D_MS_QUALITY_FULL = 1,
+ SVGA3D_MS_QUALITY_RESOLVED = 2,
+ SVGA3D_MS_QUALITY_MAX = 3,
} SVGA3dMSQualityLevel;
-/*
- * Screen Target Update Flags
- */
-
typedef enum SVGA3dFrameUpdateType {
- SVGA3D_FRAME_END = 0,
- SVGA3D_FRAME_PARTIAL = 1,
- SVGA3D_FRAME_UNKNOWN = 2,
- SVGA3D_FRAME_MAX = 3,
+ SVGA3D_FRAME_END = 0,
+ SVGA3D_FRAME_MIN = 0,
+ SVGA3D_FRAME_PARTIAL = 1,
+ SVGA3D_FRAME_UNKNOWN = 2,
+ SVGA3D_FRAME_MAX = 3,
} SVGA3dFrameUpdateType;
-#endif /* _SVGA3D_TYPES_H_ */
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga_escape.h b/drivers/gpu/drm/vmwgfx/device_include/svga_escape.h
index acb41e28e46f..bf242c21f352 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga_escape.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga_escape.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
- * Copyright 2007-2015 VMware, Inc.
+ * Copyright 2007,2020 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -30,61 +30,27 @@
* Definitions for our own (vendor-specific) SVGA Escape commands.
*/
-#ifndef _SVGA_ESCAPE_H_
-#define _SVGA_ESCAPE_H_
-/*
- * Namespace IDs for the escape command
- */
+#ifndef _SVGA_ESCAPE_H_
+#define _SVGA_ESCAPE_H_
#define SVGA_ESCAPE_NSID_VMWARE 0x00000000
-#define SVGA_ESCAPE_NSID_DEVEL 0xFFFFFFFF
-
+#define SVGA_ESCAPE_NSID_DEVEL 0xFFFFFFFF
-/*
- * Within SVGA_ESCAPE_NSID_VMWARE, we multiplex commands according to
- * the first DWORD of escape data (after the nsID and size). As a
- * guideline we're using the high word and low word as a major and
- * minor command number, respectively.
- *
- * Major command number allocation:
- *
- * 0000: Reserved
- * 0001: SVGA_ESCAPE_VMWARE_LOG (svga_binary_logger.h)
- * 0002: SVGA_ESCAPE_VMWARE_VIDEO (svga_overlay.h)
- * 0003: SVGA_ESCAPE_VMWARE_HINT (svga_escape.h)
- */
-
-#define SVGA_ESCAPE_VMWARE_MAJOR_MASK 0xFFFF0000
-
-
-/*
- * SVGA Hint commands.
- *
- * These escapes let the SVGA driver provide optional information to
- * he host about the state of the guest or guest applications. The
- * host can use these hints to make user interface or performance
- * decisions.
- *
- * Notes:
- *
- * - SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN is deprecated for guests
- * that use the SVGA Screen Object extension. Instead of sending
- * this escape, use the SVGA_SCREEN_FULLSCREEN_HINT flag on your
- * Screen Object.
- */
+#define SVGA_ESCAPE_VMWARE_MAJOR_MASK 0xFFFF0000
-#define SVGA_ESCAPE_VMWARE_HINT 0x00030000
-#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN 0x00030001 /* Deprecated */
+#define SVGA_ESCAPE_VMWARE_HINT 0x00030000
+#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN 0x00030001
-typedef
-struct {
- uint32 command;
- uint32 fullscreen;
- struct {
- int32 x, y;
- } monitorPosition;
+#pragma pack(push, 1)
+typedef struct {
+ uint32 command;
+ uint32 fullscreen;
+ struct {
+ int32 x, y;
+ } monitorPosition;
} SVGAEscapeHintFullscreen;
+#pragma pack(pop)
-#endif /* _SVGA_ESCAPE_H_ */
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga_overlay.h b/drivers/gpu/drm/vmwgfx/device_include/svga_overlay.h
index e5385146e7fc..aec17c3c6c29 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga_overlay.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga_overlay.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
- * Copyright 2007-2015 VMware, Inc.
+ * Copyright 2007-2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -30,171 +30,88 @@
* Definitions for video-overlay support.
*/
+
+
#ifndef _SVGA_OVERLAY_H_
#define _SVGA_OVERLAY_H_
#include "svga_reg.h"
-/*
- * Video formats we support
- */
+#if defined __cplusplus
+extern "C" {
+#endif
-#define VMWARE_FOURCC_YV12 0x32315659 /* 'Y' 'V' '1' '2' */
-#define VMWARE_FOURCC_YUY2 0x32595559 /* 'Y' 'U' 'Y' '2' */
-#define VMWARE_FOURCC_UYVY 0x59565955 /* 'U' 'Y' 'V' 'Y' */
+#define VMWARE_FOURCC_YV12 0x32315659
+#define VMWARE_FOURCC_YUY2 0x32595559
+#define VMWARE_FOURCC_UYVY 0x59565955
typedef enum {
- SVGA_OVERLAY_FORMAT_INVALID = 0,
- SVGA_OVERLAY_FORMAT_YV12 = VMWARE_FOURCC_YV12,
- SVGA_OVERLAY_FORMAT_YUY2 = VMWARE_FOURCC_YUY2,
- SVGA_OVERLAY_FORMAT_UYVY = VMWARE_FOURCC_UYVY,
+ SVGA_OVERLAY_FORMAT_INVALID = 0,
+ SVGA_OVERLAY_FORMAT_YV12 = VMWARE_FOURCC_YV12,
+ SVGA_OVERLAY_FORMAT_YUY2 = VMWARE_FOURCC_YUY2,
+ SVGA_OVERLAY_FORMAT_UYVY = VMWARE_FOURCC_UYVY,
} SVGAOverlayFormat;
-#define SVGA_VIDEO_COLORKEY_MASK 0x00ffffff
+#define SVGA_VIDEO_COLORKEY_MASK 0x00ffffff
-#define SVGA_ESCAPE_VMWARE_VIDEO 0x00020000
+#define SVGA_ESCAPE_VMWARE_VIDEO 0x00020000
-#define SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS 0x00020001
- /* FIFO escape layout:
- * Type, Stream Id, (Register Id, Value) pairs */
+#define SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS 0x00020001
-#define SVGA_ESCAPE_VMWARE_VIDEO_FLUSH 0x00020002
- /* FIFO escape layout:
- * Type, Stream Id */
+#define SVGA_ESCAPE_VMWARE_VIDEO_FLUSH 0x00020002
-typedef
-struct SVGAEscapeVideoSetRegs {
- struct {
- uint32 cmdType;
- uint32 streamId;
- } header;
+typedef struct SVGAEscapeVideoSetRegs {
+ struct {
+ uint32 cmdType;
+ uint32 streamId;
+ } header;
- /* May include zero or more items. */
- struct {
- uint32 registerId;
- uint32 value;
- } items[1];
+ struct {
+ uint32 registerId;
+ uint32 value;
+ } items[1];
} SVGAEscapeVideoSetRegs;
-typedef
-struct SVGAEscapeVideoFlush {
- uint32 cmdType;
- uint32 streamId;
+typedef struct SVGAEscapeVideoFlush {
+ uint32 cmdType;
+ uint32 streamId;
} SVGAEscapeVideoFlush;
-
-/*
- * Struct definitions for the video overlay commands built on
- * SVGAFifoCmdEscape.
- */
-typedef
-struct {
- uint32 command;
- uint32 overlay;
+#pragma pack(push, 1)
+typedef struct {
+ uint32 command;
+ uint32 overlay;
} SVGAFifoEscapeCmdVideoBase;
+#pragma pack(pop)
-typedef
-struct {
- SVGAFifoEscapeCmdVideoBase videoCmd;
+#pragma pack(push, 1)
+typedef struct {
+ SVGAFifoEscapeCmdVideoBase videoCmd;
} SVGAFifoEscapeCmdVideoFlush;
-
-typedef
-struct {
- SVGAFifoEscapeCmdVideoBase videoCmd;
- struct {
- uint32 regId;
- uint32 value;
- } items[1];
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAFifoEscapeCmdVideoBase videoCmd;
+ struct {
+ uint32 regId;
+ uint32 value;
+ } items[1];
} SVGAFifoEscapeCmdVideoSetRegs;
-
-typedef
-struct {
- SVGAFifoEscapeCmdVideoBase videoCmd;
- struct {
- uint32 regId;
- uint32 value;
- } items[SVGA_VIDEO_NUM_REGS];
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAFifoEscapeCmdVideoBase videoCmd;
+ struct {
+ uint32 regId;
+ uint32 value;
+ } items[SVGA_VIDEO_NUM_REGS];
} SVGAFifoEscapeCmdVideoSetAllRegs;
+#pragma pack(pop)
-
-/*
- *----------------------------------------------------------------------
- *
- * VMwareVideoGetAttributes --
- *
- * Computes the size, pitches and offsets for YUV frames.
- *
- * Results:
- * TRUE on success; otherwise FALSE on failure.
- *
- * Side effects:
- * Pitches and offsets for the given YUV frame are put in 'pitches'
- * and 'offsets' respectively. They are both optional though.
- *
- *----------------------------------------------------------------------
- */
-
-static inline bool
-VMwareVideoGetAttributes(const SVGAOverlayFormat format, /* IN */
- uint32 *width, /* IN / OUT */
- uint32 *height, /* IN / OUT */
- uint32 *size, /* OUT */
- uint32 *pitches, /* OUT (optional) */
- uint32 *offsets) /* OUT (optional) */
-{
- int tmp;
-
- *width = (*width + 1) & ~1;
-
- if (offsets) {
- offsets[0] = 0;
- }
-
- switch (format) {
- case VMWARE_FOURCC_YV12:
- *height = (*height + 1) & ~1;
- *size = (*width) * (*height);
-
- if (pitches) {
- pitches[0] = *width;
- }
-
- if (offsets) {
- offsets[1] = *size;
- }
-
- tmp = *width >> 1;
-
- if (pitches) {
- pitches[1] = pitches[2] = tmp;
- }
-
- tmp *= (*height >> 1);
- *size += tmp;
-
- if (offsets) {
- offsets[2] = *size;
- }
-
- *size += tmp;
- break;
-
- case VMWARE_FOURCC_YUY2:
- case VMWARE_FOURCC_UYVY:
- *size = *width * 2;
-
- if (pitches) {
- pitches[0] = *size;
- }
-
- *size *= *height;
- break;
-
- default:
- return false;
- }
-
- return true;
+#if defined __cplusplus
}
+#endif
-#endif /* _SVGA_OVERLAY_H_ */
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga_reg.h b/drivers/gpu/drm/vmwgfx/device_include/svga_reg.h
index 193a57f6aae5..b3602557de2e 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/svga_reg.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga_reg.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**********************************************************
* Copyright 1998-2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -30,2277 +30,870 @@
* Virtual hardware definitions for the VMware SVGA II device.
*/
-#ifndef _SVGA_REG_H_
-#define _SVGA_REG_H_
-#include <linux/pci_ids.h>
-#define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_USERLEVEL
-#define INCLUDE_ALLOW_VMCORE
-#include "includeCheck.h"
+#ifndef _SVGA_REG_H_
+#define _SVGA_REG_H_
-#include "svga_types.h"
+#include "vm_basic_types.h"
-/*
- * SVGA_REG_ENABLE bit definitions.
- */
typedef enum {
- SVGA_REG_ENABLE_DISABLE = 0,
- SVGA_REG_ENABLE_ENABLE = (1 << 0),
- SVGA_REG_ENABLE_HIDE = (1 << 1),
+ SVGA_REG_ENABLE_DISABLE = 0,
+ SVGA_REG_ENABLE_ENABLE = (1 << 0),
+ SVGA_REG_ENABLE_HIDE = (1 << 1),
} SvgaRegEnable;
typedef uint32 SVGAMobId;
-/*
- * Arbitrary and meaningless limits. Please ignore these when writing
- * new drivers.
- */
-#define SVGA_MAX_WIDTH 2560
-#define SVGA_MAX_HEIGHT 1600
-
+#define SVGA_MAX_WIDTH 2560
+#define SVGA_MAX_HEIGHT 1600
-#define SVGA_MAX_BITS_PER_PIXEL 32
-#define SVGA_MAX_DEPTH 24
-#define SVGA_MAX_DISPLAYS 10
-#define SVGA_MAX_SCREEN_SIZE 8192
+#define SVGA_MAX_BITS_PER_PIXEL 32
+#define SVGA_MAX_DEPTH 24
+#define SVGA_MAX_DISPLAYS 10
+#define SVGA_MAX_SCREEN_SIZE 8192
#define SVGA_SCREEN_ROOT_LIMIT (SVGA_MAX_SCREEN_SIZE * SVGA_MAX_DISPLAYS)
+#define SVGA_CURSOR_ON_HIDE 0x0
+#define SVGA_CURSOR_ON_SHOW 0x1
-/*
- * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned
- * cursor bypass mode.
- */
-#define SVGA_CURSOR_ON_HIDE 0x0
-#define SVGA_CURSOR_ON_SHOW 0x1
-
-/*
- * Remove the cursor from the framebuffer
- * because we need to see what's under it
- */
-#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2
+#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2
-/* Put the cursor back in the framebuffer so the user can see it */
-#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3
+#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3
-/*
- * The maximum framebuffer size that can traced for guests unless the
- * SVGA_CAP_GBOBJECTS is set in SVGA_REG_CAPABILITIES. In that case
- * the full framebuffer can be traced independent of this limit.
- */
-#define SVGA_FB_MAX_TRACEABLE_SIZE 0x1000000
+#define SVGA_FB_MAX_TRACEABLE_SIZE 0x1000000
-#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8
-#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)
-#define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS)
+#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8
+#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)
+#define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS)
-#define SVGA_MAGIC 0x900000UL
-#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver))
+#define SVGA_MAGIC 0x900000UL
+#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver))
-/* Version 3 has the control bar instead of the FIFO */
-#define SVGA_VERSION_3 3
-#define SVGA_ID_3 SVGA_MAKE_ID(SVGA_VERSION_3)
+#define SVGA_VERSION_3 3
+#define SVGA_ID_3 SVGA_MAKE_ID(SVGA_VERSION_3)
-/* Version 2 let the address of the frame buffer be unsigned on Win32 */
-#define SVGA_VERSION_2 2
-#define SVGA_ID_2 SVGA_MAKE_ID(SVGA_VERSION_2)
+#define SVGA_VERSION_2 2
+#define SVGA_ID_2 SVGA_MAKE_ID(SVGA_VERSION_2)
-/* Version 1 has new registers starting with SVGA_REG_CAPABILITIES so
- PALETTE_BASE has moved */
-#define SVGA_VERSION_1 1
-#define SVGA_ID_1 SVGA_MAKE_ID(SVGA_VERSION_1)
+#define SVGA_VERSION_1 1
+#define SVGA_ID_1 SVGA_MAKE_ID(SVGA_VERSION_1)
-/* Version 0 is the initial version */
-#define SVGA_VERSION_0 0
-#define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0)
+#define SVGA_VERSION_0 0
+#define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0)
-/*
- * "Invalid" value for all SVGA IDs.
- * (Version ID, screen object ID, surface ID...)
- */
-#define SVGA_ID_INVALID 0xFFFFFFFF
+#define SVGA_ID_INVALID 0xFFFFFFFF
-/* Port offsets, relative to BAR0 */
-#define SVGA_INDEX_PORT 0x0
-#define SVGA_VALUE_PORT 0x1
-#define SVGA_BIOS_PORT 0x2
-#define SVGA_IRQSTATUS_PORT 0x8
+#define SVGA_INDEX_PORT 0x0
+#define SVGA_VALUE_PORT 0x1
+#define SVGA_BIOS_PORT 0x2
+#define SVGA_IRQSTATUS_PORT 0x8
-/*
- * Interrupt source flags for IRQSTATUS_PORT and IRQMASK.
- *
- * Interrupts are only supported when the
- * SVGA_CAP_IRQMASK capability is present.
- */
-#define SVGA_IRQFLAG_ANY_FENCE (1 << 0) /* Any fence was passed */
-#define SVGA_IRQFLAG_FIFO_PROGRESS (1 << 1) /* Made forward progress in the FIFO */
-#define SVGA_IRQFLAG_FENCE_GOAL (1 << 2) /* SVGA_FIFO_FENCE_GOAL reached */
-#define SVGA_IRQFLAG_COMMAND_BUFFER (1 << 3) /* Command buffer completed */
-#define SVGA_IRQFLAG_ERROR (1 << 4) /* Error while processing commands */
-#define SVGA_IRQFLAG_MAX (1 << 5)
+#define SVGA_IRQFLAG_ANY_FENCE (1 << 0)
+#define SVGA_IRQFLAG_FIFO_PROGRESS (1 << 1)
+#define SVGA_IRQFLAG_FENCE_GOAL (1 << 2)
+#define SVGA_IRQFLAG_COMMAND_BUFFER (1 << 3)
+#define SVGA_IRQFLAG_ERROR (1 << 4)
+#define SVGA_IRQFLAG_REG_FENCE_GOAL (1 << 5)
+#define SVGA_IRQFLAG_MAX (1 << 6)
-/*
- * The byte-size is the size of the actual cursor data,
- * possibly after expanding it to the current bit depth.
- *
- * 40K is sufficient memory for two 32-bit planes for a 64 x 64 cursor.
- *
- * The dimension limit is a bound on the maximum width or height.
- */
-#define SVGA_MAX_CURSOR_CMD_BYTES (40 * 1024)
+#define SVGA_MAX_CURSOR_CMD_BYTES (40 * 1024)
#define SVGA_MAX_CURSOR_CMD_DIMENSION 1024
-/*
- * Registers
- */
-
enum {
- SVGA_REG_ID = 0,
- SVGA_REG_ENABLE = 1,
- SVGA_REG_WIDTH = 2,
- SVGA_REG_HEIGHT = 3,
- SVGA_REG_MAX_WIDTH = 4,
- SVGA_REG_MAX_HEIGHT = 5,
- SVGA_REG_DEPTH = 6,
- SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */
- SVGA_REG_PSEUDOCOLOR = 8,
- SVGA_REG_RED_MASK = 9,
- SVGA_REG_GREEN_MASK = 10,
- SVGA_REG_BLUE_MASK = 11,
- SVGA_REG_BYTES_PER_LINE = 12,
- SVGA_REG_FB_START = 13, /* (Deprecated) */
- SVGA_REG_FB_OFFSET = 14,
- SVGA_REG_VRAM_SIZE = 15,
- SVGA_REG_FB_SIZE = 16,
-
- /* ID 0 implementation only had the above registers, then the palette */
- SVGA_REG_ID_0_TOP = 17,
-
- SVGA_REG_CAPABILITIES = 17,
- SVGA_REG_MEM_START = 18, /* (Deprecated) */
- SVGA_REG_MEM_SIZE = 19,
- SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */
- SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */
- SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */
- SVGA_REG_GUEST_ID = 23, /* (Deprecated) */
- SVGA_REG_DEAD = 24, /* Drivers should never write this. */
- SVGA_REG_CURSOR_X = 25, /* (Deprecated) */
- SVGA_REG_CURSOR_Y = 26, /* (Deprecated) */
- SVGA_REG_CURSOR_ON = 27, /* (Deprecated) */
- SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* (Deprecated) */
- SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */
- SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */
- SVGA_REG_NUM_DISPLAYS = 31, /* (Deprecated) */
- SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */
- SVGA_REG_IRQMASK = 33, /* Interrupt mask */
-
- /* Legacy multi-monitor support */
- SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */
- SVGA_REG_DISPLAY_ID = 35, /* Display ID for the following display attributes */
- SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */
- SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */
- SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */
- SVGA_REG_DISPLAY_WIDTH = 39, /* The display's width */
- SVGA_REG_DISPLAY_HEIGHT = 40, /* The display's height */
-
- /* See "Guest memory regions" below. */
- SVGA_REG_GMR_ID = 41,
- SVGA_REG_GMR_DESCRIPTOR = 42,
- SVGA_REG_GMR_MAX_IDS = 43,
- SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
-
- SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */
- SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */
- SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */
- SVGA_REG_COMMAND_LOW = 48, /* Lower 32 bits and submits commands */
- SVGA_REG_COMMAND_HIGH = 49, /* Upper 32 bits of command buffer PA */
-
- /*
- * Max primary memory.
- * See SVGA_CAP_NO_BB_RESTRICTION.
- */
- SVGA_REG_MAX_PRIMARY_MEM = 50,
- SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM = 50,
-
- /*
- * Legacy version of SVGA_REG_GBOBJECT_MEM_SIZE_KB for drivers that
- * don't know how to convert to a 64-bit byte value without overflowing.
- * (See SVGA_REG_GBOBJECT_MEM_SIZE_KB).
- */
- SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51,
-
- SVGA_REG_DEV_CAP = 52, /* Write dev cap index, read value */
- SVGA_REG_CMD_PREPEND_LOW = 53,
- SVGA_REG_CMD_PREPEND_HIGH = 54,
- SVGA_REG_SCREENTARGET_MAX_WIDTH = 55,
- SVGA_REG_SCREENTARGET_MAX_HEIGHT = 56,
- SVGA_REG_MOB_MAX_SIZE = 57,
- SVGA_REG_BLANK_SCREEN_TARGETS = 58,
- SVGA_REG_CAP2 = 59,
- SVGA_REG_DEVEL_CAP = 60,
-
- /*
- * Allow the guest to hint to the device which driver is running.
- *
- * This should not generally change device behavior, but might be
- * convenient to work-around specific bugs in guest drivers.
- *
- * Drivers should first write their id value into SVGA_REG_GUEST_DRIVER_ID,
- * and then fill out all of the version registers that they have defined.
- *
- * After the driver has written all of the registers, they should
- * then write the value SVGA_REG_GUEST_DRIVER_ID_SUBMIT to the
- * SVGA_REG_GUEST_DRIVER_ID register, to signal that they have finished.
- *
- * The SVGA_REG_GUEST_DRIVER_ID values are defined below by the
- * SVGARegGuestDriverId enum.
- *
- * The SVGA_REG_GUEST_DRIVER_VERSION fields are driver-specific,
- * but ideally should encode a monotonically increasing number that allows
- * the device to perform inequality checks against ranges of driver versions.
- */
- SVGA_REG_GUEST_DRIVER_ID = 61,
- SVGA_REG_GUEST_DRIVER_VERSION1 = 62,
- SVGA_REG_GUEST_DRIVER_VERSION2 = 63,
- SVGA_REG_GUEST_DRIVER_VERSION3 = 64,
- SVGA_REG_CURSOR_MOBID = 65,
- SVGA_REG_CURSOR_MAX_BYTE_SIZE = 66,
- SVGA_REG_CURSOR_MAX_DIMENSION = 67,
-
- SVGA_REG_FIFO_CAPS = 68,
- SVGA_REG_FENCE = 69,
-
- SVGA_REG_RESERVED1 = 70,
- SVGA_REG_RESERVED2 = 71,
- SVGA_REG_RESERVED3 = 72,
- SVGA_REG_RESERVED4 = 73,
- SVGA_REG_RESERVED5 = 74,
- SVGA_REG_SCREENDMA = 75,
-
- /*
- * The maximum amount of guest-backed objects that the device can have
- * resident at a time. Guest-drivers should keep their working set size
- * below this limit for best performance.
- *
- * Note that this value is in kilobytes, and not bytes, because the actual
- * number of bytes might be larger than can fit in a 32-bit register.
- *
- * PLEASE USE A 64-BIT VALUE WHEN CONVERTING THIS INTO BYTES.
- * (See SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB).
- */
- SVGA_REG_GBOBJECT_MEM_SIZE_KB = 76,
-
- /*
- + * These registers are for the addresses of the memory BARs for SVGA3
- */
- SVGA_REG_REGS_START_HIGH32 = 77,
- SVGA_REG_REGS_START_LOW32 = 78,
- SVGA_REG_FB_START_HIGH32 = 79,
- SVGA_REG_FB_START_LOW32 = 80,
-
- /*
- * A hint register that recommends which quality level the guest should
- * currently use to define multisample surfaces.
- *
- * If the register is SVGA_REG_MSHINT_DISABLED,
- * the guest is only allowed to use SVGA3D_MS_QUALITY_FULL.
- *
- * Otherwise, this is a live value that can change while the VM is
- * powered on with the hint suggestion for which quality level the guest
- * should be using. Guests are free to ignore the hint and use either
- * RESOLVE or FULL quality.
- */
- SVGA_REG_MSHINT = 81,
-
- SVGA_REG_IRQ_STATUS = 82,
- SVGA_REG_DIRTY_TRACKING = 83,
-
- SVGA_REG_TOP = 84, /* Must be 1 more than the last register */
-
- SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */
- /* Next 768 (== 256*3) registers exist for colormap */
- SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS
- /* Base of scratch registers */
- /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage:
- First 4 are reserved for VESA BIOS Extension; any remaining are for
- the use of the current SVGA driver. */
-};
+ SVGA_REG_ID = 0,
+ SVGA_REG_ENABLE = 1,
+ SVGA_REG_WIDTH = 2,
+ SVGA_REG_HEIGHT = 3,
+ SVGA_REG_MAX_WIDTH = 4,
+ SVGA_REG_MAX_HEIGHT = 5,
+ SVGA_REG_DEPTH = 6,
+ SVGA_REG_BITS_PER_PIXEL = 7,
+ SVGA_REG_PSEUDOCOLOR = 8,
+ SVGA_REG_RED_MASK = 9,
+ SVGA_REG_GREEN_MASK = 10,
+ SVGA_REG_BLUE_MASK = 11,
+ SVGA_REG_BYTES_PER_LINE = 12,
+ SVGA_REG_FB_START = 13,
+ SVGA_REG_FB_OFFSET = 14,
+ SVGA_REG_VRAM_SIZE = 15,
+ SVGA_REG_FB_SIZE = 16,
+
+ SVGA_REG_ID_0_TOP = 17,
+
+ SVGA_REG_CAPABILITIES = 17,
+ SVGA_REG_MEM_START = 18,
+ SVGA_REG_MEM_SIZE = 19,
+ SVGA_REG_CONFIG_DONE = 20,
+ SVGA_REG_SYNC = 21,
+ SVGA_REG_BUSY = 22,
+ SVGA_REG_GUEST_ID = 23,
+ SVGA_REG_DEAD = 24,
+ SVGA_REG_CURSOR_X = 25,
+ SVGA_REG_CURSOR_Y = 26,
+ SVGA_REG_CURSOR_ON = 27,
+ SVGA_REG_HOST_BITS_PER_PIXEL = 28,
+ SVGA_REG_SCRATCH_SIZE = 29,
+ SVGA_REG_MEM_REGS = 30,
+ SVGA_REG_NUM_DISPLAYS = 31,
+ SVGA_REG_PITCHLOCK = 32,
+ SVGA_REG_IRQMASK = 33,
+
+ SVGA_REG_NUM_GUEST_DISPLAYS = 34,
+ SVGA_REG_DISPLAY_ID = 35,
+ SVGA_REG_DISPLAY_IS_PRIMARY = 36,
+ SVGA_REG_DISPLAY_POSITION_X = 37,
+ SVGA_REG_DISPLAY_POSITION_Y = 38,
+ SVGA_REG_DISPLAY_WIDTH = 39,
+ SVGA_REG_DISPLAY_HEIGHT = 40,
+
+ SVGA_REG_GMR_ID = 41,
+ SVGA_REG_GMR_DESCRIPTOR = 42,
+ SVGA_REG_GMR_MAX_IDS = 43,
+ SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
+
+ SVGA_REG_TRACES = 45,
+ SVGA_REG_GMRS_MAX_PAGES = 46,
+ SVGA_REG_MEMORY_SIZE = 47,
+ SVGA_REG_COMMAND_LOW = 48,
+ SVGA_REG_COMMAND_HIGH = 49,
+
+ SVGA_REG_MAX_PRIMARY_MEM = 50,
+
+ SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51,
+
+ SVGA_REG_DEV_CAP = 52,
+ SVGA_REG_CMD_PREPEND_LOW = 53,
+ SVGA_REG_CMD_PREPEND_HIGH = 54,
+ SVGA_REG_SCREENTARGET_MAX_WIDTH = 55,
+ SVGA_REG_SCREENTARGET_MAX_HEIGHT = 56,
+ SVGA_REG_MOB_MAX_SIZE = 57,
+ SVGA_REG_BLANK_SCREEN_TARGETS = 58,
+ SVGA_REG_CAP2 = 59,
+ SVGA_REG_DEVEL_CAP = 60,
+
+ SVGA_REG_GUEST_DRIVER_ID = 61,
+ SVGA_REG_GUEST_DRIVER_VERSION1 = 62,
+ SVGA_REG_GUEST_DRIVER_VERSION2 = 63,
+ SVGA_REG_GUEST_DRIVER_VERSION3 = 64,
+
+ SVGA_REG_CURSOR_MOBID = 65,
+ SVGA_REG_CURSOR_MAX_BYTE_SIZE = 66,
+ SVGA_REG_CURSOR_MAX_DIMENSION = 67,
+
+ SVGA_REG_FIFO_CAPS = 68,
+ SVGA_REG_FENCE = 69,
+
+ SVGA_REG_CURSOR4_ON = 70,
+ SVGA_REG_CURSOR4_X = 71,
+ SVGA_REG_CURSOR4_Y = 72,
+ SVGA_REG_CURSOR4_SCREEN_ID = 73,
+ SVGA_REG_CURSOR4_SUBMIT = 74,
+
+ SVGA_REG_SCREENDMA = 75,
+
+ SVGA_REG_GBOBJECT_MEM_SIZE_KB = 76,
+
+ SVGA_REG_REGS_START_HIGH32 = 77,
+ SVGA_REG_REGS_START_LOW32 = 78,
+ SVGA_REG_FB_START_HIGH32 = 79,
+ SVGA_REG_FB_START_LOW32 = 80,
+
+ SVGA_REG_MSHINT = 81,
+
+ SVGA_REG_IRQ_STATUS = 82,
+
+ SVGA_REG_DIRTY_TRACKING = 83,
+ SVGA_REG_FENCE_GOAL = 84,
+
+ SVGA_REG_TOP = 85,
+
+ SVGA_PALETTE_BASE = 1024,
+
+ SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS
+};
-/*
- * Values for SVGA_REG_GUEST_DRIVER_ID.
- */
typedef enum SVGARegGuestDriverId {
- SVGA_REG_GUEST_DRIVER_ID_UNKNOWN = 0,
- SVGA_REG_GUEST_DRIVER_ID_WDDM = 1,
- SVGA_REG_GUEST_DRIVER_ID_LINUX = 2,
- SVGA_REG_GUEST_DRIVER_ID_MAX,
+ SVGA_REG_GUEST_DRIVER_ID_UNKNOWN = 0,
+ SVGA_REG_GUEST_DRIVER_ID_WDDM = 1,
+ SVGA_REG_GUEST_DRIVER_ID_LINUX = 2,
+ SVGA_REG_GUEST_DRIVER_ID_MAX,
- SVGA_REG_GUEST_DRIVER_ID_SUBMIT = MAX_UINT32,
+ SVGA_REG_GUEST_DRIVER_ID_SUBMIT = MAX_UINT32,
} SVGARegGuestDriverId;
typedef enum SVGARegMSHint {
- SVGA_REG_MSHINT_DISABLED = 0,
- SVGA_REG_MSHINT_FULL = 1,
- SVGA_REG_MSHINT_RESOLVED = 2,
+ SVGA_REG_MSHINT_DISABLED = 0,
+ SVGA_REG_MSHINT_FULL = 1,
+ SVGA_REG_MSHINT_RESOLVED = 2,
} SVGARegMSHint;
typedef enum SVGARegDirtyTracking {
- SVGA_REG_DIRTY_TRACKING_PER_IMAGE = 0,
- SVGA_REG_DIRTY_TRACKING_PER_SURFACE = 1,
+ SVGA_REG_DIRTY_TRACKING_PER_IMAGE = 0,
+ SVGA_REG_DIRTY_TRACKING_PER_SURFACE = 1,
} SVGARegDirtyTracking;
-
-/*
- * Guest memory regions (GMRs):
- *
- * This is a new memory mapping feature available in SVGA devices
- * which have the SVGA_CAP_GMR bit set. Previously, there were two
- * fixed memory regions available with which to share data between the
- * device and the driver: the FIFO ('MEM') and the framebuffer. GMRs
- * are our name for an extensible way of providing arbitrary DMA
- * buffers for use between the driver and the SVGA device. They are a
- * new alternative to framebuffer memory, usable for both 2D and 3D
- * graphics operations.
- *
- * Since GMR mapping must be done synchronously with guest CPU
- * execution, we use a new pair of SVGA registers:
- *
- * SVGA_REG_GMR_ID --
- *
- * Read/write.
- * This register holds the 32-bit ID (a small positive integer)
- * of a GMR to create, delete, or redefine. Writing this register
- * has no side-effects.
- *
- * SVGA_REG_GMR_DESCRIPTOR --
- *
- * Write-only.
- * Writing this register will create, delete, or redefine the GMR
- * specified by the above ID register. If this register is zero,
- * the GMR is deleted. Any pointers into this GMR (including those
- * currently being processed by FIFO commands) will be
- * synchronously invalidated.
- *
- * If this register is nonzero, it must be the physical page
- * number (PPN) of a data structure which describes the physical
- * layout of the memory region this GMR should describe. The
- * descriptor structure will be read synchronously by the SVGA
- * device when this register is written. The descriptor need not
- * remain allocated for the lifetime of the GMR.
- *
- * The guest driver should write SVGA_REG_GMR_ID first, then
- * SVGA_REG_GMR_DESCRIPTOR.
- *
- * SVGA_REG_GMR_MAX_IDS --
- *
- * Read-only.
- * The SVGA device may choose to support a maximum number of
- * user-defined GMR IDs. This register holds the number of supported
- * IDs. (The maximum supported ID plus 1)
- *
- * SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH --
- *
- * Read-only.
- * The SVGA device may choose to put a limit on the total number
- * of SVGAGuestMemDescriptor structures it will read when defining
- * a single GMR.
- *
- * The descriptor structure is an array of SVGAGuestMemDescriptor
- * structures. Each structure may do one of three things:
- *
- * - Terminate the GMR descriptor list.
- * (ppn==0, numPages==0)
- *
- * - Add a PPN or range of PPNs to the GMR's virtual address space.
- * (ppn != 0, numPages != 0)
- *
- * - Provide the PPN of the next SVGAGuestMemDescriptor, in order to
- * support multi-page GMR descriptor tables without forcing the
- * driver to allocate physically contiguous memory.
- * (ppn != 0, numPages == 0)
- *
- * Note that each physical page of SVGAGuestMemDescriptor structures
- * can describe at least 2MB of guest memory. If the driver needs to
- * use more than one page of descriptor structures, it must use one of
- * its SVGAGuestMemDescriptors to point to an additional page. The
- * device will never automatically cross a page boundary.
- *
- * Once the driver has described a GMR, it is immediately available
- * for use via any FIFO command that uses an SVGAGuestPtr structure.
- * These pointers include a GMR identifier plus an offset into that
- * GMR.
- *
- * The driver must check the SVGA_CAP_GMR bit before using the GMR
- * registers.
- */
-
-/*
- * Special GMR IDs, allowing SVGAGuestPtrs to point to framebuffer
- * memory as well. In the future, these IDs could even be used to
- * allow legacy memory regions to be redefined by the guest as GMRs.
- *
- * Using the guest framebuffer (GFB) at BAR1 for general purpose DMA
- * is being phased out. Please try to use user-defined GMRs whenever
- * possible.
- */
-#define SVGA_GMR_NULL ((uint32) -1)
-#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) /* Guest Framebuffer (GFB) */
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGAGuestMemDescriptor {
- uint32 ppn;
- uint32 numPages;
-}
-#include "vmware_pack_end.h"
-SVGAGuestMemDescriptor;
-
-typedef
-#include "vmware_pack_begin.h"
-struct SVGAGuestPtr {
- uint32 gmrId;
- uint32 offset;
-}
-#include "vmware_pack_end.h"
-SVGAGuestPtr;
-
-/*
- * Register based command buffers --
- *
- * Provide an SVGA device interface that allows the guest to submit
- * command buffers to the SVGA device through an SVGA device register.
- * The metadata for each command buffer is contained in the
- * SVGACBHeader structure along with the return status codes.
- *
- * The SVGA device supports command buffers if
- * SVGA_CAP_COMMAND_BUFFERS is set in the device caps register. The
- * fifo must be enabled for command buffers to be submitted.
- *
- * Command buffers are submitted when the guest writing the 64 byte
- * aligned physical address into the SVGA_REG_COMMAND_LOW and
- * SVGA_REG_COMMAND_HIGH. SVGA_REG_COMMAND_HIGH contains the upper 32
- * bits of the physical address. SVGA_REG_COMMAND_LOW contains the
- * lower 32 bits of the physical address, since the command buffer
- * headers are required to be 64 byte aligned the lower 6 bits are
- * used for the SVGACBContext value. Writing to SVGA_REG_COMMAND_LOW
- * submits the command buffer to the device and queues it for
- * execution. The SVGA device supports at least
- * SVGA_CB_MAX_QUEUED_PER_CONTEXT command buffers that can be queued
- * per context and if that limit is reached the device will write the
- * status SVGA_CB_STATUS_QUEUE_FULL to the status value of the command
- * buffer header synchronously and not raise any IRQs.
- *
- * It is invalid to submit a command buffer without a valid physical
- * address and results are undefined.
- *
- * The device guarantees that command buffers of size SVGA_CB_MAX_SIZE
- * will be supported. If a larger command buffer is submitted results
- * are unspecified and the device will either complete the command
- * buffer or return an error.
- *
- * The device guarantees that any individual command in a command
- * buffer can be up to SVGA_CB_MAX_COMMAND_SIZE in size which is
- * enough to fit a 64x64 color-cursor definition. If the command is
- * too large the device is allowed to process the command or return an
- * error.
- *
- * The device context is a special SVGACBContext that allows for
- * synchronous register like accesses with the flexibility of
- * commands. There is a different command set defined by
- * SVGADeviceContextCmdId. The commands in each command buffer is not
- * allowed to straddle physical pages.
- *
- * The offset field which is available starting with the
- * SVGA_CAP_CMD_BUFFERS_2 cap bit can be set by the guest to bias the
- * start of command processing into the buffer. If an error is
- * encountered the errorOffset will still be relative to the specific
- * PA, not biased by the offset. When the command buffer is finished
- * the guest should not read the offset field as there is no guarantee
- * what it will set to.
- *
- * When the SVGA_CAP_HP_CMD_QUEUE cap bit is set a new command queue
- * SVGA_CB_CONTEXT_1 is available. Commands submitted to this queue
- * will be executed as quickly as possible by the SVGA device
- * potentially before already queued commands on SVGA_CB_CONTEXT_0.
- * The SVGA device guarantees that any command buffers submitted to
- * SVGA_CB_CONTEXT_0 will be executed after any _already_ submitted
- * command buffers to SVGA_CB_CONTEXT_1.
- */
-
-#define SVGA_CB_MAX_SIZE (512 * 1024) /* 512 KB */
+#define SVGA_GMR_NULL ((uint32)-1)
+#define SVGA_GMR_FRAMEBUFFER ((uint32)-2)
+
+#pragma pack(push, 1)
+typedef struct SVGAGuestMemDescriptor {
+ uint32 ppn;
+ uint32 numPages;
+} SVGAGuestMemDescriptor;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct SVGAGuestPtr {
+ uint32 gmrId;
+ uint32 offset;
+} SVGAGuestPtr;
+#pragma pack(pop)
+
+#define SVGA_CB_MAX_SIZE_DEFAULT (KBYTES_2_BYTES(512))
+#define SVGA_CB_MAX_SIZE_4MB (MBYTES_2_BYTES(4))
+#define SVGA_CB_MAX_SIZE SVGA_CB_MAX_SIZE_4MB
#define SVGA_CB_MAX_QUEUED_PER_CONTEXT 32
-#define SVGA_CB_MAX_COMMAND_SIZE (32 * 1024) /* 32 KB */
+#define SVGA_CB_MAX_COMMAND_SIZE (32 * 1024)
#define SVGA_CB_CONTEXT_MASK 0x3f
typedef enum {
- SVGA_CB_CONTEXT_DEVICE = 0x3f,
- SVGA_CB_CONTEXT_0 = 0x0,
- SVGA_CB_CONTEXT_1 = 0x1, /* Supported with SVGA_CAP_HP_CMD_QUEUE */
- SVGA_CB_CONTEXT_MAX = 0x2,
+ SVGA_CB_CONTEXT_DEVICE = 0x3f,
+ SVGA_CB_CONTEXT_0 = 0x0,
+ SVGA_CB_CONTEXT_1 = 0x1,
+ SVGA_CB_CONTEXT_MAX = 0x2,
} SVGACBContext;
-
typedef enum {
- /*
- * The guest is supposed to write SVGA_CB_STATUS_NONE to the status
- * field before submitting the command buffer header, the host will
- * change the value when it is done with the command buffer.
- */
- SVGA_CB_STATUS_NONE = 0,
-
- /*
- * Written by the host when a command buffer completes successfully.
- * The device raises an IRQ with SVGA_IRQFLAG_COMMAND_BUFFER unless
- * the SVGA_CB_FLAG_NO_IRQ flag is set.
- */
- SVGA_CB_STATUS_COMPLETED = 1,
-
- /*
- * Written by the host synchronously with the command buffer
- * submission to indicate the command buffer was not submitted. No
- * IRQ is raised.
- */
- SVGA_CB_STATUS_QUEUE_FULL = 2,
-
- /*
- * Written by the host when an error was detected parsing a command
- * in the command buffer, errorOffset is written to contain the
- * offset to the first byte of the failing command. The device
- * raises the IRQ with both SVGA_IRQFLAG_ERROR and
- * SVGA_IRQFLAG_COMMAND_BUFFER. Some of the commands may have been
- * processed.
- */
- SVGA_CB_STATUS_COMMAND_ERROR = 3,
-
- /*
- * Written by the host if there is an error parsing the command
- * buffer header. The device raises the IRQ with both
- * SVGA_IRQFLAG_ERROR and SVGA_IRQFLAG_COMMAND_BUFFER. The device
- * did not processes any of the command buffer.
- */
- SVGA_CB_STATUS_CB_HEADER_ERROR = 4,
-
- /*
- * Written by the host if the guest requested the host to preempt
- * the command buffer. The device will not raise any IRQs and the
- * command buffer was not processed.
- */
- SVGA_CB_STATUS_PREEMPTED = 5,
-
- /*
- * Written by the host synchronously with the command buffer
- * submission to indicate the the command buffer was not submitted
- * due to an error. No IRQ is raised.
- */
- SVGA_CB_STATUS_SUBMISSION_ERROR = 6,
-
- /*
- * Written by the host when the host finished a
- * SVGA_DC_CMD_ASYNC_STOP_QUEUE request for this command buffer
- * queue. The offset of the first byte not processed is stored in
- * the errorOffset field of the command buffer header. All guest
- * visible side effects of commands till that point are guaranteed
- * to be finished before this is written. The
- * SVGA_IRQFLAG_COMMAND_BUFFER IRQ is raised as long as the
- * SVGA_CB_FLAG_NO_IRQ is not set.
- */
- SVGA_CB_STATUS_PARTIAL_COMPLETE = 7,
+
+ SVGA_CB_STATUS_NONE = 0,
+
+ SVGA_CB_STATUS_COMPLETED = 1,
+
+ SVGA_CB_STATUS_QUEUE_FULL = 2,
+
+ SVGA_CB_STATUS_COMMAND_ERROR = 3,
+
+ SVGA_CB_STATUS_CB_HEADER_ERROR = 4,
+
+ SVGA_CB_STATUS_PREEMPTED = 5,
+
+ SVGA_CB_STATUS_SUBMISSION_ERROR = 6,
+
+ SVGA_CB_STATUS_PARTIAL_COMPLETE = 7,
} SVGACBStatus;
typedef enum {
- SVGA_CB_FLAG_NONE = 0,
- SVGA_CB_FLAG_NO_IRQ = 1 << 0,
- SVGA_CB_FLAG_DX_CONTEXT = 1 << 1,
- SVGA_CB_FLAG_MOB = 1 << 2,
+ SVGA_CB_FLAG_NONE = 0,
+ SVGA_CB_FLAG_NO_IRQ = 1 << 0,
+ SVGA_CB_FLAG_DX_CONTEXT = 1 << 1,
+ SVGA_CB_FLAG_MOB = 1 << 2,
} SVGACBFlags;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- volatile SVGACBStatus status; /* Modified by device. */
- volatile uint32 errorOffset; /* Modified by device. */
- uint64 id;
- SVGACBFlags flags;
- uint32 length;
- union {
- PA pa;
- struct {
- SVGAMobId mobid;
- uint32 mobOffset;
- } mob;
- } ptr;
- uint32 offset; /* Valid if CMD_BUFFERS_2 cap set, must be zero otherwise,
- * modified by device.
- */
- uint32 dxContext; /* Valid if DX_CONTEXT flag set, must be zero otherwise */
- uint32 mustBeZero[6];
-}
-#include "vmware_pack_end.h"
-SVGACBHeader;
+#pragma pack(push, 1)
+typedef struct {
+ volatile SVGACBStatus status;
+ volatile uint32 errorOffset;
+ uint64 id;
+ SVGACBFlags flags;
+ uint32 length;
+ union {
+ PA pa;
+ struct {
+ SVGAMobId mobid;
+ uint32 mobOffset;
+ } mob;
+ } ptr;
+ uint32 offset;
+ uint32 dxContext;
+ uint32 mustBeZero[6];
+} SVGACBHeader;
+#pragma pack(pop)
typedef enum {
- SVGA_DC_CMD_NOP = 0,
- SVGA_DC_CMD_START_STOP_CONTEXT = 1,
- SVGA_DC_CMD_PREEMPT = 2,
- SVGA_DC_CMD_START_QUEUE = 3, /* Requires SVGA_CAP_HP_CMD_QUEUE */
- SVGA_DC_CMD_ASYNC_STOP_QUEUE = 4, /* Requires SVGA_CAP_HP_CMD_QUEUE */
- SVGA_DC_CMD_EMPTY_CONTEXT_QUEUE = 5, /* Requires SVGA_CAP_HP_CMD_QUEUE */
- SVGA_DC_CMD_MAX = 6,
+ SVGA_DC_CMD_NOP = 0,
+ SVGA_DC_CMD_START_STOP_CONTEXT = 1,
+ SVGA_DC_CMD_PREEMPT = 2,
+ SVGA_DC_CMD_START_QUEUE = 3,
+ SVGA_DC_CMD_ASYNC_STOP_QUEUE = 4,
+ SVGA_DC_CMD_EMPTY_CONTEXT_QUEUE = 5,
+ SVGA_DC_CMD_MAX = 6
} SVGADeviceContextCmdId;
-/*
- * Starts or stops both SVGA_CB_CONTEXT_0 and SVGA_CB_CONTEXT_1.
- */
-
typedef struct SVGADCCmdStartStop {
- uint32 enable;
- SVGACBContext context; /* Must be zero */
+ uint32 enable;
+ SVGACBContext context;
} SVGADCCmdStartStop;
-/*
- * SVGADCCmdPreempt --
- *
- * This command allows the guest to request that all command buffers
- * on SVGA_CB_CONTEXT_0 be preempted that can be. After execution
- * of this command all command buffers that were preempted will
- * already have SVGA_CB_STATUS_PREEMPTED written into the status
- * field. The device might still be processing a command buffer,
- * assuming execution of it started before the preemption request was
- * received. Specifying the ignoreIDZero flag to TRUE will cause the
- * device to not preempt command buffers with the id field in the
- * command buffer header set to zero.
- */
-
typedef struct SVGADCCmdPreempt {
- SVGACBContext context; /* Must be zero */
- uint32 ignoreIDZero;
+ SVGACBContext context;
+ uint32 ignoreIDZero;
} SVGADCCmdPreempt;
-/*
- * Starts the requested command buffer processing queue. Valid only
- * if the SVGA_CAP_HP_CMD_QUEUE cap is set.
- *
- * For a command queue to be considered runnable it must be enabled
- * and any corresponding higher priority queues must also be enabled.
- * For example in order for command buffers to be processed on
- * SVGA_CB_CONTEXT_0 both SVGA_CB_CONTEXT_0 and SVGA_CB_CONTEXT_1 must
- * be enabled. But for commands to be runnable on SVGA_CB_CONTEXT_1
- * only that queue must be enabled.
- */
-
typedef struct SVGADCCmdStartQueue {
- SVGACBContext context;
+ SVGACBContext context;
} SVGADCCmdStartQueue;
-/*
- * Requests the SVGA device to stop processing the requested command
- * buffer queue as soon as possible. The guest knows the stop has
- * completed when one of the following happens.
- *
- * 1) A command buffer status of SVGA_CB_STATUS_PARTIAL_COMPLETE is returned
- * 2) A command buffer error is encountered with would stop the queue
- * regardless of the async stop request.
- * 3) All command buffers that have been submitted complete successfully.
- * 4) The stop completes synchronously if no command buffers are
- * active on the queue when it is issued.
- *
- * If the command queue is not in a runnable state there is no
- * guarentee this async stop will finish. For instance if the high
- * priority queue is not enabled and a stop is requested on the low
- * priority queue, the high priority queue must be reenabled to
- * guarantee that the async stop will finish.
- *
- * This command along with SVGA_DC_CMD_EMPTY_CONTEXT_QUEUE can be used
- * to implement mid command buffer preemption.
- *
- * Valid only if the SVGA_CAP_HP_CMD_QUEUE cap is set.
- */
-
typedef struct SVGADCCmdAsyncStopQueue {
- SVGACBContext context;
+ SVGACBContext context;
} SVGADCCmdAsyncStopQueue;
-/*
- * Requests the SVGA device to throw away any full command buffers on
- * the requested command queue that have not been started. For a
- * driver to know which command buffers were thrown away a driver
- * should only issue this command when the queue is stopped, for
- * whatever reason.
- */
-
typedef struct SVGADCCmdEmptyQueue {
- SVGACBContext context;
+ SVGACBContext context;
} SVGADCCmdEmptyQueue;
-
-/*
- * SVGAGMRImageFormat --
- *
- * This is a packed representation of the source 2D image format
- * for a GMR-to-screen blit. Currently it is defined as an encoding
- * of the screen's color depth and bits-per-pixel, however, 16 bits
- * are reserved for future use to identify other encodings (such as
- * RGBA or higher-precision images).
- *
- * Currently supported formats:
- *
- * bpp depth Format Name
- * --- ----- -----------
- * 32 24 32-bit BGRX
- * 24 24 24-bit BGR
- * 16 16 RGB 5-6-5
- * 16 15 RGB 5-5-5
- *
- */
-
typedef struct SVGAGMRImageFormat {
- union {
- struct {
- uint32 bitsPerPixel : 8;
- uint32 colorDepth : 8;
- uint32 reserved : 16; /* Must be zero */
- };
-
- uint32 value;
- };
+ union {
+ struct {
+ uint32 bitsPerPixel : 8;
+ uint32 colorDepth : 8;
+ uint32 reserved : 16;
+ };
+
+ uint32 value;
+ };
} SVGAGMRImageFormat;
-typedef
-#include "vmware_pack_begin.h"
-struct SVGAGuestImage {
- SVGAGuestPtr ptr;
-
- /*
- * A note on interpretation of pitch: This value of pitch is the
- * number of bytes between vertically adjacent image
- * blocks. Normally this is the number of bytes between the first
- * pixel of two adjacent scanlines. With compressed textures,
- * however, this may represent the number of bytes between
- * compression blocks rather than between rows of pixels.
- *
- * XXX: Compressed textures currently must be tightly packed in guest memory.
- *
- * If the image is 1-dimensional, pitch is ignored.
- *
- * If 'pitch' is zero, the SVGA3D device calculates a pitch value
- * assuming each row of blocks is tightly packed.
- */
- uint32 pitch;
-}
-#include "vmware_pack_end.h"
-SVGAGuestImage;
+#pragma pack(push, 1)
+typedef struct SVGAGuestImage {
+ SVGAGuestPtr ptr;
-/*
- * SVGAColorBGRX --
- *
- * A 24-bit color format (BGRX), which does not depend on the
- * format of the legacy guest framebuffer (GFB) or the current
- * GMRFB state.
- */
+ uint32 pitch;
+} SVGAGuestImage;
+#pragma pack(pop)
typedef struct SVGAColorBGRX {
- union {
- struct {
- uint32 b : 8;
- uint32 g : 8;
- uint32 r : 8;
- uint32 x : 8; /* Unused */
- };
-
- uint32 value;
- };
+ union {
+ struct {
+ uint32 b : 8;
+ uint32 g : 8;
+ uint32 r : 8;
+ uint32 x : 8;
+ };
+
+ uint32 value;
+ };
} SVGAColorBGRX;
-
-/*
- * SVGASignedRect --
- * SVGASignedPoint --
- *
- * Signed rectangle and point primitives. These are used by the new
- * 2D primitives for drawing to Screen Objects, which can occupy a
- * signed virtual coordinate space.
- *
- * SVGASignedRect specifies a half-open interval: the (left, top)
- * pixel is part of the rectangle, but the (right, bottom) pixel is
- * not.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- int32 left;
- int32 top;
- int32 right;
- int32 bottom;
-}
-#include "vmware_pack_end.h"
-SVGASignedRect;
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- int32 x;
- int32 y;
-}
-#include "vmware_pack_end.h"
-SVGASignedPoint;
-
-
-/*
- * SVGA Device Capabilities
- *
- * Note the holes in the bitfield. Missing bits have been deprecated,
- * and must not be reused. Those capabilities will never be reported
- * by new versions of the SVGA device.
- *
- * SVGA_CAP_IRQMASK --
- * Provides device interrupts. Adds device register SVGA_REG_IRQMASK
- * to set interrupt mask and direct I/O port SVGA_IRQSTATUS_PORT to
- * set/clear pending interrupts.
- *
- * SVGA_CAP_GMR --
- * Provides synchronous mapping of guest memory regions (GMR).
- * Adds device registers SVGA_REG_GMR_ID, SVGA_REG_GMR_DESCRIPTOR,
- * SVGA_REG_GMR_MAX_IDS, and SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH.
- *
- * SVGA_CAP_TRACES --
- * Allows framebuffer trace-based updates even when FIFO is enabled.
- * Adds device register SVGA_REG_TRACES.
- *
- * SVGA_CAP_GMR2 --
- * Provides asynchronous commands to define and remap guest memory
- * regions. Adds device registers SVGA_REG_GMRS_MAX_PAGES and
- * SVGA_REG_MEMORY_SIZE.
- *
- * SVGA_CAP_SCREEN_OBJECT_2 --
- * Allow screen object support, and require backing stores from the
- * guest for each screen object.
- *
- * SVGA_CAP_COMMAND_BUFFERS --
- * Enable register based command buffer submission.
- *
- * SVGA_CAP_DEAD1 --
- * This cap was incorrectly used by old drivers and should not be
- * reused.
- *
- * SVGA_CAP_CMD_BUFFERS_2 --
- * Enable support for the prepend command buffer submision
- * registers. SVGA_REG_CMD_PREPEND_LOW and
- * SVGA_REG_CMD_PREPEND_HIGH.
- *
- * SVGA_CAP_GBOBJECTS --
- * Enable guest-backed objects and surfaces.
- *
- * SVGA_CAP_DX --
- * Enable support for DX commands, and command buffers in a mob.
- *
- * SVGA_CAP_HP_CMD_QUEUE --
- * Enable support for the high priority command queue, and the
- * ScreenCopy command.
- *
- * SVGA_CAP_NO_BB_RESTRICTION --
- * Allow ScreenTargets to be defined without regard to the 32-bpp
- * bounding-box memory restrictions. ie:
- *
- * The summed memory usage of all screens (assuming they were defined as
- * 32-bpp) must always be less than the value of the
- * SVGA_REG_MAX_PRIMARY_MEM register.
- *
- * If this cap is not present, the 32-bpp bounding box around all screens
- * must additionally be under the value of the SVGA_REG_MAX_PRIMARY_MEM
- * register.
- *
- * If the cap is present, the bounding box restriction is lifted (and only
- * the screen-sum limit applies).
- *
- * (Note that this is a slight lie... there is still a sanity limit on any
- * dimension of the topology to be less than SVGA_SCREEN_ROOT_LIMIT, even
- * when SVGA_CAP_NO_BB_RESTRICTION is present, but that should be
- * large enough to express any possible topology without holes between
- * monitors.)
- *
- * SVGA_CAP_CAP2_REGISTER --
- * If this cap is present, the SVGA_REG_CAP2 register is supported.
- */
-
-#define SVGA_CAP_NONE 0x00000000
-#define SVGA_CAP_RECT_COPY 0x00000002
-#define SVGA_CAP_CURSOR 0x00000020
-#define SVGA_CAP_CURSOR_BYPASS 0x00000040
-#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080
-#define SVGA_CAP_8BIT_EMULATION 0x00000100
-#define SVGA_CAP_ALPHA_CURSOR 0x00000200
-#define SVGA_CAP_3D 0x00004000
-#define SVGA_CAP_EXTENDED_FIFO 0x00008000
-#define SVGA_CAP_MULTIMON 0x00010000
-#define SVGA_CAP_PITCHLOCK 0x00020000
-#define SVGA_CAP_IRQMASK 0x00040000
-#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000
-#define SVGA_CAP_GMR 0x00100000
-#define SVGA_CAP_TRACES 0x00200000
-#define SVGA_CAP_GMR2 0x00400000
-#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000
-#define SVGA_CAP_COMMAND_BUFFERS 0x01000000
-#define SVGA_CAP_DEAD1 0x02000000
-#define SVGA_CAP_CMD_BUFFERS_2 0x04000000
-#define SVGA_CAP_GBOBJECTS 0x08000000
-#define SVGA_CAP_DX 0x10000000
-#define SVGA_CAP_HP_CMD_QUEUE 0x20000000
-#define SVGA_CAP_NO_BB_RESTRICTION 0x40000000
-#define SVGA_CAP_CAP2_REGISTER 0x80000000
-
-/*
- * The SVGA_REG_CAP2 register is an additional set of SVGA capability bits.
- *
- * SVGA_CAP2_GROW_OTABLE --
- * Allow the GrowOTable/DXGrowCOTable commands.
- *
- * SVGA_CAP2_INTRA_SURFACE_COPY --
- * Allow the IntraSurfaceCopy command.
- *
- * SVGA_CAP2_DX2 --
- * Allow the DefineGBSurface_v3, WholeSurfaceCopy, WriteZeroSurface, and
- * HintZeroSurface commands, and the SVGA_REG_GUEST_DRIVER_ID register.
- *
- * SVGA_CAP2_GB_MEMSIZE_2 --
- * Allow the SVGA_REG_GBOBJECT_MEM_SIZE_KB register.
- *
- * SVGA_CAP2_SCREENDMA_REG --
- * Allow the SVGA_REG_SCREENDMA register.
- *
- * SVGA_CAP2_OTABLE_PTDEPTH_2 --
- * Allow 2 level page tables for OTable commands.
- *
- * SVGA_CAP2_NON_MS_TO_MS_STRETCHBLT --
- * Allow a stretch blt from a non-multisampled surface to a multisampled
- * surface.
- *
- * SVGA_CAP2_CURSOR_MOB --
- * Allow the SVGA_REG_CURSOR_MOBID register.
- *
- * SVGA_CAP2_MSHINT --
- * Allow the SVGA_REG_MSHINT register.
- *
- * SVGA_CAP2_DX3 --
- * Allows the DefineGBSurface_v4 command.
- * Allows the DXDefineDepthStencilView_v2, DXDefineStreamOutputWithMob,
- * and DXBindStreamOutput commands if 3D is also available.
- * Allows the DXPredStagingCopy and DXStagingCopy commands if SM41
- * is also available.
- *
- * SVGA_CAP2_RESERVED --
- * Reserve the last bit for extending the SVGA capabilities to some
- * future mechanisms.
- */
-#define SVGA_CAP2_NONE 0x00000000
-#define SVGA_CAP2_GROW_OTABLE 0x00000001
-#define SVGA_CAP2_INTRA_SURFACE_COPY 0x00000002
-#define SVGA_CAP2_DX2 0x00000004
-#define SVGA_CAP2_GB_MEMSIZE_2 0x00000008
-#define SVGA_CAP2_SCREENDMA_REG 0x00000010
-#define SVGA_CAP2_OTABLE_PTDEPTH_2 0x00000020
+#pragma pack(push, 1)
+typedef struct {
+ int32 left;
+ int32 top;
+ int32 right;
+ int32 bottom;
+} SVGASignedRect;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ int32 x;
+ int32 y;
+} SVGASignedPoint;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 x;
+ uint32 y;
+} SVGAUnsignedPoint;
+#pragma pack(pop)
+
+#define SVGA_CAP_NONE 0x00000000
+#define SVGA_CAP_RECT_COPY 0x00000002
+#define SVGA_CAP_CURSOR 0x00000020
+#define SVGA_CAP_CURSOR_BYPASS 0x00000040
+#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080
+#define SVGA_CAP_8BIT_EMULATION 0x00000100
+#define SVGA_CAP_ALPHA_CURSOR 0x00000200
+#define SVGA_CAP_3D 0x00004000
+#define SVGA_CAP_EXTENDED_FIFO 0x00008000
+#define SVGA_CAP_MULTIMON 0x00010000
+#define SVGA_CAP_PITCHLOCK 0x00020000
+#define SVGA_CAP_IRQMASK 0x00040000
+#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000
+#define SVGA_CAP_GMR 0x00100000
+#define SVGA_CAP_TRACES 0x00200000
+#define SVGA_CAP_GMR2 0x00400000
+#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000
+#define SVGA_CAP_COMMAND_BUFFERS 0x01000000
+#define SVGA_CAP_DEAD1 0x02000000
+#define SVGA_CAP_CMD_BUFFERS_2 0x04000000
+#define SVGA_CAP_GBOBJECTS 0x08000000
+#define SVGA_CAP_DX 0x10000000
+#define SVGA_CAP_HP_CMD_QUEUE 0x20000000
+#define SVGA_CAP_NO_BB_RESTRICTION 0x40000000
+#define SVGA_CAP_CAP2_REGISTER 0x80000000
+
+#define SVGA_CAP2_NONE 0x00000000
+#define SVGA_CAP2_GROW_OTABLE 0x00000001
+#define SVGA_CAP2_INTRA_SURFACE_COPY 0x00000002
+#define SVGA_CAP2_DX2 0x00000004
+#define SVGA_CAP2_GB_MEMSIZE_2 0x00000008
+#define SVGA_CAP2_SCREENDMA_REG 0x00000010
+#define SVGA_CAP2_OTABLE_PTDEPTH_2 0x00000020
#define SVGA_CAP2_NON_MS_TO_MS_STRETCHBLT 0x00000040
-#define SVGA_CAP2_CURSOR_MOB 0x00000080
-#define SVGA_CAP2_MSHINT 0x00000100
-#define SVGA_CAP2_DX3 0x00000400
-#define SVGA_CAP2_RESERVED 0x80000000
-
-
-/*
- * The Guest can optionally read some SVGA device capabilities through
- * the backdoor with command BDOOR_CMD_GET_SVGA_CAPABILITIES before
- * the SVGA device is initialized. The type of capability the guest
- * is requesting from the SVGABackdoorCapType enum should be placed in
- * the upper 16 bits of the backdoor command id (ECX). On success the
- * the value of EBX will be set to BDOOR_MAGIC and EAX will be set to
- * the requested capability. If the command is not supported then EBX
- * will be left unchanged and EAX will be set to -1. Because it is
- * possible that -1 is the value of the requested cap the correct way
- * to check if the command was successful is to check if EBX was changed
- * to BDOOR_MAGIC making sure to initialize the register to something
- * else first.
- */
+#define SVGA_CAP2_CURSOR_MOB 0x00000080
+#define SVGA_CAP2_MSHINT 0x00000100
+#define SVGA_CAP2_CB_MAX_SIZE_4MB 0x00000200
+#define SVGA_CAP2_DX3 0x00000400
+#define SVGA_CAP2_FRAME_TYPE 0x00000800
+#define SVGA_CAP2_COTABLE_COPY 0x00001000
+#define SVGA_CAP2_TRACE_FULL_FB 0x00002000
+#define SVGA_CAP2_EXTRA_REGS 0x00004000
+#define SVGA_CAP2_LO_STAGING 0x00008000
+#define SVGA_CAP2_RESERVED 0x80000000
typedef enum {
- SVGABackdoorCapDeviceCaps = 0,
- SVGABackdoorCapFifoCaps = 1,
- SVGABackdoorCap3dHWVersion = 2,
- SVGABackdoorCapDeviceCaps2 = 3,
- SVGABackdoorCapDevelCaps = 4,
- SVGABackdoorDevelRenderer = 5,
- SVGABackdoorCapMax = 6,
+ SVGABackdoorCapDeviceCaps = 0,
+ SVGABackdoorCapFifoCaps = 1,
+ SVGABackdoorCap3dHWVersion = 2,
+ SVGABackdoorCapDeviceCaps2 = 3,
+ SVGABackdoorCapDevelCaps = 4,
+ SVGABackdoorDevelRenderer = 5,
+ SVGABackdoorDevelUsingISB = 6,
+ SVGABackdoorCapMax = 7,
} SVGABackdoorCapType;
-
-/*
- * FIFO register indices.
- *
- * The FIFO is a chunk of device memory mapped into guest physmem. It
- * is always treated as 32-bit words.
- *
- * The guest driver gets to decide how to partition it between
- * - FIFO registers (there are always at least 4, specifying where the
- * following data area is and how much data it contains; there may be
- * more registers following these, depending on the FIFO protocol
- * version in use)
- * - FIFO data, written by the guest and slurped out by the VMX.
- * These indices are 32-bit word offsets into the FIFO.
- */
-
enum {
- /*
- * Block 1 (basic registers): The originally defined FIFO registers.
- * These exist and are valid for all versions of the FIFO protocol.
- */
-
- SVGA_FIFO_MIN = 0,
- SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */
- SVGA_FIFO_NEXT_CMD,
- SVGA_FIFO_STOP,
-
- /*
- * Block 2 (extended registers): Mandatory registers for the extended
- * FIFO. These exist if the SVGA caps register includes
- * SVGA_CAP_EXTENDED_FIFO; some of them are valid only if their
- * associated capability bit is enabled.
- *
- * Note that when originally defined, SVGA_CAP_EXTENDED_FIFO implied
- * support only for (FIFO registers) CAPABILITIES, FLAGS, and FENCE.
- * This means that the guest has to test individually (in most cases
- * using FIFO caps) for the presence of registers after this; the VMX
- * can define "extended FIFO" to mean whatever it wants, and currently
- * won't enable it unless there's room for that set and much more.
- */
-
- SVGA_FIFO_CAPABILITIES = 4,
- SVGA_FIFO_FLAGS,
- /* Valid with SVGA_FIFO_CAP_FENCE: */
- SVGA_FIFO_FENCE,
-
- /*
- * Block 3a (optional extended registers): Additional registers for the
- * extended FIFO, whose presence isn't actually implied by
- * SVGA_CAP_EXTENDED_FIFO; these exist if SVGA_FIFO_MIN is high enough to
- * leave room for them.
- *
- * These in block 3a, the VMX currently considers mandatory for the
- * extended FIFO.
- */
-
- /* Valid if exists (i.e. if extended FIFO enabled): */
- SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */
- /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */
- SVGA_FIFO_PITCHLOCK,
-
- /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */
- SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */
- SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */
- SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */
- SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */
- SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */
-
- /* Valid with SVGA_FIFO_CAP_RESERVE: */
- SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */
-
- /*
- * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2:
- *
- * By default this is SVGA_ID_INVALID, to indicate that the cursor
- * coordinates are specified relative to the virtual root. If this
- * is set to a specific screen ID, cursor position is reinterpreted
- * as a signed offset relative to that screen's origin.
- */
- SVGA_FIFO_CURSOR_SCREEN_ID,
-
- /*
- * Valid with SVGA_FIFO_CAP_DEAD
- *
- * An arbitrary value written by the host, drivers should not use it.
- */
- SVGA_FIFO_DEAD,
-
- /*
- * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED:
- *
- * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h)
- * on platforms that can enforce graphics resource limits.
- */
- SVGA_FIFO_3D_HWVERSION_REVISED,
-
- /*
- * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new
- * registers, but this must be done carefully and with judicious use of
- * capability bits, since comparisons based on SVGA_FIFO_MIN aren't
- * enough to tell you whether the register exists: we've shipped drivers
- * and products that used SVGA_FIFO_3D_CAPS but didn't know about some of
- * the earlier ones. The actual order of introduction was:
- * - PITCHLOCK
- * - 3D_CAPS
- * - CURSOR_* (cursor bypass 3)
- * - RESERVED
- * So, code that wants to know whether it can use any of the
- * aforementioned registers, or anything else added after PITCHLOCK and
- * before 3D_CAPS, needs to reason about something other than
- * SVGA_FIFO_MIN.
- */
-
- /*
- * 3D caps block space; valid with 3D hardware version >=
- * SVGA3D_HWVERSION_WS6_B1.
- */
- SVGA_FIFO_3D_CAPS = 32,
- SVGA_FIFO_3D_CAPS_LAST = 32 + 255,
-
- /*
- * End of VMX's current definition of "extended-FIFO registers".
- * Registers before here are always enabled/disabled as a block; either
- * the extended FIFO is enabled and includes all preceding registers, or
- * it's disabled entirely.
- *
- * Block 3b (truly optional extended registers): Additional registers for
- * the extended FIFO, which the VMX already knows how to enable and
- * disable with correct granularity.
- *
- * Registers after here exist if and only if the guest SVGA driver
- * sets SVGA_FIFO_MIN high enough to leave room for them.
- */
-
- /* Valid if register exists: */
- SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */
- SVGA_FIFO_FENCE_GOAL, /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */
- SVGA_FIFO_BUSY, /* See "FIFO Synchronization Registers" */
-
- /*
- * Always keep this last. This defines the maximum number of
- * registers we know about. At power-on, this value is placed in
- * the SVGA_REG_MEM_REGS register, and we expect the guest driver
- * to allocate this much space in FIFO memory for registers.
- */
- SVGA_FIFO_NUM_REGS
-};
+ SVGA_FIFO_MIN = 0,
+ SVGA_FIFO_MAX,
+ SVGA_FIFO_NEXT_CMD,
+ SVGA_FIFO_STOP,
-/*
- * Definition of registers included in extended FIFO support.
- *
- * The guest SVGA driver gets to allocate the FIFO between registers
- * and data. It must always allocate at least 4 registers, but old
- * drivers stopped there.
- *
- * The VMX will enable extended FIFO support if and only if the guest
- * left enough room for all registers defined as part of the mandatory
- * set for the extended FIFO.
- *
- * Note that the guest drivers typically allocate the FIFO only at
- * initialization time, not at mode switches, so it's likely that the
- * number of FIFO registers won't change without a reboot.
- *
- * All registers less than this value are guaranteed to be present if
- * svgaUser->fifo.extended is set. Any later registers must be tested
- * individually for compatibility at each use (in the VMX).
- *
- * This value is used only by the VMX, so it can change without
- * affecting driver compatibility; keep it that way?
- */
-#define SVGA_FIFO_EXTENDED_MANDATORY_REGS (SVGA_FIFO_3D_CAPS_LAST + 1)
+ SVGA_FIFO_CAPABILITIES = 4,
+ SVGA_FIFO_FLAGS,
+ SVGA_FIFO_FENCE,
-/*
- * FIFO Synchronization Registers
- *
- * SVGA_REG_SYNC --
- *
- * The SYNC register can be used by the guest driver to signal to the
- * device that the guest driver is waiting for previously submitted
- * commands to complete.
- *
- * When the guest driver writes to the SYNC register, the device sets
- * the BUSY register to TRUE, and starts processing the submitted commands
- * (if it was not already doing so). When all previously submitted
- * commands are finished and the device is idle again, it sets the BUSY
- * register back to FALSE. (If the guest driver submits new commands
- * after writing the SYNC register, the new commands are not guaranteed
- * to have been procesesd.)
- *
- * When guest drivers are submitting commands using the FIFO, the device
- * periodically polls to check for new FIFO commands when idle, which may
- * introduce a delay in command processing. If the guest-driver wants
- * the commands to be processed quickly (which it typically does), it
- * should write SYNC after each batch of commands is committed to the
- * FIFO to immediately wake up the device. For even better performance,
- * the guest can use the SVGA_FIFO_BUSY register to avoid these extra
- * SYNC writes if the device is already active, using the technique known
- * as "Ringing the Doorbell" (described below). (Note that command
- * buffer submission implicitly wakes up the device, and so doesn't
- * suffer from this problem.)
- *
- * The SYNC register can also be used in combination with BUSY to
- * synchronously ensure that all SVGA commands are processed (with both
- * the FIFO and command-buffers). To do this, the guest driver should
- * write to SYNC, and then loop reading BUSY until BUSY returns FALSE.
- * This technique is known as a "Legacy Sync".
- *
- * SVGA_REG_BUSY --
- *
- * This register is set to TRUE when SVGA_REG_SYNC is written,
- * and is set back to FALSE when the device has finished processing
- * all commands and is idle again.
- *
- * Every read from the BUSY reigster will block for an undefined
- * amount of time (normally until the device finishes some interesting
- * work unit), or the device is idle.
- *
- * Guest drivers can also do a partial Legacy Sync to check for some
- * particular condition, for instance by stopping early when a fence
- * passes before BUSY has been set back to FALSE. This is particularly
- * useful if the guest-driver knows that it is blocked waiting on the
- * device, because it will yield CPU time back to the host.
- *
- * SVGA_FIFO_BUSY --
- *
- * The SVGA_FIFO_BUSY register is a fast way for the guest driver to check
- * whether the device is actively processing FIFO commands before writing
- * the more expensive SYNC register.
- *
- * If this register reads as TRUE, the device is actively processing
- * FIFO commands.
- *
- * If this register reads as FALSE, the device may not be actively
- * processing commands, and the guest driver should try
- * "Ringing the Doorbell".
- *
- * To Ring the Doorbell, the guest should:
- *
- * 1. Have already written their batch of commands into the FIFO.
- * 2. Check if the SVGA_FIFO_BUSY register is available by reading
- * SVGA_FIFO_MIN.
- * 3. Read SVGA_FIFO_BUSY. If it reads as TRUE, the device is actively
- * processing FIFO commands, and no further action is necessary.
- * 4. If SVGA_FIFO_BUSY was FALSE, write TRUE to SVGA_REG_SYNC.
- *
- * For maximum performance, this procedure should be followed after
- * every meaningful batch of commands has been written into the FIFO.
- * (Normally when the underlying application signals it's finished a
- * meaningful work unit by calling Flush.)
- */
+ SVGA_FIFO_3D_HWVERSION,
+ SVGA_FIFO_PITCHLOCK,
-/*
- * FIFO Capabilities
- *
- * Fence -- Fence register and command are supported
- * Accel Front -- Front buffer only commands are supported
- * Pitch Lock -- Pitch lock register is supported
- * Video -- SVGA Video overlay units are supported
- * Escape -- Escape command is supported
- *
- * SVGA_FIFO_CAP_SCREEN_OBJECT --
- *
- * Provides dynamic multi-screen rendering, for improved Unity and
- * multi-monitor modes. With Screen Object, the guest can
- * dynamically create and destroy 'screens', which can represent
- * Unity windows or virtual monitors. Screen Object also provides
- * strong guarantees that DMA operations happen only when
- * guest-initiated. Screen Object deprecates the BAR1 guest
- * framebuffer (GFB) and all commands that work only with the GFB.
- *
- * New registers:
- * FIFO_CURSOR_SCREEN_ID, VIDEO_DATA_GMRID, VIDEO_DST_SCREEN_ID
- *
- * New 2D commands:
- * DEFINE_SCREEN, DESTROY_SCREEN, DEFINE_GMRFB, BLIT_GMRFB_TO_SCREEN,
- * BLIT_SCREEN_TO_GMRFB, ANNOTATION_FILL, ANNOTATION_COPY
- *
- * New 3D commands:
- * BLIT_SURFACE_TO_SCREEN
- *
- * New guarantees:
- *
- * - The host will not read or write guest memory, including the GFB,
- * except when explicitly initiated by a DMA command.
- *
- * - All DMA, including legacy DMA like UPDATE and PRESENT_READBACK,
- * is guaranteed to complete before any subsequent FENCEs.
- *
- * - All legacy commands which affect a Screen (UPDATE, PRESENT,
- * PRESENT_READBACK) as well as new Screen blit commands will
- * all behave consistently as blits, and memory will be read
- * or written in FIFO order.
- *
- * For example, if you PRESENT from one SVGA3D surface to multiple
- * places on the screen, the data copied will always be from the
- * SVGA3D surface at the time the PRESENT was issued in the FIFO.
- * This was not necessarily true on devices without Screen Object.
- *
- * This means that on devices that support Screen Object, the
- * PRESENT_READBACK command should not be necessary unless you
- * actually want to read back the results of 3D rendering into
- * system memory. (And for that, the BLIT_SCREEN_TO_GMRFB
- * command provides a strict superset of functionality.)
- *
- * - When a screen is resized, either using Screen Object commands or
- * legacy multimon registers, its contents are preserved.
- *
- * SVGA_FIFO_CAP_GMR2 --
- *
- * Provides new commands to define and remap guest memory regions (GMR).
- *
- * New 2D commands:
- * DEFINE_GMR2, REMAP_GMR2.
- *
- * SVGA_FIFO_CAP_3D_HWVERSION_REVISED --
- *
- * Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists.
- * This register may replace SVGA_FIFO_3D_HWVERSION on platforms
- * that enforce graphics resource limits. This allows the platform
- * to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest
- * drivers that do not limit their resources.
- *
- * Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators
- * are codependent (and thus we use a single capability bit).
- *
- * SVGA_FIFO_CAP_SCREEN_OBJECT_2 --
- *
- * Modifies the DEFINE_SCREEN command to include a guest provided
- * backing store in GMR memory and the bytesPerLine for the backing
- * store. This capability requires the use of a backing store when
- * creating screen objects. However if SVGA_FIFO_CAP_SCREEN_OBJECT
- * is present then backing stores are optional.
- *
- * SVGA_FIFO_CAP_DEAD --
- *
- * Drivers should not use this cap bit. This cap bit can not be
- * reused since some hosts already expose it.
- */
+ SVGA_FIFO_CURSOR_ON,
+ SVGA_FIFO_CURSOR_X,
+ SVGA_FIFO_CURSOR_Y,
+ SVGA_FIFO_CURSOR_COUNT,
+ SVGA_FIFO_CURSOR_LAST_UPDATED,
-#define SVGA_FIFO_CAP_NONE 0
-#define SVGA_FIFO_CAP_FENCE (1<<0)
-#define SVGA_FIFO_CAP_ACCELFRONT (1<<1)
-#define SVGA_FIFO_CAP_PITCHLOCK (1<<2)
-#define SVGA_FIFO_CAP_VIDEO (1<<3)
-#define SVGA_FIFO_CAP_CURSOR_BYPASS_3 (1<<4)
-#define SVGA_FIFO_CAP_ESCAPE (1<<5)
-#define SVGA_FIFO_CAP_RESERVE (1<<6)
-#define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7)
-#define SVGA_FIFO_CAP_GMR2 (1<<8)
-#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2
-#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1<<9)
-#define SVGA_FIFO_CAP_DEAD (1<<10)
+ SVGA_FIFO_RESERVED,
+ SVGA_FIFO_CURSOR_SCREEN_ID,
-/*
- * FIFO Flags
- *
- * Accel Front -- Driver should use front buffer only commands
- */
+ SVGA_FIFO_DEAD,
-#define SVGA_FIFO_FLAG_NONE 0
-#define SVGA_FIFO_FLAG_ACCELFRONT (1<<0)
-#define SVGA_FIFO_FLAG_RESERVED (1<<31) /* Internal use only */
+ SVGA_FIFO_3D_HWVERSION_REVISED,
-/*
- * FIFO reservation sentinel value
- */
+ SVGA_FIFO_3D_CAPS = 32,
+ SVGA_FIFO_3D_CAPS_LAST = 32 + 255,
-#define SVGA_FIFO_RESERVED_UNKNOWN 0xffffffff
+ SVGA_FIFO_GUEST_3D_HWVERSION,
+ SVGA_FIFO_FENCE_GOAL,
+ SVGA_FIFO_BUSY,
+ SVGA_FIFO_NUM_REGS
+};
-/*
- * ScreenDMA Register Values
- */
+#define SVGA_FIFO_3D_CAPS_SIZE (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1)
-#define SVGA_SCREENDMA_REG_UNDEFINED 0
-#define SVGA_SCREENDMA_REG_NOT_PRESENT 1
-#define SVGA_SCREENDMA_REG_PRESENT 2
-#define SVGA_SCREENDMA_REG_MAX 3
+#define SVGA3D_FIFO_CAPS_RECORD_DEVCAPS 0x100
+typedef uint32 SVGA3dFifoCapsRecordType;
-/*
- * Video overlay support
- */
+typedef uint32 SVGA3dFifoCapPair[2];
-#define SVGA_NUM_OVERLAY_UNITS 32
+#pragma pack(push, 1)
+typedef struct SVGA3dFifoCapsRecordHeader {
+ uint32 length;
+ SVGA3dFifoCapsRecordType type;
+} SVGA3dFifoCapsRecordHeader;
+#pragma pack(pop)
-/*
- * Video capabilities that the guest is currently using
- */
+#define SVGA_FIFO_EXTENDED_MANDATORY_REGS (SVGA_FIFO_3D_CAPS_LAST + 1)
-#define SVGA_VIDEO_FLAG_COLORKEY 0x0001
+#define SVGA_FIFO_CAP_NONE 0
+#define SVGA_FIFO_CAP_FENCE (1 << 0)
+#define SVGA_FIFO_CAP_ACCELFRONT (1 << 1)
+#define SVGA_FIFO_CAP_PITCHLOCK (1 << 2)
+#define SVGA_FIFO_CAP_VIDEO (1 << 3)
+#define SVGA_FIFO_CAP_CURSOR_BYPASS_3 (1 << 4)
+#define SVGA_FIFO_CAP_ESCAPE (1 << 5)
+#define SVGA_FIFO_CAP_RESERVE (1 << 6)
+#define SVGA_FIFO_CAP_SCREEN_OBJECT (1 << 7)
+#define SVGA_FIFO_CAP_GMR2 (1 << 8)
+#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2
+#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1 << 9)
+#define SVGA_FIFO_CAP_DEAD (1 << 10)
+#define SVGA_FIFO_FLAG_NONE 0
+#define SVGA_FIFO_FLAG_ACCELFRONT (1 << 0)
+#define SVGA_FIFO_FLAG_RESERVED (1 << 31)
-/*
- * Offsets for the video overlay registers
- */
+#define SVGA_FIFO_RESERVED_UNKNOWN 0xffffffff
-enum {
- SVGA_VIDEO_ENABLED = 0,
- SVGA_VIDEO_FLAGS,
- SVGA_VIDEO_DATA_OFFSET,
- SVGA_VIDEO_FORMAT,
- SVGA_VIDEO_COLORKEY,
- SVGA_VIDEO_SIZE, /* Deprecated */
- SVGA_VIDEO_WIDTH,
- SVGA_VIDEO_HEIGHT,
- SVGA_VIDEO_SRC_X,
- SVGA_VIDEO_SRC_Y,
- SVGA_VIDEO_SRC_WIDTH,
- SVGA_VIDEO_SRC_HEIGHT,
- SVGA_VIDEO_DST_X, /* Signed int32 */
- SVGA_VIDEO_DST_Y, /* Signed int32 */
- SVGA_VIDEO_DST_WIDTH,
- SVGA_VIDEO_DST_HEIGHT,
- SVGA_VIDEO_PITCH_1,
- SVGA_VIDEO_PITCH_2,
- SVGA_VIDEO_PITCH_3,
- SVGA_VIDEO_DATA_GMRID, /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */
- SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords */
- /* (SVGA_ID_INVALID) */
- SVGA_VIDEO_NUM_REGS
-};
+#define SVGA_SCREENDMA_REG_UNDEFINED 0
+#define SVGA_SCREENDMA_REG_NOT_PRESENT 1
+#define SVGA_SCREENDMA_REG_PRESENT 2
+#define SVGA_SCREENDMA_REG_MAX 3
+#define SVGA_NUM_OVERLAY_UNITS 32
-/*
- * SVGA Overlay Units
- *
- * width and height relate to the entire source video frame.
- * srcX, srcY, srcWidth and srcHeight represent subset of the source
- * video frame to be displayed.
- */
+#define SVGA_VIDEO_FLAG_COLORKEY 0x0001
-typedef
-#include "vmware_pack_begin.h"
-struct SVGAOverlayUnit {
- uint32 enabled;
- uint32 flags;
- uint32 dataOffset;
- uint32 format;
- uint32 colorKey;
- uint32 size;
- uint32 width;
- uint32 height;
- uint32 srcX;
- uint32 srcY;
- uint32 srcWidth;
- uint32 srcHeight;
- int32 dstX;
- int32 dstY;
- uint32 dstWidth;
- uint32 dstHeight;
- uint32 pitches[3];
- uint32 dataGMRId;
- uint32 dstScreenId;
-}
-#include "vmware_pack_end.h"
-SVGAOverlayUnit;
+enum {
+ SVGA_VIDEO_ENABLED = 0,
+ SVGA_VIDEO_FLAGS,
+ SVGA_VIDEO_DATA_OFFSET,
+ SVGA_VIDEO_FORMAT,
+ SVGA_VIDEO_COLORKEY,
+ SVGA_VIDEO_SIZE,
+ SVGA_VIDEO_WIDTH,
+ SVGA_VIDEO_HEIGHT,
+ SVGA_VIDEO_SRC_X,
+ SVGA_VIDEO_SRC_Y,
+ SVGA_VIDEO_SRC_WIDTH,
+ SVGA_VIDEO_SRC_HEIGHT,
+ SVGA_VIDEO_DST_X,
+ SVGA_VIDEO_DST_Y,
+ SVGA_VIDEO_DST_WIDTH,
+ SVGA_VIDEO_DST_HEIGHT,
+ SVGA_VIDEO_PITCH_1,
+ SVGA_VIDEO_PITCH_2,
+ SVGA_VIDEO_PITCH_3,
+ SVGA_VIDEO_DATA_GMRID,
+ SVGA_VIDEO_DST_SCREEN_ID,
+ SVGA_VIDEO_NUM_REGS
+};
+#pragma pack(push, 1)
+typedef struct SVGAOverlayUnit {
+ uint32 enabled;
+ uint32 flags;
+ uint32 dataOffset;
+ uint32 format;
+ uint32 colorKey;
+ uint32 size;
+ uint32 width;
+ uint32 height;
+ uint32 srcX;
+ uint32 srcY;
+ uint32 srcWidth;
+ uint32 srcHeight;
+ int32 dstX;
+ int32 dstY;
+ uint32 dstWidth;
+ uint32 dstHeight;
+ uint32 pitches[3];
+ uint32 dataGMRId;
+ uint32 dstScreenId;
+} SVGAOverlayUnit;
+#pragma pack(pop)
-/*
- * Guest display topology
- *
- * XXX: This structure is not part of the SVGA device's interface, and
- * doesn't really belong here.
- */
#define SVGA_INVALID_DISPLAY_ID ((uint32)-1)
typedef struct SVGADisplayTopology {
- uint16 displayId;
- uint16 isPrimary;
- uint32 width;
- uint32 height;
- uint32 positionX;
- uint32 positionY;
+ uint16 displayId;
+ uint16 isPrimary;
+ uint32 width;
+ uint32 height;
+ uint32 positionX;
+ uint32 positionY;
} SVGADisplayTopology;
-
-/*
- * SVGAScreenObject --
- *
- * This is a new way to represent a guest's multi-monitor screen or
- * Unity window. Screen objects are only supported if the
- * SVGA_FIFO_CAP_SCREEN_OBJECT capability bit is set.
- *
- * If Screen Objects are supported, they can be used to fully
- * replace the functionality provided by the framebuffer registers
- * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY.
- *
- * The screen object is a struct with guaranteed binary
- * compatibility. New flags can be added, and the struct may grow,
- * but existing fields must retain their meaning.
- *
- * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of
- * a SVGAGuestPtr that is used to back the screen contents. This
- * memory must come from the GFB. The guest is not allowed to
- * access the memory and doing so will have undefined results. The
- * backing store is required to be page aligned and the size is
- * padded to the next page boundry. The number of pages is:
- * (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE
- *
- * The pitch in the backingStore is required to be at least large
- * enough to hold a 32bbp scanline. It is recommended that the
- * driver pad bytesPerLine for a potential performance win.
- *
- * The cloneCount field is treated as a hint from the guest that
- * the user wants this display to be cloned, countCount times. A
- * value of zero means no cloning should happen.
- */
-
-#define SVGA_SCREEN_MUST_BE_SET (1 << 0)
-#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */
-#define SVGA_SCREEN_IS_PRIMARY (1 << 1)
+#define SVGA_SCREEN_MUST_BE_SET (1 << 0)
+#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET
+#define SVGA_SCREEN_IS_PRIMARY (1 << 1)
#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2)
-/*
- * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When the screen is
- * deactivated the base layer is defined to lose all contents and
- * become black. When a screen is deactivated the backing store is
- * optional. When set backingPtr and bytesPerLine will be ignored.
- */
-#define SVGA_SCREEN_DEACTIVATE (1 << 3)
+#define SVGA_SCREEN_DEACTIVATE (1 << 3)
-/*
- * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When this flag is set
- * the screen contents will be outputted as all black to the user
- * though the base layer contents is preserved. The screen base layer
- * can still be read and written to like normal though the no visible
- * effect will be seen by the user. When the flag is changed the
- * screen will be blanked or redrawn to the current contents as needed
- * without any extra commands from the driver. This flag only has an
- * effect when the screen is not deactivated.
- */
#define SVGA_SCREEN_BLANKING (1 << 4)
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 structSize; /* sizeof(SVGAScreenObject) */
- uint32 id;
- uint32 flags;
- struct {
- uint32 width;
- uint32 height;
- } size;
- struct {
- int32 x;
- int32 y;
- } root;
-
- /*
- * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional
- * with SVGA_FIFO_CAP_SCREEN_OBJECT.
- */
- SVGAGuestImage backingStore;
-
- /*
- * The cloneCount field is treated as a hint from the guest that
- * the user wants this display to be cloned, cloneCount times.
- *
- * A value of zero means no cloning should happen.
- */
- uint32 cloneCount;
-}
-#include "vmware_pack_end.h"
-SVGAScreenObject;
-
-
-/*
- * Commands in the command FIFO:
- *
- * Command IDs defined below are used for the traditional 2D FIFO
- * communication (not all commands are available for all versions of the
- * SVGA FIFO protocol).
- *
- * Note the holes in the command ID numbers: These commands have been
- * deprecated, and the old IDs must not be reused.
- *
- * Command IDs from 1000 to 2999 are reserved for use by the SVGA3D
- * protocol.
- *
- * Each command's parameters are described by the comments and
- * structs below.
- */
+#pragma pack(push, 1)
+typedef struct {
+ uint32 structSize;
+ uint32 id;
+ uint32 flags;
+ struct {
+ uint32 width;
+ uint32 height;
+ } size;
+ struct {
+ int32 x;
+ int32 y;
+ } root;
+
+ SVGAGuestImage backingStore;
+
+ uint32 cloneCount;
+} SVGAScreenObject;
+#pragma pack(pop)
typedef enum {
- SVGA_CMD_INVALID_CMD = 0,
- SVGA_CMD_UPDATE = 1,
- SVGA_CMD_RECT_COPY = 3,
- SVGA_CMD_RECT_ROP_COPY = 14,
- SVGA_CMD_DEFINE_CURSOR = 19,
- SVGA_CMD_DEFINE_ALPHA_CURSOR = 22,
- SVGA_CMD_UPDATE_VERBOSE = 25,
- SVGA_CMD_FRONT_ROP_FILL = 29,
- SVGA_CMD_FENCE = 30,
- SVGA_CMD_ESCAPE = 33,
- SVGA_CMD_DEFINE_SCREEN = 34,
- SVGA_CMD_DESTROY_SCREEN = 35,
- SVGA_CMD_DEFINE_GMRFB = 36,
- SVGA_CMD_BLIT_GMRFB_TO_SCREEN = 37,
- SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38,
- SVGA_CMD_ANNOTATION_FILL = 39,
- SVGA_CMD_ANNOTATION_COPY = 40,
- SVGA_CMD_DEFINE_GMR2 = 41,
- SVGA_CMD_REMAP_GMR2 = 42,
- SVGA_CMD_DEAD = 43,
- SVGA_CMD_DEAD_2 = 44,
- SVGA_CMD_NOP = 45,
- SVGA_CMD_NOP_ERROR = 46,
- SVGA_CMD_MAX
+ SVGA_CMD_INVALID_CMD = 0,
+ SVGA_CMD_UPDATE = 1,
+ SVGA_CMD_RECT_COPY = 3,
+ SVGA_CMD_RECT_ROP_COPY = 14,
+ SVGA_CMD_DEFINE_CURSOR = 19,
+ SVGA_CMD_DEFINE_ALPHA_CURSOR = 22,
+ SVGA_CMD_UPDATE_VERBOSE = 25,
+ SVGA_CMD_FRONT_ROP_FILL = 29,
+ SVGA_CMD_FENCE = 30,
+ SVGA_CMD_ESCAPE = 33,
+ SVGA_CMD_DEFINE_SCREEN = 34,
+ SVGA_CMD_DESTROY_SCREEN = 35,
+ SVGA_CMD_DEFINE_GMRFB = 36,
+ SVGA_CMD_BLIT_GMRFB_TO_SCREEN = 37,
+ SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38,
+ SVGA_CMD_ANNOTATION_FILL = 39,
+ SVGA_CMD_ANNOTATION_COPY = 40,
+ SVGA_CMD_DEFINE_GMR2 = 41,
+ SVGA_CMD_REMAP_GMR2 = 42,
+ SVGA_CMD_DEAD = 43,
+ SVGA_CMD_DEAD_2 = 44,
+ SVGA_CMD_NOP = 45,
+ SVGA_CMD_NOP_ERROR = 46,
+ SVGA_CMD_MAX
} SVGAFifoCmdId;
-#define SVGA_CMD_MAX_DATASIZE (256 * 1024)
-#define SVGA_CMD_MAX_ARGS 64
-
-
-/*
- * SVGA_CMD_UPDATE --
- *
- * This is a DMA transfer which copies from the Guest Framebuffer
- * (GFB) at BAR1 + SVGA_REG_FB_OFFSET to any screens which
- * intersect with the provided virtual rectangle.
- *
- * This command does not support using arbitrary guest memory as a
- * data source- it only works with the pre-defined GFB memory.
- * This command also does not support signed virtual coordinates.
- * If you have defined screens (using SVGA_CMD_DEFINE_SCREEN) with
- * negative root x/y coordinates, the negative portion of those
- * screens will not be reachable by this command.
- *
- * This command is not necessary when using framebuffer
- * traces. Traces are automatically enabled if the SVGA FIFO is
- * disabled, and you may explicitly enable/disable traces using
- * SVGA_REG_TRACES. With traces enabled, any write to the GFB will
- * automatically act as if a subsequent SVGA_CMD_UPDATE was issued.
- *
- * Traces and SVGA_CMD_UPDATE are the only supported ways to render
- * pseudocolor screen updates. The newer Screen Object commands
- * only support true color formats.
- *
- * Availability:
- * Always available.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 x;
- uint32 y;
- uint32 width;
- uint32 height;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdUpdate;
-
-
-/*
- * SVGA_CMD_RECT_COPY --
- *
- * Perform a rectangular DMA transfer from one area of the GFB to
- * another, and copy the result to any screens which intersect it.
- *
- * Availability:
- * SVGA_CAP_RECT_COPY
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 srcX;
- uint32 srcY;
- uint32 destX;
- uint32 destY;
- uint32 width;
- uint32 height;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdRectCopy;
-
-
-/*
- * SVGA_CMD_RECT_ROP_COPY --
- *
- * Perform a rectangular DMA transfer from one area of the GFB to
- * another, and copy the result to any screens which intersect it.
- * The value of ROP may only be SVGA_ROP_COPY, and this command is
- * only supported for backwards compatibility reasons.
- *
- * Availability:
- * SVGA_CAP_RECT_COPY
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 srcX;
- uint32 srcY;
- uint32 destX;
- uint32 destY;
- uint32 width;
- uint32 height;
- uint32 rop;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdRectRopCopy;
-
-
-/*
- * SVGA_CMD_DEFINE_CURSOR --
- *
- * Provide a new cursor image, as an AND/XOR mask.
- *
- * The recommended way to position the cursor overlay is by using
- * the SVGA_FIFO_CURSOR_* registers, supported by the
- * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability.
- *
- * Availability:
- * SVGA_CAP_CURSOR
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 id; /* Reserved, must be zero. */
- uint32 hotspotX;
- uint32 hotspotY;
- uint32 width;
- uint32 height;
- uint32 andMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */
- uint32 xorMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */
- /*
- * Followed by scanline data for AND mask, then XOR mask.
- * Each scanline is padded to a 32-bit boundary.
- */
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdDefineCursor;
-
-
-/*
- * SVGA_CMD_DEFINE_ALPHA_CURSOR --
- *
- * Provide a new cursor image, in 32-bit BGRA format.
- *
- * The recommended way to position the cursor overlay is by using
- * the SVGA_FIFO_CURSOR_* registers, supported by the
- * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability.
- *
- * Availability:
- * SVGA_CAP_ALPHA_CURSOR
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 id; /* Reserved, must be zero. */
- uint32 hotspotX;
- uint32 hotspotY;
- uint32 width;
- uint32 height;
- /* Followed by scanline data */
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdDefineAlphaCursor;
-
-
-/*
- * Provide a new large cursor image, as an AND/XOR mask.
- *
- * Should only be used for CursorMob functionality
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 hotspotX;
- uint32 hotspotY;
- uint32 width;
- uint32 height;
- uint32 andMaskDepth;
- uint32 xorMaskDepth;
- /*
- * Followed by scanline data for AND mask, then XOR mask.
- * Each scanline is padded to a 32-bit boundary.
- */
-}
-#include "vmware_pack_end.h"
-SVGAGBColorCursorHeader;
-
-
-/*
- * Provide a new large cursor image, in 32-bit BGRA format.
- *
- * Should only be used for CursorMob functionality
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 hotspotX;
- uint32 hotspotY;
- uint32 width;
- uint32 height;
- /* Followed by scanline data */
-}
-#include "vmware_pack_end.h"
-SVGAGBAlphaCursorHeader;
-
- /*
- * Define the SVGA guest backed cursor types
- */
+#define SVGA_CMD_MAX_DATASIZE (256 * 1024)
+#define SVGA_CMD_MAX_ARGS 64
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+} SVGAFifoCmdUpdate;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 srcX;
+ uint32 srcY;
+ uint32 destX;
+ uint32 destY;
+ uint32 width;
+ uint32 height;
+} SVGAFifoCmdRectCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 srcX;
+ uint32 srcY;
+ uint32 destX;
+ uint32 destY;
+ uint32 width;
+ uint32 height;
+ uint32 rop;
+} SVGAFifoCmdRectRopCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 id;
+ uint32 hotspotX;
+ uint32 hotspotY;
+ uint32 width;
+ uint32 height;
+ uint32 andMaskDepth;
+ uint32 xorMaskDepth;
+
+} SVGAFifoCmdDefineCursor;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 id;
+ uint32 hotspotX;
+ uint32 hotspotY;
+ uint32 width;
+ uint32 height;
+
+} SVGAFifoCmdDefineAlphaCursor;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 hotspotX;
+ uint32 hotspotY;
+ uint32 width;
+ uint32 height;
+ uint32 andMaskDepth;
+ uint32 xorMaskDepth;
+
+} SVGAGBColorCursorHeader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 hotspotX;
+ uint32 hotspotY;
+ uint32 width;
+ uint32 height;
+
+} SVGAGBAlphaCursorHeader;
+#pragma pack(pop)
typedef enum {
- SVGA_COLOR_CURSOR = 0,
- SVGA_ALPHA_CURSOR = 1,
+ SVGA_COLOR_CURSOR = 0,
+ SVGA_ALPHA_CURSOR = 1,
} SVGAGBCursorType;
-/*
- * Provide a new large cursor image.
- *
- * Should only be used for CursorMob functionality
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAGBCursorType type;
- union {
- SVGAGBColorCursorHeader colorHeader;
- SVGAGBAlphaCursorHeader alphaHeader;
- } header;
- uint32 sizeInBytes;
- /*
- * Followed by the cursor data
- */
-}
-#include "vmware_pack_end.h"
-SVGAGBCursorHeader;
-
-
-/*
- * SVGA_CMD_UPDATE_VERBOSE --
- *
- * Just like SVGA_CMD_UPDATE, but also provide a per-rectangle
- * 'reason' value, an opaque cookie which is used by internal
- * debugging tools. Third party drivers should not use this
- * command.
- *
- * Availability:
- * SVGA_CAP_EXTENDED_FIFO
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 x;
- uint32 y;
- uint32 width;
- uint32 height;
- uint32 reason;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdUpdateVerbose;
-
-
-/*
- * SVGA_CMD_FRONT_ROP_FILL --
- *
- * This is a hint which tells the SVGA device that the driver has
- * just filled a rectangular region of the GFB with a solid
- * color. Instead of reading these pixels from the GFB, the device
- * can assume that they all equal 'color'. This is primarily used
- * for remote desktop protocols.
- *
- * Availability:
- * SVGA_FIFO_CAP_ACCELFRONT
- */
-
-#define SVGA_ROP_COPY 0x03
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 color; /* In the same format as the GFB */
- uint32 x;
- uint32 y;
- uint32 width;
- uint32 height;
- uint32 rop; /* Must be SVGA_ROP_COPY */
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdFrontRopFill;
-
-
-/*
- * SVGA_CMD_FENCE --
- *
- * Insert a synchronization fence. When the SVGA device reaches
- * this command, it will copy the 'fence' value into the
- * SVGA_FIFO_FENCE register. It will also compare the fence against
- * SVGA_FIFO_FENCE_GOAL. If the fence matches the goal and the
- * SVGA_IRQFLAG_FENCE_GOAL interrupt is enabled, the device will
- * raise this interrupt.
- *
- * Availability:
- * SVGA_FIFO_FENCE for this command,
- * SVGA_CAP_IRQMASK for SVGA_FIFO_FENCE_GOAL.
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 fence;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdFence;
-
-
-/*
- * SVGA_CMD_ESCAPE --
- *
- * Send an extended or vendor-specific variable length command.
- * This is used for video overlay, third party plugins, and
- * internal debugging tools. See svga_escape.h
- *
- * Availability:
- * SVGA_FIFO_CAP_ESCAPE
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 nsid;
- uint32 size;
- /* followed by 'size' bytes of data */
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdEscape;
-
-
-/*
- * SVGA_CMD_DEFINE_SCREEN --
- *
- * Define or redefine an SVGAScreenObject. See the description of
- * SVGAScreenObject above. The video driver is responsible for
- * generating new screen IDs. They should be small positive
- * integers. The virtual device will have an implementation
- * specific upper limit on the number of screen IDs
- * supported. Drivers are responsible for recycling IDs. The first
- * valid ID is zero.
- *
- * - Interaction with other registers:
- *
- * For backwards compatibility, when the GFB mode registers (WIDTH,
- * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
- * deletes all screens other than screen #0, and redefines screen
- * #0 according to the specified mode. Drivers that use
- * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0.
- *
- * If you use screen objects, do not use the legacy multi-mon
- * registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*).
- *
- * Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAScreenObject screen; /* Variable-length according to version */
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdDefineScreen;
-
-
-/*
- * SVGA_CMD_DESTROY_SCREEN --
- *
- * Destroy an SVGAScreenObject. Its ID is immediately available for
- * re-use.
- *
- * Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 screenId;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdDestroyScreen;
-
-
-/*
- * SVGA_CMD_DEFINE_GMRFB --
- *
- * This command sets a piece of SVGA device state called the
- * Guest Memory Region Framebuffer, or GMRFB. The GMRFB is a
- * piece of light-weight state which identifies the location and
- * format of an image in guest memory or in BAR1. The GMRFB has
- * an arbitrary size, and it doesn't need to match the geometry
- * of the GFB or any screen object.
- *
- * The GMRFB can be redefined as often as you like. You could
- * always use the same GMRFB, you could redefine it before
- * rendering from a different guest screen, or you could even
- * redefine it before every blit.
- *
- * There are multiple ways to use this command. The simplest way is
- * to use it to move the framebuffer either to elsewhere in the GFB
- * (BAR1) memory region, or to a user-defined GMR. This lets a
- * driver use a framebuffer allocated entirely out of normal system
- * memory, which we encourage.
- *
- * Another way to use this command is to set up a ring buffer of
- * updates in GFB memory. If a driver wants to ensure that no
- * frames are skipped by the SVGA device, it is important that the
- * driver not modify the source data for a blit until the device is
- * done processing the command. One efficient way to accomplish
- * this is to use a ring of small DMA buffers. Each buffer is used
- * for one blit, then we move on to the next buffer in the
- * ring. The FENCE mechanism is used to protect each buffer from
- * re-use until the device is finished with that buffer's
- * corresponding blit.
- *
- * This command does not affect the meaning of SVGA_CMD_UPDATE.
- * UPDATEs always occur from the legacy GFB memory area. This
- * command has no support for pseudocolor GMRFBs. Currently only
- * true-color 15, 16, and 24-bit depths are supported. Future
- * devices may expose capabilities for additional framebuffer
- * formats.
- *
- * The default GMRFB value is undefined. Drivers must always send
- * this command at least once before performing any blit from the
- * GMRFB.
- *
- * Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAGuestPtr ptr;
- uint32 bytesPerLine;
- SVGAGMRImageFormat format;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdDefineGMRFB;
-
-
-/*
- * SVGA_CMD_BLIT_GMRFB_TO_SCREEN --
- *
- * This is a guest-to-host blit. It performs a DMA operation to
- * copy a rectangular region of pixels from the current GMRFB to
- * a ScreenObject.
- *
- * The destination coordinate may be specified relative to a
- * screen's origin. The provided screen ID must be valid.
- *
- * The SVGA device is guaranteed to finish reading from the GMRFB
- * by the time any subsequent FENCE commands are reached.
- *
- * This command consumes an annotation. See the
- * SVGA_CMD_ANNOTATION_* commands for details.
- *
- * Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGASignedPoint srcOrigin;
- SVGASignedRect destRect;
- uint32 destScreenId;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdBlitGMRFBToScreen;
-
-
-/*
- * SVGA_CMD_BLIT_SCREEN_TO_GMRFB --
- *
- * This is a host-to-guest blit. It performs a DMA operation to
- * copy a rectangular region of pixels from a single ScreenObject
- * back to the current GMRFB.
- *
- * The source coordinate is specified relative to a screen's
- * origin. The provided screen ID must be valid. If any parameters
- * are invalid, the resulting pixel values are undefined.
- *
- * The SVGA device is guaranteed to finish writing to the GMRFB by
- * the time any subsequent FENCE commands are reached.
- *
- * Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGASignedPoint destOrigin;
- SVGASignedRect srcRect;
- uint32 srcScreenId;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdBlitScreenToGMRFB;
-
-
-/*
- * SVGA_CMD_ANNOTATION_FILL --
- *
- * The annotation commands have been deprecated, should not be used
- * by new drivers. They used to provide performance hints to the SVGA
- * device about the content of screen updates, but newer SVGA devices
- * ignore these.
- *
- * Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGAColorBGRX color;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdAnnotationFill;
-
-
-/*
- * SVGA_CMD_ANNOTATION_COPY --
- *
- * The annotation commands have been deprecated, should not be used
- * by new drivers. They used to provide performance hints to the SVGA
- * device about the content of screen updates, but newer SVGA devices
- * ignore these.
- *
- * Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- SVGASignedPoint srcOrigin;
- uint32 srcScreenId;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdAnnotationCopy;
-
-
-/*
- * SVGA_CMD_DEFINE_GMR2 --
- *
- * Define guest memory region v2. See the description of GMRs above.
- *
- * Availability:
- * SVGA_CAP_GMR2
- */
-
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 gmrId;
- uint32 numPages;
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdDefineGMR2;
-
-
-/*
- * SVGA_CMD_REMAP_GMR2 --
- *
- * Remap guest memory region v2. See the description of GMRs above.
- *
- * This command allows guest to modify a portion of an existing GMR by
- * invalidating it or reassigning it to different guest physical pages.
- * The pages are identified by physical page number (PPN). The pages
- * are assumed to be pinned and valid for DMA operations.
- *
- * Description of command flags:
- *
- * SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR.
- * The PPN list must not overlap with the remap region (this can be
- * handled trivially by referencing a separate GMR). If flag is
- * disabled, PPN list is appended to SVGARemapGMR command.
- *
- * SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise
- * it is in PPN32 format.
- *
- * SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry.
- * A single PPN can be used to invalidate a portion of a GMR or
- * map it to to a single guest scratch page.
- *
- * Availability:
- * SVGA_CAP_GMR2
- */
+#pragma pack(push, 1)
+typedef struct {
+ SVGAGBCursorType type;
+ union {
+ SVGAGBColorCursorHeader colorHeader;
+ SVGAGBAlphaCursorHeader alphaHeader;
+ } header;
+ uint32 sizeInBytes;
+
+} SVGAGBCursorHeader;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+ uint32 reason;
+} SVGAFifoCmdUpdateVerbose;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 color;
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+ uint32 rop;
+} SVGAFifoCmdFrontRopFill;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 fence;
+} SVGAFifoCmdFence;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 nsid;
+ uint32 size;
+
+} SVGAFifoCmdEscape;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAScreenObject screen;
+} SVGAFifoCmdDefineScreen;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 screenId;
+} SVGAFifoCmdDestroyScreen;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAGuestPtr ptr;
+ uint32 bytesPerLine;
+ SVGAGMRImageFormat format;
+} SVGAFifoCmdDefineGMRFB;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGASignedPoint srcOrigin;
+ SVGASignedRect destRect;
+ uint32 destScreenId;
+} SVGAFifoCmdBlitGMRFBToScreen;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGASignedPoint destOrigin;
+ SVGASignedRect srcRect;
+ uint32 srcScreenId;
+} SVGAFifoCmdBlitScreenToGMRFB;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGAColorBGRX color;
+} SVGAFifoCmdAnnotationFill;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ SVGASignedPoint srcOrigin;
+ uint32 srcScreenId;
+} SVGAFifoCmdAnnotationCopy;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct {
+ uint32 gmrId;
+ uint32 numPages;
+} SVGAFifoCmdDefineGMR2;
+#pragma pack(pop)
typedef enum {
- SVGA_REMAP_GMR2_PPN32 = 0,
- SVGA_REMAP_GMR2_VIA_GMR = (1 << 0),
- SVGA_REMAP_GMR2_PPN64 = (1 << 1),
- SVGA_REMAP_GMR2_SINGLE_PPN = (1 << 2),
+ SVGA_REMAP_GMR2_PPN32 = 0,
+ SVGA_REMAP_GMR2_VIA_GMR = (1 << 0),
+ SVGA_REMAP_GMR2_PPN64 = (1 << 1),
+ SVGA_REMAP_GMR2_SINGLE_PPN = (1 << 2),
} SVGARemapGMR2Flags;
-typedef
-#include "vmware_pack_begin.h"
-struct {
- uint32 gmrId;
- SVGARemapGMR2Flags flags;
- uint32 offsetPages; /* offset in pages to begin remap */
- uint32 numPages; /* number of pages to remap */
- /*
- * Followed by additional data depending on SVGARemapGMR2Flags.
- *
- * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows.
- * Otherwise an array of page descriptors in PPN32 or PPN64 format
- * (according to flag SVGA_REMAP_GMR2_PPN64) follows. If flag
- * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry.
- */
-}
-#include "vmware_pack_end.h"
-SVGAFifoCmdRemapGMR2;
-
-
-/*
- * Size of SVGA device memory such as frame buffer and FIFO.
- */
-#define SVGA_VRAM_MIN_SIZE (4 * 640 * 480) /* bytes */
-#define SVGA_VRAM_MIN_SIZE_3D (16 * 1024 * 1024)
-#define SVGA_VRAM_MAX_SIZE (128 * 1024 * 1024)
-#define SVGA_MEMORY_SIZE_MAX (1024 * 1024 * 1024)
-#define SVGA_FIFO_SIZE_MAX (2 * 1024 * 1024)
-#define SVGA_GRAPHICS_MEMORY_KB_MIN (32 * 1024)
+#pragma pack(push, 1)
+typedef struct {
+ uint32 gmrId;
+ SVGARemapGMR2Flags flags;
+ uint32 offsetPages;
+ uint32 numPages;
+
+} SVGAFifoCmdRemapGMR2;
+#pragma pack(pop)
+
+#define SVGA_VRAM_MIN_SIZE (4 * 640 * 480)
+#define SVGA_VRAM_MIN_SIZE_3D (16 * 1024 * 1024)
+#define SVGA_VRAM_MAX_SIZE (128 * 1024 * 1024)
+#define SVGA_MEMORY_SIZE_MAX (1024 * 1024 * 1024)
+#define SVGA_FIFO_SIZE_MAX (2 * 1024 * 1024)
+#define SVGA_GRAPHICS_MEMORY_KB_MIN (32 * 1024)
#define SVGA_GRAPHICS_MEMORY_KB_MAX_2GB (2 * 1024 * 1024)
#define SVGA_GRAPHICS_MEMORY_KB_MAX_3GB (3 * 1024 * 1024)
#define SVGA_GRAPHICS_MEMORY_KB_MAX_4GB (4 * 1024 * 1024)
#define SVGA_GRAPHICS_MEMORY_KB_MAX_8GB (8 * 1024 * 1024)
#define SVGA_GRAPHICS_MEMORY_KB_DEFAULT (256 * 1024)
-#define SVGA_VRAM_SIZE_W2K (64 * 1024 * 1024) /* 64 MB */
+#define SVGA_VRAM_SIZE_W2K (64 * 1024 * 1024)
#if defined(VMX86_SERVER)
-#define SVGA_VRAM_SIZE (4 * 1024 * 1024)
-#define SVGA_VRAM_SIZE_3D (64 * 1024 * 1024)
-#define SVGA_FIFO_SIZE (256 * 1024)
-#define SVGA_FIFO_SIZE_3D (516 * 1024)
-#define SVGA_MEMORY_SIZE_DEFAULT (160 * 1024 * 1024)
-#define SVGA_AUTODETECT_DEFAULT FALSE
+#define SVGA_VRAM_SIZE (4 * 1024 * 1024)
+#define SVGA_VRAM_SIZE_3D (64 * 1024 * 1024)
+#define SVGA_FIFO_SIZE (256 * 1024)
+#define SVGA_FIFO_SIZE_3D (516 * 1024)
+#define SVGA_MEMORY_SIZE_DEFAULT (160 * 1024 * 1024)
+#define SVGA_AUTODETECT_DEFAULT FALSE
#else
-#define SVGA_VRAM_SIZE (16 * 1024 * 1024)
-#define SVGA_VRAM_SIZE_3D SVGA_VRAM_MAX_SIZE
-#define SVGA_FIFO_SIZE (2 * 1024 * 1024)
-#define SVGA_FIFO_SIZE_3D SVGA_FIFO_SIZE
-#define SVGA_MEMORY_SIZE_DEFAULT (768 * 1024 * 1024)
-#define SVGA_AUTODETECT_DEFAULT TRUE
+#define SVGA_VRAM_SIZE (16 * 1024 * 1024)
+#define SVGA_VRAM_SIZE_3D SVGA_VRAM_MAX_SIZE
+#define SVGA_FIFO_SIZE (2 * 1024 * 1024)
+#define SVGA_FIFO_SIZE_3D SVGA_FIFO_SIZE
+#define SVGA_MEMORY_SIZE_DEFAULT (768 * 1024 * 1024)
+#define SVGA_AUTODETECT_DEFAULT TRUE
#endif
-#define SVGA_FIFO_SIZE_GBOBJECTS (256 * 1024)
-#define SVGA_VRAM_SIZE_GBOBJECTS (4 * 1024 * 1024)
-
-#define SVGA_PCI_REGS_PAGES (1)
+#define SVGA_FIFO_SIZE_GBOBJECTS (256 * 1024)
+#define SVGA_VRAM_SIZE_GBOBJECTS (4 * 1024 * 1024)
#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga_types.h b/drivers/gpu/drm/vmwgfx/device_include/svga_types.h
deleted file mode 100644
index beddccee40f6..000000000000
--- a/drivers/gpu/drm/vmwgfx/device_include/svga_types.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
-/**********************************************************
- * Copyright 2015 VMware, Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- **********************************************************/
-#ifndef _VM_BASIC_TYPES_H_
-#define _VM_BASIC_TYPES_H_
-#include <linux/kernel.h>
-
-typedef u32 uint32;
-typedef s32 int32;
-typedef u64 uint64;
-typedef u16 uint16;
-typedef s16 int16;
-typedef u8 uint8;
-typedef s8 int8;
-
-typedef uint64 PA;
-typedef uint32 PPN;
-typedef uint32 PPN32;
-typedef uint64 PPN64;
-
-typedef bool Bool;
-
-#define MAX_UINT64 U64_MAX
-#define MAX_UINT32 U32_MAX
-#define MAX_UINT16 U16_MAX
-
-#define CONST64U(x) x##ULL
-
-#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h b/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h
index 3a195e8106b3..1f6e3bbc6605 100644
--- a/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h
+++ b/drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h
@@ -1,7 +1,34 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VM_BASIC_TYPES_H_
-#define _VM_BASIC_TYPES_H_
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/**********************************************************
+ * Copyright 2015-2021 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+#ifndef VM_BASIC_TYPES_H
+#define VM_BASIC_TYPES_H
+
#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/page.h>
typedef u32 uint32;
typedef s32 int32;
@@ -13,10 +40,107 @@ typedef s8 int8;
typedef uint64 PA;
typedef uint32 PPN;
+typedef uint32 PPN32;
typedef uint64 PPN64;
typedef bool Bool;
+#define MAX_UINT64 U64_MAX
#define MAX_UINT32 U32_MAX
+#define MAX_UINT16 U16_MAX
+
+#define CONST64U(x) x##ULL
+
+#ifndef MBYTES_SHIFT
+#define MBYTES_SHIFT 20
+#endif
+#ifndef MBYTES_2_BYTES
+#define MBYTES_2_BYTES(_nbytes) ((uint64)(_nbytes) << MBYTES_SHIFT)
+#endif
+
+/*
+ * MKS Guest Stats types
+ */
+
+typedef struct MKSGuestStatCounter {
+ atomic64_t count;
+} MKSGuestStatCounter;
+
+typedef struct MKSGuestStatCounterTime {
+ MKSGuestStatCounter counter;
+ atomic64_t selfCycles;
+ atomic64_t totalCycles;
+} MKSGuestStatCounterTime;
+
+/*
+ * Flags for MKSGuestStatInfoEntry::flags below
+ */
+
+#define MKS_GUEST_STAT_FLAG_NONE 0
+#define MKS_GUEST_STAT_FLAG_TIME (1U << 0)
+
+typedef __attribute__((aligned(32))) struct MKSGuestStatInfoEntry {
+ union {
+ const char *s;
+ uint64 u;
+ } name;
+ union {
+ const char *s;
+ uint64 u;
+ } description;
+ uint64 flags;
+ union {
+ MKSGuestStatCounter *counter;
+ MKSGuestStatCounterTime *counterTime;
+ uint64 u;
+ } stat;
+} MKSGuestStatInfoEntry;
+
+#define INVALID_PPN64 ((PPN64)0x000fffffffffffffULL)
+
+#define MKS_GUEST_STAT_INSTANCE_DESC_LENGTH 1024
+#define MKS_GUEST_STAT_INSTANCE_MAX_STATS 4096
+#define MKS_GUEST_STAT_INSTANCE_MAX_STAT_PPNS \
+ (PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
+ sizeof(MKSGuestStatCounterTime)))
+#define MKS_GUEST_STAT_INSTANCE_MAX_INFO_PPNS \
+ (PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
+ sizeof(MKSGuestStatInfoEntry)))
+#define MKS_GUEST_STAT_AVERAGE_NAME_LENGTH 40
+#define MKS_GUEST_STAT_INSTANCE_MAX_STRS_PPNS \
+ (PFN_UP(MKS_GUEST_STAT_INSTANCE_MAX_STATS * \
+ MKS_GUEST_STAT_AVERAGE_NAME_LENGTH))
+
+/*
+ * The MKSGuestStatInstanceDescriptor is used as main interface to
+ * communicate guest stats back to the host code. The guest must
+ * allocate an instance of this structure at the start of a page and
+ * provide the physical address to the host. From there the host code
+ * can walk this structure to find other (pinned) pages containing the
+ * stats data.
+ *
+ * Since the MKSGuestStatInfoEntry structures contain userlevel
+ * pointers, the InstanceDescriptor also contains pointers to the
+ * begining of these sections allowing the host side code to correctly
+ * interpret the pointers.
+ *
+ * Because the host side code never acknowledges anything back to the
+ * guest there is no strict requirement to maintain compatability
+ * across releases. If the interface changes the host might not be
+ * able to log stats, but the guest will continue to run normally.
+ */
+
+typedef struct MKSGuestStatInstanceDescriptor {
+ uint64 reservedMBZ; /* must be zero for now. */
+ uint64 statStartVA; /* VA of the start of the stats section. */
+ uint64 strsStartVA; /* VA of the start of the strings section. */
+ uint64 statLength; /* length of the stats section in bytes. */
+ uint64 infoLength; /* length of the info entry section in bytes. */
+ uint64 strsLength; /* length of the strings section in bytes. */
+ PPN64 statPPNs[MKS_GUEST_STAT_INSTANCE_MAX_STAT_PPNS]; /* stat counters */
+ PPN64 infoPPNs[MKS_GUEST_STAT_INSTANCE_MAX_INFO_PPNS]; /* stat info */
+ PPN64 strsPPNs[MKS_GUEST_STAT_INSTANCE_MAX_STRS_PPNS]; /* strings */
+ char description[MKS_GUEST_STAT_INSTANCE_DESC_LENGTH];
+} MKSGuestStatInstanceDescriptor;
#endif
diff --git a/drivers/gpu/drm/vmwgfx/device_include/vmware_pack_begin.h b/drivers/gpu/drm/vmwgfx/device_include/vmware_pack_begin.h
deleted file mode 100644
index 75308bd0d970..000000000000
--- a/drivers/gpu/drm/vmwgfx/device_include/vmware_pack_begin.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <linux/compiler.h>
diff --git a/drivers/gpu/drm/vmwgfx/device_include/vmware_pack_end.h b/drivers/gpu/drm/vmwgfx/device_include/vmware_pack_end.h
deleted file mode 100644
index e93d6f28b68c..000000000000
--- a/drivers/gpu/drm/vmwgfx/device_include/vmware_pack_end.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-__packed
diff --git a/drivers/gpu/drm/vmwgfx/ttm_memory.c b/drivers/gpu/drm/vmwgfx/ttm_memory.c
index aeb0a22a2c34..edd17c30d5a5 100644
--- a/drivers/gpu/drm/vmwgfx/ttm_memory.c
+++ b/drivers/gpu/drm/vmwgfx/ttm_memory.c
@@ -435,8 +435,10 @@ int ttm_mem_global_init(struct ttm_mem_global *glob, struct device *dev)
si_meminfo(&si);
+ spin_lock(&glob->lock);
/* set it as 0 by default to keep original behavior of OOM */
glob->lower_mem_limit = 0;
+ spin_unlock(&glob->lock);
ret = ttm_mem_init_kernel_zone(glob, &si);
if (unlikely(ret != 0))
diff --git a/drivers/gpu/drm/vmwgfx/vmw_surface_cache.h b/drivers/gpu/drm/vmwgfx/vmw_surface_cache.h
new file mode 100644
index 000000000000..b0d87c5f58d8
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmw_surface_cache.h
@@ -0,0 +1,539 @@
+/**********************************************************
+ * Copyright 2021 VMware, Inc.
+ * SPDX-License-Identifier: GPL-2.0 OR MIT
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+#ifndef VMW_SURFACE_CACHE_H
+#define VMW_SURFACE_CACHE_H
+
+#include "device_include/svga3d_surfacedefs.h"
+
+#include <drm/vmwgfx_drm.h>
+
+static inline u32 clamped_umul32(u32 a, u32 b)
+{
+ uint64_t tmp = (uint64_t) a*b;
+ return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp;
+}
+
+/**
+ * vmw_surface_get_desc - Look up the appropriate SVGA3dSurfaceDesc for the
+ * given format.
+ */
+static inline const SVGA3dSurfaceDesc *
+vmw_surface_get_desc(SVGA3dSurfaceFormat format)
+{
+ if (format < ARRAY_SIZE(g_SVGA3dSurfaceDescs))
+ return &g_SVGA3dSurfaceDescs[format];
+
+ return &g_SVGA3dSurfaceDescs[SVGA3D_FORMAT_INVALID];
+}
+
+/**
+ * vmw_surface_get_mip_size - Given a base level size and the mip level,
+ * compute the size of the mip level.
+ */
+static inline struct drm_vmw_size
+vmw_surface_get_mip_size(struct drm_vmw_size base_level, u32 mip_level)
+{
+ struct drm_vmw_size size = {
+ .width = max_t(u32, base_level.width >> mip_level, 1),
+ .height = max_t(u32, base_level.height >> mip_level, 1),
+ .depth = max_t(u32, base_level.depth >> mip_level, 1)
+ };
+
+ return size;
+}
+
+static inline void
+vmw_surface_get_size_in_blocks(const SVGA3dSurfaceDesc *desc,
+ const struct drm_vmw_size *pixel_size,
+ SVGA3dSize *block_size)
+{
+ block_size->width = __KERNEL_DIV_ROUND_UP(pixel_size->width,
+ desc->blockSize.width);
+ block_size->height = __KERNEL_DIV_ROUND_UP(pixel_size->height,
+ desc->blockSize.height);
+ block_size->depth = __KERNEL_DIV_ROUND_UP(pixel_size->depth,
+ desc->blockSize.depth);
+}
+
+static inline bool
+vmw_surface_is_planar_surface(const SVGA3dSurfaceDesc *desc)
+{
+ return (desc->blockDesc & SVGA3DBLOCKDESC_PLANAR_YUV) != 0;
+}
+
+static inline u32
+vmw_surface_calculate_pitch(const SVGA3dSurfaceDesc *desc,
+ const struct drm_vmw_size *size)
+{
+ u32 pitch;
+ SVGA3dSize blocks;
+
+ vmw_surface_get_size_in_blocks(desc, size, &blocks);
+
+ pitch = blocks.width * desc->pitchBytesPerBlock;
+
+ return pitch;
+}
+
+/**
+ * vmw_surface_get_image_buffer_size - Calculates image buffer size.
+ *
+ * Return the number of bytes of buffer space required to store one image of a
+ * surface, optionally using the specified pitch.
+ *
+ * If pitch is zero, it is assumed that rows are tightly packed.
+ *
+ * This function is overflow-safe. If the result would have overflowed, instead
+ * we return MAX_UINT32.
+ */
+static inline u32
+vmw_surface_get_image_buffer_size(const SVGA3dSurfaceDesc *desc,
+ const struct drm_vmw_size *size,
+ u32 pitch)
+{
+ SVGA3dSize image_blocks;
+ u32 slice_size, total_size;
+
+ vmw_surface_get_size_in_blocks(desc, size, &image_blocks);
+
+ if (vmw_surface_is_planar_surface(desc)) {
+ total_size = clamped_umul32(image_blocks.width,
+ image_blocks.height);
+ total_size = clamped_umul32(total_size, image_blocks.depth);
+ total_size = clamped_umul32(total_size, desc->bytesPerBlock);
+ return total_size;
+ }
+
+ if (pitch == 0)
+ pitch = vmw_surface_calculate_pitch(desc, size);
+
+ slice_size = clamped_umul32(image_blocks.height, pitch);
+ total_size = clamped_umul32(slice_size, image_blocks.depth);
+
+ return total_size;
+}
+
+/**
+ * vmw_surface_get_serialized_size - Get the serialized size for the image.
+ */
+static inline u32
+vmw_surface_get_serialized_size(SVGA3dSurfaceFormat format,
+ struct drm_vmw_size base_level_size,
+ u32 num_mip_levels,
+ u32 num_layers)
+{
+ const SVGA3dSurfaceDesc *desc = vmw_surface_get_desc(format);
+ u32 total_size = 0;
+ u32 mip;
+
+ for (mip = 0; mip < num_mip_levels; mip++) {
+ struct drm_vmw_size size =
+ vmw_surface_get_mip_size(base_level_size, mip);
+ total_size += vmw_surface_get_image_buffer_size(desc,
+ &size, 0);
+ }
+
+ return total_size * num_layers;
+}
+
+/**
+ * vmw_surface_get_serialized_size_extended - Returns the number of bytes
+ * required for a surface with given parameters. Support for sample count.
+ */
+static inline u32
+vmw_surface_get_serialized_size_extended(SVGA3dSurfaceFormat format,
+ struct drm_vmw_size base_level_size,
+ u32 num_mip_levels,
+ u32 num_layers,
+ u32 num_samples)
+{
+ uint64_t total_size =
+ vmw_surface_get_serialized_size(format,
+ base_level_size,
+ num_mip_levels,
+ num_layers);
+ total_size *= max_t(u32, 1, num_samples);
+
+ return min_t(uint64_t, total_size, (uint64_t)U32_MAX);
+}
+
+/**
+ * vmw_surface_get_pixel_offset - Compute the offset (in bytes) to a pixel
+ * in an image (or volume).
+ *
+ * @width: The image width in pixels.
+ * @height: The image height in pixels
+ */
+static inline u32
+vmw_surface_get_pixel_offset(SVGA3dSurfaceFormat format,
+ u32 width, u32 height,
+ u32 x, u32 y, u32 z)
+{
+ const SVGA3dSurfaceDesc *desc = vmw_surface_get_desc(format);
+ const u32 bw = desc->blockSize.width, bh = desc->blockSize.height;
+ const u32 bd = desc->blockSize.depth;
+ const u32 rowstride = __KERNEL_DIV_ROUND_UP(width, bw) *
+ desc->bytesPerBlock;
+ const u32 imgstride = __KERNEL_DIV_ROUND_UP(height, bh) * rowstride;
+ const u32 offset = (z / bd * imgstride +
+ y / bh * rowstride +
+ x / bw * desc->bytesPerBlock);
+ return offset;
+}
+
+static inline u32
+vmw_surface_get_image_offset(SVGA3dSurfaceFormat format,
+ struct drm_vmw_size baseLevelSize,
+ u32 numMipLevels,
+ u32 face,
+ u32 mip)
+
+{
+ u32 offset;
+ u32 mipChainBytes;
+ u32 mipChainBytesToLevel;
+ u32 i;
+ const SVGA3dSurfaceDesc *desc;
+ struct drm_vmw_size mipSize;
+ u32 bytes;
+
+ desc = vmw_surface_get_desc(format);
+
+ mipChainBytes = 0;
+ mipChainBytesToLevel = 0;
+ for (i = 0; i < numMipLevels; i++) {
+ mipSize = vmw_surface_get_mip_size(baseLevelSize, i);
+ bytes = vmw_surface_get_image_buffer_size(desc, &mipSize, 0);
+ mipChainBytes += bytes;
+ if (i < mip)
+ mipChainBytesToLevel += bytes;
+ }
+
+ offset = mipChainBytes * face + mipChainBytesToLevel;
+
+ return offset;
+}
+
+
+/**
+ * vmw_surface_is_gb_screen_target_format - Is the specified format usable as
+ * a ScreenTarget?
+ * (with just the GBObjects cap-bit
+ * set)
+ * @format: format to queried
+ *
+ * RETURNS:
+ * true if queried format is valid for screen targets
+ */
+static inline bool
+vmw_surface_is_gb_screen_target_format(SVGA3dSurfaceFormat format)
+{
+ return (format == SVGA3D_X8R8G8B8 ||
+ format == SVGA3D_A8R8G8B8 ||
+ format == SVGA3D_R5G6B5 ||
+ format == SVGA3D_X1R5G5B5 ||
+ format == SVGA3D_A1R5G5B5 ||
+ format == SVGA3D_P8);
+}
+
+
+/**
+ * vmw_surface_is_dx_screen_target_format - Is the specified format usable as
+ * a ScreenTarget?
+ * (with DX10 enabled)
+ *
+ * @format: format to queried
+ *
+ * Results:
+ * true if queried format is valid for screen targets
+ */
+static inline bool
+vmw_surface_is_dx_screen_target_format(SVGA3dSurfaceFormat format)
+{
+ return (format == SVGA3D_R8G8B8A8_UNORM ||
+ format == SVGA3D_B8G8R8A8_UNORM ||
+ format == SVGA3D_B8G8R8X8_UNORM);
+}
+
+
+/**
+ * vmw_surface_is_screen_target_format - Is the specified format usable as a
+ * ScreenTarget?
+ * (for some combination of caps)
+ *
+ * @format: format to queried
+ *
+ * Results:
+ * true if queried format is valid for screen targets
+ */
+static inline bool
+vmw_surface_is_screen_target_format(SVGA3dSurfaceFormat format)
+{
+ if (vmw_surface_is_gb_screen_target_format(format)) {
+ return true;
+ }
+ return vmw_surface_is_dx_screen_target_format(format);
+}
+
+/**
+ * struct vmw_surface_mip - Mimpmap level information
+ * @bytes: Bytes required in the backing store of this mipmap level.
+ * @img_stride: Byte stride per image.
+ * @row_stride: Byte stride per block row.
+ * @size: The size of the mipmap.
+ */
+struct vmw_surface_mip {
+ size_t bytes;
+ size_t img_stride;
+ size_t row_stride;
+ struct drm_vmw_size size;
+
+};
+
+/**
+ * struct vmw_surface_cache - Cached surface information
+ * @desc: Pointer to the surface descriptor
+ * @mip: Array of mipmap level information. Valid size is @num_mip_levels.
+ * @mip_chain_bytes: Bytes required in the backing store for the whole chain
+ * of mip levels.
+ * @sheet_bytes: Bytes required in the backing store for a sheet
+ * representing a single sample.
+ * @num_mip_levels: Valid size of the @mip array. Number of mipmap levels in
+ * a chain.
+ * @num_layers: Number of slices in an array texture or number of faces in
+ * a cubemap texture.
+ */
+struct vmw_surface_cache {
+ const SVGA3dSurfaceDesc *desc;
+ struct vmw_surface_mip mip[DRM_VMW_MAX_MIP_LEVELS];
+ size_t mip_chain_bytes;
+ size_t sheet_bytes;
+ u32 num_mip_levels;
+ u32 num_layers;
+};
+
+/**
+ * struct vmw_surface_loc - Surface location
+ * @sheet: The multisample sheet.
+ * @sub_resource: Surface subresource. Defined as layer * num_mip_levels +
+ * mip_level.
+ * @x: X coordinate.
+ * @y: Y coordinate.
+ * @z: Z coordinate.
+ */
+struct vmw_surface_loc {
+ u32 sheet;
+ u32 sub_resource;
+ u32 x, y, z;
+};
+
+/**
+ * vmw_surface_subres - Compute the subresource from layer and mipmap.
+ * @cache: Surface layout data.
+ * @mip_level: The mipmap level.
+ * @layer: The surface layer (face or array slice).
+ *
+ * Return: The subresource.
+ */
+static inline u32 vmw_surface_subres(const struct vmw_surface_cache *cache,
+ u32 mip_level, u32 layer)
+{
+ return cache->num_mip_levels * layer + mip_level;
+}
+
+/**
+ * vmw_surface_setup_cache - Build a surface cache entry
+ * @size: The surface base level dimensions.
+ * @format: The surface format.
+ * @num_mip_levels: Number of mipmap levels.
+ * @num_layers: Number of layers.
+ * @cache: Pointer to a struct vmw_surface_cach object to be filled in.
+ *
+ * Return: Zero on success, -EINVAL on invalid surface layout.
+ */
+static inline int vmw_surface_setup_cache(const struct drm_vmw_size *size,
+ SVGA3dSurfaceFormat format,
+ u32 num_mip_levels,
+ u32 num_layers,
+ u32 num_samples,
+ struct vmw_surface_cache *cache)
+{
+ const SVGA3dSurfaceDesc *desc;
+ u32 i;
+
+ memset(cache, 0, sizeof(*cache));
+ cache->desc = desc = vmw_surface_get_desc(format);
+ cache->num_mip_levels = num_mip_levels;
+ cache->num_layers = num_layers;
+ for (i = 0; i < cache->num_mip_levels; i++) {
+ struct vmw_surface_mip *mip = &cache->mip[i];
+
+ mip->size = vmw_surface_get_mip_size(*size, i);
+ mip->bytes = vmw_surface_get_image_buffer_size
+ (desc, &mip->size, 0);
+ mip->row_stride =
+ __KERNEL_DIV_ROUND_UP(mip->size.width,
+ desc->blockSize.width) *
+ desc->bytesPerBlock * num_samples;
+ if (!mip->row_stride)
+ goto invalid_dim;
+
+ mip->img_stride =
+ __KERNEL_DIV_ROUND_UP(mip->size.height,
+ desc->blockSize.height) *
+ mip->row_stride;
+ if (!mip->img_stride)
+ goto invalid_dim;
+
+ cache->mip_chain_bytes += mip->bytes;
+ }
+ cache->sheet_bytes = cache->mip_chain_bytes * num_layers;
+ if (!cache->sheet_bytes)
+ goto invalid_dim;
+
+ return 0;
+
+invalid_dim:
+ VMW_DEBUG_USER("Invalid surface layout for dirty tracking.\n");
+ return -EINVAL;
+}
+
+/**
+ * vmw_surface_get_loc - Get a surface location from an offset into the
+ * backing store
+ * @cache: Surface layout data.
+ * @loc: Pointer to a struct vmw_surface_loc to be filled in.
+ * @offset: Offset into the surface backing store.
+ */
+static inline void
+vmw_surface_get_loc(const struct vmw_surface_cache *cache,
+ struct vmw_surface_loc *loc,
+ size_t offset)
+{
+ const struct vmw_surface_mip *mip = &cache->mip[0];
+ const SVGA3dSurfaceDesc *desc = cache->desc;
+ u32 layer;
+ int i;
+
+ loc->sheet = offset / cache->sheet_bytes;
+ offset -= loc->sheet * cache->sheet_bytes;
+
+ layer = offset / cache->mip_chain_bytes;
+ offset -= layer * cache->mip_chain_bytes;
+ for (i = 0; i < cache->num_mip_levels; ++i, ++mip) {
+ if (mip->bytes > offset)
+ break;
+ offset -= mip->bytes;
+ }
+
+ loc->sub_resource = vmw_surface_subres(cache, i, layer);
+ loc->z = offset / mip->img_stride;
+ offset -= loc->z * mip->img_stride;
+ loc->z *= desc->blockSize.depth;
+ loc->y = offset / mip->row_stride;
+ offset -= loc->y * mip->row_stride;
+ loc->y *= desc->blockSize.height;
+ loc->x = offset / desc->bytesPerBlock;
+ loc->x *= desc->blockSize.width;
+}
+
+/**
+ * vmw_surface_inc_loc - Clamp increment a surface location with one block
+ * size
+ * in each dimension.
+ * @loc: Pointer to a struct vmw_surface_loc to be incremented.
+ *
+ * When computing the size of a range as size = end - start, the range does not
+ * include the end element. However a location representing the last byte
+ * of a touched region in the backing store *is* included in the range.
+ * This function modifies such a location to match the end definition
+ * given as start + size which is the one used in a SVGA3dBox.
+ */
+static inline void
+vmw_surface_inc_loc(const struct vmw_surface_cache *cache,
+ struct vmw_surface_loc *loc)
+{
+ const SVGA3dSurfaceDesc *desc = cache->desc;
+ u32 mip = loc->sub_resource % cache->num_mip_levels;
+ const struct drm_vmw_size *size = &cache->mip[mip].size;
+
+ loc->sub_resource++;
+ loc->x += desc->blockSize.width;
+ if (loc->x > size->width)
+ loc->x = size->width;
+ loc->y += desc->blockSize.height;
+ if (loc->y > size->height)
+ loc->y = size->height;
+ loc->z += desc->blockSize.depth;
+ if (loc->z > size->depth)
+ loc->z = size->depth;
+}
+
+/**
+ * vmw_surface_min_loc - The start location in a subresource
+ * @cache: Surface layout data.
+ * @sub_resource: The subresource.
+ * @loc: Pointer to a struct vmw_surface_loc to be filled in.
+ */
+static inline void
+vmw_surface_min_loc(const struct vmw_surface_cache *cache,
+ u32 sub_resource,
+ struct vmw_surface_loc *loc)
+{
+ loc->sheet = 0;
+ loc->sub_resource = sub_resource;
+ loc->x = loc->y = loc->z = 0;
+}
+
+/**
+ * vmw_surface_min_loc - The end location in a subresource
+ * @cache: Surface layout data.
+ * @sub_resource: The subresource.
+ * @loc: Pointer to a struct vmw_surface_loc to be filled in.
+ *
+ * Following the end definition given in vmw_surface_inc_loc(),
+ * Compute the end location of a surface subresource.
+ */
+static inline void
+vmw_surface_max_loc(const struct vmw_surface_cache *cache,
+ u32 sub_resource,
+ struct vmw_surface_loc *loc)
+{
+ const struct drm_vmw_size *size;
+ u32 mip;
+
+ loc->sheet = 0;
+ loc->sub_resource = sub_resource + 1;
+ mip = sub_resource % cache->num_mip_levels;
+ size = &cache->mip[mip].size;
+ loc->x = size->width;
+ loc->y = size->height;
+ loc->z = size->depth;
+}
+
+
+#endif /* VMW_SURFACE_CACHE_H */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c b/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c
index 05b324825900..6f27d69bad0e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_binding.c
@@ -715,7 +715,7 @@ static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind)
* without checking which bindings actually need to be emitted
*
* @cbs: Pointer to the context's struct vmw_ctx_binding_state
- * @bi: Pointer to where the binding info array is stored in @cbs
+ * @biv: Pointer to where the binding info array is stored in @cbs
* @max_num: Maximum number of entries in the @bi array.
*
* Scans the @bi array for bindings and builds a buffer of view id data.
@@ -725,11 +725,9 @@ static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind)
* contains the command data.
*/
static void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs,
- const struct vmw_ctx_bindinfo *bi,
+ const struct vmw_ctx_bindinfo_view *biv,
u32 max_num)
{
- const struct vmw_ctx_bindinfo_view *biv =
- container_of(bi, struct vmw_ctx_bindinfo_view, bi);
unsigned long i;
cbs->bind_cmd_count = 0;
@@ -838,7 +836,7 @@ static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs,
*/
static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs)
{
- const struct vmw_ctx_bindinfo *loc = &cbs->render_targets[0].bi;
+ const struct vmw_ctx_bindinfo_view *loc = &cbs->render_targets[0];
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetRenderTargets body;
@@ -846,7 +844,7 @@ static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs)
size_t cmd_size, view_id_size;
const struct vmw_resource *ctx = vmw_cbs_context(cbs);
- vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS);
+ vmw_collect_view_ids(cbs, loc, SVGA3D_DX_MAX_RENDER_TARGETS);
view_id_size = cbs->bind_cmd_count*sizeof(uint32);
cmd_size = sizeof(*cmd) + view_id_size;
cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id);
@@ -874,7 +872,7 @@ static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs)
* without checking which bindings actually need to be emitted
*
* @cbs: Pointer to the context's struct vmw_ctx_binding_state
- * @bi: Pointer to where the binding info array is stored in @cbs
+ * @biso: Pointer to where the binding info array is stored in @cbs
* @max_num: Maximum number of entries in the @bi array.
*
* Scans the @bi array for bindings and builds a buffer of SVGA3dSoTarget data.
@@ -884,11 +882,9 @@ static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs)
* contains the command data.
*/
static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs,
- const struct vmw_ctx_bindinfo *bi,
+ const struct vmw_ctx_bindinfo_so_target *biso,
u32 max_num)
{
- const struct vmw_ctx_bindinfo_so_target *biso =
- container_of(bi, struct vmw_ctx_bindinfo_so_target, bi);
unsigned long i;
SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer;
@@ -919,7 +915,7 @@ static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs,
*/
static int vmw_emit_set_so_target(struct vmw_ctx_binding_state *cbs)
{
- const struct vmw_ctx_bindinfo *loc = &cbs->so_targets[0].bi;
+ const struct vmw_ctx_bindinfo_so_target *loc = &cbs->so_targets[0];
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetSOTargets body;
@@ -1066,7 +1062,7 @@ static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs)
static int vmw_emit_set_uav(struct vmw_ctx_binding_state *cbs)
{
- const struct vmw_ctx_bindinfo *loc = &cbs->ua_views[0].views[0].bi;
+ const struct vmw_ctx_bindinfo_view *loc = &cbs->ua_views[0].views[0];
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetUAViews body;
@@ -1096,7 +1092,7 @@ static int vmw_emit_set_uav(struct vmw_ctx_binding_state *cbs)
static int vmw_emit_set_cs_uav(struct vmw_ctx_binding_state *cbs)
{
- const struct vmw_ctx_bindinfo *loc = &cbs->ua_views[1].views[0].bi;
+ const struct vmw_ctx_bindinfo_view *loc = &cbs->ua_views[1].views[0];
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetCSUAViews body;
@@ -1444,7 +1440,7 @@ u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type)
static void vmw_binding_build_asserts(void)
{
BUILD_BUG_ON(SVGA3D_NUM_SHADERTYPE_DX10 != 3);
- BUILD_BUG_ON(SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS > SVGA3D_RT_MAX);
+ BUILD_BUG_ON(SVGA3D_DX_MAX_RENDER_TARGETS > SVGA3D_RT_MAX);
BUILD_BUG_ON(sizeof(uint32) != sizeof(u32));
/*
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index 362f56d5b12b..9e3e1429db94 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -405,7 +405,7 @@ static size_t vmw_bo_acc_size(struct vmw_private *dev_priv, size_t size,
bool user)
{
static size_t struct_size, user_struct_size;
- size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ size_t num_pages = PFN_UP(size);
size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *));
if (unlikely(struct_size == 0)) {
@@ -474,7 +474,6 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size,
struct ttm_placement *placement,
struct ttm_buffer_object **p_bo)
{
- unsigned npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
struct ttm_operation_ctx ctx = { false, false };
struct ttm_buffer_object *bo;
size_t acc_size;
@@ -485,7 +484,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size,
return -ENOMEM;
acc_size = ttm_round_pot(sizeof(*bo));
- acc_size += ttm_round_pot(npages * sizeof(void *));
+ acc_size += ttm_round_pot(PFN_UP(size) * sizeof(void *));
acc_size += ttm_round_pot(sizeof(struct ttm_tt));
ret = ttm_mem_global_alloc(&ttm_mem_glob, acc_size, &ctx);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
index 956b85e35cef..67db472d3493 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
@@ -30,6 +30,7 @@
#include <drm/ttm/ttm_placement.h>
#include "vmwgfx_drv.h"
+#include "vmwgfx_devcaps.h"
bool vmw_supports_3d(struct vmw_private *dev_priv)
{
@@ -45,10 +46,7 @@ bool vmw_supports_3d(struct vmw_private *dev_priv)
if (!dev_priv->has_mob)
return false;
- spin_lock(&dev_priv->cap_lock);
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_3D);
- result = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
- spin_unlock(&dev_priv->cap_lock);
+ result = vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_3D);
return (result != 0);
}
@@ -142,7 +140,8 @@ struct vmw_fifo_state *vmw_fifo_create(struct vmw_private *dev_priv)
min = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MIN);
fifo->capabilities = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_CAPABILITIES);
- DRM_INFO("Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
+ drm_info(&dev_priv->drm,
+ "Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
(unsigned int) max,
(unsigned int) min,
(unsigned int) fifo->capabilities);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
index 6bb4961e64a5..3c06df2a5474 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
@@ -358,8 +358,7 @@ static void vmw_cmdbuf_ctx_submit(struct vmw_cmdbuf_man *man,
break;
}
- list_del(&entry->list);
- list_add_tail(&entry->list, &ctx->hw_submitted);
+ list_move_tail(&entry->list, &ctx->hw_submitted);
ctx->num_hw_submitted++;
}
@@ -516,7 +515,7 @@ static void vmw_cmdbuf_work_func(struct work_struct *work)
struct vmw_cmdbuf_man *man =
container_of(work, struct vmw_cmdbuf_man, work);
struct vmw_cmdbuf_header *entry, *next;
- uint32_t dummy;
+ uint32_t dummy = 0;
bool send_fence = false;
struct list_head restart_head[SVGA_CB_CONTEXT_MAX];
int i;
@@ -802,7 +801,7 @@ static int vmw_cmdbuf_alloc_space(struct vmw_cmdbuf_man *man,
{
struct vmw_cmdbuf_alloc_info info;
- info.page_size = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ info.page_size = PFN_UP(size);
info.node = node;
info.done = false;
@@ -1272,7 +1271,8 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size)
* submissions to be able to free up space.
*/
man->default_size = VMW_CMDBUF_INLINE_SIZE;
- DRM_INFO("Using command buffers with %s pool.\n",
+ drm_info(&dev_priv->drm,
+ "Using command buffers with %s pool.\n",
(man->using_mob) ? "MOB" : "DMA");
return 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
index b262d61d839d..8381750db81b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
@@ -159,6 +159,7 @@ void vmw_cmdbuf_res_commit(struct list_head *list)
void vmw_cmdbuf_res_revert(struct list_head *list)
{
struct vmw_cmdbuf_res *entry, *next;
+ int ret;
list_for_each_entry_safe(entry, next, list, head) {
switch (entry->state) {
@@ -166,9 +167,9 @@ void vmw_cmdbuf_res_revert(struct list_head *list)
vmw_cmdbuf_res_free(entry->man, entry);
break;
case VMW_CMDBUF_RES_DEL:
- drm_ht_insert_item(&entry->man->resources, &entry->hash);
- list_del(&entry->head);
- list_add_tail(&entry->head, &entry->man->list);
+ ret = drm_ht_insert_item(&entry->man->resources, &entry->hash);
+ BUG_ON(ret);
+ list_move_tail(&entry->head, &entry->man->list);
entry->state = VMW_CMDBUF_RES_COMMITTED;
break;
default:
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
index dffe3804ad3e..4446758b6880 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -185,7 +185,7 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv,
container_of(res, struct vmw_user_context, res);
res->backup_size = (dx ? sizeof(SVGADXContextMobFormat) :
- SVGA3D_CONTEXT_DATA_SIZE);
+ sizeof(SVGAGBContextData));
ret = vmw_resource_init(dev_priv, res, true,
res_free,
dx ? &vmw_dx_context_func :
@@ -259,7 +259,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
goto out_early;
}
- if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
+ if (unlikely(res->id >= SVGA3D_HB_MAX_CONTEXT_IDS)) {
DRM_ERROR("Out of hw context ids.\n");
vmw_resource_unreference(&res);
return -ENOMEM;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
index c84a16c1def0..17a98db00017 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
@@ -607,8 +607,7 @@ struct vmw_resource *vmw_cotable_alloc(struct vmw_private *dev_priv,
if (num_entries < co_info[type].min_initial_entries) {
vcotbl->res.backup_size = co_info[type].min_initial_entries *
co_info[type].size;
- vcotbl->res.backup_size =
- (vcotbl->res.backup_size + PAGE_SIZE - 1) & PAGE_MASK;
+ vcotbl->res.backup_size = PFN_ALIGN(vcotbl->res.backup_size);
}
vcotbl->scrubbed = true;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_devcaps.c b/drivers/gpu/drm/vmwgfx/vmwgfx_devcaps.c
new file mode 100644
index 000000000000..829df395c2ed
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_devcaps.c
@@ -0,0 +1,142 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/**************************************************************************
+ *
+ * Copyright 2021 VMware, Inc., Palo Alto, CA., USA
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_devcaps.h"
+
+#include "vmwgfx_drv.h"
+
+
+struct svga_3d_compat_cap {
+ SVGA3dFifoCapsRecordHeader header;
+ SVGA3dFifoCapPair pairs[SVGA3D_DEVCAP_MAX];
+};
+
+
+static u32 vmw_mask_legacy_multisample(unsigned int cap, u32 fmt_value)
+{
+ /*
+ * A version of user-space exists which use MULTISAMPLE_MASKABLESAMPLES
+ * to check the sample count supported by virtual device. Since there
+ * never was support for multisample count for backing MOB return 0.
+ *
+ * MULTISAMPLE_MASKABLESAMPLES devcap is marked as deprecated by virtual
+ * device.
+ */
+ if (cap == SVGA3D_DEVCAP_DEAD5)
+ return 0;
+
+ return fmt_value;
+}
+
+static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce,
+ size_t size)
+{
+ struct svga_3d_compat_cap *compat_cap =
+ (struct svga_3d_compat_cap *) bounce;
+ unsigned int i;
+ size_t pair_offset = offsetof(struct svga_3d_compat_cap, pairs);
+ unsigned int max_size;
+
+ if (size < pair_offset)
+ return -EINVAL;
+
+ max_size = (size - pair_offset) / sizeof(SVGA3dFifoCapPair);
+
+ if (max_size > SVGA3D_DEVCAP_MAX)
+ max_size = SVGA3D_DEVCAP_MAX;
+
+ compat_cap->header.length =
+ (pair_offset + max_size * sizeof(SVGA3dFifoCapPair)) / sizeof(u32);
+ compat_cap->header.type = SVGA3D_FIFO_CAPS_RECORD_DEVCAPS;
+
+ for (i = 0; i < max_size; ++i) {
+ compat_cap->pairs[i][0] = i;
+ compat_cap->pairs[i][1] = vmw_mask_legacy_multisample
+ (i, dev_priv->devcaps[i]);
+ }
+
+ return 0;
+}
+
+int vmw_devcaps_create(struct vmw_private *vmw)
+{
+ bool gb_objects = !!(vmw->capabilities & SVGA_CAP_GBOBJECTS);
+ uint32_t i;
+
+ if (gb_objects) {
+ vmw->devcaps = vzalloc(sizeof(uint32_t) * SVGA3D_DEVCAP_MAX);
+ if (!vmw->devcaps)
+ return -ENOMEM;
+ for (i = 0; i < SVGA3D_DEVCAP_MAX; ++i) {
+ vmw_write(vmw, SVGA_REG_DEV_CAP, i);
+ vmw->devcaps[i] = vmw_read(vmw, SVGA_REG_DEV_CAP);
+ }
+ }
+ return 0;
+}
+
+void vmw_devcaps_destroy(struct vmw_private *vmw)
+{
+ vfree(vmw->devcaps);
+ vmw->devcaps = NULL;
+}
+
+
+uint32 vmw_devcaps_size(const struct vmw_private *vmw,
+ bool gb_aware)
+{
+ bool gb_objects = !!(vmw->capabilities & SVGA_CAP_GBOBJECTS);
+ if (gb_objects && gb_aware)
+ return SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
+ else if (gb_objects)
+ return sizeof(struct svga_3d_compat_cap) +
+ sizeof(uint32_t);
+ else if (vmw->fifo_mem != NULL)
+ return (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) *
+ sizeof(uint32_t);
+ else
+ return 0;
+}
+
+int vmw_devcaps_copy(struct vmw_private *vmw, bool gb_aware,
+ void *dst, uint32_t dst_size)
+{
+ int ret;
+ bool gb_objects = !!(vmw->capabilities & SVGA_CAP_GBOBJECTS);
+ if (gb_objects && gb_aware) {
+ memcpy(dst, vmw->devcaps, dst_size);
+ } else if (gb_objects) {
+ ret = vmw_fill_compat_cap(vmw, dst, dst_size);
+ if (unlikely(ret != 0))
+ return ret;
+ } else if (vmw->fifo_mem) {
+ u32 *fifo_mem = vmw->fifo_mem;
+ memcpy(dst, &fifo_mem[SVGA_FIFO_3D_CAPS], dst_size);
+ } else
+ return -EINVAL;
+ return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_devcaps.h b/drivers/gpu/drm/vmwgfx/vmwgfx_devcaps.h
new file mode 100644
index 000000000000..f70e923ac3e6
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_devcaps.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/**************************************************************************
+ *
+ * Copyright 2021 VMware, Inc., Palo Alto, CA., USA
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _VMWGFX_DEVCAPS_H_
+#define _VMWGFX_DEVCAPS_H_
+
+#include "vmwgfx_drv.h"
+
+#include "device_include/svga_reg.h"
+
+int vmw_devcaps_create(struct vmw_private *vmw);
+void vmw_devcaps_destroy(struct vmw_private *vmw);
+uint32_t vmw_devcaps_size(const struct vmw_private *vmw, bool gb_aware);
+int vmw_devcaps_copy(struct vmw_private *vmw, bool gb_aware,
+ void *dst, uint32_t dst_size);
+
+static inline uint32_t vmw_devcap_get(struct vmw_private *vmw,
+ uint32_t devcap)
+{
+ bool gb_objects = !!(vmw->capabilities & SVGA_CAP_GBOBJECTS);
+ if (gb_objects)
+ return vmw->devcaps[devcap];
+ return 0;
+}
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 45aeeca9b8f6..ab9a1750e1df 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -42,7 +42,9 @@
#include "ttm_object.h"
#include "vmwgfx_binding.h"
+#include "vmwgfx_devcaps.h"
#include "vmwgfx_drv.h"
+#include "vmwgfx_mksstat.h"
#define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
@@ -148,102 +150,111 @@
#define DRM_IOCTL_VMW_MSG \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_MSG, \
struct drm_vmw_msg_arg)
-
-/*
- * The core DRM version of this macro doesn't account for
- * DRM_COMMAND_BASE.
- */
-
-#define VMW_IOCTL_DEF(ioctl, func, flags) \
- [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_IOCTL_##ioctl, flags, func}
+#define DRM_IOCTL_VMW_MKSSTAT_RESET \
+ DRM_IO(DRM_COMMAND_BASE + DRM_VMW_MKSSTAT_RESET)
+#define DRM_IOCTL_VMW_MKSSTAT_ADD \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_MKSSTAT_ADD, \
+ struct drm_vmw_mksstat_add_arg)
+#define DRM_IOCTL_VMW_MKSSTAT_REMOVE \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_MKSSTAT_REMOVE, \
+ struct drm_vmw_mksstat_remove_arg)
/*
* Ioctl definitions.
*/
static const struct drm_ioctl_desc vmw_ioctls[] = {
- VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_bo_alloc_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_bo_unref_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_CURSOR_BYPASS,
- vmw_kms_cursor_bypass_ioctl,
- DRM_MASTER),
-
- VMW_IOCTL_DEF(VMW_CONTROL_STREAM, vmw_overlay_ioctl,
- DRM_MASTER),
- VMW_IOCTL_DEF(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
- DRM_MASTER),
- VMW_IOCTL_DEF(VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
- DRM_MASTER),
-
- VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
- vmw_fence_obj_signaled_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
- DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GET_PARAM, vmw_getparam_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_ALLOC_DMABUF, vmw_bo_alloc_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_DMABUF, vmw_bo_unref_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_CURSOR_BYPASS,
+ vmw_kms_cursor_bypass_ioctl,
+ DRM_MASTER),
+
+ DRM_IOCTL_DEF_DRV(VMW_CONTROL_STREAM, vmw_overlay_ioctl,
+ DRM_MASTER),
+ DRM_IOCTL_DEF_DRV(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
+ DRM_MASTER),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
+ DRM_MASTER),
+
+ DRM_IOCTL_DEF_DRV(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_EXECBUF, vmw_execbuf_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_FENCE_SIGNALED,
+ vmw_fence_obj_signaled_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
+ DRM_RENDER_ALLOW),
/* these allow direct access to the framebuffers mark as master only */
- VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
- DRM_MASTER | DRM_AUTH),
- VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
- vmw_present_readback_ioctl,
- DRM_MASTER | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(VMW_PRESENT, vmw_present_ioctl,
+ DRM_MASTER | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(VMW_PRESENT_READBACK,
+ vmw_present_readback_ioctl,
+ DRM_MASTER | DRM_AUTH),
/*
* The permissions of the below ioctl are overridden in
* vmw_generic_ioctl(). We require either
* DRM_MASTER or capable(CAP_SYS_ADMIN).
*/
- VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
- vmw_kms_update_layout_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_CREATE_SHADER,
- vmw_shader_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_UNREF_SHADER,
- vmw_shader_destroy_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
- vmw_gb_surface_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
- vmw_gb_surface_reference_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_SYNCCPU,
- vmw_user_bo_synccpu_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT,
- vmw_extended_context_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE_EXT,
- vmw_gb_surface_define_ext_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GB_SURFACE_REF_EXT,
- vmw_gb_surface_reference_ext_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_MSG,
- vmw_msg_ioctl,
- DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UPDATE_LAYOUT,
+ vmw_kms_update_layout_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_CREATE_SHADER,
+ vmw_shader_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_SHADER,
+ vmw_shader_destroy_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_CREATE,
+ vmw_gb_surface_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_REF,
+ vmw_gb_surface_reference_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_SYNCCPU,
+ vmw_user_bo_synccpu_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_CREATE_EXTENDED_CONTEXT,
+ vmw_extended_context_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_CREATE_EXT,
+ vmw_gb_surface_define_ext_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_REF_EXT,
+ vmw_gb_surface_reference_ext_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_MSG,
+ vmw_msg_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_RESET,
+ vmw_mksstat_reset_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_ADD,
+ vmw_mksstat_add_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_REMOVE,
+ vmw_mksstat_remove_ioctl,
+ DRM_RENDER_ALLOW),
};
static const struct pci_device_id vmw_pci_id_list[] = {
@@ -254,7 +265,6 @@ static const struct pci_device_id vmw_pci_id_list[] = {
MODULE_DEVICE_TABLE(pci, vmw_pci_id_list);
static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);
-static int vmw_force_iommu;
static int vmw_restrict_iommu;
static int vmw_force_coherent;
static int vmw_restrict_dma_mask;
@@ -266,8 +276,6 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
module_param_named(enable_fbdev, enable_fbdev, int, 0600);
-MODULE_PARM_DESC(force_dma_api, "Force using the DMA API for TTM pages");
-module_param_named(force_dma_api, vmw_force_iommu, int, 0600);
MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages");
module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
@@ -278,62 +286,92 @@ MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
-static void vmw_print_capabilities2(uint32_t capabilities2)
+struct bitmap_name {
+ uint32 value;
+ const char *name;
+};
+
+static const struct bitmap_name cap1_names[] = {
+ { SVGA_CAP_RECT_COPY, "rect copy" },
+ { SVGA_CAP_CURSOR, "cursor" },
+ { SVGA_CAP_CURSOR_BYPASS, "cursor bypass" },
+ { SVGA_CAP_CURSOR_BYPASS_2, "cursor bypass 2" },
+ { SVGA_CAP_8BIT_EMULATION, "8bit emulation" },
+ { SVGA_CAP_ALPHA_CURSOR, "alpha cursor" },
+ { SVGA_CAP_3D, "3D" },
+ { SVGA_CAP_EXTENDED_FIFO, "extended fifo" },
+ { SVGA_CAP_MULTIMON, "multimon" },
+ { SVGA_CAP_PITCHLOCK, "pitchlock" },
+ { SVGA_CAP_IRQMASK, "irq mask" },
+ { SVGA_CAP_DISPLAY_TOPOLOGY, "display topology" },
+ { SVGA_CAP_GMR, "gmr" },
+ { SVGA_CAP_TRACES, "traces" },
+ { SVGA_CAP_GMR2, "gmr2" },
+ { SVGA_CAP_SCREEN_OBJECT_2, "screen object 2" },
+ { SVGA_CAP_COMMAND_BUFFERS, "command buffers" },
+ { SVGA_CAP_CMD_BUFFERS_2, "command buffers 2" },
+ { SVGA_CAP_GBOBJECTS, "gbobject" },
+ { SVGA_CAP_DX, "dx" },
+ { SVGA_CAP_HP_CMD_QUEUE, "hp cmd queue" },
+ { SVGA_CAP_NO_BB_RESTRICTION, "no bb restriction" },
+ { SVGA_CAP_CAP2_REGISTER, "cap2 register" },
+};
+
+
+static const struct bitmap_name cap2_names[] = {
+ { SVGA_CAP2_GROW_OTABLE, "grow otable" },
+ { SVGA_CAP2_INTRA_SURFACE_COPY, "intra surface copy" },
+ { SVGA_CAP2_DX2, "dx2" },
+ { SVGA_CAP2_GB_MEMSIZE_2, "gb memsize 2" },
+ { SVGA_CAP2_SCREENDMA_REG, "screendma reg" },
+ { SVGA_CAP2_OTABLE_PTDEPTH_2, "otable ptdepth2" },
+ { SVGA_CAP2_NON_MS_TO_MS_STRETCHBLT, "non ms to ms stretchblt" },
+ { SVGA_CAP2_CURSOR_MOB, "cursor mob" },
+ { SVGA_CAP2_MSHINT, "mshint" },
+ { SVGA_CAP2_CB_MAX_SIZE_4MB, "cb max size 4mb" },
+ { SVGA_CAP2_DX3, "dx3" },
+ { SVGA_CAP2_FRAME_TYPE, "frame type" },
+ { SVGA_CAP2_COTABLE_COPY, "cotable copy" },
+ { SVGA_CAP2_TRACE_FULL_FB, "trace full fb" },
+ { SVGA_CAP2_EXTRA_REGS, "extra regs" },
+ { SVGA_CAP2_LO_STAGING, "lo staging" },
+};
+
+static void vmw_print_bitmap(struct drm_device *drm,
+ const char *prefix, uint32_t bitmap,
+ const struct bitmap_name *bnames,
+ uint32_t num_names)
{
- DRM_INFO("Capabilities2:\n");
- if (capabilities2 & SVGA_CAP2_GROW_OTABLE)
- DRM_INFO(" Grow oTable.\n");
- if (capabilities2 & SVGA_CAP2_INTRA_SURFACE_COPY)
- DRM_INFO(" IntraSurface copy.\n");
- if (capabilities2 & SVGA_CAP2_DX3)
- DRM_INFO(" DX3.\n");
+ char buf[512];
+ uint32_t i;
+ uint32_t offset = 0;
+ for (i = 0; i < num_names; ++i) {
+ if ((bitmap & bnames[i].value) != 0) {
+ offset += snprintf(buf + offset,
+ ARRAY_SIZE(buf) - offset,
+ "%s, ", bnames[i].name);
+ bitmap &= ~bnames[i].value;
+ }
+ }
+
+ drm_info(drm, "%s: %s\n", prefix, buf);
+ if (bitmap != 0)
+ drm_dbg(drm, "%s: unknown enums: %x\n", prefix, bitmap);
}
-static void vmw_print_capabilities(uint32_t capabilities)
+
+static void vmw_print_sm_type(struct vmw_private *dev_priv)
{
- DRM_INFO("Capabilities:\n");
- if (capabilities & SVGA_CAP_RECT_COPY)
- DRM_INFO(" Rect copy.\n");
- if (capabilities & SVGA_CAP_CURSOR)
- DRM_INFO(" Cursor.\n");
- if (capabilities & SVGA_CAP_CURSOR_BYPASS)
- DRM_INFO(" Cursor bypass.\n");
- if (capabilities & SVGA_CAP_CURSOR_BYPASS_2)
- DRM_INFO(" Cursor bypass 2.\n");
- if (capabilities & SVGA_CAP_8BIT_EMULATION)
- DRM_INFO(" 8bit emulation.\n");
- if (capabilities & SVGA_CAP_ALPHA_CURSOR)
- DRM_INFO(" Alpha cursor.\n");
- if (capabilities & SVGA_CAP_3D)
- DRM_INFO(" 3D.\n");
- if (capabilities & SVGA_CAP_EXTENDED_FIFO)
- DRM_INFO(" Extended Fifo.\n");
- if (capabilities & SVGA_CAP_MULTIMON)
- DRM_INFO(" Multimon.\n");
- if (capabilities & SVGA_CAP_PITCHLOCK)
- DRM_INFO(" Pitchlock.\n");
- if (capabilities & SVGA_CAP_IRQMASK)
- DRM_INFO(" Irq mask.\n");
- if (capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)
- DRM_INFO(" Display Topology.\n");
- if (capabilities & SVGA_CAP_GMR)
- DRM_INFO(" GMR.\n");
- if (capabilities & SVGA_CAP_TRACES)
- DRM_INFO(" Traces.\n");
- if (capabilities & SVGA_CAP_GMR2)
- DRM_INFO(" GMR2.\n");
- if (capabilities & SVGA_CAP_SCREEN_OBJECT_2)
- DRM_INFO(" Screen Object 2.\n");
- if (capabilities & SVGA_CAP_COMMAND_BUFFERS)
- DRM_INFO(" Command Buffers.\n");
- if (capabilities & SVGA_CAP_CMD_BUFFERS_2)
- DRM_INFO(" Command Buffers 2.\n");
- if (capabilities & SVGA_CAP_GBOBJECTS)
- DRM_INFO(" Guest Backed Resources.\n");
- if (capabilities & SVGA_CAP_DX)
- DRM_INFO(" DX Features.\n");
- if (capabilities & SVGA_CAP_HP_CMD_QUEUE)
- DRM_INFO(" HP Command Queue.\n");
+ static const char *names[] = {
+ [VMW_SM_LEGACY] = "Legacy",
+ [VMW_SM_4] = "SM4",
+ [VMW_SM_4_1] = "SM4_1",
+ [VMW_SM_5] = "SM_5",
+ [VMW_SM_MAX] = "Invalid"
+ };
+ BUILD_BUG_ON(ARRAY_SIZE(names) != (VMW_SM_MAX + 1));
+ drm_info(&dev_priv->drm, "Available shader model: %s.\n",
+ names[dev_priv->sm_type]);
}
/**
@@ -400,10 +438,6 @@ static int vmw_device_init(struct vmw_private *dev_priv)
{
bool uses_fb_traces = false;
- DRM_INFO("width %d\n", vmw_read(dev_priv, SVGA_REG_WIDTH));
- DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT));
- DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL));
-
dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
@@ -627,7 +661,6 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
static int vmw_dma_select_mode(struct vmw_private *dev_priv)
{
static const char *names[vmw_dma_map_max] = {
- [vmw_dma_phys] = "Using physical TTM page addresses.",
[vmw_dma_alloc_coherent] = "Using coherent TTM pages.",
[vmw_dma_map_populate] = "Caching DMA mappings.",
[vmw_dma_map_bind] = "Giving up DMA mappings early."};
@@ -643,7 +676,8 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
else
dev_priv->map_mode = vmw_dma_map_populate;
- DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
+ drm_info(&dev_priv->drm,
+ "DMA map mode: %s\n", names[dev_priv->map_mode]);
return 0;
}
@@ -661,9 +695,9 @@ static int vmw_dma_masks(struct vmw_private *dev_priv)
int ret = 0;
ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
- if (dev_priv->map_mode != vmw_dma_phys &&
- (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
- DRM_INFO("Restricting DMA addresses to 44 bits.\n");
+ if (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask) {
+ drm_info(&dev_priv->drm,
+ "Restricting DMA addresses to 44 bits.\n");
return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
}
@@ -693,7 +727,7 @@ static void vmw_vram_manager_fini(struct vmw_private *dev_priv)
}
static int vmw_setup_pci_resources(struct vmw_private *dev,
- unsigned long pci_id)
+ u32 pci_id)
{
resource_size_t rmmio_start;
resource_size_t rmmio_size;
@@ -715,13 +749,15 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
dev->vram_start = pci_resource_start(pdev, 2);
dev->vram_size = pci_resource_len(pdev, 2);
- DRM_INFO("Register MMIO at 0x%pa size is %llu kiB\n",
+ drm_info(&dev->drm,
+ "Register MMIO at 0x%pa size is %llu kiB\n",
&rmmio_start, (uint64_t)rmmio_size / 1024);
dev->rmmio = devm_ioremap(dev->drm.dev,
rmmio_start,
rmmio_size);
if (!dev->rmmio) {
- DRM_ERROR("Failed mapping registers mmio memory.\n");
+ drm_err(&dev->drm,
+ "Failed mapping registers mmio memory.\n");
pci_release_regions(pdev);
return -ENOMEM;
}
@@ -732,7 +768,8 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
fifo_start = pci_resource_start(pdev, 2);
fifo_size = pci_resource_len(pdev, 2);
- DRM_INFO("FIFO at %pa size is %llu kiB\n",
+ drm_info(&dev->drm,
+ "FIFO at %pa size is %llu kiB\n",
&fifo_start, (uint64_t)fifo_size / 1024);
dev->fifo_mem = devm_memremap(dev->drm.dev,
fifo_start,
@@ -740,7 +777,8 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
MEMREMAP_WB);
if (IS_ERR(dev->fifo_mem)) {
- DRM_ERROR("Failed mapping FIFO memory.\n");
+ drm_err(&dev->drm,
+ "Failed mapping FIFO memory.\n");
pci_release_regions(pdev);
return PTR_ERR(dev->fifo_mem);
}
@@ -755,7 +793,8 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
* size will be equal to or bigger than the size reported by
* SVGA_REG_VRAM_SIZE.
*/
- DRM_INFO("VRAM at %pa size is %llu kiB\n",
+ drm_info(&dev->drm,
+ "VRAM at %pa size is %llu kiB\n",
&dev->vram_start, (uint64_t)dev->vram_size / 1024);
return 0;
@@ -769,12 +808,14 @@ static int vmw_detect_version(struct vmw_private *dev)
SVGA_ID_3 : SVGA_ID_2);
svga_id = vmw_read(dev, SVGA_REG_ID);
if (svga_id != SVGA_ID_2 && svga_id != SVGA_ID_3) {
- DRM_ERROR("Unsupported SVGA ID 0x%x on chipset 0x%x\n",
- svga_id, dev->vmw_chipset);
+ drm_err(&dev->drm,
+ "Unsupported SVGA ID 0x%x on chipset 0x%x\n",
+ svga_id, dev->pci_id);
return -ENOSYS;
}
BUG_ON(vmw_is_svga_v3(dev) && (svga_id != SVGA_ID_3));
- DRM_INFO("Running on SVGA version %d.\n", (svga_id & 0xff));
+ drm_info(&dev->drm,
+ "Running on SVGA version %d.\n", (svga_id & 0xff));
return 0;
}
@@ -785,7 +826,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
bool refuse_dma = false;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
- dev_priv->vmw_chipset = pci_id;
dev_priv->drm.dev_private = dev_priv;
mutex_init(&dev_priv->cmdbuf_mutex);
@@ -793,7 +833,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
spin_lock_init(&dev_priv->resource_lock);
spin_lock_init(&dev_priv->hw_lock);
spin_lock_init(&dev_priv->waiter_lock);
- spin_lock_init(&dev_priv->cap_lock);
spin_lock_init(&dev_priv->cursor_lock);
ret = vmw_setup_pci_resources(dev_priv, pci_id);
@@ -830,10 +869,12 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
ret = vmw_dma_select_mode(dev_priv);
if (unlikely(ret != 0)) {
- DRM_INFO("Restricting capabilities since DMA not available.\n");
+ drm_info(&dev_priv->drm,
+ "Restricting capabilities since DMA not available.\n");
refuse_dma = true;
if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
- DRM_INFO("Disabling 3D acceleration.\n");
+ drm_info(&dev_priv->drm,
+ "Disabling 3D acceleration.\n");
}
dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
@@ -879,9 +920,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
mem_size *= 3;
dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
- dev_priv->prim_bb_mem =
- vmw_read(dev_priv,
- SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
+ dev_priv->max_primary_mem =
+ vmw_read(dev_priv, SVGA_REG_MAX_PRIMARY_MEM);
dev_priv->max_mob_size =
vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE);
dev_priv->stdu_max_width =
@@ -900,14 +940,25 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
} else {
dev_priv->texture_max_width = 8192;
dev_priv->texture_max_height = 8192;
- dev_priv->prim_bb_mem = dev_priv->vram_size;
+ dev_priv->max_primary_mem = dev_priv->vram_size;
}
-
- vmw_print_capabilities(dev_priv->capabilities);
+ drm_info(&dev_priv->drm,
+ "Legacy memory limits: VRAM = %llu kB, FIFO = %llu kB, surface = %u kB\n",
+ (u64)dev_priv->vram_size / 1024,
+ (u64)dev_priv->fifo_mem_size / 1024,
+ dev_priv->memory_size / 1024);
+
+ drm_info(&dev_priv->drm,
+ "MOB limits: max mob size = %u kB, max mob pages = %u\n",
+ dev_priv->max_mob_size / 1024, dev_priv->max_mob_pages);
+
+ vmw_print_bitmap(&dev_priv->drm, "Capabilities",
+ dev_priv->capabilities,
+ cap1_names, ARRAY_SIZE(cap1_names));
if (dev_priv->capabilities & SVGA_CAP_CAP2_REGISTER)
- vmw_print_capabilities2(dev_priv->capabilities2);
- DRM_INFO("Supports command queues = %d\n",
- vmw_cmd_supported((dev_priv)));
+ vmw_print_bitmap(&dev_priv->drm, "Capabilities2",
+ dev_priv->capabilities2,
+ cap2_names, ARRAY_SIZE(cap2_names));
ret = vmw_dma_masks(dev_priv);
if (unlikely(ret != 0))
@@ -916,15 +967,16 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dma_set_max_seg_size(dev_priv->drm.dev, U32_MAX);
if (dev_priv->capabilities & SVGA_CAP_GMR2) {
- DRM_INFO("Max GMR ids is %u\n",
+ drm_info(&dev_priv->drm,
+ "Max GMR ids is %u\n",
(unsigned)dev_priv->max_gmr_ids);
- DRM_INFO("Max number of GMR pages is %u\n",
+ drm_info(&dev_priv->drm,
+ "Max number of GMR pages is %u\n",
(unsigned)dev_priv->max_gmr_pages);
- DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n",
- (unsigned)dev_priv->memory_size / 1024);
}
- DRM_INFO("Maximum display memory size is %llu kiB\n",
- (uint64_t)dev_priv->prim_bb_mem / 1024);
+ drm_info(&dev_priv->drm,
+ "Maximum display memory size is %llu kiB\n",
+ (uint64_t)dev_priv->max_primary_mem / 1024);
/* Need mmio memory to check for fifo pitchlock cap. */
if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
@@ -939,7 +991,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
&vmw_prime_dmabuf_ops);
if (unlikely(dev_priv->tdev == NULL)) {
- DRM_ERROR("Unable to initialize TTM object management.\n");
+ drm_err(&dev_priv->drm,
+ "Unable to initialize TTM object management.\n");
ret = -ENOMEM;
goto out_err0;
}
@@ -947,7 +1000,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
ret = vmw_irq_install(&dev_priv->drm, pdev->irq);
if (ret != 0) {
- DRM_ERROR("Failed installing irq: %d\n", ret);
+ drm_err(&dev_priv->drm,
+ "Failed installing irq: %d\n", ret);
goto out_no_irq;
}
}
@@ -968,7 +1022,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dev_priv->map_mode == vmw_dma_alloc_coherent,
false);
if (unlikely(ret != 0)) {
- DRM_ERROR("Failed initializing TTM buffer object driver.\n");
+ drm_err(&dev_priv->drm,
+ "Failed initializing TTM buffer object driver.\n");
goto out_no_bdev;
}
@@ -979,7 +1034,15 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
ret = vmw_vram_manager_init(dev_priv);
if (unlikely(ret != 0)) {
- DRM_ERROR("Failed initializing memory manager for VRAM.\n");
+ drm_err(&dev_priv->drm,
+ "Failed initializing memory manager for VRAM.\n");
+ goto out_no_vram;
+ }
+
+ ret = vmw_devcaps_create(dev_priv);
+ if (unlikely(ret != 0)) {
+ drm_err(&dev_priv->drm,
+ "Failed initializing device caps.\n");
goto out_no_vram;
}
@@ -993,7 +1056,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
refuse_dma ||
vmw_gmrid_man_init(dev_priv, VMW_PL_GMR) != 0) {
- DRM_INFO("No GMR memory available. "
+ drm_info(&dev_priv->drm,
+ "No GMR memory available. "
"Graphics memory resources are very limited.\n");
dev_priv->has_gmr = false;
}
@@ -1002,18 +1066,16 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dev_priv->has_mob = true;
if (vmw_gmrid_man_init(dev_priv, VMW_PL_MOB) != 0) {
- DRM_INFO("No MOB memory available. "
+ drm_info(&dev_priv->drm,
+ "No MOB memory available. "
"3D will be disabled.\n");
dev_priv->has_mob = false;
}
}
if (dev_priv->has_mob && (dev_priv->capabilities & SVGA_CAP_DX)) {
- spin_lock(&dev_priv->cap_lock);
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_DXCONTEXT);
- if (vmw_read(dev_priv, SVGA_REG_DEV_CAP))
+ if (vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_DXCONTEXT))
dev_priv->sm_type = VMW_SM_4;
- spin_unlock(&dev_priv->cap_lock);
}
vmw_validation_mem_init_ttm(dev_priv, VMWGFX_VALIDATION_MEM_GRAN);
@@ -1021,15 +1083,11 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
/* SVGA_CAP2_DX2 (DefineGBSurface_v3) is needed for SM4_1 support */
if (has_sm4_context(dev_priv) &&
(dev_priv->capabilities2 & SVGA_CAP2_DX2)) {
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_SM41);
-
- if (vmw_read(dev_priv, SVGA_REG_DEV_CAP))
+ if (vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_SM41))
dev_priv->sm_type = VMW_SM_4_1;
-
if (has_sm4_1_context(dev_priv) &&
- (dev_priv->capabilities2 & SVGA_CAP2_DX3)) {
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_SM5);
- if (vmw_read(dev_priv, SVGA_REG_DEV_CAP))
+ (dev_priv->capabilities2 & SVGA_CAP2_DX3)) {
+ if (vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_SM5))
dev_priv->sm_type = VMW_SM_5;
}
}
@@ -1043,14 +1101,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
if (ret)
goto out_no_fifo;
- if (dev_priv->sm_type == VMW_SM_5)
- DRM_INFO("SM5 support available.\n");
- if (dev_priv->sm_type == VMW_SM_4_1)
- DRM_INFO("SM4_1 support available.\n");
- if (dev_priv->sm_type == VMW_SM_4)
- DRM_INFO("SM4 support available.\n");
- DRM_INFO("Running without reservation semaphore\n");
-
+ vmw_print_sm_type(dev_priv);
vmw_host_printf("vmwgfx: Module Version: %d.%d.%d (kernel: %s)",
VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR,
VMWGFX_DRIVER_PATCHLEVEL, UTS_RELEASE);
@@ -1074,6 +1125,7 @@ out_no_kms:
vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB);
if (dev_priv->has_gmr)
vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR);
+ vmw_devcaps_destroy(dev_priv);
vmw_vram_manager_fini(dev_priv);
out_no_vram:
ttm_device_fini(&dev_priv->bdev);
@@ -1122,6 +1174,7 @@ static void vmw_driver_unload(struct drm_device *dev)
vmw_release_device_early(dev_priv);
if (dev_priv->has_mob)
vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB);
+ vmw_devcaps_destroy(dev_priv);
vmw_vram_manager_fini(dev_priv);
ttm_device_fini(&dev_priv->bdev);
drm_vma_offset_manager_destroy(&dev_priv->vma_manager);
@@ -1137,6 +1190,8 @@ static void vmw_driver_unload(struct drm_device *dev)
for (i = vmw_res_context; i < vmw_res_max; ++i)
idr_destroy(&dev_priv->res_idr[i]);
+ vmw_mksstat_remove_all(dev_priv);
+
pci_release_regions(pdev);
}
@@ -1560,7 +1615,7 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct vmw_private *vmw;
int ret;
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "svgadrmfb");
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 5652d982b1ce..a833751099b5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**************************************************************************
*
- * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2009-2021 VMware, Inc., Palo Alto, CA., USA
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -54,10 +54,10 @@
#define VMWGFX_DRIVER_NAME "vmwgfx"
-#define VMWGFX_DRIVER_DATE "20210218"
+#define VMWGFX_DRIVER_DATE "20210722"
#define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 18
-#define VMWGFX_DRIVER_PATCHLEVEL 1
+#define VMWGFX_DRIVER_MINOR 19
+#define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
#define VMWGFX_MAX_RELOCATIONS 2048
#define VMWGFX_MAX_VALIDATIONS 2048
@@ -91,6 +91,9 @@
#define VMW_RES_FENCE ttm_driver_type3
#define VMW_RES_SHADER ttm_driver_type4
+#define MKSSTAT_CAPACITY_LOG2 5U
+#define MKSSTAT_CAPACITY (1U << MKSSTAT_CAPACITY_LOG2)
+
struct vmw_fpriv {
struct ttm_object_file *tfile;
bool gb_aware; /* user-space is guest-backed aware */
@@ -311,7 +314,6 @@ struct vmw_res_cache_entry {
* enum vmw_dma_map_mode - indicate how to perform TTM page dma mappings.
*/
enum vmw_dma_map_mode {
- vmw_dma_phys, /* Use physical page addresses */
vmw_dma_alloc_coherent, /* Use TTM coherent pages */
vmw_dma_map_populate, /* Unmap from DMA just after unpopulate */
vmw_dma_map_bind, /* Unmap from DMA just before unbind */
@@ -356,7 +358,6 @@ struct vmw_piter {
unsigned long num_pages;
bool (*next)(struct vmw_piter *);
dma_addr_t (*dma_address)(struct vmw_piter *);
- struct page *(*page)(struct vmw_piter *);
};
/*
@@ -366,7 +367,8 @@ enum vmw_display_unit_type {
vmw_du_invalid = 0,
vmw_du_legacy,
vmw_du_screen_object,
- vmw_du_screen_target
+ vmw_du_screen_target,
+ vmw_du_max
};
struct vmw_validation_context;
@@ -486,12 +488,11 @@ struct vmw_private {
struct ttm_device bdev;
struct drm_vma_offset_manager vma_manager;
- unsigned long pci_id;
- u32 vmw_chipset;
+ u32 pci_id;
resource_size_t io_start;
resource_size_t vram_start;
resource_size_t vram_size;
- resource_size_t prim_bb_mem;
+ resource_size_t max_primary_mem;
u32 __iomem *rmmio;
u32 *fifo_mem;
resource_size_t fifo_mem_size;
@@ -513,7 +514,6 @@ struct vmw_private {
bool has_gmr;
bool has_mob;
spinlock_t hw_lock;
- spinlock_t cap_lock;
bool assume_16bpp;
enum vmw_sm_type sm_type;
@@ -629,6 +629,20 @@ struct vmw_private {
/* Validation memory reservation */
struct vmw_validation_mem vvm;
+
+ uint32 *devcaps;
+
+ /*
+ * mksGuestStat instance-descriptor and pid arrays
+ */
+ struct page *mksstat_user_pages[MKSSTAT_CAPACITY];
+ atomic_t mksstat_user_pids[MKSSTAT_CAPACITY];
+
+#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
+ struct page *mksstat_kern_pages[MKSSTAT_CAPACITY];
+ u8 mksstat_kern_top_timer[MKSSTAT_CAPACITY];
+ atomic_t mksstat_kern_pids[MKSSTAT_CAPACITY];
+#endif
};
static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
@@ -1073,7 +1087,7 @@ static inline dma_addr_t vmw_piter_dma_addr(struct vmw_piter *viter)
*/
static inline struct page *vmw_piter_page(struct vmw_piter *viter)
{
- return viter->page(viter);
+ return viter->pages[viter->i];
}
/**
@@ -1281,7 +1295,6 @@ extern struct vmw_cmdbuf_res_manager *
vmw_context_res_man(struct vmw_resource *ctx);
extern struct vmw_resource *vmw_context_cotable(struct vmw_resource *ctx,
SVGACOTableType cotable_type);
-extern struct list_head *vmw_context_binding_list(struct vmw_resource *ctx);
struct vmw_ctx_binding_state;
extern struct vmw_ctx_binding_state *
vmw_context_binding_state(struct vmw_resource *ctx);
@@ -1502,6 +1515,17 @@ __printf(1, 2) int vmw_host_printf(const char *fmt, ...);
int vmw_msg_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+/* Host mksGuestStats -vmwgfx_msg.c: */
+int vmw_mksstat_get_kern_slot(pid_t pid, struct vmw_private *dev_priv);
+
+int vmw_mksstat_reset_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int vmw_mksstat_remove_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int vmw_mksstat_remove_all(struct vmw_private *dev_priv);
+
/* VMW logging */
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index a2b8464b3f56..5f2ffa9de5c8 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -32,6 +32,7 @@
#include <drm/ttm/ttm_placement.h>
#include "vmwgfx_so.h"
#include "vmwgfx_binding.h"
+#include "vmwgfx_mksstat.h"
#define VMW_RES_HT_ORDER 12
@@ -2364,7 +2365,7 @@ static int vmw_cmd_dx_set_rendertargets(struct vmw_private *dev_priv,
sizeof(SVGA3dRenderTargetViewId);
int ret;
- if (num_rt_view > SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS) {
+ if (num_rt_view > SVGA3D_DX_MAX_RENDER_TARGETS) {
VMW_DEBUG_USER("Invalid DX Rendertarget binding.\n");
return -EINVAL;
}
@@ -2546,6 +2547,8 @@ static int vmw_cmd_dx_so_define(struct vmw_private *dev_priv,
so_type = vmw_so_cmd_to_type(header->id);
res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
cmd = container_of(header, typeof(*cmd), header);
ret = vmw_cotable_notify(res, cmd->defined_id);
@@ -4406,6 +4409,9 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
int ret;
struct dma_fence *in_fence = NULL;
+ MKS_STAT_TIME_DECL(MKSSTAT_KERN_EXECBUF);
+ MKS_STAT_TIME_PUSH(MKSSTAT_KERN_EXECBUF);
+
/*
* Extend the ioctl argument while maintaining backwards compatibility:
* We take different code paths depending on the value of arg->version.
@@ -4415,7 +4421,8 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
if (unlikely(arg->version > DRM_VMW_EXECBUF_VERSION ||
arg->version == 0)) {
VMW_DEBUG_USER("Incorrect execbuf version.\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto mksstats_out;
}
switch (arg->version) {
@@ -4435,7 +4442,8 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
if (!in_fence) {
VMW_DEBUG_USER("Cannot get imported fence\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto mksstats_out;
}
ret = vmw_wait_dma_fence(dev_priv->fman, in_fence);
@@ -4458,5 +4466,8 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
out:
if (in_fence)
dma_fence_put(in_fence);
+
+mksstats_out:
+ MKS_STAT_TIME_POP(MKSSTAT_KERN_EXECBUF);
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
index 28ceb749a733..b2c4af331c9d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
@@ -71,8 +71,40 @@ static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man,
if (gman->max_gmr_pages > 0) {
gman->used_gmr_pages += (*res)->num_pages;
- if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages))
- goto nospace;
+ /*
+ * Because the graphics memory is a soft limit we can try to
+ * expand it instead of letting the userspace apps crash.
+ * We're just going to have a sane limit (half of RAM)
+ * on the number of MOB's that we create and will try to keep
+ * the system running until we reach that.
+ */
+ if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages)) {
+ const unsigned long max_graphics_pages = totalram_pages() / 2;
+ uint32_t new_max_pages = 0;
+
+ DRM_WARN("vmwgfx: mob memory overflow. Consider increasing guest RAM and graphicsMemory.\n");
+ vmw_host_printf("vmwgfx, warning: mob memory overflow. Consider increasing guest RAM and graphicsMemory.\n");
+
+ if (gman->max_gmr_pages > (max_graphics_pages / 2)) {
+ DRM_WARN("vmwgfx: guest requires more than half of RAM for graphics.\n");
+ new_max_pages = max_graphics_pages;
+ } else
+ new_max_pages = gman->max_gmr_pages * 2;
+ if (new_max_pages > gman->max_gmr_pages && new_max_pages >= gman->used_gmr_pages) {
+ DRM_WARN("vmwgfx: increasing guest mob limits to %u kB.\n",
+ ((new_max_pages) << (PAGE_SHIFT - 10)));
+
+ gman->max_gmr_pages = new_max_pages;
+ } else {
+ char buf[256];
+ snprintf(buf, sizeof(buf),
+ "vmwgfx, error: guest graphics is out of memory (mob limit at: %ukB).\n",
+ ((gman->max_gmr_pages) << (PAGE_SHIFT - 10)));
+ vmw_host_printf(buf);
+ DRM_WARN("%s", buf);
+ goto nospace;
+ }
+ }
}
(*res)->start = id;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 4fdacf9924e6..28af34ab6ed6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -26,14 +26,9 @@
**************************************************************************/
#include "vmwgfx_drv.h"
+#include "vmwgfx_devcaps.h"
#include <drm/vmwgfx_drm.h>
#include "vmwgfx_kms.h"
-#include "device_include/svga3d_caps.h"
-
-struct svga_3d_compat_cap {
- SVGA3dCapsRecordHeader header;
- SVGA3dCapPair pairs[SVGA3D_DEVCAP_MAX];
-};
int vmw_getparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
@@ -63,7 +58,7 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
param->value = vmw_fifo_caps(dev_priv);
break;
case DRM_VMW_PARAM_MAX_FB_SIZE:
- param->value = dev_priv->prim_bb_mem;
+ param->value = dev_priv->max_primary_mem;
break;
case DRM_VMW_PARAM_FIFO_HW_VERSION:
{
@@ -88,16 +83,7 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
param->value = dev_priv->memory_size;
break;
case DRM_VMW_PARAM_3D_CAPS_SIZE:
- if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
- vmw_fp->gb_aware)
- param->value = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
- else if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
- param->value = sizeof(struct svga_3d_compat_cap) +
- sizeof(uint32_t);
- else
- param->value = (SVGA_FIFO_3D_CAPS_LAST -
- SVGA_FIFO_3D_CAPS + 1) *
- sizeof(uint32_t);
+ param->value = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);
break;
case DRM_VMW_PARAM_MAX_MOB_MEMORY:
vmw_fp->gb_aware = true;
@@ -126,55 +112,6 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
return 0;
}
-static u32 vmw_mask_legacy_multisample(unsigned int cap, u32 fmt_value)
-{
- /*
- * A version of user-space exists which use MULTISAMPLE_MASKABLESAMPLES
- * to check the sample count supported by virtual device. Since there
- * never was support for multisample count for backing MOB return 0.
- *
- * MULTISAMPLE_MASKABLESAMPLES devcap is marked as deprecated by virtual
- * device.
- */
- if (cap == SVGA3D_DEVCAP_DEAD5)
- return 0;
-
- return fmt_value;
-}
-
-static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce,
- size_t size)
-{
- struct svga_3d_compat_cap *compat_cap =
- (struct svga_3d_compat_cap *) bounce;
- unsigned int i;
- size_t pair_offset = offsetof(struct svga_3d_compat_cap, pairs);
- unsigned int max_size;
-
- if (size < pair_offset)
- return -EINVAL;
-
- max_size = (size - pair_offset) / sizeof(SVGA3dCapPair);
-
- if (max_size > SVGA3D_DEVCAP_MAX)
- max_size = SVGA3D_DEVCAP_MAX;
-
- compat_cap->header.length =
- (pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32);
- compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS;
-
- spin_lock(&dev_priv->cap_lock);
- for (i = 0; i < max_size; ++i) {
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
- compat_cap->pairs[i][0] = i;
- compat_cap->pairs[i][1] = vmw_mask_legacy_multisample
- (i, vmw_read(dev_priv, SVGA_REG_DEV_CAP));
- }
- spin_unlock(&dev_priv->cap_lock);
-
- return 0;
-}
-
int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
@@ -183,11 +120,9 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
(struct drm_vmw_get_3d_cap_arg *) data;
struct vmw_private *dev_priv = vmw_priv(dev);
uint32_t size;
- u32 *fifo_mem;
void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
- void *bounce;
+ void *bounce = NULL;
int ret;
- bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);
struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {
@@ -195,13 +130,11 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
- if (gb_objects && vmw_fp->gb_aware)
- size = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
- else if (gb_objects)
- size = sizeof(struct svga_3d_compat_cap) + sizeof(uint32_t);
- else
- size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) *
- sizeof(uint32_t);
+ size = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);
+ if (unlikely(size == 0)) {
+ DRM_ERROR("Failed to figure out the devcaps size (no 3D).\n");
+ return -ENOMEM;
+ }
if (arg->max_size < size)
size = arg->max_size;
@@ -212,29 +145,9 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
return -ENOMEM;
}
- if (gb_objects && vmw_fp->gb_aware) {
- int i, num;
- uint32_t *bounce32 = (uint32_t *) bounce;
-
- num = size / sizeof(uint32_t);
- if (num > SVGA3D_DEVCAP_MAX)
- num = SVGA3D_DEVCAP_MAX;
-
- spin_lock(&dev_priv->cap_lock);
- for (i = 0; i < num; ++i) {
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
- *bounce32++ = vmw_mask_legacy_multisample
- (i, vmw_read(dev_priv, SVGA_REG_DEV_CAP));
- }
- spin_unlock(&dev_priv->cap_lock);
- } else if (gb_objects) {
- ret = vmw_fill_compat_cap(dev_priv, bounce, size);
- if (unlikely(ret != 0))
- goto out_err;
- } else {
- fifo_mem = dev_priv->fifo_mem;
- memcpy(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
- }
+ ret = vmw_devcaps_copy(dev_priv, vmw_fp->gb_aware, bounce, size);
+ if (unlikely (ret != 0))
+ goto out_err;
ret = copy_to_user(buffer, bounce, size);
if (ret)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
index b9a9b7ddadbd..c5191de365ca 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -25,6 +25,7 @@
*
**************************************************************************/
+#include <linux/pci.h>
#include <linux/sched/signal.h>
#include "vmwgfx_drv.h"
@@ -287,21 +288,18 @@ static void vmw_irq_preinstall(struct drm_device *dev)
void vmw_irq_uninstall(struct drm_device *dev)
{
struct vmw_private *dev_priv = vmw_priv(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
uint32_t status;
if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
return;
- if (!dev->irq_enabled)
- return;
-
vmw_write(dev_priv, SVGA_REG_IRQMASK, 0);
status = vmw_irq_status_read(dev_priv);
vmw_irq_status_write(dev_priv, status);
- dev->irq_enabled = false;
- free_irq(dev->irq, dev);
+ free_irq(pdev->irq, dev);
}
/**
@@ -313,20 +311,8 @@ void vmw_irq_uninstall(struct drm_device *dev)
*/
int vmw_irq_install(struct drm_device *dev, int irq)
{
- int ret;
-
- if (dev->irq_enabled)
- return -EBUSY;
-
vmw_irq_preinstall(dev);
- ret = request_threaded_irq(irq, vmw_irq_handler, vmw_thread_fn,
- IRQF_SHARED, VMWGFX_DRIVER_NAME, dev);
- if (ret < 0)
- return ret;
-
- dev->irq_enabled = true;
- dev->irq = irq;
-
- return ret;
+ return request_threaded_irq(irq, vmw_irq_handler, vmw_thread_fn,
+ IRQF_SHARED, VMWGFX_DRIVER_NAME, dev);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 220f9fd0d420..74fa41909213 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -100,7 +100,7 @@ static int vmw_cursor_update_bo(struct vmw_private *dev_priv,
int ret;
kmap_offset = 0;
- kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ kmap_num = PFN_UP(width*height*4);
ret = ttm_bo_reserve(&bo->base, true, false, NULL);
if (unlikely(ret != 0)) {
@@ -1487,7 +1487,7 @@ static int vmw_kms_check_display_memory(struct drm_device *dev,
* SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM is not present vram size is
* limit on primary bounding box
*/
- if (pixel_mem > dev_priv->prim_bb_mem) {
+ if (pixel_mem > dev_priv->max_primary_mem) {
VMW_DEBUG_KMS("Combined output size too large.\n");
return -EINVAL;
}
@@ -1497,7 +1497,7 @@ static int vmw_kms_check_display_memory(struct drm_device *dev,
!(dev_priv->capabilities & SVGA_CAP_NO_BB_RESTRICTION)) {
bb_mem = (u64) bounding_box.x2 * bounding_box.y2 * 4;
- if (bb_mem > dev_priv->prim_bb_mem) {
+ if (bb_mem > dev_priv->max_primary_mem) {
VMW_DEBUG_KMS("Topology is beyond supported limits.\n");
return -EINVAL;
}
@@ -1793,6 +1793,13 @@ int vmw_kms_init(struct vmw_private *dev_priv)
{
struct drm_device *dev = &dev_priv->drm;
int ret;
+ static const char *display_unit_names[] = {
+ "Invalid",
+ "Legacy",
+ "Screen Object",
+ "Screen Target",
+ "Invalid (max)"
+ };
drm_mode_config_init(dev);
dev->mode_config.funcs = &vmw_kms_funcs;
@@ -1810,6 +1817,9 @@ int vmw_kms_init(struct vmw_private *dev_priv)
if (ret) /* Fallback */
ret = vmw_kms_ldu_init_display(dev_priv);
}
+ BUILD_BUG_ON(ARRAY_SIZE(display_unit_names) != (vmw_du_max + 1));
+ drm_info(&dev_priv->drm, "%s display unit initialized\n",
+ display_unit_names[dev_priv->active_display_unit]);
return ret;
}
@@ -1897,7 +1907,7 @@ bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
{
return ((u64) pitch * (u64) height) < (u64)
((dev_priv->active_display_unit == vmw_du_screen_target) ?
- dev_priv->prim_bb_mem : dev_priv->vram_size);
+ dev_priv->max_primary_mem : dev_priv->vram_size);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index d85c7eab9469..fb58a71c458f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -493,8 +493,7 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
struct drm_device *dev = &dev_priv->drm;
int i, ret;
- if (dev_priv->ldu_priv) {
- DRM_INFO("ldu system already on\n");
+ if (unlikely(dev_priv->ldu_priv)) {
return -EINVAL;
}
@@ -527,8 +526,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
drm_mode_config_reset(dev);
- DRM_INFO("Legacy Display Unit initialized\n");
-
return 0;
err_free:
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h b/drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h
new file mode 100644
index 000000000000..0509f55f07b4
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/**************************************************************************
+ *
+ * Copyright 2021 VMware, Inc., Palo Alto, CA., USA
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _VMWGFX_MKSSTAT_H_
+#define _VMWGFX_MKSSTAT_H_
+
+#include <asm/page.h>
+
+/* Reservation marker for mksstat pid's */
+#define MKSSTAT_PID_RESERVED -1
+
+#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
+/*
+ * Kernel-internal mksGuestStat counters. The order of this enum dictates the
+ * order of instantiation of these counters in the mksGuestStat pages.
+ */
+
+typedef enum {
+ MKSSTAT_KERN_EXECBUF, /* vmw_execbuf_ioctl */
+
+ MKSSTAT_KERN_COUNT /* Reserved entry; always last */
+} mksstat_kern_stats_t;
+
+/**
+ * vmw_mksstat_get_kern_pstat: Computes the address of the MKSGuestStatCounterTime
+ * array from the address of the base page.
+ *
+ * @page_addr: Pointer to the base page.
+ * Return: Pointer to the MKSGuestStatCounterTime array.
+ */
+
+static inline void *vmw_mksstat_get_kern_pstat(void *page_addr)
+{
+ return page_addr + PAGE_SIZE * 1;
+}
+
+/**
+ * vmw_mksstat_get_kern_pinfo: Computes the address of the MKSGuestStatInfoEntry
+ * array from the address of the base page.
+ *
+ * @page_addr: Pointer to the base page.
+ * Return: Pointer to the MKSGuestStatInfoEntry array.
+ */
+
+static inline void *vmw_mksstat_get_kern_pinfo(void *page_addr)
+{
+ return page_addr + PAGE_SIZE * 2;
+}
+
+/**
+ * vmw_mksstat_get_kern_pstrs: Computes the address of the mksGuestStat strings
+ * sequence from the address of the base page.
+ *
+ * @page_addr: Pointer to the base page.
+ * Return: Pointer to the mksGuestStat strings sequence.
+ */
+
+static inline void *vmw_mksstat_get_kern_pstrs(void *page_addr)
+{
+ return page_addr + PAGE_SIZE * 3;
+}
+
+/*
+ * MKS_STAT_TIME_DECL/PUSH/POP macros to be used in timer-counted routines.
+ */
+
+struct mksstat_timer_t {
+/* mutable */ mksstat_kern_stats_t old_top;
+ const u64 t0;
+ const int slot;
+};
+
+#define MKS_STAT_TIME_DECL(kern_cntr) \
+ struct mksstat_timer_t _##kern_cntr = { \
+ .t0 = rdtsc(), \
+ .slot = vmw_mksstat_get_kern_slot(current->pid, dev_priv) \
+ }
+
+#define MKS_STAT_TIME_PUSH(kern_cntr) \
+ do { \
+ if (_##kern_cntr.slot >= 0) { \
+ _##kern_cntr.old_top = dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot]; \
+ dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot] = kern_cntr; \
+ } \
+ } while (0)
+
+#define MKS_STAT_TIME_POP(kern_cntr) \
+ do { \
+ if (_##kern_cntr.slot >= 0) { \
+ const pid_t pid = atomic_cmpxchg(&dev_priv->mksstat_kern_pids[_##kern_cntr.slot], current->pid, MKSSTAT_PID_RESERVED); \
+ dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot] = _##kern_cntr.old_top; \
+ \
+ if (pid == current->pid) { \
+ const u64 dt = rdtsc() - _##kern_cntr.t0; \
+ MKSGuestStatCounterTime *pstat; \
+ \
+ BUG_ON(!dev_priv->mksstat_kern_pages[_##kern_cntr.slot]); \
+ \
+ pstat = vmw_mksstat_get_kern_pstat(page_address(dev_priv->mksstat_kern_pages[_##kern_cntr.slot])); \
+ \
+ atomic64_inc(&pstat[kern_cntr].counter.count); \
+ atomic64_add(dt, &pstat[kern_cntr].selfCycles); \
+ atomic64_add(dt, &pstat[kern_cntr].totalCycles); \
+ \
+ if (_##kern_cntr.old_top != MKSSTAT_KERN_COUNT) \
+ atomic64_sub(dt, &pstat[_##kern_cntr.old_top].selfCycles); \
+ \
+ atomic_set(&dev_priv->mksstat_kern_pids[_##kern_cntr.slot], current->pid); \
+ } \
+ } \
+ } while (0)
+
+#else
+#define MKS_STAT_TIME_DECL(kern_cntr)
+#define MKS_STAT_TIME_PUSH(kern_cntr)
+#define MKS_STAT_TIME_POP(kern_cntr)
+
+#endif /* IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS */
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
index f2d625415458..f9394207dd3c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
@@ -37,14 +37,14 @@
#ifdef CONFIG_64BIT
#define VMW_PPN_SIZE 8
-#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PTDEPTH64_0
-#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PTDEPTH64_1
-#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PTDEPTH64_2
+#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PT64_0
+#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PT64_1
+#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PT64_2
#else
#define VMW_PPN_SIZE 4
-#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PTDEPTH_0
-#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PTDEPTH_1
-#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PTDEPTH_2
+#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PT_0
+#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PT_1
+#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PT_2
#endif
/*
@@ -70,20 +70,20 @@ struct vmw_mob {
* @page_table: Pointer to a struct vmw_mob holding the page table.
*/
static const struct vmw_otable pre_dx_tables[] = {
- {VMWGFX_NUM_MOB * SVGA3D_OTABLE_MOB_ENTRY_SIZE, NULL, true},
- {VMWGFX_NUM_GB_SURFACE * SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, NULL, true},
- {VMWGFX_NUM_GB_CONTEXT * SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE, NULL, true},
- {VMWGFX_NUM_GB_SHADER * SVGA3D_OTABLE_SHADER_ENTRY_SIZE, NULL, true},
- {VMWGFX_NUM_GB_SCREEN_TARGET * SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE,
+ {VMWGFX_NUM_MOB * sizeof(SVGAOTableMobEntry), NULL, true},
+ {VMWGFX_NUM_GB_SURFACE * sizeof(SVGAOTableSurfaceEntry), NULL, true},
+ {VMWGFX_NUM_GB_CONTEXT * sizeof(SVGAOTableContextEntry), NULL, true},
+ {VMWGFX_NUM_GB_SHADER * sizeof(SVGAOTableShaderEntry), NULL, true},
+ {VMWGFX_NUM_GB_SCREEN_TARGET * sizeof(SVGAOTableScreenTargetEntry),
NULL, VMWGFX_ENABLE_SCREEN_TARGET_OTABLE}
};
static const struct vmw_otable dx_tables[] = {
- {VMWGFX_NUM_MOB * SVGA3D_OTABLE_MOB_ENTRY_SIZE, NULL, true},
- {VMWGFX_NUM_GB_SURFACE * SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, NULL, true},
- {VMWGFX_NUM_GB_CONTEXT * SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE, NULL, true},
- {VMWGFX_NUM_GB_SHADER * SVGA3D_OTABLE_SHADER_ENTRY_SIZE, NULL, true},
- {VMWGFX_NUM_GB_SCREEN_TARGET * SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE,
+ {VMWGFX_NUM_MOB * sizeof(SVGAOTableMobEntry), NULL, true},
+ {VMWGFX_NUM_GB_SURFACE * sizeof(SVGAOTableSurfaceEntry), NULL, true},
+ {VMWGFX_NUM_GB_CONTEXT * sizeof(SVGAOTableContextEntry), NULL, true},
+ {VMWGFX_NUM_GB_SHADER * sizeof(SVGAOTableShaderEntry), NULL, true},
+ {VMWGFX_NUM_GB_SCREEN_TARGET * sizeof(SVGAOTableScreenTargetEntry),
NULL, VMWGFX_ENABLE_SCREEN_TARGET_OTABLE},
{VMWGFX_NUM_DXCONTEXT * sizeof(SVGAOTableDXContextEntry), NULL, true},
};
@@ -155,7 +155,7 @@ static int vmw_setup_otable_base(struct vmw_private *dev_priv,
goto out_no_populate;
vmw_mob_pt_setup(mob, iter, otable->size >> PAGE_SHIFT);
- mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
+ mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PT_1;
}
cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
@@ -256,8 +256,7 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv,
if (!otables[i].enabled)
continue;
- otables[i].size =
- (otables[i].size + PAGE_SIZE - 1) & PAGE_MASK;
+ otables[i].size = PFN_ALIGN(otables[i].size);
bo_size += otables[i].size;
}
@@ -385,7 +384,7 @@ static unsigned long vmw_mob_calculate_pt_pages(unsigned long data_pages)
while (likely(data_size > PAGE_SIZE)) {
data_size = DIV_ROUND_UP(data_size, PAGE_SIZE);
data_size *= VMW_PPN_SIZE;
- tot_size += (data_size + PAGE_SIZE - 1) & PAGE_MASK;
+ tot_size += PFN_ALIGN(data_size);
}
return tot_size >> PAGE_SHIFT;
@@ -506,11 +505,13 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob,
{
unsigned long num_pt_pages = 0;
struct ttm_buffer_object *bo = mob->pt_bo;
- struct vmw_piter save_pt_iter;
+ struct vmw_piter save_pt_iter = {0};
struct vmw_piter pt_iter;
const struct vmw_sg_table *vsgt;
int ret;
+ BUG_ON(num_data_pages == 0);
+
ret = ttm_bo_reserve(bo, false, true, NULL);
BUG_ON(ret != 0);
@@ -633,7 +634,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv,
vmw_mob_pt_setup(mob, data_iter, num_data_pages);
pt_set_up = true;
- mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
+ mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PT_1;
}
vmw_fifo_resource_inc(dev_priv);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
index 3d08f5700bdb..e50fb82a3030 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
@@ -31,10 +31,12 @@
#include <linux/mem_encrypt.h>
#include <asm/hypervisor.h>
+#include <drm/drm_ioctl.h>
#include "vmwgfx_drv.h"
#include "vmwgfx_msg_x86.h"
#include "vmwgfx_msg_arm64.h"
+#include "vmwgfx_mksstat.h"
#define MESSAGE_STATUS_SUCCESS 0x0001
#define MESSAGE_STATUS_DORECV 0x0002
@@ -56,6 +58,11 @@
#define VMW_PORT_CMD_RECVSIZE (MSG_TYPE_RECVSIZE << 16 | VMW_PORT_CMD_MSG)
#define VMW_PORT_CMD_RECVSTATUS (MSG_TYPE_RECVSTATUS << 16 | VMW_PORT_CMD_MSG)
+#define VMW_PORT_CMD_MKS_GUEST_STATS 85
+#define VMW_PORT_CMD_MKSGS_RESET (0 << 16 | VMW_PORT_CMD_MKS_GUEST_STATS)
+#define VMW_PORT_CMD_MKSGS_ADD_PPN (1 << 16 | VMW_PORT_CMD_MKS_GUEST_STATS)
+#define VMW_PORT_CMD_MKSGS_REMOVE_PPN (2 << 16 | VMW_PORT_CMD_MKS_GUEST_STATS)
+
#define HIGH_WORD(X) ((X & 0xFFFF0000) >> 16)
#define MAX_USER_MSG_LENGTH PAGE_SIZE
@@ -155,6 +162,7 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
/* HB port can't access encrypted memory. */
if (hb && !mem_encrypt_active()) {
unsigned long bp = channel->cookie_high;
+ u32 channel_id = (channel->channel_id << 16);
si = (uintptr_t) msg;
di = channel->cookie_low;
@@ -162,7 +170,7 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
VMW_PORT_HB_OUT(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
msg_len, si, di,
- VMWARE_HYPERVISOR_HB | (channel->channel_id << 16) |
+ VMWARE_HYPERVISOR_HB | channel_id |
VMWARE_HYPERVISOR_OUT,
VMW_HYPERVISOR_MAGIC, bp,
eax, ebx, ecx, edx, si, di);
@@ -210,6 +218,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
/* HB port can't access encrypted memory */
if (hb && !mem_encrypt_active()) {
unsigned long bp = channel->cookie_low;
+ u32 channel_id = (channel->channel_id << 16);
si = channel->cookie_high;
di = (uintptr_t) reply;
@@ -217,7 +226,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
VMW_PORT_HB_IN(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
reply_len, si, di,
- VMWARE_HYPERVISOR_HB | (channel->channel_id << 16),
+ VMWARE_HYPERVISOR_HB | channel_id,
VMW_HYPERVISOR_MAGIC, bp,
eax, ebx, ecx, edx, si, di);
@@ -612,3 +621,569 @@ out_open:
return -EINVAL;
}
+
+/**
+ * reset_ppn_array: Resets a PPN64 array to INVALID_PPN64 content
+ *
+ * @arr: Array to reset.
+ * @size: Array length.
+ */
+static inline void reset_ppn_array(PPN64 *arr, size_t size)
+{
+ size_t i;
+
+ BUG_ON(!arr || size == 0);
+
+ for (i = 0; i < size; ++i)
+ arr[i] = INVALID_PPN64;
+}
+
+/**
+ * hypervisor_ppn_reset_all: Removes all mksGuestStat instance descriptors from
+ * the hypervisor. All related pages should be subsequently unpinned or freed.
+ *
+ */
+static inline void hypervisor_ppn_reset_all(void)
+{
+ unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
+
+ VMW_PORT(VMW_PORT_CMD_MKSGS_RESET,
+ 0, si, di,
+ 0,
+ VMW_HYPERVISOR_MAGIC,
+ eax, ebx, ecx, edx, si, di);
+}
+
+/**
+ * hypervisor_ppn_add: Adds a single mksGuestStat instance descriptor to the
+ * hypervisor. Any related userspace pages should be pinned in advance.
+ *
+ * @pfn: Physical page number of the instance descriptor
+ */
+static inline void hypervisor_ppn_add(PPN64 pfn)
+{
+ unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
+
+ VMW_PORT(VMW_PORT_CMD_MKSGS_ADD_PPN,
+ (unsigned long)pfn, si, di,
+ 0,
+ VMW_HYPERVISOR_MAGIC,
+ eax, ebx, ecx, edx, si, di);
+}
+
+/**
+ * hypervisor_ppn_remove: Removes a single mksGuestStat instance descriptor from
+ * the hypervisor. All related pages should be subsequently unpinned or freed.
+ *
+ * @pfn: Physical page number of the instance descriptor
+ */
+static inline void hypervisor_ppn_remove(PPN64 pfn)
+{
+ unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
+
+ VMW_PORT(VMW_PORT_CMD_MKSGS_REMOVE_PPN,
+ (unsigned long)pfn, si, di,
+ 0,
+ VMW_HYPERVISOR_MAGIC,
+ eax, ebx, ecx, edx, si, di);
+}
+
+#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
+
+/* Order of the total number of pages used for kernel-internal mksGuestStat; at least 2 */
+#define MKSSTAT_KERNEL_PAGES_ORDER 2
+/* Header to the text description of mksGuestStat instance descriptor */
+#define MKSSTAT_KERNEL_DESCRIPTION "vmwgfx"
+
+/* Kernel mksGuestStats counter names and desciptions; same order as enum mksstat_kern_stats_t */
+static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] =
+{
+ { "vmw_execbuf_ioctl", "vmw_execbuf_ioctl" },
+};
+
+/**
+ * mksstat_init_record: Initializes an MKSGuestStatCounter-based record
+ * for the respective mksGuestStat index.
+ *
+ * @stat_idx: Index of the MKSGuestStatCounter-based mksGuestStat record.
+ * @pstat: Pointer to array of MKSGuestStatCounterTime.
+ * @pinfo: Pointer to array of MKSGuestStatInfoEntry.
+ * @pstrs: Pointer to current end of the name/description sequence.
+ * Return: Pointer to the new end of the names/description sequence.
+ */
+
+static inline char *mksstat_init_record(mksstat_kern_stats_t stat_idx,
+ MKSGuestStatCounterTime *pstat, MKSGuestStatInfoEntry *pinfo, char *pstrs)
+{
+ char *const pstrd = pstrs + strlen(mksstat_kern_name_desc[stat_idx][0]) + 1;
+ strcpy(pstrs, mksstat_kern_name_desc[stat_idx][0]);
+ strcpy(pstrd, mksstat_kern_name_desc[stat_idx][1]);
+
+ pinfo[stat_idx].name.s = pstrs;
+ pinfo[stat_idx].description.s = pstrd;
+ pinfo[stat_idx].flags = MKS_GUEST_STAT_FLAG_NONE;
+ pinfo[stat_idx].stat.counter = (MKSGuestStatCounter *)&pstat[stat_idx];
+
+ return pstrd + strlen(mksstat_kern_name_desc[stat_idx][1]) + 1;
+}
+
+/**
+ * mksstat_init_record_time: Initializes an MKSGuestStatCounterTime-based record
+ * for the respective mksGuestStat index.
+ *
+ * @stat_idx: Index of the MKSGuestStatCounterTime-based mksGuestStat record.
+ * @pstat: Pointer to array of MKSGuestStatCounterTime.
+ * @pinfo: Pointer to array of MKSGuestStatInfoEntry.
+ * @pstrs: Pointer to current end of the name/description sequence.
+ * Return: Pointer to the new end of the names/description sequence.
+ */
+
+static inline char *mksstat_init_record_time(mksstat_kern_stats_t stat_idx,
+ MKSGuestStatCounterTime *pstat, MKSGuestStatInfoEntry *pinfo, char *pstrs)
+{
+ char *const pstrd = pstrs + strlen(mksstat_kern_name_desc[stat_idx][0]) + 1;
+ strcpy(pstrs, mksstat_kern_name_desc[stat_idx][0]);
+ strcpy(pstrd, mksstat_kern_name_desc[stat_idx][1]);
+
+ pinfo[stat_idx].name.s = pstrs;
+ pinfo[stat_idx].description.s = pstrd;
+ pinfo[stat_idx].flags = MKS_GUEST_STAT_FLAG_TIME;
+ pinfo[stat_idx].stat.counterTime = &pstat[stat_idx];
+
+ return pstrd + strlen(mksstat_kern_name_desc[stat_idx][1]) + 1;
+}
+
+/**
+ * mksstat_init_kern_id: Creates a single mksGuestStat instance descriptor and
+ * kernel-internal counters. Adds PFN mapping to the hypervisor.
+ *
+ * Create a single mksGuestStat instance descriptor and corresponding structures
+ * for all kernel-internal counters. The corresponding PFNs are mapped with the
+ * hypervisor.
+ *
+ * @ppage: Output pointer to page containing the instance descriptor.
+ * Return: Zero on success, negative error code on error.
+ */
+
+static int mksstat_init_kern_id(struct page **ppage)
+{
+ MKSGuestStatInstanceDescriptor *pdesc;
+ MKSGuestStatCounterTime *pstat;
+ MKSGuestStatInfoEntry *pinfo;
+ char *pstrs, *pstrs_acc;
+
+ /* Allocate pages for the kernel-internal instance descriptor */
+ struct page *page = alloc_pages(GFP_KERNEL | __GFP_ZERO, MKSSTAT_KERNEL_PAGES_ORDER);
+
+ if (!page)
+ return -ENOMEM;
+
+ pdesc = page_address(page);
+ pstat = vmw_mksstat_get_kern_pstat(pdesc);
+ pinfo = vmw_mksstat_get_kern_pinfo(pdesc);
+ pstrs = vmw_mksstat_get_kern_pstrs(pdesc);
+
+ /* Set up all kernel-internal counters and corresponding structures */
+ pstrs_acc = pstrs;
+ pstrs_acc = mksstat_init_record_time(MKSSTAT_KERN_EXECBUF, pstat, pinfo, pstrs_acc);
+
+ /* Add new counters above, in their order of appearance in mksstat_kern_stats_t */
+
+ BUG_ON(pstrs_acc - pstrs > PAGE_SIZE);
+
+ /* Set up the kernel-internal instance descriptor */
+ pdesc->reservedMBZ = 0;
+ pdesc->statStartVA = (uintptr_t)pstat;
+ pdesc->strsStartVA = (uintptr_t)pstrs;
+ pdesc->statLength = sizeof(*pstat) * MKSSTAT_KERN_COUNT;
+ pdesc->infoLength = sizeof(*pinfo) * MKSSTAT_KERN_COUNT;
+ pdesc->strsLength = pstrs_acc - pstrs;
+ snprintf(pdesc->description, ARRAY_SIZE(pdesc->description) - 1, "%s pid=%d",
+ MKSSTAT_KERNEL_DESCRIPTION, current->pid);
+
+ pdesc->statPPNs[0] = page_to_pfn(virt_to_page(pstat));
+ reset_ppn_array(pdesc->statPPNs + 1, ARRAY_SIZE(pdesc->statPPNs) - 1);
+
+ pdesc->infoPPNs[0] = page_to_pfn(virt_to_page(pinfo));
+ reset_ppn_array(pdesc->infoPPNs + 1, ARRAY_SIZE(pdesc->infoPPNs) - 1);
+
+ pdesc->strsPPNs[0] = page_to_pfn(virt_to_page(pstrs));
+ reset_ppn_array(pdesc->strsPPNs + 1, ARRAY_SIZE(pdesc->strsPPNs) - 1);
+
+ *ppage = page;
+
+ hypervisor_ppn_add((PPN64)page_to_pfn(page));
+
+ return 0;
+}
+
+/**
+ * vmw_mksstat_get_kern_slot: Acquires a slot for a single kernel-internal
+ * mksGuestStat instance descriptor.
+ *
+ * Find a slot for a single kernel-internal mksGuestStat instance descriptor.
+ * In case no such was already present, allocate a new one and set up a kernel-
+ * internal mksGuestStat instance descriptor for the former.
+ *
+ * @pid: Process for which a slot is sought.
+ * @dev_priv: Identifies the drm private device.
+ * Return: Non-negative slot on success, negative error code on error.
+ */
+
+int vmw_mksstat_get_kern_slot(pid_t pid, struct vmw_private *dev_priv)
+{
+ const size_t base = (u32)hash_32(pid, MKSSTAT_CAPACITY_LOG2);
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(dev_priv->mksstat_kern_pids); ++i) {
+ const size_t slot = (i + base) % ARRAY_SIZE(dev_priv->mksstat_kern_pids);
+
+ /* Check if an instance descriptor for this pid is already present */
+ if (pid == (pid_t)atomic_read(&dev_priv->mksstat_kern_pids[slot]))
+ return (int)slot;
+
+ /* Set up a new instance descriptor for this pid */
+ if (!atomic_cmpxchg(&dev_priv->mksstat_kern_pids[slot], 0, MKSSTAT_PID_RESERVED)) {
+ const int ret = mksstat_init_kern_id(&dev_priv->mksstat_kern_pages[slot]);
+
+ if (!ret) {
+ /* Reset top-timer tracking for this slot */
+ dev_priv->mksstat_kern_top_timer[slot] = MKSSTAT_KERN_COUNT;
+
+ atomic_set(&dev_priv->mksstat_kern_pids[slot], pid);
+ return (int)slot;
+ }
+
+ atomic_set(&dev_priv->mksstat_kern_pids[slot], 0);
+ return ret;
+ }
+ }
+
+ return -ENOSPC;
+}
+
+#endif
+
+/**
+ * vmw_mksstat_cleanup_descriptor: Frees a single userspace-originating
+ * mksGuestStat instance-descriptor page and unpins all related user pages.
+ *
+ * Unpin all user pages realated to this instance descriptor and free
+ * the instance-descriptor page itself.
+ *
+ * @page: Page of the instance descriptor.
+ */
+
+static void vmw_mksstat_cleanup_descriptor(struct page *page)
+{
+ MKSGuestStatInstanceDescriptor *pdesc = page_address(page);
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(pdesc->statPPNs) && pdesc->statPPNs[i] != INVALID_PPN64; ++i)
+ unpin_user_page(pfn_to_page(pdesc->statPPNs[i]));
+
+ for (i = 0; i < ARRAY_SIZE(pdesc->infoPPNs) && pdesc->infoPPNs[i] != INVALID_PPN64; ++i)
+ unpin_user_page(pfn_to_page(pdesc->infoPPNs[i]));
+
+ for (i = 0; i < ARRAY_SIZE(pdesc->strsPPNs) && pdesc->strsPPNs[i] != INVALID_PPN64; ++i)
+ unpin_user_page(pfn_to_page(pdesc->strsPPNs[i]));
+
+ __free_page(page);
+}
+
+/**
+ * vmw_mksstat_remove_all: Resets all mksGuestStat instance descriptors
+ * from the hypervisor.
+ *
+ * Discard all hypervisor PFN mappings, containing active mksGuestState instance
+ * descriptors, unpin the related userspace pages and free the related kernel pages.
+ *
+ * @dev_priv: Identifies the drm private device.
+ * Return: Zero on success, negative error code on error.
+ */
+
+int vmw_mksstat_remove_all(struct vmw_private *dev_priv)
+{
+ int ret = 0;
+ size_t i;
+
+ /* Discard all PFN mappings with the hypervisor */
+ hypervisor_ppn_reset_all();
+
+ /* Discard all userspace-originating instance descriptors and unpin all related pages */
+ for (i = 0; i < ARRAY_SIZE(dev_priv->mksstat_user_pids); ++i) {
+ const pid_t pid0 = (pid_t)atomic_read(&dev_priv->mksstat_user_pids[i]);
+
+ if (!pid0)
+ continue;
+
+ if (pid0 != MKSSTAT_PID_RESERVED) {
+ const pid_t pid1 = atomic_cmpxchg(&dev_priv->mksstat_user_pids[i], pid0, MKSSTAT_PID_RESERVED);
+
+ if (!pid1)
+ continue;
+
+ if (pid1 == pid0) {
+ struct page *const page = dev_priv->mksstat_user_pages[i];
+
+ BUG_ON(!page);
+
+ dev_priv->mksstat_user_pages[i] = NULL;
+ atomic_set(&dev_priv->mksstat_user_pids[i], 0);
+
+ vmw_mksstat_cleanup_descriptor(page);
+ continue;
+ }
+ }
+
+ ret = -EAGAIN;
+ }
+
+#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
+ /* Discard all kernel-internal instance descriptors and free all related pages */
+ for (i = 0; i < ARRAY_SIZE(dev_priv->mksstat_kern_pids); ++i) {
+ const pid_t pid0 = (pid_t)atomic_read(&dev_priv->mksstat_kern_pids[i]);
+
+ if (!pid0)
+ continue;
+
+ if (pid0 != MKSSTAT_PID_RESERVED) {
+ const pid_t pid1 = atomic_cmpxchg(&dev_priv->mksstat_kern_pids[i], pid0, MKSSTAT_PID_RESERVED);
+
+ if (!pid1)
+ continue;
+
+ if (pid1 == pid0) {
+ struct page *const page = dev_priv->mksstat_kern_pages[i];
+
+ BUG_ON(!page);
+
+ dev_priv->mksstat_kern_pages[i] = NULL;
+ atomic_set(&dev_priv->mksstat_kern_pids[i], 0);
+
+ __free_pages(page, MKSSTAT_KERNEL_PAGES_ORDER);
+ continue;
+ }
+ }
+
+ ret = -EAGAIN;
+ }
+
+#endif
+ return ret;
+}
+
+/**
+ * vmw_mksstat_reset_ioctl: Resets all mksGuestStat instance descriptors
+ * from the hypervisor.
+ *
+ * Discard all hypervisor PFN mappings, containing active mksGuestStat instance
+ * descriptors, unpin the related userspace pages and free the related kernel pages.
+ *
+ * @dev: Identifies the drm device.
+ * @data: Pointer to the ioctl argument.
+ * @file_priv: Identifies the caller; unused.
+ * Return: Zero on success, negative error code on error.
+ */
+
+int vmw_mksstat_reset_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct vmw_private *const dev_priv = vmw_priv(dev);
+ return vmw_mksstat_remove_all(dev_priv);
+}
+
+/**
+ * vmw_mksstat_add_ioctl: Creates a single userspace-originating mksGuestStat
+ * instance descriptor and registers that with the hypervisor.
+ *
+ * Create a hypervisor PFN mapping, containing a single mksGuestStat instance
+ * descriptor and pin the corresponding userspace pages.
+ *
+ * @dev: Identifies the drm device.
+ * @data: Pointer to the ioctl argument.
+ * @file_priv: Identifies the caller; unused.
+ * Return: Zero on success, negative error code on error.
+ */
+
+int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_vmw_mksstat_add_arg *arg =
+ (struct drm_vmw_mksstat_add_arg *) data;
+
+ struct vmw_private *const dev_priv = vmw_priv(dev);
+
+ struct page *page;
+ MKSGuestStatInstanceDescriptor *pdesc;
+ const size_t num_pages_stat = PFN_UP(arg->stat_len);
+ const size_t num_pages_info = PFN_UP(arg->info_len);
+ const size_t num_pages_strs = PFN_UP(arg->strs_len);
+ long desc_len;
+ long nr_pinned_stat;
+ long nr_pinned_info;
+ long nr_pinned_strs;
+ struct page *pages_stat[ARRAY_SIZE(pdesc->statPPNs)];
+ struct page *pages_info[ARRAY_SIZE(pdesc->infoPPNs)];
+ struct page *pages_strs[ARRAY_SIZE(pdesc->strsPPNs)];
+ size_t i, slot;
+
+ arg->id = -1;
+
+ if (!arg->stat || !arg->info || !arg->strs)
+ return -EINVAL;
+
+ if (!arg->stat_len || !arg->info_len || !arg->strs_len)
+ return -EINVAL;
+
+ if (!arg->description)
+ return -EINVAL;
+
+ if (num_pages_stat > ARRAY_SIZE(pdesc->statPPNs) ||
+ num_pages_info > ARRAY_SIZE(pdesc->infoPPNs) ||
+ num_pages_strs > ARRAY_SIZE(pdesc->strsPPNs))
+ return -EINVAL;
+
+ /* Find an available slot in the mksGuestStats user array and reserve it */
+ for (slot = 0; slot < ARRAY_SIZE(dev_priv->mksstat_user_pids); ++slot)
+ if (!atomic_cmpxchg(&dev_priv->mksstat_user_pids[slot], 0, MKSSTAT_PID_RESERVED))
+ break;
+
+ if (slot == ARRAY_SIZE(dev_priv->mksstat_user_pids))
+ return -ENOSPC;
+
+ BUG_ON(dev_priv->mksstat_user_pages[slot]);
+
+ /* Allocate a page for the instance descriptor */
+ page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+
+ if (!page) {
+ atomic_set(&dev_priv->mksstat_user_pids[slot], 0);
+ return -ENOMEM;
+ }
+
+ /* Set up the instance descriptor */
+ pdesc = page_address(page);
+
+ pdesc->reservedMBZ = 0;
+ pdesc->statStartVA = arg->stat;
+ pdesc->strsStartVA = arg->strs;
+ pdesc->statLength = arg->stat_len;
+ pdesc->infoLength = arg->info_len;
+ pdesc->strsLength = arg->strs_len;
+ desc_len = strncpy_from_user(pdesc->description, u64_to_user_ptr(arg->description),
+ ARRAY_SIZE(pdesc->description) - 1);
+
+ if (desc_len < 0) {
+ atomic_set(&dev_priv->mksstat_user_pids[slot], 0);
+ return -EFAULT;
+ }
+
+ reset_ppn_array(pdesc->statPPNs, ARRAY_SIZE(pdesc->statPPNs));
+ reset_ppn_array(pdesc->infoPPNs, ARRAY_SIZE(pdesc->infoPPNs));
+ reset_ppn_array(pdesc->strsPPNs, ARRAY_SIZE(pdesc->strsPPNs));
+
+ /* Pin mksGuestStat user pages and store those in the instance descriptor */
+ nr_pinned_stat = pin_user_pages(arg->stat, num_pages_stat, FOLL_LONGTERM, pages_stat, NULL);
+ if (num_pages_stat != nr_pinned_stat)
+ goto err_pin_stat;
+
+ for (i = 0; i < num_pages_stat; ++i)
+ pdesc->statPPNs[i] = page_to_pfn(pages_stat[i]);
+
+ nr_pinned_info = pin_user_pages(arg->info, num_pages_info, FOLL_LONGTERM, pages_info, NULL);
+ if (num_pages_info != nr_pinned_info)
+ goto err_pin_info;
+
+ for (i = 0; i < num_pages_info; ++i)
+ pdesc->infoPPNs[i] = page_to_pfn(pages_info[i]);
+
+ nr_pinned_strs = pin_user_pages(arg->strs, num_pages_strs, FOLL_LONGTERM, pages_strs, NULL);
+ if (num_pages_strs != nr_pinned_strs)
+ goto err_pin_strs;
+
+ for (i = 0; i < num_pages_strs; ++i)
+ pdesc->strsPPNs[i] = page_to_pfn(pages_strs[i]);
+
+ /* Send the descriptor to the host via a hypervisor call. The mksGuestStat
+ pages will remain in use until the user requests a matching remove stats
+ or a stats reset occurs. */
+ hypervisor_ppn_add((PPN64)page_to_pfn(page));
+
+ dev_priv->mksstat_user_pages[slot] = page;
+ atomic_set(&dev_priv->mksstat_user_pids[slot], task_pgrp_vnr(current));
+
+ arg->id = slot;
+
+ DRM_DEV_INFO(dev->dev, "pid=%d arg.description='%.*s' id=%zu\n", current->pid, (int)desc_len, pdesc->description, slot);
+
+ return 0;
+
+err_pin_strs:
+ if (nr_pinned_strs > 0)
+ unpin_user_pages(pages_strs, nr_pinned_strs);
+
+err_pin_info:
+ if (nr_pinned_info > 0)
+ unpin_user_pages(pages_info, nr_pinned_info);
+
+err_pin_stat:
+ if (nr_pinned_stat > 0)
+ unpin_user_pages(pages_stat, nr_pinned_stat);
+
+ atomic_set(&dev_priv->mksstat_user_pids[slot], 0);
+ __free_page(page);
+ return -ENOMEM;
+}
+
+/**
+ * vmw_mksstat_remove_ioctl: Removes a single userspace-originating mksGuestStat
+ * instance descriptor from the hypervisor.
+ *
+ * Discard a hypervisor PFN mapping, containing a single mksGuestStat instance
+ * descriptor and unpin the corresponding userspace pages.
+ *
+ * @dev: Identifies the drm device.
+ * @data: Pointer to the ioctl argument.
+ * @file_priv: Identifies the caller; unused.
+ * Return: Zero on success, negative error code on error.
+ */
+
+int vmw_mksstat_remove_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_vmw_mksstat_remove_arg *arg =
+ (struct drm_vmw_mksstat_remove_arg *) data;
+
+ struct vmw_private *const dev_priv = vmw_priv(dev);
+
+ const size_t slot = arg->id;
+ pid_t pgid, pid;
+
+ if (slot >= ARRAY_SIZE(dev_priv->mksstat_user_pids))
+ return -EINVAL;
+
+ DRM_DEV_INFO(dev->dev, "pid=%d arg.id=%zu\n", current->pid, slot);
+
+ pgid = task_pgrp_vnr(current);
+ pid = atomic_cmpxchg(&dev_priv->mksstat_user_pids[slot], pgid, MKSSTAT_PID_RESERVED);
+
+ if (!pid)
+ return 0;
+
+ if (pid == pgid) {
+ struct page *const page = dev_priv->mksstat_user_pages[slot];
+
+ BUG_ON(!page);
+
+ dev_priv->mksstat_user_pages[slot] = NULL;
+ atomic_set(&dev_priv->mksstat_user_pids[slot], 0);
+
+ hypervisor_ppn_remove((PPN64)page_to_pfn(page));
+
+ vmw_mksstat_cleanup_descriptor(page);
+ return 0;
+ }
+
+ return -EAGAIN;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 7b45393ad98e..8d1e869cc196 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -114,6 +114,7 @@ static void vmw_resource_release(struct kref *kref)
container_of(kref, struct vmw_resource, kref);
struct vmw_private *dev_priv = res->dev_priv;
int id;
+ int ret;
struct idr *idr = &dev_priv->res_idr[res->func->res_type];
spin_lock(&dev_priv->resource_lock);
@@ -122,7 +123,8 @@ static void vmw_resource_release(struct kref *kref)
if (res->backup) {
struct ttm_buffer_object *bo = &res->backup->base;
- ttm_bo_reserve(bo, false, false, NULL);
+ ret = ttm_bo_reserve(bo, false, false, NULL);
+ BUG_ON(ret);
if (vmw_resource_mob_attached(res) &&
res->func->unbind != NULL) {
struct ttm_validate_buffer val_buf;
@@ -351,8 +353,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,
static int vmw_resource_buf_alloc(struct vmw_resource *res,
bool interruptible)
{
- unsigned long size =
- (res->backup_size + PAGE_SIZE - 1) & PAGE_MASK;
+ unsigned long size = PFN_ALIGN(res->backup_size);
struct vmw_buffer_object *backup;
int ret;
@@ -1001,7 +1002,9 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible)
if (res->backup) {
vbo = res->backup;
- ttm_bo_reserve(&vbo->base, interruptible, false, NULL);
+ ret = ttm_bo_reserve(&vbo->base, interruptible, false, NULL);
+ if (ret)
+ goto out_no_validate;
if (!vbo->base.pin_count) {
ret = ttm_bo_validate
(&vbo->base,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 145430d14219..bd157fb21b45 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -954,8 +954,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
int i, ret;
if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
- DRM_INFO("Not using screen objects,"
- " missing cap SCREEN_OBJECT_2\n");
return -ENOSYS;
}
@@ -972,8 +970,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
drm_mode_config_reset(dev);
- DRM_INFO("Screen Objects Display Unit initialized\n");
-
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index b3c8d2da6f1a..b8dd62529104 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -981,8 +981,7 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv,
goto no_reserve;
/* Map and copy shader bytecode. */
- ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT,
- &map);
+ ret = ttm_bo_kmap(&buf->base, 0, PFN_UP(size), &map);
if (unlikely(ret != 0)) {
ttm_bo_unreserve(&buf->base);
goto no_reserve;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c
index c3a8d6e8380e..9efb4463ce99 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c
@@ -539,7 +539,8 @@ const SVGACOTableType vmw_so_cotables[] = {
[vmw_so_ds] = SVGA_COTABLE_DEPTHSTENCIL,
[vmw_so_rs] = SVGA_COTABLE_RASTERIZERSTATE,
[vmw_so_ss] = SVGA_COTABLE_SAMPLER,
- [vmw_so_so] = SVGA_COTABLE_STREAMOUTPUT
+ [vmw_so_so] = SVGA_COTABLE_STREAMOUTPUT,
+ [vmw_so_max]= SVGA_COTABLE_MAX
};
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 9e236f9f8a8a..d85310b2608d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -33,7 +33,7 @@
#include <drm/drm_vblank.h>
#include "vmwgfx_kms.h"
-#include "device_include/svga3d_surfacedefs.h"
+#include "vmw_surface_cache.h"
#define vmw_crtc_to_stdu(x) \
container_of(x, struct vmw_screen_target_display_unit, base.crtc)
@@ -1889,14 +1889,13 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
ret = vmw_stdu_init(dev_priv, i);
if (unlikely(ret != 0)) {
- DRM_ERROR("Failed to initialize STDU %d", i);
+ drm_err(&dev_priv->drm,
+ "Failed to initialize STDU %d", i);
return ret;
}
}
drm_mode_config_reset(dev);
- DRM_INFO("Screen Target Display device initialized\n");
-
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index 0835468bb2ee..5d53a5f9d123 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -31,6 +31,7 @@
#include "vmwgfx_resource_priv.h"
#include "vmwgfx_so.h"
#include "vmwgfx_binding.h"
+#include "vmw_surface_cache.h"
#include "device_include/svga3d_surfacedefs.h"
#define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
@@ -78,7 +79,7 @@ struct vmw_surface_offset {
* @boxes: Array of SVGA3dBoxes indicating dirty regions. One per subresource.
*/
struct vmw_surface_dirty {
- struct svga3dsurface_cache cache;
+ struct vmw_surface_cache cache;
size_t size;
u32 num_subres;
SVGA3dBox boxes[];
@@ -307,8 +308,8 @@ static void vmw_surface_dma_encode(struct vmw_surface *srf,
{
uint32_t i;
struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
- const struct svga3d_surface_desc *desc =
- svga3dsurface_get_desc(srf->metadata.format);
+ const struct SVGA3dSurfaceDesc *desc =
+ vmw_surface_get_desc(srf->metadata.format);
for (i = 0; i < srf->metadata.num_sizes; ++i) {
SVGA3dCmdHeader *header = &cmd->header;
@@ -323,8 +324,7 @@ static void vmw_surface_dma_encode(struct vmw_surface *srf,
body->guest.ptr = *ptr;
body->guest.ptr.offset += cur_offset->bo_offset;
- body->guest.pitch = svga3dsurface_calculate_pitch(desc,
- cur_size);
+ body->guest.pitch = vmw_surface_calculate_pitch(desc, cur_size);
body->host.sid = srf->res.id;
body->host.face = cur_offset->face;
body->host.mipmap = cur_offset->mip;
@@ -342,7 +342,7 @@ static void vmw_surface_dma_encode(struct vmw_surface *srf,
suffix->suffixSize = sizeof(*suffix);
suffix->maximumOffset =
- svga3dsurface_get_image_buffer_size(desc, cur_size,
+ vmw_surface_get_image_buffer_size(desc, cur_size,
body->guest.pitch);
suffix->flags.discard = 0;
suffix->flags.unsynchronized = 0;
@@ -432,7 +432,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res)
goto out_no_id;
}
- if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
+ if (unlikely(res->id >= SVGA3D_HB_MAX_SURFACE_IDS)) {
ret = -EBUSY;
goto out_no_fifo;
}
@@ -751,7 +751,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
struct vmw_surface_offset *cur_offset;
uint32_t num_sizes;
uint32_t size;
- const struct svga3d_surface_desc *desc;
+ const SVGA3dSurfaceDesc *desc;
if (unlikely(vmw_user_surface_size == 0))
vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
@@ -772,8 +772,8 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
- desc = svga3dsurface_get_desc(req->format);
- if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
+ desc = vmw_surface_get_desc(req->format);
+ if (unlikely(desc->blockDesc == SVGA3DBLOCKDESC_NONE)) {
VMW_DEBUG_USER("Invalid format %d for surface creation.\n",
req->format);
return -EINVAL;
@@ -833,13 +833,13 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
for (j = 0; j < metadata->mip_levels[i]; ++j) {
- uint32_t stride = svga3dsurface_calculate_pitch
- (desc, cur_size);
+ uint32_t stride = vmw_surface_calculate_pitch(
+ desc, cur_size);
cur_offset->face = i;
cur_offset->mip = j;
cur_offset->bo_offset = cur_bo_offset;
- cur_bo_offset += svga3dsurface_get_image_buffer_size
+ cur_bo_offset += vmw_surface_get_image_buffer_size
(desc, cur_size, stride);
++cur_offset;
++cur_size;
@@ -865,7 +865,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
user_srf->prime.base.shareable = false;
user_srf->prime.base.tfile = NULL;
if (drm_is_primary_client(file_priv))
- user_srf->master = drm_master_get(file_priv->master);
+ user_srf->master = drm_file_get_master(file_priv);
/**
* From this point, the generic resource management functions
@@ -1534,7 +1534,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
user_srf = container_of(srf, struct vmw_user_surface, srf);
if (drm_is_primary_client(file_priv))
- user_srf->master = drm_master_get(file_priv->master);
+ user_srf->master = drm_file_get_master(file_priv);
res = &user_srf->srf.res;
@@ -1711,10 +1711,10 @@ out_bad_resource:
* than partial z slices are dirtied.
*/
static void vmw_subres_dirty_add(struct vmw_surface_dirty *dirty,
- const struct svga3dsurface_loc *loc_start,
- const struct svga3dsurface_loc *loc_end)
+ const struct vmw_surface_loc *loc_start,
+ const struct vmw_surface_loc *loc_end)
{
- const struct svga3dsurface_cache *cache = &dirty->cache;
+ const struct vmw_surface_cache *cache = &dirty->cache;
SVGA3dBox *box = &dirty->boxes[loc_start->sub_resource];
u32 mip = loc_start->sub_resource % cache->num_mip_levels;
const struct drm_vmw_size *size = &cache->mip[mip].size;
@@ -1760,7 +1760,7 @@ static void vmw_subres_dirty_add(struct vmw_surface_dirty *dirty,
*/
static void vmw_subres_dirty_full(struct vmw_surface_dirty *dirty, u32 subres)
{
- const struct svga3dsurface_cache *cache = &dirty->cache;
+ const struct vmw_surface_cache *cache = &dirty->cache;
u32 mip = subres % cache->num_mip_levels;
const struct drm_vmw_size *size = &cache->mip[mip].size;
SVGA3dBox *box = &dirty->boxes[subres];
@@ -1783,15 +1783,15 @@ static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res,
struct vmw_surface_dirty *dirty =
(struct vmw_surface_dirty *) res->dirty;
size_t backup_end = res->backup_offset + res->backup_size;
- struct svga3dsurface_loc loc1, loc2;
- const struct svga3dsurface_cache *cache;
+ struct vmw_surface_loc loc1, loc2;
+ const struct vmw_surface_cache *cache;
start = max_t(size_t, start, res->backup_offset) - res->backup_offset;
end = min(end, backup_end) - res->backup_offset;
cache = &dirty->cache;
- svga3dsurface_get_loc(cache, &loc1, start);
- svga3dsurface_get_loc(cache, &loc2, end - 1);
- svga3dsurface_inc_loc(cache, &loc2);
+ vmw_surface_get_loc(cache, &loc1, start);
+ vmw_surface_get_loc(cache, &loc2, end - 1);
+ vmw_surface_inc_loc(cache, &loc2);
if (loc1.sheet != loc2.sheet) {
u32 sub_res;
@@ -1811,12 +1811,12 @@ static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res,
vmw_subres_dirty_add(dirty, &loc1, &loc2);
} else {
/* Dirty range covers multiple sub-resources */
- struct svga3dsurface_loc loc_min, loc_max;
+ struct vmw_surface_loc loc_min, loc_max;
u32 sub_res;
- svga3dsurface_max_loc(cache, loc1.sub_resource, &loc_max);
+ vmw_surface_max_loc(cache, loc1.sub_resource, &loc_max);
vmw_subres_dirty_add(dirty, &loc1, &loc_max);
- svga3dsurface_min_loc(cache, loc2.sub_resource - 1, &loc_min);
+ vmw_surface_min_loc(cache, loc2.sub_resource - 1, &loc_min);
vmw_subres_dirty_add(dirty, &loc_min, &loc2);
for (sub_res = loc1.sub_resource + 1;
sub_res < loc2.sub_resource - 1; ++sub_res)
@@ -1833,7 +1833,7 @@ static void vmw_surface_buf_dirty_range_add(struct vmw_resource *res,
{
struct vmw_surface_dirty *dirty =
(struct vmw_surface_dirty *) res->dirty;
- const struct svga3dsurface_cache *cache = &dirty->cache;
+ const struct vmw_surface_cache *cache = &dirty->cache;
size_t backup_end = res->backup_offset + cache->mip_chain_bytes;
SVGA3dBox *box = &dirty->boxes[0];
u32 box_c2;
@@ -1872,12 +1872,11 @@ static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start,
static int vmw_surface_dirty_sync(struct vmw_resource *res)
{
struct vmw_private *dev_priv = res->dev_priv;
- bool has_dx = 0;
u32 i, num_dirty;
struct vmw_surface_dirty *dirty =
(struct vmw_surface_dirty *) res->dirty;
size_t alloc_size;
- const struct svga3dsurface_cache *cache = &dirty->cache;
+ const struct vmw_surface_cache *cache = &dirty->cache;
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXUpdateSubResource body;
@@ -1899,7 +1898,7 @@ static int vmw_surface_dirty_sync(struct vmw_resource *res)
if (!num_dirty)
goto out;
- alloc_size = num_dirty * ((has_dx) ? sizeof(*cmd1) : sizeof(*cmd2));
+ alloc_size = num_dirty * ((has_sm4_context(dev_priv)) ? sizeof(*cmd1) : sizeof(*cmd2));
cmd = VMW_CMD_RESERVE(dev_priv, alloc_size);
if (!cmd)
return -ENOMEM;
@@ -1917,7 +1916,7 @@ static int vmw_surface_dirty_sync(struct vmw_resource *res)
* DX_UPDATE_SUBRESOURCE is aware of array surfaces.
* UPDATE_GB_IMAGE is not.
*/
- if (has_dx) {
+ if (has_sm4_context(dev_priv)) {
cmd1->header.id = SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE;
cmd1->header.size = sizeof(cmd1->body);
cmd1->body.sid = res->id;
@@ -1990,7 +1989,7 @@ static int vmw_surface_dirty_alloc(struct vmw_resource *res)
}
num_samples = max_t(u32, 1, metadata->multisample_count);
- ret = svga3dsurface_setup_cache(&metadata->base_size, metadata->format,
+ ret = vmw_surface_setup_cache(&metadata->base_size, metadata->format,
num_mip, num_layers, num_samples,
&dirty->cache);
if (ret)
@@ -2081,7 +2080,7 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv,
*srf_out = NULL;
if (req->scanout) {
- if (!svga3dsurface_is_screen_target_format(req->format)) {
+ if (!vmw_surface_is_screen_target_format(req->format)) {
VMW_DEBUG_USER("Invalid Screen Target surface format.");
return -EINVAL;
}
@@ -2096,10 +2095,10 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv,
return -EINVAL;
}
} else {
- const struct svga3d_surface_desc *desc =
- svga3dsurface_get_desc(req->format);
+ const SVGA3dSurfaceDesc *desc =
+ vmw_surface_get_desc(req->format);
- if (desc->block_desc == SVGA3DBLOCKDESC_NONE) {
+ if (desc->blockDesc == SVGA3DBLOCKDESC_NONE) {
VMW_DEBUG_USER("Invalid surface format.\n");
return -EINVAL;
}
@@ -2148,11 +2147,12 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv,
sample_count = metadata->multisample_count;
srf->res.backup_size =
- svga3dsurface_get_serialized_size_extended(metadata->format,
- metadata->base_size,
- metadata->mip_levels[0],
- num_layers,
- sample_count);
+ vmw_surface_get_serialized_size_extended(
+ metadata->format,
+ metadata->base_size,
+ metadata->mip_levels[0],
+ num_layers,
+ sample_count);
if (metadata->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
srf->res.backup_size += sizeof(SVGA3dDXSOState);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
index 0488042fb287..8b8991e3ed2d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
@@ -222,36 +222,6 @@ static bool __vmw_piter_sg_next(struct vmw_piter *viter)
}
-/**
- * __vmw_piter_non_sg_page: Helper functions to return a pointer
- * to the current page.
- *
- * @viter: Pointer to the iterator
- *
- * These functions return a pointer to the page currently
- * pointed to by @viter. Functions are selected depending on the
- * current mapping mode.
- */
-static struct page *__vmw_piter_non_sg_page(struct vmw_piter *viter)
-{
- return viter->pages[viter->i];
-}
-
-/**
- * __vmw_piter_phys_addr: Helper functions to return the DMA
- * address of the current page.
- *
- * @viter: Pointer to the iterator
- *
- * These functions return the DMA address of the page currently
- * pointed to by @viter. Functions are selected depending on the
- * current mapping mode.
- */
-static dma_addr_t __vmw_piter_phys_addr(struct vmw_piter *viter)
-{
- return page_to_phys(viter->pages[viter->i]);
-}
-
static dma_addr_t __vmw_piter_dma_addr(struct vmw_piter *viter)
{
return viter->addrs[viter->i];
@@ -279,13 +249,8 @@ void vmw_piter_start(struct vmw_piter *viter, const struct vmw_sg_table *vsgt,
{
viter->i = p_offset - 1;
viter->num_pages = vsgt->num_pages;
- viter->page = &__vmw_piter_non_sg_page;
viter->pages = vsgt->pages;
switch (vsgt->mode) {
- case vmw_dma_phys:
- viter->next = &__vmw_piter_non_sg_next;
- viter->dma_address = &__vmw_piter_phys_addr;
- break;
case vmw_dma_alloc_coherent:
viter->next = &__vmw_piter_non_sg_next;
viter->dma_address = &__vmw_piter_dma_addr;
@@ -363,7 +328,6 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
int ret = 0;
static size_t sgl_size;
static size_t sgt_size;
- struct scatterlist *sg;
if (vmw_tt->mapped)
return 0;
@@ -386,15 +350,12 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
if (unlikely(ret != 0))
return ret;
- sg = __sg_alloc_table_from_pages(&vmw_tt->sgt, vsgt->pages,
- vsgt->num_pages, 0,
- (unsigned long) vsgt->num_pages << PAGE_SHIFT,
- dma_get_max_seg_size(dev_priv->drm.dev),
- NULL, 0, GFP_KERNEL);
- if (IS_ERR(sg)) {
- ret = PTR_ERR(sg);
+ ret = sg_alloc_table_from_pages_segment(
+ &vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0,
+ (unsigned long)vsgt->num_pages << PAGE_SHIFT,
+ dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL);
+ if (ret)
goto out_sg_alloc_fail;
- }
if (vsgt->num_pages > vmw_tt->sgt.orig_nents) {
uint64_t over_alloc =
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
index 8338b1d20f2a..b09094b50c5d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
@@ -586,13 +586,13 @@ int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr)
container_of(entry->base.bo, typeof(*vbo), base);
if (entry->cpu_blit) {
- struct ttm_operation_ctx ctx = {
+ struct ttm_operation_ctx ttm_ctx = {
.interruptible = intr,
.no_wait_gpu = false
};
ret = ttm_bo_validate(entry->base.bo,
- &vmw_nonfixed_placement, &ctx);
+ &vmw_nonfixed_placement, &ttm_ctx);
} else {
ret = vmw_validation_bo_validate_single
(entry->base.bo, intr, entry->as_mob);
diff --git a/drivers/gpu/drm/xen/xen_drm_front_kms.c b/drivers/gpu/drm/xen/xen_drm_front_kms.c
index 371202ebe900..cfda74490765 100644
--- a/drivers/gpu/drm/xen/xen_drm_front_kms.c
+++ b/drivers/gpu/drm/xen/xen_drm_front_kms.c
@@ -302,7 +302,6 @@ static const struct drm_simple_display_pipe_funcs display_funcs = {
.mode_valid = display_mode_valid,
.enable = display_enable,
.disable = display_disable,
- .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
.check = display_check,
.update = display_update,
};
diff --git a/drivers/gpu/drm/xlnx/Kconfig b/drivers/gpu/drm/xlnx/Kconfig
index b52c6cdfc0b8..c3d08269faa9 100644
--- a/drivers/gpu/drm/xlnx/Kconfig
+++ b/drivers/gpu/drm/xlnx/Kconfig
@@ -3,6 +3,8 @@ config DRM_ZYNQMP_DPSUB
depends on ARCH_ZYNQMP || COMPILE_TEST
depends on COMMON_CLK && DRM && OF
depends on DMADEVICES
+ depends on PHY_XILINX_ZYNQMP
+ depends on XILINX_ZYNQMP_DPDMA
select DMA_ENGINE
select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index 109d627968ac..ff2b308d8651 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -91,7 +91,7 @@ struct zynqmp_disp_format {
};
/**
- * enum zynqmp_disp_id - Layer identifier
+ * enum zynqmp_disp_layer_id - Layer identifier
* @ZYNQMP_DISP_LAYER_VID: Video layer
* @ZYNQMP_DISP_LAYER_GFX: Graphics layer
*/
@@ -159,42 +159,16 @@ struct zynqmp_disp_layer {
};
/**
- * struct zynqmp_disp_blend - Blender
- * @base: Registers I/O base address
- */
-struct zynqmp_disp_blend {
- void __iomem *base;
-};
-
-/**
- * struct zynqmp_disp_avbuf - Audio/video buffer manager
- * @base: Registers I/O base address
- */
-struct zynqmp_disp_avbuf {
- void __iomem *base;
-};
-
-/**
- * struct zynqmp_disp_audio - Audio mixer
- * @base: Registers I/O base address
- * @clk: Audio clock
- * @clk_from_ps: True of the audio clock comes from PS, false from PL
- */
-struct zynqmp_disp_audio {
- void __iomem *base;
- struct clk *clk;
- bool clk_from_ps;
-};
-
-/**
* struct zynqmp_disp - Display controller
* @dev: Device structure
* @drm: DRM core
* @dpsub: Display subsystem
* @crtc: DRM CRTC
- * @blend: Blender (video rendering pipeline)
- * @avbuf: Audio/video buffer manager
- * @audio: Audio mixer
+ * @blend.base: Register I/O base address for the blender
+ * @avbuf.base: Register I/O base address for the audio/video buffer manager
+ * @audio.base: Registers I/O base address for the audio mixer
+ * @audio.clk: Audio clock
+ * @audio.clk_from_ps: True of the audio clock comes from PS, false from PL
* @layers: Layers (planes)
* @event: Pending vblank event request
* @pclk: Pixel clock
@@ -207,9 +181,17 @@ struct zynqmp_disp {
struct drm_crtc crtc;
- struct zynqmp_disp_blend blend;
- struct zynqmp_disp_avbuf avbuf;
- struct zynqmp_disp_audio audio;
+ struct {
+ void __iomem *base;
+ } blend;
+ struct {
+ void __iomem *base;
+ } avbuf;
+ struct {
+ void __iomem *base;
+ struct clk *clk;
+ bool clk_from_ps;
+ } audio;
struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
@@ -423,51 +405,60 @@ static const struct zynqmp_disp_format avbuf_gfx_fmts[] = {
},
};
-static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp_avbuf *avbuf, int reg)
+static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg)
{
- return readl(avbuf->base + reg);
+ return readl(disp->avbuf.base + reg);
}
-static void zynqmp_disp_avbuf_write(struct zynqmp_disp_avbuf *avbuf,
- int reg, u32 val)
+static void zynqmp_disp_avbuf_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, avbuf->base + reg);
+ writel(val, disp->avbuf.base + reg);
+}
+
+static bool zynqmp_disp_layer_is_gfx(const struct zynqmp_disp_layer *layer)
+{
+ return layer->id == ZYNQMP_DISP_LAYER_GFX;
+}
+
+static bool zynqmp_disp_layer_is_video(const struct zynqmp_disp_layer *layer)
+{
+ return layer->id == ZYNQMP_DISP_LAYER_VID;
}
/**
* zynqmp_disp_avbuf_set_format - Set the input format for a layer
- * @avbuf: Audio/video buffer manager
- * @layer: The layer ID
+ * @disp: Display controller
+ * @layer: The layer
* @fmt: The format information
*
* Set the video buffer manager format for @layer to @fmt.
*/
-static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp_avbuf *avbuf,
- enum zynqmp_disp_layer_id layer,
+static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp *disp,
+ struct zynqmp_disp_layer *layer,
const struct zynqmp_disp_format *fmt)
{
unsigned int i;
u32 val;
- val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_FMT);
- val &= layer == ZYNQMP_DISP_LAYER_VID
+ val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);
+ val &= zynqmp_disp_layer_is_video(layer)
? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK
: ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
val |= fmt->buf_fmt;
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_FMT, val);
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_FMT, val);
for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++) {
- unsigned int reg = layer == ZYNQMP_DISP_LAYER_VID
+ unsigned int reg = zynqmp_disp_layer_is_video(layer)
? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i)
: ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i);
- zynqmp_disp_avbuf_write(avbuf, reg, fmt->sf[i]);
+ zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]);
}
}
/**
* zynqmp_disp_avbuf_set_clocks_sources - Set the clocks sources
- * @avbuf: Audio/video buffer manager
+ * @disp: Display controller
* @video_from_ps: True if the video clock originates from the PS
* @audio_from_ps: True if the audio clock originates from the PS
* @timings_internal: True if video timings are generated internally
@@ -477,7 +468,7 @@ static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp_avbuf *avbuf,
* generated internally or externally.
*/
static void
-zynqmp_disp_avbuf_set_clocks_sources(struct zynqmp_disp_avbuf *avbuf,
+zynqmp_disp_avbuf_set_clocks_sources(struct zynqmp_disp *disp,
bool video_from_ps, bool audio_from_ps,
bool timings_internal)
{
@@ -490,16 +481,16 @@ zynqmp_disp_avbuf_set_clocks_sources(struct zynqmp_disp_avbuf *avbuf,
if (timings_internal)
val |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_CLK_SRC, val);
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_CLK_SRC, val);
}
/**
* zynqmp_disp_avbuf_enable_channels - Enable buffer channels
- * @avbuf: Audio/video buffer manager
+ * @disp: Display controller
*
* Enable all (video and audio) buffer channels.
*/
-static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf)
+static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp *disp)
{
unsigned int i;
u32 val;
@@ -509,7 +500,7 @@ static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf)
ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT);
for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS; i++)
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_CHBUF(i),
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_CHBUF(i),
val);
val = ZYNQMP_DISP_AV_BUF_CHBUF_EN |
@@ -517,75 +508,75 @@ static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf)
ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT);
for (; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_CHBUF(i),
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_CHBUF(i),
val);
}
/**
* zynqmp_disp_avbuf_disable_channels - Disable buffer channels
- * @avbuf: Audio/video buffer manager
+ * @disp: Display controller
*
* Disable all (video and audio) buffer channels.
*/
-static void zynqmp_disp_avbuf_disable_channels(struct zynqmp_disp_avbuf *avbuf)
+static void zynqmp_disp_avbuf_disable_channels(struct zynqmp_disp *disp)
{
unsigned int i;
for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_CHBUF(i),
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_CHBUF(i),
ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH);
}
/**
* zynqmp_disp_avbuf_enable_audio - Enable audio
- * @avbuf: Audio/video buffer manager
+ * @disp: Display controller
*
* Enable all audio buffers with a non-live (memory) source.
*/
-static void zynqmp_disp_avbuf_enable_audio(struct zynqmp_disp_avbuf *avbuf)
+static void zynqmp_disp_avbuf_enable_audio(struct zynqmp_disp *disp)
{
u32 val;
- val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT);
+ val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT);
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT, val);
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_OUTPUT, val);
}
/**
* zynqmp_disp_avbuf_disable_audio - Disable audio
- * @avbuf: Audio/video buffer manager
+ * @disp: Display controller
*
* Disable all audio buffers.
*/
-static void zynqmp_disp_avbuf_disable_audio(struct zynqmp_disp_avbuf *avbuf)
+static void zynqmp_disp_avbuf_disable_audio(struct zynqmp_disp *disp)
{
u32 val;
- val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT);
+ val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT);
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE;
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT, val);
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_OUTPUT, val);
}
/**
* zynqmp_disp_avbuf_enable_video - Enable a video layer
- * @avbuf: Audio/video buffer manager
- * @layer: The layer ID
+ * @disp: Display controller
+ * @layer: The layer
* @mode: Operating mode of layer
*
* Enable the video/graphics buffer for @layer.
*/
-static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp_avbuf *avbuf,
- enum zynqmp_disp_layer_id layer,
+static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp *disp,
+ struct zynqmp_disp_layer *layer,
enum zynqmp_disp_layer_mode mode)
{
u32 val;
- val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT);
- if (layer == ZYNQMP_DISP_LAYER_VID) {
+ val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT);
+ if (zynqmp_disp_layer_is_video(layer)) {
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM;
@@ -599,52 +590,52 @@ static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp_avbuf *avbuf,
else
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE;
}
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT, val);
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_OUTPUT, val);
}
/**
* zynqmp_disp_avbuf_disable_video - Disable a video layer
- * @avbuf: Audio/video buffer manager
- * @layer: The layer ID
+ * @disp: Display controller
+ * @layer: The layer
*
* Disable the video/graphics buffer for @layer.
*/
-static void zynqmp_disp_avbuf_disable_video(struct zynqmp_disp_avbuf *avbuf,
- enum zynqmp_disp_layer_id layer)
+static void zynqmp_disp_avbuf_disable_video(struct zynqmp_disp *disp,
+ struct zynqmp_disp_layer *layer)
{
u32 val;
- val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT);
- if (layer == ZYNQMP_DISP_LAYER_VID) {
+ val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT);
+ if (zynqmp_disp_layer_is_video(layer)) {
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE;
} else {
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE;
}
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT, val);
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_OUTPUT, val);
}
/**
* zynqmp_disp_avbuf_enable - Enable the video pipe
- * @avbuf: Audio/video buffer manager
+ * @disp: Display controller
*
* De-assert the video pipe reset.
*/
-static void zynqmp_disp_avbuf_enable(struct zynqmp_disp_avbuf *avbuf)
+static void zynqmp_disp_avbuf_enable(struct zynqmp_disp *disp)
{
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_SRST_REG, 0);
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_SRST_REG, 0);
}
/**
* zynqmp_disp_avbuf_disable - Disable the video pipe
- * @avbuf: Audio/video buffer manager
+ * @disp: Display controller
*
* Assert the video pipe reset.
*/
-static void zynqmp_disp_avbuf_disable(struct zynqmp_disp_avbuf *avbuf)
+static void zynqmp_disp_avbuf_disable(struct zynqmp_disp *disp)
{
- zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_SRST_REG,
+ zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_SRST_REG,
ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST);
}
@@ -652,10 +643,9 @@ static void zynqmp_disp_avbuf_disable(struct zynqmp_disp_avbuf *avbuf)
* Blender (Video Pipeline)
*/
-static void zynqmp_disp_blend_write(struct zynqmp_disp_blend *blend,
- int reg, u32 val)
+static void zynqmp_disp_blend_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, blend->base + reg);
+ writel(val, disp->blend.base + reg);
}
/*
@@ -701,12 +691,12 @@ static const u32 csc_sdtv_to_rgb_offsets[] = {
/**
* zynqmp_disp_blend_set_output_format - Set the output format of the blender
- * @blend: Blender object
+ * @disp: Display controller
* @format: Output format
*
* Set the output format of the blender to @format.
*/
-static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend,
+static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp *disp,
enum zynqmp_dpsub_format format)
{
static const unsigned int blend_output_fmts[] = {
@@ -722,7 +712,7 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend,
const u32 *offsets;
unsigned int i;
- zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt);
+ zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt);
if (fmt == ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB) {
coeffs = csc_identity_matrix;
offsets = csc_zero_offsets;
@@ -732,19 +722,19 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend,
}
for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
- zynqmp_disp_blend_write(blend,
+ zynqmp_disp_blend_write(disp,
ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF(i),
coeffs[i]);
for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
- zynqmp_disp_blend_write(blend,
+ zynqmp_disp_blend_write(disp,
ZYNQMP_DISP_V_BLEND_OUTCSC_OFFSET(i),
offsets[i]);
}
/**
* zynqmp_disp_blend_set_bg_color - Set the background color
- * @blend: Blender object
+ * @disp: Display controller
* @rcr: Red/Cr color component
* @gy: Green/Y color component
* @bcb: Blue/Cb color component
@@ -753,31 +743,31 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend,
* B or Cr, Y and Cb components respectively depending on the selected output
* format.
*/
-static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp_blend *blend,
+static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp *disp,
u32 rcr, u32 gy, u32 bcb)
{
- zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_BG_CLR_0, rcr);
- zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_BG_CLR_1, gy);
- zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_BG_CLR_2, bcb);
+ zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_BG_CLR_0, rcr);
+ zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_BG_CLR_1, gy);
+ zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_BG_CLR_2, bcb);
}
/**
* zynqmp_disp_blend_set_global_alpha - Configure global alpha blending
- * @blend: Blender object
+ * @disp: Display controller
* @enable: True to enable global alpha blending
* @alpha: Global alpha value (ignored if @enabled is false)
*/
-static void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp_blend *blend,
+static void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp *disp,
bool enable, u32 alpha)
{
- zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA,
+ zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA,
ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_VALUE(alpha) |
(enable ? ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_EN : 0));
}
/**
* zynqmp_disp_blend_layer_set_csc - Configure colorspace conversion for layer
- * @blend: Blender object
+ * @disp: Display controller
* @layer: The layer
* @coeffs: Colorspace conversion matrix
* @offsets: Colorspace conversion offsets
@@ -786,7 +776,7 @@ static void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp_blend *blend,
* Columns of the matrix are automatically swapped based on the input format to
* handle RGB and YCrCb components permutations.
*/
-static void zynqmp_disp_blend_layer_set_csc(struct zynqmp_disp_blend *blend,
+static void zynqmp_disp_blend_layer_set_csc(struct zynqmp_disp *disp,
struct zynqmp_disp_layer *layer,
const u16 *coeffs,
const u32 *offsets)
@@ -807,32 +797,32 @@ static void zynqmp_disp_blend_layer_set_csc(struct zynqmp_disp_blend *blend,
}
}
- if (layer->id == ZYNQMP_DISP_LAYER_VID)
+ if (zynqmp_disp_layer_is_video(layer))
reg = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF(0);
else
reg = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF(0);
for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i += 3, reg += 12) {
- zynqmp_disp_blend_write(blend, reg + 0, coeffs[i + swap[0]]);
- zynqmp_disp_blend_write(blend, reg + 4, coeffs[i + swap[1]]);
- zynqmp_disp_blend_write(blend, reg + 8, coeffs[i + swap[2]]);
+ zynqmp_disp_blend_write(disp, reg + 0, coeffs[i + swap[0]]);
+ zynqmp_disp_blend_write(disp, reg + 4, coeffs[i + swap[1]]);
+ zynqmp_disp_blend_write(disp, reg + 8, coeffs[i + swap[2]]);
}
- if (layer->id == ZYNQMP_DISP_LAYER_VID)
+ if (zynqmp_disp_layer_is_video(layer))
reg = ZYNQMP_DISP_V_BLEND_IN1CSC_OFFSET(0);
else
reg = ZYNQMP_DISP_V_BLEND_IN2CSC_OFFSET(0);
for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
- zynqmp_disp_blend_write(blend, reg + i * 4, offsets[i]);
+ zynqmp_disp_blend_write(disp, reg + i * 4, offsets[i]);
}
/**
* zynqmp_disp_blend_layer_enable - Enable a layer
- * @blend: Blender object
+ * @disp: Display controller
* @layer: The layer
*/
-static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
+static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp *disp,
struct zynqmp_disp_layer *layer)
{
const u16 *coeffs;
@@ -844,7 +834,7 @@ static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
(layer->drm_fmt->hsub > 1 ?
ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US : 0);
- zynqmp_disp_blend_write(blend,
+ zynqmp_disp_blend_write(disp,
ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id),
val);
@@ -856,22 +846,22 @@ static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
offsets = csc_zero_offsets;
}
- zynqmp_disp_blend_layer_set_csc(blend, layer, coeffs, offsets);
+ zynqmp_disp_blend_layer_set_csc(disp, layer, coeffs, offsets);
}
/**
* zynqmp_disp_blend_layer_disable - Disable a layer
- * @blend: Blender object
+ * @disp: Display controller
* @layer: The layer
*/
-static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend,
+static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp *disp,
struct zynqmp_disp_layer *layer)
{
- zynqmp_disp_blend_write(blend,
+ zynqmp_disp_blend_write(disp,
ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id),
0);
- zynqmp_disp_blend_layer_set_csc(blend, layer, csc_zero_matrix,
+ zynqmp_disp_blend_layer_set_csc(disp, layer, csc_zero_matrix,
csc_zero_offsets);
}
@@ -879,57 +869,55 @@ static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend,
* Audio Mixer
*/
-static void zynqmp_disp_audio_write(struct zynqmp_disp_audio *audio,
- int reg, u32 val)
+static void zynqmp_disp_audio_write(struct zynqmp_disp *disp, int reg, u32 val)
{
- writel(val, audio->base + reg);
+ writel(val, disp->audio.base + reg);
}
/**
* zynqmp_disp_audio_enable - Enable the audio mixer
- * @audio: Audio mixer
+ * @disp: Display controller
*
* Enable the audio mixer by de-asserting the soft reset. The audio state is set to
* default values by the reset, set the default mixer volume explicitly.
*/
-static void zynqmp_disp_audio_enable(struct zynqmp_disp_audio *audio)
+static void zynqmp_disp_audio_enable(struct zynqmp_disp *disp)
{
/* Clear the audio soft reset register as it's an non-reset flop. */
- zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
- zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_MIXER_VOLUME,
+ zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
+ zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_MIXER_VOLUME,
ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE);
}
/**
* zynqmp_disp_audio_disable - Disable the audio mixer
- * @audio: Audio mixer
+ * @disp: Display controller
*
* Disable the audio mixer by asserting its soft reset.
*/
-static void zynqmp_disp_audio_disable(struct zynqmp_disp_audio *audio)
+static void zynqmp_disp_audio_disable(struct zynqmp_disp *disp)
{
- zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_SOFT_RESET,
+ zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_SOFT_RESET,
ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
}
-static void zynqmp_disp_audio_init(struct device *dev,
- struct zynqmp_disp_audio *audio)
+static void zynqmp_disp_audio_init(struct zynqmp_disp *disp)
{
/* Try the live PL audio clock. */
- audio->clk = devm_clk_get(dev, "dp_live_audio_aclk");
- if (!IS_ERR(audio->clk)) {
- audio->clk_from_ps = false;
+ disp->audio.clk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
+ if (!IS_ERR(disp->audio.clk)) {
+ disp->audio.clk_from_ps = false;
return;
}
/* If the live PL audio clock is not valid, fall back to PS clock. */
- audio->clk = devm_clk_get(dev, "dp_aud_clk");
- if (!IS_ERR(audio->clk)) {
- audio->clk_from_ps = true;
+ disp->audio.clk = devm_clk_get(disp->dev, "dp_aud_clk");
+ if (!IS_ERR(disp->audio.clk)) {
+ disp->audio.clk_from_ps = true;
return;
}
- dev_err(dev, "audio disabled due to missing clock\n");
+ dev_err(disp->dev, "audio disabled due to missing clock\n");
}
/* -----------------------------------------------------------------------------
@@ -1025,9 +1013,9 @@ zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer,
*/
static void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer)
{
- zynqmp_disp_avbuf_enable_video(&layer->disp->avbuf, layer->id,
+ zynqmp_disp_avbuf_enable_video(layer->disp, layer,
ZYNQMP_DISP_LAYER_NONLIVE);
- zynqmp_disp_blend_layer_enable(&layer->disp->blend, layer);
+ zynqmp_disp_blend_layer_enable(layer->disp, layer);
layer->mode = ZYNQMP_DISP_LAYER_NONLIVE;
}
@@ -1046,8 +1034,8 @@ static void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer)
for (i = 0; i < layer->drm_fmt->num_planes; i++)
dmaengine_terminate_sync(layer->dmas[i].chan);
- zynqmp_disp_avbuf_disable_video(&layer->disp->avbuf, layer->id);
- zynqmp_disp_blend_layer_disable(&layer->disp->blend, layer);
+ zynqmp_disp_avbuf_disable_video(layer->disp, layer);
+ zynqmp_disp_blend_layer_disable(layer->disp, layer);
}
/**
@@ -1067,8 +1055,7 @@ static void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format);
layer->drm_fmt = info;
- zynqmp_disp_avbuf_set_format(&layer->disp->avbuf, layer->id,
- layer->disp_fmt);
+ zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt);
/*
* Set slave_id for each DMA channel to indicate they're part of a
@@ -1175,6 +1162,10 @@ zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
return;
zynqmp_disp_layer_disable(layer);
+
+ if (zynqmp_disp_layer_is_gfx(layer))
+ zynqmp_disp_blend_set_global_alpha(layer->disp, false,
+ plane->state->alpha >> 8);
}
static void
@@ -1204,6 +1195,10 @@ zynqmp_disp_plane_atomic_update(struct drm_plane *plane,
zynqmp_disp_layer_update(layer, new_state);
+ if (zynqmp_disp_layer_is_gfx(layer))
+ zynqmp_disp_blend_set_global_alpha(layer->disp, true,
+ plane->state->alpha >> 8);
+
/* Enable or re-enable the plane is the format has changed. */
if (format_changed)
zynqmp_disp_layer_enable(layer);
@@ -1244,8 +1239,8 @@ static int zynqmp_disp_create_planes(struct zynqmp_disp *disp)
drm_formats[j] = layer->info->formats[j].drm_fmt;
/* Graphics layer is primary, and video layer is overlay. */
- type = i == ZYNQMP_DISP_LAYER_GFX
- ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+ type = zynqmp_disp_layer_is_video(layer)
+ ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY;
ret = drm_universal_plane_init(disp->drm, &layer->plane, 0,
&zynqmp_disp_plane_funcs,
drm_formats,
@@ -1256,6 +1251,10 @@ static int zynqmp_disp_create_planes(struct zynqmp_disp *disp)
drm_plane_helper_add(&layer->plane,
&zynqmp_disp_plane_helper_funcs);
+
+ drm_plane_create_zpos_immutable_property(&layer->plane, i);
+ if (zynqmp_disp_layer_is_gfx(layer))
+ drm_plane_create_alpha_property(&layer->plane);
}
return 0;
@@ -1387,14 +1386,14 @@ err:
*/
static void zynqmp_disp_enable(struct zynqmp_disp *disp)
{
- zynqmp_disp_avbuf_enable(&disp->avbuf);
+ zynqmp_disp_avbuf_enable(disp);
/* Choose clock source based on the DT clock handle. */
- zynqmp_disp_avbuf_set_clocks_sources(&disp->avbuf, disp->pclk_from_ps,
+ zynqmp_disp_avbuf_set_clocks_sources(disp, disp->pclk_from_ps,
disp->audio.clk_from_ps, true);
- zynqmp_disp_avbuf_enable_channels(&disp->avbuf);
- zynqmp_disp_avbuf_enable_audio(&disp->avbuf);
+ zynqmp_disp_avbuf_enable_channels(disp);
+ zynqmp_disp_avbuf_enable_audio(disp);
- zynqmp_disp_audio_enable(&disp->audio);
+ zynqmp_disp_audio_enable(disp);
}
/**
@@ -1403,11 +1402,11 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp)
*/
static void zynqmp_disp_disable(struct zynqmp_disp *disp)
{
- zynqmp_disp_audio_disable(&disp->audio);
+ zynqmp_disp_audio_disable(disp);
- zynqmp_disp_avbuf_disable_audio(&disp->avbuf);
- zynqmp_disp_avbuf_disable_channels(&disp->avbuf);
- zynqmp_disp_avbuf_disable(&disp->avbuf);
+ zynqmp_disp_avbuf_disable_audio(disp);
+ zynqmp_disp_avbuf_disable_channels(disp);
+ zynqmp_disp_avbuf_disable(disp);
}
static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
@@ -1452,9 +1451,10 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
int ret, vrefresh;
+ pm_runtime_get_sync(disp->dev);
+
zynqmp_disp_crtc_setup_clock(crtc, adjusted_mode);
- pm_runtime_get_sync(disp->dev);
ret = clk_prepare_enable(disp->pclk);
if (ret) {
dev_err(disp->dev, "failed to enable a pixel clock\n");
@@ -1462,10 +1462,8 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
return;
}
- zynqmp_disp_blend_set_output_format(&disp->blend,
- ZYNQMP_DPSUB_FORMAT_RGB);
- zynqmp_disp_blend_set_bg_color(&disp->blend, 0, 0, 0);
- zynqmp_disp_blend_set_global_alpha(&disp->blend, false, 0);
+ zynqmp_disp_blend_set_output_format(disp, ZYNQMP_DPSUB_FORMAT_RGB);
+ zynqmp_disp_blend_set_bg_color(disp, 0, 0, 0);
zynqmp_disp_enable(disp);
@@ -1674,7 +1672,7 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
disp->pclk_from_ps = true;
}
- zynqmp_disp_audio_init(disp->dev, &disp->audio);
+ zynqmp_disp_audio_init(disp);
ret = zynqmp_disp_create_layers(disp);
if (ret)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index 82430ca9b913..6f588dc09ba6 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -402,10 +402,6 @@ static int zynqmp_dp_phy_init(struct zynqmp_dp *dp)
}
}
- ret = zynqmp_dp_reset(dp, false);
- if (ret < 0)
- return ret;
-
zynqmp_dp_clr(dp, ZYNQMP_DP_PHY_RESET, ZYNQMP_DP_PHY_RESET_ALL_RESET);
/*
@@ -441,8 +437,6 @@ static void zynqmp_dp_phy_exit(struct zynqmp_dp *dp)
ret);
}
- zynqmp_dp_reset(dp, true);
-
for (i = 0; i < dp->num_lanes; i++) {
ret = phy_exit(dp->phy[i]);
if (ret)
@@ -1683,9 +1677,13 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
return PTR_ERR(dp->reset);
}
+ ret = zynqmp_dp_reset(dp, false);
+ if (ret < 0)
+ return ret;
+
ret = zynqmp_dp_phy_probe(dp);
if (ret)
- return ret;
+ goto err_reset;
/* Initialize the hardware. */
zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN,
@@ -1697,7 +1695,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
ret = zynqmp_dp_phy_init(dp);
if (ret)
- return ret;
+ goto err_reset;
zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 1);
@@ -1709,15 +1707,18 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
zynqmp_dp_irq_handler, IRQF_ONESHOT,
dev_name(dp->dev), dp);
if (ret < 0)
- goto error;
+ goto err_phy_exit;
dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n",
dp->num_lanes);
return 0;
-error:
+err_phy_exit:
zynqmp_dp_phy_exit(dp);
+err_reset:
+ zynqmp_dp_reset(dp, true);
+
return ret;
}
@@ -1735,4 +1736,5 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub)
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, 0xffffffff);
zynqmp_dp_phy_exit(dp);
+ zynqmp_dp_reset(dp, true);
}
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
index 0c1c50271a88..ac37053412a1 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
@@ -111,8 +111,6 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
if (ret)
return ret;
- drm->irq_enabled = 1;
-
drm_kms_helper_poll_init(drm);
/*
diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c
index 5506336594e2..064056503ebb 100644
--- a/drivers/gpu/drm/zte/zx_drm_drv.c
+++ b/drivers/gpu/drm/zte/zx_drm_drv.c
@@ -75,12 +75,6 @@ static int zx_drm_bind(struct device *dev)
goto out_unbind;
}
- /*
- * We will manage irq handler on our own. In this case, irq_enabled
- * need to be true for using vblank core support.
- */
- drm->irq_enabled = true;
-
drm_mode_config_reset(drm);
drm_kms_helper_poll_init(drm);
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 096017b8789d..d2b6f7de0498 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -9,6 +9,7 @@ host1x-y = \
job.o \
debug.o \
mipi.o \
+ fence.o \
hw/host1x01.o \
hw/host1x02.o \
hw/host1x04.o \
diff --git a/drivers/gpu/host1x/cdma.c b/drivers/gpu/host1x/cdma.c
index 6e6ca774f68d..765e5aa64eb6 100644
--- a/drivers/gpu/host1x/cdma.c
+++ b/drivers/gpu/host1x/cdma.c
@@ -312,10 +312,6 @@ static void update_cdma_locked(struct host1x_cdma *cdma)
bool signal = false;
struct host1x_job *job, *n;
- /* If CDMA is stopped, queue is cleared and we can return */
- if (!cdma->running)
- return;
-
/*
* Walk the sync queue, reading the sync point registers as necessary,
* to consume as many sync queue entries as possible without blocking
@@ -324,7 +320,8 @@ static void update_cdma_locked(struct host1x_cdma *cdma)
struct host1x_syncpt *sp = job->syncpt;
/* Check whether this syncpt has completed, and bail if not */
- if (!host1x_syncpt_is_expired(sp, job->syncpt_end)) {
+ if (!host1x_syncpt_is_expired(sp, job->syncpt_end) &&
+ !job->cancelled) {
/* Start timer on next pending syncpt */
if (job->timeout)
cdma_start_timer_locked(cdma, job);
@@ -413,8 +410,11 @@ syncpt_incr:
else
restart_addr = cdma->last_pos;
+ if (!job)
+ goto resume;
+
/* do CPU increments for the remaining syncpts */
- if (job) {
+ if (job->syncpt_recovery) {
dev_dbg(dev, "%s: perform CPU incr on pending buffers\n",
__func__);
@@ -433,8 +433,44 @@ syncpt_incr:
dev_dbg(dev, "%s: finished sync_queue modification\n",
__func__);
+ } else {
+ struct host1x_job *failed_job = job;
+
+ host1x_job_dump(dev, job);
+
+ host1x_syncpt_set_locked(job->syncpt);
+ failed_job->cancelled = true;
+
+ list_for_each_entry_continue(job, &cdma->sync_queue, list) {
+ unsigned int i;
+
+ if (job->syncpt != failed_job->syncpt)
+ continue;
+
+ for (i = 0; i < job->num_slots; i++) {
+ unsigned int slot = (job->first_get/8 + i) %
+ HOST1X_PUSHBUFFER_SLOTS;
+ u32 *mapped = cdma->push_buffer.mapped;
+
+ /*
+ * Overwrite opcodes with 0 word writes
+ * to offset 0xbad. This does nothing but
+ * has a easily detected signature in debug
+ * traces.
+ */
+ mapped[2*slot+0] = 0x1bad0000;
+ mapped[2*slot+1] = 0x1bad0000;
+ }
+
+ job->cancelled = true;
+ }
+
+ wmb();
+
+ update_cdma_locked(cdma);
}
+resume:
/* roll back DMAGET and start up channel again */
host1x_hw_cdma_resume(host1x, cdma, restart_addr);
}
@@ -490,6 +526,16 @@ int host1x_cdma_begin(struct host1x_cdma *cdma, struct host1x_job *job)
mutex_lock(&cdma->lock);
+ /*
+ * Check if syncpoint was locked due to previous job timeout.
+ * This needs to be done within the cdma lock to avoid a race
+ * with the timeout handler.
+ */
+ if (job->syncpt->locked) {
+ mutex_unlock(&cdma->lock);
+ return -EPERM;
+ }
+
if (job->timeout) {
/* init state on first submit with timeout value */
if (!cdma->timeout.initialized) {
diff --git a/drivers/gpu/host1x/fence.c b/drivers/gpu/host1x/fence.c
new file mode 100644
index 000000000000..6941add95d0f
--- /dev/null
+++ b/drivers/gpu/host1x/fence.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Syncpoint dma_fence implementation
+ *
+ * Copyright (c) 2020, NVIDIA Corporation.
+ */
+
+#include <linux/dma-fence.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/sync_file.h>
+
+#include "fence.h"
+#include "intr.h"
+#include "syncpt.h"
+
+DEFINE_SPINLOCK(lock);
+
+struct host1x_syncpt_fence {
+ struct dma_fence base;
+
+ atomic_t signaling;
+
+ struct host1x_syncpt *sp;
+ u32 threshold;
+
+ struct host1x_waitlist *waiter;
+ void *waiter_ref;
+
+ struct delayed_work timeout_work;
+};
+
+static const char *host1x_syncpt_fence_get_driver_name(struct dma_fence *f)
+{
+ return "host1x";
+}
+
+static const char *host1x_syncpt_fence_get_timeline_name(struct dma_fence *f)
+{
+ return "syncpoint";
+}
+
+static struct host1x_syncpt_fence *to_host1x_fence(struct dma_fence *f)
+{
+ return container_of(f, struct host1x_syncpt_fence, base);
+}
+
+static bool host1x_syncpt_fence_enable_signaling(struct dma_fence *f)
+{
+ struct host1x_syncpt_fence *sf = to_host1x_fence(f);
+ int err;
+
+ if (host1x_syncpt_is_expired(sf->sp, sf->threshold))
+ return false;
+
+ dma_fence_get(f);
+
+ /*
+ * The dma_fence framework requires the fence driver to keep a
+ * reference to any fences for which 'enable_signaling' has been
+ * called (and that have not been signalled).
+ *
+ * We provide a userspace API to create arbitrary syncpoint fences,
+ * so we cannot normally guarantee that all fences get signalled.
+ * As such, setup a timeout, so that long-lasting fences will get
+ * reaped eventually.
+ */
+ schedule_delayed_work(&sf->timeout_work, msecs_to_jiffies(30000));
+
+ err = host1x_intr_add_action(sf->sp->host, sf->sp, sf->threshold,
+ HOST1X_INTR_ACTION_SIGNAL_FENCE, f,
+ sf->waiter, &sf->waiter_ref);
+ if (err) {
+ cancel_delayed_work_sync(&sf->timeout_work);
+ dma_fence_put(f);
+ return false;
+ }
+
+ /* intr framework takes ownership of waiter */
+ sf->waiter = NULL;
+
+ /*
+ * The fence may get signalled at any time after the above call,
+ * so we need to initialize all state used by signalling
+ * before it.
+ */
+
+ return true;
+}
+
+static void host1x_syncpt_fence_release(struct dma_fence *f)
+{
+ struct host1x_syncpt_fence *sf = to_host1x_fence(f);
+
+ if (sf->waiter)
+ kfree(sf->waiter);
+
+ dma_fence_free(f);
+}
+
+const struct dma_fence_ops host1x_syncpt_fence_ops = {
+ .get_driver_name = host1x_syncpt_fence_get_driver_name,
+ .get_timeline_name = host1x_syncpt_fence_get_timeline_name,
+ .enable_signaling = host1x_syncpt_fence_enable_signaling,
+ .release = host1x_syncpt_fence_release,
+};
+
+void host1x_fence_signal(struct host1x_syncpt_fence *f)
+{
+ if (atomic_xchg(&f->signaling, 1))
+ return;
+
+ /*
+ * Cancel pending timeout work - if it races, it will
+ * not get 'f->signaling' and return.
+ */
+ cancel_delayed_work_sync(&f->timeout_work);
+
+ host1x_intr_put_ref(f->sp->host, f->sp->id, f->waiter_ref, false);
+
+ dma_fence_signal(&f->base);
+ dma_fence_put(&f->base);
+}
+
+static void do_fence_timeout(struct work_struct *work)
+{
+ struct delayed_work *dwork = (struct delayed_work *)work;
+ struct host1x_syncpt_fence *f =
+ container_of(dwork, struct host1x_syncpt_fence, timeout_work);
+
+ if (atomic_xchg(&f->signaling, 1))
+ return;
+
+ /*
+ * Cancel pending timeout work - if it races, it will
+ * not get 'f->signaling' and return.
+ */
+ host1x_intr_put_ref(f->sp->host, f->sp->id, f->waiter_ref, true);
+
+ dma_fence_set_error(&f->base, -ETIMEDOUT);
+ dma_fence_signal(&f->base);
+ dma_fence_put(&f->base);
+}
+
+struct dma_fence *host1x_fence_create(struct host1x_syncpt *sp, u32 threshold)
+{
+ struct host1x_syncpt_fence *fence;
+
+ fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+ if (!fence)
+ return ERR_PTR(-ENOMEM);
+
+ fence->waiter = kzalloc(sizeof(*fence->waiter), GFP_KERNEL);
+ if (!fence->waiter)
+ return ERR_PTR(-ENOMEM);
+
+ fence->sp = sp;
+ fence->threshold = threshold;
+
+ dma_fence_init(&fence->base, &host1x_syncpt_fence_ops, &lock,
+ dma_fence_context_alloc(1), 0);
+
+ INIT_DELAYED_WORK(&fence->timeout_work, do_fence_timeout);
+
+ return &fence->base;
+}
+EXPORT_SYMBOL(host1x_fence_create);
diff --git a/drivers/gpu/host1x/fence.h b/drivers/gpu/host1x/fence.h
new file mode 100644
index 000000000000..70c91de82f14
--- /dev/null
+++ b/drivers/gpu/host1x/fence.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, NVIDIA Corporation.
+ */
+
+#ifndef HOST1X_FENCE_H
+#define HOST1X_FENCE_H
+
+struct host1x_syncpt_fence;
+
+void host1x_fence_signal(struct host1x_syncpt_fence *fence);
+
+#endif
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index d4c28faf27d1..1999780a7203 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -47,39 +47,84 @@ static void trace_write_gather(struct host1x_cdma *cdma, struct host1x_bo *bo,
}
}
-static void submit_gathers(struct host1x_job *job)
+static void submit_wait(struct host1x_cdma *cdma, u32 id, u32 threshold,
+ u32 next_class)
+{
+#if HOST1X_HW >= 2
+ host1x_cdma_push_wide(cdma,
+ host1x_opcode_setclass(
+ HOST1X_CLASS_HOST1X,
+ HOST1X_UCLASS_LOAD_SYNCPT_PAYLOAD_32,
+ /* WAIT_SYNCPT_32 is at SYNCPT_PAYLOAD_32+2 */
+ BIT(0) | BIT(2)
+ ),
+ threshold,
+ id,
+ host1x_opcode_setclass(next_class, 0, 0)
+ );
+#else
+ /* TODO add waitchk or use waitbases or other mitigation */
+ host1x_cdma_push(cdma,
+ host1x_opcode_setclass(
+ HOST1X_CLASS_HOST1X,
+ host1x_uclass_wait_syncpt_r(),
+ BIT(0)
+ ),
+ host1x_class_host_wait_syncpt(id, threshold)
+ );
+ host1x_cdma_push(cdma,
+ host1x_opcode_setclass(next_class, 0, 0),
+ HOST1X_OPCODE_NOP
+ );
+#endif
+}
+
+static void submit_gathers(struct host1x_job *job, u32 job_syncpt_base)
{
struct host1x_cdma *cdma = &job->channel->cdma;
#if HOST1X_HW < 6
struct device *dev = job->channel->dev;
#endif
unsigned int i;
+ u32 threshold;
- for (i = 0; i < job->num_gathers; i++) {
- struct host1x_job_gather *g = &job->gathers[i];
- dma_addr_t addr = g->base + g->offset;
- u32 op2, op3;
+ for (i = 0; i < job->num_cmds; i++) {
+ struct host1x_job_cmd *cmd = &job->cmds[i];
- op2 = lower_32_bits(addr);
- op3 = upper_32_bits(addr);
+ if (cmd->is_wait) {
+ if (cmd->wait.relative)
+ threshold = job_syncpt_base + cmd->wait.threshold;
+ else
+ threshold = cmd->wait.threshold;
- trace_write_gather(cdma, g->bo, g->offset, g->words);
+ submit_wait(cdma, cmd->wait.id, threshold, cmd->wait.next_class);
+ } else {
+ struct host1x_job_gather *g = &cmd->gather;
+
+ dma_addr_t addr = g->base + g->offset;
+ u32 op2, op3;
+
+ op2 = lower_32_bits(addr);
+ op3 = upper_32_bits(addr);
- if (op3 != 0) {
+ trace_write_gather(cdma, g->bo, g->offset, g->words);
+
+ if (op3 != 0) {
#if HOST1X_HW >= 6
- u32 op1 = host1x_opcode_gather_wide(g->words);
- u32 op4 = HOST1X_OPCODE_NOP;
+ u32 op1 = host1x_opcode_gather_wide(g->words);
+ u32 op4 = HOST1X_OPCODE_NOP;
- host1x_cdma_push_wide(cdma, op1, op2, op3, op4);
+ host1x_cdma_push_wide(cdma, op1, op2, op3, op4);
#else
- dev_err(dev, "invalid gather for push buffer %pad\n",
- &addr);
- continue;
+ dev_err(dev, "invalid gather for push buffer %pad\n",
+ &addr);
+ continue;
#endif
- } else {
- u32 op1 = host1x_opcode_gather(g->words);
+ } else {
+ u32 op1 = host1x_opcode_gather(g->words);
- host1x_cdma_push(cdma, op1, op2);
+ host1x_cdma_push(cdma, op1, op2);
+ }
}
}
}
@@ -126,7 +171,7 @@ static int channel_submit(struct host1x_job *job)
struct host1x *host = dev_get_drvdata(ch->dev->parent);
trace_host1x_channel_submit(dev_name(ch->dev),
- job->num_gathers, job->num_relocs,
+ job->num_cmds, job->num_relocs,
job->syncpt->id, job->syncpt_incrs);
/* before error checks, return current max */
@@ -181,7 +226,7 @@ static int channel_submit(struct host1x_job *job)
host1x_opcode_setclass(job->class, 0, 0),
HOST1X_OPCODE_NOP);
- submit_gathers(job);
+ submit_gathers(job, syncval - user_syncpt_incrs);
/* end CDMA submit & stash pinned hMems into sync queue */
host1x_cdma_end(&ch->cdma, job);
@@ -191,7 +236,7 @@ static int channel_submit(struct host1x_job *job)
/* schedule a submit complete interrupt */
err = host1x_intr_add_action(host, sp, syncval,
HOST1X_INTR_ACTION_SUBMIT_COMPLETE, ch,
- completed_waiter, NULL);
+ completed_waiter, &job->waiter);
completed_waiter = NULL;
WARN(err, "Failed to set submit complete interrupt");
diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c
index ceb48229d14b..54e31d81517b 100644
--- a/drivers/gpu/host1x/hw/debug_hw.c
+++ b/drivers/gpu/host1x/hw/debug_hw.c
@@ -156,9 +156,9 @@ static unsigned int show_channel_command(struct output *o, u32 val,
}
}
-static void show_gather(struct output *o, phys_addr_t phys_addr,
+static void show_gather(struct output *o, dma_addr_t phys_addr,
unsigned int words, struct host1x_cdma *cdma,
- phys_addr_t pin_addr, u32 *map_addr)
+ dma_addr_t pin_addr, u32 *map_addr)
{
/* Map dmaget cursor to corresponding mem handle */
u32 offset = phys_addr - pin_addr;
@@ -176,11 +176,11 @@ static void show_gather(struct output *o, phys_addr_t phys_addr,
}
for (i = 0; i < words; i++) {
- u32 addr = phys_addr + i * 4;
+ dma_addr_t addr = phys_addr + i * 4;
u32 val = *(map_addr + offset / 4 + i);
if (!data_count) {
- host1x_debug_output(o, "%08x: %08x: ", addr, val);
+ host1x_debug_output(o, " %pad: %08x: ", &addr, val);
data_count = show_channel_command(o, val, &payload);
} else {
host1x_debug_cont(o, "%08x%s", val,
@@ -195,23 +195,25 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
struct push_buffer *pb = &cdma->push_buffer;
struct host1x_job *job;
- host1x_debug_output(o, "PUSHBUF at %pad, %u words\n",
- &pb->dma, pb->size / 4);
-
- show_gather(o, pb->dma, pb->size / 4, cdma, pb->dma, pb->mapped);
-
list_for_each_entry(job, &cdma->sync_queue, list) {
unsigned int i;
- host1x_debug_output(o, "\n%p: JOB, syncpt_id=%d, syncpt_val=%d, first_get=%08x, timeout=%d num_slots=%d, num_handles=%d\n",
- job, job->syncpt->id, job->syncpt_end,
- job->first_get, job->timeout,
+ host1x_debug_output(o, "JOB, syncpt %u: %u timeout: %u num_slots: %u num_handles: %u\n",
+ job->syncpt->id, job->syncpt_end, job->timeout,
job->num_slots, job->num_unpins);
- for (i = 0; i < job->num_gathers; i++) {
- struct host1x_job_gather *g = &job->gathers[i];
+ show_gather(o, pb->dma + job->first_get, job->num_slots * 2, cdma,
+ pb->dma + job->first_get, pb->mapped + job->first_get);
+
+ for (i = 0; i < job->num_cmds; i++) {
+ struct host1x_job_gather *g;
u32 *mapped;
+ if (job->cmds[i].is_wait)
+ continue;
+
+ g = &job->cmds[i].gather;
+
if (job->gather_copy_mapped)
mapped = (u32 *)job->gather_copy_mapped;
else
@@ -222,7 +224,7 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
continue;
}
- host1x_debug_output(o, " GATHER at %pad+%#x, %d words\n",
+ host1x_debug_output(o, " GATHER at %pad+%#x, %d words\n",
&g->base, g->offset, g->words);
show_gather(o, g->base + g->offset, g->words, cdma,
diff --git a/drivers/gpu/host1x/hw/debug_hw_1x01.c b/drivers/gpu/host1x/hw/debug_hw_1x01.c
index 02a93305ac7b..85242a59fa6a 100644
--- a/drivers/gpu/host1x/hw/debug_hw_1x01.c
+++ b/drivers/gpu/host1x/hw/debug_hw_1x01.c
@@ -16,10 +16,13 @@ static void host1x_debug_show_channel_cdma(struct host1x *host,
struct output *o)
{
struct host1x_cdma *cdma = &ch->cdma;
+ dma_addr_t dmastart, dmaend;
u32 dmaput, dmaget, dmactrl;
u32 cbstat, cbread;
u32 val, base, baseval;
+ dmastart = host1x_ch_readl(ch, HOST1X_CHANNEL_DMASTART);
+ dmaend = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAEND);
dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT);
dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET);
dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL);
@@ -56,9 +59,10 @@ static void host1x_debug_show_channel_cdma(struct host1x *host,
HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat),
cbread);
- host1x_debug_output(o, "DMAPUT %08x, DMAGET %08x, DMACTL %08x\n",
+ host1x_debug_output(o, "DMASTART %pad, DMAEND %pad\n", &dmastart, &dmaend);
+ host1x_debug_output(o, "DMAPUT %08x DMAGET %08x DMACTL %08x\n",
dmaput, dmaget, dmactrl);
- host1x_debug_output(o, "CBREAD %08x, CBSTAT %08x\n", cbread, cbstat);
+ host1x_debug_output(o, "CBREAD %08x CBSTAT %08x\n", cbread, cbstat);
show_channel_gathers(o, cdma);
host1x_debug_output(o, "\n");
diff --git a/drivers/gpu/host1x/hw/debug_hw_1x06.c b/drivers/gpu/host1x/hw/debug_hw_1x06.c
index 6d1b583aa90f..9d0667879a19 100644
--- a/drivers/gpu/host1x/hw/debug_hw_1x06.c
+++ b/drivers/gpu/host1x/hw/debug_hw_1x06.c
@@ -16,10 +16,23 @@ static void host1x_debug_show_channel_cdma(struct host1x *host,
struct output *o)
{
struct host1x_cdma *cdma = &ch->cdma;
+ dma_addr_t dmastart = 0, dmaend = 0;
u32 dmaput, dmaget, dmactrl;
u32 offset, class;
u32 ch_stat;
+#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) && HOST1X_HW >= 6
+ dmastart = host1x_ch_readl(ch, HOST1X_CHANNEL_DMASTART_HI);
+ dmastart <<= 32;
+#endif
+ dmastart |= host1x_ch_readl(ch, HOST1X_CHANNEL_DMASTART);
+
+#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) && HOST1X_HW >= 6
+ dmaend = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAEND_HI);
+ dmaend <<= 32;
+#endif
+ dmaend |= host1x_ch_readl(ch, HOST1X_CHANNEL_DMAEND);
+
dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT);
dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET);
dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL);
@@ -41,7 +54,8 @@ static void host1x_debug_show_channel_cdma(struct host1x *host,
host1x_debug_output(o, "active class %02x, offset %04x\n",
class, offset);
- host1x_debug_output(o, "DMAPUT %08x, DMAGET %08x, DMACTL %08x\n",
+ host1x_debug_output(o, "DMASTART %pad, DMAEND %pad\n", &dmastart, &dmaend);
+ host1x_debug_output(o, "DMAPUT %08x DMAGET %08x DMACTL %08x\n",
dmaput, dmaget, dmactrl);
host1x_debug_output(o, "CHANNELSTAT %02x\n", ch_stat);
diff --git a/drivers/gpu/host1x/hw/hw_host1x02_uclass.h b/drivers/gpu/host1x/hw/hw_host1x02_uclass.h
index 4fc51f70496b..0a2ab8f1da6f 100644
--- a/drivers/gpu/host1x/hw/hw_host1x02_uclass.h
+++ b/drivers/gpu/host1x/hw/hw_host1x02_uclass.h
@@ -165,5 +165,17 @@ static inline u32 host1x_uclass_indoff_rwn_read_v(void)
}
#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
host1x_uclass_indoff_indroffset_f(v)
+static inline u32 host1x_uclass_load_syncpt_payload_32_r(void)
+{
+ return 0x4e;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_PAYLOAD_32 \
+ host1x_uclass_load_syncpt_payload_32_r()
+static inline u32 host1x_uclass_wait_syncpt_32_r(void)
+{
+ return 0x50;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_32 \
+ host1x_uclass_wait_syncpt_32_r()
#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x04_uclass.h b/drivers/gpu/host1x/hw/hw_host1x04_uclass.h
index 9e84a4adca9f..60c692b92955 100644
--- a/drivers/gpu/host1x/hw/hw_host1x04_uclass.h
+++ b/drivers/gpu/host1x/hw/hw_host1x04_uclass.h
@@ -165,5 +165,17 @@ static inline u32 host1x_uclass_indoff_rwn_read_v(void)
}
#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
host1x_uclass_indoff_indroffset_f(v)
+static inline u32 host1x_uclass_load_syncpt_payload_32_r(void)
+{
+ return 0x4e;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_PAYLOAD_32 \
+ host1x_uclass_load_syncpt_payload_32_r()
+static inline u32 host1x_uclass_wait_syncpt_32_r(void)
+{
+ return 0x50;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_32 \
+ host1x_uclass_wait_syncpt_32_r()
#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x05_uclass.h b/drivers/gpu/host1x/hw/hw_host1x05_uclass.h
index aee5a4e32877..2fcc9a2ad3ef 100644
--- a/drivers/gpu/host1x/hw/hw_host1x05_uclass.h
+++ b/drivers/gpu/host1x/hw/hw_host1x05_uclass.h
@@ -165,5 +165,17 @@ static inline u32 host1x_uclass_indoff_rwn_read_v(void)
}
#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
host1x_uclass_indoff_indroffset_f(v)
+static inline u32 host1x_uclass_load_syncpt_payload_32_r(void)
+{
+ return 0x4e;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_PAYLOAD_32 \
+ host1x_uclass_load_syncpt_payload_32_r()
+static inline u32 host1x_uclass_wait_syncpt_32_r(void)
+{
+ return 0x50;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_32 \
+ host1x_uclass_wait_syncpt_32_r()
#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x06_uclass.h b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h
index c4bacdb7155f..5f831438d19b 100644
--- a/drivers/gpu/host1x/hw/hw_host1x06_uclass.h
+++ b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h
@@ -165,5 +165,17 @@ static inline u32 host1x_uclass_indoff_rwn_read_v(void)
}
#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
host1x_uclass_indoff_indroffset_f(v)
+static inline u32 host1x_uclass_load_syncpt_payload_32_r(void)
+{
+ return 0x4e;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_PAYLOAD_32 \
+ host1x_uclass_load_syncpt_payload_32_r()
+static inline u32 host1x_uclass_wait_syncpt_32_r(void)
+{
+ return 0x50;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_32 \
+ host1x_uclass_wait_syncpt_32_r()
#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x07_uclass.h b/drivers/gpu/host1x/hw/hw_host1x07_uclass.h
index c74070f3f203..8cd2ef087d5d 100644
--- a/drivers/gpu/host1x/hw/hw_host1x07_uclass.h
+++ b/drivers/gpu/host1x/hw/hw_host1x07_uclass.h
@@ -165,5 +165,17 @@ static inline u32 host1x_uclass_indoff_rwn_read_v(void)
}
#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
host1x_uclass_indoff_indroffset_f(v)
+static inline u32 host1x_uclass_load_syncpt_payload_32_r(void)
+{
+ return 0x4e;
+}
+#define HOST1X_UCLASS_LOAD_SYNCPT_PAYLOAD_32 \
+ host1x_uclass_load_syncpt_payload_32_r()
+static inline u32 host1x_uclass_wait_syncpt_32_r(void)
+{
+ return 0x50;
+}
+#define HOST1X_UCLASS_WAIT_SYNCPT_32 \
+ host1x_uclass_wait_syncpt_32_r()
#endif
diff --git a/drivers/gpu/host1x/intr.c b/drivers/gpu/host1x/intr.c
index 6d1f3c0fdbe7..45b6be927ec4 100644
--- a/drivers/gpu/host1x/intr.c
+++ b/drivers/gpu/host1x/intr.c
@@ -13,6 +13,7 @@
#include <trace/events/host1x.h>
#include "channel.h"
#include "dev.h"
+#include "fence.h"
#include "intr.h"
/* Wait list management */
@@ -121,12 +122,20 @@ static void action_wakeup_interruptible(struct host1x_waitlist *waiter)
wake_up_interruptible(wq);
}
+static void action_signal_fence(struct host1x_waitlist *waiter)
+{
+ struct host1x_syncpt_fence *f = waiter->data;
+
+ host1x_fence_signal(f);
+}
+
typedef void (*action_handler)(struct host1x_waitlist *waiter);
static const action_handler action_handlers[HOST1X_INTR_ACTION_COUNT] = {
action_submit_complete,
action_wakeup,
action_wakeup_interruptible,
+ action_signal_fence,
};
static void run_handlers(struct list_head completed[HOST1X_INTR_ACTION_COUNT])
diff --git a/drivers/gpu/host1x/intr.h b/drivers/gpu/host1x/intr.h
index 6ea55e615e3a..e4c346099273 100644
--- a/drivers/gpu/host1x/intr.h
+++ b/drivers/gpu/host1x/intr.h
@@ -33,6 +33,8 @@ enum host1x_intr_action {
*/
HOST1X_INTR_ACTION_WAKEUP_INTERRUPTIBLE,
+ HOST1X_INTR_ACTION_SIGNAL_FENCE,
+
HOST1X_INTR_ACTION_COUNT
};
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index adbdc225de8d..0eef6df7c89e 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -24,21 +24,25 @@
#define HOST1X_WAIT_SYNCPT_OFFSET 0x8
struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
- u32 num_cmdbufs, u32 num_relocs)
+ u32 num_cmdbufs, u32 num_relocs,
+ bool skip_firewall)
{
struct host1x_job *job = NULL;
unsigned int num_unpins = num_relocs;
+ bool enable_firewall;
u64 total;
void *mem;
- if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
+ enable_firewall = IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && !skip_firewall;
+
+ if (!enable_firewall)
num_unpins += num_cmdbufs;
/* Check that we're not going to overflow */
total = sizeof(struct host1x_job) +
(u64)num_relocs * sizeof(struct host1x_reloc) +
(u64)num_unpins * sizeof(struct host1x_job_unpin_data) +
- (u64)num_cmdbufs * sizeof(struct host1x_job_gather) +
+ (u64)num_cmdbufs * sizeof(struct host1x_job_cmd) +
(u64)num_unpins * sizeof(dma_addr_t) +
(u64)num_unpins * sizeof(u32 *);
if (total > ULONG_MAX)
@@ -48,6 +52,8 @@ struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
if (!job)
return NULL;
+ job->enable_firewall = enable_firewall;
+
kref_init(&job->ref);
job->channel = ch;
@@ -57,8 +63,8 @@ struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
mem += num_relocs * sizeof(struct host1x_reloc);
job->unpins = num_unpins ? mem : NULL;
mem += num_unpins * sizeof(struct host1x_job_unpin_data);
- job->gathers = num_cmdbufs ? mem : NULL;
- mem += num_cmdbufs * sizeof(struct host1x_job_gather);
+ job->cmds = num_cmdbufs ? mem : NULL;
+ mem += num_cmdbufs * sizeof(struct host1x_job_cmd);
job->addr_phys = num_unpins ? mem : NULL;
job->reloc_addr_phys = job->addr_phys;
@@ -79,6 +85,13 @@ static void job_free(struct kref *ref)
{
struct host1x_job *job = container_of(ref, struct host1x_job, ref);
+ if (job->release)
+ job->release(job);
+
+ if (job->waiter)
+ host1x_intr_put_ref(job->syncpt->host, job->syncpt->id,
+ job->waiter, false);
+
if (job->syncpt)
host1x_syncpt_put(job->syncpt);
@@ -94,22 +107,38 @@ EXPORT_SYMBOL(host1x_job_put);
void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *bo,
unsigned int words, unsigned int offset)
{
- struct host1x_job_gather *gather = &job->gathers[job->num_gathers];
+ struct host1x_job_gather *gather = &job->cmds[job->num_cmds].gather;
gather->words = words;
gather->bo = bo;
gather->offset = offset;
- job->num_gathers++;
+ job->num_cmds++;
}
EXPORT_SYMBOL(host1x_job_add_gather);
+void host1x_job_add_wait(struct host1x_job *job, u32 id, u32 thresh,
+ bool relative, u32 next_class)
+{
+ struct host1x_job_cmd *cmd = &job->cmds[job->num_cmds];
+
+ cmd->is_wait = true;
+ cmd->wait.id = id;
+ cmd->wait.threshold = thresh;
+ cmd->wait.next_class = next_class;
+ cmd->wait.relative = relative;
+
+ job->num_cmds++;
+}
+EXPORT_SYMBOL(host1x_job_add_wait);
+
static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
{
struct host1x_client *client = job->client;
struct device *dev = client->dev;
struct host1x_job_gather *g;
struct iommu_domain *domain;
+ struct sg_table *sgt;
unsigned int i;
int err;
@@ -119,7 +148,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
for (i = 0; i < job->num_relocs; i++) {
struct host1x_reloc *reloc = &job->relocs[i];
dma_addr_t phys_addr, *phys;
- struct sg_table *sgt;
reloc->target.bo = host1x_bo_get(reloc->target.bo);
if (!reloc->target.bo) {
@@ -192,20 +220,23 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
* We will copy gathers BO content later, so there is no need to
* hold and pin them.
*/
- if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
+ if (job->enable_firewall)
return 0;
- for (i = 0; i < job->num_gathers; i++) {
+ for (i = 0; i < job->num_cmds; i++) {
size_t gather_size = 0;
struct scatterlist *sg;
- struct sg_table *sgt;
dma_addr_t phys_addr;
unsigned long shift;
struct iova *alloc;
dma_addr_t *phys;
unsigned int j;
- g = &job->gathers[i];
+ if (job->cmds[i].is_wait)
+ continue;
+
+ g = &job->cmds[i].gather;
+
g->bo = host1x_bo_get(g->bo);
if (!g->bo) {
err = -EINVAL;
@@ -296,7 +327,7 @@ static int do_relocs(struct host1x_job *job, struct host1x_job_gather *g)
if (cmdbuf != reloc->cmdbuf.bo)
continue;
- if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
+ if (job->enable_firewall) {
target = (u32 *)job->gather_copy_mapped +
reloc->cmdbuf.offset / sizeof(u32) +
g->offset / sizeof(u32);
@@ -538,8 +569,13 @@ static inline int copy_gathers(struct device *host, struct host1x_job *job,
fw.num_relocs = job->num_relocs;
fw.class = job->class;
- for (i = 0; i < job->num_gathers; i++) {
- struct host1x_job_gather *g = &job->gathers[i];
+ for (i = 0; i < job->num_cmds; i++) {
+ struct host1x_job_gather *g;
+
+ if (job->cmds[i].is_wait)
+ continue;
+
+ g = &job->cmds[i].gather;
size += g->words * sizeof(u32);
}
@@ -561,10 +597,14 @@ static inline int copy_gathers(struct device *host, struct host1x_job *job,
job->gather_copy_size = size;
- for (i = 0; i < job->num_gathers; i++) {
- struct host1x_job_gather *g = &job->gathers[i];
+ for (i = 0; i < job->num_cmds; i++) {
+ struct host1x_job_gather *g;
void *gather;
+ if (job->cmds[i].is_wait)
+ continue;
+ g = &job->cmds[i].gather;
+
/* Copy the gather */
gather = host1x_bo_mmap(g->bo);
memcpy(job->gather_copy_mapped + offset, gather + g->offset,
@@ -600,28 +640,33 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
if (err)
goto out;
- if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
+ if (job->enable_firewall) {
err = copy_gathers(host->dev, job, dev);
if (err)
goto out;
}
/* patch gathers */
- for (i = 0; i < job->num_gathers; i++) {
- struct host1x_job_gather *g = &job->gathers[i];
+ for (i = 0; i < job->num_cmds; i++) {
+ struct host1x_job_gather *g;
+
+ if (job->cmds[i].is_wait)
+ continue;
+ g = &job->cmds[i].gather;
/* process each gather mem only once */
if (g->handled)
continue;
/* copy_gathers() sets gathers base if firewall is enabled */
- if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
+ if (!job->enable_firewall)
g->base = job->gather_addr_phys[i];
- for (j = i + 1; j < job->num_gathers; j++) {
- if (job->gathers[j].bo == g->bo) {
- job->gathers[j].handled = true;
- job->gathers[j].base = g->base;
+ for (j = i + 1; j < job->num_cmds; j++) {
+ if (!job->cmds[j].is_wait &&
+ job->cmds[j].gather.bo == g->bo) {
+ job->cmds[j].gather.handled = true;
+ job->cmds[j].gather.base = g->base;
}
}
@@ -649,8 +694,7 @@ void host1x_job_unpin(struct host1x_job *job)
struct device *dev = unpin->dev ?: host->dev;
struct sg_table *sgt = unpin->sgt;
- if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) &&
- unpin->size && host->domain) {
+ if (!job->enable_firewall && unpin->size && host->domain) {
iommu_unmap(host->domain, job->addr_phys[i],
unpin->size);
free_iova(&host->iova,
diff --git a/drivers/gpu/host1x/job.h b/drivers/gpu/host1x/job.h
index 94bc2e4ae241..b4428c5495c9 100644
--- a/drivers/gpu/host1x/job.h
+++ b/drivers/gpu/host1x/job.h
@@ -18,6 +18,22 @@ struct host1x_job_gather {
bool handled;
};
+struct host1x_job_wait {
+ u32 id;
+ u32 threshold;
+ u32 next_class;
+ bool relative;
+};
+
+struct host1x_job_cmd {
+ bool is_wait;
+
+ union {
+ struct host1x_job_gather gather;
+ struct host1x_job_wait wait;
+ };
+};
+
struct host1x_job_unpin_data {
struct host1x_bo *bo;
struct sg_table *sgt;
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index e648ebbb2027..d198a10848c6 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -407,6 +407,8 @@ static void syncpt_release(struct kref *ref)
atomic_set(&sp->max_val, host1x_syncpt_read(sp));
+ sp->locked = false;
+
mutex_lock(&sp->host->syncpt_mutex);
host1x_syncpt_base_free(sp->base);
diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h
index a6766f8d55ee..95cd29b79d6d 100644
--- a/drivers/gpu/host1x/syncpt.h
+++ b/drivers/gpu/host1x/syncpt.h
@@ -40,6 +40,13 @@ struct host1x_syncpt {
/* interrupt data */
struct host1x_syncpt_intr intr;
+
+ /*
+ * If a submission incrementing this syncpoint fails, lock it so that
+ * further submission cannot be made until application has handled the
+ * failure.
+ */
+ bool locked;
};
/* Initialize sync point array */
@@ -115,4 +122,9 @@ static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
return sp->id < host1x_syncpt_nb_pts(sp->host);
}
+static inline void host1x_syncpt_set_locked(struct host1x_syncpt *sp)
+{
+ sp->locked = true;
+}
+
#endif
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 949fde433ea2..569930552957 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -72,10 +72,7 @@ struct vga_device {
unsigned int io_norm_cnt; /* normal IO count */
unsigned int mem_norm_cnt; /* normal MEM count */
bool bridge_has_one_vga;
- /* allow IRQ enable/disable hook */
- void *cookie;
- void (*irq_set_state)(void *cookie, bool enable);
- unsigned int (*set_vga_decode)(void *cookie, bool decode);
+ unsigned int (*set_decode)(struct pci_dev *pdev, bool decode);
};
static LIST_HEAD(vga_list);
@@ -218,13 +215,6 @@ int vga_remove_vgacon(struct pci_dev *pdev)
#endif
EXPORT_SYMBOL(vga_remove_vgacon);
-static inline void vga_irq_set_state(struct vga_device *vgadev, bool state)
-{
- if (vgadev->irq_set_state)
- vgadev->irq_set_state(vgadev->cookie, state);
-}
-
-
/* If we don't ever use VGA arb we should avoid
turning off anything anywhere due to old X servers getting
confused about the boot device not being VGA */
@@ -284,12 +274,6 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
if (vgadev == conflict)
continue;
- /* Check if the architecture allows a conflict between those
- * 2 devices or if they are on separate domains
- */
- if (!vga_conflicts(vgadev->pdev, conflict->pdev))
- continue;
-
/* We have a possible conflict. before we go further, we must
* check if we sit on the same bus as the conflicting device.
* if we don't, then we must tie both IO and MEM resources
@@ -331,10 +315,8 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
if ((match & conflict->decodes) & VGA_RSRC_LEGACY_IO)
pci_bits |= PCI_COMMAND_IO;
- if (pci_bits) {
- vga_irq_set_state(conflict, false);
+ if (pci_bits)
flags |= PCI_VGA_STATE_CHANGE_DECODES;
- }
}
if (change_bridge)
@@ -371,9 +353,6 @@ enable_them:
pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
- if (!vgadev->bridge_has_one_vga)
- vga_irq_set_state(vgadev, true);
-
vgadev->owns |= wants;
lock_them:
vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK);
@@ -826,7 +805,7 @@ static void __vga_set_legacy_decoding(struct pci_dev *pdev,
goto bail;
/* don't let userspace futz with kernel driver decodes */
- if (userspace && vgadev->set_vga_decode)
+ if (userspace && vgadev->set_decode)
goto bail;
/* update the device decodes + counter */
@@ -840,6 +819,17 @@ bail:
spin_unlock_irqrestore(&vga_lock, flags);
}
+/**
+ * vga_set_legacy_decoding
+ * @pdev: pci device of the VGA card
+ * @decodes: bit mask of what legacy regions the card decodes
+ *
+ * Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
+ * Memory, both, or none. All cards default to both, the card driver (fbdev for
+ * example) should tell the arbiter if it has disabled legacy decoding, so the
+ * card can be left out of the arbitration process (and can be safe to take
+ * interrupts at any time.
+ */
void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes)
{
__vga_set_legacy_decoding(pdev, decodes, false);
@@ -849,17 +839,11 @@ EXPORT_SYMBOL(vga_set_legacy_decoding);
/**
* vga_client_register - register or unregister a VGA arbitration client
* @pdev: pci device of the VGA client
- * @cookie: client cookie to be used in callbacks
- * @irq_set_state: irq state change callback
- * @set_vga_decode: vga decode change callback
+ * @set_decode: vga decode change callback
*
* Clients have two callback mechanisms they can use.
*
- * @irq_set_state callback: If a client can't disable its GPUs VGA
- * resources, then we need to be able to ask it to turn off its irqs when we
- * turn off its mem and io decoding.
- *
- * @set_vga_decode callback: If a client can disable its GPU VGA resource, it
+ * @set_decode callback: If a client can disable its GPU VGA resource, it
* will get a callback from this to set the encode/decode state.
*
* Rationale: we cannot disable VGA decode resources unconditionally some single
@@ -872,15 +856,12 @@ EXPORT_SYMBOL(vga_set_legacy_decoding);
* This function does not check whether a client for @pdev has been registered
* already.
*
- * To unregister just call this function with @irq_set_state and @set_vga_decode
- * both set to NULL for the same @pdev as originally used to register them.
+ * To unregister just call vga_client_unregister().
*
* Returns: 0 on success, -1 on failure
*/
-int vga_client_register(struct pci_dev *pdev, void *cookie,
- void (*irq_set_state)(void *cookie, bool state),
- unsigned int (*set_vga_decode)(void *cookie,
- bool decode))
+int vga_client_register(struct pci_dev *pdev,
+ unsigned int (*set_decode)(struct pci_dev *pdev, bool decode))
{
int ret = -ENODEV;
struct vga_device *vgadev;
@@ -891,9 +872,7 @@ int vga_client_register(struct pci_dev *pdev, void *cookie,
if (!vgadev)
goto bail;
- vgadev->irq_set_state = irq_set_state;
- vgadev->set_vga_decode = set_vga_decode;
- vgadev->cookie = cookie;
+ vgadev->set_decode = set_decode;
ret = 0;
bail:
@@ -1403,9 +1382,9 @@ static void vga_arbiter_notify_clients(void)
new_state = false;
else
new_state = true;
- if (vgadev->set_vga_decode) {
- new_decodes = vgadev->set_vga_decode(vgadev->cookie,
- new_state);
+ if (vgadev->set_decode) {
+ new_decodes = vgadev->set_decode(vgadev->pdev,
+ new_state);
vga_update_device_decodes(vgadev, new_decodes);
}
}
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 76937f716fbe..3c33bf572d6d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -259,10 +259,11 @@ config HID_PRODIKEYS
and some additional multimedia keys.
config HID_CMEDIA
- tristate "CMedia CM6533 HID audio jack controls"
+ tristate "CMedia audio chips"
depends on HID
help
- Support for CMedia CM6533 HID audio jack controls.
+ Support for CMedia CM6533 HID audio jack controls
+ and HS100B mute buttons.
config HID_CP2112
tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
@@ -952,7 +953,7 @@ config HID_SONY
* Buzz controllers
* Sony PS3 Blue-ray Disk Remote Control (Bluetooth)
* Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
- * Guitar Hero Live PS3 and Wii U guitar dongles
+ * Guitar Hero Live PS3, Wii U and PS4 guitar dongles
* Guitar Hero PS3 and PC guitar dongles
config SONY_FF
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 1ea1a7c0b20f..e29efcb1c040 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -115,7 +115,6 @@ obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o hid-thrustmaster.o
-obj-$(CONFIG_HID_TMINIT) += hid-tminit.o
obj-$(CONFIG_HID_TIVO) += hid-tivo.o
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index efb849411d25..840fd075c56f 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -17,7 +17,6 @@
#include "amd_sfh_pcie.h"
#include "amd_sfh_hid.h"
-#define AMD_SFH_IDLE_LOOP 200
struct request_list {
struct hid_device *hid;
@@ -123,14 +122,24 @@ static void amd_sfh_work_buffer(struct work_struct *work)
int i;
for (i = 0; i < cli_data->num_hid_devices; i++) {
- report_size = get_input_report(i, cli_data->sensor_idx[i], cli_data->report_id[i],
- in_data);
- hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
- in_data->input_report[i], report_size, 0);
+ if (cli_data->sensor_sts[i] == SENSOR_ENABLED) {
+ report_size = get_input_report
+ (i, cli_data->sensor_idx[i], cli_data->report_id[i], in_data);
+ hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
+ in_data->input_report[i], report_size, 0);
+ }
}
schedule_delayed_work(&cli_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
}
+u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
+{
+ if (mp2->mp2_ops->response)
+ sensor_sts = mp2->mp2_ops->response(mp2, sid, sensor_sts);
+
+ return sensor_sts;
+}
+
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
{
struct amd_input_data *in_data = &privdata->in_data;
@@ -139,8 +148,8 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
struct device *dev;
u32 feature_report_size;
u32 input_report_size;
+ int rc, i, status;
u8 cl_idx;
- int rc, i;
dev = &privdata->pdev->dev;
@@ -155,7 +164,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
in_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
&cl_data->sensor_dma_addr[i],
GFP_KERNEL);
- cl_data->sensor_sts[i] = 0;
+ cl_data->sensor_sts[i] = SENSOR_DISABLED;
cl_data->sensor_requested_cnt[i] = 0;
cl_data->cur_hid_dev = i;
cl_idx = cl_data->sensor_idx[i];
@@ -184,7 +193,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
rc = -ENOMEM;
goto cleanup;
}
- info.period = msecs_to_jiffies(AMD_SFH_IDLE_LOOP);
+ info.period = AMD_SFH_IDLE_LOOP;
info.sensor_idx = cl_idx;
info.dma_address = cl_data->sensor_dma_addr[i];
@@ -197,11 +206,25 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
rc = get_report_descriptor(cl_idx, cl_data->report_descr[i]);
if (rc)
return rc;
- rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
- if (rc)
- return rc;
privdata->mp2_ops->start(privdata, info);
- cl_data->sensor_sts[i] = 1;
+ status = amd_sfh_wait_for_response
+ (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
+ if (status == SENSOR_ENABLED) {
+ cl_data->sensor_sts[i] = SENSOR_ENABLED;
+ rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
+ if (rc) {
+ privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
+ status = amd_sfh_wait_for_response
+ (privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
+ if (status != SENSOR_ENABLED)
+ cl_data->sensor_sts[i] = SENSOR_DISABLED;
+ dev_dbg(dev, "sid 0x%x status 0x%x\n",
+ cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
+ goto cleanup;
+ }
+ }
+ dev_dbg(dev, "sid 0x%x status 0x%x\n",
+ cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
}
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
return 0;
@@ -224,10 +247,19 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
{
struct amdtp_cl_data *cl_data = privdata->cl_data;
struct amd_input_data *in_data = cl_data->in_data;
- int i;
+ int i, status;
- for (i = 0; i < cl_data->num_hid_devices; i++)
- privdata->mp2_ops->stop(privdata, i);
+ for (i = 0; i < cl_data->num_hid_devices; i++) {
+ if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
+ privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
+ status = amd_sfh_wait_for_response
+ (privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
+ if (status != SENSOR_ENABLED)
+ cl_data->sensor_sts[i] = SENSOR_DISABLED;
+ dev_dbg(&privdata->pdev->dev, "stopping sid 0x%x status 0x%x\n",
+ cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
+ }
+ }
cancel_delayed_work_sync(&cl_data->work);
cancel_delayed_work_sync(&cl_data->work_buffer);
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index 8d68796aa905..79b138fd4261 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -13,6 +13,7 @@
#include <linux/dmi.h>
#include <linux/interrupt.h>
#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -31,6 +32,20 @@ static int sensor_mask_override = -1;
module_param_named(sensor_mask, sensor_mask_override, int, 0444);
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");
+static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
+{
+ union cmd_response cmd_resp;
+
+ /* Get response with status within a max of 800 ms timeout */
+ if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
+ (cmd_resp.response_v2.response == sensor_sts &&
+ cmd_resp.response_v2.status == 0 && (sid == 0xff ||
+ cmd_resp.response_v2.sensor_id == sid)), 500, 800000))
+ return cmd_resp.response_v2.response;
+
+ return SENSOR_DISABLED;
+}
+
static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
{
union sfh_cmd_base cmd_base;
@@ -183,6 +198,7 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
.start = amd_start_sensor_v2,
.stop = amd_stop_sensor_v2,
.stop_all = amd_stop_all_sensor_v2,
+ .response = amd_sfh_wait_response_v2,
};
static const struct amd_mp2_ops amd_sfh_ops = {
@@ -248,6 +264,58 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
return amd_sfh_hid_client_init(privdata);
}
+static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
+ struct amdtp_cl_data *cl_data = mp2->cl_data;
+ struct amd_mp2_sensor_info info;
+ int i, status;
+
+ for (i = 0; i < cl_data->num_hid_devices; i++) {
+ if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
+ info.period = AMD_SFH_IDLE_LOOP;
+ info.sensor_idx = cl_data->sensor_idx[i];
+ info.dma_address = cl_data->sensor_dma_addr[i];
+ mp2->mp2_ops->start(mp2, info);
+ status = amd_sfh_wait_for_response
+ (mp2, cl_data->sensor_idx[i], SENSOR_ENABLED);
+ if (status == SENSOR_ENABLED)
+ cl_data->sensor_sts[i] = SENSOR_ENABLED;
+ dev_dbg(dev, "resume sid 0x%x status 0x%x\n",
+ cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
+ }
+ }
+
+ return 0;
+}
+
+static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
+ struct amdtp_cl_data *cl_data = mp2->cl_data;
+ int i, status;
+
+ for (i = 0; i < cl_data->num_hid_devices; i++) {
+ if (cl_data->sensor_idx[i] != HPD_IDX &&
+ cl_data->sensor_sts[i] == SENSOR_ENABLED) {
+ mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
+ status = amd_sfh_wait_for_response
+ (mp2, cl_data->sensor_idx[i], SENSOR_DISABLED);
+ if (status != SENSOR_ENABLED)
+ cl_data->sensor_sts[i] = SENSOR_DISABLED;
+ dev_dbg(dev, "suspend sid 0x%x status 0x%x\n",
+ cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
+ }
+ }
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(amd_mp2_pm_ops, amd_mp2_pci_suspend,
+ amd_mp2_pci_resume);
+
static const struct pci_device_id amd_mp2_pci_tbl[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) },
{ }
@@ -258,6 +326,7 @@ static struct pci_driver amd_mp2_pci_driver = {
.name = DRIVER_NAME,
.id_table = amd_mp2_pci_tbl,
.probe = amd_mp2_pci_probe,
+ .driver.pm = &amd_mp2_pm_ops,
};
module_pci_driver(amd_mp2_pci_driver);
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
index 2d5c57e3782d..1ff6f83cb6fd 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
@@ -24,14 +24,20 @@
#define AMD_C2P_MSG2 0x10508
#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
+#define AMD_P2C_MSG(regno) (0x10680 + ((regno) * 4))
/* MP2 P2C Message Registers */
#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */
#define V2_STATUS 0x2
+#define SENSOR_ENABLED 4
+#define SENSOR_DISABLED 5
+
#define HPD_IDX 16
+#define AMD_SFH_IDLE_LOOP 200
+
/* SFH Command register */
union sfh_cmd_base {
u32 ul;
@@ -51,6 +57,19 @@ union sfh_cmd_base {
} cmd_v2;
};
+union cmd_response {
+ u32 resp;
+ struct {
+ u32 status : 2;
+ u32 out_in_c2p : 1;
+ u32 rsvd1 : 1;
+ u32 response : 4;
+ u32 sub_cmd : 8;
+ u32 sensor_id : 6;
+ u32 rsvd2 : 10;
+ } response_v2;
+};
+
union sfh_cmd_param {
u32 ul;
struct {
@@ -112,10 +131,14 @@ void amd_stop_all_sensors(struct amd_mp2_dev *privdata);
int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id);
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata);
int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata);
+u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
+void amd_mp2_suspend(struct amd_mp2_dev *mp2);
+void amd_mp2_resume(struct amd_mp2_dev *mp2);
struct amd_mp2_ops {
void (*start)(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
void (*stop_all)(struct amd_mp2_dev *privdata);
+ int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
};
#endif
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index dc6bd4299c54..833fcf07ff35 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -187,6 +187,15 @@ static const struct apple_key_translation *apple_find_translation(
return NULL;
}
+static void input_event_with_scancode(struct input_dev *input,
+ __u8 type, __u16 code, unsigned int hid, __s32 value)
+{
+ if (type == EV_KEY &&
+ (!test_bit(code, input->key)) == value)
+ input_event(input, EV_MSC, MSC_SCAN, hid);
+ input_event(input, type, code, value);
+}
+
static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
struct hid_usage *usage, __s32 value)
{
@@ -199,7 +208,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
if (usage->code == fn_keycode) {
asc->fn_on = !!value;
- input_event(input, usage->type, KEY_FN, value);
+ input_event_with_scancode(input, usage->type, KEY_FN,
+ usage->hid, value);
return 1;
}
@@ -240,7 +250,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
code = do_translate ? trans->to : trans->from;
}
- input_event(input, usage->type, code, value);
+ input_event_with_scancode(input, usage->type, code,
+ usage->hid, value);
return 1;
}
@@ -258,8 +269,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
clear_bit(usage->code,
asc->pressed_numlock);
- input_event(input, usage->type, trans->to,
- value);
+ input_event_with_scancode(input, usage->type,
+ trans->to, usage->hid, value);
}
return 1;
@@ -270,7 +281,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
if (hid->country == HID_COUNTRY_INTERNATIONAL_ISO) {
trans = apple_find_translation(apple_iso_keyboard, usage->code);
if (trans) {
- input_event(input, usage->type, trans->to, value);
+ input_event_with_scancode(input, usage->type,
+ trans->to, usage->hid, value);
return 1;
}
}
@@ -279,7 +291,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
if (swap_opt_cmd) {
trans = apple_find_translation(swapped_option_cmd_keys, usage->code);
if (trans) {
- input_event(input, usage->type, trans->to, value);
+ input_event_with_scancode(input, usage->type,
+ trans->to, usage->hid, value);
return 1;
}
}
@@ -287,7 +300,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
if (swap_fn_leftctrl) {
trans = apple_find_translation(swapped_fn_leftctrl_keys, usage->code);
if (trans) {
- input_event(input, usage->type, trans->to, value);
+ input_event_with_scancode(input, usage->type,
+ trans->to, usage->hid, value);
return 1;
}
}
@@ -306,8 +320,8 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field,
if ((asc->quirks & APPLE_INVERT_HWHEEL) &&
usage->code == REL_HWHEEL) {
- input_event(field->hidinput->input, usage->type, usage->code,
- -value);
+ input_event_with_scancode(field->hidinput->input, usage->type,
+ usage->code, usage->hid, -value);
return 1;
}
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index fb807c8e989b..f3ecddc519ee 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -82,6 +82,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define QUIRK_T90CHI BIT(9)
#define QUIRK_MEDION_E1239T BIT(10)
#define QUIRK_ROG_NKEY_KEYBOARD BIT(11)
+#define QUIRK_ROG_CLAYMORE_II_KEYBOARD BIT(12)
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
QUIRK_NO_INIT_REPORTS | \
@@ -366,6 +367,17 @@ static int asus_raw_event(struct hid_device *hdev,
}
+ if (drvdata->quirks & QUIRK_ROG_CLAYMORE_II_KEYBOARD) {
+ /*
+ * CLAYMORE II keyboard sends this packet when it goes to sleep
+ * this causes the whole system to go into suspend.
+ */
+
+ if(size == 2 && data[0] == 0x02 && data[1] == 0x00) {
+ return -1;
+ }
+ }
+
return 0;
}
@@ -1226,6 +1238,9 @@ static const struct hid_device_id asus_devices[] = {
USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2),
QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD),
+ QUIRK_ROG_CLAYMORE_II_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD),
QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
diff --git a/drivers/hid/hid-cmedia.c b/drivers/hid/hid-cmedia.c
index 3296c5050264..cab42047bc99 100644
--- a/drivers/hid/hid-cmedia.c
+++ b/drivers/hid/hid-cmedia.c
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* HID driver for CMedia CM6533 audio jack controls
+ * and HS100B mute buttons
*
* Copyright (C) 2015 Ben Chen <ben_chen@bizlinktech.com>
+ * Copyright (C) 2021 Thomas Weißschuh <linux@weissschuh.net>
*/
#include <linux/device.h>
@@ -11,13 +13,53 @@
#include "hid-ids.h"
MODULE_AUTHOR("Ben Chen");
-MODULE_DESCRIPTION("CM6533 HID jack controls");
+MODULE_AUTHOR("Thomas Weißschuh");
+MODULE_DESCRIPTION("CM6533 HID jack controls and HS100B mute button");
MODULE_LICENSE("GPL");
#define CM6533_JD_TYPE_COUNT 1
#define CM6533_JD_RAWEV_LEN 16
#define CM6533_JD_SFX_OFFSET 8
+#define HS100B_RDESC_ORIG_SIZE 60
+
+/* Fixed report descriptor of HS-100B audio chip
+ * Bit 4 is an abolute Microphone mute usage instead of being unassigned.
+ */
+static __u8 hs100b_rdesc_fixed[] = {
+ 0x05, 0x0C, /* Usage Page (Consumer), */
+ 0x09, 0x01, /* Usage (Consumer Control), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x15, 0x00, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x09, 0xE9, /* Usage (Volume Inc), */
+ 0x09, 0xEA, /* Usage (Volume Dec), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x02, /* Report Count (2), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x09, 0xE2, /* Usage (Mute), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x06, /* Input (Variable, Relative), */
+ 0x05, 0x0B, /* Usage Page (Telephony), */
+ 0x09, 0x2F, /* Usage (2Fh), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x09, 0x20, /* Usage (20h), */
+ 0x81, 0x06, /* Input (Variable, Relative), */
+ 0x05, 0x0C, /* Usage Page (Consumer), */
+ 0x09, 0x00, /* Usage (00h), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+ 0x09, 0x00, /* Usage (00h), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x09, 0x00, /* Usage (00h), */
+ 0x95, 0x04, /* Report Count (4), */
+ 0x91, 0x02, /* Output (Variable), */
+ 0xC0 /* End Collection */
+};
+
/*
*
*CM6533 audio jack HID raw events:
@@ -156,5 +198,49 @@ static struct hid_driver cmhid_driver = {
.remove = cmhid_remove,
.input_mapping = cmhid_input_mapping,
};
-module_hid_driver(cmhid_driver);
+static __u8 *cmhid_hs100b_report_fixup(struct hid_device *hid, __u8 *rdesc,
+ unsigned int *rsize)
+{
+ if (*rsize == HS100B_RDESC_ORIG_SIZE) {
+ hid_info(hid, "Fixing CMedia HS-100B report descriptor\n");
+ rdesc = hs100b_rdesc_fixed;
+ *rsize = sizeof(hs100b_rdesc_fixed);
+ }
+ return rdesc;
+}
+
+static const struct hid_device_id cmhid_hs100b_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CMEDIA_HS100B) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, cmhid_hs100b_devices);
+
+static struct hid_driver cmhid_hs100b_driver = {
+ .name = "cmedia_hs100b",
+ .id_table = cmhid_hs100b_devices,
+ .report_fixup = cmhid_hs100b_report_fixup,
+};
+
+static int cmedia_init(void)
+{
+ int ret;
+
+ ret = hid_register_driver(&cmhid_driver);
+ if (ret)
+ return ret;
+
+ ret = hid_register_driver(&cmhid_hs100b_driver);
+ if (ret)
+ hid_unregister_driver(&cmhid_driver);
+
+ return ret;
+}
+module_init(cmedia_init);
+
+static void cmedia_exit(void)
+{
+ hid_unregister_driver(&cmhid_driver);
+ hid_unregister_driver(&cmhid_hs100b_driver);
+}
+module_exit(cmedia_exit);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 7db332139f7d..dbed2524fd47 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2302,7 +2302,7 @@ end:
return ret;
}
-static int hid_device_remove(struct device *dev)
+static void hid_device_remove(struct device *dev)
{
struct hid_device *hdev = to_hid_device(dev);
struct hid_driver *hdrv;
@@ -2322,8 +2322,6 @@ static int hid_device_remove(struct device *dev)
if (!hdev->io_started)
up(&hdev->driver_input_lock);
-
- return 0;
}
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c
index 0d22713a3874..383dfda8c12f 100644
--- a/drivers/hid/hid-elo.c
+++ b/drivers/hid/hid-elo.c
@@ -228,13 +228,15 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
struct elo_priv *priv;
int ret;
+ struct usb_device *udev;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
INIT_DELAYED_WORK(&priv->work, elo_work);
- priv->usbdev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
+ udev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
+ priv->usbdev = usb_get_dev(udev);
hid_set_drvdata(hdev, priv);
@@ -265,6 +267,8 @@ static void elo_remove(struct hid_device *hdev)
{
struct elo_priv *priv = hid_get_drvdata(hdev);
+ usb_put_dev(priv->usbdev);
+
hid_hw_stop(hdev);
cancel_delayed_work_sync(&priv->work);
kfree(priv);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 8f1893e68112..29564b370341 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -41,9 +41,6 @@
#define USB_VENDOR_ID_ACTIONSTAR 0x2101
#define USB_DEVICE_ID_ACTIONSTAR_1011 0x1011
-#define USB_VENDOR_ID_ACTIVISION 0x1430
-#define USB_DEVICE_ID_ACTIVISION_GUITAR_DONGLE 0x474c
-
#define USB_VENDOR_ID_ADS_TECH 0x06e1
#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155
@@ -197,6 +194,7 @@
#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD 0x1866
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 0x19b6
+#define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b
#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869
#define USB_VENDOR_ID_ATEN 0x0557
@@ -292,6 +290,7 @@
#define USB_VENDOR_ID_CMEDIA 0x0d8c
#define USB_DEVICE_ID_CM109 0x000e
+#define USB_DEVICE_ID_CMEDIA_HS100B 0x0014
#define USB_DEVICE_ID_CM6533 0x0022
#define USB_VENDOR_ID_CODEMERCS 0x07c0
@@ -1018,6 +1017,10 @@
#define USB_VENDOR_ID_REALTEK 0x0bda
#define USB_DEVICE_ID_REALTEK_READER 0x0152
+#define USB_VENDOR_ID_REDOCTANE 0x1430
+#define USB_DEVICE_ID_REDOCTANE_GUITAR_DONGLE 0x474c
+#define USB_DEVICE_ID_REDOCTANE_PS4_GHLIVE_DONGLE 0x07bb
+
#define USB_VENDOR_ID_RETROUSB 0xf000
#define USB_DEVICE_ID_RETROUSB_SNES_RETROPAD 0x0003
#define USB_DEVICE_ID_RETROUSB_SNES_RETROPORT 0x00f1
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 4286a51f7f16..4b5ebeacd283 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -419,8 +419,6 @@ static int hidinput_get_battery_property(struct power_supply *psy,
if (dev->battery_status == HID_BATTERY_UNKNOWN)
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
- else if (dev->battery_capacity == 100)
- val->intval = POWER_SUPPLY_STATUS_FULL;
else
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break;
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 61635e629469..81de88ab2ecc 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -1331,6 +1331,43 @@ static int hidpp20_battery_get_battery_voltage(struct hidpp_device *hidpp,
return 0;
}
+static int hidpp20_map_battery_capacity(struct hid_device *hid_dev, int voltage)
+{
+ /* NB: This voltage curve doesn't necessarily map perfectly to all
+ * devices that implement the BATTERY_VOLTAGE feature. This is because
+ * there are a few devices that use different battery technology.
+ */
+
+ static const int voltages[] = {
+ 4186, 4156, 4143, 4133, 4122, 4113, 4103, 4094, 4086, 4075,
+ 4067, 4059, 4051, 4043, 4035, 4027, 4019, 4011, 4003, 3997,
+ 3989, 3983, 3976, 3969, 3961, 3955, 3949, 3942, 3935, 3929,
+ 3922, 3916, 3909, 3902, 3896, 3890, 3883, 3877, 3870, 3865,
+ 3859, 3853, 3848, 3842, 3837, 3833, 3828, 3824, 3819, 3815,
+ 3811, 3808, 3804, 3800, 3797, 3793, 3790, 3787, 3784, 3781,
+ 3778, 3775, 3772, 3770, 3767, 3764, 3762, 3759, 3757, 3754,
+ 3751, 3748, 3744, 3741, 3737, 3734, 3730, 3726, 3724, 3720,
+ 3717, 3714, 3710, 3706, 3702, 3697, 3693, 3688, 3683, 3677,
+ 3671, 3666, 3662, 3658, 3654, 3646, 3633, 3612, 3579, 3537
+ };
+
+ int i;
+
+ BUILD_BUG_ON(ARRAY_SIZE(voltages) != 100);
+
+ if (unlikely(voltage < 3500 || voltage >= 5000))
+ hid_warn_once(hid_dev,
+ "%s: possibly using the wrong voltage curve\n",
+ __func__);
+
+ for (i = 0; i < ARRAY_SIZE(voltages); i++) {
+ if (voltage >= voltages[i])
+ return ARRAY_SIZE(voltages) - i;
+ }
+
+ return 0;
+}
+
static int hidpp20_query_battery_voltage_info(struct hidpp_device *hidpp)
{
u8 feature_type;
@@ -1354,6 +1391,8 @@ static int hidpp20_query_battery_voltage_info(struct hidpp_device *hidpp)
hidpp->battery.status = status;
hidpp->battery.voltage = voltage;
+ hidpp->battery.capacity = hidpp20_map_battery_capacity(hidpp->hid_dev,
+ voltage);
hidpp->battery.level = level;
hidpp->battery.charge_type = charge_type;
hidpp->battery.online = status != POWER_SUPPLY_STATUS_NOT_CHARGING;
@@ -1378,6 +1417,8 @@ static int hidpp20_battery_voltage_event(struct hidpp_device *hidpp,
if (voltage != hidpp->battery.voltage || status != hidpp->battery.status) {
hidpp->battery.voltage = voltage;
+ hidpp->battery.capacity = hidpp20_map_battery_capacity(hidpp->hid_dev,
+ voltage);
hidpp->battery.status = status;
hidpp->battery.level = level;
hidpp->battery.charge_type = charge_type;
@@ -2240,11 +2281,10 @@ static int hidpp_ff_queue_work(struct hidpp_ff_private_data *data, int effect_id
wd->size = size;
memcpy(wd->params, params, size);
- atomic_inc(&data->workqueue_size);
+ s = atomic_inc_return(&data->workqueue_size);
queue_work(data->wq, &wd->work);
/* warn about excessive queue size */
- s = atomic_read(&data->workqueue_size);
if (s >= 20 && s % 20 == 0)
hid_warn(data->hidpp->hid_dev, "Force feedback command queue contains %d commands, causing substantial delays!", s);
@@ -3717,7 +3757,8 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
num_battery_props = ARRAY_SIZE(hidpp_battery_props) - 3;
if (hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_MILEAGE ||
- hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_PERCENTAGE)
+ hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_PERCENTAGE ||
+ hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_VOLTAGE)
battery_props[num_battery_props++] =
POWER_SUPPLY_PROP_CAPACITY;
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 8bcaee4ccae0..686788ebf3e1 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -68,6 +68,10 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
#define TOUCH_STATE_START 0x30
#define TOUCH_STATE_DRAG 0x40
+/* Number of high-resolution events for each low-resolution detent. */
+#define SCROLL_HR_STEPS 10
+#define SCROLL_HR_MULT (120 / SCROLL_HR_STEPS)
+#define SCROLL_HR_THRESHOLD 90 /* units */
#define SCROLL_ACCEL_DEFAULT 7
/* Touch surface information. Dimension is in hundredths of a mm, min and max
@@ -126,7 +130,11 @@ struct magicmouse_sc {
short y;
short scroll_x;
short scroll_y;
+ short scroll_x_hr;
+ short scroll_y_hr;
u8 size;
+ bool scroll_x_active;
+ bool scroll_y_active;
} touches[16];
int tracking_ids[16];
@@ -248,12 +256,20 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
unsigned long now = jiffies;
int step_x = msc->touches[id].scroll_x - x;
int step_y = msc->touches[id].scroll_y - y;
+ int step_hr = ((64 - (int)scroll_speed) * msc->scroll_accel) /
+ SCROLL_HR_STEPS;
+ int step_x_hr = msc->touches[id].scroll_x_hr - x;
+ int step_y_hr = msc->touches[id].scroll_y_hr - y;
/* Calculate and apply the scroll motion. */
switch (state) {
case TOUCH_STATE_START:
msc->touches[id].scroll_x = x;
msc->touches[id].scroll_y = y;
+ msc->touches[id].scroll_x_hr = x;
+ msc->touches[id].scroll_y_hr = y;
+ msc->touches[id].scroll_x_active = false;
+ msc->touches[id].scroll_y_active = false;
/* Reset acceleration after half a second. */
if (scroll_acceleration && time_before(now,
@@ -280,6 +296,40 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
msc->scroll_jiffies = now;
input_report_rel(input, REL_WHEEL, step_y);
}
+
+ if (!msc->touches[id].scroll_x_active &&
+ abs(step_x_hr) > SCROLL_HR_THRESHOLD) {
+ msc->touches[id].scroll_x_active = true;
+ msc->touches[id].scroll_x_hr = x;
+ step_x_hr = 0;
+ }
+
+ step_x_hr /= step_hr;
+ if (step_x_hr != 0 &&
+ msc->touches[id].scroll_x_active) {
+ msc->touches[id].scroll_x_hr -= step_x_hr *
+ step_hr;
+ input_report_rel(input,
+ REL_HWHEEL_HI_RES,
+ -step_x_hr * SCROLL_HR_MULT);
+ }
+
+ if (!msc->touches[id].scroll_y_active &&
+ abs(step_y_hr) > SCROLL_HR_THRESHOLD) {
+ msc->touches[id].scroll_y_active = true;
+ msc->touches[id].scroll_y_hr = y;
+ step_y_hr = 0;
+ }
+
+ step_y_hr /= step_hr;
+ if (step_y_hr != 0 &&
+ msc->touches[id].scroll_y_active) {
+ msc->touches[id].scroll_y_hr -= step_y_hr *
+ step_hr;
+ input_report_rel(input,
+ REL_WHEEL_HI_RES,
+ step_y_hr * SCROLL_HR_MULT);
+ }
break;
}
}
@@ -481,6 +531,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
if (emulate_scroll_wheel) {
__set_bit(REL_WHEEL, input->relbit);
__set_bit(REL_HWHEEL, input->relbit);
+ __set_bit(REL_WHEEL_HI_RES, input->relbit);
+ __set_bit(REL_HWHEEL_HI_RES, input->relbit);
}
} else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
/* setting the device name to ensure the same driver settings
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 51b39bda9a9d..2e104682c22b 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -662,8 +662,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) },
-#endif
-#if IS_ENABLED(CONFIG_HID_TMINIT)
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65d) },
#endif
#if IS_ENABLED(CONFIG_HID_TIVO)
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index b3722c51ec78..d1b107d547f5 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -11,8 +11,9 @@
* Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
* Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com>
* Copyright (c) 2018 Todd Kelner
- * Copyright (c) 2020 Pascal Giard <pascal.giard@etsmtl.ca>
+ * Copyright (c) 2020-2021 Pascal Giard <pascal.giard@etsmtl.ca>
* Copyright (c) 2020 Sanjay Govind <sanjay.govind9@gmail.com>
+ * Copyright (c) 2021 Daniel Nguyen <daniel.nguyen.1@ens.etsmtl.ca>
*/
/*
@@ -62,6 +63,7 @@
#define SHANWAN_GAMEPAD BIT(16)
#define GH_GUITAR_CONTROLLER BIT(17)
#define GHL_GUITAR_PS3WIIU BIT(18)
+#define GHL_GUITAR_PS4 BIT(19)
#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
@@ -85,18 +87,27 @@
#define NSG_MRXU_MAX_X 1667
#define NSG_MRXU_MAX_Y 1868
-#define GHL_GUITAR_POKE_INTERVAL 10 /* In seconds */
+/* The PS3/Wii U dongles require a poke every 10 seconds, but the PS4
+ * requires one every 8 seconds. Using 8 seconds for all for simplicity.
+ */
+#define GHL_GUITAR_POKE_INTERVAL 8 /* In seconds */
#define GUITAR_TILT_USAGE 44
-/* Magic value and data taken from GHLtarUtility:
+/* Magic data taken from GHLtarUtility:
* https://github.com/ghlre/GHLtarUtility/blob/master/PS3Guitar.cs
* Note: The Wii U and PS3 dongles happen to share the same!
*/
-static const u16 ghl_ps3wiiu_magic_value = 0x201;
static const char ghl_ps3wiiu_magic_data[] = {
0x02, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00
};
+/* Magic data for the PS4 dongles sniffed with a USB protocol
+ * analyzer.
+ */
+static const char ghl_ps4_magic_data[] = {
+ 0x30, 0x02, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
/* PS/3 Motion controller */
static u8 motion_rdesc[] = {
0x05, 0x01, /* Usage Page (Desktop), */
@@ -642,14 +653,14 @@ static void ghl_magic_poke(struct timer_list *t)
hid_err(sc->hdev, "usb_submit_urb failed: %d", ret);
}
-static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev)
+static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev,
+ const char ghl_magic_data[], u16 poke_size)
{
struct usb_ctrlrequest *cr;
- u16 poke_size;
u8 *databuf;
unsigned int pipe;
+ u16 ghl_magic_value = (((HID_OUTPUT_REPORT + 1) << 8) | ghl_magic_data[0]);
- poke_size = ARRAY_SIZE(ghl_ps3wiiu_magic_data);
pipe = usb_sndctrlpipe(usbdev, 0);
cr = devm_kzalloc(&sc->hdev->dev, sizeof(*cr), GFP_ATOMIC);
@@ -663,10 +674,10 @@ static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev)
cr->bRequestType =
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT;
cr->bRequest = USB_REQ_SET_CONFIGURATION;
- cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value);
+ cr->wValue = cpu_to_le16(ghl_magic_value);
cr->wIndex = 0;
cr->wLength = cpu_to_le16(poke_size);
- memcpy(databuf, ghl_ps3wiiu_magic_data, poke_size);
+ memcpy(databuf, ghl_magic_data, poke_size);
usb_fill_control_urb(
sc->ghl_urb, usbdev, pipe,
(unsigned char *) cr, databuf, poke_size,
@@ -2974,7 +2985,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (!strcmp(hdev->name, "FutureMax Dance Mat"))
quirks |= FUTUREMAX_DANCE_MAT;
- if (!strcmp(hdev->name, "SHANWAN PS3 GamePad"))
+ if (!strcmp(hdev->name, "SHANWAN PS3 GamePad") ||
+ !strcmp(hdev->name, "ShanWan PS(R) Ga`epad"))
quirks |= SHANWAN_GAMEPAD;
sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
@@ -3030,11 +3042,17 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
return -ENODEV;
}
- if (sc->quirks & GHL_GUITAR_PS3WIIU) {
+ if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) {
sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!sc->ghl_urb)
return -ENOMEM;
- ret = ghl_init_urb(sc, usbdev);
+
+ if (sc->quirks & GHL_GUITAR_PS3WIIU)
+ ret = ghl_init_urb(sc, usbdev, ghl_ps3wiiu_magic_data,
+ ARRAY_SIZE(ghl_ps3wiiu_magic_data));
+ else if (sc->quirks & GHL_GUITAR_PS4)
+ ret = ghl_init_urb(sc, usbdev, ghl_ps4_magic_data,
+ ARRAY_SIZE(ghl_ps4_magic_data));
if (ret) {
hid_err(hdev, "error preparing URB\n");
return ret;
@@ -3052,7 +3070,7 @@ static void sony_remove(struct hid_device *hdev)
{
struct sony_sc *sc = hid_get_drvdata(hdev);
- if (sc->quirks & GHL_GUITAR_PS3WIIU) {
+ if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) {
del_timer_sync(&sc->ghl_poke_timer);
usb_free_urb(sc->ghl_urb);
}
@@ -3172,11 +3190,14 @@ static const struct hid_device_id sony_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE),
.driver_data = GHL_GUITAR_PS3WIIU | GH_GUITAR_CONTROLLER },
/* Guitar Hero PC Guitar Dongle */
- { HID_USB_DEVICE(USB_VENDOR_ID_ACTIVISION, USB_DEVICE_ID_ACTIVISION_GUITAR_DONGLE),
+ { HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_GUITAR_DONGLE),
.driver_data = GH_GUITAR_CONTROLLER },
/* Guitar Hero PS3 World Tour Guitar Dongle */
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_GUITAR_DONGLE),
.driver_data = GH_GUITAR_CONTROLLER },
+ /* Guitar Hero Live PS4 guitar dongles */
+ { HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_PS4_GHLIVE_DONGLE),
+ .driver_data = GHL_GUITAR_PS4 | GH_GUITAR_CONTROLLER },
{ }
};
MODULE_DEVICE_TABLE(hid, sony_devices);
diff --git a/drivers/hid/hid-thrustmaster.c b/drivers/hid/hid-thrustmaster.c
index cdc7d82ae9ed..d44550aa8805 100644
--- a/drivers/hid/hid-thrustmaster.c
+++ b/drivers/hid/hid-thrustmaster.c
@@ -173,6 +173,7 @@ static void thrustmaster_interrupts(struct hid_device *hdev)
if (ret) {
hid_err(hdev, "setup data couldn't be sent\n");
+ kfree(send_buf);
return;
}
}
@@ -253,6 +254,7 @@ static void thrustmaster_remove(struct hid_device *hdev)
usb_kill_urb(tm_wheel->urb);
+ kfree(tm_wheel->change_request);
kfree(tm_wheel->response);
kfree(tm_wheel->model_request);
usb_free_urb(tm_wheel->urb);
@@ -336,11 +338,14 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i
);
ret = usb_submit_urb(tm_wheel->urb, GFP_ATOMIC);
- if (ret)
+ if (ret) {
hid_err(hdev, "Error %d while submitting the URB. I am unable to initialize this wheel...\n", ret);
+ goto error6;
+ }
return ret;
+error6: kfree(tm_wheel->change_request);
error5: kfree(tm_wheel->response);
error4: kfree(tm_wheel->model_request);
error3: usb_free_urb(tm_wheel->urb);
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 46474612e73c..517141138b00 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -171,8 +171,6 @@ static const struct i2c_hid_quirks {
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
{ I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_3118,
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
- { USB_VENDOR_ID_ELAN, HID_ANY_ID,
- I2C_HID_QUIRK_BOGUS_IRQ },
{ USB_VENDOR_ID_ALPS_JP, HID_ANY_ID,
I2C_HID_QUIRK_RESET_ON_RESUME },
{ I2C_VENDOR_ID_SYNAPTICS, I2C_PRODUCT_ID_SYNAPTICS_SYNA2393,
@@ -183,7 +181,8 @@ static const struct i2c_hid_quirks {
* Sending the wakeup after reset actually break ELAN touchscreen controller
*/
{ USB_VENDOR_ID_ELAN, HID_ANY_ID,
- I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET },
+ I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET |
+ I2C_HID_QUIRK_BOGUS_IRQ },
{ 0, 0 }
};
diff --git a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
index ee0225982a82..52674149a275 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
@@ -26,28 +26,29 @@ struct i2c_hid_of_goodix {
struct i2chid_ops ops;
struct regulator *vdd;
+ struct notifier_block nb;
+ struct mutex regulator_mutex;
struct gpio_desc *reset_gpio;
const struct goodix_i2c_hid_timing_data *timings;
};
-static int goodix_i2c_hid_power_up(struct i2chid_ops *ops)
+static void goodix_i2c_hid_deassert_reset(struct i2c_hid_of_goodix *ihid_goodix,
+ bool regulator_just_turned_on)
{
- struct i2c_hid_of_goodix *ihid_goodix =
- container_of(ops, struct i2c_hid_of_goodix, ops);
- int ret;
-
- ret = regulator_enable(ihid_goodix->vdd);
- if (ret)
- return ret;
-
- if (ihid_goodix->timings->post_power_delay_ms)
+ if (regulator_just_turned_on && ihid_goodix->timings->post_power_delay_ms)
msleep(ihid_goodix->timings->post_power_delay_ms);
gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 0);
if (ihid_goodix->timings->post_gpio_reset_delay_ms)
msleep(ihid_goodix->timings->post_gpio_reset_delay_ms);
+}
- return 0;
+static int goodix_i2c_hid_power_up(struct i2chid_ops *ops)
+{
+ struct i2c_hid_of_goodix *ihid_goodix =
+ container_of(ops, struct i2c_hid_of_goodix, ops);
+
+ return regulator_enable(ihid_goodix->vdd);
}
static void goodix_i2c_hid_power_down(struct i2chid_ops *ops)
@@ -55,20 +56,54 @@ static void goodix_i2c_hid_power_down(struct i2chid_ops *ops)
struct i2c_hid_of_goodix *ihid_goodix =
container_of(ops, struct i2c_hid_of_goodix, ops);
- gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
regulator_disable(ihid_goodix->vdd);
}
+static int ihid_goodix_vdd_notify(struct notifier_block *nb,
+ unsigned long event,
+ void *ignored)
+{
+ struct i2c_hid_of_goodix *ihid_goodix =
+ container_of(nb, struct i2c_hid_of_goodix, nb);
+ int ret = NOTIFY_OK;
+
+ mutex_lock(&ihid_goodix->regulator_mutex);
+
+ switch (event) {
+ case REGULATOR_EVENT_PRE_DISABLE:
+ gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
+ break;
+
+ case REGULATOR_EVENT_ENABLE:
+ goodix_i2c_hid_deassert_reset(ihid_goodix, true);
+ break;
+
+ case REGULATOR_EVENT_ABORT_DISABLE:
+ goodix_i2c_hid_deassert_reset(ihid_goodix, false);
+ break;
+
+ default:
+ ret = NOTIFY_DONE;
+ break;
+ }
+
+ mutex_unlock(&ihid_goodix->regulator_mutex);
+
+ return ret;
+}
+
static int i2c_hid_of_goodix_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_hid_of_goodix *ihid_goodix;
-
+ int ret;
ihid_goodix = devm_kzalloc(&client->dev, sizeof(*ihid_goodix),
GFP_KERNEL);
if (!ihid_goodix)
return -ENOMEM;
+ mutex_init(&ihid_goodix->regulator_mutex);
+
ihid_goodix->ops.power_up = goodix_i2c_hid_power_up;
ihid_goodix->ops.power_down = goodix_i2c_hid_power_down;
@@ -84,6 +119,37 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client,
ihid_goodix->timings = device_get_match_data(&client->dev);
+ /*
+ * We need to control the "reset" line in lockstep with the regulator
+ * actually turning on an off instead of just when we make the request.
+ * This matters if the regulator is shared with another consumer.
+ * - If the regulator is off then we must assert reset. The reset
+ * line is active low and on some boards it could cause a current
+ * leak if left high.
+ * - If the regulator is on then we don't want reset asserted for very
+ * long. Holding the controller in reset apparently draws extra
+ * power.
+ */
+ mutex_lock(&ihid_goodix->regulator_mutex);
+ ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify;
+ ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb);
+ if (ret) {
+ mutex_unlock(&ihid_goodix->regulator_mutex);
+ return dev_err_probe(&client->dev, ret,
+ "regulator notifier request failed\n");
+ }
+
+ /*
+ * If someone else is holding the regulator on (or the regulator is
+ * an always-on one) we might never be told to deassert reset. Do it
+ * now. Here we'll assume that someone else might have _just
+ * barely_ turned the regulator on so we'll do the full
+ * "post_power_delay" just in case.
+ */
+ if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd))
+ goodix_i2c_hid_deassert_reset(ihid_goodix, true);
+ mutex_unlock(&ihid_goodix->regulator_mutex);
+
return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001);
}
diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c
index aa2c51624012..334eac611774 100644
--- a/drivers/hid/intel-ish-hid/ishtp/bus.c
+++ b/drivers/hid/intel-ish-hid/ishtp/bus.c
@@ -255,7 +255,7 @@ static int ishtp_cl_bus_match(struct device *dev, struct device_driver *drv)
*
* Return: Return value from driver remove() call.
*/
-static int ishtp_cl_device_remove(struct device *dev)
+static void ishtp_cl_device_remove(struct device *dev)
{
struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
struct ishtp_cl_driver *driver = to_ishtp_cl_driver(dev->driver);
@@ -267,8 +267,6 @@ static int ishtp_cl_device_remove(struct device *dev)
if (driver->remove)
driver->remove(device);
-
- return 0;
}
/**
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 06130dc431a0..2dcaf31eb9cd 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -377,27 +377,23 @@ static int hid_submit_ctrl(struct hid_device *hid)
len = hid_report_len(report);
if (dir == USB_DIR_OUT) {
usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
- usbhid->urbctrl->transfer_buffer_length = len;
if (raw_report) {
memcpy(usbhid->ctrlbuf, raw_report, len);
kfree(raw_report);
usbhid->ctrl[usbhid->ctrltail].raw_report = NULL;
}
} else {
- int maxpacket, padlen;
+ int maxpacket;
usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0);
maxpacket = usb_maxpacket(hid_to_usb_dev(hid),
usbhid->urbctrl->pipe, 0);
- if (maxpacket > 0) {
- padlen = DIV_ROUND_UP(len, maxpacket);
- padlen *= maxpacket;
- if (padlen > usbhid->bufsize)
- padlen = usbhid->bufsize;
- } else
- padlen = 0;
- usbhid->urbctrl->transfer_buffer_length = padlen;
+ len += (len == 0); /* Don't allow 0-length reports */
+ len = round_up(len, maxpacket);
+ if (len > usbhid->bufsize)
+ len = usbhid->bufsize;
}
+ usbhid->urbctrl->transfer_buffer_length = len;
usbhid->urbctrl->dev = hid_to_usb_dev(hid);
usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
@@ -505,7 +501,7 @@ static void hid_ctrl(struct urb *urb)
if (unplug) {
usbhid->ctrltail = usbhid->ctrlhead;
- } else {
+ } else if (usbhid->ctrlhead != usbhid->ctrltail) {
usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
if (usbhid->ctrlhead != usbhid->ctrltail &&
@@ -1223,9 +1219,20 @@ static void usbhid_stop(struct hid_device *hid)
mutex_lock(&usbhid->mutex);
clear_bit(HID_STARTED, &usbhid->iofl);
+
spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
set_bit(HID_DISCONNECTED, &usbhid->iofl);
+ while (usbhid->ctrltail != usbhid->ctrlhead) {
+ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_OUT) {
+ kfree(usbhid->ctrl[usbhid->ctrltail].raw_report);
+ usbhid->ctrl[usbhid->ctrltail].raw_report = NULL;
+ }
+
+ usbhid->ctrltail = (usbhid->ctrltail + 1) &
+ (HID_CONTROL_FIFO_SIZE - 1);
+ }
spin_unlock_irq(&usbhid->lock);
+
usb_kill_urb(usbhid->urbin);
usb_kill_urb(usbhid->urbout);
usb_kill_urb(usbhid->urbctrl);
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 57bfa0ae9836..93f49b766376 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -2287,7 +2287,13 @@ static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
if (wacom_wac->has_mute_touch_switch) {
wacom_wac->shared->has_mute_touch_switch = true;
- wacom_wac->shared->is_touch_on = true;
+ /* Hardware touch switch may be off. Wait until
+ * we know the switch state to decide is_touch_on.
+ * Softkey state should be initialized to "on" to
+ * match historic default.
+ */
+ if (wacom_wac->is_soft_touch_switch)
+ wacom_wac->shared->is_touch_on = true;
}
if (wacom_wac->shared->has_mute_touch_switch &&
@@ -2791,6 +2797,7 @@ static int wacom_probe(struct hid_device *hdev,
error);
}
+ wacom_wac->probe_complete = true;
return 0;
}
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 81ba642adcb7..fd51769d0994 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -824,6 +824,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
return 0;
}
+static inline bool touch_is_muted(struct wacom_wac *wacom_wac)
+{
+ return wacom_wac->probe_complete &&
+ wacom_wac->shared->has_mute_touch_switch &&
+ !wacom_wac->shared->is_touch_on;
+}
+
static inline bool report_touch_events(struct wacom_wac *wacom)
{
return (touch_arbitration ? !wacom->shared->stylus_in_proximity : 1);
@@ -1525,11 +1532,8 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
int y_offset = 2;
- if (wacom->shared->has_mute_touch_switch &&
- !wacom->shared->is_touch_on) {
- if (!wacom->shared->touch_down)
- return 0;
- }
+ if (touch_is_muted(wacom) && !wacom->shared->touch_down)
+ return 0;
if (wacom->features.type == WACOM_27QHDT) {
current_num_contacts = data[63];
@@ -1987,14 +1991,17 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
features->numbered_buttons++;
features->device_type |= WACOM_DEVICETYPE_PAD;
break;
- case WACOM_HID_WD_TOUCHONOFF:
case WACOM_HID_WD_MUTE_DEVICE:
+ /* softkey touch switch */
+ wacom_wac->is_soft_touch_switch = true;
+ fallthrough;
+ case WACOM_HID_WD_TOUCHONOFF:
/*
- * This usage, which is used to mute touch events, comes
- * from the pad packet, but is reported on the touch
+ * These two usages, which are used to mute touch events, come
+ * from the pad packet, but are reported on the touch
* interface. Because the touch interface may not have
* been created yet, we cannot call wacom_map_usage(). In
- * order to process this usage when we receive it, we set
+ * order to process the usages when we receive them, we set
* the usage type and code directly.
*/
wacom_wac->has_mute_touch_switch = true;
@@ -2533,8 +2540,7 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
bool prox = hid_data->tipswitch &&
report_touch_events(wacom_wac);
- if (wacom_wac->shared->has_mute_touch_switch &&
- !wacom_wac->shared->is_touch_on) {
+ if (touch_is_muted(wacom_wac)) {
if (!wacom_wac->shared->touch_down)
return;
prox = false;
@@ -2548,8 +2554,17 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
int slot;
slot = input_mt_get_slot_by_key(input, hid_data->id);
- if (slot < 0)
+ if (slot < 0) {
return;
+ } else {
+ struct input_mt_slot *ps = &input->mt->slots[slot];
+ int mt_id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
+
+ if (!prox && mt_id < 0) {
+ // No data to send for this slot; short-circuit
+ return;
+ }
+ }
input_mt_slot(input, slot);
input_mt_report_slot_state(input, MT_TOOL_FINGER, prox);
@@ -2581,6 +2596,9 @@ static void wacom_wac_finger_event(struct hid_device *hdev,
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
struct wacom_features *features = &wacom->wacom_wac.features;
+ if (touch_is_muted(wacom_wac) && !wacom_wac->shared->touch_down)
+ return;
+
if (wacom_wac->is_invalid_bt_frame)
return;
@@ -2630,6 +2648,9 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
struct hid_data* hid_data = &wacom_wac->hid_data;
int i;
+ if (touch_is_muted(wacom_wac) && !wacom_wac->shared->touch_down)
+ return;
+
wacom_wac->is_invalid_bt_frame = false;
for (i = 0; i < report->maxfield; i++) {
@@ -2681,6 +2702,10 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
struct input_dev *input = wacom_wac->touch_input;
unsigned touch_max = wacom_wac->features.touch_max;
+ /* if there was nothing to process, don't send an empty sync */
+ if (wacom_wac->hid_data.num_expected == 0)
+ return;
+
/* If more packets of data are expected, give us a chance to
* process them rather than immediately syncing a partial
* update.
@@ -3835,6 +3860,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
input_dev->evbit[0] |= BIT_MASK(EV_SW);
__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
wacom_wac->has_mute_touch_switch = true;
+ wacom_wac->is_soft_touch_switch = true;
}
fallthrough;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 8f16654eca09..8b2d4e5b2303 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -337,6 +337,7 @@ struct wacom_wac {
int tool[2];
int id[2];
__u64 serial[2];
+ bool probe_complete;
bool reporting_data;
struct wacom_features features;
struct wacom_shared *shared;
@@ -352,6 +353,7 @@ struct wacom_wac {
int mode_value;
struct hid_data hid_data;
bool has_mute_touch_switch;
+ bool is_soft_touch_switch;
bool has_mode_change;
bool is_direct_mode;
bool is_invalid_bt_frame;
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 66c794d92391..d1123ceb38f3 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -4,15 +4,16 @@ menu "Microsoft Hyper-V guest support"
config HYPERV
tristate "Microsoft Hyper-V client drivers"
- depends on X86 && ACPI && X86_LOCAL_APIC && HYPERVISOR_GUEST
+ depends on ACPI && ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) \
+ || (ARM64 && !CPU_BIG_ENDIAN))
select PARAVIRT
- select X86_HV_CALLBACK_VECTOR
+ select X86_HV_CALLBACK_VECTOR if X86
help
Select this option to run Linux as a Hyper-V client operating
system.
config HYPERV_TIMER
- def_bool HYPERV
+ def_bool HYPERV && X86
config HYPERV_UTILS
tristate "Microsoft Hyper-V Utilities driver"
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 7f42da98d377..c0d9048a4112 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -13,11 +13,162 @@
*/
#include <linux/types.h>
+#include <linux/acpi.h>
#include <linux/export.h>
#include <linux/bitfield.h>
+#include <linux/cpumask.h>
+#include <linux/panic_notifier.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
#include <asm/hyperv-tlfs.h>
#include <asm/mshyperv.h>
+/*
+ * hv_root_partition and ms_hyperv are defined here with other Hyper-V
+ * specific globals so they are shared across all architectures and are
+ * built only when CONFIG_HYPERV is defined. But on x86,
+ * ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not
+ * defined, and it uses these two variables. So mark them as __weak
+ * here, allowing for an overriding definition in the module containing
+ * ms_hyperv_init_platform().
+ */
+bool __weak hv_root_partition;
+EXPORT_SYMBOL_GPL(hv_root_partition);
+
+struct ms_hyperv_info __weak ms_hyperv;
+EXPORT_SYMBOL_GPL(ms_hyperv);
+
+u32 *hv_vp_index;
+EXPORT_SYMBOL_GPL(hv_vp_index);
+
+u32 hv_max_vp_index;
+EXPORT_SYMBOL_GPL(hv_max_vp_index);
+
+void __percpu **hyperv_pcpu_input_arg;
+EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
+
+void __percpu **hyperv_pcpu_output_arg;
+EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg);
+
+/*
+ * Hyper-V specific initialization and shutdown code that is
+ * common across all architectures. Called from architecture
+ * specific initialization functions.
+ */
+
+void __init hv_common_free(void)
+{
+ kfree(hv_vp_index);
+ hv_vp_index = NULL;
+
+ free_percpu(hyperv_pcpu_output_arg);
+ hyperv_pcpu_output_arg = NULL;
+
+ free_percpu(hyperv_pcpu_input_arg);
+ hyperv_pcpu_input_arg = NULL;
+}
+
+int __init hv_common_init(void)
+{
+ int i;
+
+ /*
+ * Hyper-V expects to get crash register data or kmsg when
+ * crash enlightment is available and system crashes. Set
+ * crash_kexec_post_notifiers to be true to make sure that
+ * calling crash enlightment interface before running kdump
+ * kernel.
+ */
+ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
+ crash_kexec_post_notifiers = true;
+
+ /*
+ * Allocate the per-CPU state for the hypercall input arg.
+ * If this allocation fails, we will not be able to setup
+ * (per-CPU) hypercall input page and thus this failure is
+ * fatal on Hyper-V.
+ */
+ hyperv_pcpu_input_arg = alloc_percpu(void *);
+ BUG_ON(!hyperv_pcpu_input_arg);
+
+ /* Allocate the per-CPU state for output arg for root */
+ if (hv_root_partition) {
+ hyperv_pcpu_output_arg = alloc_percpu(void *);
+ BUG_ON(!hyperv_pcpu_output_arg);
+ }
+
+ hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
+ GFP_KERNEL);
+ if (!hv_vp_index) {
+ hv_common_free();
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < num_possible_cpus(); i++)
+ hv_vp_index[i] = VP_INVAL;
+
+ return 0;
+}
+
+/*
+ * Hyper-V specific initialization and die code for
+ * individual CPUs that is common across all architectures.
+ * Called by the CPU hotplug mechanism.
+ */
+
+int hv_common_cpu_init(unsigned int cpu)
+{
+ void **inputarg, **outputarg;
+ u64 msr_vp_index;
+ gfp_t flags;
+ int pgcount = hv_root_partition ? 2 : 1;
+
+ /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
+ flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;
+
+ inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
+ *inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
+ if (!(*inputarg))
+ return -ENOMEM;
+
+ if (hv_root_partition) {
+ outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
+ *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE;
+ }
+
+ msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX);
+
+ hv_vp_index[cpu] = msr_vp_index;
+
+ if (msr_vp_index > hv_max_vp_index)
+ hv_max_vp_index = msr_vp_index;
+
+ return 0;
+}
+
+int hv_common_cpu_die(unsigned int cpu)
+{
+ unsigned long flags;
+ void **inputarg, **outputarg;
+ void *mem;
+
+ local_irq_save(flags);
+
+ inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
+ mem = *inputarg;
+ *inputarg = NULL;
+
+ if (hv_root_partition) {
+ outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
+ *outputarg = NULL;
+ }
+
+ local_irq_restore(flags);
+
+ kfree(mem);
+
+ return 0;
+}
/* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */
bool hv_query_ext_cap(u64 cap_query)
@@ -64,3 +215,71 @@ bool hv_query_ext_cap(u64 cap_query)
return hv_extended_cap & cap_query;
}
EXPORT_SYMBOL_GPL(hv_query_ext_cap);
+
+bool hv_is_hibernation_supported(void)
+{
+ return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4);
+}
+EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);
+
+/*
+ * Default function to read the Hyper-V reference counter, independent
+ * of whether Hyper-V enlightened clocks/timers are being used. But on
+ * architectures where it is used, Hyper-V enlightenment code in
+ * hyperv_timer.c may override this function.
+ */
+static u64 __hv_read_ref_counter(void)
+{
+ return hv_get_register(HV_REGISTER_TIME_REF_COUNT);
+}
+
+u64 (*hv_read_reference_counter)(void) = __hv_read_ref_counter;
+EXPORT_SYMBOL_GPL(hv_read_reference_counter);
+
+/* These __weak functions provide default "no-op" behavior and
+ * may be overridden by architecture specific versions. Architectures
+ * for which the default "no-op" behavior is sufficient can leave
+ * them unimplemented and not be cluttered with a bunch of stub
+ * functions in arch-specific code.
+ */
+
+bool __weak hv_is_isolation_supported(void)
+{
+ return false;
+}
+EXPORT_SYMBOL_GPL(hv_is_isolation_supported);
+
+void __weak hv_setup_vmbus_handler(void (*handler)(void))
+{
+}
+EXPORT_SYMBOL_GPL(hv_setup_vmbus_handler);
+
+void __weak hv_remove_vmbus_handler(void)
+{
+}
+EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
+
+void __weak hv_setup_kexec_handler(void (*handler)(void))
+{
+}
+EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
+
+void __weak hv_remove_kexec_handler(void)
+{
+}
+EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
+
+void __weak hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
+{
+}
+EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
+
+void __weak hv_remove_crash_handler(void)
+{
+}
+EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
+
+void __weak hyperv_cleanup(void)
+{
+}
+EXPORT_SYMBOL_GPL(hyperv_cleanup);
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 2267bd4c3472..6018b9d1b1fb 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -375,6 +375,7 @@ hv_vss_init(struct hv_util_service *srv)
}
recv_buffer = srv->recv_buffer;
vss_transaction.recv_channel = srv->channel;
+ vss_transaction.recv_channel->max_pkt_size = HV_HYP_PAGE_SIZE * 2;
/*
* When this driver loads, the user level daemon that
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 136576cba26f..835e6039c186 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -17,7 +17,6 @@
#include <linux/hyperv.h>
#include <linux/clockchips.h>
#include <linux/ptp_clock_kernel.h>
-#include <clocksource/hyperv_timer.h>
#include <asm/mshyperv.h>
#include "hyperv_vmbus.h"
@@ -735,10 +734,6 @@ static struct ptp_clock *hv_ptp_clock;
static int hv_timesync_init(struct hv_util_service *srv)
{
- /* TimeSync requires Hyper-V clocksource. */
- if (!hv_read_reference_counter)
- return -ENODEV;
-
spin_lock_init(&host_ts.lock);
INIT_WORK(&adj_time_work, hv_set_host_time);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 57bbbaa4e8f7..392c1ac4f819 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -922,7 +922,7 @@ static int vmbus_probe(struct device *child_device)
/*
* vmbus_remove - Remove a vmbus device
*/
-static int vmbus_remove(struct device *child_device)
+static void vmbus_remove(struct device *child_device)
{
struct hv_driver *drv;
struct hv_device *dev = device_to_hv_device(child_device);
@@ -932,11 +932,8 @@ static int vmbus_remove(struct device *child_device)
if (drv->remove)
drv->remove(dev);
}
-
- return 0;
}
-
/*
* vmbus_shutdown - Shutdown a vmbus device
*/
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 84530fd80998..f026e5c0e777 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -8,6 +8,7 @@ menuconfig CORESIGHT
depends on OF || ACPI
select ARM_AMBA
select PERF_EVENTS
+ select CONFIGFS_FS
help
This framework provides a kernel interface for the CoreSight debug
and trace drivers to register themselves with. It's intended to build
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index d60816509755..b6c4a48140ec 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -4,7 +4,9 @@
#
obj-$(CONFIG_CORESIGHT) += coresight.o
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
- coresight-sysfs.o
+ coresight-sysfs.o coresight-syscfg.o coresight-config.o \
+ coresight-cfg-preload.o coresight-cfg-afdo.o \
+ coresight-syscfg-configfs.o
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \
coresight-tmc-etr.o
@@ -16,7 +18,8 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o
coresight-etm3x-y := coresight-etm3x-core.o coresight-etm-cp14.o \
coresight-etm3x-sysfs.o
obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o
-coresight-etm4x-y := coresight-etm4x-core.o coresight-etm4x-sysfs.o
+coresight-etm4x-y := coresight-etm4x-core.o coresight-etm4x-sysfs.o \
+ coresight-etm4x-cfg.o
obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o
diff --git a/drivers/hwtracing/coresight/coresight-cfg-afdo.c b/drivers/hwtracing/coresight/coresight-cfg-afdo.c
new file mode 100644
index 000000000000..84b31184252b
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cfg-afdo.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include "coresight-config.h"
+
+/* ETMv4 includes and features */
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+#include "coresight-etm4x-cfg.h"
+
+/* preload configurations and features */
+
+/* preload in features for ETMv4 */
+
+/* strobe feature */
+static struct cscfg_parameter_desc strobe_params[] = {
+ {
+ .name = "window",
+ .value = 5000,
+ },
+ {
+ .name = "period",
+ .value = 10000,
+ },
+};
+
+static struct cscfg_regval_desc strobe_regs[] = {
+ /* resource selectors */
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCRSCTLRn(2),
+ .hw_info = ETM4_CFG_RES_SEL,
+ .val32 = 0x20001,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCRSCTLRn(3),
+ .hw_info = ETM4_CFG_RES_SEQ,
+ .val32 = 0x20002,
+ },
+ /* strobe window counter 0 - reload from param 0 */
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_SAVE,
+ .offset = TRCCNTVRn(0),
+ .hw_info = ETM4_CFG_RES_CTR,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_PARAM,
+ .offset = TRCCNTRLDVRn(0),
+ .hw_info = ETM4_CFG_RES_CTR,
+ .val32 = 0,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCCNTCTLRn(0),
+ .hw_info = ETM4_CFG_RES_CTR,
+ .val32 = 0x10001,
+ },
+ /* strobe period counter 1 - reload from param 1 */
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_SAVE,
+ .offset = TRCCNTVRn(1),
+ .hw_info = ETM4_CFG_RES_CTR,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_PARAM,
+ .offset = TRCCNTRLDVRn(1),
+ .hw_info = ETM4_CFG_RES_CTR,
+ .val32 = 1,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCCNTCTLRn(1),
+ .hw_info = ETM4_CFG_RES_CTR,
+ .val32 = 0x8102,
+ },
+ /* sequencer */
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCSEQEVRn(0),
+ .hw_info = ETM4_CFG_RES_SEQ,
+ .val32 = 0x0081,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCSEQEVRn(1),
+ .hw_info = ETM4_CFG_RES_SEQ,
+ .val32 = 0x0000,
+ },
+ /* view-inst */
+ {
+ .type = CS_CFG_REG_TYPE_STD | CS_CFG_REG_TYPE_VAL_MASK,
+ .offset = TRCVICTLR,
+ .val32 = 0x0003,
+ .mask32 = 0x0003,
+ },
+ /* end of regs */
+};
+
+struct cscfg_feature_desc strobe_etm4x = {
+ .name = "strobing",
+ .description = "Generate periodic trace capture windows.\n"
+ "parameter \'window\': a number of CPU cycles (W)\n"
+ "parameter \'period\': trace enabled for W cycles every period x W cycles\n",
+ .match_flags = CS_CFG_MATCH_CLASS_SRC_ETM4,
+ .nr_params = ARRAY_SIZE(strobe_params),
+ .params_desc = strobe_params,
+ .nr_regs = ARRAY_SIZE(strobe_regs),
+ .regs_desc = strobe_regs,
+};
+
+/* create an autofdo configuration */
+
+/* we will provide 9 sets of preset parameter values */
+#define AFDO_NR_PRESETS 9
+/* the total number of parameters in used features */
+#define AFDO_NR_PARAMS ARRAY_SIZE(strobe_params)
+
+static const char *afdo_ref_names[] = {
+ "strobing",
+};
+
+/*
+ * set of presets leaves strobing window constant while varying period to allow
+ * experimentation with mark / space ratios for various workloads
+ */
+static u64 afdo_presets[AFDO_NR_PRESETS][AFDO_NR_PARAMS] = {
+ { 5000, 2 },
+ { 5000, 4 },
+ { 5000, 8 },
+ { 5000, 16 },
+ { 5000, 64 },
+ { 5000, 128 },
+ { 5000, 512 },
+ { 5000, 1024 },
+ { 5000, 4096 },
+};
+
+struct cscfg_config_desc afdo_etm4x = {
+ .name = "autofdo",
+ .description = "Setup ETMs with strobing for autofdo\n"
+ "Supplied presets allow experimentation with mark-space ratio for various loads\n",
+ .nr_feat_refs = ARRAY_SIZE(afdo_ref_names),
+ .feat_ref_names = afdo_ref_names,
+ .nr_presets = AFDO_NR_PRESETS,
+ .nr_total_params = AFDO_NR_PARAMS,
+ .presets = &afdo_presets[0][0],
+};
+
+/* end of ETM4x configurations */
+#endif /* IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X) */
diff --git a/drivers/hwtracing/coresight/coresight-cfg-preload.c b/drivers/hwtracing/coresight/coresight-cfg-preload.c
new file mode 100644
index 000000000000..751af3710d56
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cfg-preload.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include "coresight-cfg-preload.h"
+#include "coresight-config.h"
+#include "coresight-syscfg.h"
+
+/* Basic features and configurations pre-loaded on initialisation */
+
+static struct cscfg_feature_desc *preload_feats[] = {
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+ &strobe_etm4x,
+#endif
+ NULL
+};
+
+static struct cscfg_config_desc *preload_cfgs[] = {
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+ &afdo_etm4x,
+#endif
+ NULL
+};
+
+/* preload called on initialisation */
+int cscfg_preload(void)
+{
+ return cscfg_load_config_sets(preload_cfgs, preload_feats);
+}
diff --git a/drivers/hwtracing/coresight/coresight-cfg-preload.h b/drivers/hwtracing/coresight/coresight-cfg-preload.h
new file mode 100644
index 000000000000..21299e175477
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cfg-preload.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+/* declare preloaded configurations and features */
+
+/* from coresight-cfg-afdo.c - etm 4x features */
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+extern struct cscfg_feature_desc strobe_etm4x;
+extern struct cscfg_config_desc afdo_etm4x;
+#endif
diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c
new file mode 100644
index 000000000000..4723bf7402a2
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-config.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include <linux/sysfs.h>
+#include "coresight-config.h"
+#include "coresight-priv.h"
+
+/*
+ * This provides a set of generic functions that operate on configurations
+ * and features to manage the handling of parameters, the programming and
+ * saving of registers used by features on devices.
+ */
+
+/*
+ * Write the value held in the register structure into the driver internal memory
+ * location.
+ */
+static void cscfg_set_reg(struct cscfg_regval_csdev *reg_csdev)
+{
+ u32 *p_val32 = (u32 *)reg_csdev->driver_regval;
+ u32 tmp32 = reg_csdev->reg_desc.val32;
+
+ if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT) {
+ *((u64 *)reg_csdev->driver_regval) = reg_csdev->reg_desc.val64;
+ return;
+ }
+
+ if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_MASK) {
+ tmp32 = *p_val32;
+ tmp32 &= ~reg_csdev->reg_desc.mask32;
+ tmp32 |= reg_csdev->reg_desc.val32 & reg_csdev->reg_desc.mask32;
+ }
+ *p_val32 = tmp32;
+}
+
+/*
+ * Read the driver value into the reg if this is marked as one we want to save.
+ */
+static void cscfg_save_reg(struct cscfg_regval_csdev *reg_csdev)
+{
+ if (!(reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_SAVE))
+ return;
+ if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT)
+ reg_csdev->reg_desc.val64 = *(u64 *)(reg_csdev->driver_regval);
+ else
+ reg_csdev->reg_desc.val32 = *(u32 *)(reg_csdev->driver_regval);
+}
+
+/*
+ * Some register values are set from parameters. Initialise these registers
+ * from the current parameter values.
+ */
+static void cscfg_init_reg_param(struct cscfg_feature_csdev *feat_csdev,
+ struct cscfg_regval_desc *reg_desc,
+ struct cscfg_regval_csdev *reg_csdev)
+{
+ struct cscfg_parameter_csdev *param_csdev;
+
+ /* for param, load routines have validated the index */
+ param_csdev = &feat_csdev->params_csdev[reg_desc->param_idx];
+ param_csdev->reg_csdev = reg_csdev;
+ param_csdev->val64 = reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT;
+
+ if (param_csdev->val64)
+ reg_csdev->reg_desc.val64 = param_csdev->current_value;
+ else
+ reg_csdev->reg_desc.val32 = (u32)param_csdev->current_value;
+}
+
+/* set values into the driver locations referenced in cscfg_reg_csdev */
+static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
+{
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
+ for (i = 0; i < feat_csdev->nr_regs; i++)
+ cscfg_set_reg(&feat_csdev->regs_csdev[i]);
+ spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
+ dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
+ feat_csdev->feat_desc->name, "set on enable");
+ return 0;
+}
+
+/* copy back values from the driver locations referenced in cscfg_reg_csdev */
+static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
+{
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
+ for (i = 0; i < feat_csdev->nr_regs; i++)
+ cscfg_save_reg(&feat_csdev->regs_csdev[i]);
+ spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
+ dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
+ feat_csdev->feat_desc->name, "save on disable");
+}
+
+/* default reset - restore default values */
+void cscfg_reset_feat(struct cscfg_feature_csdev *feat_csdev)
+{
+ struct cscfg_regval_desc *reg_desc;
+ struct cscfg_regval_csdev *reg_csdev;
+ int i;
+
+ /*
+ * set the default values for all parameters and regs from the
+ * relevant static descriptors.
+ */
+ for (i = 0; i < feat_csdev->nr_params; i++)
+ feat_csdev->params_csdev[i].current_value =
+ feat_csdev->feat_desc->params_desc[i].value;
+
+ for (i = 0; i < feat_csdev->nr_regs; i++) {
+ reg_desc = &feat_csdev->feat_desc->regs_desc[i];
+ reg_csdev = &feat_csdev->regs_csdev[i];
+ reg_csdev->reg_desc.type = reg_desc->type;
+
+ /* check if reg set from a parameter otherwise desc default */
+ if (reg_desc->type & CS_CFG_REG_TYPE_VAL_PARAM)
+ cscfg_init_reg_param(feat_csdev, reg_desc, reg_csdev);
+ else
+ /*
+ * for normal values the union between val64 & val32 + mask32
+ * allows us to init using the 64 bit value
+ */
+ reg_csdev->reg_desc.val64 = reg_desc->val64;
+ }
+}
+
+/*
+ * For the selected presets, we set the register associated with the parameter, to
+ * the value of the preset index associated with the parameter.
+ */
+static int cscfg_update_presets(struct cscfg_config_csdev *config_csdev, int preset)
+{
+ int i, j, val_idx = 0, nr_cfg_params;
+ struct cscfg_parameter_csdev *param_csdev;
+ struct cscfg_feature_csdev *feat_csdev;
+ const struct cscfg_config_desc *config_desc = config_csdev->config_desc;
+ const char *name;
+ const u64 *preset_base;
+ u64 val;
+
+ /* preset in range 1 to nr_presets */
+ if (preset < 1 || preset > config_desc->nr_presets)
+ return -EINVAL;
+ /*
+ * Go through the array of features, assigning preset values to
+ * feature parameters in the order they appear.
+ * There should be precisely the same number of preset values as the
+ * sum of number of parameters over all the features - but we will
+ * ensure there is no overrun.
+ */
+ nr_cfg_params = config_desc->nr_total_params;
+ preset_base = &config_desc->presets[(preset - 1) * nr_cfg_params];
+ for (i = 0; i < config_csdev->nr_feat; i++) {
+ feat_csdev = config_csdev->feats_csdev[i];
+ if (!feat_csdev->nr_params)
+ continue;
+
+ for (j = 0; j < feat_csdev->nr_params; j++) {
+ param_csdev = &feat_csdev->params_csdev[j];
+ name = feat_csdev->feat_desc->params_desc[j].name;
+ val = preset_base[val_idx++];
+ if (param_csdev->val64) {
+ dev_dbg(&config_csdev->csdev->dev,
+ "set param %s (%lld)", name, val);
+ param_csdev->reg_csdev->reg_desc.val64 = val;
+ } else {
+ param_csdev->reg_csdev->reg_desc.val32 = (u32)val;
+ dev_dbg(&config_csdev->csdev->dev,
+ "set param %s (%d)", name, (u32)val);
+ }
+ }
+
+ /* exit early if all params filled */
+ if (val_idx >= nr_cfg_params)
+ break;
+ }
+ return 0;
+}
+
+/*
+ * if we are not using a preset, then need to update the feature params
+ * with current values. This sets the register associated with the parameter
+ * with the current value of that parameter.
+ */
+static int cscfg_update_curr_params(struct cscfg_config_csdev *config_csdev)
+{
+ int i, j;
+ struct cscfg_feature_csdev *feat_csdev;
+ struct cscfg_parameter_csdev *param_csdev;
+ const char *name;
+ u64 val;
+
+ for (i = 0; i < config_csdev->nr_feat; i++) {
+ feat_csdev = config_csdev->feats_csdev[i];
+ if (!feat_csdev->nr_params)
+ continue;
+ for (j = 0; j < feat_csdev->nr_params; j++) {
+ param_csdev = &feat_csdev->params_csdev[j];
+ name = feat_csdev->feat_desc->params_desc[j].name;
+ val = param_csdev->current_value;
+ if (param_csdev->val64) {
+ dev_dbg(&config_csdev->csdev->dev,
+ "set param %s (%lld)", name, val);
+ param_csdev->reg_csdev->reg_desc.val64 = val;
+ } else {
+ param_csdev->reg_csdev->reg_desc.val32 = (u32)val;
+ dev_dbg(&config_csdev->csdev->dev,
+ "set param %s (%d)", name, (u32)val);
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Configuration values will be programmed into the driver locations if enabling, or read
+ * from relevant locations on disable.
+ */
+static int cscfg_prog_config(struct cscfg_config_csdev *config_csdev, bool enable)
+{
+ int i, err = 0;
+ struct cscfg_feature_csdev *feat_csdev;
+ struct coresight_device *csdev;
+
+ for (i = 0; i < config_csdev->nr_feat; i++) {
+ feat_csdev = config_csdev->feats_csdev[i];
+ csdev = feat_csdev->csdev;
+ dev_dbg(&csdev->dev, "cfg %s; %s feature:%s", config_csdev->config_desc->name,
+ enable ? "enable" : "disable", feat_csdev->feat_desc->name);
+
+ if (enable)
+ err = cscfg_set_on_enable(feat_csdev);
+ else
+ cscfg_save_on_disable(feat_csdev);
+
+ if (err)
+ break;
+ }
+ return err;
+}
+
+/*
+ * Enable configuration for the device. Will result in the internal driver data
+ * being updated ready for programming into the device.
+ *
+ * @config_csdev: config_csdev to set.
+ * @preset: preset values to use - 0 for default.
+ */
+int cscfg_csdev_enable_config(struct cscfg_config_csdev *config_csdev, int preset)
+{
+ int err = 0;
+
+ if (preset)
+ err = cscfg_update_presets(config_csdev, preset);
+ else
+ err = cscfg_update_curr_params(config_csdev);
+ if (!err)
+ err = cscfg_prog_config(config_csdev, true);
+ return err;
+}
+
+void cscfg_csdev_disable_config(struct cscfg_config_csdev *config_csdev)
+{
+ cscfg_prog_config(config_csdev, false);
+}
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
new file mode 100644
index 000000000000..25eb6c632692
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#ifndef _CORESIGHT_CORESIGHT_CONFIG_H
+#define _CORESIGHT_CORESIGHT_CONFIG_H
+
+#include <linux/coresight.h>
+#include <linux/types.h>
+
+/* CoreSight Configuration Management - component and system wide configuration */
+
+/*
+ * Register type flags for register value descriptor:
+ * describe how the value is interpreted, and handled.
+ */
+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */
+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */
+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */
+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */
+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */
+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */
+
+/*
+ * flags defining what device class a feature will match to when processing a
+ * system configuration - used by config data and devices.
+ */
+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
+
+/* flags defining device instance matching - used in config match desc data. */
+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */
+
+/*
+ * Limit number of presets in a configuration
+ * This is related to the number of bits (4) we use to select the preset on
+ * the perf command line. Preset 0 is always none selected.
+ * See PMU_FORMAT_ATTR(preset, "config:0-3") in coresight-etm-perf.c
+ */
+#define CS_CFG_CONFIG_PRESET_MAX 15
+
+/**
+ * Parameter descriptor for a device feature.
+ *
+ * @name: Name of parameter.
+ * @value: Initial or default value.
+ */
+struct cscfg_parameter_desc {
+ const char *name;
+ u64 value;
+};
+
+/**
+ * Representation of register value and a descriptor of register usage.
+ *
+ * Used as a descriptor in the feature descriptors.
+ * Used as a value in when in a feature loading into a csdev.
+ *
+ * Supports full 64 bit register value, or 32 bit value with optional mask
+ * value.
+ *
+ * @type: define register usage and interpretation.
+ * @offset: the address offset for register in the hardware device (per device specification).
+ * @hw_info: optional hardware device type specific information. (ETM / CTI specific etc)
+ * @val64: 64 bit value.
+ * @val32: 32 bit value.
+ * @mask32: 32 bit mask when using 32 bit value to access device register - if mask type.
+ * @param_idx: parameter index value into parameter array if param type.
+ */
+struct cscfg_regval_desc {
+ struct {
+ u32 type:8;
+ u32 offset:12;
+ u32 hw_info:12;
+ };
+ union {
+ u64 val64;
+ struct {
+ u32 val32;
+ u32 mask32;
+ };
+ u32 param_idx;
+ };
+};
+
+/**
+ * Device feature descriptor - combination of registers and parameters to
+ * program a device to implement a specific complex function.
+ *
+ * @name: feature name.
+ * @description: brief description of the feature.
+ * @item: List entry.
+ * @match_flags: matching information if loading into a device
+ * @nr_params: number of parameters used.
+ * @params_desc: array of parameters used.
+ * @nr_regs: number of registers used.
+ * @regs_desc: array of registers used.
+ */
+struct cscfg_feature_desc {
+ const char *name;
+ const char *description;
+ struct list_head item;
+ u32 match_flags;
+ int nr_params;
+ struct cscfg_parameter_desc *params_desc;
+ int nr_regs;
+ struct cscfg_regval_desc *regs_desc;
+};
+
+/**
+ * Configuration descriptor - describes selectable system configuration.
+ *
+ * A configuration describes device features in use, and may provide preset
+ * values for the parameters in those features.
+ *
+ * A single set of presets is the sum of the parameters declared by
+ * all the features in use - this value is @nr_total_params.
+ *
+ * @name: name of the configuration - used for selection.
+ * @description: description of the purpose of the configuration.
+ * @item: list entry.
+ * @nr_feat_refs: Number of features used in this configuration.
+ * @feat_ref_names: references to features used in this configuration.
+ * @nr_presets: Number of sets of presets supplied by this configuration.
+ * @nr_total_params: Sum of all parameters declared by used features
+ * @presets: Array of preset values.
+ * @event_ea: Extended attribute for perf event value
+ * @active_cnt: ref count for activate on this configuration.
+ *
+ */
+struct cscfg_config_desc {
+ const char *name;
+ const char *description;
+ struct list_head item;
+ int nr_feat_refs;
+ const char **feat_ref_names;
+ int nr_presets;
+ int nr_total_params;
+ const u64 *presets; /* nr_presets * nr_total_params */
+ struct dev_ext_attribute *event_ea;
+ atomic_t active_cnt;
+};
+
+/**
+ * config register instance - part of a loaded feature.
+ * maps register values to csdev driver structures
+ *
+ * @reg_desc: value to use when setting feature on device / store for
+ * readback of volatile values.
+ * @driver_regval: pointer to internal driver element used to set the value
+ * in hardware.
+ */
+struct cscfg_regval_csdev {
+ struct cscfg_regval_desc reg_desc;
+ void *driver_regval;
+};
+
+/**
+ * config parameter instance - part of a loaded feature.
+ *
+ * @feat_csdev: parent feature
+ * @reg_csdev: register value updated by this parameter.
+ * @current_value: current value of parameter - may be set by user via
+ * sysfs, or modified during device operation.
+ * @val64: true if 64 bit value
+ */
+struct cscfg_parameter_csdev {
+ struct cscfg_feature_csdev *feat_csdev;
+ struct cscfg_regval_csdev *reg_csdev;
+ u64 current_value;
+ bool val64;
+};
+
+/**
+ * Feature instance loaded into a CoreSight device.
+ *
+ * When a feature is loaded into a specific device, then this structure holds
+ * the connections between the register / parameter values used and the
+ * internal data structures that are written when the feature is enabled.
+ *
+ * Since applying a feature modifies internal data structures in the device,
+ * then we have a reference to the device spinlock to protect access to these
+ * structures (@drv_spinlock).
+ *
+ * @feat_desc: pointer to the static descriptor for this feature.
+ * @csdev: parent CoreSight device instance.
+ * @node: list entry into feature list for this device.
+ * @drv_spinlock: device spinlock for access to driver register data.
+ * @nr_params: number of parameters.
+ * @params_csdev: current parameter values on this device
+ * @nr_regs: number of registers to be programmed.
+ * @regs_csdev: Programming details for the registers
+ */
+struct cscfg_feature_csdev {
+ const struct cscfg_feature_desc *feat_desc;
+ struct coresight_device *csdev;
+ struct list_head node;
+ spinlock_t *drv_spinlock;
+ int nr_params;
+ struct cscfg_parameter_csdev *params_csdev;
+ int nr_regs;
+ struct cscfg_regval_csdev *regs_csdev;
+};
+
+/**
+ * Configuration instance when loaded into a CoreSight device.
+ *
+ * The instance contains references to loaded features on this device that are
+ * used by the configuration.
+ *
+ * @config_desc:reference to the descriptor for this configuration
+ * @csdev: parent coresight device for this configuration instance.
+ * @enabled: true if configuration is enabled on this device.
+ * @node: list entry within the coresight device
+ * @nr_feat: Number of features on this device that are used in the
+ * configuration.
+ * @feats_csdev:references to the device features to enable.
+ */
+struct cscfg_config_csdev {
+ const struct cscfg_config_desc *config_desc;
+ struct coresight_device *csdev;
+ bool enabled;
+ struct list_head node;
+ int nr_feat;
+ struct cscfg_feature_csdev *feats_csdev[0];
+};
+
+/**
+ * Coresight device operations.
+ *
+ * Registered coresight devices provide these operations to manage feature
+ * instances compatible with the device hardware and drivers
+ *
+ * @load_feat: Pass a feature descriptor into the device and create the
+ * loaded feature instance (struct cscfg_feature_csdev).
+ */
+struct cscfg_csdev_feat_ops {
+ int (*load_feat)(struct coresight_device *csdev,
+ struct cscfg_feature_csdev *feat_csdev);
+};
+
+/* coresight config helper functions*/
+
+/* enable / disable config on a device - called with appropriate locks set.*/
+int cscfg_csdev_enable_config(struct cscfg_config_csdev *config_csdev, int preset);
+void cscfg_csdev_disable_config(struct cscfg_config_csdev *config_csdev);
+
+/* reset a feature to default values */
+void cscfg_reset_feat(struct cscfg_feature_csdev *feat_csdev);
+
+#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 1002605db8ba..8a18c71df37a 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -21,6 +21,7 @@
#include "coresight-etm-perf.h"
#include "coresight-priv.h"
+#include "coresight-syscfg.h"
static DEFINE_MUTEX(coresight_mutex);
static DEFINE_PER_CPU(struct coresight_device *, csdev_sink);
@@ -1763,13 +1764,22 @@ static int __init coresight_init(void)
ret = etm_perf_init();
if (ret)
- bus_unregister(&coresight_bustype);
+ goto exit_bus_unregister;
+ /* initialise the coresight syscfg API */
+ ret = cscfg_init();
+ if (!ret)
+ return 0;
+
+ etm_perf_exit();
+exit_bus_unregister:
+ bus_unregister(&coresight_bustype);
return ret;
}
static void __exit coresight_exit(void)
{
+ cscfg_exit();
etm_perf_exit();
bus_unregister(&coresight_bustype);
}
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c
index 9731d3a96073..00de46565bc4 100644
--- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
+++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
@@ -588,11 +588,11 @@ static int debug_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->base = base;
- get_online_cpus();
+ cpus_read_lock();
per_cpu(debug_drvdata, drvdata->cpu) = drvdata;
ret = smp_call_function_single(drvdata->cpu, debug_init_arch_data,
drvdata, 1);
- put_online_cpus();
+ cpus_read_unlock();
if (ret) {
dev_err(dev, "CPU%d debug arch init failed\n", drvdata->cpu);
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 6f398377fec9..8ebd728d3a80 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -18,8 +18,10 @@
#include <linux/types.h>
#include <linux/workqueue.h>
+#include "coresight-config.h"
#include "coresight-etm-perf.h"
#include "coresight-priv.h"
+#include "coresight-syscfg.h"
static struct pmu etm_pmu;
static bool etm_perf_up;
@@ -57,8 +59,13 @@ PMU_FORMAT_ATTR(contextid1, "config:" __stringify(ETM_OPT_CTXTID));
PMU_FORMAT_ATTR(contextid2, "config:" __stringify(ETM_OPT_CTXTID2));
PMU_FORMAT_ATTR(timestamp, "config:" __stringify(ETM_OPT_TS));
PMU_FORMAT_ATTR(retstack, "config:" __stringify(ETM_OPT_RETSTK));
+/* preset - if sink ID is used as a configuration selector */
+PMU_FORMAT_ATTR(preset, "config:0-3");
/* Sink ID - same for all ETMs */
PMU_FORMAT_ATTR(sinkid, "config2:0-31");
+/* config ID - set if a system configuration is selected */
+PMU_FORMAT_ATTR(configid, "config2:32-63");
+
/*
* contextid always traces the "PID". The PID is in CONTEXTIDR_EL1
@@ -88,6 +95,8 @@ static struct attribute *etm_config_formats_attr[] = {
&format_attr_timestamp.attr,
&format_attr_retstack.attr,
&format_attr_sinkid.attr,
+ &format_attr_preset.attr,
+ &format_attr_configid.attr,
NULL,
};
@@ -105,9 +114,19 @@ static const struct attribute_group etm_pmu_sinks_group = {
.attrs = etm_config_sinks_attr,
};
+static struct attribute *etm_config_events_attr[] = {
+ NULL,
+};
+
+static const struct attribute_group etm_pmu_events_group = {
+ .name = "events",
+ .attrs = etm_config_events_attr,
+};
+
static const struct attribute_group *etm_pmu_attr_groups[] = {
&etm_pmu_format_group,
&etm_pmu_sinks_group,
+ &etm_pmu_events_group,
NULL,
};
@@ -196,6 +215,10 @@ static void free_event_data(struct work_struct *work)
/* Free the sink buffers, if there are any */
free_sink_buffer(event_data);
+ /* clear any configuration we were using */
+ if (event_data->cfg_hash)
+ cscfg_deactivate_config(event_data->cfg_hash);
+
for_each_cpu(cpu, mask) {
struct list_head **ppath;
@@ -273,7 +296,7 @@ static bool sinks_compatible(struct coresight_device *a,
static void *etm_setup_aux(struct perf_event *event, void **pages,
int nr_pages, bool overwrite)
{
- u32 id;
+ u32 id, cfg_hash;
int cpu = event->cpu;
cpumask_t *mask;
struct coresight_device *sink = NULL;
@@ -286,11 +309,19 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
INIT_WORK(&event_data->work, free_event_data);
/* First get the selected sink from user space. */
- if (event->attr.config2) {
+ if (event->attr.config2 & GENMASK_ULL(31, 0)) {
id = (u32)event->attr.config2;
sink = user_sink = coresight_get_sink_by_id(id);
}
+ /* check if user wants a coresight configuration selected */
+ cfg_hash = (u32)((event->attr.config2 & GENMASK_ULL(63, 32)) >> 32);
+ if (cfg_hash) {
+ if (cscfg_activate_config(cfg_hash))
+ goto err;
+ event_data->cfg_hash = cfg_hash;
+ }
+
mask = &event_data->mask;
/*
@@ -658,68 +689,127 @@ static ssize_t etm_perf_sink_name_show(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)(ea->var));
}
-int etm_perf_add_symlink_sink(struct coresight_device *csdev)
+static struct dev_ext_attribute *
+etm_perf_add_symlink_group(struct device *dev, const char *name, const char *group_name)
{
- int ret;
+ struct dev_ext_attribute *ea;
unsigned long hash;
- const char *name;
+ int ret;
struct device *pmu_dev = etm_pmu.dev;
- struct device *dev = &csdev->dev;
- struct dev_ext_attribute *ea;
-
- if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
- csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
- return -EINVAL;
-
- if (csdev->ea != NULL)
- return -EINVAL;
if (!etm_perf_up)
- return -EPROBE_DEFER;
+ return ERR_PTR(-EPROBE_DEFER);
ea = devm_kzalloc(dev, sizeof(*ea), GFP_KERNEL);
if (!ea)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- name = dev_name(dev);
- /* See function coresight_get_sink_by_id() to know where this is used */
+ /*
+ * If this function is called adding a sink then the hash is used for
+ * sink selection - see function coresight_get_sink_by_id().
+ * If adding a configuration then the hash is used for selection in
+ * cscfg_activate_config()
+ */
hash = hashlen_hash(hashlen_string(NULL, name));
sysfs_attr_init(&ea->attr.attr);
ea->attr.attr.name = devm_kstrdup(dev, name, GFP_KERNEL);
if (!ea->attr.attr.name)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
ea->attr.attr.mode = 0444;
- ea->attr.show = etm_perf_sink_name_show;
ea->var = (unsigned long *)hash;
ret = sysfs_add_file_to_group(&pmu_dev->kobj,
- &ea->attr.attr, "sinks");
+ &ea->attr.attr, group_name);
- if (!ret)
- csdev->ea = ea;
+ return ret ? ERR_PTR(ret) : ea;
+}
- return ret;
+int etm_perf_add_symlink_sink(struct coresight_device *csdev)
+{
+ const char *name;
+ struct device *dev = &csdev->dev;
+ int err = 0;
+
+ if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
+ csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
+ return -EINVAL;
+
+ if (csdev->ea != NULL)
+ return -EINVAL;
+
+ name = dev_name(dev);
+ csdev->ea = etm_perf_add_symlink_group(dev, name, "sinks");
+ if (IS_ERR(csdev->ea)) {
+ err = PTR_ERR(csdev->ea);
+ csdev->ea = NULL;
+ } else
+ csdev->ea->attr.show = etm_perf_sink_name_show;
+
+ return err;
}
-void etm_perf_del_symlink_sink(struct coresight_device *csdev)
+static void etm_perf_del_symlink_group(struct dev_ext_attribute *ea, const char *group_name)
{
struct device *pmu_dev = etm_pmu.dev;
- struct dev_ext_attribute *ea = csdev->ea;
+ sysfs_remove_file_from_group(&pmu_dev->kobj,
+ &ea->attr.attr, group_name);
+}
+
+void etm_perf_del_symlink_sink(struct coresight_device *csdev)
+{
if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
return;
- if (!ea)
+ if (!csdev->ea)
return;
- sysfs_remove_file_from_group(&pmu_dev->kobj,
- &ea->attr.attr, "sinks");
+ etm_perf_del_symlink_group(csdev->ea, "sinks");
csdev->ea = NULL;
}
+static ssize_t etm_perf_cscfg_event_show(struct device *dev,
+ struct device_attribute *dattr,
+ char *buf)
+{
+ struct dev_ext_attribute *ea;
+
+ ea = container_of(dattr, struct dev_ext_attribute, attr);
+ return scnprintf(buf, PAGE_SIZE, "configid=0x%lx\n", (unsigned long)(ea->var));
+}
+
+int etm_perf_add_symlink_cscfg(struct device *dev, struct cscfg_config_desc *config_desc)
+{
+ int err = 0;
+
+ if (config_desc->event_ea != NULL)
+ return 0;
+
+ config_desc->event_ea = etm_perf_add_symlink_group(dev, config_desc->name, "events");
+
+ /* set the show function to the custom cscfg event */
+ if (!IS_ERR(config_desc->event_ea))
+ config_desc->event_ea->attr.show = etm_perf_cscfg_event_show;
+ else {
+ err = PTR_ERR(config_desc->event_ea);
+ config_desc->event_ea = NULL;
+ }
+
+ return err;
+}
+
+void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc)
+{
+ if (!config_desc->event_ea)
+ return;
+
+ etm_perf_del_symlink_group(config_desc->event_ea, "events");
+ config_desc->event_ea = NULL;
+}
+
int __init etm_perf_init(void)
{
int ret;
@@ -748,7 +838,7 @@ int __init etm_perf_init(void)
return ret;
}
-void __exit etm_perf_exit(void)
+void etm_perf_exit(void)
{
perf_pmu_unregister(&etm_pmu);
}
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h
index 3e4f2ad5e193..468f7799ab4f 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.h
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.h
@@ -11,6 +11,7 @@
#include "coresight-priv.h"
struct coresight_device;
+struct cscfg_config_desc;
/*
* In both ETMv3 and v4 the maximum number of address comparator implentable
@@ -48,12 +49,14 @@ struct etm_filters {
* @work: Handle to free allocated memory outside IRQ context.
* @mask: Hold the CPU(s) this event was set for.
* @snk_config: The sink configuration.
+ * @cfg_hash: The hash id of any coresight config selected.
* @path: An array of path, each slot for one CPU.
*/
struct etm_event_data {
struct work_struct work;
cpumask_t mask;
void *snk_config;
+ u32 cfg_hash;
struct list_head * __percpu *path;
};
@@ -69,6 +72,9 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
return data->snk_config;
return NULL;
}
+int etm_perf_add_symlink_cscfg(struct device *dev,
+ struct cscfg_config_desc *config_desc);
+void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc);
#else
static inline int etm_perf_symlink(struct coresight_device *csdev, bool link)
{ return -EINVAL; }
@@ -79,10 +85,14 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
{
return NULL;
}
+int etm_perf_add_symlink_cscfg(struct device *dev,
+ struct cscfg_config_desc *config_desc)
+{ return -EINVAL; }
+void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc) {}
#endif /* CONFIG_CORESIGHT */
int __init etm_perf_init(void);
-void __exit etm_perf_exit(void);
+void etm_perf_exit(void);
#endif
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
new file mode 100644
index 000000000000..d2ea903231b2
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include "coresight-etm4x.h"
+#include "coresight-etm4x-cfg.h"
+#include "coresight-priv.h"
+#include "coresight-syscfg.h"
+
+/* defines to associate register IDs with driver data locations */
+#define CHECKREG(cval, elem) \
+ { \
+ if (offset == cval) { \
+ reg_csdev->driver_regval = &drvcfg->elem; \
+ err = 0; \
+ break; \
+ } \
+ }
+
+#define CHECKREGIDX(cval, elem, off_idx, mask) \
+ { \
+ if (mask == cval) { \
+ reg_csdev->driver_regval = &drvcfg->elem[off_idx]; \
+ err = 0; \
+ break; \
+ } \
+ }
+
+/**
+ * etm4_cfg_map_reg_offset - validate and map the register offset into a
+ * location in the driver config struct.
+ *
+ * Limits the number of registers that can be accessed and programmed in
+ * features, to those which are used to control the trace capture parameters.
+ *
+ * Omits or limits access to those which the driver must use exclusively.
+ *
+ * Invalid offsets will result in fail code return and feature load failure.
+ *
+ * @drvdata: driver data to map into.
+ * @reg: register to map.
+ * @offset: device offset for the register
+ */
+static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
+ struct cscfg_regval_csdev *reg_csdev, u32 offset)
+{
+ int err = -EINVAL, idx;
+ struct etmv4_config *drvcfg = &drvdata->config;
+ u32 off_mask;
+
+ if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
+ ((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) ||
+ ((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) {
+ do {
+ CHECKREG(TRCEVENTCTL0R, eventctrl0);
+ CHECKREG(TRCEVENTCTL1R, eventctrl1);
+ CHECKREG(TRCSTALLCTLR, stall_ctrl);
+ CHECKREG(TRCTSCTLR, ts_ctrl);
+ CHECKREG(TRCSYNCPR, syncfreq);
+ CHECKREG(TRCCCCTLR, ccctlr);
+ CHECKREG(TRCBBCTLR, bb_ctrl);
+ CHECKREG(TRCVICTLR, vinst_ctrl);
+ CHECKREG(TRCVIIECTLR, viiectlr);
+ CHECKREG(TRCVISSCTLR, vissctlr);
+ CHECKREG(TRCVIPCSSCTLR, vipcssctlr);
+ CHECKREG(TRCSEQRSTEVR, seq_rst);
+ CHECKREG(TRCSEQSTR, seq_state);
+ CHECKREG(TRCEXTINSELR, ext_inp);
+ CHECKREG(TRCCIDCCTLR0, ctxid_mask0);
+ CHECKREG(TRCCIDCCTLR1, ctxid_mask1);
+ CHECKREG(TRCVMIDCCTLR0, vmid_mask0);
+ CHECKREG(TRCVMIDCCTLR1, vmid_mask1);
+ } while (0);
+ } else if ((offset & GENMASK(11, 4)) == TRCSEQEVRn(0)) {
+ /* sequencer state control registers */
+ idx = (offset & GENMASK(3, 0)) / 4;
+ if (idx < ETM_MAX_SEQ_STATES) {
+ reg_csdev->driver_regval = &drvcfg->seq_ctrl[idx];
+ err = 0;
+ }
+ } else if ((offset >= TRCSSCCRn(0)) && (offset <= TRCSSPCICRn(7))) {
+ /* 32 bit, 8 off indexed register sets */
+ idx = (offset & GENMASK(4, 0)) / 4;
+ off_mask = (offset & GENMASK(11, 5));
+ do {
+ CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx, off_mask);
+ CHECKREGIDX(TRCSSCSRn(0), ss_status, idx, off_mask);
+ CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx, off_mask);
+ } while (0);
+ } else if ((offset >= TRCCIDCVRn(0)) && (offset <= TRCVMIDCVRn(7))) {
+ /* 64 bit, 8 off indexed register sets */
+ idx = (offset & GENMASK(5, 0)) / 8;
+ off_mask = (offset & GENMASK(11, 6));
+ do {
+ CHECKREGIDX(TRCCIDCVRn(0), ctxid_pid, idx, off_mask);
+ CHECKREGIDX(TRCVMIDCVRn(0), vmid_val, idx, off_mask);
+ } while (0);
+ } else if ((offset >= TRCRSCTLRn(2)) &&
+ (offset <= TRCRSCTLRn((ETM_MAX_RES_SEL - 1)))) {
+ /* 32 bit resource selection regs, 32 off, skip fixed 0,1 */
+ idx = (offset & GENMASK(6, 0)) / 4;
+ if (idx < ETM_MAX_RES_SEL) {
+ reg_csdev->driver_regval = &drvcfg->res_ctrl[idx];
+ err = 0;
+ }
+ } else if ((offset >= TRCACVRn(0)) &&
+ (offset <= TRCACATRn((ETM_MAX_SINGLE_ADDR_CMP - 1)))) {
+ /* 64 bit addr cmp regs, 16 off */
+ idx = (offset & GENMASK(6, 0)) / 8;
+ off_mask = offset & GENMASK(11, 7);
+ do {
+ CHECKREGIDX(TRCACVRn(0), addr_val, idx, off_mask);
+ CHECKREGIDX(TRCACATRn(0), addr_acc, idx, off_mask);
+ } while (0);
+ } else if ((offset >= TRCCNTRLDVRn(0)) &&
+ (offset <= TRCCNTVRn((ETMv4_MAX_CNTR - 1)))) {
+ /* 32 bit counter regs, 4 off (ETMv4_MAX_CNTR - 1) */
+ idx = (offset & GENMASK(3, 0)) / 4;
+ off_mask = offset & GENMASK(11, 4);
+ do {
+ CHECKREGIDX(TRCCNTRLDVRn(0), cntrldvr, idx, off_mask);
+ CHECKREGIDX(TRCCNTCTLRn(0), cntr_ctrl, idx, off_mask);
+ CHECKREGIDX(TRCCNTVRn(0), cntr_val, idx, off_mask);
+ } while (0);
+ }
+ return err;
+}
+
+/**
+ * etm4_cfg_load_feature - load a feature into a device instance.
+ *
+ * @csdev: An ETMv4 CoreSight device.
+ * @feat: The feature to be loaded.
+ *
+ * The function will load a feature instance into the device, checking that
+ * the register definitions are valid for the device.
+ *
+ * Parameter and register definitions will be converted into internal
+ * structures that are used to set the values in the driver when the
+ * feature is enabled for the device.
+ *
+ * The feature spinlock pointer is initialised to the same spinlock
+ * that the driver uses to protect the internal register values.
+ */
+static int etm4_cfg_load_feature(struct coresight_device *csdev,
+ struct cscfg_feature_csdev *feat_csdev)
+{
+ struct device *dev = csdev->dev.parent;
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
+ const struct cscfg_feature_desc *feat_desc = feat_csdev->feat_desc;
+ u32 offset;
+ int i = 0, err = 0;
+
+ /*
+ * essential we set the device spinlock - this is used in the generic
+ * programming routines when copying values into the drvdata structures
+ * via the pointers setup in etm4_cfg_map_reg_offset().
+ */
+ feat_csdev->drv_spinlock = &drvdata->spinlock;
+
+ /* process the register descriptions */
+ for (i = 0; i < feat_csdev->nr_regs && !err; i++) {
+ offset = feat_desc->regs_desc[i].offset;
+ err = etm4_cfg_map_reg_offset(drvdata, &feat_csdev->regs_csdev[i], offset);
+ }
+ return err;
+}
+
+/* match information when loading configurations */
+#define CS_CFG_ETM4_MATCH_FLAGS (CS_CFG_MATCH_CLASS_SRC_ALL | \
+ CS_CFG_MATCH_CLASS_SRC_ETM4)
+
+int etm4_cscfg_register(struct coresight_device *csdev)
+{
+ struct cscfg_csdev_feat_ops ops;
+
+ ops.load_feat = &etm4_cfg_load_feature;
+
+ return cscfg_register_csdev(csdev, CS_CFG_ETM4_MATCH_FLAGS, &ops);
+}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.h b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
new file mode 100644
index 000000000000..32dab34c1dac
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _CORESIGHT_ETM4X_CFG_H
+#define _CORESIGHT_ETM4X_CFG_H
+
+#include "coresight-config.h"
+#include "coresight-etm4x.h"
+
+/* ETMv4 specific config defines */
+
+/* resource IDs */
+
+#define ETM4_CFG_RES_CTR 0x001
+#define ETM4_CFG_RES_CMP 0x002
+#define ETM4_CFG_RES_CMP_PAIR0 0x003
+#define ETM4_CFG_RES_CMP_PAIR1 0x004
+#define ETM4_CFG_RES_SEL 0x005
+#define ETM4_CFG_RES_SEL_PAIR0 0x006
+#define ETM4_CFG_RES_SEL_PAIR1 0x007
+#define ETM4_CFG_RES_SEQ 0x008
+#define ETM4_CFG_RES_TS 0x009
+#define ETM4_CFG_RES_MASK 0x00F
+
+/* ETMv4 specific config functions */
+int etm4_cscfg_register(struct coresight_device *csdev);
+
+#endif /* CORESIGHT_ETM4X_CFG_H */
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index da27cd4a3c38..e24252eaf8e4 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -39,6 +39,8 @@
#include "coresight-etm4x.h"
#include "coresight-etm-perf.h"
+#include "coresight-etm4x-cfg.h"
+#include "coresight-syscfg.h"
static int boot_enable;
module_param(boot_enable, int, 0444);
@@ -561,12 +563,15 @@ out:
return ret;
}
-static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
+static int etm4_parse_event_config(struct coresight_device *csdev,
struct perf_event *event)
{
int ret = 0;
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct etmv4_config *config = &drvdata->config;
struct perf_event_attr *attr = &event->attr;
+ unsigned long cfg_hash;
+ int preset;
/* Clear configuration from previous run */
memset(config, 0, sizeof(struct etmv4_config));
@@ -632,6 +637,20 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
/* bit[12], Return stack enable bit */
config->cfg |= BIT(12);
+ /*
+ * Set any selected configuration and preset.
+ *
+ * This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)
+ * in the perf attributes defined in coresight-etm-perf.c.
+ * configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.
+ * A zero configid means no configuration active, preset = 0 means no preset selected.
+ */
+ if (attr->config2 & GENMASK_ULL(63, 32)) {
+ cfg_hash = (u32)(attr->config2 >> 32);
+ preset = attr->config & 0xF;
+ ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
+ }
+
out:
return ret;
}
@@ -648,7 +667,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,
}
/* Configure the tracer based on the session's specifics */
- ret = etm4_parse_event_config(drvdata, event);
+ ret = etm4_parse_event_config(csdev, event);
if (ret)
goto out;
/* And enable it */
@@ -794,11 +813,18 @@ static int etm4_disable_perf(struct coresight_device *csdev,
u32 control;
struct etm_filters *filters = event->hw.addr_filters;
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ struct perf_event_attr *attr = &event->attr;
if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
return -EINVAL;
etm4_disable_hw(drvdata);
+ /*
+ * The config_id occupies bits 63:32 of the config2 perf event attr
+ * field. If this is non-zero then we will have enabled a config.
+ */
+ if (attr->config2 & GENMASK_ULL(63, 32))
+ cscfg_csdev_disable_active_config(csdev);
/*
* Check if the start/stop logic was active when the unit was stopped.
@@ -1939,6 +1965,13 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
return ret;
}
+ /* register with config infrastructure & load any current features */
+ ret = etm4_cscfg_register(drvdata->csdev);
+ if (ret) {
+ coresight_unregister(drvdata->csdev);
+ return ret;
+ }
+
etmdrvdata[drvdata->cpu] = drvdata;
dev_info(&drvdata->csdev->dev, "CPU%d: %s v%d.%d initialized\n",
@@ -2025,6 +2058,7 @@ static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata)
cpus_read_unlock();
+ cscfg_unregister_csdev(drvdata->csdev);
coresight_unregister(drvdata->csdev);
return 0;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index 007bad9e7ad8..a0640fa5c55b 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -9,6 +9,7 @@
#include <linux/sysfs.h>
#include "coresight-etm4x.h"
#include "coresight-priv.h"
+#include "coresight-syscfg.h"
static int etm4_set_mode_exclude(struct etmv4_drvdata *drvdata, bool exclude)
{
@@ -269,6 +270,8 @@ static ssize_t reset_store(struct device *dev,
spin_unlock(&drvdata->spinlock);
+ cscfg_csdev_reset_feats(to_coresight_device(dev));
+
return size;
}
static DEVICE_ATTR_WO(reset);
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
new file mode 100644
index 000000000000..c547816b9000
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
@@ -0,0 +1,396 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include <linux/configfs.h>
+
+#include "coresight-syscfg-configfs.h"
+
+/* create a default ci_type. */
+static inline struct config_item_type *cscfg_create_ci_type(void)
+{
+ struct config_item_type *ci_type;
+
+ ci_type = devm_kzalloc(cscfg_device(), sizeof(*ci_type), GFP_KERNEL);
+ if (ci_type)
+ ci_type->ct_owner = THIS_MODULE;
+
+ return ci_type;
+}
+
+/* configurations sub-group */
+
+/* attributes for the config view group */
+static ssize_t cscfg_cfg_description_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
+ struct cscfg_fs_config, group);
+
+ return scnprintf(page, PAGE_SIZE, "%s", fs_config->config_desc->description);
+}
+CONFIGFS_ATTR_RO(cscfg_cfg_, description);
+
+static ssize_t cscfg_cfg_feature_refs_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
+ struct cscfg_fs_config, group);
+ const struct cscfg_config_desc *config_desc = fs_config->config_desc;
+ ssize_t ch_used = 0;
+ int i;
+
+ for (i = 0; i < config_desc->nr_feat_refs; i++)
+ ch_used += scnprintf(page + ch_used, PAGE_SIZE - ch_used,
+ "%s\n", config_desc->feat_ref_names[i]);
+ return ch_used;
+}
+CONFIGFS_ATTR_RO(cscfg_cfg_, feature_refs);
+
+/* list preset values in order of features and params */
+static ssize_t cscfg_cfg_values_show(struct config_item *item, char *page)
+{
+ const struct cscfg_feature_desc *feat_desc;
+ const struct cscfg_config_desc *config_desc;
+ struct cscfg_fs_preset *fs_preset;
+ int i, j, val_idx, preset_idx;
+ ssize_t used = 0;
+
+ fs_preset = container_of(to_config_group(item), struct cscfg_fs_preset, group);
+ config_desc = fs_preset->config_desc;
+
+ if (!config_desc->nr_presets)
+ return 0;
+
+ preset_idx = fs_preset->preset_num - 1;
+
+ /* start index on the correct array line */
+ val_idx = config_desc->nr_total_params * preset_idx;
+
+ /*
+ * A set of presets is the sum of all params in used features,
+ * in order of declaration of features and params in the features
+ */
+ for (i = 0; i < config_desc->nr_feat_refs; i++) {
+ feat_desc = cscfg_get_named_feat_desc(config_desc->feat_ref_names[i]);
+ for (j = 0; j < feat_desc->nr_params; j++) {
+ used += scnprintf(page + used, PAGE_SIZE - used,
+ "%s.%s = 0x%llx ",
+ feat_desc->name,
+ feat_desc->params_desc[j].name,
+ config_desc->presets[val_idx++]);
+ }
+ }
+ used += scnprintf(page + used, PAGE_SIZE - used, "\n");
+
+ return used;
+}
+CONFIGFS_ATTR_RO(cscfg_cfg_, values);
+
+static struct configfs_attribute *cscfg_config_view_attrs[] = {
+ &cscfg_cfg_attr_description,
+ &cscfg_cfg_attr_feature_refs,
+ NULL,
+};
+
+static struct config_item_type cscfg_config_view_type = {
+ .ct_owner = THIS_MODULE,
+ .ct_attrs = cscfg_config_view_attrs,
+};
+
+static struct configfs_attribute *cscfg_config_preset_attrs[] = {
+ &cscfg_cfg_attr_values,
+ NULL,
+};
+
+static struct config_item_type cscfg_config_preset_type = {
+ .ct_owner = THIS_MODULE,
+ .ct_attrs = cscfg_config_preset_attrs,
+};
+
+static int cscfg_add_preset_groups(struct cscfg_fs_config *cfg_view)
+{
+ int preset_num;
+ struct cscfg_fs_preset *cfg_fs_preset;
+ struct cscfg_config_desc *config_desc = cfg_view->config_desc;
+ char name[CONFIGFS_ITEM_NAME_LEN];
+
+ if (!config_desc->nr_presets)
+ return 0;
+
+ for (preset_num = 1; preset_num <= config_desc->nr_presets; preset_num++) {
+ cfg_fs_preset = devm_kzalloc(cscfg_device(),
+ sizeof(struct cscfg_fs_preset), GFP_KERNEL);
+
+ if (!cfg_fs_preset)
+ return -ENOMEM;
+
+ snprintf(name, CONFIGFS_ITEM_NAME_LEN, "preset%d", preset_num);
+ cfg_fs_preset->preset_num = preset_num;
+ cfg_fs_preset->config_desc = cfg_view->config_desc;
+ config_group_init_type_name(&cfg_fs_preset->group, name,
+ &cscfg_config_preset_type);
+ configfs_add_default_group(&cfg_fs_preset->group, &cfg_view->group);
+ }
+ return 0;
+}
+
+static struct config_group *cscfg_create_config_group(struct cscfg_config_desc *config_desc)
+{
+ struct cscfg_fs_config *cfg_view;
+ struct device *dev = cscfg_device();
+ int err;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ cfg_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_config), GFP_KERNEL);
+ if (!cfg_view)
+ return ERR_PTR(-ENOMEM);
+
+ cfg_view->config_desc = config_desc;
+ config_group_init_type_name(&cfg_view->group, config_desc->name, &cscfg_config_view_type);
+
+ /* add in a preset<n> dir for each preset */
+ err = cscfg_add_preset_groups(cfg_view);
+ if (err)
+ return ERR_PTR(err);
+
+ return &cfg_view->group;
+}
+
+/* attributes for features view */
+
+static ssize_t cscfg_feat_description_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
+ struct cscfg_fs_feature, group);
+
+ return scnprintf(page, PAGE_SIZE, "%s", fs_feat->feat_desc->description);
+}
+CONFIGFS_ATTR_RO(cscfg_feat_, description);
+
+static ssize_t cscfg_feat_matches_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
+ struct cscfg_fs_feature, group);
+ u32 match_flags = fs_feat->feat_desc->match_flags;
+ int used = 0;
+
+ if (match_flags & CS_CFG_MATCH_CLASS_SRC_ALL)
+ used = scnprintf(page, PAGE_SIZE, "SRC_ALL ");
+
+ if (match_flags & CS_CFG_MATCH_CLASS_SRC_ETM4)
+ used += scnprintf(page + used, PAGE_SIZE - used, "SRC_ETMV4 ");
+
+ used += scnprintf(page + used, PAGE_SIZE - used, "\n");
+ return used;
+}
+CONFIGFS_ATTR_RO(cscfg_feat_, matches);
+
+static ssize_t cscfg_feat_nr_params_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
+ struct cscfg_fs_feature, group);
+
+ return scnprintf(page, PAGE_SIZE, "%d\n", fs_feat->feat_desc->nr_params);
+}
+CONFIGFS_ATTR_RO(cscfg_feat_, nr_params);
+
+/* base feature desc attrib structures */
+static struct configfs_attribute *cscfg_feature_view_attrs[] = {
+ &cscfg_feat_attr_description,
+ &cscfg_feat_attr_matches,
+ &cscfg_feat_attr_nr_params,
+ NULL,
+};
+
+static struct config_item_type cscfg_feature_view_type = {
+ .ct_owner = THIS_MODULE,
+ .ct_attrs = cscfg_feature_view_attrs,
+};
+
+static ssize_t cscfg_param_value_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_param *param_item = container_of(to_config_group(item),
+ struct cscfg_fs_param, group);
+ u64 value = param_item->feat_desc->params_desc[param_item->param_idx].value;
+
+ return scnprintf(page, PAGE_SIZE, "0x%llx\n", value);
+}
+
+static ssize_t cscfg_param_value_store(struct config_item *item,
+ const char *page, size_t size)
+{
+ struct cscfg_fs_param *param_item = container_of(to_config_group(item),
+ struct cscfg_fs_param, group);
+ struct cscfg_feature_desc *feat_desc = param_item->feat_desc;
+ int param_idx = param_item->param_idx;
+ u64 value;
+ int err;
+
+ err = kstrtoull(page, 0, &value);
+ if (!err)
+ err = cscfg_update_feat_param_val(feat_desc, param_idx, value);
+
+ return err ? err : size;
+}
+CONFIGFS_ATTR(cscfg_param_, value);
+
+static struct configfs_attribute *cscfg_param_view_attrs[] = {
+ &cscfg_param_attr_value,
+ NULL,
+};
+
+static struct config_item_type cscfg_param_view_type = {
+ .ct_owner = THIS_MODULE,
+ .ct_attrs = cscfg_param_view_attrs,
+};
+
+/*
+ * configfs has far less functionality provided to add attributes dynamically than sysfs,
+ * and the show and store fns pass the enclosing config_item so the actual attribute cannot
+ * be determined. Therefore we add each item as a group directory, with a value attribute.
+ */
+static int cscfg_create_params_group_items(struct cscfg_feature_desc *feat_desc,
+ struct config_group *params_group)
+{
+ struct device *dev = cscfg_device();
+ struct cscfg_fs_param *param_item;
+ int i;
+
+ /* parameter items - as groups with default_value attribute */
+ for (i = 0; i < feat_desc->nr_params; i++) {
+ param_item = devm_kzalloc(dev, sizeof(struct cscfg_fs_param), GFP_KERNEL);
+ if (!param_item)
+ return -ENOMEM;
+ param_item->feat_desc = feat_desc;
+ param_item->param_idx = i;
+ config_group_init_type_name(&param_item->group,
+ feat_desc->params_desc[i].name,
+ &cscfg_param_view_type);
+ configfs_add_default_group(&param_item->group, params_group);
+ }
+ return 0;
+}
+
+static struct config_group *cscfg_create_feature_group(struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_fs_feature *feat_view;
+ struct config_item_type *params_group_type;
+ struct config_group *params_group = NULL;
+ struct device *dev = cscfg_device();
+ int item_err;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ feat_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_feature), GFP_KERNEL);
+ if (!feat_view)
+ return ERR_PTR(-ENOMEM);
+
+ if (feat_desc->nr_params) {
+ params_group = devm_kzalloc(dev, sizeof(struct config_group), GFP_KERNEL);
+ if (!params_group)
+ return ERR_PTR(-ENOMEM);
+
+ params_group_type = cscfg_create_ci_type();
+ if (!params_group_type)
+ return ERR_PTR(-ENOMEM);
+ }
+
+ feat_view->feat_desc = feat_desc;
+ config_group_init_type_name(&feat_view->group,
+ feat_desc->name,
+ &cscfg_feature_view_type);
+ if (params_group) {
+ config_group_init_type_name(params_group, "params", params_group_type);
+ configfs_add_default_group(params_group, &feat_view->group);
+ item_err = cscfg_create_params_group_items(feat_desc, params_group);
+ if (item_err)
+ return ERR_PTR(item_err);
+ }
+ return &feat_view->group;
+}
+
+static struct config_item_type cscfg_configs_type = {
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group cscfg_configs_grp = {
+ .cg_item = {
+ .ci_namebuf = "configurations",
+ .ci_type = &cscfg_configs_type,
+ },
+};
+
+/* add configuration to configurations group */
+int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc)
+{
+ struct config_group *new_group;
+ int err;
+
+ new_group = cscfg_create_config_group(config_desc);
+ if (IS_ERR(new_group))
+ return PTR_ERR(new_group);
+ err = configfs_register_group(&cscfg_configs_grp, new_group);
+ return err;
+}
+
+static struct config_item_type cscfg_features_type = {
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group cscfg_features_grp = {
+ .cg_item = {
+ .ci_namebuf = "features",
+ .ci_type = &cscfg_features_type,
+ },
+};
+
+/* add feature to features group */
+int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc)
+{
+ struct config_group *new_group;
+ int err;
+
+ new_group = cscfg_create_feature_group(feat_desc);
+ if (IS_ERR(new_group))
+ return PTR_ERR(new_group);
+ err = configfs_register_group(&cscfg_features_grp, new_group);
+ return err;
+}
+
+int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr)
+{
+ struct configfs_subsystem *subsys;
+ struct config_item_type *ci_type;
+
+ if (!cscfg_mgr)
+ return -EINVAL;
+
+ ci_type = cscfg_create_ci_type();
+ if (!ci_type)
+ return -ENOMEM;
+
+ subsys = &cscfg_mgr->cfgfs_subsys;
+ config_item_set_name(&subsys->su_group.cg_item, CSCFG_FS_SUBSYS_NAME);
+ subsys->su_group.cg_item.ci_type = ci_type;
+
+ config_group_init(&subsys->su_group);
+ mutex_init(&subsys->su_mutex);
+
+ /* Add default groups to subsystem */
+ config_group_init(&cscfg_configs_grp);
+ configfs_add_default_group(&cscfg_configs_grp, &subsys->su_group);
+
+ config_group_init(&cscfg_features_grp);
+ configfs_add_default_group(&cscfg_features_grp, &subsys->su_group);
+
+ return configfs_register_subsystem(subsys);
+}
+
+void cscfg_configfs_release(struct cscfg_manager *cscfg_mgr)
+{
+ configfs_unregister_subsystem(&cscfg_mgr->cfgfs_subsys);
+}
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
new file mode 100644
index 000000000000..7d6ffe35ca4c
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Coresight system configuration driver - support for configfs.
+ */
+
+#ifndef CORESIGHT_SYSCFG_CONFIGFS_H
+#define CORESIGHT_SYSCFG_CONFIGFS_H
+
+#include <linux/configfs.h>
+#include "coresight-syscfg.h"
+
+#define CSCFG_FS_SUBSYS_NAME "cs-syscfg"
+
+/* container for configuration view */
+struct cscfg_fs_config {
+ struct cscfg_config_desc *config_desc;
+ struct config_group group;
+};
+
+/* container for feature view */
+struct cscfg_fs_feature {
+ struct cscfg_feature_desc *feat_desc;
+ struct config_group group;
+};
+
+/* container for parameter view */
+struct cscfg_fs_param {
+ int param_idx;
+ struct cscfg_feature_desc *feat_desc;
+ struct config_group group;
+};
+
+/* container for preset view */
+struct cscfg_fs_preset {
+ int preset_num;
+ struct cscfg_config_desc *config_desc;
+ struct config_group group;
+};
+
+int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr);
+void cscfg_configfs_release(struct cscfg_manager *cscfg_mgr);
+int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc);
+int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc);
+
+#endif /* CORESIGHT_SYSCFG_CONFIGFS_H */
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
new file mode 100644
index 000000000000..fc0760f55c53
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -0,0 +1,847 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include <linux/platform_device.h>
+
+#include "coresight-config.h"
+#include "coresight-etm-perf.h"
+#include "coresight-syscfg.h"
+#include "coresight-syscfg-configfs.h"
+
+/*
+ * cscfg_ API manages configurations and features for the entire coresight
+ * infrastructure.
+ *
+ * It allows the loading of configurations and features, and loads these into
+ * coresight devices as appropriate.
+ */
+
+/* protect the cscsg_data and device */
+static DEFINE_MUTEX(cscfg_mutex);
+
+/* only one of these */
+static struct cscfg_manager *cscfg_mgr;
+
+/* load features and configuations into the lists */
+
+/* get name feature instance from a coresight device list of features */
+static struct cscfg_feature_csdev *
+cscfg_get_feat_csdev(struct coresight_device *csdev, const char *name)
+{
+ struct cscfg_feature_csdev *feat_csdev = NULL;
+
+ list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
+ if (strcmp(feat_csdev->feat_desc->name, name) == 0)
+ return feat_csdev;
+ }
+ return NULL;
+}
+
+/* allocate the device config instance - with max number of used features */
+static struct cscfg_config_csdev *
+cscfg_alloc_csdev_cfg(struct coresight_device *csdev, int nr_feats)
+{
+ struct cscfg_config_csdev *config_csdev = NULL;
+ struct device *dev = csdev->dev.parent;
+
+ /* this is being allocated using the devm for the coresight device */
+ config_csdev = devm_kzalloc(dev,
+ offsetof(struct cscfg_config_csdev, feats_csdev[nr_feats]),
+ GFP_KERNEL);
+ if (!config_csdev)
+ return NULL;
+
+ config_csdev->csdev = csdev;
+ return config_csdev;
+}
+
+/* Load a config into a device if there are any feature matches between config and device */
+static int cscfg_add_csdev_cfg(struct coresight_device *csdev,
+ struct cscfg_config_desc *config_desc)
+{
+ struct cscfg_config_csdev *config_csdev = NULL;
+ struct cscfg_feature_csdev *feat_csdev;
+ unsigned long flags;
+ int i;
+
+ /* look at each required feature and see if it matches any feature on the device */
+ for (i = 0; i < config_desc->nr_feat_refs; i++) {
+ /* look for a matching name */
+ feat_csdev = cscfg_get_feat_csdev(csdev, config_desc->feat_ref_names[i]);
+ if (feat_csdev) {
+ /*
+ * At least one feature on this device matches the config
+ * add a config instance to the device and a reference to the feature.
+ */
+ if (!config_csdev) {
+ config_csdev = cscfg_alloc_csdev_cfg(csdev,
+ config_desc->nr_feat_refs);
+ if (!config_csdev)
+ return -ENOMEM;
+ config_csdev->config_desc = config_desc;
+ }
+ config_csdev->feats_csdev[config_csdev->nr_feat++] = feat_csdev;
+ }
+ }
+ /* if matched features, add config to device.*/
+ if (config_csdev) {
+ spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+ list_add(&config_csdev->node, &csdev->config_csdev_list);
+ spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+ }
+
+ return 0;
+}
+
+/*
+ * Add the config to the set of registered devices - call with mutex locked.
+ * Iterates through devices - any device that matches one or more of the
+ * configuration features will load it, the others will ignore it.
+ */
+static int cscfg_add_cfg_to_csdevs(struct cscfg_config_desc *config_desc)
+{
+ struct cscfg_registered_csdev *csdev_item;
+ int err;
+
+ list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
+ err = cscfg_add_csdev_cfg(csdev_item->csdev, config_desc);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * Allocate a feature object for load into a csdev.
+ * memory allocated using the csdev->dev object using devm managed allocator.
+ */
+static struct cscfg_feature_csdev *
+cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_feature_csdev *feat_csdev = NULL;
+ struct device *dev = csdev->dev.parent;
+ int i;
+
+ feat_csdev = devm_kzalloc(dev, sizeof(struct cscfg_feature_csdev), GFP_KERNEL);
+ if (!feat_csdev)
+ return NULL;
+
+ /* parameters are optional - could be 0 */
+ feat_csdev->nr_params = feat_desc->nr_params;
+
+ /*
+ * if we need parameters, zero alloc the space here, the load routine in
+ * the csdev device driver will fill out some information according to
+ * feature descriptor.
+ */
+ if (feat_csdev->nr_params) {
+ feat_csdev->params_csdev = devm_kcalloc(dev, feat_csdev->nr_params,
+ sizeof(struct cscfg_parameter_csdev),
+ GFP_KERNEL);
+ if (!feat_csdev->params_csdev)
+ return NULL;
+
+ /*
+ * fill in the feature reference in the param - other fields
+ * handled by loader in csdev.
+ */
+ for (i = 0; i < feat_csdev->nr_params; i++)
+ feat_csdev->params_csdev[i].feat_csdev = feat_csdev;
+ }
+
+ /*
+ * Always have registers to program - again the load routine in csdev device
+ * will fill out according to feature descriptor and device requirements.
+ */
+ feat_csdev->nr_regs = feat_desc->nr_regs;
+ feat_csdev->regs_csdev = devm_kcalloc(dev, feat_csdev->nr_regs,
+ sizeof(struct cscfg_regval_csdev),
+ GFP_KERNEL);
+ if (!feat_csdev->regs_csdev)
+ return NULL;
+
+ /* load the feature default values */
+ feat_csdev->feat_desc = feat_desc;
+ feat_csdev->csdev = csdev;
+
+ return feat_csdev;
+}
+
+/* load one feature into one coresight device */
+static int cscfg_load_feat_csdev(struct coresight_device *csdev,
+ struct cscfg_feature_desc *feat_desc,
+ struct cscfg_csdev_feat_ops *ops)
+{
+ struct cscfg_feature_csdev *feat_csdev;
+ unsigned long flags;
+ int err;
+
+ if (!ops->load_feat)
+ return -EINVAL;
+
+ feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc);
+ if (!feat_csdev)
+ return -ENOMEM;
+
+ /* load the feature into the device */
+ err = ops->load_feat(csdev, feat_csdev);
+ if (err)
+ return err;
+
+ /* add to internal csdev feature list & initialise using reset call */
+ cscfg_reset_feat(feat_csdev);
+ spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+ list_add(&feat_csdev->node, &csdev->feature_csdev_list);
+ spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+
+ return 0;
+}
+
+/*
+ * Add feature to any matching devices - call with mutex locked.
+ * Iterates through devices - any device that matches the feature will be
+ * called to load it.
+ */
+static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_registered_csdev *csdev_item;
+ int err;
+
+ list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
+ if (csdev_item->match_flags & feat_desc->match_flags) {
+ err = cscfg_load_feat_csdev(csdev_item->csdev, feat_desc, &csdev_item->ops);
+ if (err)
+ return err;
+ }
+ }
+ return 0;
+}
+
+/* check feature list for a named feature - call with mutex locked. */
+static bool cscfg_match_list_feat(const char *name)
+{
+ struct cscfg_feature_desc *feat_desc;
+
+ list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
+ if (strcmp(feat_desc->name, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+/* check all feat needed for cfg are in the list - call with mutex locked. */
+static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *config_desc)
+{
+ int i;
+
+ for (i = 0; i < config_desc->nr_feat_refs; i++)
+ if (!cscfg_match_list_feat(config_desc->feat_ref_names[i]))
+ return -EINVAL;
+ return 0;
+}
+
+/*
+ * load feature - add to feature list.
+ */
+static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc)
+{
+ int err;
+
+ /* add feature to any matching registered devices */
+ err = cscfg_add_feat_to_csdevs(feat_desc);
+ if (err)
+ return err;
+
+ list_add(&feat_desc->item, &cscfg_mgr->feat_desc_list);
+ return 0;
+}
+
+/*
+ * load config into the system - validate used features exist then add to
+ * config list.
+ */
+static int cscfg_load_config(struct cscfg_config_desc *config_desc)
+{
+ int err;
+
+ /* validate features are present */
+ err = cscfg_check_feat_for_cfg(config_desc);
+ if (err)
+ return err;
+
+ /* add config to any matching registered device */
+ err = cscfg_add_cfg_to_csdevs(config_desc);
+ if (err)
+ return err;
+
+ /* add config to perf fs to allow selection */
+ err = etm_perf_add_symlink_cscfg(cscfg_device(), config_desc);
+ if (err)
+ return err;
+
+ list_add(&config_desc->item, &cscfg_mgr->config_desc_list);
+ atomic_set(&config_desc->active_cnt, 0);
+ return 0;
+}
+
+/* get a feature descriptor by name */
+const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name)
+{
+ const struct cscfg_feature_desc *feat_desc = NULL, *feat_desc_item;
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(feat_desc_item, &cscfg_mgr->feat_desc_list, item) {
+ if (strcmp(feat_desc_item->name, name) == 0) {
+ feat_desc = feat_desc_item;
+ break;
+ }
+ }
+
+ mutex_unlock(&cscfg_mutex);
+ return feat_desc;
+}
+
+/* called with cscfg_mutex held */
+static struct cscfg_feature_csdev *
+cscfg_csdev_get_feat_from_desc(struct coresight_device *csdev,
+ struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_feature_csdev *feat_csdev;
+
+ list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
+ if (feat_csdev->feat_desc == feat_desc)
+ return feat_csdev;
+ }
+ return NULL;
+}
+
+int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc,
+ int param_idx, u64 value)
+{
+ int err = 0;
+ struct cscfg_feature_csdev *feat_csdev;
+ struct cscfg_registered_csdev *csdev_item;
+
+ mutex_lock(&cscfg_mutex);
+
+ /* check if any config active & return busy */
+ if (atomic_read(&cscfg_mgr->sys_active_cnt)) {
+ err = -EBUSY;
+ goto unlock_exit;
+ }
+
+ /* set the value */
+ if ((param_idx < 0) || (param_idx >= feat_desc->nr_params)) {
+ err = -EINVAL;
+ goto unlock_exit;
+ }
+ feat_desc->params_desc[param_idx].value = value;
+
+ /* update loaded instances.*/
+ list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
+ feat_csdev = cscfg_csdev_get_feat_from_desc(csdev_item->csdev, feat_desc);
+ if (feat_csdev)
+ feat_csdev->params_csdev[param_idx].current_value = value;
+ }
+
+unlock_exit:
+ mutex_unlock(&cscfg_mutex);
+ return err;
+}
+
+/**
+ * cscfg_load_config_sets - API function to load feature and config sets.
+ *
+ * Take a 0 terminated array of feature descriptors and/or configuration
+ * descriptors and load into the system.
+ * Features are loaded first to ensure configuration dependencies can be met.
+ *
+ * @config_descs: 0 terminated array of configuration descriptors.
+ * @feat_descs: 0 terminated array of feature descriptors.
+ */
+int cscfg_load_config_sets(struct cscfg_config_desc **config_descs,
+ struct cscfg_feature_desc **feat_descs)
+{
+ int err, i = 0;
+
+ mutex_lock(&cscfg_mutex);
+
+ /* load features first */
+ if (feat_descs) {
+ while (feat_descs[i]) {
+ err = cscfg_load_feat(feat_descs[i]);
+ if (!err)
+ err = cscfg_configfs_add_feature(feat_descs[i]);
+ if (err) {
+ pr_err("coresight-syscfg: Failed to load feature %s\n",
+ feat_descs[i]->name);
+ goto exit_unlock;
+ }
+ i++;
+ }
+ }
+
+ /* next any configurations to check feature dependencies */
+ i = 0;
+ if (config_descs) {
+ while (config_descs[i]) {
+ err = cscfg_load_config(config_descs[i]);
+ if (!err)
+ err = cscfg_configfs_add_config(config_descs[i]);
+ if (err) {
+ pr_err("coresight-syscfg: Failed to load configuration %s\n",
+ config_descs[i]->name);
+ goto exit_unlock;
+ }
+ i++;
+ }
+ }
+
+exit_unlock:
+ mutex_unlock(&cscfg_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(cscfg_load_config_sets);
+
+/* Handle coresight device registration and add configs and features to devices */
+
+/* iterate through config lists and load matching configs to device */
+static int cscfg_add_cfgs_csdev(struct coresight_device *csdev)
+{
+ struct cscfg_config_desc *config_desc;
+ int err = 0;
+
+ list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
+ err = cscfg_add_csdev_cfg(csdev, config_desc);
+ if (err)
+ break;
+ }
+ return err;
+}
+
+/* iterate through feature lists and load matching features to device */
+static int cscfg_add_feats_csdev(struct coresight_device *csdev,
+ u32 match_flags,
+ struct cscfg_csdev_feat_ops *ops)
+{
+ struct cscfg_feature_desc *feat_desc;
+ int err = 0;
+
+ if (!ops->load_feat)
+ return -EINVAL;
+
+ list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
+ if (feat_desc->match_flags & match_flags) {
+ err = cscfg_load_feat_csdev(csdev, feat_desc, ops);
+ if (err)
+ break;
+ }
+ }
+ return err;
+}
+
+/* Add coresight device to list and copy its matching info */
+static int cscfg_list_add_csdev(struct coresight_device *csdev,
+ u32 match_flags,
+ struct cscfg_csdev_feat_ops *ops)
+{
+ struct cscfg_registered_csdev *csdev_item;
+
+ /* allocate the list entry structure */
+ csdev_item = kzalloc(sizeof(struct cscfg_registered_csdev), GFP_KERNEL);
+ if (!csdev_item)
+ return -ENOMEM;
+
+ csdev_item->csdev = csdev;
+ csdev_item->match_flags = match_flags;
+ csdev_item->ops.load_feat = ops->load_feat;
+ list_add(&csdev_item->item, &cscfg_mgr->csdev_desc_list);
+
+ INIT_LIST_HEAD(&csdev->feature_csdev_list);
+ INIT_LIST_HEAD(&csdev->config_csdev_list);
+ spin_lock_init(&csdev->cscfg_csdev_lock);
+
+ return 0;
+}
+
+/* remove a coresight device from the list and free data */
+static void cscfg_list_remove_csdev(struct coresight_device *csdev)
+{
+ struct cscfg_registered_csdev *csdev_item, *tmp;
+
+ list_for_each_entry_safe(csdev_item, tmp, &cscfg_mgr->csdev_desc_list, item) {
+ if (csdev_item->csdev == csdev) {
+ list_del(&csdev_item->item);
+ kfree(csdev_item);
+ break;
+ }
+ }
+}
+
+/**
+ * cscfg_register_csdev - register a coresight device with the syscfg manager.
+ *
+ * Registers the coresight device with the system. @match_flags used to check
+ * if the device is a match for registered features. Any currently registered
+ * configurations and features that match the device will be loaded onto it.
+ *
+ * @csdev: The coresight device to register.
+ * @match_flags: Matching information to load features.
+ * @ops: Standard operations supported by the device.
+ */
+int cscfg_register_csdev(struct coresight_device *csdev,
+ u32 match_flags,
+ struct cscfg_csdev_feat_ops *ops)
+{
+ int ret = 0;
+
+ mutex_lock(&cscfg_mutex);
+
+ /* add device to list of registered devices */
+ ret = cscfg_list_add_csdev(csdev, match_flags, ops);
+ if (ret)
+ goto reg_csdev_unlock;
+
+ /* now load any registered features and configs matching the device. */
+ ret = cscfg_add_feats_csdev(csdev, match_flags, ops);
+ if (ret) {
+ cscfg_list_remove_csdev(csdev);
+ goto reg_csdev_unlock;
+ }
+
+ ret = cscfg_add_cfgs_csdev(csdev);
+ if (ret) {
+ cscfg_list_remove_csdev(csdev);
+ goto reg_csdev_unlock;
+ }
+
+ pr_info("CSCFG registered %s", dev_name(&csdev->dev));
+
+reg_csdev_unlock:
+ mutex_unlock(&cscfg_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cscfg_register_csdev);
+
+/**
+ * cscfg_unregister_csdev - remove coresight device from syscfg manager.
+ *
+ * @csdev: Device to remove.
+ */
+void cscfg_unregister_csdev(struct coresight_device *csdev)
+{
+ mutex_lock(&cscfg_mutex);
+ cscfg_list_remove_csdev(csdev);
+ mutex_unlock(&cscfg_mutex);
+}
+EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);
+
+/**
+ * cscfg_csdev_reset_feats - reset features for a CoreSight device.
+ *
+ * Resets all parameters and register values for any features loaded
+ * into @csdev to their default values.
+ *
+ * @csdev: The CoreSight device.
+ */
+void cscfg_csdev_reset_feats(struct coresight_device *csdev)
+{
+ struct cscfg_feature_csdev *feat_csdev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+ if (list_empty(&csdev->feature_csdev_list))
+ goto unlock_exit;
+
+ list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node)
+ cscfg_reset_feat(feat_csdev);
+
+unlock_exit:
+ spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+}
+EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
+
+/**
+ * cscfg_activate_config - Mark a configuration descriptor as active.
+ *
+ * This will be seen when csdev devices are enabled in the system.
+ * Only activated configurations can be enabled on individual devices.
+ * Activation protects the configuration from alteration or removal while
+ * active.
+ *
+ * Selection by hash value - generated from the configuration name when it
+ * was loaded and added to the cs_etm/configurations file system for selection
+ * by perf.
+ *
+ * Increments the configuration descriptor active count and the global active
+ * count.
+ *
+ * @cfg_hash: Hash value of the selected configuration name.
+ */
+int cscfg_activate_config(unsigned long cfg_hash)
+{
+ struct cscfg_config_desc *config_desc;
+ int err = -EINVAL;
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
+ if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
+ /*
+ * increment the global active count - control changes to
+ * active configurations
+ */
+ atomic_inc(&cscfg_mgr->sys_active_cnt);
+
+ /*
+ * mark the descriptor as active so enable config on a
+ * device instance will use it
+ */
+ atomic_inc(&config_desc->active_cnt);
+
+ err = 0;
+ dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(cscfg_activate_config);
+
+/**
+ * cscfg_deactivate_config - Mark a config descriptor as inactive.
+ *
+ * Decrement the configuration and global active counts.
+ *
+ * @cfg_hash: Hash value of the selected configuration name.
+ */
+void cscfg_deactivate_config(unsigned long cfg_hash)
+{
+ struct cscfg_config_desc *config_desc;
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
+ if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
+ atomic_dec(&config_desc->active_cnt);
+ atomic_dec(&cscfg_mgr->sys_active_cnt);
+ dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+}
+EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
+
+/**
+ * cscfg_csdev_enable_active_config - Enable matching active configuration for device.
+ *
+ * Enables the configuration selected by @cfg_hash if the configuration is supported
+ * on the device and has been activated.
+ *
+ * If active and supported the CoreSight device @csdev will be programmed with the
+ * configuration, using @preset parameters.
+ *
+ * Should be called before driver hardware enable for the requested device, prior to
+ * programming and enabling the physical hardware.
+ *
+ * @csdev: CoreSight device to program.
+ * @cfg_hash: Selector for the configuration.
+ * @preset: Preset parameter values to use, 0 for current / default values.
+ */
+int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
+ unsigned long cfg_hash, int preset)
+{
+ struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
+ const struct cscfg_config_desc *config_desc;
+ unsigned long flags;
+ int err = 0;
+
+ /* quickly check global count */
+ if (!atomic_read(&cscfg_mgr->sys_active_cnt))
+ return 0;
+
+ /*
+ * Look for matching configuration - set the active configuration
+ * context if found.
+ */
+ spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+ list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
+ config_desc = config_csdev_item->config_desc;
+ if ((atomic_read(&config_desc->active_cnt)) &&
+ ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
+ config_csdev_active = config_csdev_item;
+ csdev->active_cscfg_ctxt = (void *)config_csdev_active;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+
+ /*
+ * If found, attempt to enable
+ */
+ if (config_csdev_active) {
+ /*
+ * Call the generic routine that will program up the internal
+ * driver structures prior to programming up the hardware.
+ * This routine takes the driver spinlock saved in the configs.
+ */
+ err = cscfg_csdev_enable_config(config_csdev_active, preset);
+ if (!err) {
+ /*
+ * Successful programming. Check the active_cscfg_ctxt
+ * pointer to ensure no pre-emption disabled it via
+ * cscfg_csdev_disable_active_config() before
+ * we could start.
+ *
+ * Set enabled if OK, err if not.
+ */
+ spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+ if (csdev->active_cscfg_ctxt)
+ config_csdev_active->enabled = true;
+ else
+ err = -EBUSY;
+ spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+ }
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
+
+/**
+ * cscfg_csdev_disable_active_config - disable an active config on the device.
+ *
+ * Disables the active configuration on the CoreSight device @csdev.
+ * Disable will save the values of any registers marked in the configurations
+ * as save on disable.
+ *
+ * Should be called after driver hardware disable for the requested device,
+ * after disabling the physical hardware and reading back registers.
+ *
+ * @csdev: The CoreSight device.
+ */
+void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
+{
+ struct cscfg_config_csdev *config_csdev;
+ unsigned long flags;
+
+ /*
+ * Check if we have an active config, and that it was successfully enabled.
+ * If it was not enabled, we have no work to do, otherwise mark as disabled.
+ * Clear the active config pointer.
+ */
+ spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+ config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
+ if (config_csdev) {
+ if (!config_csdev->enabled)
+ config_csdev = NULL;
+ else
+ config_csdev->enabled = false;
+ }
+ csdev->active_cscfg_ctxt = NULL;
+ spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+
+ /* true if there was an enabled active config */
+ if (config_csdev)
+ cscfg_csdev_disable_config(config_csdev);
+}
+EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
+
+/* Initialise system configuration management device. */
+
+struct device *cscfg_device(void)
+{
+ return cscfg_mgr ? &cscfg_mgr->dev : NULL;
+}
+
+/* Must have a release function or the kernel will complain on module unload */
+static void cscfg_dev_release(struct device *dev)
+{
+ kfree(cscfg_mgr);
+ cscfg_mgr = NULL;
+}
+
+/* a device is needed to "own" some kernel elements such as sysfs entries. */
+static int cscfg_create_device(void)
+{
+ struct device *dev;
+ int err = -ENOMEM;
+
+ mutex_lock(&cscfg_mutex);
+ if (cscfg_mgr) {
+ err = -EINVAL;
+ goto create_dev_exit_unlock;
+ }
+
+ cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL);
+ if (!cscfg_mgr)
+ goto create_dev_exit_unlock;
+
+ /* setup the device */
+ dev = cscfg_device();
+ dev->release = cscfg_dev_release;
+ dev->init_name = "cs_system_cfg";
+
+ err = device_register(dev);
+ if (err)
+ cscfg_dev_release(dev);
+
+create_dev_exit_unlock:
+ mutex_unlock(&cscfg_mutex);
+ return err;
+}
+
+static void cscfg_clear_device(void)
+{
+ struct cscfg_config_desc *cfg_desc;
+
+ mutex_lock(&cscfg_mutex);
+ list_for_each_entry(cfg_desc, &cscfg_mgr->config_desc_list, item) {
+ etm_perf_del_symlink_cscfg(cfg_desc);
+ }
+ cscfg_configfs_release(cscfg_mgr);
+ device_unregister(cscfg_device());
+ mutex_unlock(&cscfg_mutex);
+}
+
+/* Initialise system config management API device */
+int __init cscfg_init(void)
+{
+ int err = 0;
+
+ err = cscfg_create_device();
+ if (err)
+ return err;
+
+ err = cscfg_configfs_init(cscfg_mgr);
+ if (err)
+ goto exit_err;
+
+ INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list);
+ INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list);
+ INIT_LIST_HEAD(&cscfg_mgr->config_desc_list);
+ atomic_set(&cscfg_mgr->sys_active_cnt, 0);
+
+ /* preload built-in configurations */
+ err = cscfg_preload();
+ if (err)
+ goto exit_err;
+
+ dev_info(cscfg_device(), "CoreSight Configuration manager initialised");
+ return 0;
+
+exit_err:
+ cscfg_clear_device();
+ return err;
+}
+
+void cscfg_exit(void)
+{
+ cscfg_clear_device();
+}
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h
new file mode 100644
index 000000000000..8d018efd6ead
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-syscfg.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Coresight system configuration driver.
+ */
+
+#ifndef CORESIGHT_SYSCFG_H
+#define CORESIGHT_SYSCFG_H
+
+#include <linux/configfs.h>
+#include <linux/coresight.h>
+#include <linux/device.h>
+
+#include "coresight-config.h"
+
+/**
+ * System configuration manager device.
+ *
+ * Contains lists of the loaded configurations and features, plus a list of CoreSight devices
+ * registered with the system as supporting configuration management.
+ *
+ * Need a device to 'own' some coresight system wide sysfs entries in
+ * perf events, configfs etc.
+ *
+ * @dev: The device.
+ * @csdev_desc_list: List of coresight devices registered with the configuration manager.
+ * @feat_desc_list: List of feature descriptors to load into registered devices.
+ * @config_desc_list: List of system configuration descriptors to load into registered devices.
+ * @sys_active_cnt: Total number of active config descriptor references.
+ * @cfgfs_subsys: configfs subsystem used to manage configurations.
+ */
+struct cscfg_manager {
+ struct device dev;
+ struct list_head csdev_desc_list;
+ struct list_head feat_desc_list;
+ struct list_head config_desc_list;
+ atomic_t sys_active_cnt;
+ struct configfs_subsystem cfgfs_subsys;
+};
+
+/* get reference to dev in cscfg_manager */
+struct device *cscfg_device(void);
+
+/**
+ * List entry for Coresight devices that are registered as supporting complex
+ * config operations.
+ *
+ * @csdev: The registered device.
+ * @match_flags: The matching type information for adding features.
+ * @ops: Operations supported by the registered device.
+ * @item: list entry.
+ */
+struct cscfg_registered_csdev {
+ struct coresight_device *csdev;
+ u32 match_flags;
+ struct cscfg_csdev_feat_ops ops;
+ struct list_head item;
+};
+
+/* internal core operations for cscfg */
+int __init cscfg_init(void);
+void cscfg_exit(void);
+int cscfg_preload(void);
+const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name);
+int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc,
+ int param_idx, u64 value);
+
+
+/* syscfg manager external API */
+int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
+ struct cscfg_feature_desc **feat_descs);
+int cscfg_register_csdev(struct coresight_device *csdev, u32 match_flags,
+ struct cscfg_csdev_feat_ops *ops);
+void cscfg_unregister_csdev(struct coresight_device *csdev);
+int cscfg_activate_config(unsigned long cfg_hash);
+void cscfg_deactivate_config(unsigned long cfg_hash);
+void cscfg_csdev_reset_feats(struct coresight_device *csdev);
+int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
+ unsigned long cfg_hash, int preset);
+void cscfg_csdev_disable_active_config(struct coresight_device *csdev);
+
+#endif /* CORESIGHT_SYSCFG_H */
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 66eed2dff818..7e753a75d23b 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -95,7 +95,7 @@ out_pm:
static void intel_th_device_remove(struct intel_th_device *thdev);
-static int intel_th_remove(struct device *dev)
+static void intel_th_remove(struct device *dev)
{
struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver);
struct intel_th_device *thdev = to_intel_th_device(dev);
@@ -164,8 +164,6 @@ static int intel_th_remove(struct device *dev)
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
-
- return 0;
}
static struct bus_type intel_th_bus = {
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 6f0aa0ed3241..aaeeacc12121 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -69,6 +69,38 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
}
EXPORT_SYMBOL_GPL(i2c_acpi_get_i2c_resource);
+static int i2c_acpi_resource_count(struct acpi_resource *ares, void *data)
+{
+ struct acpi_resource_i2c_serialbus *sb;
+ int *count = data;
+
+ if (i2c_acpi_get_i2c_resource(ares, &sb))
+ *count = *count + 1;
+
+ return 1;
+}
+
+/**
+ * i2c_acpi_client_count - Count the number of I2cSerialBus resources
+ * @adev: ACPI device
+ *
+ * Returns the number of I2cSerialBus resources in the ACPI-device's
+ * resource-list; or a negative error code.
+ */
+int i2c_acpi_client_count(struct acpi_device *adev)
+{
+ int ret, count = 0;
+ LIST_HEAD(r);
+
+ ret = acpi_dev_get_resources(adev, &r, i2c_acpi_resource_count, &count);
+ if (ret < 0)
+ return ret;
+
+ acpi_dev_free_resource_list(&r);
+ return count;
+}
+EXPORT_SYMBOL_GPL(i2c_acpi_client_count);
+
static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
{
struct i2c_acpi_lookup *lookup = data;
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 84f12bf90644..54964fbe3f03 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -601,7 +601,7 @@ put_sync_adapter:
return status;
}
-static int i2c_device_remove(struct device *dev)
+static void i2c_device_remove(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_adapter *adap;
@@ -631,9 +631,6 @@ static int i2c_device_remove(struct device *dev)
client->irq = 0;
if (client->flags & I2C_CLIENT_HOST_NOTIFY)
pm_runtime_put(&client->adapter->dev);
-
- /* return always 0 because there is WIP to make remove-functions void */
- return 0;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index e2e12a5585e5..c3b4c677b442 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -322,7 +322,7 @@ static int i3c_device_probe(struct device *dev)
return driver->probe(i3cdev);
}
-static int i3c_device_remove(struct device *dev)
+static void i3c_device_remove(struct device *dev)
{
struct i3c_device *i3cdev = dev_to_i3cdev(dev);
struct i3c_driver *driver = drv_to_i3cdrv(dev->driver);
@@ -331,8 +331,6 @@ static int i3c_device_remove(struct device *dev)
driver->remove(i3cdev);
i3c_device_free_ibi(i3cdev);
-
- return 0;
}
struct bus_type i3c_bus_type = {
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 8d8b1ba42ff8..a0e9061f6d6b 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -143,10 +143,11 @@ config BMC150_ACCEL
select BMC150_ACCEL_SPI if SPI
help
Say yes here to build support for the following Bosch accelerometers:
- BMA222, BMA222E, BMA250E, BMA253, BMA254, BMA255, BMA280, BMC150, BMI055.
+ BMA222, BMA222E, BMA250E, BMA253, BMA254, BMA255, BMA280, BMC150, BMC156
+ BMI055.
Note that some of these are combo modules:
- - BMC150: accelerometer and magnetometer
+ - BMC150/BMC156: accelerometer and magnetometer
- BMI055: accelerometer and gyroscope
This driver is only implementing accelerometer part, which has
diff --git a/drivers/iio/accel/adxl345.h b/drivers/iio/accel/adxl345.h
index 384497776b67..af0fdd02c4f2 100644
--- a/drivers/iio/accel/adxl345.h
+++ b/drivers/iio/accel/adxl345.h
@@ -15,6 +15,5 @@ enum adxl345_device_type {
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
enum adxl345_device_type type, const char *name);
-int adxl345_core_remove(struct device *dev);
#endif /* _ADXL345_H_ */
diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c
index 312866530065..4b275051ef61 100644
--- a/drivers/iio/accel/adxl345_core.c
+++ b/drivers/iio/accel/adxl345_core.c
@@ -208,6 +208,11 @@ static const struct iio_info adxl345_info = {
.write_raw_get_fmt = adxl345_write_raw_get_fmt,
};
+static void adxl345_powerdown(void *regmap)
+{
+ regmap_write(regmap, ADXL345_REG_POWER_CTL, ADXL345_POWER_CTL_STANDBY);
+}
+
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
enum adxl345_device_type type, const char *name)
{
@@ -233,7 +238,6 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
return -ENOMEM;
data = iio_priv(indio_dev);
- dev_set_drvdata(dev, indio_dev);
data->regmap = regmap;
data->type = type;
/* Enable full-resolution mode */
@@ -260,29 +264,14 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
return ret;
}
- ret = iio_device_register(indio_dev);
- if (ret < 0) {
- dev_err(dev, "iio_device_register failed: %d\n", ret);
- regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
- ADXL345_POWER_CTL_STANDBY);
- }
+ ret = devm_add_action_or_reset(dev, adxl345_powerdown, data->regmap);
+ if (ret < 0)
+ return ret;
- return ret;
+ return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_GPL(adxl345_core_probe);
-int adxl345_core_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adxl345_data *data = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- return regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
- ADXL345_POWER_CTL_STANDBY);
-}
-EXPORT_SYMBOL_GPL(adxl345_core_remove);
-
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c
index 1561364ae296..a431cba216e6 100644
--- a/drivers/iio/accel/adxl345_i2c.c
+++ b/drivers/iio/accel/adxl345_i2c.c
@@ -38,11 +38,6 @@ static int adxl345_i2c_probe(struct i2c_client *client,
id->name);
}
-static int adxl345_i2c_remove(struct i2c_client *client)
-{
- return adxl345_core_remove(&client->dev);
-}
-
static const struct i2c_device_id adxl345_i2c_id[] = {
{ "adxl345", ADXL345 },
{ "adxl375", ADXL375 },
@@ -65,7 +60,6 @@ static struct i2c_driver adxl345_i2c_driver = {
.of_match_table = adxl345_of_match,
},
.probe = adxl345_i2c_probe,
- .remove = adxl345_i2c_remove,
.id_table = adxl345_i2c_id,
};
diff --git a/drivers/iio/accel/adxl345_spi.c b/drivers/iio/accel/adxl345_spi.c
index da4591c7ef23..ea559ac2e87d 100644
--- a/drivers/iio/accel/adxl345_spi.c
+++ b/drivers/iio/accel/adxl345_spi.c
@@ -42,11 +42,6 @@ static int adxl345_spi_probe(struct spi_device *spi)
return adxl345_core_probe(&spi->dev, regmap, id->driver_data, id->name);
}
-static int adxl345_spi_remove(struct spi_device *spi)
-{
- return adxl345_core_remove(&spi->dev);
-}
-
static const struct spi_device_id adxl345_spi_id[] = {
{ "adxl345", ADXL345 },
{ "adxl375", ADXL375 },
@@ -69,7 +64,6 @@ static struct spi_driver adxl345_spi_driver = {
.of_match_table = adxl345_of_match,
},
.probe = adxl345_spi_probe,
- .remove = adxl345_spi_remove,
.id_table = adxl345_spi_id,
};
diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c
index 0622c7936499..bc4c626e454d 100644
--- a/drivers/iio/accel/bma220_spi.c
+++ b/drivers/iio/accel/bma220_spi.c
@@ -218,20 +218,33 @@ static int bma220_init(struct spi_device *spi)
return 0;
}
-static int bma220_deinit(struct spi_device *spi)
+static int bma220_power(struct spi_device *spi, bool up)
{
- int ret;
-
- /* Make sure the chip is powered off */
- ret = bma220_read_reg(spi, BMA220_REG_SUSPEND);
- if (ret == BMA220_SUSPEND_SLEEP)
+ int i, ret;
+
+ /**
+ * The chip can be suspended/woken up by a simple register read.
+ * So, we need up to 2 register reads of the suspend register
+ * to make sure that the device is in the desired state.
+ */
+ for (i = 0; i < 2; i++) {
ret = bma220_read_reg(spi, BMA220_REG_SUSPEND);
- if (ret < 0)
- return ret;
- if (ret == BMA220_SUSPEND_SLEEP)
- return -EBUSY;
+ if (ret < 0)
+ return ret;
- return 0;
+ if (up && ret == BMA220_SUSPEND_SLEEP)
+ return 0;
+
+ if (!up && ret == BMA220_SUSPEND_WAKE)
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+static void bma220_deinit(void *spi)
+{
+ bma220_power(spi, false);
}
static int bma220_probe(struct spi_device *spi)
@@ -248,7 +261,6 @@ static int bma220_probe(struct spi_device *spi)
data = iio_priv(indio_dev);
data->spi_device = spi;
- spi_set_drvdata(spi, indio_dev);
mutex_init(&data->lock);
indio_dev->info = &bma220_info;
@@ -262,49 +274,33 @@ static int bma220_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time,
- bma220_trigger_handler, NULL);
- if (ret < 0) {
- dev_err(&spi->dev, "iio triggered buffer setup failed\n");
- goto err_suspend;
- }
+ ret = devm_add_action_or_reset(&spi->dev, bma220_deinit, spi);
+ if (ret)
+ return ret;
- ret = iio_device_register(indio_dev);
+ ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+ iio_pollfunc_store_time,
+ bma220_trigger_handler, NULL);
if (ret < 0) {
- dev_err(&spi->dev, "iio_device_register failed\n");
- iio_triggered_buffer_cleanup(indio_dev);
- goto err_suspend;
+ dev_err(&spi->dev, "iio triggered buffer setup failed\n");
+ return ret;
}
- return 0;
-
-err_suspend:
- return bma220_deinit(spi);
-}
-
-static int bma220_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
-
- iio_device_unregister(indio_dev);
- iio_triggered_buffer_cleanup(indio_dev);
-
- return bma220_deinit(spi);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static __maybe_unused int bma220_suspend(struct device *dev)
{
- struct bma220_data *data = iio_priv(dev_get_drvdata(dev));
+ struct spi_device *spi = to_spi_device(dev);
- /* The chip can be suspended/woken up by a simple register read. */
- return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND);
+ return bma220_power(spi, false);
}
static __maybe_unused int bma220_resume(struct device *dev)
{
- struct bma220_data *data = iio_priv(dev_get_drvdata(dev));
+ struct spi_device *spi = to_spi_device(dev);
- return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND);
+ return bma220_power(spi, true);
}
static SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume);
@@ -326,7 +322,6 @@ static struct spi_driver bma220_driver = {
.acpi_match_table = bma220_acpi_id,
},
.probe = bma220_probe,
- .remove = bma220_remove,
.id_table = bma220_spi_id,
};
module_spi_driver(bma220_driver);
diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 5ce384ebe6c7..e8693a42ad46 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -10,6 +10,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/acpi.h>
+#include <linux/of_irq.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -57,12 +58,18 @@
#define BMC150_ACCEL_RESET_VAL 0xB6
#define BMC150_ACCEL_REG_INT_MAP_0 0x19
-#define BMC150_ACCEL_INT_MAP_0_BIT_SLOPE BIT(2)
+#define BMC150_ACCEL_INT_MAP_0_BIT_INT1_SLOPE BIT(2)
#define BMC150_ACCEL_REG_INT_MAP_1 0x1A
-#define BMC150_ACCEL_INT_MAP_1_BIT_DATA BIT(0)
-#define BMC150_ACCEL_INT_MAP_1_BIT_FWM BIT(1)
-#define BMC150_ACCEL_INT_MAP_1_BIT_FFULL BIT(2)
+#define BMC150_ACCEL_INT_MAP_1_BIT_INT1_DATA BIT(0)
+#define BMC150_ACCEL_INT_MAP_1_BIT_INT1_FWM BIT(1)
+#define BMC150_ACCEL_INT_MAP_1_BIT_INT1_FFULL BIT(2)
+#define BMC150_ACCEL_INT_MAP_1_BIT_INT2_FFULL BIT(5)
+#define BMC150_ACCEL_INT_MAP_1_BIT_INT2_FWM BIT(6)
+#define BMC150_ACCEL_INT_MAP_1_BIT_INT2_DATA BIT(7)
+
+#define BMC150_ACCEL_REG_INT_MAP_2 0x1B
+#define BMC150_ACCEL_INT_MAP_2_BIT_INT2_SLOPE BIT(2)
#define BMC150_ACCEL_REG_INT_RST_LATCH 0x21
#define BMC150_ACCEL_INT_MODE_LATCH_RESET 0x80
@@ -81,6 +88,7 @@
#define BMC150_ACCEL_REG_INT_OUT_CTRL 0x20
#define BMC150_ACCEL_INT_OUT_CTRL_INT1_LVL BIT(0)
+#define BMC150_ACCEL_INT_OUT_CTRL_INT2_LVL BIT(2)
#define BMC150_ACCEL_REG_INT_5 0x27
#define BMC150_ACCEL_SLOPE_DUR_MASK 0x03
@@ -476,21 +484,24 @@ static bool bmc150_apply_acpi_orientation(struct device *dev,
}
#endif
-static const struct bmc150_accel_interrupt_info {
+struct bmc150_accel_interrupt_info {
u8 map_reg;
u8 map_bitmask;
u8 en_reg;
u8 en_bitmask;
-} bmc150_accel_interrupts[BMC150_ACCEL_INTERRUPTS] = {
+};
+
+static const struct bmc150_accel_interrupt_info
+bmc150_accel_interrupts_int1[BMC150_ACCEL_INTERRUPTS] = {
{ /* data ready interrupt */
.map_reg = BMC150_ACCEL_REG_INT_MAP_1,
- .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_DATA,
+ .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_INT1_DATA,
.en_reg = BMC150_ACCEL_REG_INT_EN_1,
.en_bitmask = BMC150_ACCEL_INT_EN_BIT_DATA_EN,
},
{ /* motion interrupt */
.map_reg = BMC150_ACCEL_REG_INT_MAP_0,
- .map_bitmask = BMC150_ACCEL_INT_MAP_0_BIT_SLOPE,
+ .map_bitmask = BMC150_ACCEL_INT_MAP_0_BIT_INT1_SLOPE,
.en_reg = BMC150_ACCEL_REG_INT_EN_0,
.en_bitmask = BMC150_ACCEL_INT_EN_BIT_SLP_X |
BMC150_ACCEL_INT_EN_BIT_SLP_Y |
@@ -498,19 +509,56 @@ static const struct bmc150_accel_interrupt_info {
},
{ /* fifo watermark interrupt */
.map_reg = BMC150_ACCEL_REG_INT_MAP_1,
- .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_FWM,
+ .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_INT1_FWM,
+ .en_reg = BMC150_ACCEL_REG_INT_EN_1,
+ .en_bitmask = BMC150_ACCEL_INT_EN_BIT_FWM_EN,
+ },
+};
+
+static const struct bmc150_accel_interrupt_info
+bmc150_accel_interrupts_int2[BMC150_ACCEL_INTERRUPTS] = {
+ { /* data ready interrupt */
+ .map_reg = BMC150_ACCEL_REG_INT_MAP_1,
+ .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_INT2_DATA,
+ .en_reg = BMC150_ACCEL_REG_INT_EN_1,
+ .en_bitmask = BMC150_ACCEL_INT_EN_BIT_DATA_EN,
+ },
+ { /* motion interrupt */
+ .map_reg = BMC150_ACCEL_REG_INT_MAP_2,
+ .map_bitmask = BMC150_ACCEL_INT_MAP_2_BIT_INT2_SLOPE,
+ .en_reg = BMC150_ACCEL_REG_INT_EN_0,
+ .en_bitmask = BMC150_ACCEL_INT_EN_BIT_SLP_X |
+ BMC150_ACCEL_INT_EN_BIT_SLP_Y |
+ BMC150_ACCEL_INT_EN_BIT_SLP_Z
+ },
+ { /* fifo watermark interrupt */
+ .map_reg = BMC150_ACCEL_REG_INT_MAP_1,
+ .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_INT2_FWM,
.en_reg = BMC150_ACCEL_REG_INT_EN_1,
.en_bitmask = BMC150_ACCEL_INT_EN_BIT_FWM_EN,
},
};
static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev,
- struct bmc150_accel_data *data)
+ struct bmc150_accel_data *data, int irq)
{
+ const struct bmc150_accel_interrupt_info *irq_info = NULL;
+ struct device *dev = regmap_get_device(data->regmap);
int i;
+ /*
+ * For now we map all interrupts to the same output pin.
+ * However, some boards may have just INT2 (and not INT1) connected,
+ * so we try to detect which IRQ it is based on the interrupt-names.
+ * Without interrupt-names, we assume the irq belongs to INT1.
+ */
+ irq_info = bmc150_accel_interrupts_int1;
+ if (data->type == BOSCH_BMC156 ||
+ irq == of_irq_get_byname(dev->of_node, "INT2"))
+ irq_info = bmc150_accel_interrupts_int2;
+
for (i = 0; i < BMC150_ACCEL_INTERRUPTS; i++)
- data->interrupts[i].info = &bmc150_accel_interrupts[i];
+ data->interrupts[i].info = &irq_info[i];
}
static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
@@ -1127,7 +1175,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
{306458, BMC150_ACCEL_DEF_RANGE_16G} },
},
{
- .name = "BMA253/BMA254/BMA255/BMC150/BMI055",
+ .name = "BMA253/BMA254/BMA255/BMC150/BMC156/BMI055",
.chip_id = 0xFA,
.channels = bmc150_accel_channels,
.num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1614,7 +1662,8 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
}
int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
- const char *name, bool block_supported)
+ enum bmc150_type type, const char *name,
+ bool block_supported)
{
const struct attribute **fifo_attrs;
struct bmc150_accel_data *data;
@@ -1629,6 +1678,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
dev_set_drvdata(dev, indio_dev);
data->regmap = regmap;
+ data->type = type;
if (!bmc150_apply_acpi_orientation(dev, &data->orientation)) {
ret = iio_read_mount_matrix(dev, &data->orientation);
@@ -1714,7 +1764,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
goto err_buffer_cleanup;
}
- bmc150_accel_interrupts_setup(indio_dev, data);
+ bmc150_accel_interrupts_setup(indio_dev, data, irq);
ret = bmc150_accel_triggers_setup(indio_dev, data);
if (ret)
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
index 999495f0669d..88bd8a25f142 100644
--- a/drivers/iio/accel/bmc150-accel-i2c.c
+++ b/drivers/iio/accel/bmc150-accel-i2c.c
@@ -176,6 +176,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
{
struct regmap *regmap;
const char *name = NULL;
+ enum bmc150_type type = BOSCH_UNKNOWN;
bool block_supported =
i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
i2c_check_functionality(client->adapter,
@@ -188,10 +189,13 @@ static int bmc150_accel_probe(struct i2c_client *client,
return PTR_ERR(regmap);
}
- if (id)
+ if (id) {
name = id->name;
+ type = id->driver_data;
+ }
- ret = bmc150_accel_core_probe(&client->dev, regmap, client->irq, name, block_supported);
+ ret = bmc150_accel_core_probe(&client->dev, regmap, client->irq,
+ type, name, block_supported);
if (ret)
return ret;
@@ -236,6 +240,7 @@ static const struct i2c_device_id bmc150_accel_id[] = {
{"bma255"},
{"bma280"},
{"bmc150_accel"},
+ {"bmc156_accel", BOSCH_BMC156},
{"bmi055_accel"},
{}
};
@@ -251,6 +256,7 @@ static const struct of_device_id bmc150_accel_of_match[] = {
{ .compatible = "bosch,bma255" },
{ .compatible = "bosch,bma280" },
{ .compatible = "bosch,bmc150_accel" },
+ { .compatible = "bosch,bmc156_accel" },
{ .compatible = "bosch,bmi055_accel" },
{ },
};
diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c
index 54b8c9c8068b..191e312dc91a 100644
--- a/drivers/iio/accel/bmc150-accel-spi.c
+++ b/drivers/iio/accel/bmc150-accel-spi.c
@@ -16,6 +16,8 @@
static int bmc150_accel_probe(struct spi_device *spi)
{
struct regmap *regmap;
+ const char *name = NULL;
+ enum bmc150_type type = BOSCH_UNKNOWN;
const struct spi_device_id *id = spi_get_device_id(spi);
regmap = devm_regmap_init_spi(spi, &bmc150_regmap_conf);
@@ -24,7 +26,12 @@ static int bmc150_accel_probe(struct spi_device *spi)
return PTR_ERR(regmap);
}
- return bmc150_accel_core_probe(&spi->dev, regmap, spi->irq, id->name,
+ if (id) {
+ name = id->name;
+ type = id->driver_data;
+ }
+
+ return bmc150_accel_core_probe(&spi->dev, regmap, spi->irq, type, name,
true);
}
@@ -54,6 +61,7 @@ static const struct spi_device_id bmc150_accel_id[] = {
{"bma255"},
{"bma280"},
{"bmc150_accel"},
+ {"bmc156_accel", BOSCH_BMC156},
{"bmi055_accel"},
{}
};
diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h
index 47121f070fe9..1bb5023e8ed9 100644
--- a/drivers/iio/accel/bmc150-accel.h
+++ b/drivers/iio/accel/bmc150-accel.h
@@ -13,6 +13,22 @@ struct i2c_client;
struct bmc150_accel_chip_info;
struct bmc150_accel_interrupt_info;
+/*
+ * We can often guess better than "UNKNOWN" based on the device IDs
+ * but unfortunately this information is not always accurate. There are some
+ * devices where ACPI firmware specifies an ID like "BMA250E" when the device
+ * actually has a BMA222E. The driver attempts to detect those by reading the
+ * chip ID from the registers but this information is not always enough either.
+ *
+ * Therefore, this enum should be only used when the chip ID detection is not
+ * enough and we can be reasonably sure that the device IDs are reliable
+ * in practice (e.g. for device tree platforms).
+ */
+enum bmc150_type {
+ BOSCH_UNKNOWN,
+ BOSCH_BMC156,
+};
+
struct bmc150_accel_interrupt {
const struct bmc150_accel_interrupt_info *info;
atomic_t users;
@@ -62,6 +78,7 @@ struct bmc150_accel_data {
int ev_enable_state;
int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
const struct bmc150_accel_chip_info *chip_info;
+ enum bmc150_type type;
struct i2c_client *second_device;
void (*resume_callback)(struct device *dev);
struct delayed_work resume_work;
@@ -69,7 +86,8 @@ struct bmc150_accel_data {
};
int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
- const char *name, bool block_supported);
+ enum bmc150_type type, const char *name,
+ bool block_supported);
int bmc150_accel_core_remove(struct device *dev);
extern const struct dev_pm_ops bmc150_accel_pm_ops;
extern const struct regmap_config bmc150_regmap_conf;
diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c
index 5edff9ba72da..9633bdae5fd4 100644
--- a/drivers/iio/accel/da280.c
+++ b/drivers/iio/accel/da280.c
@@ -100,6 +100,11 @@ static enum da280_chipset da280_match_acpi_device(struct device *dev)
return (enum da280_chipset) id->driver_data;
}
+static void da280_disable(void *client)
+{
+ da280_enable(client, false);
+}
+
static int da280_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -118,7 +123,6 @@ static int da280_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
data->client = client;
- i2c_set_clientdata(client, indio_dev);
indio_dev->info = &da280_info;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -142,22 +146,11 @@ static int da280_probe(struct i2c_client *client,
if (ret < 0)
return ret;
- ret = iio_device_register(indio_dev);
- if (ret < 0) {
- dev_err(&client->dev, "device_register failed\n");
- da280_enable(client, false);
- }
-
- return ret;
-}
-
-static int da280_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
- iio_device_unregister(indio_dev);
+ ret = devm_add_action_or_reset(&client->dev, da280_disable, client);
+ if (ret)
+ return ret;
- return da280_enable(client, false);
+ return devm_iio_device_register(&client->dev, indio_dev);
}
#ifdef CONFIG_PM_SLEEP
@@ -194,7 +187,6 @@ static struct i2c_driver da280_driver = {
.pm = &da280_pm_ops,
},
.probe = da280_probe,
- .remove = da280_remove,
.id_table = da280_i2c_id,
};
diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c
index 92593a1cd1aa..04e13487e706 100644
--- a/drivers/iio/accel/da311.c
+++ b/drivers/iio/accel/da311.c
@@ -212,6 +212,11 @@ static const struct iio_info da311_info = {
.read_raw = da311_read_raw,
};
+static void da311_disable(void *client)
+{
+ da311_enable(client, false);
+}
+
static int da311_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -229,7 +234,6 @@ static int da311_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
data->client = client;
- i2c_set_clientdata(client, indio_dev);
indio_dev->info = &da311_info;
indio_dev->name = "da311";
@@ -245,22 +249,11 @@ static int da311_probe(struct i2c_client *client,
if (ret < 0)
return ret;
- ret = iio_device_register(indio_dev);
- if (ret < 0) {
- dev_err(&client->dev, "device_register failed\n");
- da311_enable(client, false);
- }
-
- return ret;
-}
-
-static int da311_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
- iio_device_unregister(indio_dev);
+ ret = devm_add_action_or_reset(&client->dev, da311_disable, client);
+ if (ret)
+ return ret;
- return da311_enable(client, false);
+ return devm_iio_device_register(&client->dev, indio_dev);
}
#ifdef CONFIG_PM_SLEEP
@@ -289,7 +282,6 @@ static struct i2c_driver da311_driver = {
.pm = &da311_pm_ops,
},
.probe = da311_probe,
- .remove = da311_remove,
.id_table = da311_i2c_id,
};
diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c
index e84bf8db1e89..f9f173eec202 100644
--- a/drivers/iio/accel/dmard10.c
+++ b/drivers/iio/accel/dmard10.c
@@ -170,6 +170,11 @@ static const struct iio_info dmard10_info = {
.read_raw = dmard10_read_raw,
};
+static void dmard10_shutdown_cleanup(void *client)
+{
+ dmard10_shutdown(client);
+}
+
static int dmard10_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -194,7 +199,6 @@ static int dmard10_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
data->client = client;
- i2c_set_clientdata(client, indio_dev);
indio_dev->info = &dmard10_info;
indio_dev->name = "dmard10";
@@ -206,22 +210,12 @@ static int dmard10_probe(struct i2c_client *client,
if (ret < 0)
return ret;
- ret = iio_device_register(indio_dev);
- if (ret < 0) {
- dev_err(&client->dev, "device_register failed\n");
- dmard10_shutdown(client);
- }
-
- return ret;
-}
-
-static int dmard10_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
- iio_device_unregister(indio_dev);
+ ret = devm_add_action_or_reset(&client->dev, dmard10_shutdown_cleanup,
+ client);
+ if (ret)
+ return ret;
- return dmard10_shutdown(client);
+ return devm_iio_device_register(&client->dev, indio_dev);
}
#ifdef CONFIG_PM_SLEEP
@@ -250,7 +244,6 @@ static struct i2c_driver dmard10_driver = {
.pm = &dmard10_pm_ops,
},
.probe = dmard10_probe,
- .remove = dmard10_remove,
.id_table = dmard10_i2c_id,
};
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 55cdca818b3b..a2def6f9380a 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -367,7 +367,8 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to setup common attributes\n");
return ret;
}
- indio_dev->channels = kmemdup(channel_spec, channel_size, GFP_KERNEL);
+ indio_dev->channels = devm_kmemdup(&pdev->dev, channel_spec,
+ channel_size, GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
@@ -378,7 +379,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
hsdev->usage, accel_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
- goto error_free_dev_mem;
+ return ret;
}
indio_dev->info = &accel_3d_info;
@@ -391,7 +392,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
&accel_state->common_attributes);
if (ret < 0) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_free_dev_mem;
+ return ret;
}
ret = iio_device_register(indio_dev);
@@ -416,8 +417,6 @@ error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
-error_free_dev_mem:
- kfree(indio_dev->channels);
return ret;
}
@@ -431,7 +430,6 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
- kfree(indio_dev->channels);
return 0;
}
diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
index f5b0b8bbaff7..8750dea56fcb 100644
--- a/drivers/iio/accel/st_accel.h
+++ b/drivers/iio/accel/st_accel.h
@@ -64,7 +64,6 @@ enum st_accel_type {
#ifdef CONFIG_IIO_BUFFER
int st_accel_allocate_ring(struct iio_dev *indio_dev);
-void st_accel_deallocate_ring(struct iio_dev *indio_dev);
int st_accel_trig_set_state(struct iio_trigger *trig, bool state);
#define ST_ACCEL_TRIGGER_SET_STATE (&st_accel_trig_set_state)
#else /* CONFIG_IIO_BUFFER */
@@ -72,9 +71,6 @@ static inline int st_accel_allocate_ring(struct iio_dev *indio_dev)
{
return 0;
}
-static inline void st_accel_deallocate_ring(struct iio_dev *indio_dev)
-{
-}
#define ST_ACCEL_TRIGGER_SET_STATE NULL
#endif /* CONFIG_IIO_BUFFER */
diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c
index 492263589e04..fc82fa83f1fb 100644
--- a/drivers/iio/accel/st_accel_buffer.c
+++ b/drivers/iio/accel/st_accel_buffer.c
@@ -9,14 +9,9 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/common/st_sensors.h>
@@ -67,13 +62,8 @@ static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = {
int st_accel_allocate_ring(struct iio_dev *indio_dev)
{
- return iio_triggered_buffer_setup(indio_dev, NULL,
- &st_sensors_trigger_handler, &st_accel_buffer_setup_ops);
-}
-
-void st_accel_deallocate_ring(struct iio_dev *indio_dev)
-{
- iio_triggered_buffer_cleanup(indio_dev);
+ return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
+ NULL, &st_sensors_trigger_handler, &st_accel_buffer_setup_ops);
}
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 28fceac9f2f6..f1e6ec380667 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -9,17 +9,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/acpi.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/irq.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
-#include <linux/iio/buffer.h>
#include <linux/iio/common/st_sensors.h>
#include "st_accel.h"
@@ -1381,7 +1377,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
err = st_sensors_allocate_trigger(indio_dev,
ST_ACCEL_TRIGGER_OPS);
if (err < 0)
- goto st_accel_probe_trigger_error;
+ return err;
}
err = iio_device_register(indio_dev);
@@ -1396,8 +1392,6 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
st_accel_device_register_error:
if (adata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
-st_accel_probe_trigger_error:
- st_accel_deallocate_ring(indio_dev);
return err;
}
EXPORT_SYMBOL(st_accel_common_probe);
@@ -1409,8 +1403,6 @@ void st_accel_common_remove(struct iio_dev *indio_dev)
iio_device_unregister(indio_dev);
if (adata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
-
- st_accel_deallocate_ring(indio_dev);
}
EXPORT_SYMBOL(st_accel_common_remove);
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index 95e305b88d5e..f711756e41e3 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -9,11 +9,10 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
-#include <linux/property.h>
#include <linux/iio/common/st_sensors_i2c.h>
#include "st_accel.h"
diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
index 83d3308ce5cc..bb45d9ff95b8 100644
--- a/drivers/iio/accel/st_accel_spi.c
+++ b/drivers/iio/accel/st_accel_spi.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index db0c8fb60515..af168e1c9fdb 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -887,6 +887,16 @@ config ROCKCHIP_SARADC
To compile this driver as a module, choose M here: the
module will be called rockchip_saradc.
+config RZG2L_ADC
+ tristate "Renesas RZ/G2L ADC driver"
+ depends on ARCH_R9A07G044 || COMPILE_TEST
+ help
+ Say yes here to build support for the ADC found in Renesas
+ RZ/G2L family.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rzg2l_adc.
+
config SC27XX_ADC
tristate "Spreadtrum SC27xx series PMICs ADC"
depends on MFD_SC27XX_PMIC || COMPILE_TEST
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index f70d877c555a..d68550f493e3 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o
obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o
obj-$(CONFIG_RN5T618_ADC) += rn5t618-adc.o
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
+obj-$(CONFIG_RZG2L_ADC) += rzg2l_adc.o
obj-$(CONFIG_SC27XX_ADC) += sc27xx_adc.o
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
obj-$(CONFIG_STX104) += stx104.o
diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c
index a10a4e8d94fd..8edd6407b7c3 100644
--- a/drivers/iio/adc/ep93xx_adc.c
+++ b/drivers/iio/adc/ep93xx_adc.c
@@ -205,7 +205,7 @@ static int ep93xx_adc_probe(struct platform_device *pdev)
*/
}
- ret = clk_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(&pdev->dev, "Cannot enable clock\n");
return ret;
@@ -213,7 +213,7 @@ static int ep93xx_adc_probe(struct platform_device *pdev)
ret = iio_device_register(iiodev);
if (ret)
- clk_disable(priv->clk);
+ clk_disable_unprepare(priv->clk);
return ret;
}
@@ -224,7 +224,7 @@ static int ep93xx_adc_remove(struct platform_device *pdev)
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
iio_device_unregister(iiodev);
- clk_disable(priv->clk);
+ clk_disable_unprepare(priv->clk);
return 0;
}
diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c
index ab5139e911c3..329c555b55cc 100644
--- a/drivers/iio/adc/fsl-imx25-gcq.c
+++ b/drivers/iio/adc/fsl-imx25-gcq.c
@@ -201,11 +201,11 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
*/
priv->vref[MX25_ADC_REFP_INT] = NULL;
priv->vref[MX25_ADC_REFP_EXT] =
- devm_regulator_get_optional(&pdev->dev, "vref-ext");
+ devm_regulator_get_optional(dev, "vref-ext");
priv->vref[MX25_ADC_REFP_XP] =
- devm_regulator_get_optional(&pdev->dev, "vref-xp");
+ devm_regulator_get_optional(dev, "vref-xp");
priv->vref[MX25_ADC_REFP_YP] =
- devm_regulator_get_optional(&pdev->dev, "vref-yp");
+ devm_regulator_get_optional(dev, "vref-yp");
for_each_child_of_node(np, child) {
u32 reg;
@@ -307,7 +307,7 @@ static int mx25_gcq_probe(struct platform_device *pdev)
int ret;
int i;
- indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
if (!indio_dev)
return -ENOMEM;
@@ -347,14 +347,11 @@ static int mx25_gcq_probe(struct platform_device *pdev)
goto err_vref_disable;
}
- priv->irq = platform_get_irq(pdev, 0);
- if (priv->irq <= 0) {
- ret = priv->irq;
- if (!ret)
- ret = -ENXIO;
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
goto err_clk_unprepare;
- }
+ priv->irq = ret;
ret = request_irq(priv->irq, mx25_gcq_irq, 0, pdev->name, priv);
if (ret) {
dev_err(dev, "Failed requesting IRQ\n");
diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
index 34c03a264f74..2b3912c6ca6b 100644
--- a/drivers/iio/adc/ingenic-adc.c
+++ b/drivers/iio/adc/ingenic-adc.c
@@ -37,6 +37,7 @@
#define JZ_ADC_REG_CFG_SAMPLE_NUM(n) ((n) << 10)
#define JZ_ADC_REG_CFG_PULL_UP(n) ((n) << 16)
#define JZ_ADC_REG_CFG_CMD_SEL BIT(22)
+#define JZ_ADC_REG_CFG_VBAT_SEL BIT(30)
#define JZ_ADC_REG_CFG_TOUCH_OPS_MASK (BIT(31) | GENMASK(23, 10))
#define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0
#define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB 16
@@ -71,6 +72,7 @@
#define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS 10
#define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986)
#define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12
+#define JZ4760_ADC_BATTERY_VREF 2500
#define JZ4770_ADC_BATTERY_VREF 1200
#define JZ4770_ADC_BATTERY_VREF_BITS 12
@@ -92,7 +94,7 @@ struct ingenic_adc_soc_data {
const int *battery_scale_avail;
size_t battery_scale_avail_size;
unsigned int battery_vref_mode: 1;
- unsigned int has_aux2: 1;
+ unsigned int has_aux_md: 1;
const struct iio_chan_spec *channels;
unsigned int num_channels;
int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
@@ -295,6 +297,10 @@ static const int jz4740_adc_battery_scale_avail[] = {
JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
};
+static const int jz4760_adc_battery_scale_avail[] = {
+ JZ4760_ADC_BATTERY_VREF, JZ4770_ADC_BATTERY_VREF_BITS,
+};
+
static const int jz4770_adc_battery_raw_avail[] = {
0, 1, (1 << JZ4770_ADC_BATTERY_VREF_BITS) - 1,
};
@@ -400,6 +406,47 @@ static const struct iio_chan_spec jz4740_channels[] = {
},
};
+static const struct iio_chan_spec jz4760_channels[] = {
+ {
+ .extend_name = "aux",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_AUX0,
+ .scan_index = -1,
+ },
+ {
+ .extend_name = "aux1",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_AUX,
+ .scan_index = -1,
+ },
+ {
+ .extend_name = "aux2",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_AUX2,
+ .scan_index = -1,
+ },
+ {
+ .extend_name = "battery",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_BATTERY,
+ .scan_index = -1,
+ },
+};
+
static const struct iio_chan_spec jz4770_channels[] = {
{
.type = IIO_VOLTAGE,
@@ -506,7 +553,7 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
.battery_scale_avail = jz4725b_adc_battery_scale_avail,
.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
.battery_vref_mode = true,
- .has_aux2 = false,
+ .has_aux_md = false,
.channels = jz4740_channels,
.num_channels = ARRAY_SIZE(jz4740_channels),
.init_clk_div = jz4725b_adc_init_clk_div,
@@ -520,12 +567,26 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
.battery_scale_avail = jz4740_adc_battery_scale_avail,
.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
.battery_vref_mode = true,
- .has_aux2 = false,
+ .has_aux_md = false,
.channels = jz4740_channels,
.num_channels = ARRAY_SIZE(jz4740_channels),
.init_clk_div = NULL, /* no ADCLK register on JZ4740 */
};
+static const struct ingenic_adc_soc_data jz4760_adc_soc_data = {
+ .battery_high_vref = JZ4760_ADC_BATTERY_VREF,
+ .battery_high_vref_bits = JZ4770_ADC_BATTERY_VREF_BITS,
+ .battery_raw_avail = jz4770_adc_battery_raw_avail,
+ .battery_raw_avail_size = ARRAY_SIZE(jz4770_adc_battery_raw_avail),
+ .battery_scale_avail = jz4760_adc_battery_scale_avail,
+ .battery_scale_avail_size = ARRAY_SIZE(jz4760_adc_battery_scale_avail),
+ .battery_vref_mode = false,
+ .has_aux_md = true,
+ .channels = jz4760_channels,
+ .num_channels = ARRAY_SIZE(jz4760_channels),
+ .init_clk_div = jz4770_adc_init_clk_div,
+};
+
static const struct ingenic_adc_soc_data jz4770_adc_soc_data = {
.battery_high_vref = JZ4770_ADC_BATTERY_VREF,
.battery_high_vref_bits = JZ4770_ADC_BATTERY_VREF_BITS,
@@ -534,7 +595,7 @@ static const struct ingenic_adc_soc_data jz4770_adc_soc_data = {
.battery_scale_avail = jz4770_adc_battery_scale_avail,
.battery_scale_avail_size = ARRAY_SIZE(jz4770_adc_battery_scale_avail),
.battery_vref_mode = false,
- .has_aux2 = true,
+ .has_aux_md = true,
.channels = jz4770_channels,
.num_channels = ARRAY_SIZE(jz4770_channels),
.init_clk_div = jz4770_adc_init_clk_div,
@@ -569,7 +630,7 @@ static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
struct iio_chan_spec const *chan,
int *val)
{
- int bit, ret, engine = (chan->channel == INGENIC_ADC_BATTERY);
+ int cmd, ret, engine = (chan->channel == INGENIC_ADC_BATTERY);
struct ingenic_adc *adc = iio_priv(iio_dev);
ret = clk_enable(adc->clk);
@@ -579,11 +640,22 @@ static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
return ret;
}
- /* We cannot sample AUX/AUX2 in parallel. */
+ /* We cannot sample the aux channels in parallel. */
mutex_lock(&adc->aux_lock);
- if (adc->soc_data->has_aux2 && engine == 0) {
- bit = BIT(chan->channel == INGENIC_ADC_AUX2);
- ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit);
+ if (adc->soc_data->has_aux_md && engine == 0) {
+ switch (chan->channel) {
+ case INGENIC_ADC_AUX0:
+ cmd = 0;
+ break;
+ case INGENIC_ADC_AUX:
+ cmd = 1;
+ break;
+ case INGENIC_ADC_AUX2:
+ cmd = 2;
+ break;
+ }
+
+ ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, cmd);
}
ret = ingenic_adc_capture(adc, engine);
@@ -591,6 +663,7 @@ static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
goto out;
switch (chan->channel) {
+ case INGENIC_ADC_AUX0:
case INGENIC_ADC_AUX:
case INGENIC_ADC_AUX2:
*val = readw(adc->base + JZ_ADC_REG_ADSDAT);
@@ -621,6 +694,7 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
return ingenic_adc_read_chan_info_raw(iio_dev, chan, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->channel) {
+ case INGENIC_ADC_AUX0:
case INGENIC_ADC_AUX:
case INGENIC_ADC_AUX2:
*val = JZ_ADC_AUX_VREF;
@@ -806,6 +880,14 @@ static int ingenic_adc_probe(struct platform_device *pdev)
/* Put hardware in a known passive state. */
writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
+
+ /* JZ4760B specific */
+ if (device_property_present(dev, "ingenic,use-internal-divider"))
+ ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_VBAT_SEL,
+ JZ_ADC_REG_CFG_VBAT_SEL);
+ else
+ ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_VBAT_SEL, 0);
+
usleep_range(2000, 3000); /* Must wait at least 2ms. */
clk_disable(adc->clk);
@@ -832,6 +914,8 @@ static int ingenic_adc_probe(struct platform_device *pdev)
static const struct of_device_id ingenic_adc_of_match[] = {
{ .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
{ .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
+ { .compatible = "ingenic,jz4760-adc", .data = &jz4760_adc_soc_data, },
+ { .compatible = "ingenic,jz4760b-adc", .data = &jz4760_adc_soc_data, },
{ .compatible = "ingenic,jz4770-adc", .data = &jz4770_adc_soc_data, },
{ },
};
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 66dc452d643a..705d5e11a54b 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -347,7 +347,7 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int regval, fifo_chan, fifo_val, count;
- if(!wait_for_completion_timeout(&priv->done,
+ if (!wait_for_completion_timeout(&priv->done,
msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
return -ETIMEDOUT;
@@ -497,8 +497,8 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev)
if (priv->param->has_bl30_integration) {
/* prevent BL30 from using the SAR ADC while we are using it */
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
- MESON_SAR_ADC_DELAY_KERNEL_BUSY,
- MESON_SAR_ADC_DELAY_KERNEL_BUSY);
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY,
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY);
/*
* wait until BL30 releases it's lock (so we can use the SAR
@@ -525,7 +525,7 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
if (priv->param->has_bl30_integration)
/* allow BL30 to use the SAR ADC again */
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
- MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
mutex_unlock(&indio_dev->mlock);
}
@@ -791,7 +791,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
* on the vendor driver), which we don't support at the moment.
*/
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
- MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0);
+ MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0);
/* disable all channels by default */
regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0);
@@ -1104,6 +1104,14 @@ static const struct meson_sar_adc_param meson_sar_adc_gxl_param = {
.resolution = 12,
};
+static const struct meson_sar_adc_param meson_sar_adc_g12a_param = {
+ .has_bl30_integration = false,
+ .clock_rate = 1200000,
+ .bandgap_reg = MESON_SAR_ADC_REG11,
+ .regmap_config = &meson_sar_adc_regmap_config_gxbb,
+ .resolution = 12,
+};
+
static const struct meson_sar_adc_data meson_sar_adc_meson8_data = {
.param = &meson_sar_adc_meson8_param,
.name = "meson-meson8-saradc",
@@ -1140,7 +1148,7 @@ static const struct meson_sar_adc_data meson_sar_adc_axg_data = {
};
static const struct meson_sar_adc_data meson_sar_adc_g12a_data = {
- .param = &meson_sar_adc_gxl_param,
+ .param = &meson_sar_adc_g12a_param,
.name = "meson-g12a-saradc",
};
diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
index 12584f1631d8..a237fe469a30 100644
--- a/drivers/iio/adc/rockchip_saradc.c
+++ b/drivers/iio/adc/rockchip_saradc.c
@@ -35,7 +35,7 @@
#define SARADC_DLY_PU_SOC_MASK 0x3f
#define SARADC_TIMEOUT msecs_to_jiffies(100)
-#define SARADC_MAX_CHANNELS 6
+#define SARADC_MAX_CHANNELS 8
struct rockchip_saradc_data {
const struct iio_chan_spec *channels;
@@ -49,10 +49,12 @@ struct rockchip_saradc {
struct clk *clk;
struct completion completion;
struct regulator *vref;
+ int uv_vref;
struct reset_control *reset;
const struct rockchip_saradc_data *data;
u16 last_val;
const struct iio_chan_spec *last_chan;
+ struct notifier_block nb;
};
static void rockchip_saradc_power_down(struct rockchip_saradc *info)
@@ -105,13 +107,7 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- ret = regulator_get_voltage(info->vref);
- if (ret < 0) {
- dev_err(&indio_dev->dev, "failed to get voltage\n");
- return ret;
- }
-
- *val = ret / 1000;
+ *val = info->uv_vref / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
@@ -192,6 +188,23 @@ static const struct rockchip_saradc_data rk3399_saradc_data = {
.clk_rate = 1000000,
};
+static const struct iio_chan_spec rockchip_rk3568_saradc_iio_channels[] = {
+ SARADC_CHANNEL(0, "adc0", 10),
+ SARADC_CHANNEL(1, "adc1", 10),
+ SARADC_CHANNEL(2, "adc2", 10),
+ SARADC_CHANNEL(3, "adc3", 10),
+ SARADC_CHANNEL(4, "adc4", 10),
+ SARADC_CHANNEL(5, "adc5", 10),
+ SARADC_CHANNEL(6, "adc6", 10),
+ SARADC_CHANNEL(7, "adc7", 10),
+};
+
+static const struct rockchip_saradc_data rk3568_saradc_data = {
+ .channels = rockchip_rk3568_saradc_iio_channels,
+ .num_channels = ARRAY_SIZE(rockchip_rk3568_saradc_iio_channels),
+ .clk_rate = 1000000,
+};
+
static const struct of_device_id rockchip_saradc_match[] = {
{
.compatible = "rockchip,saradc",
@@ -202,6 +215,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
}, {
.compatible = "rockchip,rk3399-saradc",
.data = &rk3399_saradc_data,
+ }, {
+ .compatible = "rockchip,rk3568-saradc",
+ .data = &rk3568_saradc_data,
},
{},
};
@@ -278,6 +294,26 @@ out:
return IRQ_HANDLED;
}
+static int rockchip_saradc_volt_notify(struct notifier_block *nb,
+ unsigned long event,
+ void *data)
+{
+ struct rockchip_saradc *info =
+ container_of(nb, struct rockchip_saradc, nb);
+
+ if (event & REGULATOR_EVENT_VOLTAGE_CHANGE)
+ info->uv_vref = (unsigned long)data;
+
+ return NOTIFY_OK;
+}
+
+static void rockchip_saradc_regulator_unreg_notifier(void *data)
+{
+ struct rockchip_saradc *info = data;
+
+ regulator_unregister_notifier(info->vref, &info->nb);
+}
+
static int rockchip_saradc_probe(struct platform_device *pdev)
{
struct rockchip_saradc *info = NULL;
@@ -390,6 +426,12 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
return ret;
}
+ ret = regulator_get_voltage(info->vref);
+ if (ret < 0)
+ return ret;
+
+ info->uv_vref = ret;
+
ret = clk_prepare_enable(info->pclk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable pclk\n");
@@ -430,6 +472,17 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
if (ret)
return ret;
+ info->nb.notifier_call = rockchip_saradc_volt_notify;
+ ret = regulator_register_notifier(info->vref, &info->nb);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&pdev->dev,
+ rockchip_saradc_regulator_unreg_notifier,
+ info);
+ if (ret)
+ return ret;
+
return devm_iio_device_register(&pdev->dev, indio_dev);
}
diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c
new file mode 100644
index 000000000000..9996d5eef289
--- /dev/null
+++ b/drivers/iio/adc/rzg2l_adc.c
@@ -0,0 +1,600 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G2L A/D Converter driver
+ *
+ * Copyright (c) 2021 Renesas Electronics Europe GmbH
+ *
+ * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#define DRIVER_NAME "rzg2l-adc"
+
+#define RZG2L_ADM(n) ((n) * 0x4)
+#define RZG2L_ADM0_ADCE BIT(0)
+#define RZG2L_ADM0_ADBSY BIT(1)
+#define RZG2L_ADM0_PWDWNB BIT(2)
+#define RZG2L_ADM0_SRESB BIT(15)
+#define RZG2L_ADM1_TRG BIT(0)
+#define RZG2L_ADM1_MS BIT(2)
+#define RZG2L_ADM1_BS BIT(4)
+#define RZG2L_ADM1_EGA_MASK GENMASK(13, 12)
+#define RZG2L_ADM2_CHSEL_MASK GENMASK(7, 0)
+#define RZG2L_ADM3_ADIL_MASK GENMASK(31, 24)
+#define RZG2L_ADM3_ADCMP_MASK GENMASK(23, 16)
+#define RZG2L_ADM3_ADCMP_E FIELD_PREP(RZG2L_ADM3_ADCMP_MASK, 0xe)
+#define RZG2L_ADM3_ADSMP_MASK GENMASK(15, 0)
+
+#define RZG2L_ADINT 0x20
+#define RZG2L_ADINT_INTEN_MASK GENMASK(7, 0)
+#define RZG2L_ADINT_CSEEN BIT(16)
+#define RZG2L_ADINT_INTS BIT(31)
+
+#define RZG2L_ADSTS 0x24
+#define RZG2L_ADSTS_CSEST BIT(16)
+#define RZG2L_ADSTS_INTST_MASK GENMASK(7, 0)
+
+#define RZG2L_ADIVC 0x28
+#define RZG2L_ADIVC_DIVADC_MASK GENMASK(8, 0)
+#define RZG2L_ADIVC_DIVADC_4 FIELD_PREP(RZG2L_ADIVC_DIVADC_MASK, 0x4)
+
+#define RZG2L_ADFIL 0x2c
+
+#define RZG2L_ADCR(n) (0x30 + ((n) * 0x4))
+#define RZG2L_ADCR_AD_MASK GENMASK(11, 0)
+
+#define RZG2L_ADSMP_DEFUALT_SAMPLING 0x578
+
+#define RZG2L_ADC_MAX_CHANNELS 8
+#define RZG2L_ADC_CHN_MASK 0x7
+#define RZG2L_ADC_TIMEOUT usecs_to_jiffies(1 * 4)
+
+struct rzg2l_adc_data {
+ const struct iio_chan_spec *channels;
+ u8 num_channels;
+};
+
+struct rzg2l_adc {
+ void __iomem *base;
+ struct clk *pclk;
+ struct clk *adclk;
+ struct reset_control *presetn;
+ struct reset_control *adrstn;
+ struct completion completion;
+ const struct rzg2l_adc_data *data;
+ struct mutex lock;
+ u16 last_val[RZG2L_ADC_MAX_CHANNELS];
+};
+
+static const char * const rzg2l_adc_channel_name[] = {
+ "adc0",
+ "adc1",
+ "adc2",
+ "adc3",
+ "adc4",
+ "adc5",
+ "adc6",
+ "adc7",
+};
+
+static unsigned int rzg2l_adc_readl(struct rzg2l_adc *adc, u32 reg)
+{
+ return readl(adc->base + reg);
+}
+
+static void rzg2l_adc_writel(struct rzg2l_adc *adc, unsigned int reg, u32 val)
+{
+ writel(val, adc->base + reg);
+}
+
+static void rzg2l_adc_pwr(struct rzg2l_adc *adc, bool on)
+{
+ u32 reg;
+
+ reg = rzg2l_adc_readl(adc, RZG2L_ADM(0));
+ if (on)
+ reg |= RZG2L_ADM0_PWDWNB;
+ else
+ reg &= ~RZG2L_ADM0_PWDWNB;
+ rzg2l_adc_writel(adc, RZG2L_ADM(0), reg);
+ udelay(2);
+}
+
+static void rzg2l_adc_start_stop(struct rzg2l_adc *adc, bool start)
+{
+ int timeout = 5;
+ u32 reg;
+
+ reg = rzg2l_adc_readl(adc, RZG2L_ADM(0));
+ if (start)
+ reg |= RZG2L_ADM0_ADCE;
+ else
+ reg &= ~RZG2L_ADM0_ADCE;
+ rzg2l_adc_writel(adc, RZG2L_ADM(0), reg);
+
+ if (start)
+ return;
+
+ do {
+ usleep_range(100, 200);
+ reg = rzg2l_adc_readl(adc, RZG2L_ADM(0));
+ timeout--;
+ if (!timeout) {
+ pr_err("%s stopping ADC timed out\n", __func__);
+ break;
+ }
+ } while (((reg & RZG2L_ADM0_ADBSY) || (reg & RZG2L_ADM0_ADCE)));
+}
+
+static void rzg2l_set_trigger(struct rzg2l_adc *adc)
+{
+ u32 reg;
+
+ /*
+ * Setup ADM1 for SW trigger
+ * EGA[13:12] - Set 00 to indicate hardware trigger is invalid
+ * BS[4] - Enable 1-buffer mode
+ * MS[1] - Enable Select mode
+ * TRG[0] - Enable software trigger mode
+ */
+ reg = rzg2l_adc_readl(adc, RZG2L_ADM(1));
+ reg &= ~RZG2L_ADM1_EGA_MASK;
+ reg &= ~RZG2L_ADM1_BS;
+ reg &= ~RZG2L_ADM1_TRG;
+ reg |= RZG2L_ADM1_MS;
+ rzg2l_adc_writel(adc, RZG2L_ADM(1), reg);
+}
+
+static int rzg2l_adc_conversion_setup(struct rzg2l_adc *adc, u8 ch)
+{
+ u32 reg;
+
+ if (rzg2l_adc_readl(adc, RZG2L_ADM(0)) & RZG2L_ADM0_ADBSY)
+ return -EBUSY;
+
+ rzg2l_set_trigger(adc);
+
+ /* Select analog input channel subjected to conversion. */
+ reg = rzg2l_adc_readl(adc, RZG2L_ADM(2));
+ reg &= ~RZG2L_ADM2_CHSEL_MASK;
+ reg |= BIT(ch);
+ rzg2l_adc_writel(adc, RZG2L_ADM(2), reg);
+
+ /*
+ * Setup ADINT
+ * INTS[31] - Select pulse signal
+ * CSEEN[16] - Enable channel select error interrupt
+ * INTEN[7:0] - Select channel interrupt
+ */
+ reg = rzg2l_adc_readl(adc, RZG2L_ADINT);
+ reg &= ~RZG2L_ADINT_INTS;
+ reg &= ~RZG2L_ADINT_INTEN_MASK;
+ reg |= (RZG2L_ADINT_CSEEN | BIT(ch));
+ rzg2l_adc_writel(adc, RZG2L_ADINT, reg);
+
+ return 0;
+}
+
+static int rzg2l_adc_set_power(struct iio_dev *indio_dev, bool on)
+{
+ struct device *dev = indio_dev->dev.parent;
+
+ if (on)
+ return pm_runtime_resume_and_get(dev);
+
+ return pm_runtime_put_sync(dev);
+}
+
+static int rzg2l_adc_conversion(struct iio_dev *indio_dev, struct rzg2l_adc *adc, u8 ch)
+{
+ int ret;
+
+ ret = rzg2l_adc_set_power(indio_dev, true);
+ if (ret)
+ return ret;
+
+ ret = rzg2l_adc_conversion_setup(adc, ch);
+ if (ret) {
+ rzg2l_adc_set_power(indio_dev, false);
+ return ret;
+ }
+
+ reinit_completion(&adc->completion);
+
+ rzg2l_adc_start_stop(adc, true);
+
+ if (!wait_for_completion_timeout(&adc->completion, RZG2L_ADC_TIMEOUT)) {
+ rzg2l_adc_writel(adc, RZG2L_ADINT,
+ rzg2l_adc_readl(adc, RZG2L_ADINT) & ~RZG2L_ADINT_INTEN_MASK);
+ rzg2l_adc_start_stop(adc, false);
+ rzg2l_adc_set_power(indio_dev, false);
+ return -ETIMEDOUT;
+ }
+
+ return rzg2l_adc_set_power(indio_dev, false);
+}
+
+static int rzg2l_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct rzg2l_adc *adc = iio_priv(indio_dev);
+ int ret;
+ u8 ch;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (chan->type != IIO_VOLTAGE)
+ return -EINVAL;
+
+ mutex_lock(&adc->lock);
+ ch = chan->channel & RZG2L_ADC_CHN_MASK;
+ ret = rzg2l_adc_conversion(indio_dev, adc, ch);
+ if (ret) {
+ mutex_unlock(&adc->lock);
+ return ret;
+ }
+ *val = adc->last_val[ch];
+ mutex_unlock(&adc->lock);
+
+ return IIO_VAL_INT;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int rzg2l_adc_read_label(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ char *label)
+{
+ if (chan->channel >= RZG2L_ADC_MAX_CHANNELS)
+ return -EINVAL;
+
+ return sysfs_emit(label, "%s\n", rzg2l_adc_channel_name[chan->channel]);
+}
+
+static const struct iio_info rzg2l_adc_iio_info = {
+ .read_raw = rzg2l_adc_read_raw,
+ .read_label = rzg2l_adc_read_label,
+};
+
+static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id)
+{
+ struct rzg2l_adc *adc = dev_id;
+ unsigned long intst;
+ u32 reg;
+ int ch;
+
+ reg = rzg2l_adc_readl(adc, RZG2L_ADSTS);
+
+ /* A/D conversion channel select error interrupt */
+ if (reg & RZG2L_ADSTS_CSEST) {
+ rzg2l_adc_writel(adc, RZG2L_ADSTS, reg);
+ return IRQ_HANDLED;
+ }
+
+ intst = reg & RZG2L_ADSTS_INTST_MASK;
+ if (!intst)
+ return IRQ_NONE;
+
+ for_each_set_bit(ch, &intst, RZG2L_ADC_MAX_CHANNELS)
+ adc->last_val[ch] = rzg2l_adc_readl(adc, RZG2L_ADCR(ch)) & RZG2L_ADCR_AD_MASK;
+
+ /* clear the channel interrupt */
+ rzg2l_adc_writel(adc, RZG2L_ADSTS, reg);
+
+ complete(&adc->completion);
+
+ return IRQ_HANDLED;
+}
+
+static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l_adc *adc)
+{
+ struct iio_chan_spec *chan_array;
+ struct fwnode_handle *fwnode;
+ struct rzg2l_adc_data *data;
+ unsigned int channel;
+ int num_channels;
+ int ret;
+ u8 i;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ num_channels = device_get_child_node_count(&pdev->dev);
+ if (!num_channels) {
+ dev_err(&pdev->dev, "no channel children\n");
+ return -ENODEV;
+ }
+
+ if (num_channels > RZG2L_ADC_MAX_CHANNELS) {
+ dev_err(&pdev->dev, "num of channel children out of range\n");
+ return -EINVAL;
+ }
+
+ chan_array = devm_kcalloc(&pdev->dev, num_channels, sizeof(*chan_array),
+ GFP_KERNEL);
+ if (!chan_array)
+ return -ENOMEM;
+
+ i = 0;
+ device_for_each_child_node(&pdev->dev, fwnode) {
+ ret = fwnode_property_read_u32(fwnode, "reg", &channel);
+ if (ret)
+ return ret;
+
+ if (channel >= RZG2L_ADC_MAX_CHANNELS)
+ return -EINVAL;
+
+ chan_array[i].type = IIO_VOLTAGE;
+ chan_array[i].indexed = 1;
+ chan_array[i].channel = channel;
+ chan_array[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+ chan_array[i].datasheet_name = rzg2l_adc_channel_name[channel];
+ i++;
+ }
+
+ data->num_channels = num_channels;
+ data->channels = chan_array;
+ adc->data = data;
+
+ return 0;
+}
+
+static int rzg2l_adc_hw_init(struct rzg2l_adc *adc)
+{
+ int timeout = 5;
+ u32 reg;
+ int ret;
+
+ ret = clk_prepare_enable(adc->pclk);
+ if (ret)
+ return ret;
+
+ /* SW reset */
+ reg = rzg2l_adc_readl(adc, RZG2L_ADM(0));
+ reg |= RZG2L_ADM0_SRESB;
+ rzg2l_adc_writel(adc, RZG2L_ADM(0), reg);
+
+ while (!(rzg2l_adc_readl(adc, RZG2L_ADM(0)) & RZG2L_ADM0_SRESB)) {
+ if (!timeout) {
+ ret = -EBUSY;
+ goto exit_hw_init;
+ }
+ timeout--;
+ usleep_range(100, 200);
+ }
+
+ /* Only division by 4 can be set */
+ reg = rzg2l_adc_readl(adc, RZG2L_ADIVC);
+ reg &= ~RZG2L_ADIVC_DIVADC_MASK;
+ reg |= RZG2L_ADIVC_DIVADC_4;
+ rzg2l_adc_writel(adc, RZG2L_ADIVC, reg);
+
+ /*
+ * Setup AMD3
+ * ADIL[31:24] - Should be always set to 0
+ * ADCMP[23:16] - Should be always set to 0xe
+ * ADSMP[15:0] - Set default (0x578) sampling period
+ */
+ reg = rzg2l_adc_readl(adc, RZG2L_ADM(3));
+ reg &= ~RZG2L_ADM3_ADIL_MASK;
+ reg &= ~RZG2L_ADM3_ADCMP_MASK;
+ reg &= ~RZG2L_ADM3_ADSMP_MASK;
+ reg |= (RZG2L_ADM3_ADCMP_E | RZG2L_ADSMP_DEFUALT_SAMPLING);
+ rzg2l_adc_writel(adc, RZG2L_ADM(3), reg);
+
+exit_hw_init:
+ clk_disable_unprepare(adc->pclk);
+
+ return 0;
+}
+
+static void rzg2l_adc_pm_runtime_disable(void *data)
+{
+ struct device *dev = data;
+
+ pm_runtime_disable(dev->parent);
+}
+
+static void rzg2l_adc_pm_runtime_set_suspended(void *data)
+{
+ struct device *dev = data;
+
+ pm_runtime_set_suspended(dev->parent);
+}
+
+static void rzg2l_adc_reset_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
+static int rzg2l_adc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct iio_dev *indio_dev;
+ struct rzg2l_adc *adc;
+ int ret;
+ int irq;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ adc = iio_priv(indio_dev);
+
+ ret = rzg2l_adc_parse_properties(pdev, adc);
+ if (ret)
+ return ret;
+
+ mutex_init(&adc->lock);
+
+ adc->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(adc->base))
+ return PTR_ERR(adc->base);
+
+ adc->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(adc->pclk)) {
+ dev_err(dev, "Failed to get pclk");
+ return PTR_ERR(adc->pclk);
+ }
+
+ adc->adclk = devm_clk_get(dev, "adclk");
+ if (IS_ERR(adc->adclk)) {
+ dev_err(dev, "Failed to get adclk");
+ return PTR_ERR(adc->adclk);
+ }
+
+ adc->adrstn = devm_reset_control_get_exclusive(dev, "adrst-n");
+ if (IS_ERR(adc->adrstn)) {
+ dev_err(dev, "failed to get adrstn\n");
+ return PTR_ERR(adc->adrstn);
+ }
+
+ adc->presetn = devm_reset_control_get_exclusive(dev, "presetn");
+ if (IS_ERR(adc->presetn)) {
+ dev_err(dev, "failed to get presetn\n");
+ return PTR_ERR(adc->presetn);
+ }
+
+ ret = reset_control_deassert(adc->adrstn);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to deassert adrstn pin, %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&pdev->dev,
+ rzg2l_adc_reset_assert, adc->adrstn);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register adrstn assert devm action, %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = reset_control_deassert(adc->presetn);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to deassert presetn pin, %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&pdev->dev,
+ rzg2l_adc_reset_assert, adc->presetn);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register presetn assert devm action, %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = rzg2l_adc_hw_init(adc);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize ADC HW, %d\n", ret);
+ return ret;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq resource\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, rzg2l_adc_isr,
+ 0, dev_name(dev), adc);
+ if (ret < 0)
+ return ret;
+
+ init_completion(&adc->completion);
+
+ platform_set_drvdata(pdev, indio_dev);
+
+ indio_dev->name = DRIVER_NAME;
+ indio_dev->info = &rzg2l_adc_iio_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = adc->data->channels;
+ indio_dev->num_channels = adc->data->num_channels;
+
+ pm_runtime_set_suspended(dev);
+ ret = devm_add_action_or_reset(&pdev->dev,
+ rzg2l_adc_pm_runtime_set_suspended, &indio_dev->dev);
+ if (ret)
+ return ret;
+
+ pm_runtime_enable(dev);
+ ret = devm_add_action_or_reset(&pdev->dev,
+ rzg2l_adc_pm_runtime_disable, &indio_dev->dev);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id rzg2l_adc_match[] = {
+ { .compatible = "renesas,rzg2l-adc",},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rzg2l_adc_match);
+
+static int __maybe_unused rzg2l_adc_pm_runtime_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct rzg2l_adc *adc = iio_priv(indio_dev);
+
+ rzg2l_adc_pwr(adc, false);
+ clk_disable_unprepare(adc->adclk);
+ clk_disable_unprepare(adc->pclk);
+
+ return 0;
+}
+
+static int __maybe_unused rzg2l_adc_pm_runtime_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct rzg2l_adc *adc = iio_priv(indio_dev);
+ int ret;
+
+ ret = clk_prepare_enable(adc->pclk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(adc->adclk);
+ if (ret)
+ return ret;
+
+ rzg2l_adc_pwr(adc, true);
+
+ return 0;
+}
+
+static const struct dev_pm_ops rzg2l_adc_pm_ops = {
+ SET_RUNTIME_PM_OPS(rzg2l_adc_pm_runtime_suspend,
+ rzg2l_adc_pm_runtime_resume,
+ NULL)
+};
+
+static struct platform_driver rzg2l_adc_driver = {
+ .probe = rzg2l_adc_probe,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = rzg2l_adc_match,
+ .pm = &rzg2l_adc_pm_ops,
+ },
+};
+
+module_platform_driver(rzg2l_adc_driver);
+
+MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
+MODULE_DESCRIPTION("Renesas RZ/G2L ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
index a4920646e9be..c03667e62732 100644
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -131,6 +131,17 @@ config SENSIRION_SGP30
To compile this driver as module, choose M here: the
module will be called sgp30.
+config SENSIRION_SGP40
+ tristate "Sensirion SGP40 gas sensor"
+ depends on I2C
+ select CRC8
+ help
+ Say Y here to build I2C interface to support Sensirion SGP40 gas
+ sensor
+
+ To compile this driver as module, choose M here: the
+ module will be called sgp40.
+
config SPS30
tristate
select IIO_BUFFER
diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile
index 4898690cc155..d07af581f234 100644
--- a/drivers/iio/chemical/Makefile
+++ b/drivers/iio/chemical/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SCD30_CORE) += scd30_core.o
obj-$(CONFIG_SCD30_I2C) += scd30_i2c.o
obj-$(CONFIG_SCD30_SERIAL) += scd30_serial.o
obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o
+obj-$(CONFIG_SENSIRION_SGP40) += sgp40.o
obj-$(CONFIG_SPS30) += sps30.o
obj-$(CONFIG_SPS30_I2C) += sps30_i2c.o
obj-$(CONFIG_SPS30_SERIAL) += sps30_serial.o
diff --git a/drivers/iio/chemical/sgp40.c b/drivers/iio/chemical/sgp40.c
new file mode 100644
index 000000000000..8a56394cea4e
--- /dev/null
+++ b/drivers/iio/chemical/sgp40.c
@@ -0,0 +1,378 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * sgp40.c - Support for Sensirion SGP40 Gas Sensor
+ *
+ * Copyright (C) 2021 Andreas Klinger <ak@it-klinger.de>
+ *
+ * I2C slave address: 0x59
+ *
+ * Datasheet can be found here:
+ * https://www.sensirion.com/file/datasheet_sgp40
+ *
+ * There are two functionalities supported:
+ *
+ * 1) read raw logarithmic resistance value from sensor
+ * --> useful to pass it to the algorithm of the sensor vendor for
+ * measuring deteriorations and improvements of air quality.
+ *
+ * 2) calculate an estimated absolute voc index (0 - 500 index points) for
+ * measuring the air quality.
+ * For this purpose the value of the resistance for which the voc index
+ * will be 250 can be set up using calibbias.
+ *
+ * Compensation values of relative humidity and temperature can be set up
+ * by writing to the out values of temp and humidityrelative.
+ */
+
+#include <linux/delay.h>
+#include <linux/crc8.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+
+/*
+ * floating point calculation of voc is done as integer
+ * where numbers are multiplied by 1 << SGP40_CALC_POWER
+ */
+#define SGP40_CALC_POWER 14
+
+#define SGP40_CRC8_POLYNOMIAL 0x31
+#define SGP40_CRC8_INIT 0xff
+
+DECLARE_CRC8_TABLE(sgp40_crc8_table);
+
+struct sgp40_data {
+ struct device *dev;
+ struct i2c_client *client;
+ int rht;
+ int temp;
+ int res_calibbias;
+ /* Prevent concurrent access to rht, tmp, calibbias */
+ struct mutex lock;
+};
+
+struct sgp40_tg_measure {
+ u8 command[2];
+ __be16 rht_ticks;
+ u8 rht_crc;
+ __be16 temp_ticks;
+ u8 temp_crc;
+} __packed;
+
+struct sgp40_tg_result {
+ __be16 res_ticks;
+ u8 res_crc;
+} __packed;
+
+static const struct iio_chan_spec sgp40_channels[] = {
+ {
+ .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_VOC,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ },
+ {
+ .type = IIO_RESISTANCE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS),
+ },
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .output = 1,
+ },
+ {
+ .type = IIO_HUMIDITYRELATIVE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .output = 1,
+ },
+};
+
+/*
+ * taylor approximation of e^x:
+ * y = 1 + x + x^2 / 2 + x^3 / 6 + x^4 / 24 + ... + x^n / n!
+ *
+ * Because we are calculating x real value multiplied by 2^power we get
+ * an additional 2^power^n to divide for every element. For a reasonable
+ * precision this would overflow after a few iterations. Therefore we
+ * divide the x^n part whenever its about to overflow (xmax).
+ */
+
+static u32 sgp40_exp(int exp, u32 power, u32 rounds)
+{
+ u32 x, y, xp;
+ u32 factorial, divider, xmax;
+ int sign = 1;
+ int i;
+
+ if (exp == 0)
+ return 1 << power;
+ else if (exp < 0) {
+ sign = -1;
+ exp *= -1;
+ }
+
+ xmax = 0x7FFFFFFF / exp;
+ x = exp;
+ xp = 1;
+ factorial = 1;
+ y = 1 << power;
+ divider = 0;
+
+ for (i = 1; i <= rounds; i++) {
+ xp *= x;
+ factorial *= i;
+ y += (xp >> divider) / factorial;
+ divider += power;
+ /* divide when next multiplication would overflow */
+ if (xp >= xmax) {
+ xp >>= power;
+ divider -= power;
+ }
+ }
+
+ if (sign == -1)
+ return (1 << (power * 2)) / y;
+ else
+ return y;
+}
+
+static int sgp40_calc_voc(struct sgp40_data *data, u16 resistance_raw, int *voc)
+{
+ int x;
+ u32 exp = 0;
+
+ /* we calculate as a multiple of 16384 (2^14) */
+ mutex_lock(&data->lock);
+ x = ((int)resistance_raw - data->res_calibbias) * 106;
+ mutex_unlock(&data->lock);
+
+ /* voc = 500 / (1 + e^x) */
+ exp = sgp40_exp(x, SGP40_CALC_POWER, 18);
+ *voc = 500 * ((1 << (SGP40_CALC_POWER * 2)) / ((1<<SGP40_CALC_POWER) + exp));
+
+ dev_dbg(data->dev, "raw: %d res_calibbias: %d x: %d exp: %d voc: %d\n",
+ resistance_raw, data->res_calibbias, x, exp, *voc);
+
+ return 0;
+}
+
+static int sgp40_measure_resistance_raw(struct sgp40_data *data, u16 *resistance_raw)
+{
+ int ret;
+ struct i2c_client *client = data->client;
+ u32 ticks;
+ u16 ticks16;
+ u8 crc;
+ struct sgp40_tg_measure tg = {.command = {0x26, 0x0F}};
+ struct sgp40_tg_result tgres;
+
+ mutex_lock(&data->lock);
+
+ ticks = (data->rht / 10) * 65535 / 10000;
+ ticks16 = (u16)clamp(ticks, 0u, 65535u); /* clamp between 0 .. 100 %rH */
+ tg.rht_ticks = cpu_to_be16(ticks16);
+ tg.rht_crc = crc8(sgp40_crc8_table, (u8 *)&tg.rht_ticks, 2, SGP40_CRC8_INIT);
+
+ ticks = ((data->temp + 45000) / 10 ) * 65535 / 17500;
+ ticks16 = (u16)clamp(ticks, 0u, 65535u); /* clamp between -45 .. +130 °C */
+ tg.temp_ticks = cpu_to_be16(ticks16);
+ tg.temp_crc = crc8(sgp40_crc8_table, (u8 *)&tg.temp_ticks, 2, SGP40_CRC8_INIT);
+
+ mutex_unlock(&data->lock);
+
+ ret = i2c_master_send(client, (const char *)&tg, sizeof(tg));
+ if (ret != sizeof(tg)) {
+ dev_warn(data->dev, "i2c_master_send ret: %d sizeof: %zu\n", ret, sizeof(tg));
+ return -EIO;
+ }
+ msleep(30);
+
+ ret = i2c_master_recv(client, (u8 *)&tgres, sizeof(tgres));
+ if (ret < 0)
+ return ret;
+ if (ret != sizeof(tgres)) {
+ dev_warn(data->dev, "i2c_master_recv ret: %d sizeof: %zu\n", ret, sizeof(tgres));
+ return -EIO;
+ }
+
+ crc = crc8(sgp40_crc8_table, (u8 *)&tgres.res_ticks, 2, SGP40_CRC8_INIT);
+ if (crc != tgres.res_crc) {
+ dev_err(data->dev, "CRC error while measure-raw\n");
+ return -EIO;
+ }
+
+ *resistance_raw = be16_to_cpu(tgres.res_ticks);
+
+ return 0;
+}
+
+static int sgp40_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct sgp40_data *data = iio_priv(indio_dev);
+ int ret, voc;
+ u16 resistance_raw;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_RESISTANCE:
+ ret = sgp40_measure_resistance_raw(data, &resistance_raw);
+ if (ret)
+ return ret;
+
+ *val = resistance_raw;
+ return IIO_VAL_INT;
+ case IIO_TEMP:
+ mutex_lock(&data->lock);
+ *val = data->temp;
+ mutex_unlock(&data->lock);
+ return IIO_VAL_INT;
+ case IIO_HUMIDITYRELATIVE:
+ mutex_lock(&data->lock);
+ *val = data->rht;
+ mutex_unlock(&data->lock);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_PROCESSED:
+ ret = sgp40_measure_resistance_raw(data, &resistance_raw);
+ if (ret)
+ return ret;
+
+ ret = sgp40_calc_voc(data, resistance_raw, &voc);
+ if (ret)
+ return ret;
+
+ *val = voc / (1 << SGP40_CALC_POWER);
+ /*
+ * calculation should fit into integer, where:
+ * voc <= (500 * 2^SGP40_CALC_POWER) = 8192000
+ * (with SGP40_CALC_POWER = 14)
+ */
+ *val2 = ((voc % (1 << SGP40_CALC_POWER)) * 244) / (1 << (SGP40_CALC_POWER - 12));
+ dev_dbg(data->dev, "voc: %d val: %d.%06d\n", voc, *val, *val2);
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ mutex_lock(&data->lock);
+ *val = data->res_calibbias;
+ mutex_unlock(&data->lock);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int sgp40_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ struct sgp40_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_TEMP:
+ if ((val < -45000) || (val > 130000))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+ data->temp = val;
+ mutex_unlock(&data->lock);
+ return 0;
+ case IIO_HUMIDITYRELATIVE:
+ if ((val < 0) || (val > 100000))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+ data->rht = val;
+ mutex_unlock(&data->lock);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_CALIBBIAS:
+ if ((val < 20000) || (val > 52768))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+ data->res_calibbias = val;
+ mutex_unlock(&data->lock);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static const struct iio_info sgp40_info = {
+ .read_raw = sgp40_read_raw,
+ .write_raw = sgp40_write_raw,
+};
+
+static int sgp40_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct iio_dev *indio_dev;
+ struct sgp40_data *data;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->client = client;
+ data->dev = dev;
+
+ crc8_populate_msb(sgp40_crc8_table, SGP40_CRC8_POLYNOMIAL);
+
+ mutex_init(&data->lock);
+
+ /* set default values */
+ data->rht = 50000; /* 50 % */
+ data->temp = 25000; /* 25 °C */
+ data->res_calibbias = 30000; /* resistance raw value for voc index of 250 */
+
+ indio_dev->info = &sgp40_info;
+ indio_dev->name = id->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = sgp40_channels;
+ indio_dev->num_channels = ARRAY_SIZE(sgp40_channels);
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ dev_err(dev, "failed to register iio device\n");
+
+ return ret;
+}
+
+static const struct i2c_device_id sgp40_id[] = {
+ { "sgp40" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, sgp40_id);
+
+static const struct of_device_id sgp40_dt_ids[] = {
+ { .compatible = "sensirion,sgp40" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, sgp40_dt_ids);
+
+static struct i2c_driver sgp40_driver = {
+ .driver = {
+ .name = "sgp40",
+ .of_match_table = sgp40_dt_ids,
+ },
+ .probe = sgp40_probe,
+ .id_table = sgp40_id,
+};
+module_i2c_driver(sgp40_driver);
+
+MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
+MODULE_DESCRIPTION("Sensirion SGP40 gas sensor");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c
index 802f9ae04cf4..dccc471e79da 100644
--- a/drivers/iio/common/st_sensors/st_sensors_buffer.c
+++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c
@@ -9,13 +9,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/interrupt.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include <linux/irqreturn.h>
#include <linux/regmap.h>
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index 7a69c1be7393..0bbb090b108c 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
+#include <linux/mutex.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.h b/drivers/iio/common/st_sensors/st_sensors_core.h
index e8894be55660..09f3e602a2e2 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.h
+++ b/drivers/iio/common/st_sensors/st_sensors_core.h
@@ -4,6 +4,7 @@
*/
#ifndef __ST_SENSORS_CORE_H
#define __ST_SENSORS_CORE_H
+struct iio_dev;
int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
u8 reg_addr, u8 mask, u8 data);
#endif
diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c
index b9e59ad32a02..b3ff88700866 100644
--- a/drivers/iio/common/st_sensors/st_sensors_i2c.c
+++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c
@@ -7,15 +7,14 @@
* Denis Ciocca <denis.ciocca@st.com>
*/
+#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/regmap.h>
#include <linux/iio/common/st_sensors_i2c.h>
-
#define ST_SENSORS_I2C_MULTIREAD 0x80
static const struct regmap_config st_sensors_i2c_regmap_config = {
diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c
index 48fc41dc5633..0d1d66c77cd8 100644
--- a/drivers/iio/common/st_sensors/st_sensors_spi.c
+++ b/drivers/iio/common/st_sensors/st_sensors_spi.c
@@ -9,13 +9,12 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/property.h>
#include <linux/regmap.h>
+#include <linux/spi/spi.h>
#include <linux/iio/common/st_sensors_spi.h>
-#include "st_sensors_core.h"
#define ST_SENSORS_SPI_MULTIREAD 0xc0
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index 0b511665dee5..64e0a748a855 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -9,7 +9,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/interrupt.h>
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index 9bde86982912..530529feebb5 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -229,7 +229,7 @@ static int ad5624r_probe(struct spi_device *spi)
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = devm_regulator_get(&spi->dev, "vcc");
+ st->reg = devm_regulator_get_optional(&spi->dev, "vref");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
@@ -240,6 +240,22 @@ static int ad5624r_probe(struct spi_device *spi)
goto error_disable_reg;
voltage_uv = ret;
+ } else {
+ if (PTR_ERR(st->reg) != -ENODEV)
+ return PTR_ERR(st->reg);
+ /* Backwards compatibility. This naming is not correct */
+ st->reg = devm_regulator_get_optional(&spi->dev, "vcc");
+ if (!IS_ERR(st->reg)) {
+ ret = regulator_enable(st->reg);
+ if (ret)
+ return ret;
+
+ ret = regulator_get_voltage(st->reg);
+ if (ret < 0)
+ goto error_disable_reg;
+
+ voltage_uv = ret;
+ }
}
spi_set_drvdata(spi, indio_dev);
diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c
index bd6e75699a63..bd0b7f361154 100644
--- a/drivers/iio/dac/max5821.c
+++ b/drivers/iio/dac/max5821.c
@@ -294,6 +294,11 @@ static const struct iio_info max5821_info = {
.write_raw = max5821_write_raw,
};
+static void max5821_regulator_disable(void *reg)
+{
+ regulator_disable(reg);
+}
+
static int max5821_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -306,7 +311,6 @@ static int max5821_probe(struct i2c_client *client,
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
- i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->lock);
@@ -321,21 +325,29 @@ static int max5821_probe(struct i2c_client *client,
ret = PTR_ERR(data->vref_reg);
dev_err(&client->dev,
"Failed to get vref regulator: %d\n", ret);
- goto error_free_reg;
+ return ret;
}
ret = regulator_enable(data->vref_reg);
if (ret) {
dev_err(&client->dev,
"Failed to enable vref regulator: %d\n", ret);
- goto error_free_reg;
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&client->dev, max5821_regulator_disable,
+ data->vref_reg);
+ if (ret) {
+ dev_err(&client->dev,
+ "Failed to add action to managed regulator: %d\n", ret);
+ return ret;
}
ret = regulator_get_voltage(data->vref_reg);
if (ret < 0) {
dev_err(&client->dev,
"Failed to get voltage on regulator: %d\n", ret);
- goto error_disable_reg;
+ return ret;
}
data->vref_mv = ret / 1000;
@@ -346,25 +358,7 @@ static int max5821_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &max5821_info;
- return iio_device_register(indio_dev);
-
-error_disable_reg:
- regulator_disable(data->vref_reg);
-
-error_free_reg:
-
- return ret;
-}
-
-static int max5821_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct max5821_data *data = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- regulator_disable(data->vref_reg);
-
- return 0;
+ return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id max5821_id[] = {
@@ -386,7 +380,6 @@ static struct i2c_driver max5821_driver = {
.pm = &max5821_pm_ops,
},
.probe = max5821_probe,
- .remove = max5821_remove,
.id_table = max5821_id,
};
module_i2c_driver(max5821_driver);
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index bc63c2a34c5e..8f0ad022c7f1 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -303,8 +303,8 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
return ret;
}
- indio_dev->channels = kmemdup(gyro_3d_channels,
- sizeof(gyro_3d_channels), GFP_KERNEL);
+ indio_dev->channels = devm_kmemdup(&pdev->dev, gyro_3d_channels,
+ sizeof(gyro_3d_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
@@ -315,7 +315,7 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
HID_USAGE_SENSOR_GYRO_3D, gyro_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
- goto error_free_dev_mem;
+ return ret;
}
indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels);
@@ -329,7 +329,7 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
&gyro_state->common_attributes);
if (ret < 0) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_free_dev_mem;
+ return ret;
}
ret = iio_device_register(indio_dev);
@@ -354,8 +354,6 @@ error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
-error_free_dev_mem:
- kfree(indio_dev->channels);
return ret;
}
@@ -369,7 +367,6 @@ static int hid_gyro_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
- kfree(indio_dev->channels);
return 0;
}
diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h
index 6537f5cb8320..f5332b6a02bc 100644
--- a/drivers/iio/gyro/st_gyro.h
+++ b/drivers/iio/gyro/st_gyro.h
@@ -26,7 +26,6 @@
#ifdef CONFIG_IIO_BUFFER
int st_gyro_allocate_ring(struct iio_dev *indio_dev);
-void st_gyro_deallocate_ring(struct iio_dev *indio_dev);
int st_gyro_trig_set_state(struct iio_trigger *trig, bool state);
#define ST_GYRO_TRIGGER_SET_STATE (&st_gyro_trig_set_state)
#else /* CONFIG_IIO_BUFFER */
@@ -34,9 +33,6 @@ static inline int st_gyro_allocate_ring(struct iio_dev *indio_dev)
{
return 0;
}
-static inline void st_gyro_deallocate_ring(struct iio_dev *indio_dev)
-{
-}
#define ST_GYRO_TRIGGER_SET_STATE NULL
#endif /* CONFIG_IIO_BUFFER */
diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c
index 4feb7ada7195..4ae33ef25b9c 100644
--- a/drivers/iio/gyro/st_gyro_buffer.c
+++ b/drivers/iio/gyro/st_gyro_buffer.c
@@ -9,14 +9,9 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/common/st_sensors.h>
@@ -66,13 +61,8 @@ static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = {
int st_gyro_allocate_ring(struct iio_dev *indio_dev)
{
- return iio_triggered_buffer_setup(indio_dev, NULL,
- &st_sensors_trigger_handler, &st_gyro_buffer_setup_ops);
-}
-
-void st_gyro_deallocate_ring(struct iio_dev *indio_dev)
-{
- iio_triggered_buffer_cleanup(indio_dev);
+ return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
+ NULL, &st_sensors_trigger_handler, &st_gyro_buffer_setup_ops);
}
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index b86ee4d940d9..e8fc8af65143 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -9,17 +9,12 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/types.h>
+#include <linux/mutex.h>
#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
+#include <linux/sysfs.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
-#include <linux/iio/buffer.h>
#include <linux/iio/common/st_sensors.h>
#include "st_gyro.h"
@@ -517,7 +512,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
err = st_sensors_allocate_trigger(indio_dev,
ST_GYRO_TRIGGER_OPS);
if (err < 0)
- goto st_gyro_probe_trigger_error;
+ return err;
}
err = iio_device_register(indio_dev);
@@ -532,8 +527,6 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
st_gyro_device_register_error:
if (gdata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
-st_gyro_probe_trigger_error:
- st_gyro_deallocate_ring(indio_dev);
return err;
}
EXPORT_SYMBOL(st_gyro_common_probe);
@@ -545,8 +538,6 @@ void st_gyro_common_remove(struct iio_dev *indio_dev)
iio_device_unregister(indio_dev);
if (gdata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
-
- st_gyro_deallocate_ring(indio_dev);
}
EXPORT_SYMBOL(st_gyro_common_remove);
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index a25cc0379e16..3ef86e16ee65 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
index 18d6a2aeda45..41d835493347 100644
--- a/drivers/iio/gyro/st_gyro_spi.c
+++ b/drivers/iio/gyro/st_gyro_spi.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 8a7a920e6200..597768c29a72 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -143,6 +143,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6050,
.fifo_size = 1024,
.temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
+ .startup_time = {INV_MPU6050_GYRO_STARTUP_TIME, INV_MPU6050_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_MPU6500_WHOAMI_VALUE,
@@ -151,6 +152,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 512,
.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_MPU6515_WHOAMI_VALUE,
@@ -159,6 +161,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 512,
.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_MPU6880_WHOAMI_VALUE,
@@ -167,6 +170,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 4096,
.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_MPU6000_WHOAMI_VALUE,
@@ -175,6 +179,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6050,
.fifo_size = 1024,
.temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
+ .startup_time = {INV_MPU6050_GYRO_STARTUP_TIME, INV_MPU6050_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_MPU9150_WHOAMI_VALUE,
@@ -183,6 +188,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6050,
.fifo_size = 1024,
.temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
+ .startup_time = {INV_MPU6050_GYRO_STARTUP_TIME, INV_MPU6050_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_MPU9250_WHOAMI_VALUE,
@@ -191,6 +197,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 512,
.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_MPU9255_WHOAMI_VALUE,
@@ -199,6 +206,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 512,
.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_ICM20608_WHOAMI_VALUE,
@@ -207,6 +215,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 512,
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_ICM20609_WHOAMI_VALUE,
@@ -215,6 +224,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 4 * 1024,
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_ICM20689_WHOAMI_VALUE,
@@ -223,6 +233,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 4 * 1024,
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_ICM20602_WHOAMI_VALUE,
@@ -231,6 +242,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 1008,
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_ICM20602_GYRO_STARTUP_TIME, INV_ICM20602_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_ICM20690_WHOAMI_VALUE,
@@ -239,6 +251,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 1024,
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_ICM20690_GYRO_STARTUP_TIME, INV_ICM20690_ACCEL_STARTUP_TIME},
},
{
.whoami = INV_IAM20680_WHOAMI_VALUE,
@@ -247,6 +260,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
.config = &chip_config_6500,
.fifo_size = 512,
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
};
@@ -379,12 +393,12 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
sleep = 0;
if (en) {
if (mask & INV_MPU6050_SENSOR_ACCL) {
- if (sleep < INV_MPU6050_ACCEL_UP_TIME)
- sleep = INV_MPU6050_ACCEL_UP_TIME;
+ if (sleep < st->hw->startup_time.accel)
+ sleep = st->hw->startup_time.accel;
}
if (mask & INV_MPU6050_SENSOR_GYRO) {
- if (sleep < INV_MPU6050_GYRO_UP_TIME)
- sleep = INV_MPU6050_GYRO_UP_TIME;
+ if (sleep < st->hw->startup_time.gyro)
+ sleep = st->hw->startup_time.gyro;
}
} else {
if (mask & INV_MPU6050_SENSOR_GYRO) {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 58188dc0dd13..c6aa36ee966a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -149,6 +149,10 @@ struct inv_mpu6050_hw {
int offset;
int scale;
} temp;
+ struct {
+ unsigned int accel;
+ unsigned int gyro;
+ } startup_time;
};
/*
@@ -320,11 +324,21 @@ struct inv_mpu6050_state {
/* delay time in milliseconds */
#define INV_MPU6050_POWER_UP_TIME 100
#define INV_MPU6050_TEMP_UP_TIME 100
-#define INV_MPU6050_ACCEL_UP_TIME 20
-#define INV_MPU6050_GYRO_UP_TIME 35
+#define INV_MPU6050_ACCEL_STARTUP_TIME 20
+#define INV_MPU6050_GYRO_STARTUP_TIME 60
#define INV_MPU6050_GYRO_DOWN_TIME 150
#define INV_MPU6050_SUSPEND_DELAY_MS 2000
+#define INV_MPU6500_GYRO_STARTUP_TIME 70
+#define INV_MPU6500_ACCEL_STARTUP_TIME 30
+
+#define INV_ICM20602_GYRO_STARTUP_TIME 100
+#define INV_ICM20602_ACCEL_STARTUP_TIME 20
+
+#define INV_ICM20690_GYRO_STARTUP_TIME 80
+#define INV_ICM20690_ACCEL_STARTUP_TIME 10
+
+
/* delay time in microseconds */
#define INV_MPU6050_REG_UP_TIME_MIN 5000
#define INV_MPU6050_REG_UP_TIME_MAX 10000
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index 2d0e8cdd4848..882546897255 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -91,22 +91,11 @@ static unsigned int inv_scan_query(struct iio_dev *indio_dev)
static unsigned int inv_compute_skip_samples(const struct inv_mpu6050_state *st)
{
- unsigned int gyro_skip = 0;
- unsigned int magn_skip = 0;
- unsigned int skip_samples;
-
- /* gyro first sample is out of specs, skip it */
- if (st->chip_config.gyro_fifo_enable)
- gyro_skip = 1;
+ unsigned int skip_samples = 0;
/* mag first sample is always not ready, skip it */
if (st->chip_config.magn_fifo_enable)
- magn_skip = 1;
-
- /* compute first samples to skip */
- skip_samples = gyro_skip;
- if (magn_skip > skip_samples)
- skip_samples = magn_skip;
+ skip_samples = 1;
return skip_samples;
}
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c
index 8204f7303fd7..5e6625140db7 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c
@@ -10,6 +10,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/common/st_sensors.h>
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
index 50a36ab53bc3..78bede358747 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
@@ -10,7 +10,8 @@
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
#include <linux/iio/common/st_sensors_i2c.h>
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
index 272c88990dd0..180b54e66438 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
@@ -9,7 +9,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/iio/common/st_sensors_spi.h>
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index fdd623407b96..a95cc2da56be 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -354,13 +354,14 @@ static int iio_scan_mask_set(struct iio_dev *indio_dev,
const unsigned long *mask;
unsigned long *trialmask;
- trialmask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
- if (trialmask == NULL)
- return -ENOMEM;
if (!indio_dev->masklength) {
WARN(1, "Trying to set scanmask prior to registering buffer\n");
- goto err_invalid_mask;
+ return -EINVAL;
}
+
+ trialmask = bitmap_alloc(indio_dev->masklength, GFP_KERNEL);
+ if (!trialmask)
+ return -ENOMEM;
bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
set_bit(bit, trialmask);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 6d2175eb7af2..2dbb37e09b8c 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -740,10 +740,13 @@ static ssize_t iio_read_channel_label(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- if (!indio_dev->info->read_label)
- return -EINVAL;
+ if (indio_dev->info->read_label)
+ return indio_dev->info->read_label(indio_dev, this_attr->c, buf);
+
+ if (this_attr->c->extend_name)
+ return sprintf(buf, "%s\n", this_attr->c->extend_name);
- return indio_dev->info->read_label(indio_dev, this_attr->c, buf);
+ return -EINVAL;
}
static ssize_t iio_read_channel_info(struct device *dev,
@@ -1183,7 +1186,7 @@ static int iio_device_add_channel_label(struct iio_dev *indio_dev,
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
int ret;
- if (!indio_dev->info->read_label)
+ if (!indio_dev->info->read_label && !chan->extend_name)
return 0;
ret = __iio_add_chan_devattr("label",
@@ -1858,6 +1861,24 @@ static int iio_check_unique_scan_index(struct iio_dev *indio_dev)
return 0;
}
+static int iio_check_extended_name(const struct iio_dev *indio_dev)
+{
+ unsigned int i;
+
+ if (!indio_dev->info->read_label)
+ return 0;
+
+ for (i = 0; i < indio_dev->num_channels; i++) {
+ if (indio_dev->channels[i].extend_name) {
+ dev_err(&indio_dev->dev,
+ "Cannot use labels and extend_name at the same time\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static const struct iio_buffer_setup_ops noop_ring_setup_ops;
int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
@@ -1882,6 +1903,10 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
if (ret < 0)
return ret;
+ ret = iio_check_extended_name(indio_dev);
+ if (ret < 0)
+ return ret;
+
iio_device_register_debugfs(indio_dev);
ret = iio_buffers_alloc_sysfs_and_mask(indio_dev);
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index 17dac8d0e11d..6b33975c8d73 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -54,7 +54,10 @@
struct adjd_s311_data {
struct i2c_client *client;
- u16 *buffer;
+ struct {
+ s16 chans[4];
+ s64 ts __aligned(8);
+ } scan;
};
enum adjd_s311_channel_idx {
@@ -129,10 +132,10 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
if (ret < 0)
goto done;
- data->buffer[j++] = ret & ADJD_S311_DATA_MASK;
+ data->scan.chans[j++] = ret & ADJD_S311_DATA_MASK;
}
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, time_ns);
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns);
done:
iio_trigger_notify_done(indio_dev->trig);
@@ -225,23 +228,9 @@ static int adjd_s311_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
-static int adjd_s311_update_scan_mode(struct iio_dev *indio_dev,
- const unsigned long *scan_mask)
-{
- struct adjd_s311_data *data = iio_priv(indio_dev);
-
- kfree(data->buffer);
- data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
- if (data->buffer == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
static const struct iio_info adjd_s311_info = {
.read_raw = adjd_s311_read_raw,
.write_raw = adjd_s311_write_raw,
- .update_scan_mode = adjd_s311_update_scan_mode,
};
static int adjd_s311_probe(struct i2c_client *client,
@@ -256,7 +245,6 @@ static int adjd_s311_probe(struct i2c_client *client,
return -ENOMEM;
data = iio_priv(indio_dev);
- i2c_set_clientdata(client, indio_dev);
data->client = client;
indio_dev->info = &adjd_s311_info;
@@ -265,34 +253,12 @@ static int adjd_s311_probe(struct i2c_client *client,
indio_dev->num_channels = ARRAY_SIZE(adjd_s311_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
- err = iio_triggered_buffer_setup(indio_dev, NULL,
- adjd_s311_trigger_handler, NULL);
+ err = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ adjd_s311_trigger_handler, NULL);
if (err < 0)
return err;
- err = iio_device_register(indio_dev);
- if (err)
- goto exit_unreg_buffer;
-
- dev_info(&client->dev, "ADJD-S311 color sensor registered\n");
-
- return 0;
-
-exit_unreg_buffer:
- iio_triggered_buffer_cleanup(indio_dev);
- return err;
-}
-
-static int adjd_s311_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct adjd_s311_data *data = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- iio_triggered_buffer_cleanup(indio_dev);
- kfree(data->buffer);
-
- return 0;
+ return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id adjd_s311_id[] = {
@@ -306,7 +272,6 @@ static struct i2c_driver adjd_s311_driver = {
.name = ADJD_S311_DRV_NAME,
},
.probe = adjd_s311_probe,
- .remove = adjd_s311_remove,
.id_table = adjd_s311_id,
};
module_i2c_driver(adjd_s311_driver);
diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c
index 6d1b0ffd144b..fd9a8c27de2e 100644
--- a/drivers/iio/light/cm3323.c
+++ b/drivers/iio/light/cm3323.c
@@ -256,9 +256,16 @@ static const struct i2c_device_id cm3323_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cm3323_id);
+static const struct of_device_id cm3323_of_match[] = {
+ { .compatible = "capella,cm3323", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cm3323_of_match);
+
static struct i2c_driver cm3323_driver = {
.driver = {
.name = CM3323_DRV_NAME,
+ .of_match_table = cm3323_of_match,
},
.probe = cm3323_probe,
.id_table = cm3323_id,
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 2ff252c75c03..5a1a625d8d16 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -294,8 +294,8 @@ static int hid_als_probe(struct platform_device *pdev)
return ret;
}
- indio_dev->channels = kmemdup(als_channels,
- sizeof(als_channels), GFP_KERNEL);
+ indio_dev->channels = devm_kmemdup(&pdev->dev, als_channels,
+ sizeof(als_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
@@ -306,7 +306,7 @@ static int hid_als_probe(struct platform_device *pdev)
HID_USAGE_SENSOR_ALS, als_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
- goto error_free_dev_mem;
+ return ret;
}
indio_dev->num_channels =
@@ -321,7 +321,7 @@ static int hid_als_probe(struct platform_device *pdev)
&als_state->common_attributes);
if (ret < 0) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_free_dev_mem;
+ return ret;
}
ret = iio_device_register(indio_dev);
@@ -346,8 +346,6 @@ error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
-error_free_dev_mem:
- kfree(indio_dev->channels);
return ret;
}
@@ -361,7 +359,6 @@ static int hid_als_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ALS);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
- kfree(indio_dev->channels);
return 0;
}
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 1621530f5f61..f10fa2abfe72 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -253,8 +253,8 @@ static int hid_prox_probe(struct platform_device *pdev)
return ret;
}
- indio_dev->channels = kmemdup(prox_channels, sizeof(prox_channels),
- GFP_KERNEL);
+ indio_dev->channels = devm_kmemdup(&pdev->dev, prox_channels,
+ sizeof(prox_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
@@ -265,7 +265,7 @@ static int hid_prox_probe(struct platform_device *pdev)
HID_USAGE_SENSOR_PROX, prox_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
- goto error_free_dev_mem;
+ return ret;
}
indio_dev->num_channels = ARRAY_SIZE(prox_channels);
@@ -279,7 +279,7 @@ static int hid_prox_probe(struct platform_device *pdev)
&prox_state->common_attributes);
if (ret) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_free_dev_mem;
+ return ret;
}
ret = iio_device_register(indio_dev);
@@ -304,8 +304,6 @@ error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
-error_free_dev_mem:
- kfree(indio_dev->channels);
return ret;
}
@@ -319,7 +317,6 @@ static int hid_prox_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PROX);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
- kfree(indio_dev->channels);
return 0;
}
diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c
index e2abad48b9f4..e8f6cdf26f22 100644
--- a/drivers/iio/light/si1145.c
+++ b/drivers/iio/light/si1145.c
@@ -220,7 +220,6 @@ static int __si1145_command_reset(struct si1145_data *data)
return -ETIMEDOUT;
}
msleep(SI1145_COMMAND_MINSLEEP_MS);
- continue;
}
}
diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c
index 0593abd600ec..b87222141429 100644
--- a/drivers/iio/light/tcs3414.c
+++ b/drivers/iio/light/tcs3414.c
@@ -267,6 +267,18 @@ static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops = {
.predisable = tcs3414_buffer_predisable,
};
+static int tcs3414_powerdown(struct tcs3414_data *data)
+{
+ return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ data->control & ~(TCS3414_CONTROL_POWER |
+ TCS3414_CONTROL_ADC_EN));
+}
+
+static void tcs3414_powerdown_cleanup(void *data)
+{
+ tcs3414_powerdown(data);
+}
+
static int tcs3414_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -309,6 +321,11 @@ static int tcs3414_probe(struct i2c_client *client,
if (ret < 0)
return ret;
+ ret = devm_add_action_or_reset(&client->dev, tcs3414_powerdown_cleanup,
+ data);
+ if (ret < 0)
+ return ret;
+
data->timing = TCS3414_INTEG_12MS; /* free running */
ret = i2c_smbus_write_byte_data(data->client, TCS3414_TIMING,
data->timing);
@@ -320,38 +337,12 @@ static int tcs3414_probe(struct i2c_client *client,
return ret;
data->gain = ret;
- ret = iio_triggered_buffer_setup(indio_dev, NULL,
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
tcs3414_trigger_handler, &tcs3414_buffer_setup_ops);
if (ret < 0)
return ret;
- ret = iio_device_register(indio_dev);
- if (ret < 0)
- goto buffer_cleanup;
-
- return 0;
-
-buffer_cleanup:
- iio_triggered_buffer_cleanup(indio_dev);
- return ret;
-}
-
-static int tcs3414_powerdown(struct tcs3414_data *data)
-{
- return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
- data->control & ~(TCS3414_CONTROL_POWER |
- TCS3414_CONTROL_ADC_EN));
-}
-
-static int tcs3414_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
- iio_device_unregister(indio_dev);
- iio_triggered_buffer_cleanup(indio_dev);
- tcs3414_powerdown(iio_priv(indio_dev));
-
- return 0;
+ return devm_iio_device_register(&client->dev, indio_dev);
}
#ifdef CONFIG_PM_SLEEP
@@ -385,7 +376,6 @@ static struct i2c_driver tcs3414_driver = {
.pm = &tcs3414_pm_ops,
},
.probe = tcs3414_probe,
- .remove = tcs3414_remove,
.id_table = tcs3414_id,
};
module_i2c_driver(tcs3414_driver);
diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h
index fb6c906c4c0c..785b7f7b8b06 100644
--- a/drivers/iio/magnetometer/st_magn.h
+++ b/drivers/iio/magnetometer/st_magn.h
@@ -25,25 +25,13 @@
#ifdef CONFIG_IIO_BUFFER
int st_magn_allocate_ring(struct iio_dev *indio_dev);
-void st_magn_deallocate_ring(struct iio_dev *indio_dev);
int st_magn_trig_set_state(struct iio_trigger *trig, bool state);
#define ST_MAGN_TRIGGER_SET_STATE (&st_magn_trig_set_state)
#else /* CONFIG_IIO_BUFFER */
-static inline int st_magn_probe_trigger(struct iio_dev *indio_dev, int irq)
-{
- return 0;
-}
-static inline void st_magn_remove_trigger(struct iio_dev *indio_dev, int irq)
-{
- return;
-}
static inline int st_magn_allocate_ring(struct iio_dev *indio_dev)
{
return 0;
}
-static inline void st_magn_deallocate_ring(struct iio_dev *indio_dev)
-{
-}
#define ST_MAGN_TRIGGER_SET_STATE NULL
#endif /* CONFIG_IIO_BUFFER */
diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c
index 4917721fa2e5..cb43ccda808d 100644
--- a/drivers/iio/magnetometer/st_magn_buffer.c
+++ b/drivers/iio/magnetometer/st_magn_buffer.c
@@ -9,14 +9,9 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/common/st_sensors.h>
@@ -46,13 +41,8 @@ static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = {
int st_magn_allocate_ring(struct iio_dev *indio_dev)
{
- return iio_triggered_buffer_setup(indio_dev, NULL,
- &st_sensors_trigger_handler, &st_magn_buffer_setup_ops);
-}
-
-void st_magn_deallocate_ring(struct iio_dev *indio_dev)
-{
- iio_triggered_buffer_cleanup(indio_dev);
+ return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
+ NULL, &st_sensors_trigger_handler, &st_magn_buffer_setup_ops);
}
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index 0048c3cd36ee..9ffd50d796bf 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -9,16 +9,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/common/st_sensors.h>
#include "st_magn.h"
@@ -652,7 +647,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
err = st_sensors_allocate_trigger(indio_dev,
ST_MAGN_TRIGGER_OPS);
if (err < 0)
- goto st_magn_probe_trigger_error;
+ return err;
}
err = iio_device_register(indio_dev);
@@ -667,8 +662,6 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
st_magn_device_register_error:
if (mdata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
-st_magn_probe_trigger_error:
- st_magn_deallocate_ring(indio_dev);
return err;
}
EXPORT_SYMBOL(st_magn_common_probe);
@@ -680,8 +673,6 @@ void st_magn_common_remove(struct iio_dev *indio_dev)
iio_device_unregister(indio_dev);
if (mdata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
-
- st_magn_deallocate_ring(indio_dev);
}
EXPORT_SYMBOL(st_magn_common_remove);
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
index 3e23c117de8e..2dfe4ee99591 100644
--- a/drivers/iio/magnetometer/st_magn_i2c.c
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
index 03c0a737aba6..fba978796395 100644
--- a/drivers/iio/magnetometer/st_magn_spi.c
+++ b/drivers/iio/magnetometer/st_magn_spi.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index c0079e2c8807..ba5b581d5b25 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -326,8 +326,8 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
return ret;
}
- indio_dev->channels = kmemdup(incl_3d_channels,
- sizeof(incl_3d_channels), GFP_KERNEL);
+ indio_dev->channels = devm_kmemdup(&pdev->dev, incl_3d_channels,
+ sizeof(incl_3d_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
@@ -339,7 +339,7 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
incl_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
- goto error_free_dev_mem;
+ return ret;
}
indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels);
@@ -353,7 +353,7 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
&incl_state->common_attributes);
if (ret) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_free_dev_mem;
+ return ret;
}
ret = iio_device_register(indio_dev);
@@ -379,8 +379,6 @@ error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
-error_free_dev_mem:
- kfree(indio_dev->channels);
return ret;
}
@@ -394,7 +392,6 @@ static int hid_incl_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
- kfree(indio_dev->channels);
return 0;
}
diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig
index 4cac0173db8b..832df8da2bc6 100644
--- a/drivers/iio/potentiometer/Kconfig
+++ b/drivers/iio/potentiometer/Kconfig
@@ -6,6 +6,16 @@
menu "Digital potentiometers"
+config AD5110
+ tristate "Analog Devices AD5110 and similar Digital Potentiometer driver"
+ depends on I2C
+ help
+ Say yes here to build support for the Analog Devices AD5110, AD5112
+ and AD5114 digital potentiometer chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5110.
+
config AD5272
tristate "Analog Devices AD5272 and similar Digital Potentiometer driver"
depends on I2C
diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile
index 091adf3cdd0b..5ebb8e3bbd76 100644
--- a/drivers/iio/potentiometer/Makefile
+++ b/drivers/iio/potentiometer/Makefile
@@ -4,6 +4,7 @@
#
# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AD5110) += ad5110.o
obj-$(CONFIG_AD5272) += ad5272.o
obj-$(CONFIG_DS1803) += ds1803.o
obj-$(CONFIG_MAX5432) += max5432.o
diff --git a/drivers/iio/potentiometer/ad5110.c b/drivers/iio/potentiometer/ad5110.c
new file mode 100644
index 000000000000..d4eeedae56e5
--- /dev/null
+++ b/drivers/iio/potentiometer/ad5110.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Analog Devices AD5110 digital potentiometer driver
+ *
+ * Copyright (C) 2021 Mugilraj Dhavachelvan <dmugil2000@gmail.com>
+ *
+ * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/AD5110_5112_5114.pdf
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+/* AD5110 commands */
+#define AD5110_EEPROM_WR 1
+#define AD5110_RDAC_WR 2
+#define AD5110_SHUTDOWN 3
+#define AD5110_RESET 4
+#define AD5110_RDAC_RD 5
+#define AD5110_EEPROM_RD 6
+
+/* AD5110_EEPROM_RD data */
+#define AD5110_WIPER_POS 0
+#define AD5110_RESISTOR_TOL 1
+
+#define AD5110_WIPER_RESISTANCE 70
+
+struct ad5110_cfg {
+ int max_pos;
+ int kohms;
+ int shift;
+};
+
+enum ad5110_type {
+ AD5110_10,
+ AD5110_80,
+ AD5112_05,
+ AD5112_10,
+ AD5112_80,
+ AD5114_10,
+ AD5114_80,
+};
+
+static const struct ad5110_cfg ad5110_cfg[] = {
+ [AD5110_10] = { .max_pos = 128, .kohms = 10 },
+ [AD5110_80] = { .max_pos = 128, .kohms = 80 },
+ [AD5112_05] = { .max_pos = 64, .kohms = 5, .shift = 1 },
+ [AD5112_10] = { .max_pos = 64, .kohms = 10, .shift = 1 },
+ [AD5112_80] = { .max_pos = 64, .kohms = 80, .shift = 1 },
+ [AD5114_10] = { .max_pos = 32, .kohms = 10, .shift = 2 },
+ [AD5114_80] = { .max_pos = 32, .kohms = 80, .shift = 2 },
+};
+
+struct ad5110_data {
+ struct i2c_client *client;
+ s16 tol; /* resistor tolerance */
+ bool enable;
+ struct mutex lock;
+ const struct ad5110_cfg *cfg;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ u8 buf[2] ____cacheline_aligned;
+};
+
+static const struct iio_chan_spec ad5110_channels[] = {
+ {
+ .type = IIO_RESISTANCE,
+ .output = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_ENABLE),
+ },
+};
+
+static int ad5110_read(struct ad5110_data *data, u8 cmd, int *val)
+{
+ int ret;
+
+ mutex_lock(&data->lock);
+ data->buf[0] = cmd;
+ data->buf[1] = *val;
+
+ ret = i2c_master_send_dmasafe(data->client, data->buf, sizeof(data->buf));
+ if (ret < 0) {
+ goto error;
+ } else if (ret != sizeof(data->buf)) {
+ ret = -EIO;
+ goto error;
+ }
+
+ ret = i2c_master_recv_dmasafe(data->client, data->buf, 1);
+ if (ret < 0) {
+ goto error;
+ } else if (ret != 1) {
+ ret = -EIO;
+ goto error;
+ }
+
+ *val = data->buf[0];
+ ret = 0;
+
+error:
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
+static int ad5110_write(struct ad5110_data *data, u8 cmd, u8 val)
+{
+ int ret;
+
+ mutex_lock(&data->lock);
+ data->buf[0] = cmd;
+ data->buf[1] = val;
+
+ ret = i2c_master_send_dmasafe(data->client, data->buf, sizeof(data->buf));
+ if (ret < 0) {
+ goto error;
+ } else if (ret != sizeof(data->buf)) {
+ ret = -EIO;
+ goto error;
+ }
+
+ ret = 0;
+
+error:
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
+static int ad5110_resistor_tol(struct ad5110_data *data, u8 cmd, int val)
+{
+ int ret;
+
+ ret = ad5110_read(data, cmd, &val);
+ if (ret)
+ return ret;
+
+ data->tol = data->cfg->kohms * (val & GENMASK(6, 0)) * 10 / 8;
+ if (!(val & BIT(7)))
+ data->tol *= -1;
+
+ return 0;
+}
+
+static ssize_t store_eeprom_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct ad5110_data *data = iio_priv(indio_dev);
+ int val = AD5110_WIPER_POS;
+ int ret;
+
+ ret = ad5110_read(data, AD5110_EEPROM_RD, &val);
+ if (ret)
+ return ret;
+
+ val = val >> data->cfg->shift;
+ return iio_format_value(buf, IIO_VAL_INT, 1, &val);
+}
+
+static ssize_t store_eeprom_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct ad5110_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = ad5110_write(data, AD5110_EEPROM_WR, 0);
+ if (ret) {
+ dev_err(&data->client->dev, "RDAC to EEPROM write failed\n");
+ return ret;
+ }
+
+ /* The storing of EEPROM data takes approximately 18 ms. */
+ msleep(20);
+
+ return len;
+}
+
+static IIO_DEVICE_ATTR_RW(store_eeprom, 0);
+
+static struct attribute *ad5110_attributes[] = {
+ &iio_dev_attr_store_eeprom.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group ad5110_attribute_group = {
+ .attrs = ad5110_attributes,
+};
+
+static int ad5110_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ad5110_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = ad5110_read(data, AD5110_RDAC_RD, val);
+ if (ret)
+ return ret;
+
+ *val = *val >> data->cfg->shift;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_OFFSET:
+ *val = AD5110_WIPER_RESISTANCE * data->cfg->max_pos;
+ *val2 = 1000 * data->cfg->kohms + data->tol;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 1000 * data->cfg->kohms + data->tol;
+ *val2 = data->cfg->max_pos;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_ENABLE:
+ *val = data->enable;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad5110_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct ad5110_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (val > data->cfg->max_pos || val < 0)
+ return -EINVAL;
+
+ return ad5110_write(data, AD5110_RDAC_WR, val << data->cfg->shift);
+ case IIO_CHAN_INFO_ENABLE:
+ if (val < 0 || val > 1)
+ return -EINVAL;
+ if (data->enable == val)
+ return 0;
+ ret = ad5110_write(data, AD5110_SHUTDOWN, val ? 0 : 1);
+ if (ret)
+ return ret;
+ data->enable = val;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info ad5110_info = {
+ .read_raw = ad5110_read_raw,
+ .write_raw = ad5110_write_raw,
+ .attrs = &ad5110_attribute_group,
+};
+
+#define AD5110_COMPATIBLE(of_compatible, cfg) { \
+ .compatible = of_compatible, \
+ .data = &ad5110_cfg[cfg], \
+}
+
+static const struct of_device_id ad5110_of_match[] = {
+ AD5110_COMPATIBLE("adi,ad5110-10", AD5110_10),
+ AD5110_COMPATIBLE("adi,ad5110-80", AD5110_80),
+ AD5110_COMPATIBLE("adi,ad5112-05", AD5112_05),
+ AD5110_COMPATIBLE("adi,ad5112-10", AD5112_10),
+ AD5110_COMPATIBLE("adi,ad5112-80", AD5112_80),
+ AD5110_COMPATIBLE("adi,ad5114-10", AD5114_10),
+ AD5110_COMPATIBLE("adi,ad5114-80", AD5114_80),
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad5110_of_match);
+
+static const struct i2c_device_id ad5110_id[] = {
+ { "ad5110-10", AD5110_10 },
+ { "ad5110-80", AD5110_80 },
+ { "ad5112-05", AD5112_05 },
+ { "ad5112-10", AD5112_10 },
+ { "ad5112-80", AD5112_80 },
+ { "ad5114-10", AD5114_10 },
+ { "ad5114-80", AD5114_80 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ad5110_id);
+
+static int ad5110_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct iio_dev *indio_dev;
+ struct ad5110_data *data;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->client = client;
+ mutex_init(&data->lock);
+ data->enable = 1;
+ data->cfg = device_get_match_data(dev);
+
+ /* refresh RDAC register with EEPROM */
+ ret = ad5110_write(data, AD5110_RESET, 0);
+ if (ret) {
+ dev_err(dev, "Refresh RDAC with EEPROM failed\n");
+ return ret;
+ }
+
+ ret = ad5110_resistor_tol(data, AD5110_EEPROM_RD, AD5110_RESISTOR_TOL);
+ if (ret) {
+ dev_err(dev, "Read resistor tolerance failed\n");
+ return ret;
+ }
+
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &ad5110_info;
+ indio_dev->channels = ad5110_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad5110_channels);
+ indio_dev->name = client->name;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static struct i2c_driver ad5110_driver = {
+ .driver = {
+ .name = "ad5110",
+ .of_match_table = ad5110_of_match,
+ },
+ .probe_new = ad5110_probe,
+ .id_table = ad5110_id,
+};
+module_i2c_driver(ad5110_driver);
+
+MODULE_AUTHOR("Mugilraj Dhavachelvan <dmugil2000@gmail.com>");
+MODULE_DESCRIPTION("AD5110 digital potentiometer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/potentiometer/max5481.c b/drivers/iio/potentiometer/max5481.c
index 6e22b538091f..098d144a8fdd 100644
--- a/drivers/iio/potentiometer/max5481.c
+++ b/drivers/iio/potentiometer/max5481.c
@@ -125,6 +125,11 @@ static const struct of_device_id max5481_match[] = {
};
MODULE_DEVICE_TABLE(of, max5481_match);
+static void max5481_wiper_save(void *data)
+{
+ max5481_write_cmd(data, MAX5481_COPY_AB_TO_NV, 0);
+}
+
static int max5481_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
@@ -136,7 +141,6 @@ static int max5481_probe(struct spi_device *spi)
if (!indio_dev)
return -ENOMEM;
- spi_set_drvdata(spi, indio_dev);
data = iio_priv(indio_dev);
data->spi = spi;
@@ -158,18 +162,11 @@ static int max5481_probe(struct spi_device *spi)
if (ret < 0)
return ret;
- return iio_device_register(indio_dev);
-}
-
-static int max5481_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct max5481_data *data = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
+ ret = devm_add_action(&spi->dev, max5481_wiper_save, data);
+ if (ret < 0)
+ return ret;
- /* save wiper reg to NV reg */
- return max5481_write_cmd(data, MAX5481_COPY_AB_TO_NV, 0);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id max5481_id_table[] = {
@@ -187,7 +184,6 @@ static struct spi_driver max5481_driver = {
.of_match_table = max5481_match,
},
.probe = max5481_probe,
- .remove = max5481_remove,
.id_table = max5481_id_table,
};
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 10c52b8df2ba..a9215eb32d70 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -13,17 +13,24 @@
#include <linux/iio/buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
-#define CHANNEL_SCAN_INDEX_PRESSURE 0
+enum {
+ CHANNEL_SCAN_INDEX_PRESSURE,
+ CHANNEL_SCAN_INDEX_TIMESTAMP,
+};
struct press_state {
struct hid_sensor_hub_callbacks callbacks;
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info press_attr;
- u32 press_data;
+ struct {
+ u32 press_data;
+ u64 timestamp __aligned(8);
+ } scan;
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
int value_offset;
+ s64 timestamp;
};
static const u32 press_sensitivity_addresses[] = {
@@ -41,7 +48,9 @@ static const struct iio_chan_spec press_channels[] = {
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_PRESSURE,
- }
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
+
};
/* Adjust channel real bits based on report descriptor */
@@ -154,14 +163,6 @@ static const struct iio_info press_info = {
.write_raw = &press_write_raw,
};
-/* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
- int len)
-{
- dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- iio_push_to_buffers(indio_dev, data);
-}
-
/* Callback handler to send event after all samples are received and captured */
static int press_proc_event(struct hid_sensor_hub_device *hsdev,
unsigned usage_id,
@@ -171,10 +172,13 @@ static int press_proc_event(struct hid_sensor_hub_device *hsdev,
struct press_state *press_state = iio_priv(indio_dev);
dev_dbg(&indio_dev->dev, "press_proc_event\n");
- if (atomic_read(&press_state->common_attributes.data_ready))
- hid_sensor_push_data(indio_dev,
- &press_state->press_data,
- sizeof(press_state->press_data));
+ if (atomic_read(&press_state->common_attributes.data_ready)) {
+ if (!press_state->timestamp)
+ press_state->timestamp = iio_get_time_ns(indio_dev);
+
+ iio_push_to_buffers_with_timestamp(
+ indio_dev, &press_state->scan, press_state->timestamp);
+ }
return 0;
}
@@ -191,9 +195,13 @@ static int press_capture_sample(struct hid_sensor_hub_device *hsdev,
switch (usage_id) {
case HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE:
- press_state->press_data = *(u32 *)raw_data;
+ press_state->scan.press_data = *(u32 *)raw_data;
ret = 0;
break;
+ case HID_USAGE_SENSOR_TIME_TIMESTAMP:
+ press_state->timestamp = hid_sensor_convert_timestamp(
+ &press_state->common_attributes, *(s64 *)raw_data);
+ break;
default:
break;
}
@@ -259,8 +267,8 @@ static int hid_press_probe(struct platform_device *pdev)
return ret;
}
- indio_dev->channels = kmemdup(press_channels, sizeof(press_channels),
- GFP_KERNEL);
+ indio_dev->channels = devm_kmemdup(&pdev->dev, press_channels,
+ sizeof(press_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
@@ -271,7 +279,7 @@ static int hid_press_probe(struct platform_device *pdev)
HID_USAGE_SENSOR_PRESSURE, press_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
- goto error_free_dev_mem;
+ return ret;
}
indio_dev->num_channels =
@@ -286,7 +294,7 @@ static int hid_press_probe(struct platform_device *pdev)
&press_state->common_attributes);
if (ret) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_free_dev_mem;
+ return ret;
}
ret = iio_device_register(indio_dev);
@@ -311,8 +319,6 @@ error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
-error_free_dev_mem:
- kfree(indio_dev->channels);
return ret;
}
@@ -326,7 +332,6 @@ static int hid_press_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
- kfree(indio_dev->channels);
return 0;
}
diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c
index e40b1d7dc129..9538118c9648 100644
--- a/drivers/iio/pressure/hp03.c
+++ b/drivers/iio/pressure/hp03.c
@@ -242,47 +242,26 @@ static int hp03_probe(struct i2c_client *client,
* which has it's dedicated I2C address and contains
* the calibration constants for the sensor.
*/
- priv->eeprom_client = i2c_new_dummy_device(client->adapter, HP03_EEPROM_ADDR);
+ priv->eeprom_client = devm_i2c_new_dummy_device(dev, client->adapter,
+ HP03_EEPROM_ADDR);
if (IS_ERR(priv->eeprom_client)) {
dev_err(dev, "New EEPROM I2C device failed\n");
return PTR_ERR(priv->eeprom_client);
}
- priv->eeprom_regmap = regmap_init_i2c(priv->eeprom_client,
- &hp03_regmap_config);
+ priv->eeprom_regmap = devm_regmap_init_i2c(priv->eeprom_client,
+ &hp03_regmap_config);
if (IS_ERR(priv->eeprom_regmap)) {
dev_err(dev, "Failed to allocate EEPROM regmap\n");
- ret = PTR_ERR(priv->eeprom_regmap);
- goto err_cleanup_eeprom_client;
+ return PTR_ERR(priv->eeprom_regmap);
}
- ret = iio_device_register(indio_dev);
+ ret = devm_iio_device_register(dev, indio_dev);
if (ret) {
dev_err(dev, "Failed to register IIO device\n");
- goto err_cleanup_eeprom_regmap;
+ return ret;
}
- i2c_set_clientdata(client, indio_dev);
-
- return 0;
-
-err_cleanup_eeprom_regmap:
- regmap_exit(priv->eeprom_regmap);
-
-err_cleanup_eeprom_client:
- i2c_unregister_device(priv->eeprom_client);
- return ret;
-}
-
-static int hp03_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct hp03_priv *priv = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- regmap_exit(priv->eeprom_regmap);
- i2c_unregister_device(priv->eeprom_client);
-
return 0;
}
@@ -304,7 +283,6 @@ static struct i2c_driver hp03_driver = {
.of_match_table = hp03_of_match,
},
.probe = hp03_probe,
- .remove = hp03_remove,
.id_table = hp03_id,
};
module_i2c_driver(hp03_driver);
diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h
index 9417b3bd7513..156e6a72dc5c 100644
--- a/drivers/iio/pressure/st_pressure.h
+++ b/drivers/iio/pressure/st_pressure.h
@@ -43,7 +43,6 @@ static __maybe_unused const struct st_sensors_platform_data default_press_pdata
#ifdef CONFIG_IIO_BUFFER
int st_press_allocate_ring(struct iio_dev *indio_dev);
-void st_press_deallocate_ring(struct iio_dev *indio_dev);
int st_press_trig_set_state(struct iio_trigger *trig, bool state);
#define ST_PRESS_TRIGGER_SET_STATE (&st_press_trig_set_state)
#else /* CONFIG_IIO_BUFFER */
@@ -51,10 +50,6 @@ static inline int st_press_allocate_ring(struct iio_dev *indio_dev)
{
return 0;
}
-
-static inline void st_press_deallocate_ring(struct iio_dev *indio_dev)
-{
-}
#define ST_PRESS_TRIGGER_SET_STATE NULL
#endif /* CONFIG_IIO_BUFFER */
diff --git a/drivers/iio/pressure/st_pressure_buffer.c b/drivers/iio/pressure/st_pressure_buffer.c
index 7cf6f06797e1..25dbd5476b26 100644
--- a/drivers/iio/pressure/st_pressure_buffer.c
+++ b/drivers/iio/pressure/st_pressure_buffer.c
@@ -9,14 +9,9 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/common/st_sensors.h>
@@ -46,13 +41,8 @@ static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = {
int st_press_allocate_ring(struct iio_dev *indio_dev)
{
- return iio_triggered_buffer_setup(indio_dev, NULL,
- &st_sensors_trigger_handler, &st_press_buffer_setup_ops);
-}
-
-void st_press_deallocate_ring(struct iio_dev *indio_dev)
-{
- iio_triggered_buffer_cleanup(indio_dev);
+ return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
+ NULL, &st_sensors_trigger_handler, &st_press_buffer_setup_ops);
}
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index 7912b5a68395..ab1c17fac807 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -9,17 +9,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
-#include <linux/iio/buffer.h>
#include <asm/unaligned.h>
#include <linux/iio/common/st_sensors.h>
@@ -724,7 +718,7 @@ int st_press_common_probe(struct iio_dev *indio_dev)
err = st_sensors_allocate_trigger(indio_dev,
ST_PRESS_TRIGGER_OPS);
if (err < 0)
- goto st_press_probe_trigger_error;
+ return err;
}
err = iio_device_register(indio_dev);
@@ -739,8 +733,6 @@ int st_press_common_probe(struct iio_dev *indio_dev)
st_press_device_register_error:
if (press_data->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
-st_press_probe_trigger_error:
- st_press_deallocate_ring(indio_dev);
return err;
}
EXPORT_SYMBOL(st_press_common_probe);
@@ -752,8 +744,6 @@ void st_press_common_remove(struct iio_dev *indio_dev)
iio_device_unregister(indio_dev);
if (press_data->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
-
- st_press_deallocate_ring(indio_dev);
}
EXPORT_SYMBOL(st_press_common_remove);
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index f0a5af314ceb..52fa98f24478 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -7,9 +7,10 @@
* Denis Ciocca <denis.ciocca@st.com>
*/
+#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c
index b48cf7d01cd7..ee393df54cee 100644
--- a/drivers/iio/pressure/st_pressure_spi.c
+++ b/drivers/iio/pressure/st_pressure_spi.c
@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
diff --git a/drivers/iio/proximity/rfd77402.c b/drivers/iio/proximity/rfd77402.c
index 7a0472323f17..8c06d02139b6 100644
--- a/drivers/iio/proximity/rfd77402.c
+++ b/drivers/iio/proximity/rfd77402.c
@@ -90,18 +90,18 @@ static const struct iio_chan_spec rfd77402_channels[] = {
},
};
-static int rfd77402_set_state(struct rfd77402_data *data, u8 state, u16 check)
+static int rfd77402_set_state(struct i2c_client *client, u8 state, u16 check)
{
int ret;
- ret = i2c_smbus_write_byte_data(data->client, RFD77402_CMD_R,
+ ret = i2c_smbus_write_byte_data(client, RFD77402_CMD_R,
state | RFD77402_CMD_VALID);
if (ret < 0)
return ret;
usleep_range(10000, 20000);
- ret = i2c_smbus_read_word_data(data->client, RFD77402_STATUS_R);
+ ret = i2c_smbus_read_word_data(client, RFD77402_STATUS_R);
if (ret < 0)
return ret;
if ((ret & RFD77402_STATUS_PM_MASK) != check)
@@ -110,24 +110,24 @@ static int rfd77402_set_state(struct rfd77402_data *data, u8 state, u16 check)
return 0;
}
-static int rfd77402_measure(struct rfd77402_data *data)
+static int rfd77402_measure(struct i2c_client *client)
{
int ret;
int tries = 10;
- ret = rfd77402_set_state(data, RFD77402_CMD_MCPU_ON,
+ ret = rfd77402_set_state(client, RFD77402_CMD_MCPU_ON,
RFD77402_STATUS_MCPU_ON);
if (ret < 0)
return ret;
- ret = i2c_smbus_write_byte_data(data->client, RFD77402_CMD_R,
+ ret = i2c_smbus_write_byte_data(client, RFD77402_CMD_R,
RFD77402_CMD_SINGLE |
RFD77402_CMD_VALID);
if (ret < 0)
goto err;
while (tries-- > 0) {
- ret = i2c_smbus_read_byte_data(data->client, RFD77402_ICSR);
+ ret = i2c_smbus_read_byte_data(client, RFD77402_ICSR);
if (ret < 0)
goto err;
if (ret & RFD77402_ICSR_RESULT)
@@ -140,7 +140,7 @@ static int rfd77402_measure(struct rfd77402_data *data)
goto err;
}
- ret = i2c_smbus_read_word_data(data->client, RFD77402_RESULT_R);
+ ret = i2c_smbus_read_word_data(client, RFD77402_RESULT_R);
if (ret < 0)
goto err;
@@ -153,7 +153,7 @@ static int rfd77402_measure(struct rfd77402_data *data)
return (ret & RFD77402_RESULT_DIST_MASK) >> 2;
err:
- rfd77402_set_state(data, RFD77402_CMD_MCPU_OFF,
+ rfd77402_set_state(client, RFD77402_CMD_MCPU_OFF,
RFD77402_STATUS_MCPU_OFF);
return ret;
}
@@ -168,7 +168,7 @@ static int rfd77402_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->lock);
- ret = rfd77402_measure(data);
+ ret = rfd77402_measure(data->client);
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
@@ -188,23 +188,23 @@ static const struct iio_info rfd77402_info = {
.read_raw = rfd77402_read_raw,
};
-static int rfd77402_init(struct rfd77402_data *data)
+static int rfd77402_init(struct i2c_client *client)
{
int ret, i;
- ret = rfd77402_set_state(data, RFD77402_CMD_STANDBY,
+ ret = rfd77402_set_state(client, RFD77402_CMD_STANDBY,
RFD77402_STATUS_STANDBY);
if (ret < 0)
return ret;
/* configure INT pad as push-pull, active low */
- ret = i2c_smbus_write_byte_data(data->client, RFD77402_ICSR,
+ ret = i2c_smbus_write_byte_data(client, RFD77402_ICSR,
RFD77402_ICSR_INT_MODE);
if (ret < 0)
return ret;
/* I2C configuration */
- ret = i2c_smbus_write_word_data(data->client, RFD77402_I2C_INIT_CFG,
+ ret = i2c_smbus_write_word_data(client, RFD77402_I2C_INIT_CFG,
RFD77402_I2C_ADDR_INCR |
RFD77402_I2C_DATA_INCR |
RFD77402_I2C_HOST_DEBUG |
@@ -213,45 +213,50 @@ static int rfd77402_init(struct rfd77402_data *data)
return ret;
/* set initialization */
- ret = i2c_smbus_write_word_data(data->client, RFD77402_PMU_CFG, 0x0500);
+ ret = i2c_smbus_write_word_data(client, RFD77402_PMU_CFG, 0x0500);
if (ret < 0)
return ret;
- ret = rfd77402_set_state(data, RFD77402_CMD_MCPU_OFF,
+ ret = rfd77402_set_state(client, RFD77402_CMD_MCPU_OFF,
RFD77402_STATUS_MCPU_OFF);
if (ret < 0)
return ret;
/* set initialization */
- ret = i2c_smbus_write_word_data(data->client, RFD77402_PMU_CFG, 0x0600);
+ ret = i2c_smbus_write_word_data(client, RFD77402_PMU_CFG, 0x0600);
if (ret < 0)
return ret;
- ret = rfd77402_set_state(data, RFD77402_CMD_MCPU_ON,
+ ret = rfd77402_set_state(client, RFD77402_CMD_MCPU_ON,
RFD77402_STATUS_MCPU_ON);
if (ret < 0)
return ret;
for (i = 0; i < ARRAY_SIZE(rf77402_tof_config); i++) {
- ret = i2c_smbus_write_word_data(data->client,
+ ret = i2c_smbus_write_word_data(client,
rf77402_tof_config[i].reg,
rf77402_tof_config[i].val);
if (ret < 0)
return ret;
}
- ret = rfd77402_set_state(data, RFD77402_CMD_STANDBY,
+ ret = rfd77402_set_state(client, RFD77402_CMD_STANDBY,
RFD77402_STATUS_STANDBY);
return ret;
}
-static int rfd77402_powerdown(struct rfd77402_data *data)
+static int rfd77402_powerdown(struct i2c_client *client)
{
- return rfd77402_set_state(data, RFD77402_CMD_STANDBY,
+ return rfd77402_set_state(client, RFD77402_CMD_STANDBY,
RFD77402_STATUS_STANDBY);
}
+static void rfd77402_disable(void *client)
+{
+ rfd77402_powerdown(client);
+}
+
static int rfd77402_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -270,7 +275,6 @@ static int rfd77402_probe(struct i2c_client *client,
return -ENOMEM;
data = iio_priv(indio_dev);
- i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->lock);
@@ -280,46 +284,26 @@ static int rfd77402_probe(struct i2c_client *client,
indio_dev->name = RFD77402_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = rfd77402_init(data);
+ ret = rfd77402_init(client);
if (ret < 0)
return ret;
- ret = iio_device_register(indio_dev);
+ ret = devm_add_action_or_reset(&client->dev, rfd77402_disable, client);
if (ret)
- goto err_powerdown;
-
- return 0;
-
-err_powerdown:
- rfd77402_powerdown(data);
- return ret;
-}
-
-static int rfd77402_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
- iio_device_unregister(indio_dev);
- rfd77402_powerdown(iio_priv(indio_dev));
+ return ret;
- return 0;
+ return devm_iio_device_register(&client->dev, indio_dev);
}
#ifdef CONFIG_PM_SLEEP
static int rfd77402_suspend(struct device *dev)
{
- struct rfd77402_data *data = iio_priv(i2c_get_clientdata(
- to_i2c_client(dev)));
-
- return rfd77402_powerdown(data);
+ return rfd77402_powerdown(to_i2c_client(dev));
}
static int rfd77402_resume(struct device *dev)
{
- struct rfd77402_data *data = iio_priv(i2c_get_clientdata(
- to_i2c_client(dev)));
-
- return rfd77402_init(data);
+ return rfd77402_init(to_i2c_client(dev));
}
#endif
@@ -337,7 +321,6 @@ static struct i2c_driver rfd77402_driver = {
.pm = &rfd77402_pm_ops,
},
.probe = rfd77402_probe,
- .remove = rfd77402_remove,
.id_table = rfd77402_id,
};
diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c
index 175f3b7c61d7..a3fdb59b06d2 100644
--- a/drivers/iio/proximity/sx9310.c
+++ b/drivers/iio/proximity/sx9310.c
@@ -20,6 +20,7 @@
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@@ -1221,10 +1222,9 @@ static int sx9310_init_compensation(struct iio_dev *indio_dev)
}
static const struct sx9310_reg_default *
-sx9310_get_default_reg(struct sx9310_data *data, int idx,
+sx9310_get_default_reg(struct device *dev, int idx,
struct sx9310_reg_default *reg_def)
{
- const struct device_node *np = data->client->dev.of_node;
u32 combined[SX9310_NUM_CHANNELS];
u32 start = 0, raw = 0, pos = 0;
unsigned long comb_mask = 0;
@@ -1232,40 +1232,24 @@ sx9310_get_default_reg(struct sx9310_data *data, int idx,
const char *res;
memcpy(reg_def, &sx9310_default_regs[idx], sizeof(*reg_def));
- if (!np)
- return reg_def;
-
switch (reg_def->reg) {
case SX9310_REG_PROX_CTRL2:
- if (of_property_read_bool(np, "semtech,cs0-ground")) {
+ if (device_property_read_bool(dev, "semtech,cs0-ground")) {
reg_def->def &= ~SX9310_REG_PROX_CTRL2_SHIELDEN_MASK;
reg_def->def |= SX9310_REG_PROX_CTRL2_SHIELDEN_GROUND;
}
- count = of_property_count_elems_of_size(np, "semtech,combined-sensors",
- sizeof(u32));
- if (count > 0 && count <= ARRAY_SIZE(combined)) {
- ret = of_property_read_u32_array(np, "semtech,combined-sensors",
- combined, count);
- if (ret)
- break;
- } else {
- /*
- * Either the property does not exist in the DT or the
- * number of entries is incorrect.
- */
+ count = device_property_count_u32(dev, "semtech,combined-sensors");
+ if (count < 0 || count > ARRAY_SIZE(combined))
break;
- }
- for (i = 0; i < count; i++) {
- if (combined[i] >= SX9310_NUM_CHANNELS) {
- /* Invalid sensor (invalid DT). */
- break;
- }
- comb_mask |= BIT(combined[i]);
- }
- if (i < count)
+ ret = device_property_read_u32_array(dev, "semtech,combined-sensors",
+ combined, count);
+ if (ret)
break;
+ for (i = 0; i < count; i++)
+ comb_mask |= BIT(combined[i]);
+
reg_def->def &= ~SX9310_REG_PROX_CTRL2_COMBMODE_MASK;
if (comb_mask == (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1_CS2_CS3;
@@ -1278,7 +1262,7 @@ sx9310_get_default_reg(struct sx9310_data *data, int idx,
break;
case SX9310_REG_PROX_CTRL4:
- ret = of_property_read_string(np, "semtech,resolution", &res);
+ ret = device_property_read_string(dev, "semtech,resolution", &res);
if (ret)
break;
@@ -1302,7 +1286,7 @@ sx9310_get_default_reg(struct sx9310_data *data, int idx,
break;
case SX9310_REG_PROX_CTRL5:
- ret = of_property_read_u32(np, "semtech,startup-sensor", &start);
+ ret = device_property_read_u32(dev, "semtech,startup-sensor", &start);
if (ret) {
start = FIELD_GET(SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK,
reg_def->def);
@@ -1312,7 +1296,7 @@ sx9310_get_default_reg(struct sx9310_data *data, int idx,
reg_def->def |= FIELD_PREP(SX9310_REG_PROX_CTRL5_STARTUPSENS_MASK,
start);
- ret = of_property_read_u32(np, "semtech,proxraw-strength", &raw);
+ ret = device_property_read_u32(dev, "semtech,proxraw-strength", &raw);
if (ret) {
raw = FIELD_GET(SX9310_REG_PROX_CTRL5_RAWFILT_MASK,
reg_def->def);
@@ -1325,7 +1309,7 @@ sx9310_get_default_reg(struct sx9310_data *data, int idx,
raw);
break;
case SX9310_REG_PROX_CTRL7:
- ret = of_property_read_u32(np, "semtech,avg-pos-strength", &pos);
+ ret = device_property_read_u32(dev, "semtech,avg-pos-strength", &pos);
if (ret)
break;
@@ -1361,7 +1345,7 @@ static int sx9310_init_device(struct iio_dev *indio_dev)
/* Program some sane defaults. */
for (i = 0; i < ARRAY_SIZE(sx9310_default_regs); i++) {
- initval = sx9310_get_default_reg(data, i, &tmp);
+ initval = sx9310_get_default_reg(&indio_dev->dev, i, &tmp);
ret = regmap_write(data->regmap, initval->reg, initval->def);
if (ret)
return ret;
diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
index 43817f6b3086..ff83638db16f 100644
--- a/drivers/iio/proximity/vcnl3020.c
+++ b/drivers/iio/proximity/vcnl3020.c
@@ -2,8 +2,6 @@
/*
* Support for Vishay VCNL3020 proximity sensor on i2c bus.
* Based on Vishay VCNL4000 driver code.
- *
- * TODO: interrupts.
*/
#include <linux/module.h>
@@ -11,9 +9,10 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/regmap.h>
+#include <linux/interrupt.h>
#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
#define VCNL3020_PROD_ID 0x21
@@ -37,6 +36,21 @@
* measurement
*/
+/* Enables periodic proximity measurement */
+#define VCNL_PS_EN BIT(1)
+
+/* Enables state machine and LP oscillator for self timed measurements */
+#define VCNL_PS_SELFTIMED_EN BIT(0)
+
+/* Bit masks for ICR */
+
+/* Enable interrupts on low or high thresholds */
+#define VCNL_ICR_THRES_EN BIT(1)
+
+/* Bit masks for ISR */
+#define VCNL_INT_TH_HI BIT(0) /* High threshold hit */
+#define VCNL_INT_TH_LOW BIT(1) /* Low threshold hit */
+
#define VCNL_ON_DEMAND_TIMEOUT_US 100000
#define VCNL_POLL_US 20000
@@ -57,12 +71,14 @@ static const int vcnl3020_prox_sampling_frequency[][2] = {
* @dev: vcnl3020 device.
* @rev: revision id.
* @lock: lock for protecting access to device hardware registers.
+ * @buf: DMA safe __be16 buffer.
*/
struct vcnl3020_data {
struct regmap *regmap;
struct device *dev;
u8 rev;
struct mutex lock;
+ __be16 buf ____cacheline_aligned;
};
/**
@@ -140,14 +156,34 @@ static int vcnl3020_init(struct vcnl3020_data *data)
vcnl3020_led_current_property);
};
+static bool vcnl3020_is_in_periodic_mode(struct vcnl3020_data *data)
+{
+ int rc;
+ unsigned int cmd;
+
+ rc = regmap_read(data->regmap, VCNL_COMMAND, &cmd);
+ if (rc) {
+ dev_err(data->dev,
+ "Error (%d) reading command register\n", rc);
+ return false;
+ }
+
+ return !!(cmd & VCNL_PS_SELFTIMED_EN);
+}
+
static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val)
{
int rc;
unsigned int reg;
- __be16 res;
mutex_lock(&data->lock);
+ /* Protect against event capture. */
+ if (vcnl3020_is_in_periodic_mode(data)) {
+ rc = -EBUSY;
+ goto err_unlock;
+ }
+
rc = regmap_write(data->regmap, VCNL_COMMAND, VCNL_PS_OD);
if (rc)
goto err_unlock;
@@ -163,12 +199,12 @@ static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val)
}
/* high & low result bytes read */
- rc = regmap_bulk_read(data->regmap, VCNL_PS_RESULT_HI, &res,
- sizeof(res));
+ rc = regmap_bulk_read(data->regmap, VCNL_PS_RESULT_HI, &data->buf,
+ sizeof(data->buf));
if (rc)
goto err_unlock;
- *val = be16_to_cpu(res);
+ *val = be16_to_cpu(data->buf);
err_unlock:
mutex_unlock(&data->lock);
@@ -200,6 +236,15 @@ static int vcnl3020_write_proxy_samp_freq(struct vcnl3020_data *data, int val,
{
unsigned int i;
int index = -1;
+ int rc;
+
+ mutex_lock(&data->lock);
+
+ /* Protect against event capture. */
+ if (vcnl3020_is_in_periodic_mode(data)) {
+ rc = -EBUSY;
+ goto err_unlock;
+ }
for (i = 0; i < ARRAY_SIZE(vcnl3020_prox_sampling_frequency); i++) {
if (val == vcnl3020_prox_sampling_frequency[i][0] &&
@@ -209,18 +254,250 @@ static int vcnl3020_write_proxy_samp_freq(struct vcnl3020_data *data, int val,
}
}
- if (index < 0)
+ if (index < 0) {
+ rc = -EINVAL;
+ goto err_unlock;
+ }
+
+ rc = regmap_write(data->regmap, VCNL_PROXIMITY_RATE, index);
+ if (rc)
+ dev_err(data->dev,
+ "Error (%d) writing proximity rate register\n", rc);
+
+err_unlock:
+ mutex_unlock(&data->lock);
+
+ return rc;
+}
+
+static bool vcnl3020_is_thr_enabled(struct vcnl3020_data *data)
+{
+ int rc;
+ unsigned int icr;
+
+ rc = regmap_read(data->regmap, VCNL_PS_ICR, &icr);
+ if (rc) {
+ dev_err(data->dev,
+ "Error (%d) reading ICR register\n", rc);
+ return false;
+ }
+
+ return !!(icr & VCNL_ICR_THRES_EN);
+}
+
+static int vcnl3020_read_event(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ int rc;
+ struct vcnl3020_data *data = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ rc = regmap_bulk_read(data->regmap, VCNL_PS_HI_THR_HI,
+ &data->buf, sizeof(data->buf));
+ if (rc < 0)
+ return rc;
+ *val = be16_to_cpu(data->buf);
+ return IIO_VAL_INT;
+ case IIO_EV_DIR_FALLING:
+ rc = regmap_bulk_read(data->regmap, VCNL_PS_LO_THR_HI,
+ &data->buf, sizeof(data->buf));
+ if (rc < 0)
+ return rc;
+ *val = be16_to_cpu(data->buf);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ default:
return -EINVAL;
+ }
+}
+
+static int vcnl3020_write_event(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ int rc;
+ struct vcnl3020_data *data = iio_priv(indio_dev);
+
+ mutex_lock(&data->lock);
- return regmap_write(data->regmap, VCNL_PROXIMITY_RATE, index);
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ /* 16 bit word/ low * high */
+ data->buf = cpu_to_be16(val);
+ rc = regmap_bulk_write(data->regmap, VCNL_PS_HI_THR_HI,
+ &data->buf, sizeof(data->buf));
+ if (rc < 0)
+ goto err_unlock;
+ rc = IIO_VAL_INT;
+ goto err_unlock;
+ case IIO_EV_DIR_FALLING:
+ data->buf = cpu_to_be16(val);
+ rc = regmap_bulk_write(data->regmap, VCNL_PS_LO_THR_HI,
+ &data->buf, sizeof(data->buf));
+ if (rc < 0)
+ goto err_unlock;
+ rc = IIO_VAL_INT;
+ goto err_unlock;
+ default:
+ rc = -EINVAL;
+ goto err_unlock;
+ }
+ default:
+ rc = -EINVAL;
+ goto err_unlock;
+ }
+err_unlock:
+ mutex_unlock(&data->lock);
+
+ return rc;
}
+static int vcnl3020_enable_periodic(struct iio_dev *indio_dev,
+ struct vcnl3020_data *data)
+{
+ int rc;
+ int cmd;
+
+ mutex_lock(&data->lock);
+
+ /* Enable periodic measurement of proximity data. */
+ cmd = VCNL_PS_EN | VCNL_PS_SELFTIMED_EN;
+
+ rc = regmap_write(data->regmap, VCNL_COMMAND, cmd);
+ if (rc) {
+ dev_err(data->dev,
+ "Error (%d) writing command register\n", rc);
+ goto err_unlock;
+ }
+
+ /*
+ * Enable interrupts on threshold, for proximity data by
+ * default.
+ */
+ rc = regmap_write(data->regmap, VCNL_PS_ICR, VCNL_ICR_THRES_EN);
+ if (rc)
+ dev_err(data->dev,
+ "Error (%d) reading ICR register\n", rc);
+
+err_unlock:
+ mutex_unlock(&data->lock);
+
+ return rc;
+}
+
+static int vcnl3020_disable_periodic(struct iio_dev *indio_dev,
+ struct vcnl3020_data *data)
+{
+ int rc;
+
+ mutex_lock(&data->lock);
+
+ rc = regmap_write(data->regmap, VCNL_COMMAND, 0);
+ if (rc) {
+ dev_err(data->dev,
+ "Error (%d) writing command register\n", rc);
+ goto err_unlock;
+ }
+
+ rc = regmap_write(data->regmap, VCNL_PS_ICR, 0);
+ if (rc) {
+ dev_err(data->dev,
+ "Error (%d) writing ICR register\n", rc);
+ goto err_unlock;
+ }
+
+ /* Clear interrupt flag bit */
+ rc = regmap_write(data->regmap, VCNL_ISR, 0);
+ if (rc)
+ dev_err(data->dev,
+ "Error (%d) writing ISR register\n", rc);
+
+err_unlock:
+ mutex_unlock(&data->lock);
+
+ return rc;
+}
+
+static int vcnl3020_config_threshold(struct iio_dev *indio_dev, bool state)
+{
+ struct vcnl3020_data *data = iio_priv(indio_dev);
+
+ if (state) {
+ return vcnl3020_enable_periodic(indio_dev, data);
+ } else {
+ if (!vcnl3020_is_thr_enabled(data))
+ return 0;
+ return vcnl3020_disable_periodic(indio_dev, data);
+ }
+}
+
+static int vcnl3020_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ int state)
+{
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ return vcnl3020_config_threshold(indio_dev, state);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vcnl3020_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct vcnl3020_data *data = iio_priv(indio_dev);
+
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ return vcnl3020_is_thr_enabled(data);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_event_spec vcnl3020_event_spec[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
static const struct iio_chan_spec vcnl3020_channels[] = {
{
.type = IIO_PROXIMITY,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SAMP_FREQ),
.info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = vcnl3020_event_spec,
+ .num_event_specs = ARRAY_SIZE(vcnl3020_event_spec),
},
};
@@ -251,17 +528,11 @@ static int vcnl3020_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
- int rc;
struct vcnl3020_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
- rc = iio_device_claim_direct_mode(indio_dev);
- if (rc)
- return rc;
- rc = vcnl3020_write_proxy_samp_freq(data, val, val2);
- iio_device_release_direct_mode(indio_dev);
- return rc;
+ return vcnl3020_write_proxy_samp_freq(data, val, val2);
default:
return -EINVAL;
}
@@ -287,6 +558,10 @@ static const struct iio_info vcnl3020_info = {
.read_raw = vcnl3020_read_raw,
.write_raw = vcnl3020_write_raw,
.read_avail = vcnl3020_read_avail,
+ .read_event_value = vcnl3020_read_event,
+ .write_event_value = vcnl3020_write_event,
+ .read_event_config = vcnl3020_read_event_config,
+ .write_event_config = vcnl3020_write_event_config,
};
static const struct regmap_config vcnl3020_regmap_config = {
@@ -295,6 +570,37 @@ static const struct regmap_config vcnl3020_regmap_config = {
.max_register = VCNL_PS_MOD_ADJ,
};
+static irqreturn_t vcnl3020_handle_irq_thread(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct vcnl3020_data *data = iio_priv(indio_dev);
+ unsigned int isr;
+ int rc;
+
+ rc = regmap_read(data->regmap, VCNL_ISR, &isr);
+ if (rc) {
+ dev_err(data->dev, "Error (%d) reading reg (0x%x)\n",
+ rc, VCNL_ISR);
+ return IRQ_HANDLED;
+ }
+
+ if (!(isr & VCNL_ICR_THRES_EN))
+ return IRQ_NONE;
+
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns(indio_dev));
+
+ rc = regmap_write(data->regmap, VCNL_ISR, isr & VCNL_ICR_THRES_EN);
+ if (rc)
+ dev_err(data->dev, "Error (%d) writing in reg (0x%x)\n",
+ rc, VCNL_ISR);
+
+ return IRQ_HANDLED;
+}
+
static int vcnl3020_probe(struct i2c_client *client)
{
struct vcnl3020_data *data;
@@ -327,6 +633,19 @@ static int vcnl3020_probe(struct i2c_client *client)
indio_dev->name = "vcnl3020";
indio_dev->modes = INDIO_DIRECT_MODE;
+ if (client->irq) {
+ rc = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, vcnl3020_handle_irq_thread,
+ IRQF_ONESHOT, indio_dev->name,
+ indio_dev);
+ if (rc) {
+ dev_err(&client->dev,
+ "Error (%d) irq request failed (%u)\n", rc,
+ client->irq);
+ return rc;
+ }
+ }
+
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
index 3b5ba26d7d86..3b4a0e60e605 100644
--- a/drivers/iio/temperature/ltc2983.c
+++ b/drivers/iio/temperature/ltc2983.c
@@ -89,6 +89,8 @@
#define LTC2983_STATUS_START_MASK BIT(7)
#define LTC2983_STATUS_START(x) FIELD_PREP(LTC2983_STATUS_START_MASK, x)
+#define LTC2983_STATUS_UP_MASK GENMASK(7, 6)
+#define LTC2983_STATUS_UP(reg) FIELD_GET(LTC2983_STATUS_UP_MASK, reg)
#define LTC2983_STATUS_CHAN_SEL_MASK GENMASK(4, 0)
#define LTC2983_STATUS_CHAN_SEL(x) \
@@ -1362,17 +1364,16 @@ put_child:
static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
{
- u32 iio_chan_t = 0, iio_chan_v = 0, chan, iio_idx = 0;
+ u32 iio_chan_t = 0, iio_chan_v = 0, chan, iio_idx = 0, status;
int ret;
- unsigned long time;
-
- /* make sure the device is up */
- time = wait_for_completion_timeout(&st->completion,
- msecs_to_jiffies(250));
- if (!time) {
+ /* make sure the device is up: start bit (7) is 0 and done bit (6) is 1 */
+ ret = regmap_read_poll_timeout(st->regmap, LTC2983_STATUS_REG, status,
+ LTC2983_STATUS_UP(status) == 1, 25000,
+ 25000 * 10);
+ if (ret) {
dev_err(&st->spi->dev, "Device startup timed out\n");
- return -ETIMEDOUT;
+ return ret;
}
st->iio_chan = devm_kzalloc(&st->spi->dev,
@@ -1492,10 +1493,11 @@ static int ltc2983_probe(struct spi_device *spi)
ret = ltc2983_parse_dt(st);
if (ret)
return ret;
- /*
- * let's request the irq now so it is used to sync the device
- * startup in ltc2983_setup()
- */
+
+ ret = ltc2983_setup(st, true);
+ if (ret)
+ return ret;
+
ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler,
IRQF_TRIGGER_RISING, name, st);
if (ret) {
@@ -1503,10 +1505,6 @@ static int ltc2983_probe(struct spi_device *spi)
return ret;
}
- ret = ltc2983_setup(st, true);
- if (ret)
- return ret;
-
indio_dev->name = name;
indio_dev->num_channels = st->iio_channels;
indio_dev->channels = st->iio_chan;
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index 54976c7dad92..e4943a0bc9aa 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -193,6 +193,25 @@ static bool tmp006_check_identification(struct i2c_client *client)
return mid == TMP006_MANUFACTURER_MAGIC && did == TMP006_DEVICE_MAGIC;
}
+static int tmp006_power(struct device *dev, bool up)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct tmp006_data *data = iio_priv(indio_dev);
+
+ if (up)
+ data->config |= TMP006_CONFIG_MOD_MASK;
+ else
+ data->config &= ~TMP006_CONFIG_MOD_MASK;
+
+ return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
+ data->config);
+}
+
+static void tmp006_powerdown_cleanup(void *dev)
+{
+ tmp006_power(dev, false);
+}
+
static int tmp006_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -228,38 +247,29 @@ static int tmp006_probe(struct i2c_client *client,
return ret;
data->config = ret;
- return iio_device_register(indio_dev);
-}
-
-static int tmp006_powerdown(struct tmp006_data *data)
-{
- return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
- data->config & ~TMP006_CONFIG_MOD_MASK);
-}
-
-static int tmp006_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ if ((ret & TMP006_CONFIG_MOD_MASK) != TMP006_CONFIG_MOD_MASK) {
+ ret = tmp006_power(&client->dev, true);
+ if (ret < 0)
+ return ret;
+ }
- iio_device_unregister(indio_dev);
- tmp006_powerdown(iio_priv(indio_dev));
+ ret = devm_add_action_or_reset(&client->dev, tmp006_powerdown_cleanup,
+ &client->dev);
+ if (ret < 0)
+ return ret;
- return 0;
+ return devm_iio_device_register(&client->dev, indio_dev);
}
#ifdef CONFIG_PM_SLEEP
static int tmp006_suspend(struct device *dev)
{
- struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
- return tmp006_powerdown(iio_priv(indio_dev));
+ return tmp006_power(dev, false);
}
static int tmp006_resume(struct device *dev)
{
- struct tmp006_data *data = iio_priv(i2c_get_clientdata(
- to_i2c_client(dev)));
- return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
- data->config | TMP006_CONFIG_MOD_MASK);
+ return tmp006_power(dev, true);
}
#endif
@@ -277,7 +287,6 @@ static struct i2c_driver tmp006_driver = {
.pm = &tmp006_pm_ops,
},
.probe = tmp006_probe,
- .remove = tmp006_remove,
.id_table = tmp006_id,
};
module_i2c_driver(tmp006_driver);
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index c9e9fc81447e..0c98dd3dee67 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -1429,7 +1429,7 @@ int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr,
EXPORT_SYMBOL(rdma_read_gid_l2_fields);
static int config_non_roce_gid_cache(struct ib_device *device,
- u32 port, int gid_tbl_len)
+ u32 port, struct ib_port_attr *tprops)
{
struct ib_gid_attr gid_attr = {};
struct ib_gid_table *table;
@@ -1441,7 +1441,7 @@ static int config_non_roce_gid_cache(struct ib_device *device,
table = rdma_gid_table(device, port);
mutex_lock(&table->lock);
- for (i = 0; i < gid_tbl_len; ++i) {
+ for (i = 0; i < tprops->gid_tbl_len; ++i) {
if (!device->ops.query_gid)
continue;
ret = device->ops.query_gid(device, port, i, &gid_attr.gid);
@@ -1452,6 +1452,8 @@ static int config_non_roce_gid_cache(struct ib_device *device,
goto err;
}
gid_attr.index = i;
+ tprops->subnet_prefix =
+ be64_to_cpu(gid_attr.gid.global.subnet_prefix);
add_modify_gid(table, &gid_attr);
}
err:
@@ -1484,7 +1486,7 @@ ib_cache_update(struct ib_device *device, u32 port, bool update_gids,
if (!rdma_protocol_roce(device, port) && update_gids) {
ret = config_non_roce_gid_cache(device, port,
- tprops->gid_tbl_len);
+ tprops);
if (ret)
goto err;
}
@@ -1619,8 +1621,6 @@ int ib_cache_setup_one(struct ib_device *device)
u32 p;
int err;
- rwlock_init(&device->cache_lock);
-
err = gid_table_setup_one(device);
if (err)
return err;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 5d3b8b8d163d..c40791baced5 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -3132,6 +3132,9 @@ int rdma_resolve_route(struct rdma_cm_id *id, unsigned long timeout_ms)
struct rdma_id_private *id_priv;
int ret;
+ if (!timeout_ms)
+ return -EINVAL;
+
id_priv = container_of(id, struct rdma_id_private, id);
if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_RESOLVED, RDMA_CM_ROUTE_QUERY))
return -EINVAL;
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 647cca4e0240..f66f48d860ec 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -316,45 +316,13 @@ struct ib_device *ib_device_get_by_index(const struct net *net, u32 index);
void nldev_init(void);
void nldev_exit(void);
-static inline struct ib_qp *
-_ib_create_qp(struct ib_device *dev, struct ib_pd *pd,
- struct ib_qp_init_attr *attr, struct ib_udata *udata,
- struct ib_uqp_object *uobj, const char *caller)
-{
- struct ib_qp *qp;
-
- if (!dev->ops.create_qp)
- return ERR_PTR(-EOPNOTSUPP);
-
- qp = dev->ops.create_qp(pd, attr, udata);
- if (IS_ERR(qp))
- return qp;
-
- qp->device = dev;
- qp->pd = pd;
- qp->uobject = uobj;
- qp->real_qp = qp;
-
- qp->qp_type = attr->qp_type;
- qp->rwq_ind_tbl = attr->rwq_ind_tbl;
- qp->send_cq = attr->send_cq;
- qp->recv_cq = attr->recv_cq;
- qp->srq = attr->srq;
- qp->rwq_ind_tbl = attr->rwq_ind_tbl;
- qp->event_handler = attr->event_handler;
- qp->port = attr->port_num;
-
- atomic_set(&qp->usecnt, 0);
- spin_lock_init(&qp->mr_lock);
- INIT_LIST_HEAD(&qp->rdma_mrs);
- INIT_LIST_HEAD(&qp->sig_mrs);
-
- rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
- WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
- rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
- rdma_restrack_add(&qp->res);
- return qp;
-}
+struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
+ struct ib_qp_init_attr *attr,
+ struct ib_udata *udata,
+ struct ib_uqp_object *uobj, const char *caller);
+
+void ib_qp_usecnt_inc(struct ib_qp *qp);
+void ib_qp_usecnt_dec(struct ib_qp *qp);
struct rdma_dev_addr;
int rdma_resolve_ip_route(struct sockaddr *src_addr,
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index fa20b1824fb8..f4814bb7f082 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -607,6 +607,8 @@ struct ib_device *_ib_alloc_device(size_t size)
for (i = 0; i < ARRAY_SIZE(device->cq_pools); i++)
INIT_LIST_HEAD(&device->cq_pools[i]);
+ rwlock_init(&device->cache_lock);
+
device->uverbs_cmd_mask =
BIT_ULL(IB_USER_VERBS_CMD_ALLOC_MW) |
BIT_ULL(IB_USER_VERBS_CMD_ALLOC_PD) |
@@ -2050,7 +2052,6 @@ static int __ib_query_port(struct ib_device *device,
u32 port_num,
struct ib_port_attr *port_attr)
{
- union ib_gid gid = {};
int err;
memset(port_attr, 0, sizeof(*port_attr));
@@ -2063,11 +2064,8 @@ static int __ib_query_port(struct ib_device *device,
IB_LINK_LAYER_INFINIBAND)
return 0;
- err = device->ops.query_gid(device, port_num, 0, &gid);
- if (err)
- return err;
-
- port_attr->subnet_prefix = be64_to_cpu(gid.global.subnet_prefix);
+ ib_get_cached_subnet_prefix(device, port_num,
+ &port_attr->subnet_prefix);
return 0;
}
@@ -2656,6 +2654,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
SET_DEVICE_OP(dev_ops, get_hw_stats);
SET_DEVICE_OP(dev_ops, get_link_layer);
SET_DEVICE_OP(dev_ops, get_netdev);
+ SET_DEVICE_OP(dev_ops, get_numa_node);
SET_DEVICE_OP(dev_ops, get_port_immutable);
SET_DEVICE_OP(dev_ops, get_vector_affinity);
SET_DEVICE_OP(dev_ops, get_vf_config);
@@ -2712,6 +2711,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
SET_OBJ_SIZE(dev_ops, ib_cq);
SET_OBJ_SIZE(dev_ops, ib_mw);
SET_OBJ_SIZE(dev_ops, ib_pd);
+ SET_OBJ_SIZE(dev_ops, ib_qp);
SET_OBJ_SIZE(dev_ops, ib_rwq_ind_table);
SET_OBJ_SIZE(dev_ops, ib_srq);
SET_OBJ_SIZE(dev_ops, ib_ucontext);
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 42261152b489..2b47073c61a6 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -1186,29 +1186,34 @@ static int __init iw_cm_init(void)
ret = iwpm_init(RDMA_NL_IWCM);
if (ret)
- pr_err("iw_cm: couldn't init iwpm\n");
- else
- rdma_nl_register(RDMA_NL_IWCM, iwcm_nl_cb_table);
+ return ret;
+
iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", 0);
if (!iwcm_wq)
- return -ENOMEM;
+ goto err_alloc;
iwcm_ctl_table_hdr = register_net_sysctl(&init_net, "net/iw_cm",
iwcm_ctl_table);
if (!iwcm_ctl_table_hdr) {
pr_err("iw_cm: couldn't register sysctl paths\n");
- destroy_workqueue(iwcm_wq);
- return -ENOMEM;
+ goto err_sysctl;
}
+ rdma_nl_register(RDMA_NL_IWCM, iwcm_nl_cb_table);
return 0;
+
+err_sysctl:
+ destroy_workqueue(iwcm_wq);
+err_alloc:
+ iwpm_exit(RDMA_NL_IWCM);
+ return -ENOMEM;
}
static void __exit iw_cm_cleanup(void)
{
+ rdma_nl_unregister(RDMA_NL_IWCM);
unregister_net_sysctl_table(iwcm_ctl_table_hdr);
destroy_workqueue(iwcm_wq);
- rdma_nl_unregister(RDMA_NL_IWCM);
iwpm_exit(RDMA_NL_IWCM);
}
diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c
index 12a9816fc0e2..3c9a9869212b 100644
--- a/drivers/infiniband/core/iwpm_msg.c
+++ b/drivers/infiniband/core/iwpm_msg.c
@@ -69,10 +69,6 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
const char *err_str = "";
int ret = -EINVAL;
- if (!iwpm_valid_client(nl_client)) {
- err_str = "Invalid port mapper client";
- goto pid_query_error;
- }
if (iwpm_check_registration(nl_client, IWPM_REG_VALID) ||
iwpm_user_pid == IWPM_PID_UNAVAILABLE)
return 0;
@@ -153,10 +149,6 @@ int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
const char *err_str = "";
int ret = -EINVAL;
- if (!iwpm_valid_client(nl_client)) {
- err_str = "Invalid port mapper client";
- goto add_mapping_error;
- }
if (!iwpm_valid_pid())
return 0;
if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
@@ -240,10 +232,6 @@ int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
const char *err_str = "";
int ret = -EINVAL;
- if (!iwpm_valid_client(nl_client)) {
- err_str = "Invalid port mapper client";
- goto query_mapping_error;
- }
if (!iwpm_valid_pid())
return 0;
if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
@@ -331,10 +319,6 @@ int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)
const char *err_str = "";
int ret = -EINVAL;
- if (!iwpm_valid_client(nl_client)) {
- err_str = "Invalid port mapper client";
- goto remove_mapping_error;
- }
if (!iwpm_valid_pid())
return 0;
if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) {
@@ -444,8 +428,7 @@ int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
__func__, iwpm_user_pid);
- if (iwpm_valid_client(nl_client))
- iwpm_set_registration(nl_client, IWPM_REG_VALID);
+ iwpm_set_registration(nl_client, IWPM_REG_VALID);
register_pid_response_exit:
nlmsg_request->request_done = 1;
/* always for found nlmsg_request */
@@ -649,11 +632,6 @@ int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
return ret;
nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
- if (!iwpm_valid_client(nl_client)) {
- pr_info("%s: Invalid port mapper client = %u\n",
- __func__, nl_client);
- return ret;
- }
atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
local_sockaddr = (struct sockaddr_storage *)
@@ -736,11 +714,6 @@ int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
return ret;
}
nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
- if (!iwpm_valid_client(nl_client)) {
- pr_info("%s: Invalid port mapper client = %u\n",
- __func__, nl_client);
- return ret;
- }
iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
iwpm_user_pid = cb->nlh->nlmsg_pid;
@@ -863,11 +836,6 @@ int iwpm_hello_cb(struct sk_buff *skb, struct netlink_callback *cb)
}
abi_version = nla_get_u16(nltb[IWPM_NLA_HELLO_ABI_VERSION]);
nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
- if (!iwpm_valid_client(nl_client)) {
- pr_info("%s: Invalid port mapper client = %u\n",
- __func__, nl_client);
- return ret;
- }
iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
iwpm_ulib_version = min_t(u16, IWPM_UABI_VERSION, abi_version);
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
index 3f8c019c7260..54f4feb604d8 100644
--- a/drivers/infiniband/core/iwpm_util.c
+++ b/drivers/infiniband/core/iwpm_util.c
@@ -48,7 +48,6 @@ static DEFINE_SPINLOCK(iwpm_mapinfo_lock);
static struct hlist_head *iwpm_reminfo_bucket;
static DEFINE_SPINLOCK(iwpm_reminfo_lock);
-static DEFINE_MUTEX(iwpm_admin_lock);
static struct iwpm_admin_data iwpm_admin;
/**
@@ -59,39 +58,21 @@ static struct iwpm_admin_data iwpm_admin;
*/
int iwpm_init(u8 nl_client)
{
- int ret = 0;
- mutex_lock(&iwpm_admin_lock);
- if (!refcount_read(&iwpm_admin.refcount)) {
- 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 = kcalloc(IWPM_REMINFO_HASH_SIZE,
- sizeof(struct hlist_head),
- GFP_KERNEL);
- if (!iwpm_reminfo_bucket) {
- kfree(iwpm_hash_bucket);
- ret = -ENOMEM;
- goto init_exit;
- }
+ iwpm_hash_bucket = kcalloc(IWPM_MAPINFO_HASH_SIZE,
+ sizeof(struct hlist_head), GFP_KERNEL);
+ if (!iwpm_hash_bucket)
+ return -ENOMEM;
- refcount_set(&iwpm_admin.refcount, 1);
- } else {
- refcount_inc(&iwpm_admin.refcount);
+ iwpm_reminfo_bucket = kcalloc(IWPM_REMINFO_HASH_SIZE,
+ sizeof(struct hlist_head), GFP_KERNEL);
+ if (!iwpm_reminfo_bucket) {
+ kfree(iwpm_hash_bucket);
+ return -ENOMEM;
}
-init_exit:
- mutex_unlock(&iwpm_admin_lock);
- if (!ret) {
- iwpm_set_valid(nl_client, 1);
- iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
- pr_debug("%s: Mapinfo and reminfo tables are created\n",
- __func__);
- }
- return ret;
+ iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
+ pr_debug("%s: Mapinfo and reminfo tables are created\n", __func__);
+ return 0;
}
static void free_hash_bucket(void);
@@ -105,22 +86,9 @@ static void free_reminfo_bucket(void);
*/
int iwpm_exit(u8 nl_client)
{
-
- if (!iwpm_valid_client(nl_client))
- return -EINVAL;
- mutex_lock(&iwpm_admin_lock);
- if (!refcount_read(&iwpm_admin.refcount)) {
- mutex_unlock(&iwpm_admin_lock);
- pr_err("%s Incorrect usage - negative refcount\n", __func__);
- return -EINVAL;
- }
- if (refcount_dec_and_test(&iwpm_admin.refcount)) {
- free_hash_bucket();
- free_reminfo_bucket();
- pr_debug("%s: Resources are destroyed\n", __func__);
- }
- mutex_unlock(&iwpm_admin_lock);
- iwpm_set_valid(nl_client, 0);
+ free_hash_bucket();
+ free_reminfo_bucket();
+ pr_debug("%s: Resources are destroyed\n", __func__);
iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
return 0;
}
@@ -145,8 +113,6 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
unsigned long flags;
int ret = -EINVAL;
- if (!iwpm_valid_client(nl_client))
- return ret;
map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL);
if (!map_info)
return -ENOMEM;
@@ -306,10 +272,6 @@ int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
unsigned long flags;
int ret = -EINVAL;
- if (!iwpm_valid_client(nl_client)) {
- pr_info("%s: Invalid client = %u\n", __func__, nl_client);
- return ret;
- }
spin_lock_irqsave(&iwpm_reminfo_lock, flags);
if (iwpm_reminfo_bucket) {
hash_bucket_head = get_reminfo_hash_bucket(
@@ -424,16 +386,6 @@ int iwpm_get_nlmsg_seq(void)
return atomic_inc_return(&iwpm_admin.nlmsg_seq);
}
-int iwpm_valid_client(u8 nl_client)
-{
- return iwpm_admin.client_list[nl_client];
-}
-
-void iwpm_set_valid(u8 nl_client, int valid)
-{
- iwpm_admin.client_list[nl_client] = valid;
-}
-
/* valid client */
u32 iwpm_get_registration(u8 nl_client)
{
diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h
index e201835de733..3a42ad43056e 100644
--- a/drivers/infiniband/core/iwpm_util.h
+++ b/drivers/infiniband/core/iwpm_util.h
@@ -90,9 +90,7 @@ struct iwpm_remote_info {
};
struct iwpm_admin_data {
- refcount_t refcount;
atomic_t nlmsg_seq;
- int client_list[RDMA_NL_NUM_CLIENTS];
u32 reg_list[RDMA_NL_NUM_CLIENTS];
};
@@ -148,22 +146,6 @@ int iwpm_get_nlmsg_seq(void);
void iwpm_add_remote_info(struct iwpm_remote_info *reminfo);
/**
- * iwpm_valid_client - Check if the port mapper client is valid
- * @nl_client: The index of the netlink client
- *
- * Valid clients need to call iwpm_init() before using
- * the port mapper
- */
-int iwpm_valid_client(u8 nl_client);
-
-/**
- * iwpm_set_valid - Set the port mapper client to valid or not
- * @nl_client: The index of the netlink client
- * @valid: 1 if valid or 0 if invalid
- */
-void iwpm_set_valid(u8 nl_client, int valid);
-
-/**
* iwpm_check_registration - Check if the client registration
* matches the given one
* @nl_client: The index of the netlink client
diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c
index 033207882c82..1f935d9f6178 100644
--- a/drivers/infiniband/core/restrack.c
+++ b/drivers/infiniband/core/restrack.c
@@ -343,7 +343,7 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)
rt = &dev->res[res->type];
old = xa_erase(&rt->xa, res->id);
- if (res->type == RDMA_RESTRACK_MR || res->type == RDMA_RESTRACK_QP)
+ if (res->type == RDMA_RESTRACK_MR)
return;
WARN_ON(old != res);
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index b61576f702b8..a20b8108e160 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -123,12 +123,6 @@ struct ib_sa_query {
#define IB_SA_CANCEL 0x00000002
#define IB_SA_QUERY_OPA 0x00000004
-struct ib_sa_service_query {
- void (*callback)(int, struct ib_sa_service_rec *, void *);
- void *context;
- struct ib_sa_query sa_query;
-};
-
struct ib_sa_path_query {
void (*callback)(int, struct sa_path_rec *, void *);
void *context;
@@ -502,54 +496,6 @@ static const struct ib_field mcmember_rec_table[] = {
.size_bits = 23 },
};
-#define SERVICE_REC_FIELD(field) \
- .struct_offset_bytes = offsetof(struct ib_sa_service_rec, field), \
- .struct_size_bytes = sizeof_field(struct ib_sa_service_rec, field), \
- .field_name = "sa_service_rec:" #field
-
-static const struct ib_field service_rec_table[] = {
- { SERVICE_REC_FIELD(id),
- .offset_words = 0,
- .offset_bits = 0,
- .size_bits = 64 },
- { SERVICE_REC_FIELD(gid),
- .offset_words = 2,
- .offset_bits = 0,
- .size_bits = 128 },
- { SERVICE_REC_FIELD(pkey),
- .offset_words = 6,
- .offset_bits = 0,
- .size_bits = 16 },
- { SERVICE_REC_FIELD(lease),
- .offset_words = 7,
- .offset_bits = 0,
- .size_bits = 32 },
- { SERVICE_REC_FIELD(key),
- .offset_words = 8,
- .offset_bits = 0,
- .size_bits = 128 },
- { SERVICE_REC_FIELD(name),
- .offset_words = 12,
- .offset_bits = 0,
- .size_bits = 64*8 },
- { SERVICE_REC_FIELD(data8),
- .offset_words = 28,
- .offset_bits = 0,
- .size_bits = 16*8 },
- { SERVICE_REC_FIELD(data16),
- .offset_words = 32,
- .offset_bits = 0,
- .size_bits = 8*16 },
- { SERVICE_REC_FIELD(data32),
- .offset_words = 36,
- .offset_bits = 0,
- .size_bits = 4*32 },
- { SERVICE_REC_FIELD(data64),
- .offset_words = 40,
- .offset_bits = 0,
- .size_bits = 2*64 },
-};
-
#define CLASSPORTINFO_REC_FIELD(field) \
.struct_offset_bytes = offsetof(struct ib_class_port_info, field), \
.struct_size_bytes = sizeof_field(struct ib_class_port_info, field), \
@@ -1358,6 +1304,7 @@ static int send_mad(struct ib_sa_query *query, unsigned long timeout_ms,
{
unsigned long flags;
int ret, id;
+ const int nmbr_sa_query_retries = 10;
xa_lock_irqsave(&queries, flags);
ret = __xa_alloc(&queries, &id, query, xa_limit_32b, gfp_mask);
@@ -1365,7 +1312,13 @@ static int send_mad(struct ib_sa_query *query, unsigned long timeout_ms,
if (ret < 0)
return ret;
- query->mad_buf->timeout_ms = timeout_ms;
+ query->mad_buf->timeout_ms = timeout_ms / nmbr_sa_query_retries;
+ query->mad_buf->retries = nmbr_sa_query_retries;
+ if (!query->mad_buf->timeout_ms) {
+ /* Special case, very small timeout_ms */
+ query->mad_buf->timeout_ms = 1;
+ query->mad_buf->retries = timeout_ms;
+ }
query->mad_buf->context[0] = query;
query->id = id;
@@ -1634,129 +1587,6 @@ err1:
}
EXPORT_SYMBOL(ib_sa_path_rec_get);
-static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,
- int status,
- struct ib_sa_mad *mad)
-{
- struct ib_sa_service_query *query =
- container_of(sa_query, struct ib_sa_service_query, sa_query);
-
- if (mad) {
- struct ib_sa_service_rec rec;
-
- ib_unpack(service_rec_table, ARRAY_SIZE(service_rec_table),
- mad->data, &rec);
- query->callback(status, &rec, query->context);
- } else
- query->callback(status, NULL, query->context);
-}
-
-static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
-{
- kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
-}
-
-/**
- * ib_sa_service_rec_query - Start Service Record operation
- * @client:SA client
- * @device:device to send request on
- * @port_num: port number to send request on
- * @method:SA method - should be get, set, or delete
- * @rec:Service Record to send in request
- * @comp_mask:component mask to send in request
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when request completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:request context, used to cancel request
- *
- * Send a Service Record set/get/delete to the SA to register,
- * unregister or query a service record.
- * The callback function will be called when the request completes (or
- * fails); status is 0 for a successful response, -EINTR if the query
- * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
- * occurred sending the query. The resp parameter of the callback is
- * only valid if status is 0.
- *
- * If the return value of ib_sa_service_rec_query() is negative, it is an
- * error code. Otherwise it is a request ID that can be used to cancel
- * the query.
- */
-int ib_sa_service_rec_query(struct ib_sa_client *client,
- struct ib_device *device, u32 port_num, u8 method,
- struct ib_sa_service_rec *rec,
- ib_sa_comp_mask comp_mask,
- unsigned long timeout_ms, gfp_t gfp_mask,
- void (*callback)(int status,
- struct ib_sa_service_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **sa_query)
-{
- struct ib_sa_service_query *query;
- struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
- struct ib_sa_port *port;
- struct ib_mad_agent *agent;
- struct ib_sa_mad *mad;
- int ret;
-
- if (!sa_dev)
- return -ENODEV;
-
- port = &sa_dev->port[port_num - sa_dev->start_port];
- agent = port->agent;
-
- if (method != IB_MGMT_METHOD_GET &&
- method != IB_MGMT_METHOD_SET &&
- method != IB_SA_METHOD_DELETE)
- return -EINVAL;
-
- query = kzalloc(sizeof(*query), gfp_mask);
- if (!query)
- return -ENOMEM;
-
- query->sa_query.port = port;
- ret = alloc_mad(&query->sa_query, gfp_mask);
- if (ret)
- goto err1;
-
- ib_sa_client_get(client);
- query->sa_query.client = client;
- query->callback = callback;
- query->context = context;
-
- mad = query->sa_query.mad_buf->mad;
- init_mad(&query->sa_query, agent);
-
- query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
- query->sa_query.release = ib_sa_service_rec_release;
- mad->mad_hdr.method = method;
- mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
- mad->sa_hdr.comp_mask = comp_mask;
-
- ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
- rec, mad->data);
-
- *sa_query = &query->sa_query;
-
- ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
- if (ret < 0)
- goto err2;
-
- return ret;
-
-err2:
- *sa_query = NULL;
- ib_sa_client_put(query->sa_query.client);
- free_mad(&query->sa_query);
-
-err1:
- kfree(query);
- return ret;
-}
-EXPORT_SYMBOL(ib_sa_service_rec_query);
-
static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
int status,
struct ib_sa_mad *mad)
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 0eb40025075f..86d479772fbc 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -51,15 +51,15 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
struct scatterlist *sg;
unsigned int i;
- if (umem->nmap > 0)
- ib_dma_unmap_sg(dev, umem->sg_head.sgl, umem->sg_nents,
- DMA_BIDIRECTIONAL);
+ if (dirty)
+ ib_dma_unmap_sgtable_attrs(dev, &umem->sgt_append.sgt,
+ DMA_BIDIRECTIONAL, 0);
- for_each_sg(umem->sg_head.sgl, sg, umem->sg_nents, i)
+ for_each_sgtable_sg(&umem->sgt_append.sgt, sg, i)
unpin_user_page_range_dirty_lock(sg_page(sg),
DIV_ROUND_UP(sg->length, PAGE_SIZE), make_dirty);
- sg_free_table(&umem->sg_head);
+ sg_free_append_table(&umem->sgt_append);
}
/**
@@ -111,7 +111,7 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
/* offset into first SGL */
pgoff = umem->address & ~PAGE_MASK;
- for_each_sg(umem->sg_head.sgl, sg, umem->nmap, i) {
+ for_each_sgtable_dma_sg(&umem->sgt_append.sgt, sg, i) {
/* Walk SGL and reduce max page size if VA/PA bits differ
* for any address.
*/
@@ -121,7 +121,7 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
* the maximum possible page size as the low bits of the iova
* must be zero when starting the next chunk.
*/
- if (i != (umem->nmap - 1))
+ if (i != (umem->sgt_append.sgt.nents - 1))
mask |= va;
pgoff = 0;
}
@@ -155,8 +155,7 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
unsigned long dma_attr = 0;
struct mm_struct *mm;
unsigned long npages;
- int ret;
- struct scatterlist *sg = NULL;
+ int pinned, ret;
unsigned int gup_flags = FOLL_WRITE;
/*
@@ -216,24 +215,24 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
while (npages) {
cond_resched();
- ret = pin_user_pages_fast(cur_base,
+ pinned = pin_user_pages_fast(cur_base,
min_t(unsigned long, npages,
PAGE_SIZE /
sizeof(struct page *)),
gup_flags | FOLL_LONGTERM, page_list);
- if (ret < 0)
+ if (pinned < 0) {
+ ret = pinned;
goto umem_release;
+ }
- cur_base += ret * PAGE_SIZE;
- npages -= ret;
- sg = __sg_alloc_table_from_pages(&umem->sg_head, page_list, ret,
- 0, ret << PAGE_SHIFT,
- ib_dma_max_seg_size(device), sg, npages,
- GFP_KERNEL);
- umem->sg_nents = umem->sg_head.nents;
- if (IS_ERR(sg)) {
- unpin_user_pages_dirty_lock(page_list, ret, 0);
- ret = PTR_ERR(sg);
+ cur_base += pinned * PAGE_SIZE;
+ npages -= pinned;
+ ret = sg_alloc_append_table_from_pages(
+ &umem->sgt_append, page_list, pinned, 0,
+ pinned << PAGE_SHIFT, ib_dma_max_seg_size(device),
+ npages, GFP_KERNEL);
+ if (ret) {
+ unpin_user_pages_dirty_lock(page_list, pinned, 0);
goto umem_release;
}
}
@@ -241,16 +240,10 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
if (access & IB_ACCESS_RELAXED_ORDERING)
dma_attr |= DMA_ATTR_WEAK_ORDERING;
- umem->nmap =
- ib_dma_map_sg_attrs(device, umem->sg_head.sgl, umem->sg_nents,
- DMA_BIDIRECTIONAL, dma_attr);
-
- if (!umem->nmap) {
- ret = -ENOMEM;
+ ret = ib_dma_map_sgtable_attrs(device, &umem->sgt_append.sgt,
+ DMA_BIDIRECTIONAL, dma_attr);
+ if (ret)
goto umem_release;
- }
-
- ret = 0;
goto out;
umem_release:
@@ -310,7 +303,8 @@ int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
return -EINVAL;
}
- ret = sg_pcopy_to_buffer(umem->sg_head.sgl, umem->sg_nents, dst, length,
+ ret = sg_pcopy_to_buffer(umem->sgt_append.sgt.sgl,
+ umem->sgt_append.sgt.orig_nents, dst, length,
offset + ib_umem_offset(umem));
if (ret < 0)
diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c
index c6e875619fac..e824baf4640d 100644
--- a/drivers/infiniband/core/umem_dmabuf.c
+++ b/drivers/infiniband/core/umem_dmabuf.c
@@ -55,9 +55,8 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf)
cur += sg_dma_len(sg);
}
- umem_dmabuf->umem.sg_head.sgl = umem_dmabuf->first_sg;
- umem_dmabuf->umem.sg_head.nents = nmap;
- umem_dmabuf->umem.nmap = nmap;
+ umem_dmabuf->umem.sgt_append.sgt.sgl = umem_dmabuf->first_sg;
+ umem_dmabuf->umem.sgt_append.sgt.nents = nmap;
umem_dmabuf->sgt = sgt;
wait_fence:
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c
index 9462dbe66014..7a47343d11f9 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -292,9 +292,6 @@ EXPORT_SYMBOL(ib_umem_odp_release);
* @dma_index: index in the umem to add the dma to.
* @page: the page struct to map and add.
* @access_mask: access permissions needed for this page.
- * @current_seq: sequence number for synchronization with invalidations.
- * the sequence number is taken from
- * umem_odp->notifiers_seq.
*
* The function returns -EFAULT if the DMA mapping operation fails.
*
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 8c8ca7bce3ca..740e6b2efe0e 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1435,35 +1435,13 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
attr.source_qpn = cmd->source_qpn;
}
- if (cmd->qp_type == IB_QPT_XRC_TGT)
- qp = ib_create_qp(pd, &attr);
- else
- qp = _ib_create_qp(device, pd, &attr, &attrs->driver_udata, obj,
- NULL);
-
+ qp = ib_create_qp_user(device, pd, &attr, &attrs->driver_udata, obj,
+ KBUILD_MODNAME);
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
}
-
- if (cmd->qp_type != IB_QPT_XRC_TGT) {
- ret = ib_create_qp_security(qp, device);
- if (ret)
- goto err_cb;
-
- atomic_inc(&pd->usecnt);
- if (attr.send_cq)
- atomic_inc(&attr.send_cq->usecnt);
- if (attr.recv_cq)
- atomic_inc(&attr.recv_cq->usecnt);
- if (attr.srq)
- atomic_inc(&attr.srq->usecnt);
- if (ind_tbl)
- atomic_inc(&ind_tbl->usecnt);
- } else {
- /* It is done in _ib_create_qp for other QP types */
- qp->uobject = obj;
- }
+ ib_qp_usecnt_inc(qp);
obj->uevent.uobject.object = qp;
obj->uevent.event_file = READ_ONCE(attrs->ufile->default_async_file);
@@ -1502,9 +1480,6 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
resp.response_length = uverbs_response_length(attrs, sizeof(resp));
return uverbs_response(attrs, &resp, sizeof(resp));
-err_cb:
- ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));
-
err_put:
if (!IS_ERR(xrcd_uobj))
uobj_put_read(xrcd_uobj);
diff --git a/drivers/infiniband/core/uverbs_std_types_qp.c b/drivers/infiniband/core/uverbs_std_types_qp.c
index c00cfb5ed387..dd1075466f61 100644
--- a/drivers/infiniband/core/uverbs_std_types_qp.c
+++ b/drivers/infiniband/core/uverbs_std_types_qp.c
@@ -248,44 +248,23 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QP_CREATE)(
set_caps(&attr, &cap, true);
mutex_init(&obj->mcast_lock);
- if (attr.qp_type == IB_QPT_XRC_TGT)
- qp = ib_create_qp(pd, &attr);
- else
- qp = _ib_create_qp(device, pd, &attr, &attrs->driver_udata, obj,
- NULL);
-
+ qp = ib_create_qp_user(device, pd, &attr, &attrs->driver_udata, obj,
+ KBUILD_MODNAME);
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
}
+ ib_qp_usecnt_inc(qp);
- if (attr.qp_type != IB_QPT_XRC_TGT) {
- atomic_inc(&pd->usecnt);
- if (attr.send_cq)
- atomic_inc(&attr.send_cq->usecnt);
- if (attr.recv_cq)
- atomic_inc(&attr.recv_cq->usecnt);
- if (attr.srq)
- atomic_inc(&attr.srq->usecnt);
- if (attr.rwq_ind_tbl)
- atomic_inc(&attr.rwq_ind_tbl->usecnt);
- } else {
+ if (attr.qp_type == IB_QPT_XRC_TGT) {
obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
uobject);
atomic_inc(&obj->uxrcd->refcnt);
- /* It is done in _ib_create_qp for other QP types */
- qp->uobject = obj;
}
obj->uevent.uobject.object = qp;
uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_QP_HANDLE);
- if (attr.qp_type != IB_QPT_XRC_TGT) {
- ret = ib_create_qp_security(qp, device);
- if (ret)
- return ret;
- }
-
set_caps(&attr, &cap, false);
ret = uverbs_copy_to_struct_or_zero(attrs,
UVERBS_ATTR_CREATE_QP_RESP_CAP, &cap,
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 7036967e4c0b..89a2b21976d6 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -1035,7 +1035,8 @@ struct ib_srq *ib_create_srq_user(struct ib_pd *pd,
}
if (srq->srq_type == IB_SRQT_XRC) {
srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
- atomic_inc(&srq->ext.xrc.xrcd->usecnt);
+ if (srq->ext.xrc.xrcd)
+ atomic_inc(&srq->ext.xrc.xrcd->usecnt);
}
atomic_inc(&pd->usecnt);
@@ -1046,7 +1047,7 @@ struct ib_srq *ib_create_srq_user(struct ib_pd *pd,
if (ret) {
rdma_restrack_put(&srq->res);
atomic_dec(&srq->pd->usecnt);
- if (srq->srq_type == IB_SRQT_XRC)
+ if (srq->srq_type == IB_SRQT_XRC && srq->ext.xrc.xrcd)
atomic_dec(&srq->ext.xrc.xrcd->usecnt);
if (ib_srq_has_cq(srq->srq_type))
atomic_dec(&srq->ext.cq->usecnt);
@@ -1090,7 +1091,7 @@ int ib_destroy_srq_user(struct ib_srq *srq, struct ib_udata *udata)
return ret;
atomic_dec(&srq->pd->usecnt);
- if (srq->srq_type == IB_SRQT_XRC)
+ if (srq->srq_type == IB_SRQT_XRC && srq->ext.xrc.xrcd)
atomic_dec(&srq->ext.xrc.xrcd->usecnt);
if (ib_srq_has_cq(srq->srq_type))
atomic_dec(&srq->ext.cq->usecnt);
@@ -1199,34 +1200,142 @@ static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp,
return qp;
}
+static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
+ struct ib_qp_init_attr *attr,
+ struct ib_udata *udata,
+ struct ib_uqp_object *uobj, const char *caller)
+{
+ struct ib_udata dummy = {};
+ struct ib_qp *qp;
+ int ret;
+
+ if (!dev->ops.create_qp)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ qp = rdma_zalloc_drv_obj_numa(dev, ib_qp);
+ if (!qp)
+ return ERR_PTR(-ENOMEM);
+
+ qp->device = dev;
+ qp->pd = pd;
+ qp->uobject = uobj;
+ qp->real_qp = qp;
+
+ qp->qp_type = attr->qp_type;
+ qp->rwq_ind_tbl = attr->rwq_ind_tbl;
+ qp->srq = attr->srq;
+ qp->event_handler = attr->event_handler;
+ qp->port = attr->port_num;
+ qp->qp_context = attr->qp_context;
+
+ spin_lock_init(&qp->mr_lock);
+ INIT_LIST_HEAD(&qp->rdma_mrs);
+ INIT_LIST_HEAD(&qp->sig_mrs);
+
+ rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
+ WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
+ rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
+ ret = dev->ops.create_qp(qp, attr, udata);
+ if (ret)
+ goto err_create;
+
+ /*
+ * TODO: The mlx4 internally overwrites send_cq and recv_cq.
+ * Unfortunately, it is not an easy task to fix that driver.
+ */
+ qp->send_cq = attr->send_cq;
+ qp->recv_cq = attr->recv_cq;
+
+ ret = ib_create_qp_security(qp, dev);
+ if (ret)
+ goto err_security;
+
+ rdma_restrack_add(&qp->res);
+ return qp;
+
+err_security:
+ qp->device->ops.destroy_qp(qp, udata ? &dummy : NULL);
+err_create:
+ rdma_restrack_put(&qp->res);
+ kfree(qp);
+ return ERR_PTR(ret);
+
+}
+
/**
- * ib_create_named_qp - Creates a kernel QP associated with the specified protection
+ * ib_create_qp_user - Creates a QP associated with the specified protection
* domain.
+ * @dev: IB device
* @pd: The protection domain associated with the QP.
- * @qp_init_attr: A list of initial attributes required to create the
+ * @attr: A list of initial attributes required to create the
* QP. If QP creation succeeds, then the attributes are updated to
* the actual capabilities of the created QP.
+ * @udata: User data
+ * @uobj: uverbs obect
* @caller: caller's build-time module name
- *
- * NOTE: for user qp use ib_create_qp_user with valid udata!
*/
-struct ib_qp *ib_create_named_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *qp_init_attr,
- const char *caller)
+struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
+ struct ib_qp_init_attr *attr,
+ struct ib_udata *udata,
+ struct ib_uqp_object *uobj, const char *caller)
{
- struct ib_device *device = pd ? pd->device : qp_init_attr->xrcd->device;
- struct ib_qp *qp;
- int ret;
+ struct ib_qp *qp, *xrc_qp;
- if (qp_init_attr->rwq_ind_tbl &&
- (qp_init_attr->recv_cq ||
- qp_init_attr->srq || qp_init_attr->cap.max_recv_wr ||
- qp_init_attr->cap.max_recv_sge))
- return ERR_PTR(-EINVAL);
+ if (attr->qp_type == IB_QPT_XRC_TGT)
+ qp = create_qp(dev, pd, attr, NULL, NULL, caller);
+ else
+ qp = create_qp(dev, pd, attr, udata, uobj, NULL);
+ if (attr->qp_type != IB_QPT_XRC_TGT || IS_ERR(qp))
+ return qp;
- if ((qp_init_attr->create_flags & IB_QP_CREATE_INTEGRITY_EN) &&
- !(device->attrs.device_cap_flags & IB_DEVICE_INTEGRITY_HANDOVER))
- return ERR_PTR(-EINVAL);
+ xrc_qp = create_xrc_qp_user(qp, attr);
+ if (IS_ERR(xrc_qp)) {
+ ib_destroy_qp(qp);
+ return xrc_qp;
+ }
+
+ xrc_qp->uobject = uobj;
+ return xrc_qp;
+}
+EXPORT_SYMBOL(ib_create_qp_user);
+
+void ib_qp_usecnt_inc(struct ib_qp *qp)
+{
+ if (qp->pd)
+ atomic_inc(&qp->pd->usecnt);
+ if (qp->send_cq)
+ atomic_inc(&qp->send_cq->usecnt);
+ if (qp->recv_cq)
+ atomic_inc(&qp->recv_cq->usecnt);
+ if (qp->srq)
+ atomic_inc(&qp->srq->usecnt);
+ if (qp->rwq_ind_tbl)
+ atomic_inc(&qp->rwq_ind_tbl->usecnt);
+}
+EXPORT_SYMBOL(ib_qp_usecnt_inc);
+
+void ib_qp_usecnt_dec(struct ib_qp *qp)
+{
+ if (qp->rwq_ind_tbl)
+ atomic_dec(&qp->rwq_ind_tbl->usecnt);
+ if (qp->srq)
+ atomic_dec(&qp->srq->usecnt);
+ if (qp->recv_cq)
+ atomic_dec(&qp->recv_cq->usecnt);
+ if (qp->send_cq)
+ atomic_dec(&qp->send_cq->usecnt);
+ if (qp->pd)
+ atomic_dec(&qp->pd->usecnt);
+}
+EXPORT_SYMBOL(ib_qp_usecnt_dec);
+
+struct ib_qp *ib_create_qp_kernel(struct ib_pd *pd,
+ struct ib_qp_init_attr *qp_init_attr,
+ const char *caller)
+{
+ struct ib_device *device = pd->device;
+ struct ib_qp *qp;
+ int ret;
/*
* If the callers is using the RDMA API calculate the resources
@@ -1237,47 +1346,11 @@ struct ib_qp *ib_create_named_qp(struct ib_pd *pd,
if (qp_init_attr->cap.max_rdma_ctxs)
rdma_rw_init_qp(device, qp_init_attr);
- qp = _ib_create_qp(device, pd, qp_init_attr, NULL, NULL, caller);
+ qp = create_qp(device, pd, qp_init_attr, NULL, NULL, caller);
if (IS_ERR(qp))
return qp;
- ret = ib_create_qp_security(qp, device);
- if (ret)
- goto err;
-
- if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
- struct ib_qp *xrc_qp =
- create_xrc_qp_user(qp, qp_init_attr);
-
- if (IS_ERR(xrc_qp)) {
- ret = PTR_ERR(xrc_qp);
- goto err;
- }
- return xrc_qp;
- }
-
- qp->event_handler = qp_init_attr->event_handler;
- qp->qp_context = qp_init_attr->qp_context;
- if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
- qp->recv_cq = NULL;
- qp->srq = NULL;
- } else {
- qp->recv_cq = qp_init_attr->recv_cq;
- if (qp_init_attr->recv_cq)
- atomic_inc(&qp_init_attr->recv_cq->usecnt);
- qp->srq = qp_init_attr->srq;
- if (qp->srq)
- atomic_inc(&qp_init_attr->srq->usecnt);
- }
-
- qp->send_cq = qp_init_attr->send_cq;
- qp->xrcd = NULL;
-
- atomic_inc(&pd->usecnt);
- if (qp_init_attr->send_cq)
- atomic_inc(&qp_init_attr->send_cq->usecnt);
- if (qp_init_attr->rwq_ind_tbl)
- atomic_inc(&qp->rwq_ind_tbl->usecnt);
+ ib_qp_usecnt_inc(qp);
if (qp_init_attr->cap.max_rdma_ctxs) {
ret = rdma_rw_init_mrs(qp, qp_init_attr);
@@ -1303,7 +1376,7 @@ err:
return ERR_PTR(ret);
}
-EXPORT_SYMBOL(ib_create_named_qp);
+EXPORT_SYMBOL(ib_create_qp_kernel);
static const struct {
int valid;
@@ -1935,10 +2008,6 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
{
const struct ib_gid_attr *alt_path_sgid_attr = qp->alt_path_sgid_attr;
const struct ib_gid_attr *av_sgid_attr = qp->av_sgid_attr;
- struct ib_pd *pd;
- struct ib_cq *scq, *rcq;
- struct ib_srq *srq;
- struct ib_rwq_ind_table *ind_tbl;
struct ib_qp_security *sec;
int ret;
@@ -1950,11 +2019,6 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
if (qp->real_qp != qp)
return __ib_destroy_shared_qp(qp);
- pd = qp->pd;
- scq = qp->send_cq;
- rcq = qp->recv_cq;
- srq = qp->srq;
- ind_tbl = qp->rwq_ind_tbl;
sec = qp->qp_sec;
if (sec)
ib_destroy_qp_security_begin(sec);
@@ -1963,30 +2027,24 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
rdma_rw_cleanup_mrs(qp);
rdma_counter_unbind_qp(qp, true);
- rdma_restrack_del(&qp->res);
ret = qp->device->ops.destroy_qp(qp, udata);
- if (!ret) {
- if (alt_path_sgid_attr)
- rdma_put_gid_attr(alt_path_sgid_attr);
- if (av_sgid_attr)
- rdma_put_gid_attr(av_sgid_attr);
- if (pd)
- atomic_dec(&pd->usecnt);
- if (scq)
- atomic_dec(&scq->usecnt);
- if (rcq)
- atomic_dec(&rcq->usecnt);
- if (srq)
- atomic_dec(&srq->usecnt);
- if (ind_tbl)
- atomic_dec(&ind_tbl->usecnt);
- if (sec)
- ib_destroy_qp_security_end(sec);
- } else {
+ if (ret) {
if (sec)
ib_destroy_qp_security_abort(sec);
+ return ret;
}
+ if (alt_path_sgid_attr)
+ rdma_put_gid_attr(alt_path_sgid_attr);
+ if (av_sgid_attr)
+ rdma_put_gid_attr(av_sgid_attr);
+
+ ib_qp_usecnt_dec(qp);
+ if (sec)
+ ib_destroy_qp_security_end(sec);
+
+ rdma_restrack_del(&qp->res);
+ kfree(qp);
return ret;
}
EXPORT_SYMBOL(ib_destroy_qp_user);
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index ea0054c60fbc..3048862c961c 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -815,7 +815,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp) {
rc = bnxt_re_destroy_gsi_sqp(qp);
if (rc)
- goto sh_fail;
+ return rc;
}
mutex_lock(&rdev->qp_lock);
@@ -826,10 +826,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
ib_umem_release(qp->rumem);
ib_umem_release(qp->sumem);
- kfree(qp);
return 0;
-sh_fail:
- return rc;
}
static u8 __from_ib_qp_type(enum ib_qp_type type)
@@ -1402,27 +1399,22 @@ static bool bnxt_re_test_qp_limits(struct bnxt_re_dev *rdev,
return rc;
}
-struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
- struct ib_qp_init_attr *qp_init_attr,
- struct ib_udata *udata)
+int bnxt_re_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *qp_init_attr,
+ struct ib_udata *udata)
{
+ struct ib_pd *ib_pd = ib_qp->pd;
struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
struct bnxt_re_dev *rdev = pd->rdev;
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
- struct bnxt_re_qp *qp;
+ struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
int rc;
rc = bnxt_re_test_qp_limits(rdev, qp_init_attr, dev_attr);
if (!rc) {
rc = -EINVAL;
- goto exit;
+ goto fail;
}
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp) {
- rc = -ENOMEM;
- goto exit;
- }
qp->rdev = rdev;
rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, udata);
if (rc)
@@ -1465,16 +1457,14 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
mutex_unlock(&rdev->qp_lock);
atomic_inc(&rdev->qp_count);
- return &qp->ib_qp;
+ return 0;
qp_destroy:
bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
free_umem:
ib_umem_release(qp->rumem);
ib_umem_release(qp->sumem);
fail:
- kfree(qp);
-exit:
- return ERR_PTR(rc);
+ return rc;
}
static u8 __from_ib_qp_state(enum ib_qp_state state)
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index d68671cc6173..b5c6e0f4f877 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -78,9 +78,9 @@ struct bnxt_re_srq {
};
struct bnxt_re_qp {
+ struct ib_qp ib_qp;
struct list_head list;
struct bnxt_re_dev *rdev;
- struct ib_qp ib_qp;
spinlock_t sq_lock; /* protect sq */
spinlock_t rq_lock; /* protect rq */
struct bnxt_qplib_qp qplib_qp;
@@ -179,9 +179,8 @@ int bnxt_re_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
int bnxt_re_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
int bnxt_re_post_srq_recv(struct ib_srq *srq, const struct ib_recv_wr *recv_wr,
const struct ib_recv_wr **bad_recv_wr);
-struct ib_qp *bnxt_re_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *qp_init_attr,
- struct ib_udata *udata);
+int bnxt_re_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *qp_init_attr,
+ struct ib_udata *udata);
int bnxt_re_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_udata *udata);
int bnxt_re_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index 4678bd6ec7d6..66268e41b470 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -711,6 +711,7 @@ static const struct ib_device_ops bnxt_re_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, bnxt_re_ah, ib_ah),
INIT_RDMA_OBJ_SIZE(ib_cq, bnxt_re_cq, ib_cq),
INIT_RDMA_OBJ_SIZE(ib_pd, bnxt_re_pd, ib_pd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, bnxt_re_qp, ib_qp),
INIT_RDMA_OBJ_SIZE(ib_srq, bnxt_re_srq, ib_srq),
INIT_RDMA_OBJ_SIZE(ib_ucontext, bnxt_re_ucontext, ib_uctx),
};
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index ac5f581aff4c..12f33467c672 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -990,9 +990,8 @@ int c4iw_destroy_srq(struct ib_srq *ib_srq, struct ib_udata *udata);
int c4iw_create_srq(struct ib_srq *srq, struct ib_srq_init_attr *attrs,
struct ib_udata *udata);
int c4iw_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata);
-struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *attrs,
- struct ib_udata *udata);
+int c4iw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
+ struct ib_udata *udata);
int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 881d515eb15a..e7337662aff8 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -499,6 +499,7 @@ static const struct ib_device_ops c4iw_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_cq, c4iw_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_mw, c4iw_mw, ibmw),
INIT_RDMA_OBJ_SIZE(ib_pd, c4iw_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, c4iw_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_srq, c4iw_srq, ibsrq),
INIT_RDMA_OBJ_SIZE(ib_ucontext, c4iw_ucontext, ibucontext),
};
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index a81fa7a56edb..d20b4ef2c853 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -2103,16 +2103,15 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
ucontext ? &ucontext->uctx : &rhp->rdev.uctx, !qhp->srq);
c4iw_put_wr_wait(qhp->wr_waitp);
-
- kfree(qhp);
return 0;
}
-struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
- struct ib_udata *udata)
+int c4iw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
+ struct ib_udata *udata)
{
+ struct ib_pd *pd = qp->pd;
struct c4iw_dev *rhp;
- struct c4iw_qp *qhp;
+ struct c4iw_qp *qhp = to_c4iw_qp(qp);
struct c4iw_pd *php;
struct c4iw_cq *schp;
struct c4iw_cq *rchp;
@@ -2124,44 +2123,36 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
struct c4iw_mm_entry *sq_key_mm, *rq_key_mm = NULL, *sq_db_key_mm;
struct c4iw_mm_entry *rq_db_key_mm = NULL, *ma_sync_key_mm = NULL;
- pr_debug("ib_pd %p\n", pd);
-
if (attrs->qp_type != IB_QPT_RC || attrs->create_flags)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
php = to_c4iw_pd(pd);
rhp = php->rhp;
schp = get_chp(rhp, ((struct c4iw_cq *)attrs->send_cq)->cq.cqid);
rchp = get_chp(rhp, ((struct c4iw_cq *)attrs->recv_cq)->cq.cqid);
if (!schp || !rchp)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
if (attrs->cap.max_inline_data > T4_MAX_SEND_INLINE)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
if (!attrs->srq) {
if (attrs->cap.max_recv_wr > rhp->rdev.hw_queue.t4_max_rq_size)
- return ERR_PTR(-E2BIG);
+ return -E2BIG;
rqsize = attrs->cap.max_recv_wr + 1;
if (rqsize < 8)
rqsize = 8;
}
if (attrs->cap.max_send_wr > rhp->rdev.hw_queue.t4_max_sq_size)
- return ERR_PTR(-E2BIG);
+ return -E2BIG;
sqsize = attrs->cap.max_send_wr + 1;
if (sqsize < 8)
sqsize = 8;
- qhp = kzalloc(sizeof(*qhp), GFP_KERNEL);
- if (!qhp)
- return ERR_PTR(-ENOMEM);
-
qhp->wr_waitp = c4iw_alloc_wr_wait(GFP_KERNEL);
- if (!qhp->wr_waitp) {
- ret = -ENOMEM;
- goto err_free_qhp;
- }
+ if (!qhp->wr_waitp)
+ return -ENOMEM;
qhp->wq.sq.size = sqsize;
qhp->wq.sq.memsize =
@@ -2339,7 +2330,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
qhp->wq.sq.qid, qhp->wq.sq.size, qhp->wq.sq.memsize,
attrs->cap.max_send_wr, qhp->wq.rq.qid, qhp->wq.rq.size,
qhp->wq.rq.memsize, attrs->cap.max_recv_wr);
- return &qhp->ibqp;
+ return 0;
err_free_ma_sync_key:
kfree(ma_sync_key_mm);
err_free_rq_db_key:
@@ -2359,9 +2350,7 @@ err_destroy_qp:
ucontext ? &ucontext->uctx : &rhp->rdev.uctx, !attrs->srq);
err_free_wr_wait:
c4iw_put_wr_wait(qhp->wr_waitp);
-err_free_qhp:
- kfree(qhp);
- return ERR_PTR(ret);
+ return ret;
}
int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
diff --git a/drivers/infiniband/hw/efa/efa.h b/drivers/infiniband/hw/efa/efa.h
index 2b8ca099b381..87b1dadeb7fe 100644
--- a/drivers/infiniband/hw/efa/efa.h
+++ b/drivers/infiniband/hw/efa/efa.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
/*
- * Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#ifndef _EFA_H_
@@ -27,8 +27,7 @@
struct efa_irq {
irq_handler_t handler;
void *data;
- int cpu;
- u32 vector;
+ u32 irqn;
cpumask_t affinity_hint_mask;
char name[EFA_IRQNAME_SIZE];
};
@@ -132,9 +131,8 @@ int efa_query_pkey(struct ib_device *ibdev, u32 port, u16 index,
int efa_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
int efa_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
int efa_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
-struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata);
+int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
struct ib_udata *udata);
diff --git a/drivers/infiniband/hw/efa/efa_main.c b/drivers/infiniband/hw/efa/efa_main.c
index be4a07bd268a..417dea5f90cf 100644
--- a/drivers/infiniband/hw/efa/efa_main.c
+++ b/drivers/infiniband/hw/efa/efa_main.c
@@ -83,8 +83,7 @@ static int efa_request_mgmnt_irq(struct efa_dev *dev)
int err;
irq = &dev->admin_irq;
- err = request_irq(irq->vector, irq->handler, 0, irq->name,
- irq->data);
+ err = request_irq(irq->irqn, irq->handler, 0, irq->name, irq->data);
if (err) {
dev_err(&dev->pdev->dev, "Failed to request admin irq (%d)\n",
err);
@@ -92,8 +91,8 @@ static int efa_request_mgmnt_irq(struct efa_dev *dev)
}
dev_dbg(&dev->pdev->dev, "Set affinity hint of mgmnt irq to %*pbl (irq vector: %d)\n",
- nr_cpumask_bits, &irq->affinity_hint_mask, irq->vector);
- irq_set_affinity_hint(irq->vector, &irq->affinity_hint_mask);
+ nr_cpumask_bits, &irq->affinity_hint_mask, irq->irqn);
+ irq_set_affinity_hint(irq->irqn, &irq->affinity_hint_mask);
return 0;
}
@@ -106,15 +105,13 @@ static void efa_setup_mgmnt_irq(struct efa_dev *dev)
"efa-mgmnt@pci:%s", pci_name(dev->pdev));
dev->admin_irq.handler = efa_intr_msix_mgmnt;
dev->admin_irq.data = dev;
- dev->admin_irq.vector =
+ dev->admin_irq.irqn =
pci_irq_vector(dev->pdev, dev->admin_msix_vector_idx);
cpu = cpumask_first(cpu_online_mask);
- dev->admin_irq.cpu = cpu;
cpumask_set_cpu(cpu,
&dev->admin_irq.affinity_hint_mask);
- dev_info(&dev->pdev->dev, "Setup irq:0x%p vector:%d name:%s\n",
- &dev->admin_irq,
- dev->admin_irq.vector,
+ dev_info(&dev->pdev->dev, "Setup irq:%d name:%s\n",
+ dev->admin_irq.irqn,
dev->admin_irq.name);
}
@@ -123,8 +120,8 @@ static void efa_free_mgmnt_irq(struct efa_dev *dev)
struct efa_irq *irq;
irq = &dev->admin_irq;
- irq_set_affinity_hint(irq->vector, NULL);
- free_irq(irq->vector, irq->data);
+ irq_set_affinity_hint(irq->irqn, NULL);
+ free_irq(irq->irqn, irq->data);
}
static int efa_set_mgmnt_irq(struct efa_dev *dev)
@@ -271,6 +268,7 @@ static const struct ib_device_ops efa_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, efa_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, efa_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, efa_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, efa_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_ucontext, efa_ucontext, ibucontext),
};
diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c
index be6d3ff0f1be..e5f9d90aad5e 100644
--- a/drivers/infiniband/hw/efa/efa_verbs.c
+++ b/drivers/infiniband/hw/efa/efa_verbs.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/*
- * Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#include <linux/vmalloc.h>
@@ -30,7 +30,21 @@ struct efa_user_mmap_entry {
u8 mmap_flag;
};
-#define EFA_DEFINE_STATS(op) \
+#define EFA_DEFINE_DEVICE_STATS(op) \
+ op(EFA_SUBMITTED_CMDS, "submitted_cmds") \
+ op(EFA_COMPLETED_CMDS, "completed_cmds") \
+ op(EFA_CMDS_ERR, "cmds_err") \
+ op(EFA_NO_COMPLETION_CMDS, "no_completion_cmds") \
+ op(EFA_KEEP_ALIVE_RCVD, "keep_alive_rcvd") \
+ op(EFA_ALLOC_PD_ERR, "alloc_pd_err") \
+ op(EFA_CREATE_QP_ERR, "create_qp_err") \
+ op(EFA_CREATE_CQ_ERR, "create_cq_err") \
+ op(EFA_REG_MR_ERR, "reg_mr_err") \
+ op(EFA_ALLOC_UCONTEXT_ERR, "alloc_ucontext_err") \
+ op(EFA_CREATE_AH_ERR, "create_ah_err") \
+ op(EFA_MMAP_ERR, "mmap_err")
+
+#define EFA_DEFINE_PORT_STATS(op) \
op(EFA_TX_BYTES, "tx_bytes") \
op(EFA_TX_PKTS, "tx_pkts") \
op(EFA_RX_BYTES, "rx_bytes") \
@@ -44,28 +58,24 @@ struct efa_user_mmap_entry {
op(EFA_RDMA_READ_BYTES, "rdma_read_bytes") \
op(EFA_RDMA_READ_WR_ERR, "rdma_read_wr_err") \
op(EFA_RDMA_READ_RESP_BYTES, "rdma_read_resp_bytes") \
- op(EFA_SUBMITTED_CMDS, "submitted_cmds") \
- op(EFA_COMPLETED_CMDS, "completed_cmds") \
- op(EFA_CMDS_ERR, "cmds_err") \
- op(EFA_NO_COMPLETION_CMDS, "no_completion_cmds") \
- op(EFA_KEEP_ALIVE_RCVD, "keep_alive_rcvd") \
- op(EFA_ALLOC_PD_ERR, "alloc_pd_err") \
- op(EFA_CREATE_QP_ERR, "create_qp_err") \
- op(EFA_CREATE_CQ_ERR, "create_cq_err") \
- op(EFA_REG_MR_ERR, "reg_mr_err") \
- op(EFA_ALLOC_UCONTEXT_ERR, "alloc_ucontext_err") \
- op(EFA_CREATE_AH_ERR, "create_ah_err") \
- op(EFA_MMAP_ERR, "mmap_err")
#define EFA_STATS_ENUM(ename, name) ename,
#define EFA_STATS_STR(ename, name) [ename] = name,
-enum efa_hw_stats {
- EFA_DEFINE_STATS(EFA_STATS_ENUM)
+enum efa_hw_device_stats {
+ EFA_DEFINE_DEVICE_STATS(EFA_STATS_ENUM)
};
-static const char *const efa_stats_names[] = {
- EFA_DEFINE_STATS(EFA_STATS_STR)
+static const char *const efa_device_stats_names[] = {
+ EFA_DEFINE_DEVICE_STATS(EFA_STATS_STR)
+};
+
+enum efa_hw_port_stats {
+ EFA_DEFINE_PORT_STATS(EFA_STATS_ENUM)
+};
+
+static const char *const efa_port_stats_names[] = {
+ EFA_DEFINE_PORT_STATS(EFA_STATS_STR)
};
#define EFA_CHUNK_PAYLOAD_SHIFT 12
@@ -440,7 +450,6 @@ int efa_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
qp->rq_size, DMA_TO_DEVICE);
}
- kfree(qp);
return 0;
}
@@ -599,17 +608,16 @@ static int efa_qp_validate_attr(struct efa_dev *dev,
return 0;
}
-struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata)
+int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
{
struct efa_com_create_qp_params create_qp_params = {};
struct efa_com_create_qp_result create_qp_resp;
- struct efa_dev *dev = to_edev(ibpd->device);
+ struct efa_dev *dev = to_edev(ibqp->device);
struct efa_ibv_create_qp_resp resp = {};
struct efa_ibv_create_qp cmd = {};
+ struct efa_qp *qp = to_eqp(ibqp);
struct efa_ucontext *ucontext;
- struct efa_qp *qp;
int err;
ucontext = rdma_udata_to_drv_context(udata, struct efa_ucontext,
@@ -654,14 +662,8 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
goto err_out;
}
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp) {
- err = -ENOMEM;
- goto err_out;
- }
-
create_qp_params.uarn = ucontext->uarn;
- create_qp_params.pd = to_epd(ibpd)->pdn;
+ create_qp_params.pd = to_epd(ibqp->pd)->pdn;
if (init_attr->qp_type == IB_QPT_UD) {
create_qp_params.qp_type = EFA_ADMIN_QP_TYPE_UD;
@@ -672,7 +674,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
"Unsupported qp type %d driver qp type %d\n",
init_attr->qp_type, cmd.driver_qp_type);
err = -EOPNOTSUPP;
- goto err_free_qp;
+ goto err_out;
}
ibdev_dbg(&dev->ibdev, "Create QP: qp type %d driver qp type %#x\n",
@@ -690,7 +692,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
qp->rq_size, DMA_TO_DEVICE);
if (!qp->rq_cpu_addr) {
err = -ENOMEM;
- goto err_free_qp;
+ goto err_out;
}
ibdev_dbg(&dev->ibdev,
@@ -717,7 +719,6 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
qp->qp_handle = create_qp_resp.qp_handle;
qp->ibqp.qp_num = create_qp_resp.qp_num;
- qp->ibqp.qp_type = init_attr->qp_type;
qp->max_send_wr = init_attr->cap.max_send_wr;
qp->max_recv_wr = init_attr->cap.max_recv_wr;
qp->max_send_sge = init_attr->cap.max_send_sge;
@@ -737,7 +738,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
ibdev_dbg(&dev->ibdev, "Created qp[%d]\n", qp->ibqp.qp_num);
- return &qp->ibqp;
+ return 0;
err_remove_mmap_entries:
efa_qp_user_mmap_entries_remove(qp);
@@ -747,11 +748,9 @@ err_free_mapped:
if (qp->rq_size)
efa_free_mapped(dev, qp->rq_cpu_addr, qp->rq_dma_addr,
qp->rq_size, DMA_TO_DEVICE);
-err_free_qp:
- kfree(qp);
err_out:
atomic64_inc(&dev->stats.create_qp_err);
- return ERR_PTR(err);
+ return err;
}
static const struct {
@@ -1904,33 +1903,53 @@ int efa_destroy_ah(struct ib_ah *ibah, u32 flags)
return 0;
}
-struct rdma_hw_stats *efa_alloc_hw_port_stats(struct ib_device *ibdev, u32 port_num)
+struct rdma_hw_stats *efa_alloc_hw_port_stats(struct ib_device *ibdev,
+ u32 port_num)
{
- return rdma_alloc_hw_stats_struct(efa_stats_names,
- ARRAY_SIZE(efa_stats_names),
+ return rdma_alloc_hw_stats_struct(efa_port_stats_names,
+ ARRAY_SIZE(efa_port_stats_names),
RDMA_HW_STATS_DEFAULT_LIFESPAN);
}
struct rdma_hw_stats *efa_alloc_hw_device_stats(struct ib_device *ibdev)
{
- /*
- * It is probably a bug that efa reports its port stats as device
- * stats
- */
- return efa_alloc_hw_port_stats(ibdev, 0);
+ return rdma_alloc_hw_stats_struct(efa_device_stats_names,
+ ARRAY_SIZE(efa_device_stats_names),
+ RDMA_HW_STATS_DEFAULT_LIFESPAN);
}
-int efa_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
- u32 port_num, int index)
+static int efa_fill_device_stats(struct efa_dev *dev,
+ struct rdma_hw_stats *stats)
+{
+ struct efa_com_stats_admin *as = &dev->edev.aq.stats;
+ struct efa_stats *s = &dev->stats;
+
+ stats->value[EFA_SUBMITTED_CMDS] = atomic64_read(&as->submitted_cmd);
+ stats->value[EFA_COMPLETED_CMDS] = atomic64_read(&as->completed_cmd);
+ stats->value[EFA_CMDS_ERR] = atomic64_read(&as->cmd_err);
+ stats->value[EFA_NO_COMPLETION_CMDS] = atomic64_read(&as->no_completion);
+
+ stats->value[EFA_KEEP_ALIVE_RCVD] = atomic64_read(&s->keep_alive_rcvd);
+ stats->value[EFA_ALLOC_PD_ERR] = atomic64_read(&s->alloc_pd_err);
+ stats->value[EFA_CREATE_QP_ERR] = atomic64_read(&s->create_qp_err);
+ stats->value[EFA_CREATE_CQ_ERR] = atomic64_read(&s->create_cq_err);
+ stats->value[EFA_REG_MR_ERR] = atomic64_read(&s->reg_mr_err);
+ stats->value[EFA_ALLOC_UCONTEXT_ERR] =
+ atomic64_read(&s->alloc_ucontext_err);
+ stats->value[EFA_CREATE_AH_ERR] = atomic64_read(&s->create_ah_err);
+ stats->value[EFA_MMAP_ERR] = atomic64_read(&s->mmap_err);
+
+ return ARRAY_SIZE(efa_device_stats_names);
+}
+
+static int efa_fill_port_stats(struct efa_dev *dev, struct rdma_hw_stats *stats,
+ u32 port_num)
{
struct efa_com_get_stats_params params = {};
union efa_com_get_stats_result result;
- struct efa_dev *dev = to_edev(ibdev);
struct efa_com_rdma_read_stats *rrs;
struct efa_com_messages_stats *ms;
struct efa_com_basic_stats *bs;
- struct efa_com_stats_admin *as;
- struct efa_stats *s;
int err;
params.scope = EFA_ADMIN_GET_STATS_SCOPE_ALL;
@@ -1969,24 +1988,16 @@ int efa_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
stats->value[EFA_RDMA_READ_WR_ERR] = rrs->read_wr_err;
stats->value[EFA_RDMA_READ_RESP_BYTES] = rrs->read_resp_bytes;
- as = &dev->edev.aq.stats;
- stats->value[EFA_SUBMITTED_CMDS] = atomic64_read(&as->submitted_cmd);
- stats->value[EFA_COMPLETED_CMDS] = atomic64_read(&as->completed_cmd);
- stats->value[EFA_CMDS_ERR] = atomic64_read(&as->cmd_err);
- stats->value[EFA_NO_COMPLETION_CMDS] = atomic64_read(&as->no_completion);
-
- s = &dev->stats;
- stats->value[EFA_KEEP_ALIVE_RCVD] = atomic64_read(&s->keep_alive_rcvd);
- stats->value[EFA_ALLOC_PD_ERR] = atomic64_read(&s->alloc_pd_err);
- stats->value[EFA_CREATE_QP_ERR] = atomic64_read(&s->create_qp_err);
- stats->value[EFA_CREATE_CQ_ERR] = atomic64_read(&s->create_cq_err);
- stats->value[EFA_REG_MR_ERR] = atomic64_read(&s->reg_mr_err);
- stats->value[EFA_ALLOC_UCONTEXT_ERR] =
- atomic64_read(&s->alloc_ucontext_err);
- stats->value[EFA_CREATE_AH_ERR] = atomic64_read(&s->create_ah_err);
- stats->value[EFA_MMAP_ERR] = atomic64_read(&s->mmap_err);
+ return ARRAY_SIZE(efa_port_stats_names);
+}
- return ARRAY_SIZE(efa_stats_names);
+int efa_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
+ u32 port_num, int index)
+{
+ if (port_num)
+ return efa_fill_port_stats(to_edev(ibdev), stats, port_num);
+ else
+ return efa_fill_device_stats(to_edev(ibdev), stats);
}
enum rdma_link_layer efa_port_link_layer(struct ib_device *ibdev,
diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c
index 16543f717527..98c813ba4304 100644
--- a/drivers/infiniband/hw/hfi1/affinity.c
+++ b/drivers/infiniband/hw/hfi1/affinity.c
@@ -1,49 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#include <linux/topology.h>
#include <linux/cpumask.h>
#include <linux/module.h>
diff --git a/drivers/infiniband/hw/hfi1/affinity.h b/drivers/infiniband/hw/hfi1/affinity.h
index f94ed5d7c7a3..00854f21787f 100644
--- a/drivers/infiniband/hw/hfi1/affinity.h
+++ b/drivers/infiniband/hw/hfi1/affinity.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#ifndef _HFI1_AFFINITY_H
#define _HFI1_AFFINITY_H
diff --git a/drivers/infiniband/hw/hfi1/aspm.h b/drivers/infiniband/hw/hfi1/aspm.h
index 75d5d18da3da..df295f47b315 100644
--- a/drivers/infiniband/hw/hfi1/aspm.h
+++ b/drivers/infiniband/hw/hfi1/aspm.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015-2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#ifndef _ASPM_H
#define _ASPM_H
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index c97544638367..37273dc0c03c 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
/*
@@ -14414,7 +14372,7 @@ static void init_qos(struct hfi1_devdata *dd, struct rsm_map_table *rmt)
if (rmt->used + rmt_entries >= NUM_MAP_ENTRIES)
goto bail;
- /* add qos entries to the the RSM map table */
+ /* add qos entries to the RSM map table */
for (i = 0, ctxt = FIRST_KERNEL_KCTXT; i < num_vls; i++) {
unsigned tctxt;
@@ -14893,7 +14851,7 @@ int hfi1_clear_ctxt_pkey(struct hfi1_devdata *dd, struct hfi1_ctxtdata *ctxt)
}
/*
- * Start doing the clean up the the chip. Our clean up happens in multiple
+ * Start doing the clean up the chip. Our clean up happens in multiple
* stages and this is just the first.
*/
void hfi1_start_cleanup(struct hfi1_devdata *dd)
@@ -15336,7 +15294,7 @@ int hfi1_init_dd(struct hfi1_devdata *dd)
init_completion(&dd->user_comp);
/* The user refcount starts with one to inidicate an active device */
- atomic_set(&dd->user_refcount, 1);
+ refcount_set(&dd->user_refcount, 1);
goto bail;
diff --git a/drivers/infiniband/hw/hfi1/chip.h b/drivers/infiniband/hw/hfi1/chip.h
index ac26649d4463..b2d53713da58 100644
--- a/drivers/infiniband/hw/hfi1/chip.h
+++ b/drivers/infiniband/hw/hfi1/chip.h
@@ -1,52 +1,10 @@
-#ifndef _CHIP_H
-#define _CHIP_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _CHIP_H
+#define _CHIP_H
/*
* This file contains all of the defines that is specific to the HFI chip
*/
diff --git a/drivers/infiniband/hw/hfi1/chip_registers.h b/drivers/infiniband/hw/hfi1/chip_registers.h
index fb3ec9bff7a2..95a8d530d554 100644
--- a/drivers/infiniband/hw/hfi1/chip_registers.h
+++ b/drivers/infiniband/hw/hfi1/chip_registers.h
@@ -1,53 +1,11 @@
-#ifndef DEF_CHIP_REG
-#define DEF_CHIP_REG
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_CHIP_REG
+#define DEF_CHIP_REG
+
#define CORE 0x000000000000
#define CCE (CORE + 0x000000000000)
#define ASIC (CORE + 0x000000400000)
diff --git a/drivers/infiniband/hw/hfi1/common.h b/drivers/infiniband/hw/hfi1/common.h
index ff423e546b80..995991d9709d 100644
--- a/drivers/infiniband/hw/hfi1/common.h
+++ b/drivers/infiniband/hw/hfi1/common.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#ifndef _COMMON_H
diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c
index 2ced236e1553..22a3cdb940be 100644
--- a/drivers/infiniband/hw/hfi1/debugfs.c
+++ b/drivers/infiniband/hw/hfi1/debugfs.c
@@ -1,49 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015-2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/kernel.h>
@@ -1358,7 +1317,7 @@ static void _driver_stats_seq_stop(struct seq_file *s, void *v)
{
}
-static u64 hfi1_sps_ints(void)
+static void hfi1_sps_show_ints(struct seq_file *s)
{
unsigned long index, flags;
struct hfi1_devdata *dd;
@@ -1369,24 +1328,19 @@ static u64 hfi1_sps_ints(void)
sps_ints += get_all_cpu_total(dd->int_counter);
}
xa_unlock_irqrestore(&hfi1_dev_table, flags);
- return sps_ints;
+ seq_write(s, &sps_ints, sizeof(u64));
}
static int _driver_stats_seq_show(struct seq_file *s, void *v)
{
loff_t *spos = v;
- char *buffer;
u64 *stats = (u64 *)&hfi1_stats;
- size_t sz = seq_get_buf(s, &buffer);
- if (sz < sizeof(u64))
- return SEQ_SKIP;
/* special case for interrupts */
if (*spos == 0)
- *(u64 *)buffer = hfi1_sps_ints();
+ hfi1_sps_show_ints(s);
else
- *(u64 *)buffer = stats[*spos];
- seq_commit(s, sizeof(u64));
+ seq_write(s, stats + *spos, sizeof(u64));
return 0;
}
diff --git a/drivers/infiniband/hw/hfi1/debugfs.h b/drivers/infiniband/hw/hfi1/debugfs.h
index 57e582caa5eb..29a5a8de2c41 100644
--- a/drivers/infiniband/hw/hfi1/debugfs.h
+++ b/drivers/infiniband/hw/hfi1/debugfs.h
@@ -1,52 +1,11 @@
-#ifndef _HFI1_DEBUGFS_H
-#define _HFI1_DEBUGFS_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016, 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_DEBUGFS_H
+#define _HFI1_DEBUGFS_H
+
struct hfi1_ibdev;
#define DEBUGFS_SEQ_FILE_OPS(name) \
diff --git a/drivers/infiniband/hw/hfi1/device.c b/drivers/infiniband/hw/hfi1/device.c
index bbb6069dec2a..68a184c39941 100644
--- a/drivers/infiniband/hw/hfi1/device.c
+++ b/drivers/infiniband/hw/hfi1/device.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/cdev.h>
diff --git a/drivers/infiniband/hw/hfi1/device.h b/drivers/infiniband/hw/hfi1/device.h
index c3ec19cb0ac9..c371b5612b6b 100644
--- a/drivers/infiniband/hw/hfi1/device.h
+++ b/drivers/infiniband/hw/hfi1/device.h
@@ -1,52 +1,11 @@
-#ifndef _HFI1_DEVICE_H
-#define _HFI1_DEVICE_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_DEVICE_H
+#define _HFI1_DEVICE_H
+
int hfi1_cdev_init(int minor, const char *name,
const struct file_operations *fops,
struct cdev *cdev, struct device **devp,
diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c
index f88bb4af245f..de411884386b 100644
--- a/drivers/infiniband/hw/hfi1/driver.c
+++ b/drivers/infiniband/hw/hfi1/driver.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015-2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/spinlock.h>
diff --git a/drivers/infiniband/hw/hfi1/efivar.c b/drivers/infiniband/hw/hfi1/efivar.c
index c22ab7b5163b..f275dd1abed8 100644
--- a/drivers/infiniband/hw/hfi1/efivar.c
+++ b/drivers/infiniband/hw/hfi1/efivar.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/ctype.h>
diff --git a/drivers/infiniband/hw/hfi1/efivar.h b/drivers/infiniband/hw/hfi1/efivar.h
index 94e9e70de568..5ebc2f07bbef 100644
--- a/drivers/infiniband/hw/hfi1/efivar.h
+++ b/drivers/infiniband/hw/hfi1/efivar.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#ifndef _HFI1_EFIVAR_H
#define _HFI1_EFIVAR_H
diff --git a/drivers/infiniband/hw/hfi1/eprom.c b/drivers/infiniband/hw/hfi1/eprom.c
index 1613af1c58d9..fbe958107457 100644
--- a/drivers/infiniband/hw/hfi1/eprom.c
+++ b/drivers/infiniband/hw/hfi1/eprom.c
@@ -1,49 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#include <linux/delay.h>
#include "hfi.h"
#include "common.h"
diff --git a/drivers/infiniband/hw/hfi1/eprom.h b/drivers/infiniband/hw/hfi1/eprom.h
index e774184f1643..772c516366ce 100644
--- a/drivers/infiniband/hw/hfi1/eprom.h
+++ b/drivers/infiniband/hw/hfi1/eprom.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
struct hfi1_devdata;
diff --git a/drivers/infiniband/hw/hfi1/exp_rcv.c b/drivers/infiniband/hw/hfi1/exp_rcv.c
index a414214f6035..b86f697c7956 100644
--- a/drivers/infiniband/hw/hfi1/exp_rcv.c
+++ b/drivers/infiniband/hw/hfi1/exp_rcv.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include "exp_rcv.h"
diff --git a/drivers/infiniband/hw/hfi1/exp_rcv.h b/drivers/infiniband/hw/hfi1/exp_rcv.h
index f25362015095..c6291bbf723c 100644
--- a/drivers/infiniband/hw/hfi1/exp_rcv.h
+++ b/drivers/infiniband/hw/hfi1/exp_rcv.h
@@ -1,52 +1,10 @@
-#ifndef _HFI1_EXP_RCV_H
-#define _HFI1_EXP_RCV_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_EXP_RCV_H
+#define _HFI1_EXP_RCV_H
#include "hfi.h"
#define EXP_TID_SET_EMPTY(set) (set.count == 0 && list_empty(&set.list))
diff --git a/drivers/infiniband/hw/hfi1/fault.c b/drivers/infiniband/hw/hfi1/fault.c
index 0dfbcfb048ca..e2e4f9f6fae2 100644
--- a/drivers/infiniband/hw/hfi1/fault.c
+++ b/drivers/infiniband/hw/hfi1/fault.c
@@ -1,49 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/kernel.h>
diff --git a/drivers/infiniband/hw/hfi1/fault.h b/drivers/infiniband/hw/hfi1/fault.h
index a83382700a7c..7fe7f47219db 100644
--- a/drivers/infiniband/hw/hfi1/fault.h
+++ b/drivers/infiniband/hw/hfi1/fault.h
@@ -1,51 +1,11 @@
-#ifndef _HFI1_FAULT_H
-#define _HFI1_FAULT_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
+#ifndef _HFI1_FAULT_H
+#define _HFI1_FAULT_H
+
#include <linux/fault-inject.h>
#include <linux/dcache.h>
#include <linux/bitops.h>
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index 955c3637980e..1783a6ea5427 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -1,50 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2020 Cornelis Networks, Inc.
* Copyright(c) 2015-2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#include <linux/poll.h>
#include <linux/cdev.h>
#include <linux/vmalloc.h>
@@ -194,7 +153,7 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
if (!((dd->flags & HFI1_PRESENT) && dd->kregbase1))
return -EINVAL;
- if (!atomic_inc_not_zero(&dd->user_refcount))
+ if (!refcount_inc_not_zero(&dd->user_refcount))
return -ENXIO;
/* The real work is performed later in assign_ctxt() */
@@ -213,7 +172,7 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
nomem:
kfree(fd);
fp->private_data = NULL;
- if (atomic_dec_and_test(&dd->user_refcount))
+ if (refcount_dec_and_test(&dd->user_refcount))
complete(&dd->user_comp);
return -ENOMEM;
}
@@ -711,7 +670,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
deallocate_ctxt(uctxt);
done:
- if (atomic_dec_and_test(&dd->user_refcount))
+ if (refcount_dec_and_test(&dd->user_refcount))
complete(&dd->user_comp);
cleanup_srcu_struct(&fdata->pq_srcu);
diff --git a/drivers/infiniband/hw/hfi1/firmware.c b/drivers/infiniband/hw/hfi1/firmware.c
index 2cf102b5abd4..31e63e245ea9 100644
--- a/drivers/infiniband/hw/hfi1/firmware.c
+++ b/drivers/infiniband/hw/hfi1/firmware.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/firmware.h>
diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h
index 31664f43c27f..7fa9cd39254f 100644
--- a/drivers/infiniband/hw/hfi1/hfi.h
+++ b/drivers/infiniband/hw/hfi1/hfi.h
@@ -1,53 +1,13 @@
-#ifndef _HFI1_KERNEL_H
-#define _HFI1_KERNEL_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2020 Cornelis Networks, Inc.
* Copyright(c) 2015-2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_KERNEL_H
+#define _HFI1_KERNEL_H
+
+#include <linux/refcount.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
@@ -1384,7 +1344,7 @@ struct hfi1_devdata {
/* Number of verbs contexts which have disabled ASPM */
atomic_t aspm_disabled_cnt;
/* Keeps track of user space clients */
- atomic_t user_refcount;
+ refcount_t user_refcount;
/* Used to wait for outstanding user space clients before dev removal */
struct completion user_comp;
@@ -2601,7 +2561,7 @@ static inline bool hfi1_get_hdr_type(u32 lid, struct rdma_ah_attr *attr)
HFI1_PKT_TYPE_16B : HFI1_PKT_TYPE_9B;
/*
- * Return a 16B header type if either the the destination
+ * Return a 16B header type if either the destination
* or source lid is extended.
*/
if (hfi1_get_packet_type(rdma_ah_get_dlid(attr)) == HFI1_PKT_TYPE_16B)
diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c
index 0986aa065418..e3679d076eaa 100644
--- a/drivers/infiniband/hw/hfi1/init.c
+++ b/drivers/infiniband/hw/hfi1/init.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/pci.h>
@@ -650,12 +608,7 @@ void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd,
ppd->pkeys[default_pkey_idx] = DEFAULT_P_KEY;
ppd->part_enforce |= HFI1_PART_ENFORCE_IN;
-
- if (loopback) {
- dd_dev_err(dd, "Faking data partition 0x8001 in idx %u\n",
- !default_pkey_idx);
- ppd->pkeys[!default_pkey_idx] = 0x8001;
- }
+ ppd->pkeys[0] = 0x8001;
INIT_WORK(&ppd->link_vc_work, handle_verify_cap);
INIT_WORK(&ppd->link_up_work, handle_link_up);
@@ -1752,7 +1705,7 @@ static void wait_for_clients(struct hfi1_devdata *dd)
* Remove the device init value and complete the device if there is
* no clients or wait for active clients to finish.
*/
- if (atomic_dec_and_test(&dd->user_refcount))
+ if (refcount_dec_and_test(&dd->user_refcount))
complete(&dd->user_comp);
wait_for_completion(&dd->user_comp);
diff --git a/drivers/infiniband/hw/hfi1/intr.c b/drivers/infiniband/hw/hfi1/intr.c
index 5ba5c11459e7..70376e6dba33 100644
--- a/drivers/infiniband/hw/hfi1/intr.c
+++ b/drivers/infiniband/hw/hfi1/intr.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/pci.h>
diff --git a/drivers/infiniband/hw/hfi1/iowait.h b/drivers/infiniband/hw/hfi1/iowait.h
index cda81a7843c2..4df0700cbaba 100644
--- a/drivers/infiniband/hw/hfi1/iowait.h
+++ b/drivers/infiniband/hw/hfi1/iowait.h
@@ -1,52 +1,11 @@
-#ifndef _HFI1_IOWAIT_H
-#define _HFI1_IOWAIT_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_IOWAIT_H
+#define _HFI1_IOWAIT_H
+
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
diff --git a/drivers/infiniband/hw/hfi1/ipoib_tx.c b/drivers/infiniband/hw/hfi1/ipoib_tx.c
index 993f9838b6c8..e74ddbe46589 100644
--- a/drivers/infiniband/hw/hfi1/ipoib_tx.c
+++ b/drivers/infiniband/hw/hfi1/ipoib_tx.c
@@ -644,10 +644,13 @@ static int hfi1_ipoib_sdma_sleep(struct sdma_engine *sde,
/* came from non-list submit */
list_add_tail(&txreq->list, &txq->tx_list);
if (list_empty(&txq->wait.list)) {
+ struct hfi1_ibport *ibp = &sde->ppd->ibport_data;
+
if (!atomic_xchg(&txq->no_desc, 1)) {
trace_hfi1_txq_queued(txq);
hfi1_ipoib_stop_txq(txq);
}
+ ibp->rvp.n_dmawait++;
iowait_queue(pkts_sent, wait->iow, &sde->dmawait);
}
diff --git a/drivers/infiniband/hw/hfi1/mad.c b/drivers/infiniband/hw/hfi1/mad.c
index 1fe5e702f31d..4146a2113a95 100644
--- a/drivers/infiniband/hw/hfi1/mad.c
+++ b/drivers/infiniband/hw/hfi1/mad.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015-2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/net.h>
diff --git a/drivers/infiniband/hw/hfi1/mad.h b/drivers/infiniband/hw/hfi1/mad.h
index 0205d308ef5e..1d45a008fa7f 100644
--- a/drivers/infiniband/hw/hfi1/mad.h
+++ b/drivers/infiniband/hw/hfi1/mad.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#ifndef _HFI1_MAD_H
#define _HFI1_MAD_H
diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.c b/drivers/infiniband/hw/hfi1/mmu_rb.c
index d213f65d4cdd..876cc78a22cc 100644
--- a/drivers/infiniband/hw/hfi1/mmu_rb.c
+++ b/drivers/infiniband/hw/hfi1/mmu_rb.c
@@ -1,50 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2020 Cornelis Networks, Inc.
* Copyright(c) 2016 - 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#include <linux/list.h>
#include <linux/rculist.h>
#include <linux/mmu_notifier.h>
diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.h b/drivers/infiniband/hw/hfi1/mmu_rb.h
index 423aacc67e94..7417be2b9dc8 100644
--- a/drivers/infiniband/hw/hfi1/mmu_rb.h
+++ b/drivers/infiniband/hw/hfi1/mmu_rb.h
@@ -1,50 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2020 Cornelis Networks, Inc.
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#ifndef _HFI1_MMU_RB_H
#define _HFI1_MMU_RB_H
diff --git a/drivers/infiniband/hw/hfi1/msix.c b/drivers/infiniband/hw/hfi1/msix.c
index 57a5f02ebc77..77d2ece9a9cb 100644
--- a/drivers/infiniband/hw/hfi1/msix.c
+++ b/drivers/infiniband/hw/hfi1/msix.c
@@ -1,49 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
* Copyright(c) 2018 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include "hfi.h"
diff --git a/drivers/infiniband/hw/hfi1/msix.h b/drivers/infiniband/hw/hfi1/msix.h
index e63e944bf0fc..9530ccb0a2ce 100644
--- a/drivers/infiniband/hw/hfi1/msix.h
+++ b/drivers/infiniband/hw/hfi1/msix.h
@@ -1,50 +1,8 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Copyright(c) 2018 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#ifndef _HFI1_MSIX_H
#define _HFI1_MSIX_H
diff --git a/drivers/infiniband/hw/hfi1/opa_compat.h b/drivers/infiniband/hw/hfi1/opa_compat.h
index 774215b95df5..31570b0cfd18 100644
--- a/drivers/infiniband/hw/hfi1/opa_compat.h
+++ b/drivers/infiniband/hw/hfi1/opa_compat.h
@@ -1,52 +1,10 @@
-#ifndef _LINUX_H
-#define _LINUX_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _LINUX_H
+#define _LINUX_H
/*
* This header file is for OPA-specific definitions which are
* required by the HFI driver, and which aren't yet in the Linux
diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c
index 6f06e9920503..a0802332c8cb 100644
--- a/drivers/infiniband/hw/hfi1/pcie.c
+++ b/drivers/infiniband/hw/hfi1/pcie.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2019 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/pci.h>
@@ -92,25 +50,18 @@ int hfi1_pcie_init(struct hfi1_devdata *dd)
goto bail;
}
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (ret) {
/*
* If the 64 bit setup fails, try 32 bit. Some systems
* do not setup 64 bit maps on systems with 2GB or less
* memory installed.
*/
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
dd_dev_err(dd, "Unable to set DMA mask: %d\n", ret);
goto bail;
}
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- } else {
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- }
- if (ret) {
- dd_dev_err(dd, "Unable to set DMA consistent mask: %d\n", ret);
- goto bail;
}
pci_set_master(pdev);
diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c
index e276522104c6..489b436f19bb 100644
--- a/drivers/infiniband/hw/hfi1/pio.c
+++ b/drivers/infiniband/hw/hfi1/pio.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015-2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/delay.h>
diff --git a/drivers/infiniband/hw/hfi1/pio.h b/drivers/infiniband/hw/hfi1/pio.h
index 9e5f08d2b985..ea714008f261 100644
--- a/drivers/infiniband/hw/hfi1/pio.h
+++ b/drivers/infiniband/hw/hfi1/pio.h
@@ -1,52 +1,10 @@
-#ifndef _PIO_H
-#define _PIO_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015-2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _PIO_H
+#define _PIO_H
/* send context types */
#define SC_KERNEL 0
#define SC_VL15 1
diff --git a/drivers/infiniband/hw/hfi1/pio_copy.c b/drivers/infiniband/hw/hfi1/pio_copy.c
index 14bfd8287f4a..136f9a99e1e0 100644
--- a/drivers/infiniband/hw/hfi1/pio_copy.c
+++ b/drivers/infiniband/hw/hfi1/pio_copy.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include "hfi.h"
diff --git a/drivers/infiniband/hw/hfi1/platform.c b/drivers/infiniband/hw/hfi1/platform.c
index 4642d6ceb890..54cbd8f1a6c1 100644
--- a/drivers/infiniband/hw/hfi1/platform.c
+++ b/drivers/infiniband/hw/hfi1/platform.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/firmware.h>
diff --git a/drivers/infiniband/hw/hfi1/platform.h b/drivers/infiniband/hw/hfi1/platform.h
index eed0aa9124fa..1d51dca1bc30 100644
--- a/drivers/infiniband/hw/hfi1/platform.h
+++ b/drivers/infiniband/hw/hfi1/platform.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#ifndef __PLATFORM_H
#define __PLATFORM_H
diff --git a/drivers/infiniband/hw/hfi1/qp.c b/drivers/infiniband/hw/hfi1/qp.c
index e037df911512..6193d48b2c1f 100644
--- a/drivers/infiniband/hw/hfi1/qp.c
+++ b/drivers/infiniband/hw/hfi1/qp.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/err.h>
diff --git a/drivers/infiniband/hw/hfi1/qp.h b/drivers/infiniband/hw/hfi1/qp.h
index b0d053d12129..cdf87bc6ad94 100644
--- a/drivers/infiniband/hw/hfi1/qp.h
+++ b/drivers/infiniband/hw/hfi1/qp.h
@@ -1,52 +1,10 @@
-#ifndef _QP_H
-#define _QP_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _QP_H
+#define _QP_H
#include <linux/hash.h>
#include <rdma/rdmavt_qp.h>
#include "verbs.h"
diff --git a/drivers/infiniband/hw/hfi1/qsfp.c b/drivers/infiniband/hw/hfi1/qsfp.c
index 38f311f855b5..19d7887a4f10 100644
--- a/drivers/infiniband/hw/hfi1/qsfp.c
+++ b/drivers/infiniband/hw/hfi1/qsfp.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/delay.h>
diff --git a/drivers/infiniband/hw/hfi1/qsfp.h b/drivers/infiniband/hw/hfi1/qsfp.h
index 36cf52359848..8f14111eaa47 100644
--- a/drivers/infiniband/hw/hfi1/qsfp.h
+++ b/drivers/infiniband/hw/hfi1/qsfp.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
/* QSFP support common definitions, for hfi driver */
diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c
index 0174b8ee9f00..acd2b273ea7d 100644
--- a/drivers/infiniband/hw/hfi1/rc.c
+++ b/drivers/infiniband/hw/hfi1/rc.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/io.h>
diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c
index c3fa1814c6a8..b0151b7293f5 100644
--- a/drivers/infiniband/hw/hfi1/ruc.c
+++ b/drivers/infiniband/hw/hfi1/ruc.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/spinlock.h>
@@ -459,7 +417,7 @@ void hfi1_make_ruc_header(struct rvt_qp *qp, struct ib_other_headers *ohdr,
* send engine
* @qp: a pointer to QP
* @ps: a pointer to a structure with commonly lookup values for
- * the the send engine progress
+ * the send engine progress
* @tid: true if it is the tid leg
*
* This routine checks if the time slice for the QP has expired
diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c
index e83dc562629e..2b6c24b7b586 100644
--- a/drivers/infiniband/hw/hfi1/sdma.c
+++ b/drivers/infiniband/hw/hfi1/sdma.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/spinlock.h>
@@ -1860,7 +1818,7 @@ retry:
/*
* The SDMA idle interrupt is not guaranteed to be ordered with respect
- * to updates to the the dma_head location in host memory. The head
+ * to updates to the dma_head location in host memory. The head
* value read might not be fully up to date. If there are pending
* descriptors and the SDMA idle interrupt fired then read from the
* CSR SDMA head instead to get the latest value from the hardware.
diff --git a/drivers/infiniband/hw/hfi1/sdma.h b/drivers/infiniband/hw/hfi1/sdma.h
index f57d55272dd2..d8170fcbfbdd 100644
--- a/drivers/infiniband/hw/hfi1/sdma.h
+++ b/drivers/infiniband/hw/hfi1/sdma.h
@@ -1,52 +1,11 @@
-#ifndef _HFI1_SDMA_H
-#define _HFI1_SDMA_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_SDMA_H
+#define _HFI1_SDMA_H
+
#include <linux/types.h>
#include <linux/list.h>
#include <asm/byteorder.h>
diff --git a/drivers/infiniband/hw/hfi1/sdma_txreq.h b/drivers/infiniband/hw/hfi1/sdma_txreq.h
index 514a4784566b..e262fb5c5ec6 100644
--- a/drivers/infiniband/hw/hfi1/sdma_txreq.h
+++ b/drivers/infiniband/hw/hfi1/sdma_txreq.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#ifndef HFI1_SDMA_TXREQ_H
diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c
index acfcbedebe0d..3b3407dc7c21 100644
--- a/drivers/infiniband/hw/hfi1/sysfs.c
+++ b/drivers/infiniband/hw/hfi1/sysfs.c
@@ -1,49 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015-2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#include <linux/ctype.h>
#include <rdma/ib_sysfs.h>
diff --git a/drivers/infiniband/hw/hfi1/tid_rdma.c b/drivers/infiniband/hw/hfi1/tid_rdma.c
index 233ea48b72c8..2a7abf7a1f7f 100644
--- a/drivers/infiniband/hw/hfi1/tid_rdma.c
+++ b/drivers/infiniband/hw/hfi1/tid_rdma.c
@@ -605,7 +605,7 @@ static void __trigger_tid_waiter(struct rvt_qp *qp)
* to this call via first_qp().
*
* If the qp trigger was already scheduled (!rval)
- * the the reference is dropped, otherwise the resume
+ * the reference is dropped, otherwise the resume
* or the destroy cancel will dispatch the reference.
*/
static void tid_rdma_schedule_tid_wakeup(struct rvt_qp *qp)
@@ -5174,7 +5174,7 @@ bail_no_tx:
priv->s_flags &= ~RVT_S_BUSY;
/*
* If we didn't get a txreq, the QP will be woken up later to try
- * again, set the flags to the the wake up which work item to wake
+ * again, set the flags to the wake up which work item to wake
* up.
* (A better algorithm should be found to do this and generalize the
* sleep/wakeup flags.)
diff --git a/drivers/infiniband/hw/hfi1/trace.c b/drivers/infiniband/hw/hfi1/trace.c
index 715c81308b85..d9b5bbb2d011 100644
--- a/drivers/infiniband/hw/hfi1/trace.c
+++ b/drivers/infiniband/hw/hfi1/trace.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#define CREATE_TRACE_POINTS
#include "trace.h"
diff --git a/drivers/infiniband/hw/hfi1/trace.h b/drivers/infiniband/hw/hfi1/trace.h
index 1ce551864118..31e027c5a0c0 100644
--- a/drivers/infiniband/hw/hfi1/trace.h
+++ b/drivers/infiniband/hw/hfi1/trace.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#define packettype_name(etype) { RHF_RCV_TYPE_##etype, #etype }
diff --git a/drivers/infiniband/hw/hfi1/trace_ctxts.h b/drivers/infiniband/hw/hfi1/trace_ctxts.h
index d8c168dc3ea8..1858eaf33b18 100644
--- a/drivers/infiniband/hw/hfi1/trace_ctxts.h
+++ b/drivers/infiniband/hw/hfi1/trace_ctxts.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
-*
-* This file is provided under a dual BSD/GPLv2 license. When using or
-* redistributing this file, you may do so under either license.
-*
-* GPL LICENSE SUMMARY
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of version 2 of the GNU General Public License as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* BSD LICENSE
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* - Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* - Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in
-* the documentation and/or other materials provided with the
-* distribution.
-* - Neither the name of Intel Corporation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
*/
+
#if !defined(__HFI1_TRACE_CTXTS_H) || defined(TRACE_HEADER_MULTI_READ)
#define __HFI1_TRACE_CTXTS_H
diff --git a/drivers/infiniband/hw/hfi1/trace_dbg.h b/drivers/infiniband/hw/hfi1/trace_dbg.h
index de7a87392b8d..707f1053f0b7 100644
--- a/drivers/infiniband/hw/hfi1/trace_dbg.h
+++ b/drivers/infiniband/hw/hfi1/trace_dbg.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
-*
-* This file is provided under a dual BSD/GPLv2 license. When using or
-* redistributing this file, you may do so under either license.
-*
-* GPL LICENSE SUMMARY
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of version 2 of the GNU General Public License as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* BSD LICENSE
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* - Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* - Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in
-* the documentation and/or other materials provided with the
-* distribution.
-* - Neither the name of Intel Corporation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
*/
+
#if !defined(__HFI1_TRACE_EXTRA_H) || defined(TRACE_HEADER_MULTI_READ)
#define __HFI1_TRACE_EXTRA_H
diff --git a/drivers/infiniband/hw/hfi1/trace_ibhdrs.h b/drivers/infiniband/hw/hfi1/trace_ibhdrs.h
index 2f84290a88ca..b33f8f575f8a 100644
--- a/drivers/infiniband/hw/hfi1/trace_ibhdrs.h
+++ b/drivers/infiniband/hw/hfi1/trace_ibhdrs.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#if !defined(__HFI1_TRACE_IBHDRS_H) || defined(TRACE_HEADER_MULTI_READ)
#define __HFI1_TRACE_IBHDRS_H
diff --git a/drivers/infiniband/hw/hfi1/trace_misc.h b/drivers/infiniband/hw/hfi1/trace_misc.h
index 93338988b922..742675fa7576 100644
--- a/drivers/infiniband/hw/hfi1/trace_misc.h
+++ b/drivers/infiniband/hw/hfi1/trace_misc.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016 Intel Corporation.
-*
-* This file is provided under a dual BSD/GPLv2 license. When using or
-* redistributing this file, you may do so under either license.
-*
-* GPL LICENSE SUMMARY
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of version 2 of the GNU General Public License as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* BSD LICENSE
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* - Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* - Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in
-* the documentation and/or other materials provided with the
-* distribution.
-* - Neither the name of Intel Corporation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
*/
+
#if !defined(__HFI1_TRACE_MISC_H) || defined(TRACE_HEADER_MULTI_READ)
#define __HFI1_TRACE_MISC_H
diff --git a/drivers/infiniband/hw/hfi1/trace_mmu.h b/drivers/infiniband/hw/hfi1/trace_mmu.h
index 3b7abbc382c2..187e9244fe5e 100644
--- a/drivers/infiniband/hw/hfi1/trace_mmu.h
+++ b/drivers/infiniband/hw/hfi1/trace_mmu.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#if !defined(__HFI1_TRACE_MMU_H) || defined(TRACE_HEADER_MULTI_READ)
#define __HFI1_TRACE_MMU_H
diff --git a/drivers/infiniband/hw/hfi1/trace_rc.h b/drivers/infiniband/hw/hfi1/trace_rc.h
index 5f49e1eeb211..7c3a1c77536d 100644
--- a/drivers/infiniband/hw/hfi1/trace_rc.h
+++ b/drivers/infiniband/hw/hfi1/trace_rc.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015, 2016, 2017 Intel Corporation.
-*
-* This file is provided under a dual BSD/GPLv2 license. When using or
-* redistributing this file, you may do so under either license.
-*
-* GPL LICENSE SUMMARY
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of version 2 of the GNU General Public License as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* BSD LICENSE
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* - Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* - Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in
-* the documentation and/or other materials provided with the
-* distribution.
-* - Neither the name of Intel Corporation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
*/
+
#if !defined(__HFI1_TRACE_RC_H) || defined(TRACE_HEADER_MULTI_READ)
#define __HFI1_TRACE_RC_H
diff --git a/drivers/infiniband/hw/hfi1/trace_rx.h b/drivers/infiniband/hw/hfi1/trace_rx.h
index 168079ed122c..0da22f9bc75e 100644
--- a/drivers/infiniband/hw/hfi1/trace_rx.h
+++ b/drivers/infiniband/hw/hfi1/trace_rx.h
@@ -1,49 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#if !defined(__HFI1_TRACE_RX_H) || defined(TRACE_HEADER_MULTI_READ)
#define __HFI1_TRACE_RX_H
diff --git a/drivers/infiniband/hw/hfi1/trace_tx.h b/drivers/infiniband/hw/hfi1/trace_tx.h
index f1922a7619fe..7318aa6150b5 100644
--- a/drivers/infiniband/hw/hfi1/trace_tx.h
+++ b/drivers/infiniband/hw/hfi1/trace_tx.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#if !defined(__HFI1_TRACE_TX_H) || defined(TRACE_HEADER_MULTI_READ)
#define __HFI1_TRACE_TX_H
diff --git a/drivers/infiniband/hw/hfi1/uc.c b/drivers/infiniband/hw/hfi1/uc.c
index 5b0f536b34e0..4e9d6aa39305 100644
--- a/drivers/infiniband/hw/hfi1/uc.c
+++ b/drivers/infiniband/hw/hfi1/uc.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include "hfi.h"
diff --git a/drivers/infiniband/hw/hfi1/ud.c b/drivers/infiniband/hw/hfi1/ud.c
index 6ecb984c85fa..b64b9d7e08f0 100644
--- a/drivers/infiniband/hw/hfi1/ud.c
+++ b/drivers/infiniband/hw/hfi1/ud.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2019 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/net.h>
diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.c b/drivers/infiniband/hw/hfi1/user_exp_rcv.c
index 58dcab2679d9..0c86e9d354f8 100644
--- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c
+++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c
@@ -1,49 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2020 Cornelis Networks, Inc.
* Copyright(c) 2015-2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <asm/page.h>
#include <linux/string.h>
@@ -177,8 +135,8 @@ static void unpin_rcv_pages(struct hfi1_filedata *fd,
struct mm_struct *mm;
if (mapped) {
- pci_unmap_single(dd->pcidev, node->dma_addr,
- node->npages * PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ dma_unmap_single(&dd->pcidev->dev, node->dma_addr,
+ node->npages * PAGE_SIZE, DMA_FROM_DEVICE);
pages = &node->pages[idx];
mm = mm_from_tid_node(node);
} else {
@@ -739,9 +697,8 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
if (!node)
return -ENOMEM;
- phys = pci_map_single(dd->pcidev,
- __va(page_to_phys(pages[0])),
- npages * PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ phys = dma_map_single(&dd->pcidev->dev, __va(page_to_phys(pages[0])),
+ npages * PAGE_SIZE, DMA_FROM_DEVICE);
if (dma_mapping_error(&dd->pcidev->dev, phys)) {
dd_dev_err(dd, "Failed to DMA map Exp Rcv pages 0x%llx\n",
phys);
@@ -783,8 +740,8 @@ out_unmap:
hfi1_cdbg(TID, "Failed to insert RB node %u 0x%lx, 0x%lx %d",
node->rcventry, node->notifier.interval_tree.start,
node->phys, ret);
- pci_unmap_single(dd->pcidev, phys, npages * PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
+ dma_unmap_single(&dd->pcidev->dev, phys, npages * PAGE_SIZE,
+ DMA_FROM_DEVICE);
kfree(node);
return -EFAULT;
}
diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.h b/drivers/infiniband/hw/hfi1/user_exp_rcv.h
index d45c7b6988d4..8c53e416bf84 100644
--- a/drivers/infiniband/hw/hfi1/user_exp_rcv.h
+++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.h
@@ -1,53 +1,12 @@
-#ifndef _HFI1_USER_EXP_RCV_H
-#define _HFI1_USER_EXP_RCV_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2020 - Cornelis Networks, Inc.
* Copyright(c) 2015 - 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_USER_EXP_RCV_H
+#define _HFI1_USER_EXP_RCV_H
+
#include "hfi.h"
#include "exp_rcv.h"
diff --git a/drivers/infiniband/hw/hfi1/user_pages.c b/drivers/infiniband/hw/hfi1/user_pages.c
index 3b505006c0a6..7bce963e2ae6 100644
--- a/drivers/infiniband/hw/hfi1/user_pages.c
+++ b/drivers/infiniband/hw/hfi1/user_pages.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015-2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/mm.h>
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c
index da5b2e37355a..5b11c8282744 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.c
+++ b/drivers/infiniband/hw/hfi1/user_sdma.c
@@ -1,50 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2020 - Cornelis Networks, Inc.
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/device.h>
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.h b/drivers/infiniband/hw/hfi1/user_sdma.h
index fabe58139906..ea56eb57e656 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.h
+++ b/drivers/infiniband/hw/hfi1/user_sdma.h
@@ -1,52 +1,11 @@
-#ifndef _HFI1_USER_SDMA_H
-#define _HFI1_USER_SDMA_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2020 - Cornelis Networks, Inc.
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_USER_SDMA_H
+#define _HFI1_USER_SDMA_H
+
#include <linux/device.h>
#include <linux/wait.h>
diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
index 9b198c35e1a1..26bea51869bf 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2015 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <rdma/ib_mad.h>
diff --git a/drivers/infiniband/hw/hfi1/verbs.h b/drivers/infiniband/hw/hfi1/verbs.h
index 420df17cd184..38565532d654 100644
--- a/drivers/infiniband/hw/hfi1/verbs.h
+++ b/drivers/infiniband/hw/hfi1/verbs.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2015 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#ifndef HFI1_VERBS_H
diff --git a/drivers/infiniband/hw/hfi1/verbs_txreq.c b/drivers/infiniband/hw/hfi1/verbs_txreq.c
index 8f766dd3f61c..cfecc81a27c7 100644
--- a/drivers/infiniband/hw/hfi1/verbs_txreq.c
+++ b/drivers/infiniband/hw/hfi1/verbs_txreq.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include "hfi.h"
diff --git a/drivers/infiniband/hw/hfi1/verbs_txreq.h b/drivers/infiniband/hw/hfi1/verbs_txreq.h
index 4bdfc7932376..2a7e0ae892e9 100644
--- a/drivers/infiniband/hw/hfi1/verbs_txreq.h
+++ b/drivers/infiniband/hw/hfi1/verbs_txreq.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#ifndef HFI1_VERBS_TXREQ_H
diff --git a/drivers/infiniband/hw/hfi1/vnic.h b/drivers/infiniband/hw/hfi1/vnic.h
index a7a450e2cf2c..34f03e7770be 100644
--- a/drivers/infiniband/hw/hfi1/vnic.h
+++ b/drivers/infiniband/hw/hfi1/vnic.h
@@ -1,52 +1,10 @@
-#ifndef _HFI1_VNIC_H
-#define _HFI1_VNIC_H
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2017 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef _HFI1_VNIC_H
+#define _HFI1_VNIC_H
#include <rdma/opa_vnic.h>
#include "hfi.h"
#include "sdma.h"
diff --git a/drivers/infiniband/hw/hfi1/vnic_main.c b/drivers/infiniband/hw/hfi1/vnic_main.c
index 7e79c0578ecf..3650fababf25 100644
--- a/drivers/infiniband/hw/hfi1/vnic_main.c
+++ b/drivers/infiniband/hw/hfi1/vnic_main.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2017 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
/*
diff --git a/drivers/infiniband/hw/hfi1/vnic_sdma.c b/drivers/infiniband/hw/hfi1/vnic_sdma.c
index 7d90b900131b..c3f0f8d877c3 100644
--- a/drivers/infiniband/hw/hfi1/vnic_sdma.c
+++ b/drivers/infiniband/hw/hfi1/vnic_sdma.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2017 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
/*
diff --git a/drivers/infiniband/hw/hns/hns_roce_alloc.c b/drivers/infiniband/hw/hns/hns_roce_alloc.c
index 1b02d3bc9bae..d4fa0fd52294 100644
--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c
+++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c
@@ -36,76 +36,6 @@
#include "hns_roce_device.h"
#include <rdma/ib_umem.h>
-int hns_roce_bitmap_alloc(struct hns_roce_bitmap *bitmap, unsigned long *obj)
-{
- int ret = 0;
-
- spin_lock(&bitmap->lock);
- *obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last);
- if (*obj >= bitmap->max) {
- bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
- & bitmap->mask;
- *obj = find_first_zero_bit(bitmap->table, bitmap->max);
- }
-
- if (*obj < bitmap->max) {
- set_bit(*obj, bitmap->table);
- bitmap->last = (*obj + 1);
- if (bitmap->last == bitmap->max)
- bitmap->last = 0;
- *obj |= bitmap->top;
- } else {
- ret = -EINVAL;
- }
-
- spin_unlock(&bitmap->lock);
-
- return ret;
-}
-
-void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj)
-{
- obj &= bitmap->max + bitmap->reserved_top - 1;
-
- spin_lock(&bitmap->lock);
- clear_bit(obj, bitmap->table);
-
- bitmap->last = min(bitmap->last, obj);
- bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
- & bitmap->mask;
- spin_unlock(&bitmap->lock);
-}
-
-int hns_roce_bitmap_init(struct hns_roce_bitmap *bitmap, u32 num, u32 mask,
- u32 reserved_bot, u32 reserved_top)
-{
- u32 i;
-
- if (num != roundup_pow_of_two(num))
- return -EINVAL;
-
- bitmap->last = 0;
- bitmap->top = 0;
- bitmap->max = num - reserved_top;
- bitmap->mask = mask;
- bitmap->reserved_top = reserved_top;
- spin_lock_init(&bitmap->lock);
- bitmap->table = kcalloc(BITS_TO_LONGS(bitmap->max), sizeof(long),
- GFP_KERNEL);
- if (!bitmap->table)
- return -ENOMEM;
-
- for (i = 0; i < reserved_bot; ++i)
- set_bit(i, bitmap->table);
-
- return 0;
-}
-
-void hns_roce_bitmap_cleanup(struct hns_roce_bitmap *bitmap)
-{
- kfree(bitmap->table);
-}
-
void hns_roce_buf_free(struct hns_roce_dev *hr_dev, struct hns_roce_buf *buf)
{
struct hns_roce_buf_list *trunks;
@@ -248,10 +178,10 @@ void hns_roce_cleanup_bitmap(struct hns_roce_dev *hr_dev)
ida_destroy(&hr_dev->xrcd_ida.ida);
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SRQ)
- hns_roce_cleanup_srq_table(hr_dev);
+ ida_destroy(&hr_dev->srq_table.srq_ida.ida);
hns_roce_cleanup_qp_table(hr_dev);
hns_roce_cleanup_cq_table(hr_dev);
ida_destroy(&hr_dev->mr_table.mtpt_ida.ida);
ida_destroy(&hr_dev->pd_ida.ida);
- hns_roce_cleanup_uar_table(hr_dev);
+ ida_destroy(&hr_dev->uar_ida.ida);
}
diff --git a/drivers/infiniband/hw/hns/hns_roce_db.c b/drivers/infiniband/hw/hns/hns_roce_db.c
index d40ea3d87260..751470c7a2ce 100644
--- a/drivers/infiniband/hw/hns/hns_roce_db.c
+++ b/drivers/infiniband/hw/hns/hns_roce_db.c
@@ -42,8 +42,8 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context, unsigned long virt,
found:
offset = virt - page_addr;
- db->dma = sg_dma_address(page->umem->sg_head.sgl) + offset;
- db->virt_addr = sg_virt(page->umem->sg_head.sgl) + offset;
+ db->dma = sg_dma_address(page->umem->sgt_append.sgt.sgl) + offset;
+ db->virt_addr = sg_virt(page->umem->sgt_append.sgt.sgl) + offset;
db->u.user_page = page;
refcount_inc(&page->refcount);
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 991f65269fa6..9467c39e3d28 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -496,6 +496,12 @@ struct hns_roce_bank {
u32 next; /* Next ID to allocate. */
};
+struct hns_roce_idx_table {
+ u32 *spare_idx;
+ u32 head;
+ u32 tail;
+};
+
struct hns_roce_qp_table {
struct hns_roce_hem_table qp_table;
struct hns_roce_hem_table irrl_table;
@@ -504,6 +510,7 @@ struct hns_roce_qp_table {
struct mutex scc_mutex;
struct hns_roce_bank bank[HNS_ROCE_QP_BANK_NUM];
struct mutex bank_mutex;
+ struct hns_roce_idx_table idx_table;
};
struct hns_roce_cq_table {
@@ -514,7 +521,7 @@ struct hns_roce_cq_table {
};
struct hns_roce_srq_table {
- struct hns_roce_bitmap bitmap;
+ struct hns_roce_ida srq_ida;
struct xarray xa;
struct hns_roce_hem_table table;
};
@@ -963,7 +970,7 @@ struct hns_roce_dev {
struct hns_roce_cmdq cmd;
struct hns_roce_ida pd_ida;
struct hns_roce_ida xrcd_ida;
- struct hns_roce_uar_table uar_table;
+ struct hns_roce_ida uar_ida;
struct hns_roce_mr_table mr_table;
struct hns_roce_cq_table cq_table;
struct hns_roce_srq_table srq_table;
@@ -1118,10 +1125,8 @@ static inline u8 get_tclass(const struct ib_global_route *grh)
grh->traffic_class >> DSCP_SHIFT : grh->traffic_class;
}
-int hns_roce_init_uar_table(struct hns_roce_dev *dev);
+void hns_roce_init_uar_table(struct hns_roce_dev *dev);
int hns_roce_uar_alloc(struct hns_roce_dev *dev, struct hns_roce_uar *uar);
-void hns_roce_uar_free(struct hns_roce_dev *dev, struct hns_roce_uar *uar);
-void hns_roce_cleanup_uar_table(struct hns_roce_dev *dev);
int hns_roce_cmd_init(struct hns_roce_dev *hr_dev);
void hns_roce_cmd_cleanup(struct hns_roce_dev *hr_dev);
@@ -1146,20 +1151,14 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
void hns_roce_init_pd_table(struct hns_roce_dev *hr_dev);
void hns_roce_init_mr_table(struct hns_roce_dev *hr_dev);
void hns_roce_init_cq_table(struct hns_roce_dev *hr_dev);
-void hns_roce_init_qp_table(struct hns_roce_dev *hr_dev);
-int hns_roce_init_srq_table(struct hns_roce_dev *hr_dev);
+int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev);
+void hns_roce_init_srq_table(struct hns_roce_dev *hr_dev);
void hns_roce_init_xrcd_table(struct hns_roce_dev *hr_dev);
void hns_roce_cleanup_eq_table(struct hns_roce_dev *hr_dev);
void hns_roce_cleanup_cq_table(struct hns_roce_dev *hr_dev);
void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev);
-void hns_roce_cleanup_srq_table(struct hns_roce_dev *hr_dev);
-int hns_roce_bitmap_alloc(struct hns_roce_bitmap *bitmap, unsigned long *obj);
-void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj);
-int hns_roce_bitmap_init(struct hns_roce_bitmap *bitmap, u32 num, u32 mask,
- u32 reserved_bot, u32 resetrved_top);
-void hns_roce_bitmap_cleanup(struct hns_roce_bitmap *bitmap);
void hns_roce_cleanup_bitmap(struct hns_roce_dev *hr_dev);
int hns_roce_create_ah(struct ib_ah *ah, struct rdma_ah_init_attr *init_attr,
@@ -1216,9 +1215,8 @@ int hns_roce_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata);
int hns_roce_alloc_xrcd(struct ib_xrcd *ib_xrcd, struct ib_udata *udata);
int hns_roce_dealloc_xrcd(struct ib_xrcd *ib_xrcd, struct ib_udata *udata);
-struct ib_qp *hns_roce_create_qp(struct ib_pd *ib_pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata);
+int hns_roce_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp);
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
index a3305d196675..e0f59b8d7d5d 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
@@ -758,7 +758,7 @@ static struct hns_roce_qp *hns_roce_v1_create_lp_qp(struct hns_roce_dev *hr_dev,
init_attr.cap.max_recv_wr = HNS_ROCE_MIN_WQE_NUM;
init_attr.cap.max_send_wr = HNS_ROCE_MIN_WQE_NUM;
- qp = hns_roce_create_qp(pd, &init_attr, NULL);
+ qp = ib_create_qp(pd, &init_attr);
if (IS_ERR(qp)) {
dev_err(dev, "Create loop qp for mr free failed!");
return NULL;
@@ -923,7 +923,7 @@ static int hns_roce_v1_rsv_lp_qp(struct hns_roce_dev *hr_dev)
create_lp_qp_failed:
for (i -= 1; i >= 0; i--) {
hr_qp = free_mr->mr_free_qp[i];
- if (hns_roce_v1_destroy_qp(&hr_qp->ibqp, NULL))
+ if (ib_destroy_qp(&hr_qp->ibqp))
dev_err(dev, "Destroy qp %d for mr free failed!\n", i);
}
@@ -953,7 +953,7 @@ static void hns_roce_v1_release_lp_qp(struct hns_roce_dev *hr_dev)
if (!hr_qp)
continue;
- ret = hns_roce_v1_destroy_qp(&hr_qp->ibqp, NULL);
+ ret = ib_destroy_qp(&hr_qp->ibqp);
if (ret)
dev_err(dev, "Destroy qp %d for mr free failed(%d)!\n",
i, ret);
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 594d4cef31b3..5b9953105752 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -1248,8 +1248,7 @@ static void hns_roce_cmq_setup_basic_desc(struct hns_roce_cmq_desc *desc,
{
memset((void *)desc, 0, sizeof(struct hns_roce_cmq_desc));
desc->opcode = cpu_to_le16(opcode);
- desc->flag =
- cpu_to_le16(HNS_ROCE_CMD_FLAG_NO_INTR | HNS_ROCE_CMD_FLAG_IN);
+ desc->flag = cpu_to_le16(HNS_ROCE_CMD_FLAG_IN);
if (is_read)
desc->flag |= cpu_to_le16(HNS_ROCE_CMD_FLAG_WR);
else
@@ -1288,16 +1287,11 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
/* Write to hardware */
roce_write(hr_dev, ROCEE_TX_CMQ_PI_REG, csq->head);
- /* If the command is sync, wait for the firmware to write back,
- * if multi descriptors to be sent, use the first one to check
- */
- if (le16_to_cpu(desc->flag) & HNS_ROCE_CMD_FLAG_NO_INTR) {
- do {
- if (hns_roce_cmq_csq_done(hr_dev))
- break;
- udelay(1);
- } while (++timeout < priv->cmq.tx_timeout);
- }
+ do {
+ if (hns_roce_cmq_csq_done(hr_dev))
+ break;
+ udelay(1);
+ } while (++timeout < priv->cmq.tx_timeout);
if (hns_roce_cmq_csq_done(hr_dev)) {
for (ret = 0, i = 0; i < num; i++) {
@@ -1761,8 +1755,7 @@ static int __hns_roce_set_vf_switch_param(struct hns_roce_dev *hr_dev,
if (ret)
return ret;
- desc.flag =
- cpu_to_le16(HNS_ROCE_CMD_FLAG_NO_INTR | HNS_ROCE_CMD_FLAG_IN);
+ desc.flag = cpu_to_le16(HNS_ROCE_CMD_FLAG_IN);
desc.flag &= cpu_to_le16(~HNS_ROCE_CMD_FLAG_WR);
roce_set_bit(swt->cfg, VF_SWITCH_DATA_CFG_ALW_LPBK_S, 1);
roce_set_bit(swt->cfg, VF_SWITCH_DATA_CFG_ALW_LCL_LPBK_S, 0);
@@ -2004,6 +1997,7 @@ static void set_default_caps(struct hns_roce_dev *hr_dev)
caps->gid_table_len[0] = HNS_ROCE_V2_GID_INDEX_NUM;
if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) {
+ caps->flags |= HNS_ROCE_CAP_FLAG_STASH;
caps->max_sq_inline = HNS_ROCE_V3_MAX_SQ_INLINE;
} else {
caps->max_sq_inline = HNS_ROCE_V2_MAX_SQ_INLINE;
@@ -4114,6 +4108,9 @@ static void modify_qp_reset_to_init(struct ib_qp *ibqp,
if (hr_qp->en_flags & HNS_ROCE_QP_CAP_RQ_RECORD_DB)
hr_reg_enable(context, QPC_RQ_RECORD_EN);
+ if (hr_qp->en_flags & HNS_ROCE_QP_CAP_OWNER_DB)
+ hr_reg_enable(context, QPC_OWNER_MODE);
+
hr_reg_write(context, QPC_RQ_DB_RECORD_ADDR_L,
lower_32_bits(hr_qp->rdb.dma) >> 1);
hr_reg_write(context, QPC_RQ_DB_RECORD_ADDR_H,
@@ -4146,8 +4143,6 @@ static void modify_qp_init_to_init(struct ib_qp *ibqp,
struct hns_roce_v2_qp_context *context,
struct hns_roce_v2_qp_context *qpc_mask)
{
- struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
-
/*
* In v2 engine, software pass context and context mask to hardware
* when modifying qp. If software need modify some fields in context,
@@ -4172,11 +4167,6 @@ static void modify_qp_init_to_init(struct ib_qp *ibqp,
hr_reg_write(context, QPC_SRQN, to_hr_srq(ibqp->srq)->srqn);
hr_reg_clear(qpc_mask, QPC_SRQN);
}
-
- if (attr_mask & IB_QP_DEST_QPN) {
- hr_reg_write(context, QPC_DQPN, hr_qp->qpn);
- hr_reg_clear(qpc_mask, QPC_DQPN);
- }
}
static int config_qp_rq_buf(struct hns_roce_dev *hr_dev,
@@ -4486,9 +4476,6 @@ static int modify_qp_rtr_to_rts(struct ib_qp *ibqp,
hr_reg_clear(qpc_mask, QPC_CHECK_FLG);
- hr_reg_write(context, QPC_LSN, 0x100);
- hr_reg_clear(qpc_mask, QPC_LSN);
-
hr_reg_clear(qpc_mask, QPC_V2_IRRL_HEAD);
return 0;
@@ -4507,15 +4494,23 @@ static int get_dip_ctx_idx(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
{
const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr);
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
+ u32 *spare_idx = hr_dev->qp_table.idx_table.spare_idx;
+ u32 *head = &hr_dev->qp_table.idx_table.head;
+ u32 *tail = &hr_dev->qp_table.idx_table.tail;
struct hns_roce_dip *hr_dip;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&hr_dev->dip_list_lock, flags);
+ spare_idx[*tail] = ibqp->qp_num;
+ *tail = (*tail == hr_dev->caps.num_qps - 1) ? 0 : (*tail + 1);
+
list_for_each_entry(hr_dip, &hr_dev->dip_list, node) {
- if (!memcmp(grh->dgid.raw, hr_dip->dgid, 16))
+ if (!memcmp(grh->dgid.raw, hr_dip->dgid, 16)) {
+ *dip_idx = hr_dip->dip_idx;
goto out;
+ }
}
/* If no dgid is found, a new dip and a mapping between dgid and
@@ -4528,7 +4523,8 @@ static int get_dip_ctx_idx(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
}
memcpy(hr_dip->dgid, grh->dgid.raw, sizeof(grh->dgid.raw));
- hr_dip->dip_idx = *dip_idx = ibqp->qp_num;
+ hr_dip->dip_idx = *dip_idx = spare_idx[*head];
+ *head = (*head == hr_dev->caps.num_qps - 1) ? 0 : (*head + 1);
list_add_tail(&hr_dip->node, &hr_dev->dip_list);
out:
@@ -5127,7 +5123,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
qp_attr->rq_psn = hr_reg_read(&context, QPC_RX_REQ_EPSN);
qp_attr->sq_psn = (u32)hr_reg_read(&context, QPC_SQ_CUR_PSN);
- qp_attr->dest_qp_num = (u8)hr_reg_read(&context, QPC_DQPN);
+ qp_attr->dest_qp_num = hr_reg_read(&context, QPC_DQPN);
qp_attr->qp_access_flags =
((hr_reg_read(&context, QPC_RRE)) << V2_QP_RRE_S) |
((hr_reg_read(&context, QPC_RWE)) << V2_QP_RWE_S) |
@@ -5224,7 +5220,6 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev,
if (send_cq && send_cq != recv_cq)
__hns_roce_v2_cq_clean(send_cq, hr_qp->qpn, NULL);
-
}
hns_roce_qp_remove(hr_dev, hr_qp);
@@ -6118,35 +6113,32 @@ static int hns_roce_v2_init_eq_table(struct hns_roce_dev *hr_dev)
ret = hns_roce_v2_create_eq(hr_dev, eq, eq_cmd);
if (ret) {
- dev_err(dev, "eq create failed.\n");
+ dev_err(dev, "failed to create eq.\n");
goto err_create_eq_fail;
}
}
- /* enable irq */
- hns_roce_v2_int_mask_enable(hr_dev, eq_num, EQ_ENABLE);
+ hr_dev->irq_workq = alloc_ordered_workqueue("hns_roce_irq_workq", 0);
+ if (!hr_dev->irq_workq) {
+ dev_err(dev, "failed to create irq workqueue.\n");
+ ret = -ENOMEM;
+ goto err_create_eq_fail;
+ }
- ret = __hns_roce_request_irq(hr_dev, irq_num, comp_num,
- aeq_num, other_num);
+ ret = __hns_roce_request_irq(hr_dev, irq_num, comp_num, aeq_num,
+ other_num);
if (ret) {
- dev_err(dev, "Request irq failed.\n");
+ dev_err(dev, "failed to request irq.\n");
goto err_request_irq_fail;
}
- hr_dev->irq_workq = alloc_ordered_workqueue("hns_roce_irq_workq", 0);
- if (!hr_dev->irq_workq) {
- dev_err(dev, "Create irq workqueue failed!\n");
- ret = -ENOMEM;
- goto err_create_wq_fail;
- }
+ /* enable irq */
+ hns_roce_v2_int_mask_enable(hr_dev, eq_num, EQ_ENABLE);
return 0;
-err_create_wq_fail:
- __hns_roce_free_irq(hr_dev);
-
err_request_irq_fail:
- hns_roce_v2_int_mask_enable(hr_dev, eq_num, EQ_DISABLE);
+ destroy_workqueue(hr_dev->irq_workq);
err_create_eq_fail:
for (i -= 1; i >= 0; i--)
@@ -6367,7 +6359,6 @@ static int hns_roce_hw_v2_init_instance(struct hnae3_handle *handle)
handle->rinfo.instance_state = HNS_ROCE_STATE_INITED;
-
return 0;
reset_chk_err:
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
index b8a09d411e2e..4d904d5e82be 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
@@ -129,19 +129,13 @@
#define HNS_ROCE_V2_TABLE_CHUNK_SIZE (1 << 18)
-#define HNS_ROCE_CMD_FLAG_IN_VALID_SHIFT 0
-#define HNS_ROCE_CMD_FLAG_OUT_VALID_SHIFT 1
-#define HNS_ROCE_CMD_FLAG_NEXT_SHIFT 2
-#define HNS_ROCE_CMD_FLAG_WR_OR_RD_SHIFT 3
-#define HNS_ROCE_CMD_FLAG_NO_INTR_SHIFT 4
-#define HNS_ROCE_CMD_FLAG_ERR_INTR_SHIFT 5
-
-#define HNS_ROCE_CMD_FLAG_IN BIT(HNS_ROCE_CMD_FLAG_IN_VALID_SHIFT)
-#define HNS_ROCE_CMD_FLAG_OUT BIT(HNS_ROCE_CMD_FLAG_OUT_VALID_SHIFT)
-#define HNS_ROCE_CMD_FLAG_NEXT BIT(HNS_ROCE_CMD_FLAG_NEXT_SHIFT)
-#define HNS_ROCE_CMD_FLAG_WR BIT(HNS_ROCE_CMD_FLAG_WR_OR_RD_SHIFT)
-#define HNS_ROCE_CMD_FLAG_NO_INTR BIT(HNS_ROCE_CMD_FLAG_NO_INTR_SHIFT)
-#define HNS_ROCE_CMD_FLAG_ERR_INTR BIT(HNS_ROCE_CMD_FLAG_ERR_INTR_SHIFT)
+enum {
+ HNS_ROCE_CMD_FLAG_IN = BIT(0),
+ HNS_ROCE_CMD_FLAG_OUT = BIT(1),
+ HNS_ROCE_CMD_FLAG_NEXT = BIT(2),
+ HNS_ROCE_CMD_FLAG_WR = BIT(3),
+ HNS_ROCE_CMD_FLAG_ERR_INTR = BIT(5),
+};
#define HNS_ROCE_CMQ_DESC_NUM_S 3
@@ -1413,7 +1407,6 @@ struct hns_roce_cmq_desc {
__le32 rsv[4];
} func_info;
};
-
};
struct hns_roce_v2_cmq_ring {
@@ -1447,7 +1440,7 @@ struct hns_roce_v2_priv {
struct hns_roce_dip {
u8 dgid[GID_LEN_V2];
- u8 dip_idx;
+ u32 dip_idx;
struct list_head node; /* all dips are on a list */
};
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
index cc6eab14a222..5d39bd08582a 100644
--- a/drivers/infiniband/hw/hns/hns_roce_main.c
+++ b/drivers/infiniband/hw/hns/hns_roce_main.c
@@ -325,7 +325,7 @@ static int hns_roce_alloc_ucontext(struct ib_ucontext *uctx,
return 0;
error_fail_copy_to_udata:
- hns_roce_uar_free(hr_dev, &context->uar);
+ ida_free(&hr_dev->uar_ida.ida, (int)context->uar.logic_idx);
error_fail_uar_alloc:
return ret;
@@ -334,8 +334,9 @@ error_fail_uar_alloc:
static void hns_roce_dealloc_ucontext(struct ib_ucontext *ibcontext)
{
struct hns_roce_ucontext *context = to_hr_ucontext(ibcontext);
+ struct hns_roce_dev *hr_dev = to_hr_dev(ibcontext->device);
- hns_roce_uar_free(to_hr_dev(ibcontext->device), &context->uar);
+ ida_free(&hr_dev->uar_ida.ida, (int)context->uar.logic_idx);
}
static int hns_roce_mmap(struct ib_ucontext *context,
@@ -454,6 +455,7 @@ static const struct ib_device_ops hns_roce_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, hns_roce_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, hns_roce_cq, ib_cq),
INIT_RDMA_OBJ_SIZE(ib_pd, hns_roce_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, hns_roce_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_ucontext, hns_roce_ucontext, ibucontext),
};
@@ -736,11 +738,7 @@ static int hns_roce_setup_hca(struct hns_roce_dev *hr_dev)
mutex_init(&hr_dev->pgdir_mutex);
}
- ret = hns_roce_init_uar_table(hr_dev);
- if (ret) {
- dev_err(dev, "Failed to initialize uar table. aborting\n");
- return ret;
- }
+ hns_roce_init_uar_table(hr_dev);
ret = hns_roce_uar_alloc(hr_dev, &hr_dev->priv_uar);
if (ret) {
@@ -748,6 +746,12 @@ static int hns_roce_setup_hca(struct hns_roce_dev *hr_dev)
goto err_uar_table_free;
}
+ ret = hns_roce_init_qp_table(hr_dev);
+ if (ret) {
+ dev_err(dev, "Failed to init qp_table.\n");
+ goto err_uar_table_free;
+ }
+
hns_roce_init_pd_table(hr_dev);
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_XRC)
@@ -757,32 +761,14 @@ static int hns_roce_setup_hca(struct hns_roce_dev *hr_dev)
hns_roce_init_cq_table(hr_dev);
- hns_roce_init_qp_table(hr_dev);
-
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SRQ) {
- ret = hns_roce_init_srq_table(hr_dev);
- if (ret) {
- dev_err(dev,
- "Failed to init share receive queue table.\n");
- goto err_qp_table_free;
- }
+ hns_roce_init_srq_table(hr_dev);
}
return 0;
-err_qp_table_free:
- hns_roce_cleanup_qp_table(hr_dev);
- hns_roce_cleanup_cq_table(hr_dev);
- ida_destroy(&hr_dev->mr_table.mtpt_ida.ida);
-
- if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_XRC)
- ida_destroy(&hr_dev->xrcd_ida.ida);
-
- ida_destroy(&hr_dev->pd_ida.ida);
- hns_roce_uar_free(hr_dev, &hr_dev->priv_uar);
-
err_uar_table_free:
- hns_roce_cleanup_uar_table(hr_dev);
+ ida_destroy(&hr_dev->uar_ida.ida);
return ret;
}
diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c
index 006c84bb3f9f..7089ac780291 100644
--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
+++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
@@ -352,7 +352,9 @@ struct ib_mr *hns_roce_rereg_user_mr(struct ib_mr *ibmr, int flags, u64 start,
free_cmd_mbox:
hns_roce_free_cmd_mailbox(hr_dev, mailbox);
- return ERR_PTR(ret);
+ if (ret)
+ return ERR_PTR(ret);
+ return NULL;
}
int hns_roce_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
diff --git a/drivers/infiniband/hw/hns/hns_roce_pd.c b/drivers/infiniband/hw/hns/hns_roce_pd.c
index ea5663630985..81ffad77ae42 100644
--- a/drivers/infiniband/hw/hns/hns_roce_pd.c
+++ b/drivers/infiniband/hw/hns/hns_roce_pd.c
@@ -85,13 +85,18 @@ int hns_roce_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata)
int hns_roce_uar_alloc(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
{
+ struct hns_roce_ida *uar_ida = &hr_dev->uar_ida;
struct resource *res;
- int ret;
+ int id;
/* Using bitmap to manager UAR index */
- ret = hns_roce_bitmap_alloc(&hr_dev->uar_table.bitmap, &uar->logic_idx);
- if (ret)
+ id = ida_alloc_range(&uar_ida->ida, uar_ida->min, uar_ida->max,
+ GFP_KERNEL);
+ if (id < 0) {
+ ibdev_err(&hr_dev->ib_dev, "failed to alloc uar id(%d).\n", id);
return -ENOMEM;
+ }
+ uar->logic_idx = (unsigned long)id;
if (uar->logic_idx > 0 && hr_dev->caps.phy_num_uars > 1)
uar->index = (uar->logic_idx - 1) %
@@ -102,6 +107,7 @@ int hns_roce_uar_alloc(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
if (!dev_is_pci(hr_dev->dev)) {
res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0);
if (!res) {
+ ida_free(&uar_ida->ida, id);
dev_err(&hr_dev->pdev->dev, "memory resource not found!\n");
return -EINVAL;
}
@@ -114,22 +120,13 @@ int hns_roce_uar_alloc(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
return 0;
}
-void hns_roce_uar_free(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
+void hns_roce_init_uar_table(struct hns_roce_dev *hr_dev)
{
- hns_roce_bitmap_free(&hr_dev->uar_table.bitmap, uar->logic_idx);
-}
+ struct hns_roce_ida *uar_ida = &hr_dev->uar_ida;
-int hns_roce_init_uar_table(struct hns_roce_dev *hr_dev)
-{
- return hns_roce_bitmap_init(&hr_dev->uar_table.bitmap,
- hr_dev->caps.num_uars,
- hr_dev->caps.num_uars - 1,
- hr_dev->caps.reserved_uars, 0);
-}
-
-void hns_roce_cleanup_uar_table(struct hns_roce_dev *hr_dev)
-{
- hns_roce_bitmap_cleanup(&hr_dev->uar_table.bitmap);
+ ida_init(&uar_ida->ida);
+ uar_ida->max = hr_dev->caps.num_uars - 1;
+ uar_ida->min = hr_dev->caps.reserved_uars;
}
static int hns_roce_xrcd_alloc(struct hns_roce_dev *hr_dev, u32 *xrcdn)
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
index b101b7e578f2..9af4509894e6 100644
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -715,7 +715,6 @@ static int alloc_rq_inline_buf(struct hns_roce_qp *hr_qp,
/* allocate recv inline buf */
wqe_list = kcalloc(wqe_cnt, sizeof(struct hns_roce_rinl_wqe),
GFP_KERNEL);
-
if (!wqe_list)
goto err;
@@ -823,77 +822,104 @@ static inline bool kernel_qp_has_rdb(struct hns_roce_dev *hr_dev,
hns_roce_qp_has_rq(init_attr));
}
+static int alloc_user_qp_db(struct hns_roce_dev *hr_dev,
+ struct hns_roce_qp *hr_qp,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata,
+ struct hns_roce_ib_create_qp *ucmd,
+ struct hns_roce_ib_create_qp_resp *resp)
+{
+ struct hns_roce_ucontext *uctx = rdma_udata_to_drv_context(udata,
+ struct hns_roce_ucontext, ibucontext);
+ struct ib_device *ibdev = &hr_dev->ib_dev;
+ int ret;
+
+ if (user_qp_has_sdb(hr_dev, init_attr, udata, resp, ucmd)) {
+ ret = hns_roce_db_map_user(uctx, ucmd->sdb_addr, &hr_qp->sdb);
+ if (ret) {
+ ibdev_err(ibdev,
+ "failed to map user SQ doorbell, ret = %d.\n",
+ ret);
+ goto err_out;
+ }
+ hr_qp->en_flags |= HNS_ROCE_QP_CAP_SQ_RECORD_DB;
+ }
+
+ if (user_qp_has_rdb(hr_dev, init_attr, udata, resp)) {
+ ret = hns_roce_db_map_user(uctx, ucmd->db_addr, &hr_qp->rdb);
+ if (ret) {
+ ibdev_err(ibdev,
+ "failed to map user RQ doorbell, ret = %d.\n",
+ ret);
+ goto err_sdb;
+ }
+ hr_qp->en_flags |= HNS_ROCE_QP_CAP_RQ_RECORD_DB;
+ }
+
+ return 0;
+
+err_sdb:
+ if (hr_qp->en_flags & HNS_ROCE_QP_CAP_SQ_RECORD_DB)
+ hns_roce_db_unmap_user(uctx, &hr_qp->sdb);
+err_out:
+ return ret;
+}
+
+static int alloc_kernel_qp_db(struct hns_roce_dev *hr_dev,
+ struct hns_roce_qp *hr_qp,
+ struct ib_qp_init_attr *init_attr)
+{
+ struct ib_device *ibdev = &hr_dev->ib_dev;
+ int ret;
+
+ if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09)
+ hr_qp->sq.db_reg = hr_dev->mem_base +
+ HNS_ROCE_DWQE_SIZE * hr_qp->qpn;
+ else
+ hr_qp->sq.db_reg = hr_dev->reg_base + hr_dev->sdb_offset +
+ DB_REG_OFFSET * hr_dev->priv_uar.index;
+
+ hr_qp->rq.db_reg = hr_dev->reg_base + hr_dev->odb_offset +
+ DB_REG_OFFSET * hr_dev->priv_uar.index;
+
+ if (kernel_qp_has_rdb(hr_dev, init_attr)) {
+ ret = hns_roce_alloc_db(hr_dev, &hr_qp->rdb, 0);
+ if (ret) {
+ ibdev_err(ibdev,
+ "failed to alloc kernel RQ doorbell, ret = %d.\n",
+ ret);
+ return ret;
+ }
+ *hr_qp->rdb.db_record = 0;
+ hr_qp->en_flags |= HNS_ROCE_QP_CAP_RQ_RECORD_DB;
+ }
+
+ return 0;
+}
+
static int alloc_qp_db(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata,
struct hns_roce_ib_create_qp *ucmd,
struct hns_roce_ib_create_qp_resp *resp)
{
- struct hns_roce_ucontext *uctx = rdma_udata_to_drv_context(
- udata, struct hns_roce_ucontext, ibucontext);
- struct ib_device *ibdev = &hr_dev->ib_dev;
int ret;
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SDI_MODE)
hr_qp->en_flags |= HNS_ROCE_QP_CAP_OWNER_DB;
if (udata) {
- if (user_qp_has_sdb(hr_dev, init_attr, udata, resp, ucmd)) {
- ret = hns_roce_db_map_user(uctx, ucmd->sdb_addr,
- &hr_qp->sdb);
- if (ret) {
- ibdev_err(ibdev,
- "failed to map user SQ doorbell, ret = %d.\n",
- ret);
- goto err_out;
- }
- hr_qp->en_flags |= HNS_ROCE_QP_CAP_SQ_RECORD_DB;
- resp->cap_flags |= HNS_ROCE_QP_CAP_SQ_RECORD_DB;
- }
-
- if (user_qp_has_rdb(hr_dev, init_attr, udata, resp)) {
- ret = hns_roce_db_map_user(uctx, ucmd->db_addr,
- &hr_qp->rdb);
- if (ret) {
- ibdev_err(ibdev,
- "failed to map user RQ doorbell, ret = %d.\n",
- ret);
- goto err_sdb;
- }
- hr_qp->en_flags |= HNS_ROCE_QP_CAP_RQ_RECORD_DB;
- resp->cap_flags |= HNS_ROCE_QP_CAP_RQ_RECORD_DB;
- }
+ ret = alloc_user_qp_db(hr_dev, hr_qp, init_attr, udata, ucmd,
+ resp);
+ if (ret)
+ return ret;
} else {
- if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09)
- hr_qp->sq.db_reg = hr_dev->mem_base +
- HNS_ROCE_DWQE_SIZE * hr_qp->qpn;
- else
- hr_qp->sq.db_reg =
- hr_dev->reg_base + hr_dev->sdb_offset +
- DB_REG_OFFSET * hr_dev->priv_uar.index;
-
- hr_qp->rq.db_reg = hr_dev->reg_base + hr_dev->odb_offset +
- DB_REG_OFFSET * hr_dev->priv_uar.index;
-
- if (kernel_qp_has_rdb(hr_dev, init_attr)) {
- ret = hns_roce_alloc_db(hr_dev, &hr_qp->rdb, 0);
- if (ret) {
- ibdev_err(ibdev,
- "failed to alloc kernel RQ doorbell, ret = %d.\n",
- ret);
- goto err_out;
- }
- *hr_qp->rdb.db_record = 0;
- hr_qp->en_flags |= HNS_ROCE_QP_CAP_RQ_RECORD_DB;
- }
+ ret = alloc_kernel_qp_db(hr_dev, hr_qp, init_attr);
+ if (ret)
+ return ret;
}
return 0;
-err_sdb:
- if (udata && hr_qp->en_flags & HNS_ROCE_QP_CAP_SQ_RECORD_DB)
- hns_roce_db_unmap_user(uctx, &hr_qp->sdb);
-err_out:
- return ret;
}
static void free_qp_db(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
@@ -959,8 +985,6 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
struct ib_device *ibdev = &hr_dev->ib_dev;
int ret;
- hr_qp->ibqp.qp_type = init_attr->qp_type;
-
if (init_attr->cap.max_inline_data > hr_dev->caps.max_sq_inline)
init_attr->cap.max_inline_data = hr_dev->caps.max_sq_inline;
@@ -1073,6 +1097,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
}
if (udata) {
+ resp.cap_flags = hr_qp->en_flags;
ret = ib_copy_to_udata(udata, &resp,
min(udata->outlen, sizeof(resp)));
if (ret) {
@@ -1121,8 +1146,6 @@ void hns_roce_qp_destroy(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
free_qp_buf(hr_dev, hr_qp);
free_kernel_wrid(hr_qp);
free_qp_db(hr_dev, hr_qp, udata);
-
- kfree(hr_qp);
}
static int check_qp_type(struct hns_roce_dev *hr_dev, enum ib_qp_type type,
@@ -1154,31 +1177,21 @@ out:
return -EOPNOTSUPP;
}
-struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata)
+int hns_roce_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
{
- struct ib_device *ibdev = pd ? pd->device : init_attr->xrcd->device;
+ struct ib_device *ibdev = qp->device;
struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
- struct hns_roce_qp *hr_qp;
+ struct hns_roce_qp *hr_qp = to_hr_qp(qp);
+ struct ib_pd *pd = qp->pd;
int ret;
ret = check_qp_type(hr_dev, init_attr->qp_type, !!udata);
if (ret)
- return ERR_PTR(ret);
-
- hr_qp = kzalloc(sizeof(*hr_qp), GFP_KERNEL);
- if (!hr_qp)
- return ERR_PTR(-ENOMEM);
-
- if (init_attr->qp_type == IB_QPT_XRC_INI)
- init_attr->recv_cq = NULL;
+ return ret;
- if (init_attr->qp_type == IB_QPT_XRC_TGT) {
+ if (init_attr->qp_type == IB_QPT_XRC_TGT)
hr_qp->xrcdn = to_hr_xrcd(init_attr->xrcd)->xrcdn;
- init_attr->recv_cq = NULL;
- init_attr->send_cq = NULL;
- }
if (init_attr->qp_type == IB_QPT_GSI) {
hr_qp->port = init_attr->port_num - 1;
@@ -1186,15 +1199,11 @@ struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
}
ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata, hr_qp);
- if (ret) {
+ if (ret)
ibdev_err(ibdev, "Create QP type 0x%x failed(%d)\n",
init_attr->qp_type, ret);
- kfree(hr_qp);
- return ERR_PTR(ret);
- }
-
- return &hr_qp->ibqp;
+ return ret;
}
int to_hr_qp_type(int qp_type)
@@ -1321,17 +1330,8 @@ int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
if (ret)
goto out;
- if (cur_state == new_state && cur_state == IB_QPS_RESET) {
- if (hr_dev->hw_rev == HNS_ROCE_HW_VER1) {
- ret = -EPERM;
- ibdev_err(&hr_dev->ib_dev,
- "RST2RST state is not supported\n");
- } else {
- ret = 0;
- }
-
+ if (cur_state == new_state && cur_state == IB_QPS_RESET)
goto out;
- }
ret = hr_dev->hw->modify_qp(ibqp, attr, attr_mask, cur_state,
new_state);
@@ -1429,12 +1429,17 @@ bool hns_roce_wq_overflow(struct hns_roce_wq *hr_wq, u32 nreq,
return cur + nreq >= hr_wq->wqe_cnt;
}
-void hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
+int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
{
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
unsigned int reserved_from_bot;
unsigned int i;
+ qp_table->idx_table.spare_idx = kcalloc(hr_dev->caps.num_qps,
+ sizeof(u32), GFP_KERNEL);
+ if (!qp_table->idx_table.spare_idx)
+ return -ENOMEM;
+
mutex_init(&qp_table->scc_mutex);
mutex_init(&qp_table->bank_mutex);
xa_init(&hr_dev->qp_table_xa);
@@ -1452,6 +1457,8 @@ void hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
HNS_ROCE_QP_BANK_NUM - 1;
hr_dev->qp_table.bank[i].next = hr_dev->qp_table.bank[i].min;
}
+
+ return 0;
}
void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev)
@@ -1460,4 +1467,5 @@ void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev)
for (i = 0; i < HNS_ROCE_QP_BANK_NUM; i++)
ida_destroy(&hr_dev->qp_table.bank[i].ida);
+ kfree(hr_dev->qp_table.idx_table.spare_idx);
}
diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c
index 6f2992f443fa..6eee9deadd12 100644
--- a/drivers/infiniband/hw/hns/hns_roce_srq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_srq.c
@@ -80,15 +80,19 @@ static int hns_roce_hw_destroy_srq(struct hns_roce_dev *dev,
static int alloc_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
{
struct hns_roce_srq_table *srq_table = &hr_dev->srq_table;
+ struct hns_roce_ida *srq_ida = &hr_dev->srq_table.srq_ida;
struct ib_device *ibdev = &hr_dev->ib_dev;
struct hns_roce_cmd_mailbox *mailbox;
int ret;
+ int id;
- ret = hns_roce_bitmap_alloc(&srq_table->bitmap, &srq->srqn);
- if (ret) {
- ibdev_err(ibdev, "failed to alloc SRQ number.\n");
+ id = ida_alloc_range(&srq_ida->ida, srq_ida->min, srq_ida->max,
+ GFP_KERNEL);
+ if (id < 0) {
+ ibdev_err(ibdev, "failed to alloc srq(%d).\n", id);
return -ENOMEM;
}
+ srq->srqn = (unsigned long)id;
ret = hns_roce_table_get(hr_dev, &srq_table->table, srq->srqn);
if (ret) {
@@ -132,7 +136,7 @@ err_xa:
err_put:
hns_roce_table_put(hr_dev, &srq_table->table, srq->srqn);
err_out:
- hns_roce_bitmap_free(&srq_table->bitmap, srq->srqn);
+ ida_free(&srq_ida->ida, id);
return ret;
}
@@ -154,7 +158,7 @@ static void free_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
wait_for_completion(&srq->free);
hns_roce_table_put(hr_dev, &srq_table->table, srq->srqn);
- hns_roce_bitmap_free(&srq_table->bitmap, srq->srqn);
+ ida_free(&srq_table->srq_ida.ida, (int)srq->srqn);
}
static int alloc_srq_idx(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq,
@@ -440,18 +444,14 @@ int hns_roce_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata)
return 0;
}
-int hns_roce_init_srq_table(struct hns_roce_dev *hr_dev)
+void hns_roce_init_srq_table(struct hns_roce_dev *hr_dev)
{
struct hns_roce_srq_table *srq_table = &hr_dev->srq_table;
+ struct hns_roce_ida *srq_ida = &srq_table->srq_ida;
xa_init(&srq_table->xa);
- return hns_roce_bitmap_init(&srq_table->bitmap, hr_dev->caps.num_srqs,
- hr_dev->caps.num_srqs - 1,
- hr_dev->caps.reserved_srqs, 0);
-}
-
-void hns_roce_cleanup_srq_table(struct hns_roce_dev *hr_dev)
-{
- hns_roce_bitmap_cleanup(&hr_dev->srq_table.bitmap);
+ ida_init(&srq_ida->ida);
+ srq_ida->max = hr_dev->caps.num_srqs - 1;
+ srq_ida->min = hr_dev->caps.reserved_srqs;
}
diff --git a/drivers/infiniband/hw/irdma/protos.h b/drivers/infiniband/hw/irdma/protos.h
index e3f5173706fe..78f598fdbccf 100644
--- a/drivers/infiniband/hw/irdma/protos.h
+++ b/drivers/infiniband/hw/irdma/protos.h
@@ -71,8 +71,6 @@ void irdma_qp_rem_qos(struct irdma_sc_qp *qp);
struct irdma_sc_qp *irdma_get_qp_from_list(struct list_head *head,
struct irdma_sc_qp *qp);
void irdma_reinitialize_ieq(struct irdma_sc_vsi *vsi);
-u16 irdma_alloc_ws_node_id(struct irdma_sc_dev *dev);
-void irdma_free_ws_node_id(struct irdma_sc_dev *dev, u16 node_id);
/* terminate functions*/
void irdma_terminate_send_fin(struct irdma_sc_qp *qp);
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
index 5bbe44e54f9a..e94470991fe0 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
@@ -1141,10 +1141,7 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)
iwqp->kqp.dma_mem.va, iwqp->kqp.dma_mem.pa);
iwqp->kqp.dma_mem.va = NULL;
kfree(iwqp->kqp.sq_wrid_mem);
- iwqp->kqp.sq_wrid_mem = NULL;
kfree(iwqp->kqp.rq_wrid_mem);
- iwqp->kqp.rq_wrid_mem = NULL;
- kfree(iwqp);
}
/**
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 717147ed0519..4fc323402073 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -790,18 +790,19 @@ static int irdma_validate_qp_attrs(struct ib_qp_init_attr *init_attr,
/**
* irdma_create_qp - create qp
- * @ibpd: ptr of pd
+ * @ibqp: ptr of qp
* @init_attr: attributes for qp
* @udata: user data for create qp
*/
-static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata)
+static int irdma_create_qp(struct ib_qp *ibqp,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
{
+ struct ib_pd *ibpd = ibqp->pd;
struct irdma_pd *iwpd = to_iwpd(ibpd);
struct irdma_device *iwdev = to_iwdev(ibpd->device);
struct irdma_pci_f *rf = iwdev->rf;
- struct irdma_qp *iwqp;
+ struct irdma_qp *iwqp = to_iwqp(ibqp);
struct irdma_create_qp_req req;
struct irdma_create_qp_resp uresp = {};
u32 qp_num = 0;
@@ -818,7 +819,7 @@ static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
err_code = irdma_validate_qp_attrs(init_attr, iwdev);
if (err_code)
- return ERR_PTR(err_code);
+ return err_code;
sq_size = init_attr->cap.max_send_wr;
rq_size = init_attr->cap.max_recv_wr;
@@ -831,10 +832,6 @@ static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
init_info.qp_uk_init_info.max_rq_frag_cnt = init_attr->cap.max_recv_sge;
init_info.qp_uk_init_info.max_inline_data = init_attr->cap.max_inline_data;
- iwqp = kzalloc(sizeof(*iwqp), GFP_KERNEL);
- if (!iwqp)
- return ERR_PTR(-ENOMEM);
-
qp = &iwqp->sc_qp;
qp->qp_uk.back_qp = iwqp;
qp->qp_uk.lock = &iwqp->lock;
@@ -847,10 +844,8 @@ static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
iwqp->q2_ctx_mem.size,
&iwqp->q2_ctx_mem.pa,
GFP_KERNEL);
- if (!iwqp->q2_ctx_mem.va) {
- err_code = -ENOMEM;
- goto error;
- }
+ if (!iwqp->q2_ctx_mem.va)
+ return -ENOMEM;
init_info.q2 = iwqp->q2_ctx_mem.va;
init_info.q2_pa = iwqp->q2_ctx_mem.pa;
@@ -999,17 +994,16 @@ static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
if (err_code) {
ibdev_dbg(&iwdev->ibdev, "VERBS: copy_to_udata failed\n");
irdma_destroy_qp(&iwqp->ibqp, udata);
- return ERR_PTR(err_code);
+ return err_code;
}
}
init_completion(&iwqp->free_qp);
- return &iwqp->ibqp;
+ return 0;
error:
irdma_free_qp_rsrc(iwqp);
-
- return ERR_PTR(err_code);
+ return err_code;
}
static int irdma_get_ib_acc_flags(struct irdma_qp *iwqp)
@@ -2235,7 +2229,7 @@ static void irdma_copy_user_pgaddrs(struct irdma_mr *iwmr, u64 *pbl,
pinfo = (level == PBLE_LEVEL_1) ? NULL : palloc->level2.leaf;
if (iwmr->type == IRDMA_MEMREG_TYPE_QP)
- iwpbl->qp_mr.sq_page = sg_page(region->sg_head.sgl);
+ iwpbl->qp_mr.sq_page = sg_page(region->sgt_append.sgt.sgl);
rdma_umem_for_each_dma_block(region, &biter, iwmr->page_size) {
*pbl = rdma_block_iter_dma_address(&biter);
@@ -4404,6 +4398,7 @@ static const struct ib_device_ops irdma_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, irdma_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, irdma_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_mw, irdma_mr, ibmw),
+ INIT_RDMA_OBJ_SIZE(ib_qp, irdma_qp, ibqp),
};
/**
diff --git a/drivers/infiniband/hw/mlx4/doorbell.c b/drivers/infiniband/hw/mlx4/doorbell.c
index d41f03ccb0e1..9bbd695a9fd5 100644
--- a/drivers/infiniband/hw/mlx4/doorbell.c
+++ b/drivers/infiniband/hw/mlx4/doorbell.c
@@ -75,7 +75,8 @@ int mlx4_ib_db_map_user(struct ib_udata *udata, unsigned long virt,
list_add(&page->list, &context->db_page_list);
found:
- db->dma = sg_dma_address(page->umem->sg_head.sgl) + (virt & ~PAGE_MASK);
+ db->dma = sg_dma_address(page->umem->sgt_append.sgt.sgl) +
+ (virt & ~PAGE_MASK);
db->u.user_page = page;
++page->refcnt;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index ae4c91b612ce..f367f4a4abff 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -2577,6 +2577,7 @@ static const struct ib_device_ops mlx4_ib_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, mlx4_ib_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, mlx4_ib_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, mlx4_ib_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, mlx4_ib_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_srq, mlx4_ib_srq, ibsrq),
INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx4_ib_ucontext, ibucontext),
};
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index e856cf23a0a1..c60f6e9ac640 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -792,9 +792,8 @@ void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index);
int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
const struct ib_recv_wr **bad_wr);
-struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata);
+int mlx4_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
int mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
void mlx4_ib_drain_sq(struct ib_qp *qp);
void mlx4_ib_drain_rq(struct ib_qp *qp);
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 50becc0e4b62..04a67b481608 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -200,7 +200,7 @@ int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt,
mtt_shift = mtt->page_shift;
mtt_size = 1ULL << mtt_shift;
- for_each_sg(umem->sg_head.sgl, sg, umem->nmap, i) {
+ for_each_sgtable_dma_sg(&umem->sgt_append.sgt, sg, i) {
if (cur_start_addr + len == sg_dma_address(sg)) {
/* still the same block */
len += sg_dma_len(sg);
@@ -273,7 +273,7 @@ int mlx4_ib_umem_calc_optimal_mtt_size(struct ib_umem *umem, u64 start_va,
*num_of_mtts = ib_umem_num_dma_blocks(umem, PAGE_SIZE);
- for_each_sg(umem->sg_head.sgl, sg, umem->nmap, i) {
+ for_each_sgtable_dma_sg(&umem->sgt_append.sgt, sg, i) {
/*
* Initialization - save the first chunk start as the
* current_block_start - block means contiguous pages.
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 4a2ef7daaded..8662f462e2a5 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1578,24 +1578,19 @@ static int _mlx4_ib_create_qp(struct ib_pd *pd, struct mlx4_ib_qp *qp,
return 0;
}
-struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata) {
- struct ib_device *device = pd ? pd->device : init_attr->xrcd->device;
+int mlx4_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ struct ib_device *device = ibqp->device;
struct mlx4_ib_dev *dev = to_mdev(device);
- struct mlx4_ib_qp *qp;
+ struct mlx4_ib_qp *qp = to_mqp(ibqp);
+ struct ib_pd *pd = ibqp->pd;
int ret;
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return ERR_PTR(-ENOMEM);
-
mutex_init(&qp->mutex);
ret = _mlx4_ib_create_qp(pd, qp, init_attr, udata);
- if (ret) {
- kfree(qp);
- return ERR_PTR(ret);
- }
+ if (ret)
+ return ret;
if (init_attr->qp_type == IB_QPT_GSI &&
!(init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI)) {
@@ -1618,7 +1613,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
init_attr->create_flags &= ~MLX4_IB_QP_CREATE_ROCE_V2_GSI;
}
}
- return &qp->ibqp;
+ return 0;
}
static int _mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
@@ -1646,8 +1641,6 @@ static int _mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
}
kfree(mqp->sqp);
- kfree(mqp);
-
return 0;
}
diff --git a/drivers/infiniband/hw/mlx5/doorbell.c b/drivers/infiniband/hw/mlx5/doorbell.c
index 9ca2e61807ec..6398e2f48579 100644
--- a/drivers/infiniband/hw/mlx5/doorbell.c
+++ b/drivers/infiniband/hw/mlx5/doorbell.c
@@ -78,7 +78,8 @@ int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt,
list_add(&page->list, &context->db_page_list);
found:
- db->dma = sg_dma_address(page->umem->sg_head.sgl) + (virt & ~PAGE_MASK);
+ db->dma = sg_dma_address(page->umem->sgt_append.sgt.sgl) +
+ (virt & ~PAGE_MASK);
db->u.user_page = page;
++page->refcnt;
diff --git a/drivers/infiniband/hw/mlx5/gsi.c b/drivers/infiniband/hw/mlx5/gsi.c
index 7fcad9135276..3ad8f637c589 100644
--- a/drivers/infiniband/hw/mlx5/gsi.c
+++ b/drivers/infiniband/hw/mlx5/gsi.c
@@ -116,8 +116,6 @@ int mlx5_ib_create_gsi(struct ib_pd *pd, struct mlx5_ib_qp *mqp,
goto err_free_tx;
}
- mutex_lock(&dev->devr.mutex);
-
if (dev->devr.ports[port_num - 1].gsi) {
mlx5_ib_warn(dev, "GSI QP already exists on port %d\n",
port_num);
@@ -147,35 +145,20 @@ int mlx5_ib_create_gsi(struct ib_pd *pd, struct mlx5_ib_qp *mqp,
hw_init_attr.cap.max_inline_data = 0;
}
- gsi->rx_qp = mlx5_ib_create_qp(pd, &hw_init_attr, NULL);
+ gsi->rx_qp = ib_create_qp(pd, &hw_init_attr);
if (IS_ERR(gsi->rx_qp)) {
mlx5_ib_warn(dev, "unable to create hardware GSI QP. error %ld\n",
PTR_ERR(gsi->rx_qp));
ret = PTR_ERR(gsi->rx_qp);
goto err_destroy_cq;
}
- gsi->rx_qp->device = pd->device;
- gsi->rx_qp->pd = pd;
- gsi->rx_qp->real_qp = gsi->rx_qp;
-
- gsi->rx_qp->qp_type = hw_init_attr.qp_type;
- gsi->rx_qp->send_cq = hw_init_attr.send_cq;
- gsi->rx_qp->recv_cq = hw_init_attr.recv_cq;
- gsi->rx_qp->event_handler = hw_init_attr.event_handler;
- spin_lock_init(&gsi->rx_qp->mr_lock);
- INIT_LIST_HEAD(&gsi->rx_qp->rdma_mrs);
- INIT_LIST_HEAD(&gsi->rx_qp->sig_mrs);
dev->devr.ports[attr->port_num - 1].gsi = gsi;
-
- mutex_unlock(&dev->devr.mutex);
-
return 0;
err_destroy_cq:
ib_free_cq(gsi->cq);
err_free_wrs:
- mutex_unlock(&dev->devr.mutex);
kfree(gsi->outstanding_wrs);
err_free_tx:
kfree(gsi->tx_qps);
@@ -190,16 +173,13 @@ int mlx5_ib_destroy_gsi(struct mlx5_ib_qp *mqp)
int qp_index;
int ret;
- mutex_lock(&dev->devr.mutex);
- ret = mlx5_ib_destroy_qp(gsi->rx_qp, NULL);
+ ret = ib_destroy_qp(gsi->rx_qp);
if (ret) {
mlx5_ib_warn(dev, "unable to destroy hardware GSI QP. error %d\n",
ret);
- mutex_unlock(&dev->devr.mutex);
return ret;
}
dev->devr.ports[port_num - 1].gsi = NULL;
- mutex_unlock(&dev->devr.mutex);
gsi->rx_qp = NULL;
for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index) {
@@ -213,8 +193,6 @@ int mlx5_ib_destroy_gsi(struct mlx5_ib_qp *mqp)
kfree(gsi->outstanding_wrs);
kfree(gsi->tx_qps);
- kfree(mqp);
-
return 0;
}
@@ -339,23 +317,13 @@ err_destroy_qp:
WARN_ON_ONCE(qp);
}
-static void setup_qps(struct mlx5_ib_gsi_qp *gsi)
-{
- struct mlx5_ib_dev *dev = to_mdev(gsi->rx_qp->device);
- u16 qp_index;
-
- mutex_lock(&dev->devr.mutex);
- for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index)
- setup_qp(gsi, qp_index);
- mutex_unlock(&dev->devr.mutex);
-}
-
int mlx5_ib_gsi_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
int attr_mask)
{
struct mlx5_ib_dev *dev = to_mdev(qp->device);
struct mlx5_ib_qp *mqp = to_mqp(qp);
struct mlx5_ib_gsi_qp *gsi = &mqp->gsi;
+ u16 qp_index;
int ret;
mlx5_ib_dbg(dev, "modifying GSI QP to state %d\n", attr->qp_state);
@@ -366,8 +334,11 @@ int mlx5_ib_gsi_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
return ret;
}
- if (to_mqp(gsi->rx_qp)->state == IB_QPS_RTS)
- setup_qps(gsi);
+ if (to_mqp(gsi->rx_qp)->state != IB_QPS_RTS)
+ return 0;
+
+ for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index)
+ setup_qp(gsi, qp_index);
return 0;
}
@@ -511,8 +482,8 @@ int mlx5_ib_gsi_post_recv(struct ib_qp *qp, const struct ib_recv_wr *wr,
void mlx5_ib_gsi_pkey_change(struct mlx5_ib_gsi_qp *gsi)
{
- if (!gsi)
- return;
+ u16 qp_index;
- setup_qps(gsi);
+ for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index)
+ setup_qp(gsi, qp_index);
}
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 466f0a521940..8664bcf6d3f5 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1184,6 +1184,16 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
MLX5_IB_TUNNELED_OFFLOADS_MPLS_UDP;
}
+ if (offsetofend(typeof(resp), dci_streams_caps) <= uhw_outlen) {
+ resp.response_length += sizeof(resp.dci_streams_caps);
+
+ resp.dci_streams_caps.max_log_num_concurent =
+ MLX5_CAP_GEN(mdev, log_max_dci_stream_channels);
+
+ resp.dci_streams_caps.max_log_num_errored =
+ MLX5_CAP_GEN(mdev, log_max_dci_errored_streams);
+ }
+
if (uhw_outlen) {
err = ib_copy_to_udata(uhw, &resp, resp.response_length);
@@ -2501,6 +2511,13 @@ static void pkey_change_handler(struct work_struct *work)
container_of(work, struct mlx5_ib_port_resources,
pkey_change_work);
+ if (!ports->gsi)
+ /*
+ * We got this event before device was fully configured
+ * and MAD registration code wasn't called/finished yet.
+ */
+ return;
+
mlx5_ib_gsi_pkey_change(ports->gsi);
}
@@ -2795,33 +2812,16 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
if (!MLX5_CAP_GEN(dev->mdev, xrc))
return -EOPNOTSUPP;
- mutex_init(&devr->mutex);
-
- devr->p0 = rdma_zalloc_drv_obj(ibdev, ib_pd);
- if (!devr->p0)
- return -ENOMEM;
-
- devr->p0->device = ibdev;
- devr->p0->uobject = NULL;
- atomic_set(&devr->p0->usecnt, 0);
-
- ret = mlx5_ib_alloc_pd(devr->p0, NULL);
- if (ret)
- goto error0;
+ devr->p0 = ib_alloc_pd(ibdev, 0);
+ if (IS_ERR(devr->p0))
+ return PTR_ERR(devr->p0);
- devr->c0 = rdma_zalloc_drv_obj(ibdev, ib_cq);
- if (!devr->c0) {
- ret = -ENOMEM;
+ devr->c0 = ib_create_cq(ibdev, NULL, NULL, NULL, &cq_attr);
+ if (IS_ERR(devr->c0)) {
+ ret = PTR_ERR(devr->c0);
goto error1;
}
- devr->c0->device = &dev->ib_dev;
- atomic_set(&devr->c0->usecnt, 0);
-
- ret = mlx5_ib_create_cq(devr->c0, &cq_attr, NULL);
- if (ret)
- goto err_create_cq;
-
ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn0, 0);
if (ret)
goto error2;
@@ -2836,45 +2836,22 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
attr.srq_type = IB_SRQT_XRC;
attr.ext.cq = devr->c0;
- devr->s0 = rdma_zalloc_drv_obj(ibdev, ib_srq);
- if (!devr->s0) {
- ret = -ENOMEM;
- goto error4;
- }
-
- devr->s0->device = &dev->ib_dev;
- devr->s0->pd = devr->p0;
- devr->s0->srq_type = IB_SRQT_XRC;
- devr->s0->ext.cq = devr->c0;
- ret = mlx5_ib_create_srq(devr->s0, &attr, NULL);
- if (ret)
+ devr->s0 = ib_create_srq(devr->p0, &attr);
+ if (IS_ERR(devr->s0)) {
+ ret = PTR_ERR(devr->s0);
goto err_create;
-
- atomic_inc(&devr->s0->ext.cq->usecnt);
- atomic_inc(&devr->p0->usecnt);
- atomic_set(&devr->s0->usecnt, 0);
+ }
memset(&attr, 0, sizeof(attr));
attr.attr.max_sge = 1;
attr.attr.max_wr = 1;
attr.srq_type = IB_SRQT_BASIC;
- devr->s1 = rdma_zalloc_drv_obj(ibdev, ib_srq);
- if (!devr->s1) {
- ret = -ENOMEM;
- goto error5;
- }
-
- devr->s1->device = &dev->ib_dev;
- devr->s1->pd = devr->p0;
- devr->s1->srq_type = IB_SRQT_BASIC;
- devr->s1->ext.cq = devr->c0;
- ret = mlx5_ib_create_srq(devr->s1, &attr, NULL);
- if (ret)
+ devr->s1 = ib_create_srq(devr->p0, &attr);
+ if (IS_ERR(devr->s1)) {
+ ret = PTR_ERR(devr->s1);
goto error6;
-
- atomic_inc(&devr->p0->usecnt);
- atomic_set(&devr->s1->usecnt, 0);
+ }
for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
INIT_WORK(&devr->ports[port].pkey_change_work,
@@ -2883,23 +2860,15 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
return 0;
error6:
- kfree(devr->s1);
-error5:
- mlx5_ib_destroy_srq(devr->s0, NULL);
+ ib_destroy_srq(devr->s0);
err_create:
- kfree(devr->s0);
-error4:
mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0);
error3:
mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);
error2:
- mlx5_ib_destroy_cq(devr->c0, NULL);
-err_create_cq:
- kfree(devr->c0);
+ ib_destroy_cq(devr->c0);
error1:
- mlx5_ib_dealloc_pd(devr->p0, NULL);
-error0:
- kfree(devr->p0);
+ ib_dealloc_pd(devr->p0);
return ret;
}
@@ -2908,20 +2877,21 @@ static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)
struct mlx5_ib_resources *devr = &dev->devr;
int port;
- mlx5_ib_destroy_srq(devr->s1, NULL);
- kfree(devr->s1);
- mlx5_ib_destroy_srq(devr->s0, NULL);
- kfree(devr->s0);
- mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0);
- mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);
- mlx5_ib_destroy_cq(devr->c0, NULL);
- kfree(devr->c0);
- mlx5_ib_dealloc_pd(devr->p0, NULL);
- kfree(devr->p0);
-
- /* Make sure no change P_Key work items are still executing */
+ /*
+ * Make sure no change P_Key work items are still executing.
+ *
+ * At this stage, the mlx5_ib_event should be unregistered
+ * and it ensures that no new works are added.
+ */
for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
cancel_work_sync(&devr->ports[port].pkey_change_work);
+
+ ib_destroy_srq(devr->s1);
+ ib_destroy_srq(devr->s0);
+ mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0);
+ mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);
+ ib_destroy_cq(devr->c0);
+ ib_dealloc_pd(devr->p0);
}
static u32 get_core_cap_flags(struct ib_device *ibdev,
@@ -3799,6 +3769,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_counters, mlx5_ib_mcounters, ibcntrs),
INIT_RDMA_OBJ_SIZE(ib_cq, mlx5_ib_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, mlx5_ib_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, mlx5_ib_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_srq, mlx5_ib_srq, ibsrq),
INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx5_ib_ucontext, ibucontext),
};
@@ -4061,7 +4032,7 @@ static void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev)
mlx5_ib_warn(dev, "mr cache cleanup failed\n");
if (dev->umrc.qp)
- mlx5_ib_destroy_qp(dev->umrc.qp, NULL);
+ ib_destroy_qp(dev->umrc.qp);
if (dev->umrc.cq)
ib_free_cq(dev->umrc.cq);
if (dev->umrc.pd)
@@ -4114,23 +4085,17 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
init_attr->cap.max_send_sge = 1;
init_attr->qp_type = MLX5_IB_QPT_REG_UMR;
init_attr->port_num = 1;
- qp = mlx5_ib_create_qp(pd, init_attr, NULL);
+ qp = ib_create_qp(pd, init_attr);
if (IS_ERR(qp)) {
mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n");
ret = PTR_ERR(qp);
goto error_3;
}
- qp->device = &dev->ib_dev;
- qp->real_qp = qp;
- qp->uobject = NULL;
- qp->qp_type = MLX5_IB_QPT_REG_UMR;
- qp->send_cq = init_attr->send_cq;
- qp->recv_cq = init_attr->recv_cq;
attr->qp_state = IB_QPS_INIT;
attr->port_num = 1;
- ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_PKEY_INDEX |
- IB_QP_PORT, NULL);
+ ret = ib_modify_qp(qp, attr,
+ IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT);
if (ret) {
mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n");
goto error_4;
@@ -4140,7 +4105,7 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
attr->qp_state = IB_QPS_RTR;
attr->path_mtu = IB_MTU_256;
- ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL);
+ ret = ib_modify_qp(qp, attr, IB_QP_STATE);
if (ret) {
mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n");
goto error_4;
@@ -4148,7 +4113,7 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
memset(attr, 0, sizeof(*attr));
attr->qp_state = IB_QPS_RTS;
- ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL);
+ ret = ib_modify_qp(qp, attr, IB_QP_STATE);
if (ret) {
mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n");
goto error_4;
@@ -4171,7 +4136,7 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
return 0;
error_4:
- mlx5_ib_destroy_qp(qp, NULL);
+ ib_destroy_qp(qp);
dev->umrc.qp = NULL;
error_3:
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 585fb00bdce8..bf20a388eabe 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -795,8 +795,6 @@ struct mlx5_ib_resources {
struct ib_srq *s0;
struct ib_srq *s1;
struct mlx5_ib_port_resources ports[2];
- /* Protects changes to the port resources */
- struct mutex mutex;
};
struct mlx5_ib_counters {
@@ -1221,9 +1219,8 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
const struct ib_recv_wr **bad_wr);
int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp);
void mlx5_ib_disable_lb(struct mlx5_ib_dev *dev, bool td, bool qp);
-struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata);
+int mlx5_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 3f1c5a4f158b..a520ac8ab68c 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -1226,7 +1226,8 @@ int mlx5_ib_update_mr_pas(struct mlx5_ib_mr *mr, unsigned int flags)
orig_sg_length = sg.length;
cur_mtt = mtt;
- rdma_for_each_block (mr->umem->sg_head.sgl, &biter, mr->umem->nmap,
+ rdma_for_each_block (mr->umem->sgt_append.sgt.sgl, &biter,
+ mr->umem->sgt_append.sgt.nents,
BIT(mr->page_shift)) {
if (cur_mtt == (void *)mtt + sg.length) {
dma_sync_single_for_device(ddev, sg.addr, sg.length,
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index a77db29f8391..b2fca110346c 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -1906,7 +1906,6 @@ static int get_atomic_mode(struct mlx5_ib_dev *dev,
static int create_xrc_tgt_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
struct mlx5_create_qp_params *params)
{
- struct mlx5_ib_create_qp *ucmd = params->ucmd;
struct ib_qp_init_attr *attr = params->attr;
u32 uidx = params->uidx;
struct mlx5_ib_resources *devr = &dev->devr;
@@ -1926,8 +1925,6 @@ static int create_xrc_tgt_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
if (!in)
return -ENOMEM;
- if (MLX5_CAP_GEN(mdev, ece_support) && ucmd)
- MLX5_SET(create_qp_in, in, ece, ucmd->ece_options);
qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
MLX5_SET(qpc, qpc, st, MLX5_QP_ST_XRC);
@@ -1982,6 +1979,167 @@ static int create_xrc_tgt_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
return 0;
}
+static int create_dci(struct mlx5_ib_dev *dev, struct ib_pd *pd,
+ struct mlx5_ib_qp *qp,
+ struct mlx5_create_qp_params *params)
+{
+ struct ib_qp_init_attr *init_attr = params->attr;
+ struct mlx5_ib_create_qp *ucmd = params->ucmd;
+ u32 out[MLX5_ST_SZ_DW(create_qp_out)] = {};
+ struct ib_udata *udata = params->udata;
+ u32 uidx = params->uidx;
+ struct mlx5_ib_resources *devr = &dev->devr;
+ int inlen = MLX5_ST_SZ_BYTES(create_qp_in);
+ struct mlx5_core_dev *mdev = dev->mdev;
+ struct mlx5_ib_cq *send_cq;
+ struct mlx5_ib_cq *recv_cq;
+ unsigned long flags;
+ struct mlx5_ib_qp_base *base;
+ int ts_format;
+ int mlx5_st;
+ void *qpc;
+ u32 *in;
+ int err;
+
+ spin_lock_init(&qp->sq.lock);
+ spin_lock_init(&qp->rq.lock);
+
+ mlx5_st = to_mlx5_st(qp->type);
+ if (mlx5_st < 0)
+ return -EINVAL;
+
+ if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
+ qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE;
+
+ base = &qp->trans_qp.base;
+
+ qp->has_rq = qp_has_rq(init_attr);
+ err = set_rq_size(dev, &init_attr->cap, qp->has_rq, qp, ucmd);
+ if (err) {
+ mlx5_ib_dbg(dev, "err %d\n", err);
+ return err;
+ }
+
+ if (ucmd->rq_wqe_shift != qp->rq.wqe_shift ||
+ ucmd->rq_wqe_count != qp->rq.wqe_cnt)
+ return -EINVAL;
+
+ if (ucmd->sq_wqe_count > (1 << MLX5_CAP_GEN(mdev, log_max_qp_sz)))
+ return -EINVAL;
+
+ ts_format = get_qp_ts_format(dev, to_mcq(init_attr->send_cq),
+ to_mcq(init_attr->recv_cq));
+
+ if (ts_format < 0)
+ return ts_format;
+
+ err = _create_user_qp(dev, pd, qp, udata, init_attr, &in, &params->resp,
+ &inlen, base, ucmd);
+ if (err)
+ return err;
+
+ if (MLX5_CAP_GEN(mdev, ece_support))
+ MLX5_SET(create_qp_in, in, ece, ucmd->ece_options);
+ qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
+
+ MLX5_SET(qpc, qpc, st, mlx5_st);
+ MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED);
+ MLX5_SET(qpc, qpc, pd, to_mpd(pd)->pdn);
+
+ if (qp->flags_en & MLX5_QP_FLAG_SIGNATURE)
+ MLX5_SET(qpc, qpc, wq_signature, 1);
+
+ if (qp->flags & IB_QP_CREATE_CROSS_CHANNEL)
+ MLX5_SET(qpc, qpc, cd_master, 1);
+ if (qp->flags & IB_QP_CREATE_MANAGED_SEND)
+ MLX5_SET(qpc, qpc, cd_slave_send, 1);
+ if (qp->flags_en & MLX5_QP_FLAG_SCATTER_CQE)
+ configure_requester_scat_cqe(dev, qp, init_attr, qpc);
+
+ if (qp->rq.wqe_cnt) {
+ MLX5_SET(qpc, qpc, log_rq_stride, qp->rq.wqe_shift - 4);
+ MLX5_SET(qpc, qpc, log_rq_size, ilog2(qp->rq.wqe_cnt));
+ }
+
+ if (qp->flags_en & MLX5_QP_FLAG_DCI_STREAM) {
+ MLX5_SET(qpc, qpc, log_num_dci_stream_channels,
+ ucmd->dci_streams.log_num_concurent);
+ MLX5_SET(qpc, qpc, log_num_dci_errored_streams,
+ ucmd->dci_streams.log_num_errored);
+ }
+
+ MLX5_SET(qpc, qpc, ts_format, ts_format);
+ MLX5_SET(qpc, qpc, rq_type, get_rx_type(qp, init_attr));
+
+ MLX5_SET(qpc, qpc, log_sq_size, ilog2(qp->sq.wqe_cnt));
+
+ /* Set default resources */
+ if (init_attr->srq) {
+ MLX5_SET(qpc, qpc, xrcd, devr->xrcdn0);
+ MLX5_SET(qpc, qpc, srqn_rmpn_xrqn,
+ to_msrq(init_attr->srq)->msrq.srqn);
+ } else {
+ MLX5_SET(qpc, qpc, xrcd, devr->xrcdn1);
+ MLX5_SET(qpc, qpc, srqn_rmpn_xrqn,
+ to_msrq(devr->s1)->msrq.srqn);
+ }
+
+ if (init_attr->send_cq)
+ MLX5_SET(qpc, qpc, cqn_snd,
+ to_mcq(init_attr->send_cq)->mcq.cqn);
+
+ if (init_attr->recv_cq)
+ MLX5_SET(qpc, qpc, cqn_rcv,
+ to_mcq(init_attr->recv_cq)->mcq.cqn);
+
+ MLX5_SET64(qpc, qpc, dbr_addr, qp->db.dma);
+
+ /* 0xffffff means we ask to work with cqe version 0 */
+ if (MLX5_CAP_GEN(mdev, cqe_version) == MLX5_CQE_VERSION_V1)
+ MLX5_SET(qpc, qpc, user_index, uidx);
+
+ if (qp->flags & IB_QP_CREATE_PCI_WRITE_END_PADDING) {
+ MLX5_SET(qpc, qpc, end_padding_mode,
+ MLX5_WQ_END_PAD_MODE_ALIGN);
+ /* Special case to clean flag */
+ qp->flags &= ~IB_QP_CREATE_PCI_WRITE_END_PADDING;
+ }
+
+ err = mlx5_qpc_create_qp(dev, &base->mqp, in, inlen, out);
+
+ kvfree(in);
+ if (err)
+ goto err_create;
+
+ base->container_mibqp = qp;
+ base->mqp.event = mlx5_ib_qp_event;
+ if (MLX5_CAP_GEN(mdev, ece_support))
+ params->resp.ece_options = MLX5_GET(create_qp_out, out, ece);
+
+ get_cqs(qp->type, init_attr->send_cq, init_attr->recv_cq,
+ &send_cq, &recv_cq);
+ spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
+ mlx5_ib_lock_cqs(send_cq, recv_cq);
+ /* Maintain device to QPs access, needed for further handling via reset
+ * flow
+ */
+ list_add_tail(&qp->qps_list, &dev->qp_list);
+ /* Maintain CQ to QPs access, needed for further handling via reset flow
+ */
+ if (send_cq)
+ list_add_tail(&qp->cq_send_list, &send_cq->list_send_qp);
+ if (recv_cq)
+ list_add_tail(&qp->cq_recv_list, &recv_cq->list_recv_qp);
+ mlx5_ib_unlock_cqs(send_cq, recv_cq);
+ spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
+
+ return 0;
+
+err_create:
+ destroy_qp(dev, qp, base, udata);
+ return err;
+}
+
static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
struct mlx5_ib_qp *qp,
struct mlx5_create_qp_params *params)
@@ -2512,7 +2670,6 @@ static int create_dct(struct mlx5_ib_dev *dev, struct ib_pd *pd,
}
qp->state = IB_QPS_RESET;
- rdma_restrack_no_track(&qp->ibqp.res);
return 0;
}
@@ -2653,6 +2810,9 @@ static int process_vendor_flags(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
process_vendor_flag(dev, &flags, MLX5_QP_FLAG_TYPE_DCI, true, qp);
process_vendor_flag(dev, &flags, MLX5_QP_FLAG_TYPE_DCT, true, qp);
+ process_vendor_flag(dev, &flags, MLX5_QP_FLAG_DCI_STREAM,
+ MLX5_CAP_GEN(mdev, log_max_dci_stream_channels),
+ qp);
process_vendor_flag(dev, &flags, MLX5_QP_FLAG_SIGNATURE, true, qp);
process_vendor_flag(dev, &flags, MLX5_QP_FLAG_SCATTER_CQE,
@@ -2847,6 +3007,10 @@ static int create_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
switch (qp->type) {
case MLX5_IB_QPT_DCT:
err = create_dct(dev, pd, qp, params);
+ rdma_restrack_no_track(&qp->ibqp.res);
+ break;
+ case MLX5_IB_QPT_DCI:
+ err = create_dci(dev, pd, qp, params);
break;
case IB_QPT_XRC_TGT:
err = create_xrc_tgt_qp(dev, qp, params);
@@ -2854,6 +3018,10 @@ static int create_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
case IB_QPT_GSI:
err = mlx5_ib_create_gsi(pd, qp, params->attr);
break;
+ case MLX5_IB_QPT_HW_GSI:
+ case MLX5_IB_QPT_REG_UMR:
+ rdma_restrack_no_track(&qp->ibqp.res);
+ fallthrough;
default:
if (params->udata)
err = create_user_qp(dev, pd, qp, params);
@@ -2942,7 +3110,6 @@ static int mlx5_ib_destroy_dct(struct mlx5_ib_qp *mqp)
}
kfree(mqp->dct.in);
- kfree(mqp);
return 0;
}
@@ -2980,25 +3147,23 @@ static int check_ucmd_data(struct mlx5_ib_dev *dev,
return ret ? 0 : -EINVAL;
}
-struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
- struct ib_udata *udata)
+int mlx5_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
+ struct ib_udata *udata)
{
struct mlx5_create_qp_params params = {};
- struct mlx5_ib_dev *dev;
- struct mlx5_ib_qp *qp;
+ struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
+ struct mlx5_ib_qp *qp = to_mqp(ibqp);
+ struct ib_pd *pd = ibqp->pd;
enum ib_qp_type type;
int err;
- dev = pd ? to_mdev(pd->device) :
- to_mdev(to_mxrcd(attr->xrcd)->ibxrcd.device);
-
err = check_qp_type(dev, attr, &type);
if (err)
- return ERR_PTR(err);
+ return err;
err = check_valid_flow(dev, pd, attr, udata);
if (err)
- return ERR_PTR(err);
+ return err;
params.udata = udata;
params.uidx = MLX5_IB_DEFAULT_UIDX;
@@ -3008,49 +3173,43 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
if (udata) {
err = process_udata_size(dev, &params);
if (err)
- return ERR_PTR(err);
+ return err;
err = check_ucmd_data(dev, &params);
if (err)
- return ERR_PTR(err);
+ return err;
params.ucmd = kzalloc(params.ucmd_size, GFP_KERNEL);
if (!params.ucmd)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
err = ib_copy_from_udata(params.ucmd, udata, params.inlen);
if (err)
goto free_ucmd;
}
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp) {
- err = -ENOMEM;
- goto free_ucmd;
- }
-
mutex_init(&qp->mutex);
qp->type = type;
if (udata) {
err = process_vendor_flags(dev, qp, params.ucmd, attr);
if (err)
- goto free_qp;
+ goto free_ucmd;
err = get_qp_uidx(qp, &params);
if (err)
- goto free_qp;
+ goto free_ucmd;
}
err = process_create_flags(dev, qp, attr);
if (err)
- goto free_qp;
+ goto free_ucmd;
err = check_qp_attr(dev, qp, attr);
if (err)
- goto free_qp;
+ goto free_ucmd;
err = create_qp(dev, pd, qp, &params);
if (err)
- goto free_qp;
+ goto free_ucmd;
kfree(params.ucmd);
params.ucmd = NULL;
@@ -3065,7 +3224,7 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
if (err)
goto destroy_qp;
- return &qp->ibqp;
+ return 0;
destroy_qp:
switch (qp->type) {
@@ -3076,22 +3235,12 @@ destroy_qp:
mlx5_ib_destroy_gsi(qp);
break;
default:
- /*
- * These lines below are temp solution till QP allocation
- * will be moved to be under IB/core responsiblity.
- */
- qp->ibqp.send_cq = attr->send_cq;
- qp->ibqp.recv_cq = attr->recv_cq;
- qp->ibqp.pd = pd;
destroy_qp_common(dev, qp, udata);
}
- qp = NULL;
-free_qp:
- kfree(qp);
free_ucmd:
kfree(params.ucmd);
- return ERR_PTR(err);
+ return err;
}
int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
@@ -3106,9 +3255,6 @@ int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
return mlx5_ib_destroy_dct(mqp);
destroy_qp_common(dev, mqp, udata);
-
- kfree(mqp);
-
return 0;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 2cdf686203c1..97287c544da8 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -617,9 +617,9 @@ static void mthca_free_eq(struct mthca_dev *dev,
mthca_free_mr(dev, &eq->mr);
for (i = 0; i < npages; ++i)
- pci_free_consistent(dev->pdev, PAGE_SIZE,
- eq->page_list[i].buf,
- dma_unmap_addr(&eq->page_list[i], mapping));
+ dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+ eq->page_list[i].buf,
+ dma_unmap_addr(&eq->page_list[i], mapping));
kfree(eq->page_list);
mthca_free_mailbox(dev, mailbox);
@@ -739,17 +739,18 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
dev->eq_table.icm_page = alloc_page(GFP_HIGHUSER);
if (!dev->eq_table.icm_page)
return -ENOMEM;
- dev->eq_table.icm_dma = pci_map_page(dev->pdev, dev->eq_table.icm_page, 0,
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(dev->pdev, dev->eq_table.icm_dma)) {
+ dev->eq_table.icm_dma =
+ dma_map_page(&dev->pdev->dev, dev->eq_table.icm_page, 0,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&dev->pdev->dev, dev->eq_table.icm_dma)) {
__free_page(dev->eq_table.icm_page);
return -ENOMEM;
}
ret = mthca_MAP_ICM_page(dev, dev->eq_table.icm_dma, icm_virt);
if (ret) {
- pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_page(&dev->pdev->dev, dev->eq_table.icm_dma,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
__free_page(dev->eq_table.icm_page);
}
@@ -759,8 +760,8 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
void mthca_unmap_eq_icm(struct mthca_dev *dev)
{
mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1);
- pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_page(&dev->pdev->dev, dev->eq_table.icm_dma, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
__free_page(dev->eq_table.icm_page);
}
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index fe9654a7af71..f507c4cd46d3 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -937,26 +937,15 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type)
pci_set_master(pdev);
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (err) {
dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n");
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (err) {
dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n");
goto err_free_res;
}
}
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (err) {
- dev_warn(&pdev->dev, "Warning: couldn't set 64-bit "
- "consistent PCI DMA mask.\n");
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (err) {
- dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, "
- "aborting.\n");
- goto err_free_res;
- }
- }
/* We can handle large RDMA requests, so allow larger segments. */
dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index fa808582b08b..f2734a5c5f26 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -66,8 +66,8 @@ static void mthca_free_icm_pages(struct mthca_dev *dev, struct mthca_icm_chunk *
int i;
if (chunk->nsg > 0)
- pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_sg(&dev->pdev->dev, chunk->mem, chunk->npages,
+ DMA_BIDIRECTIONAL);
for (i = 0; i < chunk->npages; ++i)
__free_pages(sg_page(&chunk->mem[i]),
@@ -184,9 +184,10 @@ struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
if (coherent)
++chunk->nsg;
else if (chunk->npages == MTHCA_ICM_CHUNK_LEN) {
- chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
- chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
+ chunk->nsg =
+ dma_map_sg(&dev->pdev->dev, chunk->mem,
+ chunk->npages,
+ DMA_BIDIRECTIONAL);
if (chunk->nsg <= 0)
goto fail;
@@ -204,9 +205,8 @@ struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
}
if (!coherent && chunk) {
- chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
- chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
+ chunk->nsg = dma_map_sg(&dev->pdev->dev, chunk->mem,
+ chunk->npages, DMA_BIDIRECTIONAL);
if (chunk->nsg <= 0)
goto fail;
@@ -480,7 +480,8 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
sg_set_page(&db_tab->page[i].mem, pages[0], MTHCA_ICM_PAGE_SIZE,
uaddr & ~PAGE_MASK);
- ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
+ ret = dma_map_sg(&dev->pdev->dev, &db_tab->page[i].mem, 1,
+ DMA_TO_DEVICE);
if (ret < 0) {
unpin_user_page(pages[0]);
goto out;
@@ -489,7 +490,8 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
ret = mthca_MAP_ICM_page(dev, sg_dma_address(&db_tab->page[i].mem),
mthca_uarc_virt(dev, uar, i));
if (ret) {
- pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
+ dma_unmap_sg(&dev->pdev->dev, &db_tab->page[i].mem, 1,
+ DMA_TO_DEVICE);
unpin_user_page(sg_page(&db_tab->page[i].mem));
goto out;
}
@@ -555,7 +557,8 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
for (i = 0; i < dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; ++i) {
if (db_tab->page[i].uvirt) {
mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1);
- pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
+ dma_unmap_sg(&dev->pdev->dev, &db_tab->page[i].mem, 1,
+ DMA_TO_DEVICE);
unpin_user_page(sg_page(&db_tab->page[i].mem));
}
}
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index adf4fcf0fee4..ceee23ebc0f2 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -459,52 +459,45 @@ static int mthca_destroy_srq(struct ib_srq *srq, struct ib_udata *udata)
return 0;
}
-static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata)
+static int mthca_create_qp(struct ib_qp *ibqp,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
{
struct mthca_ucontext *context = rdma_udata_to_drv_context(
udata, struct mthca_ucontext, ibucontext);
struct mthca_create_qp ucmd;
- struct mthca_qp *qp;
+ struct mthca_qp *qp = to_mqp(ibqp);
+ struct mthca_dev *dev = to_mdev(ibqp->device);
int err;
if (init_attr->create_flags)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
switch (init_attr->qp_type) {
case IB_QPT_RC:
case IB_QPT_UC:
case IB_QPT_UD:
{
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return ERR_PTR(-ENOMEM);
-
if (udata) {
- if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
- kfree(qp);
- return ERR_PTR(-EFAULT);
- }
+ if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd)))
+ return -EFAULT;
- err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+ err = mthca_map_user_db(dev, &context->uar,
context->db_tab,
- ucmd.sq_db_index, ucmd.sq_db_page);
- if (err) {
- kfree(qp);
- return ERR_PTR(err);
- }
+ ucmd.sq_db_index,
+ ucmd.sq_db_page);
+ if (err)
+ return err;
- err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+ err = mthca_map_user_db(dev, &context->uar,
context->db_tab,
- ucmd.rq_db_index, ucmd.rq_db_page);
+ ucmd.rq_db_index,
+ ucmd.rq_db_page);
if (err) {
- mthca_unmap_user_db(to_mdev(pd->device),
- &context->uar,
+ mthca_unmap_user_db(dev, &context->uar,
context->db_tab,
ucmd.sq_db_index);
- kfree(qp);
- return ERR_PTR(err);
+ return err;
}
qp->mr.ibmr.lkey = ucmd.lkey;
@@ -512,20 +505,16 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
qp->rq.db_index = ucmd.rq_db_index;
}
- err = mthca_alloc_qp(to_mdev(pd->device), to_mpd(pd),
+ err = mthca_alloc_qp(dev, to_mpd(ibqp->pd),
to_mcq(init_attr->send_cq),
to_mcq(init_attr->recv_cq),
init_attr->qp_type, init_attr->sq_sig_type,
&init_attr->cap, qp, udata);
if (err && udata) {
- mthca_unmap_user_db(to_mdev(pd->device),
- &context->uar,
- context->db_tab,
+ mthca_unmap_user_db(dev, &context->uar, context->db_tab,
ucmd.sq_db_index);
- mthca_unmap_user_db(to_mdev(pd->device),
- &context->uar,
- context->db_tab,
+ mthca_unmap_user_db(dev, &context->uar, context->db_tab,
ucmd.rq_db_index);
}
@@ -535,34 +524,28 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
case IB_QPT_SMI:
case IB_QPT_GSI:
{
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return ERR_PTR(-ENOMEM);
qp->sqp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL);
- if (!qp->sqp) {
- kfree(qp);
- return ERR_PTR(-ENOMEM);
- }
+ if (!qp->sqp)
+ return -ENOMEM;
qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1;
- err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd),
+ err = mthca_alloc_sqp(dev, to_mpd(ibqp->pd),
to_mcq(init_attr->send_cq),
to_mcq(init_attr->recv_cq),
init_attr->sq_sig_type, &init_attr->cap,
- qp->ibqp.qp_num, init_attr->port_num,
- qp, udata);
+ qp->ibqp.qp_num, init_attr->port_num, qp,
+ udata);
break;
}
default:
/* Don't support raw QPs */
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
}
if (err) {
kfree(qp->sqp);
- kfree(qp);
- return ERR_PTR(err);
+ return err;
}
init_attr->cap.max_send_wr = qp->sq.max;
@@ -571,7 +554,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
init_attr->cap.max_recv_sge = qp->rq.max_gs;
init_attr->cap.max_inline_data = qp->max_inline_data;
- return &qp->ibqp;
+ return 0;
}
static int mthca_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
@@ -594,7 +577,6 @@ static int mthca_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
}
mthca_free_qp(to_mdev(qp->device), to_mqp(qp));
kfree(to_mqp(qp)->sqp);
- kfree(to_mqp(qp));
return 0;
}
@@ -1121,6 +1103,7 @@ static const struct ib_device_ops mthca_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, mthca_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, mthca_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, mthca_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, mthca_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_ucontext, mthca_ucontext, ibucontext),
};
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index f329db0c591f..7abf6cf1e937 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -185,6 +185,7 @@ static const struct ib_device_ops ocrdma_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, ocrdma_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, ocrdma_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, ocrdma_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, ocrdma_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_ucontext, ocrdma_ucontext, ibucontext),
};
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 58619ce64d0d..735123d0e9ec 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -1288,19 +1288,19 @@ static void ocrdma_store_gsi_qp_cq(struct ocrdma_dev *dev,
}
}
-struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
- struct ib_qp_init_attr *attrs,
- struct ib_udata *udata)
+int ocrdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
+ struct ib_udata *udata)
{
int status;
+ struct ib_pd *ibpd = ibqp->pd;
struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
- struct ocrdma_qp *qp;
- struct ocrdma_dev *dev = get_ocrdma_dev(ibpd->device);
+ struct ocrdma_qp *qp = get_ocrdma_qp(ibqp);
+ struct ocrdma_dev *dev = get_ocrdma_dev(ibqp->device);
struct ocrdma_create_qp_ureq ureq;
u16 dpp_credit_lmt, dpp_offset;
if (attrs->create_flags)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
status = ocrdma_check_qp_params(ibpd, dev, attrs, udata);
if (status)
@@ -1309,12 +1309,7 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
memset(&ureq, 0, sizeof(ureq));
if (udata) {
if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
- return ERR_PTR(-EFAULT);
- }
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp) {
- status = -ENOMEM;
- goto gen_err;
+ return -EFAULT;
}
ocrdma_set_qp_init_params(qp, pd, attrs);
if (udata == NULL)
@@ -1349,7 +1344,7 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
ocrdma_store_gsi_qp_cq(dev, attrs);
qp->ibqp.qp_num = qp->id;
mutex_unlock(&dev->dev_lock);
- return &qp->ibqp;
+ return 0;
cpy_err:
ocrdma_del_qpn_map(dev, qp);
@@ -1359,10 +1354,9 @@ mbx_err:
mutex_unlock(&dev->dev_lock);
kfree(qp->wqe_wr_id_tbl);
kfree(qp->rqe_wr_id_tbl);
- kfree(qp);
pr_err("%s(%d) error=%d\n", __func__, dev->id, status);
gen_err:
- return ERR_PTR(status);
+ return status;
}
int _ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
@@ -1731,7 +1725,6 @@ int ocrdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
kfree(qp->wqe_wr_id_tbl);
kfree(qp->rqe_wr_id_tbl);
- kfree(qp);
return 0;
}
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
index b1c5fad81603..b73d742a520c 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
@@ -75,9 +75,8 @@ int ocrdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
int ocrdma_resize_cq(struct ib_cq *, int cqe, struct ib_udata *);
int ocrdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
-struct ib_qp *ocrdma_create_qp(struct ib_pd *,
- struct ib_qp_init_attr *attrs,
- struct ib_udata *);
+int ocrdma_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
+ struct ib_udata *udata);
int _ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
int attr_mask);
int ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
index de98e0604f91..755930be01b8 100644
--- a/drivers/infiniband/hw/qedr/main.c
+++ b/drivers/infiniband/hw/qedr/main.c
@@ -233,6 +233,7 @@ static const struct ib_device_ops qedr_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, qedr_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, qedr_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, qedr_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, qedr_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_srq, qedr_srq, ibsrq),
INIT_RDMA_OBJ_SIZE(ib_xrcd, qedr_xrcd, ibxrcd),
INIT_RDMA_OBJ_SIZE(ib_ucontext, qedr_ucontext, ibucontext),
diff --git a/drivers/infiniband/hw/qedr/qedr_roce_cm.c b/drivers/infiniband/hw/qedr/qedr_roce_cm.c
index 13e5e6bbec99..05307c1488b8 100644
--- a/drivers/infiniband/hw/qedr/qedr_roce_cm.c
+++ b/drivers/infiniband/hw/qedr/qedr_roce_cm.c
@@ -319,20 +319,19 @@ err1:
return rc;
}
-struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
- struct ib_qp_init_attr *attrs,
- struct qedr_qp *qp)
+int qedr_create_gsi_qp(struct qedr_dev *dev, struct ib_qp_init_attr *attrs,
+ struct qedr_qp *qp)
{
int rc;
rc = qedr_check_gsi_qp_attrs(dev, attrs);
if (rc)
- return ERR_PTR(rc);
+ return rc;
rc = qedr_ll2_start(dev, attrs, qp);
if (rc) {
DP_ERR(dev, "create gsi qp: failed on ll2 start. rc=%d\n", rc);
- return ERR_PTR(rc);
+ return rc;
}
/* create QP */
@@ -359,7 +358,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
DP_DEBUG(dev, QEDR_MSG_GSI, "created GSI QP %p\n", qp);
- return &qp->ibqp;
+ return 0;
err:
kfree(qp->rqe_wr_id);
@@ -368,7 +367,7 @@ err:
if (rc)
DP_ERR(dev, "create gsi qp: failed destroy on create\n");
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
}
int qedr_destroy_gsi_qp(struct qedr_dev *dev)
diff --git a/drivers/infiniband/hw/qedr/qedr_roce_cm.h b/drivers/infiniband/hw/qedr/qedr_roce_cm.h
index d46dcd3f6424..f3432f035ec6 100644
--- a/drivers/infiniband/hw/qedr/qedr_roce_cm.h
+++ b/drivers/infiniband/hw/qedr/qedr_roce_cm.h
@@ -50,9 +50,8 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
const struct ib_recv_wr **bad_wr);
int qedr_gsi_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
const struct ib_send_wr **bad_wr);
-struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
- struct ib_qp_init_attr *attrs,
- struct qedr_qp *qp);
+int qedr_create_gsi_qp(struct qedr_dev *dev, struct ib_qp_init_attr *attrs,
+ struct qedr_qp *qp);
void qedr_store_gsi_qp_cq(struct qedr_dev *dev,
struct qedr_qp *qp, struct ib_qp_init_attr *attrs);
int qedr_destroy_gsi_qp(struct qedr_dev *dev);
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index fdc47ef7d861..3fbf172dbbef 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -1339,6 +1339,15 @@ static int qedr_copy_qp_uresp(struct qedr_dev *dev,
return rc;
}
+static void qedr_reset_qp_hwq_info(struct qedr_qp_hwq_info *qph)
+{
+ qed_chain_reset(&qph->pbl);
+ qph->prod = 0;
+ qph->cons = 0;
+ qph->wqe_cons = 0;
+ qph->db_data.data.value = cpu_to_le16(0);
+}
+
static void qedr_set_common_qp_params(struct qedr_dev *dev,
struct qedr_qp *qp,
struct qedr_pd *pd,
@@ -1354,9 +1363,13 @@ static void qedr_set_common_qp_params(struct qedr_dev *dev,
qp->qp_type = attrs->qp_type;
qp->max_inline_data = attrs->cap.max_inline_data;
qp->state = QED_ROCE_QP_STATE_RESET;
+
+ qp->prev_wqe_size = 0;
+
qp->signaled = (attrs->sq_sig_type == IB_SIGNAL_ALL_WR) ? true : false;
qp->dev = dev;
if (qedr_qp_has_sq(qp)) {
+ qedr_reset_qp_hwq_info(&qp->sq);
qp->sq.max_sges = attrs->cap.max_send_sge;
qp->sq_cq = get_qedr_cq(attrs->send_cq);
DP_DEBUG(dev, QEDR_MSG_QP,
@@ -1368,6 +1381,7 @@ static void qedr_set_common_qp_params(struct qedr_dev *dev,
qp->srq = get_qedr_srq(attrs->srq);
if (qedr_qp_has_rq(qp)) {
+ qedr_reset_qp_hwq_info(&qp->rq);
qp->rq_cq = get_qedr_cq(attrs->recv_cq);
qp->rq.max_sges = attrs->cap.max_recv_sge;
DP_DEBUG(dev, QEDR_MSG_QP,
@@ -1481,7 +1495,7 @@ static int qedr_init_srq_user_params(struct ib_udata *udata,
return PTR_ERR(srq->prod_umem);
}
- sg = srq->prod_umem->sg_head.sgl;
+ sg = srq->prod_umem->sgt_append.sgt.sgl;
srq->hw_srq.phy_prod_pair_addr = sg_dma_address(sg);
return 0;
@@ -2239,34 +2253,30 @@ static int qedr_free_qp_resources(struct qedr_dev *dev, struct qedr_qp *qp,
return 0;
}
-struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
- struct ib_qp_init_attr *attrs,
- struct ib_udata *udata)
+int qedr_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
+ struct ib_udata *udata)
{
struct qedr_xrcd *xrcd = NULL;
- struct qedr_pd *pd = NULL;
- struct qedr_dev *dev;
- struct qedr_qp *qp;
- struct ib_qp *ibqp;
+ struct ib_pd *ibpd = ibqp->pd;
+ struct qedr_pd *pd = get_qedr_pd(ibpd);
+ struct qedr_dev *dev = get_qedr_dev(ibqp->device);
+ struct qedr_qp *qp = get_qedr_qp(ibqp);
int rc = 0;
if (attrs->create_flags)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
- if (attrs->qp_type == IB_QPT_XRC_TGT) {
+ if (attrs->qp_type == IB_QPT_XRC_TGT)
xrcd = get_qedr_xrcd(attrs->xrcd);
- dev = get_qedr_dev(xrcd->ibxrcd.device);
- } else {
+ else
pd = get_qedr_pd(ibpd);
- dev = get_qedr_dev(ibpd->device);
- }
DP_DEBUG(dev, QEDR_MSG_QP, "create qp: called from %s, pd=%p\n",
udata ? "user library" : "kernel", pd);
rc = qedr_check_qp_attrs(ibpd, dev, attrs, udata);
if (rc)
- return ERR_PTR(rc);
+ return rc;
DP_DEBUG(dev, QEDR_MSG_QP,
"create qp: called from %s, event_handler=%p, eepd=%p sq_cq=%p, sq_icid=%d, rq_cq=%p, rq_icid=%d\n",
@@ -2276,20 +2286,10 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
get_qedr_cq(attrs->recv_cq),
attrs->recv_cq ? get_qedr_cq(attrs->recv_cq)->icid : 0);
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp) {
- DP_ERR(dev, "create qp: failed allocating memory\n");
- return ERR_PTR(-ENOMEM);
- }
-
qedr_set_common_qp_params(dev, qp, pd, attrs);
- if (attrs->qp_type == IB_QPT_GSI) {
- ibqp = qedr_create_gsi_qp(dev, attrs, qp);
- if (IS_ERR(ibqp))
- kfree(qp);
- return ibqp;
- }
+ if (attrs->qp_type == IB_QPT_GSI)
+ return qedr_create_gsi_qp(dev, attrs, qp);
if (udata || xrcd)
rc = qedr_create_user_qp(dev, qp, ibpd, udata, attrs);
@@ -2297,7 +2297,7 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
rc = qedr_create_kernel_qp(dev, qp, ibpd, attrs);
if (rc)
- goto out_free_qp;
+ return rc;
qp->ibqp.qp_num = qp->qp_id;
@@ -2307,14 +2307,11 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
goto out_free_qp_resources;
}
- return &qp->ibqp;
+ return 0;
out_free_qp_resources:
qedr_free_qp_resources(dev, qp, udata);
-out_free_qp:
- kfree(qp);
-
- return ERR_PTR(-EFAULT);
+ return -EFAULT;
}
static enum ib_qp_state qedr_get_ibqp_state(enum qed_roce_qp_state qp_state)
@@ -2359,15 +2356,6 @@ static enum qed_roce_qp_state qedr_get_state_from_ibqp(
}
}
-static void qedr_reset_qp_hwq_info(struct qedr_qp_hwq_info *qph)
-{
- qed_chain_reset(&qph->pbl);
- qph->prod = 0;
- qph->cons = 0;
- qph->wqe_cons = 0;
- qph->db_data.data.value = cpu_to_le16(0);
-}
-
static int qedr_update_qp_state(struct qedr_dev *dev,
struct qedr_qp *qp,
enum qed_roce_qp_state cur_state,
@@ -2382,9 +2370,6 @@ static int qedr_update_qp_state(struct qedr_dev *dev,
case QED_ROCE_QP_STATE_RESET:
switch (new_state) {
case QED_ROCE_QP_STATE_INIT:
- qp->prev_wqe_size = 0;
- qedr_reset_qp_hwq_info(&qp->sq);
- qedr_reset_qp_hwq_info(&qp->rq);
break;
default:
status = -EINVAL;
@@ -2874,8 +2859,6 @@ int qedr_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
if (rdma_protocol_iwarp(&dev->ibdev, 1))
qedr_iw_qp_rem_ref(&qp->ibqp);
- else
- kfree(qp);
return 0;
}
@@ -2996,7 +2979,11 @@ struct ib_mr *qedr_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
rc = dev->ops->rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
if (rc) {
- DP_ERR(dev, "roce alloc tid returned an error %d\n", rc);
+ if (rc == -EINVAL)
+ DP_ERR(dev, "Out of MR resources\n");
+ else
+ DP_ERR(dev, "roce alloc tid returned error %d\n", rc);
+
goto err1;
}
@@ -3091,7 +3078,11 @@ static struct qedr_mr *__qedr_alloc_mr(struct ib_pd *ibpd,
rc = dev->ops->rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
if (rc) {
- DP_ERR(dev, "roce alloc tid returned an error %d\n", rc);
+ if (rc == -EINVAL)
+ DP_ERR(dev, "Out of MR resources\n");
+ else
+ DP_ERR(dev, "roce alloc tid returned error %d\n", rc);
+
goto err0;
}
@@ -3221,7 +3212,11 @@ struct ib_mr *qedr_get_dma_mr(struct ib_pd *ibpd, int acc)
rc = dev->ops->rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
if (rc) {
- DP_ERR(dev, "roce alloc tid returned an error %d\n", rc);
+ if (rc == -EINVAL)
+ DP_ERR(dev, "Out of MR resources\n");
+ else
+ DP_ERR(dev, "roce alloc tid returned error %d\n", rc);
+
goto err1;
}
@@ -3915,12 +3910,6 @@ int qedr_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
spin_lock_irqsave(&qp->q_lock, flags);
- if (qp->state == QED_ROCE_QP_STATE_RESET) {
- spin_unlock_irqrestore(&qp->q_lock, flags);
- *bad_wr = wr;
- return -EINVAL;
- }
-
while (wr) {
int i;
diff --git a/drivers/infiniband/hw/qedr/verbs.h b/drivers/infiniband/hw/qedr/verbs.h
index 34ad47515861..031687dafc61 100644
--- a/drivers/infiniband/hw/qedr/verbs.h
+++ b/drivers/infiniband/hw/qedr/verbs.h
@@ -56,8 +56,8 @@ int qedr_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
int qedr_resize_cq(struct ib_cq *, int cqe, struct ib_udata *);
int qedr_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
int qedr_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
-struct ib_qp *qedr_create_qp(struct ib_pd *, struct ib_qp_init_attr *attrs,
- struct ib_udata *);
+int qedr_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
+ struct ib_udata *udata);
int qedr_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
int qedr_query_qp(struct ib_qp *, struct ib_qp_attr *qp_attr,
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index c60e79d214a1..63854f4b6524 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -429,8 +429,8 @@ cleanup:
dd->f_put_tid(dd, &tidbase[tid],
RCVHQ_RCV_TYPE_EXPECTED,
dd->tidinvalid);
- pci_unmap_page(dd->pcidev, phys, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
+ dma_unmap_page(&dd->pcidev->dev, phys,
+ PAGE_SIZE, DMA_FROM_DEVICE);
dd->pageshadow[ctxttid + tid] = NULL;
}
}
@@ -544,8 +544,8 @@ static int qib_tid_free(struct qib_ctxtdata *rcd, unsigned subctxt,
*/
dd->f_put_tid(dd, &tidbase[tid],
RCVHQ_RCV_TYPE_EXPECTED, dd->tidinvalid);
- pci_unmap_page(dd->pcidev, phys, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
+ dma_unmap_page(&dd->pcidev->dev, phys, PAGE_SIZE,
+ DMA_FROM_DEVICE);
qib_release_user_pages(&p, 1);
}
}
@@ -1781,8 +1781,8 @@ static void unlock_expected_tids(struct qib_ctxtdata *rcd)
phys = dd->physshadow[i];
dd->physshadow[i] = dd->tidinvalid;
dd->pageshadow[i] = NULL;
- pci_unmap_page(dd->pcidev, phys, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
+ dma_unmap_page(&dd->pcidev->dev, phys, PAGE_SIZE,
+ DMA_FROM_DEVICE);
qib_release_user_pages(&p, 1);
cnt++;
}
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index b5a78576c48b..d1a72e89e297 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1335,8 +1335,8 @@ static void cleanup_device_data(struct qib_devdata *dd)
for (i = ctxt_tidbase; i < maxtid; i++) {
if (!tmpp[i])
continue;
- pci_unmap_page(dd->pcidev, tmpd[i],
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ dma_unmap_page(&dd->pcidev->dev, tmpd[i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
qib_release_user_pages(&tmpp[i], 1);
tmpp[i] = NULL;
}
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
index 5d6cf7427431..f4b5f05058e4 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -60,15 +60,15 @@ int qib_map_page(struct pci_dev *hwdev, struct page *page, dma_addr_t *daddr)
{
dma_addr_t phys;
- phys = pci_map_page(hwdev, page, 0, PAGE_SIZE, PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(hwdev, phys))
+ phys = dma_map_page(&hwdev->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(&hwdev->dev, phys))
return -ENOMEM;
if (!phys) {
- pci_unmap_page(hwdev, phys, PAGE_SIZE, PCI_DMA_FROMDEVICE);
- phys = pci_map_page(hwdev, page, 0, PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(hwdev, phys))
+ dma_unmap_page(&hwdev->dev, phys, PAGE_SIZE, DMA_FROM_DEVICE);
+ phys = dma_map_page(&hwdev->dev, page, 0, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(&hwdev->dev, phys))
return -ENOMEM;
/*
* FIXME: If we get 0 again, we should keep this page,
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
index c49f9e19d926..228e9a36dad0 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
@@ -360,6 +360,7 @@ static const struct ib_device_ops usnic_dev_ops = {
.reg_user_mr = usnic_ib_reg_mr,
INIT_RDMA_OBJ_SIZE(ib_pd, usnic_ib_pd, ibpd),
INIT_RDMA_OBJ_SIZE(ib_cq, usnic_ib_cq, ibcq),
+ INIT_RDMA_OBJ_SIZE(ib_qp, usnic_ib_qp_grp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_ucontext, usnic_ib_ucontext, ibucontext),
};
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
index 0cdb156e165e..3b60fa9cb58d 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
@@ -665,13 +665,12 @@ static int qp_grp_id_from_flow(struct usnic_ib_qp_grp_flow *qp_flow,
return 0;
}
-struct usnic_ib_qp_grp *
-usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
- struct usnic_ib_pd *pd,
- struct usnic_vnic_res_spec *res_spec,
- struct usnic_transport_spec *transport_spec)
+int usnic_ib_qp_grp_create(struct usnic_ib_qp_grp *qp_grp,
+ struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
+ struct usnic_ib_pd *pd,
+ struct usnic_vnic_res_spec *res_spec,
+ struct usnic_transport_spec *transport_spec)
{
- struct usnic_ib_qp_grp *qp_grp;
int err;
enum usnic_transport_type transport = transport_spec->trans_type;
struct usnic_ib_qp_grp_flow *qp_flow;
@@ -684,20 +683,15 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
usnic_err("Spec does not meet minimum req for transport %d\n",
transport);
log_spec(res_spec);
- return ERR_PTR(err);
+ return err;
}
- qp_grp = kzalloc(sizeof(*qp_grp), GFP_ATOMIC);
- if (!qp_grp)
- return NULL;
-
qp_grp->res_chunk_list = alloc_res_chunk_list(vf->vnic, res_spec,
qp_grp);
- if (IS_ERR_OR_NULL(qp_grp->res_chunk_list)) {
- err = qp_grp->res_chunk_list ?
- PTR_ERR(qp_grp->res_chunk_list) : -ENOMEM;
- goto out_free_qp_grp;
- }
+ if (IS_ERR_OR_NULL(qp_grp->res_chunk_list))
+ return qp_grp->res_chunk_list ?
+ PTR_ERR(qp_grp->res_chunk_list) :
+ -ENOMEM;
err = qp_grp_and_vf_bind(vf, pd, qp_grp);
if (err)
@@ -724,7 +718,7 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
usnic_ib_sysfs_qpn_add(qp_grp);
- return qp_grp;
+ return 0;
out_release_flow:
release_and_remove_flow(qp_flow);
@@ -732,10 +726,7 @@ out_qp_grp_vf_unbind:
qp_grp_and_vf_unbind(qp_grp);
out_free_res:
free_qp_grp_res(qp_grp->res_chunk_list);
-out_free_qp_grp:
- kfree(qp_grp);
-
- return ERR_PTR(err);
+ return err;
}
void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
@@ -748,7 +739,6 @@ void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
usnic_ib_sysfs_qpn_remove(qp_grp);
qp_grp_and_vf_unbind(qp_grp);
free_qp_grp_res(qp_grp->res_chunk_list);
- kfree(qp_grp);
}
struct usnic_vnic_res_chunk*
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
index a8a2314c9531..62e732be6736 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
@@ -89,11 +89,11 @@ extern const struct usnic_vnic_res_spec min_transport_spec[USNIC_TRANSPORT_MAX];
const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state);
int usnic_ib_qp_grp_dump_hdr(char *buf, int buf_sz);
int usnic_ib_qp_grp_dump_rows(void *obj, char *buf, int buf_sz);
-struct usnic_ib_qp_grp *
-usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
- struct usnic_ib_pd *pd,
- struct usnic_vnic_res_spec *res_spec,
- struct usnic_transport_spec *trans_spec);
+int usnic_ib_qp_grp_create(struct usnic_ib_qp_grp *qp,
+ struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
+ struct usnic_ib_pd *pd,
+ struct usnic_vnic_res_spec *res_spec,
+ struct usnic_transport_spec *trans_spec);
void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp);
int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
enum ib_qp_state new_state,
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 57d210ca855a..06a4e9d4545d 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -168,30 +168,31 @@ static int usnic_ib_fill_create_qp_resp(struct usnic_ib_qp_grp *qp_grp,
return 0;
}
-static struct usnic_ib_qp_grp*
-find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
- struct usnic_ib_pd *pd,
- struct usnic_transport_spec *trans_spec,
- struct usnic_vnic_res_spec *res_spec)
+static int
+find_free_vf_and_create_qp_grp(struct ib_qp *qp,
+ struct usnic_transport_spec *trans_spec,
+ struct usnic_vnic_res_spec *res_spec)
{
+ struct usnic_ib_dev *us_ibdev = to_usdev(qp->device);
+ struct usnic_ib_pd *pd = to_upd(qp->pd);
struct usnic_ib_vf *vf;
struct usnic_vnic *vnic;
- struct usnic_ib_qp_grp *qp_grp;
+ struct usnic_ib_qp_grp *qp_grp = to_uqp_grp(qp);
struct device *dev, **dev_list;
- int i;
+ int i, ret;
BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock));
if (list_empty(&us_ibdev->vf_dev_list)) {
usnic_info("No vfs to allocate\n");
- return NULL;
+ return -ENOMEM;
}
if (usnic_ib_share_vf) {
/* Try to find resouces on a used vf which is in pd */
dev_list = usnic_uiom_get_dev_list(pd->umem_pd);
if (IS_ERR(dev_list))
- return ERR_CAST(dev_list);
+ return PTR_ERR(dev_list);
for (i = 0; dev_list[i]; i++) {
dev = dev_list[i];
vf = dev_get_drvdata(dev);
@@ -202,10 +203,10 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
dev_name(&us_ibdev->ib_dev.dev),
pci_name(usnic_vnic_get_pdev(
vnic)));
- qp_grp = usnic_ib_qp_grp_create(us_ibdev->ufdev,
- vf, pd,
- res_spec,
- trans_spec);
+ ret = usnic_ib_qp_grp_create(qp_grp,
+ us_ibdev->ufdev,
+ vf, pd, res_spec,
+ trans_spec);
spin_unlock(&vf->lock);
goto qp_grp_check;
@@ -223,9 +224,9 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
vnic = vf->vnic;
if (vf->qp_grp_ref_cnt == 0 &&
usnic_vnic_check_room(vnic, res_spec) == 0) {
- qp_grp = usnic_ib_qp_grp_create(us_ibdev->ufdev, vf,
- pd, res_spec,
- trans_spec);
+ ret = usnic_ib_qp_grp_create(qp_grp, us_ibdev->ufdev,
+ vf, pd, res_spec,
+ trans_spec);
spin_unlock(&vf->lock);
goto qp_grp_check;
@@ -235,16 +236,15 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
usnic_info("No free qp grp found on %s\n",
dev_name(&us_ibdev->ib_dev.dev));
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
qp_grp_check:
- if (IS_ERR_OR_NULL(qp_grp)) {
+ if (ret) {
usnic_err("Failed to allocate qp_grp\n");
if (usnic_ib_share_vf)
usnic_uiom_free_dev_list(dev_list);
- return ERR_PTR(qp_grp ? PTR_ERR(qp_grp) : -ENOMEM);
}
- return qp_grp;
+ return ret;
}
static void qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
@@ -458,13 +458,12 @@ int usnic_ib_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata)
return 0;
}
-struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata)
+int usnic_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
{
int err;
struct usnic_ib_dev *us_ibdev;
- struct usnic_ib_qp_grp *qp_grp;
+ struct usnic_ib_qp_grp *qp_grp = to_uqp_grp(ibqp);
struct usnic_ib_ucontext *ucontext = rdma_udata_to_drv_context(
udata, struct usnic_ib_ucontext, ibucontext);
int cq_cnt;
@@ -474,29 +473,29 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
usnic_dbg("\n");
- us_ibdev = to_usdev(pd->device);
+ us_ibdev = to_usdev(ibqp->device);
if (init_attr->create_flags)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
err = ib_copy_from_udata(&cmd, udata, sizeof(cmd));
if (err) {
usnic_err("%s: cannot copy udata for create_qp\n",
dev_name(&us_ibdev->ib_dev.dev));
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
err = create_qp_validate_user_data(cmd);
if (err) {
usnic_err("%s: Failed to validate user data\n",
dev_name(&us_ibdev->ib_dev.dev));
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
if (init_attr->qp_type != IB_QPT_UD) {
usnic_err("%s asked to make a non-UD QP: %d\n",
dev_name(&us_ibdev->ib_dev.dev), init_attr->qp_type);
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
}
trans_spec = cmd.spec;
@@ -504,13 +503,9 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
cq_cnt = (init_attr->send_cq == init_attr->recv_cq) ? 1 : 2;
res_spec = min_transport_spec[trans_spec.trans_type];
usnic_vnic_res_spec_update(&res_spec, USNIC_VNIC_RES_TYPE_CQ, cq_cnt);
- qp_grp = find_free_vf_and_create_qp_grp(us_ibdev, to_upd(pd),
- &trans_spec,
- &res_spec);
- if (IS_ERR_OR_NULL(qp_grp)) {
- err = qp_grp ? PTR_ERR(qp_grp) : -ENOMEM;
+ err = find_free_vf_and_create_qp_grp(ibqp, &trans_spec, &res_spec);
+ if (err)
goto out_release_mutex;
- }
err = usnic_ib_fill_create_qp_resp(qp_grp, udata);
if (err) {
@@ -522,13 +517,13 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
list_add_tail(&qp_grp->link, &ucontext->qp_grp_list);
usnic_ib_log_vf(qp_grp->vf);
mutex_unlock(&us_ibdev->usdev_lock);
- return &qp_grp->ibqp;
+ return 0;
out_release_qp_grp:
qp_grp_destroy(qp_grp);
out_release_mutex:
mutex_unlock(&us_ibdev->usdev_lock);
- return ERR_PTR(err);
+ return err;
}
int usnic_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
index 6b82d0f2d184..6ca9ee0dddbe 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
@@ -50,9 +50,8 @@ int usnic_ib_query_gid(struct ib_device *ibdev, u32 port, int index,
union ib_gid *gid);
int usnic_ib_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
int usnic_ib_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata);
-struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata);
+int usnic_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
int usnic_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
index 8ed8bc24c69f..105f3a155939 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
@@ -185,6 +185,7 @@ static const struct ib_device_ops pvrdma_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, pvrdma_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, pvrdma_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, pvrdma_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, pvrdma_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_ucontext, pvrdma_ucontext, ibucontext),
};
@@ -810,18 +811,10 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
}
/* Enable 64-Bit DMA */
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0) {
+ ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret != 0) {
- dev_err(&pdev->dev,
- "pci_set_consistent_dma_mask failed\n");
- goto err_free_resource;
- }
- } else {
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (ret != 0) {
- dev_err(&pdev->dev,
- "pci_set_dma_mask failed\n");
+ dev_err(&pdev->dev, "dma_set_mask failed\n");
goto err_free_resource;
}
}
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
index 67769b715126..f83cd4a9d992 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
@@ -182,18 +182,17 @@ static int pvrdma_set_sq_size(struct pvrdma_dev *dev, struct ib_qp_cap *req_cap,
/**
* pvrdma_create_qp - create queue pair
- * @pd: protection domain
+ * @ibqp: queue pair
* @init_attr: queue pair attributes
* @udata: user data
*
- * @return: the ib_qp pointer on success, otherwise returns an errno.
+ * @return: the 0 on success, otherwise returns an errno.
*/
-struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata)
+int pvrdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
{
- struct pvrdma_qp *qp = NULL;
- struct pvrdma_dev *dev = to_vdev(pd->device);
+ struct pvrdma_qp *qp = to_vqp(ibqp);
+ struct pvrdma_dev *dev = to_vdev(ibqp->device);
union pvrdma_cmd_req req;
union pvrdma_cmd_resp rsp;
struct pvrdma_cmd_create_qp *cmd = &req.create_qp;
@@ -209,7 +208,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
dev_warn(&dev->pdev->dev,
"invalid create queuepair flags %#x\n",
init_attr->create_flags);
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
}
if (init_attr->qp_type != IB_QPT_RC &&
@@ -217,22 +216,22 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
init_attr->qp_type != IB_QPT_GSI) {
dev_warn(&dev->pdev->dev, "queuepair type %d not supported\n",
init_attr->qp_type);
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
}
if (is_srq && !dev->dsr->caps.max_srq) {
dev_warn(&dev->pdev->dev,
"SRQs not supported by device\n");
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
if (!atomic_add_unless(&dev->num_qps, 1, dev->dsr->caps.max_qp))
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
switch (init_attr->qp_type) {
case IB_QPT_GSI:
if (init_attr->port_num == 0 ||
- init_attr->port_num > pd->device->phys_port_cnt) {
+ init_attr->port_num > ibqp->device->phys_port_cnt) {
dev_warn(&dev->pdev->dev, "invalid queuepair attrs\n");
ret = -EINVAL;
goto err_qp;
@@ -240,12 +239,6 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
fallthrough;
case IB_QPT_RC:
case IB_QPT_UD:
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp) {
- ret = -ENOMEM;
- goto err_qp;
- }
-
spin_lock_init(&qp->sq.lock);
spin_lock_init(&qp->rq.lock);
mutex_init(&qp->mutex);
@@ -275,9 +268,9 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
if (!is_srq) {
/* set qp->sq.wqe_cnt, shift, buf_size.. */
- qp->rumem =
- ib_umem_get(pd->device, ucmd.rbuf_addr,
- ucmd.rbuf_size, 0);
+ qp->rumem = ib_umem_get(ibqp->device,
+ ucmd.rbuf_addr,
+ ucmd.rbuf_size, 0);
if (IS_ERR(qp->rumem)) {
ret = PTR_ERR(qp->rumem);
goto err_qp;
@@ -288,7 +281,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
qp->srq = to_vsrq(init_attr->srq);
}
- qp->sumem = ib_umem_get(pd->device, ucmd.sbuf_addr,
+ qp->sumem = ib_umem_get(ibqp->device, ucmd.sbuf_addr,
ucmd.sbuf_size, 0);
if (IS_ERR(qp->sumem)) {
if (!is_srq)
@@ -306,12 +299,12 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
qp->npages_recv = 0;
qp->npages = qp->npages_send + qp->npages_recv;
} else {
- ret = pvrdma_set_sq_size(to_vdev(pd->device),
+ ret = pvrdma_set_sq_size(to_vdev(ibqp->device),
&init_attr->cap, qp);
if (ret)
goto err_qp;
- ret = pvrdma_set_rq_size(to_vdev(pd->device),
+ ret = pvrdma_set_rq_size(to_vdev(ibqp->device),
&init_attr->cap, qp);
if (ret)
goto err_qp;
@@ -362,7 +355,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
memset(cmd, 0, sizeof(*cmd));
cmd->hdr.cmd = PVRDMA_CMD_CREATE_QP;
- cmd->pd_handle = to_vpd(pd)->pd_handle;
+ cmd->pd_handle = to_vpd(ibqp->pd)->pd_handle;
cmd->send_cq_handle = to_vcq(init_attr->send_cq)->cq_handle;
cmd->recv_cq_handle = to_vcq(init_attr->recv_cq)->cq_handle;
if (is_srq)
@@ -418,11 +411,11 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
dev_warn(&dev->pdev->dev,
"failed to copy back udata\n");
__pvrdma_destroy_qp(dev, qp);
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
}
- return &qp->ibqp;
+ return 0;
err_pdir:
pvrdma_page_dir_cleanup(dev, &qp->pdir);
@@ -430,10 +423,8 @@ err_umem:
ib_umem_release(qp->rumem);
ib_umem_release(qp->sumem);
err_qp:
- kfree(qp);
atomic_dec(&dev->num_qps);
-
- return ERR_PTR(ret);
+ return ret;
}
static void _pvrdma_free_qp(struct pvrdma_qp *qp)
@@ -454,8 +445,6 @@ static void _pvrdma_free_qp(struct pvrdma_qp *qp)
pvrdma_page_dir_cleanup(dev, &qp->pdir);
- kfree(qp);
-
atomic_dec(&dev->num_qps);
}
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
index 544b94d97c3a..78807b23d831 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
@@ -390,9 +390,8 @@ int pvrdma_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
int pvrdma_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
int pvrdma_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
-struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata);
+int pvrdma_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
int pvrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
int pvrdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
diff --git a/drivers/infiniband/sw/rdmavt/ah.c b/drivers/infiniband/sw/rdmavt/ah.c
index a3e5b368c5e7..63999239ed9e 100644
--- a/drivers/infiniband/sw/rdmavt/ah.c
+++ b/drivers/infiniband/sw/rdmavt/ah.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 - 2019 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/slab.h>
diff --git a/drivers/infiniband/sw/rdmavt/ah.h b/drivers/infiniband/sw/rdmavt/ah.h
index 5a85edd06491..c11fdf637d64 100644
--- a/drivers/infiniband/sw/rdmavt/ah.h
+++ b/drivers/infiniband/sw/rdmavt/ah.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RVTAH_H
-#define DEF_RVTAH_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RVTAH_H
+#define DEF_RVTAH_H
+
#include <rdma/rdma_vt.h>
int rvt_create_ah(struct ib_ah *ah, struct rdma_ah_init_attr *init_attr,
diff --git a/drivers/infiniband/sw/rdmavt/cq.c b/drivers/infiniband/sw/rdmavt/cq.c
index 5138afca067f..9fe4dcaa049a 100644
--- a/drivers/infiniband/sw/rdmavt/cq.c
+++ b/drivers/infiniband/sw/rdmavt/cq.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/slab.h>
diff --git a/drivers/infiniband/sw/rdmavt/cq.h b/drivers/infiniband/sw/rdmavt/cq.h
index feb01e7ee004..b0a948ec760b 100644
--- a/drivers/infiniband/sw/rdmavt/cq.h
+++ b/drivers/infiniband/sw/rdmavt/cq.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RVTCQ_H
-#define DEF_RVTCQ_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RVTCQ_H
+#define DEF_RVTCQ_H
+
#include <rdma/rdma_vt.h>
#include <rdma/rdmavt_cq.h>
diff --git a/drivers/infiniband/sw/rdmavt/mad.c b/drivers/infiniband/sw/rdmavt/mad.c
index 207bc0ed96ff..98a8fe3b04ef 100644
--- a/drivers/infiniband/sw/rdmavt/mad.c
+++ b/drivers/infiniband/sw/rdmavt/mad.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <rdma/ib_mad.h>
diff --git a/drivers/infiniband/sw/rdmavt/mad.h b/drivers/infiniband/sw/rdmavt/mad.h
index 1eae5efea4be..368be29eab37 100644
--- a/drivers/infiniband/sw/rdmavt/mad.h
+++ b/drivers/infiniband/sw/rdmavt/mad.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RVTMAD_H
-#define DEF_RVTMAD_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RVTMAD_H
+#define DEF_RVTMAD_H
+
#include <rdma/rdma_vt.h>
int rvt_process_mad(struct ib_device *ibdev, int mad_flags, u32 port_num,
diff --git a/drivers/infiniband/sw/rdmavt/mcast.c b/drivers/infiniband/sw/rdmavt/mcast.c
index 951abac13dbb..a123874e1ca7 100644
--- a/drivers/infiniband/sw/rdmavt/mcast.c
+++ b/drivers/infiniband/sw/rdmavt/mcast.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/slab.h>
diff --git a/drivers/infiniband/sw/rdmavt/mcast.h b/drivers/infiniband/sw/rdmavt/mcast.h
index 29f579267608..b96d86f9625b 100644
--- a/drivers/infiniband/sw/rdmavt/mcast.h
+++ b/drivers/infiniband/sw/rdmavt/mcast.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RVTMCAST_H
-#define DEF_RVTMCAST_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RVTMCAST_H
+#define DEF_RVTMCAST_H
+
#include <rdma/rdma_vt.h>
void rvt_driver_mcast_init(struct rvt_dev_info *rdi);
diff --git a/drivers/infiniband/sw/rdmavt/mmap.c b/drivers/infiniband/sw/rdmavt/mmap.c
index f5d0e33cf3d7..4d2238f3f3c8 100644
--- a/drivers/infiniband/sw/rdmavt/mmap.c
+++ b/drivers/infiniband/sw/rdmavt/mmap.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/slab.h>
diff --git a/drivers/infiniband/sw/rdmavt/mmap.h b/drivers/infiniband/sw/rdmavt/mmap.h
index 02466c40bc1e..7e92cf28e071 100644
--- a/drivers/infiniband/sw/rdmavt/mmap.h
+++ b/drivers/infiniband/sw/rdmavt/mmap.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RDMAVTMMAP_H
-#define DEF_RDMAVTMMAP_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RDMAVTMMAP_H
+#define DEF_RDMAVTMMAP_H
+
#include <rdma/rdma_vt.h>
void rvt_mmap_init(struct rvt_dev_info *rdi);
diff --git a/drivers/infiniband/sw/rdmavt/mr.c b/drivers/infiniband/sw/rdmavt/mr.c
index 34b7af6ab9c2..8a1f2e285180 100644
--- a/drivers/infiniband/sw/rdmavt/mr.c
+++ b/drivers/infiniband/sw/rdmavt/mr.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/slab.h>
@@ -410,7 +368,7 @@ struct ib_mr *rvt_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
mr->mr.page_shift = PAGE_SHIFT;
m = 0;
n = 0;
- for_each_sg_page (umem->sg_head.sgl, &sg_iter, umem->nmap, 0) {
+ for_each_sgtable_page (&umem->sgt_append.sgt, &sg_iter, 0) {
void *vaddr;
vaddr = page_address(sg_page_iter_page(&sg_iter));
diff --git a/drivers/infiniband/sw/rdmavt/mr.h b/drivers/infiniband/sw/rdmavt/mr.h
index b3aba359401b..d17f1400b5f6 100644
--- a/drivers/infiniband/sw/rdmavt/mr.h
+++ b/drivers/infiniband/sw/rdmavt/mr.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RVTMR_H
-#define DEF_RVTMR_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RVTMR_H
+#define DEF_RVTMR_H
+
#include <rdma/rdma_vt.h>
struct rvt_mr {
diff --git a/drivers/infiniband/sw/rdmavt/pd.c b/drivers/infiniband/sw/rdmavt/pd.c
index 01b7abf91520..ae62071969fa 100644
--- a/drivers/infiniband/sw/rdmavt/pd.c
+++ b/drivers/infiniband/sw/rdmavt/pd.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/slab.h>
diff --git a/drivers/infiniband/sw/rdmavt/pd.h b/drivers/infiniband/sw/rdmavt/pd.h
index 06a6a38beedc..42a0ef3b7da3 100644
--- a/drivers/infiniband/sw/rdmavt/pd.h
+++ b/drivers/infiniband/sw/rdmavt/pd.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RDMAVTPD_H
-#define DEF_RDMAVTPD_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RDMAVTPD_H
+#define DEF_RDMAVTPD_H
+
#include <rdma/rdma_vt.h>
int rvt_alloc_pd(struct ib_pd *pd, struct ib_udata *udata);
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
index e9f3d356b361..49bdd78ac664 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 - 2020 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/hash.h>
@@ -1058,7 +1016,7 @@ static int alloc_ud_wq_attr(struct rvt_qp *qp, int node)
/**
* rvt_create_qp - create a queue pair for a device
- * @ibpd: the protection domain who's device we create the queue pair for
+ * @ibqp: the queue pair
* @init_attr: the attributes of the queue pair
* @udata: user data for libibverbs.so
*
@@ -1066,47 +1024,45 @@ static int alloc_ud_wq_attr(struct rvt_qp *qp, int node)
* unique idea of what queue pair numbers mean. For instance there is a reserved
* range for PSM.
*
- * Return: the queue pair on success, otherwise returns an errno.
+ * Return: 0 on success, otherwise returns an errno.
*
* Called by the ib_create_qp() core verbs function.
*/
-struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata)
+int rvt_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
{
- struct rvt_qp *qp;
- int err;
+ struct rvt_qp *qp = ibqp_to_rvtqp(ibqp);
+ int ret = -ENOMEM;
struct rvt_swqe *swq = NULL;
size_t sz;
- size_t sg_list_sz;
- struct ib_qp *ret = ERR_PTR(-ENOMEM);
- struct rvt_dev_info *rdi = ib_to_rvt(ibpd->device);
+ size_t sg_list_sz = 0;
+ struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device);
void *priv = NULL;
size_t sqsize;
u8 exclude_prefix = 0;
if (!rdi)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
if (init_attr->create_flags & ~IB_QP_CREATE_NETDEV_USE)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
if (init_attr->cap.max_send_sge > rdi->dparms.props.max_send_sge ||
init_attr->cap.max_send_wr > rdi->dparms.props.max_qp_wr)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
/* Check receive queue parameters if no SRQ is specified. */
if (!init_attr->srq) {
if (init_attr->cap.max_recv_sge >
rdi->dparms.props.max_recv_sge ||
init_attr->cap.max_recv_wr > rdi->dparms.props.max_qp_wr)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
if (init_attr->cap.max_send_sge +
init_attr->cap.max_send_wr +
init_attr->cap.max_recv_sge +
init_attr->cap.max_recv_wr == 0)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
sqsize =
init_attr->cap.max_send_wr + 1 +
@@ -1115,8 +1071,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
case IB_QPT_SMI:
case IB_QPT_GSI:
if (init_attr->port_num == 0 ||
- init_attr->port_num > ibpd->device->phys_port_cnt)
- return ERR_PTR(-EINVAL);
+ init_attr->port_num > ibqp->device->phys_port_cnt)
+ return -EINVAL;
fallthrough;
case IB_QPT_UC:
case IB_QPT_RC:
@@ -1124,10 +1080,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
sz = struct_size(swq, sg_list, init_attr->cap.max_send_sge);
swq = vzalloc_node(array_size(sz, sqsize), rdi->dparms.node);
if (!swq)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
- sz = sizeof(*qp);
- sg_list_sz = 0;
if (init_attr->srq) {
struct rvt_srq *srq = ibsrq_to_rvtsrq(init_attr->srq);
@@ -1137,10 +1091,10 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
} else if (init_attr->cap.max_recv_sge > 1)
sg_list_sz = sizeof(*qp->r_sg_list) *
(init_attr->cap.max_recv_sge - 1);
- qp = kzalloc_node(sz + sg_list_sz, GFP_KERNEL,
- rdi->dparms.node);
- if (!qp)
- goto bail_swq;
+ qp->r_sg_list =
+ kzalloc_node(sg_list_sz, GFP_KERNEL, rdi->dparms.node);
+ if (!qp->r_sg_list)
+ goto bail_qp;
qp->allowed_ops = get_allowed_ops(init_attr->qp_type);
RCU_INIT_POINTER(qp->next, NULL);
@@ -1165,7 +1119,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
*/
priv = rdi->driver_f.qp_priv_alloc(rdi, qp);
if (IS_ERR(priv)) {
- ret = priv;
+ ret = PTR_ERR(priv);
goto bail_qp;
}
qp->priv = priv;
@@ -1179,12 +1133,10 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) +
sizeof(struct rvt_rwqe);
- err = rvt_alloc_rq(&qp->r_rq, qp->r_rq.size * sz,
+ ret = rvt_alloc_rq(&qp->r_rq, qp->r_rq.size * sz,
rdi->dparms.node, udata);
- if (err) {
- ret = ERR_PTR(err);
+ if (ret)
goto bail_driver_priv;
- }
}
/*
@@ -1205,40 +1157,35 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
qp->s_max_sge = init_attr->cap.max_send_sge;
if (init_attr->sq_sig_type == IB_SIGNAL_REQ_WR)
qp->s_flags = RVT_S_SIGNAL_REQ_WR;
- err = alloc_ud_wq_attr(qp, rdi->dparms.node);
- if (err) {
- ret = (ERR_PTR(err));
+ ret = alloc_ud_wq_attr(qp, rdi->dparms.node);
+ if (ret)
goto bail_rq_rvt;
- }
if (init_attr->create_flags & IB_QP_CREATE_NETDEV_USE)
exclude_prefix = RVT_AIP_QP_PREFIX;
- err = alloc_qpn(rdi, &rdi->qp_dev->qpn_table,
+ ret = alloc_qpn(rdi, &rdi->qp_dev->qpn_table,
init_attr->qp_type,
init_attr->port_num,
exclude_prefix);
- if (err < 0) {
- ret = ERR_PTR(err);
+ if (ret < 0)
goto bail_rq_wq;
- }
- qp->ibqp.qp_num = err;
+
+ qp->ibqp.qp_num = ret;
if (init_attr->create_flags & IB_QP_CREATE_NETDEV_USE)
qp->ibqp.qp_num |= RVT_AIP_QP_BASE;
qp->port_num = init_attr->port_num;
rvt_init_qp(rdi, qp, init_attr->qp_type);
if (rdi->driver_f.qp_priv_init) {
- err = rdi->driver_f.qp_priv_init(rdi, qp, init_attr);
- if (err) {
- ret = ERR_PTR(err);
+ ret = rdi->driver_f.qp_priv_init(rdi, qp, init_attr);
+ if (ret)
goto bail_rq_wq;
- }
}
break;
default:
/* Don't support raw QPs */
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
}
init_attr->cap.max_inline_data = 0;
@@ -1251,28 +1198,24 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
if (!qp->r_rq.wq) {
__u64 offset = 0;
- err = ib_copy_to_udata(udata, &offset,
+ ret = ib_copy_to_udata(udata, &offset,
sizeof(offset));
- if (err) {
- ret = ERR_PTR(err);
+ if (ret)
goto bail_qpn;
- }
} else {
u32 s = sizeof(struct rvt_rwq) + qp->r_rq.size * sz;
qp->ip = rvt_create_mmap_info(rdi, s, udata,
qp->r_rq.wq);
if (IS_ERR(qp->ip)) {
- ret = ERR_CAST(qp->ip);
+ ret = PTR_ERR(qp->ip);
goto bail_qpn;
}
- err = ib_copy_to_udata(udata, &qp->ip->offset,
+ ret = ib_copy_to_udata(udata, &qp->ip->offset,
sizeof(qp->ip->offset));
- if (err) {
- ret = ERR_PTR(err);
+ if (ret)
goto bail_ip;
- }
}
qp->pid = current->pid;
}
@@ -1280,7 +1223,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
spin_lock(&rdi->n_qps_lock);
if (rdi->n_qps_allocated == rdi->dparms.props.max_qp) {
spin_unlock(&rdi->n_qps_lock);
- ret = ERR_PTR(-ENOMEM);
+ ret = ENOMEM;
goto bail_ip;
}
@@ -1306,9 +1249,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
spin_unlock_irq(&rdi->pending_lock);
}
- ret = &qp->ibqp;
-
- return ret;
+ return 0;
bail_ip:
if (qp->ip)
@@ -1328,11 +1269,8 @@ bail_driver_priv:
bail_qp:
kfree(qp->s_ack_queue);
- kfree(qp);
-
-bail_swq:
+ kfree(qp->r_sg_list);
vfree(swq);
-
return ret;
}
@@ -1762,11 +1700,11 @@ int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
kvfree(qp->r_rq.kwq);
rdi->driver_f.qp_priv_free(rdi, qp);
kfree(qp->s_ack_queue);
+ kfree(qp->r_sg_list);
rdma_destroy_ah_attr(&qp->remote_ah_attr);
rdma_destroy_ah_attr(&qp->alt_ah_attr);
free_ud_wq_attr(qp);
vfree(qp->s_wq);
- kfree(qp);
return 0;
}
diff --git a/drivers/infiniband/sw/rdmavt/qp.h b/drivers/infiniband/sw/rdmavt/qp.h
index 2cdba1283bf6..bd04be80723c 100644
--- a/drivers/infiniband/sw/rdmavt/qp.h
+++ b/drivers/infiniband/sw/rdmavt/qp.h
@@ -1,60 +1,17 @@
-#ifndef DEF_RVTQP_H
-#define DEF_RVTQP_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RVTQP_H
+#define DEF_RVTQP_H
+
#include <rdma/rdmavt_qp.h>
int rvt_driver_qp_init(struct rvt_dev_info *rdi);
void rvt_qp_exit(struct rvt_dev_info *rdi);
-struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata);
+int rvt_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
diff --git a/drivers/infiniband/sw/rdmavt/rc.c b/drivers/infiniband/sw/rdmavt/rc.c
index c58735f4c94a..4e5d4a27633c 100644
--- a/drivers/infiniband/sw/rdmavt/rc.c
+++ b/drivers/infiniband/sw/rdmavt/rc.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <rdma/rdmavt_qp.h>
diff --git a/drivers/infiniband/sw/rdmavt/srq.c b/drivers/infiniband/sw/rdmavt/srq.c
index 2a7c2f12d372..14d196bde2a1 100644
--- a/drivers/infiniband/sw/rdmavt/srq.c
+++ b/drivers/infiniband/sw/rdmavt/srq.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/err.h>
diff --git a/drivers/infiniband/sw/rdmavt/srq.h b/drivers/infiniband/sw/rdmavt/srq.h
index d5a1a053b1b9..7d17372cd269 100644
--- a/drivers/infiniband/sw/rdmavt/srq.h
+++ b/drivers/infiniband/sw/rdmavt/srq.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RVTSRQ_H
-#define DEF_RVTSRQ_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RVTSRQ_H
+#define DEF_RVTSRQ_H
+
#include <rdma/rdma_vt.h>
void rvt_driver_srq_init(struct rvt_dev_info *rdi);
int rvt_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *srq_init_attr,
diff --git a/drivers/infiniband/sw/rdmavt/trace.c b/drivers/infiniband/sw/rdmavt/trace.c
index d593285a349c..01704b8dd683 100644
--- a/drivers/infiniband/sw/rdmavt/trace.c
+++ b/drivers/infiniband/sw/rdmavt/trace.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#define CREATE_TRACE_POINTS
diff --git a/drivers/infiniband/sw/rdmavt/trace.h b/drivers/infiniband/sw/rdmavt/trace.h
index 36ddbd291ee0..30eb4a72ea7d 100644
--- a/drivers/infiniband/sw/rdmavt/trace.h
+++ b/drivers/infiniband/sw/rdmavt/trace.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016, 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#define RDI_DEV_ENTRY(rdi) __string(dev, rvt_get_ibdev_name(rdi))
diff --git a/drivers/infiniband/sw/rdmavt/trace_cq.h b/drivers/infiniband/sw/rdmavt/trace_cq.h
index 91bc192cee5e..30dd1d9bae26 100644
--- a/drivers/infiniband/sw/rdmavt/trace_cq.h
+++ b/drivers/infiniband/sw/rdmavt/trace_cq.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#if !defined(__RVT_TRACE_CQ_H) || defined(TRACE_HEADER_MULTI_READ)
#define __RVT_TRACE_CQ_H
diff --git a/drivers/infiniband/sw/rdmavt/trace_mr.h b/drivers/infiniband/sw/rdmavt/trace_mr.h
index c5b675ca4fa0..1de7012000cb 100644
--- a/drivers/infiniband/sw/rdmavt/trace_mr.h
+++ b/drivers/infiniband/sw/rdmavt/trace_mr.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#if !defined(__RVT_TRACE_MR_H) || defined(TRACE_HEADER_MULTI_READ)
#define __RVT_TRACE_MR_H
diff --git a/drivers/infiniband/sw/rdmavt/trace_qp.h b/drivers/infiniband/sw/rdmavt/trace_qp.h
index 800cec8bb3c7..c28c81fcb32a 100644
--- a/drivers/infiniband/sw/rdmavt/trace_qp.h
+++ b/drivers/infiniband/sw/rdmavt/trace_qp.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#if !defined(__RVT_TRACE_QP_H) || defined(TRACE_HEADER_MULTI_READ)
#define __RVT_TRACE_QP_H
diff --git a/drivers/infiniband/sw/rdmavt/trace_rc.h b/drivers/infiniband/sw/rdmavt/trace_rc.h
index 9de52e138025..833bf778b05d 100644
--- a/drivers/infiniband/sw/rdmavt/trace_rc.h
+++ b/drivers/infiniband/sw/rdmavt/trace_rc.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#if !defined(__RVT_TRACE_RC_H) || defined(TRACE_HEADER_MULTI_READ)
#define __RVT_TRACE_RC_H
diff --git a/drivers/infiniband/sw/rdmavt/trace_rvt.h b/drivers/infiniband/sw/rdmavt/trace_rvt.h
index 746f33461d9a..9df6b0b8263b 100644
--- a/drivers/infiniband/sw/rdmavt/trace_rvt.h
+++ b/drivers/infiniband/sw/rdmavt/trace_rvt.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#if !defined(__RVT_TRACE_RVT_H) || defined(TRACE_HEADER_MULTI_READ)
#define __RVT_TRACE_RVT_H
diff --git a/drivers/infiniband/sw/rdmavt/trace_tx.h b/drivers/infiniband/sw/rdmavt/trace_tx.h
index cb96be0f8f19..ff7d39a30768 100644
--- a/drivers/infiniband/sw/rdmavt/trace_tx.h
+++ b/drivers/infiniband/sw/rdmavt/trace_tx.h
@@ -1,48 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#if !defined(__RVT_TRACE_TX_H) || defined(TRACE_HEADER_MULTI_READ)
#define __RVT_TRACE_TX_H
diff --git a/drivers/infiniband/sw/rdmavt/vt.c b/drivers/infiniband/sw/rdmavt/vt.c
index ac17209816cd..59481ae39505 100644
--- a/drivers/infiniband/sw/rdmavt/vt.c
+++ b/drivers/infiniband/sw/rdmavt/vt.c
@@ -1,48 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
/*
* Copyright(c) 2016 - 2018 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <linux/module.h>
@@ -131,6 +89,13 @@ static int rvt_query_device(struct ib_device *ibdev,
return 0;
}
+static int rvt_get_numa_node(struct ib_device *ibdev)
+{
+ struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
+
+ return rdi->dparms.node;
+}
+
static int rvt_modify_device(struct ib_device *device,
int device_modify_mask,
struct ib_device_modify *device_modify)
@@ -380,6 +345,7 @@ static const struct ib_device_ops rvt_dev_ops = {
.destroy_srq = rvt_destroy_srq,
.detach_mcast = rvt_detach_mcast,
.get_dma_mr = rvt_get_dma_mr,
+ .get_numa_node = rvt_get_numa_node,
.get_port_immutable = rvt_get_port_immutable,
.map_mr_sg = rvt_map_mr_sg,
.mmap = rvt_mmap,
@@ -406,6 +372,7 @@ static const struct ib_device_ops rvt_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, rvt_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, rvt_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, rvt_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, rvt_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_srq, rvt_srq, ibsrq),
INIT_RDMA_OBJ_SIZE(ib_ucontext, rvt_ucontext, ibucontext),
};
diff --git a/drivers/infiniband/sw/rdmavt/vt.h b/drivers/infiniband/sw/rdmavt/vt.h
index c0fed6510f0b..461574e3f6a5 100644
--- a/drivers/infiniband/sw/rdmavt/vt.h
+++ b/drivers/infiniband/sw/rdmavt/vt.h
@@ -1,53 +1,11 @@
-#ifndef DEF_RDMAVT_H
-#define DEF_RDMAVT_H
-
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
* Copyright(c) 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
+#ifndef DEF_RDMAVT_H
+#define DEF_RDMAVT_H
+
#include <rdma/rdma_vt.h>
#include <linux/pci.h>
#include "pd.h"
diff --git a/drivers/infiniband/sw/rxe/rxe.h b/drivers/infiniband/sw/rxe/rxe.h
index 623fd17df02d..1bb3fb618bf5 100644
--- a/drivers/infiniband/sw/rxe/rxe.h
+++ b/drivers/infiniband/sw/rxe/rxe.h
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/crc32.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
@@ -42,27 +41,6 @@
extern bool rxe_initialized;
-static inline u32 rxe_crc32(struct rxe_dev *rxe,
- u32 crc, void *next, size_t len)
-{
- u32 retval;
- int err;
-
- SHASH_DESC_ON_STACK(shash, rxe->tfm);
-
- shash->tfm = rxe->tfm;
- *(u32 *)shash_desc_ctx(shash) = crc;
- err = crypto_shash_update(shash, next, len);
- if (unlikely(err)) {
- pr_warn_ratelimited("failed crc calculation, err: %d\n", err);
- return crc32_le(crc, next, len);
- }
-
- retval = *(u32 *)shash_desc_ctx(shash);
- barrier_data(shash_desc_ctx(shash));
- return retval;
-}
-
void rxe_set_mtu(struct rxe_dev *rxe, unsigned int dev_mtu);
int rxe_add(struct rxe_dev *rxe, unsigned int mtu, const char *ibdev_name);
diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
index 58ad9c2644f3..d2d802c776fd 100644
--- a/drivers/infiniband/sw/rxe/rxe_comp.c
+++ b/drivers/infiniband/sw/rxe/rxe_comp.c
@@ -349,7 +349,7 @@ static inline enum comp_state do_read(struct rxe_qp *qp,
ret = copy_data(qp->pd, IB_ACCESS_LOCAL_WRITE,
&wqe->dma, payload_addr(pkt),
- payload_size(pkt), RXE_TO_MR_OBJ, NULL);
+ payload_size(pkt), RXE_TO_MR_OBJ);
if (ret) {
wqe->status = IB_WC_LOC_PROT_ERR;
return COMPST_ERROR;
@@ -371,7 +371,7 @@ static inline enum comp_state do_atomic(struct rxe_qp *qp,
ret = copy_data(qp->pd, IB_ACCESS_LOCAL_WRITE,
&wqe->dma, &atomic_orig,
- sizeof(u64), RXE_TO_MR_OBJ, NULL);
+ sizeof(u64), RXE_TO_MR_OBJ);
if (ret) {
wqe->status = IB_WC_LOC_PROT_ERR;
return COMPST_ERROR;
diff --git a/drivers/infiniband/sw/rxe/rxe_icrc.c b/drivers/infiniband/sw/rxe/rxe_icrc.c
index 66b2aad54bb7..e03af3012590 100644
--- a/drivers/infiniband/sw/rxe/rxe_icrc.c
+++ b/drivers/infiniband/sw/rxe/rxe_icrc.c
@@ -4,18 +4,79 @@
* Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
*/
+#include <linux/crc32.h>
+
#include "rxe.h"
#include "rxe_loc.h"
-/* Compute a partial ICRC for all the IB transport headers. */
-u32 rxe_icrc_hdr(struct rxe_pkt_info *pkt, struct sk_buff *skb)
+/**
+ * rxe_icrc_init() - Initialize crypto function for computing crc32
+ * @rxe: rdma_rxe device object
+ *
+ * Return: 0 on success else an error
+ */
+int rxe_icrc_init(struct rxe_dev *rxe)
+{
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash("crc32", 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_warn("failed to init crc32 algorithm err:%ld\n",
+ PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }
+
+ rxe->tfm = tfm;
+
+ return 0;
+}
+
+/**
+ * rxe_crc32() - Compute cumulative crc32 for a contiguous segment
+ * @rxe: rdma_rxe device object
+ * @crc: starting crc32 value from previous segments
+ * @next: starting address of current segment
+ * @len: length of current segment
+ *
+ * Return: the cumulative crc32 checksum
+ */
+static __be32 rxe_crc32(struct rxe_dev *rxe, __be32 crc, void *next, size_t len)
+{
+ __be32 icrc;
+ int err;
+
+ SHASH_DESC_ON_STACK(shash, rxe->tfm);
+
+ shash->tfm = rxe->tfm;
+ *(__be32 *)shash_desc_ctx(shash) = crc;
+ err = crypto_shash_update(shash, next, len);
+ if (unlikely(err)) {
+ pr_warn_ratelimited("failed crc calculation, err: %d\n", err);
+ return (__force __be32)crc32_le((__force u32)crc, next, len);
+ }
+
+ icrc = *(__be32 *)shash_desc_ctx(shash);
+ barrier_data(shash_desc_ctx(shash));
+
+ return icrc;
+}
+
+/**
+ * rxe_icrc_hdr() - Compute the partial ICRC for the network and transport
+ * headers of a packet.
+ * @skb: packet buffer
+ * @pkt: packet information
+ *
+ * Return: the partial ICRC
+ */
+static __be32 rxe_icrc_hdr(struct sk_buff *skb, struct rxe_pkt_info *pkt)
{
unsigned int bth_offset = 0;
struct iphdr *ip4h = NULL;
struct ipv6hdr *ip6h = NULL;
struct udphdr *udph;
struct rxe_bth *bth;
- int crc;
+ __be32 crc;
int length;
int hdr_size = sizeof(struct udphdr) +
(skb->protocol == htons(ETH_P_IP) ?
@@ -30,7 +91,7 @@ u32 rxe_icrc_hdr(struct rxe_pkt_info *pkt, struct sk_buff *skb)
/* This seed is the result of computing a CRC with a seed of
* 0xfffffff and 8 bytes of 0xff representing a masked LRH.
*/
- crc = 0xdebb20e3;
+ crc = (__force __be32)0xdebb20e3;
if (skb->protocol == htons(ETH_P_IP)) { /* IPv4 */
memcpy(pshdr, ip_hdr(skb), hdr_size);
@@ -67,3 +128,58 @@ u32 rxe_icrc_hdr(struct rxe_pkt_info *pkt, struct sk_buff *skb)
rxe_opcode[pkt->opcode].length - RXE_BTH_BYTES);
return crc;
}
+
+/**
+ * rxe_icrc_check() - Compute ICRC for a packet and compare to the ICRC
+ * delivered in the packet.
+ * @skb: packet buffer
+ * @pkt: packet information
+ *
+ * Return: 0 if the values match else an error
+ */
+int rxe_icrc_check(struct sk_buff *skb, struct rxe_pkt_info *pkt)
+{
+ __be32 *icrcp;
+ __be32 pkt_icrc;
+ __be32 icrc;
+
+ icrcp = (__be32 *)(pkt->hdr + pkt->paylen - RXE_ICRC_SIZE);
+ pkt_icrc = *icrcp;
+
+ icrc = rxe_icrc_hdr(skb, pkt);
+ icrc = rxe_crc32(pkt->rxe, icrc, (u8 *)payload_addr(pkt),
+ payload_size(pkt) + bth_pad(pkt));
+ icrc = ~icrc;
+
+ if (unlikely(icrc != pkt_icrc)) {
+ if (skb->protocol == htons(ETH_P_IPV6))
+ pr_warn_ratelimited("bad ICRC from %pI6c\n",
+ &ipv6_hdr(skb)->saddr);
+ else if (skb->protocol == htons(ETH_P_IP))
+ pr_warn_ratelimited("bad ICRC from %pI4\n",
+ &ip_hdr(skb)->saddr);
+ else
+ pr_warn_ratelimited("bad ICRC from unknown\n");
+
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * rxe_icrc_generate() - compute ICRC for a packet.
+ * @skb: packet buffer
+ * @pkt: packet information
+ */
+void rxe_icrc_generate(struct sk_buff *skb, struct rxe_pkt_info *pkt)
+{
+ __be32 *icrcp;
+ __be32 icrc;
+
+ icrcp = (__be32 *)(pkt->hdr + pkt->paylen - RXE_ICRC_SIZE);
+ icrc = rxe_icrc_hdr(skb, pkt);
+ icrc = rxe_crc32(pkt->rxe, icrc, (u8 *)payload_addr(pkt),
+ payload_size(pkt) + bth_pad(pkt));
+ *icrcp = ~icrc;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h
index 1ddb20855dee..f0c954575bde 100644
--- a/drivers/infiniband/sw/rxe/rxe_loc.h
+++ b/drivers/infiniband/sw/rxe/rxe_loc.h
@@ -77,10 +77,9 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova,
int access, struct rxe_mr *mr);
int rxe_mr_init_fast(struct rxe_pd *pd, int max_pages, struct rxe_mr *mr);
int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length,
- enum rxe_mr_copy_dir dir, u32 *crcp);
-int copy_data(struct rxe_pd *pd, int access,
- struct rxe_dma_info *dma, void *addr, int length,
- enum rxe_mr_copy_dir dir, u32 *crcp);
+ enum rxe_mr_copy_dir dir);
+int copy_data(struct rxe_pd *pd, int access, struct rxe_dma_info *dma,
+ void *addr, int length, enum rxe_mr_copy_dir dir);
void *iova_to_vaddr(struct rxe_mr *mr, u64 iova, int length);
struct rxe_mr *lookup_mr(struct rxe_pd *pd, int access, u32 key,
enum rxe_mr_lookup_type type);
@@ -99,11 +98,11 @@ struct rxe_mw *rxe_lookup_mw(struct rxe_qp *qp, int access, u32 rkey);
void rxe_mw_cleanup(struct rxe_pool_entry *arg);
/* rxe_net.c */
-void rxe_loopback(struct sk_buff *skb);
-int rxe_send(struct rxe_pkt_info *pkt, struct sk_buff *skb);
struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av,
int paylen, struct rxe_pkt_info *pkt);
-int rxe_prepare(struct rxe_pkt_info *pkt, struct sk_buff *skb, u32 *crc);
+int rxe_prepare(struct rxe_pkt_info *pkt, struct sk_buff *skb);
+int rxe_xmit_packet(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
+ struct sk_buff *skb);
const char *rxe_parent_name(struct rxe_dev *rxe, unsigned int port_num);
int rxe_mcast_add(struct rxe_dev *rxe, union ib_gid *mgid);
int rxe_mcast_delete(struct rxe_dev *rxe, union ib_gid *mgid);
@@ -193,7 +192,10 @@ int rxe_completer(void *arg);
int rxe_requester(void *arg);
int rxe_responder(void *arg);
-u32 rxe_icrc_hdr(struct rxe_pkt_info *pkt, struct sk_buff *skb);
+/* rxe_icrc.c */
+int rxe_icrc_init(struct rxe_dev *rxe);
+int rxe_icrc_check(struct sk_buff *skb, struct rxe_pkt_info *pkt);
+void rxe_icrc_generate(struct sk_buff *skb, struct rxe_pkt_info *pkt);
void rxe_resp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb);
@@ -204,47 +206,4 @@ static inline unsigned int wr_opcode_mask(int opcode, struct rxe_qp *qp)
return rxe_wr_opcode_info[opcode].mask[qp->ibqp.qp_type];
}
-static inline int rxe_xmit_packet(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
- struct sk_buff *skb)
-{
- int err;
- int is_request = pkt->mask & RXE_REQ_MASK;
- struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
-
- if ((is_request && (qp->req.state != QP_STATE_READY)) ||
- (!is_request && (qp->resp.state != QP_STATE_READY))) {
- pr_info("Packet dropped. QP is not in ready state\n");
- goto drop;
- }
-
- if (pkt->mask & RXE_LOOPBACK_MASK) {
- memcpy(SKB_TO_PKT(skb), pkt, sizeof(*pkt));
- rxe_loopback(skb);
- err = 0;
- } else {
- err = rxe_send(pkt, skb);
- }
-
- if (err) {
- rxe->xmit_errors++;
- rxe_counter_inc(rxe, RXE_CNT_SEND_ERR);
- return err;
- }
-
- if ((qp_type(qp) != IB_QPT_RC) &&
- (pkt->mask & RXE_END_MASK)) {
- pkt->wqe->state = wqe_state_done;
- rxe_run_task(&qp->comp.task, 1);
- }
-
- rxe_counter_inc(rxe, RXE_CNT_SENT_PKTS);
- goto done;
-
-drop:
- kfree_skb(skb);
- err = 0;
-done:
- return err;
-}
-
#endif /* RXE_LOC_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
index be4bcb420fab..5890a8246216 100644
--- a/drivers/infiniband/sw/rxe/rxe_mr.c
+++ b/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -123,7 +123,6 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova,
goto err_out;
}
- mr->umem = umem;
num_buf = ib_umem_num_pages(umem);
rxe_mr_init(access, mr);
@@ -143,7 +142,7 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova,
if (length > 0) {
buf = map[0]->buf;
- for_each_sg_page(umem->sg_head.sgl, &sg_iter, umem->nmap, 0) {
+ for_each_sgtable_page (&umem->sgt_append.sgt, &sg_iter, 0) {
if (num_buf >= RXE_BUF_PER_MAP) {
map++;
buf = map[0]->buf;
@@ -286,11 +285,10 @@ out:
}
/* copy data from a range (vaddr, vaddr+length-1) to or from
- * a mr object starting at iova. Compute incremental value of
- * crc32 if crcp is not zero. caller must hold a reference to mr
+ * a mr object starting at iova.
*/
int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length,
- enum rxe_mr_copy_dir dir, u32 *crcp)
+ enum rxe_mr_copy_dir dir)
{
int err;
int bytes;
@@ -300,7 +298,6 @@ int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length,
int m;
int i;
size_t offset;
- u32 crc = crcp ? (*crcp) : 0;
if (length == 0)
return 0;
@@ -314,10 +311,6 @@ int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length,
memcpy(dest, src, length);
- if (crcp)
- *crcp = rxe_crc32(to_rdev(mr->ibmr.device), *crcp, dest,
- length);
-
return 0;
}
@@ -348,10 +341,6 @@ int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length,
memcpy(dest, src, bytes);
- if (crcp)
- crc = rxe_crc32(to_rdev(mr->ibmr.device), crc, dest,
- bytes);
-
length -= bytes;
addr += bytes;
@@ -366,9 +355,6 @@ int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length,
}
}
- if (crcp)
- *crcp = crc;
-
return 0;
err1:
@@ -384,8 +370,7 @@ int copy_data(
struct rxe_dma_info *dma,
void *addr,
int length,
- enum rxe_mr_copy_dir dir,
- u32 *crcp)
+ enum rxe_mr_copy_dir dir)
{
int bytes;
struct rxe_sge *sge = &dma->sge[dma->cur_sge];
@@ -446,7 +431,7 @@ int copy_data(
if (bytes > 0) {
iova = sge->addr + offset;
- err = rxe_mr_copy(mr, iova, addr, bytes, dir, crcp);
+ err = rxe_mr_copy(mr, iova, addr, bytes, dir);
if (err)
goto err2;
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 5ac27f28ace1..2cb810cb890a 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -344,7 +344,7 @@ static int prepare6(struct rxe_pkt_info *pkt, struct sk_buff *skb)
return 0;
}
-int rxe_prepare(struct rxe_pkt_info *pkt, struct sk_buff *skb, u32 *crc)
+int rxe_prepare(struct rxe_pkt_info *pkt, struct sk_buff *skb)
{
int err = 0;
@@ -353,8 +353,6 @@ int rxe_prepare(struct rxe_pkt_info *pkt, struct sk_buff *skb, u32 *crc)
else if (skb->protocol == htons(ETH_P_IPV6))
err = prepare6(pkt, skb);
- *crc = rxe_icrc_hdr(pkt, skb);
-
if (ether_addr_equal(skb->dev->dev_addr, rxe_get_av(pkt)->dmac))
pkt->mask |= RXE_LOOPBACK_MASK;
@@ -374,7 +372,7 @@ static void rxe_skb_tx_dtor(struct sk_buff *skb)
rxe_drop_ref(qp);
}
-int rxe_send(struct rxe_pkt_info *pkt, struct sk_buff *skb)
+static int rxe_send(struct sk_buff *skb, struct rxe_pkt_info *pkt)
{
int err;
@@ -407,19 +405,64 @@ int rxe_send(struct rxe_pkt_info *pkt, struct sk_buff *skb)
/* fix up a send packet to match the packets
* received from UDP before looping them back
*/
-void rxe_loopback(struct sk_buff *skb)
+static int rxe_loopback(struct sk_buff *skb, struct rxe_pkt_info *pkt)
{
- struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
+ memcpy(SKB_TO_PKT(skb), pkt, sizeof(*pkt));
if (skb->protocol == htons(ETH_P_IP))
skb_pull(skb, sizeof(struct iphdr));
else
skb_pull(skb, sizeof(struct ipv6hdr));
- if (WARN_ON(!ib_device_try_get(&pkt->rxe->ib_dev)))
+ if (WARN_ON(!ib_device_try_get(&pkt->rxe->ib_dev))) {
kfree_skb(skb);
+ return -EIO;
+ }
+
+ rxe_rcv(skb);
+
+ return 0;
+}
+
+int rxe_xmit_packet(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
+ struct sk_buff *skb)
+{
+ int err;
+ int is_request = pkt->mask & RXE_REQ_MASK;
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+
+ if ((is_request && (qp->req.state != QP_STATE_READY)) ||
+ (!is_request && (qp->resp.state != QP_STATE_READY))) {
+ pr_info("Packet dropped. QP is not in ready state\n");
+ goto drop;
+ }
+
+ rxe_icrc_generate(skb, pkt);
+
+ if (pkt->mask & RXE_LOOPBACK_MASK)
+ err = rxe_loopback(skb, pkt);
else
- rxe_rcv(skb);
+ err = rxe_send(skb, pkt);
+ if (err) {
+ rxe->xmit_errors++;
+ rxe_counter_inc(rxe, RXE_CNT_SEND_ERR);
+ return err;
+ }
+
+ if ((qp_type(qp) != IB_QPT_RC) &&
+ (pkt->mask & RXE_END_MASK)) {
+ pkt->wqe->state = wqe_state_done;
+ rxe_run_task(&qp->comp.task, 1);
+ }
+
+ rxe_counter_inc(rxe, RXE_CNT_SENT_PKTS);
+ goto done;
+
+drop:
+ kfree_skb(skb);
+ err = 0;
+done:
+ return err;
}
struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av,
diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c
index 0b8e7c6255a2..ffa8420b4765 100644
--- a/drivers/infiniband/sw/rxe/rxe_pool.c
+++ b/drivers/infiniband/sw/rxe/rxe_pool.c
@@ -41,7 +41,7 @@ struct rxe_type_info rxe_type_info[RXE_NUM_TYPES] = {
.size = sizeof(struct rxe_qp),
.elem_offset = offsetof(struct rxe_qp, pelem),
.cleanup = rxe_qp_cleanup,
- .flags = RXE_POOL_INDEX,
+ .flags = RXE_POOL_INDEX | RXE_POOL_NO_ALLOC,
.min_index = RXE_MIN_QP_INDEX,
.max_index = RXE_MAX_QP_INDEX,
},
diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c
index 7a49e27da23a..6a6cc1fa90e4 100644
--- a/drivers/infiniband/sw/rxe/rxe_recv.c
+++ b/drivers/infiniband/sw/rxe/rxe_recv.c
@@ -361,8 +361,6 @@ void rxe_rcv(struct sk_buff *skb)
int err;
struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
struct rxe_dev *rxe = pkt->rxe;
- __be32 *icrcp;
- u32 calc_icrc, pack_icrc;
if (unlikely(skb->len < RXE_BTH_BYTES))
goto drop;
@@ -384,26 +382,9 @@ void rxe_rcv(struct sk_buff *skb)
if (unlikely(err))
goto drop;
- /* Verify ICRC */
- icrcp = (__be32 *)(pkt->hdr + pkt->paylen - RXE_ICRC_SIZE);
- pack_icrc = be32_to_cpu(*icrcp);
-
- calc_icrc = rxe_icrc_hdr(pkt, skb);
- calc_icrc = rxe_crc32(rxe, calc_icrc, (u8 *)payload_addr(pkt),
- payload_size(pkt) + bth_pad(pkt));
- calc_icrc = (__force u32)cpu_to_be32(~calc_icrc);
- if (unlikely(calc_icrc != pack_icrc)) {
- if (skb->protocol == htons(ETH_P_IPV6))
- pr_warn_ratelimited("bad ICRC from %pI6c\n",
- &ipv6_hdr(skb)->saddr);
- else if (skb->protocol == htons(ETH_P_IP))
- pr_warn_ratelimited("bad ICRC from %pI4\n",
- &ip_hdr(skb)->saddr);
- else
- pr_warn_ratelimited("bad ICRC from unknown\n");
-
+ err = rxe_icrc_check(skb, pkt);
+ if (unlikely(err))
goto drop;
- }
rxe_counter_inc(rxe, RXE_CNT_RCVD_PKTS);
diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
index c57699cc6578..3894197a82f6 100644
--- a/drivers/infiniband/sw/rxe/rxe_req.c
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
@@ -466,12 +466,9 @@ static int finish_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
struct rxe_pkt_info *pkt, struct sk_buff *skb,
int paylen)
{
- struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
- u32 crc = 0;
- u32 *p;
int err;
- err = rxe_prepare(pkt, skb, &crc);
+ err = rxe_prepare(pkt, skb);
if (err)
return err;
@@ -479,7 +476,6 @@ static int finish_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
if (wqe->wr.send_flags & IB_SEND_INLINE) {
u8 *tmp = &wqe->dma.inline_data[wqe->dma.sge_offset];
- crc = rxe_crc32(rxe, crc, tmp, paylen);
memcpy(payload_addr(pkt), tmp, paylen);
wqe->dma.resid -= paylen;
@@ -487,8 +483,7 @@ static int finish_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
} else {
err = copy_data(qp->pd, 0, &wqe->dma,
payload_addr(pkt), paylen,
- RXE_FROM_MR_OBJ,
- &crc);
+ RXE_FROM_MR_OBJ);
if (err)
return err;
}
@@ -496,12 +491,8 @@ static int finish_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
u8 *pad = payload_addr(pkt) + paylen;
memset(pad, 0, bth_pad(pkt));
- crc = rxe_crc32(rxe, crc, pad, bth_pad(pkt));
}
}
- p = payload_addr(pkt) + paylen + bth_pad(pkt);
-
- *p = ~crc;
return 0;
}
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
index 360ec67cb9e1..5501227ddc65 100644
--- a/drivers/infiniband/sw/rxe/rxe_resp.c
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -536,7 +536,7 @@ static enum resp_states send_data_in(struct rxe_qp *qp, void *data_addr,
int err;
err = copy_data(qp->pd, IB_ACCESS_LOCAL_WRITE, &qp->resp.wqe->dma,
- data_addr, data_len, RXE_TO_MR_OBJ, NULL);
+ data_addr, data_len, RXE_TO_MR_OBJ);
if (unlikely(err))
return (err == -ENOSPC) ? RESPST_ERR_LENGTH
: RESPST_ERR_MALFORMED_WQE;
@@ -552,7 +552,7 @@ static enum resp_states write_data_in(struct rxe_qp *qp,
int data_len = payload_size(pkt);
err = rxe_mr_copy(qp->resp.mr, qp->resp.va + qp->resp.offset,
- payload_addr(pkt), data_len, RXE_TO_MR_OBJ, NULL);
+ payload_addr(pkt), data_len, RXE_TO_MR_OBJ);
if (err) {
rc = RESPST_ERR_RKEY_VIOLATION;
goto out;
@@ -613,13 +613,10 @@ static struct sk_buff *prepare_ack_packet(struct rxe_qp *qp,
int opcode,
int payload,
u32 psn,
- u8 syndrome,
- u32 *crcp)
+ u8 syndrome)
{
struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
struct sk_buff *skb;
- u32 crc = 0;
- u32 *p;
int paylen;
int pad;
int err;
@@ -651,20 +648,12 @@ static struct sk_buff *prepare_ack_packet(struct rxe_qp *qp,
if (ack->mask & RXE_ATMACK_MASK)
atmack_set_orig(ack, qp->resp.atomic_orig);
- err = rxe_prepare(ack, skb, &crc);
+ err = rxe_prepare(ack, skb);
if (err) {
kfree_skb(skb);
return NULL;
}
- if (crcp) {
- /* CRC computation will be continued by the caller */
- *crcp = crc;
- } else {
- p = payload_addr(ack) + payload + bth_pad(ack);
- *p = ~crc;
- }
-
return skb;
}
@@ -682,8 +671,6 @@ static enum resp_states read_reply(struct rxe_qp *qp,
int opcode;
int err;
struct resp_res *res = qp->resp.res;
- u32 icrc;
- u32 *p;
if (!res) {
/* This is the first time we process that request. Get a
@@ -742,24 +729,20 @@ static enum resp_states read_reply(struct rxe_qp *qp,
payload = min_t(int, res->read.resid, mtu);
skb = prepare_ack_packet(qp, req_pkt, &ack_pkt, opcode, payload,
- res->cur_psn, AETH_ACK_UNLIMITED, &icrc);
+ res->cur_psn, AETH_ACK_UNLIMITED);
if (!skb)
return RESPST_ERR_RNR;
err = rxe_mr_copy(res->read.mr, res->read.va, payload_addr(&ack_pkt),
- payload, RXE_FROM_MR_OBJ, &icrc);
+ payload, RXE_FROM_MR_OBJ);
if (err)
pr_err("Failed copying memory\n");
if (bth_pad(&ack_pkt)) {
- struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
u8 *pad = payload_addr(&ack_pkt) + payload;
memset(pad, 0, bth_pad(&ack_pkt));
- icrc = rxe_crc32(rxe, icrc, pad, bth_pad(&ack_pkt));
}
- p = payload_addr(&ack_pkt) + payload + bth_pad(&ack_pkt);
- *p = ~icrc;
err = rxe_xmit_packet(qp, &ack_pkt, skb);
if (err) {
@@ -984,7 +967,7 @@ static int send_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
struct sk_buff *skb;
skb = prepare_ack_packet(qp, pkt, &ack_pkt, IB_OPCODE_RC_ACKNOWLEDGE,
- 0, psn, syndrome, NULL);
+ 0, psn, syndrome);
if (!skb) {
err = -ENOMEM;
goto err1;
@@ -1008,7 +991,7 @@ static int send_atomic_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
skb = prepare_ack_packet(qp, pkt, &ack_pkt,
IB_OPCODE_RC_ATOMIC_ACKNOWLEDGE, 0, pkt->psn,
- syndrome, NULL);
+ syndrome);
if (!skb) {
rc = -ENOMEM;
goto out;
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index c223959ac174..267b5a9c345d 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -391,59 +391,52 @@ static int rxe_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
return err;
}
-static struct ib_qp *rxe_create_qp(struct ib_pd *ibpd,
- struct ib_qp_init_attr *init,
- struct ib_udata *udata)
+static int rxe_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init,
+ struct ib_udata *udata)
{
int err;
- struct rxe_dev *rxe = to_rdev(ibpd->device);
- struct rxe_pd *pd = to_rpd(ibpd);
- struct rxe_qp *qp;
+ struct rxe_dev *rxe = to_rdev(ibqp->device);
+ struct rxe_pd *pd = to_rpd(ibqp->pd);
+ struct rxe_qp *qp = to_rqp(ibqp);
struct rxe_create_qp_resp __user *uresp = NULL;
if (udata) {
if (udata->outlen < sizeof(*uresp))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
uresp = udata->outbuf;
}
if (init->create_flags)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
err = rxe_qp_chk_init(rxe, init);
if (err)
- goto err1;
-
- qp = rxe_alloc(&rxe->qp_pool);
- if (!qp) {
- err = -ENOMEM;
- goto err1;
- }
+ return err;
if (udata) {
- if (udata->inlen) {
- err = -EINVAL;
- goto err2;
- }
+ if (udata->inlen)
+ return -EINVAL;
+
qp->is_user = true;
} else {
qp->is_user = false;
}
- rxe_add_index(qp);
+ err = rxe_add_to_pool(&rxe->qp_pool, qp);
+ if (err)
+ return err;
- err = rxe_qp_from_init(rxe, qp, pd, init, uresp, ibpd, udata);
+ rxe_add_index(qp);
+ err = rxe_qp_from_init(rxe, qp, pd, init, uresp, ibqp->pd, udata);
if (err)
- goto err3;
+ goto qp_init;
- return &qp->ibqp;
+ return 0;
-err3:
+qp_init:
rxe_drop_index(qp);
-err2:
rxe_drop_ref(qp);
-err1:
- return ERR_PTR(err);
+ return err;
}
static int rxe_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
@@ -1145,6 +1138,7 @@ static const struct ib_device_ops rxe_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ah, rxe_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, rxe_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, rxe_pd, ibpd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, rxe_qp, ibqp),
INIT_RDMA_OBJ_SIZE(ib_srq, rxe_srq, ibsrq),
INIT_RDMA_OBJ_SIZE(ib_ucontext, rxe_ucontext, ibuc),
INIT_RDMA_OBJ_SIZE(ib_mw, rxe_mw, ibmw),
@@ -1154,7 +1148,6 @@ int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name)
{
int err;
struct ib_device *dev = &rxe->ib_dev;
- struct crypto_shash *tfm;
strscpy(dev->node_desc, "rxe", sizeof(dev->node_desc));
@@ -1173,13 +1166,9 @@ int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name)
if (err)
return err;
- tfm = crypto_alloc_shash("crc32", 0, 0);
- if (IS_ERR(tfm)) {
- pr_err("failed to allocate crc algorithm err:%ld\n",
- PTR_ERR(tfm));
- return PTR_ERR(tfm);
- }
- rxe->tfm = tfm;
+ err = rxe_icrc_init(rxe);
+ if (err)
+ return err;
err = ib_register_device(dev, ibdev_name, NULL);
if (err)
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
index 959a3260fcab..ac2a2148027f 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.h
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -210,8 +210,8 @@ struct rxe_resp_info {
};
struct rxe_qp {
- struct rxe_pool_entry pelem;
struct ib_qp ibqp;
+ struct rxe_pool_entry pelem;
struct ib_qp_attr attr;
unsigned int valid;
unsigned int mtu;
diff --git a/drivers/infiniband/sw/siw/siw_main.c b/drivers/infiniband/sw/siw/siw_main.c
index cf55326f2ab4..9093e6a80b26 100644
--- a/drivers/infiniband/sw/siw/siw_main.c
+++ b/drivers/infiniband/sw/siw/siw_main.c
@@ -297,6 +297,7 @@ static const struct ib_device_ops siw_device_ops = {
INIT_RDMA_OBJ_SIZE(ib_cq, siw_cq, base_cq),
INIT_RDMA_OBJ_SIZE(ib_pd, siw_pd, base_pd),
+ INIT_RDMA_OBJ_SIZE(ib_qp, siw_qp, base_qp),
INIT_RDMA_OBJ_SIZE(ib_srq, siw_srq, base_srq),
INIT_RDMA_OBJ_SIZE(ib_ucontext, siw_ucontext, base_ucontext),
};
diff --git a/drivers/infiniband/sw/siw/siw_qp.c b/drivers/infiniband/sw/siw/siw_qp.c
index ddb2e66f9f13..7e01f2438afc 100644
--- a/drivers/infiniband/sw/siw/siw_qp.c
+++ b/drivers/infiniband/sw/siw/siw_qp.c
@@ -1344,6 +1344,4 @@ void siw_free_qp(struct kref *ref)
siw_put_tx_cpu(qp->tx_cpu);
atomic_dec(&sdev->num_qp);
- siw_dbg_qp(qp, "free QP\n");
- kfree_rcu(qp, rcu);
}
diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c
index 7989c4043db4..1f4e60257700 100644
--- a/drivers/infiniband/sw/siw/siw_qp_tx.c
+++ b/drivers/infiniband/sw/siw/siw_qp_tx.c
@@ -76,7 +76,7 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, void *paddr)
if (unlikely(!p))
return -EFAULT;
- buffer = kmap(p);
+ buffer = kmap_local_page(p);
if (likely(PAGE_SIZE - off >= bytes)) {
memcpy(paddr, buffer + off, bytes);
@@ -84,7 +84,7 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, void *paddr)
unsigned long part = bytes - (PAGE_SIZE - off);
memcpy(paddr, buffer + off, part);
- kunmap(p);
+ kunmap_local(buffer);
if (!mem->is_pbl)
p = siw_get_upage(mem->umem,
@@ -96,10 +96,10 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, void *paddr)
if (unlikely(!p))
return -EFAULT;
- buffer = kmap(p);
+ buffer = kmap_local_page(p);
memcpy(paddr + part, buffer, bytes - part);
}
- kunmap(p);
+ kunmap_local(buffer);
}
}
return (int)bytes;
@@ -396,13 +396,20 @@ static int siw_0copy_tx(struct socket *s, struct page **page,
#define MAX_TRAILER (MPA_CRC_SIZE + 4)
-static void siw_unmap_pages(struct page **pp, unsigned long kmap_mask)
+static void siw_unmap_pages(struct kvec *iov, unsigned long kmap_mask, int len)
{
- while (kmap_mask) {
- if (kmap_mask & BIT(0))
- kunmap(*pp);
- pp++;
- kmap_mask >>= 1;
+ int i;
+
+ /*
+ * Work backwards through the array to honor the kmap_local_page()
+ * ordering requirements.
+ */
+ for (i = (len-1); i >= 0; i--) {
+ if (kmap_mask & BIT(i)) {
+ unsigned long addr = (unsigned long)iov[i].iov_base;
+
+ kunmap_local((void *)(addr & PAGE_MASK));
+ }
}
}
@@ -485,6 +492,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
while (sge_len) {
size_t plen = min((int)PAGE_SIZE - fp_off, sge_len);
+ void *kaddr;
if (!is_kva) {
struct page *p;
@@ -497,7 +505,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
p = siw_get_upage(mem->umem,
sge->laddr + sge_off);
if (unlikely(!p)) {
- siw_unmap_pages(page_array, kmap_mask);
+ siw_unmap_pages(iov, kmap_mask, seg);
wqe->processed -= c_tx->bytes_unsent;
rv = -EFAULT;
goto done_crc;
@@ -505,11 +513,12 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
page_array[seg] = p;
if (!c_tx->use_sendpage) {
- iov[seg].iov_base = kmap(p) + fp_off;
- iov[seg].iov_len = plen;
+ void *kaddr = kmap_local_page(p);
/* Remember for later kunmap() */
kmap_mask |= BIT(seg);
+ iov[seg].iov_base = kaddr + fp_off;
+ iov[seg].iov_len = plen;
if (do_crc)
crypto_shash_update(
@@ -517,10 +526,11 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
iov[seg].iov_base,
plen);
} else if (do_crc) {
+ kaddr = kmap_local_page(p);
crypto_shash_update(c_tx->mpa_crc_hd,
- kmap(p) + fp_off,
+ kaddr + fp_off,
plen);
- kunmap(p);
+ kunmap_local(kaddr);
}
} else {
u64 va = sge->laddr + sge_off;
@@ -540,7 +550,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
if (++seg > (int)MAX_ARRAY) {
siw_dbg_qp(tx_qp(c_tx), "to many fragments\n");
- siw_unmap_pages(page_array, kmap_mask);
+ siw_unmap_pages(iov, kmap_mask, seg-1);
wqe->processed -= c_tx->bytes_unsent;
rv = -EMSGSIZE;
goto done_crc;
@@ -591,7 +601,7 @@ sge_done:
} else {
rv = kernel_sendmsg(s, &msg, iov, seg + 1,
hdr_len + data_len + trl_len);
- siw_unmap_pages(page_array, kmap_mask);
+ siw_unmap_pages(iov, kmap_mask, seg);
}
if (rv < (int)hdr_len) {
/* Not even complete hdr pushed or negative rv */
diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c
index 3f175f220a22..1b36350601fa 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.c
+++ b/drivers/infiniband/sw/siw/siw_verbs.c
@@ -285,16 +285,16 @@ siw_mmap_entry_insert(struct siw_ucontext *uctx,
*
* Create QP of requested size on given device.
*
- * @pd: Protection Domain
+ * @qp: Queue pait
* @attrs: Initial QP attributes.
* @udata: used to provide QP ID, SQ and RQ size back to user.
*/
-struct ib_qp *siw_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *attrs,
- struct ib_udata *udata)
+int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
+ struct ib_udata *udata)
{
- struct siw_qp *qp = NULL;
+ struct ib_pd *pd = ibqp->pd;
+ struct siw_qp *qp = to_siw_qp(ibqp);
struct ib_device *base_dev = pd->device;
struct siw_device *sdev = to_siw_dev(base_dev);
struct siw_ucontext *uctx =
@@ -307,17 +307,16 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
siw_dbg(base_dev, "create new QP\n");
if (attrs->create_flags)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
if (atomic_inc_return(&sdev->num_qp) > SIW_MAX_QP) {
siw_dbg(base_dev, "too many QP's\n");
- rv = -ENOMEM;
- goto err_out;
+ return -ENOMEM;
}
if (attrs->qp_type != IB_QPT_RC) {
siw_dbg(base_dev, "only RC QP's supported\n");
rv = -EOPNOTSUPP;
- goto err_out;
+ goto err_atomic;
}
if ((attrs->cap.max_send_wr > SIW_MAX_QP_WR) ||
(attrs->cap.max_recv_wr > SIW_MAX_QP_WR) ||
@@ -325,13 +324,13 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
(attrs->cap.max_recv_sge > SIW_MAX_SGE)) {
siw_dbg(base_dev, "QP size error\n");
rv = -EINVAL;
- goto err_out;
+ goto err_atomic;
}
if (attrs->cap.max_inline_data > SIW_MAX_INLINE) {
siw_dbg(base_dev, "max inline send: %d > %d\n",
attrs->cap.max_inline_data, (int)SIW_MAX_INLINE);
rv = -EINVAL;
- goto err_out;
+ goto err_atomic;
}
/*
* NOTE: we allow for zero element SQ and RQ WQE's SGL's
@@ -340,19 +339,15 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
if (attrs->cap.max_send_wr + attrs->cap.max_recv_wr == 0) {
siw_dbg(base_dev, "QP must have send or receive queue\n");
rv = -EINVAL;
- goto err_out;
+ goto err_atomic;
}
if (!attrs->send_cq || (!attrs->recv_cq && !attrs->srq)) {
siw_dbg(base_dev, "send CQ or receive CQ invalid\n");
rv = -EINVAL;
- goto err_out;
- }
- qp = kzalloc(sizeof(*qp), GFP_KERNEL);
- if (!qp) {
- rv = -ENOMEM;
- goto err_out;
+ goto err_atomic;
}
+
init_rwsem(&qp->state_lock);
spin_lock_init(&qp->sq_lock);
spin_lock_init(&qp->rq_lock);
@@ -360,7 +355,7 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
rv = siw_qp_add(sdev, qp);
if (rv)
- goto err_out;
+ goto err_atomic;
num_sqe = attrs->cap.max_send_wr;
num_rqe = attrs->cap.max_recv_wr;
@@ -482,23 +477,20 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
list_add_tail(&qp->devq, &sdev->qp_list);
spin_unlock_irqrestore(&sdev->lock, flags);
- return &qp->base_qp;
+ return 0;
err_out_xa:
xa_erase(&sdev->qp_xa, qp_id(qp));
-err_out:
- if (qp) {
- if (uctx) {
- rdma_user_mmap_entry_remove(qp->sq_entry);
- rdma_user_mmap_entry_remove(qp->rq_entry);
- }
- vfree(qp->sendq);
- vfree(qp->recvq);
- kfree(qp);
+ if (uctx) {
+ rdma_user_mmap_entry_remove(qp->sq_entry);
+ rdma_user_mmap_entry_remove(qp->rq_entry);
}
- atomic_dec(&sdev->num_qp);
+ vfree(qp->sendq);
+ vfree(qp->recvq);
- return ERR_PTR(rv);
+err_atomic:
+ atomic_dec(&sdev->num_qp);
+ return rv;
}
/*
diff --git a/drivers/infiniband/sw/siw/siw_verbs.h b/drivers/infiniband/sw/siw/siw_verbs.h
index 67ac08886a70..09964234f8d3 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.h
+++ b/drivers/infiniband/sw/siw/siw_verbs.h
@@ -50,9 +50,8 @@ int siw_query_gid(struct ib_device *base_dev, u32 port, int idx,
union ib_gid *gid);
int siw_alloc_pd(struct ib_pd *base_pd, struct ib_udata *udata);
int siw_dealloc_pd(struct ib_pd *base_pd, struct ib_udata *udata);
-struct ib_qp *siw_create_qp(struct ib_pd *base_pd,
- struct ib_qp_init_attr *attr,
- struct ib_udata *udata);
+int siw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attr,
+ struct ib_udata *udata);
int siw_query_qp(struct ib_qp *base_qp, struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
int siw_verbs_modify_qp(struct ib_qp *base_qp, struct ib_qp_attr *attr,
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index afec40da9b58..9776b755d848 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -159,7 +159,7 @@ iser_set_dif_domain(struct scsi_cmnd *sc, struct ib_sig_domain *domain)
{
domain->sig_type = IB_SIG_TYPE_T10_DIF;
domain->sig.dif.pi_interval = scsi_prot_interval(sc);
- domain->sig.dif.ref_tag = t10_pi_ref_tag(sc->request);
+ domain->sig.dif.ref_tag = t10_pi_ref_tag(scsi_cmd_to_rq(sc));
/*
* At the moment we hard code those, but in the future
* we will take them from sc.
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index b44cbb8e84eb..b566f7cb7797 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -949,7 +949,7 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
sector_t sector_off = mr_status.sig_err.sig_err_offset;
sector_div(sector_off, sector_size + 8);
- *sector = scsi_get_lba(iser_task->sc) + sector_off;
+ *sector = scsi_get_sector(iser_task->sc) + sector_off;
iser_err("PI error found type %d at sector %llx "
"expected %x vs actual %x\n",
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c b/drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c
index 26bbe5d6dff5..5e780bdd763d 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-stats.c
@@ -20,7 +20,7 @@ void rtrs_clt_update_wc_stats(struct rtrs_clt_con *con)
cpu = raw_smp_processor_id();
s = this_cpu_ptr(stats->pcpu_stats);
- if (unlikely(con->cpu != cpu)) {
+ if (con->cpu != cpu) {
s->cpu_migr.to++;
/* Careful here, override s pointer */
@@ -180,7 +180,7 @@ void rtrs_clt_update_all_stats(struct rtrs_clt_io_req *req, int dir)
len = req->usr_len + req->data_len;
rtrs_clt_update_rdma_stats(stats, len, dir);
- if (sess->clt->mp_policy == MP_POLICY_MIN_INFLIGHT)
+ if (req->mp_policy == MP_POLICY_MIN_INFLIGHT)
atomic_inc(&stats->inflight);
}
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index f2c40e50f25e..bc8824b4ee0d 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -75,9 +75,9 @@ __rtrs_get_permit(struct rtrs_clt *clt, enum rtrs_clt_con_type con_type)
*/
do {
bit = find_first_zero_bit(clt->permits_map, max_depth);
- if (unlikely(bit >= max_depth))
+ if (bit >= max_depth)
return NULL;
- } while (unlikely(test_and_set_bit_lock(bit, clt->permits_map)));
+ } while (test_and_set_bit_lock(bit, clt->permits_map));
permit = get_permit(clt, bit);
WARN_ON(permit->mem_id != bit);
@@ -115,14 +115,14 @@ struct rtrs_permit *rtrs_clt_get_permit(struct rtrs_clt *clt,
DEFINE_WAIT(wait);
permit = __rtrs_get_permit(clt, con_type);
- if (likely(permit) || !can_wait)
+ if (permit || !can_wait)
return permit;
do {
prepare_to_wait(&clt->permits_wait, &wait,
TASK_UNINTERRUPTIBLE);
permit = __rtrs_get_permit(clt, con_type);
- if (likely(permit))
+ if (permit)
break;
io_schedule();
@@ -175,7 +175,7 @@ struct rtrs_clt_con *rtrs_permit_to_clt_con(struct rtrs_clt_sess *sess,
{
int id = 0;
- if (likely(permit->con_type == RTRS_IO_CON))
+ if (permit->con_type == RTRS_IO_CON)
id = (permit->cpu_id % (sess->s.irq_con_num - 1)) + 1;
return to_clt_con(sess->s.con[id]);
@@ -329,7 +329,7 @@ static void rtrs_clt_fast_reg_done(struct ib_cq *cq, struct ib_wc *wc)
{
struct rtrs_clt_con *con = to_clt_con(wc->qp->qp_context);
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
rtrs_err(con->c.sess, "Failed IB_WR_REG_MR: %s\n",
ib_wc_status_msg(wc->status));
rtrs_rdma_error_recovery(con);
@@ -349,13 +349,13 @@ static void rtrs_clt_inv_rkey_done(struct ib_cq *cq, struct ib_wc *wc)
container_of(wc->wr_cqe, typeof(*req), inv_cqe);
struct rtrs_clt_con *con = to_clt_con(wc->qp->qp_context);
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
rtrs_err(con->c.sess, "Failed IB_WR_LOCAL_INV: %s\n",
ib_wc_status_msg(wc->status));
rtrs_rdma_error_recovery(con);
}
req->need_inv = false;
- if (likely(req->need_inv_comp))
+ if (req->need_inv_comp)
complete(&req->inv_comp);
else
/* Complete request from INV callback */
@@ -390,7 +390,7 @@ static void complete_rdma_req(struct rtrs_clt_io_req *req, int errno,
sess = to_clt_sess(con->c.sess);
if (req->sg_cnt) {
- if (unlikely(req->dir == DMA_FROM_DEVICE && req->need_inv)) {
+ if (req->dir == DMA_FROM_DEVICE && req->need_inv) {
/*
* We are here to invalidate read requests
* ourselves. In normal scenario server should
@@ -405,7 +405,7 @@ static void complete_rdma_req(struct rtrs_clt_io_req *req, int errno,
* should do that ourselves.
*/
- if (likely(can_wait)) {
+ if (can_wait) {
req->need_inv_comp = true;
} else {
/* This should be IO path, so always notify */
@@ -416,10 +416,10 @@ static void complete_rdma_req(struct rtrs_clt_io_req *req, int errno,
refcount_inc(&req->ref);
err = rtrs_inv_rkey(req);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(con->c.sess, "Send INV WR key=%#x: %d\n",
req->mr->rkey, err);
- } else if (likely(can_wait)) {
+ } else if (can_wait) {
wait_for_completion(&req->inv_comp);
} else {
/*
@@ -438,7 +438,7 @@ static void complete_rdma_req(struct rtrs_clt_io_req *req, int errno,
}
if (!refcount_dec_and_test(&req->ref))
return;
- if (sess->clt->mp_policy == MP_POLICY_MIN_INFLIGHT)
+ if (req->mp_policy == MP_POLICY_MIN_INFLIGHT)
atomic_dec(&sess->stats->inflight);
req->in_use = false;
@@ -463,7 +463,7 @@ static int rtrs_post_send_rdma(struct rtrs_clt_con *con,
enum ib_send_flags flags;
struct ib_sge sge;
- if (unlikely(!req->sg_size)) {
+ if (!req->sg_size) {
rtrs_wrn(con->c.sess,
"Doing RDMA Write failed, no data supplied\n");
return -EINVAL;
@@ -478,7 +478,7 @@ static int rtrs_post_send_rdma(struct rtrs_clt_con *con,
* From time to time we have to post signalled sends,
* or send queue will fill up and only QP reset can help.
*/
- flags = atomic_inc_return(&con->io_cnt) % sess->queue_depth ?
+ flags = atomic_inc_return(&con->c.wr_cnt) % sess->s.signal_interval ?
0 : IB_SEND_SIGNALED;
ib_dma_sync_single_for_device(sess->s.dev->ib_dev, req->iu->dma_addr,
@@ -513,7 +513,7 @@ static void rtrs_clt_recv_done(struct rtrs_clt_con *con, struct ib_wc *wc)
iu = container_of(wc->wr_cqe, struct rtrs_iu,
cqe);
err = rtrs_iu_post_recv(&con->c, iu);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(con->c.sess, "post iu failed %d\n", err);
rtrs_rdma_error_recovery(con);
}
@@ -533,7 +533,7 @@ static void rtrs_clt_rkey_rsp_done(struct rtrs_clt_con *con, struct ib_wc *wc)
iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe);
- if (unlikely(wc->byte_len < sizeof(*msg))) {
+ if (wc->byte_len < sizeof(*msg)) {
rtrs_err(con->c.sess, "rkey response is malformed: size %d\n",
wc->byte_len);
goto out;
@@ -541,7 +541,7 @@ static void rtrs_clt_rkey_rsp_done(struct rtrs_clt_con *con, struct ib_wc *wc)
ib_dma_sync_single_for_cpu(sess->s.dev->ib_dev, iu->dma_addr,
iu->size, DMA_FROM_DEVICE);
msg = iu->buf;
- if (unlikely(le16_to_cpu(msg->type) != RTRS_MSG_RKEY_RSP)) {
+ if (le16_to_cpu(msg->type) != RTRS_MSG_RKEY_RSP) {
rtrs_err(sess->clt, "rkey response is malformed: type %d\n",
le16_to_cpu(msg->type));
goto out;
@@ -551,8 +551,8 @@ static void rtrs_clt_rkey_rsp_done(struct rtrs_clt_con *con, struct ib_wc *wc)
goto out;
rtrs_from_imm(be32_to_cpu(wc->ex.imm_data), &imm_type, &imm_payload);
- if (likely(imm_type == RTRS_IO_RSP_IMM ||
- imm_type == RTRS_IO_RSP_W_INV_IMM)) {
+ if (imm_type == RTRS_IO_RSP_IMM ||
+ imm_type == RTRS_IO_RSP_W_INV_IMM) {
u32 msg_id;
w_inval = (imm_type == RTRS_IO_RSP_W_INV_IMM);
@@ -605,7 +605,7 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc)
bool w_inval = false;
int err;
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
if (wc->status != IB_WC_WR_FLUSH_ERR) {
rtrs_err(sess->clt, "RDMA failed: %s\n",
ib_wc_status_msg(wc->status));
@@ -625,8 +625,8 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc)
return;
rtrs_from_imm(be32_to_cpu(wc->ex.imm_data),
&imm_type, &imm_payload);
- if (likely(imm_type == RTRS_IO_RSP_IMM ||
- imm_type == RTRS_IO_RSP_W_INV_IMM)) {
+ if (imm_type == RTRS_IO_RSP_IMM ||
+ imm_type == RTRS_IO_RSP_W_INV_IMM) {
u32 msg_id;
w_inval = (imm_type == RTRS_IO_RSP_W_INV_IMM);
@@ -657,7 +657,7 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc)
err = rtrs_post_recv_empty_x2(&con->c, &io_comp_cqe);
else
err = rtrs_post_recv_empty(&con->c, &io_comp_cqe);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(con->c.sess, "rtrs_post_recv_empty(): %d\n",
err);
rtrs_rdma_error_recovery(con);
@@ -680,6 +680,7 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc)
case IB_WC_RDMA_WRITE:
/*
* post_send() RDMA write completions of IO reqs (read/write)
+ * and hb.
*/
break;
@@ -702,7 +703,7 @@ static int post_recv_io(struct rtrs_clt_con *con, size_t q_size)
} else {
err = rtrs_post_recv_empty(&con->c, &io_comp_cqe);
}
- if (unlikely(err))
+ if (err)
return err;
}
@@ -727,7 +728,7 @@ static int post_recv_sess(struct rtrs_clt_sess *sess)
q_size *= 2;
err = post_recv_io(to_clt_con(sess->s.con[cid]), q_size);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(sess->clt, "post_recv_io(), err: %d\n", err);
return err;
}
@@ -788,7 +789,7 @@ static struct rtrs_clt_sess *get_next_path_rr(struct path_it *it)
ppcpu_path = this_cpu_ptr(clt->pcpu_path);
path = rcu_dereference(*ppcpu_path);
- if (unlikely(!path))
+ if (!path)
path = list_first_or_null_rcu(&clt->paths_list,
typeof(*path), s.entry);
else
@@ -819,10 +820,10 @@ static struct rtrs_clt_sess *get_next_path_min_inflight(struct path_it *it)
int inflight;
list_for_each_entry_rcu(sess, &clt->paths_list, s.entry) {
- if (unlikely(READ_ONCE(sess->state) != RTRS_CLT_CONNECTED))
+ if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED)
continue;
- if (unlikely(!list_empty(raw_cpu_ptr(sess->mp_skip_entry))))
+ if (!list_empty(raw_cpu_ptr(sess->mp_skip_entry)))
continue;
inflight = atomic_read(&sess->stats->inflight);
@@ -870,10 +871,10 @@ static struct rtrs_clt_sess *get_next_path_min_latency(struct path_it *it)
ktime_t latency;
list_for_each_entry_rcu(sess, &clt->paths_list, s.entry) {
- if (unlikely(READ_ONCE(sess->state) != RTRS_CLT_CONNECTED))
+ if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED)
continue;
- if (unlikely(!list_empty(raw_cpu_ptr(sess->mp_skip_entry))))
+ if (!list_empty(raw_cpu_ptr(sess->mp_skip_entry)))
continue;
latency = sess->s.hb_cur_latency;
@@ -963,6 +964,7 @@ static void rtrs_clt_init_req(struct rtrs_clt_io_req *req,
req->need_inv_comp = false;
req->inv_errno = 0;
refcount_set(&req->ref, 1);
+ req->mp_policy = sess->clt->mp_policy;
iov_iter_kvec(&iter, READ, vec, 1, usr_len);
len = _copy_from_iter(req->iu->buf, usr_len, &iter);
@@ -1043,7 +1045,7 @@ static int rtrs_post_rdma_write_sg(struct rtrs_clt_con *con,
* From time to time we have to post signalled sends,
* or send queue will fill up and only QP reset can help.
*/
- flags = atomic_inc_return(&con->io_cnt) % sess->queue_depth ?
+ flags = atomic_inc_return(&con->c.wr_cnt) % sess->s.signal_interval ?
0 : IB_SEND_SIGNALED;
ib_dma_sync_single_for_device(sess->s.dev->ib_dev, req->iu->dma_addr,
@@ -1062,7 +1064,7 @@ static int rtrs_map_sg_fr(struct rtrs_clt_io_req *req, size_t count)
nr = ib_map_mr_sg(req->mr, req->sglist, count, NULL, SZ_4K);
if (nr < 0)
return nr;
- if (unlikely(nr < req->sg_cnt))
+ if (nr < req->sg_cnt)
return -EINVAL;
ib_update_fast_reg_key(req->mr, ib_inc_rkey(req->mr->rkey));
@@ -1086,7 +1088,7 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req)
const size_t tsize = sizeof(*msg) + req->data_len + req->usr_len;
- if (unlikely(tsize > sess->chunk_size)) {
+ if (tsize > sess->chunk_size) {
rtrs_wrn(s, "Write request failed, size too big %zu > %d\n",
tsize, sess->chunk_size);
return -EMSGSIZE;
@@ -1094,7 +1096,7 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req)
if (req->sg_cnt) {
count = ib_dma_map_sg(sess->s.dev->ib_dev, req->sglist,
req->sg_cnt, req->dir);
- if (unlikely(!count)) {
+ if (!count) {
rtrs_wrn(s, "Write request failed, map failed\n");
return -EINVAL;
}
@@ -1148,12 +1150,12 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req)
ret = rtrs_post_rdma_write_sg(req->con, req, rbuf, fr_en,
req->usr_len + sizeof(*msg),
imm, wr, &inv_wr);
- if (unlikely(ret)) {
+ if (ret) {
rtrs_err_rl(s,
"Write request failed: error=%d path=%s [%s:%u]\n",
ret, kobject_name(&sess->kobj), sess->hca_name,
sess->hca_port);
- if (sess->clt->mp_policy == MP_POLICY_MIN_INFLIGHT)
+ if (req->mp_policy == MP_POLICY_MIN_INFLIGHT)
atomic_dec(&sess->stats->inflight);
if (req->sg_cnt)
ib_dma_unmap_sg(sess->s.dev->ib_dev, req->sglist,
@@ -1179,7 +1181,7 @@ static int rtrs_clt_read_req(struct rtrs_clt_io_req *req)
const size_t tsize = sizeof(*msg) + req->data_len + req->usr_len;
- if (unlikely(tsize > sess->chunk_size)) {
+ if (tsize > sess->chunk_size) {
rtrs_wrn(s,
"Read request failed, message size is %zu, bigger than CHUNK_SIZE %d\n",
tsize, sess->chunk_size);
@@ -1189,7 +1191,7 @@ static int rtrs_clt_read_req(struct rtrs_clt_io_req *req)
if (req->sg_cnt) {
count = ib_dma_map_sg(dev->ib_dev, req->sglist, req->sg_cnt,
req->dir);
- if (unlikely(!count)) {
+ if (!count) {
rtrs_wrn(s,
"Read request failed, dma map failed\n");
return -EINVAL;
@@ -1254,12 +1256,12 @@ static int rtrs_clt_read_req(struct rtrs_clt_io_req *req)
ret = rtrs_post_send_rdma(req->con, req, &sess->rbufs[buf_id],
req->data_len, imm, wr);
- if (unlikely(ret)) {
+ if (ret) {
rtrs_err_rl(s,
"Read request failed: error=%d path=%s [%s:%u]\n",
ret, kobject_name(&sess->kobj), sess->hca_name,
sess->hca_port);
- if (sess->clt->mp_policy == MP_POLICY_MIN_INFLIGHT)
+ if (req->mp_policy == MP_POLICY_MIN_INFLIGHT)
atomic_dec(&sess->stats->inflight);
req->need_inv = false;
if (req->sg_cnt)
@@ -1287,15 +1289,14 @@ static int rtrs_clt_failover_req(struct rtrs_clt *clt,
for (path_it_init(&it, clt);
(alive_sess = it.next_path(&it)) && it.i < it.clt->paths_num;
it.i++) {
- if (unlikely(READ_ONCE(alive_sess->state) !=
- RTRS_CLT_CONNECTED))
+ if (READ_ONCE(alive_sess->state) != RTRS_CLT_CONNECTED)
continue;
req = rtrs_clt_get_copy_req(alive_sess, fail_req);
if (req->dir == DMA_TO_DEVICE)
err = rtrs_clt_write_req(req);
else
err = rtrs_clt_read_req(req);
- if (unlikely(err)) {
+ if (err) {
req->in_use = false;
continue;
}
@@ -1330,7 +1331,7 @@ static void fail_all_outstanding_reqs(struct rtrs_clt_sess *sess)
complete_rdma_req(req, -ECONNABORTED, false, true);
err = rtrs_clt_failover_req(clt, req);
- if (unlikely(err))
+ if (err)
/* Failover failed, notify anyway */
req->conf(req->priv, err);
}
@@ -1601,7 +1602,8 @@ static int create_con(struct rtrs_clt_sess *sess, unsigned int cid)
con->cpu = (cid ? cid - 1 : 0) % nr_cpu_ids;
con->c.cid = cid;
con->c.sess = &sess->s;
- atomic_set(&con->io_cnt, 0);
+ /* Align with srv, init as 1 */
+ atomic_set(&con->c.wr_cnt, 1);
mutex_init(&con->con_mutex);
sess->s.con[cid] = &con->c;
@@ -1678,6 +1680,7 @@ static int create_con_cq_qp(struct rtrs_clt_con *con)
sess->queue_depth * 3 + 1);
max_send_sge = 2;
}
+ atomic_set(&con->c.sq_wr_avail, max_send_wr);
cq_num = max_send_wr + max_recv_wr;
/* alloc iu to recv new rkey reply when server reports flags set */
if (sess->flags & RTRS_MSG_NEW_RKEY_F || con->c.cid == 0) {
@@ -1841,13 +1844,14 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con,
}
if (!sess->rbufs) {
- kfree(sess->rbufs);
sess->rbufs = kcalloc(queue_depth, sizeof(*sess->rbufs),
GFP_KERNEL);
if (!sess->rbufs)
return -ENOMEM;
}
sess->queue_depth = queue_depth;
+ sess->s.signal_interval = min_not_zero(queue_depth,
+ (unsigned short) SERVICE_CON_QUEUE_DEPTH);
sess->max_hdr_size = le32_to_cpu(msg->max_hdr_size);
sess->max_io_size = le32_to_cpu(msg->max_io_size);
sess->flags = le32_to_cpu(msg->flags);
@@ -1958,7 +1962,7 @@ static int rtrs_clt_rdma_cm_handler(struct rdma_cm_id *cm_id,
break;
case RDMA_CM_EVENT_ESTABLISHED:
cm_err = rtrs_rdma_conn_established(con, ev);
- if (likely(!cm_err)) {
+ if (!cm_err) {
/*
* Report success and wake up. Here we abuse state_wq,
* i.e. wake up without state change, but we set cm_err.
@@ -2377,7 +2381,7 @@ static void rtrs_clt_info_req_done(struct ib_cq *cq, struct ib_wc *wc)
iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe);
rtrs_iu_free(iu, sess->s.dev->ib_dev, 1);
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
rtrs_err(sess->clt, "Sess info request send failed: %s\n",
ib_wc_status_msg(wc->status));
rtrs_clt_change_state_get_old(sess, RTRS_CLT_CONNECTING_ERR, NULL);
@@ -2394,7 +2398,7 @@ static int process_info_rsp(struct rtrs_clt_sess *sess,
int i, sgi;
sg_cnt = le16_to_cpu(msg->sg_cnt);
- if (unlikely(!sg_cnt || (sess->queue_depth % sg_cnt))) {
+ if (!sg_cnt || (sess->queue_depth % sg_cnt)) {
rtrs_err(sess->clt, "Incorrect sg_cnt %d, is not multiple\n",
sg_cnt);
return -EINVAL;
@@ -2404,9 +2408,8 @@ static int process_info_rsp(struct rtrs_clt_sess *sess,
* Check if IB immediate data size is enough to hold the mem_id and
* the offset inside the memory chunk.
*/
- if (unlikely((ilog2(sg_cnt - 1) + 1) +
- (ilog2(sess->chunk_size - 1) + 1) >
- MAX_IMM_PAYL_BITS)) {
+ if ((ilog2(sg_cnt - 1) + 1) + (ilog2(sess->chunk_size - 1) + 1) >
+ MAX_IMM_PAYL_BITS) {
rtrs_err(sess->clt,
"RDMA immediate size (%db) not enough to encode %d buffers of size %dB\n",
MAX_IMM_PAYL_BITS, sg_cnt, sess->chunk_size);
@@ -2424,7 +2427,7 @@ static int process_info_rsp(struct rtrs_clt_sess *sess,
total_len += len;
- if (unlikely(!len || (len % sess->chunk_size))) {
+ if (!len || (len % sess->chunk_size)) {
rtrs_err(sess->clt, "Incorrect [%d].len %d\n", sgi,
len);
return -EINVAL;
@@ -2438,11 +2441,11 @@ static int process_info_rsp(struct rtrs_clt_sess *sess,
}
}
/* Sanity check */
- if (unlikely(sgi != sg_cnt || i != sess->queue_depth)) {
+ if (sgi != sg_cnt || i != sess->queue_depth) {
rtrs_err(sess->clt, "Incorrect sg vector, not fully mapped\n");
return -EINVAL;
}
- if (unlikely(total_len != sess->chunk_size * sess->queue_depth)) {
+ if (total_len != sess->chunk_size * sess->queue_depth) {
rtrs_err(sess->clt, "Incorrect total_len %d\n", total_len);
return -EINVAL;
}
@@ -2464,14 +2467,14 @@ static void rtrs_clt_info_rsp_done(struct ib_cq *cq, struct ib_wc *wc)
WARN_ON(con->c.cid);
iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe);
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
rtrs_err(sess->clt, "Sess info response recv failed: %s\n",
ib_wc_status_msg(wc->status));
goto out;
}
WARN_ON(wc->opcode != IB_WC_RECV);
- if (unlikely(wc->byte_len < sizeof(*msg))) {
+ if (wc->byte_len < sizeof(*msg)) {
rtrs_err(sess->clt, "Sess info response is malformed: size %d\n",
wc->byte_len);
goto out;
@@ -2479,24 +2482,24 @@ static void rtrs_clt_info_rsp_done(struct ib_cq *cq, struct ib_wc *wc)
ib_dma_sync_single_for_cpu(sess->s.dev->ib_dev, iu->dma_addr,
iu->size, DMA_FROM_DEVICE);
msg = iu->buf;
- if (unlikely(le16_to_cpu(msg->type) != RTRS_MSG_INFO_RSP)) {
+ if (le16_to_cpu(msg->type) != RTRS_MSG_INFO_RSP) {
rtrs_err(sess->clt, "Sess info response is malformed: type %d\n",
le16_to_cpu(msg->type));
goto out;
}
rx_sz = sizeof(*msg);
rx_sz += sizeof(msg->desc[0]) * le16_to_cpu(msg->sg_cnt);
- if (unlikely(wc->byte_len < rx_sz)) {
+ if (wc->byte_len < rx_sz) {
rtrs_err(sess->clt, "Sess info response is malformed: size %d\n",
wc->byte_len);
goto out;
}
err = process_info_rsp(sess, msg);
- if (unlikely(err))
+ if (err)
goto out;
err = post_recv_sess(sess);
- if (unlikely(err))
+ if (err)
goto out;
state = RTRS_CLT_CONNECTED;
@@ -2523,13 +2526,13 @@ static int rtrs_send_sess_info(struct rtrs_clt_sess *sess)
rtrs_clt_info_req_done);
rx_iu = rtrs_iu_alloc(1, rx_sz, GFP_KERNEL, sess->s.dev->ib_dev,
DMA_FROM_DEVICE, rtrs_clt_info_rsp_done);
- if (unlikely(!tx_iu || !rx_iu)) {
+ if (!tx_iu || !rx_iu) {
err = -ENOMEM;
goto out;
}
/* Prepare for getting info response */
err = rtrs_iu_post_recv(&usr_con->c, rx_iu);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(sess->clt, "rtrs_iu_post_recv(), err: %d\n", err);
goto out;
}
@@ -2544,7 +2547,7 @@ static int rtrs_send_sess_info(struct rtrs_clt_sess *sess)
/* Send info request */
err = rtrs_iu_post_send(&usr_con->c, tx_iu, sizeof(*msg), NULL);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(sess->clt, "rtrs_iu_post_send(), err: %d\n", err);
goto out;
}
@@ -2555,7 +2558,7 @@ static int rtrs_send_sess_info(struct rtrs_clt_sess *sess)
sess->state != RTRS_CLT_CONNECTING,
msecs_to_jiffies(
RTRS_CONNECT_TIMEOUT_MS));
- if (unlikely(READ_ONCE(sess->state) != RTRS_CLT_CONNECTED)) {
+ if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED) {
if (READ_ONCE(sess->state) == RTRS_CLT_CONNECTING_ERR)
err = -ECONNRESET;
else
@@ -2567,7 +2570,7 @@ out:
rtrs_iu_free(tx_iu, sess->s.dev->ib_dev, 1);
if (rx_iu)
rtrs_iu_free(rx_iu, sess->s.dev->ib_dev, 1);
- if (unlikely(err))
+ if (err)
/* If we've never taken async path because of malloc problems */
rtrs_clt_change_state_get_old(sess, RTRS_CLT_CONNECTING_ERR, NULL);
@@ -2915,7 +2918,7 @@ int rtrs_clt_remove_path_from_sysfs(struct rtrs_clt_sess *sess,
&old_state);
} while (!changed && old_state != RTRS_CLT_DEAD);
- if (likely(changed)) {
+ if (changed) {
rtrs_clt_remove_path_from_arr(sess);
rtrs_clt_destroy_sess_files(sess, sysfs_self);
kobject_put(&sess->kobj);
@@ -2987,10 +2990,10 @@ int rtrs_clt_request(int dir, struct rtrs_clt_req_ops *ops,
rcu_read_lock();
for (path_it_init(&it, clt);
(sess = it.next_path(&it)) && it.i < it.clt->paths_num; it.i++) {
- if (unlikely(READ_ONCE(sess->state) != RTRS_CLT_CONNECTED))
+ if (READ_ONCE(sess->state) != RTRS_CLT_CONNECTED)
continue;
- if (unlikely(usr_len + hdr_len > sess->max_hdr_size)) {
+ if (usr_len + hdr_len > sess->max_hdr_size) {
rtrs_wrn_rl(sess->clt,
"%s request failed, user message size is %zu and header length %zu, but max size is %u\n",
dir == READ ? "Read" : "Write",
@@ -3005,7 +3008,7 @@ int rtrs_clt_request(int dir, struct rtrs_clt_req_ops *ops,
err = rtrs_clt_read_req(req);
else
err = rtrs_clt_write_req(req);
- if (unlikely(err)) {
+ if (err) {
req->in_use = false;
continue;
}
@@ -3078,6 +3081,18 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt *clt,
if (IS_ERR(sess))
return PTR_ERR(sess);
+ mutex_lock(&clt->paths_mutex);
+ if (clt->paths_num == 0) {
+ /*
+ * When all the paths are removed for a session,
+ * the addition of the first path is like a new session for
+ * the storage server
+ */
+ sess->for_new_clt = 1;
+ }
+
+ mutex_unlock(&clt->paths_mutex);
+
/*
* It is totally safe to add path in CONNECTING state: coming
* IO will never grab it. Also it is very important to add
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.h b/drivers/infiniband/ulp/rtrs/rtrs-clt.h
index e276a2dfcf7c..9dc819885ec7 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.h
@@ -74,7 +74,6 @@ struct rtrs_clt_con {
u32 queue_num;
unsigned int cpu;
struct mutex con_mutex;
- atomic_t io_cnt;
int cm_err;
};
@@ -102,6 +101,7 @@ struct rtrs_clt_io_req {
unsigned int usr_len;
void *priv;
bool in_use;
+ enum rtrs_mp_policy mp_policy;
struct rtrs_clt_con *con;
struct rtrs_sg_desc *desc;
struct ib_sge *sge;
@@ -230,10 +230,7 @@ int rtrs_clt_stats_migration_cnt_to_str(struct rtrs_clt_stats *stats, char *buf,
size_t len);
int rtrs_clt_reset_reconnects_stat(struct rtrs_clt_stats *stats, bool enable);
int rtrs_clt_stats_reconnects_to_str(struct rtrs_clt_stats *stats, char *buf,
- size_t len);
-int rtrs_clt_reset_wc_comp_stats(struct rtrs_clt_stats *stats, bool enable);
-int rtrs_clt_stats_wc_completion_to_str(struct rtrs_clt_stats *stats, char *buf,
- size_t len);
+ size_t len);
int rtrs_clt_reset_rdma_stats(struct rtrs_clt_stats *stats, bool enable);
ssize_t rtrs_clt_stats_rdma_to_str(struct rtrs_clt_stats *stats,
char *page, size_t len);
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-pri.h b/drivers/infiniband/ulp/rtrs/rtrs-pri.h
index 36f184a3b676..d12ddfa50747 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-pri.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs-pri.h
@@ -96,6 +96,8 @@ struct rtrs_con {
struct rdma_cm_id *cm_id;
unsigned int cid;
int nr_cqe;
+ atomic_t wr_cnt;
+ atomic_t sq_wr_avail;
};
struct rtrs_sess {
@@ -108,6 +110,7 @@ struct rtrs_sess {
unsigned int con_num;
unsigned int irq_con_num;
unsigned int recon_cnt;
+ unsigned int signal_interval;
struct rtrs_ib_dev *dev;
int dev_ref;
struct ib_cqe *hb_cqe;
@@ -309,9 +312,6 @@ int rtrs_iu_post_rdma_write_imm(struct rtrs_con *con, struct rtrs_iu *iu,
struct ib_send_wr *tail);
int rtrs_post_recv_empty(struct rtrs_con *con, struct ib_cqe *cqe);
-int rtrs_post_rdma_write_imm_empty(struct rtrs_con *con, struct ib_cqe *cqe,
- u32 imm_data, enum ib_send_flags flags,
- struct ib_send_wr *head);
int rtrs_cq_qp_create(struct rtrs_sess *sess, struct rtrs_con *con,
u32 max_send_sge, int cq_vector, int nr_cqe,
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
index 3df290086169..716ef7b23558 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -183,7 +183,7 @@ static void rtrs_srv_reg_mr_done(struct ib_cq *cq, struct ib_wc *wc)
struct rtrs_sess *s = con->c.sess;
struct rtrs_srv_sess *sess = to_srv_sess(s);
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
rtrs_err(s, "REG MR failed: %s\n",
ib_wc_status_msg(wc->status));
close_sess(sess);
@@ -201,7 +201,6 @@ static int rdma_write_sg(struct rtrs_srv_op *id)
struct rtrs_srv_sess *sess = to_srv_sess(s);
dma_addr_t dma_addr = sess->dma_addr[id->msg_id];
struct rtrs_srv_mr *srv_mr;
- struct rtrs_srv *srv = sess->srv;
struct ib_send_wr inv_wr;
struct ib_rdma_wr imm_wr;
struct ib_rdma_wr *wr = NULL;
@@ -216,7 +215,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id)
sg_cnt = le16_to_cpu(id->rd_msg->sg_cnt);
need_inval = le16_to_cpu(id->rd_msg->flags) & RTRS_MSG_NEED_INVAL_F;
- if (unlikely(sg_cnt != 1))
+ if (sg_cnt != 1)
return -EINVAL;
offset = 0;
@@ -229,7 +228,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id)
/* WR will fail with length error
* if this is 0
*/
- if (unlikely(plist->length == 0)) {
+ if (plist->length == 0) {
rtrs_err(s, "Invalid RDMA-Write sg list length 0\n");
return -EINVAL;
}
@@ -269,7 +268,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id)
* From time to time we have to post signaled sends,
* or send queue will fill up and only QP reset can help.
*/
- flags = (atomic_inc_return(&id->con->wr_cnt) % srv->queue_depth) ?
+ flags = (atomic_inc_return(&id->con->c.wr_cnt) % s->signal_interval) ?
0 : IB_SEND_SIGNALED;
if (need_inval) {
@@ -322,7 +321,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id)
offset, DMA_BIDIRECTIONAL);
err = ib_post_send(id->con->c.qp, &id->tx_wr.wr, NULL);
- if (unlikely(err))
+ if (err)
rtrs_err(s,
"Posting RDMA-Write-Request to QP failed, err: %d\n",
err);
@@ -347,7 +346,6 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
struct ib_send_wr inv_wr, *wr = NULL;
struct ib_rdma_wr imm_wr;
struct ib_reg_wr rwr;
- struct rtrs_srv *srv = sess->srv;
struct rtrs_srv_mr *srv_mr;
bool need_inval = false;
enum ib_send_flags flags;
@@ -363,7 +361,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
sg_cnt = le16_to_cpu(rd_msg->sg_cnt);
if (need_inval) {
- if (likely(sg_cnt)) {
+ if (sg_cnt) {
inv_wr.wr_cqe = &io_comp_cqe;
inv_wr.sg_list = NULL;
inv_wr.num_sge = 0;
@@ -396,7 +394,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
* From time to time we have to post signalled sends,
* or send queue will fill up and only QP reset can help.
*/
- flags = (atomic_inc_return(&con->wr_cnt) % srv->queue_depth) ?
+ flags = (atomic_inc_return(&con->c.wr_cnt) % s->signal_interval) ?
0 : IB_SEND_SIGNALED;
imm = rtrs_to_io_rsp_imm(id->msg_id, errno, need_inval);
imm_wr.wr.next = NULL;
@@ -439,7 +437,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
imm_wr.wr.ex.imm_data = cpu_to_be32(imm);
err = ib_post_send(id->con->c.qp, wr, NULL);
- if (unlikely(err))
+ if (err)
rtrs_err_rl(s, "Posting RDMA-Reply to QP failed, err: %d\n",
err);
@@ -496,7 +494,7 @@ bool rtrs_srv_resp_rdma(struct rtrs_srv_op *id, int status)
id->status = status;
- if (unlikely(sess->state != RTRS_SRV_CONNECTED)) {
+ if (sess->state != RTRS_SRV_CONNECTED) {
rtrs_err_rl(s,
"Sending I/O response failed, session %s is disconnected, sess state %s\n",
kobject_name(&sess->kobj),
@@ -508,12 +506,11 @@ bool rtrs_srv_resp_rdma(struct rtrs_srv_op *id, int status)
ib_update_fast_reg_key(mr->mr, ib_inc_rkey(mr->mr->rkey));
}
- if (unlikely(atomic_sub_return(1,
- &con->sq_wr_avail) < 0)) {
+ if (atomic_sub_return(1, &con->c.sq_wr_avail) < 0) {
rtrs_err(s, "IB send queue full: sess=%s cid=%d\n",
kobject_name(&sess->kobj),
con->c.cid);
- atomic_add(1, &con->sq_wr_avail);
+ atomic_add(1, &con->c.sq_wr_avail);
spin_lock(&con->rsp_wr_wait_lock);
list_add_tail(&id->wait_list, &con->rsp_wr_wait_list);
spin_unlock(&con->rsp_wr_wait_lock);
@@ -525,7 +522,7 @@ bool rtrs_srv_resp_rdma(struct rtrs_srv_op *id, int status)
else
err = rdma_write_sg(id);
- if (unlikely(err)) {
+ if (err) {
rtrs_err_rl(s, "IO response failed: %d: sess=%s\n", err,
kobject_name(&sess->kobj));
close_sess(sess);
@@ -712,7 +709,7 @@ static void rtrs_srv_info_rsp_done(struct ib_cq *cq, struct ib_wc *wc)
iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe);
rtrs_iu_free(iu, sess->s.dev->ib_dev, 1);
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
rtrs_err(s, "Sess info response send failed: %s\n",
ib_wc_status_msg(wc->status));
close_sess(sess);
@@ -801,7 +798,7 @@ static int process_info_req(struct rtrs_srv_con *con,
size_t tx_sz;
err = post_recv_sess(sess);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(s, "post_recv_sess(), err: %d\n", err);
return err;
}
@@ -814,14 +811,14 @@ static int process_info_req(struct rtrs_srv_con *con,
strscpy(sess->s.sessname, msg->sessname, sizeof(sess->s.sessname));
rwr = kcalloc(sess->mrs_num, sizeof(*rwr), GFP_KERNEL);
- if (unlikely(!rwr))
+ if (!rwr)
return -ENOMEM;
tx_sz = sizeof(*rsp);
tx_sz += sizeof(rsp->desc[0]) * sess->mrs_num;
tx_iu = rtrs_iu_alloc(1, tx_sz, GFP_KERNEL, sess->s.dev->ib_dev,
DMA_TO_DEVICE, rtrs_srv_info_rsp_done);
- if (unlikely(!tx_iu)) {
+ if (!tx_iu) {
err = -ENOMEM;
goto rwr_free;
}
@@ -853,7 +850,7 @@ static int process_info_req(struct rtrs_srv_con *con,
}
err = rtrs_srv_create_sess_files(sess);
- if (unlikely(err))
+ if (err)
goto iu_free;
kobject_get(&sess->kobj);
get_device(&sess->srv->dev);
@@ -873,7 +870,7 @@ static int process_info_req(struct rtrs_srv_con *con,
/* Send info response */
err = rtrs_iu_post_send(&con->c, tx_iu, tx_sz, reg_wr);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(s, "rtrs_iu_post_send(), err: %d\n", err);
iu_free:
rtrs_iu_free(tx_iu, sess->s.dev->ib_dev, 1);
@@ -896,14 +893,14 @@ static void rtrs_srv_info_req_done(struct ib_cq *cq, struct ib_wc *wc)
WARN_ON(con->c.cid);
iu = container_of(wc->wr_cqe, struct rtrs_iu, cqe);
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
rtrs_err(s, "Sess info request receive failed: %s\n",
ib_wc_status_msg(wc->status));
goto close;
}
WARN_ON(wc->opcode != IB_WC_RECV);
- if (unlikely(wc->byte_len < sizeof(*msg))) {
+ if (wc->byte_len < sizeof(*msg)) {
rtrs_err(s, "Sess info request is malformed: size %d\n",
wc->byte_len);
goto close;
@@ -911,13 +908,13 @@ static void rtrs_srv_info_req_done(struct ib_cq *cq, struct ib_wc *wc)
ib_dma_sync_single_for_cpu(sess->s.dev->ib_dev, iu->dma_addr,
iu->size, DMA_FROM_DEVICE);
msg = iu->buf;
- if (unlikely(le16_to_cpu(msg->type) != RTRS_MSG_INFO_REQ)) {
+ if (le16_to_cpu(msg->type) != RTRS_MSG_INFO_REQ) {
rtrs_err(s, "Sess info request is malformed: type %d\n",
le16_to_cpu(msg->type));
goto close;
}
err = process_info_req(con, msg);
- if (unlikely(err))
+ if (err)
goto close;
out:
@@ -938,11 +935,11 @@ static int post_recv_info_req(struct rtrs_srv_con *con)
rx_iu = rtrs_iu_alloc(1, sizeof(struct rtrs_msg_info_req),
GFP_KERNEL, sess->s.dev->ib_dev,
DMA_FROM_DEVICE, rtrs_srv_info_req_done);
- if (unlikely(!rx_iu))
+ if (!rx_iu)
return -ENOMEM;
/* Prepare for getting info response */
err = rtrs_iu_post_recv(&con->c, rx_iu);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(s, "rtrs_iu_post_recv(), err: %d\n", err);
rtrs_iu_free(rx_iu, sess->s.dev->ib_dev, 1);
return err;
@@ -957,7 +954,7 @@ static int post_recv_io(struct rtrs_srv_con *con, size_t q_size)
for (i = 0; i < q_size; i++) {
err = rtrs_post_recv_empty(&con->c, &io_comp_cqe);
- if (unlikely(err))
+ if (err)
return err;
}
@@ -978,7 +975,7 @@ static int post_recv_sess(struct rtrs_srv_sess *sess)
q_size = srv->queue_depth;
err = post_recv_io(to_srv_con(sess->s.con[cid]), q_size);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(s, "post_recv_io(), err: %d\n", err);
return err;
}
@@ -1001,13 +998,13 @@ static void process_read(struct rtrs_srv_con *con,
void *data;
int ret;
- if (unlikely(sess->state != RTRS_SRV_CONNECTED)) {
+ if (sess->state != RTRS_SRV_CONNECTED) {
rtrs_err_rl(s,
"Processing read request failed, session is disconnected, sess state %s\n",
rtrs_srv_state_str(sess->state));
return;
}
- if (unlikely(msg->sg_cnt != 1 && msg->sg_cnt != 0)) {
+ if (msg->sg_cnt != 1 && msg->sg_cnt != 0) {
rtrs_err_rl(s,
"Processing read request failed, invalid message\n");
return;
@@ -1025,7 +1022,7 @@ static void process_read(struct rtrs_srv_con *con,
ret = ctx->ops.rdma_ev(srv->priv, id, READ, data, data_len,
data + data_len, usr_len);
- if (unlikely(ret)) {
+ if (ret) {
rtrs_err_rl(s,
"Processing read request failed, user module cb reported for msg_id %d, err: %d\n",
buf_id, ret);
@@ -1059,7 +1056,7 @@ static void process_write(struct rtrs_srv_con *con,
void *data;
int ret;
- if (unlikely(sess->state != RTRS_SRV_CONNECTED)) {
+ if (sess->state != RTRS_SRV_CONNECTED) {
rtrs_err_rl(s,
"Processing write request failed, session is disconnected, sess state %s\n",
rtrs_srv_state_str(sess->state));
@@ -1076,8 +1073,8 @@ static void process_write(struct rtrs_srv_con *con,
data_len = off - usr_len;
data = page_address(srv->chunks[buf_id]);
ret = ctx->ops.rdma_ev(srv->priv, id, WRITE, data, data_len,
- data + data_len, usr_len);
- if (unlikely(ret)) {
+ data + data_len, usr_len);
+ if (ret) {
rtrs_err_rl(s,
"Processing write request failed, user module callback reports err: %d\n",
ret);
@@ -1141,7 +1138,7 @@ static void rtrs_srv_inv_rkey_done(struct ib_cq *cq, struct ib_wc *wc)
u32 msg_id, off;
void *data;
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
rtrs_err(s, "Failed IB_WR_LOCAL_INV: %s\n",
ib_wc_status_msg(wc->status));
close_sess(sess);
@@ -1198,7 +1195,7 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc)
u32 imm_type, imm_payload;
int err;
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ if (wc->status != IB_WC_SUCCESS) {
if (wc->status != IB_WC_WR_FLUSH_ERR) {
rtrs_err(s,
"%s (wr_cqe: %p, type: %d, vendor_err: 0x%x, len: %u)\n",
@@ -1218,21 +1215,20 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc)
if (WARN_ON(wc->wr_cqe != &io_comp_cqe))
return;
err = rtrs_post_recv_empty(&con->c, &io_comp_cqe);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(s, "rtrs_post_recv(), err: %d\n", err);
close_sess(sess);
break;
}
rtrs_from_imm(be32_to_cpu(wc->ex.imm_data),
&imm_type, &imm_payload);
- if (likely(imm_type == RTRS_IO_REQ_IMM)) {
+ if (imm_type == RTRS_IO_REQ_IMM) {
u32 msg_id, off;
void *data;
msg_id = imm_payload >> sess->mem_bits;
off = imm_payload & ((1 << sess->mem_bits) - 1);
- if (unlikely(msg_id >= srv->queue_depth ||
- off >= max_chunk_size)) {
+ if (msg_id >= srv->queue_depth || off >= max_chunk_size) {
rtrs_err(s, "Wrong msg_id %u, off %u\n",
msg_id, off);
close_sess(sess);
@@ -1244,7 +1240,7 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc)
mr->msg_off = off;
mr->msg_id = msg_id;
err = rtrs_srv_inv_rkey(con, mr);
- if (unlikely(err)) {
+ if (err) {
rtrs_err(s, "rtrs_post_recv(), err: %d\n",
err);
close_sess(sess);
@@ -1268,10 +1264,11 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc)
case IB_WC_SEND:
/*
* post_send() RDMA write completions of IO reqs (read/write)
+ * and hb.
*/
- atomic_add(srv->queue_depth, &con->sq_wr_avail);
+ atomic_add(s->signal_interval, &con->c.sq_wr_avail);
- if (unlikely(!list_empty_careful(&con->rsp_wr_wait_list)))
+ if (!list_empty_careful(&con->rsp_wr_wait_list))
rtrs_rdma_process_wr_wait_list(con);
break;
@@ -1648,7 +1645,7 @@ static int create_con(struct rtrs_srv_sess *sess,
con->c.cm_id = cm_id;
con->c.sess = &sess->s;
con->c.cid = cid;
- atomic_set(&con->wr_cnt, 1);
+ atomic_set(&con->c.wr_cnt, 1);
wr_limit = sess->s.dev->ib_dev->attrs.max_qp_wr;
if (con->c.cid == 0) {
@@ -1659,6 +1656,8 @@ static int create_con(struct rtrs_srv_sess *sess,
max_send_wr = min_t(int, wr_limit,
SERVICE_CON_QUEUE_DEPTH * 2 + 2);
max_recv_wr = max_send_wr;
+ s->signal_interval = min_not_zero(srv->queue_depth,
+ (size_t)SERVICE_CON_QUEUE_DEPTH);
} else {
/* when always_invlaidate enalbed, we need linv+rinv+mr+imm */
if (always_invalidate)
@@ -1679,7 +1678,7 @@ static int create_con(struct rtrs_srv_sess *sess,
*/
}
cq_num = max_send_wr + max_recv_wr;
- atomic_set(&con->sq_wr_avail, max_send_wr);
+ atomic_set(&con->c.sq_wr_avail, max_send_wr);
cq_vector = rtrs_srv_get_next_cq_vector(sess);
/* TODO: SOFTIRQ can be faster, but be careful with softirq context */
@@ -1894,7 +1893,7 @@ static int rtrs_rdma_connect(struct rdma_cm_id *cm_id,
err = create_con(sess, cm_id, cid);
if (err) {
rtrs_err((&sess->s), "create_con(), error %d\n", err);
- (void)rtrs_rdma_do_reject(cm_id, err);
+ rtrs_rdma_do_reject(cm_id, err);
/*
* Since session has other connections we follow normal way
* through workqueue, but still return an error to tell cma.c
@@ -1905,7 +1904,7 @@ static int rtrs_rdma_connect(struct rdma_cm_id *cm_id,
err = rtrs_rdma_do_accept(sess, cm_id);
if (err) {
rtrs_err((&sess->s), "rtrs_rdma_do_accept(), error %d\n", err);
- (void)rtrs_rdma_do_reject(cm_id, err);
+ rtrs_rdma_do_reject(cm_id, err);
/*
* Since current connection was successfully added to the
* session we follow normal way through workqueue to close the
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.h b/drivers/infiniband/ulp/rtrs/rtrs-srv.h
index f8da2e3f0bda..9d8d2a91a235 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.h
@@ -42,8 +42,6 @@ struct rtrs_srv_stats {
struct rtrs_srv_con {
struct rtrs_con c;
- atomic_t wr_cnt;
- atomic_t sq_wr_avail;
struct list_head rsp_wr_wait_list;
spinlock_t rsp_wr_wait_lock;
};
@@ -140,10 +138,6 @@ static inline void rtrs_srv_update_rdma_stats(struct rtrs_srv_stats *s,
int rtrs_srv_reset_rdma_stats(struct rtrs_srv_stats *stats, bool enable);
ssize_t rtrs_srv_stats_rdma_to_str(struct rtrs_srv_stats *stats,
char *page, size_t len);
-int rtrs_srv_reset_wc_completion_stats(struct rtrs_srv_stats *stats,
- bool enable);
-int rtrs_srv_stats_wc_completion_to_str(struct rtrs_srv_stats *stats, char *buf,
- size_t len);
int rtrs_srv_reset_all_stats(struct rtrs_srv_stats *stats, bool enable);
ssize_t rtrs_srv_reset_all_help(struct rtrs_srv_stats *stats,
char *page, size_t len);
diff --git a/drivers/infiniband/ulp/rtrs/rtrs.c b/drivers/infiniband/ulp/rtrs/rtrs.c
index 61919ebd92b2..ca542e477d38 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs.c
@@ -182,22 +182,28 @@ int rtrs_iu_post_rdma_write_imm(struct rtrs_con *con, struct rtrs_iu *iu,
}
EXPORT_SYMBOL_GPL(rtrs_iu_post_rdma_write_imm);
-int rtrs_post_rdma_write_imm_empty(struct rtrs_con *con, struct ib_cqe *cqe,
- u32 imm_data, enum ib_send_flags flags,
- struct ib_send_wr *head)
+static int rtrs_post_rdma_write_imm_empty(struct rtrs_con *con,
+ struct ib_cqe *cqe,
+ u32 imm_data,
+ struct ib_send_wr *head)
{
struct ib_rdma_wr wr;
+ struct rtrs_sess *sess = con->sess;
+ enum ib_send_flags sflags;
+
+ atomic_dec_if_positive(&con->sq_wr_avail);
+ sflags = (atomic_inc_return(&con->wr_cnt) % sess->signal_interval) ?
+ 0 : IB_SEND_SIGNALED;
wr = (struct ib_rdma_wr) {
.wr.wr_cqe = cqe,
- .wr.send_flags = flags,
+ .wr.send_flags = sflags,
.wr.opcode = IB_WR_RDMA_WRITE_WITH_IMM,
.wr.ex.imm_data = cpu_to_be32(imm_data),
};
return rtrs_post_send(con->qp, head, &wr.wr, NULL);
}
-EXPORT_SYMBOL_GPL(rtrs_post_rdma_write_imm_empty);
static void qp_event_handler(struct ib_event *ev, void *ctx)
{
@@ -314,8 +320,9 @@ void rtrs_send_hb_ack(struct rtrs_sess *sess)
imm = rtrs_to_imm(RTRS_HB_ACK_IMM, 0);
err = rtrs_post_rdma_write_imm_empty(usr_con, sess->hb_cqe, imm,
- 0, NULL);
+ NULL);
if (err) {
+ rtrs_err(sess, "send HB ACK failed, errno: %d\n", err);
sess->hb_err_handler(usr_con);
return;
}
@@ -333,6 +340,7 @@ static void hb_work(struct work_struct *work)
usr_con = sess->con[0];
if (sess->hb_missed_cnt > sess->hb_missed_max) {
+ rtrs_err(sess, "HB missed max reached.\n");
sess->hb_err_handler(usr_con);
return;
}
@@ -346,8 +354,9 @@ static void hb_work(struct work_struct *work)
imm = rtrs_to_imm(RTRS_HB_MSG_IMM, 0);
err = rtrs_post_rdma_write_imm_empty(usr_con, sess->hb_cqe, imm,
- 0, NULL);
+ NULL);
if (err) {
+ rtrs_err(sess, "HB send failed, errno: %d\n", err);
sess->hb_err_handler(usr_con);
return;
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 8d5cf5eb5778..71eda91e810c 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1280,7 +1280,7 @@ static bool srp_terminate_cmd(struct scsi_cmnd *scmnd, void *context_ptr,
{
struct srp_terminate_context *context = context_ptr;
struct srp_target_port *target = context->srp_target;
- u32 tag = blk_mq_unique_tag(scmnd->request);
+ u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmnd));
struct srp_rdma_ch *ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
struct srp_request *req = scsi_cmd_priv(scmnd);
@@ -2152,6 +2152,7 @@ static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
{
+ struct request *rq = scsi_cmd_to_rq(scmnd);
struct srp_target_port *target = host_to_target(shost);
struct srp_rdma_ch *ch;
struct srp_request *req = scsi_cmd_priv(scmnd);
@@ -2166,8 +2167,8 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
if (unlikely(scmnd->result))
goto err;
- WARN_ON_ONCE(scmnd->request->tag < 0);
- tag = blk_mq_unique_tag(scmnd->request);
+ WARN_ON_ONCE(rq->tag < 0);
+ tag = blk_mq_unique_tag(rq);
ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
spin_lock_irqsave(&ch->lock, flags);
@@ -2791,7 +2792,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
if (!req)
return SUCCESS;
- tag = blk_mq_unique_tag(scmnd->request);
+ tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmnd));
ch_idx = blk_mq_unique_tag_to_hwq(tag);
if (WARN_ON_ONCE(ch_idx >= target->ch_count))
return SUCCESS;
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 61fa7e724172..db58a01b23d3 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -697,13 +697,12 @@ static int gameport_driver_probe(struct device *dev)
return gameport->drv ? 0 : -ENODEV;
}
-static int gameport_driver_remove(struct device *dev)
+static void gameport_driver_remove(struct device *dev)
{
struct gameport *gameport = to_gameport_port(dev);
struct gameport_driver *drv = to_gameport_driver(dev->driver);
drv->disconnect(gameport);
- return 0;
}
static void gameport_attach_driver(struct gameport_driver *drv)
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index 62ccfebf2f60..c1a4d5055de6 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -316,11 +316,9 @@ static int __init hil_probe_chip(struct parisc_device *dev)
return hil_keyb_init();
}
-static int __exit hil_remove_chip(struct parisc_device *dev)
+static void __exit hil_remove_chip(struct parisc_device *dev)
{
hil_keyb_exit();
-
- return 0;
}
static const struct parisc_device_id hil_tbl[] __initconst = {
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 2f9775de3c5b..a9065c6ab550 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -411,7 +411,7 @@ fail_nomem:
* @return: success/error report
*/
-static int __exit gscps2_remove(struct parisc_device *dev)
+static void __exit gscps2_remove(struct parisc_device *dev)
{
struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
@@ -425,7 +425,6 @@ static int __exit gscps2_remove(struct parisc_device *dev)
#endif
dev_set_drvdata(&dev->dev, NULL);
kfree(ps2port);
- return 0;
}
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 29f491082926..ec117be3d8d8 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -778,12 +778,11 @@ static int serio_driver_probe(struct device *dev)
return serio_connect_driver(serio, drv);
}
-static int serio_driver_remove(struct device *dev)
+static void serio_driver_remove(struct device *dev)
{
struct serio *serio = to_serio_port(dev);
serio_disconnect_driver(serio);
- return 0;
}
static void serio_cleanup(struct serio *serio)
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 7887941730db..9050ca1f4285 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -959,6 +959,9 @@ EXPORT_SYMBOL_GPL(icc_link_destroy);
*/
void icc_node_add(struct icc_node *node, struct icc_provider *provider)
{
+ if (WARN_ON(node->provider))
+ return;
+
mutex_lock(&icc_lock);
node->provider = provider;
diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
index 0d7a2500d0b8..daf1e25f6042 100644
--- a/drivers/interconnect/qcom/Kconfig
+++ b/drivers/interconnect/qcom/Kconfig
@@ -83,6 +83,15 @@ config INTERCONNECT_QCOM_SC7280
This is a driver for the Qualcomm Network-on-Chip on sc7280-based
platforms.
+config INTERCONNECT_QCOM_SC8180X
+ tristate "Qualcomm SC8180X interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Network-on-Chip on sc8180x-based
+ platforms.
+
config INTERCONNECT_QCOM_SDM660
tristate "Qualcomm SDM660 interconnect driver"
depends on INTERCONNECT_QCOM
diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
index 2880129a6fe4..69300b1d48ef 100644
--- a/drivers/interconnect/qcom/Makefile
+++ b/drivers/interconnect/qcom/Makefile
@@ -9,6 +9,7 @@ qnoc-qcs404-objs := qcs404.o
icc-rpmh-obj := icc-rpmh.o
qnoc-sc7180-objs := sc7180.o
qnoc-sc7280-objs := sc7280.o
+qnoc-sc8180x-objs := sc8180x.o
qnoc-sdm660-objs := sdm660.o
qnoc-sdm845-objs := sdm845.o
qnoc-sdx55-objs := sdx55.o
@@ -26,6 +27,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7280) += qnoc-sc7280.o
+obj-$(CONFIG_INTERCONNECT_QCOM_SC8180X) += qnoc-sc8180x.o
obj-$(CONFIG_INTERCONNECT_QCOM_SDM660) += qnoc-sdm660.o
obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o
obj-$(CONFIG_INTERCONNECT_QCOM_SDX55) += qnoc-sdx55.o
diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c
index f6fae64861ce..3eb7936d2cf6 100644
--- a/drivers/interconnect/qcom/icc-rpmh.c
+++ b/drivers/interconnect/qcom/icc-rpmh.c
@@ -7,6 +7,7 @@
#include <linux/interconnect-provider.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
#include "bcm-voter.h"
@@ -182,4 +183,96 @@ int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
}
EXPORT_SYMBOL_GPL(qcom_icc_bcm_init);
+int qcom_icc_rpmh_probe(struct platform_device *pdev)
+{
+ const struct qcom_icc_desc *desc;
+ struct device *dev = &pdev->dev;
+ struct icc_onecell_data *data;
+ struct icc_provider *provider;
+ struct qcom_icc_node **qnodes, *qn;
+ struct qcom_icc_provider *qp;
+ struct icc_node *node;
+ size_t num_nodes, i, j;
+ int ret;
+
+ desc = of_device_get_match_data(dev);
+ if (!desc)
+ return -EINVAL;
+
+ qnodes = desc->nodes;
+ num_nodes = desc->num_nodes;
+
+ qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
+ if (!qp)
+ return -ENOMEM;
+
+ data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ provider = &qp->provider;
+ provider->dev = dev;
+ provider->set = qcom_icc_set;
+ provider->pre_aggregate = qcom_icc_pre_aggregate;
+ provider->aggregate = qcom_icc_aggregate;
+ provider->xlate_extended = qcom_icc_xlate_extended;
+ INIT_LIST_HEAD(&provider->nodes);
+ provider->data = data;
+
+ qp->dev = dev;
+ qp->bcms = desc->bcms;
+ qp->num_bcms = desc->num_bcms;
+
+ qp->voter = of_bcm_voter_get(qp->dev, NULL);
+ if (IS_ERR(qp->voter))
+ return PTR_ERR(qp->voter);
+
+ ret = icc_provider_add(provider);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < qp->num_bcms; i++)
+ qcom_icc_bcm_init(qp->bcms[i], dev);
+
+ for (i = 0; i < num_nodes; i++) {
+ qn = qnodes[i];
+ if (!qn)
+ continue;
+
+ node = icc_node_create(qn->id);
+ if (IS_ERR(node)) {
+ ret = PTR_ERR(node);
+ goto err;
+ }
+
+ node->name = qn->name;
+ node->data = qn;
+ icc_node_add(node, provider);
+
+ for (j = 0; j < qn->num_links; j++)
+ icc_link_create(node, qn->links[j]);
+
+ data->nodes[i] = node;
+ }
+
+ data->num_nodes = num_nodes;
+ platform_set_drvdata(pdev, qp);
+
+ return 0;
+err:
+ icc_nodes_remove(provider);
+ icc_provider_del(provider);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_icc_rpmh_probe);
+
+int qcom_icc_rpmh_remove(struct platform_device *pdev)
+{
+ struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
+
+ icc_nodes_remove(&qp->provider);
+ return icc_provider_del(&qp->provider);
+}
+EXPORT_SYMBOL_GPL(qcom_icc_rpmh_remove);
+
MODULE_LICENSE("GPL v2");
diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h
index e5f61ab989e7..4bfc060529ba 100644
--- a/drivers/interconnect/qcom/icc-rpmh.h
+++ b/drivers/interconnect/qcom/icc-rpmh.h
@@ -134,5 +134,7 @@ int qcom_icc_set(struct icc_node *src, struct icc_node *dst);
struct icc_node_data *qcom_icc_xlate_extended(struct of_phandle_args *spec, void *data);
int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev);
void qcom_icc_pre_aggregate(struct icc_node *node);
+int qcom_icc_rpmh_probe(struct platform_device *pdev);
+int qcom_icc_rpmh_remove(struct platform_device *pdev);
#endif
diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c
index 695f28789e98..c7af143980de 100644
--- a/drivers/interconnect/qcom/osm-l3.c
+++ b/drivers/interconnect/qcom/osm-l3.c
@@ -15,6 +15,7 @@
#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include "sc7180.h"
+#include "sc8180x.h"
#include "sdm845.h"
#include "sm8150.h"
#include "sm8250.h"
@@ -37,7 +38,7 @@
#define OSM_L3_MAX_LINKS 1
-#define to_qcom_provider(_provider) \
+#define to_osm_l3_provider(_provider) \
container_of(_provider, struct qcom_osm_l3_icc_provider, provider)
struct qcom_osm_l3_icc_provider {
@@ -49,14 +50,14 @@ struct qcom_osm_l3_icc_provider {
};
/**
- * struct qcom_icc_node - Qualcomm specific interconnect nodes
+ * struct qcom_osm_l3_node - Qualcomm specific interconnect nodes
* @name: the node name used in debugfs
* @links: an array of nodes where we can go next while traversing
* @id: a unique node identifier
* @num_links: the total number of @links
* @buswidth: width of the interconnect between a node and the bus
*/
-struct qcom_icc_node {
+struct qcom_osm_l3_node {
const char *name;
u16 links[OSM_L3_MAX_LINKS];
u16 id;
@@ -64,8 +65,8 @@ struct qcom_icc_node {
u16 buswidth;
};
-struct qcom_icc_desc {
- const struct qcom_icc_node **nodes;
+struct qcom_osm_l3_desc {
+ const struct qcom_osm_l3_node **nodes;
size_t num_nodes;
unsigned int lut_row_size;
unsigned int reg_freq_lut;
@@ -73,7 +74,7 @@ struct qcom_icc_desc {
};
#define DEFINE_QNODE(_name, _id, _buswidth, ...) \
- static const struct qcom_icc_node _name = { \
+ static const struct qcom_osm_l3_node _name = { \
.name = #_name, \
.id = _id, \
.buswidth = _buswidth, \
@@ -84,12 +85,12 @@ struct qcom_icc_desc {
DEFINE_QNODE(sdm845_osm_apps_l3, SDM845_MASTER_OSM_L3_APPS, 16, SDM845_SLAVE_OSM_L3);
DEFINE_QNODE(sdm845_osm_l3, SDM845_SLAVE_OSM_L3, 16);
-static const struct qcom_icc_node *sdm845_osm_l3_nodes[] = {
+static const struct qcom_osm_l3_node *sdm845_osm_l3_nodes[] = {
[MASTER_OSM_L3_APPS] = &sdm845_osm_apps_l3,
[SLAVE_OSM_L3] = &sdm845_osm_l3,
};
-static const struct qcom_icc_desc sdm845_icc_osm_l3 = {
+static const struct qcom_osm_l3_desc sdm845_icc_osm_l3 = {
.nodes = sdm845_osm_l3_nodes,
.num_nodes = ARRAY_SIZE(sdm845_osm_l3_nodes),
.lut_row_size = OSM_LUT_ROW_SIZE,
@@ -100,12 +101,12 @@ static const struct qcom_icc_desc sdm845_icc_osm_l3 = {
DEFINE_QNODE(sc7180_osm_apps_l3, SC7180_MASTER_OSM_L3_APPS, 16, SC7180_SLAVE_OSM_L3);
DEFINE_QNODE(sc7180_osm_l3, SC7180_SLAVE_OSM_L3, 16);
-static const struct qcom_icc_node *sc7180_osm_l3_nodes[] = {
+static const struct qcom_osm_l3_node *sc7180_osm_l3_nodes[] = {
[MASTER_OSM_L3_APPS] = &sc7180_osm_apps_l3,
[SLAVE_OSM_L3] = &sc7180_osm_l3,
};
-static const struct qcom_icc_desc sc7180_icc_osm_l3 = {
+static const struct qcom_osm_l3_desc sc7180_icc_osm_l3 = {
.nodes = sc7180_osm_l3_nodes,
.num_nodes = ARRAY_SIZE(sc7180_osm_l3_nodes),
.lut_row_size = OSM_LUT_ROW_SIZE,
@@ -113,15 +114,31 @@ static const struct qcom_icc_desc sc7180_icc_osm_l3 = {
.reg_perf_state = OSM_REG_PERF_STATE,
};
+DEFINE_QNODE(sc8180x_osm_apps_l3, SC8180X_MASTER_OSM_L3_APPS, 32, SC8180X_SLAVE_OSM_L3);
+DEFINE_QNODE(sc8180x_osm_l3, SC8180X_SLAVE_OSM_L3, 32);
+
+static const struct qcom_osm_l3_node *sc8180x_osm_l3_nodes[] = {
+ [MASTER_OSM_L3_APPS] = &sc8180x_osm_apps_l3,
+ [SLAVE_OSM_L3] = &sc8180x_osm_l3,
+};
+
+static const struct qcom_osm_l3_desc sc8180x_icc_osm_l3 = {
+ .nodes = sc8180x_osm_l3_nodes,
+ .num_nodes = ARRAY_SIZE(sc8180x_osm_l3_nodes),
+ .lut_row_size = OSM_LUT_ROW_SIZE,
+ .reg_freq_lut = OSM_REG_FREQ_LUT,
+ .reg_perf_state = OSM_REG_PERF_STATE,
+};
+
DEFINE_QNODE(sm8150_osm_apps_l3, SM8150_MASTER_OSM_L3_APPS, 32, SM8150_SLAVE_OSM_L3);
DEFINE_QNODE(sm8150_osm_l3, SM8150_SLAVE_OSM_L3, 32);
-static const struct qcom_icc_node *sm8150_osm_l3_nodes[] = {
+static const struct qcom_osm_l3_node *sm8150_osm_l3_nodes[] = {
[MASTER_OSM_L3_APPS] = &sm8150_osm_apps_l3,
[SLAVE_OSM_L3] = &sm8150_osm_l3,
};
-static const struct qcom_icc_desc sm8150_icc_osm_l3 = {
+static const struct qcom_osm_l3_desc sm8150_icc_osm_l3 = {
.nodes = sm8150_osm_l3_nodes,
.num_nodes = ARRAY_SIZE(sm8150_osm_l3_nodes),
.lut_row_size = OSM_LUT_ROW_SIZE,
@@ -132,12 +149,12 @@ static const struct qcom_icc_desc sm8150_icc_osm_l3 = {
DEFINE_QNODE(sm8250_epss_apps_l3, SM8250_MASTER_EPSS_L3_APPS, 32, SM8250_SLAVE_EPSS_L3);
DEFINE_QNODE(sm8250_epss_l3, SM8250_SLAVE_EPSS_L3, 32);
-static const struct qcom_icc_node *sm8250_epss_l3_nodes[] = {
+static const struct qcom_osm_l3_node *sm8250_epss_l3_nodes[] = {
[MASTER_EPSS_L3_APPS] = &sm8250_epss_apps_l3,
[SLAVE_EPSS_L3_SHARED] = &sm8250_epss_l3,
};
-static const struct qcom_icc_desc sm8250_icc_epss_l3 = {
+static const struct qcom_osm_l3_desc sm8250_icc_epss_l3 = {
.nodes = sm8250_epss_l3_nodes,
.num_nodes = ARRAY_SIZE(sm8250_epss_l3_nodes),
.lut_row_size = EPSS_LUT_ROW_SIZE,
@@ -145,11 +162,11 @@ static const struct qcom_icc_desc sm8250_icc_epss_l3 = {
.reg_perf_state = EPSS_REG_PERF_STATE,
};
-static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
+static int qcom_osm_l3_set(struct icc_node *src, struct icc_node *dst)
{
struct qcom_osm_l3_icc_provider *qp;
struct icc_provider *provider;
- const struct qcom_icc_node *qn;
+ const struct qcom_osm_l3_node *qn;
struct icc_node *n;
unsigned int index;
u32 agg_peak = 0;
@@ -158,7 +175,7 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
qn = src->data;
provider = src->provider;
- qp = to_qcom_provider(provider);
+ qp = to_osm_l3_provider(provider);
list_for_each_entry(n, &provider->nodes, node_list)
provider->aggregate(n, 0, n->avg_bw, n->peak_bw,
@@ -191,10 +208,10 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
u32 info, src, lval, i, prev_freq = 0, freq;
static unsigned long hw_rate, xo_rate;
struct qcom_osm_l3_icc_provider *qp;
- const struct qcom_icc_desc *desc;
+ const struct qcom_osm_l3_desc *desc;
struct icc_onecell_data *data;
struct icc_provider *provider;
- const struct qcom_icc_node **qnodes;
+ const struct qcom_osm_l3_node **qnodes;
struct icc_node *node;
size_t num_nodes;
struct clk *clk;
@@ -264,7 +281,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
provider = &qp->provider;
provider->dev = &pdev->dev;
- provider->set = qcom_icc_set;
+ provider->set = qcom_osm_l3_set;
provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell;
INIT_LIST_HEAD(&provider->nodes);
@@ -286,7 +303,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
}
node->name = qnodes[i]->name;
- /* Cast away const and add it back in qcom_icc_set() */
+ /* Cast away const and add it back in qcom_osm_l3_set() */
node->data = (void *)qnodes[i];
icc_node_add(node, provider);
@@ -311,6 +328,7 @@ static const struct of_device_id osm_l3_of_match[] = {
{ .compatible = "qcom,sc7180-osm-l3", .data = &sc7180_icc_osm_l3 },
{ .compatible = "qcom,sdm845-osm-l3", .data = &sdm845_icc_osm_l3 },
{ .compatible = "qcom,sm8150-osm-l3", .data = &sm8150_icc_osm_l3 },
+ { .compatible = "qcom,sc8180x-osm-l3", .data = &sc8180x_icc_osm_l3 },
{ .compatible = "qcom,sm8250-epss-l3", .data = &sm8250_icc_epss_l3 },
{ }
};
diff --git a/drivers/interconnect/qcom/sc7180.c b/drivers/interconnect/qcom/sc7180.c
index 8d9044ed18ab..12d59c36df53 100644
--- a/drivers/interconnect/qcom/sc7180.c
+++ b/drivers/interconnect/qcom/sc7180.c
@@ -504,98 +504,6 @@ static struct qcom_icc_desc sc7180_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
-static int qnoc_probe(struct platform_device *pdev)
-{
- const struct qcom_icc_desc *desc;
- struct icc_onecell_data *data;
- struct icc_provider *provider;
- struct qcom_icc_node **qnodes;
- struct qcom_icc_provider *qp;
- struct icc_node *node;
- size_t num_nodes, i;
- int ret;
-
- desc = device_get_match_data(&pdev->dev);
- if (!desc)
- return -EINVAL;
-
- qnodes = desc->nodes;
- num_nodes = desc->num_nodes;
-
- qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return -ENOMEM;
-
- data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- provider = &qp->provider;
- provider->dev = &pdev->dev;
- provider->set = qcom_icc_set;
- provider->pre_aggregate = qcom_icc_pre_aggregate;
- provider->aggregate = qcom_icc_aggregate;
- provider->xlate_extended = qcom_icc_xlate_extended;
- INIT_LIST_HEAD(&provider->nodes);
- provider->data = data;
-
- qp->dev = &pdev->dev;
- qp->bcms = desc->bcms;
- qp->num_bcms = desc->num_bcms;
-
- qp->voter = of_bcm_voter_get(qp->dev, NULL);
- if (IS_ERR(qp->voter))
- return PTR_ERR(qp->voter);
-
- ret = icc_provider_add(provider);
- if (ret) {
- dev_err(&pdev->dev, "error adding interconnect provider\n");
- return ret;
- }
-
- for (i = 0; i < qp->num_bcms; i++)
- qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
- for (i = 0; i < num_nodes; i++) {
- size_t j;
-
- if (!qnodes[i])
- continue;
-
- node = icc_node_create(qnodes[i]->id);
- if (IS_ERR(node)) {
- ret = PTR_ERR(node);
- goto err;
- }
-
- node->name = qnodes[i]->name;
- node->data = qnodes[i];
- icc_node_add(node, provider);
-
- for (j = 0; j < qnodes[i]->num_links; j++)
- icc_link_create(node, qnodes[i]->links[j]);
-
- data->nodes[i] = node;
- }
- data->num_nodes = num_nodes;
-
- platform_set_drvdata(pdev, qp);
-
- return 0;
-err:
- icc_nodes_remove(provider);
- icc_provider_del(provider);
- return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
- struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
- icc_nodes_remove(&qp->provider);
- return icc_provider_del(&qp->provider);
-}
-
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sc7180-aggre1-noc",
.data = &sc7180_aggre1_noc},
@@ -628,8 +536,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
- .probe = qnoc_probe,
- .remove = qnoc_remove,
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc7180",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc7280.c b/drivers/interconnect/qcom/sc7280.c
index 8d1b55c3705c..f8b34f6cbb0d 100644
--- a/drivers/interconnect/qcom/sc7280.c
+++ b/drivers/interconnect/qcom/sc7280.c
@@ -1802,98 +1802,6 @@ static struct qcom_icc_desc sc7280_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
-static int qnoc_probe(struct platform_device *pdev)
-{
- const struct qcom_icc_desc *desc;
- struct icc_onecell_data *data;
- struct icc_provider *provider;
- struct qcom_icc_node **qnodes;
- struct qcom_icc_provider *qp;
- struct icc_node *node;
- size_t num_nodes, i;
- int ret;
-
- desc = device_get_match_data(&pdev->dev);
- if (!desc)
- return -EINVAL;
-
- qnodes = desc->nodes;
- num_nodes = desc->num_nodes;
-
- qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return -ENOMEM;
-
- data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- provider = &qp->provider;
- provider->dev = &pdev->dev;
- provider->set = qcom_icc_set;
- provider->pre_aggregate = qcom_icc_pre_aggregate;
- provider->aggregate = qcom_icc_aggregate;
- provider->xlate_extended = qcom_icc_xlate_extended;
- INIT_LIST_HEAD(&provider->nodes);
- provider->data = data;
-
- qp->dev = &pdev->dev;
- qp->bcms = desc->bcms;
- qp->num_bcms = desc->num_bcms;
-
- qp->voter = of_bcm_voter_get(qp->dev, NULL);
- if (IS_ERR(qp->voter))
- return PTR_ERR(qp->voter);
-
- ret = icc_provider_add(provider);
- if (ret) {
- dev_err(&pdev->dev, "error adding interconnect provider\n");
- return ret;
- }
-
- for (i = 0; i < qp->num_bcms; i++)
- qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
- for (i = 0; i < num_nodes; i++) {
- size_t j;
-
- if (!qnodes[i])
- continue;
-
- node = icc_node_create(qnodes[i]->id);
- if (IS_ERR(node)) {
- ret = PTR_ERR(node);
- goto err;
- }
-
- node->name = qnodes[i]->name;
- node->data = qnodes[i];
- icc_node_add(node, provider);
-
- for (j = 0; j < qnodes[i]->num_links; j++)
- icc_link_create(node, qnodes[i]->links[j]);
-
- data->nodes[i] = node;
- }
- data->num_nodes = num_nodes;
-
- platform_set_drvdata(pdev, qp);
-
- return 0;
-err:
- icc_nodes_remove(provider);
- icc_provider_del(provider);
- return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
- struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
- icc_nodes_remove(&qp->provider);
- return icc_provider_del(&qp->provider);
-}
-
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sc7280-aggre1-noc",
.data = &sc7280_aggre1_noc},
@@ -1924,8 +1832,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
- .probe = qnoc_probe,
- .remove = qnoc_remove,
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc7280",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc8180x.c b/drivers/interconnect/qcom/sc8180x.c
new file mode 100644
index 000000000000..e9adf05b9330
--- /dev/null
+++ b/drivers/interconnect/qcom/sc8180x.c
@@ -0,0 +1,626 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Linaro Ltd.
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+#include <dt-bindings/interconnect/qcom,sc8180x.h>
+
+#include "bcm-voter.h"
+#include "icc-rpmh.h"
+#include "sc8180x.h"
+
+DEFINE_QNODE(mas_qhm_a1noc_cfg, SC8180X_MASTER_A1NOC_CFG, 1, 4, SC8180X_SLAVE_SERVICE_A1NOC);
+DEFINE_QNODE(mas_xm_ufs_card, SC8180X_MASTER_UFS_CARD, 1, 8, SC8180X_A1NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_ufs_g4, SC8180X_MASTER_UFS_GEN4, 1, 8, SC8180X_A1NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_ufs_mem, SC8180X_MASTER_UFS_MEM, 1, 8, SC8180X_A1NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_usb3_0, SC8180X_MASTER_USB3, 1, 8, SC8180X_A1NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_usb3_1, SC8180X_MASTER_USB3_1, 1, 8, SC8180X_A1NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_usb3_2, SC8180X_MASTER_USB3_2, 1, 16, SC8180X_A1NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qhm_a2noc_cfg, SC8180X_MASTER_A2NOC_CFG, 1, 4, SC8180X_SLAVE_SERVICE_A2NOC);
+DEFINE_QNODE(mas_qhm_qdss_bam, SC8180X_MASTER_QDSS_BAM, 1, 4, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qhm_qspi, SC8180X_MASTER_QSPI_0, 1, 4, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qhm_qspi1, SC8180X_MASTER_QSPI_1, 1, 4, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qhm_qup0, SC8180X_MASTER_QUP_0, 1, 4, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qhm_qup1, SC8180X_MASTER_QUP_1, 1, 4, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qhm_qup2, SC8180X_MASTER_QUP_2, 1, 4, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qhm_sensorss_ahb, SC8180X_MASTER_SENSORS_AHB, 1, 4, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qxm_crypto, SC8180X_MASTER_CRYPTO_CORE_0, 1, 8, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qxm_ipa, SC8180X_MASTER_IPA, 1, 8, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_emac, SC8180X_MASTER_EMAC, 1, 8, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_pcie3_0, SC8180X_MASTER_PCIE, 1, 8, SC8180X_SLAVE_ANOC_PCIE_GEM_NOC);
+DEFINE_QNODE(mas_xm_pcie3_1, SC8180X_MASTER_PCIE_1, 1, 16, SC8180X_SLAVE_ANOC_PCIE_GEM_NOC);
+DEFINE_QNODE(mas_xm_pcie3_2, SC8180X_MASTER_PCIE_2, 1, 8, SC8180X_SLAVE_ANOC_PCIE_GEM_NOC);
+DEFINE_QNODE(mas_xm_pcie3_3, SC8180X_MASTER_PCIE_3, 1, 16, SC8180X_SLAVE_ANOC_PCIE_GEM_NOC);
+DEFINE_QNODE(mas_xm_qdss_etr, SC8180X_MASTER_QDSS_ETR, 1, 8, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_sdc2, SC8180X_MASTER_SDCC_2, 1, 8, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_xm_sdc4, SC8180X_MASTER_SDCC_4, 1, 8, SC8180X_A2NOC_SNOC_SLV);
+DEFINE_QNODE(mas_qxm_camnoc_hf0_uncomp, SC8180X_MASTER_CAMNOC_HF0_UNCOMP, 1, 32, SC8180X_SLAVE_CAMNOC_UNCOMP);
+DEFINE_QNODE(mas_qxm_camnoc_hf1_uncomp, SC8180X_MASTER_CAMNOC_HF1_UNCOMP, 1, 32, SC8180X_SLAVE_CAMNOC_UNCOMP);
+DEFINE_QNODE(mas_qxm_camnoc_sf_uncomp, SC8180X_MASTER_CAMNOC_SF_UNCOMP, 1, 32, SC8180X_SLAVE_CAMNOC_UNCOMP);
+DEFINE_QNODE(mas_qnm_npu, SC8180X_MASTER_NPU, 1, 32, SC8180X_SLAVE_CDSP_MEM_NOC);
+DEFINE_QNODE(mas_qnm_snoc, SC8180X_SNOC_CNOC_MAS, 1, 8, SC8180X_SLAVE_TLMM_SOUTH, SC8180X_SLAVE_CDSP_CFG, SC8180X_SLAVE_SPSS_CFG, SC8180X_SLAVE_CAMERA_CFG, SC8180X_SLAVE_SDCC_4, SC8180X_SLAVE_AHB2PHY_CENTER, SC8180X_SLAVE_SDCC_2, SC8180X_SLAVE_PCIE_2_CFG, SC8180X_SLAVE_CNOC_MNOC_CFG, SC8180X_SLAVE_EMAC_CFG, SC8180X_SLAVE_QSPI_0, SC8180X_SLAVE_QSPI_1, SC8180X_SLAVE_TLMM_EAST, SC8180X_SLAVE_SNOC_CFG, SC8180X_SLAVE_AHB2PHY_EAST, SC8180X_SLAVE_GLM, SC8180X_SLAVE_PDM, SC8180X_SLAVE_PCIE_1_CFG, SC8180X_SLAVE_A2NOC_CFG, SC8180X_SLAVE_QDSS_CFG, SC8180X_SLAVE_DISPLAY_CFG, SC8180X_SLAVE_TCSR, SC8180X_SLAVE_UFS_MEM_0_CFG, SC8180X_SLAVE_CNOC_DDRSS, SC8180X_SLAVE_PCIE_0_CFG, SC8180X_SLAVE_QUP_1, SC8180X_SLAVE_QUP_2, SC8180X_SLAVE_NPU_CFG, SC8180X_SLAVE_CRYPTO_0_CFG, SC8180X_SLAVE_GRAPHICS_3D_CFG, SC8180X_SLAVE_VENUS_CFG, SC8180X_SLAVE_TSIF, SC8180X_SLAVE_IPA_CFG, SC8180X_SLAVE_CLK_CTL, SC8180X_SLAVE_SECURITY, SC8180X_SLAVE_AOP, SC8180X_SLAVE_AHB2PHY_WEST, SC8180X_SLAVE_AHB2PHY_SOUTH, SC8180X_SLAVE_SERVICE_CNOC, SC8180X_SLAVE_UFS_CARD_CFG, SC8180X_SLAVE_USB3_1, SC8180X_SLAVE_USB3_2, SC8180X_SLAVE_PCIE_3_CFG, SC8180X_SLAVE_RBCPR_CX_CFG, SC8180X_SLAVE_TLMM_WEST, SC8180X_SLAVE_A1NOC_CFG, SC8180X_SLAVE_AOSS, SC8180X_SLAVE_PRNG, SC8180X_SLAVE_VSENSE_CTRL_CFG, SC8180X_SLAVE_QUP_0, SC8180X_SLAVE_USB3, SC8180X_SLAVE_RBCPR_MMCX_CFG, SC8180X_SLAVE_PIMEM_CFG, SC8180X_SLAVE_UFS_MEM_1_CFG, SC8180X_SLAVE_RBCPR_MX_CFG, SC8180X_SLAVE_IMEM_CFG);
+DEFINE_QNODE(mas_qhm_cnoc_dc_noc, SC8180X_MASTER_CNOC_DC_NOC, 1, 4, SC8180X_SLAVE_LLCC_CFG, SC8180X_SLAVE_GEM_NOC_CFG);
+DEFINE_QNODE(mas_acm_apps, SC8180X_MASTER_AMPSS_M0, 4, 64, SC8180X_SLAVE_ECC, SC8180X_SLAVE_LLCC, SC8180X_SLAVE_GEM_NOC_SNOC);
+DEFINE_QNODE(mas_acm_gpu_tcu, SC8180X_MASTER_GPU_TCU, 1, 8, SC8180X_SLAVE_LLCC, SC8180X_SLAVE_GEM_NOC_SNOC);
+DEFINE_QNODE(mas_acm_sys_tcu, SC8180X_MASTER_SYS_TCU, 1, 8, SC8180X_SLAVE_LLCC, SC8180X_SLAVE_GEM_NOC_SNOC);
+DEFINE_QNODE(mas_qhm_gemnoc_cfg, SC8180X_MASTER_GEM_NOC_CFG, 1, 4, SC8180X_SLAVE_SERVICE_GEM_NOC_1, SC8180X_SLAVE_SERVICE_GEM_NOC, SC8180X_SLAVE_MSS_PROC_MS_MPU_CFG);
+DEFINE_QNODE(mas_qnm_cmpnoc, SC8180X_MASTER_COMPUTE_NOC, 2, 32, SC8180X_SLAVE_ECC, SC8180X_SLAVE_LLCC, SC8180X_SLAVE_GEM_NOC_SNOC);
+DEFINE_QNODE(mas_qnm_gpu, SC8180X_MASTER_GRAPHICS_3D, 4, 32, SC8180X_SLAVE_LLCC, SC8180X_SLAVE_GEM_NOC_SNOC);
+DEFINE_QNODE(mas_qnm_mnoc_hf, SC8180X_MASTER_MNOC_HF_MEM_NOC, 2, 32, SC8180X_SLAVE_LLCC);
+DEFINE_QNODE(mas_qnm_mnoc_sf, SC8180X_MASTER_MNOC_SF_MEM_NOC, 1, 32, SC8180X_SLAVE_LLCC, SC8180X_SLAVE_GEM_NOC_SNOC);
+DEFINE_QNODE(mas_qnm_pcie, SC8180X_MASTER_GEM_NOC_PCIE_SNOC, 1, 32, SC8180X_SLAVE_LLCC, SC8180X_SLAVE_GEM_NOC_SNOC);
+DEFINE_QNODE(mas_qnm_snoc_gc, SC8180X_MASTER_SNOC_GC_MEM_NOC, 1, 8, SC8180X_SLAVE_LLCC);
+DEFINE_QNODE(mas_qnm_snoc_sf, SC8180X_MASTER_SNOC_SF_MEM_NOC, 1, 32, SC8180X_SLAVE_LLCC);
+DEFINE_QNODE(mas_qxm_ecc, SC8180X_MASTER_ECC, 2, 32, SC8180X_SLAVE_LLCC);
+DEFINE_QNODE(mas_ipa_core_master, SC8180X_MASTER_IPA_CORE, 1, 8, SC8180X_SLAVE_IPA_CORE);
+DEFINE_QNODE(mas_llcc_mc, SC8180X_MASTER_LLCC, 8, 4, SC8180X_SLAVE_EBI_CH0);
+DEFINE_QNODE(mas_qhm_mnoc_cfg, SC8180X_MASTER_CNOC_MNOC_CFG, 1, 4, SC8180X_SLAVE_SERVICE_MNOC);
+DEFINE_QNODE(mas_qxm_camnoc_hf0, SC8180X_MASTER_CAMNOC_HF0, 1, 32, SC8180X_SLAVE_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(mas_qxm_camnoc_hf1, SC8180X_MASTER_CAMNOC_HF1, 1, 32, SC8180X_SLAVE_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(mas_qxm_camnoc_sf, SC8180X_MASTER_CAMNOC_SF, 1, 32, SC8180X_SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(mas_qxm_mdp0, SC8180X_MASTER_MDP_PORT0, 1, 32, SC8180X_SLAVE_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(mas_qxm_mdp1, SC8180X_MASTER_MDP_PORT1, 1, 32, SC8180X_SLAVE_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(mas_qxm_rot, SC8180X_MASTER_ROTATOR, 1, 32, SC8180X_SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(mas_qxm_venus0, SC8180X_MASTER_VIDEO_P0, 1, 32, SC8180X_SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(mas_qxm_venus1, SC8180X_MASTER_VIDEO_P1, 1, 32, SC8180X_SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(mas_qxm_venus_arm9, SC8180X_MASTER_VIDEO_PROC, 1, 8, SC8180X_SLAVE_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(mas_qhm_snoc_cfg, SC8180X_MASTER_SNOC_CFG, 1, 4, SC8180X_SLAVE_SERVICE_SNOC);
+DEFINE_QNODE(mas_qnm_aggre1_noc, SC8180X_A1NOC_SNOC_MAS, 1, 32, SC8180X_SLAVE_SNOC_GEM_NOC_SF, SC8180X_SLAVE_PIMEM, SC8180X_SLAVE_OCIMEM, SC8180X_SLAVE_APPSS, SC8180X_SNOC_CNOC_SLV, SC8180X_SLAVE_QDSS_STM);
+DEFINE_QNODE(mas_qnm_aggre2_noc, SC8180X_A2NOC_SNOC_MAS, 1, 16, SC8180X_SLAVE_SNOC_GEM_NOC_SF, SC8180X_SLAVE_PIMEM, SC8180X_SLAVE_PCIE_3, SC8180X_SLAVE_OCIMEM, SC8180X_SLAVE_APPSS, SC8180X_SLAVE_PCIE_2, SC8180X_SNOC_CNOC_SLV, SC8180X_SLAVE_PCIE_0, SC8180X_SLAVE_PCIE_1, SC8180X_SLAVE_TCU, SC8180X_SLAVE_QDSS_STM);
+DEFINE_QNODE(mas_qnm_gemnoc, SC8180X_MASTER_GEM_NOC_SNOC, 1, 8, SC8180X_SLAVE_PIMEM, SC8180X_SLAVE_OCIMEM, SC8180X_SLAVE_APPSS, SC8180X_SNOC_CNOC_SLV, SC8180X_SLAVE_TCU, SC8180X_SLAVE_QDSS_STM);
+DEFINE_QNODE(mas_qxm_pimem, SC8180X_MASTER_PIMEM, 1, 8, SC8180X_SLAVE_SNOC_GEM_NOC_GC, SC8180X_SLAVE_OCIMEM);
+DEFINE_QNODE(mas_xm_gic, SC8180X_MASTER_GIC, 1, 8, SC8180X_SLAVE_SNOC_GEM_NOC_GC, SC8180X_SLAVE_OCIMEM);
+DEFINE_QNODE(slv_qns_a1noc_snoc, SC8180X_A1NOC_SNOC_SLV, 1, 32, SC8180X_A1NOC_SNOC_MAS);
+DEFINE_QNODE(slv_srvc_aggre1_noc, SC8180X_SLAVE_SERVICE_A1NOC, 1, 4);
+DEFINE_QNODE(slv_qns_a2noc_snoc, SC8180X_A2NOC_SNOC_SLV, 1, 16, SC8180X_A2NOC_SNOC_MAS);
+DEFINE_QNODE(slv_qns_pcie_mem_noc, SC8180X_SLAVE_ANOC_PCIE_GEM_NOC, 1, 32, SC8180X_MASTER_GEM_NOC_PCIE_SNOC);
+DEFINE_QNODE(slv_srvc_aggre2_noc, SC8180X_SLAVE_SERVICE_A2NOC, 1, 4);
+DEFINE_QNODE(slv_qns_camnoc_uncomp, SC8180X_SLAVE_CAMNOC_UNCOMP, 1, 32);
+DEFINE_QNODE(slv_qns_cdsp_mem_noc, SC8180X_SLAVE_CDSP_MEM_NOC, 2, 32, SC8180X_MASTER_COMPUTE_NOC);
+DEFINE_QNODE(slv_qhs_a1_noc_cfg, SC8180X_SLAVE_A1NOC_CFG, 1, 4, SC8180X_MASTER_A1NOC_CFG);
+DEFINE_QNODE(slv_qhs_a2_noc_cfg, SC8180X_SLAVE_A2NOC_CFG, 1, 4, SC8180X_MASTER_A2NOC_CFG);
+DEFINE_QNODE(slv_qhs_ahb2phy_refgen_center, SC8180X_SLAVE_AHB2PHY_CENTER, 1, 4);
+DEFINE_QNODE(slv_qhs_ahb2phy_refgen_east, SC8180X_SLAVE_AHB2PHY_EAST, 1, 4);
+DEFINE_QNODE(slv_qhs_ahb2phy_refgen_west, SC8180X_SLAVE_AHB2PHY_WEST, 1, 4);
+DEFINE_QNODE(slv_qhs_ahb2phy_south, SC8180X_SLAVE_AHB2PHY_SOUTH, 1, 4);
+DEFINE_QNODE(slv_qhs_aop, SC8180X_SLAVE_AOP, 1, 4);
+DEFINE_QNODE(slv_qhs_aoss, SC8180X_SLAVE_AOSS, 1, 4);
+DEFINE_QNODE(slv_qhs_camera_cfg, SC8180X_SLAVE_CAMERA_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_clk_ctl, SC8180X_SLAVE_CLK_CTL, 1, 4);
+DEFINE_QNODE(slv_qhs_compute_dsp, SC8180X_SLAVE_CDSP_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_cpr_cx, SC8180X_SLAVE_RBCPR_CX_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_cpr_mmcx, SC8180X_SLAVE_RBCPR_MMCX_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_cpr_mx, SC8180X_SLAVE_RBCPR_MX_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_crypto0_cfg, SC8180X_SLAVE_CRYPTO_0_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_ddrss_cfg, SC8180X_SLAVE_CNOC_DDRSS, 1, 4, SC8180X_MASTER_CNOC_DC_NOC);
+DEFINE_QNODE(slv_qhs_display_cfg, SC8180X_SLAVE_DISPLAY_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_emac_cfg, SC8180X_SLAVE_EMAC_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_glm, SC8180X_SLAVE_GLM, 1, 4);
+DEFINE_QNODE(slv_qhs_gpuss_cfg, SC8180X_SLAVE_GRAPHICS_3D_CFG, 1, 8);
+DEFINE_QNODE(slv_qhs_imem_cfg, SC8180X_SLAVE_IMEM_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_ipa, SC8180X_SLAVE_IPA_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_mnoc_cfg, SC8180X_SLAVE_CNOC_MNOC_CFG, 1, 4, SC8180X_MASTER_CNOC_MNOC_CFG);
+DEFINE_QNODE(slv_qhs_npu_cfg, SC8180X_SLAVE_NPU_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_pcie0_cfg, SC8180X_SLAVE_PCIE_0_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_pcie1_cfg, SC8180X_SLAVE_PCIE_1_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_pcie2_cfg, SC8180X_SLAVE_PCIE_2_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_pcie3_cfg, SC8180X_SLAVE_PCIE_3_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_pdm, SC8180X_SLAVE_PDM, 1, 4);
+DEFINE_QNODE(slv_qhs_pimem_cfg, SC8180X_SLAVE_PIMEM_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_prng, SC8180X_SLAVE_PRNG, 1, 4);
+DEFINE_QNODE(slv_qhs_qdss_cfg, SC8180X_SLAVE_QDSS_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_qspi_0, SC8180X_SLAVE_QSPI_0, 1, 4);
+DEFINE_QNODE(slv_qhs_qspi_1, SC8180X_SLAVE_QSPI_1, 1, 4);
+DEFINE_QNODE(slv_qhs_qupv3_east0, SC8180X_SLAVE_QUP_1, 1, 4);
+DEFINE_QNODE(slv_qhs_qupv3_east1, SC8180X_SLAVE_QUP_2, 1, 4);
+DEFINE_QNODE(slv_qhs_qupv3_west, SC8180X_SLAVE_QUP_0, 1, 4);
+DEFINE_QNODE(slv_qhs_sdc2, SC8180X_SLAVE_SDCC_2, 1, 4);
+DEFINE_QNODE(slv_qhs_sdc4, SC8180X_SLAVE_SDCC_4, 1, 4);
+DEFINE_QNODE(slv_qhs_security, SC8180X_SLAVE_SECURITY, 1, 4);
+DEFINE_QNODE(slv_qhs_snoc_cfg, SC8180X_SLAVE_SNOC_CFG, 1, 4, SC8180X_MASTER_SNOC_CFG);
+DEFINE_QNODE(slv_qhs_spss_cfg, SC8180X_SLAVE_SPSS_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_tcsr, SC8180X_SLAVE_TCSR, 1, 4);
+DEFINE_QNODE(slv_qhs_tlmm_east, SC8180X_SLAVE_TLMM_EAST, 1, 4);
+DEFINE_QNODE(slv_qhs_tlmm_south, SC8180X_SLAVE_TLMM_SOUTH, 1, 4);
+DEFINE_QNODE(slv_qhs_tlmm_west, SC8180X_SLAVE_TLMM_WEST, 1, 4);
+DEFINE_QNODE(slv_qhs_tsif, SC8180X_SLAVE_TSIF, 1, 4);
+DEFINE_QNODE(slv_qhs_ufs_card_cfg, SC8180X_SLAVE_UFS_CARD_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_ufs_mem0_cfg, SC8180X_SLAVE_UFS_MEM_0_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_ufs_mem1_cfg, SC8180X_SLAVE_UFS_MEM_1_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_usb3_0, SC8180X_SLAVE_USB3, 1, 4);
+DEFINE_QNODE(slv_qhs_usb3_1, SC8180X_SLAVE_USB3_1, 1, 4);
+DEFINE_QNODE(slv_qhs_usb3_2, SC8180X_SLAVE_USB3_2, 1, 4);
+DEFINE_QNODE(slv_qhs_venus_cfg, SC8180X_SLAVE_VENUS_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_vsense_ctrl_cfg, SC8180X_SLAVE_VSENSE_CTRL_CFG, 1, 4);
+DEFINE_QNODE(slv_srvc_cnoc, SC8180X_SLAVE_SERVICE_CNOC, 1, 4);
+DEFINE_QNODE(slv_qhs_gemnoc, SC8180X_SLAVE_GEM_NOC_CFG, 1, 4, SC8180X_MASTER_GEM_NOC_CFG);
+DEFINE_QNODE(slv_qhs_llcc, SC8180X_SLAVE_LLCC_CFG, 1, 4);
+DEFINE_QNODE(slv_qhs_mdsp_ms_mpu_cfg, SC8180X_SLAVE_MSS_PROC_MS_MPU_CFG, 1, 4);
+DEFINE_QNODE(slv_qns_ecc, SC8180X_SLAVE_ECC, 1, 32);
+DEFINE_QNODE(slv_qns_gem_noc_snoc, SC8180X_SLAVE_GEM_NOC_SNOC, 1, 8, SC8180X_MASTER_GEM_NOC_SNOC);
+DEFINE_QNODE(slv_qns_llcc, SC8180X_SLAVE_LLCC, 8, 16, SC8180X_MASTER_LLCC);
+DEFINE_QNODE(slv_srvc_gemnoc, SC8180X_SLAVE_SERVICE_GEM_NOC, 1, 4);
+DEFINE_QNODE(slv_srvc_gemnoc1, SC8180X_SLAVE_SERVICE_GEM_NOC_1, 1, 4);
+DEFINE_QNODE(slv_ipa_core_slave, SC8180X_SLAVE_IPA_CORE, 1, 8);
+DEFINE_QNODE(slv_ebi, SC8180X_SLAVE_EBI_CH0, 8, 4);
+DEFINE_QNODE(slv_qns2_mem_noc, SC8180X_SLAVE_MNOC_SF_MEM_NOC, 1, 32, SC8180X_MASTER_MNOC_SF_MEM_NOC);
+DEFINE_QNODE(slv_qns_mem_noc_hf, SC8180X_SLAVE_MNOC_HF_MEM_NOC, 2, 32, SC8180X_MASTER_MNOC_HF_MEM_NOC);
+DEFINE_QNODE(slv_srvc_mnoc, SC8180X_SLAVE_SERVICE_MNOC, 1, 4);
+DEFINE_QNODE(slv_qhs_apss, SC8180X_SLAVE_APPSS, 1, 8);
+DEFINE_QNODE(slv_qns_cnoc, SC8180X_SNOC_CNOC_SLV, 1, 8, SC8180X_SNOC_CNOC_MAS);
+DEFINE_QNODE(slv_qns_gemnoc_gc, SC8180X_SLAVE_SNOC_GEM_NOC_GC, 1, 8, SC8180X_MASTER_SNOC_GC_MEM_NOC);
+DEFINE_QNODE(slv_qns_gemnoc_sf, SC8180X_SLAVE_SNOC_GEM_NOC_SF, 1, 32, SC8180X_MASTER_SNOC_SF_MEM_NOC);
+DEFINE_QNODE(slv_qxs_imem, SC8180X_SLAVE_OCIMEM, 1, 8);
+DEFINE_QNODE(slv_qxs_pimem, SC8180X_SLAVE_PIMEM, 1, 8);
+DEFINE_QNODE(slv_srvc_snoc, SC8180X_SLAVE_SERVICE_SNOC, 1, 4);
+DEFINE_QNODE(slv_xs_pcie_0, SC8180X_SLAVE_PCIE_0, 1, 8);
+DEFINE_QNODE(slv_xs_pcie_1, SC8180X_SLAVE_PCIE_1, 1, 8);
+DEFINE_QNODE(slv_xs_pcie_2, SC8180X_SLAVE_PCIE_2, 1, 8);
+DEFINE_QNODE(slv_xs_pcie_3, SC8180X_SLAVE_PCIE_3, 1, 8);
+DEFINE_QNODE(slv_xs_qdss_stm, SC8180X_SLAVE_QDSS_STM, 1, 4);
+DEFINE_QNODE(slv_xs_sys_tcu_cfg, SC8180X_SLAVE_TCU, 1, 8);
+
+DEFINE_QBCM(bcm_acv, "ACV", false, &slv_ebi);
+DEFINE_QBCM(bcm_mc0, "MC0", false, &slv_ebi);
+DEFINE_QBCM(bcm_sh0, "SH0", false, &slv_qns_llcc);
+DEFINE_QBCM(bcm_mm0, "MM0", false, &slv_qns_mem_noc_hf);
+DEFINE_QBCM(bcm_co0, "CO0", false, &slv_qns_cdsp_mem_noc);
+DEFINE_QBCM(bcm_ce0, "CE0", false, &mas_qxm_crypto);
+DEFINE_QBCM(bcm_cn0, "CN0", false, &mas_qnm_snoc, &slv_qhs_a1_noc_cfg, &slv_qhs_a2_noc_cfg, &slv_qhs_ahb2phy_refgen_center, &slv_qhs_ahb2phy_refgen_east, &slv_qhs_ahb2phy_refgen_west, &slv_qhs_ahb2phy_south, &slv_qhs_aop, &slv_qhs_aoss, &slv_qhs_camera_cfg, &slv_qhs_clk_ctl, &slv_qhs_compute_dsp, &slv_qhs_cpr_cx, &slv_qhs_cpr_mmcx, &slv_qhs_cpr_mx, &slv_qhs_crypto0_cfg, &slv_qhs_ddrss_cfg, &slv_qhs_display_cfg, &slv_qhs_emac_cfg, &slv_qhs_glm, &slv_qhs_gpuss_cfg, &slv_qhs_imem_cfg, &slv_qhs_ipa, &slv_qhs_mnoc_cfg, &slv_qhs_npu_cfg, &slv_qhs_pcie0_cfg, &slv_qhs_pcie1_cfg, &slv_qhs_pcie2_cfg, &slv_qhs_pcie3_cfg, &slv_qhs_pdm, &slv_qhs_pimem_cfg, &slv_qhs_prng, &slv_qhs_qdss_cfg, &slv_qhs_qspi_0, &slv_qhs_qspi_1, &slv_qhs_qupv3_east0, &slv_qhs_qupv3_east1, &slv_qhs_qupv3_west, &slv_qhs_sdc2, &slv_qhs_sdc4, &slv_qhs_security, &slv_qhs_snoc_cfg, &slv_qhs_spss_cfg, &slv_qhs_tcsr, &slv_qhs_tlmm_east, &slv_qhs_tlmm_south, &slv_qhs_tlmm_west, &slv_qhs_tsif, &slv_qhs_ufs_card_cfg, &slv_qhs_ufs_mem0_cfg, &slv_qhs_ufs_mem1_cfg, &slv_qhs_usb3_0, &slv_qhs_usb3_1, &slv_qhs_usb3_2, &slv_qhs_venus_cfg, &slv_qhs_vsense_ctrl_cfg, &slv_srvc_cnoc);
+DEFINE_QBCM(bcm_mm1, "MM1", false, &mas_qxm_camnoc_hf0_uncomp, &mas_qxm_camnoc_hf1_uncomp, &mas_qxm_camnoc_sf_uncomp, &mas_qxm_camnoc_hf0, &mas_qxm_camnoc_hf1, &mas_qxm_mdp0, &mas_qxm_mdp1);
+DEFINE_QBCM(bcm_qup0, "QUP0", false, &mas_qhm_qup0, &mas_qhm_qup1, &mas_qhm_qup2);
+DEFINE_QBCM(bcm_sh2, "SH2", false, &slv_qns_gem_noc_snoc);
+DEFINE_QBCM(bcm_mm2, "MM2", false, &mas_qxm_camnoc_sf, &mas_qxm_rot, &mas_qxm_venus0, &mas_qxm_venus1, &mas_qxm_venus_arm9, &slv_qns2_mem_noc);
+DEFINE_QBCM(bcm_sh3, "SH3", false, &mas_acm_apps);
+DEFINE_QBCM(bcm_sn0, "SN0", false, &slv_qns_gemnoc_sf);
+DEFINE_QBCM(bcm_sn1, "SN1", false, &slv_qxs_imem);
+DEFINE_QBCM(bcm_sn2, "SN2", false, &slv_qns_gemnoc_gc);
+DEFINE_QBCM(bcm_co2, "CO2", false, &mas_qnm_npu);
+DEFINE_QBCM(bcm_ip0, "IP0", false, &slv_ipa_core_slave);
+DEFINE_QBCM(bcm_sn3, "SN3", false, &slv_srvc_aggre1_noc, &slv_qns_cnoc);
+DEFINE_QBCM(bcm_sn4, "SN4", false, &slv_qxs_pimem);
+DEFINE_QBCM(bcm_sn8, "SN8", false, &slv_xs_pcie_0, &slv_xs_pcie_1, &slv_xs_pcie_2, &slv_xs_pcie_3);
+DEFINE_QBCM(bcm_sn9, "SN9", false, &mas_qnm_aggre1_noc);
+DEFINE_QBCM(bcm_sn11, "SN11", false, &mas_qnm_aggre2_noc);
+DEFINE_QBCM(bcm_sn14, "SN14", false, &slv_qns_pcie_mem_noc);
+DEFINE_QBCM(bcm_sn15, "SN15", false, &mas_qnm_gemnoc);
+
+static struct qcom_icc_bcm *aggre1_noc_bcms[] = {
+ &bcm_sn3,
+ &bcm_ce0,
+ &bcm_qup0,
+};
+
+static struct qcom_icc_bcm *aggre2_noc_bcms[] = {
+ &bcm_sn14,
+ &bcm_ce0,
+ &bcm_qup0,
+};
+
+static struct qcom_icc_bcm *camnoc_virt_bcms[] = {
+ &bcm_mm1,
+};
+
+static struct qcom_icc_bcm *compute_noc_bcms[] = {
+ &bcm_co0,
+ &bcm_co2,
+};
+
+static struct qcom_icc_bcm *config_noc_bcms[] = {
+ &bcm_cn0,
+};
+
+static struct qcom_icc_bcm *gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh2,
+ &bcm_sh3,
+};
+
+static struct qcom_icc_bcm *ipa_virt_bcms[] = {
+ &bcm_ip0,
+};
+
+static struct qcom_icc_bcm *mc_virt_bcms[] = {
+ &bcm_mc0,
+ &bcm_acv,
+};
+
+static struct qcom_icc_bcm *mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+ &bcm_mm2,
+};
+
+static struct qcom_icc_bcm *system_noc_bcms[] = {
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn2,
+ &bcm_sn3,
+ &bcm_sn4,
+ &bcm_sn8,
+ &bcm_sn9,
+ &bcm_sn11,
+ &bcm_sn15,
+};
+
+static struct qcom_icc_node *aggre1_noc_nodes[] = {
+ [MASTER_A1NOC_CFG] = &mas_qhm_a1noc_cfg,
+ [MASTER_UFS_CARD] = &mas_xm_ufs_card,
+ [MASTER_UFS_GEN4] = &mas_xm_ufs_g4,
+ [MASTER_UFS_MEM] = &mas_xm_ufs_mem,
+ [MASTER_USB3] = &mas_xm_usb3_0,
+ [MASTER_USB3_1] = &mas_xm_usb3_1,
+ [MASTER_USB3_2] = &mas_xm_usb3_2,
+ [A1NOC_SNOC_SLV] = &slv_qns_a1noc_snoc,
+ [SLAVE_SERVICE_A1NOC] = &slv_srvc_aggre1_noc,
+};
+
+static struct qcom_icc_node *aggre2_noc_nodes[] = {
+ [MASTER_A2NOC_CFG] = &mas_qhm_a2noc_cfg,
+ [MASTER_QDSS_BAM] = &mas_qhm_qdss_bam,
+ [MASTER_QSPI_0] = &mas_qhm_qspi,
+ [MASTER_QSPI_1] = &mas_qhm_qspi1,
+ [MASTER_QUP_0] = &mas_qhm_qup0,
+ [MASTER_QUP_1] = &mas_qhm_qup1,
+ [MASTER_QUP_2] = &mas_qhm_qup2,
+ [MASTER_SENSORS_AHB] = &mas_qhm_sensorss_ahb,
+ [MASTER_CRYPTO_CORE_0] = &mas_qxm_crypto,
+ [MASTER_IPA] = &mas_qxm_ipa,
+ [MASTER_EMAC] = &mas_xm_emac,
+ [MASTER_PCIE] = &mas_xm_pcie3_0,
+ [MASTER_PCIE_1] = &mas_xm_pcie3_1,
+ [MASTER_PCIE_2] = &mas_xm_pcie3_2,
+ [MASTER_PCIE_3] = &mas_xm_pcie3_3,
+ [MASTER_QDSS_ETR] = &mas_xm_qdss_etr,
+ [MASTER_SDCC_2] = &mas_xm_sdc2,
+ [MASTER_SDCC_4] = &mas_xm_sdc4,
+ [A2NOC_SNOC_SLV] = &slv_qns_a2noc_snoc,
+ [SLAVE_ANOC_PCIE_GEM_NOC] = &slv_qns_pcie_mem_noc,
+ [SLAVE_SERVICE_A2NOC] = &slv_srvc_aggre2_noc,
+};
+
+static struct qcom_icc_node *camnoc_virt_nodes[] = {
+ [MASTER_CAMNOC_HF0_UNCOMP] = &mas_qxm_camnoc_hf0_uncomp,
+ [MASTER_CAMNOC_HF1_UNCOMP] = &mas_qxm_camnoc_hf1_uncomp,
+ [MASTER_CAMNOC_SF_UNCOMP] = &mas_qxm_camnoc_sf_uncomp,
+ [SLAVE_CAMNOC_UNCOMP] = &slv_qns_camnoc_uncomp,
+};
+
+static struct qcom_icc_node *compute_noc_nodes[] = {
+ [MASTER_NPU] = &mas_qnm_npu,
+ [SLAVE_CDSP_MEM_NOC] = &slv_qns_cdsp_mem_noc,
+};
+
+static struct qcom_icc_node *config_noc_nodes[] = {
+ [SNOC_CNOC_MAS] = &mas_qnm_snoc,
+ [SLAVE_A1NOC_CFG] = &slv_qhs_a1_noc_cfg,
+ [SLAVE_A2NOC_CFG] = &slv_qhs_a2_noc_cfg,
+ [SLAVE_AHB2PHY_CENTER] = &slv_qhs_ahb2phy_refgen_center,
+ [SLAVE_AHB2PHY_EAST] = &slv_qhs_ahb2phy_refgen_east,
+ [SLAVE_AHB2PHY_WEST] = &slv_qhs_ahb2phy_refgen_west,
+ [SLAVE_AHB2PHY_SOUTH] = &slv_qhs_ahb2phy_south,
+ [SLAVE_AOP] = &slv_qhs_aop,
+ [SLAVE_AOSS] = &slv_qhs_aoss,
+ [SLAVE_CAMERA_CFG] = &slv_qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &slv_qhs_clk_ctl,
+ [SLAVE_CDSP_CFG] = &slv_qhs_compute_dsp,
+ [SLAVE_RBCPR_CX_CFG] = &slv_qhs_cpr_cx,
+ [SLAVE_RBCPR_MMCX_CFG] = &slv_qhs_cpr_mmcx,
+ [SLAVE_RBCPR_MX_CFG] = &slv_qhs_cpr_mx,
+ [SLAVE_CRYPTO_0_CFG] = &slv_qhs_crypto0_cfg,
+ [SLAVE_CNOC_DDRSS] = &slv_qhs_ddrss_cfg,
+ [SLAVE_DISPLAY_CFG] = &slv_qhs_display_cfg,
+ [SLAVE_EMAC_CFG] = &slv_qhs_emac_cfg,
+ [SLAVE_GLM] = &slv_qhs_glm,
+ [SLAVE_GRAPHICS_3D_CFG] = &slv_qhs_gpuss_cfg,
+ [SLAVE_IMEM_CFG] = &slv_qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &slv_qhs_ipa,
+ [SLAVE_CNOC_MNOC_CFG] = &slv_qhs_mnoc_cfg,
+ [SLAVE_NPU_CFG] = &slv_qhs_npu_cfg,
+ [SLAVE_PCIE_0_CFG] = &slv_qhs_pcie0_cfg,
+ [SLAVE_PCIE_1_CFG] = &slv_qhs_pcie1_cfg,
+ [SLAVE_PCIE_2_CFG] = &slv_qhs_pcie2_cfg,
+ [SLAVE_PCIE_3_CFG] = &slv_qhs_pcie3_cfg,
+ [SLAVE_PDM] = &slv_qhs_pdm,
+ [SLAVE_PIMEM_CFG] = &slv_qhs_pimem_cfg,
+ [SLAVE_PRNG] = &slv_qhs_prng,
+ [SLAVE_QDSS_CFG] = &slv_qhs_qdss_cfg,
+ [SLAVE_QSPI_0] = &slv_qhs_qspi_0,
+ [SLAVE_QSPI_1] = &slv_qhs_qspi_1,
+ [SLAVE_QUP_1] = &slv_qhs_qupv3_east0,
+ [SLAVE_QUP_2] = &slv_qhs_qupv3_east1,
+ [SLAVE_QUP_0] = &slv_qhs_qupv3_west,
+ [SLAVE_SDCC_2] = &slv_qhs_sdc2,
+ [SLAVE_SDCC_4] = &slv_qhs_sdc4,
+ [SLAVE_SECURITY] = &slv_qhs_security,
+ [SLAVE_SNOC_CFG] = &slv_qhs_snoc_cfg,
+ [SLAVE_SPSS_CFG] = &slv_qhs_spss_cfg,
+ [SLAVE_TCSR] = &slv_qhs_tcsr,
+ [SLAVE_TLMM_EAST] = &slv_qhs_tlmm_east,
+ [SLAVE_TLMM_SOUTH] = &slv_qhs_tlmm_south,
+ [SLAVE_TLMM_WEST] = &slv_qhs_tlmm_west,
+ [SLAVE_TSIF] = &slv_qhs_tsif,
+ [SLAVE_UFS_CARD_CFG] = &slv_qhs_ufs_card_cfg,
+ [SLAVE_UFS_MEM_0_CFG] = &slv_qhs_ufs_mem0_cfg,
+ [SLAVE_UFS_MEM_1_CFG] = &slv_qhs_ufs_mem1_cfg,
+ [SLAVE_USB3] = &slv_qhs_usb3_0,
+ [SLAVE_USB3_1] = &slv_qhs_usb3_1,
+ [SLAVE_USB3_2] = &slv_qhs_usb3_2,
+ [SLAVE_VENUS_CFG] = &slv_qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &slv_qhs_vsense_ctrl_cfg,
+ [SLAVE_SERVICE_CNOC] = &slv_srvc_cnoc,
+};
+
+static struct qcom_icc_node *dc_noc_nodes[] = {
+ [MASTER_CNOC_DC_NOC] = &mas_qhm_cnoc_dc_noc,
+ [SLAVE_GEM_NOC_CFG] = &slv_qhs_gemnoc,
+ [SLAVE_LLCC_CFG] = &slv_qhs_llcc,
+};
+
+static struct qcom_icc_node *gem_noc_nodes[] = {
+ [MASTER_AMPSS_M0] = &mas_acm_apps,
+ [MASTER_GPU_TCU] = &mas_acm_gpu_tcu,
+ [MASTER_SYS_TCU] = &mas_acm_sys_tcu,
+ [MASTER_GEM_NOC_CFG] = &mas_qhm_gemnoc_cfg,
+ [MASTER_COMPUTE_NOC] = &mas_qnm_cmpnoc,
+ [MASTER_GRAPHICS_3D] = &mas_qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &mas_qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &mas_qnm_mnoc_sf,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &mas_qnm_pcie,
+ [MASTER_SNOC_GC_MEM_NOC] = &mas_qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &mas_qnm_snoc_sf,
+ [MASTER_ECC] = &mas_qxm_ecc,
+ [SLAVE_MSS_PROC_MS_MPU_CFG] = &slv_qhs_mdsp_ms_mpu_cfg,
+ [SLAVE_ECC] = &slv_qns_ecc,
+ [SLAVE_GEM_NOC_SNOC] = &slv_qns_gem_noc_snoc,
+ [SLAVE_LLCC] = &slv_qns_llcc,
+ [SLAVE_SERVICE_GEM_NOC] = &slv_srvc_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC_1] = &slv_srvc_gemnoc1,
+};
+
+static struct qcom_icc_node *ipa_virt_nodes[] = {
+ [MASTER_IPA_CORE] = &mas_ipa_core_master,
+ [SLAVE_IPA_CORE] = &slv_ipa_core_slave,
+};
+
+static struct qcom_icc_node *mc_virt_nodes[] = {
+ [MASTER_LLCC] = &mas_llcc_mc,
+ [SLAVE_EBI_CH0] = &slv_ebi,
+};
+
+static struct qcom_icc_node *mmss_noc_nodes[] = {
+ [MASTER_CNOC_MNOC_CFG] = &mas_qhm_mnoc_cfg,
+ [MASTER_CAMNOC_HF0] = &mas_qxm_camnoc_hf0,
+ [MASTER_CAMNOC_HF1] = &mas_qxm_camnoc_hf1,
+ [MASTER_CAMNOC_SF] = &mas_qxm_camnoc_sf,
+ [MASTER_MDP_PORT0] = &mas_qxm_mdp0,
+ [MASTER_MDP_PORT1] = &mas_qxm_mdp1,
+ [MASTER_ROTATOR] = &mas_qxm_rot,
+ [MASTER_VIDEO_P0] = &mas_qxm_venus0,
+ [MASTER_VIDEO_P1] = &mas_qxm_venus1,
+ [MASTER_VIDEO_PROC] = &mas_qxm_venus_arm9,
+ [SLAVE_MNOC_SF_MEM_NOC] = &slv_qns2_mem_noc,
+ [SLAVE_MNOC_HF_MEM_NOC] = &slv_qns_mem_noc_hf,
+ [SLAVE_SERVICE_MNOC] = &slv_srvc_mnoc,
+};
+
+static struct qcom_icc_node *system_noc_nodes[] = {
+ [MASTER_SNOC_CFG] = &mas_qhm_snoc_cfg,
+ [A1NOC_SNOC_MAS] = &mas_qnm_aggre1_noc,
+ [A2NOC_SNOC_MAS] = &mas_qnm_aggre2_noc,
+ [MASTER_GEM_NOC_SNOC] = &mas_qnm_gemnoc,
+ [MASTER_PIMEM] = &mas_qxm_pimem,
+ [MASTER_GIC] = &mas_xm_gic,
+ [SLAVE_APPSS] = &slv_qhs_apss,
+ [SNOC_CNOC_SLV] = &slv_qns_cnoc,
+ [SLAVE_SNOC_GEM_NOC_GC] = &slv_qns_gemnoc_gc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &slv_qns_gemnoc_sf,
+ [SLAVE_OCIMEM] = &slv_qxs_imem,
+ [SLAVE_PIMEM] = &slv_qxs_pimem,
+ [SLAVE_SERVICE_SNOC] = &slv_srvc_snoc,
+ [SLAVE_QDSS_STM] = &slv_xs_qdss_stm,
+ [SLAVE_TCU] = &slv_xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc sc8180x_aggre1_noc = {
+ .nodes = aggre1_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
+ .bcms = aggre1_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_aggre2_noc = {
+ .nodes = aggre2_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
+ .bcms = aggre2_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_camnoc_virt = {
+ .nodes = camnoc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(camnoc_virt_nodes),
+ .bcms = camnoc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(camnoc_virt_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_compute_noc = {
+ .nodes = compute_noc_nodes,
+ .num_nodes = ARRAY_SIZE(compute_noc_nodes),
+ .bcms = compute_noc_bcms,
+ .num_bcms = ARRAY_SIZE(compute_noc_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_config_noc = {
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_dc_noc = {
+ .nodes = dc_noc_nodes,
+ .num_nodes = ARRAY_SIZE(dc_noc_nodes),
+};
+
+static const struct qcom_icc_desc sc8180x_gem_noc = {
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_ipa_virt = {
+ .nodes = ipa_virt_nodes,
+ .num_nodes = ARRAY_SIZE(ipa_virt_nodes),
+ .bcms = ipa_virt_bcms,
+ .num_bcms = ARRAY_SIZE(ipa_virt_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_mmss_noc = {
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static const struct qcom_icc_desc sc8180x_system_noc = {
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static int qnoc_probe(struct platform_device *pdev)
+{
+ const struct qcom_icc_desc *desc;
+ struct icc_onecell_data *data;
+ struct icc_provider *provider;
+ struct qcom_icc_node **qnodes;
+ struct qcom_icc_provider *qp;
+ struct icc_node *node;
+ size_t num_nodes, i;
+ int ret;
+
+ desc = device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ qnodes = desc->nodes;
+ num_nodes = desc->num_nodes;
+
+ qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
+ if (!qp)
+ return -ENOMEM;
+
+ data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ provider = &qp->provider;
+ provider->dev = &pdev->dev;
+ provider->set = qcom_icc_set;
+ provider->pre_aggregate = qcom_icc_pre_aggregate;
+ provider->aggregate = qcom_icc_aggregate;
+ provider->xlate = of_icc_xlate_onecell;
+ INIT_LIST_HEAD(&provider->nodes);
+ provider->data = data;
+
+ qp->dev = &pdev->dev;
+ qp->bcms = desc->bcms;
+ qp->num_bcms = desc->num_bcms;
+
+ qp->voter = of_bcm_voter_get(qp->dev, NULL);
+ if (IS_ERR(qp->voter))
+ return PTR_ERR(qp->voter);
+
+ ret = icc_provider_add(provider);
+ if (ret) {
+ dev_err(&pdev->dev, "error adding interconnect provider\n");
+ return ret;
+ }
+
+ for (i = 0; i < qp->num_bcms; i++)
+ qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
+
+ for (i = 0; i < num_nodes; i++) {
+ size_t j;
+
+ if (!qnodes[i])
+ continue;
+
+ node = icc_node_create(qnodes[i]->id);
+ if (IS_ERR(node)) {
+ ret = PTR_ERR(node);
+ goto err;
+ }
+
+ node->name = qnodes[i]->name;
+ node->data = qnodes[i];
+ icc_node_add(node, provider);
+
+ for (j = 0; j < qnodes[i]->num_links; j++)
+ icc_link_create(node, qnodes[i]->links[j]);
+
+ data->nodes[i] = node;
+ }
+ data->num_nodes = num_nodes;
+
+ platform_set_drvdata(pdev, qp);
+
+ return 0;
+err:
+ icc_nodes_remove(provider);
+ icc_provider_del(provider);
+ return ret;
+}
+
+static int qnoc_remove(struct platform_device *pdev)
+{
+ struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
+
+ icc_nodes_remove(&qp->provider);
+ return icc_provider_del(&qp->provider);
+}
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,sc8180x-aggre1-noc", .data = &sc8180x_aggre1_noc },
+ { .compatible = "qcom,sc8180x-aggre2-noc", .data = &sc8180x_aggre2_noc },
+ { .compatible = "qcom,sc8180x-camnoc-virt", .data = &sc8180x_camnoc_virt },
+ { .compatible = "qcom,sc8180x-compute-noc", .data = &sc8180x_compute_noc, },
+ { .compatible = "qcom,sc8180x-config-noc", .data = &sc8180x_config_noc },
+ { .compatible = "qcom,sc8180x-dc-noc", .data = &sc8180x_dc_noc },
+ { .compatible = "qcom,sc8180x-gem-noc", .data = &sc8180x_gem_noc },
+ { .compatible = "qcom,sc8180x-ipa-virt", .data = &sc8180x_ipa_virt },
+ { .compatible = "qcom,sc8180x-mc-virt", .data = &sc8180x_mc_virt },
+ { .compatible = "qcom,sc8180x-mmss-noc", .data = &sc8180x_mmss_noc },
+ { .compatible = "qcom,sc8180x-system-noc", .data = &sc8180x_system_noc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qnoc_probe,
+ .remove = qnoc_remove,
+ .driver = {
+ .name = "qnoc-sc8180x",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+module_platform_driver(qnoc_driver);
+
+MODULE_DESCRIPTION("Qualcomm sc8180x NoC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/interconnect/qcom/sc8180x.h b/drivers/interconnect/qcom/sc8180x.h
new file mode 100644
index 000000000000..e70cf7032f80
--- /dev/null
+++ b/drivers/interconnect/qcom/sc8180x.h
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Qualcomm #define SC8180X interconnect IDs
+ *
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __DRIVERS_INTERCONNECT_QCOM_SC8180X_H
+#define __DRIVERS_INTERCONNECT_QCOM_SC8180X_H
+
+#define SC8180X_MASTER_A1NOC_CFG 1
+#define SC8180X_MASTER_UFS_CARD 2
+#define SC8180X_MASTER_UFS_GEN4 3
+#define SC8180X_MASTER_UFS_MEM 4
+#define SC8180X_MASTER_USB3 5
+#define SC8180X_MASTER_USB3_1 6
+#define SC8180X_MASTER_USB3_2 7
+#define SC8180X_MASTER_A2NOC_CFG 8
+#define SC8180X_MASTER_QDSS_BAM 9
+#define SC8180X_MASTER_QSPI_0 10
+#define SC8180X_MASTER_QSPI_1 11
+#define SC8180X_MASTER_QUP_0 12
+#define SC8180X_MASTER_QUP_1 13
+#define SC8180X_MASTER_QUP_2 14
+#define SC8180X_MASTER_SENSORS_AHB 15
+#define SC8180X_MASTER_CRYPTO_CORE_0 16
+#define SC8180X_MASTER_IPA 17
+#define SC8180X_MASTER_EMAC 18
+#define SC8180X_MASTER_PCIE 19
+#define SC8180X_MASTER_PCIE_1 20
+#define SC8180X_MASTER_PCIE_2 21
+#define SC8180X_MASTER_PCIE_3 22
+#define SC8180X_MASTER_QDSS_ETR 23
+#define SC8180X_MASTER_SDCC_2 24
+#define SC8180X_MASTER_SDCC_4 25
+#define SC8180X_MASTER_CAMNOC_HF0_UNCOMP 26
+#define SC8180X_MASTER_CAMNOC_HF1_UNCOMP 27
+#define SC8180X_MASTER_CAMNOC_SF_UNCOMP 28
+#define SC8180X_MASTER_NPU 29
+#define SC8180X_SNOC_CNOC_MAS 30
+#define SC8180X_MASTER_CNOC_DC_NOC 31
+#define SC8180X_MASTER_AMPSS_M0 32
+#define SC8180X_MASTER_GPU_TCU 33
+#define SC8180X_MASTER_SYS_TCU 34
+#define SC8180X_MASTER_GEM_NOC_CFG 35
+#define SC8180X_MASTER_COMPUTE_NOC 36
+#define SC8180X_MASTER_GRAPHICS_3D 37
+#define SC8180X_MASTER_MNOC_HF_MEM_NOC 38
+#define SC8180X_MASTER_MNOC_SF_MEM_NOC 39
+#define SC8180X_MASTER_GEM_NOC_PCIE_SNOC 40
+#define SC8180X_MASTER_SNOC_GC_MEM_NOC 41
+#define SC8180X_MASTER_SNOC_SF_MEM_NOC 42
+#define SC8180X_MASTER_ECC 43
+#define SC8180X_MASTER_IPA_CORE 44
+#define SC8180X_MASTER_LLCC 45
+#define SC8180X_MASTER_CNOC_MNOC_CFG 46
+#define SC8180X_MASTER_CAMNOC_HF0 47
+#define SC8180X_MASTER_CAMNOC_HF1 48
+#define SC8180X_MASTER_CAMNOC_SF 49
+#define SC8180X_MASTER_MDP_PORT0 50
+#define SC8180X_MASTER_MDP_PORT1 51
+#define SC8180X_MASTER_ROTATOR 52
+#define SC8180X_MASTER_VIDEO_P0 53
+#define SC8180X_MASTER_VIDEO_P1 54
+#define SC8180X_MASTER_VIDEO_PROC 55
+#define SC8180X_MASTER_SNOC_CFG 56
+#define SC8180X_A1NOC_SNOC_MAS 57
+#define SC8180X_A2NOC_SNOC_MAS 58
+#define SC8180X_MASTER_GEM_NOC_SNOC 59
+#define SC8180X_MASTER_PIMEM 60
+#define SC8180X_MASTER_GIC 61
+#define SC8180X_MASTER_MNOC_HF_MEM_NOC_DISPLAY 62
+#define SC8180X_MASTER_MNOC_SF_MEM_NOC_DISPLAY 63
+#define SC8180X_MASTER_LLCC_DISPLAY 64
+#define SC8180X_MASTER_MDP_PORT0_DISPLAY 65
+#define SC8180X_MASTER_MDP_PORT1_DISPLAY 66
+#define SC8180X_MASTER_ROTATOR_DISPLAY 67
+#define SC8180X_A1NOC_SNOC_SLV 68
+#define SC8180X_SLAVE_SERVICE_A1NOC 69
+#define SC8180X_A2NOC_SNOC_SLV 70
+#define SC8180X_SLAVE_ANOC_PCIE_GEM_NOC 71
+#define SC8180X_SLAVE_SERVICE_A2NOC 72
+#define SC8180X_SLAVE_CAMNOC_UNCOMP 73
+#define SC8180X_SLAVE_CDSP_MEM_NOC 74
+#define SC8180X_SLAVE_A1NOC_CFG 75
+#define SC8180X_SLAVE_A2NOC_CFG 76
+#define SC8180X_SLAVE_AHB2PHY_CENTER 77
+#define SC8180X_SLAVE_AHB2PHY_EAST 78
+#define SC8180X_SLAVE_AHB2PHY_WEST 79
+#define SC8180X_SLAVE_AHB2PHY_SOUTH 80
+#define SC8180X_SLAVE_AOP 81
+#define SC8180X_SLAVE_AOSS 82
+#define SC8180X_SLAVE_CAMERA_CFG 83
+#define SC8180X_SLAVE_CLK_CTL 84
+#define SC8180X_SLAVE_CDSP_CFG 85
+#define SC8180X_SLAVE_RBCPR_CX_CFG 86
+#define SC8180X_SLAVE_RBCPR_MMCX_CFG 87
+#define SC8180X_SLAVE_RBCPR_MX_CFG 88
+#define SC8180X_SLAVE_CRYPTO_0_CFG 89
+#define SC8180X_SLAVE_CNOC_DDRSS 90
+#define SC8180X_SLAVE_DISPLAY_CFG 91
+#define SC8180X_SLAVE_EMAC_CFG 92
+#define SC8180X_SLAVE_GLM 93
+#define SC8180X_SLAVE_GRAPHICS_3D_CFG 94
+#define SC8180X_SLAVE_IMEM_CFG 95
+#define SC8180X_SLAVE_IPA_CFG 96
+#define SC8180X_SLAVE_CNOC_MNOC_CFG 97
+#define SC8180X_SLAVE_NPU_CFG 98
+#define SC8180X_SLAVE_PCIE_0_CFG 99
+#define SC8180X_SLAVE_PCIE_1_CFG 100
+#define SC8180X_SLAVE_PCIE_2_CFG 101
+#define SC8180X_SLAVE_PCIE_3_CFG 102
+#define SC8180X_SLAVE_PDM 103
+#define SC8180X_SLAVE_PIMEM_CFG 104
+#define SC8180X_SLAVE_PRNG 105
+#define SC8180X_SLAVE_QDSS_CFG 106
+#define SC8180X_SLAVE_QSPI_0 107
+#define SC8180X_SLAVE_QSPI_1 108
+#define SC8180X_SLAVE_QUP_1 109
+#define SC8180X_SLAVE_QUP_2 110
+#define SC8180X_SLAVE_QUP_0 111
+#define SC8180X_SLAVE_SDCC_2 112
+#define SC8180X_SLAVE_SDCC_4 113
+#define SC8180X_SLAVE_SECURITY 114
+#define SC8180X_SLAVE_SNOC_CFG 115
+#define SC8180X_SLAVE_SPSS_CFG 116
+#define SC8180X_SLAVE_TCSR 117
+#define SC8180X_SLAVE_TLMM_EAST 118
+#define SC8180X_SLAVE_TLMM_SOUTH 119
+#define SC8180X_SLAVE_TLMM_WEST 120
+#define SC8180X_SLAVE_TSIF 121
+#define SC8180X_SLAVE_UFS_CARD_CFG 122
+#define SC8180X_SLAVE_UFS_MEM_0_CFG 123
+#define SC8180X_SLAVE_UFS_MEM_1_CFG 124
+#define SC8180X_SLAVE_USB3 125
+#define SC8180X_SLAVE_USB3_1 126
+#define SC8180X_SLAVE_USB3_2 127
+#define SC8180X_SLAVE_VENUS_CFG 128
+#define SC8180X_SLAVE_VSENSE_CTRL_CFG 129
+#define SC8180X_SLAVE_SERVICE_CNOC 130
+#define SC8180X_SLAVE_GEM_NOC_CFG 131
+#define SC8180X_SLAVE_LLCC_CFG 132
+#define SC8180X_SLAVE_MSS_PROC_MS_MPU_CFG 133
+#define SC8180X_SLAVE_ECC 134
+#define SC8180X_SLAVE_GEM_NOC_SNOC 135
+#define SC8180X_SLAVE_LLCC 136
+#define SC8180X_SLAVE_SERVICE_GEM_NOC 137
+#define SC8180X_SLAVE_SERVICE_GEM_NOC_1 138
+#define SC8180X_SLAVE_IPA_CORE 139
+#define SC8180X_SLAVE_EBI_CH0 140
+#define SC8180X_SLAVE_MNOC_SF_MEM_NOC 141
+#define SC8180X_SLAVE_MNOC_HF_MEM_NOC 142
+#define SC8180X_SLAVE_SERVICE_MNOC 143
+#define SC8180X_SLAVE_APPSS 144
+#define SC8180X_SNOC_CNOC_SLV 145
+#define SC8180X_SLAVE_SNOC_GEM_NOC_GC 146
+#define SC8180X_SLAVE_SNOC_GEM_NOC_SF 147
+#define SC8180X_SLAVE_OCIMEM 148
+#define SC8180X_SLAVE_PIMEM 149
+#define SC8180X_SLAVE_SERVICE_SNOC 150
+#define SC8180X_SLAVE_PCIE_0 151
+#define SC8180X_SLAVE_PCIE_1 152
+#define SC8180X_SLAVE_PCIE_2 153
+#define SC8180X_SLAVE_PCIE_3 154
+#define SC8180X_SLAVE_QDSS_STM 155
+#define SC8180X_SLAVE_TCU 156
+#define SC8180X_SLAVE_LLCC_DISPLAY 157
+#define SC8180X_SLAVE_EBI_CH0_DISPLAY 158
+#define SC8180X_SLAVE_MNOC_SF_MEM_NOC_DISPLAY 159
+#define SC8180X_SLAVE_MNOC_HF_MEM_NOC_DISPLAY 160
+#define SC8180X_MASTER_OSM_L3_APPS 161
+#define SC8180X_SLAVE_OSM_L3 162
+
+#endif
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
index 366870150cbd..d2195079c228 100644
--- a/drivers/interconnect/qcom/sdm845.c
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -440,101 +440,6 @@ static const struct qcom_icc_desc sdm845_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
-static int qnoc_probe(struct platform_device *pdev)
-{
- const struct qcom_icc_desc *desc;
- struct icc_onecell_data *data;
- struct icc_provider *provider;
- struct qcom_icc_node **qnodes;
- struct qcom_icc_provider *qp;
- struct icc_node *node;
- size_t num_nodes, i;
- int ret;
-
- desc = device_get_match_data(&pdev->dev);
- if (!desc)
- return -EINVAL;
-
- qnodes = desc->nodes;
- num_nodes = desc->num_nodes;
-
- qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return -ENOMEM;
-
- data = devm_kzalloc(&pdev->dev, struct_size(data, nodes, num_nodes),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- provider = &qp->provider;
- provider->dev = &pdev->dev;
- provider->set = qcom_icc_set;
- provider->pre_aggregate = qcom_icc_pre_aggregate;
- provider->aggregate = qcom_icc_aggregate;
- provider->xlate_extended = qcom_icc_xlate_extended;
- INIT_LIST_HEAD(&provider->nodes);
- provider->data = data;
-
- qp->dev = &pdev->dev;
- qp->bcms = desc->bcms;
- qp->num_bcms = desc->num_bcms;
-
- qp->voter = of_bcm_voter_get(qp->dev, NULL);
- if (IS_ERR(qp->voter)) {
- dev_err(&pdev->dev, "bcm_voter err:%ld\n", PTR_ERR(qp->voter));
- return PTR_ERR(qp->voter);
- }
-
- ret = icc_provider_add(provider);
- if (ret) {
- dev_err(&pdev->dev, "error adding interconnect provider\n");
- return ret;
- }
-
- for (i = 0; i < qp->num_bcms; i++)
- qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
- for (i = 0; i < num_nodes; i++) {
- size_t j;
-
- if (!qnodes[i])
- continue;
-
- node = icc_node_create(qnodes[i]->id);
- if (IS_ERR(node)) {
- ret = PTR_ERR(node);
- goto err;
- }
-
- node->name = qnodes[i]->name;
- node->data = qnodes[i];
- icc_node_add(node, provider);
-
- for (j = 0; j < qnodes[i]->num_links; j++)
- icc_link_create(node, qnodes[i]->links[j]);
-
- data->nodes[i] = node;
- }
- data->num_nodes = num_nodes;
-
- platform_set_drvdata(pdev, qp);
-
- return 0;
-err:
- icc_nodes_remove(provider);
- icc_provider_del(provider);
- return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
- struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
- icc_nodes_remove(&qp->provider);
- return icc_provider_del(&qp->provider);
-}
-
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sdm845-aggre1-noc",
.data = &sdm845_aggre1_noc},
@@ -557,8 +462,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
- .probe = qnoc_probe,
- .remove = qnoc_remove,
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdm845",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx55.c b/drivers/interconnect/qcom/sdx55.c
index a5a122ee3d21..03d604f84cc5 100644
--- a/drivers/interconnect/qcom/sdx55.c
+++ b/drivers/interconnect/qcom/sdx55.c
@@ -235,98 +235,6 @@ static const struct qcom_icc_desc sdx55_ipa_virt = {
.num_bcms = ARRAY_SIZE(ipa_virt_bcms),
};
-static int qnoc_probe(struct platform_device *pdev)
-{
- const struct qcom_icc_desc *desc;
- struct icc_onecell_data *data;
- struct icc_provider *provider;
- struct qcom_icc_node **qnodes;
- struct qcom_icc_provider *qp;
- struct icc_node *node;
- size_t num_nodes, i;
- int ret;
-
- desc = device_get_match_data(&pdev->dev);
- if (!desc)
- return -EINVAL;
-
- qnodes = desc->nodes;
- num_nodes = desc->num_nodes;
-
- qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return -ENOMEM;
-
- data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- provider = &qp->provider;
- provider->dev = &pdev->dev;
- provider->set = qcom_icc_set;
- provider->pre_aggregate = qcom_icc_pre_aggregate;
- provider->aggregate = qcom_icc_aggregate;
- provider->xlate = of_icc_xlate_onecell;
- INIT_LIST_HEAD(&provider->nodes);
- provider->data = data;
-
- qp->dev = &pdev->dev;
- qp->bcms = desc->bcms;
- qp->num_bcms = desc->num_bcms;
-
- qp->voter = of_bcm_voter_get(qp->dev, NULL);
- if (IS_ERR(qp->voter))
- return PTR_ERR(qp->voter);
-
- ret = icc_provider_add(provider);
- if (ret) {
- dev_err(&pdev->dev, "error adding interconnect provider\n");
- return ret;
- }
-
- for (i = 0; i < qp->num_bcms; i++)
- qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
- for (i = 0; i < num_nodes; i++) {
- size_t j;
-
- if (!qnodes[i])
- continue;
-
- node = icc_node_create(qnodes[i]->id);
- if (IS_ERR(node)) {
- ret = PTR_ERR(node);
- goto err;
- }
-
- node->name = qnodes[i]->name;
- node->data = qnodes[i];
- icc_node_add(node, provider);
-
- for (j = 0; j < qnodes[i]->num_links; j++)
- icc_link_create(node, qnodes[i]->links[j]);
-
- data->nodes[i] = node;
- }
- data->num_nodes = num_nodes;
-
- platform_set_drvdata(pdev, qp);
-
- return 0;
-err:
- icc_nodes_remove(provider);
- icc_provider_del(provider);
- return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
- struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
- icc_nodes_remove(&qp->provider);
- return icc_provider_del(&qp->provider);
-}
-
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sdx55-mc-virt",
.data = &sdx55_mc_virt},
@@ -341,8 +249,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
- .probe = qnoc_probe,
- .remove = qnoc_remove,
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx55",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8150.c b/drivers/interconnect/qcom/sm8150.c
index c76b2c7f9b10..2a85f53802b5 100644
--- a/drivers/interconnect/qcom/sm8150.c
+++ b/drivers/interconnect/qcom/sm8150.c
@@ -502,98 +502,6 @@ static struct qcom_icc_desc sm8150_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
-static int qnoc_probe(struct platform_device *pdev)
-{
- const struct qcom_icc_desc *desc;
- struct icc_onecell_data *data;
- struct icc_provider *provider;
- struct qcom_icc_node **qnodes;
- struct qcom_icc_provider *qp;
- struct icc_node *node;
- size_t num_nodes, i;
- int ret;
-
- desc = device_get_match_data(&pdev->dev);
- if (!desc)
- return -EINVAL;
-
- qnodes = desc->nodes;
- num_nodes = desc->num_nodes;
-
- qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return -ENOMEM;
-
- data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- provider = &qp->provider;
- provider->dev = &pdev->dev;
- provider->set = qcom_icc_set;
- provider->pre_aggregate = qcom_icc_pre_aggregate;
- provider->aggregate = qcom_icc_aggregate;
- provider->xlate = of_icc_xlate_onecell;
- INIT_LIST_HEAD(&provider->nodes);
- provider->data = data;
-
- qp->dev = &pdev->dev;
- qp->bcms = desc->bcms;
- qp->num_bcms = desc->num_bcms;
-
- qp->voter = of_bcm_voter_get(qp->dev, NULL);
- if (IS_ERR(qp->voter))
- return PTR_ERR(qp->voter);
-
- ret = icc_provider_add(provider);
- if (ret) {
- dev_err(&pdev->dev, "error adding interconnect provider\n");
- return ret;
- }
-
- for (i = 0; i < qp->num_bcms; i++)
- qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
- for (i = 0; i < num_nodes; i++) {
- size_t j;
-
- if (!qnodes[i])
- continue;
-
- node = icc_node_create(qnodes[i]->id);
- if (IS_ERR(node)) {
- ret = PTR_ERR(node);
- goto err;
- }
-
- node->name = qnodes[i]->name;
- node->data = qnodes[i];
- icc_node_add(node, provider);
-
- for (j = 0; j < qnodes[i]->num_links; j++)
- icc_link_create(node, qnodes[i]->links[j]);
-
- data->nodes[i] = node;
- }
- data->num_nodes = num_nodes;
-
- platform_set_drvdata(pdev, qp);
-
- return 0;
-err:
- icc_nodes_remove(provider);
- icc_provider_del(provider);
- return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
- struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
- icc_nodes_remove(&qp->provider);
- return icc_provider_del(&qp->provider);
-}
-
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sm8150-aggre1-noc",
.data = &sm8150_aggre1_noc},
@@ -622,8 +530,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
- .probe = qnoc_probe,
- .remove = qnoc_remove,
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8150",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8250.c b/drivers/interconnect/qcom/sm8250.c
index cc558fec74e3..8dfb5dea562a 100644
--- a/drivers/interconnect/qcom/sm8250.c
+++ b/drivers/interconnect/qcom/sm8250.c
@@ -518,98 +518,6 @@ static struct qcom_icc_desc sm8250_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
-static int qnoc_probe(struct platform_device *pdev)
-{
- const struct qcom_icc_desc *desc;
- struct icc_onecell_data *data;
- struct icc_provider *provider;
- struct qcom_icc_node **qnodes;
- struct qcom_icc_provider *qp;
- struct icc_node *node;
- size_t num_nodes, i;
- int ret;
-
- desc = device_get_match_data(&pdev->dev);
- if (!desc)
- return -EINVAL;
-
- qnodes = desc->nodes;
- num_nodes = desc->num_nodes;
-
- qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return -ENOMEM;
-
- data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- provider = &qp->provider;
- provider->dev = &pdev->dev;
- provider->set = qcom_icc_set;
- provider->pre_aggregate = qcom_icc_pre_aggregate;
- provider->aggregate = qcom_icc_aggregate;
- provider->xlate = of_icc_xlate_onecell;
- INIT_LIST_HEAD(&provider->nodes);
- provider->data = data;
-
- qp->dev = &pdev->dev;
- qp->bcms = desc->bcms;
- qp->num_bcms = desc->num_bcms;
-
- qp->voter = of_bcm_voter_get(qp->dev, NULL);
- if (IS_ERR(qp->voter))
- return PTR_ERR(qp->voter);
-
- ret = icc_provider_add(provider);
- if (ret) {
- dev_err(&pdev->dev, "error adding interconnect provider\n");
- return ret;
- }
-
- for (i = 0; i < qp->num_bcms; i++)
- qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
- for (i = 0; i < num_nodes; i++) {
- size_t j;
-
- if (!qnodes[i])
- continue;
-
- node = icc_node_create(qnodes[i]->id);
- if (IS_ERR(node)) {
- ret = PTR_ERR(node);
- goto err;
- }
-
- node->name = qnodes[i]->name;
- node->data = qnodes[i];
- icc_node_add(node, provider);
-
- for (j = 0; j < qnodes[i]->num_links; j++)
- icc_link_create(node, qnodes[i]->links[j]);
-
- data->nodes[i] = node;
- }
- data->num_nodes = num_nodes;
-
- platform_set_drvdata(pdev, qp);
-
- return 0;
-err:
- icc_nodes_remove(provider);
- icc_provider_del(provider);
- return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
- struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
- icc_nodes_remove(&qp->provider);
- return icc_provider_del(&qp->provider);
-}
-
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sm8250-aggre1-noc",
.data = &sm8250_aggre1_noc},
@@ -638,8 +546,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
- .probe = qnoc_probe,
- .remove = qnoc_remove,
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8250",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8350.c b/drivers/interconnect/qcom/sm8350.c
index 579b6ce8e046..3e26a2175b28 100644
--- a/drivers/interconnect/qcom/sm8350.c
+++ b/drivers/interconnect/qcom/sm8350.c
@@ -510,99 +510,6 @@ static struct qcom_icc_desc sm8350_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
-static int qnoc_probe(struct platform_device *pdev)
-{
- const struct qcom_icc_desc *desc;
- struct icc_onecell_data *data;
- struct icc_provider *provider;
- struct qcom_icc_node **qnodes;
- struct qcom_icc_provider *qp;
- struct icc_node *node;
- size_t num_nodes, i;
- int ret;
-
- desc = of_device_get_match_data(&pdev->dev);
- if (!desc)
- return -EINVAL;
-
- qnodes = desc->nodes;
- num_nodes = desc->num_nodes;
-
- qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return -ENOMEM;
-
- data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- provider = &qp->provider;
- provider->dev = &pdev->dev;
- provider->set = qcom_icc_set;
- provider->pre_aggregate = qcom_icc_pre_aggregate;
- provider->aggregate = qcom_icc_aggregate;
- provider->xlate = of_icc_xlate_onecell;
- INIT_LIST_HEAD(&provider->nodes);
- provider->data = data;
-
- qp->dev = &pdev->dev;
- qp->bcms = desc->bcms;
- qp->num_bcms = desc->num_bcms;
-
- qp->voter = of_bcm_voter_get(qp->dev, NULL);
- if (IS_ERR(qp->voter))
- return PTR_ERR(qp->voter);
-
- ret = icc_provider_add(provider);
- if (ret) {
- dev_err(&pdev->dev, "error adding interconnect provider\n");
- return ret;
- }
-
- for (i = 0; i < qp->num_bcms; i++)
- qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
- for (i = 0; i < num_nodes; i++) {
- size_t j;
-
- if (!qnodes[i])
- continue;
-
- node = icc_node_create(qnodes[i]->id);
- if (IS_ERR(node)) {
- ret = PTR_ERR(node);
- goto err;
- }
-
- node->name = qnodes[i]->name;
- node->data = qnodes[i];
- icc_node_add(node, provider);
-
- for (j = 0; j < qnodes[i]->num_links; j++)
- icc_link_create(node, qnodes[i]->links[j]);
-
- data->nodes[i] = node;
- }
- data->num_nodes = num_nodes;
-
- platform_set_drvdata(pdev, qp);
-
- return ret;
-
-err:
- icc_nodes_remove(provider);
- icc_provider_del(provider);
- return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
- struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
- icc_nodes_remove(&qp->provider);
- return icc_provider_del(&qp->provider);
-}
-
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sm8350-aggre1-noc", .data = &sm8350_aggre1_noc},
{ .compatible = "qcom,sm8350-aggre2-noc", .data = &sm8350_aggre2_noc},
@@ -619,8 +526,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
- .probe = qnoc_probe,
- .remove = qnoc_remove,
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8350",
.of_match_table = qnoc_of_match,
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 07b7c25cbed8..8ad8618b3530 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -79,16 +79,57 @@ config IOMMU_DEBUGFS
debug/iommu directory, and then populate a subdirectory with
entries as required.
-config IOMMU_DEFAULT_PASSTHROUGH
- bool "IOMMU passthrough by default"
+choice
+ prompt "IOMMU default domain type"
depends on IOMMU_API
+ default IOMMU_DEFAULT_DMA_LAZY if AMD_IOMMU || INTEL_IOMMU
+ default IOMMU_DEFAULT_DMA_STRICT
help
- Enable passthrough by default, removing the need to pass in
- iommu.passthrough=on or iommu=pt through command line. If this
- is enabled, you can still disable with iommu.passthrough=off
- or iommu=nopt depending on the architecture.
+ Choose the type of IOMMU domain used to manage DMA API usage by
+ device drivers. The options here typically represent different
+ levels of tradeoff between robustness/security and performance,
+ depending on the IOMMU driver. Not all IOMMUs support all options.
+ This choice can be overridden at boot via the command line, and for
+ some devices also at runtime via sysfs.
- If unsure, say N here.
+ If unsure, keep the default.
+
+config IOMMU_DEFAULT_DMA_STRICT
+ bool "Translated - Strict"
+ help
+ Trusted devices use translation to restrict their access to only
+ DMA-mapped pages, with strict TLB invalidation on unmap. Equivalent
+ to passing "iommu.passthrough=0 iommu.strict=1" on the command line.
+
+ Untrusted devices always use this mode, with an additional layer of
+ bounce-buffering such that they cannot gain access to any unrelated
+ data within a mapped page.
+
+config IOMMU_DEFAULT_DMA_LAZY
+ bool "Translated - Lazy"
+ help
+ Trusted devices use translation to restrict their access to only
+ DMA-mapped pages, but with "lazy" batched TLB invalidation. This
+ mode allows higher performance with some IOMMUs due to reduced TLB
+ flushing, but at the cost of reduced isolation since devices may be
+ able to access memory for some time after it has been unmapped.
+ Equivalent to passing "iommu.passthrough=0 iommu.strict=0" on the
+ command line.
+
+ If this mode is not supported by the IOMMU driver, the effective
+ runtime default will fall back to IOMMU_DEFAULT_DMA_STRICT.
+
+config IOMMU_DEFAULT_PASSTHROUGH
+ bool "Passthrough"
+ help
+ Trusted devices are identity-mapped, giving them unrestricted access
+ to memory with minimal performance overhead. Equivalent to passing
+ "iommu.passthrough=1" (historically "iommu=pt") on the command line.
+
+ If this mode is not supported by the IOMMU driver, the effective
+ runtime default will fall back to IOMMU_DEFAULT_DMA_STRICT.
+
+endchoice
config OF_IOMMU
def_bool y
@@ -249,10 +290,25 @@ config SPAPR_TCE_IOMMU
Enables bits of IOMMU API required by VFIO. The iommu_ops
is not implemented as it is not necessary for VFIO.
+config APPLE_DART
+ tristate "Apple DART IOMMU Support"
+ depends on ARCH_APPLE || (COMPILE_TEST && !GENERIC_ATOMIC64)
+ select IOMMU_API
+ select IOMMU_IO_PGTABLE_LPAE
+ default ARCH_APPLE
+ help
+ Support for Apple DART (Device Address Resolution Table) IOMMUs
+ found in Apple ARM SoCs like the M1.
+ This IOMMU is required for most peripherals using DMA to access
+ the main memory.
+
+ Say Y here if you are using an Apple SoC.
+
# ARM IOMMU support
config ARM_SMMU
tristate "ARM Ltd. System MMU (SMMU) Support"
depends on ARM64 || ARM || (COMPILE_TEST && !GENERIC_ATOMIC64)
+ depends on QCOM_SCM || !QCOM_SCM #if QCOM_SCM=m this can't be =y
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
select ARM_DMA_USE_IOMMU if ARM
@@ -382,6 +438,7 @@ config QCOM_IOMMU
# Note: iommu drivers cannot (yet?) be built as modules
bool "Qualcomm IOMMU Support"
depends on ARCH_QCOM || (COMPILE_TEST && !GENERIC_ATOMIC64)
+ depends on QCOM_SCM=y
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
select ARM_DMA_USE_IOMMU
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c0fb0ba88143..bc7f730edbb0 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_HYPERV_IOMMU) += hyperv-iommu.o
obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu.o
obj-$(CONFIG_IOMMU_SVA_LIB) += iommu-sva-lib.o io-pgfault.o
obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o
+obj-$(CONFIG_APPLE_DART) += apple-dart.o
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 94c1a7a9876d..8dbe61e2b3c1 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -779,12 +779,6 @@ extern u16 amd_iommu_last_bdf;
/* allocation bitmap for domain ids */
extern unsigned long *amd_iommu_pd_alloc_bitmap;
-/*
- * If true, the addresses will be flushed on unmap time, not when
- * they are reused
- */
-extern bool amd_iommu_unmap_flush;
-
/* Smallest max PASID supported by any IOMMU in the system */
extern u32 amd_iommu_max_pasid;
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 46280e6e1535..bdcf167b4afe 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -161,7 +161,6 @@ u16 amd_iommu_last_bdf; /* largest PCI device id we have
to handle */
LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings
we find in ACPI */
-bool amd_iommu_unmap_flush; /* if true, flush on every unmap */
LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
system */
@@ -1850,8 +1849,11 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
if (ret)
return ret;
- if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE))
+ if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) {
+ pr_info("Using strict mode due to virtualization\n");
+ iommu_set_dma_strict();
amd_iommu_np_cache = true;
+ }
init_iommu_perf_ctr(iommu);
@@ -3098,8 +3100,10 @@ static int __init parse_amd_iommu_intr(char *str)
static int __init parse_amd_iommu_options(char *str)
{
for (; *str; ++str) {
- if (strncmp(str, "fullflush", 9) == 0)
- amd_iommu_unmap_flush = true;
+ if (strncmp(str, "fullflush", 9) == 0) {
+ pr_warn("amd_iommu=fullflush deprecated; use iommu.strict=1 instead\n");
+ iommu_set_dma_strict();
+ }
if (strncmp(str, "force_enable", 12) == 0)
amd_iommu_force_enable = true;
if (strncmp(str, "off", 3) == 0)
diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
index bb0ee5c9fde7..182c93a43efd 100644
--- a/drivers/iommu/amd/io_pgtable.c
+++ b/drivers/iommu/amd/io_pgtable.c
@@ -493,9 +493,6 @@ static phys_addr_t iommu_v1_iova_to_phys(struct io_pgtable_ops *ops, unsigned lo
unsigned long offset_mask, pte_pgsize;
u64 *pte, __pte;
- if (pgtable->mode == PAGE_MODE_NONE)
- return iova;
-
pte = fetch_pte(pgtable, iova, &pte_pgsize);
if (!pte || !IOMMU_PTE_PRESENT(*pte))
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 811a49a95d04..1722bb161841 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -425,9 +425,11 @@ static void amd_iommu_report_rmp_hw_error(volatile u32 *event)
if (pdev)
dev_data = dev_iommu_priv_get(&pdev->dev);
- if (dev_data && __ratelimit(&dev_data->rs)) {
- pci_err(pdev, "Event logged [RMP_HW_ERROR vmg_tag=0x%04x, spa=0x%llx, flags=0x%04x]\n",
- vmg_tag, spa, flags);
+ if (dev_data) {
+ if (__ratelimit(&dev_data->rs)) {
+ pci_err(pdev, "Event logged [RMP_HW_ERROR vmg_tag=0x%04x, spa=0x%llx, flags=0x%04x]\n",
+ vmg_tag, spa, flags);
+ }
} else {
pr_err_ratelimited("Event logged [RMP_HW_ERROR device=%02x:%02x.%x, vmg_tag=0x%04x, spa=0x%llx, flags=0x%04x]\n",
PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
@@ -456,9 +458,11 @@ static void amd_iommu_report_rmp_fault(volatile u32 *event)
if (pdev)
dev_data = dev_iommu_priv_get(&pdev->dev);
- if (dev_data && __ratelimit(&dev_data->rs)) {
- pci_err(pdev, "Event logged [RMP_PAGE_FAULT vmg_tag=0x%04x, gpa=0x%llx, flags_rmp=0x%04x, flags=0x%04x]\n",
- vmg_tag, gpa, flags_rmp, flags);
+ if (dev_data) {
+ if (__ratelimit(&dev_data->rs)) {
+ pci_err(pdev, "Event logged [RMP_PAGE_FAULT vmg_tag=0x%04x, gpa=0x%llx, flags_rmp=0x%04x, flags=0x%04x]\n",
+ vmg_tag, gpa, flags_rmp, flags);
+ }
} else {
pr_err_ratelimited("Event logged [RMP_PAGE_FAULT device=%02x:%02x.%x, vmg_tag=0x%04x, gpa=0x%llx, flags_rmp=0x%04x, flags=0x%04x]\n",
PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
@@ -480,11 +484,13 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
if (pdev)
dev_data = dev_iommu_priv_get(&pdev->dev);
- if (dev_data && __ratelimit(&dev_data->rs)) {
- pci_err(pdev, "Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%llx flags=0x%04x]\n",
- domain_id, address, flags);
- } else if (printk_ratelimit()) {
- pr_err("Event logged [IO_PAGE_FAULT device=%02x:%02x.%x domain=0x%04x address=0x%llx flags=0x%04x]\n",
+ if (dev_data) {
+ if (__ratelimit(&dev_data->rs)) {
+ pci_err(pdev, "Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%llx flags=0x%04x]\n",
+ domain_id, address, flags);
+ }
+ } else {
+ pr_err_ratelimited("Event logged [IO_PAGE_FAULT device=%02x:%02x.%x domain=0x%04x address=0x%llx flags=0x%04x]\n",
PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
domain_id, address, flags);
}
@@ -1261,15 +1267,52 @@ static void __domain_flush_pages(struct protection_domain *domain,
}
static void domain_flush_pages(struct protection_domain *domain,
- u64 address, size_t size)
+ u64 address, size_t size, int pde)
{
- __domain_flush_pages(domain, address, size, 0);
+ if (likely(!amd_iommu_np_cache)) {
+ __domain_flush_pages(domain, address, size, pde);
+ return;
+ }
+
+ /*
+ * When NpCache is on, we infer that we run in a VM and use a vIOMMU.
+ * In such setups it is best to avoid flushes of ranges which are not
+ * naturally aligned, since it would lead to flushes of unmodified
+ * PTEs. Such flushes would require the hypervisor to do more work than
+ * necessary. Therefore, perform repeated flushes of aligned ranges
+ * until you cover the range. Each iteration flushes the smaller
+ * between the natural alignment of the address that we flush and the
+ * greatest naturally aligned region that fits in the range.
+ */
+ while (size != 0) {
+ int addr_alignment = __ffs(address);
+ int size_alignment = __fls(size);
+ int min_alignment;
+ size_t flush_size;
+
+ /*
+ * size is always non-zero, but address might be zero, causing
+ * addr_alignment to be negative. As the casting of the
+ * argument in __ffs(address) to long might trim the high bits
+ * of the address on x86-32, cast to long when doing the check.
+ */
+ if (likely((unsigned long)address != 0))
+ min_alignment = min(addr_alignment, size_alignment);
+ else
+ min_alignment = size_alignment;
+
+ flush_size = 1ul << min_alignment;
+
+ __domain_flush_pages(domain, address, flush_size, pde);
+ address += flush_size;
+ size -= flush_size;
+ }
}
/* Flush the whole IO/TLB for a given protection domain - including PDE */
void amd_iommu_domain_flush_tlb_pde(struct protection_domain *domain)
{
- __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
+ domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
}
void amd_iommu_domain_flush_complete(struct protection_domain *domain)
@@ -1296,7 +1339,7 @@ static void domain_flush_np_cache(struct protection_domain *domain,
unsigned long flags;
spin_lock_irqsave(&domain->lock, flags);
- domain_flush_pages(domain, iova, size);
+ domain_flush_pages(domain, iova, size, 1);
amd_iommu_domain_flush_complete(domain);
spin_unlock_irqrestore(&domain->lock, flags);
}
@@ -1707,14 +1750,9 @@ static struct iommu_device *amd_iommu_probe_device(struct device *dev)
static void amd_iommu_probe_finalize(struct device *dev)
{
- struct iommu_domain *domain;
-
/* Domains are initialized for this device - have a look what we ended up with */
- domain = iommu_get_domain_for_dev(dev);
- if (domain->type == IOMMU_DOMAIN_DMA)
- iommu_setup_dma_ops(dev, 0, U64_MAX);
- else
- set_dma_ops(dev, NULL);
+ set_dma_ops(dev, NULL);
+ iommu_setup_dma_ops(dev, 0, U64_MAX);
}
static void amd_iommu_release_device(struct device *dev)
@@ -1775,12 +1813,6 @@ void amd_iommu_domain_update(struct protection_domain *domain)
static void __init amd_iommu_init_dma_ops(void)
{
swiotlb = (iommu_default_passthrough() || sme_me_mask) ? 1 : 0;
-
- if (amd_iommu_unmap_flush)
- pr_info("IO/TLB flush on unmap enabled\n");
- else
- pr_info("Lazy IO/TLB flushing enabled\n");
- iommu_set_dma_strict(amd_iommu_unmap_flush);
}
int __init amd_iommu_init_api(void)
@@ -1924,16 +1956,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
domain->domain.geometry.aperture_end = ~0ULL;
domain->domain.geometry.force_aperture = true;
- if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&domain->domain) == -ENOMEM)
- goto free_domain;
-
return &domain->domain;
-
-free_domain:
- protection_domain_free(domain);
-
- return NULL;
}
static void amd_iommu_domain_free(struct iommu_domain *dom)
@@ -1950,9 +1973,6 @@ static void amd_iommu_domain_free(struct iommu_domain *dom)
if (!dom)
return;
- if (dom->type == IOMMU_DOMAIN_DMA)
- iommu_put_dma_cookie(&domain->domain);
-
if (domain->flags & PD_IOMMUV2_MASK)
free_gcr3_table(domain);
@@ -2022,6 +2042,16 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
return ret;
}
+static void amd_iommu_iotlb_sync_map(struct iommu_domain *dom,
+ unsigned long iova, size_t size)
+{
+ struct protection_domain *domain = to_pdomain(dom);
+ struct io_pgtable_ops *ops = &domain->iop.iop.ops;
+
+ if (ops->map)
+ domain_flush_np_cache(domain, iova, size);
+}
+
static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
phys_addr_t paddr, size_t page_size, int iommu_prot,
gfp_t gfp)
@@ -2040,26 +2070,50 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
if (iommu_prot & IOMMU_WRITE)
prot |= IOMMU_PROT_IW;
- if (ops->map) {
+ if (ops->map)
ret = ops->map(ops, iova, paddr, page_size, prot, gfp);
- domain_flush_np_cache(domain, iova, page_size);
- }
return ret;
}
+static void amd_iommu_iotlb_gather_add_page(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t size)
+{
+ /*
+ * AMD's IOMMU can flush as many pages as necessary in a single flush.
+ * Unless we run in a virtual machine, which can be inferred according
+ * to whether "non-present cache" is on, it is probably best to prefer
+ * (potentially) too extensive TLB flushing (i.e., more misses) over
+ * mutliple TLB flushes (i.e., more flushes). For virtual machines the
+ * hypervisor needs to synchronize the host IOMMU PTEs with those of
+ * the guest, and the trade-off is different: unnecessary TLB flushes
+ * should be avoided.
+ */
+ if (amd_iommu_np_cache &&
+ iommu_iotlb_gather_is_disjoint(gather, iova, size))
+ iommu_iotlb_sync(domain, gather);
+
+ iommu_iotlb_gather_add_range(gather, iova, size);
+}
+
static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
size_t page_size,
struct iommu_iotlb_gather *gather)
{
struct protection_domain *domain = to_pdomain(dom);
struct io_pgtable_ops *ops = &domain->iop.iop.ops;
+ size_t r;
if ((amd_iommu_pgtable == AMD_IOMMU_V1) &&
(domain->iop.mode == PAGE_MODE_NONE))
return 0;
- return (ops->unmap) ? ops->unmap(ops, iova, page_size, gather) : 0;
+ r = (ops->unmap) ? ops->unmap(ops, iova, page_size, gather) : 0;
+
+ amd_iommu_iotlb_gather_add_page(dom, gather, iova, page_size);
+
+ return r;
}
static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
@@ -2162,7 +2216,13 @@ static void amd_iommu_flush_iotlb_all(struct iommu_domain *domain)
static void amd_iommu_iotlb_sync(struct iommu_domain *domain,
struct iommu_iotlb_gather *gather)
{
- amd_iommu_flush_iotlb_all(domain);
+ struct protection_domain *dom = to_pdomain(domain);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dom->lock, flags);
+ domain_flush_pages(dom, gather->start, gather->end - gather->start, 1);
+ amd_iommu_domain_flush_complete(dom);
+ spin_unlock_irqrestore(&dom->lock, flags);
}
static int amd_iommu_def_domain_type(struct device *dev)
@@ -2191,6 +2251,7 @@ const struct iommu_ops amd_iommu_ops = {
.attach_dev = amd_iommu_attach_device,
.detach_dev = amd_iommu_detach_device,
.map = amd_iommu_map,
+ .iotlb_sync_map = amd_iommu_iotlb_sync_map,
.unmap = amd_iommu_unmap,
.iova_to_phys = amd_iommu_iova_to_phys,
.probe_device = amd_iommu_probe_device,
diff --git a/drivers/iommu/amd/iommu_v2.c b/drivers/iommu/amd/iommu_v2.c
index f8d4ad421e07..a9e568276c99 100644
--- a/drivers/iommu/amd/iommu_v2.c
+++ b/drivers/iommu/amd/iommu_v2.c
@@ -6,6 +6,7 @@
#define pr_fmt(fmt) "AMD-Vi: " fmt
+#include <linux/refcount.h>
#include <linux/mmu_notifier.h>
#include <linux/amd-iommu.h>
#include <linux/mm_types.h>
@@ -33,7 +34,7 @@ struct pri_queue {
struct pasid_state {
struct list_head list; /* For global state-list */
- atomic_t count; /* Reference count */
+ refcount_t count; /* Reference count */
unsigned mmu_notifier_count; /* Counting nested mmu_notifier
calls */
struct mm_struct *mm; /* mm_struct for the faults */
@@ -242,7 +243,7 @@ static struct pasid_state *get_pasid_state(struct device_state *dev_state,
ret = *ptr;
if (ret)
- atomic_inc(&ret->count);
+ refcount_inc(&ret->count);
out_unlock:
spin_unlock_irqrestore(&dev_state->lock, flags);
@@ -257,14 +258,14 @@ static void free_pasid_state(struct pasid_state *pasid_state)
static void put_pasid_state(struct pasid_state *pasid_state)
{
- if (atomic_dec_and_test(&pasid_state->count))
+ if (refcount_dec_and_test(&pasid_state->count))
wake_up(&pasid_state->wq);
}
static void put_pasid_state_wait(struct pasid_state *pasid_state)
{
- atomic_dec(&pasid_state->count);
- wait_event(pasid_state->wq, !atomic_read(&pasid_state->count));
+ refcount_dec(&pasid_state->count);
+ wait_event(pasid_state->wq, !refcount_read(&pasid_state->count));
free_pasid_state(pasid_state);
}
@@ -624,7 +625,7 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, u32 pasid,
goto out;
- atomic_set(&pasid_state->count, 1);
+ refcount_set(&pasid_state->count, 1);
init_waitqueue_head(&pasid_state->wq);
spin_lock_init(&pasid_state->lock);
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
new file mode 100644
index 000000000000..559db9259e65
--- /dev/null
+++ b/drivers/iommu/apple-dart.c
@@ -0,0 +1,923 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Apple DART (Device Address Resolution Table) IOMMU driver
+ *
+ * Copyright (C) 2021 The Asahi Linux Contributors
+ *
+ * Based on arm/arm-smmu/arm-ssmu.c and arm/arm-smmu-v3/arm-smmu-v3.c
+ * Copyright (C) 2013 ARM Limited
+ * Copyright (C) 2015 ARM Limited
+ * and on exynos-iommu.c
+ * Copyright (c) 2011,2016 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/atomic.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/dev_printk.h>
+#include <linux/dma-iommu.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io-pgtable.h>
+#include <linux/iommu.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_iommu.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/swab.h>
+#include <linux/types.h>
+
+#define DART_MAX_STREAMS 16
+#define DART_MAX_TTBR 4
+#define MAX_DARTS_PER_DEVICE 2
+
+#define DART_STREAM_ALL 0xffff
+
+#define DART_PARAMS1 0x00
+#define DART_PARAMS_PAGE_SHIFT GENMASK(27, 24)
+
+#define DART_PARAMS2 0x04
+#define DART_PARAMS_BYPASS_SUPPORT BIT(0)
+
+#define DART_STREAM_COMMAND 0x20
+#define DART_STREAM_COMMAND_BUSY BIT(2)
+#define DART_STREAM_COMMAND_INVALIDATE BIT(20)
+
+#define DART_STREAM_SELECT 0x34
+
+#define DART_ERROR 0x40
+#define DART_ERROR_STREAM GENMASK(27, 24)
+#define DART_ERROR_CODE GENMASK(11, 0)
+#define DART_ERROR_FLAG BIT(31)
+
+#define DART_ERROR_READ_FAULT BIT(4)
+#define DART_ERROR_WRITE_FAULT BIT(3)
+#define DART_ERROR_NO_PTE BIT(2)
+#define DART_ERROR_NO_PMD BIT(1)
+#define DART_ERROR_NO_TTBR BIT(0)
+
+#define DART_CONFIG 0x60
+#define DART_CONFIG_LOCK BIT(15)
+
+#define DART_STREAM_COMMAND_BUSY_TIMEOUT 100
+
+#define DART_ERROR_ADDR_HI 0x54
+#define DART_ERROR_ADDR_LO 0x50
+
+#define DART_TCR(sid) (0x100 + 4 * (sid))
+#define DART_TCR_TRANSLATE_ENABLE BIT(7)
+#define DART_TCR_BYPASS0_ENABLE BIT(8)
+#define DART_TCR_BYPASS1_ENABLE BIT(12)
+
+#define DART_TTBR(sid, idx) (0x200 + 16 * (sid) + 4 * (idx))
+#define DART_TTBR_VALID BIT(31)
+#define DART_TTBR_SHIFT 12
+
+/*
+ * Private structure associated with each DART device.
+ *
+ * @dev: device struct
+ * @regs: mapped MMIO region
+ * @irq: interrupt number, can be shared with other DARTs
+ * @clks: clocks associated with this DART
+ * @num_clks: number of @clks
+ * @lock: lock for hardware operations involving this dart
+ * @pgsize: pagesize supported by this DART
+ * @supports_bypass: indicates if this DART supports bypass mode
+ * @force_bypass: force bypass mode due to pagesize mismatch?
+ * @sid2group: maps stream ids to iommu_groups
+ * @iommu: iommu core device
+ */
+struct apple_dart {
+ struct device *dev;
+
+ void __iomem *regs;
+
+ int irq;
+ struct clk_bulk_data *clks;
+ int num_clks;
+
+ spinlock_t lock;
+
+ u32 pgsize;
+ u32 supports_bypass : 1;
+ u32 force_bypass : 1;
+
+ struct iommu_group *sid2group[DART_MAX_STREAMS];
+ struct iommu_device iommu;
+};
+
+/*
+ * Convenience struct to identify streams.
+ *
+ * The normal variant is used inside apple_dart_master_cfg which isn't written
+ * to concurrently.
+ * The atomic variant is used inside apple_dart_domain where we have to guard
+ * against races from potential parallel calls to attach/detach_device.
+ * Note that even inside the atomic variant the apple_dart pointer is not
+ * protected: This pointer is initialized once under the domain init mutex
+ * and never changed again afterwards. Devices with different dart pointers
+ * cannot be attached to the same domain.
+ *
+ * @dart dart pointer
+ * @sid stream id bitmap
+ */
+struct apple_dart_stream_map {
+ struct apple_dart *dart;
+ unsigned long sidmap;
+};
+struct apple_dart_atomic_stream_map {
+ struct apple_dart *dart;
+ atomic64_t sidmap;
+};
+
+/*
+ * This structure is attached to each iommu domain handled by a DART.
+ *
+ * @pgtbl_ops: pagetable ops allocated by io-pgtable
+ * @finalized: true if the domain has been completely initialized
+ * @init_lock: protects domain initialization
+ * @stream_maps: streams attached to this domain (valid for DMA/UNMANAGED only)
+ * @domain: core iommu domain pointer
+ */
+struct apple_dart_domain {
+ struct io_pgtable_ops *pgtbl_ops;
+
+ bool finalized;
+ struct mutex init_lock;
+ struct apple_dart_atomic_stream_map stream_maps[MAX_DARTS_PER_DEVICE];
+
+ struct iommu_domain domain;
+};
+
+/*
+ * This structure is attached to devices with dev_iommu_priv_set() on of_xlate
+ * and contains a list of streams bound to this device.
+ * So far the worst case seen is a single device with two streams
+ * from different darts, such that this simple static array is enough.
+ *
+ * @streams: streams for this device
+ */
+struct apple_dart_master_cfg {
+ struct apple_dart_stream_map stream_maps[MAX_DARTS_PER_DEVICE];
+};
+
+/*
+ * Helper macro to iterate over apple_dart_master_cfg.stream_maps and
+ * apple_dart_domain.stream_maps
+ *
+ * @i int used as loop variable
+ * @base pointer to base struct (apple_dart_master_cfg or apple_dart_domain)
+ * @stream pointer to the apple_dart_streams struct for each loop iteration
+ */
+#define for_each_stream_map(i, base, stream_map) \
+ for (i = 0, stream_map = &(base)->stream_maps[0]; \
+ i < MAX_DARTS_PER_DEVICE && stream_map->dart; \
+ stream_map = &(base)->stream_maps[++i])
+
+static struct platform_driver apple_dart_driver;
+static const struct iommu_ops apple_dart_iommu_ops;
+static const struct iommu_flush_ops apple_dart_tlb_ops;
+
+static struct apple_dart_domain *to_dart_domain(struct iommu_domain *dom)
+{
+ return container_of(dom, struct apple_dart_domain, domain);
+}
+
+static void
+apple_dart_hw_enable_translation(struct apple_dart_stream_map *stream_map)
+{
+ int sid;
+
+ for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ writel(DART_TCR_TRANSLATE_ENABLE,
+ stream_map->dart->regs + DART_TCR(sid));
+}
+
+static void apple_dart_hw_disable_dma(struct apple_dart_stream_map *stream_map)
+{
+ int sid;
+
+ for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ writel(0, stream_map->dart->regs + DART_TCR(sid));
+}
+
+static void
+apple_dart_hw_enable_bypass(struct apple_dart_stream_map *stream_map)
+{
+ int sid;
+
+ WARN_ON(!stream_map->dart->supports_bypass);
+ for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ writel(DART_TCR_BYPASS0_ENABLE | DART_TCR_BYPASS1_ENABLE,
+ stream_map->dart->regs + DART_TCR(sid));
+}
+
+static void apple_dart_hw_set_ttbr(struct apple_dart_stream_map *stream_map,
+ u8 idx, phys_addr_t paddr)
+{
+ int sid;
+
+ WARN_ON(paddr & ((1 << DART_TTBR_SHIFT) - 1));
+ for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ writel(DART_TTBR_VALID | (paddr >> DART_TTBR_SHIFT),
+ stream_map->dart->regs + DART_TTBR(sid, idx));
+}
+
+static void apple_dart_hw_clear_ttbr(struct apple_dart_stream_map *stream_map,
+ u8 idx)
+{
+ int sid;
+
+ for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ writel(0, stream_map->dart->regs + DART_TTBR(sid, idx));
+}
+
+static void
+apple_dart_hw_clear_all_ttbrs(struct apple_dart_stream_map *stream_map)
+{
+ int i;
+
+ for (i = 0; i < DART_MAX_TTBR; ++i)
+ apple_dart_hw_clear_ttbr(stream_map, i);
+}
+
+static int
+apple_dart_hw_stream_command(struct apple_dart_stream_map *stream_map,
+ u32 command)
+{
+ unsigned long flags;
+ int ret;
+ u32 command_reg;
+
+ spin_lock_irqsave(&stream_map->dart->lock, flags);
+
+ writel(stream_map->sidmap, stream_map->dart->regs + DART_STREAM_SELECT);
+ writel(command, stream_map->dart->regs + DART_STREAM_COMMAND);
+
+ ret = readl_poll_timeout_atomic(
+ stream_map->dart->regs + DART_STREAM_COMMAND, command_reg,
+ !(command_reg & DART_STREAM_COMMAND_BUSY), 1,
+ DART_STREAM_COMMAND_BUSY_TIMEOUT);
+
+ spin_unlock_irqrestore(&stream_map->dart->lock, flags);
+
+ if (ret) {
+ dev_err(stream_map->dart->dev,
+ "busy bit did not clear after command %x for streams %lx\n",
+ command, stream_map->sidmap);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+apple_dart_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
+{
+ return apple_dart_hw_stream_command(stream_map,
+ DART_STREAM_COMMAND_INVALIDATE);
+}
+
+static int apple_dart_hw_reset(struct apple_dart *dart)
+{
+ u32 config;
+ struct apple_dart_stream_map stream_map;
+
+ config = readl(dart->regs + DART_CONFIG);
+ if (config & DART_CONFIG_LOCK) {
+ dev_err(dart->dev, "DART is locked down until reboot: %08x\n",
+ config);
+ return -EINVAL;
+ }
+
+ stream_map.dart = dart;
+ stream_map.sidmap = DART_STREAM_ALL;
+ apple_dart_hw_disable_dma(&stream_map);
+ apple_dart_hw_clear_all_ttbrs(&stream_map);
+
+ /* clear any pending errors before the interrupt is unmasked */
+ writel(readl(dart->regs + DART_ERROR), dart->regs + DART_ERROR);
+
+ return apple_dart_hw_invalidate_tlb(&stream_map);
+}
+
+static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
+{
+ int i;
+ struct apple_dart_atomic_stream_map *domain_stream_map;
+ struct apple_dart_stream_map stream_map;
+
+ for_each_stream_map(i, domain, domain_stream_map) {
+ stream_map.dart = domain_stream_map->dart;
+ stream_map.sidmap = atomic64_read(&domain_stream_map->sidmap);
+ apple_dart_hw_invalidate_tlb(&stream_map);
+ }
+}
+
+static void apple_dart_flush_iotlb_all(struct iommu_domain *domain)
+{
+ apple_dart_domain_flush_tlb(to_dart_domain(domain));
+}
+
+static void apple_dart_iotlb_sync(struct iommu_domain *domain,
+ struct iommu_iotlb_gather *gather)
+{
+ apple_dart_domain_flush_tlb(to_dart_domain(domain));
+}
+
+static void apple_dart_iotlb_sync_map(struct iommu_domain *domain,
+ unsigned long iova, size_t size)
+{
+ apple_dart_domain_flush_tlb(to_dart_domain(domain));
+}
+
+static void apple_dart_tlb_flush_all(void *cookie)
+{
+ apple_dart_domain_flush_tlb(cookie);
+}
+
+static void apple_dart_tlb_flush_walk(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
+{
+ apple_dart_domain_flush_tlb(cookie);
+}
+
+static const struct iommu_flush_ops apple_dart_tlb_ops = {
+ .tlb_flush_all = apple_dart_tlb_flush_all,
+ .tlb_flush_walk = apple_dart_tlb_flush_walk,
+};
+
+static phys_addr_t apple_dart_iova_to_phys(struct iommu_domain *domain,
+ dma_addr_t iova)
+{
+ struct apple_dart_domain *dart_domain = to_dart_domain(domain);
+ struct io_pgtable_ops *ops = dart_domain->pgtbl_ops;
+
+ if (!ops)
+ return 0;
+
+ return ops->iova_to_phys(ops, iova);
+}
+
+static int apple_dart_map_pages(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t pgsize,
+ size_t pgcount, int prot, gfp_t gfp,
+ size_t *mapped)
+{
+ struct apple_dart_domain *dart_domain = to_dart_domain(domain);
+ struct io_pgtable_ops *ops = dart_domain->pgtbl_ops;
+
+ if (!ops)
+ return -ENODEV;
+
+ return ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, gfp,
+ mapped);
+}
+
+static size_t apple_dart_unmap_pages(struct iommu_domain *domain,
+ unsigned long iova, size_t pgsize,
+ size_t pgcount,
+ struct iommu_iotlb_gather *gather)
+{
+ struct apple_dart_domain *dart_domain = to_dart_domain(domain);
+ struct io_pgtable_ops *ops = dart_domain->pgtbl_ops;
+
+ return ops->unmap_pages(ops, iova, pgsize, pgcount, gather);
+}
+
+static void
+apple_dart_setup_translation(struct apple_dart_domain *domain,
+ struct apple_dart_stream_map *stream_map)
+{
+ int i;
+ struct io_pgtable_cfg *pgtbl_cfg =
+ &io_pgtable_ops_to_pgtable(domain->pgtbl_ops)->cfg;
+
+ for (i = 0; i < pgtbl_cfg->apple_dart_cfg.n_ttbrs; ++i)
+ apple_dart_hw_set_ttbr(stream_map, i,
+ pgtbl_cfg->apple_dart_cfg.ttbr[i]);
+ for (; i < DART_MAX_TTBR; ++i)
+ apple_dart_hw_clear_ttbr(stream_map, i);
+
+ apple_dart_hw_enable_translation(stream_map);
+ apple_dart_hw_invalidate_tlb(stream_map);
+}
+
+static int apple_dart_finalize_domain(struct iommu_domain *domain,
+ struct apple_dart_master_cfg *cfg)
+{
+ struct apple_dart_domain *dart_domain = to_dart_domain(domain);
+ struct apple_dart *dart = cfg->stream_maps[0].dart;
+ struct io_pgtable_cfg pgtbl_cfg;
+ int ret = 0;
+ int i;
+
+ mutex_lock(&dart_domain->init_lock);
+
+ if (dart_domain->finalized)
+ goto done;
+
+ for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
+ dart_domain->stream_maps[i].dart = cfg->stream_maps[i].dart;
+ atomic64_set(&dart_domain->stream_maps[i].sidmap,
+ cfg->stream_maps[i].sidmap);
+ }
+
+ pgtbl_cfg = (struct io_pgtable_cfg){
+ .pgsize_bitmap = dart->pgsize,
+ .ias = 32,
+ .oas = 36,
+ .coherent_walk = 1,
+ .tlb = &apple_dart_tlb_ops,
+ .iommu_dev = dart->dev,
+ };
+
+ dart_domain->pgtbl_ops =
+ alloc_io_pgtable_ops(APPLE_DART, &pgtbl_cfg, domain);
+ if (!dart_domain->pgtbl_ops) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+ domain->geometry.aperture_start = 0;
+ domain->geometry.aperture_end = DMA_BIT_MASK(32);
+ domain->geometry.force_aperture = true;
+
+ dart_domain->finalized = true;
+
+done:
+ mutex_unlock(&dart_domain->init_lock);
+ return ret;
+}
+
+static int
+apple_dart_mod_streams(struct apple_dart_atomic_stream_map *domain_maps,
+ struct apple_dart_stream_map *master_maps,
+ bool add_streams)
+{
+ int i;
+
+ for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
+ if (domain_maps[i].dart != master_maps[i].dart)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
+ if (!domain_maps[i].dart)
+ break;
+ if (add_streams)
+ atomic64_or(master_maps[i].sidmap,
+ &domain_maps[i].sidmap);
+ else
+ atomic64_and(~master_maps[i].sidmap,
+ &domain_maps[i].sidmap);
+ }
+
+ return 0;
+}
+
+static int apple_dart_domain_add_streams(struct apple_dart_domain *domain,
+ struct apple_dart_master_cfg *cfg)
+{
+ return apple_dart_mod_streams(domain->stream_maps, cfg->stream_maps,
+ true);
+}
+
+static int apple_dart_domain_remove_streams(struct apple_dart_domain *domain,
+ struct apple_dart_master_cfg *cfg)
+{
+ return apple_dart_mod_streams(domain->stream_maps, cfg->stream_maps,
+ false);
+}
+
+static int apple_dart_attach_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ int ret, i;
+ struct apple_dart_stream_map *stream_map;
+ struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
+ struct apple_dart_domain *dart_domain = to_dart_domain(domain);
+
+ if (cfg->stream_maps[0].dart->force_bypass &&
+ domain->type != IOMMU_DOMAIN_IDENTITY)
+ return -EINVAL;
+ if (!cfg->stream_maps[0].dart->supports_bypass &&
+ domain->type == IOMMU_DOMAIN_IDENTITY)
+ return -EINVAL;
+
+ ret = apple_dart_finalize_domain(domain, cfg);
+ if (ret)
+ return ret;
+
+ switch (domain->type) {
+ case IOMMU_DOMAIN_DMA:
+ case IOMMU_DOMAIN_UNMANAGED:
+ ret = apple_dart_domain_add_streams(dart_domain, cfg);
+ if (ret)
+ return ret;
+
+ for_each_stream_map(i, cfg, stream_map)
+ apple_dart_setup_translation(dart_domain, stream_map);
+ break;
+ case IOMMU_DOMAIN_BLOCKED:
+ for_each_stream_map(i, cfg, stream_map)
+ apple_dart_hw_disable_dma(stream_map);
+ break;
+ case IOMMU_DOMAIN_IDENTITY:
+ for_each_stream_map(i, cfg, stream_map)
+ apple_dart_hw_enable_bypass(stream_map);
+ break;
+ }
+
+ return ret;
+}
+
+static void apple_dart_detach_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ int i;
+ struct apple_dart_stream_map *stream_map;
+ struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
+ struct apple_dart_domain *dart_domain = to_dart_domain(domain);
+
+ for_each_stream_map(i, cfg, stream_map)
+ apple_dart_hw_disable_dma(stream_map);
+
+ if (domain->type == IOMMU_DOMAIN_DMA ||
+ domain->type == IOMMU_DOMAIN_UNMANAGED)
+ apple_dart_domain_remove_streams(dart_domain, cfg);
+}
+
+static struct iommu_device *apple_dart_probe_device(struct device *dev)
+{
+ struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
+ struct apple_dart_stream_map *stream_map;
+ int i;
+
+ if (!cfg)
+ return ERR_PTR(-ENODEV);
+
+ for_each_stream_map(i, cfg, stream_map)
+ device_link_add(
+ dev, stream_map->dart->dev,
+ DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER);
+
+ return &cfg->stream_maps[0].dart->iommu;
+}
+
+static void apple_dart_release_device(struct device *dev)
+{
+ struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
+
+ if (!cfg)
+ return;
+
+ dev_iommu_priv_set(dev, NULL);
+ kfree(cfg);
+}
+
+static struct iommu_domain *apple_dart_domain_alloc(unsigned int type)
+{
+ struct apple_dart_domain *dart_domain;
+
+ if (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_UNMANAGED &&
+ type != IOMMU_DOMAIN_IDENTITY && type != IOMMU_DOMAIN_BLOCKED)
+ return NULL;
+
+ dart_domain = kzalloc(sizeof(*dart_domain), GFP_KERNEL);
+ if (!dart_domain)
+ return NULL;
+
+ iommu_get_dma_cookie(&dart_domain->domain);
+ mutex_init(&dart_domain->init_lock);
+
+ /* no need to allocate pgtbl_ops or do any other finalization steps */
+ if (type == IOMMU_DOMAIN_IDENTITY || type == IOMMU_DOMAIN_BLOCKED)
+ dart_domain->finalized = true;
+
+ return &dart_domain->domain;
+}
+
+static void apple_dart_domain_free(struct iommu_domain *domain)
+{
+ struct apple_dart_domain *dart_domain = to_dart_domain(domain);
+
+ if (dart_domain->pgtbl_ops)
+ free_io_pgtable_ops(dart_domain->pgtbl_ops);
+
+ kfree(dart_domain);
+}
+
+static int apple_dart_of_xlate(struct device *dev, struct of_phandle_args *args)
+{
+ struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
+ struct platform_device *iommu_pdev = of_find_device_by_node(args->np);
+ struct apple_dart *dart = platform_get_drvdata(iommu_pdev);
+ struct apple_dart *cfg_dart;
+ int i, sid;
+
+ if (args->args_count != 1)
+ return -EINVAL;
+ sid = args->args[0];
+
+ if (!cfg)
+ cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+ if (!cfg)
+ return -ENOMEM;
+ dev_iommu_priv_set(dev, cfg);
+
+ cfg_dart = cfg->stream_maps[0].dart;
+ if (cfg_dart) {
+ if (cfg_dart->supports_bypass != dart->supports_bypass)
+ return -EINVAL;
+ if (cfg_dart->force_bypass != dart->force_bypass)
+ return -EINVAL;
+ if (cfg_dart->pgsize != dart->pgsize)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
+ if (cfg->stream_maps[i].dart == dart) {
+ cfg->stream_maps[i].sidmap |= 1 << sid;
+ return 0;
+ }
+ }
+ for (i = 0; i < MAX_DARTS_PER_DEVICE; ++i) {
+ if (!cfg->stream_maps[i].dart) {
+ cfg->stream_maps[i].dart = dart;
+ cfg->stream_maps[i].sidmap = 1 << sid;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static struct iommu_group *apple_dart_device_group(struct device *dev)
+{
+ static DEFINE_MUTEX(lock);
+ int i, sid;
+ struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
+ struct apple_dart_stream_map *stream_map;
+ struct iommu_group *group = NULL;
+ struct iommu_group *res = ERR_PTR(-EINVAL);
+
+ mutex_lock(&lock);
+
+ for_each_stream_map(i, cfg, stream_map) {
+ for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS) {
+ struct iommu_group *stream_group =
+ stream_map->dart->sid2group[sid];
+
+ if (group && group != stream_group) {
+ res = ERR_PTR(-EINVAL);
+ goto out;
+ }
+
+ group = stream_group;
+ }
+ }
+
+ if (group) {
+ res = iommu_group_ref_get(group);
+ goto out;
+ }
+
+#ifdef CONFIG_PCI
+ if (dev_is_pci(dev))
+ group = pci_device_group(dev);
+ else
+#endif
+ group = generic_device_group(dev);
+
+ for_each_stream_map(i, cfg, stream_map)
+ for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS)
+ stream_map->dart->sid2group[sid] = group;
+
+ res = group;
+
+out:
+ mutex_unlock(&lock);
+ return res;
+}
+
+static int apple_dart_def_domain_type(struct device *dev)
+{
+ struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
+
+ if (cfg->stream_maps[0].dart->force_bypass)
+ return IOMMU_DOMAIN_IDENTITY;
+ if (!cfg->stream_maps[0].dart->supports_bypass)
+ return IOMMU_DOMAIN_DMA;
+
+ return 0;
+}
+
+static const struct iommu_ops apple_dart_iommu_ops = {
+ .domain_alloc = apple_dart_domain_alloc,
+ .domain_free = apple_dart_domain_free,
+ .attach_dev = apple_dart_attach_dev,
+ .detach_dev = apple_dart_detach_dev,
+ .map_pages = apple_dart_map_pages,
+ .unmap_pages = apple_dart_unmap_pages,
+ .flush_iotlb_all = apple_dart_flush_iotlb_all,
+ .iotlb_sync = apple_dart_iotlb_sync,
+ .iotlb_sync_map = apple_dart_iotlb_sync_map,
+ .iova_to_phys = apple_dart_iova_to_phys,
+ .probe_device = apple_dart_probe_device,
+ .release_device = apple_dart_release_device,
+ .device_group = apple_dart_device_group,
+ .of_xlate = apple_dart_of_xlate,
+ .def_domain_type = apple_dart_def_domain_type,
+ .pgsize_bitmap = -1UL, /* Restricted during dart probe */
+};
+
+static irqreturn_t apple_dart_irq(int irq, void *dev)
+{
+ struct apple_dart *dart = dev;
+ const char *fault_name = NULL;
+ u32 error = readl(dart->regs + DART_ERROR);
+ u32 error_code = FIELD_GET(DART_ERROR_CODE, error);
+ u32 addr_lo = readl(dart->regs + DART_ERROR_ADDR_LO);
+ u32 addr_hi = readl(dart->regs + DART_ERROR_ADDR_HI);
+ u64 addr = addr_lo | (((u64)addr_hi) << 32);
+ u8 stream_idx = FIELD_GET(DART_ERROR_STREAM, error);
+
+ if (!(error & DART_ERROR_FLAG))
+ return IRQ_NONE;
+
+ /* there should only be a single bit set but let's use == to be sure */
+ if (error_code == DART_ERROR_READ_FAULT)
+ fault_name = "READ FAULT";
+ else if (error_code == DART_ERROR_WRITE_FAULT)
+ fault_name = "WRITE FAULT";
+ else if (error_code == DART_ERROR_NO_PTE)
+ fault_name = "NO PTE FOR IOVA";
+ else if (error_code == DART_ERROR_NO_PMD)
+ fault_name = "NO PMD FOR IOVA";
+ else if (error_code == DART_ERROR_NO_TTBR)
+ fault_name = "NO TTBR FOR IOVA";
+ else
+ fault_name = "unknown";
+
+ dev_err_ratelimited(
+ dart->dev,
+ "translation fault: status:0x%x stream:%d code:0x%x (%s) at 0x%llx",
+ error, stream_idx, error_code, fault_name, addr);
+
+ writel(error, dart->regs + DART_ERROR);
+ return IRQ_HANDLED;
+}
+
+static int apple_dart_set_bus_ops(const struct iommu_ops *ops)
+{
+ int ret;
+
+ if (!iommu_present(&platform_bus_type)) {
+ ret = bus_set_iommu(&platform_bus_type, ops);
+ if (ret)
+ return ret;
+ }
+#ifdef CONFIG_PCI
+ if (!iommu_present(&pci_bus_type)) {
+ ret = bus_set_iommu(&pci_bus_type, ops);
+ if (ret) {
+ bus_set_iommu(&platform_bus_type, NULL);
+ return ret;
+ }
+ }
+#endif
+ return 0;
+}
+
+static int apple_dart_probe(struct platform_device *pdev)
+{
+ int ret;
+ u32 dart_params[2];
+ struct resource *res;
+ struct apple_dart *dart;
+ struct device *dev = &pdev->dev;
+
+ dart = devm_kzalloc(dev, sizeof(*dart), GFP_KERNEL);
+ if (!dart)
+ return -ENOMEM;
+
+ dart->dev = dev;
+ spin_lock_init(&dart->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (resource_size(res) < 0x4000) {
+ dev_err(dev, "MMIO region too small (%pr)\n", res);
+ return -EINVAL;
+ }
+
+ dart->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(dart->regs))
+ return PTR_ERR(dart->regs);
+
+ dart->irq = platform_get_irq(pdev, 0);
+ if (dart->irq < 0)
+ return -ENODEV;
+
+ ret = devm_clk_bulk_get_all(dev, &dart->clks);
+ if (ret < 0)
+ return ret;
+ dart->num_clks = ret;
+
+ ret = clk_bulk_prepare_enable(dart->num_clks, dart->clks);
+ if (ret)
+ return ret;
+
+ ret = apple_dart_hw_reset(dart);
+ if (ret)
+ goto err_clk_disable;
+
+ dart_params[0] = readl(dart->regs + DART_PARAMS1);
+ dart_params[1] = readl(dart->regs + DART_PARAMS2);
+ dart->pgsize = 1 << FIELD_GET(DART_PARAMS_PAGE_SHIFT, dart_params[0]);
+ dart->supports_bypass = dart_params[1] & DART_PARAMS_BYPASS_SUPPORT;
+ dart->force_bypass = dart->pgsize > PAGE_SIZE;
+
+ ret = request_irq(dart->irq, apple_dart_irq, IRQF_SHARED,
+ "apple-dart fault handler", dart);
+ if (ret)
+ goto err_clk_disable;
+
+ platform_set_drvdata(pdev, dart);
+
+ ret = apple_dart_set_bus_ops(&apple_dart_iommu_ops);
+ if (ret)
+ goto err_free_irq;
+
+ ret = iommu_device_sysfs_add(&dart->iommu, dev, NULL, "apple-dart.%s",
+ dev_name(&pdev->dev));
+ if (ret)
+ goto err_remove_bus_ops;
+
+ ret = iommu_device_register(&dart->iommu, &apple_dart_iommu_ops, dev);
+ if (ret)
+ goto err_sysfs_remove;
+
+ dev_info(
+ &pdev->dev,
+ "DART [pagesize %x, bypass support: %d, bypass forced: %d] initialized\n",
+ dart->pgsize, dart->supports_bypass, dart->force_bypass);
+ return 0;
+
+err_sysfs_remove:
+ iommu_device_sysfs_remove(&dart->iommu);
+err_remove_bus_ops:
+ apple_dart_set_bus_ops(NULL);
+err_free_irq:
+ free_irq(dart->irq, dart);
+err_clk_disable:
+ clk_bulk_disable_unprepare(dart->num_clks, dart->clks);
+
+ return ret;
+}
+
+static int apple_dart_remove(struct platform_device *pdev)
+{
+ struct apple_dart *dart = platform_get_drvdata(pdev);
+
+ apple_dart_hw_reset(dart);
+ free_irq(dart->irq, dart);
+ apple_dart_set_bus_ops(NULL);
+
+ iommu_device_unregister(&dart->iommu);
+ iommu_device_sysfs_remove(&dart->iommu);
+
+ clk_bulk_disable_unprepare(dart->num_clks, dart->clks);
+
+ return 0;
+}
+
+static const struct of_device_id apple_dart_of_match[] = {
+ { .compatible = "apple,t8103-dart", .data = NULL },
+ {},
+};
+MODULE_DEVICE_TABLE(of, apple_dart_of_match);
+
+static struct platform_driver apple_dart_driver = {
+ .driver = {
+ .name = "apple-dart",
+ .of_match_table = apple_dart_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = apple_dart_probe,
+ .remove = apple_dart_remove,
+};
+
+module_platform_driver(apple_dart_driver);
+
+MODULE_DESCRIPTION("IOMMU API for Apple's DART");
+MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 235f9bdaeaf2..a388e318f86e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -335,10 +335,14 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
return 0;
}
+static struct arm_smmu_cmdq *arm_smmu_get_cmdq(struct arm_smmu_device *smmu)
+{
+ return &smmu->cmdq;
+}
+
static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device *smmu,
- u32 prod)
+ struct arm_smmu_queue *q, u32 prod)
{
- struct arm_smmu_queue *q = &smmu->cmdq.q;
struct arm_smmu_cmdq_ent ent = {
.opcode = CMDQ_OP_CMD_SYNC,
};
@@ -355,7 +359,8 @@ static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device *smmu,
arm_smmu_cmdq_build_cmd(cmd, &ent);
}
-static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
+static void __arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu,
+ struct arm_smmu_queue *q)
{
static const char * const cerror_str[] = {
[CMDQ_ERR_CERROR_NONE_IDX] = "No error",
@@ -366,7 +371,6 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
int i;
u64 cmd[CMDQ_ENT_DWORDS];
- struct arm_smmu_queue *q = &smmu->cmdq.q;
u32 cons = readl_relaxed(q->cons_reg);
u32 idx = FIELD_GET(CMDQ_CONS_ERR, cons);
struct arm_smmu_cmdq_ent cmd_sync = {
@@ -413,6 +417,11 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
}
+static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
+{
+ __arm_smmu_cmdq_skip_err(smmu, &smmu->cmdq.q);
+}
+
/*
* Command queue locking.
* This is a form of bastardised rwlock with the following major changes:
@@ -579,7 +588,7 @@ static int arm_smmu_cmdq_poll_until_not_full(struct arm_smmu_device *smmu,
{
unsigned long flags;
struct arm_smmu_queue_poll qp;
- struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+ struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
int ret = 0;
/*
@@ -595,7 +604,7 @@ static int arm_smmu_cmdq_poll_until_not_full(struct arm_smmu_device *smmu,
queue_poll_init(smmu, &qp);
do {
- llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+ llq->val = READ_ONCE(cmdq->q.llq.val);
if (!queue_full(llq))
break;
@@ -614,7 +623,7 @@ static int __arm_smmu_cmdq_poll_until_msi(struct arm_smmu_device *smmu,
{
int ret = 0;
struct arm_smmu_queue_poll qp;
- struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+ struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
u32 *cmd = (u32 *)(Q_ENT(&cmdq->q, llq->prod));
queue_poll_init(smmu, &qp);
@@ -637,12 +646,12 @@ static int __arm_smmu_cmdq_poll_until_consumed(struct arm_smmu_device *smmu,
struct arm_smmu_ll_queue *llq)
{
struct arm_smmu_queue_poll qp;
- struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
+ struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
u32 prod = llq->prod;
int ret = 0;
queue_poll_init(smmu, &qp);
- llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
+ llq->val = READ_ONCE(cmdq->q.llq.val);
do {
if (queue_consumed(llq, prod))
break;
@@ -732,12 +741,12 @@ static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
u32 prod;
unsigned long flags;
bool owner;
- struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
- struct arm_smmu_ll_queue llq = {
- .max_n_shift = cmdq->q.llq.max_n_shift,
- }, head = llq;
+ struct arm_smmu_cmdq *cmdq = arm_smmu_get_cmdq(smmu);
+ struct arm_smmu_ll_queue llq, head;
int ret = 0;
+ llq.max_n_shift = cmdq->q.llq.max_n_shift;
+
/* 1. Allocate some space in the queue */
local_irq_save(flags);
llq.val = READ_ONCE(cmdq->q.llq.val);
@@ -772,7 +781,7 @@ static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n);
if (sync) {
prod = queue_inc_prod_n(&llq, n);
- arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod);
+ arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, &cmdq->q, prod);
queue_write(Q_ENT(&cmdq->q, prod), cmd_sync, CMDQ_ENT_DWORDS);
/*
@@ -845,8 +854,9 @@ static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
return ret;
}
-static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
- struct arm_smmu_cmdq_ent *ent)
+static int __arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
+ struct arm_smmu_cmdq_ent *ent,
+ bool sync)
{
u64 cmd[CMDQ_ENT_DWORDS];
@@ -856,12 +866,19 @@ static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
return -EINVAL;
}
- return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, false);
+ return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, sync);
+}
+
+static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
+ struct arm_smmu_cmdq_ent *ent)
+{
+ return __arm_smmu_cmdq_issue_cmd(smmu, ent, false);
}
-static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
+static int arm_smmu_cmdq_issue_cmd_with_sync(struct arm_smmu_device *smmu,
+ struct arm_smmu_cmdq_ent *ent)
{
- return arm_smmu_cmdq_issue_cmdlist(smmu, NULL, 0, true);
+ return __arm_smmu_cmdq_issue_cmd(smmu, ent, true);
}
static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu,
@@ -929,8 +946,7 @@ void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
.tlbi.asid = asid,
};
- arm_smmu_cmdq_issue_cmd(smmu, &cmd);
- arm_smmu_cmdq_issue_sync(smmu);
+ arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
}
static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
@@ -939,7 +955,7 @@ static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
size_t i;
unsigned long flags;
struct arm_smmu_master *master;
- struct arm_smmu_cmdq_batch cmds = {};
+ struct arm_smmu_cmdq_batch cmds;
struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_cmdq_ent cmd = {
.opcode = CMDQ_OP_CFGI_CD,
@@ -949,6 +965,8 @@ static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
},
};
+ cmds.num = 0;
+
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
list_for_each_entry(master, &smmu_domain->devices, domain_head) {
for (i = 0; i < master->num_streams; i++) {
@@ -1211,8 +1229,7 @@ static void arm_smmu_sync_ste_for_sid(struct arm_smmu_device *smmu, u32 sid)
},
};
- arm_smmu_cmdq_issue_cmd(smmu, &cmd);
- arm_smmu_cmdq_issue_sync(smmu);
+ arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
}
static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
@@ -1747,15 +1764,16 @@ static int arm_smmu_atc_inv_master(struct arm_smmu_master *master)
{
int i;
struct arm_smmu_cmdq_ent cmd;
+ struct arm_smmu_cmdq_batch cmds = {};
arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd);
for (i = 0; i < master->num_streams; i++) {
cmd.atc.sid = master->streams[i].id;
- arm_smmu_cmdq_issue_cmd(master->smmu, &cmd);
+ arm_smmu_cmdq_batch_add(master->smmu, &cmds, &cmd);
}
- return arm_smmu_cmdq_issue_sync(master->smmu);
+ return arm_smmu_cmdq_batch_submit(master->smmu, &cmds);
}
int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
@@ -1765,7 +1783,7 @@ int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
unsigned long flags;
struct arm_smmu_cmdq_ent cmd;
struct arm_smmu_master *master;
- struct arm_smmu_cmdq_batch cmds = {};
+ struct arm_smmu_cmdq_batch cmds;
if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS))
return 0;
@@ -1789,6 +1807,8 @@ int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
arm_smmu_atc_inv_to_cmd(ssid, iova, size, &cmd);
+ cmds.num = 0;
+
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
list_for_each_entry(master, &smmu_domain->devices, domain_head) {
if (!master->ats_enabled)
@@ -1823,8 +1843,7 @@ static void arm_smmu_tlb_inv_context(void *cookie)
} else {
cmd.opcode = CMDQ_OP_TLBI_S12_VMALL;
cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid;
- arm_smmu_cmdq_issue_cmd(smmu, &cmd);
- arm_smmu_cmdq_issue_sync(smmu);
+ arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
}
arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
}
@@ -1837,7 +1856,7 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
struct arm_smmu_device *smmu = smmu_domain->smmu;
unsigned long end = iova + size, num_pages = 0, tg = 0;
size_t inv_range = granule;
- struct arm_smmu_cmdq_batch cmds = {};
+ struct arm_smmu_cmdq_batch cmds;
if (!size)
return;
@@ -1855,6 +1874,8 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
num_pages = size >> tg;
}
+ cmds.num = 0;
+
while (iova < end) {
if (smmu->features & ARM_SMMU_FEAT_RANGE_INV) {
/*
@@ -1972,6 +1993,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
if (type != IOMMU_DOMAIN_UNMANAGED &&
type != IOMMU_DOMAIN_DMA &&
+ type != IOMMU_DOMAIN_DMA_FQ &&
type != IOMMU_DOMAIN_IDENTITY)
return NULL;
@@ -1984,12 +2006,6 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
if (!smmu_domain)
return NULL;
- if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&smmu_domain->domain)) {
- kfree(smmu_domain);
- return NULL;
- }
-
mutex_init(&smmu_domain->init_mutex);
INIT_LIST_HEAD(&smmu_domain->devices);
spin_lock_init(&smmu_domain->devices_lock);
@@ -2021,7 +2037,6 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;
- iommu_put_dma_cookie(domain);
free_io_pgtable_ops(smmu_domain->pgtbl_ops);
/* Free the CD and ASID, if we allocated them */
@@ -2181,9 +2196,6 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
.iommu_dev = smmu->dev,
};
- if (!iommu_get_dma_strict(domain))
- pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_NON_STRICT;
-
pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain);
if (!pgtbl_ops)
return -ENOMEM;
@@ -2439,19 +2451,21 @@ out_unlock:
return ret;
}
-static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
- phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
+static int arm_smmu_map_pages(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t pgsize, size_t pgcount,
+ int prot, gfp_t gfp, size_t *mapped)
{
struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
if (!ops)
return -ENODEV;
- return ops->map(ops, iova, paddr, size, prot, gfp);
+ return ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, gfp, mapped);
}
-static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t size, struct iommu_iotlb_gather *gather)
+static size_t arm_smmu_unmap_pages(struct iommu_domain *domain, unsigned long iova,
+ size_t pgsize, size_t pgcount,
+ struct iommu_iotlb_gather *gather)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
@@ -2459,7 +2473,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
if (!ops)
return 0;
- return ops->unmap(ops, iova, size, gather);
+ return ops->unmap_pages(ops, iova, pgsize, pgcount, gather);
}
static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain)
@@ -2488,9 +2502,6 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
{
struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
- if (domain->type == IOMMU_DOMAIN_IDENTITY)
- return iova;
-
if (!ops)
return 0;
@@ -2825,8 +2836,8 @@ static struct iommu_ops arm_smmu_ops = {
.domain_alloc = arm_smmu_domain_alloc,
.domain_free = arm_smmu_domain_free,
.attach_dev = arm_smmu_attach_dev,
- .map = arm_smmu_map,
- .unmap = arm_smmu_unmap,
+ .map_pages = arm_smmu_map_pages,
+ .unmap_pages = arm_smmu_unmap_pages,
.flush_iotlb_all = arm_smmu_flush_iotlb_all,
.iotlb_sync = arm_smmu_iotlb_sync,
.iova_to_phys = arm_smmu_iova_to_phys,
@@ -3338,18 +3349,16 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
/* Invalidate any cached configuration */
cmd.opcode = CMDQ_OP_CFGI_ALL;
- arm_smmu_cmdq_issue_cmd(smmu, &cmd);
- arm_smmu_cmdq_issue_sync(smmu);
+ arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
/* Invalidate any stale TLB entries */
if (smmu->features & ARM_SMMU_FEAT_HYP) {
cmd.opcode = CMDQ_OP_TLBI_EL2_ALL;
- arm_smmu_cmdq_issue_cmd(smmu, &cmd);
+ arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
}
cmd.opcode = CMDQ_OP_TLBI_NSNH_ALL;
- arm_smmu_cmdq_issue_cmd(smmu, &cmd);
- arm_smmu_cmdq_issue_sync(smmu);
+ arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
/* Event queue */
writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 9b9d13ec5a88..55690af1b25d 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -193,6 +193,8 @@ static int qcom_adreno_smmu_init_context(struct arm_smmu_domain *smmu_domain,
{
struct adreno_smmu_priv *priv;
+ smmu_domain->cfg.flush_walk_prefer_tlbiasid = true;
+
/* Only enable split pagetables for the GPU device (SID 0) */
if (!qcom_adreno_smmu_is_gpu_device(dev))
return 0;
@@ -235,6 +237,14 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
{ }
};
+static int qcom_smmu_init_context(struct arm_smmu_domain *smmu_domain,
+ struct io_pgtable_cfg *pgtbl_cfg, struct device *dev)
+{
+ smmu_domain->cfg.flush_walk_prefer_tlbiasid = true;
+
+ return 0;
+}
+
static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
{
unsigned int last_s2cr = ARM_SMMU_GR0_S2CR(smmu->num_mapping_groups - 1);
@@ -358,6 +368,7 @@ static int qcom_smmu500_reset(struct arm_smmu_device *smmu)
}
static const struct arm_smmu_impl qcom_smmu_impl = {
+ .init_context = qcom_smmu_init_context,
.cfg_probe = qcom_smmu_cfg_probe,
.def_domain_type = qcom_smmu_def_domain_type,
.reset = qcom_smmu500_reset,
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index f22dbeb1e510..4bc75c4ce402 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -327,9 +327,16 @@ static void arm_smmu_tlb_inv_range_s2(unsigned long iova, size_t size,
static void arm_smmu_tlb_inv_walk_s1(unsigned long iova, size_t size,
size_t granule, void *cookie)
{
- arm_smmu_tlb_inv_range_s1(iova, size, granule, cookie,
- ARM_SMMU_CB_S1_TLBIVA);
- arm_smmu_tlb_sync_context(cookie);
+ struct arm_smmu_domain *smmu_domain = cookie;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+
+ if (cfg->flush_walk_prefer_tlbiasid) {
+ arm_smmu_tlb_inv_context_s1(cookie);
+ } else {
+ arm_smmu_tlb_inv_range_s1(iova, size, granule, cookie,
+ ARM_SMMU_CB_S1_TLBIVA);
+ arm_smmu_tlb_sync_context(cookie);
+ }
}
static void arm_smmu_tlb_add_page_s1(struct iommu_iotlb_gather *gather,
@@ -765,9 +772,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
.iommu_dev = smmu->dev,
};
- if (!iommu_get_dma_strict(domain))
- pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_NON_STRICT;
-
if (smmu->impl && smmu->impl->init_context) {
ret = smmu->impl->init_context(smmu_domain, &pgtbl_cfg, dev);
if (ret)
@@ -868,10 +872,11 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
{
struct arm_smmu_domain *smmu_domain;
- if (type != IOMMU_DOMAIN_UNMANAGED &&
- type != IOMMU_DOMAIN_DMA &&
- type != IOMMU_DOMAIN_IDENTITY)
- return NULL;
+ if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_IDENTITY) {
+ if (using_legacy_binding ||
+ (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_DMA_FQ))
+ return NULL;
+ }
/*
* Allocate the domain and initialise some of its data structures.
* We can't really do anything meaningful until we've added a
@@ -881,12 +886,6 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
if (!smmu_domain)
return NULL;
- if (type == IOMMU_DOMAIN_DMA && (using_legacy_binding ||
- iommu_get_dma_cookie(&smmu_domain->domain))) {
- kfree(smmu_domain);
- return NULL;
- }
-
mutex_init(&smmu_domain->init_mutex);
spin_lock_init(&smmu_domain->cb_lock);
@@ -901,7 +900,6 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
* Free the domain resources. We assume that all devices have
* already been detached.
*/
- iommu_put_dma_cookie(domain);
arm_smmu_destroy_domain_context(domain);
kfree(smmu_domain);
}
@@ -1198,8 +1196,9 @@ rpm_put:
return ret;
}
-static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
- phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
+static int arm_smmu_map_pages(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t pgsize, size_t pgcount,
+ int prot, gfp_t gfp, size_t *mapped)
{
struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;
@@ -1209,14 +1208,15 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
return -ENODEV;
arm_smmu_rpm_get(smmu);
- ret = ops->map(ops, iova, paddr, size, prot, gfp);
+ ret = ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, gfp, mapped);
arm_smmu_rpm_put(smmu);
return ret;
}
-static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
- size_t size, struct iommu_iotlb_gather *gather)
+static size_t arm_smmu_unmap_pages(struct iommu_domain *domain, unsigned long iova,
+ size_t pgsize, size_t pgcount,
+ struct iommu_iotlb_gather *iotlb_gather)
{
struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;
@@ -1226,7 +1226,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
return 0;
arm_smmu_rpm_get(smmu);
- ret = ops->unmap(ops, iova, size, gather);
+ ret = ops->unmap_pages(ops, iova, pgsize, pgcount, iotlb_gather);
arm_smmu_rpm_put(smmu);
return ret;
@@ -1320,9 +1320,6 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
- if (domain->type == IOMMU_DOMAIN_IDENTITY)
- return iova;
-
if (!ops)
return 0;
@@ -1478,16 +1475,21 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev)
struct iommu_group *group = NULL;
int i, idx;
+ mutex_lock(&smmu->stream_map_mutex);
for_each_cfg_sme(cfg, fwspec, i, idx) {
if (group && smmu->s2crs[idx].group &&
- group != smmu->s2crs[idx].group)
+ group != smmu->s2crs[idx].group) {
+ mutex_unlock(&smmu->stream_map_mutex);
return ERR_PTR(-EINVAL);
+ }
group = smmu->s2crs[idx].group;
}
- if (group)
+ if (group) {
+ mutex_unlock(&smmu->stream_map_mutex);
return iommu_group_ref_get(group);
+ }
if (dev_is_pci(dev))
group = pci_device_group(dev);
@@ -1501,6 +1503,7 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev)
for_each_cfg_sme(cfg, fwspec, i, idx)
smmu->s2crs[idx].group = group;
+ mutex_unlock(&smmu->stream_map_mutex);
return group;
}
@@ -1582,8 +1585,8 @@ static struct iommu_ops arm_smmu_ops = {
.domain_alloc = arm_smmu_domain_alloc,
.domain_free = arm_smmu_domain_free,
.attach_dev = arm_smmu_attach_dev,
- .map = arm_smmu_map,
- .unmap = arm_smmu_unmap,
+ .map_pages = arm_smmu_map_pages,
+ .unmap_pages = arm_smmu_unmap_pages,
.flush_iotlb_all = arm_smmu_flush_iotlb_all,
.iotlb_sync = arm_smmu_iotlb_sync,
.iova_to_phys = arm_smmu_iova_to_phys,
@@ -2281,18 +2284,38 @@ static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev)
static int __maybe_unused arm_smmu_pm_resume(struct device *dev)
{
+ int ret;
+ struct arm_smmu_device *smmu = dev_get_drvdata(dev);
+
+ ret = clk_bulk_prepare(smmu->num_clks, smmu->clks);
+ if (ret)
+ return ret;
+
if (pm_runtime_suspended(dev))
return 0;
- return arm_smmu_runtime_resume(dev);
+ ret = arm_smmu_runtime_resume(dev);
+ if (ret)
+ clk_bulk_unprepare(smmu->num_clks, smmu->clks);
+
+ return ret;
}
static int __maybe_unused arm_smmu_pm_suspend(struct device *dev)
{
+ int ret = 0;
+ struct arm_smmu_device *smmu = dev_get_drvdata(dev);
+
if (pm_runtime_suspended(dev))
- return 0;
+ goto clk_unprepare;
+
+ ret = arm_smmu_runtime_suspend(dev);
+ if (ret)
+ return ret;
- return arm_smmu_runtime_suspend(dev);
+clk_unprepare:
+ clk_bulk_unprepare(smmu->num_clks, smmu->clks);
+ return ret;
}
static const struct dev_pm_ops arm_smmu_pm_ops = {
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index a50271595960..432de2f742c3 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -346,6 +346,7 @@ struct arm_smmu_cfg {
};
enum arm_smmu_cbar_type cbar;
enum arm_smmu_context_fmt fmt;
+ bool flush_walk_prefer_tlbiasid;
};
#define ARM_SMMU_INVALID_IRPTNDX 0xff
diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index 021cf8f65ffc..b91874cb6cf3 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -10,7 +10,6 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
-#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/interrupt.h>
@@ -335,12 +334,6 @@ static struct iommu_domain *qcom_iommu_domain_alloc(unsigned type)
if (!qcom_domain)
return NULL;
- if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&qcom_domain->domain)) {
- kfree(qcom_domain);
- return NULL;
- }
-
mutex_init(&qcom_domain->init_mutex);
spin_lock_init(&qcom_domain->pgtbl_lock);
@@ -351,8 +344,6 @@ static void qcom_iommu_domain_free(struct iommu_domain *domain)
{
struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
- iommu_put_dma_cookie(domain);
-
if (qcom_domain->iommu) {
/*
* NOTE: unmap can be called after client device is powered
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 6f0df629353f..896bea04c347 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -317,6 +317,30 @@ static bool dev_is_untrusted(struct device *dev)
return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
}
+/* sysfs updates are serialised by the mutex of the group owning @domain */
+int iommu_dma_init_fq(struct iommu_domain *domain)
+{
+ struct iommu_dma_cookie *cookie = domain->iova_cookie;
+ int ret;
+
+ if (cookie->fq_domain)
+ return 0;
+
+ ret = init_iova_flush_queue(&cookie->iovad, iommu_dma_flush_iotlb_all,
+ iommu_dma_entry_dtor);
+ if (ret) {
+ pr_warn("iova flush queue initialization failed\n");
+ return ret;
+ }
+ /*
+ * Prevent incomplete iovad->fq being observable. Pairs with path from
+ * __iommu_dma_unmap() through iommu_dma_free_iova() to queue_iova()
+ */
+ smp_wmb();
+ WRITE_ONCE(cookie->fq_domain, domain);
+ return 0;
+}
+
/**
* iommu_dma_init_domain - Initialise a DMA mapping domain
* @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
@@ -370,17 +394,9 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
init_iova_domain(iovad, 1UL << order, base_pfn);
- if (!cookie->fq_domain && (!dev || !dev_is_untrusted(dev)) &&
- domain->ops->flush_iotlb_all && !iommu_get_dma_strict(domain)) {
- if (init_iova_flush_queue(iovad, iommu_dma_flush_iotlb_all,
- iommu_dma_entry_dtor))
- pr_warn("iova flush queue initialization failed\n");
- else
- cookie->fq_domain = domain;
- }
-
- if (!dev)
- return 0;
+ /* If the FQ fails we can simply fall back to strict mode */
+ if (domain->type == IOMMU_DOMAIN_DMA_FQ && iommu_dma_init_fq(domain))
+ domain->type = IOMMU_DOMAIN_DMA;
return iova_reserve_iommu_regions(dev, domain);
}
@@ -455,17 +471,17 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
}
static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
- dma_addr_t iova, size_t size, struct page *freelist)
+ dma_addr_t iova, size_t size, struct iommu_iotlb_gather *gather)
{
struct iova_domain *iovad = &cookie->iovad;
/* The MSI case is only ever cleaning up its most recent allocation */
if (cookie->type == IOMMU_DMA_MSI_COOKIE)
cookie->msi_iova -= size;
- else if (cookie->fq_domain) /* non-strict mode */
+ else if (gather && gather->queued)
queue_iova(iovad, iova_pfn(iovad, iova),
size >> iova_shift(iovad),
- (unsigned long)freelist);
+ (unsigned long)gather->freelist);
else
free_iova_fast(iovad, iova_pfn(iovad, iova),
size >> iova_shift(iovad));
@@ -484,13 +500,14 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr,
dma_addr -= iova_off;
size = iova_align(iovad, size + iova_off);
iommu_iotlb_gather_init(&iotlb_gather);
+ iotlb_gather.queued = READ_ONCE(cookie->fq_domain);
unmapped = iommu_unmap_fast(domain, dma_addr, size, &iotlb_gather);
WARN_ON(unmapped != size);
- if (!cookie->fq_domain)
+ if (!iotlb_gather.queued)
iommu_iotlb_sync(domain, &iotlb_gather);
- iommu_dma_free_iova(cookie, dma_addr, size, iotlb_gather.freelist);
+ iommu_dma_free_iova(cookie, dma_addr, size, &iotlb_gather);
}
static void __iommu_dma_unmap_swiotlb(struct device *dev, dma_addr_t dma_addr,
@@ -506,7 +523,7 @@ static void __iommu_dma_unmap_swiotlb(struct device *dev, dma_addr_t dma_addr,
__iommu_dma_unmap(dev, dma_addr, size);
- if (unlikely(is_swiotlb_buffer(phys)))
+ if (unlikely(is_swiotlb_buffer(dev, phys)))
swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs);
}
@@ -577,7 +594,7 @@ static dma_addr_t __iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys,
}
iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask);
- if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(phys))
+ if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys))
swiotlb_tbl_unmap_single(dev, phys, org_size, dir, attrs);
return iova;
}
@@ -784,7 +801,7 @@ static void iommu_dma_sync_single_for_cpu(struct device *dev,
if (!dev_is_dma_coherent(dev))
arch_sync_dma_for_cpu(phys, size, dir);
- if (is_swiotlb_buffer(phys))
+ if (is_swiotlb_buffer(dev, phys))
swiotlb_sync_single_for_cpu(dev, phys, size, dir);
}
@@ -797,7 +814,7 @@ static void iommu_dma_sync_single_for_device(struct device *dev,
return;
phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
- if (is_swiotlb_buffer(phys))
+ if (is_swiotlb_buffer(dev, phys))
swiotlb_sync_single_for_device(dev, phys, size, dir);
if (!dev_is_dma_coherent(dev))
@@ -818,7 +835,7 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev,
if (!dev_is_dma_coherent(dev))
arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir);
- if (is_swiotlb_buffer(sg_phys(sg)))
+ if (is_swiotlb_buffer(dev, sg_phys(sg)))
swiotlb_sync_single_for_cpu(dev, sg_phys(sg),
sg->length, dir);
}
@@ -835,7 +852,7 @@ static void iommu_dma_sync_sg_for_device(struct device *dev,
return;
for_each_sg(sgl, sg, nelems, i) {
- if (is_swiotlb_buffer(sg_phys(sg)))
+ if (is_swiotlb_buffer(dev, sg_phys(sg)))
swiotlb_sync_single_for_device(dev, sg_phys(sg),
sg->length, dir);
@@ -973,7 +990,7 @@ static int iommu_dma_map_sg_swiotlb(struct device *dev, struct scatterlist *sg,
out_unmap:
iommu_dma_unmap_sg_swiotlb(dev, sg, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC);
- return 0;
+ return -EIO;
}
/*
@@ -994,11 +1011,13 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
dma_addr_t iova;
size_t iova_len = 0;
unsigned long mask = dma_get_seg_boundary(dev);
+ ssize_t ret;
int i;
- if (static_branch_unlikely(&iommu_deferred_attach_enabled) &&
- iommu_deferred_attach(dev, domain))
- return 0;
+ if (static_branch_unlikely(&iommu_deferred_attach_enabled)) {
+ ret = iommu_deferred_attach(dev, domain);
+ goto out;
+ }
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
iommu_dma_sync_sg_for_device(dev, sg, nents, dir);
@@ -1046,14 +1065,17 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
}
iova = iommu_dma_alloc_iova(domain, iova_len, dma_get_mask(dev), dev);
- if (!iova)
+ if (!iova) {
+ ret = -ENOMEM;
goto out_restore_sg;
+ }
/*
* We'll leave any physical concatenation to the IOMMU driver's
* implementation - it knows better than we do.
*/
- if (iommu_map_sg_atomic(domain, iova, sg, nents, prot) < iova_len)
+ ret = iommu_map_sg_atomic(domain, iova, sg, nents, prot);
+ if (ret < iova_len)
goto out_free_iova;
return __finalise_sg(dev, sg, nents, iova);
@@ -1062,7 +1084,10 @@ out_free_iova:
iommu_dma_free_iova(cookie, iova, iova_len, NULL);
out_restore_sg:
__invalidate_sg(sg, nents);
- return 0;
+out:
+ if (ret != -ENOMEM)
+ return -EINVAL;
+ return ret;
}
static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
@@ -1322,7 +1347,7 @@ void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 dma_limit)
* The IOMMU core code allocates the default DMA domain, which the
* underlying IOMMU driver needs to support via the dma-iommu layer.
*/
- if (domain->type == IOMMU_DOMAIN_DMA) {
+ if (iommu_is_dma_domain(domain)) {
if (iommu_dma_init_domain(domain, dma_base, dma_limit, dev))
goto out_err;
dev->dma_ops = &iommu_dma_ops;
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index d0fbf1d10e18..939ffa768986 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -21,7 +21,6 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
-#include <linux/dma-iommu.h>
typedef u32 sysmmu_iova_t;
typedef u32 sysmmu_pte_t;
@@ -735,20 +734,16 @@ static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type)
/* Check if correct PTE offsets are initialized */
BUG_ON(PG_ENT_SHIFT < 0 || !dma_dev);
+ if (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_UNMANAGED)
+ return NULL;
+
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
- if (type == IOMMU_DOMAIN_DMA) {
- if (iommu_get_dma_cookie(&domain->domain) != 0)
- goto err_pgtable;
- } else if (type != IOMMU_DOMAIN_UNMANAGED) {
- goto err_pgtable;
- }
-
domain->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
if (!domain->pgtable)
- goto err_dma_cookie;
+ goto err_pgtable;
domain->lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
if (!domain->lv2entcnt)
@@ -779,9 +774,6 @@ err_lv2ent:
free_pages((unsigned long)domain->lv2entcnt, 1);
err_counter:
free_pages((unsigned long)domain->pgtable, 2);
-err_dma_cookie:
- if (type == IOMMU_DOMAIN_DMA)
- iommu_put_dma_cookie(&domain->domain);
err_pgtable:
kfree(domain);
return NULL;
@@ -809,9 +801,6 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain)
spin_unlock_irqrestore(&domain->lock, flags);
- if (iommu_domain->type == IOMMU_DOMAIN_DMA)
- iommu_put_dma_cookie(iommu_domain);
-
dma_unmap_single(dma_dev, virt_to_phys(domain->pgtable), LV1TABLE_SIZE,
DMA_TO_DEVICE);
diff --git a/drivers/iommu/intel/Kconfig b/drivers/iommu/intel/Kconfig
index 43ebd8af11c5..0ddb77115be7 100644
--- a/drivers/iommu/intel/Kconfig
+++ b/drivers/iommu/intel/Kconfig
@@ -25,9 +25,11 @@ config INTEL_IOMMU
and include PCI device scope covered by these DMA
remapping devices.
+if INTEL_IOMMU
+
config INTEL_IOMMU_DEBUGFS
bool "Export Intel IOMMU internals in Debugfs"
- depends on INTEL_IOMMU && IOMMU_DEBUGFS
+ depends on IOMMU_DEBUGFS
select DMAR_PERF
help
!!!WARNING!!!
@@ -41,7 +43,7 @@ config INTEL_IOMMU_DEBUGFS
config INTEL_IOMMU_SVM
bool "Support for Shared Virtual Memory with Intel IOMMU"
- depends on INTEL_IOMMU && X86_64
+ depends on X86_64
select PCI_PASID
select PCI_PRI
select MMU_NOTIFIER
@@ -53,9 +55,8 @@ config INTEL_IOMMU_SVM
means of a Process Address Space ID (PASID).
config INTEL_IOMMU_DEFAULT_ON
- def_bool y
- prompt "Enable Intel DMA Remapping Devices by default"
- depends on INTEL_IOMMU
+ bool "Enable Intel DMA Remapping Devices by default"
+ default y
help
Selecting this option will enable a DMAR device at boot time if
one is found. If this option is not selected, DMAR support can
@@ -63,7 +64,7 @@ config INTEL_IOMMU_DEFAULT_ON
config INTEL_IOMMU_BROKEN_GFX_WA
bool "Workaround broken graphics drivers (going away soon)"
- depends on INTEL_IOMMU && BROKEN && X86
+ depends on BROKEN && X86
help
Current Graphics drivers tend to use physical address
for DMA and avoid using DMA APIs. Setting this config
@@ -74,7 +75,7 @@ config INTEL_IOMMU_BROKEN_GFX_WA
config INTEL_IOMMU_FLOPPY_WA
def_bool y
- depends on INTEL_IOMMU && X86
+ depends on X86
help
Floppy disk drivers are known to bypass DMA API calls
thereby failing to work when IOMMU is enabled. This
@@ -83,7 +84,7 @@ config INTEL_IOMMU_FLOPPY_WA
config INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON
bool "Enable Intel IOMMU scalable mode by default"
- depends on INTEL_IOMMU
+ default y
help
Selecting this option will enable by default the scalable mode if
hardware presents the capability. The scalable mode is defined in
@@ -92,3 +93,5 @@ config INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON
is not selected, scalable mode support could also be enabled by
passing intel_iommu=sm_on to the kernel. If not sure, please use
the default value.
+
+endif # INTEL_IOMMU
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index d66f79acd14d..0ec5514c9980 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -149,8 +149,6 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event)
} else {
info = kzalloc(size, GFP_KERNEL);
if (!info) {
- pr_warn("Out of memory when allocating notify_info "
- "for %s.\n", pci_name(dev));
if (dmar_dev_scope_status == 0)
dmar_dev_scope_status = -ENOMEM;
return NULL;
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index dd22fc7d5176..d75f59ae28e6 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -33,6 +33,7 @@
#include <linux/iommu.h>
#include <linux/dma-iommu.h>
#include <linux/intel-iommu.h>
+#include <linux/intel-svm.h>
#include <linux/syscore_ops.h>
#include <linux/tboot.h>
#include <linux/dmi.h>
@@ -85,24 +86,6 @@
#define LEVEL_STRIDE (9)
#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
-/*
- * This bitmap is used to advertise the page sizes our hardware support
- * to the IOMMU core, which will then use this information to split
- * physically contiguous memory regions it is mapping into page sizes
- * that we support.
- *
- * Traditionally the IOMMU core just handed us the mappings directly,
- * after making sure the size is an order of a 4KiB page and that the
- * mapping has natural alignment.
- *
- * To retain this behavior, we currently advertise that we support
- * all page sizes that are an order of 4KiB.
- *
- * If at some point we'd like to utilize the IOMMU core's new behavior,
- * we could change this to advertise the real page sizes we support.
- */
-#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
-
static inline int agaw_to_level(int agaw)
{
return agaw + 2;
@@ -345,23 +328,13 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova);
-#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
-int dmar_disabled = 0;
-#else
-int dmar_disabled = 1;
-#endif /* CONFIG_INTEL_IOMMU_DEFAULT_ON */
-
-#ifdef CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON
-int intel_iommu_sm = 1;
-#else
-int intel_iommu_sm;
-#endif /* CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON */
+int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
+int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON);
int intel_iommu_enabled = 0;
EXPORT_SYMBOL_GPL(intel_iommu_enabled);
static int dmar_map_gfx = 1;
-static int intel_iommu_strict;
static int intel_iommu_superpage = 1;
static int iommu_identity_mapping;
static int iommu_skip_te_disable;
@@ -454,14 +427,17 @@ static int __init intel_iommu_setup(char *str)
pr_warn("intel_iommu=forcedac deprecated; use iommu.forcedac instead\n");
iommu_dma_forcedac = true;
} else if (!strncmp(str, "strict", 6)) {
- pr_info("Disable batched IOTLB flush\n");
- intel_iommu_strict = 1;
+ pr_warn("intel_iommu=strict deprecated; use iommu.strict=1 instead\n");
+ iommu_set_dma_strict();
} else if (!strncmp(str, "sp_off", 6)) {
pr_info("Disable supported super page\n");
intel_iommu_superpage = 0;
} else if (!strncmp(str, "sm_on", 5)) {
- pr_info("Intel-IOMMU: scalable mode supported\n");
+ pr_info("Enable scalable mode if hardware supports\n");
intel_iommu_sm = 1;
+ } else if (!strncmp(str, "sm_off", 6)) {
+ pr_info("Scalable mode is disallowed\n");
+ intel_iommu_sm = 0;
} else if (!strncmp(str, "tboot_noforce", 13)) {
pr_info("Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
intel_iommu_tboot_noforce = 1;
@@ -601,7 +577,7 @@ struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
int iommu_id;
/* si_domain and vm domain should not get here. */
- if (WARN_ON(domain->domain.type != IOMMU_DOMAIN_DMA))
+ if (WARN_ON(!iommu_is_dma_domain(&domain->domain)))
return NULL;
for_each_domain_iommu(iommu_id, domain)
@@ -736,6 +712,23 @@ static int domain_update_device_node(struct dmar_domain *domain)
static void domain_update_iotlb(struct dmar_domain *domain);
+/* Return the super pagesize bitmap if supported. */
+static unsigned long domain_super_pgsize_bitmap(struct dmar_domain *domain)
+{
+ unsigned long bitmap = 0;
+
+ /*
+ * 1-level super page supports page size of 2MiB, 2-level super page
+ * supports page size of both 2MiB and 1GiB.
+ */
+ if (domain->iommu_superpage == 1)
+ bitmap |= SZ_2M;
+ else if (domain->iommu_superpage == 2)
+ bitmap |= SZ_2M | SZ_1G;
+
+ return bitmap;
+}
+
/* Some capabilities may be different across iommus */
static void domain_update_iommu_cap(struct dmar_domain *domain)
{
@@ -762,6 +755,7 @@ static void domain_update_iommu_cap(struct dmar_domain *domain)
else
domain->domain.geometry.aperture_end = __DOMAIN_MAX_ADDR(domain->gaw);
+ domain->domain.pgsize_bitmap |= domain_super_pgsize_bitmap(domain);
domain_update_iotlb(domain);
}
@@ -1035,7 +1029,7 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
if (domain_use_first_level(domain)) {
pteval |= DMA_FL_PTE_XD | DMA_FL_PTE_US;
- if (domain->domain.type == IOMMU_DOMAIN_DMA)
+ if (iommu_is_dma_domain(&domain->domain))
pteval |= DMA_FL_PTE_ACCESS;
}
if (cmpxchg64(&pte->val, 0ULL, pteval))
@@ -1548,7 +1542,7 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info)
if (info->pri_supported &&
(info->pasid_enabled ? pci_prg_resp_pasid_required(pdev) : 1) &&
- !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32))
+ !pci_reset_pri(pdev) && !pci_enable_pri(pdev, PRQ_DEPTH))
info->pri_enabled = 1;
#endif
if (info->ats_supported && pci_ats_page_aligned(pdev) &&
@@ -1780,11 +1774,8 @@ static int iommu_init_domains(struct intel_iommu *iommu)
spin_lock_init(&iommu->lock);
iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
- if (!iommu->domain_ids) {
- pr_err("%s: Allocating domain id array failed\n",
- iommu->name);
+ if (!iommu->domain_ids)
return -ENOMEM;
- }
size = (ALIGN(ndomains, 256) >> 8) * sizeof(struct dmar_domain **);
iommu->domains = kzalloc(size, GFP_KERNEL);
@@ -1980,10 +1971,6 @@ static void domain_exit(struct dmar_domain *domain)
/* Remove associated devices and clear attached or cached domains */
domain_remove_dev_info(domain);
- /* destroy iovas */
- if (domain->domain.type == IOMMU_DOMAIN_DMA)
- iommu_put_dma_cookie(&domain->domain);
-
if (domain->pgd) {
struct page *freelist;
@@ -2334,9 +2321,9 @@ static int
__domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
unsigned long phys_pfn, unsigned long nr_pages, int prot)
{
+ struct dma_pte *first_pte = NULL, *pte = NULL;
unsigned int largepage_lvl = 0;
unsigned long lvl_pages = 0;
- struct dma_pte *pte = NULL;
phys_addr_t pteval;
u64 attr;
@@ -2348,13 +2335,9 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
attr = prot & (DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP);
attr |= DMA_FL_PTE_PRESENT;
if (domain_use_first_level(domain)) {
- attr |= DMA_FL_PTE_XD | DMA_FL_PTE_US;
-
- if (domain->domain.type == IOMMU_DOMAIN_DMA) {
- attr |= DMA_FL_PTE_ACCESS;
- if (prot & DMA_PTE_WRITE)
- attr |= DMA_FL_PTE_DIRTY;
- }
+ attr |= DMA_FL_PTE_XD | DMA_FL_PTE_US | DMA_FL_PTE_ACCESS;
+ if (prot & DMA_PTE_WRITE)
+ attr |= DMA_FL_PTE_DIRTY;
}
pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | attr;
@@ -2369,6 +2352,8 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
if (!pte)
return -ENOMEM;
+ first_pte = pte;
+
/* It is large page*/
if (largepage_lvl > 1) {
unsigned long end_pfn;
@@ -2416,14 +2401,14 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
* recalculate 'pte' and switch back to smaller pages for the
* end of the mapping, if the trailing size is not enough to
* use another superpage (i.e. nr_pages < lvl_pages).
- *
- * We leave clflush for the leaf pte changes to iotlb_sync_map()
- * callback.
*/
pte++;
if (!nr_pages || first_pte_in_page(pte) ||
- (largepage_lvl > 1 && nr_pages < lvl_pages))
+ (largepage_lvl > 1 && nr_pages < lvl_pages)) {
+ domain_flush_cache(domain, first_pte,
+ (void *)pte - (void *)first_pte);
pte = NULL;
+ }
}
return 0;
@@ -3227,7 +3212,6 @@ static int __init init_dmars(void)
g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
GFP_KERNEL);
if (!g_iommus) {
- pr_err("Allocating global iommu array failed\n");
ret = -ENOMEM;
goto error;
}
@@ -4393,9 +4377,9 @@ int __init intel_iommu_init(void)
* is likely to be much lower than the overhead of synchronizing
* the virtual and physical IOMMU page-tables.
*/
- if (!intel_iommu_strict && cap_caching_mode(iommu->cap)) {
- pr_warn("IOMMU batching is disabled due to virtualization");
- intel_iommu_strict = 1;
+ if (cap_caching_mode(iommu->cap)) {
+ pr_info_once("IOMMU batching disallowed due to virtualization\n");
+ iommu_set_dma_strict();
}
iommu_device_sysfs_add(&iommu->iommu, NULL,
intel_iommu_groups,
@@ -4404,7 +4388,6 @@ int __init intel_iommu_init(void)
}
up_read(&dmar_global_lock);
- iommu_set_dma_strict(intel_iommu_strict);
bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
if (si_domain && !hw_pass_through)
register_memory_notifier(&intel_iommu_memory_nb);
@@ -4532,6 +4515,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
switch (type) {
case IOMMU_DOMAIN_DMA:
+ case IOMMU_DOMAIN_DMA_FQ:
case IOMMU_DOMAIN_UNMANAGED:
dmar_domain = alloc_domain(0);
if (!dmar_domain) {
@@ -4544,10 +4528,6 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
return NULL;
}
- if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&dmar_domain->domain))
- return NULL;
-
domain = &dmar_domain->domain;
domain->geometry.aperture_start = 0;
domain->geometry.aperture_end =
@@ -5067,6 +5047,28 @@ static int intel_iommu_map(struct iommu_domain *domain,
hpa >> VTD_PAGE_SHIFT, size, prot);
}
+static int intel_iommu_map_pages(struct iommu_domain *domain,
+ unsigned long iova, phys_addr_t paddr,
+ size_t pgsize, size_t pgcount,
+ int prot, gfp_t gfp, size_t *mapped)
+{
+ unsigned long pgshift = __ffs(pgsize);
+ size_t size = pgcount << pgshift;
+ int ret;
+
+ if (pgsize != SZ_4K && pgsize != SZ_2M && pgsize != SZ_1G)
+ return -EINVAL;
+
+ if (!IS_ALIGNED(iova | paddr, pgsize))
+ return -EINVAL;
+
+ ret = intel_iommu_map(domain, iova, paddr, size, prot, gfp);
+ if (!ret && mapped)
+ *mapped = size;
+
+ return ret;
+}
+
static size_t intel_iommu_unmap(struct iommu_domain *domain,
unsigned long iova, size_t size,
struct iommu_iotlb_gather *gather)
@@ -5096,6 +5098,17 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
return size;
}
+static size_t intel_iommu_unmap_pages(struct iommu_domain *domain,
+ unsigned long iova,
+ size_t pgsize, size_t pgcount,
+ struct iommu_iotlb_gather *gather)
+{
+ unsigned long pgshift = __ffs(pgsize);
+ size_t size = pgcount << pgshift;
+
+ return intel_iommu_unmap(domain, iova, size, gather);
+}
+
static void intel_iommu_tlb_sync(struct iommu_domain *domain,
struct iommu_iotlb_gather *gather)
{
@@ -5172,12 +5185,8 @@ static void intel_iommu_release_device(struct device *dev)
static void intel_iommu_probe_finalize(struct device *dev)
{
- struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-
- if (domain && domain->type == IOMMU_DOMAIN_DMA)
- iommu_setup_dma_ops(dev, 0, U64_MAX);
- else
- set_dma_ops(dev, NULL);
+ set_dma_ops(dev, NULL);
+ iommu_setup_dma_ops(dev, 0, U64_MAX);
}
static void intel_iommu_get_resv_regions(struct device *device,
@@ -5532,39 +5541,6 @@ static bool risky_device(struct pci_dev *pdev)
return false;
}
-static void clflush_sync_map(struct dmar_domain *domain, unsigned long clf_pfn,
- unsigned long clf_pages)
-{
- struct dma_pte *first_pte = NULL, *pte = NULL;
- unsigned long lvl_pages = 0;
- int level = 0;
-
- while (clf_pages > 0) {
- if (!pte) {
- level = 0;
- pte = pfn_to_dma_pte(domain, clf_pfn, &level);
- if (WARN_ON(!pte))
- return;
- first_pte = pte;
- lvl_pages = lvl_to_nr_pages(level);
- }
-
- if (WARN_ON(!lvl_pages || clf_pages < lvl_pages))
- return;
-
- clf_pages -= lvl_pages;
- clf_pfn += lvl_pages;
- pte++;
-
- if (!clf_pages || first_pte_in_page(pte) ||
- (level > 1 && clf_pages < lvl_pages)) {
- domain_flush_cache(domain, first_pte,
- (void *)pte - (void *)first_pte);
- pte = NULL;
- }
- }
-}
-
static void intel_iommu_iotlb_sync_map(struct iommu_domain *domain,
unsigned long iova, size_t size)
{
@@ -5574,9 +5550,6 @@ static void intel_iommu_iotlb_sync_map(struct iommu_domain *domain,
struct intel_iommu *iommu;
int iommu_id;
- if (!dmar_domain->iommu_coherency)
- clflush_sync_map(dmar_domain, pfn, pages);
-
for_each_domain_iommu(iommu_id, dmar_domain) {
iommu = g_iommus[iommu_id];
__mapping_notify_one(iommu, dmar_domain, pfn, pages);
@@ -5593,9 +5566,9 @@ const struct iommu_ops intel_iommu_ops = {
.aux_attach_dev = intel_iommu_aux_attach_device,
.aux_detach_dev = intel_iommu_aux_detach_device,
.aux_get_pasid = intel_iommu_aux_get_pasid,
- .map = intel_iommu_map,
+ .map_pages = intel_iommu_map_pages,
+ .unmap_pages = intel_iommu_unmap_pages,
.iotlb_sync_map = intel_iommu_iotlb_sync_map,
- .unmap = intel_iommu_unmap,
.flush_iotlb_all = intel_flush_iotlb_all,
.iotlb_sync = intel_iommu_tlb_sync,
.iova_to_phys = intel_iommu_iova_to_phys,
@@ -5611,7 +5584,7 @@ const struct iommu_ops intel_iommu_ops = {
.dev_disable_feat = intel_iommu_dev_disable_feat,
.is_attach_deferred = intel_iommu_is_attach_deferred,
.def_domain_type = device_def_domain_type,
- .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
+ .pgsize_bitmap = SZ_4K,
#ifdef CONFIG_INTEL_IOMMU_SVM
.cache_invalidate = intel_iommu_sva_invalidate,
.sva_bind_gpasid = intel_svm_bind_gpasid,
@@ -5714,8 +5687,8 @@ static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
} else if (dmar_map_gfx) {
/* we have to ensure the gfx device is idle before we flush */
pci_info(dev, "Disabling batched IOTLB flush on Ironlake\n");
- intel_iommu_strict = 1;
- }
+ iommu_set_dma_strict();
+ }
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
index 9ec374e17469..07c390aed1fe 100644
--- a/drivers/iommu/intel/pasid.c
+++ b/drivers/iommu/intel/pasid.c
@@ -517,7 +517,7 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
if (WARN_ON(!pte))
return;
- if (!(pte->val[0] & PASID_PTE_PRESENT))
+ if (!pasid_pte_is_present(pte))
return;
did = pasid_get_domain_id(pte);
@@ -540,6 +540,10 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
devtlb_invalidation_with_pasid(iommu, dev, pasid);
}
+/*
+ * This function flushes cache for a newly setup pasid table entry.
+ * Caller of it should not modify the in-use pasid table entries.
+ */
static void pasid_flush_caches(struct intel_iommu *iommu,
struct pasid_entry *pte,
u32 pasid, u16 did)
@@ -591,6 +595,10 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,
if (WARN_ON(!pte))
return -EINVAL;
+ /* Caller must ensure PASID entry is not in use. */
+ if (pasid_pte_is_present(pte))
+ return -EBUSY;
+
pasid_clear_entry(pte);
/* Setup the first level page table pointer: */
@@ -690,6 +698,10 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
return -ENODEV;
}
+ /* Caller must ensure PASID entry is not in use. */
+ if (pasid_pte_is_present(pte))
+ return -EBUSY;
+
pasid_clear_entry(pte);
pasid_set_domain_id(pte, did);
pasid_set_slptr(pte, pgd_val);
@@ -729,6 +741,10 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
return -ENODEV;
}
+ /* Caller must ensure PASID entry is not in use. */
+ if (pasid_pte_is_present(pte))
+ return -EBUSY;
+
pasid_clear_entry(pte);
pasid_set_domain_id(pte, did);
pasid_set_address_width(pte, iommu->agaw);
diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
index c11bc8b833b8..d5552e2c160d 100644
--- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -28,12 +28,12 @@
#define VCMD_CMD_ALLOC 0x1
#define VCMD_CMD_FREE 0x2
#define VCMD_VRSP_IP 0x1
-#define VCMD_VRSP_SC(e) (((e) >> 1) & 0x3)
+#define VCMD_VRSP_SC(e) (((e) & 0xff) >> 1)
#define VCMD_VRSP_SC_SUCCESS 0
-#define VCMD_VRSP_SC_NO_PASID_AVAIL 2
-#define VCMD_VRSP_SC_INVALID_PASID 2
-#define VCMD_VRSP_RESULT_PASID(e) (((e) >> 8) & 0xfffff)
-#define VCMD_CMD_OPERAND(e) ((e) << 8)
+#define VCMD_VRSP_SC_NO_PASID_AVAIL 16
+#define VCMD_VRSP_SC_INVALID_PASID 16
+#define VCMD_VRSP_RESULT_PASID(e) (((e) >> 16) & 0xfffff)
+#define VCMD_CMD_OPERAND(e) ((e) << 16)
/*
* Domain ID reserved for pasid entries programmed for first-level
* only and pass-through transfer modes.
diff --git a/drivers/iommu/intel/perf.c b/drivers/iommu/intel/perf.c
index 73b7ec705552..0e8e03252d92 100644
--- a/drivers/iommu/intel/perf.c
+++ b/drivers/iommu/intel/perf.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/**
+/*
* perf.c - performance monitor
*
* Copyright (C) 2021 Intel Corporation
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 4b9b3f35ba0e..2014fe8695ac 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -31,8 +31,6 @@ static irqreturn_t prq_event_thread(int irq, void *d);
static void intel_svm_drain_prq(struct device *dev, u32 pasid);
#define to_intel_svm_dev(handle) container_of(handle, struct intel_svm_dev, sva)
-#define PRQ_ORDER 0
-
static DEFINE_XARRAY_ALLOC(pasid_private_array);
static int pasid_private_add(ioasid_t pasid, void *priv)
{
@@ -725,8 +723,6 @@ struct page_req_dsc {
u64 priv_data[2];
};
-#define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x20)
-
static bool is_canonical_address(u64 addr)
{
int shift = 64 - (__VIRTUAL_MASK_SHIFT + 1);
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index d4004bcf333a..bfb6acb651e5 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -519,11 +519,12 @@ static int __arm_v7s_map(struct arm_v7s_io_pgtable *data, unsigned long iova,
return __arm_v7s_map(data, iova, paddr, size, prot, lvl + 1, cptep, gfp);
}
-static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
- phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
+static int arm_v7s_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
+ phys_addr_t paddr, size_t pgsize, size_t pgcount,
+ int prot, gfp_t gfp, size_t *mapped)
{
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
- int ret;
+ int ret = -EINVAL;
if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias) ||
paddr >= (1ULL << data->iop.cfg.oas)))
@@ -533,7 +534,17 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
return 0;
- ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd, gfp);
+ while (pgcount--) {
+ ret = __arm_v7s_map(data, iova, paddr, pgsize, prot, 1, data->pgd,
+ gfp);
+ if (ret)
+ break;
+
+ iova += pgsize;
+ paddr += pgsize;
+ if (mapped)
+ *mapped += pgsize;
+ }
/*
* Synchronise all PTE updates for the new mapping before there's
* a chance for anything to kick off a table walk for the new iova.
@@ -543,6 +554,12 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
return ret;
}
+static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
+ phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
+{
+ return arm_v7s_map_pages(ops, iova, paddr, size, 1, prot, gfp, NULL);
+}
+
static void arm_v7s_free_pgtable(struct io_pgtable *iop)
{
struct arm_v7s_io_pgtable *data = io_pgtable_to_data(iop);
@@ -683,14 +700,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
ARM_V7S_BLOCK_SIZE(lvl + 1));
ptep = iopte_deref(pte[i], lvl, data);
__arm_v7s_free_table(ptep, lvl + 1, data);
- } else if (iop->cfg.quirks & IO_PGTABLE_QUIRK_NON_STRICT) {
- /*
- * Order the PTE update against queueing the IOVA, to
- * guarantee that a flush callback from a different CPU
- * has observed it before the TLBIALL can be issued.
- */
- smp_wmb();
- } else {
+ } else if (!iommu_iotlb_gather_queued(gather)) {
io_pgtable_tlb_add_page(iop, gather, iova, blk_size);
}
iova += blk_size;
@@ -710,15 +720,32 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
return __arm_v7s_unmap(data, gather, iova, size, lvl + 1, ptep);
}
-static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
- size_t size, struct iommu_iotlb_gather *gather)
+static size_t arm_v7s_unmap_pages(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t pgsize, size_t pgcount,
+ struct iommu_iotlb_gather *gather)
{
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
+ size_t unmapped = 0, ret;
if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias)))
return 0;
- return __arm_v7s_unmap(data, gather, iova, size, 1, data->pgd);
+ while (pgcount--) {
+ ret = __arm_v7s_unmap(data, gather, iova, pgsize, 1, data->pgd);
+ if (!ret)
+ break;
+
+ unmapped += pgsize;
+ iova += pgsize;
+ }
+
+ return unmapped;
+}
+
+static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t size, struct iommu_iotlb_gather *gather)
+{
+ return arm_v7s_unmap_pages(ops, iova, size, 1, gather);
}
static phys_addr_t arm_v7s_iova_to_phys(struct io_pgtable_ops *ops,
@@ -757,8 +784,7 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
IO_PGTABLE_QUIRK_NO_PERMS |
- IO_PGTABLE_QUIRK_ARM_MTK_EXT |
- IO_PGTABLE_QUIRK_NON_STRICT))
+ IO_PGTABLE_QUIRK_ARM_MTK_EXT))
return NULL;
/* If ARM_MTK_4GB is enabled, the NO_PERMS is also expected. */
@@ -780,7 +806,9 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
data->iop.ops = (struct io_pgtable_ops) {
.map = arm_v7s_map,
+ .map_pages = arm_v7s_map_pages,
.unmap = arm_v7s_unmap,
+ .unmap_pages = arm_v7s_unmap_pages,
.iova_to_phys = arm_v7s_iova_to_phys,
};
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 87def58e79b5..dd9e47189d0d 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -46,6 +46,9 @@
#define ARM_LPAE_PGD_SIZE(d) \
(sizeof(arm_lpae_iopte) << (d)->pgd_bits)
+#define ARM_LPAE_PTES_PER_TABLE(d) \
+ (ARM_LPAE_GRANULE(d) >> ilog2(sizeof(arm_lpae_iopte)))
+
/*
* Calculate the index at level l used to map virtual address a using the
* pagetable in d.
@@ -127,6 +130,9 @@
#define ARM_MALI_LPAE_MEMATTR_IMP_DEF 0x88ULL
#define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL
+#define APPLE_DART_PTE_PROT_NO_WRITE (1<<7)
+#define APPLE_DART_PTE_PROT_NO_READ (1<<8)
+
/* IOPTE accessors */
#define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d))
@@ -232,70 +238,77 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
free_pages((unsigned long)pages, get_order(size));
}
-static void __arm_lpae_sync_pte(arm_lpae_iopte *ptep,
+static void __arm_lpae_sync_pte(arm_lpae_iopte *ptep, int num_entries,
struct io_pgtable_cfg *cfg)
{
dma_sync_single_for_device(cfg->iommu_dev, __arm_lpae_dma_addr(ptep),
- sizeof(*ptep), DMA_TO_DEVICE);
+ sizeof(*ptep) * num_entries, DMA_TO_DEVICE);
}
-static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
- struct io_pgtable_cfg *cfg)
+static void __arm_lpae_clear_pte(arm_lpae_iopte *ptep, struct io_pgtable_cfg *cfg)
{
- *ptep = pte;
+
+ *ptep = 0;
if (!cfg->coherent_walk)
- __arm_lpae_sync_pte(ptep, cfg);
+ __arm_lpae_sync_pte(ptep, 1, cfg);
}
static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
struct iommu_iotlb_gather *gather,
- unsigned long iova, size_t size, int lvl,
- arm_lpae_iopte *ptep);
+ unsigned long iova, size_t size, size_t pgcount,
+ int lvl, arm_lpae_iopte *ptep);
static void __arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
phys_addr_t paddr, arm_lpae_iopte prot,
- int lvl, arm_lpae_iopte *ptep)
+ int lvl, int num_entries, arm_lpae_iopte *ptep)
{
arm_lpae_iopte pte = prot;
+ struct io_pgtable_cfg *cfg = &data->iop.cfg;
+ size_t sz = ARM_LPAE_BLOCK_SIZE(lvl, data);
+ int i;
if (data->iop.fmt != ARM_MALI_LPAE && lvl == ARM_LPAE_MAX_LEVELS - 1)
pte |= ARM_LPAE_PTE_TYPE_PAGE;
else
pte |= ARM_LPAE_PTE_TYPE_BLOCK;
- pte |= paddr_to_iopte(paddr, data);
+ for (i = 0; i < num_entries; i++)
+ ptep[i] = pte | paddr_to_iopte(paddr + i * sz, data);
- __arm_lpae_set_pte(ptep, pte, &data->iop.cfg);
+ if (!cfg->coherent_walk)
+ __arm_lpae_sync_pte(ptep, num_entries, cfg);
}
static int arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
unsigned long iova, phys_addr_t paddr,
- arm_lpae_iopte prot, int lvl,
+ arm_lpae_iopte prot, int lvl, int num_entries,
arm_lpae_iopte *ptep)
{
- arm_lpae_iopte pte = *ptep;
-
- if (iopte_leaf(pte, lvl, data->iop.fmt)) {
- /* We require an unmap first */
- WARN_ON(!selftest_running);
- return -EEXIST;
- } else if (iopte_type(pte) == ARM_LPAE_PTE_TYPE_TABLE) {
- /*
- * We need to unmap and free the old table before
- * overwriting it with a block entry.
- */
- arm_lpae_iopte *tblp;
- size_t sz = ARM_LPAE_BLOCK_SIZE(lvl, data);
-
- tblp = ptep - ARM_LPAE_LVL_IDX(iova, lvl, data);
- if (__arm_lpae_unmap(data, NULL, iova, sz, lvl, tblp) != sz) {
- WARN_ON(1);
- return -EINVAL;
+ int i;
+
+ for (i = 0; i < num_entries; i++)
+ if (iopte_leaf(ptep[i], lvl, data->iop.fmt)) {
+ /* We require an unmap first */
+ WARN_ON(!selftest_running);
+ return -EEXIST;
+ } else if (iopte_type(ptep[i]) == ARM_LPAE_PTE_TYPE_TABLE) {
+ /*
+ * We need to unmap and free the old table before
+ * overwriting it with a block entry.
+ */
+ arm_lpae_iopte *tblp;
+ size_t sz = ARM_LPAE_BLOCK_SIZE(lvl, data);
+
+ tblp = ptep - ARM_LPAE_LVL_IDX(iova, lvl, data);
+ if (__arm_lpae_unmap(data, NULL, iova + i * sz, sz, 1,
+ lvl, tblp) != sz) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
}
- }
- __arm_lpae_init_pte(data, paddr, prot, lvl, ptep);
+ __arm_lpae_init_pte(data, paddr, prot, lvl, num_entries, ptep);
return 0;
}
@@ -323,7 +336,7 @@ static arm_lpae_iopte arm_lpae_install_table(arm_lpae_iopte *table,
return old;
/* Even if it's not ours, there's no point waiting; just kick it */
- __arm_lpae_sync_pte(ptep, cfg);
+ __arm_lpae_sync_pte(ptep, 1, cfg);
if (old == curr)
WRITE_ONCE(*ptep, new | ARM_LPAE_PTE_SW_SYNC);
@@ -331,20 +344,30 @@ static arm_lpae_iopte arm_lpae_install_table(arm_lpae_iopte *table,
}
static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
- phys_addr_t paddr, size_t size, arm_lpae_iopte prot,
- int lvl, arm_lpae_iopte *ptep, gfp_t gfp)
+ phys_addr_t paddr, size_t size, size_t pgcount,
+ arm_lpae_iopte prot, int lvl, arm_lpae_iopte *ptep,
+ gfp_t gfp, size_t *mapped)
{
arm_lpae_iopte *cptep, pte;
size_t block_size = ARM_LPAE_BLOCK_SIZE(lvl, data);
size_t tblsz = ARM_LPAE_GRANULE(data);
struct io_pgtable_cfg *cfg = &data->iop.cfg;
+ int ret = 0, num_entries, max_entries, map_idx_start;
/* Find our entry at the current level */
- ptep += ARM_LPAE_LVL_IDX(iova, lvl, data);
+ map_idx_start = ARM_LPAE_LVL_IDX(iova, lvl, data);
+ ptep += map_idx_start;
/* If we can install a leaf entry at this level, then do so */
- if (size == block_size)
- return arm_lpae_init_pte(data, iova, paddr, prot, lvl, ptep);
+ if (size == block_size) {
+ max_entries = ARM_LPAE_PTES_PER_TABLE(data) - map_idx_start;
+ num_entries = min_t(int, pgcount, max_entries);
+ ret = arm_lpae_init_pte(data, iova, paddr, prot, lvl, num_entries, ptep);
+ if (!ret && mapped)
+ *mapped += num_entries * size;
+
+ return ret;
+ }
/* We can't allocate tables at the final level */
if (WARN_ON(lvl >= ARM_LPAE_MAX_LEVELS - 1))
@@ -361,7 +384,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
if (pte)
__arm_lpae_free_pages(cptep, tblsz, cfg);
} else if (!cfg->coherent_walk && !(pte & ARM_LPAE_PTE_SW_SYNC)) {
- __arm_lpae_sync_pte(ptep, cfg);
+ __arm_lpae_sync_pte(ptep, 1, cfg);
}
if (pte && !iopte_leaf(pte, lvl, data->iop.fmt)) {
@@ -373,7 +396,8 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
}
/* Rinse, repeat */
- return __arm_lpae_map(data, iova, paddr, size, prot, lvl + 1, cptep, gfp);
+ return __arm_lpae_map(data, iova, paddr, size, pgcount, prot, lvl + 1,
+ cptep, gfp, mapped);
}
static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
@@ -381,6 +405,15 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
{
arm_lpae_iopte pte;
+ if (data->iop.fmt == APPLE_DART) {
+ pte = 0;
+ if (!(prot & IOMMU_WRITE))
+ pte |= APPLE_DART_PTE_PROT_NO_WRITE;
+ if (!(prot & IOMMU_READ))
+ pte |= APPLE_DART_PTE_PROT_NO_READ;
+ return pte;
+ }
+
if (data->iop.fmt == ARM_64_LPAE_S1 ||
data->iop.fmt == ARM_32_LPAE_S1) {
pte = ARM_LPAE_PTE_nG;
@@ -440,8 +473,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
return pte;
}
-static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
- phys_addr_t paddr, size_t size, int iommu_prot, gfp_t gfp)
+static int arm_lpae_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
+ phys_addr_t paddr, size_t pgsize, size_t pgcount,
+ int iommu_prot, gfp_t gfp, size_t *mapped)
{
struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
struct io_pgtable_cfg *cfg = &data->iop.cfg;
@@ -450,7 +484,7 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
arm_lpae_iopte prot;
long iaext = (s64)iova >> cfg->ias;
- if (WARN_ON(!size || (size & cfg->pgsize_bitmap) != size))
+ if (WARN_ON(!pgsize || (pgsize & cfg->pgsize_bitmap) != pgsize))
return -EINVAL;
if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1)
@@ -463,7 +497,8 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
return 0;
prot = arm_lpae_prot_to_pte(data, iommu_prot);
- ret = __arm_lpae_map(data, iova, paddr, size, prot, lvl, ptep, gfp);
+ ret = __arm_lpae_map(data, iova, paddr, pgsize, pgcount, prot, lvl,
+ ptep, gfp, mapped);
/*
* Synchronise all PTE updates for the new mapping before there's
* a chance for anything to kick off a table walk for the new iova.
@@ -473,6 +508,13 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
return ret;
}
+static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
+ phys_addr_t paddr, size_t size, int iommu_prot, gfp_t gfp)
+{
+ return arm_lpae_map_pages(ops, iova, paddr, size, 1, iommu_prot, gfp,
+ NULL);
+}
+
static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
arm_lpae_iopte *ptep)
{
@@ -516,14 +558,15 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size,
arm_lpae_iopte blk_pte, int lvl,
- arm_lpae_iopte *ptep)
+ arm_lpae_iopte *ptep, size_t pgcount)
{
struct io_pgtable_cfg *cfg = &data->iop.cfg;
arm_lpae_iopte pte, *tablep;
phys_addr_t blk_paddr;
size_t tablesz = ARM_LPAE_GRANULE(data);
size_t split_sz = ARM_LPAE_BLOCK_SIZE(lvl, data);
- int i, unmap_idx = -1;
+ int ptes_per_table = ARM_LPAE_PTES_PER_TABLE(data);
+ int i, unmap_idx_start = -1, num_entries = 0, max_entries;
if (WARN_ON(lvl == ARM_LPAE_MAX_LEVELS))
return 0;
@@ -532,18 +575,21 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
if (!tablep)
return 0; /* Bytes unmapped */
- if (size == split_sz)
- unmap_idx = ARM_LPAE_LVL_IDX(iova, lvl, data);
+ if (size == split_sz) {
+ unmap_idx_start = ARM_LPAE_LVL_IDX(iova, lvl, data);
+ max_entries = ptes_per_table - unmap_idx_start;
+ num_entries = min_t(int, pgcount, max_entries);
+ }
blk_paddr = iopte_to_paddr(blk_pte, data);
pte = iopte_prot(blk_pte);
- for (i = 0; i < tablesz / sizeof(pte); i++, blk_paddr += split_sz) {
+ for (i = 0; i < ptes_per_table; i++, blk_paddr += split_sz) {
/* Unmap! */
- if (i == unmap_idx)
+ if (i >= unmap_idx_start && i < (unmap_idx_start + num_entries))
continue;
- __arm_lpae_init_pte(data, blk_paddr, pte, lvl, &tablep[i]);
+ __arm_lpae_init_pte(data, blk_paddr, pte, lvl, 1, &tablep[i]);
}
pte = arm_lpae_install_table(tablep, ptep, blk_pte, cfg);
@@ -558,76 +604,85 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
return 0;
tablep = iopte_deref(pte, data);
- } else if (unmap_idx >= 0) {
- io_pgtable_tlb_add_page(&data->iop, gather, iova, size);
- return size;
+ } else if (unmap_idx_start >= 0) {
+ for (i = 0; i < num_entries; i++)
+ io_pgtable_tlb_add_page(&data->iop, gather, iova + i * size, size);
+
+ return num_entries * size;
}
- return __arm_lpae_unmap(data, gather, iova, size, lvl, tablep);
+ return __arm_lpae_unmap(data, gather, iova, size, pgcount, lvl, tablep);
}
static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
struct iommu_iotlb_gather *gather,
- unsigned long iova, size_t size, int lvl,
- arm_lpae_iopte *ptep)
+ unsigned long iova, size_t size, size_t pgcount,
+ int lvl, arm_lpae_iopte *ptep)
{
arm_lpae_iopte pte;
struct io_pgtable *iop = &data->iop;
+ int i = 0, num_entries, max_entries, unmap_idx_start;
/* Something went horribly wrong and we ran out of page table */
if (WARN_ON(lvl == ARM_LPAE_MAX_LEVELS))
return 0;
- ptep += ARM_LPAE_LVL_IDX(iova, lvl, data);
+ unmap_idx_start = ARM_LPAE_LVL_IDX(iova, lvl, data);
+ ptep += unmap_idx_start;
pte = READ_ONCE(*ptep);
if (WARN_ON(!pte))
return 0;
/* If the size matches this level, we're in the right place */
if (size == ARM_LPAE_BLOCK_SIZE(lvl, data)) {
- __arm_lpae_set_pte(ptep, 0, &iop->cfg);
-
- if (!iopte_leaf(pte, lvl, iop->fmt)) {
- /* Also flush any partial walks */
- io_pgtable_tlb_flush_walk(iop, iova, size,
- ARM_LPAE_GRANULE(data));
- ptep = iopte_deref(pte, data);
- __arm_lpae_free_pgtable(data, lvl + 1, ptep);
- } else if (iop->cfg.quirks & IO_PGTABLE_QUIRK_NON_STRICT) {
- /*
- * Order the PTE update against queueing the IOVA, to
- * guarantee that a flush callback from a different CPU
- * has observed it before the TLBIALL can be issued.
- */
- smp_wmb();
- } else {
- io_pgtable_tlb_add_page(iop, gather, iova, size);
+ max_entries = ARM_LPAE_PTES_PER_TABLE(data) - unmap_idx_start;
+ num_entries = min_t(int, pgcount, max_entries);
+
+ while (i < num_entries) {
+ pte = READ_ONCE(*ptep);
+ if (WARN_ON(!pte))
+ break;
+
+ __arm_lpae_clear_pte(ptep, &iop->cfg);
+
+ if (!iopte_leaf(pte, lvl, iop->fmt)) {
+ /* Also flush any partial walks */
+ io_pgtable_tlb_flush_walk(iop, iova + i * size, size,
+ ARM_LPAE_GRANULE(data));
+ __arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
+ } else if (!iommu_iotlb_gather_queued(gather)) {
+ io_pgtable_tlb_add_page(iop, gather, iova + i * size, size);
+ }
+
+ ptep++;
+ i++;
}
- return size;
+ return i * size;
} else if (iopte_leaf(pte, lvl, iop->fmt)) {
/*
* Insert a table at the next level to map the old region,
* minus the part we want to unmap
*/
return arm_lpae_split_blk_unmap(data, gather, iova, size, pte,
- lvl + 1, ptep);
+ lvl + 1, ptep, pgcount);
}
/* Keep on walkin' */
ptep = iopte_deref(pte, data);
- return __arm_lpae_unmap(data, gather, iova, size, lvl + 1, ptep);
+ return __arm_lpae_unmap(data, gather, iova, size, pgcount, lvl + 1, ptep);
}
-static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
- size_t size, struct iommu_iotlb_gather *gather)
+static size_t arm_lpae_unmap_pages(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t pgsize, size_t pgcount,
+ struct iommu_iotlb_gather *gather)
{
struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
struct io_pgtable_cfg *cfg = &data->iop.cfg;
arm_lpae_iopte *ptep = data->pgd;
long iaext = (s64)iova >> cfg->ias;
- if (WARN_ON(!size || (size & cfg->pgsize_bitmap) != size))
+ if (WARN_ON(!pgsize || (pgsize & cfg->pgsize_bitmap) != pgsize || !pgcount))
return 0;
if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1)
@@ -635,7 +690,14 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
if (WARN_ON(iaext))
return 0;
- return __arm_lpae_unmap(data, gather, iova, size, data->start_level, ptep);
+ return __arm_lpae_unmap(data, gather, iova, pgsize, pgcount,
+ data->start_level, ptep);
+}
+
+static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t size, struct iommu_iotlb_gather *gather)
+{
+ return arm_lpae_unmap_pages(ops, iova, size, 1, gather);
}
static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
@@ -750,7 +812,9 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
data->iop.ops = (struct io_pgtable_ops) {
.map = arm_lpae_map,
+ .map_pages = arm_lpae_map_pages,
.unmap = arm_lpae_unmap,
+ .unmap_pages = arm_lpae_unmap_pages,
.iova_to_phys = arm_lpae_iova_to_phys,
};
@@ -766,7 +830,6 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
bool tg1;
if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
- IO_PGTABLE_QUIRK_NON_STRICT |
IO_PGTABLE_QUIRK_ARM_TTBR1 |
IO_PGTABLE_QUIRK_ARM_OUTER_WBWA))
return NULL;
@@ -870,7 +933,7 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
typeof(&cfg->arm_lpae_s2_cfg.vtcr) vtcr = &cfg->arm_lpae_s2_cfg.vtcr;
/* The NS quirk doesn't apply at stage 2 */
- if (cfg->quirks & ~(IO_PGTABLE_QUIRK_NON_STRICT))
+ if (cfg->quirks)
return NULL;
data = arm_lpae_alloc_pgtable(cfg);
@@ -1043,6 +1106,52 @@ out_free_data:
return NULL;
}
+static struct io_pgtable *
+apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
+{
+ struct arm_lpae_io_pgtable *data;
+ int i;
+
+ if (cfg->oas > 36)
+ return NULL;
+
+ data = arm_lpae_alloc_pgtable(cfg);
+ if (!data)
+ return NULL;
+
+ /*
+ * The table format itself always uses two levels, but the total VA
+ * space is mapped by four separate tables, making the MMIO registers
+ * an effective "level 1". For simplicity, though, we treat this
+ * equivalently to LPAE stage 2 concatenation at level 2, with the
+ * additional TTBRs each just pointing at consecutive pages.
+ */
+ if (data->start_level < 1)
+ goto out_free_data;
+ if (data->start_level == 1 && data->pgd_bits > 2)
+ goto out_free_data;
+ if (data->start_level > 1)
+ data->pgd_bits = 0;
+ data->start_level = 2;
+ cfg->apple_dart_cfg.n_ttbrs = 1 << data->pgd_bits;
+ data->pgd_bits += data->bits_per_level;
+
+ data->pgd = __arm_lpae_alloc_pages(ARM_LPAE_PGD_SIZE(data), GFP_KERNEL,
+ cfg);
+ if (!data->pgd)
+ goto out_free_data;
+
+ for (i = 0; i < cfg->apple_dart_cfg.n_ttbrs; ++i)
+ cfg->apple_dart_cfg.ttbr[i] =
+ virt_to_phys(data->pgd + i * ARM_LPAE_GRANULE(data));
+
+ return &data->iop;
+
+out_free_data:
+ kfree(data);
+ return NULL;
+}
+
struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = {
.alloc = arm_64_lpae_alloc_pgtable_s1,
.free = arm_lpae_free_pgtable,
@@ -1068,6 +1177,11 @@ struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = {
.free = arm_lpae_free_pgtable,
};
+struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns = {
+ .alloc = apple_dart_alloc_pgtable,
+ .free = arm_lpae_free_pgtable,
+};
+
#ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST
static struct io_pgtable_cfg *cfg_cookie __initdata;
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
index 6e9917ce980f..f4bfcef98297 100644
--- a/drivers/iommu/io-pgtable.c
+++ b/drivers/iommu/io-pgtable.c
@@ -20,6 +20,7 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
[ARM_64_LPAE_S1] = &io_pgtable_arm_64_lpae_s1_init_fns,
[ARM_64_LPAE_S2] = &io_pgtable_arm_64_lpae_s2_init_fns,
[ARM_MALI_LPAE] = &io_pgtable_arm_mali_lpae_init_fns,
+ [APPLE_DART] = &io_pgtable_apple_dart_init_fns,
#endif
#ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S
[ARM_V7S] = &io_pgtable_arm_v7s_init_fns,
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 63f0af10c403..3303d707bab4 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -7,7 +7,9 @@
#define pr_fmt(fmt) "iommu: " fmt
#include <linux/device.h>
+#include <linux/dma-iommu.h>
#include <linux/kernel.h>
+#include <linux/bits.h>
#include <linux/bug.h>
#include <linux/types.h>
#include <linux/init.h>
@@ -29,7 +31,7 @@ static struct kset *iommu_group_kset;
static DEFINE_IDA(iommu_group_ida);
static unsigned int iommu_def_domain_type __read_mostly;
-static bool iommu_dma_strict __read_mostly = true;
+static bool iommu_dma_strict __read_mostly = IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_STRICT);
static u32 iommu_cmd_line __read_mostly;
struct iommu_group {
@@ -113,6 +115,7 @@ static const char *iommu_domain_type_str(unsigned int t)
case IOMMU_DOMAIN_UNMANAGED:
return "Unmanaged";
case IOMMU_DOMAIN_DMA:
+ case IOMMU_DOMAIN_DMA_FQ:
return "Translated";
default:
return "Unknown";
@@ -133,11 +136,20 @@ static int __init iommu_subsys_init(void)
}
}
+ if (!iommu_default_passthrough() && !iommu_dma_strict)
+ iommu_def_domain_type = IOMMU_DOMAIN_DMA_FQ;
+
pr_info("Default domain type: %s %s\n",
iommu_domain_type_str(iommu_def_domain_type),
(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API) ?
"(set via kernel command line)" : "");
+ if (!iommu_default_passthrough())
+ pr_info("DMA domain TLB invalidation policy: %s mode %s\n",
+ iommu_dma_strict ? "strict" : "lazy",
+ (iommu_cmd_line & IOMMU_CMD_LINE_STRICT) ?
+ "(set via kernel command line)" : "");
+
return 0;
}
subsys_initcall(iommu_subsys_init);
@@ -273,7 +285,9 @@ int iommu_probe_device(struct device *dev)
* support default domains, so the return value is not yet
* checked.
*/
+ mutex_lock(&group->mutex);
iommu_alloc_default_domain(group, dev);
+ mutex_unlock(&group->mutex);
if (group->default_domain) {
ret = __iommu_attach_device(group->default_domain, dev);
@@ -344,20 +358,12 @@ static int __init iommu_dma_setup(char *str)
}
early_param("iommu.strict", iommu_dma_setup);
-void iommu_set_dma_strict(bool strict)
-{
- if (strict || !(iommu_cmd_line & IOMMU_CMD_LINE_STRICT))
- iommu_dma_strict = strict;
-}
-
-bool iommu_get_dma_strict(struct iommu_domain *domain)
+void iommu_set_dma_strict(void)
{
- /* only allow lazy flushing for DMA domains */
- if (domain->type == IOMMU_DOMAIN_DMA)
- return iommu_dma_strict;
- return true;
+ iommu_dma_strict = true;
+ if (iommu_def_domain_type == IOMMU_DOMAIN_DMA_FQ)
+ iommu_def_domain_type = IOMMU_DOMAIN_DMA;
}
-EXPORT_SYMBOL_GPL(iommu_get_dma_strict);
static ssize_t iommu_group_attr_show(struct kobject *kobj,
struct attribute *__attr, char *buf)
@@ -546,6 +552,9 @@ static ssize_t iommu_group_show_type(struct iommu_group *group,
case IOMMU_DOMAIN_DMA:
type = "DMA\n";
break;
+ case IOMMU_DOMAIN_DMA_FQ:
+ type = "DMA-FQ\n";
+ break;
}
}
mutex_unlock(&group->mutex);
@@ -759,7 +768,7 @@ static int iommu_create_device_direct_mappings(struct iommu_group *group,
unsigned long pg_size;
int ret = 0;
- if (!domain || domain->type != IOMMU_DOMAIN_DMA)
+ if (!domain || !iommu_is_dma_domain(domain))
return 0;
BUG_ON(!domain->pgsize_bitmap);
@@ -1944,6 +1953,11 @@ static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
/* Assume all sizes by default; the driver may override this later */
domain->pgsize_bitmap = bus->iommu_ops->pgsize_bitmap;
+ /* Temporarily avoid -EEXIST while drivers still get their own cookies */
+ if (iommu_is_dma_domain(domain) && !domain->iova_cookie && iommu_get_dma_cookie(domain)) {
+ iommu_domain_free(domain);
+ domain = NULL;
+ }
return domain;
}
@@ -1955,6 +1969,7 @@ EXPORT_SYMBOL_GPL(iommu_domain_alloc);
void iommu_domain_free(struct iommu_domain *domain)
{
+ iommu_put_dma_cookie(domain);
domain->ops->domain_free(domain);
}
EXPORT_SYMBOL_GPL(iommu_domain_free);
@@ -2370,45 +2385,94 @@ EXPORT_SYMBOL_GPL(iommu_detach_group);
phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
{
- if (unlikely(domain->ops->iova_to_phys == NULL))
+ if (domain->type == IOMMU_DOMAIN_IDENTITY)
+ return iova;
+
+ if (domain->type == IOMMU_DOMAIN_BLOCKED)
return 0;
return domain->ops->iova_to_phys(domain, iova);
}
EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
-static size_t iommu_pgsize(struct iommu_domain *domain,
- unsigned long addr_merge, size_t size)
+static size_t iommu_pgsize(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t size, size_t *count)
{
- unsigned int pgsize_idx;
- size_t pgsize;
+ unsigned int pgsize_idx, pgsize_idx_next;
+ unsigned long pgsizes;
+ size_t offset, pgsize, pgsize_next;
+ unsigned long addr_merge = paddr | iova;
- /* Max page size that still fits into 'size' */
- pgsize_idx = __fls(size);
+ /* Page sizes supported by the hardware and small enough for @size */
+ pgsizes = domain->pgsize_bitmap & GENMASK(__fls(size), 0);
- /* need to consider alignment requirements ? */
- if (likely(addr_merge)) {
- /* Max page size allowed by address */
- unsigned int align_pgsize_idx = __ffs(addr_merge);
- pgsize_idx = min(pgsize_idx, align_pgsize_idx);
- }
+ /* Constrain the page sizes further based on the maximum alignment */
+ if (likely(addr_merge))
+ pgsizes &= GENMASK(__ffs(addr_merge), 0);
- /* build a mask of acceptable page sizes */
- pgsize = (1UL << (pgsize_idx + 1)) - 1;
+ /* Make sure we have at least one suitable page size */
+ BUG_ON(!pgsizes);
- /* throw away page sizes not supported by the hardware */
- pgsize &= domain->pgsize_bitmap;
+ /* Pick the biggest page size remaining */
+ pgsize_idx = __fls(pgsizes);
+ pgsize = BIT(pgsize_idx);
+ if (!count)
+ return pgsize;
- /* make sure we're still sane */
- BUG_ON(!pgsize);
+ /* Find the next biggest support page size, if it exists */
+ pgsizes = domain->pgsize_bitmap & ~GENMASK(pgsize_idx, 0);
+ if (!pgsizes)
+ goto out_set_count;
- /* pick the biggest page */
- pgsize_idx = __fls(pgsize);
- pgsize = 1UL << pgsize_idx;
+ pgsize_idx_next = __ffs(pgsizes);
+ pgsize_next = BIT(pgsize_idx_next);
+ /*
+ * There's no point trying a bigger page size unless the virtual
+ * and physical addresses are similarly offset within the larger page.
+ */
+ if ((iova ^ paddr) & (pgsize_next - 1))
+ goto out_set_count;
+
+ /* Calculate the offset to the next page size alignment boundary */
+ offset = pgsize_next - (addr_merge & (pgsize_next - 1));
+
+ /*
+ * If size is big enough to accommodate the larger page, reduce
+ * the number of smaller pages.
+ */
+ if (offset + pgsize_next <= size)
+ size = offset;
+
+out_set_count:
+ *count = size >> pgsize_idx;
return pgsize;
}
+static int __iommu_map_pages(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t size, int prot,
+ gfp_t gfp, size_t *mapped)
+{
+ const struct iommu_ops *ops = domain->ops;
+ size_t pgsize, count;
+ int ret;
+
+ pgsize = iommu_pgsize(domain, iova, paddr, size, &count);
+
+ pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx count %zu\n",
+ iova, &paddr, pgsize, count);
+
+ if (ops->map_pages) {
+ ret = ops->map_pages(domain, iova, paddr, pgsize, count, prot,
+ gfp, mapped);
+ } else {
+ ret = ops->map(domain, iova, paddr, pgsize, prot, gfp);
+ *mapped = ret ? 0 : pgsize;
+ }
+
+ return ret;
+}
+
static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
{
@@ -2419,7 +2483,7 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t orig_paddr = paddr;
int ret = 0;
- if (unlikely(ops->map == NULL ||
+ if (unlikely(!(ops->map || ops->map_pages) ||
domain->pgsize_bitmap == 0UL))
return -ENODEV;
@@ -2443,18 +2507,21 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
pr_debug("map: iova 0x%lx pa %pa size 0x%zx\n", iova, &paddr, size);
while (size) {
- size_t pgsize = iommu_pgsize(domain, iova | paddr, size);
+ size_t mapped = 0;
- pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n",
- iova, &paddr, pgsize);
- ret = ops->map(domain, iova, paddr, pgsize, prot, gfp);
+ ret = __iommu_map_pages(domain, iova, paddr, size, prot, gfp,
+ &mapped);
+ /*
+ * Some pages may have been mapped, even if an error occurred,
+ * so we should account for those so they can be unmapped.
+ */
+ size -= mapped;
if (ret)
break;
- iova += pgsize;
- paddr += pgsize;
- size -= pgsize;
+ iova += mapped;
+ paddr += mapped;
}
/* unroll mapping in case something went wrong */
@@ -2494,6 +2561,19 @@ int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova,
}
EXPORT_SYMBOL_GPL(iommu_map_atomic);
+static size_t __iommu_unmap_pages(struct iommu_domain *domain,
+ unsigned long iova, size_t size,
+ struct iommu_iotlb_gather *iotlb_gather)
+{
+ const struct iommu_ops *ops = domain->ops;
+ size_t pgsize, count;
+
+ pgsize = iommu_pgsize(domain, iova, iova, size, &count);
+ return ops->unmap_pages ?
+ ops->unmap_pages(domain, iova, pgsize, count, iotlb_gather) :
+ ops->unmap(domain, iova, pgsize, iotlb_gather);
+}
+
static size_t __iommu_unmap(struct iommu_domain *domain,
unsigned long iova, size_t size,
struct iommu_iotlb_gather *iotlb_gather)
@@ -2503,7 +2583,7 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
unsigned long orig_iova = iova;
unsigned int min_pagesz;
- if (unlikely(ops->unmap == NULL ||
+ if (unlikely(!(ops->unmap || ops->unmap_pages) ||
domain->pgsize_bitmap == 0UL))
return 0;
@@ -2531,9 +2611,9 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
* or we hit an area that isn't mapped.
*/
while (unmapped < size) {
- size_t pgsize = iommu_pgsize(domain, iova, size - unmapped);
-
- unmapped_page = ops->unmap(domain, iova, pgsize, iotlb_gather);
+ unmapped_page = __iommu_unmap_pages(domain, iova,
+ size - unmapped,
+ iotlb_gather);
if (!unmapped_page)
break;
@@ -2570,9 +2650,9 @@ size_t iommu_unmap_fast(struct iommu_domain *domain,
}
EXPORT_SYMBOL_GPL(iommu_unmap_fast);
-static size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
- struct scatterlist *sg, unsigned int nents, int prot,
- gfp_t gfp)
+static ssize_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+ struct scatterlist *sg, unsigned int nents, int prot,
+ gfp_t gfp)
{
const struct iommu_ops *ops = domain->ops;
size_t len = 0, mapped = 0;
@@ -2613,19 +2693,18 @@ out_err:
/* undo mappings already done */
iommu_unmap(domain, iova, mapped);
- return 0;
-
+ return ret;
}
-size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
- struct scatterlist *sg, unsigned int nents, int prot)
+ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+ struct scatterlist *sg, unsigned int nents, int prot)
{
might_sleep();
return __iommu_map_sg(domain, iova, sg, nents, prot, GFP_KERNEL);
}
EXPORT_SYMBOL_GPL(iommu_map_sg);
-size_t iommu_map_sg_atomic(struct iommu_domain *domain, unsigned long iova,
+ssize_t iommu_map_sg_atomic(struct iommu_domain *domain, unsigned long iova,
struct scatterlist *sg, unsigned int nents, int prot)
{
return __iommu_map_sg(domain, iova, sg, nents, prot, GFP_ATOMIC);
@@ -3129,6 +3208,14 @@ static int iommu_change_dev_def_domain(struct iommu_group *group,
goto out;
}
+ /* We can bring up a flush queue without tearing down the domain */
+ if (type == IOMMU_DOMAIN_DMA_FQ && prev_dom->type == IOMMU_DOMAIN_DMA) {
+ ret = iommu_dma_init_fq(prev_dom);
+ if (!ret)
+ prev_dom->type = IOMMU_DOMAIN_DMA_FQ;
+ goto out;
+ }
+
/* Sets group->default_domain to the newly allocated domain */
ret = iommu_group_alloc_default_domain(dev->bus, group, type);
if (ret)
@@ -3169,9 +3256,9 @@ out:
}
/*
- * Changing the default domain through sysfs requires the users to ubind the
- * drivers from the devices in the iommu group. Return failure if this doesn't
- * meet.
+ * Changing the default domain through sysfs requires the users to unbind the
+ * drivers from the devices in the iommu group, except for a DMA -> DMA-FQ
+ * transition. Return failure if this isn't met.
*
* We need to consider the race between this and the device release path.
* device_lock(dev) is used here to guarantee that the device release path
@@ -3194,6 +3281,8 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
req_type = IOMMU_DOMAIN_IDENTITY;
else if (sysfs_streq(buf, "DMA"))
req_type = IOMMU_DOMAIN_DMA;
+ else if (sysfs_streq(buf, "DMA-FQ"))
+ req_type = IOMMU_DOMAIN_DMA_FQ;
else if (sysfs_streq(buf, "auto"))
req_type = 0;
else
@@ -3245,7 +3334,8 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
/* Check if the device in the group still has a driver bound to it */
device_lock(dev);
- if (device_is_bound(dev)) {
+ if (device_is_bound(dev) && !(req_type == IOMMU_DOMAIN_DMA_FQ &&
+ group->default_domain->type == IOMMU_DOMAIN_DMA)) {
pr_err_ratelimited("Device is still bound to driver\n");
ret = -EBUSY;
goto out;
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index b6cf5f16123b..0af42fb93a49 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -121,8 +121,6 @@ int init_iova_flush_queue(struct iova_domain *iovad,
spin_lock_init(&fq->lock);
}
- smp_wmb();
-
iovad->fq = queue;
timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
@@ -633,10 +631,20 @@ void queue_iova(struct iova_domain *iovad,
unsigned long pfn, unsigned long pages,
unsigned long data)
{
- struct iova_fq *fq = raw_cpu_ptr(iovad->fq);
+ struct iova_fq *fq;
unsigned long flags;
unsigned idx;
+ /*
+ * Order against the IOMMU driver's pagetable update from unmapping
+ * @pte, to guarantee that iova_domain_flush() observes that if called
+ * from a different CPU before we release the lock below. Full barrier
+ * so it also pairs with iommu_dma_init_fq() to avoid seeing partially
+ * written fq state here.
+ */
+ smp_mb();
+
+ fq = raw_cpu_ptr(iovad->fq);
spin_lock_irqsave(&fq->lock, flags);
/*
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 51ea6f00db2f..d38ff29a76e8 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -8,7 +8,6 @@
#include <linux/bitmap.h>
#include <linux/delay.h>
-#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/export.h>
@@ -564,10 +563,13 @@ static irqreturn_t ipmmu_irq(int irq, void *dev)
* IOMMU Operations
*/
-static struct iommu_domain *__ipmmu_domain_alloc(unsigned type)
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
{
struct ipmmu_vmsa_domain *domain;
+ if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
+ return NULL;
+
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
@@ -577,27 +579,6 @@ static struct iommu_domain *__ipmmu_domain_alloc(unsigned type)
return &domain->io_domain;
}
-static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
-{
- struct iommu_domain *io_domain = NULL;
-
- switch (type) {
- case IOMMU_DOMAIN_UNMANAGED:
- io_domain = __ipmmu_domain_alloc(type);
- break;
-
- case IOMMU_DOMAIN_DMA:
- io_domain = __ipmmu_domain_alloc(type);
- if (io_domain && iommu_get_dma_cookie(io_domain)) {
- kfree(io_domain);
- io_domain = NULL;
- }
- break;
- }
-
- return io_domain;
-}
-
static void ipmmu_domain_free(struct iommu_domain *io_domain)
{
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
@@ -606,7 +587,6 @@ static void ipmmu_domain_free(struct iommu_domain *io_domain)
* Free the domain resources. We assume that all devices have already
* been detached.
*/
- iommu_put_dma_cookie(io_domain);
ipmmu_domain_destroy_context(domain);
free_io_pgtable_ops(domain->iop);
kfree(domain);
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 6f7c69688ce2..d837adfd1da5 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -9,7 +9,6 @@
#include <linux/component.h>
#include <linux/device.h>
#include <linux/dma-direct.h>
-#include <linux/dma-iommu.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -441,17 +440,11 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
if (!dom)
return NULL;
- if (iommu_get_dma_cookie(&dom->domain)) {
- kfree(dom);
- return NULL;
- }
-
return &dom->domain;
}
static void mtk_iommu_domain_free(struct iommu_domain *domain)
{
- iommu_put_dma_cookie(domain);
kfree(to_mtk_domain(domain));
}
@@ -520,12 +513,8 @@ static size_t mtk_iommu_unmap(struct iommu_domain *domain,
struct iommu_iotlb_gather *gather)
{
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
- unsigned long end = iova + size - 1;
- if (gather->start > iova)
- gather->start = iova;
- if (gather->end < end)
- gather->end = end;
+ iommu_iotlb_gather_add_range(gather, iova, size);
return dom->iop->unmap(dom->iop, iova, size, gather);
}
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 778e66f5f1aa..be22fcf988ce 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -13,7 +13,6 @@
#include <linux/component.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
-#include <linux/dma-iommu.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 9febfb7f3025..5cb260820eda 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -10,7 +10,6 @@
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
@@ -1074,10 +1073,6 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
if (!rk_domain)
return NULL;
- if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&rk_domain->domain))
- goto err_free_domain;
-
/*
* rk32xx iommus use a 2 level pagetable.
* Each level1 (dt) and level2 (pt) table has 1024 4-byte entries.
@@ -1085,7 +1080,7 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
*/
rk_domain->dt = (u32 *)get_zeroed_page(GFP_KERNEL | GFP_DMA32);
if (!rk_domain->dt)
- goto err_put_cookie;
+ goto err_free_domain;
rk_domain->dt_dma = dma_map_single(dma_dev, rk_domain->dt,
SPAGE_SIZE, DMA_TO_DEVICE);
@@ -1106,9 +1101,6 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
err_free_dt:
free_page((unsigned long)rk_domain->dt);
-err_put_cookie:
- if (type == IOMMU_DOMAIN_DMA)
- iommu_put_dma_cookie(&rk_domain->domain);
err_free_domain:
kfree(rk_domain);
@@ -1137,8 +1129,6 @@ static void rk_iommu_domain_free(struct iommu_domain *domain)
SPAGE_SIZE, DMA_TO_DEVICE);
free_page((unsigned long)rk_domain->dt);
- if (domain->type == IOMMU_DOMAIN_DMA)
- iommu_put_dma_cookie(&rk_domain->domain);
kfree(rk_domain);
}
diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
index 73dfd9946312..27ac818b0354 100644
--- a/drivers/iommu/sprd-iommu.c
+++ b/drivers/iommu/sprd-iommu.c
@@ -8,7 +8,6 @@
#include <linux/clk.h>
#include <linux/device.h>
-#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/iommu.h>
@@ -144,11 +143,6 @@ static struct iommu_domain *sprd_iommu_domain_alloc(unsigned int domain_type)
if (!dom)
return NULL;
- if (iommu_get_dma_cookie(&dom->domain)) {
- kfree(dom);
- return NULL;
- }
-
spin_lock_init(&dom->pgtlock);
dom->domain.geometry.aperture_start = 0;
@@ -161,7 +155,6 @@ static void sprd_iommu_domain_free(struct iommu_domain *domain)
{
struct sprd_iommu_domain *dom = to_sprd_domain(domain);
- iommu_put_dma_cookie(domain);
kfree(dom);
}
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index 181bb1c3437c..92997021e188 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -7,7 +7,6 @@
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dma-direction.h>
-#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/errno.h>
@@ -610,14 +609,10 @@ static struct iommu_domain *sun50i_iommu_domain_alloc(unsigned type)
if (!sun50i_domain)
return NULL;
- if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&sun50i_domain->domain))
- goto err_free_domain;
-
sun50i_domain->dt = (u32 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
get_order(DT_SIZE));
if (!sun50i_domain->dt)
- goto err_put_cookie;
+ goto err_free_domain;
refcount_set(&sun50i_domain->refcnt, 1);
@@ -627,10 +622,6 @@ static struct iommu_domain *sun50i_iommu_domain_alloc(unsigned type)
return &sun50i_domain->domain;
-err_put_cookie:
- if (type == IOMMU_DOMAIN_DMA)
- iommu_put_dma_cookie(&sun50i_domain->domain);
-
err_free_domain:
kfree(sun50i_domain);
@@ -644,8 +635,6 @@ static void sun50i_iommu_domain_free(struct iommu_domain *domain)
free_pages((unsigned long)sun50i_domain->dt, get_order(DT_SIZE));
sun50i_domain->dt = NULL;
- iommu_put_dma_cookie(domain);
-
kfree(sun50i_domain);
}
diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 6abdcab7273b..80930ce04a16 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -598,12 +598,6 @@ static struct iommu_domain *viommu_domain_alloc(unsigned type)
spin_lock_init(&vdomain->mappings_lock);
vdomain->mappings = RB_ROOT_CACHED;
- if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&vdomain->domain)) {
- kfree(vdomain);
- return NULL;
- }
-
return &vdomain->domain;
}
@@ -643,8 +637,6 @@ static void viommu_domain_free(struct iommu_domain *domain)
{
struct viommu_domain *vdomain = to_viommu_domain(domain);
- iommu_put_dma_cookie(domain);
-
/* Free all remaining mappings (size 2^64) */
viommu_del_mappings(vdomain, 0, 0);
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c
index 20fa02c81070..c14e65a5d38f 100644
--- a/drivers/ipack/devices/ipoctal.c
+++ b/drivers/ipack/devices/ipoctal.c
@@ -347,10 +347,10 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
/* Register the TTY device */
/* Each IP-OCTAL channel is a TTY port */
- tty = alloc_tty_driver(NR_CHANNELS);
-
- if (!tty)
- return -ENOMEM;
+ tty = tty_alloc_driver(NR_CHANNELS, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(tty))
+ return PTR_ERR(tty);
/* Fill struct tty_driver with ipoctal data */
tty->owner = THIS_MODULE;
@@ -362,7 +362,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
tty->minor_start = 0;
tty->type = TTY_DRIVER_TYPE_SERIAL;
tty->subtype = SERIAL_TYPE_NORMAL;
- tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty->init_termios = tty_std_termios;
tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
tty->init_termios.c_ispeed = 9600;
@@ -372,7 +371,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
res = tty_register_driver(tty);
if (res) {
dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
- put_tty_driver(tty);
+ tty_driver_kref_put(tty);
return res;
}
@@ -697,7 +696,7 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
}
tty_unregister_driver(ipoctal->tty_drv);
- put_tty_driver(ipoctal->tty_drv);
+ tty_driver_kref_put(ipoctal->tty_drv);
kfree(ipoctal);
}
diff --git a/drivers/ipack/ipack.c b/drivers/ipack/ipack.c
index 7de9605cac4f..b1c3198355e7 100644
--- a/drivers/ipack/ipack.c
+++ b/drivers/ipack/ipack.c
@@ -67,15 +67,13 @@ static int ipack_bus_probe(struct device *device)
return drv->ops->probe(dev);
}
-static int ipack_bus_remove(struct device *device)
+static void ipack_bus_remove(struct device *device)
{
struct ipack_device *dev = to_ipack_dev(device);
struct ipack_driver *drv = to_ipack_driver(device->driver);
if (drv->ops->remove)
drv->ops->remove(dev);
-
- return 0;
}
static int ipack_uevent(struct device *dev, struct kobj_uevent_env *env)
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index d5f9261fa879..0f00be62438d 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1269,10 +1269,11 @@ static int __init capinc_tty_init(void)
if (!capiminors)
return -ENOMEM;
- drv = alloc_tty_driver(capi_ttyminors);
- if (!drv) {
+ drv = tty_alloc_driver(capi_ttyminors, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(drv)) {
kfree(capiminors);
- return -ENOMEM;
+ return PTR_ERR(drv);
}
drv->driver_name = "capi_nc";
drv->name = "capi!";
@@ -1285,14 +1286,11 @@ static int __init capinc_tty_init(void)
drv->init_termios.c_oflag = OPOST | ONLCR;
drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
drv->init_termios.c_lflag = 0;
- drv->flags =
- TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS |
- TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(drv, &capinc_ops);
err = tty_register_driver(drv);
if (err) {
- put_tty_driver(drv);
+ tty_driver_kref_put(drv);
kfree(capiminors);
printk(KERN_ERR "Couldn't register capi_nc driver\n");
return err;
@@ -1304,7 +1302,7 @@ static int __init capinc_tty_init(void)
static void __exit capinc_tty_exit(void)
{
tty_unregister_driver(capinc_tty_driver);
- put_tty_driver(capinc_tty_driver);
+ tty_driver_kref_put(capinc_tty_driver);
kfree(capiminors);
}
diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c
index f26bf3c66d7e..d7ae42edc4a8 100644
--- a/drivers/isdn/capi/capiutil.c
+++ b/drivers/isdn/capi/capiutil.c
@@ -379,7 +379,7 @@ static char *pnames[] =
/*2f */ "Useruserdata"
};
-#include <stdarg.h>
+#include <linux/stdarg.h>
/*-------------------------------------------------------*/
static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt, ...)
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index d4759db002c6..dc634c2932fd 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -2,7 +2,6 @@
/*
* Driver for the ADB controller in the Mac I/O (Hydra) chip.
*/
-#include <stdarg.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 49af60bdac92..c1fdf2896021 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -88,7 +88,7 @@ static int macio_device_probe(struct device *dev)
return error;
}
-static int macio_device_remove(struct device *dev)
+static void macio_device_remove(struct device *dev)
{
struct macio_dev * macio_dev = to_macio_device(dev);
struct macio_driver * drv = to_macio_driver(dev->driver);
@@ -96,8 +96,6 @@ static int macio_device_remove(struct device *dev)
if (dev->driver && drv->remove)
drv->remove(macio_dev);
macio_dev_put(macio_dev);
-
- return 0;
}
static void macio_device_shutdown(struct device *dev)
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 3581abfb0c6a..cd267392289c 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -9,7 +9,7 @@
*
* Copyright (C) 1996 Paul Mackerras.
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 060e03f2264b..db9270da5b8e 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -23,8 +23,6 @@
* Apple's "ADB Analyzer" bus sniffer is invaluable:
* ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/
*/
-
-#include <stdarg.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 4bdd4c45e7a7..4b98bc26a94b 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -18,7 +18,7 @@
* a sleep or a freq. switch
*
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/errno.h>
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index b4b780ea2ac8..c9fc06c7e685 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -264,7 +264,7 @@ config SPRD_MBOX
you want to build the Spreatrum mailbox controller driver.
config QCOM_IPCC
- bool "Qualcomm Technologies, Inc. IPCC driver"
+ tristate "Qualcomm Technologies, Inc. IPCC driver"
depends on ARCH_QCOM || COMPILE_TEST
help
Qualcomm Technologies, Inc. Inter-Processor Communication Controller
diff --git a/drivers/mailbox/mailbox-sti.c b/drivers/mailbox/mailbox-sti.c
index 2baf69a0b81c..ab3a6ab762d3 100644
--- a/drivers/mailbox/mailbox-sti.c
+++ b/drivers/mailbox/mailbox-sti.c
@@ -36,12 +36,7 @@
#define MBOX_BASE(mdev, inst) ((mdev)->base + ((inst) * 4))
/**
- * STi Mailbox device data
- *
- * An IP Mailbox is currently composed of 4 instances
- * Each instance is currently composed of 32 channels
- * This means that we have 128 channels per Mailbox
- * A channel an be used for TX or RX
+ * struct sti_mbox_device - STi Mailbox device data
*
* @dev: Device to which it is attached
* @mbox: Representation of a communication channel controller
@@ -49,6 +44,11 @@
* @name: Name of the mailbox
* @enabled: Local copy of enabled channels
* @lock: Mutex protecting enabled status
+ *
+ * An IP Mailbox is currently composed of 4 instances
+ * Each instance is currently composed of 32 channels
+ * This means that we have 128 channels per Mailbox
+ * A channel an be used for TX or RX
*/
struct sti_mbox_device {
struct device *dev;
@@ -60,7 +60,7 @@ struct sti_mbox_device {
};
/**
- * STi Mailbox platform specific configuration
+ * struct sti_mbox_pdata - STi Mailbox platform specific configuration
*
* @num_inst: Maximum number of instances in one HW Mailbox
* @num_chan: Maximum number of channel per instance
@@ -71,7 +71,7 @@ struct sti_mbox_pdata {
};
/**
- * STi Mailbox allocated channel information
+ * struct sti_channel - STi Mailbox allocated channel information
*
* @mdev: Pointer to parent Mailbox device
* @instance: Instance number channel resides in
diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index 67a42b514429..64175a893312 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -19,6 +19,7 @@
#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)
#define CMDQ_NUM_CMD(t) (t->cmd_buf_size / CMDQ_INST_SIZE)
+#define CMDQ_GCE_NUM_MAX (2)
#define CMDQ_CURR_IRQ_STATUS 0x10
#define CMDQ_SYNC_TOKEN_UPDATE 0x68
@@ -36,6 +37,8 @@
#define CMDQ_THR_WAIT_TOKEN 0x30
#define CMDQ_THR_PRIORITY 0x40
+#define GCE_GCTL_VALUE 0x48
+
#define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200
#define CMDQ_THR_ENABLED 0x1
#define CMDQ_THR_DISABLED 0x0
@@ -73,14 +76,18 @@ struct cmdq {
u32 thread_nr;
u32 irq_mask;
struct cmdq_thread *thread;
- struct clk *clock;
+ struct clk_bulk_data clocks[CMDQ_GCE_NUM_MAX];
bool suspended;
u8 shift_pa;
+ bool control_by_sw;
+ u32 gce_num;
};
struct gce_plat {
u32 thread_nr;
u8 shift;
+ bool control_by_sw;
+ u32 gce_num;
};
u8 cmdq_get_shift_pa(struct mbox_chan *chan)
@@ -120,11 +127,13 @@ static void cmdq_init(struct cmdq *cmdq)
{
int i;
- WARN_ON(clk_enable(cmdq->clock) < 0);
+ WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
+ if (cmdq->control_by_sw)
+ writel(0x7, cmdq->base + GCE_GCTL_VALUE);
writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
for (i = 0; i <= CMDQ_MAX_EVENT; i++)
writel(i, cmdq->base + CMDQ_SYNC_TOKEN_UPDATE);
- clk_disable(cmdq->clock);
+ clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
}
static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
@@ -168,7 +177,8 @@ static void cmdq_task_insert_into_thread(struct cmdq_task *task)
dma_sync_single_for_cpu(dev, prev_task->pa_base,
prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] =
- (u64)CMDQ_JUMP_BY_PA << 32 | task->pa_base;
+ (u64)CMDQ_JUMP_BY_PA << 32 |
+ (task->pa_base >> task->cmdq->shift_pa);
dma_sync_single_for_device(dev, prev_task->pa_base,
prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
@@ -262,7 +272,7 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
if (list_empty(&thread->task_busy_list)) {
cmdq_thread_disable(cmdq, thread);
- clk_disable(cmdq->clock);
+ clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
}
}
@@ -307,7 +317,7 @@ static int cmdq_suspend(struct device *dev)
if (task_running)
dev_warn(dev, "exist running task(s) in suspend\n");
- clk_unprepare(cmdq->clock);
+ clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
return 0;
}
@@ -316,7 +326,7 @@ static int cmdq_resume(struct device *dev)
{
struct cmdq *cmdq = dev_get_drvdata(dev);
- WARN_ON(clk_prepare(cmdq->clock) < 0);
+ WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
cmdq->suspended = false;
return 0;
}
@@ -325,8 +335,7 @@ static int cmdq_remove(struct platform_device *pdev)
{
struct cmdq *cmdq = platform_get_drvdata(pdev);
- clk_unprepare(cmdq->clock);
-
+ clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
return 0;
}
@@ -352,7 +361,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
task->pkt = pkt;
if (list_empty(&thread->task_busy_list)) {
- WARN_ON(clk_enable(cmdq->clock) < 0);
+ WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
+
/*
* The thread reset will clear thread related register to 0,
* including pc, end, priority, irq, suspend and enable. Thus
@@ -424,7 +434,8 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
}
cmdq_thread_disable(cmdq, thread);
- clk_disable(cmdq->clock);
+ clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
+
done:
/*
* The thread->task_busy_list empty means thread already disable. The
@@ -469,7 +480,7 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
cmdq_thread_resume(thread);
cmdq_thread_disable(cmdq, thread);
- clk_disable(cmdq->clock);
+ clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
out:
spin_unlock_irqrestore(&thread->chan->lock, flags);
@@ -518,6 +529,10 @@ static int cmdq_probe(struct platform_device *pdev)
struct cmdq *cmdq;
int err, i;
struct gce_plat *plat_data;
+ struct device_node *phandle = dev->of_node;
+ struct device_node *node;
+ int alias_id = 0;
+ char clk_name[4] = "gce";
cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
if (!cmdq)
@@ -540,6 +555,8 @@ static int cmdq_probe(struct platform_device *pdev)
cmdq->thread_nr = plat_data->thread_nr;
cmdq->shift_pa = plat_data->shift;
+ cmdq->control_by_sw = plat_data->control_by_sw;
+ cmdq->gce_num = plat_data->gce_num;
cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
"mtk_cmdq", cmdq);
@@ -551,10 +568,28 @@ static int cmdq_probe(struct platform_device *pdev)
dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
dev, cmdq->base, cmdq->irq);
- cmdq->clock = devm_clk_get(dev, "gce");
- if (IS_ERR(cmdq->clock)) {
- dev_err(dev, "failed to get gce clk\n");
- return PTR_ERR(cmdq->clock);
+ if (cmdq->gce_num > 1) {
+ for_each_child_of_node(phandle->parent, node) {
+ char clk_id[8];
+
+ alias_id = of_alias_get_id(node, clk_name);
+ if (alias_id < cmdq->gce_num) {
+ snprintf(clk_id, sizeof(clk_id), "%s%d", clk_name, alias_id);
+ cmdq->clocks[alias_id].id = clk_id;
+ cmdq->clocks[alias_id].clk = of_clk_get(node, 0);
+ if (IS_ERR(cmdq->clocks[alias_id].clk)) {
+ dev_err(dev, "failed to get gce clk: %d\n", alias_id);
+ return PTR_ERR(cmdq->clocks[alias_id].clk);
+ }
+ }
+ }
+ } else {
+ cmdq->clocks[alias_id].id = clk_name;
+ cmdq->clocks[alias_id].clk = devm_clk_get(&pdev->dev, clk_name);
+ if (IS_ERR(cmdq->clocks[alias_id].clk)) {
+ dev_err(dev, "failed to get gce clk\n");
+ return PTR_ERR(cmdq->clocks[alias_id].clk);
+ }
}
cmdq->mbox.dev = dev;
@@ -590,7 +625,8 @@ static int cmdq_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, cmdq);
- WARN_ON(clk_prepare(cmdq->clock) < 0);
+
+ WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
cmdq_init(cmdq);
@@ -602,14 +638,47 @@ static const struct dev_pm_ops cmdq_pm_ops = {
.resume = cmdq_resume,
};
-static const struct gce_plat gce_plat_v2 = {.thread_nr = 16};
-static const struct gce_plat gce_plat_v3 = {.thread_nr = 24};
-static const struct gce_plat gce_plat_v4 = {.thread_nr = 24, .shift = 3};
+static const struct gce_plat gce_plat_v2 = {
+ .thread_nr = 16,
+ .shift = 0,
+ .control_by_sw = false,
+ .gce_num = 1
+};
+
+static const struct gce_plat gce_plat_v3 = {
+ .thread_nr = 24,
+ .shift = 0,
+ .control_by_sw = false,
+ .gce_num = 1
+};
+
+static const struct gce_plat gce_plat_v4 = {
+ .thread_nr = 24,
+ .shift = 3,
+ .control_by_sw = false,
+ .gce_num = 1
+};
+
+static const struct gce_plat gce_plat_v5 = {
+ .thread_nr = 24,
+ .shift = 3,
+ .control_by_sw = true,
+ .gce_num = 2
+};
+
+static const struct gce_plat gce_plat_v6 = {
+ .thread_nr = 24,
+ .shift = 3,
+ .control_by_sw = false,
+ .gce_num = 2
+};
static const struct of_device_id cmdq_of_ids[] = {
{.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_v2},
{.compatible = "mediatek,mt8183-gce", .data = (void *)&gce_plat_v3},
{.compatible = "mediatek,mt6779-gce", .data = (void *)&gce_plat_v4},
+ {.compatible = "mediatek,mt8192-gce", .data = (void *)&gce_plat_v5},
+ {.compatible = "mediatek,mt8195-gce", .data = (void *)&gce_plat_v6},
{}
};
diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
index 03bdc96dc457..82ccfaf14b24 100644
--- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
@@ -163,6 +163,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = {
{ .compatible = "qcom,ipq8074-apcs-apps-global", .data = &ipq8074_apcs_data },
{ .compatible = "qcom,msm8916-apcs-kpss-global", .data = &msm8916_apcs_data },
{ .compatible = "qcom,msm8939-apcs-kpss-global", .data = &msm8916_apcs_data },
+ { .compatible = "qcom,msm8953-apcs-kpss-global", .data = &msm8994_apcs_data },
{ .compatible = "qcom,msm8994-apcs-kpss-global", .data = &msm8994_apcs_data },
{ .compatible = "qcom,msm8996-apcs-hmss-global", .data = &msm8996_apcs_data },
{ .compatible = "qcom,msm8998-apcs-hmss-global", .data = &msm8998_apcs_data },
@@ -173,6 +174,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = {
{ .compatible = "qcom,sdm845-apss-shared", .data = &apps_shared_apcs_data },
{ .compatible = "qcom,sm6125-apcs-hmss-global", .data = &sm6125_apcs_data },
{ .compatible = "qcom,sm8150-apss-shared", .data = &apps_shared_apcs_data },
+ { .compatible = "qcom,sm6115-apcs-hmss-global", .data = &sdm660_apcs_data },
{ .compatible = "qcom,sdx55-apcs-gcc", .data = &sdx55_apcs_data },
{}
};
diff --git a/drivers/mailbox/qcom-ipcc.c b/drivers/mailbox/qcom-ipcc.c
index 584700cd1585..f1d4f4679b17 100644
--- a/drivers/mailbox/qcom-ipcc.c
+++ b/drivers/mailbox/qcom-ipcc.c
@@ -277,6 +277,7 @@ static struct platform_driver qcom_ipcc_driver = {
.driver = {
.name = "qcom-ipcc",
.of_match_table = qcom_ipcc_of_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c
index 38fbb3b59873..edf4ee6eff25 100644
--- a/drivers/mcb/mcb-core.c
+++ b/drivers/mcb/mcb-core.c
@@ -77,7 +77,7 @@ static int mcb_probe(struct device *dev)
return ret;
}
-static int mcb_remove(struct device *dev)
+static void mcb_remove(struct device *dev)
{
struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
struct mcb_device *mdev = to_mcb_device(dev);
@@ -89,8 +89,6 @@ static int mcb_remove(struct device *dev)
module_put(carrier_mod);
put_device(&mdev->dev);
-
- return 0;
}
static void mcb_shutdown(struct device *dev)
diff --git a/drivers/md/dm-ima.c b/drivers/md/dm-ima.c
index 3fd69ab12a8e..2c5edfbd7711 100644
--- a/drivers/md/dm-ima.c
+++ b/drivers/md/dm-ima.c
@@ -136,7 +136,8 @@ static void dm_ima_measure_data(const char *event_name, const void *buf, size_t
if (noio)
noio_flag = memalloc_noio_save();
- ima_measure_critical_data(DM_NAME, event_name, buf, buf_len, false);
+ ima_measure_critical_data(DM_NAME, event_name, buf, buf_len,
+ false, NULL, 0);
if (noio)
memalloc_noio_restore(noio_flag);
diff --git a/drivers/media/cec/core/cec-pin-priv.h b/drivers/media/cec/core/cec-pin-priv.h
index f423db8855d9..fb101f15865c 100644
--- a/drivers/media/cec/core/cec-pin-priv.h
+++ b/drivers/media/cec/core/cec-pin-priv.h
@@ -209,8 +209,8 @@ struct cec_pin {
u32 work_pin_events_dropped_cnt;
ktime_t timer_ts;
u32 timer_cnt;
- u32 timer_100ms_overruns;
- u32 timer_300ms_overruns;
+ u32 timer_100us_overruns;
+ u32 timer_300us_overruns;
u32 timer_max_overrun;
u32 timer_sum_overrun;
diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c
index f006bd8eec63..8c613aa649c6 100644
--- a/drivers/media/cec/core/cec-pin.c
+++ b/drivers/media/cec/core/cec-pin.c
@@ -854,9 +854,9 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
if (delta > 100 && pin->state != CEC_ST_IDLE) {
/* Keep track of timer overruns */
pin->timer_sum_overrun += delta;
- pin->timer_100ms_overruns++;
+ pin->timer_100us_overruns++;
if (delta > 300)
- pin->timer_300ms_overruns++;
+ pin->timer_300us_overruns++;
if (delta > pin->timer_max_overrun)
pin->timer_max_overrun = delta;
}
@@ -1207,15 +1207,15 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
seq_printf(file, "cec pin events dropped: %u\n",
pin->work_pin_events_dropped_cnt);
seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
- if (pin->timer_100ms_overruns) {
- seq_printf(file, "timer overruns > 100ms: %u of %u\n",
- pin->timer_100ms_overruns, pin->timer_cnt);
- seq_printf(file, "timer overruns > 300ms: %u of %u\n",
- pin->timer_300ms_overruns, pin->timer_cnt);
+ if (pin->timer_100us_overruns) {
+ seq_printf(file, "timer overruns > 100us: %u of %u\n",
+ pin->timer_100us_overruns, pin->timer_cnt);
+ seq_printf(file, "timer overruns > 300us: %u of %u\n",
+ pin->timer_300us_overruns, pin->timer_cnt);
seq_printf(file, "max timer overrun: %u usecs\n",
pin->timer_max_overrun);
seq_printf(file, "avg timer overrun: %u usecs\n",
- pin->timer_sum_overrun / pin->timer_100ms_overruns);
+ pin->timer_sum_overrun / pin->timer_100us_overruns);
}
if (pin->rx_start_bit_low_too_short_cnt)
seq_printf(file,
@@ -1245,8 +1245,8 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
seq_printf(file, "tx detected low drive: %u\n", pin->tx_low_drive_cnt);
pin->work_pin_events_dropped_cnt = 0;
pin->timer_cnt = 0;
- pin->timer_100ms_overruns = 0;
- pin->timer_300ms_overruns = 0;
+ pin->timer_100us_overruns = 0;
+ pin->timer_300us_overruns = 0;
pin->timer_max_overrun = 0;
pin->timer_sum_overrun = 0;
pin->rx_start_bit_low_too_short_cnt = 0;
diff --git a/drivers/media/cec/platform/stm32/stm32-cec.c b/drivers/media/cec/platform/stm32/stm32-cec.c
index ea4b1ebfca99..0ffd89712536 100644
--- a/drivers/media/cec/platform/stm32/stm32-cec.c
+++ b/drivers/media/cec/platform/stm32/stm32-cec.c
@@ -305,14 +305,16 @@ static int stm32_cec_probe(struct platform_device *pdev)
cec->clk_hdmi_cec = devm_clk_get(&pdev->dev, "hdmi-cec");
if (IS_ERR(cec->clk_hdmi_cec) &&
- PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
+ PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_unprepare_cec_clk;
+ }
if (!IS_ERR(cec->clk_hdmi_cec)) {
ret = clk_prepare(cec->clk_hdmi_cec);
if (ret) {
dev_err(&pdev->dev, "Can't prepare hdmi-cec clock\n");
- return ret;
+ goto err_unprepare_cec_clk;
}
}
@@ -324,19 +326,27 @@ static int stm32_cec_probe(struct platform_device *pdev)
CEC_NAME, caps, CEC_MAX_LOG_ADDRS);
ret = PTR_ERR_OR_ZERO(cec->adap);
if (ret)
- return ret;
+ goto err_unprepare_hdmi_cec_clk;
ret = cec_register_adapter(cec->adap, &pdev->dev);
- if (ret) {
- cec_delete_adapter(cec->adap);
- return ret;
- }
+ if (ret)
+ goto err_delete_adapter;
cec_hw_init(cec);
platform_set_drvdata(pdev, cec);
return 0;
+
+err_delete_adapter:
+ cec_delete_adapter(cec->adap);
+
+err_unprepare_hdmi_cec_clk:
+ clk_unprepare(cec->clk_hdmi_cec);
+
+err_unprepare_cec_clk:
+ clk_unprepare(cec->clk_cec);
+ return ret;
}
static int stm32_cec_remove(struct platform_device *pdev)
diff --git a/drivers/media/cec/platform/tegra/tegra_cec.c b/drivers/media/cec/platform/tegra/tegra_cec.c
index 1ac0c70a5981..5e907395ca2e 100644
--- a/drivers/media/cec/platform/tegra/tegra_cec.c
+++ b/drivers/media/cec/platform/tegra/tegra_cec.c
@@ -366,7 +366,11 @@ static int tegra_cec_probe(struct platform_device *pdev)
return -ENOENT;
}
- clk_prepare_enable(cec->clk);
+ ret = clk_prepare_enable(cec->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to prepare clock for CEC\n");
+ return ret;
+ }
/* set context info. */
cec->dev = &pdev->dev;
@@ -446,9 +450,7 @@ static int tegra_cec_resume(struct platform_device *pdev)
dev_notice(&pdev->dev, "Resuming\n");
- clk_prepare_enable(cec->clk);
-
- return 0;
+ return clk_prepare_enable(cec->clk);
}
#endif
diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c
index 9fccc906d85a..ac6e47d81b9e 100644
--- a/drivers/media/dvb-frontends/cx24117.c
+++ b/drivers/media/dvb-frontends/cx24117.c
@@ -1172,7 +1172,6 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
"%s: Error attaching frontend %d\n",
KBUILD_MODNAME, demod);
goto error1;
- break;
case 1:
/* new priv instance */
priv->i2c = i2c;
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
index 082796534b0a..bb02354a48b8 100644
--- a/drivers/media/dvb-frontends/dib8000.c
+++ b/drivers/media/dvb-frontends/dib8000.c
@@ -2107,32 +2107,55 @@ static void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *an
dib8000_write_word(state, 117 + mode, ana_fe[mode]);
}
-static const u16 lut_prbs_2k[14] = {
- 0, 0x423, 0x009, 0x5C7, 0x7A6, 0x3D8, 0x527, 0x7FF, 0x79B, 0x3D6, 0x3A2, 0x53B, 0x2F4, 0x213
+static const u16 lut_prbs_2k[13] = {
+ 0x423, 0x009, 0x5C7,
+ 0x7A6, 0x3D8, 0x527,
+ 0x7FF, 0x79B, 0x3D6,
+ 0x3A2, 0x53B, 0x2F4,
+ 0x213
};
-static const u16 lut_prbs_4k[14] = {
- 0, 0x208, 0x0C3, 0x7B9, 0x423, 0x5C7, 0x3D8, 0x7FF, 0x3D6, 0x53B, 0x213, 0x029, 0x0D0, 0x48E
+
+static const u16 lut_prbs_4k[13] = {
+ 0x208, 0x0C3, 0x7B9,
+ 0x423, 0x5C7, 0x3D8,
+ 0x7FF, 0x3D6, 0x53B,
+ 0x213, 0x029, 0x0D0,
+ 0x48E
};
-static const u16 lut_prbs_8k[14] = {
- 0, 0x740, 0x069, 0x7DD, 0x208, 0x7B9, 0x5C7, 0x7FF, 0x53B, 0x029, 0x48E, 0x4C4, 0x367, 0x684
+
+static const u16 lut_prbs_8k[13] = {
+ 0x740, 0x069, 0x7DD,
+ 0x208, 0x7B9, 0x5C7,
+ 0x7FF, 0x53B, 0x029,
+ 0x48E, 0x4C4, 0x367,
+ 0x684
};
static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel)
{
int sub_channel_prbs_group = 0;
+ int prbs_group;
- sub_channel_prbs_group = (subchannel / 3) + 1;
- dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]);
+ sub_channel_prbs_group = subchannel / 3;
+ if (sub_channel_prbs_group >= ARRAY_SIZE(lut_prbs_2k))
+ return 0;
switch (state->fe[0]->dtv_property_cache.transmission_mode) {
case TRANSMISSION_MODE_2K:
- return lut_prbs_2k[sub_channel_prbs_group];
+ prbs_group = lut_prbs_2k[sub_channel_prbs_group];
+ break;
case TRANSMISSION_MODE_4K:
- return lut_prbs_4k[sub_channel_prbs_group];
+ prbs_group = lut_prbs_4k[sub_channel_prbs_group];
+ break;
default:
case TRANSMISSION_MODE_8K:
- return lut_prbs_8k[sub_channel_prbs_group];
+ prbs_group = lut_prbs_8k[sub_channel_prbs_group];
}
+
+ dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n",
+ sub_channel_prbs_group, subchannel, prbs_group);
+
+ return prbs_group;
}
static void dib8000_set_13seg_channel(struct dib8000_state *state)
@@ -2409,10 +2432,8 @@ static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq
/* TSB or ISDBT ? apply it now */
if (c->isdbt_sb_mode) {
dib8000_set_sb_channel(state);
- if (c->isdbt_sb_subchannel < 14)
- init_prbs = dib8000_get_init_prbs(state, c->isdbt_sb_subchannel);
- else
- init_prbs = 0;
+ init_prbs = dib8000_get_init_prbs(state,
+ c->isdbt_sb_subchannel);
} else {
dib8000_set_13seg_channel(state);
init_prbs = 0xfff;
@@ -3004,6 +3025,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
unsigned long *timeout = &state->timeout;
unsigned long now = jiffies;
+ u16 init_prbs;
#ifdef DIB8000_AGC_FREEZE
u16 agc1, agc2;
#endif
@@ -3302,8 +3324,10 @@ static int dib8000_tune(struct dvb_frontend *fe)
break;
case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
- if (state->subchannel <= 41) {
- dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
+ init_prbs = dib8000_get_init_prbs(state, state->subchannel);
+
+ if (init_prbs) {
+ dib8000_set_subchannel_prbs(state, init_prbs);
*tune_state = CT_DEMOD_STEP_9;
} else {
*tune_state = CT_DEMOD_STOP;
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 588f8eb95984..08feb3e8c1bf 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -842,6 +842,20 @@ config VIDEO_IMX334
To compile this driver as a module, choose M here: the
module will be called imx334.
+config VIDEO_IMX335
+ tristate "Sony IMX335 sensor support"
+ depends on OF_GPIO
+ depends on I2C && VIDEO_V4L2
+ select VIDEO_V4L2_SUBDEV_API
+ select MEDIA_CONTROLLER
+ select V4L2_FWNODE
+ help
+ This is a Video4Linux2 sensor driver for the Sony
+ IMX335 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called imx335.
+
config VIDEO_IMX355
tristate "Sony IMX355 sensor support"
depends on I2C && VIDEO_V4L2
@@ -854,6 +868,20 @@ config VIDEO_IMX355
To compile this driver as a module, choose M here: the
module will be called imx355.
+config VIDEO_IMX412
+ tristate "Sony IMX412 sensor support"
+ depends on OF_GPIO
+ depends on I2C && VIDEO_V4L2
+ select VIDEO_V4L2_SUBDEV_API
+ select MEDIA_CONTROLLER
+ select V4L2_FWNODE
+ help
+ This is a Video4Linux2 sensor driver for the Sony
+ IMX412 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called imx412.
+
config VIDEO_OV02A10
tristate "OmniVision OV02A10 sensor support"
depends on VIDEO_V4L2 && I2C
@@ -1103,6 +1131,20 @@ config VIDEO_OV8865
To compile this driver as a module, choose M here: the
module will be called ov8865.
+config VIDEO_OV9282
+ tristate "OmniVision OV9282 sensor support"
+ depends on OF_GPIO
+ depends on I2C && VIDEO_V4L2
+ select VIDEO_V4L2_SUBDEV_API
+ select MEDIA_CONTROLLER
+ select V4L2_FWNODE
+ help
+ This is a Video4Linux2 sensor driver for the OmniVision
+ OV9282 camera sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ov9282.
+
config VIDEO_OV9640
tristate "OmniVision OV9640 sensor support"
depends on I2C && VIDEO_V4L2
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 1168fa6b84ed..83268f20aa3a 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
obj-$(CONFIG_VIDEO_OV8856) += ov8856.o
obj-$(CONFIG_VIDEO_OV8865) += ov8865.o
+obj-$(CONFIG_VIDEO_OV9282) += ov9282.o
obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
@@ -124,11 +125,12 @@ obj-$(CONFIG_VIDEO_IMX274) += imx274.o
obj-$(CONFIG_VIDEO_IMX290) += imx290.o
obj-$(CONFIG_VIDEO_IMX319) += imx319.o
obj-$(CONFIG_VIDEO_IMX334) += imx334.o
+obj-$(CONFIG_VIDEO_IMX335) += imx335.o
obj-$(CONFIG_VIDEO_IMX355) += imx355.o
+obj-$(CONFIG_VIDEO_IMX412) += imx412.o
obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
obj-$(CONFIG_VIDEO_RDACM20) += rdacm20.o
obj-$(CONFIG_VIDEO_RDACM21) += rdacm21.o
obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
-
obj-$(CONFIG_SDR_MAX2175) += max2175.o
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index fa5bc55bc944..d9a99fcfacb1 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -94,6 +94,7 @@
#define ADV7180_REG_SHAP_FILTER_CTL_1 0x0017
#define ADV7180_REG_CTRL_2 0x001d
#define ADV7180_REG_VSYNC_FIELD_CTL_1 0x0031
+#define ADV7180_VSYNC_FIELD_CTL_1_NEWAV 0x12
#define ADV7180_REG_MANUAL_WIN_CTL_1 0x003d
#define ADV7180_REG_MANUAL_WIN_CTL_2 0x003e
#define ADV7180_REG_MANUAL_WIN_CTL_3 0x003f
@@ -205,6 +206,7 @@ struct adv7180_state {
struct mutex mutex; /* mutual excl. when accessing chip */
int irq;
struct gpio_desc *pwdn_gpio;
+ struct gpio_desc *rst_gpio;
v4l2_std_id curr_norm;
bool powered;
bool streaming;
@@ -216,6 +218,7 @@ struct adv7180_state {
struct i2c_client *vpp_client;
const struct adv7180_chip_info *chip_info;
enum v4l2_field field;
+ bool force_bt656_4;
};
#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \
struct adv7180_state, \
@@ -484,6 +487,19 @@ static void adv7180_set_power_pin(struct adv7180_state *state, bool on)
}
}
+static void adv7180_set_reset_pin(struct adv7180_state *state, bool on)
+{
+ if (!state->rst_gpio)
+ return;
+
+ if (on) {
+ gpiod_set_value_cansleep(state->rst_gpio, 1);
+ } else {
+ gpiod_set_value_cansleep(state->rst_gpio, 0);
+ usleep_range(5000, 10000);
+ }
+}
+
static int adv7180_set_power(struct adv7180_state *state, bool on)
{
u8 val;
@@ -963,10 +979,26 @@ static int adv7182_init(struct adv7180_state *state)
adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x57);
adv7180_write(state, ADV7180_REG_CTRL_2, 0xc0);
} else {
- if (state->chip_info->flags & ADV7180_FLAG_V2)
- adv7180_write(state,
- ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
- 0x17);
+ if (state->chip_info->flags & ADV7180_FLAG_V2) {
+ if (state->force_bt656_4) {
+ /* ITU-R BT.656-4 compatible */
+ adv7180_write(state,
+ ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
+ ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
+ /* Manually set NEWAVMODE */
+ adv7180_write(state,
+ ADV7180_REG_VSYNC_FIELD_CTL_1,
+ ADV7180_VSYNC_FIELD_CTL_1_NEWAV);
+ /* Manually set V bit end position in NTSC mode */
+ adv7180_write(state,
+ ADV7180_REG_NTSC_V_BIT_END,
+ ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
+ } else {
+ adv7180_write(state,
+ ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
+ 0x17);
+ }
+ }
else
adv7180_write(state,
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
@@ -1263,6 +1295,7 @@ static int init_device(struct adv7180_state *state)
mutex_lock(&state->mutex);
adv7180_set_power_pin(state, true);
+ adv7180_set_reset_pin(state, false);
adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES);
usleep_range(5000, 10000);
@@ -1314,6 +1347,7 @@ out_unlock:
static int adv7180_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device_node *np = client->dev.of_node;
struct adv7180_state *state;
struct v4l2_subdev *sd;
int ret;
@@ -1338,6 +1372,17 @@ static int adv7180_probe(struct i2c_client *client,
return ret;
}
+ state->rst_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(state->rst_gpio)) {
+ ret = PTR_ERR(state->rst_gpio);
+ v4l_err(client, "request for reset pin failed: %d\n", ret);
+ return ret;
+ }
+
+ if (of_property_read_bool(np, "adv,force-bt656-4"))
+ state->force_bt656_4 = true;
+
if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
state->csi_client = i2c_new_dummy_device(client->adapter,
ADV7180_DEFAULT_CSI_I2C_ADDR);
@@ -1392,11 +1437,19 @@ static int adv7180_probe(struct i2c_client *client,
if (ret)
goto err_free_irq;
- v4l_info(client, "chip found @ 0x%02x (%s)\n",
- client->addr, client->adapter->name);
+ mutex_lock(&state->mutex);
+ ret = adv7180_read(state, ADV7180_REG_IDENT);
+ mutex_unlock(&state->mutex);
+ if (ret < 0)
+ goto err_v4l2_async_unregister;
+
+ v4l_info(client, "chip id 0x%x found @ 0x%02x (%s)\n",
+ ret, client->addr, client->adapter->name);
return 0;
+err_v4l2_async_unregister:
+ v4l2_async_unregister_subdev(sd);
err_free_irq:
if (state->irq > 0)
free_irq(client->irq, state);
@@ -1428,6 +1481,7 @@ static int adv7180_remove(struct i2c_client *client)
i2c_unregister_device(state->vpp_client);
i2c_unregister_device(state->csi_client);
+ adv7180_set_reset_pin(state, true);
adv7180_set_power_pin(state, false);
mutex_destroy(&state->mutex);
diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
index a9403a227c6b..5363f3bcafe3 100644
--- a/drivers/media/i2c/ccs/ccs-core.c
+++ b/drivers/media/i2c/ccs/ccs-core.c
@@ -1943,6 +1943,51 @@ static int ccs_set_stream(struct v4l2_subdev *subdev, int enable)
return rval;
}
+static int ccs_pre_streamon(struct v4l2_subdev *subdev, u32 flags)
+{
+ struct ccs_sensor *sensor = to_ccs_sensor(subdev);
+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+ int rval;
+
+ if (flags & V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP) {
+ switch (sensor->hwcfg.csi_signalling_mode) {
+ case CCS_CSI_SIGNALING_MODE_CSI_2_DPHY:
+ if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY_2) &
+ CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_DPHY))
+ return -EACCES;
+ break;
+ case CCS_CSI_SIGNALING_MODE_CSI_2_CPHY:
+ if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY_2) &
+ CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_CPHY))
+ return -EACCES;
+ break;
+ default:
+ return -EACCES;
+ }
+ }
+
+ rval = ccs_pm_get_init(sensor);
+ if (rval)
+ return rval;
+
+ if (flags & V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP) {
+ rval = ccs_write(sensor, MANUAL_LP_CTRL,
+ CCS_MANUAL_LP_CTRL_ENABLE);
+ if (rval)
+ pm_runtime_put(&client->dev);
+ }
+
+ return rval;
+}
+
+static int ccs_post_streamoff(struct v4l2_subdev *subdev)
+{
+ struct ccs_sensor *sensor = to_ccs_sensor(subdev);
+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+
+ return pm_runtime_put(&client->dev);
+}
+
static int ccs_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
@@ -2673,8 +2718,7 @@ static int ccs_get_skip_top_lines(struct v4l2_subdev *subdev, u32 *lines)
*/
static ssize_t
-ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
- char *buf)
+nvm_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
struct i2c_client *client = v4l2_get_subdevdata(subdev);
@@ -2704,11 +2748,10 @@ ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
*/
return rval;
}
-static DEVICE_ATTR(nvm, S_IRUGO, ccs_sysfs_nvm_read, NULL);
+static DEVICE_ATTR_RO(nvm);
static ssize_t
-ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
- char *buf)
+ident_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
struct ccs_sensor *sensor = to_ccs_sensor(subdev);
@@ -2723,8 +2766,7 @@ ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
minfo->smia_manufacturer_id, minfo->model_id,
minfo->revision_number) + 1;
}
-
-static DEVICE_ATTR(ident, S_IRUGO, ccs_sysfs_ident_read, NULL);
+static DEVICE_ATTR_RO(ident);
/* -----------------------------------------------------------------------------
* V4L2 subdev core operations
@@ -3058,6 +3100,8 @@ static int ccs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
static const struct v4l2_subdev_video_ops ccs_video_ops = {
.s_stream = ccs_set_stream,
+ .pre_streamon = ccs_pre_streamon,
+ .post_streamoff = ccs_post_streamoff,
};
static const struct v4l2_subdev_pad_ops ccs_pad_ops = {
diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c
index c7b91c0c03b5..873d614339bb 100644
--- a/drivers/media/i2c/et8ek8/et8ek8_driver.c
+++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c
@@ -1237,8 +1237,7 @@ out_poweroff:
* sysfs attributes
*/
static ssize_t
-et8ek8_priv_mem_read(struct device *dev, struct device_attribute *attr,
- char *buf)
+priv_mem_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct v4l2_subdev *subdev = dev_get_drvdata(dev);
struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);
@@ -1251,7 +1250,7 @@ et8ek8_priv_mem_read(struct device *dev, struct device_attribute *attr,
return ET8EK8_PRIV_MEM_SIZE;
}
-static DEVICE_ATTR(priv_mem, 0444, et8ek8_priv_mem_read, NULL);
+static DEVICE_ATTR_RO(priv_mem);
/* --------------------------------------------------------------------------
* V4L2 subdev core operations
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 7ab9e5f9f267..81cdf37216ca 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -23,7 +23,7 @@
#define IMX258_CHIP_ID 0x0258
/* V_TIMING internal */
-#define IMX258_VTS_30FPS 0x0c98
+#define IMX258_VTS_30FPS 0x0c50
#define IMX258_VTS_30FPS_2K 0x0638
#define IMX258_VTS_30FPS_VGA 0x034c
#define IMX258_VTS_MAX 0xffff
@@ -47,7 +47,7 @@
/* Analog gain control */
#define IMX258_REG_ANALOG_GAIN 0x0204
#define IMX258_ANA_GAIN_MIN 0
-#define IMX258_ANA_GAIN_MAX 0x1fff
+#define IMX258_ANA_GAIN_MAX 480
#define IMX258_ANA_GAIN_STEP 1
#define IMX258_ANA_GAIN_DEFAULT 0x0
diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c
new file mode 100644
index 000000000000..410d6b86feb5
--- /dev/null
+++ b/drivers/media/i2c/imx335.c
@@ -0,0 +1,1129 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Sony imx335 Camera Sensor Driver
+ *
+ * Copyright (C) 2021 Intel Corporation
+ */
+#include <asm/unaligned.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+/* Streaming Mode */
+#define IMX335_REG_MODE_SELECT 0x3000
+#define IMX335_MODE_STANDBY 0x01
+#define IMX335_MODE_STREAMING 0x00
+
+/* Lines per frame */
+#define IMX335_REG_LPFR 0x3030
+
+/* Chip ID */
+#define IMX335_REG_ID 0x3912
+#define IMX335_ID 0x00
+
+/* Exposure control */
+#define IMX335_REG_SHUTTER 0x3058
+#define IMX335_EXPOSURE_MIN 1
+#define IMX335_EXPOSURE_OFFSET 9
+#define IMX335_EXPOSURE_STEP 1
+#define IMX335_EXPOSURE_DEFAULT 0x0648
+
+/* Analog gain control */
+#define IMX335_REG_AGAIN 0x30e8
+#define IMX335_AGAIN_MIN 0
+#define IMX335_AGAIN_MAX 240
+#define IMX335_AGAIN_STEP 1
+#define IMX335_AGAIN_DEFAULT 0
+
+/* Group hold register */
+#define IMX335_REG_HOLD 0x3001
+
+/* Input clock rate */
+#define IMX335_INCLK_RATE 24000000
+
+/* CSI2 HW configuration */
+#define IMX335_LINK_FREQ 594000000
+#define IMX335_NUM_DATA_LANES 4
+
+#define IMX335_REG_MIN 0x00
+#define IMX335_REG_MAX 0xfffff
+
+/**
+ * struct imx335_reg - imx335 sensor register
+ * @address: Register address
+ * @val: Register value
+ */
+struct imx335_reg {
+ u16 address;
+ u8 val;
+};
+
+/**
+ * struct imx335_reg_list - imx335 sensor register list
+ * @num_of_regs: Number of registers in the list
+ * @regs: Pointer to register list
+ */
+struct imx335_reg_list {
+ u32 num_of_regs;
+ const struct imx335_reg *regs;
+};
+
+/**
+ * struct imx335_mode - imx335 sensor mode structure
+ * @width: Frame width
+ * @height: Frame height
+ * @code: Format code
+ * @hblank: Horizontal blanking in lines
+ * @vblank: Vertical blanking in lines
+ * @vblank_min: Minimum vertical blanking in lines
+ * @vblank_max: Maximum vertical blanking in lines
+ * @pclk: Sensor pixel clock
+ * @link_freq_idx: Link frequency index
+ * @reg_list: Register list for sensor mode
+ */
+struct imx335_mode {
+ u32 width;
+ u32 height;
+ u32 code;
+ u32 hblank;
+ u32 vblank;
+ u32 vblank_min;
+ u32 vblank_max;
+ u64 pclk;
+ u32 link_freq_idx;
+ struct imx335_reg_list reg_list;
+};
+
+/**
+ * struct imx335 - imx335 sensor device structure
+ * @dev: Pointer to generic device
+ * @client: Pointer to i2c client
+ * @sd: V4L2 sub-device
+ * @pad: Media pad. Only one pad supported
+ * @reset_gpio: Sensor reset gpio
+ * @inclk: Sensor input clock
+ * @ctrl_handler: V4L2 control handler
+ * @link_freq_ctrl: Pointer to link frequency control
+ * @pclk_ctrl: Pointer to pixel clock control
+ * @hblank_ctrl: Pointer to horizontal blanking control
+ * @vblank_ctrl: Pointer to vertical blanking control
+ * @exp_ctrl: Pointer to exposure control
+ * @again_ctrl: Pointer to analog gain control
+ * @vblank: Vertical blanking in lines
+ * @cur_mode: Pointer to current selected sensor mode
+ * @mutex: Mutex for serializing sensor controls
+ * @streaming: Flag indicating streaming state
+ */
+struct imx335 {
+ struct device *dev;
+ struct i2c_client *client;
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct gpio_desc *reset_gpio;
+ struct clk *inclk;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *link_freq_ctrl;
+ struct v4l2_ctrl *pclk_ctrl;
+ struct v4l2_ctrl *hblank_ctrl;
+ struct v4l2_ctrl *vblank_ctrl;
+ struct {
+ struct v4l2_ctrl *exp_ctrl;
+ struct v4l2_ctrl *again_ctrl;
+ };
+ u32 vblank;
+ const struct imx335_mode *cur_mode;
+ struct mutex mutex;
+ bool streaming;
+};
+
+static const s64 link_freq[] = {
+ IMX335_LINK_FREQ,
+};
+
+/* Sensor mode registers */
+static const struct imx335_reg mode_2592x1940_regs[] = {
+ {0x3000, 0x01},
+ {0x3002, 0x00},
+ {0x300c, 0x3b},
+ {0x300d, 0x2a},
+ {0x3018, 0x04},
+ {0x302c, 0x3c},
+ {0x302e, 0x20},
+ {0x3056, 0x94},
+ {0x3074, 0xc8},
+ {0x3076, 0x28},
+ {0x304c, 0x00},
+ {0x314c, 0xc6},
+ {0x315a, 0x02},
+ {0x3168, 0xa0},
+ {0x316a, 0x7e},
+ {0x31a1, 0x00},
+ {0x3288, 0x21},
+ {0x328a, 0x02},
+ {0x3414, 0x05},
+ {0x3416, 0x18},
+ {0x3648, 0x01},
+ {0x364a, 0x04},
+ {0x364c, 0x04},
+ {0x3678, 0x01},
+ {0x367c, 0x31},
+ {0x367e, 0x31},
+ {0x3706, 0x10},
+ {0x3708, 0x03},
+ {0x3714, 0x02},
+ {0x3715, 0x02},
+ {0x3716, 0x01},
+ {0x3717, 0x03},
+ {0x371c, 0x3d},
+ {0x371d, 0x3f},
+ {0x372c, 0x00},
+ {0x372d, 0x00},
+ {0x372e, 0x46},
+ {0x372f, 0x00},
+ {0x3730, 0x89},
+ {0x3731, 0x00},
+ {0x3732, 0x08},
+ {0x3733, 0x01},
+ {0x3734, 0xfe},
+ {0x3735, 0x05},
+ {0x3740, 0x02},
+ {0x375d, 0x00},
+ {0x375e, 0x00},
+ {0x375f, 0x11},
+ {0x3760, 0x01},
+ {0x3768, 0x1b},
+ {0x3769, 0x1b},
+ {0x376a, 0x1b},
+ {0x376b, 0x1b},
+ {0x376c, 0x1a},
+ {0x376d, 0x17},
+ {0x376e, 0x0f},
+ {0x3776, 0x00},
+ {0x3777, 0x00},
+ {0x3778, 0x46},
+ {0x3779, 0x00},
+ {0x377a, 0x89},
+ {0x377b, 0x00},
+ {0x377c, 0x08},
+ {0x377d, 0x01},
+ {0x377e, 0x23},
+ {0x377f, 0x02},
+ {0x3780, 0xd9},
+ {0x3781, 0x03},
+ {0x3782, 0xf5},
+ {0x3783, 0x06},
+ {0x3784, 0xa5},
+ {0x3788, 0x0f},
+ {0x378a, 0xd9},
+ {0x378b, 0x03},
+ {0x378c, 0xeb},
+ {0x378d, 0x05},
+ {0x378e, 0x87},
+ {0x378f, 0x06},
+ {0x3790, 0xf5},
+ {0x3792, 0x43},
+ {0x3794, 0x7a},
+ {0x3796, 0xa1},
+ {0x37b0, 0x36},
+ {0x3a00, 0x01},
+};
+
+/* Supported sensor mode configurations */
+static const struct imx335_mode supported_mode = {
+ .width = 2592,
+ .height = 1940,
+ .hblank = 342,
+ .vblank = 2560,
+ .vblank_min = 2560,
+ .vblank_max = 133060,
+ .pclk = 396000000,
+ .link_freq_idx = 0,
+ .code = MEDIA_BUS_FMT_SRGGB12_1X12,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_2592x1940_regs),
+ .regs = mode_2592x1940_regs,
+ },
+};
+
+/**
+ * to_imx335() - imx335 V4L2 sub-device to imx335 device.
+ * @subdev: pointer to imx335 V4L2 sub-device
+ *
+ * Return: pointer to imx335 device
+ */
+static inline struct imx335 *to_imx335(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct imx335, sd);
+}
+
+/**
+ * imx335_read_reg() - Read registers.
+ * @imx335: pointer to imx335 device
+ * @reg: register address
+ * @len: length of bytes to read. Max supported bytes is 4
+ * @val: pointer to register value to be filled.
+ *
+ * Big endian register addresses with little endian values.
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_read_reg(struct imx335 *imx335, u16 reg, u32 len, u32 *val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx335->sd);
+ struct i2c_msg msgs[2] = {0};
+ u8 addr_buf[2] = {0};
+ u8 data_buf[4] = {0};
+ int ret;
+
+ if (WARN_ON(len > 4))
+ return -EINVAL;
+
+ put_unaligned_be16(reg, addr_buf);
+
+ /* Write register address */
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = ARRAY_SIZE(addr_buf);
+ msgs[0].buf = addr_buf;
+
+ /* Read data from register */
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = data_buf;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs))
+ return -EIO;
+
+ *val = get_unaligned_le32(data_buf);
+
+ return 0;
+}
+
+/**
+ * imx335_write_reg() - Write register
+ * @imx335: pointer to imx335 device
+ * @reg: register address
+ * @len: length of bytes. Max supported bytes is 4
+ * @val: register value
+ *
+ * Big endian register addresses with little endian values.
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_write_reg(struct imx335 *imx335, u16 reg, u32 len, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx335->sd);
+ u8 buf[6] = {0};
+
+ if (WARN_ON(len > 4))
+ return -EINVAL;
+
+ put_unaligned_be16(reg, buf);
+ put_unaligned_le32(val, buf + 2);
+ if (i2c_master_send(client, buf, len + 2) != len + 2)
+ return -EIO;
+
+ return 0;
+}
+
+/**
+ * imx335_write_regs() - Write a list of registers
+ * @imx335: pointer to imx335 device
+ * @regs: list of registers to be written
+ * @len: length of registers array
+ *
+ * Return: 0 if successful. error code otherwise.
+ */
+static int imx335_write_regs(struct imx335 *imx335,
+ const struct imx335_reg *regs, u32 len)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < len; i++) {
+ ret = imx335_write_reg(imx335, regs[i].address, 1, regs[i].val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * imx335_update_controls() - Update control ranges based on streaming mode
+ * @imx335: pointer to imx335 device
+ * @mode: pointer to imx335_mode sensor mode
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_update_controls(struct imx335 *imx335,
+ const struct imx335_mode *mode)
+{
+ int ret;
+
+ ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, mode->link_freq_idx);
+ if (ret)
+ return ret;
+
+ ret = __v4l2_ctrl_s_ctrl(imx335->hblank_ctrl, mode->hblank);
+ if (ret)
+ return ret;
+
+ return __v4l2_ctrl_modify_range(imx335->vblank_ctrl, mode->vblank_min,
+ mode->vblank_max, 1, mode->vblank);
+}
+
+/**
+ * imx335_update_exp_gain() - Set updated exposure and gain
+ * @imx335: pointer to imx335 device
+ * @exposure: updated exposure value
+ * @gain: updated analog gain value
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_update_exp_gain(struct imx335 *imx335, u32 exposure, u32 gain)
+{
+ u32 lpfr, shutter;
+ int ret;
+
+ lpfr = imx335->vblank + imx335->cur_mode->height;
+ shutter = lpfr - exposure;
+
+ dev_dbg(imx335->dev, "Set exp %u, analog gain %u, shutter %u, lpfr %u",
+ exposure, gain, shutter, lpfr);
+
+ ret = imx335_write_reg(imx335, IMX335_REG_HOLD, 1, 1);
+ if (ret)
+ return ret;
+
+ ret = imx335_write_reg(imx335, IMX335_REG_LPFR, 3, lpfr);
+ if (ret)
+ goto error_release_group_hold;
+
+ ret = imx335_write_reg(imx335, IMX335_REG_SHUTTER, 3, shutter);
+ if (ret)
+ goto error_release_group_hold;
+
+ ret = imx335_write_reg(imx335, IMX335_REG_AGAIN, 2, gain);
+
+error_release_group_hold:
+ imx335_write_reg(imx335, IMX335_REG_HOLD, 1, 0);
+
+ return ret;
+}
+
+/**
+ * imx335_set_ctrl() - Set subdevice control
+ * @ctrl: pointer to v4l2_ctrl structure
+ *
+ * Supported controls:
+ * - V4L2_CID_VBLANK
+ * - cluster controls:
+ * - V4L2_CID_ANALOGUE_GAIN
+ * - V4L2_CID_EXPOSURE
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct imx335 *imx335 =
+ container_of(ctrl->handler, struct imx335, ctrl_handler);
+ u32 analog_gain;
+ u32 exposure;
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_VBLANK:
+ imx335->vblank = imx335->vblank_ctrl->val;
+
+ dev_dbg(imx335->dev, "Received vblank %u, new lpfr %u",
+ imx335->vblank,
+ imx335->vblank + imx335->cur_mode->height);
+
+ ret = __v4l2_ctrl_modify_range(imx335->exp_ctrl,
+ IMX335_EXPOSURE_MIN,
+ imx335->vblank +
+ imx335->cur_mode->height -
+ IMX335_EXPOSURE_OFFSET,
+ 1, IMX335_EXPOSURE_DEFAULT);
+ break;
+ case V4L2_CID_EXPOSURE:
+ /* Set controls only if sensor is in power on state */
+ if (!pm_runtime_get_if_in_use(imx335->dev))
+ return 0;
+
+ exposure = ctrl->val;
+ analog_gain = imx335->again_ctrl->val;
+
+ dev_dbg(imx335->dev, "Received exp %u, analog gain %u",
+ exposure, analog_gain);
+
+ ret = imx335_update_exp_gain(imx335, exposure, analog_gain);
+
+ pm_runtime_put(imx335->dev);
+
+ break;
+ default:
+ dev_err(imx335->dev, "Invalid control %d", ctrl->id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/* V4l2 subdevice control ops*/
+static const struct v4l2_ctrl_ops imx335_ctrl_ops = {
+ .s_ctrl = imx335_set_ctrl,
+};
+
+/**
+ * imx335_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
+ * @sd: pointer to imx335 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @code: V4L2 sub-device code enumeration need to be filled
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ code->code = supported_mode.code;
+
+ return 0;
+}
+
+/**
+ * imx335_enum_frame_size() - Enumerate V4L2 sub-device frame sizes
+ * @sd: pointer to imx335 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fsize: V4L2 sub-device size enumeration need to be filled
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fsize)
+{
+ if (fsize->index > 0)
+ return -EINVAL;
+
+ if (fsize->code != supported_mode.code)
+ return -EINVAL;
+
+ fsize->min_width = supported_mode.width;
+ fsize->max_width = fsize->min_width;
+ fsize->min_height = supported_mode.height;
+ fsize->max_height = fsize->min_height;
+
+ return 0;
+}
+
+/**
+ * imx335_fill_pad_format() - Fill subdevice pad format
+ * from selected sensor mode
+ * @imx335: pointer to imx335 device
+ * @mode: pointer to imx335_mode sensor mode
+ * @fmt: V4L2 sub-device format need to be filled
+ */
+static void imx335_fill_pad_format(struct imx335 *imx335,
+ const struct imx335_mode *mode,
+ struct v4l2_subdev_format *fmt)
+{
+ fmt->format.width = mode->width;
+ fmt->format.height = mode->height;
+ fmt->format.code = mode->code;
+ fmt->format.field = V4L2_FIELD_NONE;
+ fmt->format.colorspace = V4L2_COLORSPACE_RAW;
+ fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ fmt->format.quantization = V4L2_QUANTIZATION_DEFAULT;
+ fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
+}
+
+/**
+ * imx335_get_pad_format() - Get subdevice pad format
+ * @sd: pointer to imx335 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fmt: V4L2 sub-device format need to be set
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_get_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx335 *imx335 = to_imx335(sd);
+
+ mutex_lock(&imx335->mutex);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *framefmt;
+
+ framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ fmt->format = *framefmt;
+ } else {
+ imx335_fill_pad_format(imx335, imx335->cur_mode, fmt);
+ }
+
+ mutex_unlock(&imx335->mutex);
+
+ return 0;
+}
+
+/**
+ * imx335_set_pad_format() - Set subdevice pad format
+ * @sd: pointer to imx335 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fmt: V4L2 sub-device format need to be set
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx335 *imx335 = to_imx335(sd);
+ const struct imx335_mode *mode;
+ int ret = 0;
+
+ mutex_lock(&imx335->mutex);
+
+ mode = &supported_mode;
+ imx335_fill_pad_format(imx335, mode, fmt);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *framefmt;
+
+ framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ *framefmt = fmt->format;
+ } else {
+ ret = imx335_update_controls(imx335, mode);
+ if (!ret)
+ imx335->cur_mode = mode;
+ }
+
+ mutex_unlock(&imx335->mutex);
+
+ return ret;
+}
+
+/**
+ * imx335_init_pad_cfg() - Initialize sub-device pad configuration
+ * @sd: pointer to imx335 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_init_pad_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ struct imx335 *imx335 = to_imx335(sd);
+ struct v4l2_subdev_format fmt = { 0 };
+
+ fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+ imx335_fill_pad_format(imx335, &supported_mode, &fmt);
+
+ return imx335_set_pad_format(sd, sd_state, &fmt);
+}
+
+/**
+ * imx335_start_streaming() - Start sensor stream
+ * @imx335: pointer to imx335 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_start_streaming(struct imx335 *imx335)
+{
+ const struct imx335_reg_list *reg_list;
+ int ret;
+
+ /* Write sensor mode registers */
+ reg_list = &imx335->cur_mode->reg_list;
+ ret = imx335_write_regs(imx335, reg_list->regs,
+ reg_list->num_of_regs);
+ if (ret) {
+ dev_err(imx335->dev, "fail to write initial registers");
+ return ret;
+ }
+
+ /* Setup handler will write actual exposure and gain */
+ ret = __v4l2_ctrl_handler_setup(imx335->sd.ctrl_handler);
+ if (ret) {
+ dev_err(imx335->dev, "fail to setup handler");
+ return ret;
+ }
+
+ /* Start streaming */
+ ret = imx335_write_reg(imx335, IMX335_REG_MODE_SELECT,
+ 1, IMX335_MODE_STREAMING);
+ if (ret) {
+ dev_err(imx335->dev, "fail to start streaming");
+ return ret;
+ }
+
+ /* Initial regulator stabilization period */
+ usleep_range(18000, 20000);
+
+ return 0;
+}
+
+/**
+ * imx335_stop_streaming() - Stop sensor stream
+ * @imx335: pointer to imx335 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_stop_streaming(struct imx335 *imx335)
+{
+ return imx335_write_reg(imx335, IMX335_REG_MODE_SELECT,
+ 1, IMX335_MODE_STANDBY);
+}
+
+/**
+ * imx335_set_stream() - Enable sensor streaming
+ * @sd: pointer to imx335 subdevice
+ * @enable: set to enable sensor streaming
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct imx335 *imx335 = to_imx335(sd);
+ int ret;
+
+ mutex_lock(&imx335->mutex);
+
+ if (imx335->streaming == enable) {
+ mutex_unlock(&imx335->mutex);
+ return 0;
+ }
+
+ if (enable) {
+ ret = pm_runtime_resume_and_get(imx335->dev);
+ if (ret)
+ goto error_unlock;
+
+ ret = imx335_start_streaming(imx335);
+ if (ret)
+ goto error_power_off;
+ } else {
+ imx335_stop_streaming(imx335);
+ pm_runtime_put(imx335->dev);
+ }
+
+ imx335->streaming = enable;
+
+ mutex_unlock(&imx335->mutex);
+
+ return 0;
+
+error_power_off:
+ pm_runtime_put(imx335->dev);
+error_unlock:
+ mutex_unlock(&imx335->mutex);
+
+ return ret;
+}
+
+/**
+ * imx335_detect() - Detect imx335 sensor
+ * @imx335: pointer to imx335 device
+ *
+ * Return: 0 if successful, -EIO if sensor id does not match
+ */
+static int imx335_detect(struct imx335 *imx335)
+{
+ int ret;
+ u32 val;
+
+ ret = imx335_read_reg(imx335, IMX335_REG_ID, 2, &val);
+ if (ret)
+ return ret;
+
+ if (val != IMX335_ID) {
+ dev_err(imx335->dev, "chip id mismatch: %x!=%x",
+ IMX335_ID, val);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+/**
+ * imx335_parse_hw_config() - Parse HW configuration and check if supported
+ * @imx335: pointer to imx335 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_parse_hw_config(struct imx335 *imx335)
+{
+ struct fwnode_handle *fwnode = dev_fwnode(imx335->dev);
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ struct fwnode_handle *ep;
+ unsigned long rate;
+ unsigned int i;
+ int ret;
+
+ if (!fwnode)
+ return -ENXIO;
+
+ /* Request optional reset pin */
+ imx335->reset_gpio = devm_gpiod_get_optional(imx335->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(imx335->reset_gpio)) {
+ dev_err(imx335->dev, "failed to get reset gpio %ld",
+ PTR_ERR(imx335->reset_gpio));
+ return PTR_ERR(imx335->reset_gpio);
+ }
+
+ /* Get sensor input clock */
+ imx335->inclk = devm_clk_get(imx335->dev, NULL);
+ if (IS_ERR(imx335->inclk)) {
+ dev_err(imx335->dev, "could not get inclk");
+ return PTR_ERR(imx335->inclk);
+ }
+
+ rate = clk_get_rate(imx335->inclk);
+ if (rate != IMX335_INCLK_RATE) {
+ dev_err(imx335->dev, "inclk frequency mismatch");
+ return -EINVAL;
+ }
+
+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+ if (!ep)
+ return -ENXIO;
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ fwnode_handle_put(ep);
+ if (ret)
+ return ret;
+
+ if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX335_NUM_DATA_LANES) {
+ dev_err(imx335->dev,
+ "number of CSI2 data lanes %d is not supported",
+ bus_cfg.bus.mipi_csi2.num_data_lanes);
+ ret = -EINVAL;
+ goto done_endpoint_free;
+ }
+
+ if (!bus_cfg.nr_of_link_frequencies) {
+ dev_err(imx335->dev, "no link frequencies defined");
+ ret = -EINVAL;
+ goto done_endpoint_free;
+ }
+
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
+ if (bus_cfg.link_frequencies[i] == IMX335_LINK_FREQ)
+ goto done_endpoint_free;
+
+ ret = -EINVAL;
+
+done_endpoint_free:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+
+ return ret;
+}
+
+/* V4l2 subdevice ops */
+static const struct v4l2_subdev_video_ops imx335_video_ops = {
+ .s_stream = imx335_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops imx335_pad_ops = {
+ .init_cfg = imx335_init_pad_cfg,
+ .enum_mbus_code = imx335_enum_mbus_code,
+ .enum_frame_size = imx335_enum_frame_size,
+ .get_fmt = imx335_get_pad_format,
+ .set_fmt = imx335_set_pad_format,
+};
+
+static const struct v4l2_subdev_ops imx335_subdev_ops = {
+ .video = &imx335_video_ops,
+ .pad = &imx335_pad_ops,
+};
+
+/**
+ * imx335_power_on() - Sensor power on sequence
+ * @dev: pointer to i2c device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct imx335 *imx335 = to_imx335(sd);
+ int ret;
+
+ gpiod_set_value_cansleep(imx335->reset_gpio, 1);
+
+ ret = clk_prepare_enable(imx335->inclk);
+ if (ret) {
+ dev_err(imx335->dev, "fail to enable inclk");
+ goto error_reset;
+ }
+
+ usleep_range(20, 22);
+
+ return 0;
+
+error_reset:
+ gpiod_set_value_cansleep(imx335->reset_gpio, 0);
+
+ return ret;
+}
+
+/**
+ * imx335_power_off() - Sensor power off sequence
+ * @dev: pointer to i2c device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct imx335 *imx335 = to_imx335(sd);
+
+ gpiod_set_value_cansleep(imx335->reset_gpio, 0);
+
+ clk_disable_unprepare(imx335->inclk);
+
+ return 0;
+}
+
+/**
+ * imx335_init_controls() - Initialize sensor subdevice controls
+ * @imx335: pointer to imx335 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_init_controls(struct imx335 *imx335)
+{
+ struct v4l2_ctrl_handler *ctrl_hdlr = &imx335->ctrl_handler;
+ const struct imx335_mode *mode = imx335->cur_mode;
+ u32 lpfr;
+ int ret;
+
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6);
+ if (ret)
+ return ret;
+
+ /* Serialize controls with sensor device */
+ ctrl_hdlr->lock = &imx335->mutex;
+
+ /* Initialize exposure and gain */
+ lpfr = mode->vblank + mode->height;
+ imx335->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx335_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ IMX335_EXPOSURE_MIN,
+ lpfr - IMX335_EXPOSURE_OFFSET,
+ IMX335_EXPOSURE_STEP,
+ IMX335_EXPOSURE_DEFAULT);
+
+ imx335->again_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx335_ctrl_ops,
+ V4L2_CID_ANALOGUE_GAIN,
+ IMX335_AGAIN_MIN,
+ IMX335_AGAIN_MAX,
+ IMX335_AGAIN_STEP,
+ IMX335_AGAIN_DEFAULT);
+
+ v4l2_ctrl_cluster(2, &imx335->exp_ctrl);
+
+ imx335->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx335_ctrl_ops,
+ V4L2_CID_VBLANK,
+ mode->vblank_min,
+ mode->vblank_max,
+ 1, mode->vblank);
+
+ /* Read only controls */
+ imx335->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx335_ctrl_ops,
+ V4L2_CID_PIXEL_RATE,
+ mode->pclk, mode->pclk,
+ 1, mode->pclk);
+
+ imx335->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr,
+ &imx335_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(link_freq) -
+ 1,
+ mode->link_freq_idx,
+ link_freq);
+ if (imx335->link_freq_ctrl)
+ imx335->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ imx335->hblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx335_ctrl_ops,
+ V4L2_CID_HBLANK,
+ IMX335_REG_MIN,
+ IMX335_REG_MAX,
+ 1, mode->hblank);
+ if (imx335->hblank_ctrl)
+ imx335->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ if (ctrl_hdlr->error) {
+ dev_err(imx335->dev, "control init failed: %d",
+ ctrl_hdlr->error);
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+ return ctrl_hdlr->error;
+ }
+
+ imx335->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+}
+
+/**
+ * imx335_probe() - I2C client device binding
+ * @client: pointer to i2c client device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_probe(struct i2c_client *client)
+{
+ struct imx335 *imx335;
+ int ret;
+
+ imx335 = devm_kzalloc(&client->dev, sizeof(*imx335), GFP_KERNEL);
+ if (!imx335)
+ return -ENOMEM;
+
+ imx335->dev = &client->dev;
+
+ /* Initialize subdev */
+ v4l2_i2c_subdev_init(&imx335->sd, client, &imx335_subdev_ops);
+
+ ret = imx335_parse_hw_config(imx335);
+ if (ret) {
+ dev_err(imx335->dev, "HW configuration is not supported");
+ return ret;
+ }
+
+ mutex_init(&imx335->mutex);
+
+ ret = imx335_power_on(imx335->dev);
+ if (ret) {
+ dev_err(imx335->dev, "failed to power-on the sensor");
+ goto error_mutex_destroy;
+ }
+
+ /* Check module identity */
+ ret = imx335_detect(imx335);
+ if (ret) {
+ dev_err(imx335->dev, "failed to find sensor: %d", ret);
+ goto error_power_off;
+ }
+
+ /* Set default mode to max resolution */
+ imx335->cur_mode = &supported_mode;
+ imx335->vblank = imx335->cur_mode->vblank;
+
+ ret = imx335_init_controls(imx335);
+ if (ret) {
+ dev_err(imx335->dev, "failed to init controls: %d", ret);
+ goto error_power_off;
+ }
+
+ /* Initialize subdev */
+ imx335->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ imx335->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ /* Initialize source pad */
+ imx335->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&imx335->sd.entity, 1, &imx335->pad);
+ if (ret) {
+ dev_err(imx335->dev, "failed to init entity pads: %d", ret);
+ goto error_handler_free;
+ }
+
+ ret = v4l2_async_register_subdev_sensor(&imx335->sd);
+ if (ret < 0) {
+ dev_err(imx335->dev,
+ "failed to register async subdev: %d", ret);
+ goto error_media_entity;
+ }
+
+ pm_runtime_set_active(imx335->dev);
+ pm_runtime_enable(imx335->dev);
+ pm_runtime_idle(imx335->dev);
+
+ return 0;
+
+error_media_entity:
+ media_entity_cleanup(&imx335->sd.entity);
+error_handler_free:
+ v4l2_ctrl_handler_free(imx335->sd.ctrl_handler);
+error_power_off:
+ imx335_power_off(imx335->dev);
+error_mutex_destroy:
+ mutex_destroy(&imx335->mutex);
+
+ return ret;
+}
+
+/**
+ * imx335_remove() - I2C client device unbinding
+ * @client: pointer to I2C client device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct imx335 *imx335 = to_imx335(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev))
+ imx335_power_off(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+
+ mutex_destroy(&imx335->mutex);
+
+ return 0;
+}
+
+static const struct dev_pm_ops imx335_pm_ops = {
+ SET_RUNTIME_PM_OPS(imx335_power_off, imx335_power_on, NULL)
+};
+
+static const struct of_device_id imx335_of_match[] = {
+ { .compatible = "sony,imx335" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, imx335_of_match);
+
+static struct i2c_driver imx335_driver = {
+ .probe_new = imx335_probe,
+ .remove = imx335_remove,
+ .driver = {
+ .name = "imx335",
+ .pm = &imx335_pm_ops,
+ .of_match_table = imx335_of_match,
+ },
+};
+
+module_i2c_driver(imx335_driver);
+
+MODULE_DESCRIPTION("Sony imx335 sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/imx412.c b/drivers/media/i2c/imx412.c
new file mode 100644
index 000000000000..be3f6ea55559
--- /dev/null
+++ b/drivers/media/i2c/imx412.c
@@ -0,0 +1,1272 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Sony imx412 Camera Sensor Driver
+ *
+ * Copyright (C) 2021 Intel Corporation
+ */
+#include <asm/unaligned.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+/* Streaming Mode */
+#define IMX412_REG_MODE_SELECT 0x0100
+#define IMX412_MODE_STANDBY 0x00
+#define IMX412_MODE_STREAMING 0x01
+
+/* Lines per frame */
+#define IMX412_REG_LPFR 0x0340
+
+/* Chip ID */
+#define IMX412_REG_ID 0x0016
+#define IMX412_ID 0x577
+
+/* Exposure control */
+#define IMX412_REG_EXPOSURE_CIT 0x0202
+#define IMX412_EXPOSURE_MIN 8
+#define IMX412_EXPOSURE_OFFSET 22
+#define IMX412_EXPOSURE_STEP 1
+#define IMX412_EXPOSURE_DEFAULT 0x0648
+
+/* Analog gain control */
+#define IMX412_REG_AGAIN 0x0204
+#define IMX412_AGAIN_MIN 0
+#define IMX412_AGAIN_MAX 978
+#define IMX412_AGAIN_STEP 1
+#define IMX412_AGAIN_DEFAULT 0
+
+/* Group hold register */
+#define IMX412_REG_HOLD 0x0104
+
+/* Input clock rate */
+#define IMX412_INCLK_RATE 24000000
+
+/* CSI2 HW configuration */
+#define IMX412_LINK_FREQ 600000000
+#define IMX412_NUM_DATA_LANES 4
+
+#define IMX412_REG_MIN 0x00
+#define IMX412_REG_MAX 0xffff
+
+/**
+ * struct imx412_reg - imx412 sensor register
+ * @address: Register address
+ * @val: Register value
+ */
+struct imx412_reg {
+ u16 address;
+ u8 val;
+};
+
+/**
+ * struct imx412_reg_list - imx412 sensor register list
+ * @num_of_regs: Number of registers in the list
+ * @regs: Pointer to register list
+ */
+struct imx412_reg_list {
+ u32 num_of_regs;
+ const struct imx412_reg *regs;
+};
+
+/**
+ * struct imx412_mode - imx412 sensor mode structure
+ * @width: Frame width
+ * @height: Frame height
+ * @code: Format code
+ * @hblank: Horizontal blanking in lines
+ * @vblank: Vertical blanking in lines
+ * @vblank_min: Minimum vertical blanking in lines
+ * @vblank_max: Maximum vertical blanking in lines
+ * @pclk: Sensor pixel clock
+ * @link_freq_idx: Link frequency index
+ * @reg_list: Register list for sensor mode
+ */
+struct imx412_mode {
+ u32 width;
+ u32 height;
+ u32 code;
+ u32 hblank;
+ u32 vblank;
+ u32 vblank_min;
+ u32 vblank_max;
+ u64 pclk;
+ u32 link_freq_idx;
+ struct imx412_reg_list reg_list;
+};
+
+/**
+ * struct imx412 - imx412 sensor device structure
+ * @dev: Pointer to generic device
+ * @client: Pointer to i2c client
+ * @sd: V4L2 sub-device
+ * @pad: Media pad. Only one pad supported
+ * @reset_gpio: Sensor reset gpio
+ * @inclk: Sensor input clock
+ * @ctrl_handler: V4L2 control handler
+ * @link_freq_ctrl: Pointer to link frequency control
+ * @pclk_ctrl: Pointer to pixel clock control
+ * @hblank_ctrl: Pointer to horizontal blanking control
+ * @vblank_ctrl: Pointer to vertical blanking control
+ * @exp_ctrl: Pointer to exposure control
+ * @again_ctrl: Pointer to analog gain control
+ * @vblank: Vertical blanking in lines
+ * @cur_mode: Pointer to current selected sensor mode
+ * @mutex: Mutex for serializing sensor controls
+ * @streaming: Flag indicating streaming state
+ */
+struct imx412 {
+ struct device *dev;
+ struct i2c_client *client;
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct gpio_desc *reset_gpio;
+ struct clk *inclk;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *link_freq_ctrl;
+ struct v4l2_ctrl *pclk_ctrl;
+ struct v4l2_ctrl *hblank_ctrl;
+ struct v4l2_ctrl *vblank_ctrl;
+ struct {
+ struct v4l2_ctrl *exp_ctrl;
+ struct v4l2_ctrl *again_ctrl;
+ };
+ u32 vblank;
+ const struct imx412_mode *cur_mode;
+ struct mutex mutex;
+ bool streaming;
+};
+
+static const s64 link_freq[] = {
+ IMX412_LINK_FREQ,
+};
+
+/* Sensor mode registers */
+static const struct imx412_reg mode_4056x3040_regs[] = {
+ {0x0136, 0x18},
+ {0x0137, 0x00},
+ {0x3c7e, 0x08},
+ {0x3c7f, 0x02},
+ {0x38a8, 0x1f},
+ {0x38a9, 0xff},
+ {0x38aa, 0x1f},
+ {0x38ab, 0xff},
+ {0x55d4, 0x00},
+ {0x55d5, 0x00},
+ {0x55d6, 0x07},
+ {0x55d7, 0xff},
+ {0x55e8, 0x07},
+ {0x55e9, 0xff},
+ {0x55ea, 0x00},
+ {0x55eb, 0x00},
+ {0x575c, 0x07},
+ {0x575d, 0xff},
+ {0x575e, 0x00},
+ {0x575f, 0x00},
+ {0x5764, 0x00},
+ {0x5765, 0x00},
+ {0x5766, 0x07},
+ {0x5767, 0xff},
+ {0x5974, 0x04},
+ {0x5975, 0x01},
+ {0x5f10, 0x09},
+ {0x5f11, 0x92},
+ {0x5f12, 0x32},
+ {0x5f13, 0x72},
+ {0x5f14, 0x16},
+ {0x5f15, 0xba},
+ {0x5f17, 0x13},
+ {0x5f18, 0x24},
+ {0x5f19, 0x60},
+ {0x5f1a, 0xe3},
+ {0x5f1b, 0xad},
+ {0x5f1c, 0x74},
+ {0x5f2d, 0x25},
+ {0x5f5c, 0xd0},
+ {0x6a22, 0x00},
+ {0x6a23, 0x1d},
+ {0x7ba8, 0x00},
+ {0x7ba9, 0x00},
+ {0x886b, 0x00},
+ {0x9002, 0x0a},
+ {0x9004, 0x1a},
+ {0x9214, 0x93},
+ {0x9215, 0x69},
+ {0x9216, 0x93},
+ {0x9217, 0x6b},
+ {0x9218, 0x93},
+ {0x9219, 0x6d},
+ {0x921a, 0x57},
+ {0x921b, 0x58},
+ {0x921c, 0x57},
+ {0x921d, 0x59},
+ {0x921e, 0x57},
+ {0x921f, 0x5a},
+ {0x9220, 0x57},
+ {0x9221, 0x5b},
+ {0x9222, 0x93},
+ {0x9223, 0x02},
+ {0x9224, 0x93},
+ {0x9225, 0x03},
+ {0x9226, 0x93},
+ {0x9227, 0x04},
+ {0x9228, 0x93},
+ {0x9229, 0x05},
+ {0x922a, 0x98},
+ {0x922b, 0x21},
+ {0x922c, 0xb2},
+ {0x922d, 0xdb},
+ {0x922e, 0xb2},
+ {0x922f, 0xdc},
+ {0x9230, 0xb2},
+ {0x9231, 0xdd},
+ {0x9232, 0xe2},
+ {0x9233, 0xe1},
+ {0x9234, 0xb2},
+ {0x9235, 0xe2},
+ {0x9236, 0xb2},
+ {0x9237, 0xe3},
+ {0x9238, 0xb7},
+ {0x9239, 0xb9},
+ {0x923a, 0xb7},
+ {0x923b, 0xbb},
+ {0x923c, 0xb7},
+ {0x923d, 0xbc},
+ {0x923e, 0xb7},
+ {0x923f, 0xc5},
+ {0x9240, 0xb7},
+ {0x9241, 0xc7},
+ {0x9242, 0xb7},
+ {0x9243, 0xc9},
+ {0x9244, 0x98},
+ {0x9245, 0x56},
+ {0x9246, 0x98},
+ {0x9247, 0x55},
+ {0x9380, 0x00},
+ {0x9381, 0x62},
+ {0x9382, 0x00},
+ {0x9383, 0x56},
+ {0x9384, 0x00},
+ {0x9385, 0x52},
+ {0x9388, 0x00},
+ {0x9389, 0x55},
+ {0x938a, 0x00},
+ {0x938b, 0x55},
+ {0x938c, 0x00},
+ {0x938d, 0x41},
+ {0x5078, 0x01},
+ {0x0112, 0x0a},
+ {0x0113, 0x0a},
+ {0x0114, 0x03},
+ {0x0342, 0x11},
+ {0x0343, 0xa0},
+ {0x0340, 0x0d},
+ {0x0341, 0xda},
+ {0x3210, 0x00},
+ {0x0344, 0x00},
+ {0x0345, 0x00},
+ {0x0346, 0x00},
+ {0x0347, 0x00},
+ {0x0348, 0x0f},
+ {0x0349, 0xd7},
+ {0x034a, 0x0b},
+ {0x034b, 0xdf},
+ {0x00e3, 0x00},
+ {0x00e4, 0x00},
+ {0x00e5, 0x01},
+ {0x00fc, 0x0a},
+ {0x00fd, 0x0a},
+ {0x00fe, 0x0a},
+ {0x00ff, 0x0a},
+ {0xe013, 0x00},
+ {0x0220, 0x00},
+ {0x0221, 0x11},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0900, 0x00},
+ {0x0901, 0x11},
+ {0x0902, 0x00},
+ {0x3140, 0x02},
+ {0x3241, 0x11},
+ {0x3250, 0x03},
+ {0x3e10, 0x00},
+ {0x3e11, 0x00},
+ {0x3f0d, 0x00},
+ {0x3f42, 0x00},
+ {0x3f43, 0x00},
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x0408, 0x00},
+ {0x0409, 0x00},
+ {0x040a, 0x00},
+ {0x040b, 0x00},
+ {0x040c, 0x0f},
+ {0x040d, 0xd8},
+ {0x040e, 0x0b},
+ {0x040f, 0xe0},
+ {0x034c, 0x0f},
+ {0x034d, 0xd8},
+ {0x034e, 0x0b},
+ {0x034f, 0xe0},
+ {0x0301, 0x05},
+ {0x0303, 0x02},
+ {0x0305, 0x04},
+ {0x0306, 0x00},
+ {0x0307, 0xc8},
+ {0x0309, 0x0a},
+ {0x030b, 0x01},
+ {0x030d, 0x02},
+ {0x030e, 0x01},
+ {0x030f, 0x5e},
+ {0x0310, 0x00},
+ {0x0820, 0x12},
+ {0x0821, 0xc0},
+ {0x0822, 0x00},
+ {0x0823, 0x00},
+ {0x3e20, 0x01},
+ {0x3e37, 0x00},
+ {0x3f50, 0x00},
+ {0x3f56, 0x00},
+ {0x3f57, 0xe2},
+ {0x3c0a, 0x5a},
+ {0x3c0b, 0x55},
+ {0x3c0c, 0x28},
+ {0x3c0d, 0x07},
+ {0x3c0e, 0xff},
+ {0x3c0f, 0x00},
+ {0x3c10, 0x00},
+ {0x3c11, 0x02},
+ {0x3c12, 0x00},
+ {0x3c13, 0x03},
+ {0x3c14, 0x00},
+ {0x3c15, 0x00},
+ {0x3c16, 0x0c},
+ {0x3c17, 0x0c},
+ {0x3c18, 0x0c},
+ {0x3c19, 0x0a},
+ {0x3c1a, 0x0a},
+ {0x3c1b, 0x0a},
+ {0x3c1c, 0x00},
+ {0x3c1d, 0x00},
+ {0x3c1e, 0x00},
+ {0x3c1f, 0x00},
+ {0x3c20, 0x00},
+ {0x3c21, 0x00},
+ {0x3c22, 0x3f},
+ {0x3c23, 0x0a},
+ {0x3e35, 0x01},
+ {0x3f4a, 0x03},
+ {0x3f4b, 0xbf},
+ {0x3f26, 0x00},
+ {0x0202, 0x0d},
+ {0x0203, 0xc4},
+ {0x0204, 0x00},
+ {0x0205, 0x00},
+ {0x020e, 0x01},
+ {0x020f, 0x00},
+ {0x0210, 0x01},
+ {0x0211, 0x00},
+ {0x0212, 0x01},
+ {0x0213, 0x00},
+ {0x0214, 0x01},
+ {0x0215, 0x00},
+ {0xbcf1, 0x00},
+};
+
+/* Supported sensor mode configurations */
+static const struct imx412_mode supported_mode = {
+ .width = 4056,
+ .height = 3040,
+ .hblank = 456,
+ .vblank = 506,
+ .vblank_min = 506,
+ .vblank_max = 32420,
+ .pclk = 480000000,
+ .link_freq_idx = 0,
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_4056x3040_regs),
+ .regs = mode_4056x3040_regs,
+ },
+};
+
+/**
+ * to_imx412() - imx412 V4L2 sub-device to imx412 device.
+ * @subdev: pointer to imx412 V4L2 sub-device
+ *
+ * Return: pointer to imx412 device
+ */
+static inline struct imx412 *to_imx412(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct imx412, sd);
+}
+
+/**
+ * imx412_read_reg() - Read registers.
+ * @imx412: pointer to imx412 device
+ * @reg: register address
+ * @len: length of bytes to read. Max supported bytes is 4
+ * @val: pointer to register value to be filled.
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_read_reg(struct imx412 *imx412, u16 reg, u32 len, u32 *val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx412->sd);
+ struct i2c_msg msgs[2] = {0};
+ u8 addr_buf[2] = {0};
+ u8 data_buf[4] = {0};
+ int ret;
+
+ if (WARN_ON(len > 4))
+ return -EINVAL;
+
+ put_unaligned_be16(reg, addr_buf);
+
+ /* Write register address */
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = ARRAY_SIZE(addr_buf);
+ msgs[0].buf = addr_buf;
+
+ /* Read data from register */
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = &data_buf[4 - len];
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs))
+ return -EIO;
+
+ *val = get_unaligned_be32(data_buf);
+
+ return 0;
+}
+
+/**
+ * imx412_write_reg() - Write register
+ * @imx412: pointer to imx412 device
+ * @reg: register address
+ * @len: length of bytes. Max supported bytes is 4
+ * @val: register value
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_write_reg(struct imx412 *imx412, u16 reg, u32 len, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx412->sd);
+ u8 buf[6] = {0};
+
+ if (WARN_ON(len > 4))
+ return -EINVAL;
+
+ put_unaligned_be16(reg, buf);
+ put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
+ if (i2c_master_send(client, buf, len + 2) != len + 2)
+ return -EIO;
+
+ return 0;
+}
+
+/**
+ * imx412_write_regs() - Write a list of registers
+ * @imx412: pointer to imx412 device
+ * @regs: list of registers to be written
+ * @len: length of registers array
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_write_regs(struct imx412 *imx412,
+ const struct imx412_reg *regs, u32 len)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < len; i++) {
+ ret = imx412_write_reg(imx412, regs[i].address, 1, regs[i].val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * imx412_update_controls() - Update control ranges based on streaming mode
+ * @imx412: pointer to imx412 device
+ * @mode: pointer to imx412_mode sensor mode
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_update_controls(struct imx412 *imx412,
+ const struct imx412_mode *mode)
+{
+ int ret;
+
+ ret = __v4l2_ctrl_s_ctrl(imx412->link_freq_ctrl, mode->link_freq_idx);
+ if (ret)
+ return ret;
+
+ ret = __v4l2_ctrl_s_ctrl(imx412->hblank_ctrl, mode->hblank);
+ if (ret)
+ return ret;
+
+ return __v4l2_ctrl_modify_range(imx412->vblank_ctrl, mode->vblank_min,
+ mode->vblank_max, 1, mode->vblank);
+}
+
+/**
+ * imx412_update_exp_gain() - Set updated exposure and gain
+ * @imx412: pointer to imx412 device
+ * @exposure: updated exposure value
+ * @gain: updated analog gain value
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain)
+{
+ u32 lpfr, shutter;
+ int ret;
+
+ lpfr = imx412->vblank + imx412->cur_mode->height;
+ shutter = lpfr - exposure;
+
+ dev_dbg(imx412->dev, "Set exp %u, analog gain %u, shutter %u, lpfr %u",
+ exposure, gain, shutter, lpfr);
+
+ ret = imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 1);
+ if (ret)
+ return ret;
+
+ ret = imx412_write_reg(imx412, IMX412_REG_LPFR, 2, lpfr);
+ if (ret)
+ goto error_release_group_hold;
+
+ ret = imx412_write_reg(imx412, IMX412_REG_EXPOSURE_CIT, 2, shutter);
+ if (ret)
+ goto error_release_group_hold;
+
+ ret = imx412_write_reg(imx412, IMX412_REG_AGAIN, 2, gain);
+
+error_release_group_hold:
+ imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 0);
+
+ return ret;
+}
+
+/**
+ * imx412_set_ctrl() - Set subdevice control
+ * @ctrl: pointer to v4l2_ctrl structure
+ *
+ * Supported controls:
+ * - V4L2_CID_VBLANK
+ * - cluster controls:
+ * - V4L2_CID_ANALOGUE_GAIN
+ * - V4L2_CID_EXPOSURE
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct imx412 *imx412 =
+ container_of(ctrl->handler, struct imx412, ctrl_handler);
+ u32 analog_gain;
+ u32 exposure;
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_VBLANK:
+ imx412->vblank = imx412->vblank_ctrl->val;
+
+ dev_dbg(imx412->dev, "Received vblank %u, new lpfr %u",
+ imx412->vblank,
+ imx412->vblank + imx412->cur_mode->height);
+
+ ret = __v4l2_ctrl_modify_range(imx412->exp_ctrl,
+ IMX412_EXPOSURE_MIN,
+ imx412->vblank +
+ imx412->cur_mode->height -
+ IMX412_EXPOSURE_OFFSET,
+ 1, IMX412_EXPOSURE_DEFAULT);
+ break;
+ case V4L2_CID_EXPOSURE:
+ /* Set controls only if sensor is in power on state */
+ if (!pm_runtime_get_if_in_use(imx412->dev))
+ return 0;
+
+ exposure = ctrl->val;
+ analog_gain = imx412->again_ctrl->val;
+
+ dev_dbg(imx412->dev, "Received exp %u, analog gain %u",
+ exposure, analog_gain);
+
+ ret = imx412_update_exp_gain(imx412, exposure, analog_gain);
+
+ pm_runtime_put(imx412->dev);
+
+ break;
+ default:
+ dev_err(imx412->dev, "Invalid control %d", ctrl->id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/* V4l2 subdevice control ops*/
+static const struct v4l2_ctrl_ops imx412_ctrl_ops = {
+ .s_ctrl = imx412_set_ctrl,
+};
+
+/**
+ * imx412_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
+ * @sd: pointer to imx412 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @code: V4L2 sub-device code enumeration need to be filled
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ code->code = supported_mode.code;
+
+ return 0;
+}
+
+/**
+ * imx412_enum_frame_size() - Enumerate V4L2 sub-device frame sizes
+ * @sd: pointer to imx412 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fsize: V4L2 sub-device size enumeration need to be filled
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fsize)
+{
+ if (fsize->index > 0)
+ return -EINVAL;
+
+ if (fsize->code != supported_mode.code)
+ return -EINVAL;
+
+ fsize->min_width = supported_mode.width;
+ fsize->max_width = fsize->min_width;
+ fsize->min_height = supported_mode.height;
+ fsize->max_height = fsize->min_height;
+
+ return 0;
+}
+
+/**
+ * imx412_fill_pad_format() - Fill subdevice pad format
+ * from selected sensor mode
+ * @imx412: pointer to imx412 device
+ * @mode: pointer to imx412_mode sensor mode
+ * @fmt: V4L2 sub-device format need to be filled
+ */
+static void imx412_fill_pad_format(struct imx412 *imx412,
+ const struct imx412_mode *mode,
+ struct v4l2_subdev_format *fmt)
+{
+ fmt->format.width = mode->width;
+ fmt->format.height = mode->height;
+ fmt->format.code = mode->code;
+ fmt->format.field = V4L2_FIELD_NONE;
+ fmt->format.colorspace = V4L2_COLORSPACE_RAW;
+ fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ fmt->format.quantization = V4L2_QUANTIZATION_DEFAULT;
+ fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
+}
+
+/**
+ * imx412_get_pad_format() - Get subdevice pad format
+ * @sd: pointer to imx412 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fmt: V4L2 sub-device format need to be set
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_get_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx412 *imx412 = to_imx412(sd);
+
+ mutex_lock(&imx412->mutex);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *framefmt;
+
+ framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ fmt->format = *framefmt;
+ } else {
+ imx412_fill_pad_format(imx412, imx412->cur_mode, fmt);
+ }
+
+ mutex_unlock(&imx412->mutex);
+
+ return 0;
+}
+
+/**
+ * imx412_set_pad_format() - Set subdevice pad format
+ * @sd: pointer to imx412 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fmt: V4L2 sub-device format need to be set
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx412 *imx412 = to_imx412(sd);
+ const struct imx412_mode *mode;
+ int ret = 0;
+
+ mutex_lock(&imx412->mutex);
+
+ mode = &supported_mode;
+ imx412_fill_pad_format(imx412, mode, fmt);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *framefmt;
+
+ framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ *framefmt = fmt->format;
+ } else {
+ ret = imx412_update_controls(imx412, mode);
+ if (!ret)
+ imx412->cur_mode = mode;
+ }
+
+ mutex_unlock(&imx412->mutex);
+
+ return ret;
+}
+
+/**
+ * imx412_init_pad_cfg() - Initialize sub-device pad configuration
+ * @sd: pointer to imx412 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_init_pad_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ struct imx412 *imx412 = to_imx412(sd);
+ struct v4l2_subdev_format fmt = { 0 };
+
+ fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+ imx412_fill_pad_format(imx412, &supported_mode, &fmt);
+
+ return imx412_set_pad_format(sd, sd_state, &fmt);
+}
+
+/**
+ * imx412_start_streaming() - Start sensor stream
+ * @imx412: pointer to imx412 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_start_streaming(struct imx412 *imx412)
+{
+ const struct imx412_reg_list *reg_list;
+ int ret;
+
+ /* Write sensor mode registers */
+ reg_list = &imx412->cur_mode->reg_list;
+ ret = imx412_write_regs(imx412, reg_list->regs,
+ reg_list->num_of_regs);
+ if (ret) {
+ dev_err(imx412->dev, "fail to write initial registers");
+ return ret;
+ }
+
+ /* Setup handler will write actual exposure and gain */
+ ret = __v4l2_ctrl_handler_setup(imx412->sd.ctrl_handler);
+ if (ret) {
+ dev_err(imx412->dev, "fail to setup handler");
+ return ret;
+ }
+
+ /* Delay is required before streaming*/
+ usleep_range(7400, 8000);
+
+ /* Start streaming */
+ ret = imx412_write_reg(imx412, IMX412_REG_MODE_SELECT,
+ 1, IMX412_MODE_STREAMING);
+ if (ret) {
+ dev_err(imx412->dev, "fail to start streaming");
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * imx412_stop_streaming() - Stop sensor stream
+ * @imx412: pointer to imx412 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_stop_streaming(struct imx412 *imx412)
+{
+ return imx412_write_reg(imx412, IMX412_REG_MODE_SELECT,
+ 1, IMX412_MODE_STANDBY);
+}
+
+/**
+ * imx412_set_stream() - Enable sensor streaming
+ * @sd: pointer to imx412 subdevice
+ * @enable: set to enable sensor streaming
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct imx412 *imx412 = to_imx412(sd);
+ int ret;
+
+ mutex_lock(&imx412->mutex);
+
+ if (imx412->streaming == enable) {
+ mutex_unlock(&imx412->mutex);
+ return 0;
+ }
+
+ if (enable) {
+ ret = pm_runtime_resume_and_get(imx412->dev);
+ if (ret)
+ goto error_unlock;
+
+ ret = imx412_start_streaming(imx412);
+ if (ret)
+ goto error_power_off;
+ } else {
+ imx412_stop_streaming(imx412);
+ pm_runtime_put(imx412->dev);
+ }
+
+ imx412->streaming = enable;
+
+ mutex_unlock(&imx412->mutex);
+
+ return 0;
+
+error_power_off:
+ pm_runtime_put(imx412->dev);
+error_unlock:
+ mutex_unlock(&imx412->mutex);
+
+ return ret;
+}
+
+/**
+ * imx412_detect() - Detect imx412 sensor
+ * @imx412: pointer to imx412 device
+ *
+ * Return: 0 if successful, -EIO if sensor id does not match
+ */
+static int imx412_detect(struct imx412 *imx412)
+{
+ int ret;
+ u32 val;
+
+ ret = imx412_read_reg(imx412, IMX412_REG_ID, 2, &val);
+ if (ret)
+ return ret;
+
+ if (val != IMX412_ID) {
+ dev_err(imx412->dev, "chip id mismatch: %x!=%x",
+ IMX412_ID, val);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+/**
+ * imx412_parse_hw_config() - Parse HW configuration and check if supported
+ * @imx412: pointer to imx412 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_parse_hw_config(struct imx412 *imx412)
+{
+ struct fwnode_handle *fwnode = dev_fwnode(imx412->dev);
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ struct fwnode_handle *ep;
+ unsigned long rate;
+ unsigned int i;
+ int ret;
+
+ if (!fwnode)
+ return -ENXIO;
+
+ /* Request optional reset pin */
+ imx412->reset_gpio = devm_gpiod_get_optional(imx412->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(imx412->reset_gpio)) {
+ dev_err(imx412->dev, "failed to get reset gpio %ld",
+ PTR_ERR(imx412->reset_gpio));
+ return PTR_ERR(imx412->reset_gpio);
+ }
+
+ /* Get sensor input clock */
+ imx412->inclk = devm_clk_get(imx412->dev, NULL);
+ if (IS_ERR(imx412->inclk)) {
+ dev_err(imx412->dev, "could not get inclk");
+ return PTR_ERR(imx412->inclk);
+ }
+
+ rate = clk_get_rate(imx412->inclk);
+ if (rate != IMX412_INCLK_RATE) {
+ dev_err(imx412->dev, "inclk frequency mismatch");
+ return -EINVAL;
+ }
+
+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+ if (!ep)
+ return -ENXIO;
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ fwnode_handle_put(ep);
+ if (ret)
+ return ret;
+
+ if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX412_NUM_DATA_LANES) {
+ dev_err(imx412->dev,
+ "number of CSI2 data lanes %d is not supported",
+ bus_cfg.bus.mipi_csi2.num_data_lanes);
+ ret = -EINVAL;
+ goto done_endpoint_free;
+ }
+
+ if (!bus_cfg.nr_of_link_frequencies) {
+ dev_err(imx412->dev, "no link frequencies defined");
+ ret = -EINVAL;
+ goto done_endpoint_free;
+ }
+
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
+ if (bus_cfg.link_frequencies[i] == IMX412_LINK_FREQ)
+ goto done_endpoint_free;
+
+ ret = -EINVAL;
+
+done_endpoint_free:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+
+ return ret;
+}
+
+/* V4l2 subdevice ops */
+static const struct v4l2_subdev_video_ops imx412_video_ops = {
+ .s_stream = imx412_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops imx412_pad_ops = {
+ .init_cfg = imx412_init_pad_cfg,
+ .enum_mbus_code = imx412_enum_mbus_code,
+ .enum_frame_size = imx412_enum_frame_size,
+ .get_fmt = imx412_get_pad_format,
+ .set_fmt = imx412_set_pad_format,
+};
+
+static const struct v4l2_subdev_ops imx412_subdev_ops = {
+ .video = &imx412_video_ops,
+ .pad = &imx412_pad_ops,
+};
+
+/**
+ * imx412_power_on() - Sensor power on sequence
+ * @dev: pointer to i2c device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct imx412 *imx412 = to_imx412(sd);
+ int ret;
+
+ gpiod_set_value_cansleep(imx412->reset_gpio, 1);
+
+ ret = clk_prepare_enable(imx412->inclk);
+ if (ret) {
+ dev_err(imx412->dev, "fail to enable inclk");
+ goto error_reset;
+ }
+
+ usleep_range(1000, 1200);
+
+ return 0;
+
+error_reset:
+ gpiod_set_value_cansleep(imx412->reset_gpio, 0);
+
+ return ret;
+}
+
+/**
+ * imx412_power_off() - Sensor power off sequence
+ * @dev: pointer to i2c device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct imx412 *imx412 = to_imx412(sd);
+
+ gpiod_set_value_cansleep(imx412->reset_gpio, 0);
+
+ clk_disable_unprepare(imx412->inclk);
+
+ return 0;
+}
+
+/**
+ * imx412_init_controls() - Initialize sensor subdevice controls
+ * @imx412: pointer to imx412 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_init_controls(struct imx412 *imx412)
+{
+ struct v4l2_ctrl_handler *ctrl_hdlr = &imx412->ctrl_handler;
+ const struct imx412_mode *mode = imx412->cur_mode;
+ u32 lpfr;
+ int ret;
+
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6);
+ if (ret)
+ return ret;
+
+ /* Serialize controls with sensor device */
+ ctrl_hdlr->lock = &imx412->mutex;
+
+ /* Initialize exposure and gain */
+ lpfr = mode->vblank + mode->height;
+ imx412->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx412_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ IMX412_EXPOSURE_MIN,
+ lpfr - IMX412_EXPOSURE_OFFSET,
+ IMX412_EXPOSURE_STEP,
+ IMX412_EXPOSURE_DEFAULT);
+
+ imx412->again_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx412_ctrl_ops,
+ V4L2_CID_ANALOGUE_GAIN,
+ IMX412_AGAIN_MIN,
+ IMX412_AGAIN_MAX,
+ IMX412_AGAIN_STEP,
+ IMX412_AGAIN_DEFAULT);
+
+ v4l2_ctrl_cluster(2, &imx412->exp_ctrl);
+
+ imx412->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx412_ctrl_ops,
+ V4L2_CID_VBLANK,
+ mode->vblank_min,
+ mode->vblank_max,
+ 1, mode->vblank);
+
+ /* Read only controls */
+ imx412->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx412_ctrl_ops,
+ V4L2_CID_PIXEL_RATE,
+ mode->pclk, mode->pclk,
+ 1, mode->pclk);
+
+ imx412->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr,
+ &imx412_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(link_freq) -
+ 1,
+ mode->link_freq_idx,
+ link_freq);
+ if (imx412->link_freq_ctrl)
+ imx412->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ imx412->hblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &imx412_ctrl_ops,
+ V4L2_CID_HBLANK,
+ IMX412_REG_MIN,
+ IMX412_REG_MAX,
+ 1, mode->hblank);
+ if (imx412->hblank_ctrl)
+ imx412->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ if (ctrl_hdlr->error) {
+ dev_err(imx412->dev, "control init failed: %d",
+ ctrl_hdlr->error);
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+ return ctrl_hdlr->error;
+ }
+
+ imx412->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+}
+
+/**
+ * imx412_probe() - I2C client device binding
+ * @client: pointer to i2c client device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_probe(struct i2c_client *client)
+{
+ struct imx412 *imx412;
+ int ret;
+
+ imx412 = devm_kzalloc(&client->dev, sizeof(*imx412), GFP_KERNEL);
+ if (!imx412)
+ return -ENOMEM;
+
+ imx412->dev = &client->dev;
+
+ /* Initialize subdev */
+ v4l2_i2c_subdev_init(&imx412->sd, client, &imx412_subdev_ops);
+
+ ret = imx412_parse_hw_config(imx412);
+ if (ret) {
+ dev_err(imx412->dev, "HW configuration is not supported");
+ return ret;
+ }
+
+ mutex_init(&imx412->mutex);
+
+ ret = imx412_power_on(imx412->dev);
+ if (ret) {
+ dev_err(imx412->dev, "failed to power-on the sensor");
+ goto error_mutex_destroy;
+ }
+
+ /* Check module identity */
+ ret = imx412_detect(imx412);
+ if (ret) {
+ dev_err(imx412->dev, "failed to find sensor: %d", ret);
+ goto error_power_off;
+ }
+
+ /* Set default mode to max resolution */
+ imx412->cur_mode = &supported_mode;
+ imx412->vblank = imx412->cur_mode->vblank;
+
+ ret = imx412_init_controls(imx412);
+ if (ret) {
+ dev_err(imx412->dev, "failed to init controls: %d", ret);
+ goto error_power_off;
+ }
+
+ /* Initialize subdev */
+ imx412->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ imx412->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ /* Initialize source pad */
+ imx412->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&imx412->sd.entity, 1, &imx412->pad);
+ if (ret) {
+ dev_err(imx412->dev, "failed to init entity pads: %d", ret);
+ goto error_handler_free;
+ }
+
+ ret = v4l2_async_register_subdev_sensor(&imx412->sd);
+ if (ret < 0) {
+ dev_err(imx412->dev,
+ "failed to register async subdev: %d", ret);
+ goto error_media_entity;
+ }
+
+ pm_runtime_set_active(imx412->dev);
+ pm_runtime_enable(imx412->dev);
+ pm_runtime_idle(imx412->dev);
+
+ return 0;
+
+error_media_entity:
+ media_entity_cleanup(&imx412->sd.entity);
+error_handler_free:
+ v4l2_ctrl_handler_free(imx412->sd.ctrl_handler);
+error_power_off:
+ imx412_power_off(imx412->dev);
+error_mutex_destroy:
+ mutex_destroy(&imx412->mutex);
+
+ return ret;
+}
+
+/**
+ * imx412_remove() - I2C client device unbinding
+ * @client: pointer to I2C client device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx412_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct imx412 *imx412 = to_imx412(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev))
+ imx412_power_off(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+
+ mutex_destroy(&imx412->mutex);
+
+ return 0;
+}
+
+static const struct dev_pm_ops imx412_pm_ops = {
+ SET_RUNTIME_PM_OPS(imx412_power_off, imx412_power_on, NULL)
+};
+
+static const struct of_device_id imx412_of_match[] = {
+ { .compatible = "sony,imx412" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, imx412_of_match);
+
+static struct i2c_driver imx412_driver = {
+ .probe_new = imx412_probe,
+ .remove = imx412_remove,
+ .driver = {
+ .name = "imx412",
+ .pm = &imx412_pm_ops,
+ .of_match_table = imx412_of_match,
+ },
+};
+
+module_i2c_driver(imx412_driver);
+
+MODULE_DESCRIPTION("Sony imx412 sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 599369a3d192..934c9d65cb09 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -51,7 +51,7 @@
#define OV2740_REG_MWB_R_GAIN 0x500a
#define OV2740_REG_MWB_G_GAIN 0x500c
#define OV2740_REG_MWB_B_GAIN 0x500e
-#define OV2740_DGTL_GAIN_MIN 0
+#define OV2740_DGTL_GAIN_MIN 1024
#define OV2740_DGTL_GAIN_MAX 4095
#define OV2740_DGTL_GAIN_STEP 1
#define OV2740_DGTL_GAIN_DEFAULT 1024
@@ -61,6 +61,12 @@
#define OV2740_TEST_PATTERN_ENABLE BIT(7)
#define OV2740_TEST_PATTERN_BAR_SHIFT 2
+/* Group Access */
+#define OV2740_REG_GROUP_ACCESS 0x3208
+#define OV2740_GROUP_HOLD_START 0x0
+#define OV2740_GROUP_HOLD_END 0x10
+#define OV2740_GROUP_HOLD_LAUNCH 0xa0
+
/* ISP CTRL00 */
#define OV2740_REG_ISP_CTRL00 0x5000
/* ISP CTRL01 */
@@ -438,6 +444,11 @@ static int ov2740_update_digital_gain(struct ov2740 *ov2740, u32 d_gain)
{
int ret = 0;
+ ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
+ OV2740_GROUP_HOLD_START);
+ if (ret)
+ return ret;
+
ret = ov2740_write_reg(ov2740, OV2740_REG_MWB_R_GAIN, 2, d_gain);
if (ret)
return ret;
@@ -446,7 +457,18 @@ static int ov2740_update_digital_gain(struct ov2740 *ov2740, u32 d_gain)
if (ret)
return ret;
- return ov2740_write_reg(ov2740, OV2740_REG_MWB_B_GAIN, 2, d_gain);
+ ret = ov2740_write_reg(ov2740, OV2740_REG_MWB_B_GAIN, 2, d_gain);
+ if (ret)
+ return ret;
+
+ ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
+ OV2740_GROUP_HOLD_END);
+ if (ret)
+ return ret;
+
+ ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
+ OV2740_GROUP_HOLD_LAUNCH);
+ return ret;
}
static int ov2740_test_pattern(struct ov2740 *ov2740, u32 pattern)
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index f6e1e51e0375..ddbd71394db3 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -135,7 +135,9 @@ struct ov5640_pixfmt {
static const struct ov5640_pixfmt ov5640_formats[] = {
{ MEDIA_BUS_FMT_JPEG_1X8, V4L2_COLORSPACE_JPEG, },
{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB, },
+ { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB, },
+ { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB, },
@@ -2338,11 +2340,13 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
u8 fmt, mux;
switch (format->code) {
+ case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_UYVY8_2X8:
/* YUV422, UYVY */
fmt = 0x3f;
mux = OV5640_FMT_MUX_YUV422;
break;
+ case MEDIA_BUS_FMT_YUYV8_1X16:
case MEDIA_BUS_FMT_YUYV8_2X8:
/* YUV422, YUYV */
fmt = 0x30;
diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c
index 88e19f30d376..aa74744b91c7 100644
--- a/drivers/media/i2c/ov8856.c
+++ b/drivers/media/i2c/ov8856.c
@@ -2304,25 +2304,26 @@ static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev)
clk_set_rate(ov8856->xvclk, xvclk_rate);
xvclk_rate = clk_get_rate(ov8856->xvclk);
+
+ ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ov8856->reset_gpio))
+ return PTR_ERR(ov8856->reset_gpio);
+
+ for (i = 0; i < ARRAY_SIZE(ov8856_supply_names); i++)
+ ov8856->supplies[i].supply = ov8856_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev,
+ ARRAY_SIZE(ov8856_supply_names),
+ ov8856->supplies);
+ if (ret)
+ return ret;
}
if (xvclk_rate != OV8856_XVCLK_19_2)
dev_warn(dev, "external clock rate %u is unsupported",
xvclk_rate);
- ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset",
- GPIOD_OUT_LOW);
- if (IS_ERR(ov8856->reset_gpio))
- return PTR_ERR(ov8856->reset_gpio);
-
- for (i = 0; i < ARRAY_SIZE(ov8856_supply_names); i++)
- ov8856->supplies[i].supply = ov8856_supply_names[i];
-
- ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ov8856_supply_names),
- ov8856->supplies);
- if (ret)
- return ret;
-
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
if (!ep)
return -ENXIO;
diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
new file mode 100644
index 000000000000..2e0b315801e5
--- /dev/null
+++ b/drivers/media/i2c/ov9282.c
@@ -0,0 +1,1137 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * OmniVision ov9282 Camera Sensor Driver
+ *
+ * Copyright (C) 2021 Intel Corporation
+ */
+#include <asm/unaligned.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+/* Streaming Mode */
+#define OV9282_REG_MODE_SELECT 0x0100
+#define OV9282_MODE_STANDBY 0x00
+#define OV9282_MODE_STREAMING 0x01
+
+/* Lines per frame */
+#define OV9282_REG_LPFR 0x380e
+
+/* Chip ID */
+#define OV9282_REG_ID 0x300a
+#define OV9282_ID 0x9281
+
+/* Exposure control */
+#define OV9282_REG_EXPOSURE 0x3500
+#define OV9282_EXPOSURE_MIN 1
+#define OV9282_EXPOSURE_OFFSET 12
+#define OV9282_EXPOSURE_STEP 1
+#define OV9282_EXPOSURE_DEFAULT 0x0282
+
+/* Analog gain control */
+#define OV9282_REG_AGAIN 0x3509
+#define OV9282_AGAIN_MIN 0x10
+#define OV9282_AGAIN_MAX 0xff
+#define OV9282_AGAIN_STEP 1
+#define OV9282_AGAIN_DEFAULT 0x10
+
+/* Group hold register */
+#define OV9282_REG_HOLD 0x3308
+
+/* Input clock rate */
+#define OV9282_INCLK_RATE 24000000
+
+/* CSI2 HW configuration */
+#define OV9282_LINK_FREQ 400000000
+#define OV9282_NUM_DATA_LANES 2
+
+#define OV9282_REG_MIN 0x00
+#define OV9282_REG_MAX 0xfffff
+
+/**
+ * struct ov9282_reg - ov9282 sensor register
+ * @address: Register address
+ * @val: Register value
+ */
+struct ov9282_reg {
+ u16 address;
+ u8 val;
+};
+
+/**
+ * struct ov9282_reg_list - ov9282 sensor register list
+ * @num_of_regs: Number of registers in the list
+ * @regs: Pointer to register list
+ */
+struct ov9282_reg_list {
+ u32 num_of_regs;
+ const struct ov9282_reg *regs;
+};
+
+/**
+ * struct ov9282_mode - ov9282 sensor mode structure
+ * @width: Frame width
+ * @height: Frame height
+ * @code: Format code
+ * @hblank: Horizontal blanking in lines
+ * @vblank: Vertical blanking in lines
+ * @vblank_min: Minimum vertical blanking in lines
+ * @vblank_max: Maximum vertical blanking in lines
+ * @pclk: Sensor pixel clock
+ * @link_freq_idx: Link frequency index
+ * @reg_list: Register list for sensor mode
+ */
+struct ov9282_mode {
+ u32 width;
+ u32 height;
+ u32 code;
+ u32 hblank;
+ u32 vblank;
+ u32 vblank_min;
+ u32 vblank_max;
+ u64 pclk;
+ u32 link_freq_idx;
+ struct ov9282_reg_list reg_list;
+};
+
+/**
+ * struct ov9282 - ov9282 sensor device structure
+ * @dev: Pointer to generic device
+ * @client: Pointer to i2c client
+ * @sd: V4L2 sub-device
+ * @pad: Media pad. Only one pad supported
+ * @reset_gpio: Sensor reset gpio
+ * @inclk: Sensor input clock
+ * @ctrl_handler: V4L2 control handler
+ * @link_freq_ctrl: Pointer to link frequency control
+ * @pclk_ctrl: Pointer to pixel clock control
+ * @hblank_ctrl: Pointer to horizontal blanking control
+ * @vblank_ctrl: Pointer to vertical blanking control
+ * @exp_ctrl: Pointer to exposure control
+ * @again_ctrl: Pointer to analog gain control
+ * @vblank: Vertical blanking in lines
+ * @cur_mode: Pointer to current selected sensor mode
+ * @mutex: Mutex for serializing sensor controls
+ * @streaming: Flag indicating streaming state
+ */
+struct ov9282 {
+ struct device *dev;
+ struct i2c_client *client;
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct gpio_desc *reset_gpio;
+ struct clk *inclk;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *link_freq_ctrl;
+ struct v4l2_ctrl *pclk_ctrl;
+ struct v4l2_ctrl *hblank_ctrl;
+ struct v4l2_ctrl *vblank_ctrl;
+ struct {
+ struct v4l2_ctrl *exp_ctrl;
+ struct v4l2_ctrl *again_ctrl;
+ };
+ u32 vblank;
+ const struct ov9282_mode *cur_mode;
+ struct mutex mutex;
+ bool streaming;
+};
+
+static const s64 link_freq[] = {
+ OV9282_LINK_FREQ,
+};
+
+/* Sensor mode registers */
+static const struct ov9282_reg mode_1280x720_regs[] = {
+ {0x0302, 0x32},
+ {0x030d, 0x50},
+ {0x030e, 0x02},
+ {0x3001, 0x00},
+ {0x3004, 0x00},
+ {0x3005, 0x00},
+ {0x3006, 0x04},
+ {0x3011, 0x0a},
+ {0x3013, 0x18},
+ {0x301c, 0xf0},
+ {0x3022, 0x01},
+ {0x3030, 0x10},
+ {0x3039, 0x32},
+ {0x303a, 0x00},
+ {0x3500, 0x00},
+ {0x3501, 0x5f},
+ {0x3502, 0x1e},
+ {0x3503, 0x08},
+ {0x3505, 0x8c},
+ {0x3507, 0x03},
+ {0x3508, 0x00},
+ {0x3509, 0x10},
+ {0x3610, 0x80},
+ {0x3611, 0xa0},
+ {0x3620, 0x6e},
+ {0x3632, 0x56},
+ {0x3633, 0x78},
+ {0x3666, 0x00},
+ {0x366f, 0x5a},
+ {0x3680, 0x84},
+ {0x3712, 0x80},
+ {0x372d, 0x22},
+ {0x3731, 0x80},
+ {0x3732, 0x30},
+ {0x3778, 0x00},
+ {0x377d, 0x22},
+ {0x3788, 0x02},
+ {0x3789, 0xa4},
+ {0x378a, 0x00},
+ {0x378b, 0x4a},
+ {0x3799, 0x20},
+ {0x3800, 0x00},
+ {0x3801, 0x00},
+ {0x3802, 0x00},
+ {0x3803, 0x00},
+ {0x3804, 0x05},
+ {0x3805, 0x0f},
+ {0x3806, 0x02},
+ {0x3807, 0xdf},
+ {0x3808, 0x05},
+ {0x3809, 0x00},
+ {0x380a, 0x02},
+ {0x380b, 0xd0},
+ {0x380c, 0x05},
+ {0x380d, 0xfa},
+ {0x380e, 0x06},
+ {0x380f, 0xce},
+ {0x3810, 0x00},
+ {0x3811, 0x08},
+ {0x3812, 0x00},
+ {0x3813, 0x08},
+ {0x3814, 0x11},
+ {0x3815, 0x11},
+ {0x3820, 0x3c},
+ {0x3821, 0x84},
+ {0x3881, 0x42},
+ {0x38a8, 0x02},
+ {0x38a9, 0x80},
+ {0x38b1, 0x00},
+ {0x38c4, 0x00},
+ {0x38c5, 0xc0},
+ {0x38c6, 0x04},
+ {0x38c7, 0x80},
+ {0x3920, 0xff},
+ {0x4003, 0x40},
+ {0x4008, 0x02},
+ {0x4009, 0x05},
+ {0x400c, 0x00},
+ {0x400d, 0x03},
+ {0x4010, 0x40},
+ {0x4043, 0x40},
+ {0x4307, 0x30},
+ {0x4317, 0x00},
+ {0x4501, 0x00},
+ {0x4507, 0x00},
+ {0x4509, 0x80},
+ {0x450a, 0x08},
+ {0x4601, 0x04},
+ {0x470f, 0x00},
+ {0x4f07, 0x00},
+ {0x4800, 0x20},
+ {0x5000, 0x9f},
+ {0x5001, 0x00},
+ {0x5e00, 0x00},
+ {0x5d00, 0x07},
+ {0x5d01, 0x00},
+ {0x0101, 0x01},
+ {0x1000, 0x03},
+ {0x5a08, 0x84},
+};
+
+/* Supported sensor mode configurations */
+static const struct ov9282_mode supported_mode = {
+ .width = 1280,
+ .height = 720,
+ .hblank = 250,
+ .vblank = 1022,
+ .vblank_min = 151,
+ .vblank_max = 51540,
+ .pclk = 160000000,
+ .link_freq_idx = 0,
+ .code = MEDIA_BUS_FMT_Y10_1X10,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
+ .regs = mode_1280x720_regs,
+ },
+};
+
+/**
+ * to_ov9282() - ov9282 V4L2 sub-device to ov9282 device.
+ * @subdev: pointer to ov9282 V4L2 sub-device
+ *
+ * Return: pointer to ov9282 device
+ */
+static inline struct ov9282 *to_ov9282(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct ov9282, sd);
+}
+
+/**
+ * ov9282_read_reg() - Read registers.
+ * @ov9282: pointer to ov9282 device
+ * @reg: register address
+ * @len: length of bytes to read. Max supported bytes is 4
+ * @val: pointer to register value to be filled.
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_read_reg(struct ov9282 *ov9282, u16 reg, u32 len, u32 *val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd);
+ struct i2c_msg msgs[2] = {0};
+ u8 addr_buf[2] = {0};
+ u8 data_buf[4] = {0};
+ int ret;
+
+ if (WARN_ON(len > 4))
+ return -EINVAL;
+
+ put_unaligned_be16(reg, addr_buf);
+
+ /* Write register address */
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = ARRAY_SIZE(addr_buf);
+ msgs[0].buf = addr_buf;
+
+ /* Read data from register */
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = &data_buf[4 - len];
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs))
+ return -EIO;
+
+ *val = get_unaligned_be32(data_buf);
+
+ return 0;
+}
+
+/**
+ * ov9282_write_reg() - Write register
+ * @ov9282: pointer to ov9282 device
+ * @reg: register address
+ * @len: length of bytes. Max supported bytes is 4
+ * @val: register value
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_write_reg(struct ov9282 *ov9282, u16 reg, u32 len, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd);
+ u8 buf[6] = {0};
+
+ if (WARN_ON(len > 4))
+ return -EINVAL;
+
+ put_unaligned_be16(reg, buf);
+ put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
+ if (i2c_master_send(client, buf, len + 2) != len + 2)
+ return -EIO;
+
+ return 0;
+}
+
+/**
+ * ov9282_write_regs() - Write a list of registers
+ * @ov9282: pointer to ov9282 device
+ * @regs: list of registers to be written
+ * @len: length of registers array
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_write_regs(struct ov9282 *ov9282,
+ const struct ov9282_reg *regs, u32 len)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < len; i++) {
+ ret = ov9282_write_reg(ov9282, regs[i].address, 1, regs[i].val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ov9282_update_controls() - Update control ranges based on streaming mode
+ * @ov9282: pointer to ov9282 device
+ * @mode: pointer to ov9282_mode sensor mode
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_update_controls(struct ov9282 *ov9282,
+ const struct ov9282_mode *mode)
+{
+ int ret;
+
+ ret = __v4l2_ctrl_s_ctrl(ov9282->link_freq_ctrl, mode->link_freq_idx);
+ if (ret)
+ return ret;
+
+ ret = __v4l2_ctrl_s_ctrl(ov9282->hblank_ctrl, mode->hblank);
+ if (ret)
+ return ret;
+
+ return __v4l2_ctrl_modify_range(ov9282->vblank_ctrl, mode->vblank_min,
+ mode->vblank_max, 1, mode->vblank);
+}
+
+/**
+ * ov9282_update_exp_gain() - Set updated exposure and gain
+ * @ov9282: pointer to ov9282 device
+ * @exposure: updated exposure value
+ * @gain: updated analog gain value
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain)
+{
+ u32 lpfr;
+ int ret;
+
+ lpfr = ov9282->vblank + ov9282->cur_mode->height;
+
+ dev_dbg(ov9282->dev, "Set exp %u, analog gain %u, lpfr %u",
+ exposure, gain, lpfr);
+
+ ret = ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 1);
+ if (ret)
+ return ret;
+
+ ret = ov9282_write_reg(ov9282, OV9282_REG_LPFR, 2, lpfr);
+ if (ret)
+ goto error_release_group_hold;
+
+ ret = ov9282_write_reg(ov9282, OV9282_REG_EXPOSURE, 3, exposure << 4);
+ if (ret)
+ goto error_release_group_hold;
+
+ ret = ov9282_write_reg(ov9282, OV9282_REG_AGAIN, 1, gain);
+
+error_release_group_hold:
+ ov9282_write_reg(ov9282, OV9282_REG_HOLD, 1, 0);
+
+ return ret;
+}
+
+/**
+ * ov9282_set_ctrl() - Set subdevice control
+ * @ctrl: pointer to v4l2_ctrl structure
+ *
+ * Supported controls:
+ * - V4L2_CID_VBLANK
+ * - cluster controls:
+ * - V4L2_CID_ANALOGUE_GAIN
+ * - V4L2_CID_EXPOSURE
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ov9282 *ov9282 =
+ container_of(ctrl->handler, struct ov9282, ctrl_handler);
+ u32 analog_gain;
+ u32 exposure;
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_VBLANK:
+ ov9282->vblank = ov9282->vblank_ctrl->val;
+
+ dev_dbg(ov9282->dev, "Received vblank %u, new lpfr %u",
+ ov9282->vblank,
+ ov9282->vblank + ov9282->cur_mode->height);
+
+ ret = __v4l2_ctrl_modify_range(ov9282->exp_ctrl,
+ OV9282_EXPOSURE_MIN,
+ ov9282->vblank +
+ ov9282->cur_mode->height -
+ OV9282_EXPOSURE_OFFSET,
+ 1, OV9282_EXPOSURE_DEFAULT);
+ break;
+ case V4L2_CID_EXPOSURE:
+ /* Set controls only if sensor is in power on state */
+ if (!pm_runtime_get_if_in_use(ov9282->dev))
+ return 0;
+
+ exposure = ctrl->val;
+ analog_gain = ov9282->again_ctrl->val;
+
+ dev_dbg(ov9282->dev, "Received exp %u, analog gain %u",
+ exposure, analog_gain);
+
+ ret = ov9282_update_exp_gain(ov9282, exposure, analog_gain);
+
+ pm_runtime_put(ov9282->dev);
+
+ break;
+ default:
+ dev_err(ov9282->dev, "Invalid control %d", ctrl->id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/* V4l2 subdevice control ops*/
+static const struct v4l2_ctrl_ops ov9282_ctrl_ops = {
+ .s_ctrl = ov9282_set_ctrl,
+};
+
+/**
+ * ov9282_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
+ * @sd: pointer to ov9282 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @code: V4L2 sub-device code enumeration need to be filled
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ code->code = supported_mode.code;
+
+ return 0;
+}
+
+/**
+ * ov9282_enum_frame_size() - Enumerate V4L2 sub-device frame sizes
+ * @sd: pointer to ov9282 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fsize: V4L2 sub-device size enumeration need to be filled
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fsize)
+{
+ if (fsize->index > 0)
+ return -EINVAL;
+
+ if (fsize->code != supported_mode.code)
+ return -EINVAL;
+
+ fsize->min_width = supported_mode.width;
+ fsize->max_width = fsize->min_width;
+ fsize->min_height = supported_mode.height;
+ fsize->max_height = fsize->min_height;
+
+ return 0;
+}
+
+/**
+ * ov9282_fill_pad_format() - Fill subdevice pad format
+ * from selected sensor mode
+ * @ov9282: pointer to ov9282 device
+ * @mode: pointer to ov9282_mode sensor mode
+ * @fmt: V4L2 sub-device format need to be filled
+ */
+static void ov9282_fill_pad_format(struct ov9282 *ov9282,
+ const struct ov9282_mode *mode,
+ struct v4l2_subdev_format *fmt)
+{
+ fmt->format.width = mode->width;
+ fmt->format.height = mode->height;
+ fmt->format.code = mode->code;
+ fmt->format.field = V4L2_FIELD_NONE;
+ fmt->format.colorspace = V4L2_COLORSPACE_RAW;
+ fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ fmt->format.quantization = V4L2_QUANTIZATION_DEFAULT;
+ fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
+}
+
+/**
+ * ov9282_get_pad_format() - Get subdevice pad format
+ * @sd: pointer to ov9282 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fmt: V4L2 sub-device format need to be set
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_get_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct ov9282 *ov9282 = to_ov9282(sd);
+
+ mutex_lock(&ov9282->mutex);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *framefmt;
+
+ framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ fmt->format = *framefmt;
+ } else {
+ ov9282_fill_pad_format(ov9282, ov9282->cur_mode, fmt);
+ }
+
+ mutex_unlock(&ov9282->mutex);
+
+ return 0;
+}
+
+/**
+ * ov9282_set_pad_format() - Set subdevice pad format
+ * @sd: pointer to ov9282 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @fmt: V4L2 sub-device format need to be set
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct ov9282 *ov9282 = to_ov9282(sd);
+ const struct ov9282_mode *mode;
+ int ret = 0;
+
+ mutex_lock(&ov9282->mutex);
+
+ mode = &supported_mode;
+ ov9282_fill_pad_format(ov9282, mode, fmt);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *framefmt;
+
+ framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ *framefmt = fmt->format;
+ } else {
+ ret = ov9282_update_controls(ov9282, mode);
+ if (!ret)
+ ov9282->cur_mode = mode;
+ }
+
+ mutex_unlock(&ov9282->mutex);
+
+ return ret;
+}
+
+/**
+ * ov9282_init_pad_cfg() - Initialize sub-device pad configuration
+ * @sd: pointer to ov9282 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_init_pad_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ struct ov9282 *ov9282 = to_ov9282(sd);
+ struct v4l2_subdev_format fmt = { 0 };
+
+ fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+ ov9282_fill_pad_format(ov9282, &supported_mode, &fmt);
+
+ return ov9282_set_pad_format(sd, sd_state, &fmt);
+}
+
+/**
+ * ov9282_start_streaming() - Start sensor stream
+ * @ov9282: pointer to ov9282 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_start_streaming(struct ov9282 *ov9282)
+{
+ const struct ov9282_reg_list *reg_list;
+ int ret;
+
+ /* Write sensor mode registers */
+ reg_list = &ov9282->cur_mode->reg_list;
+ ret = ov9282_write_regs(ov9282, reg_list->regs, reg_list->num_of_regs);
+ if (ret) {
+ dev_err(ov9282->dev, "fail to write initial registers");
+ return ret;
+ }
+
+ /* Setup handler will write actual exposure and gain */
+ ret = __v4l2_ctrl_handler_setup(ov9282->sd.ctrl_handler);
+ if (ret) {
+ dev_err(ov9282->dev, "fail to setup handler");
+ return ret;
+ }
+
+ /* Start streaming */
+ ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
+ 1, OV9282_MODE_STREAMING);
+ if (ret) {
+ dev_err(ov9282->dev, "fail to start streaming");
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ov9282_stop_streaming() - Stop sensor stream
+ * @ov9282: pointer to ov9282 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_stop_streaming(struct ov9282 *ov9282)
+{
+ return ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
+ 1, OV9282_MODE_STANDBY);
+}
+
+/**
+ * ov9282_set_stream() - Enable sensor streaming
+ * @sd: pointer to ov9282 subdevice
+ * @enable: set to enable sensor streaming
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct ov9282 *ov9282 = to_ov9282(sd);
+ int ret;
+
+ mutex_lock(&ov9282->mutex);
+
+ if (ov9282->streaming == enable) {
+ mutex_unlock(&ov9282->mutex);
+ return 0;
+ }
+
+ if (enable) {
+ ret = pm_runtime_resume_and_get(ov9282->dev);
+ if (ret)
+ goto error_unlock;
+
+ ret = ov9282_start_streaming(ov9282);
+ if (ret)
+ goto error_power_off;
+ } else {
+ ov9282_stop_streaming(ov9282);
+ pm_runtime_put(ov9282->dev);
+ }
+
+ ov9282->streaming = enable;
+
+ mutex_unlock(&ov9282->mutex);
+
+ return 0;
+
+error_power_off:
+ pm_runtime_put(ov9282->dev);
+error_unlock:
+ mutex_unlock(&ov9282->mutex);
+
+ return ret;
+}
+
+/**
+ * ov9282_detect() - Detect ov9282 sensor
+ * @ov9282: pointer to ov9282 device
+ *
+ * Return: 0 if successful, -EIO if sensor id does not match
+ */
+static int ov9282_detect(struct ov9282 *ov9282)
+{
+ int ret;
+ u32 val;
+
+ ret = ov9282_read_reg(ov9282, OV9282_REG_ID, 2, &val);
+ if (ret)
+ return ret;
+
+ if (val != OV9282_ID) {
+ dev_err(ov9282->dev, "chip id mismatch: %x!=%x",
+ OV9282_ID, val);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+/**
+ * ov9282_parse_hw_config() - Parse HW configuration and check if supported
+ * @ov9282: pointer to ov9282 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_parse_hw_config(struct ov9282 *ov9282)
+{
+ struct fwnode_handle *fwnode = dev_fwnode(ov9282->dev);
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ struct fwnode_handle *ep;
+ unsigned long rate;
+ unsigned int i;
+ int ret;
+
+ if (!fwnode)
+ return -ENXIO;
+
+ /* Request optional reset pin */
+ ov9282->reset_gpio = devm_gpiod_get_optional(ov9282->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ov9282->reset_gpio)) {
+ dev_err(ov9282->dev, "failed to get reset gpio %ld",
+ PTR_ERR(ov9282->reset_gpio));
+ return PTR_ERR(ov9282->reset_gpio);
+ }
+
+ /* Get sensor input clock */
+ ov9282->inclk = devm_clk_get(ov9282->dev, NULL);
+ if (IS_ERR(ov9282->inclk)) {
+ dev_err(ov9282->dev, "could not get inclk");
+ return PTR_ERR(ov9282->inclk);
+ }
+
+ rate = clk_get_rate(ov9282->inclk);
+ if (rate != OV9282_INCLK_RATE) {
+ dev_err(ov9282->dev, "inclk frequency mismatch");
+ return -EINVAL;
+ }
+
+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+ if (!ep)
+ return -ENXIO;
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ fwnode_handle_put(ep);
+ if (ret)
+ return ret;
+
+ if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV9282_NUM_DATA_LANES) {
+ dev_err(ov9282->dev,
+ "number of CSI2 data lanes %d is not supported",
+ bus_cfg.bus.mipi_csi2.num_data_lanes);
+ ret = -EINVAL;
+ goto done_endpoint_free;
+ }
+
+ if (!bus_cfg.nr_of_link_frequencies) {
+ dev_err(ov9282->dev, "no link frequencies defined");
+ ret = -EINVAL;
+ goto done_endpoint_free;
+ }
+
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
+ if (bus_cfg.link_frequencies[i] == OV9282_LINK_FREQ)
+ goto done_endpoint_free;
+
+ ret = -EINVAL;
+
+done_endpoint_free:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+
+ return ret;
+}
+
+/* V4l2 subdevice ops */
+static const struct v4l2_subdev_video_ops ov9282_video_ops = {
+ .s_stream = ov9282_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops ov9282_pad_ops = {
+ .init_cfg = ov9282_init_pad_cfg,
+ .enum_mbus_code = ov9282_enum_mbus_code,
+ .enum_frame_size = ov9282_enum_frame_size,
+ .get_fmt = ov9282_get_pad_format,
+ .set_fmt = ov9282_set_pad_format,
+};
+
+static const struct v4l2_subdev_ops ov9282_subdev_ops = {
+ .video = &ov9282_video_ops,
+ .pad = &ov9282_pad_ops,
+};
+
+/**
+ * ov9282_power_on() - Sensor power on sequence
+ * @dev: pointer to i2c device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov9282 *ov9282 = to_ov9282(sd);
+ int ret;
+
+ usleep_range(400, 600);
+
+ gpiod_set_value_cansleep(ov9282->reset_gpio, 1);
+
+ ret = clk_prepare_enable(ov9282->inclk);
+ if (ret) {
+ dev_err(ov9282->dev, "fail to enable inclk");
+ goto error_reset;
+ }
+
+ usleep_range(400, 600);
+
+ return 0;
+
+error_reset:
+ gpiod_set_value_cansleep(ov9282->reset_gpio, 0);
+
+ return ret;
+}
+
+/**
+ * ov9282_power_off() - Sensor power off sequence
+ * @dev: pointer to i2c device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov9282 *ov9282 = to_ov9282(sd);
+
+ gpiod_set_value_cansleep(ov9282->reset_gpio, 0);
+
+ clk_disable_unprepare(ov9282->inclk);
+
+ return 0;
+}
+
+/**
+ * ov9282_init_controls() - Initialize sensor subdevice controls
+ * @ov9282: pointer to ov9282 device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_init_controls(struct ov9282 *ov9282)
+{
+ struct v4l2_ctrl_handler *ctrl_hdlr = &ov9282->ctrl_handler;
+ const struct ov9282_mode *mode = ov9282->cur_mode;
+ u32 lpfr;
+ int ret;
+
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6);
+ if (ret)
+ return ret;
+
+ /* Serialize controls with sensor device */
+ ctrl_hdlr->lock = &ov9282->mutex;
+
+ /* Initialize exposure and gain */
+ lpfr = mode->vblank + mode->height;
+ ov9282->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &ov9282_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ OV9282_EXPOSURE_MIN,
+ lpfr - OV9282_EXPOSURE_OFFSET,
+ OV9282_EXPOSURE_STEP,
+ OV9282_EXPOSURE_DEFAULT);
+
+ ov9282->again_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &ov9282_ctrl_ops,
+ V4L2_CID_ANALOGUE_GAIN,
+ OV9282_AGAIN_MIN,
+ OV9282_AGAIN_MAX,
+ OV9282_AGAIN_STEP,
+ OV9282_AGAIN_DEFAULT);
+
+ v4l2_ctrl_cluster(2, &ov9282->exp_ctrl);
+
+ ov9282->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &ov9282_ctrl_ops,
+ V4L2_CID_VBLANK,
+ mode->vblank_min,
+ mode->vblank_max,
+ 1, mode->vblank);
+
+ /* Read only controls */
+ ov9282->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &ov9282_ctrl_ops,
+ V4L2_CID_PIXEL_RATE,
+ mode->pclk, mode->pclk,
+ 1, mode->pclk);
+
+ ov9282->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr,
+ &ov9282_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(link_freq) -
+ 1,
+ mode->link_freq_idx,
+ link_freq);
+ if (ov9282->link_freq_ctrl)
+ ov9282->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ ov9282->hblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
+ &ov9282_ctrl_ops,
+ V4L2_CID_HBLANK,
+ OV9282_REG_MIN,
+ OV9282_REG_MAX,
+ 1, mode->hblank);
+ if (ov9282->hblank_ctrl)
+ ov9282->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ if (ctrl_hdlr->error) {
+ dev_err(ov9282->dev, "control init failed: %d",
+ ctrl_hdlr->error);
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+ return ctrl_hdlr->error;
+ }
+
+ ov9282->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+}
+
+/**
+ * ov9282_probe() - I2C client device binding
+ * @client: pointer to i2c client device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_probe(struct i2c_client *client)
+{
+ struct ov9282 *ov9282;
+ int ret;
+
+ ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL);
+ if (!ov9282)
+ return -ENOMEM;
+
+ ov9282->dev = &client->dev;
+
+ /* Initialize subdev */
+ v4l2_i2c_subdev_init(&ov9282->sd, client, &ov9282_subdev_ops);
+
+ ret = ov9282_parse_hw_config(ov9282);
+ if (ret) {
+ dev_err(ov9282->dev, "HW configuration is not supported");
+ return ret;
+ }
+
+ mutex_init(&ov9282->mutex);
+
+ ret = ov9282_power_on(ov9282->dev);
+ if (ret) {
+ dev_err(ov9282->dev, "failed to power-on the sensor");
+ goto error_mutex_destroy;
+ }
+
+ /* Check module identity */
+ ret = ov9282_detect(ov9282);
+ if (ret) {
+ dev_err(ov9282->dev, "failed to find sensor: %d", ret);
+ goto error_power_off;
+ }
+
+ /* Set default mode to max resolution */
+ ov9282->cur_mode = &supported_mode;
+ ov9282->vblank = ov9282->cur_mode->vblank;
+
+ ret = ov9282_init_controls(ov9282);
+ if (ret) {
+ dev_err(ov9282->dev, "failed to init controls: %d", ret);
+ goto error_power_off;
+ }
+
+ /* Initialize subdev */
+ ov9282->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ ov9282->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ /* Initialize source pad */
+ ov9282->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&ov9282->sd.entity, 1, &ov9282->pad);
+ if (ret) {
+ dev_err(ov9282->dev, "failed to init entity pads: %d", ret);
+ goto error_handler_free;
+ }
+
+ ret = v4l2_async_register_subdev_sensor(&ov9282->sd);
+ if (ret < 0) {
+ dev_err(ov9282->dev,
+ "failed to register async subdev: %d", ret);
+ goto error_media_entity;
+ }
+
+ pm_runtime_set_active(ov9282->dev);
+ pm_runtime_enable(ov9282->dev);
+ pm_runtime_idle(ov9282->dev);
+
+ return 0;
+
+error_media_entity:
+ media_entity_cleanup(&ov9282->sd.entity);
+error_handler_free:
+ v4l2_ctrl_handler_free(ov9282->sd.ctrl_handler);
+error_power_off:
+ ov9282_power_off(ov9282->dev);
+error_mutex_destroy:
+ mutex_destroy(&ov9282->mutex);
+
+ return ret;
+}
+
+/**
+ * ov9282_remove() - I2C client device unbinding
+ * @client: pointer to I2C client device
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int ov9282_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov9282 *ov9282 = to_ov9282(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev))
+ ov9282_power_off(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+
+ mutex_destroy(&ov9282->mutex);
+
+ return 0;
+}
+
+static const struct dev_pm_ops ov9282_pm_ops = {
+ SET_RUNTIME_PM_OPS(ov9282_power_off, ov9282_power_on, NULL)
+};
+
+static const struct of_device_id ov9282_of_match[] = {
+ { .compatible = "ovti,ov9282" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, ov9282_of_match);
+
+static struct i2c_driver ov9282_driver = {
+ .probe_new = ov9282_probe,
+ .remove = ov9282_remove,
+ .driver = {
+ .name = "ov9282",
+ .pm = &ov9282_pm_ops,
+ .of_match_table = ov9282_of_match,
+ },
+};
+
+module_i2c_driver(ov9282_driver);
+
+MODULE_DESCRIPTION("OmniVision ov9282 sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c
index af50c66cf5ce..df538ceb71c3 100644
--- a/drivers/media/i2c/ov9734.c
+++ b/drivers/media/i2c/ov9734.c
@@ -60,6 +60,12 @@
#define OV9734_TEST_PATTERN_ENABLE BIT(7)
#define OV9734_TEST_PATTERN_BAR_SHIFT 2
+/* Group Access */
+#define OV9734_REG_GROUP_ACCESS 0x3208
+#define OV9734_GROUP_HOLD_START 0x0
+#define OV9734_GROUP_HOLD_END 0x10
+#define OV9734_GROUP_HOLD_LAUNCH 0xa0
+
enum {
OV9734_LINK_FREQ_180MHZ_INDEX,
};
@@ -433,6 +439,11 @@ static int ov9734_update_digital_gain(struct ov9734 *ov9734, u32 d_gain)
{
int ret;
+ ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
+ OV9734_GROUP_HOLD_START);
+ if (ret)
+ return ret;
+
ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_R_GAIN, 2, d_gain);
if (ret)
return ret;
@@ -441,7 +452,18 @@ static int ov9734_update_digital_gain(struct ov9734 *ov9734, u32 d_gain)
if (ret)
return ret;
- return ov9734_write_reg(ov9734, OV9734_REG_MWB_B_GAIN, 2, d_gain);
+ ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_B_GAIN, 2, d_gain);
+ if (ret)
+ return ret;
+
+ ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
+ OV9734_GROUP_HOLD_END);
+ if (ret)
+ return ret;
+
+ ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
+ OV9734_GROUP_HOLD_LAUNCH);
+ return ret;
}
static int ov9734_test_pattern(struct ov9734 *ov9734, u32 pattern)
diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c
index 91e6db847bb5..6070aaf0b32e 100644
--- a/drivers/media/i2c/tda1997x.c
+++ b/drivers/media/i2c/tda1997x.c
@@ -563,7 +563,7 @@ static void tda1997x_delayed_work_enable_hpd(struct work_struct *work)
delayed_work_enable_hpd);
struct v4l2_subdev *sd = &state->sd;
- v4l2_dbg(2, debug, sd, "%s:\n", __func__);
+ v4l2_dbg(2, debug, sd, "%s\n", __func__);
/* Set HPD high */
tda1997x_manual_hpd(sd, HPD_HIGH_OTHER);
@@ -1107,7 +1107,8 @@ tda1997x_detect_std(struct tda1997x_state *state,
hper = io_read16(sd, REG_H_PER) & MASK_HPER;
hsper = io_read16(sd, REG_HS_WIDTH) & MASK_HSWIDTH;
v4l2_dbg(1, debug, sd, "Signal Timings: %u/%u/%u\n", vper, hper, hsper);
- if (!vper || !hper || !hsper)
+
+ if (!state->input_detect[0] && !state->input_detect[1])
return -ENOLINK;
for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
@@ -1695,14 +1696,15 @@ static int tda1997x_query_dv_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
struct tda1997x_state *state = to_state(sd);
+ int ret;
v4l_dbg(1, debug, state->client, "%s\n", __func__);
memset(timings, 0, sizeof(struct v4l2_dv_timings));
mutex_lock(&state->lock);
- tda1997x_detect_std(state, timings);
+ ret = tda1997x_detect_std(state, timings);
mutex_unlock(&state->lock);
- return 0;
+ return ret;
}
static const struct v4l2_subdev_video_ops tda1997x_video_ops = {
@@ -2233,6 +2235,7 @@ static int tda1997x_core_init(struct v4l2_subdev *sd)
/* get initial HDMI status */
state->hdmi_status = io_read(sd, REG_HDMI_FLAGS);
+ io_write(sd, REG_EDID_ENABLE, EDID_ENABLE_A_EN | EDID_ENABLE_B_EN);
return 0;
}
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 30c63552556d..4b16ffcaef98 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -964,7 +964,7 @@ static int tvp5150_enable(struct v4l2_subdev *sd)
/*
* Enable the YCbCr and clock outputs. In discrete sync mode
- * (non-BT.656) additionally enable the the sync outputs.
+ * (non-BT.656) additionally enable the sync outputs.
*/
switch (decoder->mbus_type) {
case V4L2_MBUS_PARALLEL:
diff --git a/drivers/media/mc/mc-device.c b/drivers/media/mc/mc-device.c
index 9e56d2ad6b94..cf5e459b1d96 100644
--- a/drivers/media/mc/mc-device.c
+++ b/drivers/media/mc/mc-device.c
@@ -556,7 +556,7 @@ static const struct media_file_operations media_device_fops = {
* sysfs
*/
-static ssize_t show_model(struct device *cd,
+static ssize_t model_show(struct device *cd,
struct device_attribute *attr, char *buf)
{
struct media_devnode *devnode = to_media_devnode(cd);
@@ -565,7 +565,7 @@ static ssize_t show_model(struct device *cd,
return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model);
}
-static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
+static DEVICE_ATTR_RO(model);
/* -----------------------------------------------------------------------------
* Registration/unregistration
diff --git a/drivers/media/pci/bt8xx/bttv-gpio.c b/drivers/media/pci/bt8xx/bttv-gpio.c
index b730225ca887..a2b18e2bed1b 100644
--- a/drivers/media/pci/bt8xx/bttv-gpio.c
+++ b/drivers/media/pci/bt8xx/bttv-gpio.c
@@ -46,14 +46,13 @@ static int bttv_sub_probe(struct device *dev)
return sub->probe ? sub->probe(sdev) : -ENODEV;
}
-static int bttv_sub_remove(struct device *dev)
+static void bttv_sub_remove(struct device *dev)
{
struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
if (sub->remove)
sub->remove(sdev);
- return 0;
}
struct bus_type bttv_sub_bus_type = {
diff --git a/drivers/media/pci/ivtv/ivtv-cards.h b/drivers/media/pci/ivtv/ivtv-cards.h
index f3e2c5634962..c252733df340 100644
--- a/drivers/media/pci/ivtv/ivtv-cards.h
+++ b/drivers/media/pci/ivtv/ivtv-cards.h
@@ -78,27 +78,53 @@
#define IVTV_PCI_ID_SONY 0x104d
/* hardware flags, no gaps allowed */
-#define IVTV_HW_CX25840 (1 << 0)
-#define IVTV_HW_SAA7115 (1 << 1)
-#define IVTV_HW_SAA7127 (1 << 2)
-#define IVTV_HW_MSP34XX (1 << 3)
-#define IVTV_HW_TUNER (1 << 4)
-#define IVTV_HW_WM8775 (1 << 5)
-#define IVTV_HW_CS53L32A (1 << 6)
-#define IVTV_HW_TVEEPROM (1 << 7)
-#define IVTV_HW_SAA7114 (1 << 8)
-#define IVTV_HW_UPD64031A (1 << 9)
-#define IVTV_HW_UPD6408X (1 << 10)
-#define IVTV_HW_SAA717X (1 << 11)
-#define IVTV_HW_WM8739 (1 << 12)
-#define IVTV_HW_VP27SMPX (1 << 13)
-#define IVTV_HW_M52790 (1 << 14)
-#define IVTV_HW_GPIO (1 << 15)
-#define IVTV_HW_I2C_IR_RX_AVER (1 << 16)
-#define IVTV_HW_I2C_IR_RX_HAUP_EXT (1 << 17) /* External before internal */
-#define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18)
-#define IVTV_HW_Z8F0811_IR_HAUP (1 << 19)
-#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 20)
+enum ivtv_hw_bits {
+ IVTV_HW_BIT_CX25840,
+ IVTV_HW_BIT_SAA7115,
+ IVTV_HW_BIT_SAA7127,
+ IVTV_HW_BIT_MSP34XX,
+ IVTV_HW_BIT_TUNER,
+ IVTV_HW_BIT_WM8775,
+ IVTV_HW_BIT_CS53L32A,
+ IVTV_HW_BIT_TVEEPROM,
+ IVTV_HW_BIT_SAA7114,
+ IVTV_HW_BIT_UPD64031A,
+ IVTV_HW_BIT_UPD6408X,
+ IVTV_HW_BIT_SAA717X,
+ IVTV_HW_BIT_WM8739,
+ IVTV_HW_BIT_VP27SMPX,
+ IVTV_HW_BIT_M52790,
+ IVTV_HW_BIT_GPIO,
+ IVTV_HW_BIT_I2C_IR_RX_AVER,
+ IVTV_HW_BIT_I2C_IR_RX_HAUP_EXT, /* External before internal */
+ IVTV_HW_BIT_I2C_IR_RX_HAUP_INT,
+ IVTV_HW_BIT_Z8F0811_IR_HAUP,
+ IVTV_HW_BIT_I2C_IR_RX_ADAPTEC,
+
+ IVTV_HW_MAX_BITS /* Should be the last one */
+};
+
+#define IVTV_HW_CX25840 BIT(IVTV_HW_BIT_CX25840)
+#define IVTV_HW_SAA7115 BIT(IVTV_HW_BIT_SAA7115)
+#define IVTV_HW_SAA7127 BIT(IVTV_HW_BIT_SAA7127)
+#define IVTV_HW_MSP34XX BIT(IVTV_HW_BIT_MSP34XX)
+#define IVTV_HW_TUNER BIT(IVTV_HW_BIT_TUNER)
+#define IVTV_HW_WM8775 BIT(IVTV_HW_BIT_WM8775)
+#define IVTV_HW_CS53L32A BIT(IVTV_HW_BIT_CS53L32A)
+#define IVTV_HW_TVEEPROM BIT(IVTV_HW_BIT_TVEEPROM)
+#define IVTV_HW_SAA7114 BIT(IVTV_HW_BIT_SAA7114)
+#define IVTV_HW_UPD64031A BIT(IVTV_HW_BIT_UPD64031A)
+#define IVTV_HW_UPD6408X BIT(IVTV_HW_BIT_UPD6408X)
+#define IVTV_HW_SAA717X BIT(IVTV_HW_BIT_SAA717X)
+#define IVTV_HW_WM8739 BIT(IVTV_HW_BIT_WM8739)
+#define IVTV_HW_VP27SMPX BIT(IVTV_HW_BIT_VP27SMPX)
+#define IVTV_HW_M52790 BIT(IVTV_HW_BIT_M52790)
+#define IVTV_HW_GPIO BIT(IVTV_HW_BIT_GPIO)
+#define IVTV_HW_I2C_IR_RX_AVER BIT(IVTV_HW_BIT_I2C_IR_RX_AVER)
+#define IVTV_HW_I2C_IR_RX_HAUP_EXT BIT(IVTV_HW_BIT_I2C_IR_RX_HAUP_EXT)
+#define IVTV_HW_I2C_IR_RX_HAUP_INT BIT(IVTV_HW_BIT_I2C_IR_RX_HAUP_INT)
+#define IVTV_HW_Z8F0811_IR_HAUP BIT(IVTV_HW_BIT_Z8F0811_IR_HAUP)
+#define IVTV_HW_I2C_IR_RX_ADAPTEC BIT(IVTV_HW_BIT_I2C_IR_RX_ADAPTEC)
#define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114)
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
index 982045c4eea8..c052c57c6dce 100644
--- a/drivers/media/pci/ivtv/ivtv-i2c.c
+++ b/drivers/media/pci/ivtv/ivtv-i2c.c
@@ -85,7 +85,7 @@
#define IVTV_ADAPTEC_IR_ADDR 0x6b
/* This array should match the IVTV_HW_ defines */
-static const u8 hw_addrs[] = {
+static const u8 hw_addrs[IVTV_HW_MAX_BITS] = {
IVTV_CX25840_I2C_ADDR,
IVTV_SAA7115_I2C_ADDR,
IVTV_SAA7127_I2C_ADDR,
@@ -110,7 +110,7 @@ static const u8 hw_addrs[] = {
};
/* This array should match the IVTV_HW_ defines */
-static const char * const hw_devicenames[] = {
+static const char * const hw_devicenames[IVTV_HW_MAX_BITS] = {
"cx25840",
"saa7115",
"saa7127_auto", /* saa7127 or saa7129 */
@@ -240,10 +240,16 @@ void ivtv_i2c_new_ir_legacy(struct ivtv *itv)
int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
{
- struct v4l2_subdev *sd;
struct i2c_adapter *adap = &itv->i2c_adap;
- const char *type = hw_devicenames[idx];
- u32 hw = 1 << idx;
+ struct v4l2_subdev *sd;
+ const char *type;
+ u32 hw;
+
+ if (idx >= IVTV_HW_MAX_BITS)
+ return -ENODEV;
+
+ type = hw_devicenames[idx];
+ hw = 1 << idx;
if (hw == IVTV_HW_TUNER) {
/* special tuner handling */
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index 7a1fb067b0e0..fb24d2ed3621 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -1215,15 +1215,13 @@ static int alsa_device_exit(struct saa7134_dev *dev)
static int saa7134_alsa_init(void)
{
struct saa7134_dev *dev = NULL;
- struct list_head *list;
saa7134_dmasound_init = alsa_device_init;
saa7134_dmasound_exit = alsa_device_exit;
pr_info("saa7134 ALSA driver for DMA sound loaded\n");
- list_for_each(list,&saa7134_devlist) {
- dev = list_entry(list, struct saa7134_dev, devlist);
+ list_for_each_entry(dev, &saa7134_devlist, devlist) {
if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
pr_info("%s/alsa: %s doesn't support digital audio\n",
dev->name, saa7134_boards[dev->board].name);
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 47158ab3956b..96328b0af164 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -223,7 +223,8 @@ int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
__le32 *cpu;
dma_addr_t dma_addr = 0;
- cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
+ cpu = dma_alloc_coherent(&pci->dev, SAA7134_PGTABLE_SIZE, &dma_addr,
+ GFP_KERNEL);
if (NULL == cpu)
return -ENOMEM;
pt->size = SAA7134_PGTABLE_SIZE;
@@ -254,7 +255,7 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
{
if (NULL == pt->cpu)
return;
- pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
+ dma_free_coherent(&pci->dev, pt->size, pt->cpu, pt->dma);
pt->cpu = NULL;
}
@@ -1092,7 +1093,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
dev->pci_lat,
(unsigned long long)pci_resource_start(pci_dev, 0));
pci_set_master(pci_dev);
- err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+ err = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32));
if (err) {
pr_warn("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
goto err_v4l2_unregister;
diff --git a/drivers/media/pci/saa7164/saa7164-cmd.c b/drivers/media/pci/saa7164/saa7164-cmd.c
index 716162055fb7..a65d810ce212 100644
--- a/drivers/media/pci/saa7164/saa7164-cmd.c
+++ b/drivers/media/pci/saa7164/saa7164-cmd.c
@@ -549,9 +549,6 @@ int saa7164_cmd_send(struct saa7164_dev *dev, u8 id, enum tmComResCmd command,
/* See of other commands are on the bus */
if (saa7164_cmd_dequeue(dev) != SAA_OK)
printk(KERN_ERR "dequeue(3) failed\n");
-
- continue;
-
} /* (loop) */
/* Release the sequence number allocation */
diff --git a/drivers/media/pci/tw5864/tw5864-reg.h b/drivers/media/pci/tw5864/tw5864-reg.h
index a26a439c4dc0..25d4a9a6cc6b 100644
--- a/drivers/media/pci/tw5864/tw5864-reg.h
+++ b/drivers/media/pci/tw5864/tw5864-reg.h
@@ -663,7 +663,7 @@
#define TW5864_SYNC 0x8008
/* Define controls in register TW5864_SYNC */
/*
- * 0 vlc stream to syncrous port
+ * 0 vlc stream to synchronous port
* 1 vlc stream to ddr buffers
*/
#define TW5864_SYNC_CFG BIT(7)
diff --git a/drivers/media/platform/atmel/atmel-sama5d2-isc.c b/drivers/media/platform/atmel/atmel-sama5d2-isc.c
index 925aa80a139b..b66f1d174e9d 100644
--- a/drivers/media/platform/atmel/atmel-sama5d2-isc.c
+++ b/drivers/media/platform/atmel/atmel-sama5d2-isc.c
@@ -255,6 +255,23 @@ static void isc_sama5d2_config_rlp(struct isc_device *isc)
struct regmap *regmap = isc->regmap;
u32 rlp_mode = isc->config.rlp_cfg_mode;
+ /*
+ * In sama5d2, the YUV planar modes and the YUYV modes are treated
+ * in the same way in RLP register.
+ * Normally, YYCC mode should be Luma(n) - Color B(n) - Color R (n)
+ * and YCYC should be Luma(n + 1) - Color B (n) - Luma (n) - Color R (n)
+ * but in sama5d2, the YCYC mode does not exist, and YYCC must be
+ * selected for both planar and interleaved modes, as in fact
+ * both modes are supported.
+ *
+ * Thus, if the YCYC mode is selected, replace it with the
+ * sama5d2-compliant mode which is YYCC .
+ */
+ if ((rlp_mode & ISC_RLP_CFG_MODE_YCYC) == ISC_RLP_CFG_MODE_YCYC) {
+ rlp_mode &= ~ISC_RLP_CFG_MODE_MASK;
+ rlp_mode |= ISC_RLP_CFG_MODE_YYCC;
+ }
+
regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp,
ISC_RLP_CFG_MODE_MASK, rlp_mode);
}
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index 2f42808c43a4..c484c008ab02 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -2053,17 +2053,25 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
u32 src_fourcc, dst_fourcc;
int ret;
+ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ src_fourcc = q_data_src->fourcc;
+ dst_fourcc = q_data_dst->fourcc;
+
if (!ctx->initialized) {
ret = __coda_decoder_seq_init(ctx);
if (ret < 0)
return ret;
+ } else {
+ ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
+ CODA9_FRAME_TILED2LINEAR);
+ if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
+ ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
+ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
+ ctx->frame_mem_ctrl |= (0x3 << 9) |
+ ((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
}
- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- src_fourcc = q_data_src->fourcc;
- dst_fourcc = q_data_dst->fourcc;
-
coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index f9f7dd17c57c..0a2226b321d7 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -189,7 +189,7 @@ int vpfe_register_ccdc_device(const struct ccdc_hw_device *dev)
if (!ccdc_cfg) {
/*
* TODO. Will this ever happen? if so, we need to fix it.
- * Proabably we need to add the request to a linked list and
+ * Probably we need to add the request to a linked list and
* walk through it during vpfe probe
*/
printk(KERN_ERR "vpfe capture not initialized\n");
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 3b8a24bb724c..fa648721eaab 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -1238,8 +1238,8 @@ static const struct media_device_ops fimc_md_ops = {
.link_notify = fimc_md_link_notify,
};
-static ssize_t fimc_md_sysfs_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t subdev_conf_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct fimc_md *fmd = dev_get_drvdata(dev);
@@ -1249,9 +1249,9 @@ static ssize_t fimc_md_sysfs_show(struct device *dev,
return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
}
-static ssize_t fimc_md_sysfs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t subdev_conf_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct fimc_md *fmd = dev_get_drvdata(dev);
bool subdev_api;
@@ -1278,8 +1278,7 @@ static ssize_t fimc_md_sysfs_store(struct device *dev,
* sub-dev - for media controller API, subdevs must be configured in user
* space before starting streaming.
*/
-static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
- fimc_md_sysfs_show, fimc_md_sysfs_store);
+static DEVICE_ATTR_RW(subdev_conf_mode);
static int cam_clk_prepare(struct clk_hw *hw)
{
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 070a0f3fc337..58f9463f3b8c 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -692,7 +692,7 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
* Scatter/gather mode requires stopping the controller between
* frames so we can put in a new DMA descriptor array. If no new
* buffer exists at frame completion, the controller is left stopped;
- * this function is charged with gettig things going again.
+ * this function is charged with getting things going again.
*/
static void mcam_sg_restart(struct mcam_camera *cam)
{
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 53025c8c7531..20f59c59ff8a 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -2037,8 +2037,10 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
mutex_lock(&isp->media_dev.graph_mutex);
ret = media_entity_enum_init(&isp->crashed, &isp->media_dev);
- if (ret)
+ if (ret) {
+ mutex_unlock(&isp->media_dev.graph_mutex);
return ret;
+ }
list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
if (sd->notifier != &isp->notifier)
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 8df2d497d706..5ec851115eca 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -234,6 +234,7 @@ struct venc_controls {
u32 h264_loop_filter_mode;
s32 h264_loop_filter_alpha;
s32 h264_loop_filter_beta;
+ u32 h264_8x8_transform;
u32 hevc_i_qp;
u32 hevc_p_qp;
@@ -256,6 +257,7 @@ struct venc_controls {
u32 header_mode;
bool aud_enable;
+ u32 intra_refresh_period;
struct {
u32 h264;
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c
index 1fe6d463dc99..8012f5c7bf34 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -1137,6 +1137,9 @@ int venus_helper_set_format_constraints(struct venus_inst *inst)
if (!IS_V6(inst->core))
return 0;
+ if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC)
+ return 0;
+
pconstraint.buffer_type = HFI_BUFFER_OUTPUT2;
pconstraint.num_planes = 2;
pconstraint.plane_format[0].stride_multiples = 128;
diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c
index f51024786991..60f4b8e4b8d0 100644
--- a/drivers/media/platform/qcom/venus/hfi_cmds.c
+++ b/drivers/media/platform/qcom/venus/hfi_cmds.c
@@ -1239,6 +1239,14 @@ pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt,
break;
}
+ case HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8: {
+ struct hfi_h264_8x8_transform *in = pdata, *tm = prop_data;
+
+ tm->enable_type = in->enable_type;
+ pkt->shdr.hdr.size += sizeof(u32) + sizeof(*tm);
+ break;
+ }
+
case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE:
case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE:
diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h
index b0a9beb4163c..bec4feb63ceb 100644
--- a/drivers/media/platform/qcom/venus/hfi_helper.h
+++ b/drivers/media/platform/qcom/venus/hfi_helper.h
@@ -507,6 +507,7 @@
#define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020
#define HFI_PROPERTY_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC 0x2005021
#define HFI_PROPERTY_PARAM_VENC_PRESERVE_TEXT_QUALITY 0x2005023
+#define HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8 0x2005025
#define HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER 0x2005026
#define HFI_PROPERTY_PARAM_VENC_DISABLE_RC_TIMESTAMP 0x2005027
#define HFI_PROPERTY_PARAM_VENC_INITIAL_QP 0x2005028
@@ -562,6 +563,10 @@ struct hfi_bitrate {
u32 layer_id;
};
+struct hfi_h264_8x8_transform {
+ u32 enable_type;
+};
+
#define HFI_CAPABILITY_FRAME_WIDTH 0x01
#define HFI_CAPABILITY_FRAME_HEIGHT 0x02
#define HFI_CAPABILITY_MBS_PER_FRAME 0x03
diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c
index d9fde66f6fa8..9a2bdb002edc 100644
--- a/drivers/media/platform/qcom/venus/hfi_msgs.c
+++ b/drivers/media/platform/qcom/venus/hfi_msgs.c
@@ -261,7 +261,7 @@ sys_get_prop_image_version(struct device *dev,
smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
SMEM_IMG_VER_TBL, &smem_blk_sz);
- if (smem_tbl_ptr && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
+ if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS,
img_ver, VER_STR_SZ);
}
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 8dd49d4f124c..bc1c42dd53c0 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -183,6 +183,8 @@ venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
else
return NULL;
fmt = find_format(inst, pixmp->pixelformat, f->type);
+ if (!fmt)
+ return NULL;
}
pixmp->width = clamp(pixmp->width, frame_width_min(inst),
@@ -547,6 +549,7 @@ static int venc_set_properties(struct venus_inst *inst)
struct hfi_quantization_range quant_range;
struct hfi_enable en;
struct hfi_ltr_mode ltr_mode;
+ struct hfi_intra_refresh intra_refresh = {};
u32 ptype, rate_control, bitrate;
u32 profile, level;
int ret;
@@ -567,6 +570,7 @@ static int venc_set_properties(struct venus_inst *inst)
struct hfi_h264_vui_timing_info info;
struct hfi_h264_entropy_control entropy;
struct hfi_h264_db_control deblock;
+ struct hfi_h264_8x8_transform h264_transform;
ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
info.enable = 1;
@@ -597,6 +601,17 @@ static int venc_set_properties(struct venus_inst *inst)
ret = hfi_session_set_property(inst, ptype, &deblock);
if (ret)
return ret;
+
+ ptype = HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8;
+ h264_transform.enable_type = 0;
+ if (ctr->profile.h264 == HFI_H264_PROFILE_HIGH ||
+ ctr->profile.h264 == HFI_H264_PROFILE_CONSTRAINED_HIGH)
+ h264_transform.enable_type = ctr->h264_8x8_transform;
+
+ ret = hfi_session_set_property(inst, ptype, &h264_transform);
+ if (ret)
+ return ret;
+
}
if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
@@ -802,6 +817,31 @@ static int venc_set_properties(struct venus_inst *inst)
en.enable = 1;
ret = hfi_session_set_property(inst, ptype, &en);
+ }
+
+ if ((inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
+ inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) &&
+ (rate_control == HFI_RATE_CONTROL_CBR_VFR ||
+ rate_control == HFI_RATE_CONTROL_CBR_CFR)) {
+ intra_refresh.mode = HFI_INTRA_REFRESH_NONE;
+ intra_refresh.cir_mbs = 0;
+
+ if (ctr->intra_refresh_period) {
+ u32 mbs;
+
+ mbs = ALIGN(inst->width, 16) * ALIGN(inst->height, 16);
+ mbs /= 16 * 16;
+ if (mbs % ctr->intra_refresh_period)
+ mbs++;
+ mbs /= ctr->intra_refresh_period;
+
+ intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
+ intra_refresh.cir_mbs = mbs;
+ }
+
+ ptype = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
+
+ ret = hfi_session_set_property(inst, ptype, &intra_refresh);
if (ret)
return ret;
}
diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c
index 637c92f6c5be..1ada42df314d 100644
--- a/drivers/media/platform/qcom/venus/venc_ctrls.c
+++ b/drivers/media/platform/qcom/venus/venc_ctrls.c
@@ -17,7 +17,6 @@
#define SLICE_BYTE_SIZE_MAX 1024
#define SLICE_BYTE_SIZE_MIN 1024
#define SLICE_MB_SIZE_MAX 300
-#define INTRA_REFRESH_MBS_MAX 300
#define AT_SLICE_BOUNDARY \
V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY
#define MAX_LTR_FRAME_COUNT 4
@@ -227,8 +226,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
}
mutex_unlock(&inst->lock);
break;
- case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
- break;
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
ret = venc_calc_bpframes(ctrl->val, ctr->num_b_frames, &bframes,
&ctr->num_p_frames);
@@ -319,6 +316,28 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY:
ctr->mastering = *ctrl->p_new.p_hdr10_mastering;
break;
+ case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD:
+ ctr->intra_refresh_period = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+ if (ctr->profile.h264 != HFI_H264_PROFILE_HIGH &&
+ ctr->profile.h264 != HFI_H264_PROFILE_CONSTRAINED_HIGH)
+ return -EINVAL;
+
+ /*
+ * In video firmware, 8x8 transform is supported only for
+ * high profile(HP) and constrained high profile(CHP).
+ * If client wants to disable 8x8 transform for HP/CHP,
+ * it is better to set profile as main profile(MP).
+ * Because there is no difference between HP and MP
+ * if we disable 8x8 transform for HP.
+ */
+
+ if (ctrl->val == 0)
+ return -EINVAL;
+
+ ctr->h264_8x8_transform = ctrl->val;
+ break;
default:
return -EINVAL;
}
@@ -334,7 +353,7 @@ int venc_ctrl_init(struct venus_inst *inst)
{
int ret;
- ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 57);
+ ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 58);
if (ret)
return ret;
@@ -438,6 +457,9 @@ int venc_ctrl_init(struct venus_inst *inst)
V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP, 1, 51, 1, 1);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, 0, 1, 1, 0);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP, 1, 51, 1, 1);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
@@ -503,10 +525,6 @@ int venc_ctrl_init(struct venus_inst *inst)
V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
- 0, INTRA_REFRESH_MBS_MAX, 1, 0);
-
- v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, (1 << 16) - 1, 1, 30);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
@@ -564,6 +582,10 @@ int venc_ctrl_init(struct venus_inst *inst)
V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY,
v4l2_ctrl_ptr_create(NULL));
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD, 0,
+ ((4096 * 2304) >> 8), 1, 0);
+
ret = inst->ctrl_handler.error;
if (ret)
goto err;
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index cca15a10c0b3..0d141155f0e3 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -253,8 +253,8 @@ static int rvin_try_format(struct rvin_dev *vin, u32 which,
int ret;
sd_state = v4l2_subdev_alloc_state(sd);
- if (sd_state == NULL)
- return -ENOMEM;
+ if (IS_ERR(sd_state))
+ return PTR_ERR(sd_state);
if (!rvin_format_from_pixel(vin, pix->pixelformat))
pix->pixelformat = RVIN_DEFAULT_FORMAT;
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index bf3fd71ec3af..6759091b15e0 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -863,12 +863,12 @@ static int rga_probe(struct platform_device *pdev)
if (IS_ERR(rga->m2m_dev)) {
v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n");
ret = PTR_ERR(rga->m2m_dev);
- goto unreg_video_dev;
+ goto rel_vdev;
}
ret = pm_runtime_resume_and_get(rga->dev);
if (ret < 0)
- goto unreg_video_dev;
+ goto rel_vdev;
rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
@@ -882,11 +882,23 @@ static int rga_probe(struct platform_device *pdev)
rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE,
&rga->cmdbuf_phy, GFP_KERNEL,
DMA_ATTR_WRITE_COMBINE);
+ if (!rga->cmdbuf_virt) {
+ ret = -ENOMEM;
+ goto rel_vdev;
+ }
rga->src_mmu_pages =
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
+ if (!rga->src_mmu_pages) {
+ ret = -ENOMEM;
+ goto free_dma;
+ }
rga->dst_mmu_pages =
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
+ if (rga->dst_mmu_pages) {
+ ret = -ENOMEM;
+ goto free_src_pages;
+ }
def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
def_frame.size = def_frame.stride * def_frame.height;
@@ -894,7 +906,7 @@ static int rga_probe(struct platform_device *pdev)
ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
if (ret) {
v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
- goto rel_vdev;
+ goto free_dst_pages;
}
v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n",
@@ -902,10 +914,15 @@ static int rga_probe(struct platform_device *pdev)
return 0;
+free_dst_pages:
+ free_pages((unsigned long)rga->dst_mmu_pages, 3);
+free_src_pages:
+ free_pages((unsigned long)rga->src_mmu_pages, 3);
+free_dma:
+ dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
+ rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
rel_vdev:
video_device_release(vfd);
-unreg_video_dev:
- video_unregister_device(rga->vfd);
unreg_v4l2_dev:
v4l2_device_unregister(&rga->v4l2_dev);
err_put_clk:
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
index 60cd2200e7ae..41988eb0ec0a 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
@@ -750,7 +750,7 @@ static int rkisp1_vb2_queue_setup(struct vb2_queue *queue,
return 0;
}
-static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
+static int rkisp1_vb2_buf_init(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkisp1_buffer *ispbuf =
@@ -780,6 +780,15 @@ static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
if (cap->pix.info->comp_planes == 3 && cap->pix.cfg->uv_swap)
swap(ispbuf->buff_addr[RKISP1_PLANE_CR],
ispbuf->buff_addr[RKISP1_PLANE_CB]);
+ return 0;
+}
+
+static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct rkisp1_buffer *ispbuf =
+ container_of(vbuf, struct rkisp1_buffer, vb);
+ struct rkisp1_capture *cap = vb->vb2_queue->drv_priv;
spin_lock_irq(&cap->buf.lock);
list_add_tail(&ispbuf->queue, &cap->buf.queue);
@@ -1039,6 +1048,7 @@ err_ret_buffers:
static const struct vb2_ops rkisp1_vb2_ops = {
.queue_setup = rkisp1_vb2_queue_setup,
+ .buf_init = rkisp1_vb2_buf_init,
.buf_queue = rkisp1_vb2_buf_queue,
.buf_prepare = rkisp1_vb2_buf_prepare,
.wait_prepare = vb2_ops_wait_prepare,
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index 038c303a8aed..bb73f4e17b66 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -156,15 +156,11 @@ struct rkisp1_vdev_node {
* @vb: vb2 buffer
* @queue: entry of the buffer in the queue
* @buff_addr: dma addresses of each plane, used only by the capture devices: selfpath, mainpath
- * @vaddr: virtual address for buffers used by params and stats devices
*/
struct rkisp1_buffer {
struct vb2_v4l2_buffer vb;
struct list_head queue;
- union {
- u32 buff_addr[VIDEO_MAX_PLANES];
- void *vaddr;
- };
+ u32 buff_addr[VIDEO_MAX_PLANES];
};
/*
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 529c6e21815f..8fa5b0abf1f9 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -1143,7 +1143,7 @@ static void rkisp1_params_apply_params_cfg(struct rkisp1_params *params,
cur_buf = list_first_entry(&params->params,
struct rkisp1_buffer, queue);
- new_params = (struct rkisp1_params_cfg *)(cur_buf->vaddr);
+ new_params = (struct rkisp1_params_cfg *)vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0);
rkisp1_isp_isr_other_config(params, new_params);
rkisp1_isp_isr_meas_config(params, new_params);
@@ -1382,7 +1382,6 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_params *params = vq->drv_priv;
- params_buf->vaddr = vb2_plane_vaddr(vb, 0);
spin_lock_irq(&params->config_lock);
list_add_tail(&params_buf->queue, &params->params);
spin_unlock_irq(&params->config_lock);
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
index c1d07a2e8839..e88bdd612d71 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
@@ -112,7 +112,6 @@ static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb)
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_stats *stats_dev = vq->drv_priv;
- stats_buf->vaddr = vb2_plane_vaddr(vb, 0);
spin_lock_irq(&stats_dev->lock);
list_add_tail(&stats_buf->queue, &stats_dev->stat);
@@ -305,9 +304,8 @@ rkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris)
if (!cur_buf)
return;
- cur_stat_buf =
- (struct rkisp1_stat_buffer *)(cur_buf->vaddr);
-
+ cur_stat_buf = (struct rkisp1_stat_buffer *)
+ vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0);
if (isp_ris & RKISP1_CIF_ISP_AWB_DONE)
rkisp1_stats_get_awb_meas(stats, cur_stat_buf);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index 49503c20d320..28a06dc343fd 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -1418,7 +1418,7 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
mfc_err("Failed to unlock hardware\n");
- /* This is in deed imporant, as no operation has been
+ /* This is indeed important, as no operation has been
* scheduled, reduce the clock count as no one will
* ever do this, because no interrupt related to this try_run
* will ever come from hardware. */
diff --git a/drivers/media/platform/sti/delta/delta-ipc.c b/drivers/media/platform/sti/delta/delta-ipc.c
index 186d88f02ecd..21d3e08e259a 100644
--- a/drivers/media/platform/sti/delta/delta-ipc.c
+++ b/drivers/media/platform/sti/delta/delta-ipc.c
@@ -175,8 +175,7 @@ int delta_ipc_open(struct delta_ctx *pctx, const char *name,
msg.ipc_buf_size = ipc_buf_size;
msg.ipc_buf_paddr = ctx->ipc_buf->paddr;
- memcpy(msg.name, name, sizeof(msg.name));
- msg.name[sizeof(msg.name) - 1] = 0;
+ strscpy(msg.name, name, sizeof(msg.name));
msg.param_size = param->size;
memcpy(ctx->ipc_buf->vaddr, param->data, msg.param_size);
diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index 124a4e2bdefe..4bf7a8c2e711 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -45,22 +45,30 @@ static inline void camerarx_write(struct cal_camerarx *phy, u32 offset, u32 val)
* ------------------------------------------------------------------
*/
-static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
+static s64 cal_camerarx_get_ext_link_freq(struct cal_camerarx *phy)
{
- struct v4l2_ctrl *ctrl;
- s64 rate;
-
- ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
- if (!ctrl) {
- phy_err(phy, "no pixel rate control in subdev: %s\n",
- phy->sensor->name);
- return -EPIPE;
+ struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 = &phy->endpoint.bus.mipi_csi2;
+ u32 num_lanes = mipi_csi2->num_data_lanes;
+ const struct cal_format_info *fmtinfo;
+ u32 bpp;
+ s64 freq;
+
+ fmtinfo = cal_format_by_code(phy->formats[CAL_CAMERARX_PAD_SINK].code);
+ if (!fmtinfo)
+ return -EINVAL;
+
+ bpp = fmtinfo->bpp;
+
+ freq = v4l2_get_link_freq(phy->source->ctrl_handler, bpp, 2 * num_lanes);
+ if (freq < 0) {
+ phy_err(phy, "failed to get link freq for subdev '%s'\n",
+ phy->source->name);
+ return freq;
}
- rate = v4l2_ctrl_g_ctrl_int64(ctrl);
- phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
+ phy_dbg(3, phy, "Source Link Freq: %llu\n", freq);
- return rate;
+ return freq;
}
static void cal_camerarx_lane_config(struct cal_camerarx *phy)
@@ -116,34 +124,19 @@ void cal_camerarx_disable(struct cal_camerarx *phy)
#define TCLK_MISS 1
#define TCLK_SETTLE 14
-static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate)
+static void cal_camerarx_config(struct cal_camerarx *phy, s64 link_freq)
{
unsigned int reg0, reg1;
unsigned int ths_term, ths_settle;
- unsigned int csi2_ddrclk_khz;
- struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
- &phy->endpoint.bus.mipi_csi2;
- u32 num_lanes = mipi_csi2->num_data_lanes;
/* DPHY timing configuration */
- /*
- * CSI-2 is DDR and we only count used lanes.
- *
- * csi2_ddrclk_khz = external_rate / 1000
- * / (2 * num_lanes) * phy->fmtinfo->bpp;
- */
- csi2_ddrclk_khz = div_s64(external_rate * phy->fmtinfo->bpp,
- 2 * num_lanes * 1000);
-
- phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
-
/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
- ths_term = 20 * csi2_ddrclk_khz / 1000000;
+ ths_term = div_s64(20 * link_freq, 1000 * 1000 * 1000);
phy_dbg(1, phy, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
/* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */
- ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
+ ths_settle = div_s64(105 * link_freq, 1000 * 1000 * 1000) + 4;
phy_dbg(1, phy, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
reg0 = camerarx_read(phy, CAL_CSI2_PHY_REG0);
@@ -240,25 +233,42 @@ static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
-
- /* Enable CIO error IRQs. */
+ const u32 vc_err_mask =
+ CAL_CSI2_VC_IRQ_CS_IRQ_MASK(0) |
+ CAL_CSI2_VC_IRQ_CS_IRQ_MASK(1) |
+ CAL_CSI2_VC_IRQ_CS_IRQ_MASK(2) |
+ CAL_CSI2_VC_IRQ_CS_IRQ_MASK(3) |
+ CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(0) |
+ CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(1) |
+ CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(2) |
+ CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(3);
+
+ /* Enable CIO & VC error IRQs. */
cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
- CAL_HL_IRQ_CIO_MASK(phy->instance));
+ CAL_HL_IRQ_CIO_MASK(phy->instance) |
+ CAL_HL_IRQ_VC_MASK(phy->instance));
cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
cio_err_mask);
+ cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(phy->instance),
+ vc_err_mask);
}
static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
{
/* Disable CIO error irqs */
cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
- CAL_HL_IRQ_CIO_MASK(phy->instance));
+ CAL_HL_IRQ_CIO_MASK(phy->instance) |
+ CAL_HL_IRQ_VC_MASK(phy->instance));
cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), 0);
+ cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(phy->instance), 0);
}
static void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
{
cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+ 1, CAL_CSI2_PPI_CTRL_ECC_EN_MASK);
+
+ cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
}
@@ -270,16 +280,21 @@ static void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
static int cal_camerarx_start(struct cal_camerarx *phy)
{
- s64 external_rate;
+ s64 link_freq;
u32 sscounter;
u32 val;
int ret;
- external_rate = cal_camerarx_get_external_rate(phy);
- if (external_rate < 0)
- return external_rate;
+ if (phy->enable_count > 0) {
+ phy->enable_count++;
+ return 0;
+ }
+
+ link_freq = cal_camerarx_get_ext_link_freq(phy);
+ if (link_freq < 0)
+ return link_freq;
- ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
+ ret = v4l2_subdev_call(phy->source, core, s_power, 1);
if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
phy_err(phy, "power on failed in subdev\n");
return ret;
@@ -311,7 +326,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
* 2. CSI PHY and link initialization sequence.
*
* a. Deassert the CSI-2 PHY reset. Do not wait for reset completion
- * at this point, as it requires the external sensor to send the
+ * at this point, as it requires the external source to send the
* CSI-2 HS clock.
*/
cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
@@ -325,7 +340,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
camerarx_read(phy, CAL_CSI2_PHY_REG0);
/* Program the PHY timing parameters. */
- cal_camerarx_config(phy, external_rate);
+ cal_camerarx_config(phy, link_freq);
/*
* b. Assert the FORCERXMODE signal.
@@ -370,12 +385,12 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
cal_camerarx_power(phy, true);
/*
- * Start the sensor to enable the CSI-2 HS clock. We can now wait for
+ * Start the source to enable the CSI-2 HS clock. We can now wait for
* CSI-2 PHY reset to complete.
*/
- ret = v4l2_subdev_call(phy->sensor, video, s_stream, 1);
+ ret = v4l2_subdev_call(phy->source, video, s_stream, 1);
if (ret) {
- v4l2_subdev_call(phy->sensor, core, s_power, 0);
+ v4l2_subdev_call(phy->source, core, s_power, 0);
cal_camerarx_disable_irqs(phy);
phy_err(phy, "stream on failed in subdev\n");
return ret;
@@ -399,14 +414,18 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
/* Finally, enable the PHY Protocol Interface (PPI). */
cal_camerarx_ppi_enable(phy);
+ phy->enable_count++;
+
return 0;
}
static void cal_camerarx_stop(struct cal_camerarx *phy)
{
- unsigned int i;
int ret;
+ if (--phy->enable_count > 0)
+ return;
+
cal_camerarx_ppi_disable(phy);
cal_camerarx_disable_irqs(phy);
@@ -418,27 +437,17 @@ static void cal_camerarx_stop(struct cal_camerarx *phy)
CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
- /* Wait for power down completion */
- for (i = 0; i < 10; i++) {
- if (cal_read_field(phy->cal,
- CAL_CSI2_COMPLEXIO_CFG(phy->instance),
- CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
- CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING)
- break;
- usleep_range(1000, 1100);
- }
- phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
+ phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset\n",
phy->instance,
- cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i,
- (i >= 10) ? "(timeout)" : "");
+ cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
/* Disable the phy */
cal_camerarx_disable(phy);
- if (v4l2_subdev_call(phy->sensor, video, s_stream, 0))
+ if (v4l2_subdev_call(phy->source, video, s_stream, 0))
phy_err(phy, "stream off failed in subdev\n");
- ret = v4l2_subdev_call(phy->sensor, core, s_power, 0);
+ ret = v4l2_subdev_call(phy->source, core, s_power, 0);
if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
phy_err(phy, "power off failed in subdev\n");
}
@@ -558,16 +567,16 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
endpoint->bus.mipi_csi2.flags);
/* Retrieve the connected device and store it for later use. */
- phy->sensor_ep_node = of_graph_get_remote_endpoint(ep_node);
- phy->sensor_node = of_graph_get_port_parent(phy->sensor_ep_node);
- if (!phy->sensor_node) {
+ phy->source_ep_node = of_graph_get_remote_endpoint(ep_node);
+ phy->source_node = of_graph_get_port_parent(phy->source_ep_node);
+ if (!phy->source_node) {
phy_dbg(3, phy, "Can't get remote parent\n");
- of_node_put(phy->sensor_ep_node);
+ of_node_put(phy->source_ep_node);
ret = -EINVAL;
goto done;
}
- phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
+ phy_dbg(1, phy, "Found connected device %pOFn\n", phy->source_node);
done:
of_node_put(ep_node);
@@ -602,12 +611,18 @@ cal_camerarx_get_pad_format(struct cal_camerarx *phy,
static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable)
{
struct cal_camerarx *phy = to_cal_camerarx(sd);
+ int ret = 0;
+
+ mutex_lock(&phy->mutex);
if (enable)
- return cal_camerarx_start(phy);
+ ret = cal_camerarx_start(phy);
+ else
+ cal_camerarx_stop(phy);
- cal_camerarx_stop(phy);
- return 0;
+ mutex_unlock(&phy->mutex);
+
+ return ret;
}
static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
@@ -615,27 +630,36 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_mbus_code_enum *code)
{
struct cal_camerarx *phy = to_cal_camerarx(sd);
+ int ret = 0;
+
+ mutex_lock(&phy->mutex);
/* No transcoding, source and sink codes must match. */
- if (code->pad == CAL_CAMERARX_PAD_SOURCE) {
+ if (cal_rx_pad_is_source(code->pad)) {
struct v4l2_mbus_framefmt *fmt;
- if (code->index > 0)
- return -EINVAL;
+ if (code->index > 0) {
+ ret = -EINVAL;
+ goto out;
+ }
fmt = cal_camerarx_get_pad_format(phy, sd_state,
CAL_CAMERARX_PAD_SINK,
code->which);
code->code = fmt->code;
- return 0;
- }
+ } else {
+ if (code->index >= cal_num_formats) {
+ ret = -EINVAL;
+ goto out;
+ }
- if (code->index >= cal_num_formats)
- return -EINVAL;
+ code->code = cal_formats[code->index].code;
+ }
- code->code = cal_formats[code->index].code;
+out:
+ mutex_unlock(&phy->mutex);
- return 0;
+ return ret;
}
static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
@@ -644,38 +668,46 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
{
struct cal_camerarx *phy = to_cal_camerarx(sd);
const struct cal_format_info *fmtinfo;
+ int ret = 0;
if (fse->index > 0)
return -EINVAL;
+ mutex_lock(&phy->mutex);
+
/* No transcoding, source and sink formats must match. */
- if (fse->pad == CAL_CAMERARX_PAD_SOURCE) {
+ if (cal_rx_pad_is_source(fse->pad)) {
struct v4l2_mbus_framefmt *fmt;
fmt = cal_camerarx_get_pad_format(phy, sd_state,
CAL_CAMERARX_PAD_SINK,
fse->which);
- if (fse->code != fmt->code)
- return -EINVAL;
+ if (fse->code != fmt->code) {
+ ret = -EINVAL;
+ goto out;
+ }
fse->min_width = fmt->width;
fse->max_width = fmt->width;
fse->min_height = fmt->height;
fse->max_height = fmt->height;
+ } else {
+ fmtinfo = cal_format_by_code(fse->code);
+ if (!fmtinfo) {
+ ret = -EINVAL;
+ goto out;
+ }
- return 0;
+ fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
+ fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
+ fse->min_height = CAL_MIN_HEIGHT_LINES;
+ fse->max_height = CAL_MAX_HEIGHT_LINES;
}
- fmtinfo = cal_format_by_code(fse->code);
- if (!fmtinfo)
- return -EINVAL;
-
- fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
- fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
- fse->min_height = CAL_MIN_HEIGHT_LINES;
- fse->max_height = CAL_MAX_HEIGHT_LINES;
+out:
+ mutex_unlock(&phy->mutex);
- return 0;
+ return ret;
}
static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd,
@@ -685,10 +717,14 @@ static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd,
struct cal_camerarx *phy = to_cal_camerarx(sd);
struct v4l2_mbus_framefmt *fmt;
+ mutex_lock(&phy->mutex);
+
fmt = cal_camerarx_get_pad_format(phy, sd_state, format->pad,
format->which);
format->format = *fmt;
+ mutex_unlock(&phy->mutex);
+
return 0;
}
@@ -702,21 +738,18 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
unsigned int bpp;
/* No transcoding, source and sink formats must match. */
- if (format->pad == CAL_CAMERARX_PAD_SOURCE)
+ if (cal_rx_pad_is_source(format->pad))
return cal_camerarx_sd_get_fmt(sd, sd_state, format);
/*
- * Default to the first format is the requested media bus code isn't
+ * Default to the first format if the requested media bus code isn't
* supported.
*/
fmtinfo = cal_format_by_code(format->format.code);
if (!fmtinfo)
fmtinfo = &cal_formats[0];
- /*
- * Clamp the size, update the code. The field and colorspace are
- * accepted as-is.
- */
+ /* Clamp the size, update the code. The colorspace is accepted as-is. */
bpp = ALIGN(fmtinfo->bpp, 8);
format->format.width = clamp_t(unsigned int, format->format.width,
@@ -726,20 +759,23 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
CAL_MIN_HEIGHT_LINES,
CAL_MAX_HEIGHT_LINES);
format->format.code = fmtinfo->code;
+ format->format.field = V4L2_FIELD_NONE;
/* Store the format and propagate it to the source pad. */
+
+ mutex_lock(&phy->mutex);
+
fmt = cal_camerarx_get_pad_format(phy, sd_state,
CAL_CAMERARX_PAD_SINK,
format->which);
*fmt = format->format;
fmt = cal_camerarx_get_pad_format(phy, sd_state,
- CAL_CAMERARX_PAD_SOURCE,
+ CAL_CAMERARX_PAD_FIRST_SOURCE,
format->which);
*fmt = format->format;
- if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
- phy->fmtinfo = fmtinfo;
+ mutex_unlock(&phy->mutex);
return 0;
}
@@ -798,6 +834,7 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
struct platform_device *pdev = to_platform_device(cal->dev);
struct cal_camerarx *phy;
struct v4l2_subdev *sd;
+ unsigned int i;
int ret;
phy = kzalloc(sizeof(*phy), GFP_KERNEL);
@@ -807,6 +844,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
phy->cal = cal;
phy->instance = instance;
+ mutex_init(&phy->mutex);
+
phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
(instance == 0) ?
"cal_rx_core0" :
@@ -838,14 +877,17 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
sd->dev = cal->dev;
phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
- phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+ for (i = CAL_CAMERARX_PAD_FIRST_SOURCE; i < CAL_CAMERARX_NUM_PADS; ++i)
+ phy->pads[i].flags = MEDIA_PAD_FL_SOURCE;
sd->entity.ops = &cal_camerarx_media_ops;
ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads),
phy->pads);
if (ret)
goto error;
- cal_camerarx_sd_init_cfg(sd, NULL);
+ ret = cal_camerarx_sd_init_cfg(sd, NULL);
+ if (ret)
+ goto error;
ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd);
if (ret)
@@ -866,7 +908,8 @@ void cal_camerarx_destroy(struct cal_camerarx *phy)
v4l2_device_unregister_subdev(&phy->subdev);
media_entity_cleanup(&phy->subdev.entity);
- of_node_put(phy->sensor_ep_node);
- of_node_put(phy->sensor_node);
+ of_node_put(phy->source_ep_node);
+ of_node_put(phy->source_node);
+ mutex_destroy(&phy->mutex);
kfree(phy);
}
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 15fb5360cf13..7799da1cc261 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -102,8 +102,8 @@ static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
return NULL;
}
-static int cal_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
+static int cal_legacy_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@@ -128,7 +128,7 @@ static int __subdev_get_format(struct cal_ctx *ctx,
sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sd_fmt.pad = 0;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, get_fmt, NULL, &sd_fmt);
+ ret = v4l2_subdev_call(ctx->phy->source, pad, get_fmt, NULL, &sd_fmt);
if (ret)
return ret;
@@ -151,7 +151,7 @@ static int __subdev_set_format(struct cal_ctx *ctx,
sd_fmt.pad = 0;
*mbus_fmt = *fmt;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, set_fmt, NULL, &sd_fmt);
+ ret = v4l2_subdev_call(ctx->phy->source, pad, set_fmt, NULL, &sd_fmt);
if (ret)
return ret;
@@ -189,8 +189,8 @@ static void cal_calc_format_size(struct cal_ctx *ctx,
f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
}
-static int cal_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int cal_legacy_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@@ -216,7 +216,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
fse.code = fmtinfo->code;
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
for (fse.index = 0; ; fse.index++) {
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size,
+ ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size,
NULL, &fse);
if (ret)
break;
@@ -249,8 +249,8 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
-static int cal_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+static int cal_legacy_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct cal_ctx *ctx = video_drvdata(file);
struct vb2_queue *q = &ctx->vb_vidq;
@@ -266,7 +266,7 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
return -EBUSY;
}
- ret = cal_try_fmt_vid_cap(file, priv, f);
+ ret = cal_legacy_try_fmt_vid_cap(file, priv, f);
if (ret < 0)
return ret;
@@ -300,8 +300,8 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
-static int cal_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
+static int cal_legacy_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *fsize)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@@ -321,7 +321,7 @@ static int cal_enum_framesizes(struct file *file, void *fh,
fse.code = fmtinfo->code;
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL,
+ ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size, NULL,
&fse);
if (ret)
return ret;
@@ -337,8 +337,8 @@ static int cal_enum_framesizes(struct file *file, void *fh,
return 0;
}
-static int cal_enum_input(struct file *file, void *priv,
- struct v4l2_input *inp)
+static int cal_legacy_enum_input(struct file *file, void *priv,
+ struct v4l2_input *inp)
{
if (inp->index > 0)
return -EINVAL;
@@ -348,20 +348,20 @@ static int cal_enum_input(struct file *file, void *priv,
return 0;
}
-static int cal_g_input(struct file *file, void *priv, unsigned int *i)
+static int cal_legacy_g_input(struct file *file, void *priv, unsigned int *i)
{
*i = 0;
return 0;
}
-static int cal_s_input(struct file *file, void *priv, unsigned int i)
+static int cal_legacy_s_input(struct file *file, void *priv, unsigned int i)
{
return i > 0 ? -EINVAL : 0;
}
/* timeperframe is arbitrary and continuous */
-static int cal_enum_frameintervals(struct file *file, void *priv,
- struct v4l2_frmivalenum *fival)
+static int cal_legacy_enum_frameintervals(struct file *file, void *priv,
+ struct v4l2_frmivalenum *fival)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@@ -378,7 +378,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
return -EINVAL;
fie.code = fmtinfo->code;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval,
+ ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_interval,
NULL, &fie);
if (ret)
return ret;
@@ -388,13 +388,27 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
return 0;
}
-static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
+static int cal_legacy_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ struct cal_ctx *ctx = video_drvdata(file);
+
+ return v4l2_g_parm_cap(video_devdata(file), ctx->phy->source, a);
+}
+
+static int cal_legacy_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ struct cal_ctx *ctx = video_drvdata(file);
+
+ return v4l2_s_parm_cap(video_devdata(file), ctx->phy->source, a);
+}
+
+static const struct v4l2_ioctl_ops cal_ioctl_legacy_ops = {
.vidioc_querycap = cal_querycap,
- .vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap,
+ .vidioc_enum_fmt_vid_cap = cal_legacy_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap,
- .vidioc_enum_framesizes = cal_enum_framesizes,
+ .vidioc_try_fmt_vid_cap = cal_legacy_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = cal_legacy_s_fmt_vid_cap,
+ .vidioc_enum_framesizes = cal_legacy_enum_framesizes,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
@@ -402,15 +416,17 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_expbuf = vb2_ioctl_expbuf,
- .vidioc_enum_input = cal_enum_input,
- .vidioc_g_input = cal_g_input,
- .vidioc_s_input = cal_s_input,
- .vidioc_enum_frameintervals = cal_enum_frameintervals,
+ .vidioc_enum_input = cal_legacy_enum_input,
+ .vidioc_g_input = cal_legacy_g_input,
+ .vidioc_s_input = cal_legacy_s_input,
+ .vidioc_enum_frameintervals = cal_legacy_enum_frameintervals,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_log_status = v4l2_ctrl_log_status,
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+ .vidioc_g_parm = cal_legacy_g_parm,
+ .vidioc_s_parm = cal_legacy_s_parm,
};
/* ------------------------------------------------------------------
@@ -421,13 +437,28 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
static int cal_mc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
+ unsigned int i;
+ unsigned int idx;
+
if (f->index >= cal_num_formats)
return -EINVAL;
- f->pixelformat = cal_formats[f->index].fourcc;
- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ idx = 0;
- return 0;
+ for (i = 0; i < cal_num_formats; ++i) {
+ if (f->mbus_code && cal_formats[i].code != f->mbus_code)
+ continue;
+
+ if (idx == f->index) {
+ f->pixelformat = cal_formats[i].fourcc;
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ return 0;
+ }
+
+ idx++;
+ }
+
+ return -EINVAL;
}
static void cal_mc_try_fmt(struct cal_ctx *ctx, struct v4l2_format *f,
@@ -656,8 +687,13 @@ static void cal_release_buffers(struct cal_ctx *ctx,
static int cal_video_check_format(struct cal_ctx *ctx)
{
const struct v4l2_mbus_framefmt *format;
+ struct media_pad *remote_pad;
+
+ remote_pad = media_entity_remote_pad(&ctx->pad);
+ if (!remote_pad)
+ return -ENODEV;
- format = &ctx->phy->formats[CAL_CAMERARX_PAD_SOURCE];
+ format = &ctx->phy->formats[remote_pad->index];
if (ctx->fmtinfo->code != format->code ||
ctx->v_fmt.fmt.pix.height != format->height ||
@@ -692,9 +728,15 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
goto error_pipeline;
}
+ ret = cal_ctx_prepare(ctx);
+ if (ret) {
+ ctx_err(ctx, "Failed to prepare context: %d\n", ret);
+ goto error_pipeline;
+ }
+
spin_lock_irq(&ctx->dma.lock);
buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
- ctx->dma.pending = buf;
+ ctx->dma.active = buf;
list_del(&buf->list);
spin_unlock_irq(&ctx->dma.lock);
@@ -719,6 +761,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
error_stop:
cal_ctx_stop(ctx);
pm_runtime_put_sync(ctx->cal->dev);
+ cal_ctx_unprepare(ctx);
error_pipeline:
media_pipeline_stop(&ctx->vdev.entity);
@@ -738,6 +781,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
pm_runtime_put_sync(ctx->cal->dev);
+ cal_ctx_unprepare(ctx);
+
cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
media_pipeline_stop(&ctx->vdev.entity);
@@ -785,20 +830,20 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
memset(&mbus_code, 0, sizeof(mbus_code));
mbus_code.index = j;
mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
- ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_mbus_code,
+ ret = v4l2_subdev_call(ctx->phy->source, pad, enum_mbus_code,
NULL, &mbus_code);
if (ret == -EINVAL)
break;
if (ret) {
ctx_err(ctx, "Error enumerating mbus codes in subdev %s: %d\n",
- ctx->phy->sensor->name, ret);
+ ctx->phy->source->name, ret);
return ret;
}
ctx_dbg(2, ctx,
"subdev %s: code: %04x idx: %u\n",
- ctx->phy->sensor->name, mbus_code.code, j);
+ ctx->phy->source->name, mbus_code.code, j);
for (k = 0; k < cal_num_formats; k++) {
fmtinfo = &cal_formats[k];
@@ -816,7 +861,7 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
if (i == 0) {
ctx_err(ctx, "No suitable format reported by subdev %s\n",
- ctx->phy->sensor->name);
+ ctx->phy->source->name);
return -EINVAL;
}
@@ -841,22 +886,57 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
return 0;
}
+static int cal_ctx_v4l2_init_mc_format(struct cal_ctx *ctx)
+{
+ const struct cal_format_info *fmtinfo;
+ struct v4l2_pix_format *pix_fmt = &ctx->v_fmt.fmt.pix;
+
+ fmtinfo = cal_format_by_code(MEDIA_BUS_FMT_UYVY8_2X8);
+ if (!fmtinfo)
+ return -EINVAL;
+
+ pix_fmt->width = 640;
+ pix_fmt->height = 480;
+ pix_fmt->field = V4L2_FIELD_NONE;
+ pix_fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
+ pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
+ pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB;
+ pix_fmt->pixelformat = fmtinfo->fourcc;
+
+ ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ /* Save current format */
+ cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt);
+ ctx->fmtinfo = fmtinfo;
+
+ return 0;
+}
+
int cal_ctx_v4l2_register(struct cal_ctx *ctx)
{
struct video_device *vfd = &ctx->vdev;
int ret;
- ret = cal_ctx_v4l2_init_formats(ctx);
- if (ret)
- return ret;
-
if (!cal_mc_api) {
struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
- ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler,
+ ret = cal_ctx_v4l2_init_formats(ctx);
+ if (ret) {
+ ctx_err(ctx, "Failed to init formats: %d\n", ret);
+ return ret;
+ }
+
+ ret = v4l2_ctrl_add_handler(hdl, ctx->phy->source->ctrl_handler,
NULL, true);
if (ret < 0) {
- ctx_err(ctx, "Failed to add sensor ctrl handler\n");
+ ctx_err(ctx, "Failed to add source ctrl handler\n");
+ return ret;
+ }
+ } else {
+ ret = cal_ctx_v4l2_init_mc_format(ctx);
+ if (ret) {
+ ctx_err(ctx, "Failed to init format: %d\n", ret);
return ret;
}
}
@@ -868,13 +948,13 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx)
}
ret = media_create_pad_link(&ctx->phy->subdev.entity,
- CAL_CAMERARX_PAD_SOURCE,
+ CAL_CAMERARX_PAD_FIRST_SOURCE,
&vfd->entity, 0,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED);
if (ret) {
ctx_err(ctx, "Failed to create media link for context %u\n",
- ctx->index);
+ ctx->dma_ctx);
video_unregister_device(vfd);
return ret;
}
@@ -926,9 +1006,9 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
| (cal_mc_api ? V4L2_CAP_IO_MC : 0);
vfd->v4l2_dev = &ctx->cal->v4l2_dev;
vfd->queue = q;
- snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
+ snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->dma_ctx);
vfd->release = video_device_release_empty;
- vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_video_ops;
+ vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_legacy_ops;
vfd->lock = &ctx->mutex;
video_set_drvdata(vfd, ctx);
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 76fe7a8b33f6..8e469d518a74 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -290,11 +290,42 @@ void cal_quickdump_regs(struct cal_dev *cal)
* ------------------------------------------------------------------
*/
+#define CAL_MAX_PIX_PROC 4
+
+static int cal_reserve_pix_proc(struct cal_dev *cal)
+{
+ unsigned long ret;
+
+ spin_lock(&cal->v4l2_dev.lock);
+
+ ret = find_first_zero_bit(&cal->reserved_pix_proc_mask, CAL_MAX_PIX_PROC);
+
+ if (ret == CAL_MAX_PIX_PROC) {
+ spin_unlock(&cal->v4l2_dev.lock);
+ return -ENOSPC;
+ }
+
+ cal->reserved_pix_proc_mask |= BIT(ret);
+
+ spin_unlock(&cal->v4l2_dev.lock);
+
+ return ret;
+}
+
+static void cal_release_pix_proc(struct cal_dev *cal, unsigned int pix_proc_num)
+{
+ spin_lock(&cal->v4l2_dev.lock);
+
+ cal->reserved_pix_proc_mask &= ~BIT(pix_proc_num);
+
+ spin_unlock(&cal->v4l2_dev.lock);
+}
+
static void cal_ctx_csi2_config(struct cal_ctx *ctx)
{
u32 val;
- val = cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
+ val = cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx));
cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
/*
* DT type: MIPI CSI-2 Specs
@@ -304,15 +335,16 @@ static void cal_ctx_csi2_config(struct cal_ctx *ctx)
* 0x2A: RAW8 1 pixel = 1 byte
* 0x1E: YUV422 2 pixels = 4 bytes
*/
- cal_set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
- cal_set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
+ cal_set_field(&val, ctx->datatype, CAL_CSI2_CTX_DT_MASK);
+ cal_set_field(&val, ctx->vc, CAL_CSI2_CTX_VC_MASK);
cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
CAL_CSI2_CTX_PACK_MODE_MASK);
- cal_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
- ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index,
- cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
+ cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), val);
+ ctx_dbg(3, ctx, "CAL_CSI2_CTX(%u, %u) = 0x%08x\n",
+ ctx->phy->instance, ctx->csi2_ctx,
+ cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx)));
}
static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
@@ -354,16 +386,16 @@ static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
break;
}
- val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->index));
+ val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc));
cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
- cal_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
- ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index,
- cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
+ cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), val);
+ ctx_dbg(3, ctx, "CAL_PIX_PROC(%u) = 0x%08x\n", ctx->pix_proc,
+ cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc)));
}
static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
@@ -371,27 +403,25 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline;
u32 val;
- val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
+ val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
cal_set_field(&val, ctx->v_fmt.fmt.pix.height,
CAL_WR_DMA_CTRL_YSIZE_MASK);
cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
CAL_WR_DMA_CTRL_DTAG_MASK);
- cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
- CAL_WR_DMA_CTRL_MODE_MASK);
cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
CAL_WR_DMA_CTRL_PATTERN_MASK);
cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
- cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
- ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
- cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
+ cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
+ ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->dma_ctx,
+ cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx)));
- cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->index),
+ cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx),
stride / 16, CAL_WR_DMA_OFST_MASK);
- ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
- cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
+ ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->dma_ctx,
+ cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx)));
- val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
+ val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx));
/* 64 bit word means no skipping */
cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
/*
@@ -400,34 +430,32 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
* written per line.
*/
cal_set_field(&val, stride / 8, CAL_WR_DMA_XSIZE_MASK);
- cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
- ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
- cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
-
- val = cal_read(ctx->cal, CAL_CTRL);
- cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
- CAL_CTRL_BURSTSIZE_MASK);
- cal_set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
- cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
- CAL_CTRL_POSTED_WRITES_MASK);
- cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
- cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
- cal_write(ctx->cal, CAL_CTRL, val);
- ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
+ cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx), val);
+ ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->dma_ctx,
+ cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx)));
}
void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
{
- cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), addr);
+ cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->dma_ctx), addr);
+}
+
+static void cal_ctx_wr_dma_enable(struct cal_ctx *ctx)
+{
+ u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
+
+ cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
+ CAL_WR_DMA_CTRL_MODE_MASK);
+ cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
}
static void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
{
- u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
+ u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_DIS,
CAL_WR_DMA_CTRL_MODE_MASK);
- cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
+ cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
}
static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
@@ -441,6 +469,31 @@ static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
return stopped;
}
+int cal_ctx_prepare(struct cal_ctx *ctx)
+{
+ int ret;
+
+ ctx->use_pix_proc = !ctx->fmtinfo->meta;
+
+ if (ctx->use_pix_proc) {
+ ret = cal_reserve_pix_proc(ctx->cal);
+ if (ret < 0) {
+ ctx_err(ctx, "Failed to reserve pix proc: %d\n", ret);
+ return ret;
+ }
+
+ ctx->pix_proc = ret;
+ }
+
+ return 0;
+}
+
+void cal_ctx_unprepare(struct cal_ctx *ctx)
+{
+ if (ctx->use_pix_proc)
+ cal_release_pix_proc(ctx->cal, ctx->pix_proc);
+}
+
void cal_ctx_start(struct cal_ctx *ctx)
{
ctx->sequence = 0;
@@ -448,14 +501,17 @@ void cal_ctx_start(struct cal_ctx *ctx)
/* Configure the CSI-2, pixel processing and write DMA contexts. */
cal_ctx_csi2_config(ctx);
- cal_ctx_pix_proc_config(ctx);
+ if (ctx->use_pix_proc)
+ cal_ctx_pix_proc_config(ctx);
cal_ctx_wr_dma_config(ctx);
/* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
- CAL_HL_IRQ_MASK(ctx->index));
+ CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx));
cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
- CAL_HL_IRQ_MASK(ctx->index));
+ CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx));
+
+ cal_ctx_wr_dma_enable(ctx);
}
void cal_ctx_stop(struct cal_ctx *ctx)
@@ -479,11 +535,18 @@ void cal_ctx_stop(struct cal_ctx *ctx)
/* Disable IRQ_WDMA_END and IRQ_WDMA_START. */
cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1),
- CAL_HL_IRQ_MASK(ctx->index));
+ CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx));
cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2),
- CAL_HL_IRQ_MASK(ctx->index));
+ CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx));
ctx->dma.state = CAL_DMA_STOPPED;
+
+ /* Disable CSI2 context */
+ cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), 0);
+
+ /* Disable pix proc */
+ if (ctx->use_pix_proc)
+ cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), 0);
}
/* ------------------------------------------------------------------
@@ -577,6 +640,16 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
cio_stat);
}
+
+ if (status & CAL_HL_IRQ_VC_MASK(i)) {
+ u32 vc_stat = cal_read(cal, CAL_CSI2_VC_IRQSTATUS(i));
+
+ dev_err_ratelimited(cal->dev,
+ "CIO%u VC error: %#08x\n",
+ i, vc_stat);
+
+ cal_write(cal, CAL_CSI2_VC_IRQSTATUS(i), vc_stat);
+ }
}
}
@@ -588,8 +661,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
/* Clear Interrupt status */
cal_write(cal, CAL_HL_IRQSTATUS(1), status);
- for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
- if (status & CAL_HL_IRQ_MASK(i))
+ for (i = 0; i < cal->num_contexts; ++i) {
+ if (status & CAL_HL_IRQ_WDMA_END_MASK(i))
cal_irq_wdma_end(cal->ctx[i]);
}
}
@@ -602,8 +675,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
/* Clear Interrupt status */
cal_write(cal, CAL_HL_IRQSTATUS(2), status);
- for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
- if (status & CAL_HL_IRQ_MASK(i))
+ for (i = 0; i < cal->num_contexts; ++i) {
+ if (status & CAL_HL_IRQ_WDMA_START_MASK(i))
cal_irq_wdma_start(cal->ctx[i]);
}
}
@@ -635,20 +708,20 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
int pad;
int ret;
- if (phy->sensor) {
+ if (phy->source) {
phy_info(phy, "Rejecting subdev %s (Already set!!)",
subdev->name);
return 0;
}
- phy->sensor = subdev;
- phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
+ phy->source = subdev;
+ phy_dbg(1, phy, "Using source %s for capture\n", subdev->name);
pad = media_entity_get_fwnode_pad(&subdev->entity,
- of_fwnode_handle(phy->sensor_ep_node),
+ of_fwnode_handle(phy->source_ep_node),
MEDIA_PAD_FL_SOURCE);
if (pad < 0) {
- phy_err(phy, "Sensor %s has no connected source pad\n",
+ phy_err(phy, "Source %s has no connected source pad\n",
subdev->name);
return pad;
}
@@ -658,7 +731,7 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED);
if (ret) {
- phy_err(phy, "Failed to create media link for sensor %s\n",
+ phy_err(phy, "Failed to create media link for source %s\n",
subdev->name);
return ret;
}
@@ -670,15 +743,30 @@ static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
{
struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
unsigned int i;
- int ret = 0;
+ int ret;
- for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
- if (cal->ctx[i])
- cal_ctx_v4l2_register(cal->ctx[i]);
+ for (i = 0; i < cal->num_contexts; ++i) {
+ ret = cal_ctx_v4l2_register(cal->ctx[i]);
+ if (ret)
+ goto err_ctx_unreg;
}
- if (cal_mc_api)
- ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
+ if (!cal_mc_api)
+ return 0;
+
+ ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
+ if (ret)
+ goto err_ctx_unreg;
+
+ return 0;
+
+err_ctx_unreg:
+ for (; i > 0; --i) {
+ if (!cal->ctx[i - 1])
+ continue;
+
+ cal_ctx_v4l2_unregister(cal->ctx[i - 1]);
+ }
return ret;
}
@@ -701,10 +789,10 @@ static int cal_async_notifier_register(struct cal_dev *cal)
struct cal_v4l2_async_subdev *casd;
struct fwnode_handle *fwnode;
- if (!phy->sensor_node)
+ if (!phy->source_node)
continue;
- fwnode = of_fwnode_handle(phy->sensor_node);
+ fwnode = of_fwnode_handle(phy->source_node);
casd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
fwnode,
struct cal_v4l2_async_subdev);
@@ -777,10 +865,8 @@ static void cal_media_unregister(struct cal_dev *cal)
unsigned int i;
/* Unregister all the V4L2 video devices. */
- for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
- if (cal->ctx[i])
- cal_ctx_v4l2_unregister(cal->ctx[i]);
- }
+ for (i = 0; i < cal->num_contexts; i++)
+ cal_ctx_v4l2_unregister(cal->ctx[i]);
cal_async_notifier_unregister(cal);
media_device_unregister(&cal->mdev);
@@ -825,13 +911,6 @@ static int cal_media_init(struct cal_dev *cal)
*/
static void cal_media_cleanup(struct cal_dev *cal)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
- if (cal->ctx[i])
- cal_ctx_v4l2_cleanup(cal->ctx[i]);
- }
-
v4l2_device_unregister(&cal->v4l2_dev);
media_device_cleanup(&cal->mdev);
@@ -848,14 +927,17 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
struct cal_ctx *ctx;
int ret;
- ctx = devm_kzalloc(cal->dev, sizeof(*ctx), GFP_KERNEL);
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return NULL;
ctx->cal = cal;
ctx->phy = cal->phy[inst];
- ctx->index = inst;
+ ctx->dma_ctx = inst;
+ ctx->csi2_ctx = inst;
ctx->cport = inst;
+ ctx->vc = 0;
+ ctx->datatype = CAL_CSI2_CTX_DT_ANY;
ret = cal_ctx_v4l2_init(ctx);
if (ret)
@@ -864,6 +946,13 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
return ctx;
}
+static void cal_ctx_destroy(struct cal_ctx *ctx)
+{
+ cal_ctx_v4l2_cleanup(ctx);
+
+ kfree(ctx);
+}
+
static const struct of_device_id cal_of_match[] = {
{
.compatible = "ti,dra72-cal",
@@ -976,7 +1065,6 @@ static int cal_init_camerarx_regmap(struct cal_dev *cal)
static int cal_probe(struct platform_device *pdev)
{
struct cal_dev *cal;
- struct cal_ctx *ctx;
bool connected = false;
unsigned int i;
int ret;
@@ -1045,7 +1133,7 @@ static int cal_probe(struct platform_device *pdev)
goto error_camerarx;
}
- if (cal->phy[i]->sensor_node)
+ if (cal->phy[i]->source_node)
connected = true;
}
@@ -1057,15 +1145,17 @@ static int cal_probe(struct platform_device *pdev)
/* Create contexts. */
for (i = 0; i < cal->data->num_csi2_phy; ++i) {
- if (!cal->phy[i]->sensor_node)
+ if (!cal->phy[i]->source_node)
continue;
- cal->ctx[i] = cal_ctx_create(cal, i);
- if (!cal->ctx[i]) {
- cal_err(cal, "Failed to create context %u\n", i);
+ cal->ctx[cal->num_contexts] = cal_ctx_create(cal, i);
+ if (!cal->ctx[cal->num_contexts]) {
+ cal_err(cal, "Failed to create context %u\n", cal->num_contexts);
ret = -ENODEV;
goto error_context;
}
+
+ cal->num_contexts++;
}
/* Register the media device. */
@@ -1076,11 +1166,8 @@ static int cal_probe(struct platform_device *pdev)
return 0;
error_context:
- for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
- ctx = cal->ctx[i];
- if (ctx)
- cal_ctx_v4l2_cleanup(ctx);
- }
+ for (i = 0; i < cal->num_contexts; i++)
+ cal_ctx_destroy(cal->ctx[i]);
error_camerarx:
for (i = 0; i < cal->data->num_csi2_phy; i++)
@@ -1106,16 +1193,17 @@ static int cal_remove(struct platform_device *pdev)
cal_media_unregister(cal);
- for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
- if (cal->phy[i])
- cal_camerarx_disable(cal->phy[i]);
- }
+ for (i = 0; i < cal->data->num_csi2_phy; i++)
+ cal_camerarx_disable(cal->phy[i]);
- cal_media_cleanup(cal);
+ for (i = 0; i < cal->num_contexts; i++)
+ cal_ctx_destroy(cal->ctx[i]);
for (i = 0; i < cal->data->num_csi2_phy; i++)
cal_camerarx_destroy(cal->phy[i]);
+ cal_media_cleanup(cal);
+
if (ret >= 0)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -1127,6 +1215,7 @@ static int cal_runtime_resume(struct device *dev)
{
struct cal_dev *cal = dev_get_drvdata(dev);
unsigned int i;
+ u32 val;
if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
/*
@@ -1143,6 +1232,17 @@ static int cal_runtime_resume(struct device *dev)
*/
cal_write(cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
+ val = cal_read(cal, CAL_CTRL);
+ cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
+ CAL_CTRL_BURSTSIZE_MASK);
+ cal_set_field(&val, 0xf, CAL_CTRL_TAGCNT_MASK);
+ cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
+ CAL_CTRL_POSTED_WRITES_MASK);
+ cal_set_field(&val, 0xff, CAL_CTRL_MFLAGL_MASK);
+ cal_set_field(&val, 0xff, CAL_CTRL_MFLAGH_MASK);
+ cal_write(cal, CAL_CTRL, val);
+ cal_dbg(3, cal, "CAL_CTRL = 0x%08x\n", cal_read(cal, CAL_CTRL));
+
return 0;
}
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index db0e408eaa94..527e22d022f3 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -29,7 +29,7 @@
#include <media/videobuf2-v4l2.h>
#define CAL_MODULE_NAME "cal"
-#define CAL_NUM_CONTEXT 2
+#define CAL_MAX_NUM_CONTEXT 8
#define CAL_NUM_CSI2_PORTS 2
/*
@@ -44,7 +44,22 @@
#define CAL_MAX_HEIGHT_LINES 16383
#define CAL_CAMERARX_PAD_SINK 0
-#define CAL_CAMERARX_PAD_SOURCE 1
+#define CAL_CAMERARX_PAD_FIRST_SOURCE 1
+#define CAL_CAMERARX_NUM_SOURCE_PADS 1
+#define CAL_CAMERARX_NUM_PADS (1 + CAL_CAMERARX_NUM_SOURCE_PADS)
+
+static inline bool cal_rx_pad_is_sink(u32 pad)
+{
+ /* Camera RX has 1 sink pad, and N source pads */
+ return pad == 0;
+}
+
+static inline bool cal_rx_pad_is_source(u32 pad)
+{
+ /* Camera RX has 1 sink pad, and N source pads */
+ return pad >= CAL_CAMERARX_PAD_FIRST_SOURCE &&
+ pad <= CAL_CAMERARX_NUM_SOURCE_PADS;
+}
struct device;
struct device_node;
@@ -73,6 +88,7 @@ struct cal_format_info {
u32 code;
/* Bits per pixel */
u8 bpp;
+ bool meta;
};
/* buffer for one video frame */
@@ -149,22 +165,29 @@ struct cal_data {
struct cal_camerarx {
void __iomem *base;
struct resource *res;
- struct device *dev;
struct regmap_field *fields[F_MAX_FIELDS];
struct cal_dev *cal;
unsigned int instance;
struct v4l2_fwnode_endpoint endpoint;
- struct device_node *sensor_ep_node;
- struct device_node *sensor_node;
- struct v4l2_subdev *sensor;
+ struct device_node *source_ep_node;
+ struct device_node *source_node;
+ struct v4l2_subdev *source;
struct media_pipeline pipe;
struct v4l2_subdev subdev;
- struct media_pad pads[2];
- struct v4l2_mbus_framefmt formats[2];
- const struct cal_format_info *fmtinfo;
+ struct media_pad pads[CAL_CAMERARX_NUM_PADS];
+ struct v4l2_mbus_framefmt formats[CAL_CAMERARX_NUM_PADS];
+
+ /*
+ * Lock for camerarx ops. Protects:
+ * - formats
+ * - enable_count
+ */
+ struct mutex mutex;
+
+ unsigned int enable_count;
};
struct cal_dev {
@@ -184,11 +207,14 @@ struct cal_dev {
/* Camera Core Module handle */
struct cal_camerarx *phy[CAL_NUM_CSI2_PORTS];
- struct cal_ctx *ctx[CAL_NUM_CONTEXT];
+ u32 num_contexts;
+ struct cal_ctx *ctx[CAL_MAX_NUM_CONTEXT];
struct media_device mdev;
struct v4l2_device v4l2_dev;
struct v4l2_async_notifier notifier;
+
+ unsigned long reserved_pix_proc_mask;
};
/*
@@ -212,14 +238,20 @@ struct cal_ctx {
/* Used to store current pixel format */
struct v4l2_format v_fmt;
- /* Current subdev enumerated format */
+ /* Current subdev enumerated format (legacy) */
const struct cal_format_info **active_fmt;
unsigned int num_active_fmt;
unsigned int sequence;
struct vb2_queue vb_vidq;
- unsigned int index;
- unsigned int cport;
+ u8 dma_ctx;
+ u8 cport;
+ u8 csi2_ctx;
+ u8 pix_proc;
+ u8 vc;
+ u8 datatype;
+
+ bool use_pix_proc;
};
extern unsigned int cal_debug;
@@ -237,11 +269,11 @@ extern bool cal_mc_api;
dev_err((cal)->dev, fmt, ##arg)
#define ctx_dbg(level, ctx, fmt, arg...) \
- cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
+ cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
#define ctx_info(ctx, fmt, arg...) \
- cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
+ cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
#define ctx_err(ctx, fmt, arg...) \
- cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
+ cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
#define phy_dbg(level, phy, fmt, arg...) \
cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
@@ -297,6 +329,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
unsigned int instance);
void cal_camerarx_destroy(struct cal_camerarx *phy);
+int cal_ctx_prepare(struct cal_ctx *ctx);
+void cal_ctx_unprepare(struct cal_ctx *ctx);
void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr);
void cal_ctx_start(struct cal_ctx *ctx);
void cal_ctx_stop(struct cal_ctx *ctx);
diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h
index f752096dcf7f..40e4f972fcb7 100644
--- a/drivers/media/platform/ti-vpe/cal_regs.h
+++ b/drivers/media/platform/ti-vpe/cal_regs.h
@@ -72,22 +72,8 @@
#define CAL_CSI2_TIMING(m) (0x314U + (m) * 0x80U)
#define CAL_CSI2_VC_IRQENABLE(m) (0x318U + (m) * 0x80U)
#define CAL_CSI2_VC_IRQSTATUS(m) (0x328U + (m) * 0x80U)
-#define CAL_CSI2_CTX0(m) (0x330U + (m) * 0x80U)
-#define CAL_CSI2_CTX1(m) (0x334U + (m) * 0x80U)
-#define CAL_CSI2_CTX2(m) (0x338U + (m) * 0x80U)
-#define CAL_CSI2_CTX3(m) (0x33cU + (m) * 0x80U)
-#define CAL_CSI2_CTX4(m) (0x340U + (m) * 0x80U)
-#define CAL_CSI2_CTX5(m) (0x344U + (m) * 0x80U)
-#define CAL_CSI2_CTX6(m) (0x348U + (m) * 0x80U)
-#define CAL_CSI2_CTX7(m) (0x34cU + (m) * 0x80U)
-#define CAL_CSI2_STATUS0(m) (0x350U + (m) * 0x80U)
-#define CAL_CSI2_STATUS1(m) (0x354U + (m) * 0x80U)
-#define CAL_CSI2_STATUS2(m) (0x358U + (m) * 0x80U)
-#define CAL_CSI2_STATUS3(m) (0x35cU + (m) * 0x80U)
-#define CAL_CSI2_STATUS4(m) (0x360U + (m) * 0x80U)
-#define CAL_CSI2_STATUS5(m) (0x364U + (m) * 0x80U)
-#define CAL_CSI2_STATUS6(m) (0x368U + (m) * 0x80U)
-#define CAL_CSI2_STATUS7(m) (0x36cU + (m) * 0x80U)
+#define CAL_CSI2_CTX(phy, csi2_ctx) (0x330U + (phy) * 0x80U + (csi2_ctx) * 4)
+#define CAL_CSI2_STATUS(phy, csi2_ctx) (0x350U + (phy) * 0x80U + (csi2_ctx) * 4)
/* CAL CSI2 PHY register offsets */
#define CAL_CSI2_PHY_REG0 0x000
@@ -139,7 +125,8 @@
#define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0 0
#define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0 0
-#define CAL_HL_IRQ_MASK(m) BIT(m)
+#define CAL_HL_IRQ_WDMA_END_MASK(m) BIT(m)
+#define CAL_HL_IRQ_WDMA_START_MASK(m) BIT(m)
#define CAL_HL_IRQ_OCPO_ERR_MASK BIT(6)
@@ -419,32 +406,16 @@
#define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK BIT(14)
#define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK BIT(15)
-#define CAL_CSI2_VC_IRQ_FS_IRQ_0_MASK BIT(0)
-#define CAL_CSI2_VC_IRQ_FE_IRQ_0_MASK BIT(1)
-#define CAL_CSI2_VC_IRQ_LS_IRQ_0_MASK BIT(2)
-#define CAL_CSI2_VC_IRQ_LE_IRQ_0_MASK BIT(3)
-#define CAL_CSI2_VC_IRQ_CS_IRQ_0_MASK BIT(4)
-#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_0_MASK BIT(5)
-#define CAL_CSI2_VC_IRQ_FS_IRQ_1_MASK BIT(8)
-#define CAL_CSI2_VC_IRQ_FE_IRQ_1_MASK BIT(9)
-#define CAL_CSI2_VC_IRQ_LS_IRQ_1_MASK BIT(10)
-#define CAL_CSI2_VC_IRQ_LE_IRQ_1_MASK BIT(11)
-#define CAL_CSI2_VC_IRQ_CS_IRQ_1_MASK BIT(12)
-#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_1_MASK BIT(13)
-#define CAL_CSI2_VC_IRQ_FS_IRQ_2_MASK BIT(16)
-#define CAL_CSI2_VC_IRQ_FE_IRQ_2_MASK BIT(17)
-#define CAL_CSI2_VC_IRQ_LS_IRQ_2_MASK BIT(18)
-#define CAL_CSI2_VC_IRQ_LE_IRQ_2_MASK BIT(19)
-#define CAL_CSI2_VC_IRQ_CS_IRQ_2_MASK BIT(20)
-#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_2_MASK BIT(21)
-#define CAL_CSI2_VC_IRQ_FS_IRQ_3_MASK BIT(24)
-#define CAL_CSI2_VC_IRQ_FE_IRQ_3_MASK BIT(25)
-#define CAL_CSI2_VC_IRQ_LS_IRQ_3_MASK BIT(26)
-#define CAL_CSI2_VC_IRQ_LE_IRQ_3_MASK BIT(27)
-#define CAL_CSI2_VC_IRQ_CS_IRQ_3_MASK BIT(28)
-#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_3_MASK BIT(29)
+#define CAL_CSI2_VC_IRQ_FS_IRQ_MASK(n) BIT(0 + ((n) * 8))
+#define CAL_CSI2_VC_IRQ_FE_IRQ_MASK(n) BIT(1 + ((n) * 8))
+#define CAL_CSI2_VC_IRQ_LS_IRQ_MASK(n) BIT(2 + ((n) * 8))
+#define CAL_CSI2_VC_IRQ_LE_IRQ_MASK(n) BIT(3 + ((n) * 8))
+#define CAL_CSI2_VC_IRQ_CS_IRQ_MASK(n) BIT(4 + ((n) * 8))
+#define CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(n) BIT(5 + ((n) * 8))
#define CAL_CSI2_CTX_DT_MASK GENMASK(5, 0)
+#define CAL_CSI2_CTX_DT_DISABLED 0
+#define CAL_CSI2_CTX_DT_ANY 1
#define CAL_CSI2_CTX_VC_MASK GENMASK(7, 6)
#define CAL_CSI2_CTX_CPORT_MASK GENMASK(12, 8)
#define CAL_CSI2_CTX_ATT_MASK BIT(13)
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 6f51e5c75543..823c15facd1b 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -676,9 +676,9 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
* rectangles.
*/
entity->config = v4l2_subdev_alloc_state(&entity->subdev);
- if (entity->config == NULL) {
+ if (IS_ERR(entity->config)) {
media_entity_cleanup(&entity->subdev.entity);
- return -ENOMEM;
+ return PTR_ERR(entity->config);
}
return 0;
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index d0a8326b75c2..fd5a7a058714 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -246,6 +246,16 @@ config IR_MESON
To compile this driver as a module, choose M here: the
module will be called meson-ir.
+config IR_MESON_TX
+ tristate "Amlogic Meson IR TX"
+ depends on ARCH_MESON || COMPILE_TEST
+ help
+ Say Y if you want to use the IR transmitter available on
+ Amlogic Meson SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called meson-ir-tx.
+
config IR_MTK
tristate "Mediatek IR remote receiver"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 692e9b6b203f..0db51fad27d6 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
obj-$(CONFIG_IR_FINTEK) += fintek-cir.o
obj-$(CONFIG_IR_MESON) += meson-ir.o
+obj-$(CONFIG_IR_MESON_TX) += meson-ir-tx.o
obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
obj-$(CONFIG_IR_ENE) += ene_ir.o
obj-$(CONFIG_IR_REDRAT3) += redrat3.o
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index 6049e5c95394..e09270916fbc 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1052,7 +1052,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
rdev->device_name = "ENE eHome Infrared Remote Receiver";
if (dev->hw_learning_and_tx_capable) {
- rdev->s_learning_mode = ene_set_learning_mode;
+ rdev->s_wideband_receiver = ene_set_learning_mode;
init_completion(&dev->tx_complete);
rdev->tx_ir = ene_transmit;
rdev->s_tx_mask = ene_set_tx_mask;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 116daf90c858..7f591ff5269d 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -412,7 +412,7 @@ static long lirc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
val |= LIRC_CAN_SET_REC_CARRIER |
LIRC_CAN_SET_REC_CARRIER_RANGE;
- if (dev->s_learning_mode)
+ if (dev->s_wideband_receiver)
val |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
if (dev->s_carrier_report)
@@ -519,10 +519,10 @@ static long lirc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
case LIRC_SET_WIDEBAND_RECEIVER:
- if (!dev->s_learning_mode)
+ if (!dev->s_wideband_receiver)
ret = -ENOTTY;
else
- ret = dev->s_learning_mode(dev, !!val);
+ ret = dev->s_wideband_receiver(dev, !!val);
break;
case LIRC_SET_MEASURE_CARRIER_MODE:
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 5642595a057e..e03dd1f0144f 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1630,7 +1630,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
rc->tx_ir = mceusb_tx_ir;
}
if (ir->flags.rx2 > 0) {
- rc->s_learning_mode = mceusb_set_rx_wideband;
+ rc->s_wideband_receiver = mceusb_set_rx_wideband;
rc->s_carrier_report = mceusb_set_rx_carrier_report;
}
rc->driver_name = DRIVER_NAME;
diff --git a/drivers/media/rc/meson-ir-tx.c b/drivers/media/rc/meson-ir-tx.c
new file mode 100644
index 000000000000..3055f8e1b6ff
--- /dev/null
+++ b/drivers/media/rc/meson-ir-tx.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+ * meson-ir-tx.c - Amlogic Meson IR TX driver
+ *
+ * Copyright (c) 2021, SberDevices. All Rights Reserved.
+ *
+ * Author: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <media/rc-core.h>
+
+#define DEVICE_NAME "Meson IR TX"
+#define DRIVER_NAME "meson-ir-tx"
+
+#define MIRTX_DEFAULT_CARRIER 38000
+#define MIRTX_DEFAULT_DUTY_CYCLE 50
+#define MIRTX_FIFO_THD 32
+
+#define IRB_MOD_1US_CLK_RATE 1000000
+
+#define IRB_FIFO_LEN 128
+
+#define IRB_ADDR0 0x0
+#define IRB_ADDR1 0x4
+#define IRB_ADDR2 0x8
+#define IRB_ADDR3 0xc
+
+#define IRB_MAX_DELAY (1 << 10)
+#define IRB_DELAY_MASK (IRB_MAX_DELAY - 1)
+
+/* IRCTRL_IR_BLASTER_ADDR0 */
+#define IRB_MOD_CLK(x) ((x) << 12)
+#define IRB_MOD_SYS_CLK 0
+#define IRB_MOD_XTAL3_CLK 1
+#define IRB_MOD_1US_CLK 2
+#define IRB_MOD_10US_CLK 3
+#define IRB_INIT_HIGH BIT(2)
+#define IRB_ENABLE BIT(0)
+
+/* IRCTRL_IR_BLASTER_ADDR2 */
+#define IRB_MOD_COUNT(lo, hi) ((((lo) - 1) << 16) | ((hi) - 1))
+
+/* IRCTRL_IR_BLASTER_ADDR2 */
+#define IRB_WRITE_FIFO BIT(16)
+#define IRB_MOD_ENABLE BIT(12)
+#define IRB_TB_1US (0x0 << 10)
+#define IRB_TB_10US (0x1 << 10)
+#define IRB_TB_100US (0x2 << 10)
+#define IRB_TB_MOD_CLK (0x3 << 10)
+
+/* IRCTRL_IR_BLASTER_ADDR3 */
+#define IRB_FIFO_THD_PENDING BIT(16)
+#define IRB_FIFO_IRQ_ENABLE BIT(8)
+
+struct meson_irtx {
+ struct device *dev;
+ void __iomem *reg_base;
+ u32 *buf;
+ unsigned int buf_len;
+ unsigned int buf_head;
+ unsigned int carrier;
+ unsigned int duty_cycle;
+ /* Locks buf */
+ spinlock_t lock;
+ struct completion completion;
+ unsigned long clk_rate;
+};
+
+static void meson_irtx_set_mod(struct meson_irtx *ir)
+{
+ unsigned int cnt = DIV_ROUND_CLOSEST(ir->clk_rate, ir->carrier);
+ unsigned int pulse_cnt = DIV_ROUND_CLOSEST(cnt * ir->duty_cycle, 100);
+ unsigned int space_cnt = cnt - pulse_cnt;
+
+ dev_dbg(ir->dev, "F_mod = %uHz, T_mod = %luns, duty_cycle = %u%%\n",
+ ir->carrier, NSEC_PER_SEC / ir->clk_rate * cnt,
+ 100 * pulse_cnt / cnt);
+
+ writel(IRB_MOD_COUNT(pulse_cnt, space_cnt),
+ ir->reg_base + IRB_ADDR1);
+}
+
+static void meson_irtx_setup(struct meson_irtx *ir, unsigned int clk_nr)
+{
+ /*
+ * Disable the TX, set modulator clock tick and set initialize
+ * output to be high. Set up carrier frequency and duty cycle. Then
+ * unset initialize output. Enable FIFO interrupt, set FIFO interrupt
+ * threshold. Finally, enable the transmitter back.
+ */
+ writel(~IRB_ENABLE & (IRB_MOD_CLK(clk_nr) | IRB_INIT_HIGH),
+ ir->reg_base + IRB_ADDR0);
+ meson_irtx_set_mod(ir);
+ writel(readl(ir->reg_base + IRB_ADDR0) & ~IRB_INIT_HIGH,
+ ir->reg_base + IRB_ADDR0);
+ writel(IRB_FIFO_IRQ_ENABLE | MIRTX_FIFO_THD,
+ ir->reg_base + IRB_ADDR3);
+ writel(readl(ir->reg_base + IRB_ADDR0) | IRB_ENABLE,
+ ir->reg_base + IRB_ADDR0);
+}
+
+static u32 meson_irtx_prepare_pulse(struct meson_irtx *ir, unsigned int time)
+{
+ unsigned int delay;
+ unsigned int tb = IRB_TB_MOD_CLK;
+ unsigned int tb_us = DIV_ROUND_CLOSEST(USEC_PER_SEC, ir->carrier);
+
+ delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
+
+ return ((IRB_WRITE_FIFO | IRB_MOD_ENABLE) | tb | delay);
+}
+
+static u32 meson_irtx_prepare_space(struct meson_irtx *ir, unsigned int time)
+{
+ unsigned int delay;
+ unsigned int tb = IRB_TB_100US;
+ unsigned int tb_us = 100;
+
+ if (time <= IRB_MAX_DELAY) {
+ tb = IRB_TB_1US;
+ tb_us = 1;
+ } else if (time <= 10 * IRB_MAX_DELAY) {
+ tb = IRB_TB_10US;
+ tb_us = 10;
+ } else if (time <= 100 * IRB_MAX_DELAY) {
+ tb = IRB_TB_100US;
+ tb_us = 100;
+ }
+
+ delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
+
+ return ((IRB_WRITE_FIFO & ~IRB_MOD_ENABLE) | tb | delay);
+}
+
+static void meson_irtx_send_buffer(struct meson_irtx *ir)
+{
+ unsigned int nr = 0;
+ unsigned int max_fifo_level = IRB_FIFO_LEN - MIRTX_FIFO_THD;
+
+ while (ir->buf_head < ir->buf_len && nr < max_fifo_level) {
+ writel(ir->buf[ir->buf_head], ir->reg_base + IRB_ADDR2);
+
+ ir->buf_head++;
+ nr++;
+ }
+}
+
+static bool meson_irtx_check_buf(struct meson_irtx *ir,
+ unsigned int *buf, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++) {
+ unsigned int max_tb_us;
+ /*
+ * Max space timebase is 100 us.
+ * Pulse timebase equals to carrier period.
+ */
+ if (i % 2 == 0)
+ max_tb_us = USEC_PER_SEC / ir->carrier;
+ else
+ max_tb_us = 100;
+
+ if (buf[i] >= max_tb_us * IRB_MAX_DELAY)
+ return false;
+ }
+
+ return true;
+}
+
+static void meson_irtx_fill_buf(struct meson_irtx *ir, u32 *dst_buf,
+ unsigned int *src_buf, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++) {
+ if (i % 2 == 0)
+ dst_buf[i] = meson_irtx_prepare_pulse(ir, src_buf[i]);
+ else
+ dst_buf[i] = meson_irtx_prepare_space(ir, src_buf[i]);
+ }
+}
+
+static irqreturn_t meson_irtx_irqhandler(int irq, void *data)
+{
+ unsigned long flags;
+ struct meson_irtx *ir = data;
+
+ writel(readl(ir->reg_base + IRB_ADDR3) & ~IRB_FIFO_THD_PENDING,
+ ir->reg_base + IRB_ADDR3);
+
+ if (completion_done(&ir->completion))
+ return IRQ_HANDLED;
+
+ spin_lock_irqsave(&ir->lock, flags);
+ if (ir->buf_head < ir->buf_len)
+ meson_irtx_send_buffer(ir);
+ else
+ complete(&ir->completion);
+ spin_unlock_irqrestore(&ir->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int meson_irtx_set_carrier(struct rc_dev *rc, u32 carrier)
+{
+ struct meson_irtx *ir = rc->priv;
+
+ if (carrier == 0)
+ return -EINVAL;
+
+ ir->carrier = carrier;
+ meson_irtx_set_mod(ir);
+
+ return 0;
+}
+
+static int meson_irtx_set_duty_cycle(struct rc_dev *rc, u32 duty_cycle)
+{
+ struct meson_irtx *ir = rc->priv;
+
+ ir->duty_cycle = duty_cycle;
+ meson_irtx_set_mod(ir);
+
+ return 0;
+}
+
+static void meson_irtx_update_buf(struct meson_irtx *ir, u32 *buf,
+ unsigned int len, unsigned int head)
+{
+ ir->buf = buf;
+ ir->buf_len = len;
+ ir->buf_head = head;
+}
+
+static int meson_irtx_transmit(struct rc_dev *rc, unsigned int *buf,
+ unsigned int len)
+{
+ unsigned long flags;
+ struct meson_irtx *ir = rc->priv;
+ u32 *tx_buf;
+ int ret = len;
+
+ if (!meson_irtx_check_buf(ir, buf, len))
+ return -EINVAL;
+
+ tx_buf = kmalloc_array(len, sizeof(u32), GFP_KERNEL);
+ if (!tx_buf)
+ return -ENOMEM;
+
+ meson_irtx_fill_buf(ir, tx_buf, buf, len);
+ dev_dbg(ir->dev, "TX buffer filled, length = %u\n", len);
+
+ spin_lock_irqsave(&ir->lock, flags);
+ meson_irtx_update_buf(ir, tx_buf, len, 0);
+ reinit_completion(&ir->completion);
+ meson_irtx_send_buffer(ir);
+ spin_unlock_irqrestore(&ir->lock, flags);
+
+ if (!wait_for_completion_timeout(&ir->completion,
+ usecs_to_jiffies(IR_MAX_DURATION)))
+ ret = -ETIMEDOUT;
+
+ spin_lock_irqsave(&ir->lock, flags);
+ kfree(ir->buf);
+ meson_irtx_update_buf(ir, NULL, 0, 0);
+ spin_unlock_irqrestore(&ir->lock, flags);
+
+ return ret;
+}
+
+static int meson_irtx_mod_clock_probe(struct meson_irtx *ir,
+ unsigned int *clk_nr)
+{
+ struct device_node *np = ir->dev->of_node;
+ struct clk *clock;
+
+ if (!np)
+ return -ENODEV;
+
+ clock = devm_clk_get(ir->dev, "xtal");
+ if (IS_ERR(clock) || clk_prepare_enable(clock))
+ return -ENODEV;
+
+ *clk_nr = IRB_MOD_XTAL3_CLK;
+ ir->clk_rate = clk_get_rate(clock) / 3;
+
+ if (ir->clk_rate < IRB_MOD_1US_CLK_RATE) {
+ *clk_nr = IRB_MOD_1US_CLK;
+ ir->clk_rate = IRB_MOD_1US_CLK_RATE;
+ }
+
+ dev_info(ir->dev, "F_clk = %luHz\n", ir->clk_rate);
+
+ return 0;
+}
+
+static int __init meson_irtx_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct meson_irtx *ir;
+ struct rc_dev *rc;
+ int irq;
+ unsigned int clk_nr;
+ int ret;
+
+ ir = devm_kzalloc(dev, sizeof(*ir), GFP_KERNEL);
+ if (!ir)
+ return -ENOMEM;
+
+ ir->reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(ir->reg_base))
+ return PTR_ERR(ir->reg_base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq resource found\n");
+ return -ENODEV;
+ }
+
+ ir->dev = dev;
+ ir->carrier = MIRTX_DEFAULT_CARRIER;
+ ir->duty_cycle = MIRTX_DEFAULT_DUTY_CYCLE;
+ init_completion(&ir->completion);
+ spin_lock_init(&ir->lock);
+
+ ret = meson_irtx_mod_clock_probe(ir, &clk_nr);
+ if (ret) {
+ dev_err(dev, "modulator clock setup failed\n");
+ return ret;
+ }
+ meson_irtx_setup(ir, clk_nr);
+
+ ret = devm_request_irq(dev, irq,
+ meson_irtx_irqhandler,
+ IRQF_TRIGGER_RISING,
+ DRIVER_NAME, ir);
+ if (ret) {
+ dev_err(dev, "irq request failed\n");
+ return ret;
+ }
+
+ rc = rc_allocate_device(RC_DRIVER_IR_RAW_TX);
+ if (!rc)
+ return -ENOMEM;
+
+ rc->driver_name = DRIVER_NAME;
+ rc->device_name = DEVICE_NAME;
+ rc->priv = ir;
+
+ rc->tx_ir = meson_irtx_transmit;
+ rc->s_tx_carrier = meson_irtx_set_carrier;
+ rc->s_tx_duty_cycle = meson_irtx_set_duty_cycle;
+
+ ret = rc_register_device(rc);
+ if (ret < 0) {
+ dev_err(dev, "rc_dev registration failed\n");
+ rc_free_device(rc);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, rc);
+
+ return 0;
+}
+
+static int meson_irtx_remove(struct platform_device *pdev)
+{
+ struct rc_dev *rc = platform_get_drvdata(pdev);
+
+ rc_unregister_device(rc);
+
+ return 0;
+}
+
+static const struct of_device_id meson_irtx_dt_match[] = {
+ {
+ .compatible = "amlogic,meson-g12a-ir-tx",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, meson_irtx_dt_match);
+
+static struct platform_driver meson_irtx_pd = {
+ .remove = meson_irtx_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = meson_irtx_dt_match,
+ },
+};
+
+module_platform_driver_probe(meson_irtx_pd, meson_irtx_probe);
+
+MODULE_DESCRIPTION("Meson IR TX driver");
+MODULE_AUTHOR("Viktor Prutyanov <viktor.prutyanov@phystech.edu>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index 1ba3f96ffa7d..6441879fcba1 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -15,12 +15,9 @@
#include <linux/slab.h>
#include <media/rc-core.h>
-#define DRIVER_NAME "rc-loopback"
-#define dprintk(x...) if (debug) printk(KERN_INFO DRIVER_NAME ": " x)
-#define RXMASK_REGULAR 0x1
-#define RXMASK_LEARNING 0x2
-
-static bool debug;
+#define DRIVER_NAME "rc-loopback"
+#define RXMASK_NARROWBAND 0x1
+#define RXMASK_WIDEBAND 0x2
struct loopback_dev {
struct rc_dev *dev;
@@ -28,7 +25,7 @@ struct loopback_dev {
u32 txcarrier;
u32 txduty;
bool idle;
- bool learning;
+ bool wideband;
bool carrierreport;
u32 rxcarriermin;
u32 rxcarriermax;
@@ -40,12 +37,12 @@ static int loop_set_tx_mask(struct rc_dev *dev, u32 mask)
{
struct loopback_dev *lodev = dev->priv;
- if ((mask & (RXMASK_REGULAR | RXMASK_LEARNING)) != mask) {
- dprintk("invalid tx mask: %u\n", mask);
- return -EINVAL;
+ if ((mask & (RXMASK_NARROWBAND | RXMASK_WIDEBAND)) != mask) {
+ dev_dbg(&dev->dev, "invalid tx mask: %u\n", mask);
+ return 2;
}
- dprintk("setting tx mask: %u\n", mask);
+ dev_dbg(&dev->dev, "setting tx mask: %u\n", mask);
lodev->txmask = mask;
return 0;
}
@@ -54,7 +51,7 @@ static int loop_set_tx_carrier(struct rc_dev *dev, u32 carrier)
{
struct loopback_dev *lodev = dev->priv;
- dprintk("setting tx carrier: %u\n", carrier);
+ dev_dbg(&dev->dev, "setting tx carrier: %u\n", carrier);
lodev->txcarrier = carrier;
return 0;
}
@@ -64,11 +61,11 @@ static int loop_set_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
struct loopback_dev *lodev = dev->priv;
if (duty_cycle < 1 || duty_cycle > 99) {
- dprintk("invalid duty cycle: %u\n", duty_cycle);
+ dev_dbg(&dev->dev, "invalid duty cycle: %u\n", duty_cycle);
return -EINVAL;
}
- dprintk("setting duty cycle: %u\n", duty_cycle);
+ dev_dbg(&dev->dev, "setting duty cycle: %u\n", duty_cycle);
lodev->txduty = duty_cycle;
return 0;
}
@@ -78,11 +75,11 @@ static int loop_set_rx_carrier_range(struct rc_dev *dev, u32 min, u32 max)
struct loopback_dev *lodev = dev->priv;
if (min < 1 || min > max) {
- dprintk("invalid rx carrier range %u to %u\n", min, max);
+ dev_dbg(&dev->dev, "invalid rx carrier range %u to %u\n", min, max);
return -EINVAL;
}
- dprintk("setting rx carrier range %u to %u\n", min, max);
+ dev_dbg(&dev->dev, "setting rx carrier range %u to %u\n", min, max);
lodev->rxcarriermin = min;
lodev->rxcarriermax = max;
return 0;
@@ -97,25 +94,33 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
if (lodev->txcarrier < lodev->rxcarriermin ||
lodev->txcarrier > lodev->rxcarriermax) {
- dprintk("ignoring tx, carrier out of range\n");
+ dev_dbg(&dev->dev, "ignoring tx, carrier out of range\n");
goto out;
}
- if (lodev->learning)
- rxmask = RXMASK_LEARNING;
+ if (lodev->wideband)
+ rxmask = RXMASK_WIDEBAND;
else
- rxmask = RXMASK_REGULAR;
+ rxmask = RXMASK_NARROWBAND;
if (!(rxmask & lodev->txmask)) {
- dprintk("ignoring tx, rx mask mismatch\n");
+ dev_dbg(&dev->dev, "ignoring tx, rx mask mismatch\n");
goto out;
}
for (i = 0; i < count; i++) {
rawir.pulse = i % 2 ? false : true;
rawir.duration = txbuf[i];
- if (rawir.duration)
- ir_raw_event_store_with_filter(dev, &rawir);
+
+ ir_raw_event_store_with_filter(dev, &rawir);
+ }
+
+ if (lodev->carrierreport) {
+ rawir.pulse = false;
+ rawir.carrier_report = true;
+ rawir.carrier = lodev->txcarrier;
+
+ ir_raw_event_store(dev, &rawir);
}
/* Fake a silence long enough to cause us to go idle */
@@ -134,18 +139,18 @@ static void loop_set_idle(struct rc_dev *dev, bool enable)
struct loopback_dev *lodev = dev->priv;
if (lodev->idle != enable) {
- dprintk("%sing idle mode\n", enable ? "enter" : "exit");
+ dev_dbg(&dev->dev, "%sing idle mode\n", enable ? "enter" : "exit");
lodev->idle = enable;
}
}
-static int loop_set_learning_mode(struct rc_dev *dev, int enable)
+static int loop_set_wideband_receiver(struct rc_dev *dev, int enable)
{
struct loopback_dev *lodev = dev->priv;
- if (lodev->learning != enable) {
- dprintk("%sing learning mode\n", enable ? "enter" : "exit");
- lodev->learning = !!enable;
+ if (lodev->wideband != enable) {
+ dev_dbg(&dev->dev, "using %sband receiver\n", enable ? "wide" : "narrow");
+ lodev->wideband = !!enable;
}
return 0;
@@ -156,7 +161,7 @@ static int loop_set_carrier_report(struct rc_dev *dev, int enable)
struct loopback_dev *lodev = dev->priv;
if (lodev->carrierreport != enable) {
- dprintk("%sabling carrier reports\n", enable ? "en" : "dis");
+ dev_dbg(&dev->dev, "%sabling carrier reports\n", enable ? "en" : "dis");
lodev->carrierreport = !!enable;
}
@@ -204,10 +209,8 @@ static int __init loop_init(void)
int ret;
rc = rc_allocate_device(RC_DRIVER_IR_RAW);
- if (!rc) {
- printk(KERN_ERR DRIVER_NAME ": rc_dev allocation failed\n");
+ if (!rc)
return -ENOMEM;
- }
rc->device_name = "rc-core loopback device";
rc->input_phys = "rc-core/virtual";
@@ -219,9 +222,9 @@ static int __init loop_init(void)
rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
rc->allowed_wakeup_protocols = RC_PROTO_BIT_ALL_IR_ENCODER;
rc->encode_wakeup = true;
- rc->timeout = MS_TO_US(100); /* 100 ms */
+ rc->timeout = IR_DEFAULT_TIMEOUT;
rc->min_timeout = 1;
- rc->max_timeout = UINT_MAX;
+ rc->max_timeout = IR_MAX_TIMEOUT;
rc->rx_resolution = 1;
rc->tx_resolution = 1;
rc->s_tx_mask = loop_set_tx_mask;
@@ -230,22 +233,22 @@ static int __init loop_init(void)
rc->s_rx_carrier_range = loop_set_rx_carrier_range;
rc->tx_ir = loop_tx_ir;
rc->s_idle = loop_set_idle;
- rc->s_learning_mode = loop_set_learning_mode;
+ rc->s_wideband_receiver = loop_set_wideband_receiver;
rc->s_carrier_report = loop_set_carrier_report;
rc->s_wakeup_filter = loop_set_wakeup_filter;
- loopdev.txmask = RXMASK_REGULAR;
+ loopdev.txmask = RXMASK_NARROWBAND;
loopdev.txcarrier = 36000;
loopdev.txduty = 50;
loopdev.rxcarriermin = 1;
loopdev.rxcarriermax = ~0;
loopdev.idle = true;
- loopdev.learning = false;
+ loopdev.wideband = false;
loopdev.carrierreport = false;
ret = rc_register_device(rc);
if (ret < 0) {
- printk(KERN_ERR DRIVER_NAME ": rc_dev registration failed\n");
+ dev_err(&rc->dev, "rc_dev registration failed\n");
rc_free_device(rc);
return ret;
}
@@ -262,9 +265,6 @@ static void __exit loop_exit(void)
module_init(loop_init);
module_exit(loop_exit);
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debug messages");
-
MODULE_DESCRIPTION("Loopback device for rc-core debugging");
MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 8e88dc8ea6c5..b90438a71c80 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1940,7 +1940,7 @@ int rc_register_device(struct rc_dev *dev)
kfree(path);
/*
- * once the the input device is registered in rc_setup_rx_device,
+ * once the input device is registered in rc_setup_rx_device,
* userspace can open the input device and rc_open() will be called
* as a result. This results in driver code being allowed to submit
* keycodes with rc_keydown, so lirc must be registered first.
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 2cf3377ec63a..ac85464864b9 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -6,7 +6,7 @@
* based heavily on the work of Stephen Cox, with additional
* help from RedRat Ltd.
*
- * This driver began life based an an old version of the first-generation
+ * This driver began life based on an old version of the first-generation
* lirc_mceusb driver from the lirc 0.7.2 distribution. It was then
* significantly rewritten by Stephen Cox with the aid of RedRat Ltd's
* Chris Dodge.
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index 9f3cd9fb6b6e..9cd765e31c49 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -265,8 +265,6 @@ static void streamzap_callback(struct urb *urb)
ir_raw_event_handle(sz->rdev);
usb_submit_urb(urb, GFP_ATOMIC);
-
- return;
}
static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
diff --git a/drivers/media/spi/cxd2880-spi.c b/drivers/media/spi/cxd2880-spi.c
index e5094fff04c5..b91a1e845b97 100644
--- a/drivers/media/spi/cxd2880-spi.c
+++ b/drivers/media/spi/cxd2880-spi.c
@@ -524,13 +524,13 @@ cxd2880_spi_probe(struct spi_device *spi)
if (IS_ERR(dvb_spi->vcc_supply)) {
if (PTR_ERR(dvb_spi->vcc_supply) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
- goto fail_adapter;
+ goto fail_regulator;
}
dvb_spi->vcc_supply = NULL;
} else {
ret = regulator_enable(dvb_spi->vcc_supply);
if (ret)
- goto fail_adapter;
+ goto fail_regulator;
}
dvb_spi->spi = spi;
@@ -618,6 +618,9 @@ fail_frontend:
fail_attach:
dvb_unregister_adapter(&dvb_spi->adapter);
fail_adapter:
+ if (!dvb_spi->vcc_supply)
+ regulator_disable(dvb_spi->vcc_supply);
+fail_regulator:
kfree(dvb_spi);
return ret;
}
diff --git a/drivers/media/test-drivers/vivid/vivid-cec.c b/drivers/media/test-drivers/vivid/vivid-cec.c
index 4d2413e87730..55ea039fe5b2 100644
--- a/drivers/media/test-drivers/vivid/vivid-cec.c
+++ b/drivers/media/test-drivers/vivid/vivid-cec.c
@@ -282,5 +282,5 @@ struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
snprintf(name, sizeof(name), "vivid-%03d-vid-%s%d",
dev->inst, is_source ? "out" : "cap", idx);
return cec_allocate_adapter(&vivid_cec_adap_ops, dev,
- name, caps, 1);
+ name, caps, CEC_MAX_LOG_ADDRS);
}
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index 5c75303fba9d..60ca8b9d070b 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -34,6 +34,8 @@ config DVB_USB_AF9035
tristate "Afatech AF9035 DVB-T USB2.0 support"
depends on DVB_USB_V2
select DVB_AF9033
+ select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_TUA9001 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_FC0011 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index b1f69c11c839..5eef37b00a52 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -210,6 +210,7 @@ static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
/* register I2C device */
client = i2c_new_client_device(adapter, &board_info);
if (!i2c_client_has_driver(client)) {
+ dev_err(&intf->dev, "failed to bind i2c device to %s driver\n", type);
ret = -ENODEV;
goto err;
}
diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c
index 689829f1b52a..1221c924312a 100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -541,7 +541,9 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
si2168_config.i2c_adapter = &i2c_adapter;
si2168_config.fe = &adap->fe[0];
si2168_config.ts_mode = SI2168_TS_PARALLEL;
- if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2)
+ if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2 ||
+ le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2_LITE ||
+ le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230A)
si2168_config.ts_mode |= SI2168_TS_CLK_MANUAL;
si2168_config.ts_clock_inv = 1;
@@ -577,15 +579,24 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
{
- dvbsky_gpio_ctrl(d, 0x04, 1);
- msleep(20);
- dvbsky_gpio_ctrl(d, 0x83, 0);
- dvbsky_gpio_ctrl(d, 0xc0, 1);
- msleep(100);
- dvbsky_gpio_ctrl(d, 0x83, 1);
- dvbsky_gpio_ctrl(d, 0xc0, 0);
- msleep(50);
-
+ if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230A) {
+ dvbsky_gpio_ctrl(d, 0x87, 0);
+ msleep(20);
+ dvbsky_gpio_ctrl(d, 0x86, 1);
+ dvbsky_gpio_ctrl(d, 0x80, 0);
+ msleep(100);
+ dvbsky_gpio_ctrl(d, 0x80, 1);
+ msleep(50);
+ } else {
+ dvbsky_gpio_ctrl(d, 0x04, 1);
+ msleep(20);
+ dvbsky_gpio_ctrl(d, 0x83, 0);
+ dvbsky_gpio_ctrl(d, 0xc0, 1);
+ msleep(100);
+ dvbsky_gpio_ctrl(d, 0x83, 1);
+ dvbsky_gpio_ctrl(d, 0xc0, 0);
+ msleep(50);
+ }
return WARM;
}
@@ -789,6 +800,12 @@ static const struct usb_device_id dvbsky_id_table[] = {
{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2,
&mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2",
RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
+ { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2_LITE,
+ &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2 Lite",
+ NULL) },
+ { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230A,
+ &mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230A",
+ NULL) },
{ }
};
MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c
index 2e07106f4680..bc4b2abdde1a 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c
@@ -17,7 +17,8 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
if (d->props.i2c_algo == NULL) {
err("no i2c algorithm specified");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err;
}
strscpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
@@ -27,11 +28,15 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
i2c_set_adapdata(&d->i2c_adap, d);
- if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
+ ret = i2c_add_adapter(&d->i2c_adap);
+ if (ret < 0) {
err("could not add i2c adapter");
+ goto err;
+ }
d->state |= DVB_USB_STATE_I2C;
+err:
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 28e1fd64dd3c..61439c8f33ca 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c
@@ -194,8 +194,8 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
err_adapter_init:
dvb_usb_adapter_exit(d);
-err_i2c_init:
dvb_usb_i2c_exit(d);
+err_i2c_init:
if (d->priv && d->props.priv_destroy)
d->props.priv_destroy(d);
err_priv_init:
diff --git a/drivers/media/usb/dvb-usb/nova-t-usb2.c b/drivers/media/usb/dvb-usb/nova-t-usb2.c
index e7b290552b66..9c0eb0d40822 100644
--- a/drivers/media/usb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/usb/dvb-usb/nova-t-usb2.c
@@ -130,7 +130,7 @@ ret:
static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
{
- int i;
+ int i, ret;
u8 b;
mac[0] = 0x00;
@@ -139,7 +139,9 @@ static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
/* this is a complete guess, but works for my box */
for (i = 136; i < 139; i++) {
- dibusb_read_eeprom_byte(d,i, &b);
+ ret = dibusb_read_eeprom_byte(d, i, &b);
+ if (ret)
+ return ret;
mac[5 - (i - 136)] = b;
}
diff --git a/drivers/media/usb/dvb-usb/vp702x.c b/drivers/media/usb/dvb-usb/vp702x.c
index bf54747e2e01..a1d9e4801a2b 100644
--- a/drivers/media/usb/dvb-usb/vp702x.c
+++ b/drivers/media/usb/dvb-usb/vp702x.c
@@ -291,16 +291,22 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
{
u8 i, *buf;
+ int ret;
struct vp702x_device_state *st = d->priv;
mutex_lock(&st->buf_mutex);
buf = st->buf;
- for (i = 6; i < 12; i++)
- vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1);
+ for (i = 6; i < 12; i++) {
+ ret = vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1,
+ &buf[i - 6], 1);
+ if (ret < 0)
+ goto err;
+ }
memcpy(mac, buf, 6);
+err:
mutex_unlock(&st->buf_mutex);
- return 0;
+ return ret;
}
static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 59529cbf9cd0..0b6d77c3bec8 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -842,7 +842,6 @@ error:
kfree(ir);
ref_put:
em28xx_shutdown_buttons(dev);
- kref_put(&dev->ref, em28xx_free_device);
return err;
}
diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c
index f1767be9d868..6650eab913d8 100644
--- a/drivers/media/usb/go7007/go7007-driver.c
+++ b/drivers/media/usb/go7007/go7007-driver.c
@@ -691,49 +691,23 @@ struct go7007 *go7007_alloc(const struct go7007_board_info *board,
struct device *dev)
{
struct go7007 *go;
- int i;
go = kzalloc(sizeof(struct go7007), GFP_KERNEL);
if (go == NULL)
return NULL;
go->dev = dev;
go->board_info = board;
- go->board_id = 0;
go->tuner_type = -1;
- go->channel_number = 0;
- go->name[0] = 0;
mutex_init(&go->hw_lock);
init_waitqueue_head(&go->frame_waitq);
spin_lock_init(&go->spinlock);
go->status = STATUS_INIT;
- memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
- go->i2c_adapter_online = 0;
- go->interrupt_available = 0;
init_waitqueue_head(&go->interrupt_waitq);
- go->input = 0;
go7007_update_board(go);
- go->encoder_h_halve = 0;
- go->encoder_v_halve = 0;
- go->encoder_subsample = 0;
go->format = V4L2_PIX_FMT_MJPEG;
go->bitrate = 1500000;
go->fps_scale = 1;
- go->pali = 0;
go->aspect_ratio = GO7007_RATIO_1_1;
- go->gop_size = 0;
- go->ipb = 0;
- go->closed_gop = 0;
- go->repeat_seqhead = 0;
- go->seq_header_enable = 0;
- go->gop_header_enable = 0;
- go->dvd_mode = 0;
- go->interlace_coding = 0;
- for (i = 0; i < 4; ++i)
- go->modet[i].enable = 0;
- for (i = 0; i < 1624; ++i)
- go->modet_map[i] = 0;
- go->audio_deliver = NULL;
- go->audio_enabled = 0;
return go;
}
diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c
index dbf0455d5d50..eeb85981e02b 100644
--- a/drivers/media/usb/go7007/go7007-usb.c
+++ b/drivers/media/usb/go7007/go7007-usb.c
@@ -1134,7 +1134,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
ep = usb->usbdev->ep_in[4];
if (!ep)
- return -ENODEV;
+ goto allocfail;
/* Allocate the URB and buffer for receiving incoming interrupts */
usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig
index 0283e3b908e4..dca4e16ed133 100644
--- a/drivers/media/usb/gspca/Kconfig
+++ b/drivers/media/usb/gspca/Kconfig
@@ -4,7 +4,6 @@ menuconfig USB_GSPCA
depends on VIDEO_V4L2
depends on INPUT || INPUT=n
select VIDEOBUF2_VMALLOC
- default m
help
Say Y here if you want to enable selecting webcams based
on the GSPCA framework.
diff --git a/drivers/media/usb/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c
index 4cb7c92ea132..e7a534be061d 100644
--- a/drivers/media/usb/gspca/vc032x.c
+++ b/drivers/media/usb/gspca/vc032x.c
@@ -1796,7 +1796,7 @@ static const u8 ov7660_60HZ[][4] = {
{}
};
-static const u8 ov7660_NoFliker[][4] = {
+static const u8 ov7660_NoFlicker[][4] = {
{0x00, 0x13, 0x87, 0xaa},
{}
};
@@ -3319,8 +3319,8 @@ static void sethvflip(struct gspca_dev *gspca_dev, bool hflip, bool vflip)
static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
- static const u8 (*ov7660_freq_tb[3])[4] =
- {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
+ static const u8 (*ov7660_freq_tb[3])[4] = {
+ ov7660_NoFlicker, ov7660_50HZ, ov7660_60HZ};
if (sd->sensor != SENSOR_OV7660)
return;
diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c
index aa285d5d6c0d..5bcbf0d40147 100644
--- a/drivers/media/usb/gspca/zc3xx.c
+++ b/drivers/media/usb/gspca/zc3xx.c
@@ -323,7 +323,7 @@ static const struct usb_action adcm2700_60HZ[] = {
{0xaa, 0x28, 0x0002}, /* 00,28,02,aa */
{}
};
-static const struct usb_action adcm2700_NoFliker[] = {
+static const struct usb_action adcm2700_NoFlicker[] = {
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
{0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
@@ -525,7 +525,7 @@ static const struct usb_action cs2102_60HZ[] = {
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
{}
};
-static const struct usb_action cs2102_NoFlikerScale[] = {
+static const struct usb_action cs2102_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xaa, 0x23, 0x0001},
{0xaa, 0x24, 0x005f},
@@ -547,7 +547,7 @@ static const struct usb_action cs2102_NoFlikerScale[] = {
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
{}
};
-static const struct usb_action cs2102_NoFliker[] = {
+static const struct usb_action cs2102_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xaa, 0x23, 0x0000},
{0xaa, 0x24, 0x00af},
@@ -1385,7 +1385,7 @@ static const struct usb_action gc0305_60HZ[] = {
{}
};
-static const struct usb_action gc0305_NoFliker[] = {
+static const struct usb_action gc0305_NoFlicker[] = {
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
@@ -1710,7 +1710,7 @@ static const struct usb_action hdcs2020_60HZ[] = {
{0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
{}
};
-static const struct usb_action hdcs2020_NoFliker[] = {
+static const struct usb_action hdcs2020_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x13, 0x0010}, /* 00,13,10,aa */
{0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
@@ -1925,7 +1925,7 @@ static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */
{0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
{}
};
-static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
+static const struct usb_action hv7131b_NoFlicker[] = { /* 640x480*/
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
{0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
@@ -1950,7 +1950,7 @@ static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
{0xa0, 0x03, ZC3XX_R020_HSYNC_3}, /* 00,20,03,cc */
{}
};
-static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
+static const struct usb_action hv7131b_NoFlickerScale[] = { /* 320x240 */
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
{0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
@@ -2141,7 +2141,7 @@ static const struct usb_action hv7131r_60HZScale[] = {
{0xa0, 0x08, ZC3XX_R020_HSYNC_3},
{}
};
-static const struct usb_action hv7131r_NoFliker[] = {
+static const struct usb_action hv7131r_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
{0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
@@ -2159,7 +2159,7 @@ static const struct usb_action hv7131r_NoFliker[] = {
{0xa0, 0x08, ZC3XX_R020_HSYNC_3},
{}
};
-static const struct usb_action hv7131r_NoFlikerScale[] = {
+static const struct usb_action hv7131r_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
{0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
@@ -2662,7 +2662,7 @@ static const struct usb_action icm105a_60HZ[] = {
{0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
{}
};
-static const struct usb_action icm105a_NoFlikerScale[] = {
+static const struct usb_action icm105a_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
@@ -2693,7 +2693,7 @@ static const struct usb_action icm105a_NoFlikerScale[] = {
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
{}
};
-static const struct usb_action icm105a_NoFliker[] = {
+static const struct usb_action icm105a_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
@@ -3009,7 +3009,7 @@ static const struct usb_action mc501cb_60HZScale[] = {
{}
};
-static const struct usb_action mc501cb_NoFliker[] = {
+static const struct usb_action mc501cb_NoFlicker[] = {
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
{0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
@@ -3021,7 +3021,7 @@ static const struct usb_action mc501cb_NoFliker[] = {
{}
};
-static const struct usb_action mc501cb_NoFlikerScale[] = {
+static const struct usb_action mc501cb_NoFlickerScale[] = {
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
{0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
@@ -3211,7 +3211,7 @@ static const struct usb_action ov7620_60HZ[] = {
{0xa1, 0x01, 0x0037}, */
{}
};
-static const struct usb_action ov7620_NoFliker[] = {
+static const struct usb_action ov7620_NoFlicker[] = {
{0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
{0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
/* disable 1/120s & 1/100s exposures for banding filter */
@@ -3827,7 +3827,7 @@ static const struct usb_action pas106b_60HZ[] = {
{0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
{}
};
-static const struct usb_action pas106b_NoFliker[] = {
+static const struct usb_action pas106b_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
{0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
{0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
@@ -4051,7 +4051,7 @@ static const struct usb_action pas202b_60HZScale[] = {
{0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
{}
};
-static const struct usb_action pas202b_NoFliker[] = {
+static const struct usb_action pas202b_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
@@ -4080,7 +4080,7 @@ static const struct usb_action pas202b_NoFliker[] = {
{0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
{}
};
-static const struct usb_action pas202b_NoFlikerScale[] = {
+static const struct usb_action pas202b_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
@@ -4309,7 +4309,7 @@ static const struct usb_action mt9v111_1_AE60HZScale[] = {
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
{}
};
-static const struct usb_action mt9v111_1_AENoFliker[] = {
+static const struct usb_action mt9v111_1_AENoFlicker[] = {
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xbb, 0x00, 0x0509},
@@ -4332,7 +4332,7 @@ static const struct usb_action mt9v111_1_AENoFliker[] = {
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
{}
};
-static const struct usb_action mt9v111_1_AENoFlikerScale[] = {
+static const struct usb_action mt9v111_1_AENoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xbb, 0x00, 0x0534},
@@ -4554,7 +4554,7 @@ static const struct usb_action mt9v111_3_AE60HZScale[] = {
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
{}
};
-static const struct usb_action mt9v111_3_AENoFliker[] = {
+static const struct usb_action mt9v111_3_AENoFlicker[] = {
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xaa, 0x05, 0x0034},
@@ -4577,7 +4577,7 @@ static const struct usb_action mt9v111_3_AENoFliker[] = {
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
{}
};
-static const struct usb_action mt9v111_3_AENoFlikerScale[] = {
+static const struct usb_action mt9v111_3_AENoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xaa, 0x05, 0x0034},
@@ -4787,7 +4787,7 @@ static const struct usb_action pb0330_60HZScale[] = {
{0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
{}
};
-static const struct usb_action pb0330_NoFliker[] = {
+static const struct usb_action pb0330_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xbb, 0x00, 0x0509},
{0xbb, 0x02, 0x0940},
@@ -4809,7 +4809,7 @@ static const struct usb_action pb0330_NoFliker[] = {
{0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
{}
};
-static const struct usb_action pb0330_NoFlikerScale[] = {
+static const struct usb_action pb0330_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xbb, 0x00, 0x0535},
{0xbb, 0x01, 0x0980},
@@ -5031,7 +5031,7 @@ static const struct usb_action po2030_60HZ[] = {
{}
};
-static const struct usb_action po2030_NoFliker[] = {
+static const struct usb_action po2030_NoFlicker[] = {
{0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
{0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
{0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
@@ -5215,7 +5215,7 @@ static const struct usb_action tas5130c_60HZScale[] = {
{0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
{}
};
-static const struct usb_action tas5130c_NoFliker[] = {
+static const struct usb_action tas5130c_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
{0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
@@ -5241,7 +5241,7 @@ static const struct usb_action tas5130c_NoFliker[] = {
{}
};
-static const struct usb_action tas5130c_NoFlikerScale[] = {
+static const struct usb_action tas5130c_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
{0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
@@ -5482,7 +5482,7 @@ static const struct usb_action gc0303_60HZScale[] = {
{}
};
-static const struct usb_action gc0303_NoFliker[] = {
+static const struct usb_action gc0303_NoFlicker[] = {
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
@@ -5504,7 +5504,7 @@ static const struct usb_action gc0303_NoFliker[] = {
{}
};
-static const struct usb_action gc0303_NoFlikerScale[] = {
+static const struct usb_action gc0303_NoFlickerScale[] = {
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
@@ -5806,7 +5806,7 @@ static void setquality(struct gspca_dev *gspca_dev)
* Valid frequencies are:
* 50Hz, for European and Asian lighting (default)
* 60Hz, for American lighting
- * 0 = No Fliker (for outdoore usage)
+ * 0 = No Flicker (for outdoor usage)
*/
static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
{
@@ -5814,80 +5814,80 @@ static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
int i, mode;
const struct usb_action *zc3_freq;
static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
- [SENSOR_ADCM2700] =
- {adcm2700_NoFliker, adcm2700_NoFliker,
+ [SENSOR_ADCM2700] = {
+ adcm2700_NoFlicker, adcm2700_NoFlicker,
adcm2700_50HZ, adcm2700_50HZ,
adcm2700_60HZ, adcm2700_60HZ},
- [SENSOR_CS2102] =
- {cs2102_NoFliker, cs2102_NoFlikerScale,
+ [SENSOR_CS2102] = {
+ cs2102_NoFlicker, cs2102_NoFlickerScale,
cs2102_50HZ, cs2102_50HZScale,
cs2102_60HZ, cs2102_60HZScale},
- [SENSOR_CS2102K] =
- {cs2102_NoFliker, cs2102_NoFlikerScale,
+ [SENSOR_CS2102K] = {
+ cs2102_NoFlicker, cs2102_NoFlickerScale,
NULL, NULL, /* currently disabled */
NULL, NULL},
- [SENSOR_GC0303] =
- {gc0303_NoFliker, gc0303_NoFlikerScale,
+ [SENSOR_GC0303] = {
+ gc0303_NoFlicker, gc0303_NoFlickerScale,
gc0303_50HZ, gc0303_50HZScale,
gc0303_60HZ, gc0303_60HZScale},
- [SENSOR_GC0305] =
- {gc0305_NoFliker, gc0305_NoFliker,
+ [SENSOR_GC0305] = {
+ gc0305_NoFlicker, gc0305_NoFlicker,
gc0305_50HZ, gc0305_50HZ,
gc0305_60HZ, gc0305_60HZ},
- [SENSOR_HDCS2020] =
- {hdcs2020_NoFliker, hdcs2020_NoFliker,
+ [SENSOR_HDCS2020] = {
+ hdcs2020_NoFlicker, hdcs2020_NoFlicker,
hdcs2020_50HZ, hdcs2020_50HZ,
hdcs2020_60HZ, hdcs2020_60HZ},
- [SENSOR_HV7131B] =
- {hv7131b_NoFliker, hv7131b_NoFlikerScale,
+ [SENSOR_HV7131B] = {
+ hv7131b_NoFlicker, hv7131b_NoFlickerScale,
hv7131b_50HZ, hv7131b_50HZScale,
hv7131b_60HZ, hv7131b_60HZScale},
- [SENSOR_HV7131R] =
- {hv7131r_NoFliker, hv7131r_NoFlikerScale,
+ [SENSOR_HV7131R] = {
+ hv7131r_NoFlicker, hv7131r_NoFlickerScale,
hv7131r_50HZ, hv7131r_50HZScale,
hv7131r_60HZ, hv7131r_60HZScale},
- [SENSOR_ICM105A] =
- {icm105a_NoFliker, icm105a_NoFlikerScale,
+ [SENSOR_ICM105A] = {
+ icm105a_NoFlicker, icm105a_NoFlickerScale,
icm105a_50HZ, icm105a_50HZScale,
icm105a_60HZ, icm105a_60HZScale},
- [SENSOR_MC501CB] =
- {mc501cb_NoFliker, mc501cb_NoFlikerScale,
+ [SENSOR_MC501CB] = {
+ mc501cb_NoFlicker, mc501cb_NoFlickerScale,
mc501cb_50HZ, mc501cb_50HZScale,
mc501cb_60HZ, mc501cb_60HZScale},
- [SENSOR_MT9V111_1] =
- {mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale,
+ [SENSOR_MT9V111_1] = {
+ mt9v111_1_AENoFlicker, mt9v111_1_AENoFlickerScale,
mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale,
mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale},
- [SENSOR_MT9V111_3] =
- {mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale,
+ [SENSOR_MT9V111_3] = {
+ mt9v111_3_AENoFlicker, mt9v111_3_AENoFlickerScale,
mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale,
mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale},
- [SENSOR_OV7620] =
- {ov7620_NoFliker, ov7620_NoFliker,
+ [SENSOR_OV7620] = {
+ ov7620_NoFlicker, ov7620_NoFlicker,
ov7620_50HZ, ov7620_50HZ,
ov7620_60HZ, ov7620_60HZ},
- [SENSOR_OV7630C] =
- {NULL, NULL,
+ [SENSOR_OV7630C] = {
+ NULL, NULL,
NULL, NULL,
NULL, NULL},
- [SENSOR_PAS106] =
- {pas106b_NoFliker, pas106b_NoFliker,
+ [SENSOR_PAS106] = {
+ pas106b_NoFlicker, pas106b_NoFlicker,
pas106b_50HZ, pas106b_50HZ,
pas106b_60HZ, pas106b_60HZ},
- [SENSOR_PAS202B] =
- {pas202b_NoFliker, pas202b_NoFlikerScale,
+ [SENSOR_PAS202B] = {
+ pas202b_NoFlicker, pas202b_NoFlickerScale,
pas202b_50HZ, pas202b_50HZScale,
pas202b_60HZ, pas202b_60HZScale},
- [SENSOR_PB0330] =
- {pb0330_NoFliker, pb0330_NoFlikerScale,
+ [SENSOR_PB0330] = {
+ pb0330_NoFlicker, pb0330_NoFlickerScale,
pb0330_50HZ, pb0330_50HZScale,
pb0330_60HZ, pb0330_60HZScale},
- [SENSOR_PO2030] =
- {po2030_NoFliker, po2030_NoFliker,
+ [SENSOR_PO2030] = {
+ po2030_NoFlicker, po2030_NoFlicker,
po2030_50HZ, po2030_50HZ,
po2030_60HZ, po2030_60HZ},
- [SENSOR_TAS5130C] =
- {tas5130c_NoFliker, tas5130c_NoFlikerScale,
+ [SENSOR_TAS5130C] = {
+ tas5130c_NoFlicker, tas5130c_NoFlickerScale,
tas5130c_50HZ, tas5130c_50HZScale,
tas5130c_60HZ, tas5130c_60HZScale},
};
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index a45d464427c4..0e231e576dc3 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -1346,7 +1346,7 @@ static int stk_camera_probe(struct usb_interface *interface,
if (!dev->isoc_ep) {
pr_err("Could not find isoc-in endpoint\n");
err = -ENODEV;
- goto error;
+ goto error_put;
}
dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
dev->vsettings.mode = MODE_VGA;
@@ -1359,10 +1359,12 @@ static int stk_camera_probe(struct usb_interface *interface,
err = stk_register_video_device(dev);
if (err)
- goto error;
+ goto error_put;
return 0;
+error_put:
+ usb_put_intf(interface);
error:
v4l2_ctrl_handler_free(hdl);
v4l2_device_unregister(&dev->v4l2_dev);
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 252136cc885c..6acb8013de08 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -899,8 +899,8 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
{
struct uvc_fh *handle = fh;
struct uvc_video_chain *chain = handle->chain;
+ u8 *buf;
int ret;
- u8 i;
if (chain->selector == NULL ||
(chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
@@ -908,22 +908,27 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
return 0;
}
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
- &i, 1);
- if (ret < 0)
- return ret;
+ buf, 1);
+ if (!ret)
+ *input = *buf - 1;
- *input = i - 1;
- return 0;
+ kfree(buf);
+
+ return ret;
}
static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
{
struct uvc_fh *handle = fh;
struct uvc_video_chain *chain = handle->chain;
+ u8 *buf;
int ret;
- u32 i;
ret = uvc_acquire_privileges(handle);
if (ret < 0)
@@ -939,10 +944,17 @@ static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
if (input >= chain->selector->bNrInPins)
return -EINVAL;
- i = input + 1;
- return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
- chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
- &i, 1);
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ *buf = input + 1;
+ ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
+ chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
+ buf, 1);
+ kfree(buf);
+
+ return ret;
}
static int uvc_ioctl_queryctrl(struct file *file, void *fh,
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index b6344bbf1e00..421300e13a41 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -833,6 +833,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: return "Decoder Slice Interface";
case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: return "MPEG4 Loop Filter Enable";
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "Number of Intra Refresh MBs";
+ case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD: return "Intra Refresh Period";
case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: return "Frame Level Rate Control Enable";
case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control";
case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode";
@@ -1258,6 +1259,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:
case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:
case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:
+ case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD:
*type = V4L2_CTRL_TYPE_INTEGER;
break;
case V4L2_CID_MPEG_VIDEO_LTR_COUNT:
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c
index 230d65a64217..af48705c704f 100644
--- a/drivers/media/v4l2-core/v4l2-dv-timings.c
+++ b/drivers/media/v4l2-core/v4l2-dv-timings.c
@@ -196,7 +196,7 @@ bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t,
if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle))
return false;
- for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) {
+ for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
fnc, fnc_handle) &&
v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i,
@@ -218,7 +218,7 @@ bool v4l2_find_dv_timings_cea861_vic(struct v4l2_dv_timings *t, u8 vic)
{
unsigned int i;
- for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) {
+ for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
const struct v4l2_bt_timings *bt =
&v4l2_dv_timings_presets[i].bt;
diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
index 10ddcc48aa17..e70e128ccc9c 100644
--- a/drivers/media/v4l2-core/v4l2-flash-led-class.c
+++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
@@ -76,10 +76,11 @@ static s32 __led_brightness_to_intensity(struct v4l2_ctrl *ctrl,
return (brightness * ctrl->step) + ctrl->minimum;
}
-static void v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
- struct v4l2_ctrl *ctrl)
+static int v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
+ struct v4l2_ctrl *ctrl)
{
struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
+ struct led_classdev *led_cdev;
enum led_brightness brightness;
if (has_flash_op(v4l2_flash, intensity_to_led_brightness))
@@ -102,14 +103,20 @@ static void v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
if (ctrl == ctrls[TORCH_INTENSITY]) {
if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
- return;
+ return 0;
- led_set_brightness_sync(&v4l2_flash->fled_cdev->led_cdev,
- brightness);
+ if (WARN_ON_ONCE(!v4l2_flash->fled_cdev))
+ return -EINVAL;
+
+ led_cdev = &v4l2_flash->fled_cdev->led_cdev;
} else {
- led_set_brightness_sync(v4l2_flash->iled_cdev,
- brightness);
+ if (WARN_ON_ONCE(!v4l2_flash->iled_cdev))
+ return -EINVAL;
+
+ led_cdev = v4l2_flash->iled_cdev;
}
+
+ return led_set_brightness_sync(led_cdev, brightness);
}
static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
@@ -128,8 +135,15 @@ static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
*/
if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
return 0;
+
+ if (WARN_ON_ONCE(!v4l2_flash->fled_cdev))
+ return -EINVAL;
+
led_cdev = &v4l2_flash->fled_cdev->led_cdev;
} else {
+ if (WARN_ON_ONCE(!v4l2_flash->iled_cdev))
+ return -EINVAL;
+
led_cdev = v4l2_flash->iled_cdev;
}
@@ -159,6 +173,12 @@ static int v4l2_flash_g_volatile_ctrl(struct v4l2_ctrl *c)
case V4L2_CID_FLASH_TORCH_INTENSITY:
case V4L2_CID_FLASH_INDICATOR_INTENSITY:
return v4l2_flash_update_led_brightness(v4l2_flash, c);
+ }
+
+ if (!fled_cdev)
+ return -EINVAL;
+
+ switch (c->id) {
case V4L2_CID_FLASH_INTENSITY:
ret = led_update_flash_brightness(fled_cdev);
if (ret < 0)
@@ -194,12 +214,23 @@ static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
{
struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
- struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
+ struct led_classdev *led_cdev;
struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
bool external_strobe;
int ret = 0;
switch (c->id) {
+ case V4L2_CID_FLASH_TORCH_INTENSITY:
+ case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+ return v4l2_flash_set_led_brightness(v4l2_flash, c);
+ }
+
+ if (!fled_cdev)
+ return -EINVAL;
+
+ led_cdev = &fled_cdev->led_cdev;
+
+ switch (c->id) {
case V4L2_CID_FLASH_LED_MODE:
switch (c->val) {
case V4L2_FLASH_LED_MODE_NONE:
@@ -230,9 +261,8 @@ static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
if (ret < 0)
return ret;
- v4l2_flash_set_led_brightness(v4l2_flash,
- ctrls[TORCH_INTENSITY]);
- return 0;
+ return v4l2_flash_set_led_brightness(v4l2_flash,
+ ctrls[TORCH_INTENSITY]);
}
break;
case V4L2_CID_FLASH_STROBE_SOURCE:
@@ -268,10 +298,6 @@ static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
* microamperes for flash intensity units.
*/
return led_set_flash_brightness(fled_cdev, c->val);
- case V4L2_CID_FLASH_TORCH_INTENSITY:
- case V4L2_CID_FLASH_INDICATOR_INTENSITY:
- v4l2_flash_set_led_brightness(v4l2_flash, c);
- return 0;
}
return -EINVAL;
@@ -483,15 +509,24 @@ static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
int ret = 0;
- if (ctrls[TORCH_INTENSITY])
- v4l2_flash_set_led_brightness(v4l2_flash,
- ctrls[TORCH_INTENSITY]);
+ if (ctrls[TORCH_INTENSITY]) {
+ ret = v4l2_flash_set_led_brightness(v4l2_flash,
+ ctrls[TORCH_INTENSITY]);
+ if (ret < 0)
+ return ret;
+ }
- if (ctrls[INDICATOR_INTENSITY])
- v4l2_flash_set_led_brightness(v4l2_flash,
- ctrls[INDICATOR_INTENSITY]);
+ if (ctrls[INDICATOR_INTENSITY]) {
+ ret = v4l2_flash_set_led_brightness(v4l2_flash,
+ ctrls[INDICATOR_INTENSITY]);
+ if (ret < 0)
+ return ret;
+ }
if (ctrls[FLASH_TIMEOUT]) {
+ if (WARN_ON_ONCE(!fled_cdev))
+ return -EINVAL;
+
ret = led_set_flash_timeout(fled_cdev,
ctrls[FLASH_TIMEOUT]->val);
if (ret < 0)
@@ -499,6 +534,9 @@ static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
}
if (ctrls[FLASH_INTENSITY]) {
+ if (WARN_ON_ONCE(!fled_cdev))
+ return -EINVAL;
+
ret = led_set_flash_brightness(fled_cdev,
ctrls[FLASH_INTENSITY]->val);
if (ret < 0)
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index f80c2ea39ca4..be0858bff4d3 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -9,6 +9,7 @@
* Copyright (C) 2009 Texas Instruments
* Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
*/
+#include <linux/cpu_pm.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -232,7 +233,10 @@ struct gpmc_device {
int irq;
struct irq_chip irq_chip;
struct gpio_chip gpio_chip;
+ struct notifier_block nb;
+ struct omap3_gpmc_regs context;
int nirqs;
+ unsigned int is_suspended:1;
};
static struct irq_domain *gpmc_irq_domain;
@@ -2384,6 +2388,106 @@ static int gpmc_gpio_init(struct gpmc_device *gpmc)
return 0;
}
+static void omap3_gpmc_save_context(struct gpmc_device *gpmc)
+{
+ struct omap3_gpmc_regs *gpmc_context;
+ int i;
+
+ if (!gpmc || !gpmc_base)
+ return;
+
+ gpmc_context = &gpmc->context;
+
+ gpmc_context->sysconfig = gpmc_read_reg(GPMC_SYSCONFIG);
+ gpmc_context->irqenable = gpmc_read_reg(GPMC_IRQENABLE);
+ gpmc_context->timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL);
+ gpmc_context->config = gpmc_read_reg(GPMC_CONFIG);
+ gpmc_context->prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
+ gpmc_context->prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
+ gpmc_context->prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
+ for (i = 0; i < gpmc_cs_num; i++) {
+ gpmc_context->cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
+ if (gpmc_context->cs_context[i].is_valid) {
+ gpmc_context->cs_context[i].config1 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG1);
+ gpmc_context->cs_context[i].config2 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG2);
+ gpmc_context->cs_context[i].config3 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG3);
+ gpmc_context->cs_context[i].config4 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG4);
+ gpmc_context->cs_context[i].config5 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG5);
+ gpmc_context->cs_context[i].config6 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG6);
+ gpmc_context->cs_context[i].config7 =
+ gpmc_cs_read_reg(i, GPMC_CS_CONFIG7);
+ }
+ }
+}
+
+static void omap3_gpmc_restore_context(struct gpmc_device *gpmc)
+{
+ struct omap3_gpmc_regs *gpmc_context;
+ int i;
+
+ if (!gpmc || !gpmc_base)
+ return;
+
+ gpmc_context = &gpmc->context;
+
+ gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context->sysconfig);
+ gpmc_write_reg(GPMC_IRQENABLE, gpmc_context->irqenable);
+ gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context->timeout_ctrl);
+ gpmc_write_reg(GPMC_CONFIG, gpmc_context->config);
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context->prefetch_config1);
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context->prefetch_config2);
+ gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context->prefetch_control);
+ for (i = 0; i < gpmc_cs_num; i++) {
+ if (gpmc_context->cs_context[i].is_valid) {
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
+ gpmc_context->cs_context[i].config1);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG2,
+ gpmc_context->cs_context[i].config2);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG3,
+ gpmc_context->cs_context[i].config3);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG4,
+ gpmc_context->cs_context[i].config4);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG5,
+ gpmc_context->cs_context[i].config5);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG6,
+ gpmc_context->cs_context[i].config6);
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG7,
+ gpmc_context->cs_context[i].config7);
+ } else {
+ gpmc_cs_write_reg(i, GPMC_CS_CONFIG7, 0);
+ }
+ }
+}
+
+static int omap_gpmc_context_notifier(struct notifier_block *nb,
+ unsigned long cmd, void *v)
+{
+ struct gpmc_device *gpmc;
+
+ gpmc = container_of(nb, struct gpmc_device, nb);
+ if (gpmc->is_suspended || pm_runtime_suspended(gpmc->dev))
+ return NOTIFY_OK;
+
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ omap3_gpmc_save_context(gpmc);
+ break;
+ case CPU_CLUSTER_PM_ENTER_FAILED: /* No need to restore context */
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ omap3_gpmc_restore_context(gpmc);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
static int gpmc_probe(struct platform_device *pdev)
{
int rc;
@@ -2472,6 +2576,9 @@ static int gpmc_probe(struct platform_device *pdev)
gpmc_probe_dt_children(pdev);
+ gpmc->nb.notifier_call = omap_gpmc_context_notifier;
+ cpu_pm_register_notifier(&gpmc->nb);
+
return 0;
gpio_init_failed:
@@ -2486,6 +2593,7 @@ static int gpmc_remove(struct platform_device *pdev)
{
struct gpmc_device *gpmc = platform_get_drvdata(pdev);
+ cpu_pm_unregister_notifier(&gpmc->nb);
gpmc_free_irq(gpmc);
gpmc_mem_exit();
pm_runtime_put_sync(&pdev->dev);
@@ -2497,15 +2605,23 @@ static int gpmc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int gpmc_suspend(struct device *dev)
{
- omap3_gpmc_save_context();
+ struct gpmc_device *gpmc = dev_get_drvdata(dev);
+
+ omap3_gpmc_save_context(gpmc);
pm_runtime_put_sync(dev);
+ gpmc->is_suspended = 1;
+
return 0;
}
static int gpmc_resume(struct device *dev)
{
+ struct gpmc_device *gpmc = dev_get_drvdata(dev);
+
pm_runtime_get_sync(dev);
- omap3_gpmc_restore_context();
+ omap3_gpmc_restore_context(gpmc);
+ gpmc->is_suspended = 0;
+
return 0;
}
#endif
@@ -2527,74 +2643,3 @@ static __init int gpmc_init(void)
return platform_driver_register(&gpmc_driver);
}
postcore_initcall(gpmc_init);
-
-static struct omap3_gpmc_regs gpmc_context;
-
-void omap3_gpmc_save_context(void)
-{
- int i;
-
- if (!gpmc_base)
- return;
-
- gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG);
- gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE);
- gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL);
- gpmc_context.config = gpmc_read_reg(GPMC_CONFIG);
- gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
- gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
- gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
- for (i = 0; i < gpmc_cs_num; i++) {
- gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
- if (gpmc_context.cs_context[i].is_valid) {
- gpmc_context.cs_context[i].config1 =
- gpmc_cs_read_reg(i, GPMC_CS_CONFIG1);
- gpmc_context.cs_context[i].config2 =
- gpmc_cs_read_reg(i, GPMC_CS_CONFIG2);
- gpmc_context.cs_context[i].config3 =
- gpmc_cs_read_reg(i, GPMC_CS_CONFIG3);
- gpmc_context.cs_context[i].config4 =
- gpmc_cs_read_reg(i, GPMC_CS_CONFIG4);
- gpmc_context.cs_context[i].config5 =
- gpmc_cs_read_reg(i, GPMC_CS_CONFIG5);
- gpmc_context.cs_context[i].config6 =
- gpmc_cs_read_reg(i, GPMC_CS_CONFIG6);
- gpmc_context.cs_context[i].config7 =
- gpmc_cs_read_reg(i, GPMC_CS_CONFIG7);
- }
- }
-}
-
-void omap3_gpmc_restore_context(void)
-{
- int i;
-
- if (!gpmc_base)
- return;
-
- gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig);
- gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable);
- gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl);
- gpmc_write_reg(GPMC_CONFIG, gpmc_context.config);
- gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1);
- gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2);
- gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control);
- for (i = 0; i < gpmc_cs_num; i++) {
- if (gpmc_context.cs_context[i].is_valid) {
- gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
- gpmc_context.cs_context[i].config1);
- gpmc_cs_write_reg(i, GPMC_CS_CONFIG2,
- gpmc_context.cs_context[i].config2);
- gpmc_cs_write_reg(i, GPMC_CS_CONFIG3,
- gpmc_context.cs_context[i].config3);
- gpmc_cs_write_reg(i, GPMC_CS_CONFIG4,
- gpmc_context.cs_context[i].config4);
- gpmc_cs_write_reg(i, GPMC_CS_CONFIG5,
- gpmc_context.cs_context[i].config5);
- gpmc_cs_write_reg(i, GPMC_CS_CONFIG6,
- gpmc_context.cs_context[i].config6);
- gpmc_cs_write_reg(i, GPMC_CS_CONFIG7,
- gpmc_context.cs_context[i].config7);
- }
- }
-}
diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
index e65eac5764d4..3d153881abc1 100644
--- a/drivers/memory/tegra/tegra186.c
+++ b/drivers/memory/tegra/tegra186.c
@@ -71,6 +71,7 @@ static int tegra186_mc_resume(struct tegra_mc *mc)
return 0;
}
+#if IS_ENABLED(CONFIG_IOMMU_API)
static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
const struct tegra_mc_client *client,
unsigned int sid)
@@ -108,6 +109,7 @@ static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
writel(sid, mc->regs + client->regs.sid.override);
}
}
+#endif
static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
{
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index bb1065990aeb..660df7d269fa 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -91,7 +91,7 @@ static int memstick_device_probe(struct device *dev)
return rc;
}
-static int memstick_device_remove(struct device *dev)
+static void memstick_device_remove(struct device *dev)
{
struct memstick_dev *card = container_of(dev, struct memstick_dev,
dev);
@@ -105,7 +105,6 @@ static int memstick_device_remove(struct device *dev)
}
put_device(dev);
- return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6a3fd2d75f96..ca0edab91aeb 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -510,6 +510,22 @@ config MFD_HI6421_PMIC
menus in order to enable them.
We communicate with the Hi6421 via memory-mapped I/O.
+config MFD_HI6421_SPMI
+ tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC"
+ depends on OF
+ depends on SPMI
+ select MFD_CORE
+ select REGMAP_SPMI
+ help
+ Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes
+ multi-functions, such as regulators, RTC, codec, Coulomb counter,
+ etc.
+
+ This driver includes core APIs _only_. You have to select
+ individual components like voltage regulators under corresponding
+ menus in order to enable them.
+ We communicate with the Hi6421v600 via a SPMI bus.
+
config MFD_HI655X_PMIC
tristate "HiSilicon Hi655X series PMU/Codec IC"
depends on ARCH_HISI || COMPILE_TEST
@@ -2183,5 +2199,33 @@ config MFD_INTEL_M10_BMC
additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_RSMU_I2C
+ tristate "Renesas Synchronization Management Unit with I2C"
+ depends on I2C && OF
+ select MFD_CORE
+ select REGMAP_I2C
+ help
+ Support for the Renesas Synchronization Management Unit, such as
+ Clockmatrix and 82P33XXX series. This option supports I2C as
+ the control interface.
+
+ This driver provides common support for accessing the device.
+ Additional drivers must be enabled in order to use the functionality
+ of the device.
+
+config MFD_RSMU_SPI
+ tristate "Renesas Synchronization Management Unit with SPI"
+ depends on SPI && OF
+ select MFD_CORE
+ select REGMAP_SPI
+ help
+ Support for the Renesas Synchronization Management Unit, such as
+ Clockmatrix and 82P33XXX series. This option supports SPI as
+ the control interface.
+
+ This driver provides common support for accessing the device.
+ Additional drivers must be enabled in order to use the functionality
+ of the device.
+
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8116c19d5fd4..2ba6646e874c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -231,6 +231,7 @@ obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
obj-$(CONFIG_MFD_IQS62X) += iqs62x.o
obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o
+obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o
obj-$(CONFIG_MFD_HI655X_PMIC) += hi655x-pmic.o
obj-$(CONFIG_MFD_DLN2) += dln2.o
obj-$(CONFIG_MFD_RT4831) += rt4831.o
@@ -272,3 +273,8 @@ obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
+
+rsmu-i2c-objs := rsmu_core.o rsmu_i2c.o
+rsmu-spi-objs := rsmu_core.o rsmu_spi.o
+obj-$(CONFIG_MFD_RSMU_I2C) += rsmu-i2c.o
+obj-$(CONFIG_MFD_RSMU_SPI) += rsmu-spi.o
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 30489670ea52..cca0aac26148 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -485,7 +485,7 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
line += 1;
- handle_nested_irq(irq_create_mapping(ab8500->domain, line));
+ handle_nested_irq(irq_find_mapping(ab8500->domain, line));
}
return 0;
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 4145a38b3890..8161a5dc68e8 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -125,12 +125,13 @@ static const struct regmap_range axp288_writeable_ranges[] = {
static const struct regmap_range axp288_volatile_ranges[] = {
regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
+ regmap_reg_range(AXP22X_PWR_OUT_CTRL1, AXP22X_ALDO3_V_OUT),
regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT),
regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL),
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
- regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+ regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
};
@@ -699,6 +700,18 @@ static const struct resource axp288_charger_resources[] = {
DEFINE_RES_IRQ(AXP288_IRQ_CBTO),
};
+static const char * const axp288_fuel_gauge_suppliers[] = { "axp288_charger" };
+
+static const struct property_entry axp288_fuel_gauge_properties[] = {
+ PROPERTY_ENTRY_STRING_ARRAY("supplied-from", axp288_fuel_gauge_suppliers),
+ { }
+};
+
+static const struct software_node axp288_fuel_gauge_sw_node = {
+ .name = "axp288_fuel_gauge",
+ .properties = axp288_fuel_gauge_properties,
+};
+
static const struct mfd_cell axp288_cells[] = {
{
.name = "axp288_adc",
@@ -716,6 +729,7 @@ static const struct mfd_cell axp288_cells[] = {
.name = "axp288_fuel_gauge",
.num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
.resources = axp288_fuel_gauge_resources,
+ .swnode = &axp288_fuel_gauge_sw_node,
}, {
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp288_power_button_resources),
diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/db8500-prcmu-regs.h
index 75fd1069372c..75fd1069372c 100644
--- a/drivers/mfd/dbx500-prcmu-regs.h
+++ b/drivers/mfd/db8500-prcmu-regs.h
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 287da20f1231..c1d3e7c116cf 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -37,7 +37,7 @@
#include <linux/regulator/db8500-prcmu.h>
#include <linux/regulator/machine.h>
#include <linux/platform_data/ux500_wdt.h>
-#include "dbx500-prcmu-regs.h"
+#include "db8500-prcmu-regs.h"
/* Index of different voltages to be used when accessing AVSData */
#define PRCM_AVS_BASE 0x2FC
@@ -1622,22 +1622,20 @@ static long round_clock_rate(u8 clock, unsigned long rate)
}
static const unsigned long db8500_armss_freqs[] = {
- 200000000,
- 400000000,
- 800000000,
+ 199680000,
+ 399360000,
+ 798720000,
998400000
};
/* The DB8520 has slightly higher ARMSS max frequency */
static const unsigned long db8520_armss_freqs[] = {
- 200000000,
- 400000000,
- 800000000,
+ 199680000,
+ 399360000,
+ 798720000,
1152000000
};
-
-
static long round_armss_rate(unsigned long rate)
{
unsigned long freq = 0;
@@ -2567,14 +2565,16 @@ static char *fw_project_name(u32 project)
return "U8500 C4";
case PRCMU_FW_PROJECT_U9500_MBL:
return "U9500 MBL";
- case PRCMU_FW_PROJECT_U8500_MBL:
- return "U8500 MBL";
+ case PRCMU_FW_PROJECT_U8500_SSG1:
+ return "U8500 Samsung 1";
case PRCMU_FW_PROJECT_U8500_MBL2:
return "U8500 MBL2";
case PRCMU_FW_PROJECT_U8520:
return "U8520 MBL";
case PRCMU_FW_PROJECT_U8420:
return "U8420";
+ case PRCMU_FW_PROJECT_U8500_SSG2:
+ return "U8500 Samsung 2";
case PRCMU_FW_PROJECT_U8420_SYSCLK:
return "U8420-sysclk";
case PRCMU_FW_PROJECT_U9540:
@@ -2951,14 +2951,13 @@ static const struct mfd_cell common_prcmu_devs[] = {
.pdata_size = sizeof(db8500_wdt_pdata),
.id = -1,
},
+ MFD_CELL_NAME("db8500-cpuidle"),
};
static const struct mfd_cell db8500_prcmu_devs[] = {
MFD_CELL_OF("db8500-prcmu-regulators", NULL,
&db8500_regulators, sizeof(db8500_regulators), 0,
"stericsson,db8500-prcmu-regulator"),
- MFD_CELL_OF("cpuidle-dbx500",
- NULL, NULL, 0, 0, "stericsson,cpuidle-dbx500"),
MFD_CELL_OF("db8500-thermal",
NULL, NULL, 0, 0, "stericsson,db8500-thermal"),
};
diff --git a/drivers/mfd/hi6421-spmi-pmic.c b/drivers/mfd/hi6421-spmi-pmic.c
new file mode 100644
index 000000000000..4f136826681b
--- /dev/null
+++ b/drivers/mfd/hi6421-spmi-pmic.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device driver for regulators in HISI PMIC IC
+ *
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2011 Hisilicon.
+ * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd.
+ */
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/hi6421-spmi-pmic.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+
+static const struct mfd_cell hi6421v600_devs[] = {
+ { .name = "hi6421v600-irq", },
+ { .name = "hi6421v600-regulator", },
+};
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 16,
+ .val_bits = BITS_PER_BYTE,
+ .max_register = 0xffff,
+ .fast_io = true
+};
+
+static int hi6421_spmi_pmic_probe(struct spmi_device *sdev)
+{
+ struct device *dev = &sdev->dev;
+ int ret;
+ struct hi6421_spmi_pmic *ddata;
+ ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ ddata->regmap = devm_regmap_init_spmi_ext(sdev, &regmap_config);
+ if (IS_ERR(ddata->regmap))
+ return PTR_ERR(ddata->regmap);
+
+ ddata->dev = dev;
+
+ dev_set_drvdata(&sdev->dev, ddata);
+
+ ret = devm_mfd_add_devices(&sdev->dev, PLATFORM_DEVID_NONE,
+ hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
+ NULL, 0, NULL);
+ if (ret < 0)
+ dev_err(dev, "Failed to add child devices: %d\n", ret);
+
+ return ret;
+}
+
+static const struct of_device_id pmic_spmi_id_table[] = {
+ { .compatible = "hisilicon,hi6421-spmi" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
+
+static struct spmi_driver hi6421_spmi_pmic_driver = {
+ .driver = {
+ .name = "hi6421-spmi-pmic",
+ .of_match_table = pmic_spmi_id_table,
+ },
+ .probe = hi6421_spmi_pmic_probe,
+};
+module_spmi_driver(hi6421_spmi_pmic_driver);
+
+MODULE_DESCRIPTION("HiSilicon Hi6421v600 SPMI PMIC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c
index 1f396039d58f..3f1d976eb67c 100644
--- a/drivers/mfd/intel-lpss-acpi.c
+++ b/drivers/mfd/intel-lpss-acpi.c
@@ -89,6 +89,11 @@ static const struct intel_lpss_platform_info apl_i2c_info = {
.swnode = &apl_i2c_node,
};
+static const struct intel_lpss_platform_info cnl_i2c_info = {
+ .clk_rate = 216000000,
+ .swnode = &spt_i2c_node,
+};
+
static const struct acpi_device_id intel_lpss_acpi_ids[] = {
/* SPT */
{ "INT3440", (kernel_ulong_t)&spt_info },
@@ -102,6 +107,19 @@ static const struct acpi_device_id intel_lpss_acpi_ids[] = {
{ "INT3448", (kernel_ulong_t)&spt_uart_info },
{ "INT3449", (kernel_ulong_t)&spt_uart_info },
{ "INT344A", (kernel_ulong_t)&spt_uart_info },
+ /* CNL */
+ { "INT34B0", (kernel_ulong_t)&spt_info },
+ { "INT34B1", (kernel_ulong_t)&spt_info },
+ { "INT34B2", (kernel_ulong_t)&cnl_i2c_info },
+ { "INT34B3", (kernel_ulong_t)&cnl_i2c_info },
+ { "INT34B4", (kernel_ulong_t)&cnl_i2c_info },
+ { "INT34B5", (kernel_ulong_t)&cnl_i2c_info },
+ { "INT34B6", (kernel_ulong_t)&cnl_i2c_info },
+ { "INT34B7", (kernel_ulong_t)&cnl_i2c_info },
+ { "INT34B8", (kernel_ulong_t)&spt_uart_info },
+ { "INT34B9", (kernel_ulong_t)&spt_uart_info },
+ { "INT34BA", (kernel_ulong_t)&spt_uart_info },
+ { "INT34BC", (kernel_ulong_t)&spt_info },
/* BXT */
{ "80860AAC", (kernel_ulong_t)&bxt_i2c_info },
{ "80860ABC", (kernel_ulong_t)&bxt_info },
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index a9bf10bee796..0e15afc39f54 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -301,7 +301,8 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,
snprintf(name, sizeof(name), "%s-div", devname);
tmp = clk_register_fractional_divider(NULL, name, __clk_get_name(tmp),
- 0, lpss->priv, 1, 15, 16, 15, 0,
+ CLK_FRAC_DIVIDER_POWER_OF_TWO_PS,
+ lpss->priv, 1, 15, 16, 15, 0,
NULL);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
diff --git a/drivers/mfd/intel-m10-bmc.c b/drivers/mfd/intel-m10-bmc.c
index 1a9bfb7f48cd..8db3bcf5fccc 100644
--- a/drivers/mfd/intel-m10-bmc.c
+++ b/drivers/mfd/intel-m10-bmc.c
@@ -15,7 +15,8 @@
enum m10bmc_type {
M10_N3000,
- M10_D5005
+ M10_D5005,
+ M10_N5010,
};
static struct mfd_cell m10bmc_d5005_subdevs[] = {
@@ -28,6 +29,10 @@ static struct mfd_cell m10bmc_pacn3000_subdevs[] = {
{ .name = "n3000bmc-secure" },
};
+static struct mfd_cell m10bmc_n5010_subdevs[] = {
+ { .name = "n5010bmc-hwmon" },
+};
+
static const struct regmap_range m10bmc_regmap_range[] = {
regmap_reg_range(M10BMC_LEGACY_BUILD_VER, M10BMC_LEGACY_BUILD_VER),
regmap_reg_range(M10BMC_SYS_BASE, M10BMC_SYS_END),
@@ -192,6 +197,10 @@ static int intel_m10_bmc_spi_probe(struct spi_device *spi)
cells = m10bmc_d5005_subdevs;
n_cell = ARRAY_SIZE(m10bmc_d5005_subdevs);
break;
+ case M10_N5010:
+ cells = m10bmc_n5010_subdevs;
+ n_cell = ARRAY_SIZE(m10bmc_n5010_subdevs);
+ break;
default:
return -ENODEV;
}
@@ -207,6 +216,7 @@ static int intel_m10_bmc_spi_probe(struct spi_device *spi)
static const struct spi_device_id m10bmc_spi_id[] = {
{ "m10-n3000", M10_N3000 },
{ "m10-d5005", M10_D5005 },
+ { "m10-n5010", M10_N5010 },
{ }
};
MODULE_DEVICE_TABLE(spi, m10bmc_spi_id);
diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c
index 01935ae4e9e1..9b9c76bd067b 100644
--- a/drivers/mfd/intel_quark_i2c_gpio.c
+++ b/drivers/mfd/intel_quark_i2c_gpio.c
@@ -17,7 +17,6 @@
#include <linux/clk-provider.h>
#include <linux/dmi.h>
#include <linux/i2c.h>
-#include <linux/platform_data/gpio-dwapb.h>
#include <linux/property.h>
/* PCI BAR for register base address */
@@ -28,15 +27,6 @@
#define MFD_ACPI_MATCH_GPIO 0ULL
#define MFD_ACPI_MATCH_I2C 1ULL
-/* The base GPIO number under GPIOLIB framework */
-#define INTEL_QUARK_MFD_GPIO_BASE 8
-
-/* The default number of South-Cluster GPIO on Quark. */
-#define INTEL_QUARK_MFD_NGPIO 8
-
-/* The DesignWare GPIO ports on Quark. */
-#define INTEL_QUARK_GPIO_NPORTS 1
-
#define INTEL_QUARK_IORES_MEM 0
#define INTEL_QUARK_IORES_IRQ 1
@@ -111,12 +101,38 @@ static struct resource intel_quark_gpio_res[] = {
[INTEL_QUARK_IORES_MEM] = {
.flags = IORESOURCE_MEM,
},
+ [INTEL_QUARK_IORES_IRQ] = {
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = {
.adr = MFD_ACPI_MATCH_GPIO,
};
+static const struct software_node intel_quark_gpio_controller_node = {
+ .name = "intel-quark-gpio-controller",
+};
+
+static const struct property_entry intel_quark_gpio_portA_properties[] = {
+ PROPERTY_ENTRY_U32("reg", 0),
+ PROPERTY_ENTRY_U32("snps,nr-gpios", 8),
+ PROPERTY_ENTRY_U32("gpio-base", 8),
+ { }
+};
+
+static const struct software_node intel_quark_gpio_portA_node = {
+ .name = "portA",
+ .parent = &intel_quark_gpio_controller_node,
+ .properties = intel_quark_gpio_portA_properties,
+};
+
+static const struct software_node *intel_quark_gpio_node_group[] = {
+ &intel_quark_gpio_controller_node,
+ &intel_quark_gpio_portA_node,
+ NULL
+};
+
static struct mfd_cell intel_quark_mfd_cells[] = {
[MFD_I2C_BAR] = {
.id = MFD_I2C_BAR,
@@ -203,35 +219,19 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev)
{
struct mfd_cell *cell = &intel_quark_mfd_cells[MFD_GPIO_BAR];
struct resource *res = intel_quark_gpio_res;
- struct dwapb_platform_data *pdata;
- struct device *dev = &pdev->dev;
+ int ret;
res[INTEL_QUARK_IORES_MEM].start = pci_resource_start(pdev, MFD_GPIO_BAR);
res[INTEL_QUARK_IORES_MEM].end = pci_resource_end(pdev, MFD_GPIO_BAR);
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
-
- /* For intel quark x1000, it has only one port: portA */
- pdata->nports = INTEL_QUARK_GPIO_NPORTS;
- pdata->properties = devm_kcalloc(dev, pdata->nports,
- sizeof(*pdata->properties),
- GFP_KERNEL);
- if (!pdata->properties)
- return -ENOMEM;
-
- /* Set the properties for portA */
- pdata->properties->fwnode = NULL;
- pdata->properties->idx = 0;
- pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO;
- pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE;
- pdata->properties->irq[0] = pci_irq_vector(pdev, 0);
- pdata->properties->irq_shared = true;
+ res[INTEL_QUARK_IORES_IRQ].start = pci_irq_vector(pdev, 0);
+ res[INTEL_QUARK_IORES_IRQ].end = pci_irq_vector(pdev, 0);
- cell->platform_data = pdata;
- cell->pdata_size = sizeof(*pdata);
+ ret = software_node_register_node_group(intel_quark_gpio_node_group);
+ if (ret)
+ return ret;
+ cell->swnode = &intel_quark_gpio_controller_node;
return 0;
}
@@ -274,10 +274,12 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,
NULL);
if (ret)
- goto err_free_irq_vectors;
+ goto err_unregister_gpio_node_group;
return 0;
+err_unregister_gpio_node_group:
+ software_node_unregister_node_group(intel_quark_gpio_node_group);
err_free_irq_vectors:
pci_free_irq_vectors(pdev);
err_unregister_i2c_clk:
@@ -288,6 +290,7 @@ err_unregister_i2c_clk:
static void intel_quark_mfd_remove(struct pci_dev *pdev)
{
mfd_remove_devices(&pdev->dev);
+ software_node_unregister_node_group(intel_quark_gpio_node_group);
pci_free_irq_vectors(pdev);
intel_quark_unregister_i2c_clk(&pdev->dev);
}
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 3bbb29a7e7a5..f10e53187f67 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -489,6 +489,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
[LPC_DH89XXCC] = {
.name = "DH89xxCC",
.iTCO_version = 2,
+ .gpio_version = ICH_V5_GPIO,
},
[LPC_PPT] = {
.name = "Panther Point",
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index 428a526cbe86..9ab9adce06fd 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -22,7 +22,7 @@
#define SMBASE 0x40
#define SMBUS_IO_SIZE 64
-#define GPIOBASE 0x44
+#define GPIO_BASE 0x44
#define GPIO_IO_SIZE 64
#define GPIO_IO_SIZE_CENTERTON 128
@@ -145,7 +145,7 @@ static int lpc_sch_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (ret == 0)
cells++;
- ret = lpc_sch_populate_cell(dev, GPIOBASE, "sch_gpio",
+ ret = lpc_sch_populate_cell(dev, GPIO_BASE, "sch_gpio",
info->io_size_gpio,
id->device, &lpc_sch_cells[cells]);
if (ret < 0)
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index eff9423e90f5..2fa592c37c6f 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -33,13 +33,12 @@ static int mcp_bus_probe(struct device *dev)
return drv->probe(mcp);
}
-static int mcp_bus_remove(struct device *dev)
+static void mcp_bus_remove(struct device *dev)
{
struct mcp *mcp = to_mcp(dev);
struct mcp_driver *drv = to_mcp_driver(dev->driver);
drv->remove(mcp);
- return 0;
}
static struct bus_type mcp_bus_type = {
diff --git a/drivers/mfd/mt6360-core.c b/drivers/mfd/mt6360-core.c
index e628953548ce..6eaa6775b888 100644
--- a/drivers/mfd/mt6360-core.c
+++ b/drivers/mfd/mt6360-core.c
@@ -319,18 +319,18 @@ static const struct resource mt6360_regulator_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OC_EVT, "buck2_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OV_EVT, "buck2_ov_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_UV_EVT, "buck2_uv_evt"),
- DEFINE_RES_IRQ_NAMED(MT6360_LDO6_OC_EVT, "ldo6_oc_evt"),
- DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT, "ldo7_oc_evt"),
- DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT, "ldo6_pgb_evt"),
- DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT, "ldo7_pgb_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO1_OC_EVT, "ldo1_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO2_OC_EVT, "ldo2_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO3_OC_EVT, "ldo3_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO5_OC_EVT, "ldo5_oc_evt"),
+ DEFINE_RES_IRQ_NAMED(MT6360_LDO6_OC_EVT, "ldo6_oc_evt"),
+ DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT, "ldo7_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO1_PGB_EVT, "ldo1_pgb_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO2_PGB_EVT, "ldo2_pgb_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO3_PGB_EVT, "ldo3_pgb_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO5_PGB_EVT, "ldo5_pgb_evt"),
+ DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT, "ldo6_pgb_evt"),
+ DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT, "ldo7_pgb_evt"),
};
static const struct mfd_cell mt6360_devs[] = {
diff --git a/drivers/mfd/rsmu.h b/drivers/mfd/rsmu.h
new file mode 100644
index 000000000000..bb88597d189f
--- /dev/null
+++ b/drivers/mfd/rsmu.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Renesas Synchronization Management Unit (SMU) devices.
+ *
+ * Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
+ */
+
+#ifndef __RSMU_MFD_H
+#define __RSMU_MFD_H
+
+#include <linux/mfd/rsmu.h>
+
+int rsmu_core_init(struct rsmu_ddata *rsmu);
+void rsmu_core_exit(struct rsmu_ddata *rsmu);
+
+#endif /* __RSMU_MFD_H */
diff --git a/drivers/mfd/rsmu_core.c b/drivers/mfd/rsmu_core.c
new file mode 100644
index 000000000000..29437fd0bd5b
--- /dev/null
+++ b/drivers/mfd/rsmu_core.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Core driver for Renesas Synchronization Management Unit (SMU) devices.
+ *
+ * Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rsmu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "rsmu.h"
+
+enum {
+ RSMU_PHC = 0,
+ RSMU_CDEV = 1,
+ RSMU_N_DEVS = 2,
+};
+
+static struct mfd_cell rsmu_cm_devs[] = {
+ [RSMU_PHC] = {
+ .name = "8a3400x-phc",
+ },
+ [RSMU_CDEV] = {
+ .name = "8a3400x-cdev",
+ },
+};
+
+static struct mfd_cell rsmu_sabre_devs[] = {
+ [RSMU_PHC] = {
+ .name = "82p33x1x-phc",
+ },
+ [RSMU_CDEV] = {
+ .name = "82p33x1x-cdev",
+ },
+};
+
+static struct mfd_cell rsmu_sl_devs[] = {
+ [RSMU_PHC] = {
+ .name = "8v19n85x-phc",
+ },
+ [RSMU_CDEV] = {
+ .name = "8v19n85x-cdev",
+ },
+};
+
+int rsmu_core_init(struct rsmu_ddata *rsmu)
+{
+ struct mfd_cell *cells;
+ int ret;
+
+ switch (rsmu->type) {
+ case RSMU_CM:
+ cells = rsmu_cm_devs;
+ break;
+ case RSMU_SABRE:
+ cells = rsmu_sabre_devs;
+ break;
+ case RSMU_SL:
+ cells = rsmu_sl_devs;
+ break;
+ default:
+ dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
+ return -ENODEV;
+ }
+
+ mutex_init(&rsmu->lock);
+
+ ret = devm_mfd_add_devices(rsmu->dev, PLATFORM_DEVID_AUTO, cells,
+ RSMU_N_DEVS, NULL, 0, NULL);
+ if (ret < 0)
+ dev_err(rsmu->dev, "Failed to register sub-devices: %d\n", ret);
+
+ return ret;
+}
+
+void rsmu_core_exit(struct rsmu_ddata *rsmu)
+{
+ mutex_destroy(&rsmu->lock);
+}
+
+MODULE_DESCRIPTION("Renesas SMU core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/rsmu_i2c.c b/drivers/mfd/rsmu_i2c.c
new file mode 100644
index 000000000000..dc001c9791c1
--- /dev/null
+++ b/drivers/mfd/rsmu_i2c.c
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * I2C driver for Renesas Synchronization Management Unit (SMU) devices.
+ *
+ * Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rsmu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "rsmu.h"
+
+/*
+ * 16-bit register address: the lower 8 bits of the register address come
+ * from the offset addr byte and the upper 8 bits come from the page register.
+ */
+#define RSMU_CM_PAGE_ADDR 0xFD
+#define RSMU_CM_PAGE_WINDOW 256
+
+/*
+ * 15-bit register address: the lower 7 bits of the register address come
+ * from the offset addr byte and the upper 8 bits come from the page register.
+ */
+#define RSMU_SABRE_PAGE_ADDR 0x7F
+#define RSMU_SABRE_PAGE_WINDOW 128
+
+static const struct regmap_range_cfg rsmu_cm_range_cfg[] = {
+ {
+ .range_min = 0,
+ .range_max = 0xD000,
+ .selector_reg = RSMU_CM_PAGE_ADDR,
+ .selector_mask = 0xFF,
+ .selector_shift = 0,
+ .window_start = 0,
+ .window_len = RSMU_CM_PAGE_WINDOW,
+ }
+};
+
+static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = {
+ {
+ .range_min = 0,
+ .range_max = 0x400,
+ .selector_reg = RSMU_SABRE_PAGE_ADDR,
+ .selector_mask = 0xFF,
+ .selector_shift = 0,
+ .window_start = 0,
+ .window_len = RSMU_SABRE_PAGE_WINDOW,
+ }
+};
+
+static bool rsmu_cm_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case RSMU_CM_PAGE_ADDR:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case RSMU_SABRE_PAGE_ADDR:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static const struct regmap_config rsmu_cm_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xD000,
+ .ranges = rsmu_cm_range_cfg,
+ .num_ranges = ARRAY_SIZE(rsmu_cm_range_cfg),
+ .volatile_reg = rsmu_cm_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+ .can_multi_write = true,
+};
+
+static const struct regmap_config rsmu_sabre_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x400,
+ .ranges = rsmu_sabre_range_cfg,
+ .num_ranges = ARRAY_SIZE(rsmu_sabre_range_cfg),
+ .volatile_reg = rsmu_sabre_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+ .can_multi_write = true,
+};
+
+static const struct regmap_config rsmu_sl_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .max_register = 0x339,
+ .cache_type = REGCACHE_NONE,
+ .can_multi_write = true,
+};
+
+static int rsmu_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ const struct regmap_config *cfg;
+ struct rsmu_ddata *rsmu;
+ int ret;
+
+ rsmu = devm_kzalloc(&client->dev, sizeof(*rsmu), GFP_KERNEL);
+ if (!rsmu)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, rsmu);
+
+ rsmu->dev = &client->dev;
+ rsmu->type = (enum rsmu_type)id->driver_data;
+
+ switch (rsmu->type) {
+ case RSMU_CM:
+ cfg = &rsmu_cm_regmap_config;
+ break;
+ case RSMU_SABRE:
+ cfg = &rsmu_sabre_regmap_config;
+ break;
+ case RSMU_SL:
+ cfg = &rsmu_sl_regmap_config;
+ break;
+ default:
+ dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
+ return -ENODEV;
+ }
+ rsmu->regmap = devm_regmap_init_i2c(client, cfg);
+ if (IS_ERR(rsmu->regmap)) {
+ ret = PTR_ERR(rsmu->regmap);
+ dev_err(rsmu->dev, "Failed to allocate register map: %d\n", ret);
+ return ret;
+ }
+
+ return rsmu_core_init(rsmu);
+}
+
+static int rsmu_i2c_remove(struct i2c_client *client)
+{
+ struct rsmu_ddata *rsmu = i2c_get_clientdata(client);
+
+ rsmu_core_exit(rsmu);
+
+ return 0;
+}
+
+static const struct i2c_device_id rsmu_i2c_id[] = {
+ { "8a34000", RSMU_CM },
+ { "8a34001", RSMU_CM },
+ { "82p33810", RSMU_SABRE },
+ { "82p33811", RSMU_SABRE },
+ { "8v19n850", RSMU_SL },
+ { "8v19n851", RSMU_SL },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, rsmu_i2c_id);
+
+static const struct of_device_id rsmu_i2c_of_match[] = {
+ { .compatible = "idt,8a34000", .data = (void *)RSMU_CM },
+ { .compatible = "idt,8a34001", .data = (void *)RSMU_CM },
+ { .compatible = "idt,82p33810", .data = (void *)RSMU_SABRE },
+ { .compatible = "idt,82p33811", .data = (void *)RSMU_SABRE },
+ { .compatible = "idt,8v19n850", .data = (void *)RSMU_SL },
+ { .compatible = "idt,8v19n851", .data = (void *)RSMU_SL },
+ {}
+};
+MODULE_DEVICE_TABLE(of, rsmu_i2c_of_match);
+
+static struct i2c_driver rsmu_i2c_driver = {
+ .driver = {
+ .name = "rsmu-i2c",
+ .of_match_table = of_match_ptr(rsmu_i2c_of_match),
+ },
+ .probe = rsmu_i2c_probe,
+ .remove = rsmu_i2c_remove,
+ .id_table = rsmu_i2c_id,
+};
+
+static int __init rsmu_i2c_init(void)
+{
+ return i2c_add_driver(&rsmu_i2c_driver);
+}
+subsys_initcall(rsmu_i2c_init);
+
+static void __exit rsmu_i2c_exit(void)
+{
+ i2c_del_driver(&rsmu_i2c_driver);
+}
+module_exit(rsmu_i2c_exit);
+
+MODULE_DESCRIPTION("Renesas SMU I2C driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/rsmu_spi.c b/drivers/mfd/rsmu_spi.c
new file mode 100644
index 000000000000..fec2b4ec477c
--- /dev/null
+++ b/drivers/mfd/rsmu_spi.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SPI driver for Renesas Synchronization Management Unit (SMU) devices.
+ *
+ * Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rsmu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include "rsmu.h"
+
+#define RSMU_CM_PAGE_ADDR 0x7C
+#define RSMU_SABRE_PAGE_ADDR 0x7F
+#define RSMU_HIGHER_ADDR_MASK 0xFF80
+#define RSMU_HIGHER_ADDR_SHIFT 7
+#define RSMU_LOWER_ADDR_MASK 0x7F
+
+static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
+{
+ struct spi_device *client = to_spi_device(rsmu->dev);
+ struct spi_transfer xfer = {0};
+ struct spi_message msg;
+ u8 cmd[256] = {0};
+ u8 rsp[256] = {0};
+ int ret;
+
+ cmd[0] = reg | 0x80;
+ xfer.rx_buf = rsp;
+ xfer.len = bytes + 1;
+ xfer.tx_buf = cmd;
+ xfer.bits_per_word = client->bits_per_word;
+ xfer.speed_hz = client->max_speed_hz;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ /*
+ * 4-wire SPI is a shift register, so for every byte you send,
+ * you get one back at the same time. Example read from 0xC024,
+ * which has value of 0x2D
+ *
+ * MOSI:
+ * 7C 00 C0 #Set page register
+ * A4 00 #MSB is set, so this is read command
+ * MISO:
+ * XX 2D #XX is a dummy byte from sending A4 and we
+ * need to throw it away
+ */
+ ret = spi_sync(client, &msg);
+ if (ret >= 0)
+ memcpy(buf, &rsp[1], xfer.len-1);
+
+ return ret;
+}
+
+static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
+{
+ struct spi_device *client = to_spi_device(rsmu->dev);
+ struct spi_transfer xfer = {0};
+ struct spi_message msg;
+ u8 cmd[256] = {0};
+
+ cmd[0] = reg;
+ memcpy(&cmd[1], buf, bytes);
+
+ xfer.len = bytes + 1;
+ xfer.tx_buf = cmd;
+ xfer.bits_per_word = client->bits_per_word;
+ xfer.speed_hz = client->max_speed_hz;
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ return spi_sync(client, &msg);
+}
+
+/*
+ * 1-byte (1B) offset addressing:
+ * 16-bit register address: the lower 7 bits of the register address come
+ * from the offset addr byte and the upper 9 bits come from the page register.
+ */
+static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u16 reg)
+{
+ u8 page_reg;
+ u8 buf[2];
+ u16 bytes;
+ u16 page;
+ int err;
+
+ switch (rsmu->type) {
+ case RSMU_CM:
+ page_reg = RSMU_CM_PAGE_ADDR;
+ page = reg & RSMU_HIGHER_ADDR_MASK;
+ buf[0] = (u8)(page & 0xff);
+ buf[1] = (u8)((page >> 8) & 0xff);
+ bytes = 2;
+ break;
+ case RSMU_SABRE:
+ page_reg = RSMU_SABRE_PAGE_ADDR;
+ page = reg >> RSMU_HIGHER_ADDR_SHIFT;
+ buf[0] = (u8)(page & 0xff);
+ bytes = 1;
+ break;
+ default:
+ dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
+ return -ENODEV;
+ }
+
+ /* Simply return if we are on the same page */
+ if (rsmu->page == page)
+ return 0;
+
+ err = rsmu_write_device(rsmu, page_reg, buf, bytes);
+ if (err)
+ dev_err(rsmu->dev, "Failed to set page offset 0x%x\n", page);
+ else
+ /* Remember the last page */
+ rsmu->page = page;
+
+ return err;
+}
+
+static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context);
+ u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK);
+ int err;
+
+ err = rsmu_write_page_register(rsmu, reg);
+ if (err)
+ return err;
+
+ err = rsmu_read_device(rsmu, addr, (u8 *)val, 1);
+ if (err)
+ dev_err(rsmu->dev, "Failed to read offset address 0x%x\n", addr);
+
+ return err;
+}
+
+static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context);
+ u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK);
+ u8 data = (u8)val;
+ int err;
+
+ err = rsmu_write_page_register(rsmu, reg);
+ if (err)
+ return err;
+
+ err = rsmu_write_device(rsmu, addr, &data, 1);
+ if (err)
+ dev_err(rsmu->dev,
+ "Failed to write offset address 0x%x\n", addr);
+
+ return err;
+}
+
+static const struct regmap_config rsmu_cm_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = 0xD000,
+ .reg_read = rsmu_reg_read,
+ .reg_write = rsmu_reg_write,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_config rsmu_sabre_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = 0x400,
+ .reg_read = rsmu_reg_read,
+ .reg_write = rsmu_reg_write,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int rsmu_spi_probe(struct spi_device *client)
+{
+ const struct spi_device_id *id = spi_get_device_id(client);
+ const struct regmap_config *cfg;
+ struct rsmu_ddata *rsmu;
+ int ret;
+
+ rsmu = devm_kzalloc(&client->dev, sizeof(*rsmu), GFP_KERNEL);
+ if (!rsmu)
+ return -ENOMEM;
+
+ spi_set_drvdata(client, rsmu);
+
+ rsmu->dev = &client->dev;
+ rsmu->type = (enum rsmu_type)id->driver_data;
+
+ /* Initialize regmap */
+ switch (rsmu->type) {
+ case RSMU_CM:
+ cfg = &rsmu_cm_regmap_config;
+ break;
+ case RSMU_SABRE:
+ cfg = &rsmu_sabre_regmap_config;
+ break;
+ default:
+ dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
+ return -ENODEV;
+ }
+
+ rsmu->regmap = devm_regmap_init(&client->dev, NULL, client, cfg);
+ if (IS_ERR(rsmu->regmap)) {
+ ret = PTR_ERR(rsmu->regmap);
+ dev_err(rsmu->dev, "Failed to allocate register map: %d\n", ret);
+ return ret;
+ }
+
+ return rsmu_core_init(rsmu);
+}
+
+static int rsmu_spi_remove(struct spi_device *client)
+{
+ struct rsmu_ddata *rsmu = spi_get_drvdata(client);
+
+ rsmu_core_exit(rsmu);
+
+ return 0;
+}
+
+static const struct spi_device_id rsmu_spi_id[] = {
+ { "8a34000", RSMU_CM },
+ { "8a34001", RSMU_CM },
+ { "82p33810", RSMU_SABRE },
+ { "82p33811", RSMU_SABRE },
+ {}
+};
+MODULE_DEVICE_TABLE(spi, rsmu_spi_id);
+
+static const struct of_device_id rsmu_spi_of_match[] = {
+ { .compatible = "idt,8a34000", .data = (void *)RSMU_CM },
+ { .compatible = "idt,8a34001", .data = (void *)RSMU_CM },
+ { .compatible = "idt,82p33810", .data = (void *)RSMU_SABRE },
+ { .compatible = "idt,82p33811", .data = (void *)RSMU_SABRE },
+ {}
+};
+MODULE_DEVICE_TABLE(of, rsmu_spi_of_match);
+
+static struct spi_driver rsmu_spi_driver = {
+ .driver = {
+ .name = "rsmu-spi",
+ .of_match_table = of_match_ptr(rsmu_spi_of_match),
+ },
+ .probe = rsmu_spi_probe,
+ .remove = rsmu_spi_remove,
+ .id_table = rsmu_spi_id,
+};
+
+static int __init rsmu_spi_init(void)
+{
+ return spi_register_driver(&rsmu_spi_driver);
+}
+subsys_initcall(rsmu_spi_init);
+
+static void __exit rsmu_spi_exit(void)
+{
+ spi_unregister_driver(&rsmu_spi_driver);
+}
+module_exit(rsmu_spi_exit);
+
+MODULE_DESCRIPTION("Renesas SMU SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c
index 87f684cff9a1..51536691ad9d 100644
--- a/drivers/mfd/simple-mfd-i2c.c
+++ b/drivers/mfd/simple-mfd-i2c.c
@@ -2,39 +2,64 @@
/*
* Simple MFD - I2C
*
+ * Author(s):
+ * Michael Walle <michael@walle.cc>
+ * Lee Jones <lee.jones@linaro.org>
+ *
* This driver creates a single register map with the intention for it to be
* shared by all sub-devices. Children can use their parent's device structure
* (dev.parent) in order to reference it.
*
* Once the register map has been successfully initialised, any sub-devices
- * represented by child nodes in Device Tree will be subsequently registered.
+ * represented by child nodes in Device Tree or via the MFD cells in this file
+ * will be subsequently registered.
*/
#include <linux/i2c.h>
#include <linux/kernel.h>
+#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
-static const struct regmap_config simple_regmap_config = {
+#include "simple-mfd-i2c.h"
+
+static const struct regmap_config regmap_config_8r_8v = {
.reg_bits = 8,
.val_bits = 8,
};
static int simple_mfd_i2c_probe(struct i2c_client *i2c)
{
- const struct regmap_config *config;
+ const struct simple_mfd_data *simple_mfd_data;
+ const struct regmap_config *regmap_config;
struct regmap *regmap;
+ int ret;
+
+ simple_mfd_data = device_get_match_data(&i2c->dev);
- config = device_get_match_data(&i2c->dev);
- if (!config)
- config = &simple_regmap_config;
+ /* If no regmap_config is specified, use the default 8reg and 8val bits */
+ if (!simple_mfd_data || !simple_mfd_data->regmap_config)
+ regmap_config = &regmap_config_8r_8v;
+ else
+ regmap_config = simple_mfd_data->regmap_config;
- regmap = devm_regmap_init_i2c(i2c, config);
+ regmap = devm_regmap_init_i2c(i2c, regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- return devm_of_platform_populate(&i2c->dev);
+ /* If no MFD cells are spedified, use register the DT child nodes instead */
+ if (!simple_mfd_data || !simple_mfd_data->mfd_cell)
+ return devm_of_platform_populate(&i2c->dev);
+
+ ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
+ simple_mfd_data->mfd_cell,
+ simple_mfd_data->mfd_cell_size,
+ NULL, 0, NULL);
+ if (ret)
+ dev_err(&i2c->dev, "Failed to add child devices\n");
+
+ return ret;
}
static const struct of_device_id simple_mfd_i2c_of_match[] = {
diff --git a/drivers/mfd/simple-mfd-i2c.h b/drivers/mfd/simple-mfd-i2c.h
new file mode 100644
index 000000000000..7cb2bdd347d9
--- /dev/null
+++ b/drivers/mfd/simple-mfd-i2c.h
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Simple MFD - I2C
+ *
+ * Author: Lee Jones <lee.jones@linaro.org>
+ *
+ * This driver creates a single register map with the intention for it to be
+ * shared by all sub-devices. Children can use their parent's device structure
+ * (dev.parent) in order to reference it.
+ *
+ * This driver creates a single register map with the intention for it to be
+ * shared by all sub-devices. Children can use their parent's device structure
+ * (dev.parent) in order to reference it.
+ *
+ * Once the register map has been successfully initialised, any sub-devices
+ * represented by child nodes in Device Tree or via the MFD cells in the
+ * associated C file will be subsequently registered.
+ */
+
+#ifndef __MFD_SIMPLE_MFD_I2C_H
+#define __MFD_SIMPLE_MFD_I2C_H
+
+#include <linux/mfd/core.h>
+#include <linux/regmap.h>
+
+struct simple_mfd_data {
+ const struct regmap_config *regmap_config;
+ const struct mfd_cell *mfd_cell;
+ size_t mfd_cell_size;
+};
+
+#endif /* __MFD_SIMPLE_MFD_I2C_H */
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 1dd39483e7c1..58d09c615e67 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -1095,7 +1095,7 @@ static irqreturn_t stmpe_irq(int irq, void *data)
if (variant->id_val == STMPE801_ID ||
variant->id_val == STMPE1600_ID) {
- int base = irq_create_mapping(stmpe->domain, 0);
+ int base = irq_find_mapping(stmpe->domain, 0);
handle_nested_irq(base);
return IRQ_HANDLED;
@@ -1123,7 +1123,7 @@ static irqreturn_t stmpe_irq(int irq, void *data)
while (status) {
int bit = __ffs(status);
int line = bank * 8 + bit;
- int nestedirq = irq_create_mapping(stmpe->domain, line);
+ int nestedirq = irq_find_mapping(stmpe->domain, line);
handle_nested_irq(nestedirq);
status &= ~(1 << bit);
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 765c0210cb52..191fdb87c424 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -60,7 +60,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
goto err_map;
}
- base = ioremap(res.start, resource_size(&res));
+ base = of_iomap(np, 0);
if (!base) {
ret = -ENOMEM;
goto err_map;
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index 7614f8fe0e91..13583cdb93b6 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -187,7 +187,7 @@ again:
while (status) {
int bit = __ffs(status);
- int virq = irq_create_mapping(tc3589x->domain, bit);
+ int virq = irq_find_mapping(tc3589x->domain, bit);
handle_nested_irq(virq);
status &= ~(1 << bit);
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 0e6e25308190..55adc379f94b 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -175,10 +175,9 @@ static int ti_tscadc_probe(struct platform_device *pdev)
tscadc->dev = &pdev->dev;
err = platform_get_irq(pdev, 0);
- if (err < 0) {
- dev_err(&pdev->dev, "no irq ID is specified.\n");
+ if (err < 0)
goto ret;
- } else
+ else
tscadc->irq = err;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/mfd/tps65086.c b/drivers/mfd/tps65086.c
index 341466ef20cc..3bd5728844a0 100644
--- a/drivers/mfd/tps65086.c
+++ b/drivers/mfd/tps65086.c
@@ -24,6 +24,7 @@
static const struct mfd_cell tps65086_cells[] = {
{ .name = "tps65086-regulator", },
{ .name = "tps65086-gpio", },
+ { .name = "tps65086-reset", },
};
static const struct regmap_range tps65086_yes_ranges[] = {
@@ -100,29 +101,30 @@ static int tps65086_probe(struct i2c_client *client,
(char)((version & TPS65086_DEVICEID_OTP_MASK) >> 4) + 'A',
(version & TPS65086_DEVICEID_REV_MASK) >> 6);
- ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0,
- &tps65086_irq_chip, &tps->irq_data);
- if (ret) {
- dev_err(tps->dev, "Failed to register IRQ chip\n");
- return ret;
+ if (tps->irq > 0) {
+ ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0,
+ &tps65086_irq_chip, &tps->irq_data);
+ if (ret) {
+ dev_err(tps->dev, "Failed to register IRQ chip\n");
+ return ret;
+ }
}
ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65086_cells,
ARRAY_SIZE(tps65086_cells), NULL, 0,
regmap_irq_get_domain(tps->irq_data));
- if (ret) {
+ if (ret && tps->irq > 0)
regmap_del_irq_chip(tps->irq, tps->irq_data);
- return ret;
- }
- return 0;
+ return ret;
}
static int tps65086_remove(struct i2c_client *client)
{
struct tps65086 *tps = i2c_get_clientdata(client);
- regmap_del_irq_chip(tps->irq, tps->irq_data);
+ if (tps->irq > 0)
+ regmap_del_irq_chip(tps->irq, tps->irq_data);
return 0;
}
diff --git a/drivers/mfd/tqmx86.c b/drivers/mfd/tqmx86.c
index ddddf08b6a4c..7ae906ff8e35 100644
--- a/drivers/mfd/tqmx86.c
+++ b/drivers/mfd/tqmx86.c
@@ -35,7 +35,11 @@
#define TQMX86_REG_BOARD_ID_E39x 7
#define TQMX86_REG_BOARD_ID_70EB 8
#define TQMX86_REG_BOARD_ID_80UC 9
-#define TQMX86_REG_BOARD_ID_90UC 10
+#define TQMX86_REG_BOARD_ID_110EB 11
+#define TQMX86_REG_BOARD_ID_E40M 12
+#define TQMX86_REG_BOARD_ID_E40S 13
+#define TQMX86_REG_BOARD_ID_E40C1 14
+#define TQMX86_REG_BOARD_ID_E40C2 15
#define TQMX86_REG_BOARD_REV 0x21
#define TQMX86_REG_IO_EXT_INT 0x26
#define TQMX86_REG_IO_EXT_INT_NONE 0
@@ -77,7 +81,7 @@ static struct i2c_board_info tqmx86_i2c_devices[] = {
},
};
-static struct ocores_i2c_platform_data ocores_platfom_data = {
+static struct ocores_i2c_platform_data ocores_platform_data = {
.num_devices = ARRAY_SIZE(tqmx86_i2c_devices),
.devices = tqmx86_i2c_devices,
};
@@ -85,8 +89,8 @@ static struct ocores_i2c_platform_data ocores_platfom_data = {
static const struct mfd_cell tqmx86_i2c_soft_dev[] = {
{
.name = "ocores-i2c",
- .platform_data = &ocores_platfom_data,
- .pdata_size = sizeof(ocores_platfom_data),
+ .platform_data = &ocores_platform_data,
+ .pdata_size = sizeof(ocores_platform_data),
.resources = tqmx_i2c_soft_resources,
.num_resources = ARRAY_SIZE(tqmx_i2c_soft_resources),
},
@@ -128,21 +132,33 @@ static const char *tqmx86_board_id_to_name(u8 board_id)
return "TQMx70EB";
case TQMX86_REG_BOARD_ID_80UC:
return "TQMx80UC";
- case TQMX86_REG_BOARD_ID_90UC:
- return "TQMx90UC";
+ case TQMX86_REG_BOARD_ID_110EB:
+ return "TQMx110EB";
+ case TQMX86_REG_BOARD_ID_E40M:
+ return "TQMxE40M";
+ case TQMX86_REG_BOARD_ID_E40S:
+ return "TQMxE40S";
+ case TQMX86_REG_BOARD_ID_E40C1:
+ return "TQMxE40C1";
+ case TQMX86_REG_BOARD_ID_E40C2:
+ return "TQMxE40C2";
default:
return "Unknown";
}
}
-static int tqmx86_board_id_to_clk_rate(u8 board_id)
+static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
{
switch (board_id) {
case TQMX86_REG_BOARD_ID_50UC:
case TQMX86_REG_BOARD_ID_60EB:
case TQMX86_REG_BOARD_ID_70EB:
case TQMX86_REG_BOARD_ID_80UC:
- case TQMX86_REG_BOARD_ID_90UC:
+ case TQMX86_REG_BOARD_ID_110EB:
+ case TQMX86_REG_BOARD_ID_E40M:
+ case TQMX86_REG_BOARD_ID_E40S:
+ case TQMX86_REG_BOARD_ID_E40C1:
+ case TQMX86_REG_BOARD_ID_E40C2:
return 24000;
case TQMX86_REG_BOARD_ID_E39M:
case TQMX86_REG_BOARD_ID_E39C:
@@ -152,7 +168,9 @@ static int tqmx86_board_id_to_clk_rate(u8 board_id)
case TQMX86_REG_BOARD_ID_E38C:
return 33000;
default:
- return 0;
+ dev_warn(dev, "unknown board %d, assuming 24MHz LPC clock\n",
+ board_id);
+ return 24000;
}
}
@@ -209,9 +227,11 @@ static int tqmx86_probe(struct platform_device *pdev)
/* Assumes the IRQ resource is first. */
tqmx_gpio_resources[0].start = gpio_irq;
+ } else {
+ tqmx_gpio_resources[0].flags = 0;
}
- ocores_platfom_data.clock_khz = tqmx86_board_id_to_clk_rate(board_id);
+ ocores_platform_data.clock_khz = tqmx86_board_id_to_clk_rate(dev, board_id);
if (i2c_det == TQMX86_REG_I2C_DETECT_SOFT) {
err = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
@@ -253,6 +273,14 @@ static const struct dmi_system_id tqmx86_dmi_table[] __initconst = {
},
.callback = tqmx86_create_platform_device,
},
+ {
+ .ident = "TQMX86",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TQ-Systems"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TQMx"),
+ },
+ .callback = tqmx86_create_platform_device,
+ },
{}
};
MODULE_DEVICE_TABLE(dmi, tqmx86_dmi_table);
diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c
index 6c3a619e2628..651a028bc519 100644
--- a/drivers/mfd/wm8994-irq.c
+++ b/drivers/mfd/wm8994-irq.c
@@ -154,7 +154,7 @@ static irqreturn_t wm8994_edge_irq(int irq, void *data)
struct wm8994 *wm8994 = data;
while (gpio_get_value_cansleep(wm8994->pdata.irq_gpio))
- handle_nested_irq(irq_create_mapping(wm8994->edge_irq, 0));
+ handle_nested_irq(irq_find_mapping(wm8994->edge_irq, 0));
return IRQ_HANDLED;
}
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index f4fb5c52b863..85ba901bc11b 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -208,6 +208,28 @@ config CS5535_CLOCK_EVENT_SRC
MFGPTs have a better resolution and max interval than the
generic PIT, and are suitable for use as high-res timers.
+config GEHC_ACHC
+ tristate "GEHC ACHC support"
+ depends on SPI && SYSFS
+ depends on SOC_IMX53 || COMPILE_TEST
+ select FW_LOADER
+ help
+ Support for GE ACHC microcontroller, that is part of the GE
+ PPD device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gehc-achc.
+
+config HI6421V600_IRQ
+ tristate "HiSilicon Hi6421v600 IRQ and powerkey"
+ depends on OF
+ depends on SPMI
+ select MFD_CORE
+ select REGMAP_SPMI
+ help
+ This driver provides IRQ handling for Hi6421v600, used on
+ some Kirin chipsets, like the one at Hikey 970.
+
config HP_ILO
tristate "Channel interface driver for the HP iLO processor"
depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e92a56d4442f..a086197af544 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
obj-$(CONFIG_SGI_XP) += sgi-xp/
obj-$(CONFIG_SGI_GRU) += sgi-gru/
obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o
+obj-$(CONFIG_GEHC_ACHC) += gehc-achc.o
obj-$(CONFIG_HP_ILO) += hpilo.o
obj-$(CONFIG_APDS9802ALS) += apds9802als.o
obj-$(CONFIG_ISL29003) += isl29003.o
@@ -57,3 +58,4 @@ obj-$(CONFIG_HABANA_AI) += habanalabs/
obj-$(CONFIG_UACCE) += uacce/
obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o
obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o
+obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o
diff --git a/drivers/misc/bcm-vk/bcm_vk_tty.c b/drivers/misc/bcm-vk/bcm_vk_tty.c
index dae9eeed84a2..1b6076a89ca6 100644
--- a/drivers/misc/bcm-vk/bcm_vk_tty.c
+++ b/drivers/misc/bcm-vk/bcm_vk_tty.c
@@ -249,7 +249,7 @@ int bcm_vk_tty_init(struct bcm_vk *vk, char *name)
tty_drv->name = kstrdup(name, GFP_KERNEL);
if (!tty_drv->name) {
err = -ENOMEM;
- goto err_put_tty_driver;
+ goto err_tty_driver_kref_put;
}
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
tty_drv->subtype = SERIAL_TYPE_NORMAL;
@@ -295,8 +295,8 @@ err_kfree_tty_name:
kfree(tty_drv->name);
tty_drv->name = NULL;
-err_put_tty_driver:
- put_tty_driver(tty_drv);
+err_tty_driver_kref_put:
+ tty_driver_kref_put(tty_drv);
return err;
}
@@ -317,7 +317,7 @@ void bcm_vk_tty_exit(struct bcm_vk *vk)
kfree(vk->tty_drv->name);
vk->tty_drv->name = NULL;
- put_tty_driver(vk->tty_drv);
+ tty_driver_kref_put(vk->tty_drv);
}
void bcm_vk_tty_terminate_tty_user(struct bcm_vk *vk)
diff --git a/drivers/misc/gehc-achc.c b/drivers/misc/gehc-achc.c
new file mode 100644
index 000000000000..02f33bc60c56
--- /dev/null
+++ b/drivers/misc/gehc-achc.c
@@ -0,0 +1,565 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * datasheet: https://www.nxp.com/docs/en/data-sheet/K20P144M120SF3.pdf
+ *
+ * Copyright (C) 2018-2021 Collabora
+ * Copyright (C) 2018-2021 GE Healthcare
+ */
+
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+
+#define ACHC_MAX_FREQ_HZ 300000
+#define ACHC_FAST_READ_FREQ_HZ 1000000
+
+struct achc_data {
+ struct spi_device *main;
+ struct spi_device *ezport;
+ struct gpio_desc *reset;
+
+ struct mutex device_lock; /* avoid concurrent device access */
+};
+
+#define EZPORT_RESET_DELAY_MS 100
+#define EZPORT_STARTUP_DELAY_MS 200
+#define EZPORT_WRITE_WAIT_MS 10
+#define EZPORT_TRANSFER_SIZE 2048
+
+#define EZPORT_CMD_SP 0x02 /* flash section program */
+#define EZPORT_CMD_RDSR 0x05 /* read status register */
+#define EZPORT_CMD_WREN 0x06 /* write enable */
+#define EZPORT_CMD_FAST_READ 0x0b /* flash read data at high speed */
+#define EZPORT_CMD_RESET 0xb9 /* reset chip */
+#define EZPORT_CMD_BE 0xc7 /* bulk erase */
+#define EZPORT_CMD_SE 0xd8 /* sector erase */
+
+#define EZPORT_SECTOR_SIZE 4096
+#define EZPORT_SECTOR_MASK (EZPORT_SECTOR_SIZE - 1)
+
+#define EZPORT_STATUS_WIP BIT(0) /* write in progress */
+#define EZPORT_STATUS_WEN BIT(1) /* write enable */
+#define EZPORT_STATUS_BEDIS BIT(2) /* bulk erase disable */
+#define EZPORT_STATUS_FLEXRAM BIT(3) /* FlexRAM mode */
+#define EZPORT_STATUS_WEF BIT(6) /* write error flag */
+#define EZPORT_STATUS_FS BIT(7) /* flash security */
+
+static void ezport_reset(struct gpio_desc *reset)
+{
+ gpiod_set_value(reset, 1);
+ msleep(EZPORT_RESET_DELAY_MS);
+ gpiod_set_value(reset, 0);
+ msleep(EZPORT_STARTUP_DELAY_MS);
+}
+
+static int ezport_start_programming(struct spi_device *spi, struct gpio_desc *reset)
+{
+ struct spi_message msg;
+ struct spi_transfer assert_cs = {
+ .cs_change = 1,
+ };
+ struct spi_transfer release_cs = { };
+ int ret;
+
+ spi_bus_lock(spi->master);
+
+ /* assert chip select */
+ spi_message_init(&msg);
+ spi_message_add_tail(&assert_cs, &msg);
+ ret = spi_sync_locked(spi, &msg);
+ if (ret)
+ goto fail;
+
+ msleep(EZPORT_STARTUP_DELAY_MS);
+
+ /* reset with asserted chip select to switch into programming mode */
+ ezport_reset(reset);
+
+ /* release chip select */
+ spi_message_init(&msg);
+ spi_message_add_tail(&release_cs, &msg);
+ ret = spi_sync_locked(spi, &msg);
+
+fail:
+ spi_bus_unlock(spi->master);
+ return ret;
+}
+
+static void ezport_stop_programming(struct spi_device *spi, struct gpio_desc *reset)
+{
+ /* reset without asserted chip select to return into normal mode */
+ spi_bus_lock(spi->master);
+ ezport_reset(reset);
+ spi_bus_unlock(spi->master);
+}
+
+static int ezport_get_status_register(struct spi_device *spi)
+{
+ int ret;
+
+ ret = spi_w8r8(spi, EZPORT_CMD_RDSR);
+ if (ret < 0)
+ return ret;
+ if (ret == 0xff) {
+ dev_err(&spi->dev, "Invalid EzPort status, EzPort is not functional!\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int ezport_soft_reset(struct spi_device *spi)
+{
+ u8 cmd = EZPORT_CMD_RESET;
+ int ret;
+
+ ret = spi_write(spi, &cmd, 1);
+ if (ret < 0)
+ return ret;
+
+ msleep(EZPORT_STARTUP_DELAY_MS);
+
+ return 0;
+}
+
+static int ezport_send_simple(struct spi_device *spi, u8 cmd)
+{
+ int ret;
+
+ ret = spi_write(spi, &cmd, 1);
+ if (ret < 0)
+ return ret;
+
+ return ezport_get_status_register(spi);
+}
+
+static int ezport_wait_write(struct spi_device *spi, u32 retries)
+{
+ int ret;
+ u32 i;
+
+ for (i = 0; i < retries; i++) {
+ ret = ezport_get_status_register(spi);
+ if (ret >= 0 && !(ret & EZPORT_STATUS_WIP))
+ break;
+ msleep(EZPORT_WRITE_WAIT_MS);
+ }
+
+ return ret;
+}
+
+static int ezport_write_enable(struct spi_device *spi)
+{
+ int ret = 0, retries = 3;
+
+ for (retries = 0; retries < 3; retries++) {
+ ret = ezport_send_simple(spi, EZPORT_CMD_WREN);
+ if (ret > 0 && ret & EZPORT_STATUS_WEN)
+ break;
+ }
+
+ if (!(ret & EZPORT_STATUS_WEN)) {
+ dev_err(&spi->dev, "EzPort write enable timed out\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int ezport_bulk_erase(struct spi_device *spi)
+{
+ int ret;
+ static const u8 cmd = EZPORT_CMD_BE;
+
+ dev_dbg(&spi->dev, "EzPort bulk erase...\n");
+
+ ret = ezport_write_enable(spi);
+ if (ret < 0)
+ return ret;
+
+ ret = spi_write(spi, &cmd, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = ezport_wait_write(spi, 1000);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int ezport_section_erase(struct spi_device *spi, u32 address)
+{
+ u8 query[] = {EZPORT_CMD_SE, (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff};
+ int ret;
+
+ dev_dbg(&spi->dev, "Ezport section erase @ 0x%06x...\n", address);
+
+ if (address & EZPORT_SECTOR_MASK)
+ return -EINVAL;
+
+ ret = ezport_write_enable(spi);
+ if (ret < 0)
+ return ret;
+
+ ret = spi_write(spi, query, sizeof(query));
+ if (ret < 0)
+ return ret;
+
+ return ezport_wait_write(spi, 200);
+}
+
+static int ezport_flash_transfer(struct spi_device *spi, u32 address,
+ const u8 *payload, size_t payload_size)
+{
+ struct spi_transfer xfers[2] = {};
+ u8 *command;
+ int ret;
+
+ dev_dbg(&spi->dev, "EzPort write %zu bytes @ 0x%06x...\n", payload_size, address);
+
+ ret = ezport_write_enable(spi);
+ if (ret < 0)
+ return ret;
+
+ command = kmalloc(4, GFP_KERNEL | GFP_DMA);
+ if (!command)
+ return -ENOMEM;
+
+ command[0] = EZPORT_CMD_SP;
+ command[1] = address >> 16;
+ command[2] = address >> 8;
+ command[3] = address >> 0;
+
+ xfers[0].tx_buf = command;
+ xfers[0].len = 4;
+
+ xfers[1].tx_buf = payload;
+ xfers[1].len = payload_size;
+
+ ret = spi_sync_transfer(spi, xfers, 2);
+ kfree(command);
+ if (ret < 0)
+ return ret;
+
+ return ezport_wait_write(spi, 40);
+}
+
+static int ezport_flash_compare(struct spi_device *spi, u32 address,
+ const u8 *payload, size_t payload_size)
+{
+ struct spi_transfer xfers[2] = {};
+ u8 *buffer;
+ int ret;
+
+ buffer = kmalloc(payload_size + 5, GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+
+ buffer[0] = EZPORT_CMD_FAST_READ;
+ buffer[1] = address >> 16;
+ buffer[2] = address >> 8;
+ buffer[3] = address >> 0;
+
+ xfers[0].tx_buf = buffer;
+ xfers[0].len = 4;
+ xfers[0].speed_hz = ACHC_FAST_READ_FREQ_HZ;
+
+ xfers[1].rx_buf = buffer + 4;
+ xfers[1].len = payload_size + 1;
+ xfers[1].speed_hz = ACHC_FAST_READ_FREQ_HZ;
+
+ ret = spi_sync_transfer(spi, xfers, 2);
+ if (ret)
+ goto err;
+
+ /* FAST_READ receives one dummy byte before the real data */
+ ret = memcmp(payload, buffer + 4 + 1, payload_size);
+ if (ret) {
+ ret = -EBADMSG;
+ dev_dbg(&spi->dev, "Verification failure @ %06x", address);
+ print_hex_dump_bytes("fw: ", DUMP_PREFIX_OFFSET, payload, payload_size);
+ print_hex_dump_bytes("dev: ", DUMP_PREFIX_OFFSET, buffer + 4, payload_size);
+ }
+
+err:
+ kfree(buffer);
+ return ret;
+}
+
+static int ezport_firmware_compare_data(struct spi_device *spi,
+ const u8 *data, size_t size)
+{
+ int ret;
+ size_t address = 0;
+ size_t transfer_size;
+
+ dev_dbg(&spi->dev, "EzPort compare data with %zu bytes...\n", size);
+
+ ret = ezport_get_status_register(spi);
+ if (ret < 0)
+ return ret;
+
+ if (ret & EZPORT_STATUS_FS) {
+ dev_info(&spi->dev, "Device is in secure mode (status=0x%02x)!\n", ret);
+ dev_info(&spi->dev, "FW verification is not possible\n");
+ return -EACCES;
+ }
+
+ while (size - address > 0) {
+ transfer_size = min((size_t) EZPORT_TRANSFER_SIZE, size - address);
+
+ ret = ezport_flash_compare(spi, address, data+address, transfer_size);
+ if (ret)
+ return ret;
+
+ address += transfer_size;
+ }
+
+ return 0;
+}
+
+static int ezport_firmware_flash_data(struct spi_device *spi,
+ const u8 *data, size_t size)
+{
+ int ret;
+ size_t address = 0;
+ size_t transfer_size;
+
+ dev_dbg(&spi->dev, "EzPort flash data with %zu bytes...\n", size);
+
+ ret = ezport_get_status_register(spi);
+ if (ret < 0)
+ return ret;
+
+ if (ret & EZPORT_STATUS_FS) {
+ ret = ezport_bulk_erase(spi);
+ if (ret < 0)
+ return ret;
+ if (ret & EZPORT_STATUS_FS)
+ return -EINVAL;
+ }
+
+ while (size - address > 0) {
+ if (!(address & EZPORT_SECTOR_MASK)) {
+ ret = ezport_section_erase(spi, address);
+ if (ret < 0)
+ return ret;
+ if (ret & EZPORT_STATUS_WIP || ret & EZPORT_STATUS_WEF)
+ return -EIO;
+ }
+
+ transfer_size = min((size_t) EZPORT_TRANSFER_SIZE, size - address);
+
+ ret = ezport_flash_transfer(spi, address,
+ data+address, transfer_size);
+ if (ret < 0)
+ return ret;
+ else if (ret & EZPORT_STATUS_WIP)
+ return -ETIMEDOUT;
+ else if (ret & EZPORT_STATUS_WEF)
+ return -EIO;
+
+ address += transfer_size;
+ }
+
+ dev_dbg(&spi->dev, "EzPort verify flashed data...\n");
+ ret = ezport_firmware_compare_data(spi, data, size);
+
+ /* allow missing FW verfication in secure mode */
+ if (ret == -EACCES)
+ ret = 0;
+
+ if (ret < 0)
+ dev_err(&spi->dev, "Failed to verify flashed data: %d\n", ret);
+
+ ret = ezport_soft_reset(spi);
+ if (ret < 0)
+ dev_warn(&spi->dev, "EzPort reset failed!\n");
+
+ return ret;
+}
+
+static int ezport_firmware_load(struct spi_device *spi, const char *fwname)
+{
+ const struct firmware *fw;
+ int ret;
+
+ ret = request_firmware(&fw, fwname, &spi->dev);
+ if (ret) {
+ dev_err(&spi->dev, "Could not get firmware: %d\n", ret);
+ return ret;
+ }
+
+ ret = ezport_firmware_flash_data(spi, fw->data, fw->size);
+
+ release_firmware(fw);
+
+ return ret;
+}
+
+/**
+ * ezport_flash - flash device firmware
+ * @spi: SPI device for NXP EzPort interface
+ * @reset: the gpio connected to the device reset pin
+ * @fwname: filename of the firmware that should be flashed
+ *
+ * Context: can sleep
+ *
+ * Return: 0 on success; negative errno on failure
+ */
+static int ezport_flash(struct spi_device *spi, struct gpio_desc *reset, const char *fwname)
+{
+ int ret;
+
+ ret = ezport_start_programming(spi, reset);
+ if (ret)
+ return ret;
+
+ ret = ezport_firmware_load(spi, fwname);
+
+ ezport_stop_programming(spi, reset);
+
+ if (ret)
+ dev_err(&spi->dev, "Failed to flash firmware: %d\n", ret);
+ else
+ dev_dbg(&spi->dev, "Finished FW flashing!\n");
+
+ return ret;
+}
+
+static ssize_t update_firmware_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct achc_data *achc = dev_get_drvdata(dev);
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &value);
+ if (ret < 0 || value != 1)
+ return -EINVAL;
+
+ mutex_lock(&achc->device_lock);
+ ret = ezport_flash(achc->ezport, achc->reset, "achc.bin");
+ mutex_unlock(&achc->device_lock);
+
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+static DEVICE_ATTR_WO(update_firmware);
+
+static ssize_t reset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct achc_data *achc = dev_get_drvdata(dev);
+ int ret;
+
+ mutex_lock(&achc->device_lock);
+ ret = gpiod_get_value(achc->reset);
+ mutex_unlock(&achc->device_lock);
+
+ if (ret < 0)
+ return ret;
+
+ return sysfs_emit(buf, "%d\n", ret);
+}
+
+static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct achc_data *achc = dev_get_drvdata(dev);
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &value);
+ if (ret < 0 || value > 1)
+ return -EINVAL;
+
+ mutex_lock(&achc->device_lock);
+ gpiod_set_value(achc->reset, value);
+ mutex_unlock(&achc->device_lock);
+
+ return count;
+}
+static DEVICE_ATTR_RW(reset);
+
+static struct attribute *gehc_achc_attrs[] = {
+ &dev_attr_update_firmware.attr,
+ &dev_attr_reset.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(gehc_achc);
+
+static void unregister_ezport(void *data)
+{
+ struct spi_device *ezport = data;
+
+ spi_unregister_device(ezport);
+}
+
+static int gehc_achc_probe(struct spi_device *spi)
+{
+ struct achc_data *achc;
+ int ezport_reg, ret;
+
+ spi->max_speed_hz = ACHC_MAX_FREQ_HZ;
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_0;
+
+ achc = devm_kzalloc(&spi->dev, sizeof(*achc), GFP_KERNEL);
+ if (!achc)
+ return -ENOMEM;
+ spi_set_drvdata(spi, achc);
+ achc->main = spi;
+
+ mutex_init(&achc->device_lock);
+
+ ret = of_property_read_u32_index(spi->dev.of_node, "reg", 1, &ezport_reg);
+ if (ret)
+ return dev_err_probe(&spi->dev, ret, "missing second reg entry!\n");
+
+ achc->ezport = spi_new_ancillary_device(spi, ezport_reg);
+ if (IS_ERR(achc->ezport))
+ return PTR_ERR(achc->ezport);
+
+ ret = devm_add_action_or_reset(&spi->dev, unregister_ezport, achc->ezport);
+ if (ret)
+ return ret;
+
+ achc->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(achc->reset))
+ return dev_err_probe(&spi->dev, PTR_ERR(achc->reset), "Could not get reset gpio\n");
+
+ return 0;
+}
+
+static const struct spi_device_id gehc_achc_id[] = {
+ { "ge,achc", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, gehc_achc_id);
+
+static const struct of_device_id gehc_achc_of_match[] = {
+ { .compatible = "ge,achc" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, gehc_achc_of_match);
+
+static struct spi_driver gehc_achc_spi_driver = {
+ .driver = {
+ .name = "gehc-achc",
+ .of_match_table = gehc_achc_of_match,
+ .dev_groups = gehc_achc_groups,
+ },
+ .probe = gehc_achc_probe,
+ .id_table = gehc_achc_id,
+};
+module_spi_driver(gehc_achc_spi_driver);
+
+MODULE_DESCRIPTION("GEHC ACHC driver");
+MODULE_AUTHOR("Sebastian Reichel <sebastian.reichel@collabora.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/hi6421v600-irq.c b/drivers/misc/hi6421v600-irq.c
new file mode 100644
index 000000000000..08535e97ff43
--- /dev/null
+++ b/drivers/misc/hi6421v600-irq.c
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device driver for irqs in HISI PMIC IC
+ *
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2011 Hisilicon.
+ * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd.
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/hi6421-spmi-pmic.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+
+struct hi6421v600_irq {
+ struct device *dev;
+ struct irq_domain *domain;
+ int irq;
+ unsigned int *irqs;
+ struct regmap *regmap;
+
+ /* Protect IRQ mask changes */
+ spinlock_t lock;
+};
+
+enum hi6421v600_irq_list {
+ OTMP = 0,
+ VBUS_CONNECT,
+ VBUS_DISCONNECT,
+ ALARMON_R,
+ HOLD_6S,
+ HOLD_1S,
+ POWERKEY_UP,
+ POWERKEY_DOWN,
+ OCP_SCP_R,
+ COUL_R,
+ SIM0_HPD_R,
+ SIM0_HPD_F,
+ SIM1_HPD_R,
+ SIM1_HPD_F,
+
+ PMIC_IRQ_LIST_MAX
+};
+
+#define HISI_IRQ_BANK_SIZE 2
+
+/*
+ * IRQ number for the power key button and mask for both UP and DOWN IRQs
+ */
+#define HISI_POWERKEY_IRQ_NUM 0
+#define HISI_IRQ_POWERKEY_UP_DOWN (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
+
+/*
+ * Registers for IRQ address and IRQ mask bits
+ *
+ * Please notice that we need to regmap a larger region, as other
+ * registers are used by the irqs.
+ * See drivers/irq/hi6421-irq.c.
+ */
+#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202
+#define SOC_PMIC_IRQ0_ADDR 0x0212
+
+/*
+ * The IRQs are mapped as:
+ *
+ * ====================== ============= ============ =====
+ * IRQ MASK REGISTER IRQ REGISTER BIT
+ * ====================== ============= ============ =====
+ * OTMP 0x0202 0x212 bit 0
+ * VBUS_CONNECT 0x0202 0x212 bit 1
+ * VBUS_DISCONNECT 0x0202 0x212 bit 2
+ * ALARMON_R 0x0202 0x212 bit 3
+ * HOLD_6S 0x0202 0x212 bit 4
+ * HOLD_1S 0x0202 0x212 bit 5
+ * POWERKEY_UP 0x0202 0x212 bit 6
+ * POWERKEY_DOWN 0x0202 0x212 bit 7
+ *
+ * OCP_SCP_R 0x0203 0x213 bit 0
+ * COUL_R 0x0203 0x213 bit 1
+ * SIM0_HPD_R 0x0203 0x213 bit 2
+ * SIM0_HPD_F 0x0203 0x213 bit 3
+ * SIM1_HPD_R 0x0203 0x213 bit 4
+ * SIM1_HPD_F 0x0203 0x213 bit 5
+ * ====================== ============= ============ =====
+ *
+ * Each mask register contains 8 bits. The ancillary macros below
+ * convert a number from 0 to 14 into a register address and a bit mask
+ */
+#define HISI_IRQ_MASK_REG(irq_data) (SOC_PMIC_IRQ_MASK_0_ADDR + \
+ (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
+#define HISI_IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
+#define HISI_8BITS_MASK 0xff
+
+static irqreturn_t hi6421v600_irq_handler(int irq, void *__priv)
+{
+ struct hi6421v600_irq *priv = __priv;
+ unsigned long pending;
+ unsigned int in;
+ int i, offset;
+
+ for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
+ regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
+
+ /* Mark pending IRQs as handled */
+ regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, in);
+
+ pending = in & HISI_8BITS_MASK;
+
+ if (i == HISI_POWERKEY_IRQ_NUM &&
+ (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
+ /*
+ * If both powerkey down and up IRQs are received,
+ * handle them at the right order
+ */
+ generic_handle_irq(priv->irqs[POWERKEY_DOWN]);
+ generic_handle_irq(priv->irqs[POWERKEY_UP]);
+ pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
+ }
+
+ if (!pending)
+ continue;
+
+ for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
+ generic_handle_irq(priv->irqs[offset + i * BITS_PER_BYTE]);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void hi6421v600_irq_mask(struct irq_data *d)
+{
+ struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d);
+ unsigned long flags;
+ unsigned int data;
+ u32 offset;
+
+ offset = HISI_IRQ_MASK_REG(d);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ regmap_read(priv->regmap, offset, &data);
+ data |= HISI_IRQ_MASK_BIT(d);
+ regmap_write(priv->regmap, offset, data);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void hi6421v600_irq_unmask(struct irq_data *d)
+{
+ struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d);
+ u32 data, offset;
+ unsigned long flags;
+
+ offset = HISI_IRQ_MASK_REG(d);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ regmap_read(priv->regmap, offset, &data);
+ data &= ~HISI_IRQ_MASK_BIT(d);
+ regmap_write(priv->regmap, offset, data);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static struct irq_chip hi6421v600_pmu_irqchip = {
+ .name = "hi6421v600-irq",
+ .irq_mask = hi6421v600_irq_mask,
+ .irq_unmask = hi6421v600_irq_unmask,
+ .irq_disable = hi6421v600_irq_mask,
+ .irq_enable = hi6421v600_irq_unmask,
+};
+
+static int hi6421v600_irq_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct hi6421v600_irq *priv = d->host_data;
+
+ irq_set_chip_and_handler_name(virq, &hi6421v600_pmu_irqchip,
+ handle_simple_irq, "hi6421v600");
+ irq_set_chip_data(virq, priv);
+ irq_set_irq_type(virq, IRQ_TYPE_NONE);
+
+ return 0;
+}
+
+static const struct irq_domain_ops hi6421v600_domain_ops = {
+ .map = hi6421v600_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static void hi6421v600_irq_init(struct hi6421v600_irq *priv)
+{
+ int i;
+ unsigned int pending;
+
+ /* Mask all IRQs */
+ for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
+ regmap_write(priv->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
+ HISI_8BITS_MASK);
+
+ /* Mark all IRQs as handled */
+ for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
+ regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
+ regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i,
+ HISI_8BITS_MASK);
+ }
+}
+
+static int hi6421v600_irq_probe(struct platform_device *pdev)
+{
+ struct device *pmic_dev = pdev->dev.parent;
+ struct device_node *np = pmic_dev->of_node;
+ struct platform_device *pmic_pdev;
+ struct device *dev = &pdev->dev;
+ struct hi6421v600_irq *priv;
+ struct hi6421_spmi_pmic *pmic;
+ unsigned int virq;
+ int i, ret;
+
+ /*
+ * This driver is meant to be called by hi6421-spmi-core,
+ * which should first set drvdata. If this doesn't happen, hit
+ * a warn on and return.
+ */
+ pmic = dev_get_drvdata(pmic_dev);
+ if (WARN_ON(!pmic))
+ return -ENODEV;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ priv->regmap = pmic->regmap;
+
+ spin_lock_init(&priv->lock);
+
+ pmic_pdev = container_of(pmic_dev, struct platform_device, dev);
+
+ priv->irq = platform_get_irq(pmic_pdev, 0);
+ if (priv->irq < 0) {
+ dev_err(dev, "Error %d when getting IRQs\n", priv->irq);
+ return priv->irq;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ hi6421v600_irq_init(priv);
+
+ priv->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
+ if (!priv->irqs)
+ return -ENOMEM;
+
+ priv->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
+ &hi6421v600_domain_ops, priv);
+ if (!priv->domain) {
+ dev_err(dev, "Failed to create IRQ domain\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
+ virq = irq_create_mapping(priv->domain, i);
+ if (!virq) {
+ dev_err(dev, "Failed to map H/W IRQ\n");
+ return -ENODEV;
+ }
+ priv->irqs[i] = virq;
+ }
+
+ ret = devm_request_threaded_irq(dev,
+ priv->irq, hi6421v600_irq_handler,
+ NULL,
+ IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
+ "pmic", priv);
+ if (ret < 0) {
+ dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id hi6421v600_irq_table[] = {
+ { .name = "hi6421v600-irq" },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, hi6421v600_irq_table);
+
+static struct platform_driver hi6421v600_irq_driver = {
+ .id_table = hi6421v600_irq_table,
+ .driver = {
+ .name = "hi6421v600-irq",
+ },
+ .probe = hi6421v600_irq_probe,
+};
+module_platform_driver(hi6421v600_irq_driver);
+
+MODULE_DESCRIPTION("HiSilicon Hi6421v600 IRQ driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h
index 7ac788fae1b8..c394c0b08519 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.h
+++ b/drivers/misc/lis3lv02d/lis3lv02d.h
@@ -271,7 +271,6 @@ struct lis3lv02d {
int regs_size;
u8 *reg_cache;
bool regs_stored;
- bool init_required;
u8 odr_mask; /* ODR bit mask */
u8 whoami; /* indicates measurement precision */
s16 (*read_data) (struct lis3lv02d *lis3, int reg);
diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
index 88c218a9f8b3..4282b625200f 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -267,6 +267,7 @@ void lkdtm_ARRAY_BOUNDS(void)
kfree(not_checked);
kfree(checked);
pr_err("FAIL: survived array bounds overflow!\n");
+ pr_expected_config(CONFIG_UBSAN_BOUNDS);
}
void lkdtm_CORRUPT_LIST_ADD(void)
@@ -506,53 +507,3 @@ noinline void lkdtm_CORRUPT_PAC(void)
pr_err("XFAIL: this test is arm64-only\n");
#endif
}
-
-void lkdtm_FORTIFY_OBJECT(void)
-{
- struct target {
- char a[10];
- } target[2] = {};
- int result;
-
- /*
- * Using volatile prevents the compiler from determining the value of
- * 'size' at compile time. Without that, we would get a compile error
- * rather than a runtime error.
- */
- volatile int size = 11;
-
- pr_info("trying to read past the end of a struct\n");
-
- result = memcmp(&target[0], &target[1], size);
-
- /* Print result to prevent the code from being eliminated */
- pr_err("FAIL: fortify did not catch an object overread!\n"
- "\"%d\" was the memcmp result.\n", result);
-}
-
-void lkdtm_FORTIFY_SUBOBJECT(void)
-{
- struct target {
- char a[10];
- char b[10];
- } target;
- char *src;
-
- src = kmalloc(20, GFP_KERNEL);
- strscpy(src, "over ten bytes", 20);
-
- pr_info("trying to strcpy past the end of a member of a struct\n");
-
- /*
- * strncpy(target.a, src, 20); will hit a compile error because the
- * compiler knows at build time that target.a < 20 bytes. Use strcpy()
- * to force a runtime error.
- */
- strcpy(target.a, src);
-
- /* Use target.a to prevent the code from being eliminated */
- pr_err("FAIL: fortify did not catch an sub-object overrun!\n"
- "\"%s\" was copied.\n", target.a);
-
- kfree(src);
-}
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index 9dda87c6b54a..95b1c6800a22 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -26,7 +26,6 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
-#include <linux/init.h>
#define DEFAULT_COUNT 10
@@ -82,8 +81,7 @@ static struct crashpoint crashpoints[] = {
CRASHPOINT("FS_DEVRW", "ll_rw_block"),
CRASHPOINT("MEM_SWAPOUT", "shrink_inactive_list"),
CRASHPOINT("TIMERADD", "hrtimer_start"),
- CRASHPOINT("SCSI_DISPATCH_CMD", "scsi_dispatch_cmd"),
- CRASHPOINT("IDE_CORE_CP", "generic_ide_ioctl"),
+ CRASHPOINT("SCSI_QUEUE_RQ", "scsi_queue_rq"),
#endif
};
@@ -119,8 +117,6 @@ static const struct crashtype crashtypes[] = {
CRASHTYPE(UNSET_SMEP),
CRASHTYPE(CORRUPT_PAC),
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
- CRASHTYPE(FORTIFY_OBJECT),
- CRASHTYPE(FORTIFY_SUBOBJECT),
CRASHTYPE(SLAB_LINEAR_OVERFLOW),
CRASHTYPE(VMALLOC_LINEAR_OVERFLOW),
CRASHTYPE(WRITE_AFTER_FREE),
@@ -180,6 +176,8 @@ static const struct crashtype crashtypes[] = {
CRASHTYPE(USERCOPY_KERNEL),
CRASHTYPE(STACKLEAK_ERASING),
CRASHTYPE(CFI_FORWARD_PROTO),
+ CRASHTYPE(FORTIFIED_OBJECT),
+ CRASHTYPE(FORTIFIED_SUBOBJECT),
CRASHTYPE(FORTIFIED_STRSCPY),
CRASHTYPE(DOUBLE_FAULT),
#ifdef CONFIG_PPC_BOOK3S_64
diff --git a/drivers/misc/lkdtm/fortify.c b/drivers/misc/lkdtm/fortify.c
index 0f51d31b57ca..d06458a4858e 100644
--- a/drivers/misc/lkdtm/fortify.c
+++ b/drivers/misc/lkdtm/fortify.c
@@ -8,6 +8,59 @@
#include <linux/string.h>
#include <linux/slab.h>
+static volatile int fortify_scratch_space;
+
+void lkdtm_FORTIFIED_OBJECT(void)
+{
+ struct target {
+ char a[10];
+ } target[2] = {};
+ /*
+ * Using volatile prevents the compiler from determining the value of
+ * 'size' at compile time. Without that, we would get a compile error
+ * rather than a runtime error.
+ */
+ volatile int size = 11;
+
+ pr_info("trying to read past the end of a struct\n");
+
+ /* Store result to global to prevent the code from being eliminated */
+ fortify_scratch_space = memcmp(&target[0], &target[1], size);
+
+ pr_err("FAIL: fortify did not block an object overread!\n");
+ pr_expected_config(CONFIG_FORTIFY_SOURCE);
+}
+
+void lkdtm_FORTIFIED_SUBOBJECT(void)
+{
+ struct target {
+ char a[10];
+ char b[10];
+ } target;
+ volatile int size = 20;
+ char *src;
+
+ src = kmalloc(size, GFP_KERNEL);
+ strscpy(src, "over ten bytes", size);
+ size = strlen(src) + 1;
+
+ pr_info("trying to strcpy past the end of a member of a struct\n");
+
+ /*
+ * memcpy(target.a, src, 20); will hit a compile error because the
+ * compiler knows at build time that target.a < 20 bytes. Use a
+ * volatile to force a runtime error.
+ */
+ memcpy(target.a, src, size);
+
+ /* Store result to global to prevent the code from being eliminated */
+ fortify_scratch_space = target.a[3];
+
+ pr_err("FAIL: fortify did not block an sub-object overrun!\n");
+ pr_expected_config(CONFIG_FORTIFY_SOURCE);
+
+ kfree(src);
+}
/*
* Calls fortified strscpy to test that it returns the same result as vanilla
diff --git a/drivers/misc/lkdtm/heap.c b/drivers/misc/lkdtm/heap.c
index 3d9aae5821a0..8a92f5a800fa 100644
--- a/drivers/misc/lkdtm/heap.c
+++ b/drivers/misc/lkdtm/heap.c
@@ -13,6 +13,13 @@ static struct kmem_cache *a_cache;
static struct kmem_cache *b_cache;
/*
+ * Using volatile here means the compiler cannot ever make assumptions
+ * about this value. This means compile-time length checks involving
+ * this variable cannot be performed; only run-time checks.
+ */
+static volatile int __offset = 1;
+
+/*
* If there aren't guard pages, it's likely that a consecutive allocation will
* let us overflow into the second allocation without overwriting something real.
*/
@@ -24,7 +31,7 @@ void lkdtm_VMALLOC_LINEAR_OVERFLOW(void)
two = vzalloc(PAGE_SIZE);
pr_info("Attempting vmalloc linear overflow ...\n");
- memset(one, 0xAA, PAGE_SIZE + 1);
+ memset(one, 0xAA, PAGE_SIZE + __offset);
vfree(two);
vfree(one);
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 6a30b60519f3..d7d64d9765eb 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -5,13 +5,17 @@
#define pr_fmt(fmt) "lkdtm: " fmt
#include <linux/kernel.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+
+#define LKDTM_KERNEL "kernel (" UTS_RELEASE " " UTS_MACHINE ")"
#define pr_expected_config(kconfig) \
{ \
if (IS_ENABLED(kconfig)) \
- pr_err("Unexpected! This kernel was built with " #kconfig "=y\n"); \
+ pr_err("Unexpected! This " LKDTM_KERNEL " was built with " #kconfig "=y\n"); \
else \
- pr_warn("This is probably expected, since this kernel was built *without* " #kconfig "=y\n"); \
+ pr_warn("This is probably expected, since this " LKDTM_KERNEL " was built *without* " #kconfig "=y\n"); \
}
#ifndef MODULE
@@ -21,24 +25,24 @@ int lkdtm_check_bool_cmdline(const char *param);
if (IS_ENABLED(kconfig)) { \
switch (lkdtm_check_bool_cmdline(param)) { \
case 0: \
- pr_warn("This is probably expected, since this kernel was built with " #kconfig "=y but booted with '" param "=N'\n"); \
+ pr_warn("This is probably expected, since this " LKDTM_KERNEL " was built with " #kconfig "=y but booted with '" param "=N'\n"); \
break; \
case 1: \
- pr_err("Unexpected! This kernel was built with " #kconfig "=y and booted with '" param "=Y'\n"); \
+ pr_err("Unexpected! This " LKDTM_KERNEL " was built with " #kconfig "=y and booted with '" param "=Y'\n"); \
break; \
default: \
- pr_err("Unexpected! This kernel was built with " #kconfig "=y (and booted without '" param "' specified)\n"); \
+ pr_err("Unexpected! This " LKDTM_KERNEL " was built with " #kconfig "=y (and booted without '" param "' specified)\n"); \
} \
} else { \
switch (lkdtm_check_bool_cmdline(param)) { \
case 0: \
- pr_warn("This is probably expected, as kernel was built *without* " #kconfig "=y and booted with '" param "=N'\n"); \
+ pr_warn("This is probably expected, as this " LKDTM_KERNEL " was built *without* " #kconfig "=y and booted with '" param "=N'\n"); \
break; \
case 1: \
- pr_err("Unexpected! This kernel was built *without* " #kconfig "=y but booted with '" param "=Y'\n"); \
+ pr_err("Unexpected! This " LKDTM_KERNEL " was built *without* " #kconfig "=y but booted with '" param "=Y'\n"); \
break; \
default: \
- pr_err("This is probably expected, since this kernel was built *without* " #kconfig "=y (and booted without '" param "' specified)\n"); \
+ pr_err("This is probably expected, since this " LKDTM_KERNEL " was built *without* " #kconfig "=y (and booted without '" param "' specified)\n"); \
break; \
} \
} \
@@ -74,8 +78,6 @@ void lkdtm_STACK_GUARD_PAGE_TRAILING(void);
void lkdtm_UNSET_SMEP(void);
void lkdtm_DOUBLE_FAULT(void);
void lkdtm_CORRUPT_PAC(void);
-void lkdtm_FORTIFY_OBJECT(void);
-void lkdtm_FORTIFY_SUBOBJECT(void);
/* heap.c */
void __init lkdtm_heap_init(void);
@@ -150,6 +152,8 @@ void lkdtm_STACKLEAK_ERASING(void);
void lkdtm_CFI_FORWARD_PROTO(void);
/* fortify.c */
+void lkdtm_FORTIFIED_OBJECT(void);
+void lkdtm_FORTIFIED_SUBOBJECT(void);
void lkdtm_FORTIFIED_STRSCPY(void);
/* powerpc.c */
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 935acc6bbf3c..44bac4ad687c 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -31,7 +31,7 @@
*
* Return: written size bytes or < 0 on error
*/
-ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, u8 vtag,
+ssize_t __mei_cl_send(struct mei_cl *cl, const u8 *buf, size_t length, u8 vtag,
unsigned int mode)
{
struct mei_device *bus;
@@ -232,8 +232,8 @@ out:
* * < 0 on error
*/
-ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
- u8 vtag)
+ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, const u8 *buf,
+ size_t length, u8 vtag)
{
struct mei_cl *cl = cldev->cl;
@@ -296,7 +296,7 @@ EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock_vtag);
* * written size in bytes
* * < 0 on error
*/
-ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
+ssize_t mei_cldev_send(struct mei_cl_device *cldev, const u8 *buf, size_t length)
{
return mei_cldev_send_vtag(cldev, buf, length, 0);
}
@@ -552,7 +552,7 @@ EXPORT_SYMBOL_GPL(mei_cldev_ver);
*
* Return: true if me client is initialized and connected
*/
-bool mei_cldev_enabled(struct mei_cl_device *cldev)
+bool mei_cldev_enabled(const struct mei_cl_device *cldev)
{
return mei_cl_is_connected(cldev->cl);
}
@@ -771,8 +771,8 @@ EXPORT_SYMBOL_GPL(mei_cldev_disable);
* Return: id on success; NULL if no id is matching
*/
static const
-struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev,
- struct mei_cl_driver *cldrv)
+struct mei_cl_device_id *mei_cl_device_find(const struct mei_cl_device *cldev,
+ const struct mei_cl_driver *cldrv)
{
const struct mei_cl_device_id *id;
const uuid_le *uuid;
@@ -815,8 +815,8 @@ struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev,
*/
static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
{
- struct mei_cl_device *cldev = to_mei_cl_device(dev);
- struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
+ const struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ const struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
const struct mei_cl_device_id *found_id;
if (!cldev)
@@ -884,7 +884,7 @@ static int mei_cl_device_probe(struct device *dev)
*
* Return: 0 on success; < 0 otherwise
*/
-static int mei_cl_device_remove(struct device *dev)
+static void mei_cl_device_remove(struct device *dev)
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
struct mei_cl_driver *cldrv = to_mei_cl_driver(dev->driver);
@@ -896,8 +896,6 @@ static int mei_cl_device_remove(struct device *dev)
mei_cl_bus_module_put(cldev);
module_put(THIS_MODULE);
-
- return 0;
}
static ssize_t name_show(struct device *dev, struct device_attribute *a,
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index b12cdcde9436..418056fb1489 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -160,7 +160,7 @@ int mei_cl_vt_support_check(const struct mei_cl *cl);
*
* Return: true if the host client is connected
*/
-static inline bool mei_cl_is_connected(struct mei_cl *cl)
+static inline bool mei_cl_is_connected(const struct mei_cl *cl)
{
return cl->state == MEI_FILE_CONNECTED;
}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index b7b6ef344e80..694f866f87ef 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -356,7 +356,7 @@ struct mei_hw_ops {
/* MEI bus API*/
void mei_cl_bus_rescan_work(struct work_struct *work);
void mei_cl_bus_dev_fixup(struct mei_cl_device *dev);
-ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, u8 vtag,
+ssize_t __mei_cl_send(struct mei_cl *cl, const u8 *buf, size_t length, u8 vtag,
unsigned int mode);
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length, u8 *vtag,
unsigned int mode, unsigned long timeout);
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 1b2868ca4f2a..d1137a95ad02 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -862,6 +862,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
err = -ENOMEM;
goto err_release_irq;
}
+ misc_device->parent = &pdev->dev;
misc_device->fops = &pci_endpoint_test_fops,
err = misc_register(misc_device);
diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c
index a43c401017ae..741116b3d995 100644
--- a/drivers/misc/pvpanic/pvpanic-pci.c
+++ b/drivers/misc/pvpanic/pvpanic-pci.c
@@ -108,4 +108,6 @@ static struct pci_driver pvpanic_pci_driver = {
},
};
+MODULE_DEVICE_TABLE(pci, pvpanic_pci_id_tbl);
+
module_pci_driver(pvpanic_pci_driver);
diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c
index 02b807c788c9..bb7aa6368538 100644
--- a/drivers/misc/pvpanic/pvpanic.c
+++ b/drivers/misc/pvpanic/pvpanic.c
@@ -85,6 +85,8 @@ int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi)
list_add(&pi->list, &pvpanic_list);
spin_unlock(&pvpanic_lock);
+ dev_set_drvdata(dev, pi);
+
return devm_add_action_or_reset(dev, pvpanic_remove, pi);
}
EXPORT_SYMBOL_GPL(devm_pvpanic_probe);
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index 40ac59dd018c..9afda47efbf2 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -282,7 +282,7 @@ static void gru_unload_mm_tracker(struct gru_state *gru,
*/
void gts_drop(struct gru_thread_state *gts)
{
- if (gts && atomic_dec_return(&gts->ts_refcnt) == 0) {
+ if (gts && refcount_dec_and_test(&gts->ts_refcnt)) {
if (gts->ts_gms)
gru_drop_mmu_notifier(gts->ts_gms);
kfree(gts);
@@ -323,7 +323,7 @@ struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
STAT(gts_alloc);
memset(gts, 0, sizeof(struct gru_thread_state)); /* zero out header */
- atomic_set(&gts->ts_refcnt, 1);
+ refcount_set(&gts->ts_refcnt, 1);
mutex_init(&gts->ts_ctxlock);
gts->ts_cbr_au_count = cbr_au_count;
gts->ts_dsr_au_count = dsr_au_count;
@@ -888,7 +888,7 @@ again:
gts->ts_gru = gru;
gts->ts_blade = gru->gs_blade_id;
gts->ts_ctxnum = gru_assign_context_number(gru);
- atomic_inc(&gts->ts_refcnt);
+ refcount_inc(&gts->ts_refcnt);
gru->gs_gts[gts->ts_ctxnum] = gts;
spin_unlock(&gru->gs_lock);
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index 5ce8f3081e96..e4c067c61251 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -129,6 +129,7 @@
*
*/
+#include <linux/refcount.h>
#include <linux/rmap.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
@@ -358,7 +359,7 @@ struct gru_thread_state {
enabled */
int ts_ctxnum; /* context number where the
context is loaded */
- atomic_t ts_refcnt; /* reference count GTS */
+ refcount_t ts_refcnt; /* reference count GTS */
unsigned char ts_dsr_au_count;/* Number of DSR resources
required for contest */
unsigned char ts_cbr_au_count;/* Number of CBR resources
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index 7791bde81a36..ba9ae0e2df0f 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -1742,7 +1742,7 @@ xpc_init_mq_node(int nid)
{
int cpu;
- get_online_cpus();
+ cpus_read_lock();
for_each_cpu(cpu, cpumask_of_node(nid)) {
xpc_activate_mq_uv =
@@ -1753,7 +1753,7 @@ xpc_init_mq_node(int nid)
break;
}
if (IS_ERR(xpc_activate_mq_uv)) {
- put_online_cpus();
+ cpus_read_unlock();
return PTR_ERR(xpc_activate_mq_uv);
}
@@ -1767,11 +1767,11 @@ xpc_init_mq_node(int nid)
}
if (IS_ERR(xpc_notify_mq_uv)) {
xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
- put_online_cpus();
+ cpus_read_unlock();
return PTR_ERR(xpc_notify_mq_uv);
}
- put_online_cpus();
+ cpus_read_unlock();
return 0;
}
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 93638ae2753a..4c26b19f5154 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -97,7 +97,24 @@ static int sram_add_partition(struct sram_dev *sram, struct sram_reserve *block,
struct sram_partition *part = &sram->partition[sram->partitions];
mutex_init(&part->lock);
- part->base = sram->virt_base + block->start;
+
+ if (sram->config && sram->config->map_only_reserved) {
+ void __iomem *virt_base;
+
+ if (sram->no_memory_wc)
+ virt_base = devm_ioremap_resource(sram->dev, &block->res);
+ else
+ virt_base = devm_ioremap_resource_wc(sram->dev, &block->res);
+
+ if (IS_ERR(virt_base)) {
+ dev_err(sram->dev, "could not map SRAM at %pr\n", &block->res);
+ return PTR_ERR(virt_base);
+ }
+
+ part->base = virt_base;
+ } else {
+ part->base = sram->virt_base + block->start;
+ }
if (block->pool) {
ret = sram_add_pool(sram, block, start, part);
@@ -198,6 +215,7 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
block->start = child_res.start - res->start;
block->size = resource_size(&child_res);
+ block->res = child_res;
list_add_tail(&block->list, &reserve_list);
if (of_find_property(child, "export", NULL))
@@ -295,15 +313,17 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
*/
cur_size = block->start - cur_start;
- dev_dbg(sram->dev, "adding chunk 0x%lx-0x%lx\n",
- cur_start, cur_start + cur_size);
+ if (sram->pool) {
+ dev_dbg(sram->dev, "adding chunk 0x%lx-0x%lx\n",
+ cur_start, cur_start + cur_size);
- ret = gen_pool_add_virt(sram->pool,
- (unsigned long)sram->virt_base + cur_start,
- res->start + cur_start, cur_size, -1);
- if (ret < 0) {
- sram_free_partitions(sram);
- goto err_chunks;
+ ret = gen_pool_add_virt(sram->pool,
+ (unsigned long)sram->virt_base + cur_start,
+ res->start + cur_start, cur_size, -1);
+ if (ret < 0) {
+ sram_free_partitions(sram);
+ goto err_chunks;
+ }
}
/* next allocation after this reserved block */
@@ -331,40 +351,63 @@ static int atmel_securam_wait(void)
10000, 500000);
}
+static const struct sram_config atmel_securam_config = {
+ .init = atmel_securam_wait,
+};
+
+/*
+ * SYSRAM contains areas that are not accessible by the
+ * kernel, such as the first 256K that is reserved for TZ.
+ * Accesses to those areas (including speculative accesses)
+ * trigger SErrors. As such we must map only the areas of
+ * SYSRAM specified in the device tree.
+ */
+static const struct sram_config tegra_sysram_config = {
+ .map_only_reserved = true,
+};
+
static const struct of_device_id sram_dt_ids[] = {
{ .compatible = "mmio-sram" },
- { .compatible = "atmel,sama5d2-securam", .data = atmel_securam_wait },
+ { .compatible = "atmel,sama5d2-securam", .data = &atmel_securam_config },
+ { .compatible = "nvidia,tegra186-sysram", .data = &tegra_sysram_config },
+ { .compatible = "nvidia,tegra194-sysram", .data = &tegra_sysram_config },
{}
};
static int sram_probe(struct platform_device *pdev)
{
+ const struct sram_config *config;
struct sram_dev *sram;
int ret;
struct resource *res;
- int (*init_func)(void);
+
+ config = of_device_get_match_data(&pdev->dev);
sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL);
if (!sram)
return -ENOMEM;
sram->dev = &pdev->dev;
+ sram->no_memory_wc = of_property_read_bool(pdev->dev.of_node, "no-memory-wc");
+ sram->config = config;
+
+ if (!config || !config->map_only_reserved) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (sram->no_memory_wc)
+ sram->virt_base = devm_ioremap_resource(&pdev->dev, res);
+ else
+ sram->virt_base = devm_ioremap_resource_wc(&pdev->dev, res);
+ if (IS_ERR(sram->virt_base)) {
+ dev_err(&pdev->dev, "could not map SRAM registers\n");
+ return PTR_ERR(sram->virt_base);
+ }
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (of_property_read_bool(pdev->dev.of_node, "no-memory-wc"))
- sram->virt_base = devm_ioremap_resource(&pdev->dev, res);
- else
- sram->virt_base = devm_ioremap_resource_wc(&pdev->dev, res);
- if (IS_ERR(sram->virt_base)) {
- dev_err(&pdev->dev, "could not map SRAM registers\n");
- return PTR_ERR(sram->virt_base);
+ sram->pool = devm_gen_pool_create(sram->dev, ilog2(SRAM_GRANULARITY),
+ NUMA_NO_NODE, NULL);
+ if (IS_ERR(sram->pool))
+ return PTR_ERR(sram->pool);
}
- sram->pool = devm_gen_pool_create(sram->dev, ilog2(SRAM_GRANULARITY),
- NUMA_NO_NODE, NULL);
- if (IS_ERR(sram->pool))
- return PTR_ERR(sram->pool);
-
sram->clk = devm_clk_get(sram->dev, NULL);
if (IS_ERR(sram->clk))
sram->clk = NULL;
@@ -378,15 +421,15 @@ static int sram_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sram);
- init_func = of_device_get_match_data(&pdev->dev);
- if (init_func) {
- ret = init_func();
+ if (config && config->init) {
+ ret = config->init();
if (ret)
goto err_free_partitions;
}
- dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n",
- gen_pool_size(sram->pool) / 1024, sram->virt_base);
+ if (sram->pool)
+ dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n",
+ gen_pool_size(sram->pool) / 1024, sram->virt_base);
return 0;
@@ -405,7 +448,7 @@ static int sram_remove(struct platform_device *pdev)
sram_free_partitions(sram);
- if (gen_pool_avail(sram->pool) < gen_pool_size(sram->pool))
+ if (sram->pool && gen_pool_avail(sram->pool) < gen_pool_size(sram->pool))
dev_err(sram->dev, "removed while SRAM allocated\n");
if (sram->clk)
diff --git a/drivers/misc/sram.h b/drivers/misc/sram.h
index 9c1d21ff7347..d2058d8c8f1d 100644
--- a/drivers/misc/sram.h
+++ b/drivers/misc/sram.h
@@ -5,6 +5,11 @@
#ifndef __SRAM_H
#define __SRAM_H
+struct sram_config {
+ int (*init)(void);
+ bool map_only_reserved;
+};
+
struct sram_partition {
void __iomem *base;
@@ -15,8 +20,11 @@ struct sram_partition {
};
struct sram_dev {
+ const struct sram_config *config;
+
struct device *dev;
void __iomem *virt_base;
+ bool no_memory_wc;
struct gen_pool *pool;
struct clk *clk;
@@ -29,6 +37,7 @@ struct sram_reserve {
struct list_head list;
u32 start;
u32 size;
+ struct resource res;
bool export;
bool pool;
bool protect_exec;
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index 667e574a7df2..52656fc87e99 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -87,7 +87,7 @@ static void tifm_dummy_event(struct tifm_dev *sock)
return;
}
-static int tifm_device_remove(struct device *dev)
+static void tifm_device_remove(struct device *dev)
{
struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
@@ -101,7 +101,6 @@ static int tifm_device_remove(struct device *dev)
}
put_device(dev);
- return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
index 880c33ab9f47..94ebf7f3fd58 100644
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
+++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
@@ -2243,7 +2243,8 @@ int vmci_qp_broker_map(struct vmci_handle handle,
result = VMCI_SUCCESS;
- if (context_id != VMCI_HOST_CONTEXT_ID) {
+ if (context_id != VMCI_HOST_CONTEXT_ID &&
+ !QPBROKERSTATE_HAS_MEM(entry)) {
struct vmci_qp_page_store page_store;
page_store.pages = guest_mem;
@@ -2350,7 +2351,8 @@ int vmci_qp_broker_unmap(struct vmci_handle handle,
goto out;
}
- if (context_id != VMCI_HOST_CONTEXT_ID) {
+ if (context_id != VMCI_HOST_CONTEXT_ID &&
+ QPBROKERSTATE_HAS_MEM(entry)) {
qp_acquire_queue_mutex(entry->produce_q);
result = qp_save_headers(entry);
if (result < VMCI_SUCCESS)
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 4383c262b3f5..f6b7a9c5bbff 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -140,14 +140,12 @@ static int mmc_bus_probe(struct device *dev)
return drv->probe(card);
}
-static int mmc_bus_remove(struct device *dev)
+static void mmc_bus_remove(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
drv->remove(card);
-
- return 0;
}
static void mmc_bus_shutdown(struct device *dev)
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 3d709029e07c..fda03b35c14a 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -203,7 +203,7 @@ disable_runtimepm:
return ret;
}
-static int sdio_bus_remove(struct device *dev)
+static void sdio_bus_remove(struct device *dev)
{
struct sdio_driver *drv = to_sdio_driver(dev->driver);
struct sdio_func *func = dev_to_sdio_func(dev);
@@ -232,8 +232,6 @@ static int sdio_bus_remove(struct device *dev)
pm_runtime_put_sync(dev);
dev_pm_domain_detach(dev, false);
-
- return 0;
}
static const struct dev_pm_ops sdio_bus_pm_ops = {
diff --git a/drivers/mmc/core/sdio_uart.c b/drivers/mmc/core/sdio_uart.c
index c36242b86b1d..04c0823e0359 100644
--- a/drivers/mmc/core/sdio_uart.c
+++ b/drivers/mmc/core/sdio_uart.c
@@ -1135,9 +1135,10 @@ static int __init sdio_uart_init(void)
int ret;
struct tty_driver *tty_drv;
- sdio_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);
- if (!tty_drv)
- return -ENOMEM;
+ sdio_uart_tty_driver = tty_drv = tty_alloc_driver(UART_NR,
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(tty_drv))
+ return PTR_ERR(tty_drv);
tty_drv->driver_name = "sdio_uart";
tty_drv->name = "ttySDIO";
@@ -1145,7 +1146,6 @@ static int __init sdio_uart_init(void)
tty_drv->minor_start = 0;
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
tty_drv->subtype = SERIAL_TYPE_NORMAL;
- tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_drv->init_termios = tty_std_termios;
tty_drv->init_termios.c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
tty_drv->init_termios.c_ispeed = 4800;
@@ -1165,7 +1165,7 @@ static int __init sdio_uart_init(void)
err2:
tty_unregister_driver(tty_drv);
err1:
- put_tty_driver(tty_drv);
+ tty_driver_kref_put(tty_drv);
return ret;
}
@@ -1173,7 +1173,7 @@ static void __exit sdio_uart_exit(void)
{
sdio_unregister_driver(&sdio_uart_driver);
tty_unregister_driver(sdio_uart_tty_driver);
- put_tty_driver(sdio_uart_tty_driver);
+ tty_driver_kref_put(sdio_uart_tty_driver);
}
module_init(sdio_uart_init);
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index cb1a64a5c256..80a2c270d502 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -578,10 +578,6 @@ static bool jz4740_mmc_read_data(struct jz4740_mmc_host *host,
}
}
data->bytes_xfered += miter->length;
-
- /* This can go away once MIPS implements
- * flush_kernel_dcache_page */
- flush_dcache_page(miter->page);
}
sg_miter_stop(miter);
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index a1bcde3395a6..f4c8e1a61f53 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -941,7 +941,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
/* discard mappings */
if (direction == DMA_FROM_DEVICE)
- flush_kernel_dcache_page(sg_page(sg));
+ flush_dcache_page(sg_page(sg));
kunmap(sg_page(sg));
if (dma_dev)
dma_unmap_page(dma_dev, dma_addr, PAGE_SIZE, dir);
diff --git a/drivers/most/most_cdev.c b/drivers/most/most_cdev.c
index 8908b9363a96..3722f9abd7b9 100644
--- a/drivers/most/most_cdev.c
+++ b/drivers/most/most_cdev.c
@@ -486,7 +486,7 @@ static struct cdev_component comp = {
},
};
-static int __init mod_init(void)
+static int __init most_cdev_init(void)
{
int err;
@@ -518,7 +518,7 @@ dest_ida:
return err;
}
-static void __exit mod_exit(void)
+static void __exit most_cdev_exit(void)
{
struct comp_channel *c, *tmp;
@@ -534,8 +534,8 @@ static void __exit mod_exit(void)
class_destroy(comp.class);
}
-module_init(mod_init);
-module_exit(mod_exit);
+module_init(most_cdev_init);
+module_exit(most_cdev_exit);
MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("character device component for mostcore");
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 8bab6f8718a9..796a2eccbef0 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -45,10 +45,9 @@ config MTD_BLOCK
on RAM chips in this manner. This block device is a user of MTD
devices performing that function.
- At the moment, it is also required for the Journalling Flash File
- System(s) to obtain a handle on the MTD device when it's mounted
- (although JFFS and JFFS2 don't actually use any of the functionality
- of the mtdblock device).
+ Note that mounting a JFFS2 filesystem doesn't require using mtdblock.
+ It's possible to mount a rootfs using the MTD device on the "root="
+ bootargs as "root=mtd2" or "root=mtd:name_of_device".
Later, it may be extended to perform read/erase/modify/write cycles
on flash chips to emulate a smaller block size. Needless to say,
@@ -70,6 +69,9 @@ config MTD_BLOCK_RO
You do not need this option for use with the DiskOnChip devices. For
those, enable NFTL support (CONFIG_NFTL) instead.
+comment "Note that in some cases UBI block is preferred. See MTD_UBI_BLOCK."
+ depends on MTD_BLOCK || MTD_BLOCK_RO
+
config FTL
tristate "FTL (Flash Translation Layer) support"
depends on BLOCK
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 9b33c082179d..f655d2905270 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1029,7 +1029,7 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
partition->mbd.tr = tr;
partition->mbd.devnum = -1;
- if (!add_mtd_blktrans_dev((void *)partition))
+ if (!add_mtd_blktrans_dev(&partition->mbd))
return;
}
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 6650acbc961e..aaa164b977fe 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -127,29 +127,6 @@ config MTD_PHYSMAP_GPIO_ADDR
Extend the physmap driver to allow flashes to be partially
physically addressed and assisted by GPIOs.
-config MTD_PMC_MSP_EVM
- tristate "CFI Flash device mapped on PMC-Sierra MSP"
- depends on PMC_MSP && MTD_CFI
- help
- This provides a 'mapping' driver which supports the way
- in which user-programmable flash chips are connected on the
- PMC-Sierra MSP eval/demo boards.
-
-choice
- prompt "Maximum mappable memory available for flash IO"
- depends on MTD_PMC_MSP_EVM
- default MSP_FLASH_MAP_LIMIT_32M
-
-config MSP_FLASH_MAP_LIMIT_32M
- bool "32M"
-
-endchoice
-
-config MSP_FLASH_MAP_LIMIT
- hex
- default "0x02000000"
- depends on MSP_FLASH_MAP_LIMIT_32M
-
config MTD_SUN_UFLASH
tristate "Sun Microsystems userflash support"
depends on SPARC && MTD_CFI && PCI
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 79f018cf412f..11fea9c8d561 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -25,7 +25,6 @@ physmap-objs-$(CONFIG_MTD_PHYSMAP_IXP4XX) += physmap-ixp4xx.o
physmap-objs := $(physmap-objs-y)
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
obj-$(CONFIG_MTD_PISMO) += pismo.o
-obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c
deleted file mode 100644
index 2051f28ddac6..000000000000
--- a/drivers/mtd/maps/pmcmsp-flash.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions.
- * Config with both CFI and JEDEC device support.
- *
- * Basically physmap.c with the addition of partitions and
- * an array of mapping info to accommodate more than one flash type per board.
- *
- * Copyright 2005-2007 PMC-Sierra, 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR 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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-
-#include <msp_prom.h>
-#include <msp_regs.h>
-
-
-static struct mtd_info **msp_flash;
-static struct mtd_partition **msp_parts;
-static struct map_info *msp_maps;
-static int fcnt;
-
-#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n", __func__, __LINE__)
-
-static int __init init_msp_flash(void)
-{
- int i, j, ret = -ENOMEM;
- int offset, coff;
- char *env;
- int pcnt;
- char flash_name[] = "flash0";
- char part_name[] = "flash0_0";
- unsigned addr, size;
-
- /* If ELB is disabled by "ful-mux" mode, we can't get at flash */
- if ((*DEV_ID_REG & DEV_ID_SINGLE_PC) &&
- (*ELB_1PC_EN_REG & SINGLE_PCCARD)) {
- printk(KERN_NOTICE "Single PC Card mode: no flash access\n");
- return -ENXIO;
- }
-
- /* examine the prom environment for flash devices */
- for (fcnt = 0; (env = prom_getenv(flash_name)); fcnt++)
- flash_name[5] = '0' + fcnt + 1;
-
- if (fcnt < 1)
- return -ENXIO;
-
- printk(KERN_NOTICE "Found %d PMC flash devices\n", fcnt);
-
- msp_flash = kcalloc(fcnt, sizeof(*msp_flash), GFP_KERNEL);
- if (!msp_flash)
- return -ENOMEM;
-
- msp_parts = kcalloc(fcnt, sizeof(*msp_parts), GFP_KERNEL);
- if (!msp_parts)
- goto free_msp_flash;
-
- msp_maps = kcalloc(fcnt, sizeof(*msp_maps), GFP_KERNEL);
- if (!msp_maps)
- goto free_msp_parts;
-
- /* loop over the flash devices, initializing each */
- for (i = 0; i < fcnt; i++) {
- /* examine the prom environment for flash partititions */
- part_name[5] = '0' + i;
- part_name[7] = '0';
- for (pcnt = 0; (env = prom_getenv(part_name)); pcnt++)
- part_name[7] = '0' + pcnt + 1;
-
- if (pcnt == 0) {
- printk(KERN_NOTICE "Skipping flash device %d "
- "(no partitions defined)\n", i);
- continue;
- }
-
- msp_parts[i] = kcalloc(pcnt, sizeof(struct mtd_partition),
- GFP_KERNEL);
- if (!msp_parts[i])
- goto cleanup_loop;
-
- /* now initialize the devices proper */
- flash_name[5] = '0' + i;
- env = prom_getenv(flash_name);
-
- if (sscanf(env, "%x:%x", &addr, &size) < 2) {
- ret = -ENXIO;
- kfree(msp_parts[i]);
- goto cleanup_loop;
- }
- addr = CPHYSADDR(addr);
-
- printk(KERN_NOTICE
- "MSP flash device \"%s\": 0x%08x at 0x%08x\n",
- flash_name, size, addr);
- /* This must matchs the actual size of the flash chip */
- msp_maps[i].size = size;
- msp_maps[i].phys = addr;
-
- /*
- * Platforms have a specific limit of the size of memory
- * which may be mapped for flash:
- */
- if (size > CONFIG_MSP_FLASH_MAP_LIMIT)
- size = CONFIG_MSP_FLASH_MAP_LIMIT;
-
- msp_maps[i].virt = ioremap(addr, size);
- if (msp_maps[i].virt == NULL) {
- ret = -ENXIO;
- kfree(msp_parts[i]);
- goto cleanup_loop;
- }
-
- msp_maps[i].bankwidth = 1;
- msp_maps[i].name = kstrndup(flash_name, 7, GFP_KERNEL);
- if (!msp_maps[i].name) {
- iounmap(msp_maps[i].virt);
- kfree(msp_parts[i]);
- goto cleanup_loop;
- }
-
- for (j = 0; j < pcnt; j++) {
- part_name[5] = '0' + i;
- part_name[7] = '0' + j;
-
- env = prom_getenv(part_name);
-
- if (sscanf(env, "%x:%x:%n", &offset, &size,
- &coff) < 2) {
- ret = -ENXIO;
- kfree(msp_maps[i].name);
- iounmap(msp_maps[i].virt);
- kfree(msp_parts[i]);
- goto cleanup_loop;
- }
-
- msp_parts[i][j].size = size;
- msp_parts[i][j].offset = offset;
- msp_parts[i][j].name = env + coff;
- }
-
- /* now probe and add the device */
- simple_map_init(&msp_maps[i]);
- msp_flash[i] = do_map_probe("cfi_probe", &msp_maps[i]);
- if (msp_flash[i]) {
- msp_flash[i]->owner = THIS_MODULE;
- mtd_device_register(msp_flash[i], msp_parts[i], pcnt);
- } else {
- printk(KERN_ERR "map probe failed for flash\n");
- ret = -ENXIO;
- kfree(msp_maps[i].name);
- iounmap(msp_maps[i].virt);
- kfree(msp_parts[i]);
- goto cleanup_loop;
- }
- }
-
- return 0;
-
-cleanup_loop:
- while (i--) {
- mtd_device_unregister(msp_flash[i]);
- map_destroy(msp_flash[i]);
- kfree(msp_maps[i].name);
- iounmap(msp_maps[i].virt);
- kfree(msp_parts[i]);
- }
- kfree(msp_maps);
-free_msp_parts:
- kfree(msp_parts);
-free_msp_flash:
- kfree(msp_flash);
- return ret;
-}
-
-static void __exit cleanup_msp_flash(void)
-{
- int i;
-
- for (i = 0; i < fcnt; i++) {
- mtd_device_unregister(msp_flash[i]);
- map_destroy(msp_flash[i]);
- iounmap((void *)msp_maps[i].virt);
-
- /* free the memory */
- kfree(msp_maps[i].name);
- kfree(msp_parts[i]);
- }
-
- kfree(msp_flash);
- kfree(msp_parts);
- kfree(msp_maps);
-}
-
-MODULE_AUTHOR("PMC-Sierra, Inc");
-MODULE_DESCRIPTION("MTD map driver for PMC-Sierra MSP boards");
-MODULE_LICENSE("GPL");
-
-module_init(init_msp_flash);
-module_exit(cleanup_msp_flash);
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 44bea3f65060..b8ae1ec14e17 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -23,7 +23,6 @@
#include "mtdcore.h"
static LIST_HEAD(blktrans_majors);
-static DEFINE_MUTEX(blktrans_ref_mutex);
static void blktrans_dev_release(struct kref *kref)
{
@@ -37,26 +36,9 @@ static void blktrans_dev_release(struct kref *kref)
kfree(dev);
}
-static struct mtd_blktrans_dev *blktrans_dev_get(struct gendisk *disk)
-{
- struct mtd_blktrans_dev *dev;
-
- mutex_lock(&blktrans_ref_mutex);
- dev = disk->private_data;
-
- if (!dev)
- goto unlock;
- kref_get(&dev->ref);
-unlock:
- mutex_unlock(&blktrans_ref_mutex);
- return dev;
-}
-
static void blktrans_dev_put(struct mtd_blktrans_dev *dev)
{
- mutex_lock(&blktrans_ref_mutex);
kref_put(&dev->ref, blktrans_dev_release);
- mutex_unlock(&blktrans_ref_mutex);
}
@@ -201,19 +183,16 @@ static blk_status_t mtd_queue_rq(struct blk_mq_hw_ctx *hctx,
static int blktrans_open(struct block_device *bdev, fmode_t mode)
{
- struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk);
+ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
int ret = 0;
- if (!dev)
- return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
+ kref_get(&dev->ref);
- mutex_lock(&mtd_table_mutex);
mutex_lock(&dev->lock);
if (dev->open)
goto unlock;
- kref_get(&dev->ref);
__module_get(dev->tr->owner);
if (!dev->mtd)
@@ -233,8 +212,6 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
unlock:
dev->open++;
mutex_unlock(&dev->lock);
- mutex_unlock(&mtd_table_mutex);
- blktrans_dev_put(dev);
return ret;
error_release:
@@ -242,27 +219,20 @@ error_release:
dev->tr->release(dev);
error_put:
module_put(dev->tr->owner);
- kref_put(&dev->ref, blktrans_dev_release);
mutex_unlock(&dev->lock);
- mutex_unlock(&mtd_table_mutex);
blktrans_dev_put(dev);
return ret;
}
static void blktrans_release(struct gendisk *disk, fmode_t mode)
{
- struct mtd_blktrans_dev *dev = blktrans_dev_get(disk);
-
- if (!dev)
- return;
+ struct mtd_blktrans_dev *dev = disk->private_data;
- mutex_lock(&mtd_table_mutex);
mutex_lock(&dev->lock);
if (--dev->open)
goto unlock;
- kref_put(&dev->ref, blktrans_dev_release);
module_put(dev->tr->owner);
if (dev->mtd) {
@@ -272,18 +242,14 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode)
}
unlock:
mutex_unlock(&dev->lock);
- mutex_unlock(&mtd_table_mutex);
blktrans_dev_put(dev);
}
static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk);
+ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
int ret = -ENXIO;
- if (!dev)
- return ret;
-
mutex_lock(&dev->lock);
if (!dev->mtd)
@@ -292,7 +258,6 @@ static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
ret = dev->tr->getgeo ? dev->tr->getgeo(dev, geo) : -ENOTTY;
unlock:
mutex_unlock(&dev->lock);
- blktrans_dev_put(dev);
return ret;
}
@@ -315,12 +280,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
struct gendisk *gd;
int ret;
- if (mutex_trylock(&mtd_table_mutex)) {
- mutex_unlock(&mtd_table_mutex);
- BUG();
- }
+ lockdep_assert_held(&mtd_table_mutex);
- mutex_lock(&blktrans_ref_mutex);
list_for_each_entry(d, &tr->devs, list) {
if (new->devnum == -1) {
/* Use first free number */
@@ -332,7 +293,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
}
} else if (d->devnum == new->devnum) {
/* Required number taken */
- mutex_unlock(&blktrans_ref_mutex);
return -EBUSY;
} else if (d->devnum > new->devnum) {
/* Required number was free */
@@ -350,14 +310,11 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
* minor numbers and that the disk naming code below can cope
* with this number. */
if (new->devnum > (MINORMASK >> tr->part_bits) ||
- (tr->part_bits && new->devnum >= 27 * 26)) {
- mutex_unlock(&blktrans_ref_mutex);
+ (tr->part_bits && new->devnum >= 27 * 26))
return ret;
- }
list_add_tail(&new->list, &tr->devs);
added:
- mutex_unlock(&blktrans_ref_mutex);
mutex_init(&new->lock);
kref_init(&new->ref);
@@ -449,10 +406,7 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
{
unsigned long flags;
- if (mutex_trylock(&mtd_table_mutex)) {
- mutex_unlock(&mtd_table_mutex);
- BUG();
- }
+ lockdep_assert_held(&mtd_table_mutex);
if (old->disk_attributes)
sysfs_remove_group(&disk_to_dev(old->disk)->kobj,
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index a80809543793..03e3de3a5d79 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -322,6 +322,10 @@ static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
if (!(mtd->flags & MTD_WRITEABLE))
dev->mbd.readonly = 1;
+ if (mtd_type_is_nand(mtd))
+ pr_warn("%s: MTD device '%s' is NAND, please consider using UBI block devices instead.\n",
+ tr->name, mtd->name);
+
if (add_mtd_blktrans_dev(&dev->mbd))
kfree(dev);
}
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
index d92914f73d52..7c51952ce55d 100644
--- a/drivers/mtd/mtdblock_ro.c
+++ b/drivers/mtd/mtdblock_ro.c
@@ -46,6 +46,10 @@ static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
dev->tr = tr;
dev->readonly = 1;
+ if (mtd_type_is_nand(mtd))
+ pr_warn("%s: MTD device '%s' is NAND, please consider using UBI block devices instead.\n",
+ tr->name, mtd->name);
+
if (add_mtd_blktrans_dev(dev))
kfree(dev);
}
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 6e4d0017c0bd..f685a581df48 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -641,6 +641,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
int i;
size_t size;
struct mtd_concat *concat;
+ struct mtd_info *subdev_master = NULL;
uint32_t max_erasesize, curr_erasesize;
int num_erase_region;
int max_writebufsize = 0;
@@ -679,18 +680,24 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.subpage_sft = subdev[0]->subpage_sft;
concat->mtd.oobsize = subdev[0]->oobsize;
concat->mtd.oobavail = subdev[0]->oobavail;
- if (subdev[0]->_writev)
+
+ subdev_master = mtd_get_master(subdev[0]);
+ if (subdev_master->_writev)
concat->mtd._writev = concat_writev;
- if (subdev[0]->_read_oob)
+ if (subdev_master->_read_oob)
concat->mtd._read_oob = concat_read_oob;
- if (subdev[0]->_write_oob)
+ if (subdev_master->_write_oob)
concat->mtd._write_oob = concat_write_oob;
- if (subdev[0]->_block_isbad)
+ if (subdev_master->_block_isbad)
concat->mtd._block_isbad = concat_block_isbad;
- if (subdev[0]->_block_markbad)
+ if (subdev_master->_block_markbad)
concat->mtd._block_markbad = concat_block_markbad;
- if (subdev[0]->_panic_write)
+ if (subdev_master->_panic_write)
concat->mtd._panic_write = concat_panic_write;
+ if (subdev_master->_read)
+ concat->mtd._read = concat_read;
+ if (subdev_master->_write)
+ concat->mtd._write = concat_write;
concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
@@ -721,14 +728,22 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
subdev[i]->flags & MTD_WRITEABLE;
}
+ subdev_master = mtd_get_master(subdev[i]);
concat->mtd.size += subdev[i]->size;
concat->mtd.ecc_stats.badblocks +=
subdev[i]->ecc_stats.badblocks;
if (concat->mtd.writesize != subdev[i]->writesize ||
concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
concat->mtd.oobsize != subdev[i]->oobsize ||
- !concat->mtd._read_oob != !subdev[i]->_read_oob ||
- !concat->mtd._write_oob != !subdev[i]->_write_oob) {
+ !concat->mtd._read_oob != !subdev_master->_read_oob ||
+ !concat->mtd._write_oob != !subdev_master->_write_oob) {
+ /*
+ * Check against subdev[i] for data members, because
+ * subdev's attributes may be different from master
+ * mtd device. Check against subdev's master mtd
+ * device for callbacks, because the existence of
+ * subdev's callbacks is decided by master mtd device.
+ */
kfree(concat);
printk("Incompatible OOB or ECC data on \"%s\"\n",
subdev[i]->name);
@@ -744,8 +759,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.name = name;
concat->mtd._erase = concat_erase;
- concat->mtd._read = concat_read;
- concat->mtd._write = concat_write;
concat->mtd._sync = concat_sync;
concat->mtd._lock = concat_lock;
concat->mtd._unlock = concat_unlock;
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 630728de4b7c..67b7cb67c030 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -480,9 +480,9 @@ config MTD_NAND_RICOH
select MTD_SM_COMMON
help
Enable support for Ricoh R5C852 xD card reader
- You also need to enable ether
+ You also need to enable either
NAND SSFDC (SmartMedia) read only translation layer' or new
- expermental, readwrite
+ experimental, readwrite
'SmartMedia/xD new translation layer'
config MTD_NAND_DISKONCHIP
diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index d0e8ffd55c22..9dbf031716a6 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -751,7 +751,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
"CAFE NAND", mtd);
if (err) {
dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
- goto out_ior;
+ goto out_free_rs;
}
/* Disable master reset, enable NAND clock */
@@ -795,6 +795,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
/* Disable NAND IRQ in global IRQ mask register */
cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
free_irq(pdev->irq, mtd);
+ out_free_rs:
+ free_rs(cafe->rs);
out_ior:
pci_iounmap(pdev, cafe->mmio);
out_free_mtd:
diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c
index 8b49fd56cf96..29e8a546dcd6 100644
--- a/drivers/mtd/nand/raw/intel-nand-controller.c
+++ b/drivers/mtd/nand/raw/intel-nand-controller.c
@@ -631,19 +631,26 @@ static int ebu_nand_probe(struct platform_device *pdev)
ebu_host->clk_rate = clk_get_rate(ebu_host->clk);
ebu_host->dma_tx = dma_request_chan(dev, "tx");
- if (IS_ERR(ebu_host->dma_tx))
- return dev_err_probe(dev, PTR_ERR(ebu_host->dma_tx),
- "failed to request DMA tx chan!.\n");
+ if (IS_ERR(ebu_host->dma_tx)) {
+ ret = dev_err_probe(dev, PTR_ERR(ebu_host->dma_tx),
+ "failed to request DMA tx chan!.\n");
+ goto err_disable_unprepare_clk;
+ }
ebu_host->dma_rx = dma_request_chan(dev, "rx");
- if (IS_ERR(ebu_host->dma_rx))
- return dev_err_probe(dev, PTR_ERR(ebu_host->dma_rx),
- "failed to request DMA rx chan!.\n");
+ if (IS_ERR(ebu_host->dma_rx)) {
+ ret = dev_err_probe(dev, PTR_ERR(ebu_host->dma_rx),
+ "failed to request DMA rx chan!.\n");
+ ebu_host->dma_rx = NULL;
+ goto err_cleanup_dma;
+ }
resname = devm_kasprintf(dev, GFP_KERNEL, "addr_sel%d", cs);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resname);
- if (!res)
- return -EINVAL;
+ if (!res) {
+ ret = -EINVAL;
+ goto err_cleanup_dma;
+ }
ebu_host->cs[cs].addr_sel = res->start;
writel(ebu_host->cs[cs].addr_sel | EBU_ADDR_MASK(5) | EBU_ADDR_SEL_REGEN,
ebu_host->ebu + EBU_ADDR_SEL(cs));
@@ -653,7 +660,8 @@ static int ebu_nand_probe(struct platform_device *pdev)
mtd = nand_to_mtd(&ebu_host->chip);
if (!mtd->name) {
dev_err(ebu_host->dev, "NAND label property is mandatory\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_cleanup_dma;
}
mtd->dev.parent = dev;
@@ -681,6 +689,7 @@ err_clean_nand:
nand_cleanup(&ebu_host->chip);
err_cleanup_dma:
ebu_dma_cleanup(ebu_host);
+err_disable_unprepare_clk:
clk_disable_unprepare(ebu_host->clk);
return ret;
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index 817bddccb775..ac3be92872d0 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -580,7 +580,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
u32 *addrs = nfc->cmdfifo.rw.addrs;
u32 cs = nfc->param.chip_select;
u32 cmd0, cmd_num, row_start;
- int ret = 0, i;
+ int i;
cmd_num = sizeof(struct nand_rw_cmd) / sizeof(int);
@@ -620,7 +620,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
meson_nfc_cmd_idle(nfc, nfc->timing.tadl);
}
- return ret;
+ return 0;
}
static int meson_nfc_write_page_sub(struct nand_chip *nand,
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index dced32a126d9..b7ad030225f8 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -447,6 +447,35 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
return 0;
}
+/* Check if a potential BBT block is marked as bad */
+static int bbt_block_checkbad(struct nand_chip *this, struct nand_bbt_descr *td,
+ loff_t offs, uint8_t *buf)
+{
+ struct nand_bbt_descr *bd = this->badblock_pattern;
+
+ /*
+ * No need to check for a bad BBT block if the BBM area overlaps with
+ * the bad block table marker area in OOB since writing a BBM here
+ * invalidates the bad block table marker anyway.
+ */
+ if (!(td->options & NAND_BBT_NO_OOB) &&
+ td->offs >= bd->offs && td->offs < bd->offs + bd->len)
+ return 0;
+
+ /*
+ * There is no point in checking for a bad block marker if writing
+ * such marker is not supported
+ */
+ if (this->bbt_options & NAND_BBT_NO_OOB_BBM ||
+ this->options & NAND_NO_BBM_QUIRK)
+ return 0;
+
+ if (scan_block_fast(this, bd, offs, buf) > 0)
+ return 1;
+
+ return 0;
+}
+
/**
* create_bbt - [GENERIC] Create a bad block table by scanning the device
* @this: NAND chip object
@@ -560,6 +589,10 @@ static int search_bbt(struct nand_chip *this, uint8_t *buf,
int actblock = startblock + dir * block;
loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
+ /* Check if block is marked bad */
+ if (bbt_block_checkbad(this, td, offs, buf))
+ continue;
+
/* Read first page */
scan_read(this, buf, offs, mtd->writesize, td);
if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index b1839eef5b65..b26d4947af02 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -911,7 +911,7 @@ static int omap_correct_data(struct nand_chip *chip, u_char *dat,
}
/**
- * omap_calcuate_ecc - Generate non-inverted ECC bytes.
+ * omap_calculate_ecc - Generate non-inverted ECC bytes.
* @chip: NAND chip object
* @dat: The pointer to data on which ecc is computed
* @ecc_code: The ecc_code buffer
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 446ba8d43fbc..2c8685f1f2fa 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -288,6 +288,8 @@ static int spinand_ondie_ecc_prepare_io_req(struct nand_device *nand,
struct spinand_device *spinand = nand_to_spinand(nand);
bool enable = (req->mode != MTD_OPS_RAW);
+ memset(spinand->oobbuf, 0xff, nanddev_per_page_oobsize(nand));
+
/* Only enable or disable the engine */
return spinand_ecc_enable(spinand, enable);
}
@@ -307,7 +309,7 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand,
if (req->type == NAND_PAGE_WRITE)
return 0;
- /* Finish a page write: check the status, report errors/bitflips */
+ /* Finish a page read: check the status, report errors/bitflips */
ret = spinand_check_ecc_status(spinand, engine_conf->status);
if (ret == -EBADMSG)
mtd->ecc_stats.failed++;
diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index a9890350db02..3f31f1381a62 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -126,7 +126,7 @@ static const struct spinand_info macronix_spinand_table[] = {
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
- 0,
+ SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35LF4GE4AD",
@@ -136,7 +136,7 @@ static const struct spinand_info macronix_spinand_table[] = {
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
- 0,
+ SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX35LF1G24AD",
@@ -146,16 +146,16 @@ static const struct spinand_info macronix_spinand_table[] = {
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
- 0,
+ SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
SPINAND_INFO("MX35LF2G24AD",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
- NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
- 0,
+ SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
SPINAND_INFO("MX35LF4G24AD",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
@@ -164,7 +164,7 @@ static const struct spinand_info macronix_spinand_table[] = {
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
- 0,
+ SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
SPINAND_INFO("MX31LF1GE4BC",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
@@ -173,7 +173,7 @@ static const struct spinand_info macronix_spinand_table[] = {
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
- 0 /*SPINAND_HAS_QE_BIT*/,
+ SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
SPINAND_INFO("MX31UF1GE4BC",
@@ -183,7 +183,7 @@ static const struct spinand_info macronix_spinand_table[] = {
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
- 0 /*SPINAND_HAS_QE_BIT*/,
+ SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
mx35lf1ge4ab_ecc_get_status)),
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index 6e0d5ce9b010..c546f8c5f24d 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -239,7 +239,7 @@ err:
static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *buf)
{
- struct partition *part = (struct partition*)dev;
+ struct partition *part = container_of(dev, struct partition, mbd);
u_long addr;
size_t retlen;
int rc;
@@ -600,7 +600,7 @@ static int find_free_sector(const struct partition *part, const struct block *bl
static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, ulong *old_addr)
{
- struct partition *part = (struct partition*)dev;
+ struct partition *part = container_of(dev, struct partition, mbd);
struct block *block;
u_long addr;
int i;
@@ -666,7 +666,7 @@ err:
static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf)
{
- struct partition *part = (struct partition*)dev;
+ struct partition *part = container_of(dev, struct partition, mbd);
u_long old_addr;
int i;
int rc = 0;
@@ -705,9 +705,37 @@ err:
return rc;
}
+static int rfd_ftl_discardsect(struct mtd_blktrans_dev *dev,
+ unsigned long sector, unsigned int nr_sects)
+{
+ struct partition *part = container_of(dev, struct partition, mbd);
+ u_long addr;
+ int rc;
+
+ while (nr_sects) {
+ if (sector >= part->sector_count)
+ return -EIO;
+
+ addr = part->sector_map[sector];
+
+ if (addr != -1) {
+ rc = mark_sector_deleted(part, addr);
+ if (rc)
+ return rc;
+
+ part->sector_map[sector] = -1;
+ }
+
+ sector++;
+ nr_sects--;
+ }
+
+ return 0;
+}
+
static int rfd_ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
{
- struct partition *part = (struct partition*)dev;
+ struct partition *part = container_of(dev, struct partition, mbd);
geo->heads = 1;
geo->sectors = SECTORS_PER_TRACK;
@@ -720,7 +748,8 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
struct partition *part;
- if (mtd->type != MTD_NORFLASH || mtd->size > UINT_MAX)
+ if ((mtd->type != MTD_NORFLASH && mtd->type != MTD_RAM) ||
+ mtd->size > UINT_MAX)
return;
part = kzalloc(sizeof(struct partition), GFP_KERNEL);
@@ -754,7 +783,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
printk(KERN_INFO PREFIX "name: '%s' type: %d flags %x\n",
mtd->name, mtd->type, mtd->flags);
- if (!add_mtd_blktrans_dev((void*)part))
+ if (!add_mtd_blktrans_dev(&part->mbd))
return;
}
out:
@@ -763,7 +792,7 @@ out:
static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev)
{
- struct partition *part = (struct partition*)dev;
+ struct partition *part = container_of(dev, struct partition, mbd);
int i;
for (i=0; i<part->total_blocks; i++) {
@@ -771,10 +800,10 @@ static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev)
part->mbd.mtd->name, i, part->blocks[i].erases);
}
- del_mtd_blktrans_dev(dev);
vfree(part->sector_map);
kfree(part->header_cache);
kfree(part->blocks);
+ del_mtd_blktrans_dev(&part->mbd);
}
static struct mtd_blktrans_ops rfd_ftl_tr = {
@@ -785,6 +814,7 @@ static struct mtd_blktrans_ops rfd_ftl_tr = {
.readsect = rfd_ftl_readsect,
.writesect = rfd_ftl_writesect,
+ .discard = rfd_ftl_discardsect,
.getgeo = rfd_ftl_getgeo,
.add_mtd = rfd_ftl_add_mtd,
.remove_dev = rfd_ftl_remove_dev,
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index a4a202b9a0a2..6006c2e8fa2b 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -96,7 +96,7 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker);
static void ad_mux_machine(struct port *port, bool *update_slave_arr);
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
static void ad_tx_machine(struct port *port);
-static void ad_periodic_machine(struct port *port, struct bond_params bond_params);
+static void ad_periodic_machine(struct port *port, struct bond_params *bond_params);
static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
static void ad_agg_selection_logic(struct aggregator *aggregator,
bool *update_slave_arr);
@@ -1298,7 +1298,7 @@ static void ad_tx_machine(struct port *port)
*
* Turn ntt flag on priodically to perform periodic transmission of lacpdu's.
*/
-static void ad_periodic_machine(struct port *port, struct bond_params bond_params)
+static void ad_periodic_machine(struct port *port, struct bond_params *bond_params)
{
periodic_states_t last_state;
@@ -1308,7 +1308,7 @@ static void ad_periodic_machine(struct port *port, struct bond_params bond_param
/* check if port was reinitialized */
if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
(!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) ||
- !bond_params.lacp_active) {
+ !bond_params->lacp_active) {
port->sm_periodic_state = AD_NO_PERIODIC;
}
/* check if state machine should change state */
@@ -2342,7 +2342,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
}
ad_rx_machine(NULL, port);
- ad_periodic_machine(port, bond->params);
+ ad_periodic_machine(port, &bond->params);
ad_port_selection_logic(port, &update_slave_arr);
ad_mux_machine(port, &update_slave_arr);
ad_tx_machine(port);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b0966e733926..77dc79a7f574 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2169,7 +2169,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
res = -EOPNOTSUPP;
goto err_sysfs_del;
}
- } else {
+ } else if (bond->xdp_prog) {
struct netdev_bpf xdp = {
.command = XDP_SETUP_PROG,
.flags = 0,
@@ -2910,9 +2910,9 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
* probe to generate any traffic (arp_validate=0)
*/
if (bond->params.arp_validate)
- net_warn_ratelimited("%s: no route to arp_ip_target %pI4 and arp_validate is set\n",
- bond->dev->name,
- &targets[i]);
+ pr_warn_once("%s: no route to arp_ip_target %pI4 and arp_validate is set\n",
+ bond->dev->name,
+ &targets[i]);
bond_arp_send(slave, ARPOP_REQUEST, targets[i],
0, tags);
continue;
@@ -5224,13 +5224,12 @@ static int bond_xdp_set(struct net_device *dev, struct bpf_prog *prog,
bpf_prog_inc(prog);
}
- if (old_prog)
- bpf_prog_put(old_prog);
-
- if (prog)
+ if (prog) {
static_branch_inc(&bpf_master_redirect_enabled_key);
- else
+ } else if (old_prog) {
+ bpf_prog_put(old_prog);
static_branch_dec(&bpf_master_redirect_enabled_key);
+ }
return 0;
diff --git a/drivers/net/can/c_can/c_can_ethtool.c b/drivers/net/can/c_can/c_can_ethtool.c
index cd5f07fca2a5..377c7d2e7612 100644
--- a/drivers/net/can/c_can/c_can_ethtool.c
+++ b/drivers/net/can/c_can/c_can_ethtool.c
@@ -15,10 +15,8 @@ static void c_can_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
{
struct c_can_priv *priv = netdev_priv(netdev);
- struct platform_device *pdev = to_platform_device(priv->device);
-
strscpy(info->driver, "c_can", sizeof(info->driver));
- strscpy(info->bus_info, pdev->name, sizeof(info->bus_info));
+ strscpy(info->bus_info, dev_name(priv->device), sizeof(info->bus_info));
}
static void c_can_get_ringparam(struct net_device *netdev,
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index c47988d3674e..ff9d0f5ae0dd 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -2017,7 +2017,7 @@ static int __maybe_unused rcar_canfd_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend,
rcar_canfd_resume);
-static const struct of_device_id rcar_canfd_of_table[] = {
+static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = {
{ .compatible = "renesas,rcar-gen3-canfd", .data = (void *)RENESAS_RCAR_GEN3 },
{ .compatible = "renesas,rzg2l-canfd", .data = (void *)RENESAS_RZG2L },
{ }
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index bd1417a66cbf..604f54112665 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1144,7 +1144,7 @@ static void b53_force_link(struct b53_device *dev, int port, int link)
u8 reg, val, off;
/* Override the port settings */
- if (port == dev->cpu_port) {
+ if (port == dev->imp_port) {
off = B53_PORT_OVERRIDE_CTRL;
val = PORT_OVERRIDE_EN;
} else {
@@ -1168,7 +1168,7 @@ static void b53_force_port_config(struct b53_device *dev, int port,
u8 reg, val, off;
/* Override the port settings */
- if (port == dev->cpu_port) {
+ if (port == dev->imp_port) {
off = B53_PORT_OVERRIDE_CTRL;
val = PORT_OVERRIDE_EN;
} else {
@@ -1236,7 +1236,7 @@ static void b53_adjust_link(struct dsa_switch *ds, int port,
b53_force_link(dev, port, phydev->link);
if (is531x5(dev) && phy_interface_is_rgmii(phydev)) {
- if (port == 8)
+ if (port == dev->imp_port)
off = B53_RGMII_CTRL_IMP;
else
off = B53_RGMII_CTRL_P(port);
@@ -2280,6 +2280,7 @@ struct b53_chip_data {
const char *dev_name;
u16 vlans;
u16 enabled_ports;
+ u8 imp_port;
u8 cpu_port;
u8 vta_regs[3];
u8 arl_bins;
@@ -2304,6 +2305,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1f,
.arl_bins = 2,
.arl_buckets = 1024,
+ .imp_port = 5,
.cpu_port = B53_CPU_PORT_25,
.duplex_reg = B53_DUPLEX_STAT_FE,
},
@@ -2314,6 +2316,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1f,
.arl_bins = 2,
.arl_buckets = 1024,
+ .imp_port = 5,
.cpu_port = B53_CPU_PORT_25,
.duplex_reg = B53_DUPLEX_STAT_FE,
},
@@ -2324,6 +2327,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1f,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2337,6 +2341,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1f,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2350,6 +2355,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1f,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS_9798,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2363,6 +2369,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x7f,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS_9798,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2377,6 +2384,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.arl_bins = 4,
.arl_buckets = 1024,
.vta_regs = B53_VTA_REGS,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.duplex_reg = B53_DUPLEX_STAT_GE,
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
@@ -2389,6 +2397,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0xff,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2402,6 +2411,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1ff,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2415,6 +2425,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0, /* pdata must provide them */
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS_63XX,
.duplex_reg = B53_DUPLEX_STAT_63XX,
@@ -2428,6 +2439,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1f,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2441,6 +2453,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1bf,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2454,6 +2467,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1bf,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2467,6 +2481,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1f,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2480,6 +2495,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1f,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2493,6 +2509,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1ff,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2506,6 +2523,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x103,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2520,6 +2538,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1bf,
.arl_bins = 4,
.arl_buckets = 256,
+ .imp_port = 8,
.cpu_port = 8, /* TODO: ports 4, 5, 8 */
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2533,6 +2552,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1ff,
.arl_bins = 4,
.arl_buckets = 1024,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2546,6 +2566,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
.enabled_ports = 0x1ff,
.arl_bins = 4,
.arl_buckets = 256,
+ .imp_port = 8,
.cpu_port = B53_CPU_PORT,
.vta_regs = B53_VTA_REGS,
.duplex_reg = B53_DUPLEX_STAT_GE,
@@ -2571,6 +2592,7 @@ static int b53_switch_init(struct b53_device *dev)
dev->vta_regs[1] = chip->vta_regs[1];
dev->vta_regs[2] = chip->vta_regs[2];
dev->jumbo_pm_reg = chip->jumbo_pm_reg;
+ dev->imp_port = chip->imp_port;
dev->cpu_port = chip->cpu_port;
dev->num_vlans = chip->vlans;
dev->num_arl_bins = chip->arl_bins;
@@ -2612,9 +2634,10 @@ static int b53_switch_init(struct b53_device *dev)
dev->cpu_port = 5;
}
- /* cpu port is always last */
- dev->num_ports = dev->cpu_port + 1;
dev->enabled_ports |= BIT(dev->cpu_port);
+ dev->num_ports = fls(dev->enabled_ports);
+
+ dev->ds->num_ports = min_t(unsigned int, dev->num_ports, DSA_MAX_PORTS);
/* Include non standard CPU port built-in PHYs to be probed */
if (is539x(dev) || is531x5(dev)) {
@@ -2660,7 +2683,6 @@ struct b53_device *b53_switch_alloc(struct device *base,
return NULL;
ds->dev = base;
- ds->num_ports = DSA_MAX_PORTS;
dev = devm_kzalloc(base, sizeof(*dev), GFP_KERNEL);
if (!dev)
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 9bf8319342b0..5d068acf7cf8 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -123,6 +123,7 @@ struct b53_device {
/* used ports mask */
u16 enabled_ports;
+ unsigned int imp_port;
unsigned int cpu_port;
/* connect specific data */
diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
index e78026ef6d8c..267324889dd6 100644
--- a/drivers/net/dsa/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq_gswip.c
@@ -843,7 +843,8 @@ static int gswip_setup(struct dsa_switch *ds)
gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
GSWIP_MAC_CTRL_2p(cpu_port));
- gswip_switch_w(priv, VLAN_ETH_FRAME_LEN + 8, GSWIP_MAC_FLEN);
+ gswip_switch_w(priv, VLAN_ETH_FRAME_LEN + 8 + ETH_FCS_LEN,
+ GSWIP_MAC_FLEN);
gswip_switch_mask(priv, 0, GSWIP_BM_QUEUE_GCTRL_GL_MOD,
GSWIP_BM_QUEUE_GCTRL);
@@ -1884,6 +1885,12 @@ static int gswip_gphy_fw_load(struct gswip_priv *priv, struct gswip_gphy_fw *gph
reset_control_assert(gphy_fw->reset);
+ /* The vendor BSP uses a 200ms delay after asserting the reset line.
+ * Without this some users are observing that the PHY is not coming up
+ * on the MDIO bus.
+ */
+ msleep(200);
+
ret = request_firmware(&fw, gphy_fw->fw_name, dev);
if (ret) {
dev_err(dev, "failed to load firmware: %s, error: %i\n",
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 1f63f50f73f1..bda5a9bf4f52 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -643,10 +643,8 @@ qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask)
}
static int
-qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data)
+qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data)
{
- struct qca8k_priv *priv = salve_bus->priv;
- struct mii_bus *bus = priv->bus;
u16 r1, r2, page;
u32 val;
int ret;
@@ -682,10 +680,8 @@ exit:
}
static int
-qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum)
+qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum)
{
- struct qca8k_priv *priv = salve_bus->priv;
- struct mii_bus *bus = priv->bus;
u16 r1, r2, page;
u32 val;
int ret;
@@ -727,6 +723,24 @@ exit:
}
static int
+qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 data)
+{
+ struct qca8k_priv *priv = slave_bus->priv;
+ struct mii_bus *bus = priv->bus;
+
+ return qca8k_mdio_write(bus, phy, regnum, data);
+}
+
+static int
+qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum)
+{
+ struct qca8k_priv *priv = slave_bus->priv;
+ struct mii_bus *bus = priv->bus;
+
+ return qca8k_mdio_read(bus, phy, regnum);
+}
+
+static int
qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data)
{
struct qca8k_priv *priv = ds->priv;
@@ -775,8 +789,8 @@ qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio)
bus->priv = (void *)priv;
bus->name = "qca8k slave mii";
- bus->read = qca8k_mdio_read;
- bus->write = qca8k_mdio_write;
+ bus->read = qca8k_internal_mdio_read;
+ bus->write = qca8k_internal_mdio_write;
snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d",
ds->index);
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 17c16333a412..7b0ae9efc004 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -2786,7 +2786,7 @@ static void
dump_tx_ring(struct net_device *dev)
{
if (vortex_debug > 0) {
- struct vortex_private *vp = netdev_priv(dev);
+ struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
if (vp->full_bus_master_tx) {
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index 9aac7119d382..91b04abfd687 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -428,13 +428,12 @@ out:
return err;
}
-static int mac8390_device_remove(struct nubus_board *board)
+static void mac8390_device_remove(struct nubus_board *board)
{
struct net_device *dev = nubus_get_drvdata(board);
unregister_netdev(dev);
free_netdev(dev);
- return 0;
}
static struct nubus_driver mac8390_driver = {
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
index 53660bc8d6ff..9afc712f5948 100644
--- a/drivers/net/ethernet/8390/ne.c
+++ b/drivers/net/ethernet/8390/ne.c
@@ -922,13 +922,16 @@ static void __init ne_add_devices(void)
}
}
-#ifdef MODULE
static int __init ne_init(void)
{
int retval;
- ne_add_devices();
+
+ if (IS_MODULE(CONFIG_NE2000))
+ ne_add_devices();
+
retval = platform_driver_probe(&ne_driver, ne_drv_probe);
- if (retval) {
+
+ if (IS_MODULE(CONFIG_NE2000) && retval) {
if (io[0] == 0)
pr_notice("ne.c: You must supply \"io=0xNNN\""
" value(s) for ISA cards.\n");
@@ -941,18 +944,8 @@ static int __init ne_init(void)
return retval;
}
module_init(ne_init);
-#else /* MODULE */
-static int __init ne_init(void)
-{
- int retval = platform_driver_probe(&ne_driver, ne_drv_probe);
-
- /* Unregister unused platform_devices. */
- ne_loop_rm_unreg(0);
- return retval;
-}
-module_init(ne_init);
-#ifdef CONFIG_NETDEV_LEGACY_INIT
+#if !defined(MODULE) && defined(CONFIG_NETDEV_LEGACY_INIT)
struct net_device * __init ne_probe(int unit)
{
int this_dev;
@@ -994,7 +987,6 @@ struct net_device * __init ne_probe(int unit)
return ERR_PTR(-ENODEV);
}
#endif
-#endif /* MODULE */
static void __exit ne_exit(void)
{
diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c
index b5df7ad5a83f..032e8922b482 100644
--- a/drivers/net/ethernet/amd/ni65.c
+++ b/drivers/net/ethernet/amd/ni65.c
@@ -748,7 +748,7 @@ static void ni65_stop_start(struct net_device *dev,struct priv *p)
#ifdef XMT_VIA_SKB
skb_save[i] = p->tmd_skb[i];
#endif
- buffer[i] = (u32) isa_bus_to_virt(tmdp->u.buffer);
+ buffer[i] = (unsigned long)isa_bus_to_virt(tmdp->u.buffer);
blen[i] = tmdp->blen;
tmdp->u.s.status = 0x0;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 627f85ee3922..f32431a7e5a6 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -305,13 +305,15 @@ static bool bnxt_vf_pciid(enum board_idx idx)
writel(DB_CP_FLAGS | RING_CMP(idx), (db)->doorbell)
#define BNXT_DB_NQ_P5(db, idx) \
- writeq((db)->db_key64 | DBR_TYPE_NQ | RING_CMP(idx), (db)->doorbell)
+ bnxt_writeq(bp, (db)->db_key64 | DBR_TYPE_NQ | RING_CMP(idx), \
+ (db)->doorbell)
#define BNXT_DB_CQ_ARM(db, idx) \
writel(DB_CP_REARM_FLAGS | RING_CMP(idx), (db)->doorbell)
#define BNXT_DB_NQ_ARM_P5(db, idx) \
- writeq((db)->db_key64 | DBR_TYPE_NQ_ARM | RING_CMP(idx), (db)->doorbell)
+ bnxt_writeq(bp, (db)->db_key64 | DBR_TYPE_NQ_ARM | RING_CMP(idx),\
+ (db)->doorbell)
static void bnxt_db_nq(struct bnxt *bp, struct bnxt_db_info *db, u32 idx)
{
@@ -332,8 +334,8 @@ static void bnxt_db_nq_arm(struct bnxt *bp, struct bnxt_db_info *db, u32 idx)
static void bnxt_db_cq(struct bnxt *bp, struct bnxt_db_info *db, u32 idx)
{
if (bp->flags & BNXT_FLAG_CHIP_P5)
- writeq(db->db_key64 | DBR_TYPE_CQ_ARMALL | RING_CMP(idx),
- db->doorbell);
+ bnxt_writeq(bp, db->db_key64 | DBR_TYPE_CQ_ARMALL |
+ RING_CMP(idx), db->doorbell);
else
BNXT_DB_CQ(db, idx);
}
@@ -2200,25 +2202,33 @@ static int bnxt_async_event_process(struct bnxt *bp,
if (!fw_health)
goto async_event_process_exit;
- fw_health->enabled = EVENT_DATA1_RECOVERY_ENABLED(data1);
- fw_health->master = EVENT_DATA1_RECOVERY_MASTER_FUNC(data1);
- if (!fw_health->enabled) {
+ if (!EVENT_DATA1_RECOVERY_ENABLED(data1)) {
+ fw_health->enabled = false;
netif_info(bp, drv, bp->dev,
"Error recovery info: error recovery[0]\n");
break;
}
+ fw_health->master = EVENT_DATA1_RECOVERY_MASTER_FUNC(data1);
fw_health->tmr_multiplier =
DIV_ROUND_UP(fw_health->polling_dsecs * HZ,
bp->current_interval * 10);
fw_health->tmr_counter = fw_health->tmr_multiplier;
- fw_health->last_fw_heartbeat =
- bnxt_fw_health_readl(bp, BNXT_FW_HEARTBEAT_REG);
+ if (!fw_health->enabled)
+ fw_health->last_fw_heartbeat =
+ bnxt_fw_health_readl(bp, BNXT_FW_HEARTBEAT_REG);
fw_health->last_fw_reset_cnt =
bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG);
netif_info(bp, drv, bp->dev,
"Error recovery info: error recovery[1], master[%d], reset count[%u], health status: 0x%x\n",
fw_health->master, fw_health->last_fw_reset_cnt,
bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG));
+ if (!fw_health->enabled) {
+ /* Make sure tmr_counter is set and visible to
+ * bnxt_health_check() before setting enabled to true.
+ */
+ smp_wmb();
+ fw_health->enabled = true;
+ }
goto async_event_process_exit;
}
case ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION:
@@ -2638,8 +2648,8 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
if (cpr2 && cpr2->had_work_done) {
db = &cpr2->cp_db;
- writeq(db->db_key64 | dbr_type |
- RING_CMP(cpr2->cp_raw_cons), db->doorbell);
+ bnxt_writeq(bp, db->db_key64 | dbr_type |
+ RING_CMP(cpr2->cp_raw_cons), db->doorbell);
cpr2->had_work_done = 0;
}
}
@@ -2719,6 +2729,9 @@ static void bnxt_free_tx_skbs(struct bnxt *bp)
struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
int j;
+ if (!txr->tx_buf_ring)
+ continue;
+
for (j = 0; j < max_idx;) {
struct bnxt_sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
struct sk_buff *skb;
@@ -2803,6 +2816,9 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
}
skip_rx_tpa_free:
+ if (!rxr->rx_buf_ring)
+ goto skip_rx_buf_free;
+
for (i = 0; i < max_idx; i++) {
struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[i];
dma_addr_t mapping = rx_buf->mapping;
@@ -2825,6 +2841,11 @@ skip_rx_tpa_free:
kfree(data);
}
}
+
+skip_rx_buf_free:
+ if (!rxr->rx_agg_ring)
+ goto skip_rx_agg_free;
+
for (i = 0; i < max_agg_idx; i++) {
struct bnxt_sw_rx_agg_bd *rx_agg_buf = &rxr->rx_agg_ring[i];
struct page *page = rx_agg_buf->page;
@@ -2841,6 +2862,8 @@ skip_rx_tpa_free:
__free_page(page);
}
+
+skip_rx_agg_free:
if (rxr->rx_page) {
__free_page(rxr->rx_page);
rxr->rx_page = NULL;
@@ -2889,6 +2912,9 @@ static void bnxt_free_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem)
struct pci_dev *pdev = bp->pdev;
int i;
+ if (!rmem->pg_arr)
+ goto skip_pages;
+
for (i = 0; i < rmem->nr_pages; i++) {
if (!rmem->pg_arr[i])
continue;
@@ -2898,6 +2924,7 @@ static void bnxt_free_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem)
rmem->pg_arr[i] = NULL;
}
+skip_pages:
if (rmem->pg_tbl) {
size_t pg_tbl_size = rmem->nr_pages * 8;
@@ -3217,10 +3244,14 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
static void bnxt_free_cp_arrays(struct bnxt_cp_ring_info *cpr)
{
+ struct bnxt_ring_struct *ring = &cpr->cp_ring_struct;
+
kfree(cpr->cp_desc_ring);
cpr->cp_desc_ring = NULL;
+ ring->ring_mem.pg_arr = NULL;
kfree(cpr->cp_desc_mapping);
cpr->cp_desc_mapping = NULL;
+ ring->ring_mem.dma_arr = NULL;
}
static int bnxt_alloc_cp_arrays(struct bnxt_cp_ring_info *cpr, int n)
@@ -4639,6 +4670,13 @@ static int bnxt_hwrm_tunnel_dst_port_free(struct bnxt *bp, u8 tunnel_type)
struct hwrm_tunnel_dst_port_free_input *req;
int rc;
+ if (tunnel_type == TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN &&
+ bp->vxlan_fw_dst_port_id == INVALID_HW_RING_ID)
+ return 0;
+ if (tunnel_type == TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE &&
+ bp->nge_fw_dst_port_id == INVALID_HW_RING_ID)
+ return 0;
+
rc = hwrm_req_init(bp, req, HWRM_TUNNEL_DST_PORT_FREE);
if (rc)
return rc;
@@ -4648,10 +4686,12 @@ static int bnxt_hwrm_tunnel_dst_port_free(struct bnxt *bp, u8 tunnel_type)
switch (tunnel_type) {
case TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN:
req->tunnel_dst_port_id = cpu_to_le16(bp->vxlan_fw_dst_port_id);
+ bp->vxlan_port = 0;
bp->vxlan_fw_dst_port_id = INVALID_HW_RING_ID;
break;
case TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE:
req->tunnel_dst_port_id = cpu_to_le16(bp->nge_fw_dst_port_id);
+ bp->nge_port = 0;
bp->nge_fw_dst_port_id = INVALID_HW_RING_ID;
break;
default:
@@ -4689,10 +4729,12 @@ static int bnxt_hwrm_tunnel_dst_port_alloc(struct bnxt *bp, __be16 port,
switch (tunnel_type) {
case TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_VXLAN:
+ bp->vxlan_port = port;
bp->vxlan_fw_dst_port_id =
le16_to_cpu(resp->tunnel_dst_port_id);
break;
case TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_GENEVE:
+ bp->nge_port = port;
bp->nge_fw_dst_port_id = le16_to_cpu(resp->tunnel_dst_port_id);
break;
default:
@@ -8221,12 +8263,10 @@ static int bnxt_hwrm_port_qstats_ext(struct bnxt *bp, u8 flags)
static void bnxt_hwrm_free_tunnel_ports(struct bnxt *bp)
{
- if (bp->vxlan_fw_dst_port_id != INVALID_HW_RING_ID)
- bnxt_hwrm_tunnel_dst_port_free(
- bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
- if (bp->nge_fw_dst_port_id != INVALID_HW_RING_ID)
- bnxt_hwrm_tunnel_dst_port_free(
- bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE);
+ bnxt_hwrm_tunnel_dst_port_free(bp,
+ TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
+ bnxt_hwrm_tunnel_dst_port_free(bp,
+ TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE);
}
static int bnxt_set_tpa(struct bnxt *bp, bool set_tpa)
@@ -11247,6 +11287,8 @@ static void bnxt_fw_health_check(struct bnxt *bp)
if (!fw_health->enabled || test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
return;
+ /* Make sure it is enabled before checking the tmr_counter. */
+ smp_rmb();
if (fw_health->tmr_counter) {
fw_health->tmr_counter--;
return;
@@ -12185,6 +12227,11 @@ static void bnxt_fw_reset_task(struct work_struct *work)
return;
}
+ if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) &&
+ bp->fw_health->enabled) {
+ bp->fw_health->last_fw_reset_cnt =
+ bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG);
+ }
bp->fw_reset_state = 0;
/* Make sure fw_reset_state is 0 before clearing the flag */
smp_mb__before_atomic();
@@ -12625,13 +12672,10 @@ static int bnxt_udp_tunnel_sync(struct net_device *netdev, unsigned int table)
unsigned int cmd;
udp_tunnel_nic_get_port(netdev, table, 0, &ti);
- if (ti.type == UDP_TUNNEL_TYPE_VXLAN) {
- bp->vxlan_port = ti.port;
+ if (ti.type == UDP_TUNNEL_TYPE_VXLAN)
cmd = TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN;
- } else {
- bp->nge_port = ti.port;
+ else
cmd = TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE;
- }
if (ti.port)
return bnxt_hwrm_tunnel_dst_port_alloc(bp, ti.port, cmd);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index a8212dcdad5f..ec046e7a2484 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -28,6 +28,7 @@
#include <net/dst_metadata.h>
#include <net/xdp.h>
#include <linux/dim.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#ifdef CONFIG_TEE_BNXT_FW
#include <linux/firmware/broadcom/tee_bnxt_fw.h>
#endif
@@ -1981,7 +1982,7 @@ struct bnxt {
struct mutex sriov_lock;
#endif
-#ifndef writeq
+#if BITS_PER_LONG == 32
/* ensure atomic 64-bit doorbell writes on 32-bit systems. */
spinlock_t db_lock;
#endif
@@ -2110,24 +2111,36 @@ static inline u32 bnxt_tx_avail(struct bnxt *bp, struct bnxt_tx_ring_info *txr)
((txr->tx_prod - txr->tx_cons) & bp->tx_ring_mask);
}
-#ifndef writeq
-#define writeq(val64, db) \
-do { \
- spin_lock(&bp->db_lock); \
- writel((val64) & 0xffffffff, db); \
- writel((val64) >> 32, (db) + 4); \
- spin_unlock(&bp->db_lock); \
-} while (0)
+static inline void bnxt_writeq(struct bnxt *bp, u64 val,
+ volatile void __iomem *addr)
+{
+#if BITS_PER_LONG == 32
+ spin_lock(&bp->db_lock);
+ lo_hi_writeq(val, addr);
+ spin_unlock(&bp->db_lock);
+#else
+ writeq(val, addr);
+#endif
+}
-#define writeq_relaxed writeq
+static inline void bnxt_writeq_relaxed(struct bnxt *bp, u64 val,
+ volatile void __iomem *addr)
+{
+#if BITS_PER_LONG == 32
+ spin_lock(&bp->db_lock);
+ lo_hi_writeq_relaxed(val, addr);
+ spin_unlock(&bp->db_lock);
+#else
+ writeq_relaxed(val, addr);
#endif
+}
/* For TX and RX ring doorbells with no ordering guarantee*/
static inline void bnxt_db_write_relaxed(struct bnxt *bp,
struct bnxt_db_info *db, u32 idx)
{
if (bp->flags & BNXT_FLAG_CHIP_P5) {
- writeq_relaxed(db->db_key64 | idx, db->doorbell);
+ bnxt_writeq_relaxed(bp, db->db_key64 | idx, db->doorbell);
} else {
u32 db_val = db->db_key32 | idx;
@@ -2142,7 +2155,7 @@ static inline void bnxt_db_write(struct bnxt *bp, struct bnxt_db_info *db,
u32 idx)
{
if (bp->flags & BNXT_FLAG_CHIP_P5) {
- writeq(db->db_key64 | idx, db->doorbell);
+ bnxt_writeq(bp, db->db_key64 | idx, db->doorbell);
} else {
u32 db_val = db->db_key32 | idx;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index 1423cc617d93..9576547df4ab 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -352,13 +352,16 @@ static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
dst->vu8 = (u8)val32;
}
-static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp,
- union devlink_param_value *nvm_cfg_ver)
+static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp, u32 *nvm_cfg_ver)
{
struct hwrm_nvm_get_variable_input *req;
+ u16 bytes = BNXT_NVM_CFG_VER_BYTES;
+ u16 bits = BNXT_NVM_CFG_VER_BITS;
+ union devlink_param_value ver;
union bnxt_nvm_data *data;
dma_addr_t data_dma_addr;
- int rc;
+ int rc, i = 2;
+ u16 dim = 1;
rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE);
if (rc)
@@ -370,16 +373,34 @@ static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp,
goto exit;
}
+ /* earlier devices present as an array of raw bytes */
+ if (!BNXT_CHIP_P5(bp)) {
+ dim = 0;
+ i = 0;
+ bits *= 3; /* array of 3 version components */
+ bytes *= 4; /* copy whole word */
+ }
+
hwrm_req_hold(bp, req);
req->dest_data_addr = cpu_to_le64(data_dma_addr);
- req->data_len = cpu_to_le16(BNXT_NVM_CFG_VER_BITS);
+ req->data_len = cpu_to_le16(bits);
req->option_num = cpu_to_le16(NVM_OFF_NVM_CFG_VER);
+ req->dimensions = cpu_to_le16(dim);
- rc = hwrm_req_send_silent(bp, req);
- if (!rc)
- bnxt_copy_from_nvm_data(nvm_cfg_ver, data,
- BNXT_NVM_CFG_VER_BITS,
- BNXT_NVM_CFG_VER_BYTES);
+ while (i >= 0) {
+ req->index_0 = cpu_to_le16(i--);
+ rc = hwrm_req_send_silent(bp, req);
+ if (rc)
+ goto exit;
+ bnxt_copy_from_nvm_data(&ver, data, bits, bytes);
+
+ if (BNXT_CHIP_P5(bp)) {
+ *nvm_cfg_ver <<= 8;
+ *nvm_cfg_ver |= ver.vu8;
+ } else {
+ *nvm_cfg_ver = ver.vu32;
+ }
+ }
exit:
hwrm_req_drop(bp, req);
@@ -416,12 +437,12 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
{
struct hwrm_nvm_get_dev_info_output nvm_dev_info;
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
- union devlink_param_value nvm_cfg_ver;
struct hwrm_ver_get_output *ver_resp;
char mgmt_ver[FW_VER_STR_LEN];
char roce_ver[FW_VER_STR_LEN];
char ncsi_ver[FW_VER_STR_LEN];
char buf[32];
+ u32 ver = 0;
int rc;
rc = devlink_info_driver_name_put(req, DRV_MODULE_NAME);
@@ -456,7 +477,7 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
return rc;
ver_resp = &bp->ver_resp;
- sprintf(buf, "%X", ver_resp->chip_rev);
+ sprintf(buf, "%c%d", 'A' + ver_resp->chip_rev, ver_resp->chip_metal);
rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
if (rc)
@@ -475,11 +496,9 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
if (rc)
return rc;
- if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) {
- u32 ver = nvm_cfg_ver.vu32;
-
- sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xf, (ver >> 8) & 0xf,
- ver & 0xf);
+ if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &ver)) {
+ sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xff, (ver >> 8) & 0xff,
+ ver & 0xff);
rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
buf);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
index d22cab5d6856..d889f240da2b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
@@ -40,8 +40,8 @@ static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl)
#define NVM_OFF_ENABLE_SRIOV 401
#define NVM_OFF_NVM_CFG_VER 602
-#define BNXT_NVM_CFG_VER_BITS 24
-#define BNXT_NVM_CFG_VER_BYTES 4
+#define BNXT_NVM_CFG_VER_BITS 8
+#define BNXT_NVM_CFG_VER_BYTES 1
#define BNXT_MSIX_VEC_MAX 512
#define BNXT_MSIX_VEC_MIN_MAX 128
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
index acef61abe35d..bb7327b82d0b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
@@ -145,11 +145,11 @@ void hwrm_req_timeout(struct bnxt *bp, void *req, unsigned int timeout)
* @bp: The driver context.
* @req: The request for which calls to hwrm_req_dma_slice() will have altered
* allocation flags.
- * @flags: A bitmask of GFP flags. These flags are passed to
- * dma_alloc_coherent() whenever it is used to allocate backing memory
- * for slices. Note that calls to hwrm_req_dma_slice() will not always
- * result in new allocations, however, memory suballocated from the
- * request buffer is already __GFP_ZERO.
+ * @gfp: A bitmask of GFP flags. These flags are passed to dma_alloc_coherent()
+ * whenever it is used to allocate backing memory for slices. Note that
+ * calls to hwrm_req_dma_slice() will not always result in new allocations,
+ * however, memory suballocated from the request buffer is already
+ * __GFP_ZERO.
*
* Sets the GFP allocation flags associated with the request for subsequent
* calls to hwrm_req_dma_slice(). This can be useful for specifying __GFP_ZERO
@@ -698,8 +698,8 @@ int hwrm_req_send_silent(struct bnxt *bp, void *req)
* @bp: The driver context.
* @req: The request for which indirect data will be associated.
* @size: The size of the allocation.
- * @dma: The bus address associated with the allocation. The HWRM API has no
- * knowledge about the type of the request and so cannot infer how the
+ * @dma_handle: The bus address associated with the allocation. The HWRM API has
+ * no knowledge about the type of the request and so cannot infer how the
* caller intends to use the indirect data. Thus, the caller is
* responsible for configuring the request object appropriately to
* point to the associated indirect memory. Note, DMA handle has the
diff --git a/drivers/net/ethernet/cadence/macb_pci.c b/drivers/net/ethernet/cadence/macb_pci.c
index 8b7b59908a1a..f66d22de5168 100644
--- a/drivers/net/ethernet/cadence/macb_pci.c
+++ b/drivers/net/ethernet/cadence/macb_pci.c
@@ -111,9 +111,9 @@ static void macb_remove(struct pci_dev *pdev)
struct platform_device *plat_dev = pci_get_drvdata(pdev);
struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev);
- platform_device_unregister(plat_dev);
clk_unregister(plat_data->pclk);
clk_unregister(plat_data->hclk);
+ platform_device_unregister(plat_dev);
}
static const struct pci_device_id dev_id_table[] = {
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 73c016166f06..d246eee4b6d5 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -1111,6 +1111,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!adapter->registered_device_map) {
pr_err("%s: could not register any net devices\n",
pci_name(pdev));
+ err = -EINVAL;
goto out_release_adapter_res;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index e21a2e691382..c3afec1041f8 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -3301,6 +3301,9 @@ void t3_sge_stop(struct adapter *adap)
t3_sge_stop_dma(adap);
+ /* workqueues aren't initialized otherwise */
+ if (!(adap->flags & FULL_INIT_DONE))
+ return;
for (i = 0; i < SGE_QSETS; ++i) {
struct sge_qset *qs = &adap->sge.qs[i];
diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig
index dac1764ba740..5bdf731d9503 100644
--- a/drivers/net/ethernet/cirrus/Kconfig
+++ b/drivers/net/ethernet/cirrus/Kconfig
@@ -38,7 +38,7 @@ config CS89x0_ISA
config CS89x0_PLATFORM
tristate "CS89x0 platform driver support"
- depends on ARM || COMPILE_TEST
+ depends on ARM || (COMPILE_TEST && !PPC)
select CS89x0
help
Say Y to compile the cs89x0 platform driver. This makes this driver
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 22af3d6ce178..adc54a726661 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -61,6 +61,9 @@ static unsigned int tx_sgl = 1;
module_param(tx_sgl, uint, 0600);
MODULE_PARM_DESC(tx_sgl, "Minimum number of frags when using dma_map_sg() to optimize the IOMMU mapping");
+static bool page_pool_enabled = true;
+module_param(page_pool_enabled, bool, 0400);
+
#define HNS3_SGL_SIZE(nfrag) (sizeof(struct scatterlist) * (nfrag) + \
sizeof(struct sg_table))
#define HNS3_MAX_SGL_SIZE ALIGN(HNS3_SGL_SIZE(HNS3_MAX_TSO_BD_NUM), \
@@ -73,6 +76,7 @@ MODULE_PARM_DESC(tx_sgl, "Minimum number of frags when using dma_map_sg() to opt
#define HNS3_OUTER_VLAN_TAG 2
#define HNS3_MIN_TX_LEN 33U
+#define HNS3_MIN_TUN_PKT_LEN 65U
/* hns3_pci_tbl - PCI Device ID Table
*
@@ -1424,8 +1428,11 @@ static int hns3_set_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
l4.tcp->doff);
break;
case IPPROTO_UDP:
- if (hns3_tunnel_csum_bug(skb))
- return skb_checksum_help(skb);
+ if (hns3_tunnel_csum_bug(skb)) {
+ int ret = skb_put_padto(skb, HNS3_MIN_TUN_PKT_LEN);
+
+ return ret ? ret : skb_checksum_help(skb);
+ }
hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
@@ -4753,7 +4760,8 @@ static int hns3_alloc_ring_memory(struct hns3_enet_ring *ring)
goto out_with_desc_cb;
if (!HNAE3_IS_TX_RING(ring)) {
- hns3_alloc_page_pool(ring);
+ if (page_pool_enabled)
+ hns3_alloc_page_pool(ring);
ret = hns3_alloc_ring_buffers(ring);
if (ret)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
index 474c6d1664e7..ac9b69513332 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -362,7 +362,7 @@ static void hclge_set_default_capability(struct hclge_dev *hdev)
}
}
-const struct hclge_caps_bit_map hclge_cmd_caps_bit_map0[] = {
+static const struct hclge_caps_bit_map hclge_cmd_caps_bit_map0[] = {
{HCLGE_CAP_UDP_GSO_B, HNAE3_DEV_SUPPORT_UDP_GSO_B},
{HCLGE_CAP_PTP_B, HNAE3_DEV_SUPPORT_PTP_B},
{HCLGE_CAP_INT_QL_B, HNAE3_DEV_SUPPORT_INT_QL_B},
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 68ed1715ac52..87d96f82c318 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -1724,6 +1724,10 @@ hclge_dbg_get_imp_stats_info(struct hclge_dev *hdev, char *buf, int len)
}
bd_num = le32_to_cpu(req->bd_num);
+ if (!bd_num) {
+ dev_err(&hdev->pdev->dev, "imp statistics bd number is 0!\n");
+ return -EINVAL;
+ }
desc_src = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL);
if (!desc_src)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index e55ba2e511b1..f1e46ba799f9 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1528,9 +1528,10 @@ static void hclge_init_kdump_kernel_config(struct hclge_dev *hdev)
static int hclge_configure(struct hclge_dev *hdev)
{
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
+ const struct cpumask *cpumask = cpu_online_mask;
struct hclge_cfg cfg;
unsigned int i;
- int ret;
+ int node, ret;
ret = hclge_get_cfg(hdev, &cfg);
if (ret)
@@ -1595,11 +1596,12 @@ static int hclge_configure(struct hclge_dev *hdev)
hclge_init_kdump_kernel_config(hdev);
- /* Set the init affinity based on pci func number */
- i = cpumask_weight(cpumask_of_node(dev_to_node(&hdev->pdev->dev)));
- i = i ? PCI_FUNC(hdev->pdev->devfn) % i : 0;
- cpumask_set_cpu(cpumask_local_spread(i, dev_to_node(&hdev->pdev->dev)),
- &hdev->affinity_mask);
+ /* Set the affinity based on numa node */
+ node = dev_to_node(&hdev->pdev->dev);
+ if (node != NUMA_NO_NODE)
+ cpumask = cpumask_of_node(node);
+
+ cpumask_copy(&hdev->affinity_mask, cpumask);
return ret;
}
@@ -8125,11 +8127,12 @@ static void hclge_ae_stop(struct hnae3_handle *handle)
hclge_clear_arfs_rules(hdev);
spin_unlock_bh(&hdev->fd_rule_lock);
- /* If it is not PF reset, the firmware will disable the MAC,
+ /* If it is not PF reset or FLR, the firmware will disable the MAC,
* so it only need to stop phy here.
*/
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) &&
- hdev->reset_type != HNAE3_FUNC_RESET) {
+ hdev->reset_type != HNAE3_FUNC_RESET &&
+ hdev->reset_type != HNAE3_FLR_RESET) {
hclge_mac_stop_phy(hdev);
hclge_update_link_status(hdev);
return;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
index 59772b0e9531..f89bfb352adf 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
@@ -342,7 +342,7 @@ static void hclgevf_set_default_capability(struct hclgevf_dev *hdev)
set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps);
}
-const struct hclgevf_caps_bit_map hclgevf_cmd_caps_bit_map0[] = {
+static const struct hclgevf_caps_bit_map hclgevf_cmd_caps_bit_map0[] = {
{HCLGEVF_CAP_UDP_GSO_B, HNAE3_DEV_SUPPORT_UDP_GSO_B},
{HCLGEVF_CAP_INT_QL_B, HNAE3_DEV_SUPPORT_INT_QL_B},
{HCLGEVF_CAP_TQP_TXRX_INDEP_B, HNAE3_DEV_SUPPORT_TQP_TXRX_INDEP_B},
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index 82e727020120..a69e892277b3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -2465,6 +2465,8 @@ static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
hclgevf_enable_vector(&hdev->misc_vector, false);
event_cause = hclgevf_check_evt_cause(hdev, &clearval);
+ if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER)
+ hclgevf_clear_event_cause(hdev, clearval);
switch (event_cause) {
case HCLGEVF_VECTOR0_EVENT_RST:
@@ -2477,10 +2479,8 @@ static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
break;
}
- if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER) {
- hclgevf_clear_event_cause(hdev, clearval);
+ if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER)
hclgevf_enable_vector(&hdev->misc_vector, true);
- }
return IRQ_HANDLED;
}
diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c
index 96c6f4f36904..48e001881c75 100644
--- a/drivers/net/ethernet/i825xx/lasi_82596.c
+++ b/drivers/net/ethernet/i825xx/lasi_82596.c
@@ -196,7 +196,7 @@ out_free_netdev:
return retval;
}
-static int __exit lan_remove_chip(struct parisc_device *pdev)
+static void __exit lan_remove_chip(struct parisc_device *pdev)
{
struct net_device *dev = parisc_get_drvdata(pdev);
struct i596_private *lp = netdev_priv(dev);
@@ -205,7 +205,6 @@ static int __exit lan_remove_chip(struct parisc_device *pdev)
dma_free_noncoherent(&pdev->dev, sizeof(struct i596_private), lp->dma,
lp->dma_addr, DMA_BIDIRECTIONAL);
free_netdev (dev);
- return 0;
}
static const struct parisc_device_id lan_tbl[] __initconst = {
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c
index 893e0ddcb611..0696f723228a 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.c
+++ b/drivers/net/ethernet/i825xx/sun3_82586.c
@@ -314,7 +314,7 @@ static int __init sun3_82586_probe(void)
err = register_netdev(dev);
if (err)
goto out2;
- return dev;
+ return 0;
out2:
release_region(ioaddr, SUN3_82586_TOTAL_SIZE);
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index a775c69e4fd7..a4579b340120 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4700,6 +4700,22 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
return 0;
}
+ if (adapter->failover_pending) {
+ adapter->init_done_rc = -EAGAIN;
+ netdev_dbg(netdev, "Failover pending, ignoring login response\n");
+ complete(&adapter->init_done);
+ /* login response buffer will be released on reset */
+ return 0;
+ }
+
+ if (adapter->failover_pending) {
+ adapter->init_done_rc = -EAGAIN;
+ netdev_dbg(netdev, "Failover pending, ignoring login response\n");
+ complete(&adapter->init_done);
+ /* login response buffer will be released on reset */
+ return 0;
+ }
+
netdev->mtu = adapter->req_mtu - ETH_HLEN;
netdev_dbg(adapter->netdev, "Login Response Buffer:\n");
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index eadcb9958346..3c4f08d20414 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -695,6 +695,7 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf)
{
if (pf->hw.func_caps.common_cap.rdma && pf->num_rdma_msix) {
set_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+ set_bit(ICE_FLAG_AUX_ENA, pf->flags);
ice_plug_aux_dev(pf);
}
}
@@ -707,5 +708,6 @@ static inline void ice_clear_rdma_cap(struct ice_pf *pf)
{
ice_unplug_aux_dev(pf);
clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+ clear_bit(ICE_FLAG_AUX_ENA, pf->flags);
}
#endif /* _ICE_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c
index 1f2afdf6cd48..adcc9a251595 100644
--- a/drivers/net/ethernet/intel/ice/ice_idc.c
+++ b/drivers/net/ethernet/intel/ice/ice_idc.c
@@ -271,6 +271,12 @@ int ice_plug_aux_dev(struct ice_pf *pf)
struct auxiliary_device *adev;
int ret;
+ /* if this PF doesn't support a technology that requires auxiliary
+ * devices, then gracefully exit
+ */
+ if (!ice_is_aux_ena(pf))
+ return 0;
+
iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
if (!iadev)
return -ENOMEM;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index 7f3d01059e19..34a089b71e55 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -1487,7 +1487,7 @@ static int cgx_lmac_init(struct cgx *cgx)
MAX_DMAC_ENTRIES_PER_CGX / cgx->lmac_count;
err = rvu_alloc_bitmap(&lmac->mac_to_index_bmap);
if (err)
- return err;
+ goto err_name_free;
/* Reserve first entry for default MAC address */
set_bit(0, lmac->mac_to_index_bmap.bmap);
@@ -1497,7 +1497,7 @@ static int cgx_lmac_init(struct cgx *cgx)
spin_lock_init(&lmac->event_cb_lock);
err = cgx_configure_interrupt(cgx, lmac, lmac->lmac_id, false);
if (err)
- goto err_irq;
+ goto err_bitmap_free;
/* Add reference */
cgx->lmac_idmap[lmac->lmac_id] = lmac;
@@ -1507,7 +1507,9 @@ static int cgx_lmac_init(struct cgx *cgx)
return cgx_lmac_verify_fwi_version(cgx);
-err_irq:
+err_bitmap_free:
+ rvu_free_bitmap(&lmac->mac_to_index_bmap);
+err_name_free:
kfree(lmac->name);
err_lmac_free:
kfree(lmac);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index ce647e037f4d..35836903b7fb 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -92,7 +92,8 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu)
*/
int rvu_poll_reg(struct rvu *rvu, u64 block, u64 offset, u64 mask, bool zero)
{
- unsigned long timeout = jiffies + usecs_to_jiffies(10000);
+ unsigned long timeout = jiffies + usecs_to_jiffies(20000);
+ bool twice = false;
void __iomem *reg;
u64 reg_val;
@@ -107,6 +108,15 @@ again:
usleep_range(1, 5);
goto again;
}
+ /* In scenarios where CPU is scheduled out before checking
+ * 'time_before' (above) and gets scheduled in such that
+ * jiffies are beyond timeout value, then check again if HW is
+ * done with the operation in the meantime.
+ */
+ if (!twice) {
+ twice = true;
+ goto again;
+ }
return -EBUSY;
}
@@ -201,6 +211,11 @@ int rvu_alloc_bitmap(struct rsrc_bmap *rsrc)
return 0;
}
+void rvu_free_bitmap(struct rsrc_bmap *rsrc)
+{
+ kfree(rsrc->bmap);
+}
+
/* Get block LF's HW index from a PF_FUNC's block slot number */
int rvu_get_lf(struct rvu *rvu, struct rvu_block *block, u16 pcifunc, u16 slot)
{
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index d38e5c980c30..1d9411232f1d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -638,6 +638,7 @@ static inline bool is_rvu_fwdata_valid(struct rvu *rvu)
}
int rvu_alloc_bitmap(struct rsrc_bmap *rsrc);
+void rvu_free_bitmap(struct rsrc_bmap *rsrc);
int rvu_alloc_rsrc(struct rsrc_bmap *rsrc);
void rvu_free_rsrc(struct rsrc_bmap *rsrc, int id);
bool is_rsrc_free(struct rsrc_bmap *rsrc, int id);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
index 3cc76f14d2fd..95f21dfdba48 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
@@ -27,7 +27,8 @@ int cn10k_lmtst_init(struct otx2_nic *pfvf)
{
struct lmtst_tbl_setup_req *req;
- int qcount, err;
+ struct otx2_lmt_info *lmt_info;
+ int err, cpu;
if (!test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) {
pfvf->hw_ops = &otx2_hw_ops;
@@ -35,15 +36,9 @@ int cn10k_lmtst_init(struct otx2_nic *pfvf)
}
pfvf->hw_ops = &cn10k_hw_ops;
- qcount = pfvf->hw.max_queues;
- /* LMTST lines allocation
- * qcount = num_online_cpus();
- * NPA = TX + RX + XDP.
- * NIX = TX * 32 (For Burst SQE flush).
- */
- pfvf->tot_lmt_lines = (qcount * 3) + (qcount * 32);
- pfvf->npa_lmt_lines = qcount * 3;
- pfvf->nix_lmt_size = LMT_BURST_SIZE * LMT_LINE_SIZE;
+ /* Total LMTLINES = num_online_cpus() * 32 (For Burst flush).*/
+ pfvf->tot_lmt_lines = (num_online_cpus() * LMT_BURST_SIZE);
+ pfvf->hw.lmt_info = alloc_percpu(struct otx2_lmt_info);
mutex_lock(&pfvf->mbox.lock);
req = otx2_mbox_alloc_msg_lmtst_tbl_setup(&pfvf->mbox);
@@ -66,6 +61,13 @@ int cn10k_lmtst_init(struct otx2_nic *pfvf)
err = otx2_sync_mbox_msg(&pfvf->mbox);
mutex_unlock(&pfvf->mbox.lock);
+ for_each_possible_cpu(cpu) {
+ lmt_info = per_cpu_ptr(pfvf->hw.lmt_info, cpu);
+ lmt_info->lmt_addr = ((u64)pfvf->hw.lmt_base +
+ (cpu * LMT_BURST_SIZE * LMT_LINE_SIZE));
+ lmt_info->lmt_id = cpu * LMT_BURST_SIZE;
+ }
+
return 0;
}
EXPORT_SYMBOL(cn10k_lmtst_init);
@@ -74,13 +76,6 @@ int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
{
struct nix_cn10k_aq_enq_req *aq;
struct otx2_nic *pfvf = dev;
- struct otx2_snd_queue *sq;
-
- sq = &pfvf->qset.sq[qidx];
- sq->lmt_addr = (u64 *)((u64)pfvf->hw.nix_lmt_base +
- (qidx * pfvf->nix_lmt_size));
-
- sq->lmt_id = pfvf->npa_lmt_lines + (qidx * LMT_BURST_SIZE);
/* Get memory to put this msg */
aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
@@ -125,8 +120,7 @@ void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
if (otx2_alloc_buffer(pfvf, cq, &bufptr)) {
if (num_ptrs--)
__cn10k_aura_freeptr(pfvf, cq->cq_idx, ptrs,
- num_ptrs,
- cq->rbpool->lmt_addr);
+ num_ptrs);
break;
}
cq->pool_ptrs--;
@@ -134,8 +128,7 @@ void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
num_ptrs++;
if (num_ptrs == NPA_MAX_BURST || cq->pool_ptrs == 0) {
__cn10k_aura_freeptr(pfvf, cq->cq_idx, ptrs,
- num_ptrs,
- cq->rbpool->lmt_addr);
+ num_ptrs);
num_ptrs = 1;
}
}
@@ -143,20 +136,23 @@ void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx)
{
+ struct otx2_lmt_info *lmt_info;
+ struct otx2_nic *pfvf = dev;
u64 val = 0, tar_addr = 0;
+ lmt_info = per_cpu_ptr(pfvf->hw.lmt_info, smp_processor_id());
/* FIXME: val[0:10] LMT_ID.
* [12:15] no of LMTST - 1 in the burst.
* [19:63] data size of each LMTST in the burst except first.
*/
- val = (sq->lmt_id & 0x7FF);
+ val = (lmt_info->lmt_id & 0x7FF);
/* Target address for LMTST flush tells HW how many 128bit
* words are present.
* tar_addr[6:4] size of first LMTST - 1 in units of 128b.
*/
tar_addr |= sq->io_addr | (((size / 16) - 1) & 0x7) << 4;
dma_wmb();
- memcpy(sq->lmt_addr, sq->sqe_base, size);
+ memcpy((u64 *)lmt_info->lmt_addr, sq->sqe_base, size);
cn10k_lmt_flush(val, tar_addr);
sq->head++;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index ce25c2744435..78df173e6df2 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -1230,11 +1230,6 @@ static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
pool->rbsize = buf_size;
- /* Set LMTST addr for NPA batch free */
- if (test_bit(CN10K_LMTST, &pfvf->hw.cap_flag))
- pool->lmt_addr = (__force u64 *)((u64)pfvf->hw.npa_lmt_base +
- (pool_id * LMT_LINE_SIZE));
-
/* Initialize this pool's context via AF */
aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
if (!aq) {
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 48227cec06ee..a51ecd771d07 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -53,6 +53,10 @@ enum arua_mapped_qtypes {
/* Send skid of 2000 packets required for CQ size of 4K CQEs. */
#define SEND_CQ_SKID 2000
+struct otx2_lmt_info {
+ u64 lmt_addr;
+ u16 lmt_id;
+};
/* RSS configuration */
struct otx2_rss_ctx {
u8 ind_tbl[MAX_RSS_INDIR_TBL_SIZE];
@@ -224,8 +228,7 @@ struct otx2_hw {
#define LMT_LINE_SIZE 128
#define LMT_BURST_SIZE 32 /* 32 LMTST lines for burst SQE flush */
u64 *lmt_base;
- u64 *npa_lmt_base;
- u64 *nix_lmt_base;
+ struct otx2_lmt_info __percpu *lmt_info;
};
enum vfperm {
@@ -407,17 +410,18 @@ static inline bool is_96xx_B0(struct pci_dev *pdev)
*/
#define PCI_REVISION_ID_96XX 0x00
#define PCI_REVISION_ID_95XX 0x10
-#define PCI_REVISION_ID_LOKI 0x20
+#define PCI_REVISION_ID_95XXN 0x20
#define PCI_REVISION_ID_98XX 0x30
#define PCI_REVISION_ID_95XXMM 0x40
+#define PCI_REVISION_ID_95XXO 0xE0
static inline bool is_dev_otx2(struct pci_dev *pdev)
{
u8 midr = pdev->revision & 0xF0;
return (midr == PCI_REVISION_ID_96XX || midr == PCI_REVISION_ID_95XX ||
- midr == PCI_REVISION_ID_LOKI || midr == PCI_REVISION_ID_98XX ||
- midr == PCI_REVISION_ID_95XXMM);
+ midr == PCI_REVISION_ID_95XXN || midr == PCI_REVISION_ID_98XX ||
+ midr == PCI_REVISION_ID_95XXMM || midr == PCI_REVISION_ID_95XXO);
}
static inline void otx2_setup_dev_hw_settings(struct otx2_nic *pfvf)
@@ -562,15 +566,16 @@ static inline u64 otx2_atomic64_add(u64 incr, u64 *ptr)
#endif
static inline void __cn10k_aura_freeptr(struct otx2_nic *pfvf, u64 aura,
- u64 *ptrs, u64 num_ptrs,
- u64 *lmt_addr)
+ u64 *ptrs, u64 num_ptrs)
{
+ struct otx2_lmt_info *lmt_info;
u64 size = 0, count_eot = 0;
u64 tar_addr, val = 0;
+ lmt_info = per_cpu_ptr(pfvf->hw.lmt_info, smp_processor_id());
tar_addr = (__force u64)otx2_get_regaddr(pfvf, NPA_LF_AURA_BATCH_FREE0);
/* LMTID is same as AURA Id */
- val = (aura & 0x7FF) | BIT_ULL(63);
+ val = (lmt_info->lmt_id & 0x7FF) | BIT_ULL(63);
/* Set if [127:64] of last 128bit word has a valid pointer */
count_eot = (num_ptrs % 2) ? 0ULL : 1ULL;
/* Set AURA ID to free pointer */
@@ -586,7 +591,7 @@ static inline void __cn10k_aura_freeptr(struct otx2_nic *pfvf, u64 aura,
size++;
tar_addr |= ((size - 1) & 0x7) << 4;
}
- memcpy(lmt_addr, ptrs, sizeof(u64) * num_ptrs);
+ memcpy((u64 *)lmt_info->lmt_addr, ptrs, sizeof(u64) * num_ptrs);
/* Perform LMTST flush */
cn10k_lmt_flush(val, tar_addr);
}
@@ -594,12 +599,11 @@ static inline void __cn10k_aura_freeptr(struct otx2_nic *pfvf, u64 aura,
static inline void cn10k_aura_freeptr(void *dev, int aura, u64 buf)
{
struct otx2_nic *pfvf = dev;
- struct otx2_pool *pool;
u64 ptrs[2];
- pool = &pfvf->qset.pool[aura];
ptrs[1] = buf;
- __cn10k_aura_freeptr(pfvf, aura, ptrs, 2, pool->lmt_addr);
+ /* Free only one buffer at time during init and teardown */
+ __cn10k_aura_freeptr(pfvf, aura, ptrs, 2);
}
/* Alloc pointer from pool/aura */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index 799486c72177..dbfa3bc39e34 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -16,8 +16,8 @@
#include "otx2_common.h"
#include "otx2_ptp.h"
-#define DRV_NAME "octeontx2-nicpf"
-#define DRV_VF_NAME "octeontx2-nicvf"
+#define DRV_NAME "rvu-nicpf"
+#define DRV_VF_NAME "rvu-nicvf"
struct otx2_stat {
char name[ETH_GSTRING_LEN];
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 2f2e8a3d7924..53df7fff92c4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1533,14 +1533,6 @@ int otx2_open(struct net_device *netdev)
if (!qset->rq)
goto err_free_mem;
- if (test_bit(CN10K_LMTST, &pf->hw.cap_flag)) {
- /* Reserve LMT lines for NPA AURA batch free */
- pf->hw.npa_lmt_base = pf->hw.lmt_base;
- /* Reserve LMT lines for NIX TX */
- pf->hw.nix_lmt_base = (u64 *)((u64)pf->hw.npa_lmt_base +
- (pf->npa_lmt_lines * LMT_LINE_SIZE));
- }
-
err = otx2_init_hw_resources(pf);
if (err)
goto err_free_mem;
@@ -2668,6 +2660,8 @@ err_del_mcam_entries:
err_ptp_destroy:
otx2_ptp_destroy(pf);
err_detach_rsrc:
+ if (pf->hw.lmt_info)
+ free_percpu(pf->hw.lmt_info);
if (test_bit(CN10K_LMTST, &pf->hw.cap_flag))
qmem_free(pf->dev, pf->dync_lmt);
otx2_detach_resources(&pf->mbox);
@@ -2811,6 +2805,8 @@ static void otx2_remove(struct pci_dev *pdev)
otx2_mcam_flow_del(pf);
otx2_shutdown_tc(pf);
otx2_detach_resources(&pf->mbox);
+ if (pf->hw.lmt_info)
+ free_percpu(pf->hw.lmt_info);
if (test_bit(CN10K_LMTST, &pf->hw.cap_flag))
qmem_free(pf->dev, pf->dync_lmt);
otx2_disable_mbox_intr(pf);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
index 869de5f59e73..3ff1ad79c001 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
@@ -80,7 +80,6 @@ struct otx2_snd_queue {
u16 num_sqbs;
u16 sqe_thresh;
u8 sqe_per_sqb;
- u32 lmt_id;
u64 io_addr;
u64 *aura_fc_addr;
u64 *lmt_addr;
@@ -111,7 +110,6 @@ struct otx2_cq_poll {
struct otx2_pool {
struct qmem *stack;
struct qmem *fc_addr;
- u64 *lmt_addr;
u16 rbsize;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
index e84287ffc7ce..dcf9f27ba2ef 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -658,11 +658,10 @@ static const struct devlink_param enable_rdma_param =
static int mlx5_devlink_rdma_param_register(struct devlink *devlink)
{
- struct mlx5_core_dev *dev = devlink_priv(devlink);
union devlink_param_value value;
int err;
- if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND) || MLX5_ESWITCH_MANAGER(dev))
+ if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
return 0;
err = devlink_param_register(devlink, &enable_rdma_param);
@@ -679,9 +678,7 @@ static int mlx5_devlink_rdma_param_register(struct devlink *devlink)
static void mlx5_devlink_rdma_param_unregister(struct devlink *devlink)
{
- struct mlx5_core_dev *dev = devlink_priv(devlink);
-
- if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND) || MLX5_ESWITCH_MANAGER(dev))
+ if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
return;
devlink_param_unpublish(devlink, &enable_rdma_param);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
index 3f8a98093f8c..f9cf9fb31547 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
@@ -1007,7 +1007,7 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
err = mlx5_core_alloc_pd(dev, &tracer->buff.pdn);
if (err) {
mlx5_core_warn(dev, "FWTracer: Failed to allocate PD %d\n", err);
- return err;
+ goto err_cancel_work;
}
err = mlx5_fw_tracer_create_mkey(tracer);
@@ -1031,6 +1031,7 @@ err_notifier_unregister:
mlx5_core_destroy_mkey(dev, &tracer->buff.mkey);
err_dealloc_pd:
mlx5_core_dealloc_pd(dev, tracer->buff.pdn);
+err_cancel_work:
cancel_work_sync(&tracer->read_fw_strings_work);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 669a75f3537a..7b8c8187543a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -922,7 +922,7 @@ void mlx5e_set_rx_mode_work(struct work_struct *work);
int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr);
int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr);
-int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool val);
+int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool val, bool rx_filter);
int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
u16 vid);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
index 0c38c2e319be..b5ddaa82755f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
@@ -137,7 +137,7 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
u16 vport_num, esw_owner_vhca_id;
struct netlink_ext_ack *extack;
int ifindex = upper->ifindex;
- int err;
+ int err = 0;
if (!netif_is_bridge_master(upper))
return 0;
@@ -244,7 +244,7 @@ mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_attr_info->info);
const struct switchdev_attr *attr = port_attr_info->attr;
u16 vport_num, esw_owner_vhca_id;
- int err;
+ int err = 0;
if (!mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
&esw_owner_vhca_id))
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
index bf0313e2682b..13056cb9757d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
@@ -572,7 +572,7 @@ void mlx5e_rx_res_channels_activate(struct mlx5e_rx_res *res, struct mlx5e_chann
if (res->features & MLX5E_RX_RES_FEATURE_PTP) {
u32 rqn;
- if (mlx5e_channels_get_ptp_rqn(chs, &rqn))
+ if (!mlx5e_channels_get_ptp_rqn(chs, &rqn))
rqn = res->drop_rqn;
err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, rqn);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 2cfd12953909..306fb5d6a36d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1884,7 +1884,7 @@ static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
return set_pflag_cqe_based_moder(netdev, enable, true);
}
-int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val)
+int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val, bool rx_filter)
{
bool curr_val = MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_RX_CQE_COMPRESS);
struct mlx5e_params new_params;
@@ -1896,8 +1896,7 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val
if (curr_val == new_val)
return 0;
- if (new_val && !priv->profile->rx_ptp_support &&
- priv->tstamp.rx_filter != HWTSTAMP_FILTER_NONE) {
+ if (new_val && !priv->profile->rx_ptp_support && rx_filter) {
netdev_err(priv->netdev,
"Profile doesn't support enabling of CQE compression while hardware time-stamping is enabled.\n");
return -EINVAL;
@@ -1905,7 +1904,7 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val
new_params = priv->channels.params;
MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_RX_CQE_COMPRESS, new_val);
- if (priv->tstamp.rx_filter != HWTSTAMP_FILTER_NONE)
+ if (rx_filter)
new_params.ptp_rx = new_val;
if (new_params.ptp_rx == priv->channels.params.ptp_rx)
@@ -1928,12 +1927,14 @@ static int set_pflag_rx_cqe_compress(struct net_device *netdev,
{
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5_core_dev *mdev = priv->mdev;
+ bool rx_filter;
int err;
if (!MLX5_CAP_GEN(mdev, cqe_compression))
return -EOPNOTSUPP;
- err = mlx5e_modify_rx_cqe_compression_locked(priv, enable);
+ rx_filter = priv->tstamp.rx_filter != HWTSTAMP_FILTER_NONE;
+ err = mlx5e_modify_rx_cqe_compression_locked(priv, enable, rx_filter);
if (err)
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 47efd858964d..3fd515e7bf30 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3554,14 +3554,14 @@ static int mlx5e_hwstamp_config_no_ptp_rx(struct mlx5e_priv *priv, bool rx_filte
if (!rx_filter)
/* Reset CQE compression to Admin default */
- return mlx5e_modify_rx_cqe_compression_locked(priv, rx_cqe_compress_def);
+ return mlx5e_modify_rx_cqe_compression_locked(priv, rx_cqe_compress_def, false);
if (!MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_RX_CQE_COMPRESS))
return 0;
/* Disable CQE compression */
netdev_warn(priv->netdev, "Disabling RX cqe compression\n");
- err = mlx5e_modify_rx_cqe_compression_locked(priv, false);
+ err = mlx5e_modify_rx_cqe_compression_locked(priv, false, true);
if (err)
netdev_err(priv->netdev, "Failed disabling cqe compression err=%d\n", err);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 9fe8e3c204d6..fe501ba88bea 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -1682,14 +1682,13 @@ static int build_match_list(struct match_list *match_head,
curr_match = kmalloc(sizeof(*curr_match), GFP_ATOMIC);
if (!curr_match) {
+ rcu_read_unlock();
free_match_list(match_head, ft_locked);
- err = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
curr_match->g = g;
list_add_tail(&curr_match->list, &match_head->list);
}
-out:
rcu_read_unlock();
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
index 49ca57c6d31d..ca5690b0a7ab 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
@@ -927,9 +927,12 @@ void mlx5_lag_disable_change(struct mlx5_core_dev *dev)
struct mlx5_core_dev *dev1;
struct mlx5_lag *ldev;
+ ldev = mlx5_lag_dev(dev);
+ if (!ldev)
+ return;
+
mlx5_dev_list_lock();
- ldev = mlx5_lag_dev(dev);
dev0 = ldev->pf[MLX5_LAG_P1].dev;
dev1 = ldev->pf[MLX5_LAG_P2].dev;
@@ -946,8 +949,11 @@ void mlx5_lag_enable_change(struct mlx5_core_dev *dev)
{
struct mlx5_lag *ldev;
- mlx5_dev_list_lock();
ldev = mlx5_lag_dev(dev);
+ if (!ldev)
+ return;
+
+ mlx5_dev_list_lock();
ldev->mode_changes_in_progress--;
mlx5_dev_list_unlock();
mlx5_queue_bond_work(ldev, 0);
diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
index c1310ea1c216..d5c485a6d284 100644
--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
+++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
@@ -398,9 +398,7 @@ static int mana_hwc_alloc_dma_buf(struct hw_channel_context *hwc, u16 q_depth,
int err;
u16 i;
- dma_buf = kzalloc(sizeof(*dma_buf) +
- q_depth * sizeof(struct hwc_work_request),
- GFP_KERNEL);
+ dma_buf = kzalloc(struct_size(dma_buf, reqs, q_depth), GFP_KERNEL);
if (!dma_buf)
return -ENOMEM;
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index 2289e1fe3741..8709d700e15a 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -603,7 +603,7 @@ out:
return err;
}
-static int mac_sonic_nubus_remove(struct nubus_board *board)
+static void mac_sonic_nubus_remove(struct nubus_board *board)
{
struct net_device *ndev = nubus_get_drvdata(board);
struct sonic_local *lp = netdev_priv(ndev);
@@ -613,8 +613,6 @@ static int mac_sonic_nubus_remove(struct nubus_board *board)
SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
lp->descriptors, lp->descriptors_laddr);
free_netdev(ndev);
-
- return 0;
}
static struct nubus_driver mac_sonic_nubus_driver = {
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
index e91b4874a57f..3de1a03839e2 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
@@ -582,7 +582,10 @@ static int ionic_set_ringparam(struct net_device *netdev,
qparam.ntxq_descs = ring->tx_pending;
qparam.nrxq_descs = ring->rx_pending;
+
+ mutex_lock(&lif->queue_lock);
err = ionic_reconfigure_queues(lif, &qparam);
+ mutex_unlock(&lif->queue_lock);
if (err)
netdev_info(netdev, "Ring reconfiguration failed, changes canceled: %d\n", err);
@@ -679,7 +682,9 @@ static int ionic_set_channels(struct net_device *netdev,
return 0;
}
+ mutex_lock(&lif->queue_lock);
err = ionic_reconfigure_queues(lif, &qparam);
+ mutex_unlock(&lif->queue_lock);
if (err)
netdev_info(netdev, "Queue reconfiguration failed, changes canceled: %d\n", err);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 23c9e196a784..381966e8f557 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1715,7 +1715,6 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
static void ionic_stop_queues_reconfig(struct ionic_lif *lif)
{
/* Stop and clean the queues before reconfiguration */
- mutex_lock(&lif->queue_lock);
netif_device_detach(lif->netdev);
ionic_stop_queues(lif);
ionic_txrx_deinit(lif);
@@ -1734,8 +1733,7 @@ static int ionic_start_queues_reconfig(struct ionic_lif *lif)
* DOWN and UP to try to reset and clear the issue.
*/
err = ionic_txrx_init(lif);
- mutex_unlock(&lif->queue_lock);
- ionic_link_status_check_request(lif, CAN_SLEEP);
+ ionic_link_status_check_request(lif, CAN_NOT_SLEEP);
netif_device_attach(lif->netdev);
return err;
@@ -1765,9 +1763,13 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
return 0;
}
+ mutex_lock(&lif->queue_lock);
ionic_stop_queues_reconfig(lif);
netdev->mtu = new_mtu;
- return ionic_start_queues_reconfig(lif);
+ err = ionic_start_queues_reconfig(lif);
+ mutex_unlock(&lif->queue_lock);
+
+ return err;
}
static void ionic_tx_timeout_work(struct work_struct *ws)
@@ -1783,8 +1785,10 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
if (!netif_running(lif->netdev))
return;
+ mutex_lock(&lif->queue_lock);
ionic_stop_queues_reconfig(lif);
ionic_start_queues_reconfig(lif);
+ mutex_unlock(&lif->queue_lock);
}
static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue)
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
index 7e3a5634c161..25ecfcfa1281 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
@@ -318,7 +318,7 @@ void ionic_rx_filter_sync(struct ionic_lif *lif)
if (f->state == IONIC_FILTER_STATE_NEW ||
f->state == IONIC_FILTER_STATE_OLD) {
sync_item = devm_kzalloc(dev, sizeof(*sync_item),
- GFP_KERNEL);
+ GFP_ATOMIC);
if (!sync_item)
goto loop_out;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c
index 5a0a3cbcc1c1..cb0f2a3a1ac9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c
@@ -2226,8 +2226,8 @@ qed_cxt_dynamic_ilt_alloc(struct qed_hwfn *p_hwfn,
p_blk = &p_cli->pf_blks[CDUT_SEG_BLK(QED_CXT_ROCE_TID_SEG)];
break;
default:
- DP_NOTICE(p_hwfn, "-EINVALID elem type = %d", elem_type);
- return -EINVAL;
+ DP_NOTICE(p_hwfn, "-EOPNOTSUPP elem type = %d", elem_type);
+ return -EOPNOTSUPP;
}
/* Calculate line in ilt */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 6e5a6cc97d0e..24cd41567775 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -3367,6 +3367,7 @@ qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn,
struct qed_nvm_image_att *p_image_att)
{
enum nvm_image_type type;
+ int rc;
u32 i;
/* Translate image_id into MFW definitions */
@@ -3395,7 +3396,10 @@ qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn,
return -EINVAL;
}
- qed_mcp_nvm_info_populate(p_hwfn);
+ rc = qed_mcp_nvm_info_populate(p_hwfn);
+ if (rc)
+ return rc;
+
for (i = 0; i < p_hwfn->nvm_info.num_images; i++)
if (type == p_hwfn->nvm_info.image_att[i].image_type)
break;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index 0a2f34fc8b24..27dffa299ca6 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -1354,10 +1354,10 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
const struct firmware *fw = fw_info->fw;
u32 dest, *p_cache, *temp;
- int i, ret = -EIO;
__le32 *temp_le;
u8 data[16];
size_t size;
+ int i, ret;
u64 addr;
temp = vzalloc(fw->size);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index 3d61a767a8a3..09f20c794754 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -437,7 +437,6 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, 1);
msleep(20);
- qlcnic_rom_unlock(adapter);
/* big hammer don't reset CAM block on reset */
QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-ethtool.c b/drivers/net/ethernet/qualcomm/emac/emac-ethtool.c
index 79e50079ed03..f72e13b83869 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-ethtool.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-ethtool.c
@@ -100,7 +100,7 @@ static void emac_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
case ETH_SS_STATS:
for (i = 0; i < EMAC_STATS_LEN; i++) {
- strlcpy(data, emac_ethtool_stat_strings[i],
+ strscpy(data, emac_ethtool_stat_strings[i],
ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}
diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index 4b2eca5e08e2..01ef5efd7bc2 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -119,6 +119,8 @@
#define PHY_ST 0x8A /* PHY status register */
#define MAC_SM 0xAC /* MAC status machine */
#define MAC_SM_RST 0x0002 /* MAC status machine reset */
+#define MD_CSC 0xb6 /* MDC speed control register */
+#define MD_CSC_DEFAULT 0x0030
#define MAC_ID 0xBE /* Identifier register */
#define TX_DCNT 0x80 /* TX descriptor count */
@@ -355,8 +357,9 @@ static void r6040_reset_mac(struct r6040_private *lp)
{
void __iomem *ioaddr = lp->base;
int limit = MAC_DEF_TIMEOUT;
- u16 cmd;
+ u16 cmd, md_csc;
+ md_csc = ioread16(ioaddr + MD_CSC);
iowrite16(MAC_RST, ioaddr + MCR1);
while (limit--) {
cmd = ioread16(ioaddr + MCR1);
@@ -368,6 +371,10 @@ static void r6040_reset_mac(struct r6040_private *lp)
iowrite16(MAC_SM_RST, ioaddr + MAC_SM);
iowrite16(0, ioaddr + MAC_SM);
mdelay(5);
+
+ /* Restore MDIO clock frequency */
+ if (md_csc != MD_CSC_DEFAULT)
+ iowrite16(md_csc, ioaddr + MD_CSC);
}
static void r6040_init_mac_regs(struct net_device *dev)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 6c8ba916d1a6..1374faa229a2 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2533,6 +2533,7 @@ static netdev_tx_t sh_eth_start_xmit(struct sk_buff *skb,
else
txdesc->status |= cpu_to_le32(TD_TACT);
+ wmb(); /* cur_tx must be incremented after TACT bit was set */
mdp->cur_tx++;
if (!(sh_eth_read(ndev, EDTRR) & mdp->cd->edtrr_trns))
diff --git a/drivers/net/ethernet/sfc/efx_channels.c b/drivers/net/ethernet/sfc/efx_channels.c
index e5b0d795c301..3dbea028b325 100644
--- a/drivers/net/ethernet/sfc/efx_channels.c
+++ b/drivers/net/ethernet/sfc/efx_channels.c
@@ -166,32 +166,46 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
* We need a channel per event queue, plus a VI per tx queue.
* This may be more pessimistic than it needs to be.
*/
- if (n_channels + n_xdp_ev > max_channels) {
- netif_err(efx, drv, efx->net_dev,
- "Insufficient resources for %d XDP event queues (%d other channels, max %d)\n",
- n_xdp_ev, n_channels, max_channels);
- netif_err(efx, drv, efx->net_dev,
- "XDP_TX and XDP_REDIRECT will not work on this interface");
- efx->n_xdp_channels = 0;
- efx->xdp_tx_per_channel = 0;
- efx->xdp_tx_queue_count = 0;
+ if (n_channels >= max_channels) {
+ efx->xdp_txq_queues_mode = EFX_XDP_TX_QUEUES_BORROWED;
+ netif_warn(efx, drv, efx->net_dev,
+ "Insufficient resources for %d XDP event queues (%d other channels, max %d)\n",
+ n_xdp_ev, n_channels, max_channels);
+ netif_warn(efx, drv, efx->net_dev,
+ "XDP_TX and XDP_REDIRECT might decrease device's performance\n");
} else if (n_channels + n_xdp_tx > efx->max_vis) {
- netif_err(efx, drv, efx->net_dev,
- "Insufficient resources for %d XDP TX queues (%d other channels, max VIs %d)\n",
- n_xdp_tx, n_channels, efx->max_vis);
- netif_err(efx, drv, efx->net_dev,
- "XDP_TX and XDP_REDIRECT will not work on this interface");
- efx->n_xdp_channels = 0;
- efx->xdp_tx_per_channel = 0;
- efx->xdp_tx_queue_count = 0;
+ efx->xdp_txq_queues_mode = EFX_XDP_TX_QUEUES_BORROWED;
+ netif_warn(efx, drv, efx->net_dev,
+ "Insufficient resources for %d XDP TX queues (%d other channels, max VIs %d)\n",
+ n_xdp_tx, n_channels, efx->max_vis);
+ netif_warn(efx, drv, efx->net_dev,
+ "XDP_TX and XDP_REDIRECT might decrease device's performance\n");
+ } else if (n_channels + n_xdp_ev > max_channels) {
+ efx->xdp_txq_queues_mode = EFX_XDP_TX_QUEUES_SHARED;
+ netif_warn(efx, drv, efx->net_dev,
+ "Insufficient resources for %d XDP event queues (%d other channels, max %d)\n",
+ n_xdp_ev, n_channels, max_channels);
+
+ n_xdp_ev = max_channels - n_channels;
+ netif_warn(efx, drv, efx->net_dev,
+ "XDP_TX and XDP_REDIRECT will work with reduced performance (%d cpus/tx_queue)\n",
+ DIV_ROUND_UP(n_xdp_tx, tx_per_ev * n_xdp_ev));
} else {
+ efx->xdp_txq_queues_mode = EFX_XDP_TX_QUEUES_DEDICATED;
+ }
+
+ if (efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_BORROWED) {
efx->n_xdp_channels = n_xdp_ev;
efx->xdp_tx_per_channel = tx_per_ev;
efx->xdp_tx_queue_count = n_xdp_tx;
n_channels += n_xdp_ev;
netif_dbg(efx, drv, efx->net_dev,
"Allocating %d TX and %d event queues for XDP\n",
- n_xdp_tx, n_xdp_ev);
+ n_xdp_ev * tx_per_ev, n_xdp_ev);
+ } else {
+ efx->n_xdp_channels = 0;
+ efx->xdp_tx_per_channel = 0;
+ efx->xdp_tx_queue_count = n_xdp_tx;
}
if (vec_count < n_channels) {
@@ -858,6 +872,20 @@ rollback:
goto out;
}
+static inline int
+efx_set_xdp_tx_queue(struct efx_nic *efx, int xdp_queue_number,
+ struct efx_tx_queue *tx_queue)
+{
+ if (xdp_queue_number >= efx->xdp_tx_queue_count)
+ return -EINVAL;
+
+ netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is XDP %u, HW %u\n",
+ tx_queue->channel->channel, tx_queue->label,
+ xdp_queue_number, tx_queue->queue);
+ efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
+ return 0;
+}
+
int efx_set_channels(struct efx_nic *efx)
{
struct efx_tx_queue *tx_queue;
@@ -896,20 +924,9 @@ int efx_set_channels(struct efx_nic *efx)
if (efx_channel_is_xdp_tx(channel)) {
efx_for_each_channel_tx_queue(tx_queue, channel) {
tx_queue->queue = next_queue++;
-
- /* We may have a few left-over XDP TX
- * queues owing to xdp_tx_queue_count
- * not dividing evenly by EFX_MAX_TXQ_PER_CHANNEL.
- * We still allocate and probe those
- * TXQs, but never use them.
- */
- if (xdp_queue_number < efx->xdp_tx_queue_count) {
- netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is XDP %u, HW %u\n",
- channel->channel, tx_queue->label,
- xdp_queue_number, tx_queue->queue);
- efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
+ rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
+ if (rc == 0)
xdp_queue_number++;
- }
}
} else {
efx_for_each_channel_tx_queue(tx_queue, channel) {
@@ -918,10 +935,35 @@ int efx_set_channels(struct efx_nic *efx)
channel->channel, tx_queue->label,
tx_queue->queue);
}
+
+ /* If XDP is borrowing queues from net stack, it must use the queue
+ * with no csum offload, which is the first one of the channel
+ * (note: channel->tx_queue_by_type is not initialized yet)
+ */
+ if (efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_BORROWED) {
+ tx_queue = &channel->tx_queue[0];
+ rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
+ if (rc == 0)
+ xdp_queue_number++;
+ }
}
}
}
- WARN_ON(xdp_queue_number != efx->xdp_tx_queue_count);
+ WARN_ON(efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_DEDICATED &&
+ xdp_queue_number != efx->xdp_tx_queue_count);
+ WARN_ON(efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED &&
+ xdp_queue_number > efx->xdp_tx_queue_count);
+
+ /* If we have more CPUs than assigned XDP TX queues, assign the already
+ * existing queues to the exceeding CPUs
+ */
+ next_queue = 0;
+ while (xdp_queue_number < efx->xdp_tx_queue_count) {
+ tx_queue = efx->xdp_tx_queues[next_queue++];
+ rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
+ if (rc == 0)
+ xdp_queue_number++;
+ }
rc = netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
if (rc)
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 9b4b25704271..f6981810039d 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -782,6 +782,12 @@ struct efx_async_filter_insertion {
#define EFX_RPS_MAX_IN_FLIGHT 8
#endif /* CONFIG_RFS_ACCEL */
+enum efx_xdp_tx_queues_mode {
+ EFX_XDP_TX_QUEUES_DEDICATED, /* one queue per core, locking not needed */
+ EFX_XDP_TX_QUEUES_SHARED, /* each queue used by more than 1 core */
+ EFX_XDP_TX_QUEUES_BORROWED /* queues borrowed from net stack */
+};
+
/**
* struct efx_nic - an Efx NIC
* @name: Device name (net device name or bus id before net device registered)
@@ -820,6 +826,7 @@ struct efx_async_filter_insertion {
* should be allocated for this NIC
* @xdp_tx_queue_count: Number of entries in %xdp_tx_queues.
* @xdp_tx_queues: Array of pointers to tx queues used for XDP transmit.
+ * @xdp_txq_queues_mode: XDP TX queues sharing strategy.
* @rxq_entries: Size of receive queues requested by user.
* @txq_entries: Size of transmit queues requested by user.
* @txq_stop_thresh: TX queue fill level at or above which we stop it.
@@ -979,6 +986,7 @@ struct efx_nic {
unsigned int xdp_tx_queue_count;
struct efx_tx_queue **xdp_tx_queues;
+ enum efx_xdp_tx_queues_mode xdp_txq_queues_mode;
unsigned rxq_entries;
unsigned txq_entries;
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 0c6650d2e239..d16e031e95f4 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -428,23 +428,32 @@ int efx_xdp_tx_buffers(struct efx_nic *efx, int n, struct xdp_frame **xdpfs,
unsigned int len;
int space;
int cpu;
- int i;
+ int i = 0;
- cpu = raw_smp_processor_id();
+ if (unlikely(n && !xdpfs))
+ return -EINVAL;
+ if (unlikely(!n))
+ return 0;
- if (!efx->xdp_tx_queue_count ||
- unlikely(cpu >= efx->xdp_tx_queue_count))
+ cpu = raw_smp_processor_id();
+ if (unlikely(cpu >= efx->xdp_tx_queue_count))
return -EINVAL;
tx_queue = efx->xdp_tx_queues[cpu];
if (unlikely(!tx_queue))
return -EINVAL;
- if (unlikely(n && !xdpfs))
- return -EINVAL;
+ if (efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED)
+ HARD_TX_LOCK(efx->net_dev, tx_queue->core_txq, cpu);
- if (!n)
- return 0;
+ /* If we're borrowing net stack queues we have to handle stop-restart
+ * or we might block the queue and it will be considered as frozen
+ */
+ if (efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_BORROWED) {
+ if (netif_tx_queue_stopped(tx_queue->core_txq))
+ goto unlock;
+ efx_tx_maybe_stop_queue(tx_queue);
+ }
/* Check for available space. We should never need multiple
* descriptors per frame.
@@ -484,6 +493,10 @@ int efx_xdp_tx_buffers(struct efx_nic *efx, int n, struct xdp_frame **xdpfs,
if (flush && i > 0)
efx_nic_push_buffers(tx_queue);
+unlock:
+ if (efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED)
+ HARD_TX_UNLOCK(efx->net_dev, tx_queue->core_txq);
+
return i == 0 ? -EIO : i;
}
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 22cdbf12c823..b008b4e8a2a5 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -1550,7 +1550,7 @@ static int smc911x_ethtool_getregslen(struct net_device *dev)
}
static void smc911x_ethtool_getregs(struct net_device *dev,
- struct ethtool_regs* regs, void *buf)
+ struct ethtool_regs *regs, void *buf)
{
struct smc911x_local *lp = netdev_priv(dev);
unsigned long flags;
@@ -1600,7 +1600,7 @@ static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev)
}
static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev,
- int cmd, int addr)
+ int cmd, int addr)
{
struct smc911x_local *lp = netdev_priv(dev);
int ret;
@@ -1614,7 +1614,7 @@ static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev,
}
static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev,
- u8 *data)
+ u8 *data)
{
struct smc911x_local *lp = netdev_priv(dev);
int ret;
@@ -1626,7 +1626,7 @@ static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev,
}
static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev,
- u8 data)
+ u8 data)
{
struct smc911x_local *lp = netdev_priv(dev);
int ret;
@@ -1638,7 +1638,7 @@ static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev,
}
static int smc911x_ethtool_geteeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
+ struct ethtool_eeprom *eeprom, u8 *data)
{
u8 eebuf[SMC911X_EEPROM_LEN];
int i, ret;
@@ -1654,7 +1654,7 @@ static int smc911x_ethtool_geteeprom(struct net_device *dev,
}
static int smc911x_ethtool_seteeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
+ struct ethtool_eeprom *eeprom, u8 *data)
{
int i, ret;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 4c9a37dd0d3f..ecf759ee1c9f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -109,8 +109,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
plat->bus_id = pci_dev_id(pdev);
phy_mode = device_get_phy_mode(&pdev->dev);
- if (phy_mode < 0)
+ if (phy_mode < 0) {
dev_err(&pdev->dev, "phy_mode not found\n");
+ return phy_mode;
+ }
plat->phy_interface = phy_mode;
plat->interface = PHY_INTERFACE_MODE_GMII;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ed0cd3920171..553c4403258a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -309,7 +309,7 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
priv->clk_csr = STMMAC_CSR_100_150M;
else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
priv->clk_csr = STMMAC_CSR_150_250M;
- else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
+ else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
priv->clk_csr = STMMAC_CSR_250_300M;
}
@@ -5347,7 +5347,7 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget)
struct stmmac_channel *ch =
container_of(napi, struct stmmac_channel, rxtx_napi);
struct stmmac_priv *priv = ch->priv_data;
- int rx_done, tx_done;
+ int rx_done, tx_done, rxtx_done;
u32 chan = ch->index;
priv->xstats.napi_poll++;
@@ -5357,14 +5357,16 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget)
rx_done = stmmac_rx_zc(priv, budget, chan);
+ rxtx_done = max(tx_done, rx_done);
+
/* If either TX or RX work is not complete, return budget
* and keep pooling
*/
- if (tx_done >= budget || rx_done >= budget)
+ if (rxtx_done >= budget)
return budget;
/* all work done, exit the polling mode */
- if (napi_complete_done(napi, rx_done)) {
+ if (napi_complete_done(napi, rxtx_done)) {
unsigned long flags;
spin_lock_irqsave(&ch->lock, flags);
@@ -5375,7 +5377,7 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget)
spin_unlock_irqrestore(&ch->lock, flags);
}
- return min(rx_done, budget - 1);
+ return min(rxtx_done, budget - 1);
}
/**
@@ -7116,13 +7118,10 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
- phylink_mac_change(priv->phylink, false);
-
mutex_lock(&priv->lock);
netif_device_detach(ndev);
@@ -7148,27 +7147,22 @@ int stmmac_suspend(struct device *dev)
stmmac_pmt(priv, priv->hw, priv->wolopts);
priv->irq_wake = 1;
} else {
- mutex_unlock(&priv->lock);
- rtnl_lock();
- if (device_may_wakeup(priv->device))
- phylink_speed_down(priv->phylink, false);
- phylink_stop(priv->phylink);
- rtnl_unlock();
- mutex_lock(&priv->lock);
-
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
+ rtnl_lock();
+ if (device_may_wakeup(priv->device) && priv->plat->pmt) {
+ phylink_suspend(priv->phylink, true);
+ } else {
+ if (device_may_wakeup(priv->device))
+ phylink_speed_down(priv->phylink, false);
+ phylink_suspend(priv->phylink, false);
+ }
+ rtnl_unlock();
+
if (priv->dma_cap.fpesel) {
/* Disable FPE */
stmmac_fpe_configure(priv, priv->ioaddr,
@@ -7240,12 +7234,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
@@ -7259,13 +7247,15 @@ int stmmac_resume(struct device *dev)
return ret;
}
- if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
- rtnl_lock();
- phylink_start(priv->phylink);
- /* We may have called phylink_speed_down before */
- phylink_speed_up(priv->phylink);
- rtnl_unlock();
+ rtnl_lock();
+ if (device_may_wakeup(priv->device) && priv->plat->pmt) {
+ phylink_resume(priv->phylink);
+ } else {
+ phylink_resume(priv->phylink);
+ if (device_may_wakeup(priv->device))
+ phylink_speed_up(priv->phylink);
}
+ rtnl_unlock();
rtnl_lock();
mutex_lock(&priv->lock);
@@ -7286,8 +7276,6 @@ int stmmac_resume(struct device *dev)
mutex_unlock(&priv->lock);
rtnl_unlock();
- phylink_mac_change(priv->phylink, true);
-
netif_device_attach(ndev);
return 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5ca710844cc1..62cec9bfcd33 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -771,9 +772,52 @@ static int __maybe_unused stmmac_runtime_resume(struct device *dev)
return stmmac_bus_clks_config(priv, true);
}
+static int __maybe_unused stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
diff --git a/drivers/net/ethernet/xscale/ptp_ixp46x.c b/drivers/net/ethernet/xscale/ptp_ixp46x.c
index ecece21315c3..39234852e01b 100644
--- a/drivers/net/ethernet/xscale/ptp_ixp46x.c
+++ b/drivers/net/ethernet/xscale/ptp_ixp46x.c
@@ -16,7 +16,6 @@
#include <linux/ptp_clock_kernel.h>
#include <linux/platform_device.h>
#include <linux/soc/ixp4xx/cpu.h>
-#include <linux/module.h>
#include <mach/ixp4xx-regs.h>
#include "ixp46x_ts.h"
diff --git a/drivers/net/ipa/ipa_table.c b/drivers/net/ipa/ipa_table.c
index 2324e1b93e37..1da334f54944 100644
--- a/drivers/net/ipa/ipa_table.c
+++ b/drivers/net/ipa/ipa_table.c
@@ -430,7 +430,8 @@ static void ipa_table_init_add(struct gsi_trans *trans, bool filter,
* table region determines the number of entries it has.
*/
if (filter) {
- count = hweight32(ipa->filter_map);
+ /* Include one extra "slot" to hold the filter map itself */
+ count = 1 + hweight32(ipa->filter_map);
hash_count = hash_mem->size ? count : 0;
} else {
count = mem->size / sizeof(__le64);
diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c
index 62d033a1a557..29f5627d11e6 100644
--- a/drivers/net/netdevsim/bus.c
+++ b/drivers/net/netdevsim/bus.c
@@ -374,12 +374,11 @@ static int nsim_bus_probe(struct device *dev)
return nsim_dev_probe(nsim_bus_dev);
}
-static int nsim_bus_remove(struct device *dev)
+static void nsim_bus_remove(struct device *dev)
{
struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
nsim_dev_remove(nsim_bus_dev);
- return 0;
}
static int nsim_num_vf(struct device *dev)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 2cdf9f989dec..0a0abe8e4be0 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -33,6 +33,7 @@
enum {
PHYLINK_DISABLE_STOPPED,
PHYLINK_DISABLE_LINK,
+ PHYLINK_DISABLE_MAC_WOL,
};
/**
@@ -1282,6 +1283,9 @@ EXPORT_SYMBOL_GPL(phylink_start);
* network device driver's &struct net_device_ops ndo_stop() method. The
* network device's carrier state should not be changed prior to calling this
* function.
+ *
+ * This will synchronously bring down the link if the link is not already
+ * down (in other words, it will trigger a mac_link_down() method call.)
*/
void phylink_stop(struct phylink *pl)
{
@@ -1302,6 +1306,84 @@ void phylink_stop(struct phylink *pl)
EXPORT_SYMBOL_GPL(phylink_stop);
/**
+ * phylink_suspend() - handle a network device suspend event
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ * @mac_wol: true if the MAC needs to receive packets for Wake-on-Lan
+ *
+ * Handle a network device suspend event. There are several cases:
+ * - If Wake-on-Lan is not active, we can bring down the link between
+ * the MAC and PHY by calling phylink_stop().
+ * - If Wake-on-Lan is active, and being handled only by the PHY, we
+ * can also bring down the link between the MAC and PHY.
+ * - If Wake-on-Lan is active, but being handled by the MAC, the MAC
+ * still needs to receive packets, so we can not bring the link down.
+ */
+void phylink_suspend(struct phylink *pl, bool mac_wol)
+{
+ ASSERT_RTNL();
+
+ if (mac_wol && (!pl->netdev || pl->netdev->wol_enabled)) {
+ /* Wake-on-Lan enabled, MAC handling */
+ mutex_lock(&pl->state_mutex);
+
+ /* Stop the resolver bringing the link up */
+ __set_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state);
+
+ /* Disable the carrier, to prevent transmit timeouts,
+ * but one would hope all packets have been sent. This
+ * also means phylink_resolve() will do nothing.
+ */
+ netif_carrier_off(pl->netdev);
+
+ /* We do not call mac_link_down() here as we want the
+ * link to remain up to receive the WoL packets.
+ */
+ mutex_unlock(&pl->state_mutex);
+ } else {
+ phylink_stop(pl);
+ }
+}
+EXPORT_SYMBOL_GPL(phylink_suspend);
+
+/**
+ * phylink_resume() - handle a network device resume event
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * Undo the effects of phylink_suspend(), returning the link to an
+ * operational state.
+ */
+void phylink_resume(struct phylink *pl)
+{
+ ASSERT_RTNL();
+
+ if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
+ /* Wake-on-Lan enabled, MAC handling */
+
+ /* Call mac_link_down() so we keep the overall state balanced.
+ * Do this under the state_mutex lock for consistency. This
+ * will cause a "Link Down" message to be printed during
+ * resume, which is harmless - the true link state will be
+ * printed when we run a resolve.
+ */
+ mutex_lock(&pl->state_mutex);
+ phylink_link_down(pl);
+ mutex_unlock(&pl->state_mutex);
+
+ /* Re-apply the link parameters so that all the settings get
+ * restored to the MAC.
+ */
+ phylink_mac_initial_config(pl, true);
+
+ /* Re-enable and re-resolve the link parameters */
+ clear_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state);
+ phylink_run_resolve(pl);
+ } else {
+ phylink_start(pl);
+ }
+}
+EXPORT_SYMBOL_GPL(phylink_resume);
+
+/**
* phylink_ethtool_get_wol() - get the wake on lan parameters for the PHY
* @pl: a pointer to a &struct phylink returned from phylink_create()
* @wol: a pointer to &struct ethtool_wolinfo to hold the read parameters
@@ -1525,6 +1607,32 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
if (config.an_enabled && phylink_is_empty_linkmode(config.advertising))
return -EINVAL;
+ /* If this link is with an SFP, ensure that changes to advertised modes
+ * also cause the associated interface to be selected such that the
+ * link can be configured correctly.
+ */
+ if (pl->sfp_port && pl->sfp_bus) {
+ config.interface = sfp_select_interface(pl->sfp_bus,
+ config.advertising);
+ if (config.interface == PHY_INTERFACE_MODE_NA) {
+ phylink_err(pl,
+ "selection of interface failed, advertisement %*pb\n",
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+ config.advertising);
+ return -EINVAL;
+ }
+
+ /* Revalidate with the selected interface */
+ linkmode_copy(support, pl->supported);
+ if (phylink_validate(pl, support, &config)) {
+ phylink_err(pl, "validation of %s/%s with support %*pb failed\n",
+ phylink_an_mode_str(pl->cur_link_an_mode),
+ phy_modes(config.interface),
+ __ETHTOOL_LINK_MODE_MASK_NBITS, support);
+ return -EINVAL;
+ }
+ }
+
mutex_lock(&pl->state_mutex);
pl->link_config.speed = config.speed;
pl->link_config.duplex = config.duplex;
@@ -2104,7 +2212,9 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
if (phy_interface_mode_is_8023z(iface) && pl->phydev)
return -EINVAL;
- changed = !linkmode_equal(pl->supported, support);
+ changed = !linkmode_equal(pl->supported, support) ||
+ !linkmode_equal(pl->link_config.advertising,
+ config.advertising);
if (changed) {
linkmode_copy(pl->supported, support);
linkmode_copy(pl->link_config.advertising, config.advertising);
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 4c4ab7b38d78..82bb5ed94c48 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -654,6 +654,11 @@ static const struct usb_device_id mbim_devs[] = {
.driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle,
},
+ /* Telit LN920 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1061, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle,
+ },
+
/* default entry */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&cdc_mbim_info_zlp,
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 24bc1e678b7b..a57251ba5991 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2535,13 +2535,17 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
if (!hso_net->mux_bulk_tx_buf)
goto err_free_tx_urb;
- add_net_device(hso_dev);
+ result = add_net_device(hso_dev);
+ if (result) {
+ dev_err(&interface->dev, "Failed to add net device\n");
+ goto err_free_tx_buf;
+ }
/* registering our net device */
result = register_netdev(net);
if (result) {
dev_err(&interface->dev, "Failed to register device\n");
- goto err_free_tx_buf;
+ goto err_rmv_ndev;
}
hso_log_port(hso_dev);
@@ -2550,8 +2554,9 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
return hso_dev;
-err_free_tx_buf:
+err_rmv_ndev:
remove_net_device(hso_dev);
+err_free_tx_buf:
kfree(hso_net->mux_bulk_tx_buf);
err_free_tx_urb:
usb_free_urb(hso_net->mux_bulk_tx_urb);
@@ -3241,9 +3246,10 @@ static int __init hso_init(void)
serial_table[i] = NULL;
/* allocate our driver using the proper amount of supported minors */
- tty_drv = alloc_tty_driver(HSO_SERIAL_TTY_MINORS);
- if (!tty_drv)
- return -ENOMEM;
+ tty_drv = tty_alloc_driver(HSO_SERIAL_TTY_MINORS, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(tty_drv))
+ return PTR_ERR(tty_drv);
/* fill in all needed values */
tty_drv->driver_name = driver_name;
@@ -3256,7 +3262,6 @@ static int __init hso_init(void)
tty_drv->minor_start = 0;
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
tty_drv->subtype = SERIAL_TYPE_NORMAL;
- tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_drv->init_termios = tty_std_termios;
hso_init_termios(&tty_drv->init_termios);
tty_set_operations(tty_drv, &hso_serial_ops);
@@ -3281,7 +3286,7 @@ static int __init hso_init(void)
err_unreg_tty:
tty_unregister_driver(tty_drv);
err_free_tty:
- put_tty_driver(tty_drv);
+ tty_driver_kref_put(tty_drv);
return result;
}
@@ -3292,7 +3297,7 @@ static void __exit hso_exit(void)
tty_unregister_driver(tty_drv);
/* deregister the usb driver */
usb_deregister(&hso_driver);
- put_tty_driver(tty_drv);
+ tty_driver_kref_put(tty_drv);
}
/* Module definitions */
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 6a2e4f884b12..33ada2c59952 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1354,6 +1354,7 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1031, 3)}, /* Telit LE910C1-EUX */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1050, 2)}, /* Telit FN980 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */
{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */
{QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 40f91bc8514d..741289e385d5 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -44,6 +44,7 @@ config ATH10K_SNOC
tristate "Qualcomm ath10k SNOC support"
depends on ATH10K
depends on ARCH_QCOM || COMPILE_TEST
+ depends on QCOM_SCM || !QCOM_SCM #if QCOM_SCM=m this can't be =y
select QCOM_QMI_HELPERS
help
This module adds support for integrated WCN3990 chip connected
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index 75cc2d80fde8..26c7ae242db6 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -330,6 +330,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
mhi_ctrl->cntrl_dev = ab->dev;
mhi_ctrl->fw_image = ab_pci->amss_path;
mhi_ctrl->regs = ab->mem;
+ mhi_ctrl->reg_len = ab->mem_len;
ret = ath11k_mhi_get_msi(ab_pci);
if (ret) {
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 52d1d391f4c6..d8231cc821ae 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -9,7 +9,7 @@
#include "iwl-prph.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 65
+#define IWL_22000_UCODE_API_MAX 66
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
index 314ed90c23dd..dde22bdc8703 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
@@ -231,6 +231,7 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
{
const struct firmware *pnvm;
char pnvm_name[MAX_PNVM_NAME];
+ size_t new_len;
int ret;
iwl_pnvm_get_fs_name(trans, pnvm_name, sizeof(pnvm_name));
@@ -242,11 +243,14 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
return ret;
}
+ new_len = pnvm->size;
*data = kmemdup(pnvm->data, pnvm->size, GFP_KERNEL);
+ release_firmware(pnvm);
+
if (!*data)
return -ENOMEM;
- *len = pnvm->size;
+ *len = new_len;
return 0;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index a7c79d814aa4..c875bf35533c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -49,14 +49,14 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
err = efivar_entry_get(pnvm_efivar, NULL, &package_size, data);
if (err) {
IWL_DEBUG_FW(trans,
- "PNVM UEFI variable not found %d (len %zd)\n",
+ "PNVM UEFI variable not found %d (len %lu)\n",
err, package_size);
kfree(data);
data = ERR_PTR(err);
goto out;
}
- IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %zd\n", package_size);
+ IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size);
*len = package_size;
out:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 6f60018feed1..77ea2d0a3091 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -686,6 +686,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm)
{
int ret;
+ rtnl_lock();
mutex_lock(&mvm->mutex);
ret = iwl_run_init_mvm_ucode(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 8dc1b8eecb86..61b2797a34a8 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -558,6 +558,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),
IWL_DEV_INFO(0xA0F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
IWL_DEV_INFO(0xA0F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
+ IWL_DEV_INFO(0xA0F0, 0x6074, iwl_ax201_cfg_qu_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x0070, iwl_ax201_cfg_quz_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x0074, iwl_ax201_cfg_quz_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x6074, iwl_ax201_cfg_quz_hr, NULL),
diff --git a/drivers/net/wireless/intersil/orinoco/hermes.c b/drivers/net/wireless/intersil/orinoco/hermes.c
index 6d4b7f64efcf..256946552742 100644
--- a/drivers/net/wireless/intersil/orinoco/hermes.c
+++ b/drivers/net/wireless/intersil/orinoco/hermes.c
@@ -79,7 +79,6 @@
#undef HERMES_DEBUG
#ifdef HERMES_DEBUG
-#include <stdarg.h>
#define DEBUG(lvl, stuff...) if ((lvl) <= HERMES_DEBUG) DMSG(stuff)
diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h
index 0d2f10e4cbc8..dc65b0712261 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_imem.h
+++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h
@@ -7,7 +7,6 @@
#define IOSM_IPC_IMEM_H
#include <linux/skbuff.h>
-#include <stdbool.h>
#include "iosm_ipc_mmio.h"
#include "iosm_ipc_pcie.h"
diff --git a/drivers/net/wwan/iosm/iosm_ipc_mmio.c b/drivers/net/wwan/iosm/iosm_ipc_mmio.c
index 06c94b1720b6..09f94c123531 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_mmio.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_mmio.c
@@ -69,7 +69,7 @@ void ipc_mmio_update_cp_capability(struct iosm_mmio *ipc_mmio)
unsigned int ver;
ver = ipc_mmio_get_cp_version(ipc_mmio);
- cp_cap = readl(ipc_mmio->base + ipc_mmio->offset.cp_capability);
+ cp_cap = ioread32(ipc_mmio->base + ipc_mmio->offset.cp_capability);
ipc_mmio->has_mux_lite = (ver >= IOSM_CP_VERSION) &&
!(cp_cap & DL_AGGR) && !(cp_cap & UL_AGGR);
@@ -150,8 +150,8 @@ enum ipc_mem_exec_stage ipc_mmio_get_exec_stage(struct iosm_mmio *ipc_mmio)
if (!ipc_mmio)
return IPC_MEM_EXEC_STAGE_INVALID;
- return (enum ipc_mem_exec_stage)readl(ipc_mmio->base +
- ipc_mmio->offset.exec_stage);
+ return (enum ipc_mem_exec_stage)ioread32(ipc_mmio->base +
+ ipc_mmio->offset.exec_stage);
}
void ipc_mmio_copy_chip_info(struct iosm_mmio *ipc_mmio, void *dest,
@@ -167,8 +167,8 @@ enum ipc_mem_device_ipc_state ipc_mmio_get_ipc_state(struct iosm_mmio *ipc_mmio)
if (!ipc_mmio)
return IPC_MEM_DEVICE_IPC_INVALID;
- return (enum ipc_mem_device_ipc_state)
- readl(ipc_mmio->base + ipc_mmio->offset.ipc_status);
+ return (enum ipc_mem_device_ipc_state)ioread32(ipc_mmio->base +
+ ipc_mmio->offset.ipc_status);
}
enum rom_exit_code ipc_mmio_get_rom_exit_code(struct iosm_mmio *ipc_mmio)
@@ -176,8 +176,8 @@ enum rom_exit_code ipc_mmio_get_rom_exit_code(struct iosm_mmio *ipc_mmio)
if (!ipc_mmio)
return IMEM_ROM_EXIT_FAIL;
- return (enum rom_exit_code)readl(ipc_mmio->base +
- ipc_mmio->offset.rom_exit_code);
+ return (enum rom_exit_code)ioread32(ipc_mmio->base +
+ ipc_mmio->offset.rom_exit_code);
}
void ipc_mmio_config(struct iosm_mmio *ipc_mmio)
@@ -188,10 +188,10 @@ void ipc_mmio_config(struct iosm_mmio *ipc_mmio)
/* AP memory window (full window is open and active so that modem checks
* each AP address) 0 means don't check on modem side.
*/
- iowrite64_lo_hi(0, ipc_mmio->base + ipc_mmio->offset.ap_win_base);
- iowrite64_lo_hi(0, ipc_mmio->base + ipc_mmio->offset.ap_win_end);
+ iowrite64(0, ipc_mmio->base + ipc_mmio->offset.ap_win_base);
+ iowrite64(0, ipc_mmio->base + ipc_mmio->offset.ap_win_end);
- iowrite64_lo_hi(ipc_mmio->context_info_addr,
+ iowrite64(ipc_mmio->context_info_addr,
ipc_mmio->base + ipc_mmio->offset.context_info);
}
@@ -201,8 +201,8 @@ void ipc_mmio_set_psi_addr_and_size(struct iosm_mmio *ipc_mmio, dma_addr_t addr,
if (!ipc_mmio)
return;
- iowrite64_lo_hi(addr, ipc_mmio->base + ipc_mmio->offset.psi_address);
- writel(size, ipc_mmio->base + ipc_mmio->offset.psi_size);
+ iowrite64(addr, ipc_mmio->base + ipc_mmio->offset.psi_address);
+ iowrite32(size, ipc_mmio->base + ipc_mmio->offset.psi_size);
}
void ipc_mmio_set_contex_info_addr(struct iosm_mmio *ipc_mmio, phys_addr_t addr)
@@ -218,6 +218,8 @@ void ipc_mmio_set_contex_info_addr(struct iosm_mmio *ipc_mmio, phys_addr_t addr)
int ipc_mmio_get_cp_version(struct iosm_mmio *ipc_mmio)
{
- return ipc_mmio ? readl(ipc_mmio->base + ipc_mmio->offset.cp_version) :
- -EFAULT;
+ if (ipc_mmio)
+ return ioread32(ipc_mmio->base + ipc_mmio->offset.cp_version);
+
+ return -EFAULT;
}
diff --git a/drivers/ntb/core.c b/drivers/ntb/core.c
index f8f75a504a58..27dd93deff6e 100644
--- a/drivers/ntb/core.c
+++ b/drivers/ntb/core.c
@@ -271,7 +271,7 @@ static int ntb_probe(struct device *dev)
return rc;
}
-static int ntb_remove(struct device *dev)
+static void ntb_remove(struct device *dev)
{
struct ntb_dev *ntb;
struct ntb_client *client;
@@ -283,8 +283,6 @@ static int ntb_remove(struct device *dev)
client->ops.remove(client, ntb);
put_device(dev);
}
-
- return 0;
}
static void ntb_dev_release(struct device *dev)
diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c
index 71428d8cbcfc..87847c380051 100644
--- a/drivers/ntb/hw/amd/ntb_hw_amd.c
+++ b/drivers/ntb/hw/amd/ntb_hw_amd.c
@@ -1176,22 +1176,14 @@ static int amd_ntb_init_pci(struct amd_ntb_dev *ndev,
pci_set_master(pdev);
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (rc) {
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (rc)
goto err_dma_mask;
dev_warn(&pdev->dev, "Cannot DMA highmem\n");
}
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (rc) {
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (rc)
- goto err_dma_mask;
- dev_warn(&pdev->dev, "Cannot DMA consistent highmem\n");
- }
-
ndev->self_mmio = pci_iomap(pdev, 0, 0);
if (!ndev->self_mmio) {
rc = -EIO;
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c
index e7a4c2aa8baa..733557231ed0 100644
--- a/drivers/ntb/hw/idt/ntb_hw_idt.c
+++ b/drivers/ntb/hw/idt/ntb_hw_idt.c
@@ -2640,26 +2640,15 @@ static int idt_init_pci(struct idt_ntb_dev *ndev)
int ret;
/* Initialize the bit mask of PCI/NTB DMA */
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (ret != 0) {
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret != 0) {
dev_err(&pdev->dev, "Failed to set DMA bit mask\n");
return ret;
}
dev_warn(&pdev->dev, "Cannot set DMA highmem bit mask\n");
}
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (ret != 0) {
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (ret != 0) {
- dev_err(&pdev->dev,
- "Failed to set consistent DMA bit mask\n");
- return ret;
- }
- dev_warn(&pdev->dev,
- "Cannot set consistent DMA highmem bit mask\n");
- }
/*
* Enable the device advanced error reporting. It's not critical to
diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c
index 093dd20057b9..e5f14e20a9ff 100644
--- a/drivers/ntb/hw/intel/ntb_hw_gen1.c
+++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c
@@ -1771,22 +1771,14 @@ static int intel_ntb_init_pci(struct intel_ntb_dev *ndev, struct pci_dev *pdev)
pci_set_master(pdev);
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (rc) {
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (rc)
goto err_dma_mask;
dev_warn(&pdev->dev, "Cannot DMA highmem\n");
}
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (rc) {
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (rc)
- goto err_dma_mask;
- dev_warn(&pdev->dev, "Cannot DMA consistent highmem\n");
- }
-
ndev->self_mmio = pci_iomap(pdev, 0, 0);
if (!ndev->self_mmio) {
rc = -EIO;
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.h b/drivers/ntb/hw/intel/ntb_hw_intel.h
index 05e2335c9596..b233d1c6ba2d 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.h
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.h
@@ -43,9 +43,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>
*/
#ifndef NTB_HW_INTEL_H
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 4a02561cfb96..a9b97ebc71ac 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -304,7 +304,7 @@ static int ntb_transport_bus_probe(struct device *dev)
return rc;
}
-static int ntb_transport_bus_remove(struct device *dev)
+static void ntb_transport_bus_remove(struct device *dev)
{
const struct ntb_transport_client *client;
@@ -312,8 +312,6 @@ static int ntb_transport_bus_remove(struct device *dev)
client->remove(dev);
put_device(dev);
-
- return 0;
}
static struct bus_type ntb_transport_bus = {
diff --git a/drivers/ntb/test/ntb_msi_test.c b/drivers/ntb/test/ntb_msi_test.c
index 7095ecd6223a..4e18e08776c9 100644
--- a/drivers/ntb/test/ntb_msi_test.c
+++ b/drivers/ntb/test/ntb_msi_test.c
@@ -369,8 +369,10 @@ static int ntb_msit_probe(struct ntb_client *client, struct ntb_dev *ntb)
if (ret)
goto remove_dbgfs;
- if (!nm->isr_ctx)
+ if (!nm->isr_ctx) {
+ ret = -ENOMEM;
goto remove_dbgfs;
+ }
ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
diff --git a/drivers/ntb/test/ntb_perf.c b/drivers/ntb/test/ntb_perf.c
index 89df1350fefd..65e1e5cf1b29 100644
--- a/drivers/ntb/test/ntb_perf.c
+++ b/drivers/ntb/test/ntb_perf.c
@@ -598,6 +598,7 @@ static int perf_setup_inbuf(struct perf_peer *peer)
return -ENOMEM;
}
if (!IS_ALIGNED(peer->inbuf_xlat, xlat_align)) {
+ ret = -EINVAL;
dev_err(&perf->ntb->dev, "Unaligned inbuf allocated\n");
goto err_free_inbuf;
}
diff --git a/drivers/ntb/test/ntb_pingpong.c b/drivers/ntb/test/ntb_pingpong.c
index 2164e8492772..8aeca7914050 100644
--- a/drivers/ntb/test/ntb_pingpong.c
+++ b/drivers/ntb/test/ntb_pingpong.c
@@ -187,7 +187,7 @@ static void pp_ping(struct pp_ctx *pp)
static void pp_pong(struct pp_ctx *pp)
{
- u32 msg_data = -1, spad_data = -1;
+ u32 msg_data, spad_data;
int pidx = 0;
/* Read pong data */
diff --git a/drivers/nubus/bus.c b/drivers/nubus/bus.c
index ad3d17c42e23..17fad660032c 100644
--- a/drivers/nubus/bus.c
+++ b/drivers/nubus/bus.c
@@ -29,14 +29,12 @@ static int nubus_device_probe(struct device *dev)
return err;
}
-static int nubus_device_remove(struct device *dev)
+static void nubus_device_remove(struct device *dev)
{
struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
- int err = -ENODEV;
- if (dev->driver && ndrv->remove)
- err = ndrv->remove(to_nubus_board(dev));
- return err;
+ if (ndrv->remove)
+ ndrv->remove(to_nubus_board(dev));
}
struct bus_type nubus_bus_type = {
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index e6aa87043a95..9dc7f3edd42b 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -108,7 +108,7 @@ static int nvdimm_bus_probe(struct device *dev)
return rc;
}
-static int nvdimm_bus_remove(struct device *dev)
+static void nvdimm_bus_remove(struct device *dev)
{
struct nd_device_driver *nd_drv = to_nd_device_driver(dev->driver);
struct module *provider = to_bus_provider(dev);
@@ -123,7 +123,6 @@ static int nvdimm_bus_remove(struct device *dev)
dev_dbg(&nvdimm_bus->dev, "%s.remove(%s)\n", dev->driver->name,
dev_name(dev));
module_put(provider);
- return 0;
}
static void nvdimm_bus_shutdown(struct device *dev)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index dd2019006838..39854d43758b 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -107,6 +107,17 @@ config MTK_EFUSE
This driver can also be built as a module. If so, the module
will be called efuse-mtk.
+config NVMEM_NINTENDO_OTP
+ tristate "Nintendo Wii and Wii U OTP Support"
+ help
+ This is a driver exposing the OTP of a Nintendo Wii or Wii U console.
+
+ This memory contains common and per-console keys, signatures and
+ related data required to access peripherals.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-nintendo-otp.
+
config QCOM_QFPROM
tristate "QCOM QFPROM Support"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index bbea1410240a..dcbbde35b6a8 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -23,6 +23,8 @@ obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
nvmem_lpc18xx_otp-y := lpc18xx_otp.o
obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-mxs-ocotp.o
nvmem-mxs-ocotp-y := mxs-ocotp.o
+obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o
+nvmem-nintendo-otp-y := nintendo-otp.o
obj-$(CONFIG_MTK_EFUSE) += nvmem_mtk-efuse.o
nvmem_mtk-efuse-y := mtk-efuse.o
obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index b3bc30a04ed7..3d87fadaa160 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -824,8 +824,11 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
if (nvmem->nkeepout) {
rval = nvmem_validate_keepouts(nvmem);
- if (rval)
- goto err_put_device;
+ if (rval) {
+ ida_free(&nvmem_ida, nvmem->id);
+ kfree(nvmem);
+ return ERR_PTR(rval);
+ }
}
dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
diff --git a/drivers/nvmem/nintendo-otp.c b/drivers/nvmem/nintendo-otp.c
new file mode 100644
index 000000000000..33961b17f9f1
--- /dev/null
+++ b/drivers/nvmem/nintendo-otp.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Nintendo Wii and Wii U OTP driver
+ *
+ * This is a driver exposing the OTP of a Nintendo Wii or Wii U console.
+ *
+ * This memory contains common and per-console keys, signatures and
+ * related data required to access peripherals.
+ *
+ * Based on reversed documentation from https://wiiubrew.org/wiki/Hardware/OTP
+ *
+ * Copyright (C) 2021 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#define HW_OTPCMD 0
+#define HW_OTPDATA 4
+#define OTP_READ 0x80000000
+#define BANK_SIZE 128
+#define WORD_SIZE 4
+
+struct nintendo_otp_priv {
+ void __iomem *regs;
+};
+
+struct nintendo_otp_devtype_data {
+ const char *name;
+ unsigned int num_banks;
+};
+
+static const struct nintendo_otp_devtype_data hollywood_otp_data = {
+ .name = "wii-otp",
+ .num_banks = 1,
+};
+
+static const struct nintendo_otp_devtype_data latte_otp_data = {
+ .name = "wiiu-otp",
+ .num_banks = 8,
+};
+
+static int nintendo_otp_reg_read(void *context,
+ unsigned int reg, void *_val, size_t bytes)
+{
+ struct nintendo_otp_priv *priv = context;
+ u32 *val = _val;
+ int words = bytes / WORD_SIZE;
+ u32 bank, addr;
+
+ while (words--) {
+ bank = (reg / BANK_SIZE) << 8;
+ addr = (reg / WORD_SIZE) % (BANK_SIZE / WORD_SIZE);
+ iowrite32be(OTP_READ | bank | addr, priv->regs + HW_OTPCMD);
+ *val++ = ioread32be(priv->regs + HW_OTPDATA);
+ reg += WORD_SIZE;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id nintendo_otp_of_table[] = {
+ { .compatible = "nintendo,hollywood-otp", .data = &hollywood_otp_data },
+ { .compatible = "nintendo,latte-otp", .data = &latte_otp_data },
+ {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, nintendo_otp_of_table);
+
+static int nintendo_otp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id =
+ of_match_device(nintendo_otp_of_table, dev);
+ struct resource *res;
+ struct nvmem_device *nvmem;
+ struct nintendo_otp_priv *priv;
+
+ struct nvmem_config config = {
+ .stride = WORD_SIZE,
+ .word_size = WORD_SIZE,
+ .reg_read = nintendo_otp_reg_read,
+ .read_only = true,
+ .root_only = true,
+ };
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->regs))
+ return PTR_ERR(priv->regs);
+
+ if (of_id->data) {
+ const struct nintendo_otp_devtype_data *data = of_id->data;
+ config.name = data->name;
+ config.size = data->num_banks * BANK_SIZE;
+ }
+
+ config.dev = dev;
+ config.priv = priv;
+
+ nvmem = devm_nvmem_register(dev, &config);
+
+ return PTR_ERR_OR_ZERO(nvmem);
+}
+
+static struct platform_driver nintendo_otp_driver = {
+ .probe = nintendo_otp_probe,
+ .driver = {
+ .name = "nintendo-otp",
+ .of_match_table = nintendo_otp_of_table,
+ },
+};
+module_platform_driver(nintendo_otp_driver);
+MODULE_AUTHOR("Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>");
+MODULE_DESCRIPTION("Nintendo Wii and Wii U OTP driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
index 81fbad5e939d..c500d6235bf6 100644
--- a/drivers/nvmem/qfprom.c
+++ b/drivers/nvmem/qfprom.c
@@ -12,6 +12,8 @@
#include <linux/mod_devicetable.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
@@ -139,6 +141,12 @@ static void qfprom_disable_fuse_blowing(const struct qfprom_priv *priv,
{
int ret;
+ writel(old->timer_val, priv->qfpconf + QFPROM_BLOW_TIMER_OFFSET);
+ writel(old->accel_val, priv->qfpconf + QFPROM_ACCEL_OFFSET);
+
+ dev_pm_genpd_set_performance_state(priv->dev, 0);
+ pm_runtime_put(priv->dev);
+
/*
* This may be a shared rail and may be able to run at a lower rate
* when we're not blowing fuses. At the moment, the regulator framework
@@ -159,9 +167,6 @@ static void qfprom_disable_fuse_blowing(const struct qfprom_priv *priv,
"Failed to set clock rate for disable (ignoring)\n");
clk_disable_unprepare(priv->secclk);
-
- writel(old->timer_val, priv->qfpconf + QFPROM_BLOW_TIMER_OFFSET);
- writel(old->accel_val, priv->qfpconf + QFPROM_ACCEL_OFFSET);
}
/**
@@ -212,6 +217,14 @@ static int qfprom_enable_fuse_blowing(const struct qfprom_priv *priv,
goto err_clk_rate_set;
}
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ dev_err(priv->dev, "Failed to enable power-domain\n");
+ goto err_reg_enable;
+ }
+ dev_pm_genpd_set_performance_state(priv->dev, INT_MAX);
+
old->timer_val = readl(priv->qfpconf + QFPROM_BLOW_TIMER_OFFSET);
old->accel_val = readl(priv->qfpconf + QFPROM_ACCEL_OFFSET);
writel(priv->soc_data->qfprom_blow_timer_value,
@@ -221,6 +234,8 @@ static int qfprom_enable_fuse_blowing(const struct qfprom_priv *priv,
return 0;
+err_reg_enable:
+ regulator_disable(priv->vcc);
err_clk_rate_set:
clk_set_rate(priv->secclk, old->clk_rate);
err_clk_prepared:
@@ -320,6 +335,11 @@ static int qfprom_reg_read(void *context,
return 0;
}
+static void qfprom_runtime_disable(void *data)
+{
+ pm_runtime_disable(data);
+}
+
static const struct qfprom_soc_data qfprom_7_8_data = {
.accel_value = 0xD10,
.qfprom_blow_timer_value = 25,
@@ -420,6 +440,11 @@ static int qfprom_probe(struct platform_device *pdev)
econfig.reg_write = qfprom_reg_write;
}
+ pm_runtime_enable(dev);
+ ret = devm_add_action_or_reset(dev, qfprom_runtime_disable, dev);
+ if (ret)
+ return ret;
+
nvmem = devm_nvmem_register(dev, &econfig);
return PTR_ERR_OR_ZERO(nvmem);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 48e941f99558..f720c0d246f2 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -708,9 +708,7 @@ static struct device_node *__of_get_next_child(const struct device_node *node,
return NULL;
next = prev ? prev->sibling : node->child;
- for (; next; next = next->sibling)
- if (of_node_get(next))
- break;
+ of_node_get(next);
of_node_put(prev);
return next;
}
@@ -1821,6 +1819,7 @@ int of_add_property(struct device_node *np, struct property *prop)
return rc;
}
+EXPORT_SYMBOL_GPL(of_add_property);
int __of_remove_property(struct device_node *np, struct property *prop)
{
diff --git a/drivers/of/device.c b/drivers/of/device.c
index c5a9473a5fb1..5b043ee30824 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -5,6 +5,7 @@
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/of_iommu.h>
+#include <linux/of_reserved_mem.h>
#include <linux/dma-direct.h> /* for bus_dma_region */
#include <linux/dma-map-ops.h>
#include <linux/init.h>
@@ -52,6 +53,42 @@ int of_device_add(struct platform_device *ofdev)
return device_add(&ofdev->dev);
}
+static void
+of_dma_set_restricted_buffer(struct device *dev, struct device_node *np)
+{
+ struct device_node *node, *of_node = dev->of_node;
+ int count, i;
+
+ if (!IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL))
+ return;
+
+ count = of_property_count_elems_of_size(of_node, "memory-region",
+ sizeof(u32));
+ /*
+ * If dev->of_node doesn't exist or doesn't contain memory-region, try
+ * the OF node having DMA configuration.
+ */
+ if (count <= 0) {
+ of_node = np;
+ count = of_property_count_elems_of_size(
+ of_node, "memory-region", sizeof(u32));
+ }
+
+ for (i = 0; i < count; i++) {
+ node = of_parse_phandle(of_node, "memory-region", i);
+ /*
+ * There might be multiple memory regions, but only one
+ * restricted-dma-pool region is allowed.
+ */
+ if (of_device_is_compatible(node, "restricted-dma-pool") &&
+ of_device_is_available(node))
+ break;
+ }
+
+ if (i != count && of_reserved_mem_device_init_by_idx(dev, of_node, i))
+ dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n");
+}
+
/**
* of_dma_configure_id - Setup DMA configuration
* @dev: Device to apply DMA configuration
@@ -165,6 +202,9 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
arch_setup_dma_ops(dev, dma_start, size, iommu, coherent);
+ if (!iommu)
+ of_dma_set_restricted_buffer(dev, np);
+
return 0;
}
EXPORT_SYMBOL_GPL(of_dma_configure_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index e0f96e3ef1da..4546572af24b 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -8,6 +8,7 @@
#define pr_fmt(fmt) "OF: fdt: " fmt
+#include <linux/crash_dump.h>
#include <linux/crc32.h>
#include <linux/kernel.h>
#include <linux/initrd.h>
@@ -193,16 +194,12 @@ static void populate_properties(const void *blob,
pp->length = len;
pp->value = pp + 1;
*pprev = pp;
- pprev = &pp->next;
memcpy(pp->value, ps, len - 1);
((char *)pp->value)[len - 1] = 0;
pr_debug("fixed up name for %s -> %s\n",
nodename, (char *)pp->value);
}
}
-
- if (!dryrun)
- *pprev = NULL;
}
static int populate_node(const void *blob,
@@ -479,6 +476,22 @@ void *initial_boot_params __ro_after_init;
static u32 of_fdt_crc32;
+static int __init early_init_dt_reserve_memory_arch(phys_addr_t base,
+ phys_addr_t size, bool nomap)
+{
+ if (nomap) {
+ /*
+ * If the memory is already reserved (by another region), we
+ * should not allow it to be marked nomap.
+ */
+ if (memblock_is_region_reserved(base, size))
+ return -EBUSY;
+
+ return memblock_mark_nomap(base, size);
+ }
+ return memblock_reserve(base, size);
+}
+
/*
* __reserved_mem_reserve_reg() - reserve all memory described in 'reg' property
*/
@@ -585,6 +598,30 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
return 0;
}
+/*
+ * fdt_reserve_elfcorehdr() - reserves memory for elf core header
+ *
+ * This function reserves the memory occupied by an elf core header
+ * described in the device tree. This region contains all the
+ * information about primary kernel's core image and is used by a dump
+ * capture kernel to access the system memory on primary kernel.
+ */
+static void __init fdt_reserve_elfcorehdr(void)
+{
+ if (!IS_ENABLED(CONFIG_CRASH_DUMP) || !elfcorehdr_size)
+ return;
+
+ if (memblock_is_region_reserved(elfcorehdr_addr, elfcorehdr_size)) {
+ pr_warn("elfcorehdr is overlapped\n");
+ return;
+ }
+
+ memblock_reserve(elfcorehdr_addr, elfcorehdr_size);
+
+ pr_info("Reserving %llu KiB of memory at 0x%llx for elfcorehdr\n",
+ elfcorehdr_size >> 10, elfcorehdr_addr);
+}
+
/**
* early_init_fdt_scan_reserved_mem() - create reserved memory regions
*
@@ -610,6 +647,7 @@ void __init early_init_fdt_scan_reserved_mem(void)
of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);
fdt_init_reserved_mem();
+ fdt_reserve_elfcorehdr();
}
/**
@@ -858,7 +896,6 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
return best_data;
}
-#ifdef CONFIG_BLK_DEV_INITRD
static void __early_init_dt_declare_initrd(unsigned long start,
unsigned long end)
{
@@ -884,6 +921,9 @@ static void __init early_init_dt_check_for_initrd(unsigned long node)
int len;
const __be32 *prop;
+ if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD))
+ return;
+
pr_debug("Looking for initrd properties... ");
prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
@@ -902,11 +942,58 @@ static void __init early_init_dt_check_for_initrd(unsigned long node)
pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", start, end);
}
-#else
-static inline void early_init_dt_check_for_initrd(unsigned long node)
+
+/**
+ * early_init_dt_check_for_elfcorehdr - Decode elfcorehdr location from flat
+ * tree
+ * @node: reference to node containing elfcorehdr location ('chosen')
+ */
+static void __init early_init_dt_check_for_elfcorehdr(unsigned long node)
+{
+ const __be32 *prop;
+ int len;
+
+ if (!IS_ENABLED(CONFIG_CRASH_DUMP))
+ return;
+
+ pr_debug("Looking for elfcorehdr property... ");
+
+ prop = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len);
+ if (!prop || (len < (dt_root_addr_cells + dt_root_size_cells)))
+ return;
+
+ elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, &prop);
+ elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+ pr_debug("elfcorehdr_start=0x%llx elfcorehdr_size=0x%llx\n",
+ elfcorehdr_addr, elfcorehdr_size);
+}
+
+static phys_addr_t cap_mem_addr;
+static phys_addr_t cap_mem_size;
+
+/**
+ * early_init_dt_check_for_usable_mem_range - Decode usable memory range
+ * location from flat tree
+ * @node: reference to node containing usable memory range location ('chosen')
+ */
+static void __init early_init_dt_check_for_usable_mem_range(unsigned long node)
{
+ const __be32 *prop;
+ int len;
+
+ pr_debug("Looking for usable-memory-range property... ");
+
+ prop = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len);
+ if (!prop || (len < (dt_root_addr_cells + dt_root_size_cells)))
+ return;
+
+ cap_mem_addr = dt_mem_next_cell(dt_root_addr_cells, &prop);
+ cap_mem_size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+ pr_debug("cap_mem_start=%pa cap_mem_size=%pa\n", &cap_mem_addr,
+ &cap_mem_size);
}
-#endif /* CONFIG_BLK_DEV_INITRD */
#ifdef CONFIG_SERIAL_EARLYCON
@@ -1033,7 +1120,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
if (!hotpluggable)
continue;
- if (early_init_dt_mark_hotplug_memory_arch(base, size))
+ if (memblock_mark_hotplug(base, size))
pr_warn("failed to mark hotplug range 0x%llx - 0x%llx\n",
base, base + size);
}
@@ -1055,6 +1142,8 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
return 0;
early_init_dt_check_for_initrd(node);
+ early_init_dt_check_for_elfcorehdr(node);
+ early_init_dt_check_for_usable_mem_range(node);
/* Retrieve command line */
p = of_get_flat_dt_prop(node, "bootargs", &l);
@@ -1146,27 +1235,6 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
memblock_add(base, size);
}
-int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size)
-{
- return memblock_mark_hotplug(base, size);
-}
-
-int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
- phys_addr_t size, bool nomap)
-{
- if (nomap) {
- /*
- * If the memory is already reserved (by another region), we
- * should not allow it to be marked nomap.
- */
- if (memblock_is_region_reserved(base, size))
- return -EBUSY;
-
- return memblock_mark_nomap(base, size);
- }
- return memblock_reserve(base, size);
-}
-
static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
{
void *ptr = memblock_alloc(size, align);
@@ -1199,16 +1267,19 @@ void __init early_init_dt_scan_nodes(void)
{
int rc = 0;
+ /* Initialize {size,address}-cells info */
+ of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
/* Retrieve various information from the /chosen node */
rc = of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
if (!rc)
pr_warn("No chosen node found, continuing without\n");
- /* Initialize {size,address}-cells info */
- of_scan_flat_dt(early_init_dt_scan_root, NULL);
-
/* Setup memory, calling early_init_dt_add_memory_arch */
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+ /* Handle linux,usable-memory-range property */
+ memblock_cap_memory_range(cap_mem_addr, cap_mem_size);
}
bool __init early_init_dt_scan(void *params)
diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c
index f335d941a716..761fd870d1db 100644
--- a/drivers/of/kexec.c
+++ b/drivers/of/kexec.c
@@ -18,14 +18,6 @@
#include <linux/random.h>
#include <linux/types.h>
-/* relevant device tree properties */
-#define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr"
-#define FDT_PROP_MEM_RANGE "linux,usable-memory-range"
-#define FDT_PROP_INITRD_START "linux,initrd-start"
-#define FDT_PROP_INITRD_END "linux,initrd-end"
-#define FDT_PROP_BOOTARGS "bootargs"
-#define FDT_PROP_KASLR_SEED "kaslr-seed"
-#define FDT_PROP_RNG_SEED "rng-seed"
#define RNG_SEED_SIZE 128
/*
@@ -310,10 +302,10 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
goto out;
}
- ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KEXEC_ELFHDR);
+ ret = fdt_delprop(fdt, chosen_node, "linux,elfcorehdr");
if (ret && ret != -FDT_ERR_NOTFOUND)
goto out;
- ret = fdt_delprop(fdt, chosen_node, FDT_PROP_MEM_RANGE);
+ ret = fdt_delprop(fdt, chosen_node, "linux,usable-memory-range");
if (ret && ret != -FDT_ERR_NOTFOUND)
goto out;
@@ -347,12 +339,12 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
/* add initrd-* */
if (initrd_load_addr) {
- ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_START,
+ ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-start",
initrd_load_addr);
if (ret)
goto out;
- ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_END,
+ ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-end",
initrd_load_addr + initrd_len);
if (ret)
goto out;
@@ -362,11 +354,11 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
goto out;
} else {
- ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_START);
+ ret = fdt_delprop(fdt, chosen_node, "linux,initrd-start");
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
- ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_END);
+ ret = fdt_delprop(fdt, chosen_node, "linux,initrd-end");
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
}
@@ -374,8 +366,7 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
if (image->type == KEXEC_TYPE_CRASH) {
/* add linux,elfcorehdr */
ret = fdt_appendprop_addrrange(fdt, 0, chosen_node,
- FDT_PROP_KEXEC_ELFHDR,
- image->elf_load_addr,
+ "linux,elfcorehdr", image->elf_load_addr,
image->elf_headers_sz);
if (ret)
goto out;
@@ -391,8 +382,7 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
/* add linux,usable-memory-range */
ret = fdt_appendprop_addrrange(fdt, 0, chosen_node,
- FDT_PROP_MEM_RANGE,
- crashk_res.start,
+ "linux,usable-memory-range", crashk_res.start,
crashk_res.end - crashk_res.start + 1);
if (ret)
goto out;
@@ -400,17 +390,17 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
/* add bootargs */
if (cmdline) {
- ret = fdt_setprop_string(fdt, chosen_node, FDT_PROP_BOOTARGS, cmdline);
+ ret = fdt_setprop_string(fdt, chosen_node, "bootargs", cmdline);
if (ret)
goto out;
} else {
- ret = fdt_delprop(fdt, chosen_node, FDT_PROP_BOOTARGS);
+ ret = fdt_delprop(fdt, chosen_node, "bootargs");
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
}
/* add kaslr-seed */
- ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KASLR_SEED);
+ ret = fdt_delprop(fdt, chosen_node, "kaslr-seed");
if (ret == -FDT_ERR_NOTFOUND)
ret = 0;
else if (ret)
@@ -419,26 +409,26 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
if (rng_is_initialized()) {
u64 seed = get_random_u64();
- ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_KASLR_SEED, seed);
+ ret = fdt_setprop_u64(fdt, chosen_node, "kaslr-seed", seed);
if (ret)
goto out;
} else {
pr_notice("RNG is not initialised: omitting \"%s\" property\n",
- FDT_PROP_KASLR_SEED);
+ "kaslr-seed");
}
/* add rng-seed */
if (rng_is_initialized()) {
void *rng_seed;
- ret = fdt_setprop_placeholder(fdt, chosen_node, FDT_PROP_RNG_SEED,
+ ret = fdt_setprop_placeholder(fdt, chosen_node, "rng-seed",
RNG_SEED_SIZE, &rng_seed);
if (ret)
goto out;
get_random_bytes(rng_seed, RNG_SEED_SIZE);
} else {
pr_notice("RNG is not initialised: omitting \"%s\" property\n",
- FDT_PROP_RNG_SEED);
+ "rng-seed");
}
ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
diff --git a/drivers/of/kobj.c b/drivers/of/kobj.c
index a32e60b024b8..6675b5e56960 100644
--- a/drivers/of/kobj.c
+++ b/drivers/of/kobj.c
@@ -119,7 +119,7 @@ int __of_attach_node_sysfs(struct device_node *np)
struct property *pp;
int rc;
- if (!of_kset)
+ if (!IS_ENABLED(CONFIG_SYSFS) || !of_kset)
return 0;
np->kobj.kset = of_kset;
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index fd3964d24224..59c1390cdf42 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -33,18 +33,22 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
phys_addr_t *res_base)
{
phys_addr_t base;
+ int err = 0;
end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
align = !align ? SMP_CACHE_BYTES : align;
- base = memblock_find_in_range(start, end, size, align);
+ base = memblock_phys_alloc_range(size, align, start, end);
if (!base)
return -ENOMEM;
*res_base = base;
- if (nomap)
- return memblock_mark_nomap(base, size);
+ if (nomap) {
+ err = memblock_mark_nomap(base, size);
+ if (err)
+ memblock_free(base, size);
+ }
- return memblock_reserve(base, size);
+ return err;
}
/*
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 6c028632f425..0c0dc2e369c0 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1287,6 +1287,11 @@ DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL)
DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
DEFINE_SIMPLE_PROP(remote_endpoint, "remote-endpoint", NULL)
+DEFINE_SIMPLE_PROP(pwms, "pwms", "#pwm-cells")
+DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells")
+DEFINE_SIMPLE_PROP(leds, "leds", NULL)
+DEFINE_SIMPLE_PROP(backlight, "backlight", NULL)
+DEFINE_SIMPLE_PROP(phy_handle, "phy-handle", NULL)
DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
@@ -1371,6 +1376,11 @@ static const struct supplier_bindings of_supplier_bindings[] = {
{ .parse_prop = parse_pinctrl7, },
{ .parse_prop = parse_pinctrl8, },
{ .parse_prop = parse_remote_endpoint, .node_not_dev = true, },
+ { .parse_prop = parse_pwms, },
+ { .parse_prop = parse_resets, },
+ { .parse_prop = parse_leds, },
+ { .parse_prop = parse_backlight, },
+ { .parse_prop = parse_phy_handle, },
{ .parse_prop = parse_gpio_compat, },
{ .parse_prop = parse_interrupts, },
{ .parse_prop = parse_regulators, },
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index b5f9ee81a46c..059566f54429 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -111,29 +111,29 @@
#define CMD_TLB_PURGE 33 /* IO_COMMAND to Purge I/O TLB entry */
struct ioa_registers {
- /* Runway Supervisory Set */
- int32_t unused1[12];
- uint32_t io_command; /* Offset 12 */
- uint32_t io_status; /* Offset 13 */
- uint32_t io_control; /* Offset 14 */
- int32_t unused2[1];
-
- /* Runway Auxiliary Register Set */
- uint32_t io_err_resp; /* Offset 0 */
- uint32_t io_err_info; /* Offset 1 */
- uint32_t io_err_req; /* Offset 2 */
- uint32_t io_err_resp_hi; /* Offset 3 */
- uint32_t io_tlb_entry_m; /* Offset 4 */
- uint32_t io_tlb_entry_l; /* Offset 5 */
- uint32_t unused3[1];
- uint32_t io_pdir_base; /* Offset 7 */
- uint32_t io_io_low_hv; /* Offset 8 */
- uint32_t io_io_high_hv; /* Offset 9 */
- uint32_t unused4[1];
- uint32_t io_chain_id_mask; /* Offset 11 */
- uint32_t unused5[2];
- uint32_t io_io_low; /* Offset 14 */
- uint32_t io_io_high; /* Offset 15 */
+ /* Runway Supervisory Set */
+ int32_t unused1[12];
+ uint32_t io_command; /* Offset 12 */
+ uint32_t io_status; /* Offset 13 */
+ uint32_t io_control; /* Offset 14 */
+ int32_t unused2[1];
+
+ /* Runway Auxiliary Register Set */
+ uint32_t io_err_resp; /* Offset 0 */
+ uint32_t io_err_info; /* Offset 1 */
+ uint32_t io_err_req; /* Offset 2 */
+ uint32_t io_err_resp_hi; /* Offset 3 */
+ uint32_t io_tlb_entry_m; /* Offset 4 */
+ uint32_t io_tlb_entry_l; /* Offset 5 */
+ uint32_t unused3[1];
+ uint32_t io_pdir_base; /* Offset 7 */
+ uint32_t io_io_low_hv; /* Offset 8 */
+ uint32_t io_io_high_hv; /* Offset 9 */
+ uint32_t unused4[1];
+ uint32_t io_chain_id_mask; /* Offset 11 */
+ uint32_t unused5[2];
+ uint32_t io_io_low; /* Offset 14 */
+ uint32_t io_io_high; /* Offset 15 */
};
/*
@@ -198,7 +198,7 @@ struct ioa_registers {
** In order for a Runway address to reside within GSC+ extended address space:
** Runway Address [0:7] must identically compare to 8'b11111111
** Runway Address [8:11] must be equal to IO_IO_LOW(_HV)[16:19]
-** Runway Address [12:23] must be greater than or equal to
+** Runway Address [12:23] must be greater than or equal to
** IO_IO_LOW(_HV)[20:31] and less than IO_IO_HIGH(_HV)[20:31].
** Runway Address [24:39] is not used in the comparison.
**
@@ -226,10 +226,10 @@ struct ioc {
struct ioa_registers __iomem *ioc_regs; /* I/O MMU base address */
u8 *res_map; /* resource map, bit == pdir entry */
u64 *pdir_base; /* physical base address */
- u32 pdir_size; /* bytes, function of IOV Space size */
- u32 res_hint; /* next available IOVP -
+ u32 pdir_size; /* bytes, function of IOV Space size */
+ u32 res_hint; /* next available IOVP -
circular search */
- u32 res_size; /* size of resource map in bytes */
+ u32 res_size; /* size of resource map in bytes */
spinlock_t res_lock;
#ifdef CCIO_COLLECT_STATS
@@ -249,7 +249,7 @@ struct ioc {
unsigned short cujo20_bug;
/* STUFF We don't need in performance path */
- u32 chainid_shift; /* specify bit location of chain_id */
+ u32 chainid_shift; /* specify bit location of chain_id */
struct ioc *next; /* Linked list of discovered iocs */
const char *name; /* device name from firmware */
unsigned int hw_path; /* the hardware path this ioc is associatd with */
@@ -293,7 +293,7 @@ static int ioc_count;
** cause the kernel to panic anyhow.
*/
#define CCIO_SEARCH_LOOP(ioc, res_idx, mask, size) \
- for(; res_ptr < res_end; ++res_ptr) { \
+ for (; res_ptr < res_end; ++res_ptr) { \
int ret;\
unsigned int idx;\
idx = (unsigned int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \
@@ -309,9 +309,9 @@ static int ioc_count;
#define CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, size) \
u##size *res_ptr = (u##size *)&((ioc)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \
u##size *res_end = (u##size *)&(ioc)->res_map[ioa->res_size]; \
- CCIO_SEARCH_LOOP(ioc, res_idx, mask, size); \
- res_ptr = (u##size *)&(ioc)->res_map[0]; \
- CCIO_SEARCH_LOOP(ioa, res_idx, mask, size);
+ CCIO_SEARCH_LOOP(ioc, res_idx, mask, size); \
+ res_ptr = (u##size *)&(ioc)->res_map[0]; \
+ CCIO_SEARCH_LOOP(ioa, res_idx, mask, size);
/*
** Find available bit in this ioa's resource map.
@@ -348,9 +348,9 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
BUG_ON(pages_needed == 0);
BUG_ON((pages_needed * IOVP_SIZE) > DMA_CHUNK_SIZE);
-
- DBG_RES("%s() size: %d pages_needed %d\n",
- __func__, size, pages_needed);
+
+ DBG_RES("%s() size: %d pages_needed %d\n",
+ __func__, size, pages_needed);
/*
** "seek and ye shall find"...praying never hurts either...
@@ -416,7 +416,7 @@ resource_found:
#define CCIO_FREE_MAPPINGS(ioc, res_idx, mask, size) \
u##size *res_ptr = (u##size *)&((ioc)->res_map[res_idx]); \
BUG_ON((*res_ptr & mask) != mask); \
- *res_ptr &= ~(mask);
+ *res_ptr &= ~(mask);
/**
* ccio_free_range - Free pages from the ioc's resource map.
@@ -518,9 +518,9 @@ typedef unsigned long space_t;
** when it passes in BIDIRECTIONAL flag.
*/
static u32 hint_lookup[] = {
- [PCI_DMA_BIDIRECTIONAL] = HINT_STOP_MOST | HINT_SAFE_DMA | IOPDIR_VALID,
- [PCI_DMA_TODEVICE] = HINT_STOP_MOST | HINT_PREFETCH | IOPDIR_VALID,
- [PCI_DMA_FROMDEVICE] = HINT_STOP_MOST | IOPDIR_VALID,
+ [DMA_BIDIRECTIONAL] = HINT_STOP_MOST | HINT_SAFE_DMA | IOPDIR_VALID,
+ [DMA_TO_DEVICE] = HINT_STOP_MOST | HINT_PREFETCH | IOPDIR_VALID,
+ [DMA_FROM_DEVICE] = HINT_STOP_MOST | IOPDIR_VALID,
};
/**
@@ -845,7 +845,7 @@ static void *
ccio_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag,
unsigned long attrs)
{
- void *ret;
+ void *ret;
#if 0
/* GRANT Need to establish hierarchy for non-PCI devs as well
** and then provide matching gsc_map_xxx() functions for them as well.
@@ -856,11 +856,11 @@ ccio_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag,
return 0;
}
#endif
- ret = (void *) __get_free_pages(flag, get_order(size));
+ ret = (void *) __get_free_pages(flag, get_order(size));
if (ret) {
memset(ret, 0, size);
- *dma_handle = ccio_map_single(dev, ret, size, PCI_DMA_BIDIRECTIONAL);
+ *dma_handle = ccio_map_single(dev, ret, size, DMA_BIDIRECTIONAL);
}
return ret;
@@ -918,7 +918,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
BUG_ON(!dev);
ioc = GET_IOC(dev);
if (!ioc)
- return 0;
+ return -EINVAL;
DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
@@ -1022,8 +1022,8 @@ static const struct dma_map_ops ccio_ops = {
.free = ccio_free,
.map_page = ccio_map_page,
.unmap_page = ccio_unmap_page,
- .map_sg = ccio_map_sg,
- .unmap_sg = ccio_unmap_sg,
+ .map_sg = ccio_map_sg,
+ .unmap_sg = ccio_unmap_sg,
.get_sgtable = dma_common_get_sgtable,
.alloc_pages = dma_common_alloc_pages,
.free_pages = dma_common_free_pages,
@@ -1080,7 +1080,7 @@ static int ccio_proc_info(struct seq_file *m, void *p)
max = ioc->usingle_pages - ioc->usg_pages;
seq_printf(m, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
min, max, (int)((max * 1000)/min));
-
+
seq_printf(m, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
ioc->msg_calls, ioc->msg_pages,
(int)((ioc->msg_pages * 1000)/ioc->msg_calls));
@@ -1169,7 +1169,7 @@ void __init ccio_cujo20_fixup(struct parisc_device *cujo, u32 iovp)
idx = PDIR_INDEX(iovp) >> 3;
while (idx < ioc->res_size) {
- res_ptr[idx] |= 0xff;
+ res_ptr[idx] |= 0xff;
idx += PDIR_INDEX(CUJO_20_STEP) >> 3;
}
}
@@ -1297,7 +1297,7 @@ ccio_ioc_init(struct ioc *ioc)
DBG_INIT(" base %p\n", ioc->pdir_base);
/* resource map size dictated by pdir_size */
- ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3;
+ ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3;
DBG_INIT("%s() res_size 0x%x\n", __func__, ioc->res_size);
ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL,
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 36c6613f7a36..cf91cb024be3 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -250,14 +250,14 @@ static int __init led_create_procfs(void)
if (!lcd_no_led_support)
{
- ent = proc_create_data("led", S_IRUGO|S_IWUSR, proc_pdc_root,
+ ent = proc_create_data("led", 0644, proc_pdc_root,
&led_proc_ops, (void *)LED_NOLCD); /* LED */
if (!ent) return -1;
}
if (led_type == LED_HASLCD)
{
- ent = proc_create_data("lcd", S_IRUGO|S_IWUSR, proc_pdc_root,
+ ent = proc_create_data("lcd", 0644, proc_pdc_root,
&led_proc_ops, (void *)LED_HASLCD); /* LCD */
if (!ent) return -1;
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index dce4cdf786cd..e60690d38d67 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -947,7 +947,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
ioc = GET_IOC(dev);
if (!ioc)
- return 0;
+ return -EINVAL;
/* Fast path single entry scatterlists. */
if (nents == 1) {
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
index 2c11bd3fe1fd..17061f1df0f4 100644
--- a/drivers/parport/ieee1284_ops.c
+++ b/drivers/parport/ieee1284_ops.c
@@ -518,7 +518,7 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port,
goto out;
/* Yield the port for a while. */
- if (count && dev->port->irq != PARPORT_IRQ_NONE) {
+ if (dev->port->irq != PARPORT_IRQ_NONE) {
parport_release (dev);
schedule_timeout_interruptible(msecs_to_jiffies(40));
parport_claim_or_block (dev);
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 1e43b3f399a8..0dcc497b0449 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -378,7 +378,7 @@ static int __init parport_init_chip(struct parisc_device *dev)
return 0;
}
-static int __exit parport_remove_chip(struct parisc_device *dev)
+static void __exit parport_remove_chip(struct parisc_device *dev)
{
struct parport *p = dev_get_drvdata(&dev->dev);
if (p) {
@@ -390,14 +390,12 @@ static int __exit parport_remove_chip(struct parisc_device *dev)
if (p->irq != PARPORT_IRQ_NONE)
free_irq(p->irq, p);
if (priv->dma_buf)
- pci_free_consistent(priv->dev, PAGE_SIZE,
- priv->dma_buf,
- priv->dma_handle);
+ dma_free_coherent(&priv->dev->dev, PAGE_SIZE,
+ priv->dma_buf, priv->dma_handle);
kfree (p->private_data);
parport_put_port(p);
kfree (ops); /* hope no-one cached it */
}
- return 0;
}
static const struct parisc_device_id parport_tbl[] __initconst = {
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 96b888bb49c6..9f5d784cd95d 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -606,12 +606,15 @@ static int parport_register(struct pci_dev *dev, const struct pci_device_id *id)
"hi" as an offset (see SYBA
def.) */
/* TODO: test if sharing interrupts works */
- irq = dev->irq;
- if (irq == IRQ_NONE) {
+ irq = pci_irq_vector(dev, 0);
+ if (irq < 0)
+ return irq;
+ if (irq == 0)
+ irq = PARPORT_IRQ_NONE;
+ if (irq == PARPORT_IRQ_NONE) {
dev_dbg(&dev->dev,
"PCI parallel port detected: I/O at %#lx(%#lx)\n",
io_lo, io_hi);
- irq = PARPORT_IRQ_NONE;
} else {
dev_dbg(&dev->dev,
"PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n",
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
index e9289d10f822..502eb79cd551 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -387,17 +387,14 @@ static int pci_epf_device_probe(struct device *dev)
return driver->probe(epf);
}
-static int pci_epf_device_remove(struct device *dev)
+static void pci_epf_device_remove(struct device *dev)
{
- int ret = 0;
struct pci_epf *epf = to_pci_epf(dev);
struct pci_epf_driver *driver = to_pci_epf_driver(dev->driver);
if (driver->remove)
- ret = driver->remove(epf);
+ driver->remove(epf);
epf->driver = NULL;
-
- return ret;
}
static struct bus_type pci_epf_bus_type = {
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 3a72352aa5cf..2761ab86490d 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -136,7 +136,7 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
struct pci_dev *dev)
{
struct pci_dynid *dynid;
- const struct pci_device_id *found_id = NULL;
+ const struct pci_device_id *found_id = NULL, *ids;
/* When driver_override is set, only bind to the matching driver */
if (dev->driver_override && strcmp(dev->driver_override, drv->name))
@@ -152,14 +152,28 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
}
spin_unlock(&drv->dynids.lock);
- if (!found_id)
- found_id = pci_match_id(drv->id_table, dev);
+ if (found_id)
+ return found_id;
- /* driver_override will always match, send a dummy id */
- if (!found_id && dev->driver_override)
- found_id = &pci_device_id_any;
+ for (ids = drv->id_table; (found_id = pci_match_id(ids, dev));
+ ids = found_id + 1) {
+ /*
+ * The match table is split based on driver_override.
+ * In case override_only was set, enforce driver_override
+ * matching.
+ */
+ if (found_id->override_only) {
+ if (dev->driver_override)
+ return found_id;
+ } else {
+ return found_id;
+ }
+ }
- return found_id;
+ /* driver_override will always match, send a dummy id */
+ if (dev->driver_override)
+ return &pci_device_id_any;
+ return NULL;
}
/**
@@ -440,7 +454,7 @@ static int pci_device_probe(struct device *dev)
return error;
}
-static int pci_device_remove(struct device *dev)
+static void pci_device_remove(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver *drv = pci_dev->driver;
@@ -476,7 +490,6 @@ static int pci_device_remove(struct device *dev)
*/
pci_dev_put(pci_dev);
- return 0;
}
static void pci_device_shutdown(struct device *dev)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7bbf2673c7f2..b70f61fbcd4b 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -965,7 +965,7 @@ void pci_create_legacy_files(struct pci_bus *b)
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
b->legacy_io->mmap = pci_mmap_legacy_io;
- b->legacy_io->mapping = iomem_get_mapping();
+ b->legacy_io->f_mapping = iomem_get_mapping;
pci_adjust_legacy_attr(b, pci_mmap_io);
error = device_create_bin_file(&b->dev, b->legacy_io);
if (error)
@@ -978,7 +978,7 @@ void pci_create_legacy_files(struct pci_bus *b)
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = 0600;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
- b->legacy_mem->mapping = iomem_get_mapping();
+ b->legacy_mem->f_mapping = iomem_get_mapping;
pci_adjust_legacy_attr(b, pci_mmap_mem);
error = device_create_bin_file(&b->dev, b->legacy_mem);
if (error)
@@ -1195,7 +1195,7 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
}
}
if (res_attr->mmap)
- res_attr->mapping = iomem_get_mapping();
+ res_attr->f_mapping = iomem_get_mapping;
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = 0600;
res_attr->size = pci_resource_len(pdev, num);
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index b7a8f3a1921f..2156c632524d 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -115,7 +115,7 @@ static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
struct xen_pci_op *active_op = &pdev->sh_info->op;
unsigned long irq_flags;
evtchn_port_t port = pdev->evtchn;
- unsigned irq = pdev->irq;
+ unsigned int irq = pdev->irq;
s64 ns, ns_timeout;
spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
@@ -153,10 +153,10 @@ static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
}
/*
- * We might lose backend service request since we
- * reuse same evtchn with pci_conf backend response. So re-schedule
- * aer pcifront service.
- */
+ * We might lose backend service request since we
+ * reuse same evtchn with pci_conf backend response. So re-schedule
+ * aer pcifront service.
+ */
if (test_bit(_XEN_PCIB_active,
(unsigned long *)&pdev->sh_info->flags)) {
dev_err(&pdev->xdev->dev,
@@ -414,7 +414,8 @@ static int pcifront_scan_bus(struct pcifront_device *pdev,
struct pci_dev *d;
unsigned int devfn;
- /* Scan the bus for functions and add.
+ /*
+ * Scan the bus for functions and add.
* We omit handling of PCI bridge attachment because pciback prevents
* bridges from being exported.
*/
@@ -492,8 +493,10 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
list_add(&bus_entry->list, &pdev->root_buses);
- /* pci_scan_root_bus skips devices which do not have a
- * devfn==0. The pcifront_scan_bus enumerates all devfn. */
+ /*
+ * pci_scan_root_bus skips devices which do not have a
+ * devfn==0. The pcifront_scan_bus enumerates all devfn.
+ */
err = pcifront_scan_bus(pdev, domain, bus, b);
/* Claim resources before going "live" with our devices */
@@ -651,8 +654,10 @@ static void pcifront_do_aer(struct work_struct *data)
pci_channel_state_t state =
(pci_channel_state_t)pdev->sh_info->aer_op.err;
- /*If a pci_conf op is in progress,
- we have to wait until it is done before service aer op*/
+ /*
+ * If a pci_conf op is in progress, we have to wait until it is done
+ * before service aer op
+ */
dev_dbg(&pdev->xdev->dev,
"pcifront service aer bus %x devfn %x\n",
pdev->sh_info->aer_op.bus, pdev->sh_info->aer_op.devfn);
@@ -676,6 +681,7 @@ static void pcifront_do_aer(struct work_struct *data)
static irqreturn_t pcifront_handler_aer(int irq, void *dev)
{
struct pcifront_device *pdev = dev;
+
schedule_pcifront_aer_op(pdev);
return IRQ_HANDLED;
}
@@ -693,7 +699,7 @@ static int pcifront_connect_and_init_dma(struct pcifront_device *pdev)
spin_unlock(&pcifront_dev_lock);
- if (!err && !is_swiotlb_active()) {
+ if (!err && !is_swiotlb_active(&pdev->xdev->dev)) {
err = pci_xen_swiotlb_init_late();
if (err)
dev_err(&pdev->xdev->dev, "Could not setup SWIOTLB!\n");
@@ -1027,6 +1033,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
/* Find devices being detached and remove them. */
for (i = 0; i < num_devs; i++) {
int l, state;
+
l = snprintf(str, sizeof(str), "state-%d", i);
if (unlikely(l >= (sizeof(str) - 1))) {
err = -ENOMEM;
@@ -1078,7 +1085,7 @@ out:
return err;
}
-static void __ref pcifront_backend_changed(struct xenbus_device *xdev,
+static void pcifront_backend_changed(struct xenbus_device *xdev,
enum xenbus_state be_state)
{
struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev);
@@ -1137,6 +1144,7 @@ out:
static int pcifront_xenbus_remove(struct xenbus_device *xdev)
{
struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev);
+
if (pdev)
free_pdev(pdev);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index bd81aa64d011..5bd1b80424e7 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -350,7 +350,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
return;
}
-static int pcmcia_device_remove(struct device *dev)
+static void pcmcia_device_remove(struct device *dev)
{
struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
@@ -389,8 +389,6 @@ static int pcmcia_device_remove(struct device *dev)
/* references from pcmcia_device_probe */
pcmcia_put_dev(p_dev);
module_put(p_drv->owner);
-
- return 0;
}
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 7dd35f1b9cc5..82b63e60c5a2 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -37,7 +37,7 @@ config PHY_LPC18XX_USB_OTG
config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver"
- depends on MACH_PISTACHIO
+ depends on MIPS || COMPILE_TEST
select GENERIC_PHY
help
Enable this to support the USB2.0 PHY on the IMG Pistachio SoC.
diff --git a/drivers/phy/amlogic/phy-meson8b-usb2.c b/drivers/phy/amlogic/phy-meson8b-usb2.c
index 03c061dd5f0d..cf10bed40528 100644
--- a/drivers/phy/amlogic/phy-meson8b-usb2.c
+++ b/drivers/phy/amlogic/phy-meson8b-usb2.c
@@ -219,6 +219,10 @@ static int phy_meson8b_usb2_power_off(struct phy *phy)
clk_disable_unprepare(priv->clk_usb);
clk_disable_unprepare(priv->clk_usb_general);
+ /* power off the PHY by putting it into reset mode */
+ regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET,
+ REG_CTRL_POWER_ON_RESET);
+
return 0;
}
@@ -273,8 +277,8 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev)
phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops);
if (IS_ERR(phy)) {
- dev_err(&pdev->dev, "failed to create PHY\n");
- return PTR_ERR(phy);
+ return dev_err_probe(&pdev->dev, PTR_ERR(phy),
+ "failed to create PHY\n");
}
phy_set_drvdata(phy, priv);
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c
index 0477e7beebbf..415ace64adc5 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -24,13 +24,15 @@
#include <linux/reset.h>
#include <linux/regmap.h>
-#define REF_CLK_19_2MHz 19200000
-#define REF_CLK_25MHz 25000000
+#define REF_CLK_19_2MHZ 19200000
+#define REF_CLK_25MHZ 25000000
+#define REF_CLK_100MHZ 100000000
#define MAX_NUM_LANES 4
#define DEFAULT_MAX_BIT_RATE 8100 /* in Mbps */
#define NUM_SSC_MODE 3
+#define NUM_REF_CLK 3
#define NUM_PHY_TYPE 6
#define POLL_TIMEOUT_US 5000
@@ -49,6 +51,10 @@
#define TORRENT_PHY_PCS_COMMON_OFFSET(block_offset) \
(0xC000 << (block_offset))
+#define TORRENT_PHY_PCS_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \
+ ((0xD000 << (block_offset)) + \
+ (((ln) << 8) << (reg_offset)))
+
#define TORRENT_PHY_PMA_COMMON_OFFSET(block_offset) \
(0xE000 << (block_offset))
@@ -101,6 +107,7 @@
#define CMN_PLL0_FRACDIVH_M0 0x0092U
#define CMN_PLL0_HIGH_THR_M0 0x0093U
#define CMN_PLL0_DSM_DIAG_M0 0x0094U
+#define CMN_PLL0_DSM_FBH_OVRD_M0 0x0095U
#define CMN_PLL0_SS_CTRL1_M0 0x0098U
#define CMN_PLL0_SS_CTRL2_M0 0x0099U
#define CMN_PLL0_SS_CTRL3_M0 0x009AU
@@ -220,6 +227,9 @@
#define PHY_PIPE_USB3_GEN2_POST_CFG0 0x0022U
#define PHY_PIPE_USB3_GEN2_POST_CFG1 0x0023U
+/* PHY PCS lane registers */
+#define PHY_PCS_ISO_LINK_CTRL 0x000BU
+
/* PHY PMA common registers */
#define PHY_PMA_CMN_CTRL1 0x0000U
#define PHY_PMA_CMN_CTRL2 0x0001U
@@ -244,6 +254,9 @@ static const struct reg_field phy_pma_pll_raw_ctrl =
static const struct reg_field phy_reset_ctrl =
REG_FIELD(PHY_RESET, 8, 8);
+static const struct reg_field phy_pcs_iso_link_ctrl_1 =
+ REG_FIELD(PHY_PCS_ISO_LINK_CTRL, 1, 1);
+
static const struct reg_field phy_pipe_cmn_ctrl1_0 = REG_FIELD(PHY_PIPE_CMN_CTRL1, 0, 0);
#define REFCLK_OUT_NUM_CMN_CONFIG 5
@@ -273,6 +286,12 @@ enum cdns_torrent_phy_type {
TYPE_USB,
};
+enum cdns_torrent_ref_clk {
+ CLK_19_2_MHZ,
+ CLK_25_MHZ,
+ CLK_100_MHZ
+};
+
enum cdns_torrent_ssc_mode {
NO_SSC,
EXTERNAL_SSC,
@@ -296,7 +315,7 @@ struct cdns_torrent_phy {
struct reset_control *apb_rst;
struct device *dev;
struct clk *clk;
- unsigned long ref_clk_rate;
+ enum cdns_torrent_ref_clk ref_clk_rate;
struct cdns_torrent_inst phys[MAX_NUM_LANES];
int nsubnodes;
const struct cdns_torrent_data *init_data;
@@ -306,12 +325,14 @@ struct cdns_torrent_phy {
struct regmap *regmap_phy_pma_common_cdb;
struct regmap *regmap_tx_lane_cdb[MAX_NUM_LANES];
struct regmap *regmap_rx_lane_cdb[MAX_NUM_LANES];
+ struct regmap *regmap_phy_pcs_lane_cdb[MAX_NUM_LANES];
struct regmap *regmap_dptx_phy_reg;
struct regmap_field *phy_pll_cfg;
struct regmap_field *phy_pma_cmn_ctrl_1;
struct regmap_field *phy_pma_cmn_ctrl_2;
struct regmap_field *phy_pma_pll_raw_ctrl;
struct regmap_field *phy_reset_ctrl;
+ struct regmap_field *phy_pcs_iso_link_ctrl_1[MAX_NUM_LANES];
struct clk *clks[CDNS_TORRENT_REFCLK_DRIVER + 1];
struct clk_onecell_data clk_data;
};
@@ -333,57 +354,6 @@ struct cdns_torrent_derived_refclk {
#define to_cdns_torrent_derived_refclk(_hw) \
container_of(_hw, struct cdns_torrent_derived_refclk, hw)
-static int cdns_torrent_phy_init(struct phy *phy);
-static int cdns_torrent_dp_init(struct phy *phy);
-static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy,
- u32 num_lanes);
-static
-int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy);
-static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy,
- struct cdns_torrent_inst *inst);
-static
-void cdns_torrent_dp_pma_cmn_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy);
-static
-void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy,
- u32 rate, bool ssc);
-static
-void cdns_torrent_dp_pma_cmn_cfg_25mhz(struct cdns_torrent_phy *cdns_phy);
-static
-void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy,
- u32 rate, bool ssc);
-static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy,
- unsigned int lane);
-static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
- u32 rate, u32 num_lanes);
-static int cdns_torrent_dp_configure(struct phy *phy,
- union phy_configure_opts *opts);
-static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
- u32 num_lanes,
- enum phy_powerstate powerstate);
-static int cdns_torrent_phy_on(struct phy *phy);
-static int cdns_torrent_phy_off(struct phy *phy);
-
-static const struct phy_ops cdns_torrent_phy_ops = {
- .init = cdns_torrent_phy_init,
- .configure = cdns_torrent_dp_configure,
- .power_on = cdns_torrent_phy_on,
- .power_off = cdns_torrent_phy_off,
- .owner = THIS_MODULE,
-};
-
-static int cdns_torrent_noop_phy_on(struct phy *phy)
-{
- /* Give 5ms to 10ms delay for the PIPE clock to be stable */
- usleep_range(5000, 10000);
-
- return 0;
-}
-
-static const struct phy_ops noop_ops = {
- .power_on = cdns_torrent_noop_phy_on,
- .owner = THIS_MODULE,
-};
-
struct cdns_reg_pairs {
u32 val;
u32 off;
@@ -403,12 +373,12 @@ struct cdns_torrent_data {
[NUM_SSC_MODE];
struct cdns_torrent_vals *pcs_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
[NUM_SSC_MODE];
- struct cdns_torrent_vals *cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
- [NUM_SSC_MODE];
- struct cdns_torrent_vals *tx_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
- [NUM_SSC_MODE];
- struct cdns_torrent_vals *rx_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
- [NUM_SSC_MODE];
+ struct cdns_torrent_vals *cmn_vals[NUM_REF_CLK][NUM_PHY_TYPE]
+ [NUM_PHY_TYPE][NUM_SSC_MODE];
+ struct cdns_torrent_vals *tx_ln_vals[NUM_REF_CLK][NUM_PHY_TYPE]
+ [NUM_PHY_TYPE][NUM_SSC_MODE];
+ struct cdns_torrent_vals *rx_ln_vals[NUM_REF_CLK][NUM_PHY_TYPE]
+ [NUM_PHY_TYPE][NUM_SSC_MODE];
};
struct cdns_regmap_cdb_context {
@@ -497,6 +467,22 @@ static const struct regmap_config cdns_torrent_common_cdb_config = {
.reg_read = cdns_regmap_read,
};
+#define TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF(n) \
+{ \
+ .name = "torrent_phy_pcs_lane" n "_cdb", \
+ .reg_stride = 1, \
+ .fast_io = true, \
+ .reg_write = cdns_regmap_write, \
+ .reg_read = cdns_regmap_read, \
+}
+
+static const struct regmap_config cdns_torrent_phy_pcs_lane_cdb_config[] = {
+ TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("0"),
+ TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("1"),
+ TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("2"),
+ TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("3"),
+};
+
static const struct regmap_config cdns_torrent_phy_pcs_cmn_cdb_config = {
.name = "torrent_phy_pcs_cmn_cdb",
.reg_stride = 1,
@@ -615,6 +601,351 @@ static const struct coefficients vltg_coeff[4][4] = {
}
};
+static const char *cdns_torrent_get_phy_type(enum cdns_torrent_phy_type phy_type)
+{
+ switch (phy_type) {
+ case TYPE_DP:
+ return "DisplayPort";
+ case TYPE_PCIE:
+ return "PCIe";
+ case TYPE_SGMII:
+ return "SGMII";
+ case TYPE_QSGMII:
+ return "QSGMII";
+ case TYPE_USB:
+ return "USB";
+ default:
+ return "None";
+ }
+}
+
+/*
+ * Set registers responsible for enabling and configuring SSC, with second and
+ * third register values provided by parameters.
+ */
+static
+void cdns_torrent_dp_enable_ssc_19_2mhz(struct cdns_torrent_phy *cdns_phy,
+ u32 ctrl2_val, u32 ctrl3_val)
+{
+ struct regmap *regmap = cdns_phy->regmap_common_cdb;
+
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl3_val);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl3_val);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003);
+}
+
+static
+void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy,
+ u32 rate, bool ssc)
+{
+ struct regmap *regmap = cdns_phy->regmap_common_cdb;
+
+ /* Assumes 19.2 MHz refclock */
+ switch (rate) {
+ /* Setting VCO for 10.8GHz */
+ case 2700:
+ case 5400:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0119);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x4000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00BC);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0012);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0119);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x4000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00BC);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0012);
+ if (ssc)
+ cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x033A, 0x006A);
+ break;
+ /* Setting VCO for 9.72GHz */
+ case 1620:
+ case 2430:
+ case 3240:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01FA);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x4000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0152);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01FA);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x4000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0152);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ if (ssc)
+ cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x05DD, 0x0069);
+ break;
+ /* Setting VCO for 8.64GHz */
+ case 2160:
+ case 4320:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01C2);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x012C);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01C2);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x012C);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ if (ssc)
+ cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x0536, 0x0069);
+ break;
+ /* Setting VCO for 8.1GHz */
+ case 8100:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01A5);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0xE000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x011A);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01A5);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0xE000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x011A);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ if (ssc)
+ cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x04D7, 0x006A);
+ break;
+ }
+
+ if (ssc) {
+ cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_PLLCNT_START, 0x025E);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_THR, 0x0005);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_PLLCNT_START, 0x025E);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_THR, 0x0005);
+ } else {
+ cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_PLLCNT_START, 0x0260);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_PLLCNT_START, 0x0260);
+ /* Set reset register values to disable SSC */
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL2_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL3_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_THR, 0x0003);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL2_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL3_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_THR, 0x0003);
+ }
+
+ cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x0099);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x0099);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x0099);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x0099);
+}
+
+/*
+ * Set registers responsible for enabling and configuring SSC, with second
+ * register value provided by a parameter.
+ */
+static void cdns_torrent_dp_enable_ssc_25mhz(struct cdns_torrent_phy *cdns_phy,
+ u32 ctrl2_val)
+{
+ struct regmap *regmap = cdns_phy->regmap_common_cdb;
+
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x007F);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x007F);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003);
+}
+
+static
+void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy,
+ u32 rate, bool ssc)
+{
+ struct regmap *regmap = cdns_phy->regmap_common_cdb;
+
+ /* Assumes 25 MHz refclock */
+ switch (rate) {
+ /* Setting VCO for 10.8GHz */
+ case 2700:
+ case 5400:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01B0);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0120);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01B0);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0120);
+ if (ssc)
+ cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x0423);
+ break;
+ /* Setting VCO for 9.72GHz */
+ case 1620:
+ case 2430:
+ case 3240:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0184);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0xCCCD);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0104);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0184);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0xCCCD);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0104);
+ if (ssc)
+ cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x03B9);
+ break;
+ /* Setting VCO for 8.64GHz */
+ case 2160:
+ case 4320:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0159);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x999A);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00E7);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0159);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x999A);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00E7);
+ if (ssc)
+ cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x034F);
+ break;
+ /* Setting VCO for 8.1GHz */
+ case 8100:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0144);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00D8);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0144);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00D8);
+ if (ssc)
+ cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x031A);
+ break;
+ }
+
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+
+ if (ssc) {
+ cdns_torrent_phy_write(regmap,
+ CMN_PLL0_VCOCAL_PLLCNT_START, 0x0315);
+ cdns_torrent_phy_write(regmap,
+ CMN_PLL0_LOCK_PLLCNT_THR, 0x0005);
+ cdns_torrent_phy_write(regmap,
+ CMN_PLL1_VCOCAL_PLLCNT_START, 0x0315);
+ cdns_torrent_phy_write(regmap,
+ CMN_PLL1_LOCK_PLLCNT_THR, 0x0005);
+ } else {
+ cdns_torrent_phy_write(regmap,
+ CMN_PLL0_VCOCAL_PLLCNT_START, 0x0317);
+ cdns_torrent_phy_write(regmap,
+ CMN_PLL1_VCOCAL_PLLCNT_START, 0x0317);
+ /* Set reset register values to disable SSC */
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL2_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL3_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0000);
+ cdns_torrent_phy_write(regmap,
+ CMN_PLL0_LOCK_PLLCNT_THR, 0x0003);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL2_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL3_M0, 0x0000);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0000);
+ cdns_torrent_phy_write(regmap,
+ CMN_PLL1_LOCK_PLLCNT_THR, 0x0003);
+ }
+
+ cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x00C7);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x00C7);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x00C7);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x00C7);
+}
+
+static
+void cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(struct cdns_torrent_phy *cdns_phy,
+ u32 rate, bool ssc)
+{
+ struct regmap *regmap = cdns_phy->regmap_common_cdb;
+
+ /* Assumes 100 MHz refclock */
+ switch (rate) {
+ /* Setting VCO for 10.8GHz */
+ case 2700:
+ case 5400:
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C);
+ break;
+ /* Setting VCO for 9.72GHz */
+ case 1620:
+ case 2430:
+ case 3240:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ break;
+ /* Setting VCO for 8.64GHz */
+ case 2160:
+ case 4320:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ break;
+ /* Setting VCO for 8.1GHz */
+ case 8100:
+ cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036);
+ cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+ cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+ break;
+ }
+}
+
/*
* Enable or disable PLL for selected lanes.
*/
@@ -669,6 +1000,161 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
return ret;
}
+static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
+ u32 num_lanes,
+ enum phy_powerstate powerstate)
+{
+ /* Register value for power state for a single byte. */
+ u32 value_part;
+ u32 value;
+ u32 mask;
+ u32 read_val;
+ u32 ret;
+ struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
+
+ switch (powerstate) {
+ case (POWERSTATE_A0):
+ value_part = 0x01U;
+ break;
+ case (POWERSTATE_A2):
+ value_part = 0x04U;
+ break;
+ default:
+ /* Powerstate A3 */
+ value_part = 0x08U;
+ break;
+ }
+
+ /* Select values of registers and mask, depending on enabled
+ * lane count.
+ */
+ switch (num_lanes) {
+ /* lane 0 */
+ case (1):
+ value = value_part;
+ mask = 0x0000003FU;
+ break;
+ /* lanes 0-1 */
+ case (2):
+ value = (value_part
+ | (value_part << 8));
+ mask = 0x00003F3FU;
+ break;
+ /* lanes 0-3, all */
+ default:
+ value = (value_part
+ | (value_part << 8)
+ | (value_part << 16)
+ | (value_part << 24));
+ mask = 0x3F3F3F3FU;
+ break;
+ }
+
+ /* Set power state A<n>. */
+ cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value);
+ /* Wait, until PHY acknowledges power state completion. */
+ ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK,
+ read_val, (read_val & mask) == value, 0,
+ POLL_TIMEOUT_US);
+ cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000);
+ ndelay(100);
+
+ return ret;
+}
+
+static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
+{
+ unsigned int read_val;
+ int ret;
+ struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
+
+ /*
+ * waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the
+ * master lane
+ */
+ ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_PLLCLK_EN_ACK,
+ read_val, read_val & 1,
+ 0, POLL_TIMEOUT_US);
+ if (ret == -ETIMEDOUT) {
+ dev_err(cdns_phy->dev,
+ "timeout waiting for link PLL clock enable ack\n");
+ return ret;
+ }
+
+ ndelay(100);
+
+ ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
+ POWERSTATE_A2);
+ if (ret)
+ return ret;
+
+ ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
+ POWERSTATE_A0);
+
+ return ret;
+}
+
+static int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy)
+{
+ unsigned int reg;
+ int ret;
+ struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
+
+ ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg,
+ reg & 1, 0, POLL_TIMEOUT_US);
+ if (ret == -ETIMEDOUT) {
+ dev_err(cdns_phy->dev,
+ "timeout waiting for PMA common ready\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
+ u32 rate, u32 num_lanes)
+{
+ unsigned int clk_sel_val = 0;
+ unsigned int hsclk_div_val = 0;
+ unsigned int i;
+
+ switch (rate) {
+ case 1620:
+ clk_sel_val = 0x0f01;
+ hsclk_div_val = 2;
+ break;
+ case 2160:
+ case 2430:
+ case 2700:
+ clk_sel_val = 0x0701;
+ hsclk_div_val = 1;
+ break;
+ case 3240:
+ clk_sel_val = 0x0b00;
+ hsclk_div_val = 2;
+ break;
+ case 4320:
+ case 5400:
+ clk_sel_val = 0x0301;
+ hsclk_div_val = 0;
+ break;
+ case 8100:
+ clk_sel_val = 0x0200;
+ hsclk_div_val = 0;
+ break;
+ }
+
+ cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
+ CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
+ cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
+ CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
+
+ /* PMA lane configuration to deal with multi-link operation */
+ for (i = 0; i < num_lanes; i++)
+ cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i],
+ XCVR_DIAG_HSCLK_DIV, hsclk_div_val);
+}
+
/*
* Perform register operations related to setting link rate, once powerstate is
* set and PLL disable request was processed.
@@ -676,8 +1162,7 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
struct phy_configure_opts_dp *dp)
{
- u32 ret;
- u32 read_val;
+ u32 read_val, ret;
/* Disable the cmn_pll0_en before re-programming the new data rate. */
regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0);
@@ -695,17 +1180,16 @@ static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
ndelay(200);
/* DP Rate Change - VCO Output settings. */
- if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz) {
+ if (cdns_phy->ref_clk_rate == CLK_19_2_MHZ)
/* PMA common configuration 19.2MHz */
- cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy, dp->link_rate,
- dp->ssc);
- cdns_torrent_dp_pma_cmn_cfg_19_2mhz(cdns_phy);
- } else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz) {
+ cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy, dp->link_rate, dp->ssc);
+ else if (cdns_phy->ref_clk_rate == CLK_25_MHZ)
/* PMA common configuration 25MHz */
- cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy, dp->link_rate,
- dp->ssc);
- cdns_torrent_dp_pma_cmn_cfg_25mhz(cdns_phy);
- }
+ cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy, dp->link_rate, dp->ssc);
+ else if (cdns_phy->ref_clk_rate == CLK_100_MHZ)
+ /* PMA common configuration 100MHz */
+ cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, dp->link_rate, dp->ssc);
+
cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes);
/* Enable the cmn_pll0_en. */
@@ -984,28 +1468,71 @@ static int cdns_torrent_dp_configure(struct phy *phy,
return ret;
}
-static int cdns_torrent_dp_init(struct phy *phy)
+static int cdns_torrent_phy_on(struct phy *phy)
{
- unsigned char lane_bits;
- int ret;
struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
- struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
+ u32 read_val;
+ int ret;
- switch (cdns_phy->ref_clk_rate) {
- case REF_CLK_19_2MHz:
- case REF_CLK_25MHz:
- /* Valid Ref Clock Rate */
- break;
- default:
- dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n");
- return -EINVAL;
+ if (cdns_phy->nsubnodes == 1) {
+ /* Take the PHY lane group out of reset */
+ reset_control_deassert(inst->lnk_rst);
+
+ /* Take the PHY out of reset */
+ ret = reset_control_deassert(cdns_phy->phy_rst);
+ if (ret)
+ return ret;
}
- cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */
+ /*
+ * Wait for cmn_ready assertion
+ * PHY_PMA_CMN_CTRL1[0] == 1
+ */
+ ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1,
+ read_val, read_val, 1000,
+ PLL_LOCK_TIMEOUT);
+ if (ret) {
+ dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n");
+ return ret;
+ }
+
+ if (inst->phy_type == TYPE_PCIE || inst->phy_type == TYPE_USB) {
+ ret = regmap_field_read_poll_timeout(cdns_phy->phy_pcs_iso_link_ctrl_1[inst->mlane],
+ read_val, !read_val, 1000,
+ PLL_LOCK_TIMEOUT);
+ if (ret == -ETIMEDOUT) {
+ dev_err(cdns_phy->dev, "Timeout waiting for PHY status ready\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int cdns_torrent_phy_off(struct phy *phy)
+{
+ struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
+ struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
+ int ret;
- /* PHY PMA registers configuration function */
- cdns_torrent_dp_pma_cfg(cdns_phy, inst);
+ if (cdns_phy->nsubnodes != 1)
+ return 0;
+
+ ret = reset_control_assert(cdns_phy->phy_rst);
+ if (ret)
+ return ret;
+
+ return reset_control_assert(inst->lnk_rst);
+}
+
+static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst)
+{
+ struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
+ unsigned char lane_bits;
+
+ cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */
/*
* Set lines power state to A0
@@ -1024,21 +1551,35 @@ static int cdns_torrent_dp_init(struct phy *phy)
/* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
- /* PHY PMA registers configuration functions */
- /* Initialize PHY with max supported link rate, without SSC. */
- if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
+ /*
+ * PHY PMA registers configuration functions
+ * Initialize PHY with max supported link rate, without SSC.
+ */
+ if (cdns_phy->ref_clk_rate == CLK_19_2_MHZ)
cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy,
cdns_phy->max_bit_rate,
false);
- else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
+ else if (cdns_phy->ref_clk_rate == CLK_25_MHZ)
cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy,
cdns_phy->max_bit_rate,
false);
+ else if (cdns_phy->ref_clk_rate == CLK_100_MHZ)
+ cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy,
+ cdns_phy->max_bit_rate,
+ false);
+
cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate,
inst->num_lanes);
/* take out of reset */
regmap_field_write(cdns_phy->phy_reset_ctrl, 0x1);
+}
+
+static int cdns_torrent_dp_start(struct cdns_torrent_phy *cdns_phy,
+ struct cdns_torrent_inst *inst,
+ struct phy *phy)
+{
+ int ret;
cdns_torrent_phy_on(phy);
@@ -1051,615 +1592,25 @@ static int cdns_torrent_dp_init(struct phy *phy)
return ret;
}
-static
-int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy)
-{
- unsigned int reg;
- int ret;
- struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
-
- ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg,
- reg & 1, 0, POLL_TIMEOUT_US);
- if (ret == -ETIMEDOUT) {
- dev_err(cdns_phy->dev,
- "timeout waiting for PMA common ready\n");
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy,
- struct cdns_torrent_inst *inst)
-{
- unsigned int i;
-
- if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
- /* PMA common configuration 19.2MHz */
- cdns_torrent_dp_pma_cmn_cfg_19_2mhz(cdns_phy);
- else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
- /* PMA common configuration 25MHz */
- cdns_torrent_dp_pma_cmn_cfg_25mhz(cdns_phy);
-
- /* PMA lane configuration to deal with multi-link operation */
- for (i = 0; i < inst->num_lanes; i++)
- cdns_torrent_dp_pma_lane_cfg(cdns_phy, i);
-}
-
-static
-void cdns_torrent_dp_pma_cmn_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy)
-{
- struct regmap *regmap = cdns_phy->regmap_common_cdb;
-
- /* refclock registers - assumes 19.2 MHz refclock */
- cdns_torrent_phy_write(regmap, CMN_SSM_BIAS_TMR, 0x0014);
- cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLPRE_TMR, 0x0027);
- cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLLOCK_TMR, 0x00A1);
- cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLPRE_TMR, 0x0027);
- cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLLOCK_TMR, 0x00A1);
- cdns_torrent_phy_write(regmap, CMN_BGCAL_INIT_TMR, 0x0060);
- cdns_torrent_phy_write(regmap, CMN_BGCAL_ITER_TMR, 0x0060);
- cdns_torrent_phy_write(regmap, CMN_IBCAL_INIT_TMR, 0x0014);
- cdns_torrent_phy_write(regmap, CMN_TXPUCAL_INIT_TMR, 0x0018);
- cdns_torrent_phy_write(regmap, CMN_TXPUCAL_ITER_TMR, 0x0005);
- cdns_torrent_phy_write(regmap, CMN_TXPDCAL_INIT_TMR, 0x0018);
- cdns_torrent_phy_write(regmap, CMN_TXPDCAL_ITER_TMR, 0x0005);
- cdns_torrent_phy_write(regmap, CMN_RXCAL_INIT_TMR, 0x0240);
- cdns_torrent_phy_write(regmap, CMN_RXCAL_ITER_TMR, 0x0005);
- cdns_torrent_phy_write(regmap, CMN_SD_CAL_INIT_TMR, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_SD_CAL_ITER_TMR, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_SD_CAL_REFTIM_START, 0x000B);
- cdns_torrent_phy_write(regmap, CMN_SD_CAL_PLLCNT_START, 0x0137);
-
- /* PLL registers */
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_INIT_TMR, 0x00C0);
- cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_ITER_TMR, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_INIT_TMR, 0x00C0);
- cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_ITER_TMR, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_REFTIM_START, 0x0260);
- cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_TCTRL, 0x0003);
- cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_REFTIM_START, 0x0260);
- cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_TCTRL, 0x0003);
-}
-
-/*
- * Set registers responsible for enabling and configuring SSC, with second and
- * third register values provided by parameters.
- */
-static
-void cdns_torrent_dp_enable_ssc_19_2mhz(struct cdns_torrent_phy *cdns_phy,
- u32 ctrl2_val, u32 ctrl3_val)
-{
- struct regmap *regmap = cdns_phy->regmap_common_cdb;
-
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl3_val);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl3_val);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003);
-}
-
-static
-void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy,
- u32 rate, bool ssc)
-{
- struct regmap *regmap = cdns_phy->regmap_common_cdb;
-
- /* Assumes 19.2 MHz refclock */
- switch (rate) {
- /* Setting VCO for 10.8GHz */
- case 2700:
- case 5400:
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_INTDIV_M0, 0x0119);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_FRACDIVL_M0, 0x4000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_HIGH_THR_M0, 0x00BC);
- cdns_torrent_phy_write(regmap,
- CMN_PDIAG_PLL0_CTRL_M0, 0x0012);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_INTDIV_M0, 0x0119);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_FRACDIVL_M0, 0x4000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_HIGH_THR_M0, 0x00BC);
- cdns_torrent_phy_write(regmap,
- CMN_PDIAG_PLL1_CTRL_M0, 0x0012);
- if (ssc)
- cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x033A,
- 0x006A);
- break;
- /* Setting VCO for 9.72GHz */
- case 1620:
- case 2430:
- case 3240:
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_INTDIV_M0, 0x01FA);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_FRACDIVL_M0, 0x4000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_HIGH_THR_M0, 0x0152);
- cdns_torrent_phy_write(regmap,
- CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_INTDIV_M0, 0x01FA);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_FRACDIVL_M0, 0x4000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_HIGH_THR_M0, 0x0152);
- cdns_torrent_phy_write(regmap,
- CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
- if (ssc)
- cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x05DD,
- 0x0069);
- break;
- /* Setting VCO for 8.64GHz */
- case 2160:
- case 4320:
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_INTDIV_M0, 0x01C2);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_FRACDIVL_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_HIGH_THR_M0, 0x012C);
- cdns_torrent_phy_write(regmap,
- CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_INTDIV_M0, 0x01C2);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_FRACDIVL_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_HIGH_THR_M0, 0x012C);
- cdns_torrent_phy_write(regmap,
- CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
- if (ssc)
- cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x0536,
- 0x0069);
- break;
- /* Setting VCO for 8.1GHz */
- case 8100:
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_INTDIV_M0, 0x01A5);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_FRACDIVL_M0, 0xE000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_HIGH_THR_M0, 0x011A);
- cdns_torrent_phy_write(regmap,
- CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_INTDIV_M0, 0x01A5);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_FRACDIVL_M0, 0xE000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_HIGH_THR_M0, 0x011A);
- cdns_torrent_phy_write(regmap,
- CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
- if (ssc)
- cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x04D7,
- 0x006A);
- break;
- }
-
- if (ssc) {
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_VCOCAL_PLLCNT_START, 0x025E);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_LOCK_PLLCNT_THR, 0x0005);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_VCOCAL_PLLCNT_START, 0x025E);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_LOCK_PLLCNT_THR, 0x0005);
- } else {
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_VCOCAL_PLLCNT_START, 0x0260);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_VCOCAL_PLLCNT_START, 0x0260);
- /* Set reset register values to disable SSC */
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_SS_CTRL1_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_SS_CTRL2_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_SS_CTRL3_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_SS_CTRL4_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_LOCK_PLLCNT_THR, 0x0003);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_SS_CTRL1_M0, 0x0002);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_SS_CTRL2_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_SS_CTRL3_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_SS_CTRL4_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_LOCK_PLLCNT_THR, 0x0003);
- }
-
- cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x0099);
- cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x0099);
- cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x0099);
- cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x0099);
-}
-
-static
-void cdns_torrent_dp_pma_cmn_cfg_25mhz(struct cdns_torrent_phy *cdns_phy)
-{
- struct regmap *regmap = cdns_phy->regmap_common_cdb;
-
- /* refclock registers - assumes 25 MHz refclock */
- cdns_torrent_phy_write(regmap, CMN_SSM_BIAS_TMR, 0x0019);
- cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLPRE_TMR, 0x0032);
- cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLLOCK_TMR, 0x00D1);
- cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLPRE_TMR, 0x0032);
- cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLLOCK_TMR, 0x00D1);
- cdns_torrent_phy_write(regmap, CMN_BGCAL_INIT_TMR, 0x007D);
- cdns_torrent_phy_write(regmap, CMN_BGCAL_ITER_TMR, 0x007D);
- cdns_torrent_phy_write(regmap, CMN_IBCAL_INIT_TMR, 0x0019);
- cdns_torrent_phy_write(regmap, CMN_TXPUCAL_INIT_TMR, 0x001E);
- cdns_torrent_phy_write(regmap, CMN_TXPUCAL_ITER_TMR, 0x0006);
- cdns_torrent_phy_write(regmap, CMN_TXPDCAL_INIT_TMR, 0x001E);
- cdns_torrent_phy_write(regmap, CMN_TXPDCAL_ITER_TMR, 0x0006);
- cdns_torrent_phy_write(regmap, CMN_RXCAL_INIT_TMR, 0x02EE);
- cdns_torrent_phy_write(regmap, CMN_RXCAL_ITER_TMR, 0x0006);
- cdns_torrent_phy_write(regmap, CMN_SD_CAL_INIT_TMR, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_SD_CAL_ITER_TMR, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_SD_CAL_REFTIM_START, 0x000E);
- cdns_torrent_phy_write(regmap, CMN_SD_CAL_PLLCNT_START, 0x012B);
-
- /* PLL registers */
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
- cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_INIT_TMR, 0x00FA);
- cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_ITER_TMR, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_INIT_TMR, 0x00FA);
- cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_ITER_TMR, 0x0004);
- cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_REFTIM_START, 0x0317);
- cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_TCTRL, 0x0003);
- cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_REFTIM_START, 0x0317);
- cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_TCTRL, 0x0003);
-}
-
-/*
- * Set registers responsible for enabling and configuring SSC, with second
- * register value provided by a parameter.
- */
-static void cdns_torrent_dp_enable_ssc_25mhz(struct cdns_torrent_phy *cdns_phy,
- u32 ctrl2_val)
-{
- struct regmap *regmap = cdns_phy->regmap_common_cdb;
-
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x007F);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x007F);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003);
-}
-
-static
-void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy,
- u32 rate, bool ssc)
-{
- struct regmap *regmap = cdns_phy->regmap_common_cdb;
-
- /* Assumes 25 MHz refclock */
- switch (rate) {
- /* Setting VCO for 10.8GHz */
- case 2700:
- case 5400:
- cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01B0);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0120);
- cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01B0);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0120);
- if (ssc)
- cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x0423);
- break;
- /* Setting VCO for 9.72GHz */
- case 1620:
- case 2430:
- case 3240:
- cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0184);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0xCCCD);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0104);
- cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0184);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0xCCCD);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0104);
- if (ssc)
- cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x03B9);
- break;
- /* Setting VCO for 8.64GHz */
- case 2160:
- case 4320:
- cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0159);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x999A);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00E7);
- cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0159);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x999A);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00E7);
- if (ssc)
- cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x034F);
- break;
- /* Setting VCO for 8.1GHz */
- case 8100:
- cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0144);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000);
- cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00D8);
- cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0144);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000);
- cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00D8);
- if (ssc)
- cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x031A);
- break;
- }
-
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
-
- if (ssc) {
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_VCOCAL_PLLCNT_START, 0x0315);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_LOCK_PLLCNT_THR, 0x0005);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_VCOCAL_PLLCNT_START, 0x0315);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_LOCK_PLLCNT_THR, 0x0005);
- } else {
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_VCOCAL_PLLCNT_START, 0x0317);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_VCOCAL_PLLCNT_START, 0x0317);
- /* Set reset register values to disable SSC */
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL2_M0, 0x0000);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL3_M0, 0x0000);
- cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL0_LOCK_PLLCNT_THR, 0x0003);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0002);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL2_M0, 0x0000);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL3_M0, 0x0000);
- cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0000);
- cdns_torrent_phy_write(regmap,
- CMN_PLL1_LOCK_PLLCNT_THR, 0x0003);
- }
-
- cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x00C7);
- cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x00C7);
- cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x00C7);
- cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x00C7);
-}
-
-static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
- u32 rate, u32 num_lanes)
-{
- unsigned int clk_sel_val = 0;
- unsigned int hsclk_div_val = 0;
- unsigned int i;
-
- /* 16'h0000 for single DP link configuration */
- regmap_field_write(cdns_phy->phy_pll_cfg, 0x0);
-
- switch (rate) {
- case 1620:
- clk_sel_val = 0x0f01;
- hsclk_div_val = 2;
- break;
- case 2160:
- case 2430:
- case 2700:
- clk_sel_val = 0x0701;
- hsclk_div_val = 1;
- break;
- case 3240:
- clk_sel_val = 0x0b00;
- hsclk_div_val = 2;
- break;
- case 4320:
- case 5400:
- clk_sel_val = 0x0301;
- hsclk_div_val = 0;
- break;
- case 8100:
- clk_sel_val = 0x0200;
- hsclk_div_val = 0;
- break;
- }
-
- cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
- CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
- cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
- CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
-
- /* PMA lane configuration to deal with multi-link operation */
- for (i = 0; i < num_lanes; i++)
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i],
- XCVR_DIAG_HSCLK_DIV, hsclk_div_val);
-}
-
-static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy,
- unsigned int lane)
-{
- /* Per lane, refclock-dependent receiver detection setting */
- if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz)
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
- TX_RCVDET_ST_TMR, 0x0780);
- else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz)
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
- TX_RCVDET_ST_TMR, 0x09C4);
-
- /* Writing Tx/Rx Power State Controllers registers */
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
- TX_PSC_A0, 0x00FB);
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
- TX_PSC_A2, 0x04AA);
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
- TX_PSC_A3, 0x04AA);
- cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
- RX_PSC_A0, 0x0000);
- cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
- RX_PSC_A2, 0x0000);
- cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
- RX_PSC_A3, 0x0000);
-
- cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
- RX_PSC_CAL, 0x0000);
-
- cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
- RX_REE_GCSM1_CTRL, 0x0000);
- cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
- RX_REE_GCSM2_CTRL, 0x0000);
- cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane],
- RX_REE_PERGCSM_CTRL, 0x0000);
-
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
- XCVR_DIAG_BIDI_CTRL, 0x000F);
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
- XCVR_DIAG_PLLDRC_CTRL, 0x0001);
- cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
- XCVR_DIAG_HSCLK_SEL, 0x0000);
-}
-
-static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
- u32 num_lanes,
- enum phy_powerstate powerstate)
+static int cdns_torrent_dp_init(struct phy *phy)
{
- /* Register value for power state for a single byte. */
- u32 value_part;
- u32 value;
- u32 mask;
- u32 read_val;
- u32 ret;
- struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
-
- switch (powerstate) {
- case (POWERSTATE_A0):
- value_part = 0x01U;
- break;
- case (POWERSTATE_A2):
- value_part = 0x04U;
- break;
- default:
- /* Powerstate A3 */
- value_part = 0x08U;
- break;
- }
+ struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
+ struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
- /* Select values of registers and mask, depending on enabled
- * lane count.
- */
- switch (num_lanes) {
- /* lane 0 */
- case (1):
- value = value_part;
- mask = 0x0000003FU;
- break;
- /* lanes 0-1 */
- case (2):
- value = (value_part
- | (value_part << 8));
- mask = 0x00003F3FU;
+ switch (cdns_phy->ref_clk_rate) {
+ case CLK_19_2_MHZ:
+ case CLK_25_MHZ:
+ case CLK_100_MHZ:
+ /* Valid Ref Clock Rate */
break;
- /* lanes 0-3, all */
default:
- value = (value_part
- | (value_part << 8)
- | (value_part << 16)
- | (value_part << 24));
- mask = 0x3F3F3F3FU;
- break;
- }
-
- /* Set power state A<n>. */
- cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value);
- /* Wait, until PHY acknowledges power state completion. */
- ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK,
- read_val, (read_val & mask) == value, 0,
- POLL_TIMEOUT_US);
- cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000);
- ndelay(100);
-
- return ret;
-}
-
-static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
-{
- unsigned int read_val;
- int ret;
- struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
-
- /*
- * waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the
- * master lane
- */
- ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_PLLCLK_EN_ACK,
- read_val, read_val & 1,
- 0, POLL_TIMEOUT_US);
- if (ret == -ETIMEDOUT) {
- dev_err(cdns_phy->dev,
- "timeout waiting for link PLL clock enable ack\n");
- return ret;
+ dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n");
+ return -EINVAL;
}
- ndelay(100);
-
- ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
- POWERSTATE_A2);
- if (ret)
- return ret;
-
- ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
- POWERSTATE_A0);
+ cdns_torrent_dp_common_init(cdns_phy, inst);
- return ret;
+ return cdns_torrent_dp_start(cdns_phy, inst, phy);
}
static int cdns_torrent_derived_refclk_enable(struct clk_hw *hw)
@@ -1764,56 +1715,6 @@ static int cdns_torrent_derived_refclk_register(struct cdns_torrent_phy *cdns_ph
return 0;
}
-static int cdns_torrent_phy_on(struct phy *phy)
-{
- struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
- struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
- u32 read_val;
- int ret;
-
- if (cdns_phy->nsubnodes == 1) {
- /* Take the PHY lane group out of reset */
- reset_control_deassert(inst->lnk_rst);
-
- /* Take the PHY out of reset */
- ret = reset_control_deassert(cdns_phy->phy_rst);
- if (ret)
- return ret;
- }
-
- /*
- * Wait for cmn_ready assertion
- * PHY_PMA_CMN_CTRL1[0] == 1
- */
- ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1,
- read_val, read_val, 1000,
- PLL_LOCK_TIMEOUT);
- if (ret) {
- dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n");
- return ret;
- }
-
- mdelay(10);
-
- return 0;
-}
-
-static int cdns_torrent_phy_off(struct phy *phy)
-{
- struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
- struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
- int ret;
-
- if (cdns_phy->nsubnodes != 1)
- return 0;
-
- ret = reset_control_assert(cdns_phy->phy_rst);
- if (ret)
- return ret;
-
- return reset_control_assert(inst->lnk_rst);
-}
-
static struct regmap *cdns_regmap_init(struct device *dev, void __iomem *base,
u32 block_offset,
u8 reg_offset_shift,
@@ -1854,6 +1755,7 @@ static int cdns_torrent_regfield_init(struct cdns_torrent_phy *cdns_phy)
struct device *dev = cdns_phy->dev;
struct regmap_field *field;
struct regmap *regmap;
+ int i;
regmap = cdns_phy->regmap_phy_pcs_common_cdb;
field = devm_regmap_field_alloc(dev, regmap, phy_pll_cfg);
@@ -1887,6 +1789,16 @@ static int cdns_torrent_regfield_init(struct cdns_torrent_phy *cdns_phy)
}
cdns_phy->phy_pma_pll_raw_ctrl = field;
+ for (i = 0; i < MAX_NUM_LANES; i++) {
+ regmap = cdns_phy->regmap_phy_pcs_lane_cdb[i];
+ field = devm_regmap_field_alloc(dev, regmap, phy_pcs_iso_link_ctrl_1);
+ if (IS_ERR(field)) {
+ dev_err(dev, "PHY_PCS_ISO_LINK_CTRL reg field init for ln %d failed\n", i);
+ return PTR_ERR(field);
+ }
+ cdns_phy->phy_pcs_iso_link_ctrl_1[i] = field;
+ }
+
return 0;
}
@@ -1947,6 +1859,17 @@ static int cdns_torrent_regmap_init(struct cdns_torrent_phy *cdns_phy)
return PTR_ERR(regmap);
}
cdns_phy->regmap_rx_lane_cdb[i] = regmap;
+
+ block_offset = TORRENT_PHY_PCS_LANE_CDB_OFFSET(i, block_offset_shift,
+ reg_offset_shift);
+ regmap = cdns_regmap_init(dev, sd_base, block_offset,
+ reg_offset_shift,
+ &cdns_torrent_phy_pcs_lane_cdb_config[i]);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to init PHY PCS lane CDB regmap\n");
+ return PTR_ERR(regmap);
+ }
+ cdns_phy->regmap_phy_pcs_lane_cdb[i] = regmap;
}
block_offset = TORRENT_COMMON_CDB_OFFSET;
@@ -1987,6 +1910,7 @@ static int cdns_torrent_phy_init(struct phy *phy)
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
const struct cdns_torrent_data *init_data = cdns_phy->init_data;
struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals;
+ enum cdns_torrent_ref_clk ref_clk = cdns_phy->ref_clk_rate;
struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals;
struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
enum cdns_torrent_phy_type phy_type = inst->phy_type;
@@ -2000,9 +1924,6 @@ static int cdns_torrent_phy_init(struct phy *phy)
if (cdns_phy->nsubnodes > 1)
return 0;
- if (phy_type == TYPE_DP)
- return cdns_torrent_dp_init(phy);
-
/**
* Spread spectrum generation is not required or supported
* for SGMII/QSGMII
@@ -2052,7 +1973,7 @@ static int cdns_torrent_phy_init(struct phy *phy)
}
/* PMA common registers configurations */
- cmn_vals = init_data->cmn_vals[phy_type][TYPE_NONE][ssc];
+ cmn_vals = init_data->cmn_vals[ref_clk][phy_type][TYPE_NONE][ssc];
if (cmn_vals) {
reg_pairs = cmn_vals->reg_pairs;
num_regs = cmn_vals->num_regs;
@@ -2063,7 +1984,7 @@ static int cdns_torrent_phy_init(struct phy *phy)
}
/* PMA TX lane registers configurations */
- tx_ln_vals = init_data->tx_ln_vals[phy_type][TYPE_NONE][ssc];
+ tx_ln_vals = init_data->tx_ln_vals[ref_clk][phy_type][TYPE_NONE][ssc];
if (tx_ln_vals) {
reg_pairs = tx_ln_vals->reg_pairs;
num_regs = tx_ln_vals->num_regs;
@@ -2076,7 +1997,7 @@ static int cdns_torrent_phy_init(struct phy *phy)
}
/* PMA RX lane registers configurations */
- rx_ln_vals = init_data->rx_ln_vals[phy_type][TYPE_NONE][ssc];
+ rx_ln_vals = init_data->rx_ln_vals[ref_clk][phy_type][TYPE_NONE][ssc];
if (rx_ln_vals) {
reg_pairs = rx_ln_vals->reg_pairs;
num_regs = rx_ln_vals->num_regs;
@@ -2088,14 +2009,39 @@ static int cdns_torrent_phy_init(struct phy *phy)
}
}
+ if (phy_type == TYPE_DP)
+ return cdns_torrent_dp_init(phy);
+
+ return 0;
+}
+
+static const struct phy_ops cdns_torrent_phy_ops = {
+ .init = cdns_torrent_phy_init,
+ .configure = cdns_torrent_dp_configure,
+ .power_on = cdns_torrent_phy_on,
+ .power_off = cdns_torrent_phy_off,
+ .owner = THIS_MODULE,
+};
+
+static int cdns_torrent_noop_phy_on(struct phy *phy)
+{
+ /* Give 5ms to 10ms delay for the PIPE clock to be stable */
+ usleep_range(5000, 10000);
+
return 0;
}
+static const struct phy_ops noop_ops = {
+ .power_on = cdns_torrent_noop_phy_on,
+ .owner = THIS_MODULE,
+};
+
static
int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
{
const struct cdns_torrent_data *init_data = cdns_phy->init_data;
struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals;
+ enum cdns_torrent_ref_clk ref_clk = cdns_phy->ref_clk_rate;
struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals;
enum cdns_torrent_phy_type phy_t1, phy_t2, tmp_phy_type;
struct cdns_torrent_vals *pcs_cmn_vals;
@@ -2184,7 +2130,7 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
}
/* PMA common registers configurations */
- cmn_vals = init_data->cmn_vals[phy_t1][phy_t2][ssc];
+ cmn_vals = init_data->cmn_vals[ref_clk][phy_t1][phy_t2][ssc];
if (cmn_vals) {
reg_pairs = cmn_vals->reg_pairs;
num_regs = cmn_vals->num_regs;
@@ -2195,7 +2141,7 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
}
/* PMA TX lane registers configurations */
- tx_ln_vals = init_data->tx_ln_vals[phy_t1][phy_t2][ssc];
+ tx_ln_vals = init_data->tx_ln_vals[ref_clk][phy_t1][phy_t2][ssc];
if (tx_ln_vals) {
reg_pairs = tx_ln_vals->reg_pairs;
num_regs = tx_ln_vals->num_regs;
@@ -2208,7 +2154,7 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
}
/* PMA RX lane registers configurations */
- rx_ln_vals = init_data->rx_ln_vals[phy_t1][phy_t2][ssc];
+ rx_ln_vals = init_data->rx_ln_vals[ref_clk][phy_t1][phy_t2][ssc];
if (rx_ln_vals) {
reg_pairs = rx_ln_vals->reg_pairs;
num_regs = rx_ln_vals->num_regs;
@@ -2286,6 +2232,7 @@ static int cdns_torrent_reset(struct cdns_torrent_phy *cdns_phy)
static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
{
struct device *dev = cdns_phy->dev;
+ unsigned long ref_clk_rate;
int ret;
cdns_phy->clk = devm_clk_get(dev, "refclk");
@@ -2300,13 +2247,29 @@ static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
return ret;
}
- cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk);
- if (!(cdns_phy->ref_clk_rate)) {
+ ref_clk_rate = clk_get_rate(cdns_phy->clk);
+ if (!ref_clk_rate) {
dev_err(cdns_phy->dev, "Failed to get ref clock rate\n");
clk_disable_unprepare(cdns_phy->clk);
return -EINVAL;
}
+ switch (ref_clk_rate) {
+ case REF_CLK_19_2MHZ:
+ cdns_phy->ref_clk_rate = CLK_19_2_MHZ;
+ break;
+ case REF_CLK_25MHZ:
+ cdns_phy->ref_clk_rate = CLK_25_MHZ;
+ break;
+ case REF_CLK_100MHZ:
+ cdns_phy->ref_clk_rate = CLK_100_MHZ;
+ break;
+ default:
+ dev_err(cdns_phy->dev, "Invalid Ref Clock Rate\n");
+ clk_disable_unprepare(cdns_phy->clk);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -2505,10 +2468,9 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
init_dp_regmap++;
}
- dev_info(dev, "%d lanes, max bit rate %d.%03d Gbps\n",
- cdns_phy->phys[node].num_lanes,
- cdns_phy->max_bit_rate / 1000,
- cdns_phy->max_bit_rate % 1000);
+ dev_dbg(dev, "DP max bit rate %d.%03d Gbps\n",
+ cdns_phy->max_bit_rate / 1000,
+ cdns_phy->max_bit_rate % 1000);
gphy->attrs.bus_width = cdns_phy->phys[node].num_lanes;
gphy->attrs.max_link_rate = cdns_phy->max_bit_rate;
@@ -2540,6 +2502,17 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
goto put_lnk_rst;
}
+ if (cdns_phy->nsubnodes > 1)
+ dev_dbg(dev, "Multi-link: %s (%d lanes) & %s (%d lanes)",
+ cdns_torrent_get_phy_type(cdns_phy->phys[0].phy_type),
+ cdns_phy->phys[0].num_lanes,
+ cdns_torrent_get_phy_type(cdns_phy->phys[1].phy_type),
+ cdns_phy->phys[1].num_lanes);
+ else
+ dev_dbg(dev, "Single link: %s (%d lanes)",
+ cdns_torrent_get_phy_type(cdns_phy->phys[0].phy_type),
+ cdns_phy->phys[0].num_lanes);
+
return 0;
put_child:
@@ -2573,6 +2546,206 @@ static int cdns_torrent_phy_remove(struct platform_device *pdev)
return 0;
}
+/* Single DisplayPort(DP) link configuration */
+static struct cdns_reg_pairs sl_dp_link_cmn_regs[] = {
+ {0x0000, PHY_PLL_CFG},
+};
+
+static struct cdns_reg_pairs sl_dp_xcvr_diag_ln_regs[] = {
+ {0x0000, XCVR_DIAG_HSCLK_SEL},
+ {0x0001, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_torrent_vals sl_dp_link_cmn_vals = {
+ .reg_pairs = sl_dp_link_cmn_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_link_cmn_regs),
+};
+
+static struct cdns_torrent_vals sl_dp_xcvr_diag_ln_vals = {
+ .reg_pairs = sl_dp_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_xcvr_diag_ln_regs),
+};
+
+/* Single DP, 19.2 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs sl_dp_19_2_no_ssc_cmn_regs[] = {
+ {0x0014, CMN_SSM_BIAS_TMR},
+ {0x0027, CMN_PLLSM0_PLLPRE_TMR},
+ {0x00A1, CMN_PLLSM0_PLLLOCK_TMR},
+ {0x0027, CMN_PLLSM1_PLLPRE_TMR},
+ {0x00A1, CMN_PLLSM1_PLLLOCK_TMR},
+ {0x0060, CMN_BGCAL_INIT_TMR},
+ {0x0060, CMN_BGCAL_ITER_TMR},
+ {0x0014, CMN_IBCAL_INIT_TMR},
+ {0x0018, CMN_TXPUCAL_INIT_TMR},
+ {0x0005, CMN_TXPUCAL_ITER_TMR},
+ {0x0018, CMN_TXPDCAL_INIT_TMR},
+ {0x0005, CMN_TXPDCAL_ITER_TMR},
+ {0x0240, CMN_RXCAL_INIT_TMR},
+ {0x0005, CMN_RXCAL_ITER_TMR},
+ {0x0002, CMN_SD_CAL_INIT_TMR},
+ {0x0002, CMN_SD_CAL_ITER_TMR},
+ {0x000B, CMN_SD_CAL_REFTIM_START},
+ {0x0137, CMN_SD_CAL_PLLCNT_START},
+ {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0},
+ {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0},
+ {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0},
+ {0x0004, CMN_PLL0_DSM_DIAG_M0},
+ {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0},
+ {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0},
+ {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0},
+ {0x0004, CMN_PLL1_DSM_DIAG_M0},
+ {0x00C0, CMN_PLL0_VCOCAL_INIT_TMR},
+ {0x0004, CMN_PLL0_VCOCAL_ITER_TMR},
+ {0x00C0, CMN_PLL1_VCOCAL_INIT_TMR},
+ {0x0004, CMN_PLL1_VCOCAL_ITER_TMR},
+ {0x0260, CMN_PLL0_VCOCAL_REFTIM_START},
+ {0x0003, CMN_PLL0_VCOCAL_TCTRL},
+ {0x0260, CMN_PLL1_VCOCAL_REFTIM_START},
+ {0x0003, CMN_PLL1_VCOCAL_TCTRL}
+};
+
+static struct cdns_reg_pairs sl_dp_19_2_no_ssc_tx_ln_regs[] = {
+ {0x0780, TX_RCVDET_ST_TMR},
+ {0x00FB, TX_PSC_A0},
+ {0x04AA, TX_PSC_A2},
+ {0x04AA, TX_PSC_A3},
+ {0x000F, XCVR_DIAG_BIDI_CTRL}
+};
+
+static struct cdns_reg_pairs sl_dp_19_2_no_ssc_rx_ln_regs[] = {
+ {0x0000, RX_PSC_A0},
+ {0x0000, RX_PSC_A2},
+ {0x0000, RX_PSC_A3},
+ {0x0000, RX_PSC_CAL},
+ {0x0000, RX_REE_GCSM1_CTRL},
+ {0x0000, RX_REE_GCSM2_CTRL},
+ {0x0000, RX_REE_PERGCSM_CTRL}
+};
+
+static struct cdns_torrent_vals sl_dp_19_2_no_ssc_cmn_vals = {
+ .reg_pairs = sl_dp_19_2_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_cmn_regs),
+};
+
+static struct cdns_torrent_vals sl_dp_19_2_no_ssc_tx_ln_vals = {
+ .reg_pairs = sl_dp_19_2_no_ssc_tx_ln_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_torrent_vals sl_dp_19_2_no_ssc_rx_ln_vals = {
+ .reg_pairs = sl_dp_19_2_no_ssc_rx_ln_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_rx_ln_regs),
+};
+
+/* Single DP, 25 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs sl_dp_25_no_ssc_cmn_regs[] = {
+ {0x0019, CMN_SSM_BIAS_TMR},
+ {0x0032, CMN_PLLSM0_PLLPRE_TMR},
+ {0x00D1, CMN_PLLSM0_PLLLOCK_TMR},
+ {0x0032, CMN_PLLSM1_PLLPRE_TMR},
+ {0x00D1, CMN_PLLSM1_PLLLOCK_TMR},
+ {0x007D, CMN_BGCAL_INIT_TMR},
+ {0x007D, CMN_BGCAL_ITER_TMR},
+ {0x0019, CMN_IBCAL_INIT_TMR},
+ {0x001E, CMN_TXPUCAL_INIT_TMR},
+ {0x0006, CMN_TXPUCAL_ITER_TMR},
+ {0x001E, CMN_TXPDCAL_INIT_TMR},
+ {0x0006, CMN_TXPDCAL_ITER_TMR},
+ {0x02EE, CMN_RXCAL_INIT_TMR},
+ {0x0006, CMN_RXCAL_ITER_TMR},
+ {0x0002, CMN_SD_CAL_INIT_TMR},
+ {0x0002, CMN_SD_CAL_ITER_TMR},
+ {0x000E, CMN_SD_CAL_REFTIM_START},
+ {0x012B, CMN_SD_CAL_PLLCNT_START},
+ {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0},
+ {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0},
+ {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0},
+ {0x0004, CMN_PLL0_DSM_DIAG_M0},
+ {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0},
+ {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0},
+ {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0},
+ {0x0004, CMN_PLL1_DSM_DIAG_M0},
+ {0x00FA, CMN_PLL0_VCOCAL_INIT_TMR},
+ {0x0004, CMN_PLL0_VCOCAL_ITER_TMR},
+ {0x00FA, CMN_PLL1_VCOCAL_INIT_TMR},
+ {0x0004, CMN_PLL1_VCOCAL_ITER_TMR},
+ {0x0317, CMN_PLL0_VCOCAL_REFTIM_START},
+ {0x0003, CMN_PLL0_VCOCAL_TCTRL},
+ {0x0317, CMN_PLL1_VCOCAL_REFTIM_START},
+ {0x0003, CMN_PLL1_VCOCAL_TCTRL}
+};
+
+static struct cdns_reg_pairs sl_dp_25_no_ssc_tx_ln_regs[] = {
+ {0x09C4, TX_RCVDET_ST_TMR},
+ {0x00FB, TX_PSC_A0},
+ {0x04AA, TX_PSC_A2},
+ {0x04AA, TX_PSC_A3},
+ {0x000F, XCVR_DIAG_BIDI_CTRL}
+};
+
+static struct cdns_reg_pairs sl_dp_25_no_ssc_rx_ln_regs[] = {
+ {0x0000, RX_PSC_A0},
+ {0x0000, RX_PSC_A2},
+ {0x0000, RX_PSC_A3},
+ {0x0000, RX_PSC_CAL},
+ {0x0000, RX_REE_GCSM1_CTRL},
+ {0x0000, RX_REE_GCSM2_CTRL},
+ {0x0000, RX_REE_PERGCSM_CTRL}
+};
+
+static struct cdns_torrent_vals sl_dp_25_no_ssc_cmn_vals = {
+ .reg_pairs = sl_dp_25_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_cmn_regs),
+};
+
+static struct cdns_torrent_vals sl_dp_25_no_ssc_tx_ln_vals = {
+ .reg_pairs = sl_dp_25_no_ssc_tx_ln_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_torrent_vals sl_dp_25_no_ssc_rx_ln_vals = {
+ .reg_pairs = sl_dp_25_no_ssc_rx_ln_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_rx_ln_regs),
+};
+
+/* Single DP, 100 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs sl_dp_100_no_ssc_cmn_regs[] = {
+ {0x0003, CMN_PLL0_VCOCAL_TCTRL},
+ {0x0003, CMN_PLL1_VCOCAL_TCTRL}
+};
+
+static struct cdns_reg_pairs sl_dp_100_no_ssc_tx_ln_regs[] = {
+ {0x00FB, TX_PSC_A0},
+ {0x04AA, TX_PSC_A2},
+ {0x04AA, TX_PSC_A3},
+ {0x000F, XCVR_DIAG_BIDI_CTRL}
+};
+
+static struct cdns_reg_pairs sl_dp_100_no_ssc_rx_ln_regs[] = {
+ {0x0000, RX_PSC_A0},
+ {0x0000, RX_PSC_A2},
+ {0x0000, RX_PSC_A3},
+ {0x0000, RX_PSC_CAL},
+ {0x0000, RX_REE_GCSM1_CTRL},
+ {0x0000, RX_REE_GCSM2_CTRL},
+ {0x0000, RX_REE_PERGCSM_CTRL}
+};
+
+static struct cdns_torrent_vals sl_dp_100_no_ssc_cmn_vals = {
+ .reg_pairs = sl_dp_100_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_cmn_regs),
+};
+
+static struct cdns_torrent_vals sl_dp_100_no_ssc_tx_ln_vals = {
+ .reg_pairs = sl_dp_100_no_ssc_tx_ln_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_torrent_vals sl_dp_100_no_ssc_rx_ln_vals = {
+ .reg_pairs = sl_dp_100_no_ssc_rx_ln_regs,
+ .num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_rx_ln_regs),
+};
+
/* USB and SGMII/QSGMII link configuration */
static struct cdns_reg_pairs usb_sgmii_link_cmn_regs[] = {
{0x0002, PHY_PLL_CFG},
@@ -3311,6 +3484,11 @@ static const struct cdns_torrent_data cdns_map_torrent = {
.block_offset_shift = 0x2,
.reg_offset_shift = 0x2,
.link_cmn_vals = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_link_cmn_vals,
+ },
+ },
[TYPE_PCIE] = {
[TYPE_NONE] = {
[NO_SSC] = NULL,
@@ -3387,6 +3565,11 @@ static const struct cdns_torrent_data cdns_map_torrent = {
},
},
.xcvr_diag_vals = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_xcvr_diag_ln_vals,
+ },
+ },
[TYPE_PCIE] = {
[TYPE_NONE] = {
[NO_SSC] = NULL,
@@ -3487,230 +3670,293 @@ static const struct cdns_torrent_data cdns_map_torrent = {
},
},
.cmn_vals = {
- [TYPE_PCIE] = {
- [TYPE_NONE] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals,
- },
- [TYPE_SGMII] = {
- [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
- },
- [TYPE_QSGMII] = {
- [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
- },
- },
- [TYPE_SGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [CLK_19_2_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_19_2_no_ssc_cmn_vals,
+ },
},
},
- [TYPE_QSGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [CLK_25_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_25_no_ssc_cmn_vals,
+ },
},
},
- [TYPE_USB] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ [CLK_100_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals,
+ },
},
[TYPE_PCIE] = {
- [NO_SSC] = &usb_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
+ },
},
[TYPE_SGMII] = {
- [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ },
},
[TYPE_QSGMII] = {
- [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
- },
- },
- },
- .tx_ln_vals = {
- [TYPE_PCIE] = {
- [TYPE_NONE] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = NULL,
- },
- [TYPE_SGMII] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = NULL,
- },
- [TYPE_QSGMII] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = NULL,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ },
},
[TYPE_USB] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = NULL,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &usb_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ },
},
},
- [TYPE_SGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
+ },
+ .tx_ln_vals = {
+ [CLK_19_2_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_19_2_no_ssc_tx_ln_vals,
+ },
},
},
- [TYPE_QSGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
+ [CLK_25_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_25_no_ssc_tx_ln_vals,
+ },
},
},
- [TYPE_USB] = {
- [TYPE_NONE] = {
- [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [CLK_100_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals,
+ },
},
[TYPE_PCIE] = {
- [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = NULL,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = NULL,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = NULL,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = NULL,
+ },
},
[TYPE_SGMII] = {
- [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
+ },
},
[TYPE_QSGMII] = {
- [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- },
- },
- },
- .rx_ln_vals = {
- [TYPE_PCIE] = {
- [TYPE_NONE] = {
- [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- },
- [TYPE_SGMII] = {
- [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- },
- [TYPE_QSGMII] = {
- [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
+ },
},
[TYPE_USB] = {
- [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
},
},
- [TYPE_SGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ },
+ .rx_ln_vals = {
+ [CLK_19_2_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_19_2_no_ssc_rx_ln_vals,
+ },
},
},
- [TYPE_QSGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [CLK_25_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_25_no_ssc_rx_ln_vals,
+ },
},
},
- [TYPE_USB] = {
- [TYPE_NONE] = {
- [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [CLK_100_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_PCIE] = {
- [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_SGMII] = {
- [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_QSGMII] = {
- [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ },
+ },
+ [TYPE_USB] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
},
},
},
@@ -3720,6 +3966,11 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
.block_offset_shift = 0x0,
.reg_offset_shift = 0x1,
.link_cmn_vals = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_link_cmn_vals,
+ },
+ },
[TYPE_PCIE] = {
[TYPE_NONE] = {
[NO_SSC] = NULL,
@@ -3796,6 +4047,11 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
},
},
.xcvr_diag_vals = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_xcvr_diag_ln_vals,
+ },
+ },
[TYPE_PCIE] = {
[TYPE_NONE] = {
[NO_SSC] = NULL,
@@ -3896,230 +4152,293 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
},
},
.cmn_vals = {
- [TYPE_PCIE] = {
- [TYPE_NONE] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals,
- },
- [TYPE_SGMII] = {
- [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
- },
- [TYPE_QSGMII] = {
- [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
- },
- },
- [TYPE_SGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [CLK_19_2_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_19_2_no_ssc_cmn_vals,
+ },
},
},
- [TYPE_QSGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [CLK_25_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_25_no_ssc_cmn_vals,
+ },
},
},
- [TYPE_USB] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ [CLK_100_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals,
+ },
},
[TYPE_PCIE] = {
- [NO_SSC] = &usb_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
+ },
},
[TYPE_SGMII] = {
- [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
+ },
},
[TYPE_QSGMII] = {
- [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
- [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
- },
- },
- },
- .tx_ln_vals = {
- [TYPE_PCIE] = {
- [TYPE_NONE] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = NULL,
- },
- [TYPE_SGMII] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = NULL,
- },
- [TYPE_QSGMII] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = NULL,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
+ },
},
[TYPE_USB] = {
- [NO_SSC] = NULL,
- [EXTERNAL_SSC] = NULL,
- [INTERNAL_SSC] = NULL,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &usb_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
+ [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
+ },
},
},
- [TYPE_SGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
+ },
+ .tx_ln_vals = {
+ [CLK_19_2_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_19_2_no_ssc_tx_ln_vals,
+ },
},
},
- [TYPE_QSGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
+ [CLK_25_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_25_no_ssc_tx_ln_vals,
+ },
},
},
- [TYPE_USB] = {
- [TYPE_NONE] = {
- [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [CLK_100_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals,
+ },
},
[TYPE_PCIE] = {
- [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- },
- [TYPE_SGMII] = {
- [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- },
- [TYPE_QSGMII] = {
- [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
- },
- },
- },
- .rx_ln_vals = {
- [TYPE_PCIE] = {
- [TYPE_NONE] = {
- [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = NULL,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = NULL,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = NULL,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = NULL,
+ [EXTERNAL_SSC] = NULL,
+ [INTERNAL_SSC] = NULL,
+ },
},
[TYPE_SGMII] = {
- [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
+ },
},
[TYPE_QSGMII] = {
- [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
+ },
},
[TYPE_USB] = {
- [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
+ },
},
},
- [TYPE_SGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ },
+ .rx_ln_vals = {
+ [CLK_19_2_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_19_2_no_ssc_rx_ln_vals,
+ },
},
},
- [TYPE_QSGMII] = {
- [TYPE_NONE] = {
- [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- },
- [TYPE_PCIE] = {
- [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- },
- [TYPE_USB] = {
- [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [CLK_25_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_25_no_ssc_rx_ln_vals,
+ },
},
},
- [TYPE_USB] = {
- [TYPE_NONE] = {
- [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [CLK_100_MHZ] = {
+ [TYPE_DP] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_PCIE] = {
- [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_SGMII] = {
- [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
+ },
},
[TYPE_QSGMII] = {
- [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
- [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [TYPE_NONE] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_USB] = {
+ [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
+ },
+ },
+ [TYPE_USB] = {
+ [TYPE_NONE] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_PCIE] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_SGMII] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
+ [TYPE_QSGMII] = {
+ [NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
+ },
},
},
},
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c
index 8ad8f717ef43..5fb4217fb8e0 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi.c
+++ b/drivers/phy/mediatek/phy-mtk-hdmi.c
@@ -100,7 +100,6 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mtk_hdmi_phy *hdmi_phy;
- struct resource *mem;
struct clk *ref_clk;
const char *ref_clk_name;
struct clk_init_data clk_init = {
@@ -116,11 +115,9 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
if (!hdmi_phy)
return -ENOMEM;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hdmi_phy->regs = devm_ioremap_resource(dev, mem);
- if (IS_ERR(hdmi_phy->regs)) {
+ hdmi_phy->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(hdmi_phy->regs))
return PTR_ERR(hdmi_phy->regs);
- }
ref_clk = devm_clk_get(dev, "pll_ref");
if (IS_ERR(ref_clk)) {
diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c
index 01cf31633019..28ad9403c441 100644
--- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c
+++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c
@@ -130,7 +130,6 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mtk_mipi_tx *mipi_tx;
- struct resource *mem;
const char *ref_clk_name;
struct clk *ref_clk;
struct clk_init_data clk_init = {
@@ -148,11 +147,9 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
mipi_tx->driver_data = of_device_get_match_data(dev);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mipi_tx->regs = devm_ioremap_resource(dev, mem);
- if (IS_ERR(mipi_tx->regs)) {
+ mipi_tx->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mipi_tx->regs))
return PTR_ERR(mipi_tx->regs);
- }
ref_clk = devm_clk_get(dev, NULL);
if (IS_ERR(ref_clk)) {
@@ -203,10 +200,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
phy_set_drvdata(phy, mipi_tx);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider)) {
- ret = PTR_ERR(phy_provider);
- return ret;
- }
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
mipi_tx->dev = dev;
diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
index 731c483a04de..cdcef865fe9e 100644
--- a/drivers/phy/mediatek/phy-mtk-tphy.c
+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
@@ -10,11 +10,13 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
/* version V1 sub-banks offset base address */
/* banks shared by multiple phys */
@@ -27,7 +29,8 @@
#define SSUSB_SIFSLV_V1_U3PHYD 0x000
#define SSUSB_SIFSLV_V1_U3PHYA 0x200
-/* version V2 sub-banks offset base address */
+/* version V2/V3 sub-banks offset base address */
+/* V3: U2FREQ is not used anymore, but reserved */
/* u2 phy banks */
#define SSUSB_SIFSLV_V2_MISC 0x000
#define SSUSB_SIFSLV_V2_U2FREQ 0x100
@@ -40,6 +43,8 @@
#define U3P_USBPHYACR0 0x000
#define PA0_RG_U2PLL_FORCE_ON BIT(15)
+#define PA0_USB20_PLL_PREDIV GENMASK(7, 6)
+#define PA0_USB20_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6)
#define PA0_RG_USB20_INTR_EN BIT(5)
#define U3P_USBPHYACR1 0x004
@@ -51,6 +56,8 @@
#define PA1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8)
#define U3P_USBPHYACR2 0x008
+#define PA2_RG_U2PLL_BW GENMASK(21, 19)
+#define PA2_RG_U2PLL_BW_VAL(x) ((0x7 & (x)) << 19)
#define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18)
#define U3P_USBPHYACR5 0x014
@@ -72,6 +79,14 @@
#define P2C_USB20_GPIO_MODE BIT(8)
#define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
+#define U3P_U2PHYA_RESV 0x030
+#define P2R_RG_U2PLL_FBDIV_26M 0x1bb13b
+#define P2R_RG_U2PLL_FBDIV_48M 0x3c0000
+
+#define U3P_U2PHYA_RESV1 0x044
+#define P2R_RG_U2PLL_REFCLK_SEL BIT(5)
+#define P2R_RG_U2PLL_FRA_EN BIT(3)
+
#define U3D_U2PHYDCR0 0x060
#define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24)
@@ -267,14 +282,31 @@
#define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
+/* PHY switch between pcie/usb3/sgmii/sata */
+#define USB_PHY_SWITCH_CTRL 0x0
+#define RG_PHY_SW_TYPE GENMASK(3, 0)
+#define RG_PHY_SW_PCIE 0x0
+#define RG_PHY_SW_USB3 0x1
+#define RG_PHY_SW_SGMII 0x2
+#define RG_PHY_SW_SATA 0x3
+
+#define TPHY_CLKS_CNT 2
+
enum mtk_phy_version {
MTK_PHY_V1 = 1,
MTK_PHY_V2,
+ MTK_PHY_V3,
};
struct mtk_phy_pdata {
/* avoid RX sensitivity level degradation only for mt8173 */
bool avoid_rx_sen_degradation;
+ /*
+ * workaround only for mt8195, HW fix it for others of V3,
+ * u2phy should use integer mode instead of fractional mode of
+ * 48M PLL, fix it by switching PLL to 26M from default 48M
+ */
+ bool sw_pll_48m_to_26m;
enum mtk_phy_version version;
};
@@ -298,10 +330,12 @@ struct mtk_phy_instance {
struct u2phy_banks u2_banks;
struct u3phy_banks u3_banks;
};
- struct clk *ref_clk; /* reference clock of (digital) phy */
- struct clk *da_ref_clk; /* reference clock of analog phy */
+ struct clk_bulk_data clks[TPHY_CLKS_CNT];
u32 index;
- u8 type;
+ u32 type;
+ struct regmap *type_sw;
+ u32 type_sw_reg;
+ u32 type_sw_index;
int eye_src;
int eye_vrt;
int eye_term;
@@ -330,6 +364,10 @@ static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
int fm_out;
u32 tmp;
+ /* HW V3 doesn't support slew rate cal anymore */
+ if (tphy->pdata->version == MTK_PHY_V3)
+ return;
+
/* use force value */
if (instance->eye_src)
return;
@@ -450,6 +488,33 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy,
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
}
+static void u2_phy_pll_26m_set(struct mtk_tphy *tphy,
+ struct mtk_phy_instance *instance)
+{
+ struct u2phy_banks *u2_banks = &instance->u2_banks;
+ void __iomem *com = u2_banks->com;
+ u32 tmp;
+
+ if (!tphy->pdata->sw_pll_48m_to_26m)
+ return;
+
+ tmp = readl(com + U3P_USBPHYACR0);
+ tmp &= ~PA0_USB20_PLL_PREDIV;
+ tmp |= PA0_USB20_PLL_PREDIV_VAL(0);
+ writel(tmp, com + U3P_USBPHYACR0);
+
+ tmp = readl(com + U3P_USBPHYACR2);
+ tmp &= ~PA2_RG_U2PLL_BW;
+ tmp |= PA2_RG_U2PLL_BW_VAL(3);
+ writel(tmp, com + U3P_USBPHYACR2);
+
+ writel(P2R_RG_U2PLL_FBDIV_26M, com + U3P_U2PHYA_RESV);
+
+ tmp = readl(com + U3P_U2PHYA_RESV1);
+ tmp |= P2R_RG_U2PLL_FRA_EN | P2R_RG_U2PLL_REFCLK_SEL;
+ writel(tmp, com + U3P_U2PHYA_RESV1);
+}
+
static void u2_phy_instance_init(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
@@ -509,6 +574,9 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy,
tmp |= PA6_RG_U2_SQTH_VAL(2);
writel(tmp, com + U3P_USBPHYACR6);
+ /* Workaround only for mt8195, HW fix it for others (V3) */
+ u2_phy_pll_26m_set(tphy, instance);
+
dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
}
@@ -878,7 +946,7 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
writel(tmp, com + U3P_U2PHYBC12C);
}
- if (instance->eye_src) {
+ if (tphy->pdata->version < MTK_PHY_V3 && instance->eye_src) {
tmp = readl(com + U3P_USBPHYACR5);
tmp &= ~PA5_RG_U2_HSTX_SRCTRL;
tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(instance->eye_src);
@@ -914,24 +982,73 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
}
}
-static int mtk_phy_init(struct phy *phy)
+/* type switch for usb3/pcie/sgmii/sata */
+static int phy_type_syscon_get(struct mtk_phy_instance *instance,
+ struct device_node *dn)
{
- struct mtk_phy_instance *instance = phy_get_drvdata(phy);
- struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
+ struct of_phandle_args args;
int ret;
- ret = clk_prepare_enable(instance->ref_clk);
- if (ret) {
- dev_err(tphy->dev, "failed to enable ref_clk\n");
+ /* type switch function is optional */
+ if (!of_property_read_bool(dn, "mediatek,syscon-type"))
+ return 0;
+
+ ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type",
+ 2, 0, &args);
+ if (ret)
return ret;
+
+ instance->type_sw_reg = args.args[0];
+ instance->type_sw_index = args.args[1] & 0x3; /* <=3 */
+ instance->type_sw = syscon_node_to_regmap(args.np);
+ of_node_put(args.np);
+ dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n",
+ instance->type_sw_reg, instance->type_sw_index);
+
+ return PTR_ERR_OR_ZERO(instance->type_sw);
+}
+
+static int phy_type_set(struct mtk_phy_instance *instance)
+{
+ int type;
+ u32 mask;
+
+ if (!instance->type_sw)
+ return 0;
+
+ switch (instance->type) {
+ case PHY_TYPE_USB3:
+ type = RG_PHY_SW_USB3;
+ break;
+ case PHY_TYPE_PCIE:
+ type = RG_PHY_SW_PCIE;
+ break;
+ case PHY_TYPE_SGMII:
+ type = RG_PHY_SW_SGMII;
+ break;
+ case PHY_TYPE_SATA:
+ type = RG_PHY_SW_SATA;
+ break;
+ case PHY_TYPE_USB2:
+ default:
+ return 0;
}
- ret = clk_prepare_enable(instance->da_ref_clk);
- if (ret) {
- dev_err(tphy->dev, "failed to enable da_ref\n");
- clk_disable_unprepare(instance->ref_clk);
+ mask = RG_PHY_SW_TYPE << (instance->type_sw_index * BITS_PER_BYTE);
+ regmap_update_bits(instance->type_sw, instance->type_sw_reg, mask, type);
+
+ return 0;
+}
+
+static int mtk_phy_init(struct phy *phy)
+{
+ struct mtk_phy_instance *instance = phy_get_drvdata(phy);
+ struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
+ int ret;
+
+ ret = clk_bulk_prepare_enable(TPHY_CLKS_CNT, instance->clks);
+ if (ret)
return ret;
- }
switch (instance->type) {
case PHY_TYPE_USB2:
@@ -947,10 +1064,12 @@ static int mtk_phy_init(struct phy *phy)
case PHY_TYPE_SATA:
sata_phy_instance_init(tphy, instance);
break;
+ case PHY_TYPE_SGMII:
+ /* nothing to do, only used to set type */
+ break;
default:
dev_err(tphy->dev, "incompatible PHY type\n");
- clk_disable_unprepare(instance->ref_clk);
- clk_disable_unprepare(instance->da_ref_clk);
+ clk_bulk_disable_unprepare(TPHY_CLKS_CNT, instance->clks);
return -EINVAL;
}
@@ -993,8 +1112,7 @@ static int mtk_phy_exit(struct phy *phy)
if (instance->type == PHY_TYPE_USB2)
u2_phy_instance_exit(tphy, instance);
- clk_disable_unprepare(instance->ref_clk);
- clk_disable_unprepare(instance->da_ref_clk);
+ clk_bulk_disable_unprepare(TPHY_CLKS_CNT, instance->clks);
return 0;
}
@@ -1037,21 +1155,27 @@ static struct phy *mtk_phy_xlate(struct device *dev,
if (!(instance->type == PHY_TYPE_USB2 ||
instance->type == PHY_TYPE_USB3 ||
instance->type == PHY_TYPE_PCIE ||
- instance->type == PHY_TYPE_SATA)) {
+ instance->type == PHY_TYPE_SATA ||
+ instance->type == PHY_TYPE_SGMII)) {
dev_err(dev, "unsupported device type: %d\n", instance->type);
return ERR_PTR(-EINVAL);
}
- if (tphy->pdata->version == MTK_PHY_V1) {
+ switch (tphy->pdata->version) {
+ case MTK_PHY_V1:
phy_v1_banks_init(tphy, instance);
- } else if (tphy->pdata->version == MTK_PHY_V2) {
+ break;
+ case MTK_PHY_V2:
+ case MTK_PHY_V3:
phy_v2_banks_init(tphy, instance);
- } else {
+ break;
+ default:
dev_err(dev, "phy version is not supported\n");
return ERR_PTR(-EINVAL);
}
phy_parse_property(tphy, instance);
+ phy_type_set(instance);
return instance->phy;
}
@@ -1075,17 +1199,28 @@ static const struct mtk_phy_pdata tphy_v2_pdata = {
.version = MTK_PHY_V2,
};
+static const struct mtk_phy_pdata tphy_v3_pdata = {
+ .version = MTK_PHY_V3,
+};
+
static const struct mtk_phy_pdata mt8173_pdata = {
.avoid_rx_sen_degradation = true,
.version = MTK_PHY_V1,
};
+static const struct mtk_phy_pdata mt8195_pdata = {
+ .sw_pll_48m_to_26m = true,
+ .version = MTK_PHY_V3,
+};
+
static const struct of_device_id mtk_tphy_id_table[] = {
{ .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata },
{ .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata },
{ .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata },
+ { .compatible = "mediatek,mt8195-tphy", .data = &mt8195_pdata },
{ .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata },
{ .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata },
+ { .compatible = "mediatek,generic-tphy-v3", .data = &tphy_v3_pdata },
{ },
};
MODULE_DEVICE_TABLE(of, mtk_tphy_id_table);
@@ -1129,16 +1264,21 @@ static int mtk_tphy_probe(struct platform_device *pdev)
}
}
- tphy->src_ref_clk = U3P_REF_CLK;
- tphy->src_coef = U3P_SLEW_RATE_COEF;
- /* update parameters of slew rate calibrate if exist */
- device_property_read_u32(dev, "mediatek,src-ref-clk-mhz",
- &tphy->src_ref_clk);
- device_property_read_u32(dev, "mediatek,src-coef", &tphy->src_coef);
+ if (tphy->pdata->version < MTK_PHY_V3) {
+ tphy->src_ref_clk = U3P_REF_CLK;
+ tphy->src_coef = U3P_SLEW_RATE_COEF;
+ /* update parameters of slew rate calibrate if exist */
+ device_property_read_u32(dev, "mediatek,src-ref-clk-mhz",
+ &tphy->src_ref_clk);
+ device_property_read_u32(dev, "mediatek,src-coef",
+ &tphy->src_coef);
+ }
port = 0;
for_each_child_of_node(np, child_np) {
struct mtk_phy_instance *instance;
+ struct clk_bulk_data *clks;
+ struct device *subdev;
struct phy *phy;
instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
@@ -1156,16 +1296,16 @@ static int mtk_tphy_probe(struct platform_device *pdev)
goto put_child;
}
+ subdev = &phy->dev;
retval = of_address_to_resource(child_np, 0, &res);
if (retval) {
- dev_err(dev, "failed to get address resource(id-%d)\n",
+ dev_err(subdev, "failed to get address resource(id-%d)\n",
port);
goto put_child;
}
- instance->port_base = devm_ioremap_resource(&phy->dev, &res);
+ instance->port_base = devm_ioremap_resource(subdev, &res);
if (IS_ERR(instance->port_base)) {
- dev_err(dev, "failed to remap phy regs\n");
retval = PTR_ERR(instance->port_base);
goto put_child;
}
@@ -1175,20 +1315,16 @@ static int mtk_tphy_probe(struct platform_device *pdev)
phy_set_drvdata(phy, instance);
port++;
- instance->ref_clk = devm_clk_get_optional(&phy->dev, "ref");
- if (IS_ERR(instance->ref_clk)) {
- dev_err(dev, "failed to get ref_clk(id-%d)\n", port);
- retval = PTR_ERR(instance->ref_clk);
+ clks = instance->clks;
+ clks[0].id = "ref"; /* digital (& analog) clock */
+ clks[1].id = "da_ref"; /* analog clock */
+ retval = devm_clk_bulk_get_optional(subdev, TPHY_CLKS_CNT, clks);
+ if (retval)
goto put_child;
- }
- instance->da_ref_clk =
- devm_clk_get_optional(&phy->dev, "da_ref");
- if (IS_ERR(instance->da_ref_clk)) {
- dev_err(dev, "failed to get da_ref_clk(id-%d)\n", port);
- retval = PTR_ERR(instance->da_ref_clk);
+ retval = phy_type_syscon_get(instance, child_np);
+ if (retval)
goto put_child;
- }
}
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
diff --git a/drivers/phy/mediatek/phy-mtk-ufs.c b/drivers/phy/mediatek/phy-mtk-ufs.c
index 769b00b038d8..a6af06941203 100644
--- a/drivers/phy/mediatek/phy-mtk-ufs.c
+++ b/drivers/phy/mediatek/phy-mtk-ufs.c
@@ -31,11 +31,12 @@
#define FRC_CDR_ISO_EN BIT(19)
#define CDR_ISO_EN BIT(20)
+#define UFSPHY_CLKS_CNT 2
+
struct ufs_mtk_phy {
struct device *dev;
void __iomem *mmio;
- struct clk *mp_clk;
- struct clk *unipro_clk;
+ struct clk_bulk_data clks[UFSPHY_CLKS_CNT];
};
static inline u32 mphy_readl(struct ufs_mtk_phy *phy, u32 reg)
@@ -74,20 +75,11 @@ static struct ufs_mtk_phy *get_ufs_mtk_phy(struct phy *generic_phy)
static int ufs_mtk_phy_clk_init(struct ufs_mtk_phy *phy)
{
struct device *dev = phy->dev;
+ struct clk_bulk_data *clks = phy->clks;
- phy->unipro_clk = devm_clk_get(dev, "unipro");
- if (IS_ERR(phy->unipro_clk)) {
- dev_err(dev, "failed to get clock: unipro");
- return PTR_ERR(phy->unipro_clk);
- }
-
- phy->mp_clk = devm_clk_get(dev, "mp");
- if (IS_ERR(phy->mp_clk)) {
- dev_err(dev, "failed to get clock: mp");
- return PTR_ERR(phy->mp_clk);
- }
-
- return 0;
+ clks[0].id = "unipro";
+ clks[1].id = "mp";
+ return devm_clk_bulk_get(dev, UFSPHY_CLKS_CNT, clks);
}
static void ufs_mtk_phy_set_active(struct ufs_mtk_phy *phy)
@@ -150,26 +142,13 @@ static int ufs_mtk_phy_power_on(struct phy *generic_phy)
struct ufs_mtk_phy *phy = get_ufs_mtk_phy(generic_phy);
int ret;
- ret = clk_prepare_enable(phy->unipro_clk);
- if (ret) {
- dev_err(phy->dev, "unipro_clk enable failed %d\n", ret);
- goto out;
- }
-
- ret = clk_prepare_enable(phy->mp_clk);
- if (ret) {
- dev_err(phy->dev, "mp_clk enable failed %d\n", ret);
- goto out_unprepare_unipro_clk;
- }
+ ret = clk_bulk_prepare_enable(UFSPHY_CLKS_CNT, phy->clks);
+ if (ret)
+ return ret;
ufs_mtk_phy_set_active(phy);
return 0;
-
-out_unprepare_unipro_clk:
- clk_disable_unprepare(phy->unipro_clk);
-out:
- return ret;
}
static int ufs_mtk_phy_power_off(struct phy *generic_phy)
@@ -178,8 +157,7 @@ static int ufs_mtk_phy_power_off(struct phy *generic_phy)
ufs_mtk_phy_set_deep_hibern(phy);
- clk_disable_unprepare(phy->unipro_clk);
- clk_disable_unprepare(phy->mp_clk);
+ clk_bulk_disable_unprepare(UFSPHY_CLKS_CNT, phy->clks);
return 0;
}
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index cfe359488f5c..f14032170b1c 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -234,6 +234,11 @@ static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_READY_STATUS] = 0x160,
};
+static const unsigned int sm6115_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_START_CTRL] = 0x00,
+ [QPHY_PCS_READY_STATUS] = 0x168,
+};
+
static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = 0x00,
[QPHY_START_CTRL] = 0x44,
@@ -1329,6 +1334,97 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60),
};
+static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00),
+
+ /* Rate B */
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44),
+};
+
+static const struct qmp_phy_init_tbl sm6115_ufsphy_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
+ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
+};
+
+static const struct qmp_phy_init_tbl sm6115_ufsphy_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B),
+};
+
+static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_RX_PWM_GEAR_BAND, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_CTRL2, 0x6d),
+ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_DRV_LVL, 0x0f),
+ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_DRV_LVL, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28),
+ QMP_PHY_INIT_CFG(QPHY_RX_SYM_RESYNC_CTRL, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_POST_EMP_LVL, 0x12),
+ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_POST_EMP_LVL, 0x0f),
+ QMP_PHY_INIT_CFG(QPHY_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */
+};
+
static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
@@ -2035,6 +2131,113 @@ static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20),
};
+static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90),
+};
+
+static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x5),
+};
+
+static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x6e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x4a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x37),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x39),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x39),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x75),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0xc0),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03),
+};
+
+static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x01),
+};
+
+static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
+};
+
static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
@@ -3289,6 +3492,31 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
.no_pcs_sw_reset = true,
};
+static const struct qmp_phy_cfg sm6115_ufsphy_cfg = {
+ .type = PHY_TYPE_UFS,
+ .nlanes = 1,
+
+ .serdes_tbl = sm6115_ufsphy_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl),
+ .tx_tbl = sm6115_ufsphy_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_tx_tbl),
+ .rx_tbl = sm6115_ufsphy_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_rx_tbl),
+ .pcs_tbl = sm6115_ufsphy_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sm6115_ufsphy_pcs_tbl),
+ .clk_list = sdm845_ufs_phy_clk_l,
+ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = sm6115_ufsphy_regs_layout,
+
+ .start_ctrl = SERDES_START,
+ .pwrdn_ctrl = SW_PWRDN,
+
+ .is_dual_lane_phy = false,
+ .no_pcs_sw_reset = true,
+};
+
static const struct qmp_phy_cfg msm8998_pciephy_cfg = {
.type = PHY_TYPE_PCIE,
.nlanes = 1,
@@ -3399,6 +3627,76 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
.is_dual_lane_phy = true,
};
+static const struct qmp_phy_cfg sc8180x_pciephy_cfg = {
+ .type = PHY_TYPE_PCIE,
+ .nlanes = 1,
+
+ .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl),
+ .tx_tbl = sc8180x_qmp_pcie_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl),
+ .rx_tbl = sc8180x_qmp_pcie_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl),
+ .pcs_tbl = sc8180x_qmp_pcie_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl),
+ .pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl,
+ .pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl),
+ .clk_list = sdm845_pciephy_clk_l,
+ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = sm8250_pcie_regs_layout,
+
+ .start_ctrl = PCS_START | SERDES_START,
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+
+ .has_pwrdn_delay = true,
+ .pwrdn_delay_min = 995, /* us */
+ .pwrdn_delay_max = 1005, /* us */
+};
+
+static const struct qmp_phy_cfg sc8180x_dpphy_cfg = {
+ .type = PHY_TYPE_DP,
+ .nlanes = 1,
+
+ .serdes_tbl = qmp_v4_dp_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl),
+ .tx_tbl = qmp_v4_dp_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl),
+
+ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr,
+ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr),
+ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr,
+ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr),
+ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2,
+ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2),
+ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3,
+ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3),
+
+ .clk_list = qmp_v3_phy_clk_l,
+ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l),
+ .reset_list = sc7180_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v3_usb3phy_regs_layout,
+
+ .has_phy_dp_com_ctrl = true,
+ .is_dual_lane_phy = true,
+
+ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init,
+ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx,
+ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy,
+ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate,
+};
+
+static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = {
+ .usb_cfg = &sm8150_usb3phy_cfg,
+ .dp_cfg = &sc8180x_dpphy_cfg,
+};
+
static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
.type = PHY_TYPE_USB3,
.nlanes = 1,
@@ -5018,6 +5316,7 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy,
{
struct clk_init_data init = { };
struct qmp_phy_dp_clks *dp_clks;
+ char name[64];
int ret;
dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL);
@@ -5027,15 +5326,17 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy,
dp_clks->qphy = qphy;
qphy->dp_clks = dp_clks;
+ snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev));
init.ops = &qcom_qmp_dp_link_clk_ops;
- init.name = "qmp_dp_phy_pll_link_clk";
+ init.name = name;
dp_clks->dp_link_hw.init = &init;
ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw);
if (ret)
return ret;
+ snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev));
init.ops = &qcom_qmp_dp_pixel_clk_ops;
- init.name = "qmp_dp_phy_pll_vco_div_clk";
+ init.name = name;
dp_clks->dp_pixel_hw.init = &init;
ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw);
if (ret)
@@ -5226,18 +5527,27 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
.compatible = "qcom,ipq6018-qmp-pcie-phy",
.data = &ipq6018_pciephy_cfg,
}, {
+ .compatible = "qcom,ipq6018-qmp-usb3-phy",
+ .data = &ipq8074_usb3phy_cfg,
+ }, {
.compatible = "qcom,sc7180-qmp-usb3-phy",
.data = &sc7180_usb3phy_cfg,
}, {
.compatible = "qcom,sc7180-qmp-usb3-dp-phy",
/* It's a combo phy */
}, {
+ .compatible = "qcom,sc8180x-qmp-pcie-phy",
+ .data = &sc8180x_pciephy_cfg,
+ }, {
.compatible = "qcom,sc8180x-qmp-ufs-phy",
.data = &sm8150_ufsphy_cfg,
}, {
.compatible = "qcom,sc8180x-qmp-usb3-phy",
.data = &sm8150_usb3phy_cfg,
}, {
+ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy",
+ /* It's a combo phy */
+ }, {
.compatible = "qcom,sdm845-qhp-pcie-phy",
.data = &sdm845_qhp_pciephy_cfg,
}, {
@@ -5256,6 +5566,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
.compatible = "qcom,msm8998-qmp-usb3-phy",
.data = &msm8998_usb3phy_cfg,
}, {
+ .compatible = "qcom,sm6115-qmp-ufs-phy",
+ .data = &sm6115_ufsphy_cfg,
+ }, {
.compatible = "qcom,sm8150-qmp-ufs-phy",
.data = &sm8150_ufsphy_cfg,
}, {
@@ -5314,6 +5627,10 @@ static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = {
.compatible = "qcom,sm8250-qmp-usb3-dp-phy",
.data = &sm8250_usb3dpphy_cfg,
},
+ {
+ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy",
+ .data = &sc8180x_usb3dpphy_cfg,
+ },
{ }
};
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index 6592b58b13f6..bebeac2c091c 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -191,6 +191,8 @@
#define QSERDES_COM_VCO_TUNE2_MODE0 0x130
#define QSERDES_COM_VCO_TUNE1_MODE1 0x134
#define QSERDES_COM_VCO_TUNE2_MODE1 0x138
+#define QSERDES_COM_VCO_TUNE_INITVAL1 0x13c
+#define QSERDES_COM_VCO_TUNE_INITVAL2 0x140
#define QSERDES_COM_VCO_TUNE_TIMER1 0x144
#define QSERDES_COM_VCO_TUNE_TIMER2 0x148
#define QSERDES_COM_BG_CTRL 0x170
@@ -220,6 +222,10 @@
/* Only for QMP V2 PHY - RX registers */
#define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010
#define QSERDES_RX_UCDR_SO_GAIN 0x01c
+#define QSERDES_RX_UCDR_SVS_SO_GAIN_HALF 0x030
+#define QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER 0x034
+#define QSERDES_RX_UCDR_SVS_SO_GAIN_EIGHTH 0x038
+#define QSERDES_RX_UCDR_SVS_SO_GAIN 0x03c
#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040
#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048
#define QSERDES_RX_RX_TERM_BW 0x090
@@ -243,6 +249,10 @@
#define QPHY_POWER_DOWN_CONTROL 0x04
#define QPHY_TXDEEMPH_M6DB_V0 0x24
#define QPHY_TXDEEMPH_M3P5DB_V0 0x28
+#define QPHY_TX_LARGE_AMP_DRV_LVL 0x34
+#define QPHY_TX_LARGE_AMP_POST_EMP_LVL 0x38
+#define QPHY_TX_SMALL_AMP_DRV_LVL 0x3c
+#define QPHY_TX_SMALL_AMP_POST_EMP_LVL 0x40
#define QPHY_ENDPOINT_REFCLK_DRIVE 0x54
#define QPHY_RX_IDLE_DTCT_CNTRL 0x58
#define QPHY_POWER_STATE_CONFIG1 0x60
@@ -253,6 +263,11 @@
#define QPHY_LOCK_DETECT_CONFIG3 0x88
#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
+#define QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP 0xcc
+#define QPHY_RX_SYM_RESYNC_CTRL 0x13c
+#define QPHY_RX_MIN_HIBERN8_TIME 0x140
+#define QPHY_RX_SIGDET_CTRL2 0x148
+#define QPHY_RX_PWM_GEAR_BAND 0x154
#define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8
#define QPHY_OSC_DTCT_ACTIONS 0x1AC
#define QPHY_RX_SIGDET_LVL 0x1D8
@@ -280,6 +295,8 @@
#define QSERDES_V3_COM_SSC_PER2 0x020
#define QSERDES_V3_COM_SSC_STEP_SIZE1 0x024
#define QSERDES_V3_COM_SSC_STEP_SIZE2 0x028
+#define QSERDES_V3_COM_POST_DIV 0x02c
+#define QSERDES_V3_COM_POST_DIV_MUX 0x030
#define QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN 0x034
# define QSERDES_V3_COM_BIAS_EN 0x0001
# define QSERDES_V3_COM_BIAS_EN_MUX 0x0002
@@ -291,6 +308,7 @@
#define QSERDES_V3_COM_CLK_ENABLE1 0x038
#define QSERDES_V3_COM_SYS_CLK_CTRL 0x03c
#define QSERDES_V3_COM_SYSCLK_BUF_ENABLE 0x040
+#define QSERDES_V3_COM_PLL_EN 0x044
#define QSERDES_V3_COM_PLL_IVCO 0x048
#define QSERDES_V3_COM_LOCK_CMP1_MODE0 0x098
#define QSERDES_V3_COM_LOCK_CMP2_MODE0 0x09c
diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
index 5c6c17673396..53e46c220a3a 100644
--- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c
+++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/**
+/*
* Copyright (C) 2016 Linaro Ltd
*/
#include <linux/module.h>
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index fbc55232120e..9de617ca9daa 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -64,6 +64,7 @@
/* VBCTRL */
#define USB2_VBCTRL_OCCLREN BIT(16)
#define USB2_VBCTRL_DRVVBUSSEL BIT(8)
+#define USB2_VBCTRL_VBOUT BIT(0)
/* LINECTRL1 */
#define USB2_LINECTRL1_DPRPD_EN BIT(19)
@@ -78,6 +79,10 @@
#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */
#define USB2_ADPCTRL_DRVVBUS BIT(4)
+/* RZ/G2L specific */
+#define USB2_OBINT_IDCHG_EN BIT(0)
+#define USB2_LINECTRL1_USB2_IDMON BIT(0)
+
#define NUM_OF_PHYS 4
enum rcar_gen3_phy_index {
PHY_INDEX_BOTH_HC,
@@ -112,9 +117,16 @@ struct rcar_gen3_chan {
struct mutex lock; /* protects rphys[...].powered */
enum usb_dr_mode dr_mode;
int irq;
+ u32 obint_enable_bits;
bool extcon_host;
bool is_otg_channel;
bool uses_otg_pins;
+ bool soc_no_adp_ctrl;
+};
+
+struct rcar_gen3_phy_drv_data {
+ const struct phy_ops *phy_usb2_ops;
+ bool no_adp_ctrl;
};
/*
@@ -172,14 +184,22 @@ static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
{
void __iomem *usb2_base = ch->base;
- u32 val = readl(usb2_base + USB2_ADPCTRL);
+ u32 vbus_ctrl_reg = USB2_ADPCTRL;
+ u32 vbus_ctrl_val = USB2_ADPCTRL_DRVVBUS;
+ u32 val;
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
+ if (ch->soc_no_adp_ctrl) {
+ vbus_ctrl_reg = USB2_VBCTRL;
+ vbus_ctrl_val = USB2_VBCTRL_VBOUT;
+ }
+
+ val = readl(usb2_base + vbus_ctrl_reg);
if (vbus)
- val |= USB2_ADPCTRL_DRVVBUS;
+ val |= vbus_ctrl_val;
else
- val &= ~USB2_ADPCTRL_DRVVBUS;
- writel(val, usb2_base + USB2_ADPCTRL);
+ val &= ~vbus_ctrl_val;
+ writel(val, usb2_base + vbus_ctrl_reg);
}
static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable)
@@ -188,9 +208,9 @@ static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable)
u32 val = readl(usb2_base + USB2_OBINTEN);
if (ch->uses_otg_pins && enable)
- val |= USB2_OBINT_BITS;
+ val |= ch->obint_enable_bits;
else
- val &= ~USB2_OBINT_BITS;
+ val &= ~ch->obint_enable_bits;
writel(val, usb2_base + USB2_OBINTEN);
}
@@ -252,6 +272,9 @@ static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
if (!ch->uses_otg_pins)
return (ch->dr_mode == USB_DR_MODE_HOST) ? false : true;
+ if (ch->soc_no_adp_ctrl)
+ return !!(readl(ch->base + USB2_LINECTRL1) & USB2_LINECTRL1_USB2_IDMON);
+
return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
}
@@ -376,16 +399,17 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
USB2_LINECTRL1_DMRPD_EN | USB2_LINECTRL1_DM_RPD;
writel(val, usb2_base + USB2_LINECTRL1);
- val = readl(usb2_base + USB2_VBCTRL);
- val &= ~USB2_VBCTRL_OCCLREN;
- writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
- val = readl(usb2_base + USB2_ADPCTRL);
- writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
-
+ if (!ch->soc_no_adp_ctrl) {
+ val = readl(usb2_base + USB2_VBCTRL);
+ val &= ~USB2_VBCTRL_OCCLREN;
+ writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
+ val = readl(usb2_base + USB2_ADPCTRL);
+ writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
+ }
msleep(20);
writel(0xffffffff, usb2_base + USB2_OBINTSTA);
- writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+ writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN);
rcar_gen3_device_recognition(ch);
}
@@ -397,9 +421,9 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
u32 status = readl(usb2_base + USB2_OBINTSTA);
irqreturn_t ret = IRQ_NONE;
- if (status & USB2_OBINT_BITS) {
+ if (status & ch->obint_enable_bits) {
dev_vdbg(ch->dev, "%s: %08x\n", __func__, status);
- writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
+ writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA);
rcar_gen3_device_recognition(ch);
ret = IRQ_HANDLED;
}
@@ -535,26 +559,45 @@ static const struct phy_ops rz_g1c_phy_usb2_ops = {
.owner = THIS_MODULE,
};
+static const struct rcar_gen3_phy_drv_data rcar_gen3_phy_usb2_data = {
+ .phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
+ .no_adp_ctrl = false,
+};
+
+static const struct rcar_gen3_phy_drv_data rz_g1c_phy_usb2_data = {
+ .phy_usb2_ops = &rz_g1c_phy_usb2_ops,
+ .no_adp_ctrl = false,
+};
+
+static const struct rcar_gen3_phy_drv_data rz_g2l_phy_usb2_data = {
+ .phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
+ .no_adp_ctrl = true,
+};
+
static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
{
.compatible = "renesas,usb2-phy-r8a77470",
- .data = &rz_g1c_phy_usb2_ops,
+ .data = &rz_g1c_phy_usb2_data,
},
{
.compatible = "renesas,usb2-phy-r8a7795",
- .data = &rcar_gen3_phy_usb2_ops,
+ .data = &rcar_gen3_phy_usb2_data,
},
{
.compatible = "renesas,usb2-phy-r8a7796",
- .data = &rcar_gen3_phy_usb2_ops,
+ .data = &rcar_gen3_phy_usb2_data,
},
{
.compatible = "renesas,usb2-phy-r8a77965",
- .data = &rcar_gen3_phy_usb2_ops,
+ .data = &rcar_gen3_phy_usb2_data,
+ },
+ {
+ .compatible = "renesas,rzg2l-usb2-phy",
+ .data = &rz_g2l_phy_usb2_data,
},
{
.compatible = "renesas,rcar-gen3-usb2-phy",
- .data = &rcar_gen3_phy_usb2_ops,
+ .data = &rcar_gen3_phy_usb2_data,
},
{ /* sentinel */ },
};
@@ -608,10 +651,10 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np)
static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
{
+ const struct rcar_gen3_phy_drv_data *phy_data;
struct device *dev = &pdev->dev;
struct rcar_gen3_chan *channel;
struct phy_provider *provider;
- const struct phy_ops *phy_usb2_ops;
int ret = 0, i;
if (!dev->of_node) {
@@ -627,6 +670,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
if (IS_ERR(channel->base))
return PTR_ERR(channel->base);
+ channel->obint_enable_bits = USB2_OBINT_BITS;
/* get irq number here and request_irq for OTG in phy_init */
channel->irq = platform_get_irq_optional(pdev, 0);
channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node);
@@ -653,16 +697,21 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
* And then, phy-core will manage runtime pm for this device.
*/
pm_runtime_enable(dev);
- phy_usb2_ops = of_device_get_match_data(dev);
- if (!phy_usb2_ops) {
+
+ phy_data = of_device_get_match_data(dev);
+ if (!phy_data) {
ret = -EINVAL;
goto error;
}
+ channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
+ if (phy_data->no_adp_ctrl)
+ channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
+
mutex_init(&channel->lock);
for (i = 0; i < NUM_OF_PHYS; i++) {
channel->rphys[i].phy = devm_phy_create(dev, NULL,
- phy_usb2_ops);
+ phy_data->phy_usb2_ops);
if (IS_ERR(channel->rphys[i].phy)) {
dev_err(dev, "Failed to create USB2 PHY\n");
ret = PTR_ERR(channel->rphys[i].phy);
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index beacac1dd253..4f569d9307b9 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -1180,8 +1180,10 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
next_child:
/* to prevent out of boundary */
- if (++index >= rphy->phy_cfg->num_ports)
+ if (++index >= rphy->phy_cfg->num_ports) {
+ of_node_put(child_np);
break;
+ }
}
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile
index 3959100fe8a2..65e4cc59403f 100644
--- a/drivers/phy/samsung/Makefile
+++ b/drivers/phy/samsung/Makefile
@@ -2,7 +2,10 @@
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o
-obj-$(CONFIG_PHY_SAMSUNG_UFS) += phy-samsung-ufs.o
+obj-$(CONFIG_PHY_SAMSUNG_UFS) += phy-exynos-ufs.o
+phy-exynos-ufs-y += phy-samsung-ufs.o
+phy-exynos-ufs-y += phy-exynos7-ufs.o
+phy-exynos-ufs-y += phy-exynosautov9-ufs.o
obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
phy-exynos-usb2-y += phy-samsung-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
diff --git a/drivers/phy/samsung/phy-exynos7-ufs.h b/drivers/phy/samsung/phy-exynos7-ufs.c
index 518923141958..7c9008e163db 100644
--- a/drivers/phy/samsung/phy-exynos7-ufs.h
+++ b/drivers/phy/samsung/phy-exynos7-ufs.c
@@ -1,11 +1,9 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+// SPDX-License-Identifier: GPL-2.0-only
/*
* UFS PHY driver data for Samsung EXYNOS7 SoC
*
* Copyright (C) 2020 Samsung Electronics Co., Ltd.
*/
-#ifndef _PHY_EXYNOS7_UFS_H_
-#define _PHY_EXYNOS7_UFS_H_
#include "phy-samsung-ufs.h"
@@ -68,7 +66,7 @@ static const struct samsung_ufs_phy_cfg *exynos7_ufs_phy_cfgs[CFG_TAG_MAX] = {
[CFG_POST_PWR_HS] = exynos7_post_pwr_hs_cfg,
};
-static struct samsung_ufs_phy_drvdata exynos7_ufs_phy = {
+const struct samsung_ufs_phy_drvdata exynos7_ufs_phy = {
.cfg = exynos7_ufs_phy_cfgs,
.isol = {
.offset = EXYNOS7_EMBEDDED_COMBO_PHY_CTRL,
@@ -77,5 +75,3 @@ static struct samsung_ufs_phy_drvdata exynos7_ufs_phy = {
},
.has_symbol_clk = 1,
};
-
-#endif /* _PHY_EXYNOS7_UFS_H_ */
diff --git a/drivers/phy/samsung/phy-exynosautov9-ufs.c b/drivers/phy/samsung/phy-exynosautov9-ufs.c
new file mode 100644
index 000000000000..36398a15c2db
--- /dev/null
+++ b/drivers/phy/samsung/phy-exynosautov9-ufs.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * UFS PHY driver data for Samsung EXYNOSAUTO v9 SoC
+ *
+ * Copyright (C) 2021 Samsung Electronics Co., Ltd.
+ */
+
+#include "phy-samsung-ufs.h"
+
+#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL 0x728
+#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_MASK 0x1
+#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_EN BIT(0)
+
+#define PHY_TRSV_REG_CFG_AUTOV9(o, v, d) \
+ PHY_TRSV_REG_CFG_OFFSET(o, v, d, 0x50)
+
+/* Calibration for phy initialization */
+static const struct samsung_ufs_phy_cfg exynosautov9_pre_init_cfg[] = {
+ PHY_COMN_REG_CFG(0x023, 0x80, PWR_MODE_ANY),
+ PHY_COMN_REG_CFG(0x01d, 0x10, PWR_MODE_ANY),
+
+ PHY_TRSV_REG_CFG_AUTOV9(0x044, 0xb5, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_AUTOV9(0x04d, 0x43, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_AUTOV9(0x05b, 0x20, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_AUTOV9(0x05e, 0xc0, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_AUTOV9(0x038, 0x12, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_AUTOV9(0x059, 0x58, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_AUTOV9(0x06c, 0x18, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_AUTOV9(0x06d, 0x02, PWR_MODE_ANY),
+
+ PHY_COMN_REG_CFG(0x023, 0xc0, PWR_MODE_ANY),
+ PHY_COMN_REG_CFG(0x023, 0x00, PWR_MODE_ANY),
+
+ PHY_TRSV_REG_CFG(0x042, 0x5d, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG(0x043, 0x80, PWR_MODE_ANY),
+
+ END_UFS_PHY_CFG,
+};
+
+/* Calibration for HS mode series A/B */
+static const struct samsung_ufs_phy_cfg exynosautov9_pre_pwr_hs_cfg[] = {
+ PHY_TRSV_REG_CFG(0x032, 0xbc, PWR_MODE_HS_ANY),
+ PHY_TRSV_REG_CFG(0x03c, 0x7f, PWR_MODE_HS_ANY),
+ PHY_TRSV_REG_CFG(0x048, 0xc0, PWR_MODE_HS_ANY),
+
+ PHY_TRSV_REG_CFG(0x04a, 0x00, PWR_MODE_HS_G3_SER_B),
+ PHY_TRSV_REG_CFG(0x04b, 0x10, PWR_MODE_HS_G1_SER_B |
+ PWR_MODE_HS_G3_SER_B),
+ PHY_TRSV_REG_CFG(0x04d, 0x63, PWR_MODE_HS_G3_SER_B),
+
+ END_UFS_PHY_CFG,
+};
+
+static const struct samsung_ufs_phy_cfg *exynosautov9_ufs_phy_cfgs[CFG_TAG_MAX] = {
+ [CFG_PRE_INIT] = exynosautov9_pre_init_cfg,
+ [CFG_PRE_PWR_HS] = exynosautov9_pre_pwr_hs_cfg,
+};
+
+const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy = {
+ .cfg = exynosautov9_ufs_phy_cfgs,
+ .isol = {
+ .offset = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL,
+ .mask = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_MASK,
+ .en = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_EN,
+ },
+ .has_symbol_clk = 0,
+};
diff --git a/drivers/phy/samsung/phy-samsung-ufs.c b/drivers/phy/samsung/phy-samsung-ufs.c
index dd9ab1519d83..602ddef259eb 100644
--- a/drivers/phy/samsung/phy-samsung-ufs.c
+++ b/drivers/phy/samsung/phy-samsung-ufs.c
@@ -347,6 +347,9 @@ static const struct of_device_id samsung_ufs_phy_match[] = {
{
.compatible = "samsung,exynos7-ufs-phy",
.data = &exynos7_ufs_phy,
+ }, {
+ .compatible = "samsung,exynosautov9-ufs-phy",
+ .data = &exynosautov9_ufs_phy,
},
{},
};
diff --git a/drivers/phy/samsung/phy-samsung-ufs.h b/drivers/phy/samsung/phy-samsung-ufs.h
index 5de78710524c..91a0e9f94f98 100644
--- a/drivers/phy/samsung/phy-samsung-ufs.h
+++ b/drivers/phy/samsung/phy-samsung-ufs.h
@@ -10,6 +10,9 @@
#ifndef _PHY_SAMSUNG_UFS_
#define _PHY_SAMSUNG_UFS_
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
#define PHY_COMN_BLK 1
#define PHY_TRSV_BLK 2
#define END_UFS_PHY_CFG { 0 }
@@ -24,14 +27,17 @@
.id = PHY_COMN_BLK, \
}
-#define PHY_TRSV_REG_CFG(o, v, d) { \
+#define PHY_TRSV_REG_CFG_OFFSET(o, v, d, c) { \
.off_0 = PHY_APB_ADDR((o)), \
- .off_1 = PHY_APB_ADDR((o) + PHY_TRSV_CH_OFFSET), \
+ .off_1 = PHY_APB_ADDR((o) + (c)), \
.val = (v), \
.desc = (d), \
.id = PHY_TRSV_BLK, \
}
+#define PHY_TRSV_REG_CFG(o, v, d) \
+ PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_TRSV_CH_OFFSET)
+
/* UFS PHY registers */
#define PHY_PLL_LOCK_STATUS 0x1e
#define PHY_CDR_LOCK_STATUS 0x5e
@@ -134,6 +140,7 @@ static inline void samsung_ufs_phy_ctrl_isol(
phy->isol->mask, isol ? 0 : phy->isol->en);
}
-#include "phy-exynos7-ufs.h"
+extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy;
+extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy;
#endif /* _PHY_SAMSUNG_UFS_ */
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index 0aadac678191..963de5913e50 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -1273,7 +1273,7 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev)
return err;
}
-static int tegra_xusb_padctl_suspend_noirq(struct device *dev)
+static __maybe_unused int tegra_xusb_padctl_suspend_noirq(struct device *dev)
{
struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
@@ -1283,7 +1283,7 @@ static int tegra_xusb_padctl_suspend_noirq(struct device *dev)
return 0;
}
-static int tegra_xusb_padctl_resume_noirq(struct device *dev)
+static __maybe_unused int tegra_xusb_padctl_resume_noirq(struct device *dev)
{
struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
diff --git a/drivers/phy/ti/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c
index 5771e2486a3b..ac71017a0bc1 100644
--- a/drivers/phy/ti/phy-twl4030-usb.c
+++ b/drivers/phy/ti/phy-twl4030-usb.c
@@ -162,6 +162,8 @@ struct twl4030_usb {
atomic_t connected;
bool vbus_supplied;
bool musb_mailbox_pending;
+ unsigned long runtime_suspended:1;
+ unsigned long needs_resume:1;
struct delayed_work id_workaround_work;
};
@@ -384,6 +386,9 @@ static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
}
+static int twl4030_usb_runtime_suspend(struct device *dev);
+static int twl4030_usb_runtime_resume(struct device *dev);
+
static int __maybe_unused twl4030_usb_suspend(struct device *dev)
{
struct twl4030_usb *twl = dev_get_drvdata(dev);
@@ -395,6 +400,10 @@ static int __maybe_unused twl4030_usb_suspend(struct device *dev)
*/
dev_dbg(twl->dev, "%s\n", __func__);
disable_irq(twl->irq);
+ if (!twl->runtime_suspended && !atomic_read(&twl->connected)) {
+ twl4030_usb_runtime_suspend(dev);
+ twl->needs_resume = 1;
+ }
return 0;
}
@@ -405,9 +414,13 @@ static int __maybe_unused twl4030_usb_resume(struct device *dev)
dev_dbg(twl->dev, "%s\n", __func__);
enable_irq(twl->irq);
+ if (twl->needs_resume)
+ twl4030_usb_runtime_resume(dev);
/* check whether cable status changed */
twl4030_usb_irq(0, twl);
+ twl->runtime_suspended = 0;
+
return 0;
}
@@ -422,6 +435,8 @@ static int __maybe_unused twl4030_usb_runtime_suspend(struct device *dev)
regulator_disable(twl->usb1v8);
regulator_disable(twl->usb3v1);
+ twl->runtime_suspended = 1;
+
return 0;
}
diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
index 35652152ce5d..f478d8a17115 100644
--- a/drivers/phy/xilinx/phy-zynqmp.c
+++ b/drivers/phy/xilinx/phy-zynqmp.c
@@ -626,6 +626,9 @@ static int xpsgtr_phy_power_on(struct phy *phy)
struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
int ret = 0;
+ /* Skip initialization if not required. */
+ if (!xpsgtr_phy_init_required(gtr_phy))
+ return ret;
/*
* Wait for the PLL to lock. For DP, only wait on DP0 to avoid
* cumulating waits for both lanes. The user is expected to initialize
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index f38f12801f18..31921108e456 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -248,12 +248,15 @@ config PINCTRL_SX150X
- 16 bits: sx1509q, sx1506q
config PINCTRL_PISTACHIO
- def_bool y if MACH_PISTACHIO
+ bool "IMG Pistachio SoC pinctrl driver"
+ depends on OF && (MIPS || COMPILE_TEST)
depends on GPIOLIB
select PINMUX
select GENERIC_PINCONF
select GPIOLIB_IRQCHIP
select OF_GPIO
+ help
+ This support pinctrl and gpio driver for IMG Pistachio SoC.
config PINCTRL_ST
bool
@@ -404,6 +407,25 @@ config PINCTRL_K210
Add support for the Canaan Kendryte K210 RISC-V SOC Field
Programmable IO Array (FPIOA) controller.
+config PINCTRL_KEEMBAY
+ tristate "Pinctrl driver for Intel Keem Bay SoC"
+ depends on ARCH_KEEMBAY || (ARM64 && COMPILE_TEST)
+ depends on HAS_IOMEM
+ select PINMUX
+ select PINCONF
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GPIOLIB
+ select GPIOLIB_IRQCHIP
+ select GPIO_GENERIC
+ help
+ This selects pin control driver for the Intel Keembay SoC.
+ It provides pin config functions such as pullup, pulldown,
+ interrupt, drive strength, sec lock, schmitt trigger, slew
+ rate control and direction control. This module will be
+ called as pinctrl-keembay.
+
source "drivers/pinctrl/actions/Kconfig"
source "drivers/pinctrl/aspeed/Kconfig"
source "drivers/pinctrl/bcm/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 5ef5334a797f..200073bcc2c1 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o
obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO) += pinctrl-microchip-sgpio.o
obj-$(CONFIG_PINCTRL_EQUILIBRIUM) += pinctrl-equilibrium.o
obj-$(CONFIG_PINCTRL_K210) += pinctrl-k210.o
+obj-$(CONFIG_PINCTRL_KEEMBAY) += pinctrl-keembay.o
obj-y += actions/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
index 9bbfe5c14b36..c94e24aadf92 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
@@ -133,8 +133,8 @@ static int aspeed_disable_sig(struct aspeed_pinmux_data *ctx,
}
/**
- * Search for the signal expression needed to enable the pin's signal for the
- * requested function.
+ * aspeed_find_expr_by_name - Search for the signal expression needed to
+ * enable the pin's signal for the requested function.
*
* @exprs: List of signal expressions (haystack)
* @name: The name of the requested function (needle)
diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.c b/drivers/pinctrl/aspeed/pinmux-aspeed.c
index 894e2efd3be7..4aa46383c2c5 100644
--- a/drivers/pinctrl/aspeed/pinmux-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinmux-aspeed.c
@@ -59,7 +59,8 @@ int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
}
/**
- * Query the enabled or disabled state for a mux function's signal on a pin
+ * aspeed_sig_expr_eval - Query the enabled or disabled state for a
+ * mux function's signal on a pin
*
* @ctx: The driver context for the pinctrl IP
* @expr: An expression controlling the signal for a mux function on a pin
diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.h b/drivers/pinctrl/aspeed/pinmux-aspeed.h
index b69ba6b360a2..4d7548686f39 100644
--- a/drivers/pinctrl/aspeed/pinmux-aspeed.h
+++ b/drivers/pinctrl/aspeed/pinmux-aspeed.h
@@ -5,7 +5,6 @@
#define ASPEED_PINMUX_H
#include <linux/regmap.h>
-#include <stdbool.h>
/*
* The ASPEED SoCs provide typically more than 200 pins for GPIO and other
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 8b34d2c308c7..6e6fefeb21ea 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -416,8 +416,7 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
}
}
/* This should not happen, every IRQ has a bank */
- if (i == BCM2835_NUM_IRQS)
- BUG();
+ BUG_ON(i == BCM2835_NUM_IRQS);
chained_irq_enter(host_chip, desc);
diff --git a/drivers/pinctrl/freescale/Kconfig b/drivers/pinctrl/freescale/Kconfig
index f294336430cc..21fa21c6547b 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -166,6 +166,13 @@ config PINCTRL_IMX8DXL
help
Say Y here to enable the imx8dxl pinctrl driver
+config PINCTRL_IMX8ULP
+ tristate "IMX8ULP pinctrl driver"
+ depends on ARCH_MXC
+ select PINCTRL_IMX
+ help
+ Say Y here to enable the imx8ulp pinctrl driver
+
config PINCTRL_VF610
bool "Freescale Vybrid VF610 pinctrl driver"
depends on SOC_VF610
diff --git a/drivers/pinctrl/freescale/Makefile b/drivers/pinctrl/freescale/Makefile
index e476cb671037..c44930b1b362 100644
--- a/drivers/pinctrl/freescale/Makefile
+++ b/drivers/pinctrl/freescale/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_PINCTRL_IMX8MQ) += pinctrl-imx8mq.o
obj-$(CONFIG_PINCTRL_IMX8QM) += pinctrl-imx8qm.o
obj-$(CONFIG_PINCTRL_IMX8QXP) += pinctrl-imx8qxp.o
obj-$(CONFIG_PINCTRL_IMX8DXL) += pinctrl-imx8dxl.o
+obj-$(CONFIG_PINCTRL_IMX8ULP) += pinctrl-imx8ulp.o
obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8dxl.c b/drivers/pinctrl/freescale/pinctrl-imx8dxl.c
index 041455c13d0d..f947b1d0d1aa 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx8dxl.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx8dxl.c
@@ -155,7 +155,7 @@ static const struct pinctrl_pin_desc imx8dxl_pinctrl_pads[] = {
};
-static struct imx_pinctrl_soc_info imx8dxl_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx8dxl_pinctrl_info = {
.pins = imx8dxl_pinctrl_pads,
.npins = ARRAY_SIZE(imx8dxl_pinctrl_pads),
.flags = IMX_USE_SCU,
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8mn.c b/drivers/pinctrl/freescale/pinctrl-imx8mn.c
index 448a79eb4568..dbf89cfba477 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx8mn.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx8mn.c
@@ -317,7 +317,7 @@ static const struct pinctrl_pin_desc imx8mn_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX8MN_IOMUXC_UART4_TXD),
};
-static struct imx_pinctrl_soc_info imx8mn_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx8mn_pinctrl_info = {
.pins = imx8mn_pinctrl_pads,
.npins = ARRAY_SIZE(imx8mn_pinctrl_pads),
.gpr_compatible = "fsl,imx8mn-iomuxc-gpr",
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8qxp.c b/drivers/pinctrl/freescale/pinctrl-imx8qxp.c
index 4f97813ba8b7..0a0acc0038d0 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx8qxp.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx8qxp.c
@@ -194,7 +194,7 @@ static const struct pinctrl_pin_desc imx8qxp_pinctrl_pads[] = {
IMX_PINCTRL_PIN(IMX8QXP_COMP_CTL_GPIO_1V8_3V3_QSPI0B),
};
-static struct imx_pinctrl_soc_info imx8qxp_pinctrl_info = {
+static const struct imx_pinctrl_soc_info imx8qxp_pinctrl_info = {
.pins = imx8qxp_pinctrl_pads,
.npins = ARRAY_SIZE(imx8qxp_pinctrl_pads),
.flags = IMX_USE_SCU,
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8ulp.c b/drivers/pinctrl/freescale/pinctrl-imx8ulp.c
new file mode 100644
index 000000000000..f8572597a54e
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx8ulp.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 NXP
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx8ulp_pads {
+ IMX8ULP_PAD_PTD0 = 0,
+ IMX8ULP_PAD_PTD1,
+ IMX8ULP_PAD_PTD2,
+ IMX8ULP_PAD_PTD3,
+ IMX8ULP_PAD_PTD4,
+ IMX8ULP_PAD_PTD5,
+ IMX8ULP_PAD_PTD6,
+ IMX8ULP_PAD_PTD7,
+ IMX8ULP_PAD_PTD8,
+ IMX8ULP_PAD_PTD9,
+ IMX8ULP_PAD_PTD10,
+ IMX8ULP_PAD_PTD11,
+ IMX8ULP_PAD_PTD12,
+ IMX8ULP_PAD_PTD13,
+ IMX8ULP_PAD_PTD14,
+ IMX8ULP_PAD_PTD15,
+ IMX8ULP_PAD_PTD16,
+ IMX8ULP_PAD_PTD17,
+ IMX8ULP_PAD_PTD18,
+ IMX8ULP_PAD_PTD19,
+ IMX8ULP_PAD_PTD20,
+ IMX8ULP_PAD_PTD21,
+ IMX8ULP_PAD_PTD22,
+ IMX8ULP_PAD_PTD23,
+ IMX8ULP_PAD_RESERVE0,
+ IMX8ULP_PAD_RESERVE1,
+ IMX8ULP_PAD_RESERVE2,
+ IMX8ULP_PAD_RESERVE3,
+ IMX8ULP_PAD_RESERVE4,
+ IMX8ULP_PAD_RESERVE5,
+ IMX8ULP_PAD_RESERVE6,
+ IMX8ULP_PAD_RESERVE7,
+ IMX8ULP_PAD_PTE0,
+ IMX8ULP_PAD_PTE1,
+ IMX8ULP_PAD_PTE2,
+ IMX8ULP_PAD_PTE3,
+ IMX8ULP_PAD_PTE4,
+ IMX8ULP_PAD_PTE5,
+ IMX8ULP_PAD_PTE6,
+ IMX8ULP_PAD_PTE7,
+ IMX8ULP_PAD_PTE8,
+ IMX8ULP_PAD_PTE9,
+ IMX8ULP_PAD_PTE10,
+ IMX8ULP_PAD_PTE11,
+ IMX8ULP_PAD_PTE12,
+ IMX8ULP_PAD_PTE13,
+ IMX8ULP_PAD_PTE14,
+ IMX8ULP_PAD_PTE15,
+ IMX8ULP_PAD_PTE16,
+ IMX8ULP_PAD_PTE17,
+ IMX8ULP_PAD_PTE18,
+ IMX8ULP_PAD_PTE19,
+ IMX8ULP_PAD_PTE20,
+ IMX8ULP_PAD_PTE21,
+ IMX8ULP_PAD_PTE22,
+ IMX8ULP_PAD_PTE23,
+ IMX8ULP_PAD_RESERVE8,
+ IMX8ULP_PAD_RESERVE9,
+ IMX8ULP_PAD_RESERVE10,
+ IMX8ULP_PAD_RESERVE11,
+ IMX8ULP_PAD_RESERVE12,
+ IMX8ULP_PAD_RESERVE13,
+ IMX8ULP_PAD_RESERVE14,
+ IMX8ULP_PAD_RESERVE15,
+ IMX8ULP_PAD_PTF0,
+ IMX8ULP_PAD_PTF1,
+ IMX8ULP_PAD_PTF2,
+ IMX8ULP_PAD_PTF3,
+ IMX8ULP_PAD_PTF4,
+ IMX8ULP_PAD_PTF5,
+ IMX8ULP_PAD_PTF6,
+ IMX8ULP_PAD_PTF7,
+ IMX8ULP_PAD_PTF8,
+ IMX8ULP_PAD_PTF9,
+ IMX8ULP_PAD_PTF10,
+ IMX8ULP_PAD_PTF11,
+ IMX8ULP_PAD_PTF12,
+ IMX8ULP_PAD_PTF13,
+ IMX8ULP_PAD_PTF14,
+ IMX8ULP_PAD_PTF15,
+ IMX8ULP_PAD_PTF16,
+ IMX8ULP_PAD_PTF17,
+ IMX8ULP_PAD_PTF18,
+ IMX8ULP_PAD_PTF19,
+ IMX8ULP_PAD_PTF20,
+ IMX8ULP_PAD_PTF21,
+ IMX8ULP_PAD_PTF22,
+ IMX8ULP_PAD_PTF23,
+ IMX8ULP_PAD_PTF24,
+ IMX8ULP_PAD_PTF25,
+ IMX8ULP_PAD_PTF26,
+ IMX8ULP_PAD_PTF27,
+ IMX8ULP_PAD_PTF28,
+ IMX8ULP_PAD_PTF29,
+ IMX8ULP_PAD_PTF30,
+ IMX8ULP_PAD_PTF31,
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx8ulp_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD0),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD1),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD2),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD3),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD4),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD5),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD6),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD7),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD8),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD9),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD10),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD11),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD12),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD13),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD14),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD15),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD16),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD17),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD18),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD19),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD20),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD21),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD22),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTD23),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE0),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE1),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE2),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE3),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE4),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE5),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE6),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE7),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE0),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE1),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE2),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE3),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE4),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE5),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE6),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE7),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE8),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE9),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE10),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE11),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE12),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE13),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE14),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE15),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE16),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE17),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE18),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE19),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE20),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE21),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE22),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTE23),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE8),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE9),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE10),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE11),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE12),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE13),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE14),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_RESERVE15),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF0),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF1),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF2),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF3),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF4),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF5),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF6),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF7),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF8),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF9),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF10),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF11),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF12),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF13),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF14),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF15),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF16),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF17),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF18),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF19),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF20),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF21),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF22),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF23),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF24),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF25),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF26),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF27),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF28),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF29),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF30),
+ IMX_PINCTRL_PIN(IMX8ULP_PAD_PTF31),
+};
+
+#define BM_OBE_ENABLED BIT(17)
+#define BM_IBE_ENABLED BIT(16)
+#define BM_MUX_MODE 0xf00
+#define BP_MUX_MODE 8
+
+static int imx8ulp_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset, bool input)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pin_reg *pin_reg;
+ u32 reg;
+
+ pin_reg = &ipctl->pin_regs[offset];
+ if (pin_reg->mux_reg == -1)
+ return -EINVAL;
+
+ reg = readl(ipctl->base + pin_reg->mux_reg);
+ if (input)
+ reg = (reg & ~BM_OBE_ENABLED) | BM_IBE_ENABLED;
+ else
+ reg = (reg & ~BM_IBE_ENABLED) | BM_OBE_ENABLED;
+ writel(reg, ipctl->base + pin_reg->mux_reg);
+
+ return 0;
+}
+
+static const struct imx_pinctrl_soc_info imx8ulp_pinctrl_info = {
+ .pins = imx8ulp_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx8ulp_pinctrl_pads),
+ .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG,
+ .gpio_set_direction = imx8ulp_pmx_gpio_set_direction,
+ .mux_mask = BM_MUX_MODE,
+ .mux_shift = BP_MUX_MODE,
+};
+
+static const struct of_device_id imx8ulp_pinctrl_of_match[] = {
+ { .compatible = "fsl,imx8ulp-iomuxc1", },
+ { /* sentinel */ }
+};
+
+static int imx8ulp_pinctrl_probe(struct platform_device *pdev)
+{
+ return imx_pinctrl_probe(pdev, &imx8ulp_pinctrl_info);
+}
+
+static struct platform_driver imx8ulp_pinctrl_driver = {
+ .driver = {
+ .name = "imx8ulp-pinctrl",
+ .of_match_table = imx8ulp_pinctrl_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = imx8ulp_pinctrl_probe,
+};
+
+static int __init imx8ulp_pinctrl_init(void)
+{
+ return platform_driver_register(&imx8ulp_pinctrl_driver);
+}
+arch_initcall(imx8ulp_pinctrl_init);
+
+MODULE_AUTHOR("Jacky Bai <ping.bai@nxp.com>");
+MODULE_DESCRIPTION("NXP i.MX8ULP pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8365.c b/drivers/pinctrl/mediatek/pinctrl-mt8365.c
index 22c33c3cb581..79b1fee5a1eb 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8365.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8365.c
@@ -485,7 +485,6 @@ static struct platform_driver mtk_pinctrl_driver = {
.probe = mtk_pinctrl_probe,
.driver = {
.name = "mediatek-mt8365-pinctrl",
- .owner = THIS_MODULE,
.of_match_table = mt8365_pctrl_match,
.pm = &mtk_eint_pm_ops,
},
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 5a68e242f6b3..5cb018f98800 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -167,10 +167,14 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
PIN_GRP_GPIO("jtag", 20, 5, BIT(0), "jtag"),
PIN_GRP_GPIO("sdio0", 8, 3, BIT(1), "sdio"),
PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"),
- PIN_GRP_GPIO("pwm0", 11, 1, BIT(3), "pwm"),
- PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"),
- PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"),
- PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"),
+ PIN_GRP_GPIO_3("pwm0", 11, 1, BIT(3) | BIT(20), 0, BIT(20), BIT(3),
+ "pwm", "led"),
+ PIN_GRP_GPIO_3("pwm1", 12, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4),
+ "pwm", "led"),
+ PIN_GRP_GPIO_3("pwm2", 13, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5),
+ "pwm", "led"),
+ PIN_GRP_GPIO_3("pwm3", 14, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6),
+ "pwm", "led"),
PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"),
PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"),
PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"),
@@ -184,10 +188,6 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19),
BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19),
18, 2, "gpio", "uart"),
- PIN_GRP_GPIO_2("led0_od", 11, 1, BIT(20), BIT(20), 0, "led"),
- PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"),
- PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"),
- PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"),
};
static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
index ce9cc719c395..2712f51eb238 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -104,6 +104,7 @@ enum jz_version {
ID_X1500,
ID_X1830,
ID_X2000,
+ ID_X2100,
};
struct ingenic_chip_info {
@@ -589,6 +590,18 @@ static int jz4755_uart0_data_pins[] = { 0x7c, 0x7d, };
static int jz4755_uart0_hwflow_pins[] = { 0x7e, 0x7f, };
static int jz4755_uart1_data_pins[] = { 0x97, 0x99, };
static int jz4755_uart2_data_pins[] = { 0x9f, };
+static int jz4755_ssi_dt_b_pins[] = { 0x3b, };
+static int jz4755_ssi_dt_f_pins[] = { 0xa1, };
+static int jz4755_ssi_dr_b_pins[] = { 0x3c, };
+static int jz4755_ssi_dr_f_pins[] = { 0xa2, };
+static int jz4755_ssi_clk_b_pins[] = { 0x3a, };
+static int jz4755_ssi_clk_f_pins[] = { 0xa0, };
+static int jz4755_ssi_gpc_b_pins[] = { 0x3e, };
+static int jz4755_ssi_gpc_f_pins[] = { 0xa4, };
+static int jz4755_ssi_ce0_b_pins[] = { 0x3d, };
+static int jz4755_ssi_ce0_f_pins[] = { 0xa3, };
+static int jz4755_ssi_ce1_b_pins[] = { 0x3f, };
+static int jz4755_ssi_ce1_f_pins[] = { 0xa5, };
static int jz4755_mmc0_1bit_pins[] = { 0x2f, 0x50, 0x5c, };
static int jz4755_mmc0_4bit_pins[] = { 0x5d, 0x5b, 0x51, };
static int jz4755_mmc1_1bit_pins[] = { 0x3a, 0x3d, 0x3c, };
@@ -630,6 +643,18 @@ static const struct group_desc jz4755_groups[] = {
INGENIC_PIN_GROUP("uart0-hwflow", jz4755_uart0_hwflow, 0),
INGENIC_PIN_GROUP("uart1-data", jz4755_uart1_data, 0),
INGENIC_PIN_GROUP("uart2-data", jz4755_uart2_data, 1),
+ INGENIC_PIN_GROUP("ssi-dt-b", jz4755_ssi_dt_b, 0),
+ INGENIC_PIN_GROUP("ssi-dt-f", jz4755_ssi_dt_f, 0),
+ INGENIC_PIN_GROUP("ssi-dr-b", jz4755_ssi_dr_b, 0),
+ INGENIC_PIN_GROUP("ssi-dr-f", jz4755_ssi_dr_f, 0),
+ INGENIC_PIN_GROUP("ssi-clk-b", jz4755_ssi_clk_b, 0),
+ INGENIC_PIN_GROUP("ssi-clk-f", jz4755_ssi_clk_f, 0),
+ INGENIC_PIN_GROUP("ssi-gpc-b", jz4755_ssi_gpc_b, 0),
+ INGENIC_PIN_GROUP("ssi-gpc-f", jz4755_ssi_gpc_f, 0),
+ INGENIC_PIN_GROUP("ssi-ce0-b", jz4755_ssi_ce0_b, 0),
+ INGENIC_PIN_GROUP("ssi-ce0-f", jz4755_ssi_ce0_f, 0),
+ INGENIC_PIN_GROUP("ssi-ce1-b", jz4755_ssi_ce1_b, 0),
+ INGENIC_PIN_GROUP("ssi-ce1-f", jz4755_ssi_ce1_f, 0),
INGENIC_PIN_GROUP_FUNCS("mmc0-1bit", jz4755_mmc0_1bit,
jz4755_mmc0_1bit_funcs),
INGENIC_PIN_GROUP_FUNCS("mmc0-4bit", jz4755_mmc0_4bit,
@@ -661,6 +686,14 @@ static const struct group_desc jz4755_groups[] = {
static const char *jz4755_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
static const char *jz4755_uart1_groups[] = { "uart1-data", };
static const char *jz4755_uart2_groups[] = { "uart2-data", };
+static const char *jz4755_ssi_groups[] = {
+ "ssi-dt-b", "ssi-dt-f",
+ "ssi-dr-b", "ssi-dr-f",
+ "ssi-clk-b", "ssi-clk-f",
+ "ssi-gpc-b", "ssi-gpc-f",
+ "ssi-ce0-b", "ssi-ce0-f",
+ "ssi-ce1-b", "ssi-ce1-f",
+};
static const char *jz4755_mmc0_groups[] = { "mmc0-1bit", "mmc0-4bit", };
static const char *jz4755_mmc1_groups[] = { "mmc0-1bit", "mmc0-4bit", };
static const char *jz4755_i2c_groups[] = { "i2c-data", };
@@ -683,6 +716,7 @@ static const struct function_desc jz4755_functions[] = {
{ "uart0", jz4755_uart0_groups, ARRAY_SIZE(jz4755_uart0_groups), },
{ "uart1", jz4755_uart1_groups, ARRAY_SIZE(jz4755_uart1_groups), },
{ "uart2", jz4755_uart2_groups, ARRAY_SIZE(jz4755_uart2_groups), },
+ { "ssi", jz4755_ssi_groups, ARRAY_SIZE(jz4755_ssi_groups), },
{ "mmc0", jz4755_mmc0_groups, ARRAY_SIZE(jz4755_mmc0_groups), },
{ "mmc1", jz4755_mmc1_groups, ARRAY_SIZE(jz4755_mmc1_groups), },
{ "i2c", jz4755_i2c_groups, ARRAY_SIZE(jz4755_i2c_groups), },
@@ -710,7 +744,7 @@ static const struct ingenic_chip_info jz4755_chip_info = {
};
static const u32 jz4760_pull_ups[6] = {
- 0xffffffff, 0xfffcf3ff, 0xffffffff, 0xffffcfff, 0xfffffb7c, 0xfffff00f,
+ 0xffffffff, 0xfffcf3ff, 0xffffffff, 0xffffcfff, 0xfffffb7c, 0x0000000f,
};
static const u32 jz4760_pull_downs[6] = {
@@ -725,6 +759,58 @@ static int jz4760_uart2_data_pins[] = { 0x5c, 0x5e, };
static int jz4760_uart2_hwflow_pins[] = { 0x5d, 0x5f, };
static int jz4760_uart3_data_pins[] = { 0x6c, 0x85, };
static int jz4760_uart3_hwflow_pins[] = { 0x88, 0x89, };
+static int jz4760_ssi0_dt_a_pins[] = { 0x15, };
+static int jz4760_ssi0_dt_b_pins[] = { 0x35, };
+static int jz4760_ssi0_dt_d_pins[] = { 0x75, };
+static int jz4760_ssi0_dt_e_pins[] = { 0x91, };
+static int jz4760_ssi0_dr_a_pins[] = { 0x14, };
+static int jz4760_ssi0_dr_b_pins[] = { 0x34, };
+static int jz4760_ssi0_dr_d_pins[] = { 0x74, };
+static int jz4760_ssi0_dr_e_pins[] = { 0x8e, };
+static int jz4760_ssi0_clk_a_pins[] = { 0x12, };
+static int jz4760_ssi0_clk_b_pins[] = { 0x3c, };
+static int jz4760_ssi0_clk_d_pins[] = { 0x78, };
+static int jz4760_ssi0_clk_e_pins[] = { 0x8f, };
+static int jz4760_ssi0_gpc_b_pins[] = { 0x3e, };
+static int jz4760_ssi0_gpc_d_pins[] = { 0x76, };
+static int jz4760_ssi0_gpc_e_pins[] = { 0x93, };
+static int jz4760_ssi0_ce0_a_pins[] = { 0x13, };
+static int jz4760_ssi0_ce0_b_pins[] = { 0x3d, };
+static int jz4760_ssi0_ce0_d_pins[] = { 0x79, };
+static int jz4760_ssi0_ce0_e_pins[] = { 0x90, };
+static int jz4760_ssi0_ce1_b_pins[] = { 0x3f, };
+static int jz4760_ssi0_ce1_d_pins[] = { 0x77, };
+static int jz4760_ssi0_ce1_e_pins[] = { 0x92, };
+static int jz4760_ssi1_dt_b_9_pins[] = { 0x29, };
+static int jz4760_ssi1_dt_b_21_pins[] = { 0x35, };
+static int jz4760_ssi1_dt_d_12_pins[] = { 0x6c, };
+static int jz4760_ssi1_dt_d_21_pins[] = { 0x75, };
+static int jz4760_ssi1_dt_e_pins[] = { 0x91, };
+static int jz4760_ssi1_dt_f_pins[] = { 0xa3, };
+static int jz4760_ssi1_dr_b_6_pins[] = { 0x26, };
+static int jz4760_ssi1_dr_b_20_pins[] = { 0x34, };
+static int jz4760_ssi1_dr_d_13_pins[] = { 0x6d, };
+static int jz4760_ssi1_dr_d_20_pins[] = { 0x74, };
+static int jz4760_ssi1_dr_e_pins[] = { 0x8e, };
+static int jz4760_ssi1_dr_f_pins[] = { 0xa0, };
+static int jz4760_ssi1_clk_b_7_pins[] = { 0x27, };
+static int jz4760_ssi1_clk_b_28_pins[] = { 0x3c, };
+static int jz4760_ssi1_clk_d_pins[] = { 0x78, };
+static int jz4760_ssi1_clk_e_7_pins[] = { 0x87, };
+static int jz4760_ssi1_clk_e_15_pins[] = { 0x8f, };
+static int jz4760_ssi1_clk_f_pins[] = { 0xa2, };
+static int jz4760_ssi1_gpc_b_pins[] = { 0x3e, };
+static int jz4760_ssi1_gpc_d_pins[] = { 0x76, };
+static int jz4760_ssi1_gpc_e_pins[] = { 0x93, };
+static int jz4760_ssi1_ce0_b_8_pins[] = { 0x28, };
+static int jz4760_ssi1_ce0_b_29_pins[] = { 0x3d, };
+static int jz4760_ssi1_ce0_d_pins[] = { 0x79, };
+static int jz4760_ssi1_ce0_e_6_pins[] = { 0x86, };
+static int jz4760_ssi1_ce0_e_16_pins[] = { 0x90, };
+static int jz4760_ssi1_ce0_f_pins[] = { 0xa1, };
+static int jz4760_ssi1_ce1_b_pins[] = { 0x3f, };
+static int jz4760_ssi1_ce1_d_pins[] = { 0x77, };
+static int jz4760_ssi1_ce1_e_pins[] = { 0x92, };
static int jz4760_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, };
static int jz4760_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, };
static int jz4760_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
@@ -801,6 +887,58 @@ static const struct group_desc jz4760_groups[] = {
INGENIC_PIN_GROUP_FUNCS("uart3-data", jz4760_uart3_data,
jz4760_uart3_data_funcs),
INGENIC_PIN_GROUP("uart3-hwflow", jz4760_uart3_hwflow, 0),
+ INGENIC_PIN_GROUP("ssi0-dt-a", jz4760_ssi0_dt_a, 2),
+ INGENIC_PIN_GROUP("ssi0-dt-b", jz4760_ssi0_dt_b, 1),
+ INGENIC_PIN_GROUP("ssi0-dt-d", jz4760_ssi0_dt_d, 1),
+ INGENIC_PIN_GROUP("ssi0-dt-e", jz4760_ssi0_dt_e, 0),
+ INGENIC_PIN_GROUP("ssi0-dr-a", jz4760_ssi0_dr_a, 1),
+ INGENIC_PIN_GROUP("ssi0-dr-b", jz4760_ssi0_dr_b, 1),
+ INGENIC_PIN_GROUP("ssi0-dr-d", jz4760_ssi0_dr_d, 1),
+ INGENIC_PIN_GROUP("ssi0-dr-e", jz4760_ssi0_dr_e, 0),
+ INGENIC_PIN_GROUP("ssi0-clk-a", jz4760_ssi0_clk_a, 2),
+ INGENIC_PIN_GROUP("ssi0-clk-b", jz4760_ssi0_clk_b, 1),
+ INGENIC_PIN_GROUP("ssi0-clk-d", jz4760_ssi0_clk_d, 1),
+ INGENIC_PIN_GROUP("ssi0-clk-e", jz4760_ssi0_clk_e, 0),
+ INGENIC_PIN_GROUP("ssi0-gpc-b", jz4760_ssi0_gpc_b, 1),
+ INGENIC_PIN_GROUP("ssi0-gpc-d", jz4760_ssi0_gpc_d, 1),
+ INGENIC_PIN_GROUP("ssi0-gpc-e", jz4760_ssi0_gpc_e, 0),
+ INGENIC_PIN_GROUP("ssi0-ce0-a", jz4760_ssi0_ce0_a, 2),
+ INGENIC_PIN_GROUP("ssi0-ce0-b", jz4760_ssi0_ce0_b, 1),
+ INGENIC_PIN_GROUP("ssi0-ce0-d", jz4760_ssi0_ce0_d, 1),
+ INGENIC_PIN_GROUP("ssi0-ce0-e", jz4760_ssi0_ce0_e, 0),
+ INGENIC_PIN_GROUP("ssi0-ce1-b", jz4760_ssi0_ce1_b, 1),
+ INGENIC_PIN_GROUP("ssi0-ce1-d", jz4760_ssi0_ce1_d, 1),
+ INGENIC_PIN_GROUP("ssi0-ce1-e", jz4760_ssi0_ce1_e, 0),
+ INGENIC_PIN_GROUP("ssi1-dt-b-9", jz4760_ssi1_dt_b_9, 2),
+ INGENIC_PIN_GROUP("ssi1-dt-b-21", jz4760_ssi1_dt_b_21, 2),
+ INGENIC_PIN_GROUP("ssi1-dt-d-12", jz4760_ssi1_dt_d_12, 2),
+ INGENIC_PIN_GROUP("ssi1-dt-d-21", jz4760_ssi1_dt_d_21, 2),
+ INGENIC_PIN_GROUP("ssi1-dt-e", jz4760_ssi1_dt_e, 1),
+ INGENIC_PIN_GROUP("ssi1-dt-f", jz4760_ssi1_dt_f, 2),
+ INGENIC_PIN_GROUP("ssi1-dr-b-6", jz4760_ssi1_dr_b_6, 2),
+ INGENIC_PIN_GROUP("ssi1-dr-b-20", jz4760_ssi1_dr_b_20, 2),
+ INGENIC_PIN_GROUP("ssi1-dr-d-13", jz4760_ssi1_dr_d_13, 2),
+ INGENIC_PIN_GROUP("ssi1-dr-d-20", jz4760_ssi1_dr_d_20, 2),
+ INGENIC_PIN_GROUP("ssi1-dr-e", jz4760_ssi1_dr_e, 1),
+ INGENIC_PIN_GROUP("ssi1-dr-f", jz4760_ssi1_dr_f, 2),
+ INGENIC_PIN_GROUP("ssi1-clk-b-7", jz4760_ssi1_clk_b_7, 2),
+ INGENIC_PIN_GROUP("ssi1-clk-b-28", jz4760_ssi1_clk_b_28, 2),
+ INGENIC_PIN_GROUP("ssi1-clk-d", jz4760_ssi1_clk_d, 2),
+ INGENIC_PIN_GROUP("ssi1-clk-e-7", jz4760_ssi1_clk_e_7, 2),
+ INGENIC_PIN_GROUP("ssi1-clk-e-15", jz4760_ssi1_clk_e_15, 1),
+ INGENIC_PIN_GROUP("ssi1-clk-f", jz4760_ssi1_clk_f, 2),
+ INGENIC_PIN_GROUP("ssi1-gpc-b", jz4760_ssi1_gpc_b, 2),
+ INGENIC_PIN_GROUP("ssi1-gpc-d", jz4760_ssi1_gpc_d, 2),
+ INGENIC_PIN_GROUP("ssi1-gpc-e", jz4760_ssi1_gpc_e, 1),
+ INGENIC_PIN_GROUP("ssi1-ce0-b-8", jz4760_ssi1_ce0_b_8, 2),
+ INGENIC_PIN_GROUP("ssi1-ce0-b-29", jz4760_ssi1_ce0_b_29, 2),
+ INGENIC_PIN_GROUP("ssi1-ce0-d", jz4760_ssi1_ce0_d, 2),
+ INGENIC_PIN_GROUP("ssi1-ce0-e-6", jz4760_ssi1_ce0_e_6, 2),
+ INGENIC_PIN_GROUP("ssi1-ce0-e-16", jz4760_ssi1_ce0_e_16, 1),
+ INGENIC_PIN_GROUP("ssi1-ce0-f", jz4760_ssi1_ce0_f, 2),
+ INGENIC_PIN_GROUP("ssi1-ce1-b", jz4760_ssi1_ce1_b, 2),
+ INGENIC_PIN_GROUP("ssi1-ce1-d", jz4760_ssi1_ce1_d, 2),
+ INGENIC_PIN_GROUP("ssi1-ce1-e", jz4760_ssi1_ce1_e, 1),
INGENIC_PIN_GROUP_FUNCS("mmc0-1bit-a", jz4760_mmc0_1bit_a,
jz4760_mmc0_1bit_a_funcs),
INGENIC_PIN_GROUP("mmc0-4bit-a", jz4760_mmc0_4bit_a, 1),
@@ -854,6 +992,22 @@ static const char *jz4760_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
static const char *jz4760_uart1_groups[] = { "uart1-data", "uart1-hwflow", };
static const char *jz4760_uart2_groups[] = { "uart2-data", "uart2-hwflow", };
static const char *jz4760_uart3_groups[] = { "uart3-data", "uart3-hwflow", };
+static const char *jz4760_ssi0_groups[] = {
+ "ssi0-dt-a", "ssi0-dt-b", "ssi0-dt-d", "ssi0-dt-e",
+ "ssi0-dr-a", "ssi0-dr-b", "ssi0-dr-d", "ssi0-dr-e",
+ "ssi0-clk-a", "ssi0-clk-b", "ssi0-clk-d", "ssi0-clk-e",
+ "ssi0-gpc-b", "ssi0-gpc-d", "ssi0-gpc-e",
+ "ssi0-ce0-a", "ssi0-ce0-b", "ssi0-ce0-d", "ssi0-ce0-e",
+ "ssi0-ce1-b", "ssi0-ce1-d", "ssi0-ce1-e",
+};
+static const char *jz4760_ssi1_groups[] = {
+ "ssi1-dt-b-9", "ssi1-dt-b-21", "ssi1-dt-d-12", "ssi1-dt-d-21", "ssi1-dt-e", "ssi1-dt-f",
+ "ssi1-dr-b-6", "ssi1-dr-b-20", "ssi1-dr-d-13", "ssi1-dr-d-20", "ssi1-dr-e", "ssi1-dr-f",
+ "ssi1-clk-b-7", "ssi1-clk-b-28", "ssi1-clk-d", "ssi1-clk-e-7", "ssi1-clk-e-15", "ssi1-clk-f",
+ "ssi1-gpc-b", "ssi1-gpc-d", "ssi1-gpc-e",
+ "ssi1-ce0-b-8", "ssi1-ce0-b-29", "ssi1-ce0-d", "ssi1-ce0-e-6", "ssi1-ce0-e-16", "ssi1-ce0-f",
+ "ssi1-ce1-b", "ssi1-ce1-d", "ssi1-ce1-e",
+};
static const char *jz4760_mmc0_groups[] = {
"mmc0-1bit-a", "mmc0-4bit-a",
"mmc0-1bit-e", "mmc0-4bit-e", "mmc0-8bit-e",
@@ -898,6 +1052,8 @@ static const struct function_desc jz4760_functions[] = {
{ "uart1", jz4760_uart1_groups, ARRAY_SIZE(jz4760_uart1_groups), },
{ "uart2", jz4760_uart2_groups, ARRAY_SIZE(jz4760_uart2_groups), },
{ "uart3", jz4760_uart3_groups, ARRAY_SIZE(jz4760_uart3_groups), },
+ { "ssi0", jz4760_ssi0_groups, ARRAY_SIZE(jz4760_ssi0_groups), },
+ { "ssi1", jz4760_ssi1_groups, ARRAY_SIZE(jz4760_ssi1_groups), },
{ "mmc0", jz4760_mmc0_groups, ARRAY_SIZE(jz4760_mmc0_groups), },
{ "mmc1", jz4760_mmc1_groups, ARRAY_SIZE(jz4760_mmc1_groups), },
{ "mmc2", jz4760_mmc2_groups, ARRAY_SIZE(jz4760_mmc2_groups), },
@@ -936,11 +1092,11 @@ static const struct ingenic_chip_info jz4760_chip_info = {
};
static const u32 jz4770_pull_ups[6] = {
- 0x3fffffff, 0xfff0030c, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0xffa7f00f,
+ 0x3fffffff, 0xfff0f3fc, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0x0024f00f,
};
static const u32 jz4770_pull_downs[6] = {
- 0x00000000, 0x000f0c03, 0x00000000, 0x0000b000, 0x00000483, 0x00580ff0,
+ 0x00000000, 0x000f0c03, 0x00000000, 0x0000b000, 0x00000483, 0x005b0ff0,
};
static int jz4770_uart0_data_pins[] = { 0xa0, 0xa3, };
@@ -1827,7 +1983,9 @@ static int x1000_uart1_data_d_pins[] = { 0x62, 0x63, };
static int x1000_uart1_hwflow_pins[] = { 0x64, 0x65, };
static int x1000_uart2_data_a_pins[] = { 0x02, 0x03, };
static int x1000_uart2_data_d_pins[] = { 0x65, 0x64, };
-static int x1000_sfc_pins[] = { 0x1d, 0x1c, 0x1e, 0x1f, 0x1a, 0x1b, };
+static int x1000_sfc_data_pins[] = { 0x1d, 0x1c, 0x1e, 0x1f, };
+static int x1000_sfc_clk_pins[] = { 0x1a, };
+static int x1000_sfc_ce_pins[] = { 0x1b, };
static int x1000_ssi_dt_a_22_pins[] = { 0x16, };
static int x1000_ssi_dt_a_29_pins[] = { 0x1d, };
static int x1000_ssi_dt_d_pins[] = { 0x62, };
@@ -1871,8 +2029,8 @@ static int x1000_i2s_data_tx_pins[] = { 0x24, };
static int x1000_i2s_data_rx_pins[] = { 0x23, };
static int x1000_i2s_clk_txrx_pins[] = { 0x21, 0x22, };
static int x1000_i2s_sysclk_pins[] = { 0x20, };
-static int x1000_dmic0_pins[] = { 0x35, 0x36, };
-static int x1000_dmic1_pins[] = { 0x25, };
+static int x1000_dmic_if0_pins[] = { 0x35, 0x36, };
+static int x1000_dmic_if1_pins[] = { 0x25, };
static int x1000_cim_pins[] = {
0x08, 0x09, 0x0a, 0x0b,
0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c,
@@ -1901,7 +2059,9 @@ static const struct group_desc x1000_groups[] = {
INGENIC_PIN_GROUP("uart1-hwflow", x1000_uart1_hwflow, 1),
INGENIC_PIN_GROUP("uart2-data-a", x1000_uart2_data_a, 2),
INGENIC_PIN_GROUP("uart2-data-d", x1000_uart2_data_d, 0),
- INGENIC_PIN_GROUP("sfc", x1000_sfc, 1),
+ INGENIC_PIN_GROUP("sfc-data", x1000_sfc_data, 1),
+ INGENIC_PIN_GROUP("sfc-clk", x1000_sfc_clk, 1),
+ INGENIC_PIN_GROUP("sfc-ce", x1000_sfc_ce, 1),
INGENIC_PIN_GROUP("ssi-dt-a-22", x1000_ssi_dt_a_22, 2),
INGENIC_PIN_GROUP("ssi-dt-a-29", x1000_ssi_dt_a_29, 2),
INGENIC_PIN_GROUP("ssi-dt-d", x1000_ssi_dt_d, 0),
@@ -1938,8 +2098,8 @@ static const struct group_desc x1000_groups[] = {
INGENIC_PIN_GROUP("i2s-data-rx", x1000_i2s_data_rx, 1),
INGENIC_PIN_GROUP("i2s-clk-txrx", x1000_i2s_clk_txrx, 1),
INGENIC_PIN_GROUP("i2s-sysclk", x1000_i2s_sysclk, 1),
- INGENIC_PIN_GROUP("dmic0", x1000_dmic0, 0),
- INGENIC_PIN_GROUP("dmic1", x1000_dmic1, 1),
+ INGENIC_PIN_GROUP("dmic-if0", x1000_dmic_if0, 0),
+ INGENIC_PIN_GROUP("dmic-if1", x1000_dmic_if1, 1),
INGENIC_PIN_GROUP("cim-data", x1000_cim, 2),
INGENIC_PIN_GROUP("lcd-8bit", x1000_lcd_8bit, 1),
INGENIC_PIN_GROUP("lcd-16bit", x1000_lcd_16bit, 1),
@@ -1956,7 +2116,7 @@ static const char *x1000_uart1_groups[] = {
"uart1-data-a", "uart1-data-d", "uart1-hwflow",
};
static const char *x1000_uart2_groups[] = { "uart2-data-a", "uart2-data-d", };
-static const char *x1000_sfc_groups[] = { "sfc", };
+static const char *x1000_sfc_groups[] = { "sfc-data", "sfc-clk", "sfc-ce", };
static const char *x1000_ssi_groups[] = {
"ssi-dt-a-22", "ssi-dt-a-29", "ssi-dt-d",
"ssi-dr-a-23", "ssi-dr-a-28", "ssi-dr-d",
@@ -1983,7 +2143,7 @@ static const char *x1000_i2c2_groups[] = { "i2c2-data", };
static const char *x1000_i2s_groups[] = {
"i2s-data-tx", "i2s-data-rx", "i2s-clk-txrx", "i2s-sysclk",
};
-static const char *x1000_dmic_groups[] = { "dmic0", "dmic1", };
+static const char *x1000_dmic_groups[] = { "dmic-if0", "dmic-if1", };
static const char *x1000_cim_groups[] = { "cim-data", };
static const char *x1000_lcd_groups[] = { "lcd-8bit", "lcd-16bit", };
static const char *x1000_pwm0_groups[] = { "pwm0", };
@@ -2048,8 +2208,8 @@ static int x1500_i2s_data_tx_pins[] = { 0x24, };
static int x1500_i2s_data_rx_pins[] = { 0x23, };
static int x1500_i2s_clk_txrx_pins[] = { 0x21, 0x22, };
static int x1500_i2s_sysclk_pins[] = { 0x20, };
-static int x1500_dmic0_pins[] = { 0x35, 0x36, };
-static int x1500_dmic1_pins[] = { 0x25, };
+static int x1500_dmic_if0_pins[] = { 0x35, 0x36, };
+static int x1500_dmic_if1_pins[] = { 0x25, };
static int x1500_cim_pins[] = {
0x08, 0x09, 0x0a, 0x0b,
0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c,
@@ -2068,7 +2228,9 @@ static const struct group_desc x1500_groups[] = {
INGENIC_PIN_GROUP("uart1-hwflow", x1500_uart1_hwflow, 1),
INGENIC_PIN_GROUP("uart2-data-a", x1500_uart2_data_a, 2),
INGENIC_PIN_GROUP("uart2-data-d", x1500_uart2_data_d, 0),
- INGENIC_PIN_GROUP("sfc", x1000_sfc, 1),
+ INGENIC_PIN_GROUP("sfc-data", x1000_sfc_data, 1),
+ INGENIC_PIN_GROUP("sfc-clk", x1000_sfc_clk, 1),
+ INGENIC_PIN_GROUP("sfc-ce", x1000_sfc_ce, 1),
INGENIC_PIN_GROUP("mmc-1bit", x1500_mmc_1bit, 1),
INGENIC_PIN_GROUP("mmc-4bit", x1500_mmc_4bit, 1),
INGENIC_PIN_GROUP("i2c0-data", x1500_i2c0, 0),
@@ -2079,8 +2241,8 @@ static const struct group_desc x1500_groups[] = {
INGENIC_PIN_GROUP("i2s-data-rx", x1500_i2s_data_rx, 1),
INGENIC_PIN_GROUP("i2s-clk-txrx", x1500_i2s_clk_txrx, 1),
INGENIC_PIN_GROUP("i2s-sysclk", x1500_i2s_sysclk, 1),
- INGENIC_PIN_GROUP("dmic0", x1500_dmic0, 0),
- INGENIC_PIN_GROUP("dmic1", x1500_dmic1, 1),
+ INGENIC_PIN_GROUP("dmic-if0", x1500_dmic_if0, 0),
+ INGENIC_PIN_GROUP("dmic-if1", x1500_dmic_if1, 1),
INGENIC_PIN_GROUP("cim-data", x1500_cim, 2),
INGENIC_PIN_GROUP("pwm0", x1500_pwm_pwm0, 0),
INGENIC_PIN_GROUP("pwm1", x1500_pwm_pwm1, 1),
@@ -2101,7 +2263,7 @@ static const char *x1500_i2c2_groups[] = { "i2c2-data", };
static const char *x1500_i2s_groups[] = {
"i2s-data-tx", "i2s-data-rx", "i2s-clk-txrx", "i2s-sysclk",
};
-static const char *x1500_dmic_groups[] = { "dmic0", "dmic1", };
+static const char *x1500_dmic_groups[] = { "dmic-if0", "dmic-if1", };
static const char *x1500_cim_groups[] = { "cim-data", };
static const char *x1500_pwm0_groups[] = { "pwm0", };
static const char *x1500_pwm1_groups[] = { "pwm1", };
@@ -2151,7 +2313,9 @@ static const u32 x1830_pull_downs[4] = {
static int x1830_uart0_data_pins[] = { 0x33, 0x36, };
static int x1830_uart0_hwflow_pins[] = { 0x34, 0x35, };
static int x1830_uart1_data_pins[] = { 0x38, 0x37, };
-static int x1830_sfc_pins[] = { 0x17, 0x18, 0x1a, 0x19, 0x1b, 0x1c, };
+static int x1830_sfc_data_pins[] = { 0x17, 0x18, 0x1a, 0x19, };
+static int x1830_sfc_clk_pins[] = { 0x1b, };
+static int x1830_sfc_ce_pins[] = { 0x1c, };
static int x1830_ssi0_dt_pins[] = { 0x4c, };
static int x1830_ssi0_dr_pins[] = { 0x4b, };
static int x1830_ssi0_clk_pins[] = { 0x4f, };
@@ -2182,8 +2346,8 @@ static int x1830_i2s_data_rx_pins[] = { 0x54, };
static int x1830_i2s_clk_txrx_pins[] = { 0x58, 0x52, };
static int x1830_i2s_clk_rx_pins[] = { 0x56, 0x55, };
static int x1830_i2s_sysclk_pins[] = { 0x57, };
-static int x1830_dmic0_pins[] = { 0x48, 0x59, };
-static int x1830_dmic1_pins[] = { 0x5a, };
+static int x1830_dmic_if0_pins[] = { 0x48, 0x59, };
+static int x1830_dmic_if1_pins[] = { 0x5a, };
static int x1830_lcd_tft_8bit_pins[] = {
0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x73, 0x72, 0x69,
@@ -2223,7 +2387,9 @@ static const struct group_desc x1830_groups[] = {
INGENIC_PIN_GROUP("uart0-data", x1830_uart0_data, 0),
INGENIC_PIN_GROUP("uart0-hwflow", x1830_uart0_hwflow, 0),
INGENIC_PIN_GROUP("uart1-data", x1830_uart1_data, 0),
- INGENIC_PIN_GROUP("sfc", x1830_sfc, 1),
+ INGENIC_PIN_GROUP("sfc-data", x1830_sfc_data, 1),
+ INGENIC_PIN_GROUP("sfc-clk", x1830_sfc_clk, 1),
+ INGENIC_PIN_GROUP("sfc-ce", x1830_sfc_ce, 1),
INGENIC_PIN_GROUP("ssi0-dt", x1830_ssi0_dt, 0),
INGENIC_PIN_GROUP("ssi0-dr", x1830_ssi0_dr, 0),
INGENIC_PIN_GROUP("ssi0-clk", x1830_ssi0_clk, 0),
@@ -2254,8 +2420,8 @@ static const struct group_desc x1830_groups[] = {
INGENIC_PIN_GROUP("i2s-clk-txrx", x1830_i2s_clk_txrx, 0),
INGENIC_PIN_GROUP("i2s-clk-rx", x1830_i2s_clk_rx, 0),
INGENIC_PIN_GROUP("i2s-sysclk", x1830_i2s_sysclk, 0),
- INGENIC_PIN_GROUP("dmic0", x1830_dmic0, 2),
- INGENIC_PIN_GROUP("dmic1", x1830_dmic1, 2),
+ INGENIC_PIN_GROUP("dmic-if0", x1830_dmic_if0, 2),
+ INGENIC_PIN_GROUP("dmic-if1", x1830_dmic_if1, 2),
INGENIC_PIN_GROUP("lcd-tft-8bit", x1830_lcd_tft_8bit, 0),
INGENIC_PIN_GROUP("lcd-tft-24bit", x1830_lcd_tft_24bit, 0),
INGENIC_PIN_GROUP("lcd-slcd-8bit", x1830_lcd_slcd_8bit, 1),
@@ -2281,7 +2447,7 @@ static const struct group_desc x1830_groups[] = {
static const char *x1830_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
static const char *x1830_uart1_groups[] = { "uart1-data", };
-static const char *x1830_sfc_groups[] = { "sfc", };
+static const char *x1830_sfc_groups[] = { "sfc-data", "sfc-clk", "sfc-ce", };
static const char *x1830_ssi0_groups[] = {
"ssi0-dt", "ssi0-dr", "ssi0-clk", "ssi0-gpc", "ssi0-ce0", "ssi0-ce1",
};
@@ -2301,7 +2467,7 @@ static const char *x1830_i2c2_groups[] = { "i2c2-data", };
static const char *x1830_i2s_groups[] = {
"i2s-data-tx", "i2s-data-rx", "i2s-clk-txrx", "i2s-clk-rx", "i2s-sysclk",
};
-static const char *x1830_dmic_groups[] = { "dmic0", "dmic1", };
+static const char *x1830_dmic_groups[] = { "dmic-if0", "dmic-if1", };
static const char *x1830_lcd_groups[] = {
"lcd-tft-8bit", "lcd-tft-24bit", "lcd-slcd-8bit", "lcd-slcd-16bit",
};
@@ -2381,17 +2547,21 @@ static int x2000_uart7_data_a_pins[] = { 0x08, 0x09, };
static int x2000_uart7_data_c_pins[] = { 0x41, 0x42, };
static int x2000_uart8_data_pins[] = { 0x3c, 0x3d, };
static int x2000_uart9_data_pins[] = { 0x3e, 0x3f, };
-static int x2000_sfc0_d_pins[] = { 0x73, 0x74, 0x75, 0x76, 0x71, 0x72, };
-static int x2000_sfc0_e_pins[] = { 0x92, 0x93, 0x94, 0x95, 0x90, 0x91, };
-static int x2000_sfc1_pins[] = { 0x77, 0x78, 0x79, 0x7a, };
+static int x2000_sfc_data_if0_d_pins[] = { 0x73, 0x74, 0x75, 0x76, };
+static int x2000_sfc_data_if0_e_pins[] = { 0x92, 0x93, 0x94, 0x95, };
+static int x2000_sfc_data_if1_pins[] = { 0x77, 0x78, 0x79, 0x7a, };
+static int x2000_sfc_clk_d_pins[] = { 0x71, };
+static int x2000_sfc_clk_e_pins[] = { 0x90, };
+static int x2000_sfc_ce_d_pins[] = { 0x72, };
+static int x2000_sfc_ce_e_pins[] = { 0x91, };
static int x2000_ssi0_dt_b_pins[] = { 0x3e, };
static int x2000_ssi0_dt_d_pins[] = { 0x69, };
static int x2000_ssi0_dr_b_pins[] = { 0x3d, };
static int x2000_ssi0_dr_d_pins[] = { 0x6a, };
static int x2000_ssi0_clk_b_pins[] = { 0x3f, };
static int x2000_ssi0_clk_d_pins[] = { 0x68, };
-static int x2000_ssi0_ce0_b_pins[] = { 0x3c, };
-static int x2000_ssi0_ce0_d_pins[] = { 0x6d, };
+static int x2000_ssi0_ce_b_pins[] = { 0x3c, };
+static int x2000_ssi0_ce_d_pins[] = { 0x6d, };
static int x2000_ssi1_dt_c_pins[] = { 0x4b, };
static int x2000_ssi1_dt_d_pins[] = { 0x72, };
static int x2000_ssi1_dt_e_pins[] = { 0x91, };
@@ -2401,9 +2571,9 @@ static int x2000_ssi1_dr_e_pins[] = { 0x92, };
static int x2000_ssi1_clk_c_pins[] = { 0x4c, };
static int x2000_ssi1_clk_d_pins[] = { 0x71, };
static int x2000_ssi1_clk_e_pins[] = { 0x90, };
-static int x2000_ssi1_ce0_c_pins[] = { 0x49, };
-static int x2000_ssi1_ce0_d_pins[] = { 0x76, };
-static int x2000_ssi1_ce0_e_pins[] = { 0x95, };
+static int x2000_ssi1_ce_c_pins[] = { 0x49, };
+static int x2000_ssi1_ce_d_pins[] = { 0x76, };
+static int x2000_ssi1_ce_e_pins[] = { 0x95, };
static int x2000_mmc0_1bit_pins[] = { 0x71, 0x72, 0x73, };
static int x2000_mmc0_4bit_pins[] = { 0x74, 0x75, 0x75, };
static int x2000_mmc0_8bit_pins[] = { 0x77, 0x78, 0x79, 0x7a, };
@@ -2455,10 +2625,10 @@ static int x2000_i2s3_data_tx2_pins[] = { 0x05, };
static int x2000_i2s3_data_tx3_pins[] = { 0x06, };
static int x2000_i2s3_clk_tx_pins[] = { 0x10, 0x02, };
static int x2000_i2s3_sysclk_tx_pins[] = { 0x00, };
-static int x2000_dmic0_pins[] = { 0x54, 0x55, };
-static int x2000_dmic1_pins[] = { 0x56, };
-static int x2000_dmic2_pins[] = { 0x57, };
-static int x2000_dmic3_pins[] = { 0x58, };
+static int x2000_dmic_if0_pins[] = { 0x54, 0x55, };
+static int x2000_dmic_if1_pins[] = { 0x56, };
+static int x2000_dmic_if2_pins[] = { 0x57, };
+static int x2000_dmic_if3_pins[] = { 0x58, };
static int x2000_cim_8bit_pins[] = {
0x0e, 0x0c, 0x0d, 0x4f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -2545,17 +2715,21 @@ static const struct group_desc x2000_groups[] = {
INGENIC_PIN_GROUP("uart7-data-c", x2000_uart7_data_c, 3),
INGENIC_PIN_GROUP("uart8-data", x2000_uart8_data, 3),
INGENIC_PIN_GROUP("uart9-data", x2000_uart9_data, 3),
- INGENIC_PIN_GROUP("sfc0-d", x2000_sfc0_d, 1),
- INGENIC_PIN_GROUP("sfc0-e", x2000_sfc0_e, 0),
- INGENIC_PIN_GROUP("sfc1", x2000_sfc1, 1),
+ INGENIC_PIN_GROUP("sfc-data-if0-d", x2000_sfc_data_if0_d, 1),
+ INGENIC_PIN_GROUP("sfc-data-if0-e", x2000_sfc_data_if0_e, 0),
+ INGENIC_PIN_GROUP("sfc-data-if1", x2000_sfc_data_if1, 1),
+ INGENIC_PIN_GROUP("sfc-clk-d", x2000_sfc_clk_d, 1),
+ INGENIC_PIN_GROUP("sfc-clk-e", x2000_sfc_clk_e, 0),
+ INGENIC_PIN_GROUP("sfc-ce-d", x2000_sfc_ce_d, 1),
+ INGENIC_PIN_GROUP("sfc-ce-e", x2000_sfc_ce_e, 0),
INGENIC_PIN_GROUP("ssi0-dt-b", x2000_ssi0_dt_b, 1),
INGENIC_PIN_GROUP("ssi0-dt-d", x2000_ssi0_dt_d, 1),
INGENIC_PIN_GROUP("ssi0-dr-b", x2000_ssi0_dr_b, 1),
INGENIC_PIN_GROUP("ssi0-dr-d", x2000_ssi0_dr_d, 1),
INGENIC_PIN_GROUP("ssi0-clk-b", x2000_ssi0_clk_b, 1),
INGENIC_PIN_GROUP("ssi0-clk-d", x2000_ssi0_clk_d, 1),
- INGENIC_PIN_GROUP("ssi0-ce0-b", x2000_ssi0_ce0_b, 1),
- INGENIC_PIN_GROUP("ssi0-ce0-d", x2000_ssi0_ce0_d, 1),
+ INGENIC_PIN_GROUP("ssi0-ce-b", x2000_ssi0_ce_b, 1),
+ INGENIC_PIN_GROUP("ssi0-ce-d", x2000_ssi0_ce_d, 1),
INGENIC_PIN_GROUP("ssi1-dt-c", x2000_ssi1_dt_c, 2),
INGENIC_PIN_GROUP("ssi1-dt-d", x2000_ssi1_dt_d, 2),
INGENIC_PIN_GROUP("ssi1-dt-e", x2000_ssi1_dt_e, 1),
@@ -2565,9 +2739,9 @@ static const struct group_desc x2000_groups[] = {
INGENIC_PIN_GROUP("ssi1-clk-c", x2000_ssi1_clk_c, 2),
INGENIC_PIN_GROUP("ssi1-clk-d", x2000_ssi1_clk_d, 2),
INGENIC_PIN_GROUP("ssi1-clk-e", x2000_ssi1_clk_e, 1),
- INGENIC_PIN_GROUP("ssi1-ce0-c", x2000_ssi1_ce0_c, 2),
- INGENIC_PIN_GROUP("ssi1-ce0-d", x2000_ssi1_ce0_d, 2),
- INGENIC_PIN_GROUP("ssi1-ce0-e", x2000_ssi1_ce0_e, 1),
+ INGENIC_PIN_GROUP("ssi1-ce-c", x2000_ssi1_ce_c, 2),
+ INGENIC_PIN_GROUP("ssi1-ce-d", x2000_ssi1_ce_d, 2),
+ INGENIC_PIN_GROUP("ssi1-ce-e", x2000_ssi1_ce_e, 1),
INGENIC_PIN_GROUP("mmc0-1bit", x2000_mmc0_1bit, 0),
INGENIC_PIN_GROUP("mmc0-4bit", x2000_mmc0_4bit, 0),
INGENIC_PIN_GROUP("mmc0-8bit", x2000_mmc0_8bit, 0),
@@ -2612,10 +2786,10 @@ static const struct group_desc x2000_groups[] = {
INGENIC_PIN_GROUP("i2s3-data-tx3", x2000_i2s3_data_tx3, 2),
INGENIC_PIN_GROUP("i2s3-clk-tx", x2000_i2s3_clk_tx, 2),
INGENIC_PIN_GROUP("i2s3-sysclk-tx", x2000_i2s3_sysclk_tx, 2),
- INGENIC_PIN_GROUP("dmic0", x2000_dmic0, 0),
- INGENIC_PIN_GROUP("dmic1", x2000_dmic1, 0),
- INGENIC_PIN_GROUP("dmic2", x2000_dmic2, 0),
- INGENIC_PIN_GROUP("dmic3", x2000_dmic3, 0),
+ INGENIC_PIN_GROUP("dmic-if0", x2000_dmic_if0, 0),
+ INGENIC_PIN_GROUP("dmic-if1", x2000_dmic_if1, 0),
+ INGENIC_PIN_GROUP("dmic-if2", x2000_dmic_if2, 0),
+ INGENIC_PIN_GROUP("dmic-if3", x2000_dmic_if3, 0),
INGENIC_PIN_GROUP_FUNCS("cim-data-8bit", x2000_cim_8bit,
x2000_cim_8bit_funcs),
INGENIC_PIN_GROUP("cim-data-12bit", x2000_cim_12bit, 0),
@@ -2670,18 +2844,21 @@ static const char *x2000_uart6_groups[] = { "uart6-data-a", "uart6-data-c", };
static const char *x2000_uart7_groups[] = { "uart7-data-a", "uart7-data-c", };
static const char *x2000_uart8_groups[] = { "uart8-data", };
static const char *x2000_uart9_groups[] = { "uart9-data", };
-static const char *x2000_sfc_groups[] = { "sfc0-d", "sfc0-e", "sfc1", };
+static const char *x2000_sfc_groups[] = {
+ "sfc-data-if0-d", "sfc-data-if0-e", "sfc-data-if1",
+ "sfc-clk-d", "sfc-clk-e", "sfc-ce-d", "sfc-ce-e",
+};
static const char *x2000_ssi0_groups[] = {
"ssi0-dt-b", "ssi0-dt-d",
"ssi0-dr-b", "ssi0-dr-d",
"ssi0-clk-b", "ssi0-clk-d",
- "ssi0-ce0-b", "ssi0-ce0-d",
+ "ssi0-ce-b", "ssi0-ce-d",
};
static const char *x2000_ssi1_groups[] = {
"ssi1-dt-c", "ssi1-dt-d", "ssi1-dt-e",
"ssi1-dr-c", "ssi1-dr-d", "ssi1-dr-e",
"ssi1-clk-c", "ssi1-clk-d", "ssi1-clk-e",
- "ssi1-ce0-c", "ssi1-ce0-d", "ssi1-ce0-e",
+ "ssi1-ce-c", "ssi1-ce-d", "ssi1-ce-e",
};
static const char *x2000_mmc0_groups[] = { "mmc0-1bit", "mmc0-4bit", "mmc0-8bit", };
static const char *x2000_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", };
@@ -2711,7 +2888,9 @@ static const char *x2000_i2s3_groups[] = {
"i2s3-data-tx0", "i2s3-data-tx1", "i2s3-data-tx2", "i2s3-data-tx3",
"i2s3-clk-tx", "i2s3-sysclk-tx",
};
-static const char *x2000_dmic_groups[] = { "dmic0", "dmic1", "dmic2", "dmic3", };
+static const char *x2000_dmic_groups[] = {
+ "dmic-if0", "dmic-if1", "dmic-if2", "dmic-if3",
+};
static const char *x2000_cim_groups[] = { "cim-data-8bit", "cim-data-12bit", };
static const char *x2000_lcd_groups[] = {
"lcd-tft-8bit", "lcd-tft-16bit", "lcd-tft-18bit", "lcd-tft-24bit",
@@ -2802,6 +2981,216 @@ static const struct ingenic_chip_info x2000_chip_info = {
.pull_downs = x2000_pull_downs,
};
+static const u32 x2100_pull_ups[5] = {
+ 0x0003ffff, 0xffffffff, 0x1ff0ffff, 0xc7fe3f3f, 0x0fbf003f,
+};
+
+static const u32 x2100_pull_downs[5] = {
+ 0x0003ffff, 0xffffffff, 0x1ff0ffff, 0x00000000, 0x0fbf003f,
+};
+
+static int x2100_mac_pins[] = {
+ 0x4b, 0x47, 0x46, 0x4a, 0x43, 0x42, 0x4c, 0x4d, 0x4f, 0x41,
+};
+
+static const struct group_desc x2100_groups[] = {
+ INGENIC_PIN_GROUP("uart0-data", x2000_uart0_data, 2),
+ INGENIC_PIN_GROUP("uart0-hwflow", x2000_uart0_hwflow, 2),
+ INGENIC_PIN_GROUP("uart1-data", x2000_uart1_data, 1),
+ INGENIC_PIN_GROUP("uart1-hwflow", x2000_uart1_hwflow, 1),
+ INGENIC_PIN_GROUP("uart2-data", x2000_uart2_data, 0),
+ INGENIC_PIN_GROUP("uart3-data-c", x2000_uart3_data_c, 0),
+ INGENIC_PIN_GROUP("uart3-data-d", x2000_uart3_data_d, 1),
+ INGENIC_PIN_GROUP("uart3-hwflow-c", x2000_uart3_hwflow_c, 0),
+ INGENIC_PIN_GROUP("uart3-hwflow-d", x2000_uart3_hwflow_d, 1),
+ INGENIC_PIN_GROUP("uart4-data-a", x2000_uart4_data_a, 1),
+ INGENIC_PIN_GROUP("uart4-data-c", x2000_uart4_data_c, 3),
+ INGENIC_PIN_GROUP("uart4-hwflow-a", x2000_uart4_hwflow_a, 1),
+ INGENIC_PIN_GROUP("uart4-hwflow-c", x2000_uart4_hwflow_c, 3),
+ INGENIC_PIN_GROUP("uart5-data-a", x2000_uart5_data_a, 1),
+ INGENIC_PIN_GROUP("uart5-data-c", x2000_uart5_data_c, 3),
+ INGENIC_PIN_GROUP("uart6-data-a", x2000_uart6_data_a, 1),
+ INGENIC_PIN_GROUP("uart6-data-c", x2000_uart6_data_c, 3),
+ INGENIC_PIN_GROUP("uart7-data-a", x2000_uart7_data_a, 1),
+ INGENIC_PIN_GROUP("uart7-data-c", x2000_uart7_data_c, 3),
+ INGENIC_PIN_GROUP("uart8-data", x2000_uart8_data, 3),
+ INGENIC_PIN_GROUP("uart9-data", x2000_uart9_data, 3),
+ INGENIC_PIN_GROUP("sfc-data-if0-d", x2000_sfc_data_if0_d, 1),
+ INGENIC_PIN_GROUP("sfc-data-if0-e", x2000_sfc_data_if0_e, 0),
+ INGENIC_PIN_GROUP("sfc-data-if1", x2000_sfc_data_if1, 1),
+ INGENIC_PIN_GROUP("sfc-clk-d", x2000_sfc_clk_d, 1),
+ INGENIC_PIN_GROUP("sfc-clk-e", x2000_sfc_clk_e, 0),
+ INGENIC_PIN_GROUP("sfc-ce-d", x2000_sfc_ce_d, 1),
+ INGENIC_PIN_GROUP("sfc-ce-e", x2000_sfc_ce_e, 0),
+ INGENIC_PIN_GROUP("ssi0-dt-b", x2000_ssi0_dt_b, 1),
+ INGENIC_PIN_GROUP("ssi0-dt-d", x2000_ssi0_dt_d, 1),
+ INGENIC_PIN_GROUP("ssi0-dr-b", x2000_ssi0_dr_b, 1),
+ INGENIC_PIN_GROUP("ssi0-dr-d", x2000_ssi0_dr_d, 1),
+ INGENIC_PIN_GROUP("ssi0-clk-b", x2000_ssi0_clk_b, 1),
+ INGENIC_PIN_GROUP("ssi0-clk-d", x2000_ssi0_clk_d, 1),
+ INGENIC_PIN_GROUP("ssi0-ce-b", x2000_ssi0_ce_b, 1),
+ INGENIC_PIN_GROUP("ssi0-ce-d", x2000_ssi0_ce_d, 1),
+ INGENIC_PIN_GROUP("ssi1-dt-c", x2000_ssi1_dt_c, 2),
+ INGENIC_PIN_GROUP("ssi1-dt-d", x2000_ssi1_dt_d, 2),
+ INGENIC_PIN_GROUP("ssi1-dt-e", x2000_ssi1_dt_e, 1),
+ INGENIC_PIN_GROUP("ssi1-dr-c", x2000_ssi1_dr_c, 2),
+ INGENIC_PIN_GROUP("ssi1-dr-d", x2000_ssi1_dr_d, 2),
+ INGENIC_PIN_GROUP("ssi1-dr-e", x2000_ssi1_dr_e, 1),
+ INGENIC_PIN_GROUP("ssi1-clk-c", x2000_ssi1_clk_c, 2),
+ INGENIC_PIN_GROUP("ssi1-clk-d", x2000_ssi1_clk_d, 2),
+ INGENIC_PIN_GROUP("ssi1-clk-e", x2000_ssi1_clk_e, 1),
+ INGENIC_PIN_GROUP("ssi1-ce-c", x2000_ssi1_ce_c, 2),
+ INGENIC_PIN_GROUP("ssi1-ce-d", x2000_ssi1_ce_d, 2),
+ INGENIC_PIN_GROUP("ssi1-ce-e", x2000_ssi1_ce_e, 1),
+ INGENIC_PIN_GROUP("mmc0-1bit", x2000_mmc0_1bit, 0),
+ INGENIC_PIN_GROUP("mmc0-4bit", x2000_mmc0_4bit, 0),
+ INGENIC_PIN_GROUP("mmc0-8bit", x2000_mmc0_8bit, 0),
+ INGENIC_PIN_GROUP("mmc1-1bit", x2000_mmc1_1bit, 0),
+ INGENIC_PIN_GROUP("mmc1-4bit", x2000_mmc1_4bit, 0),
+ INGENIC_PIN_GROUP("mmc2-1bit", x2000_mmc2_1bit, 0),
+ INGENIC_PIN_GROUP("mmc2-4bit", x2000_mmc2_4bit, 0),
+ INGENIC_PIN_GROUP("emc-8bit-data", x2000_emc_8bit_data, 0),
+ INGENIC_PIN_GROUP("emc-16bit-data", x2000_emc_16bit_data, 0),
+ INGENIC_PIN_GROUP("emc-addr", x2000_emc_addr, 0),
+ INGENIC_PIN_GROUP("emc-rd-we", x2000_emc_rd_we, 0),
+ INGENIC_PIN_GROUP("emc-wait", x2000_emc_wait, 0),
+ INGENIC_PIN_GROUP("emc-cs1", x2000_emc_cs1, 3),
+ INGENIC_PIN_GROUP("emc-cs2", x2000_emc_cs2, 3),
+ INGENIC_PIN_GROUP("i2c0-data", x2000_i2c0, 3),
+ INGENIC_PIN_GROUP("i2c1-data-c", x2000_i2c1_c, 2),
+ INGENIC_PIN_GROUP("i2c1-data-d", x2000_i2c1_d, 1),
+ INGENIC_PIN_GROUP("i2c2-data-b", x2000_i2c2_b, 2),
+ INGENIC_PIN_GROUP("i2c2-data-d", x2000_i2c2_d, 2),
+ INGENIC_PIN_GROUP("i2c2-data-e", x2000_i2c2_e, 1),
+ INGENIC_PIN_GROUP("i2c3-data-a", x2000_i2c3_a, 0),
+ INGENIC_PIN_GROUP("i2c3-data-d", x2000_i2c3_d, 1),
+ INGENIC_PIN_GROUP("i2c4-data-c", x2000_i2c4_c, 1),
+ INGENIC_PIN_GROUP("i2c4-data-d", x2000_i2c4_d, 2),
+ INGENIC_PIN_GROUP("i2c5-data-c", x2000_i2c5_c, 1),
+ INGENIC_PIN_GROUP("i2c5-data-d", x2000_i2c5_d, 1),
+ INGENIC_PIN_GROUP("i2s1-data-tx", x2000_i2s1_data_tx, 2),
+ INGENIC_PIN_GROUP("i2s1-data-rx", x2000_i2s1_data_rx, 2),
+ INGENIC_PIN_GROUP("i2s1-clk-tx", x2000_i2s1_clk_tx, 2),
+ INGENIC_PIN_GROUP("i2s1-clk-rx", x2000_i2s1_clk_rx, 2),
+ INGENIC_PIN_GROUP("i2s1-sysclk-tx", x2000_i2s1_sysclk_tx, 2),
+ INGENIC_PIN_GROUP("i2s1-sysclk-rx", x2000_i2s1_sysclk_rx, 2),
+ INGENIC_PIN_GROUP("i2s2-data-rx0", x2000_i2s2_data_rx0, 2),
+ INGENIC_PIN_GROUP("i2s2-data-rx1", x2000_i2s2_data_rx1, 2),
+ INGENIC_PIN_GROUP("i2s2-data-rx2", x2000_i2s2_data_rx2, 2),
+ INGENIC_PIN_GROUP("i2s2-data-rx3", x2000_i2s2_data_rx3, 2),
+ INGENIC_PIN_GROUP("i2s2-clk-rx", x2000_i2s2_clk_rx, 2),
+ INGENIC_PIN_GROUP("i2s2-sysclk-rx", x2000_i2s2_sysclk_rx, 2),
+ INGENIC_PIN_GROUP("i2s3-data-tx0", x2000_i2s3_data_tx0, 2),
+ INGENIC_PIN_GROUP("i2s3-data-tx1", x2000_i2s3_data_tx1, 2),
+ INGENIC_PIN_GROUP("i2s3-data-tx2", x2000_i2s3_data_tx2, 2),
+ INGENIC_PIN_GROUP("i2s3-data-tx3", x2000_i2s3_data_tx3, 2),
+ INGENIC_PIN_GROUP("i2s3-clk-tx", x2000_i2s3_clk_tx, 2),
+ INGENIC_PIN_GROUP("i2s3-sysclk-tx", x2000_i2s3_sysclk_tx, 2),
+ INGENIC_PIN_GROUP("dmic-if0", x2000_dmic_if0, 0),
+ INGENIC_PIN_GROUP("dmic-if1", x2000_dmic_if1, 0),
+ INGENIC_PIN_GROUP("dmic-if2", x2000_dmic_if2, 0),
+ INGENIC_PIN_GROUP("dmic-if3", x2000_dmic_if3, 0),
+ INGENIC_PIN_GROUP_FUNCS("cim-data-8bit", x2000_cim_8bit,
+ x2000_cim_8bit_funcs),
+ INGENIC_PIN_GROUP("cim-data-12bit", x2000_cim_12bit, 0),
+ INGENIC_PIN_GROUP("lcd-tft-8bit", x2000_lcd_tft_8bit, 1),
+ INGENIC_PIN_GROUP("lcd-tft-16bit", x2000_lcd_tft_16bit, 1),
+ INGENIC_PIN_GROUP("lcd-tft-18bit", x2000_lcd_tft_18bit, 1),
+ INGENIC_PIN_GROUP("lcd-tft-24bit", x2000_lcd_tft_24bit, 1),
+ INGENIC_PIN_GROUP("lcd-slcd-8bit", x2000_lcd_slcd_8bit, 2),
+ INGENIC_PIN_GROUP("lcd-slcd-16bit", x2000_lcd_tft_16bit, 2),
+ INGENIC_PIN_GROUP("pwm0-c", x2000_pwm_pwm0_c, 0),
+ INGENIC_PIN_GROUP("pwm0-d", x2000_pwm_pwm0_d, 2),
+ INGENIC_PIN_GROUP("pwm1-c", x2000_pwm_pwm1_c, 0),
+ INGENIC_PIN_GROUP("pwm1-d", x2000_pwm_pwm1_d, 2),
+ INGENIC_PIN_GROUP("pwm2-c", x2000_pwm_pwm2_c, 0),
+ INGENIC_PIN_GROUP("pwm2-e", x2000_pwm_pwm2_e, 1),
+ INGENIC_PIN_GROUP("pwm3-c", x2000_pwm_pwm3_c, 0),
+ INGENIC_PIN_GROUP("pwm3-e", x2000_pwm_pwm3_e, 1),
+ INGENIC_PIN_GROUP("pwm4-c", x2000_pwm_pwm4_c, 0),
+ INGENIC_PIN_GROUP("pwm4-e", x2000_pwm_pwm4_e, 1),
+ INGENIC_PIN_GROUP("pwm5-c", x2000_pwm_pwm5_c, 0),
+ INGENIC_PIN_GROUP("pwm5-e", x2000_pwm_pwm5_e, 1),
+ INGENIC_PIN_GROUP("pwm6-c", x2000_pwm_pwm6_c, 0),
+ INGENIC_PIN_GROUP("pwm6-e", x2000_pwm_pwm6_e, 1),
+ INGENIC_PIN_GROUP("pwm7-c", x2000_pwm_pwm7_c, 0),
+ INGENIC_PIN_GROUP("pwm7-e", x2000_pwm_pwm7_e, 1),
+ INGENIC_PIN_GROUP("pwm8", x2000_pwm_pwm8, 0),
+ INGENIC_PIN_GROUP("pwm9", x2000_pwm_pwm9, 0),
+ INGENIC_PIN_GROUP("pwm10", x2000_pwm_pwm10, 0),
+ INGENIC_PIN_GROUP("pwm11", x2000_pwm_pwm11, 0),
+ INGENIC_PIN_GROUP("pwm12", x2000_pwm_pwm12, 0),
+ INGENIC_PIN_GROUP("pwm13", x2000_pwm_pwm13, 0),
+ INGENIC_PIN_GROUP("pwm14", x2000_pwm_pwm14, 0),
+ INGENIC_PIN_GROUP("pwm15", x2000_pwm_pwm15, 0),
+ INGENIC_PIN_GROUP("mac", x2100_mac, 1),
+};
+
+static const char *x2100_mac_groups[] = { "mac", };
+
+static const struct function_desc x2100_functions[] = {
+ { "uart0", x2000_uart0_groups, ARRAY_SIZE(x2000_uart0_groups), },
+ { "uart1", x2000_uart1_groups, ARRAY_SIZE(x2000_uart1_groups), },
+ { "uart2", x2000_uart2_groups, ARRAY_SIZE(x2000_uart2_groups), },
+ { "uart3", x2000_uart3_groups, ARRAY_SIZE(x2000_uart3_groups), },
+ { "uart4", x2000_uart4_groups, ARRAY_SIZE(x2000_uart4_groups), },
+ { "uart5", x2000_uart5_groups, ARRAY_SIZE(x2000_uart5_groups), },
+ { "uart6", x2000_uart6_groups, ARRAY_SIZE(x2000_uart6_groups), },
+ { "uart7", x2000_uart7_groups, ARRAY_SIZE(x2000_uart7_groups), },
+ { "uart8", x2000_uart8_groups, ARRAY_SIZE(x2000_uart8_groups), },
+ { "uart9", x2000_uart9_groups, ARRAY_SIZE(x2000_uart9_groups), },
+ { "sfc", x2000_sfc_groups, ARRAY_SIZE(x2000_sfc_groups), },
+ { "ssi0", x2000_ssi0_groups, ARRAY_SIZE(x2000_ssi0_groups), },
+ { "ssi1", x2000_ssi1_groups, ARRAY_SIZE(x2000_ssi1_groups), },
+ { "mmc0", x2000_mmc0_groups, ARRAY_SIZE(x2000_mmc0_groups), },
+ { "mmc1", x2000_mmc1_groups, ARRAY_SIZE(x2000_mmc1_groups), },
+ { "mmc2", x2000_mmc2_groups, ARRAY_SIZE(x2000_mmc2_groups), },
+ { "emc", x2000_emc_groups, ARRAY_SIZE(x2000_emc_groups), },
+ { "emc-cs1", x2000_cs1_groups, ARRAY_SIZE(x2000_cs1_groups), },
+ { "emc-cs2", x2000_cs2_groups, ARRAY_SIZE(x2000_cs2_groups), },
+ { "i2c0", x2000_i2c0_groups, ARRAY_SIZE(x2000_i2c0_groups), },
+ { "i2c1", x2000_i2c1_groups, ARRAY_SIZE(x2000_i2c1_groups), },
+ { "i2c2", x2000_i2c2_groups, ARRAY_SIZE(x2000_i2c2_groups), },
+ { "i2c3", x2000_i2c3_groups, ARRAY_SIZE(x2000_i2c3_groups), },
+ { "i2c4", x2000_i2c4_groups, ARRAY_SIZE(x2000_i2c4_groups), },
+ { "i2c5", x2000_i2c5_groups, ARRAY_SIZE(x2000_i2c5_groups), },
+ { "i2s1", x2000_i2s1_groups, ARRAY_SIZE(x2000_i2s1_groups), },
+ { "i2s2", x2000_i2s2_groups, ARRAY_SIZE(x2000_i2s2_groups), },
+ { "i2s3", x2000_i2s3_groups, ARRAY_SIZE(x2000_i2s3_groups), },
+ { "dmic", x2000_dmic_groups, ARRAY_SIZE(x2000_dmic_groups), },
+ { "cim", x2000_cim_groups, ARRAY_SIZE(x2000_cim_groups), },
+ { "lcd", x2000_lcd_groups, ARRAY_SIZE(x2000_lcd_groups), },
+ { "pwm0", x2000_pwm0_groups, ARRAY_SIZE(x2000_pwm0_groups), },
+ { "pwm1", x2000_pwm1_groups, ARRAY_SIZE(x2000_pwm1_groups), },
+ { "pwm2", x2000_pwm2_groups, ARRAY_SIZE(x2000_pwm2_groups), },
+ { "pwm3", x2000_pwm3_groups, ARRAY_SIZE(x2000_pwm3_groups), },
+ { "pwm4", x2000_pwm4_groups, ARRAY_SIZE(x2000_pwm4_groups), },
+ { "pwm5", x2000_pwm5_groups, ARRAY_SIZE(x2000_pwm5_groups), },
+ { "pwm6", x2000_pwm6_groups, ARRAY_SIZE(x2000_pwm6_groups), },
+ { "pwm7", x2000_pwm7_groups, ARRAY_SIZE(x2000_pwm7_groups), },
+ { "pwm8", x2000_pwm8_groups, ARRAY_SIZE(x2000_pwm8_groups), },
+ { "pwm9", x2000_pwm9_groups, ARRAY_SIZE(x2000_pwm9_groups), },
+ { "pwm10", x2000_pwm10_groups, ARRAY_SIZE(x2000_pwm10_groups), },
+ { "pwm11", x2000_pwm11_groups, ARRAY_SIZE(x2000_pwm11_groups), },
+ { "pwm12", x2000_pwm12_groups, ARRAY_SIZE(x2000_pwm12_groups), },
+ { "pwm13", x2000_pwm13_groups, ARRAY_SIZE(x2000_pwm13_groups), },
+ { "pwm14", x2000_pwm14_groups, ARRAY_SIZE(x2000_pwm14_groups), },
+ { "pwm15", x2000_pwm15_groups, ARRAY_SIZE(x2000_pwm15_groups), },
+ { "mac", x2100_mac_groups, ARRAY_SIZE(x2100_mac_groups), },
+};
+
+static const struct ingenic_chip_info x2100_chip_info = {
+ .num_chips = 5,
+ .reg_offset = 0x100,
+ .version = ID_X2100,
+ .groups = x2100_groups,
+ .num_groups = ARRAY_SIZE(x2100_groups),
+ .functions = x2100_functions,
+ .num_functions = ARRAY_SIZE(x2100_functions),
+ .pull_ups = x2100_pull_ups,
+ .pull_downs = x2100_pull_downs,
+};
+
static u32 ingenic_gpio_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
{
unsigned int val;
@@ -3441,17 +3830,17 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
{
if (jzpc->info->version >= ID_X2000) {
switch (bias) {
- case PIN_CONFIG_BIAS_PULL_UP:
+ case GPIO_PULL_UP:
ingenic_config_pin(jzpc, pin, X2000_GPIO_PEPD, false);
ingenic_config_pin(jzpc, pin, X2000_GPIO_PEPU, true);
break;
- case PIN_CONFIG_BIAS_PULL_DOWN:
+ case GPIO_PULL_DOWN:
ingenic_config_pin(jzpc, pin, X2000_GPIO_PEPU, false);
ingenic_config_pin(jzpc, pin, X2000_GPIO_PEPD, true);
break;
- case PIN_CONFIG_BIAS_DISABLE:
+ case GPIO_PULL_DIS:
default:
ingenic_config_pin(jzpc, pin, X2000_GPIO_PEPU, false);
ingenic_config_pin(jzpc, pin, X2000_GPIO_PEPD, false);
@@ -3654,19 +4043,20 @@ static const struct regmap_config ingenic_pinctrl_regmap_config = {
.reg_stride = 4,
};
-static const struct of_device_id ingenic_gpio_of_match[] __initconst = {
- { .compatible = "ingenic,jz4730-gpio", },
- { .compatible = "ingenic,jz4740-gpio", },
- { .compatible = "ingenic,jz4725b-gpio", },
- { .compatible = "ingenic,jz4750-gpio", },
- { .compatible = "ingenic,jz4755-gpio", },
- { .compatible = "ingenic,jz4760-gpio", },
- { .compatible = "ingenic,jz4770-gpio", },
- { .compatible = "ingenic,jz4775-gpio", },
- { .compatible = "ingenic,jz4780-gpio", },
- { .compatible = "ingenic,x1000-gpio", },
- { .compatible = "ingenic,x1830-gpio", },
- { .compatible = "ingenic,x2000-gpio", },
+static const struct of_device_id ingenic_gpio_of_matches[] __initconst = {
+ { .compatible = "ingenic,jz4730-gpio" },
+ { .compatible = "ingenic,jz4740-gpio" },
+ { .compatible = "ingenic,jz4725b-gpio" },
+ { .compatible = "ingenic,jz4750-gpio" },
+ { .compatible = "ingenic,jz4755-gpio" },
+ { .compatible = "ingenic,jz4760-gpio" },
+ { .compatible = "ingenic,jz4770-gpio" },
+ { .compatible = "ingenic,jz4775-gpio" },
+ { .compatible = "ingenic,jz4780-gpio" },
+ { .compatible = "ingenic,x1000-gpio" },
+ { .compatible = "ingenic,x1830-gpio" },
+ { .compatible = "ingenic,x2000-gpio" },
+ { .compatible = "ingenic,x2100-gpio" },
{},
};
@@ -3759,6 +4149,7 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
void __iomem *base;
const struct ingenic_chip_info *chip_info;
struct device_node *node;
+ struct regmap_config regmap_config;
unsigned int i;
int err;
@@ -3776,8 +4167,10 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- jzpc->map = devm_regmap_init_mmio(dev, base,
- &ingenic_pinctrl_regmap_config);
+ regmap_config = ingenic_pinctrl_regmap_config;
+ regmap_config.max_register = chip_info->num_chips * chip_info->reg_offset;
+
+ jzpc->map = devm_regmap_init_mmio(dev, base, &regmap_config);
if (IS_ERR(jzpc->map)) {
dev_err(dev, "Failed to create regmap\n");
return PTR_ERR(jzpc->map);
@@ -3843,7 +4236,7 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
dev_set_drvdata(dev, jzpc->map);
for_each_child_of_node(dev->of_node, node) {
- if (of_match_node(ingenic_gpio_of_match, node)) {
+ if (of_match_node(ingenic_gpio_of_matches, node)) {
err = ingenic_gpio_probe(jzpc, node);
if (err) {
of_node_put(node);
@@ -3857,7 +4250,7 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
#define IF_ENABLED(cfg, ptr) PTR_IF(IS_ENABLED(cfg), (ptr))
-static const struct of_device_id ingenic_pinctrl_of_match[] = {
+static const struct of_device_id ingenic_pinctrl_of_matches[] = {
{
.compatible = "ingenic,jz4730-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_JZ4730, &jz4730_chip_info)
@@ -3922,13 +4315,17 @@ static const struct of_device_id ingenic_pinctrl_of_match[] = {
.compatible = "ingenic,x2000e-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_X2000, &x2000_chip_info)
},
+ {
+ .compatible = "ingenic,x2100-pinctrl",
+ .data = IF_ENABLED(CONFIG_MACH_X2100, &x2100_chip_info)
+ },
{ /* sentinel */ },
};
static struct platform_driver ingenic_pinctrl_driver = {
.driver = {
.name = "pinctrl-ingenic",
- .of_match_table = ingenic_pinctrl_of_match,
+ .of_match_table = ingenic_pinctrl_of_matches,
},
};
diff --git a/drivers/pinctrl/pinctrl-keembay.c b/drivers/pinctrl/pinctrl-keembay.c
new file mode 100644
index 000000000000..2bce563d5b8b
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-keembay.c
@@ -0,0 +1,1731 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2020 Intel Corporation */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include <linux/platform_device.h>
+
+#include "core.h"
+#include "pinmux.h"
+
+/* GPIO data registers' offsets */
+#define KEEMBAY_GPIO_DATA_OUT 0x000
+#define KEEMBAY_GPIO_DATA_IN 0x020
+#define KEEMBAY_GPIO_DATA_IN_RAW 0x040
+#define KEEMBAY_GPIO_DATA_HIGH 0x060
+#define KEEMBAY_GPIO_DATA_LOW 0x080
+
+/* GPIO Interrupt and mode registers' offsets */
+#define KEEMBAY_GPIO_INT_CFG 0x000
+#define KEEMBAY_GPIO_MODE 0x070
+
+/* GPIO mode register bit fields */
+#define KEEMBAY_GPIO_MODE_PULLUP_MASK GENMASK(13, 12)
+#define KEEMBAY_GPIO_MODE_DRIVE_MASK GENMASK(8, 7)
+#define KEEMBAY_GPIO_MODE_INV_MASK GENMASK(5, 4)
+#define KEEMBAY_GPIO_MODE_SELECT_MASK GENMASK(2, 0)
+#define KEEMBAY_GPIO_MODE_DIR_OVR BIT(15)
+#define KEEMBAY_GPIO_MODE_REN BIT(11)
+#define KEEMBAY_GPIO_MODE_SCHMITT_EN BIT(10)
+#define KEEMBAY_GPIO_MODE_SLEW_RATE BIT(9)
+#define KEEMBAY_GPIO_IRQ_ENABLE BIT(7)
+#define KEEMBAY_GPIO_MODE_DIR BIT(3)
+#define KEEMBAY_GPIO_MODE_DEFAULT 0x7
+#define KEEMBAY_GPIO_MODE_INV_VAL 0x3
+
+#define KEEMBAY_GPIO_DISABLE 0
+#define KEEMBAY_GPIO_PULL_UP 1
+#define KEEMBAY_GPIO_PULL_DOWN 2
+#define KEEMBAY_GPIO_BUS_HOLD 3
+#define KEEMBAY_GPIO_NUM_IRQ 8
+#define KEEMBAY_GPIO_MAX_PER_IRQ 4
+#define KEEMBAY_GPIO_MAX_PER_REG 32
+#define KEEMBAY_GPIO_MIN_STRENGTH 2
+#define KEEMBAY_GPIO_MAX_STRENGTH 12
+#define KEEMBAY_GPIO_SENSE_LOW (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)
+
+/* GPIO reg address calculation */
+#define KEEMBAY_GPIO_REG_OFFSET(pin) ((pin) * 4)
+
+/**
+ * struct keembay_mux_desc - Mux properties of each GPIO pin
+ * @mode: Pin mode when operating in this function
+ * @name: Pin function name
+ */
+struct keembay_mux_desc {
+ u8 mode;
+ const char *name;
+};
+
+#define KEEMBAY_PIN_DESC(pin_number, pin_name, ...) { \
+ .number = pin_number, \
+ .name = pin_name, \
+ .drv_data = &(struct keembay_mux_desc[]) { \
+ __VA_ARGS__, { } }, \
+} \
+
+#define KEEMBAY_MUX(pin_mode, pin_function) { \
+ .mode = pin_mode, \
+ .name = pin_function, \
+} \
+
+/**
+ * struct keembay_gpio_irq - Config of each GPIO Interrupt sources
+ * @source: Interrupt source number (0 - 7)
+ * @line: Actual Interrupt line number
+ * @pins: Array of GPIO pins using this Interrupt line
+ * @trigger: Interrupt trigger type for this line
+ * @num_share: Number of pins currently using this Interrupt line
+ */
+struct keembay_gpio_irq {
+ unsigned int source;
+ unsigned int line;
+ unsigned int pins[KEEMBAY_GPIO_MAX_PER_IRQ];
+ unsigned int trigger;
+ unsigned int num_share;
+};
+
+/**
+ * struct keembay_pinctrl - Intel Keembay pinctrl structure
+ * @pctrl: Pointer to the pin controller device
+ * @base0: First register base address
+ * @base1: Second register base address
+ * @dev: Pointer to the device structure
+ * @chip: GPIO chip used by this pin controller
+ * @soc: Pin control configuration data based on SoC
+ * @lock: Spinlock to protect various gpio config register access
+ * @ngroups: Number of pin groups available
+ * @nfuncs: Number of pin functions available
+ * @npins: Number of GPIO pins available
+ * @irq: Store Interrupt source
+ * @max_gpios_level_type: Store max level trigger type
+ * @max_gpios_edge_type: Store max edge trigger type
+ */
+struct keembay_pinctrl {
+ struct pinctrl_dev *pctrl;
+ void __iomem *base0;
+ void __iomem *base1;
+ struct device *dev;
+ struct gpio_chip chip;
+ const struct keembay_pin_soc *soc;
+ raw_spinlock_t lock;
+ unsigned int ngroups;
+ unsigned int nfuncs;
+ unsigned int npins;
+ struct keembay_gpio_irq irq[KEEMBAY_GPIO_NUM_IRQ];
+ int max_gpios_level_type;
+ int max_gpios_edge_type;
+};
+
+/**
+ * struct keembay_pin_soc - Pin control config data based on SoC
+ * @pins: Pin description structure
+ */
+struct keembay_pin_soc {
+ const struct pinctrl_pin_desc *pins;
+};
+
+static const struct pinctrl_pin_desc keembay_pins[] = {
+ KEEMBAY_PIN_DESC(0, "GPIO0",
+ KEEMBAY_MUX(0x0, "I2S0_M0"),
+ KEEMBAY_MUX(0x1, "SD0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "I2C0_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(1, "GPIO1",
+ KEEMBAY_MUX(0x0, "I2S0_M0"),
+ KEEMBAY_MUX(0x1, "SD0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "I2C0_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(2, "GPIO2",
+ KEEMBAY_MUX(0x0, "I2S0_M0"),
+ KEEMBAY_MUX(0x1, "I2S0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "I2C1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(3, "GPIO3",
+ KEEMBAY_MUX(0x0, "I2S0_M0"),
+ KEEMBAY_MUX(0x1, "I2S0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "I2C1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(4, "GPIO4",
+ KEEMBAY_MUX(0x0, "I2S0_M0"),
+ KEEMBAY_MUX(0x1, "I2S0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "I2C2_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(5, "GPIO5",
+ KEEMBAY_MUX(0x0, "I2S0_M0"),
+ KEEMBAY_MUX(0x1, "I2S0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "I2C2_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(6, "GPIO6",
+ KEEMBAY_MUX(0x0, "I2S1_M0"),
+ KEEMBAY_MUX(0x1, "SD0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "I2C3_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(7, "GPIO7",
+ KEEMBAY_MUX(0x0, "I2S1_M0"),
+ KEEMBAY_MUX(0x1, "SD0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "I2C3_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(8, "GPIO8",
+ KEEMBAY_MUX(0x0, "I2S1_M0"),
+ KEEMBAY_MUX(0x1, "I2S1_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS0_M2"),
+ KEEMBAY_MUX(0x3, "UART0_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(9, "GPIO9",
+ KEEMBAY_MUX(0x0, "I2S1_M0"),
+ KEEMBAY_MUX(0x1, "I2S1_M1"),
+ KEEMBAY_MUX(0x2, "PWM_M2"),
+ KEEMBAY_MUX(0x3, "UART0_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(10, "GPIO10",
+ KEEMBAY_MUX(0x0, "I2S2_M0"),
+ KEEMBAY_MUX(0x1, "SD0_M1"),
+ KEEMBAY_MUX(0x2, "PWM_M2"),
+ KEEMBAY_MUX(0x3, "UART0_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(11, "GPIO11",
+ KEEMBAY_MUX(0x0, "I2S2_M0"),
+ KEEMBAY_MUX(0x1, "SD0_M1"),
+ KEEMBAY_MUX(0x2, "PWM_M2"),
+ KEEMBAY_MUX(0x3, "UART0_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(12, "GPIO12",
+ KEEMBAY_MUX(0x0, "I2S2_M0"),
+ KEEMBAY_MUX(0x1, "I2S2_M1"),
+ KEEMBAY_MUX(0x2, "PWM_M2"),
+ KEEMBAY_MUX(0x3, "SPI0_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(13, "GPIO13",
+ KEEMBAY_MUX(0x0, "I2S2_M0"),
+ KEEMBAY_MUX(0x1, "I2S2_M1"),
+ KEEMBAY_MUX(0x2, "PWM_M2"),
+ KEEMBAY_MUX(0x3, "SPI0_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(14, "GPIO14",
+ KEEMBAY_MUX(0x0, "UART0_M0"),
+ KEEMBAY_MUX(0x1, "I2S3_M1"),
+ KEEMBAY_MUX(0x2, "PWM_M2"),
+ KEEMBAY_MUX(0x3, "SD1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "ETH_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(15, "GPIO15",
+ KEEMBAY_MUX(0x0, "UART0_M0"),
+ KEEMBAY_MUX(0x1, "I2S3_M1"),
+ KEEMBAY_MUX(0x2, "UART0_M2"),
+ KEEMBAY_MUX(0x3, "SD1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "SPI1_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(16, "GPIO16",
+ KEEMBAY_MUX(0x0, "UART0_M0"),
+ KEEMBAY_MUX(0x1, "I2S3_M1"),
+ KEEMBAY_MUX(0x2, "UART0_M2"),
+ KEEMBAY_MUX(0x3, "SD1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "SPI1_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(17, "GPIO17",
+ KEEMBAY_MUX(0x0, "UART0_M0"),
+ KEEMBAY_MUX(0x1, "I2S3_M1"),
+ KEEMBAY_MUX(0x2, "I2S3_M2"),
+ KEEMBAY_MUX(0x3, "SD1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "SPI1_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(18, "GPIO18",
+ KEEMBAY_MUX(0x0, "UART1_M0"),
+ KEEMBAY_MUX(0x1, "SPI0_M1"),
+ KEEMBAY_MUX(0x2, "I2S3_M2"),
+ KEEMBAY_MUX(0x3, "SD1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "SPI1_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(19, "GPIO19",
+ KEEMBAY_MUX(0x0, "UART1_M0"),
+ KEEMBAY_MUX(0x1, "LCD_M1"),
+ KEEMBAY_MUX(0x2, "DEBUG_M2"),
+ KEEMBAY_MUX(0x3, "SD1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "SPI1_M5"),
+ KEEMBAY_MUX(0x6, "LCD_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(20, "GPIO20",
+ KEEMBAY_MUX(0x0, "UART1_M0"),
+ KEEMBAY_MUX(0x1, "LCD_M1"),
+ KEEMBAY_MUX(0x2, "DEBUG_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "SPI1_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(21, "GPIO21",
+ KEEMBAY_MUX(0x0, "UART1_M0"),
+ KEEMBAY_MUX(0x1, "LCD_M1"),
+ KEEMBAY_MUX(0x2, "DEBUG_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C0_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(22, "GPIO22",
+ KEEMBAY_MUX(0x0, "I2C0_M0"),
+ KEEMBAY_MUX(0x1, "UART2_M1"),
+ KEEMBAY_MUX(0x2, "DEBUG_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C0_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(23, "GPIO23",
+ KEEMBAY_MUX(0x0, "I2C0_M0"),
+ KEEMBAY_MUX(0x1, "UART2_M1"),
+ KEEMBAY_MUX(0x2, "DEBUG_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C1_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(24, "GPIO24",
+ KEEMBAY_MUX(0x0, "I2C1_M0"),
+ KEEMBAY_MUX(0x1, "UART2_M1"),
+ KEEMBAY_MUX(0x2, "DEBUG_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C1_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(25, "GPIO25",
+ KEEMBAY_MUX(0x0, "I2C1_M0"),
+ KEEMBAY_MUX(0x1, "UART2_M1"),
+ KEEMBAY_MUX(0x2, "SPI0_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C2_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(26, "GPIO26",
+ KEEMBAY_MUX(0x0, "SPI0_M0"),
+ KEEMBAY_MUX(0x1, "I2C2_M1"),
+ KEEMBAY_MUX(0x2, "UART0_M2"),
+ KEEMBAY_MUX(0x3, "DSU_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C2_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(27, "GPIO27",
+ KEEMBAY_MUX(0x0, "SPI0_M0"),
+ KEEMBAY_MUX(0x1, "I2C2_M1"),
+ KEEMBAY_MUX(0x2, "UART0_M2"),
+ KEEMBAY_MUX(0x3, "DSU_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C0_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(28, "GPIO28",
+ KEEMBAY_MUX(0x0, "SPI0_M0"),
+ KEEMBAY_MUX(0x1, "I2C3_M1"),
+ KEEMBAY_MUX(0x2, "UART0_M2"),
+ KEEMBAY_MUX(0x3, "PWM_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C1_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS0_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(29, "GPIO29",
+ KEEMBAY_MUX(0x0, "SPI0_M0"),
+ KEEMBAY_MUX(0x1, "I2C3_M1"),
+ KEEMBAY_MUX(0x2, "UART0_M2"),
+ KEEMBAY_MUX(0x3, "PWM_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I3C2_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(30, "GPIO30",
+ KEEMBAY_MUX(0x0, "SPI0_M0"),
+ KEEMBAY_MUX(0x1, "I2S0_M1"),
+ KEEMBAY_MUX(0x2, "I2C4_M2"),
+ KEEMBAY_MUX(0x3, "PWM_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(31, "GPIO31",
+ KEEMBAY_MUX(0x0, "SPI0_M0"),
+ KEEMBAY_MUX(0x1, "I2S0_M1"),
+ KEEMBAY_MUX(0x2, "I2C4_M2"),
+ KEEMBAY_MUX(0x3, "PWM_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "UART1_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(32, "GPIO32",
+ KEEMBAY_MUX(0x0, "SD0_M0"),
+ KEEMBAY_MUX(0x1, "SPI0_M1"),
+ KEEMBAY_MUX(0x2, "UART1_M2"),
+ KEEMBAY_MUX(0x3, "PWM_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "PCIE_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(33, "GPIO33",
+ KEEMBAY_MUX(0x0, "SD0_M0"),
+ KEEMBAY_MUX(0x1, "SPI0_M1"),
+ KEEMBAY_MUX(0x2, "UART1_M2"),
+ KEEMBAY_MUX(0x3, "PWM_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "PCIE_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(34, "GPIO34",
+ KEEMBAY_MUX(0x0, "SD0_M0"),
+ KEEMBAY_MUX(0x1, "SPI0_M1"),
+ KEEMBAY_MUX(0x2, "I2C0_M2"),
+ KEEMBAY_MUX(0x3, "UART1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I2S0_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(35, "GPIO35",
+ KEEMBAY_MUX(0x0, "SD0_M0"),
+ KEEMBAY_MUX(0x1, "PCIE_M1"),
+ KEEMBAY_MUX(0x2, "I2C0_M2"),
+ KEEMBAY_MUX(0x3, "UART1_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I2S0_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(36, "GPIO36",
+ KEEMBAY_MUX(0x0, "SD0_M0"),
+ KEEMBAY_MUX(0x1, "SPI3_M1"),
+ KEEMBAY_MUX(0x2, "I2C1_M2"),
+ KEEMBAY_MUX(0x3, "DEBUG_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I2S0_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(37, "GPIO37",
+ KEEMBAY_MUX(0x0, "SD0_M0"),
+ KEEMBAY_MUX(0x1, "SPI3_M1"),
+ KEEMBAY_MUX(0x2, "I2C1_M2"),
+ KEEMBAY_MUX(0x3, "DEBUG_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "I2S0_M5"),
+ KEEMBAY_MUX(0x6, "SLVDS1_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(38, "GPIO38",
+ KEEMBAY_MUX(0x0, "I3C1_M0"),
+ KEEMBAY_MUX(0x1, "SPI3_M1"),
+ KEEMBAY_MUX(0x2, "UART3_M2"),
+ KEEMBAY_MUX(0x3, "DEBUG_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2C2_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(39, "GPIO39",
+ KEEMBAY_MUX(0x0, "I3C1_M0"),
+ KEEMBAY_MUX(0x1, "SPI3_M1"),
+ KEEMBAY_MUX(0x2, "UART3_M2"),
+ KEEMBAY_MUX(0x3, "DEBUG_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2C2_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(40, "GPIO40",
+ KEEMBAY_MUX(0x0, "I2S2_M0"),
+ KEEMBAY_MUX(0x1, "SPI3_M1"),
+ KEEMBAY_MUX(0x2, "UART3_M2"),
+ KEEMBAY_MUX(0x3, "DEBUG_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2C3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(41, "GPIO41",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI3_M1"),
+ KEEMBAY_MUX(0x2, "SPI3_M2"),
+ KEEMBAY_MUX(0x3, "DEBUG_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2C3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(42, "GPIO42",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SD1_M1"),
+ KEEMBAY_MUX(0x2, "SPI3_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "CAM_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2C4_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(43, "GPIO43",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SD1_M1"),
+ KEEMBAY_MUX(0x2, "SPI3_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "I2S0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2C4_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(44, "GPIO44",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SD1_M1"),
+ KEEMBAY_MUX(0x2, "SPI0_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "I2S0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(45, "GPIO45",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SD1_M1"),
+ KEEMBAY_MUX(0x2, "SPI0_M2"),
+ KEEMBAY_MUX(0x3, "CPR_M3"),
+ KEEMBAY_MUX(0x4, "I2S0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(46, "GPIO46",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SD1_M1"),
+ KEEMBAY_MUX(0x2, "SPI0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(47, "GPIO47",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SD1_M1"),
+ KEEMBAY_MUX(0x2, "SPI0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(48, "GPIO48",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "UART2_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(49, "GPIO49",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "UART2_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S1_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(50, "GPIO50",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "UART2_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S1_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(51, "GPIO51",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "UART2_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S1_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(52, "GPIO52",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "SD0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S1_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(53, "GPIO53",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "SD0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S2_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(54, "GPIO54",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "SD0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S2_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(55, "GPIO55",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "SD1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S2_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(56, "GPIO56",
+ KEEMBAY_MUX(0x0, "ETH_M0"),
+ KEEMBAY_MUX(0x1, "SPI2_M1"),
+ KEEMBAY_MUX(0x2, "SD1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I2S2_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(57, "GPIO57",
+ KEEMBAY_MUX(0x0, "SPI1_M0"),
+ KEEMBAY_MUX(0x1, "I2S1_M1"),
+ KEEMBAY_MUX(0x2, "SD1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "UART0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(58, "GPIO58",
+ KEEMBAY_MUX(0x0, "SPI1_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SD0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "UART0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(59, "GPIO59",
+ KEEMBAY_MUX(0x0, "SPI1_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SD0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "UART0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(60, "GPIO60",
+ KEEMBAY_MUX(0x0, "SPI1_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "I3C1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "UART0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(61, "GPIO61",
+ KEEMBAY_MUX(0x0, "SPI1_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SD0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "UART1_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(62, "GPIO62",
+ KEEMBAY_MUX(0x0, "SPI1_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SD1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "UART1_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(63, "GPIO63",
+ KEEMBAY_MUX(0x0, "I2S1_M0"),
+ KEEMBAY_MUX(0x1, "SPI1_M1"),
+ KEEMBAY_MUX(0x2, "SD1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "UART1_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(64, "GPIO64",
+ KEEMBAY_MUX(0x0, "I2S2_M0"),
+ KEEMBAY_MUX(0x1, "SPI1_M1"),
+ KEEMBAY_MUX(0x2, "ETH_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "UART1_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(65, "GPIO65",
+ KEEMBAY_MUX(0x0, "I3C0_M0"),
+ KEEMBAY_MUX(0x1, "SPI1_M1"),
+ KEEMBAY_MUX(0x2, "SD1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SPI0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(66, "GPIO66",
+ KEEMBAY_MUX(0x0, "I3C0_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "I2C0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SPI0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "CAM_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(67, "GPIO67",
+ KEEMBAY_MUX(0x0, "I3C1_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "I2C0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SPI0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2S3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(68, "GPIO68",
+ KEEMBAY_MUX(0x0, "I3C1_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "I2C1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SPI0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2S3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(69, "GPIO69",
+ KEEMBAY_MUX(0x0, "I3C2_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "I2C1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SPI0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2S3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(70, "GPIO70",
+ KEEMBAY_MUX(0x0, "I3C2_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SPI0_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SD0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2S3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(71, "GPIO71",
+ KEEMBAY_MUX(0x0, "I3C0_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SD0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "I2S3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(72, "GPIO72",
+ KEEMBAY_MUX(0x0, "I3C1_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SD0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "UART2_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(73, "GPIO73",
+ KEEMBAY_MUX(0x0, "I3C2_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SD0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "UART2_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(74, "GPIO74",
+ KEEMBAY_MUX(0x0, "I3C0_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SD0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "UART2_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(75, "GPIO75",
+ KEEMBAY_MUX(0x0, "I3C0_M0"),
+ KEEMBAY_MUX(0x1, "ETH_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "SD0_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "UART2_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(76, "GPIO76",
+ KEEMBAY_MUX(0x0, "I2C2_M0"),
+ KEEMBAY_MUX(0x1, "I3C0_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "ETH_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "UART3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(77, "GPIO77",
+ KEEMBAY_MUX(0x0, "PCIE_M0"),
+ KEEMBAY_MUX(0x1, "I3C1_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I3C2_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "UART3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(78, "GPIO78",
+ KEEMBAY_MUX(0x0, "PCIE_M0"),
+ KEEMBAY_MUX(0x1, "I3C2_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I3C2_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "UART3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+ KEEMBAY_PIN_DESC(79, "GPIO79",
+ KEEMBAY_MUX(0x0, "PCIE_M0"),
+ KEEMBAY_MUX(0x1, "I2C2_M1"),
+ KEEMBAY_MUX(0x2, "SLVDS1_M2"),
+ KEEMBAY_MUX(0x3, "TPIU_M3"),
+ KEEMBAY_MUX(0x4, "I3C2_M4"),
+ KEEMBAY_MUX(0x5, "LCD_M5"),
+ KEEMBAY_MUX(0x6, "UART3_M6"),
+ KEEMBAY_MUX(0x7, "GPIO_M7")),
+};
+
+static inline u32 keembay_read_reg(void __iomem *base, unsigned int pin)
+{
+ return readl(base + KEEMBAY_GPIO_REG_OFFSET(pin));
+}
+
+static inline u32 keembay_read_gpio_reg(void __iomem *base, unsigned int pin)
+{
+ return keembay_read_reg(base, pin / KEEMBAY_GPIO_MAX_PER_REG);
+}
+
+static inline u32 keembay_read_pin(void __iomem *base, unsigned int pin)
+{
+ u32 val = keembay_read_gpio_reg(base, pin);
+
+ return !!(val & BIT(pin % KEEMBAY_GPIO_MAX_PER_REG));
+}
+
+static inline void keembay_write_reg(u32 val, void __iomem *base, unsigned int pin)
+{
+ writel(val, base + KEEMBAY_GPIO_REG_OFFSET(pin));
+}
+
+static inline void keembay_write_gpio_reg(u32 val, void __iomem *base, unsigned int pin)
+{
+ keembay_write_reg(val, base, pin / KEEMBAY_GPIO_MAX_PER_REG);
+}
+
+static void keembay_gpio_invert(struct keembay_pinctrl *kpc, unsigned int pin)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ /*
+ * This IP doesn't support the falling edge and low level interrupt
+ * trigger. Invert API is used to mimic the falling edge and low
+ * level support
+ */
+
+ val |= FIELD_PREP(KEEMBAY_GPIO_MODE_INV_MASK, KEEMBAY_GPIO_MODE_INV_VAL);
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+}
+
+static void keembay_gpio_restore_default(struct keembay_pinctrl *kpc, unsigned int pin)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ val &= FIELD_PREP(KEEMBAY_GPIO_MODE_INV_MASK, 0);
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+}
+
+static int keembay_request_gpio(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned int pin)
+{
+ struct keembay_pinctrl *kpc = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int val;
+
+ if (pin >= kpc->npins)
+ return -EINVAL;
+
+ val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+ val = FIELD_GET(KEEMBAY_GPIO_MODE_SELECT_MASK, val);
+
+ /* As per Pin Mux Map, Modes 0 to 6 are for peripherals */
+ if (val != KEEMBAY_GPIO_MODE_DEFAULT)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int keembay_set_mux(struct pinctrl_dev *pctldev, unsigned int fun_sel,
+ unsigned int grp_sel)
+{
+ struct keembay_pinctrl *kpc = pinctrl_dev_get_drvdata(pctldev);
+ struct function_desc *func;
+ struct group_desc *grp;
+ unsigned int val;
+ u8 pin_mode;
+ int pin;
+
+ grp = pinctrl_generic_get_group(pctldev, grp_sel);
+ if (!grp)
+ return -EINVAL;
+
+ func = pinmux_generic_get_function(pctldev, fun_sel);
+ if (!func)
+ return -EINVAL;
+
+ /* Change modes for pins in the selected group */
+ pin = *grp->pins;
+ pin_mode = *(u8 *)(func->data);
+
+ val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+ val = u32_replace_bits(val, pin_mode, KEEMBAY_GPIO_MODE_SELECT_MASK);
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return 0;
+}
+
+static u32 keembay_pinconf_get_pull(struct keembay_pinctrl *kpc, unsigned int pin)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return FIELD_GET(KEEMBAY_GPIO_MODE_PULLUP_MASK, val);
+}
+
+static int keembay_pinconf_set_pull(struct keembay_pinctrl *kpc, unsigned int pin,
+ unsigned int pull)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ val = u32_replace_bits(val, pull, KEEMBAY_GPIO_MODE_PULLUP_MASK);
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return 0;
+}
+
+static int keembay_pinconf_get_drive(struct keembay_pinctrl *kpc, unsigned int pin)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ val = FIELD_GET(KEEMBAY_GPIO_MODE_DRIVE_MASK, val) * 4;
+ if (val)
+ return val;
+
+ return KEEMBAY_GPIO_MIN_STRENGTH;
+}
+
+static int keembay_pinconf_set_drive(struct keembay_pinctrl *kpc, unsigned int pin,
+ unsigned int drive)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+ unsigned int strength = clamp_val(drive, KEEMBAY_GPIO_MIN_STRENGTH,
+ KEEMBAY_GPIO_MAX_STRENGTH) / 4;
+
+ val = u32_replace_bits(val, strength, KEEMBAY_GPIO_MODE_DRIVE_MASK);
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return 0;
+}
+
+static int keembay_pinconf_get_slew_rate(struct keembay_pinctrl *kpc, unsigned int pin)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return !!(val & KEEMBAY_GPIO_MODE_SLEW_RATE);
+}
+
+static int keembay_pinconf_set_slew_rate(struct keembay_pinctrl *kpc, unsigned int pin,
+ unsigned int slew_rate)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ if (slew_rate)
+ val |= KEEMBAY_GPIO_MODE_SLEW_RATE;
+ else
+ val &= ~KEEMBAY_GPIO_MODE_SLEW_RATE;
+
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return 0;
+}
+
+static int keembay_pinconf_get_schmitt(struct keembay_pinctrl *kpc, unsigned int pin)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return !!(val & KEEMBAY_GPIO_MODE_SCHMITT_EN);
+}
+
+static int keembay_pinconf_set_schmitt(struct keembay_pinctrl *kpc, unsigned int pin,
+ unsigned int schmitt_en)
+{
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ if (schmitt_en)
+ val |= KEEMBAY_GPIO_MODE_SCHMITT_EN;
+ else
+ val &= ~KEEMBAY_GPIO_MODE_SCHMITT_EN;
+
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return 0;
+}
+
+static int keembay_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *cfg)
+{
+ struct keembay_pinctrl *kpc = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int param = pinconf_to_config_param(*cfg);
+ unsigned int val;
+
+ if (pin >= kpc->npins)
+ return -EINVAL;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ if (keembay_pinconf_get_pull(kpc, pin) != KEEMBAY_GPIO_DISABLE)
+ return -EINVAL;
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (keembay_pinconf_get_pull(kpc, pin) != KEEMBAY_GPIO_PULL_UP)
+ return -EINVAL;
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (keembay_pinconf_get_pull(kpc, pin) != KEEMBAY_GPIO_PULL_DOWN)
+ return -EINVAL;
+ break;
+
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ if (keembay_pinconf_get_pull(kpc, pin) != KEEMBAY_GPIO_BUS_HOLD)
+ return -EINVAL;
+ break;
+
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (!keembay_pinconf_get_schmitt(kpc, pin))
+ return -EINVAL;
+ break;
+
+ case PIN_CONFIG_SLEW_RATE:
+ val = keembay_pinconf_get_slew_rate(kpc, pin);
+ *cfg = pinconf_to_config_packed(param, val);
+ break;
+
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ val = keembay_pinconf_get_drive(kpc, pin);
+ *cfg = pinconf_to_config_packed(param, val);
+ break;
+
+ default:
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int keembay_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *cfg, unsigned int num_configs)
+{
+ struct keembay_pinctrl *kpc = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param;
+ unsigned int arg, i;
+ int ret = 0;
+
+ if (pin >= kpc->npins)
+ return -EINVAL;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(cfg[i]);
+ arg = pinconf_to_config_argument(cfg[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ ret = keembay_pinconf_set_pull(kpc, pin, KEEMBAY_GPIO_DISABLE);
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ ret = keembay_pinconf_set_pull(kpc, pin, KEEMBAY_GPIO_PULL_UP);
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ ret = keembay_pinconf_set_pull(kpc, pin, KEEMBAY_GPIO_PULL_DOWN);
+ break;
+
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ ret = keembay_pinconf_set_pull(kpc, pin, KEEMBAY_GPIO_BUS_HOLD);
+ break;
+
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ ret = keembay_pinconf_set_schmitt(kpc, pin, arg);
+ break;
+
+ case PIN_CONFIG_SLEW_RATE:
+ ret = keembay_pinconf_set_slew_rate(kpc, pin, arg);
+ break;
+
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ ret = keembay_pinconf_set_drive(kpc, pin, arg);
+ break;
+
+ default:
+ return -ENOTSUPP;
+ }
+ if (ret)
+ return ret;
+ }
+ return ret;
+}
+
+static const struct pinctrl_ops keembay_pctlops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static const struct pinmux_ops keembay_pmxops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .gpio_request_enable = keembay_request_gpio,
+ .set_mux = keembay_set_mux,
+};
+
+static const struct pinconf_ops keembay_confops = {
+ .is_generic = true,
+ .pin_config_get = keembay_pinconf_get,
+ .pin_config_set = keembay_pinconf_set,
+};
+
+static struct pinctrl_desc keembay_pinctrl_desc = {
+ .name = "keembay-pinmux",
+ .pctlops = &keembay_pctlops,
+ .pmxops = &keembay_pmxops,
+ .confops = &keembay_confops,
+ .owner = THIS_MODULE,
+};
+
+static int keembay_gpio_get(struct gpio_chip *gc, unsigned int pin)
+{
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+ unsigned int val, offset;
+
+ val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+ offset = (val & KEEMBAY_GPIO_MODE_DIR) ? KEEMBAY_GPIO_DATA_IN : KEEMBAY_GPIO_DATA_OUT;
+
+ return keembay_read_pin(kpc->base0 + offset, pin);
+}
+
+static void keembay_gpio_set(struct gpio_chip *gc, unsigned int pin, int val)
+{
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+ unsigned int reg_val;
+
+ reg_val = keembay_read_gpio_reg(kpc->base0 + KEEMBAY_GPIO_DATA_OUT, pin);
+ if (val)
+ keembay_write_gpio_reg(reg_val | BIT(pin % KEEMBAY_GPIO_MAX_PER_REG),
+ kpc->base0 + KEEMBAY_GPIO_DATA_HIGH, pin);
+ else
+ keembay_write_gpio_reg(~reg_val | BIT(pin % KEEMBAY_GPIO_MAX_PER_REG),
+ kpc->base0 + KEEMBAY_GPIO_DATA_LOW, pin);
+}
+
+static int keembay_gpio_get_direction(struct gpio_chip *gc, unsigned int pin)
+{
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+ unsigned int val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return !!(val & KEEMBAY_GPIO_MODE_DIR);
+}
+
+static int keembay_gpio_set_direction_in(struct gpio_chip *gc, unsigned int pin)
+{
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+ unsigned int val;
+
+ val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+ val |= KEEMBAY_GPIO_MODE_DIR;
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+
+ return 0;
+}
+
+static int keembay_gpio_set_direction_out(struct gpio_chip *gc,
+ unsigned int pin, int value)
+{
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+ unsigned int val;
+
+ val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+ val &= ~KEEMBAY_GPIO_MODE_DIR;
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_MODE, pin);
+ keembay_gpio_set(gc, pin, value);
+
+ return 0;
+}
+
+static void keembay_gpio_irq_handler(struct irq_desc *desc)
+{
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ unsigned int kmb_irq = irq_desc_get_irq(desc);
+ unsigned long reg, clump = 0, bit = 0;
+ struct irq_chip *parent_chip;
+ struct keembay_pinctrl *kpc;
+ unsigned int src, pin, val;
+
+ /* Identify GPIO interrupt number from GIC interrupt number */
+ for (src = 0; src < KEEMBAY_GPIO_NUM_IRQ; src++) {
+ if (kmb_irq == gc->irq.parents[src])
+ break;
+ }
+
+ if (src == KEEMBAY_GPIO_NUM_IRQ)
+ return;
+
+ parent_chip = irq_desc_get_chip(desc);
+ kpc = gpiochip_get_data(gc);
+
+ chained_irq_enter(parent_chip, desc);
+ reg = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_INT_CFG, src);
+
+ /*
+ * Each Interrupt line can be shared by up to 4 GPIO pins. Enable bit
+ * and input values were checked to identify the source of the
+ * Interrupt. The checked enable bit positions are 7, 15, 23 and 31.
+ */
+ for_each_set_clump8(bit, clump, &reg, BITS_PER_TYPE(typeof(reg))) {
+ pin = clump & ~KEEMBAY_GPIO_IRQ_ENABLE;
+ val = keembay_read_pin(kpc->base0 + KEEMBAY_GPIO_DATA_IN, pin);
+ kmb_irq = irq_linear_revmap(gc->irq.domain, pin);
+
+ /* Checks if the interrupt is enabled */
+ if (val && (clump & KEEMBAY_GPIO_IRQ_ENABLE))
+ generic_handle_irq(kmb_irq);
+ }
+ chained_irq_exit(parent_chip, desc);
+}
+
+static void keembay_gpio_clear_irq(struct irq_data *data, unsigned long pos,
+ u32 src, irq_hw_number_t pin)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+ unsigned long trig = irqd_get_trigger_type(data);
+ struct keembay_gpio_irq *irq = &kpc->irq[src];
+ unsigned long val;
+
+ /* Check if the value of pos/KEEMBAY_GPIO_NUM_IRQ is in valid range. */
+ if ((pos / KEEMBAY_GPIO_NUM_IRQ) >= KEEMBAY_GPIO_MAX_PER_IRQ)
+ return;
+
+ /* Retains val register as it handles other interrupts as well. */
+ val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_INT_CFG, src);
+
+ bitmap_set_value8(&val, 0, pos);
+ keembay_write_reg(val, kpc->base1 + KEEMBAY_GPIO_INT_CFG, src);
+
+ irq->num_share--;
+ irq->pins[pos / KEEMBAY_GPIO_NUM_IRQ] = 0;
+
+ if (trig & IRQ_TYPE_LEVEL_MASK)
+ keembay_gpio_restore_default(kpc, pin);
+
+ if (irq->trigger == IRQ_TYPE_LEVEL_HIGH)
+ kpc->max_gpios_level_type++;
+ else if (irq->trigger == IRQ_TYPE_EDGE_RISING)
+ kpc->max_gpios_edge_type++;
+}
+
+static int keembay_find_free_slot(struct keembay_pinctrl *kpc, unsigned int src)
+{
+ unsigned long val = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_INT_CFG, src);
+
+ return bitmap_find_free_region(&val, KEEMBAY_GPIO_MAX_PER_REG, 3) / KEEMBAY_GPIO_NUM_IRQ;
+}
+
+static int keembay_find_free_src(struct keembay_pinctrl *kpc, unsigned int trig)
+{
+ int src, type = 0;
+
+ if (trig & IRQ_TYPE_LEVEL_MASK)
+ type = IRQ_TYPE_LEVEL_HIGH;
+ else if (trig & IRQ_TYPE_EDGE_BOTH)
+ type = IRQ_TYPE_EDGE_RISING;
+
+ for (src = 0; src < KEEMBAY_GPIO_NUM_IRQ; src++) {
+ if (kpc->irq[src].trigger != type)
+ continue;
+
+ if (!keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_INT_CFG, src) ||
+ kpc->irq[src].num_share < KEEMBAY_GPIO_MAX_PER_IRQ)
+ return src;
+ }
+
+ return -EBUSY;
+}
+
+static void keembay_gpio_set_irq(struct keembay_pinctrl *kpc, int src,
+ int slot, irq_hw_number_t pin)
+{
+ unsigned long val = pin | KEEMBAY_GPIO_IRQ_ENABLE;
+ struct keembay_gpio_irq *irq = &kpc->irq[src];
+ unsigned long flags, reg;
+
+ raw_spin_lock_irqsave(&kpc->lock, flags);
+ reg = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_INT_CFG, src);
+ bitmap_set_value8(&reg, val, slot * 8);
+ keembay_write_reg(reg, kpc->base1 + KEEMBAY_GPIO_INT_CFG, src);
+ raw_spin_unlock_irqrestore(&kpc->lock, flags);
+
+ if (irq->trigger == IRQ_TYPE_LEVEL_HIGH)
+ kpc->max_gpios_level_type--;
+ else if (irq->trigger == IRQ_TYPE_EDGE_RISING)
+ kpc->max_gpios_edge_type--;
+
+ irq->source = src;
+ irq->pins[slot] = pin;
+ irq->num_share++;
+}
+
+static void keembay_gpio_irq_enable(struct irq_data *data)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+ unsigned int trig = irqd_get_trigger_type(data);
+ irq_hw_number_t pin = irqd_to_hwirq(data);
+ int src, slot;
+
+ /* Check which Interrupt source and slot is available */
+ src = keembay_find_free_src(kpc, trig);
+ slot = keembay_find_free_slot(kpc, src);
+
+ if (src < 0 || slot < 0)
+ return;
+
+ if (trig & KEEMBAY_GPIO_SENSE_LOW)
+ keembay_gpio_invert(kpc, pin);
+
+ keembay_gpio_set_irq(kpc, src, slot, pin);
+}
+
+static void keembay_gpio_irq_ack(struct irq_data *data)
+{
+ /*
+ * The keembay_gpio_irq_ack function is needed to handle_edge_irq.
+ * IRQ ack is not possible from the SOC perspective. The IP by itself
+ * is used for handling interrupts which do not come in short-time and
+ * not used as protocol or communication interrupts. All the interrupts
+ * are threaded IRQ interrupts. But this function is expected to be
+ * present as the gpio IP is registered with irq framework. Otherwise
+ * handle_edge_irq() fails.
+ */
+}
+
+static void keembay_gpio_irq_disable(struct irq_data *data)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+ irq_hw_number_t pin = irqd_to_hwirq(data);
+ unsigned long reg, clump = 0, pos = 0;
+ unsigned int src;
+
+ for (src = 0; src < KEEMBAY_GPIO_NUM_IRQ; src++) {
+ reg = keembay_read_reg(kpc->base1 + KEEMBAY_GPIO_INT_CFG, src);
+ for_each_set_clump8(pos, clump, &reg, BITS_PER_TYPE(typeof(reg))) {
+ if ((clump & ~KEEMBAY_GPIO_IRQ_ENABLE) == pin) {
+ keembay_gpio_clear_irq(data, pos, src, pin);
+ return;
+ }
+ }
+ }
+}
+
+static int keembay_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct keembay_pinctrl *kpc = gpiochip_get_data(gc);
+
+ /* Change EDGE_BOTH as EDGE_RISING in order to claim the IRQ for power button */
+ if (!kpc->max_gpios_edge_type && (type & IRQ_TYPE_EDGE_BOTH))
+ type = IRQ_TYPE_EDGE_RISING;
+
+ if (!kpc->max_gpios_level_type && (type & IRQ_TYPE_LEVEL_MASK))
+ type = IRQ_TYPE_NONE;
+
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ irq_set_handler_locked(data, handle_edge_irq);
+ else if (type & IRQ_TYPE_LEVEL_MASK)
+ irq_set_handler_locked(data, handle_level_irq);
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int keembay_gpio_add_pin_ranges(struct gpio_chip *chip)
+{
+ struct keembay_pinctrl *kpc = gpiochip_get_data(chip);
+ int ret;
+
+ ret = gpiochip_add_pin_range(chip, dev_name(kpc->dev), 0, 0, chip->ngpio);
+ if (ret)
+ dev_err_probe(kpc->dev, ret, "failed to add GPIO pin range\n");
+ return ret;
+}
+
+static struct irq_chip keembay_gpio_irqchip = {
+ .name = "keembay-gpio",
+ .irq_enable = keembay_gpio_irq_enable,
+ .irq_disable = keembay_gpio_irq_disable,
+ .irq_set_type = keembay_gpio_irq_set_type,
+ .irq_ack = keembay_gpio_irq_ack,
+};
+
+static int keembay_gpiochip_probe(struct keembay_pinctrl *kpc,
+ struct platform_device *pdev)
+{
+ unsigned int i, level_line = 0, edge_line = 0;
+ struct gpio_chip *gc = &kpc->chip;
+ struct gpio_irq_chip *girq;
+
+ /* Setup GPIO IRQ chip */
+ girq = &kpc->chip.irq;
+ girq->chip = &keembay_gpio_irqchip;
+ girq->parent_handler = keembay_gpio_irq_handler;
+ girq->num_parents = KEEMBAY_GPIO_NUM_IRQ;
+ girq->parents = devm_kcalloc(kpc->dev, girq->num_parents,
+ sizeof(*girq->parents), GFP_KERNEL);
+
+ if (!girq->parents)
+ return -ENOMEM;
+
+ /* Setup GPIO chip */
+ gc->label = dev_name(kpc->dev);
+ gc->parent = kpc->dev;
+ gc->request = gpiochip_generic_request;
+ gc->free = gpiochip_generic_free;
+ gc->get_direction = keembay_gpio_get_direction;
+ gc->direction_input = keembay_gpio_set_direction_in;
+ gc->direction_output = keembay_gpio_set_direction_out;
+ gc->get = keembay_gpio_get;
+ gc->set = keembay_gpio_set;
+ gc->set_config = gpiochip_generic_config;
+ gc->base = -1;
+ gc->ngpio = kpc->npins;
+ gc->add_pin_ranges = keembay_gpio_add_pin_ranges;
+
+ for (i = 0; i < KEEMBAY_GPIO_NUM_IRQ; i++) {
+ struct keembay_gpio_irq *kmb_irq = &kpc->irq[i];
+ int irq;
+
+ irq = platform_get_irq_optional(pdev, i);
+ if (irq <= 0)
+ continue;
+
+ girq->parents[i] = irq;
+ kmb_irq->line = girq->parents[i];
+ kmb_irq->source = i;
+ kmb_irq->trigger = irq_get_trigger_type(girq->parents[i]);
+ kmb_irq->num_share = 0;
+
+ if (kmb_irq->trigger == IRQ_TYPE_LEVEL_HIGH)
+ level_line++;
+ else
+ edge_line++;
+ }
+
+ kpc->max_gpios_level_type = level_line * KEEMBAY_GPIO_MAX_PER_IRQ;
+ kpc->max_gpios_edge_type = edge_line * KEEMBAY_GPIO_MAX_PER_IRQ;
+
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+
+ return devm_gpiochip_add_data(kpc->dev, gc, kpc);
+}
+
+static int keembay_build_groups(struct keembay_pinctrl *kpc)
+{
+ struct group_desc *grp;
+ unsigned int i;
+
+ kpc->ngroups = kpc->npins;
+ grp = devm_kcalloc(kpc->dev, kpc->ngroups, sizeof(*grp), GFP_KERNEL);
+ if (!grp)
+ return -ENOMEM;
+
+ /* Each pin is categorised as one group */
+ for (i = 0; i < kpc->ngroups; i++) {
+ const struct pinctrl_pin_desc *pdesc = keembay_pins + i;
+ struct group_desc *kmb_grp = grp + i;
+
+ kmb_grp->name = pdesc->name;
+ kmb_grp->pins = (int *)&pdesc->number;
+ pinctrl_generic_add_group(kpc->pctrl, kmb_grp->name,
+ kmb_grp->pins, 1, NULL);
+ }
+
+ return 0;
+}
+
+static int keembay_pinctrl_reg(struct keembay_pinctrl *kpc, struct device *dev)
+{
+ int ret;
+
+ keembay_pinctrl_desc.pins = keembay_pins;
+ ret = of_property_read_u32(dev->of_node, "ngpios", &kpc->npins);
+ if (ret < 0)
+ return ret;
+ keembay_pinctrl_desc.npins = kpc->npins;
+
+ kpc->pctrl = devm_pinctrl_register(kpc->dev, &keembay_pinctrl_desc, kpc);
+
+ return PTR_ERR_OR_ZERO(kpc->pctrl);
+}
+
+static int keembay_add_functions(struct keembay_pinctrl *kpc,
+ struct function_desc *function)
+{
+ unsigned int i;
+
+ /* Assign the groups for each function */
+ for (i = 0; i < kpc->npins; i++) {
+ const struct pinctrl_pin_desc *pdesc = keembay_pins + i;
+ struct keembay_mux_desc *mux = pdesc->drv_data;
+
+ while (mux->name) {
+ struct function_desc *func;
+ const char **grp;
+ size_t grp_size;
+ u32 j, grp_num;
+
+ for (j = 0; j < kpc->nfuncs; j++) {
+ if (!strcmp(mux->name, function[j].name))
+ break;
+ }
+
+ if (j == kpc->nfuncs)
+ return -EINVAL;
+
+ func = function + j;
+ grp_num = func->num_group_names;
+ grp_size = sizeof(*func->group_names);
+
+ if (!func->group_names) {
+ func->group_names = devm_kcalloc(kpc->dev,
+ grp_num,
+ grp_size,
+ GFP_KERNEL);
+ if (!func->group_names)
+ return -ENOMEM;
+ }
+
+ grp = func->group_names;
+ while (*grp)
+ grp++;
+
+ *grp = pdesc->name;
+ mux++;
+ }
+ }
+
+ /* Add all functions */
+ for (i = 0; i < kpc->nfuncs; i++) {
+ pinmux_generic_add_function(kpc->pctrl,
+ function[i].name,
+ function[i].group_names,
+ function[i].num_group_names,
+ function[i].data);
+ }
+
+ return 0;
+}
+
+static int keembay_build_functions(struct keembay_pinctrl *kpc)
+{
+ struct function_desc *keembay_funcs, *new_funcs;
+ int i;
+
+ /* Allocate total number of functions */
+ kpc->nfuncs = 0;
+ keembay_funcs = kcalloc(kpc->npins * 8, sizeof(*keembay_funcs), GFP_KERNEL);
+ if (!keembay_funcs)
+ return -ENOMEM;
+
+ /* Find total number of functions and each's properties */
+ for (i = 0; i < kpc->npins; i++) {
+ const struct pinctrl_pin_desc *pdesc = keembay_pins + i;
+ struct keembay_mux_desc *mux = pdesc->drv_data;
+
+ while (mux->name) {
+ struct function_desc *fdesc = keembay_funcs;
+
+ while (fdesc->name) {
+ if (!strcmp(mux->name, fdesc->name)) {
+ fdesc->num_group_names++;
+ break;
+ }
+
+ fdesc++;
+ }
+
+ if (!fdesc->name) {
+ fdesc->name = mux->name;
+ fdesc->num_group_names = 1;
+ fdesc->data = &mux->mode;
+ kpc->nfuncs++;
+ }
+
+ mux++;
+ }
+ }
+
+ /* Reallocate memory based on actual number of functions */
+ new_funcs = krealloc(keembay_funcs, kpc->nfuncs * sizeof(*new_funcs), GFP_KERNEL);
+ if (!new_funcs) {
+ kfree(keembay_funcs);
+ return -ENOMEM;
+ }
+
+ return keembay_add_functions(kpc, new_funcs);
+}
+
+static const struct keembay_pin_soc keembay_data = {
+ .pins = keembay_pins,
+};
+
+static const struct of_device_id keembay_pinctrl_match[] = {
+ { .compatible = "intel,keembay-pinctrl", .data = &keembay_data },
+ { }
+};
+MODULE_DEVICE_TABLE(of, keembay_pinctrl_match);
+
+static int keembay_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct keembay_pinctrl *kpc;
+ int ret;
+
+ kpc = devm_kzalloc(dev, sizeof(*kpc), GFP_KERNEL);
+ if (!kpc)
+ return -ENOMEM;
+
+ kpc->dev = dev;
+ kpc->soc = device_get_match_data(dev);
+
+ kpc->base0 = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(kpc->base0))
+ return PTR_ERR(kpc->base0);
+
+ kpc->base1 = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(kpc->base1))
+ return PTR_ERR(kpc->base1);
+
+ raw_spin_lock_init(&kpc->lock);
+
+ ret = keembay_pinctrl_reg(kpc, dev);
+ if (ret)
+ return ret;
+
+ ret = keembay_build_groups(kpc);
+ if (ret)
+ return ret;
+
+ ret = keembay_build_functions(kpc);
+ if (ret)
+ return ret;
+
+ ret = keembay_gpiochip_probe(kpc, pdev);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, kpc);
+
+ return 0;
+}
+
+static struct platform_driver keembay_pinctrl_driver = {
+ .probe = keembay_pinctrl_probe,
+ .driver = {
+ .name = "keembay-pinctrl",
+ .of_match_table = keembay_pinctrl_match,
+ },
+};
+module_platform_driver(keembay_pinctrl_driver);
+
+MODULE_AUTHOR("Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>");
+MODULE_AUTHOR("Vijayakannan Ayyathurai <vijayakannan.ayyathurai@intel.com>");
+MODULE_AUTHOR("Lakshmi Sowjanya D <lakshmi.sowjanya.d@intel.com>");
+MODULE_DESCRIPTION("Intel Keem Bay SoC pinctrl/GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index aa6e72214609..67bec7ea0f8b 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1115,7 +1115,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
{
const char *name = "pinctrl-single,bits";
struct pcs_func_vals *vals;
- int rows, *pins, found = 0, res = -ENOMEM, i, fsel, gsel;
+ int rows, *pins, found = 0, res = -ENOMEM, i, fsel;
int npins_in_row;
struct pcs_function *function = NULL;
@@ -1125,6 +1125,11 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
return -EINVAL;
}
+ if (PCS_HAS_PINCONF) {
+ dev_err(pcs->dev, "pinconf not supported\n");
+ return -ENOTSUPP;
+ }
+
npins_in_row = pcs->width / pcs->bits_per_pin;
vals = devm_kzalloc(pcs->dev,
@@ -1212,29 +1217,19 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
goto free_pins;
}
- gsel = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
- if (gsel < 0) {
- res = gsel;
+ res = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
+ if (res < 0)
goto free_function;
- }
(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
(*map)->data.mux.group = np->name;
(*map)->data.mux.function = np->name;
- if (PCS_HAS_PINCONF) {
- dev_err(pcs->dev, "pinconf not supported\n");
- goto free_pingroups;
- }
-
*num_maps = 1;
mutex_unlock(&pcs->mutex);
return 0;
-free_pingroups:
- pinctrl_generic_remove_group(pcs->pctl, gsel);
- *num_maps = 1;
free_function:
pinmux_generic_remove_function(pcs->pctl, fsel);
free_pins:
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index 008c83107a3c..5fa2488fae87 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -566,7 +566,7 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
u8 pending[NR_GPIO_REGS];
u8 src[NR_GPIO_REGS] = {0, 0, 0};
unsigned long n, status;
- int ret;
+ int i, ret;
ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_IRQ_GPI_PENDING,
&pending, NR_GPIO_REGS);
@@ -576,7 +576,9 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
src, NR_GPIO_REGS);
- status = *(unsigned long *)pending;
+ BUILD_BUG_ON(NR_GPIO_REGS > sizeof(status));
+ for (i = 0, status = 0; i < NR_GPIO_REGS; i++)
+ status |= (unsigned long)pending[i] << (i * 8);
for_each_set_bit(n, &status, gc->ngpio) {
handle_nested_irq(irq_find_mapping(gc->irq.domain, n));
stmfx_pinctrl_irq_toggle_trigger(pctl, n);
diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c
index 5fb924a2eedd..a96af8a76a7a 100644
--- a/drivers/pinctrl/pinctrl-zynq.c
+++ b/drivers/pinctrl/pinctrl-zynq.c
@@ -1028,6 +1028,7 @@ static int zynq_pinconf_cfg_get(struct pinctrl_dev *pctldev,
break;
}
case PIN_CONFIG_IOSTANDARD:
+ case PIN_CONFIG_POWER_SOURCE:
arg = zynq_pinconf_iostd_get(reg);
break;
default:
@@ -1078,6 +1079,7 @@ static int zynq_pinconf_cfg_set(struct pinctrl_dev *pctldev,
break;
case PIN_CONFIG_IOSTANDARD:
+ case PIN_CONFIG_POWER_SOURCE:
if (arg <= zynq_iostd_min || arg >= zynq_iostd_max) {
dev_warn(pctldev->dev,
"unsupported IO standard '%u'\n",
diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c
index bbde676b7313..e14012209992 100644
--- a/drivers/pinctrl/pinctrl-zynqmp.c
+++ b/drivers/pinctrl/pinctrl-zynqmp.c
@@ -866,15 +866,6 @@ static int zynqmp_pinctrl_probe(struct platform_device *pdev)
return ret;
}
-static int zynqmp_pinctrl_remove(struct platform_device *pdev)
-{
- struct zynqmp_pinctrl *pctrl = platform_get_drvdata(pdev);
-
- pinctrl_unregister(pctrl->pctrl);
-
- return 0;
-}
-
static const struct of_device_id zynqmp_pinctrl_of_match[] = {
{ .compatible = "xlnx,zynqmp-pinctrl" },
{ }
@@ -887,7 +878,6 @@ static struct platform_driver zynqmp_pinctrl_driver = {
.of_match_table = zynqmp_pinctrl_of_match,
},
.probe = zynqmp_pinctrl_probe,
- .remove = zynqmp_pinctrl_remove,
};
module_platform_driver(zynqmp_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index cad4e60df618..32ea2a8ec02b 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -88,6 +88,14 @@ config PINCTRL_MSM8960
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found in the Qualcomm 8960 platform.
+config PINCTRL_MDM9607
+ tristate "Qualcomm 9607 pin controller driver"
+ depends on GPIOLIB && OF
+ depends on PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 9607 platform.
+
config PINCTRL_MDM9615
tristate "Qualcomm 9615 pin controller driver"
depends on OF
@@ -256,6 +264,15 @@ config PINCTRL_SDX55
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc SDX55 platform.
+config PINCTRL_SM6115
+ tristate "Qualcomm Technologies Inc SM6115,SM4250 pin controller driver"
+ depends on GPIOLIB && OF
+ depends on PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM6115 and SM4250 platforms.
+
config PINCTRL_SM6125
tristate "Qualcomm Technologies Inc SM6125 pin controller driver"
depends on OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index d696fe2789bb..7a12e8cd2fba 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o
obj-$(CONFIG_PINCTRL_MSM8998) += pinctrl-msm8998.o
obj-$(CONFIG_PINCTRL_QCS404) += pinctrl-qcs404.o
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
+obj-$(CONFIG_PINCTRL_MDM9607) += pinctrl-mdm9607.o
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
@@ -30,6 +31,7 @@ obj-$(CONFIG_PINCTRL_SC8180X) += pinctrl-sc8180x.o
obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o
+obj-$(CONFIG_PINCTRL_SM6115) += pinctrl-sm6115.o
obj-$(CONFIG_PINCTRL_SM6125) += pinctrl-sm6125.o
obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o
obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o
diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
new file mode 100644
index 000000000000..d622b3df0fe7
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
@@ -0,0 +1,1087 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ *
+ * based on pinctrl-msm8916.c
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+static const struct pinctrl_pin_desc mdm9607_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "SDC1_CLK"),
+ PINCTRL_PIN(81, "SDC1_CMD"),
+ PINCTRL_PIN(82, "SDC1_DATA"),
+ PINCTRL_PIN(83, "SDC2_CLK"),
+ PINCTRL_PIN(84, "SDC2_CMD"),
+ PINCTRL_PIN(85, "SDC2_DATA"),
+ PINCTRL_PIN(86, "QDSD_CLK"),
+ PINCTRL_PIN(87, "QDSD_CMD"),
+ PINCTRL_PIN(88, "QDSD_DATA0"),
+ PINCTRL_PIN(89, "QDSD_DATA1"),
+ PINCTRL_PIN(90, "QDSD_DATA2"),
+ PINCTRL_PIN(91, "QDSD_DATA3"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+
+static const unsigned int sdc1_clk_pins[] = { 80 };
+static const unsigned int sdc1_cmd_pins[] = { 81 };
+static const unsigned int sdc1_data_pins[] = { 82 };
+static const unsigned int sdc2_clk_pins[] = { 83 };
+static const unsigned int sdc2_cmd_pins[] = { 84 };
+static const unsigned int sdc2_data_pins[] = { 85 };
+static const unsigned int qdsd_clk_pins[] = { 86 };
+static const unsigned int qdsd_cmd_pins[] = { 87 };
+static const unsigned int qdsd_data0_pins[] = { 88 };
+static const unsigned int qdsd_data1_pins[] = { 89 };
+static const unsigned int qdsd_data2_pins[] = { 90 };
+static const unsigned int qdsd_data3_pins[] = { 91 };
+
+#define FUNCTION(fname) \
+ [msm_mux_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = 0x1000 * id, \
+ .io_reg = 0x4 + 0x1000 * id, \
+ .intr_cfg_reg = 0x8 + 0x1000 * id, \
+ .intr_status_reg = 0xc + 0x1000 * id, \
+ .intr_target_reg = 0x8 + 0x1000 * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 4, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_target_kpss_val = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+enum mdm9607_functions {
+ msm_mux_adsp_ext,
+ msm_mux_atest_bbrx0,
+ msm_mux_atest_bbrx1,
+ msm_mux_atest_char,
+ msm_mux_atest_char0,
+ msm_mux_atest_char1,
+ msm_mux_atest_char2,
+ msm_mux_atest_char3,
+ msm_mux_atest_combodac_to_gpio_native,
+ msm_mux_atest_gpsadc_dtest0_native,
+ msm_mux_atest_gpsadc_dtest1_native,
+ msm_mux_atest_tsens,
+ msm_mux_backlight_en_b,
+ msm_mux_bimc_dte0,
+ msm_mux_bimc_dte1,
+ msm_mux_blsp1_spi,
+ msm_mux_blsp2_spi,
+ msm_mux_blsp3_spi,
+ msm_mux_blsp_i2c1,
+ msm_mux_blsp_i2c2,
+ msm_mux_blsp_i2c3,
+ msm_mux_blsp_i2c4,
+ msm_mux_blsp_i2c5,
+ msm_mux_blsp_i2c6,
+ msm_mux_blsp_spi1,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_spi3,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_spi6,
+ msm_mux_blsp_uart1,
+ msm_mux_blsp_uart2,
+ msm_mux_blsp_uart3,
+ msm_mux_blsp_uart4,
+ msm_mux_blsp_uart5,
+ msm_mux_blsp_uart6,
+ msm_mux_blsp_uim1,
+ msm_mux_blsp_uim2,
+ msm_mux_codec_int,
+ msm_mux_codec_rst,
+ msm_mux_coex_uart,
+ msm_mux_cri_trng,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_dbg_out,
+ msm_mux_ebi0_wrcdc,
+ msm_mux_ebi2_a,
+ msm_mux_ebi2_a_d_8_b,
+ msm_mux_ebi2_lcd,
+ msm_mux_ebi2_lcd_cs_n_b,
+ msm_mux_ebi2_lcd_te_b,
+ msm_mux_eth_irq,
+ msm_mux_eth_rst,
+ msm_mux_gcc_gp1_clk_a,
+ msm_mux_gcc_gp1_clk_b,
+ msm_mux_gcc_gp2_clk_a,
+ msm_mux_gcc_gp2_clk_b,
+ msm_mux_gcc_gp3_clk_a,
+ msm_mux_gcc_gp3_clk_b,
+ msm_mux_gcc_plltest,
+ msm_mux_gcc_tlmm,
+ msm_mux_gmac_mdio,
+ msm_mux_gpio,
+ msm_mux_gsm0_tx,
+ msm_mux_lcd_rst,
+ msm_mux_ldo_en,
+ msm_mux_ldo_update,
+ msm_mux_m_voc,
+ msm_mux_modem_tsync,
+ msm_mux_nav_ptp_pps_in_a,
+ msm_mux_nav_ptp_pps_in_b,
+ msm_mux_nav_tsync_out_a,
+ msm_mux_nav_tsync_out_b,
+ msm_mux_pa_indicator,
+ msm_mux_pbs0,
+ msm_mux_pbs1,
+ msm_mux_pbs2,
+ msm_mux_pri_mi2s_data0_a,
+ msm_mux_pri_mi2s_data1_a,
+ msm_mux_pri_mi2s_mclk_a,
+ msm_mux_pri_mi2s_sck_a,
+ msm_mux_pri_mi2s_ws_a,
+ msm_mux_prng_rosc,
+ msm_mux_ptp_pps_out_a,
+ msm_mux_ptp_pps_out_b,
+ msm_mux_pwr_crypto_enabled_a,
+ msm_mux_pwr_crypto_enabled_b,
+ msm_mux_pwr_modem_enabled_a,
+ msm_mux_pwr_modem_enabled_b,
+ msm_mux_pwr_nav_enabled_a,
+ msm_mux_pwr_nav_enabled_b,
+ msm_mux_qdss_cti_trig_in_a0,
+ msm_mux_qdss_cti_trig_in_a1,
+ msm_mux_qdss_cti_trig_in_b0,
+ msm_mux_qdss_cti_trig_in_b1,
+ msm_mux_qdss_cti_trig_out_a0,
+ msm_mux_qdss_cti_trig_out_a1,
+ msm_mux_qdss_cti_trig_out_b0,
+ msm_mux_qdss_cti_trig_out_b1,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_qdss_traceclk_b,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_qdss_tracectl_b,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_qdss_tracedata_b,
+ msm_mux_rcm_marker1,
+ msm_mux_rcm_marker2,
+ msm_mux_sd_write,
+ msm_mux_sec_mi2s,
+ msm_mux_sensor_en,
+ msm_mux_sensor_int2,
+ msm_mux_sensor_int3,
+ msm_mux_sensor_rst,
+ msm_mux_ssbi1,
+ msm_mux_ssbi2,
+ msm_mux_touch_rst,
+ msm_mux_ts_int,
+ msm_mux_uim1_clk,
+ msm_mux_uim1_data,
+ msm_mux_uim1_present,
+ msm_mux_uim1_reset,
+ msm_mux_uim2_clk,
+ msm_mux_uim2_data,
+ msm_mux_uim2_present,
+ msm_mux_uim2_reset,
+ msm_mux_uim_batt,
+ msm_mux_wlan_en1,
+ msm_mux__,
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79",
+};
+static const char * const blsp_spi3_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const blsp_uart3_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const qdss_tracedata_a_groups[] = {
+ "gpio0", "gpio1", "gpio4", "gpio5", "gpio20", "gpio21", "gpio22",
+ "gpio23", "gpio24", "gpio25", "gpio26", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79",
+};
+static const char * const bimc_dte1_groups[] = {
+ "gpio1", "gpio24",
+};
+static const char * const blsp_i2c3_groups[] = {
+ "gpio2", "gpio3",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+ "gpio2",
+};
+static const char * const bimc_dte0_groups[] = {
+ "gpio2", "gpio15",
+};
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+ "gpio3",
+};
+static const char * const blsp_spi2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uim2_groups[] = {
+ "gpio4", "gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio6", "gpio7",
+};
+static const char * const qdss_tracectl_a_groups[] = {
+ "gpio6",
+};
+static const char * const sensor_int2_groups[] = {
+ "gpio8",
+};
+static const char * const blsp_spi5_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const blsp_uart5_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const ebi2_lcd_groups[] = {
+ "gpio8", "gpio11", "gpio74", "gpio78",
+};
+static const char * const m_voc_groups[] = {
+ "gpio8", "gpio78",
+};
+static const char * const sensor_int3_groups[] = {
+ "gpio9",
+};
+static const char * const sensor_en_groups[] = {
+ "gpio10",
+};
+static const char * const blsp_i2c5_groups[] = {
+ "gpio10", "gpio11",
+};
+static const char * const ebi2_a_groups[] = {
+ "gpio10",
+};
+static const char * const qdss_tracedata_b_groups[] = {
+ "gpio10", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", "gpio46",
+ "gpio47", "gpio48", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55",
+ "gpio58", "gpio59",
+};
+static const char * const sensor_rst_groups[] = {
+ "gpio11",
+};
+static const char * const blsp2_spi_groups[] = {
+ "gpio11", "gpio13", "gpio77",
+};
+static const char * const blsp_spi1_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const blsp_uart1_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const blsp_uim1_groups[] = {
+ "gpio12", "gpio13",
+};
+static const char * const blsp3_spi_groups[] = {
+ "gpio12", "gpio26", "gpio76",
+};
+static const char * const gcc_gp2_clk_b_groups[] = {
+ "gpio12",
+};
+static const char * const gcc_gp3_clk_b_groups[] = {
+ "gpio13",
+};
+static const char * const blsp_i2c1_groups[] = {
+ "gpio14", "gpio15",
+};
+static const char * const gcc_gp1_clk_b_groups[] = {
+ "gpio14",
+};
+static const char * const blsp_spi4_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const blsp_uart4_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const rcm_marker1_groups[] = {
+ "gpio18",
+};
+static const char * const blsp_i2c4_groups[] = {
+ "gpio18", "gpio19",
+};
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+ "gpio18",
+};
+static const char * const rcm_marker2_groups[] = {
+ "gpio19",
+};
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+ "gpio19",
+};
+static const char * const blsp_spi6_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const blsp_uart6_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const pri_mi2s_ws_a_groups[] = {
+ "gpio20",
+};
+static const char * const ebi2_lcd_te_b_groups[] = {
+ "gpio20",
+};
+static const char * const blsp1_spi_groups[] = {
+ "gpio20", "gpio21", "gpio78",
+};
+static const char * const backlight_en_b_groups[] = {
+ "gpio21",
+};
+static const char * const pri_mi2s_data0_a_groups[] = {
+ "gpio21",
+};
+static const char * const pri_mi2s_data1_a_groups[] = {
+ "gpio22",
+};
+static const char * const blsp_i2c6_groups[] = {
+ "gpio22", "gpio23",
+};
+static const char * const ebi2_a_d_8_b_groups[] = {
+ "gpio22",
+};
+static const char * const pri_mi2s_sck_a_groups[] = {
+ "gpio23",
+};
+static const char * const ebi2_lcd_cs_n_b_groups[] = {
+ "gpio23",
+};
+static const char * const touch_rst_groups[] = {
+ "gpio24",
+};
+static const char * const pri_mi2s_mclk_a_groups[] = {
+ "gpio24",
+};
+static const char * const pwr_nav_enabled_a_groups[] = {
+ "gpio24",
+};
+static const char * const ts_int_groups[] = {
+ "gpio25",
+};
+static const char * const sd_write_groups[] = {
+ "gpio25",
+};
+static const char * const pwr_crypto_enabled_a_groups[] = {
+ "gpio25",
+};
+static const char * const codec_rst_groups[] = {
+ "gpio26",
+};
+static const char * const adsp_ext_groups[] = {
+ "gpio26",
+};
+static const char * const atest_combodac_to_gpio_native_groups[] = {
+ "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
+ "gpio33", "gpio34", "gpio35", "gpio41", "gpio45", "gpio49", "gpio50",
+ "gpio51", "gpio52", "gpio54", "gpio55", "gpio57", "gpio59",
+};
+static const char * const uim2_data_groups[] = {
+ "gpio27",
+};
+static const char * const gmac_mdio_groups[] = {
+ "gpio27", "gpio28",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+ "gpio27",
+};
+static const char * const uim2_clk_groups[] = {
+ "gpio28",
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+ "gpio28",
+};
+static const char * const eth_irq_groups[] = {
+ "gpio29",
+};
+static const char * const uim2_reset_groups[] = {
+ "gpio29",
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+ "gpio29",
+};
+static const char * const eth_rst_groups[] = {
+ "gpio30",
+};
+static const char * const uim2_present_groups[] = {
+ "gpio30",
+};
+static const char * const prng_rosc_groups[] = {
+ "gpio30",
+};
+static const char * const uim1_data_groups[] = {
+ "gpio31",
+};
+static const char * const uim1_clk_groups[] = {
+ "gpio32",
+};
+static const char * const uim1_reset_groups[] = {
+ "gpio33",
+};
+static const char * const uim1_present_groups[] = {
+ "gpio34",
+};
+static const char * const gcc_plltest_groups[] = {
+ "gpio34", "gpio35",
+};
+static const char * const uim_batt_groups[] = {
+ "gpio35",
+};
+static const char * const coex_uart_groups[] = {
+ "gpio36", "gpio37",
+};
+static const char * const codec_int_groups[] = {
+ "gpio38",
+};
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+ "gpio38",
+};
+static const char * const atest_bbrx1_groups[] = {
+ "gpio39",
+};
+static const char * const cri_trng0_groups[] = {
+ "gpio40",
+};
+static const char * const atest_bbrx0_groups[] = {
+ "gpio40",
+};
+static const char * const cri_trng_groups[] = {
+ "gpio42",
+};
+static const char * const qdss_cti_trig_in_b0_groups[] = {
+ "gpio44",
+};
+static const char * const atest_gpsadc_dtest0_native_groups[] = {
+ "gpio44",
+};
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+ "gpio45",
+};
+static const char * const qdss_tracectl_b_groups[] = {
+ "gpio49",
+};
+static const char * const qdss_traceclk_b_groups[] = {
+ "gpio50",
+};
+static const char * const pa_indicator_groups[] = {
+ "gpio51",
+};
+static const char * const modem_tsync_groups[] = {
+ "gpio53",
+};
+static const char * const nav_tsync_out_a_groups[] = {
+ "gpio53",
+};
+static const char * const nav_ptp_pps_in_a_groups[] = {
+ "gpio53",
+};
+static const char * const ptp_pps_out_a_groups[] = {
+ "gpio53",
+};
+static const char * const gsm0_tx_groups[] = {
+ "gpio55",
+};
+static const char * const qdss_cti_trig_in_b1_groups[] = {
+ "gpio56",
+};
+static const char * const cri_trng1_groups[] = {
+ "gpio57",
+};
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+ "gpio57",
+};
+static const char * const ssbi1_groups[] = {
+ "gpio58",
+};
+static const char * const atest_gpsadc_dtest1_native_groups[] = {
+ "gpio58",
+};
+static const char * const ssbi2_groups[] = {
+ "gpio59",
+};
+static const char * const atest_char3_groups[] = {
+ "gpio60",
+};
+static const char * const atest_char2_groups[] = {
+ "gpio61",
+};
+static const char * const atest_char1_groups[] = {
+ "gpio62",
+};
+static const char * const atest_char0_groups[] = {
+ "gpio63",
+};
+static const char * const atest_char_groups[] = {
+ "gpio64",
+};
+static const char * const ebi0_wrcdc_groups[] = {
+ "gpio70",
+};
+static const char * const ldo_update_groups[] = {
+ "gpio72",
+};
+static const char * const gcc_tlmm_groups[] = {
+ "gpio72",
+};
+static const char * const ldo_en_groups[] = {
+ "gpio73",
+};
+static const char * const dbg_out_groups[] = {
+ "gpio73",
+};
+static const char * const atest_tsens_groups[] = {
+ "gpio73",
+};
+static const char * const lcd_rst_groups[] = {
+ "gpio74",
+};
+static const char * const wlan_en1_groups[] = {
+ "gpio75",
+};
+static const char * const nav_tsync_out_b_groups[] = {
+ "gpio75",
+};
+static const char * const nav_ptp_pps_in_b_groups[] = {
+ "gpio75",
+};
+static const char * const ptp_pps_out_b_groups[] = {
+ "gpio75",
+};
+static const char * const pbs0_groups[] = {
+ "gpio76",
+};
+static const char * const sec_mi2s_groups[] = {
+ "gpio76", "gpio77", "gpio78", "gpio79",
+};
+static const char * const pwr_modem_enabled_a_groups[] = {
+ "gpio76",
+};
+static const char * const pbs1_groups[] = {
+ "gpio77",
+};
+static const char * const pwr_modem_enabled_b_groups[] = {
+ "gpio77",
+};
+static const char * const pbs2_groups[] = {
+ "gpio78",
+};
+static const char * const pwr_nav_enabled_b_groups[] = {
+ "gpio78",
+};
+static const char * const pwr_crypto_enabled_b_groups[] = {
+ "gpio79",
+};
+
+static const struct msm_function mdm9607_functions[] = {
+ FUNCTION(adsp_ext),
+ FUNCTION(atest_bbrx0),
+ FUNCTION(atest_bbrx1),
+ FUNCTION(atest_char),
+ FUNCTION(atest_char0),
+ FUNCTION(atest_char1),
+ FUNCTION(atest_char2),
+ FUNCTION(atest_char3),
+ FUNCTION(atest_combodac_to_gpio_native),
+ FUNCTION(atest_gpsadc_dtest0_native),
+ FUNCTION(atest_gpsadc_dtest1_native),
+ FUNCTION(atest_tsens),
+ FUNCTION(backlight_en_b),
+ FUNCTION(bimc_dte0),
+ FUNCTION(bimc_dte1),
+ FUNCTION(blsp1_spi),
+ FUNCTION(blsp2_spi),
+ FUNCTION(blsp3_spi),
+ FUNCTION(blsp_i2c1),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(blsp_i2c3),
+ FUNCTION(blsp_i2c4),
+ FUNCTION(blsp_i2c5),
+ FUNCTION(blsp_i2c6),
+ FUNCTION(blsp_spi1),
+ FUNCTION(blsp_spi2),
+ FUNCTION(blsp_spi3),
+ FUNCTION(blsp_spi4),
+ FUNCTION(blsp_spi5),
+ FUNCTION(blsp_spi6),
+ FUNCTION(blsp_uart1),
+ FUNCTION(blsp_uart2),
+ FUNCTION(blsp_uart3),
+ FUNCTION(blsp_uart4),
+ FUNCTION(blsp_uart5),
+ FUNCTION(blsp_uart6),
+ FUNCTION(blsp_uim1),
+ FUNCTION(blsp_uim2),
+ FUNCTION(codec_int),
+ FUNCTION(codec_rst),
+ FUNCTION(coex_uart),
+ FUNCTION(cri_trng),
+ FUNCTION(cri_trng0),
+ FUNCTION(cri_trng1),
+ FUNCTION(dbg_out),
+ FUNCTION(ebi0_wrcdc),
+ FUNCTION(ebi2_a),
+ FUNCTION(ebi2_a_d_8_b),
+ FUNCTION(ebi2_lcd),
+ FUNCTION(ebi2_lcd_cs_n_b),
+ FUNCTION(ebi2_lcd_te_b),
+ FUNCTION(eth_irq),
+ FUNCTION(eth_rst),
+ FUNCTION(gcc_gp1_clk_a),
+ FUNCTION(gcc_gp1_clk_b),
+ FUNCTION(gcc_gp2_clk_a),
+ FUNCTION(gcc_gp2_clk_b),
+ FUNCTION(gcc_gp3_clk_a),
+ FUNCTION(gcc_gp3_clk_b),
+ FUNCTION(gcc_plltest),
+ FUNCTION(gcc_tlmm),
+ FUNCTION(gmac_mdio),
+ FUNCTION(gpio),
+ FUNCTION(gsm0_tx),
+ FUNCTION(lcd_rst),
+ FUNCTION(ldo_en),
+ FUNCTION(ldo_update),
+ FUNCTION(m_voc),
+ FUNCTION(modem_tsync),
+ FUNCTION(nav_ptp_pps_in_a),
+ FUNCTION(nav_ptp_pps_in_b),
+ FUNCTION(nav_tsync_out_a),
+ FUNCTION(nav_tsync_out_b),
+ FUNCTION(pa_indicator),
+ FUNCTION(pbs0),
+ FUNCTION(pbs1),
+ FUNCTION(pbs2),
+ FUNCTION(pri_mi2s_data0_a),
+ FUNCTION(pri_mi2s_data1_a),
+ FUNCTION(pri_mi2s_mclk_a),
+ FUNCTION(pri_mi2s_sck_a),
+ FUNCTION(pri_mi2s_ws_a),
+ FUNCTION(prng_rosc),
+ FUNCTION(ptp_pps_out_a),
+ FUNCTION(ptp_pps_out_b),
+ FUNCTION(pwr_crypto_enabled_a),
+ FUNCTION(pwr_crypto_enabled_b),
+ FUNCTION(pwr_modem_enabled_a),
+ FUNCTION(pwr_modem_enabled_b),
+ FUNCTION(pwr_nav_enabled_a),
+ FUNCTION(pwr_nav_enabled_b),
+ FUNCTION(qdss_cti_trig_in_a0),
+ FUNCTION(qdss_cti_trig_in_a1),
+ FUNCTION(qdss_cti_trig_in_b0),
+ FUNCTION(qdss_cti_trig_in_b1),
+ FUNCTION(qdss_cti_trig_out_a0),
+ FUNCTION(qdss_cti_trig_out_a1),
+ FUNCTION(qdss_cti_trig_out_b0),
+ FUNCTION(qdss_cti_trig_out_b1),
+ FUNCTION(qdss_traceclk_a),
+ FUNCTION(qdss_traceclk_b),
+ FUNCTION(qdss_tracectl_a),
+ FUNCTION(qdss_tracectl_b),
+ FUNCTION(qdss_tracedata_a),
+ FUNCTION(qdss_tracedata_b),
+ FUNCTION(rcm_marker1),
+ FUNCTION(rcm_marker2),
+ FUNCTION(sd_write),
+ FUNCTION(sec_mi2s),
+ FUNCTION(sensor_en),
+ FUNCTION(sensor_int2),
+ FUNCTION(sensor_int3),
+ FUNCTION(sensor_rst),
+ FUNCTION(ssbi1),
+ FUNCTION(ssbi2),
+ FUNCTION(touch_rst),
+ FUNCTION(ts_int),
+ FUNCTION(uim1_clk),
+ FUNCTION(uim1_data),
+ FUNCTION(uim1_present),
+ FUNCTION(uim1_reset),
+ FUNCTION(uim2_clk),
+ FUNCTION(uim2_data),
+ FUNCTION(uim2_present),
+ FUNCTION(uim2_reset),
+ FUNCTION(uim_batt),
+ FUNCTION(wlan_en1)
+};
+
+static const struct msm_pingroup mdm9607_groups[] = {
+ PINGROUP(0, blsp_uart3, blsp_spi3, _, _, _, _, _, qdss_tracedata_a, _),
+ PINGROUP(1, blsp_uart3, blsp_spi3, _, _, _, _, _, qdss_tracedata_a, bimc_dte1),
+ PINGROUP(2, blsp_uart3, blsp_i2c3, blsp_spi3, _, _, _, _, _, qdss_traceclk_a),
+ PINGROUP(3, blsp_uart3, blsp_i2c3, blsp_spi3, _, _, _, _, _, _),
+ PINGROUP(4, blsp_spi2, blsp_uart2, blsp_uim2, _, _, _, _, qdss_tracedata_a, _),
+ PINGROUP(5, blsp_spi2, blsp_uart2, blsp_uim2, _, _, _, _, qdss_tracedata_a, _),
+ PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, _, _, _, _, _, _),
+ PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, _, _, _, _, _, _),
+ PINGROUP(8, blsp_spi5, blsp_uart5, ebi2_lcd, m_voc, _, _, _, _, _),
+ PINGROUP(9, blsp_spi5, blsp_uart5, _, _, _, _, _, _, _),
+ PINGROUP(10, blsp_spi5, blsp_i2c5, blsp_uart5, ebi2_a, _, _, qdss_tracedata_b, _, _),
+ PINGROUP(11, blsp_spi5, blsp_i2c5, blsp_uart5, blsp2_spi, ebi2_lcd, _, _, _, _),
+ PINGROUP(12, blsp_spi1, blsp_uart1, blsp_uim1, blsp3_spi, gcc_gp2_clk_b, _, _, _, _),
+ PINGROUP(13, blsp_spi1, blsp_uart1, blsp_uim1, blsp2_spi, gcc_gp3_clk_b, _, _, _, _),
+ PINGROUP(14, blsp_spi1, blsp_uart1, blsp_i2c1, gcc_gp1_clk_b, _, _, _, _, _),
+ PINGROUP(15, blsp_spi1, blsp_uart1, blsp_i2c1, _, _, _, _, _, _),
+ PINGROUP(16, blsp_spi4, blsp_uart4, _, _, _, _, _, _, _),
+ PINGROUP(17, blsp_spi4, blsp_uart4, _, _, _, _, _, _, _),
+ PINGROUP(18, blsp_spi4, blsp_uart4, blsp_i2c4, _, _, _, _, _, _),
+ PINGROUP(19, blsp_spi4, blsp_uart4, blsp_i2c4, _, _, _, _, _, _),
+ PINGROUP(20, blsp_spi6, blsp_uart6, pri_mi2s_ws_a, ebi2_lcd_te_b, blsp1_spi, _, _, _,
+ qdss_tracedata_a),
+ PINGROUP(21, blsp_spi6, blsp_uart6, pri_mi2s_data0_a, blsp1_spi, _, _, _, _, _),
+ PINGROUP(22, blsp_spi6, blsp_uart6, pri_mi2s_data1_a, blsp_i2c6, ebi2_a_d_8_b, _, _, _, _),
+ PINGROUP(23, blsp_spi6, blsp_uart6, pri_mi2s_sck_a, blsp_i2c6, ebi2_lcd_cs_n_b, _, _, _, _),
+ PINGROUP(24, pri_mi2s_mclk_a, _, pwr_nav_enabled_a, _, _, _, _, qdss_tracedata_a,
+ bimc_dte1),
+ PINGROUP(25, sd_write, _, pwr_crypto_enabled_a, _, _, _, _, qdss_tracedata_a, _),
+ PINGROUP(26, blsp3_spi, adsp_ext, _, qdss_tracedata_a, _, atest_combodac_to_gpio_native, _,
+ _, _),
+ PINGROUP(27, uim2_data, gmac_mdio, gcc_gp1_clk_a, _, _, atest_combodac_to_gpio_native, _, _,
+ _),
+ PINGROUP(28, uim2_clk, gmac_mdio, gcc_gp2_clk_a, _, _, atest_combodac_to_gpio_native, _, _,
+ _),
+ PINGROUP(29, uim2_reset, gcc_gp3_clk_a, _, _, atest_combodac_to_gpio_native, _, _, _, _),
+ PINGROUP(30, uim2_present, prng_rosc, _, _, atest_combodac_to_gpio_native, _, _, _, _),
+ PINGROUP(31, uim1_data, _, _, atest_combodac_to_gpio_native, _, _, _, _, _),
+ PINGROUP(32, uim1_clk, _, _, atest_combodac_to_gpio_native, _, _, _, _, _),
+ PINGROUP(33, uim1_reset, _, _, atest_combodac_to_gpio_native, _, _, _, _, _),
+ PINGROUP(34, uim1_present, gcc_plltest, _, _, atest_combodac_to_gpio_native, _, _, _, _),
+ PINGROUP(35, uim_batt, gcc_plltest, _, atest_combodac_to_gpio_native, _, _, _, _, _),
+ PINGROUP(36, coex_uart, _, _, _, _, _, _, _, _),
+ PINGROUP(37, coex_uart, _, _, _, _, _, _, _, _),
+ PINGROUP(38, _, _, _, qdss_cti_trig_in_a0, _, _, _, _, _),
+ PINGROUP(39, _, _, _, qdss_tracedata_b, _, atest_bbrx1, _, _, _),
+ PINGROUP(40, _, cri_trng0, _, _, _, _, qdss_tracedata_b, _, atest_bbrx0),
+ PINGROUP(41, _, _, _, _, _, qdss_tracedata_b, _, atest_combodac_to_gpio_native, _),
+ PINGROUP(42, _, cri_trng, _, _, qdss_tracedata_b, _, _, _, _),
+ PINGROUP(43, _, _, _, _, qdss_tracedata_b, _, _, _, _),
+ PINGROUP(44, _, _, qdss_cti_trig_in_b0, _, atest_gpsadc_dtest0_native, _, _, _, _),
+ PINGROUP(45, _, _, qdss_cti_trig_out_b0, _, atest_combodac_to_gpio_native, _, _, _, _),
+ PINGROUP(46, _, _, qdss_tracedata_b, _, _, _, _, _, _),
+ PINGROUP(47, _, _, qdss_tracedata_b, _, _, _, _, _, _),
+ PINGROUP(48, _, _, qdss_tracedata_b, _, _, _, _, _, _),
+ PINGROUP(49, _, _, qdss_tracectl_b, _, atest_combodac_to_gpio_native, _, _, _, _),
+ PINGROUP(50, _, _, qdss_traceclk_b, _, atest_combodac_to_gpio_native, _, _, _, _),
+ PINGROUP(51, _, pa_indicator, _, qdss_tracedata_b, _, atest_combodac_to_gpio_native, _, _,
+ _),
+ PINGROUP(52, _, _, _, qdss_tracedata_b, _, atest_combodac_to_gpio_native, _, _, _),
+ PINGROUP(53, _, modem_tsync, nav_tsync_out_a, nav_ptp_pps_in_a, ptp_pps_out_a,
+ qdss_tracedata_b, _, _, _),
+ PINGROUP(54, _, qdss_tracedata_b, _, atest_combodac_to_gpio_native, _, _, _, _, _),
+ PINGROUP(55, gsm0_tx, _, qdss_tracedata_b, _, atest_combodac_to_gpio_native, _, _, _, _),
+ PINGROUP(56, _, _, qdss_cti_trig_in_b1, _, _, _, _, _, _),
+ PINGROUP(57, _, cri_trng1, _, qdss_cti_trig_out_b1, _, atest_combodac_to_gpio_native, _, _,
+ _),
+ PINGROUP(58, _, ssbi1, _, qdss_tracedata_b, _, atest_gpsadc_dtest1_native, _, _, _),
+ PINGROUP(59, _, ssbi2, _, qdss_tracedata_b, _, atest_combodac_to_gpio_native, _, _, _),
+ PINGROUP(60, atest_char3, _, _, _, _, _, _, _, _),
+ PINGROUP(61, atest_char2, _, _, _, _, _, _, _, _),
+ PINGROUP(62, atest_char1, _, _, _, _, _, _, _, _),
+ PINGROUP(63, atest_char0, _, _, _, _, _, _, _, _),
+ PINGROUP(64, atest_char, _, _, _, _, _, _, _, _),
+ PINGROUP(65, _, _, _, _, _, _, _, _, _),
+ PINGROUP(66, _, _, _, _, _, _, _, _, _),
+ PINGROUP(67, _, _, _, _, _, _, _, _, _),
+ PINGROUP(68, _, _, _, _, _, _, _, _, _),
+ PINGROUP(69, _, _, _, _, _, _, _, _, _),
+ PINGROUP(70, _, _, ebi0_wrcdc, _, _, _, _, _, _),
+ PINGROUP(71, _, _, _, _, _, _, _, _, _),
+ PINGROUP(72, ldo_update, _, gcc_tlmm, _, _, _, _, _, _),
+ PINGROUP(73, ldo_en, dbg_out, _, _, _, atest_tsens, _, _, _),
+ PINGROUP(74, ebi2_lcd, _, _, _, _, _, _, _, _),
+ PINGROUP(75, nav_tsync_out_b, nav_ptp_pps_in_b, ptp_pps_out_b, _, qdss_tracedata_a, _, _, _,
+ _),
+ PINGROUP(76, pbs0, sec_mi2s, blsp3_spi, pwr_modem_enabled_a, _, qdss_tracedata_a, _, _, _),
+ PINGROUP(77, pbs1, sec_mi2s, blsp2_spi, pwr_modem_enabled_b, _, qdss_tracedata_a, _, _, _),
+ PINGROUP(78, pbs2, sec_mi2s, blsp1_spi, ebi2_lcd, m_voc, pwr_nav_enabled_b, _,
+ qdss_tracedata_a, _),
+ PINGROUP(79, sec_mi2s, _, pwr_crypto_enabled_b, _, qdss_tracedata_a, _, _, _, _),
+ SDC_PINGROUP(sdc1_clk, 0x10a000, 13, 6),
+ SDC_PINGROUP(sdc1_cmd, 0x10a000, 11, 3),
+ SDC_PINGROUP(sdc1_data, 0x10a000, 9, 0),
+ SDC_PINGROUP(sdc2_clk, 0x109000, 14, 6),
+ SDC_PINGROUP(sdc2_cmd, 0x109000, 11, 3),
+ SDC_PINGROUP(sdc2_data, 0x109000, 9, 0),
+ SDC_PINGROUP(qdsd_clk, 0x19c000, 3, 0),
+ SDC_PINGROUP(qdsd_cmd, 0x19c000, 8, 5),
+ SDC_PINGROUP(qdsd_data0, 0x19c000, 13, 10),
+ SDC_PINGROUP(qdsd_data1, 0x19c000, 18, 15),
+ SDC_PINGROUP(qdsd_data2, 0x19c000, 23, 20),
+ SDC_PINGROUP(qdsd_data3, 0x19c000, 28, 25),
+};
+
+static const struct msm_pinctrl_soc_data mdm9607_pinctrl = {
+ .pins = mdm9607_pins,
+ .npins = ARRAY_SIZE(mdm9607_pins),
+ .functions = mdm9607_functions,
+ .nfunctions = ARRAY_SIZE(mdm9607_functions),
+ .groups = mdm9607_groups,
+ .ngroups = ARRAY_SIZE(mdm9607_groups),
+ .ngpios = 80,
+};
+
+static int mdm9607_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &mdm9607_pinctrl);
+}
+
+static const struct of_device_id mdm9607_pinctrl_of_match[] = {
+ { .compatible = "qcom,mdm9607-tlmm", },
+ { }
+};
+
+static struct platform_driver mdm9607_pinctrl_driver = {
+ .driver = {
+ .name = "mdm9607-pinctrl",
+ .of_match_table = mdm9607_pinctrl_of_match,
+ },
+ .probe = mdm9607_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init mdm9607_pinctrl_init(void)
+{
+ return platform_driver_register(&mdm9607_pinctrl_driver);
+}
+arch_initcall(mdm9607_pinctrl_init);
+
+static void __exit mdm9607_pinctrl_exit(void)
+{
+ platform_driver_unregister(&mdm9607_pinctrl_driver);
+}
+module_exit(mdm9607_pinctrl_exit);
+
+MODULE_DESCRIPTION("Qualcomm mdm9607 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, mdm9607_pinctrl_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115.c b/drivers/pinctrl/qcom/pinctrl-sm6115.c
new file mode 100644
index 000000000000..b3a0161ca377
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-sm6115.c
@@ -0,0 +1,923 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+static const char * const sm6115_tiles[] = {
+ "south",
+ "east",
+ "west"
+};
+
+enum {
+ SOUTH,
+ EAST,
+ WEST
+};
+
+#define FUNCTION(fname) \
+ [msm_mux_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = 0x1000 * id, \
+ .io_reg = 0x4 + 0x1000 * id, \
+ .intr_cfg_reg = 0x8 + 0x1000 * id, \
+ .intr_status_reg = 0xc + 0x1000 * id, \
+ .intr_target_reg = 0x8 + 0x1000 * id, \
+ .tile = _tile, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .tile = _tile, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+#define UFS_RESET(pg_name, offset) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = offset, \
+ .io_reg = offset + 0x4, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .tile = WEST, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+static const struct pinctrl_pin_desc sm6115_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "UFS_RESET"),
+ PINCTRL_PIN(114, "SDC1_RCLK"),
+ PINCTRL_PIN(115, "SDC1_CLK"),
+ PINCTRL_PIN(116, "SDC1_CMD"),
+ PINCTRL_PIN(117, "SDC1_DATA"),
+ PINCTRL_PIN(118, "SDC2_CLK"),
+ PINCTRL_PIN(119, "SDC2_CMD"),
+ PINCTRL_PIN(120, "SDC2_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+
+static const unsigned int ufs_reset_pins[] = { 113 };
+static const unsigned int sdc1_rclk_pins[] = { 114 };
+static const unsigned int sdc1_clk_pins[] = { 115 };
+static const unsigned int sdc1_cmd_pins[] = { 116 };
+static const unsigned int sdc1_data_pins[] = { 117 };
+static const unsigned int sdc2_clk_pins[] = { 118 };
+static const unsigned int sdc2_cmd_pins[] = { 119 };
+static const unsigned int sdc2_data_pins[] = { 120 };
+
+enum sm6115_functions {
+ msm_mux_adsp_ext,
+ msm_mux_agera_pll,
+ msm_mux_atest,
+ msm_mux_cam_mclk,
+ msm_mux_cci_async,
+ msm_mux_cci_i2c,
+ msm_mux_cci_timer,
+ msm_mux_cri_trng,
+ msm_mux_dac_calib,
+ msm_mux_dbg_out,
+ msm_mux_ddr_bist,
+ msm_mux_ddr_pxi0,
+ msm_mux_ddr_pxi1,
+ msm_mux_ddr_pxi2,
+ msm_mux_ddr_pxi3,
+ msm_mux_gcc_gp1,
+ msm_mux_gcc_gp2,
+ msm_mux_gcc_gp3,
+ msm_mux_gpio,
+ msm_mux_gp_pdm0,
+ msm_mux_gp_pdm1,
+ msm_mux_gp_pdm2,
+ msm_mux_gsm0_tx,
+ msm_mux_gsm1_tx,
+ msm_mux_jitter_bist,
+ msm_mux_mdp_vsync,
+ msm_mux_mdp_vsync_out_0,
+ msm_mux_mdp_vsync_out_1,
+ msm_mux_mpm_pwr,
+ msm_mux_mss_lte,
+ msm_mux_m_voc,
+ msm_mux_nav_gpio,
+ msm_mux_pa_indicator,
+ msm_mux_pbs,
+ msm_mux_pbs_out,
+ msm_mux_phase_flag,
+ msm_mux_pll_bist,
+ msm_mux_pll_bypassnl,
+ msm_mux_pll_reset,
+ msm_mux_prng_rosc,
+ msm_mux_qdss_cti,
+ msm_mux_qdss_gpio,
+ msm_mux_qup0,
+ msm_mux_qup1,
+ msm_mux_qup2,
+ msm_mux_qup3,
+ msm_mux_qup4,
+ msm_mux_qup5,
+ msm_mux_sdc1_tb,
+ msm_mux_sdc2_tb,
+ msm_mux_sd_write,
+ msm_mux_ssbi_wtr1,
+ msm_mux_tgu,
+ msm_mux_tsense_pwm,
+ msm_mux_uim1_clk,
+ msm_mux_uim1_data,
+ msm_mux_uim1_present,
+ msm_mux_uim1_reset,
+ msm_mux_uim2_clk,
+ msm_mux_uim2_data,
+ msm_mux_uim2_present,
+ msm_mux_uim2_reset,
+ msm_mux_usb_phy,
+ msm_mux_vfr_1,
+ msm_mux_vsense_trigger,
+ msm_mux_wlan1_adc0,
+ msm_mux_wlan1_adc1,
+ msm_mux__,
+};
+
+static const char * const qup0_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio82", "gpio86",
+};
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112",
+};
+static const char * const ddr_bist_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const phase_flag_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6",
+ "gpio14", "gpio15", "gpio16", "gpio17", "gpio22", "gpio23", "gpio24",
+ "gpio25", "gpio26", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33",
+ "gpio35", "gpio36", "gpio43", "gpio44", "gpio45", "gpio63", "gpio64",
+ "gpio102", "gpio103", "gpio104", "gpio105",
+};
+static const char * const qdss_gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio8", "gpio9", "gpio10",
+ "gpio11", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19",
+ "gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26",
+ "gpio47", "gpio48", "gpio69", "gpio70", "gpio87", "gpio90", "gpio91",
+ "gpio94", "gpio95", "gpio104", "gpio105", "gpio106", "gpio107",
+ "gpio109", "gpio110",
+};
+static const char * const atest_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio29", "gpio30",
+ "gpio31", "gpio32", "gpio33", "gpio86", "gpio87", "gpio88", "gpio89",
+ "gpio100", "gpio101",
+};
+static const char * const mpm_pwr_groups[] = {
+ "gpio1",
+};
+static const char * const m_voc_groups[] = {
+ "gpio0",
+};
+static const char * const dac_calib_groups[] = {
+ "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio14", "gpio15",
+ "gpio16", "gpio17", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio80", "gpio81",
+ "gpio82", "gpio102", "gpio103", "gpio104", "gpio105"
+};
+static const char * const qup1_groups[] = {
+ "gpio4", "gpio5", "gpio69", "gpio70",
+};
+static const char * const cri_trng_groups[] = {
+ "gpio4", "gpio5", "gpio18",
+};
+static const char * const qup2_groups[] = {
+ "gpio6", "gpio7", "gpio71", "gpio80",
+};
+static const char * const qup3_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const pbs_out_groups[] = {
+ "gpio8", "gpio9", "gpio52",
+};
+static const char * const pll_bist_groups[] = {
+ "gpio8", "gpio9",
+};
+static const char * const tsense_pwm_groups[] = {
+ "gpio8",
+};
+static const char * const agera_pll_groups[] = {
+ "gpio10", "gpio11",
+};
+static const char * const pbs_groups[] = {
+ "gpio10", "gpio11", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22",
+ "gpio23", "gpio24", "gpio25", "gpio26", "gpio47", "gpio48", "gpio87",
+ "gpio90", "gpio91",
+};
+static const char * const qup4_groups[] = {
+ "gpio12", "gpio13", "gpio96", "gpio97",
+};
+static const char * const tgu_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const qup5_groups[] = {
+ "gpio14", "gpio15", "gpio16", "gpio17",
+};
+static const char * const sdc2_tb_groups[] = {
+ "gpio18",
+};
+static const char * const sdc1_tb_groups[] = {
+ "gpio19",
+};
+static const char * const cam_mclk_groups[] = {
+ "gpio20", "gpio21", "gpio27", "gpio28",
+};
+static const char * const adsp_ext_groups[] = {
+ "gpio21",
+};
+static const char * const cci_i2c_groups[] = {
+ "gpio22", "gpio23", "gpio29", "gpio30",
+};
+static const char * const prng_rosc_groups[] = {
+ "gpio22", "gpio23",
+};
+static const char * const cci_timer_groups[] = {
+ "gpio24", "gpio25", "gpio28", "gpio32",
+};
+static const char * const gcc_gp1_groups[] = {
+ "gpio24", "gpio86",
+};
+static const char * const cci_async_groups[] = {
+ "gpio25",
+};
+static const char * const vsense_trigger_groups[] = {
+ "gpio26",
+};
+static const char * const qdss_cti_groups[] = {
+ "gpio27", "gpio28", "gpio72", "gpio73", "gpio96", "gpio97",
+};
+static const char * const gp_pdm0_groups[] = {
+ "gpio31", "gpio95",
+};
+static const char * const gp_pdm1_groups[] = {
+ "gpio32", "gpio96",
+};
+static const char * const gp_pdm2_groups[] = {
+ "gpio33", "gpio97",
+};
+static const char * const nav_gpio_groups[] = {
+ "gpio42", "gpio47", "gpio52", "gpio95", "gpio96", "gpio97", "gpio106",
+ "gpio107", "gpio108",
+};
+static const char * const vfr_1_groups[] = {
+ "gpio48",
+};
+static const char * const pa_indicator_groups[] = {
+ "gpio49",
+};
+static const char * const gsm1_tx_groups[] = {
+ "gpio53",
+};
+static const char * const ssbi_wtr1_groups[] = {
+ "gpio59", "gpio60",
+};
+static const char * const pll_bypassnl_groups[] = {
+ "gpio62",
+};
+static const char * const pll_reset_groups[] = {
+ "gpio63",
+};
+static const char * const ddr_pxi0_groups[] = {
+ "gpio63", "gpio64",
+};
+static const char * const gsm0_tx_groups[] = {
+ "gpio64",
+};
+static const char * const gcc_gp2_groups[] = {
+ "gpio69", "gpio107",
+};
+static const char * const ddr_pxi1_groups[] = {
+ "gpio69", "gpio70",
+};
+static const char * const gcc_gp3_groups[] = {
+ "gpio70", "gpio106",
+};
+static const char * const dbg_out_groups[] = {
+ "gpio71",
+};
+static const char * const uim2_data_groups[] = {
+ "gpio72",
+};
+static const char * const uim2_clk_groups[] = {
+ "gpio73",
+};
+static const char * const uim2_reset_groups[] = {
+ "gpio74",
+};
+static const char * const uim2_present_groups[] = {
+ "gpio75",
+};
+static const char * const uim1_data_groups[] = {
+ "gpio76",
+};
+static const char * const uim1_clk_groups[] = {
+ "gpio77",
+};
+static const char * const uim1_reset_groups[] = {
+ "gpio78",
+};
+static const char * const uim1_present_groups[] = {
+ "gpio79",
+};
+static const char * const mdp_vsync_groups[] = {
+ "gpio81", "gpio96", "gpio97",
+};
+static const char * const mdp_vsync_out_0_groups[] = {
+ "gpio81",
+};
+static const char * const mdp_vsync_out_1_groups[] = {
+ "gpio81",
+};
+static const char * const usb_phy_groups[] = {
+ "gpio89",
+};
+static const char * const mss_lte_groups[] = {
+ "gpio90", "gpio91",
+};
+static const char * const wlan1_adc0_groups[] = {
+ "gpio94",
+};
+static const char * const wlan1_adc1_groups[] = {
+ "gpio95",
+};
+static const char * const sd_write_groups[] = {
+ "gpio96",
+};
+static const char * const jitter_bist_groups[] = {
+ "gpio96", "gpio97",
+};
+static const char * const ddr_pxi2_groups[] = {
+ "gpio102", "gpio103",
+};
+static const char * const ddr_pxi3_groups[] = {
+ "gpio104", "gpio105",
+};
+
+static const struct msm_function sm6115_functions[] = {
+ FUNCTION(adsp_ext),
+ FUNCTION(agera_pll),
+ FUNCTION(atest),
+ FUNCTION(cam_mclk),
+ FUNCTION(cci_async),
+ FUNCTION(cci_i2c),
+ FUNCTION(cci_timer),
+ FUNCTION(cri_trng),
+ FUNCTION(dac_calib),
+ FUNCTION(dbg_out),
+ FUNCTION(ddr_bist),
+ FUNCTION(ddr_pxi0),
+ FUNCTION(ddr_pxi1),
+ FUNCTION(ddr_pxi2),
+ FUNCTION(ddr_pxi3),
+ FUNCTION(gcc_gp1),
+ FUNCTION(gcc_gp2),
+ FUNCTION(gcc_gp3),
+ FUNCTION(gpio),
+ FUNCTION(gp_pdm0),
+ FUNCTION(gp_pdm1),
+ FUNCTION(gp_pdm2),
+ FUNCTION(gsm0_tx),
+ FUNCTION(gsm1_tx),
+ FUNCTION(jitter_bist),
+ FUNCTION(mdp_vsync),
+ FUNCTION(mdp_vsync_out_0),
+ FUNCTION(mdp_vsync_out_1),
+ FUNCTION(mpm_pwr),
+ FUNCTION(mss_lte),
+ FUNCTION(m_voc),
+ FUNCTION(nav_gpio),
+ FUNCTION(pa_indicator),
+ FUNCTION(pbs),
+ FUNCTION(pbs_out),
+ FUNCTION(phase_flag),
+ FUNCTION(pll_bist),
+ FUNCTION(pll_bypassnl),
+ FUNCTION(pll_reset),
+ FUNCTION(prng_rosc),
+ FUNCTION(qdss_cti),
+ FUNCTION(qdss_gpio),
+ FUNCTION(qup0),
+ FUNCTION(qup1),
+ FUNCTION(qup2),
+ FUNCTION(qup3),
+ FUNCTION(qup4),
+ FUNCTION(qup5),
+ FUNCTION(sdc1_tb),
+ FUNCTION(sdc2_tb),
+ FUNCTION(sd_write),
+ FUNCTION(ssbi_wtr1),
+ FUNCTION(tgu),
+ FUNCTION(tsense_pwm),
+ FUNCTION(uim1_clk),
+ FUNCTION(uim1_data),
+ FUNCTION(uim1_present),
+ FUNCTION(uim1_reset),
+ FUNCTION(uim2_clk),
+ FUNCTION(uim2_data),
+ FUNCTION(uim2_present),
+ FUNCTION(uim2_reset),
+ FUNCTION(usb_phy),
+ FUNCTION(vfr_1),
+ FUNCTION(vsense_trigger),
+ FUNCTION(wlan1_adc0),
+ FUNCTION(wlan1_adc1),
+};
+
+/* Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup sm6115_groups[] = {
+ [0] = PINGROUP(0, WEST, qup0, m_voc, ddr_bist, _, phase_flag, qdss_gpio, atest, _, _),
+ [1] = PINGROUP(1, WEST, qup0, mpm_pwr, ddr_bist, _, phase_flag, qdss_gpio, atest, _, _),
+ [2] = PINGROUP(2, WEST, qup0, ddr_bist, _, phase_flag, qdss_gpio, dac_calib, atest, _, _),
+ [3] = PINGROUP(3, WEST, qup0, ddr_bist, _, phase_flag, qdss_gpio, dac_calib, atest, _, _),
+ [4] = PINGROUP(4, WEST, qup1, cri_trng, _, phase_flag, dac_calib, atest, _, _, _),
+ [5] = PINGROUP(5, WEST, qup1, cri_trng, _, phase_flag, dac_calib, atest, _, _, _),
+ [6] = PINGROUP(6, WEST, qup2, _, phase_flag, dac_calib, atest, _, _, _, _),
+ [7] = PINGROUP(7, WEST, qup2, _, _, _, _, _, _, _, _),
+ [8] = PINGROUP(8, EAST, qup3, pbs_out, pll_bist, _, qdss_gpio, _, tsense_pwm, _, _),
+ [9] = PINGROUP(9, EAST, qup3, pbs_out, pll_bist, _, qdss_gpio, _, _, _, _),
+ [10] = PINGROUP(10, EAST, qup3, agera_pll, _, pbs, qdss_gpio, _, _, _, _),
+ [11] = PINGROUP(11, EAST, qup3, agera_pll, _, pbs, qdss_gpio, _, _, _, _),
+ [12] = PINGROUP(12, WEST, qup4, tgu, _, _, _, _, _, _, _),
+ [13] = PINGROUP(13, WEST, qup4, tgu, _, _, _, _, _, _, _),
+ [14] = PINGROUP(14, WEST, qup5, tgu, _, phase_flag, qdss_gpio, dac_calib, _, _, _),
+ [15] = PINGROUP(15, WEST, qup5, tgu, _, phase_flag, qdss_gpio, dac_calib, _, _, _),
+ [16] = PINGROUP(16, WEST, qup5, _, phase_flag, qdss_gpio, dac_calib, _, _, _, _),
+ [17] = PINGROUP(17, WEST, qup5, _, phase_flag, qdss_gpio, dac_calib, _, _, _, _),
+ [18] = PINGROUP(18, EAST, sdc2_tb, cri_trng, pbs, qdss_gpio, _, _, _, _, _),
+ [19] = PINGROUP(19, EAST, sdc1_tb, pbs, qdss_gpio, _, _, _, _, _, _),
+ [20] = PINGROUP(20, EAST, cam_mclk, pbs, qdss_gpio, _, _, _, _, _, _),
+ [21] = PINGROUP(21, EAST, cam_mclk, adsp_ext, pbs, qdss_gpio, _, _, _, _, _),
+ [22] = PINGROUP(22, EAST, cci_i2c, prng_rosc, _, pbs, phase_flag, qdss_gpio, dac_calib, atest, _),
+ [23] = PINGROUP(23, EAST, cci_i2c, prng_rosc, _, pbs, phase_flag, qdss_gpio, dac_calib, atest, _),
+ [24] = PINGROUP(24, EAST, cci_timer, gcc_gp1, _, pbs, phase_flag, qdss_gpio, dac_calib, atest, _),
+ [25] = PINGROUP(25, EAST, cci_async, cci_timer, _, pbs, phase_flag, qdss_gpio, dac_calib, atest, _),
+ [26] = PINGROUP(26, EAST, _, pbs, phase_flag, qdss_gpio, dac_calib, atest, vsense_trigger, _, _),
+ [27] = PINGROUP(27, EAST, cam_mclk, qdss_cti, _, _, _, _, _, _, _),
+ [28] = PINGROUP(28, EAST, cam_mclk, cci_timer, qdss_cti, _, _, _, _, _, _),
+ [29] = PINGROUP(29, EAST, cci_i2c, _, phase_flag, dac_calib, atest, _, _, _, _),
+ [30] = PINGROUP(30, EAST, cci_i2c, _, phase_flag, dac_calib, atest, _, _, _, _),
+ [31] = PINGROUP(31, EAST, gp_pdm0, _, phase_flag, dac_calib, atest, _, _, _, _),
+ [32] = PINGROUP(32, EAST, cci_timer, gp_pdm1, _, phase_flag, dac_calib, atest, _, _, _),
+ [33] = PINGROUP(33, EAST, gp_pdm2, _, phase_flag, dac_calib, atest, _, _, _, _),
+ [34] = PINGROUP(34, EAST, _, _, _, _, _, _, _, _, _),
+ [35] = PINGROUP(35, EAST, _, phase_flag, _, _, _, _, _, _, _),
+ [36] = PINGROUP(36, EAST, _, phase_flag, _, _, _, _, _, _, _),
+ [37] = PINGROUP(37, EAST, _, _, _, _, _, _, _, _, _),
+ [38] = PINGROUP(38, EAST, _, _, _, _, _, _, _, _, _),
+ [39] = PINGROUP(39, EAST, _, _, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, EAST, _, _, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, EAST, _, _, _, _, _, _, _, _, _),
+ [42] = PINGROUP(42, EAST, _, nav_gpio, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, EAST, _, _, phase_flag, _, _, _, _, _, _),
+ [44] = PINGROUP(44, EAST, _, _, phase_flag, _, _, _, _, _, _),
+ [45] = PINGROUP(45, EAST, _, _, phase_flag, _, _, _, _, _, _),
+ [46] = PINGROUP(46, EAST, _, _, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, EAST, _, nav_gpio, pbs, qdss_gpio, _, _, _, _, _),
+ [48] = PINGROUP(48, EAST, _, vfr_1, _, pbs, qdss_gpio, _, _, _, _),
+ [49] = PINGROUP(49, EAST, _, pa_indicator, _, _, _, _, _, _, _),
+ [50] = PINGROUP(50, EAST, _, _, _, _, _, _, _, _, _),
+ [51] = PINGROUP(51, EAST, _, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, EAST, _, nav_gpio, pbs_out, _, _, _, _, _, _),
+ [53] = PINGROUP(53, EAST, _, gsm1_tx, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, EAST, _, _, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, EAST, _, _, _, _, _, _, _, _, _),
+ [56] = PINGROUP(56, EAST, _, _, _, _, _, _, _, _, _),
+ [57] = PINGROUP(57, EAST, _, _, _, _, _, _, _, _, _),
+ [58] = PINGROUP(58, EAST, _, _, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, EAST, _, ssbi_wtr1, _, _, _, _, _, _, _),
+ [60] = PINGROUP(60, EAST, _, ssbi_wtr1, _, _, _, _, _, _, _),
+ [61] = PINGROUP(61, EAST, _, _, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, EAST, _, pll_bypassnl, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, EAST, pll_reset, _, phase_flag, ddr_pxi0, _, _, _, _, _),
+ [64] = PINGROUP(64, EAST, gsm0_tx, _, phase_flag, ddr_pxi0, _, _, _, _, _),
+ [65] = PINGROUP(65, WEST, _, _, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, WEST, _, _, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, WEST, _, _, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, WEST, _, _, _, _, _, _, _, _, _),
+ [69] = PINGROUP(69, WEST, qup1, gcc_gp2, qdss_gpio, ddr_pxi1, _, _, _, _, _),
+ [70] = PINGROUP(70, WEST, qup1, gcc_gp3, qdss_gpio, ddr_pxi1, _, _, _, _, _),
+ [71] = PINGROUP(71, WEST, qup2, dbg_out, _, _, _, _, _, _, _),
+ [72] = PINGROUP(72, SOUTH, uim2_data, qdss_cti, _, _, _, _, _, _, _),
+ [73] = PINGROUP(73, SOUTH, uim2_clk, _, qdss_cti, _, _, _, _, _, _),
+ [74] = PINGROUP(74, SOUTH, uim2_reset, _, _, _, _, _, _, _, _),
+ [75] = PINGROUP(75, SOUTH, uim2_present, _, _, _, _, _, _, _, _),
+ [76] = PINGROUP(76, SOUTH, uim1_data, _, _, _, _, _, _, _, _),
+ [77] = PINGROUP(77, SOUTH, uim1_clk, _, _, _, _, _, _, _, _),
+ [78] = PINGROUP(78, SOUTH, uim1_reset, _, _, _, _, _, _, _, _),
+ [79] = PINGROUP(79, SOUTH, uim1_present, _, _, _, _, _, _, _, _),
+ [80] = PINGROUP(80, WEST, qup2, dac_calib, _, _, _, _, _, _, _),
+ [81] = PINGROUP(81, WEST, mdp_vsync_out_0, mdp_vsync_out_1, mdp_vsync, dac_calib, _, _, _, _, _),
+ [82] = PINGROUP(82, WEST, qup0, dac_calib, _, _, _, _, _, _, _),
+ [83] = PINGROUP(83, WEST, _, _, _, _, _, _, _, _, _),
+ [84] = PINGROUP(84, WEST, _, _, _, _, _, _, _, _, _),
+ [85] = PINGROUP(85, WEST, _, _, _, _, _, _, _, _, _),
+ [86] = PINGROUP(86, WEST, qup0, gcc_gp1, atest, _, _, _, _, _, _),
+ [87] = PINGROUP(87, EAST, pbs, qdss_gpio, _, _, _, _, _, _, _),
+ [88] = PINGROUP(88, EAST, _, _, _, _, _, _, _, _, _),
+ [89] = PINGROUP(89, WEST, usb_phy, atest, _, _, _, _, _, _, _),
+ [90] = PINGROUP(90, EAST, mss_lte, pbs, qdss_gpio, _, _, _, _, _, _),
+ [91] = PINGROUP(91, EAST, mss_lte, pbs, qdss_gpio, _, _, _, _, _, _),
+ [92] = PINGROUP(92, WEST, _, _, _, _, _, _, _, _, _),
+ [93] = PINGROUP(93, WEST, _, _, _, _, _, _, _, _, _),
+ [94] = PINGROUP(94, WEST, _, qdss_gpio, wlan1_adc0, _, _, _, _, _, _),
+ [95] = PINGROUP(95, WEST, nav_gpio, gp_pdm0, qdss_gpio, wlan1_adc1, _, _, _, _, _),
+ [96] = PINGROUP(96, WEST, qup4, nav_gpio, mdp_vsync, gp_pdm1, sd_write, jitter_bist, qdss_cti, qdss_cti, _),
+ [97] = PINGROUP(97, WEST, qup4, nav_gpio, mdp_vsync, gp_pdm2, jitter_bist, qdss_cti, qdss_cti, _, _),
+ [98] = PINGROUP(98, SOUTH, _, _, _, _, _, _, _, _, _),
+ [99] = PINGROUP(99, SOUTH, _, _, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, SOUTH, atest, _, _, _, _, _, _, _, _),
+ [101] = PINGROUP(101, SOUTH, atest, _, _, _, _, _, _, _, _),
+ [102] = PINGROUP(102, SOUTH, _, phase_flag, dac_calib, ddr_pxi2, _, _, _, _, _),
+ [103] = PINGROUP(103, SOUTH, _, phase_flag, dac_calib, ddr_pxi2, _, _, _, _, _),
+ [104] = PINGROUP(104, SOUTH, _, phase_flag, qdss_gpio, dac_calib, ddr_pxi3, _, _, _, _),
+ [105] = PINGROUP(105, SOUTH, _, phase_flag, qdss_gpio, dac_calib, ddr_pxi3, _, _, _, _),
+ [106] = PINGROUP(106, SOUTH, nav_gpio, gcc_gp3, qdss_gpio, _, _, _, _, _, _),
+ [107] = PINGROUP(107, SOUTH, nav_gpio, gcc_gp2, qdss_gpio, _, _, _, _, _, _),
+ [108] = PINGROUP(108, SOUTH, nav_gpio, _, _, _, _, _, _, _, _),
+ [109] = PINGROUP(109, SOUTH, _, qdss_gpio, _, _, _, _, _, _, _),
+ [110] = PINGROUP(110, SOUTH, _, qdss_gpio, _, _, _, _, _, _, _),
+ [111] = PINGROUP(111, SOUTH, _, _, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, SOUTH, _, _, _, _, _, _, _, _, _),
+ [113] = UFS_RESET(ufs_reset, 0x78000),
+ [114] = SDC_QDSD_PINGROUP(sdc1_rclk, WEST, 0x75000, 15, 0),
+ [115] = SDC_QDSD_PINGROUP(sdc1_clk, WEST, 0x75000, 13, 6),
+ [116] = SDC_QDSD_PINGROUP(sdc1_cmd, WEST, 0x75000, 11, 3),
+ [117] = SDC_QDSD_PINGROUP(sdc1_data, WEST, 0x75000, 9, 0),
+ [118] = SDC_QDSD_PINGROUP(sdc2_clk, SOUTH, 0x73000, 14, 6),
+ [119] = SDC_QDSD_PINGROUP(sdc2_cmd, SOUTH, 0x73000, 11, 3),
+ [120] = SDC_QDSD_PINGROUP(sdc2_data, SOUTH, 0x73000, 9, 0),
+};
+
+static const struct msm_pinctrl_soc_data sm6115_tlmm = {
+ .pins = sm6115_pins,
+ .npins = ARRAY_SIZE(sm6115_pins),
+ .functions = sm6115_functions,
+ .nfunctions = ARRAY_SIZE(sm6115_functions),
+ .groups = sm6115_groups,
+ .ngroups = ARRAY_SIZE(sm6115_groups),
+ .ngpios = 114,
+ .tiles = sm6115_tiles,
+ .ntiles = ARRAY_SIZE(sm6115_tiles),
+};
+
+static int sm6115_tlmm_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &sm6115_tlmm);
+}
+
+static const struct of_device_id sm6115_tlmm_of_match[] = {
+ { .compatible = "qcom,sm6115-tlmm", },
+ { }
+};
+
+static struct platform_driver sm6115_tlmm_driver = {
+ .driver = {
+ .name = "sm6115-tlmm",
+ .of_match_table = sm6115_tlmm_of_match,
+ },
+ .probe = sm6115_tlmm_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init sm6115_tlmm_init(void)
+{
+ return platform_driver_register(&sm6115_tlmm_driver);
+}
+arch_initcall(sm6115_tlmm_init);
+
+static void __exit sm6115_tlmm_exit(void)
+{
+ platform_driver_unregister(&sm6115_tlmm_driver);
+}
+module_exit(sm6115_tlmm_exit);
+
+MODULE_DESCRIPTION("QTI sm6115 tlmm driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, sm6115_tlmm_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index a89d24a040af..98bf0e2a2a8d 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -1104,39 +1104,42 @@ static int pmic_gpio_remove(struct platform_device *pdev)
}
static const struct of_device_id pmic_gpio_of_match[] = {
- { .compatible = "qcom,pm8005-gpio", .data = (void *) 4 },
- { .compatible = "qcom,pm8916-gpio", .data = (void *) 4 },
- { .compatible = "qcom,pm8941-gpio", .data = (void *) 36 },
- /* pm8950 has 8 GPIOs with holes on 3 */
- { .compatible = "qcom,pm8950-gpio", .data = (void *) 8 },
- { .compatible = "qcom,pmi8950-gpio", .data = (void *) 2 },
- { .compatible = "qcom,pm8994-gpio", .data = (void *) 22 },
- { .compatible = "qcom,pmi8994-gpio", .data = (void *) 10 },
- { .compatible = "qcom,pm8998-gpio", .data = (void *) 26 },
- { .compatible = "qcom,pmi8998-gpio", .data = (void *) 14 },
- { .compatible = "qcom,pma8084-gpio", .data = (void *) 22 },
- /* pms405 has 12 GPIOs with holes on 1, 9, and 10 */
- { .compatible = "qcom,pms405-gpio", .data = (void *) 12 },
/* pm660 has 13 GPIOs with holes on 1, 5, 6, 7, 8 and 10 */
{ .compatible = "qcom,pm660-gpio", .data = (void *) 13 },
/* pm660l has 12 GPIOs with holes on 1, 2, 10, 11 and 12 */
{ .compatible = "qcom,pm660l-gpio", .data = (void *) 12 },
+ { .compatible = "qcom,pm6150-gpio", .data = (void *) 10 },
+ { .compatible = "qcom,pm6150l-gpio", .data = (void *) 12 },
+ { .compatible = "qcom,pm7325-gpio", .data = (void *) 10 },
+ { .compatible = "qcom,pm8005-gpio", .data = (void *) 4 },
+ { .compatible = "qcom,pm8008-gpio", .data = (void *) 2 },
/* pm8150 has 10 GPIOs with holes on 2, 5, 7 and 8 */
{ .compatible = "qcom,pm8150-gpio", .data = (void *) 10 },
+ { .compatible = "qcom,pmc8180-gpio", .data = (void *) 10 },
/* pm8150b has 12 GPIOs with holes on 3, r and 7 */
{ .compatible = "qcom,pm8150b-gpio", .data = (void *) 12 },
/* pm8150l has 12 GPIOs with holes on 7 */
{ .compatible = "qcom,pm8150l-gpio", .data = (void *) 12 },
+ { .compatible = "qcom,pmc8180c-gpio", .data = (void *) 12 },
{ .compatible = "qcom,pm8350-gpio", .data = (void *) 10 },
{ .compatible = "qcom,pm8350b-gpio", .data = (void *) 8 },
{ .compatible = "qcom,pm8350c-gpio", .data = (void *) 9 },
+ { .compatible = "qcom,pm8916-gpio", .data = (void *) 4 },
+ { .compatible = "qcom,pm8941-gpio", .data = (void *) 36 },
+ /* pm8950 has 8 GPIOs with holes on 3 */
+ { .compatible = "qcom,pm8950-gpio", .data = (void *) 8 },
+ { .compatible = "qcom,pm8994-gpio", .data = (void *) 22 },
+ { .compatible = "qcom,pm8998-gpio", .data = (void *) 26 },
+ { .compatible = "qcom,pma8084-gpio", .data = (void *) 22 },
+ { .compatible = "qcom,pmi8950-gpio", .data = (void *) 2 },
+ { .compatible = "qcom,pmi8994-gpio", .data = (void *) 10 },
+ { .compatible = "qcom,pmi8998-gpio", .data = (void *) 14 },
{ .compatible = "qcom,pmk8350-gpio", .data = (void *) 4 },
- { .compatible = "qcom,pm7325-gpio", .data = (void *) 10 },
+ { .compatible = "qcom,pmm8155au-gpio", .data = (void *) 10 },
{ .compatible = "qcom,pmr735a-gpio", .data = (void *) 4 },
{ .compatible = "qcom,pmr735b-gpio", .data = (void *) 4 },
- { .compatible = "qcom,pm6150-gpio", .data = (void *) 10 },
- { .compatible = "qcom,pm6150l-gpio", .data = (void *) 12 },
- { .compatible = "qcom,pm8008-gpio", .data = (void *) 2 },
+ /* pms405 has 12 GPIOs with holes on 1, 9, and 10 */
+ { .compatible = "qcom,pms405-gpio", .data = (void *) 12 },
/* pmx55 has 11 GPIOs with holes on 3, 7, 10, 11 */
{ .compatible = "qcom,pmx55-gpio", .data = (void *) 11 },
{ },
diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig
index 4b84a744ae87..9a72999084b3 100644
--- a/drivers/pinctrl/renesas/Kconfig
+++ b/drivers/pinctrl/renesas/Kconfig
@@ -37,6 +37,7 @@ config PINCTRL_RENESAS
select PINCTRL_PFC_R8A77990 if ARCH_R8A77990
select PINCTRL_PFC_R8A77995 if ARCH_R8A77995
select PINCTRL_PFC_R8A779A0 if ARCH_R8A779A0
+ select PINCTRL_RZG2L if ARCH_R9A07G044
select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203
select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264
select PINCTRL_PFC_SH7269 if CPU_SUBTYPE_SH7269
@@ -176,6 +177,16 @@ config PINCTRL_RZA2
help
This selects GPIO and pinctrl driver for Renesas RZ/A2 platforms.
+config PINCTRL_RZG2L
+ bool "pin control support for RZ/G2L" if COMPILE_TEST
+ depends on OF
+ select GPIOLIB
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GENERIC_PINCONF
+ help
+ This selects GPIO and pinctrl driver for Renesas RZ/G2L platforms.
+
config PINCTRL_PFC_R8A77470
bool "pin control support for RZ/G1C" if COMPILE_TEST
select PINCTRL_SH_PFC
diff --git a/drivers/pinctrl/renesas/Makefile b/drivers/pinctrl/renesas/Makefile
index 353563228dc2..7d9238a9ef57 100644
--- a/drivers/pinctrl/renesas/Makefile
+++ b/drivers/pinctrl/renesas/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_PINCTRL_PFC_SHX3) += pfc-shx3.o
obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o
obj-$(CONFIG_PINCTRL_RZA2) += pinctrl-rza2.o
+obj-$(CONFIG_PINCTRL_RZG2L) += pinctrl-rzg2l.o
obj-$(CONFIG_PINCTRL_RZN1) += pinctrl-rzn1.o
ifeq ($(CONFIG_COMPILE_TEST),y)
diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c
index 5ccc49b387f1..f2ab02225837 100644
--- a/drivers/pinctrl/renesas/core.c
+++ b/drivers/pinctrl/renesas/core.c
@@ -571,17 +571,21 @@ static const struct of_device_id sh_pfc_of_table[] = {
.data = &r8a7794_pinmux_info,
},
#endif
-/* Both r8a7795 entries must be present to make sanity checks work */
-#ifdef CONFIG_PINCTRL_PFC_R8A77950
+/*
+ * Both r8a7795 entries must be present to make sanity checks work, but only
+ * the first entry is actually used.
+ * R-Car H3 ES1.x is matched using soc_device_match() instead.
+ */
+#ifdef CONFIG_PINCTRL_PFC_R8A77951
{
.compatible = "renesas,pfc-r8a7795",
- .data = &r8a77950_pinmux_info,
+ .data = &r8a77951_pinmux_info,
},
#endif
-#ifdef CONFIG_PINCTRL_PFC_R8A77951
+#ifdef CONFIG_PINCTRL_PFC_R8A77950
{
.compatible = "renesas,pfc-r8a7795",
- .data = &r8a77951_pinmux_info,
+ .data = &r8a77950_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A77960
@@ -1085,26 +1089,20 @@ static inline void sh_pfc_check_driver(struct platform_driver *pdrv) {}
#ifdef CONFIG_OF
static const void *sh_pfc_quirk_match(void)
{
-#if defined(CONFIG_PINCTRL_PFC_R8A77950) || \
- defined(CONFIG_PINCTRL_PFC_R8A77951)
+#ifdef CONFIG_PINCTRL_PFC_R8A77950
const struct soc_device_attribute *match;
static const struct soc_device_attribute quirks[] = {
{
.soc_id = "r8a7795", .revision = "ES1.*",
.data = &r8a77950_pinmux_info,
},
- {
- .soc_id = "r8a7795",
- .data = &r8a77951_pinmux_info,
- },
-
{ /* sentinel */ }
};
match = soc_device_match(quirks);
if (match)
- return match->data ?: ERR_PTR(-ENODEV);
-#endif /* CONFIG_PINCTRL_PFC_R8A77950 || CONFIG_PINCTRL_PFC_R8A77951 */
+ return match->data;
+#endif /* CONFIG_PINCTRL_PFC_R8A77950 */
return NULL;
}
@@ -1119,9 +1117,6 @@ static int sh_pfc_probe(struct platform_device *pdev)
#ifdef CONFIG_OF
if (pdev->dev.of_node) {
info = sh_pfc_quirk_match();
- if (IS_ERR(info))
- return PTR_ERR(info);
-
if (!info)
info = of_device_get_match_data(&pdev->dev);
} else
diff --git a/drivers/pinctrl/renesas/pfc-r8a77995.c b/drivers/pinctrl/renesas/pfc-r8a77995.c
index b479f87a3b23..c56e1e4c13b3 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77995.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77995.c
@@ -14,16 +14,27 @@
#include <linux/errno.h>
#include <linux/kernel.h>
+#include "core.h"
#include "sh_pfc.h"
-#define CPU_ALL_GP(fn, sfx) \
- PORT_GP_9(0, fn, sfx), \
- PORT_GP_32(1, fn, sfx), \
- PORT_GP_32(2, fn, sfx), \
- PORT_GP_CFG_10(3, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
- PORT_GP_32(4, fn, sfx), \
- PORT_GP_21(5, fn, sfx), \
- PORT_GP_14(6, fn, sfx)
+#define CPU_ALL_GP(fn, sfx) \
+ PORT_GP_CFG_9(0, fn, sfx, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PORT_GP_CFG_32(1, fn, sfx, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PORT_GP_CFG_32(2, fn, sfx, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PORT_GP_CFG_10(3, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE | SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PORT_GP_CFG_32(4, fn, sfx, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PORT_GP_CFG_21(5, fn, sfx, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PORT_GP_CFG_14(6, fn, sfx, SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
+#define CPU_ALL_NOGP(fn) \
+ PIN_NOGP_CFG(DU_DOTCLKIN0, "DU_DOTCLKIN0", fn, SH_PFC_PIN_CFG_PULL_DOWN), \
+ PIN_NOGP_CFG(FSCLKST_N, "FSCLKST#", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT#", fn, SH_PFC_PIN_CFG_PULL_UP_DOWN), \
+ PIN_NOGP_CFG(TCK, "TCK", fn, SH_PFC_PIN_CFG_PULL_UP), \
+ PIN_NOGP_CFG(TDI, "TDI", fn, SH_PFC_PIN_CFG_PULL_UP), \
+ PIN_NOGP_CFG(TMS, "TMS", fn, SH_PFC_PIN_CFG_PULL_UP), \
+ PIN_NOGP_CFG(TRST_N, "TRST#", fn, SH_PFC_PIN_CFG_PULL_UP)
/*
* F_() : just information
@@ -930,8 +941,17 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_GPSR(IP13_7_4, TPU0TO3_A),
};
+/*
+ * Pins not associated with a GPIO port.
+ */
+enum {
+ GP_ASSIGN_LAST(),
+ NOGP_ALL(),
+};
+
static const struct sh_pfc_pin pinmux_pins[] = {
PINMUX_GPIO_GP_ALL(),
+ PINMUX_NOGP_ALL(),
};
/* - AUDIO CLOCK ------------------------------------------------------------- */
@@ -2834,6 +2854,214 @@ static int r8a77995_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *po
return bit;
}
+static const struct pinmux_bias_reg pinmux_bias_regs[] = {
+ { PINMUX_BIAS_REG("PUEN0", 0xe6060400, "PUD0", 0xe6060440) {
+ [ 0] = RCAR_GP_PIN(1, 9), /* DU_DG1 */
+ [ 1] = RCAR_GP_PIN(1, 8), /* DU_DG0 */
+ [ 2] = RCAR_GP_PIN(1, 7), /* DU_DB7 */
+ [ 3] = RCAR_GP_PIN(1, 6), /* DU_DB6 */
+ [ 4] = RCAR_GP_PIN(1, 5), /* DU_DB5 */
+ [ 5] = RCAR_GP_PIN(1, 4), /* DU_DB4 */
+ [ 6] = RCAR_GP_PIN(1, 3), /* DU_DB3 */
+ [ 7] = RCAR_GP_PIN(1, 2), /* DU_DB2 */
+ [ 8] = RCAR_GP_PIN(1, 1), /* DU_DB1 */
+ [ 9] = RCAR_GP_PIN(1, 0), /* DU_DB0 */
+ [10] = PIN_MLB_REF, /* MLB_REF */
+ [11] = RCAR_GP_PIN(0, 8), /* MLB_SIG */
+ [12] = RCAR_GP_PIN(0, 7), /* MLB_DAT */
+ [13] = RCAR_GP_PIN(0, 6), /* MLB_CLK */
+ [14] = RCAR_GP_PIN(0, 5), /* MSIOF2_RXD */
+ [15] = RCAR_GP_PIN(0, 4), /* MSIOF2_TXD */
+ [16] = RCAR_GP_PIN(0, 3), /* MSIOF2_SCK */
+ [17] = RCAR_GP_PIN(0, 2), /* IRQ0_A */
+ [18] = RCAR_GP_PIN(0, 1), /* USB0_OVC */
+ [19] = RCAR_GP_PIN(0, 0), /* USB0_PWEN */
+ [20] = PIN_PRESETOUT_N, /* PRESETOUT# */
+ [21] = PIN_DU_DOTCLKIN0, /* DU_DOTCLKIN0 */
+ [22] = PIN_FSCLKST_N, /* FSCLKST# */
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = PIN_TDI, /* TDI */
+ [29] = PIN_TMS, /* TMS */
+ [30] = PIN_TCK, /* TCK */
+ [31] = PIN_TRST_N, /* TRST# */
+ } },
+ { PINMUX_BIAS_REG("PUEN1", 0xe6060404, "PUD1", 0xe6060444) {
+ [ 0] = RCAR_GP_PIN(2, 9), /* VI4_DATA8 */
+ [ 1] = RCAR_GP_PIN(2, 8), /* VI4_DATA7 */
+ [ 2] = RCAR_GP_PIN(2, 7), /* VI4_DATA6 */
+ [ 3] = RCAR_GP_PIN(2, 6), /* VI4_DATA5 */
+ [ 4] = RCAR_GP_PIN(2, 5), /* VI4_DATA4 */
+ [ 5] = RCAR_GP_PIN(2, 4), /* VI4_DATA3 */
+ [ 6] = RCAR_GP_PIN(2, 3), /* VI4_DATA2 */
+ [ 7] = RCAR_GP_PIN(2, 2), /* VI4_DATA1 */
+ [ 8] = RCAR_GP_PIN(2, 1), /* VI4_DATA0 */
+ [ 9] = RCAR_GP_PIN(2, 0), /* VI4_CLK */
+ [10] = RCAR_GP_PIN(1, 31), /* QPOLB */
+ [11] = RCAR_GP_PIN(1, 30), /* QPOLA */
+ [12] = RCAR_GP_PIN(1, 29), /* DU_CDE */
+ [13] = RCAR_GP_PIN(1, 28), /* DU_DISP/CDE */
+ [14] = RCAR_GP_PIN(1, 27), /* DU_DISP */
+ [15] = RCAR_GP_PIN(1, 26), /* DU_VSYNC */
+ [16] = RCAR_GP_PIN(1, 25), /* DU_HSYNC */
+ [17] = RCAR_GP_PIN(1, 24), /* DU_DOTCLKOUT0 */
+ [18] = RCAR_GP_PIN(1, 23), /* DU_DR7 */
+ [19] = RCAR_GP_PIN(1, 22), /* DU_DR6 */
+ [20] = RCAR_GP_PIN(1, 21), /* DU_DR5 */
+ [21] = RCAR_GP_PIN(1, 20), /* DU_DR4 */
+ [22] = RCAR_GP_PIN(1, 19), /* DU_DR3 */
+ [23] = RCAR_GP_PIN(1, 18), /* DU_DR2 */
+ [24] = RCAR_GP_PIN(1, 17), /* DU_DR1 */
+ [25] = RCAR_GP_PIN(1, 16), /* DU_DR0 */
+ [26] = RCAR_GP_PIN(1, 15), /* DU_DG7 */
+ [27] = RCAR_GP_PIN(1, 14), /* DU_DG6 */
+ [28] = RCAR_GP_PIN(1, 13), /* DU_DG5 */
+ [29] = RCAR_GP_PIN(1, 12), /* DU_DG4 */
+ [30] = RCAR_GP_PIN(1, 11), /* DU_DG3 */
+ [31] = RCAR_GP_PIN(1, 10), /* DU_DG2 */
+ } },
+ { PINMUX_BIAS_REG("PUEN2", 0xe6060408, "PUD2", 0xe6060448) {
+ [ 0] = RCAR_GP_PIN(3, 8), /* NFDATA6 */
+ [ 1] = RCAR_GP_PIN(3, 7), /* NFDATA5 */
+ [ 2] = RCAR_GP_PIN(3, 6), /* NFDATA4 */
+ [ 3] = RCAR_GP_PIN(3, 5), /* NFDATA3 */
+ [ 4] = RCAR_GP_PIN(3, 4), /* NFDATA2 */
+ [ 5] = RCAR_GP_PIN(3, 3), /* NFDATA1 */
+ [ 6] = RCAR_GP_PIN(3, 2), /* NFDATA0 */
+ [ 7] = RCAR_GP_PIN(3, 1), /* NFWE# (PUEN) / NFRE# (PUD) */
+ [ 8] = RCAR_GP_PIN(3, 0), /* NFRE# (PUEN) / NFWE# (PUD) */
+ [ 9] = RCAR_GP_PIN(4, 0), /* NFRB# */
+ [10] = RCAR_GP_PIN(2, 31), /* NFCE# */
+ [11] = RCAR_GP_PIN(2, 30), /* NFCLE */
+ [12] = RCAR_GP_PIN(2, 29), /* NFALE */
+ [13] = RCAR_GP_PIN(2, 28), /* VI4_CLKENB */
+ [14] = RCAR_GP_PIN(2, 27), /* VI4_FIELD */
+ [15] = RCAR_GP_PIN(2, 26), /* VI4_HSYNC# */
+ [16] = RCAR_GP_PIN(2, 25), /* VI4_VSYNC# */
+ [17] = RCAR_GP_PIN(2, 24), /* VI4_DATA23 */
+ [18] = RCAR_GP_PIN(2, 23), /* VI4_DATA22 */
+ [19] = RCAR_GP_PIN(2, 22), /* VI4_DATA21 */
+ [20] = RCAR_GP_PIN(2, 21), /* VI4_DATA20 */
+ [21] = RCAR_GP_PIN(2, 20), /* VI4_DATA19 */
+ [22] = RCAR_GP_PIN(2, 19), /* VI4_DATA18 */
+ [23] = RCAR_GP_PIN(2, 18), /* VI4_DATA17 */
+ [24] = RCAR_GP_PIN(2, 17), /* VI4_DATA16 */
+ [25] = RCAR_GP_PIN(2, 16), /* VI4_DATA15 */
+ [26] = RCAR_GP_PIN(2, 15), /* VI4_DATA14 */
+ [27] = RCAR_GP_PIN(2, 14), /* VI4_DATA13 */
+ [28] = RCAR_GP_PIN(2, 13), /* VI4_DATA12 */
+ [29] = RCAR_GP_PIN(2, 12), /* VI4_DATA11 */
+ [30] = RCAR_GP_PIN(2, 11), /* VI4_DATA10 */
+ [31] = RCAR_GP_PIN(2, 10), /* VI4_DATA9 */
+ } },
+ { PINMUX_BIAS_REG("PUEN3", 0xe606040c, "PUD3", 0xe606044c) {
+ [ 0] = RCAR_GP_PIN(4, 31), /* CAN0_RX_A */
+ [ 1] = RCAR_GP_PIN(5, 2), /* CAN_CLK */
+ [ 2] = RCAR_GP_PIN(5, 1), /* TPU0TO1_A */
+ [ 3] = RCAR_GP_PIN(5, 0), /* TPU0TO0_A */
+ [ 4] = RCAR_GP_PIN(4, 27), /* TX2 */
+ [ 5] = RCAR_GP_PIN(4, 26), /* RX2 */
+ [ 6] = RCAR_GP_PIN(4, 25), /* SCK2 */
+ [ 7] = RCAR_GP_PIN(4, 24), /* TX1_A */
+ [ 8] = RCAR_GP_PIN(4, 23), /* RX1_A */
+ [ 9] = RCAR_GP_PIN(4, 22), /* SCK1_A */
+ [10] = RCAR_GP_PIN(4, 21), /* TX0_A */
+ [11] = RCAR_GP_PIN(4, 20), /* RX0_A */
+ [12] = RCAR_GP_PIN(4, 19), /* SCK0_A */
+ [13] = RCAR_GP_PIN(4, 18), /* MSIOF1_RXD */
+ [14] = RCAR_GP_PIN(4, 17), /* MSIOF1_TXD */
+ [15] = RCAR_GP_PIN(4, 16), /* MSIOF1_SCK */
+ [16] = RCAR_GP_PIN(4, 15), /* MSIOF0_RXD */
+ [17] = RCAR_GP_PIN(4, 14), /* MSIOF0_TXD */
+ [18] = RCAR_GP_PIN(4, 13), /* MSIOF0_SYNC */
+ [19] = RCAR_GP_PIN(4, 12), /* MSIOF0_SCK */
+ [20] = RCAR_GP_PIN(4, 11), /* SDA1 */
+ [21] = RCAR_GP_PIN(4, 10), /* SCL1 */
+ [22] = RCAR_GP_PIN(4, 9), /* SDA0 */
+ [23] = RCAR_GP_PIN(4, 8), /* SCL0 */
+ [24] = RCAR_GP_PIN(4, 7), /* SSI_WS4_A */
+ [25] = RCAR_GP_PIN(4, 6), /* SSI_SDATA4_A */
+ [26] = RCAR_GP_PIN(4, 5), /* SSI_SCK4_A */
+ [27] = RCAR_GP_PIN(4, 4), /* SSI_WS34 */
+ [28] = RCAR_GP_PIN(4, 3), /* SSI_SDATA3 */
+ [29] = RCAR_GP_PIN(4, 2), /* SSI_SCK34 */
+ [30] = RCAR_GP_PIN(4, 1), /* AUDIO_CLKA */
+ [31] = RCAR_GP_PIN(3, 9), /* NFDATA7 */
+ } },
+ { PINMUX_BIAS_REG("PUEN4", 0xe6060410, "PUD4", 0xe6060450) {
+ [ 0] = RCAR_GP_PIN(6, 10), /* QSPI1_IO3 */
+ [ 1] = RCAR_GP_PIN(6, 9), /* QSPI1_IO2 */
+ [ 2] = RCAR_GP_PIN(6, 8), /* QSPI1_MISO_IO1 */
+ [ 3] = RCAR_GP_PIN(6, 7), /* QSPI1_MOSI_IO0 */
+ [ 4] = RCAR_GP_PIN(6, 6), /* QSPI1_SPCLK */
+ [ 5] = RCAR_GP_PIN(6, 5), /* QSPI0_SSL */
+ [ 6] = RCAR_GP_PIN(6, 4), /* QSPI0_IO3 */
+ [ 7] = RCAR_GP_PIN(6, 3), /* QSPI0_IO2 */
+ [ 8] = RCAR_GP_PIN(6, 2), /* QSPI0_MISO_IO1 */
+ [ 9] = RCAR_GP_PIN(6, 1), /* QSPI0_MOSI_IO0 */
+ [10] = RCAR_GP_PIN(6, 0), /* QSPI0_SPCLK */
+ [11] = RCAR_GP_PIN(5, 20), /* AVB0_LINK */
+ [12] = RCAR_GP_PIN(5, 19), /* AVB0_PHY_INT */
+ [13] = RCAR_GP_PIN(5, 18), /* AVB0_MAGIC */
+ [14] = RCAR_GP_PIN(5, 17), /* AVB0_MDC */
+ [15] = RCAR_GP_PIN(5, 16), /* AVB0_MDIO */
+ [16] = RCAR_GP_PIN(5, 15), /* AVB0_TXCREFCLK */
+ [17] = RCAR_GP_PIN(5, 14), /* AVB0_TD3 */
+ [18] = RCAR_GP_PIN(5, 13), /* AVB0_TD2 */
+ [19] = RCAR_GP_PIN(5, 12), /* AVB0_TD1 */
+ [20] = RCAR_GP_PIN(5, 11), /* AVB0_TD0 */
+ [21] = RCAR_GP_PIN(5, 10), /* AVB0_TXC */
+ [22] = RCAR_GP_PIN(5, 9), /* AVB0_TX_CTL */
+ [23] = RCAR_GP_PIN(5, 8), /* AVB0_RD3 */
+ [24] = RCAR_GP_PIN(5, 7), /* AVB0_RD2 */
+ [25] = RCAR_GP_PIN(5, 6), /* AVB0_RD1 */
+ [26] = RCAR_GP_PIN(5, 5), /* AVB0_RD0 */
+ [27] = RCAR_GP_PIN(5, 4), /* AVB0_RXC */
+ [28] = RCAR_GP_PIN(5, 3), /* AVB0_RX_CTL */
+ [29] = RCAR_GP_PIN(4, 30), /* CAN1_TX_A */
+ [30] = RCAR_GP_PIN(4, 29), /* CAN1_RX_A */
+ [31] = RCAR_GP_PIN(4, 28), /* CAN0_TX_A */
+ } },
+ { PINMUX_BIAS_REG("PUEN5", 0xe6060414, "PUD4", 0xe6060454) {
+ [ 0] = SH_PFC_PIN_NONE,
+ [ 1] = SH_PFC_PIN_NONE,
+ [ 2] = SH_PFC_PIN_NONE,
+ [ 3] = SH_PFC_PIN_NONE,
+ [ 4] = SH_PFC_PIN_NONE,
+ [ 5] = SH_PFC_PIN_NONE,
+ [ 6] = SH_PFC_PIN_NONE,
+ [ 7] = SH_PFC_PIN_NONE,
+ [ 8] = SH_PFC_PIN_NONE,
+ [ 9] = SH_PFC_PIN_NONE,
+ [10] = SH_PFC_PIN_NONE,
+ [11] = SH_PFC_PIN_NONE,
+ [12] = SH_PFC_PIN_NONE,
+ [13] = SH_PFC_PIN_NONE,
+ [14] = SH_PFC_PIN_NONE,
+ [15] = SH_PFC_PIN_NONE,
+ [16] = SH_PFC_PIN_NONE,
+ [17] = SH_PFC_PIN_NONE,
+ [18] = SH_PFC_PIN_NONE,
+ [19] = SH_PFC_PIN_NONE,
+ [20] = SH_PFC_PIN_NONE,
+ [21] = SH_PFC_PIN_NONE,
+ [22] = SH_PFC_PIN_NONE,
+ [23] = SH_PFC_PIN_NONE,
+ [24] = SH_PFC_PIN_NONE,
+ [25] = SH_PFC_PIN_NONE,
+ [26] = SH_PFC_PIN_NONE,
+ [27] = SH_PFC_PIN_NONE,
+ [28] = SH_PFC_PIN_NONE,
+ [29] = RCAR_GP_PIN(6, 13), /* RPC_INT# */
+ [30] = RCAR_GP_PIN(6, 12), /* RPC_RESET# */
+ [31] = RCAR_GP_PIN(6, 11), /* QSPI1_SSL */
+ } },
+ { /* sentinel */ }
+};
+
enum ioctrl_regs {
TDSELCTRL,
};
@@ -2843,8 +3071,83 @@ static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = {
{ /* sentinel */ },
};
+static const struct pinmux_bias_reg *
+r8a77995_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
+ unsigned int *puen_bit, unsigned int *pud_bit)
+{
+ const struct pinmux_bias_reg *reg;
+ unsigned int bit;
+
+ reg = rcar_pin_to_bias_reg(pfc, pin, &bit);
+ if (!reg)
+ return reg;
+
+ *puen_bit = bit;
+
+ /* NFWE# and NFRE# use different bit positions in PUD2 */
+ switch (pin) {
+ case RCAR_GP_PIN(3, 0): /* NFRE# */
+ *pud_bit = 7;
+ break;
+
+ case RCAR_GP_PIN(3, 1): /* NFWE# */
+ *pud_bit = 8;
+ break;
+
+ default:
+ *pud_bit = bit;
+ break;
+ }
+
+ return reg;
+}
+
+static unsigned int r8a77995_pinmux_get_bias(struct sh_pfc *pfc,
+ unsigned int pin)
+{
+ const struct pinmux_bias_reg *reg;
+ unsigned int puen_bit, pud_bit;
+
+ reg = r8a77995_pin_to_bias_reg(pfc, pin, &puen_bit, &pud_bit);
+ if (!reg)
+ return PIN_CONFIG_BIAS_DISABLE;
+
+ if (!(sh_pfc_read(pfc, reg->puen) & BIT(puen_bit)))
+ return PIN_CONFIG_BIAS_DISABLE;
+ else if (sh_pfc_read(pfc, reg->pud) & BIT(pud_bit))
+ return PIN_CONFIG_BIAS_PULL_UP;
+ else
+ return PIN_CONFIG_BIAS_PULL_DOWN;
+}
+
+static void r8a77995_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
+ unsigned int bias)
+{
+ const struct pinmux_bias_reg *reg;
+ unsigned int puen_bit, pud_bit;
+ u32 enable, updown;
+
+ reg = r8a77995_pin_to_bias_reg(pfc, pin, &puen_bit, &pud_bit);
+ if (!reg)
+ return;
+
+ enable = sh_pfc_read(pfc, reg->puen) & ~BIT(puen_bit);
+ if (bias != PIN_CONFIG_BIAS_DISABLE) {
+ enable |= BIT(puen_bit);
+
+ updown = sh_pfc_read(pfc, reg->pud) & ~BIT(pud_bit);
+ if (bias == PIN_CONFIG_BIAS_PULL_UP)
+ updown |= BIT(pud_bit);
+
+ sh_pfc_write(pfc, reg->pud, updown);
+ }
+ sh_pfc_write(pfc, reg->puen, enable);
+}
+
static const struct sh_pfc_soc_operations r8a77995_pinmux_ops = {
.pin_to_pocctrl = r8a77995_pin_to_pocctrl,
+ .get_bias = r8a77995_pinmux_get_bias,
+ .set_bias = r8a77995_pinmux_set_bias,
};
const struct sh_pfc_soc_info r8a77995_pinmux_info = {
@@ -2862,6 +3165,7 @@ const struct sh_pfc_soc_info r8a77995_pinmux_info = {
.nr_functions = ARRAY_SIZE(pinmux_functions),
.cfg_regs = pinmux_config_regs,
+ .bias_regs = pinmux_bias_regs,
.ioctrl_regs = pinmux_ioctrl_regs,
.pinmux_data = pinmux_data,
diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
new file mode 100644
index 000000000000..dbf2f521bb27
--- /dev/null
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -0,0 +1,1175 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2L Pin Control and GPIO driver core
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/pinctrl/rzg2l-pinctrl.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+
+#define DRV_NAME "pinctrl-rzg2l"
+
+/*
+ * Use 16 lower bits [15:0] for pin identifier
+ * Use 16 higher bits [31:16] for pin mux function
+ */
+#define MUX_PIN_ID_MASK GENMASK(15, 0)
+#define MUX_FUNC_MASK GENMASK(31, 16)
+#define MUX_FUNC_OFFS 16
+#define MUX_FUNC(pinconf) (((pinconf) & MUX_FUNC_MASK) >> MUX_FUNC_OFFS)
+
+/* PIN capabilities */
+#define PIN_CFG_IOLH BIT(0)
+#define PIN_CFG_SR BIT(1)
+#define PIN_CFG_IEN BIT(2)
+#define PIN_CFG_PUPD BIT(3)
+#define PIN_CFG_IOLH_SD0 BIT(4)
+#define PIN_CFG_IOLH_SD1 BIT(5)
+#define PIN_CFG_IOLH_QSPI BIT(6)
+#define PIN_CFG_IOLH_ETH0 BIT(7)
+#define PIN_CFG_IOLH_ETH1 BIT(8)
+#define PIN_CFG_FILONOFF BIT(9)
+#define PIN_CFG_FILNUM BIT(10)
+#define PIN_CFG_FILCLKSEL BIT(11)
+
+#define RZG2L_MPXED_PIN_FUNCS (PIN_CFG_IOLH | \
+ PIN_CFG_SR | \
+ PIN_CFG_PUPD | \
+ PIN_CFG_FILONOFF | \
+ PIN_CFG_FILNUM | \
+ PIN_CFG_FILCLKSEL)
+
+#define RZG2L_MPXED_ETH_PIN_FUNCS(x) ((x) | \
+ PIN_CFG_FILONOFF | \
+ PIN_CFG_FILNUM | \
+ PIN_CFG_FILCLKSEL)
+
+/*
+ * n indicates number of pins in the port, a is the register index
+ * and f is pin configuration capabilities supported.
+ */
+#define RZG2L_GPIO_PORT_PACK(n, a, f) (((n) << 28) | ((a) << 20) | (f))
+#define RZG2L_GPIO_PORT_GET_PINCNT(x) (((x) & GENMASK(30, 28)) >> 28)
+#define RZG2L_GPIO_PORT_GET_INDEX(x) (((x) & GENMASK(26, 20)) >> 20)
+#define RZG2L_GPIO_PORT_GET_CFGS(x) ((x) & GENMASK(19, 0))
+
+/*
+ * BIT(31) indicates dedicated pin, p is the register index while
+ * referencing to SR/IEN/IOLH/FILxx registers, b is the register bits
+ * (b * 8) and f is the pin configuration capabilities supported.
+ */
+#define RZG2L_SINGLE_PIN BIT(31)
+#define RZG2L_SINGLE_PIN_PACK(p, b, f) (RZG2L_SINGLE_PIN | \
+ ((p) << 24) | ((b) << 20) | (f))
+#define RZG2L_SINGLE_PIN_GET_PORT(x) (((x) & GENMASK(30, 24)) >> 24)
+#define RZG2L_SINGLE_PIN_GET_BIT(x) (((x) & GENMASK(22, 20)) >> 20)
+#define RZG2L_SINGLE_PIN_GET_CFGS(x) ((x) & GENMASK(19, 0))
+
+#define P(n) (0x0000 + 0x10 + (n))
+#define PM(n) (0x0100 + 0x20 + (n) * 2)
+#define PMC(n) (0x0200 + 0x10 + (n))
+#define PFC(n) (0x0400 + 0x40 + (n) * 4)
+#define PIN(n) (0x0800 + 0x10 + (n))
+#define IEN(n) (0x1800 + (n) * 8)
+#define PWPR (0x3014)
+#define SD_CH(n) (0x3000 + (n) * 4)
+#define QSPI (0x3008)
+
+#define PVDD_1800 1 /* I/O domain voltage <= 1.8V */
+#define PVDD_3300 0 /* I/O domain voltage >= 3.3V */
+
+#define PWPR_B0WI BIT(7) /* Bit Write Disable */
+#define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */
+
+#define PM_MASK 0x03
+#define PVDD_MASK 0x01
+#define PFC_MASK 0x07
+#define IEN_MASK 0x01
+
+#define PM_INPUT 0x1
+#define PM_OUTPUT 0x2
+
+#define RZG2L_PIN_ID_TO_PORT(id) ((id) / RZG2L_PINS_PER_PORT)
+#define RZG2L_PIN_ID_TO_PIN(id) ((id) % RZG2L_PINS_PER_PORT)
+
+struct rzg2l_dedicated_configs {
+ const char *name;
+ u32 config;
+};
+
+struct rzg2l_pinctrl_data {
+ const char * const *port_pins;
+ const u32 *port_pin_configs;
+ struct rzg2l_dedicated_configs *dedicated_pins;
+ unsigned int n_port_pins;
+ unsigned int n_dedicated_pins;
+};
+
+struct rzg2l_pinctrl {
+ struct pinctrl_dev *pctl;
+ struct pinctrl_desc desc;
+ struct pinctrl_pin_desc *pins;
+
+ const struct rzg2l_pinctrl_data *data;
+ void __iomem *base;
+ struct device *dev;
+ struct clk *clk;
+
+ struct gpio_chip gpio_chip;
+ struct pinctrl_gpio_range gpio_range;
+
+ spinlock_t lock;
+};
+
+static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl,
+ u8 port, u8 pin, u8 func)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+
+ /* Set pin to 'Non-use (Hi-Z input protection)' */
+ reg = readw(pctrl->base + PM(port));
+ reg &= ~(PM_MASK << (pin * 2));
+ writew(reg, pctrl->base + PM(port));
+
+ /* Temporarily switch to GPIO mode with PMC register */
+ reg = readb(pctrl->base + PMC(port));
+ writeb(reg & ~BIT(pin), pctrl->base + PMC(port));
+
+ /* Set the PWPR register to allow PFC register to write */
+ writel(0x0, pctrl->base + PWPR); /* B0WI=0, PFCWE=0 */
+ writel(PWPR_PFCWE, pctrl->base + PWPR); /* B0WI=0, PFCWE=1 */
+
+ /* Select Pin function mode with PFC register */
+ reg = readl(pctrl->base + PFC(port));
+ reg &= ~(PFC_MASK << (pin * 4));
+ writel(reg | (func << (pin * 4)), pctrl->base + PFC(port));
+
+ /* Set the PWPR register to be write-protected */
+ writel(0x0, pctrl->base + PWPR); /* B0WI=0, PFCWE=0 */
+ writel(PWPR_B0WI, pctrl->base + PWPR); /* B0WI=1, PFCWE=0 */
+
+ /* Switch to Peripheral pin function with PMC register */
+ reg = readb(pctrl->base + PMC(port));
+ writeb(reg | BIT(pin), pctrl->base + PMC(port));
+
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+};
+
+static int rzg2l_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int func_selector,
+ unsigned int group_selector)
+{
+ struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct function_desc *func;
+ unsigned int i, *psel_val;
+ struct group_desc *group;
+ int *pins;
+
+ func = pinmux_generic_get_function(pctldev, func_selector);
+ if (!func)
+ return -EINVAL;
+ group = pinctrl_generic_get_group(pctldev, group_selector);
+ if (!group)
+ return -EINVAL;
+
+ psel_val = func->data;
+ pins = group->pins;
+
+ for (i = 0; i < group->num_pins; i++) {
+ dev_dbg(pctrl->dev, "port:%u pin: %u PSEL:%u\n",
+ RZG2L_PIN_ID_TO_PORT(pins[i]), RZG2L_PIN_ID_TO_PIN(pins[i]),
+ psel_val[i]);
+ rzg2l_pinctrl_set_pfc_mode(pctrl, RZG2L_PIN_ID_TO_PORT(pins[i]),
+ RZG2L_PIN_ID_TO_PIN(pins[i]), psel_val[i]);
+ }
+
+ return 0;
+};
+
+static int rzg2l_map_add_config(struct pinctrl_map *map,
+ const char *group_or_pin,
+ enum pinctrl_map_type type,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ unsigned long *cfgs;
+
+ cfgs = kmemdup(configs, num_configs * sizeof(*cfgs),
+ GFP_KERNEL);
+ if (!cfgs)
+ return -ENOMEM;
+
+ map->type = type;
+ map->data.configs.group_or_pin = group_or_pin;
+ map->data.configs.configs = cfgs;
+ map->data.configs.num_configs = num_configs;
+
+ return 0;
+}
+
+static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned int *num_maps,
+ unsigned int *index)
+{
+ struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct pinctrl_map *maps = *map;
+ unsigned int nmaps = *num_maps;
+ unsigned long *configs = NULL;
+ unsigned int *pins, *psel_val;
+ unsigned int num_pinmux = 0;
+ unsigned int idx = *index;
+ unsigned int num_pins, i;
+ unsigned int num_configs;
+ struct property *pinmux;
+ struct property *prop;
+ int ret, gsel, fsel;
+ const char **pin_fn;
+ const char *pin;
+
+ pinmux = of_find_property(np, "pinmux", NULL);
+ if (pinmux)
+ num_pinmux = pinmux->length / sizeof(u32);
+
+ ret = of_property_count_strings(np, "pins");
+ if (ret == -EINVAL) {
+ num_pins = 0;
+ } else if (ret < 0) {
+ dev_err(pctrl->dev, "Invalid pins list in DT\n");
+ return ret;
+ } else {
+ num_pins = ret;
+ }
+
+ if (!num_pinmux && !num_pins)
+ return 0;
+
+ if (num_pinmux && num_pins) {
+ dev_err(pctrl->dev,
+ "DT node must contain either a pinmux or pins and not both\n");
+ return -EINVAL;
+ }
+
+ ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &num_configs);
+ if (ret < 0)
+ return ret;
+
+ if (num_pins && !num_configs) {
+ dev_err(pctrl->dev, "DT node must contain a config\n");
+ ret = -ENODEV;
+ goto done;
+ }
+
+ if (num_pinmux)
+ nmaps += 1;
+
+ if (num_pins)
+ nmaps += num_pins;
+
+ maps = krealloc_array(maps, nmaps, sizeof(*maps), GFP_KERNEL);
+ if (!maps) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ *map = maps;
+ *num_maps = nmaps;
+ if (num_pins) {
+ of_property_for_each_string(np, "pins", prop, pin) {
+ ret = rzg2l_map_add_config(&maps[idx], pin,
+ PIN_MAP_TYPE_CONFIGS_PIN,
+ configs, num_configs);
+ if (ret < 0)
+ goto done;
+
+ idx++;
+ }
+ ret = 0;
+ goto done;
+ }
+
+ pins = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*pins), GFP_KERNEL);
+ psel_val = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*psel_val),
+ GFP_KERNEL);
+ pin_fn = devm_kzalloc(pctrl->dev, sizeof(*pin_fn), GFP_KERNEL);
+ if (!pins || !psel_val || !pin_fn) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ /* Collect pin locations and mux settings from DT properties */
+ for (i = 0; i < num_pinmux; ++i) {
+ u32 value;
+
+ ret = of_property_read_u32_index(np, "pinmux", i, &value);
+ if (ret)
+ goto done;
+ pins[i] = value & MUX_PIN_ID_MASK;
+ psel_val[i] = MUX_FUNC(value);
+ }
+
+ /* Register a single pin group listing all the pins we read from DT */
+ gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL);
+ if (gsel < 0) {
+ ret = gsel;
+ goto done;
+ }
+
+ /*
+ * Register a single group function where the 'data' is an array PSEL
+ * register values read from DT.
+ */
+ pin_fn[0] = np->name;
+ fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1,
+ psel_val);
+ if (fsel < 0) {
+ ret = fsel;
+ goto remove_group;
+ }
+
+ maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
+ maps[idx].data.mux.group = np->name;
+ maps[idx].data.mux.function = np->name;
+ idx++;
+
+ dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
+ ret = 0;
+ goto done;
+
+remove_group:
+ pinctrl_generic_remove_group(pctldev, gsel);
+done:
+ *index = idx;
+ kfree(configs);
+ return ret;
+}
+
+static void rzg2l_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map,
+ unsigned int num_maps)
+{
+ unsigned int i;
+
+ if (!map)
+ return;
+
+ for (i = 0; i < num_maps; ++i) {
+ if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP ||
+ map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+ kfree(map[i].data.configs.configs);
+ }
+ kfree(map);
+}
+
+static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned int *num_maps)
+{
+ struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct device_node *child;
+ unsigned int index;
+ int ret;
+
+ *map = NULL;
+ *num_maps = 0;
+ index = 0;
+
+ for_each_child_of_node(np, child) {
+ ret = rzg2l_dt_subnode_to_map(pctldev, child, map,
+ num_maps, &index);
+ if (ret < 0) {
+ of_node_put(child);
+ goto done;
+ }
+ }
+
+ if (*num_maps == 0) {
+ ret = rzg2l_dt_subnode_to_map(pctldev, np, map,
+ num_maps, &index);
+ if (ret < 0)
+ goto done;
+ }
+
+ if (*num_maps)
+ return 0;
+
+ dev_err(pctrl->dev, "no mapping found in node %pOF\n", np);
+ ret = -EINVAL;
+
+done:
+ if (ret < 0)
+ rzg2l_dt_free_map(pctldev, *map, *num_maps);
+
+ return ret;
+}
+
+static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int _pin,
+ unsigned long *config)
+{
+ struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin];
+ unsigned int *pin_data = pin->drv_data;
+ unsigned int arg = 0;
+ unsigned long flags;
+ void __iomem *addr;
+ u32 port = 0, reg;
+ u32 cfg = 0;
+ u8 bit = 0;
+
+ if (!pin_data)
+ return -EINVAL;
+
+ if (*pin_data & RZG2L_SINGLE_PIN) {
+ port = RZG2L_SINGLE_PIN_GET_PORT(*pin_data);
+ cfg = RZG2L_SINGLE_PIN_GET_CFGS(*pin_data);
+ bit = RZG2L_SINGLE_PIN_GET_BIT(*pin_data);
+ }
+
+ switch (param) {
+ case PIN_CONFIG_INPUT_ENABLE:
+ if (!(cfg & PIN_CFG_IEN))
+ return -EINVAL;
+ spin_lock_irqsave(&pctrl->lock, flags);
+ /* handle _L/_H for 32-bit register read/write */
+ addr = pctrl->base + IEN(port);
+ if (bit >= 4) {
+ bit -= 4;
+ addr += 4;
+ }
+
+ reg = readl(addr) & (IEN_MASK << (bit * 8));
+ arg = (reg >> (bit * 8)) & 0x1;
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+ break;
+
+ case PIN_CONFIG_POWER_SOURCE: {
+ u32 pwr_reg = 0x0;
+
+ if (cfg & PIN_CFG_IOLH_SD0)
+ pwr_reg = SD_CH(0);
+ else if (cfg & PIN_CFG_IOLH_SD1)
+ pwr_reg = SD_CH(1);
+ else if (cfg & PIN_CFG_IOLH_QSPI)
+ pwr_reg = QSPI;
+ else
+ return -EINVAL;
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+ addr = pctrl->base + pwr_reg;
+ arg = (readl(addr) & PVDD_MASK) ? 1800 : 3300;
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+ break;
+ }
+
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+};
+
+static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int _pin,
+ unsigned long *_configs,
+ unsigned int num_configs)
+{
+ struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin];
+ unsigned int *pin_data = pin->drv_data;
+ enum pin_config_param param;
+ unsigned long flags;
+ void __iomem *addr;
+ u32 port = 0, reg;
+ unsigned int i;
+ u32 cfg = 0;
+ u8 bit = 0;
+
+ if (!pin_data)
+ return -EINVAL;
+
+ if (*pin_data & RZG2L_SINGLE_PIN) {
+ port = RZG2L_SINGLE_PIN_GET_PORT(*pin_data);
+ cfg = RZG2L_SINGLE_PIN_GET_CFGS(*pin_data);
+ bit = RZG2L_SINGLE_PIN_GET_BIT(*pin_data);
+ }
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(_configs[i]);
+ switch (param) {
+ case PIN_CONFIG_INPUT_ENABLE: {
+ unsigned int arg =
+ pinconf_to_config_argument(_configs[i]);
+
+ if (!(cfg & PIN_CFG_IEN))
+ return -EINVAL;
+
+ /* handle _L/_H for 32-bit register read/write */
+ addr = pctrl->base + IEN(port);
+ if (bit >= 4) {
+ bit -= 4;
+ addr += 4;
+ }
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+ reg = readl(addr) & ~(IEN_MASK << (bit * 8));
+ writel(reg | (arg << (bit * 8)), addr);
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+ break;
+ }
+
+ case PIN_CONFIG_POWER_SOURCE: {
+ unsigned int mV = pinconf_to_config_argument(_configs[i]);
+ u32 pwr_reg = 0x0;
+
+ if (mV != 1800 && mV != 3300)
+ return -EINVAL;
+
+ if (cfg & PIN_CFG_IOLH_SD0)
+ pwr_reg = SD_CH(0);
+ else if (cfg & PIN_CFG_IOLH_SD1)
+ pwr_reg = SD_CH(1);
+ else if (cfg & PIN_CFG_IOLH_QSPI)
+ pwr_reg = QSPI;
+ else
+ return -EINVAL;
+
+ addr = pctrl->base + pwr_reg;
+ spin_lock_irqsave(&pctrl->lock, flags);
+ writel((mV == 1800) ? PVDD_1800 : PVDD_3300, addr);
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+ break;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+static int rzg2l_pinctrl_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int group,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ const unsigned int *pins;
+ unsigned int i, npins;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ ret = rzg2l_pinctrl_pinconf_set(pctldev, pins[i], configs,
+ num_configs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+};
+
+static int rzg2l_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned int group,
+ unsigned long *config)
+{
+ const unsigned int *pins;
+ unsigned int i, npins, prev_config = 0;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ ret = rzg2l_pinctrl_pinconf_get(pctldev, pins[i], config);
+ if (ret)
+ return ret;
+
+ /* Check config matching between to pin */
+ if (i && prev_config != *config)
+ return -EOPNOTSUPP;
+
+ prev_config = *config;
+ }
+
+ return 0;
+};
+
+static const struct pinctrl_ops rzg2l_pinctrl_pctlops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = rzg2l_dt_node_to_map,
+ .dt_free_map = rzg2l_dt_free_map,
+};
+
+static const struct pinmux_ops rzg2l_pinctrl_pmxops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = rzg2l_pinctrl_set_mux,
+ .strict = true,
+};
+
+static const struct pinconf_ops rzg2l_pinctrl_confops = {
+ .is_generic = true,
+ .pin_config_get = rzg2l_pinctrl_pinconf_get,
+ .pin_config_set = rzg2l_pinctrl_pinconf_set,
+ .pin_config_group_set = rzg2l_pinctrl_pinconf_group_set,
+ .pin_config_group_get = rzg2l_pinctrl_pinconf_group_get,
+ .pin_config_config_dbg_show = pinconf_generic_dump_config,
+};
+
+static int rzg2l_gpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip);
+ u32 port = RZG2L_PIN_ID_TO_PORT(offset);
+ u8 bit = RZG2L_PIN_ID_TO_PIN(offset);
+ unsigned long flags;
+ u8 reg8;
+ int ret;
+
+ ret = pinctrl_gpio_request(chip->base + offset);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+
+ /* Select GPIO mode in PMC Register */
+ reg8 = readb(pctrl->base + PMC(port));
+ reg8 &= ~BIT(bit);
+ writeb(reg8, pctrl->base + PMC(port));
+
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ return 0;
+}
+
+static void rzg2l_gpio_set_direction(struct rzg2l_pinctrl *pctrl, u32 port,
+ u8 bit, bool output)
+{
+ unsigned long flags;
+ u16 reg16;
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+
+ reg16 = readw(pctrl->base + PM(port));
+ reg16 &= ~(PM_MASK << (bit * 2));
+
+ reg16 |= (output ? PM_OUTPUT : PM_INPUT) << (bit * 2);
+ writew(reg16, pctrl->base + PM(port));
+
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static int rzg2l_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip);
+ u32 port = RZG2L_PIN_ID_TO_PORT(offset);
+ u8 bit = RZG2L_PIN_ID_TO_PIN(offset);
+
+ if (!(readb(pctrl->base + PMC(port)) & BIT(bit))) {
+ u16 reg16;
+
+ reg16 = readw(pctrl->base + PM(port));
+ reg16 = (reg16 >> (bit * 2)) & PM_MASK;
+ if (reg16 == PM_OUTPUT)
+ return GPIO_LINE_DIRECTION_OUT;
+ }
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
+static int rzg2l_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip);
+ u32 port = RZG2L_PIN_ID_TO_PORT(offset);
+ u8 bit = RZG2L_PIN_ID_TO_PIN(offset);
+
+ rzg2l_gpio_set_direction(pctrl, port, bit, false);
+
+ return 0;
+}
+
+static void rzg2l_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip);
+ u32 port = RZG2L_PIN_ID_TO_PORT(offset);
+ u8 bit = RZG2L_PIN_ID_TO_PIN(offset);
+ unsigned long flags;
+ u8 reg8;
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+
+ reg8 = readb(pctrl->base + P(port));
+
+ if (value)
+ writeb(reg8 | BIT(bit), pctrl->base + P(port));
+ else
+ writeb(reg8 & ~BIT(bit), pctrl->base + P(port));
+
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static int rzg2l_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip);
+ u32 port = RZG2L_PIN_ID_TO_PORT(offset);
+ u8 bit = RZG2L_PIN_ID_TO_PIN(offset);
+
+ rzg2l_gpio_set(chip, offset, value);
+ rzg2l_gpio_set_direction(pctrl, port, bit, true);
+
+ return 0;
+}
+
+static int rzg2l_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip);
+ u32 port = RZG2L_PIN_ID_TO_PORT(offset);
+ u8 bit = RZG2L_PIN_ID_TO_PIN(offset);
+ u16 reg16;
+
+ reg16 = readw(pctrl->base + PM(port));
+ reg16 = (reg16 >> (bit * 2)) & PM_MASK;
+
+ if (reg16 == PM_INPUT)
+ return !!(readb(pctrl->base + PIN(port)) & BIT(bit));
+ else if (reg16 == PM_OUTPUT)
+ return !!(readb(pctrl->base + P(port)) & BIT(bit));
+ else
+ return -EINVAL;
+}
+
+static void rzg2l_gpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+ pinctrl_gpio_free(chip->base + offset);
+
+ /*
+ * Set the GPIO as an input to ensure that the next GPIO request won't
+ * drive the GPIO pin as an output.
+ */
+ rzg2l_gpio_direction_input(chip, offset);
+}
+
+static const char * const rzg2l_gpio_names[] = {
+ "P0_0", "P0_1", "P0_2", "P0_3", "P0_4", "P0_5", "P0_6", "P0_7",
+ "P1_0", "P1_1", "P1_2", "P1_3", "P1_4", "P1_5", "P1_6", "P1_7",
+ "P2_0", "P2_1", "P2_2", "P2_3", "P2_4", "P2_5", "P2_6", "P2_7",
+ "P3_0", "P3_1", "P3_2", "P3_3", "P3_4", "P3_5", "P3_6", "P3_7",
+ "P4_0", "P4_1", "P4_2", "P4_3", "P4_4", "P4_5", "P4_6", "P4_7",
+ "P5_0", "P5_1", "P5_2", "P5_3", "P5_4", "P5_5", "P5_6", "P5_7",
+ "P6_0", "P6_1", "P6_2", "P6_3", "P6_4", "P6_5", "P6_6", "P6_7",
+ "P7_0", "P7_1", "P7_2", "P7_3", "P7_4", "P7_5", "P7_6", "P7_7",
+ "P8_0", "P8_1", "P8_2", "P8_3", "P8_4", "P8_5", "P8_6", "P8_7",
+ "P9_0", "P9_1", "P9_2", "P9_3", "P9_4", "P9_5", "P9_6", "P9_7",
+ "P10_0", "P10_1", "P10_2", "P10_3", "P10_4", "P10_5", "P10_6", "P10_7",
+ "P11_0", "P11_1", "P11_2", "P11_3", "P11_4", "P11_5", "P11_6", "P11_7",
+ "P12_0", "P12_1", "P12_2", "P12_3", "P12_4", "P12_5", "P12_6", "P12_7",
+ "P13_0", "P13_1", "P13_2", "P13_3", "P13_4", "P13_5", "P13_6", "P13_7",
+ "P14_0", "P14_1", "P14_2", "P14_3", "P14_4", "P14_5", "P14_6", "P14_7",
+ "P15_0", "P15_1", "P15_2", "P15_3", "P15_4", "P15_5", "P15_6", "P15_7",
+ "P16_0", "P16_1", "P16_2", "P16_3", "P16_4", "P16_5", "P16_6", "P16_7",
+ "P17_0", "P17_1", "P17_2", "P17_3", "P17_4", "P17_5", "P17_6", "P17_7",
+ "P18_0", "P18_1", "P18_2", "P18_3", "P18_4", "P18_5", "P18_6", "P18_7",
+ "P19_0", "P19_1", "P19_2", "P19_3", "P19_4", "P19_5", "P19_6", "P19_7",
+ "P20_0", "P20_1", "P20_2", "P20_3", "P20_4", "P20_5", "P20_6", "P20_7",
+ "P21_0", "P21_1", "P21_2", "P21_3", "P21_4", "P21_5", "P21_6", "P21_7",
+ "P22_0", "P22_1", "P22_2", "P22_3", "P22_4", "P22_5", "P22_6", "P22_7",
+ "P23_0", "P23_1", "P23_2", "P23_3", "P23_4", "P23_5", "P23_6", "P23_7",
+ "P24_0", "P24_1", "P24_2", "P24_3", "P24_4", "P24_5", "P24_6", "P24_7",
+ "P25_0", "P25_1", "P25_2", "P25_3", "P25_4", "P25_5", "P25_6", "P25_7",
+ "P26_0", "P26_1", "P26_2", "P26_3", "P26_4", "P26_5", "P26_6", "P26_7",
+ "P27_0", "P27_1", "P27_2", "P27_3", "P27_4", "P27_5", "P27_6", "P27_7",
+ "P28_0", "P28_1", "P28_2", "P28_3", "P28_4", "P28_5", "P28_6", "P28_7",
+ "P29_0", "P29_1", "P29_2", "P29_3", "P29_4", "P29_5", "P29_6", "P29_7",
+ "P30_0", "P30_1", "P30_2", "P30_3", "P30_4", "P30_5", "P30_6", "P30_7",
+ "P31_0", "P31_1", "P31_2", "P31_3", "P31_4", "P31_5", "P31_6", "P31_7",
+ "P32_0", "P32_1", "P32_2", "P32_3", "P32_4", "P32_5", "P32_6", "P32_7",
+ "P33_0", "P33_1", "P33_2", "P33_3", "P33_4", "P33_5", "P33_6", "P33_7",
+ "P34_0", "P34_1", "P34_2", "P34_3", "P34_4", "P34_5", "P34_6", "P34_7",
+ "P35_0", "P35_1", "P35_2", "P35_3", "P35_4", "P35_5", "P35_6", "P35_7",
+ "P36_0", "P36_1", "P36_2", "P36_3", "P36_4", "P36_5", "P36_6", "P36_7",
+ "P37_0", "P37_1", "P37_2", "P37_3", "P37_4", "P37_5", "P37_6", "P37_7",
+ "P38_0", "P38_1", "P38_2", "P38_3", "P38_4", "P38_5", "P38_6", "P38_7",
+ "P39_0", "P39_1", "P39_2", "P39_3", "P39_4", "P39_5", "P39_6", "P39_7",
+ "P40_0", "P40_1", "P40_2", "P40_3", "P40_4", "P40_5", "P40_6", "P40_7",
+ "P41_0", "P41_1", "P41_2", "P41_3", "P41_4", "P41_5", "P41_6", "P41_7",
+ "P42_0", "P42_1", "P42_2", "P42_3", "P42_4", "P42_5", "P42_6", "P42_7",
+ "P43_0", "P43_1", "P43_2", "P43_3", "P43_4", "P43_5", "P43_6", "P43_7",
+ "P44_0", "P44_1", "P44_2", "P44_3", "P44_4", "P44_5", "P44_6", "P44_7",
+ "P45_0", "P45_1", "P45_2", "P45_3", "P45_4", "P45_5", "P45_6", "P45_7",
+ "P46_0", "P46_1", "P46_2", "P46_3", "P46_4", "P46_5", "P46_6", "P46_7",
+ "P47_0", "P47_1", "P47_2", "P47_3", "P47_4", "P47_5", "P47_6", "P47_7",
+ "P48_0", "P48_1", "P48_2", "P48_3", "P48_4", "P48_5", "P48_6", "P48_7",
+};
+
+static const u32 rzg2l_gpio_configs[] = {
+ RZG2L_GPIO_PORT_PACK(2, 0x10, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x11, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x12, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x13, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x14, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(3, 0x15, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x16, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(3, 0x17, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(3, 0x18, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x19, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x1a, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x1b, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x1c, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(3, 0x1d, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x1e, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x1f, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x20, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(3, 0x22, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x22, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x23, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(3, 0x24, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x25, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x26, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x27, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x28, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x29, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x2a, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x2b, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x2c, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)),
+ RZG2L_GPIO_PORT_PACK(2, 0x2d, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(2, 0x2e, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(2, 0x2f, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(2, 0x30, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(2, 0x31, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(2, 0x32, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(2, 0x33, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(2, 0x34, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(3, 0x35, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH1)),
+ RZG2L_GPIO_PORT_PACK(2, 0x36, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(3, 0x37, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(3, 0x38, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(2, 0x39, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(5, 0x3a, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(4, 0x3b, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(4, 0x3c, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(4, 0x3d, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(4, 0x3e, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(4, 0x3f, RZG2L_MPXED_PIN_FUNCS),
+ RZG2L_GPIO_PORT_PACK(5, 0x40, RZG2L_MPXED_PIN_FUNCS),
+};
+
+static struct rzg2l_dedicated_configs rzg2l_dedicated_pins[] = {
+ { "NMI", RZG2L_SINGLE_PIN_PACK(0x1, 0,
+ (PIN_CFG_FILONOFF | PIN_CFG_FILNUM | PIN_CFG_FILCLKSEL)) },
+ { "TMS/SWDIO", RZG2L_SINGLE_PIN_PACK(0x2, 0,
+ (PIN_CFG_SR | PIN_CFG_IOLH | PIN_CFG_IEN)) },
+ { "TDO", RZG2L_SINGLE_PIN_PACK(0x3, 0,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN)) },
+ { "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x4, 0, PIN_CFG_IEN) },
+ { "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x4, 1, PIN_CFG_IEN) },
+ { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x6, 0,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_SD0)) },
+ { "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x6, 1,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x6, 2,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_SD0)) },
+ { "SD0_DATA0", RZG2L_SINGLE_PIN_PACK(0x7, 0,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD0_DATA1", RZG2L_SINGLE_PIN_PACK(0x7, 1,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD0_DATA2", RZG2L_SINGLE_PIN_PACK(0x7, 2,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD0_DATA3", RZG2L_SINGLE_PIN_PACK(0x7, 3,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD0_DATA4", RZG2L_SINGLE_PIN_PACK(0x7, 4,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD0_DATA5", RZG2L_SINGLE_PIN_PACK(0x7, 5,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD0_DATA6", RZG2L_SINGLE_PIN_PACK(0x7, 6,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD0_DATA7", RZG2L_SINGLE_PIN_PACK(0x7, 7,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD0)) },
+ { "SD1_CLK", RZG2L_SINGLE_PIN_PACK(0x8, 0,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_SD1))},
+ { "SD1_CMD", RZG2L_SINGLE_PIN_PACK(0x8, 1,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD1)) },
+ { "SD1_DATA0", RZG2L_SINGLE_PIN_PACK(0x9, 0,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD1)) },
+ { "SD1_DATA1", RZG2L_SINGLE_PIN_PACK(0x9, 1,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD1)) },
+ { "SD1_DATA2", RZG2L_SINGLE_PIN_PACK(0x9, 2,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD1)) },
+ { "SD1_DATA3", RZG2L_SINGLE_PIN_PACK(0x9, 3,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IOLH_SD1)) },
+ { "QSPI0_SPCLK", RZG2L_SINGLE_PIN_PACK(0xa, 0,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI0_IO0", RZG2L_SINGLE_PIN_PACK(0xa, 1,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI0_IO1", RZG2L_SINGLE_PIN_PACK(0xa, 2,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI0_IO2", RZG2L_SINGLE_PIN_PACK(0xa, 3,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI0_IO3", RZG2L_SINGLE_PIN_PACK(0xa, 4,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI0_SSL", RZG2L_SINGLE_PIN_PACK(0xa, 5,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI1_SPCLK", RZG2L_SINGLE_PIN_PACK(0xb, 0,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI1_IO0", RZG2L_SINGLE_PIN_PACK(0xb, 1,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI1_IO1", RZG2L_SINGLE_PIN_PACK(0xb, 2,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI1_IO2", RZG2L_SINGLE_PIN_PACK(0xb, 3,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI1_IO3", RZG2L_SINGLE_PIN_PACK(0xb, 4,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI1_SSL", RZG2L_SINGLE_PIN_PACK(0xb, 5,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI_RESET#", RZG2L_SINGLE_PIN_PACK(0xc, 0,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI_WP#", RZG2L_SINGLE_PIN_PACK(0xc, 1,
+ (PIN_CFG_IOLH | PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "QSPI_INT#", RZG2L_SINGLE_PIN_PACK(0xc, 2, (PIN_CFG_SR | PIN_CFG_IOLH_QSPI)) },
+ { "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0xd, 0, (PIN_CFG_IOLH | PIN_CFG_SR)) },
+ { "RIIC0_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 0, PIN_CFG_IEN) },
+ { "RIIC0_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 1, PIN_CFG_IEN) },
+ { "RIIC1_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 2, PIN_CFG_IEN) },
+ { "RIIC1_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 3, PIN_CFG_IEN) },
+};
+
+static int rzg2l_gpio_register(struct rzg2l_pinctrl *pctrl)
+{
+ struct device_node *np = pctrl->dev->of_node;
+ struct gpio_chip *chip = &pctrl->gpio_chip;
+ const char *name = dev_name(pctrl->dev);
+ struct of_phandle_args of_args;
+ int ret;
+
+ ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &of_args);
+ if (ret) {
+ dev_err(pctrl->dev, "Unable to parse gpio-ranges\n");
+ return ret;
+ }
+
+ if (of_args.args[0] != 0 || of_args.args[1] != 0 ||
+ of_args.args[2] != ARRAY_SIZE(rzg2l_gpio_names)) {
+ dev_err(pctrl->dev, "gpio-ranges does not match selected SOC\n");
+ return -EINVAL;
+ }
+
+ chip->names = rzg2l_gpio_names;
+ chip->request = rzg2l_gpio_request;
+ chip->free = rzg2l_gpio_free;
+ chip->get_direction = rzg2l_gpio_get_direction;
+ chip->direction_input = rzg2l_gpio_direction_input;
+ chip->direction_output = rzg2l_gpio_direction_output;
+ chip->get = rzg2l_gpio_get;
+ chip->set = rzg2l_gpio_set;
+ chip->label = name;
+ chip->parent = pctrl->dev;
+ chip->owner = THIS_MODULE;
+ chip->base = -1;
+ chip->ngpio = of_args.args[2];
+
+ pctrl->gpio_range.id = 0;
+ pctrl->gpio_range.pin_base = 0;
+ pctrl->gpio_range.base = 0;
+ pctrl->gpio_range.npins = chip->ngpio;
+ pctrl->gpio_range.name = chip->label;
+ pctrl->gpio_range.gc = chip;
+ ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
+ if (ret) {
+ dev_err(pctrl->dev, "failed to add GPIO controller\n");
+ return ret;
+ }
+
+ dev_dbg(pctrl->dev, "Registered gpio controller\n");
+
+ return 0;
+}
+
+static int rzg2l_pinctrl_register(struct rzg2l_pinctrl *pctrl)
+{
+ struct pinctrl_pin_desc *pins;
+ unsigned int i, j;
+ u32 *pin_data;
+ int ret;
+
+ pctrl->desc.name = DRV_NAME;
+ pctrl->desc.npins = pctrl->data->n_port_pins + pctrl->data->n_dedicated_pins;
+ pctrl->desc.pctlops = &rzg2l_pinctrl_pctlops;
+ pctrl->desc.pmxops = &rzg2l_pinctrl_pmxops;
+ pctrl->desc.confops = &rzg2l_pinctrl_confops;
+ pctrl->desc.owner = THIS_MODULE;
+
+ pins = devm_kcalloc(pctrl->dev, pctrl->desc.npins, sizeof(*pins), GFP_KERNEL);
+ if (!pins)
+ return -ENOMEM;
+
+ pin_data = devm_kcalloc(pctrl->dev, pctrl->desc.npins,
+ sizeof(*pin_data), GFP_KERNEL);
+ if (!pin_data)
+ return -ENOMEM;
+
+ pctrl->pins = pins;
+ pctrl->desc.pins = pins;
+
+ for (i = 0, j = 0; i < pctrl->data->n_port_pins; i++) {
+ pins[i].number = i;
+ pins[i].name = pctrl->data->port_pins[i];
+ if (i && !(i % RZG2L_PINS_PER_PORT))
+ j++;
+ pin_data[i] = pctrl->data->port_pin_configs[j];
+ pins[i].drv_data = &pin_data[i];
+ }
+
+ for (i = 0; i < pctrl->data->n_dedicated_pins; i++) {
+ unsigned int index = pctrl->data->n_port_pins + i;
+
+ pins[index].number = index;
+ pins[index].name = pctrl->data->dedicated_pins[i].name;
+ pin_data[index] = pctrl->data->dedicated_pins[i].config;
+ pins[index].drv_data = &pin_data[index];
+ }
+
+ ret = devm_pinctrl_register_and_init(pctrl->dev, &pctrl->desc, pctrl,
+ &pctrl->pctl);
+ if (ret) {
+ dev_err(pctrl->dev, "pinctrl registration failed\n");
+ return ret;
+ }
+
+ ret = pinctrl_enable(pctrl->pctl);
+ if (ret) {
+ dev_err(pctrl->dev, "pinctrl enable failed\n");
+ return ret;
+ }
+
+ ret = rzg2l_gpio_register(pctrl);
+ if (ret) {
+ dev_err(pctrl->dev, "failed to add GPIO chip: %i\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void rzg2l_pinctrl_clk_disable(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+static int rzg2l_pinctrl_probe(struct platform_device *pdev)
+{
+ struct rzg2l_pinctrl *pctrl;
+ int ret;
+
+ pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
+ if (!pctrl)
+ return -ENOMEM;
+
+ pctrl->dev = &pdev->dev;
+
+ pctrl->data = of_device_get_match_data(&pdev->dev);
+ if (!pctrl->data)
+ return -EINVAL;
+
+ pctrl->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pctrl->base))
+ return PTR_ERR(pctrl->base);
+
+ pctrl->clk = devm_clk_get(pctrl->dev, NULL);
+ if (IS_ERR(pctrl->clk)) {
+ ret = PTR_ERR(pctrl->clk);
+ dev_err(pctrl->dev, "failed to get GPIO clk : %i\n", ret);
+ return ret;
+ }
+
+ spin_lock_init(&pctrl->lock);
+
+ platform_set_drvdata(pdev, pctrl);
+
+ ret = clk_prepare_enable(pctrl->clk);
+ if (ret) {
+ dev_err(pctrl->dev, "failed to enable GPIO clk: %i\n", ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&pdev->dev, rzg2l_pinctrl_clk_disable,
+ pctrl->clk);
+ if (ret) {
+ dev_err(pctrl->dev,
+ "failed to register GPIO clk disable action, %i\n",
+ ret);
+ return ret;
+ }
+
+ ret = rzg2l_pinctrl_register(pctrl);
+ if (ret)
+ return ret;
+
+ dev_info(pctrl->dev, "%s support registered\n", DRV_NAME);
+ return 0;
+}
+
+static struct rzg2l_pinctrl_data r9a07g044_data = {
+ .port_pins = rzg2l_gpio_names,
+ .port_pin_configs = rzg2l_gpio_configs,
+ .dedicated_pins = rzg2l_dedicated_pins,
+ .n_port_pins = ARRAY_SIZE(rzg2l_gpio_names),
+ .n_dedicated_pins = ARRAY_SIZE(rzg2l_dedicated_pins),
+};
+
+static const struct of_device_id rzg2l_pinctrl_of_table[] = {
+ {
+ .compatible = "renesas,r9a07g044-pinctrl",
+ .data = &r9a07g044_data,
+ },
+ { /* sentinel */ }
+};
+
+static struct platform_driver rzg2l_pinctrl_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = of_match_ptr(rzg2l_pinctrl_of_table),
+ },
+ .probe = rzg2l_pinctrl_probe,
+};
+
+static int __init rzg2l_pinctrl_init(void)
+{
+ return platform_driver_register(&rzg2l_pinctrl_driver);
+}
+core_initcall(rzg2l_pinctrl_init);
+
+MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
+MODULE_DESCRIPTION("Pin and gpio controller driver for RZ/G2L family");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/renesas/pinctrl.c b/drivers/pinctrl/renesas/pinctrl.c
index bb488af29862..f3eecb20c086 100644
--- a/drivers/pinctrl/renesas/pinctrl.c
+++ b/drivers/pinctrl/renesas/pinctrl.c
@@ -841,7 +841,7 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
return pinctrl_enable(pmx->pctl);
}
-static const struct pinmux_bias_reg *
+const struct pinmux_bias_reg *
rcar_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
unsigned int *bit)
{
@@ -898,17 +898,17 @@ void rcar_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
if (reg->puen) {
enable = sh_pfc_read(pfc, reg->puen) & ~BIT(bit);
- if (bias != PIN_CONFIG_BIAS_DISABLE)
+ if (bias != PIN_CONFIG_BIAS_DISABLE) {
enable |= BIT(bit);
- if (reg->pud) {
- updown = sh_pfc_read(pfc, reg->pud) & ~BIT(bit);
- if (bias == PIN_CONFIG_BIAS_PULL_UP)
- updown |= BIT(bit);
+ if (reg->pud) {
+ updown = sh_pfc_read(pfc, reg->pud) & ~BIT(bit);
+ if (bias == PIN_CONFIG_BIAS_PULL_UP)
+ updown |= BIT(bit);
- sh_pfc_write(pfc, reg->pud, updown);
+ sh_pfc_write(pfc, reg->pud, updown);
+ }
}
-
sh_pfc_write(pfc, reg->puen, enable);
} else {
enable = sh_pfc_read(pfc, reg->pud) & ~BIT(bit);
diff --git a/drivers/pinctrl/renesas/sh_pfc.h b/drivers/pinctrl/renesas/sh_pfc.h
index 320898861c4b..2479b4fb9cf9 100644
--- a/drivers/pinctrl/renesas/sh_pfc.h
+++ b/drivers/pinctrl/renesas/sh_pfc.h
@@ -332,8 +332,8 @@ extern const struct sh_pfc_soc_info r8a7791_pinmux_info;
extern const struct sh_pfc_soc_info r8a7792_pinmux_info;
extern const struct sh_pfc_soc_info r8a7793_pinmux_info;
extern const struct sh_pfc_soc_info r8a7794_pinmux_info;
-extern const struct sh_pfc_soc_info r8a77950_pinmux_info __weak;
-extern const struct sh_pfc_soc_info r8a77951_pinmux_info __weak;
+extern const struct sh_pfc_soc_info r8a77950_pinmux_info;
+extern const struct sh_pfc_soc_info r8a77951_pinmux_info;
extern const struct sh_pfc_soc_info r8a77960_pinmux_info;
extern const struct sh_pfc_soc_info r8a77961_pinmux_info;
extern const struct sh_pfc_soc_info r8a77965_pinmux_info;
@@ -781,6 +781,9 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
/*
* Bias helpers
*/
+const struct pinmux_bias_reg *
+rcar_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
+ unsigned int *bit);
unsigned int rcar_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin);
void rcar_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
unsigned int bias);
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index b6e56422a700..fe5f6046fbd5 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -40,6 +40,24 @@ static const struct samsung_pin_bank_type exynos5433_bank_type_alive = {
.reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
};
+/*
+ * Bank type for non-alive type. Bit fields:
+ * CON: 4, DAT: 1, PUD: 4, DRV: 4, CONPDN: 2, PUDPDN: 4
+ */
+static const struct samsung_pin_bank_type exynos850_bank_type_off = {
+ .fld_width = { 4, 1, 4, 4, 2, 4, },
+ .reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, },
+};
+
+/*
+ * Bank type for alive type. Bit fields:
+ * CON: 4, DAT: 1, PUD: 4, DRV: 4
+ */
+static const struct samsung_pin_bank_type exynos850_bank_type_alive = {
+ .fld_width = { 4, 1, 4, 4, },
+ .reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
+};
+
/* Pad retention control code for accessing PMU regmap */
static atomic_t exynos_shared_retention_refcnt;
@@ -422,3 +440,101 @@ const struct samsung_pinctrl_of_match_data exynos7_of_data __initconst = {
.ctrl = exynos7_pin_ctrl,
.num_ctrl = ARRAY_SIZE(exynos7_pin_ctrl),
};
+
+/* pin banks of exynos850 pin-controller 0 (ALIVE) */
+static const struct samsung_pin_bank_data exynos850_pin_banks0[] __initconst = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
+ EXYNOS850_PIN_BANK_EINTW(4, 0x080, "gpa4", 0x10),
+ EXYNOS850_PIN_BANK_EINTN(3, 0x0a0, "gpq0"),
+};
+
+/* pin banks of exynos850 pin-controller 1 (CMGP) */
+static const struct samsung_pin_bank_data exynos850_pin_banks1[] __initconst = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTW(1, 0x000, "gpm0", 0x00),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x020, "gpm1", 0x04),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x040, "gpm2", 0x08),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x060, "gpm3", 0x0c),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x080, "gpm4", 0x10),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0a0, "gpm5", 0x14),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0c0, "gpm6", 0x18),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0e0, "gpm7", 0x1c),
+};
+
+/* pin banks of exynos850 pin-controller 2 (AUD) */
+static const struct samsung_pin_bank_data exynos850_pin_banks2[] __initconst = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(5, 0x000, "gpb0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(5, 0x020, "gpb1", 0x04),
+};
+
+/* pin banks of exynos850 pin-controller 3 (HSI) */
+static const struct samsung_pin_bank_data exynos850_pin_banks3[] __initconst = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(6, 0x000, "gpf2", 0x00),
+};
+
+/* pin banks of exynos850 pin-controller 4 (CORE) */
+static const struct samsung_pin_bank_data exynos850_pin_banks4[] __initconst = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(4, 0x000, "gpf0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x020, "gpf1", 0x04),
+};
+
+/* pin banks of exynos850 pin-controller 5 (PERI) */
+static const struct samsung_pin_bank_data exynos850_pin_banks5[] __initconst = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(2, 0x000, "gpg0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(6, 0x020, "gpp0", 0x04),
+ EXYNOS850_PIN_BANK_EINTG(4, 0x040, "gpp1", 0x08),
+ EXYNOS850_PIN_BANK_EINTG(4, 0x060, "gpp2", 0x0c),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x080, "gpg1", 0x10),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x0a0, "gpg2", 0x14),
+ EXYNOS850_PIN_BANK_EINTG(1, 0x0c0, "gpg3", 0x18),
+ EXYNOS850_PIN_BANK_EINTG(3, 0x0e0, "gpc0", 0x1c),
+ EXYNOS850_PIN_BANK_EINTG(6, 0x100, "gpc1", 0x20),
+};
+
+static const struct samsung_pin_ctrl exynos850_pin_ctrl[] __initconst = {
+ {
+ /* pin-controller instance 0 ALIVE data */
+ .pin_banks = exynos850_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos850_pin_banks0),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .eint_wkup_init = exynos_eint_wkup_init,
+ }, {
+ /* pin-controller instance 1 CMGP data */
+ .pin_banks = exynos850_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos850_pin_banks1),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .eint_wkup_init = exynos_eint_wkup_init,
+ }, {
+ /* pin-controller instance 2 AUD data */
+ .pin_banks = exynos850_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos850_pin_banks2),
+ }, {
+ /* pin-controller instance 3 HSI data */
+ .pin_banks = exynos850_pin_banks3,
+ .nr_banks = ARRAY_SIZE(exynos850_pin_banks3),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ }, {
+ /* pin-controller instance 4 CORE data */
+ .pin_banks = exynos850_pin_banks4,
+ .nr_banks = ARRAY_SIZE(exynos850_pin_banks4),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ }, {
+ /* pin-controller instance 5 PERI data */
+ .pin_banks = exynos850_pin_banks5,
+ .nr_banks = ARRAY_SIZE(exynos850_pin_banks5),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ },
+};
+
+const struct samsung_pinctrl_of_match_data exynos850_of_data __initconst = {
+ .ctrl = exynos850_pin_ctrl,
+ .num_ctrl = ARRAY_SIZE(exynos850_pin_ctrl),
+};
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index da1ec13697e7..bfad1ced8017 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -108,6 +108,35 @@
.pctl_res_idx = pctl_idx, \
} \
+#define EXYNOS850_PIN_BANK_EINTN(pins, reg, id) \
+ { \
+ .type = &exynos850_bank_type_alive, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_NONE, \
+ .name = id \
+ }
+
+#define EXYNOS850_PIN_BANK_EINTG(pins, reg, id, offs) \
+ { \
+ .type = &exynos850_bank_type_off, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_GPIO, \
+ .eint_offset = offs, \
+ .name = id \
+ }
+
+#define EXYNOS850_PIN_BANK_EINTW(pins, reg, id, offs) \
+ { \
+ .type = &exynos850_bank_type_alive, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_WKUP, \
+ .eint_offset = offs, \
+ .name = id \
+ }
+
/**
* struct exynos_weint_data: irq specific data for all the wakeup interrupts
* generated by the external wakeup interrupt controller.
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 376876bd6605..2a0fc63516f1 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -918,7 +918,7 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
pin_bank->grange.pin_base = drvdata->pin_base
+ pin_bank->pin_base;
pin_bank->grange.base = pin_bank->grange.pin_base;
- pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
+ pin_bank->grange.npins = pin_bank->nr_pins;
pin_bank->grange.gc = &pin_bank->gpio_chip;
pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
}
@@ -1264,6 +1264,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
.data = &exynos5433_of_data },
{ .compatible = "samsung,exynos7-pinctrl",
.data = &exynos7_of_data },
+ { .compatible = "samsung,exynos850-pinctrl",
+ .data = &exynos850_of_data },
#endif
#ifdef CONFIG_PINCTRL_S3C64XX
{ .compatible = "samsung,s3c64xx-pinctrl",
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index de44f8ec330b..4c2149e9c544 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -339,6 +339,7 @@ extern const struct samsung_pinctrl_of_match_data exynos5410_of_data;
extern const struct samsung_pinctrl_of_match_data exynos5420_of_data;
extern const struct samsung_pinctrl_of_match_data exynos5433_of_data;
extern const struct samsung_pinctrl_of_match_data exynos7_of_data;
+extern const struct samsung_pinctrl_of_match_data exynos850_of_data;
extern const struct samsung_pinctrl_of_match_data s3c64xx_of_data;
extern const struct samsung_pinctrl_of_match_data s3c2412_of_data;
extern const struct samsung_pinctrl_of_match_data s3c2416_of_data;
diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig
index f36f29113370..d532f3c6f670 100644
--- a/drivers/pinctrl/stm32/Kconfig
+++ b/drivers/pinctrl/stm32/Kconfig
@@ -40,6 +40,12 @@ config PINCTRL_STM32H743
default MACH_STM32H743
select PINCTRL_STM32
+config PINCTRL_STM32MP135
+ bool "STMicroelectronics STM32MP135 pin control" if COMPILE_TEST && !MACH_STM32MP13
+ depends on OF && HAS_IOMEM
+ default MACH_STM32MP13
+ select PINCTRL_STM32
+
config PINCTRL_STM32MP157
bool "STMicroelectronics STM32MP157 pin control" if COMPILE_TEST && !MACH_STM32MP157
depends on OF && HAS_IOMEM
diff --git a/drivers/pinctrl/stm32/Makefile b/drivers/pinctrl/stm32/Makefile
index f7c56d4b941c..619629ee9944 100644
--- a/drivers/pinctrl/stm32/Makefile
+++ b/drivers/pinctrl/stm32/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_PINCTRL_STM32F469) += pinctrl-stm32f469.o
obj-$(CONFIG_PINCTRL_STM32F746) += pinctrl-stm32f746.o
obj-$(CONFIG_PINCTRL_STM32F769) += pinctrl-stm32f769.o
obj-$(CONFIG_PINCTRL_STM32H743) += pinctrl-stm32h743.o
+obj-$(CONFIG_PINCTRL_STM32MP135) += pinctrl-stm32mp135.o
obj-$(CONFIG_PINCTRL_STM32MP157) += pinctrl-stm32mp157.o
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp135.c b/drivers/pinctrl/stm32/pinctrl-stm32mp135.c
new file mode 100644
index 000000000000..4ab03520c407
--- /dev/null
+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp135.c
@@ -0,0 +1,1679 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2021 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-stm32.h"
+
+static const struct stm32_desc_pin stm32mp135_pins[] = {
+ STM32_PIN(
+ PINCTRL_PIN(0, "PA0"),
+ STM32_FUNCTION(0, "GPIOA0"),
+ STM32_FUNCTION(2, "TIM2_CH1"),
+ STM32_FUNCTION(3, "TIM5_CH1"),
+ STM32_FUNCTION(4, "TIM8_ETR"),
+ STM32_FUNCTION(5, "TIM15_BKIN"),
+ STM32_FUNCTION(7, "SAI1_SD_B"),
+ STM32_FUNCTION(9, "UART5_TX"),
+ STM32_FUNCTION(12, "ETH1_MII_CRS"),
+ STM32_FUNCTION(13, "ETH2_MII_CRS"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(1, "PA1"),
+ STM32_FUNCTION(0, "GPIOA1"),
+ STM32_FUNCTION(2, "TIM2_CH2"),
+ STM32_FUNCTION(3, "TIM5_CH2"),
+ STM32_FUNCTION(4, "LPTIM3_OUT"),
+ STM32_FUNCTION(5, "TIM15_CH1N"),
+ STM32_FUNCTION(7, "DFSDM1_CKIN0"),
+ STM32_FUNCTION(8, "USART2_RTS USART2_DE"),
+ STM32_FUNCTION(12, "ETH1_MII_RX_CLK ETH1_RGMII_RX_CLK ETH1_RMII_REF_CLK"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(2, "PA2"),
+ STM32_FUNCTION(0, "GPIOA2"),
+ STM32_FUNCTION(2, "TIM2_CH3"),
+ STM32_FUNCTION(3, "TIM5_CH3"),
+ STM32_FUNCTION(4, "LPTIM4_OUT"),
+ STM32_FUNCTION(5, "TIM15_CH1"),
+ STM32_FUNCTION(8, "USART2_TX"),
+ STM32_FUNCTION(12, "ETH1_MDIO"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(3, "PA3"),
+ STM32_FUNCTION(0, "GPIOA3"),
+ STM32_FUNCTION(2, "TIM2_CH4"),
+ STM32_FUNCTION(3, "TIM5_CH4"),
+ STM32_FUNCTION(4, "LPTIM5_OUT"),
+ STM32_FUNCTION(5, "TIM15_CH2"),
+ STM32_FUNCTION(6, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(7, "SAI1_FS_B"),
+ STM32_FUNCTION(8, "USART2_RX"),
+ STM32_FUNCTION(12, "ETH1_MII_COL"),
+ STM32_FUNCTION(13, "ETH2_MII_COL"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(4, "PA4"),
+ STM32_FUNCTION(0, "GPIOA4"),
+ STM32_FUNCTION(3, "TIM5_ETR"),
+ STM32_FUNCTION(4, "USART2_CK"),
+ STM32_FUNCTION(5, "SAI1_SCK_B"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "DFSDM1_CKIN1"),
+ STM32_FUNCTION(11, "ETH1_PPS_OUT"),
+ STM32_FUNCTION(12, "ETH2_PPS_OUT"),
+ STM32_FUNCTION(13, "SAI1_SCK_A"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(5, "PA5"),
+ STM32_FUNCTION(0, "GPIOA5"),
+ STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+ STM32_FUNCTION(3, "USART2_CK"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(5, "SAI1_D1"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(11, "ETH1_PPS_OUT"),
+ STM32_FUNCTION(12, "ETH2_PPS_OUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(6, "PA6"),
+ STM32_FUNCTION(0, "GPIOA6"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(5, "SAI2_CK2"),
+ STM32_FUNCTION(6, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(8, "USART1_CK"),
+ STM32_FUNCTION(9, "UART4_RTS UART4_DE"),
+ STM32_FUNCTION(10, "TIM13_CH1"),
+ STM32_FUNCTION(13, "SAI2_SCK_A"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(7, "PA7"),
+ STM32_FUNCTION(0, "GPIOA7"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(5, "SAI2_D1"),
+ STM32_FUNCTION(6, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(8, "USART1_CTS USART1_NSS"),
+ STM32_FUNCTION(10, "TIM14_CH1"),
+ STM32_FUNCTION(12, "ETH1_MII_RX_DV ETH1_RGMII_RX_CTL ETH1_RMII_CRS_DV"),
+ STM32_FUNCTION(13, "SAI2_SD_A"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(8, "PA8"),
+ STM32_FUNCTION(0, "GPIOA8"),
+ STM32_FUNCTION(1, "MCO1"),
+ STM32_FUNCTION(3, "SAI2_MCLK_A"),
+ STM32_FUNCTION(4, "TIM8_BKIN2"),
+ STM32_FUNCTION(5, "I2C4_SDA"),
+ STM32_FUNCTION(6, "SPI5_MISO"),
+ STM32_FUNCTION(7, "SAI2_CK1"),
+ STM32_FUNCTION(8, "USART1_CK"),
+ STM32_FUNCTION(9, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(11, "OTG_HS_SOF"),
+ STM32_FUNCTION(12, "ETH2_MII_RXD3 ETH2_RGMII_RXD3"),
+ STM32_FUNCTION(13, "FMC_A21"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(9, "PA9"),
+ STM32_FUNCTION(0, "GPIOA9"),
+ STM32_FUNCTION(2, "TIM1_CH2"),
+ STM32_FUNCTION(5, "I2C3_SMBA"),
+ STM32_FUNCTION(7, "DFSDM1_DATIN0"),
+ STM32_FUNCTION(8, "USART1_TX"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(11, "FMC_NWAIT"),
+ STM32_FUNCTION(14, "DCMIPP_D0"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(10, "PA10"),
+ STM32_FUNCTION(0, "GPIOA10"),
+ STM32_FUNCTION(2, "TIM1_CH3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(11, "PA11"),
+ STM32_FUNCTION(0, "GPIOA11"),
+ STM32_FUNCTION(2, "TIM1_CH4"),
+ STM32_FUNCTION(5, "I2C5_SCL"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(8, "USART1_CTS USART1_NSS"),
+ STM32_FUNCTION(11, "ETH2_MII_RXD1 ETH2_RGMII_RXD1 ETH2_RMII_RXD1"),
+ STM32_FUNCTION(12, "ETH1_CLK"),
+ STM32_FUNCTION(14, "ETH2_CLK"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(12, "PA12"),
+ STM32_FUNCTION(0, "GPIOA12"),
+ STM32_FUNCTION(2, "TIM1_ETR"),
+ STM32_FUNCTION(3, "SAI2_MCLK_A"),
+ STM32_FUNCTION(8, "USART1_RTS USART1_DE"),
+ STM32_FUNCTION(11, "TSC_G1_IO2"),
+ STM32_FUNCTION(12, "ETH2_MII_RX_DV ETH2_RGMII_RX_CTL ETH2_RMII_CRS_DV"),
+ STM32_FUNCTION(13, "FMC_A7"),
+ STM32_FUNCTION(14, "DCMIPP_D1"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(13, "PA13"),
+ STM32_FUNCTION(0, "GPIOA13"),
+ STM32_FUNCTION(1, "DBTRGO"),
+ STM32_FUNCTION(2, "DBTRGI"),
+ STM32_FUNCTION(3, "MCO1"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(14, "PA14"),
+ STM32_FUNCTION(0, "GPIOA14"),
+ STM32_FUNCTION(1, "DBTRGO"),
+ STM32_FUNCTION(2, "DBTRGI"),
+ STM32_FUNCTION(3, "MCO2"),
+ STM32_FUNCTION(11, "OTG_HS_SOF"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(15, "PA15"),
+ STM32_FUNCTION(0, "GPIOA15"),
+ STM32_FUNCTION(1, "TRACED5"),
+ STM32_FUNCTION(2, "TIM2_CH1"),
+ STM32_FUNCTION(6, "I2S4_MCK"),
+ STM32_FUNCTION(8, "UART4_RTS UART4_DE"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "LCD_R0"),
+ STM32_FUNCTION(11, "TSC_G3_IO1"),
+ STM32_FUNCTION(12, "LCD_G7"),
+ STM32_FUNCTION(13, "FMC_A9"),
+ STM32_FUNCTION(14, "DCMIPP_D14"),
+ STM32_FUNCTION(15, "DCMIPP_D5"),
+ STM32_FUNCTION(16, "HDP5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(16, "PB0"),
+ STM32_FUNCTION(0, "GPIOB0"),
+ STM32_FUNCTION(1, "DBTRGI"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(3, "TIM3_CH3"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(5, "USART1_RX"),
+ STM32_FUNCTION(6, "I2S1_MCK"),
+ STM32_FUNCTION(7, "SAI2_FS_A"),
+ STM32_FUNCTION(8, "USART1_CK"),
+ STM32_FUNCTION(9, "UART4_CTS"),
+ STM32_FUNCTION(11, "SAI2_D2"),
+ STM32_FUNCTION(12, "ETH1_MII_RXD2 ETH1_RGMII_RXD2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(17, "PB1"),
+ STM32_FUNCTION(0, "GPIOB1"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(3, "TIM3_CH4"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(6, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(7, "DFSDM1_DATIN1"),
+ STM32_FUNCTION(8, "UART4_RX"),
+ STM32_FUNCTION(12, "ETH1_MII_RXD3 ETH1_RGMII_RXD3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(18, "PB2"),
+ STM32_FUNCTION(0, "GPIOB2"),
+ STM32_FUNCTION(2, "RTC_OUT2"),
+ STM32_FUNCTION(3, "SAI1_D1"),
+ STM32_FUNCTION(6, "I2S_CKIN"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_NCS"),
+ STM32_FUNCTION(12, "ETH2_MDIO"),
+ STM32_FUNCTION(13, "FMC_A6"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(19, "PB3"),
+ STM32_FUNCTION(0, "GPIOB3"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(2, "TIM2_CH2"),
+ STM32_FUNCTION(5, "SAI2_CK1"),
+ STM32_FUNCTION(6, "SPI4_NSS I2S4_WS"),
+ STM32_FUNCTION(9, "SDMMC1_D123DIR"),
+ STM32_FUNCTION(11, "SDMMC2_D2"),
+ STM32_FUNCTION(12, "LCD_R6"),
+ STM32_FUNCTION(13, "SAI2_MCLK_A"),
+ STM32_FUNCTION(14, "UART7_RX"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(20, "PB4"),
+ STM32_FUNCTION(0, "GPIOB4"),
+ STM32_FUNCTION(1, "TRACED14"),
+ STM32_FUNCTION(2, "TIM16_BKIN"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(5, "SAI2_CK2"),
+ STM32_FUNCTION(6, "SPI4_SCK I2S4_CK"),
+ STM32_FUNCTION(8, "USART3_CK"),
+ STM32_FUNCTION(11, "SDMMC2_D3"),
+ STM32_FUNCTION(12, "LCD_G1"),
+ STM32_FUNCTION(13, "SAI2_SCK_A"),
+ STM32_FUNCTION(14, "LCD_B6"),
+ STM32_FUNCTION(15, "LCD_R0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(21, "PB5"),
+ STM32_FUNCTION(0, "GPIOB5"),
+ STM32_FUNCTION(1, "TRACED4"),
+ STM32_FUNCTION(2, "TIM17_BKIN"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(6, "SPI2_MISO I2S2_SDI"),
+ STM32_FUNCTION(7, "I2C4_SMBA"),
+ STM32_FUNCTION(9, "SDMMC1_CKIN"),
+ STM32_FUNCTION(10, "FDCAN2_RX"),
+ STM32_FUNCTION(12, "UART5_RX"),
+ STM32_FUNCTION(14, "LCD_B6"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(22, "PB6"),
+ STM32_FUNCTION(0, "GPIOB6"),
+ STM32_FUNCTION(1, "TRACED6"),
+ STM32_FUNCTION(2, "TIM16_CH1N"),
+ STM32_FUNCTION(3, "TIM4_CH1"),
+ STM32_FUNCTION(4, "TIM8_CH1"),
+ STM32_FUNCTION(5, "USART1_TX"),
+ STM32_FUNCTION(7, "SAI1_CK2"),
+ STM32_FUNCTION(8, "LCD_B6"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_NCS"),
+ STM32_FUNCTION(11, "TSC_G1_IO4"),
+ STM32_FUNCTION(12, "ETH2_MDIO"),
+ STM32_FUNCTION(13, "FMC_NE3"),
+ STM32_FUNCTION(14, "DCMIPP_D5"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "HDP6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(23, "PB7"),
+ STM32_FUNCTION(0, "GPIOB7"),
+ STM32_FUNCTION(2, "TIM17_CH1N"),
+ STM32_FUNCTION(3, "TIM4_CH2"),
+ STM32_FUNCTION(4, "TSC_SYNC"),
+ STM32_FUNCTION(6, "I2S4_CK"),
+ STM32_FUNCTION(7, "I2C4_SDA"),
+ STM32_FUNCTION(11, "FMC_NCE2"),
+ STM32_FUNCTION(13, "FMC_NL"),
+ STM32_FUNCTION(14, "DCMIPP_D13"),
+ STM32_FUNCTION(15, "DCMIPP_PIXCLK"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(24, "PB8"),
+ STM32_FUNCTION(0, "GPIOB8"),
+ STM32_FUNCTION(2, "TIM16_CH1"),
+ STM32_FUNCTION(3, "TIM4_CH3"),
+ STM32_FUNCTION(5, "I2C1_SCL"),
+ STM32_FUNCTION(6, "I2C3_SCL"),
+ STM32_FUNCTION(7, "DFSDM1_DATIN1"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(11, "SAI1_D1"),
+ STM32_FUNCTION(13, "FMC_D13 FMC_AD13"),
+ STM32_FUNCTION(14, "DCMIPP_D6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(25, "PB9"),
+ STM32_FUNCTION(0, "GPIOB9"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(3, "TIM4_CH4"),
+ STM32_FUNCTION(7, "I2C4_SDA"),
+ STM32_FUNCTION(10, "FDCAN1_TX"),
+ STM32_FUNCTION(11, "SDMMC2_D5"),
+ STM32_FUNCTION(12, "UART5_TX"),
+ STM32_FUNCTION(13, "SDMMC1_CDIR"),
+ STM32_FUNCTION(14, "LCD_DE"),
+ STM32_FUNCTION(15, "LCD_B1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(26, "PB10"),
+ STM32_FUNCTION(0, "GPIOB10"),
+ STM32_FUNCTION(2, "TIM2_CH3"),
+ STM32_FUNCTION(4, "LPTIM2_IN1"),
+ STM32_FUNCTION(5, "I2C5_SMBA"),
+ STM32_FUNCTION(6, "SPI4_NSS I2S4_WS"),
+ STM32_FUNCTION(7, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(15, "LCD_R3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(27, "PB11"),
+ STM32_FUNCTION(0, "GPIOB11"),
+ STM32_FUNCTION(2, "TIM2_CH4"),
+ STM32_FUNCTION(4, "LPTIM1_OUT"),
+ STM32_FUNCTION(5, "I2C5_SMBA"),
+ STM32_FUNCTION(8, "USART3_RX"),
+ STM32_FUNCTION(12, "ETH1_MII_TX_EN ETH1_RGMII_TX_CTL ETH1_RMII_TX_EN"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(28, "PB12"),
+ STM32_FUNCTION(0, "GPIOB12"),
+ STM32_FUNCTION(1, "TRACED10"),
+ STM32_FUNCTION(5, "I2C2_SMBA"),
+ STM32_FUNCTION(7, "DFSDM1_DATIN1"),
+ STM32_FUNCTION(8, "UART7_RTS UART7_DE"),
+ STM32_FUNCTION(9, "USART3_RX"),
+ STM32_FUNCTION(12, "UART5_RX"),
+ STM32_FUNCTION(13, "SDMMC1_D5"),
+ STM32_FUNCTION(14, "LCD_R3"),
+ STM32_FUNCTION(15, "LCD_VSYNC"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(29, "PB13"),
+ STM32_FUNCTION(0, "GPIOB13"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(5, "LPTIM2_OUT"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(7, "I2C4_SCL"),
+ STM32_FUNCTION(9, "SDMMC1_D123DIR"),
+ STM32_FUNCTION(10, "FDCAN2_TX"),
+ STM32_FUNCTION(12, "UART5_TX"),
+ STM32_FUNCTION(14, "LCD_CLK"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(30, "PB14"),
+ STM32_FUNCTION(0, "GPIOB14"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(3, "TIM12_CH1"),
+ STM32_FUNCTION(4, "TIM8_CH2N"),
+ STM32_FUNCTION(5, "USART1_TX"),
+ STM32_FUNCTION(11, "SDMMC2_D0"),
+ STM32_FUNCTION(12, "SDMMC1_D4"),
+ STM32_FUNCTION(14, "LCD_R0"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(31, "PB15"),
+ STM32_FUNCTION(0, "GPIOB15"),
+ STM32_FUNCTION(1, "RTC_REFIN"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(3, "TIM12_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH3N"),
+ STM32_FUNCTION(5, "SAI2_D2"),
+ STM32_FUNCTION(6, "SPI4_MOSI I2S4_SDO"),
+ STM32_FUNCTION(7, "DFSDM1_CKIN2"),
+ STM32_FUNCTION(8, "UART7_CTS"),
+ STM32_FUNCTION(9, "SDMMC1_CKIN"),
+ STM32_FUNCTION(11, "SDMMC2_D1"),
+ STM32_FUNCTION(13, "SAI2_FS_A"),
+ STM32_FUNCTION(14, "LCD_CLK"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(32, "PC0"),
+ STM32_FUNCTION(0, "GPIOC0"),
+ STM32_FUNCTION(3, "SAI1_SCK_A"),
+ STM32_FUNCTION(5, "SAI1_CK2"),
+ STM32_FUNCTION(6, "I2S1_MCK"),
+ STM32_FUNCTION(7, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(8, "USART1_TX"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(33, "PC1"),
+ STM32_FUNCTION(0, "GPIOC1"),
+ STM32_FUNCTION(4, "DFSDM1_DATIN0"),
+ STM32_FUNCTION(7, "SAI1_D3"),
+ STM32_FUNCTION(11, "ETH1_MII_RX_DV ETH1_RMII_CRS_DV"),
+ STM32_FUNCTION(12, "ETH1_RGMII_GTX_CLK"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(34, "PC2"),
+ STM32_FUNCTION(0, "GPIOC2"),
+ STM32_FUNCTION(2, "SPI5_NSS"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "SAI2_MCLK_A"),
+ STM32_FUNCTION(8, "USART1_RTS USART1_DE"),
+ STM32_FUNCTION(11, "SAI2_CK1"),
+ STM32_FUNCTION(12, "ETH1_MII_TXD2 ETH1_RGMII_TXD2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(35, "PC3"),
+ STM32_FUNCTION(0, "GPIOC3"),
+ STM32_FUNCTION(3, "SAI1_CK1"),
+ STM32_FUNCTION(4, "DFSDM1_CKOUT"),
+ STM32_FUNCTION(6, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(7, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(9, "UART5_CTS"),
+ STM32_FUNCTION(11, "SAI1_MCLK_A"),
+ STM32_FUNCTION(12, "ETH1_MII_TX_CLK"),
+ STM32_FUNCTION(13, "ETH2_MII_TX_CLK"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(36, "PC4"),
+ STM32_FUNCTION(0, "GPIOC4"),
+ STM32_FUNCTION(3, "TIM3_ETR"),
+ STM32_FUNCTION(4, "DFSDM1_CKIN2"),
+ STM32_FUNCTION(5, "SAI1_D3"),
+ STM32_FUNCTION(6, "I2S1_MCK"),
+ STM32_FUNCTION(9, "UART5_RTS UART5_DE"),
+ STM32_FUNCTION(10, "SPDIFRX_IN2"),
+ STM32_FUNCTION(12, "ETH1_MII_RXD0 ETH1_RGMII_RXD0 ETH1_RMII_RXD0"),
+ STM32_FUNCTION(13, "SAI2_D3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(37, "PC5"),
+ STM32_FUNCTION(0, "GPIOC5"),
+ STM32_FUNCTION(4, "DFSDM1_DATIN2"),
+ STM32_FUNCTION(5, "SAI2_D4"),
+ STM32_FUNCTION(6, "I2S_CKIN"),
+ STM32_FUNCTION(7, "SAI1_D4"),
+ STM32_FUNCTION(8, "USART2_CTS USART2_NSS"),
+ STM32_FUNCTION(10, "SPDIFRX_IN3"),
+ STM32_FUNCTION(12, "ETH1_MII_RXD1 ETH1_RGMII_RXD1 ETH1_RMII_RXD1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(38, "PC6"),
+ STM32_FUNCTION(0, "GPIOC6"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(3, "TIM3_CH1"),
+ STM32_FUNCTION(4, "TIM8_CH1"),
+ STM32_FUNCTION(5, "DFSDM1_DATIN0"),
+ STM32_FUNCTION(6, "I2S3_MCK"),
+ STM32_FUNCTION(8, "USART6_TX"),
+ STM32_FUNCTION(9, "SDMMC1_D6"),
+ STM32_FUNCTION(10, "SDMMC2_D0DIR"),
+ STM32_FUNCTION(11, "SDMMC2_D6"),
+ STM32_FUNCTION(12, "LCD_B1"),
+ STM32_FUNCTION(13, "FMC_A19"),
+ STM32_FUNCTION(14, "LCD_R6"),
+ STM32_FUNCTION(15, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "HDP2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(39, "PC7"),
+ STM32_FUNCTION(0, "GPIOC7"),
+ STM32_FUNCTION(1, "TRACED4"),
+ STM32_FUNCTION(3, "TIM3_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH2"),
+ STM32_FUNCTION(7, "I2S2_MCK"),
+ STM32_FUNCTION(8, "USART6_RX"),
+ STM32_FUNCTION(9, "USART3_CTS"),
+ STM32_FUNCTION(10, "SDMMC2_CDIR"),
+ STM32_FUNCTION(11, "SDMMC2_D7"),
+ STM32_FUNCTION(12, "LCD_R1"),
+ STM32_FUNCTION(13, "SDMMC1_D7"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(16, "HDP4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(40, "PC8"),
+ STM32_FUNCTION(0, "GPIOC8"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(3, "TIM3_CH3"),
+ STM32_FUNCTION(4, "TIM8_CH3"),
+ STM32_FUNCTION(6, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(8, "USART6_CK"),
+ STM32_FUNCTION(9, "USART3_CTS"),
+ STM32_FUNCTION(11, "SAI2_FS_B"),
+ STM32_FUNCTION(12, "UART5_RTS UART5_DE"),
+ STM32_FUNCTION(13, "SDMMC1_D0"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(41, "PC9"),
+ STM32_FUNCTION(0, "GPIOC9"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(3, "TIM3_CH4"),
+ STM32_FUNCTION(4, "TIM8_CH4"),
+ STM32_FUNCTION(8, "USART3_RTS"),
+ STM32_FUNCTION(9, "UART5_CTS"),
+ STM32_FUNCTION(10, "FDCAN1_TX"),
+ STM32_FUNCTION(13, "SDMMC1_D1"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(42, "PC10"),
+ STM32_FUNCTION(0, "GPIOC10"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(6, "I2C1_SCL"),
+ STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(13, "SDMMC1_D2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(43, "PC11"),
+ STM32_FUNCTION(0, "GPIOC11"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(5, "I2C1_SDA"),
+ STM32_FUNCTION(7, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(8, "USART3_CK"),
+ STM32_FUNCTION(9, "UART5_RX"),
+ STM32_FUNCTION(11, "SAI2_SCK_B"),
+ STM32_FUNCTION(13, "SDMMC1_D3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(44, "PC12"),
+ STM32_FUNCTION(0, "GPIOC12"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(9, "UART7_TX"),
+ STM32_FUNCTION(11, "SAI2_SD_B"),
+ STM32_FUNCTION(13, "SDMMC1_CK"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(45, "PC13"),
+ STM32_FUNCTION(0, "GPIOC13"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(46, "PC14"),
+ STM32_FUNCTION(0, "GPIOC14"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(47, "PC15"),
+ STM32_FUNCTION(0, "GPIOC15"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(48, "PD0"),
+ STM32_FUNCTION(0, "GPIOD0"),
+ STM32_FUNCTION(3, "SAI1_MCLK_A"),
+ STM32_FUNCTION(7, "SAI1_CK1"),
+ STM32_FUNCTION(10, "FDCAN1_RX"),
+ STM32_FUNCTION(13, "FMC_D2 FMC_AD2"),
+ STM32_FUNCTION(14, "DCMIPP_D1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(49, "PD1"),
+ STM32_FUNCTION(0, "GPIOD1"),
+ STM32_FUNCTION(5, "I2C5_SCL"),
+ STM32_FUNCTION(6, "SPI4_MOSI I2S4_SDO"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_NCS"),
+ STM32_FUNCTION(12, "LCD_B6"),
+ STM32_FUNCTION(13, "FMC_D3 FMC_AD3"),
+ STM32_FUNCTION(14, "DCMIPP_D13"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(50, "PD2"),
+ STM32_FUNCTION(0, "GPIOD2"),
+ STM32_FUNCTION(1, "TRACED4"),
+ STM32_FUNCTION(3, "TIM3_ETR"),
+ STM32_FUNCTION(5, "I2C1_SMBA"),
+ STM32_FUNCTION(6, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(7, "SAI2_D1"),
+ STM32_FUNCTION(8, "USART3_RX"),
+ STM32_FUNCTION(13, "SDMMC1_CMD"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(51, "PD3"),
+ STM32_FUNCTION(0, "GPIOD3"),
+ STM32_FUNCTION(3, "TIM2_CH1"),
+ STM32_FUNCTION(4, "USART2_CTS USART2_NSS"),
+ STM32_FUNCTION(5, "DFSDM1_CKOUT"),
+ STM32_FUNCTION(6, "I2C1_SDA"),
+ STM32_FUNCTION(7, "SAI1_D3"),
+ STM32_FUNCTION(13, "FMC_CLK"),
+ STM32_FUNCTION(14, "DCMIPP_D5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(52, "PD4"),
+ STM32_FUNCTION(0, "GPIOD4"),
+ STM32_FUNCTION(4, "USART2_RTS USART2_DE"),
+ STM32_FUNCTION(6, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(7, "DFSDM1_CKIN0"),
+ STM32_FUNCTION(10, "QUADSPI_CLK"),
+ STM32_FUNCTION(12, "LCD_R1"),
+ STM32_FUNCTION(13, "FMC_NOE"),
+ STM32_FUNCTION(14, "LCD_R4"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(53, "PD5"),
+ STM32_FUNCTION(0, "GPIOD5"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO0"),
+ STM32_FUNCTION(13, "FMC_NWE"),
+ STM32_FUNCTION(14, "LCD_B0"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(54, "PD6"),
+ STM32_FUNCTION(0, "GPIOD6"),
+ STM32_FUNCTION(2, "TIM16_CH1N"),
+ STM32_FUNCTION(3, "SAI1_D1"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(12, "TSC_G2_IO1"),
+ STM32_FUNCTION(14, "DCMIPP_D4"),
+ STM32_FUNCTION(15, "DCMIPP_D0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(55, "PD7"),
+ STM32_FUNCTION(0, "GPIOD7"),
+ STM32_FUNCTION(1, "MCO1"),
+ STM32_FUNCTION(4, "USART2_CK"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(6, "I2C3_SDA"),
+ STM32_FUNCTION(10, "SPDIFRX_IN0"),
+ STM32_FUNCTION(11, "ETH1_MII_RX_CLK ETH1_RGMII_RX_CLK ETH1_RMII_REF_CLK"),
+ STM32_FUNCTION(12, "QUADSPI_BK1_IO2"),
+ STM32_FUNCTION(13, "FMC_NE1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(56, "PD8"),
+ STM32_FUNCTION(0, "GPIOD8"),
+ STM32_FUNCTION(4, "USART2_TX"),
+ STM32_FUNCTION(6, "I2S4_WS"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(11, "TSC_G1_IO3"),
+ STM32_FUNCTION(14, "DCMIPP_D9"),
+ STM32_FUNCTION(15, "DCMIPP_D3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(57, "PD9"),
+ STM32_FUNCTION(0, "GPIOD9"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(4, "DFSDM1_DATIN3"),
+ STM32_FUNCTION(11, "SDMMC2_CDIR"),
+ STM32_FUNCTION(12, "LCD_B5"),
+ STM32_FUNCTION(13, "FMC_D14 FMC_AD14"),
+ STM32_FUNCTION(14, "LCD_CLK"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(58, "PD10"),
+ STM32_FUNCTION(0, "GPIOD10"),
+ STM32_FUNCTION(1, "RTC_REFIN"),
+ STM32_FUNCTION(5, "I2C5_SMBA"),
+ STM32_FUNCTION(6, "SPI4_NSS I2S4_WS"),
+ STM32_FUNCTION(8, "USART3_CK"),
+ STM32_FUNCTION(10, "LCD_G5"),
+ STM32_FUNCTION(11, "TSC_G2_IO2"),
+ STM32_FUNCTION(12, "LCD_B7"),
+ STM32_FUNCTION(13, "FMC_D15 FMC_AD15"),
+ STM32_FUNCTION(14, "DCMIPP_VSYNC"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(59, "PD11"),
+ STM32_FUNCTION(0, "GPIOD11"),
+ STM32_FUNCTION(4, "LPTIM2_IN2"),
+ STM32_FUNCTION(5, "I2C4_SMBA"),
+ STM32_FUNCTION(8, "USART3_CTS USART3_NSS"),
+ STM32_FUNCTION(9, "SPDIFRX_IN0"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO2"),
+ STM32_FUNCTION(11, "ETH2_RGMII_CLK125"),
+ STM32_FUNCTION(12, "LCD_R7"),
+ STM32_FUNCTION(13, "FMC_CLE FMC_A16"),
+ STM32_FUNCTION(14, "UART7_RX"),
+ STM32_FUNCTION(15, "DCMIPP_D4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(60, "PD12"),
+ STM32_FUNCTION(0, "GPIOD12"),
+ STM32_FUNCTION(2, "LPTIM1_IN1"),
+ STM32_FUNCTION(3, "TIM4_CH1"),
+ STM32_FUNCTION(6, "I2C1_SCL"),
+ STM32_FUNCTION(8, "USART3_RTS USART3_DE"),
+ STM32_FUNCTION(13, "FMC_ALE FMC_A17"),
+ STM32_FUNCTION(14, "DCMIPP_D6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(61, "PD13"),
+ STM32_FUNCTION(0, "GPIOD13"),
+ STM32_FUNCTION(2, "LPTIM2_ETR"),
+ STM32_FUNCTION(3, "TIM4_CH2"),
+ STM32_FUNCTION(4, "TIM8_CH2"),
+ STM32_FUNCTION(5, "SAI1_CK1"),
+ STM32_FUNCTION(7, "SAI1_MCLK_A"),
+ STM32_FUNCTION(8, "USART1_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO3"),
+ STM32_FUNCTION(11, "TSC_G2_IO4"),
+ STM32_FUNCTION(12, "QUADSPI_BK2_IO2"),
+ STM32_FUNCTION(13, "FMC_A18"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(62, "PD14"),
+ STM32_FUNCTION(0, "GPIOD14"),
+ STM32_FUNCTION(3, "TIM4_CH3"),
+ STM32_FUNCTION(5, "I2C3_SDA"),
+ STM32_FUNCTION(8, "USART1_RX"),
+ STM32_FUNCTION(9, "UART8_CTS"),
+ STM32_FUNCTION(13, "FMC_D0 FMC_AD0"),
+ STM32_FUNCTION(14, "DCMIPP_D8"),
+ STM32_FUNCTION(15, "LCD_R4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(63, "PD15"),
+ STM32_FUNCTION(0, "GPIOD15"),
+ STM32_FUNCTION(2, "USART2_RX"),
+ STM32_FUNCTION(3, "TIM4_CH4"),
+ STM32_FUNCTION(4, "DFSDM1_DATIN2"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO3"),
+ STM32_FUNCTION(13, "FMC_D1 FMC_AD1"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(64, "PE0"),
+ STM32_FUNCTION(0, "GPIOE0"),
+ STM32_FUNCTION(7, "DCMIPP_D12"),
+ STM32_FUNCTION(9, "UART8_RX"),
+ STM32_FUNCTION(10, "FDCAN2_RX"),
+ STM32_FUNCTION(11, "TSC_G4_IO1"),
+ STM32_FUNCTION(12, "LCD_B1"),
+ STM32_FUNCTION(13, "FMC_A11"),
+ STM32_FUNCTION(14, "DCMIPP_D1"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(65, "PE1"),
+ STM32_FUNCTION(0, "GPIOE1"),
+ STM32_FUNCTION(2, "LPTIM1_IN2"),
+ STM32_FUNCTION(4, "TSC_G2_IO3"),
+ STM32_FUNCTION(9, "UART8_TX"),
+ STM32_FUNCTION(10, "LCD_HSYNC"),
+ STM32_FUNCTION(12, "LCD_R4"),
+ STM32_FUNCTION(13, "FMC_NBL1"),
+ STM32_FUNCTION(14, "DCMIPP_D3"),
+ STM32_FUNCTION(15, "DCMIPP_D12"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(66, "PE2"),
+ STM32_FUNCTION(0, "GPIOE2"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(2, "TIM2_ETR"),
+ STM32_FUNCTION(4, "TSC_G5_IO1"),
+ STM32_FUNCTION(5, "I2C4_SCL"),
+ STM32_FUNCTION(6, "SPI5_MOSI"),
+ STM32_FUNCTION(7, "SAI1_FS_B"),
+ STM32_FUNCTION(8, "USART6_RTS USART6_DE"),
+ STM32_FUNCTION(10, "SPDIFRX_IN1"),
+ STM32_FUNCTION(11, "ETH2_MII_RXD1 ETH2_RGMII_RXD1 ETH2_RMII_RXD1"),
+ STM32_FUNCTION(13, "FMC_A23"),
+ STM32_FUNCTION(15, "LCD_R1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(67, "PE3"),
+ STM32_FUNCTION(0, "GPIOE3"),
+ STM32_FUNCTION(1, "TRACED11"),
+ STM32_FUNCTION(3, "SAI2_D4"),
+ STM32_FUNCTION(5, "TIM15_BKIN"),
+ STM32_FUNCTION(6, "SPI4_MISO I2S4_SDI"),
+ STM32_FUNCTION(9, "USART3_RTS USART3_DE"),
+ STM32_FUNCTION(10, "FDCAN1_RX"),
+ STM32_FUNCTION(11, "SDMMC2_CK"),
+ STM32_FUNCTION(14, "LCD_R4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(68, "PE4"),
+ STM32_FUNCTION(0, "GPIOE4"),
+ STM32_FUNCTION(2, "SPI5_MISO"),
+ STM32_FUNCTION(3, "SAI1_D2"),
+ STM32_FUNCTION(4, "DFSDM1_DATIN3"),
+ STM32_FUNCTION(5, "TIM15_CH1N"),
+ STM32_FUNCTION(6, "I2S_CKIN"),
+ STM32_FUNCTION(7, "SAI1_FS_A"),
+ STM32_FUNCTION(8, "UART7_RTS UART7_DE"),
+ STM32_FUNCTION(9, "UART8_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_NCS"),
+ STM32_FUNCTION(11, "FMC_NCE2"),
+ STM32_FUNCTION(12, "TSC_G1_IO1"),
+ STM32_FUNCTION(13, "FMC_A25"),
+ STM32_FUNCTION(14, "DCMIPP_D3"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(69, "PE5"),
+ STM32_FUNCTION(0, "GPIOE5"),
+ STM32_FUNCTION(3, "SAI2_SCK_B"),
+ STM32_FUNCTION(4, "TIM8_CH3"),
+ STM32_FUNCTION(5, "TIM15_CH1"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(11, "ETH1_MII_TXD3 ETH1_RGMII_TXD3"),
+ STM32_FUNCTION(13, "FMC_NE1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(70, "PE6"),
+ STM32_FUNCTION(0, "GPIOE6"),
+ STM32_FUNCTION(1, "MCO2"),
+ STM32_FUNCTION(2, "TIM1_BKIN2"),
+ STM32_FUNCTION(3, "SAI2_SCK_B"),
+ STM32_FUNCTION(5, "TIM15_CH2"),
+ STM32_FUNCTION(6, "I2C3_SMBA"),
+ STM32_FUNCTION(7, "SAI1_SCK_B"),
+ STM32_FUNCTION(9, "UART4_RTS UART4_DE"),
+ STM32_FUNCTION(12, "ETH2_MII_TXD3 ETH2_RGMII_TXD3"),
+ STM32_FUNCTION(13, "FMC_A22"),
+ STM32_FUNCTION(14, "DCMIPP_D7"),
+ STM32_FUNCTION(15, "LCD_G3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(71, "PE7"),
+ STM32_FUNCTION(0, "GPIOE7"),
+ STM32_FUNCTION(2, "TIM1_ETR"),
+ STM32_FUNCTION(5, "LPTIM2_IN1"),
+ STM32_FUNCTION(9, "UART5_TX"),
+ STM32_FUNCTION(13, "FMC_D4 FMC_AD4"),
+ STM32_FUNCTION(14, "LCD_B3"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(72, "PE8"),
+ STM32_FUNCTION(0, "GPIOE8"),
+ STM32_FUNCTION(2, "TIM1_CH1N"),
+ STM32_FUNCTION(4, "DFSDM1_CKIN2"),
+ STM32_FUNCTION(6, "I2C1_SDA"),
+ STM32_FUNCTION(8, "UART7_TX"),
+ STM32_FUNCTION(13, "FMC_D5 FMC_AD5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(73, "PE9"),
+ STM32_FUNCTION(0, "GPIOE9"),
+ STM32_FUNCTION(2, "TIM1_CH1"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO1"),
+ STM32_FUNCTION(12, "LCD_HSYNC"),
+ STM32_FUNCTION(13, "FMC_D6 FMC_AD6"),
+ STM32_FUNCTION(14, "DCMIPP_D7"),
+ STM32_FUNCTION(15, "LCD_R7"),
+ STM32_FUNCTION(16, "HDP3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(74, "PE10"),
+ STM32_FUNCTION(0, "GPIOE10"),
+ STM32_FUNCTION(2, "TIM1_CH2N"),
+ STM32_FUNCTION(8, "UART7_RX"),
+ STM32_FUNCTION(10, "FDCAN1_TX"),
+ STM32_FUNCTION(13, "FMC_D7 FMC_AD7"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(75, "PE11"),
+ STM32_FUNCTION(0, "GPIOE11"),
+ STM32_FUNCTION(2, "TIM1_CH2"),
+ STM32_FUNCTION(3, "USART2_CTS USART2_NSS"),
+ STM32_FUNCTION(5, "SAI1_D2"),
+ STM32_FUNCTION(6, "SPI4_MOSI I2S4_SDO"),
+ STM32_FUNCTION(7, "SAI1_FS_A"),
+ STM32_FUNCTION(8, "USART6_CK"),
+ STM32_FUNCTION(10, "LCD_R0"),
+ STM32_FUNCTION(11, "ETH2_MII_TX_ER"),
+ STM32_FUNCTION(12, "ETH1_MII_TX_ER"),
+ STM32_FUNCTION(13, "FMC_D8 FMC_AD8"),
+ STM32_FUNCTION(14, "DCMIPP_D10"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(76, "PE12"),
+ STM32_FUNCTION(0, "GPIOE12"),
+ STM32_FUNCTION(2, "TIM1_CH3N"),
+ STM32_FUNCTION(6, "SPI4_SCK I2S4_CK"),
+ STM32_FUNCTION(9, "UART8_RTS UART8_DE"),
+ STM32_FUNCTION(10, "LCD_VSYNC"),
+ STM32_FUNCTION(11, "TSC_G3_IO2"),
+ STM32_FUNCTION(12, "LCD_G4"),
+ STM32_FUNCTION(13, "FMC_D9 FMC_AD9"),
+ STM32_FUNCTION(14, "DCMIPP_D11"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(16, "HDP4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(77, "PE13"),
+ STM32_FUNCTION(0, "GPIOE13"),
+ STM32_FUNCTION(2, "TIM1_CH3"),
+ STM32_FUNCTION(5, "I2C5_SDA"),
+ STM32_FUNCTION(6, "SPI4_MISO I2S4_SDI"),
+ STM32_FUNCTION(12, "LCD_B1"),
+ STM32_FUNCTION(13, "FMC_D10 FMC_AD10"),
+ STM32_FUNCTION(14, "DCMIPP_D4"),
+ STM32_FUNCTION(15, "LCD_R6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(78, "PE14"),
+ STM32_FUNCTION(0, "GPIOE14"),
+ STM32_FUNCTION(2, "TIM1_BKIN"),
+ STM32_FUNCTION(5, "SAI1_D4"),
+ STM32_FUNCTION(9, "UART8_RTS UART8_DE"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_NCS"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO2"),
+ STM32_FUNCTION(13, "FMC_D11 FMC_AD11"),
+ STM32_FUNCTION(14, "DCMIPP_D7"),
+ STM32_FUNCTION(15, "LCD_G0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(79, "PE15"),
+ STM32_FUNCTION(0, "GPIOE15"),
+ STM32_FUNCTION(2, "TIM2_ETR"),
+ STM32_FUNCTION(3, "TIM1_BKIN"),
+ STM32_FUNCTION(4, "USART2_CTS USART2_NSS"),
+ STM32_FUNCTION(7, "I2C4_SCL"),
+ STM32_FUNCTION(13, "FMC_D12 FMC_AD12"),
+ STM32_FUNCTION(14, "DCMIPP_D10"),
+ STM32_FUNCTION(15, "LCD_B7"),
+ STM32_FUNCTION(16, "HDP7"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(80, "PF0"),
+ STM32_FUNCTION(0, "GPIOF0"),
+ STM32_FUNCTION(1, "TRACED13"),
+ STM32_FUNCTION(4, "DFSDM1_CKOUT"),
+ STM32_FUNCTION(8, "USART3_CK"),
+ STM32_FUNCTION(11, "SDMMC2_D4"),
+ STM32_FUNCTION(13, "FMC_A0"),
+ STM32_FUNCTION(14, "LCD_R6"),
+ STM32_FUNCTION(15, "LCD_G0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(81, "PF1"),
+ STM32_FUNCTION(0, "GPIOF1"),
+ STM32_FUNCTION(1, "TRACED7"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(6, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(13, "FMC_A1"),
+ STM32_FUNCTION(14, "LCD_B7"),
+ STM32_FUNCTION(15, "LCD_G1"),
+ STM32_FUNCTION(16, "HDP7"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(82, "PF2"),
+ STM32_FUNCTION(0, "GPIOF2"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(5, "I2C2_SCL"),
+ STM32_FUNCTION(7, "DFSDM1_CKIN1"),
+ STM32_FUNCTION(8, "USART6_CK"),
+ STM32_FUNCTION(10, "SDMMC2_D0DIR"),
+ STM32_FUNCTION(12, "SDMMC1_D0DIR"),
+ STM32_FUNCTION(13, "FMC_A2"),
+ STM32_FUNCTION(14, "LCD_G4"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(83, "PF3"),
+ STM32_FUNCTION(0, "GPIOF3"),
+ STM32_FUNCTION(4, "LPTIM2_IN2"),
+ STM32_FUNCTION(5, "I2C5_SDA"),
+ STM32_FUNCTION(6, "SPI4_MISO I2S4_SDI"),
+ STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(13, "FMC_A3"),
+ STM32_FUNCTION(15, "LCD_G3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(84, "PF4"),
+ STM32_FUNCTION(0, "GPIOF4"),
+ STM32_FUNCTION(4, "USART2_RX"),
+ STM32_FUNCTION(11, "TSC_G3_IO3"),
+ STM32_FUNCTION(12, "ETH2_MII_RXD0 ETH2_RGMII_RXD0 ETH2_RMII_RXD0"),
+ STM32_FUNCTION(13, "FMC_A4"),
+ STM32_FUNCTION(14, "DCMIPP_D4"),
+ STM32_FUNCTION(15, "LCD_B6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(85, "PF5"),
+ STM32_FUNCTION(0, "GPIOF5"),
+ STM32_FUNCTION(1, "TRACED12"),
+ STM32_FUNCTION(5, "DFSDM1_CKIN0"),
+ STM32_FUNCTION(6, "I2C1_SMBA"),
+ STM32_FUNCTION(10, "LCD_G0"),
+ STM32_FUNCTION(13, "FMC_A5"),
+ STM32_FUNCTION(14, "DCMIPP_D11"),
+ STM32_FUNCTION(15, "LCD_R5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(86, "PF6"),
+ STM32_FUNCTION(0, "GPIOF6"),
+ STM32_FUNCTION(2, "TIM16_CH1"),
+ STM32_FUNCTION(6, "SPI5_NSS"),
+ STM32_FUNCTION(8, "UART7_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO2"),
+ STM32_FUNCTION(12, "ETH2_MII_TX_EN ETH2_RGMII_TX_CTL ETH2_RMII_TX_EN"),
+ STM32_FUNCTION(14, "LCD_R7"),
+ STM32_FUNCTION(15, "LCD_G4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(87, "PF7"),
+ STM32_FUNCTION(0, "GPIOF7"),
+ STM32_FUNCTION(2, "TIM17_CH1"),
+ STM32_FUNCTION(8, "UART7_TX"),
+ STM32_FUNCTION(9, "UART4_CTS"),
+ STM32_FUNCTION(11, "ETH1_RGMII_CLK125"),
+ STM32_FUNCTION(12, "ETH2_MII_TXD0 ETH2_RGMII_TXD0 ETH2_RMII_TXD0"),
+ STM32_FUNCTION(13, "FMC_A18"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(88, "PF8"),
+ STM32_FUNCTION(0, "GPIOF8"),
+ STM32_FUNCTION(2, "TIM16_CH1N"),
+ STM32_FUNCTION(3, "TIM4_CH3"),
+ STM32_FUNCTION(4, "TIM8_CH3"),
+ STM32_FUNCTION(7, "SAI1_SCK_B"),
+ STM32_FUNCTION(8, "USART6_TX"),
+ STM32_FUNCTION(10, "TIM13_CH1"),
+ STM32_FUNCTION(11, "QUADSPI_BK1_IO0"),
+ STM32_FUNCTION(14, "DCMIPP_D15"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(89, "PF9"),
+ STM32_FUNCTION(0, "GPIOF9"),
+ STM32_FUNCTION(2, "TIM17_CH1N"),
+ STM32_FUNCTION(3, "TIM1_CH1"),
+ STM32_FUNCTION(4, "DFSDM1_CKIN3"),
+ STM32_FUNCTION(7, "SAI1_D4"),
+ STM32_FUNCTION(8, "UART7_CTS"),
+ STM32_FUNCTION(9, "UART8_RX"),
+ STM32_FUNCTION(10, "TIM14_CH1"),
+ STM32_FUNCTION(11, "QUADSPI_BK1_IO1"),
+ STM32_FUNCTION(12, "QUADSPI_BK2_IO3"),
+ STM32_FUNCTION(13, "FMC_A9"),
+ STM32_FUNCTION(15, "LCD_B6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(90, "PF10"),
+ STM32_FUNCTION(0, "GPIOF10"),
+ STM32_FUNCTION(2, "TIM16_BKIN"),
+ STM32_FUNCTION(3, "SAI1_D3"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(6, "SPI5_NSS"),
+ STM32_FUNCTION(8, "USART6_RTS USART6_DE"),
+ STM32_FUNCTION(9, "UART7_RTS UART7_DE"),
+ STM32_FUNCTION(10, "QUADSPI_CLK"),
+ STM32_FUNCTION(14, "DCMIPP_HSYNC"),
+ STM32_FUNCTION(15, "LCD_B5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(91, "PF11"),
+ STM32_FUNCTION(0, "GPIOF11"),
+ STM32_FUNCTION(2, "USART2_TX"),
+ STM32_FUNCTION(3, "SAI1_D2"),
+ STM32_FUNCTION(4, "DFSDM1_CKIN3"),
+ STM32_FUNCTION(7, "SAI1_FS_A"),
+ STM32_FUNCTION(13, "ETH2_MII_RX_ER"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(92, "PF12"),
+ STM32_FUNCTION(0, "GPIOF12"),
+ STM32_FUNCTION(6, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "SAI1_SD_A"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(11, "ETH1_MII_TX_ER"),
+ STM32_FUNCTION(12, "ETH1_RGMII_CLK125"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(93, "PF13"),
+ STM32_FUNCTION(0, "GPIOF13"),
+ STM32_FUNCTION(2, "TIM2_ETR"),
+ STM32_FUNCTION(3, "SAI1_MCLK_B"),
+ STM32_FUNCTION(7, "DFSDM1_DATIN3"),
+ STM32_FUNCTION(8, "USART2_TX"),
+ STM32_FUNCTION(9, "UART5_RX"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(94, "PF14"),
+ STM32_FUNCTION(0, "GPIOF14"),
+ STM32_FUNCTION(1, "JTCK SWCLK"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(95, "PF15"),
+ STM32_FUNCTION(0, "GPIOF15"),
+ STM32_FUNCTION(1, "JTMS SWDIO"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(96, "PG0"),
+ STM32_FUNCTION(0, "GPIOG0"),
+ STM32_FUNCTION(10, "FDCAN2_TX"),
+ STM32_FUNCTION(11, "TSC_G4_IO2"),
+ STM32_FUNCTION(13, "FMC_A10"),
+ STM32_FUNCTION(14, "DCMIPP_PIXCLK"),
+ STM32_FUNCTION(15, "LCD_G5"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(97, "PG1"),
+ STM32_FUNCTION(0, "GPIOG1"),
+ STM32_FUNCTION(2, "LPTIM1_ETR"),
+ STM32_FUNCTION(3, "TIM4_ETR"),
+ STM32_FUNCTION(4, "SAI2_FS_A"),
+ STM32_FUNCTION(5, "I2C2_SMBA"),
+ STM32_FUNCTION(6, "SPI2_MISO I2S2_SDI"),
+ STM32_FUNCTION(7, "SAI2_D2"),
+ STM32_FUNCTION(10, "FDCAN2_TX"),
+ STM32_FUNCTION(11, "ETH2_MII_TXD2 ETH2_RGMII_TXD2"),
+ STM32_FUNCTION(13, "FMC_NBL0"),
+ STM32_FUNCTION(15, "LCD_G7"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(98, "PG2"),
+ STM32_FUNCTION(0, "GPIOG2"),
+ STM32_FUNCTION(2, "MCO2"),
+ STM32_FUNCTION(4, "TIM8_BKIN"),
+ STM32_FUNCTION(11, "SAI2_MCLK_B"),
+ STM32_FUNCTION(12, "ETH1_MDC"),
+ STM32_FUNCTION(14, "DCMIPP_D1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(99, "PG3"),
+ STM32_FUNCTION(0, "GPIOG3"),
+ STM32_FUNCTION(4, "TIM8_BKIN2"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(7, "SAI2_SD_B"),
+ STM32_FUNCTION(10, "FDCAN2_RX"),
+ STM32_FUNCTION(11, "ETH2_RGMII_GTX_CLK"),
+ STM32_FUNCTION(12, "ETH1_MDIO"),
+ STM32_FUNCTION(13, "FMC_A13"),
+ STM32_FUNCTION(14, "DCMIPP_D15"),
+ STM32_FUNCTION(15, "DCMIPP_D12"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(100, "PG4"),
+ STM32_FUNCTION(0, "GPIOG4"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(2, "TIM1_BKIN2"),
+ STM32_FUNCTION(5, "DFSDM1_CKIN3"),
+ STM32_FUNCTION(9, "USART3_RX"),
+ STM32_FUNCTION(11, "SDMMC2_D123DIR"),
+ STM32_FUNCTION(12, "LCD_VSYNC"),
+ STM32_FUNCTION(13, "FMC_A14"),
+ STM32_FUNCTION(14, "DCMIPP_D8"),
+ STM32_FUNCTION(15, "DCMIPP_D13"),
+ STM32_FUNCTION(16, "HDP1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(101, "PG5"),
+ STM32_FUNCTION(0, "GPIOG5"),
+ STM32_FUNCTION(2, "TIM17_CH1"),
+ STM32_FUNCTION(11, "ETH2_MDC"),
+ STM32_FUNCTION(12, "LCD_G4"),
+ STM32_FUNCTION(13, "FMC_A15"),
+ STM32_FUNCTION(14, "DCMIPP_VSYNC"),
+ STM32_FUNCTION(15, "DCMIPP_D3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(102, "PG6"),
+ STM32_FUNCTION(0, "GPIOG6"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(2, "TIM17_BKIN"),
+ STM32_FUNCTION(3, "TIM5_CH4"),
+ STM32_FUNCTION(4, "SAI2_D1"),
+ STM32_FUNCTION(5, "USART1_RX"),
+ STM32_FUNCTION(7, "SAI2_SD_A"),
+ STM32_FUNCTION(11, "SDMMC2_CMD"),
+ STM32_FUNCTION(12, "LCD_G0"),
+ STM32_FUNCTION(14, "LCD_DE"),
+ STM32_FUNCTION(15, "LCD_R7"),
+ STM32_FUNCTION(16, "HDP3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(103, "PG7"),
+ STM32_FUNCTION(0, "GPIOG7"),
+ STM32_FUNCTION(1, "TRACED8"),
+ STM32_FUNCTION(2, "TIM1_ETR"),
+ STM32_FUNCTION(6, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(9, "UART7_CTS"),
+ STM32_FUNCTION(11, "SDMMC2_CKIN"),
+ STM32_FUNCTION(12, "LCD_R1"),
+ STM32_FUNCTION(14, "LCD_R5"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(104, "PG8"),
+ STM32_FUNCTION(0, "GPIOG8"),
+ STM32_FUNCTION(2, "TIM2_CH1"),
+ STM32_FUNCTION(4, "TIM8_ETR"),
+ STM32_FUNCTION(6, "SPI5_MISO"),
+ STM32_FUNCTION(7, "SAI1_MCLK_B"),
+ STM32_FUNCTION(8, "LCD_B1"),
+ STM32_FUNCTION(9, "USART3_RTS USART3_DE"),
+ STM32_FUNCTION(10, "SPDIFRX_IN2"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO2"),
+ STM32_FUNCTION(12, "QUADSPI_BK1_IO3"),
+ STM32_FUNCTION(13, "FMC_NE2"),
+ STM32_FUNCTION(14, "ETH2_CLK"),
+ STM32_FUNCTION(15, "DCMIPP_D6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(105, "PG9"),
+ STM32_FUNCTION(0, "GPIOG9"),
+ STM32_FUNCTION(1, "DBTRGO"),
+ STM32_FUNCTION(5, "I2C2_SDA"),
+ STM32_FUNCTION(8, "USART6_RX"),
+ STM32_FUNCTION(9, "SPDIFRX_IN3"),
+ STM32_FUNCTION(10, "FDCAN1_RX"),
+ STM32_FUNCTION(11, "FMC_NE2"),
+ STM32_FUNCTION(13, "FMC_NCE"),
+ STM32_FUNCTION(14, "DCMIPP_VSYNC"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(106, "PG10"),
+ STM32_FUNCTION(0, "GPIOG10"),
+ STM32_FUNCTION(6, "SPI5_SCK"),
+ STM32_FUNCTION(7, "SAI1_SD_B"),
+ STM32_FUNCTION(9, "UART8_CTS"),
+ STM32_FUNCTION(10, "FDCAN1_TX"),
+ STM32_FUNCTION(11, "QUADSPI_BK2_IO1"),
+ STM32_FUNCTION(13, "FMC_NE3"),
+ STM32_FUNCTION(14, "DCMIPP_D2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(107, "PG11"),
+ STM32_FUNCTION(0, "GPIOG11"),
+ STM32_FUNCTION(5, "SAI2_D3"),
+ STM32_FUNCTION(6, "I2S2_MCK"),
+ STM32_FUNCTION(8, "USART3_TX"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(11, "ETH2_MII_TXD1 ETH2_RGMII_TXD1 ETH2_RMII_TXD1"),
+ STM32_FUNCTION(13, "FMC_A24"),
+ STM32_FUNCTION(14, "DCMIPP_D14"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(108, "PG12"),
+ STM32_FUNCTION(0, "GPIOG12"),
+ STM32_FUNCTION(2, "LPTIM1_IN1"),
+ STM32_FUNCTION(4, "TSC_G5_IO2"),
+ STM32_FUNCTION(5, "SAI2_SCK_A"),
+ STM32_FUNCTION(7, "SAI2_CK2"),
+ STM32_FUNCTION(8, "USART6_RTS USART6_DE"),
+ STM32_FUNCTION(9, "USART3_CTS"),
+ STM32_FUNCTION(11, "ETH2_PHY_INTN"),
+ STM32_FUNCTION(12, "ETH1_PHY_INTN"),
+ STM32_FUNCTION(13, "ETH2_MII_RX_DV ETH2_RGMII_RX_CTL ETH2_RMII_CRS_DV"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(109, "PG13"),
+ STM32_FUNCTION(0, "GPIOG13"),
+ STM32_FUNCTION(2, "LPTIM1_OUT"),
+ STM32_FUNCTION(8, "USART6_CTS USART6_NSS"),
+ STM32_FUNCTION(12, "ETH1_MII_TXD0 ETH1_RGMII_TXD0 ETH1_RMII_TXD0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(110, "PG14"),
+ STM32_FUNCTION(0, "GPIOG14"),
+ STM32_FUNCTION(2, "LPTIM1_ETR"),
+ STM32_FUNCTION(7, "SAI2_D1"),
+ STM32_FUNCTION(8, "USART6_TX"),
+ STM32_FUNCTION(11, "SAI2_SD_A"),
+ STM32_FUNCTION(12, "ETH1_MII_TXD1 ETH1_RGMII_TXD1 ETH1_RMII_TXD1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(111, "PG15"),
+ STM32_FUNCTION(0, "GPIOG15"),
+ STM32_FUNCTION(8, "USART6_CTS USART6_NSS"),
+ STM32_FUNCTION(9, "UART7_CTS"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO1"),
+ STM32_FUNCTION(11, "ETH2_PHY_INTN"),
+ STM32_FUNCTION(12, "LCD_B4"),
+ STM32_FUNCTION(14, "DCMIPP_D10"),
+ STM32_FUNCTION(15, "LCD_B3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(112, "PH0"),
+ STM32_FUNCTION(0, "GPIOH0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(113, "PH1"),
+ STM32_FUNCTION(0, "GPIOH1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(114, "PH2"),
+ STM32_FUNCTION(0, "GPIOH2"),
+ STM32_FUNCTION(2, "LPTIM1_IN2"),
+ STM32_FUNCTION(4, "TSC_G4_IO3"),
+ STM32_FUNCTION(7, "DCMIPP_D9"),
+ STM32_FUNCTION(8, "LCD_G1"),
+ STM32_FUNCTION(9, "UART7_TX"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO0"),
+ STM32_FUNCTION(11, "ETH2_MII_CRS"),
+ STM32_FUNCTION(12, "ETH1_MII_CRS"),
+ STM32_FUNCTION(13, "FMC_NE4"),
+ STM32_FUNCTION(14, "ETH2_RGMII_CLK125"),
+ STM32_FUNCTION(15, "LCD_B0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(115, "PH3"),
+ STM32_FUNCTION(0, "GPIOH3"),
+ STM32_FUNCTION(5, "I2C3_SCL"),
+ STM32_FUNCTION(6, "SPI5_MOSI"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO1"),
+ STM32_FUNCTION(11, "ETH1_MII_COL"),
+ STM32_FUNCTION(12, "LCD_R5"),
+ STM32_FUNCTION(13, "ETH2_MII_COL"),
+ STM32_FUNCTION(14, "QUADSPI_BK1_IO0"),
+ STM32_FUNCTION(15, "LCD_B4"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(116, "PH4"),
+ STM32_FUNCTION(0, "GPIOH4"),
+ STM32_FUNCTION(1, "JTDI"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(117, "PH5"),
+ STM32_FUNCTION(0, "GPIOH5"),
+ STM32_FUNCTION(1, "JTDO"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(118, "PH6"),
+ STM32_FUNCTION(0, "GPIOH6"),
+ STM32_FUNCTION(3, "TIM12_CH1"),
+ STM32_FUNCTION(4, "USART2_CK"),
+ STM32_FUNCTION(5, "I2C5_SDA"),
+ STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(10, "QUADSPI_BK1_IO2"),
+ STM32_FUNCTION(11, "ETH1_PHY_INTN"),
+ STM32_FUNCTION(12, "ETH1_MII_RX_ER"),
+ STM32_FUNCTION(13, "ETH2_MII_RXD2 ETH2_RGMII_RXD2"),
+ STM32_FUNCTION(14, "QUADSPI_BK1_NCS"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(119, "PH7"),
+ STM32_FUNCTION(0, "GPIOH7"),
+ STM32_FUNCTION(3, "SAI2_FS_B"),
+ STM32_FUNCTION(6, "I2C3_SDA"),
+ STM32_FUNCTION(7, "SPI5_SCK"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO3"),
+ STM32_FUNCTION(11, "ETH2_MII_TX_CLK"),
+ STM32_FUNCTION(12, "ETH1_MII_TX_CLK"),
+ STM32_FUNCTION(14, "QUADSPI_BK1_IO3"),
+ STM32_FUNCTION(15, "LCD_B2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(120, "PH8"),
+ STM32_FUNCTION(0, "GPIOH8"),
+ STM32_FUNCTION(1, "TRACED9"),
+ STM32_FUNCTION(3, "TIM5_ETR"),
+ STM32_FUNCTION(4, "USART2_RX"),
+ STM32_FUNCTION(5, "I2C3_SDA"),
+ STM32_FUNCTION(12, "LCD_R6"),
+ STM32_FUNCTION(13, "FMC_A8"),
+ STM32_FUNCTION(14, "DCMIPP_HSYNC"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "HDP2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(121, "PH9"),
+ STM32_FUNCTION(0, "GPIOH9"),
+ STM32_FUNCTION(2, "TIM1_CH4"),
+ STM32_FUNCTION(3, "TIM12_CH2"),
+ STM32_FUNCTION(4, "TSC_SYNC"),
+ STM32_FUNCTION(6, "SPI4_SCK I2S4_CK"),
+ STM32_FUNCTION(7, "DCMIPP_D13"),
+ STM32_FUNCTION(10, "LCD_B5"),
+ STM32_FUNCTION(12, "LCD_DE"),
+ STM32_FUNCTION(13, "FMC_A20"),
+ STM32_FUNCTION(14, "DCMIPP_D9"),
+ STM32_FUNCTION(15, "DCMIPP_D8"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(122, "PH10"),
+ STM32_FUNCTION(0, "GPIOH10"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(3, "TIM5_CH1"),
+ STM32_FUNCTION(4, "SAI2_D3"),
+ STM32_FUNCTION(5, "DFSDM1_DATIN2"),
+ STM32_FUNCTION(6, "I2S3_MCK"),
+ STM32_FUNCTION(7, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(8, "USART3_CTS USART3_NSS"),
+ STM32_FUNCTION(9, "SDMMC1_D4"),
+ STM32_FUNCTION(14, "LCD_HSYNC"),
+ STM32_FUNCTION(15, "LCD_R2"),
+ STM32_FUNCTION(16, "HDP0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(123, "PH11"),
+ STM32_FUNCTION(0, "GPIOH11"),
+ STM32_FUNCTION(2, "SPI5_NSS"),
+ STM32_FUNCTION(3, "TIM5_CH2"),
+ STM32_FUNCTION(4, "SAI2_SD_A"),
+ STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(7, "I2C4_SCL"),
+ STM32_FUNCTION(8, "USART6_RX"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO0"),
+ STM32_FUNCTION(12, "ETH2_MII_RX_CLK ETH2_RGMII_RX_CLK ETH2_RMII_REF_CLK"),
+ STM32_FUNCTION(13, "FMC_A12"),
+ STM32_FUNCTION(15, "LCD_G6"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(124, "PH12"),
+ STM32_FUNCTION(0, "GPIOH12"),
+ STM32_FUNCTION(2, "USART2_TX"),
+ STM32_FUNCTION(3, "TIM5_CH3"),
+ STM32_FUNCTION(4, "DFSDM1_CKIN1"),
+ STM32_FUNCTION(5, "I2C3_SCL"),
+ STM32_FUNCTION(6, "SPI5_MOSI"),
+ STM32_FUNCTION(7, "SAI1_SCK_A"),
+ STM32_FUNCTION(10, "QUADSPI_BK2_IO2"),
+ STM32_FUNCTION(11, "SAI1_CK2"),
+ STM32_FUNCTION(12, "ETH1_MII_CRS"),
+ STM32_FUNCTION(13, "FMC_A6"),
+ STM32_FUNCTION(14, "DCMIPP_D3"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(125, "PH13"),
+ STM32_FUNCTION(0, "GPIOH13"),
+ STM32_FUNCTION(1, "TRACED15"),
+ STM32_FUNCTION(3, "USART2_CK"),
+ STM32_FUNCTION(4, "TIM8_CH1N"),
+ STM32_FUNCTION(5, "I2C5_SCL"),
+ STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(9, "UART4_TX"),
+ STM32_FUNCTION(14, "LCD_G3"),
+ STM32_FUNCTION(15, "LCD_G2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(126, "PH14"),
+ STM32_FUNCTION(0, "GPIOH14"),
+ STM32_FUNCTION(4, "DFSDM1_DATIN2"),
+ STM32_FUNCTION(5, "I2C3_SDA"),
+ STM32_FUNCTION(7, "DCMIPP_D8"),
+ STM32_FUNCTION(9, "UART4_RX"),
+ STM32_FUNCTION(12, "LCD_B4"),
+ STM32_FUNCTION(14, "DCMIPP_D2"),
+ STM32_FUNCTION(15, "DCMIPP_PIXCLK"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(128, "PI0"),
+ STM32_FUNCTION(0, "GPIOI0"),
+ STM32_FUNCTION(9, "SPDIFRX_IN0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(129, "PI1"),
+ STM32_FUNCTION(0, "GPIOI1"),
+ STM32_FUNCTION(9, "SPDIFRX_IN1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(130, "PI2"),
+ STM32_FUNCTION(0, "GPIOI2"),
+ STM32_FUNCTION(9, "SPDIFRX_IN2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(131, "PI3"),
+ STM32_FUNCTION(0, "GPIOI3"),
+ STM32_FUNCTION(9, "SPDIFRX_IN3"),
+ STM32_FUNCTION(12, "ETH1_MII_RX_ER"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(132, "PI4"),
+ STM32_FUNCTION(0, "GPIOI4"),
+ STM32_FUNCTION(1, "BOOT0"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(133, "PI5"),
+ STM32_FUNCTION(0, "GPIOI5"),
+ STM32_FUNCTION(1, "BOOT1"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(134, "PI6"),
+ STM32_FUNCTION(0, "GPIOI6"),
+ STM32_FUNCTION(1, "BOOT2"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN(
+ PINCTRL_PIN(135, "PI7"),
+ STM32_FUNCTION(0, "GPIOI7"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+};
+
+static struct stm32_pinctrl_match_data stm32mp135_match_data = {
+ .pins = stm32mp135_pins,
+ .npins = ARRAY_SIZE(stm32mp135_pins),
+};
+
+static const struct of_device_id stm32mp135_pctrl_match[] = {
+ {
+ .compatible = "st,stm32mp135-pinctrl",
+ .data = &stm32mp135_match_data,
+ },
+ { }
+};
+
+static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume)
+};
+
+static struct platform_driver stm32mp135_pinctrl_driver = {
+ .probe = stm32_pctl_probe,
+ .driver = {
+ .name = "stm32mp135-pinctrl",
+ .of_match_table = stm32mp135_pctrl_match,
+ .pm = &stm32_pinctrl_dev_pm_ops,
+ },
+};
+
+static int __init stm32mp135_pinctrl_init(void)
+{
+ return platform_driver_register(&stm32mp135_pinctrl_driver);
+}
+arch_initcall(stm32mp135_pinctrl_init);
diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c
index 35883984251f..04bc3b50aa7a 100644
--- a/drivers/platform/mellanox/mlxbf-pmc.c
+++ b/drivers/platform/mellanox/mlxbf-pmc.c
@@ -79,7 +79,8 @@
#define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0)
/**
- * Structure to hold attribute and block info for each sysfs entry
+ * struct mlxbf_pmc_attribute - Structure to hold attribute and block info
+ * for each sysfs entry
* @dev_attr: Device attribute struct
* @index: index to identify counter number within a block
* @nr: block number to which the sysfs belongs
@@ -91,7 +92,7 @@ struct mlxbf_pmc_attribute {
};
/**
- * Structure to hold info for each HW block
+ * struct mlxbf_pmc_block_info - Structure to hold info for each HW block
*
* @mmio_base: The VA at which the PMC block is mapped
* @blk_size: Size of each mapped region
@@ -102,7 +103,7 @@ struct mlxbf_pmc_attribute {
* @attr_event_list: Attributes for "event_list" sysfs files
* @attr_enable: Attributes for "enable" sysfs files
* @block_attr: All attributes needed for the block
- * @blcok_attr_grp: Attribute group for the block
+ * @block_attr_grp: Attribute group for the block
*/
struct mlxbf_pmc_block_info {
void __iomem *mmio_base;
@@ -118,7 +119,7 @@ struct mlxbf_pmc_block_info {
};
/**
- * Structure to hold PMC context info
+ * struct mlxbf_pmc_context - Structure to hold PMC context info
*
* @pdev: The kernel structure representing the device
* @total_blocks: Total number of blocks
@@ -127,7 +128,7 @@ struct mlxbf_pmc_block_info {
* @block_name: Block name
* @block: Block info
* @groups: Attribute groups from each block
- * @sv_sreg_support: Whether SMCs are used to access performance registers
+ * @svc_sreg_support: Whether SMCs are used to access performance registers
* @sreg_tbl_perf: Secure register access table number
* @event_set: Event set to use
*/
@@ -145,7 +146,7 @@ struct mlxbf_pmc_context {
};
/**
- * Structure to hold supported events for each block
+ * struct mlxbf_pmc_events - Structure to hold supported events for each block
* @evt_num: Event number used to program counters
* @evt_name: Name of the event
*/
diff --git a/drivers/platform/surface/aggregator/Makefile b/drivers/platform/surface/aggregator/Makefile
index c8498c41e758..c0d550eda5cd 100644
--- a/drivers/platform/surface/aggregator/Makefile
+++ b/drivers/platform/surface/aggregator/Makefile
@@ -6,12 +6,9 @@ CFLAGS_core.o = -I$(src)
obj-$(CONFIG_SURFACE_AGGREGATOR) += surface_aggregator.o
-surface_aggregator-objs := core.o
-surface_aggregator-objs += ssh_parser.o
-surface_aggregator-objs += ssh_packet_layer.o
-surface_aggregator-objs += ssh_request_layer.o
-surface_aggregator-objs += controller.o
-
-ifeq ($(CONFIG_SURFACE_AGGREGATOR_BUS),y)
-surface_aggregator-objs += bus.o
-endif
+surface_aggregator-y := core.o
+surface_aggregator-y += ssh_parser.o
+surface_aggregator-y += ssh_packet_layer.o
+surface_aggregator-y += ssh_request_layer.o
+surface_aggregator-$(CONFIG_SURFACE_AGGREGATOR_BUS) += bus.o
+surface_aggregator-y += controller.o
diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
index 0169677c243e..0a40dd9c94ed 100644
--- a/drivers/platform/surface/aggregator/bus.c
+++ b/drivers/platform/surface/aggregator/bus.c
@@ -316,14 +316,12 @@ static int ssam_bus_probe(struct device *dev)
->probe(to_ssam_device(dev));
}
-static int ssam_bus_remove(struct device *dev)
+static void ssam_bus_remove(struct device *dev)
{
struct ssam_device_driver *sdrv = to_ssam_device_driver(dev->driver);
if (sdrv->remove)
sdrv->remove(to_ssam_device(dev));
-
- return 0;
}
struct bus_type ssam_bus_type = {
diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c
index 279d9df19c01..c61bbeeec2df 100644
--- a/drivers/platform/surface/aggregator/core.c
+++ b/drivers/platform/surface/aggregator/core.c
@@ -301,20 +301,13 @@ static acpi_status ssam_serdev_setup_via_acpi_crs(struct acpi_resource *rsc,
void *ctx)
{
struct serdev_device *serdev = ctx;
- struct acpi_resource_common_serialbus *serial;
struct acpi_resource_uart_serialbus *uart;
bool flow_control;
int status = 0;
- if (rsc->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
+ if (!serdev_acpi_get_uart_resource(rsc, &uart))
return AE_OK;
- serial = &rsc->data.common_serial_bus;
- if (serial->type != ACPI_RESOURCE_SERIAL_TYPE_UART)
- return AE_OK;
-
- uart = &rsc->data.uart_serial_bus;
-
/* Set up serdev device. */
serdev_device_set_baudrate(serdev, uart->default_baud_rate);
diff --git a/drivers/platform/surface/surface3_power.c b/drivers/platform/surface/surface3_power.c
index dea82aa1abd4..90c1568ea4e0 100644
--- a/drivers/platform/surface/surface3_power.c
+++ b/drivers/platform/surface/surface3_power.c
@@ -384,13 +384,7 @@ mshw0011_space_handler(u32 function, acpi_physical_address command,
if (ACPI_FAILURE(ret))
return ret;
- if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
- ret = AE_BAD_PARAMETER;
- goto err;
- }
-
- sb = &ares->data.i2c_serial_bus;
- if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+ if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) {
ret = AE_BAD_PARAMETER;
goto err;
}
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index d12db6c316ea..e21ea3d23e6f 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -77,28 +77,6 @@ config UV_SYSFS
To compile this driver as a module, choose M here: the module will
be called uv_sysfs.
-config INTEL_WMI_SBL_FW_UPDATE
- tristate "Intel WMI Slim Bootloader firmware update signaling driver"
- depends on ACPI_WMI
- help
- Say Y here if you want to be able to use the WMI interface to signal
- Slim Bootloader to trigger update on next reboot.
-
- To compile this driver as a module, choose M here: the module will
- be called intel-wmi-sbl-fw-update.
-
-config INTEL_WMI_THUNDERBOLT
- tristate "Intel WMI thunderbolt force power driver"
- depends on ACPI_WMI
- help
- Say Y here if you want to be able to use the WMI interface on select
- systems to force the power control of Intel Thunderbolt controllers.
- This is useful for updating the firmware when devices are not plugged
- into the controller.
-
- To compile this driver as a module, choose M here: the module will
- be called intel-wmi-thunderbolt.
-
config MXM_WMI
tristate "WMI support for MXM Laptop Graphics"
depends on ACPI_WMI
@@ -281,6 +259,7 @@ config ASUS_WMI
select INPUT_SPARSEKMAP
select LEDS_CLASS
select NEW_LEDS
+ select ACPI_PLATFORM_PROFILE
help
Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new
Asus Notebooks).
@@ -302,6 +281,19 @@ config ASUS_NB_WMI
If you have an ACPI-WMI compatible Asus Notebook, say Y or M
here.
+config MERAKI_MX100
+ tristate "Cisco Meraki MX100 Platform Driver"
+ depends on GPIOLIB
+ depends on GPIO_ICH
+ depends on LEDS_CLASS
+ select LEDS_GPIO
+ help
+ This driver provides support for the front button and LEDs on
+ the Cisco Meraki MX100 (Tinkerbell) 1U appliance.
+
+ To compile this driver as a module, choose M here: the module
+ will be called meraki-mx100.
+
config EEEPC_LAPTOP
tristate "Eee PC Hotkey Driver"
depends on ACPI
@@ -654,105 +646,6 @@ config THINKPAD_LMI
source "drivers/platform/x86/intel/Kconfig"
-config INTEL_ATOMISP2_LED
- tristate "Intel AtomISP2 camera LED driver"
- depends on GPIOLIB && LEDS_GPIO
- help
- Many Bay Trail and Cherry Trail devices come with a camera attached
- to Intel's Image Signal Processor. Linux currently does not have a
- driver for these, so they do not work as a camera. Some of these
- camera's have a LED which is controlled through a GPIO.
-
- Some of these devices have a firmware issue where the LED gets turned
- on at boot. This driver will turn the LED off at boot and also allows
- controlling the LED (repurposing it) through the sysfs LED interface.
-
- Which GPIO is attached to the LED is usually not described in the
- ACPI tables, so this driver contains per-system info about the GPIO
- inside the driver, this means that this driver only works on systems
- the driver knows about.
-
- To compile this driver as a module, choose M here: the module
- will be called intel_atomisp2_led.
-
-config INTEL_ATOMISP2_PM
- tristate "Intel AtomISP2 dummy / power-management driver"
- depends on PCI && IOSF_MBI && PM
- depends on !INTEL_ATOMISP
- help
- Power-management driver for Intel's Image Signal Processor found on
- Bay Trail and Cherry Trail devices. This dummy driver's sole purpose
- is to turn the ISP off (put it in D3) to save power and to allow
- entering of S0ix modes.
-
- To compile this driver as a module, choose M here: the module
- will be called intel_atomisp2_pm.
-
-config INTEL_HID_EVENT
- tristate "INTEL HID Event"
- depends on ACPI
- depends on INPUT
- depends on I2C
- select INPUT_SPARSEKMAP
- help
- This driver provides support for the Intel HID Event hotkey interface.
- Some laptops require this driver for hotkey support.
-
- To compile this driver as a module, choose M here: the module will
- be called intel_hid.
-
-config INTEL_INT0002_VGPIO
- tristate "Intel ACPI INT0002 Virtual GPIO driver"
- depends on GPIOLIB && ACPI && PM_SLEEP
- select GPIOLIB_IRQCHIP
- help
- Some peripherals on Bay Trail and Cherry Trail platforms signal a
- Power Management Event (PME) to the Power Management Controller (PMC)
- to wakeup the system. When this happens software needs to explicitly
- clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
- IRQ storm on IRQ 9.
-
- This is modelled in ACPI through the INT0002 ACPI device, which is
- called a "Virtual GPIO controller" in ACPI because it defines the
- event handler to call when the PME triggers through _AEI and _L02
- methods as would be done for a real GPIO interrupt in ACPI.
-
- To compile this driver as a module, choose M here: the module will
- be called intel_int0002_vgpio.
-
-config INTEL_MENLOW
- tristate "Thermal Management driver for Intel menlow platform"
- depends on ACPI_THERMAL
- select THERMAL
- help
- ACPI thermal management enhancement driver on
- Intel Menlow platform.
-
- If unsure, say N.
-
-config INTEL_OAKTRAIL
- tristate "Intel Oaktrail Platform Extras"
- depends on ACPI
- depends on ACPI_VIDEO || ACPI_VIDEO = n
- depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI
- help
- Intel Oaktrail platform need this driver to provide interfaces to
- enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
- here; it will only load on supported platforms.
-
-config INTEL_VBTN
- tristate "INTEL VIRTUAL BUTTON"
- depends on ACPI
- depends on INPUT
- depends on I2C
- select INPUT_SPARSEKMAP
- help
- This driver provides support for the Intel Virtual Button interface.
- Some laptops require this driver for power button support.
-
- To compile this driver as a module, choose M here: the module will
- be called intel_vbtn.
-
config MSI_LAPTOP
tristate "MSI Laptop Extras"
depends on ACPI
@@ -1106,150 +999,6 @@ config INTEL_IPS
functionality. If in doubt, say Y here; it will only load on
supported platforms.
-config INTEL_RST
- tristate "Intel Rapid Start Technology Driver"
- depends on ACPI
- help
- This driver provides support for modifying parameters on systems
- equipped with Intel's Rapid Start Technology. When put in an ACPI
- sleep state, these devices will wake after either a configured
- timeout or when the system battery reaches a critical state,
- automatically copying memory contents to disk. On resume, the
- firmware will copy the memory contents back to RAM and resume the OS
- as usual.
-
-config INTEL_SMARTCONNECT
- tristate "Intel Smart Connect disabling driver"
- depends on ACPI
- help
- Intel Smart Connect is a technology intended to permit devices to
- update state by resuming for a short period of time at regular
- intervals. If a user enables this functionality under Windows and
- then reboots into Linux, the system may remain configured to resume
- on suspend. In the absence of any userspace to support it, the system
- will then remain awake until something triggers another suspend.
-
- This driver checks to determine whether the device has Intel Smart
- Connect enabled, and if so disables it.
-
-source "drivers/platform/x86/intel_speed_select_if/Kconfig"
-
-config INTEL_TURBO_MAX_3
- bool "Intel Turbo Boost Max Technology 3.0 enumeration driver"
- depends on X86_64 && SCHED_MC_PRIO
- help
- This driver reads maximum performance ratio of each CPU and set up
- the scheduler priority metrics. In this way scheduler can prefer
- CPU with higher performance to schedule tasks.
- This driver is only required when the system is not using Hardware
- P-States (HWP). In HWP mode, priority can be read from ACPI tables.
-
-config INTEL_UNCORE_FREQ_CONTROL
- tristate "Intel Uncore frequency control driver"
- depends on X86_64
- help
- This driver allows control of uncore frequency limits on
- supported server platforms.
- Uncore frequency controls RING/LLC (last-level cache) clocks.
-
- To compile this driver as a module, choose M here: the module
- will be called intel-uncore-frequency.
-
-config INTEL_BXTWC_PMIC_TMU
- tristate "Intel BXT Whiskey Cove TMU Driver"
- depends on REGMAP
- depends on MFD_INTEL_PMC_BXT
- depends on INTEL_SOC_PMIC_BXTWC
- help
- Select this driver to use Intel BXT Whiskey Cove PMIC TMU feature.
- This driver enables the alarm wakeup functionality in the TMU unit
- of Whiskey Cove PMIC.
-
-config INTEL_CHTDC_TI_PWRBTN
- tristate "Intel Cherry Trail Dollar Cove TI power button driver"
- depends on INTEL_SOC_PMIC_CHTDC_TI
- depends on INPUT
- help
- This option adds a power button driver driver for Dollar Cove TI
- PMIC on Intel Cherry Trail devices.
-
- To compile this driver as a module, choose M here: the module
- will be called intel_chtdc_ti_pwrbtn.
-
-config INTEL_MRFLD_PWRBTN
- tristate "Intel Merrifield Basin Cove power button driver"
- depends on INTEL_SOC_PMIC_MRFLD
- depends on INPUT
- help
- This option adds a power button driver for Basin Cove PMIC
- on Intel Merrifield devices.
-
- To compile this driver as a module, choose M here: the module
- will be called intel_mrfld_pwrbtn.
-
-config INTEL_PMC_CORE
- tristate "Intel PMC Core driver"
- depends on PCI
- depends on ACPI
- help
- The Intel Platform Controller Hub for Intel Core SoCs provides access
- to Power Management Controller registers via various interfaces. This
- driver can utilize debugging capabilities and supported features as
- exposed by the Power Management Controller. It also may perform some
- tasks in the PMC in order to enable transition into the SLPS0 state.
- It should be selected on all Intel platforms supported by the driver.
-
- Supported features:
- - SLP_S0_RESIDENCY counter
- - PCH IP Power Gating status
- - LTR Ignore / LTR Show
- - MPHY/PLL gating status (Sunrisepoint PCH only)
- - SLPS0 Debug registers (Cannonlake/Icelake PCH)
- - Low Power Mode registers (Tigerlake and beyond)
- - PMC quirks as needed to enable SLPS0/S0ix
-
-config INTEL_PMT_CLASS
- tristate
- help
- The Intel Platform Monitoring Technology (PMT) class driver provides
- the basic sysfs interface and file hierarchy used by PMT devices.
-
- For more information, see:
- <file:Documentation/ABI/testing/sysfs-class-intel_pmt>
-
- To compile this driver as a module, choose M here: the module
- will be called intel_pmt_class.
-
-config INTEL_PMT_TELEMETRY
- tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver"
- depends on MFD_INTEL_PMT
- select INTEL_PMT_CLASS
- help
- The Intel Platform Monitory Technology (PMT) Telemetry driver provides
- access to hardware telemetry metrics on devices that support the
- feature.
-
- To compile this driver as a module, choose M here: the module
- will be called intel_pmt_telemetry.
-
-config INTEL_PMT_CRASHLOG
- tristate "Intel Platform Monitoring Technology (PMT) Crashlog driver"
- depends on MFD_INTEL_PMT
- select INTEL_PMT_CLASS
- help
- The Intel Platform Monitoring Technology (PMT) crashlog driver provides
- access to hardware crashlog capabilities on devices that support the
- feature.
-
- To compile this driver as a module, choose M here: the module
- will be called intel_pmt_crashlog.
-
-config INTEL_PUNIT_IPC
- tristate "Intel P-Unit IPC Driver"
- help
- This driver provides support for Intel P-Unit Mailbox IPC mechanism,
- which is used to bridge the communications between kernel and P-Unit.
-
config INTEL_SCU_IPC
bool
@@ -1297,18 +1046,6 @@ config INTEL_SCU_IPC_UTIL
low level access for debug work and updating the firmware. Say
N unless you will be doing this on an Intel MID platform.
-config INTEL_TELEMETRY
- tristate "Intel SoC Telemetry Driver"
- depends on X86_64
- depends on MFD_INTEL_PMC_BXT
- depends on INTEL_PUNIT_IPC
- help
- This driver provides interfaces to configure and use
- telemetry for INTEL SoC from APL onwards. It is also
- used to get various SoC events and parameters
- directly via debugfs files. Various tools may use
- this interface for SoC state monitoring.
-
endif # X86_PLATFORM_DEVICES
config PMC_ATOM
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 7ee369aab10d..69690e26bb6d 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -10,8 +10,6 @@ obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o
# WMI drivers
obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
-obj-$(CONFIG_INTEL_WMI_SBL_FW_UPDATE) += intel-wmi-sbl-fw-update.o
-obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
@@ -39,6 +37,9 @@ obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o
obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o
+# Cisco/Meraki
+obj-$(CONFIG_MERAKI_MX100) += meraki-mx100.o
+
# Dell
obj-$(CONFIG_X86_PLATFORM_DRIVERS_DELL) += dell/
@@ -68,14 +69,6 @@ obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o
# Intel
obj-$(CONFIG_X86_PLATFORM_DRIVERS_INTEL) += intel/
-obj-$(CONFIG_INTEL_ATOMISP2_LED) += intel_atomisp2_led.o
-obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o
-obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
-obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
-obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
-obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
-obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
-
# MSI
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
obj-$(CONFIG_MSI_WMI) += msi-wmi.o
@@ -118,27 +111,11 @@ obj-$(CONFIG_WIRELESS_HOTKEY) += wireless-hotkey.o
# Intel uncore drivers
obj-$(CONFIG_INTEL_IPS) += intel_ips.o
-obj-$(CONFIG_INTEL_RST) += intel-rst.o
-obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
-obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += intel_speed_select_if/
-obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
-obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o
# Intel PMIC / PMC / P-Unit devices
-obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o
-obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
-obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o
-obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o
-obj-$(CONFIG_INTEL_PMT_CLASS) += intel_pmt_class.o
-obj-$(CONFIG_INTEL_PMT_TELEMETRY) += intel_pmt_telemetry.o
-obj-$(CONFIG_INTEL_PMT_CRASHLOG) += intel_pmt_crashlog.o
-obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
obj-$(CONFIG_INTEL_SCU_PCI) += intel_scu_pcidrv.o
obj-$(CONFIG_INTEL_SCU_PLATFORM) += intel_scu_pltdrv.o
obj-$(CONFIG_INTEL_SCU_WDT) += intel_scu_wdt.o
obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
-obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \
- intel_telemetry_pltdrv.o \
- intel_telemetry_debugfs.o
obj-$(CONFIG_PMC_ATOM) += pmc_atom.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 85db9403cc14..694b45ed06a2 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -60,6 +60,11 @@ MODULE_LICENSE("GPL");
#define ACER_WMID_GET_THREEG_METHODID 10
#define ACER_WMID_SET_THREEG_METHODID 11
+#define ACER_WMID_SET_GAMING_LED_METHODID 2
+#define ACER_WMID_GET_GAMING_LED_METHODID 4
+#define ACER_WMID_SET_GAMING_FAN_BEHAVIOR 14
+#define ACER_WMID_SET_GAMING_MISC_SETTING_METHODID 22
+
/*
* Acer ACPI method GUIDs
*/
@@ -68,6 +73,7 @@ MODULE_LICENSE("GPL");
#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
#define WMID_GUID2 "95764E09-FB56-4E83-B31A-37761F60994A"
#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
+#define WMID_GUID4 "7A4DDFE7-5B5D-40B4-8595-4408E0CC7F56"
/*
* Acer ACPI event GUIDs
@@ -81,6 +87,7 @@ MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
enum acer_wmi_event_ids {
WMID_HOTKEY_EVENT = 0x1,
WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5,
+ WMID_GAMING_TURBO_KEY_EVENT = 0x7,
};
static const struct key_entry acer_wmi_keymap[] __initconst = {
@@ -215,6 +222,9 @@ struct hotkey_function_type_aa {
#define ACER_CAP_THREEG BIT(4)
#define ACER_CAP_SET_FUNCTION_MODE BIT(5)
#define ACER_CAP_KBD_DOCK BIT(6)
+#define ACER_CAP_TURBO_OC BIT(7)
+#define ACER_CAP_TURBO_LED BIT(8)
+#define ACER_CAP_TURBO_FAN BIT(9)
/*
* Interface type flags
@@ -301,6 +311,9 @@ struct quirk_entry {
u8 mailled;
s8 brightness;
u8 bluetooth;
+ u8 turbo;
+ u8 cpu_fans;
+ u8 gpu_fans;
};
static struct quirk_entry *quirks;
@@ -312,6 +325,10 @@ static void __init set_quirks(void)
if (quirks->brightness)
interface->capability |= ACER_CAP_BRIGHTNESS;
+
+ if (quirks->turbo)
+ interface->capability |= ACER_CAP_TURBO_OC | ACER_CAP_TURBO_LED
+ | ACER_CAP_TURBO_FAN;
}
static int __init dmi_matched(const struct dmi_system_id *dmi)
@@ -340,6 +357,12 @@ static struct quirk_entry quirk_acer_travelmate_2490 = {
.mailled = 1,
};
+static struct quirk_entry quirk_acer_predator_ph315_53 = {
+ .turbo = 1,
+ .cpu_fans = 1,
+ .gpu_fans = 1,
+};
+
/* This AMW0 laptop has no bluetooth */
static struct quirk_entry quirk_medion_md_98300 = {
.wireless = 1,
@@ -508,6 +531,15 @@ static const struct dmi_system_id acer_quirks[] __initconst = {
.driver_data = &quirk_acer_travelmate_2490,
},
{
+ .callback = dmi_matched,
+ .ident = "Acer Predator PH315-53",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH315-53"),
+ },
+ .driver_data = &quirk_acer_predator_ph315_53,
+ },
+ {
.callback = set_force_caps,
.ident = "Acer Aspire Switch 10E SW3-016",
.matches = {
@@ -1345,6 +1377,114 @@ static struct wmi_interface wmid_v2_interface = {
};
/*
+ * WMID Gaming interface
+ */
+
+static acpi_status
+WMI_gaming_execute_u64(u32 method_id, u64 in, u64 *out)
+{
+ struct acpi_buffer input = { (acpi_size) sizeof(u64), (void *)(&in) };
+ struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
+ u32 tmp = 0;
+ acpi_status status;
+
+ status = wmi_evaluate_method(WMID_GUID4, 0, method_id, &input, &result);
+
+ if (ACPI_FAILURE(status))
+ return status;
+ obj = (union acpi_object *) result.pointer;
+
+ if (obj) {
+ if (obj->type == ACPI_TYPE_BUFFER) {
+ if (obj->buffer.length == sizeof(u32))
+ tmp = *((u32 *) obj->buffer.pointer);
+ else if (obj->buffer.length == sizeof(u64))
+ tmp = *((u64 *) obj->buffer.pointer);
+ } else if (obj->type == ACPI_TYPE_INTEGER) {
+ tmp = (u64) obj->integer.value;
+ }
+ }
+
+ if (out)
+ *out = tmp;
+
+ kfree(result.pointer);
+
+ return status;
+}
+
+static acpi_status WMID_gaming_set_u64(u64 value, u32 cap)
+{
+ u32 method_id = 0;
+
+ if (!(interface->capability & cap))
+ return AE_BAD_PARAMETER;
+
+ switch (cap) {
+ case ACER_CAP_TURBO_LED:
+ method_id = ACER_WMID_SET_GAMING_LED_METHODID;
+ break;
+ case ACER_CAP_TURBO_FAN:
+ method_id = ACER_WMID_SET_GAMING_FAN_BEHAVIOR;
+ break;
+ case ACER_CAP_TURBO_OC:
+ method_id = ACER_WMID_SET_GAMING_MISC_SETTING_METHODID;
+ break;
+ default:
+ return AE_BAD_PARAMETER;
+ }
+
+ return WMI_gaming_execute_u64(method_id, value, NULL);
+}
+
+static acpi_status WMID_gaming_get_u64(u64 *value, u32 cap)
+{
+ acpi_status status;
+ u64 result;
+ u64 input;
+ u32 method_id;
+
+ if (!(interface->capability & cap))
+ return AE_BAD_PARAMETER;
+
+ switch (cap) {
+ case ACER_CAP_TURBO_LED:
+ method_id = ACER_WMID_GET_GAMING_LED_METHODID;
+ input = 0x1;
+ break;
+ default:
+ return AE_BAD_PARAMETER;
+ }
+ status = WMI_gaming_execute_u64(method_id, input, &result);
+ if (ACPI_SUCCESS(status))
+ *value = (u64) result;
+
+ return status;
+}
+
+static void WMID_gaming_set_fan_mode(u8 fan_mode)
+{
+ /* fan_mode = 1 is used for auto, fan_mode = 2 used for turbo*/
+ u64 gpu_fan_config1 = 0, gpu_fan_config2 = 0;
+ int i;
+
+ if (quirks->cpu_fans > 0)
+ gpu_fan_config2 |= 1;
+ for (i = 0; i < (quirks->cpu_fans + quirks->gpu_fans); ++i)
+ gpu_fan_config2 |= 1 << (i + 1);
+ for (i = 0; i < quirks->gpu_fans; ++i)
+ gpu_fan_config2 |= 1 << (i + 3);
+ if (quirks->cpu_fans > 0)
+ gpu_fan_config1 |= fan_mode;
+ for (i = 0; i < (quirks->cpu_fans + quirks->gpu_fans); ++i)
+ gpu_fan_config1 |= fan_mode << (2 * i + 2);
+ for (i = 0; i < quirks->gpu_fans; ++i)
+ gpu_fan_config1 |= fan_mode << (2 * i + 6);
+ WMID_gaming_set_u64(gpu_fan_config2 | gpu_fan_config1 << 16, ACER_CAP_TURBO_FAN);
+}
+
+/*
* Generic Device (interface-independent)
*/
@@ -1576,6 +1716,41 @@ static int acer_gsensor_event(void)
}
/*
+ * Predator series turbo button
+ */
+static int acer_toggle_turbo(void)
+{
+ u64 turbo_led_state;
+
+ /* Get current state from turbo button */
+ if (ACPI_FAILURE(WMID_gaming_get_u64(&turbo_led_state, ACER_CAP_TURBO_LED)))
+ return -1;
+
+ if (turbo_led_state) {
+ /* Turn off turbo led */
+ WMID_gaming_set_u64(0x1, ACER_CAP_TURBO_LED);
+
+ /* Set FAN mode to auto */
+ WMID_gaming_set_fan_mode(0x1);
+
+ /* Set OC to normal */
+ WMID_gaming_set_u64(0x5, ACER_CAP_TURBO_OC);
+ WMID_gaming_set_u64(0x7, ACER_CAP_TURBO_OC);
+ } else {
+ /* Turn on turbo led */
+ WMID_gaming_set_u64(0x10001, ACER_CAP_TURBO_LED);
+
+ /* Set FAN mode to turbo */
+ WMID_gaming_set_fan_mode(0x2);
+
+ /* Set OC to turbo mode */
+ WMID_gaming_set_u64(0x205, ACER_CAP_TURBO_OC);
+ WMID_gaming_set_u64(0x207, ACER_CAP_TURBO_OC);
+ }
+ return turbo_led_state;
+}
+
+/*
* Switch series keyboard dock status
*/
static int acer_kbd_dock_state_to_sw_tablet_mode(u8 kbd_dock_state)
@@ -1872,6 +2047,10 @@ static void acer_wmi_notify(u32 value, void *context)
acer_gsensor_event();
acer_kbd_dock_event(&return_value);
break;
+ case WMID_GAMING_TURBO_KEY_EVENT:
+ if (return_value.key_num == 0x4)
+ acer_toggle_turbo();
+ break;
default:
pr_warn("Unknown function number - %d - %d\n",
return_value.function, return_value.key_num);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index ebaeb7bb80f5..e14fb5fa7324 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -26,6 +26,7 @@
#include <linux/rfkill.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
+#include <linux/platform_profile.h>
#include <linux/power_supply.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
@@ -210,12 +211,24 @@ struct asus_wmi {
u8 fan_boost_mode_mask;
u8 fan_boost_mode;
+ bool egpu_enable_available; // 0 = enable
+ bool egpu_enable;
+
+ bool dgpu_disable_available;
+ bool dgpu_disable;
+
bool throttle_thermal_policy_available;
u8 throttle_thermal_policy_mode;
+ struct platform_profile_handler platform_profile_handler;
+ bool platform_profile_support;
+
// The RSOC controls the maximum charging percentage.
bool battery_rsoc_available;
+ bool panel_overdrive_available;
+ bool panel_overdrive;
+
struct hotplug_slot hotplug_slot;
struct mutex hotplug_lock;
struct mutex wmi_lock;
@@ -424,6 +437,181 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus)
}
}
+/* dGPU ********************************************************************/
+static int dgpu_disable_check_present(struct asus_wmi *asus)
+{
+ u32 result;
+ int err;
+
+ asus->dgpu_disable_available = false;
+
+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_DGPU, &result);
+ if (err) {
+ if (err == -ENODEV)
+ return 0;
+ return err;
+ }
+
+ if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
+ asus->dgpu_disable_available = true;
+ asus->dgpu_disable = result & ASUS_WMI_DSTS_STATUS_BIT;
+ }
+
+ return 0;
+}
+
+static int dgpu_disable_write(struct asus_wmi *asus)
+{
+ u32 retval;
+ u8 value;
+ int err;
+
+ /* Don't rely on type conversion */
+ value = asus->dgpu_disable ? 1 : 0;
+
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, value, &retval);
+ if (err) {
+ pr_warn("Failed to set dgpu disable: %d\n", err);
+ return err;
+ }
+
+ if (retval > 1) {
+ pr_warn("Failed to set dgpu disable (retval): 0x%x\n", retval);
+ return -EIO;
+ }
+
+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "dgpu_disable");
+
+ return 0;
+}
+
+static ssize_t dgpu_disable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+ u8 mode = asus->dgpu_disable;
+
+ return sysfs_emit(buf, "%d\n", mode);
+}
+
+/*
+ * A user may be required to store the value twice, typcial store first, then
+ * rescan PCI bus to activate power, then store a second time to save correctly.
+ * The reason for this is that an extra code path in the ACPI is enabled when
+ * the device and bus are powered.
+ */
+static ssize_t dgpu_disable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ bool disable;
+ int result;
+
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+
+ result = kstrtobool(buf, &disable);
+ if (result)
+ return result;
+
+ asus->dgpu_disable = disable;
+
+ result = dgpu_disable_write(asus);
+ if (result)
+ return result;
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(dgpu_disable);
+
+/* eGPU ********************************************************************/
+static int egpu_enable_check_present(struct asus_wmi *asus)
+{
+ u32 result;
+ int err;
+
+ asus->egpu_enable_available = false;
+
+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_EGPU, &result);
+ if (err) {
+ if (err == -ENODEV)
+ return 0;
+ return err;
+ }
+
+ if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
+ asus->egpu_enable_available = true;
+ asus->egpu_enable = result & ASUS_WMI_DSTS_STATUS_BIT;
+ }
+
+ return 0;
+}
+
+static int egpu_enable_write(struct asus_wmi *asus)
+{
+ u32 retval;
+ u8 value;
+ int err;
+
+ /* Don't rely on type conversion */
+ value = asus->egpu_enable ? 1 : 0;
+
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, value, &retval);
+
+ if (err) {
+ pr_warn("Failed to set egpu disable: %d\n", err);
+ return err;
+ }
+
+ if (retval > 1) {
+ pr_warn("Failed to set egpu disable (retval): 0x%x\n", retval);
+ return -EIO;
+ }
+
+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "egpu_enable");
+
+ return 0;
+}
+
+static ssize_t egpu_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+ bool mode = asus->egpu_enable;
+
+ return sysfs_emit(buf, "%d\n", mode);
+}
+
+/* The ACPI call to enable the eGPU also disables the internal dGPU */
+static ssize_t egpu_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ bool enable;
+ int result;
+
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+
+ result = kstrtobool(buf, &enable);
+ if (result)
+ return result;
+
+ asus->egpu_enable = enable;
+
+ result = egpu_enable_write(asus);
+ if (result)
+ return result;
+
+ /* Ensure that the kernel status of dgpu is updated */
+ result = dgpu_disable_check_present(asus);
+ if (result)
+ return result;
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(egpu_enable);
+
/* Battery ********************************************************************/
/* The battery maximum charging percentage */
@@ -1221,6 +1409,87 @@ exit:
return result;
}
+/* Panel Overdrive ************************************************************/
+static int panel_od_check_present(struct asus_wmi *asus)
+{
+ u32 result;
+ int err;
+
+ asus->panel_overdrive_available = false;
+
+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_PANEL_OD, &result);
+ if (err) {
+ if (err == -ENODEV)
+ return 0;
+ return err;
+ }
+
+ if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
+ asus->panel_overdrive_available = true;
+ asus->panel_overdrive = result & ASUS_WMI_DSTS_STATUS_BIT;
+ }
+
+ return 0;
+}
+
+static int panel_od_write(struct asus_wmi *asus)
+{
+ u32 retval;
+ u8 value;
+ int err;
+
+ /* Don't rely on type conversion */
+ value = asus->panel_overdrive ? 1 : 0;
+
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PANEL_OD, value, &retval);
+
+ if (err) {
+ pr_warn("Failed to set panel overdrive: %d\n", err);
+ return err;
+ }
+
+ if (retval > 1) {
+ pr_warn("Failed to set panel overdrive (retval): 0x%x\n", retval);
+ return -EIO;
+ }
+
+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "panel_od");
+
+ return 0;
+}
+
+static ssize_t panel_od_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d\n", asus->panel_overdrive);
+}
+
+static ssize_t panel_od_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ bool overdrive;
+ int result;
+
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+
+ result = kstrtobool(buf, &overdrive);
+ if (result)
+ return result;
+
+ asus->panel_overdrive = overdrive;
+ result = panel_od_write(asus);
+
+ if (result)
+ return result;
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(panel_od);
+
/* Quirks *********************************************************************/
static void asus_wmi_set_xusb2pr(struct asus_wmi *asus)
@@ -1838,12 +2107,23 @@ static int throttle_thermal_policy_set_default(struct asus_wmi *asus)
static int throttle_thermal_policy_switch_next(struct asus_wmi *asus)
{
u8 new_mode = asus->throttle_thermal_policy_mode + 1;
+ int err;
if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
asus->throttle_thermal_policy_mode = new_mode;
- return throttle_thermal_policy_write(asus);
+ err = throttle_thermal_policy_write(asus);
+ if (err)
+ return err;
+
+ /*
+ * Ensure that platform_profile updates userspace with the change to ensure
+ * that platform_profile and throttle_thermal_policy_mode are in sync.
+ */
+ platform_profile_notify();
+
+ return 0;
}
static ssize_t throttle_thermal_policy_show(struct device *dev,
@@ -1859,9 +2139,10 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- int result;
- u8 new_mode;
struct asus_wmi *asus = dev_get_drvdata(dev);
+ u8 new_mode;
+ int result;
+ int err;
result = kstrtou8(buf, 10, &new_mode);
if (result < 0)
@@ -1871,7 +2152,15 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
return -EINVAL;
asus->throttle_thermal_policy_mode = new_mode;
- throttle_thermal_policy_write(asus);
+ err = throttle_thermal_policy_write(asus);
+ if (err)
+ return err;
+
+ /*
+ * Ensure that platform_profile updates userspace with the change to ensure
+ * that platform_profile and throttle_thermal_policy_mode are in sync.
+ */
+ platform_profile_notify();
return count;
}
@@ -1879,6 +2168,91 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
// Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent
static DEVICE_ATTR_RW(throttle_thermal_policy);
+/* Platform profile ***********************************************************/
+static int platform_profile_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ struct asus_wmi *asus;
+ int tp;
+
+ asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
+
+ tp = asus->throttle_thermal_policy_mode;
+
+ switch (tp) {
+ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case ASUS_THROTTLE_THERMAL_POLICY_SILENT:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int platform_profile_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ struct asus_wmi *asus;
+ int tp;
+
+ asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
+
+ switch (profile) {
+ case PLATFORM_PROFILE_PERFORMANCE:
+ tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
+ break;
+ case PLATFORM_PROFILE_BALANCED:
+ tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
+ break;
+ case PLATFORM_PROFILE_QUIET:
+ tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ asus->throttle_thermal_policy_mode = tp;
+ return throttle_thermal_policy_write(asus);
+}
+
+static int platform_profile_setup(struct asus_wmi *asus)
+{
+ struct device *dev = &asus->platform_device->dev;
+ int err;
+
+ /*
+ * Not an error if a component platform_profile relies on is unavailable
+ * so early return, skipping the setup of platform_profile.
+ */
+ if (!asus->throttle_thermal_policy_available)
+ return 0;
+
+ dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
+
+ asus->platform_profile_handler.profile_get = platform_profile_get;
+ asus->platform_profile_handler.profile_set = platform_profile_set;
+
+ set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);
+ set_bit(PLATFORM_PROFILE_BALANCED,
+ asus->platform_profile_handler.choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE,
+ asus->platform_profile_handler.choices);
+
+ err = platform_profile_register(&asus->platform_profile_handler);
+ if (err)
+ return err;
+
+ asus->platform_profile_support = true;
+ return 0;
+}
+
/* Backlight ******************************************************************/
static int read_backlight_power(struct asus_wmi *asus)
@@ -2328,10 +2702,13 @@ static struct attribute *platform_attributes[] = {
&dev_attr_camera.attr,
&dev_attr_cardr.attr,
&dev_attr_touchpad.attr,
+ &dev_attr_egpu_enable.attr,
+ &dev_attr_dgpu_disable.attr,
&dev_attr_lid_resume.attr,
&dev_attr_als_enable.attr,
&dev_attr_fan_boost_mode.attr,
&dev_attr_throttle_thermal_policy.attr,
+ &dev_attr_panel_od.attr,
NULL
};
@@ -2353,10 +2730,16 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
devid = ASUS_WMI_DEVID_LID_RESUME;
else if (attr == &dev_attr_als_enable.attr)
devid = ASUS_WMI_DEVID_ALS_ENABLE;
+ else if (attr == &dev_attr_egpu_enable.attr)
+ ok = asus->egpu_enable_available;
+ else if (attr == &dev_attr_dgpu_disable.attr)
+ ok = asus->dgpu_disable_available;
else if (attr == &dev_attr_fan_boost_mode.attr)
ok = asus->fan_boost_mode_available;
else if (attr == &dev_attr_throttle_thermal_policy.attr)
ok = asus->throttle_thermal_policy_available;
+ else if (attr == &dev_attr_panel_od.attr)
+ ok = asus->panel_overdrive_available;
if (devid != -1)
ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
@@ -2612,6 +2995,14 @@ static int asus_wmi_add(struct platform_device *pdev)
if (err)
goto fail_platform;
+ err = egpu_enable_check_present(asus);
+ if (err)
+ goto fail_egpu_enable;
+
+ err = dgpu_disable_check_present(asus);
+ if (err)
+ goto fail_dgpu_disable;
+
err = fan_boost_mode_check_present(asus);
if (err)
goto fail_fan_boost_mode;
@@ -2622,6 +3013,14 @@ static int asus_wmi_add(struct platform_device *pdev)
else
throttle_thermal_policy_set_default(asus);
+ err = platform_profile_setup(asus);
+ if (err)
+ goto fail_platform_profile_setup;
+
+ err = panel_od_check_present(asus);
+ if (err)
+ goto fail_panel_od;
+
err = asus_wmi_sysfs_init(asus->platform_device);
if (err)
goto fail_sysfs;
@@ -2707,8 +3106,14 @@ fail_input:
asus_wmi_sysfs_exit(asus->platform_device);
fail_sysfs:
fail_throttle_thermal_policy:
+fail_platform_profile_setup:
+ if (asus->platform_profile_support)
+ platform_profile_remove();
fail_fan_boost_mode:
+fail_egpu_enable:
+fail_dgpu_disable:
fail_platform:
+fail_panel_od:
kfree(asus);
return err;
}
@@ -2728,6 +3133,9 @@ static int asus_wmi_remove(struct platform_device *device)
asus_fan_set_auto(asus);
asus_wmi_battery_exit(asus);
+ if (asus->platform_profile_support)
+ platform_profile_remove();
+
kfree(asus);
return 0;
}
diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
index 9e7314d90bea..821aba31821c 100644
--- a/drivers/platform/x86/dell/Kconfig
+++ b/drivers/platform/x86/dell/Kconfig
@@ -140,7 +140,7 @@ config DELL_SMBIOS_SMM
config DELL_SMO8800
tristate "Dell Latitude freefall driver (ACPI SMO88XX)"
default m
- depends on ACPI
+ depends on ACPI || COMPILE_TEST
help
Say Y here if you want to support SMO88XX freefall devices
on Dell Latitude laptops.
diff --git a/drivers/platform/x86/dell/dcdbas.c b/drivers/platform/x86/dell/dcdbas.c
index 28447c180be8..5e63d6225048 100644
--- a/drivers/platform/x86/dell/dcdbas.c
+++ b/drivers/platform/x86/dell/dcdbas.c
@@ -278,9 +278,9 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd)
}
/* SMI requires CPU 0 */
- get_online_cpus();
+ cpus_read_lock();
ret = smp_call_on_cpu(0, raise_smi, smi_cmd, true);
- put_online_cpus();
+ cpus_read_unlock();
return ret;
}
diff --git a/drivers/platform/x86/dell/dell-smbios-smm.c b/drivers/platform/x86/dell/dell-smbios-smm.c
index 97c52a839a3e..320c032418ac 100644
--- a/drivers/platform/x86/dell/dell-smbios-smm.c
+++ b/drivers/platform/x86/dell/dell-smbios-smm.c
@@ -24,37 +24,6 @@ static struct calling_interface_buffer *buffer;
static struct platform_device *platform_device;
static DEFINE_MUTEX(smm_mutex);
-static const struct dmi_system_id dell_device_table[] __initconst = {
- {
- .ident = "Dell laptop",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
- },
- },
- {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/
- },
- },
- {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /*Notebook*/
- },
- },
- {
- .ident = "Dell Computer Corporation",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
- DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
- },
- },
- { }
-};
-MODULE_DEVICE_TABLE(dmi, dell_device_table);
-
static void parse_da_table(const struct dmi_header *dm)
{
struct calling_interface_structure *table =
diff --git a/drivers/platform/x86/dell/dell-smbios-wmi.c b/drivers/platform/x86/dell/dell-smbios-wmi.c
index 33f823772733..931cc50136de 100644
--- a/drivers/platform/x86/dell/dell-smbios-wmi.c
+++ b/drivers/platform/x86/dell/dell-smbios-wmi.c
@@ -69,9 +69,10 @@ static int run_smbios_call(struct wmi_device *wdev)
if (obj->type == ACPI_TYPE_INTEGER)
dev_dbg(&wdev->dev, "SMBIOS call failed: %llu\n",
obj->integer.value);
+ kfree(output.pointer);
return -EIO;
}
- memcpy(&priv->buf->std, obj->buffer.pointer, obj->buffer.length);
+ memcpy(input.pointer, obj->buffer.pointer, obj->buffer.length);
dev_dbg(&wdev->dev, "result: [%08x,%08x,%08x,%08x]\n",
priv->buf->std.output[0], priv->buf->std.output[1],
priv->buf->std.output[2], priv->buf->std.output[3]);
diff --git a/drivers/platform/x86/dell/dell-smo8800.c b/drivers/platform/x86/dell/dell-smo8800.c
index 5d9304a7de1b..3385e852104c 100644
--- a/drivers/platform/x86/dell/dell-smo8800.c
+++ b/drivers/platform/x86/dell/dell-smo8800.c
@@ -10,13 +10,14 @@
#define DRIVER_NAME "smo8800"
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/acpi.h>
+#include <linux/fs.h>
#include <linux/interrupt.h>
+#include <linux/kernel.h>
#include <linux/miscdevice.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/uaccess.h>
-#include <linux/fs.h>
struct smo8800_device {
u32 irq; /* acpi device irq */
@@ -44,37 +45,6 @@ static irqreturn_t smo8800_interrupt_thread(int irq, void *data)
return IRQ_HANDLED;
}
-static acpi_status smo8800_get_resource(struct acpi_resource *resource,
- void *context)
-{
- struct acpi_resource_extended_irq *irq;
-
- if (resource->type != ACPI_RESOURCE_TYPE_EXTENDED_IRQ)
- return AE_OK;
-
- irq = &resource->data.extended_irq;
- if (!irq || !irq->interrupt_count)
- return AE_OK;
-
- *((u32 *)context) = irq->interrupts[0];
- return AE_CTRL_TERMINATE;
-}
-
-static u32 smo8800_get_irq(struct acpi_device *device)
-{
- u32 irq = 0;
- acpi_status status;
-
- status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- smo8800_get_resource, &irq);
- if (ACPI_FAILURE(status)) {
- dev_err(&device->dev, "acpi_walk_resources failed\n");
- return 0;
- }
-
- return irq;
-}
-
static ssize_t smo8800_misc_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
@@ -136,7 +106,7 @@ static const struct file_operations smo8800_misc_fops = {
.release = smo8800_misc_release,
};
-static int smo8800_add(struct acpi_device *device)
+static int smo8800_probe(struct platform_device *device)
{
int err;
struct smo8800_device *smo8800;
@@ -160,14 +130,12 @@ static int smo8800_add(struct acpi_device *device)
return err;
}
- device->driver_data = smo8800;
+ platform_set_drvdata(device, smo8800);
- smo8800->irq = smo8800_get_irq(device);
- if (!smo8800->irq) {
- dev_err(&device->dev, "failed to obtain IRQ\n");
- err = -EINVAL;
+ err = platform_get_irq(device, 0);
+ if (err < 0)
goto error;
- }
+ smo8800->irq = err;
err = request_threaded_irq(smo8800->irq, smo8800_interrupt_quick,
smo8800_interrupt_thread,
@@ -189,9 +157,9 @@ error:
return err;
}
-static int smo8800_remove(struct acpi_device *device)
+static int smo8800_remove(struct platform_device *device)
{
- struct smo8800_device *smo8800 = device->driver_data;
+ struct smo8800_device *smo8800 = platform_get_drvdata(device);
free_irq(smo8800->irq, smo8800);
misc_deregister(&smo8800->miscdev);
@@ -211,21 +179,17 @@ static const struct acpi_device_id smo8800_ids[] = {
{ "SMO8831", 0 },
{ "", 0 },
};
-
MODULE_DEVICE_TABLE(acpi, smo8800_ids);
-static struct acpi_driver smo8800_driver = {
- .name = DRIVER_NAME,
- .class = "Latitude",
- .ids = smo8800_ids,
- .ops = {
- .add = smo8800_add,
- .remove = smo8800_remove,
+static struct platform_driver smo8800_driver = {
+ .probe = smo8800_probe,
+ .remove = smo8800_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .acpi_match_table = smo8800_ids,
},
- .owner = THIS_MODULE,
};
-
-module_acpi_driver(smo8800_driver);
+module_platform_driver(smo8800_driver);
MODULE_DESCRIPTION("Dell Latitude freefall driver (ACPI SMO88XX)");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dual_accel_detect.h b/drivers/platform/x86/dual_accel_detect.h
index a9eae17cc43d..72e9624331c8 100644
--- a/drivers/platform/x86/dual_accel_detect.h
+++ b/drivers/platform/x86/dual_accel_detect.h
@@ -17,30 +17,6 @@
#include <linux/acpi.h>
#include <linux/i2c.h>
-static int dual_accel_i2c_resource_count(struct acpi_resource *ares, void *data)
-{
- struct acpi_resource_i2c_serialbus *sb;
- int *count = data;
-
- if (i2c_acpi_get_i2c_resource(ares, &sb))
- *count = *count + 1;
-
- return 1;
-}
-
-static int dual_accel_i2c_client_count(struct acpi_device *adev)
-{
- int ret, count = 0;
- LIST_HEAD(r);
-
- ret = acpi_dev_get_resources(adev, &r, dual_accel_i2c_resource_count, &count);
- if (ret < 0)
- return ret;
-
- acpi_dev_free_resource_list(&r);
- return count;
-}
-
static bool dual_accel_detect_bosc0200(void)
{
struct acpi_device *adev;
@@ -50,7 +26,7 @@ static bool dual_accel_detect_bosc0200(void)
if (!adev)
return false;
- count = dual_accel_i2c_client_count(adev);
+ count = i2c_acpi_client_count(adev);
acpi_dev_put(adev);
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 8c0867bda828..cc53f725c041 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -28,9 +28,6 @@
#include <linux/serio.h>
#include "../../misc/lis3lv02d/lis3lv02d.h"
-#define DRIVER_NAME "hp_accel"
-#define ACPI_MDPS_CLASS "accelerometer"
-
/* Delayed LEDs infrastructure ------------------------------------ */
/* Special LED class that can defer work */
@@ -78,23 +75,14 @@ static const struct acpi_device_id lis3lv02d_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
-
/**
- * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
+ * lis3lv02d_acpi_init - initialize the device for ACPI
* @lis3: pointer to the device struct
*
* Returns 0 on success.
*/
static int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
{
- struct acpi_device *dev = lis3->bus_priv;
- if (!lis3->init_required)
- return 0;
-
- if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
- NULL, NULL) != AE_OK)
- return -EINVAL;
-
return 0;
}
@@ -278,30 +266,6 @@ static struct delayed_led_classdev hpled_led = {
.set_brightness = hpled_set,
};
-static acpi_status
-lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
-{
- if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
- struct acpi_resource_extended_irq *irq;
- u32 *device_irq = context;
-
- irq = &resource->data.extended_irq;
- *device_irq = irq->interrupts[0];
- }
-
- return AE_OK;
-}
-
-static void lis3lv02d_enum_resources(struct acpi_device *device)
-{
- acpi_status status;
-
- status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- lis3lv02d_get_resource, &lis3_dev.irq);
- if (ACPI_FAILURE(status))
- printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
-}
-
static bool hp_accel_i8042_filter(unsigned char data, unsigned char str,
struct serio *port)
{
@@ -331,23 +295,19 @@ static bool hp_accel_i8042_filter(unsigned char data, unsigned char str,
return false;
}
-static int lis3lv02d_add(struct acpi_device *device)
+static int lis3lv02d_probe(struct platform_device *device)
{
int ret;
- if (!device)
- return -EINVAL;
-
- lis3_dev.bus_priv = device;
+ lis3_dev.bus_priv = ACPI_COMPANION(&device->dev);
lis3_dev.init = lis3lv02d_acpi_init;
lis3_dev.read = lis3lv02d_acpi_read;
lis3_dev.write = lis3lv02d_acpi_write;
- strcpy(acpi_device_name(device), DRIVER_NAME);
- strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
- device->driver_data = &lis3_dev;
/* obtain IRQ number of our device from ACPI */
- lis3lv02d_enum_resources(device);
+ ret = platform_get_irq_optional(device, 0);
+ if (ret > 0)
+ lis3_dev.irq = ret;
/* If possible use a "standard" axes order */
if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
@@ -359,7 +319,6 @@ static int lis3lv02d_add(struct acpi_device *device)
}
/* call the core layer do its init */
- lis3_dev.init_required = true;
ret = lis3lv02d_init_device(&lis3_dev);
if (ret)
return ret;
@@ -381,11 +340,8 @@ static int lis3lv02d_add(struct acpi_device *device)
return ret;
}
-static int lis3lv02d_remove(struct acpi_device *device)
+static int lis3lv02d_remove(struct platform_device *device)
{
- if (!device)
- return -EINVAL;
-
i8042_remove_filter(hp_accel_i8042_filter);
lis3lv02d_joystick_disable(&lis3_dev);
lis3lv02d_poweroff(&lis3_dev);
@@ -396,7 +352,6 @@ static int lis3lv02d_remove(struct acpi_device *device)
return lis3lv02d_remove_fs(&lis3_dev);
}
-
#ifdef CONFIG_PM_SLEEP
static int lis3lv02d_suspend(struct device *dev)
{
@@ -407,14 +362,12 @@ static int lis3lv02d_suspend(struct device *dev)
static int lis3lv02d_resume(struct device *dev)
{
- lis3_dev.init_required = false;
lis3lv02d_poweron(&lis3_dev);
return 0;
}
static int lis3lv02d_restore(struct device *dev)
{
- lis3_dev.init_required = true;
lis3lv02d_poweron(&lis3_dev);
return 0;
}
@@ -434,17 +387,16 @@ static const struct dev_pm_ops hp_accel_pm = {
#endif
/* For the HP MDPS aka 3D Driveguard */
-static struct acpi_driver lis3lv02d_driver = {
- .name = DRIVER_NAME,
- .class = ACPI_MDPS_CLASS,
- .ids = lis3lv02d_device_ids,
- .ops = {
- .add = lis3lv02d_add,
- .remove = lis3lv02d_remove,
+static struct platform_driver lis3lv02d_driver = {
+ .probe = lis3lv02d_probe,
+ .remove = lis3lv02d_remove,
+ .driver = {
+ .name = "hp_accel",
+ .pm = HP_ACCEL_PM,
+ .acpi_match_table = lis3lv02d_device_ids,
},
- .drv.pm = HP_ACCEL_PM,
};
-module_acpi_driver(lis3lv02d_driver);
+module_platform_driver(lis3lv02d_driver);
MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
index 2cce82579d09..a50153ecd560 100644
--- a/drivers/platform/x86/i2c-multi-instantiate.c
+++ b/drivers/platform/x86/i2c-multi-instantiate.c
@@ -32,31 +32,6 @@ struct i2c_multi_inst_data {
struct i2c_client *clients[];
};
-static int i2c_multi_inst_count(struct acpi_resource *ares, void *data)
-{
- struct acpi_resource_i2c_serialbus *sb;
- int *count = data;
-
- if (i2c_acpi_get_i2c_resource(ares, &sb))
- *count = *count + 1;
-
- return 1;
-}
-
-static int i2c_multi_inst_count_resources(struct acpi_device *adev)
-{
- LIST_HEAD(r);
- int count = 0;
- int ret;
-
- ret = acpi_dev_get_resources(adev, &r, i2c_multi_inst_count, &count);
- if (ret < 0)
- return ret;
-
- acpi_dev_free_resource_list(&r);
- return count;
-}
-
static int i2c_multi_inst_probe(struct platform_device *pdev)
{
struct i2c_multi_inst_data *multi;
@@ -76,7 +51,7 @@ static int i2c_multi_inst_probe(struct platform_device *pdev)
adev = ACPI_COMPANION(dev);
/* Count number of clients to instantiate */
- ret = i2c_multi_inst_count_resources(adev);
+ ret = i2c_acpi_client_count(adev);
if (ret < 0)
return ret;
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 784326bd72f0..e7a1299e3776 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -41,6 +41,7 @@
static const char *const ideapad_wmi_fnesc_events[] = {
"26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", /* Yoga 3 */
"56322276-8493-4CE8-A783-98C991274F5E", /* Yoga 700 */
+ "8FC0DE0C-B4E4-43FD-B0F3-8871711C1294", /* Legion 5 */
};
#endif
@@ -1459,11 +1460,19 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
static void ideapad_wmi_notify(u32 value, void *context)
{
struct ideapad_private *priv = context;
+ unsigned long result;
switch (value) {
case 128:
ideapad_input_report(priv, value);
break;
+ case 208:
+ if (!eval_hals(priv->adev->handle, &result)) {
+ bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result);
+
+ exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
+ }
+ break;
default:
dev_info(&priv->platform_device->dev,
"Unknown WMI event: %u\n", value);
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index f2eef337eb98..0b21468e1bd0 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -16,7 +16,156 @@ menuconfig X86_PLATFORM_DRIVERS_INTEL
if X86_PLATFORM_DRIVERS_INTEL
+source "drivers/platform/x86/intel/atomisp2/Kconfig"
+source "drivers/platform/x86/intel/int1092/Kconfig"
source "drivers/platform/x86/intel/int33fe/Kconfig"
source "drivers/platform/x86/intel/int3472/Kconfig"
+source "drivers/platform/x86/intel/pmc/Kconfig"
+source "drivers/platform/x86/intel/pmt/Kconfig"
+source "drivers/platform/x86/intel/speed_select_if/Kconfig"
+source "drivers/platform/x86/intel/telemetry/Kconfig"
+source "drivers/platform/x86/intel/wmi/Kconfig"
+
+config INTEL_HID_EVENT
+ tristate "Intel HID Event"
+ depends on ACPI
+ depends on INPUT
+ depends on I2C
+ select INPUT_SPARSEKMAP
+ help
+ This driver provides support for the Intel HID Event hotkey interface.
+ Some laptops require this driver for hotkey support.
+
+ To compile this driver as a module, choose M here: the module will
+ be called intel_hid.
+
+config INTEL_VBTN
+ tristate "Intel Virtual Button"
+ depends on ACPI
+ depends on INPUT
+ depends on I2C
+ select INPUT_SPARSEKMAP
+ help
+ This driver provides support for the Intel Virtual Button interface.
+ Some laptops require this driver for power button support.
+
+ To compile this driver as a module, choose M here: the module will
+ be called intel_vbtn.
+
+config INTEL_INT0002_VGPIO
+ tristate "Intel ACPI INT0002 Virtual GPIO driver"
+ depends on GPIOLIB && ACPI && PM_SLEEP
+ select GPIOLIB_IRQCHIP
+ help
+ Some peripherals on Bay Trail and Cherry Trail platforms signal a
+ Power Management Event (PME) to the Power Management Controller (PMC)
+ to wakeup the system. When this happens software needs to explicitly
+ clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
+ IRQ storm on IRQ 9.
+
+ This is modelled in ACPI through the INT0002 ACPI device, which is
+ called a "Virtual GPIO controller" in ACPI because it defines the
+ event handler to call when the PME triggers through _AEI and _L02
+ methods as would be done for a real GPIO interrupt in ACPI.
+
+ To compile this driver as a module, choose M here: the module will
+ be called intel_int0002_vgpio.
+
+config INTEL_OAKTRAIL
+ tristate "Intel Oaktrail Platform Extras"
+ depends on ACPI
+ depends on ACPI_VIDEO || ACPI_VIDEO=n
+ depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI
+ help
+ Intel Oaktrail platform need this driver to provide interfaces to
+ enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
+ here; it will only load on supported platforms.
+
+config INTEL_BXTWC_PMIC_TMU
+ tristate "Intel Broxton Whiskey Cove TMU Driver"
+ depends on INTEL_SOC_PMIC_BXTWC
+ depends on MFD_INTEL_PMC_BXT
+ select REGMAP
+ help
+ Select this driver to use Intel Broxton Whiskey Cove PMIC TMU feature.
+ This driver enables the alarm wakeup functionality in the TMU unit of
+ Whiskey Cove PMIC.
+
+config INTEL_CHTDC_TI_PWRBTN
+ tristate "Intel Cherry Trail Dollar Cove TI power button driver"
+ depends on INTEL_SOC_PMIC_CHTDC_TI
+ depends on INPUT
+ help
+ This option adds a power button driver for Dollar Cove TI
+ PMIC on Intel Cherry Trail devices.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_chtdc_ti_pwrbtn.
+
+config INTEL_MRFLD_PWRBTN
+ tristate "Intel Merrifield Basin Cove power button driver"
+ depends on INTEL_SOC_PMIC_MRFLD
+ depends on INPUT
+ help
+ This option adds a power button driver for Basin Cove PMIC
+ on Intel Merrifield devices.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_mrfld_pwrbtn.
+
+config INTEL_PUNIT_IPC
+ tristate "Intel P-Unit IPC Driver"
+ help
+ This driver provides support for Intel P-Unit Mailbox IPC mechanism,
+ which is used to bridge the communications between kernel and P-Unit.
+
+config INTEL_RST
+ tristate "Intel Rapid Start Technology Driver"
+ depends on ACPI
+ help
+ This driver provides support for modifying parameters on systems
+ equipped with Intel's Rapid Start Technology. When put in an ACPI
+ sleep state, these devices will wake after either a configured
+ timeout or when the system battery reaches a critical state,
+ automatically copying memory contents to disk. On resume, the
+ firmware will copy the memory contents back to RAM and resume the OS
+ as usual.
+
+config INTEL_SMARTCONNECT
+ tristate "Intel Smart Connect disabling driver"
+ depends on ACPI
+ help
+ Intel Smart Connect is a technology intended to permit devices to
+ update state by resuming for a short period of time at regular
+ intervals. If a user enables this functionality under Windows and
+ then reboots into Linux, the system may remain configured to resume
+ on suspend. In the absence of any userspace to support it, the system
+ will then remain awake until something triggers another suspend.
+
+ This driver checks to determine whether the device has Intel Smart
+ Connect enabled, and if so disables it.
+
+config INTEL_TURBO_MAX_3
+ bool "Intel Turbo Boost Max Technology 3.0 enumeration driver"
+ depends on X86_64 && SCHED_MC_PRIO
+ help
+ This driver reads maximum performance ratio of each CPU and set up
+ the scheduler priority metrics. In this way scheduler can prefer
+ CPU with higher performance to schedule tasks.
+
+ This driver is only required when the system is not using Hardware
+ P-States (HWP). In HWP mode, priority can be read from ACPI tables.
+
+config INTEL_UNCORE_FREQ_CONTROL
+ tristate "Intel Uncore frequency control driver"
+ depends on X86_64
+ help
+ This driver allows control of Uncore frequency limits on
+ supported server platforms.
+
+ Uncore frequency controls RING/LLC (last-level cache) clocks.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel-uncore-frequency.
endif # X86_PLATFORM_DRIVERS_INTEL
diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
index 0653055942d5..8b3a3f7bab49 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -4,5 +4,44 @@
# Intel x86 Platform-Specific Drivers
#
+obj-$(CONFIG_INTEL_ATOMISP2_PDX86) += atomisp2/
+obj-$(CONFIG_INTEL_SAR_INT1092) += int1092/
obj-$(CONFIG_INTEL_CHT_INT33FE) += int33fe/
obj-$(CONFIG_INTEL_SKL_INT3472) += int3472/
+obj-$(CONFIG_INTEL_PMC_CORE) += pmc/
+obj-$(CONFIG_INTEL_PMT_CLASS) += pmt/
+obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += speed_select_if/
+obj-$(CONFIG_INTEL_TELEMETRY) += telemetry/
+obj-$(CONFIG_INTEL_WMI) += wmi/
+
+# Intel input drivers
+intel-hid-y := hid.o
+obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
+intel-vbtn-y := vbtn.o
+obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
+
+# Intel miscellaneous drivers
+intel_int0002_vgpio-y := int0002_vgpio.o
+obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
+intel_oaktrail-y := oaktrail.o
+obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
+
+# Intel PMIC / PMC / P-Unit drivers
+intel_bxtwc_tmu-y := bxtwc_tmu.o
+obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o
+intel_chtdc_ti_pwrbtn-y := chtdc_ti_pwrbtn.o
+obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
+intel_mrfld_pwrbtn-y := mrfld_pwrbtn.o
+obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o
+intel_punit_ipc-y := punit_ipc.o
+obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
+
+# Intel Uncore drivers
+intel-rst-y := rst.o
+obj-$(CONFIG_INTEL_RST) += intel-rst.o
+intel-smartconnect-y := smartconnect.o
+obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
+intel_turbo_max_3-y := turbo_max_3.o
+obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
+intel-uncore-frequency-y := uncore-frequency.o
+obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o
diff --git a/drivers/platform/x86/intel/atomisp2/Kconfig b/drivers/platform/x86/intel/atomisp2/Kconfig
new file mode 100644
index 000000000000..35dd2be9d2a1
--- /dev/null
+++ b/drivers/platform/x86/intel/atomisp2/Kconfig
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Intel x86 Platform Specific Drivers
+#
+
+config INTEL_ATOMISP2_PDX86
+ bool
+
+config INTEL_ATOMISP2_LED
+ tristate "Intel AtomISP v2 camera LED driver"
+ depends on GPIOLIB && LEDS_GPIO
+ select INTEL_ATOMISP2_PDX86
+ help
+ Many Bay Trail and Cherry Trail devices come with a camera attached
+ to Intel's Image Signal Processor. Linux currently does not have a
+ driver for these, so they do not work as a camera. Some of these
+ camera's have a LED which is controlled through a GPIO.
+
+ Some of these devices have a firmware issue where the LED gets turned
+ on at boot. This driver will turn the LED off at boot and also allows
+ controlling the LED (repurposing it) through the sysfs LED interface.
+
+ Which GPIO is attached to the LED is usually not described in the
+ ACPI tables, so this driver contains per-system info about the GPIO
+ inside the driver, this means that this driver only works on systems
+ the driver knows about.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_atomisp2_led.
+
+config INTEL_ATOMISP2_PM
+ tristate "Intel AtomISP v2 dummy / power-management driver"
+ depends on PCI && IOSF_MBI && PM
+ depends on !INTEL_ATOMISP
+ select INTEL_ATOMISP2_PDX86
+ help
+ Power-management driver for Intel's Image Signal Processor found on
+ Bay Trail and Cherry Trail devices. This dummy driver's sole purpose
+ is to turn the ISP off (put it in D3) to save power and to allow
+ entering of S0ix modes.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_atomisp2_pm.
diff --git a/drivers/platform/x86/intel/atomisp2/Makefile b/drivers/platform/x86/intel/atomisp2/Makefile
new file mode 100644
index 000000000000..96b1e877d1f1
--- /dev/null
+++ b/drivers/platform/x86/intel/atomisp2/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Intel x86 Platform Specific Drivers
+#
+
+intel_atomisp2_led-y := led.o
+obj-$(CONFIG_INTEL_ATOMISP2_LED) += intel_atomisp2_led.o
+intel_atomisp2_pm-y += pm.o
+obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o
diff --git a/drivers/platform/x86/intel_atomisp2_led.c b/drivers/platform/x86/intel/atomisp2/led.c
index 5935dfca166f..5935dfca166f 100644
--- a/drivers/platform/x86/intel_atomisp2_led.c
+++ b/drivers/platform/x86/intel/atomisp2/led.c
diff --git a/drivers/platform/x86/intel_atomisp2_pm.c b/drivers/platform/x86/intel/atomisp2/pm.c
index 805fc0d8515c..805fc0d8515c 100644
--- a/drivers/platform/x86/intel_atomisp2_pm.c
+++ b/drivers/platform/x86/intel/atomisp2/pm.c
diff --git a/drivers/platform/x86/intel_bxtwc_tmu.c b/drivers/platform/x86/intel/bxtwc_tmu.c
index 7ccf583649e6..7ccf583649e6 100644
--- a/drivers/platform/x86/intel_bxtwc_tmu.c
+++ b/drivers/platform/x86/intel/bxtwc_tmu.c
diff --git a/drivers/platform/x86/intel_chtdc_ti_pwrbtn.c b/drivers/platform/x86/intel/chtdc_ti_pwrbtn.c
index 9606a994af22..9606a994af22 100644
--- a/drivers/platform/x86/intel_chtdc_ti_pwrbtn.c
+++ b/drivers/platform/x86/intel/chtdc_ti_pwrbtn.c
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel/hid.c
index 2e4e97a626a5..a33a5826e81a 100644
--- a/drivers/platform/x86/intel-hid.c
+++ b/drivers/platform/x86/intel/hid.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
-#include "dual_accel_detect.h"
+#include "../dual_accel_detect.h"
/* When NOT in tablet mode, VGBS returns with the flag 0x40 */
#define TABLET_MODE_FLAG BIT(6)
diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel/int0002_vgpio.c
index 569342aa8926..569342aa8926 100644
--- a/drivers/platform/x86/intel_int0002_vgpio.c
+++ b/drivers/platform/x86/intel/int0002_vgpio.c
diff --git a/drivers/platform/x86/intel/int1092/Kconfig b/drivers/platform/x86/intel/int1092/Kconfig
new file mode 100644
index 000000000000..2e9a177241aa
--- /dev/null
+++ b/drivers/platform/x86/intel/int1092/Kconfig
@@ -0,0 +1,14 @@
+config INTEL_SAR_INT1092
+ tristate "Intel Specific Absorption Rate Driver"
+ depends on ACPI
+ help
+ This driver helps to limit the exposure of human body to RF frequency by
+ providing information to userspace application that will inform the Intel
+ M.2 modem to regulate the RF power based on SAR data obtained from the
+ sensors captured in the BIOS. ACPI interface exposes this data from the BIOS
+ to SAR driver. The front end application in userspace will interact with SAR
+ driver to obtain information like the device mode, Antenna index, baseband index,
+ SAR table index and use available communication like MBIM interface to enable
+ data communication to modem for RF power regulation. Enable this config when
+ given platform needs to support "Dynamic SAR" configuration for a modem available
+ on the platform.
diff --git a/drivers/platform/x86/intel/int1092/Makefile b/drivers/platform/x86/intel/int1092/Makefile
new file mode 100644
index 000000000000..4ab94e541de3
--- /dev/null
+++ b/drivers/platform/x86/intel/int1092/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_INTEL_SAR_INT1092) += intel_sar.o
diff --git a/drivers/platform/x86/intel/int1092/intel_sar.c b/drivers/platform/x86/intel/int1092/intel_sar.c
new file mode 100644
index 000000000000..379560fe5df9
--- /dev/null
+++ b/drivers/platform/x86/intel/int1092/intel_sar.c
@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, Intel Corporation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+#include "intel_sar.h"
+
+/**
+ * get_int_value: Retrieve integer values from ACPI Object
+ * @obj: acpi_object pointer which has the integer value
+ * @out: output pointer will get integer value
+ *
+ * Function is used to retrieve integer value from acpi object.
+ *
+ * Return:
+ * * 0 on success
+ * * -EIO if there is an issue in acpi_object passed.
+ */
+static int get_int_value(union acpi_object *obj, int *out)
+{
+ if (!obj || obj->type != ACPI_TYPE_INTEGER)
+ return -EIO;
+ *out = (int)obj->integer.value;
+ return 0;
+}
+
+/**
+ * update_sar_data: sar data is updated based on regulatory mode
+ * @context: pointer to driver context structure
+ *
+ * sar_data is updated based on regulatory value
+ * context->reg_value will never exceed MAX_REGULATORY
+ */
+static void update_sar_data(struct wwan_sar_context *context)
+{
+ struct wwan_device_mode_configuration *config =
+ &context->config_data[context->reg_value];
+
+ if (config->device_mode_info &&
+ context->sar_data.device_mode < config->total_dev_mode) {
+ struct wwan_device_mode_info *dev_mode =
+ &config->device_mode_info[context->sar_data.device_mode];
+
+ context->sar_data.antennatable_index = dev_mode->antennatable_index;
+ context->sar_data.bandtable_index = dev_mode->bandtable_index;
+ context->sar_data.sartable_index = dev_mode->sartable_index;
+ }
+}
+
+/**
+ * parse_package: parse acpi package for retrieving SAR information
+ * @context: pointer to driver context structure
+ * @item : acpi_object pointer
+ *
+ * Given acpi_object is iterated to retrieve information for each device mode.
+ * If a given package corresponding to a specific device mode is faulty, it is
+ * skipped and the specific entry in context structure will have the default value
+ * of zero. Decoding of subsequent device modes is realized by having "continue"
+ * statements in the for loop on encountering error in parsing given device mode.
+ *
+ * Return:
+ * AE_OK if success
+ * AE_ERROR on error
+ */
+static acpi_status parse_package(struct wwan_sar_context *context, union acpi_object *item)
+{
+ struct wwan_device_mode_configuration *data;
+ int value, itr, reg;
+ union acpi_object *num;
+
+ num = &item->package.elements[0];
+ if (get_int_value(num, &value) || value < 0 || value >= MAX_REGULATORY)
+ return AE_ERROR;
+
+ reg = value;
+
+ data = &context->config_data[reg];
+ if (data->total_dev_mode > MAX_DEV_MODES || data->total_dev_mode == 0 ||
+ item->package.count <= data->total_dev_mode)
+ return AE_ERROR;
+
+ data->device_mode_info = kmalloc_array(data->total_dev_mode,
+ sizeof(struct wwan_device_mode_info), GFP_KERNEL);
+ if (!data->device_mode_info)
+ return AE_ERROR;
+
+ for (itr = 0; itr < data->total_dev_mode; itr++) {
+ struct wwan_device_mode_info temp = { 0 };
+
+ num = &item->package.elements[itr + 1];
+ if (num->type != ACPI_TYPE_PACKAGE || num->package.count < TOTAL_DATA)
+ continue;
+ if (get_int_value(&num->package.elements[0], &temp.device_mode))
+ continue;
+ if (get_int_value(&num->package.elements[1], &temp.bandtable_index))
+ continue;
+ if (get_int_value(&num->package.elements[2], &temp.antennatable_index))
+ continue;
+ if (get_int_value(&num->package.elements[3], &temp.sartable_index))
+ continue;
+ data->device_mode_info[itr] = temp;
+ }
+ return AE_OK;
+}
+
+/**
+ * sar_get_device_mode: Extraction of information from BIOS via DSM calls
+ * @device: ACPI device for which to retrieve the data
+ *
+ * Retrieve the current device mode information from the BIOS.
+ *
+ * Return:
+ * AE_OK on success
+ * AE_ERROR on error
+ */
+static acpi_status sar_get_device_mode(struct platform_device *device)
+{
+ struct wwan_sar_context *context = dev_get_drvdata(&device->dev);
+ acpi_status status = AE_OK;
+ union acpi_object *out;
+ u32 rev = 0;
+ int value;
+
+ out = acpi_evaluate_dsm(context->handle, &context->guid, rev,
+ COMMAND_ID_DEV_MODE, NULL);
+ if (get_int_value(out, &value)) {
+ dev_err(&device->dev, "DSM cmd:%d Failed to retrieve value\n", COMMAND_ID_DEV_MODE);
+ status = AE_ERROR;
+ goto dev_mode_error;
+ }
+ context->sar_data.device_mode = value;
+ update_sar_data(context);
+ sysfs_notify(&device->dev.kobj, NULL, SYSFS_DATANAME);
+
+dev_mode_error:
+ ACPI_FREE(out);
+ return status;
+}
+
+static const struct acpi_device_id sar_device_ids[] = {
+ { "INTC1092", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, sar_device_ids);
+
+static ssize_t intc_data_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct wwan_sar_context *context = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d %d %d %d\n", context->sar_data.device_mode,
+ context->sar_data.bandtable_index,
+ context->sar_data.antennatable_index,
+ context->sar_data.sartable_index);
+}
+static DEVICE_ATTR_RO(intc_data);
+
+static ssize_t intc_reg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct wwan_sar_context *context = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d\n", context->reg_value);
+}
+
+static ssize_t intc_reg_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wwan_sar_context *context = dev_get_drvdata(dev);
+ unsigned int value;
+ int read;
+
+ if (!count)
+ return -EINVAL;
+ read = kstrtouint(buf, 10, &value);
+ if (read < 0)
+ return read;
+ if (value >= MAX_REGULATORY)
+ return -EOVERFLOW;
+ context->reg_value = value;
+ update_sar_data(context);
+ sysfs_notify(&dev->kobj, NULL, SYSFS_DATANAME);
+ return count;
+}
+static DEVICE_ATTR_RW(intc_reg);
+
+static struct attribute *intcsar_attrs[] = {
+ &dev_attr_intc_data.attr,
+ &dev_attr_intc_reg.attr,
+ NULL
+};
+
+static struct attribute_group intcsar_group = {
+ .attrs = intcsar_attrs,
+};
+
+static void sar_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct platform_device *device = data;
+
+ if (event == SAR_EVENT) {
+ if (sar_get_device_mode(device) != AE_OK)
+ dev_err(&device->dev, "sar_get_device_mode error");
+ }
+}
+
+static void sar_get_data(int reg, struct wwan_sar_context *context)
+{
+ union acpi_object *out, req;
+ u32 rev = 0;
+
+ req.type = ACPI_TYPE_INTEGER;
+ req.integer.value = reg;
+ out = acpi_evaluate_dsm(context->handle, &context->guid, rev,
+ COMMAND_ID_CONFIG_TABLE, &req);
+ if (!out)
+ return;
+ if (out->type == ACPI_TYPE_PACKAGE && out->package.count >= 3 &&
+ out->package.elements[0].type == ACPI_TYPE_INTEGER &&
+ out->package.elements[1].type == ACPI_TYPE_INTEGER &&
+ out->package.elements[2].type == ACPI_TYPE_PACKAGE &&
+ out->package.elements[2].package.count > 0) {
+ context->config_data[reg].version = out->package.elements[0].integer.value;
+ context->config_data[reg].total_dev_mode =
+ out->package.elements[1].integer.value;
+ if (context->config_data[reg].total_dev_mode <= 0 ||
+ context->config_data[reg].total_dev_mode > MAX_DEV_MODES) {
+ ACPI_FREE(out);
+ return;
+ }
+ parse_package(context, &out->package.elements[2]);
+ }
+ ACPI_FREE(out);
+}
+
+static int sar_probe(struct platform_device *device)
+{
+ struct wwan_sar_context *context;
+ int reg;
+ int result;
+
+ context = kzalloc(sizeof(*context), GFP_KERNEL);
+ if (!context)
+ return -ENOMEM;
+
+ context->sar_device = device;
+ context->handle = ACPI_HANDLE(&device->dev);
+ dev_set_drvdata(&device->dev, context);
+
+ result = guid_parse(SAR_DSM_UUID, &context->guid);
+ if (result) {
+ dev_err(&device->dev, "SAR UUID parse error: %d\n", result);
+ goto r_free;
+ }
+
+ for (reg = 0; reg < MAX_REGULATORY; reg++)
+ sar_get_data(reg, context);
+
+ if (sar_get_device_mode(device) != AE_OK) {
+ dev_err(&device->dev, "Failed to get device mode\n");
+ result = -EIO;
+ goto r_free;
+ }
+
+ result = sysfs_create_group(&device->dev.kobj, &intcsar_group);
+ if (result) {
+ dev_err(&device->dev, "sysfs creation failed\n");
+ goto r_free;
+ }
+
+ if (acpi_install_notify_handler(ACPI_HANDLE(&device->dev), ACPI_DEVICE_NOTIFY,
+ sar_notify, (void *)device) != AE_OK) {
+ dev_err(&device->dev, "Failed acpi_install_notify_handler\n");
+ result = -EIO;
+ goto r_sys;
+ }
+ return 0;
+
+r_sys:
+ sysfs_remove_group(&device->dev.kobj, &intcsar_group);
+r_free:
+ kfree(context);
+ return result;
+}
+
+static int sar_remove(struct platform_device *device)
+{
+ struct wwan_sar_context *context = dev_get_drvdata(&device->dev);
+ int reg;
+
+ acpi_remove_notify_handler(ACPI_HANDLE(&device->dev),
+ ACPI_DEVICE_NOTIFY, sar_notify);
+ sysfs_remove_group(&device->dev.kobj, &intcsar_group);
+ for (reg = 0; reg < MAX_REGULATORY; reg++)
+ kfree(context->config_data[reg].device_mode_info);
+
+ kfree(context);
+ return 0;
+}
+
+static struct platform_driver sar_driver = {
+ .probe = sar_probe,
+ .remove = sar_remove,
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ .acpi_match_table = ACPI_PTR(sar_device_ids)
+ }
+};
+module_platform_driver(sar_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Platform device driver for INTEL MODEM BIOS SAR");
+MODULE_AUTHOR("Shravan S <s.shravan@intel.com>");
diff --git a/drivers/platform/x86/intel/int1092/intel_sar.h b/drivers/platform/x86/intel/int1092/intel_sar.h
new file mode 100644
index 000000000000..b5310510b84c
--- /dev/null
+++ b/drivers/platform/x86/intel/int1092/intel_sar.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021, Intel Corporation.
+ */
+#ifndef INTEL_SAR_H
+#define INTEL_SAR_H
+
+#define COMMAND_ID_DEV_MODE 1
+#define COMMAND_ID_CONFIG_TABLE 2
+#define DRVNAME "intc_sar"
+#define MAX_DEV_MODES 50
+#define MAX_REGULATORY 3
+#define SAR_DSM_UUID "82737E72-3A33-4C45-A9C7-57C0411A5F13"
+#define SAR_EVENT 0x80
+#define SYSFS_DATANAME "intc_data"
+#define TOTAL_DATA 4
+
+/**
+ * Structure wwan_device_mode_info - device mode information
+ * Holds the data that needs to be passed to userspace.
+ * The data is updated from the BIOS sensor information.
+ * @device_mode: Specific mode of the device
+ * @bandtable_index: Index of RF band
+ * @antennatable_index: Index of antenna
+ * @sartable_index: Index of SAR
+ */
+struct wwan_device_mode_info {
+ int device_mode;
+ int bandtable_index;
+ int antennatable_index;
+ int sartable_index;
+};
+
+/**
+ * Structure wwan_device_mode_configuration - device configuration
+ * Holds the data that is configured and obtained on probe event.
+ * The data is updated from the BIOS sensor information.
+ * @version: Mode configuration version
+ * @total_dev_mode: Total number of device modes
+ * @device_mode_info: pointer to structure wwan_device_mode_info
+ */
+struct wwan_device_mode_configuration {
+ int version;
+ int total_dev_mode;
+ struct wwan_device_mode_info *device_mode_info;
+};
+
+/**
+ * Structure wwan_supported_info - userspace datastore
+ * Holds the data that is obtained from userspace
+ * The data is updated from the userspace and send value back in the
+ * structure format that is mentioned here.
+ * @reg_mode_needed: regulatory mode set by user for tests
+ * @bios_table_revision: Version of SAR table
+ * @num_supported_modes: Total supported modes based on reg_mode
+ */
+struct wwan_supported_info {
+ int reg_mode_needed;
+ int bios_table_revision;
+ int num_supported_modes;
+};
+
+/**
+ * Structure wwan_sar_context - context of SAR
+ * Holds the complete context as long as the driver is in existence
+ * The context holds instance of the data used for different cases.
+ * @guid: Group id
+ * @handle: store acpi handle
+ * @reg_value: regulatory value
+ * Regulatory 0: FCC, 1: CE, 2: ISED
+ * @sar_device: platform_device type
+ * @sar_kobject: kobject for sysfs
+ * @supported_data: wwan_supported_info struct
+ * @sar_data: wwan_device_mode_info struct
+ * @config_data: wwan_device_mode_configuration array struct
+ */
+struct wwan_sar_context {
+ guid_t guid;
+ acpi_handle handle;
+ int reg_value;
+ struct platform_device *sar_device;
+ struct wwan_supported_info supported_data;
+ struct wwan_device_mode_info sar_data;
+ struct wwan_device_mode_configuration config_data[MAX_REGULATORY];
+};
+#endif /* INTEL_SAR_H */
diff --git a/drivers/platform/x86/intel/int33fe/Makefile b/drivers/platform/x86/intel/int33fe/Makefile
index cc11183ce179..9456e3b37f6f 100644
--- a/drivers/platform/x86/intel/int33fe/Makefile
+++ b/drivers/platform/x86/intel/int33fe/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
-intel_cht_int33fe-objs := intel_cht_int33fe_common.o \
+intel_cht_int33fe-y := intel_cht_int33fe_common.o \
intel_cht_int33fe_typec.o \
intel_cht_int33fe_microb.o
diff --git a/drivers/platform/x86/intel/int33fe/intel_cht_int33fe_common.c b/drivers/platform/x86/intel/int33fe/intel_cht_int33fe_common.c
index 251ed9bac789..463222521e61 100644
--- a/drivers/platform/x86/intel/int33fe/intel_cht_int33fe_common.c
+++ b/drivers/platform/x86/intel/int33fe/intel_cht_int33fe_common.c
@@ -16,33 +16,6 @@
#define EXPECTED_PTYPE 4
-static int cht_int33fe_i2c_res_filter(struct acpi_resource *ares, void *data)
-{
- struct acpi_resource_i2c_serialbus *sb;
- int *count = data;
-
- if (i2c_acpi_get_i2c_resource(ares, &sb))
- (*count)++;
-
- return 1;
-}
-
-static int cht_int33fe_count_i2c_clients(struct device *dev)
-{
- struct acpi_device *adev = ACPI_COMPANION(dev);
- LIST_HEAD(resource_list);
- int count = 0;
- int ret;
-
- ret = acpi_dev_get_resources(adev, &resource_list,
- cht_int33fe_i2c_res_filter, &count);
- acpi_dev_free_resource_list(&resource_list);
- if (ret < 0)
- return ret;
-
- return count;
-}
-
static int cht_int33fe_check_hw_type(struct device *dev)
{
unsigned long long ptyp;
@@ -69,7 +42,7 @@ static int cht_int33fe_check_hw_type(struct device *dev)
return -ENODEV;
}
- ret = cht_int33fe_count_i2c_clients(dev);
+ ret = i2c_acpi_client_count(ACPI_COMPANION(dev));
if (ret < 0)
return ret;
diff --git a/drivers/platform/x86/intel/int3472/Makefile b/drivers/platform/x86/intel/int3472/Makefile
index 48bd97f0a04e..2362e04db18d 100644
--- a/drivers/platform/x86/intel/int3472/Makefile
+++ b/drivers/platform/x86/intel/int3472/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472.o
-intel_skl_int3472-objs := intel_skl_int3472_common.o \
+intel_skl_int3472-y := intel_skl_int3472_common.o \
intel_skl_int3472_discrete.o \
intel_skl_int3472_tps68470.o \
intel_skl_int3472_clk_and_regulator.o
diff --git a/drivers/platform/x86/intel_mrfld_pwrbtn.c b/drivers/platform/x86/intel/mrfld_pwrbtn.c
index d58fea51747e..d58fea51747e 100644
--- a/drivers/platform/x86/intel_mrfld_pwrbtn.c
+++ b/drivers/platform/x86/intel/mrfld_pwrbtn.c
diff --git a/drivers/platform/x86/intel_oaktrail.c b/drivers/platform/x86/intel/oaktrail.c
index 1a09a75bd16d..1a09a75bd16d 100644
--- a/drivers/platform/x86/intel_oaktrail.c
+++ b/drivers/platform/x86/intel/oaktrail.c
diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig
new file mode 100644
index 000000000000..b526597e4deb
--- /dev/null
+++ b/drivers/platform/x86/intel/pmc/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Intel x86 Platform-Specific Drivers
+#
+
+config INTEL_PMC_CORE
+ tristate "Intel PMC Core driver"
+ depends on PCI
+ depends on ACPI
+ help
+ The Intel Platform Controller Hub for Intel Core SoCs provides access
+ to Power Management Controller registers via various interfaces. This
+ driver can utilize debugging capabilities and supported features as
+ exposed by the Power Management Controller. It also may perform some
+ tasks in the PMC in order to enable transition into the SLPS0 state.
+ It should be selected on all Intel platforms supported by the driver.
+
+ Supported features:
+ - SLP_S0_RESIDENCY counter
+ - PCH IP Power Gating status
+ - LTR Ignore / LTR Show
+ - MPHY/PLL gating status (Sunrisepoint PCH only)
+ - SLPS0 Debug registers (Cannonlake/Icelake PCH)
+ - Low Power Mode registers (Tigerlake and beyond)
+ - PMC quirks as needed to enable SLPS0/S0ix
diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile
new file mode 100644
index 000000000000..8966fcdc0e1d
--- /dev/null
+++ b/drivers/platform/x86/intel/pmc/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Intel x86 Platform-Specific Drivers
+#
+
+intel_pmc_core-y := core.o
+obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o
+intel_pmc_core_pltdrv-y := pltdrv.o
+obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o
diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel/pmc/core.c
index b0e486a6bdfb..ac19fcc9abbf 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -31,7 +31,7 @@
#include <asm/msr.h>
#include <asm/tsc.h>
-#include "intel_pmc_core.h"
+#include "core.h"
#define ACPI_S0IX_DSM_UUID "57a6512e-3979-4e9d-9708-ff13b2508972"
#define ACPI_GET_LOW_MODE_REGISTERS 1
@@ -645,6 +645,306 @@ free_acpi_obj:
ACPI_FREE(out_obj);
}
+/* Alder Lake: PGD PFET Enable Ack Status Register(s) bitmap */
+static const struct pmc_bit_map adl_pfear_map[] = {
+ {"SPI/eSPI", BIT(2)},
+ {"XHCI", BIT(3)},
+ {"SPA", BIT(4)},
+ {"SPB", BIT(5)},
+ {"SPC", BIT(6)},
+ {"GBE", BIT(7)},
+
+ {"SATA", BIT(0)},
+ {"HDA_PGD0", BIT(1)},
+ {"HDA_PGD1", BIT(2)},
+ {"HDA_PGD2", BIT(3)},
+ {"HDA_PGD3", BIT(4)},
+ {"SPD", BIT(5)},
+ {"LPSS", BIT(6)},
+
+ {"SMB", BIT(0)},
+ {"ISH", BIT(1)},
+ {"ITH", BIT(3)},
+
+ {"XDCI", BIT(1)},
+ {"DCI", BIT(2)},
+ {"CSE", BIT(3)},
+ {"CSME_KVM", BIT(4)},
+ {"CSME_PMT", BIT(5)},
+ {"CSME_CLINK", BIT(6)},
+ {"CSME_PTIO", BIT(7)},
+
+ {"CSME_USBR", BIT(0)},
+ {"CSME_SUSRAM", BIT(1)},
+ {"CSME_SMT1", BIT(2)},
+ {"CSME_SMS2", BIT(4)},
+ {"CSME_SMS1", BIT(5)},
+ {"CSME_RTC", BIT(6)},
+ {"CSME_PSF", BIT(7)},
+
+ {"CNVI", BIT(3)},
+
+ {"HDA_PGD4", BIT(2)},
+ {"HDA_PGD5", BIT(3)},
+ {"HDA_PGD6", BIT(4)},
+ {}
+};
+
+static const struct pmc_bit_map *ext_adl_pfear_map[] = {
+ /*
+ * Check intel_pmc_core_ids[] users of cnp_reg_map for
+ * a list of core SoCs using this.
+ */
+ adl_pfear_map,
+ NULL
+};
+
+static const struct pmc_bit_map adl_ltr_show_map[] = {
+ {"SOUTHPORT_A", CNP_PMC_LTR_SPA},
+ {"SOUTHPORT_B", CNP_PMC_LTR_SPB},
+ {"SATA", CNP_PMC_LTR_SATA},
+ {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE},
+ {"XHCI", CNP_PMC_LTR_XHCI},
+ {"SOUTHPORT_F", ADL_PMC_LTR_SPF},
+ {"ME", CNP_PMC_LTR_ME},
+ /* EVA is Enterprise Value Add, doesn't really exist on PCH */
+ {"SATA1", CNP_PMC_LTR_EVA},
+ {"SOUTHPORT_C", CNP_PMC_LTR_SPC},
+ {"HD_AUDIO", CNP_PMC_LTR_AZ},
+ {"CNV", CNP_PMC_LTR_CNV},
+ {"LPSS", CNP_PMC_LTR_LPSS},
+ {"SOUTHPORT_D", CNP_PMC_LTR_SPD},
+ {"SOUTHPORT_E", CNP_PMC_LTR_SPE},
+ {"SATA2", CNP_PMC_LTR_CAM},
+ {"ESPI", CNP_PMC_LTR_ESPI},
+ {"SCC", CNP_PMC_LTR_SCC},
+ {"ISH", CNP_PMC_LTR_ISH},
+ {"UFSX2", CNP_PMC_LTR_UFSX2},
+ {"EMMC", CNP_PMC_LTR_EMMC},
+ /*
+ * Check intel_pmc_core_ids[] users of cnp_reg_map for
+ * a list of core SoCs using this.
+ */
+ {"WIGIG", ICL_PMC_LTR_WIGIG},
+ {"THC0", TGL_PMC_LTR_THC0},
+ {"THC1", TGL_PMC_LTR_THC1},
+ {"SOUTHPORT_G", CNP_PMC_LTR_RESERVED},
+
+ /* Below two cannot be used for LTR_IGNORE */
+ {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT},
+ {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT},
+ {}
+};
+
+static const struct pmc_bit_map adl_clocksource_status_map[] = {
+ {"CLKPART1_OFF_STS", BIT(0)},
+ {"CLKPART2_OFF_STS", BIT(1)},
+ {"CLKPART3_OFF_STS", BIT(2)},
+ {"CLKPART4_OFF_STS", BIT(3)},
+ {"CLKPART5_OFF_STS", BIT(4)},
+ {"CLKPART6_OFF_STS", BIT(5)},
+ {"CLKPART7_OFF_STS", BIT(6)},
+ {"CLKPART8_OFF_STS", BIT(7)},
+ {"PCIE0PLL_OFF_STS", BIT(10)},
+ {"PCIE1PLL_OFF_STS", BIT(11)},
+ {"PCIE2PLL_OFF_STS", BIT(12)},
+ {"PCIE3PLL_OFF_STS", BIT(13)},
+ {"PCIE4PLL_OFF_STS", BIT(14)},
+ {"PCIE5PLL_OFF_STS", BIT(15)},
+ {"PCIE6PLL_OFF_STS", BIT(16)},
+ {"USB2PLL_OFF_STS", BIT(18)},
+ {"OCPLL_OFF_STS", BIT(22)},
+ {"AUDIOPLL_OFF_STS", BIT(23)},
+ {"GBEPLL_OFF_STS", BIT(24)},
+ {"Fast_XTAL_Osc_OFF_STS", BIT(25)},
+ {"AC_Ring_Osc_OFF_STS", BIT(26)},
+ {"MC_Ring_Osc_OFF_STS", BIT(27)},
+ {"SATAPLL_OFF_STS", BIT(29)},
+ {"USB3PLL_OFF_STS", BIT(31)},
+ {}
+};
+
+static const struct pmc_bit_map adl_power_gating_status_0_map[] = {
+ {"PMC_PGD0_PG_STS", BIT(0)},
+ {"DMI_PGD0_PG_STS", BIT(1)},
+ {"ESPISPI_PGD0_PG_STS", BIT(2)},
+ {"XHCI_PGD0_PG_STS", BIT(3)},
+ {"SPA_PGD0_PG_STS", BIT(4)},
+ {"SPB_PGD0_PG_STS", BIT(5)},
+ {"SPC_PGD0_PG_STS", BIT(6)},
+ {"GBE_PGD0_PG_STS", BIT(7)},
+ {"SATA_PGD0_PG_STS", BIT(8)},
+ {"DSP_PGD0_PG_STS", BIT(9)},
+ {"DSP_PGD1_PG_STS", BIT(10)},
+ {"DSP_PGD2_PG_STS", BIT(11)},
+ {"DSP_PGD3_PG_STS", BIT(12)},
+ {"SPD_PGD0_PG_STS", BIT(13)},
+ {"LPSS_PGD0_PG_STS", BIT(14)},
+ {"SMB_PGD0_PG_STS", BIT(16)},
+ {"ISH_PGD0_PG_STS", BIT(17)},
+ {"NPK_PGD0_PG_STS", BIT(19)},
+ {"PECI_PGD0_PG_STS", BIT(21)},
+ {"XDCI_PGD0_PG_STS", BIT(25)},
+ {"EXI_PGD0_PG_STS", BIT(26)},
+ {"CSE_PGD0_PG_STS", BIT(27)},
+ {"KVMCC_PGD0_PG_STS", BIT(28)},
+ {"PMT_PGD0_PG_STS", BIT(29)},
+ {"CLINK_PGD0_PG_STS", BIT(30)},
+ {"PTIO_PGD0_PG_STS", BIT(31)},
+ {}
+};
+
+static const struct pmc_bit_map adl_power_gating_status_1_map[] = {
+ {"USBR0_PGD0_PG_STS", BIT(0)},
+ {"SMT1_PGD0_PG_STS", BIT(2)},
+ {"CSMERTC_PGD0_PG_STS", BIT(6)},
+ {"CSMEPSF_PGD0_PG_STS", BIT(7)},
+ {"CNVI_PGD0_PG_STS", BIT(19)},
+ {"DSP_PGD4_PG_STS", BIT(26)},
+ {"SPG_PGD0_PG_STS", BIT(27)},
+ {"SPE_PGD0_PG_STS", BIT(28)},
+ {}
+};
+
+static const struct pmc_bit_map adl_power_gating_status_2_map[] = {
+ {"THC0_PGD0_PG_STS", BIT(7)},
+ {"THC1_PGD0_PG_STS", BIT(8)},
+ {"SPF_PGD0_PG_STS", BIT(14)},
+ {}
+};
+
+static const struct pmc_bit_map adl_d3_status_0_map[] = {
+ {"ISH_D3_STS", BIT(2)},
+ {"LPSS_D3_STS", BIT(3)},
+ {"XDCI_D3_STS", BIT(4)},
+ {"XHCI_D3_STS", BIT(5)},
+ {"SPA_D3_STS", BIT(12)},
+ {"SPB_D3_STS", BIT(13)},
+ {"SPC_D3_STS", BIT(14)},
+ {"SPD_D3_STS", BIT(15)},
+ {"SPE_D3_STS", BIT(16)},
+ {"DSP_D3_STS", BIT(19)},
+ {"SATA_D3_STS", BIT(20)},
+ {"DMI_D3_STS", BIT(22)},
+ {}
+};
+
+static const struct pmc_bit_map adl_d3_status_1_map[] = {
+ {"GBE_D3_STS", BIT(19)},
+ {"CNVI_D3_STS", BIT(27)},
+ {}
+};
+
+static const struct pmc_bit_map adl_d3_status_2_map[] = {
+ {"CSMERTC_D3_STS", BIT(1)},
+ {"CSE_D3_STS", BIT(4)},
+ {"KVMCC_D3_STS", BIT(5)},
+ {"USBR0_D3_STS", BIT(6)},
+ {"SMT1_D3_STS", BIT(8)},
+ {"PTIO_D3_STS", BIT(16)},
+ {"PMT_D3_STS", BIT(17)},
+ {}
+};
+
+static const struct pmc_bit_map adl_d3_status_3_map[] = {
+ {"THC0_D3_STS", BIT(14)},
+ {"THC1_D3_STS", BIT(15)},
+ {}
+};
+
+static const struct pmc_bit_map adl_vnn_req_status_0_map[] = {
+ {"ISH_VNN_REQ_STS", BIT(2)},
+ {"ESPISPI_VNN_REQ_STS", BIT(18)},
+ {"DSP_VNN_REQ_STS", BIT(19)},
+ {}
+};
+
+static const struct pmc_bit_map adl_vnn_req_status_1_map[] = {
+ {"NPK_VNN_REQ_STS", BIT(4)},
+ {"EXI_VNN_REQ_STS", BIT(9)},
+ {"GBE_VNN_REQ_STS", BIT(19)},
+ {"SMB_VNN_REQ_STS", BIT(25)},
+ {"CNVI_VNN_REQ_STS", BIT(27)},
+ {}
+};
+
+static const struct pmc_bit_map adl_vnn_req_status_2_map[] = {
+ {"CSMERTC_VNN_REQ_STS", BIT(1)},
+ {"CSE_VNN_REQ_STS", BIT(4)},
+ {"SMT1_VNN_REQ_STS", BIT(8)},
+ {"CLINK_VNN_REQ_STS", BIT(14)},
+ {"GPIOCOM4_VNN_REQ_STS", BIT(20)},
+ {"GPIOCOM3_VNN_REQ_STS", BIT(21)},
+ {"GPIOCOM2_VNN_REQ_STS", BIT(22)},
+ {"GPIOCOM1_VNN_REQ_STS", BIT(23)},
+ {"GPIOCOM0_VNN_REQ_STS", BIT(24)},
+ {}
+};
+
+static const struct pmc_bit_map adl_vnn_req_status_3_map[] = {
+ {"GPIOCOM5_VNN_REQ_STS", BIT(11)},
+ {}
+};
+
+static const struct pmc_bit_map adl_vnn_misc_status_map[] = {
+ {"CPU_C10_REQ_STS", BIT(0)},
+ {"PCIe_LPM_En_REQ_STS", BIT(3)},
+ {"ITH_REQ_STS", BIT(5)},
+ {"CNVI_REQ_STS", BIT(6)},
+ {"ISH_REQ_STS", BIT(7)},
+ {"USB2_SUS_PG_Sys_REQ_STS", BIT(10)},
+ {"PCIe_Clk_REQ_STS", BIT(12)},
+ {"MPHY_Core_DL_REQ_STS", BIT(16)},
+ {"Break-even_En_REQ_STS", BIT(17)},
+ {"MPHY_SUS_REQ_STS", BIT(22)},
+ {"xDCI_attached_REQ_STS", BIT(24)},
+ {}
+};
+
+static const struct pmc_bit_map *adl_lpm_maps[] = {
+ adl_clocksource_status_map,
+ adl_power_gating_status_0_map,
+ adl_power_gating_status_1_map,
+ adl_power_gating_status_2_map,
+ adl_d3_status_0_map,
+ adl_d3_status_1_map,
+ adl_d3_status_2_map,
+ adl_d3_status_3_map,
+ adl_vnn_req_status_0_map,
+ adl_vnn_req_status_1_map,
+ adl_vnn_req_status_2_map,
+ adl_vnn_req_status_3_map,
+ adl_vnn_misc_status_map,
+ tgl_signal_status_map,
+ NULL
+};
+
+static const struct pmc_reg_map adl_reg_map = {
+ .pfear_sts = ext_adl_pfear_map,
+ .slp_s0_offset = ADL_PMC_SLP_S0_RES_COUNTER_OFFSET,
+ .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP,
+ .ltr_show_sts = adl_ltr_show_map,
+ .msr_sts = msr_map,
+ .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
+ .regmap_length = CNP_PMC_MMIO_REG_LEN,
+ .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
+ .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES,
+ .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
+ .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
+ .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED,
+ .lpm_num_modes = ADL_LPM_NUM_MODES,
+ .lpm_num_maps = ADL_LPM_NUM_MAPS,
+ .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
+ .etr3_offset = ETR3_OFFSET,
+ .lpm_sts_latch_en_offset = ADL_LPM_STATUS_LATCH_EN_OFFSET,
+ .lpm_priority_offset = ADL_LPM_PRI_OFFSET,
+ .lpm_en_offset = ADL_LPM_EN_OFFSET,
+ .lpm_residency_offset = ADL_LPM_RESIDENCY_OFFSET,
+ .lpm_sts = adl_lpm_maps,
+ .lpm_status_offset = ADL_LPM_STATUS_OFFSET,
+ .lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET,
+};
+
static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
{
return readl(pmcdev->regbase + reg_offset);
@@ -1449,9 +1749,42 @@ static int pmc_core_pkgc_show(struct seq_file *s, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_pkgc);
-static void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev)
+static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order)
{
- u8 lpm_priority[LPM_MAX_NUM_MODES];
+ int i, j;
+
+ if (!lpm_pri)
+ return false;
+ /*
+ * Each byte contains the priority level for 2 modes (7:4 and 3:0).
+ * In a 32 bit register this allows for describing 8 modes. Store the
+ * levels and look for values out of range.
+ */
+ for (i = 0; i < 8; i++) {
+ int level = lpm_pri & GENMASK(3, 0);
+
+ if (level >= LPM_MAX_NUM_MODES)
+ return false;
+
+ mode_order[i] = level;
+ lpm_pri >>= 4;
+ }
+
+ /* Check that we have unique values */
+ for (i = 0; i < LPM_MAX_NUM_MODES - 1; i++)
+ for (j = i + 1; j < LPM_MAX_NUM_MODES; j++)
+ if (mode_order[i] == mode_order[j])
+ return false;
+
+ return true;
+}
+
+static void pmc_core_get_low_power_modes(struct platform_device *pdev)
+{
+ struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
+ u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI;
+ u8 mode_order[LPM_MAX_NUM_MODES];
+ u32 lpm_pri;
u32 lpm_en;
int mode, i, p;
@@ -1462,24 +1795,28 @@ static void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev)
lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset);
pmcdev->num_lpm_modes = hweight32(lpm_en);
- /* Each byte contains information for 2 modes (7:4 and 3:0) */
- for (mode = 0; mode < LPM_MAX_NUM_MODES; mode += 2) {
- u8 priority = pmc_core_reg_read_byte(pmcdev,
- pmcdev->map->lpm_priority_offset + (mode / 2));
- int pri0 = GENMASK(3, 0) & priority;
- int pri1 = (GENMASK(7, 4) & priority) >> 4;
+ /* Read 32 bit LPM_PRI register */
+ lpm_pri = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_priority_offset);
- lpm_priority[pri0] = mode;
- lpm_priority[pri1] = mode + 1;
- }
/*
- * Loop though all modes from lowest to highest priority,
+ * If lpm_pri value passes verification, then override the default
+ * modes here. Otherwise stick with the default.
+ */
+ if (pmc_core_pri_verify(lpm_pri, mode_order))
+ /* Get list of modes in priority order */
+ for (mode = 0; mode < LPM_MAX_NUM_MODES; mode++)
+ pri_order[mode_order[mode]] = mode;
+ else
+ dev_warn(&pdev->dev, "Assuming a default substate order for this platform\n");
+
+ /*
+ * Loop through all modes from lowest to highest priority,
* and capture all enabled modes in order
*/
i = 0;
for (p = LPM_MAX_NUM_MODES - 1; p >= 0; p--) {
- int mode = lpm_priority[p];
+ int mode = pri_order[p];
if (!(BIT(mode) & lpm_en))
continue;
@@ -1574,6 +1911,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &icl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &tgl_reg_map),
+ X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_reg_map),
{}
};
@@ -1675,17 +2013,17 @@ static int pmc_core_probe(struct platform_device *pdev)
mutex_init(&pmcdev->lock);
pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev);
- pmc_core_get_low_power_modes(pmcdev);
+ pmc_core_get_low_power_modes(pdev);
pmc_core_do_dmi_quirks(pmcdev);
if (pmcdev->map == &tgl_reg_map)
pmc_core_get_tgl_lpm_reqs(pdev);
/*
- * On TGL, due to a hardware limitation, the GBE LTR blocks PC10 when
- * a cable is attached. Tell the PMC to ignore it.
+ * On TGL and ADL, due to a hardware limitation, the GBE LTR blocks PC10
+ * when a cable is attached. Tell the PMC to ignore it.
*/
- if (pmcdev->map == &tgl_reg_map) {
+ if (pmcdev->map == &tgl_reg_map || pmcdev->map == &adl_reg_map) {
dev_dbg(&pdev->dev, "ignoring GBE LTR\n");
pmc_core_send_ltr_ignore(pmcdev, 3);
}
diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel/pmc/core.h
index e8dae9c6c45f..a46d3b53bf61 100644
--- a/drivers/platform/x86/intel_pmc_core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -188,6 +188,8 @@ enum ppfear_regs {
#define ICL_PMC_SLP_S0_RES_COUNTER_STEP 0x64
#define LPM_MAX_NUM_MODES 8
+#define LPM_DEFAULT_PRI { 7, 6, 2, 5, 4, 1, 3, 0 }
+
#define GET_X2_COUNTER(v) ((v) >> 1)
#define LPM_STS_LATCH_MODE BIT(31)
@@ -197,6 +199,10 @@ enum ppfear_regs {
#define TGL_NUM_IP_IGN_ALLOWED 23
#define TGL_PMC_LPM_RES_COUNTER_STEP_X2 61 /* 30.5us * 2 */
+#define ADL_PMC_LTR_SPF 0x1C00
+#define ADL_NUM_IP_IGN_ALLOWED 23
+#define ADL_PMC_SLP_S0_RES_COUNTER_OFFSET 0x1098
+
/*
* Tigerlake Power Management Controller register offsets
*/
@@ -218,6 +224,18 @@ enum ppfear_regs {
/* Extended Test Mode Register LPM bits (TGL and later */
#define ETR3_CLEAR_LPM_EVENTS BIT(28)
+/* Alder Lake Power Management Controller register offsets */
+#define ADL_LPM_EN_OFFSET 0x179C
+#define ADL_LPM_RESIDENCY_OFFSET 0x17A4
+#define ADL_LPM_NUM_MODES 2
+#define ADL_LPM_NUM_MAPS 14
+
+/* Alder Lake Low Power Mode debug registers */
+#define ADL_LPM_STATUS_OFFSET 0x170C
+#define ADL_LPM_PRI_OFFSET 0x17A0
+#define ADL_LPM_STATUS_LATCH_EN_OFFSET 0x1704
+#define ADL_LPM_LIVE_STATUS_OFFSET 0x1764
+
const char *pmc_lpm_modes[] = {
"S0i2.0",
"S0i2.1",
@@ -277,6 +295,7 @@ struct pmc_reg_map {
const u32 pm_vric1_offset;
/* Low Power Mode registers */
const int lpm_num_maps;
+ const int lpm_num_modes;
const int lpm_res_counter_step_x2;
const u32 lpm_sts_latch_en_offset;
const u32 lpm_en_offset;
diff --git a/drivers/platform/x86/intel_pmc_core_pltdrv.c b/drivers/platform/x86/intel/pmc/pltdrv.c
index 73797680b895..73797680b895 100644
--- a/drivers/platform/x86/intel_pmc_core_pltdrv.c
+++ b/drivers/platform/x86/intel/pmc/pltdrv.c
diff --git a/drivers/platform/x86/intel/pmt/Kconfig b/drivers/platform/x86/intel/pmt/Kconfig
new file mode 100644
index 000000000000..d630f883a717
--- /dev/null
+++ b/drivers/platform/x86/intel/pmt/Kconfig
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Intel Platform Monitoring Technology drivers
+#
+
+config INTEL_PMT_CLASS
+ tristate
+ help
+ The Intel Platform Monitoring Technology (PMT) class driver provides
+ the basic sysfs interface and file hierarchy used by PMT devices.
+
+ For more information, see:
+ <file:Documentation/ABI/testing/sysfs-class-intel_pmt>
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_pmt_class.
+
+config INTEL_PMT_TELEMETRY
+ tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver"
+ depends on MFD_INTEL_PMT
+ select INTEL_PMT_CLASS
+ help
+ The Intel Platform Monitory Technology (PMT) Telemetry driver provides
+ access to hardware telemetry metrics on devices that support the
+ feature.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_pmt_telemetry.
+
+config INTEL_PMT_CRASHLOG
+ tristate "Intel Platform Monitoring Technology (PMT) Crashlog driver"
+ depends on MFD_INTEL_PMT
+ select INTEL_PMT_CLASS
+ help
+ The Intel Platform Monitoring Technology (PMT) crashlog driver provides
+ access to hardware crashlog capabilities on devices that support the
+ feature.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_pmt_crashlog.
diff --git a/drivers/platform/x86/intel/pmt/Makefile b/drivers/platform/x86/intel/pmt/Makefile
new file mode 100644
index 000000000000..279e158c7c23
--- /dev/null
+++ b/drivers/platform/x86/intel/pmt/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for linux/drivers/platform/x86/intel/pmt
+# Intel Platform Monitoring Technology Drivers
+#
+
+obj-$(CONFIG_INTEL_PMT_CLASS) += pmt_class.o
+pmt_class-y := class.o
+obj-$(CONFIG_INTEL_PMT_TELEMETRY) += pmt_telemetry.o
+pmt_telemetry-y := telemetry.o
+obj-$(CONFIG_INTEL_PMT_CRASHLOG) += pmt_crashlog.o
+pmt_crashlog-y := crashlog.o
diff --git a/drivers/platform/x86/intel_pmt_class.c b/drivers/platform/x86/intel/pmt/class.c
index c86ff15b1ed5..659b1073033c 100644
--- a/drivers/platform/x86/intel_pmt_class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -13,7 +13,7 @@
#include <linux/mm.h>
#include <linux/pci.h>
-#include "intel_pmt_class.h"
+#include "class.h"
#define PMT_XA_START 0
#define PMT_XA_MAX INT_MAX
diff --git a/drivers/platform/x86/intel_pmt_class.h b/drivers/platform/x86/intel/pmt/class.h
index 1337019c2873..1337019c2873 100644
--- a/drivers/platform/x86/intel_pmt_class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
diff --git a/drivers/platform/x86/intel_pmt_crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c
index 56963ceb6345..1c1021f04d3c 100644
--- a/drivers/platform/x86/intel_pmt_crashlog.c
+++ b/drivers/platform/x86/intel/pmt/crashlog.c
@@ -15,7 +15,7 @@
#include <linux/uaccess.h>
#include <linux/overflow.h>
-#include "intel_pmt_class.h"
+#include "class.h"
#define DRV_NAME "pmt_crashlog"
diff --git a/drivers/platform/x86/intel_pmt_telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index 9b95ef050457..38d52651c572 100644
--- a/drivers/platform/x86/intel_pmt_telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -15,7 +15,7 @@
#include <linux/uaccess.h>
#include <linux/overflow.h>
-#include "intel_pmt_class.h"
+#include "class.h"
#define TELEM_DEV_NAME "pmt_telemetry"
@@ -61,6 +61,14 @@ static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
/* Size is measured in DWORDS, but accessor returns bytes */
header->size = TELEM_SIZE(readl(disc_table));
+ /*
+ * Some devices may expose non-functioning entries that are
+ * reserved for future use. They have zero size. Do not fail
+ * probe for these. Just ignore them.
+ */
+ if (header->size == 0)
+ return 1;
+
return 0;
}
diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel/punit_ipc.c
index f58b8543f6ac..f58b8543f6ac 100644
--- a/drivers/platform/x86/intel_punit_ipc.c
+++ b/drivers/platform/x86/intel/punit_ipc.c
diff --git a/drivers/platform/x86/intel-rst.c b/drivers/platform/x86/intel/rst.c
index 3b81cb896fed..3b81cb896fed 100644
--- a/drivers/platform/x86/intel-rst.c
+++ b/drivers/platform/x86/intel/rst.c
diff --git a/drivers/platform/x86/intel-smartconnect.c b/drivers/platform/x86/intel/smartconnect.c
index 64c2dc93472f..64c2dc93472f 100644
--- a/drivers/platform/x86/intel-smartconnect.c
+++ b/drivers/platform/x86/intel/smartconnect.c
diff --git a/drivers/platform/x86/intel_speed_select_if/Kconfig b/drivers/platform/x86/intel/speed_select_if/Kconfig
index ce3e3dc076d2..ce3e3dc076d2 100644
--- a/drivers/platform/x86/intel_speed_select_if/Kconfig
+++ b/drivers/platform/x86/intel/speed_select_if/Kconfig
diff --git a/drivers/platform/x86/intel_speed_select_if/Makefile b/drivers/platform/x86/intel/speed_select_if/Makefile
index 856076206f35..856076206f35 100644
--- a/drivers/platform/x86/intel_speed_select_if/Makefile
+++ b/drivers/platform/x86/intel/speed_select_if/Makefile
diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
index 6f0cc679c8e5..c9a85eb2e860 100644
--- a/drivers/platform/x86/intel_speed_select_if/isst_if_common.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
@@ -265,9 +265,9 @@ static int isst_if_get_platform_info(void __user *argp)
{
struct isst_if_platform_info info;
- info.api_version = ISST_IF_API_VERSION,
- info.driver_version = ISST_IF_DRIVER_VERSION,
- info.max_cmds_per_ioctl = ISST_IF_CMD_LIMIT,
+ info.api_version = ISST_IF_API_VERSION;
+ info.driver_version = ISST_IF_DRIVER_VERSION;
+ info.max_cmds_per_ioctl = ISST_IF_CMD_LIMIT;
info.mbox_supported = punit_callbacks[ISST_IF_DEV_MBOX].registered;
info.mmio_supported = punit_callbacks[ISST_IF_DEV_MMIO].registered;
@@ -379,6 +379,8 @@ static int isst_if_cpu_online(unsigned int cpu)
u64 data;
int ret;
+ isst_cpu_info[cpu].numa_node = cpu_to_node(cpu);
+
ret = rdmsrl_safe(MSR_CPU_BUS_NUMBER, &data);
if (ret) {
/* This is not a fatal error on MSR mailbox only I/F */
@@ -397,7 +399,6 @@ static int isst_if_cpu_online(unsigned int cpu)
return ret;
}
isst_cpu_info[cpu].punit_cpu_id = data;
- isst_cpu_info[cpu].numa_node = cpu_to_node(cpu);
isst_restore_msr_local(cpu);
diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_common.h b/drivers/platform/x86/intel/speed_select_if/isst_if_common.h
index fdecdae248d7..fdecdae248d7 100644
--- a/drivers/platform/x86/intel_speed_select_if/isst_if_common.h
+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.h
diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_mbox_msr.c b/drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c
index 1b6eab071068..1b6eab071068 100644
--- a/drivers/platform/x86/intel_speed_select_if/isst_if_mbox_msr.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c
diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_mbox_pci.c b/drivers/platform/x86/intel/speed_select_if/isst_if_mbox_pci.c
index df1fc6c719f3..df1fc6c719f3 100644
--- a/drivers/platform/x86/intel_speed_select_if/isst_if_mbox_pci.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_mbox_pci.c
diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c b/drivers/platform/x86/intel/speed_select_if/isst_if_mmio.c
index ff49025ec085..ff49025ec085 100644
--- a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_mmio.c
diff --git a/drivers/platform/x86/intel/telemetry/Kconfig b/drivers/platform/x86/intel/telemetry/Kconfig
new file mode 100644
index 000000000000..da887bd03731
--- /dev/null
+++ b/drivers/platform/x86/intel/telemetry/Kconfig
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Intel x86 Platform Specific Drivers
+#
+
+config INTEL_TELEMETRY
+ tristate "Intel SoC Telemetry driver"
+ depends on X86_64
+ depends on MFD_INTEL_PMC_BXT
+ depends on INTEL_PUNIT_IPC
+ help
+ This driver provides interfaces to configure and use
+ telemetry for Intel SoC from Apollo Lake onwards.
+ It is also used to get various SoC events and parameters
+ directly via debugfs files. Various tools may use
+ this interface for SoC state monitoring.
diff --git a/drivers/platform/x86/intel/telemetry/Makefile b/drivers/platform/x86/intel/telemetry/Makefile
new file mode 100644
index 000000000000..bfdba5b6c59a
--- /dev/null
+++ b/drivers/platform/x86/intel/telemetry/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Intel x86 Platform Specific Drivers
+#
+
+intel_telemetry_core-y := core.o
+obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o
+intel_telemetry_pltdrv-y := pltdrv.o
+obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_pltdrv.o
+intel_telemetry_debugfs-y := debugfs.o
+obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_debugfs.o
diff --git a/drivers/platform/x86/intel_telemetry_core.c b/drivers/platform/x86/intel/telemetry/core.c
index fdf55b5d6948..fdf55b5d6948 100644
--- a/drivers/platform/x86/intel_telemetry_core.c
+++ b/drivers/platform/x86/intel/telemetry/core.c
diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel/telemetry/debugfs.c
index 1d4d0fbfd63c..1d4d0fbfd63c 100644
--- a/drivers/platform/x86/intel_telemetry_debugfs.c
+++ b/drivers/platform/x86/intel/telemetry/debugfs.c
diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel/telemetry/pltdrv.c
index 405dea87de6b..405dea87de6b 100644
--- a/drivers/platform/x86/intel_telemetry_pltdrv.c
+++ b/drivers/platform/x86/intel/telemetry/pltdrv.c
diff --git a/drivers/platform/x86/intel_turbo_max_3.c b/drivers/platform/x86/intel/turbo_max_3.c
index 892140b62898..892140b62898 100644
--- a/drivers/platform/x86/intel_turbo_max_3.c
+++ b/drivers/platform/x86/intel/turbo_max_3.c
diff --git a/drivers/platform/x86/intel-uncore-frequency.c b/drivers/platform/x86/intel/uncore-frequency.c
index 3ee4c5c8a64f..3ee4c5c8a64f 100644
--- a/drivers/platform/x86/intel-uncore-frequency.c
+++ b/drivers/platform/x86/intel/uncore-frequency.c
diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel/vbtn.c
index 309166431063..15f013af9e62 100644
--- a/drivers/platform/x86/intel-vbtn.c
+++ b/drivers/platform/x86/intel/vbtn.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
-#include "dual_accel_detect.h"
+#include "../dual_accel_detect.h"
/* Returned when NOT in tablet mode on some HP Stream x360 11 models */
#define VGBS_TABLET_MODE_FLAG_ALT 0x10
diff --git a/drivers/platform/x86/intel/wmi/Kconfig b/drivers/platform/x86/intel/wmi/Kconfig
new file mode 100644
index 000000000000..8e159f712179
--- /dev/null
+++ b/drivers/platform/x86/intel/wmi/Kconfig
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Intel x86 Platform Specific Drivers
+#
+
+config INTEL_WMI
+ bool
+
+config INTEL_WMI_SBL_FW_UPDATE
+ tristate "Intel WMI Slim Bootloader firmware update signaling driver"
+ depends on ACPI_WMI
+ select INTEL_WMI
+ help
+ Say Y here if you want to be able to use the WMI interface to signal
+ Slim Bootloader to trigger update on next reboot.
+
+ To compile this driver as a module, choose M here: the module will
+ be called intel-wmi-sbl-fw-update.
+
+config INTEL_WMI_THUNDERBOLT
+ tristate "Intel WMI thunderbolt force power driver"
+ depends on ACPI_WMI
+ select INTEL_WMI
+ help
+ Say Y here if you want to be able to use the WMI interface on select
+ systems to force the power control of Intel Thunderbolt controllers.
+ This is useful for updating the firmware when devices are not plugged
+ into the controller.
+
+ To compile this driver as a module, choose M here: the module will
+ be called intel-wmi-thunderbolt.
diff --git a/drivers/platform/x86/intel/wmi/Makefile b/drivers/platform/x86/intel/wmi/Makefile
new file mode 100644
index 000000000000..c2d56d25dea0
--- /dev/null
+++ b/drivers/platform/x86/intel/wmi/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Intel x86 Platform Specific Drivers
+#
+
+intel-wmi-sbl-fw-update-y := sbl-fw-update.o
+obj-$(CONFIG_INTEL_WMI_SBL_FW_UPDATE) += intel-wmi-sbl-fw-update.o
+intel-wmi-thunderbolt-y := thunderbolt.o
+obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o
diff --git a/drivers/platform/x86/intel-wmi-sbl-fw-update.c b/drivers/platform/x86/intel/wmi/sbl-fw-update.c
index 3c86e0108a24..3c86e0108a24 100644
--- a/drivers/platform/x86/intel-wmi-sbl-fw-update.c
+++ b/drivers/platform/x86/intel/wmi/sbl-fw-update.c
diff --git a/drivers/platform/x86/intel-wmi-thunderbolt.c b/drivers/platform/x86/intel/wmi/thunderbolt.c
index 4ae87060d18b..4ae87060d18b 100644
--- a/drivers/platform/x86/intel-wmi-thunderbolt.c
+++ b/drivers/platform/x86/intel/wmi/thunderbolt.c
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 9171a46a9e3f..bfa0cc20750d 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -457,7 +457,7 @@ int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd,
EXPORT_SYMBOL(intel_scu_ipc_dev_simple_command);
/**
- * intel_scu_ipc_command_with_size() - Command with data
+ * intel_scu_ipc_dev_command_with_size() - Command with data
* @scu: Optional SCU IPC instance
* @cmd: Command
* @sub: Sub type
diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c
index 20145b539335..3e520d5bca07 100644
--- a/drivers/platform/x86/lg-laptop.c
+++ b/drivers/platform/x86/lg-laptop.c
@@ -8,6 +8,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h>
+#include <linux/dmi.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/kernel.h>
@@ -16,11 +17,12 @@
#include <linux/platform_device.h>
#include <linux/types.h>
-#define LED_DEVICE(_name, max) struct led_classdev _name = { \
+#define LED_DEVICE(_name, max, flag) struct led_classdev _name = { \
.name = __stringify(_name), \
.max_brightness = max, \
.brightness_set = _name##_set, \
.brightness_get = _name##_get, \
+ .flags = flag, \
}
MODULE_AUTHOR("Matan Ziv-Av");
@@ -69,9 +71,13 @@ static u32 inited;
#define INIT_INPUT_ACPI 0x04
#define INIT_SPARSE_KEYMAP 0x80
+static int battery_limit_use_wmbb;
+static struct led_classdev kbd_backlight;
+static enum led_brightness get_kbd_backlight_level(void);
+
static const struct key_entry wmi_keymap[] = {
{KE_KEY, 0x70, {KEY_F15} }, /* LG control panel (F1) */
- {KE_KEY, 0x74, {KEY_F13} }, /* Touchpad toggle (F5) */
+ {KE_KEY, 0x74, {KEY_F21} }, /* Touchpad toggle (F5) */
{KE_KEY, 0xf020000, {KEY_F14} }, /* Read mode (F9) */
{KE_KEY, 0x10000000, {KEY_F16} },/* Keyboard backlight (F8) - pressing
* this key both sends an event and
@@ -214,10 +220,16 @@ static void wmi_notify(u32 value, void *context)
int eventcode = obj->integer.value;
struct key_entry *key;
- key =
- sparse_keymap_entry_from_scancode(wmi_input_dev, eventcode);
- if (key && key->type == KE_KEY)
- sparse_keymap_report_entry(wmi_input_dev, key, 1, true);
+ if (eventcode == 0x10000000) {
+ led_classdev_notify_brightness_hw_changed(
+ &kbd_backlight, get_kbd_backlight_level());
+ } else {
+ key = sparse_keymap_entry_from_scancode(
+ wmi_input_dev, eventcode);
+ if (key && key->type == KE_KEY)
+ sparse_keymap_report_entry(wmi_input_dev,
+ key, 1, true);
+ }
}
pr_debug("Type: %i Eventcode: 0x%llx\n", obj->type,
@@ -461,7 +473,10 @@ static ssize_t battery_care_limit_store(struct device *dev,
if (value == 100 || value == 80) {
union acpi_object *r;
- r = lg_wmab(WM_BATT_LIMIT, WM_SET, value);
+ if (battery_limit_use_wmbb)
+ r = lg_wmbb(WMBB_BATT_LIMIT, WM_SET, value);
+ else
+ r = lg_wmab(WM_BATT_LIMIT, WM_SET, value);
if (!r)
return -EIO;
@@ -479,16 +494,29 @@ static ssize_t battery_care_limit_show(struct device *dev,
unsigned int status;
union acpi_object *r;
- r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0);
- if (!r)
- return -EIO;
+ if (battery_limit_use_wmbb) {
+ r = lg_wmbb(WMBB_BATT_LIMIT, WM_GET, 0);
+ if (!r)
+ return -EIO;
- if (r->type != ACPI_TYPE_INTEGER) {
- kfree(r);
- return -EIO;
- }
+ if (r->type != ACPI_TYPE_BUFFER) {
+ kfree(r);
+ return -EIO;
+ }
- status = r->integer.value;
+ status = r->buffer.pointer[0x10];
+ } else {
+ r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0);
+ if (!r)
+ return -EIO;
+
+ if (r->type != ACPI_TYPE_INTEGER) {
+ kfree(r);
+ return -EIO;
+ }
+
+ status = r->integer.value;
+ }
kfree(r);
if (status != 80 && status != 100)
status = 0;
@@ -529,7 +557,7 @@ static enum led_brightness tpad_led_get(struct led_classdev *cdev)
return ggov(GOV_TLED) > 0 ? LED_ON : LED_OFF;
}
-static LED_DEVICE(tpad_led, 1);
+static LED_DEVICE(tpad_led, 1, 0);
static void kbd_backlight_set(struct led_classdev *cdev,
enum led_brightness brightness)
@@ -546,7 +574,7 @@ static void kbd_backlight_set(struct led_classdev *cdev,
kfree(r);
}
-static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
+static enum led_brightness get_kbd_backlight_level(void)
{
union acpi_object *r;
int val;
@@ -577,7 +605,12 @@ static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
return val;
}
-static LED_DEVICE(kbd_backlight, 255);
+static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
+{
+ return get_kbd_backlight_level();
+}
+
+static LED_DEVICE(kbd_backlight, 255, LED_BRIGHT_HW_CHANGED);
static void wmi_input_destroy(void)
{
@@ -602,6 +635,8 @@ static struct platform_driver pf_driver = {
static int acpi_add(struct acpi_device *device)
{
int ret;
+ const char *product;
+ int year = 2017;
if (pf_device)
return 0;
@@ -619,6 +654,42 @@ static int acpi_add(struct acpi_device *device)
pr_err("unable to register platform device\n");
goto out_platform_registered;
}
+ product = dmi_get_system_info(DMI_PRODUCT_NAME);
+ if (strlen(product) > 4)
+ switch (product[4]) {
+ case '5':
+ case '6':
+ year = 2016;
+ break;
+ case '7':
+ year = 2017;
+ break;
+ case '8':
+ year = 2018;
+ break;
+ case '9':
+ year = 2019;
+ break;
+ case '0':
+ if (strlen(product) > 5)
+ switch (product[5]) {
+ case 'N':
+ year = 2020;
+ break;
+ case 'P':
+ year = 2021;
+ break;
+ default:
+ year = 2022;
+ }
+ break;
+ default:
+ year = 2019;
+ }
+ pr_info("product: %s year: %d\n", product, year);
+
+ if (year >= 2019)
+ battery_limit_use_wmbb = 1;
ret = sysfs_create_group(&pf_device->dev.kobj, &dev_attribute_group);
if (ret)
diff --git a/drivers/platform/x86/meraki-mx100.c b/drivers/platform/x86/meraki-mx100.c
new file mode 100644
index 000000000000..3751ed36a980
--- /dev/null
+++ b/drivers/platform/x86/meraki-mx100.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Cisco Meraki MX100 (Tinkerbell) board platform driver
+ *
+ * Based off of arch/x86/platform/meraki/tink.c from the
+ * Meraki GPL release meraki-firmware-sources-r23-20150601
+ *
+ * Format inspired by platform/x86/pcengines-apuv2.c
+ *
+ * Copyright (C) 2021 Chris Blake <chrisrblake93@gmail.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/dmi.h>
+#include <linux/err.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio/machine.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define TINK_GPIO_DRIVER_NAME "gpio_ich"
+
+/* LEDs */
+static const struct gpio_led tink_leds[] = {
+ {
+ .name = "mx100:green:internet",
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "mx100:green:lan2",
+ },
+ {
+ .name = "mx100:green:lan3",
+ },
+ {
+ .name = "mx100:green:lan4",
+ },
+ {
+ .name = "mx100:green:lan5",
+ },
+ {
+ .name = "mx100:green:lan6",
+ },
+ {
+ .name = "mx100:green:lan7",
+ },
+ {
+ .name = "mx100:green:lan8",
+ },
+ {
+ .name = "mx100:green:lan9",
+ },
+ {
+ .name = "mx100:green:lan10",
+ },
+ {
+ .name = "mx100:green:lan11",
+ },
+ {
+ .name = "mx100:green:ha",
+ },
+ {
+ .name = "mx100:orange:ha",
+ },
+ {
+ .name = "mx100:green:usb",
+ },
+ {
+ .name = "mx100:orange:usb",
+ },
+};
+
+static const struct gpio_led_platform_data tink_leds_pdata = {
+ .num_leds = ARRAY_SIZE(tink_leds),
+ .leds = tink_leds,
+};
+
+static struct gpiod_lookup_table tink_leds_table = {
+ .dev_id = "leds-gpio",
+ .table = {
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 11,
+ NULL, 0, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 18,
+ NULL, 1, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 20,
+ NULL, 2, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 22,
+ NULL, 3, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 23,
+ NULL, 4, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 32,
+ NULL, 5, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 34,
+ NULL, 6, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 35,
+ NULL, 7, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 36,
+ NULL, 8, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 37,
+ NULL, 9, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 48,
+ NULL, 10, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 16,
+ NULL, 11, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 7,
+ NULL, 12, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 21,
+ NULL, 13, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 19,
+ NULL, 14, GPIO_ACTIVE_LOW),
+ {} /* Terminating entry */
+ }
+};
+
+/* Reset Button */
+static struct gpio_keys_button tink_buttons[] = {
+ {
+ .desc = "Reset",
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .active_low = 1,
+ .debounce_interval = 100,
+ },
+};
+
+static const struct gpio_keys_platform_data tink_buttons_pdata = {
+ .buttons = tink_buttons,
+ .nbuttons = ARRAY_SIZE(tink_buttons),
+ .poll_interval = 20,
+ .rep = 0,
+ .name = "mx100-keys",
+};
+
+static struct gpiod_lookup_table tink_keys_table = {
+ .dev_id = "gpio-keys-polled",
+ .table = {
+ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 60,
+ NULL, 0, GPIO_ACTIVE_LOW),
+ {} /* Terminating entry */
+ }
+};
+
+/* Board setup */
+static const struct dmi_system_id tink_systems[] __initconst = {
+ {
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Cisco"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MX100-HW"),
+ },
+ },
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(dmi, tink_systems);
+
+static struct platform_device *tink_leds_pdev;
+static struct platform_device *tink_keys_pdev;
+
+static struct platform_device * __init tink_create_dev(
+ const char *name, const void *pdata, size_t sz)
+{
+ struct platform_device *pdev;
+
+ pdev = platform_device_register_data(NULL,
+ name, PLATFORM_DEVID_NONE, pdata, sz);
+ if (IS_ERR(pdev))
+ pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev));
+
+ return pdev;
+}
+
+static int __init tink_board_init(void)
+{
+ int ret;
+
+ if (!dmi_first_match(tink_systems))
+ return -ENODEV;
+
+ /*
+ * We need to make sure that GPIO60 isn't set to native mode as is default since it's our
+ * Reset Button. To do this, write to GPIO_USE_SEL2 to have GPIO60 set to GPIO mode.
+ * This is documented on page 1609 of the PCH datasheet, order number 327879-005US
+ */
+ outl(inl(0x530) | BIT(28), 0x530);
+
+ gpiod_add_lookup_table(&tink_leds_table);
+ gpiod_add_lookup_table(&tink_keys_table);
+
+ tink_leds_pdev = tink_create_dev("leds-gpio",
+ &tink_leds_pdata, sizeof(tink_leds_pdata));
+ if (IS_ERR(tink_leds_pdev)) {
+ ret = PTR_ERR(tink_leds_pdev);
+ goto err;
+ }
+
+ tink_keys_pdev = tink_create_dev("gpio-keys-polled",
+ &tink_buttons_pdata, sizeof(tink_buttons_pdata));
+ if (IS_ERR(tink_keys_pdev)) {
+ ret = PTR_ERR(tink_keys_pdev);
+ platform_device_unregister(tink_leds_pdev);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ gpiod_remove_lookup_table(&tink_keys_table);
+ gpiod_remove_lookup_table(&tink_leds_table);
+ return ret;
+}
+module_init(tink_board_init);
+
+static void __exit tink_board_exit(void)
+{
+ platform_device_unregister(tink_keys_pdev);
+ platform_device_unregister(tink_leds_pdev);
+ gpiod_remove_lookup_table(&tink_keys_table);
+ gpiod_remove_lookup_table(&tink_leds_table);
+}
+module_exit(tink_board_exit);
+
+MODULE_AUTHOR("Chris Blake <chrisrblake93@gmail.com>");
+MODULE_DESCRIPTION("Cisco Meraki MX100 Platform Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:meraki-mx100");
diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
index 6cfed4427fb0..9472aae72df2 100644
--- a/drivers/platform/x86/think-lmi.c
+++ b/drivers/platform/x86/think-lmi.c
@@ -20,6 +20,10 @@
#include "firmware_attributes_class.h"
#include "think-lmi.h"
+static bool debug_support;
+module_param(debug_support, bool, 0444);
+MODULE_PARM_DESC(debug_support, "Enable debug command support");
+
/*
* Name:
* Lenovo_BiosSetting
@@ -116,6 +120,14 @@
*/
#define LENOVO_GET_BIOS_SELECTIONS_GUID "7364651A-132F-4FE7-ADAA-40C6C7EE2E3B"
+/*
+ * Name:
+ * Lenovo_DebugCmdGUID
+ * Description
+ * Debug entry GUID method for entering debug commands to the BIOS
+ */
+#define LENOVO_DEBUG_CMD_GUID "7FF47003-3B6C-4E5E-A227-E979824A85D1"
+
#define TLMI_POP_PWD (1 << 0)
#define TLMI_PAP_PWD (1 << 1)
#define to_tlmi_pwd_setting(kobj) container_of(kobj, struct tlmi_pwd_setting, kobj)
@@ -660,6 +672,64 @@ static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *
static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
+/* ---- Debug interface--------------------------------------------------------- */
+static ssize_t debug_cmd_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ char *set_str = NULL, *new_setting = NULL;
+ char *auth_str = NULL;
+ char *p;
+ int ret;
+
+ if (!tlmi_priv.can_debug_cmd)
+ return -EOPNOTSUPP;
+
+ new_setting = kstrdup(buf, GFP_KERNEL);
+ if (!new_setting)
+ return -ENOMEM;
+
+ /* Strip out CR if one is present */
+ p = strchrnul(new_setting, '\n');
+ *p = '\0';
+
+ if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
+ auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
+ tlmi_priv.pwd_admin->password,
+ encoding_options[tlmi_priv.pwd_admin->encoding],
+ tlmi_priv.pwd_admin->kbdlang);
+ if (!auth_str) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (auth_str)
+ set_str = kasprintf(GFP_KERNEL, "%s,%s", new_setting, auth_str);
+ else
+ set_str = kasprintf(GFP_KERNEL, "%s;", new_setting);
+ if (!set_str) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = tlmi_simple_call(LENOVO_DEBUG_CMD_GUID, set_str);
+ if (ret)
+ goto out;
+
+ if (!ret && !tlmi_priv.pending_changes) {
+ tlmi_priv.pending_changes = true;
+ /* let userland know it may need to check reboot pending again */
+ kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
+ }
+out:
+ kfree(auth_str);
+ kfree(set_str);
+ kfree(new_setting);
+ return ret ?: count;
+}
+
+static struct kobj_attribute debug_cmd = __ATTR_WO(debug_cmd);
+
/* ---- Initialisation --------------------------------------------------------- */
static void tlmi_release_attr(void)
{
@@ -673,6 +743,8 @@ static void tlmi_release_attr(void)
}
}
sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr);
+ if (tlmi_priv.can_debug_cmd && debug_support)
+ sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
kset_unregister(tlmi_priv.attribute_kset);
/* Authentication structures */
@@ -737,6 +809,11 @@ static int tlmi_sysfs_init(void)
if (ret)
goto fail_create_attr;
+ if (tlmi_priv.can_debug_cmd && debug_support) {
+ ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
+ if (ret)
+ goto fail_create_attr;
+ }
/* Create authentication entries */
tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL,
&tlmi_priv.class_dev->kobj);
@@ -793,6 +870,9 @@ static int tlmi_analyze(void)
if (wmi_has_guid(LENOVO_BIOS_PASSWORD_SETTINGS_GUID))
tlmi_priv.can_get_password_settings = true;
+ if (wmi_has_guid(LENOVO_DEBUG_CMD_GUID))
+ tlmi_priv.can_debug_cmd = true;
+
/*
* Try to find the number of valid settings of this machine
* and use it to create sysfs attributes.
diff --git a/drivers/platform/x86/think-lmi.h b/drivers/platform/x86/think-lmi.h
index eb598846628a..f8e26823075f 100644
--- a/drivers/platform/x86/think-lmi.h
+++ b/drivers/platform/x86/think-lmi.h
@@ -61,6 +61,7 @@ struct think_lmi {
bool can_set_bios_password;
bool can_get_password_settings;
bool pending_changes;
+ bool can_debug_cmd;
struct tlmi_attr_setting *setting[TLMI_SETTINGS_COUNT];
struct device *class_dev;
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 62e0d56a3332..a76313006bdc 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -980,7 +980,7 @@ probe_failure:
return ret;
}
-static int wmi_dev_remove(struct device *dev)
+static void wmi_dev_remove(struct device *dev)
{
struct wmi_block *wblock = dev_to_wblock(dev);
struct wmi_driver *wdriver =
@@ -997,8 +997,6 @@ static int wmi_dev_remove(struct device *dev)
if (ACPI_FAILURE(wmi_method_enable(wblock, 0)))
dev_warn(dev, "failed to disable device\n");
-
- return 0;
}
static struct class wmi_bus_class = {
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index c29d590c5e4f..cc6757dfa3f1 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -123,7 +123,7 @@ fail:
return error;
}
-static int pnp_device_remove(struct device *dev)
+static void pnp_device_remove(struct device *dev)
{
struct pnp_dev *pnp_dev = to_pnp_dev(dev);
struct pnp_driver *drv = pnp_dev->driver;
@@ -139,7 +139,6 @@ static int pnp_device_remove(struct device *dev)
pnp_disable_dev(pnp_dev);
pnp_device_detach(pnp_dev);
- return 0;
}
static void pnp_device_shutdown(struct device *dev)
diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c
index 7a41fb7b0dec..42f93d4c6ee3 100644
--- a/drivers/pps/clients/pps_parport.c
+++ b/drivers/pps/clients/pps_parport.c
@@ -22,8 +22,6 @@
#include <linux/parport.h>
#include <linux/pps_kernel.h>
-#define DRVDESC "parallel port PPS client"
-
/* module parameters */
#define CLEAR_WAIT_MAX 100
@@ -138,6 +136,12 @@ static void parport_attach(struct parport *port)
.dev = NULL
};
+ if (clear_wait > CLEAR_WAIT_MAX) {
+ pr_err("clear_wait value should be not greater then %d\n",
+ CLEAR_WAIT_MAX);
+ return;
+ }
+
device = kzalloc(sizeof(struct pps_client_pp), GFP_KERNEL);
if (!device) {
pr_err("memory allocation failed, not attaching\n");
@@ -214,38 +218,8 @@ static struct parport_driver pps_parport_driver = {
.detach = parport_detach,
.devmodel = true,
};
-
-/* module staff */
-
-static int __init pps_parport_init(void)
-{
- int ret;
-
- pr_info(DRVDESC "\n");
-
- if (clear_wait > CLEAR_WAIT_MAX) {
- pr_err("clear_wait value should be not greater"
- " then %d\n", CLEAR_WAIT_MAX);
- return -EINVAL;
- }
-
- ret = parport_register_driver(&pps_parport_driver);
- if (ret) {
- pr_err("unable to register with parport\n");
- return ret;
- }
-
- return 0;
-}
-
-static void __exit pps_parport_exit(void)
-{
- parport_unregister_driver(&pps_parport_driver);
-}
-
-module_init(pps_parport_init);
-module_exit(pps_parport_exit);
+module_parport_driver(pps_parport_driver);
MODULE_AUTHOR("Alexander Gordeev <lasaine@lvk.cs.msu.su>");
-MODULE_DESCRIPTION(DRVDESC);
+MODULE_DESCRIPTION("parallel port PPS client");
MODULE_LICENSE("GPL");
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index 72874153972e..a72bb0a40fcf 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -112,7 +112,7 @@ static int rio_device_probe(struct device *dev)
* driver, then run the driver remove() method. Then update
* the reference count.
*/
-static int rio_device_remove(struct device *dev)
+static void rio_device_remove(struct device *dev)
{
struct rio_dev *rdev = to_rio_dev(dev);
struct rio_driver *rdrv = rdev->driver;
@@ -124,8 +124,6 @@ static int rio_device_remove(struct device *dev)
}
rio_dev_put(rdev);
-
- return 0;
}
static void rio_device_shutdown(struct device *dev)
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index a79bee901e9b..401b1ec90785 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -833,6 +833,7 @@ static const struct of_device_id adsp_of_match[] = {
{ .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
{ .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
{ .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
+ { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
{ .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init},
{ .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init},
{ .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index f1cbc6b2edbb..ebadc6c08e11 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -142,18 +142,6 @@ static const struct wcnss_data pronto_v2_data = {
.num_vregs = 1,
};
-void qcom_wcnss_assign_iris(struct qcom_wcnss *wcnss,
- struct qcom_iris *iris,
- bool use_48mhz_xo)
-{
- mutex_lock(&wcnss->iris_lock);
-
- wcnss->iris = iris;
- wcnss->use_48mhz_xo = use_48mhz_xo;
-
- mutex_unlock(&wcnss->iris_lock);
-}
-
static int wcnss_load(struct rproc *rproc, const struct firmware *fw)
{
struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
@@ -639,12 +627,20 @@ static int wcnss_probe(struct platform_device *pdev)
goto detach_pds;
}
+ wcnss->iris = qcom_iris_probe(&pdev->dev, &wcnss->use_48mhz_xo);
+ if (IS_ERR(wcnss->iris)) {
+ ret = PTR_ERR(wcnss->iris);
+ goto detach_pds;
+ }
+
ret = rproc_add(rproc);
if (ret)
- goto detach_pds;
+ goto remove_iris;
- return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+ return 0;
+remove_iris:
+ qcom_iris_remove(wcnss->iris);
detach_pds:
wcnss_release_pds(wcnss);
free_rproc:
@@ -657,7 +653,7 @@ static int wcnss_remove(struct platform_device *pdev)
{
struct qcom_wcnss *wcnss = platform_get_drvdata(pdev);
- of_platform_depopulate(&pdev->dev);
+ qcom_iris_remove(wcnss->iris);
rproc_del(wcnss->rproc);
@@ -686,28 +682,7 @@ static struct platform_driver wcnss_driver = {
},
};
-static int __init wcnss_init(void)
-{
- int ret;
-
- ret = platform_driver_register(&wcnss_driver);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&qcom_iris_driver);
- if (ret)
- platform_driver_unregister(&wcnss_driver);
-
- return ret;
-}
-module_init(wcnss_init);
-
-static void __exit wcnss_exit(void)
-{
- platform_driver_unregister(&qcom_iris_driver);
- platform_driver_unregister(&wcnss_driver);
-}
-module_exit(wcnss_exit);
+module_platform_driver(wcnss_driver);
MODULE_DESCRIPTION("Qualcomm Peripheral Image Loader for Wireless Subsystem");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/qcom_wcnss.h b/drivers/remoteproc/qcom_wcnss.h
index 62c8682d0a92..6d01ee6afa7f 100644
--- a/drivers/remoteproc/qcom_wcnss.h
+++ b/drivers/remoteproc/qcom_wcnss.h
@@ -17,9 +17,9 @@ struct wcnss_vreg_info {
bool super_turbo;
};
+struct qcom_iris *qcom_iris_probe(struct device *parent, bool *use_48mhz_xo);
+void qcom_iris_remove(struct qcom_iris *iris);
int qcom_iris_enable(struct qcom_iris *iris);
void qcom_iris_disable(struct qcom_iris *iris);
-void qcom_wcnss_assign_iris(struct qcom_wcnss *wcnss, struct qcom_iris *iris, bool use_48mhz_xo);
-
#endif
diff --git a/drivers/remoteproc/qcom_wcnss_iris.c b/drivers/remoteproc/qcom_wcnss_iris.c
index 169acd305ae3..09720ddddc85 100644
--- a/drivers/remoteproc/qcom_wcnss_iris.c
+++ b/drivers/remoteproc/qcom_wcnss_iris.c
@@ -17,7 +17,7 @@
#include "qcom_wcnss.h"
struct qcom_iris {
- struct device *dev;
+ struct device dev;
struct clk *xo_clk;
@@ -75,7 +75,7 @@ int qcom_iris_enable(struct qcom_iris *iris)
ret = clk_prepare_enable(iris->xo_clk);
if (ret) {
- dev_err(iris->dev, "failed to enable xo clk\n");
+ dev_err(&iris->dev, "failed to enable xo clk\n");
goto disable_regulators;
}
@@ -93,43 +93,90 @@ void qcom_iris_disable(struct qcom_iris *iris)
regulator_bulk_disable(iris->num_vregs, iris->vregs);
}
-static int qcom_iris_probe(struct platform_device *pdev)
+static const struct of_device_id iris_of_match[] = {
+ { .compatible = "qcom,wcn3620", .data = &wcn3620_data },
+ { .compatible = "qcom,wcn3660", .data = &wcn3660_data },
+ { .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
+ { .compatible = "qcom,wcn3680", .data = &wcn3680_data },
+ {}
+};
+
+static void qcom_iris_release(struct device *dev)
+{
+ struct qcom_iris *iris = container_of(dev, struct qcom_iris, dev);
+
+ of_node_put(iris->dev.of_node);
+ kfree(iris);
+}
+
+struct qcom_iris *qcom_iris_probe(struct device *parent, bool *use_48mhz_xo)
{
+ const struct of_device_id *match;
const struct iris_data *data;
- struct qcom_wcnss *wcnss;
+ struct device_node *of_node;
struct qcom_iris *iris;
int ret;
int i;
- iris = devm_kzalloc(&pdev->dev, sizeof(struct qcom_iris), GFP_KERNEL);
- if (!iris)
- return -ENOMEM;
+ of_node = of_get_child_by_name(parent->of_node, "iris");
+ if (!of_node) {
+ dev_err(parent, "No child node \"iris\" found\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ iris = kzalloc(sizeof(*iris), GFP_KERNEL);
+ if (!iris) {
+ of_node_put(of_node);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ device_initialize(&iris->dev);
+ iris->dev.parent = parent;
+ iris->dev.release = qcom_iris_release;
+ iris->dev.of_node = of_node;
+
+ dev_set_name(&iris->dev, "%s.iris", dev_name(parent));
+
+ ret = device_add(&iris->dev);
+ if (ret) {
+ put_device(&iris->dev);
+ return ERR_PTR(ret);
+ }
+
+ match = of_match_device(iris_of_match, &iris->dev);
+ if (!match) {
+ dev_err(&iris->dev, "no matching compatible for iris\n");
+ ret = -EINVAL;
+ goto err_device_del;
+ }
- data = of_device_get_match_data(&pdev->dev);
- wcnss = dev_get_drvdata(pdev->dev.parent);
+ data = match->data;
- iris->xo_clk = devm_clk_get(&pdev->dev, "xo");
+ iris->xo_clk = devm_clk_get(&iris->dev, "xo");
if (IS_ERR(iris->xo_clk)) {
- if (PTR_ERR(iris->xo_clk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to acquire xo clk\n");
- return PTR_ERR(iris->xo_clk);
+ ret = PTR_ERR(iris->xo_clk);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&iris->dev, "failed to acquire xo clk\n");
+ goto err_device_del;
}
iris->num_vregs = data->num_vregs;
- iris->vregs = devm_kcalloc(&pdev->dev,
+ iris->vregs = devm_kcalloc(&iris->dev,
iris->num_vregs,
sizeof(struct regulator_bulk_data),
GFP_KERNEL);
- if (!iris->vregs)
- return -ENOMEM;
+ if (!iris->vregs) {
+ ret = -ENOMEM;
+ goto err_device_del;
+ }
for (i = 0; i < iris->num_vregs; i++)
iris->vregs[i].supply = data->vregs[i].name;
- ret = devm_regulator_bulk_get(&pdev->dev, iris->num_vregs, iris->vregs);
+ ret = devm_regulator_bulk_get(&iris->dev, iris->num_vregs, iris->vregs);
if (ret) {
- dev_err(&pdev->dev, "failed to get regulators\n");
- return ret;
+ dev_err(&iris->dev, "failed to get regulators\n");
+ goto err_device_del;
}
for (i = 0; i < iris->num_vregs; i++) {
@@ -143,34 +190,17 @@ static int qcom_iris_probe(struct platform_device *pdev)
data->vregs[i].load_uA);
}
- qcom_wcnss_assign_iris(wcnss, iris, data->use_48mhz_xo);
-
- return 0;
-}
+ *use_48mhz_xo = data->use_48mhz_xo;
-static int qcom_iris_remove(struct platform_device *pdev)
-{
- struct qcom_wcnss *wcnss = dev_get_drvdata(pdev->dev.parent);
+ return iris;
- qcom_wcnss_assign_iris(wcnss, NULL, false);
+err_device_del:
+ device_del(&iris->dev);
- return 0;
+ return ERR_PTR(ret);
}
-static const struct of_device_id iris_of_match[] = {
- { .compatible = "qcom,wcn3620", .data = &wcn3620_data },
- { .compatible = "qcom,wcn3660", .data = &wcn3660_data },
- { .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
- { .compatible = "qcom,wcn3680", .data = &wcn3680_data },
- {}
-};
-MODULE_DEVICE_TABLE(of, iris_of_match);
-
-struct platform_driver qcom_iris_driver = {
- .probe = qcom_iris_probe,
- .remove = qcom_iris_remove,
- .driver = {
- .name = "qcom-iris",
- .of_match_table = iris_of_match,
- },
-};
+void qcom_iris_remove(struct qcom_iris *iris)
+{
+ device_del(&iris->dev);
+}
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 7de5905d276a..502b6604b757 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -2750,8 +2750,8 @@ void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type)
dev_err(&rproc->dev, "crash detected in %s: type %s\n",
rproc->name, rproc_crash_to_string(type));
- /* create a new task to handle the error */
- schedule_work(&rproc->crash_handler);
+ /* Have a worker handle the error; ensure system is not suspended */
+ queue_work(system_freezable_wq, &rproc->crash_handler);
}
EXPORT_SYMBOL(rproc_report_crash);
diff --git a/drivers/remoteproc/remoteproc_elf_helpers.h b/drivers/remoteproc/remoteproc_elf_helpers.h
index 26404e68e17a..e6de53a5000c 100644
--- a/drivers/remoteproc/remoteproc_elf_helpers.h
+++ b/drivers/remoteproc/remoteproc_elf_helpers.h
@@ -15,7 +15,7 @@
* fw_elf_get_class - Get elf class
* @fw: the ELF firmware image
*
- * Note that we use and elf32_hdr to access the class since the start of the
+ * Note that we use elf32_hdr to access the class since the start of the
* struct is the same for both elf class
*
* Return: elf class of the firmware
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 5656cac04b4c..be799a5abf8a 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -181,6 +181,13 @@ config RESET_RASPBERRYPI
interfacing with RPi4's co-processor and model these firmware
initialization routines as reset lines.
+config RESET_RZG2L_USBPHY_CTRL
+ tristate "Renesas RZ/G2L USBPHY control driver"
+ depends on ARCH_R9A07G044 || COMPILE_TEST
+ help
+ Support for USBPHY Control found on RZ/G2L family. It mainly
+ controls reset and power down of the USB/PHY.
+
config RESET_SCMI
tristate "Reset driver controlled via ARM SCMI interface"
depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
@@ -207,7 +214,6 @@ config RESET_SIMPLE
- Realtek SoCs
- RCC reset controller in STM32 MCUs
- Allwinner SoCs
- - ZTE's zx2967 family
- SiFive FU740 SoCs
config RESET_SOCFPGA
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index ea8b8d9ca565..21d46d8869ff 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o
+obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
diff --git a/drivers/reset/reset-qcom-pdc.c b/drivers/reset/reset-qcom-pdc.c
index ab74bccd4a5b..f22bb49a4ac8 100644
--- a/drivers/reset/reset-qcom-pdc.c
+++ b/drivers/reset/reset-qcom-pdc.c
@@ -11,18 +11,26 @@
#include <dt-bindings/reset/qcom,sdm845-pdc.h>
-#define RPMH_PDC_SYNC_RESET 0x100
+#define RPMH_SDM845_PDC_SYNC_RESET 0x100
+#define RPMH_SC7280_PDC_SYNC_RESET 0x1000
struct qcom_pdc_reset_map {
u8 bit;
};
+struct qcom_pdc_reset_desc {
+ const struct qcom_pdc_reset_map *resets;
+ size_t num_resets;
+ unsigned int offset;
+};
+
struct qcom_pdc_reset_data {
struct reset_controller_dev rcdev;
struct regmap *regmap;
+ const struct qcom_pdc_reset_desc *desc;
};
-static const struct regmap_config sdm845_pdc_regmap_config = {
+static const struct regmap_config pdc_regmap_config = {
.name = "pdc-reset",
.reg_bits = 32,
.reg_stride = 4,
@@ -44,6 +52,33 @@ static const struct qcom_pdc_reset_map sdm845_pdc_resets[] = {
[PDC_MODEM_SYNC_RESET] = {9},
};
+static const struct qcom_pdc_reset_desc sdm845_pdc_reset_desc = {
+ .resets = sdm845_pdc_resets,
+ .num_resets = ARRAY_SIZE(sdm845_pdc_resets),
+ .offset = RPMH_SDM845_PDC_SYNC_RESET,
+};
+
+static const struct qcom_pdc_reset_map sc7280_pdc_resets[] = {
+ [PDC_APPS_SYNC_RESET] = {0},
+ [PDC_SP_SYNC_RESET] = {1},
+ [PDC_AUDIO_SYNC_RESET] = {2},
+ [PDC_SENSORS_SYNC_RESET] = {3},
+ [PDC_AOP_SYNC_RESET] = {4},
+ [PDC_DEBUG_SYNC_RESET] = {5},
+ [PDC_GPU_SYNC_RESET] = {6},
+ [PDC_DISPLAY_SYNC_RESET] = {7},
+ [PDC_COMPUTE_SYNC_RESET] = {8},
+ [PDC_MODEM_SYNC_RESET] = {9},
+ [PDC_WLAN_RF_SYNC_RESET] = {10},
+ [PDC_WPSS_SYNC_RESET] = {11},
+};
+
+static const struct qcom_pdc_reset_desc sc7280_pdc_reset_desc = {
+ .resets = sc7280_pdc_resets,
+ .num_resets = ARRAY_SIZE(sc7280_pdc_resets),
+ .offset = RPMH_SC7280_PDC_SYNC_RESET,
+};
+
static inline struct qcom_pdc_reset_data *to_qcom_pdc_reset_data(
struct reset_controller_dev *rcdev)
{
@@ -54,19 +89,18 @@ static int qcom_pdc_control_assert(struct reset_controller_dev *rcdev,
unsigned long idx)
{
struct qcom_pdc_reset_data *data = to_qcom_pdc_reset_data(rcdev);
+ u32 mask = BIT(data->desc->resets[idx].bit);
- return regmap_update_bits(data->regmap, RPMH_PDC_SYNC_RESET,
- BIT(sdm845_pdc_resets[idx].bit),
- BIT(sdm845_pdc_resets[idx].bit));
+ return regmap_update_bits(data->regmap, data->desc->offset, mask, mask);
}
static int qcom_pdc_control_deassert(struct reset_controller_dev *rcdev,
unsigned long idx)
{
struct qcom_pdc_reset_data *data = to_qcom_pdc_reset_data(rcdev);
+ u32 mask = BIT(data->desc->resets[idx].bit);
- return regmap_update_bits(data->regmap, RPMH_PDC_SYNC_RESET,
- BIT(sdm845_pdc_resets[idx].bit), 0);
+ return regmap_update_bits(data->regmap, data->desc->offset, mask, 0);
}
static const struct reset_control_ops qcom_pdc_reset_ops = {
@@ -76,22 +110,27 @@ static const struct reset_control_ops qcom_pdc_reset_ops = {
static int qcom_pdc_reset_probe(struct platform_device *pdev)
{
+ const struct qcom_pdc_reset_desc *desc;
struct qcom_pdc_reset_data *data;
struct device *dev = &pdev->dev;
void __iomem *base;
struct resource *res;
+ desc = device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+ data->desc = desc;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
- data->regmap = devm_regmap_init_mmio(dev, base,
- &sdm845_pdc_regmap_config);
+ data->regmap = devm_regmap_init_mmio(dev, base, &pdc_regmap_config);
if (IS_ERR(data->regmap)) {
dev_err(dev, "Unable to initialize regmap\n");
return PTR_ERR(data->regmap);
@@ -99,14 +138,15 @@ static int qcom_pdc_reset_probe(struct platform_device *pdev)
data->rcdev.owner = THIS_MODULE;
data->rcdev.ops = &qcom_pdc_reset_ops;
- data->rcdev.nr_resets = ARRAY_SIZE(sdm845_pdc_resets);
+ data->rcdev.nr_resets = desc->num_resets;
data->rcdev.of_node = dev->of_node;
return devm_reset_controller_register(dev, &data->rcdev);
}
static const struct of_device_id qcom_pdc_reset_of_match[] = {
- { .compatible = "qcom,sdm845-pdc-global" },
+ { .compatible = "qcom,sc7280-pdc-global", .data = &sc7280_pdc_reset_desc },
+ { .compatible = "qcom,sdm845-pdc-global", .data = &sdm845_pdc_reset_desc },
{}
};
MODULE_DEVICE_TABLE(of, qcom_pdc_reset_of_match);
diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
new file mode 100644
index 000000000000..e0704fd2b533
--- /dev/null
+++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2L USBPHY control driver
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/reset-controller.h>
+
+#define RESET 0x000
+
+#define RESET_SEL_PLLRESET BIT(12)
+#define RESET_PLLRESET BIT(8)
+
+#define RESET_SEL_P2RESET BIT(5)
+#define RESET_SEL_P1RESET BIT(4)
+#define RESET_PHYRST_2 BIT(1)
+#define RESET_PHYRST_1 BIT(0)
+
+#define PHY_RESET_PORT2 (RESET_SEL_P2RESET | RESET_PHYRST_2)
+#define PHY_RESET_PORT1 (RESET_SEL_P1RESET | RESET_PHYRST_1)
+
+#define NUM_PORTS 2
+
+struct rzg2l_usbphy_ctrl_priv {
+ struct reset_controller_dev rcdev;
+ struct reset_control *rstc;
+ void __iomem *base;
+
+ spinlock_t lock;
+};
+
+#define rcdev_to_priv(x) container_of(x, struct rzg2l_usbphy_ctrl_priv, rcdev)
+
+static int rzg2l_usbphy_ctrl_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rzg2l_usbphy_ctrl_priv *priv = rcdev_to_priv(rcdev);
+ u32 port_mask = PHY_RESET_PORT1 | PHY_RESET_PORT2;
+ void __iomem *base = priv->base;
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ val = readl(base + RESET);
+ val |= id ? PHY_RESET_PORT2 : PHY_RESET_PORT1;
+ if (port_mask == (val & port_mask))
+ val |= RESET_PLLRESET;
+ writel(val, base + RESET);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int rzg2l_usbphy_ctrl_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rzg2l_usbphy_ctrl_priv *priv = rcdev_to_priv(rcdev);
+ void __iomem *base = priv->base;
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ val = readl(base + RESET);
+
+ val |= RESET_SEL_PLLRESET;
+ val &= ~(RESET_PLLRESET | (id ? PHY_RESET_PORT2 : PHY_RESET_PORT1));
+ writel(val, base + RESET);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int rzg2l_usbphy_ctrl_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rzg2l_usbphy_ctrl_priv *priv = rcdev_to_priv(rcdev);
+ u32 port_mask;
+
+ port_mask = id ? PHY_RESET_PORT2 : PHY_RESET_PORT1;
+
+ return !!(readl(priv->base + RESET) & port_mask);
+}
+
+static const struct of_device_id rzg2l_usbphy_ctrl_match_table[] = {
+ { .compatible = "renesas,rzg2l-usbphy-ctrl" },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rzg2l_usbphy_ctrl_match_table);
+
+static const struct reset_control_ops rzg2l_usbphy_ctrl_reset_ops = {
+ .assert = rzg2l_usbphy_ctrl_assert,
+ .deassert = rzg2l_usbphy_ctrl_deassert,
+ .status = rzg2l_usbphy_ctrl_status,
+};
+
+static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rzg2l_usbphy_ctrl_priv *priv;
+ unsigned long flags;
+ int error;
+ u32 val;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(priv->rstc))
+ return dev_err_probe(dev, PTR_ERR(priv->rstc),
+ "failed to get reset\n");
+
+ reset_control_deassert(priv->rstc);
+
+ priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops;
+ priv->rcdev.of_reset_n_cells = 1;
+ priv->rcdev.nr_resets = NUM_PORTS;
+ priv->rcdev.of_node = dev->of_node;
+ priv->rcdev.dev = dev;
+
+ error = devm_reset_controller_register(dev, &priv->rcdev);
+ if (error)
+ return error;
+
+ spin_lock_init(&priv->lock);
+ dev_set_drvdata(dev, priv);
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_resume_and_get(&pdev->dev);
+
+ /* put pll and phy into reset state */
+ spin_lock_irqsave(&priv->lock, flags);
+ val = readl(priv->base + RESET);
+ val |= RESET_SEL_PLLRESET | RESET_PLLRESET | PHY_RESET_PORT2 | PHY_RESET_PORT1;
+ writel(val, priv->base + RESET);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int rzg2l_usbphy_ctrl_remove(struct platform_device *pdev)
+{
+ struct rzg2l_usbphy_ctrl_priv *priv = dev_get_drvdata(&pdev->dev);
+
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ reset_control_assert(priv->rstc);
+
+ return 0;
+}
+
+static struct platform_driver rzg2l_usbphy_ctrl_driver = {
+ .driver = {
+ .name = "rzg2l_usbphy_ctrl",
+ .of_match_table = rzg2l_usbphy_ctrl_match_table,
+ },
+ .probe = rzg2l_usbphy_ctrl_probe,
+ .remove = rzg2l_usbphy_ctrl_remove,
+};
+module_platform_driver(rzg2l_usbphy_ctrl_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas RZ/G2L USBPHY Control");
+MODULE_AUTHOR("biju.das.jz@bp.renesas.com>");
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index c1404d3dae2c..9151836190ce 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -530,14 +530,13 @@ out:
return err;
}
-static int rpmsg_dev_remove(struct device *dev)
+static void rpmsg_dev_remove(struct device *dev)
{
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
- int err = 0;
if (rpdev->ops->announce_destroy)
- err = rpdev->ops->announce_destroy(rpdev);
+ rpdev->ops->announce_destroy(rpdev);
if (rpdrv->remove)
rpdrv->remove(rpdev);
@@ -546,8 +545,6 @@ static int rpmsg_dev_remove(struct device *dev)
if (rpdev->ept)
rpmsg_destroy_ept(rpdev->ept);
-
- return err;
}
static struct bus_type rpmsg_bus = {
diff --git a/drivers/s390/block/scm_drv.c b/drivers/s390/block/scm_drv.c
index 3134fd6e058e..69a845eb8b1f 100644
--- a/drivers/s390/block/scm_drv.c
+++ b/drivers/s390/block/scm_drv.c
@@ -60,15 +60,13 @@ out:
return ret;
}
-static int scm_remove(struct scm_device *scmdev)
+static void scm_remove(struct scm_device *scmdev)
{
struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev);
scm_blk_dev_cleanup(bdev);
dev_set_drvdata(&scmdev->dev, NULL);
kfree(bdev);
-
- return 0;
}
static struct scm_driver scm_drv = {
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 67c0009ca545..f356607835d8 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -1076,13 +1076,13 @@ static int __init tty3215_init(void)
if (!CONSOLE_IS_3215)
return 0;
- driver = alloc_tty_driver(NR_3215);
- if (!driver)
- return -ENOMEM;
+ driver = tty_alloc_driver(NR_3215, TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
ret = ccw_driver_register(&raw3215_ccw_driver);
if (ret) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
return ret;
}
/*
@@ -1101,11 +1101,10 @@ static int __init tty3215_init(void)
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
driver->init_termios.c_oflag = ONLCR;
driver->init_termios.c_lflag = ISIG;
- driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &tty3215_ops);
ret = tty_register_driver(driver);
if (ret) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
return ret;
}
tty3215_driver = driver;
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 6be9de8ed37d..971fbb52740b 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -503,20 +503,20 @@ sclp_tty_init(void)
return 0;
if (!sclp.has_linemode)
return 0;
- driver = alloc_tty_driver(1);
- if (!driver)
- return -ENOMEM;
+ driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
rc = sclp_rw_init();
if (rc) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
return rc;
}
/* Allocate pages for output buffering */
for (i = 0; i < MAX_KMEM_PAGES; i++) {
page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (page == NULL) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
return -ENOMEM;
}
list_add_tail((struct list_head *) page, &sclp_tty_pages);
@@ -532,7 +532,7 @@ sclp_tty_init(void)
rc = sclp_register(&sclp_input_event);
if (rc) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
return rc;
}
@@ -548,12 +548,11 @@ sclp_tty_init(void)
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
driver->init_termios.c_oflag = ONLCR;
driver->init_termios.c_lflag = ISIG | ECHO;
- driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &sclp_ops);
tty_port_link_device(&sclp_port, driver, 0);
rc = tty_register_driver(driver);
if (rc) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
tty_port_destroy(&sclp_port);
return rc;
}
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index da2496306c04..29a6a0099f83 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -732,9 +732,9 @@ static int __init sclp_vt220_tty_init(void)
/* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
* symmetry between VM and LPAR systems regarding ttyS1. */
- driver = alloc_tty_driver(1);
- if (!driver)
- return -ENOMEM;
+ driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
rc = __sclp_vt220_init(MAX_KMEM_PAGES);
if (rc)
goto out_driver;
@@ -746,7 +746,6 @@ static int __init sclp_vt220_tty_init(void)
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
- driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &sclp_vt220_ops);
tty_port_link_device(&sclp_vt220_port, driver, 0);
@@ -764,7 +763,7 @@ out_reg:
out_init:
__sclp_vt220_cleanup();
out_driver:
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
return rc;
}
__initcall(sclp_vt220_tty_init);
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index adc33846bf8e..5c83f71c1d0e 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -1935,7 +1935,7 @@ static int __init tty3270_init(void)
tty_set_operations(driver, &tty3270_ops);
ret = tty_register_driver(driver);
if (ret) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
return ret;
}
tty3270_driver = driver;
@@ -1952,7 +1952,7 @@ tty3270_exit(void)
driver = tty3270_driver;
tty3270_driver = NULL;
tty_unregister_driver(driver);
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
tty3270_del_views();
}
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index acbe76a76fb2..2ec741106cb6 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -439,17 +439,13 @@ module_exit(cleanup_ccwgroup);
/************************** driver stuff ******************************/
-static int ccwgroup_remove(struct device *dev)
+static void ccwgroup_remove(struct device *dev)
{
struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
- if (!dev->driver)
- return 0;
if (gdrv->remove)
gdrv->remove(gdev);
-
- return 0;
}
static void ccwgroup_shutdown(struct device *dev)
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index c42405c620b5..684348d82f08 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -100,7 +100,7 @@ static int chsc_subchannel_probe(struct subchannel *sch)
return ret;
}
-static int chsc_subchannel_remove(struct subchannel *sch)
+static void chsc_subchannel_remove(struct subchannel *sch)
{
struct chsc_private *private;
@@ -112,7 +112,6 @@ static int chsc_subchannel_remove(struct subchannel *sch)
put_device(&sch->dev);
}
kfree(private);
- return 0;
}
static void chsc_subchannel_shutdown(struct subchannel *sch)
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 0ce48a354e04..3377097e65de 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1401,15 +1401,14 @@ static int css_probe(struct device *dev)
return ret;
}
-static int css_remove(struct device *dev)
+static void css_remove(struct device *dev)
{
struct subchannel *sch;
- int ret;
sch = to_subchannel(dev);
- ret = sch->driver->remove ? sch->driver->remove(sch) : 0;
+ if (sch->driver->remove)
+ sch->driver->remove(sch);
sch->driver = NULL;
- return ret;
}
static void css_shutdown(struct device *dev)
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 2eddfc47f687..c98522cbe276 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -81,7 +81,7 @@ struct css_driver {
int (*chp_event)(struct subchannel *, struct chp_link *, int);
int (*sch_event)(struct subchannel *, int);
int (*probe)(struct subchannel *);
- int (*remove)(struct subchannel *);
+ void (*remove)(struct subchannel *);
void (*shutdown)(struct subchannel *);
int (*settle)(void);
};
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 84f659cafe76..adf33b653d87 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -137,7 +137,7 @@ static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env)
static void io_subchannel_irq(struct subchannel *);
static int io_subchannel_probe(struct subchannel *);
-static int io_subchannel_remove(struct subchannel *);
+static void io_subchannel_remove(struct subchannel *);
static void io_subchannel_shutdown(struct subchannel *);
static int io_subchannel_sch_event(struct subchannel *, int);
static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
@@ -1101,7 +1101,7 @@ out_schedule:
return 0;
}
-static int io_subchannel_remove(struct subchannel *sch)
+static void io_subchannel_remove(struct subchannel *sch)
{
struct io_subchannel_private *io_priv = to_io_private(sch);
struct ccw_device *cdev;
@@ -1120,7 +1120,6 @@ out_free:
io_priv->dma_area, io_priv->dma_area_dma);
kfree(io_priv);
sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
- return 0;
}
static void io_subchannel_verify(struct subchannel *sch)
@@ -1742,7 +1741,7 @@ ccw_device_probe (struct device *dev)
return 0;
}
-static int ccw_device_remove(struct device *dev)
+static void ccw_device_remove(struct device *dev)
{
struct ccw_device *cdev = to_ccwdev(dev);
struct ccw_driver *cdrv = cdev->drv;
@@ -1776,8 +1775,6 @@ static int ccw_device_remove(struct device *dev)
spin_unlock_irq(cdev->ccwlock);
io_subchannel_quiesce(sch);
__disable_cmf(cdev);
-
- return 0;
}
static void ccw_device_shutdown(struct device *dev)
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index c8964e0a23e7..15bdae5981ca 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -282,7 +282,7 @@ disable:
spin_unlock_irq(sch->lock);
}
-static int eadm_subchannel_remove(struct subchannel *sch)
+static void eadm_subchannel_remove(struct subchannel *sch)
{
struct eadm_private *private = get_eadm_private(sch);
@@ -297,8 +297,6 @@ static int eadm_subchannel_remove(struct subchannel *sch)
spin_unlock_irq(sch->lock);
kfree(private);
-
- return 0;
}
static void eadm_subchannel_shutdown(struct subchannel *sch)
diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c
index 9f26d4310bb3..b6b4589c70bd 100644
--- a/drivers/s390/cio/scm.c
+++ b/drivers/s390/cio/scm.c
@@ -28,12 +28,13 @@ static int scmdev_probe(struct device *dev)
return scmdrv->probe ? scmdrv->probe(scmdev) : -ENODEV;
}
-static int scmdev_remove(struct device *dev)
+static void scmdev_remove(struct device *dev)
{
struct scm_device *scmdev = to_scm_dev(dev);
struct scm_driver *scmdrv = to_scm_drv(dev->driver);
- return scmdrv->remove ? scmdrv->remove(scmdev) : -ENODEV;
+ if (scmdrv->remove)
+ scmdrv->remove(scmdev);
}
static int scmdev_uevent(struct device *dev, struct kobj_uevent_env *env)
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 9b61e9b131ad..76099bcb765b 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -234,7 +234,7 @@ out_free:
return ret;
}
-static int vfio_ccw_sch_remove(struct subchannel *sch)
+static void vfio_ccw_sch_remove(struct subchannel *sch)
{
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
struct vfio_ccw_crw *crw, *temp;
@@ -257,7 +257,6 @@ static int vfio_ccw_sch_remove(struct subchannel *sch)
VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n",
sch->schid.cssid, sch->schid.ssid,
sch->schid.sch_no);
- return 0;
}
static void vfio_ccw_sch_shutdown(struct subchannel *sch)
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index c57d2a7f0919..7f540ad0b568 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -159,7 +159,7 @@ static int vfio_ccw_mdev_remove(struct mdev_device *mdev)
return 0;
}
-static int vfio_ccw_mdev_open(struct mdev_device *mdev)
+static int vfio_ccw_mdev_open_device(struct mdev_device *mdev)
{
struct vfio_ccw_private *private =
dev_get_drvdata(mdev_parent_dev(mdev));
@@ -194,7 +194,7 @@ out_unregister:
return ret;
}
-static void vfio_ccw_mdev_release(struct mdev_device *mdev)
+static void vfio_ccw_mdev_close_device(struct mdev_device *mdev)
{
struct vfio_ccw_private *private =
dev_get_drvdata(mdev_parent_dev(mdev));
@@ -638,8 +638,8 @@ static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
.supported_type_groups = mdev_type_groups,
.create = vfio_ccw_mdev_create,
.remove = vfio_ccw_mdev_remove,
- .open = vfio_ccw_mdev_open,
- .release = vfio_ccw_mdev_release,
+ .open_device = vfio_ccw_mdev_open_device,
+ .close_device = vfio_ccw_mdev_close_device,
.read = vfio_ccw_mdev_read,
.write = vfio_ccw_mdev_write,
.ioctl = vfio_ccw_mdev_ioctl,
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 439c1f6d2866..f433428057d9 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -890,7 +890,7 @@ out:
return rc;
}
-static int ap_device_remove(struct device *dev)
+static void ap_device_remove(struct device *dev)
{
struct ap_device *ap_dev = to_ap_dev(dev);
struct ap_driver *ap_drv = to_ap_drv(dev->driver);
@@ -914,8 +914,6 @@ static int ap_device_remove(struct device *dev)
spin_unlock_bh(&ap_queues_lock);
put_device(dev);
-
- return 0;
}
struct ap_queue *ap_get_qdev(ap_qid_t qid)
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 67f145589f58..118939a7729a 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -24,8 +24,9 @@
#define VFIO_AP_MDEV_TYPE_HWVIRT "passthrough"
#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
-static int vfio_ap_mdev_reset_queues(struct mdev_device *mdev);
+static int vfio_ap_mdev_reset_queues(struct ap_matrix_mdev *matrix_mdev);
static struct vfio_ap_queue *vfio_ap_find_queue(int apqn);
+static const struct vfio_device_ops vfio_ap_matrix_dev_ops;
static int match_apqn(struct device *dev, const void *data)
{
@@ -295,15 +296,6 @@ static int handle_pqap(struct kvm_vcpu *vcpu)
matrix_mdev = container_of(vcpu->kvm->arch.crypto.pqap_hook,
struct ap_matrix_mdev, pqap_hook);
- /*
- * If the KVM pointer is in the process of being set, wait until the
- * process has completed.
- */
- wait_event_cmd(matrix_mdev->wait_for_kvm,
- !matrix_mdev->kvm_busy,
- mutex_unlock(&matrix_dev->lock),
- mutex_lock(&matrix_dev->lock));
-
/* If the there is no guest using the mdev, there is nothing to do */
if (!matrix_mdev->kvm)
goto out_unlock;
@@ -336,45 +328,57 @@ static void vfio_ap_matrix_init(struct ap_config_info *info,
matrix->adm_max = info->apxa ? info->Nd : 15;
}
-static int vfio_ap_mdev_create(struct mdev_device *mdev)
+static int vfio_ap_mdev_probe(struct mdev_device *mdev)
{
struct ap_matrix_mdev *matrix_mdev;
+ int ret;
if ((atomic_dec_if_positive(&matrix_dev->available_instances) < 0))
return -EPERM;
matrix_mdev = kzalloc(sizeof(*matrix_mdev), GFP_KERNEL);
if (!matrix_mdev) {
- atomic_inc(&matrix_dev->available_instances);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_dec_available;
}
+ vfio_init_group_dev(&matrix_mdev->vdev, &mdev->dev,
+ &vfio_ap_matrix_dev_ops);
matrix_mdev->mdev = mdev;
vfio_ap_matrix_init(&matrix_dev->info, &matrix_mdev->matrix);
- init_waitqueue_head(&matrix_mdev->wait_for_kvm);
- mdev_set_drvdata(mdev, matrix_mdev);
- matrix_mdev->pqap_hook.hook = handle_pqap;
- matrix_mdev->pqap_hook.owner = THIS_MODULE;
+ matrix_mdev->pqap_hook = handle_pqap;
mutex_lock(&matrix_dev->lock);
list_add(&matrix_mdev->node, &matrix_dev->mdev_list);
mutex_unlock(&matrix_dev->lock);
+ ret = vfio_register_group_dev(&matrix_mdev->vdev);
+ if (ret)
+ goto err_list;
+ dev_set_drvdata(&mdev->dev, matrix_mdev);
return 0;
+
+err_list:
+ mutex_lock(&matrix_dev->lock);
+ list_del(&matrix_mdev->node);
+ mutex_unlock(&matrix_dev->lock);
+ kfree(matrix_mdev);
+err_dec_available:
+ atomic_inc(&matrix_dev->available_instances);
+ return ret;
}
-static int vfio_ap_mdev_remove(struct mdev_device *mdev)
+static void vfio_ap_mdev_remove(struct mdev_device *mdev)
{
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(&mdev->dev);
+
+ vfio_unregister_group_dev(&matrix_mdev->vdev);
mutex_lock(&matrix_dev->lock);
- vfio_ap_mdev_reset_queues(mdev);
+ vfio_ap_mdev_reset_queues(matrix_mdev);
list_del(&matrix_mdev->node);
kfree(matrix_mdev);
- mdev_set_drvdata(mdev, NULL);
atomic_inc(&matrix_dev->available_instances);
mutex_unlock(&matrix_dev->lock);
-
- return 0;
}
static ssize_t name_show(struct mdev_type *mtype,
@@ -614,16 +618,12 @@ static ssize_t assign_adapter_store(struct device *dev,
{
int ret;
unsigned long apid;
- struct mdev_device *mdev = mdev_from_dev(dev);
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
mutex_lock(&matrix_dev->lock);
- /*
- * If the KVM pointer is in flux or the guest is running, disallow
- * un-assignment of adapter
- */
- if (matrix_mdev->kvm_busy || matrix_mdev->kvm) {
+ /* If the KVM guest is running, disallow assignment of adapter */
+ if (matrix_mdev->kvm) {
ret = -EBUSY;
goto done;
}
@@ -685,16 +685,12 @@ static ssize_t unassign_adapter_store(struct device *dev,
{
int ret;
unsigned long apid;
- struct mdev_device *mdev = mdev_from_dev(dev);
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
mutex_lock(&matrix_dev->lock);
- /*
- * If the KVM pointer is in flux or the guest is running, disallow
- * un-assignment of adapter
- */
- if (matrix_mdev->kvm_busy || matrix_mdev->kvm) {
+ /* If the KVM guest is running, disallow unassignment of adapter */
+ if (matrix_mdev->kvm) {
ret = -EBUSY;
goto done;
}
@@ -773,17 +769,13 @@ static ssize_t assign_domain_store(struct device *dev,
{
int ret;
unsigned long apqi;
- struct mdev_device *mdev = mdev_from_dev(dev);
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
unsigned long max_apqi = matrix_mdev->matrix.aqm_max;
mutex_lock(&matrix_dev->lock);
- /*
- * If the KVM pointer is in flux or the guest is running, disallow
- * assignment of domain
- */
- if (matrix_mdev->kvm_busy || matrix_mdev->kvm) {
+ /* If the KVM guest is running, disallow assignment of domain */
+ if (matrix_mdev->kvm) {
ret = -EBUSY;
goto done;
}
@@ -840,16 +832,12 @@ static ssize_t unassign_domain_store(struct device *dev,
{
int ret;
unsigned long apqi;
- struct mdev_device *mdev = mdev_from_dev(dev);
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
mutex_lock(&matrix_dev->lock);
- /*
- * If the KVM pointer is in flux or the guest is running, disallow
- * un-assignment of domain
- */
- if (matrix_mdev->kvm_busy || matrix_mdev->kvm) {
+ /* If the KVM guest is running, disallow unassignment of domain */
+ if (matrix_mdev->kvm) {
ret = -EBUSY;
goto done;
}
@@ -893,16 +881,12 @@ static ssize_t assign_control_domain_store(struct device *dev,
{
int ret;
unsigned long id;
- struct mdev_device *mdev = mdev_from_dev(dev);
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
mutex_lock(&matrix_dev->lock);
- /*
- * If the KVM pointer is in flux or the guest is running, disallow
- * assignment of control domain.
- */
- if (matrix_mdev->kvm_busy || matrix_mdev->kvm) {
+ /* If the KVM guest is running, disallow assignment of control domain */
+ if (matrix_mdev->kvm) {
ret = -EBUSY;
goto done;
}
@@ -949,17 +933,13 @@ static ssize_t unassign_control_domain_store(struct device *dev,
{
int ret;
unsigned long domid;
- struct mdev_device *mdev = mdev_from_dev(dev);
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
unsigned long max_domid = matrix_mdev->matrix.adm_max;
mutex_lock(&matrix_dev->lock);
- /*
- * If the KVM pointer is in flux or the guest is running, disallow
- * un-assignment of control domain.
- */
- if (matrix_mdev->kvm_busy || matrix_mdev->kvm) {
+ /* If a KVM guest is running, disallow unassignment of control domain */
+ if (matrix_mdev->kvm) {
ret = -EBUSY;
goto done;
}
@@ -988,8 +968,7 @@ static ssize_t control_domains_show(struct device *dev,
int nchars = 0;
int n;
char *bufpos = buf;
- struct mdev_device *mdev = mdev_from_dev(dev);
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
unsigned long max_domid = matrix_mdev->matrix.adm_max;
mutex_lock(&matrix_dev->lock);
@@ -1007,8 +986,7 @@ static DEVICE_ATTR_RO(control_domains);
static ssize_t matrix_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct mdev_device *mdev = mdev_from_dev(dev);
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
char *bufpos = buf;
unsigned long apid;
unsigned long apqi;
@@ -1098,23 +1076,30 @@ static int vfio_ap_mdev_set_kvm(struct ap_matrix_mdev *matrix_mdev,
struct ap_matrix_mdev *m;
if (kvm->arch.crypto.crycbd) {
+ down_write(&kvm->arch.crypto.pqap_hook_rwsem);
+ kvm->arch.crypto.pqap_hook = &matrix_mdev->pqap_hook;
+ up_write(&kvm->arch.crypto.pqap_hook_rwsem);
+
+ mutex_lock(&kvm->lock);
+ mutex_lock(&matrix_dev->lock);
+
list_for_each_entry(m, &matrix_dev->mdev_list, node) {
- if (m != matrix_mdev && m->kvm == kvm)
+ if (m != matrix_mdev && m->kvm == kvm) {
+ mutex_unlock(&kvm->lock);
+ mutex_unlock(&matrix_dev->lock);
return -EPERM;
+ }
}
kvm_get_kvm(kvm);
- matrix_mdev->kvm_busy = true;
- mutex_unlock(&matrix_dev->lock);
+ matrix_mdev->kvm = kvm;
kvm_arch_crypto_set_masks(kvm,
matrix_mdev->matrix.apm,
matrix_mdev->matrix.aqm,
matrix_mdev->matrix.adm);
- mutex_lock(&matrix_dev->lock);
- kvm->arch.crypto.pqap_hook = &matrix_mdev->pqap_hook;
- matrix_mdev->kvm = kvm;
- matrix_mdev->kvm_busy = false;
- wake_up_all(&matrix_mdev->wait_for_kvm);
+
+ mutex_unlock(&kvm->lock);
+ mutex_unlock(&matrix_dev->lock);
}
return 0;
@@ -1163,28 +1148,24 @@ static int vfio_ap_mdev_iommu_notifier(struct notifier_block *nb,
* certain circumstances, will result in a circular lock dependency if this is
* done under the @matrix_mdev->lock.
*/
-static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev)
+static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev,
+ struct kvm *kvm)
{
- /*
- * If the KVM pointer is in the process of being set, wait until the
- * process has completed.
- */
- wait_event_cmd(matrix_mdev->wait_for_kvm,
- !matrix_mdev->kvm_busy,
- mutex_unlock(&matrix_dev->lock),
- mutex_lock(&matrix_dev->lock));
+ if (kvm && kvm->arch.crypto.crycbd) {
+ down_write(&kvm->arch.crypto.pqap_hook_rwsem);
+ kvm->arch.crypto.pqap_hook = NULL;
+ up_write(&kvm->arch.crypto.pqap_hook_rwsem);
- if (matrix_mdev->kvm) {
- matrix_mdev->kvm_busy = true;
- mutex_unlock(&matrix_dev->lock);
- kvm_arch_crypto_clear_masks(matrix_mdev->kvm);
+ mutex_lock(&kvm->lock);
mutex_lock(&matrix_dev->lock);
- vfio_ap_mdev_reset_queues(matrix_mdev->mdev);
- matrix_mdev->kvm->arch.crypto.pqap_hook = NULL;
- kvm_put_kvm(matrix_mdev->kvm);
+
+ kvm_arch_crypto_clear_masks(kvm);
+ vfio_ap_mdev_reset_queues(matrix_mdev);
+ kvm_put_kvm(kvm);
matrix_mdev->kvm = NULL;
- matrix_mdev->kvm_busy = false;
- wake_up_all(&matrix_mdev->wait_for_kvm);
+
+ mutex_unlock(&kvm->lock);
+ mutex_unlock(&matrix_dev->lock);
}
}
@@ -1197,16 +1178,13 @@ static int vfio_ap_mdev_group_notifier(struct notifier_block *nb,
if (action != VFIO_GROUP_NOTIFY_SET_KVM)
return NOTIFY_OK;
- mutex_lock(&matrix_dev->lock);
matrix_mdev = container_of(nb, struct ap_matrix_mdev, group_notifier);
if (!data)
- vfio_ap_mdev_unset_kvm(matrix_mdev);
+ vfio_ap_mdev_unset_kvm(matrix_mdev, matrix_mdev->kvm);
else if (vfio_ap_mdev_set_kvm(matrix_mdev, data))
notify_rc = NOTIFY_DONE;
- mutex_unlock(&matrix_dev->lock);
-
return notify_rc;
}
@@ -1276,13 +1254,12 @@ free_resources:
return ret;
}
-static int vfio_ap_mdev_reset_queues(struct mdev_device *mdev)
+static int vfio_ap_mdev_reset_queues(struct ap_matrix_mdev *matrix_mdev)
{
int ret;
int rc = 0;
unsigned long apid, apqi;
struct vfio_ap_queue *q;
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
for_each_set_bit_inv(apid, matrix_mdev->matrix.apm,
matrix_mdev->matrix.apm_max + 1) {
@@ -1303,52 +1280,45 @@ static int vfio_ap_mdev_reset_queues(struct mdev_device *mdev)
return rc;
}
-static int vfio_ap_mdev_open(struct mdev_device *mdev)
+static int vfio_ap_mdev_open_device(struct vfio_device *vdev)
{
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ struct ap_matrix_mdev *matrix_mdev =
+ container_of(vdev, struct ap_matrix_mdev, vdev);
unsigned long events;
int ret;
-
- if (!try_module_get(THIS_MODULE))
- return -ENODEV;
-
matrix_mdev->group_notifier.notifier_call = vfio_ap_mdev_group_notifier;
events = VFIO_GROUP_NOTIFY_SET_KVM;
- ret = vfio_register_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
+ ret = vfio_register_notifier(vdev->dev, VFIO_GROUP_NOTIFY,
&events, &matrix_mdev->group_notifier);
- if (ret) {
- module_put(THIS_MODULE);
+ if (ret)
return ret;
- }
matrix_mdev->iommu_notifier.notifier_call = vfio_ap_mdev_iommu_notifier;
events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
- ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
+ ret = vfio_register_notifier(vdev->dev, VFIO_IOMMU_NOTIFY,
&events, &matrix_mdev->iommu_notifier);
- if (!ret)
- return ret;
+ if (ret)
+ goto out_unregister_group;
+ return 0;
- vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
+out_unregister_group:
+ vfio_unregister_notifier(vdev->dev, VFIO_GROUP_NOTIFY,
&matrix_mdev->group_notifier);
- module_put(THIS_MODULE);
return ret;
}
-static void vfio_ap_mdev_release(struct mdev_device *mdev)
+static void vfio_ap_mdev_close_device(struct vfio_device *vdev)
{
- struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
-
- mutex_lock(&matrix_dev->lock);
- vfio_ap_mdev_unset_kvm(matrix_mdev);
- mutex_unlock(&matrix_dev->lock);
+ struct ap_matrix_mdev *matrix_mdev =
+ container_of(vdev, struct ap_matrix_mdev, vdev);
- vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
+ vfio_unregister_notifier(vdev->dev, VFIO_IOMMU_NOTIFY,
&matrix_mdev->iommu_notifier);
- vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
+ vfio_unregister_notifier(vdev->dev, VFIO_GROUP_NOTIFY,
&matrix_mdev->group_notifier);
- module_put(THIS_MODULE);
+ vfio_ap_mdev_unset_kvm(matrix_mdev, matrix_mdev->kvm);
}
static int vfio_ap_mdev_get_device_info(unsigned long arg)
@@ -1371,11 +1341,12 @@ static int vfio_ap_mdev_get_device_info(unsigned long arg)
return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
}
-static ssize_t vfio_ap_mdev_ioctl(struct mdev_device *mdev,
+static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev,
unsigned int cmd, unsigned long arg)
{
+ struct ap_matrix_mdev *matrix_mdev =
+ container_of(vdev, struct ap_matrix_mdev, vdev);
int ret;
- struct ap_matrix_mdev *matrix_mdev;
mutex_lock(&matrix_dev->lock);
switch (cmd) {
@@ -1383,22 +1354,7 @@ static ssize_t vfio_ap_mdev_ioctl(struct mdev_device *mdev,
ret = vfio_ap_mdev_get_device_info(arg);
break;
case VFIO_DEVICE_RESET:
- matrix_mdev = mdev_get_drvdata(mdev);
- if (WARN(!matrix_mdev, "Driver data missing from mdev!!")) {
- ret = -EINVAL;
- break;
- }
-
- /*
- * If the KVM pointer is in the process of being set, wait until
- * the process has completed.
- */
- wait_event_cmd(matrix_mdev->wait_for_kvm,
- !matrix_mdev->kvm_busy,
- mutex_unlock(&matrix_dev->lock),
- mutex_lock(&matrix_dev->lock));
-
- ret = vfio_ap_mdev_reset_queues(mdev);
+ ret = vfio_ap_mdev_reset_queues(matrix_mdev);
break;
default:
ret = -EOPNOTSUPP;
@@ -1409,25 +1365,51 @@ static ssize_t vfio_ap_mdev_ioctl(struct mdev_device *mdev,
return ret;
}
+static const struct vfio_device_ops vfio_ap_matrix_dev_ops = {
+ .open_device = vfio_ap_mdev_open_device,
+ .close_device = vfio_ap_mdev_close_device,
+ .ioctl = vfio_ap_mdev_ioctl,
+};
+
+static struct mdev_driver vfio_ap_matrix_driver = {
+ .driver = {
+ .name = "vfio_ap_mdev",
+ .owner = THIS_MODULE,
+ .mod_name = KBUILD_MODNAME,
+ .dev_groups = vfio_ap_mdev_attr_groups,
+ },
+ .probe = vfio_ap_mdev_probe,
+ .remove = vfio_ap_mdev_remove,
+};
+
static const struct mdev_parent_ops vfio_ap_matrix_ops = {
.owner = THIS_MODULE,
+ .device_driver = &vfio_ap_matrix_driver,
.supported_type_groups = vfio_ap_mdev_type_groups,
- .mdev_attr_groups = vfio_ap_mdev_attr_groups,
- .create = vfio_ap_mdev_create,
- .remove = vfio_ap_mdev_remove,
- .open = vfio_ap_mdev_open,
- .release = vfio_ap_mdev_release,
- .ioctl = vfio_ap_mdev_ioctl,
};
int vfio_ap_mdev_register(void)
{
+ int ret;
+
atomic_set(&matrix_dev->available_instances, MAX_ZDEV_ENTRIES_EXT);
- return mdev_register_device(&matrix_dev->device, &vfio_ap_matrix_ops);
+ ret = mdev_register_driver(&vfio_ap_matrix_driver);
+ if (ret)
+ return ret;
+
+ ret = mdev_register_device(&matrix_dev->device, &vfio_ap_matrix_ops);
+ if (ret)
+ goto err_driver;
+ return 0;
+
+err_driver:
+ mdev_unregister_driver(&vfio_ap_matrix_driver);
+ return ret;
}
void vfio_ap_mdev_unregister(void)
{
mdev_unregister_device(&matrix_dev->device);
+ mdev_unregister_driver(&vfio_ap_matrix_driver);
}
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index f82a6396acae..77760e2b546f 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/kvm_host.h>
+#include <linux/vfio.h>
#include "ap_bus.h"
@@ -79,14 +80,13 @@ struct ap_matrix {
* @kvm: the struct holding guest's state
*/
struct ap_matrix_mdev {
+ struct vfio_device vdev;
struct list_head node;
struct ap_matrix matrix;
struct notifier_block group_notifier;
struct notifier_block iommu_notifier;
- bool kvm_busy;
- wait_queue_head_t wait_for_kvm;
struct kvm *kvm;
- struct kvm_s390_module_hook pqap_hook;
+ crypto_hook pqap_hook;
struct mdev_device *mdev;
};
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 2e4804ef2fb9..6da8f6d05d39 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -2377,7 +2377,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
}
}
- blk_add_driver_data(scsi->request, &blktrc, sizeof(blktrc));
+ blk_add_driver_data(scsi_cmd_to_rq(scsi), &blktrc, sizeof(blktrc));
}
/**
@@ -2599,8 +2599,8 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
io->fcp_cmnd_length = FCP_CMND_LEN;
if (scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) {
- io->data_block_length = scsi_cmnd->device->sector_size;
- io->ref_tag_value = scsi_get_lba(scsi_cmnd) & 0xFFFFFFFF;
+ io->data_block_length = scsi_prot_interval(scsi_cmnd);
+ io->ref_tag_value = scsi_prot_ref_tag(scsi_cmnd);
}
if (zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction))
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 1c6b4e672687..a12e3525977d 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1823,7 +1823,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
if ((hostdata->tag_negotiated & (1<<scmd_id(SCp))) &&
SCp->device->simple_tags) {
- slot->tag = SCp->request->tag;
+ slot->tag = scsi_cmd_to_rq(SCp)->tag;
CDEBUG(KERN_DEBUG, SCp, "sending out tag %d, slot %p\n",
slot->tag, slot);
} else {
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index adddcd589941..40088dcb98cd 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -1711,7 +1711,7 @@ static bool __init blogic_reportconfig(struct blogic_adapter *adapter)
if (adapter->adapter_bus_type != BLOGIC_PCI_BUS) {
blogic_info(" DMA Channel: None, ", adapter);
if (adapter->bios_addr > 0)
- blogic_info("BIOS Address: 0x%lX, ", adapter,
+ blogic_info("BIOS Address: 0x%X, ", adapter,
adapter->bios_addr);
else
blogic_info("BIOS Address: None, ", adapter);
@@ -3436,7 +3436,7 @@ static void blogic_msg(enum blogic_msglevel msglevel, char *fmt,
int len = 0;
va_start(args, adapter);
- len = vsprintf(buf, fmt, args);
+ len = vscnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (msglevel == BLOGIC_ANNOUNCE_LEVEL) {
static int msglines = 0;
@@ -3451,7 +3451,7 @@ static void blogic_msg(enum blogic_msglevel msglevel, char *fmt,
if (buf[0] != '\n' || len > 1)
printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
} else
- printk("%s", buf);
+ pr_cont("%s", buf);
} else {
if (begin) {
if (adapter != NULL && adapter->adapter_initd)
@@ -3459,7 +3459,7 @@ static void blogic_msg(enum blogic_msglevel msglevel, char *fmt,
else
printk("%s%s", blogic_msglevelmap[msglevel], buf);
} else
- printk("%s", buf);
+ pr_cont("%s", buf);
}
begin = (buf[len - 1] == '\n');
}
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 8f44d433e06e..6e3a04107bb6 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -14,12 +14,16 @@ config RAID_ATTRS
help
Provides RAID
+config SCSI_COMMON
+ tristate
+
config SCSI
tristate "SCSI device support"
depends on BLOCK
select SCSI_DMA if HAS_DMA
select SG_POOL
- select BLK_SCSI_REQUEST
+ select SCSI_COMMON
+ select BLK_DEV_BSG_COMMON if BLK_DEV_BSG
help
If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
any other SCSI device under Linux, say Y and make sure that you know
@@ -140,6 +144,18 @@ config CHR_DEV_SG
If unsure, say N.
+config BLK_DEV_BSG
+ bool "/dev/bsg support (SG v4)"
+ depends on SCSI
+ default y
+ help
+ Saying Y here will enable generic SG (SCSI generic) v4 support
+ for any SCSI device.
+
+ This option is required by UDEV to access device serial numbers, etc.
+
+ If unsure, say Y.
+
config CHR_DEV_SCH
tristate "SCSI media changer support"
depends on SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1748d1ec1338..19814c26c908 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -20,7 +20,7 @@ CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF
obj-$(CONFIG_PCMCIA) += pcmcia/
obj-$(CONFIG_SCSI) += scsi_mod.o
-obj-$(CONFIG_BLK_SCSI_REQUEST) += scsi_common.o
+obj-$(CONFIG_SCSI_COMMON) += scsi_common.o
obj-$(CONFIG_RAID_ATTRS) += raid_class.o
@@ -168,6 +168,7 @@ scsi_mod-$(CONFIG_BLK_DEBUG_FS) += scsi_debugfs.o
scsi_mod-y += scsi_trace.o scsi_logging.o
scsi_mod-$(CONFIG_PM) += scsi_pm.o
scsi_mod-$(CONFIG_SCSI_DH) += scsi_dh.o
+scsi_mod-$(CONFIG_BLK_DEV_BSG) += scsi_bsg.o
hv_storvsc-y := storvsc_drv.o
@@ -183,7 +184,7 @@ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
zalon7xx-objs := zalon.o ncr53c8xx.o
# Files generated that shall be removed upon make clean
-clean-files := 53c700_d.h 53c700_u.h scsi_devinfo_tbl.c
+clean-files := 53c700_d.h 53c700_u.h
$(obj)/53c700.o: $(obj)/53c700_d.h
@@ -192,9 +193,11 @@ $(obj)/scsi_sysfs.o: $(obj)/scsi_devinfo_tbl.c
quiet_cmd_bflags = GEN $@
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
+$(obj)/scsi_devinfo_tbl.c: include/scsi/scsi_devinfo.h FORCE
$(call if_changed,bflags)
+targets += scsi_devinfo_tbl.c
+
# If you want to play with the firmware, uncomment
# GENERATE_FIRMWARE := 1
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 3baadd068768..a85589a2a8af 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -778,7 +778,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
}
#ifdef CONFIG_SUN3
- if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) {
+ if (sun3scsi_dma_finish(hostdata->connected->sc_data_direction)) {
pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n",
instance->host_no);
BUG();
@@ -1710,7 +1710,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
count = sun3scsi_dma_xfer_len(hostdata, cmd);
if (count > 0) {
- if (rq_data_dir(cmd->request))
+ if (cmd->sc_data_direction == DMA_TO_DEVICE)
sun3scsi_dma_send_setup(hostdata,
cmd->SCp.ptr, count);
else
@@ -2158,7 +2158,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
count = sun3scsi_dma_xfer_len(hostdata, tmp);
if (count > 0) {
- if (rq_data_dir(tmp->request))
+ if (tmp->sc_data_direction == DMA_TO_DEVICE)
sun3scsi_dma_send_setup(hostdata,
tmp->SCp.ptr, count);
else
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 46b8dffce2dd..c2d6f0a9e0b1 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -25,7 +25,6 @@
#include <linux/completion.h>
#include <linux/blkdev.h>
#include <linux/uaccess.h>
-#include <linux/highmem.h> /* For flush_kernel_dcache_page */
#include <linux/module.h>
#include <asm/unaligned.h>
@@ -1505,7 +1504,7 @@ static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd
srbcmd->id = cpu_to_le32(scmd_id(cmd));
srbcmd->lun = cpu_to_le32(cmd->device->lun);
srbcmd->flags = cpu_to_le32(flag);
- timeout = cmd->request->timeout/HZ;
+ timeout = scsi_cmd_to_rq(cmd)->timeout / HZ;
if (timeout == 0)
timeout = (dev->sa_firmware ? AAC_SA_TIMEOUT : AAC_ARC_TIMEOUT);
srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 54eb4d41bc2c..deb32c9f4b3e 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -224,7 +224,7 @@ struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd)
{
struct fib *fibptr;
- fibptr = &dev->fibs[scmd->request->tag];
+ fibptr = &dev->fibs[scsi_cmd_to_rq(scmd)->tag];
/*
* Null out fields that depend on being zero at the start of
* each I/O
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index f3377e2ef5fb..ffb391967573 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -7423,7 +7423,7 @@ static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
* Set the srb_tag to the command tag + 1, as
* srb_tag '0' is used internally by the chip.
*/
- srb_tag = scp->request->tag + 1;
+ srb_tag = scsi_cmd_to_rq(scp)->tag + 1;
asc_scsi_q->q2.srb_tag = srb_tag;
/*
@@ -7637,7 +7637,7 @@ static int
adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp,
adv_req_t **adv_reqpp)
{
- u32 srb_tag = scp->request->tag;
+ u32 srb_tag = scsi_cmd_to_rq(scp)->tag;
adv_req_t *reqp;
ADV_SCSI_REQ_Q *scsiqp;
int ret;
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 1210e61afb18..584a59522038 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -262,11 +262,12 @@ static void aha1542_free_cmd(struct scsi_cmnd *cmd)
struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+ struct request *rq = scsi_cmd_to_rq(cmd);
void *buf = acmd->data_buffer;
struct req_iterator iter;
struct bio_vec bv;
- rq_for_each_segment(bv, cmd->request, iter) {
+ rq_for_each_segment(bv, rq, iter) {
memcpy_to_page(bv.bv_page, bv.bv_offset, buf,
bv.bv_len);
buf += bv.bv_len;
@@ -447,11 +448,12 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
#endif
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+ struct request *rq = scsi_cmd_to_rq(cmd);
void *buf = acmd->data_buffer;
struct req_iterator iter;
struct bio_vec bv;
- rq_for_each_segment(bv, cmd->request, iter) {
+ rq_for_each_segment(bv, rq, iter) {
memcpy_from_page(buf, bv.bv_page, bv.bv_offset,
bv.bv_len);
buf += bv.bv_len;
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 462717bbb5b7..4e899ec1477d 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -235,8 +235,7 @@ static int beiscsi_exec_nemb_cmd(struct beiscsi_hba *phba,
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
- rc = -ENOMEM;
- goto free_cmd;
+ return -ENOMEM;
}
sge = nonembedded_sgl(wrb);
@@ -269,24 +268,6 @@ static int beiscsi_exec_nemb_cmd(struct beiscsi_hba *phba,
/* copy the response, if any */
if (resp_buf)
memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);
- /**
- * This is special case of NTWK_GET_IF_INFO where the size of
- * response is not known. beiscsi_if_get_info checks the return
- * value to free DMA buffer.
- */
- if (rc == -EAGAIN)
- return rc;
-
- /**
- * If FW is busy that is driver timed out, DMA buffer is saved with
- * the tag, only when the cmd completes this buffer is freed.
- */
- if (rc == -EBUSY)
- return rc;
-
-free_cmd:
- dma_free_coherent(&ctrl->pdev->dev, nonemb_cmd->size,
- nonemb_cmd->va, nonemb_cmd->dma);
return rc;
}
@@ -309,6 +290,19 @@ static int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba,
return 0;
}
+static void beiscsi_free_nemb_cmd(struct beiscsi_hba *phba,
+ struct be_dma_mem *cmd, int rc)
+{
+ /*
+ * If FW is busy the DMA buffer is saved with the tag. When the cmd
+ * completes this buffer is freed.
+ */
+ if (rc == -EBUSY)
+ return;
+
+ dma_free_coherent(&phba->ctrl.pdev->dev, cmd->size, cmd->va, cmd->dma);
+}
+
static void __beiscsi_eq_delay_compl(struct beiscsi_hba *phba, unsigned int tag)
{
struct be_dma_mem *tag_mem;
@@ -344,8 +338,16 @@ int beiscsi_modify_eq_delay(struct beiscsi_hba *phba,
cpu_to_le32(set_eqd[i].delay_multiplier);
}
- return beiscsi_exec_nemb_cmd(phba, &nonemb_cmd,
- __beiscsi_eq_delay_compl, NULL, 0);
+ rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, __beiscsi_eq_delay_compl,
+ NULL, 0);
+ if (rc) {
+ /*
+ * Only free on failure. Async cmds are handled like -EBUSY
+ * where it's handled for us.
+ */
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
+ }
+ return rc;
}
/**
@@ -372,6 +374,7 @@ int beiscsi_get_initiator_name(struct beiscsi_hba *phba, char *name, bool cfg)
req->hdr.version = 1;
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL,
&resp, sizeof(resp));
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
if (rc) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
@@ -449,7 +452,9 @@ static int beiscsi_if_mod_gw(struct beiscsi_hba *phba,
req->ip_addr.ip_type = ip_type;
memcpy(req->ip_addr.addr, gw,
(ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN);
- return beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
+ rt_val = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rt_val);
+ return rt_val;
}
int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw)
@@ -499,8 +504,10 @@ int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type,
req = nonemb_cmd.va;
req->ip_type = ip_type;
- return beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL,
- resp, sizeof(*resp));
+ rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, resp,
+ sizeof(*resp));
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
+ return rc;
}
static int
@@ -537,6 +544,7 @@ beiscsi_if_clr_ip(struct beiscsi_hba *phba,
"BG_%d : failed to clear IP: rc %d status %d\n",
rc, req->ip_params.ip_record.status);
}
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
return rc;
}
@@ -581,6 +589,7 @@ beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip,
if (req->ip_params.ip_record.status)
rc = -EINVAL;
}
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
return rc;
}
@@ -608,6 +617,7 @@ int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,
reldhcp->interface_hndl = phba->interface_handle;
reldhcp->ip_type = ip_type;
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
if (rc < 0) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BG_%d : failed to release existing DHCP: %d\n",
@@ -689,7 +699,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
dhcpreq->interface_hndl = phba->interface_handle;
dhcpreq->ip_type = ip_type;
rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
-
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
exit:
kfree(if_info);
return rc;
@@ -762,11 +772,8 @@ int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
"BG_%d : Memory Allocation Failure\n");
- /* Free the DMA memory for the IOCTL issuing */
- dma_free_coherent(&phba->ctrl.pdev->dev,
- nonemb_cmd.size,
- nonemb_cmd.va,
- nonemb_cmd.dma);
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd,
+ -ENOMEM);
return -ENOMEM;
}
@@ -781,15 +788,13 @@ int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type,
nonemb_cmd.va)->actual_resp_len;
ioctl_size += sizeof(struct be_cmd_req_hdr);
- /* Free the previous allocated DMA memory */
- dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,
- nonemb_cmd.va,
- nonemb_cmd.dma);
-
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
/* Free the virtual memory */
kfree(*if_info);
- } else
+ } else {
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
break;
+ }
} while (true);
return rc;
}
@@ -806,8 +811,9 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba,
if (rc)
return rc;
- return beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL,
- nic, sizeof(*nic));
+ rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, nic, sizeof(*nic));
+ beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
+ return rc;
}
static void beiscsi_boot_process_compl(struct beiscsi_hba *phba,
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 43e8a1dafec0..5521469ce678 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1918,7 +1918,7 @@ static int bnx2i_queue_scsi_cmd_resp(struct iscsi_session *session,
spin_unlock(&session->back_lock);
- p = &per_cpu(bnx2i_percpu, blk_mq_rq_cpu(sc->request));
+ p = &per_cpu(bnx2i_percpu, blk_mq_rq_cpu(scsi_cmd_to_rq(sc)));
spin_lock(&p->p_work_lock);
if (unlikely(!p->iothread)) {
rc = -EINVAL;
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index fc7197abfcdf..27012908b586 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -618,6 +618,12 @@ ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
return 0;
}
+struct changer_element_status32 {
+ int ces_type;
+ compat_uptr_t ces_data;
+};
+#define CHIOGSTATUS32 _IOW('c', 8, struct changer_element_status32)
+
static long ch_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -748,7 +754,20 @@ static long ch_ioctl(struct file *file,
return ch_gstatus(ch, ces.ces_type, ces.ces_data);
}
+#ifdef CONFIG_COMPAT
+ case CHIOGSTATUS32:
+ {
+ struct changer_element_status32 ces32;
+ if (copy_from_user(&ces32, argp, sizeof(ces32)))
+ return -EFAULT;
+ if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
+ return -EINVAL;
+
+ return ch_gstatus(ch, ces32.ces_type,
+ compat_ptr(ces32.ces_data));
+ }
+#endif
case CHIOGELEM:
{
struct changer_get_element cge;
@@ -858,59 +877,11 @@ static long ch_ioctl(struct file *file,
}
default:
- return scsi_ioctl(ch->device, cmd, argp);
+ return scsi_ioctl(ch->device, NULL, file->f_mode, cmd, argp);
}
}
-#ifdef CONFIG_COMPAT
-
-struct changer_element_status32 {
- int ces_type;
- compat_uptr_t ces_data;
-};
-#define CHIOGSTATUS32 _IOW('c', 8,struct changer_element_status32)
-
-static long ch_ioctl_compat(struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- scsi_changer *ch = file->private_data;
- int retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
- file->f_flags & O_NDELAY);
- if (retval)
- return retval;
-
- switch (cmd) {
- case CHIOGPARAMS:
- case CHIOGVPARAMS:
- case CHIOPOSITION:
- case CHIOMOVE:
- case CHIOEXCHANGE:
- case CHIOGELEM:
- case CHIOINITELEM:
- case CHIOSVOLTAG:
- /* compatible */
- return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
- case CHIOGSTATUS32:
- {
- struct changer_element_status32 ces32;
- unsigned char __user *data;
-
- if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
- return -EFAULT;
- if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
- return -EINVAL;
-
- data = compat_ptr(ces32.ces_data);
- return ch_gstatus(ch, ces32.ces_type, data);
- }
- default:
- return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg));
-
- }
-}
-#endif
-
/* ------------------------------------------------------------------------ */
static int ch_probe(struct device *dev)
@@ -1015,9 +986,7 @@ static const struct file_operations changer_fops = {
.open = ch_open,
.release = ch_release,
.unlocked_ioctl = ch_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = ch_ioctl_compat,
-#endif
+ .compat_ioctl = compat_ptr_ioctl,
.llseek = noop_llseek,
};
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
index 56b9ad0a1ca0..3b2eb6ce1fcf 100644
--- a/drivers/scsi/csiostor/csio_scsi.c
+++ b/drivers/scsi/csiostor/csio_scsi.c
@@ -1786,7 +1786,7 @@ csio_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmnd)
struct csio_scsi_qset *sqset;
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
- sqset = &hw->sqset[ln->portid][blk_mq_rq_cpu(cmnd->request)];
+ sqset = &hw->sqset[ln->portid][blk_mq_rq_cpu(scsi_cmd_to_rq(cmnd))];
nr = fc_remote_port_chkready(rport);
if (nr) {
@@ -1989,13 +1989,13 @@ inval_scmnd:
csio_info(hw,
"Aborted SCSI command to (%d:%llu) tag %u\n",
cmnd->device->id, cmnd->device->lun,
- cmnd->request->tag);
+ scsi_cmd_to_rq(cmnd)->tag);
return SUCCESS;
} else {
csio_info(hw,
"Failed to abort SCSI command, (%d:%llu) tag %u\n",
cmnd->device->id, cmnd->device->lun,
- cmnd->request->tag);
+ scsi_cmd_to_rq(cmnd)->tag);
return FAILED;
}
}
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 222593bc2afe..2f1894588e0b 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -433,7 +433,7 @@ static u32 cmd_to_target_hwq(struct Scsi_Host *host, struct scsi_cmnd *scp,
hwq = afu->hwq_rr_count++ % afu->num_hwqs;
break;
case HWQ_MODE_TAG:
- tag = blk_mq_unique_tag(scp->request);
+ tag = blk_mq_unique_tag(scsi_cmd_to_rq(scp));
hwq = blk_mq_unique_tag_to_hwq(tag);
break;
case HWQ_MODE_CPU:
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index a18a4a08f049..7af96d14c9bc 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -652,7 +652,7 @@ static int adpt_abort(struct scsi_cmnd * cmd)
msg[2] = 0;
msg[3]= 0;
/* Add 1 to avoid firmware treating it as invalid command */
- msg[4] = cmd->request->tag + 1;
+ msg[4] = scsi_cmd_to_rq(cmd)->tag + 1;
if (pHba->host)
spin_lock_irq(pHba->host->host_lock);
rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER);
@@ -2236,7 +2236,7 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d
msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid);
msg[2] = 0;
/* Add 1 to avoid firmware treating it as invalid command */
- msg[3] = cmd->request->tag + 1;
+ msg[3] = scsi_cmd_to_rq(cmd)->tag + 1;
// Our cards use the transaction context as the tag for queueing
// Adaptec/DPT Private stuff
msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16);
diff --git a/drivers/scsi/elx/efct/efct_driver.h b/drivers/scsi/elx/efct/efct_driver.h
index dab8eac4f243..0e3c931db7c2 100644
--- a/drivers/scsi/elx/efct/efct_driver.h
+++ b/drivers/scsi/elx/efct/efct_driver.h
@@ -10,7 +10,6 @@
/***************************************************************************
* OS specific includes
*/
-#include <stdarg.h>
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/firmware.h>
diff --git a/drivers/scsi/elx/efct/efct_lio.c b/drivers/scsi/elx/efct/efct_lio.c
index e0d798d6baee..bb3b460dc0bc 100644
--- a/drivers/scsi/elx/efct/efct_lio.c
+++ b/drivers/scsi/elx/efct/efct_lio.c
@@ -780,7 +780,7 @@ efct_lio_npiv_make_nport(struct target_fabric_configfs *tf,
{
struct efct_lio_vport *lio_vport;
struct efct *efct;
- int ret = -1;
+ int ret;
u64 p_wwpn, npiv_wwpn, npiv_wwnn;
char *p, *pbuf, tmp[128];
struct efct_lio_vport_list_t *vport_list;
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 762cc8bd2653..f8afbfb468dc 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -107,7 +107,7 @@ static void fnic_cleanup_io(struct fnic *fnic);
static inline spinlock_t *fnic_io_lock_hash(struct fnic *fnic,
struct scsi_cmnd *sc)
{
- u32 hash = sc->request->tag & (FNIC_IO_LOCKS - 1);
+ u32 hash = scsi_cmd_to_rq(sc)->tag & (FNIC_IO_LOCKS - 1);
return &fnic->io_req_lock[hash];
}
@@ -390,7 +390,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
(rp->flags & FC_RP_FLAGS_RETRY))
exch_flags |= FCPIO_ICMND_SRFLAG_RETRY;
- fnic_queue_wq_copy_desc_icmnd_16(wq, sc->request->tag,
+ fnic_queue_wq_copy_desc_icmnd_16(wq, scsi_cmd_to_rq(sc)->tag,
0, exch_flags, io_req->sgl_cnt,
SCSI_SENSE_BUFFERSIZE,
io_req->sgl_list_pa,
@@ -422,6 +422,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
*/
static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
{
+ const int tag = scsi_cmd_to_rq(sc)->tag;
struct fc_lport *lp = shost_priv(sc->device->host);
struct fc_rport *rport;
struct fnic_io_req *io_req = NULL;
@@ -511,8 +512,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
sg_count = scsi_dma_map(sc);
if (sg_count < 0) {
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
- sc->request->tag, sc, 0, sc->cmnd[0],
- sg_count, CMD_STATE(sc));
+ tag, sc, 0, sc->cmnd[0], sg_count, CMD_STATE(sc));
mempool_free(io_req, fnic->io_req_pool);
goto out;
}
@@ -571,7 +571,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
* refetch the pointer under the lock.
*/
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
- sc->request->tag, sc, 0, 0, 0,
+ tag, sc, 0, 0, 0,
(((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
io_req = (struct fnic_io_req *)CMD_SP(sc);
CMD_SP(sc) = NULL;
@@ -603,8 +603,7 @@ out:
sc->cmnd[5]);
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
- sc->request->tag, sc, io_req,
- sg_count, cmd_trace,
+ tag, sc, io_req, sg_count, cmd_trace,
(((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
/* if only we issued IO, will we have the io lock */
@@ -1364,6 +1363,7 @@ int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do)
static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data,
bool reserved)
{
+ const int tag = scsi_cmd_to_rq(sc)->tag;
struct fnic *fnic = data;
struct fnic_io_req *io_req;
unsigned long flags = 0;
@@ -1371,7 +1371,7 @@ static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data,
unsigned long start_time = 0;
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
- io_lock = fnic_io_lock_tag(fnic, sc->request->tag);
+ io_lock = fnic_io_lock_tag(fnic, tag);
spin_lock_irqsave(io_lock, flags);
io_req = (struct fnic_io_req *)CMD_SP(sc);
@@ -1413,7 +1413,7 @@ cleanup_scsi_cmd:
sc->result = DID_TRANSPORT_DISRUPTED << 16;
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"fnic_cleanup_io: tag:0x%x : sc:0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
- sc->request->tag, sc, (jiffies - start_time));
+ tag, sc, jiffies - start_time);
if (atomic64_read(&fnic->io_cmpl_skip))
atomic64_dec(&fnic->io_cmpl_skip);
@@ -1425,10 +1425,10 @@ cleanup_scsi_cmd:
if (!(CMD_FLAGS(sc) & FNIC_IO_ISSUED))
shost_printk(KERN_ERR, fnic->lport->host,
"Calling done for IO not issued to fw: tag:0x%x sc:0x%p\n",
- sc->request->tag, sc);
+ tag, sc);
FNIC_TRACE(fnic_cleanup_io,
- sc->device->host->host_no, sc->request->tag, sc,
+ sc->device->host->host_no, tag, sc,
jiffies_to_msecs(jiffies - start_time),
0, ((u64)sc->cmnd[0] << 32 |
(u64)sc->cmnd[2] << 24 |
@@ -1566,7 +1566,7 @@ static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data,
{
struct fnic_rport_abort_io_iter_data *iter_data = data;
struct fnic *fnic = iter_data->fnic;
- int abt_tag = sc->request->tag;
+ int abt_tag = scsi_cmd_to_rq(sc)->tag;
struct fnic_io_req *io_req;
spinlock_t *io_lock;
unsigned long flags;
@@ -1727,6 +1727,7 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
*/
int fnic_abort_cmd(struct scsi_cmnd *sc)
{
+ struct request *const rq = scsi_cmd_to_rq(sc);
struct fc_lport *lp;
struct fnic *fnic;
struct fnic_io_req *io_req = NULL;
@@ -1741,7 +1742,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
struct abort_stats *abts_stats;
struct terminate_stats *term_stats;
enum fnic_ioreq_state old_ioreq_state;
- int tag;
+ const int tag = rq->tag;
unsigned long abt_issued_time;
DECLARE_COMPLETION_ONSTACK(tm_done);
@@ -1757,7 +1758,6 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
term_stats = &fnic->fnic_stats.term_stats;
rport = starget_to_rport(scsi_target(sc->device));
- tag = sc->request->tag;
FNIC_SCSI_DBG(KERN_DEBUG,
fnic->lport->host,
"Abort Cmd called FCID 0x%x, LUN 0x%llx TAG %x flags %x\n",
@@ -1842,8 +1842,8 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
/* Now queue the abort command to firmware */
int_to_scsilun(sc->device->lun, &fc_lun);
- if (fnic_queue_abort_io_req(fnic, sc->request->tag, task_req,
- fc_lun.scsi_lun, io_req)) {
+ if (fnic_queue_abort_io_req(fnic, tag, task_req, fc_lun.scsi_lun,
+ io_req)) {
spin_lock_irqsave(io_lock, flags);
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
CMD_STATE(sc) = old_ioreq_state;
@@ -1943,8 +1943,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
}
fnic_abort_cmd_end:
- FNIC_TRACE(fnic_abort_cmd, sc->device->host->host_no,
- sc->request->tag, sc,
+ FNIC_TRACE(fnic_abort_cmd, sc->device->host->host_no, tag, sc,
jiffies_to_msecs(jiffies - start_time),
0, ((u64)sc->cmnd[0] << 32 |
(u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
@@ -1994,7 +1993,7 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
/* fill in the lun info */
int_to_scsilun(sc->device->lun, &fc_lun);
- fnic_queue_wq_copy_desc_itmf(wq, sc->request->tag | FNIC_TAG_DEV_RST,
+ fnic_queue_wq_copy_desc_itmf(wq, scsi_cmd_to_rq(sc)->tag | FNIC_TAG_DEV_RST,
0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG,
fc_lun.scsi_lun, io_req->port_id,
fnic->config.ra_tov, fnic->config.ed_tov);
@@ -2025,7 +2024,7 @@ static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc,
struct fnic_pending_aborts_iter_data *iter_data = data;
struct fnic *fnic = iter_data->fnic;
struct scsi_device *lun_dev = iter_data->lun_dev;
- int abt_tag = sc->request->tag;
+ int abt_tag = scsi_cmd_to_rq(sc)->tag;
struct fnic_io_req *io_req;
spinlock_t *io_lock;
unsigned long flags;
@@ -2206,14 +2205,15 @@ clean_pending_aborts_end:
static inline int
fnic_scsi_host_start_tag(struct fnic *fnic, struct scsi_cmnd *sc)
{
- struct request_queue *q = sc->request->q;
+ struct request *rq = scsi_cmd_to_rq(sc);
+ struct request_queue *q = rq->q;
struct request *dummy;
dummy = blk_mq_alloc_request(q, REQ_OP_WRITE, BLK_MQ_REQ_NOWAIT);
if (IS_ERR(dummy))
return SCSI_NO_TAG;
- sc->tag = sc->request->tag = dummy->tag;
+ rq->tag = dummy->tag;
sc->host_scribble = (unsigned char *)dummy;
return dummy->tag;
@@ -2238,6 +2238,7 @@ fnic_scsi_host_end_tag(struct fnic *fnic, struct scsi_cmnd *sc)
*/
int fnic_device_reset(struct scsi_cmnd *sc)
{
+ struct request *rq = scsi_cmd_to_rq(sc);
struct fc_lport *lp;
struct fnic *fnic;
struct fnic_io_req *io_req = NULL;
@@ -2250,7 +2251,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
struct scsi_lun fc_lun;
struct fnic_stats *fnic_stats;
struct reset_stats *reset_stats;
- int tag = 0;
+ int tag = rq->tag;
DECLARE_COMPLETION_ONSTACK(tm_done);
int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/
bool new_sc = 0;
@@ -2284,7 +2285,6 @@ int fnic_device_reset(struct scsi_cmnd *sc)
CMD_FLAGS(sc) = FNIC_DEVICE_RESET;
/* Allocate tag if not present */
- tag = sc->request->tag;
if (unlikely(tag < 0)) {
/*
* Really should fix the midlayer to pass in a proper
@@ -2458,8 +2458,7 @@ fnic_device_reset_clean:
}
fnic_device_reset_end:
- FNIC_TRACE(fnic_device_reset, sc->device->host->host_no,
- sc->request->tag, sc,
+ FNIC_TRACE(fnic_device_reset, sc->device->host->host_no, rq->tag, sc,
jiffies_to_msecs(jiffies - start_time),
0, ((u64)sc->cmnd[0] << 32 |
(u64)sc->cmnd[2] << 24 | (u64)sc->cmnd[3] << 16 |
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 3a903e8e0384..9515c45affa5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -185,7 +185,7 @@ static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba,
void *bitmap = hisi_hba->slot_index_tags;
if (scsi_cmnd)
- return scsi_cmnd->request->tag;
+ return scsi_cmd_to_rq(scsi_cmnd)->tag;
spin_lock(&hisi_hba->lock);
index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count,
@@ -449,7 +449,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
unsigned int dq_index;
u32 blk_tag;
- blk_tag = blk_mq_unique_tag(scmd->request);
+ blk_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
dq_index = blk_mq_unique_tag_to_hwq(blk_tag);
*dq_pointer = dq = &hisi_hba->dq[dq_index];
} else {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index a4885d03afe2..3ab669dc806f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1153,7 +1153,7 @@ static void fill_prot_v3_hw(struct scsi_cmnd *scsi_cmnd,
{
unsigned char prot_op = scsi_get_prot_op(scsi_cmnd);
unsigned int interval = scsi_prot_interval(scsi_cmnd);
- u32 lbrt_chk_val = t10_pi_ref_tag(scsi_cmnd->request);
+ u32 lbrt_chk_val = t10_pi_ref_tag(scsi_cmd_to_rq(scsi_cmnd));
switch (prot_op) {
case SCSI_PROT_READ_INSERT:
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index f135a10f582b..3faa87fa296a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5686,7 +5686,7 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
/* Get the ptr to our adapter structure out of cmd->host. */
h = sdev_to_hba(cmd->device);
- BUG_ON(cmd->request->tag < 0);
+ BUG_ON(scsi_cmd_to_rq(cmd)->tag < 0);
dev = cmd->device->hostdata;
if (!dev) {
@@ -5729,7 +5729,7 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
* and is therefore a brand-new command.
*/
if (likely(cmd->retries == 0 &&
- !blk_rq_is_passthrough(cmd->request) &&
+ !blk_rq_is_passthrough(scsi_cmd_to_rq(cmd)) &&
h->acciopath_status)) {
/* Submit with the retry_pending flag unset. */
rc = hpsa_ioaccel_submit(h, c, cmd, false);
@@ -5894,7 +5894,7 @@ static int hpsa_scsi_add_host(struct ctlr_info *h)
*/
static int hpsa_get_cmd_index(struct scsi_cmnd *scmd)
{
- int idx = scmd->request->tag;
+ int idx = scsi_cmd_to_rq(scmd)->tag;
if (idx < 0)
return idx;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 935b01ee44b7..1f1586ad48fe 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1926,7 +1926,7 @@ static int ibmvfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
struct ibmvfc_cmd *vfc_cmd;
struct ibmvfc_fcp_cmd_iu *iu;
struct ibmvfc_event *evt;
- u32 tag_and_hwq = blk_mq_unique_tag(cmnd->request);
+ u32 tag_and_hwq = blk_mq_unique_tag(scsi_cmd_to_rq(cmnd));
u16 hwq = blk_mq_unique_tag_to_hwq(tag_and_hwq);
u16 scsi_channel;
int rc;
@@ -1956,7 +1956,7 @@ static int ibmvfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);
if (cmnd->flags & SCMD_TAGGED) {
- vfc_cmd->task_tag = cpu_to_be64(cmnd->tag);
+ vfc_cmd->task_tag = cpu_to_be64(scsi_cmd_to_rq(cmnd)->tag);
iu->pri_task_attr = IBMVFC_SIMPLE_TASK;
}
@@ -3292,14 +3292,18 @@ static int ibmvfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
int done = 0;
spin_lock_irqsave(shost->host_lock, flags);
- if (time >= (init_timeout * HZ)) {
+ if (!vhost->scan_timeout)
+ done = 1;
+ else if (time >= (vhost->scan_timeout * HZ)) {
dev_info(vhost->dev, "Scan taking longer than %d seconds, "
- "continuing initialization\n", init_timeout);
+ "continuing initialization\n", vhost->scan_timeout);
done = 1;
}
- if (vhost->scan_complete)
+ if (vhost->scan_complete) {
+ vhost->scan_timeout = init_timeout;
done = 1;
+ }
spin_unlock_irqrestore(shost->host_lock, flags);
return done;
}
@@ -6084,6 +6088,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
vhost->client_scsi_channels = min(shost->nr_hw_queues, nr_scsi_channels);
vhost->using_channels = 0;
vhost->do_enquiry = 1;
+ vhost->scan_timeout = 0;
strcpy(vhost->partition_name, "UNKNOWN");
init_waitqueue_head(&vhost->work_wait_q);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 92fb889d7eb0..3718406e0988 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -876,6 +876,7 @@ struct ibmvfc_host {
int reinit;
int delay_init;
int scan_complete;
+ int scan_timeout;
int logged_in;
int mq_enabled;
int using_channels;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index e6a3eaaa57d9..50df7dd9cb91 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1072,7 +1072,7 @@ static int ibmvscsi_queuecommand_lck(struct scsi_cmnd *cmnd,
init_event_struct(evt_struct,
handle_cmd_rsp,
VIOSRP_SRP_FORMAT,
- cmnd->request->timeout/HZ);
+ scsi_cmd_to_rq(cmnd)->timeout / HZ);
evt_struct->cmnd = cmnd;
evt_struct->cmnd_done = done;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 8b33c9871484..cdd94fb2aab7 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -3735,7 +3735,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
scb->cmd.dcdb.segment_4G = 0;
scb->cmd.dcdb.enhanced_sg = 0;
- TimeOut = scb->scsi_cmd->request->timeout;
+ TimeOut = scsi_cmd_to_rq(scb->scsi_cmd)->timeout;
if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */
if (!scb->sg_len) {
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index e1ff79464131..fcaa84a3c210 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -341,7 +341,7 @@ static void scu_ssp_ireq_dif_insert(struct isci_request *ireq, u8 type, u8 op)
tc->reserved_E8_0 = 0;
if ((type & SCSI_PROT_DIF_TYPE1) || (type & SCSI_PROT_DIF_TYPE2))
- tc->ref_tag_seed_gen = scsi_get_lba(scmd) & 0xffffffff;
+ tc->ref_tag_seed_gen = scsi_prot_ref_tag(scmd);
else if (type & SCSI_PROT_DIF_TYPE3)
tc->ref_tag_seed_gen = 0;
}
@@ -369,7 +369,7 @@ static void scu_ssp_ireq_dif_strip(struct isci_request *ireq, u8 type, u8 op)
tc->app_tag_gen = 0;
if ((type & SCSI_PROT_DIF_TYPE1) || (type & SCSI_PROT_DIF_TYPE2))
- tc->ref_tag_seed_verify = scsi_get_lba(scmd) & 0xffffffff;
+ tc->ref_tag_seed_verify = scsi_prot_ref_tag(scmd);
else if (type & SCSI_PROT_DIF_TYPE3)
tc->ref_tag_seed_verify = 0;
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 6d14a7a94d0b..86fe19e0468d 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -134,7 +134,7 @@ lasi700_probe(struct parisc_device *dev)
return -ENODEV;
}
-static int __exit
+static void __exit
lasi700_driver_remove(struct parisc_device *dev)
{
struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
@@ -146,8 +146,6 @@ lasi700_driver_remove(struct parisc_device *dev)
free_irq(host->irq, host);
iounmap(hostdata->base);
kfree(hostdata);
-
- return 0;
}
static struct parisc_driver lasi700_driver __refdata = {
diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
index 052ee3a26f6e..c640535d1ac0 100644
--- a/drivers/scsi/libsas/Kconfig
+++ b/drivers/scsi/libsas/Kconfig
@@ -10,7 +10,6 @@ config SCSI_SAS_LIBSAS
tristate "SAS Domain Transport Attributes"
depends on SCSI
select SCSI_SAS_ATTRS
- select BLK_DEV_BSGLIB
help
This provides transport specific helpers for SAS drivers which
use the domain device construct (like the aic94xxx).
diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile
index e63a54f5ab8c..9dc32736cf21 100644
--- a/drivers/scsi/libsas/Makefile
+++ b/drivers/scsi/libsas/Makefile
@@ -18,4 +18,4 @@ libsas-y += sas_init.o \
libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o
libsas-$(CONFIG_SCSI_SAS_HOST_SMP) += sas_host_smp.o
-ccflags-y := -DDEBUG
+ccflags-y := -DDEBUG -I$(srctree)/drivers/scsi
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 4aa1fda95f35..a315715b3622 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -20,8 +20,8 @@
#include <scsi/scsi.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
-#include "../scsi_sas_internal.h"
-#include "../scsi_transport_api.h"
+#include "scsi_sas_internal.h"
+#include "scsi_transport_api.h"
#include <scsi/scsi_eh.h>
static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts)
@@ -596,7 +596,7 @@ void sas_ata_task_abort(struct sas_task *task)
/* Bounce SCSI-initiated commands to the SCSI EH */
if (qc->scsicmd) {
- blk_abort_request(qc->scsicmd->request);
+ blk_abort_request(scsi_cmd_to_rq(qc->scsicmd));
return;
}
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index dd205414e505..12e1e36d7c04 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -16,7 +16,7 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
#include <scsi/sas_ata.h>
-#include "../scsi_sas_internal.h"
+#include "scsi_sas_internal.h"
/* ---------- Basic task processing for discovery purposes ---------- */
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index e00688540219..c2150a818423 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -18,7 +18,7 @@
#include <scsi/sas_ata.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
-#include "../scsi_sas_internal.h"
+#include "scsi_sas_internal.h"
static int sas_discover_expander(struct domain_device *dev);
static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr);
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index eca2a6bf3601..32cdc969b736 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -14,7 +14,7 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
-#include "../scsi_sas_internal.h"
+#include "scsi_sas_internal.h"
static void sas_host_smp_discover(struct sas_ha_struct *sas_ha, u8 *resp_data,
u8 phy_id)
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2b0f98ca6ec3..80592f53017a 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -19,7 +19,7 @@
#include "sas_internal.h"
-#include "../scsi_sas_internal.h"
+#include "scsi_sas_internal.h"
static struct kmem_cache *sas_task_cache;
static struct kmem_cache *sas_event_cache;
diff --git a/drivers/scsi/libsas/sas_phy.c b/drivers/scsi/libsas/sas_phy.c
index 4ca4b1f30bd0..a0d592d11dfb 100644
--- a/drivers/scsi/libsas/sas_phy.c
+++ b/drivers/scsi/libsas/sas_phy.c
@@ -10,7 +10,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
-#include "../scsi_sas_internal.h"
+#include "scsi_sas_internal.h"
/* ---------- Phy events ---------- */
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index e3d03d744713..67b429dcf1ff 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -10,7 +10,7 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
-#include "../scsi_sas_internal.h"
+#include "scsi_sas_internal.h"
static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy *phy)
{
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index ee44a0d7730b..08ffb8788290 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -22,9 +22,9 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
#include <scsi/sas_ata.h>
-#include "../scsi_sas_internal.h"
-#include "../scsi_transport_api.h"
-#include "../scsi_priv.h"
+#include "scsi_sas_internal.h"
+#include "scsi_transport_api.h"
+#include "scsi_priv.h"
#include <linux/err.h>
#include <linux/blkdev.h>
@@ -908,7 +908,7 @@ void sas_task_abort(struct sas_task *task)
if (dev_is_sata(task->dev))
sas_ata_task_abort(task);
else
- blk_abort_request(sc->request);
+ blk_abort_request(scsi_cmd_to_rq(sc));
}
int sas_slave_alloc(struct scsi_device *sdev)
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 17028861234b..befeb7c34290 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -114,6 +114,12 @@ struct lpfc_sli2_slim;
#define LPFC_MBX_NO_WAIT 0
#define LPFC_MBX_WAIT 1
+#define LPFC_CFG_PARAM_MAGIC_NUM 0xFEAA0005
+#define LPFC_PORT_CFG_NAME "/cfg/port.cfg"
+
+#define lpfc_rangecheck(val, min, max) \
+ ((uint)(val) >= (uint)(min) && (val) <= (max))
+
enum lpfc_polling_flags {
ENABLE_FCP_RING_POLLING = 0x1,
DISABLE_FCP_RING_INT = 0x2
@@ -403,6 +409,160 @@ struct lpfc_trunk_link {
link3;
};
+/* Format of congestion module parameters */
+struct lpfc_cgn_param {
+ uint32_t cgn_param_magic;
+ uint8_t cgn_param_version; /* version 1 */
+ uint8_t cgn_param_mode; /* 0=off 1=managed 2=monitor only */
+#define LPFC_CFG_OFF 0
+#define LPFC_CFG_MANAGED 1
+#define LPFC_CFG_MONITOR 2
+ uint8_t cgn_rsvd1;
+ uint8_t cgn_rsvd2;
+ uint8_t cgn_param_level0;
+ uint8_t cgn_param_level1;
+ uint8_t cgn_param_level2;
+ uint8_t byte11;
+ uint8_t byte12;
+ uint8_t byte13;
+ uint8_t byte14;
+ uint8_t byte15;
+};
+
+/* Max number of days of congestion data */
+#define LPFC_MAX_CGN_DAYS 10
+
+/* Format of congestion buffer info
+ * This structure defines memory thats allocated and registered with
+ * the HBA firmware. When adding or removing fields from this structure
+ * the alignment must match the HBA firmware.
+ */
+
+struct lpfc_cgn_info {
+ /* Header */
+ __le16 cgn_info_size; /* is sizeof(struct lpfc_cgn_info) */
+ uint8_t cgn_info_version; /* represents format of structure */
+#define LPFC_CGN_INFO_V1 1
+#define LPFC_CGN_INFO_V2 2
+#define LPFC_CGN_INFO_V3 3
+ uint8_t cgn_info_mode; /* 0=off 1=managed 2=monitor only */
+ uint8_t cgn_info_detect;
+ uint8_t cgn_info_action;
+ uint8_t cgn_info_level0;
+ uint8_t cgn_info_level1;
+ uint8_t cgn_info_level2;
+
+ /* Start Time */
+ uint8_t cgn_info_month;
+ uint8_t cgn_info_day;
+ uint8_t cgn_info_year;
+ uint8_t cgn_info_hour;
+ uint8_t cgn_info_minute;
+ uint8_t cgn_info_second;
+
+ /* minute / hours / daily indices */
+ uint8_t cgn_index_minute;
+ uint8_t cgn_index_hour;
+ uint8_t cgn_index_day;
+
+ __le16 cgn_warn_freq;
+ __le16 cgn_alarm_freq;
+ __le16 cgn_lunq;
+ uint8_t cgn_pad1[8];
+
+ /* Driver Information */
+ __le16 cgn_drvr_min[60];
+ __le32 cgn_drvr_hr[24];
+ __le32 cgn_drvr_day[LPFC_MAX_CGN_DAYS];
+
+ /* Congestion Warnings */
+ __le16 cgn_warn_min[60];
+ __le32 cgn_warn_hr[24];
+ __le32 cgn_warn_day[LPFC_MAX_CGN_DAYS];
+
+ /* Latency Information */
+ __le32 cgn_latency_min[60];
+ __le32 cgn_latency_hr[24];
+ __le32 cgn_latency_day[LPFC_MAX_CGN_DAYS];
+
+ /* Bandwidth Information */
+ __le16 cgn_bw_min[60];
+ __le16 cgn_bw_hr[24];
+ __le16 cgn_bw_day[LPFC_MAX_CGN_DAYS];
+
+ /* Congestion Alarms */
+ __le16 cgn_alarm_min[60];
+ __le32 cgn_alarm_hr[24];
+ __le32 cgn_alarm_day[LPFC_MAX_CGN_DAYS];
+
+ /* Start of congestion statistics */
+ uint8_t cgn_stat_npm; /* Notifications per minute */
+
+ /* Start Time */
+ uint8_t cgn_stat_month;
+ uint8_t cgn_stat_day;
+ uint8_t cgn_stat_year;
+ uint8_t cgn_stat_hour;
+ uint8_t cgn_stat_minute;
+ uint8_t cgn_pad2[2];
+
+ __le32 cgn_notification;
+ __le32 cgn_peer_notification;
+ __le32 link_integ_notification;
+ __le32 delivery_notification;
+
+ uint8_t cgn_stat_cgn_month; /* Last congestion notification FPIN */
+ uint8_t cgn_stat_cgn_day;
+ uint8_t cgn_stat_cgn_year;
+ uint8_t cgn_stat_cgn_hour;
+ uint8_t cgn_stat_cgn_min;
+ uint8_t cgn_stat_cgn_sec;
+
+ uint8_t cgn_stat_peer_month; /* Last peer congestion FPIN */
+ uint8_t cgn_stat_peer_day;
+ uint8_t cgn_stat_peer_year;
+ uint8_t cgn_stat_peer_hour;
+ uint8_t cgn_stat_peer_min;
+ uint8_t cgn_stat_peer_sec;
+
+ uint8_t cgn_stat_lnk_month; /* Last link integrity FPIN */
+ uint8_t cgn_stat_lnk_day;
+ uint8_t cgn_stat_lnk_year;
+ uint8_t cgn_stat_lnk_hour;
+ uint8_t cgn_stat_lnk_min;
+ uint8_t cgn_stat_lnk_sec;
+
+ uint8_t cgn_stat_del_month; /* Last delivery notification FPIN */
+ uint8_t cgn_stat_del_day;
+ uint8_t cgn_stat_del_year;
+ uint8_t cgn_stat_del_hour;
+ uint8_t cgn_stat_del_min;
+ uint8_t cgn_stat_del_sec;
+#define LPFC_CGN_STAT_SIZE 48
+#define LPFC_CGN_DATA_SIZE (sizeof(struct lpfc_cgn_info) - \
+ LPFC_CGN_STAT_SIZE - sizeof(uint32_t))
+
+ __le32 cgn_info_crc;
+#define LPFC_CGN_CRC32_MAGIC_NUMBER 0x1EDC6F41
+#define LPFC_CGN_CRC32_SEED 0xFFFFFFFF
+};
+
+#define LPFC_CGN_INFO_SZ (sizeof(struct lpfc_cgn_info) - \
+ sizeof(uint32_t))
+
+struct lpfc_cgn_stat {
+ atomic64_t total_bytes;
+ atomic64_t rcv_bytes;
+ atomic64_t rx_latency;
+#define LPFC_CGN_NOT_SENT 0xFFFFFFFFFFFFFFFFLL
+ atomic_t rx_io_cnt;
+};
+
+struct lpfc_cgn_acqe_stat {
+ atomic64_t alarm;
+ atomic64_t warn;
+};
+
struct lpfc_vport {
struct lpfc_hba *phba;
struct list_head listentry;
@@ -869,7 +1029,10 @@ struct lpfc_hba {
* capability
*/
#define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */
+#define HBA_CGN_RSVD1 0x200000 /* Reserved CGN flag */
+#define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */
#define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */
+#define HBA_SETUP 0x1000000 /* Signifies HBA setup is completed */
#define HBA_NEEDS_CFG_PORT 0x2000000 /* SLI3 - needs a CONFIG_PORT mbox */
#define HBA_HBEAT_INP 0x4000000 /* mbox HBEAT is in progress */
#define HBA_HBEAT_TMO 0x8000000 /* HBEAT initiated after timeout */
@@ -922,7 +1085,6 @@ struct lpfc_hba {
uint8_t wwpn[8];
uint32_t RandomData[7];
uint8_t fcp_embed_io;
- uint8_t nvme_support; /* Firmware supports NVME */
uint8_t nvmet_support; /* driver supports NVMET */
#define LPFC_NVMET_MAX_PORTS 32
uint8_t mds_diags_support;
@@ -1121,6 +1283,7 @@ struct lpfc_hba {
uint32_t total_iocbq_bufs;
struct list_head active_rrq_list;
spinlock_t hbalock;
+ struct work_struct unblock_request_work; /* SCSI layer unblock IOs */
/* dma_mem_pools */
struct dma_pool *lpfc_sg_dma_buf_pool;
@@ -1194,6 +1357,8 @@ struct lpfc_hba {
#ifdef LPFC_HDWQ_LOCK_STAT
struct dentry *debug_lockstat;
#endif
+ struct dentry *debug_cgn_buffer;
+ struct dentry *debug_rx_monitor;
struct dentry *debug_ras_log;
atomic_t nvmeio_trc_cnt;
uint32_t nvmeio_trc_size;
@@ -1344,6 +1509,76 @@ struct lpfc_hba {
uint64_t ktime_seg10_min;
uint64_t ktime_seg10_max;
#endif
+ /* CMF objects */
+ struct lpfc_cgn_stat __percpu *cmf_stat;
+ uint32_t cmf_interval_rate; /* timer interval limit in ms */
+ uint32_t cmf_timer_cnt;
+#define LPFC_CMF_INTERVAL 90
+ uint64_t cmf_link_byte_count;
+ uint64_t cmf_max_line_rate;
+ uint64_t cmf_max_bytes_per_interval;
+ uint64_t cmf_last_sync_bw;
+#define LPFC_CMF_BLK_SIZE 512
+ struct hrtimer cmf_timer;
+ atomic_t cmf_bw_wait;
+ atomic_t cmf_busy;
+ atomic_t cmf_stop_io; /* To block request and stop IO's */
+ uint32_t cmf_active_mode;
+ uint32_t cmf_info_per_interval;
+#define LPFC_MAX_CMF_INFO 32
+ struct timespec64 cmf_latency; /* Interval congestion timestamp */
+ uint32_t cmf_last_ts; /* Interval congestion time (ms) */
+ uint32_t cmf_active_info;
+
+ /* Signal / FPIN handling for Congestion Mgmt */
+ u8 cgn_reg_fpin; /* Negotiated value from RDF */
+ u8 cgn_init_reg_fpin; /* Initial value from READ_CONFIG */
+#define LPFC_CGN_FPIN_NONE 0x0
+#define LPFC_CGN_FPIN_WARN 0x1
+#define LPFC_CGN_FPIN_ALARM 0x2
+#define LPFC_CGN_FPIN_BOTH (LPFC_CGN_FPIN_WARN | LPFC_CGN_FPIN_ALARM)
+
+ u8 cgn_reg_signal; /* Negotiated value from EDC */
+ u8 cgn_init_reg_signal; /* Initial value from READ_CONFIG */
+ /* cgn_reg_signal and cgn_init_reg_signal use
+ * enum fc_edc_cg_signal_cap_types
+ */
+ u16 cgn_fpin_frequency;
+#define LPFC_FPIN_INIT_FREQ 0xffff
+ u32 cgn_sig_freq;
+ u32 cgn_acqe_cnt;
+
+ /* RX monitor handling for CMF */
+ struct rxtable_entry *rxtable; /* RX_monitor information */
+ atomic_t rxtable_idx_head;
+#define LPFC_RXMONITOR_TABLE_IN_USE (LPFC_MAX_RXMONITOR_ENTRY + 73)
+ atomic_t rxtable_idx_tail;
+ atomic_t rx_max_read_cnt; /* Maximum read bytes */
+ uint64_t rx_block_cnt;
+
+ /* Congestion parameters from flash */
+ struct lpfc_cgn_param cgn_p;
+
+ /* Statistics counter for ACQE cgn alarms and warnings */
+ struct lpfc_cgn_acqe_stat cgn_acqe_stat;
+
+ /* Congestion buffer information */
+ struct lpfc_dmabuf *cgn_i; /* Congestion Info buffer */
+ atomic_t cgn_fabric_warn_cnt; /* Total warning cgn events for info */
+ atomic_t cgn_fabric_alarm_cnt; /* Total alarm cgn events for info */
+ atomic_t cgn_sync_warn_cnt; /* Total warning events for SYNC wqe */
+ atomic_t cgn_sync_alarm_cnt; /* Total alarm events for SYNC wqe */
+ atomic_t cgn_driver_evt_cnt; /* Total driver cgn events for fmw */
+ atomic_t cgn_latency_evt_cnt;
+ struct timespec64 cgn_daily_ts;
+ atomic64_t cgn_latency_evt; /* Avg latency per minute */
+ unsigned long cgn_evt_timestamp;
+#define LPFC_CGN_TIMER_TO_MIN 60000 /* ms in a minute */
+ uint32_t cgn_evt_minute;
+#define LPFC_SEC_MIN 60
+#define LPFC_MIN_HOUR 60
+#define LPFC_HOUR_DAY 24
+#define LPFC_MIN_DAY (LPFC_MIN_HOUR * LPFC_HOUR_DAY)
struct hlist_node cpuhp; /* used for cpuhp per hba callback */
struct timer_list cpuhp_poll_timer;
@@ -1364,6 +1599,22 @@ struct lpfc_hba {
struct dbg_log_ent dbg_log[DBG_LOG_SZ];
};
+#define LPFC_MAX_RXMONITOR_ENTRY 800
+#define LPFC_MAX_RXMONITOR_DUMP 32
+struct rxtable_entry {
+ uint64_t total_bytes; /* Total no of read bytes requested */
+ uint64_t rcv_bytes; /* Total no of read bytes completed */
+ uint64_t avg_io_size;
+ uint64_t avg_io_latency;/* Average io latency in microseconds */
+ uint64_t max_read_cnt; /* Maximum read bytes */
+ uint64_t max_bytes_per_interval;
+ uint32_t cmf_busy;
+ uint32_t cmf_info; /* CMF_SYNC_WQE info */
+ uint32_t io_cnt;
+ uint32_t timer_utilization;
+ uint32_t timer_interval;
+};
+
static inline struct Scsi_Host *
lpfc_shost_from_vport(struct lpfc_vport *vport)
{
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index eb88aaaf36eb..b35bf70a8c0d 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -57,6 +57,8 @@
#define LPFC_MIN_DEVLOSS_TMO 1
#define LPFC_MAX_DEVLOSS_TMO 255
+#define LPFC_MAX_INFO_TMP_LEN 100
+#define LPFC_INFO_MORE_STR "\nCould be more info...\n"
/*
* Write key size should be multiple of 4. If write key is changed
* make sure that library write key is also changed.
@@ -112,6 +114,186 @@ lpfc_jedec_to_ascii(int incr, char hdw[])
return;
}
+static ssize_t
+lpfc_cmf_info_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_cgn_info *cp = NULL;
+ struct lpfc_cgn_stat *cgs;
+ int len = 0;
+ int cpu;
+ u64 rcv, total;
+ char tmp[LPFC_MAX_INFO_TMP_LEN] = {0};
+
+ if (phba->cgn_i)
+ cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
+
+ scnprintf(tmp, sizeof(tmp),
+ "Congestion Mgmt Info: E2Eattr %d Ver %d "
+ "CMF %d cnt %d\n",
+ phba->sli4_hba.pc_sli4_params.mi_ver,
+ cp ? cp->cgn_info_version : 0,
+ phba->sli4_hba.pc_sli4_params.cmf, phba->cmf_timer_cnt);
+
+ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+ goto buffer_done;
+
+ if (!phba->sli4_hba.pc_sli4_params.cmf)
+ goto buffer_done;
+
+ switch (phba->cgn_init_reg_signal) {
+ case EDC_CG_SIG_WARN_ONLY:
+ scnprintf(tmp, sizeof(tmp),
+ "Register: Init: Signal:WARN ");
+ break;
+ case EDC_CG_SIG_WARN_ALARM:
+ scnprintf(tmp, sizeof(tmp),
+ "Register: Init: Signal:WARN|ALARM ");
+ break;
+ default:
+ scnprintf(tmp, sizeof(tmp),
+ "Register: Init: Signal:NONE ");
+ break;
+ }
+ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+ goto buffer_done;
+
+ switch (phba->cgn_init_reg_fpin) {
+ case LPFC_CGN_FPIN_WARN:
+ scnprintf(tmp, sizeof(tmp),
+ "FPIN:WARN\n");
+ break;
+ case LPFC_CGN_FPIN_ALARM:
+ scnprintf(tmp, sizeof(tmp),
+ "FPIN:ALARM\n");
+ break;
+ case LPFC_CGN_FPIN_BOTH:
+ scnprintf(tmp, sizeof(tmp),
+ "FPIN:WARN|ALARM\n");
+ break;
+ default:
+ scnprintf(tmp, sizeof(tmp),
+ "FPIN:NONE\n");
+ break;
+ }
+ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+ goto buffer_done;
+
+ switch (phba->cgn_reg_signal) {
+ case EDC_CG_SIG_WARN_ONLY:
+ scnprintf(tmp, sizeof(tmp),
+ " Current: Signal:WARN ");
+ break;
+ case EDC_CG_SIG_WARN_ALARM:
+ scnprintf(tmp, sizeof(tmp),
+ " Current: Signal:WARN|ALARM ");
+ break;
+ default:
+ scnprintf(tmp, sizeof(tmp),
+ " Current: Signal:NONE ");
+ break;
+ }
+ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+ goto buffer_done;
+
+ switch (phba->cgn_reg_fpin) {
+ case LPFC_CGN_FPIN_WARN:
+ scnprintf(tmp, sizeof(tmp),
+ "FPIN:WARN ACQEcnt:%d\n", phba->cgn_acqe_cnt);
+ break;
+ case LPFC_CGN_FPIN_ALARM:
+ scnprintf(tmp, sizeof(tmp),
+ "FPIN:ALARM ACQEcnt:%d\n", phba->cgn_acqe_cnt);
+ break;
+ case LPFC_CGN_FPIN_BOTH:
+ scnprintf(tmp, sizeof(tmp),
+ "FPIN:WARN|ALARM ACQEcnt:%d\n", phba->cgn_acqe_cnt);
+ break;
+ default:
+ scnprintf(tmp, sizeof(tmp),
+ "FPIN:NONE ACQEcnt:%d\n", phba->cgn_acqe_cnt);
+ break;
+ }
+ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+ goto buffer_done;
+
+ if (phba->cmf_active_mode != phba->cgn_p.cgn_param_mode) {
+ switch (phba->cmf_active_mode) {
+ case LPFC_CFG_OFF:
+ scnprintf(tmp, sizeof(tmp), "Active: Mode:Off\n");
+ break;
+ case LPFC_CFG_MANAGED:
+ scnprintf(tmp, sizeof(tmp), "Active: Mode:Managed\n");
+ break;
+ case LPFC_CFG_MONITOR:
+ scnprintf(tmp, sizeof(tmp), "Active: Mode:Monitor\n");
+ break;
+ default:
+ scnprintf(tmp, sizeof(tmp), "Active: Mode:Unknown\n");
+ }
+ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+ goto buffer_done;
+ }
+
+ switch (phba->cgn_p.cgn_param_mode) {
+ case LPFC_CFG_OFF:
+ scnprintf(tmp, sizeof(tmp), "Config: Mode:Off ");
+ break;
+ case LPFC_CFG_MANAGED:
+ scnprintf(tmp, sizeof(tmp), "Config: Mode:Managed ");
+ break;
+ case LPFC_CFG_MONITOR:
+ scnprintf(tmp, sizeof(tmp), "Config: Mode:Monitor ");
+ break;
+ default:
+ scnprintf(tmp, sizeof(tmp), "Config: Mode:Unknown ");
+ }
+ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+ goto buffer_done;
+
+ total = 0;
+ rcv = 0;
+ for_each_present_cpu(cpu) {
+ cgs = per_cpu_ptr(phba->cmf_stat, cpu);
+ total += atomic64_read(&cgs->total_bytes);
+ rcv += atomic64_read(&cgs->rcv_bytes);
+ }
+
+ scnprintf(tmp, sizeof(tmp),
+ "IObusy:%d Info:%d Bytes: Rcv:x%llx Total:x%llx\n",
+ atomic_read(&phba->cmf_busy),
+ phba->cmf_active_info, rcv, total);
+ if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+ goto buffer_done;
+
+ scnprintf(tmp, sizeof(tmp),
+ "Port_speed:%d Link_byte_cnt:%ld "
+ "Max_byte_per_interval:%ld\n",
+ lpfc_sli_port_speed_get(phba),
+ (unsigned long)phba->cmf_link_byte_count,
+ (unsigned long)phba->cmf_max_bytes_per_interval);
+ strlcat(buf, tmp, PAGE_SIZE);
+
+buffer_done:
+ len = strnlen(buf, PAGE_SIZE);
+
+ if (unlikely(len >= (PAGE_SIZE - 1))) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6312 Catching potential buffer "
+ "overflow > PAGE_SIZE = %lu bytes\n",
+ PAGE_SIZE);
+ strscpy(buf + PAGE_SIZE - 1 -
+ strnlen(LPFC_INFO_MORE_STR, PAGE_SIZE - 1),
+ LPFC_INFO_MORE_STR,
+ strnlen(LPFC_INFO_MORE_STR, PAGE_SIZE - 1)
+ + 1);
+ }
+ return len;
+}
+
/**
* lpfc_drvr_version_show - Return the Emulex driver string with version number
* @dev: class unused variable.
@@ -168,7 +350,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
char *statep;
int i;
int len = 0;
- char tmp[LPFC_MAX_NVME_INFO_TMP_LEN] = {0};
+ char tmp[LPFC_MAX_INFO_TMP_LEN] = {0};
if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n");
@@ -512,9 +694,9 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
"6314 Catching potential buffer "
"overflow > PAGE_SIZE = %lu bytes\n",
PAGE_SIZE);
- strlcpy(buf + PAGE_SIZE - 1 - sizeof(LPFC_NVME_INFO_MORE_STR),
- LPFC_NVME_INFO_MORE_STR,
- sizeof(LPFC_NVME_INFO_MORE_STR) + 1);
+ strscpy(buf + PAGE_SIZE - 1 - sizeof(LPFC_INFO_MORE_STR),
+ LPFC_INFO_MORE_STR,
+ sizeof(LPFC_INFO_MORE_STR) + 1);
}
return len;
@@ -2248,11 +2430,6 @@ lpfc_sriov_hw_max_virtfn_show(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
}
-static inline bool lpfc_rangecheck(uint val, uint min, uint max)
-{
- return val >= min && val <= max;
-}
-
/**
* lpfc_enable_bbcr_set: Sets an attribute value.
* @phba: pointer the the adapter structure.
@@ -2641,6 +2818,7 @@ static DEVICE_ATTR_RO(lpfc_sriov_hw_max_virtfn);
static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show,
NULL);
+static DEVICE_ATTR(cmf_info, 0444, lpfc_cmf_info_show, NULL);
static char *lpfc_soft_wwn_key = "C99G71SL8032A";
#define WWN_SZ 8
@@ -4038,6 +4216,7 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
const char *val_buf = buf;
int err;
uint32_t prev_val;
+ u8 sli_family, if_type;
if (!strncmp(buf, "nolip ", strlen("nolip "))) {
nolip = 1;
@@ -4061,13 +4240,16 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
/*
* The 'topology' is not a configurable parameter if :
* - persistent topology enabled
- * - G7/G6 with no private loop support
+ * - ASIC_GEN_NUM >= 0xC, with no private loop support
*/
-
+ sli_family = bf_get(lpfc_sli_intf_sli_family,
+ &phba->sli4_hba.sli_intf);
+ if_type = bf_get(lpfc_sli_intf_if_type,
+ &phba->sli4_hba.sli_intf);
if ((phba->hba_flag & HBA_PERSISTENT_TOPO ||
- (!phba->sli4_hba.pc_sli4_params.pls &&
- (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
- phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC))) &&
+ (!phba->sli4_hba.pc_sli4_params.pls &&
+ (sli_family == LPFC_SLI_INTF_FAMILY_G6 ||
+ if_type == LPFC_SLI_INTF_IF_TYPE_6))) &&
val == 4) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"3114 Loop mode not supported\n");
@@ -5412,9 +5594,9 @@ LPFC_VPORT_ATTR_R(fcp_class, 3, 2, 3,
/*
# lpfc_use_adisc: Use ADISC for FCP rediscovery instead of PLOGI. Value range
-# is [0,1]. Default value is 0.
+# is [0,1]. Default value is 1.
*/
-LPFC_VPORT_ATTR_RW(use_adisc, 0, 0, 1,
+LPFC_VPORT_ATTR_RW(use_adisc, 1, 0, 1,
"Use ADISC on rediscovery to authenticate FCP devices");
/*
@@ -6146,6 +6328,19 @@ LPFC_ATTR_RW(ras_fwlog_func, 0, 0, 7, "Firmware Logging Enabled on Function");
*/
LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
+/* Signaling module parameters */
+int lpfc_fabric_cgn_frequency = 100; /* 100 ms default */
+module_param(lpfc_fabric_cgn_frequency, int, 0444);
+MODULE_PARM_DESC(lpfc_fabric_cgn_frequency, "Congestion signaling fabric freq");
+
+int lpfc_acqe_cgn_frequency = 10; /* 10 sec default */
+module_param(lpfc_acqe_cgn_frequency, int, 0444);
+MODULE_PARM_DESC(lpfc_acqe_cgn_frequency, "Congestion signaling ACQE freq");
+
+int lpfc_use_cgn_signal = 1; /* 0 - only use FPINs, 1 - Use signals if avail */
+module_param(lpfc_use_cgn_signal, int, 0444);
+MODULE_PARM_DESC(lpfc_use_cgn_signal, "Use Congestion signaling if available");
+
/*
* lpfc_enable_dpp: Enable DPP on G7
* 0 = DPP on G7 disabled
@@ -6320,6 +6515,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_enable_bbcr,
&dev_attr_lpfc_enable_dpp,
&dev_attr_lpfc_enable_mi,
+ &dev_attr_cmf_info,
&dev_attr_lpfc_max_vmid,
&dev_attr_lpfc_vmid_inactivity_timeout,
&dev_attr_lpfc_vmid_app_header,
@@ -6350,6 +6546,7 @@ struct device_attribute *lpfc_vport_attrs[] = {
&dev_attr_lpfc_max_scsicmpl_time,
&dev_attr_lpfc_stat_data_ctrl,
&dev_attr_lpfc_static_vport,
+ &dev_attr_cmf_info,
NULL,
};
@@ -6741,6 +6938,9 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
case LPFC_LINK_SPEED_128GHZ:
fc_host_speed(shost) = FC_PORTSPEED_128GBIT;
break;
+ case LPFC_LINK_SPEED_256GHZ:
+ fc_host_speed(shost) = FC_PORTSPEED_256GBIT;
+ break;
default:
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
@@ -6908,6 +7108,9 @@ lpfc_get_stats(struct Scsi_Host *shost)
hs->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
hs->error_frames = pmb->un.varRdLnk.crcCnt;
+ hs->cn_sig_warn = atomic64_read(&phba->cgn_acqe_stat.warn);
+ hs->cn_sig_alarm = atomic64_read(&phba->cgn_acqe_stat.alarm);
+
hs->link_failure_count -= lso->link_failure_count;
hs->loss_of_sync_count -= lso->loss_of_sync_count;
hs->loss_of_signal_count -= lso->loss_of_signal_count;
@@ -7019,6 +7222,12 @@ lpfc_reset_stats(struct Scsi_Host *shost)
else
lso->link_events = (phba->fc_eventTag >> 1);
+ atomic64_set(&phba->cgn_acqe_stat.warn, 0);
+ atomic64_set(&phba->cgn_acqe_stat.alarm, 0);
+
+ memset(&shost_to_fc_host(shost)->fpin_stats, 0,
+ sizeof(shost_to_fc_host(shost)->fpin_stats));
+
psli->stats_start = ktime_get_seconds();
mempool_free(pmboxq, phba->mbox_mem_pool);
@@ -7452,6 +7661,12 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
lpfc_enable_mi_init(phba, lpfc_enable_mi);
+ phba->cgn_p.cgn_param_mode = LPFC_CFG_OFF;
+ phba->cmf_active_mode = LPFC_CFG_OFF;
+ if (lpfc_fabric_cgn_frequency > EDC_CG_SIGFREQ_CNT_MAX ||
+ lpfc_fabric_cgn_frequency < EDC_CG_SIGFREQ_CNT_MIN)
+ lpfc_fabric_cgn_frequency = 100; /* 100 ms default */
+
if (phba->sli_rev != LPFC_SLI_REV4) {
/* NVME only supported on SLI4 */
phba->nvmet_support = 0;
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 38cfe1bc6a4d..fdf08cb57207 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -5751,6 +5751,92 @@ job_error:
}
+static int
+lpfc_get_cgnbuf_info(struct bsg_job *job)
+{
+ struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
+ struct lpfc_hba *phba = vport->phba;
+ struct fc_bsg_request *bsg_request = job->request;
+ struct fc_bsg_reply *bsg_reply = job->reply;
+ struct get_cgnbuf_info_req *cgnbuf_req;
+ struct lpfc_cgn_info *cp;
+ uint8_t *cgn_buff;
+ int size, cinfosz;
+ int rc = 0;
+
+ if (job->request_len < sizeof(struct fc_bsg_request) +
+ sizeof(struct get_cgnbuf_info_req)) {
+ rc = -ENOMEM;
+ goto job_exit;
+ }
+
+ if (!phba->sli4_hba.pc_sli4_params.cmf) {
+ rc = -ENOENT;
+ goto job_exit;
+ }
+
+ if (!phba->cgn_i || !phba->cgn_i->virt) {
+ rc = -ENOENT;
+ goto job_exit;
+ }
+
+ cp = phba->cgn_i->virt;
+ if (cp->cgn_info_version < LPFC_CGN_INFO_V3) {
+ rc = -EPERM;
+ goto job_exit;
+ }
+
+ cgnbuf_req = (struct get_cgnbuf_info_req *)
+ bsg_request->rqst_data.h_vendor.vendor_cmd;
+
+ /* For reset or size == 0 */
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ if (cgnbuf_req->reset == LPFC_BSG_CGN_RESET_STAT) {
+ lpfc_init_congestion_stat(phba);
+ goto job_exit;
+ }
+
+ /* We don't want to include the CRC at the end */
+ cinfosz = sizeof(struct lpfc_cgn_info) - sizeof(uint32_t);
+
+ size = cgnbuf_req->read_size;
+ if (!size)
+ goto job_exit;
+
+ if (size < cinfosz) {
+ /* Just copy back what we can */
+ cinfosz = size;
+ rc = -E2BIG;
+ }
+
+ /* Allocate memory to read congestion info */
+ cgn_buff = vmalloc(cinfosz);
+ if (!cgn_buff) {
+ rc = -ENOMEM;
+ goto job_exit;
+ }
+
+ memcpy(cgn_buff, cp, cinfosz);
+
+ bsg_reply->reply_payload_rcv_len =
+ sg_copy_from_buffer(job->reply_payload.sg_list,
+ job->reply_payload.sg_cnt,
+ cgn_buff, cinfosz);
+
+ vfree(cgn_buff);
+
+job_exit:
+ bsg_reply->result = rc;
+ if (!rc)
+ bsg_job_done(job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ else
+ lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
+ "2724 GET CGNBUF error: %d\n", rc);
+ return rc;
+}
+
/**
* lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
* @job: fc_bsg_job to handle
@@ -5813,6 +5899,9 @@ lpfc_bsg_hst_vendor(struct bsg_job *job)
case LPFC_BSG_VENDOR_GET_TRUNK_INFO:
rc = lpfc_get_trunk_info(job);
break;
+ case LPFC_BSG_VENDOR_GET_CGNBUF_INFO:
+ rc = lpfc_get_cgnbuf_info(job);
+ break;
default:
rc = -EINVAL;
bsg_reply->reply_payload_rcv_len = 0;
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h
index 2dc71243775d..749d6c43cfce 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.h
+++ b/drivers/scsi/lpfc/lpfc_bsg.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2010-2015 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -43,6 +43,7 @@
#define LPFC_BSG_VENDOR_RAS_GET_CONFIG 18
#define LPFC_BSG_VENDOR_RAS_SET_CONFIG 19
#define LPFC_BSG_VENDOR_GET_TRUNK_INFO 20
+#define LPFC_BSG_VENDOR_GET_CGNBUF_INFO 21
struct set_ct_event {
uint32_t command;
@@ -386,6 +387,13 @@ struct get_trunk_info_req {
uint32_t command;
};
+struct get_cgnbuf_info_req {
+ uint32_t command;
+ uint32_t read_size;
+ uint32_t reset;
+#define LPFC_BSG_CGN_RESET_STAT 1
+};
+
/* driver only */
#define SLI_CONFIG_NOT_HANDLED 0
#define SLI_CONFIG_HANDLED 1
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 737483c3f01d..c512f4199142 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -58,6 +58,8 @@ void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *);
int lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *, struct lpfcMboxq *,
uint16_t, uint16_t, bool);
int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *);
+int lpfc_reg_congestion_buf(struct lpfc_hba *phba);
+int lpfc_unreg_congestion_buf(struct lpfc_hba *phba);
struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
void lpfc_cleanup_rcv_buffers(struct lpfc_vport *);
void lpfc_rcv_seq_check_edtov(struct lpfc_vport *);
@@ -74,6 +76,20 @@ int lpfc_init_iocb_list(struct lpfc_hba *phba, int cnt);
void lpfc_free_iocb_list(struct lpfc_hba *phba);
int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
struct lpfc_queue *drq, int count, int idx);
+uint32_t lpfc_calc_cmf_latency(struct lpfc_hba *phba);
+void lpfc_cmf_signal_init(struct lpfc_hba *phba);
+void lpfc_cmf_start(struct lpfc_hba *phba);
+void lpfc_cmf_stop(struct lpfc_hba *phba);
+void lpfc_init_congestion_stat(struct lpfc_hba *phba);
+void lpfc_init_congestion_buf(struct lpfc_hba *phba);
+int lpfc_sli4_cgn_params_read(struct lpfc_hba *phba);
+uint32_t lpfc_cgn_calc_crc32(void *bufp, uint32_t sz, uint32_t seed);
+int lpfc_config_cgn_signal(struct lpfc_hba *phba);
+int lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total);
+void lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba);
+void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag);
+void lpfc_unblock_requests(struct lpfc_hba *phba);
+void lpfc_block_requests(struct lpfc_hba *phba);
void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -87,6 +103,8 @@ void lpfc_unregister_vfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_enqueue_node(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_nlp_set_state(struct lpfc_vport *, struct lpfc_nodelist *, int);
+void lpfc_nlp_reg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp);
+void lpfc_nlp_unreg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp);
void lpfc_drop_node(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_set_disctmo(struct lpfc_vport *);
int lpfc_can_disctmo(struct lpfc_vport *);
@@ -141,6 +159,8 @@ int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_fabric_reglogin(struct lpfc_vport *);
int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry);
+int lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry);
+void lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length);
int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
@@ -213,6 +233,9 @@ irqreturn_t lpfc_sli_fp_intr_handler(int, void *);
irqreturn_t lpfc_sli4_intr_handler(int, void *);
irqreturn_t lpfc_sli4_hba_intr_handler(int, void *);
+int lpfc_read_object(struct lpfc_hba *phba, char *s, uint32_t *datap,
+ uint32_t len);
+
void lpfc_sli4_cleanup_poll_list(struct lpfc_hba *phba);
int lpfc_sli4_poll_eq(struct lpfc_queue *q, uint8_t path);
void lpfc_sli4_poll_hbtimer(struct timer_list *t);
@@ -459,6 +482,9 @@ void lpfc_free_fast_evt(struct lpfc_hba *, struct lpfc_fast_path_event *);
void lpfc_create_static_vport(struct lpfc_hba *);
void lpfc_stop_hba_timers(struct lpfc_hba *);
void lpfc_stop_port(struct lpfc_hba *);
+int lpfc_update_cmf_cmd(struct lpfc_hba *phba, uint32_t sz);
+int lpfc_update_cmf_cmpl(struct lpfc_hba *phba, uint64_t val, uint32_t sz,
+ struct Scsi_Host *shost);
void __lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *);
void lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *);
void lpfc_parse_fcoe_conf(struct lpfc_hba *, uint8_t *, uint32_t);
@@ -605,6 +631,10 @@ extern int lpfc_enable_nvmet_cnt;
extern unsigned long long lpfc_enable_nvmet[];
extern int lpfc_no_hba_reset_cnt;
extern unsigned long lpfc_no_hba_reset[];
+extern int lpfc_acqe_cgn_frequency;
+extern int lpfc_fabric_cgn_frequency;
+extern int lpfc_use_cgn_signal;
+
extern union lpfc_wqe128 lpfc_iread_cmd_template;
extern union lpfc_wqe128 lpfc_iwrite_cmd_template;
extern union lpfc_wqe128 lpfc_icmnd_cmd_template;
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 610b6dabb3b5..dfcb7d4bd7fa 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -2288,6 +2288,8 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* No retry on Vendor, RPA only done on physical port */
if (phba->link_flag & LS_CT_VEN_RPA) {
phba->link_flag &= ~LS_CT_VEN_RPA;
+ if (phba->cmf_active_mode == LPFC_CFG_OFF)
+ return;
lpfc_printf_log(phba, KERN_ERR,
LOG_DISCOVERY | LOG_ELS,
"6460 VEN FDMI RPA failure\n");
@@ -2332,24 +2334,29 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
break;
case SLI_MGMT_RPA:
if (vport->port_type == LPFC_PHYSICAL_PORT &&
- phba->cfg_enable_mi &&
- phba->sli4_hba.pc_sli4_params.mi_ver > LPFC_MIB1_SUPPORT) {
+ phba->sli4_hba.pc_sli4_params.mi_ver) {
/* mi is only for the phyical port, no vports */
if (phba->link_flag & LS_CT_VEN_RPA) {
lpfc_printf_vlog(vport, KERN_INFO,
- LOG_DISCOVERY | LOG_ELS,
+ LOG_DISCOVERY | LOG_ELS |
+ LOG_CGN_MGMT,
"6449 VEN RPA FDMI Success\n");
phba->link_flag &= ~LS_CT_VEN_RPA;
break;
}
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6210 Issue Vendor MI FDMI %x\n",
+ phba->sli4_hba.pc_sli4_params.mi_ver);
+
+ /* CGN is only for the physical port, no vports */
if (lpfc_fdmi_cmd(vport, ndlp, cmd,
LPFC_FDMI_VENDOR_ATTR_mi) == 0)
phba->link_flag |= LS_CT_VEN_RPA;
lpfc_printf_log(phba, KERN_INFO,
LOG_DISCOVERY | LOG_ELS,
"6458 Send MI FDMI:%x Flag x%x\n",
- phba->sli4_hba.pc_sli4_params.mi_value,
+ phba->sli4_hba.pc_sli4_params.mi_ver,
phba->link_flag);
} else {
lpfc_printf_log(phba, KERN_INFO,
@@ -2846,6 +2853,8 @@ lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport,
ae->un.AttrInt = 0;
if (!(phba->hba_flag & HBA_FCOE_MODE)) {
+ if (phba->lmt & LMT_256Gb)
+ ae->un.AttrInt |= HBA_PORTSPEED_256GFC;
if (phba->lmt & LMT_128Gb)
ae->un.AttrInt |= HBA_PORTSPEED_128GFC;
if (phba->lmt & LMT_64Gb)
@@ -2927,6 +2936,9 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport,
case LPFC_LINK_SPEED_128GHZ:
ae->un.AttrInt = HBA_PORTSPEED_128GFC;
break;
+ case LPFC_LINK_SPEED_256GHZ:
+ ae->un.AttrInt = HBA_PORTSPEED_256GFC;
+ break;
default:
ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN;
break;
@@ -3343,7 +3355,7 @@ lpfc_fdmi_vendor_attr_mi(struct lpfc_vport *vport,
ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
memset(ae, 0, 256);
sprintf(mibrevision, "ELXE2EM:%04d",
- phba->sli4_hba.pc_sli4_params.mi_value);
+ phba->sli4_hba.pc_sli4_params.mi_ver);
strncpy(ae->un.AttrString, &mibrevision[0], sizeof(ae->un.AttrString));
len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
len += (len & 3) ? (4 - (len & 3)) : 4;
@@ -3884,9 +3896,8 @@ lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/**
* lpfc_vmid_cmd - Build and send a FDMI cmd to the specified NPort
* @vport: pointer to a host virtual N_Port data structure.
- * @ndlp: ndlp to send FDMI cmd to (if NULL use FDMI_DID)
- * cmdcode: FDMI command to send
- * mask: Mask of HBA or PORT Attributes to send
+ * @cmdcode: application server command code to send
+ * @vmid: pointer to vmid info structure
*
* Builds and sends a FDMI command using the CT subsystem.
*/
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 6ff85ae57e79..bd6d459afce5 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -5429,6 +5429,180 @@ lpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes,
return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
}
+static int
+lpfc_cgn_buffer_open(struct inode *inode, struct file *file)
+{
+ struct lpfc_debug *debug;
+ int rc = -ENOMEM;
+
+ debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+ if (!debug)
+ goto out;
+
+ debug->buffer = vmalloc(LPFC_CGN_BUF_SIZE);
+ if (!debug->buffer) {
+ kfree(debug);
+ goto out;
+ }
+
+ debug->i_private = inode->i_private;
+ file->private_data = debug;
+
+ rc = 0;
+out:
+ return rc;
+}
+
+static ssize_t
+lpfc_cgn_buffer_read(struct file *file, char __user *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ struct lpfc_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ char *buffer = debug->buffer;
+ uint32_t *ptr;
+ int cnt, len = 0;
+
+ if (!phba->sli4_hba.pc_sli4_params.mi_ver || !phba->cgn_i) {
+ len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
+ "Congestion Mgmt is not supported\n");
+ goto out;
+ }
+ ptr = (uint32_t *)phba->cgn_i->virt;
+ len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
+ "Congestion Buffer Header\n");
+ /* Dump the first 32 bytes */
+ cnt = 32;
+ len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
+ "000: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3),
+ *(ptr + 4), *(ptr + 5), *(ptr + 6), *(ptr + 7));
+ ptr += 8;
+ len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
+ "Congestion Buffer Data\n");
+ while (cnt < sizeof(struct lpfc_cgn_info)) {
+ if (len > (LPFC_CGN_BUF_SIZE - LPFC_DEBUG_OUT_LINE_SZ)) {
+ len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
+ "Truncated . . .\n");
+ break;
+ }
+ len += scnprintf(buffer + len, LPFC_CGN_BUF_SIZE - len,
+ "%03x: %08x %08x %08x %08x "
+ "%08x %08x %08x %08x\n",
+ cnt, *ptr, *(ptr + 1), *(ptr + 2),
+ *(ptr + 3), *(ptr + 4), *(ptr + 5),
+ *(ptr + 6), *(ptr + 7));
+ cnt += 32;
+ ptr += 8;
+ }
+out:
+ return simple_read_from_buffer(buf, nbytes, ppos, buffer, len);
+}
+
+static int
+lpfc_cgn_buffer_release(struct inode *inode, struct file *file)
+{
+ struct lpfc_debug *debug = file->private_data;
+
+ vfree(debug->buffer);
+ kfree(debug);
+
+ return 0;
+}
+
+static int
+lpfc_rx_monitor_open(struct inode *inode, struct file *file)
+{
+ struct lpfc_rx_monitor_debug *debug;
+ int rc = -ENOMEM;
+
+ debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+ if (!debug)
+ goto out;
+
+ debug->buffer = vmalloc(MAX_DEBUGFS_RX_TABLE_SIZE);
+ if (!debug->buffer) {
+ kfree(debug);
+ goto out;
+ }
+
+ debug->i_private = inode->i_private;
+ file->private_data = debug;
+
+ rc = 0;
+out:
+ return rc;
+}
+
+static ssize_t
+lpfc_rx_monitor_read(struct file *file, char __user *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ struct lpfc_rx_monitor_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ char *buffer = debug->buffer;
+ struct rxtable_entry *entry;
+ int i, len = 0, head, tail, last, start;
+
+ head = atomic_read(&phba->rxtable_idx_head);
+ while (head == LPFC_RXMONITOR_TABLE_IN_USE) {
+ /* Table is getting updated */
+ msleep(20);
+ head = atomic_read(&phba->rxtable_idx_head);
+ }
+
+ tail = atomic_xchg(&phba->rxtable_idx_tail, head);
+ if (!phba->rxtable || head == tail) {
+ len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
+ "Rxtable is empty\n");
+ goto out;
+ }
+ last = (head > tail) ? head : LPFC_MAX_RXMONITOR_ENTRY;
+ start = tail;
+
+ len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
+ " MaxBPI\t Total Data Cmd Total Data Cmpl "
+ " Latency(us) Avg IO Size\tMax IO Size IO cnt "
+ "Info BWutil(ms)\n");
+get_table:
+ for (i = start; i < last; i++) {
+ entry = &phba->rxtable[i];
+ len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
+ "%3d:%12lld %12lld\t%12lld\t"
+ "%8lldus\t%8lld\t%10lld "
+ "%8d %2d %2d(%2d)\n",
+ i, entry->max_bytes_per_interval,
+ entry->total_bytes,
+ entry->rcv_bytes,
+ entry->avg_io_latency,
+ entry->avg_io_size,
+ entry->max_read_cnt,
+ entry->io_cnt,
+ entry->cmf_info,
+ entry->timer_utilization,
+ entry->timer_interval);
+ }
+
+ if (head != last) {
+ start = 0;
+ last = head;
+ goto get_table;
+ }
+out:
+ return simple_read_from_buffer(buf, nbytes, ppos, buffer, len);
+}
+
+static int
+lpfc_rx_monitor_release(struct inode *inode, struct file *file)
+{
+ struct lpfc_rx_monitor_debug *debug = file->private_data;
+
+ vfree(debug->buffer);
+ kfree(debug);
+
+ return 0;
+}
+
#undef lpfc_debugfs_op_disc_trc
static const struct file_operations lpfc_debugfs_op_disc_trc = {
.owner = THIS_MODULE,
@@ -5657,6 +5831,23 @@ static const struct file_operations lpfc_idiag_op_extAcc = {
.write = lpfc_idiag_extacc_write,
.release = lpfc_idiag_cmd_release,
};
+#undef lpfc_cgn_buffer_op
+static const struct file_operations lpfc_cgn_buffer_op = {
+ .owner = THIS_MODULE,
+ .open = lpfc_cgn_buffer_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_cgn_buffer_read,
+ .release = lpfc_cgn_buffer_release,
+};
+
+#undef lpfc_rx_monitor_op
+static const struct file_operations lpfc_rx_monitor_op = {
+ .owner = THIS_MODULE,
+ .open = lpfc_rx_monitor_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_rx_monitor_read,
+ .release = lpfc_rx_monitor_release,
+};
#endif
/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
@@ -5907,6 +6098,32 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
goto debug_failed;
}
+ /* Congestion Info Buffer */
+ scnprintf(name, sizeof(name), "cgn_buffer");
+ phba->debug_cgn_buffer =
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_cgn_buffer_op);
+ if (!phba->debug_cgn_buffer) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6527 Cannot create debugfs "
+ "cgn_buffer\n");
+ goto debug_failed;
+ }
+
+ /* RX Monitor */
+ scnprintf(name, sizeof(name), "rx_monitor");
+ phba->debug_rx_monitor =
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_rx_monitor_op);
+ if (!phba->debug_rx_monitor) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6528 Cannot create debugfs "
+ "rx_monitor\n");
+ goto debug_failed;
+ }
+
/* RAS log */
snprintf(name, sizeof(name), "ras_log");
phba->debug_ras_log =
@@ -6335,6 +6552,12 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
phba->debug_hbqinfo = NULL;
+ debugfs_remove(phba->debug_cgn_buffer);
+ phba->debug_cgn_buffer = NULL;
+
+ debugfs_remove(phba->debug_rx_monitor);
+ phba->debug_rx_monitor = NULL;
+
debugfs_remove(phba->debug_ras_log);
phba->debug_ras_log = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index 7ab6d3b08698..a5bf71b34972 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2007-2011 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -52,6 +52,9 @@
/* scsistat output buffer size */
#define LPFC_SCSISTAT_SIZE 8192
+/* Congestion Info Buffer size */
+#define LPFC_CGN_BUF_SIZE 8192
+
#define LPFC_DEBUG_OUT_LINE_SZ 80
/*
@@ -279,6 +282,12 @@ struct lpfc_idiag {
void *ptr_private;
};
+#define MAX_DEBUGFS_RX_TABLE_SIZE (100 * LPFC_MAX_RXMONITOR_ENTRY)
+struct lpfc_rx_monitor_debug {
+ char *i_private;
+ char *buffer;
+};
+
#else
#define lpfc_nvmeio_data(phba, fmt, arg...) \
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 131374a61d7e..871b665bd72e 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -78,10 +78,11 @@ struct lpfc_node_rrqs {
};
enum lpfc_fc4_xpt_flags {
- NLP_WAIT_FOR_UNREG = 0x1,
- SCSI_XPT_REGD = 0x2,
- NVME_XPT_REGD = 0x4,
- NLP_XPT_HAS_HH = 0x8,
+ NLP_XPT_REGD = 0x1,
+ SCSI_XPT_REGD = 0x2,
+ NVME_XPT_REGD = 0x4,
+ NVME_XPT_UNREG_WAIT = 0x8,
+ NLP_XPT_HAS_HH = 0x10
};
struct lpfc_nodelist {
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index e481f5fe29d7..1254a575fd47 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -56,6 +56,9 @@ static int lpfc_issue_els_fdisc(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp, uint8_t retry);
static int lpfc_issue_fabric_iocb(struct lpfc_hba *phba,
struct lpfc_iocbq *iocb);
+static void lpfc_cmpl_els_edc(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdiocb,
+ struct lpfc_iocbq *rspiocb);
static void lpfc_cmpl_els_uvem(struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_iocbq *);
@@ -1664,6 +1667,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
if (!new_ndlp || (new_ndlp == ndlp))
return ndlp;
+ /*
+ * Unregister from backend if not done yet. Could have been skipped
+ * due to ADISC
+ */
+ lpfc_nlp_unreg_node(vport, new_ndlp);
+
if (phba->sli_rev == LPFC_SLI_REV4) {
active_rrqs_xri_bitmap = mempool_alloc(phba->active_rrq_pool,
GFP_KERNEL);
@@ -2025,9 +2034,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
irsp->un.ulpWord[4]);
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
- if (lpfc_error_lost_link(irsp))
- goto check_plogi;
- else
+ if (!lpfc_error_lost_link(irsp))
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_PLOGI);
@@ -2080,7 +2087,6 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
NLP_EVT_CMPL_PLOGI);
}
- check_plogi:
if (disc && vport->num_disc_nodes) {
/* Check to see if there are more PLOGIs to be sent */
lpfc_more_plogi(vport);
@@ -2607,6 +2613,14 @@ lpfc_adisc_done(struct lpfc_vport *vport)
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
!(vport->fc_flag & FC_RSCN_MODE) &&
(phba->sli_rev < LPFC_SLI_REV4)) {
+
+ /*
+ * If link is down, clear_la and reg_vpi will be done after
+ * flogi following a link up event
+ */
+ if (!lpfc_is_link_up(phba))
+ return;
+
/* The ADISCs are complete. Doesn't matter if they
* succeeded or failed because the ADISC completion
* routine guarantees to call the state machine and
@@ -2749,12 +2763,9 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
"2755 ADISC failure DID:%06X Status:x%x/x%x\n",
ndlp->nlp_DID, irsp->ulpStatus,
irsp->un.ulpWord[4]);
- /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
- if (lpfc_error_lost_link(irsp))
- goto check_adisc;
- else
- lpfc_disc_state_machine(vport, ndlp, cmdiocb,
- NLP_EVT_CMPL_ADISC);
+
+ lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+ NLP_EVT_CMPL_ADISC);
/* As long as this node is not registered with the SCSI or NVMe
* transport, it is no longer an active node. Otherwise
@@ -2772,7 +2783,6 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_ADISC);
- check_adisc:
/* Check to see if there are more ADISCs to be sent */
if (disc && vport->num_disc_nodes)
lpfc_more_adisc(vport);
@@ -3253,7 +3263,7 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
irsp->ulpStatus, irsp->un.ulpWord[4],
irsp->un.elsreq64.remoteID);
/* ELS cmd tag <ulpIoTag> completes */
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
"0217 ELS cmd tag x%x completes Data: x%x x%x x%x "
"x%x\n",
irsp->ulpIoTag, irsp->ulpStatus,
@@ -3279,6 +3289,9 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
case ELS_CMD_SCR:
lpfc_issue_els_scr(vport, cmdiocb->retry);
break;
+ case ELS_CMD_EDC:
+ lpfc_issue_els_edc(vport, cmdiocb->retry);
+ break;
case ELS_CMD_RDF:
cmdiocb->context1 = NULL; /* save ndlp refcnt */
lpfc_issue_els_rdf(vport, cmdiocb->retry);
@@ -3288,6 +3301,11 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
phba->fc_stat.elsRetryExceeded++;
}
+ if (cmd == ELS_CMD_EDC) {
+ /* must be called before checking uplStatus and returning */
+ lpfc_cmpl_els_edc(phba, cmdiocb, rspiocb);
+ return;
+ }
if (irsp->ulpStatus) {
/* ELS discovery cmd completes with error */
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
@@ -3312,11 +3330,14 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
for (i = 0; i < ELS_RDF_REG_TAG_CNT &&
i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++)
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "4677 Fabric RDF Notification Grant Data: "
- "0x%08x\n",
- be32_to_cpu(
- prdf->reg_d1.desc_tags[i]));
+ lpfc_printf_vlog(vport, KERN_INFO,
+ LOG_ELS | LOG_CGN_MGMT,
+ "4677 Fabric RDF Notification Grant "
+ "Data: 0x%08x Reg: %x %x\n",
+ be32_to_cpu(
+ prdf->reg_d1.desc_tags[i]),
+ phba->cgn_reg_signal,
+ phba->cgn_reg_fpin);
}
out:
@@ -3375,6 +3396,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
if (phba->sli_rev == LPFC_SLI_REV4) {
rc = lpfc_reg_fab_ctrl_node(vport, ndlp);
if (rc) {
+ lpfc_els_free_iocb(phba, elsiocb);
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
"0937 %s: Failed to reg fc node, rc %d\n",
__func__, rc);
@@ -3413,7 +3435,6 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
return 1;
}
- /* Keep the ndlp just in case RDF is being sent */
return 0;
}
@@ -3657,28 +3678,15 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
lpfc_enqueue_node(vport, ndlp);
}
- /* RDF ELS is not required on an NPIV VN_Port. */
- if (vport->port_type == LPFC_NPIV_PORT) {
- lpfc_nlp_put(ndlp);
+ /* RDF ELS is not required on an NPIV VN_Port. */
+ if (vport->port_type == LPFC_NPIV_PORT)
return -EACCES;
- }
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_RDF);
if (!elsiocb)
return -ENOMEM;
- if (phba->sli_rev == LPFC_SLI_REV4 &&
- !(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
- "0939 %s: FC_NODE x%x RPI x%x flag x%x "
- "ste x%x type x%x Not registered\n",
- __func__, ndlp->nlp_DID, ndlp->nlp_rpi,
- ndlp->nlp_flag, ndlp->nlp_state,
- ndlp->nlp_type);
- return -ENODEV;
- }
-
/* Configure the payload for the supported FPIN events. */
prdf = (struct lpfc_els_rdf_req *)
(((struct lpfc_dmabuf *)elsiocb->context2)->virt);
@@ -3695,10 +3703,12 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
prdf->reg_d1.desc_tags[2] = cpu_to_be32(ELS_DTAG_PEER_CONGEST);
prdf->reg_d1.desc_tags[3] = cpu_to_be32(ELS_DTAG_CONGESTION);
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "6444 Xmit RDF to remote NPORT x%x\n",
- ndlp->nlp_DID);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
+ "6444 Xmit RDF to remote NPORT x%x Reg: %x %x\n",
+ ndlp->nlp_DID, phba->cgn_reg_signal,
+ phba->cgn_reg_fpin);
+ phba->cgn_fpin_frequency = LPFC_FPIN_INIT_FREQ;
elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
elsiocb->context1 = lpfc_nlp_get(ndlp);
if (!elsiocb->context1) {
@@ -3739,7 +3749,7 @@ lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
{
/* Send LS_ACC */
if (lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL)) {
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
"1623 Failed to RDF_ACC from x%x for x%x\n",
ndlp->nlp_DID, vport->fc_myDID);
return -EIO;
@@ -3747,7 +3757,7 @@ lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
/* Issue new RDF for reregistering */
if (lpfc_issue_els_rdf(vport, 0)) {
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
"2623 Failed to re register RDF for x%x\n",
vport->fc_myDID);
return -EIO;
@@ -3757,6 +3767,448 @@ lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
+ * lpfc_least_capable_settings - helper function for EDC rsp processing
+ * @phba: pointer to lpfc hba data structure.
+ * @pcgd: pointer to congestion detection descriptor in EDC rsp.
+ *
+ * This helper routine determines the least capable setting for
+ * congestion signals, signal freq, including scale, from the
+ * congestion detection descriptor in the EDC rsp. The routine
+ * sets @phba values in preparation for a set_featues mailbox.
+ **/
+static void
+lpfc_least_capable_settings(struct lpfc_hba *phba,
+ struct fc_diag_cg_sig_desc *pcgd)
+{
+ u32 rsp_sig_cap = 0, drv_sig_cap = 0;
+ u32 rsp_sig_freq_cyc = 0, rsp_sig_freq_scale = 0;
+ struct lpfc_cgn_info *cp;
+ u32 crc;
+ u16 sig_freq;
+
+ /* Get rsp signal and frequency capabilities. */
+ rsp_sig_cap = be32_to_cpu(pcgd->xmt_signal_capability);
+ rsp_sig_freq_cyc = be16_to_cpu(pcgd->xmt_signal_frequency.count);
+ rsp_sig_freq_scale = be16_to_cpu(pcgd->xmt_signal_frequency.units);
+
+ /* If the Fport does not support signals. Set FPIN only */
+ if (rsp_sig_cap == EDC_CG_SIG_NOTSUPPORTED)
+ goto out_no_support;
+
+ /* Apply the xmt scale to the xmt cycle to get the correct frequency.
+ * Adapter default is 100 millisSeconds. Convert all xmt cycle values
+ * to milliSeconds.
+ */
+ switch (rsp_sig_freq_scale) {
+ case EDC_CG_SIGFREQ_SEC:
+ rsp_sig_freq_cyc *= MSEC_PER_SEC;
+ break;
+ case EDC_CG_SIGFREQ_MSEC:
+ rsp_sig_freq_cyc = 1;
+ break;
+ default:
+ goto out_no_support;
+ }
+
+ /* Convenient shorthand. */
+ drv_sig_cap = phba->cgn_reg_signal;
+
+ /* Choose the least capable frequency. */
+ if (rsp_sig_freq_cyc > phba->cgn_sig_freq)
+ phba->cgn_sig_freq = rsp_sig_freq_cyc;
+
+ /* Should be some common signals support. Settle on least capable
+ * signal and adjust FPIN values. Initialize defaults to ease the
+ * decision.
+ */
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_WARN | LPFC_CGN_FPIN_ALARM;
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ if (rsp_sig_cap == EDC_CG_SIG_WARN_ONLY &&
+ (drv_sig_cap == EDC_CG_SIG_WARN_ONLY ||
+ drv_sig_cap == EDC_CG_SIG_WARN_ALARM)) {
+ phba->cgn_reg_signal = EDC_CG_SIG_WARN_ONLY;
+ phba->cgn_reg_fpin &= ~LPFC_CGN_FPIN_WARN;
+ }
+ if (rsp_sig_cap == EDC_CG_SIG_WARN_ALARM) {
+ if (drv_sig_cap == EDC_CG_SIG_WARN_ALARM) {
+ phba->cgn_reg_signal = EDC_CG_SIG_WARN_ALARM;
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_NONE;
+ }
+ if (drv_sig_cap == EDC_CG_SIG_WARN_ONLY) {
+ phba->cgn_reg_signal = EDC_CG_SIG_WARN_ONLY;
+ phba->cgn_reg_fpin &= ~LPFC_CGN_FPIN_WARN;
+ }
+ }
+
+ if (!phba->cgn_i)
+ return;
+
+ /* Update signal frequency in congestion info buffer */
+ cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
+
+ /* Frequency (in ms) Signal Warning/Signal Congestion Notifications
+ * are received by the HBA
+ */
+ sig_freq = phba->cgn_sig_freq;
+
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY)
+ cp->cgn_warn_freq = cpu_to_le16(sig_freq);
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
+ cp->cgn_alarm_freq = cpu_to_le16(sig_freq);
+ cp->cgn_warn_freq = cpu_to_le16(sig_freq);
+ }
+ crc = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED);
+ cp->cgn_info_crc = cpu_to_le32(crc);
+ return;
+
+out_no_support:
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ phba->cgn_sig_freq = 0;
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_ALARM | LPFC_CGN_FPIN_WARN;
+}
+
+DECLARE_ENUM2STR_LOOKUP(lpfc_get_tlv_dtag_nm, fc_ls_tlv_dtag,
+ FC_LS_TLV_DTAG_INIT);
+
+/**
+ * lpfc_cmpl_els_edc - Completion callback function for EDC
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the completion callback function for issuing the Exchange
+ * Diagnostic Capabilities (EDC) command. The driver issues an EDC to
+ * notify the FPort of its Congestion and Link Fault capabilities. This
+ * routine parses the FPort's response and decides on the least common
+ * values applicable to both FPort and NPort for Warnings and Alarms that
+ * are communicated via hardware signals.
+ **/
+static void
+lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ struct lpfc_iocbq *rspiocb)
+{
+ IOCB_t *irsp;
+ struct fc_els_edc_resp *edc_rsp;
+ struct fc_tlv_desc *tlv;
+ struct fc_diag_cg_sig_desc *pcgd;
+ struct fc_diag_lnkflt_desc *plnkflt;
+ struct lpfc_dmabuf *pcmd, *prsp;
+ const char *dtag_nm;
+ u32 *pdata, dtag;
+ int desc_cnt = 0, bytes_remain;
+ bool rcv_cap_desc = false;
+ struct lpfc_nodelist *ndlp;
+
+ irsp = &rspiocb->iocb;
+ ndlp = cmdiocb->context1;
+
+ lpfc_debugfs_disc_trc(phba->pport, LPFC_DISC_TRC_ELS_CMD,
+ "EDC cmpl: status:x%x/x%x did:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->un.elsreq64.remoteID);
+
+ /* ELS cmd tag <ulpIoTag> completes */
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
+ "4201 EDC cmd tag x%x completes Data: x%x x%x x%x\n",
+ irsp->ulpIoTag, irsp->ulpStatus,
+ irsp->un.ulpWord[4], irsp->ulpTimeout);
+
+ pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
+ if (!pcmd)
+ goto out;
+
+ pdata = (u32 *)pcmd->virt;
+ if (!pdata)
+ goto out;
+
+ /* Need to clear signal values, send features MB and RDF with FPIN. */
+ if (irsp->ulpStatus)
+ goto out;
+
+ prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
+ if (!prsp)
+ goto out;
+
+ edc_rsp = prsp->virt;
+ if (!edc_rsp)
+ goto out;
+
+ /* ELS cmd tag <ulpIoTag> completes */
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
+ "4676 Fabric EDC Rsp: "
+ "0x%02x, 0x%08x\n",
+ edc_rsp->acc_hdr.la_cmd,
+ be32_to_cpu(edc_rsp->desc_list_len));
+
+ /*
+ * Payload length in bytes is the response descriptor list
+ * length minus the 12 bytes of Link Service Request
+ * Information descriptor in the reply.
+ */
+ bytes_remain = be32_to_cpu(edc_rsp->desc_list_len) -
+ sizeof(struct fc_els_lsri_desc);
+ if (bytes_remain <= 0)
+ goto out;
+
+ tlv = edc_rsp->desc;
+
+ /*
+ * cycle through EDC diagnostic descriptors to find the
+ * congestion signaling capability descriptor
+ */
+ while (bytes_remain) {
+ if (bytes_remain < FC_TLV_DESC_HDR_SZ) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6461 Truncated TLV hdr on "
+ "Diagnostic descriptor[%d]\n",
+ desc_cnt);
+ goto out;
+ }
+
+ dtag = be32_to_cpu(tlv->desc_tag);
+ switch (dtag) {
+ case ELS_DTAG_LNK_FAULT_CAP:
+ if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
+ FC_TLV_DESC_SZ_FROM_LENGTH(tlv) !=
+ sizeof(struct fc_diag_lnkflt_desc)) {
+ lpfc_printf_log(
+ phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6462 Truncated Link Fault Diagnostic "
+ "descriptor[%d]: %d vs 0x%zx 0x%zx\n",
+ desc_cnt, bytes_remain,
+ FC_TLV_DESC_SZ_FROM_LENGTH(tlv),
+ sizeof(struct fc_diag_cg_sig_desc));
+ goto out;
+ }
+ plnkflt = (struct fc_diag_lnkflt_desc *)tlv;
+ lpfc_printf_log(
+ phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
+ "4617 Link Fault Desc Data: 0x%08x 0x%08x "
+ "0x%08x 0x%08x 0x%08x\n",
+ be32_to_cpu(plnkflt->desc_tag),
+ be32_to_cpu(plnkflt->desc_len),
+ be32_to_cpu(
+ plnkflt->degrade_activate_threshold),
+ be32_to_cpu(
+ plnkflt->degrade_deactivate_threshold),
+ be32_to_cpu(plnkflt->fec_degrade_interval));
+ break;
+ case ELS_DTAG_CG_SIGNAL_CAP:
+ if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
+ FC_TLV_DESC_SZ_FROM_LENGTH(tlv) !=
+ sizeof(struct fc_diag_cg_sig_desc)) {
+ lpfc_printf_log(
+ phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6463 Truncated Cgn Signal Diagnostic "
+ "descriptor[%d]: %d vs 0x%zx 0x%zx\n",
+ desc_cnt, bytes_remain,
+ FC_TLV_DESC_SZ_FROM_LENGTH(tlv),
+ sizeof(struct fc_diag_cg_sig_desc));
+ goto out;
+ }
+
+ pcgd = (struct fc_diag_cg_sig_desc *)tlv;
+ lpfc_printf_log(
+ phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
+ "4616 CGN Desc Data: 0x%08x 0x%08x "
+ "0x%08x 0x%04x 0x%04x 0x%08x 0x%04x 0x%04x\n",
+ be32_to_cpu(pcgd->desc_tag),
+ be32_to_cpu(pcgd->desc_len),
+ be32_to_cpu(pcgd->xmt_signal_capability),
+ be32_to_cpu(pcgd->xmt_signal_frequency.count),
+ be32_to_cpu(pcgd->xmt_signal_frequency.units),
+ be32_to_cpu(pcgd->rcv_signal_capability),
+ be32_to_cpu(pcgd->rcv_signal_frequency.count),
+ be32_to_cpu(pcgd->rcv_signal_frequency.units));
+
+ /* Compare driver and Fport capabilities and choose
+ * least common.
+ */
+ lpfc_least_capable_settings(phba, pcgd);
+ rcv_cap_desc = true;
+ break;
+ default:
+ dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "4919 unknown Diagnostic "
+ "Descriptor[%d]: tag x%x (%s)\n",
+ desc_cnt, dtag, dtag_nm);
+ }
+
+ bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);
+ tlv = fc_tlv_next_desc(tlv);
+ desc_cnt++;
+ }
+
+out:
+ if (!rcv_cap_desc) {
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_ALARM | LPFC_CGN_FPIN_WARN;
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ phba->cgn_sig_freq = 0;
+ lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_CGN_MGMT,
+ "4202 EDC rsp error - sending RDF "
+ "for FPIN only.\n");
+ }
+
+ lpfc_config_cgn_signal(phba);
+
+ /* Check to see if link went down during discovery */
+ lpfc_els_chk_latt(phba->pport);
+ lpfc_debugfs_disc_trc(phba->pport, LPFC_DISC_TRC_ELS_CMD,
+ "EDC Cmpl: did:x%x refcnt %d",
+ ndlp->nlp_DID, kref_read(&ndlp->kref), 0);
+ lpfc_els_free_iocb(phba, cmdiocb);
+ lpfc_nlp_put(ndlp);
+}
+
+static void
+lpfc_format_edc_cgn_desc(struct lpfc_hba *phba, struct fc_diag_cg_sig_desc *cgd)
+{
+ /* We are assuming cgd was zero'ed before calling this routine */
+
+ /* Configure the congestion detection capability */
+ cgd->desc_tag = cpu_to_be32(ELS_DTAG_CG_SIGNAL_CAP);
+
+ /* Descriptor len doesn't include the tag or len fields. */
+ cgd->desc_len = cpu_to_be32(
+ FC_TLV_DESC_LENGTH_FROM_SZ(struct fc_diag_cg_sig_desc));
+
+ /* xmt_signal_capability already set to EDC_CG_SIG_NOTSUPPORTED.
+ * xmt_signal_frequency.count already set to 0.
+ * xmt_signal_frequency.units already set to 0.
+ */
+
+ if (phba->cmf_active_mode == LPFC_CFG_OFF) {
+ /* rcv_signal_capability already set to EDC_CG_SIG_NOTSUPPORTED.
+ * rcv_signal_frequency.count already set to 0.
+ * rcv_signal_frequency.units already set to 0.
+ */
+ phba->cgn_sig_freq = 0;
+ return;
+ }
+ switch (phba->cgn_reg_signal) {
+ case EDC_CG_SIG_WARN_ONLY:
+ cgd->rcv_signal_capability = cpu_to_be32(EDC_CG_SIG_WARN_ONLY);
+ break;
+ case EDC_CG_SIG_WARN_ALARM:
+ cgd->rcv_signal_capability = cpu_to_be32(EDC_CG_SIG_WARN_ALARM);
+ break;
+ default:
+ /* rcv_signal_capability left 0 thus no support */
+ break;
+ }
+
+ /* We start negotiation with lpfc_fabric_cgn_frequency, after
+ * the completion we settle on the higher frequency.
+ */
+ cgd->rcv_signal_frequency.count =
+ cpu_to_be16(lpfc_fabric_cgn_frequency);
+ cgd->rcv_signal_frequency.units =
+ cpu_to_be16(EDC_CG_SIGFREQ_MSEC);
+}
+
+ /**
+ * lpfc_issue_els_edc - Exchange Diagnostic Capabilities with the fabric.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @retry: retry counter for the command iocb.
+ *
+ * This routine issues an ELS EDC to the F-Port Controller to communicate
+ * this N_Port's support of hardware signals in its Congestion
+ * Capabilities Descriptor.
+ *
+ * Note: This routine does not check if one or more signals are
+ * set in the cgn_reg_signal parameter. The caller makes the
+ * decision to enforce cgn_reg_signal as nonzero or zero depending
+ * on the conditions. During Fabric requests, the driver
+ * requires cgn_reg_signals to be nonzero. But a dynamic request
+ * to set the congestion mode to OFF from Monitor or Manage
+ * would correctly issue an EDC with no signals enabled to
+ * turn off switch functionality and then update the FW.
+ *
+ * Return code
+ * 0 - Successfully issued edc command
+ * 1 - Failed to issue edc command
+ **/
+int
+lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_iocbq *elsiocb;
+ struct lpfc_els_edc_req *edc_req;
+ struct fc_diag_cg_sig_desc *cgn_desc;
+ u16 cmdsize;
+ struct lpfc_nodelist *ndlp;
+ u8 *pcmd = NULL;
+ u32 edc_req_size, cgn_desc_size;
+ int rc;
+
+ if (vport->port_type == LPFC_NPIV_PORT)
+ return -EACCES;
+
+ ndlp = lpfc_findnode_did(vport, Fabric_DID);
+ if (!ndlp || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)
+ return -ENODEV;
+
+ /* If HBA doesn't support signals, drop into RDF */
+ if (!phba->cgn_init_reg_signal)
+ goto try_rdf;
+
+ edc_req_size = sizeof(struct fc_els_edc);
+ cgn_desc_size = sizeof(struct fc_diag_cg_sig_desc);
+ cmdsize = edc_req_size + cgn_desc_size;
+ elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+ ndlp->nlp_DID, ELS_CMD_EDC);
+ if (!elsiocb)
+ goto try_rdf;
+
+ /* Configure the payload for the supported Diagnostics capabilities. */
+ pcmd = (u8 *)(((struct lpfc_dmabuf *)elsiocb->context2)->virt);
+ memset(pcmd, 0, cmdsize);
+ edc_req = (struct lpfc_els_edc_req *)pcmd;
+ edc_req->edc.desc_len = cpu_to_be32(cgn_desc_size);
+ edc_req->edc.edc_cmd = ELS_EDC;
+
+ cgn_desc = &edc_req->cgn_desc;
+
+ lpfc_format_edc_cgn_desc(phba, cgn_desc);
+
+ phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_CGN_MGMT,
+ "4623 Xmit EDC to remote "
+ "NPORT x%x reg_sig x%x reg_fpin:x%x\n",
+ ndlp->nlp_DID, phba->cgn_reg_signal,
+ phba->cgn_reg_fpin);
+
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+ return -EIO;
+ }
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue EDC: did:x%x refcnt %d",
+ ndlp->nlp_DID, kref_read(&ndlp->kref), 0);
+ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
+ if (rc == IOCB_ERROR) {
+ /* The additional lpfc_nlp_put will cause the following
+ * lpfc_els_free_iocb routine to trigger the rlease of
+ * the node.
+ */
+ lpfc_els_free_iocb(phba, elsiocb);
+ lpfc_nlp_put(ndlp);
+ goto try_rdf;
+ }
+ return 0;
+try_rdf:
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_WARN | LPFC_CGN_FPIN_ALARM;
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ rc = lpfc_issue_els_rdf(vport, 0);
+ return rc;
+}
+
+/**
* lpfc_cancel_retry_delay_tmo - Cancel the timer with delayed iocb-cmd retry
* @vport: pointer to a host virtual N_Port data structure.
* @nlp: pointer to a node-list data structure.
@@ -4378,7 +4830,7 @@ out_retry:
(cmd == ELS_CMD_NVMEPRLI))
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_PRLI_ISSUE);
- else
+ else if (cmd != ELS_CMD_ADISC)
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_NPR_NODE);
ndlp->nlp_last_elscmd = cmd;
@@ -4520,7 +4972,7 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
{
struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
- /* The I/O job is complete. Clear the context1 data. */
+ /* The I/O iocb is complete. Clear the context1 data. */
elsiocb->context1 = NULL;
/* context2 = cmd, context2->next = rsp, context3 = bpl */
@@ -4612,6 +5064,15 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
+
+ /* If PLOGI is being retried, PLOGI completion will cleanup the
+ * node. The NLP_NPR_2B_DISC flag needs to be retained to make
+ * progress on nodes discovered from last RSCN.
+ */
+ if ((ndlp->nlp_flag & NLP_DELAY_TMO) &&
+ (ndlp->nlp_last_elscmd == ELS_CMD_PLOGI))
+ goto out;
+
/* NPort Recovery mode or node is just allocated */
if (!lpfc_nlp_not_used(ndlp)) {
/* A LOGO is completing and the node is in NPR state.
@@ -5158,6 +5619,86 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
return 0;
}
+ /**
+ * lpfc_issue_els_edc_rsp - Exchange Diagnostic Capabilities with the fabric.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to the original lpfc command iocb data structure.
+ * @ndlp: NPort to where rsp is directed
+ *
+ * This routine issues an EDC ACC RSP to the F-Port Controller to communicate
+ * this N_Port's support of hardware signals in its Congestion
+ * Capabilities Descriptor.
+ *
+ * Return code
+ * 0 - Successfully issued edc rsp command
+ * 1 - Failed to issue edc rsp command
+ **/
+static int
+lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+ struct lpfc_nodelist *ndlp)
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_els_edc_rsp *edc_rsp;
+ struct lpfc_iocbq *elsiocb;
+ IOCB_t *icmd, *cmd;
+ uint8_t *pcmd;
+ int cmdsize, rc;
+
+ cmdsize = sizeof(struct lpfc_els_edc_rsp);
+ elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, cmdiocb->retry,
+ ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+ if (!elsiocb)
+ return 1;
+
+ icmd = &elsiocb->iocb;
+ cmd = &cmdiocb->iocb;
+ icmd->ulpContext = cmd->ulpContext; /* Xri / rx_id */
+ icmd->unsli3.rcvsli3.ox_id = cmd->unsli3.rcvsli3.ox_id;
+ pcmd = (((struct lpfc_dmabuf *)elsiocb->context2)->virt);
+ memset(pcmd, 0, cmdsize);
+
+ edc_rsp = (struct lpfc_els_edc_rsp *)pcmd;
+ edc_rsp->edc_rsp.acc_hdr.la_cmd = ELS_LS_ACC;
+ edc_rsp->edc_rsp.desc_list_len = cpu_to_be32(
+ FC_TLV_DESC_LENGTH_FROM_SZ(struct lpfc_els_edc_rsp));
+ edc_rsp->edc_rsp.lsri.desc_tag = cpu_to_be32(ELS_DTAG_LS_REQ_INFO);
+ edc_rsp->edc_rsp.lsri.desc_len = cpu_to_be32(
+ FC_TLV_DESC_LENGTH_FROM_SZ(struct fc_els_lsri_desc));
+ edc_rsp->edc_rsp.lsri.rqst_w0.cmd = ELS_EDC;
+ lpfc_format_edc_cgn_desc(phba, &edc_rsp->cgn_desc);
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+ "Issue EDC ACC: did:x%x flg:x%x refcnt %d",
+ ndlp->nlp_DID, ndlp->nlp_flag,
+ kref_read(&ndlp->kref));
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
+
+ phba->fc_stat.elsXmitACC++;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+ return 1;
+ }
+
+ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
+ if (rc == IOCB_ERROR) {
+ lpfc_els_free_iocb(phba, elsiocb);
+ lpfc_nlp_put(ndlp);
+ return 1;
+ }
+
+ /* Xmit ELS ACC response tag <ulpIoTag> */
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0152 Xmit EDC ACC response Status: x%x, IoTag: x%x, "
+ "XRI: x%x, DID: x%x, nlp_flag: x%x nlp_state: x%x "
+ "RPI: x%x, fc_flag x%x\n",
+ rc, elsiocb->iotag, elsiocb->sli4_xritag,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi, vport->fc_flag);
+
+ return 0;
+}
+
/**
* lpfc_els_rsp_adisc_acc - Prepare and issue acc response to adisc iocb cmd
* @vport: pointer to a virtual N_Port data structure.
@@ -5657,25 +6198,40 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport)
/* go thru NPR nodes and issue any remaining ELS ADISCs */
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
- if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
- (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
- (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) {
- spin_lock_irq(&ndlp->lock);
- ndlp->nlp_flag &= ~NLP_NPR_ADISC;
- spin_unlock_irq(&ndlp->lock);
- ndlp->nlp_prev_state = ndlp->nlp_state;
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
- lpfc_issue_els_adisc(vport, ndlp, 0);
- sentadisc++;
- vport->num_disc_nodes++;
- if (vport->num_disc_nodes >=
- vport->cfg_discovery_threads) {
- spin_lock_irq(shost->host_lock);
- vport->fc_flag |= FC_NLP_MORE;
- spin_unlock_irq(shost->host_lock);
- break;
- }
+
+ if (ndlp->nlp_state != NLP_STE_NPR_NODE ||
+ !(ndlp->nlp_flag & NLP_NPR_ADISC))
+ continue;
+
+ spin_lock_irq(&ndlp->lock);
+ ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+ spin_unlock_irq(&ndlp->lock);
+
+ if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
+ /* This node was marked for ADISC but was not picked
+ * for discovery. This is possible if the node was
+ * missing in gidft response.
+ *
+ * At time of marking node for ADISC, we skipped unreg
+ * from backend
+ */
+ lpfc_nlp_unreg_node(vport, ndlp);
+ continue;
+ }
+
+ ndlp->nlp_prev_state = ndlp->nlp_state;
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+ lpfc_issue_els_adisc(vport, ndlp, 0);
+ sentadisc++;
+ vport->num_disc_nodes++;
+ if (vport->num_disc_nodes >=
+ vport->cfg_discovery_threads) {
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag |= FC_NLP_MORE;
+ spin_unlock_irq(shost->host_lock);
+ break;
}
+
}
if (sentadisc == 0) {
spin_lock_irq(shost->host_lock);
@@ -6087,6 +6643,12 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
case LPFC_LINK_SPEED_64GHZ:
rdp_speed = RDP_PS_64GB;
break;
+ case LPFC_LINK_SPEED_128GHZ:
+ rdp_speed = RDP_PS_128GB;
+ break;
+ case LPFC_LINK_SPEED_256GHZ:
+ rdp_speed = RDP_PS_256GB;
+ break;
default:
rdp_speed = RDP_PS_UNKNOWN;
break;
@@ -6094,6 +6656,8 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
desc->info.port_speed.speed = cpu_to_be16(rdp_speed);
+ if (phba->lmt & LMT_256Gb)
+ rdp_cap |= RDP_PS_256GB;
if (phba->lmt & LMT_128Gb)
rdp_cap |= RDP_PS_128GB;
if (phba->lmt & LMT_64Gb)
@@ -6886,13 +7450,6 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
continue;
}
- /* Check to see if we need to NVME rescan this target
- * remoteport.
- */
- if (ndlp->nlp_fc4_type & NLP_FC4_NVME &&
- ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_DISCOVERY))
- lpfc_nvme_rescan_port(vport, ndlp);
-
lpfc_disc_state_machine(vport, ndlp, NULL,
NLP_EVT_DEVICE_RECOVERY);
lpfc_cancel_retry_delay_tmo(vport, ndlp);
@@ -8212,6 +8769,125 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/**
+ * lpfc_els_rcv_edc - Process an unsolicited EDC iocb
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * Return code
+ * 0 - Successfully processed echo iocb (currently always return 0)
+ **/
+static int
+lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+ struct lpfc_nodelist *ndlp)
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct fc_els_edc *edc_req;
+ struct fc_tlv_desc *tlv;
+ uint8_t *payload;
+ uint32_t *ptr, dtag;
+ const char *dtag_nm;
+ int desc_cnt = 0, bytes_remain;
+ bool rcv_cap_desc = false;
+
+ payload = ((struct lpfc_dmabuf *)cmdiocb->context2)->virt;
+
+ edc_req = (struct fc_els_edc *)payload;
+ bytes_remain = be32_to_cpu(edc_req->desc_len);
+
+ ptr = (uint32_t *)payload;
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
+ "3319 Rcv EDC payload len %d: x%x x%x x%x\n",
+ bytes_remain, be32_to_cpu(*ptr),
+ be32_to_cpu(*(ptr + 1)), be32_to_cpu(*(ptr + 2)));
+
+ /* No signal support unless there is a congestion descriptor */
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ phba->cgn_sig_freq = 0;
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_ALARM | LPFC_CGN_FPIN_WARN;
+
+ if (bytes_remain <= 0)
+ goto out;
+
+ tlv = edc_req->desc;
+
+ /*
+ * cycle through EDC diagnostic descriptors to find the
+ * congestion signaling capability descriptor
+ */
+ while (bytes_remain && !rcv_cap_desc) {
+ if (bytes_remain < FC_TLV_DESC_HDR_SZ) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6464 Truncated TLV hdr on "
+ "Diagnostic descriptor[%d]\n",
+ desc_cnt);
+ goto out;
+ }
+
+ dtag = be32_to_cpu(tlv->desc_tag);
+ switch (dtag) {
+ case ELS_DTAG_LNK_FAULT_CAP:
+ if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
+ FC_TLV_DESC_SZ_FROM_LENGTH(tlv) !=
+ sizeof(struct fc_diag_lnkflt_desc)) {
+ lpfc_printf_log(
+ phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6465 Truncated Link Fault Diagnostic "
+ "descriptor[%d]: %d vs 0x%zx 0x%zx\n",
+ desc_cnt, bytes_remain,
+ FC_TLV_DESC_SZ_FROM_LENGTH(tlv),
+ sizeof(struct fc_diag_cg_sig_desc));
+ goto out;
+ }
+ /* No action for Link Fault descriptor for now */
+ break;
+ case ELS_DTAG_CG_SIGNAL_CAP:
+ if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
+ FC_TLV_DESC_SZ_FROM_LENGTH(tlv) !=
+ sizeof(struct fc_diag_cg_sig_desc)) {
+ lpfc_printf_log(
+ phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6466 Truncated cgn signal Diagnostic "
+ "descriptor[%d]: %d vs 0x%zx 0x%zx\n",
+ desc_cnt, bytes_remain,
+ FC_TLV_DESC_SZ_FROM_LENGTH(tlv),
+ sizeof(struct fc_diag_cg_sig_desc));
+ goto out;
+ }
+
+ phba->cgn_reg_fpin = phba->cgn_init_reg_fpin;
+ phba->cgn_reg_signal = phba->cgn_init_reg_signal;
+
+ /* We start negotiation with lpfc_fabric_cgn_frequency.
+ * When we process the EDC, we will settle on the
+ * higher frequency.
+ */
+ phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
+
+ lpfc_least_capable_settings(
+ phba, (struct fc_diag_cg_sig_desc *)tlv);
+ rcv_cap_desc = true;
+ break;
+ default:
+ dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6467 unknown Diagnostic "
+ "Descriptor[%d]: tag x%x (%s)\n",
+ desc_cnt, dtag, dtag_nm);
+ }
+ bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);
+ tlv = fc_tlv_next_desc(tlv);
+ desc_cnt++;
+ }
+out:
+ /* Need to send back an ACC */
+ lpfc_issue_els_edc_rsp(vport, cmdiocb, ndlp);
+
+ lpfc_config_cgn_signal(phba);
+ return 0;
+}
+
+/**
* lpfc_els_timeout - Handler funciton to the els timer
* @t: timer context used to obtain the vport.
*
@@ -8668,50 +9344,304 @@ lpfc_send_els_event(struct lpfc_vport *vport,
}
-DECLARE_ENUM2STR_LOOKUP(lpfc_get_tlv_dtag_nm, fc_ls_tlv_dtag,
- FC_LS_TLV_DTAG_INIT);
-
DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_li_event_nm, fc_fpin_li_event_types,
FC_FPIN_LI_EVT_TYPES_INIT);
+DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_deli_event_nm, fc_fpin_deli_event_types,
+ FC_FPIN_DELI_EVT_TYPES_INIT);
+
+DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_congn_event_nm, fc_fpin_congn_event_types,
+ FC_FPIN_CONGN_EVT_TYPES_INIT);
+
+DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_congn_severity_nm,
+ fc_fpin_congn_severity_types,
+ FC_FPIN_CONGN_SEVERITY_INIT);
+
+
+/**
+ * lpfc_display_fpin_wwpn - Display WWPNs accessible by the attached port
+ * @phba: Pointer to phba object.
+ * @wwnlist: Pointer to list of WWPNs in FPIN payload
+ * @cnt: count of WWPNs in FPIN payload
+ *
+ * This routine is called by LI and PC descriptors.
+ * Limit the number of WWPNs displayed to 6 log messages, 6 per log message
+ */
+static void
+lpfc_display_fpin_wwpn(struct lpfc_hba *phba, __be64 *wwnlist, u32 cnt)
+{
+ char buf[LPFC_FPIN_WWPN_LINE_SZ];
+ __be64 wwn;
+ u64 wwpn;
+ int i, len;
+ int line = 0;
+ int wcnt = 0;
+ bool endit = false;
+
+ len = scnprintf(buf, LPFC_FPIN_WWPN_LINE_SZ, "Accessible WWPNs:");
+ for (i = 0; i < cnt; i++) {
+ /* Are we on the last WWPN */
+ if (i == (cnt - 1))
+ endit = true;
+
+ /* Extract the next WWPN from the payload */
+ wwn = *wwnlist++;
+ wwpn = be64_to_cpu(wwn);
+ len += scnprintf(buf + len, LPFC_FPIN_WWPN_LINE_SZ,
+ " %016llx", wwpn);
+
+ /* Log a message if we are on the last WWPN
+ * or if we hit the max allowed per message.
+ */
+ wcnt++;
+ if (wcnt == LPFC_FPIN_WWPN_LINE_CNT || endit) {
+ buf[len] = 0;
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+ "4686 %s\n", buf);
+
+ /* Check if we reached the last WWPN */
+ if (endit)
+ return;
+
+ /* Limit the number of log message displayed per FPIN */
+ line++;
+ if (line == LPFC_FPIN_WWPN_NUM_LINE) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+ "4687 %d WWPNs Truncated\n",
+ cnt - i - 1);
+ return;
+ }
+
+ /* Start over with next log message */
+ wcnt = 0;
+ len = scnprintf(buf, LPFC_FPIN_WWPN_LINE_SZ,
+ "Additional WWPNs:");
+ }
+ }
+}
+
/**
* lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event.
- * @vport: Pointer to vport object.
+ * @phba: Pointer to phba object.
* @tlv: Pointer to the Link Integrity Notification Descriptor.
*
- * This function processes a link integrity FPIN event by
- * logging a message
+ * This function processes a Link Integrity FPIN event by logging a message.
**/
static void
-lpfc_els_rcv_fpin_li(struct lpfc_vport *vport, struct fc_tlv_desc *tlv)
+lpfc_els_rcv_fpin_li(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
{
struct fc_fn_li_desc *li = (struct fc_fn_li_desc *)tlv;
const char *li_evt_str;
- u32 li_evt;
+ u32 li_evt, cnt;
li_evt = be16_to_cpu(li->event_type);
li_evt_str = lpfc_get_fpin_li_event_nm(li_evt);
+ cnt = be32_to_cpu(li->pname_count);
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "4680 FPIN Link Integrity %s (x%x) "
- "Detecting PN x%016llx Attached PN x%016llx "
- "Duration %d mSecs Count %d Port Cnt %d\n",
- li_evt_str, li_evt,
- be64_to_cpu(li->detecting_wwpn),
- be64_to_cpu(li->attached_wwpn),
- be32_to_cpu(li->event_threshold),
- be32_to_cpu(li->event_count),
- be32_to_cpu(li->pname_count));
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+ "4680 FPIN Link Integrity %s (x%x) "
+ "Detecting PN x%016llx Attached PN x%016llx "
+ "Duration %d mSecs Count %d Port Cnt %d\n",
+ li_evt_str, li_evt,
+ be64_to_cpu(li->detecting_wwpn),
+ be64_to_cpu(li->attached_wwpn),
+ be32_to_cpu(li->event_threshold),
+ be32_to_cpu(li->event_count), cnt);
+
+ lpfc_display_fpin_wwpn(phba, (__be64 *)&li->pname_list, cnt);
+}
+
+/**
+ * lpfc_els_rcv_fpin_del - Process an FPIN Delivery Event.
+ * @phba: Pointer to hba object.
+ * @tlv: Pointer to the Delivery Notification Descriptor TLV
+ *
+ * This function processes a Delivery FPIN event by logging a message.
+ **/
+static void
+lpfc_els_rcv_fpin_del(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
+{
+ struct fc_fn_deli_desc *del = (struct fc_fn_deli_desc *)tlv;
+ const char *del_rsn_str;
+ u32 del_rsn;
+ __be32 *frame;
+
+ del_rsn = be16_to_cpu(del->deli_reason_code);
+ del_rsn_str = lpfc_get_fpin_deli_event_nm(del_rsn);
+
+ /* Skip over desc_tag/desc_len header to payload */
+ frame = (__be32 *)(del + 1);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+ "4681 FPIN Delivery %s (x%x) "
+ "Detecting PN x%016llx Attached PN x%016llx "
+ "DiscHdr0 x%08x "
+ "DiscHdr1 x%08x DiscHdr2 x%08x DiscHdr3 x%08x "
+ "DiscHdr4 x%08x DiscHdr5 x%08x\n",
+ del_rsn_str, del_rsn,
+ be64_to_cpu(del->detecting_wwpn),
+ be64_to_cpu(del->attached_wwpn),
+ be32_to_cpu(frame[0]),
+ be32_to_cpu(frame[1]),
+ be32_to_cpu(frame[2]),
+ be32_to_cpu(frame[3]),
+ be32_to_cpu(frame[4]),
+ be32_to_cpu(frame[5]));
}
+/**
+ * lpfc_els_rcv_fpin_peer_cgn - Process a FPIN Peer Congestion Event.
+ * @phba: Pointer to hba object.
+ * @tlv: Pointer to the Peer Congestion Notification Descriptor TLV
+ *
+ * This function processes a Peer Congestion FPIN event by logging a message.
+ **/
static void
-lpfc_els_rcv_fpin(struct lpfc_vport *vport, struct fc_els_fpin *fpin,
- u32 fpin_length)
+lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
{
- struct fc_tlv_desc *tlv;
+ struct fc_fn_peer_congn_desc *pc = (struct fc_fn_peer_congn_desc *)tlv;
+ const char *pc_evt_str;
+ u32 pc_evt, cnt;
+
+ pc_evt = be16_to_cpu(pc->event_type);
+ pc_evt_str = lpfc_get_fpin_congn_event_nm(pc_evt);
+ cnt = be32_to_cpu(pc->pname_count);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_ELS,
+ "4684 FPIN Peer Congestion %s (x%x) "
+ "Duration %d mSecs "
+ "Detecting PN x%016llx Attached PN x%016llx "
+ "Impacted Port Cnt %d\n",
+ pc_evt_str, pc_evt,
+ be32_to_cpu(pc->event_period),
+ be64_to_cpu(pc->detecting_wwpn),
+ be64_to_cpu(pc->attached_wwpn),
+ cnt);
+
+ lpfc_display_fpin_wwpn(phba, (__be64 *)&pc->pname_list, cnt);
+}
+
+/**
+ * lpfc_els_rcv_fpin_cgn - Process an FPIN Congestion notification
+ * @phba: Pointer to hba object.
+ * @tlv: Pointer to the Congestion Notification Descriptor TLV
+ *
+ * This function processes an FPIN Congestion Notifiction. The notification
+ * could be an Alarm or Warning. This routine feeds that data into driver's
+ * running congestion algorithm. It also processes the FPIN by
+ * logging a message. It returns 1 to indicate deliver this message
+ * to the upper layer or 0 to indicate don't deliver it.
+ **/
+static int
+lpfc_els_rcv_fpin_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
+{
+ struct lpfc_cgn_info *cp;
+ struct fc_fn_congn_desc *cgn = (struct fc_fn_congn_desc *)tlv;
+ const char *cgn_evt_str;
+ u32 cgn_evt;
+ const char *cgn_sev_str;
+ u32 cgn_sev;
+ uint16_t value;
+ u32 crc;
+ bool nm_log = false;
+ int rc = 1;
+
+ cgn_evt = be16_to_cpu(cgn->event_type);
+ cgn_evt_str = lpfc_get_fpin_congn_event_nm(cgn_evt);
+ cgn_sev = cgn->severity;
+ cgn_sev_str = lpfc_get_fpin_congn_severity_nm(cgn_sev);
+
+ /* The driver only takes action on a Credit Stall or Oversubscription
+ * event type to engage the IO algorithm. The driver prints an
+ * unmaskable message only for Lost Credit and Credit Stall.
+ * TODO: Still need to have definition of host action on clear,
+ * lost credit and device specific event types.
+ */
+ switch (cgn_evt) {
+ case FPIN_CONGN_LOST_CREDIT:
+ nm_log = true;
+ break;
+ case FPIN_CONGN_CREDIT_STALL:
+ nm_log = true;
+ fallthrough;
+ case FPIN_CONGN_OVERSUBSCRIPTION:
+ if (cgn_evt == FPIN_CONGN_OVERSUBSCRIPTION)
+ nm_log = false;
+ switch (cgn_sev) {
+ case FPIN_CONGN_SEVERITY_ERROR:
+ /* Take action here for an Alarm event */
+ if (phba->cmf_active_mode != LPFC_CFG_OFF) {
+ if (phba->cgn_reg_fpin & LPFC_CGN_FPIN_ALARM) {
+ /* Track of alarm cnt for cgn_info */
+ atomic_inc(&phba->cgn_fabric_alarm_cnt);
+ /* Track of alarm cnt for SYNC_WQE */
+ atomic_inc(&phba->cgn_sync_alarm_cnt);
+ }
+ goto cleanup;
+ }
+ break;
+ case FPIN_CONGN_SEVERITY_WARNING:
+ /* Take action here for a Warning event */
+ if (phba->cmf_active_mode != LPFC_CFG_OFF) {
+ if (phba->cgn_reg_fpin & LPFC_CGN_FPIN_WARN) {
+ /* Track of warning cnt for cgn_info */
+ atomic_inc(&phba->cgn_fabric_warn_cnt);
+ /* Track of warning cnt for SYNC_WQE */
+ atomic_inc(&phba->cgn_sync_warn_cnt);
+ }
+cleanup:
+ /* Save frequency in ms */
+ phba->cgn_fpin_frequency =
+ be32_to_cpu(cgn->event_period);
+ value = phba->cgn_fpin_frequency;
+ if (phba->cgn_i) {
+ cp = (struct lpfc_cgn_info *)
+ phba->cgn_i->virt;
+ if (phba->cgn_reg_fpin &
+ LPFC_CGN_FPIN_ALARM)
+ cp->cgn_alarm_freq =
+ cpu_to_le16(value);
+ if (phba->cgn_reg_fpin &
+ LPFC_CGN_FPIN_WARN)
+ cp->cgn_warn_freq =
+ cpu_to_le16(value);
+ crc = lpfc_cgn_calc_crc32
+ (cp,
+ LPFC_CGN_INFO_SZ,
+ LPFC_CGN_CRC32_SEED);
+ cp->cgn_info_crc = cpu_to_le32(crc);
+ }
+
+ /* Don't deliver to upper layer since
+ * driver took action on this tlv.
+ */
+ rc = 0;
+ }
+ break;
+ }
+ break;
+ }
+
+ /* Change the log level to unmaskable for the following event types. */
+ lpfc_printf_log(phba, (nm_log ? KERN_WARNING : KERN_INFO),
+ LOG_CGN_MGMT | LOG_ELS,
+ "4683 FPIN CONGESTION %s type %s (x%x) Event "
+ "Duration %d mSecs\n",
+ cgn_sev_str, cgn_evt_str, cgn_evt,
+ be32_to_cpu(cgn->event_period));
+ return rc;
+}
+
+void
+lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct fc_els_fpin *fpin = (struct fc_els_fpin *)p;
+ struct fc_tlv_desc *tlv, *first_tlv, *current_tlv;
const char *dtag_nm;
- uint32_t desc_cnt = 0, bytes_remain;
- u32 dtag;
+ int desc_cnt = 0, bytes_remain, cnt;
+ u32 dtag, deliver = 0;
+ int len;
/* FPINs handled only if we are in the right discovery state */
if (vport->port_state < LPFC_DISC_AUTH)
@@ -8721,35 +9651,92 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, struct fc_els_fpin *fpin,
if (fpin_length < sizeof(struct fc_els_fpin))
return;
+ /* Sanity check descriptor length. The desc_len value does not
+ * include space for the ELS command and the desc_len fields.
+ */
+ len = be32_to_cpu(fpin->desc_len);
+ if (fpin_length < len + sizeof(struct fc_els_fpin)) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "4671 Bad ELS FPIN length %d: %d\n",
+ len, fpin_length);
+ return;
+ }
+
tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0];
+ first_tlv = tlv;
bytes_remain = fpin_length - offsetof(struct fc_els_fpin, fpin_desc);
bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len));
- /* process each descriptor */
+ /* process each descriptor separately */
while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&
bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {
-
dtag = be32_to_cpu(tlv->desc_tag);
switch (dtag) {
case ELS_DTAG_LNK_INTEGRITY:
- lpfc_els_rcv_fpin_li(vport, tlv);
+ lpfc_els_rcv_fpin_li(phba, tlv);
+ deliver = 1;
+ break;
+ case ELS_DTAG_DELIVERY:
+ lpfc_els_rcv_fpin_del(phba, tlv);
+ deliver = 1;
+ break;
+ case ELS_DTAG_PEER_CONGEST:
+ lpfc_els_rcv_fpin_peer_cgn(phba, tlv);
+ deliver = 1;
+ break;
+ case ELS_DTAG_CONGESTION:
+ deliver = lpfc_els_rcv_fpin_cgn(phba, tlv);
break;
default:
dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
- "4678 skipped FPIN descriptor[%d]: "
- "tag x%x (%s)\n",
- desc_cnt, dtag, dtag_nm);
- break;
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "4678 unknown FPIN descriptor[%d]: "
+ "tag x%x (%s)\n",
+ desc_cnt, dtag, dtag_nm);
+
+ /* If descriptor is bad, drop the rest of the data */
+ return;
}
+ lpfc_cgn_update_stat(phba, dtag);
+ cnt = be32_to_cpu(tlv->desc_len);
- desc_cnt++;
+ /* Sanity check descriptor length. The desc_len value does not
+ * include space for the desc_tag and the desc_len fields.
+ */
+ len -= (cnt + sizeof(struct fc_tlv_desc));
+ if (len < 0) {
+ dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "4672 Bad FPIN descriptor TLV length "
+ "%d: %d %d %s\n",
+ cnt, len, fpin_length, dtag_nm);
+ return;
+ }
+
+ current_tlv = tlv;
bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);
tlv = fc_tlv_next_desc(tlv);
- }
- fc_host_fpin_rcv(lpfc_shost_from_vport(vport), fpin_length,
- (char *)fpin);
+ /* Format payload such that the FPIN delivered to the
+ * upper layer is a single descriptor FPIN.
+ */
+ if (desc_cnt)
+ memcpy(first_tlv, current_tlv,
+ (cnt + sizeof(struct fc_els_fpin)));
+
+ /* Adjust the length so that it only reflects a
+ * single descriptor FPIN.
+ */
+ fpin_length = cnt + sizeof(struct fc_els_fpin);
+ fpin->desc_len = cpu_to_be32(fpin_length);
+ fpin_length += sizeof(struct fc_els_fpin); /* the entire FPIN */
+
+ /* Send every descriptor individually to the upper layer */
+ if (deliver)
+ fc_host_fpin_rcv(lpfc_shost_from_vport(vport),
+ fpin_length, (char *)fpin);
+ desc_cnt++;
+ }
}
/**
@@ -8948,6 +9935,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
+ if (newnode)
+ lpfc_disc_state_machine(vport, ndlp, NULL,
+ NLP_EVT_DEVICE_RM);
break;
case ELS_CMD_PRLO:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -9137,6 +10127,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
/* There are no replies, so no rjt codes */
break;
+ case ELS_CMD_EDC:
+ lpfc_els_rcv_edc(vport, elsiocb, ndlp);
+ break;
case ELS_CMD_RDF:
phba->fc_stat.elsRcvRDF++;
/* Accept RDF only from fabric controller */
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 7cc5920979f8..7195ca0275f9 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -3331,6 +3331,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
case LPFC_LINK_SPEED_32GHZ:
case LPFC_LINK_SPEED_64GHZ:
case LPFC_LINK_SPEED_128GHZ:
+ case LPFC_LINK_SPEED_256GHZ:
break;
default:
phba->fc_linkspeed = LPFC_LINK_SPEED_UNKNOWN;
@@ -3646,6 +3647,10 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
phba->wait_4_mlo_maint_flg);
}
lpfc_mbx_process_link_up(phba, la);
+
+ if (phba->cmf_active_mode != LPFC_CFG_OFF)
+ lpfc_cmf_signal_init(phba);
+
} else if (attn_type == LPFC_ATT_LINK_DOWN ||
attn_type == LPFC_ATT_UNEXP_WWPN) {
phba->fc_stat.LinkDown++;
@@ -4208,6 +4213,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
struct lpfc_vport *vport = pmb->vport;
+ int rc;
pmb->ctx_buf = NULL;
pmb->ctx_ndlp = NULL;
@@ -4283,9 +4289,23 @@ out:
/* Issue SCR just before NameServer GID_FT Query */
lpfc_issue_els_scr(vport, 0);
- if (!phba->cfg_enable_mi ||
- phba->sli4_hba.pc_sli4_params.mi_ver < LPFC_MIB3_SUPPORT)
+ /* Link was bounced or a Fabric LOGO occurred. Start EDC
+ * with initial FW values provided the congestion mode is
+ * not off. Note that signals may or may not be supported
+ * by the adapter but FPIN is provided by default for 1
+ * or both missing signals support.
+ */
+ if (phba->cmf_active_mode != LPFC_CFG_OFF) {
+ phba->cgn_reg_fpin = phba->cgn_init_reg_fpin;
+ phba->cgn_reg_signal = phba->cgn_init_reg_signal;
+ rc = lpfc_issue_els_edc(vport, 0);
+ lpfc_printf_log(phba, KERN_INFO,
+ LOG_INIT | LOG_ELS | LOG_DISCOVERY,
+ "4220 EDC issue error x%x, Data: x%x\n",
+ rc, phba->cgn_init_reg_signal);
+ } else {
lpfc_issue_els_rdf(vport, 0);
+ }
}
vport->fc_ns_retry = 0;
@@ -4501,10 +4521,152 @@ lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count)
spin_unlock_irqrestore(shost->host_lock, iflags);
}
+/* Register a node with backend if not already done */
+void
+lpfc_nlp_reg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+{
+
+ unsigned long iflags;
+
+ spin_lock_irqsave(&ndlp->lock, iflags);
+ if (ndlp->fc4_xpt_flags & NLP_XPT_REGD) {
+ /* Already registered with backend, trigger rescan */
+ spin_unlock_irqrestore(&ndlp->lock, iflags);
+
+ if (ndlp->fc4_xpt_flags & NVME_XPT_REGD &&
+ ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_DISCOVERY)) {
+ lpfc_nvme_rescan_port(vport, ndlp);
+ }
+ return;
+ }
+
+ ndlp->fc4_xpt_flags |= NLP_XPT_REGD;
+ spin_unlock_irqrestore(&ndlp->lock, iflags);
+
+ if (lpfc_valid_xpt_node(ndlp)) {
+ vport->phba->nport_event_cnt++;
+ /*
+ * Tell the fc transport about the port, if we haven't
+ * already. If we have, and it's a scsi entity, be
+ */
+ lpfc_register_remote_port(vport, ndlp);
+ }
+
+ /* We are done if we do not have any NVME remote node */
+ if (!(ndlp->nlp_fc4_type & NLP_FC4_NVME))
+ return;
+
+ /* Notify the NVME transport of this new rport. */
+ if (vport->phba->sli_rev >= LPFC_SLI_REV4 &&
+ ndlp->nlp_fc4_type & NLP_FC4_NVME) {
+ if (vport->phba->nvmet_support == 0) {
+ /* Register this rport with the transport.
+ * Only NVME Target Rports are registered with
+ * the transport.
+ */
+ if (ndlp->nlp_type & NLP_NVME_TARGET) {
+ vport->phba->nport_event_cnt++;
+ lpfc_nvme_register_port(vport, ndlp);
+ }
+ } else {
+ /* Just take an NDLP ref count since the
+ * target does not register rports.
+ */
+ lpfc_nlp_get(ndlp);
+ }
+ }
+}
+
+/* Unregister a node with backend if not already done */
+void
+lpfc_nlp_unreg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+{
+ unsigned long iflags;
+
+ spin_lock_irqsave(&ndlp->lock, iflags);
+ if (!(ndlp->fc4_xpt_flags & NLP_XPT_REGD)) {
+ spin_unlock_irqrestore(&ndlp->lock, iflags);
+ return;
+ }
+
+ ndlp->fc4_xpt_flags &= ~NLP_XPT_REGD;
+ spin_unlock_irqrestore(&ndlp->lock, iflags);
+
+ if (ndlp->rport &&
+ ndlp->fc4_xpt_flags & SCSI_XPT_REGD) {
+ vport->phba->nport_event_cnt++;
+ lpfc_unregister_remote_port(ndlp);
+ }
+
+ if (ndlp->fc4_xpt_flags & NVME_XPT_REGD) {
+ vport->phba->nport_event_cnt++;
+ if (vport->phba->nvmet_support == 0) {
+ /* Start devloss if target. */
+ if (ndlp->nlp_type & NLP_NVME_TARGET)
+ lpfc_nvme_unregister_port(vport, ndlp);
+ } else {
+ /* NVMET has no upcall. */
+ lpfc_nlp_put(ndlp);
+ }
+ }
+
+}
+
+/*
+ * Adisc state change handling
+ */
+static void
+lpfc_handle_adisc_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ int new_state)
+{
+ switch (new_state) {
+ /*
+ * Any state to ADISC_ISSUE
+ * Do nothing, adisc cmpl handling will trigger state changes
+ */
+ case NLP_STE_ADISC_ISSUE:
+ break;
+
+ /*
+ * ADISC_ISSUE to mapped states
+ * Trigger a registration with backend, it will be nop if
+ * already registered
+ */
+ case NLP_STE_UNMAPPED_NODE:
+ ndlp->nlp_type |= NLP_FC_NODE;
+ fallthrough;
+ case NLP_STE_MAPPED_NODE:
+ ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
+ lpfc_nlp_reg_node(vport, ndlp);
+ break;
+
+ /*
+ * ADISC_ISSUE to non-mapped states
+ * We are moving from ADISC_ISSUE to a non-mapped state because
+ * ADISC failed, we would have skipped unregistering with
+ * backend, attempt it now
+ */
+ case NLP_STE_NPR_NODE:
+ ndlp->nlp_flag &= ~NLP_RCV_PLOGI;
+ fallthrough;
+ default:
+ lpfc_nlp_unreg_node(vport, ndlp);
+ break;
+ }
+
+}
+
static void
lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
int old_state, int new_state)
{
+ /* Trap ADISC changes here */
+ if (new_state == NLP_STE_ADISC_ISSUE ||
+ old_state == NLP_STE_ADISC_ISSUE) {
+ lpfc_handle_adisc_state(vport, ndlp, new_state);
+ return;
+ }
+
if (new_state == NLP_STE_UNMAPPED_NODE) {
ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
ndlp->nlp_type |= NLP_FC_NODE;
@@ -4514,60 +4676,17 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (new_state == NLP_STE_NPR_NODE)
ndlp->nlp_flag &= ~NLP_RCV_PLOGI;
- /* FCP and NVME Transport interface */
+ /* Reg/Unreg for FCP and NVME Transport interface */
if ((old_state == NLP_STE_MAPPED_NODE ||
old_state == NLP_STE_UNMAPPED_NODE)) {
- if (ndlp->rport &&
- lpfc_valid_xpt_node(ndlp)) {
- vport->phba->nport_event_cnt++;
- lpfc_unregister_remote_port(ndlp);
- }
-
- if (ndlp->nlp_fc4_type & NLP_FC4_NVME) {
- vport->phba->nport_event_cnt++;
- if (vport->phba->nvmet_support == 0) {
- /* Start devloss if target. */
- if (ndlp->nlp_type & NLP_NVME_TARGET)
- lpfc_nvme_unregister_port(vport, ndlp);
- } else {
- /* NVMET has no upcall. */
- lpfc_nlp_put(ndlp);
- }
- }
+ /* For nodes marked for ADISC, Handle unreg in ADISC cmpl */
+ if (!(ndlp->nlp_flag & NLP_NPR_ADISC))
+ lpfc_nlp_unreg_node(vport, ndlp);
}
- /* FCP and NVME Transport interfaces */
-
if (new_state == NLP_STE_MAPPED_NODE ||
- new_state == NLP_STE_UNMAPPED_NODE) {
- if (lpfc_valid_xpt_node(ndlp)) {
- vport->phba->nport_event_cnt++;
- /*
- * Tell the fc transport about the port, if we haven't
- * already. If we have, and it's a scsi entity, be
- */
- lpfc_register_remote_port(vport, ndlp);
- }
- /* Notify the NVME transport of this new rport. */
- if (vport->phba->sli_rev >= LPFC_SLI_REV4 &&
- ndlp->nlp_fc4_type & NLP_FC4_NVME) {
- if (vport->phba->nvmet_support == 0) {
- /* Register this rport with the transport.
- * Only NVME Target Rports are registered with
- * the transport.
- */
- if (ndlp->nlp_type & NLP_NVME_TARGET) {
- vport->phba->nport_event_cnt++;
- lpfc_nvme_register_port(vport, ndlp);
- }
- } else {
- /* Just take an NDLP ref count since the
- * target does not register rports.
- */
- lpfc_nlp_get(ndlp);
- }
- }
- }
+ new_state == NLP_STE_UNMAPPED_NODE)
+ lpfc_nlp_reg_node(vport, ndlp);
if ((new_state == NLP_STE_MAPPED_NODE) &&
(vport->stat_data_enabled)) {
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 4a5a85ed42ec..634f8fff7425 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -608,6 +608,7 @@ struct fc_vft_header {
#define ELS_CMD_LIRR 0x7A000000
#define ELS_CMD_LCB 0x81000000
#define ELS_CMD_FPIN 0x16000000
+#define ELS_CMD_EDC 0x17000000
#define ELS_CMD_QFPA 0xB0000000
#define ELS_CMD_UVEM 0xB1000000
#else /* __LITTLE_ENDIAN_BITFIELD */
@@ -652,6 +653,7 @@ struct fc_vft_header {
#define ELS_CMD_LIRR 0x7A
#define ELS_CMD_LCB 0x81
#define ELS_CMD_FPIN ELS_FPIN
+#define ELS_CMD_EDC ELS_EDC
#define ELS_CMD_QFPA 0xB0
#define ELS_CMD_UVEM 0xB1
#endif
@@ -1694,6 +1696,7 @@ struct lpfc_fdmi_reg_portattr {
#define PCI_DEVICE_ID_LANCER_FCOE_VF 0xe268
#define PCI_DEVICE_ID_LANCER_G6_FC 0xe300
#define PCI_DEVICE_ID_LANCER_G7_FC 0xf400
+#define PCI_DEVICE_ID_LANCER_G7P_FC 0xf500
#define PCI_DEVICE_ID_SAT_SMB 0xf011
#define PCI_DEVICE_ID_SAT_MID 0xf015
#define PCI_DEVICE_ID_RFLY 0xf095
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index eb8c735a243b..79a4872c2edb 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -20,6 +20,7 @@
* included with this package. *
*******************************************************************/
+#include <uapi/scsi/fc/fc_fs.h>
#include <uapi/scsi/fc/fc_els.h>
/* Macros to deal with bit fields. Each bit field must have 3 #defines
@@ -94,6 +95,9 @@ struct lpfc_sli_intf {
#define LPFC_SLI_INTF_FAMILY_BE3 0x1
#define LPFC_SLI_INTF_FAMILY_LNCR_A0 0xa
#define LPFC_SLI_INTF_FAMILY_LNCR_B0 0xb
+#define LPFC_SLI_INTF_FAMILY_G6 0xc
+#define LPFC_SLI_INTF_FAMILY_G7 0xd
+#define LPFC_SLI_INTF_FAMILY_G7P 0xe
#define lpfc_sli_intf_slirev_SHIFT 4
#define lpfc_sli_intf_slirev_MASK 0x0000000F
#define lpfc_sli_intf_slirev_WORD word0
@@ -393,6 +397,12 @@ struct lpfc_wcqe_complete {
#define lpfc_wcqe_c_ersp0_MASK 0x0000FFFF
#define lpfc_wcqe_c_ersp0_WORD word0
uint32_t total_data_placed;
+#define lpfc_wcqe_c_cmf_cg_SHIFT 31
+#define lpfc_wcqe_c_cmf_cg_MASK 0x00000001
+#define lpfc_wcqe_c_cmf_cg_WORD total_data_placed
+#define lpfc_wcqe_c_cmf_bw_SHIFT 0
+#define lpfc_wcqe_c_cmf_bw_MASK 0x0FFFFFFF
+#define lpfc_wcqe_c_cmf_bw_WORD total_data_placed
uint32_t parameter;
#define lpfc_wcqe_c_bg_edir_SHIFT 5
#define lpfc_wcqe_c_bg_edir_MASK 0x00000001
@@ -687,6 +697,7 @@ struct lpfc_register {
#define lpfc_sliport_eqdelay_id_MASK 0xfff
#define lpfc_sliport_eqdelay_id_WORD word0
#define LPFC_SEC_TO_USEC 1000000
+#define LPFC_SEC_TO_MSEC 1000
/* The following Registers apply to SLI4 if_type 0 UCNAs. They typically
* reside in BAR 2.
@@ -959,6 +970,12 @@ union lpfc_sli4_cfg_shdr {
#define lpfc_mbox_hdr_add_status_SHIFT 8
#define lpfc_mbox_hdr_add_status_MASK 0x000000FF
#define lpfc_mbox_hdr_add_status_WORD word7
+#define LPFC_ADD_STATUS_INCOMPAT_OBJ 0xA2
+#define lpfc_mbox_hdr_add_status_2_SHIFT 16
+#define lpfc_mbox_hdr_add_status_2_MASK 0x000000FF
+#define lpfc_mbox_hdr_add_status_2_WORD word7
+#define LPFC_ADD_STATUS_2_INCOMPAT_FLASH 0x01
+#define LPFC_ADD_STATUS_2_INCORRECT_ASIC 0x02
uint32_t response_length;
uint32_t actual_response_length;
} response;
@@ -1015,6 +1032,7 @@ struct mbox_header {
#define LPFC_MBOX_OPCODE_SET_HOST_DATA 0x5D
#define LPFC_MBOX_OPCODE_SEND_ACTIVATION 0x73
#define LPFC_MBOX_OPCODE_RESET_LICENSES 0x74
+#define LPFC_MBOX_OPCODE_REG_CONGESTION_BUF 0x8E
#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A
#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B
#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C
@@ -1123,6 +1141,12 @@ struct lpfc_mbx_sge {
uint32_t length;
};
+struct lpfc_mbx_host_buf {
+ uint32_t length;
+ uint32_t pa_lo;
+ uint32_t pa_hi;
+};
+
struct lpfc_mbx_nembed_cmd {
struct lpfc_sli4_cfg_mhdr cfg_mhdr;
#define LPFC_SLI4_MBX_SGE_MAX_PAGES 19
@@ -1133,6 +1157,31 @@ struct lpfc_mbx_nembed_sge_virt {
void *addr[LPFC_SLI4_MBX_SGE_MAX_PAGES];
};
+#define LPFC_MBX_OBJECT_NAME_LEN_DW 26
+struct lpfc_mbx_read_object { /* Version 0 */
+ struct mbox_header header;
+ union {
+ struct {
+ uint32_t word0;
+#define lpfc_mbx_rd_object_rlen_SHIFT 0
+#define lpfc_mbx_rd_object_rlen_MASK 0x00FFFFFF
+#define lpfc_mbx_rd_object_rlen_WORD word0
+ uint32_t rd_object_offset;
+ uint32_t rd_object_name[LPFC_MBX_OBJECT_NAME_LEN_DW];
+#define LPFC_OBJ_NAME_SZ 104 /* 26 x sizeof(uint32_t) is 104. */
+ uint32_t rd_object_cnt;
+ struct lpfc_mbx_host_buf rd_object_hbuf[4];
+ } request;
+ struct {
+ uint32_t rd_object_actual_rlen;
+ uint32_t word1;
+#define lpfc_mbx_rd_object_eof_SHIFT 31
+#define lpfc_mbx_rd_object_eof_MASK 0x1
+#define lpfc_mbx_rd_object_eof_WORD word1
+ } response;
+ } u;
+};
+
struct lpfc_mbx_eq_create {
struct mbox_header header;
union {
@@ -1555,7 +1604,7 @@ struct rq_context {
#define lpfc_rq_context_hdr_size_WORD word1
uint32_t word2;
#define lpfc_rq_context_cq_id_SHIFT 16
-#define lpfc_rq_context_cq_id_MASK 0x000003FF
+#define lpfc_rq_context_cq_id_MASK 0x0000FFFF
#define lpfc_rq_context_cq_id_WORD word2
#define lpfc_rq_context_buf_size_SHIFT 0
#define lpfc_rq_context_buf_size_MASK 0x0000FFFF
@@ -2328,6 +2377,7 @@ struct lpfc_mbx_redisc_fcf_tbl {
#define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67
#define ADD_STATUS_FW_NOT_SUPPORTED 0xEB
#define ADD_STATUS_INVALID_REQUEST 0x4B
+#define ADD_STATUS_INVALID_OBJECT_NAME 0xA0
#define ADD_STATUS_FW_DOWNLOAD_HW_DISABLED 0x58
struct lpfc_mbx_sli4_config {
@@ -2803,6 +2853,12 @@ struct lpfc_mbx_read_config {
#define lpfc_mbx_rd_conf_extnts_inuse_SHIFT 31
#define lpfc_mbx_rd_conf_extnts_inuse_MASK 0x00000001
#define lpfc_mbx_rd_conf_extnts_inuse_WORD word1
+#define lpfc_mbx_rd_conf_wcs_SHIFT 28 /* warning signaling */
+#define lpfc_mbx_rd_conf_wcs_MASK 0x00000001
+#define lpfc_mbx_rd_conf_wcs_WORD word1
+#define lpfc_mbx_rd_conf_acs_SHIFT 27 /* alarm signaling */
+#define lpfc_mbx_rd_conf_acs_MASK 0x00000001
+#define lpfc_mbx_rd_conf_acs_WORD word1
uint32_t word2;
#define lpfc_mbx_rd_conf_lnk_numb_SHIFT 0
#define lpfc_mbx_rd_conf_lnk_numb_MASK 0x0000003F
@@ -3328,17 +3384,20 @@ struct lpfc_sli4_parameters {
#define cfg_nosr_SHIFT 9
#define cfg_nosr_MASK 0x00000001
#define cfg_nosr_WORD word19
-
#define cfg_bv1s_SHIFT 10
#define cfg_bv1s_MASK 0x00000001
#define cfg_bv1s_WORD word19
-#define cfg_pvl_SHIFT 13
-#define cfg_pvl_MASK 0x00000001
-#define cfg_pvl_WORD word19
#define cfg_nsler_SHIFT 12
#define cfg_nsler_MASK 0x00000001
#define cfg_nsler_WORD word19
+#define cfg_pvl_SHIFT 13
+#define cfg_pvl_MASK 0x00000001
+#define cfg_pvl_WORD word19
+
+#define cfg_pbde_SHIFT 20
+#define cfg_pbde_MASK 0x00000001
+#define cfg_pbde_WORD word19
uint32_t word20;
#define cfg_max_tow_xri_SHIFT 0
@@ -3346,12 +3405,13 @@ struct lpfc_sli4_parameters {
#define cfg_max_tow_xri_WORD word20
uint32_t word21;
-#define cfg_mib_bde_cnt_SHIFT 16
-#define cfg_mib_bde_cnt_MASK 0x000000ff
-#define cfg_mib_bde_cnt_WORD word21
#define cfg_mi_ver_SHIFT 0
#define cfg_mi_ver_MASK 0x0000ffff
#define cfg_mi_ver_WORD word21
+#define cfg_cmf_SHIFT 24
+#define cfg_cmf_MASK 0x000000ff
+#define cfg_cmf_WORD word21
+
uint32_t mib_size;
uint32_t word23; /* RESERVED */
@@ -3380,7 +3440,10 @@ struct lpfc_sli4_parameters {
#define LPFC_SET_UE_RECOVERY 0x10
#define LPFC_SET_MDS_DIAGS 0x12
+#define LPFC_SET_CGN_SIGNAL 0x1f
#define LPFC_SET_DUAL_DUMP 0x1e
+#define LPFC_SET_ENABLE_MI 0x21
+#define LPFC_SET_ENABLE_CMF 0x24
struct lpfc_mbx_set_feature {
struct mbox_header header;
uint32_t feature;
@@ -3395,6 +3458,9 @@ struct lpfc_mbx_set_feature {
#define lpfc_mbx_set_feature_mds_deep_loopbk_SHIFT 1
#define lpfc_mbx_set_feature_mds_deep_loopbk_MASK 0x00000001
#define lpfc_mbx_set_feature_mds_deep_loopbk_WORD word6
+#define lpfc_mbx_set_feature_CGN_warn_freq_SHIFT 0
+#define lpfc_mbx_set_feature_CGN_warn_freq_MASK 0x0000ffff
+#define lpfc_mbx_set_feature_CGN_warn_freq_WORD word6
#define lpfc_mbx_set_feature_dd_SHIFT 0
#define lpfc_mbx_set_feature_dd_MASK 0x00000001
#define lpfc_mbx_set_feature_dd_WORD word6
@@ -3404,6 +3470,15 @@ struct lpfc_mbx_set_feature {
#define LPFC_DISABLE_DUAL_DUMP 0
#define LPFC_ENABLE_DUAL_DUMP 1
#define LPFC_QUERY_OP_DUAL_DUMP 2
+#define lpfc_mbx_set_feature_cmf_SHIFT 0
+#define lpfc_mbx_set_feature_cmf_MASK 0x00000001
+#define lpfc_mbx_set_feature_cmf_WORD word6
+#define lpfc_mbx_set_feature_mi_SHIFT 0
+#define lpfc_mbx_set_feature_mi_MASK 0x0000ffff
+#define lpfc_mbx_set_feature_mi_WORD word6
+#define lpfc_mbx_set_feature_milunq_SHIFT 16
+#define lpfc_mbx_set_feature_milunq_MASK 0x0000ffff
+#define lpfc_mbx_set_feature_milunq_WORD word6
uint32_t word7;
#define lpfc_mbx_set_feature_UERP_SHIFT 0
#define lpfc_mbx_set_feature_UERP_MASK 0x0000ffff
@@ -3411,16 +3486,51 @@ struct lpfc_mbx_set_feature {
#define lpfc_mbx_set_feature_UESR_SHIFT 16
#define lpfc_mbx_set_feature_UESR_MASK 0x0000ffff
#define lpfc_mbx_set_feature_UESR_WORD word7
+#define lpfc_mbx_set_feature_CGN_alarm_freq_SHIFT 0
+#define lpfc_mbx_set_feature_CGN_alarm_freq_MASK 0x0000ffff
+#define lpfc_mbx_set_feature_CGN_alarm_freq_WORD word7
+ u32 word8;
+#define lpfc_mbx_set_feature_CGN_acqe_freq_SHIFT 0
+#define lpfc_mbx_set_feature_CGN_acqe_freq_MASK 0x000000ff
+#define lpfc_mbx_set_feature_CGN_acqe_freq_WORD word8
};
#define LPFC_SET_HOST_OS_DRIVER_VERSION 0x2
+#define LPFC_SET_HOST_DATE_TIME 0x4
+
+struct lpfc_mbx_set_host_date_time {
+ uint32_t word6;
+#define lpfc_mbx_set_host_month_WORD word6
+#define lpfc_mbx_set_host_month_SHIFT 16
+#define lpfc_mbx_set_host_month_MASK 0xFF
+#define lpfc_mbx_set_host_day_WORD word6
+#define lpfc_mbx_set_host_day_SHIFT 8
+#define lpfc_mbx_set_host_day_MASK 0xFF
+#define lpfc_mbx_set_host_year_WORD word6
+#define lpfc_mbx_set_host_year_SHIFT 0
+#define lpfc_mbx_set_host_year_MASK 0xFF
+ uint32_t word7;
+#define lpfc_mbx_set_host_hour_WORD word7
+#define lpfc_mbx_set_host_hour_SHIFT 16
+#define lpfc_mbx_set_host_hour_MASK 0xFF
+#define lpfc_mbx_set_host_min_WORD word7
+#define lpfc_mbx_set_host_min_SHIFT 8
+#define lpfc_mbx_set_host_min_MASK 0xFF
+#define lpfc_mbx_set_host_sec_WORD word7
+#define lpfc_mbx_set_host_sec_SHIFT 0
+#define lpfc_mbx_set_host_sec_MASK 0xFF
+};
+
struct lpfc_mbx_set_host_data {
#define LPFC_HOST_OS_DRIVER_VERSION_SIZE 48
struct mbox_header header;
uint32_t param_id;
uint32_t param_len;
- uint8_t data[LPFC_HOST_OS_DRIVER_VERSION_SIZE];
+ union {
+ uint8_t data[LPFC_HOST_OS_DRIVER_VERSION_SIZE];
+ struct lpfc_mbx_set_host_date_time tm;
+ } un;
};
struct lpfc_mbx_set_trunk_mode {
@@ -3438,6 +3548,21 @@ struct lpfc_mbx_get_sli4_parameters {
struct lpfc_sli4_parameters sli4_parameters;
};
+struct lpfc_mbx_reg_congestion_buf {
+ struct mbox_header header;
+ uint32_t word0;
+#define lpfc_mbx_reg_cgn_buf_type_WORD word0
+#define lpfc_mbx_reg_cgn_buf_type_SHIFT 0
+#define lpfc_mbx_reg_cgn_buf_type_MASK 0xFF
+#define lpfc_mbx_reg_cgn_buf_cnt_WORD word0
+#define lpfc_mbx_reg_cgn_buf_cnt_SHIFT 16
+#define lpfc_mbx_reg_cgn_buf_cnt_MASK 0xFF
+ uint32_t word1;
+ uint32_t length;
+ uint32_t addr_lo;
+ uint32_t addr_hi;
+};
+
struct lpfc_rscr_desc_generic {
#define LPFC_RSRC_DESC_WSIZE 22
uint32_t desc[LPFC_RSRC_DESC_WSIZE];
@@ -3603,6 +3728,9 @@ struct lpfc_controller_attribute {
#define lpfc_cntl_attr_eprom_ver_hi_SHIFT 8
#define lpfc_cntl_attr_eprom_ver_hi_MASK 0x000000ff
#define lpfc_cntl_attr_eprom_ver_hi_WORD word17
+#define lpfc_cntl_attr_flash_id_SHIFT 16
+#define lpfc_cntl_attr_flash_id_MASK 0x000000ff
+#define lpfc_cntl_attr_flash_id_WORD word17
uint32_t mbx_da_struct_ver;
uint32_t ep_fw_da_struct_ver;
uint32_t ncsi_ver_str[3];
@@ -3744,6 +3872,7 @@ struct lpfc_mbx_get_port_name {
#define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4
#define MB_CQE_STATUS_DMA_FAILED 0x5
+
#define LPFC_MBX_WR_CONFIG_MAX_BDE 1
struct lpfc_mbx_wr_object {
struct mbox_header header;
@@ -3760,7 +3889,7 @@ struct lpfc_mbx_wr_object {
#define lpfc_wr_object_write_length_MASK 0x00FFFFFF
#define lpfc_wr_object_write_length_WORD word4
uint32_t write_offset;
- uint32_t object_name[26];
+ uint32_t object_name[LPFC_MBX_OBJECT_NAME_LEN_DW];
uint32_t bde_count;
struct ulp_bde64 bde[LPFC_MBX_WR_CONFIG_MAX_BDE];
} request;
@@ -3809,6 +3938,7 @@ struct lpfc_mqe {
struct lpfc_mbx_unreg_fcfi unreg_fcfi;
struct lpfc_mbx_mq_create mq_create;
struct lpfc_mbx_mq_create_ext mq_create_ext;
+ struct lpfc_mbx_read_object read_object;
struct lpfc_mbx_eq_create eq_create;
struct lpfc_mbx_modify_eq_delay eq_delay;
struct lpfc_mbx_cq_create cq_create;
@@ -3834,6 +3964,7 @@ struct lpfc_mqe {
struct lpfc_mbx_query_fw_config query_fw_cfg;
struct lpfc_mbx_set_beacon_config beacon_config;
struct lpfc_mbx_get_sli4_parameters get_sli4_parameters;
+ struct lpfc_mbx_reg_congestion_buf reg_congestion_buf;
struct lpfc_mbx_set_link_diag_state link_diag_state;
struct lpfc_mbx_set_link_diag_loopback link_diag_loopback;
struct lpfc_mbx_run_link_diag_test link_diag_test;
@@ -3888,6 +4019,7 @@ struct lpfc_mcqe {
#define LPFC_TRAILER_CODE_GRP5 0x5
#define LPFC_TRAILER_CODE_FC 0x10
#define LPFC_TRAILER_CODE_SLI 0x11
+#define LPFC_TRAILER_CODE_CMSTAT 0x13
};
struct lpfc_acqe_link {
@@ -4122,6 +4254,19 @@ struct lpfc_acqe_misconfigured_event {
#define LPFC_SLI_EVENT_STATUS_UNCERTIFIED 0x05
};
+struct lpfc_acqe_cgn_signal {
+ u32 word0;
+#define lpfc_warn_acqe_SHIFT 0
+#define lpfc_warn_acqe_MASK 0x7FFFFFFF
+#define lpfc_warn_acqe_WORD word0
+#define lpfc_imm_acqe_SHIFT 31
+#define lpfc_imm_acqe_MASK 0x1
+#define lpfc_imm_acqe_WORD word0
+ u32 alarm_cnt;
+ u32 word2;
+ u32 trailer;
+};
+
struct lpfc_acqe_sli {
uint32_t event_data1;
uint32_t event_data2;
@@ -4134,8 +4279,10 @@ struct lpfc_acqe_sli {
#define LPFC_SLI_EVENT_TYPE_DIAG_DUMP 0x5
#define LPFC_SLI_EVENT_TYPE_MISCONFIGURED 0x9
#define LPFC_SLI_EVENT_TYPE_REMOTE_DPORT 0xA
+#define LPFC_SLI_EVENT_TYPE_PORT_PARAMS_CHG 0xE
#define LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN 0xF
#define LPFC_SLI_EVENT_TYPE_EEPROM_FAILURE 0x10
+#define LPFC_SLI_EVENT_TYPE_CGN_SIGNAL 0x11
};
/*
@@ -4543,6 +4690,69 @@ struct create_xri_wqe {
#define T_REQUEST_TAG 3
#define T_XRI_TAG 1
+struct cmf_sync_wqe {
+ uint32_t rsrvd[3];
+ uint32_t word3;
+#define cmf_sync_interval_SHIFT 0
+#define cmf_sync_interval_MASK 0x00000ffff
+#define cmf_sync_interval_WORD word3
+#define cmf_sync_afpin_SHIFT 16
+#define cmf_sync_afpin_MASK 0x000000001
+#define cmf_sync_afpin_WORD word3
+#define cmf_sync_asig_SHIFT 17
+#define cmf_sync_asig_MASK 0x000000001
+#define cmf_sync_asig_WORD word3
+#define cmf_sync_op_SHIFT 20
+#define cmf_sync_op_MASK 0x00000000f
+#define cmf_sync_op_WORD word3
+#define cmf_sync_ver_SHIFT 24
+#define cmf_sync_ver_MASK 0x0000000ff
+#define cmf_sync_ver_WORD word3
+#define LPFC_CMF_SYNC_VER 1
+ uint32_t event_tag;
+ uint32_t word5;
+#define cmf_sync_wsigmax_SHIFT 0
+#define cmf_sync_wsigmax_MASK 0x00000ffff
+#define cmf_sync_wsigmax_WORD word5
+#define cmf_sync_wsigcnt_SHIFT 16
+#define cmf_sync_wsigcnt_MASK 0x00000ffff
+#define cmf_sync_wsigcnt_WORD word5
+ uint32_t word6;
+ uint32_t word7;
+#define cmf_sync_cmnd_SHIFT 8
+#define cmf_sync_cmnd_MASK 0x0000000ff
+#define cmf_sync_cmnd_WORD word7
+ uint32_t word8;
+ uint32_t word9;
+#define cmf_sync_reqtag_SHIFT 0
+#define cmf_sync_reqtag_MASK 0x00000ffff
+#define cmf_sync_reqtag_WORD word9
+#define cmf_sync_wfpinmax_SHIFT 16
+#define cmf_sync_wfpinmax_MASK 0x0000000ff
+#define cmf_sync_wfpinmax_WORD word9
+#define cmf_sync_wfpincnt_SHIFT 24
+#define cmf_sync_wfpincnt_MASK 0x0000000ff
+#define cmf_sync_wfpincnt_WORD word9
+ uint32_t word10;
+#define cmf_sync_qosd_SHIFT 9
+#define cmf_sync_qosd_MASK 0x00000001
+#define cmf_sync_qosd_WORD word10
+ uint32_t word11;
+#define cmf_sync_cmd_type_SHIFT 0
+#define cmf_sync_cmd_type_MASK 0x0000000f
+#define cmf_sync_cmd_type_WORD word11
+#define cmf_sync_wqec_SHIFT 7
+#define cmf_sync_wqec_MASK 0x00000001
+#define cmf_sync_wqec_WORD word11
+#define cmf_sync_cqid_SHIFT 16
+#define cmf_sync_cqid_MASK 0x0000ffff
+#define cmf_sync_cqid_WORD word11
+ uint32_t read_bytes;
+ uint32_t word13;
+ uint32_t word14;
+ uint32_t word15;
+};
+
struct abort_cmd_wqe {
uint32_t rsrvd[3];
uint32_t word3;
@@ -4672,6 +4882,7 @@ union lpfc_wqe {
struct fcp_iread64_wqe fcp_iread;
struct fcp_iwrite64_wqe fcp_iwrite;
struct abort_cmd_wqe abort_cmd;
+ struct cmf_sync_wqe cmf_sync;
struct create_xri_wqe create_xri;
struct xmit_bcast64_wqe xmit_bcast64;
struct xmit_seq64_wqe xmit_sequence;
@@ -4692,6 +4903,7 @@ union lpfc_wqe128 {
struct fcp_iread64_wqe fcp_iread;
struct fcp_iwrite64_wqe fcp_iwrite;
struct abort_cmd_wqe abort_cmd;
+ struct cmf_sync_wqe cmf_sync;
struct create_xri_wqe create_xri;
struct xmit_bcast64_wqe xmit_bcast64;
struct xmit_seq64_wqe xmit_sequence;
@@ -4707,6 +4919,7 @@ union lpfc_wqe128 {
#define MAGIC_NUMBER_G6 0xFEAA0003
#define MAGIC_NUMBER_G7 0xFEAA0005
+#define MAGIC_NUMBER_G7P 0xFEAA0020
struct lpfc_grp_hdr {
uint32_t size;
@@ -4734,6 +4947,7 @@ struct lpfc_grp_hdr {
#define FCP_COMMAND_TRSP 0x3
#define FCP_COMMAND_TSEND 0x7
#define OTHER_COMMAND 0x8
+#define CMF_SYNC_COMMAND 0xA
#define ELS_COMMAND_NON_FIP 0xC
#define ELS_COMMAND_FIP 0xD
@@ -4755,6 +4969,7 @@ struct lpfc_grp_hdr {
#define CMD_FCP_TRECEIVE64_WQE 0xA1
#define CMD_FCP_TRSP64_WQE 0xA3
#define CMD_GEN_REQUEST64_WQE 0xC2
+#define CMD_CMF_SYNC_WQE 0xE8
#define CMD_WQE_MASK 0xff
@@ -4762,3 +4977,43 @@ struct lpfc_grp_hdr {
#define LPFC_FW_DUMP 1
#define LPFC_FW_RESET 2
#define LPFC_DV_RESET 3
+
+/* On some kernels, enum fc_ls_tlv_dtag does not have
+ * these 2 enums defined, on other kernels it does.
+ * To get aound this we need to add these 2 defines here.
+ */
+#ifndef ELS_DTAG_LNK_FAULT_CAP
+#define ELS_DTAG_LNK_FAULT_CAP 0x0001000D
+#endif
+#ifndef ELS_DTAG_CG_SIGNAL_CAP
+#define ELS_DTAG_CG_SIGNAL_CAP 0x0001000F
+#endif
+
+/*
+ * Initializer useful for decoding FPIN string table.
+ */
+#define FC_FPIN_CONGN_SEVERITY_INIT { \
+ { FPIN_CONGN_SEVERITY_WARNING, "Warning" }, \
+ { FPIN_CONGN_SEVERITY_ERROR, "Alarm" }, \
+}
+
+/* EDC supports two descriptors. When allocated, it is the
+ * size of this structure plus each supported descriptor.
+ */
+struct lpfc_els_edc_req {
+ struct fc_els_edc edc; /* hdr up to descriptors */
+ struct fc_diag_cg_sig_desc cgn_desc; /* 1st descriptor */
+};
+
+/* Minimum structure defines for the EDC response.
+ * Balance is in buffer.
+ */
+struct lpfc_els_edc_rsp {
+ struct fc_els_edc_resp edc_rsp; /* hdr up to descriptors */
+ struct fc_diag_cg_sig_desc cgn_desc; /* 1st descriptor */
+};
+
+/* Used for logging FPIN messages */
+#define LPFC_FPIN_WWPN_LINE_SZ 128
+#define LPFC_FPIN_WWPN_LINE_CNT 6
+#define LPFC_FPIN_WWPN_NUM_LINE 6
diff --git a/drivers/scsi/lpfc/lpfc_ids.h b/drivers/scsi/lpfc/lpfc_ids.h
index d48414e295a0..6a90e6e53d09 100644
--- a/drivers/scsi/lpfc/lpfc_ids.h
+++ b/drivers/scsi/lpfc/lpfc_ids.h
@@ -1,7 +1,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 *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -118,6 +118,8 @@ const struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G7_FC,
PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G7P_FC,
+ PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index e29523a1b530..0ec322f0e3cb 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -93,6 +93,7 @@ static uint32_t lpfc_sli4_enable_intr(struct lpfc_hba *, uint32_t);
static void lpfc_sli4_oas_verify(struct lpfc_hba *phba);
static uint16_t lpfc_find_cpu_handle(struct lpfc_hba *, uint16_t, int);
static void lpfc_setup_bg(struct lpfc_hba *, struct Scsi_Host *);
+static int lpfc_sli4_cgn_parm_chg_evt(struct lpfc_hba *);
static struct scsi_transport_template *lpfc_transport_template = NULL;
static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
@@ -1243,7 +1244,8 @@ lpfc_idle_stat_delay_work(struct work_struct *work)
return;
if (phba->link_state == LPFC_HBA_ERROR ||
- phba->pport->fc_flag & FC_OFFLINE_MODE)
+ phba->pport->fc_flag & FC_OFFLINE_MODE ||
+ phba->cmf_active_mode != LPFC_CFG_OFF)
goto requeue;
for_each_present_cpu(i) {
@@ -1852,6 +1854,7 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
{
int rc;
uint32_t intr_mode;
+ LPFC_MBOXQ_t *mboxq;
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
LPFC_SLI_INTF_IF_TYPE_2) {
@@ -1871,11 +1874,19 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
"Recovery...\n");
/* If we are no wait, the HBA has been reset and is not
- * functional, thus we should clear LPFC_SLI_ACTIVE flag.
+ * functional, thus we should clear
+ * (LPFC_SLI_ACTIVE | LPFC_SLI_MBOX_ACTIVE) flags.
*/
if (mbx_action == LPFC_MBX_NO_WAIT) {
spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag &= ~LPFC_SLI_ACTIVE;
+ if (phba->sli.mbox_active) {
+ mboxq = phba->sli.mbox_active;
+ mboxq->u.mb.mbxStatus = MBX_NOT_FINISHED;
+ __lpfc_mbox_cmpl_put(phba, mboxq);
+ phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ phba->sli.mbox_active = NULL;
+ }
spin_unlock_irq(&phba->hbalock);
}
@@ -2590,6 +2601,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
case PCI_DEVICE_ID_LANCER_G7_FC:
m = (typeof(m)){"LPe36000", "PCIe", "Fibre Channel Adapter"};
break;
+ case PCI_DEVICE_ID_LANCER_G7P_FC:
+ m = (typeof(m)){"LPe38000", "PCIe", "Fibre Channel Adapter"};
+ break;
case PCI_DEVICE_ID_SKYHAWK:
case PCI_DEVICE_ID_SKYHAWK_VF:
oneConnect = 1;
@@ -3008,6 +3022,123 @@ lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *phba)
}
/**
+ * lpfc_cmf_stop - Stop CMF processing
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This is called when the link goes down or if CMF mode is turned OFF.
+ * It is also called when going offline or unloaded just before the
+ * congestion info buffer is unregistered.
+ **/
+void
+lpfc_cmf_stop(struct lpfc_hba *phba)
+{
+ int cpu;
+ struct lpfc_cgn_stat *cgs;
+
+ /* We only do something if CMF is enabled */
+ if (!phba->sli4_hba.pc_sli4_params.cmf)
+ return;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6221 Stop CMF / Cancel Timer\n");
+
+ /* Cancel the CMF timer */
+ hrtimer_cancel(&phba->cmf_timer);
+
+ /* Zero CMF counters */
+ atomic_set(&phba->cmf_busy, 0);
+ for_each_present_cpu(cpu) {
+ cgs = per_cpu_ptr(phba->cmf_stat, cpu);
+ atomic64_set(&cgs->total_bytes, 0);
+ atomic64_set(&cgs->rcv_bytes, 0);
+ atomic_set(&cgs->rx_io_cnt, 0);
+ atomic64_set(&cgs->rx_latency, 0);
+ }
+ atomic_set(&phba->cmf_bw_wait, 0);
+
+ /* Resume any blocked IO - Queue unblock on workqueue */
+ queue_work(phba->wq, &phba->unblock_request_work);
+}
+
+static inline uint64_t
+lpfc_get_max_line_rate(struct lpfc_hba *phba)
+{
+ uint64_t rate = lpfc_sli_port_speed_get(phba);
+
+ return ((((unsigned long)rate) * 1024 * 1024) / 10);
+}
+
+void
+lpfc_cmf_signal_init(struct lpfc_hba *phba)
+{
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6223 Signal CMF init\n");
+
+ /* Use the new fc_linkspeed to recalculate */
+ phba->cmf_interval_rate = LPFC_CMF_INTERVAL;
+ phba->cmf_max_line_rate = lpfc_get_max_line_rate(phba);
+ phba->cmf_link_byte_count = div_u64(phba->cmf_max_line_rate *
+ phba->cmf_interval_rate, 1000);
+ phba->cmf_max_bytes_per_interval = phba->cmf_link_byte_count;
+
+ /* This is a signal to firmware to sync up CMF BW with link speed */
+ lpfc_issue_cmf_sync_wqe(phba, 0, 0);
+}
+
+/**
+ * lpfc_cmf_start - Start CMF processing
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This is called when the link comes up or if CMF mode is turned OFF
+ * to Monitor or Managed.
+ **/
+void
+lpfc_cmf_start(struct lpfc_hba *phba)
+{
+ struct lpfc_cgn_stat *cgs;
+ int cpu;
+
+ /* We only do something if CMF is enabled */
+ if (!phba->sli4_hba.pc_sli4_params.cmf ||
+ phba->cmf_active_mode == LPFC_CFG_OFF)
+ return;
+
+ /* Reinitialize congestion buffer info */
+ lpfc_init_congestion_buf(phba);
+
+ atomic_set(&phba->cgn_fabric_warn_cnt, 0);
+ atomic_set(&phba->cgn_fabric_alarm_cnt, 0);
+ atomic_set(&phba->cgn_sync_alarm_cnt, 0);
+ atomic_set(&phba->cgn_sync_warn_cnt, 0);
+
+ atomic_set(&phba->cmf_busy, 0);
+ for_each_present_cpu(cpu) {
+ cgs = per_cpu_ptr(phba->cmf_stat, cpu);
+ atomic64_set(&cgs->total_bytes, 0);
+ atomic64_set(&cgs->rcv_bytes, 0);
+ atomic_set(&cgs->rx_io_cnt, 0);
+ atomic64_set(&cgs->rx_latency, 0);
+ }
+ phba->cmf_latency.tv_sec = 0;
+ phba->cmf_latency.tv_nsec = 0;
+
+ lpfc_cmf_signal_init(phba);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6222 Start CMF / Timer\n");
+
+ phba->cmf_timer_cnt = 0;
+ hrtimer_start(&phba->cmf_timer,
+ ktime_set(0, LPFC_CMF_INTERVAL * 1000000),
+ HRTIMER_MODE_REL);
+ /* Setup for latency check in IO cmpl routines */
+ ktime_get_real_ts64(&phba->cmf_latency);
+
+ atomic_set(&phba->cmf_bw_wait, 0);
+ atomic_set(&phba->cmf_stop_io, 0);
+}
+
+/**
* lpfc_stop_hba_timers - Stop all the timers associated with an HBA
* @phba: pointer to lpfc hba data structure.
*
@@ -3541,6 +3672,8 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
spin_lock_irq(&ndlp->lock);
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
spin_unlock_irq(&ndlp->lock);
+
+ lpfc_unreg_rpi(vports[i], ndlp);
/*
* Whenever an SLI4 port goes offline, free the
* RPI. Get a new RPI when the adapter port
@@ -3556,7 +3689,6 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
}
- lpfc_unreg_rpi(vports[i], ndlp);
if (ndlp->nlp_type & NLP_FABRIC) {
lpfc_disc_state_machine(vports[i], ndlp,
@@ -4666,6 +4798,8 @@ static void lpfc_host_supported_speeds_set(struct Scsi_Host *shost)
if (phba->hba_flag & HBA_FCOE_MODE)
return;
+ if (phba->lmt & LMT_256Gb)
+ fc_host_supported_speeds(shost) |= FC_PORTSPEED_256GBIT;
if (phba->lmt & LMT_128Gb)
fc_host_supported_speeds(shost) |= FC_PORTSPEED_128GBIT;
if (phba->lmt & LMT_64Gb)
@@ -4845,7 +4979,7 @@ lpfc_sli4_fcf_redisc_wait_tmo(struct timer_list *t)
/**
* lpfc_vmid_poll - VMID timeout detection
- * @ptr: Map to lpfc_hba data structure pointer.
+ * @t: Timer context used to obtain the pointer to lpfc hba data structure.
*
* This routine is invoked when there is no I/O on by a VM for the specified
* amount of time. When this situation is detected, the VMID has to be
@@ -5074,6 +5208,9 @@ lpfc_sli4_port_speed_parse(struct lpfc_hba *phba, uint32_t evt_code,
case LPFC_FC_LA_SPEED_128G:
port_speed = 128000;
break;
+ case LPFC_FC_LA_SPEED_256G:
+ port_speed = 256000;
+ break;
default:
port_speed = 0;
}
@@ -5267,6 +5404,645 @@ lpfc_async_link_speed_to_read_top(struct lpfc_hba *phba, uint8_t speed_code)
return port_speed;
}
+void
+lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba)
+{
+ struct rxtable_entry *entry;
+ int cnt = 0, head, tail, last, start;
+
+ head = atomic_read(&phba->rxtable_idx_head);
+ tail = atomic_read(&phba->rxtable_idx_tail);
+ if (!phba->rxtable || head == tail) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
+ "4411 Rxtable is empty\n");
+ return;
+ }
+ last = tail;
+ start = head;
+
+ /* Display the last LPFC_MAX_RXMONITOR_DUMP entries from the rxtable */
+ while (start != last) {
+ if (start)
+ start--;
+ else
+ start = LPFC_MAX_RXMONITOR_ENTRY - 1;
+ entry = &phba->rxtable[start];
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "4410 %02d: MBPI %lld Xmit %lld Cmpl %lld "
+ "Lat %lld ASz %lld Info %02d BWUtil %d "
+ "Int %d slot %d\n",
+ cnt, entry->max_bytes_per_interval,
+ entry->total_bytes, entry->rcv_bytes,
+ entry->avg_io_latency, entry->avg_io_size,
+ entry->cmf_info, entry->timer_utilization,
+ entry->timer_interval, start);
+ cnt++;
+ if (cnt >= LPFC_MAX_RXMONITOR_DUMP)
+ return;
+ }
+}
+
+/**
+ * lpfc_cgn_update_stat - Save data into congestion stats buffer
+ * @phba: pointer to lpfc hba data structure.
+ * @dtag: FPIN descriptor received
+ *
+ * Increment the FPIN received counter/time when it happens.
+ */
+void
+lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag)
+{
+ struct lpfc_cgn_info *cp;
+ struct tm broken;
+ struct timespec64 cur_time;
+ u32 cnt;
+ u16 value;
+
+ /* Make sure we have a congestion info buffer */
+ if (!phba->cgn_i)
+ return;
+ cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
+ ktime_get_real_ts64(&cur_time);
+ time64_to_tm(cur_time.tv_sec, 0, &broken);
+
+ /* Update congestion statistics */
+ switch (dtag) {
+ case ELS_DTAG_LNK_INTEGRITY:
+ cnt = le32_to_cpu(cp->link_integ_notification);
+ cnt++;
+ cp->link_integ_notification = cpu_to_le32(cnt);
+
+ cp->cgn_stat_lnk_month = broken.tm_mon + 1;
+ cp->cgn_stat_lnk_day = broken.tm_mday;
+ cp->cgn_stat_lnk_year = broken.tm_year - 100;
+ cp->cgn_stat_lnk_hour = broken.tm_hour;
+ cp->cgn_stat_lnk_min = broken.tm_min;
+ cp->cgn_stat_lnk_sec = broken.tm_sec;
+ break;
+ case ELS_DTAG_DELIVERY:
+ cnt = le32_to_cpu(cp->delivery_notification);
+ cnt++;
+ cp->delivery_notification = cpu_to_le32(cnt);
+
+ cp->cgn_stat_del_month = broken.tm_mon + 1;
+ cp->cgn_stat_del_day = broken.tm_mday;
+ cp->cgn_stat_del_year = broken.tm_year - 100;
+ cp->cgn_stat_del_hour = broken.tm_hour;
+ cp->cgn_stat_del_min = broken.tm_min;
+ cp->cgn_stat_del_sec = broken.tm_sec;
+ break;
+ case ELS_DTAG_PEER_CONGEST:
+ cnt = le32_to_cpu(cp->cgn_peer_notification);
+ cnt++;
+ cp->cgn_peer_notification = cpu_to_le32(cnt);
+
+ cp->cgn_stat_peer_month = broken.tm_mon + 1;
+ cp->cgn_stat_peer_day = broken.tm_mday;
+ cp->cgn_stat_peer_year = broken.tm_year - 100;
+ cp->cgn_stat_peer_hour = broken.tm_hour;
+ cp->cgn_stat_peer_min = broken.tm_min;
+ cp->cgn_stat_peer_sec = broken.tm_sec;
+ break;
+ case ELS_DTAG_CONGESTION:
+ cnt = le32_to_cpu(cp->cgn_notification);
+ cnt++;
+ cp->cgn_notification = cpu_to_le32(cnt);
+
+ cp->cgn_stat_cgn_month = broken.tm_mon + 1;
+ cp->cgn_stat_cgn_day = broken.tm_mday;
+ cp->cgn_stat_cgn_year = broken.tm_year - 100;
+ cp->cgn_stat_cgn_hour = broken.tm_hour;
+ cp->cgn_stat_cgn_min = broken.tm_min;
+ cp->cgn_stat_cgn_sec = broken.tm_sec;
+ }
+ if (phba->cgn_fpin_frequency &&
+ phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) {
+ value = LPFC_CGN_TIMER_TO_MIN / phba->cgn_fpin_frequency;
+ cp->cgn_stat_npm = cpu_to_le32(value);
+ }
+ value = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ,
+ LPFC_CGN_CRC32_SEED);
+ cp->cgn_info_crc = cpu_to_le32(value);
+}
+
+/**
+ * lpfc_cgn_save_evt_cnt - Save data into registered congestion buffer
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * Save the congestion event data every minute.
+ * On the hour collapse all the minute data into hour data. Every day
+ * collapse all the hour data into daily data. Separate driver
+ * and fabrc congestion event counters that will be saved out
+ * to the registered congestion buffer every minute.
+ */
+static void
+lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba)
+{
+ struct lpfc_cgn_info *cp;
+ struct tm broken;
+ struct timespec64 cur_time;
+ uint32_t i, index;
+ uint16_t value, mvalue;
+ uint64_t bps;
+ uint32_t mbps;
+ uint32_t dvalue, wvalue, lvalue, avalue;
+ uint64_t latsum;
+ uint16_t *ptr;
+ uint32_t *lptr;
+ uint16_t *mptr;
+
+ /* Make sure we have a congestion info buffer */
+ if (!phba->cgn_i)
+ return;
+ cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
+
+ if (time_before(jiffies, phba->cgn_evt_timestamp))
+ return;
+ phba->cgn_evt_timestamp = jiffies +
+ msecs_to_jiffies(LPFC_CGN_TIMER_TO_MIN);
+ phba->cgn_evt_minute++;
+
+ /* We should get to this point in the routine on 1 minute intervals */
+
+ ktime_get_real_ts64(&cur_time);
+ time64_to_tm(cur_time.tv_sec, 0, &broken);
+
+ if (phba->cgn_fpin_frequency &&
+ phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) {
+ value = LPFC_CGN_TIMER_TO_MIN / phba->cgn_fpin_frequency;
+ cp->cgn_stat_npm = cpu_to_le32(value);
+ }
+
+ /* Read and clear the latency counters for this minute */
+ lvalue = atomic_read(&phba->cgn_latency_evt_cnt);
+ latsum = atomic64_read(&phba->cgn_latency_evt);
+ atomic_set(&phba->cgn_latency_evt_cnt, 0);
+ atomic64_set(&phba->cgn_latency_evt, 0);
+
+ /* We need to store MB/sec bandwidth in the congestion information.
+ * block_cnt is count of 512 byte blocks for the entire minute,
+ * bps will get bytes per sec before finally converting to MB/sec.
+ */
+ bps = div_u64(phba->rx_block_cnt, LPFC_SEC_MIN) * 512;
+ phba->rx_block_cnt = 0;
+ mvalue = bps / (1024 * 1024); /* convert to MB/sec */
+
+ /* Every minute */
+ /* cgn parameters */
+ cp->cgn_info_mode = phba->cgn_p.cgn_param_mode;
+ cp->cgn_info_level0 = phba->cgn_p.cgn_param_level0;
+ cp->cgn_info_level1 = phba->cgn_p.cgn_param_level1;
+ cp->cgn_info_level2 = phba->cgn_p.cgn_param_level2;
+
+ /* Fill in default LUN qdepth */
+ value = (uint16_t)(phba->pport->cfg_lun_queue_depth);
+ cp->cgn_lunq = cpu_to_le16(value);
+
+ /* Record congestion buffer info - every minute
+ * cgn_driver_evt_cnt (Driver events)
+ * cgn_fabric_warn_cnt (Congestion Warnings)
+ * cgn_latency_evt_cnt / cgn_latency_evt (IO Latency)
+ * cgn_fabric_alarm_cnt (Congestion Alarms)
+ */
+ index = ++cp->cgn_index_minute;
+ if (cp->cgn_index_minute == LPFC_MIN_HOUR) {
+ cp->cgn_index_minute = 0;
+ index = 0;
+ }
+
+ /* Get the number of driver events in this sample and reset counter */
+ dvalue = atomic_read(&phba->cgn_driver_evt_cnt);
+ atomic_set(&phba->cgn_driver_evt_cnt, 0);
+
+ /* Get the number of warning events - FPIN and Signal for this minute */
+ wvalue = 0;
+ if ((phba->cgn_reg_fpin & LPFC_CGN_FPIN_WARN) ||
+ phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY ||
+ phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM)
+ wvalue = atomic_read(&phba->cgn_fabric_warn_cnt);
+ atomic_set(&phba->cgn_fabric_warn_cnt, 0);
+
+ /* Get the number of alarm events - FPIN and Signal for this minute */
+ avalue = 0;
+ if ((phba->cgn_reg_fpin & LPFC_CGN_FPIN_ALARM) ||
+ phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM)
+ avalue = atomic_read(&phba->cgn_fabric_alarm_cnt);
+ atomic_set(&phba->cgn_fabric_alarm_cnt, 0);
+
+ /* Collect the driver, warning, alarm and latency counts for this
+ * minute into the driver congestion buffer.
+ */
+ ptr = &cp->cgn_drvr_min[index];
+ value = (uint16_t)dvalue;
+ *ptr = cpu_to_le16(value);
+
+ ptr = &cp->cgn_warn_min[index];
+ value = (uint16_t)wvalue;
+ *ptr = cpu_to_le16(value);
+
+ ptr = &cp->cgn_alarm_min[index];
+ value = (uint16_t)avalue;
+ *ptr = cpu_to_le16(value);
+
+ lptr = &cp->cgn_latency_min[index];
+ if (lvalue) {
+ lvalue = (uint32_t)div_u64(latsum, lvalue);
+ *lptr = cpu_to_le32(lvalue);
+ } else {
+ *lptr = 0;
+ }
+
+ /* Collect the bandwidth value into the driver's congesion buffer. */
+ mptr = &cp->cgn_bw_min[index];
+ *mptr = cpu_to_le16(mvalue);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "2418 Congestion Info - minute (%d): %d %d %d %d %d\n",
+ index, dvalue, wvalue, *lptr, mvalue, avalue);
+
+ /* Every hour */
+ if ((phba->cgn_evt_minute % LPFC_MIN_HOUR) == 0) {
+ /* Record congestion buffer info - every hour
+ * Collapse all minutes into an hour
+ */
+ index = ++cp->cgn_index_hour;
+ if (cp->cgn_index_hour == LPFC_HOUR_DAY) {
+ cp->cgn_index_hour = 0;
+ index = 0;
+ }
+
+ dvalue = 0;
+ wvalue = 0;
+ lvalue = 0;
+ avalue = 0;
+ mvalue = 0;
+ mbps = 0;
+ for (i = 0; i < LPFC_MIN_HOUR; i++) {
+ dvalue += le16_to_cpu(cp->cgn_drvr_min[i]);
+ wvalue += le16_to_cpu(cp->cgn_warn_min[i]);
+ lvalue += le32_to_cpu(cp->cgn_latency_min[i]);
+ mbps += le16_to_cpu(cp->cgn_bw_min[i]);
+ avalue += le16_to_cpu(cp->cgn_alarm_min[i]);
+ }
+ if (lvalue) /* Avg of latency averages */
+ lvalue /= LPFC_MIN_HOUR;
+ if (mbps) /* Avg of Bandwidth averages */
+ mvalue = mbps / LPFC_MIN_HOUR;
+
+ lptr = &cp->cgn_drvr_hr[index];
+ *lptr = cpu_to_le32(dvalue);
+ lptr = &cp->cgn_warn_hr[index];
+ *lptr = cpu_to_le32(wvalue);
+ lptr = &cp->cgn_latency_hr[index];
+ *lptr = cpu_to_le32(lvalue);
+ mptr = &cp->cgn_bw_hr[index];
+ *mptr = cpu_to_le16(mvalue);
+ lptr = &cp->cgn_alarm_hr[index];
+ *lptr = cpu_to_le32(avalue);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "2419 Congestion Info - hour "
+ "(%d): %d %d %d %d %d\n",
+ index, dvalue, wvalue, lvalue, mvalue, avalue);
+ }
+
+ /* Every day */
+ if ((phba->cgn_evt_minute % LPFC_MIN_DAY) == 0) {
+ /* Record congestion buffer info - every hour
+ * Collapse all hours into a day. Rotate days
+ * after LPFC_MAX_CGN_DAYS.
+ */
+ index = ++cp->cgn_index_day;
+ if (cp->cgn_index_day == LPFC_MAX_CGN_DAYS) {
+ cp->cgn_index_day = 0;
+ index = 0;
+ }
+
+ /* Anytime we overwrite daily index 0, after we wrap,
+ * we will be overwriting the oldest day, so we must
+ * update the congestion data start time for that day.
+ * That start time should have previously been saved after
+ * we wrote the last days worth of data.
+ */
+ if ((phba->hba_flag & HBA_CGN_DAY_WRAP) && index == 0) {
+ time64_to_tm(phba->cgn_daily_ts.tv_sec, 0, &broken);
+
+ cp->cgn_info_month = broken.tm_mon + 1;
+ cp->cgn_info_day = broken.tm_mday;
+ cp->cgn_info_year = broken.tm_year - 100;
+ cp->cgn_info_hour = broken.tm_hour;
+ cp->cgn_info_minute = broken.tm_min;
+ cp->cgn_info_second = broken.tm_sec;
+
+ lpfc_printf_log
+ (phba, KERN_INFO, LOG_CGN_MGMT,
+ "2646 CGNInfo idx0 Start Time: "
+ "%d/%d/%d %d:%d:%d\n",
+ cp->cgn_info_day, cp->cgn_info_month,
+ cp->cgn_info_year, cp->cgn_info_hour,
+ cp->cgn_info_minute, cp->cgn_info_second);
+ }
+
+ dvalue = 0;
+ wvalue = 0;
+ lvalue = 0;
+ mvalue = 0;
+ mbps = 0;
+ avalue = 0;
+ for (i = 0; i < LPFC_HOUR_DAY; i++) {
+ dvalue += le32_to_cpu(cp->cgn_drvr_hr[i]);
+ wvalue += le32_to_cpu(cp->cgn_warn_hr[i]);
+ lvalue += le32_to_cpu(cp->cgn_latency_hr[i]);
+ mbps += le32_to_cpu(cp->cgn_bw_hr[i]);
+ avalue += le32_to_cpu(cp->cgn_alarm_hr[i]);
+ }
+ if (lvalue) /* Avg of latency averages */
+ lvalue /= LPFC_HOUR_DAY;
+ if (mbps) /* Avg of Bandwidth averages */
+ mvalue = mbps / LPFC_HOUR_DAY;
+
+ lptr = &cp->cgn_drvr_day[index];
+ *lptr = cpu_to_le32(dvalue);
+ lptr = &cp->cgn_warn_day[index];
+ *lptr = cpu_to_le32(wvalue);
+ lptr = &cp->cgn_latency_day[index];
+ *lptr = cpu_to_le32(lvalue);
+ mptr = &cp->cgn_bw_day[index];
+ *mptr = cpu_to_le16(mvalue);
+ lptr = &cp->cgn_alarm_day[index];
+ *lptr = cpu_to_le32(avalue);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "2420 Congestion Info - daily (%d): "
+ "%d %d %d %d %d\n",
+ index, dvalue, wvalue, lvalue, mvalue, avalue);
+
+ /* We just wrote LPFC_MAX_CGN_DAYS of data,
+ * so we are wrapped on any data after this.
+ * Save this as the start time for the next day.
+ */
+ if (index == (LPFC_MAX_CGN_DAYS - 1)) {
+ phba->hba_flag |= HBA_CGN_DAY_WRAP;
+ ktime_get_real_ts64(&phba->cgn_daily_ts);
+ }
+ }
+
+ /* Use the frequency found in the last rcv'ed FPIN */
+ value = phba->cgn_fpin_frequency;
+ if (phba->cgn_reg_fpin & LPFC_CGN_FPIN_WARN)
+ cp->cgn_warn_freq = cpu_to_le16(value);
+ if (phba->cgn_reg_fpin & LPFC_CGN_FPIN_ALARM)
+ cp->cgn_alarm_freq = cpu_to_le16(value);
+
+ /* Frequency (in ms) Signal Warning/Signal Congestion Notifications
+ * are received by the HBA
+ */
+ value = phba->cgn_sig_freq;
+
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY ||
+ phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM)
+ cp->cgn_warn_freq = cpu_to_le16(value);
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM)
+ cp->cgn_alarm_freq = cpu_to_le16(value);
+
+ lvalue = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ,
+ LPFC_CGN_CRC32_SEED);
+ cp->cgn_info_crc = cpu_to_le32(lvalue);
+}
+
+/**
+ * lpfc_calc_cmf_latency - latency from start of rxate timer interval
+ * @phba: The Hba for which this call is being executed.
+ *
+ * The routine calculates the latency from the beginning of the CMF timer
+ * interval to the current point in time. It is called from IO completion
+ * when we exceed our Bandwidth limitation for the time interval.
+ */
+uint32_t
+lpfc_calc_cmf_latency(struct lpfc_hba *phba)
+{
+ struct timespec64 cmpl_time;
+ uint32_t msec = 0;
+
+ ktime_get_real_ts64(&cmpl_time);
+
+ /* This routine works on a ms granularity so sec and usec are
+ * converted accordingly.
+ */
+ if (cmpl_time.tv_sec == phba->cmf_latency.tv_sec) {
+ msec = (cmpl_time.tv_nsec - phba->cmf_latency.tv_nsec) /
+ NSEC_PER_MSEC;
+ } else {
+ if (cmpl_time.tv_nsec >= phba->cmf_latency.tv_nsec) {
+ msec = (cmpl_time.tv_sec -
+ phba->cmf_latency.tv_sec) * MSEC_PER_SEC;
+ msec += ((cmpl_time.tv_nsec -
+ phba->cmf_latency.tv_nsec) / NSEC_PER_MSEC);
+ } else {
+ msec = (cmpl_time.tv_sec - phba->cmf_latency.tv_sec -
+ 1) * MSEC_PER_SEC;
+ msec += (((NSEC_PER_SEC - phba->cmf_latency.tv_nsec) +
+ cmpl_time.tv_nsec) / NSEC_PER_MSEC);
+ }
+ }
+ return msec;
+}
+
+/**
+ * lpfc_cmf_timer - This is the timer function for one congestion
+ * rate interval.
+ * @timer: Pointer to the high resolution timer that expired
+ */
+static enum hrtimer_restart
+lpfc_cmf_timer(struct hrtimer *timer)
+{
+ struct lpfc_hba *phba = container_of(timer, struct lpfc_hba,
+ cmf_timer);
+ struct rxtable_entry *entry;
+ uint32_t io_cnt;
+ uint32_t head, tail;
+ uint32_t busy, max_read;
+ uint64_t total, rcv, lat, mbpi;
+ int timer_interval = LPFC_CMF_INTERVAL;
+ uint32_t ms;
+ struct lpfc_cgn_stat *cgs;
+ int cpu;
+
+ /* Only restart the timer if congestion mgmt is on */
+ if (phba->cmf_active_mode == LPFC_CFG_OFF ||
+ !phba->cmf_latency.tv_sec) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6224 CMF timer exit: %d %lld\n",
+ phba->cmf_active_mode,
+ (uint64_t)phba->cmf_latency.tv_sec);
+ return HRTIMER_NORESTART;
+ }
+
+ /* If pport is not ready yet, just exit and wait for
+ * the next timer cycle to hit.
+ */
+ if (!phba->pport)
+ goto skip;
+
+ /* Do not block SCSI IO while in the timer routine since
+ * total_bytes will be cleared
+ */
+ atomic_set(&phba->cmf_stop_io, 1);
+
+ /* First we need to calculate the actual ms between
+ * the last timer interrupt and this one. We ask for
+ * LPFC_CMF_INTERVAL, however the actual time may
+ * vary depending on system overhead.
+ */
+ ms = lpfc_calc_cmf_latency(phba);
+
+
+ /* Immediately after we calculate the time since the last
+ * timer interrupt, set the start time for the next
+ * interrupt
+ */
+ ktime_get_real_ts64(&phba->cmf_latency);
+
+ phba->cmf_link_byte_count =
+ div_u64(phba->cmf_max_line_rate * LPFC_CMF_INTERVAL, 1000);
+
+ /* Collect all the stats from the prior timer interval */
+ total = 0;
+ io_cnt = 0;
+ lat = 0;
+ rcv = 0;
+ for_each_present_cpu(cpu) {
+ cgs = per_cpu_ptr(phba->cmf_stat, cpu);
+ total += atomic64_xchg(&cgs->total_bytes, 0);
+ io_cnt += atomic_xchg(&cgs->rx_io_cnt, 0);
+ lat += atomic64_xchg(&cgs->rx_latency, 0);
+ rcv += atomic64_xchg(&cgs->rcv_bytes, 0);
+ }
+
+ /* Before we issue another CMF_SYNC_WQE, retrieve the BW
+ * returned from the last CMF_SYNC_WQE issued, from
+ * cmf_last_sync_bw. This will be the target BW for
+ * this next timer interval.
+ */
+ if (phba->cmf_active_mode == LPFC_CFG_MANAGED &&
+ phba->link_state != LPFC_LINK_DOWN &&
+ phba->hba_flag & HBA_SETUP) {
+ mbpi = phba->cmf_last_sync_bw;
+ phba->cmf_last_sync_bw = 0;
+ lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total);
+ } else {
+ /* For Monitor mode or link down we want mbpi
+ * to be the full link speed
+ */
+ mbpi = phba->cmf_link_byte_count;
+ }
+ phba->cmf_timer_cnt++;
+
+ if (io_cnt) {
+ /* Update congestion info buffer latency in us */
+ atomic_add(io_cnt, &phba->cgn_latency_evt_cnt);
+ atomic64_add(lat, &phba->cgn_latency_evt);
+ }
+ busy = atomic_xchg(&phba->cmf_busy, 0);
+ max_read = atomic_xchg(&phba->rx_max_read_cnt, 0);
+
+ /* Calculate MBPI for the next timer interval */
+ if (mbpi) {
+ if (mbpi > phba->cmf_link_byte_count ||
+ phba->cmf_active_mode == LPFC_CFG_MONITOR)
+ mbpi = phba->cmf_link_byte_count;
+
+ /* Change max_bytes_per_interval to what the prior
+ * CMF_SYNC_WQE cmpl indicated.
+ */
+ if (mbpi != phba->cmf_max_bytes_per_interval)
+ phba->cmf_max_bytes_per_interval = mbpi;
+ }
+
+ /* Save rxmonitor information for debug */
+ if (phba->rxtable) {
+ head = atomic_xchg(&phba->rxtable_idx_head,
+ LPFC_RXMONITOR_TABLE_IN_USE);
+ entry = &phba->rxtable[head];
+ entry->total_bytes = total;
+ entry->rcv_bytes = rcv;
+ entry->cmf_busy = busy;
+ entry->cmf_info = phba->cmf_active_info;
+ if (io_cnt) {
+ entry->avg_io_latency = div_u64(lat, io_cnt);
+ entry->avg_io_size = div_u64(rcv, io_cnt);
+ } else {
+ entry->avg_io_latency = 0;
+ entry->avg_io_size = 0;
+ }
+ entry->max_read_cnt = max_read;
+ entry->io_cnt = io_cnt;
+ entry->max_bytes_per_interval = mbpi;
+ if (phba->cmf_active_mode == LPFC_CFG_MANAGED)
+ entry->timer_utilization = phba->cmf_last_ts;
+ else
+ entry->timer_utilization = ms;
+ entry->timer_interval = ms;
+ phba->cmf_last_ts = 0;
+
+ /* Increment rxtable index */
+ head = (head + 1) % LPFC_MAX_RXMONITOR_ENTRY;
+ tail = atomic_read(&phba->rxtable_idx_tail);
+ if (head == tail) {
+ tail = (tail + 1) % LPFC_MAX_RXMONITOR_ENTRY;
+ atomic_set(&phba->rxtable_idx_tail, tail);
+ }
+ atomic_set(&phba->rxtable_idx_head, head);
+ }
+
+ if (phba->cmf_active_mode == LPFC_CFG_MONITOR) {
+ /* If Monitor mode, check if we are oversubscribed
+ * against the full line rate.
+ */
+ if (mbpi && total > mbpi)
+ atomic_inc(&phba->cgn_driver_evt_cnt);
+ }
+ phba->rx_block_cnt += div_u64(rcv, 512); /* save 512 byte block cnt */
+
+ /* Each minute save Fabric and Driver congestion information */
+ lpfc_cgn_save_evt_cnt(phba);
+
+ /* Since we need to call lpfc_cgn_save_evt_cnt every minute, on the
+ * minute, adjust our next timer interval, if needed, to ensure a
+ * 1 minute granularity when we get the next timer interrupt.
+ */
+ if (time_after(jiffies + msecs_to_jiffies(LPFC_CMF_INTERVAL),
+ phba->cgn_evt_timestamp)) {
+ timer_interval = jiffies_to_msecs(phba->cgn_evt_timestamp -
+ jiffies);
+ if (timer_interval <= 0)
+ timer_interval = LPFC_CMF_INTERVAL;
+
+ /* If we adjust timer_interval, max_bytes_per_interval
+ * needs to be adjusted as well.
+ */
+ phba->cmf_link_byte_count = div_u64(phba->cmf_max_line_rate *
+ timer_interval, 1000);
+ if (phba->cmf_active_mode == LPFC_CFG_MONITOR)
+ phba->cmf_max_bytes_per_interval =
+ phba->cmf_link_byte_count;
+ }
+
+ /* Since total_bytes has already been zero'ed, its okay to unblock
+ * after max_bytes_per_interval is setup.
+ */
+ if (atomic_xchg(&phba->cmf_bw_wait, 0))
+ queue_work(phba->wq, &phba->unblock_request_work);
+
+ /* SCSI IO is now unblocked */
+ atomic_set(&phba->cmf_stop_io, 0);
+
+skip:
+ hrtimer_forward_now(timer,
+ ktime_set(0, timer_interval * NSEC_PER_MSEC));
+ return HRTIMER_RESTART;
+}
+
#define trunk_link_status(__idx)\
bf_get(lpfc_acqe_fc_la_trunk_config_port##__idx, acqe_fc) ?\
((phba->trunk_link.link##__idx.state == LPFC_LINK_UP) ?\
@@ -5329,6 +6105,9 @@ lpfc_update_trunk_link_status(struct lpfc_hba *phba,
trunk_link_status(0), trunk_link_status(1),
trunk_link_status(2), trunk_link_status(3));
+ if (phba->cmf_active_mode != LPFC_CFG_OFF)
+ lpfc_cmf_signal_init(phba);
+
if (port_fault)
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3202 trunk error:0x%x (%s) seen on port0:%s "
@@ -5510,9 +6289,10 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
uint8_t operational = 0;
struct temp_event temp_event_data;
struct lpfc_acqe_misconfigured_event *misconfigured;
+ struct lpfc_acqe_cgn_signal *cgn_signal;
struct Scsi_Host *shost;
struct lpfc_vport **vports;
- int rc, i;
+ int rc, i, cnt;
evt_type = bf_get(lpfc_trailer_type, acqe_sli);
@@ -5668,6 +6448,10 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
"Event Data1:x%08x Event Data2: x%08x\n",
acqe_sli->event_data1, acqe_sli->event_data2);
break;
+ case LPFC_SLI_EVENT_TYPE_PORT_PARAMS_CHG:
+ /* Call FW to obtain active parms */
+ lpfc_sli4_cgn_parm_chg_evt(phba);
+ break;
case LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN:
/* Misconfigured WWN. Reports that the SLI Port is configured
* to use FA-WWN, but the attached device doesn’t support it.
@@ -5685,6 +6469,40 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
"Event Data1: x%08x Event Data2: x%08x\n",
acqe_sli->event_data1, acqe_sli->event_data2);
break;
+ case LPFC_SLI_EVENT_TYPE_CGN_SIGNAL:
+ if (phba->cmf_active_mode == LPFC_CFG_OFF)
+ break;
+ cgn_signal = (struct lpfc_acqe_cgn_signal *)
+ &acqe_sli->event_data1;
+ phba->cgn_acqe_cnt++;
+
+ cnt = bf_get(lpfc_warn_acqe, cgn_signal);
+ atomic64_add(cnt, &phba->cgn_acqe_stat.warn);
+ atomic64_add(cgn_signal->alarm_cnt, &phba->cgn_acqe_stat.alarm);
+
+ /* no threshold for CMF, even 1 signal will trigger an event */
+
+ /* Alarm overrides warning, so check that first */
+ if (cgn_signal->alarm_cnt) {
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
+ /* Keep track of alarm cnt for cgn_info */
+ atomic_add(cgn_signal->alarm_cnt,
+ &phba->cgn_fabric_alarm_cnt);
+ /* Keep track of alarm cnt for CMF_SYNC_WQE */
+ atomic_add(cgn_signal->alarm_cnt,
+ &phba->cgn_sync_alarm_cnt);
+ }
+ } else if (cnt) {
+ /* signal action needs to be taken */
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY ||
+ phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
+ /* Keep track of warning cnt for cgn_info */
+ atomic_add(cnt, &phba->cgn_fabric_warn_cnt);
+ /* Keep track of warning cnt for CMF_SYNC_WQE */
+ atomic_add(cnt, &phba->cgn_sync_warn_cnt);
+ }
+ }
+ break;
default:
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"3193 Unrecognized SLI event, type: 0x%x",
@@ -6060,6 +6878,276 @@ lpfc_sli4_async_grp5_evt(struct lpfc_hba *phba,
}
/**
+ * lpfc_sli4_async_cmstat_evt - Process the asynchronous cmstat event
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is to handle the SLI4 asynchronous cmstat event. A cmstat event
+ * is an asynchronous notification of a request to reset CM stats.
+ **/
+static void
+lpfc_sli4_async_cmstat_evt(struct lpfc_hba *phba)
+{
+ if (!phba->cgn_i)
+ return;
+ lpfc_init_congestion_stat(phba);
+}
+
+/**
+ * lpfc_cgn_params_val - Validate FW congestion parameters.
+ * @phba: pointer to lpfc hba data structure.
+ * @p_cfg_param: pointer to FW provided congestion parameters.
+ *
+ * This routine validates the congestion parameters passed
+ * by the FW to the driver via an ACQE event.
+ **/
+static void
+lpfc_cgn_params_val(struct lpfc_hba *phba, struct lpfc_cgn_param *p_cfg_param)
+{
+ spin_lock_irq(&phba->hbalock);
+
+ if (!lpfc_rangecheck(p_cfg_param->cgn_param_mode, LPFC_CFG_OFF,
+ LPFC_CFG_MONITOR)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
+ "6225 CMF mode param out of range: %d\n",
+ p_cfg_param->cgn_param_mode);
+ p_cfg_param->cgn_param_mode = LPFC_CFG_OFF;
+ }
+
+ spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_cgn_params_parse - Process a FW cong parm change event
+ * @phba: pointer to lpfc hba data structure.
+ * @p_cgn_param: pointer to a data buffer with the FW cong params.
+ * @len: the size of pdata in bytes.
+ *
+ * This routine validates the congestion management buffer signature
+ * from the FW, validates the contents and makes corrections for
+ * valid, in-range values. If the signature magic is correct and
+ * after parameter validation, the contents are copied to the driver's
+ * @phba structure. If the magic is incorrect, an error message is
+ * logged.
+ **/
+static void
+lpfc_cgn_params_parse(struct lpfc_hba *phba,
+ struct lpfc_cgn_param *p_cgn_param, uint32_t len)
+{
+ struct lpfc_cgn_info *cp;
+ uint32_t crc, oldmode;
+
+ /* Make sure the FW has encoded the correct magic number to
+ * validate the congestion parameter in FW memory.
+ */
+ if (p_cgn_param->cgn_param_magic == LPFC_CFG_PARAM_MAGIC_NUM) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT,
+ "4668 FW cgn parm buffer data: "
+ "magic 0x%x version %d mode %d "
+ "level0 %d level1 %d "
+ "level2 %d byte13 %d "
+ "byte14 %d byte15 %d "
+ "byte11 %d byte12 %d activeMode %d\n",
+ p_cgn_param->cgn_param_magic,
+ p_cgn_param->cgn_param_version,
+ p_cgn_param->cgn_param_mode,
+ p_cgn_param->cgn_param_level0,
+ p_cgn_param->cgn_param_level1,
+ p_cgn_param->cgn_param_level2,
+ p_cgn_param->byte13,
+ p_cgn_param->byte14,
+ p_cgn_param->byte15,
+ p_cgn_param->byte11,
+ p_cgn_param->byte12,
+ phba->cmf_active_mode);
+
+ oldmode = phba->cmf_active_mode;
+
+ /* Any parameters out of range are corrected to defaults
+ * by this routine. No need to fail.
+ */
+ lpfc_cgn_params_val(phba, p_cgn_param);
+
+ /* Parameters are verified, move them into driver storage */
+ spin_lock_irq(&phba->hbalock);
+ memcpy(&phba->cgn_p, p_cgn_param,
+ sizeof(struct lpfc_cgn_param));
+
+ /* Update parameters in congestion info buffer now */
+ if (phba->cgn_i) {
+ cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
+ cp->cgn_info_mode = phba->cgn_p.cgn_param_mode;
+ cp->cgn_info_level0 = phba->cgn_p.cgn_param_level0;
+ cp->cgn_info_level1 = phba->cgn_p.cgn_param_level1;
+ cp->cgn_info_level2 = phba->cgn_p.cgn_param_level2;
+ crc = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ,
+ LPFC_CGN_CRC32_SEED);
+ cp->cgn_info_crc = cpu_to_le32(crc);
+ }
+ spin_unlock_irq(&phba->hbalock);
+
+ phba->cmf_active_mode = phba->cgn_p.cgn_param_mode;
+
+ switch (oldmode) {
+ case LPFC_CFG_OFF:
+ if (phba->cgn_p.cgn_param_mode != LPFC_CFG_OFF) {
+ /* Turning CMF on */
+ lpfc_cmf_start(phba);
+
+ if (phba->link_state >= LPFC_LINK_UP) {
+ phba->cgn_reg_fpin =
+ phba->cgn_init_reg_fpin;
+ phba->cgn_reg_signal =
+ phba->cgn_init_reg_signal;
+ lpfc_issue_els_edc(phba->pport, 0);
+ }
+ }
+ break;
+ case LPFC_CFG_MANAGED:
+ switch (phba->cgn_p.cgn_param_mode) {
+ case LPFC_CFG_OFF:
+ /* Turning CMF off */
+ lpfc_cmf_stop(phba);
+ if (phba->link_state >= LPFC_LINK_UP)
+ lpfc_issue_els_edc(phba->pport, 0);
+ break;
+ case LPFC_CFG_MONITOR:
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "4661 Switch from MANAGED to "
+ "`MONITOR mode\n");
+ phba->cmf_max_bytes_per_interval =
+ phba->cmf_link_byte_count;
+
+ /* Resume blocked IO - unblock on workqueue */
+ queue_work(phba->wq,
+ &phba->unblock_request_work);
+ break;
+ }
+ break;
+ case LPFC_CFG_MONITOR:
+ switch (phba->cgn_p.cgn_param_mode) {
+ case LPFC_CFG_OFF:
+ /* Turning CMF off */
+ lpfc_cmf_stop(phba);
+ if (phba->link_state >= LPFC_LINK_UP)
+ lpfc_issue_els_edc(phba->pport, 0);
+ break;
+ case LPFC_CFG_MANAGED:
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "4662 Switch from MONITOR to "
+ "MANAGED mode\n");
+ lpfc_cmf_signal_init(phba);
+ break;
+ }
+ break;
+ }
+ } else {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
+ "4669 FW cgn parm buf wrong magic 0x%x "
+ "version %d\n", p_cgn_param->cgn_param_magic,
+ p_cgn_param->cgn_param_version);
+ }
+}
+
+/**
+ * lpfc_sli4_cgn_params_read - Read and Validate FW congestion parameters.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine issues a read_object mailbox command to
+ * get the congestion management parameters from the FW
+ * parses it and updates the driver maintained values.
+ *
+ * Returns
+ * 0 if the object was empty
+ * -Eval if an error was encountered
+ * Count if bytes were read from object
+ **/
+int
+lpfc_sli4_cgn_params_read(struct lpfc_hba *phba)
+{
+ int ret = 0;
+ struct lpfc_cgn_param *p_cgn_param = NULL;
+ u32 *pdata = NULL;
+ u32 len = 0;
+
+ /* Find out if the FW has a new set of congestion parameters. */
+ len = sizeof(struct lpfc_cgn_param);
+ pdata = kzalloc(len, GFP_KERNEL);
+ ret = lpfc_read_object(phba, (char *)LPFC_PORT_CFG_NAME,
+ pdata, len);
+
+ /* 0 means no data. A negative means error. A positive means
+ * bytes were copied.
+ */
+ if (!ret) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
+ "4670 CGN RD OBJ returns no data\n");
+ goto rd_obj_err;
+ } else if (ret < 0) {
+ /* Some error. Just exit and return it to the caller.*/
+ goto rd_obj_err;
+ }
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT,
+ "6234 READ CGN PARAMS Successful %d\n", len);
+
+ /* Parse data pointer over len and update the phba congestion
+ * parameters with values passed back. The receive rate values
+ * may have been altered in FW, but take no action here.
+ */
+ p_cgn_param = (struct lpfc_cgn_param *)pdata;
+ lpfc_cgn_params_parse(phba, p_cgn_param, len);
+
+ rd_obj_err:
+ kfree(pdata);
+ return ret;
+}
+
+/**
+ * lpfc_sli4_cgn_parm_chg_evt - Process a FW congestion param change event
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * The FW generated Async ACQE SLI event calls this routine when
+ * the event type is an SLI Internal Port Event and the Event Code
+ * indicates a change to the FW maintained congestion parameters.
+ *
+ * This routine executes a Read_Object mailbox call to obtain the
+ * current congestion parameters maintained in FW and corrects
+ * the driver's active congestion parameters.
+ *
+ * The acqe event is not passed because there is no further data
+ * required.
+ *
+ * Returns nonzero error if event processing encountered an error.
+ * Zero otherwise for success.
+ **/
+static int
+lpfc_sli4_cgn_parm_chg_evt(struct lpfc_hba *phba)
+{
+ int ret = 0;
+
+ if (!phba->sli4_hba.pc_sli4_params.cmf) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
+ "4664 Cgn Evt when E2E off. Drop event\n");
+ return -EACCES;
+ }
+
+ /* If the event is claiming an empty object, it's ok. A write
+ * could have cleared it. Only error is a negative return
+ * status.
+ */
+ ret = lpfc_sli4_cgn_params_read(phba);
+ if (ret < 0) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
+ "4667 Error reading Cgn Params (%d)\n",
+ ret);
+ } else if (!ret) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
+ "4673 CGN Event empty object.\n");
+ }
+ return ret;
+}
+
+/**
* lpfc_sli4_async_event_proc - Process all the pending asynchronous event
* @phba: pointer to lpfc hba data structure.
*
@@ -6107,6 +7195,9 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba)
case LPFC_TRAILER_CODE_SLI:
lpfc_sli4_async_sli_evt(phba, &cq_event->cqe.acqe_sli);
break;
+ case LPFC_TRAILER_CODE_CMSTAT:
+ lpfc_sli4_async_cmstat_evt(phba);
+ break;
default:
lpfc_printf_log(phba, KERN_ERR,
LOG_TRACE_EVENT,
@@ -6391,6 +7482,15 @@ lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *phba, int nr_vfn)
return rc;
}
+static void
+lpfc_unblock_requests_work(struct work_struct *work)
+{
+ struct lpfc_hba *phba = container_of(work, struct lpfc_hba,
+ unblock_request_work);
+
+ lpfc_unblock_requests(phba);
+}
+
/**
* lpfc_setup_driver_resource_phase1 - Phase1 etup driver internal resources.
* @phba: pointer to lpfc hba data structure.
@@ -6466,7 +7566,7 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
INIT_DELAYED_WORK(&phba->idle_stat_delay_work,
lpfc_idle_stat_delay_work);
-
+ INIT_WORK(&phba->unblock_request_work, lpfc_unblock_requests_work);
return 0;
}
@@ -6697,6 +7797,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
/* FCF rediscover timer */
timer_setup(&phba->fcf.redisc_wait, lpfc_sli4_fcf_redisc_wait_tmo, 0);
+ /* CMF congestion timer */
+ hrtimer_init(&phba->cmf_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ phba->cmf_timer.function = lpfc_cmf_timer;
+
/*
* Control structure for handling external multi-buffer mailbox
* command pass-through.
@@ -7145,6 +8249,14 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
}
#endif
+ phba->cmf_stat = alloc_percpu(struct lpfc_cgn_stat);
+ if (!phba->cmf_stat) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3331 Failed allocating per cpu cgn stats\n");
+ rc = -ENOMEM;
+ goto out_free_hba_hdwq_info;
+ }
+
/*
* Enable sr-iov virtual functions if supported and configured
* through the module parameter.
@@ -7164,6 +8276,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
return 0;
+out_free_hba_hdwq_info:
+ free_percpu(phba->sli4_hba.c_stat);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
out_free_hba_idle_stat:
kfree(phba->sli4_hba.idle_stat);
@@ -7211,6 +8325,7 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
free_percpu(phba->sli4_hba.c_stat);
#endif
+ free_percpu(phba->cmf_stat);
kfree(phba->sli4_hba.idle_stat);
/* Free memory allocated for msi-x interrupt vector to CPU mapping */
@@ -8537,9 +9652,12 @@ lpfc_map_topology(struct lpfc_hba *phba, struct lpfc_mbx_read_config *rd_config)
}
/* FW supports persistent topology - override module parameter value */
phba->hba_flag |= HBA_PERSISTENT_TOPO;
- switch (phba->pcidev->device) {
- case PCI_DEVICE_ID_LANCER_G7_FC:
- case PCI_DEVICE_ID_LANCER_G6_FC:
+
+ /* if ASIC_GEN_NUM >= 0xC) */
+ if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_IF_TYPE_6) ||
+ (bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_FAMILY_G6)) {
if (!tf) {
phba->cfg_topology = ((pt == LINK_FLAGS_LOOP)
? FLAGS_TOPOLOGY_MODE_LOOP
@@ -8547,8 +9665,7 @@ lpfc_map_topology(struct lpfc_hba *phba, struct lpfc_mbx_read_config *rd_config)
} else {
phba->hba_flag &= ~HBA_PERSISTENT_TOPO;
}
- break;
- default: /* G5 */
+ } else { /* G5 */
if (tf) {
/* If topology failover set - pt is '0' or '1' */
phba->cfg_topology = (pt ? FLAGS_TOPOLOGY_MODE_PT_LOOP :
@@ -8558,7 +9675,6 @@ lpfc_map_topology(struct lpfc_hba *phba, struct lpfc_mbx_read_config *rd_config)
? FLAGS_TOPOLOGY_MODE_PT_PT
: FLAGS_TOPOLOGY_MODE_LOOP);
}
- break;
}
if (phba->hba_flag & HBA_PERSISTENT_TOPO) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
@@ -8683,6 +9799,52 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
phba->max_vpi = (phba->sli4_hba.max_cfg_param.max_vpi > 0) ?
(phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0;
phba->max_vports = phba->max_vpi;
+
+ /* Next decide on FPIN or Signal E2E CGN support
+ * For congestion alarms and warnings valid combination are:
+ * 1. FPIN alarms / FPIN warnings
+ * 2. Signal alarms / Signal warnings
+ * 3. FPIN alarms / Signal warnings
+ * 4. Signal alarms / FPIN warnings
+ *
+ * Initialize the adapter frequency to 100 mSecs
+ */
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_BOTH;
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
+
+ if (lpfc_use_cgn_signal) {
+ if (bf_get(lpfc_mbx_rd_conf_wcs, rd_config)) {
+ phba->cgn_reg_signal = EDC_CG_SIG_WARN_ONLY;
+ phba->cgn_reg_fpin &= ~LPFC_CGN_FPIN_WARN;
+ }
+ if (bf_get(lpfc_mbx_rd_conf_acs, rd_config)) {
+ /* MUST support both alarm and warning
+ * because EDC does not support alarm alone.
+ */
+ if (phba->cgn_reg_signal !=
+ EDC_CG_SIG_WARN_ONLY) {
+ /* Must support both or none */
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_BOTH;
+ phba->cgn_reg_signal =
+ EDC_CG_SIG_NOTSUPPORTED;
+ } else {
+ phba->cgn_reg_signal =
+ EDC_CG_SIG_WARN_ALARM;
+ phba->cgn_reg_fpin =
+ LPFC_CGN_FPIN_NONE;
+ }
+ }
+ }
+
+ /* Set the congestion initial signal and fpin values. */
+ phba->cgn_init_reg_fpin = phba->cgn_reg_fpin;
+ phba->cgn_init_reg_signal = phba->cgn_reg_signal;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6446 READ_CONFIG reg_sig x%x reg_fpin:x%x\n",
+ phba->cgn_reg_signal, phba->cgn_reg_fpin);
+
lpfc_map_topology(phba, rd_config);
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"2003 cfg params Extents? %d "
@@ -12063,6 +13225,8 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
struct pci_dev *pdev = phba->pcidev;
lpfc_stop_hba_timers(phba);
+ hrtimer_cancel(&phba->cmf_timer);
+
if (phba->pport)
phba->sli4_hba.intr_enable = 0;
@@ -12133,6 +13297,240 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
phba->pport->work_port_events = 0;
}
+static uint32_t
+lpfc_cgn_crc32(uint32_t crc, u8 byte)
+{
+ uint32_t msb = 0;
+ uint32_t bit;
+
+ for (bit = 0; bit < 8; bit++) {
+ msb = (crc >> 31) & 1;
+ crc <<= 1;
+
+ if (msb ^ (byte & 1)) {
+ crc ^= LPFC_CGN_CRC32_MAGIC_NUMBER;
+ crc |= 1;
+ }
+ byte >>= 1;
+ }
+ return crc;
+}
+
+static uint32_t
+lpfc_cgn_reverse_bits(uint32_t wd)
+{
+ uint32_t result = 0;
+ uint32_t i;
+
+ for (i = 0; i < 32; i++) {
+ result <<= 1;
+ result |= (1 & (wd >> i));
+ }
+ return result;
+}
+
+/*
+ * The routine corresponds with the algorithm the HBA firmware
+ * uses to validate the data integrity.
+ */
+uint32_t
+lpfc_cgn_calc_crc32(void *ptr, uint32_t byteLen, uint32_t crc)
+{
+ uint32_t i;
+ uint32_t result;
+ uint8_t *data = (uint8_t *)ptr;
+
+ for (i = 0; i < byteLen; ++i)
+ crc = lpfc_cgn_crc32(crc, data[i]);
+
+ result = ~lpfc_cgn_reverse_bits(crc);
+ return result;
+}
+
+void
+lpfc_init_congestion_buf(struct lpfc_hba *phba)
+{
+ struct lpfc_cgn_info *cp;
+ struct timespec64 cmpl_time;
+ struct tm broken;
+ uint16_t size;
+ uint32_t crc;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6235 INIT Congestion Buffer %p\n", phba->cgn_i);
+
+ if (!phba->cgn_i)
+ return;
+ cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
+
+ atomic_set(&phba->cgn_fabric_warn_cnt, 0);
+ atomic_set(&phba->cgn_fabric_alarm_cnt, 0);
+ atomic_set(&phba->cgn_sync_alarm_cnt, 0);
+ atomic_set(&phba->cgn_sync_warn_cnt, 0);
+
+ atomic64_set(&phba->cgn_acqe_stat.alarm, 0);
+ atomic64_set(&phba->cgn_acqe_stat.warn, 0);
+ atomic_set(&phba->cgn_driver_evt_cnt, 0);
+ atomic_set(&phba->cgn_latency_evt_cnt, 0);
+ atomic64_set(&phba->cgn_latency_evt, 0);
+ phba->cgn_evt_minute = 0;
+ phba->hba_flag &= ~HBA_CGN_DAY_WRAP;
+
+ memset(cp, 0xff, LPFC_CGN_DATA_SIZE);
+ cp->cgn_info_size = cpu_to_le16(LPFC_CGN_INFO_SZ);
+ cp->cgn_info_version = LPFC_CGN_INFO_V3;
+
+ /* cgn parameters */
+ cp->cgn_info_mode = phba->cgn_p.cgn_param_mode;
+ cp->cgn_info_level0 = phba->cgn_p.cgn_param_level0;
+ cp->cgn_info_level1 = phba->cgn_p.cgn_param_level1;
+ cp->cgn_info_level2 = phba->cgn_p.cgn_param_level2;
+
+ ktime_get_real_ts64(&cmpl_time);
+ time64_to_tm(cmpl_time.tv_sec, 0, &broken);
+
+ cp->cgn_info_month = broken.tm_mon + 1;
+ cp->cgn_info_day = broken.tm_mday;
+ cp->cgn_info_year = broken.tm_year - 100; /* relative to 2000 */
+ cp->cgn_info_hour = broken.tm_hour;
+ cp->cgn_info_minute = broken.tm_min;
+ cp->cgn_info_second = broken.tm_sec;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT,
+ "2643 CGNInfo Init: Start Time "
+ "%d/%d/%d %d:%d:%d\n",
+ cp->cgn_info_day, cp->cgn_info_month,
+ cp->cgn_info_year, cp->cgn_info_hour,
+ cp->cgn_info_minute, cp->cgn_info_second);
+
+ /* Fill in default LUN qdepth */
+ if (phba->pport) {
+ size = (uint16_t)(phba->pport->cfg_lun_queue_depth);
+ cp->cgn_lunq = cpu_to_le16(size);
+ }
+
+ /* last used Index initialized to 0xff already */
+
+ cp->cgn_warn_freq = LPFC_FPIN_INIT_FREQ;
+ cp->cgn_alarm_freq = LPFC_FPIN_INIT_FREQ;
+ crc = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED);
+ cp->cgn_info_crc = cpu_to_le32(crc);
+
+ phba->cgn_evt_timestamp = jiffies +
+ msecs_to_jiffies(LPFC_CGN_TIMER_TO_MIN);
+}
+
+void
+lpfc_init_congestion_stat(struct lpfc_hba *phba)
+{
+ struct lpfc_cgn_info *cp;
+ struct timespec64 cmpl_time;
+ struct tm broken;
+ uint32_t crc;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6236 INIT Congestion Stat %p\n", phba->cgn_i);
+
+ if (!phba->cgn_i)
+ return;
+
+ cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
+ memset(&cp->cgn_stat_npm, 0, LPFC_CGN_STAT_SIZE);
+
+ ktime_get_real_ts64(&cmpl_time);
+ time64_to_tm(cmpl_time.tv_sec, 0, &broken);
+
+ cp->cgn_stat_month = broken.tm_mon + 1;
+ cp->cgn_stat_day = broken.tm_mday;
+ cp->cgn_stat_year = broken.tm_year - 100; /* relative to 2000 */
+ cp->cgn_stat_hour = broken.tm_hour;
+ cp->cgn_stat_minute = broken.tm_min;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT,
+ "2647 CGNstat Init: Start Time "
+ "%d/%d/%d %d:%d\n",
+ cp->cgn_stat_day, cp->cgn_stat_month,
+ cp->cgn_stat_year, cp->cgn_stat_hour,
+ cp->cgn_stat_minute);
+
+ crc = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED);
+ cp->cgn_info_crc = cpu_to_le32(crc);
+}
+
+/**
+ * __lpfc_reg_congestion_buf - register congestion info buffer with HBA
+ * @phba: Pointer to hba context object.
+ * @reg: flag to determine register or unregister.
+ */
+static int
+__lpfc_reg_congestion_buf(struct lpfc_hba *phba, int reg)
+{
+ struct lpfc_mbx_reg_congestion_buf *reg_congestion_buf;
+ union lpfc_sli4_cfg_shdr *shdr;
+ uint32_t shdr_status, shdr_add_status;
+ LPFC_MBOXQ_t *mboxq;
+ int length, rc;
+
+ if (!phba->cgn_i)
+ return -ENXIO;
+
+ mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mboxq) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ "2641 REG_CONGESTION_BUF mbox allocation fail: "
+ "HBA state x%x reg %d\n",
+ phba->pport->port_state, reg);
+ return -ENOMEM;
+ }
+
+ length = (sizeof(struct lpfc_mbx_reg_congestion_buf) -
+ sizeof(struct lpfc_sli4_cfg_mhdr));
+ lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_REG_CONGESTION_BUF, length,
+ LPFC_SLI4_MBX_EMBED);
+ reg_congestion_buf = &mboxq->u.mqe.un.reg_congestion_buf;
+ bf_set(lpfc_mbx_reg_cgn_buf_type, reg_congestion_buf, 1);
+ if (reg > 0)
+ bf_set(lpfc_mbx_reg_cgn_buf_cnt, reg_congestion_buf, 1);
+ else
+ bf_set(lpfc_mbx_reg_cgn_buf_cnt, reg_congestion_buf, 0);
+ reg_congestion_buf->length = sizeof(struct lpfc_cgn_info);
+ reg_congestion_buf->addr_lo =
+ putPaddrLow(phba->cgn_i->phys);
+ reg_congestion_buf->addr_hi =
+ putPaddrHigh(phba->cgn_i->phys);
+
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ shdr = (union lpfc_sli4_cfg_shdr *)
+ &mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
+ &shdr->response);
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ if (shdr_status || shdr_add_status || rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2642 REG_CONGESTION_BUF mailbox "
+ "failed with status x%x add_status x%x,"
+ " mbx status x%x reg %d\n",
+ shdr_status, shdr_add_status, rc, reg);
+ return -ENXIO;
+ }
+ return 0;
+}
+
+int
+lpfc_unreg_congestion_buf(struct lpfc_hba *phba)
+{
+ lpfc_cmf_stop(phba);
+ return __lpfc_reg_congestion_buf(phba, 0);
+}
+
+int
+lpfc_reg_congestion_buf(struct lpfc_hba *phba)
+{
+ return __lpfc_reg_congestion_buf(phba, 1);
+}
+
/**
* lpfc_get_sli4_parameters - Get the SLI4 Config PARAMETERS.
* @phba: Pointer to HBA context object.
@@ -12241,7 +13639,6 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
bf_get(cfg_xib, mbx_sli4_parameters),
phba->cfg_enable_fc4_type);
fcponly:
- phba->nvme_support = 0;
phba->nvmet_support = 0;
phba->cfg_nvmet_mrq = 0;
phba->cfg_nvme_seg_cnt = 0;
@@ -12259,9 +13656,10 @@ fcponly:
if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)
phba->cfg_sg_seg_cnt = LPFC_MAX_NVME_SEG_CNT;
- /* Only embed PBDE for if_type 6, PBDE support requires xib be set */
- if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
- LPFC_SLI_INTF_IF_TYPE_6) || (!bf_get(cfg_xib, mbx_sli4_parameters)))
+ /* Enable embedded Payload BDE if support is indicated */
+ if (bf_get(cfg_pbde, mbx_sli4_parameters))
+ phba->cfg_enable_pbde = 1;
+ else
phba->cfg_enable_pbde = 0;
/*
@@ -12299,7 +13697,7 @@ fcponly:
"6422 XIB %d PBDE %d: FCP %d NVME %d %d %d\n",
bf_get(cfg_xib, mbx_sli4_parameters),
phba->cfg_enable_pbde,
- phba->fcp_embed_io, phba->nvme_support,
+ phba->fcp_embed_io, sli4_params->nvme,
phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp);
if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
@@ -12331,21 +13729,6 @@ fcponly:
else
phba->nsler = 0;
- /* Save PB info for use during HBA setup */
- sli4_params->mi_ver = bf_get(cfg_mi_ver, mbx_sli4_parameters);
- sli4_params->mib_bde_cnt = bf_get(cfg_mib_bde_cnt, mbx_sli4_parameters);
- sli4_params->mib_size = mbx_sli4_parameters->mib_size;
- sli4_params->mi_value = LPFC_DFLT_MIB_VAL;
-
- /* Next we check for Vendor MIB support */
- if (sli4_params->mi_ver && phba->cfg_enable_mi)
- phba->cfg_fdmi_on = LPFC_FDMI_SUPPORT;
-
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "6461 MIB attr %d enable %d FDMI %d buf %d:%d\n",
- sli4_params->mi_ver, phba->cfg_enable_mi,
- sli4_params->mi_value, sli4_params->mib_bde_cnt,
- sli4_params->mib_size);
return 0;
}
@@ -12978,7 +14361,9 @@ lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset,
const struct firmware *fw)
{
int rc;
+ u8 sli_family;
+ sli_family = bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf);
/* Three cases: (1) FW was not supported on the detected adapter.
* (2) FW update has been locked out administratively.
* (3) Some other error during FW update.
@@ -12986,10 +14371,12 @@ lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset,
* for admin diagnosis.
*/
if (offset == ADD_STATUS_FW_NOT_SUPPORTED ||
- (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
+ (sli_family == LPFC_SLI_INTF_FAMILY_G6 &&
magic_number != MAGIC_NUMBER_G6) ||
- (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC &&
- magic_number != MAGIC_NUMBER_G7)) {
+ (sli_family == LPFC_SLI_INTF_FAMILY_G7 &&
+ magic_number != MAGIC_NUMBER_G7) ||
+ (sli_family == LPFC_SLI_INTF_FAMILY_G7P &&
+ magic_number != MAGIC_NUMBER_G7P)) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3030 This firmware version is not supported on"
" this HBA model. Device:%x Magic:%x Type:%x "
@@ -13377,6 +14764,8 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
spin_lock_irq(&phba->hbalock);
vport->load_flag |= FC_UNLOADING;
spin_unlock_irq(&phba->hbalock);
+ if (phba->cgn_i)
+ lpfc_unreg_congestion_buf(phba);
lpfc_free_sysfs_attr(vport);
@@ -14041,17 +15430,18 @@ lpfc_sli4_oas_verify(struct lpfc_hba *phba)
void
lpfc_sli4_ras_init(struct lpfc_hba *phba)
{
- switch (phba->pcidev->device) {
- case PCI_DEVICE_ID_LANCER_G6_FC:
- case PCI_DEVICE_ID_LANCER_G7_FC:
+ /* if ASIC_GEN_NUM >= 0xC) */
+ if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_IF_TYPE_6) ||
+ (bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_FAMILY_G6)) {
phba->ras_fwlog.ras_hwsupport = true;
if (phba->cfg_ras_fwlog_func == PCI_FUNC(phba->pcidev->devfn) &&
phba->cfg_ras_fwlog_buffsize)
phba->ras_fwlog.ras_enabled = true;
else
phba->ras_fwlog.ras_enabled = false;
- break;
- default:
+ } else {
phba->ras_fwlog.ras_hwsupport = false;
}
}
@@ -14164,8 +15554,9 @@ void lpfc_dmp_dbg(struct lpfc_hba *phba)
unsigned int temp_idx;
int i;
int j = 0;
- unsigned long rem_nsec;
- struct lpfc_vport **vports;
+ unsigned long rem_nsec, iflags;
+ bool log_verbose = false;
+ struct lpfc_vport *port_iterator;
/* Don't dump messages if we explicitly set log_verbose for the
* physical port or any vport.
@@ -14173,16 +15564,24 @@ void lpfc_dmp_dbg(struct lpfc_hba *phba)
if (phba->cfg_log_verbose)
return;
- vports = lpfc_create_vport_work_array(phba);
- if (vports != NULL) {
- for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
- if (vports[i]->cfg_log_verbose) {
- lpfc_destroy_vport_work_array(phba, vports);
+ spin_lock_irqsave(&phba->port_list_lock, iflags);
+ list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+ if (port_iterator->load_flag & FC_UNLOADING)
+ continue;
+ if (scsi_host_get(lpfc_shost_from_vport(port_iterator))) {
+ if (port_iterator->cfg_log_verbose)
+ log_verbose = true;
+
+ scsi_host_put(lpfc_shost_from_vport(port_iterator));
+
+ if (log_verbose) {
+ spin_unlock_irqrestore(&phba->port_list_lock,
+ iflags);
return;
}
}
}
- lpfc_destroy_vport_work_array(phba, vports);
+ spin_unlock_irqrestore(&phba->port_list_lock, iflags);
if (atomic_cmpxchg(&phba->dbg_log_dmping, 0, 1) != 0)
return;
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index 5660a8729462..7d480c798794 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -1,7 +1,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 *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -44,6 +44,9 @@
#define LOG_NVME_DISC 0x00200000 /* NVME Discovery/Connect events. */
#define LOG_NVME_ABTS 0x00400000 /* NVME ABTS events. */
#define LOG_NVME_IOERR 0x00800000 /* NVME IO Error events. */
+#define LOG_RSVD1 0x01000000 /* Reserved */
+#define LOG_RSVD2 0x02000000 /* Reserved */
+#define LOG_CGN_MGMT 0x04000000 /* Congestion Mgmt events */
#define LOG_TRACE_EVENT 0x80000000 /* Dmp the DBG log on this err */
#define LOG_ALL_MSG 0x7fffffff /* LOG all messages */
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 84bc373190d8..6c754ee96bee 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -513,8 +513,9 @@ lpfc_init_link(struct lpfc_hba * phba,
break;
}
- if ((phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
- phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) &&
+ /* Topology handling for ASIC_GEN_NUM 0xC and later */
+ if ((phba->sli4_hba.pc_sli4_params.sli_family == LPFC_SLI_INTF_FAMILY_G6 ||
+ phba->sli4_hba.pc_sli4_params.if_type == LPFC_SLI_INTF_IF_TYPE_6) &&
!(phba->sli4_hba.pc_sli4_params.pls) &&
mb->un.varInitLnk.link_flags & FLAGS_TOPOLOGY_MODE_LOOP) {
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index be54fbf5146f..870e53b8f81d 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -1,7 +1,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 *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2014 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -335,6 +335,19 @@ lpfc_mem_free_all(struct lpfc_hba *phba)
dma_pool_destroy(phba->lpfc_cmd_rsp_buf_pool);
phba->lpfc_cmd_rsp_buf_pool = NULL;
+ /* Free Congestion Data buffer */
+ if (phba->cgn_i) {
+ dma_free_coherent(&phba->pcidev->dev,
+ sizeof(struct lpfc_cgn_info),
+ phba->cgn_i->virt, phba->cgn_i->phys);
+ kfree(phba->cgn_i);
+ phba->cgn_i = NULL;
+ }
+
+ /* Free RX table */
+ kfree(phba->rxtable);
+ phba->rxtable = NULL;
+
/* Free the iocb lookup array */
kfree(psli->iocbq_lookup);
psli->iocbq_lookup = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index e12f83fb795c..27263f02ab9f 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -736,9 +736,13 @@ out:
* is already in MAPPED or UNMAPPED state. Catch this
* condition and don't set the nlp_state again because
* it causes an unnecessary transport unregister/register.
+ *
+ * Nodes marked for ADISC will move MAPPED or UNMAPPED state
+ * after issuing ADISC
*/
if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) {
- if (ndlp->nlp_state != NLP_STE_MAPPED_NODE)
+ if ((ndlp->nlp_state != NLP_STE_MAPPED_NODE) &&
+ !(ndlp->nlp_flag & NLP_NPR_ADISC))
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_MAPPED_NODE);
}
@@ -863,6 +867,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
}
out:
+ /* Unregister from backend, could have been skipped due to ADISC */
+ lpfc_nlp_unreg_node(vport, ndlp);
+
ndlp->nlp_prev_state = ndlp->nlp_state;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
@@ -1677,9 +1684,6 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
spin_unlock_irq(&ndlp->lock);
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
- memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name));
- memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name));
-
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
lpfc_unreg_rpi(vport, ndlp);
@@ -2597,13 +2601,14 @@ lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
void *arg,
uint32_t evt)
{
+ lpfc_disc_set_adisc(vport, ndlp);
+
ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(&ndlp->lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
spin_unlock_irq(&ndlp->lock);
- lpfc_disc_set_adisc(vport, ndlp);
return ndlp->nlp_state;
}
@@ -2645,14 +2650,13 @@ lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
- if (ndlp->nlp_flag & NLP_NPR_ADISC) {
- spin_lock_irq(&ndlp->lock);
- ndlp->nlp_flag &= ~NLP_NPR_ADISC;
- ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
- spin_unlock_irq(&ndlp->lock);
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
- lpfc_issue_els_adisc(vport, ndlp, 0);
- } else {
+ /*
+ * ADISC nodes will be handled in regular discovery path after
+ * receiving response from NS.
+ *
+ * For other nodes, Send PLOGI to trigger an implicit LOGO.
+ */
+ if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
@@ -2685,12 +2689,13 @@ lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
*/
if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
- if (ndlp->nlp_flag & NLP_NPR_ADISC) {
- ndlp->nlp_flag &= ~NLP_NPR_ADISC;
- ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
- lpfc_issue_els_adisc(vport, ndlp, 0);
- } else {
+ /*
+ * ADISC nodes will be handled in regular discovery path after
+ * receiving response from NS.
+ *
+ * For other nodes, Send PLOGI to trigger an implicit LOGO.
+ */
+ if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index bcc804cefd30..73a3568ff17e 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -216,8 +216,8 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport)
/* The register rebind might have occurred before the delete
* downcall. Guard against this race.
*/
- if (ndlp->fc4_xpt_flags & NLP_WAIT_FOR_UNREG)
- ndlp->fc4_xpt_flags &= ~(NLP_WAIT_FOR_UNREG | NVME_XPT_REGD);
+ if (ndlp->fc4_xpt_flags & NVME_XPT_UNREG_WAIT)
+ ndlp->fc4_xpt_flags &= ~(NVME_XPT_UNREG_WAIT | NVME_XPT_REGD);
spin_unlock_irq(&ndlp->lock);
@@ -931,6 +931,8 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
uint32_t code, status, idx;
uint16_t cid, sqhd, data;
uint32_t *ptr;
+ uint32_t lat;
+ bool call_done = false;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
int cpu;
#endif
@@ -1135,10 +1137,21 @@ out_err:
freqpriv = nCmd->private;
freqpriv->nvme_buf = NULL;
lpfc_ncmd->nvmeCmd = NULL;
- spin_unlock(&lpfc_ncmd->buf_lock);
+ call_done = true;
+ }
+ spin_unlock(&lpfc_ncmd->buf_lock);
+
+ /* Check if IO qualified for CMF */
+ if (phba->cmf_active_mode != LPFC_CFG_OFF &&
+ nCmd->io_dir == NVMEFC_FCP_READ &&
+ nCmd->payload_length) {
+ /* Used when calculating average latency */
+ lat = ktime_get_ns() - lpfc_ncmd->rx_cmd_start;
+ lpfc_update_cmf_cmpl(phba, lat, nCmd->payload_length, NULL);
+ }
+
+ if (call_done)
nCmd->done(nCmd);
- } else
- spin_unlock(&lpfc_ncmd->buf_lock);
/* Call release with XB=1 to queue the IO into the abort list. */
lpfc_release_nvme_buf(phba, lpfc_ncmd);
@@ -1212,6 +1225,10 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
/* Word 5 */
wqe->fcp_iread.rsrvd5 = 0;
+ /* For a CMF Managed port, iod must be zero'ed */
+ if (phba->cmf_active_mode == LPFC_CFG_MANAGED)
+ bf_set(wqe_iod, &wqe->fcp_iread.wqe_com,
+ LPFC_WQE_IOD_NONE);
cstat->input_requests++;
}
} else {
@@ -1562,6 +1579,19 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
expedite = 1;
}
+ /* Check if IO qualifies for CMF */
+ if (phba->cmf_active_mode != LPFC_CFG_OFF &&
+ pnvme_fcreq->io_dir == NVMEFC_FCP_READ &&
+ pnvme_fcreq->payload_length) {
+ ret = lpfc_update_cmf_cmd(phba, pnvme_fcreq->payload_length);
+ if (ret) {
+ ret = -EBUSY;
+ goto out_fail;
+ }
+ /* Get start time for IO latency */
+ start = ktime_get_ns();
+ }
+
/* The node is shared with FCP IO, make sure the IO pending count does
* not exceed the programmed depth.
*/
@@ -1576,7 +1606,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
ndlp->cmd_qdepth);
atomic_inc(&lport->xmt_fcp_qdepth);
ret = -EBUSY;
- goto out_fail;
+ goto out_fail1;
}
}
@@ -1596,7 +1626,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
"idx %d DID %x\n",
lpfc_queue_info->index, ndlp->nlp_DID);
ret = -EBUSY;
- goto out_fail;
+ goto out_fail1;
}
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (start) {
@@ -1606,6 +1636,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
lpfc_ncmd->ts_cmd_start = 0;
}
#endif
+ lpfc_ncmd->rx_cmd_start = start;
/*
* Store the data needed by the driver to issue, abort, and complete
@@ -1687,6 +1718,9 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
} else
cstat->control_requests--;
lpfc_release_nvme_buf(phba, lpfc_ncmd);
+ out_fail1:
+ lpfc_update_cmf_cmpl(phba, LPFC_CGN_NOT_SENT,
+ pnvme_fcreq->payload_length, NULL);
out_fail:
return ret;
}
@@ -2324,7 +2358,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* race that leaves the WAIT flag set.
*/
spin_lock_irq(&ndlp->lock);
- ndlp->fc4_xpt_flags &= ~NLP_WAIT_FOR_UNREG;
+ ndlp->fc4_xpt_flags &= ~NVME_XPT_UNREG_WAIT;
ndlp->fc4_xpt_flags |= NVME_XPT_REGD;
spin_unlock_irq(&ndlp->lock);
rport = remote_port->private;
@@ -2336,7 +2370,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
*/
spin_lock_irq(&ndlp->lock);
ndlp->nrport = NULL;
- ndlp->fc4_xpt_flags &= ~NLP_WAIT_FOR_UNREG;
+ ndlp->fc4_xpt_flags &= ~NVME_XPT_UNREG_WAIT;
spin_unlock_irq(&ndlp->lock);
rport->ndlp = NULL;
rport->remoteport = NULL;
@@ -2488,7 +2522,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* The transport will update it.
*/
spin_lock_irq(&vport->phba->hbalock);
- ndlp->fc4_xpt_flags |= NLP_WAIT_FOR_UNREG;
+ ndlp->fc4_xpt_flags |= NVME_XPT_UNREG_WAIT;
spin_unlock_irq(&vport->phba->hbalock);
/* Don't let the host nvme transport keep sending keep-alives
diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h
index 69a5a844c69c..cc54ffb5c205 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.h
+++ b/drivers/scsi/lpfc/lpfc_nvme.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -34,11 +34,8 @@
#define LPFC_NVME_FB_SHIFT 9
#define LPFC_NVME_MAX_FB (1 << 20) /* 1M */
-#define LPFC_MAX_NVME_INFO_TMP_LEN 100
-#define LPFC_NVME_INFO_MORE_STR "\nCould be more info...\n"
-
-#define lpfc_ndlp_get_nrport(ndlp) \
- ((!ndlp->nrport || (ndlp->fc4_xpt_flags & NLP_WAIT_FOR_UNREG)) \
+#define lpfc_ndlp_get_nrport(ndlp) \
+ ((!ndlp->nrport || (ndlp->fc4_xpt_flags & NVME_XPT_UNREG_WAIT))\
? NULL : ndlp->nrport)
struct lpfc_nvme_qhandle {
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index f2d9a3580887..6e3dd0b9bcfa 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -1797,19 +1797,22 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
if (ctxp->ctxbuf->sglq->sli4_xritag != xri)
continue;
- spin_lock(&ctxp->ctxlock);
+ spin_unlock_irqrestore(&phba->sli4_hba.abts_nvmet_buf_list_lock,
+ iflag);
+
+ spin_lock_irqsave(&ctxp->ctxlock, iflag);
/* Check if we already received a free context call
* and we have completed processing an abort situation.
*/
if (ctxp->flag & LPFC_NVME_CTX_RLS &&
!(ctxp->flag & LPFC_NVME_ABORT_OP)) {
+ spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
list_del_init(&ctxp->list);
+ spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
released = true;
}
ctxp->flag &= ~LPFC_NVME_XBUSY;
- spin_unlock(&ctxp->ctxlock);
- spin_unlock_irqrestore(&phba->sli4_hba.abts_nvmet_buf_list_lock,
- iflag);
+ spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
rrq_empty = list_empty(&phba->active_rrq_list);
ndlp = lpfc_findnode_did(phba->pport, ctxp->sid);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 1b248c237be1..0fde1e874c7a 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -96,30 +96,6 @@ static void lpfc_vmid_update_entry(struct lpfc_vport *vport, struct scsi_cmnd
static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport,
struct lpfc_vmid *vmid);
-static inline unsigned
-lpfc_cmd_blksize(struct scsi_cmnd *sc)
-{
- return sc->device->sector_size;
-}
-
-#define LPFC_CHECK_PROTECT_GUARD 1
-#define LPFC_CHECK_PROTECT_REF 2
-static inline unsigned
-lpfc_cmd_protect(struct scsi_cmnd *sc, int flag)
-{
- return 1;
-}
-
-static inline unsigned
-lpfc_cmd_guard_csum(struct scsi_cmnd *sc)
-{
- if (lpfc_prot_group_type(NULL, sc) == LPFC_PG_TYPE_NO_DIF)
- return 0;
- if (scsi_host_get_guard(sc->device->host) == SHOST_DIX_GUARD_IP)
- return 1;
- return 0;
-}
-
/**
* lpfc_sli4_set_rsp_sgl_last - Set the last bit in the response sge.
* @phba: Pointer to HBA object.
@@ -683,7 +659,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
cpu = raw_smp_processor_id();
if (cmnd && phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ) {
- tag = blk_mq_unique_tag(cmnd->request);
+ tag = blk_mq_unique_tag(scsi_cmd_to_rq(cmnd));
idx = blk_mq_unique_tag_to_hwq(tag);
} else {
idx = phba->sli4_hba.cpu_map[cpu].hdwq;
@@ -1046,13 +1022,13 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
return 0;
sgpe = scsi_prot_sglist(sc);
- lba = t10_pi_ref_tag(sc->request);
+ lba = scsi_prot_ref_tag(sc);
if (lba == LPFC_INVALID_REFTAG)
return 0;
/* First check if we need to match the LBA */
if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) {
- blksize = lpfc_cmd_blksize(sc);
+ blksize = scsi_prot_interval(sc);
numblks = (scsi_bufflen(sc) + blksize - 1) / blksize;
/* Make sure we have the right LBA if one is specified */
@@ -1441,7 +1417,7 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
{
uint8_t ret = 0;
- if (lpfc_cmd_guard_csum(sc)) {
+ if (sc->prot_flags & SCSI_PROT_IP_CHECKSUM) {
switch (scsi_get_prot_op(sc)) {
case SCSI_PROT_READ_INSERT:
case SCSI_PROT_WRITE_STRIP:
@@ -1521,7 +1497,7 @@ lpfc_bg_err_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
{
uint8_t ret = 0;
- if (lpfc_cmd_guard_csum(sc)) {
+ if (sc->prot_flags & SCSI_PROT_IP_CHECKSUM) {
switch (scsi_get_prot_op(sc)) {
case SCSI_PROT_READ_INSERT:
case SCSI_PROT_WRITE_STRIP:
@@ -1629,7 +1605,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
goto out;
/* extract some info from the scsi command for pde*/
- reftag = t10_pi_ref_tag(sc->request);
+ reftag = scsi_prot_ref_tag(sc);
if (reftag == LPFC_INVALID_REFTAG)
goto out;
@@ -1668,12 +1644,12 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
* protection data is automatically generated, not checked.
*/
if (datadir == DMA_FROM_DEVICE) {
- if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD))
+ if (sc->prot_flags & SCSI_PROT_GUARD_CHECK)
bf_set(pde6_ce, pde6, checking);
else
bf_set(pde6_ce, pde6, 0);
- if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF))
+ if (sc->prot_flags & SCSI_PROT_REF_CHECK)
bf_set(pde6_re, pde6, checking);
else
bf_set(pde6_re, pde6, 0);
@@ -1791,8 +1767,8 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
goto out;
/* extract some info from the scsi command */
- blksize = lpfc_cmd_blksize(sc);
- reftag = t10_pi_ref_tag(sc->request);
+ blksize = scsi_prot_interval(sc);
+ reftag = scsi_prot_ref_tag(sc);
if (reftag == LPFC_INVALID_REFTAG)
goto out;
@@ -1832,12 +1808,12 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
bf_set(pde6_optx, pde6, txop);
bf_set(pde6_oprx, pde6, rxop);
- if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD))
+ if (sc->prot_flags & SCSI_PROT_GUARD_CHECK)
bf_set(pde6_ce, pde6, checking);
else
bf_set(pde6_ce, pde6, 0);
- if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF))
+ if (sc->prot_flags & SCSI_PROT_REF_CHECK)
bf_set(pde6_re, pde6, checking);
else
bf_set(pde6_re, pde6, 0);
@@ -2023,7 +1999,7 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
goto out;
/* extract some info from the scsi command for pde*/
- reftag = t10_pi_ref_tag(sc->request);
+ reftag = scsi_prot_ref_tag(sc);
if (reftag == LPFC_INVALID_REFTAG)
goto out;
@@ -2051,12 +2027,12 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
* protection data is automatically generated, not checked.
*/
if (sc->sc_data_direction == DMA_FROM_DEVICE) {
- if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD))
+ if (sc->prot_flags & SCSI_PROT_GUARD_CHECK)
bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
else
bf_set(lpfc_sli4_sge_dif_ce, diseed, 0);
- if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF))
+ if (sc->prot_flags & SCSI_PROT_REF_CHECK)
bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
else
bf_set(lpfc_sli4_sge_dif_re, diseed, 0);
@@ -2223,8 +2199,8 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
goto out;
/* extract some info from the scsi command */
- blksize = lpfc_cmd_blksize(sc);
- reftag = t10_pi_ref_tag(sc->request);
+ blksize = scsi_prot_interval(sc);
+ reftag = scsi_prot_ref_tag(sc);
if (reftag == LPFC_INVALID_REFTAG)
goto out;
@@ -2281,9 +2257,8 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
diseed->ref_tag = cpu_to_le32(reftag);
diseed->ref_tag_tran = diseed->ref_tag;
- if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD)) {
+ if (sc->prot_flags & SCSI_PROT_GUARD_CHECK) {
bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
-
} else {
bf_set(lpfc_sli4_sge_dif_ce, diseed, 0);
/*
@@ -2300,7 +2275,7 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
}
- if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF))
+ if (sc->prot_flags & SCSI_PROT_REF_CHECK)
bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
else
bf_set(lpfc_sli4_sge_dif_re, diseed, 0);
@@ -2557,7 +2532,7 @@ lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba,
* DIF (trailer) attached to it. Must ajust FCP data length
* to account for the protection data.
*/
- fcpdl += (fcpdl / lpfc_cmd_blksize(sc)) * 8;
+ fcpdl += (fcpdl / scsi_prot_interval(sc)) * 8;
return fcpdl;
}
@@ -2811,14 +2786,14 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
* data length is a multiple of the blksize.
*/
sgde = scsi_sglist(cmd);
- blksize = lpfc_cmd_blksize(cmd);
+ blksize = scsi_prot_interval(cmd);
data_src = (uint8_t *)sg_virt(sgde);
data_len = sgde->length;
if ((data_len & (blksize - 1)) == 0)
chk_guard = 1;
src = (struct scsi_dif_tuple *)sg_virt(sgpe);
- start_ref_tag = t10_pi_ref_tag(cmd->request);
+ start_ref_tag = scsi_prot_ref_tag(cmd);
if (start_ref_tag == LPFC_INVALID_REFTAG)
goto out;
start_app_tag = src->app_tag;
@@ -2839,7 +2814,8 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
/* First Guard Tag checking */
if (chk_guard) {
guard_tag = src->guard_tag;
- if (lpfc_cmd_guard_csum(cmd))
+ if (cmd->prot_flags
+ & SCSI_PROT_IP_CHECKSUM)
sum = lpfc_bg_csum(data_src,
blksize);
else
@@ -2910,7 +2886,7 @@ out:
phba->bg_guard_err_cnt++;
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
"9069 BLKGRD: reftag %x grd_tag err %x != %x\n",
- t10_pi_ref_tag(cmd->request),
+ scsi_prot_ref_tag(cmd),
sum, guard_tag);
} else if (err_type == BGS_REFTAG_ERR_MASK) {
@@ -2920,7 +2896,7 @@ out:
phba->bg_reftag_err_cnt++;
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
"9066 BLKGRD: reftag %x ref_tag err %x != %x\n",
- t10_pi_ref_tag(cmd->request),
+ scsi_prot_ref_tag(cmd),
ref_tag, start_ref_tag);
} else if (err_type == BGS_APPTAG_ERR_MASK) {
@@ -2930,7 +2906,7 @@ out:
phba->bg_apptag_err_cnt++;
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
"9041 BLKGRD: reftag %x app_tag err %x != %x\n",
- t10_pi_ref_tag(cmd->request),
+ scsi_prot_ref_tag(cmd),
app_tag, start_app_tag);
}
}
@@ -2992,7 +2968,7 @@ lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
" 0x%x lba 0x%llx blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
(unsigned long long)scsi_get_lba(cmd),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_logical_block_count(cmd), bgstat, bghm);
}
if (lpfc_bgs_get_reftag_err(bgstat)) {
@@ -3007,7 +2983,7 @@ lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
" 0x%x lba 0x%llx blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
(unsigned long long)scsi_get_lba(cmd),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_logical_block_count(cmd), bgstat, bghm);
}
if (lpfc_bgs_get_apptag_err(bgstat)) {
@@ -3022,7 +2998,7 @@ lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
" 0x%x lba 0x%llx blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
(unsigned long long)scsi_get_lba(cmd),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_logical_block_count(cmd), bgstat, bghm);
}
if (lpfc_bgs_get_hi_water_mark_present(bgstat)) {
@@ -3066,9 +3042,9 @@ lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
" 0x%x lba 0x%llx blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
(unsigned long long)scsi_get_lba(cmd),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_logical_block_count(cmd), bgstat, bghm);
- /* Calcuate what type of error it was */
+ /* Calculate what type of error it was */
lpfc_calc_bg_err(phba, lpfc_cmd);
}
return ret;
@@ -3103,8 +3079,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
"9072 BLKGRD: Invalid BG Profile in cmd "
"0x%x reftag 0x%x blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
- t10_pi_ref_tag(cmd->request),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_prot_ref_tag(cmd),
+ scsi_logical_block_count(cmd), bgstat, bghm);
ret = (-1);
goto out;
}
@@ -3115,8 +3091,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
"9073 BLKGRD: Invalid BG PDIF Block in cmd "
"0x%x reftag 0x%x blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
- t10_pi_ref_tag(cmd->request),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_prot_ref_tag(cmd),
+ scsi_logical_block_count(cmd), bgstat, bghm);
ret = (-1);
goto out;
}
@@ -3131,8 +3107,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
"9055 BLKGRD: Guard Tag error in cmd "
"0x%x reftag 0x%x blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
- t10_pi_ref_tag(cmd->request),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_prot_ref_tag(cmd),
+ scsi_logical_block_count(cmd), bgstat, bghm);
}
if (lpfc_bgs_get_reftag_err(bgstat)) {
@@ -3146,8 +3122,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
"9056 BLKGRD: Ref Tag error in cmd "
"0x%x reftag 0x%x blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
- t10_pi_ref_tag(cmd->request),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_prot_ref_tag(cmd),
+ scsi_logical_block_count(cmd), bgstat, bghm);
}
if (lpfc_bgs_get_apptag_err(bgstat)) {
@@ -3161,8 +3137,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
"9061 BLKGRD: App Tag error in cmd "
"0x%x reftag 0x%x blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
- t10_pi_ref_tag(cmd->request),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_prot_ref_tag(cmd),
+ scsi_logical_block_count(cmd), bgstat, bghm);
}
if (lpfc_bgs_get_hi_water_mark_present(bgstat)) {
@@ -3205,10 +3181,10 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
"9057 BLKGRD: Unknown error in cmd "
"0x%x reftag 0x%x blk cnt 0x%x "
"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
- t10_pi_ref_tag(cmd->request),
- blk_rq_sectors(cmd->request), bgstat, bghm);
+ scsi_prot_ref_tag(cmd),
+ scsi_logical_block_count(cmd), bgstat, bghm);
- /* Calcuate what type of error it was */
+ /* Calculate what type of error it was */
lpfc_calc_bg_err(phba, lpfc_cmd);
}
out:
@@ -3854,6 +3830,143 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba *phba, struct lpfc_io_buf *psb)
}
/**
+ * lpfc_unblock_requests - allow further commands to be queued.
+ * @phba: pointer to phba object
+ *
+ * For single vport, just call scsi_unblock_requests on physical port.
+ * For multiple vports, send scsi_unblock_requests for all the vports.
+ */
+void
+lpfc_unblock_requests(struct lpfc_hba *phba)
+{
+ struct lpfc_vport **vports;
+ struct Scsi_Host *shost;
+ int i;
+
+ if (phba->sli_rev == LPFC_SLI_REV4 &&
+ !phba->sli4_hba.max_cfg_param.vpi_used) {
+ shost = lpfc_shost_from_vport(phba->pport);
+ scsi_unblock_requests(shost);
+ return;
+ }
+
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports != NULL)
+ for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
+ shost = lpfc_shost_from_vport(vports[i]);
+ scsi_unblock_requests(shost);
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+}
+
+/**
+ * lpfc_block_requests - prevent further commands from being queued.
+ * @phba: pointer to phba object
+ *
+ * For single vport, just call scsi_block_requests on physical port.
+ * For multiple vports, send scsi_block_requests for all the vports.
+ */
+void
+lpfc_block_requests(struct lpfc_hba *phba)
+{
+ struct lpfc_vport **vports;
+ struct Scsi_Host *shost;
+ int i;
+
+ if (atomic_read(&phba->cmf_stop_io))
+ return;
+
+ if (phba->sli_rev == LPFC_SLI_REV4 &&
+ !phba->sli4_hba.max_cfg_param.vpi_used) {
+ shost = lpfc_shost_from_vport(phba->pport);
+ scsi_block_requests(shost);
+ return;
+ }
+
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports != NULL)
+ for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
+ shost = lpfc_shost_from_vport(vports[i]);
+ scsi_block_requests(shost);
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+}
+
+/**
+ * lpfc_update_cmf_cmpl - Adjust CMF counters for IO completion
+ * @phba: The HBA for which this call is being executed.
+ * @time: The latency of the IO that completed (in ns)
+ * @size: The size of the IO that completed
+ * @shost: SCSI host the IO completed on (NULL for a NVME IO)
+ *
+ * The routine adjusts the various Burst and Bandwidth counters used in
+ * Congestion management and E2E. If time is set to LPFC_CGN_NOT_SENT,
+ * that means the IO was never issued to the HBA, so this routine is
+ * just being called to cleanup the counter from a previous
+ * lpfc_update_cmf_cmd call.
+ */
+int
+lpfc_update_cmf_cmpl(struct lpfc_hba *phba,
+ uint64_t time, uint32_t size, struct Scsi_Host *shost)
+{
+ struct lpfc_cgn_stat *cgs;
+
+ if (time != LPFC_CGN_NOT_SENT) {
+ /* lat is ns coming in, save latency in us */
+ if (time < 1000)
+ time = 1;
+ else
+ time = div_u64(time + 500, 1000); /* round it */
+
+ cgs = this_cpu_ptr(phba->cmf_stat);
+ atomic64_add(size, &cgs->rcv_bytes);
+ atomic64_add(time, &cgs->rx_latency);
+ atomic_inc(&cgs->rx_io_cnt);
+ }
+ return 0;
+}
+
+/**
+ * lpfc_update_cmf_cmd - Adjust CMF counters for IO submission
+ * @phba: The HBA for which this call is being executed.
+ * @size: The size of the IO that will be issued
+ *
+ * The routine adjusts the various Burst and Bandwidth counters used in
+ * Congestion management and E2E.
+ */
+int
+lpfc_update_cmf_cmd(struct lpfc_hba *phba, uint32_t size)
+{
+ uint64_t total;
+ struct lpfc_cgn_stat *cgs;
+ int cpu;
+
+ /* At this point we are either LPFC_CFG_MANAGED or LPFC_CFG_MONITOR */
+ if (phba->cmf_active_mode == LPFC_CFG_MANAGED) {
+ total = 0;
+ for_each_present_cpu(cpu) {
+ cgs = per_cpu_ptr(phba->cmf_stat, cpu);
+ total += atomic64_read(&cgs->total_bytes);
+ }
+ if (total >= phba->cmf_max_bytes_per_interval) {
+ if (!atomic_xchg(&phba->cmf_bw_wait, 1)) {
+ lpfc_block_requests(phba);
+ phba->cmf_last_ts =
+ lpfc_calc_cmf_latency(phba);
+ }
+ atomic_inc(&phba->cmf_busy);
+ return -EBUSY;
+ }
+ if (size > atomic_read(&phba->rx_max_read_cnt))
+ atomic_set(&phba->rx_max_read_cnt, size);
+ }
+
+ cgs = this_cpu_ptr(phba->cmf_stat);
+ atomic64_add(size, &cgs->total_bytes);
+ return 0;
+}
+
+/**
* lpfc_handle_fcp_err - FCP response handler
* @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: Pointer to lpfc_io_buf data structure.
@@ -4063,6 +4176,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
u32 logit = LOG_FCP;
u32 status, idx;
unsigned long iflags = 0;
+ u32 lat;
u8 wait_xb_clr = 0;
/* Sanity check on return of outstanding command */
@@ -4351,10 +4465,21 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
lpfc_io_ktime(phba, lpfc_cmd);
}
#endif
+ if (likely(!wait_xb_clr))
+ lpfc_cmd->pCmd = NULL;
+ spin_unlock(&lpfc_cmd->buf_lock);
+
+ /* Check if IO qualified for CMF */
+ if (phba->cmf_active_mode != LPFC_CFG_OFF &&
+ cmd->sc_data_direction == DMA_FROM_DEVICE &&
+ (scsi_sg_count(cmd))) {
+ /* Used when calculating average latency */
+ lat = ktime_get_ns() - lpfc_cmd->rx_cmd_start;
+ lpfc_update_cmf_cmpl(phba, lat, scsi_bufflen(cmd), shost);
+ }
+
if (wait_xb_clr)
goto out;
- lpfc_cmd->pCmd = NULL;
- spin_unlock(&lpfc_cmd->buf_lock);
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
cmd->scsi_done(cmd);
@@ -4367,8 +4492,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED;
if (lpfc_cmd->waitq)
wake_up(lpfc_cmd->waitq);
-out:
spin_unlock(&lpfc_cmd->buf_lock);
+out:
lpfc_release_scsi_buf(phba, lpfc_cmd);
}
@@ -4775,6 +4900,11 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport,
fcp_cmnd->fcpCntl3 = READ_DATA;
if (hdwq)
hdwq->scsi_cstat.input_requests++;
+
+ /* For a CMF Managed port, iod must be zero'ed */
+ if (phba->cmf_active_mode == LPFC_CFG_MANAGED)
+ bf_set(wqe_iod, &wqe->fcp_iread.wqe_com,
+ LPFC_WQE_IOD_NONE);
}
} else {
/* From the icmnd template, initialize words 4 - 11 */
@@ -5029,12 +5159,8 @@ lpfc_check_pci_resettable(struct lpfc_hba *phba)
}
/* Check for valid Emulex Device ID */
- switch (ptr->device) {
- case PCI_DEVICE_ID_LANCER_FC:
- case PCI_DEVICE_ID_LANCER_G6_FC:
- case PCI_DEVICE_ID_LANCER_G7_FC:
- break;
- default:
+ if (phba->sli_rev != LPFC_SLI_REV4 ||
+ phba->hba_flag & HBA_FCOE_MODE) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"8347 Incapable PCI reset device: "
"0x%04x\n", ptr->device);
@@ -5423,13 +5549,9 @@ static int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct
*/
static char *lpfc_is_command_vm_io(struct scsi_cmnd *cmd)
{
- char *uuid = NULL;
+ struct bio *bio = scsi_cmd_to_rq(cmd)->bio;
- if (cmd->request) {
- if (cmd->request->bio)
- uuid = blkcg_get_fc_appid(cmd->request->bio);
- }
- return uuid;
+ return bio ? blkcg_get_fc_appid(bio) : NULL;
}
/**
@@ -5462,7 +5584,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
if (phba->ktime_on)
start = ktime_get_ns();
#endif
-
+ start = ktime_get_ns();
rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
/* sanity check on references */
@@ -5493,7 +5615,18 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
* transport is still transitioning.
*/
if (!ndlp)
- goto out_tgt_busy;
+ goto out_tgt_busy1;
+
+ /* Check if IO qualifies for CMF */
+ if (phba->cmf_active_mode != LPFC_CFG_OFF &&
+ cmnd->sc_data_direction == DMA_FROM_DEVICE &&
+ (scsi_sg_count(cmnd))) {
+ /* Latency start time saved in rx_cmd_start later in routine */
+ err = lpfc_update_cmf_cmd(phba, scsi_bufflen(cmnd));
+ if (err)
+ goto out_tgt_busy1;
+ }
+
if (lpfc_ndlp_check_qdepth(phba, ndlp)) {
if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR,
@@ -5521,7 +5654,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
ndlp->nlp_portname.u.wwn[5],
ndlp->nlp_portname.u.wwn[6],
ndlp->nlp_portname.u.wwn[7]);
- goto out_tgt_busy;
+ goto out_tgt_busy2;
}
}
@@ -5534,6 +5667,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
"IO busied\n");
goto out_host_busy;
}
+ lpfc_cmd->rx_cmd_start = start;
/*
* Store the midlayer's command structure for the completion phase
@@ -5557,8 +5691,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
"reftag x%x cnt %u pt %x\n",
dif_op_str[scsi_get_prot_op(cmnd)],
cmnd->cmnd[0],
- t10_pi_ref_tag(cmnd->request),
- blk_rq_sectors(cmnd->request),
+ scsi_prot_ref_tag(cmnd),
+ scsi_logical_block_count(cmnd),
(cmnd->cmnd[1]>>5));
}
err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd);
@@ -5569,8 +5703,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
"9038 BLKGRD: rcvd PROT_NORMAL cmd: "
"x%x reftag x%x cnt %u pt %x\n",
cmnd->cmnd[0],
- t10_pi_ref_tag(cmnd->request),
- blk_rq_sectors(cmnd->request),
+ scsi_prot_ref_tag(cmnd),
+ scsi_logical_block_count(cmnd),
(cmnd->cmnd[1]>>5));
}
err = lpfc_scsi_prep_dma_buf(phba, lpfc_cmd);
@@ -5641,8 +5775,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
bf_get(wqe_tmo,
&lpfc_cmd->cur_iocbq.wqe.generic.wqe_com) :
lpfc_cmd->cur_iocbq.iocb.ulpTimeout,
- (uint32_t)
- (cmnd->request->timeout / 1000));
+ (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000));
goto out_host_busy_free_buf;
}
@@ -5678,13 +5811,20 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
out_host_busy_release_buf:
lpfc_release_scsi_buf(phba, lpfc_cmd);
out_host_busy:
+ lpfc_update_cmf_cmpl(phba, LPFC_CGN_NOT_SENT, scsi_bufflen(cmnd),
+ shost);
return SCSI_MLQUEUE_HOST_BUSY;
- out_tgt_busy:
+ out_tgt_busy2:
+ lpfc_update_cmf_cmpl(phba, LPFC_CGN_NOT_SENT, scsi_bufflen(cmnd),
+ shost);
+ out_tgt_busy1:
return SCSI_MLQUEUE_TARGET_BUSY;
out_fail_command_release_buf:
lpfc_release_scsi_buf(phba, lpfc_cmd);
+ lpfc_update_cmf_cmpl(phba, LPFC_CGN_NOT_SENT, scsi_bufflen(cmnd),
+ shost);
out_fail_command:
cmnd->scsi_done(cmnd);
@@ -6273,6 +6413,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
struct lpfc_scsi_event_header scsi_event;
int status;
u32 logit = LOG_FCP;
+ u32 dev_loss_tmo = vport->cfg_devloss_tmo;
unsigned long flags;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
@@ -6314,39 +6455,44 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id,
FCP_TARGET_RESET);
- if (status != SUCCESS)
- logit = LOG_TRACE_EVENT;
- spin_lock_irqsave(&pnode->lock, flags);
- if (status != SUCCESS &&
- (!(pnode->upcall_flags & NLP_WAIT_FOR_LOGO)) &&
- !pnode->logo_waitq) {
- pnode->logo_waitq = &waitq;
- pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
- pnode->nlp_flag |= NLP_ISSUE_LOGO;
- pnode->upcall_flags |= NLP_WAIT_FOR_LOGO;
- spin_unlock_irqrestore(&pnode->lock, flags);
- lpfc_unreg_rpi(vport, pnode);
- wait_event_timeout(waitq,
- (!(pnode->upcall_flags & NLP_WAIT_FOR_LOGO)),
- msecs_to_jiffies(vport->cfg_devloss_tmo *
- 1000));
-
- if (pnode->upcall_flags & NLP_WAIT_FOR_LOGO) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
- "0725 SCSI layer TGTRST failed & LOGO TMO "
- " (%d, %llu) return x%x\n", tgt_id,
- lun_id, status);
- spin_lock_irqsave(&pnode->lock, flags);
- pnode->upcall_flags &= ~NLP_WAIT_FOR_LOGO;
+ if (status != SUCCESS) {
+ logit = LOG_TRACE_EVENT;
+
+ /* Issue LOGO, if no LOGO is outstanding */
+ spin_lock_irqsave(&pnode->lock, flags);
+ if (!(pnode->upcall_flags & NLP_WAIT_FOR_LOGO) &&
+ !pnode->logo_waitq) {
+ pnode->logo_waitq = &waitq;
+ pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
+ pnode->nlp_flag |= NLP_ISSUE_LOGO;
+ pnode->upcall_flags |= NLP_WAIT_FOR_LOGO;
+ spin_unlock_irqrestore(&pnode->lock, flags);
+ lpfc_unreg_rpi(vport, pnode);
+ wait_event_timeout(waitq,
+ (!(pnode->upcall_flags &
+ NLP_WAIT_FOR_LOGO)),
+ msecs_to_jiffies(dev_loss_tmo *
+ 1000));
+
+ if (pnode->upcall_flags & NLP_WAIT_FOR_LOGO) {
+ lpfc_printf_vlog(vport, KERN_ERR, logit,
+ "0725 SCSI layer TGTRST "
+ "failed & LOGO TMO (%d, %llu) "
+ "return x%x\n",
+ tgt_id, lun_id, status);
+ spin_lock_irqsave(&pnode->lock, flags);
+ pnode->upcall_flags &= ~NLP_WAIT_FOR_LOGO;
+ } else {
+ spin_lock_irqsave(&pnode->lock, flags);
+ }
+ pnode->logo_waitq = NULL;
+ spin_unlock_irqrestore(&pnode->lock, flags);
+ status = SUCCESS;
+
} else {
- spin_lock_irqsave(&pnode->lock, flags);
+ spin_unlock_irqrestore(&pnode->lock, flags);
+ status = FAILED;
}
- pnode->logo_waitq = NULL;
- spin_unlock_irqrestore(&pnode->lock, flags);
- status = SUCCESS;
- } else {
- status = FAILED;
- spin_unlock_irqrestore(&pnode->lock, flags);
}
lpfc_printf_vlog(vport, KERN_ERR, logit,
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index f76667b7da7b..3836d7f6a575 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -142,6 +142,10 @@ struct lpfc_scsicmd_bkt {
#define FC_PORTSPEED_128GBIT 0x2000
#endif
+#ifndef FC_PORTSPEED_256GBIT
+#define FC_PORTSPEED_256GBIT 0x4000
+#endif
+
#define TXRDY_PAYLOAD_LEN 12
/* For sysfs/debugfs tmp string max len */
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index f530d8fe7a8c..ffd8a140638c 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1439,7 +1439,7 @@ out:
memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean);
iocbq->sli4_lxritag = NO_XRI;
iocbq->sli4_xritag = NO_XRI;
- iocbq->iocb_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET |
+ iocbq->iocb_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF |
LPFC_IO_NVME_LS);
list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
}
@@ -1769,6 +1769,254 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
}
/**
+ * lpfc_cmf_sync_cmpl - Process a CMF_SYNC_WQE cmpl
+ * @phba: Pointer to HBA context object.
+ * @cmdiocb: Pointer to driver command iocb object.
+ * @cmf_cmpl: Pointer to completed WCQE.
+ *
+ * This routine will inform the driver of any BW adjustments we need
+ * to make. These changes will be picked up during the next CMF
+ * timer interrupt. In addition, any BW changes will be logged
+ * with LOG_CGN_MGMT.
+ **/
+static void
+lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ struct lpfc_wcqe_complete *cmf_cmpl)
+{
+ union lpfc_wqe128 *wqe;
+ uint32_t status, info;
+ uint64_t bw, bwdif, slop;
+ uint64_t pcent, bwpcent;
+ int asig, afpin, sigcnt, fpincnt;
+ int wsigmax, wfpinmax, cg, tdp;
+ char *s;
+
+ /* First check for error */
+ status = bf_get(lpfc_wcqe_c_status, cmf_cmpl);
+ if (status) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6211 CMF_SYNC_WQE Error "
+ "req_tag x%x status x%x hwstatus x%x "
+ "tdatap x%x parm x%x\n",
+ bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl),
+ bf_get(lpfc_wcqe_c_status, cmf_cmpl),
+ bf_get(lpfc_wcqe_c_hw_status, cmf_cmpl),
+ cmf_cmpl->total_data_placed,
+ cmf_cmpl->parameter);
+ goto out;
+ }
+
+ /* Gather congestion information on a successful cmpl */
+ info = cmf_cmpl->parameter;
+ phba->cmf_active_info = info;
+
+ /* See if firmware info count is valid or has changed */
+ if (info > LPFC_MAX_CMF_INFO || phba->cmf_info_per_interval == info)
+ info = 0;
+ else
+ phba->cmf_info_per_interval = info;
+
+ tdp = bf_get(lpfc_wcqe_c_cmf_bw, cmf_cmpl);
+ cg = bf_get(lpfc_wcqe_c_cmf_cg, cmf_cmpl);
+
+ /* Get BW requirement from firmware */
+ bw = (uint64_t)tdp * LPFC_CMF_BLK_SIZE;
+ if (!bw) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6212 CMF_SYNC_WQE x%x: NULL bw\n",
+ bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl));
+ goto out;
+ }
+
+ /* Gather information needed for logging if a BW change is required */
+ wqe = &cmdiocb->wqe;
+ asig = bf_get(cmf_sync_asig, &wqe->cmf_sync);
+ afpin = bf_get(cmf_sync_afpin, &wqe->cmf_sync);
+ fpincnt = bf_get(cmf_sync_wfpincnt, &wqe->cmf_sync);
+ sigcnt = bf_get(cmf_sync_wsigcnt, &wqe->cmf_sync);
+ if (phba->cmf_max_bytes_per_interval != bw ||
+ (asig || afpin || sigcnt || fpincnt)) {
+ /* Are we increasing or decreasing BW */
+ if (phba->cmf_max_bytes_per_interval < bw) {
+ bwdif = bw - phba->cmf_max_bytes_per_interval;
+ s = "Increase";
+ } else {
+ bwdif = phba->cmf_max_bytes_per_interval - bw;
+ s = "Decrease";
+ }
+
+ /* What is the change percentage */
+ slop = div_u64(phba->cmf_link_byte_count, 200); /*For rounding*/
+ pcent = div64_u64(bwdif * 100 + slop,
+ phba->cmf_link_byte_count);
+ bwpcent = div64_u64(bw * 100 + slop,
+ phba->cmf_link_byte_count);
+ if (asig) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6237 BW Threshold %lld%% (%lld): "
+ "%lld%% %s: Signal Alarm: cg:%d "
+ "Info:%u\n",
+ bwpcent, bw, pcent, s, cg,
+ phba->cmf_active_info);
+ } else if (afpin) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6238 BW Threshold %lld%% (%lld): "
+ "%lld%% %s: FPIN Alarm: cg:%d "
+ "Info:%u\n",
+ bwpcent, bw, pcent, s, cg,
+ phba->cmf_active_info);
+ } else if (sigcnt) {
+ wsigmax = bf_get(cmf_sync_wsigmax, &wqe->cmf_sync);
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6239 BW Threshold %lld%% (%lld): "
+ "%lld%% %s: Signal Warning: "
+ "Cnt %d Max %d: cg:%d Info:%u\n",
+ bwpcent, bw, pcent, s, sigcnt,
+ wsigmax, cg, phba->cmf_active_info);
+ } else if (fpincnt) {
+ wfpinmax = bf_get(cmf_sync_wfpinmax, &wqe->cmf_sync);
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6240 BW Threshold %lld%% (%lld): "
+ "%lld%% %s: FPIN Warning: "
+ "Cnt %d Max %d: cg:%d Info:%u\n",
+ bwpcent, bw, pcent, s, fpincnt,
+ wfpinmax, cg, phba->cmf_active_info);
+ } else {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6241 BW Threshold %lld%% (%lld): "
+ "CMF %lld%% %s: cg:%d Info:%u\n",
+ bwpcent, bw, pcent, s, cg,
+ phba->cmf_active_info);
+ }
+ } else if (info) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6246 Info Threshold %u\n", info);
+ }
+
+ /* Save BW change to be picked up during next timer interrupt */
+ phba->cmf_last_sync_bw = bw;
+out:
+ lpfc_sli_release_iocbq(phba, cmdiocb);
+}
+
+/**
+ * lpfc_issue_cmf_sync_wqe - Issue a CMF_SYNC_WQE
+ * @phba: Pointer to HBA context object.
+ * @ms: ms to set in WQE interval, 0 means use init op
+ * @total: Total rcv bytes for this interval
+ *
+ * This routine is called every CMF timer interrupt. Its purpose is
+ * to issue a CMF_SYNC_WQE to the firmware to inform it of any events
+ * that may indicate we have congestion (FPINs or Signals). Upon
+ * completion, the firmware will indicate any BW restrictions the
+ * driver may need to take.
+ **/
+int
+lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
+{
+ union lpfc_wqe128 *wqe;
+ struct lpfc_iocbq *sync_buf;
+ unsigned long iflags;
+ u32 ret_val;
+ u32 atot, wtot, max;
+
+ /* First address any alarm / warning activity */
+ atot = atomic_xchg(&phba->cgn_sync_alarm_cnt, 0);
+ wtot = atomic_xchg(&phba->cgn_sync_warn_cnt, 0);
+
+ /* ONLY Managed mode will send the CMF_SYNC_WQE to the HBA */
+ if (phba->cmf_active_mode != LPFC_CFG_MANAGED ||
+ phba->link_state == LPFC_LINK_DOWN)
+ return 0;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ sync_buf = __lpfc_sli_get_iocbq(phba);
+ if (!sync_buf) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
+ "6213 No available WQEs for CMF_SYNC_WQE\n");
+ ret_val = ENOMEM;
+ goto out_unlock;
+ }
+
+ wqe = &sync_buf->wqe;
+
+ /* WQEs are reused. Clear stale data and set key fields to zero */
+ memset(wqe, 0, sizeof(*wqe));
+
+ /* If this is the very first CMF_SYNC_WQE, issue an init operation */
+ if (!ms) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6441 CMF Init %d - CMF_SYNC_WQE\n",
+ phba->fc_eventTag);
+ bf_set(cmf_sync_op, &wqe->cmf_sync, 1); /* 1=init */
+ bf_set(cmf_sync_interval, &wqe->cmf_sync, LPFC_CMF_INTERVAL);
+ goto initpath;
+ }
+
+ bf_set(cmf_sync_op, &wqe->cmf_sync, 0); /* 0=recalc */
+ bf_set(cmf_sync_interval, &wqe->cmf_sync, ms);
+
+ /* Check for alarms / warnings */
+ if (atot) {
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
+ /* We hit an Signal alarm condition */
+ bf_set(cmf_sync_asig, &wqe->cmf_sync, 1);
+ } else {
+ /* We hit a FPIN alarm condition */
+ bf_set(cmf_sync_afpin, &wqe->cmf_sync, 1);
+ }
+ } else if (wtot) {
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY ||
+ phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
+ /* We hit an Signal warning condition */
+ max = LPFC_SEC_TO_MSEC / lpfc_fabric_cgn_frequency *
+ lpfc_acqe_cgn_frequency;
+ bf_set(cmf_sync_wsigmax, &wqe->cmf_sync, max);
+ bf_set(cmf_sync_wsigcnt, &wqe->cmf_sync, wtot);
+ } else {
+ /* We hit a FPIN warning condition */
+ bf_set(cmf_sync_wfpinmax, &wqe->cmf_sync, 1);
+ bf_set(cmf_sync_wfpincnt, &wqe->cmf_sync, 1);
+ }
+ }
+
+ /* Update total read blocks during previous timer interval */
+ wqe->cmf_sync.read_bytes = (u32)(total / LPFC_CMF_BLK_SIZE);
+
+initpath:
+ bf_set(cmf_sync_ver, &wqe->cmf_sync, LPFC_CMF_SYNC_VER);
+ wqe->cmf_sync.event_tag = phba->fc_eventTag;
+ bf_set(cmf_sync_cmnd, &wqe->cmf_sync, CMD_CMF_SYNC_WQE);
+
+ /* Setup reqtag to match the wqe completion. */
+ bf_set(cmf_sync_reqtag, &wqe->cmf_sync, sync_buf->iotag);
+
+ bf_set(cmf_sync_qosd, &wqe->cmf_sync, 1);
+
+ bf_set(cmf_sync_cmd_type, &wqe->cmf_sync, CMF_SYNC_COMMAND);
+ bf_set(cmf_sync_wqec, &wqe->cmf_sync, 1);
+ bf_set(cmf_sync_cqid, &wqe->cmf_sync, LPFC_WQE_CQ_ID_DEFAULT);
+
+ sync_buf->vport = phba->pport;
+ sync_buf->wqe_cmpl = lpfc_cmf_sync_cmpl;
+ sync_buf->iocb_cmpl = NULL;
+ sync_buf->context1 = NULL;
+ sync_buf->context2 = NULL;
+ sync_buf->context3 = NULL;
+ sync_buf->sli4_xritag = NO_XRI;
+
+ sync_buf->iocb_flag |= LPFC_IO_CMF;
+ ret_val = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], sync_buf);
+ if (ret_val)
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6214 Cannot issue CMF_SYNC_WQE: x%x\n",
+ ret_val);
+out_unlock:
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return ret_val;
+}
+
+/**
* lpfc_sli_next_iocb_slot - Get next iocb slot in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
@@ -4467,6 +4715,7 @@ lpfc_sli_brdready_s4(struct lpfc_hba *phba, uint32_t mask)
} else
phba->sli4_hba.intr_enable = 0;
+ phba->hba_flag &= ~HBA_SETUP;
return retval;
}
@@ -4787,6 +5036,7 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
phba->link_events = 0;
phba->pport->fc_myDID = 0;
phba->pport->fc_prevDID = 0;
+ phba->hba_flag &= ~HBA_SETUP;
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~(LPFC_PROCESS_LA);
@@ -5674,16 +5924,20 @@ lpfc_sli4_get_ctl_attr(struct lpfc_hba *phba)
bf_get(lpfc_cntl_attr_lnk_type, cntl_attr);
phba->sli4_hba.lnk_info.lnk_no =
bf_get(lpfc_cntl_attr_lnk_numb, cntl_attr);
+ phba->sli4_hba.flash_id = bf_get(lpfc_cntl_attr_flash_id, cntl_attr);
+ phba->sli4_hba.asic_rev = bf_get(lpfc_cntl_attr_asic_rev, cntl_attr);
memset(phba->BIOSVersion, 0, sizeof(phba->BIOSVersion));
strlcat(phba->BIOSVersion, (char *)cntl_attr->bios_ver_str,
sizeof(phba->BIOSVersion));
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "3086 lnk_type:%d, lnk_numb:%d, bios_ver:%s\n",
+ "3086 lnk_type:%d, lnk_numb:%d, bios_ver:%s, "
+ "flash_id: x%02x, asic_rev: x%02x\n",
phba->sli4_hba.lnk_info.lnk_tp,
phba->sli4_hba.lnk_info.lnk_no,
- phba->BIOSVersion);
+ phba->BIOSVersion, phba->sli4_hba.flash_id,
+ phba->sli4_hba.asic_rev);
out_free_mboxq:
if (bf_get(lpfc_mqe_command, &mboxq->u.mqe) == MBX_SLI4_CONFIG)
lpfc_sli4_mbox_cmd_free(phba, mboxq);
@@ -6413,6 +6667,7 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
uint32_t feature)
{
uint32_t len;
+ u32 sig_freq = 0;
len = sizeof(struct lpfc_mbx_set_feature) -
sizeof(struct lpfc_sli4_cfg_mhdr);
@@ -6435,6 +6690,35 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
mbox->u.mqe.un.set_feature.param_len = 8;
break;
+ case LPFC_SET_CGN_SIGNAL:
+ if (phba->cmf_active_mode == LPFC_CFG_OFF)
+ sig_freq = 0;
+ else
+ sig_freq = phba->cgn_sig_freq;
+
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
+ bf_set(lpfc_mbx_set_feature_CGN_alarm_freq,
+ &mbox->u.mqe.un.set_feature, sig_freq);
+ bf_set(lpfc_mbx_set_feature_CGN_warn_freq,
+ &mbox->u.mqe.un.set_feature, sig_freq);
+ }
+
+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY)
+ bf_set(lpfc_mbx_set_feature_CGN_warn_freq,
+ &mbox->u.mqe.un.set_feature, sig_freq);
+
+ if (phba->cmf_active_mode == LPFC_CFG_OFF ||
+ phba->cgn_reg_signal == EDC_CG_SIG_NOTSUPPORTED)
+ sig_freq = 0;
+ else
+ sig_freq = lpfc_acqe_cgn_frequency;
+
+ bf_set(lpfc_mbx_set_feature_CGN_acqe_freq,
+ &mbox->u.mqe.un.set_feature, sig_freq);
+
+ mbox->u.mqe.un.set_feature.feature = LPFC_SET_CGN_SIGNAL;
+ mbox->u.mqe.un.set_feature.param_len = 12;
+ break;
case LPFC_SET_DUAL_DUMP:
bf_set(lpfc_mbx_set_feature_dd,
&mbox->u.mqe.un.set_feature, LPFC_ENABLE_DUAL_DUMP);
@@ -6443,8 +6727,22 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
mbox->u.mqe.un.set_feature.feature = LPFC_SET_DUAL_DUMP;
mbox->u.mqe.un.set_feature.param_len = 4;
break;
+ case LPFC_SET_ENABLE_MI:
+ mbox->u.mqe.un.set_feature.feature = LPFC_SET_ENABLE_MI;
+ mbox->u.mqe.un.set_feature.param_len = 4;
+ bf_set(lpfc_mbx_set_feature_milunq, &mbox->u.mqe.un.set_feature,
+ phba->pport->cfg_lun_queue_depth);
+ bf_set(lpfc_mbx_set_feature_mi, &mbox->u.mqe.un.set_feature,
+ phba->sli4_hba.pc_sli4_params.mi_ver);
+ break;
+ case LPFC_SET_ENABLE_CMF:
+ bf_set(lpfc_mbx_set_feature_dd, &mbox->u.mqe.un.set_feature, 1);
+ mbox->u.mqe.un.set_feature.feature = LPFC_SET_ENABLE_CMF;
+ mbox->u.mqe.un.set_feature.param_len = 4;
+ bf_set(lpfc_mbx_set_feature_cmf,
+ &mbox->u.mqe.un.set_feature, 1);
+ break;
}
-
return;
}
@@ -7365,7 +7663,7 @@ lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
mbox->u.mqe.un.set_host_data.param_id = LPFC_SET_HOST_OS_DRIVER_VERSION;
mbox->u.mqe.un.set_host_data.param_len =
LPFC_HOST_OS_DRIVER_VERSION_SIZE;
- snprintf(mbox->u.mqe.un.set_host_data.data,
+ snprintf(mbox->u.mqe.un.set_host_data.un.data,
LPFC_HOST_OS_DRIVER_VERSION_SIZE,
"Linux %s v"LPFC_DRIVER_VERSION,
(phba->hba_flag & HBA_FCOE_MODE) ? "FCoE" : "FC");
@@ -7433,6 +7731,91 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
return 1;
}
+static void
+lpfc_mbx_cmpl_cgn_set_ftrs(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+{
+ struct lpfc_vport *vport = pmb->vport;
+ union lpfc_sli4_cfg_shdr *shdr;
+ u32 shdr_status, shdr_add_status;
+ u32 sig, acqe;
+
+ /* Two outcomes. (1) Set featurs was successul and EDC negotiation
+ * is done. (2) Mailbox failed and send FPIN support only.
+ */
+ shdr = (union lpfc_sli4_cfg_shdr *)
+ &pmb->u.mqe.un.sli4_config.header.cfg_shdr;
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+ if (shdr_status || shdr_add_status || pmb->u.mb.mbxStatus) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_CGN_MGMT,
+ "2516 CGN SET_FEATURE mbox failed with "
+ "status x%x add_status x%x, mbx status x%x "
+ "Reset Congestion to FPINs only\n",
+ shdr_status, shdr_add_status,
+ pmb->u.mb.mbxStatus);
+ /* If there is a mbox error, move on to RDF */
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_WARN | LPFC_CGN_FPIN_ALARM;
+ goto out;
+ }
+
+ /* Zero out Congestion Signal ACQE counter */
+ phba->cgn_acqe_cnt = 0;
+ atomic64_set(&phba->cgn_acqe_stat.warn, 0);
+ atomic64_set(&phba->cgn_acqe_stat.alarm, 0);
+
+ acqe = bf_get(lpfc_mbx_set_feature_CGN_acqe_freq,
+ &pmb->u.mqe.un.set_feature);
+ sig = bf_get(lpfc_mbx_set_feature_CGN_warn_freq,
+ &pmb->u.mqe.un.set_feature);
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "4620 SET_FEATURES Success: Freq: %ds %dms "
+ " Reg: x%x x%x\n", acqe, sig,
+ phba->cgn_reg_signal, phba->cgn_reg_fpin);
+out:
+ mempool_free(pmb, phba->mbox_mem_pool);
+
+ /* Register for FPIN events from the fabric now that the
+ * EDC common_set_features has completed.
+ */
+ lpfc_issue_els_rdf(vport, 0);
+}
+
+int
+lpfc_config_cgn_signal(struct lpfc_hba *phba)
+{
+ LPFC_MBOXQ_t *mboxq;
+ u32 rc;
+
+ mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mboxq)
+ goto out_rdf;
+
+ lpfc_set_features(phba, mboxq, LPFC_SET_CGN_SIGNAL);
+ mboxq->vport = phba->pport;
+ mboxq->mbox_cmpl = lpfc_mbx_cmpl_cgn_set_ftrs;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "4621 SET_FEATURES: FREQ sig x%x acqe x%x: "
+ "Reg: x%x x%x\n",
+ phba->cgn_sig_freq, lpfc_acqe_cgn_frequency,
+ phba->cgn_reg_signal, phba->cgn_reg_fpin);
+
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED)
+ goto out;
+ return 0;
+
+out:
+ mempool_free(mboxq, phba->mbox_mem_pool);
+out_rdf:
+ /* If there is a mbox error, move on to RDF */
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_WARN | LPFC_CGN_FPIN_ALARM;
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ lpfc_issue_els_rdf(phba->pport, 0);
+ return -EIO;
+}
+
/**
* lpfc_init_idle_stat_hb - Initialize idle_stat tracking
* @phba: pointer to lpfc hba data structure.
@@ -7464,7 +7847,8 @@ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba)
idle_stat->prev_idle = get_cpu_idle_time(i, &wall, 1);
idle_stat->prev_wall = wall;
- if (phba->nvmet_support)
+ if (phba->nvmet_support ||
+ phba->cmf_active_mode != LPFC_CFG_OFF)
cq->poll_mode = LPFC_QUEUE_WORK;
else
cq->poll_mode = LPFC_IRQ_POLL;
@@ -7496,6 +7880,258 @@ static void lpfc_sli4_dip(struct lpfc_hba *phba)
}
/**
+ * lpfc_cmf_setup - Initialize idle_stat tracking
+ * @phba: Pointer to HBA context object.
+ *
+ * This is called from HBA setup during driver load or when the HBA
+ * comes online. this does all the initialization to support CMF and MI.
+ **/
+static int
+lpfc_cmf_setup(struct lpfc_hba *phba)
+{
+ LPFC_MBOXQ_t *mboxq;
+ struct lpfc_mqe *mqe;
+ struct lpfc_dmabuf *mp;
+ struct lpfc_pc_sli4_params *sli4_params;
+ struct lpfc_sli4_parameters *mbx_sli4_parameters;
+ int length;
+ int rc, cmf, mi_ver;
+
+ mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mboxq)
+ return -ENOMEM;
+ mqe = &mboxq->u.mqe;
+
+ /* Read the port's SLI4 Config Parameters */
+ length = (sizeof(struct lpfc_mbx_get_sli4_parameters) -
+ sizeof(struct lpfc_sli4_cfg_mhdr));
+ lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS,
+ length, LPFC_SLI4_MBX_EMBED);
+
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ if (unlikely(rc)) {
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ return rc;
+ }
+
+ /* Gather info on CMF and MI support */
+ sli4_params = &phba->sli4_hba.pc_sli4_params;
+ mbx_sli4_parameters = &mqe->un.get_sli4_parameters.sli4_parameters;
+ sli4_params->mi_ver = bf_get(cfg_mi_ver, mbx_sli4_parameters);
+ sli4_params->cmf = bf_get(cfg_cmf, mbx_sli4_parameters);
+
+ /* Are we forcing MI off via module parameter? */
+ if (!phba->cfg_enable_mi)
+ sli4_params->mi_ver = 0;
+
+ /* Always try to enable MI feature if we can */
+ if (sli4_params->mi_ver) {
+ lpfc_set_features(phba, mboxq, LPFC_SET_ENABLE_MI);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ mi_ver = bf_get(lpfc_mbx_set_feature_mi,
+ &mboxq->u.mqe.un.set_feature);
+
+ if (rc == MBX_SUCCESS) {
+ if (mi_ver) {
+ lpfc_printf_log(phba,
+ KERN_WARNING, LOG_CGN_MGMT,
+ "6215 MI is enabled\n");
+ sli4_params->mi_ver = mi_ver;
+ } else {
+ lpfc_printf_log(phba,
+ KERN_WARNING, LOG_CGN_MGMT,
+ "6338 MI is disabled\n");
+ sli4_params->mi_ver = 0;
+ }
+ } else {
+ /* mi_ver is already set from GET_SLI4_PARAMETERS */
+ lpfc_printf_log(phba, KERN_INFO,
+ LOG_CGN_MGMT | LOG_INIT,
+ "6245 Enable MI Mailbox x%x (x%x/x%x) "
+ "failed, rc:x%x mi:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ lpfc_sli_config_mbox_subsys_get
+ (phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get
+ (phba, mboxq),
+ rc, sli4_params->mi_ver);
+ }
+ } else {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6217 MI is disabled\n");
+ }
+
+ /* Ensure FDMI is enabled for MI if enable_mi is set */
+ if (sli4_params->mi_ver)
+ phba->cfg_fdmi_on = LPFC_FDMI_SUPPORT;
+
+ /* Always try to enable CMF feature if we can */
+ if (sli4_params->cmf) {
+ lpfc_set_features(phba, mboxq, LPFC_SET_ENABLE_CMF);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ cmf = bf_get(lpfc_mbx_set_feature_cmf,
+ &mboxq->u.mqe.un.set_feature);
+ if (rc == MBX_SUCCESS && cmf) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6218 CMF is enabled: mode %d\n",
+ phba->cmf_active_mode);
+ } else {
+ lpfc_printf_log(phba, KERN_WARNING,
+ LOG_CGN_MGMT | LOG_INIT,
+ "6219 Enable CMF Mailbox x%x (x%x/x%x) "
+ "failed, rc:x%x dd:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ lpfc_sli_config_mbox_subsys_get
+ (phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get
+ (phba, mboxq),
+ rc, cmf);
+ sli4_params->cmf = 0;
+ phba->cmf_active_mode = LPFC_CFG_OFF;
+ goto no_cmf;
+ }
+
+ /* Allocate Congestion Information Buffer */
+ if (!phba->cgn_i) {
+ mp = kmalloc(sizeof(*mp), GFP_KERNEL);
+ if (mp)
+ mp->virt = dma_alloc_coherent
+ (&phba->pcidev->dev,
+ sizeof(struct lpfc_cgn_info),
+ &mp->phys, GFP_KERNEL);
+ if (!mp || !mp->virt) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2640 Failed to alloc memory "
+ "for Congestion Info\n");
+ kfree(mp);
+ sli4_params->cmf = 0;
+ phba->cmf_active_mode = LPFC_CFG_OFF;
+ goto no_cmf;
+ }
+ phba->cgn_i = mp;
+
+ /* initialize congestion buffer info */
+ lpfc_init_congestion_buf(phba);
+ lpfc_init_congestion_stat(phba);
+ }
+
+ rc = lpfc_sli4_cgn_params_read(phba);
+ if (rc < 0) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
+ "6242 Error reading Cgn Params (%d)\n",
+ rc);
+ /* Ensure CGN Mode is off */
+ sli4_params->cmf = 0;
+ } else if (!rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
+ "6243 CGN Event empty object.\n");
+ /* Ensure CGN Mode is off */
+ sli4_params->cmf = 0;
+ }
+ } else {
+no_cmf:
+ lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
+ "6220 CMF is disabled\n");
+ }
+
+ /* Only register congestion buffer with firmware if BOTH
+ * CMF and E2E are enabled.
+ */
+ if (sli4_params->cmf && sli4_params->mi_ver) {
+ rc = lpfc_reg_congestion_buf(phba);
+ if (rc) {
+ dma_free_coherent(&phba->pcidev->dev,
+ sizeof(struct lpfc_cgn_info),
+ phba->cgn_i->virt, phba->cgn_i->phys);
+ kfree(phba->cgn_i);
+ phba->cgn_i = NULL;
+ /* Ensure CGN Mode is off */
+ phba->cmf_active_mode = LPFC_CFG_OFF;
+ return 0;
+ }
+ }
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "6470 Setup MI version %d CMF %d mode %d\n",
+ sli4_params->mi_ver, sli4_params->cmf,
+ phba->cmf_active_mode);
+
+ mempool_free(mboxq, phba->mbox_mem_pool);
+
+ /* Initialize atomic counters */
+ atomic_set(&phba->cgn_fabric_warn_cnt, 0);
+ atomic_set(&phba->cgn_fabric_alarm_cnt, 0);
+ atomic_set(&phba->cgn_sync_alarm_cnt, 0);
+ atomic_set(&phba->cgn_sync_warn_cnt, 0);
+ atomic_set(&phba->cgn_driver_evt_cnt, 0);
+ atomic_set(&phba->cgn_latency_evt_cnt, 0);
+ atomic64_set(&phba->cgn_latency_evt, 0);
+
+ phba->cmf_interval_rate = LPFC_CMF_INTERVAL;
+
+ /* Allocate RX Monitor Buffer */
+ if (!phba->rxtable) {
+ phba->rxtable = kmalloc_array(LPFC_MAX_RXMONITOR_ENTRY,
+ sizeof(struct rxtable_entry),
+ GFP_KERNEL);
+ if (!phba->rxtable) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2644 Failed to alloc memory "
+ "for RX Monitor Buffer\n");
+ return -ENOMEM;
+ }
+ }
+ atomic_set(&phba->rxtable_idx_head, 0);
+ atomic_set(&phba->rxtable_idx_tail, 0);
+ return 0;
+}
+
+static int
+lpfc_set_host_tm(struct lpfc_hba *phba)
+{
+ LPFC_MBOXQ_t *mboxq;
+ uint32_t len, rc;
+ struct timespec64 cur_time;
+ struct tm broken;
+ uint32_t month, day, year;
+ uint32_t hour, minute, second;
+ struct lpfc_mbx_set_host_date_time *tm;
+
+ mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mboxq)
+ return -ENOMEM;
+
+ len = sizeof(struct lpfc_mbx_set_host_data) -
+ sizeof(struct lpfc_sli4_cfg_mhdr);
+ lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_SET_HOST_DATA, len,
+ LPFC_SLI4_MBX_EMBED);
+
+ mboxq->u.mqe.un.set_host_data.param_id = LPFC_SET_HOST_DATE_TIME;
+ mboxq->u.mqe.un.set_host_data.param_len =
+ sizeof(struct lpfc_mbx_set_host_date_time);
+ tm = &mboxq->u.mqe.un.set_host_data.un.tm;
+ ktime_get_real_ts64(&cur_time);
+ time64_to_tm(cur_time.tv_sec, 0, &broken);
+ month = broken.tm_mon + 1;
+ day = broken.tm_mday;
+ year = broken.tm_year - 100;
+ hour = broken.tm_hour;
+ minute = broken.tm_min;
+ second = broken.tm_sec;
+ bf_set(lpfc_mbx_set_host_month, tm, month);
+ bf_set(lpfc_mbx_set_host_day, tm, day);
+ bf_set(lpfc_mbx_set_host_year, tm, year);
+ bf_set(lpfc_mbx_set_host_hour, tm, hour);
+ bf_set(lpfc_mbx_set_host_min, tm, minute);
+ bf_set(lpfc_mbx_set_host_sec, tm, second);
+
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ return rc;
+}
+
+/**
* lpfc_sli4_hba_setup - SLI4 device initialization PCI function
* @phba: Pointer to HBA context object.
*
@@ -7584,6 +8220,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
goto out_free_mbox;
}
+ rc = lpfc_set_host_tm(phba);
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT,
+ "6468 Set host date / time: Status x%x:\n", rc);
+
/*
* Continue initialization with default values even if driver failed
* to read FCoE param config regions, only read parameters if the
@@ -8111,6 +8751,9 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
/* Indicate device interrupt mode */
phba->sli4_hba.intr_enable = 1;
+ /* Setup CMF after HBA is initialized */
+ lpfc_cmf_setup(phba);
+
if (!(phba->hba_flag & HBA_FCOE_MODE) &&
(phba->hba_flag & LINK_DISABLED)) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
@@ -8132,7 +8775,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
}
}
mempool_free(mboxq, phba->mbox_mem_pool);
+
+ phba->hba_flag |= HBA_SETUP;
return rc;
+
out_io_buff_free:
/* Free allocated IO Buffers */
lpfc_io_free(phba);
@@ -8790,8 +9436,11 @@ static int
lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
+ LPFC_MBOXQ_t *mboxq;
int rc = 0;
unsigned long timeout = 0;
+ u32 sli_flag;
+ u8 cmd, subsys, opcode;
/* Mark the asynchronous mailbox command posting as blocked */
spin_lock_irq(&phba->hbalock);
@@ -8809,12 +9458,37 @@ lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
if (timeout)
lpfc_sli4_process_missed_mbox_completions(phba);
- /* Wait for the outstnading mailbox command to complete */
+ /* Wait for the outstanding mailbox command to complete */
while (phba->sli.mbox_active) {
/* Check active mailbox complete status every 2ms */
msleep(2);
if (time_after(jiffies, timeout)) {
- /* Timeout, marked the outstanding cmd not complete */
+ /* Timeout, mark the outstanding cmd not complete */
+
+ /* Sanity check sli.mbox_active has not completed or
+ * cancelled from another context during last 2ms sleep,
+ * so take hbalock to be sure before logging.
+ */
+ spin_lock_irq(&phba->hbalock);
+ if (phba->sli.mbox_active) {
+ mboxq = phba->sli.mbox_active;
+ cmd = mboxq->u.mb.mbxCommand;
+ subsys = lpfc_sli_config_mbox_subsys_get(phba,
+ mboxq);
+ opcode = lpfc_sli_config_mbox_opcode_get(phba,
+ mboxq);
+ sli_flag = psli->sli_flag;
+ spin_unlock_irq(&phba->hbalock);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2352 Mailbox command x%x "
+ "(x%x/x%x) sli_flag x%x could "
+ "not complete\n",
+ cmd, subsys, opcode,
+ sli_flag);
+ } else {
+ spin_unlock_irq(&phba->hbalock);
+ }
+
rc = 1;
break;
}
@@ -9763,6 +10437,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
*pcmd == ELS_CMD_SCR ||
*pcmd == ELS_CMD_RDF ||
+ *pcmd == ELS_CMD_EDC ||
*pcmd == ELS_CMD_RSCN_XMT ||
*pcmd == ELS_CMD_FDISC ||
*pcmd == ELS_CMD_LOGO ||
@@ -10097,8 +10772,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0);
bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp,
phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
- pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
- iocbq->context2)->virt);
if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
bf_set(els_rsp64_sp, &wqe->xmit_els_rsp, 1);
bf_set(els_rsp64_sid, &wqe->xmit_els_rsp,
@@ -11619,6 +12292,7 @@ void
lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
+ struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
IOCB_t *irsp = &rspiocb->iocb;
/* ELS cmd tag <ulpIoTag> completes */
@@ -11627,11 +12301,16 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
"x%x x%x x%x\n",
irsp->ulpIoTag, irsp->ulpStatus,
irsp->un.ulpWord[4], irsp->ulpTimeout);
- lpfc_nlp_put((struct lpfc_nodelist *)cmdiocb->context1);
+ /*
+ * Deref the ndlp after free_iocb. sli_release_iocb will access the ndlp
+ * if exchange is busy.
+ */
if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR)
lpfc_ct_free_iocb(phba, cmdiocb);
else
lpfc_els_free_iocb(phba, cmdiocb);
+
+ lpfc_nlp_put(ndlp);
}
/**
@@ -14626,8 +15305,12 @@ static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba,
switch (cq->poll_mode) {
case LPFC_IRQ_POLL:
- irq_poll_sched(&cq->iop);
- break;
+ /* CGN mgmt is mutually exclusive from softirq processing */
+ if (phba->cmf_active_mode == LPFC_CFG_OFF) {
+ irq_poll_sched(&cq->iop);
+ break;
+ }
+ fallthrough;
case LPFC_QUEUE_WORK:
default:
if (is_kdump_kernel())
@@ -20021,6 +20704,91 @@ out:
}
/**
+ * lpfc_log_fw_write_cmpl - logs firmware write completion status
+ * @phba: pointer to lpfc hba data structure
+ * @shdr_status: wr_object rsp's status field
+ * @shdr_add_status: wr_object rsp's add_status field
+ * @shdr_add_status_2: wr_object rsp's add_status_2 field
+ * @shdr_change_status: wr_object rsp's change_status field
+ * @shdr_csf: wr_object rsp's csf bit
+ *
+ * This routine is intended to be called after a firmware write completes.
+ * It will log next action items to be performed by the user to instantiate
+ * the newly downloaded firmware or reason for incompatibility.
+ **/
+static void
+lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status,
+ u32 shdr_add_status, u32 shdr_add_status_2,
+ u32 shdr_change_status, u32 shdr_csf)
+{
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+ "4198 %s: flash_id x%02x, asic_rev x%02x, "
+ "status x%02x, add_status x%02x, add_status_2 x%02x, "
+ "change_status x%02x, csf %01x\n", __func__,
+ phba->sli4_hba.flash_id, phba->sli4_hba.asic_rev,
+ shdr_status, shdr_add_status, shdr_add_status_2,
+ shdr_change_status, shdr_csf);
+
+ if (shdr_add_status == LPFC_ADD_STATUS_INCOMPAT_OBJ) {
+ switch (shdr_add_status_2) {
+ case LPFC_ADD_STATUS_2_INCOMPAT_FLASH:
+ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+ "4199 Firmware write failed: "
+ "image incompatible with flash x%02x\n",
+ phba->sli4_hba.flash_id);
+ break;
+ case LPFC_ADD_STATUS_2_INCORRECT_ASIC:
+ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+ "4200 Firmware write failed: "
+ "image incompatible with ASIC "
+ "architecture x%02x\n",
+ phba->sli4_hba.asic_rev);
+ break;
+ default:
+ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+ "4210 Firmware write failed: "
+ "add_status_2 x%02x\n",
+ shdr_add_status_2);
+ break;
+ }
+ } else if (!shdr_status && !shdr_add_status) {
+ if (shdr_change_status == LPFC_CHANGE_STATUS_FW_RESET ||
+ shdr_change_status == LPFC_CHANGE_STATUS_PORT_MIGRATION) {
+ if (shdr_csf)
+ shdr_change_status =
+ LPFC_CHANGE_STATUS_PCI_RESET;
+ }
+
+ switch (shdr_change_status) {
+ case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET):
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+ "3198 Firmware write complete: System "
+ "reboot required to instantiate\n");
+ break;
+ case (LPFC_CHANGE_STATUS_FW_RESET):
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+ "3199 Firmware write complete: "
+ "Firmware reset required to "
+ "instantiate\n");
+ break;
+ case (LPFC_CHANGE_STATUS_PORT_MIGRATION):
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+ "3200 Firmware write complete: Port "
+ "Migration or PCI Reset required to "
+ "instantiate\n");
+ break;
+ case (LPFC_CHANGE_STATUS_PCI_RESET):
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+ "3201 Firmware write complete: PCI "
+ "Reset required to instantiate\n");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
* lpfc_wr_object - write an object to the firmware
* @phba: HBA structure that indicates port to create a queue on.
* @dmabuf_list: list of dmabufs to write to the port.
@@ -20046,7 +20814,8 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list,
struct lpfc_mbx_wr_object *wr_object;
LPFC_MBOXQ_t *mbox;
int rc = 0, i = 0;
- uint32_t shdr_status, shdr_add_status, shdr_change_status, shdr_csf;
+ uint32_t shdr_status, shdr_add_status, shdr_add_status_2;
+ uint32_t shdr_change_status = 0, shdr_csf = 0;
uint32_t mbox_tmo;
struct lpfc_dmabuf *dmabuf;
uint32_t written = 0;
@@ -20100,58 +20869,36 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list,
&wr_object->header.cfg_shdr.response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
&wr_object->header.cfg_shdr.response);
+ shdr_add_status_2 = bf_get(lpfc_mbox_hdr_add_status_2,
+ &wr_object->header.cfg_shdr.response);
if (check_change_status) {
shdr_change_status = bf_get(lpfc_wr_object_change_status,
&wr_object->u.response);
-
- if (shdr_change_status == LPFC_CHANGE_STATUS_FW_RESET ||
- shdr_change_status == LPFC_CHANGE_STATUS_PORT_MIGRATION) {
- shdr_csf = bf_get(lpfc_wr_object_csf,
- &wr_object->u.response);
- if (shdr_csf)
- shdr_change_status =
- LPFC_CHANGE_STATUS_PCI_RESET;
- }
-
- switch (shdr_change_status) {
- case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET):
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "3198 Firmware write complete: System "
- "reboot required to instantiate\n");
- break;
- case (LPFC_CHANGE_STATUS_FW_RESET):
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "3199 Firmware write complete: Firmware"
- " reset required to instantiate\n");
- break;
- case (LPFC_CHANGE_STATUS_PORT_MIGRATION):
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "3200 Firmware write complete: Port "
- "Migration or PCI Reset required to "
- "instantiate\n");
- break;
- case (LPFC_CHANGE_STATUS_PCI_RESET):
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "3201 Firmware write complete: PCI "
- "Reset required to instantiate\n");
- break;
- default:
- break;
- }
+ shdr_csf = bf_get(lpfc_wr_object_csf,
+ &wr_object->u.response);
}
+
if (!phba->sli4_hba.intr_enable)
mempool_free(mbox, phba->mbox_mem_pool);
else if (rc != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
- if (shdr_status || shdr_add_status || rc) {
+ if (shdr_status || shdr_add_status || shdr_add_status_2 || rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3025 Write Object mailbox failed with "
- "status x%x add_status x%x, mbx status x%x\n",
- shdr_status, shdr_add_status, rc);
+ "status x%x add_status x%x, add_status_2 x%x, "
+ "mbx status x%x\n",
+ shdr_status, shdr_add_status, shdr_add_status_2,
+ rc);
rc = -ENXIO;
*offset = shdr_add_status;
- } else
+ } else {
*offset += wr_object->u.response.actual_write_length;
+ }
+
+ if (rc || check_change_status)
+ lpfc_log_fw_write_cmpl(phba, shdr_status, shdr_add_status,
+ shdr_add_status_2, shdr_change_status,
+ shdr_csf);
return rc;
}
@@ -20543,8 +21290,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
}
/* NVME_FCREQ and NVME_ABTS requests */
- if (pwqe->iocb_flag & LPFC_IO_NVME ||
- pwqe->iocb_flag & LPFC_IO_FCP) {
+ if (pwqe->iocb_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) {
/* Get the IO distribution (hba_wqidx) for WQ assignment. */
wq = qp->io_wq;
pring = wq->pring;
@@ -21323,6 +22069,116 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba,
}
/**
+ * lpfc_read_object - Retrieve object data from HBA
+ * @phba: The HBA for which this call is being executed.
+ * @rdobject: Pathname of object data we want to read.
+ * @datap: Pointer to where data will be copied to.
+ * @datasz: size of data area
+ *
+ * This routine is limited to object sizes of LPFC_BPL_SIZE (1024) or less.
+ * The data will be truncated if datasz is not large enough.
+ * Version 1 is not supported with Embedded mbox cmd, so we must use version 0.
+ * Returns the actual bytes read from the object.
+ */
+int
+lpfc_read_object(struct lpfc_hba *phba, char *rdobject, uint32_t *datap,
+ uint32_t datasz)
+{
+ struct lpfc_mbx_read_object *read_object;
+ LPFC_MBOXQ_t *mbox;
+ int rc, length, eof, j, byte_cnt = 0;
+ uint32_t shdr_status, shdr_add_status;
+ union lpfc_sli4_cfg_shdr *shdr;
+ struct lpfc_dmabuf *pcmd;
+
+ /* sanity check on queue memory */
+ if (!datap)
+ return -ENODEV;
+
+ mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mbox)
+ return -ENOMEM;
+ length = (sizeof(struct lpfc_mbx_read_object) -
+ sizeof(struct lpfc_sli4_cfg_mhdr));
+ lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_READ_OBJECT,
+ length, LPFC_SLI4_MBX_EMBED);
+ read_object = &mbox->u.mqe.un.read_object;
+ shdr = (union lpfc_sli4_cfg_shdr *)&read_object->header.cfg_shdr;
+
+ bf_set(lpfc_mbox_hdr_version, &shdr->request, LPFC_Q_CREATE_VERSION_0);
+ bf_set(lpfc_mbx_rd_object_rlen, &read_object->u.request, datasz);
+ read_object->u.request.rd_object_offset = 0;
+ read_object->u.request.rd_object_cnt = 1;
+
+ memset((void *)read_object->u.request.rd_object_name, 0,
+ LPFC_OBJ_NAME_SZ);
+ sprintf((uint8_t *)read_object->u.request.rd_object_name, rdobject);
+ for (j = 0; j < strlen(rdobject); j++)
+ read_object->u.request.rd_object_name[j] =
+ cpu_to_le32(read_object->u.request.rd_object_name[j]);
+
+ pcmd = kmalloc(sizeof(*pcmd), GFP_KERNEL);
+ if (pcmd)
+ pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pcmd->phys);
+ if (!pcmd || !pcmd->virt) {
+ kfree(pcmd);
+ mempool_free(mbox, phba->mbox_mem_pool);
+ return -ENOMEM;
+ }
+ memset((void *)pcmd->virt, 0, LPFC_BPL_SIZE);
+ read_object->u.request.rd_object_hbuf[0].pa_lo =
+ putPaddrLow(pcmd->phys);
+ read_object->u.request.rd_object_hbuf[0].pa_hi =
+ putPaddrHigh(pcmd->phys);
+ read_object->u.request.rd_object_hbuf[0].length = LPFC_BPL_SIZE;
+
+ mbox->vport = phba->pport;
+ mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+ mbox->ctx_buf = NULL;
+ mbox->ctx_ndlp = NULL;
+
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+
+ if (shdr_status == STATUS_FAILED &&
+ shdr_add_status == ADD_STATUS_INVALID_OBJECT_NAME) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_CGN_MGMT,
+ "4674 No port cfg file in FW.\n");
+ byte_cnt = -ENOENT;
+ } else if (shdr_status || shdr_add_status || rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_CGN_MGMT,
+ "2625 READ_OBJECT mailbox failed with "
+ "status x%x add_status x%x, mbx status x%x\n",
+ shdr_status, shdr_add_status, rc);
+ byte_cnt = -ENXIO;
+ } else {
+ /* Success */
+ length = read_object->u.response.rd_object_actual_rlen;
+ eof = bf_get(lpfc_mbx_rd_object_eof, &read_object->u.response);
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_CGN_MGMT,
+ "2626 READ_OBJECT Success len %d:%d, EOF %d\n",
+ length, datasz, eof);
+
+ /* Detect the port config file exists but is empty */
+ if (!length && eof) {
+ byte_cnt = 0;
+ goto exit;
+ }
+
+ byte_cnt = length;
+ lpfc_sli_pcimem_bcopy(pcmd->virt, datap, byte_cnt);
+ }
+
+ exit:
+ lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
+ kfree(pcmd);
+ mempool_free(mbox, phba->mbox_mem_pool);
+ return byte_cnt;
+}
+
+/**
* lpfc_get_sgl_per_hdwq - Get one SGL chunk from hdwq's pool
* @phba: The HBA for which this call is being executed.
* @lpfc_buf: IO buf structure to append the SGL chunk
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index dde8eb9d796d..5161ccacea3e 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -107,6 +107,7 @@ struct lpfc_iocbq {
#define LPFC_IO_NVME_LS 0x400000 /* NVME LS command */
#define LPFC_IO_NVMET 0x800000 /* NVMET command */
#define LPFC_IO_VMID 0x1000000 /* VMID tagged IO */
+#define LPFC_IO_CMF 0x4000000 /* CMF command */
uint32_t drvrTimeout; /* driver timeout in seconds */
struct lpfc_vport *vport;/* virtual port pointer */
@@ -462,4 +463,5 @@ struct lpfc_io_buf {
uint64_t ts_isr_cmpl;
uint64_t ts_data_io;
#endif
+ uint64_t rx_cmd_start;
};
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 26f19c95380f..99c5d1e4da5e 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -557,6 +557,7 @@ struct lpfc_pc_sli4_params {
uint16_t mi_value;
#define LPFC_DFLT_MIB_VAL 2
uint8_t mib_bde_cnt;
+ uint8_t cmf;
uint8_t cqv;
uint8_t mqv;
uint8_t wqv;
@@ -978,6 +979,8 @@ struct lpfc_sli4_hba {
#define lpfc_conf_trunk_port3_nd_WORD conf_trunk
#define lpfc_conf_trunk_port3_nd_SHIFT 7
#define lpfc_conf_trunk_port3_nd_MASK 0x1
+ uint8_t flash_id;
+ uint8_t asic_rev;
};
enum lpfc_sge_type {
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 2d62fd2a9824..a7aba7833425 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "12.8.0.10"
+#define LPFC_DRIVER_VERSION "14.0.0.1"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index ec10b2497310..e4298bf4a482 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -1451,10 +1451,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
* pthru timeout to the os layer timeout value.
*/
if (scp->device->type == TYPE_TAPE) {
- if ((scp->request->timeout / HZ) > 0xFFFF)
+ if (scsi_cmd_to_rq(scp)->timeout / HZ > 0xFFFF)
pthru->timeout = cpu_to_le16(0xFFFF);
else
- pthru->timeout = cpu_to_le16(scp->request->timeout / HZ);
+ pthru->timeout = cpu_to_le16(scsi_cmd_to_rq(scp)->timeout / HZ);
}
/*
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 06399c026a8d..26d0cf9353dd 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -402,7 +402,7 @@ megasas_get_msix_index(struct megasas_instance *instance,
(mega_mod64(atomic64_add_return(1, &instance->total_io_count),
instance->msix_vectors));
} else if (instance->host->nr_hw_queues > 1) {
- u32 tag = blk_mq_unique_tag(scmd->request);
+ u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
cmd->request_desc->SCSIIO.MSIxIndex = blk_mq_unique_tag_to_hwq(tag) +
instance->low_latency_index_start;
@@ -3023,7 +3023,7 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
io_request->DevHandle = cpu_to_le16(device_id);
io_request->LUN[1] = scmd->device->lun;
pRAID_Context->timeout_value =
- cpu_to_le16 (scmd->request->timeout / HZ);
+ cpu_to_le16(scsi_cmd_to_rq(scmd)->timeout / HZ);
cmd->request_desc->SCSIIO.RequestFlags =
(MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
@@ -3086,7 +3086,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
device_id = MEGASAS_DEV_INDEX(scmd);
pd_index = MEGASAS_PD_INDEX(scmd);
- os_timeout_value = scmd->request->timeout / HZ;
+ os_timeout_value = scsi_cmd_to_rq(scmd)->timeout / HZ;
mr_device_priv_data = scmd->device->hostdata;
cmd->pd_interface = mr_device_priv_data->interface_type;
@@ -3381,7 +3381,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
return SCSI_MLQUEUE_HOST_BUSY;
}
- cmd = megasas_get_cmd_fusion(instance, scmd->request->tag);
+ cmd = megasas_get_cmd_fusion(instance, scsi_cmd_to_rq(scmd)->tag);
if (!cmd) {
atomic_dec(&instance->fw_outstanding);
@@ -3422,7 +3422,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
*/
if (cmd->r1_alt_dev_handle != MR_DEVHANDLE_INVALID) {
r1_cmd = megasas_get_cmd_fusion(instance,
- (scmd->request->tag + instance->max_fw_cmds));
+ scsi_cmd_to_rq(scmd)->tag + instance->max_fw_cmds);
megasas_prepare_secondRaid1_IO(instance, cmd, r1_cmd);
}
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
index 6f5dc9e78553..9787b53a2b59 100644
--- a/drivers/scsi/mpi3mr/mpi3mr.h
+++ b/drivers/scsi/mpi3mr/mpi3mr.h
@@ -183,6 +183,20 @@ enum mpi3mr_iocstate {
MRIOC_STATE_UNRECOVERABLE,
};
+/* Init type definitions */
+enum mpi3mr_init_type {
+ MPI3MR_IT_INIT = 0,
+ MPI3MR_IT_RESET,
+ MPI3MR_IT_RESUME,
+};
+
+/* Cleanup reason definitions */
+enum mpi3mr_cleanup_reason {
+ MPI3MR_COMPLETE_CLEANUP = 0,
+ MPI3MR_REINIT_FAILURE,
+ MPI3MR_SUSPEND,
+};
+
/* Reset reason code definitions*/
enum mpi3mr_reset_reason {
MPI3MR_RESET_FROM_BRINGUP = 1,
@@ -855,8 +869,8 @@ struct delayed_dev_rmhs_node {
int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc);
void mpi3mr_cleanup_resources(struct mpi3mr_ioc *mrioc);
-int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init);
-void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc, u8 re_init);
+int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type);
+void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc, u8 reason);
int mpi3mr_issue_port_enable(struct mpi3mr_ioc *mrioc, u8 async);
int mpi3mr_admin_request_post(struct mpi3mr_ioc *mrioc, void *admin_req,
u16 admin_req_sz, u8 ignore_reset);
@@ -872,6 +886,7 @@ void *mpi3mr_get_reply_virt_addr(struct mpi3mr_ioc *mrioc,
void mpi3mr_repost_sense_buf(struct mpi3mr_ioc *mrioc,
u64 sense_buf_dma);
+void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc);
void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
struct mpi3_event_notification_reply *event_reply);
void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index 2dba2b0af166..4a8316c6bd41 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -3205,7 +3205,7 @@ out_failed:
/**
* mpi3mr_init_ioc - Initialize the controller
* @mrioc: Adapter instance reference
- * @re_init: Flag to indicate is this fresh init or re-init
+ * @init_type: Flag to indicate is the init_type
*
* This the controller initialization routine, executed either
* after soft reset or from pci probe callback.
@@ -3218,7 +3218,7 @@ out_failed:
*
* Return: 0 on success and non-zero on failure.
*/
-int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
+int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type)
{
int retval = 0;
enum mpi3mr_iocstate ioc_state;
@@ -3229,7 +3229,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
mrioc->irqpoll_sleep = MPI3MR_IRQ_POLL_SLEEP;
mrioc->change_count = 0;
- if (!re_init) {
+ if (init_type == MPI3MR_IT_INIT) {
mrioc->cpu_count = num_online_cpus();
retval = mpi3mr_setup_resources(mrioc);
if (retval) {
@@ -3314,7 +3314,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
goto out_failed;
}
- if (!re_init) {
+ if (init_type != MPI3MR_IT_RESET) {
retval = mpi3mr_setup_isr(mrioc, 1);
if (retval) {
ioc_err(mrioc, "Failed to setup ISR error %d\n",
@@ -3332,7 +3332,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
}
mpi3mr_process_factsdata(mrioc, &facts_data);
- if (!re_init) {
+ if (init_type == MPI3MR_IT_INIT) {
retval = mpi3mr_check_reset_dma_mask(mrioc);
if (retval) {
ioc_err(mrioc, "Resetting dma mask failed %d\n",
@@ -3351,7 +3351,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
goto out_failed;
}
- if (!re_init) {
+ if (init_type == MPI3MR_IT_INIT) {
retval = mpi3mr_alloc_chain_bufs(mrioc);
if (retval) {
ioc_err(mrioc, "Failed to allocated chain buffers %d\n",
@@ -3374,7 +3374,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
writel(mrioc->sbq_host_index,
&mrioc->sysif_regs->sense_buffer_free_host_index);
- if (!re_init) {
+ if (init_type != MPI3MR_IT_RESET) {
retval = mpi3mr_setup_isr(mrioc, 0);
if (retval) {
ioc_err(mrioc, "Failed to re-setup ISR, error %d\n",
@@ -3390,7 +3390,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
goto out_failed;
}
- if (re_init &&
+ if ((init_type != MPI3MR_IT_INIT) &&
(mrioc->shost->nr_hw_queues > mrioc->num_op_reply_q)) {
retval = -1;
ioc_err(mrioc,
@@ -3422,7 +3422,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
goto out_failed;
}
- if (re_init) {
+ if (init_type != MPI3MR_IT_INIT) {
ioc_info(mrioc, "Issuing Port Enable\n");
retval = mpi3mr_issue_port_enable(mrioc, 0);
if (retval) {
@@ -3434,7 +3434,10 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
return retval;
out_failed:
- mpi3mr_cleanup_ioc(mrioc, re_init);
+ if (init_type == MPI3MR_IT_INIT)
+ mpi3mr_cleanup_ioc(mrioc, MPI3MR_COMPLETE_CLEANUP);
+ else
+ mpi3mr_cleanup_ioc(mrioc, MPI3MR_REINIT_FAILURE);
out_nocleanup:
return retval;
}
@@ -3495,7 +3498,7 @@ static void mpi3mr_memset_op_req_q_buffers(struct mpi3mr_ioc *mrioc, u16 qidx)
*
* Return: Nothing.
*/
-static void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
+void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
{
u16 i;
@@ -3710,7 +3713,7 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc)
/**
* mpi3mr_cleanup_ioc - Cleanup controller
* @mrioc: Adapter instance reference
- * @re_init: Cleanup due to a reinit or not
+ * @reason: Cleanup reason
*
* controller cleanup handler, Message unit reset or soft reset
* and shutdown notification is issued to the controller and the
@@ -3718,11 +3721,11 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc)
*
* Return: Nothing.
*/
-void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
+void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc, u8 reason)
{
enum mpi3mr_iocstate ioc_state;
- if (!re_init)
+ if (reason == MPI3MR_COMPLETE_CLEANUP)
mpi3mr_stop_watchdog(mrioc);
mpi3mr_ioc_disable_intr(mrioc);
@@ -3737,11 +3740,11 @@ void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc, u8 re_init)
MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
MPI3MR_RESET_FROM_MUR_FAILURE);
- if (!re_init)
+ if (reason != MPI3MR_REINIT_FAILURE)
mpi3mr_issue_ioc_shutdown(mrioc);
}
- if (!re_init) {
+ if (reason == MPI3MR_COMPLETE_CLEANUP) {
mpi3mr_free_mem(mrioc);
mpi3mr_cleanup_resources(mrioc);
}
@@ -3923,7 +3926,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
mpi3mr_flush_host_io(mrioc);
mpi3mr_invalidate_devhandles(mrioc);
mpi3mr_memset_buffers(mrioc);
- retval = mpi3mr_init_ioc(mrioc, 1);
+ retval = mpi3mr_init_ioc(mrioc, MPI3MR_IT_RESET);
if (retval) {
pr_err(IOCNAME "reinit after soft reset failed: reason %d\n",
mrioc->name, reset_reason);
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index 24ac7ddec749..2197988333fe 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
@@ -50,7 +50,7 @@ static u16 mpi3mr_host_tag_for_scmd(struct mpi3mr_ioc *mrioc,
u32 unique_tag;
u16 host_tag, hw_queue;
- unique_tag = blk_mq_unique_tag(scmd->request);
+ unique_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
hw_queue = blk_mq_unique_tag_to_hwq(unique_tag);
if (hw_queue >= mrioc->num_op_reply_q)
@@ -1963,7 +1963,6 @@ static void mpi3mr_setup_eedp(struct mpi3mr_ioc *mrioc,
{
u16 eedp_flags = 0;
unsigned char prot_op = scsi_get_prot_op(scmd);
- unsigned char prot_type = scsi_get_prot_type(scmd);
switch (prot_op) {
case SCSI_PROT_NORMAL:
@@ -1983,60 +1982,42 @@ static void mpi3mr_setup_eedp(struct mpi3mr_ioc *mrioc,
scsiio_req->msg_flags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID;
break;
case SCSI_PROT_READ_PASS:
- eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK |
- MPI3_EEDPFLAGS_CHK_REF_TAG | MPI3_EEDPFLAGS_CHK_APP_TAG |
- MPI3_EEDPFLAGS_CHK_GUARD;
+ eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK;
scsiio_req->msg_flags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID;
break;
case SCSI_PROT_WRITE_PASS:
- if (scsi_host_get_guard(scmd->device->host)
- & SHOST_DIX_GUARD_IP) {
- eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK_REGEN |
- MPI3_EEDPFLAGS_CHK_APP_TAG |
- MPI3_EEDPFLAGS_CHK_GUARD |
- MPI3_EEDPFLAGS_INCR_PRI_REF_TAG;
+ if (scmd->prot_flags & SCSI_PROT_IP_CHECKSUM) {
+ eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK_REGEN;
scsiio_req->sgl[0].eedp.application_tag_translation_mask =
0xffff;
- } else {
- eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK |
- MPI3_EEDPFLAGS_CHK_REF_TAG |
- MPI3_EEDPFLAGS_CHK_APP_TAG |
- MPI3_EEDPFLAGS_CHK_GUARD;
- }
+ } else
+ eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK;
+
scsiio_req->msg_flags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID;
break;
default:
return;
}
- if (scsi_host_get_guard(scmd->device->host) & SHOST_DIX_GUARD_IP)
+ if (scmd->prot_flags & SCSI_PROT_GUARD_CHECK)
+ eedp_flags |= MPI3_EEDPFLAGS_CHK_GUARD;
+
+ if (scmd->prot_flags & SCSI_PROT_IP_CHECKSUM)
eedp_flags |= MPI3_EEDPFLAGS_HOST_GUARD_IP_CHKSUM;
- switch (prot_type) {
- case SCSI_PROT_DIF_TYPE0:
- eedp_flags |= MPI3_EEDPFLAGS_INCR_PRI_REF_TAG;
+ if (scmd->prot_flags & SCSI_PROT_REF_CHECK) {
+ eedp_flags |= MPI3_EEDPFLAGS_CHK_REF_TAG |
+ MPI3_EEDPFLAGS_INCR_PRI_REF_TAG;
scsiio_req->cdb.eedp32.primary_reference_tag =
- cpu_to_be32(t10_pi_ref_tag(scmd->request));
- break;
- case SCSI_PROT_DIF_TYPE1:
- case SCSI_PROT_DIF_TYPE2:
- eedp_flags |= MPI3_EEDPFLAGS_INCR_PRI_REF_TAG |
- MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE |
- MPI3_EEDPFLAGS_CHK_GUARD;
- scsiio_req->cdb.eedp32.primary_reference_tag =
- cpu_to_be32(t10_pi_ref_tag(scmd->request));
- break;
- case SCSI_PROT_DIF_TYPE3:
- eedp_flags |= MPI3_EEDPFLAGS_CHK_GUARD |
- MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE;
- break;
-
- default:
- scsiio_req->msg_flags &= ~(MPI3_SCSIIO_MSGFLAGS_METASGL_VALID);
- return;
+ cpu_to_be32(scsi_prot_ref_tag(scmd));
}
- switch (scmd->device->sector_size) {
+ if (scmd->prot_flags & SCSI_PROT_REF_INCREMENT)
+ eedp_flags |= MPI3_EEDPFLAGS_INCR_PRI_REF_TAG;
+
+ eedp_flags |= MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE;
+
+ switch (scsi_prot_interval(scmd)) {
case 512:
scsiio_req->sgl[0].eedp.user_data_size = MPI3_EEDP_UDS_512;
break;
@@ -3451,7 +3432,7 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
u16 dev_handle;
u16 host_tag;
u32 scsiio_flags = 0;
- struct request *rq = scmd->request;
+ struct request *rq = scsi_cmd_to_rq(scmd);
int iprio_class;
sdev_priv_data = scmd->device->hostdata;
@@ -3795,7 +3776,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
mrioc->is_driver_loading = 1;
- if (mpi3mr_init_ioc(mrioc, 0)) {
+ if (mpi3mr_init_ioc(mrioc, MPI3MR_IT_INIT)) {
ioc_err(mrioc, "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
retval = -ENODEV;
@@ -3818,7 +3799,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return retval;
addhost_failed:
- mpi3mr_cleanup_ioc(mrioc, 0);
+ mpi3mr_cleanup_ioc(mrioc, MPI3MR_COMPLETE_CLEANUP);
out_iocinit_failed:
destroy_workqueue(mrioc->fwevt_worker_thread);
out_fwevtthread_failed:
@@ -3870,7 +3851,7 @@ static void mpi3mr_remove(struct pci_dev *pdev)
mpi3mr_tgtdev_del_from_list(mrioc, tgtdev);
mpi3mr_tgtdev_put(tgtdev);
}
- mpi3mr_cleanup_ioc(mrioc, 0);
+ mpi3mr_cleanup_ioc(mrioc, MPI3MR_COMPLETE_CLEANUP);
spin_lock(&mrioc_list_lock);
list_del(&mrioc->list);
@@ -3910,7 +3891,7 @@ static void mpi3mr_shutdown(struct pci_dev *pdev)
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
if (wq)
destroy_workqueue(wq);
- mpi3mr_cleanup_ioc(mrioc, 0);
+ mpi3mr_cleanup_ioc(mrioc, MPI3MR_COMPLETE_CLEANUP);
}
#ifdef CONFIG_PM
@@ -3940,7 +3921,7 @@ static int mpi3mr_suspend(struct pci_dev *pdev, pm_message_t state)
mpi3mr_cleanup_fwevt_list(mrioc);
scsi_block_requests(shost);
mpi3mr_stop_watchdog(mrioc);
- mpi3mr_cleanup_ioc(mrioc, 1);
+ mpi3mr_cleanup_ioc(mrioc, MPI3MR_SUSPEND);
device_state = pci_choose_state(pdev, state);
ioc_info(mrioc, "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
@@ -3988,7 +3969,8 @@ static int mpi3mr_resume(struct pci_dev *pdev)
}
mrioc->stop_drv_processing = 0;
- mpi3mr_init_ioc(mrioc, 1);
+ mpi3mr_memset_buffers(mrioc);
+ mpi3mr_init_ioc(mrioc, MPI3MR_IT_RESUME);
scsi_unblock_requests(shost);
mpi3mr_start_watchdog(mrioc);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index cf4a3a2c22ad..6c82435bc9cc 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -116,6 +116,14 @@ MODULE_PARM_DESC(perf_mode,
"\t\tdefault - default perf_mode is 'balanced'"
);
+static int poll_queues;
+module_param(poll_queues, int, 0444);
+MODULE_PARM_DESC(poll_queues, "Number of queues to be use for io_uring poll mode.\n\t\t"
+ "This parameter is effective only if host_tagset_enable=1. &\n\t\t"
+ "when poll_queues are enabled then &\n\t\t"
+ "perf_mode is set to latency mode. &\n\t\t"
+ );
+
enum mpt3sas_perf_mode {
MPT_PERF_MODE_DEFAULT = -1,
MPT_PERF_MODE_BALANCED = 0,
@@ -709,6 +717,7 @@ _base_fault_reset_work(struct work_struct *work)
* and this call is safe since dead ioc will never return any
* command back from HW.
*/
+ mpt3sas_base_pause_mq_polling(ioc);
ioc->schedule_dead_ioc_flush_running_cmds(ioc);
/*
* Set remove_host flag early since kernel thread will
@@ -744,6 +753,7 @@ _base_fault_reset_work(struct work_struct *work)
spin_unlock_irqrestore(
&ioc->ioc_reset_in_progress_lock, flags);
mpt3sas_base_mask_interrupts(ioc);
+ mpt3sas_base_pause_mq_polling(ioc);
_base_clear_outstanding_commands(ioc);
}
@@ -1548,6 +1558,53 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
}
/**
+ * mpt3sas_base_pause_mq_polling - pause polling on the mq poll queues
+ * when driver is flushing out the IOs.
+ * @ioc: per adapter object
+ *
+ * Pause polling on the mq poll (io uring) queues when driver is flushing
+ * out the IOs. Otherwise we may see the race condition of completing the same
+ * IO from two paths.
+ *
+ * Returns nothing.
+ */
+void
+mpt3sas_base_pause_mq_polling(struct MPT3SAS_ADAPTER *ioc)
+{
+ int iopoll_q_count =
+ ioc->reply_queue_count - ioc->iopoll_q_start_index;
+ int qid;
+
+ for (qid = 0; qid < iopoll_q_count; qid++)
+ atomic_set(&ioc->io_uring_poll_queues[qid].pause, 1);
+
+ /*
+ * wait for current poll to complete.
+ */
+ for (qid = 0; qid < iopoll_q_count; qid++) {
+ while (atomic_read(&ioc->io_uring_poll_queues[qid].busy))
+ udelay(500);
+ }
+}
+
+/**
+ * mpt3sas_base_resume_mq_polling - Resume polling on mq poll queues.
+ * @ioc: per adapter object
+ *
+ * Returns nothing.
+ */
+void
+mpt3sas_base_resume_mq_polling(struct MPT3SAS_ADAPTER *ioc)
+{
+ int iopoll_q_count =
+ ioc->reply_queue_count - ioc->iopoll_q_start_index;
+ int qid;
+
+ for (qid = 0; qid < iopoll_q_count; qid++)
+ atomic_set(&ioc->io_uring_poll_queues[qid].pause, 0);
+}
+
+/**
* mpt3sas_base_mask_interrupts - disable interrupts
* @ioc: per adapter object
*
@@ -1722,7 +1779,8 @@ _base_process_reply_queue(struct adapter_reply_queue *reply_q)
MPI2_RPHI_MSIX_INDEX_SHIFT),
&ioc->chip->ReplyPostHostIndex);
}
- if (!reply_q->irq_poll_scheduled) {
+ if (!reply_q->is_iouring_poll_q &&
+ !reply_q->irq_poll_scheduled) {
reply_q->irq_poll_scheduled = true;
irq_poll_sched(&reply_q->irqpoll);
}
@@ -1779,6 +1837,33 @@ _base_process_reply_queue(struct adapter_reply_queue *reply_q)
}
/**
+ * mpt3sas_blk_mq_poll - poll the blk mq poll queue
+ * @shost: Scsi_Host object
+ * @queue_num: hw ctx queue number
+ *
+ * Return number of entries that has been processed from poll queue.
+ */
+int mpt3sas_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
+{
+ struct MPT3SAS_ADAPTER *ioc =
+ (struct MPT3SAS_ADAPTER *)shost->hostdata;
+ struct adapter_reply_queue *reply_q;
+ int num_entries = 0;
+ int qid = queue_num - ioc->iopoll_q_start_index;
+
+ if (atomic_read(&ioc->io_uring_poll_queues[qid].pause) ||
+ !atomic_add_unless(&ioc->io_uring_poll_queues[qid].busy, 1, 1))
+ return 0;
+
+ reply_q = ioc->io_uring_poll_queues[qid].reply_q;
+
+ num_entries = _base_process_reply_queue(reply_q);
+ atomic_dec(&ioc->io_uring_poll_queues[qid].busy);
+
+ return num_entries;
+}
+
+/**
* _base_interrupt - MPT adapter (IOC) specific interrupt handler.
* @irq: irq number (not used)
* @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
@@ -1851,6 +1936,8 @@ _base_init_irqpolls(struct MPT3SAS_ADAPTER *ioc)
return;
list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
+ if (reply_q->is_iouring_poll_q)
+ continue;
irq_poll_init(&reply_q->irqpoll,
ioc->hba_queue_depth/4, _base_irqpoll);
reply_q->irq_poll_scheduled = false;
@@ -1900,6 +1987,12 @@ mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc, u8 poll)
/* TMs are on msix_index == 0 */
if (reply_q->msix_index == 0)
continue;
+
+ if (reply_q->is_iouring_poll_q) {
+ _base_process_reply_queue(reply_q);
+ continue;
+ }
+
synchronize_irq(pci_irq_vector(ioc->pdev, reply_q->msix_index));
if (reply_q->irq_poll_scheduled) {
/* Calling irq_poll_disable will wait for any pending
@@ -2998,6 +3091,11 @@ mpt3sas_base_free_irq(struct MPT3SAS_ADAPTER *ioc)
list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
list_del(&reply_q->list);
+ if (reply_q->is_iouring_poll_q) {
+ kfree(reply_q);
+ continue;
+ }
+
if (ioc->smp_affinity_enable)
irq_set_affinity_hint(pci_irq_vector(ioc->pdev,
reply_q->msix_index), NULL);
@@ -3019,7 +3117,7 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index)
{
struct pci_dev *pdev = ioc->pdev;
struct adapter_reply_queue *reply_q;
- int r;
+ int r, qid;
reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL);
if (!reply_q) {
@@ -3031,6 +3129,17 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index)
reply_q->msix_index = index;
atomic_set(&reply_q->busy, 0);
+
+ if (index >= ioc->iopoll_q_start_index) {
+ qid = index - ioc->iopoll_q_start_index;
+ snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-mq-poll%d",
+ ioc->driver_name, ioc->id, qid);
+ reply_q->is_iouring_poll_q = 1;
+ ioc->io_uring_poll_queues[qid].reply_q = reply_q;
+ goto out;
+ }
+
+
if (ioc->msix_enable)
snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
ioc->driver_name, ioc->id, index);
@@ -3045,7 +3154,7 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index)
kfree(reply_q);
return -EBUSY;
}
-
+out:
INIT_LIST_HEAD(&reply_q->list);
list_add_tail(&reply_q->list, &ioc->reply_queue_list);
return 0;
@@ -3066,6 +3175,8 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
unsigned int cpu, nr_cpus, nr_msix, index = 0;
struct adapter_reply_queue *reply_q;
int local_numa_node;
+ int iopoll_q_count = ioc->reply_queue_count -
+ ioc->iopoll_q_start_index;
if (!_base_is_controller_msix_enabled(ioc))
return;
@@ -3099,7 +3210,8 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
const cpumask_t *mask;
- if (reply_q->msix_index < ioc->high_iops_queues)
+ if (reply_q->msix_index < ioc->high_iops_queues ||
+ reply_q->msix_index >= ioc->iopoll_q_start_index)
continue;
mask = pci_irq_get_affinity(ioc->pdev,
@@ -3121,13 +3233,14 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
fall_back:
cpu = cpumask_first(cpu_online_mask);
- nr_msix -= ioc->high_iops_queues;
+ nr_msix -= (ioc->high_iops_queues - iopoll_q_count);
index = 0;
list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
unsigned int i, group = nr_cpus / nr_msix;
- if (reply_q->msix_index < ioc->high_iops_queues)
+ if (reply_q->msix_index < ioc->high_iops_queues ||
+ reply_q->msix_index >= ioc->iopoll_q_start_index)
continue;
if (cpu >= nr_cpus)
@@ -3164,8 +3277,12 @@ _base_check_and_enable_high_iops_queues(struct MPT3SAS_ADAPTER *ioc,
{
u16 lnksta, speed;
+ /*
+ * Disable high iops queues if io uring poll queues are enabled.
+ */
if (perf_mode == MPT_PERF_MODE_IOPS ||
- perf_mode == MPT_PERF_MODE_LATENCY) {
+ perf_mode == MPT_PERF_MODE_LATENCY ||
+ ioc->io_uring_poll_queues) {
ioc->high_iops_queues = 0;
return;
}
@@ -3202,6 +3319,7 @@ mpt3sas_base_disable_msix(struct MPT3SAS_ADAPTER *ioc)
return;
pci_free_irq_vectors(ioc->pdev);
ioc->msix_enable = 0;
+ kfree(ioc->io_uring_poll_queues);
}
/**
@@ -3215,18 +3333,24 @@ _base_alloc_irq_vectors(struct MPT3SAS_ADAPTER *ioc)
int i, irq_flags = PCI_IRQ_MSIX;
struct irq_affinity desc = { .pre_vectors = ioc->high_iops_queues };
struct irq_affinity *descp = &desc;
+ /*
+ * Don't allocate msix vectors for poll_queues.
+ * msix_vectors is always within a range of FW supported reply queue.
+ */
+ int nr_msix_vectors = ioc->iopoll_q_start_index;
+
if (ioc->smp_affinity_enable)
- irq_flags |= PCI_IRQ_AFFINITY;
+ irq_flags |= PCI_IRQ_AFFINITY | PCI_IRQ_ALL_TYPES;
else
descp = NULL;
- ioc_info(ioc, " %d %d\n", ioc->high_iops_queues,
- ioc->reply_queue_count);
+ ioc_info(ioc, " %d %d %d\n", ioc->high_iops_queues,
+ ioc->reply_queue_count, nr_msix_vectors);
i = pci_alloc_irq_vectors_affinity(ioc->pdev,
ioc->high_iops_queues,
- ioc->reply_queue_count, irq_flags, descp);
+ nr_msix_vectors, irq_flags, descp);
return i;
}
@@ -3242,6 +3366,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
int r;
int i, local_max_msix_vectors;
u8 try_msix = 0;
+ int iopoll_q_count = 0;
ioc->msix_load_balance = false;
@@ -3257,22 +3382,16 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
ioc_info(ioc, "MSI-X vectors supported: %d\n", ioc->msix_vector_count);
pr_info("\t no of cores: %d, max_msix_vectors: %d\n",
ioc->cpu_count, max_msix_vectors);
- if (ioc->is_aero_ioc)
- _base_check_and_enable_high_iops_queues(ioc,
- ioc->msix_vector_count);
+
ioc->reply_queue_count =
- min_t(int, ioc->cpu_count + ioc->high_iops_queues,
- ioc->msix_vector_count);
+ min_t(int, ioc->cpu_count, ioc->msix_vector_count);
if (!ioc->rdpq_array_enable && max_msix_vectors == -1)
local_max_msix_vectors = (reset_devices) ? 1 : 8;
else
local_max_msix_vectors = max_msix_vectors;
- if (local_max_msix_vectors > 0)
- ioc->reply_queue_count = min_t(int, local_max_msix_vectors,
- ioc->reply_queue_count);
- else if (local_max_msix_vectors == 0)
+ if (local_max_msix_vectors == 0)
goto try_ioapic;
/*
@@ -3293,14 +3412,77 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
if (ioc->msix_load_balance)
ioc->smp_affinity_enable = 0;
+ if (!ioc->smp_affinity_enable || ioc->reply_queue_count <= 1)
+ ioc->shost->host_tagset = 0;
+
+ /*
+ * Enable io uring poll queues only if host_tagset is enabled.
+ */
+ if (ioc->shost->host_tagset)
+ iopoll_q_count = poll_queues;
+
+ if (iopoll_q_count) {
+ ioc->io_uring_poll_queues = kcalloc(iopoll_q_count,
+ sizeof(struct io_uring_poll_queue), GFP_KERNEL);
+ if (!ioc->io_uring_poll_queues)
+ iopoll_q_count = 0;
+ }
+
+ if (ioc->is_aero_ioc)
+ _base_check_and_enable_high_iops_queues(ioc,
+ ioc->msix_vector_count);
+
+ /*
+ * Add high iops queues count to reply queue count if high iops queues
+ * are enabled.
+ */
+ ioc->reply_queue_count = min_t(int,
+ ioc->reply_queue_count + ioc->high_iops_queues,
+ ioc->msix_vector_count);
+
+ /*
+ * Adjust the reply queue count incase reply queue count
+ * exceeds the user provided MSIx vectors count.
+ */
+ if (local_max_msix_vectors > 0)
+ ioc->reply_queue_count = min_t(int, local_max_msix_vectors,
+ ioc->reply_queue_count);
+ /*
+ * Add io uring poll queues count to reply queues count
+ * if io uring is enabled in driver.
+ */
+ if (iopoll_q_count) {
+ if (ioc->reply_queue_count < (iopoll_q_count + MPT3_MIN_IRQS))
+ iopoll_q_count = 0;
+ ioc->reply_queue_count = min_t(int,
+ ioc->reply_queue_count + iopoll_q_count,
+ ioc->msix_vector_count);
+ }
+
+ /*
+ * Starting index of io uring poll queues in reply queue list.
+ */
+ ioc->iopoll_q_start_index =
+ ioc->reply_queue_count - iopoll_q_count;
+
r = _base_alloc_irq_vectors(ioc);
if (r < 0) {
ioc_info(ioc, "pci_alloc_irq_vectors failed (r=%d) !!!\n", r);
goto try_ioapic;
}
+ /*
+ * Adjust the reply queue count if the allocated
+ * MSIx vectors is less then the requested number
+ * of MSIx vectors.
+ */
+ if (r < ioc->iopoll_q_start_index) {
+ ioc->reply_queue_count = r + iopoll_q_count;
+ ioc->iopoll_q_start_index =
+ ioc->reply_queue_count - iopoll_q_count;
+ }
+
ioc->msix_enable = 1;
- ioc->reply_queue_count = r;
for (i = 0; i < ioc->reply_queue_count; i++) {
r = _base_request_irq(ioc, i);
if (r) {
@@ -3320,6 +3502,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
ioc->high_iops_queues = 0;
ioc_info(ioc, "High IOPs queues : disabled\n");
ioc->reply_queue_count = 1;
+ ioc->iopoll_q_start_index = ioc->reply_queue_count - 0;
r = pci_alloc_irq_vectors(ioc->pdev, 1, 1, PCI_IRQ_LEGACY);
if (r < 0) {
dfailprintk(ioc,
@@ -3416,6 +3599,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
u64 pio_chip = 0;
phys_addr_t chip_phys = 0;
struct adapter_reply_queue *reply_q;
+ int iopoll_q_count = 0;
dinitprintk(ioc, ioc_info(ioc, "%s\n", __func__));
@@ -3489,6 +3673,12 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
if (r)
goto out_fail;
+ iopoll_q_count = ioc->reply_queue_count - ioc->iopoll_q_start_index;
+ for (i = 0; i < iopoll_q_count; i++) {
+ atomic_set(&ioc->io_uring_poll_queues[i].busy, 0);
+ atomic_set(&ioc->io_uring_poll_queues[i].pause, 0);
+ }
+
if (!ioc->is_driver_loading)
_base_init_irqpolls(ioc);
/* Use the Combined reply queue feature only for SAS3 C0 & higher
@@ -3530,11 +3720,18 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
* 4)));
}
- list_for_each_entry(reply_q, &ioc->reply_queue_list, list)
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+ if (reply_q->msix_index >= ioc->iopoll_q_start_index) {
+ pr_info("%s: enabled: index: %d\n",
+ reply_q->name, reply_q->msix_index);
+ continue;
+ }
+
pr_info("%s: %s enabled: IRQ %d\n",
reply_q->name,
ioc->msix_enable ? "PCI-MSI-X" : "IO-APIC",
pci_irq_vector(ioc->pdev, reply_q->msix_index));
+ }
ioc_info(ioc, "iomem(%pap), mapped(0x%p), size(%d)\n",
&chip_phys, ioc->chip, memap_sz);
@@ -3651,7 +3848,7 @@ _base_get_msix_index(struct MPT3SAS_ADAPTER *ioc,
&ioc->total_io_cnt), ioc->reply_queue_count) : 0;
if (scmd && ioc->shost->nr_hw_queues > 1) {
- u32 tag = blk_mq_unique_tag(scmd->request);
+ u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
return blk_mq_unique_tag_to_hwq(tag) +
ioc->high_iops_queues;
@@ -3735,7 +3932,7 @@ mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
u16 smid;
u32 tag, unique_tag;
- unique_tag = blk_mq_unique_tag(scmd->request);
+ unique_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
tag = blk_mq_unique_tag_to_tag(unique_tag);
/*
@@ -5169,6 +5366,73 @@ _base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc)
}
/**
+ * _base_assign_fw_reported_qd - Get FW reported QD for SAS/SATA devices.
+ * - On failure set default QD values.
+ * @ioc : per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc)
+{
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+ Mpi26PCIeIOUnitPage1_t pcie_iounit_pg1;
+ int sz;
+ int rc = 0;
+
+ ioc->max_wideport_qd = MPT3SAS_SAS_QUEUE_DEPTH;
+ ioc->max_narrowport_qd = MPT3SAS_SAS_QUEUE_DEPTH;
+ ioc->max_sata_qd = MPT3SAS_SATA_QUEUE_DEPTH;
+ ioc->max_nvme_qd = MPT3SAS_NVME_QUEUE_DEPTH;
+ if (!ioc->is_gen35_ioc)
+ goto out;
+ /* sas iounit page 1 */
+ sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData);
+ sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
+ if (!sas_iounit_pg1) {
+ pr_err("%s: failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return rc;
+ }
+ rc = mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
+ sas_iounit_pg1, sz);
+ if (rc) {
+ pr_err("%s: failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ ioc->max_wideport_qd =
+ (le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth)) ?
+ le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth) :
+ MPT3SAS_SAS_QUEUE_DEPTH;
+ ioc->max_narrowport_qd =
+ (le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth)) ?
+ le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth) :
+ MPT3SAS_SAS_QUEUE_DEPTH;
+ ioc->max_sata_qd = (sas_iounit_pg1->SATAMaxQDepth) ?
+ sas_iounit_pg1->SATAMaxQDepth : MPT3SAS_SATA_QUEUE_DEPTH;
+ /* pcie iounit page 1 */
+ rc = mpt3sas_config_get_pcie_iounit_pg1(ioc, &mpi_reply,
+ &pcie_iounit_pg1, sizeof(Mpi26PCIeIOUnitPage1_t));
+ if (rc) {
+ pr_err("%s: failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ ioc->max_nvme_qd = (le16_to_cpu(pcie_iounit_pg1.NVMeMaxQueueDepth)) ?
+ (le16_to_cpu(pcie_iounit_pg1.NVMeMaxQueueDepth)) :
+ MPT3SAS_NVME_QUEUE_DEPTH;
+out:
+ dinitprintk(ioc, pr_err(
+ "MaxWidePortQD: 0x%x MaxNarrowPortQD: 0x%x MaxSataQD: 0x%x MaxNvmeQD: 0x%x\n",
+ ioc->max_wideport_qd, ioc->max_narrowport_qd,
+ ioc->max_sata_qd, ioc->max_nvme_qd));
+ kfree(sas_iounit_pg1);
+ return rc;
+}
+
+/**
* _base_static_config_pages - static start of day config pages
* @ioc: per adapter object
*/
@@ -5237,6 +5501,9 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
ioc_warn(ioc,
"TimeSync Interval in Manuf page-11 is not enabled. Periodic Time-Sync will be disabled\n");
}
+ rc = _base_assign_fw_reported_qd(ioc);
+ if (rc)
+ return rc;
rc = mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
if (rc)
return rc;
@@ -8471,6 +8738,7 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
_base_pre_reset_handler(ioc);
mpt3sas_wait_for_commands_to_complete(ioc);
mpt3sas_base_mask_interrupts(ioc);
+ mpt3sas_base_pause_mq_polling(ioc);
r = mpt3sas_base_make_ioc_ready(ioc, type);
if (r)
goto out;
@@ -8512,6 +8780,7 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
ioc->ioc_reset_count++;
mutex_unlock(&ioc->reset_in_progress_mutex);
+ mpt3sas_base_resume_mq_polling(ioc);
out_unlocked:
if ((r == 0) && is_trigger) {
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 0c6c3df0038d..f87c0911f66a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -77,9 +77,9 @@
#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 "37.101.00.00"
-#define MPT3SAS_MAJOR_VERSION 37
-#define MPT3SAS_MINOR_VERSION 101
+#define MPT3SAS_DRIVER_VERSION "39.100.00.00"
+#define MPT3SAS_MAJOR_VERSION 39
+#define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
@@ -354,6 +354,7 @@ struct mpt3sas_nvme_cmd {
#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G3 12
#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G35 16
#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET (0x10)
+#define MPT3_MIN_IRQS 1
/* OEM Identifiers */
#define MFG10_OEM_ID_INVALID (0x00000000)
@@ -575,6 +576,7 @@ struct _sas_device {
u8 is_chassis_slot_valid;
u8 connector_name[5];
struct kref refcount;
+ u8 port_type;
struct hba_port *port;
struct sas_rphy *rphy;
};
@@ -936,6 +938,8 @@ struct _event_ack_list {
* @os_irq: irq number
* @irqpoll: irq_poll object
* @irq_poll_scheduled: Tells whether irq poll is scheduled or not
+ * @is_iouring_poll_q: Tells whether reply queues is assigned
+ * to io uring poll queues or not
* @list: this list
*/
struct adapter_reply_queue {
@@ -949,9 +953,22 @@ struct adapter_reply_queue {
struct irq_poll irqpoll;
bool irq_poll_scheduled;
bool irq_line_enable;
+ bool is_iouring_poll_q;
struct list_head list;
};
+/**
+ * struct io_uring_poll_queue - the io uring poll queue structure
+ * @busy: Tells whether io uring poll queue is busy or not
+ * @pause: Tells whether IOs are paused on io uring poll queue or not
+ * @reply_q: reply queue mapped for io uring poll queue
+ */
+struct io_uring_poll_queue {
+ atomic_t busy;
+ atomic_t pause;
+ struct adapter_reply_queue *reply_q;
+};
+
typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
/* SAS3.0 support */
@@ -1176,6 +1193,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
* @thresh_hold: Max number of reply descriptors processed
* before updating Host Index
+ * @iopoll_q_start_index: starting index of io uring poll queues
+ * in reply queue list
* @drv_internal_flags: Bit map internal to driver
* @drv_support_bitmap: driver's supported feature bit map
* @use_32bit_dma: Flag to use 32 bit consistent dma mask
@@ -1372,11 +1391,13 @@ struct MPT3SAS_ADAPTER {
bool msix_load_balance;
u16 thresh_hold;
u8 high_iops_queues;
+ u8 iopoll_q_start_index;
u32 drv_internal_flags;
u32 drv_support_bitmap;
u32 dma_mask;
bool enable_sdev_max_qd;
bool use_32bit_dma;
+ struct io_uring_poll_queue *io_uring_poll_queues;
/* internal commands, callback index */
u8 scsi_io_cb_idx;
@@ -1423,6 +1444,10 @@ struct MPT3SAS_ADAPTER {
u8 tm_custom_handling;
u8 nvme_abort_timeout;
u16 max_shutdown_latency;
+ u16 max_wideport_qd;
+ u16 max_narrowport_qd;
+ u16 max_nvme_qd;
+ u8 max_sata_qd;
/* static config pages */
struct mpt3sas_facts facts;
@@ -1730,10 +1755,12 @@ do { ioc_err(ioc, "In func: %s\n", __func__); \
status, mpi_request, sz); } while (0)
int mpt3sas_wait_for_ioc(struct MPT3SAS_ADAPTER *ioc, int wait_count);
-int
-mpt3sas_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type);
+int mpt3sas_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type);
void mpt3sas_base_free_irq(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_base_disable_msix(struct MPT3SAS_ADAPTER *ioc);
+int mpt3sas_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num);
+void mpt3sas_base_pause_mq_polling(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_base_resume_mq_polling(struct MPT3SAS_ADAPTER *ioc);
/* scsih shared API */
struct scsi_cmnd *mpt3sas_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc,
@@ -1829,6 +1856,9 @@ int mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
int mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
u32 form, u32 handle);
+int mpt3sas_config_get_pcie_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeIOUnitPage1_t *config_page,
+ u16 sz);
int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
u16 sz);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
index 83a5c2172ad4..0563078227de 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -1169,6 +1169,43 @@ out:
}
/**
+ * mpt3sas_config_get_pcie_iounit_pg1 - obtain pcie iounit page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_pcie_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeIOUnitPage1_t *config_page,
+ u16 sz)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT;
+ mpi_request.Header.PageVersion = MPI26_PCIEIOUNITPAGE1_PAGEVERSION;
+ mpi_request.Header.PageNumber = 1;
+ ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+ if (r)
+ goto out;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
+out:
+ return r;
+}
+
+/**
* mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index b66140e4c370..770b241d7bb2 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -3820,9 +3820,10 @@ enable_sdev_max_qd_store(struct device *cdev,
}
} else if (sas_target_priv_data->flags &
MPT_TARGET_FLAGS_PCIE_DEVICE)
- qdepth = MPT3SAS_NVME_QUEUE_DEPTH;
+ qdepth = ioc->max_nvme_qd;
else
- qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
+ qdepth = (sas_target_priv_data->sas_dev->port_type > 1) ?
+ ioc->max_wideport_qd : ioc->max_narrowport_qd;
mpt3sas_scsih_change_queue_depth(sdev, qdepth);
}
@@ -3919,6 +3920,24 @@ sas_device_handle_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RO(sas_device_handle);
/**
+ * sas_ncq_prio_supported_show - Indicate if device supports NCQ priority
+ * @dev: pointer to embedded device
+ * @attr: sas_ncq_prio_supported attribute descriptor
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' sdev attribute, only works with SATA
+ */
+static ssize_t
+sas_ncq_prio_supported_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ return sysfs_emit(buf, "%d\n", scsih_ncq_prio_supp(sdev));
+}
+static DEVICE_ATTR_RO(sas_ncq_prio_supported);
+
+/**
* sas_ncq_prio_enable_show - send prioritized io commands to device
* @dev: pointer to embedded device
* @attr: ?
@@ -3960,6 +3979,7 @@ static DEVICE_ATTR_RW(sas_ncq_prio_enable);
struct device_attribute *mpt3sas_dev_attrs[] = {
&dev_attr_sas_address,
&dev_attr_sas_device_handle,
+ &dev_attr_sas_ncq_prio_supported,
&dev_attr_sas_ncq_prio_enable,
NULL,
};
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 8e64a6f14542..2f82b1e629af 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1803,7 +1803,7 @@ scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
* limit max device queue for SATA to 32 if enable_sdev_max_qd
* is disabled.
*/
- if (ioc->enable_sdev_max_qd)
+ if (ioc->enable_sdev_max_qd || ioc->is_gen35_ioc)
goto not_sata;
sas_device_priv_data = sdev->hostdata;
@@ -2657,7 +2657,7 @@ scsih_slave_configure(struct scsi_device *sdev)
return 1;
}
- qdepth = MPT3SAS_NVME_QUEUE_DEPTH;
+ qdepth = ioc->max_nvme_qd;
ds = "NVMe";
sdev_printk(KERN_INFO, sdev,
"%s: handle(0x%04x), wwid(0x%016llx), port(%d)\n",
@@ -2709,7 +2709,8 @@ scsih_slave_configure(struct scsi_device *sdev)
sas_device->volume_handle = volume_handle;
sas_device->volume_wwid = volume_wwid;
if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
- qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
+ qdepth = (sas_device->port_type > 1) ?
+ ioc->max_wideport_qd : ioc->max_narrowport_qd;
ssp_target = 1;
if (sas_device->device_info &
MPI2_SAS_DEVICE_INFO_SEP) {
@@ -2721,7 +2722,7 @@ scsih_slave_configure(struct scsi_device *sdev)
} else
ds = "SSP";
} else {
- qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
+ qdepth = ioc->max_sata_qd;
if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
ds = "STP";
else if (sas_device->device_info &
@@ -3304,7 +3305,7 @@ scsih_abort(struct scsi_cmnd *scmd)
sdev_printk(KERN_INFO, scmd->device, "attempting task abort!"
"scmd(0x%p), outstanding for %u ms & timeout %u ms\n",
scmd, jiffies_to_msecs(jiffies - scmd->jiffies_at_alloc),
- (scmd->request->timeout / HZ) * 1000);
+ (scsi_cmd_to_rq(scmd)->timeout / HZ) * 1000);
_scsih_tm_display_info(ioc, scmd);
sas_device_priv_data = scmd->device->hostdata;
@@ -5047,48 +5048,31 @@ _scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
Mpi25SCSIIORequest_t *mpi_request)
{
u16 eedp_flags;
- unsigned char prot_op = scsi_get_prot_op(scmd);
- unsigned char prot_type = scsi_get_prot_type(scmd);
Mpi25SCSIIORequest_t *mpi_request_3v =
(Mpi25SCSIIORequest_t *)mpi_request;
- if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
- return;
-
- if (prot_op == SCSI_PROT_READ_STRIP)
+ switch (scsi_get_prot_op(scmd)) {
+ case SCSI_PROT_READ_STRIP:
eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
- else if (prot_op == SCSI_PROT_WRITE_INSERT)
+ break;
+ case SCSI_PROT_WRITE_INSERT:
eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
- else
+ break;
+ default:
return;
+ }
- switch (prot_type) {
- case SCSI_PROT_DIF_TYPE1:
- case SCSI_PROT_DIF_TYPE2:
+ if (scmd->prot_flags & SCSI_PROT_GUARD_CHECK)
+ eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
- /*
- * enable ref/guard checking
- * auto increment ref tag
- */
+ if (scmd->prot_flags & SCSI_PROT_REF_CHECK) {
eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
- MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
- MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG;
mpi_request->CDB.EEDP32.PrimaryReferenceTag =
- cpu_to_be32(t10_pi_ref_tag(scmd->request));
- break;
-
- case SCSI_PROT_DIF_TYPE3:
-
- /*
- * enable guard checking
- */
- eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
-
- break;
+ cpu_to_be32(scsi_prot_ref_tag(scmd));
}
- mpi_request_3v->EEDPBlockSize =
- cpu_to_le16(scmd->device->sector_size);
+ mpi_request_3v->EEDPBlockSize = cpu_to_le16(scsi_prot_interval(scmd));
if (ioc->is_gen35_ioc)
eedp_flags |= MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE;
@@ -5141,7 +5125,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
struct MPT3SAS_DEVICE *sas_device_priv_data;
struct MPT3SAS_TARGET *sas_target_priv_data;
struct _raid_device *raid_device;
- struct request *rq = scmd->request;
+ struct request *rq = scsi_cmd_to_rq(scmd);
int class;
Mpi25SCSIIORequest_t *mpi_request;
struct _pcie_device *pcie_device = NULL;
@@ -7371,6 +7355,10 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
/* get device name */
sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
+ sas_device->port_type = sas_device_pg0.MaxPortConnections;
+ ioc_info(ioc,
+ "handle(0x%0x) sas_address(0x%016llx) port_type(0x%0x)\n",
+ handle, sas_device->sas_address, sas_device->port_type);
if (ioc->wait_for_discovery_to_complete)
_scsih_sas_device_init_add(ioc, sas_device);
@@ -9604,6 +9592,42 @@ _scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
}
/**
+ * _scsih_update_device_qdepth - Update QD during Reset.
+ * @ioc: per adapter object
+ *
+ */
+static void
+_scsih_update_device_qdepth(struct MPT3SAS_ADAPTER *ioc)
+{
+ struct MPT3SAS_DEVICE *sas_device_priv_data;
+ struct MPT3SAS_TARGET *sas_target_priv_data;
+ struct _sas_device *sas_device;
+ struct scsi_device *sdev;
+ u16 qdepth;
+
+ ioc_info(ioc, "Update devices with firmware reported queue depth\n");
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (sas_device_priv_data && sas_device_priv_data->sas_target) {
+ sas_target_priv_data = sas_device_priv_data->sas_target;
+ sas_device = sas_device_priv_data->sas_target->sas_dev;
+ if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_PCIE_DEVICE)
+ qdepth = ioc->max_nvme_qd;
+ else if (sas_device &&
+ sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
+ qdepth = (sas_device->port_type > 1) ?
+ ioc->max_wideport_qd : ioc->max_narrowport_qd;
+ else if (sas_device &&
+ sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+ qdepth = ioc->max_sata_qd;
+ else
+ continue;
+ mpt3sas_scsih_change_queue_depth(sdev, qdepth);
+ }
+ }
+}
+
+/**
* _scsih_mark_responding_sas_device - mark a sas_devices as responding
* @ioc: per adapter object
* @sas_device_pg0: SAS Device page 0
@@ -10654,6 +10678,8 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
_scsih_remove_unresponding_devices(ioc);
_scsih_del_dirty_vphy(ioc);
_scsih_del_dirty_port_entries(ioc);
+ if (ioc->is_gen35_ioc)
+ _scsih_update_device_qdepth(ioc);
_scsih_scan_for_devices_after_reset(ioc);
/*
* If diag reset has occurred during the driver load
@@ -11178,8 +11204,10 @@ static void scsih_remove(struct pci_dev *pdev)
ioc->remove_host = 1;
- if (!pci_device_is_present(pdev))
+ if (!pci_device_is_present(pdev)) {
+ mpt3sas_base_pause_mq_polling(ioc);
_scsih_flush_running_cmds(ioc);
+ }
_scsih_fw_event_cleanup_queue(ioc);
@@ -11274,8 +11302,10 @@ scsih_shutdown(struct pci_dev *pdev)
ioc->remove_host = 1;
- if (!pci_device_is_present(pdev))
+ if (!pci_device_is_present(pdev)) {
+ mpt3sas_base_pause_mq_polling(ioc);
_scsih_flush_running_cmds(ioc);
+ }
_scsih_fw_event_cleanup_queue(ioc);
@@ -11785,12 +11815,41 @@ static int scsih_map_queues(struct Scsi_Host *shost)
{
struct MPT3SAS_ADAPTER *ioc =
(struct MPT3SAS_ADAPTER *)shost->hostdata;
+ struct blk_mq_queue_map *map;
+ int i, qoff, offset;
+ int nr_msix_vectors = ioc->iopoll_q_start_index;
+ int iopoll_q_count = ioc->reply_queue_count - nr_msix_vectors;
- if (ioc->shost->nr_hw_queues == 1)
+ if (shost->nr_hw_queues == 1)
return 0;
- return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
- ioc->pdev, ioc->high_iops_queues);
+ for (i = 0, qoff = 0; i < shost->nr_maps; i++) {
+ map = &shost->tag_set.map[i];
+ map->nr_queues = 0;
+ offset = 0;
+ if (i == HCTX_TYPE_DEFAULT) {
+ map->nr_queues =
+ nr_msix_vectors - ioc->high_iops_queues;
+ offset = ioc->high_iops_queues;
+ } else if (i == HCTX_TYPE_POLL)
+ map->nr_queues = iopoll_q_count;
+
+ if (!map->nr_queues)
+ BUG_ON(i == HCTX_TYPE_DEFAULT);
+
+ /*
+ * The poll queue(s) doesn't have an IRQ (and hence IRQ
+ * affinity), so use the regular blk-mq cpu mapping
+ */
+ map->queue_offset = qoff;
+ if (i != HCTX_TYPE_POLL)
+ blk_mq_pci_map_queues(map, ioc->pdev, offset);
+ else
+ blk_mq_map_queues(map);
+
+ qoff += map->nr_queues;
+ }
+ return 0;
}
/* shost template for SAS 2.0 HBA devices */
@@ -11861,6 +11920,7 @@ static struct scsi_host_template mpt3sas_driver_template = {
.track_queue_depth = 1,
.cmd_size = sizeof(struct scsiio_tracker),
.map_queues = scsih_map_queues,
+ .mq_poll = mpt3sas_blk_mq_poll,
};
/* raid transport support for SAS 3.0 HBA devices */
@@ -11957,6 +12017,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct Scsi_Host *shost = NULL;
int rv;
u16 hba_mpi_version;
+ int iopoll_q_count = 0;
/* Determine in which MPI version class this pci device belongs */
hba_mpi_version = _scsih_determine_hba_mpi_version(pdev);
@@ -12204,6 +12265,11 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_thread_fail;
}
+ shost->host_tagset = 0;
+
+ if (ioc->is_gen35_ioc && host_tagset_enable)
+ shost->host_tagset = 1;
+
ioc->is_driver_loading = 1;
if ((mpt3sas_base_attach(ioc))) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
@@ -12226,16 +12292,17 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
} else
ioc->hide_drives = 0;
- shost->host_tagset = 0;
shost->nr_hw_queues = 1;
- if (ioc->is_gen35_ioc && ioc->reply_queue_count > 1 &&
- host_tagset_enable && ioc->smp_affinity_enable) {
-
- shost->host_tagset = 1;
+ if (shost->host_tagset) {
shost->nr_hw_queues =
ioc->reply_queue_count - ioc->high_iops_queues;
+ iopoll_q_count =
+ ioc->reply_queue_count - ioc->iopoll_q_start_index;
+
+ shost->nr_maps = iopoll_q_count ? 3 : 1;
+
dev_info(&ioc->pdev->dev,
"Max SCSIIO MPT commands: %d shared with nr_hw_queues = %d\n",
shost->can_queue, shost->nr_hw_queues);
@@ -12359,6 +12426,7 @@ scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
/* Permanent error, prepare for device removal */
ioc->pci_error_recovery = 1;
mpt3sas_base_stop_watchdog(ioc);
+ mpt3sas_base_pause_mq_polling(ioc);
_scsih_flush_running_cmds(ioc);
return PCI_ERS_RESULT_DISCONNECT;
}
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index 6bb03d7a254d..4d251bf630a3 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -702,7 +702,7 @@ static int mvumi_host_reset(struct scsi_cmnd *scmd)
mhba = (struct mvumi_hba *) scmd->device->host->hostdata;
scmd_printk(KERN_NOTICE, scmd, "RESET -%u cmd=%x retries=%x\n",
- scmd->request->tag, scmd->cmnd[0], scmd->retries);
+ scsi_cmd_to_rq(scmd)->tag, scmd->cmnd[0], scmd->retries);
return mhba->instancet->reset_host(mhba);
}
diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c
index 542ed88ef90d..a4a88323e020 100644
--- a/drivers/scsi/myrb.c
+++ b/drivers/scsi/myrb.c
@@ -1263,6 +1263,7 @@ static int myrb_host_reset(struct scsi_cmnd *scmd)
static int myrb_pthru_queuecommand(struct Scsi_Host *shost,
struct scsi_cmnd *scmd)
{
+ struct request *rq = scsi_cmd_to_rq(scmd);
struct myrb_hba *cb = shost_priv(shost);
struct myrb_cmdblk *cmd_blk = scsi_cmd_priv(scmd);
union myrb_cmd_mbox *mbox = &cmd_blk->mbox;
@@ -1286,7 +1287,7 @@ static int myrb_pthru_queuecommand(struct Scsi_Host *shost,
}
mbox->type3.opcode = MYRB_CMD_DCDB;
- mbox->type3.id = scmd->request->tag + 3;
+ mbox->type3.id = rq->tag + 3;
mbox->type3.addr = dcdb_addr;
dcdb->channel = sdev->channel;
dcdb->target = sdev->id;
@@ -1305,11 +1306,11 @@ static int myrb_pthru_queuecommand(struct Scsi_Host *shost,
break;
}
dcdb->early_status = false;
- if (scmd->request->timeout <= 10)
+ if (rq->timeout <= 10)
dcdb->timeout = MYRB_DCDB_TMO_10_SECS;
- else if (scmd->request->timeout <= 60)
+ else if (rq->timeout <= 60)
dcdb->timeout = MYRB_DCDB_TMO_60_SECS;
- else if (scmd->request->timeout <= 600)
+ else if (rq->timeout <= 600)
dcdb->timeout = MYRB_DCDB_TMO_10_MINS;
else
dcdb->timeout = MYRB_DCDB_TMO_24_HRS;
@@ -1550,7 +1551,7 @@ static int myrb_ldev_queuecommand(struct Scsi_Host *shost,
}
myrb_reset_cmd(cmd_blk);
- mbox->type5.id = scmd->request->tag + 3;
+ mbox->type5.id = scsi_cmd_to_rq(scmd)->tag + 3;
if (scmd->sc_data_direction == DMA_NONE)
goto submit;
nsge = scsi_dma_map(scmd);
diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c
index 26326af23dbc..07f274afd7e5 100644
--- a/drivers/scsi/myrs.c
+++ b/drivers/scsi/myrs.c
@@ -1582,6 +1582,7 @@ static void myrs_mode_sense(struct myrs_hba *cs, struct scsi_cmnd *scmd,
static int myrs_queuecommand(struct Scsi_Host *shost,
struct scsi_cmnd *scmd)
{
+ struct request *rq = scsi_cmd_to_rq(scmd);
struct myrs_hba *cs = shost_priv(shost);
struct myrs_cmdblk *cmd_blk = scsi_cmd_priv(scmd);
union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
@@ -1628,7 +1629,7 @@ static int myrs_queuecommand(struct Scsi_Host *shost,
return SCSI_MLQUEUE_HOST_BUSY;
cmd_blk->sense_addr = sense_addr;
- timeout = scmd->request->timeout;
+ timeout = rq->timeout;
if (scmd->cmd_len <= 10) {
if (scmd->device->channel >= cs->ctlr_info->physchan_present) {
struct myrs_ldev_info *ldev_info = sdev->hostdata;
@@ -1644,10 +1645,10 @@ static int myrs_queuecommand(struct Scsi_Host *shost,
mbox->SCSI_10.pdev.target = sdev->id;
mbox->SCSI_10.pdev.channel = sdev->channel;
}
- mbox->SCSI_10.id = scmd->request->tag + 3;
+ mbox->SCSI_10.id = rq->tag + 3;
mbox->SCSI_10.control.dma_ctrl_to_host =
(scmd->sc_data_direction == DMA_FROM_DEVICE);
- if (scmd->request->cmd_flags & REQ_FUA)
+ if (rq->cmd_flags & REQ_FUA)
mbox->SCSI_10.control.fua = true;
mbox->SCSI_10.dma_size = scsi_bufflen(scmd);
mbox->SCSI_10.sense_addr = cmd_blk->sense_addr;
@@ -1690,10 +1691,10 @@ static int myrs_queuecommand(struct Scsi_Host *shost,
mbox->SCSI_255.pdev.target = sdev->id;
mbox->SCSI_255.pdev.channel = sdev->channel;
}
- mbox->SCSI_255.id = scmd->request->tag + 3;
+ mbox->SCSI_255.id = rq->tag + 3;
mbox->SCSI_255.control.dma_ctrl_to_host =
(scmd->sc_data_direction == DMA_FROM_DEVICE);
- if (scmd->request->cmd_flags & REQ_FUA)
+ if (rq->cmd_flags & REQ_FUA)
mbox->SCSI_255.control.fua = true;
mbox->SCSI_255.dma_size = scsi_bufflen(scmd);
mbox->SCSI_255.sense_addr = cmd_blk->sense_addr;
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index c76e9f05d042..7a4f5d4dd670 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -1453,11 +1453,6 @@ struct head {
#define xerr_status phys.xerr_st
#define nego_status phys.nego_st
-#if 0
-#define sync_status phys.sync_st
-#define wide_status phys.wide_st
-#endif
-
/*==========================================================
**
** Declaration of structs: Data structure block
@@ -1980,9 +1975,6 @@ static inline char *ncr_name (struct ncb *np)
#define RELOC_SOFTC 0x40000000
#define RELOC_LABEL 0x50000000
#define RELOC_REGISTER 0x60000000
-#if 0
-#define RELOC_KVAR 0x70000000
-#endif
#define RELOC_LABELH 0x80000000
#define RELOC_MASK 0xf0000000
@@ -1991,21 +1983,7 @@ static inline char *ncr_name (struct ncb *np)
#define PADDRH(label) (RELOC_LABELH | offsetof(struct scripth, label))
#define RADDR(label) (RELOC_REGISTER | REG(label))
#define FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs)))
-#if 0
-#define KVAR(which) (RELOC_KVAR | (which))
-#endif
-#if 0
-#define SCRIPT_KVAR_JIFFIES (0)
-#define SCRIPT_KVAR_FIRST SCRIPT_KVAR_JIFFIES
-#define SCRIPT_KVAR_LAST SCRIPT_KVAR_JIFFIES
-/*
- * Kernel variables referenced in the scripts.
- * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY.
- */
-static void *script_kvars[] __initdata =
- { (void *)&jiffies };
-#endif
static struct script script0 __initdata = {
/*--------------------------< START >-----------------------*/ {
@@ -2162,11 +2140,6 @@ static struct script script0 __initdata = {
SCR_COPY (1),
RADDR (scratcha),
NADDR (msgout),
-#if 0
- SCR_COPY (1),
- RADDR (scratcha),
- NADDR (msgin),
-#endif
/*
** Anticipate the COMMAND phase.
** This is the normal case for initial selection.
@@ -4164,8 +4137,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**
**----------------------------------------------------
*/
- if (np->settle_time && cmd->request->timeout >= HZ) {
- u_long tlimit = jiffies + cmd->request->timeout - HZ;
+ if (np->settle_time && scsi_cmd_to_rq(cmd)->timeout >= HZ) {
+ u_long tlimit = jiffies + scsi_cmd_to_rq(cmd)->timeout - HZ;
if (time_after(np->settle_time, tlimit))
np->settle_time = tlimit;
}
@@ -4378,10 +4351,6 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
cp->parity_status = 0;
cp->xerr_status = XE_OK;
-#if 0
- cp->sync_status = tp->sval;
- cp->wide_status = tp->wval;
-#endif
/*----------------------------------------------------
**
@@ -4553,12 +4522,8 @@ static void ncr_start_reset(struct ncb *np)
**
**==========================================================
*/
-static int ncr_reset_bus (struct ncb *np, struct scsi_cmnd *cmd, int sync_reset)
+static int ncr_reset_bus (struct ncb *np)
{
-/* struct scsi_device *device = cmd->device; */
- struct ccb *cp;
- int found;
-
/*
* Return immediately if reset is in progress.
*/
@@ -4573,24 +4538,6 @@ static int ncr_reset_bus (struct ncb *np, struct scsi_cmnd *cmd, int sync_reset)
*/
ncr_start_reset(np);
/*
- * First, look in the wakeup list
- */
- for (found=0, cp=np->ccb; cp; cp=cp->link_ccb) {
- /*
- ** look for the ccb of this command.
- */
- if (cp->host_status == HS_IDLE) continue;
- if (cp->cmd == cmd) {
- found = 1;
- break;
- }
- }
-/*
- * Then, look in the waiting list
- */
- if (!found && retrieve_from_waiting_list(0, np, cmd))
- found = 1;
-/*
* Wake-up all awaiting commands with DID_RESET.
*/
reset_waiting_list(np);
@@ -4598,103 +4545,10 @@ static int ncr_reset_bus (struct ncb *np, struct scsi_cmnd *cmd, int sync_reset)
* Wake-up all pending commands with HS_RESET -> DID_RESET.
*/
ncr_wakeup(np, HS_RESET);
-/*
- * If the involved command was not in a driver queue, and the
- * scsi driver told us reset is synchronous, and the command is not
- * currently in the waiting list, complete it with DID_RESET status,
- * in order to keep it alive.
- */
- if (!found && sync_reset && !retrieve_from_waiting_list(0, np, cmd)) {
- set_host_byte(cmd, DID_RESET);
- ncr_queue_done_cmd(np, cmd);
- }
return SUCCESS;
}
-#if 0 /* unused and broken.. */
-/*==========================================================
-**
-**
-** Abort an SCSI command.
-** This is called from the generic SCSI driver.
-**
-**
-**==========================================================
-*/
-static int ncr_abort_command (struct ncb *np, struct scsi_cmnd *cmd)
-{
-/* struct scsi_device *device = cmd->device; */
- struct ccb *cp;
- int found;
- int retv;
-
-/*
- * First, look for the scsi command in the waiting list
- */
- if (remove_from_waiting_list(np, cmd)) {
- set_host_byte(cmd, DID_ABORT);
- ncr_queue_done_cmd(np, cmd);
- return SCSI_ABORT_SUCCESS;
- }
-
-/*
- * Then, look in the wakeup list
- */
- for (found=0, cp=np->ccb; cp; cp=cp->link_ccb) {
- /*
- ** look for the ccb of this command.
- */
- if (cp->host_status == HS_IDLE) continue;
- if (cp->cmd == cmd) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- if (np->settle_time) {
- return SCSI_ABORT_SNOOZE;
- }
-
- /*
- ** If the CCB is active, patch schedule jumps for the
- ** script to abort the command.
- */
-
- switch(cp->host_status) {
- case HS_BUSY:
- case HS_NEGOTIATE:
- printk ("%s: abort ccb=%p (cancel)\n", ncr_name (np), cp);
- cp->start.schedule.l_paddr =
- cpu_to_scr(NCB_SCRIPTH_PHYS (np, cancel));
- retv = SCSI_ABORT_PENDING;
- break;
- case HS_DISCONNECT:
- cp->restart.schedule.l_paddr =
- cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort));
- retv = SCSI_ABORT_PENDING;
- break;
- default:
- retv = SCSI_ABORT_NOT_RUNNING;
- break;
-
- }
-
- /*
- ** If there are no requests, the script
- ** processor will sleep on SEL_WAIT_RESEL.
- ** Let's wake it up, since it may have to work.
- */
- OUTB (nc_istat, SIGP);
-
- return retv;
-}
-#endif
-
static void ncr_detach(struct ncb *np)
{
struct ccb *cp;
@@ -5453,27 +5307,6 @@ static void ncr_getsync(struct ncb *np, u_char sfac, u_char *fakp, u_char *scntl
*/
fak = (kpc - 1) / div_10M[div] + 1;
-#if 0 /* This optimization does not seem very useful */
-
- per = (fak * div_10M[div]) / clk;
-
- /*
- ** Why not to try the immediate lower divisor and to choose
- ** the one that allows the fastest output speed ?
- ** We don't want input speed too much greater than output speed.
- */
- if (div >= 1 && fak < 8) {
- u_long fak2, per2;
- fak2 = (kpc - 1) / div_10M[div-1] + 1;
- per2 = (fak2 * div_10M[div-1]) / clk;
- if (per2 < per && fak2 <= 8) {
- fak = fak2;
- per = per2;
- --div;
- }
- }
-#endif
-
if (fak < 4) fak = 4; /* Should never happen, too bad ... */
/*
@@ -5511,10 +5344,6 @@ static void ncr_set_sync_wide_status (struct ncb *np, u_char target)
for (cp = np->ccb; cp; cp = cp->link_ccb) {
if (!cp->cmd) continue;
if (scmd_id(cp->cmd) != target) continue;
-#if 0
- cp->sync_status = tp->sval;
- cp->wide_status = tp->wval;
-#endif
cp->phys.select.sel_scntl3 = tp->wval;
cp->phys.select.sel_sxfer = tp->sval;
}
@@ -8125,7 +7954,7 @@ static int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd)
*/
spin_lock_irqsave(&np->smp_lock, flags);
- sts = ncr_reset_bus(np, cmd, 1);
+ sts = ncr_reset_bus(np);
done_list = np->done_list;
np->done_list = NULL;
@@ -8136,30 +7965,6 @@ static int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd)
return sts;
}
-#if 0 /* unused and broken */
-static int ncr53c8xx_abort(struct scsi_cmnd *cmd)
-{
- struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb;
- int sts;
- unsigned long flags;
- struct scsi_cmnd *done_list;
-
- printk("ncr53c8xx_abort\n");
-
- NCR_LOCK_NCB(np, flags);
-
- sts = ncr_abort_command(np, cmd);
-out:
- done_list = np->done_list;
- np->done_list = NULL;
- NCR_UNLOCK_NCB(np, flags);
-
- ncr_flush_done_cmds(done_list);
-
- return sts;
-}
-#endif
-
/*
** Scsi command waiting list management.
diff --git a/drivers/scsi/pcmcia/fdomain_cs.c b/drivers/scsi/pcmcia/fdomain_cs.c
index e42acf314d06..33df6a9ba9b5 100644
--- a/drivers/scsi/pcmcia/fdomain_cs.c
+++ b/drivers/scsi/pcmcia/fdomain_cs.c
@@ -45,8 +45,10 @@ static int fdomain_probe(struct pcmcia_device *link)
goto fail_disable;
if (!request_region(link->resource[0]->start, FDOMAIN_REGION_SIZE,
- "fdomain_cs"))
+ "fdomain_cs")) {
+ ret = -EBUSY;
goto fail_disable;
+ }
sh = fdomain_create(link->resource[0]->start, link->irq, 7, &link->dev);
if (!sh) {
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 17c0f26e683a..63690508313b 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1323,7 +1323,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
void *pMessage;
unsigned long flags;
int q_index = circularQ - pm8001_ha->inbnd_q_tbl;
- int rv = -1;
+ int rv;
WARN_ON(q_index >= PM8001_MAX_INB_NUM);
spin_lock_irqsave(&circularQ->iq_lock, flags);
diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c
index 6b5b6a75ac88..3404782988d5 100644
--- a/drivers/scsi/qedf/qedf_io.c
+++ b/drivers/scsi/qedf/qedf_io.c
@@ -1162,13 +1162,7 @@ void qedf_scsi_completion(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
return;
}
- if (!sc_cmd->request) {
- QEDF_WARN(&(qedf->dbg_ctx), "sc_cmd->request is NULL, "
- "sc_cmd=%p.\n", sc_cmd);
- return;
- }
-
- if (!sc_cmd->request->q) {
+ if (!scsi_cmd_to_rq(sc_cmd)->q) {
QEDF_WARN(&(qedf->dbg_ctx), "request->q is NULL so request "
"is not valid, sc_cmd=%p.\n", sc_cmd);
return;
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 85f41abcb56c..42d0d941dba5 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -3004,7 +3004,7 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
{
u32 *list;
int i;
- int status = 0, rc;
+ int status;
u32 *pbl;
dma_addr_t page;
int num_pages;
@@ -3016,7 +3016,7 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
*/
if (!qedf->num_queues) {
QEDF_ERR(&(qedf->dbg_ctx), "No MSI-X vectors available!\n");
- return 1;
+ return -ENOMEM;
}
/*
@@ -3024,7 +3024,7 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
* addresses of our queues
*/
if (!qedf->p_cpuq) {
- status = 1;
+ status = -EINVAL;
QEDF_ERR(&qedf->dbg_ctx, "p_cpuq is NULL.\n");
goto mem_alloc_failure;
}
@@ -3040,8 +3040,8 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
"qedf->global_queues=%p.\n", qedf->global_queues);
/* Allocate DMA coherent buffers for BDQ */
- rc = qedf_alloc_bdq(qedf);
- if (rc) {
+ status = qedf_alloc_bdq(qedf);
+ if (status) {
QEDF_ERR(&qedf->dbg_ctx, "Unable to allocate bdq.\n");
goto mem_alloc_failure;
}
diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c
index 71333d3c5c86..d01cd829ef97 100644
--- a/drivers/scsi/qedi/qedi_fw.c
+++ b/drivers/scsi/qedi/qedi_fw.c
@@ -609,14 +609,7 @@ static void qedi_scsi_completion(struct qedi_ctx *qedi,
goto error;
}
- if (!sc_cmd->request) {
- QEDI_WARN(&qedi->dbg_ctx,
- "sc_cmd->request is NULL, sc_cmd=%p.\n",
- sc_cmd);
- goto error;
- }
-
- if (!sc_cmd->request->q) {
+ if (!scsi_cmd_to_rq(sc_cmd)->q) {
QEDI_WARN(&qedi->dbg_ctx,
"request->q is NULL so request is not valid, sc_cmd=%p.\n",
sc_cmd);
@@ -936,17 +929,11 @@ exit_fp_process:
static void qedi_ring_doorbell(struct qedi_conn *qedi_conn)
{
- struct iscsi_db_data dbell = { 0 };
-
- dbell.agg_flags = 0;
+ qedi_conn->ep->db_data.sq_prod = qedi_conn->ep->fw_sq_prod_idx;
- dbell.params |= DB_DEST_XCM << ISCSI_DB_DATA_DEST_SHIFT;
- dbell.params |= DB_AGG_CMD_SET << ISCSI_DB_DATA_AGG_CMD_SHIFT;
- dbell.params |=
- DQ_XCM_ISCSI_SQ_PROD_CMD << ISCSI_DB_DATA_AGG_VAL_SEL_SHIFT;
-
- dbell.sq_prod = qedi_conn->ep->fw_sq_prod_idx;
- writel(*(u32 *)&dbell, qedi_conn->ep->p_doorbell);
+ /* wmb - Make sure fw idx is coherent */
+ wmb();
+ writel(*(u32 *)&qedi_conn->ep->db_data, qedi_conn->ep->p_doorbell);
/* Make sure fw write idx is coherent, and include both memory barriers
* as a failsafe as for some architectures the call is the same but on
diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
index 97f83760da88..c5260429c637 100644
--- a/drivers/scsi/qedi/qedi_iscsi.c
+++ b/drivers/scsi/qedi/qedi_iscsi.c
@@ -499,8 +499,8 @@ static u16 qedi_calc_mss(u16 pmtu, u8 is_ipv6, u8 tcp_ts_en, u8 vlan_en)
static int qedi_iscsi_offload_conn(struct qedi_endpoint *qedi_ep)
{
- struct qedi_ctx *qedi = qedi_ep->qedi;
struct qed_iscsi_params_offload *conn_info;
+ struct qedi_ctx *qedi = qedi_ep->qedi;
int rval;
int i;
@@ -577,10 +577,37 @@ static int qedi_iscsi_offload_conn(struct qedi_endpoint *qedi_ep)
"Default cq index [%d], mss [%d]\n",
conn_info->default_cq, conn_info->mss);
+ /* Prepare the doorbell parameters */
+ qedi_ep->db_data.agg_flags = 0;
+ qedi_ep->db_data.params = 0;
+ SET_FIELD(qedi_ep->db_data.params, ISCSI_DB_DATA_DEST, DB_DEST_XCM);
+ SET_FIELD(qedi_ep->db_data.params, ISCSI_DB_DATA_AGG_CMD,
+ DB_AGG_CMD_MAX);
+ SET_FIELD(qedi_ep->db_data.params, ISCSI_DB_DATA_AGG_VAL_SEL,
+ DQ_XCM_ISCSI_SQ_PROD_CMD);
+ SET_FIELD(qedi_ep->db_data.params, ISCSI_DB_DATA_BYPASS_EN, 1);
+
+ /* Register doorbell with doorbell recovery mechanism */
+ rval = qedi_ops->common->db_recovery_add(qedi->cdev,
+ qedi_ep->p_doorbell,
+ &qedi_ep->db_data,
+ DB_REC_WIDTH_32B,
+ DB_REC_KERNEL);
+ if (rval) {
+ kfree(conn_info);
+ return rval;
+ }
+
rval = qedi_ops->offload_conn(qedi->cdev, qedi_ep->handle, conn_info);
- if (rval)
+ if (rval) {
+ /* delete doorbell from doorbell recovery mechanism */
+ rval = qedi_ops->common->db_recovery_del(qedi->cdev,
+ qedi_ep->p_doorbell,
+ &qedi_ep->db_data);
+
QEDI_ERR(&qedi->dbg_ctx, "offload_conn returned %d, ep=%p\n",
rval, qedi_ep);
+ }
kfree(conn_info);
return rval;
@@ -1109,6 +1136,11 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
test_bit(QEDI_IN_RECOVERY, &qedi->flags))
goto ep_release_conn;
+ /* Delete doorbell from doorbell recovery mechanism */
+ ret = qedi_ops->common->db_recovery_del(qedi->cdev,
+ qedi_ep->p_doorbell,
+ &qedi_ep->db_data);
+
ret = qedi_ops->destroy_conn(qedi->cdev, qedi_ep->handle, abrt_conn);
if (ret) {
QEDI_WARN(&qedi->dbg_ctx,
diff --git a/drivers/scsi/qedi/qedi_iscsi.h b/drivers/scsi/qedi/qedi_iscsi.h
index 758735209e15..a31c5de74754 100644
--- a/drivers/scsi/qedi/qedi_iscsi.h
+++ b/drivers/scsi/qedi/qedi_iscsi.h
@@ -80,6 +80,7 @@ struct qedi_endpoint {
u32 handle;
u32 fw_cid;
void __iomem *p_doorbell;
+ struct iscsi_db_data db_data;
/* Send queue management */
struct iscsi_wqe *sq;
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index 0b0acb827071..e6dc0b495a82 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -1621,7 +1621,7 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
{
u32 *list;
int i;
- int status = 0, rc;
+ int status;
u32 *pbl;
dma_addr_t page;
int num_pages;
@@ -1632,14 +1632,14 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
*/
if (!qedi->num_queues) {
QEDI_ERR(&qedi->dbg_ctx, "No MSI-X vectors available!\n");
- return 1;
+ return -ENOMEM;
}
/* Make sure we allocated the PBL that will contain the physical
* addresses of our queues
*/
if (!qedi->p_cpuq) {
- status = 1;
+ status = -EINVAL;
goto mem_alloc_failure;
}
@@ -1654,13 +1654,13 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
"qedi->global_queues=%p.\n", qedi->global_queues);
/* Allocate DMA coherent buffers for BDQ */
- rc = qedi_alloc_bdq(qedi);
- if (rc)
+ status = qedi_alloc_bdq(qedi);
+ if (status)
goto mem_alloc_failure;
/* Allocate DMA coherent buffers for NVM_ISCSI_CFG */
- rc = qedi_alloc_nvm_iscsi_cfg(qedi);
- if (rc)
+ status = qedi_alloc_nvm_iscsi_cfg(qedi);
+ if (status)
goto mem_alloc_failure;
/* Allocate a CQ and an associated PBL for each MSI-X
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 928da90b79be..d0b4e063bfe1 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -490,7 +490,6 @@ __setup("qla1280=", qla1280_setup);
#define CMD_SNSLEN(Cmnd) SCSI_SENSE_BUFFERSIZE
#define CMD_RESULT(Cmnd) Cmnd->result
#define CMD_HANDLE(Cmnd) Cmnd->host_scribble
-#define CMD_REQUEST(Cmnd) Cmnd->request->cmd
#define CMD_HOST(Cmnd) Cmnd->device->host
#define SCSI_BUS_32(Cmnd) Cmnd->device->channel
@@ -2827,7 +2826,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
/* Set ISP command timeout. */
- pkt->timeout = cpu_to_le16(cmd->request->timeout/HZ);
+ pkt->timeout = cpu_to_le16(scsi_cmd_to_rq(cmd)->timeout / HZ);
/* Set device target ID and LUN */
pkt->lun = SCSI_LUN_32(cmd);
@@ -3082,7 +3081,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
/* Set ISP command timeout. */
- pkt->timeout = cpu_to_le16(cmd->request->timeout/HZ);
+ pkt->timeout = cpu_to_le16(scsi_cmd_to_rq(cmd)->timeout / HZ);
/* Set device target ID and LUN */
pkt->lun = SCSI_LUN_32(cmd);
@@ -3981,7 +3980,7 @@ __qla1280_print_scsi_cmd(struct scsi_cmnd *cmd)
qla1280_dump_buffer(1, (char *)sg, (cmd->use_sg*sizeof(struct scatterlist)));
} */
printk(" tag=%d, transfersize=0x%x \n",
- cmd->tag, cmd->transfersize);
+ scsi_cmd_to_rq(cmd)->tag, cmd->transfersize);
printk(" SP=0x%p\n", CMD_SP(cmd));
printk(" underflow size = 0x%x, direction=0x%x\n",
cmd->underflow, cmd->sc_data_direction);
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index 17d5bc1cc56b..cbc1303e761e 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \
- qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o
+ qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o \
+ qla_edif.o
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 3aa9869f6fae..d09776b77af2 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1887,6 +1887,30 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
return scnprintf(buf, PAGE_SIZE, "%s\n", spd[ha->link_data_rate]);
}
+static ssize_t
+qla2x00_mpi_pause_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ int rval = 0;
+
+ if (sscanf(buf, "%d", &rval) != 1)
+ return -EINVAL;
+
+ ql_log(ql_log_warn, vha, 0x7089, "Pausing MPI...\n");
+
+ rval = qla83xx_wr_reg(vha, 0x002012d4, 0x30000001);
+
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x708a, "Unable to pause MPI.\n");
+ count = 0;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(mpi_pause, S_IWUSR, NULL, qla2x00_mpi_pause_store);
+
/* ----- */
static ssize_t
@@ -2435,6 +2459,7 @@ static DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show,
qla2x00_port_speed_store);
static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL);
static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL);
+static DEVICE_ATTR_RO(edif_doorbell);
struct device_attribute *qla2x00_host_attrs[] = {
@@ -2480,6 +2505,8 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_port_no,
&dev_attr_fw_attr,
&dev_attr_dport_diagnostics,
+ &dev_attr_edif_doorbell,
+ &dev_attr_mpi_pause,
NULL, /* reserve for qlini_mode */
NULL, /* reserve for ql2xiniexchg */
NULL, /* reserve for ql2xexchoffld */
@@ -2706,12 +2733,14 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
* final cleanup of firmware resources (PCBs and XCBs).
*/
if (fcport->loop_id != FC_NO_LOOP_ID) {
- if (IS_FWI2_CAPABLE(fcport->vha->hw))
- fcport->vha->hw->isp_ops->fabric_logout(fcport->vha,
- fcport->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa);
- else
+ if (IS_FWI2_CAPABLE(fcport->vha->hw)) {
+ if (fcport->loop_id != FC_NO_LOOP_ID)
+ fcport->logout_on_delete = 1;
+
+ qlt_schedule_sess_for_deletion(fcport);
+ } else {
qla2x00_port_logout(fcport->vha, fcport);
+ }
}
}
@@ -3107,6 +3136,9 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
qla2x00_wait_for_sess_deletion(vha);
qla_nvme_delete(vha);
+ qla_enode_stop(vha);
+ qla_edb_stop(vha);
+
vha->flags.delete_progress = 1;
qlt_remove_target(ha, vha);
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index d42b2ad84049..4b5d28d89d69 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -25,6 +25,10 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
struct bsg_job *bsg_job = sp->u.bsg_job;
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ ql_dbg(ql_dbg_user, sp->vha, 0x7009,
+ "%s: sp hdl %x, result=%x bsg ptr %p\n",
+ __func__, sp->handle, res, bsg_job);
+
sp->free(sp);
bsg_reply->result = res;
@@ -53,11 +57,19 @@ void qla2x00_bsg_sp_free(srb_t *sp)
bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
} else {
- dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
- bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
- dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
- bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ if (sp->remap.remapped) {
+ dma_pool_free(ha->purex_dma_pool, sp->remap.rsp.buf,
+ sp->remap.rsp.dma);
+ dma_pool_free(ha->purex_dma_pool, sp->remap.req.buf,
+ sp->remap.req.dma);
+ } else {
+ dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
+
+ dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
+ }
}
if (sp->type == SRB_CT_CMD ||
@@ -266,6 +278,7 @@ qla2x00_process_els(struct bsg_job *bsg_job)
int req_sg_cnt, rsp_sg_cnt;
int rval = (DID_ERROR << 16);
uint16_t nextlid = 0;
+ uint32_t els_cmd = 0;
if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
rport = fc_bsg_to_rport(bsg_job);
@@ -279,6 +292,9 @@ qla2x00_process_els(struct bsg_job *bsg_job)
vha = shost_priv(host);
ha = vha->hw;
type = "FC_BSG_HST_ELS_NOLOGIN";
+ els_cmd = bsg_request->rqst_data.h_els.command_code;
+ if (els_cmd == ELS_AUTH_ELS)
+ return qla_edif_process_els(vha, bsg_job);
}
if (!vha->flags.online) {
@@ -2768,10 +2784,13 @@ qla2x00_manage_host_port(struct bsg_job *bsg_job)
}
static int
-qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
+qla2x00_process_vendor_specific(struct scsi_qla_host *vha, struct bsg_job *bsg_job)
{
struct fc_bsg_request *bsg_request = bsg_job->request;
+ ql_dbg(ql_dbg_edif, vha, 0x911b, "%s FC_BSG_HST_VENDOR cmd[0]=0x%x\n",
+ __func__, bsg_request->rqst_data.h_vendor.vendor_cmd[0]);
+
switch (bsg_request->rqst_data.h_vendor.vendor_cmd[0]) {
case QL_VND_LOOPBACK:
return qla2x00_process_loopback(bsg_job);
@@ -2840,6 +2859,9 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
case QL_VND_DPORT_DIAGNOSTICS:
return qla2x00_do_dport_diagnostics(bsg_job);
+ case QL_VND_EDIF_MGMT:
+ return qla_edif_app_mgmt(bsg_job);
+
case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
return qla2x00_get_flash_image_status(bsg_job);
@@ -2897,12 +2919,19 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
ql_dbg(ql_dbg_user, vha, 0x709f,
"BSG: ISP abort active/needed -- cmd=%d.\n",
bsg_request->msgcode);
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
return -EBUSY;
}
+ if (test_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags)) {
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ return -EIO;
+ }
+
skip_chip_chk:
- ql_dbg(ql_dbg_user, vha, 0x7000,
- "Entered %s msgcode=0x%x.\n", __func__, bsg_request->msgcode);
+ ql_dbg(ql_dbg_user + ql_dbg_verbose, vha, 0x7000,
+ "Entered %s msgcode=0x%x. bsg ptr %px\n",
+ __func__, bsg_request->msgcode, bsg_job);
switch (bsg_request->msgcode) {
case FC_BSG_RPT_ELS:
@@ -2913,7 +2942,7 @@ skip_chip_chk:
ret = qla2x00_process_ct(bsg_job);
break;
case FC_BSG_HST_VENDOR:
- ret = qla2x00_process_vendor_specific(bsg_job);
+ ret = qla2x00_process_vendor_specific(vha, bsg_job);
break;
case FC_BSG_HST_ADD_RPORT:
case FC_BSG_HST_DEL_RPORT:
@@ -2922,6 +2951,10 @@ skip_chip_chk:
ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n");
break;
}
+
+ ql_dbg(ql_dbg_user + ql_dbg_verbose, vha, 0x7000,
+ "%s done with return %x\n", __func__, ret);
+
return ret;
}
@@ -2936,6 +2969,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
unsigned long flags;
struct req_que *req;
+ ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n",
+ __func__, bsg_job);
/* find the bsg job from the active list of commands */
spin_lock_irqsave(&ha->hardware_lock, flags);
for (que = 0; que < ha->max_req_queues; que++) {
@@ -2945,27 +2980,26 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
- if (sp) {
- if (((sp->type == SRB_CT_CMD) ||
- (sp->type == SRB_ELS_CMD_HST) ||
- (sp->type == SRB_FXIOCB_BCMD))
- && (sp->u.bsg_job == bsg_job)) {
- req->outstanding_cmds[cnt] = NULL;
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- if (ha->isp_ops->abort_command(sp)) {
- ql_log(ql_log_warn, vha, 0x7089,
- "mbx abort_command "
- "failed.\n");
- bsg_reply->result = -EIO;
- } else {
- ql_dbg(ql_dbg_user, vha, 0x708a,
- "mbx abort_command "
- "success.\n");
- bsg_reply->result = 0;
- }
- spin_lock_irqsave(&ha->hardware_lock, flags);
- goto done;
+ if (sp &&
+ (sp->type == SRB_CT_CMD ||
+ sp->type == SRB_ELS_CMD_HST ||
+ sp->type == SRB_ELS_CMD_HST_NOLOGIN ||
+ sp->type == SRB_FXIOCB_BCMD) &&
+ sp->u.bsg_job == bsg_job) {
+ req->outstanding_cmds[cnt] = NULL;
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ if (ha->isp_ops->abort_command(sp)) {
+ ql_log(ql_log_warn, vha, 0x7089,
+ "mbx abort_command failed.\n");
+ bsg_reply->result = -EIO;
+ } else {
+ ql_dbg(ql_dbg_user, vha, 0x708a,
+ "mbx abort_command success.\n");
+ bsg_reply->result = 0;
}
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ goto done;
+
}
}
}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 0274e99e4a12..dd793cf8bc1e 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -31,6 +31,7 @@
#define QL_VND_DPORT_DIAGNOSTICS 0x19
#define QL_VND_GET_PRIV_STATS_EX 0x1A
#define QL_VND_SS_GET_FLASH_IMAGE_STATUS 0x1E
+#define QL_VND_EDIF_MGMT 0X1F
#define QL_VND_MANAGE_HOST_STATS 0x23
#define QL_VND_GET_HOST_STATS 0x24
#define QL_VND_GET_TGT_STATS 0x25
@@ -294,4 +295,6 @@ struct qla_active_regions {
uint8_t reserved[32];
} __packed;
+#include "qla_edif_bsg.h"
+
#endif
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index f2d05592c1e2..25549a8a2d72 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -12,8 +12,7 @@
* ----------------------------------------------------------------------
* | Module Init and Probe | 0x0199 | |
* | Mailbox commands | 0x1206 | 0x11a5-0x11ff |
- * | Device Discovery | 0x2134 | 0x210e-0x2116 |
- * | | | 0x211a |
+ * | Device Discovery | 0x2134 | 0x210e-0x2115 |
* | | | 0x211c-0x2128 |
* | | | 0x212c-0x2134 |
* | Queue Command and IO tracing | 0x3074 | 0x300b |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 9eb708e5e22e..f1f6c740bdcd 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -367,6 +367,7 @@ ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...);
#define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */
#define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */
#define ql_dbg_tgt_dif 0x00000800 /* Target mode dif */
+#define ql_dbg_edif 0x00000400 /* edif and purex debug */
extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,
uint32_t, void **);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 2f67ec1df3e6..be2eb75ee1a3 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -49,6 +49,28 @@ typedef struct {
uint8_t domain;
} le_id_t;
+/*
+ * 24 bit port ID type definition.
+ */
+typedef union {
+ uint32_t b24 : 24;
+ struct {
+#ifdef __BIG_ENDIAN
+ uint8_t domain;
+ uint8_t area;
+ uint8_t al_pa;
+#elif defined(__LITTLE_ENDIAN)
+ uint8_t al_pa;
+ uint8_t area;
+ uint8_t domain;
+#else
+#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
+#endif
+ uint8_t rsvd_1;
+ } b;
+} port_id_t;
+#define INVALID_PORT_ID 0xFFFFFF
+
#include "qla_bsg.h"
#include "qla_dsd.h"
#include "qla_nx.h"
@@ -319,6 +341,13 @@ struct name_list_extended {
u32 size;
u8 sent;
};
+
+struct els_reject {
+ struct fc_els_ls_rjt *c;
+ dma_addr_t cdma;
+ u16 size;
+};
+
/*
* Timeout timer counts in seconds
*/
@@ -345,6 +374,8 @@ struct name_list_extended {
#define FW_MAX_EXCHANGES_CNT (32 * 1024)
#define REDUCE_EXCHANGES_CNT (8 * 1024)
+#define SET_DID_STATUS(stat_var, status) (stat_var = status << 16)
+
struct req_que;
struct qla_tgt_sess;
@@ -370,32 +401,10 @@ struct srb_cmd {
#define SRB_CRC_CTX_DSD_VALID BIT_5 /* DIF: dsd_list valid */
#define SRB_WAKEUP_ON_COMP BIT_6
#define SRB_DIF_BUNDL_DMA_VALID BIT_7 /* DIF: DMA list valid */
+#define SRB_EDIF_CLEANUP_DELETE BIT_9
/* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
#define IS_PROT_IO(sp) (sp->flags & SRB_CRC_CTX_DSD_VALID)
-
-/*
- * 24 bit port ID type definition.
- */
-typedef union {
- uint32_t b24 : 24;
-
- struct {
-#ifdef __BIG_ENDIAN
- uint8_t domain;
- uint8_t area;
- uint8_t al_pa;
-#elif defined(__LITTLE_ENDIAN)
- uint8_t al_pa;
- uint8_t area;
- uint8_t domain;
-#else
-#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
-#endif
- uint8_t rsvd_1;
- } b;
-} port_id_t;
-#define INVALID_PORT_ID 0xFFFFFF
#define ISP_REG16_DISCONNECT 0xFFFF
static inline le_id_t be_id_to_le(be_id_t id)
@@ -483,6 +492,7 @@ struct srb_iocb {
#define SRB_LOGIN_SKIP_PRLI BIT_2
#define SRB_LOGIN_NVME_PRLI BIT_3
#define SRB_LOGIN_PRLI_ONLY BIT_4
+#define SRB_LOGIN_FCSP BIT_5
uint16_t data[2];
u32 iop[2];
} logio;
@@ -587,6 +597,10 @@ struct srb_iocb {
u16 cmd;
u16 vp_index;
} ctrlvp;
+ struct {
+ struct edif_sa_ctl *sa_ctl;
+ struct qla_sa_update_frame sa_frame;
+ } sa_update;
} u;
struct timer_list timer;
@@ -617,6 +631,21 @@ struct srb_iocb {
#define SRB_PRLI_CMD 21
#define SRB_CTRL_VP 22
#define SRB_PRLO_CMD 23
+#define SRB_SA_UPDATE 25
+#define SRB_ELS_CMD_HST_NOLOGIN 26
+#define SRB_SA_REPLACE 27
+
+struct qla_els_pt_arg {
+ u8 els_opcode;
+ u8 vp_idx;
+ __le16 nport_handle;
+ u16 control_flags;
+ __le32 rx_xchg_address;
+ port_id_t did;
+ u32 tx_len, tx_byte_count, rx_len, rx_byte_count;
+ dma_addr_t tx_addr, rx_addr;
+
+};
enum {
TYPE_SRB,
@@ -630,6 +659,13 @@ struct iocb_resource {
u16 iocb_cnt;
};
+struct bsg_cmd {
+ struct bsg_job *bsg_job;
+ union {
+ struct qla_els_pt_arg els_arg;
+ } u;
+};
+
typedef struct srb {
/*
* Do not move cmd_type field, it needs to
@@ -662,7 +698,21 @@ typedef struct srb {
struct srb_iocb iocb_cmd;
struct bsg_job *bsg_job;
struct srb_cmd scmd;
+ struct bsg_cmd bsg_cmd;
} u;
+ struct {
+ bool remapped;
+ struct {
+ dma_addr_t dma;
+ void *buf;
+ uint len;
+ } req;
+ struct {
+ dma_addr_t dma;
+ void *buf;
+ uint len;
+ } rsp;
+ } remap;
/*
* Report completion status @res and call sp_put(@sp). @res is
* an NVMe status code, a SCSI result (e.g. DID_OK << 16) or a
@@ -2294,6 +2344,7 @@ struct imm_ntfy_from_isp {
__le16 nport_handle;
uint16_t reserved_2;
__le16 flags;
+#define NOTIFY24XX_FLAGS_FCSP BIT_5
#define NOTIFY24XX_FLAGS_GLOBAL_TPRLO BIT_1
#define NOTIFY24XX_FLAGS_PUREX_IOCB BIT_0
__le16 srr_rx_id;
@@ -2377,11 +2428,9 @@ struct mbx_24xx_entry {
*/
typedef enum {
FCT_UNKNOWN,
- FCT_RSCN,
- FCT_SWITCH,
- FCT_BROADCAST,
- FCT_INITIATOR,
- FCT_TARGET,
+ FCT_BROADCAST = 0x01,
+ FCT_INITIATOR = 0x02,
+ FCT_TARGET = 0x04,
FCT_NVME_INITIATOR = 0x10,
FCT_NVME_TARGET = 0x20,
FCT_NVME_DISCOVERY = 0x40,
@@ -2424,6 +2473,7 @@ enum discovery_state {
DSC_LOGIN_COMPLETE,
DSC_ADISC,
DSC_DELETE_PEND,
+ DSC_LOGIN_AUTH_PEND,
};
enum login_state { /* FW control Target side */
@@ -2467,6 +2517,8 @@ typedef struct fc_port {
unsigned int n2n_flag:1;
unsigned int explicit_logout:1;
unsigned int prli_pend_timer:1;
+ unsigned int do_prli_nvme:1;
+
uint8_t nvme_flag;
uint8_t node_name[WWN_SIZE];
@@ -2563,6 +2615,33 @@ typedef struct fc_port {
u64 tgt_short_link_down_cnt;
u64 tgt_link_down_time;
u64 dev_loss_tmo;
+ /*
+ * EDIF parameters for encryption.
+ */
+ struct {
+ uint32_t enable:1; /* device is edif enabled/req'd */
+ uint32_t app_stop:2;
+ uint32_t app_started:1;
+ uint32_t aes_gmac:1;
+ uint32_t app_sess_online:1;
+ uint32_t tx_sa_set:1;
+ uint32_t rx_sa_set:1;
+ uint32_t tx_sa_pending:1;
+ uint32_t rx_sa_pending:1;
+ uint32_t tx_rekey_cnt;
+ uint32_t rx_rekey_cnt;
+ uint64_t tx_bytes;
+ uint64_t rx_bytes;
+ uint8_t auth_state;
+ uint16_t authok:1;
+ uint16_t rekey_cnt;
+ struct list_head edif_indx_list;
+ spinlock_t indx_list_lock;
+
+ struct list_head tx_sa_list;
+ struct list_head rx_sa_list;
+ spinlock_t sa_list_lock;
+ } edif;
} fc_port_t;
enum {
@@ -2604,7 +2683,8 @@ static const char * const port_dstate_str[] = {
"UPD_FCPORT",
"LOGIN_COMPLETE",
"ADISC",
- "DELETE_PEND"
+ "DELETE_PEND",
+ "LOGIN_AUTH_PEND",
};
/*
@@ -2616,6 +2696,8 @@ static const char * const port_dstate_str[] = {
#define FCF_ASYNC_SENT BIT_3
#define FCF_CONF_COMP_SUPPORTED BIT_4
#define FCF_ASYNC_ACTIVE BIT_5
+#define FCF_FCSP_DEVICE BIT_6
+#define FCF_EDIF_DELETE BIT_7
/* No loop ID flag. */
#define FC_NO_LOOP_ID 0x1000
@@ -2707,7 +2789,7 @@ static const char * const port_dstate_str[] = {
/*
* FDMI HBA attribute types.
*/
-#define FDMI1_HBA_ATTR_COUNT 9
+#define FDMI1_HBA_ATTR_COUNT 10
#define FDMI2_HBA_ATTR_COUNT 17
#define FDMI_HBA_NODE_NAME 0x1
@@ -3386,6 +3468,7 @@ enum qla_work_type {
QLA_EVT_SP_RETRY,
QLA_EVT_IIDMA,
QLA_EVT_ELS_PLOGI,
+ QLA_EVT_SA_REPLACE,
};
@@ -3444,6 +3527,11 @@ struct qla_work_evt {
u8 fc4_type;
srb_t *sp;
} gpnft;
+ struct {
+ struct edif_sa_ctl *sa_ctl;
+ fc_port_t *fcport;
+ uint16_t nport_handle;
+ } sa_update;
} u;
};
@@ -3845,7 +3933,6 @@ struct qlt_hw_data {
int num_act_qpairs;
#define DEFAULT_NAQP 2
spinlock_t atio_lock ____cacheline_aligned;
- struct btree_head32 host_map;
};
#define MAX_QFULL_CMDS_ALLOC 8192
@@ -3935,7 +4022,9 @@ struct qla_hw_data {
uint32_t scm_supported_f:1;
/* Enabled in Driver */
uint32_t scm_enabled:1;
- uint32_t max_req_queue_warned:1;
+ uint32_t edif_hw:1;
+ uint32_t edif_enabled:1;
+ uint32_t n2n_fw_acc_sec:1;
uint32_t plogi_template_valid:1;
uint32_t port_isolated:1;
} flags;
@@ -4347,6 +4436,7 @@ struct qla_hw_data {
/* Cisco fabric attached */
#define FW_ATTR_EXT0_SCM_CISCO 0x00002000
#define FW_ATTR_EXT0_NVME2 BIT_13
+#define FW_ATTR_EXT0_EDIF BIT_5
uint16_t fw_attributes_ext[2];
uint32_t fw_memory_size;
uint32_t fw_transfer_size;
@@ -4619,8 +4709,24 @@ struct qla_hw_data {
struct qla_hw_data_stat stat;
pci_error_state_t pci_error_state;
u64 prev_cmd_cnt;
+ struct dma_pool *purex_dma_pool;
+ struct btree_head32 host_map;
+
+#define EDIF_NUM_SA_INDEX 512
+#define EDIF_TX_SA_INDEX_BASE EDIF_NUM_SA_INDEX
+ void *edif_rx_sa_id_map;
+ void *edif_tx_sa_id_map;
+ spinlock_t sadb_fp_lock;
+
+ struct list_head sadb_tx_index_list;
+ struct list_head sadb_rx_index_list;
+ spinlock_t sadb_lock; /* protects list */
+ struct els_reject elsrej;
+ u8 edif_post_stop_cnt_down;
};
+#define RX_ELS_SIZE (roundup(sizeof(struct enode) + ELS_MAX_PAYLOAD, SMP_CACHE_BYTES))
+
struct active_regions {
uint8_t global;
struct {
@@ -4659,6 +4765,8 @@ struct purex_item {
} iocb;
};
+#include "qla_edif.h"
+
#define SCM_FLAG_RDF_REJECT 0x00
#define SCM_FLAG_RDF_COMPLETED 0x01
@@ -4888,6 +4996,8 @@ typedef struct scsi_qla_host {
u64 reset_cmd_err_cnt;
u64 link_down_time;
u64 short_link_down_cnt;
+ struct edif_dbell e_dbell;
+ struct pur_core pur_cinfo;
} scsi_qla_host_t;
struct qla27xx_image_status {
@@ -5058,6 +5168,9 @@ struct secure_flash_update_block_pk {
#define QLA_BUSY 0x107
#define QLA_ALREADY_REGISTERED 0x109
#define QLA_OS_TIMER_EXPIRED 0x10a
+#define QLA_ERR_NO_QPAIR 0x10b
+#define QLA_ERR_NOT_FOUND 0x10c
+#define QLA_ERR_FROM_FW 0x10d
#define NVRAM_DELAY() udelay(10)
@@ -5088,6 +5201,43 @@ enum nexus_wait_type {
WAIT_LUN,
};
+#define INVALID_EDIF_SA_INDEX 0xffff
+#define RX_DELETE_NO_EDIF_SA_INDEX 0xfffe
+
+#define QLA_SKIP_HANDLE QLA_TGT_SKIP_HANDLE
+
+/* edif hash element */
+struct edif_list_entry {
+ uint16_t handle; /* nport_handle */
+ uint32_t update_sa_index;
+ uint32_t delete_sa_index;
+ uint32_t count; /* counter for filtering sa_index */
+#define EDIF_ENTRY_FLAGS_CLEANUP 0x01 /* this index is being cleaned up */
+ uint32_t flags; /* used by sadb cleanup code */
+ fc_port_t *fcport; /* needed by rx delay timer function */
+ struct timer_list timer; /* rx delay timer */
+ struct list_head next;
+};
+
+#define EDIF_TX_INDX_BASE 512
+#define EDIF_RX_INDX_BASE 0
+#define EDIF_RX_DELETE_FILTER_COUNT 3 /* delay queuing rx delete until this many */
+
+/* entry in the sa_index free pool */
+
+struct sa_index_pair {
+ uint16_t sa_index;
+ uint32_t spi;
+};
+
+/* edif sa_index data structure */
+struct edif_sa_index_entry {
+ struct sa_index_pair sa_pair[2];
+ fc_port_t *fcport;
+ uint16_t handle;
+ struct list_head next;
+};
+
/* Refer to SNIA SFF 8247 */
struct sff_8247_a0 {
u8 txid; /* transceiver id */
@@ -5203,9 +5353,12 @@ struct sff_8247_a0 {
#define NVME_FCP_TARGET(fcport) \
(FCP_TYPE(fcport) && NVME_TYPE(fcport)) \
+#define NVME_PRIORITY(ha, fcport) \
+ (NVME_FCP_TARGET(fcport) && \
+ (ha->fc4_type_priority == FC4_PRIORITY_NVME))
+
#define NVME_TARGET(ha, fcport) \
- ((NVME_FCP_TARGET(fcport) && \
- (ha->fc4_type_priority == FC4_PRIORITY_NVME)) || \
+ (fcport->do_prli_nvme || \
NVME_ONLY_TARGET(fcport)) \
#define PRLI_PHASE(_cls) \
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
new file mode 100644
index 000000000000..ad746c62f0d4
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_edif.c
@@ -0,0 +1,3461 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Marvell Fibre Channel HBA Driver
+ * Copyright (c) 2021 Marvell
+ */
+#include "qla_def.h"
+#include "qla_edif.h"
+
+#include <linux/kthread.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <scsi/scsi_tcq.h>
+
+static struct edif_sa_index_entry *qla_edif_sadb_find_sa_index_entry(uint16_t nport_handle,
+ struct list_head *sa_list);
+static uint16_t qla_edif_sadb_get_sa_index(fc_port_t *fcport,
+ struct qla_sa_update_frame *sa_frame);
+static int qla_edif_sadb_delete_sa_index(fc_port_t *fcport, uint16_t nport_handle,
+ uint16_t sa_index);
+static int qla_pur_get_pending(scsi_qla_host_t *, fc_port_t *, struct bsg_job *);
+
+struct edb_node {
+ struct list_head list;
+ uint32_t ntype;
+ union {
+ port_id_t plogi_did;
+ uint32_t async;
+ port_id_t els_sid;
+ struct edif_sa_update_aen sa_aen;
+ } u;
+};
+
+static struct els_sub_cmd {
+ uint16_t cmd;
+ const char *str;
+} sc_str[] = {
+ {SEND_ELS, "send ELS"},
+ {SEND_ELS_REPLY, "send ELS Reply"},
+ {PULL_ELS, "retrieve ELS"},
+};
+
+const char *sc_to_str(uint16_t cmd)
+{
+ int i;
+ struct els_sub_cmd *e;
+
+ for (i = 0; i < ARRAY_SIZE(sc_str); i++) {
+ e = sc_str + i;
+ if (cmd == e->cmd)
+ return e->str;
+ }
+ return "unknown";
+}
+
+static struct edif_list_entry *qla_edif_list_find_sa_index(fc_port_t *fcport,
+ uint16_t handle)
+{
+ struct edif_list_entry *entry;
+ struct edif_list_entry *tentry;
+ struct list_head *indx_list = &fcport->edif.edif_indx_list;
+
+ list_for_each_entry_safe(entry, tentry, indx_list, next) {
+ if (entry->handle == handle)
+ return entry;
+ }
+ return NULL;
+}
+
+/* timeout called when no traffic and delayed rx sa_index delete */
+static void qla2x00_sa_replace_iocb_timeout(struct timer_list *t)
+{
+ struct edif_list_entry *edif_entry = from_timer(edif_entry, t, timer);
+ fc_port_t *fcport = edif_entry->fcport;
+ struct scsi_qla_host *vha = fcport->vha;
+ struct edif_sa_ctl *sa_ctl;
+ uint16_t nport_handle;
+ unsigned long flags = 0;
+
+ ql_dbg(ql_dbg_edif, vha, 0x3069,
+ "%s: nport_handle 0x%x, SA REPL Delay Timeout, %8phC portid=%06x\n",
+ __func__, edif_entry->handle, fcport->port_name, fcport->d_id.b24);
+
+ /*
+ * if delete_sa_index is valid then no one has serviced this
+ * delayed delete
+ */
+ spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);
+
+ /*
+ * delete_sa_index is invalidated when we find the new sa_index in
+ * the incoming data stream. If it is not invalidated then we are
+ * still looking for the new sa_index because there is no I/O and we
+ * need to just force the rx delete and move on. Otherwise
+ * we could get another rekey which will result in an error 66.
+ */
+ if (edif_entry->delete_sa_index != INVALID_EDIF_SA_INDEX) {
+ uint16_t delete_sa_index = edif_entry->delete_sa_index;
+
+ edif_entry->delete_sa_index = INVALID_EDIF_SA_INDEX;
+ nport_handle = edif_entry->handle;
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+
+ sa_ctl = qla_edif_find_sa_ctl_by_index(fcport,
+ delete_sa_index, 0);
+
+ if (sa_ctl) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: sa_ctl: %p, delete index %d, update index: %d, lid: 0x%x\n",
+ __func__, sa_ctl, delete_sa_index, edif_entry->update_sa_index,
+ nport_handle);
+
+ sa_ctl->flags = EDIF_SA_CTL_FLG_DEL;
+ set_bit(EDIF_SA_CTL_REPL, &sa_ctl->state);
+ qla_post_sa_replace_work(fcport->vha, fcport,
+ nport_handle, sa_ctl);
+
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: sa_ctl not found for delete_sa_index: %d\n",
+ __func__, edif_entry->delete_sa_index);
+ }
+ } else {
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+ }
+}
+
+/*
+ * create a new list entry for this nport handle and
+ * add an sa_update index to the list - called for sa_update
+ */
+static int qla_edif_list_add_sa_update_index(fc_port_t *fcport,
+ uint16_t sa_index, uint16_t handle)
+{
+ struct edif_list_entry *entry;
+ unsigned long flags = 0;
+
+ /* if the entry exists, then just update the sa_index */
+ entry = qla_edif_list_find_sa_index(fcport, handle);
+ if (entry) {
+ entry->update_sa_index = sa_index;
+ entry->count = 0;
+ return 0;
+ }
+
+ /*
+ * This is the normal path - there should be no existing entry
+ * when update is called. The exception is at startup
+ * when update is called for the first two sa_indexes
+ * followed by a delete of the first sa_index
+ */
+ entry = kzalloc((sizeof(struct edif_list_entry)), GFP_ATOMIC);
+ if (!entry)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&entry->next);
+ entry->handle = handle;
+ entry->update_sa_index = sa_index;
+ entry->delete_sa_index = INVALID_EDIF_SA_INDEX;
+ entry->count = 0;
+ entry->flags = 0;
+ timer_setup(&entry->timer, qla2x00_sa_replace_iocb_timeout, 0);
+ spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);
+ list_add_tail(&entry->next, &fcport->edif.edif_indx_list);
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+ return 0;
+}
+
+/* remove an entry from the list */
+static void qla_edif_list_delete_sa_index(fc_port_t *fcport, struct edif_list_entry *entry)
+{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);
+ list_del(&entry->next);
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+}
+
+int qla_post_sa_replace_work(struct scsi_qla_host *vha,
+ fc_port_t *fcport, uint16_t nport_handle, struct edif_sa_ctl *sa_ctl)
+{
+ struct qla_work_evt *e;
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_SA_REPLACE);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.sa_update.fcport = fcport;
+ e->u.sa_update.sa_ctl = sa_ctl;
+ e->u.sa_update.nport_handle = nport_handle;
+ fcport->flags |= FCF_ASYNC_ACTIVE;
+ return qla2x00_post_work(vha, e);
+}
+
+static void
+qla_edif_sa_ctl_init(scsi_qla_host_t *vha, struct fc_port *fcport)
+{
+ ql_dbg(ql_dbg_edif, vha, 0x2058,
+ "Init SA_CTL List for fcport - nn %8phN pn %8phN portid=%06x.\n",
+ fcport->node_name, fcport->port_name, fcport->d_id.b24);
+
+ fcport->edif.tx_rekey_cnt = 0;
+ fcport->edif.rx_rekey_cnt = 0;
+
+ fcport->edif.tx_bytes = 0;
+ fcport->edif.rx_bytes = 0;
+}
+
+static int qla_bsg_check(scsi_qla_host_t *vha, struct bsg_job *bsg_job,
+fc_port_t *fcport)
+{
+ struct extra_auth_els *p;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct qla_bsg_auth_els_request *req =
+ (struct qla_bsg_auth_els_request *)bsg_job->request;
+
+ if (!vha->hw->flags.edif_enabled) {
+ ql_dbg(ql_dbg_edif, vha, 0x9105,
+ "%s edif not enabled\n", __func__);
+ goto done;
+ }
+ if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s doorbell not enabled\n", __func__);
+ goto done;
+ }
+
+ p = &req->e;
+
+ /* Get response */
+ if (p->sub_cmd == PULL_ELS) {
+ struct qla_bsg_auth_els_reply *rpl =
+ (struct qla_bsg_auth_els_reply *)bsg_job->reply;
+
+ qla_pur_get_pending(vha, fcport, bsg_job);
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s %s %8phN sid=%x. xchg %x, nb=%xh bsg ptr %p\n",
+ __func__, sc_to_str(p->sub_cmd), fcport->port_name,
+ fcport->d_id.b24, rpl->rx_xchg_address,
+ rpl->r.reply_payload_rcv_len, bsg_job);
+
+ goto done;
+ }
+ return 0;
+
+done:
+
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ return -EIO;
+}
+
+fc_port_t *
+qla2x00_find_fcport_by_pid(scsi_qla_host_t *vha, port_id_t *id)
+{
+ fc_port_t *f, *tf;
+
+ f = NULL;
+ list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
+ if ((f->flags & FCF_FCSP_DEVICE)) {
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x2058,
+ "Found secure fcport - nn %8phN pn %8phN portid=0x%x, 0x%x.\n",
+ f->node_name, f->port_name,
+ f->d_id.b24, id->b24);
+ if (f->d_id.b24 == id->b24)
+ return f;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * qla_edif_app_check(): check for valid application id.
+ * @vha: host adapter pointer
+ * @appid: application id
+ * Return: false = fail, true = pass
+ */
+static bool
+qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid)
+{
+ /* check that the app is allow/known to the driver */
+
+ if (appid.app_vid == EDIF_APP_ID) {
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d, "%s app id ok\n", __func__);
+ return true;
+ }
+ ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app id not ok (%x)",
+ __func__, appid.app_vid);
+
+ return false;
+}
+
+static void qla_edif_reset_auth_wait(struct fc_port *fcport, int state,
+ int waitonly)
+{
+ int cnt, max_cnt = 200;
+ bool traced = false;
+
+ fcport->keep_nport_handle = 1;
+
+ if (!waitonly) {
+ qla2x00_set_fcport_disc_state(fcport, state);
+ qlt_schedule_sess_for_deletion(fcport);
+ } else {
+ qla2x00_set_fcport_disc_state(fcport, state);
+ }
+
+ ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,
+ "%s: waiting for session, max_cnt=%u\n",
+ __func__, max_cnt);
+
+ cnt = 0;
+
+ if (waitonly) {
+ /* Marker wait min 10 msecs. */
+ msleep(50);
+ cnt += 50;
+ }
+ while (1) {
+ if (!traced) {
+ ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,
+ "%s: session sleep.\n",
+ __func__);
+ traced = true;
+ }
+ msleep(20);
+ cnt++;
+ if (waitonly && (fcport->disc_state == state ||
+ fcport->disc_state == DSC_LOGIN_COMPLETE))
+ break;
+ if (fcport->disc_state == DSC_LOGIN_AUTH_PEND)
+ break;
+ if (cnt > max_cnt)
+ break;
+ }
+
+ if (!waitonly) {
+ ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,
+ "%s: waited for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",
+ __func__, fcport->port_name, fcport->loop_id,
+ fcport->d_id.b24, fcport, fcport->disc_state, cnt);
+ } else {
+ ql_dbg(ql_dbg_edif, fcport->vha, 0xf086,
+ "%s: waited ONLY for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n",
+ __func__, fcport->port_name, fcport->loop_id,
+ fcport->d_id.b24, fcport, fcport->disc_state, cnt);
+ }
+}
+
+static void
+qla_edif_free_sa_ctl(fc_port_t *fcport, struct edif_sa_ctl *sa_ctl,
+ int index)
+{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&fcport->edif.sa_list_lock, flags);
+ list_del(&sa_ctl->next);
+ spin_unlock_irqrestore(&fcport->edif.sa_list_lock, flags);
+ if (index >= 512)
+ fcport->edif.tx_rekey_cnt--;
+ else
+ fcport->edif.rx_rekey_cnt--;
+ kfree(sa_ctl);
+}
+
+/* return an index to the freepool */
+static void qla_edif_add_sa_index_to_freepool(fc_port_t *fcport, int dir,
+ uint16_t sa_index)
+{
+ void *sa_id_map;
+ struct scsi_qla_host *vha = fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags = 0;
+ u16 lsa_index = sa_index;
+
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,
+ "%s: entry\n", __func__);
+
+ if (dir) {
+ sa_id_map = ha->edif_tx_sa_id_map;
+ lsa_index -= EDIF_TX_SA_INDEX_BASE;
+ } else {
+ sa_id_map = ha->edif_rx_sa_id_map;
+ }
+
+ spin_lock_irqsave(&ha->sadb_fp_lock, flags);
+ clear_bit(lsa_index, sa_id_map);
+ spin_unlock_irqrestore(&ha->sadb_fp_lock, flags);
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: index %d added to free pool\n", __func__, sa_index);
+}
+
+static void __qla2x00_release_all_sadb(struct scsi_qla_host *vha,
+ struct fc_port *fcport, struct edif_sa_index_entry *entry,
+ int pdir)
+{
+ struct edif_list_entry *edif_entry;
+ struct edif_sa_ctl *sa_ctl;
+ int i, dir;
+ int key_cnt = 0;
+
+ for (i = 0; i < 2; i++) {
+ if (entry->sa_pair[i].sa_index == INVALID_EDIF_SA_INDEX)
+ continue;
+
+ if (fcport->loop_id != entry->handle) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: ** WARNING %d** entry handle: 0x%x, lid: 0x%x, sa_index: %d\n",
+ __func__, i, entry->handle, fcport->loop_id,
+ entry->sa_pair[i].sa_index);
+ }
+
+ /* release the sa_ctl */
+ sa_ctl = qla_edif_find_sa_ctl_by_index(fcport,
+ entry->sa_pair[i].sa_index, pdir);
+ if (sa_ctl &&
+ qla_edif_find_sa_ctl_by_index(fcport, sa_ctl->index, pdir)) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: freeing sa_ctl for index %d\n", __func__, sa_ctl->index);
+ qla_edif_free_sa_ctl(fcport, sa_ctl, sa_ctl->index);
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: sa_ctl NOT freed, sa_ctl: %p\n", __func__, sa_ctl);
+ }
+
+ /* Release the index */
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: freeing sa_index %d, nph: 0x%x\n",
+ __func__, entry->sa_pair[i].sa_index, entry->handle);
+
+ dir = (entry->sa_pair[i].sa_index <
+ EDIF_TX_SA_INDEX_BASE) ? 0 : 1;
+ qla_edif_add_sa_index_to_freepool(fcport, dir,
+ entry->sa_pair[i].sa_index);
+
+ /* Delete timer on RX */
+ if (pdir != SAU_FLG_TX) {
+ edif_entry =
+ qla_edif_list_find_sa_index(fcport, entry->handle);
+ if (edif_entry) {
+ ql_dbg(ql_dbg_edif, vha, 0x5033,
+ "%s: remove edif_entry %p, update_sa_index: 0x%x, delete_sa_index: 0x%x\n",
+ __func__, edif_entry, edif_entry->update_sa_index,
+ edif_entry->delete_sa_index);
+ qla_edif_list_delete_sa_index(fcport, edif_entry);
+ /*
+ * valid delete_sa_index indicates there is a rx
+ * delayed delete queued
+ */
+ if (edif_entry->delete_sa_index !=
+ INVALID_EDIF_SA_INDEX) {
+ del_timer(&edif_entry->timer);
+
+ /* build and send the aen */
+ fcport->edif.rx_sa_set = 1;
+ fcport->edif.rx_sa_pending = 0;
+ qla_edb_eventcreate(vha,
+ VND_CMD_AUTH_STATE_SAUPDATE_COMPL,
+ QL_VND_SA_STAT_SUCCESS,
+ QL_VND_RX_SA_KEY, fcport);
+ }
+ ql_dbg(ql_dbg_edif, vha, 0x5033,
+ "%s: release edif_entry %p, update_sa_index: 0x%x, delete_sa_index: 0x%x\n",
+ __func__, edif_entry, edif_entry->update_sa_index,
+ edif_entry->delete_sa_index);
+
+ kfree(edif_entry);
+ }
+ }
+ key_cnt++;
+ }
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: %d %s keys released\n",
+ __func__, key_cnt, pdir ? "tx" : "rx");
+}
+
+/* find an release all outstanding sadb sa_indicies */
+void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport)
+{
+ struct edif_sa_index_entry *entry, *tmp;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,
+ "%s: Starting...\n", __func__);
+
+ spin_lock_irqsave(&ha->sadb_lock, flags);
+
+ list_for_each_entry_safe(entry, tmp, &ha->sadb_rx_index_list, next) {
+ if (entry->fcport == fcport) {
+ list_del(&entry->next);
+ spin_unlock_irqrestore(&ha->sadb_lock, flags);
+ __qla2x00_release_all_sadb(vha, fcport, entry, 0);
+ kfree(entry);
+ spin_lock_irqsave(&ha->sadb_lock, flags);
+ break;
+ }
+ }
+
+ list_for_each_entry_safe(entry, tmp, &ha->sadb_tx_index_list, next) {
+ if (entry->fcport == fcport) {
+ list_del(&entry->next);
+ spin_unlock_irqrestore(&ha->sadb_lock, flags);
+
+ __qla2x00_release_all_sadb(vha, fcport, entry, SAU_FLG_TX);
+
+ kfree(entry);
+ spin_lock_irqsave(&ha->sadb_lock, flags);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&ha->sadb_lock, flags);
+}
+
+/**
+ * qla_edif_app_start: application has announce its present
+ * @vha: host adapter pointer
+ * @bsg_job: user request
+ *
+ * Set/activate doorbell. Reset current sessions and re-login with
+ * secure flag.
+ */
+static int
+qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+ int32_t rval = 0;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct app_start appstart;
+ struct app_start_reply appreply;
+ struct fc_port *fcport, *tf;
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app start\n", __func__);
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, &appstart,
+ sizeof(struct app_start));
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app_vid=%x app_start_flags %x\n",
+ __func__, appstart.app_info.app_vid, appstart.app_start_flags);
+
+ if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+ /* mark doorbell as active since an app is now present */
+ vha->e_dbell.db_flags = EDB_ACTIVE;
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x911e, "%s doorbell already active\n",
+ __func__);
+ }
+
+ if (N2N_TOPO(vha->hw)) {
+ if (vha->hw->flags.n2n_fw_acc_sec)
+ set_bit(N2N_LINK_RESET, &vha->dpc_flags);
+ else
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ } else {
+ list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+ ql_dbg(ql_dbg_edif, vha, 0xf084,
+ "%s: sess %p %8phC lid %#04x s_id %06x logout %d\n",
+ __func__, fcport, fcport->port_name,
+ fcport->loop_id, fcport->d_id.b24,
+ fcport->logout_on_delete);
+
+ ql_dbg(ql_dbg_edif, vha, 0xf084,
+ "keep %d els_logo %d disc state %d auth state %d stop state %d\n",
+ fcport->keep_nport_handle,
+ fcport->send_els_logo, fcport->disc_state,
+ fcport->edif.auth_state, fcport->edif.app_stop);
+
+ if (atomic_read(&vha->loop_state) == LOOP_DOWN)
+ break;
+ if (!(fcport->flags & FCF_FCSP_DEVICE))
+ continue;
+
+ fcport->edif.app_started = 1;
+ if (fcport->edif.app_stop ||
+ (fcport->disc_state != DSC_LOGIN_COMPLETE &&
+ fcport->disc_state != DSC_LOGIN_PEND &&
+ fcport->disc_state != DSC_DELETED)) {
+ /* no activity */
+ fcport->edif.app_stop = 0;
+
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s wwpn %8phC calling qla_edif_reset_auth_wait\n",
+ __func__, fcport->port_name);
+ fcport->edif.app_sess_online = 1;
+ qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0);
+ }
+ qla_edif_sa_ctl_init(vha, fcport);
+ }
+ }
+
+ if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {
+ /* mark as active since an app is now present */
+ vha->pur_cinfo.enode_flags = ENODE_ACTIVE;
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x911f, "%s enode already active\n",
+ __func__);
+ }
+
+ appreply.host_support_edif = vha->hw->flags.edif_enabled;
+ appreply.edif_enode_active = vha->pur_cinfo.enode_flags;
+ appreply.edif_edb_active = vha->e_dbell.db_flags;
+
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
+ sizeof(struct app_start_reply);
+
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, &appreply,
+ sizeof(struct app_start_reply));
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s app start completed with 0x%x\n",
+ __func__, rval);
+
+ return rval;
+}
+
+/**
+ * qla_edif_app_stop - app has announced it's exiting.
+ * @vha: host adapter pointer
+ * @bsg_job: user space command pointer
+ *
+ * Free any in flight messages, clear all doorbell events
+ * to application. Reject any message relate to security.
+ */
+static int
+qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+ struct app_stop appstop;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct fc_port *fcport, *tf;
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, &appstop,
+ sizeof(struct app_stop));
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d, "%s Stopping APP: app_vid=%x\n",
+ __func__, appstop.app_info.app_vid);
+
+ /* Call db stop and enode stop functions */
+
+ /* if we leave this running short waits are operational < 16 secs */
+ qla_enode_stop(vha); /* stop enode */
+ qla_edb_stop(vha); /* stop db */
+
+ list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+ if (!(fcport->flags & FCF_FCSP_DEVICE))
+ continue;
+
+ if (fcport->flags & FCF_FCSP_DEVICE) {
+ ql_dbg(ql_dbg_edif, vha, 0xf084,
+ "%s: sess %p from port %8phC lid %#04x s_id %06x logout %d keep %d els_logo %d\n",
+ __func__, fcport,
+ fcport->port_name, fcport->loop_id, fcport->d_id.b24,
+ fcport->logout_on_delete, fcport->keep_nport_handle,
+ fcport->send_els_logo);
+
+ if (atomic_read(&vha->loop_state) == LOOP_DOWN)
+ break;
+
+ fcport->edif.app_stop = 1;
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s wwpn %8phC calling qla_edif_reset_auth_wait\n",
+ __func__, fcport->port_name);
+
+ fcport->send_els_logo = 1;
+ qlt_schedule_sess_for_deletion(fcport);
+
+ /* qla_edif_flush_sa_ctl_lists(fcport); */
+ fcport->edif.app_started = 0;
+ }
+ }
+
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+
+ /* no return interface to app - it assumes we cleaned up ok */
+
+ return 0;
+}
+
+static int
+qla_edif_app_chk_sa_update(scsi_qla_host_t *vha, fc_port_t *fcport,
+ struct app_plogi_reply *appplogireply)
+{
+ int ret = 0;
+
+ if (!(fcport->edif.rx_sa_set && fcport->edif.tx_sa_set)) {
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d.\n",
+ __func__, fcport->port_name, fcport->edif.tx_sa_set,
+ fcport->edif.rx_sa_set);
+ appplogireply->prli_status = 0;
+ ret = 1;
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s wwpn %8phC Both SA(s) updated.\n", __func__,
+ fcport->port_name);
+ fcport->edif.rx_sa_set = fcport->edif.tx_sa_set = 0;
+ fcport->edif.rx_sa_pending = fcport->edif.tx_sa_pending = 0;
+ appplogireply->prli_status = 1;
+ }
+ return ret;
+}
+
+/**
+ * qla_edif_app_authok - authentication by app succeeded. Driver can proceed
+ * with prli
+ * @vha: host adapter pointer
+ * @bsg_job: user request
+ */
+static int
+qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+ int32_t rval = 0;
+ struct auth_complete_cmd appplogiok;
+ struct app_plogi_reply appplogireply = {0};
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ fc_port_t *fcport = NULL;
+ port_id_t portid = {0};
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, &appplogiok,
+ sizeof(struct auth_complete_cmd));
+
+ switch (appplogiok.type) {
+ case PL_TYPE_WWPN:
+ fcport = qla2x00_find_fcport_by_wwpn(vha,
+ appplogiok.u.wwpn, 0);
+ if (!fcport)
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s wwpn lookup failed: %8phC\n",
+ __func__, appplogiok.u.wwpn);
+ break;
+ case PL_TYPE_DID:
+ fcport = qla2x00_find_fcport_by_pid(vha, &appplogiok.u.d_id);
+ if (!fcport)
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s d_id lookup failed: %x\n", __func__,
+ portid.b24);
+ break;
+ default:
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s undefined type: %x\n", __func__,
+ appplogiok.type);
+ break;
+ }
+
+ if (!fcport) {
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ goto errstate_exit;
+ }
+
+ /*
+ * if port is online then this is a REKEY operation
+ * Only do sa update checking
+ */
+ if (atomic_read(&fcport->state) == FCS_ONLINE) {
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s Skipping PRLI complete based on rekey\n", __func__);
+ appplogireply.prli_status = 1;
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ qla_edif_app_chk_sa_update(vha, fcport, &appplogireply);
+ goto errstate_exit;
+ }
+
+ /* make sure in AUTH_PENDING or else reject */
+ if (fcport->disc_state != DSC_LOGIN_AUTH_PEND) {
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s wwpn %8phC is not in auth pending state (%x)\n",
+ __func__, fcport->port_name, fcport->disc_state);
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ appplogireply.prli_status = 0;
+ goto errstate_exit;
+ }
+
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ appplogireply.prli_status = 1;
+ fcport->edif.authok = 1;
+ if (!(fcport->edif.rx_sa_set && fcport->edif.tx_sa_set)) {
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d.\n",
+ __func__, fcport->port_name, fcport->edif.tx_sa_set,
+ fcport->edif.rx_sa_set);
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ appplogireply.prli_status = 0;
+ goto errstate_exit;
+
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s wwpn %8phC Both SA(s) updated.\n", __func__,
+ fcport->port_name);
+ fcport->edif.rx_sa_set = fcport->edif.tx_sa_set = 0;
+ fcport->edif.rx_sa_pending = fcport->edif.tx_sa_pending = 0;
+ }
+
+ if (qla_ini_mode_enabled(vha)) {
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s AUTH complete - RESUME with prli for wwpn %8phC\n",
+ __func__, fcport->port_name);
+ qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 1);
+ qla24xx_post_prli_work(vha, fcport);
+ }
+
+errstate_exit:
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, &appplogireply,
+ sizeof(struct app_plogi_reply));
+
+ return rval;
+}
+
+/**
+ * qla_edif_app_authfail - authentication by app has failed. Driver is given
+ * notice to tear down current session.
+ * @vha: host adapter pointer
+ * @bsg_job: user request
+ */
+static int
+qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+ int32_t rval = 0;
+ struct auth_complete_cmd appplogifail;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ fc_port_t *fcport = NULL;
+ port_id_t portid = {0};
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app auth fail\n", __func__);
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, &appplogifail,
+ sizeof(struct auth_complete_cmd));
+
+ /*
+ * TODO: edif: app has failed this plogi. Inform driver to
+ * take any action (if any).
+ */
+ switch (appplogifail.type) {
+ case PL_TYPE_WWPN:
+ fcport = qla2x00_find_fcport_by_wwpn(vha,
+ appplogifail.u.wwpn, 0);
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ break;
+ case PL_TYPE_DID:
+ fcport = qla2x00_find_fcport_by_pid(vha, &appplogifail.u.d_id);
+ if (!fcport)
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s d_id lookup failed: %x\n", __func__,
+ portid.b24);
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ break;
+ default:
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s undefined type: %x\n", __func__,
+ appplogifail.type);
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ rval = -1;
+ break;
+ }
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s fcport is 0x%p\n", __func__, fcport);
+
+ if (fcport) {
+ /* set/reset edif values and flags */
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s reset the auth process - %8phC, loopid=%x portid=%06x.\n",
+ __func__, fcport->port_name, fcport->loop_id, fcport->d_id.b24);
+
+ if (qla_ini_mode_enabled(fcport->vha)) {
+ fcport->send_els_logo = 1;
+ qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0);
+ }
+ }
+
+ return rval;
+}
+
+/**
+ * qla_edif_app_getfcinfo - app would like to read session info (wwpn, nportid,
+ * [initiator|target] mode. It can specific session with specific nport id or
+ * all sessions.
+ * @vha: host adapter pointer
+ * @bsg_job: user request pointer
+ */
+static int
+qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+ int32_t rval = 0;
+ int32_t num_cnt;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct app_pinfo_req app_req;
+ struct app_pinfo_reply *app_reply;
+ port_id_t tdid;
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app get fcinfo\n", __func__);
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, &app_req,
+ sizeof(struct app_pinfo_req));
+
+ num_cnt = app_req.num_ports; /* num of ports alloc'd by app */
+
+ app_reply = kzalloc((sizeof(struct app_pinfo_reply) +
+ sizeof(struct app_pinfo) * num_cnt), GFP_KERNEL);
+ if (!app_reply) {
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ rval = -1;
+ } else {
+ struct fc_port *fcport = NULL, *tf;
+ uint32_t pcnt = 0;
+
+ list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+ if (!(fcport->flags & FCF_FCSP_DEVICE))
+ continue;
+
+ tdid = app_req.remote_pid;
+
+ ql_dbg(ql_dbg_edif, vha, 0x2058,
+ "APP request entry - portid=%06x.\n", tdid.b24);
+
+ /* Ran out of space */
+ if (pcnt > app_req.num_ports)
+ break;
+
+ if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24)
+ continue;
+
+ app_reply->ports[pcnt].rekey_count =
+ fcport->edif.rekey_cnt;
+
+ app_reply->ports[pcnt].remote_type =
+ VND_CMD_RTYPE_UNKNOWN;
+ if (fcport->port_type & (FCT_NVME_TARGET | FCT_TARGET))
+ app_reply->ports[pcnt].remote_type |=
+ VND_CMD_RTYPE_TARGET;
+ if (fcport->port_type & (FCT_NVME_INITIATOR | FCT_INITIATOR))
+ app_reply->ports[pcnt].remote_type |=
+ VND_CMD_RTYPE_INITIATOR;
+
+ app_reply->ports[pcnt].remote_pid = fcport->d_id;
+
+ ql_dbg(ql_dbg_edif, vha, 0x2058,
+ "Found FC_SP fcport - nn %8phN pn %8phN pcnt %d portid=%06x secure %d.\n",
+ fcport->node_name, fcport->port_name, pcnt,
+ fcport->d_id.b24, fcport->flags & FCF_FCSP_DEVICE);
+
+ switch (fcport->edif.auth_state) {
+ case VND_CMD_AUTH_STATE_ELS_RCVD:
+ if (fcport->disc_state == DSC_LOGIN_AUTH_PEND) {
+ fcport->edif.auth_state = VND_CMD_AUTH_STATE_NEEDED;
+ app_reply->ports[pcnt].auth_state =
+ VND_CMD_AUTH_STATE_NEEDED;
+ } else {
+ app_reply->ports[pcnt].auth_state =
+ VND_CMD_AUTH_STATE_ELS_RCVD;
+ }
+ break;
+ default:
+ app_reply->ports[pcnt].auth_state = fcport->edif.auth_state;
+ break;
+ }
+
+ memcpy(app_reply->ports[pcnt].remote_wwpn,
+ fcport->port_name, 8);
+
+ app_reply->ports[pcnt].remote_state =
+ (atomic_read(&fcport->state) ==
+ FCS_ONLINE ? 1 : 0);
+
+ pcnt++;
+
+ if (tdid.b24 != 0)
+ break;
+ }
+ app_reply->port_count = pcnt;
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ }
+
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, app_reply,
+ sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * num_cnt);
+
+ kfree(app_reply);
+
+ return rval;
+}
+
+/**
+ * qla_edif_app_getstats - app would like to read various statistics info
+ * @vha: host adapter pointer
+ * @bsg_job: user request
+ */
+static int32_t
+qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+ int32_t rval = 0;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ uint32_t ret_size, size;
+
+ struct app_sinfo_req app_req;
+ struct app_stats_reply *app_reply;
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, &app_req,
+ sizeof(struct app_sinfo_req));
+ if (app_req.num_ports == 0) {
+ ql_dbg(ql_dbg_async, vha, 0x911d,
+ "%s app did not indicate number of ports to return\n",
+ __func__);
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ rval = -1;
+ }
+
+ size = sizeof(struct app_stats_reply) +
+ (sizeof(struct app_sinfo) * app_req.num_ports);
+
+ if (size > bsg_job->reply_payload.payload_len)
+ ret_size = bsg_job->reply_payload.payload_len;
+ else
+ ret_size = size;
+
+ app_reply = kzalloc(size, GFP_KERNEL);
+ if (!app_reply) {
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ rval = -1;
+ } else {
+ struct fc_port *fcport = NULL, *tf;
+ uint32_t pcnt = 0;
+
+ list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+ if (fcport->edif.enable) {
+ if (pcnt > app_req.num_ports)
+ break;
+
+ app_reply->elem[pcnt].rekey_count =
+ fcport->edif.rekey_cnt;
+ app_reply->elem[pcnt].tx_bytes =
+ fcport->edif.tx_bytes;
+ app_reply->elem[pcnt].rx_bytes =
+ fcport->edif.rx_bytes;
+
+ memcpy(app_reply->elem[pcnt].remote_wwpn,
+ fcport->port_name, 8);
+
+ pcnt++;
+ }
+ }
+ app_reply->elem_count = pcnt;
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ }
+
+ bsg_reply->reply_payload_rcv_len =
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, app_reply, ret_size);
+
+ kfree(app_reply);
+
+ return rval;
+}
+
+int32_t
+qla_edif_app_mgmt(struct bsg_job *bsg_job)
+{
+ struct fc_bsg_request *bsg_request = bsg_job->request;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
+ scsi_qla_host_t *vha = shost_priv(host);
+ struct app_id appcheck;
+ bool done = true;
+ int32_t rval = 0;
+ uint32_t vnd_sc = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d, "%s vnd subcmd=%x\n",
+ __func__, vnd_sc);
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, &appcheck,
+ sizeof(struct app_id));
+
+ if (!vha->hw->flags.edif_enabled ||
+ test_bit(VPORT_DELETE, &vha->dpc_flags)) {
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s edif not enabled or vp delete. bsg ptr done %p. dpc_flags %lx\n",
+ __func__, bsg_job, vha->dpc_flags);
+
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ goto done;
+ }
+
+ if (!qla_edif_app_check(vha, appcheck)) {
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s app checked failed.\n",
+ __func__);
+
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ goto done;
+ }
+
+ switch (vnd_sc) {
+ case QL_VND_SC_SA_UPDATE:
+ done = false;
+ rval = qla24xx_sadb_update(bsg_job);
+ break;
+ case QL_VND_SC_APP_START:
+ rval = qla_edif_app_start(vha, bsg_job);
+ break;
+ case QL_VND_SC_APP_STOP:
+ rval = qla_edif_app_stop(vha, bsg_job);
+ break;
+ case QL_VND_SC_AUTH_OK:
+ rval = qla_edif_app_authok(vha, bsg_job);
+ break;
+ case QL_VND_SC_AUTH_FAIL:
+ rval = qla_edif_app_authfail(vha, bsg_job);
+ break;
+ case QL_VND_SC_GET_FCINFO:
+ rval = qla_edif_app_getfcinfo(vha, bsg_job);
+ break;
+ case QL_VND_SC_GET_STATS:
+ rval = qla_edif_app_getstats(vha, bsg_job);
+ break;
+ default:
+ ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n",
+ __func__,
+ bsg_request->rqst_data.h_vendor.vendor_cmd[1]);
+ rval = EXT_STATUS_INVALID_PARAM;
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ break;
+ }
+
+done:
+ if (done) {
+ ql_dbg(ql_dbg_user, vha, 0x7009,
+ "%s: %d bsg ptr done %p\n", __func__, __LINE__, bsg_job);
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ }
+
+ return rval;
+}
+
+static struct edif_sa_ctl *
+qla_edif_add_sa_ctl(fc_port_t *fcport, struct qla_sa_update_frame *sa_frame,
+ int dir)
+{
+ struct edif_sa_ctl *sa_ctl;
+ struct qla_sa_update_frame *sap;
+ int index = sa_frame->fast_sa_index;
+ unsigned long flags = 0;
+
+ sa_ctl = kzalloc(sizeof(*sa_ctl), GFP_KERNEL);
+ if (!sa_ctl) {
+ /* couldn't get space */
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,
+ "unable to allocate SA CTL\n");
+ return NULL;
+ }
+
+ /*
+ * need to allocate sa_index here and save it
+ * in both sa_ctl->index and sa_frame->fast_sa_index;
+ * If alloc fails then delete sa_ctl and return NULL
+ */
+ INIT_LIST_HEAD(&sa_ctl->next);
+ sap = &sa_ctl->sa_frame;
+ *sap = *sa_frame;
+ sa_ctl->index = index;
+ sa_ctl->fcport = fcport;
+ sa_ctl->flags = 0;
+ sa_ctl->state = 0L;
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,
+ "%s: Added sa_ctl %p, index %d, state 0x%lx\n",
+ __func__, sa_ctl, sa_ctl->index, sa_ctl->state);
+ spin_lock_irqsave(&fcport->edif.sa_list_lock, flags);
+ if (dir == SAU_FLG_TX)
+ list_add_tail(&sa_ctl->next, &fcport->edif.tx_sa_list);
+ else
+ list_add_tail(&sa_ctl->next, &fcport->edif.rx_sa_list);
+ spin_unlock_irqrestore(&fcport->edif.sa_list_lock, flags);
+
+ return sa_ctl;
+}
+
+void
+qla_edif_flush_sa_ctl_lists(fc_port_t *fcport)
+{
+ struct edif_sa_ctl *sa_ctl, *tsa_ctl;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&fcport->edif.sa_list_lock, flags);
+
+ list_for_each_entry_safe(sa_ctl, tsa_ctl, &fcport->edif.tx_sa_list,
+ next) {
+ list_del(&sa_ctl->next);
+ kfree(sa_ctl);
+ }
+
+ list_for_each_entry_safe(sa_ctl, tsa_ctl, &fcport->edif.rx_sa_list,
+ next) {
+ list_del(&sa_ctl->next);
+ kfree(sa_ctl);
+ }
+
+ spin_unlock_irqrestore(&fcport->edif.sa_list_lock, flags);
+}
+
+struct edif_sa_ctl *
+qla_edif_find_sa_ctl_by_index(fc_port_t *fcport, int index, int dir)
+{
+ struct edif_sa_ctl *sa_ctl, *tsa_ctl;
+ struct list_head *sa_list;
+
+ if (dir == SAU_FLG_TX)
+ sa_list = &fcport->edif.tx_sa_list;
+ else
+ sa_list = &fcport->edif.rx_sa_list;
+
+ list_for_each_entry_safe(sa_ctl, tsa_ctl, sa_list, next) {
+ if (test_bit(EDIF_SA_CTL_USED, &sa_ctl->state) &&
+ sa_ctl->index == index)
+ return sa_ctl;
+ }
+ return NULL;
+}
+
+/* add the sa to the correct list */
+static int
+qla24xx_check_sadb_avail_slot(struct bsg_job *bsg_job, fc_port_t *fcport,
+ struct qla_sa_update_frame *sa_frame)
+{
+ struct edif_sa_ctl *sa_ctl = NULL;
+ int dir;
+ uint16_t sa_index;
+
+ dir = (sa_frame->flags & SAU_FLG_TX);
+
+ /* map the spi to an sa_index */
+ sa_index = qla_edif_sadb_get_sa_index(fcport, sa_frame);
+ if (sa_index == RX_DELETE_NO_EDIF_SA_INDEX) {
+ /* process rx delete */
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x3063,
+ "%s: rx delete for lid 0x%x, spi 0x%x, no entry found\n",
+ __func__, fcport->loop_id, sa_frame->spi);
+
+ /* build and send the aen */
+ fcport->edif.rx_sa_set = 1;
+ fcport->edif.rx_sa_pending = 0;
+ qla_edb_eventcreate(fcport->vha,
+ VND_CMD_AUTH_STATE_SAUPDATE_COMPL,
+ QL_VND_SA_STAT_SUCCESS,
+ QL_VND_RX_SA_KEY, fcport);
+
+ /* force a return of good bsg status; */
+ return RX_DELETE_NO_EDIF_SA_INDEX;
+ } else if (sa_index == INVALID_EDIF_SA_INDEX) {
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,
+ "%s: Failed to get sa_index for spi 0x%x, dir: %d\n",
+ __func__, sa_frame->spi, dir);
+ return INVALID_EDIF_SA_INDEX;
+ }
+
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,
+ "%s: index %d allocated to spi 0x%x, dir: %d, nport_handle: 0x%x\n",
+ __func__, sa_index, sa_frame->spi, dir, fcport->loop_id);
+
+ /* This is a local copy of sa_frame. */
+ sa_frame->fast_sa_index = sa_index;
+ /* create the sa_ctl */
+ sa_ctl = qla_edif_add_sa_ctl(fcport, sa_frame, dir);
+ if (!sa_ctl) {
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,
+ "%s: Failed to add sa_ctl for spi 0x%x, dir: %d, sa_index: %d\n",
+ __func__, sa_frame->spi, dir, sa_index);
+ return -1;
+ }
+
+ set_bit(EDIF_SA_CTL_USED, &sa_ctl->state);
+
+ if (dir == SAU_FLG_TX)
+ fcport->edif.tx_rekey_cnt++;
+ else
+ fcport->edif.rx_rekey_cnt++;
+
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,
+ "%s: Found sa_ctl %p, index %d, state 0x%lx, tx_cnt %d, rx_cnt %d, nport_handle: 0x%x\n",
+ __func__, sa_ctl, sa_ctl->index, sa_ctl->state,
+ fcport->edif.tx_rekey_cnt,
+ fcport->edif.rx_rekey_cnt, fcport->loop_id);
+
+ return 0;
+}
+
+#define QLA_SA_UPDATE_FLAGS_RX_KEY 0x0
+#define QLA_SA_UPDATE_FLAGS_TX_KEY 0x2
+
+int
+qla24xx_sadb_update(struct bsg_job *bsg_job)
+{
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
+ scsi_qla_host_t *vha = shost_priv(host);
+ fc_port_t *fcport = NULL;
+ srb_t *sp = NULL;
+ struct edif_list_entry *edif_entry = NULL;
+ int found = 0;
+ int rval = 0;
+ int result = 0;
+ struct qla_sa_update_frame sa_frame;
+ struct srb_iocb *iocb_cmd;
+
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d,
+ "%s entered, vha: 0x%p\n", __func__, vha);
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, &sa_frame,
+ sizeof(struct qla_sa_update_frame));
+
+ /* Check if host is online */
+ if (!vha->flags.online) {
+ ql_log(ql_log_warn, vha, 0x70a1, "Host is not online\n");
+ rval = -EIO;
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ goto done;
+ }
+
+ if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+ ql_log(ql_log_warn, vha, 0x70a1, "App not started\n");
+ rval = -EIO;
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ goto done;
+ }
+
+ fcport = qla2x00_find_fcport_by_pid(vha, &sa_frame.port_id);
+ if (fcport) {
+ found = 1;
+ if (sa_frame.flags == QLA_SA_UPDATE_FLAGS_TX_KEY)
+ fcport->edif.tx_bytes = 0;
+ if (sa_frame.flags == QLA_SA_UPDATE_FLAGS_RX_KEY)
+ fcport->edif.rx_bytes = 0;
+ }
+
+ if (!found) {
+ ql_dbg(ql_dbg_edif, vha, 0x70a3, "Failed to find port= %06x\n",
+ sa_frame.port_id.b24);
+ rval = -EINVAL;
+ SET_DID_STATUS(bsg_reply->result, DID_TARGET_FAILURE);
+ goto done;
+ }
+
+ /* make sure the nport_handle is valid */
+ if (fcport->loop_id == FC_NO_LOOP_ID) {
+ ql_dbg(ql_dbg_edif, vha, 0x70e1,
+ "%s: %8phN lid=FC_NO_LOOP_ID, spi: 0x%x, DS %d, returning NO_CONNECT\n",
+ __func__, fcport->port_name, sa_frame.spi,
+ fcport->disc_state);
+ rval = -EINVAL;
+ SET_DID_STATUS(bsg_reply->result, DID_NO_CONNECT);
+ goto done;
+ }
+
+ /* allocate and queue an sa_ctl */
+ result = qla24xx_check_sadb_avail_slot(bsg_job, fcport, &sa_frame);
+
+ /* failure of bsg */
+ if (result == INVALID_EDIF_SA_INDEX) {
+ ql_dbg(ql_dbg_edif, vha, 0x70e1,
+ "%s: %8phN, skipping update.\n",
+ __func__, fcport->port_name);
+ rval = -EINVAL;
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ goto done;
+
+ /* rx delete failure */
+ } else if (result == RX_DELETE_NO_EDIF_SA_INDEX) {
+ ql_dbg(ql_dbg_edif, vha, 0x70e1,
+ "%s: %8phN, skipping rx delete.\n",
+ __func__, fcport->port_name);
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+ goto done;
+ }
+
+ ql_dbg(ql_dbg_edif, vha, 0x70e1,
+ "%s: %8phN, sa_index in sa_frame: %d flags %xh\n",
+ __func__, fcport->port_name, sa_frame.fast_sa_index,
+ sa_frame.flags);
+
+ /* looking for rx index and delete */
+ if (((sa_frame.flags & SAU_FLG_TX) == 0) &&
+ (sa_frame.flags & SAU_FLG_INV)) {
+ uint16_t nport_handle = fcport->loop_id;
+ uint16_t sa_index = sa_frame.fast_sa_index;
+
+ /*
+ * make sure we have an existing rx key, otherwise just process
+ * this as a straight delete just like TX
+ * This is NOT a normal case, it indicates an error recovery or key cleanup
+ * by the ipsec code above us.
+ */
+ edif_entry = qla_edif_list_find_sa_index(fcport, fcport->loop_id);
+ if (!edif_entry) {
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: WARNING: no active sa_index for nport_handle 0x%x, forcing delete for sa_index 0x%x\n",
+ __func__, fcport->loop_id, sa_index);
+ goto force_rx_delete;
+ }
+
+ /*
+ * if we have a forced delete for rx, remove the sa_index from the edif list
+ * and proceed with normal delete. The rx delay timer should not be running
+ */
+ if ((sa_frame.flags & SAU_FLG_FORCE_DELETE) == SAU_FLG_FORCE_DELETE) {
+ qla_edif_list_delete_sa_index(fcport, edif_entry);
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: FORCE DELETE flag found for nport_handle 0x%x, sa_index 0x%x, forcing DELETE\n",
+ __func__, fcport->loop_id, sa_index);
+ kfree(edif_entry);
+ goto force_rx_delete;
+ }
+
+ /*
+ * delayed rx delete
+ *
+ * if delete_sa_index is not invalid then there is already
+ * a delayed index in progress, return bsg bad status
+ */
+ if (edif_entry->delete_sa_index != INVALID_EDIF_SA_INDEX) {
+ struct edif_sa_ctl *sa_ctl;
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: delete for lid 0x%x, delete_sa_index %d is pending\n",
+ __func__, edif_entry->handle, edif_entry->delete_sa_index);
+
+ /* free up the sa_ctl that was allocated with the sa_index */
+ sa_ctl = qla_edif_find_sa_ctl_by_index(fcport, sa_index,
+ (sa_frame.flags & SAU_FLG_TX));
+ if (sa_ctl) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: freeing sa_ctl for index %d\n",
+ __func__, sa_ctl->index);
+ qla_edif_free_sa_ctl(fcport, sa_ctl, sa_ctl->index);
+ }
+
+ /* release the sa_index */
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: freeing sa_index %d, nph: 0x%x\n",
+ __func__, sa_index, nport_handle);
+ qla_edif_sadb_delete_sa_index(fcport, nport_handle, sa_index);
+
+ rval = -EINVAL;
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ goto done;
+ }
+
+ fcport->edif.rekey_cnt++;
+
+ /* configure and start the rx delay timer */
+ edif_entry->fcport = fcport;
+ edif_entry->timer.expires = jiffies + RX_DELAY_DELETE_TIMEOUT * HZ;
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: adding timer, entry: %p, delete sa_index %d, lid 0x%x to edif_list\n",
+ __func__, edif_entry, sa_index, nport_handle);
+
+ /*
+ * Start the timer when we queue the delayed rx delete.
+ * This is an activity timer that goes off if we have not
+ * received packets with the new sa_index
+ */
+ add_timer(&edif_entry->timer);
+
+ /*
+ * sa_delete for rx key with an active rx key including this one
+ * add the delete rx sa index to the hash so we can look for it
+ * in the rsp queue. Do this after making any changes to the
+ * edif_entry as part of the rx delete.
+ */
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: delete sa_index %d, lid 0x%x to edif_list. bsg done ptr %p\n",
+ __func__, sa_index, nport_handle, bsg_job);
+
+ edif_entry->delete_sa_index = sa_index;
+
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_reply->result = DID_OK << 16;
+
+ goto done;
+
+ /*
+ * rx index and update
+ * add the index to the list and continue with normal update
+ */
+ } else if (((sa_frame.flags & SAU_FLG_TX) == 0) &&
+ ((sa_frame.flags & SAU_FLG_INV) == 0)) {
+ /* sa_update for rx key */
+ uint32_t nport_handle = fcport->loop_id;
+ uint16_t sa_index = sa_frame.fast_sa_index;
+ int result;
+
+ /*
+ * add the update rx sa index to the hash so we can look for it
+ * in the rsp queue and continue normally
+ */
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: adding update sa_index %d, lid 0x%x to edif_list\n",
+ __func__, sa_index, nport_handle);
+
+ result = qla_edif_list_add_sa_update_index(fcport, sa_index,
+ nport_handle);
+ if (result) {
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: SA_UPDATE failed to add new sa index %d to list for lid 0x%x\n",
+ __func__, sa_index, nport_handle);
+ }
+ }
+ if (sa_frame.flags & SAU_FLG_GMAC_MODE)
+ fcport->edif.aes_gmac = 1;
+ else
+ fcport->edif.aes_gmac = 0;
+
+force_rx_delete:
+ /*
+ * sa_update for both rx and tx keys, sa_delete for tx key
+ * immediately process the request
+ */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp) {
+ rval = -ENOMEM;
+ SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);
+ goto done;
+ }
+
+ sp->type = SRB_SA_UPDATE;
+ sp->name = "bsg_sa_update";
+ sp->u.bsg_job = bsg_job;
+ /* sp->free = qla2x00_bsg_sp_free; */
+ sp->free = qla2x00_rel_sp;
+ sp->done = qla2x00_bsg_job_done;
+ iocb_cmd = &sp->u.iocb_cmd;
+ iocb_cmd->u.sa_update.sa_frame = sa_frame;
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_dbg_edif, vha, 0x70e3,
+ "qla2x00_start_sp failed=%d.\n", rval);
+
+ qla2x00_rel_sp(sp);
+ rval = -EIO;
+ SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);
+ goto done;
+ }
+
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: %s sent, hdl=%x, portid=%06x.\n",
+ __func__, sp->name, sp->handle, fcport->d_id.b24);
+
+ fcport->edif.rekey_cnt++;
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ SET_DID_STATUS(bsg_reply->result, DID_OK);
+
+ return 0;
+
+/*
+ * send back error status
+ */
+done:
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s:status: FAIL, result: 0x%x, bsg ptr done %p\n",
+ __func__, bsg_reply->result, bsg_job);
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+
+ return 0;
+}
+
+static void
+qla_enode_free(scsi_qla_host_t *vha, struct enode *node)
+{
+ node->ntype = N_UNDEF;
+ kfree(node);
+}
+
+/**
+ * qla_enode_init - initialize enode structs & lock
+ * @vha: host adapter pointer
+ *
+ * should only be called when driver attaching
+ */
+void
+qla_enode_init(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ char name[32];
+
+ if (vha->pur_cinfo.enode_flags == ENODE_ACTIVE) {
+ /* list still active - error */
+ ql_dbg(ql_dbg_edif, vha, 0x09102, "%s enode still active\n",
+ __func__);
+ return;
+ }
+
+ /* initialize lock which protects pur_core & init list */
+ spin_lock_init(&vha->pur_cinfo.pur_lock);
+ INIT_LIST_HEAD(&vha->pur_cinfo.head);
+
+ snprintf(name, sizeof(name), "%s_%d_purex", QLA2XXX_DRIVER_NAME,
+ ha->pdev->device);
+}
+
+/**
+ * qla_enode_stop - stop and clear and enode data
+ * @vha: host adapter pointer
+ *
+ * called when app notified it is exiting
+ */
+void
+qla_enode_stop(scsi_qla_host_t *vha)
+{
+ unsigned long flags;
+ struct enode *node, *q;
+
+ if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {
+ /* doorbell list not enabled */
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s enode not active\n", __func__);
+ return;
+ }
+
+ /* grab lock so list doesn't move */
+ spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);
+
+ vha->pur_cinfo.enode_flags &= ~ENODE_ACTIVE; /* mark it not active */
+
+ /* hopefully this is a null list at this point */
+ list_for_each_entry_safe(node, q, &vha->pur_cinfo.head, list) {
+ ql_dbg(ql_dbg_edif, vha, 0x910f,
+ "%s freeing enode type=%x, cnt=%x\n", __func__, node->ntype,
+ node->dinfo.nodecnt);
+ list_del_init(&node->list);
+ qla_enode_free(vha, node);
+ }
+ spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
+}
+
+/*
+ * allocate enode struct and populate buffer
+ * returns: enode pointer with buffers
+ * NULL on error
+ */
+static struct enode *
+qla_enode_alloc(scsi_qla_host_t *vha, uint32_t ntype)
+{
+ struct enode *node;
+ struct purexevent *purex;
+
+ node = kzalloc(RX_ELS_SIZE, GFP_ATOMIC);
+ if (!node)
+ return NULL;
+
+ purex = &node->u.purexinfo;
+ purex->msgp = (u8 *)(node + 1);
+ purex->msgp_len = ELS_MAX_PAYLOAD;
+
+ node->ntype = ntype;
+ INIT_LIST_HEAD(&node->list);
+ return node;
+}
+
+static void
+qla_enode_add(scsi_qla_host_t *vha, struct enode *ptr)
+{
+ unsigned long flags;
+
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x9109,
+ "%s add enode for type=%x, cnt=%x\n",
+ __func__, ptr->ntype, ptr->dinfo.nodecnt);
+
+ spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);
+ list_add_tail(&ptr->list, &vha->pur_cinfo.head);
+ spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
+
+ return;
+}
+
+static struct enode *
+qla_enode_find(scsi_qla_host_t *vha, uint32_t ntype, uint32_t p1, uint32_t p2)
+{
+ struct enode *node_rtn = NULL;
+ struct enode *list_node = NULL;
+ unsigned long flags;
+ struct list_head *pos, *q;
+ uint32_t sid;
+ uint32_t rw_flag;
+ struct purexevent *purex;
+
+ /* secure the list from moving under us */
+ spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);
+
+ list_for_each_safe(pos, q, &vha->pur_cinfo.head) {
+ list_node = list_entry(pos, struct enode, list);
+
+ /* node type determines what p1 and p2 are */
+ purex = &list_node->u.purexinfo;
+ sid = p1;
+ rw_flag = p2;
+
+ if (purex->pur_info.pur_sid.b24 == sid) {
+ if (purex->pur_info.pur_pend == 1 &&
+ rw_flag == PUR_GET) {
+ /*
+ * if the receive is in progress
+ * and its a read/get then can't
+ * transfer yet
+ */
+ ql_dbg(ql_dbg_edif, vha, 0x9106,
+ "%s purex xfer in progress for sid=%x\n",
+ __func__, sid);
+ } else {
+ /* found it and its complete */
+ node_rtn = list_node;
+ list_del(pos);
+ break;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
+
+ return node_rtn;
+}
+
+/**
+ * qla_pur_get_pending - read/return authentication message sent
+ * from remote port
+ * @vha: host adapter pointer
+ * @fcport: session pointer
+ * @bsg_job: user request where the message is copy to.
+ */
+static int
+qla_pur_get_pending(scsi_qla_host_t *vha, fc_port_t *fcport,
+ struct bsg_job *bsg_job)
+{
+ struct enode *ptr;
+ struct purexevent *purex;
+ struct qla_bsg_auth_els_reply *rpl =
+ (struct qla_bsg_auth_els_reply *)bsg_job->reply;
+
+ bsg_job->reply_len = sizeof(*rpl);
+
+ ptr = qla_enode_find(vha, N_PUREX, fcport->d_id.b24, PUR_GET);
+ if (!ptr) {
+ ql_dbg(ql_dbg_edif, vha, 0x9111,
+ "%s no enode data found for %8phN sid=%06x\n",
+ __func__, fcport->port_name, fcport->d_id.b24);
+ SET_DID_STATUS(rpl->r.result, DID_IMM_RETRY);
+ return -EIO;
+ }
+
+ /*
+ * enode is now off the linked list and is ours to deal with
+ */
+ purex = &ptr->u.purexinfo;
+
+ /* Copy info back to caller */
+ rpl->rx_xchg_address = purex->pur_info.pur_rx_xchg_address;
+
+ SET_DID_STATUS(rpl->r.result, DID_OK);
+ rpl->r.reply_payload_rcv_len =
+ sg_pcopy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, purex->msgp,
+ purex->pur_info.pur_bytes_rcvd, 0);
+
+ /* data copy / passback completed - destroy enode */
+ qla_enode_free(vha, ptr);
+
+ return 0;
+}
+
+/* it is assume qpair lock is held */
+static int
+qla_els_reject_iocb(scsi_qla_host_t *vha, struct qla_qpair *qp,
+ struct qla_els_pt_arg *a)
+{
+ struct els_entry_24xx *els_iocb;
+
+ els_iocb = __qla2x00_alloc_iocbs(qp, NULL);
+ if (!els_iocb) {
+ ql_log(ql_log_warn, vha, 0x700c,
+ "qla2x00_alloc_iocbs failed.\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ qla_els_pt_iocb(vha, els_iocb, a);
+
+ ql_dbg(ql_dbg_edif, vha, 0x0183,
+ "Sending ELS reject...\n");
+ ql_dump_buffer(ql_dbg_edif + ql_dbg_verbose, vha, 0x0185,
+ vha->hw->elsrej.c, sizeof(*vha->hw->elsrej.c));
+ /* flush iocb to mem before notifying hw doorbell */
+ wmb();
+ qla2x00_start_iocbs(vha, qp->req);
+ return 0;
+}
+
+void
+qla_edb_init(scsi_qla_host_t *vha)
+{
+ if (vha->e_dbell.db_flags == EDB_ACTIVE) {
+ /* list already init'd - error */
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "edif db already initialized, cannot reinit\n");
+ return;
+ }
+
+ /* initialize lock which protects doorbell & init list */
+ spin_lock_init(&vha->e_dbell.db_lock);
+ INIT_LIST_HEAD(&vha->e_dbell.head);
+
+ /* create and initialize doorbell */
+ init_completion(&vha->e_dbell.dbell);
+}
+
+static void
+qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node)
+{
+ /*
+ * releases the space held by this edb node entry
+ * this function does _not_ free the edb node itself
+ * NB: the edb node entry passed should not be on any list
+ *
+ * currently for doorbell there's no additional cleanup
+ * needed, but here as a placeholder for furture use.
+ */
+
+ if (!node) {
+ ql_dbg(ql_dbg_edif, vha, 0x09122,
+ "%s error - no valid node passed\n", __func__);
+ return;
+ }
+
+ node->ntype = N_UNDEF;
+}
+
+/* function called when app is stopping */
+
+void
+qla_edb_stop(scsi_qla_host_t *vha)
+{
+ unsigned long flags;
+ struct edb_node *node, *q;
+
+ if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+ /* doorbell list not enabled */
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s doorbell not enabled\n", __func__);
+ return;
+ }
+
+ /* grab lock so list doesn't move */
+ spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
+
+ vha->e_dbell.db_flags &= ~EDB_ACTIVE; /* mark it not active */
+ /* hopefully this is a null list at this point */
+ list_for_each_entry_safe(node, q, &vha->e_dbell.head, list) {
+ ql_dbg(ql_dbg_edif, vha, 0x910f,
+ "%s freeing edb_node type=%x\n",
+ __func__, node->ntype);
+ qla_edb_node_free(vha, node);
+ list_del(&node->list);
+
+ kfree(node);
+ }
+ spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
+
+ /* wake up doorbell waiters - they'll be dismissed with error code */
+ complete_all(&vha->e_dbell.dbell);
+}
+
+static struct edb_node *
+qla_edb_node_alloc(scsi_qla_host_t *vha, uint32_t ntype)
+{
+ struct edb_node *node;
+
+ node = kzalloc(sizeof(*node), GFP_ATOMIC);
+ if (!node) {
+ /* couldn't get space */
+ ql_dbg(ql_dbg_edif, vha, 0x9100,
+ "edb node unable to be allocated\n");
+ return NULL;
+ }
+
+ node->ntype = ntype;
+ INIT_LIST_HEAD(&node->list);
+ return node;
+}
+
+/* adds a already allocated enode to the linked list */
+static bool
+qla_edb_node_add(scsi_qla_host_t *vha, struct edb_node *ptr)
+{
+ unsigned long flags;
+
+ if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+ /* doorbell list not enabled */
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s doorbell not enabled\n", __func__);
+ return false;
+ }
+
+ spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
+ list_add_tail(&ptr->list, &vha->e_dbell.head);
+ spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
+
+ /* ring doorbell for waiters */
+ complete(&vha->e_dbell.dbell);
+
+ return true;
+}
+
+/* adds event to doorbell list */
+void
+qla_edb_eventcreate(scsi_qla_host_t *vha, uint32_t dbtype,
+ uint32_t data, uint32_t data2, fc_port_t *sfcport)
+{
+ struct edb_node *edbnode;
+ fc_port_t *fcport = sfcport;
+ port_id_t id;
+
+ if (!vha->hw->flags.edif_enabled) {
+ /* edif not enabled */
+ return;
+ }
+
+ if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+ if (fcport)
+ fcport->edif.auth_state = dbtype;
+ /* doorbell list not enabled */
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s doorbell not enabled (type=%d\n", __func__, dbtype);
+ return;
+ }
+
+ edbnode = qla_edb_node_alloc(vha, dbtype);
+ if (!edbnode) {
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s unable to alloc db node\n", __func__);
+ return;
+ }
+
+ if (!fcport) {
+ id.b.domain = (data >> 16) & 0xff;
+ id.b.area = (data >> 8) & 0xff;
+ id.b.al_pa = data & 0xff;
+ ql_dbg(ql_dbg_edif, vha, 0x09222,
+ "%s: Arrived s_id: %06x\n", __func__,
+ id.b24);
+ fcport = qla2x00_find_fcport_by_pid(vha, &id);
+ if (!fcport) {
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s can't find fcport for sid= 0x%x - ignoring\n",
+ __func__, id.b24);
+ kfree(edbnode);
+ return;
+ }
+ }
+
+ /* populate the edb node */
+ switch (dbtype) {
+ case VND_CMD_AUTH_STATE_NEEDED:
+ case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
+ edbnode->u.plogi_did.b24 = fcport->d_id.b24;
+ break;
+ case VND_CMD_AUTH_STATE_ELS_RCVD:
+ edbnode->u.els_sid.b24 = fcport->d_id.b24;
+ break;
+ case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:
+ edbnode->u.sa_aen.port_id = fcport->d_id;
+ edbnode->u.sa_aen.status = data;
+ edbnode->u.sa_aen.key_type = data2;
+ break;
+ default:
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s unknown type: %x\n", __func__, dbtype);
+ qla_edb_node_free(vha, edbnode);
+ kfree(edbnode);
+ edbnode = NULL;
+ break;
+ }
+
+ if (edbnode && (!qla_edb_node_add(vha, edbnode))) {
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s unable to add dbnode\n", __func__);
+ qla_edb_node_free(vha, edbnode);
+ kfree(edbnode);
+ return;
+ }
+ if (edbnode && fcport)
+ fcport->edif.auth_state = dbtype;
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s Doorbell produced : type=%d %p\n", __func__, dbtype, edbnode);
+}
+
+static struct edb_node *
+qla_edb_getnext(scsi_qla_host_t *vha)
+{
+ unsigned long flags;
+ struct edb_node *edbnode = NULL;
+
+ spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
+
+ /* db nodes are fifo - no qualifications done */
+ if (!list_empty(&vha->e_dbell.head)) {
+ edbnode = list_first_entry(&vha->e_dbell.head,
+ struct edb_node, list);
+ list_del(&edbnode->list);
+ }
+
+ spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
+
+ return edbnode;
+}
+
+void
+qla_edif_timer(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!vha->vp_idx && N2N_TOPO(ha) && ha->flags.n2n_fw_acc_sec) {
+ if (vha->e_dbell.db_flags != EDB_ACTIVE &&
+ ha->edif_post_stop_cnt_down) {
+ ha->edif_post_stop_cnt_down--;
+
+ /*
+ * turn off auto 'Plogi Acc + secure=1' feature
+ * Set Add FW option[3]
+ * BIT_15, if.
+ */
+ if (ha->edif_post_stop_cnt_down == 0) {
+ ql_dbg(ql_dbg_async, vha, 0x911d,
+ "%s chip reset to turn off PLOGI ACC + secure\n",
+ __func__);
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ }
+ } else {
+ ha->edif_post_stop_cnt_down = 60;
+ }
+ }
+}
+
+/*
+ * app uses separate thread to read this. It'll wait until the doorbell
+ * is rung by the driver or the max wait time has expired
+ */
+ssize_t
+edif_doorbell_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct edb_node *dbnode = NULL;
+ struct edif_app_dbell *ap = (struct edif_app_dbell *)buf;
+ uint32_t dat_siz, buf_size, sz;
+
+ /* TODO: app currently hardcoded to 256. Will transition to bsg */
+ sz = 256;
+
+ /* stop new threads from waiting if we're not init'd */
+ if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x09122,
+ "%s error - edif db not enabled\n", __func__);
+ return 0;
+ }
+
+ if (!vha->hw->flags.edif_enabled) {
+ /* edif not enabled */
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x09122,
+ "%s error - edif not enabled\n", __func__);
+ return -1;
+ }
+
+ buf_size = 0;
+ while ((sz - buf_size) >= sizeof(struct edb_node)) {
+ /* remove the next item from the doorbell list */
+ dat_siz = 0;
+ dbnode = qla_edb_getnext(vha);
+ if (dbnode) {
+ ap->event_code = dbnode->ntype;
+ switch (dbnode->ntype) {
+ case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
+ case VND_CMD_AUTH_STATE_NEEDED:
+ ap->port_id = dbnode->u.plogi_did;
+ dat_siz += sizeof(ap->port_id);
+ break;
+ case VND_CMD_AUTH_STATE_ELS_RCVD:
+ ap->port_id = dbnode->u.els_sid;
+ dat_siz += sizeof(ap->port_id);
+ break;
+ case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:
+ ap->port_id = dbnode->u.sa_aen.port_id;
+ memcpy(ap->event_data, &dbnode->u,
+ sizeof(struct edif_sa_update_aen));
+ dat_siz += sizeof(struct edif_sa_update_aen);
+ break;
+ default:
+ /* unknown node type, rtn unknown ntype */
+ ap->event_code = VND_CMD_AUTH_STATE_UNDEF;
+ memcpy(ap->event_data, &dbnode->ntype, 4);
+ dat_siz += 4;
+ break;
+ }
+
+ ql_dbg(ql_dbg_edif, vha, 0x09102,
+ "%s Doorbell consumed : type=%d %p\n",
+ __func__, dbnode->ntype, dbnode);
+ /* we're done with the db node, so free it up */
+ qla_edb_node_free(vha, dbnode);
+ kfree(dbnode);
+ } else {
+ break;
+ }
+
+ ap->event_data_size = dat_siz;
+ /* 8bytes = ap->event_code + ap->event_data_size */
+ buf_size += dat_siz + 8;
+ ap = (struct edif_app_dbell *)(buf + buf_size);
+ }
+ return buf_size;
+}
+
+static void qla_noop_sp_done(srb_t *sp, int res)
+{
+ sp->free(sp);
+}
+
+/*
+ * Called from work queue
+ * build and send the sa_update iocb to delete an rx sa_index
+ */
+int
+qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e)
+{
+ srb_t *sp;
+ fc_port_t *fcport = NULL;
+ struct srb_iocb *iocb_cmd = NULL;
+ int rval = QLA_SUCCESS;
+ struct edif_sa_ctl *sa_ctl = e->u.sa_update.sa_ctl;
+ uint16_t nport_handle = e->u.sa_update.nport_handle;
+
+ ql_dbg(ql_dbg_edif, vha, 0x70e6,
+ "%s: starting, sa_ctl: %p\n", __func__, sa_ctl);
+
+ if (!sa_ctl) {
+ ql_dbg(ql_dbg_edif, vha, 0x70e6,
+ "sa_ctl allocation failed\n");
+ return -ENOMEM;
+ }
+
+ fcport = sa_ctl->fcport;
+
+ /* Alloc SRB structure */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp) {
+ ql_dbg(ql_dbg_edif, vha, 0x70e6,
+ "SRB allocation failed\n");
+ return -ENOMEM;
+ }
+
+ fcport->flags |= FCF_ASYNC_SENT;
+ iocb_cmd = &sp->u.iocb_cmd;
+ iocb_cmd->u.sa_update.sa_ctl = sa_ctl;
+
+ ql_dbg(ql_dbg_edif, vha, 0x3073,
+ "Enter: SA REPL portid=%06x, sa_ctl %p, index %x, nport_handle: 0x%x\n",
+ fcport->d_id.b24, sa_ctl, sa_ctl->index, nport_handle);
+ /*
+ * if this is a sadb cleanup delete, mark it so the isr can
+ * take the correct action
+ */
+ if (sa_ctl->flags & EDIF_SA_CTL_FLG_CLEANUP_DEL) {
+ /* mark this srb as a cleanup delete */
+ sp->flags |= SRB_EDIF_CLEANUP_DELETE;
+ ql_dbg(ql_dbg_edif, vha, 0x70e6,
+ "%s: sp 0x%p flagged as cleanup delete\n", __func__, sp);
+ }
+
+ sp->type = SRB_SA_REPLACE;
+ sp->name = "SA_REPLACE";
+ sp->fcport = fcport;
+ sp->free = qla2x00_rel_sp;
+ sp->done = qla_noop_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+
+ if (rval != QLA_SUCCESS)
+ rval = QLA_FUNCTION_FAILED;
+
+ return rval;
+}
+
+void qla24xx_sa_update_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb)
+{
+ int itr = 0;
+ struct scsi_qla_host *vha = sp->vha;
+ struct qla_sa_update_frame *sa_frame =
+ &sp->u.iocb_cmd.u.sa_update.sa_frame;
+ u8 flags = 0;
+
+ switch (sa_frame->flags & (SAU_FLG_INV | SAU_FLG_TX)) {
+ case 0:
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: EDIF SA UPDATE RX IOCB vha: 0x%p index: %d\n",
+ __func__, vha, sa_frame->fast_sa_index);
+ break;
+ case 1:
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: EDIF SA DELETE RX IOCB vha: 0x%p index: %d\n",
+ __func__, vha, sa_frame->fast_sa_index);
+ flags |= SA_FLAG_INVALIDATE;
+ break;
+ case 2:
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: EDIF SA UPDATE TX IOCB vha: 0x%p index: %d\n",
+ __func__, vha, sa_frame->fast_sa_index);
+ flags |= SA_FLAG_TX;
+ break;
+ case 3:
+ ql_dbg(ql_dbg_edif, vha, 0x911d,
+ "%s: EDIF SA DELETE TX IOCB vha: 0x%p index: %d\n",
+ __func__, vha, sa_frame->fast_sa_index);
+ flags |= SA_FLAG_TX | SA_FLAG_INVALIDATE;
+ break;
+ }
+
+ sa_update_iocb->entry_type = SA_UPDATE_IOCB_TYPE;
+ sa_update_iocb->entry_count = 1;
+ sa_update_iocb->sys_define = 0;
+ sa_update_iocb->entry_status = 0;
+ sa_update_iocb->handle = sp->handle;
+ sa_update_iocb->u.nport_handle = cpu_to_le16(sp->fcport->loop_id);
+ sa_update_iocb->vp_index = sp->fcport->vha->vp_idx;
+ sa_update_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
+ sa_update_iocb->port_id[1] = sp->fcport->d_id.b.area;
+ sa_update_iocb->port_id[2] = sp->fcport->d_id.b.domain;
+
+ sa_update_iocb->flags = flags;
+ sa_update_iocb->salt = cpu_to_le32(sa_frame->salt);
+ sa_update_iocb->spi = cpu_to_le32(sa_frame->spi);
+ sa_update_iocb->sa_index = cpu_to_le16(sa_frame->fast_sa_index);
+
+ sa_update_iocb->sa_control |= SA_CNTL_ENC_FCSP;
+ if (sp->fcport->edif.aes_gmac)
+ sa_update_iocb->sa_control |= SA_CNTL_AES_GMAC;
+
+ if (sa_frame->flags & SAU_FLG_KEY256) {
+ sa_update_iocb->sa_control |= SA_CNTL_KEY256;
+ for (itr = 0; itr < 32; itr++)
+ sa_update_iocb->sa_key[itr] = sa_frame->sa_key[itr];
+ } else {
+ sa_update_iocb->sa_control |= SA_CNTL_KEY128;
+ for (itr = 0; itr < 16; itr++)
+ sa_update_iocb->sa_key[itr] = sa_frame->sa_key[itr];
+ }
+
+ ql_dbg(ql_dbg_edif, vha, 0x921d,
+ "%s SAU Port ID = %02x%02x%02x, flags=%xh, index=%u, ctl=%xh, SPI 0x%x flags 0x%x hdl=%x gmac %d\n",
+ __func__, sa_update_iocb->port_id[2], sa_update_iocb->port_id[1],
+ sa_update_iocb->port_id[0], sa_update_iocb->flags, sa_update_iocb->sa_index,
+ sa_update_iocb->sa_control, sa_update_iocb->spi, sa_frame->flags, sp->handle,
+ sp->fcport->edif.aes_gmac);
+
+ if (sa_frame->flags & SAU_FLG_TX)
+ sp->fcport->edif.tx_sa_pending = 1;
+ else
+ sp->fcport->edif.rx_sa_pending = 1;
+
+ sp->fcport->vha->qla_stats.control_requests++;
+}
+
+void
+qla24xx_sa_replace_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb)
+{
+ struct scsi_qla_host *vha = sp->vha;
+ struct srb_iocb *srb_iocb = &sp->u.iocb_cmd;
+ struct edif_sa_ctl *sa_ctl = srb_iocb->u.sa_update.sa_ctl;
+ uint16_t nport_handle = sp->fcport->loop_id;
+
+ sa_update_iocb->entry_type = SA_UPDATE_IOCB_TYPE;
+ sa_update_iocb->entry_count = 1;
+ sa_update_iocb->sys_define = 0;
+ sa_update_iocb->entry_status = 0;
+ sa_update_iocb->handle = sp->handle;
+
+ sa_update_iocb->u.nport_handle = cpu_to_le16(nport_handle);
+
+ sa_update_iocb->vp_index = sp->fcport->vha->vp_idx;
+ sa_update_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
+ sa_update_iocb->port_id[1] = sp->fcport->d_id.b.area;
+ sa_update_iocb->port_id[2] = sp->fcport->d_id.b.domain;
+
+ /* Invalidate the index. salt, spi, control & key are ignore */
+ sa_update_iocb->flags = SA_FLAG_INVALIDATE;
+ sa_update_iocb->salt = 0;
+ sa_update_iocb->spi = 0;
+ sa_update_iocb->sa_index = cpu_to_le16(sa_ctl->index);
+ sa_update_iocb->sa_control = 0;
+
+ ql_dbg(ql_dbg_edif, vha, 0x921d,
+ "%s SAU DELETE RX Port ID = %02x:%02x:%02x, lid %d flags=%xh, index=%u, hdl=%x\n",
+ __func__, sa_update_iocb->port_id[2], sa_update_iocb->port_id[1],
+ sa_update_iocb->port_id[0], nport_handle, sa_update_iocb->flags,
+ sa_update_iocb->sa_index, sp->handle);
+
+ sp->fcport->vha->qla_stats.control_requests++;
+}
+
+void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
+{
+ struct purex_entry_24xx *p = *pkt;
+ struct enode *ptr;
+ int sid;
+ u16 totlen;
+ struct purexevent *purex;
+ struct scsi_qla_host *host = NULL;
+ int rc;
+ struct fc_port *fcport;
+ struct qla_els_pt_arg a;
+ be_id_t beid;
+
+ memset(&a, 0, sizeof(a));
+
+ a.els_opcode = ELS_AUTH_ELS;
+ a.nport_handle = p->nport_handle;
+ a.rx_xchg_address = p->rx_xchg_addr;
+ a.did.b.domain = p->s_id[2];
+ a.did.b.area = p->s_id[1];
+ a.did.b.al_pa = p->s_id[0];
+ a.tx_byte_count = a.tx_len = sizeof(struct fc_els_ls_rjt);
+ a.tx_addr = vha->hw->elsrej.cdma;
+ a.vp_idx = vha->vp_idx;
+ a.control_flags = EPD_ELS_RJT;
+
+ sid = p->s_id[0] | (p->s_id[1] << 8) | (p->s_id[2] << 16);
+
+ totlen = (le16_to_cpu(p->frame_size) & 0x0fff) - PURX_ELS_HEADER_SIZE;
+ if (le16_to_cpu(p->status_flags) & 0x8000) {
+ totlen = le16_to_cpu(p->trunc_frame_size);
+ qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+ __qla_consume_iocb(vha, pkt, rsp);
+ return;
+ }
+
+ if (totlen > MAX_PAYLOAD) {
+ ql_dbg(ql_dbg_edif, vha, 0x0910d,
+ "%s WARNING: verbose ELS frame received (totlen=%x)\n",
+ __func__, totlen);
+ qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+ __qla_consume_iocb(vha, pkt, rsp);
+ return;
+ }
+
+ if (!vha->hw->flags.edif_enabled) {
+ /* edif support not enabled */
+ ql_dbg(ql_dbg_edif, vha, 0x910e, "%s edif not enabled\n",
+ __func__);
+ qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+ __qla_consume_iocb(vha, pkt, rsp);
+ return;
+ }
+
+ ptr = qla_enode_alloc(vha, N_PUREX);
+ if (!ptr) {
+ ql_dbg(ql_dbg_edif, vha, 0x09109,
+ "WARNING: enode alloc failed for sid=%x\n",
+ sid);
+ qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+ __qla_consume_iocb(vha, pkt, rsp);
+ return;
+ }
+
+ purex = &ptr->u.purexinfo;
+ purex->pur_info.pur_sid = a.did;
+ purex->pur_info.pur_pend = 0;
+ purex->pur_info.pur_bytes_rcvd = totlen;
+ purex->pur_info.pur_rx_xchg_address = le32_to_cpu(p->rx_xchg_addr);
+ purex->pur_info.pur_nphdl = le16_to_cpu(p->nport_handle);
+ purex->pur_info.pur_did.b.domain = p->d_id[2];
+ purex->pur_info.pur_did.b.area = p->d_id[1];
+ purex->pur_info.pur_did.b.al_pa = p->d_id[0];
+ purex->pur_info.vp_idx = p->vp_idx;
+
+ rc = __qla_copy_purex_to_buffer(vha, pkt, rsp, purex->msgp,
+ purex->msgp_len);
+ if (rc) {
+ qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+ qla_enode_free(vha, ptr);
+ return;
+ }
+ beid.al_pa = purex->pur_info.pur_did.b.al_pa;
+ beid.area = purex->pur_info.pur_did.b.area;
+ beid.domain = purex->pur_info.pur_did.b.domain;
+ host = qla_find_host_by_d_id(vha, beid);
+ if (!host) {
+ ql_log(ql_log_fatal, vha, 0x508b,
+ "%s Drop ELS due to unable to find host %06x\n",
+ __func__, purex->pur_info.pur_did.b24);
+
+ qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
+ qla_enode_free(vha, ptr);
+ return;
+ }
+
+ fcport = qla2x00_find_fcport_by_pid(host, &purex->pur_info.pur_sid);
+
+ if (host->e_dbell.db_flags != EDB_ACTIVE ||
+ (fcport && EDIF_SESSION_DOWN(fcport))) {
+ ql_dbg(ql_dbg_edif, host, 0x0910c, "%s e_dbell.db_flags =%x %06x\n",
+ __func__, host->e_dbell.db_flags,
+ fcport ? fcport->d_id.b24 : 0);
+
+ qla_els_reject_iocb(host, (*rsp)->qpair, &a);
+ qla_enode_free(host, ptr);
+ return;
+ }
+
+ /* add the local enode to the list */
+ qla_enode_add(host, ptr);
+
+ ql_dbg(ql_dbg_edif, host, 0x0910c,
+ "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n",
+ __func__, purex->pur_info.pur_bytes_rcvd, purex->pur_info.pur_sid.b24,
+ purex->pur_info.pur_did.b24, p->rx_xchg_addr);
+
+ qla_edb_eventcreate(host, VND_CMD_AUTH_STATE_ELS_RCVD, sid, 0, NULL);
+}
+
+static uint16_t qla_edif_get_sa_index_from_freepool(fc_port_t *fcport, int dir)
+{
+ struct scsi_qla_host *vha = fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ void *sa_id_map;
+ unsigned long flags = 0;
+ u16 sa_index;
+
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,
+ "%s: entry\n", __func__);
+
+ if (dir)
+ sa_id_map = ha->edif_tx_sa_id_map;
+ else
+ sa_id_map = ha->edif_rx_sa_id_map;
+
+ spin_lock_irqsave(&ha->sadb_fp_lock, flags);
+ sa_index = find_first_zero_bit(sa_id_map, EDIF_NUM_SA_INDEX);
+ if (sa_index >= EDIF_NUM_SA_INDEX) {
+ spin_unlock_irqrestore(&ha->sadb_fp_lock, flags);
+ return INVALID_EDIF_SA_INDEX;
+ }
+ set_bit(sa_index, sa_id_map);
+ spin_unlock_irqrestore(&ha->sadb_fp_lock, flags);
+
+ if (dir)
+ sa_index += EDIF_TX_SA_INDEX_BASE;
+
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: index retrieved from free pool %d\n", __func__, sa_index);
+
+ return sa_index;
+}
+
+/* find an sadb entry for an nport_handle */
+static struct edif_sa_index_entry *
+qla_edif_sadb_find_sa_index_entry(uint16_t nport_handle,
+ struct list_head *sa_list)
+{
+ struct edif_sa_index_entry *entry;
+ struct edif_sa_index_entry *tentry;
+ struct list_head *indx_list = sa_list;
+
+ list_for_each_entry_safe(entry, tentry, indx_list, next) {
+ if (entry->handle == nport_handle)
+ return entry;
+ }
+ return NULL;
+}
+
+/* remove an sa_index from the nport_handle and return it to the free pool */
+static int qla_edif_sadb_delete_sa_index(fc_port_t *fcport, uint16_t nport_handle,
+ uint16_t sa_index)
+{
+ struct edif_sa_index_entry *entry;
+ struct list_head *sa_list;
+ int dir = (sa_index < EDIF_TX_SA_INDEX_BASE) ? 0 : 1;
+ int slot = 0;
+ int free_slot_count = 0;
+ scsi_qla_host_t *vha = fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags = 0;
+
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: entry\n", __func__);
+
+ if (dir)
+ sa_list = &ha->sadb_tx_index_list;
+ else
+ sa_list = &ha->sadb_rx_index_list;
+
+ entry = qla_edif_sadb_find_sa_index_entry(nport_handle, sa_list);
+ if (!entry) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: no entry found for nport_handle 0x%x\n",
+ __func__, nport_handle);
+ return -1;
+ }
+
+ spin_lock_irqsave(&ha->sadb_lock, flags);
+ /*
+ * each tx/rx direction has up to 2 sa indexes/slots. 1 slot for in flight traffic
+ * the other is use at re-key time.
+ */
+ for (slot = 0; slot < 2; slot++) {
+ if (entry->sa_pair[slot].sa_index == sa_index) {
+ entry->sa_pair[slot].sa_index = INVALID_EDIF_SA_INDEX;
+ entry->sa_pair[slot].spi = 0;
+ free_slot_count++;
+ qla_edif_add_sa_index_to_freepool(fcport, dir, sa_index);
+ } else if (entry->sa_pair[slot].sa_index == INVALID_EDIF_SA_INDEX) {
+ free_slot_count++;
+ }
+ }
+
+ if (free_slot_count == 2) {
+ list_del(&entry->next);
+ kfree(entry);
+ }
+ spin_unlock_irqrestore(&ha->sadb_lock, flags);
+
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: sa_index %d removed, free_slot_count: %d\n",
+ __func__, sa_index, free_slot_count);
+
+ return 0;
+}
+
+void
+qla28xx_sa_update_iocb_entry(scsi_qla_host_t *v, struct req_que *req,
+ struct sa_update_28xx *pkt)
+{
+ const char *func = "SA_UPDATE_RESPONSE_IOCB";
+ srb_t *sp;
+ struct edif_sa_ctl *sa_ctl;
+ int old_sa_deleted = 1;
+ uint16_t nport_handle;
+ struct scsi_qla_host *vha;
+
+ sp = qla2x00_get_sp_from_handle(v, func, req, pkt);
+
+ if (!sp) {
+ ql_dbg(ql_dbg_edif, v, 0x3063,
+ "%s: no sp found for pkt\n", __func__);
+ return;
+ }
+ /* use sp->vha due to npiv */
+ vha = sp->vha;
+
+ switch (pkt->flags & (SA_FLAG_INVALIDATE | SA_FLAG_TX)) {
+ case 0:
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: EDIF SA UPDATE RX IOCB vha: 0x%p index: %d\n",
+ __func__, vha, pkt->sa_index);
+ break;
+ case 1:
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: EDIF SA DELETE RX IOCB vha: 0x%p index: %d\n",
+ __func__, vha, pkt->sa_index);
+ break;
+ case 2:
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: EDIF SA UPDATE TX IOCB vha: 0x%p index: %d\n",
+ __func__, vha, pkt->sa_index);
+ break;
+ case 3:
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: EDIF SA DELETE TX IOCB vha: 0x%p index: %d\n",
+ __func__, vha, pkt->sa_index);
+ break;
+ }
+
+ /*
+ * dig the nport handle out of the iocb, fcport->loop_id can not be trusted
+ * to be correct during cleanup sa_update iocbs.
+ */
+ nport_handle = sp->fcport->loop_id;
+
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: %8phN comp status=%x old_sa_info=%x new_sa_info=%x lid %d, index=0x%x pkt_flags %xh hdl=%x\n",
+ __func__, sp->fcport->port_name, pkt->u.comp_sts, pkt->old_sa_info, pkt->new_sa_info,
+ nport_handle, pkt->sa_index, pkt->flags, sp->handle);
+
+ /* if rx delete, remove the timer */
+ if ((pkt->flags & (SA_FLAG_INVALIDATE | SA_FLAG_TX)) == SA_FLAG_INVALIDATE) {
+ struct edif_list_entry *edif_entry;
+
+ sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+
+ edif_entry = qla_edif_list_find_sa_index(sp->fcport, nport_handle);
+ if (edif_entry) {
+ ql_dbg(ql_dbg_edif, vha, 0x5033,
+ "%s: removing edif_entry %p, new sa_index: 0x%x\n",
+ __func__, edif_entry, pkt->sa_index);
+ qla_edif_list_delete_sa_index(sp->fcport, edif_entry);
+ del_timer(&edif_entry->timer);
+
+ ql_dbg(ql_dbg_edif, vha, 0x5033,
+ "%s: releasing edif_entry %p, new sa_index: 0x%x\n",
+ __func__, edif_entry, pkt->sa_index);
+
+ kfree(edif_entry);
+ }
+ }
+
+ /*
+ * if this is a delete for either tx or rx, make sure it succeeded.
+ * The new_sa_info field should be 0xffff on success
+ */
+ if (pkt->flags & SA_FLAG_INVALIDATE)
+ old_sa_deleted = (le16_to_cpu(pkt->new_sa_info) == 0xffff) ? 1 : 0;
+
+ /* Process update and delete the same way */
+
+ /* If this is an sadb cleanup delete, bypass sending events to IPSEC */
+ if (sp->flags & SRB_EDIF_CLEANUP_DELETE) {
+ sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: nph 0x%x, sa_index %d removed from fw\n",
+ __func__, sp->fcport->loop_id, pkt->sa_index);
+
+ } else if ((pkt->entry_status == 0) && (pkt->u.comp_sts == 0) &&
+ old_sa_deleted) {
+ /*
+ * Note: Wa are only keeping track of latest SA,
+ * so we know when we can start enableing encryption per I/O.
+ * If all SA's get deleted, let FW reject the IOCB.
+
+ * TODO: edif: don't set enabled here I think
+ * TODO: edif: prli complete is where it should be set
+ */
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,
+ "SA(%x)updated for s_id %02x%02x%02x\n",
+ pkt->new_sa_info,
+ pkt->port_id[2], pkt->port_id[1], pkt->port_id[0]);
+ sp->fcport->edif.enable = 1;
+ if (pkt->flags & SA_FLAG_TX) {
+ sp->fcport->edif.tx_sa_set = 1;
+ sp->fcport->edif.tx_sa_pending = 0;
+ qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SAUPDATE_COMPL,
+ QL_VND_SA_STAT_SUCCESS,
+ QL_VND_TX_SA_KEY, sp->fcport);
+ } else {
+ sp->fcport->edif.rx_sa_set = 1;
+ sp->fcport->edif.rx_sa_pending = 0;
+ qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SAUPDATE_COMPL,
+ QL_VND_SA_STAT_SUCCESS,
+ QL_VND_RX_SA_KEY, sp->fcport);
+ }
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: %8phN SA update FAILED: sa_index: %d, new_sa_info %d, %02x%02x%02x\n",
+ __func__, sp->fcport->port_name, pkt->sa_index, pkt->new_sa_info,
+ pkt->port_id[2], pkt->port_id[1], pkt->port_id[0]);
+
+ if (pkt->flags & SA_FLAG_TX)
+ qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SAUPDATE_COMPL,
+ (le16_to_cpu(pkt->u.comp_sts) << 16) | QL_VND_SA_STAT_FAILED,
+ QL_VND_TX_SA_KEY, sp->fcport);
+ else
+ qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SAUPDATE_COMPL,
+ (le16_to_cpu(pkt->u.comp_sts) << 16) | QL_VND_SA_STAT_FAILED,
+ QL_VND_RX_SA_KEY, sp->fcport);
+ }
+
+ /* for delete, release sa_ctl, sa_index */
+ if (pkt->flags & SA_FLAG_INVALIDATE) {
+ /* release the sa_ctl */
+ sa_ctl = qla_edif_find_sa_ctl_by_index(sp->fcport,
+ le16_to_cpu(pkt->sa_index), (pkt->flags & SA_FLAG_TX));
+ if (sa_ctl &&
+ qla_edif_find_sa_ctl_by_index(sp->fcport, sa_ctl->index,
+ (pkt->flags & SA_FLAG_TX)) != NULL) {
+ ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,
+ "%s: freeing sa_ctl for index %d\n",
+ __func__, sa_ctl->index);
+ qla_edif_free_sa_ctl(sp->fcport, sa_ctl, sa_ctl->index);
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: sa_ctl NOT freed, sa_ctl: %p\n",
+ __func__, sa_ctl);
+ }
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: freeing sa_index %d, nph: 0x%x\n",
+ __func__, le16_to_cpu(pkt->sa_index), nport_handle);
+ qla_edif_sadb_delete_sa_index(sp->fcport, nport_handle,
+ le16_to_cpu(pkt->sa_index));
+ /*
+ * check for a failed sa_update and remove
+ * the sadb entry.
+ */
+ } else if (pkt->u.comp_sts) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: freeing sa_index %d, nph: 0x%x\n",
+ __func__, pkt->sa_index, nport_handle);
+ qla_edif_sadb_delete_sa_index(sp->fcport, nport_handle,
+ le16_to_cpu(pkt->sa_index));
+ switch (le16_to_cpu(pkt->u.comp_sts)) {
+ case CS_PORT_EDIF_UNAVAIL:
+ case CS_PORT_EDIF_LOGOUT:
+ qlt_schedule_sess_for_deletion(sp->fcport);
+ break;
+ default:
+ break;
+ }
+ }
+
+ sp->done(sp, 0);
+}
+
+/**
+ * qla28xx_start_scsi_edif() - Send a SCSI type 6 command to the ISP
+ * @sp: command to send to the ISP
+ *
+ * Return: non-zero if a failure occurred, else zero.
+ */
+int
+qla28xx_start_scsi_edif(srb_t *sp)
+{
+ int nseg;
+ unsigned long flags;
+ struct scsi_cmnd *cmd;
+ uint32_t *clr_ptr;
+ uint32_t index, i;
+ uint32_t handle;
+ uint16_t cnt;
+ int16_t req_cnt;
+ uint16_t tot_dsds;
+ __be32 *fcp_dl;
+ uint8_t additional_cdb_len;
+ struct ct6_dsd *ctx;
+ struct scsi_qla_host *vha = sp->vha;
+ struct qla_hw_data *ha = vha->hw;
+ struct cmd_type_6 *cmd_pkt;
+ struct dsd64 *cur_dsd;
+ uint8_t avail_dsds = 0;
+ struct scatterlist *sg;
+ struct req_que *req = sp->qpair->req;
+ spinlock_t *lock = sp->qpair->qp_lock_ptr;
+
+ /* Setup device pointers. */
+ cmd = GET_CMD_SP(sp);
+
+ /* So we know we haven't pci_map'ed anything yet */
+ tot_dsds = 0;
+
+ /* Send marker if required */
+ if (vha->marker_needed != 0) {
+ if (qla2x00_marker(vha, sp->qpair, 0, 0, MK_SYNC_ALL) !=
+ QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x300c,
+ "qla2x00_marker failed for cmd=%p.\n", cmd);
+ return QLA_FUNCTION_FAILED;
+ }
+ vha->marker_needed = 0;
+ }
+
+ /* Acquire ring specific lock */
+ spin_lock_irqsave(lock, flags);
+
+ /* Check for room in outstanding command list. */
+ handle = req->current_outstanding_cmd;
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
+ handle++;
+ if (handle == req->num_outstanding_cmds)
+ handle = 1;
+ if (!req->outstanding_cmds[handle])
+ break;
+ }
+ if (index == req->num_outstanding_cmds)
+ goto queuing_error;
+
+ /* Map the sg table so we have an accurate count of sg entries needed */
+ if (scsi_sg_count(cmd)) {
+ nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
+ scsi_sg_count(cmd), cmd->sc_data_direction);
+ if (unlikely(!nseg))
+ goto queuing_error;
+ } else {
+ nseg = 0;
+ }
+
+ tot_dsds = nseg;
+ req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+ if (req->cnt < (req_cnt + 2)) {
+ cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
+ rd_reg_dword(req->req_q_out);
+ if (req->ring_index < cnt)
+ req->cnt = cnt - req->ring_index;
+ else
+ req->cnt = req->length -
+ (req->ring_index - cnt);
+ if (req->cnt < (req_cnt + 2))
+ goto queuing_error;
+ }
+
+ ctx = sp->u.scmd.ct6_ctx =
+ mempool_alloc(ha->ctx_mempool, GFP_ATOMIC);
+ if (!ctx) {
+ ql_log(ql_log_fatal, vha, 0x3010,
+ "Failed to allocate ctx for cmd=%p.\n", cmd);
+ goto queuing_error;
+ }
+
+ memset(ctx, 0, sizeof(struct ct6_dsd));
+ ctx->fcp_cmnd = dma_pool_zalloc(ha->fcp_cmnd_dma_pool,
+ GFP_ATOMIC, &ctx->fcp_cmnd_dma);
+ if (!ctx->fcp_cmnd) {
+ ql_log(ql_log_fatal, vha, 0x3011,
+ "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd);
+ goto queuing_error;
+ }
+
+ /* Initialize the DSD list and dma handle */
+ INIT_LIST_HEAD(&ctx->dsd_list);
+ ctx->dsd_use_cnt = 0;
+
+ if (cmd->cmd_len > 16) {
+ additional_cdb_len = cmd->cmd_len - 16;
+ if ((cmd->cmd_len % 4) != 0) {
+ /*
+ * SCSI command bigger than 16 bytes must be
+ * multiple of 4
+ */
+ ql_log(ql_log_warn, vha, 0x3012,
+ "scsi cmd len %d not multiple of 4 for cmd=%p.\n",
+ cmd->cmd_len, cmd);
+ goto queuing_error_fcp_cmnd;
+ }
+ ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4;
+ } else {
+ additional_cdb_len = 0;
+ ctx->fcp_cmnd_len = 12 + 16 + 4;
+ }
+
+ cmd_pkt = (struct cmd_type_6 *)req->ring_ptr;
+ cmd_pkt->handle = make_handle(req->id, handle);
+
+ /*
+ * Zero out remaining portion of packet.
+ * tagged queuing modifier -- default is TSK_SIMPLE (0).
+ */
+ clr_ptr = (uint32_t *)cmd_pkt + 2;
+ memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
+ cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
+
+ /* No data transfer */
+ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
+ cmd_pkt->byte_count = cpu_to_le32(0);
+ goto no_dsds;
+ }
+
+ /* Set transfer direction */
+ if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+ cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA);
+ vha->qla_stats.output_bytes += scsi_bufflen(cmd);
+ vha->qla_stats.output_requests++;
+ sp->fcport->edif.tx_bytes += scsi_bufflen(cmd);
+ } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+ cmd_pkt->control_flags = cpu_to_le16(CF_READ_DATA);
+ vha->qla_stats.input_bytes += scsi_bufflen(cmd);
+ vha->qla_stats.input_requests++;
+ sp->fcport->edif.rx_bytes += scsi_bufflen(cmd);
+ }
+
+ cmd_pkt->control_flags |= cpu_to_le16(CF_EN_EDIF);
+ cmd_pkt->control_flags &= ~(cpu_to_le16(CF_NEW_SA));
+
+ /* One DSD is available in the Command Type 6 IOCB */
+ avail_dsds = 1;
+ cur_dsd = &cmd_pkt->fcp_dsd;
+
+ /* Load data segments */
+ scsi_for_each_sg(cmd, sg, tot_dsds, i) {
+ dma_addr_t sle_dma;
+ cont_a64_entry_t *cont_pkt;
+
+ /* Allocate additional continuation packets? */
+ if (avail_dsds == 0) {
+ /*
+ * Five DSDs are available in the Continuation
+ * Type 1 IOCB.
+ */
+ cont_pkt = qla2x00_prep_cont_type1_iocb(vha, req);
+ cur_dsd = cont_pkt->dsd;
+ avail_dsds = 5;
+ }
+
+ sle_dma = sg_dma_address(sg);
+ put_unaligned_le64(sle_dma, &cur_dsd->address);
+ cur_dsd->length = cpu_to_le32(sg_dma_len(sg));
+ cur_dsd++;
+ avail_dsds--;
+ }
+
+no_dsds:
+ /* Set NPORT-ID and LUN number*/
+ cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+ cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
+ cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
+ cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
+ cmd_pkt->vp_index = sp->vha->vp_idx;
+
+ cmd_pkt->entry_type = COMMAND_TYPE_6;
+
+ /* Set total data segment count. */
+ cmd_pkt->entry_count = (uint8_t)req_cnt;
+
+ int_to_scsilun(cmd->device->lun, &cmd_pkt->lun);
+ host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
+
+ /* build FCP_CMND IU */
+ int_to_scsilun(cmd->device->lun, &ctx->fcp_cmnd->lun);
+ ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len;
+
+ if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ ctx->fcp_cmnd->additional_cdb_len |= 1;
+ else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+ ctx->fcp_cmnd->additional_cdb_len |= 2;
+
+ /* Populate the FCP_PRIO. */
+ if (ha->flags.fcp_prio_enabled)
+ ctx->fcp_cmnd->task_attribute |=
+ sp->fcport->fcp_prio << 3;
+
+ memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
+
+ fcp_dl = (__be32 *)(ctx->fcp_cmnd->cdb + 16 +
+ additional_cdb_len);
+ *fcp_dl = htonl((uint32_t)scsi_bufflen(cmd));
+
+ cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len);
+ put_unaligned_le64(ctx->fcp_cmnd_dma, &cmd_pkt->fcp_cmnd_dseg_address);
+
+ sp->flags |= SRB_FCP_CMND_DMA_VALID;
+ cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
+ /* Set total data segment count. */
+ cmd_pkt->entry_count = (uint8_t)req_cnt;
+ cmd_pkt->entry_status = 0;
+
+ /* Build command packet. */
+ req->current_outstanding_cmd = handle;
+ req->outstanding_cmds[handle] = sp;
+ sp->handle = handle;
+ cmd->host_scribble = (unsigned char *)(unsigned long)handle;
+ req->cnt -= req_cnt;
+
+ /* Adjust ring index. */
+ wmb();
+ req->ring_index++;
+ if (req->ring_index == req->length) {
+ req->ring_index = 0;
+ req->ring_ptr = req->ring;
+ } else {
+ req->ring_ptr++;
+ }
+
+ sp->qpair->cmd_cnt++;
+ /* Set chip new ring index. */
+ wrt_reg_dword(req->req_q_in, req->ring_index);
+
+ spin_unlock_irqrestore(lock, flags);
+
+ return QLA_SUCCESS;
+
+queuing_error_fcp_cmnd:
+ dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, ctx->fcp_cmnd_dma);
+queuing_error:
+ if (tot_dsds)
+ scsi_dma_unmap(cmd);
+
+ if (sp->u.scmd.ct6_ctx) {
+ mempool_free(sp->u.scmd.ct6_ctx, ha->ctx_mempool);
+ sp->u.scmd.ct6_ctx = NULL;
+ }
+ spin_unlock_irqrestore(lock, flags);
+
+ return QLA_FUNCTION_FAILED;
+}
+
+/**********************************************
+ * edif update/delete sa_index list functions *
+ **********************************************/
+
+/* clear the edif_indx_list for this port */
+void qla_edif_list_del(fc_port_t *fcport)
+{
+ struct edif_list_entry *indx_lst;
+ struct edif_list_entry *tindx_lst;
+ struct list_head *indx_list = &fcport->edif.edif_indx_list;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);
+ list_for_each_entry_safe(indx_lst, tindx_lst, indx_list, next) {
+ list_del(&indx_lst->next);
+ kfree(indx_lst);
+ }
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+}
+
+/******************
+ * SADB functions *
+ ******************/
+
+/* allocate/retrieve an sa_index for a given spi */
+static uint16_t qla_edif_sadb_get_sa_index(fc_port_t *fcport,
+ struct qla_sa_update_frame *sa_frame)
+{
+ struct edif_sa_index_entry *entry;
+ struct list_head *sa_list;
+ uint16_t sa_index;
+ int dir = sa_frame->flags & SAU_FLG_TX;
+ int slot = 0;
+ int free_slot = -1;
+ scsi_qla_host_t *vha = fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags = 0;
+ uint16_t nport_handle = fcport->loop_id;
+
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: entry fc_port: %p, nport_handle: 0x%x\n",
+ __func__, fcport, nport_handle);
+
+ if (dir)
+ sa_list = &ha->sadb_tx_index_list;
+ else
+ sa_list = &ha->sadb_rx_index_list;
+
+ entry = qla_edif_sadb_find_sa_index_entry(nport_handle, sa_list);
+ if (!entry) {
+ if ((sa_frame->flags & (SAU_FLG_TX | SAU_FLG_INV)) == SAU_FLG_INV) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: rx delete request with no entry\n", __func__);
+ return RX_DELETE_NO_EDIF_SA_INDEX;
+ }
+
+ /* if there is no entry for this nport, add one */
+ entry = kzalloc((sizeof(struct edif_sa_index_entry)), GFP_ATOMIC);
+ if (!entry)
+ return INVALID_EDIF_SA_INDEX;
+
+ sa_index = qla_edif_get_sa_index_from_freepool(fcport, dir);
+ if (sa_index == INVALID_EDIF_SA_INDEX) {
+ kfree(entry);
+ return INVALID_EDIF_SA_INDEX;
+ }
+
+ INIT_LIST_HEAD(&entry->next);
+ entry->handle = nport_handle;
+ entry->fcport = fcport;
+ entry->sa_pair[0].spi = sa_frame->spi;
+ entry->sa_pair[0].sa_index = sa_index;
+ entry->sa_pair[1].spi = 0;
+ entry->sa_pair[1].sa_index = INVALID_EDIF_SA_INDEX;
+ spin_lock_irqsave(&ha->sadb_lock, flags);
+ list_add_tail(&entry->next, sa_list);
+ spin_unlock_irqrestore(&ha->sadb_lock, flags);
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: Created new sadb entry for nport_handle 0x%x, spi 0x%x, returning sa_index %d\n",
+ __func__, nport_handle, sa_frame->spi, sa_index);
+
+ return sa_index;
+ }
+
+ spin_lock_irqsave(&ha->sadb_lock, flags);
+
+ /* see if we already have an entry for this spi */
+ for (slot = 0; slot < 2; slot++) {
+ if (entry->sa_pair[slot].sa_index == INVALID_EDIF_SA_INDEX) {
+ free_slot = slot;
+ } else {
+ if (entry->sa_pair[slot].spi == sa_frame->spi) {
+ spin_unlock_irqrestore(&ha->sadb_lock, flags);
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: sadb slot %d entry for lid 0x%x, spi 0x%x found, sa_index %d\n",
+ __func__, slot, entry->handle, sa_frame->spi,
+ entry->sa_pair[slot].sa_index);
+ return entry->sa_pair[slot].sa_index;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&ha->sadb_lock, flags);
+
+ /* both slots are used */
+ if (free_slot == -1) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: WARNING: No free slots in sadb for nport_handle 0x%x, spi: 0x%x\n",
+ __func__, entry->handle, sa_frame->spi);
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: Slot 0 spi: 0x%x sa_index: %d, Slot 1 spi: 0x%x sa_index: %d\n",
+ __func__, entry->sa_pair[0].spi, entry->sa_pair[0].sa_index,
+ entry->sa_pair[1].spi, entry->sa_pair[1].sa_index);
+
+ return INVALID_EDIF_SA_INDEX;
+ }
+
+ /* there is at least one free slot, use it */
+ sa_index = qla_edif_get_sa_index_from_freepool(fcport, dir);
+ if (sa_index == INVALID_EDIF_SA_INDEX) {
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x3063,
+ "%s: empty freepool!!\n", __func__);
+ return INVALID_EDIF_SA_INDEX;
+ }
+
+ spin_lock_irqsave(&ha->sadb_lock, flags);
+ entry->sa_pair[free_slot].spi = sa_frame->spi;
+ entry->sa_pair[free_slot].sa_index = sa_index;
+ spin_unlock_irqrestore(&ha->sadb_lock, flags);
+ ql_dbg(ql_dbg_edif, fcport->vha, 0x3063,
+ "%s: sadb slot %d entry for nport_handle 0x%x, spi 0x%x added, returning sa_index %d\n",
+ __func__, free_slot, entry->handle, sa_frame->spi, sa_index);
+
+ return sa_index;
+}
+
+/* release any sadb entries -- only done at teardown */
+void qla_edif_sadb_release(struct qla_hw_data *ha)
+{
+ struct list_head *pos;
+ struct list_head *tmp;
+ struct edif_sa_index_entry *entry;
+
+ list_for_each_safe(pos, tmp, &ha->sadb_rx_index_list) {
+ entry = list_entry(pos, struct edif_sa_index_entry, next);
+ list_del(&entry->next);
+ kfree(entry);
+ }
+
+ list_for_each_safe(pos, tmp, &ha->sadb_tx_index_list) {
+ entry = list_entry(pos, struct edif_sa_index_entry, next);
+ list_del(&entry->next);
+ kfree(entry);
+ }
+}
+
+/**************************
+ * sadb freepool functions
+ **************************/
+
+/* build the rx and tx sa_index free pools -- only done at fcport init */
+int qla_edif_sadb_build_free_pool(struct qla_hw_data *ha)
+{
+ ha->edif_tx_sa_id_map =
+ kcalloc(BITS_TO_LONGS(EDIF_NUM_SA_INDEX), sizeof(long), GFP_KERNEL);
+
+ if (!ha->edif_tx_sa_id_map) {
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0009,
+ "Unable to allocate memory for sadb tx.\n");
+ return -ENOMEM;
+ }
+
+ ha->edif_rx_sa_id_map =
+ kcalloc(BITS_TO_LONGS(EDIF_NUM_SA_INDEX), sizeof(long), GFP_KERNEL);
+ if (!ha->edif_rx_sa_id_map) {
+ kfree(ha->edif_tx_sa_id_map);
+ ha->edif_tx_sa_id_map = NULL;
+ ql_log_pci(ql_log_fatal, ha->pdev, 0x0009,
+ "Unable to allocate memory for sadb rx.\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/* release the free pool - only done during fcport teardown */
+void qla_edif_sadb_release_free_pool(struct qla_hw_data *ha)
+{
+ kfree(ha->edif_tx_sa_id_map);
+ ha->edif_tx_sa_id_map = NULL;
+ kfree(ha->edif_rx_sa_id_map);
+ ha->edif_rx_sa_id_map = NULL;
+}
+
+static void __chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha,
+ fc_port_t *fcport, uint32_t handle, uint16_t sa_index)
+{
+ struct edif_list_entry *edif_entry;
+ struct edif_sa_ctl *sa_ctl;
+ uint16_t delete_sa_index = INVALID_EDIF_SA_INDEX;
+ unsigned long flags = 0;
+ uint16_t nport_handle = fcport->loop_id;
+ uint16_t cached_nport_handle;
+
+ spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);
+ edif_entry = qla_edif_list_find_sa_index(fcport, nport_handle);
+ if (!edif_entry) {
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+ return; /* no pending delete for this handle */
+ }
+
+ /*
+ * check for no pending delete for this index or iocb does not
+ * match rx sa_index
+ */
+ if (edif_entry->delete_sa_index == INVALID_EDIF_SA_INDEX ||
+ edif_entry->update_sa_index != sa_index) {
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+ return;
+ }
+
+ /*
+ * wait until we have seen at least EDIF_DELAY_COUNT transfers before
+ * queueing RX delete
+ */
+ if (edif_entry->count++ < EDIF_RX_DELETE_FILTER_COUNT) {
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+ return;
+ }
+
+ ql_dbg(ql_dbg_edif, vha, 0x5033,
+ "%s: invalidating delete_sa_index, update_sa_index: 0x%x sa_index: 0x%x, delete_sa_index: 0x%x\n",
+ __func__, edif_entry->update_sa_index, sa_index, edif_entry->delete_sa_index);
+
+ delete_sa_index = edif_entry->delete_sa_index;
+ edif_entry->delete_sa_index = INVALID_EDIF_SA_INDEX;
+ cached_nport_handle = edif_entry->handle;
+ spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);
+
+ /* sanity check on the nport handle */
+ if (nport_handle != cached_nport_handle) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: POST SA DELETE nport_handle mismatch: lid: 0x%x, edif_entry nph: 0x%x\n",
+ __func__, nport_handle, cached_nport_handle);
+ }
+
+ /* find the sa_ctl for the delete and schedule the delete */
+ sa_ctl = qla_edif_find_sa_ctl_by_index(fcport, delete_sa_index, 0);
+ if (sa_ctl) {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: POST SA DELETE sa_ctl: %p, index recvd %d\n",
+ __func__, sa_ctl, sa_index);
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "delete index %d, update index: %d, nport handle: 0x%x, handle: 0x%x\n",
+ delete_sa_index,
+ edif_entry->update_sa_index, nport_handle, handle);
+
+ sa_ctl->flags = EDIF_SA_CTL_FLG_DEL;
+ set_bit(EDIF_SA_CTL_REPL, &sa_ctl->state);
+ qla_post_sa_replace_work(fcport->vha, fcport,
+ nport_handle, sa_ctl);
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x3063,
+ "%s: POST SA DELETE sa_ctl not found for delete_sa_index: %d\n",
+ __func__, delete_sa_index);
+ }
+}
+
+void qla_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha,
+ srb_t *sp, struct sts_entry_24xx *sts24)
+{
+ fc_port_t *fcport = sp->fcport;
+ /* sa_index used by this iocb */
+ struct scsi_cmnd *cmd = GET_CMD_SP(sp);
+ uint32_t handle;
+
+ handle = (uint32_t)LSW(sts24->handle);
+
+ /* find out if this status iosb is for a scsi read */
+ if (cmd->sc_data_direction != DMA_FROM_DEVICE)
+ return;
+
+ return __chk_edif_rx_sa_delete_pending(vha, fcport, handle,
+ le16_to_cpu(sts24->edif_sa_index));
+}
+
+void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport,
+ struct ctio7_from_24xx *pkt)
+{
+ __chk_edif_rx_sa_delete_pending(vha, fcport,
+ pkt->handle, le16_to_cpu(pkt->edif_sa_index));
+}
+
+static void qla_parse_auth_els_ctl(struct srb *sp)
+{
+ struct qla_els_pt_arg *a = &sp->u.bsg_cmd.u.els_arg;
+ struct bsg_job *bsg_job = sp->u.bsg_cmd.bsg_job;
+ struct fc_bsg_request *request = bsg_job->request;
+ struct qla_bsg_auth_els_request *p =
+ (struct qla_bsg_auth_els_request *)bsg_job->request;
+
+ a->tx_len = a->tx_byte_count = sp->remap.req.len;
+ a->tx_addr = sp->remap.req.dma;
+ a->rx_len = a->rx_byte_count = sp->remap.rsp.len;
+ a->rx_addr = sp->remap.rsp.dma;
+
+ if (p->e.sub_cmd == SEND_ELS_REPLY) {
+ a->control_flags = p->e.extra_control_flags << 13;
+ a->rx_xchg_address = cpu_to_le32(p->e.extra_rx_xchg_address);
+ if (p->e.extra_control_flags == BSG_CTL_FLAG_LS_ACC)
+ a->els_opcode = ELS_LS_ACC;
+ else if (p->e.extra_control_flags == BSG_CTL_FLAG_LS_RJT)
+ a->els_opcode = ELS_LS_RJT;
+ }
+ a->did = sp->fcport->d_id;
+ a->els_opcode = request->rqst_data.h_els.command_code;
+ a->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+ a->vp_idx = sp->vha->vp_idx;
+}
+
+int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+{
+ struct fc_bsg_request *bsg_request = bsg_job->request;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ fc_port_t *fcport = NULL;
+ struct qla_hw_data *ha = vha->hw;
+ srb_t *sp;
+ int rval = (DID_ERROR << 16);
+ port_id_t d_id;
+ struct qla_bsg_auth_els_request *p =
+ (struct qla_bsg_auth_els_request *)bsg_job->request;
+
+ d_id.b.al_pa = bsg_request->rqst_data.h_els.port_id[2];
+ d_id.b.area = bsg_request->rqst_data.h_els.port_id[1];
+ d_id.b.domain = bsg_request->rqst_data.h_els.port_id[0];
+
+ /* find matching d_id in fcport list */
+ fcport = qla2x00_find_fcport_by_pid(vha, &d_id);
+ if (!fcport) {
+ ql_dbg(ql_dbg_edif, vha, 0x911a,
+ "%s fcport not find online portid=%06x.\n",
+ __func__, d_id.b24);
+ SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+ return -EIO;
+ }
+
+ if (qla_bsg_check(vha, bsg_job, fcport))
+ return 0;
+
+ if (fcport->loop_id == FC_NO_LOOP_ID) {
+ ql_dbg(ql_dbg_edif, vha, 0x910d,
+ "%s ELS code %x, no loop id.\n", __func__,
+ bsg_request->rqst_data.r_els.els_code);
+ SET_DID_STATUS(bsg_reply->result, DID_BAD_TARGET);
+ return -ENXIO;
+ }
+
+ if (!vha->flags.online) {
+ ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
+ SET_DID_STATUS(bsg_reply->result, DID_BAD_TARGET);
+ rval = -EIO;
+ goto done;
+ }
+
+ /* pass through is supported only for ISP 4Gb or higher */
+ if (!IS_FWI2_CAPABLE(ha)) {
+ ql_dbg(ql_dbg_user, vha, 0x7001,
+ "ELS passthru not supported for ISP23xx based adapters.\n");
+ SET_DID_STATUS(bsg_reply->result, DID_BAD_TARGET);
+ rval = -EPERM;
+ goto done;
+ }
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp) {
+ ql_dbg(ql_dbg_user, vha, 0x7004,
+ "Failed get sp pid=%06x\n", fcport->d_id.b24);
+ rval = -ENOMEM;
+ SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);
+ goto done;
+ }
+
+ sp->remap.req.len = bsg_job->request_payload.payload_len;
+ sp->remap.req.buf = dma_pool_alloc(ha->purex_dma_pool,
+ GFP_KERNEL, &sp->remap.req.dma);
+ if (!sp->remap.req.buf) {
+ ql_dbg(ql_dbg_user, vha, 0x7005,
+ "Failed allocate request dma len=%x\n",
+ bsg_job->request_payload.payload_len);
+ rval = -ENOMEM;
+ SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);
+ goto done_free_sp;
+ }
+
+ sp->remap.rsp.len = bsg_job->reply_payload.payload_len;
+ sp->remap.rsp.buf = dma_pool_alloc(ha->purex_dma_pool,
+ GFP_KERNEL, &sp->remap.rsp.dma);
+ if (!sp->remap.rsp.buf) {
+ ql_dbg(ql_dbg_user, vha, 0x7006,
+ "Failed allocate response dma len=%x\n",
+ bsg_job->reply_payload.payload_len);
+ rval = -ENOMEM;
+ SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);
+ goto done_free_remap_req;
+ }
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, sp->remap.req.buf,
+ sp->remap.req.len);
+ sp->remap.remapped = true;
+
+ sp->type = SRB_ELS_CMD_HST_NOLOGIN;
+ sp->name = "SPCN_BSG_HST_NOLOGIN";
+ sp->u.bsg_cmd.bsg_job = bsg_job;
+ qla_parse_auth_els_ctl(sp);
+
+ sp->free = qla2x00_bsg_sp_free;
+ sp->done = qla2x00_bsg_job_done;
+
+ rval = qla2x00_start_sp(sp);
+
+ ql_dbg(ql_dbg_edif, vha, 0x700a,
+ "%s %s %8phN xchg %x ctlflag %x hdl %x reqlen %xh bsg ptr %p\n",
+ __func__, sc_to_str(p->e.sub_cmd), fcport->port_name,
+ p->e.extra_rx_xchg_address, p->e.extra_control_flags,
+ sp->handle, sp->remap.req.len, bsg_job);
+
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x700e,
+ "qla2x00_start_sp failed = %d\n", rval);
+ SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);
+ rval = -EIO;
+ goto done_free_remap_rsp;
+ }
+ return rval;
+
+done_free_remap_rsp:
+ dma_pool_free(ha->purex_dma_pool, sp->remap.rsp.buf,
+ sp->remap.rsp.dma);
+done_free_remap_req:
+ dma_pool_free(ha->purex_dma_pool, sp->remap.req.buf,
+ sp->remap.req.dma);
+done_free_sp:
+ qla2x00_rel_sp(sp);
+
+done:
+ return rval;
+}
+
+void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess)
+{
+ if (sess->edif.app_sess_online && vha->e_dbell.db_flags & EDB_ACTIVE) {
+ ql_dbg(ql_dbg_disc, vha, 0xf09c,
+ "%s: sess %8phN send port_offline event\n",
+ __func__, sess->port_name);
+ sess->edif.app_sess_online = 0;
+ qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SESSION_SHUTDOWN,
+ sess->d_id.b24, 0, sess);
+ qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24);
+ }
+}
diff --git a/drivers/scsi/qla2xxx/qla_edif.h b/drivers/scsi/qla2xxx/qla_edif.h
new file mode 100644
index 000000000000..9e8f28d0caa1
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_edif.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Marvell Fibre Channel HBA Driver
+ * Copyright (c) 2021 Marvell
+ */
+#ifndef __QLA_EDIF_H
+#define __QLA_EDIF_H
+
+struct qla_scsi_host;
+#define EDIF_APP_ID 0x73730001
+
+#define EDIF_MAX_INDEX 2048
+struct edif_sa_ctl {
+ struct list_head next;
+ uint16_t del_index;
+ uint16_t index;
+ uint16_t slot;
+ uint16_t flags;
+#define EDIF_SA_CTL_FLG_REPL BIT_0
+#define EDIF_SA_CTL_FLG_DEL BIT_1
+#define EDIF_SA_CTL_FLG_CLEANUP_DEL BIT_4
+ // Invalidate Index bit and mirrors QLA_SA_UPDATE_FLAGS_DELETE
+ unsigned long state;
+#define EDIF_SA_CTL_USED 1 /* Active Sa update */
+#define EDIF_SA_CTL_PEND 2 /* Waiting for slot */
+#define EDIF_SA_CTL_REPL 3 /* Active Replace and Delete */
+#define EDIF_SA_CTL_DEL 4 /* Delete Pending */
+ struct fc_port *fcport;
+ struct bsg_job *bsg_job;
+ struct qla_sa_update_frame sa_frame;
+};
+
+enum enode_flags_t {
+ ENODE_ACTIVE = 0x1,
+};
+
+struct pur_core {
+ enum enode_flags_t enode_flags;
+ spinlock_t pur_lock;
+ struct list_head head;
+};
+
+enum db_flags_t {
+ EDB_ACTIVE = 0x1,
+};
+
+struct edif_dbell {
+ enum db_flags_t db_flags;
+ spinlock_t db_lock;
+ struct list_head head;
+ struct completion dbell;
+};
+
+#define SA_UPDATE_IOCB_TYPE 0x71 /* Security Association Update IOCB entry */
+struct sa_update_28xx {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t sys_define; /* System Defined. */
+ uint8_t entry_status; /* Entry Status. */
+
+ uint32_t handle; /* IOCB System handle. */
+
+ union {
+ __le16 nport_handle; /* in: N_PORT handle. */
+ __le16 comp_sts; /* out: completion status */
+#define CS_PORT_EDIF_UNAVAIL 0x28
+#define CS_PORT_EDIF_LOGOUT 0x29
+#define CS_PORT_EDIF_SUPP_NOT_RDY 0x64
+#define CS_PORT_EDIF_INV_REQ 0x66
+ } u;
+ uint8_t vp_index;
+ uint8_t reserved_1;
+ uint8_t port_id[3];
+ uint8_t flags;
+#define SA_FLAG_INVALIDATE BIT_0
+#define SA_FLAG_TX BIT_1 // 1=tx, 0=rx
+
+ uint8_t sa_key[32]; /* 256 bit key */
+ __le32 salt;
+ __le32 spi;
+ uint8_t sa_control;
+#define SA_CNTL_ENC_FCSP (1 << 3)
+#define SA_CNTL_ENC_OPD (2 << 3)
+#define SA_CNTL_ENC_MSK (3 << 3) // mask bits 4,3
+#define SA_CNTL_AES_GMAC (1 << 2)
+#define SA_CNTL_KEY256 (2 << 0)
+#define SA_CNTL_KEY128 0
+
+ uint8_t reserved_2;
+ __le16 sa_index; // reserve: bit 11-15
+ __le16 old_sa_info;
+ __le16 new_sa_info;
+};
+
+#define NUM_ENTRIES 256
+#define MAX_PAYLOAD 1024
+#define PUR_GET 1
+
+struct dinfo {
+ int nodecnt;
+ int lstate;
+};
+
+struct pur_ninfo {
+ unsigned int pur_pend:1;
+ port_id_t pur_sid;
+ port_id_t pur_did;
+ uint8_t vp_idx;
+ short pur_bytes_rcvd;
+ unsigned short pur_nphdl;
+ unsigned int pur_rx_xchg_address;
+};
+
+struct purexevent {
+ struct pur_ninfo pur_info;
+ unsigned char *msgp;
+ u32 msgp_len;
+};
+
+#define N_UNDEF 0
+#define N_PUREX 1
+struct enode {
+ struct list_head list;
+ struct dinfo dinfo;
+ uint32_t ntype;
+ union {
+ struct purexevent purexinfo;
+ } u;
+};
+
+#define EDIF_SESSION_DOWN(_s) \
+ (qla_ini_mode_enabled(_s->vha) && (_s->disc_state == DSC_DELETE_PEND || \
+ _s->disc_state == DSC_DELETED || \
+ !_s->edif.app_sess_online))
+
+#endif /* __QLA_EDIF_H */
diff --git a/drivers/scsi/qla2xxx/qla_edif_bsg.h b/drivers/scsi/qla2xxx/qla_edif_bsg.h
new file mode 100644
index 000000000000..58b718d35d19
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_edif_bsg.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Marvell Fibre Channel HBA Driver
+ * Copyright (C) 2018- Marvell
+ *
+ */
+#ifndef __QLA_EDIF_BSG_H
+#define __QLA_EDIF_BSG_H
+
+/* BSG Vendor specific commands */
+#define ELS_MAX_PAYLOAD 1024
+#ifndef WWN_SIZE
+#define WWN_SIZE 8
+#endif
+#define VND_CMD_APP_RESERVED_SIZE 32
+
+enum auth_els_sub_cmd {
+ SEND_ELS = 0,
+ SEND_ELS_REPLY,
+ PULL_ELS,
+};
+
+struct extra_auth_els {
+ enum auth_els_sub_cmd sub_cmd;
+ uint32_t extra_rx_xchg_address;
+ uint8_t extra_control_flags;
+#define BSG_CTL_FLAG_INIT 0
+#define BSG_CTL_FLAG_LS_ACC 1
+#define BSG_CTL_FLAG_LS_RJT 2
+#define BSG_CTL_FLAG_TRM 3
+ uint8_t extra_rsvd[3];
+} __packed;
+
+struct qla_bsg_auth_els_request {
+ struct fc_bsg_request r;
+ struct extra_auth_els e;
+};
+
+struct qla_bsg_auth_els_reply {
+ struct fc_bsg_reply r;
+ uint32_t rx_xchg_address;
+};
+
+struct app_id {
+ int app_vid;
+ uint8_t app_key[32];
+} __packed;
+
+struct app_start_reply {
+ uint32_t host_support_edif;
+ uint32_t edif_enode_active;
+ uint32_t edif_edb_active;
+ uint32_t reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+struct app_start {
+ struct app_id app_info;
+ uint32_t prli_to;
+ uint32_t key_shred;
+ uint8_t app_start_flags;
+ uint8_t reserved[VND_CMD_APP_RESERVED_SIZE - 1];
+} __packed;
+
+struct app_stop {
+ struct app_id app_info;
+ char buf[16];
+} __packed;
+
+struct app_plogi_reply {
+ uint32_t prli_status;
+ uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+#define RECFG_TIME 1
+#define RECFG_BYTES 2
+
+struct app_rekey_cfg {
+ struct app_id app_info;
+ uint8_t rekey_mode;
+ port_id_t d_id;
+ uint8_t force;
+ union {
+ int64_t bytes;
+ int64_t time;
+ } rky_units;
+
+ uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+struct app_pinfo_req {
+ struct app_id app_info;
+ uint8_t num_ports;
+ port_id_t remote_pid;
+ uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+struct app_pinfo {
+ port_id_t remote_pid;
+ uint8_t remote_wwpn[WWN_SIZE];
+ uint8_t remote_type;
+#define VND_CMD_RTYPE_UNKNOWN 0
+#define VND_CMD_RTYPE_TARGET 1
+#define VND_CMD_RTYPE_INITIATOR 2
+ uint8_t remote_state;
+ uint8_t auth_state;
+ uint8_t rekey_mode;
+ int64_t rekey_count;
+ int64_t rekey_config_value;
+ int64_t rekey_consumed_value;
+
+ uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+/* AUTH States */
+#define VND_CMD_AUTH_STATE_UNDEF 0
+#define VND_CMD_AUTH_STATE_SESSION_SHUTDOWN 1
+#define VND_CMD_AUTH_STATE_NEEDED 2
+#define VND_CMD_AUTH_STATE_ELS_RCVD 3
+#define VND_CMD_AUTH_STATE_SAUPDATE_COMPL 4
+
+struct app_pinfo_reply {
+ uint8_t port_count;
+ uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
+ struct app_pinfo ports[0];
+} __packed;
+
+struct app_sinfo_req {
+ struct app_id app_info;
+ uint8_t num_ports;
+ uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+struct app_sinfo {
+ uint8_t remote_wwpn[WWN_SIZE];
+ int64_t rekey_count;
+ uint8_t rekey_mode;
+ int64_t tx_bytes;
+ int64_t rx_bytes;
+} __packed;
+
+struct app_stats_reply {
+ uint8_t elem_count;
+ struct app_sinfo elem[0];
+} __packed;
+
+struct qla_sa_update_frame {
+ struct app_id app_info;
+ uint16_t flags;
+#define SAU_FLG_INV 0x01 /* delete key */
+#define SAU_FLG_TX 0x02 /* 1=tx, 0 = rx */
+#define SAU_FLG_FORCE_DELETE 0x08
+#define SAU_FLG_GMAC_MODE 0x20 /*
+ * GMAC mode is cleartext for the IO
+ * (i.e. NULL encryption)
+ */
+#define SAU_FLG_KEY128 0x40
+#define SAU_FLG_KEY256 0x80
+ uint16_t fast_sa_index:10,
+ reserved:6;
+ uint32_t salt;
+ uint32_t spi;
+ uint8_t sa_key[32];
+ uint8_t node_name[WWN_SIZE];
+ uint8_t port_name[WWN_SIZE];
+ port_id_t port_id;
+} __packed;
+
+// used for edif mgmt bsg interface
+#define QL_VND_SC_UNDEF 0
+#define QL_VND_SC_SA_UPDATE 1
+#define QL_VND_SC_APP_START 2
+#define QL_VND_SC_APP_STOP 3
+#define QL_VND_SC_AUTH_OK 4
+#define QL_VND_SC_AUTH_FAIL 5
+#define QL_VND_SC_REKEY_CONFIG 6
+#define QL_VND_SC_GET_FCINFO 7
+#define QL_VND_SC_GET_STATS 8
+
+/* Application interface data structure for rtn data */
+#define EXT_DEF_EVENT_DATA_SIZE 64
+struct edif_app_dbell {
+ uint32_t event_code;
+ uint32_t event_data_size;
+ union {
+ port_id_t port_id;
+ uint8_t event_data[EXT_DEF_EVENT_DATA_SIZE];
+ };
+} __packed;
+
+struct edif_sa_update_aen {
+ port_id_t port_id;
+ uint32_t key_type; /* Tx (1) or RX (2) */
+ uint32_t status; /* 0 succes, 1 failed, 2 timeout , 3 error */
+ uint8_t reserved[16];
+} __packed;
+
+#define QL_VND_SA_STAT_SUCCESS 0
+#define QL_VND_SA_STAT_FAILED 1
+#define QL_VND_SA_STAT_TIMEOUT 2
+#define QL_VND_SA_STAT_ERROR 3
+
+#define QL_VND_RX_SA_KEY 1
+#define QL_VND_TX_SA_KEY 2
+
+/* App defines for plogi auth'd ok and plogi auth bad requests */
+struct auth_complete_cmd {
+ struct app_id app_info;
+#define PL_TYPE_WWPN 1
+#define PL_TYPE_DID 2
+ uint32_t type;
+ union {
+ uint8_t wwpn[WWN_SIZE];
+ port_id_t d_id;
+ } u;
+ uint32_t reserved[VND_CMD_APP_RESERVED_SIZE];
+} __packed;
+
+#define RX_DELAY_DELETE_TIMEOUT 20
+
+#endif /* QLA_EDIF_BSG_H */
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 49df418030e4..073d06e88c58 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -82,10 +82,11 @@ struct port_database_24xx {
uint8_t port_name[WWN_SIZE];
uint8_t node_name[WWN_SIZE];
- uint8_t reserved_3[4];
+ uint8_t reserved_3[2];
+ uint16_t nvme_first_burst_size;
uint16_t prli_nvme_svc_param_word_0; /* Bits 15-0 of word 0 */
uint16_t prli_nvme_svc_param_word_3; /* Bits 15-0 of word 3 */
- uint16_t nvme_first_burst_size;
+ uint8_t secure_login;
uint8_t reserved_4[14];
};
@@ -489,6 +490,9 @@ struct cmd_type_6 {
struct scsi_lun lun; /* FCP LUN (BE). */
__le16 control_flags; /* Control flags. */
+#define CF_NEW_SA BIT_12
+#define CF_EN_EDIF BIT_9
+#define CF_ADDITIONAL_PARAM_BLK BIT_8
#define CF_DIF_SEG_DESCR_ENABLE BIT_3
#define CF_DATA_SEG_DESCR_ENABLE BIT_2
#define CF_READ_DATA BIT_1
@@ -611,6 +615,7 @@ struct sts_entry_24xx {
union {
__le16 reserved_1;
__le16 nvme_rsp_pyld_len;
+ __le16 edif_sa_index; /* edif sa_index used for initiator read data */
};
__le16 state_flags; /* State flags. */
@@ -805,6 +810,7 @@ struct els_entry_24xx {
#define EPD_RX_XCHG (3 << 13)
#define ECF_CLR_PASSTHRU_PEND BIT_12
#define ECF_INCL_FRAME_HDR BIT_11
+#define ECF_SEC_LOGIN BIT_3
union {
struct {
@@ -896,6 +902,7 @@ struct logio_entry_24xx {
#define LCF_FCP2_OVERRIDE BIT_9 /* Set/Reset word 3 of PRLI. */
#define LCF_CLASS_2 BIT_8 /* Enable class 2 during PLOGI. */
#define LCF_FREE_NPORT BIT_7 /* Release NPORT handle after LOGO. */
+#define LCF_COMMON_FEAT BIT_7 /* PLOGI - Set Common Features Field */
#define LCF_EXPL_LOGO BIT_6 /* Perform an explicit LOGO. */
#define LCF_NVME_PRLI BIT_6 /* Perform NVME FC4 PRLI */
#define LCF_SKIP_PRLI BIT_5 /* Skip PRLI after PLOGI. */
@@ -920,6 +927,8 @@ struct logio_entry_24xx {
uint8_t rsp_size; /* Response size in 32bit words. */
__le32 io_parameter[11]; /* General I/O parameters. */
+#define LIO_COMM_FEAT_FCSP BIT_21
+#define LIO_COMM_FEAT_CIO BIT_31
#define LSC_SCODE_NOLINK 0x01
#define LSC_SCODE_NOIOCB 0x02
#define LSC_SCODE_NOXCB 0x03
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 2f867da822ae..1c3f055d41b8 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -12,6 +12,7 @@
* Global Function Prototypes in qla_init.c source file.
*/
extern int qla2x00_initialize_adapter(scsi_qla_host_t *);
+extern int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport);
extern int qla2100_pci_config(struct scsi_qla_host *);
extern int qla2300_pci_config(struct scsi_qla_host *);
@@ -130,6 +131,18 @@ void qla24xx_free_purex_item(struct purex_item *item);
extern bool qla24xx_risc_firmware_invalid(uint32_t *);
void qla_init_iocb_limit(scsi_qla_host_t *);
+void qla_edif_list_del(fc_port_t *fcport);
+void qla_edif_sadb_release(struct qla_hw_data *ha);
+int qla_edif_sadb_build_free_pool(struct qla_hw_data *ha);
+void qla_edif_sadb_release_free_pool(struct qla_hw_data *ha);
+void qla_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha,
+ srb_t *sp, struct sts_entry_24xx *sts24);
+void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport,
+ struct ctio7_from_24xx *ctio);
+void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport);
+int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsgjob);
+void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess);
+const char *sc_to_str(uint16_t cmd);
/*
* Global Data in qla_os.c source file.
@@ -175,6 +188,7 @@ extern int ql2xenablemsix;
extern int qla2xuseresexchforels;
extern int ql2xdifbundlinginternalbuffers;
extern int ql2xfulldump_on_mpifail;
+extern int ql2xsecenable;
extern int ql2xenforce_iocb_limit;
extern int ql2xabts_wait_nvme;
@@ -236,6 +250,8 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
struct purex_item *pkt);
void qla_pci_set_eeh_busy(struct scsi_qla_host *);
void qla_schedule_eeh_work(struct scsi_qla_host *);
+struct edif_sa_ctl *qla_edif_find_sa_ctl_by_index(fc_port_t *fcport,
+ int index, int dir);
/*
* Global Functions in qla_mid.c source file.
@@ -280,7 +296,10 @@ extern int qla2x00_vp_abort_isp(scsi_qla_host_t *);
/*
* Global Function Prototypes in qla_iocb.c source file.
*/
-
+void qla_els_pt_iocb(struct scsi_qla_host *vha,
+ struct els_entry_24xx *pkt, struct qla_els_pt_arg *a);
+cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha,
+ struct req_que *que);
extern uint16_t qla2x00_calc_iocbs_32(uint16_t);
extern uint16_t qla2x00_calc_iocbs_64(uint16_t);
extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t);
@@ -310,6 +329,8 @@ extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *,
struct dsd64 *, uint16_t, struct qla_tgt_cmd *);
extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
+extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha,
+ struct qla_work_evt *e);
/*
* Global Function Prototypes in qla_mbx.c source file.
@@ -578,6 +599,7 @@ qla2xxx_msix_rsp_q_hs(int irq, void *dev_id);
fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
+void __qla_consume_iocb(struct scsi_qla_host *vha, void **pkt, struct rsp_que **rsp);
/*
* Global Function Prototypes in qla_sup.c source file.
@@ -640,6 +662,8 @@ extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *);
+int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha, void **pkt,
+ struct rsp_que **rsp, u8 *buf, u32 buf_len);
/*
* Global Function Prototypes in qla_dbg.c source file.
@@ -879,6 +903,9 @@ extern int qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *,
dma_addr_t, size_t, uint32_t);
extern int qla2x00_get_idma_speed(scsi_qla_host_t *, uint16_t,
uint16_t *, uint16_t *);
+extern int qla24xx_sadb_update(struct bsg_job *bsg_job);
+extern int qla_post_sa_replace_work(struct scsi_qla_host *vha,
+ fc_port_t *fcport, uint16_t nport_handle, struct edif_sa_ctl *sa_ctl);
/* 83xx related functions */
void qla83xx_fw_dump(scsi_qla_host_t *vha);
@@ -923,6 +950,7 @@ extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *);
extern void qlt_handle_abts_recv(struct scsi_qla_host *, struct rsp_que *,
response_t *);
+struct scsi_qla_host *qla_find_host_by_d_id(struct scsi_qla_host *vha, be_id_t d_id);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
struct imm_ntfy_from_isp *, int);
void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
@@ -935,7 +963,7 @@ extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
void qla24xx_delete_sess_fn(struct work_struct *);
void qlt_unknown_atio_work_fn(struct work_struct *);
void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
-void qlt_remove_target_resources(struct qla_hw_data *);
+void qla_remove_hostmap(struct qla_hw_data *ha);
void qlt_clr_qp_table(struct scsi_qla_host *vha);
void qlt_set_mode(struct scsi_qla_host *);
int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode);
@@ -950,6 +978,25 @@ extern void qla_nvme_abort_process_comp_status
/* nvme.c */
void qla_nvme_unregister_remote_port(struct fc_port *fcport);
+
+/* qla_edif.c */
+fc_port_t *qla2x00_find_fcport_by_pid(scsi_qla_host_t *vha, port_id_t *id);
+void qla_edb_eventcreate(scsi_qla_host_t *vha, uint32_t dbtype, uint32_t data, uint32_t data2,
+ fc_port_t *fcport);
+void qla_edb_stop(scsi_qla_host_t *vha);
+ssize_t edif_doorbell_show(struct device *dev, struct device_attribute *attr, char *buf);
+int32_t qla_edif_app_mgmt(struct bsg_job *bsg_job);
+void qla_enode_init(scsi_qla_host_t *vha);
+void qla_enode_stop(scsi_qla_host_t *vha);
+void qla_edif_flush_sa_ctl_lists(fc_port_t *fcport);
+void qla_edb_init(scsi_qla_host_t *vha);
+void qla_edif_timer(scsi_qla_host_t *vha);
+int qla28xx_start_scsi_edif(srb_t *sp);
+void qla24xx_sa_update_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb);
+void qla24xx_sa_replace_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb);
+void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp);
+void qla28xx_sa_update_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+ struct sa_update_28xx *pkt);
void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
#define QLA2XX_HW_ERROR BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 5b6e04a91a18..ebc8fdb0b43d 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -632,7 +632,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
ct_req->req.rft_id.port_id = port_id_to_be_id(vha->d_id);
ct_req->req.rft_id.fc4_types[2] = 0x01; /* FCP-3 */
- if (vha->flags.nvme_enabled)
+ if (vha->flags.nvme_enabled && qla_ini_mode_enabled(vha))
ct_req->req.rft_id.fc4_types[6] = 1; /* NVMe type 28h */
sp->u.iocb_cmd.u.ctarg.req_size = RFT_ID_REQ_SIZE;
@@ -1730,8 +1730,6 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
size += alen;
ql_dbg(ql_dbg_disc, vha, 0x20a8,
"FIRMWARE VERSION = %s.\n", eiter->a.fw_version);
- if (callopt == CALLOPT_FDMI1)
- goto done;
/* OS Name and Version */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);
@@ -1754,6 +1752,8 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
size += alen;
ql_dbg(ql_dbg_disc, vha, 0x20a9,
"OS VERSION = %s.\n", eiter->a.os_version);
+ if (callopt == CALLOPT_FDMI1)
+ goto done;
/* MAX CT Payload Length */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);
@@ -2826,6 +2826,10 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
if (fcport->disc_state == DSC_DELETE_PEND)
return;
+ /* We will figure-out what happen after AUTH completes */
+ if (fcport->disc_state == DSC_LOGIN_AUTH_PEND)
+ return;
+
if (ea->sp->gen2 != fcport->login_gen) {
/* target side must have changed it. */
ql_dbg(ql_dbg_disc, vha, 0x20d3,
@@ -3498,7 +3502,16 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
continue;
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->last_rscn_gen = fcport->rscn_gen;
+ fcport->fc4_type = rp->fc4type;
found = true;
+
+ if (fcport->scan_needed) {
+ if (NVME_PRIORITY(vha->hw, fcport))
+ fcport->do_prli_nvme = 1;
+ else
+ fcport->do_prli_nvme = 0;
+ }
+
/*
* If device was not a fabric device before.
*/
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f8f471157109..1e4e3e83b5c7 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -34,7 +34,6 @@ static int qla2x00_restart_isp(scsi_qla_host_t *);
static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
static int qla84xx_init_chip(scsi_qla_host_t *);
static int qla25xx_init_queues(struct qla_hw_data *);
-static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *);
static void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha,
struct event_arg *ea);
static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
@@ -158,7 +157,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
GFP_ATOMIC);
if (!sp)
- return rval;
+ return QLA_MEMORY_ALLOC_FAILED;
abt_iocb = &sp->u.iocb_cmd;
sp->type = SRB_ABT_CMD;
@@ -191,7 +190,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
if (wait) {
wait_for_completion(&abt_iocb->u.abt.comp);
rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
- QLA_SUCCESS : QLA_FUNCTION_FAILED;
+ QLA_SUCCESS : QLA_ERR_FROM_FW;
sp->free(sp);
}
@@ -293,22 +292,6 @@ static void qla2x00_async_login_sp_done(srb_t *sp, int res)
sp->free(sp);
}
-static inline bool
-fcport_is_smaller(fc_port_t *fcport)
-{
- if (wwn_to_u64(fcport->port_name) <
- wwn_to_u64(fcport->vha->port_name))
- return true;
- else
- return false;
-}
-
-static inline bool
-fcport_is_bigger(fc_port_t *fcport)
-{
- return !fcport_is_smaller(fcport);
-}
-
int
qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
uint16_t *data)
@@ -343,19 +326,28 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
sp->done = qla2x00_async_login_sp_done;
- if (N2N_TOPO(fcport->vha->hw) && fcport_is_bigger(fcport))
+ if (N2N_TOPO(fcport->vha->hw) && fcport_is_bigger(fcport)) {
lio->u.logio.flags |= SRB_LOGIN_PRLI_ONLY;
- else
- lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
+ } else {
+ if (vha->hw->flags.edif_enabled &&
+ vha->e_dbell.db_flags & EDB_ACTIVE) {
+ lio->u.logio.flags |=
+ (SRB_LOGIN_FCSP | SRB_LOGIN_SKIP_PRLI);
+ ql_dbg(ql_dbg_disc, vha, 0x2072,
+ "Async-login: w/ FCSP %8phC hdl=%x, loopid=%x portid=%06x\n",
+ fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24);
+ } else {
+ lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
+ }
+ }
if (NVME_TARGET(vha->hw, fcport))
lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
- ql_log(ql_log_warn, vha, 0x2072,
- "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x retries=%d.\n",
+ ql_dbg(ql_dbg_disc, vha, 0x2072,
+ "Async-login - %8phC hdl=%x, loopid=%x portid=%06x retries=%d.\n",
fcport->port_name, sp->handle, fcport->loop_id,
- fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
- fcport->login_retry);
+ fcport->d_id.b24, fcport->login_retry);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
@@ -378,7 +370,7 @@ static void qla2x00_async_logout_sp_done(srb_t *sp, int res)
{
sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
sp->fcport->login_gen++;
- qlt_logo_completion_handler(sp->fcport, res);
+ qlt_logo_completion_handler(sp->fcport, sp->u.iocb_cmd.u.logio.data[0]);
sp->free(sp);
}
@@ -404,10 +396,10 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
sp->done = qla2x00_async_logout_sp_done;
ql_dbg(ql_dbg_disc, vha, 0x2070,
- "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC.\n",
+ "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC explicit %d.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
- fcport->port_name);
+ fcport->port_name, fcport->explicit_logout);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
@@ -692,11 +684,11 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
fcport = ea->fcport;
ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %8phC DS %d LS rc %d %d login %d|%d rscn %d|%d lid %d\n",
+ "%s %8phC DS %d LS rc %d %d login %d|%d rscn %d|%d lid %d edif %d\n",
__func__, fcport->port_name, fcport->disc_state,
fcport->fw_login_state, ea->rc,
fcport->login_gen, fcport->last_login_gen,
- fcport->rscn_gen, fcport->last_rscn_gen, vha->loop_id);
+ fcport->rscn_gen, fcport->last_rscn_gen, vha->loop_id, fcport->edif.enable);
if (fcport->disc_state == DSC_DELETE_PEND)
return;
@@ -810,7 +802,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
default:
switch (current_login_state) {
case DSC_LS_PRLI_COMP:
- ql_dbg(ql_dbg_disc + ql_dbg_verbose,
+ ql_dbg(ql_dbg_disc,
vha, 0x20e4, "%s %d %8phC post gpdb\n",
__func__, __LINE__, fcport->port_name);
@@ -822,6 +814,13 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
qla2x00_post_async_adisc_work(vha, fcport,
data);
break;
+ case DSC_LS_PLOGI_COMP:
+ if (vha->hw->flags.edif_enabled) {
+ /* check to see if App support Secure */
+ qla24xx_post_gpdb_work(vha, fcport, 0);
+ break;
+ }
+ fallthrough;
case DSC_LS_PORT_UNAVAIL:
default:
if (fcport->loop_id == FC_NO_LOOP_ID) {
@@ -849,6 +848,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
*/
qla2x00_set_fcport_disc_state(fcport,
DSC_DELETED);
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
break;
case DSC_LS_PRLI_COMP:
if ((e->prli_svc_param_word_3[0] & BIT_4) == 0)
@@ -861,6 +861,12 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
data);
break;
case DSC_LS_PLOGI_COMP:
+ if (vha->hw->flags.edif_enabled &&
+ vha->e_dbell.db_flags & EDB_ACTIVE) {
+ /* check to see if App support secure or not */
+ qla24xx_post_gpdb_work(vha, fcport, 0);
+ break;
+ }
if (fcport_is_bigger(fcport)) {
/* local adapter is smaller */
if (fcport->loop_id != FC_NO_LOOP_ID)
@@ -1191,7 +1197,7 @@ done:
sp->free(sp);
}
-static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
{
struct qla_work_evt *e;
@@ -1214,7 +1220,7 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res)
struct event_arg ea;
ql_dbg(ql_dbg_disc, vha, 0x2129,
- "%s %8phC res %d \n", __func__,
+ "%s %8phC res %x\n", __func__,
sp->fcport->port_name, res);
sp->fcport->flags &= ~FCF_ASYNC_SENT;
@@ -1227,6 +1233,8 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res)
ea.iop[0] = lio->u.logio.iop[0];
ea.iop[1] = lio->u.logio.iop[1];
ea.sp = sp;
+ if (res == QLA_OS_TIMER_EXPIRED)
+ ea.data[0] = QLA_OS_TIMER_EXPIRED;
qla24xx_handle_prli_done_event(vha, &ea);
}
@@ -1418,6 +1426,57 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
}
+static int qla_chk_secure_login(scsi_qla_host_t *vha, fc_port_t *fcport,
+ struct port_database_24xx *pd)
+{
+ int rc = 0;
+
+ if (pd->secure_login) {
+ ql_dbg(ql_dbg_disc, vha, 0x104d,
+ "Secure Login established on %8phC\n",
+ fcport->port_name);
+ fcport->flags |= FCF_FCSP_DEVICE;
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0x104d,
+ "non-Secure Login %8phC",
+ fcport->port_name);
+ fcport->flags &= ~FCF_FCSP_DEVICE;
+ }
+ if (vha->hw->flags.edif_enabled) {
+ if (fcport->flags & FCF_FCSP_DEVICE) {
+ qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_AUTH_PEND);
+ /* Start edif prli timer & ring doorbell for app */
+ fcport->edif.rx_sa_set = 0;
+ fcport->edif.tx_sa_set = 0;
+ fcport->edif.rx_sa_pending = 0;
+ fcport->edif.tx_sa_pending = 0;
+
+ qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE,
+ fcport->d_id.b24);
+
+ if (vha->e_dbell.db_flags == EDB_ACTIVE) {
+ ql_dbg(ql_dbg_disc, vha, 0x20ef,
+ "%s %d %8phC EDIF: post DB_AUTH: AUTH needed\n",
+ __func__, __LINE__, fcport->port_name);
+ fcport->edif.app_started = 1;
+ fcport->edif.app_sess_online = 1;
+
+ qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_NEEDED,
+ fcport->d_id.b24, 0, fcport);
+ }
+
+ rc = 1;
+ } else if (qla_ini_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
+ ql_dbg(ql_dbg_disc, vha, 0x2117,
+ "%s %d %8phC post prli\n",
+ __func__, __LINE__, fcport->port_name);
+ qla24xx_post_prli_work(vha, fcport);
+ rc = 1;
+ }
+ }
+ return rc;
+}
+
static
void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
{
@@ -1431,12 +1490,15 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
fcport->flags &= ~FCF_ASYNC_SENT;
ql_dbg(ql_dbg_disc, vha, 0x20d2,
- "%s %8phC DS %d LS %d fc4_type %x rc %d\n", __func__,
+ "%s %8phC DS %d LS %x fc4_type %x rc %x\n", __func__,
fcport->port_name, fcport->disc_state, pd->current_login_state,
fcport->fc4_type, ea->rc);
- if (fcport->disc_state == DSC_DELETE_PEND)
+ if (fcport->disc_state == DSC_DELETE_PEND) {
+ ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC\n",
+ __func__, __LINE__, fcport->port_name);
return;
+ }
if (NVME_TARGET(vha->hw, fcport))
ls = pd->current_login_state >> 4;
@@ -1453,6 +1515,8 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
} else if (ea->sp->gen1 != fcport->rscn_gen) {
qla_rscn_replay(fcport);
qlt_schedule_sess_for_deletion(fcport);
+ ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC, ls %x\n",
+ __func__, __LINE__, fcport->port_name, ls);
return;
}
@@ -1460,8 +1524,14 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
case PDS_PRLI_COMPLETE:
__qla24xx_parse_gpdb(vha, fcport, pd);
break;
- case PDS_PLOGI_PENDING:
case PDS_PLOGI_COMPLETE:
+ if (qla_chk_secure_login(vha, fcport, pd)) {
+ ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC, ls %x\n",
+ __func__, __LINE__, fcport->port_name, ls);
+ return;
+ }
+ fallthrough;
+ case PDS_PLOGI_PENDING:
case PDS_PRLI_PENDING:
case PDS_PRLI2_PENDING:
/* Set discovery state back to GNL to Relogin attempt */
@@ -1470,6 +1540,8 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
qla2x00_set_fcport_disc_state(fcport, DSC_GNL);
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
}
+ ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC, ls %x\n",
+ __func__, __LINE__, fcport->port_name, ls);
return;
case PDS_LOGO_PENDING:
case PDS_PORT_UNAVAILABLE:
@@ -1538,11 +1610,12 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
u16 sec;
ql_dbg(ql_dbg_disc, vha, 0x20d8,
- "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d lid %d scan %d\n",
+ "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d lid %d scan %d fc4type %x\n",
__func__, fcport->port_name, fcport->disc_state,
fcport->fw_login_state, fcport->login_pause, fcport->flags,
fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
- fcport->login_gen, fcport->loop_id, fcport->scan_state);
+ fcport->login_gen, fcport->loop_id, fcport->scan_state,
+ fcport->fc4_type);
if (fcport->scan_state != QLA_FCPORT_FOUND)
return 0;
@@ -1715,6 +1788,12 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
if (fcport) {
+ if (fcport->flags & FCF_FCP2_DEVICE) {
+ ql_dbg(ql_dbg_disc, vha, 0x2115,
+ "Delaying session delete for FCP2 portid=%06x %8phC ",
+ fcport->d_id.b24, fcport->port_name);
+ return;
+ }
fcport->scan_needed = 1;
fcport->rscn_gen++;
}
@@ -1758,6 +1837,13 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
void qla_handle_els_plogi_done(scsi_qla_host_t *vha,
struct event_arg *ea)
{
+ if (N2N_TOPO(vha->hw) && fcport_is_smaller(ea->fcport) &&
+ vha->hw->flags.edif_enabled) {
+ /* check to see if App support Secure */
+ qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+ return;
+ }
+
/* for pure Target Mode, PRLI will not be initiated */
if (vha->host->active_mode == MODE_TARGET)
return;
@@ -1902,7 +1988,7 @@ qla24xx_async_abort_command(srb_t *sp)
if (handle == req->num_outstanding_cmds) {
/* Command not found. */
- return QLA_FUNCTION_FAILED;
+ return QLA_ERR_NOT_FOUND;
}
if (sp->type == SRB_FXIOCB_DCMD)
return qlafx00_fx_disc(vha, &vha->hw->mr.fcport,
@@ -1914,6 +2000,7 @@ qla24xx_async_abort_command(srb_t *sp)
static void
qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
{
+ struct srb *sp;
WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n",
ea->data[0]);
@@ -1941,22 +2028,27 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
break;
}
+ sp = ea->sp;
ql_dbg(ql_dbg_disc, vha, 0x2118,
- "%s %d %8phC priority %s, fc4type %x\n",
+ "%s %d %8phC priority %s, fc4type %x prev try %s\n",
__func__, __LINE__, ea->fcport->port_name,
vha->hw->fc4_type_priority == FC4_PRIORITY_FCP ?
- "FCP" : "NVMe", ea->fcport->fc4_type);
+ "FCP" : "NVMe", ea->fcport->fc4_type,
+ (sp->u.iocb_cmd.u.logio.flags & SRB_LOGIN_NVME_PRLI) ?
+ "NVME" : "FCP");
- if (N2N_TOPO(vha->hw)) {
- if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME) {
- ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME;
- ea->fcport->fc4_type |= FS_FC4TYPE_FCP;
- } else {
- ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP;
- ea->fcport->fc4_type |= FS_FC4TYPE_NVME;
- }
+ if (NVME_FCP_TARGET(ea->fcport)) {
+ if (sp->u.iocb_cmd.u.logio.flags & SRB_LOGIN_NVME_PRLI)
+ ea->fcport->do_prli_nvme = 0;
+ else
+ ea->fcport->do_prli_nvme = 1;
+ } else {
+ ea->fcport->do_prli_nvme = 0;
+ }
- if (ea->fcport->n2n_link_reset_cnt < 3) {
+ if (N2N_TOPO(vha->hw)) {
+ if (ea->fcport->n2n_link_reset_cnt <
+ vha->hw->login_retry_count) {
ea->fcport->n2n_link_reset_cnt++;
vha->relogin_jif = jiffies + 2 * HZ;
/*
@@ -1964,6 +2056,7 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
* state machine
*/
set_bit(N2N_LINK_RESET, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
} else {
ql_log(ql_log_warn, vha, 0x2119,
"%s %d %8phC Unable to reconnect\n",
@@ -1975,19 +2068,6 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
* switch connect. login failed. Take connection down
* and allow relogin to retrigger
*/
- if (NVME_FCP_TARGET(ea->fcport)) {
- ql_dbg(ql_dbg_disc, vha, 0x2118,
- "%s %d %8phC post %s prli\n",
- __func__, __LINE__,
- ea->fcport->port_name,
- (ea->fcport->fc4_type & FS_FC4TYPE_NVME)
- ? "NVMe" : "FCP");
- if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME)
- ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME;
- else
- ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP;
- }
-
ea->fcport->flags &= ~FCF_ASYNC_SENT;
ea->fcport->keep_nport_handle = 0;
ea->fcport->logout_on_delete = 1;
@@ -2053,26 +2133,38 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
* force a relogin attempt via implicit LOGO, PLOGI, and PRLI
* requests.
*/
- if (NVME_TARGET(vha->hw, ea->fcport)) {
- ql_dbg(ql_dbg_disc, vha, 0x2117,
- "%s %d %8phC post prli\n",
- __func__, __LINE__, ea->fcport->port_name);
- qla24xx_post_prli_work(vha, ea->fcport);
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x20ea,
- "%s %d %8phC LoopID 0x%x in use with %06x. post gpdb\n",
- __func__, __LINE__, ea->fcport->port_name,
- ea->fcport->loop_id, ea->fcport->d_id.b24);
-
+ if (vha->hw->flags.edif_enabled) {
set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
ea->fcport->logout_on_delete = 1;
ea->fcport->send_els_logo = 0;
- ea->fcport->fw_login_state = DSC_LS_PRLI_COMP;
+ ea->fcport->fw_login_state = DSC_LS_PLOGI_COMP;
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+ } else {
+ if (NVME_TARGET(vha->hw, fcport)) {
+ ql_dbg(ql_dbg_disc, vha, 0x2117,
+ "%s %d %8phC post prli\n",
+ __func__, __LINE__, fcport->port_name);
+ qla24xx_post_prli_work(vha, fcport);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0x20ea,
+ "%s %d %8phC LoopID 0x%x in use with %06x. post gpdb\n",
+ __func__, __LINE__, fcport->port_name,
+ fcport->loop_id, fcport->d_id.b24);
+
+ set_bit(fcport->loop_id, vha->hw->loop_id_map);
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ fcport->chip_reset = vha->hw->base_qpair->chip_reset;
+ fcport->logout_on_delete = 1;
+ fcport->send_els_logo = 0;
+ fcport->fw_login_state = DSC_LS_PRLI_COMP;
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+ qla24xx_post_gpdb_work(vha, fcport, 0);
+ }
}
break;
case MBS_COMMAND_ERROR:
@@ -3877,7 +3969,8 @@ enable_82xx_npiv:
}
/* Enable PUREX PASSTHRU */
- if (ql2xrdpenable || ha->flags.scm_supported_f)
+ if (ql2xrdpenable || ha->flags.scm_supported_f ||
+ ha->flags.edif_enabled)
qla25xx_set_els_cmds_supported(vha);
} else
goto failed;
@@ -4062,7 +4155,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
}
/* Move PUREX, ABTS RX & RIDA to ATIOQ */
- if (ql2xmvasynctoatio &&
+ if (ql2xmvasynctoatio && !ha->flags.edif_enabled &&
(IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) {
if (qla_tgt_mode_enabled(vha) ||
qla_dual_mode_enabled(vha))
@@ -4081,16 +4174,30 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
qla_dual_mode_enabled(vha))
ha->fw_options[2] |= BIT_4;
else
- ha->fw_options[2] &= ~BIT_4;
+ ha->fw_options[2] &= ~(BIT_4);
/* Reserve 1/2 of emergency exchanges for ELS.*/
if (qla2xuseresexchforels)
ha->fw_options[2] |= BIT_8;
else
ha->fw_options[2] &= ~BIT_8;
+
+ /*
+ * N2N: set Secure=1 for PLOGI ACC and
+ * fw shal not send PRLI after PLOGI Acc
+ */
+ if (ha->flags.edif_enabled &&
+ vha->e_dbell.db_flags & EDB_ACTIVE) {
+ ha->fw_options[3] |= BIT_15;
+ ha->flags.n2n_fw_acc_sec = 1;
+ } else {
+ ha->fw_options[3] &= ~BIT_15;
+ ha->flags.n2n_fw_acc_sec = 0;
+ }
}
- if (ql2xrdpenable || ha->flags.scm_supported_f)
+ if (ql2xrdpenable || ha->flags.scm_supported_f ||
+ ha->flags.edif_enabled)
ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB;
/* Enable Async 8130/8131 events -- transceiver insertion/removal */
@@ -4289,8 +4396,6 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- ql_dbg(ql_dbg_init, vha, 0x00d1, "Issue init firmware.\n");
-
if (IS_QLAFX00(ha)) {
rval = qlafx00_init_firmware(vha, ha->init_cb_size);
goto next_check;
@@ -4299,6 +4404,12 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
/* Update any ISP specific firmware options before initialization. */
ha->isp_ops->update_fw_options(vha);
+ ql_dbg(ql_dbg_init, vha, 0x00d1,
+ "Issue init firmware FW opt 1-3= %08x %08x %08x.\n",
+ le32_to_cpu(mid_init_cb->init_cb.firmware_options_1),
+ le32_to_cpu(mid_init_cb->init_cb.firmware_options_2),
+ le32_to_cpu(mid_init_cb->init_cb.firmware_options_3));
+
if (ha->flags.npiv_supported) {
if (ha->operating_mode == LOOP && !IS_CNA_CAPABLE(ha))
ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1;
@@ -4531,11 +4642,11 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
/* initialize */
ha->min_external_loopid = SNS_FIRST_LOOP_ID;
ha->operating_mode = LOOP;
- ha->switch_cap = 0;
switch (topo) {
case 0:
ql_dbg(ql_dbg_disc, vha, 0x200b, "HBA in NL topology.\n");
+ ha->switch_cap = 0;
ha->current_topology = ISP_CFG_NL;
strcpy(connect_type, "(Loop)");
break;
@@ -4549,6 +4660,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
case 2:
ql_dbg(ql_dbg_disc, vha, 0x200d, "HBA in N P2P topology.\n");
+ ha->switch_cap = 0;
ha->operating_mode = P2P;
ha->current_topology = ISP_CFG_N;
strcpy(connect_type, "(N_Port-to-N_Port)");
@@ -4565,6 +4677,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
default:
ql_dbg(ql_dbg_disc, vha, 0x200f,
"HBA in unknown topology %x, using NL.\n", topo);
+ ha->switch_cap = 0;
ha->current_topology = ISP_CFG_NL;
strcpy(connect_type, "(Loop)");
break;
@@ -4577,7 +4690,10 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
id.b.al_pa = al_pa;
id.b.rsvd_1 = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (!(topo == 2 && ha->flags.n2n_bigger))
+ if (vha->hw->flags.edif_enabled) {
+ if (topo != 2)
+ qlt_update_host_map(vha, id);
+ } else if (!(topo == 2 && ha->flags.n2n_bigger))
qlt_update_host_map(vha, id);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -5071,6 +5187,16 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
INIT_LIST_HEAD(&fcport->sess_cmd_list);
spin_lock_init(&fcport->sess_cmd_lock);
+ spin_lock_init(&fcport->edif.sa_list_lock);
+ INIT_LIST_HEAD(&fcport->edif.tx_sa_list);
+ INIT_LIST_HEAD(&fcport->edif.rx_sa_list);
+
+ if (vha->e_dbell.db_flags == EDB_ACTIVE)
+ fcport->edif.app_started = 1;
+
+ spin_lock_init(&fcport->edif.indx_list_lock);
+ INIT_LIST_HEAD(&fcport->edif.edif_indx_list);
+
return fcport;
}
@@ -5084,8 +5210,13 @@ qla2x00_free_fcport(fc_port_t *fcport)
fcport->ct_desc.ct_sns = NULL;
}
+
+ qla_edif_flush_sa_ctl_lists(fcport);
list_del(&fcport->list);
qla2x00_clear_loop_id(fcport);
+
+ qla_edif_list_del(fcport);
+
kfree(fcport);
}
@@ -5204,6 +5335,16 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
"LOOP READY.\n");
ha->flags.fw_init_done = 1;
+ if (ha->flags.edif_enabled &&
+ !(vha->e_dbell.db_flags & EDB_ACTIVE) &&
+ N2N_TOPO(vha->hw)) {
+ /*
+ * use port online to wake up app to get ready
+ * for authentication
+ */
+ qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE, 0);
+ }
+
/*
* Process any ATIO queue entries that came in
* while we weren't online.
@@ -5223,7 +5364,8 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
"%s *** FAILED ***.\n", __func__);
} else {
ql_dbg(ql_dbg_disc, vha, 0x206b,
- "%s: exiting normally.\n", __func__);
+ "%s: exiting normally. local port wwpn %8phN id %06x)\n",
+ __func__, vha->port_name, vha->d_id.b24);
}
/* Restore state if a resync event occurred during processing */
@@ -5243,6 +5385,8 @@ static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha)
unsigned long flags;
fc_port_t *fcport;
+ ql_dbg(ql_dbg_disc, vha, 0x206a, "%s %d.\n", __func__, __LINE__);
+
if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags))
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
@@ -6459,13 +6603,13 @@ void
qla2x00_update_fcports(scsi_qla_host_t *base_vha)
{
fc_port_t *fcport;
- struct scsi_qla_host *vha;
+ struct scsi_qla_host *vha, *tvp;
struct qla_hw_data *ha = base_vha->hw;
unsigned long flags;
spin_lock_irqsave(&ha->vport_slock, flags);
/* Go with deferred removal of rport references. */
- list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
+ list_for_each_entry_safe(vha, tvp, &base_vha->hw->vp_list, list) {
atomic_inc(&vha->vref_count);
list_for_each_entry(fcport, &vha->vp_fcports, list) {
if (fcport->drport &&
@@ -6810,7 +6954,8 @@ void
qla2x00_quiesce_io(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
- struct scsi_qla_host *vp;
+ struct scsi_qla_host *vp, *tvp;
+ unsigned long flags;
ql_dbg(ql_dbg_dpc, vha, 0x401d,
"Quiescing I/O - ha=%p.\n", ha);
@@ -6819,8 +6964,18 @@ qla2x00_quiesce_io(scsi_qla_host_t *vha)
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
qla2x00_mark_all_devices_lost(vha);
- list_for_each_entry(vp, &ha->vp_list, list)
+
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
+ atomic_inc(&vp->vref_count);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+
qla2x00_mark_all_devices_lost(vp);
+
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ atomic_dec(&vp->vref_count);
+ }
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
} else {
if (!atomic_read(&vha->loop_down_timer))
atomic_set(&vha->loop_down_timer,
@@ -6835,7 +6990,7 @@ void
qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
- struct scsi_qla_host *vp;
+ struct scsi_qla_host *vp, *tvp;
unsigned long flags;
fc_port_t *fcport;
u16 i;
@@ -6903,7 +7058,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
qla2x00_mark_all_devices_lost(vha);
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
@@ -6925,7 +7080,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
fcport->scan_state = 0;
}
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
@@ -6969,7 +7124,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
int rval;
uint8_t status = 0;
struct qla_hw_data *ha = vha->hw;
- struct scsi_qla_host *vp;
+ struct scsi_qla_host *vp, *tvp;
struct req_que *req = ha->req_q_map[0];
unsigned long flags;
@@ -7125,7 +7280,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n", __func__);
qla2x00_configure_hba(vha);
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
@@ -8810,7 +8965,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
{
int status, rval;
struct qla_hw_data *ha = vha->hw;
- struct scsi_qla_host *vp;
+ struct scsi_qla_host *vp, *tvp;
unsigned long flags;
status = qla2x00_init_rings(vha);
@@ -8882,7 +9037,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
"qla82xx_restart_isp succeeded.\n");
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 82937c6bd9c4..5f3b7995cc8f 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -478,3 +478,19 @@ bool qla_pci_disconnected(struct scsi_qla_host *vha,
}
return ret;
}
+
+static inline bool
+fcport_is_smaller(fc_port_t *fcport)
+{
+ if (wwn_to_u64(fcport->port_name) <
+ wwn_to_u64(fcport->vha->port_name))
+ return true;
+ else
+ return false;
+}
+
+static inline bool
+fcport_is_bigger(fc_port_t *fcport)
+{
+ return !fcport_is_smaller(fcport);
+}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index d0ee843f6b04..9d4ad1d2b00a 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -118,7 +118,7 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha)
*
* Returns a pointer to the continuation type 1 IOCB packet.
*/
-static inline cont_a64_entry_t *
+cont_a64_entry_t *
qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req)
{
cont_a64_entry_t *cont_pkt;
@@ -145,7 +145,6 @@ inline int
qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts)
{
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
- uint8_t guard = scsi_host_get_guard(cmd->device->host);
/* We always use DIFF Bundling for best performance */
*fw_prot_opts = 0;
@@ -166,7 +165,7 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts)
break;
case SCSI_PROT_READ_PASS:
case SCSI_PROT_WRITE_PASS:
- if (guard & SHOST_DIX_GUARD_IP)
+ if (cmd->prot_flags & SCSI_PROT_IP_CHECKSUM)
*fw_prot_opts |= PO_MODE_DIF_TCP_CKSUM;
else
*fw_prot_opts |= PO_MODE_DIF_PASS;
@@ -176,6 +175,9 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts)
break;
}
+ if (!(cmd->prot_flags & SCSI_PROT_GUARD_CHECK))
+ *fw_prot_opts |= PO_DISABLE_GUARD_CHECK;
+
return scsi_prot_sg_count(cmd);
}
@@ -772,74 +774,19 @@ qla24xx_set_t10dif_tags(srb_t *sp, struct fw_dif_context *pkt,
{
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
- switch (scsi_get_prot_type(cmd)) {
- case SCSI_PROT_DIF_TYPE0:
- /*
- * No check for ql2xenablehba_err_chk, as it would be an
- * I/O error if hba tag generation is not done.
- */
- pkt->ref_tag = cpu_to_le32((uint32_t)
- (0xffffffff & scsi_get_lba(cmd)));
-
- if (!qla2x00_hba_err_chk_enabled(sp))
- break;
+ pkt->ref_tag = cpu_to_le32(scsi_prot_ref_tag(cmd));
+ if (cmd->prot_flags & SCSI_PROT_REF_CHECK &&
+ qla2x00_hba_err_chk_enabled(sp)) {
pkt->ref_tag_mask[0] = 0xff;
pkt->ref_tag_mask[1] = 0xff;
pkt->ref_tag_mask[2] = 0xff;
pkt->ref_tag_mask[3] = 0xff;
- break;
-
- /*
- * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to
- * match LBA in CDB + N
- */
- case SCSI_PROT_DIF_TYPE2:
- pkt->app_tag = cpu_to_le16(0);
- pkt->app_tag_mask[0] = 0x0;
- pkt->app_tag_mask[1] = 0x0;
-
- pkt->ref_tag = cpu_to_le32((uint32_t)
- (0xffffffff & scsi_get_lba(cmd)));
-
- if (!qla2x00_hba_err_chk_enabled(sp))
- break;
-
- /* enable ALL bytes of the ref tag */
- pkt->ref_tag_mask[0] = 0xff;
- pkt->ref_tag_mask[1] = 0xff;
- pkt->ref_tag_mask[2] = 0xff;
- pkt->ref_tag_mask[3] = 0xff;
- break;
-
- /* For Type 3 protection: 16 bit GUARD only */
- case SCSI_PROT_DIF_TYPE3:
- pkt->ref_tag_mask[0] = pkt->ref_tag_mask[1] =
- pkt->ref_tag_mask[2] = pkt->ref_tag_mask[3] =
- 0x00;
- break;
-
- /*
- * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and
- * 16 bit app tag.
- */
- case SCSI_PROT_DIF_TYPE1:
- pkt->ref_tag = cpu_to_le32((uint32_t)
- (0xffffffff & scsi_get_lba(cmd)));
- pkt->app_tag = cpu_to_le16(0);
- pkt->app_tag_mask[0] = 0x0;
- pkt->app_tag_mask[1] = 0x0;
-
- if (!qla2x00_hba_err_chk_enabled(sp))
- break;
-
- /* enable ALL bytes of the ref tag */
- pkt->ref_tag_mask[0] = 0xff;
- pkt->ref_tag_mask[1] = 0xff;
- pkt->ref_tag_mask[2] = 0xff;
- pkt->ref_tag_mask[3] = 0xff;
- break;
}
+
+ pkt->app_tag = cpu_to_le16(0);
+ pkt->app_tag_mask[0] = 0x0;
+ pkt->app_tag_mask[1] = 0x0;
}
int
@@ -905,7 +852,7 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
memset(&sgx, 0, sizeof(struct qla2_sgx));
if (sp) {
cmd = GET_CMD_SP(sp);
- prot_int = cmd->device->sector_size;
+ prot_int = scsi_prot_interval(cmd);
sgx.tot_bytes = scsi_bufflen(cmd);
sgx.cur_sg = scsi_sglist(cmd);
@@ -1605,6 +1552,9 @@ qla24xx_start_scsi(srb_t *sp)
struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
+ if (sp->fcport->edif.enable && (sp->fcport->flags & FCF_FCSP_DEVICE))
+ return qla28xx_start_scsi_edif(sp);
+
/* Setup device pointers. */
req = vha->req;
rsp = req->rsp;
@@ -1963,6 +1913,9 @@ qla2xxx_start_scsi_mq(srb_t *sp)
struct qla_hw_data *ha = vha->hw;
struct qla_qpair *qpair = sp->qpair;
+ if (sp->fcport->edif.enable && (sp->fcport->flags & FCF_FCSP_DEVICE))
+ return qla28xx_start_scsi_edif(sp);
+
/* Acquire qpair specific lock */
spin_lock_irqsave(&qpair->qp_lock, flags);
@@ -2466,6 +2419,12 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio)
logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI);
if (lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI)
logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI);
+ if (lio->u.logio.flags & SRB_LOGIN_FCSP) {
+ logio->control_flags |=
+ cpu_to_le16(LCF_COMMON_FEAT | LCF_SKIP_PRLI);
+ logio->io_parameter[0] =
+ cpu_to_le32(LIO_COMM_FEAT_FCSP | LIO_COMM_FEAT_CIO);
+ }
}
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
@@ -2789,7 +2748,10 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
els_iocb->s_id[0] = vha->d_id.b.domain;
if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) {
- els_iocb->control_flags = 0;
+ if (vha->hw->flags.edif_enabled)
+ els_iocb->control_flags = cpu_to_le16(ECF_SEC_LOGIN);
+ else
+ els_iocb->control_flags = 0;
els_iocb->tx_byte_count = els_iocb->tx_len =
cpu_to_le32(sizeof(struct els_plogi_payload));
put_unaligned_le64(elsio->u.els_plogi.els_plogi_pyld_dma,
@@ -2806,7 +2768,6 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
(uint8_t *)els_iocb,
sizeof(*els_iocb));
} else {
- els_iocb->control_flags = cpu_to_le16(1 << 13);
els_iocb->tx_byte_count =
cpu_to_le32(sizeof(struct els_logo_payload));
put_unaligned_le64(elsio->u.els_logo.els_logo_pyld_dma,
@@ -3030,7 +2991,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_PEND);
elsio = &sp->u.iocb_cmd;
ql_dbg(ql_dbg_io, vha, 0x3073,
- "Enter: PLOGI portid=%06x\n", fcport->d_id.b24);
+ "%s Enter: PLOGI portid=%06x\n", __func__, fcport->d_id.b24);
sp->type = SRB_ELS_DCMD;
sp->name = "ELS_DCMD";
@@ -3073,6 +3034,13 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
elsio->u.els_plogi.els_cmd = els_opcode;
elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
+ if (els_opcode == ELS_DCMD_PLOGI && vha->hw->flags.edif_enabled &&
+ vha->e_dbell.db_flags & EDB_ACTIVE) {
+ struct fc_els_flogi *p = ptr;
+
+ p->fl_csp.sp_features |= cpu_to_be16(FC_SP_FT_SEC);
+ }
+
ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x0109,
(uint8_t *)elsio->u.els_plogi.els_plogi_pyld,
@@ -3106,6 +3074,43 @@ done:
return rval;
}
+/* it is assume qpair lock is held */
+void qla_els_pt_iocb(struct scsi_qla_host *vha,
+ struct els_entry_24xx *els_iocb,
+ struct qla_els_pt_arg *a)
+{
+ els_iocb->entry_type = ELS_IOCB_TYPE;
+ els_iocb->entry_count = 1;
+ els_iocb->sys_define = 0;
+ els_iocb->entry_status = 0;
+ els_iocb->handle = QLA_SKIP_HANDLE;
+ els_iocb->nport_handle = a->nport_handle;
+ els_iocb->rx_xchg_address = a->rx_xchg_address;
+ els_iocb->tx_dsd_count = cpu_to_le16(1);
+ els_iocb->vp_index = a->vp_idx;
+ els_iocb->sof_type = EST_SOFI3;
+ els_iocb->rx_dsd_count = cpu_to_le16(0);
+ els_iocb->opcode = a->els_opcode;
+
+ els_iocb->d_id[0] = a->did.b.al_pa;
+ els_iocb->d_id[1] = a->did.b.area;
+ els_iocb->d_id[2] = a->did.b.domain;
+ /* For SID the byte order is different than DID */
+ els_iocb->s_id[1] = vha->d_id.b.al_pa;
+ els_iocb->s_id[2] = vha->d_id.b.area;
+ els_iocb->s_id[0] = vha->d_id.b.domain;
+
+ els_iocb->control_flags = cpu_to_le16(a->control_flags);
+
+ els_iocb->tx_byte_count = cpu_to_le32(a->tx_byte_count);
+ els_iocb->tx_len = cpu_to_le32(a->tx_len);
+ put_unaligned_le64(a->tx_addr, &els_iocb->tx_address);
+
+ els_iocb->rx_byte_count = cpu_to_le32(a->rx_byte_count);
+ els_iocb->rx_len = cpu_to_le32(a->rx_len);
+ put_unaligned_le64(a->rx_addr, &els_iocb->rx_address);
+}
+
static void
qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
{
@@ -3700,6 +3705,16 @@ static void qla2x00_send_notify_ack_iocb(srb_t *sp,
nack->u.isp24.srr_reject_code = 0;
nack->u.isp24.srr_reject_code_expl = 0;
nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
+
+ if (ntfy->u.isp24.status_subcode == ELS_PLOGI &&
+ (le16_to_cpu(ntfy->u.isp24.flags) & NOTIFY24XX_FLAGS_FCSP) &&
+ sp->vha->hw->flags.edif_enabled) {
+ ql_dbg(ql_dbg_disc, sp->vha, 0x3074,
+ "%s PLOGI NACK sent with FC SECURITY bit, hdl=%x, loopid=%x, to pid %06x\n",
+ sp->name, sp->handle, sp->fcport->loop_id,
+ sp->fcport->d_id.b24);
+ nack->u.isp24.flags |= cpu_to_le16(NOTIFY_ACK_FLAGS_FCSP);
+ }
}
/*
@@ -3804,6 +3819,10 @@ qla2x00_start_sp(srb_t *sp)
case SRB_ELS_CMD_HST:
qla24xx_els_iocb(sp, pkt);
break;
+ case SRB_ELS_CMD_HST_NOLOGIN:
+ qla_els_pt_iocb(sp->vha, pkt, &sp->u.bsg_cmd.u.els_arg);
+ ((struct els_entry_24xx *)pkt)->handle = sp->handle;
+ break;
case SRB_CT_CMD:
IS_FWI2_CAPABLE(ha) ?
qla24xx_ct_iocb(sp, pkt) :
@@ -3851,6 +3870,12 @@ qla2x00_start_sp(srb_t *sp)
case SRB_PRLO_CMD:
qla24xx_prlo_iocb(sp, pkt);
break;
+ case SRB_SA_UPDATE:
+ qla24xx_sa_update_iocb(sp, pkt);
+ break;
+ case SRB_SA_REPLACE:
+ qla24xx_sa_replace_iocb(sp, pkt);
+ break;
default:
break;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index d9fb093a60a1..ece60267b971 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -170,6 +170,149 @@ qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt)
}
/**
+ * __qla_consume_iocb - this routine is used to tell fw driver has processed
+ * or consumed the head IOCB along with the continuation IOCB's from the
+ * provided respond queue.
+ * @vha: host adapter pointer
+ * @pkt: pointer to current packet. On return, this pointer shall move
+ * to the next packet.
+ * @rsp: respond queue pointer.
+ *
+ * it is assumed pkt is the head iocb, not the continuation iocbk
+ */
+void __qla_consume_iocb(struct scsi_qla_host *vha,
+ void **pkt, struct rsp_que **rsp)
+{
+ struct rsp_que *rsp_q = *rsp;
+ response_t *new_pkt;
+ uint16_t entry_count_remaining;
+ struct purex_entry_24xx *purex = *pkt;
+
+ entry_count_remaining = purex->entry_count;
+ while (entry_count_remaining > 0) {
+ new_pkt = rsp_q->ring_ptr;
+ *pkt = new_pkt;
+
+ rsp_q->ring_index++;
+ if (rsp_q->ring_index == rsp_q->length) {
+ rsp_q->ring_index = 0;
+ rsp_q->ring_ptr = rsp_q->ring;
+ } else {
+ rsp_q->ring_ptr++;
+ }
+
+ new_pkt->signature = RESPONSE_PROCESSED;
+ /* flush signature */
+ wmb();
+ --entry_count_remaining;
+ }
+}
+
+/**
+ * __qla_copy_purex_to_buffer - extract ELS payload from Purex IOCB
+ * and save to provided buffer
+ * @vha: host adapter pointer
+ * @pkt: pointer Purex IOCB
+ * @rsp: respond queue
+ * @buf: extracted ELS payload copy here
+ * @buf_len: buffer length
+ */
+int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha,
+ void **pkt, struct rsp_que **rsp, u8 *buf, u32 buf_len)
+{
+ struct purex_entry_24xx *purex = *pkt;
+ struct rsp_que *rsp_q = *rsp;
+ sts_cont_entry_t *new_pkt;
+ uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
+ uint16_t buffer_copy_offset = 0;
+ uint16_t entry_count_remaining;
+ u16 tpad;
+
+ entry_count_remaining = purex->entry_count;
+ total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
+ - PURX_ELS_HEADER_SIZE;
+
+ /*
+ * end of payload may not end in 4bytes boundary. Need to
+ * round up / pad for room to swap, before saving data
+ */
+ tpad = roundup(total_bytes, 4);
+
+ if (buf_len < tpad) {
+ ql_dbg(ql_dbg_async, vha, 0x5084,
+ "%s buffer is too small %d < %d\n",
+ __func__, buf_len, tpad);
+ __qla_consume_iocb(vha, pkt, rsp);
+ return -EIO;
+ }
+
+ pending_bytes = total_bytes = tpad;
+ no_bytes = (pending_bytes > sizeof(purex->els_frame_payload)) ?
+ sizeof(purex->els_frame_payload) : pending_bytes;
+
+ memcpy(buf, &purex->els_frame_payload[0], no_bytes);
+ buffer_copy_offset += no_bytes;
+ pending_bytes -= no_bytes;
+ --entry_count_remaining;
+
+ ((response_t *)purex)->signature = RESPONSE_PROCESSED;
+ /* flush signature */
+ wmb();
+
+ do {
+ while ((total_bytes > 0) && (entry_count_remaining > 0)) {
+ new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
+ *pkt = new_pkt;
+
+ if (new_pkt->entry_type != STATUS_CONT_TYPE) {
+ ql_log(ql_log_warn, vha, 0x507a,
+ "Unexpected IOCB type, partial data 0x%x\n",
+ buffer_copy_offset);
+ break;
+ }
+
+ rsp_q->ring_index++;
+ if (rsp_q->ring_index == rsp_q->length) {
+ rsp_q->ring_index = 0;
+ rsp_q->ring_ptr = rsp_q->ring;
+ } else {
+ rsp_q->ring_ptr++;
+ }
+ no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
+ sizeof(new_pkt->data) : pending_bytes;
+ if ((buffer_copy_offset + no_bytes) <= total_bytes) {
+ memcpy((buf + buffer_copy_offset), new_pkt->data,
+ no_bytes);
+ buffer_copy_offset += no_bytes;
+ pending_bytes -= no_bytes;
+ --entry_count_remaining;
+ } else {
+ ql_log(ql_log_warn, vha, 0x5044,
+ "Attempt to copy more that we got, optimizing..%x\n",
+ buffer_copy_offset);
+ memcpy((buf + buffer_copy_offset), new_pkt->data,
+ total_bytes - buffer_copy_offset);
+ }
+
+ ((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
+ /* flush signature */
+ wmb();
+ }
+
+ if (pending_bytes != 0 || entry_count_remaining != 0) {
+ ql_log(ql_log_fatal, vha, 0x508b,
+ "Dropping partial Data, underrun bytes = 0x%x, entry cnts 0x%x\n",
+ total_bytes, entry_count_remaining);
+ return -EIO;
+ }
+ } while (entry_count_remaining > 0);
+
+ be32_to_cpu_array((u32 *)buf, (__be32 *)buf, total_bytes >> 2);
+
+ return 0;
+}
+
+/**
* qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
* @irq: interrupt number
* @dev_id: SCSI driver HA context
@@ -505,7 +648,7 @@ const char *
qla2x00_get_link_speed_str(struct qla_hw_data *ha, uint16_t speed)
{
static const char *const link_speeds[] = {
- "1", "2", "?", "4", "8", "16", "32", "10"
+ "1", "2", "?", "4", "8", "16", "32", "64", "10"
};
#define QLA_LAST_SPEED (ARRAY_SIZE(link_speeds) - 1)
@@ -1727,6 +1870,9 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
srb_t *sp;
uint16_t index;
+ if (pkt->handle == QLA_SKIP_HANDLE)
+ return NULL;
+
index = LSW(pkt->handle);
if (index >= req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x5031,
@@ -1971,7 +2117,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
}
static void
-qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
+qla24xx_els_ct_entry(scsi_qla_host_t *v, struct req_que *req,
struct sts_entry_24xx *pkt, int iocb_type)
{
struct els_sts_entry_24xx *ese = (struct els_sts_entry_24xx *)pkt;
@@ -1982,18 +2128,58 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
struct fc_bsg_reply *bsg_reply;
uint16_t comp_status;
uint32_t fw_status[3];
- int res;
+ int res, logit = 1;
struct srb_iocb *els;
+ uint n;
+ scsi_qla_host_t *vha;
+ struct els_sts_entry_24xx *e = (struct els_sts_entry_24xx *)pkt;
- sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ sp = qla2x00_get_sp_from_handle(v, func, req, pkt);
if (!sp)
return;
+ bsg_job = sp->u.bsg_job;
+ vha = sp->vha;
type = NULL;
+
+ comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status);
+ fw_status[1] = le32_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_1);
+ fw_status[2] = le32_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_2);
+
switch (sp->type) {
case SRB_ELS_CMD_RPT:
case SRB_ELS_CMD_HST:
+ type = "rpt hst";
+ break;
+ case SRB_ELS_CMD_HST_NOLOGIN:
type = "els";
+ {
+ struct els_entry_24xx *els = (void *)pkt;
+ struct qla_bsg_auth_els_request *p =
+ (struct qla_bsg_auth_els_request *)bsg_job->request;
+
+ ql_dbg(ql_dbg_user, vha, 0x700f,
+ "%s %s. portid=%02x%02x%02x status %x xchg %x bsg ptr %p\n",
+ __func__, sc_to_str(p->e.sub_cmd),
+ e->d_id[2], e->d_id[1], e->d_id[0],
+ comp_status, p->e.extra_rx_xchg_address, bsg_job);
+
+ if (!(le16_to_cpu(els->control_flags) & ECF_PAYLOAD_DESCR_MASK)) {
+ if (sp->remap.remapped) {
+ n = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt,
+ sp->remap.rsp.buf,
+ sp->remap.rsp.len);
+ ql_dbg(ql_dbg_user + ql_dbg_verbose, vha, 0x700e,
+ "%s: SG copied %x of %x\n",
+ __func__, n, sp->remap.rsp.len);
+ } else {
+ ql_dbg(ql_dbg_user, vha, 0x700f,
+ "%s: NOT REMAPPED (error)...!!!\n",
+ __func__);
+ }
+ }
+ }
break;
case SRB_CT_CMD:
type = "ct pass-through";
@@ -2023,10 +2209,6 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
return;
}
- comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status);
- fw_status[1] = le32_to_cpu(ese->error_subcode_1);
- fw_status[2] = le32_to_cpu(ese->error_subcode_2);
-
if (iocb_type == ELS_IOCB_TYPE) {
els = &sp->u.iocb_cmd;
els->u.els_plogi.fw_status[0] = cpu_to_le32(fw_status[0]);
@@ -2040,15 +2222,53 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
res = DID_OK << 16;
els->u.els_plogi.len = cpu_to_le16(le32_to_cpu(
ese->total_byte_count));
+
+ if (sp->remap.remapped &&
+ ((u8 *)sp->remap.rsp.buf)[0] == ELS_LS_ACC) {
+ ql_dbg(ql_dbg_user, vha, 0x503f,
+ "%s IOCB Done LS_ACC %02x%02x%02x -> %02x%02x%02x",
+ __func__, e->s_id[0], e->s_id[2], e->s_id[1],
+ e->d_id[2], e->d_id[1], e->d_id[0]);
+ logit = 0;
+ }
+
+ } else if (comp_status == CS_PORT_LOGGED_OUT) {
+ els->u.els_plogi.len = 0;
+ res = DID_IMM_RETRY << 16;
+ qlt_schedule_sess_for_deletion(sp->fcport);
} else {
els->u.els_plogi.len = 0;
res = DID_ERROR << 16;
}
+
+ if (logit) {
+ if (sp->remap.remapped &&
+ ((u8 *)sp->remap.rsp.buf)[0] == ELS_LS_RJT) {
+ ql_dbg(ql_dbg_user, vha, 0x503f,
+ "%s IOCB Done LS_RJT hdl=%x comp_status=0x%x\n",
+ type, sp->handle, comp_status);
+
+ ql_dbg(ql_dbg_user, vha, 0x503f,
+ "subcode 1=0x%x subcode 2=0x%x bytes=0x%x %02x%02x%02x -> %02x%02x%02x\n",
+ fw_status[1], fw_status[2],
+ le32_to_cpu(((struct els_sts_entry_24xx *)
+ pkt)->total_byte_count),
+ e->s_id[0], e->s_id[2], e->s_id[1],
+ e->d_id[2], e->d_id[1], e->d_id[0]);
+ } else {
+ ql_log(ql_log_info, vha, 0x503f,
+ "%s IOCB Done hdl=%x comp_status=0x%x\n",
+ type, sp->handle, comp_status);
+ ql_log(ql_log_info, vha, 0x503f,
+ "subcode 1=0x%x subcode 2=0x%x bytes=0x%x %02x%02x%02x -> %02x%02x%02x\n",
+ fw_status[1], fw_status[2],
+ le32_to_cpu(((struct els_sts_entry_24xx *)
+ pkt)->total_byte_count),
+ e->s_id[0], e->s_id[2], e->s_id[1],
+ e->d_id[2], e->d_id[1], e->d_id[0]);
+ }
+ }
}
- ql_dbg(ql_dbg_disc, vha, 0x503f,
- "ELS IOCB Done -%s hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n",
- type, sp->handle, comp_status, fw_status[1], fw_status[2],
- le32_to_cpu(ese->total_byte_count));
goto els_ct_done;
}
@@ -2107,6 +2327,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
struct srb_iocb *lio;
uint16_t *data;
uint32_t iop[2];
+ int logit = 1;
sp = qla2x00_get_sp_from_handle(vha, func, req, logio);
if (!sp)
@@ -2153,6 +2374,10 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
if (sp->type != SRB_LOGIN_CMD)
goto logio_done;
+ lio->u.logio.iop[1] = le32_to_cpu(logio->io_parameter[5]);
+ if (le32_to_cpu(logio->io_parameter[5]) & LIO_COMM_FEAT_FCSP)
+ fcport->flags |= FCF_FCSP_DEVICE;
+
iop[0] = le32_to_cpu(logio->io_parameter[0]);
if (iop[0] & BIT_4) {
fcport->port_type = FCT_TARGET;
@@ -2180,9 +2405,11 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
case LSC_SCODE_PORTID_USED:
data[0] = MBS_PORT_ID_USED;
data[1] = LSW(iop[1]);
+ logit = 0;
break;
case LSC_SCODE_NPORT_USED:
data[0] = MBS_LOOP_ID_USED;
+ logit = 0;
break;
case LSC_SCODE_CMD_FAILED:
if (iop[1] == 0x0606) {
@@ -2215,12 +2442,20 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
break;
}
- ql_log(ql_log_warn, sp->vha, 0x5037,
- "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
- type, sp->handle, fcport->d_id.b24, fcport->port_name,
- le16_to_cpu(logio->comp_status),
- le32_to_cpu(logio->io_parameter[0]),
- le32_to_cpu(logio->io_parameter[1]));
+ if (logit)
+ ql_log(ql_log_warn, sp->vha, 0x5037, "Async-%s failed: "
+ "handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
+ type, sp->handle, fcport->d_id.b24, fcport->port_name,
+ le16_to_cpu(logio->comp_status),
+ le32_to_cpu(logio->io_parameter[0]),
+ le32_to_cpu(logio->io_parameter[1]));
+ else
+ ql_dbg(ql_dbg_disc, sp->vha, 0x5037, "Async-%s failed: "
+ "handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
+ type, sp->handle, fcport->d_id.b24, fcport->port_name,
+ le16_to_cpu(logio->comp_status),
+ le32_to_cpu(logio->io_parameter[0]),
+ le32_to_cpu(logio->io_parameter[1]));
logio_done:
sp->done(sp, 0);
@@ -2417,6 +2652,15 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
case CS_PORT_UNAVAILABLE:
case CS_PORT_LOGGED_OUT:
fcport->nvme_flag |= NVME_FLAG_RESETTING;
+ if (atomic_read(&fcport->state) == FCS_ONLINE) {
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
+ "Port to be marked lost on fcport=%06x, current "
+ "port state= %s comp_status %x.\n",
+ fcport->d_id.b24, port_state_str[FCS_ONLINE],
+ comp_status);
+
+ qlt_schedule_sess_for_deletion(fcport);
+ }
fallthrough;
case CS_ABORTED:
case CS_PORT_BUSY:
@@ -2969,9 +3213,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
return;
}
+ /* Fast path completion. */
+ qla_chk_edif_rx_sa_delete_pending(vha, sp, sts24);
sp->qpair->cmd_completion_cnt++;
- /* Fast path completion. */
if (comp_status == CS_COMPLETE && scsi_status == 0) {
qla2x00_process_completed_request(vha, req, handle);
@@ -3366,6 +3611,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
}
break;
+ case SA_UPDATE_IOCB_TYPE:
case ABTS_RESP_24XX:
case CTIO_TYPE7:
case CTIO_CRC2:
@@ -3453,6 +3699,63 @@ void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
}
/**
+ * qla_chk_cont_iocb_avail - check for all continuation iocbs are available
+ * before iocb processing can start.
+ * @vha: host adapter pointer
+ * @rsp: respond queue
+ * @pkt: head iocb describing how many continuation iocb
+ * Return: 0 all iocbs has arrived, xx- all iocbs have not arrived.
+ */
+static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
+ struct rsp_que *rsp, response_t *pkt)
+{
+ int start_pkt_ring_index, end_pkt_ring_index, n_ring_index;
+ response_t *end_pkt;
+ int rc = 0;
+ u32 rsp_q_in;
+
+ if (pkt->entry_count == 1)
+ return rc;
+
+ /* ring_index was pre-increment. set it back to current pkt */
+ if (rsp->ring_index == 0)
+ start_pkt_ring_index = rsp->length - 1;
+ else
+ start_pkt_ring_index = rsp->ring_index - 1;
+
+ if ((start_pkt_ring_index + pkt->entry_count) >= rsp->length)
+ end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count -
+ rsp->length - 1;
+ else
+ end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count - 1;
+
+ end_pkt = rsp->ring + end_pkt_ring_index;
+
+ /* next pkt = end_pkt + 1 */
+ n_ring_index = end_pkt_ring_index + 1;
+ if (n_ring_index >= rsp->length)
+ n_ring_index = 0;
+
+ rsp_q_in = rsp->qpair->use_shadow_reg ? *rsp->in_ptr :
+ rd_reg_dword(rsp->rsp_q_in);
+
+ /* rsp_q_in is either wrapped or pointing beyond endpkt */
+ if ((rsp_q_in < start_pkt_ring_index && rsp_q_in < n_ring_index) ||
+ rsp_q_in >= n_ring_index)
+ /* all IOCBs arrived. */
+ rc = 0;
+ else
+ rc = -EIO;
+
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x5091,
+ "%s - ring %p pkt %p end pkt %p entry count %#x rsp_q_in %d rc %d\n",
+ __func__, rsp->ring, pkt, end_pkt, pkt->entry_count,
+ rsp_q_in, rc);
+
+ return rc;
+}
+
+/**
* qla24xx_process_response_queue() - Process response queue entries.
* @vha: SCSI driver HA context
* @rsp: response queue
@@ -3592,12 +3895,26 @@ process_err:
qla27xx_process_purex_fpin);
break;
+ case ELS_AUTH_ELS:
+ if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt)) {
+ ql_dbg(ql_dbg_init, vha, 0x5091,
+ "Defer processing ELS opcode %#x...\n",
+ purex_entry->els_frame_payload[3]);
+ return;
+ }
+ qla24xx_auth_els(vha, (void **)&pkt, &rsp);
+ break;
default:
ql_log(ql_log_warn, vha, 0x509c,
"Discarding ELS Request opcode 0x%x\n",
purex_entry->els_frame_payload[3]);
}
break;
+ case SA_UPDATE_IOCB_TYPE:
+ qla28xx_sa_update_iocb_entry(vha, rsp->req,
+ (struct sa_update_28xx *)pkt);
+ break;
+
default:
/* Type Not Supported. */
ql_dbg(ql_dbg_async, vha, 0x5042,
@@ -4201,6 +4518,8 @@ skip_msi:
ql_dbg(ql_dbg_init, vha, 0x0125,
"INTa mode: Enabled.\n");
ha->flags.mr_intr_valid = 1;
+ /* Set max_qpair to 0, as MSI-X and MSI in not enabled */
+ ha->max_qpairs = 0;
}
clear_risc_ints:
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 9f3ad8aa649c..7811c4952035 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -663,6 +663,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
}
#define NVME_ENABLE_FLAG BIT_3
+#define EDIF_HW_SUPPORT BIT_10
/*
* qla2x00_execute_fw
@@ -739,7 +740,7 @@ again:
mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE;
mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11;
- mcp->in_mb |= MBX_3 | MBX_2 | MBX_1;
+ mcp->in_mb |= MBX_5 | MBX_3 | MBX_2 | MBX_1;
} else {
mcp->mb[1] = LSW(risc_addr);
mcp->out_mb |= MBX_1;
@@ -795,6 +796,12 @@ again:
}
}
+ if (IS_QLA28XX(ha) && (mcp->mb[5] & EDIF_HW_SUPPORT)) {
+ ha->flags.edif_hw = 1;
+ ql_log(ql_log_info, vha, 0xffff,
+ "%s: edif HW\n", __func__);
+ }
+
done:
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
"Done %s.\n", __func__);
@@ -1130,6 +1137,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
ha->fw_attributes_ext[0]);
vha->flags.nvme2_enabled = 1;
}
+
+ if (IS_QLA28XX(ha) && ha->flags.edif_hw && ql2xsecenable &&
+ (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_EDIF)) {
+ ha->flags.edif_enabled = 1;
+ ql_log(ql_log_info, vha, 0xffff,
+ "%s: edif is enabled\n", __func__);
+ }
}
if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
@@ -3231,7 +3245,7 @@ qla24xx_abort_command(srb_t *sp)
if (sp->qpair)
req = sp->qpair->req;
else
- return QLA_FUNCTION_FAILED;
+ return QLA_ERR_NO_QPAIR;
if (ql2xasynctmfenable)
return qla24xx_async_abort_command(sp);
@@ -3244,7 +3258,7 @@ qla24xx_abort_command(srb_t *sp)
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
if (handle == req->num_outstanding_cmds) {
/* Command not found. */
- return QLA_FUNCTION_FAILED;
+ return QLA_ERR_NOT_FOUND;
}
abt = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma);
@@ -4035,6 +4049,10 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->n2n_flag = 1;
fcport->keep_nport_handle = 1;
+ fcport->login_retry = vha->hw->login_retry_count;
+ fcport->fc4_type = FS_FC4TYPE_FCP;
+ if (vha->flags.nvme_enabled)
+ fcport->fc4_type |= FS_FC4TYPE_NVME;
if (wwn_to_u64(vha->port_name) >
wwn_to_u64(fcport->port_name)) {
@@ -4172,6 +4190,16 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
rptid_entry->u.f2.remote_nport_id[1];
fcport->d_id.b.al_pa =
rptid_entry->u.f2.remote_nport_id[0];
+
+ /*
+ * For the case where remote port sending PRLO, FW
+ * sends up RIDA Format 2 as an indication of session
+ * loss. In other word, FW state change from PRLI
+ * complete back to PLOGI complete. Delete the
+ * session and let relogin drive the reconnect.
+ */
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qlt_schedule_sess_for_deletion(fcport);
}
}
}
@@ -4946,7 +4974,7 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
return rval;
}
-#define PUREX_CMD_COUNT 2
+#define PUREX_CMD_COUNT 4
int
qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
{
@@ -4954,6 +4982,7 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
uint8_t *els_cmd_map;
+ uint8_t active_cnt = 0;
dma_addr_t els_cmd_map_dma;
uint8_t cmd_opcode[PUREX_CMD_COUNT];
uint8_t i, index, purex_bit;
@@ -4975,10 +5004,20 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
}
/* List of Purex ELS */
- cmd_opcode[0] = ELS_FPIN;
- cmd_opcode[1] = ELS_RDP;
+ if (ql2xrdpenable) {
+ cmd_opcode[active_cnt] = ELS_RDP;
+ active_cnt++;
+ }
+ if (ha->flags.scm_supported_f) {
+ cmd_opcode[active_cnt] = ELS_FPIN;
+ active_cnt++;
+ }
+ if (ha->flags.edif_enabled) {
+ cmd_opcode[active_cnt] = ELS_AUTH_ELS;
+ active_cnt++;
+ }
- for (i = 0; i < PUREX_CMD_COUNT; i++) {
+ for (i = 0; i < active_cnt; i++) {
index = cmd_opcode[i] / 8;
purex_bit = cmd_opcode[i] % 8;
els_cmd_map[index] |= 1 << purex_bit;
@@ -6588,6 +6627,12 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
fcport->d_id.b.al_pa = pd->port_id[2];
fcport->d_id.b.rsvd_1 = 0;
+ ql_dbg(ql_dbg_disc, vha, 0x2062,
+ "%8phC SVC Param w3 %02x%02x",
+ fcport->port_name,
+ pd->prli_svc_param_word_3[1],
+ pd->prli_svc_param_word_3[0]);
+
if (NVME_TARGET(vha->hw, fcport)) {
fcport->port_type = FCT_NVME;
if ((pd->prli_svc_param_word_3[0] & BIT_5) == 0)
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index c7caf322f445..1c024055f8c5 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -65,7 +65,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
uint16_t vp_id;
struct qla_hw_data *ha = vha->hw;
unsigned long flags = 0;
- u8 i;
+ u32 i, bailout;
mutex_lock(&ha->vport_lock);
/*
@@ -75,21 +75,29 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
* ensures no active vp_list traversal while the vport is removed
* from the queue)
*/
- for (i = 0; i < 10; i++) {
- if (wait_event_timeout(vha->vref_waitq,
- !atomic_read(&vha->vref_count), HZ) > 0)
+ bailout = 0;
+ for (i = 0; i < 500; i++) {
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ if (atomic_read(&vha->vref_count) == 0) {
+ list_del(&vha->list);
+ qlt_update_vp_map(vha, RESET_VP_IDX);
+ bailout = 1;
+ }
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+ if (bailout)
break;
+ else
+ msleep(20);
}
-
- spin_lock_irqsave(&ha->vport_slock, flags);
- if (atomic_read(&vha->vref_count)) {
- ql_dbg(ql_dbg_vport, vha, 0xfffa,
- "vha->vref_count=%u timeout\n", vha->vref_count.counter);
- vha->vref_count = (atomic_t)ATOMIC_INIT(0);
+ if (!bailout) {
+ ql_log(ql_log_info, vha, 0xfffa,
+ "vha->vref_count=%u timeout\n", vha->vref_count.counter);
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ list_del(&vha->list);
+ qlt_update_vp_map(vha, RESET_VP_IDX);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
}
- list_del(&vha->list);
- qlt_update_vp_map(vha, RESET_VP_IDX);
- spin_unlock_irqrestore(&ha->vport_slock, flags);
vp_id = vha->vp_idx;
ha->num_vhosts--;
@@ -158,6 +166,10 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
int ret = QLA_SUCCESS;
fc_port_t *fcport;
+ if (vha->hw->flags.edif_enabled)
+ /* delete sessions and flush sa_indexes */
+ qla2x00_wait_for_sess_deletion(vha);
+
if (vha->hw->flags.fw_started)
ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
@@ -166,7 +178,8 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
list_for_each_entry(fcport, &vha->vp_fcports, list)
fcport->logout_on_delete = 0;
- qla2x00_mark_all_devices_lost(vha);
+ if (!vha->hw->flags.edif_enabled)
+ qla2x00_wait_for_sess_deletion(vha);
/* Remove port id from vp target map */
spin_lock_irqsave(&vha->hw->hardware_lock, flags);
@@ -257,13 +270,13 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
void
qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
{
- scsi_qla_host_t *vha;
+ scsi_qla_host_t *vha, *tvp;
struct qla_hw_data *ha = rsp->hw;
int i = 0;
unsigned long flags;
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vha, &ha->vp_list, list) {
+ list_for_each_entry_safe(vha, tvp, &ha->vp_list, list) {
if (vha->vp_idx) {
if (test_bit(VPORT_DELETE, &vha->dpc_flags))
continue;
@@ -416,7 +429,7 @@ void
qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
- scsi_qla_host_t *vp;
+ scsi_qla_host_t *vp, *tvp;
unsigned long flags = 0;
if (vha->vp_idx)
@@ -430,7 +443,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
return;
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index 3e5c70a1d969..1c5da2dbd6f9 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -91,8 +91,9 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport,
struct qla_hw_data *ha;
struct qla_qpair *qpair;
- if (!qidx)
- qidx++;
+ /* Map admin queue and 1st IO queue to index 0 */
+ if (qidx)
+ qidx--;
vha = (struct scsi_qla_host *)lport->private;
ha = vha->hw;
@@ -108,19 +109,24 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport,
return -EINVAL;
}
- if (ha->queue_pair_map[qidx]) {
- *handle = ha->queue_pair_map[qidx];
- ql_log(ql_log_info, vha, 0x2121,
- "Returning existing qpair of %p for idx=%x\n",
- *handle, qidx);
- return 0;
- }
+ /* Use base qpair if max_qpairs is 0 */
+ if (!ha->max_qpairs) {
+ qpair = ha->base_qpair;
+ } else {
+ if (ha->queue_pair_map[qidx]) {
+ *handle = ha->queue_pair_map[qidx];
+ ql_log(ql_log_info, vha, 0x2121,
+ "Returning existing qpair of %p for idx=%x\n",
+ *handle, qidx);
+ return 0;
+ }
- qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true);
- if (qpair == NULL) {
- ql_log(ql_log_warn, vha, 0x2122,
- "Failed to allocate qpair\n");
- return -EINVAL;
+ qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true);
+ if (!qpair) {
+ ql_log(ql_log_warn, vha, 0x2122,
+ "Failed to allocate qpair\n");
+ return -EINVAL;
+ }
}
*handle = qpair;
@@ -221,13 +227,13 @@ static void qla_nvme_abort_work(struct work_struct *work)
srb_t *sp = priv->sp;
fc_port_t *fcport = sp->fcport;
struct qla_hw_data *ha = fcport->vha->hw;
- int rval;
+ int rval, abts_done_called = 1;
ql_dbg(ql_dbg_io, fcport->vha, 0xffff,
- "%s called for sp=%p, hndl=%x on fcport=%p deleted=%d\n",
- __func__, sp, sp->handle, fcport, fcport->deleted);
+ "%s called for sp=%p, hndl=%x on fcport=%p desc=%p deleted=%d\n",
+ __func__, sp, sp->handle, fcport, sp->u.iocb_cmd.u.nvme.desc, fcport->deleted);
- if (!ha->flags.fw_started || fcport->deleted)
+ if (!ha->flags.fw_started || fcport->deleted == QLA_SESS_DELETED)
goto out;
if (ha->flags.host_shutting_down) {
@@ -246,11 +252,19 @@ static void qla_nvme_abort_work(struct work_struct *work)
sp, sp->handle, fcport, rval);
/*
+ * If async tmf is enabled, the abort callback is called only on
+ * return codes QLA_SUCCESS and QLA_ERR_FROM_FW.
+ */
+ if (ql2xasynctmfenable &&
+ rval != QLA_SUCCESS && rval != QLA_ERR_FROM_FW)
+ abts_done_called = 0;
+
+ /*
* Returned before decreasing kref so that I/O requests
* are waited until ABTS complete. This kref is decreased
* at qla24xx_abort_sp_done function.
*/
- if (ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(sp))
+ if (abts_done_called && ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(sp))
return;
out:
/* kref_get was done before work was schedule. */
@@ -463,6 +477,10 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
} else if (fd->io_dir == 0) {
cmd_pkt->control_flags = 0;
}
+
+ if (sp->fcport->edif.enable && fd->io_dir != 0)
+ cmd_pkt->control_flags |= cpu_to_le16(CF_EN_EDIF);
+
/* Set BIT_13 of control flags for Async event */
if (vha->flags.nvme2_enabled &&
cmd->sqe.common.opcode == nvme_admin_async_event) {
@@ -727,18 +745,9 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha)
WARN_ON(vha->nvme_local_port);
- if (ha->max_req_queues < 3) {
- if (!ha->flags.max_req_queue_warned)
- ql_log(ql_log_info, vha, 0x2120,
- "%s: Disabling FC-NVME due to lack of free queue pairs (%d).\n",
- __func__, ha->max_req_queues);
- ha->flags.max_req_queue_warned = 1;
- return ret;
- }
-
qla_nvme_fc_transport.max_hw_queues =
min((uint8_t)(qla_nvme_fc_transport.max_hw_queues),
- (uint8_t)(ha->max_req_queues - 2));
+ (uint8_t)(ha->max_qpairs ? ha->max_qpairs : 1));
pinfo.node_name = wwn_to_u64(vha->node_name);
pinfo.port_name = wwn_to_u64(vha->port_name);
@@ -803,14 +812,14 @@ void qla_nvme_abort_process_comp_status(struct abort_entry_24xx *abt, srb_t *ori
case CS_PORT_LOGGED_OUT:
/* BA_RJT was received for the ABTS */
case CS_PORT_CONFIG_CHG:
- ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09d,
+ ql_dbg(ql_dbg_async, vha, 0xf09d,
"Abort I/O IOCB completed with error, comp_status=%x\n",
comp_status);
break;
/* BA_RJT was received for the ABTS */
case CS_REJECT_RECEIVED:
- ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09e,
+ ql_dbg(ql_dbg_async, vha, 0xf09e,
"BA_RJT was received for the ABTS rjt_vendorUnique = %u",
abt->fw.ba_rjt_vendorUnique);
ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09e,
@@ -819,18 +828,18 @@ void qla_nvme_abort_process_comp_status(struct abort_entry_24xx *abt, srb_t *ori
break;
case CS_COMPLETE:
- ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09f,
+ ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0xf09f,
"IOCB request is completed successfully comp_status=%x\n",
comp_status);
break;
case CS_IOCB_ERROR:
- ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf0a0,
+ ql_dbg(ql_dbg_async, vha, 0xf0a0,
"IOCB request is failed, comp_status=%x\n", comp_status);
break;
default:
- ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf0a1,
+ ql_dbg(ql_dbg_async, vha, 0xf0a1,
"Invalid Abort IO IOCB Completion Status %x\n",
comp_status);
break;
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 615e44af1ca6..11aad97dfca8 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -2166,7 +2166,6 @@ qla82xx_poll(int irq, void *dev_id)
struct qla_hw_data *ha;
struct rsp_que *rsp;
struct device_reg_82xx __iomem *reg;
- int status = 0;
uint32_t stat;
uint32_t host_int = 0;
uint16_t mb[8];
@@ -2195,7 +2194,6 @@ qla82xx_poll(int irq, void *dev_id)
case 0x10:
case 0x11:
qla82xx_mbx_completion(vha, MSW(stat));
- status |= MBX_INTERRUPT;
break;
case 0x12:
mb[0] = MSW(stat);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index cedd558f65eb..d2e40aaba734 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/blk-mq-pci.h>
#include <linux/refcount.h>
+#include <linux/crash_dump.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
@@ -53,6 +54,11 @@ static struct kmem_cache *ctx_cachep;
*/
uint ql_errlev = 0x8001;
+int ql2xsecenable;
+module_param(ql2xsecenable, int, S_IRUGO);
+MODULE_PARM_DESC(ql2xsecenable,
+ "Enable/disable security. 0(Default) - Security disabled. 1 - Security enabled.");
+
static int ql2xenableclass2;
module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xenableclass2,
@@ -849,7 +855,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
uint16_t hwq;
struct qla_qpair *qpair = NULL;
- tag = blk_mq_unique_tag(cmd->request);
+ tag = blk_mq_unique_tag(scsi_cmd_to_rq(cmd));
hwq = blk_mq_unique_tag_to_hwq(tag);
qpair = ha->queue_pair_map[hwq];
@@ -1120,12 +1126,28 @@ static inline int test_fcport_count(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
int res;
+ /* Return 0 = sleep, x=wake */
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ql_dbg(ql_dbg_init, vha, 0x00ec,
"tgt %p, fcport_count=%d\n",
vha, vha->fcport_count);
res = (vha->fcport_count == 0);
+ if (res) {
+ struct fc_port *fcport;
+
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->deleted != QLA_SESS_DELETED) {
+ /* session(s) may not be fully logged in
+ * (ie fcport_count=0), but session
+ * deletion thread(s) may be inflight.
+ */
+
+ res = 0;
+ break;
+ }
+ }
+ }
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return res;
@@ -1367,18 +1389,27 @@ static char *reset_errors[] = {
};
static int
-__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
- struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, uint64_t, int))
+qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
{
- scsi_qla_host_t *vha = shost_priv(cmd->device->host);
- fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
+ struct scsi_device *sdev = cmd->device;
+ scsi_qla_host_t *vha = shost_priv(sdev->host);
+ struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+ fc_port_t *fcport = (struct fc_port *) sdev->hostdata;
+ struct qla_hw_data *ha = vha->hw;
int err;
+ if (qla2x00_isp_reg_stat(ha)) {
+ ql_log(ql_log_info, vha, 0x803e,
+ "PCI/Register disconnect, exiting.\n");
+ qla_pci_set_eeh_busy(vha);
+ return FAILED;
+ }
+
if (!fcport) {
return FAILED;
}
- err = fc_block_scsi_eh(cmd);
+ err = fc_block_rport(rport);
if (err != 0)
return err;
@@ -1386,8 +1417,8 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
return SUCCESS;
ql_log(ql_log_info, vha, 0x8009,
- "%s RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", name, vha->host_no,
- cmd->device->id, cmd->device->lun, cmd);
+ "DEVICE RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", vha->host_no,
+ sdev->id, sdev->lun, cmd);
err = 0;
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
@@ -1396,67 +1427,100 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
goto eh_reset_failed;
}
err = 2;
- if (do_reset(fcport, cmd->device->lun, 1)
+ if (ha->isp_ops->lun_reset(fcport, sdev->lun, 1)
!= QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x800c,
"do_reset failed for cmd=%p.\n", cmd);
goto eh_reset_failed;
}
err = 3;
- if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
- cmd->device->lun, type) != QLA_SUCCESS) {
+ if (qla2x00_eh_wait_for_pending_commands(vha, sdev->id,
+ sdev->lun, WAIT_LUN) != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x800d,
"wait for pending cmds failed for cmd=%p.\n", cmd);
goto eh_reset_failed;
}
ql_log(ql_log_info, vha, 0x800e,
- "%s RESET SUCCEEDED nexus:%ld:%d:%llu cmd=%p.\n", name,
- vha->host_no, cmd->device->id, cmd->device->lun, cmd);
+ "DEVICE RESET SUCCEEDED nexus:%ld:%d:%llu cmd=%p.\n",
+ vha->host_no, sdev->id, sdev->lun, cmd);
return SUCCESS;
eh_reset_failed:
ql_log(ql_log_info, vha, 0x800f,
- "%s RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n", name,
- reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun,
+ "DEVICE RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n",
+ reset_errors[err], vha->host_no, sdev->id, sdev->lun,
cmd);
vha->reset_cmd_err_cnt++;
return FAILED;
}
static int
-qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
+qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
{
- scsi_qla_host_t *vha = shost_priv(cmd->device->host);
+ struct scsi_device *sdev = cmd->device;
+ struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+ scsi_qla_host_t *vha = shost_priv(rport_to_shost(rport));
struct qla_hw_data *ha = vha->hw;
+ fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+ int err;
if (qla2x00_isp_reg_stat(ha)) {
- ql_log(ql_log_info, vha, 0x803e,
+ ql_log(ql_log_info, vha, 0x803f,
"PCI/Register disconnect, exiting.\n");
qla_pci_set_eeh_busy(vha);
return FAILED;
}
- return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
- ha->isp_ops->lun_reset);
-}
+ if (!fcport) {
+ return FAILED;
+ }
-static int
-qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
-{
- scsi_qla_host_t *vha = shost_priv(cmd->device->host);
- struct qla_hw_data *ha = vha->hw;
+ err = fc_block_rport(rport);
+ if (err != 0)
+ return err;
- if (qla2x00_isp_reg_stat(ha)) {
- ql_log(ql_log_info, vha, 0x803f,
- "PCI/Register disconnect, exiting.\n");
- qla_pci_set_eeh_busy(vha);
- return FAILED;
+ if (fcport->deleted)
+ return SUCCESS;
+
+ ql_log(ql_log_info, vha, 0x8009,
+ "TARGET RESET ISSUED nexus=%ld:%d cmd=%p.\n", vha->host_no,
+ sdev->id, cmd);
+
+ err = 0;
+ if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x800a,
+ "Wait for hba online failed for cmd=%p.\n", cmd);
+ goto eh_reset_failed;
}
+ err = 2;
+ if (ha->isp_ops->target_reset(fcport, 0, 0) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x800c,
+ "target_reset failed for cmd=%p.\n", cmd);
+ goto eh_reset_failed;
+ }
+ err = 3;
+ if (qla2x00_eh_wait_for_pending_commands(vha, sdev->id,
+ 0, WAIT_TARGET) != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x800d,
+ "wait for pending cmds failed for cmd=%p.\n", cmd);
+ goto eh_reset_failed;
+ }
+
+ ql_log(ql_log_info, vha, 0x800e,
+ "TARGET RESET SUCCEEDED nexus:%ld:%d cmd=%p.\n",
+ vha->host_no, sdev->id, cmd);
+
+ return SUCCESS;
- return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
- ha->isp_ops->target_reset);
+eh_reset_failed:
+ ql_log(ql_log_info, vha, 0x800f,
+ "TARGET RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n",
+ reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun,
+ cmd);
+ vha->reset_cmd_err_cnt++;
+ return FAILED;
}
/**************************************************************************
@@ -1478,7 +1542,6 @@ static int
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
{
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
- fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
int ret = FAILED;
unsigned int id;
uint64_t lun;
@@ -1494,15 +1557,6 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
id = cmd->device->id;
lun = cmd->device->lun;
- if (!fcport) {
- return ret;
- }
-
- ret = fc_block_scsi_eh(cmd);
- if (ret != 0)
- return ret;
- ret = FAILED;
-
if (qla2x00_chip_is_down(vha))
return ret;
@@ -1742,7 +1796,7 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res,
}
spin_lock_irqsave(qp->qp_lock_ptr, *flags);
- if (ret_cmd && blk_mq_request_started(cmd->request))
+ if (ret_cmd && blk_mq_request_started(scsi_cmd_to_rq(cmd)))
sp->done(sp, res);
} else {
sp->done(sp, res);
@@ -2818,6 +2872,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
return ret;
}
+ if (is_kdump_kernel()) {
+ ql2xmqsupport = 0;
+ ql2xallocfwdump = 0;
+ }
+
/* This may fail but that's ok */
pci_enable_pcie_error_reporting(pdev);
@@ -2835,6 +2894,17 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
spin_lock_init(&ha->tgt.sess_lock);
spin_lock_init(&ha->tgt.atio_lock);
+ spin_lock_init(&ha->sadb_lock);
+ INIT_LIST_HEAD(&ha->sadb_tx_index_list);
+ INIT_LIST_HEAD(&ha->sadb_rx_index_list);
+
+ spin_lock_init(&ha->sadb_fp_lock);
+
+ if (qla_edif_sadb_build_free_pool(ha)) {
+ kfree(ha);
+ goto disable_device;
+ }
+
atomic_set(&ha->nvme_active_aen_cnt, 0);
/* Clear our data area */
@@ -3033,8 +3103,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->portnum = PCI_FUNC(ha->pdev->devfn);
ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
- req_length = REQUEST_ENTRY_CNT_24XX;
- rsp_length = RESPONSE_ENTRY_CNT_2300;
+ req_length = REQUEST_ENTRY_CNT_83XX;
+ rsp_length = RESPONSE_ENTRY_CNT_83XX;
ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
@@ -3460,6 +3530,8 @@ skip_dpc:
return 0;
probe_failed:
+ qla_enode_stop(base_vha);
+ qla_edb_stop(base_vha);
if (base_vha->gnl.l) {
dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
base_vha->gnl.l, base_vha->gnl.ldma);
@@ -3762,6 +3834,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
base_vha->gnl.l = NULL;
+ qla_enode_stop(base_vha);
+ qla_edb_stop(base_vha);
vfree(base_vha->scan.l);
@@ -3795,7 +3869,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
qla2x00_free_sysfs_attr(base_vha, true);
fc_remove_host(base_vha->host);
- qlt_remove_target_resources(ha);
scsi_remove_host(base_vha->host);
@@ -3867,6 +3940,9 @@ qla2x00_free_device(scsi_qla_host_t *vha)
qla82xx_md_free(vha);
+ qla_edif_sadb_release_free_pool(ha);
+ qla_edif_sadb_release(ha);
+
qla2x00_free_queues(ha);
}
@@ -3919,6 +3995,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
qla2x00_schedule_rport_del(vha, fcport);
}
+
/*
* We may need to retry the login, so don't change the state of the
* port but do the retries.
@@ -3941,6 +4018,16 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha)
"Mark all dev lost\n");
list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->loop_id != FC_NO_LOOP_ID &&
+ (fcport->flags & FCF_FCP2_DEVICE) &&
+ fcport->port_type == FCT_TARGET &&
+ !qla2x00_reset_active(vha)) {
+ ql_dbg(ql_dbg_disc, vha, 0x211a,
+ "Delaying session delete for FCP2 flags 0x%x port_type = 0x%x port_id=%06x %phC",
+ fcport->flags, fcport->port_type,
+ fcport->d_id.b24, fcport->port_name);
+ continue;
+ }
fcport->scan_state = 0;
qlt_schedule_sess_for_deletion(fcport);
}
@@ -3972,15 +4059,20 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
struct req_que **req, struct rsp_que **rsp)
{
char name[16];
+ int rc;
ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
&ha->init_cb_dma, GFP_KERNEL);
if (!ha->init_cb)
goto fail;
- if (qlt_mem_alloc(ha) < 0)
+ rc = btree_init32(&ha->host_map);
+ if (rc)
goto fail_free_init_cb;
+ if (qlt_mem_alloc(ha) < 0)
+ goto fail_free_btree;
+
ha->gid_list = dma_alloc_coherent(&ha->pdev->dev,
qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL);
if (!ha->gid_list)
@@ -3990,7 +4082,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
if (!ha->srb_mempool)
goto fail_free_gid_list;
- if (IS_P3P_TYPE(ha)) {
+ if (IS_P3P_TYPE(ha) || IS_QLA27XX(ha) || (ql2xsecenable && IS_QLA28XX(ha))) {
/* Allocate cache for CT6 Ctx. */
if (!ctx_cachep) {
ctx_cachep = kmem_cache_create("qla2xxx_ctx",
@@ -4024,7 +4116,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
"init_cb=%p gid_list=%p, srb_mempool=%p s_dma_pool=%p.\n",
ha->init_cb, ha->gid_list, ha->srb_mempool, ha->s_dma_pool);
- if (IS_P3P_TYPE(ha) || ql2xenabledif) {
+ if (IS_P3P_TYPE(ha) || ql2xenabledif || (IS_QLA28XX(ha) && ql2xsecenable)) {
ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
DSD_LIST_DMA_POOL_SIZE, 8, 0);
if (!ha->dl_dma_pool) {
@@ -4264,8 +4356,36 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
goto fail_flt_buffer;
}
+ /* allocate the purex dma pool */
+ ha->purex_dma_pool = dma_pool_create(name, &ha->pdev->dev,
+ MAX_PAYLOAD, 8, 0);
+
+ if (!ha->purex_dma_pool) {
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b,
+ "Unable to allocate purex_dma_pool.\n");
+ goto fail_flt;
+ }
+
+ ha->elsrej.size = sizeof(struct fc_els_ls_rjt) + 16;
+ ha->elsrej.c = dma_alloc_coherent(&ha->pdev->dev,
+ ha->elsrej.size, &ha->elsrej.cdma, GFP_KERNEL);
+
+ if (!ha->elsrej.c) {
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0xffff,
+ "Alloc failed for els reject cmd.\n");
+ goto fail_elsrej;
+ }
+ ha->elsrej.c->er_cmd = ELS_LS_RJT;
+ ha->elsrej.c->er_reason = ELS_RJT_LOGIC;
+ ha->elsrej.c->er_explan = ELS_EXPL_UNAB_DATA;
return 0;
+fail_elsrej:
+ dma_pool_destroy(ha->purex_dma_pool);
+fail_flt:
+ dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE,
+ ha->flt, ha->flt_dma);
+
fail_flt_buffer:
dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE,
ha->sfp_data, ha->sfp_data_dma);
@@ -4356,6 +4476,8 @@ fail_free_gid_list:
ha->gid_list_dma = 0;
fail_free_tgt_mem:
qlt_mem_free(ha);
+fail_free_btree:
+ btree_destroy32(&ha->host_map);
fail_free_init_cb:
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb,
ha->init_cb_dma);
@@ -4772,10 +4894,21 @@ qla2x00_mem_free(struct qla_hw_data *ha)
ha->dif_bundl_pool = NULL;
qlt_mem_free(ha);
+ qla_remove_hostmap(ha);
if (ha->init_cb)
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
ha->init_cb, ha->init_cb_dma);
+
+ dma_pool_destroy(ha->purex_dma_pool);
+ ha->purex_dma_pool = NULL;
+
+ if (ha->elsrej.c) {
+ dma_free_coherent(&ha->pdev->dev, ha->elsrej.size,
+ ha->elsrej.c, ha->elsrej.cdma);
+ ha->elsrej.c = NULL;
+ }
+
ha->init_cb = NULL;
ha->init_cb_dma = 0;
@@ -4837,6 +4970,9 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
spin_lock_init(&vha->cmd_list_lock);
init_waitqueue_head(&vha->fcport_waitQ);
init_waitqueue_head(&vha->vref_waitq);
+ qla_enode_init(vha);
+ qla_edb_init(vha);
+
vha->gnl.size = sizeof(struct get_name_list_extended) *
(ha->max_loop_id + 1);
@@ -5080,6 +5216,11 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
WWN_SIZE);
fcport->fc4_type = e->u.new_sess.fc4_type;
+ if (NVME_PRIORITY(vha->hw, fcport))
+ fcport->do_prli_nvme = 1;
+ else
+ fcport->do_prli_nvme = 0;
+
if (e->u.new_sess.fc4_type & FS_FCP_IS_N2N) {
fcport->dm_login_expire = jiffies +
QLA_N2N_WAIT_TIME * HZ;
@@ -5327,6 +5468,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
e->u.fcport.fcport, false);
break;
+ case QLA_EVT_SA_REPLACE:
+ qla24xx_issue_sa_replace_iocb(vha, e);
+ break;
}
if (rc == EAGAIN) {
@@ -5376,6 +5520,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
if (atomic_read(&fcport->state) != FCS_ONLINE &&
fcport->login_retry) {
if (fcport->scan_state != QLA_FCPORT_FOUND ||
+ fcport->disc_state == DSC_LOGIN_AUTH_PEND ||
fcport->disc_state == DSC_LOGIN_COMPLETE)
continue;
@@ -7234,6 +7379,10 @@ qla2x00_timer(struct timer_list *t)
}
}
+ /* check if edif running */
+ if (vha->hw->flags.edif_enabled)
+ qla_edif_timer(vha);
+
/* Process any deferred work. */
if (!list_empty(&vha->work_list)) {
unsigned long flags;
@@ -7430,7 +7579,7 @@ static void qla_pci_error_cleanup(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
struct qla_qpair *qpair = NULL;
- struct scsi_qla_host *vp;
+ struct scsi_qla_host *vp, *tvp;
fc_port_t *fcport;
int i;
unsigned long flags;
@@ -7461,7 +7610,7 @@ static void qla_pci_error_cleanup(scsi_qla_host_t *vha)
qla2x00_mark_all_devices_lost(vha);
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
qla2x00_mark_all_devices_lost(vp);
@@ -7475,7 +7624,7 @@ static void qla_pci_error_cleanup(scsi_qla_host_t *vha)
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
list_for_each_entry(fcport, &vp->vp_fcports, list)
@@ -7887,7 +8036,7 @@ qla2x00_module_init(void)
BUILD_BUG_ON(sizeof(struct cmd_type_7_fx00) != 64);
BUILD_BUG_ON(sizeof(struct cmd_type_crc_2) != 64);
BUILD_BUG_ON(sizeof(struct ct_entry_24xx) != 64);
- BUILD_BUG_ON(sizeof(struct ct_fdmi1_hba_attributes) != 2344);
+ BUILD_BUG_ON(sizeof(struct ct_fdmi1_hba_attributes) != 2604);
BUILD_BUG_ON(sizeof(struct ct_fdmi2_hba_attributes) != 4424);
BUILD_BUG_ON(sizeof(struct ct_fdmi2_port_attributes) != 4164);
BUILD_BUG_ON(sizeof(struct ct_fdmi_hba_attr) != 260);
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 060c89237777..a0aeba69513d 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -2936,7 +2936,6 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
liter += dburst - 1;
faddr += dburst - 1;
dwptr += dburst - 1;
- continue;
}
write_protect:
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index eb47140a899f..b3478ed9b12e 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -184,8 +184,7 @@ static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked)
return QLA_SUCCESS;
}
-static inline
-struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
+struct scsi_qla_host *qla_find_host_by_d_id(struct scsi_qla_host *vha,
be_id_t d_id)
{
struct scsi_qla_host *host;
@@ -198,7 +197,7 @@ struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
key = be_to_port_id(d_id).b24;
- host = btree_lookup32(&vha->hw->tgt.host_map, key);
+ host = btree_lookup32(&vha->hw->host_map, key);
if (!host)
ql_dbg(ql_dbg_tgt_mgt + ql_dbg_verbose, vha, 0xf005,
"Unable to find host %06x\n", key);
@@ -299,7 +298,7 @@ static void qlt_try_to_dequeue_unknown_atios(struct scsi_qla_host *vha,
goto abort;
}
- host = qlt_find_host_by_d_id(vha, u->atio.u.isp24.fcp_hdr.d_id);
+ host = qla_find_host_by_d_id(vha, u->atio.u.isp24.fcp_hdr.d_id);
if (host != NULL) {
ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x502f,
"Requeuing unknown ATIO_TYPE7 %p\n", u);
@@ -348,7 +347,7 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
switch (atio->u.raw.entry_type) {
case ATIO_TYPE7:
{
- struct scsi_qla_host *host = qlt_find_host_by_d_id(vha,
+ struct scsi_qla_host *host = qla_find_host_by_d_id(vha,
atio->u.isp24.fcp_hdr.d_id);
if (unlikely(NULL == host)) {
ql_dbg(ql_dbg_tgt, vha, 0xe03e,
@@ -577,6 +576,18 @@ static void qla2x00_async_nack_sp_done(srb_t *sp, int res)
sp->fcport->logout_on_delete = 1;
sp->fcport->plogi_nack_done_deadline = jiffies + HZ;
sp->fcport->send_els_logo = 0;
+
+ if (sp->fcport->flags & FCF_FCSP_DEVICE) {
+ ql_dbg(ql_dbg_edif, vha, 0x20ef,
+ "%s %8phC edif: PLOGI- AUTH WAIT\n", __func__,
+ sp->fcport->port_name);
+ qla2x00_set_fcport_disc_state(sp->fcport,
+ DSC_LOGIN_AUTH_PEND);
+ qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE,
+ sp->fcport->d_id.b24);
+ qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_NEEDED, sp->fcport->d_id.b24,
+ 0, sp->fcport);
+ }
break;
case SRB_NACK_PRLI:
@@ -624,6 +635,9 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
case SRB_NACK_PLOGI:
fcport->fw_login_state = DSC_LS_PLOGI_PEND;
c = "PLOGI";
+ if (vha->hw->flags.edif_enabled &&
+ (le16_to_cpu(ntfy->u.isp24.flags) & NOTIFY24XX_FLAGS_FCSP))
+ fcport->flags |= FCF_FCSP_DEVICE;
break;
case SRB_NACK_PRLI:
fcport->fw_login_state = DSC_LS_PRLI_PEND;
@@ -693,7 +707,12 @@ void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
void qla24xx_delete_sess_fn(struct work_struct *work)
{
fc_port_t *fcport = container_of(work, struct fc_port, del_work);
- struct qla_hw_data *ha = fcport->vha->hw;
+ struct qla_hw_data *ha = NULL;
+
+ if (!fcport || !fcport->vha || !fcport->vha->hw)
+ return;
+
+ ha = fcport->vha->hw;
if (fcport->se_sess) {
ha->tgt.tgt_ops->shutdown_sess(fcport);
@@ -917,6 +936,11 @@ qlt_send_first_logo(struct scsi_qla_host *vha, qlt_port_logo_t *logo)
qlt_port_logo_t *tmp;
int res;
+ if (test_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags)) {
+ res = 0;
+ goto out;
+ }
+
mutex_lock(&vha->vha_tgt.tgt_mutex);
list_for_each_entry(tmp, &vha->logo_list, list) {
@@ -937,6 +961,7 @@ qlt_send_first_logo(struct scsi_qla_host *vha, qlt_port_logo_t *logo)
list_del(&logo->list);
mutex_unlock(&vha->vha_tgt.tgt_mutex);
+out:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf098,
"Finished LOGO to %02x:%02x:%02x, dropped %d cmds, res = %#x\n",
logo->id.b.domain, logo->id.b.area, logo->id.b.al_pa,
@@ -965,6 +990,21 @@ void qlt_free_session_done(struct work_struct *work)
sess->send_els_logo);
if (!IS_SW_RESV_ADDR(sess->d_id)) {
+ if (ha->flags.edif_enabled &&
+ (!own || own->iocb.u.isp24.status_subcode == ELS_PLOGI)) {
+ sess->edif.authok = 0;
+ if (!ha->flags.host_shutting_down) {
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s wwpn %8phC calling qla2x00_release_all_sadb\n",
+ __func__, sess->port_name);
+ qla2x00_release_all_sadb(vha, sess);
+ } else {
+ ql_dbg(ql_dbg_edif, vha, 0x911e,
+ "%s bypassing release_all_sadb\n",
+ __func__);
+ }
+ qla_edif_sess_down(vha, sess);
+ }
qla2x00_mark_device_lost(vha, sess, 0);
if (sess->send_els_logo) {
@@ -972,6 +1012,7 @@ void qlt_free_session_done(struct work_struct *work)
logo.id = sess->d_id;
logo.cmd_count = 0;
+ INIT_LIST_HEAD(&logo.list);
if (!own)
qlt_send_first_logo(vha, &logo);
sess->send_els_logo = 0;
@@ -982,6 +1023,7 @@ void qlt_free_session_done(struct work_struct *work)
if (!own ||
(own->iocb.u.isp24.status_subcode == ELS_PLOGI)) {
+ sess->logout_completed = 0;
rc = qla2x00_post_async_logout_work(vha, sess,
NULL);
if (rc != QLA_SUCCESS)
@@ -1278,8 +1320,8 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
qla24xx_chk_fcp_state(sess);
ql_dbg(ql_log_warn, sess->vha, 0xe001,
- "Scheduling sess %p for deletion %8phC\n",
- sess, sess->port_name);
+ "Scheduling sess %p for deletion %8phC fc4_type %x\n",
+ sess, sess->port_name, sess->fc4_type);
WARN_ON(!queue_work(sess->vha->hw->wq, &sess->del_work));
}
@@ -1720,6 +1762,12 @@ static void qlt_send_notify_ack(struct qla_qpair *qpair,
nack->u.isp24.srr_reject_code_expl = srr_explan;
nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
+ /* TODO qualify this with EDIF enable */
+ if (ntfy->u.isp24.status_subcode == ELS_PLOGI &&
+ (le16_to_cpu(ntfy->u.isp24.flags) & NOTIFY24XX_FLAGS_FCSP)) {
+ nack->u.isp24.flags |= cpu_to_le16(NOTIFY_ACK_FLAGS_FCSP);
+ }
+
ql_dbg(ql_dbg_tgt, vha, 0xe005,
"qla_target(%d): Sending 24xx Notify Ack %d\n",
vha->vp_idx, nack->u.isp24.status);
@@ -2571,6 +2619,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair,
struct ctio7_to_24xx *pkt;
struct atio_from_isp *atio = &prm->cmd->atio;
uint16_t temp;
+ struct qla_tgt_cmd *cmd = prm->cmd;
pkt = (struct ctio7_to_24xx *)qpair->req->ring_ptr;
prm->pkt = pkt;
@@ -2603,6 +2652,15 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair,
pkt->u.status0.ox_id = cpu_to_le16(temp);
pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset);
+ if (cmd->edif) {
+ if (cmd->dma_data_direction == DMA_TO_DEVICE)
+ prm->cmd->sess->edif.rx_bytes += cmd->bufflen;
+ if (cmd->dma_data_direction == DMA_FROM_DEVICE)
+ prm->cmd->sess->edif.tx_bytes += cmd->bufflen;
+
+ pkt->u.status0.edif_flags |= EF_EN_EDIF;
+ }
+
return 0;
}
@@ -3293,8 +3351,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
if (xmit_type & QLA_TGT_XMIT_STATUS) {
pkt->u.status0.scsi_status =
cpu_to_le16(prm.rq_result);
- pkt->u.status0.residual =
- cpu_to_le32(prm.residual);
+ if (!cmd->edif)
+ pkt->u.status0.residual =
+ cpu_to_le32(prm.residual);
+
pkt->u.status0.flags |= cpu_to_le16(
CTIO7_FLAGS_SEND_STATUS);
if (qlt_need_explicit_conf(cmd, 0)) {
@@ -3941,6 +4001,12 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
if (cmd == NULL)
return;
+ if ((le16_to_cpu(((struct ctio7_from_24xx *)ctio)->flags) & CTIO7_FLAGS_DATA_OUT) &&
+ cmd->sess) {
+ qlt_chk_edif_rx_sa_delete_pending(vha, cmd->sess,
+ (struct ctio7_from_24xx *)ctio);
+ }
+
se_cmd = &cmd->se_cmd;
cmd->cmd_sent_to_fw = 0;
@@ -4011,6 +4077,16 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
qlt_handle_dif_error(qpair, cmd, ctio);
return;
}
+
+ case CTIO_FAST_AUTH_ERR:
+ case CTIO_FAST_INCOMP_PAD_LEN:
+ case CTIO_FAST_INVALID_REQ:
+ case CTIO_FAST_SPI_ERR:
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
+ "qla_target(%d): CTIO with EDIF error status 0x%x received (state %x, se_cmd %p\n",
+ vha->vp_idx, status, cmd->state, se_cmd);
+ break;
+
default:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
"qla_target(%d): CTIO with error status 0x%x received (state %x, se_cmd %p\n",
@@ -4312,6 +4388,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
qlt_assign_qpair(vha, cmd);
cmd->reset_count = vha->hw->base_qpair->chip_reset;
cmd->vp_idx = vha->vp_idx;
+ cmd->edif = sess->edif.enable;
return cmd;
}
@@ -4727,6 +4804,34 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
goto out;
}
+ if (vha->hw->flags.edif_enabled &&
+ !(vha->e_dbell.db_flags & EDB_ACTIVE) &&
+ iocb->u.isp24.status_subcode == ELS_PLOGI &&
+ !(le16_to_cpu(iocb->u.isp24.flags) & NOTIFY24XX_FLAGS_FCSP)) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d Term INOT due to app not available lid=%d, NportID %06X ",
+ __func__, __LINE__, loop_id, port_id.b24);
+ qlt_send_term_imm_notif(vha, iocb, 1);
+ goto out;
+ }
+
+ if (vha->hw->flags.edif_enabled) {
+ if (!(vha->e_dbell.db_flags & EDB_ACTIVE)) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d Term INOT due to app not started lid=%d, NportID %06X ",
+ __func__, __LINE__, loop_id, port_id.b24);
+ qlt_send_term_imm_notif(vha, iocb, 1);
+ goto out;
+ } else if (iocb->u.isp24.status_subcode == ELS_PLOGI &&
+ !(le16_to_cpu(iocb->u.isp24.flags) & NOTIFY24XX_FLAGS_FCSP)) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d Term INOT due to unsecure lid=%d, NportID %06X ",
+ __func__, __LINE__, loop_id, port_id.b24);
+ qlt_send_term_imm_notif(vha, iocb, 1);
+ goto out;
+ }
+ }
+
pla = qlt_plogi_ack_find_add(vha, &port_id, iocb);
if (!pla) {
ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
@@ -4792,6 +4897,20 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
qlt_plogi_ack_link(vha, pla, sess, QLT_PLOGI_LINK_SAME_WWN);
sess->d_id = port_id;
sess->login_gen++;
+ sess->loop_id = loop_id;
+
+ if (iocb->u.isp24.status_subcode == ELS_PLOGI) {
+ /* remote port has assigned Port ID */
+ if (N2N_TOPO(vha->hw) && fcport_is_bigger(sess))
+ vha->d_id = sess->d_id;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %8phC - send port online\n",
+ __func__, sess->port_name);
+
+ qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE,
+ sess->d_id.b24);
+ }
if (iocb->u.isp24.status_subcode == ELS_PRLI) {
sess->fw_login_state = DSC_LS_PRLI_PEND;
@@ -4904,6 +5023,16 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
sess = qla2x00_find_fcport_by_wwpn(vha,
iocb->u.isp24.port_name, 1);
+ if (vha->hw->flags.edif_enabled && sess &&
+ (!(sess->flags & FCF_FCSP_DEVICE) ||
+ !sess->edif.authok)) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC Term PRLI due to unauthorize PRLI\n",
+ __func__, __LINE__, iocb->u.isp24.port_name);
+ qlt_send_term_imm_notif(vha, iocb, 1);
+ break;
+ }
+
if (sess && sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]) {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC Term PRLI due to PLOGI ACK not completed\n",
@@ -4952,6 +5081,16 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
bool delete = false;
int sec;
+ if (vha->hw->flags.edif_enabled && sess &&
+ (!(sess->flags & FCF_FCSP_DEVICE) ||
+ !sess->edif.authok)) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC Term PRLI due to unauthorize prli\n",
+ __func__, __LINE__, iocb->u.isp24.port_name);
+ qlt_send_term_imm_notif(vha, iocb, 1);
+ break;
+ }
+
spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
switch (sess->fw_login_state) {
case DSC_LS_PLOGI_PEND:
@@ -5141,7 +5280,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
}
/*
- * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
+ * ha->hardware_lock supposed to be held on entry.
+ * Might drop it, then reacquire.
*/
static void qlt_handle_imm_notify(struct scsi_qla_host *vha,
struct imm_ntfy_from_isp *iocb)
@@ -6444,15 +6584,15 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
return 0;
}
-void qlt_remove_target_resources(struct qla_hw_data *ha)
+void qla_remove_hostmap(struct qla_hw_data *ha)
{
struct scsi_qla_host *node;
u32 key = 0;
- btree_for_each_safe32(&ha->tgt.host_map, key, node)
- btree_remove32(&ha->tgt.host_map, key);
+ btree_for_each_safe32(&ha->host_map, key, node)
+ btree_remove32(&ha->host_map, key);
- btree_destroy32(&ha->tgt.host_map);
+ btree_destroy32(&ha->host_map);
}
static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
@@ -7080,8 +7220,7 @@ qlt_modify_vp_config(struct scsi_qla_host *vha,
void
qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
{
- int rc;
-
+ mutex_init(&base_vha->vha_tgt.tgt_mutex);
if (!QLA_TGT_MODE_ENABLED())
return;
@@ -7094,7 +7233,6 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out;
}
- mutex_init(&base_vha->vha_tgt.tgt_mutex);
mutex_init(&base_vha->vha_tgt.tgt_host_action_mutex);
INIT_LIST_HEAD(&base_vha->unknown_atio_list);
@@ -7103,11 +7241,6 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
qlt_clear_mode(base_vha);
- rc = btree_init32(&ha->tgt.host_map);
- if (rc)
- ql_log(ql_log_info, base_vha, 0xd03d,
- "Unable to initialize ha->host_map btree\n");
-
qlt_update_vp_map(base_vha, SET_VP_IDX);
}
@@ -7228,21 +7361,20 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
u32 key;
int rc;
- if (!QLA_TGT_MODE_ENABLED())
- return;
-
key = vha->d_id.b24;
switch (cmd) {
case SET_VP_IDX:
+ if (!QLA_TGT_MODE_ENABLED())
+ return;
vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha;
break;
case SET_AL_PA:
- slot = btree_lookup32(&vha->hw->tgt.host_map, key);
+ slot = btree_lookup32(&vha->hw->host_map, key);
if (!slot) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf018,
"Save vha in host_map %p %06x\n", vha, key);
- rc = btree_insert32(&vha->hw->tgt.host_map,
+ rc = btree_insert32(&vha->hw->host_map,
key, vha, GFP_ATOMIC);
if (rc)
ql_log(ql_log_info, vha, 0xd03e,
@@ -7252,17 +7384,19 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
}
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019,
"replace existing vha in host_map %p %06x\n", vha, key);
- btree_update32(&vha->hw->tgt.host_map, key, vha);
+ btree_update32(&vha->hw->host_map, key, vha);
break;
case RESET_VP_IDX:
+ if (!QLA_TGT_MODE_ENABLED())
+ return;
vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
break;
case RESET_AL_PA:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a,
"clear vha in host_map %p %06x\n", vha, key);
- slot = btree_lookup32(&vha->hw->tgt.host_map, key);
+ slot = btree_lookup32(&vha->hw->host_map, key);
if (slot)
- btree_remove32(&vha->hw->tgt.host_map, key);
+ btree_remove32(&vha->hw->host_map, key);
vha->d_id.b24 = 0;
break;
}
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 01620f3eab39..156b950ca7e7 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -176,6 +176,7 @@ struct nack_to_isp {
uint8_t reserved[2];
__le16 ox_id;
} __packed;
+#define NOTIFY_ACK_FLAGS_FCSP BIT_5
#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3
#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
#define NOTIFY_ACK_SRR_FLAGS_REJECT 1
@@ -238,6 +239,10 @@ struct ctio_to_2xxx {
#define CTIO_PORT_LOGGED_OUT 0x29
#define CTIO_PORT_CONF_CHANGED 0x2A
#define CTIO_SRR_RECEIVED 0x45
+#define CTIO_FAST_AUTH_ERR 0x63
+#define CTIO_FAST_INCOMP_PAD_LEN 0x65
+#define CTIO_FAST_INVALID_REQ 0x66
+#define CTIO_FAST_SPI_ERR 0x67
#endif
#ifndef CTIO_RET_TYPE
@@ -408,7 +413,16 @@ struct ctio7_to_24xx {
struct {
__le16 reserved1;
__le16 flags;
- __le32 residual;
+ union {
+ __le32 residual;
+ struct {
+ uint8_t rsvd1;
+ uint8_t edif_flags;
+#define EF_EN_EDIF BIT_0
+#define EF_NEW_SA BIT_1
+ uint16_t rsvd2;
+ };
+ };
__le16 ox_id;
__le16 scsi_status;
__le32 relative_offset;
@@ -446,7 +460,7 @@ struct ctio7_from_24xx {
uint8_t vp_index;
uint8_t reserved1[5];
__le32 exchange_address;
- __le16 reserved2;
+ __le16 edif_sa_index;
__le16 flags;
__le32 residual;
__le16 ox_id;
@@ -875,6 +889,7 @@ struct qla_tgt_cmd {
unsigned int term_exchg:1;
unsigned int cmd_sent_to_fw:1;
unsigned int cmd_in_wq:1;
+ unsigned int edif:1;
/*
* This variable may be set from outside the LIO and I/O completion
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index da11829fa12d..055040cbef9b 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -6,9 +6,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "10.02.00.106-k"
+#define QLA2XXX_VERSION "10.02.06.200-k"
#define QLA_DRIVER_MAJOR_VER 10
#define QLA_DRIVER_MINOR_VER 2
-#define QLA_DRIVER_PATCH_VER 0
-#define QLA_DRIVER_BETA_VER 106
+#define QLA_DRIVER_PATCH_VER 6
+#define QLA_DRIVER_BETA_VER 200
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index f786ac2f5548..301bc09c8365 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -119,8 +119,8 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha)
* the interrupt_handler to think there are responses to be
* processed when there aren't.
*/
- ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0);
- ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0);
+ ha->shadow_regs->req_q_out = cpu_to_le32(0);
+ ha->shadow_regs->rsp_q_in = cpu_to_le32(0);
wmb();
writel(0, &ha->reg->req_q_in);
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index cbd1e6ffcd67..28eab07935ba 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -160,7 +160,7 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb,
if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
/* No data being transferred */
- cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0);
+ cmd_entry->ttlByteCnt = cpu_to_le32(0);
return;
}
@@ -288,7 +288,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
/* Acquire hardware specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
- index = (uint32_t)cmd->request->tag;
+ index = scsi_cmd_to_rq(cmd)->tag;
/*
* Check to see if adapter is online before placing request on
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 187d78aa4f67..cd71074f3abe 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -645,8 +645,8 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
/* Fill in the request and response queue information. */
init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out);
init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in);
- init_fw_cb->rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
- init_fw_cb->compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
+ init_fw_cb->rqq_len = cpu_to_le16(REQUEST_QUEUE_DEPTH);
+ init_fw_cb->compq_len = cpu_to_le16(RESPONSE_QUEUE_DEPTH);
init_fw_cb->rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
init_fw_cb->rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
init_fw_cb->compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
@@ -656,20 +656,20 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
/* Set up required options. */
init_fw_cb->fw_options |=
- __constant_cpu_to_le16(FWOPT_SESSION_MODE |
- FWOPT_INITIATOR_MODE);
+ cpu_to_le16(FWOPT_SESSION_MODE |
+ FWOPT_INITIATOR_MODE);
if (is_qla80XX(ha))
init_fw_cb->fw_options |=
- __constant_cpu_to_le16(FWOPT_ENABLE_CRBDB);
+ cpu_to_le16(FWOPT_ENABLE_CRBDB);
- init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
+ init_fw_cb->fw_options &= cpu_to_le16(~FWOPT_TARGET_MODE);
init_fw_cb->add_fw_options = 0;
init_fw_cb->add_fw_options |=
- __constant_cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);
+ cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);
init_fw_cb->add_fw_options |=
- __constant_cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);
+ cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);
if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
!= QLA_SUCCESS) {
@@ -1613,7 +1613,7 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
- chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
+ chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE);
exit_get_chap:
dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
@@ -1655,7 +1655,7 @@ int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password,
chap_table->secret_len = strlen(password);
strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN - 1);
strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN - 1);
- chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
+ chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE);
if (is_qla40XX(ha)) {
chap_size = MAX_CHAP_ENTRIES_40XX * sizeof(*chap_table);
@@ -1721,7 +1721,7 @@ int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username,
mutex_lock(&ha->chap_sem);
chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index;
- if (chap_table->cookie != __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ if (chap_table->cookie != cpu_to_le16(CHAP_VALID_COOKIE)) {
rval = QLA_ERROR;
goto exit_unlock_uni_chap;
}
@@ -1784,7 +1784,7 @@ int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
for (i = 0; i < max_chap_entries; i++) {
chap_table = (struct ql4_chap_table *)ha->chap_list + i;
if (chap_table->cookie !=
- __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ cpu_to_le16(CHAP_VALID_COOKIE)) {
if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
free_index = i;
continue;
@@ -2105,18 +2105,18 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
if (conn->max_recv_dlength)
fw_ddb_entry->iscsi_max_rcv_data_seg_len =
- __constant_cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));
+ cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));
if (sess->max_r2t)
fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);
if (sess->first_burst)
fw_ddb_entry->iscsi_first_burst_len =
- __constant_cpu_to_le16((sess->first_burst / BYTE_UNITS));
+ cpu_to_le16((sess->first_burst / BYTE_UNITS));
if (sess->max_burst)
fw_ddb_entry->iscsi_max_burst_len =
- __constant_cpu_to_le16((sess->max_burst / BYTE_UNITS));
+ cpu_to_le16((sess->max_burst / BYTE_UNITS));
if (sess->time2wait)
fw_ddb_entry->iscsi_def_time2wait =
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 66a487795c53..47adff9f0506 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -3658,7 +3658,7 @@ qla4_82xx_read_flash_data(struct scsi_qla_host *ha, uint32_t *dwptr,
"Do ROM fast read failed\n");
goto done_read;
}
- dwptr[i] = __constant_cpu_to_le32(val);
+ dwptr[i] = cpu_to_le32(val);
}
done_read:
@@ -3721,9 +3721,9 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
goto no_flash_data;
}
- if (*wptr == __constant_cpu_to_le16(0xffff))
+ if (*wptr == cpu_to_le16(0xffff))
goto no_flash_data;
- if (flt->version != __constant_cpu_to_le16(1)) {
+ if (flt->version != cpu_to_le16(1)) {
DEBUG2(ql4_printk(KERN_INFO, ha, "Unsupported FLT detected: "
"version=0x%x length=0x%x checksum=0x%x.\n",
le16_to_cpu(flt->version), le16_to_cpu(flt->length),
@@ -3826,7 +3826,7 @@ qla4_82xx_get_fdt_info(struct scsi_qla_host *ha)
qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring,
hw->flt_region_fdt << 2, OPTROM_BURST_SIZE);
- if (*wptr == __constant_cpu_to_le16(0xffff))
+ if (*wptr == cpu_to_le16(0xffff))
goto no_flash_data;
if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' ||
@@ -3883,7 +3883,7 @@ qla4_82xx_get_idc_param(struct scsi_qla_host *ha)
qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring,
QLA82XX_IDC_PARAM_ADDR , 8);
- if (*wptr == __constant_cpu_to_le32(0xffffffff)) {
+ if (*wptr == cpu_to_le32(0xffffffff)) {
ha->nx_dev_init_timeout = ROM_DEV_INIT_TIMEOUT;
ha->nx_reset_timeout = ROM_DRV_RESET_ACK_TIMEOUT;
} else {
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 6ee7ea4c27e0..f1ea65c6e5f5 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -702,7 +702,7 @@ static int qla4xxx_get_chap_by_index(struct scsi_qla_host *ha,
*chap_entry = (struct ql4_chap_table *)ha->chap_list + chap_index;
if ((*chap_entry)->cookie !=
- __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ cpu_to_le16(CHAP_VALID_COOKIE)) {
*chap_entry = NULL;
} else {
rval = QLA_SUCCESS;
@@ -745,7 +745,7 @@ static int qla4xxx_find_free_chap_index(struct scsi_qla_host *ha,
chap_table = (struct ql4_chap_table *)ha->chap_list + i;
if ((chap_table->cookie !=
- __constant_cpu_to_le16(CHAP_VALID_COOKIE)) &&
+ cpu_to_le16(CHAP_VALID_COOKIE)) &&
(i > MAX_RESRV_CHAP_IDX)) {
free_index = i;
break;
@@ -794,7 +794,7 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,
for (i = chap_tbl_idx; i < max_chap_entries; i++) {
chap_table = (struct ql4_chap_table *)ha->chap_list + i;
if (chap_table->cookie !=
- __constant_cpu_to_le16(CHAP_VALID_COOKIE))
+ cpu_to_le16(CHAP_VALID_COOKIE))
continue;
chap_rec->chap_tbl_idx = i;
@@ -923,7 +923,7 @@ static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx)
goto exit_delete_chap;
}
- chap_table->cookie = __constant_cpu_to_le16(0xFFFF);
+ chap_table->cookie = cpu_to_le16(0xFFFF);
offset = FLASH_CHAP_OFFSET |
(chap_tbl_idx * sizeof(struct ql4_chap_table));
@@ -6043,7 +6043,7 @@ static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,
for (i = 0; i < max_chap_entries; i++) {
chap_table = (struct ql4_chap_table *)ha->chap_list + i;
if (chap_table->cookie !=
- __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ cpu_to_le16(CHAP_VALID_COOKIE)) {
continue;
}
@@ -9282,7 +9282,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
DEBUG2(printk(KERN_INFO
"scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x,"
"dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no,
- cmd, jiffies, cmd->request->timeout / HZ,
+ cmd, jiffies, scsi_cmd_to_rq(cmd)->timeout / HZ,
ha->dpc_flags, cmd->result, cmd->allowed));
rval = qla4xxx_isp_check_reg(ha);
@@ -9349,7 +9349,7 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
DEBUG2(printk(KERN_INFO
"scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
"to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
- ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
+ ha->host_no, cmd, jiffies, scsi_cmd_to_rq(cmd)->timeout / HZ,
ha->dpc_flags, cmd->result, cmd->allowed));
rval = qla4xxx_isp_check_reg(ha);
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index d84e218d32cb..8e7e833a36cc 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -890,7 +890,7 @@ static inline void cmd_frob(struct Command_Entry *cmd, struct scsi_cmnd *Cmnd,
cmd->control_flags |= CFLAG_WRITE;
else
cmd->control_flags |= CFLAG_READ;
- cmd->time_out = Cmnd->request->timeout/HZ;
+ cmd->time_out = scsi_cmd_to_rq(Cmnd)->timeout / HZ;
memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
}
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index d26025cf5de3..b241f9e3885c 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -190,7 +190,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
"(result %x)\n", cmd->result));
good_bytes = scsi_bufflen(cmd);
- if (!blk_rq_is_passthrough(cmd->request)) {
+ if (!blk_rq_is_passthrough(scsi_cmd_to_rq(cmd))) {
int old_good_bytes = good_bytes;
drv = scsi_cmd_to_driver(cmd);
if (drv->done)
diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
new file mode 100644
index 000000000000..81c3853a2a80
--- /dev/null
+++ b/drivers/scsi/scsi_bsg.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bsg.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/sg.h>
+#include "scsi_priv.h"
+
+#define uptr64(val) ((void __user *)(uintptr_t)(val))
+
+static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
+ fmode_t mode, unsigned int timeout)
+{
+ struct scsi_request *sreq;
+ struct request *rq;
+ struct bio *bio;
+ int ret;
+
+ if (hdr->protocol != BSG_PROTOCOL_SCSI ||
+ hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_CMD)
+ return -EINVAL;
+ if (hdr->dout_xfer_len && hdr->din_xfer_len) {
+ pr_warn_once("BIDI support in bsg has been removed.\n");
+ return -EOPNOTSUPP;
+ }
+
+ rq = blk_get_request(q, hdr->dout_xfer_len ?
+ REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
+ if (IS_ERR(rq))
+ return PTR_ERR(rq);
+ rq->timeout = timeout;
+
+ ret = -ENOMEM;
+ sreq = scsi_req(rq);
+ sreq->cmd_len = hdr->request_len;
+ if (sreq->cmd_len > BLK_MAX_CDB) {
+ sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL);
+ if (!sreq->cmd)
+ goto out_put_request;
+ }
+
+ ret = -EFAULT;
+ if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len))
+ goto out_free_cmd;
+ ret = -EPERM;
+ if (!scsi_cmd_allowed(sreq->cmd, mode))
+ goto out_free_cmd;
+
+ ret = 0;
+ if (hdr->dout_xfer_len) {
+ ret = blk_rq_map_user(rq->q, rq, NULL, uptr64(hdr->dout_xferp),
+ hdr->dout_xfer_len, GFP_KERNEL);
+ } else if (hdr->din_xfer_len) {
+ ret = blk_rq_map_user(rq->q, rq, NULL, uptr64(hdr->din_xferp),
+ hdr->din_xfer_len, GFP_KERNEL);
+ }
+
+ if (ret)
+ goto out_free_cmd;
+
+ bio = rq->bio;
+ blk_execute_rq(NULL, rq, !(hdr->flags & BSG_FLAG_Q_AT_TAIL));
+
+ /*
+ * fill in all the output members
+ */
+ hdr->device_status = sreq->result & 0xff;
+ hdr->transport_status = host_byte(sreq->result);
+ hdr->driver_status = 0;
+ if (scsi_status_is_check_condition(sreq->result))
+ hdr->driver_status = DRIVER_SENSE;
+ hdr->info = 0;
+ if (hdr->device_status || hdr->transport_status || hdr->driver_status)
+ hdr->info |= SG_INFO_CHECK;
+ hdr->response_len = 0;
+
+ if (sreq->sense_len && hdr->response) {
+ int len = min_t(unsigned int, hdr->max_response_len,
+ sreq->sense_len);
+
+ if (copy_to_user(uptr64(hdr->response), sreq->sense, len))
+ ret = -EFAULT;
+ else
+ hdr->response_len = len;
+ }
+
+ if (rq_data_dir(rq) == READ)
+ hdr->din_resid = sreq->resid_len;
+ else
+ hdr->dout_resid = sreq->resid_len;
+
+ blk_rq_unmap_user(bio);
+
+out_free_cmd:
+ scsi_req_free_cmd(scsi_req(rq));
+out_put_request:
+ blk_put_request(rq);
+ return ret;
+}
+
+struct bsg_device *scsi_bsg_register_queue(struct scsi_device *sdev)
+{
+ return bsg_register_queue(sdev->request_queue, &sdev->sdev_gendev,
+ dev_name(&sdev->sdev_gendev), scsi_bsg_sg_io_fn);
+}
diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c
index 90349498f686..6e50e81a8216 100644
--- a/drivers/scsi/scsi_common.c
+++ b/drivers/scsi/scsi_common.c
@@ -7,9 +7,18 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/module.h>
#include <asm/unaligned.h>
#include <scsi/scsi_common.h>
+MODULE_LICENSE("GPL v2");
+
+/* Command group 3 is reserved and should never be used. */
+const unsigned char scsi_command_size_tbl[8] = {
+ 6, 10, 10, 12, 16, 12, 10, 10
+};
+EXPORT_SYMBOL(scsi_command_size_tbl);
+
/* NB: These are exposed through /proc/scsi/scsi and form part of the ABI.
* You may not alter any existing entry (although adding new ones is
* encouraged once assigned by ANSI/INCITS T10).
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 5b3a20a140f9..66f507469a31 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3076,6 +3076,7 @@ static void dif_copy_prot(struct scsi_cmnd *scp, sector_t sector,
static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec,
unsigned int sectors, u32 ei_lba)
{
+ int ret = 0;
unsigned int i;
sector_t sector;
struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *)
@@ -3083,26 +3084,33 @@ static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec,
struct t10_pi_tuple *sdt;
for (i = 0; i < sectors; i++, ei_lba++) {
- int ret;
-
sector = start_sec + i;
sdt = dif_store(sip, sector);
if (sdt->app_tag == cpu_to_be16(0xffff))
continue;
- ret = dif_verify(sdt, lba2fake_store(sip, sector), sector,
- ei_lba);
- if (ret) {
- dif_errors++;
- return ret;
+ /*
+ * Because scsi_debug acts as both initiator and
+ * target we proceed to verify the PI even if
+ * RDPROTECT=3. This is done so the "initiator" knows
+ * which type of error to return. Otherwise we would
+ * have to iterate over the PI twice.
+ */
+ if (scp->cmnd[1] >> 5) { /* RDPROTECT */
+ ret = dif_verify(sdt, lba2fake_store(sip, sector),
+ sector, ei_lba);
+ if (ret) {
+ dif_errors++;
+ break;
+ }
}
}
dif_copy_prot(scp, start_sec, sectors, true);
dix_reads++;
- return 0;
+ return ret;
}
static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
@@ -3196,12 +3204,29 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
/* DIX + T10 DIF */
if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
- int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
-
- if (prot_ret) {
- read_unlock(macc_lckp);
- mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret);
- return illegal_condition_result;
+ switch (prot_verify_read(scp, lba, num, ei_lba)) {
+ case 1: /* Guard tag error */
+ if (cmd[1] >> 5 != 3) { /* RDPROTECT != 3 */
+ read_unlock(macc_lckp);
+ mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+ return check_condition_result;
+ } else if (scp->prot_flags & SCSI_PROT_GUARD_CHECK) {
+ read_unlock(macc_lckp);
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+ return illegal_condition_result;
+ }
+ break;
+ case 3: /* Reference tag error */
+ if (cmd[1] >> 5 != 3) { /* RDPROTECT != 3 */
+ read_unlock(macc_lckp);
+ mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 3);
+ return check_condition_result;
+ } else if (scp->prot_flags & SCSI_PROT_REF_CHECK) {
+ read_unlock(macc_lckp);
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 3);
+ return illegal_condition_result;
+ }
+ break;
}
}
@@ -3232,28 +3257,6 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
return 0;
}
-static void dump_sector(unsigned char *buf, int len)
-{
- int i, j, n;
-
- pr_err(">>> Sector Dump <<<\n");
- for (i = 0 ; i < len ; i += 16) {
- char b[128];
-
- for (j = 0, n = 0; j < 16; j++) {
- unsigned char c = buf[i+j];
-
- if (c >= 0x20 && c < 0x7e)
- n += scnprintf(b + n, sizeof(b) - n,
- " %c ", buf[i+j]);
- else
- n += scnprintf(b + n, sizeof(b) - n,
- "%02x ", buf[i+j]);
- }
- pr_err("%04d: %s\n", i, b);
- }
-}
-
static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
unsigned int sectors, u32 ei_lba)
{
@@ -3299,10 +3302,10 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
sdt = piter.addr + ppage_offset;
daddr = diter.addr + dpage_offset;
- ret = dif_verify(sdt, daddr, sector, ei_lba);
- if (ret) {
- dump_sector(daddr, sdebug_sector_size);
- goto out;
+ if (SCpnt->cmnd[1] >> 5 != 3) { /* WRPROTECT */
+ ret = dif_verify(sdt, daddr, sector, ei_lba);
+ if (ret)
+ goto out;
}
sector++;
@@ -3480,12 +3483,29 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
/* DIX + T10 DIF */
if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
- int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
-
- if (prot_ret) {
- write_unlock(macc_lckp);
- mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret);
- return illegal_condition_result;
+ switch (prot_verify_write(scp, lba, num, ei_lba)) {
+ case 1: /* Guard tag error */
+ if (scp->prot_flags & SCSI_PROT_GUARD_CHECK) {
+ write_unlock(macc_lckp);
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+ return illegal_condition_result;
+ } else if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
+ write_unlock(macc_lckp);
+ mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+ return check_condition_result;
+ }
+ break;
+ case 3: /* Reference tag error */
+ if (scp->prot_flags & SCSI_PROT_REF_CHECK) {
+ write_unlock(macc_lckp);
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 3);
+ return illegal_condition_result;
+ } else if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
+ write_unlock(macc_lckp);
+ mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 3);
+ return check_condition_result;
+ }
+ break;
}
}
@@ -4702,7 +4722,7 @@ fini:
static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd)
{
u16 hwq;
- u32 tag = blk_mq_unique_tag(cmnd->request);
+ u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(cmnd));
hwq = blk_mq_unique_tag_to_hwq(tag);
@@ -4715,7 +4735,7 @@ static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd)
static u32 get_tag(struct scsi_cmnd *cmnd)
{
- return blk_mq_unique_tag(cmnd->request);
+ return blk_mq_unique_tag(scsi_cmd_to_rq(cmnd));
}
/* Queued (deferred) command completions converge here. */
@@ -5364,7 +5384,7 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
{
bool new_sd_dp;
bool inject = false;
- bool hipri = (cmnd->request->cmd_flags & REQ_HIPRI);
+ bool hipri = scsi_cmd_to_rq(cmnd)->cmd_flags & REQ_HIPRI;
int k, num_in_q, qdepth;
unsigned long iflags;
u64 ns_from_boot = 0;
@@ -5567,8 +5587,9 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
if (sdebug_statistics)
sd_dp->issuing_cpu = raw_smp_processor_id();
if (unlikely(sd_dp->aborted)) {
- sdev_printk(KERN_INFO, sdp, "abort request tag %d\n", cmnd->request->tag);
- blk_abort_request(cmnd->request);
+ sdev_printk(KERN_INFO, sdp, "abort request tag %d\n",
+ scsi_cmd_to_rq(cmnd)->tag);
+ blk_abort_request(scsi_cmd_to_rq(cmnd));
atomic_set(&sdeb_inject_pending, 0);
sd_dp->aborted = false;
}
@@ -7394,7 +7415,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
(u32)cmd[k]);
}
sdev_printk(KERN_INFO, sdp, "%s: tag=%#x, cmd %s\n", my_name,
- blk_mq_unique_tag(scp->request), b);
+ blk_mq_unique_tag(scsi_cmd_to_rq(scp)), b);
}
if (unlikely(inject_now && (sdebug_opts & SDEBUG_OPT_HOST_BUSY)))
return SCSI_MLQUEUE_HOST_BUSY;
@@ -7674,7 +7695,7 @@ static int sdebug_driver_probe(struct device *dev)
return error;
}
-static int sdebug_driver_remove(struct device *dev)
+static void sdebug_driver_remove(struct device *dev)
{
struct sdebug_host_info *sdbg_host;
struct sdebug_dev_info *sdbg_devinfo, *tmp;
@@ -7691,7 +7712,6 @@ static int sdebug_driver_remove(struct device *dev)
}
scsi_host_put(sdbg_host->shost);
- return 0;
}
static int pseudo_lld_bus_match(struct device *dev,
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index d33355ab6e14..c7080454aea9 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -171,6 +171,7 @@ static struct {
{"FUJITSU", "ETERNUS_DXM", "*", BLIST_RETRY_ASC_C1},
{"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN | BLIST_INQUIRY_36},
{"Generic", "USB Storage-SMC", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36}, /* FW: 0180 and 0207 */
+ {"Generic", "Ultra HS-SD/MMC", "2.09", BLIST_IGN_MEDIA_CHANGE | BLIST_INQUIRY_36},
{"HITACHI", "DF400", "*", BLIST_REPORTLUN2},
{"HITACHI", "DF500", "*", BLIST_REPORTLUN2},
{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 58a252c38992..b6c86cce57bf 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -242,7 +242,7 @@ scsi_abort_command(struct scsi_cmnd *scmd)
*/
static void scsi_eh_reset(struct scsi_cmnd *scmd)
{
- if (!blk_rq_is_passthrough(scmd->request)) {
+ if (!blk_rq_is_passthrough(scsi_cmd_to_rq(scmd))) {
struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
if (sdrv->eh_reset)
sdrv->eh_reset(scmd);
@@ -1182,7 +1182,7 @@ static enum scsi_disposition scsi_request_sense(struct scsi_cmnd *scmd)
static enum scsi_disposition
scsi_eh_action(struct scsi_cmnd *scmd, enum scsi_disposition rtn)
{
- if (!blk_rq_is_passthrough(scmd->request)) {
+ if (!blk_rq_is_passthrough(scsi_cmd_to_rq(scmd))) {
struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
if (sdrv->eh_action)
rtn = sdrv->eh_action(scmd, rtn);
@@ -1750,21 +1750,23 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
*/
int scsi_noretry_cmd(struct scsi_cmnd *scmd)
{
+ struct request *req = scsi_cmd_to_rq(scmd);
+
switch (host_byte(scmd->result)) {
case DID_OK:
break;
case DID_TIME_OUT:
goto check_type;
case DID_BUS_BUSY:
- return (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT);
+ return req->cmd_flags & REQ_FAILFAST_TRANSPORT;
case DID_PARITY:
- return (scmd->request->cmd_flags & REQ_FAILFAST_DEV);
+ return req->cmd_flags & REQ_FAILFAST_DEV;
case DID_ERROR:
if (get_status_byte(scmd) == SAM_STAT_RESERVATION_CONFLICT)
return 0;
fallthrough;
case DID_SOFT_ERROR:
- return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER);
+ return req->cmd_flags & REQ_FAILFAST_DRIVER;
}
if (!scsi_status_is_check_condition(scmd->result))
@@ -1775,8 +1777,7 @@ check_type:
* assume caller has checked sense and determined
* the check condition was retryable.
*/
- if (scmd->request->cmd_flags & REQ_FAILFAST_DEV ||
- blk_rq_is_passthrough(scmd->request))
+ if (req->cmd_flags & REQ_FAILFAST_DEV || blk_rq_is_passthrough(req))
return 1;
return 0;
@@ -2376,7 +2377,6 @@ scsi_ioctl_reset(struct scsi_device *dev, int __user *arg)
scmd = (struct scsi_cmnd *)(rq + 1);
scsi_init_command(dev, scmd);
- scmd->request = rq;
scmd->cmnd = scsi_req(rq)->cmd;
scmd->scsi_done = scsi_reset_provider_done_command;
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 0d13610cd6bf..6ff2207bd45a 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/uaccess.h>
+#include <linux/cdrom.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -63,29 +64,6 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
return 1;
}
-/*
-
- * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
- * The IOCTL_NORMAL_TIMEOUT and NORMAL_RETRIES variables are used.
- *
- * dev is the SCSI device struct ptr, *(int *) arg is the length of the
- * input data, if any, not including the command string & counts,
- * *((int *)arg + 1) is the output buffer size in bytes.
- *
- * *(char *) ((int *) arg)[2] the actual command byte.
- *
- * Note that if more than MAX_BUF bytes are requested to be transferred,
- * the ioctl will fail with error EINVAL.
- *
- * This size *does not* include the initial lengths that were passed.
- *
- * The SCSI command is read from the memory location immediately after the
- * length words, and the input data is right after the command. The SCSI
- * routines know the command size based on the opcode decode.
- *
- * The output area is then filled in starting from the command byte.
- */
-
static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
int timeout, int retries)
{
@@ -189,10 +167,732 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg)
? -EFAULT: 0;
}
+static int sg_get_version(int __user *p)
+{
+ static const int sg_version_num = 30527;
+ return put_user(sg_version_num, p);
+}
-static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg)
+static int sg_set_timeout(struct scsi_device *sdev, int __user *p)
{
- char scsi_cmd[MAX_COMMAND_SIZE];
+ int timeout, err = get_user(timeout, p);
+
+ if (!err)
+ sdev->sg_timeout = clock_t_to_jiffies(timeout);
+
+ return err;
+}
+
+static int sg_get_reserved_size(struct scsi_device *sdev, int __user *p)
+{
+ int val = min(sdev->sg_reserved_size,
+ queue_max_bytes(sdev->request_queue));
+
+ return put_user(val, p);
+}
+
+static int sg_set_reserved_size(struct scsi_device *sdev, int __user *p)
+{
+ int size, err = get_user(size, p);
+
+ if (err)
+ return err;
+
+ if (size < 0)
+ return -EINVAL;
+
+ sdev->sg_reserved_size = min_t(unsigned int, size,
+ queue_max_bytes(sdev->request_queue));
+ return 0;
+}
+
+/*
+ * will always return that we are ATAPI even for a real SCSI drive, I'm not
+ * so sure this is worth doing anything about (why would you care??)
+ */
+static int sg_emulated_host(struct request_queue *q, int __user *p)
+{
+ return put_user(1, p);
+}
+
+static int scsi_get_idlun(struct scsi_device *sdev, void __user *argp)
+{
+ struct scsi_idlun v = {
+ .dev_id = (sdev->id & 0xff) +
+ ((sdev->lun & 0xff) << 8) +
+ ((sdev->channel & 0xff) << 16) +
+ ((sdev->host->host_no & 0xff) << 24),
+ .host_unique_id = sdev->host->unique_id
+ };
+ if (copy_to_user(argp, &v, sizeof(struct scsi_idlun)))
+ return -EFAULT;
+ return 0;
+}
+
+static int scsi_send_start_stop(struct scsi_device *sdev, int data)
+{
+ u8 cdb[MAX_COMMAND_SIZE] = { };
+
+ cdb[0] = START_STOP;
+ cdb[4] = data;
+ return ioctl_internal_command(sdev, cdb, START_STOP_TIMEOUT,
+ NORMAL_RETRIES);
+}
+
+/*
+ * Check if the given command is allowed.
+ *
+ * Only a subset of commands are allowed for unprivileged users. Commands used
+ * to format the media, update the firmware, etc. are not permitted.
+ */
+bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
+{
+ /* root can do any command. */
+ if (capable(CAP_SYS_RAWIO))
+ return true;
+
+ /* Anybody who can open the device can do a read-safe command */
+ switch (cmd[0]) {
+ /* Basic read-only commands */
+ case TEST_UNIT_READY:
+ case REQUEST_SENSE:
+ case READ_6:
+ case READ_10:
+ case READ_12:
+ case READ_16:
+ case READ_BUFFER:
+ case READ_DEFECT_DATA:
+ case READ_CAPACITY: /* also GPCMD_READ_CDVD_CAPACITY */
+ case READ_LONG:
+ case INQUIRY:
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ case LOG_SENSE:
+ case START_STOP:
+ case GPCMD_VERIFY_10:
+ case VERIFY_16:
+ case REPORT_LUNS:
+ case SERVICE_ACTION_IN_16:
+ case RECEIVE_DIAGNOSTIC:
+ case MAINTENANCE_IN: /* also GPCMD_SEND_KEY, which is a write command */
+ case GPCMD_READ_BUFFER_CAPACITY:
+ /* Audio CD commands */
+ case GPCMD_PLAY_CD:
+ case GPCMD_PLAY_AUDIO_10:
+ case GPCMD_PLAY_AUDIO_MSF:
+ case GPCMD_PLAY_AUDIO_TI:
+ case GPCMD_PAUSE_RESUME:
+ /* CD/DVD data reading */
+ case GPCMD_READ_CD:
+ case GPCMD_READ_CD_MSF:
+ case GPCMD_READ_DISC_INFO:
+ case GPCMD_READ_DVD_STRUCTURE:
+ case GPCMD_READ_HEADER:
+ case GPCMD_READ_TRACK_RZONE_INFO:
+ case GPCMD_READ_SUBCHANNEL:
+ case GPCMD_READ_TOC_PMA_ATIP:
+ case GPCMD_REPORT_KEY:
+ case GPCMD_SCAN:
+ case GPCMD_GET_CONFIGURATION:
+ case GPCMD_READ_FORMAT_CAPACITIES:
+ case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
+ case GPCMD_GET_PERFORMANCE:
+ case GPCMD_SEEK:
+ case GPCMD_STOP_PLAY_SCAN:
+ /* ZBC */
+ case ZBC_IN:
+ return true;
+ /* Basic writing commands */
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_VERIFY:
+ case WRITE_12:
+ case WRITE_VERIFY_12:
+ case WRITE_16:
+ case WRITE_LONG:
+ case WRITE_LONG_2:
+ case WRITE_SAME:
+ case WRITE_SAME_16:
+ case WRITE_SAME_32:
+ case ERASE:
+ case GPCMD_MODE_SELECT_10:
+ case MODE_SELECT:
+ case LOG_SELECT:
+ case GPCMD_BLANK:
+ case GPCMD_CLOSE_TRACK:
+ case GPCMD_FLUSH_CACHE:
+ case GPCMD_FORMAT_UNIT:
+ case GPCMD_REPAIR_RZONE_TRACK:
+ case GPCMD_RESERVE_RZONE_TRACK:
+ case GPCMD_SEND_DVD_STRUCTURE:
+ case GPCMD_SEND_EVENT:
+ case GPCMD_SEND_OPC:
+ case GPCMD_SEND_CUE_SHEET:
+ case GPCMD_SET_SPEED:
+ case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+ case GPCMD_LOAD_UNLOAD:
+ case GPCMD_SET_STREAMING:
+ case GPCMD_SET_READ_AHEAD:
+ /* ZBC */
+ case ZBC_OUT:
+ return (mode & FMODE_WRITE);
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL(scsi_cmd_allowed);
+
+static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq,
+ struct sg_io_hdr *hdr, fmode_t mode)
+{
+ struct scsi_request *req = scsi_req(rq);
+
+ if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len))
+ return -EFAULT;
+ if (!scsi_cmd_allowed(req->cmd, mode))
+ return -EPERM;
+
+ /*
+ * fill in request structure
+ */
+ req->cmd_len = hdr->cmd_len;
+
+ rq->timeout = msecs_to_jiffies(hdr->timeout);
+ if (!rq->timeout)
+ rq->timeout = sdev->sg_timeout;
+ if (!rq->timeout)
+ rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+ if (rq->timeout < BLK_MIN_SG_TIMEOUT)
+ rq->timeout = BLK_MIN_SG_TIMEOUT;
+
+ return 0;
+}
+
+static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
+ struct bio *bio)
+{
+ struct scsi_request *req = scsi_req(rq);
+ int r, ret = 0;
+
+ /*
+ * fill in all the output members
+ */
+ hdr->status = req->result & 0xff;
+ hdr->masked_status = status_byte(req->result);
+ hdr->msg_status = COMMAND_COMPLETE;
+ hdr->host_status = host_byte(req->result);
+ hdr->driver_status = 0;
+ if (scsi_status_is_check_condition(hdr->status))
+ hdr->driver_status = DRIVER_SENSE;
+ hdr->info = 0;
+ if (hdr->masked_status || hdr->host_status || hdr->driver_status)
+ hdr->info |= SG_INFO_CHECK;
+ hdr->resid = req->resid_len;
+ hdr->sb_len_wr = 0;
+
+ if (req->sense_len && hdr->sbp) {
+ int len = min((unsigned int) hdr->mx_sb_len, req->sense_len);
+
+ if (!copy_to_user(hdr->sbp, req->sense, len))
+ hdr->sb_len_wr = len;
+ else
+ ret = -EFAULT;
+ }
+
+ r = blk_rq_unmap_user(bio);
+ if (!ret)
+ ret = r;
+
+ return ret;
+}
+
+static int sg_io(struct scsi_device *sdev, struct gendisk *disk,
+ struct sg_io_hdr *hdr, fmode_t mode)
+{
+ unsigned long start_time;
+ ssize_t ret = 0;
+ int writing = 0;
+ int at_head = 0;
+ struct request *rq;
+ struct scsi_request *req;
+ struct bio *bio;
+
+ if (hdr->interface_id != 'S')
+ return -EINVAL;
+
+ if (hdr->dxfer_len > (queue_max_hw_sectors(sdev->request_queue) << 9))
+ return -EIO;
+
+ if (hdr->dxfer_len)
+ switch (hdr->dxfer_direction) {
+ default:
+ return -EINVAL;
+ case SG_DXFER_TO_DEV:
+ writing = 1;
+ break;
+ case SG_DXFER_TO_FROM_DEV:
+ case SG_DXFER_FROM_DEV:
+ break;
+ }
+ if (hdr->flags & SG_FLAG_Q_AT_HEAD)
+ at_head = 1;
+
+ ret = -ENOMEM;
+ rq = blk_get_request(sdev->request_queue, writing ?
+ REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
+ if (IS_ERR(rq))
+ return PTR_ERR(rq);
+ req = scsi_req(rq);
+
+ if (hdr->cmd_len > BLK_MAX_CDB) {
+ req->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
+ if (!req->cmd)
+ goto out_put_request;
+ }
+
+ ret = scsi_fill_sghdr_rq(sdev, rq, hdr, mode);
+ if (ret < 0)
+ goto out_free_cdb;
+
+ ret = 0;
+ if (hdr->iovec_count) {
+ struct iov_iter i;
+ struct iovec *iov = NULL;
+
+ ret = import_iovec(rq_data_dir(rq), hdr->dxferp,
+ hdr->iovec_count, 0, &iov, &i);
+ if (ret < 0)
+ goto out_free_cdb;
+
+ /* SG_IO howto says that the shorter of the two wins */
+ iov_iter_truncate(&i, hdr->dxfer_len);
+
+ ret = blk_rq_map_user_iov(rq->q, rq, NULL, &i, GFP_KERNEL);
+ kfree(iov);
+ } else if (hdr->dxfer_len)
+ ret = blk_rq_map_user(rq->q, rq, NULL, hdr->dxferp,
+ hdr->dxfer_len, GFP_KERNEL);
+
+ if (ret)
+ goto out_free_cdb;
+
+ bio = rq->bio;
+ req->retries = 0;
+
+ start_time = jiffies;
+
+ blk_execute_rq(disk, rq, at_head);
+
+ hdr->duration = jiffies_to_msecs(jiffies - start_time);
+
+ ret = scsi_complete_sghdr_rq(rq, hdr, bio);
+
+out_free_cdb:
+ scsi_req_free_cmd(req);
+out_put_request:
+ blk_put_request(rq);
+ return ret;
+}
+
+/**
+ * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
+ * @q: request queue to send scsi commands down
+ * @disk: gendisk to operate on (option)
+ * @mode: mode used to open the file through which the ioctl has been
+ * submitted
+ * @sic: userspace structure describing the command to perform
+ *
+ * Send down the scsi command described by @sic to the device below
+ * the request queue @q. If @file is non-NULL it's used to perform
+ * fine-grained permission checks that allow users to send down
+ * non-destructive SCSI commands. If the caller has a struct gendisk
+ * available it should be passed in as @disk to allow the low level
+ * driver to use the information contained in it. A non-NULL @disk
+ * is only allowed if the caller knows that the low level driver doesn't
+ * need it (e.g. in the scsi subsystem).
+ *
+ * Notes:
+ * - This interface is deprecated - users should use the SG_IO
+ * interface instead, as this is a more flexible approach to
+ * performing SCSI commands on a device.
+ * - The SCSI command length is determined by examining the 1st byte
+ * of the given command. There is no way to override this.
+ * - Data transfers are limited to PAGE_SIZE
+ * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
+ * accommodate the sense buffer when an error occurs.
+ * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
+ * old code will not be surprised.
+ * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
+ * a negative return and the Unix error code in 'errno'.
+ * If the SCSI command succeeds then 0 is returned.
+ * Positive numbers returned are the compacted SCSI error codes (4
+ * bytes in one int) where the lowest byte is the SCSI status.
+ */
+static int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk,
+ fmode_t mode, struct scsi_ioctl_command __user *sic)
+{
+ enum { OMAX_SB_LEN = 16 }; /* For backward compatibility */
+ struct request *rq;
+ struct scsi_request *req;
+ int err;
+ unsigned int in_len, out_len, bytes, opcode, cmdlen;
+ char *buffer = NULL;
+
+ if (!sic)
+ return -EINVAL;
+
+ /*
+ * get in an out lengths, verify they don't exceed a page worth of data
+ */
+ if (get_user(in_len, &sic->inlen))
+ return -EFAULT;
+ if (get_user(out_len, &sic->outlen))
+ return -EFAULT;
+ if (in_len > PAGE_SIZE || out_len > PAGE_SIZE)
+ return -EINVAL;
+ if (get_user(opcode, sic->data))
+ return -EFAULT;
+
+ bytes = max(in_len, out_len);
+ if (bytes) {
+ buffer = kzalloc(bytes, GFP_NOIO | GFP_USER | __GFP_NOWARN);
+ if (!buffer)
+ return -ENOMEM;
+
+ }
+
+ rq = blk_get_request(q, in_len ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
+ if (IS_ERR(rq)) {
+ err = PTR_ERR(rq);
+ goto error_free_buffer;
+ }
+ req = scsi_req(rq);
+
+ cmdlen = COMMAND_SIZE(opcode);
+
+ /*
+ * get command and data to send to device, if any
+ */
+ err = -EFAULT;
+ req->cmd_len = cmdlen;
+ if (copy_from_user(req->cmd, sic->data, cmdlen))
+ goto error;
+
+ if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
+ goto error;
+
+ err = -EPERM;
+ if (!scsi_cmd_allowed(req->cmd, mode))
+ goto error;
+
+ /* default. possible overridden later */
+ req->retries = 5;
+
+ switch (opcode) {
+ case SEND_DIAGNOSTIC:
+ case FORMAT_UNIT:
+ rq->timeout = FORMAT_UNIT_TIMEOUT;
+ req->retries = 1;
+ break;
+ case START_STOP:
+ rq->timeout = START_STOP_TIMEOUT;
+ break;
+ case MOVE_MEDIUM:
+ rq->timeout = MOVE_MEDIUM_TIMEOUT;
+ break;
+ case READ_ELEMENT_STATUS:
+ rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
+ break;
+ case READ_DEFECT_DATA:
+ rq->timeout = READ_DEFECT_DATA_TIMEOUT;
+ req->retries = 1;
+ break;
+ default:
+ rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+ break;
+ }
+
+ if (bytes) {
+ err = blk_rq_map_kern(q, rq, buffer, bytes, GFP_NOIO);
+ if (err)
+ goto error;
+ }
+
+ blk_execute_rq(disk, rq, 0);
+
+ err = req->result & 0xff; /* only 8 bit SCSI status */
+ if (err) {
+ if (req->sense_len && req->sense) {
+ bytes = (OMAX_SB_LEN > req->sense_len) ?
+ req->sense_len : OMAX_SB_LEN;
+ if (copy_to_user(sic->data, req->sense, bytes))
+ err = -EFAULT;
+ }
+ } else {
+ if (copy_to_user(sic->data, buffer, out_len))
+ err = -EFAULT;
+ }
+
+error:
+ blk_put_request(rq);
+
+error_free_buffer:
+ kfree(buffer);
+
+ return err;
+}
+
+int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp)
+{
+#ifdef CONFIG_COMPAT
+ if (in_compat_syscall()) {
+ struct compat_sg_io_hdr hdr32 = {
+ .interface_id = hdr->interface_id,
+ .dxfer_direction = hdr->dxfer_direction,
+ .cmd_len = hdr->cmd_len,
+ .mx_sb_len = hdr->mx_sb_len,
+ .iovec_count = hdr->iovec_count,
+ .dxfer_len = hdr->dxfer_len,
+ .dxferp = (uintptr_t)hdr->dxferp,
+ .cmdp = (uintptr_t)hdr->cmdp,
+ .sbp = (uintptr_t)hdr->sbp,
+ .timeout = hdr->timeout,
+ .flags = hdr->flags,
+ .pack_id = hdr->pack_id,
+ .usr_ptr = (uintptr_t)hdr->usr_ptr,
+ .status = hdr->status,
+ .masked_status = hdr->masked_status,
+ .msg_status = hdr->msg_status,
+ .sb_len_wr = hdr->sb_len_wr,
+ .host_status = hdr->host_status,
+ .driver_status = hdr->driver_status,
+ .resid = hdr->resid,
+ .duration = hdr->duration,
+ .info = hdr->info,
+ };
+
+ if (copy_to_user(argp, &hdr32, sizeof(hdr32)))
+ return -EFAULT;
+
+ return 0;
+ }
+#endif
+
+ if (copy_to_user(argp, hdr, sizeof(*hdr)))
+ return -EFAULT;
+
+ return 0;
+}
+EXPORT_SYMBOL(put_sg_io_hdr);
+
+int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp)
+{
+#ifdef CONFIG_COMPAT
+ struct compat_sg_io_hdr hdr32;
+
+ if (in_compat_syscall()) {
+ if (copy_from_user(&hdr32, argp, sizeof(hdr32)))
+ return -EFAULT;
+
+ *hdr = (struct sg_io_hdr) {
+ .interface_id = hdr32.interface_id,
+ .dxfer_direction = hdr32.dxfer_direction,
+ .cmd_len = hdr32.cmd_len,
+ .mx_sb_len = hdr32.mx_sb_len,
+ .iovec_count = hdr32.iovec_count,
+ .dxfer_len = hdr32.dxfer_len,
+ .dxferp = compat_ptr(hdr32.dxferp),
+ .cmdp = compat_ptr(hdr32.cmdp),
+ .sbp = compat_ptr(hdr32.sbp),
+ .timeout = hdr32.timeout,
+ .flags = hdr32.flags,
+ .pack_id = hdr32.pack_id,
+ .usr_ptr = compat_ptr(hdr32.usr_ptr),
+ .status = hdr32.status,
+ .masked_status = hdr32.masked_status,
+ .msg_status = hdr32.msg_status,
+ .sb_len_wr = hdr32.sb_len_wr,
+ .host_status = hdr32.host_status,
+ .driver_status = hdr32.driver_status,
+ .resid = hdr32.resid,
+ .duration = hdr32.duration,
+ .info = hdr32.info,
+ };
+
+ return 0;
+ }
+#endif
+
+ if (copy_from_user(hdr, argp, sizeof(*hdr)))
+ return -EFAULT;
+
+ return 0;
+}
+EXPORT_SYMBOL(get_sg_io_hdr);
+
+#ifdef CONFIG_COMPAT
+struct compat_cdrom_generic_command {
+ unsigned char cmd[CDROM_PACKET_SIZE];
+ compat_caddr_t buffer;
+ compat_uint_t buflen;
+ compat_int_t stat;
+ compat_caddr_t sense;
+ unsigned char data_direction;
+ unsigned char pad[3];
+ compat_int_t quiet;
+ compat_int_t timeout;
+ compat_caddr_t unused;
+};
+#endif
+
+static int scsi_get_cdrom_generic_arg(struct cdrom_generic_command *cgc,
+ const void __user *arg)
+{
+#ifdef CONFIG_COMPAT
+ if (in_compat_syscall()) {
+ struct compat_cdrom_generic_command cgc32;
+
+ if (copy_from_user(&cgc32, arg, sizeof(cgc32)))
+ return -EFAULT;
+
+ *cgc = (struct cdrom_generic_command) {
+ .buffer = compat_ptr(cgc32.buffer),
+ .buflen = cgc32.buflen,
+ .stat = cgc32.stat,
+ .sense = compat_ptr(cgc32.sense),
+ .data_direction = cgc32.data_direction,
+ .quiet = cgc32.quiet,
+ .timeout = cgc32.timeout,
+ .unused = compat_ptr(cgc32.unused),
+ };
+ memcpy(&cgc->cmd, &cgc32.cmd, CDROM_PACKET_SIZE);
+ return 0;
+ }
+#endif
+ if (copy_from_user(cgc, arg, sizeof(*cgc)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc,
+ void __user *arg)
+{
+#ifdef CONFIG_COMPAT
+ if (in_compat_syscall()) {
+ struct compat_cdrom_generic_command cgc32 = {
+ .buffer = (uintptr_t)(cgc->buffer),
+ .buflen = cgc->buflen,
+ .stat = cgc->stat,
+ .sense = (uintptr_t)(cgc->sense),
+ .data_direction = cgc->data_direction,
+ .quiet = cgc->quiet,
+ .timeout = cgc->timeout,
+ .unused = (uintptr_t)(cgc->unused),
+ };
+ memcpy(&cgc32.cmd, &cgc->cmd, CDROM_PACKET_SIZE);
+
+ if (copy_to_user(arg, &cgc32, sizeof(cgc32)))
+ return -EFAULT;
+
+ return 0;
+ }
+#endif
+ if (copy_to_user(arg, cgc, sizeof(*cgc)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int scsi_cdrom_send_packet(struct scsi_device *sdev, struct gendisk *disk,
+ fmode_t mode, void __user *arg)
+{
+ struct cdrom_generic_command cgc;
+ struct sg_io_hdr hdr;
+ int err;
+
+ err = scsi_get_cdrom_generic_arg(&cgc, arg);
+ if (err)
+ return err;
+
+ cgc.timeout = clock_t_to_jiffies(cgc.timeout);
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.interface_id = 'S';
+ hdr.cmd_len = sizeof(cgc.cmd);
+ hdr.dxfer_len = cgc.buflen;
+ switch (cgc.data_direction) {
+ case CGC_DATA_UNKNOWN:
+ hdr.dxfer_direction = SG_DXFER_UNKNOWN;
+ break;
+ case CGC_DATA_WRITE:
+ hdr.dxfer_direction = SG_DXFER_TO_DEV;
+ break;
+ case CGC_DATA_READ:
+ hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+ break;
+ case CGC_DATA_NONE:
+ hdr.dxfer_direction = SG_DXFER_NONE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ hdr.dxferp = cgc.buffer;
+ hdr.sbp = cgc.sense;
+ if (hdr.sbp)
+ hdr.mx_sb_len = sizeof(struct request_sense);
+ hdr.timeout = jiffies_to_msecs(cgc.timeout);
+ hdr.cmdp = ((struct cdrom_generic_command __user *) arg)->cmd;
+ hdr.cmd_len = sizeof(cgc.cmd);
+
+ err = sg_io(sdev, disk, &hdr, mode);
+ if (err == -EFAULT)
+ return -EFAULT;
+
+ if (hdr.status)
+ return -EIO;
+
+ cgc.stat = err;
+ cgc.buflen = hdr.resid;
+ if (scsi_put_cdrom_generic_arg(&cgc, arg))
+ return -EFAULT;
+
+ return err;
+}
+
+static int scsi_ioctl_sg_io(struct scsi_device *sdev, struct gendisk *disk,
+ fmode_t mode, void __user *argp)
+{
+ struct sg_io_hdr hdr;
+ int error;
+
+ error = get_sg_io_hdr(&hdr, argp);
+ if (error)
+ return error;
+ error = sg_io(sdev, disk, &hdr, mode);
+ if (error == -EFAULT)
+ return error;
+ if (put_sg_io_hdr(&hdr, argp))
+ return -EFAULT;
+ return error;
+}
+
+/**
+ * scsi_ioctl - Dispatch ioctl to scsi device
+ * @sdev: scsi device receiving ioctl
+ * @disk: disk receiving the ioctl
+ * @mode: mode the block/char device is opened with
+ * @cmd: which ioctl is it
+ * @arg: data associated with ioctl
+ *
+ * Description: The scsi_ioctl() function differs from most ioctls in that it
+ * does not take a major/minor number as the dev field. Rather, it takes
+ * a pointer to a &struct scsi_device.
+ */
+int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
+ int cmd, void __user *arg)
+{
+ struct request_queue *q = sdev->request_queue;
struct scsi_sense_hdr sense_hdr;
/* Check for deprecated ioctls ... all the ioctls which don't
@@ -212,26 +912,34 @@ static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg
}
switch (cmd) {
- case SCSI_IOCTL_GET_IDLUN: {
- struct scsi_idlun v = {
- .dev_id = (sdev->id & 0xff)
- + ((sdev->lun & 0xff) << 8)
- + ((sdev->channel & 0xff) << 16)
- + ((sdev->host->host_no & 0xff) << 24),
- .host_unique_id = sdev->host->unique_id
- };
- if (copy_to_user(arg, &v, sizeof(struct scsi_idlun)))
- return -EFAULT;
- return 0;
- }
+ case SG_GET_VERSION_NUM:
+ return sg_get_version(arg);
+ case SG_SET_TIMEOUT:
+ return sg_set_timeout(sdev, arg);
+ case SG_GET_TIMEOUT:
+ return jiffies_to_clock_t(sdev->sg_timeout);
+ case SG_GET_RESERVED_SIZE:
+ return sg_get_reserved_size(sdev, arg);
+ case SG_SET_RESERVED_SIZE:
+ return sg_set_reserved_size(sdev, arg);
+ case SG_EMULATED_HOST:
+ return sg_emulated_host(q, arg);
+ case SG_IO:
+ return scsi_ioctl_sg_io(sdev, disk, mode, arg);
+ case SCSI_IOCTL_SEND_COMMAND:
+ return sg_scsi_ioctl(q, disk, mode, arg);
+ case CDROM_SEND_PACKET:
+ return scsi_cdrom_send_packet(sdev, disk, mode, arg);
+ case CDROMCLOSETRAY:
+ return scsi_send_start_stop(sdev, 3);
+ case CDROMEJECT:
+ return scsi_send_start_stop(sdev, 2);
+ case SCSI_IOCTL_GET_IDLUN:
+ return scsi_get_idlun(sdev, arg);
case SCSI_IOCTL_GET_BUS_NUMBER:
return put_user(sdev->host->host_no, (int __user *)arg);
case SCSI_IOCTL_PROBE_HOST:
return ioctl_probe(sdev->host, arg);
- case SCSI_IOCTL_SEND_COMMAND:
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- return -EACCES;
- return sg_scsi_ioctl(sdev->request_queue, NULL, 0, arg);
case SCSI_IOCTL_DOORLOCK:
return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
case SCSI_IOCTL_DOORUNLOCK:
@@ -240,66 +948,27 @@ static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg
return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT,
NORMAL_RETRIES, &sense_hdr);
case SCSI_IOCTL_START_UNIT:
- scsi_cmd[0] = START_STOP;
- scsi_cmd[1] = 0;
- scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
- scsi_cmd[4] = 1;
- return ioctl_internal_command(sdev, scsi_cmd,
- START_STOP_TIMEOUT, NORMAL_RETRIES);
+ return scsi_send_start_stop(sdev, 1);
case SCSI_IOCTL_STOP_UNIT:
- scsi_cmd[0] = START_STOP;
- scsi_cmd[1] = 0;
- scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
- scsi_cmd[4] = 0;
- return ioctl_internal_command(sdev, scsi_cmd,
- START_STOP_TIMEOUT, NORMAL_RETRIES);
+ return scsi_send_start_stop(sdev, 0);
case SCSI_IOCTL_GET_PCI:
return scsi_ioctl_get_pci(sdev, arg);
case SG_SCSI_RESET:
return scsi_ioctl_reset(sdev, arg);
}
- return -ENOIOCTLCMD;
-}
-
-/**
- * scsi_ioctl - Dispatch ioctl to scsi device
- * @sdev: scsi device receiving ioctl
- * @cmd: which ioctl is it
- * @arg: data associated with ioctl
- *
- * Description: The scsi_ioctl() function differs from most ioctls in that it
- * does not take a major/minor number as the dev field. Rather, it takes
- * a pointer to a &struct scsi_device.
- */
-int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
-{
- int ret = scsi_ioctl_common(sdev, cmd, arg);
-
- if (ret != -ENOIOCTLCMD)
- return ret;
-
- if (sdev->host->hostt->ioctl)
- return sdev->host->hostt->ioctl(sdev, cmd, arg);
-
- return -EINVAL;
-}
-EXPORT_SYMBOL(scsi_ioctl);
#ifdef CONFIG_COMPAT
-int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
-{
- int ret = scsi_ioctl_common(sdev, cmd, arg);
-
- if (ret != -ENOIOCTLCMD)
- return ret;
-
- if (sdev->host->hostt->compat_ioctl)
+ if (in_compat_syscall()) {
+ if (!sdev->host->hostt->compat_ioctl)
+ return -EINVAL;
return sdev->host->hostt->compat_ioctl(sdev, cmd, arg);
-
- return ret;
-}
-EXPORT_SYMBOL(scsi_compat_ioctl);
+ }
#endif
+ if (!sdev->host->hostt->ioctl)
+ return -EINVAL;
+ return sdev->host->hostt->ioctl(sdev, cmd, arg);
+}
+EXPORT_SYMBOL(scsi_ioctl);
/*
* We can process a reset even when a device isn't fully operable.
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 7456a26aef51..572673873ddf 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -119,13 +119,15 @@ scsi_set_blocked(struct scsi_cmnd *cmd, int reason)
static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
{
- if (cmd->request->rq_flags & RQF_DONTPREP) {
- cmd->request->rq_flags &= ~RQF_DONTPREP;
+ struct request *rq = scsi_cmd_to_rq(cmd);
+
+ if (rq->rq_flags & RQF_DONTPREP) {
+ rq->rq_flags &= ~RQF_DONTPREP;
scsi_mq_uninit_cmd(cmd);
} else {
WARN_ON_ONCE(true);
}
- blk_mq_requeue_request(cmd->request, true);
+ blk_mq_requeue_request(rq, true);
}
/**
@@ -164,7 +166,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy)
*/
cmd->result = 0;
- blk_mq_requeue_request(cmd->request, true);
+ blk_mq_requeue_request(scsi_cmd_to_rq(cmd), true);
}
/**
@@ -478,7 +480,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
{
- if (!blk_rq_is_passthrough(cmd->request)) {
+ if (!blk_rq_is_passthrough(scsi_cmd_to_rq(cmd))) {
struct scsi_driver *drv = scsi_cmd_to_driver(cmd);
if (drv->uninit_command)
@@ -624,7 +626,7 @@ static void scsi_io_completion_reprep(struct scsi_cmnd *cmd,
static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
{
- struct request *req = cmd->request;
+ struct request *req = scsi_cmd_to_rq(cmd);
unsigned long wait_for;
if (cmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
@@ -643,7 +645,7 @@ static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
{
struct request_queue *q = cmd->device->request_queue;
- struct request *req = cmd->request;
+ struct request *req = scsi_cmd_to_rq(cmd);
int level = 0;
enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
ACTION_DELAYED_RETRY} action;
@@ -818,7 +820,7 @@ static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, int result,
{
bool sense_valid;
bool sense_current = true; /* false implies "deferred sense" */
- struct request *req = cmd->request;
+ struct request *req = scsi_cmd_to_rq(cmd);
struct scsi_sense_hdr sshdr;
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
@@ -907,7 +909,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
{
int result = cmd->result;
struct request_queue *q = cmd->device->request_queue;
- struct request *req = cmd->request;
+ struct request *req = scsi_cmd_to_rq(cmd);
blk_status_t blk_stat = BLK_STS_OK;
if (unlikely(result)) /* a nz result may or may not be an error */
@@ -978,7 +980,7 @@ static inline bool scsi_cmd_needs_dma_drain(struct scsi_device *sdev,
blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
{
struct scsi_device *sdev = cmd->device;
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
unsigned short nr_segs = blk_rq_nr_phys_segments(rq);
struct scatterlist *last_sg = NULL;
blk_status_t ret;
@@ -1083,8 +1085,13 @@ EXPORT_SYMBOL(scsi_alloc_sgtables);
static void scsi_initialize_rq(struct request *rq)
{
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+ struct scsi_request *req = &cmd->req;
+
+ memset(req->__cmd, 0, sizeof(req->__cmd));
+ req->cmd = req->__cmd;
+ req->cmd_len = BLK_MAX_CDB;
+ req->sense_len = 0;
- scsi_req_init(&cmd->req);
init_rcu_head(&cmd->rcu);
cmd->jiffies_at_alloc = jiffies;
cmd->retries = 0;
@@ -1107,7 +1114,7 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
{
void *buf = cmd->sense_buffer;
void *prot = cmd->prot_sdb;
- struct request *rq = blk_mq_rq_from_pdu(cmd);
+ struct request *rq = scsi_cmd_to_rq(cmd);
unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS;
unsigned long jiffies_at_alloc;
int retries, to_clear;
@@ -1533,8 +1540,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
scsi_init_command(sdev, cmd);
- cmd->request = req;
- cmd->tag = req->tag;
cmd->prot_op = SCSI_PROT_NORMAL;
if (blk_rq_bytes(req))
cmd->sc_data_direction = rq_dma_dir(req);
@@ -1572,12 +1577,12 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
static void scsi_mq_done(struct scsi_cmnd *cmd)
{
- if (unlikely(blk_should_fake_timeout(cmd->request->q)))
+ if (unlikely(blk_should_fake_timeout(scsi_cmd_to_rq(cmd)->q)))
return;
if (unlikely(test_and_set_bit(SCMD_STATE_COMPLETE, &cmd->state)))
return;
trace_scsi_dispatch_cmd_done(cmd);
- blk_mq_complete_request(cmd->request);
+ blk_mq_complete_request(scsi_cmd_to_rq(cmd));
}
static void scsi_mq_put_budget(struct request_queue *q, int budget_token)
diff --git a/drivers/scsi/scsi_logging.c b/drivers/scsi/scsi_logging.c
index 2317717935e9..ed9572252a42 100644
--- a/drivers/scsi/scsi_logging.c
+++ b/drivers/scsi/scsi_logging.c
@@ -28,8 +28,9 @@ static void scsi_log_release_buffer(char *bufptr)
static inline const char *scmd_name(const struct scsi_cmnd *scmd)
{
- return scmd->request->rq_disk ?
- scmd->request->rq_disk->disk_name : NULL;
+ struct request *rq = scsi_cmd_to_rq((struct scsi_cmnd *)scmd);
+
+ return rq->rq_disk ? rq->rq_disk->disk_name : NULL;
}
static size_t sdev_format_header(char *logbuf, size_t logbuf_len,
@@ -91,7 +92,7 @@ void scmd_printk(const char *level, const struct scsi_cmnd *scmd,
if (!logbuf)
return;
off = sdev_format_header(logbuf, logbuf_len, scmd_name(scmd),
- scmd->request->tag);
+ scsi_cmd_to_rq((struct scsi_cmnd *)scmd)->tag);
if (off < logbuf_len) {
va_start(args, fmt);
off += vscnprintf(logbuf + off, logbuf_len - off, fmt, args);
@@ -188,7 +189,7 @@ void scsi_print_command(struct scsi_cmnd *cmd)
return;
off = sdev_format_header(logbuf, logbuf_len,
- scmd_name(cmd), cmd->request->tag);
+ scmd_name(cmd), scsi_cmd_to_rq(cmd)->tag);
if (off >= logbuf_len)
goto out_printk;
off += scnprintf(logbuf + off, logbuf_len - off, "CDB: ");
@@ -210,7 +211,7 @@ void scsi_print_command(struct scsi_cmnd *cmd)
off = sdev_format_header(logbuf, logbuf_len,
scmd_name(cmd),
- cmd->request->tag);
+ scsi_cmd_to_rq(cmd)->tag);
if (!WARN_ON(off > logbuf_len - 58)) {
off += scnprintf(logbuf + off, logbuf_len - off,
"CDB[%02x]: ", k);
@@ -373,7 +374,8 @@ EXPORT_SYMBOL(__scsi_print_sense);
/* Normalize and print sense buffer in SCSI command */
void scsi_print_sense(const struct scsi_cmnd *cmd)
{
- scsi_log_print_sense(cmd->device, scmd_name(cmd), cmd->request->tag,
+ scsi_log_print_sense(cmd->device, scmd_name(cmd),
+ scsi_cmd_to_rq((struct scsi_cmnd *)cmd)->tag,
cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
}
EXPORT_SYMBOL(scsi_print_sense);
@@ -391,8 +393,8 @@ void scsi_print_result(const struct scsi_cmnd *cmd, const char *msg,
if (!logbuf)
return;
- off = sdev_format_header(logbuf, logbuf_len,
- scmd_name(cmd), cmd->request->tag);
+ off = sdev_format_header(logbuf, logbuf_len, scmd_name(cmd),
+ scsi_cmd_to_rq((struct scsi_cmnd *)cmd)->tag);
if (off >= logbuf_len)
goto out_printk;
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index eae2235f79b5..6d9152031a40 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -7,6 +7,7 @@
#include <scsi/scsi_device.h>
#include <linux/sbitmap.h>
+struct bsg_device;
struct request_queue;
struct request;
struct scsi_cmnd;
@@ -180,6 +181,8 @@ static inline void scsi_dh_add_device(struct scsi_device *sdev) { }
static inline void scsi_dh_release_device(struct scsi_device *sdev) { }
#endif
+struct bsg_device *scsi_bsg_register_queue(struct scsi_device *sdev);
+
extern int scsi_device_max_queue_depth(struct scsi_device *sdev);
/*
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 5b6996a2401b..fe22191522a3 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -267,6 +267,8 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
*/
sdev->borken = 1;
+ sdev->sg_reserved_size = INT_MAX;
+
q = blk_mq_init_queue(&sdev->host->tag_set);
if (IS_ERR(q)) {
/* release fn is set up in scsi_sysfs_device_initialise, so
@@ -974,6 +976,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
if (*bflags & BLIST_UNMAP_LIMIT_WS)
sdev->unmap_limit_for_ws = 1;
+ if (*bflags & BLIST_IGN_MEDIA_CHANGE)
+ sdev->ignore_media_change = 1;
+
sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT;
if (*bflags & BLIST_TRY_VPD_PAGES)
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index c0d31119d6d7..86793259e541 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -13,6 +13,7 @@
#include <linux/blkdev.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
+#include <linux/bsg.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -1333,7 +1334,6 @@ static int scsi_target_add(struct scsi_target *starget)
int scsi_sysfs_add_sdev(struct scsi_device *sdev)
{
int error, i;
- struct request_queue *rq = sdev->request_queue;
struct scsi_target *starget = sdev->sdev_target;
error = scsi_target_add(starget);
@@ -1372,12 +1372,19 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
transport_add_device(&sdev->sdev_gendev);
sdev->is_visible = 1;
- error = bsg_scsi_register_queue(rq, &sdev->sdev_gendev);
- if (error)
- /* we're treating error on bsg register as non-fatal,
- * so pretend nothing went wrong */
- sdev_printk(KERN_INFO, sdev,
- "Failed to register bsg queue, errno=%d\n", error);
+ if (IS_ENABLED(CONFIG_BLK_DEV_BSG)) {
+ sdev->bsg_dev = scsi_bsg_register_queue(sdev);
+ if (IS_ERR(sdev->bsg_dev)) {
+ /*
+ * We're treating error on bsg register as non-fatal, so
+ * pretend nothing went wrong.
+ */
+ sdev_printk(KERN_INFO, sdev,
+ "Failed to register bsg queue, errno=%d\n",
+ error);
+ sdev->bsg_dev = NULL;
+ }
+ }
/* add additional host specific attributes */
if (sdev->host->hostt->sdev_attrs) {
@@ -1439,7 +1446,8 @@ void __scsi_remove_device(struct scsi_device *sdev)
sysfs_remove_groups(&sdev->sdev_gendev.kobj,
sdev->host->hostt->sdev_groups);
- bsg_unregister_queue(sdev->request_queue);
+ if (IS_ENABLED(CONFIG_BLK_DEV_BSG) && sdev->bsg_dev)
+ bsg_unregister_queue(sdev->bsg_dev);
device_unregister(&sdev->sdev_dev);
transport_remove_device(dev);
device_del(dev);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 49748cd817a5..60e406bcf42a 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3804,7 +3804,7 @@ bool fc_eh_should_retry_cmd(struct scsi_cmnd *scmd)
struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device));
if ((rport->port_state != FC_PORTSTATE_ONLINE) &&
- (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT)) {
+ (scsi_cmd_to_rq(scmd)->cmd_flags & REQ_FAILFAST_TRANSPORT)) {
set_host_byte(scmd, DID_TRANSPORT_MARGINAL);
return false;
}
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 5af7a10e9514..bd72c38d7bfc 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -1230,7 +1230,7 @@ int spi_populate_tag_msg(unsigned char *msg, struct scsi_cmnd *cmd)
{
if (cmd->flags & SCMD_TAGGED) {
*msg++ = SIMPLE_QUEUE_TAG;
- *msg++ = cmd->request->tag;
+ *msg++ = scsi_cmd_to_rq(cmd)->tag;
return 2;
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 610ebba0d66e..cbd9999f93a6 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -110,6 +110,7 @@ static void sd_shutdown(struct device *);
static int sd_suspend_system(struct device *);
static int sd_suspend_runtime(struct device *);
static int sd_resume(struct device *);
+static int sd_resume_runtime(struct device *);
static void sd_rescan(struct device *);
static blk_status_t sd_init_command(struct scsi_cmnd *SCpnt);
static void sd_uninit_command(struct scsi_cmnd *SCpnt);
@@ -605,7 +606,7 @@ static const struct dev_pm_ops sd_pm_ops = {
.poweroff = sd_suspend_system,
.restore = sd_resume,
.runtime_suspend = sd_suspend_runtime,
- .runtime_resume = sd_resume,
+ .runtime_resume = sd_resume_runtime,
};
static struct scsi_driver sd_template = {
@@ -776,8 +777,9 @@ static unsigned int sd_prot_flag_mask(unsigned int prot_op)
static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd,
unsigned int dix, unsigned int dif)
{
- struct bio *bio = scmd->request->bio;
- unsigned int prot_op = sd_prot_op(rq_data_dir(scmd->request), dix, dif);
+ struct request *rq = scsi_cmd_to_rq(scmd);
+ struct bio *bio = rq->bio;
+ unsigned int prot_op = sd_prot_op(rq_data_dir(rq), dix, dif);
unsigned int protect = 0;
if (dix) { /* DIX Type 0, 1, 2, 3 */
@@ -868,7 +870,7 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
{
struct scsi_device *sdp = cmd->device;
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
@@ -904,7 +906,7 @@ static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
bool unmap)
{
struct scsi_device *sdp = cmd->device;
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
@@ -936,7 +938,7 @@ static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd,
bool unmap)
{
struct scsi_device *sdp = cmd->device;
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
@@ -966,7 +968,7 @@ static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd,
static blk_status_t sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
{
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_device *sdp = cmd->device;
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
@@ -1063,7 +1065,7 @@ out:
**/
static blk_status_t sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
{
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_device *sdp = cmd->device;
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
struct bio *bio = rq->bio;
@@ -1112,7 +1114,7 @@ static blk_status_t sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd)
{
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
/* flush requests don't perform I/O, zero the S/G table */
@@ -1210,7 +1212,7 @@ static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write,
static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
{
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_device *sdp = cmd->device;
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
sector_t lba = sectors_to_logical(sdp, blk_rq_pos(rq));
@@ -1324,7 +1326,7 @@ fail:
static blk_status_t sd_init_command(struct scsi_cmnd *cmd)
{
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
switch (req_op(rq)) {
case REQ_OP_DISCARD:
@@ -1370,7 +1372,7 @@ static blk_status_t sd_init_command(struct scsi_cmnd *cmd)
static void sd_uninit_command(struct scsi_cmnd *SCpnt)
{
- struct request *rq = SCpnt->request;
+ struct request *rq = scsi_cmd_to_rq(SCpnt);
u8 *cmnd;
if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
@@ -1530,11 +1532,11 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
}
/**
- * sd_ioctl_common - process an ioctl
+ * sd_ioctl - process an ioctl
* @bdev: target block device
* @mode: FMODE_* mask
* @cmd: ioctl command number
- * @p: this is third argument given to ioctl(2) system call.
+ * @arg: this is third argument given to ioctl(2) system call.
* Often contains a pointer.
*
* Returns 0 if successful (some ioctls return positive numbers on
@@ -1543,20 +1545,20 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
* Note: most ioctls are forward onto the block subsystem or further
* down in the scsi subsystem.
**/
-static int sd_ioctl_common(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, void __user *p)
+static int sd_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
{
struct gendisk *disk = bdev->bd_disk;
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
+ void __user *p = (void __user *)arg;
int error;
SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
"cmd=0x%x\n", disk->disk_name, cmd));
- error = scsi_verify_blk_ioctl(bdev, cmd);
- if (error < 0)
- return error;
+ if (bdev_is_partition(bdev) && !capable(CAP_SYS_RAWIO))
+ return -ENOIOCTLCMD;
/*
* If we are in the middle of error recovery, don't let anyone
@@ -1567,27 +1569,11 @@ static int sd_ioctl_common(struct block_device *bdev, fmode_t mode,
error = scsi_ioctl_block_when_processing_errors(sdp, cmd,
(mode & FMODE_NDELAY) != 0);
if (error)
- goto out;
+ return error;
if (is_sed_ioctl(cmd))
return sed_ioctl(sdkp->opal_dev, cmd, p);
-
- /*
- * Send SCSI addressing ioctls directly to mid level, send other
- * ioctls to block level and then onto mid level if they can't be
- * resolved.
- */
- switch (cmd) {
- case SCSI_IOCTL_GET_IDLUN:
- case SCSI_IOCTL_GET_BUS_NUMBER:
- error = scsi_ioctl(sdp, cmd, p);
- break;
- default:
- error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
- break;
- }
-out:
- return error;
+ return scsi_ioctl(sdp, disk, mode, cmd, p);
}
static void set_media_not_present(struct scsi_disk *sdkp)
@@ -1770,34 +1756,6 @@ static void sd_rescan(struct device *dev)
sd_revalidate_disk(sdkp->disk);
}
-static int sd_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- void __user *p = (void __user *)arg;
- int ret;
-
- ret = sd_ioctl_common(bdev, mode, cmd, p);
- if (ret != -ENOTTY)
- return ret;
-
- return scsi_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p);
-}
-
-#ifdef CONFIG_COMPAT
-static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- void __user *p = compat_ptr(arg);
- int ret;
-
- ret = sd_ioctl_common(bdev, mode, cmd, p);
- if (ret != -ENOTTY)
- return ret;
-
- return scsi_compat_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p);
-}
-#endif
-
static char sd_pr_type(enum pr_type type)
{
switch (type) {
@@ -1898,9 +1856,7 @@ static const struct block_device_operations sd_fops = {
.release = sd_release,
.ioctl = sd_ioctl,
.getgeo = sd_getgeo,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = sd_compat_ioctl,
-#endif
+ .compat_ioctl = blkdev_compat_ptr_ioctl,
.check_events = sd_check_events,
.unlock_native_capacity = sd_unlock_native_capacity,
.report_zones = sd_zbc_report_zones,
@@ -1921,7 +1877,7 @@ static const struct block_device_operations sd_fops = {
**/
static void sd_eh_reset(struct scsi_cmnd *scmd)
{
- struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk);
+ struct scsi_disk *sdkp = scsi_disk(scsi_cmd_to_rq(scmd)->rq_disk);
/* New SCSI EH run, reset gate variable */
sdkp->ignore_medium_access_errors = false;
@@ -1941,7 +1897,7 @@ static void sd_eh_reset(struct scsi_cmnd *scmd)
**/
static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
{
- struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk);
+ struct scsi_disk *sdkp = scsi_disk(scsi_cmd_to_rq(scmd)->rq_disk);
struct scsi_device *sdev = scmd->device;
if (!scsi_device_online(sdev) ||
@@ -1982,7 +1938,7 @@ static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
{
- struct request *req = scmd->request;
+ struct request *req = scsi_cmd_to_rq(scmd);
struct scsi_device *sdev = scmd->device;
unsigned int transferred, good_bytes;
u64 start_lba, end_lba, bad_lba;
@@ -2037,8 +1993,8 @@ static int sd_done(struct scsi_cmnd *SCpnt)
unsigned int sector_size = SCpnt->device->sector_size;
unsigned int resid;
struct scsi_sense_hdr sshdr;
- struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
- struct request *req = SCpnt->request;
+ struct request *req = scsi_cmd_to_rq(SCpnt);
+ struct scsi_disk *sdkp = scsi_disk(req->rq_disk);
int sense_valid = 0;
int sense_deferred = 0;
@@ -2181,8 +2137,10 @@ sd_spinup_disk(struct scsi_disk *sdkp)
* doesn't have any media in it, don't bother
* with any more polling.
*/
- if (media_not_present(sdkp, &sshdr))
+ if (media_not_present(sdkp, &sshdr)) {
+ sd_printk(KERN_NOTICE, sdkp, "Media removed, stopped polling\n");
return;
+ }
if (the_result)
sense_valid = scsi_sense_valid(&sshdr);
@@ -3718,6 +3676,25 @@ static int sd_resume(struct device *dev)
return ret;
}
+static int sd_resume_runtime(struct device *dev)
+{
+ struct scsi_disk *sdkp = dev_get_drvdata(dev);
+ struct scsi_device *sdp = sdkp->device;
+
+ if (sdp->ignore_media_change) {
+ /* clear the device's sense data */
+ static const u8 cmd[10] = { REQUEST_SENSE };
+
+ if (scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL,
+ NULL, sdp->request_queue->rq_timeout, 1, 0,
+ RQF_PM, NULL))
+ sd_printk(KERN_NOTICE, sdkp,
+ "Failed to clear sense data\n");
+ }
+
+ return sd_resume(dev);
+}
+
/**
* init_sd - entry point for this driver (both when built in or when
* a module).
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 186b5ff52c3a..b9757f24b0d6 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -243,7 +243,7 @@ out:
static blk_status_t sd_zbc_cmnd_checks(struct scsi_cmnd *cmd)
{
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
sector_t sector = blk_rq_pos(rq);
@@ -321,7 +321,7 @@ static void sd_zbc_update_wp_offset_workfn(struct work_struct *work)
blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
unsigned int nr_blocks)
{
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
unsigned int wp_offset, zno = blk_rq_zone_no(rq);
unsigned long flags;
@@ -386,7 +386,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
unsigned char op, bool all)
{
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
sector_t sector = blk_rq_pos(rq);
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
sector_t block = sectors_to_logical(sdkp->device, sector);
@@ -442,7 +442,7 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
unsigned int good_bytes)
{
int result = cmd->result;
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
unsigned int zno = blk_rq_zone_no(rq);
enum req_opf op = req_op(rq);
@@ -516,7 +516,7 @@ unsigned int sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
struct scsi_sense_hdr *sshdr)
{
int result = cmd->result;
- struct request *rq = cmd->request;
+ struct request *rq = scsi_cmd_to_rq(cmd);
if (op_is_zone_mgmt(req_op(rq)) &&
result &&
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index d5889b4f0fd4..8f05248920e8 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -237,8 +237,9 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
if (sfp->parentdp->device->type == TYPE_SCANNER)
return 0;
-
- return blk_verify_command(cmd, filp->f_mode);
+ if (!scsi_cmd_allowed(cmd, filp->f_mode))
+ return -EPERM;
+ return 0;
}
static int
@@ -1107,7 +1108,7 @@ sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp,
case SCSI_IOCTL_SEND_COMMAND:
if (atomic_read(&sdp->detaching))
return -ENODEV;
- return sg_scsi_ioctl(sdp->device->request_queue, NULL, filp->f_mode, p);
+ return scsi_ioctl(sdp->device, NULL, filp->f_mode, cmd_in, p);
case SG_SET_DEBUG:
result = get_user(val, ip);
if (result)
@@ -1163,28 +1164,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
if (ret != -ENOIOCTLCMD)
return ret;
-
- return scsi_ioctl(sdp->device, cmd_in, p);
-}
-
-#ifdef CONFIG_COMPAT
-static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
-{
- void __user *p = compat_ptr(arg);
- Sg_device *sdp;
- Sg_fd *sfp;
- int ret;
-
- if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
- return -ENXIO;
-
- ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
- if (ret != -ENOIOCTLCMD)
- return ret;
-
- return scsi_compat_ioctl(sdp->device, cmd_in, p);
+ return scsi_ioctl(sdp->device, NULL, filp->f_mode, cmd_in, p);
}
-#endif
static __poll_t
sg_poll(struct file *filp, poll_table * wait)
@@ -1439,9 +1420,7 @@ static const struct file_operations sg_fops = {
.write = sg_write,
.poll = sg_poll,
.unlocked_ioctl = sg_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = sg_compat_ioctl,
-#endif
+ .compat_ioctl = compat_ptr_ioctl,
.open = sg_open,
.mmap = sg_mmap,
.release = sg_release,
diff --git a/drivers/scsi/smartpqi/Kconfig b/drivers/scsi/smartpqi/Kconfig
index cb9e4e968b60..6f83e2df4d64 100644
--- a/drivers/scsi/smartpqi/Kconfig
+++ b/drivers/scsi/smartpqi/Kconfig
@@ -1,7 +1,7 @@
#
# Kernel configuration file for the SMARTPQI
#
-# Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
+# Copyright (c) 2019-2021 Microchip Technology Inc. and its subsidiaries
# Copyright (c) 2017-2018 Microsemi Corporation
# Copyright (c) 2016 Microsemi Corporation
# Copyright (c) 2016 PMC-Sierra, Inc.
@@ -38,14 +38,14 @@
# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
config SCSI_SMARTPQI
- tristate "Microsemi PQI Driver"
+ tristate "Microchip PQI Driver"
depends on PCI && SCSI && !S390
select SCSI_SAS_ATTRS
select RAID_ATTRS
help
- This driver supports Microsemi PQI controllers.
+ This driver supports Microchip PQI controllers.
- <http://www.microsemi.com>
+ <http://www.microchip.com>
To compile this driver as a module, choose M here: the
module will be called smartpqi.
diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index d7dac5572274..70eca203d72f 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
+ * driver for Microchip PQI-based storage controllers
+ * Copyright (c) 2019-2021 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
@@ -59,7 +59,7 @@ struct pqi_device_registers {
/*
* controller registers
*
- * These are defined by the Microsemi implementation.
+ * These are defined by the Microchip implementation.
*
* Some registers (those named sis_*) are only used when in
* legacy SIS mode before we transition the controller into
@@ -415,7 +415,7 @@ struct pqi_event_config {
u8 reserved[2];
u8 num_event_descriptors;
u8 reserved1;
- struct pqi_event_descriptor descriptors[1];
+ struct pqi_event_descriptor descriptors[];
};
#define PQI_MAX_EVENT_DESCRIPTORS 255
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index dcc0b9618a64..ecb2af3f43ca 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
+ * driver for Microchip PQI-based storage controllers
+ * Copyright (c) 2019-2021 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
@@ -33,13 +33,13 @@
#define BUILD_TIMESTAMP
#endif
-#define DRIVER_VERSION "2.1.8-045"
+#define DRIVER_VERSION "2.1.10-020"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 1
-#define DRIVER_RELEASE 8
-#define DRIVER_REVISION 45
+#define DRIVER_RELEASE 10
+#define DRIVER_REVISION 20
-#define DRIVER_NAME "Microsemi PQI Driver (v" \
+#define DRIVER_NAME "Microchip SmartPQI Driver (v" \
DRIVER_VERSION BUILD_TIMESTAMP ")"
#define DRIVER_NAME_SHORT "smartpqi"
@@ -48,8 +48,8 @@
#define PQI_POST_RESET_DELAY_SECS 5
#define PQI_POST_OFA_RESET_DELAY_UPON_TIMEOUT_SECS 10
-MODULE_AUTHOR("Microsemi");
-MODULE_DESCRIPTION("Driver for Microsemi Smart Family Controller version "
+MODULE_AUTHOR("Microchip");
+MODULE_DESCRIPTION("Driver for Microchip Smart Family Controller version "
DRIVER_VERSION);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
@@ -1322,6 +1322,7 @@ static int pqi_get_raid_map(struct pqi_ctrl_info *ctrl_info,
"requested %u bytes, received %u bytes\n",
raid_map_size,
get_unaligned_le32(&raid_map->structure_size));
+ rc = -EINVAL;
goto error;
}
}
@@ -4740,8 +4741,7 @@ static int pqi_create_queues(struct pqi_ctrl_info *ctrl_info)
}
#define PQI_REPORT_EVENT_CONFIG_BUFFER_LENGTH \
- (offsetof(struct pqi_event_config, descriptors) + \
- (PQI_MAX_EVENT_DESCRIPTORS * sizeof(struct pqi_event_descriptor)))
+ struct_size((struct pqi_event_config *)0, descriptors, PQI_MAX_EVENT_DESCRIPTORS)
static int pqi_configure_events(struct pqi_ctrl_info *ctrl_info,
bool enable_events)
@@ -5568,7 +5568,7 @@ static inline u16 pqi_get_hw_queue(struct pqi_ctrl_info *ctrl_info,
{
u16 hw_queue;
- hw_queue = blk_mq_unique_tag_to_hwq(blk_mq_unique_tag(scmd->request));
+ hw_queue = blk_mq_unique_tag_to_hwq(blk_mq_unique_tag(scsi_cmd_to_rq(scmd)));
if (hw_queue > ctrl_info->max_hw_queue_index)
hw_queue = 0;
@@ -5577,7 +5577,7 @@ static inline u16 pqi_get_hw_queue(struct pqi_ctrl_info *ctrl_info,
static inline bool pqi_is_bypass_eligible_request(struct scsi_cmnd *scmd)
{
- if (blk_rq_is_passthrough(scmd->request))
+ if (blk_rq_is_passthrough(scsi_cmd_to_rq(scmd)))
return false;
return scmd->SCp.this_residual == 0;
@@ -6033,8 +6033,10 @@ static int pqi_eh_device_reset_handler(struct scsi_cmnd *scmd)
mutex_lock(&ctrl_info->lun_reset_mutex);
dev_err(&ctrl_info->pci_dev->dev,
- "resetting scsi %d:%d:%d:%d\n",
- shost->host_no, device->bus, device->target, device->lun);
+ "resetting scsi %d:%d:%d:%d due to cmd 0x%02x\n",
+ shost->host_no,
+ device->bus, device->target, device->lun,
+ scmd->cmd_len > 0 ? scmd->cmnd[0] : 0xff);
pqi_check_ctrl_health(ctrl_info);
if (pqi_ctrl_offline(ctrl_info))
@@ -7758,11 +7760,11 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
pqi_init_operational_queues(ctrl_info);
- rc = pqi_request_irqs(ctrl_info);
+ rc = pqi_create_queues(ctrl_info);
if (rc)
return rc;
- rc = pqi_create_queues(ctrl_info);
+ rc = pqi_request_irqs(ctrl_info);
if (rc)
return rc;
@@ -8451,7 +8453,7 @@ static void pqi_print_ctrl_info(struct pci_dev *pci_dev,
if (id->driver_data)
ctrl_description = (char *)id->driver_data;
else
- ctrl_description = "Microsemi Smart Family Controller";
+ ctrl_description = "Microchip Smart Family Controller";
dev_info(&pci_dev->dev, "%s found\n", ctrl_description);
}
@@ -8713,6 +8715,14 @@ static const struct pci_device_id pqi_pci_id_table[] = {
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x193d, 0x1108)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x193d, 0x1109)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x193d, 0x8460)
},
{
@@ -9173,6 +9183,34 @@ static const struct pci_device_id pqi_pci_id_table[] = {
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1dfc, 0x3161)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x5445)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x5446)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x5447)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x0b27)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x0b29)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x0b45)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
PCI_ANY_ID, PCI_ANY_ID)
},
{ 0 }
diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c b/drivers/scsi/smartpqi/smartpqi_sas_transport.c
index dd628cc87f78..afd9bafebd1d 100644
--- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c
+++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
+ * driver for Microchip PQI-based storage controllers
+ * Copyright (c) 2019-2021 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c
index c954620628e0..d63c46a8e38b 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
+ * driver for Microchip PQI-based storage controllers
+ * Copyright (c) 2019-2021 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h b/drivers/scsi/smartpqi/smartpqi_sis.h
index 12cd2ab1aead..d29c1352a826 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.h
+++ b/drivers/scsi/smartpqi/smartpqi_sis.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
+ * driver for Microchip PQI-based storage controllers
+ * Copyright (c) 2019-2021 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c
index 6dd0ff188bb4..43a950185e24 100644
--- a/drivers/scsi/snic/snic_scsi.c
+++ b/drivers/scsi/snic/snic_scsi.c
@@ -33,7 +33,7 @@
#include "snic_io.h"
#include "snic.h"
-#define snic_cmd_tag(sc) (((struct scsi_cmnd *) sc)->request->tag)
+#define snic_cmd_tag(sc) (scsi_cmd_to_rq(sc)->tag)
const char *snic_state_str[] = {
[SNIC_INIT] = "SNIC_INIT",
@@ -1636,7 +1636,7 @@ snic_abort_cmd(struct scsi_cmnd *sc)
u32 start_time = jiffies;
SNIC_SCSI_DBG(snic->shost, "abt_cmd:sc %p :0x%x :req = %p :tag = %d\n",
- sc, sc->cmnd[0], sc->request, tag);
+ sc, sc->cmnd[0], scsi_cmd_to_rq(sc), tag);
if (unlikely(snic_get_state(snic) != SNIC_ONLINE)) {
SNIC_HOST_ERR(snic->shost,
@@ -2152,7 +2152,7 @@ snic_device_reset(struct scsi_cmnd *sc)
int dr_supp = 0;
SNIC_SCSI_DBG(shost, "dev_reset:sc %p :0x%x :req = %p :tag = %d\n",
- sc, sc->cmnd[0], sc->request,
+ sc, sc->cmnd[0], scsi_cmd_to_rq(sc),
snic_cmd_tag(sc));
dr_supp = snic_dev_reset_supported(sc->device);
if (!dr_supp) {
@@ -2335,7 +2335,7 @@ snic_reset(struct Scsi_Host *shost, struct scsi_cmnd *sc)
spin_lock_irqsave(&snic->snic_lock, flags);
if (snic_get_state(snic) == SNIC_FWRESET) {
spin_unlock_irqrestore(&snic->snic_lock, flags);
- SNIC_HOST_INFO(shost, "reset:prev reset is in progres\n");
+ SNIC_HOST_INFO(shost, "reset:prev reset is in progress\n");
msleep(SNIC_HOST_RESET_TIMEOUT);
ret = SUCCESS;
@@ -2383,11 +2383,11 @@ snic_host_reset(struct scsi_cmnd *sc)
{
struct Scsi_Host *shost = sc->device->host;
u32 start_time = jiffies;
- int ret = FAILED;
+ int ret;
SNIC_SCSI_DBG(shost,
"host reset:sc %p sc_cmd 0x%x req %p tag %d flags 0x%llx\n",
- sc, sc->cmnd[0], sc->request,
+ sc, sc->cmnd[0], scsi_cmd_to_rq(sc),
snic_cmd_tag(sc), CMD_FLAGS(sc));
ret = snic_reset(shost, sc);
@@ -2494,7 +2494,7 @@ cleanup:
sc->result = DID_TRANSPORT_DISRUPTED << 16;
SNIC_HOST_INFO(snic->shost,
"sc_clean: DID_TRANSPORT_DISRUPTED for sc %p, Tag %d flags 0x%llx rqi %p duration %u msecs\n",
- sc, sc->request->tag, CMD_FLAGS(sc), rqi,
+ sc, scsi_cmd_to_rq(sc)->tag, CMD_FLAGS(sc), rqi,
jiffies_to_msecs(jiffies - st_time));
/* Update IO stats */
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 2942a4ec9bdd..8b17b35283aa 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -122,6 +122,8 @@ static void get_capabilities(struct scsi_cd *);
static unsigned int sr_check_events(struct cdrom_device_info *cdi,
unsigned int clearing, int slot);
static int sr_packet(struct cdrom_device_info *, struct packet_command *);
+static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf,
+ u32 lba, u32 nr, u8 *last_sense);
static const struct cdrom_device_ops sr_dops = {
.open = sr_open,
@@ -135,8 +137,9 @@ static const struct cdrom_device_ops sr_dops = {
.get_mcn = sr_get_mcn,
.reset = sr_reset,
.audio_ioctl = sr_audio_ioctl,
- .capability = SR_CAPABILITIES,
.generic_packet = sr_packet,
+ .read_cdda_bpc = sr_read_cdda_bpc,
+ .capability = SR_CAPABILITIES,
};
static void sr_kref_release(struct kref *kref);
@@ -330,7 +333,8 @@ static int sr_done(struct scsi_cmnd *SCpnt)
int good_bytes = (result == 0 ? this_count : 0);
int block_sectors = 0;
long error_sector;
- struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk);
+ struct request *rq = scsi_cmd_to_rq(SCpnt);
+ struct scsi_cd *cd = scsi_cd(rq->rq_disk);
#ifdef DEBUG
scmd_printk(KERN_INFO, SCpnt, "done: %x\n", result);
@@ -352,16 +356,14 @@ static int sr_done(struct scsi_cmnd *SCpnt)
break;
error_sector =
get_unaligned_be32(&SCpnt->sense_buffer[3]);
- if (SCpnt->request->bio != NULL)
- block_sectors =
- bio_sectors(SCpnt->request->bio);
+ if (rq->bio != NULL)
+ block_sectors = bio_sectors(rq->bio);
if (block_sectors < 4)
block_sectors = 4;
if (cd->device->sector_size == 2048)
error_sector <<= 2;
error_sector &= ~(block_sectors - 1);
- good_bytes = (error_sector -
- blk_rq_pos(SCpnt->request)) << 9;
+ good_bytes = (error_sector - blk_rq_pos(rq)) << 9;
if (good_bytes < 0 || good_bytes >= this_count)
good_bytes = 0;
/*
@@ -393,7 +395,7 @@ static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt)
{
int block = 0, this_count, s_size;
struct scsi_cd *cd;
- struct request *rq = SCpnt->request;
+ struct request *rq = scsi_cmd_to_rq(SCpnt);
blk_status_t ret;
ret = scsi_alloc_sgtables(SCpnt);
@@ -558,53 +560,14 @@ static void sr_block_release(struct gendisk *disk, fmode_t mode)
static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
unsigned long arg)
{
- struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
+ struct gendisk *disk = bdev->bd_disk;
+ struct scsi_cd *cd = scsi_cd(disk);
struct scsi_device *sdev = cd->device;
void __user *argp = (void __user *)arg;
int ret;
- mutex_lock(&cd->lock);
-
- ret = scsi_ioctl_block_when_processing_errors(sdev, cmd,
- (mode & FMODE_NDELAY) != 0);
- if (ret)
- goto out;
-
- scsi_autopm_get_device(sdev);
-
- /*
- * Send SCSI addressing ioctls directly to mid level, send other
- * ioctls to cdrom/block level.
- */
- switch (cmd) {
- case SCSI_IOCTL_GET_IDLUN:
- case SCSI_IOCTL_GET_BUS_NUMBER:
- ret = scsi_ioctl(sdev, cmd, argp);
- goto put;
- }
-
- ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
- if (ret != -ENOSYS)
- goto put;
-
- ret = scsi_ioctl(sdev, cmd, argp);
-
-put:
- scsi_autopm_put_device(sdev);
-
-out:
- mutex_unlock(&cd->lock);
- return ret;
-}
-
-#ifdef CONFIG_COMPAT
-static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
- unsigned long arg)
-{
- struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
- struct scsi_device *sdev = cd->device;
- void __user *argp = compat_ptr(arg);
- int ret;
+ if (bdev_is_partition(bdev) && !capable(CAP_SYS_RAWIO))
+ return -ENOIOCTLCMD;
mutex_lock(&cd->lock);
@@ -615,32 +578,19 @@ static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsign
scsi_autopm_get_device(sdev);
- /*
- * Send SCSI addressing ioctls directly to mid level, send other
- * ioctls to cdrom/block level.
- */
- switch (cmd) {
- case SCSI_IOCTL_GET_IDLUN:
- case SCSI_IOCTL_GET_BUS_NUMBER:
- ret = scsi_compat_ioctl(sdev, cmd, argp);
- goto put;
+ if (ret != CDROMCLOSETRAY && ret != CDROMEJECT) {
+ ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
+ if (ret != -ENOSYS)
+ goto put;
}
-
- ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, (unsigned long)argp);
- if (ret != -ENOSYS)
- goto put;
-
- ret = scsi_compat_ioctl(sdev, cmd, argp);
+ ret = scsi_ioctl(sdev, disk, mode, cmd, argp);
put:
scsi_autopm_put_device(sdev);
-
out:
mutex_unlock(&cd->lock);
return ret;
-
}
-#endif
static unsigned int sr_block_check_events(struct gendisk *disk,
unsigned int clearing)
@@ -665,9 +615,7 @@ static const struct block_device_operations sr_bdops =
.open = sr_block_open,
.release = sr_block_release,
.ioctl = sr_block_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = sr_block_compat_ioctl,
-#endif
+ .compat_ioctl = blkdev_compat_ptr_ioctl,
.check_events = sr_block_check_events,
};
@@ -1008,6 +956,57 @@ static int sr_packet(struct cdrom_device_info *cdi,
return cgc->stat;
}
+static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf,
+ u32 lba, u32 nr, u8 *last_sense)
+{
+ struct gendisk *disk = cdi->disk;
+ u32 len = nr * CD_FRAMESIZE_RAW;
+ struct scsi_request *req;
+ struct request *rq;
+ struct bio *bio;
+ int ret;
+
+ rq = blk_get_request(disk->queue, REQ_OP_DRV_IN, 0);
+ if (IS_ERR(rq))
+ return PTR_ERR(rq);
+ req = scsi_req(rq);
+
+ ret = blk_rq_map_user(disk->queue, rq, NULL, ubuf, len, GFP_KERNEL);
+ if (ret)
+ goto out_put_request;
+
+ req->cmd[0] = GPCMD_READ_CD;
+ req->cmd[1] = 1 << 2;
+ req->cmd[2] = (lba >> 24) & 0xff;
+ req->cmd[3] = (lba >> 16) & 0xff;
+ req->cmd[4] = (lba >> 8) & 0xff;
+ req->cmd[5] = lba & 0xff;
+ req->cmd[6] = (nr >> 16) & 0xff;
+ req->cmd[7] = (nr >> 8) & 0xff;
+ req->cmd[8] = nr & 0xff;
+ req->cmd[9] = 0xf8;
+ req->cmd_len = 12;
+ rq->timeout = 60 * HZ;
+ bio = rq->bio;
+
+ blk_execute_rq(disk, rq, 0);
+ if (scsi_req(rq)->result) {
+ struct scsi_sense_hdr sshdr;
+
+ scsi_normalize_sense(req->sense, req->sense_len,
+ &sshdr);
+ *last_sense = sshdr.sense_key;
+ ret = -EIO;
+ }
+
+ if (blk_rq_unmap_user(bio))
+ ret = -EFAULT;
+out_put_request:
+ blk_put_request(rq);
+ return ret;
+}
+
+
/**
* sr_kref_release - Called to free the scsi_cd structure
* @kref: pointer to embedded kref
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index d1abc020f3c0..9d04929f03a1 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3494,8 +3494,9 @@ out:
/* The ioctl command */
-static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user *p)
+static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
{
+ void __user *p = (void __user *)arg;
int i, cmd_nr, cmd_type, bt;
int retval = 0;
unsigned int blk;
@@ -3815,74 +3816,44 @@ static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user
goto out;
}
mutex_unlock(&STp->lock);
- switch (cmd_in) {
- case SCSI_IOCTL_STOP_UNIT:
- /* unload */
- retval = scsi_ioctl(STp->device, cmd_in, p);
- if (!retval) {
- STp->rew_at_close = 0;
- STp->ready = ST_NO_TAPE;
- }
- return retval;
- case SCSI_IOCTL_GET_IDLUN:
- case SCSI_IOCTL_GET_BUS_NUMBER:
- break;
+ switch (cmd_in) {
+ case SG_IO:
+ case SCSI_IOCTL_SEND_COMMAND:
+ case CDROM_SEND_PACKET:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ default:
+ break;
+ }
- default:
- if ((cmd_in == SG_IO ||
- cmd_in == SCSI_IOCTL_SEND_COMMAND ||
- cmd_in == CDROM_SEND_PACKET) &&
- !capable(CAP_SYS_RAWIO))
- i = -EPERM;
- else
- i = scsi_cmd_ioctl(STp->device->request_queue,
- NULL, file->f_mode, cmd_in,
- p);
- if (i != -ENOTTY)
- return i;
- break;
+ retval = scsi_ioctl(STp->device, NULL, file->f_mode, cmd_in, p);
+ if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) {
+ /* unload */
+ STp->rew_at_close = 0;
+ STp->ready = ST_NO_TAPE;
}
- return -ENOTTY;
+ return retval;
out:
mutex_unlock(&STp->lock);
return retval;
}
-static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
-{
- void __user *p = (void __user *)arg;
- struct scsi_tape *STp = file->private_data;
- int ret;
-
- ret = st_ioctl_common(file, cmd_in, p);
- if (ret != -ENOTTY)
- return ret;
-
- return scsi_ioctl(STp->device, cmd_in, p);
-}
-
#ifdef CONFIG_COMPAT
static long st_compat_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
{
- void __user *p = compat_ptr(arg);
- struct scsi_tape *STp = file->private_data;
- int ret;
-
/* argument conversion is handled using put_user_mtpos/put_user_mtget */
switch (cmd_in) {
case MTIOCPOS32:
- return st_ioctl_common(file, MTIOCPOS, p);
+ cmd_in = MTIOCPOS;
+ break;
case MTIOCGET32:
- return st_ioctl_common(file, MTIOCGET, p);
+ cmd_in = MTIOCGET;
+ break;
}
- ret = st_ioctl_common(file, cmd_in, p);
- if (ret != -ENOTTY)
- return ret;
-
- return scsi_compat_ioctl(STp->device, cmd_in, p);
+ return st_ioctl(file, cmd_in, arg);
}
#endif
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 491b435273a6..f1ba7f5b52a8 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -540,7 +540,7 @@ stex_ss_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
msg_h = (struct st_msg_header *)req - 1;
if (likely(cmd)) {
msg_h->channel = (u8)cmd->device->channel;
- msg_h->timeout = cpu_to_le16(cmd->request->timeout/HZ);
+ msg_h->timeout = cpu_to_le16(scsi_cmd_to_rq(cmd)->timeout / HZ);
}
addr = hba->dma_handle + hba->req_head * hba->rq_size;
addr += (hba->ccb[tag].sg_count+4)/11;
@@ -690,7 +690,7 @@ stex_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
cmd->scsi_done = done;
- tag = cmd->request->tag;
+ tag = scsi_cmd_to_rq(cmd)->tag;
if (unlikely(tag >= host->can_queue))
return SCSI_MLQUEUE_HOST_BUSY;
@@ -1246,7 +1246,7 @@ static int stex_abort(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
struct st_hba *hba = (struct st_hba *)host->hostdata;
- u16 tag = cmd->request->tag;
+ u16 tag = scsi_cmd_to_rq(cmd)->tag;
void __iomem *base;
u32 data;
int result = SUCCESS;
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 37506b3fe5a9..ebbbc1299c62 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -710,7 +710,7 @@ static u64 storvsc_next_request_id(struct vmbus_channel *channel, u64 rqst_addr)
* Cannot return an ID of 0, which is reserved for an unsolicited
* message from Hyper-V.
*/
- return (u64)blk_mq_unique_tag(request->cmd->request) + 1;
+ return (u64)blk_mq_unique_tag(scsi_cmd_to_rq(request->cmd)) + 1;
}
static void handle_sc_creation(struct vmbus_channel *new_sc)
@@ -1211,7 +1211,7 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device,
storvsc_log(device, loglevel,
"tag#%d cmd 0x%x status: scsi 0x%x srb 0x%x hv 0x%x\n",
- request->cmd->request->tag,
+ scsi_cmd_to_rq(request->cmd)->tag,
stor_pkt->vm_srb.cdb[0],
vstor_packet->vm_srb.scsi_status,
vstor_packet->vm_srb.srb_status,
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index 2e3fbc2fae97..f7f724a3ff1d 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -336,7 +336,7 @@ static int sun3scsi_dma_xfer_len(struct NCR5380_hostdata *hostdata,
{
int wanted_len = cmd->SCp.this_residual;
- if (wanted_len < DMA_MIN_SIZE || blk_rq_is_passthrough(cmd->request))
+ if (wanted_len < DMA_MIN_SIZE || blk_rq_is_passthrough(scsi_cmd_to_rq(cmd)))
return 0;
return wanted_len;
@@ -366,8 +366,9 @@ static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data)
}
/* clean up after our dma is done */
-static int sun3scsi_dma_finish(int write_flag)
+static int sun3scsi_dma_finish(enum dma_data_direction data_dir)
{
+ const bool write_flag = data_dir == DMA_TO_DEVICE;
unsigned short __maybe_unused count;
unsigned short fifo;
int ret = 0;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 16b65fc4405c..6d0b07b9cb31 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -500,8 +500,8 @@ static int sym53c8xx_queue_command_lck(struct scsi_cmnd *cmd,
* Shorten our settle_time if needed for
* this command not to time out.
*/
- if (np->s.settle_time_valid && cmd->request->timeout) {
- unsigned long tlimit = jiffies + cmd->request->timeout;
+ if (np->s.settle_time_valid && scsi_cmd_to_rq(cmd)->timeout) {
+ unsigned long tlimit = jiffies + scsi_cmd_to_rq(cmd)->timeout;
tlimit -= SYM_CONF_TIMER_INTERVAL*2;
if (time_after(np->s.settle_time, tlimit)) {
np->s.settle_time = tlimit;
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 2d137953e7b4..432df76e6318 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -183,3 +183,19 @@ config SCSI_UFS_CRYPTO
Enabling this makes it possible for the kernel to use the crypto
capabilities of the UFS device (if present) to perform crypto
operations on data being transferred to/from the device.
+
+config SCSI_UFS_HPB
+ bool "Support UFS Host Performance Booster"
+ depends on SCSI_UFSHCD
+ help
+ The UFS HPB feature improves random read performance. It caches
+ L2P (logical to physical) map of UFS to host DRAM. The driver uses HPB
+ read command by piggybacking physical page number for bypassing FTL (flash
+ translation layer)'s L2P address translation.
+
+config SCSI_UFS_FAULT_INJECTION
+ bool "UFS Fault Injection Support"
+ depends on SCSI_UFSHCD && FAULT_INJECTION
+ help
+ Enable fault injection support in the UFS driver. This makes it easier
+ to test the UFS error handler and abort handler.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 06f3a3fe4a44..c407da9b5171 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -8,6 +8,8 @@ ufshcd-core-y += ufshcd.o ufs-sysfs.o
ufshcd-core-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
ufshcd-core-$(CONFIG_SCSI_UFS_CRYPTO) += ufshcd-crypto.o
+ufshcd-core-$(CONFIG_SCSI_UFS_HPB) += ufshpb.o
+ufshcd-core-$(CONFIG_SCSI_UFS_FAULT_INJECTION) += ufs-fault-injection.o
obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o
diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
index 908ff39c4856..7da8be2f35c4 100644
--- a/drivers/scsi/ufs/cdns-pltfrm.c
+++ b/drivers/scsi/ufs/cdns-pltfrm.c
@@ -318,11 +318,8 @@ static int cdns_ufs_pltfrm_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
- .suspend = ufshcd_pltfrm_suspend,
- .resume = ufshcd_pltfrm_resume,
- .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
- .runtime_resume = ufshcd_pltfrm_runtime_resume,
- .runtime_idle = ufshcd_pltfrm_runtime_idle,
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
};
diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c b/drivers/scsi/ufs/tc-dwc-g210-pci.c
index ec4589afbc13..679289e1a78e 100644
--- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
+++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
@@ -23,31 +23,6 @@ static int tc_type = TC_G210_INV;
module_param(tc_type, int, 0);
MODULE_PARM_DESC(tc_type, "Test Chip Type (20 = 20-bit, 40 = 40-bit)");
-static int tc_dwc_g210_pci_suspend(struct device *dev)
-{
- return ufshcd_system_suspend(dev_get_drvdata(dev));
-}
-
-static int tc_dwc_g210_pci_resume(struct device *dev)
-{
- return ufshcd_system_resume(dev_get_drvdata(dev));
-}
-
-static int tc_dwc_g210_pci_runtime_suspend(struct device *dev)
-{
- return ufshcd_runtime_suspend(dev_get_drvdata(dev));
-}
-
-static int tc_dwc_g210_pci_runtime_resume(struct device *dev)
-{
- return ufshcd_runtime_resume(dev_get_drvdata(dev));
-}
-
-static int tc_dwc_g210_pci_runtime_idle(struct device *dev)
-{
- return ufshcd_runtime_idle(dev_get_drvdata(dev));
-}
-
/*
* struct ufs_hba_dwc_vops - UFS DWC specific variant operations
*/
@@ -143,11 +118,8 @@ tc_dwc_g210_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
- .suspend = tc_dwc_g210_pci_suspend,
- .resume = tc_dwc_g210_pci_resume,
- .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
- .runtime_resume = tc_dwc_g210_pci_runtime_resume,
- .runtime_idle = tc_dwc_g210_pci_runtime_idle,
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
};
diff --git a/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c b/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c
index a1268e4f44d6..783ec43efa78 100644
--- a/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c
+++ b/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c
@@ -84,11 +84,8 @@ static int tc_dwc_g210_pltfm_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = {
- .suspend = ufshcd_pltfrm_suspend,
- .resume = ufshcd_pltfrm_resume,
- .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
- .runtime_resume = ufshcd_pltfrm_runtime_resume,
- .runtime_idle = ufshcd_pltfrm_runtime_idle,
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
};
static struct platform_driver tc_dwc_g210_pltfm_driver = {
diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
index cf46d6f86e0e..a14dd8ce56d4 100644
--- a/drivers/scsi/ufs/ufs-exynos.c
+++ b/drivers/scsi/ufs/ufs-exynos.c
@@ -260,7 +260,7 @@ static int exynos_ufs_get_clk_info(struct exynos_ufs *ufs)
struct ufs_hba *hba = ufs->hba;
struct list_head *head = &hba->clk_list_head;
struct ufs_clk_info *clki;
- u32 pclk_rate;
+ unsigned long pclk_rate;
u32 f_min, f_max;
u8 div = 0;
int ret = 0;
@@ -299,7 +299,7 @@ static int exynos_ufs_get_clk_info(struct exynos_ufs *ufs)
}
if (unlikely(pclk_rate < f_min || pclk_rate > f_max)) {
- dev_err(hba->dev, "not available pclk range %d\n", pclk_rate);
+ dev_err(hba->dev, "not available pclk range %lu\n", pclk_rate);
ret = -EINVAL;
goto out;
}
@@ -1287,11 +1287,8 @@ static const struct of_device_id exynos_ufs_of_match[] = {
};
static const struct dev_pm_ops exynos_ufs_pm_ops = {
- .suspend = ufshcd_pltfrm_suspend,
- .resume = ufshcd_pltfrm_resume,
- .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
- .runtime_resume = ufshcd_pltfrm_runtime_resume,
- .runtime_idle = ufshcd_pltfrm_runtime_idle,
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
};
diff --git a/drivers/scsi/ufs/ufs-exynos.h b/drivers/scsi/ufs/ufs-exynos.h
index 67505fe32ebf..dadf4fd10dd8 100644
--- a/drivers/scsi/ufs/ufs-exynos.h
+++ b/drivers/scsi/ufs/ufs-exynos.h
@@ -184,7 +184,7 @@ struct exynos_ufs {
u32 pclk_div;
u32 pclk_avail_min;
u32 pclk_avail_max;
- u32 mclk_rate;
+ unsigned long mclk_rate;
int avail_ln_rx;
int avail_ln_tx;
int rx_sel_idx;
diff --git a/drivers/scsi/ufs/ufs-fault-injection.c b/drivers/scsi/ufs/ufs-fault-injection.c
new file mode 100644
index 000000000000..7ac7c4e7ff83
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-fault-injection.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/kconfig.h>
+#include <linux/types.h>
+#include <linux/fault-inject.h>
+#include <linux/module.h>
+#include "ufs-fault-injection.h"
+
+static int ufs_fault_get(char *buffer, const struct kernel_param *kp);
+static int ufs_fault_set(const char *val, const struct kernel_param *kp);
+
+static const struct kernel_param_ops ufs_fault_ops = {
+ .get = ufs_fault_get,
+ .set = ufs_fault_set,
+};
+
+enum { FAULT_INJ_STR_SIZE = 80 };
+
+/*
+ * For more details about fault injection, please refer to
+ * Documentation/fault-injection/fault-injection.rst.
+ */
+static char g_trigger_eh_str[FAULT_INJ_STR_SIZE];
+module_param_cb(trigger_eh, &ufs_fault_ops, g_trigger_eh_str, 0644);
+MODULE_PARM_DESC(trigger_eh,
+ "Fault injection. trigger_eh=<interval>,<probability>,<space>,<times>");
+static DECLARE_FAULT_ATTR(ufs_trigger_eh_attr);
+
+static char g_timeout_str[FAULT_INJ_STR_SIZE];
+module_param_cb(timeout, &ufs_fault_ops, g_timeout_str, 0644);
+MODULE_PARM_DESC(timeout,
+ "Fault injection. timeout=<interval>,<probability>,<space>,<times>");
+static DECLARE_FAULT_ATTR(ufs_timeout_attr);
+
+static int ufs_fault_get(char *buffer, const struct kernel_param *kp)
+{
+ const char *fault_str = kp->arg;
+
+ return sysfs_emit(buffer, "%s\n", fault_str);
+}
+
+static int ufs_fault_set(const char *val, const struct kernel_param *kp)
+{
+ struct fault_attr *attr = NULL;
+
+ if (kp->arg == g_trigger_eh_str)
+ attr = &ufs_trigger_eh_attr;
+ else if (kp->arg == g_timeout_str)
+ attr = &ufs_timeout_attr;
+
+ if (WARN_ON_ONCE(!attr))
+ return -EINVAL;
+
+ if (!setup_fault_attr(attr, (char *)val))
+ return -EINVAL;
+
+ strlcpy(kp->arg, val, FAULT_INJ_STR_SIZE);
+
+ return 0;
+}
+
+bool ufs_trigger_eh(void)
+{
+ return should_fail(&ufs_trigger_eh_attr, 1);
+}
+
+bool ufs_fail_completion(void)
+{
+ return should_fail(&ufs_timeout_attr, 1);
+}
diff --git a/drivers/scsi/ufs/ufs-fault-injection.h b/drivers/scsi/ufs/ufs-fault-injection.h
new file mode 100644
index 000000000000..6d0cd8e10c87
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-fault-injection.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _UFS_FAULT_INJECTION_H
+#define _UFS_FAULT_INJECTION_H
+
+#include <linux/kconfig.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_SCSI_UFS_FAULT_INJECTION
+bool ufs_trigger_eh(void);
+bool ufs_fail_completion(void);
+#else
+static inline bool ufs_trigger_eh(void)
+{
+ return false;
+}
+
+static inline bool ufs_fail_completion(void)
+{
+ return false;
+}
+#endif
+
+#endif /* _UFS_FAULT_INJECTION_H */
diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c
index 5b147a48161b..6b706de8354b 100644
--- a/drivers/scsi/ufs/ufs-hisi.c
+++ b/drivers/scsi/ufs/ufs-hisi.c
@@ -572,11 +572,8 @@ static int ufs_hisi_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops ufs_hisi_pm_ops = {
- .suspend = ufshcd_pltfrm_suspend,
- .resume = ufshcd_pltfrm_resume,
- .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
- .runtime_resume = ufshcd_pltfrm_runtime_resume,
- .runtime_idle = ufshcd_pltfrm_runtime_idle,
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
};
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
index d2c251628a05..80b3545dd17d 100644
--- a/drivers/scsi/ufs/ufs-mediatek.c
+++ b/drivers/scsi/ufs/ufs-mediatek.c
@@ -1140,11 +1140,8 @@ static int ufs_mtk_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops ufs_mtk_pm_ops = {
- .suspend = ufshcd_pltfrm_suspend,
- .resume = ufshcd_pltfrm_resume,
- .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
- .runtime_resume = ufshcd_pltfrm_runtime_resume,
- .runtime_idle = ufshcd_pltfrm_runtime_idle,
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
};
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9b1d18d7c9bb..9d9770f1db4f 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1546,11 +1546,8 @@ MODULE_DEVICE_TABLE(acpi, ufs_qcom_acpi_match);
#endif
static const struct dev_pm_ops ufs_qcom_pm_ops = {
- .suspend = ufshcd_pltfrm_suspend,
- .resume = ufshcd_pltfrm_resume,
- .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
- .runtime_resume = ufshcd_pltfrm_runtime_resume,
- .runtime_idle = ufshcd_pltfrm_runtime_idle,
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
};
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 52bd807f7940..5c405ff7b6ea 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -604,6 +604,8 @@ UFS_DEVICE_DESC_PARAM(device_version, _DEV_VER, 2);
UFS_DEVICE_DESC_PARAM(number_of_secure_wpa, _NUM_SEC_WPA, 1);
UFS_DEVICE_DESC_PARAM(psa_max_data_size, _PSA_MAX_DATA, 4);
UFS_DEVICE_DESC_PARAM(psa_state_timeout, _PSA_TMT, 1);
+UFS_DEVICE_DESC_PARAM(hpb_version, _HPB_VER, 2);
+UFS_DEVICE_DESC_PARAM(hpb_control, _HPB_CONTROL, 1);
UFS_DEVICE_DESC_PARAM(ext_feature_sup, _EXT_UFS_FEATURE_SUP, 4);
UFS_DEVICE_DESC_PARAM(wb_presv_us_en, _WB_PRESRV_USRSPC_EN, 1);
UFS_DEVICE_DESC_PARAM(wb_type, _WB_TYPE, 1);
@@ -636,6 +638,8 @@ static struct attribute *ufs_sysfs_device_descriptor[] = {
&dev_attr_number_of_secure_wpa.attr,
&dev_attr_psa_max_data_size.attr,
&dev_attr_psa_state_timeout.attr,
+ &dev_attr_hpb_version.attr,
+ &dev_attr_hpb_control.attr,
&dev_attr_ext_feature_sup.attr,
&dev_attr_wb_presv_us_en.attr,
&dev_attr_wb_type.attr,
@@ -709,6 +713,10 @@ UFS_GEOMETRY_DESC_PARAM(enh4_memory_max_alloc_units,
_ENM4_MAX_NUM_UNITS, 4);
UFS_GEOMETRY_DESC_PARAM(enh4_memory_capacity_adjustment_factor,
_ENM4_CAP_ADJ_FCTR, 2);
+UFS_GEOMETRY_DESC_PARAM(hpb_region_size, _HPB_REGION_SIZE, 1);
+UFS_GEOMETRY_DESC_PARAM(hpb_number_lu, _HPB_NUMBER_LU, 1);
+UFS_GEOMETRY_DESC_PARAM(hpb_subregion_size, _HPB_SUBREGION_SIZE, 1);
+UFS_GEOMETRY_DESC_PARAM(hpb_max_active_regions, _HPB_MAX_ACTIVE_REGS, 2);
UFS_GEOMETRY_DESC_PARAM(wb_max_alloc_units, _WB_MAX_ALLOC_UNITS, 4);
UFS_GEOMETRY_DESC_PARAM(wb_max_wb_luns, _WB_MAX_WB_LUNS, 1);
UFS_GEOMETRY_DESC_PARAM(wb_buff_cap_adj, _WB_BUFF_CAP_ADJ, 1);
@@ -746,6 +754,10 @@ static struct attribute *ufs_sysfs_geometry_descriptor[] = {
&dev_attr_enh3_memory_capacity_adjustment_factor.attr,
&dev_attr_enh4_memory_max_alloc_units.attr,
&dev_attr_enh4_memory_capacity_adjustment_factor.attr,
+ &dev_attr_hpb_region_size.attr,
+ &dev_attr_hpb_number_lu.attr,
+ &dev_attr_hpb_subregion_size.attr,
+ &dev_attr_hpb_max_active_regions.attr,
&dev_attr_wb_max_alloc_units.attr,
&dev_attr_wb_max_wb_luns.attr,
&dev_attr_wb_buff_cap_adj.attr,
@@ -1006,6 +1018,7 @@ UFS_FLAG(disable_fw_update, _PERMANENTLY_DISABLE_FW_UPDATE);
UFS_FLAG(wb_enable, _WB_EN);
UFS_FLAG(wb_flush_en, _WB_BUFF_FLUSH_EN);
UFS_FLAG(wb_flush_during_h8, _WB_BUFF_FLUSH_DURING_HIBERN8);
+UFS_FLAG(hpb_enable, _HPB_EN);
static struct attribute *ufs_sysfs_device_flags[] = {
&dev_attr_device_init.attr,
@@ -1019,6 +1032,7 @@ static struct attribute *ufs_sysfs_device_flags[] = {
&dev_attr_wb_enable.attr,
&dev_attr_wb_flush_en.attr,
&dev_attr_wb_flush_during_h8.attr,
+ &dev_attr_hpb_enable.attr,
NULL,
};
@@ -1065,6 +1079,7 @@ out: \
static DEVICE_ATTR_RO(_name)
UFS_ATTRIBUTE(boot_lun_enabled, _BOOT_LU_EN);
+UFS_ATTRIBUTE(max_data_size_hpb_single_cmd, _MAX_HPB_SINGLE_CMD);
UFS_ATTRIBUTE(current_power_mode, _POWER_MODE);
UFS_ATTRIBUTE(active_icc_level, _ACTIVE_ICC_LVL);
UFS_ATTRIBUTE(ooo_data_enabled, _OOO_DATA_EN);
@@ -1088,6 +1103,7 @@ UFS_ATTRIBUTE(wb_cur_buf, _CURR_WB_BUFF_SIZE);
static struct attribute *ufs_sysfs_attributes[] = {
&dev_attr_boot_lun_enabled.attr,
+ &dev_attr_max_data_size_hpb_single_cmd.attr,
&dev_attr_current_power_mode.attr,
&dev_attr_active_icc_level.attr,
&dev_attr_ooo_data_enabled.attr,
@@ -1147,6 +1163,7 @@ static DEVICE_ATTR_RO(_pname)
#define UFS_UNIT_DESC_PARAM(_name, _uname, _size) \
UFS_LUN_DESC_PARAM(_name, _uname, UNIT, _size)
+UFS_UNIT_DESC_PARAM(lu_enable, _LU_ENABLE, 1);
UFS_UNIT_DESC_PARAM(boot_lun_id, _BOOT_LUN_ID, 1);
UFS_UNIT_DESC_PARAM(lun_write_protect, _LU_WR_PROTECT, 1);
UFS_UNIT_DESC_PARAM(lun_queue_depth, _LU_Q_DEPTH, 1);
@@ -1160,10 +1177,13 @@ UFS_UNIT_DESC_PARAM(provisioning_type, _PROVISIONING_TYPE, 1);
UFS_UNIT_DESC_PARAM(physical_memory_resourse_count, _PHY_MEM_RSRC_CNT, 8);
UFS_UNIT_DESC_PARAM(context_capabilities, _CTX_CAPABILITIES, 2);
UFS_UNIT_DESC_PARAM(large_unit_granularity, _LARGE_UNIT_SIZE_M1, 1);
+UFS_UNIT_DESC_PARAM(hpb_lu_max_active_regions, _HPB_LU_MAX_ACTIVE_RGNS, 2);
+UFS_UNIT_DESC_PARAM(hpb_pinned_region_start_offset, _HPB_PIN_RGN_START_OFF, 2);
+UFS_UNIT_DESC_PARAM(hpb_number_pinned_regions, _HPB_NUM_PIN_RGNS, 2);
UFS_UNIT_DESC_PARAM(wb_buf_alloc_units, _WB_BUF_ALLOC_UNITS, 4);
-
static struct attribute *ufs_sysfs_unit_descriptor[] = {
+ &dev_attr_lu_enable.attr,
&dev_attr_boot_lun_id.attr,
&dev_attr_lun_write_protect.attr,
&dev_attr_lun_queue_depth.attr,
@@ -1177,6 +1197,9 @@ static struct attribute *ufs_sysfs_unit_descriptor[] = {
&dev_attr_physical_memory_resourse_count.attr,
&dev_attr_context_capabilities.attr,
&dev_attr_large_unit_granularity.attr,
+ &dev_attr_hpb_lu_max_active_regions.attr,
+ &dev_attr_hpb_pinned_region_start_offset.attr,
+ &dev_attr_hpb_number_pinned_regions.attr,
&dev_attr_wb_buf_alloc_units.attr,
NULL,
};
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index cb80b9670bfe..8c6b38b1b142 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -122,12 +122,14 @@ enum flag_idn {
QUERY_FLAG_IDN_WB_EN = 0x0E,
QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN = 0x0F,
QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8 = 0x10,
+ QUERY_FLAG_IDN_HPB_RESET = 0x11,
+ QUERY_FLAG_IDN_HPB_EN = 0x12,
};
/* Attribute idn for Query requests */
enum attr_idn {
QUERY_ATTR_IDN_BOOT_LU_EN = 0x00,
- QUERY_ATTR_IDN_RESERVED = 0x01,
+ QUERY_ATTR_IDN_MAX_HPB_SINGLE_CMD = 0x01,
QUERY_ATTR_IDN_POWER_MODE = 0x02,
QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
QUERY_ATTR_IDN_OOO_DATA_EN = 0x04,
@@ -195,6 +197,9 @@ enum unit_desc_param {
UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT = 0x18,
UNIT_DESC_PARAM_CTX_CAPABILITIES = 0x20,
UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1 = 0x22,
+ UNIT_DESC_PARAM_HPB_LU_MAX_ACTIVE_RGNS = 0x23,
+ UNIT_DESC_PARAM_HPB_PIN_RGN_START_OFF = 0x25,
+ UNIT_DESC_PARAM_HPB_NUM_PIN_RGNS = 0x27,
UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS = 0x29,
};
@@ -235,6 +240,8 @@ enum device_desc_param {
DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25,
DEVICE_DESC_PARAM_PSA_TMT = 0x29,
DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
+ DEVICE_DESC_PARAM_HPB_VER = 0x40,
+ DEVICE_DESC_PARAM_HPB_CONTROL = 0x42,
DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP = 0x4F,
DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN = 0x53,
DEVICE_DESC_PARAM_WB_TYPE = 0x54,
@@ -283,6 +290,10 @@ enum geometry_desc_param {
GEOMETRY_DESC_PARAM_ENM4_MAX_NUM_UNITS = 0x3E,
GEOMETRY_DESC_PARAM_ENM4_CAP_ADJ_FCTR = 0x42,
GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE = 0x44,
+ GEOMETRY_DESC_PARAM_HPB_REGION_SIZE = 0x48,
+ GEOMETRY_DESC_PARAM_HPB_NUMBER_LU = 0x49,
+ GEOMETRY_DESC_PARAM_HPB_SUBREGION_SIZE = 0x4A,
+ GEOMETRY_DESC_PARAM_HPB_MAX_ACTIVE_REGS = 0x4B,
GEOMETRY_DESC_PARAM_WB_MAX_ALLOC_UNITS = 0x4F,
GEOMETRY_DESC_PARAM_WB_MAX_WB_LUNS = 0x53,
GEOMETRY_DESC_PARAM_WB_BUFF_CAP_ADJ = 0x54,
@@ -327,8 +338,10 @@ enum {
/* Possible values for dExtendedUFSFeaturesSupport */
enum {
+ UFS_DEV_HPB_SUPPORT = BIT(7),
UFS_DEV_WRITE_BOOSTER_SUP = BIT(8),
};
+#define UFS_DEV_HPB_SUPPORT_VERSION 0x310
#define POWER_DESC_MAX_ACTV_ICC_LVLS 16
@@ -466,6 +479,41 @@ struct utp_cmd_rsp {
u8 sense_data[UFS_SENSE_SIZE];
};
+struct ufshpb_active_field {
+ __be16 active_rgn;
+ __be16 active_srgn;
+};
+#define HPB_ACT_FIELD_SIZE 4
+
+/**
+ * struct utp_hpb_rsp - Response UPIU structure
+ * @residual_transfer_count: Residual transfer count DW-3
+ * @reserved1: Reserved double words DW-4 to DW-7
+ * @sense_data_len: Sense data length DW-8 U16
+ * @desc_type: Descriptor type of sense data
+ * @additional_len: Additional length of sense data
+ * @hpb_op: HPB operation type
+ * @lun: LUN of response UPIU
+ * @active_rgn_cnt: Active region count
+ * @inactive_rgn_cnt: Inactive region count
+ * @hpb_active_field: Recommended to read HPB region and subregion
+ * @hpb_inactive_field: To be inactivated HPB region and subregion
+ */
+struct utp_hpb_rsp {
+ __be32 residual_transfer_count;
+ __be32 reserved1[4];
+ __be16 sense_data_len;
+ u8 desc_type;
+ u8 additional_len;
+ u8 hpb_op;
+ u8 lun;
+ u8 active_rgn_cnt;
+ u8 inactive_rgn_cnt;
+ struct ufshpb_active_field hpb_active_field[2];
+ __be16 hpb_inactive_field[2];
+};
+#define UTP_HPB_RSP_SIZE 40
+
/**
* struct utp_upiu_rsp - general upiu response structure
* @header: UPIU header structure DW-0 to DW-2
@@ -476,6 +524,7 @@ struct utp_upiu_rsp {
struct utp_upiu_header header;
union {
struct utp_cmd_rsp sr;
+ struct utp_hpb_rsp hr;
struct utp_upiu_query qr;
};
};
@@ -544,6 +593,9 @@ struct ufs_dev_info {
u16 wspecversion;
u32 clk_gating_wait_us;
+ /* UFS HPB related flag */
+ bool hpb_enabled;
+
/* UFS WB related flags */
bool wb_enabled;
bool wb_buf_flush_enabled;
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 07f559ac5883..35ec9ea79869 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -116,4 +116,10 @@ struct ufs_dev_fix {
*/
#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM (1 << 11)
+/*
+ * Some UFS devices require L2P entry should be swapped before being sent to the
+ * UFS device for HPB READ command.
+ */
+#define UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ (1 << 12)
+
#endif /* UFS_QUIRKS_H_ */
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index e6c334bfb4c2..b3bcc5c882da 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -385,48 +385,6 @@ static struct ufs_hba_variant_ops ufs_intel_lkf_hba_vops = {
.device_reset = ufs_intel_device_reset,
};
-#ifdef CONFIG_PM_SLEEP
-/**
- * ufshcd_pci_suspend - suspend power management function
- * @dev: pointer to PCI device handle
- *
- * Returns 0 if successful
- * Returns non-zero otherwise
- */
-static int ufshcd_pci_suspend(struct device *dev)
-{
- return ufshcd_system_suspend(dev_get_drvdata(dev));
-}
-
-/**
- * ufshcd_pci_resume - resume power management function
- * @dev: pointer to PCI device handle
- *
- * Returns 0 if successful
- * Returns non-zero otherwise
- */
-static int ufshcd_pci_resume(struct device *dev)
-{
- return ufshcd_system_resume(dev_get_drvdata(dev));
-}
-
-#endif /* !CONFIG_PM_SLEEP */
-
-#ifdef CONFIG_PM
-static int ufshcd_pci_runtime_suspend(struct device *dev)
-{
- return ufshcd_runtime_suspend(dev_get_drvdata(dev));
-}
-static int ufshcd_pci_runtime_resume(struct device *dev)
-{
- return ufshcd_runtime_resume(dev_get_drvdata(dev));
-}
-static int ufshcd_pci_runtime_idle(struct device *dev)
-{
- return ufshcd_runtime_idle(dev_get_drvdata(dev));
-}
-#endif /* !CONFIG_PM */
-
/**
* ufshcd_pci_shutdown - main function to put the controller in reset state
* @pdev: pointer to PCI device handle
@@ -510,10 +468,8 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
static const struct dev_pm_ops ufshcd_pci_pm_ops = {
- SET_RUNTIME_PM_OPS(ufshcd_pci_runtime_suspend,
- ufshcd_pci_runtime_resume,
- ufshcd_pci_runtime_idle)
- SET_SYSTEM_SLEEP_PM_OPS(ufshcd_pci_suspend, ufshcd_pci_resume)
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
#ifdef CONFIG_PM_SLEEP
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 298e22ef907e..8859c13f4e09 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -170,53 +170,6 @@ out:
return err;
}
-#ifdef CONFIG_PM
-/**
- * ufshcd_pltfrm_suspend - suspend power management function
- * @dev: pointer to device handle
- *
- * Returns 0 if successful
- * Returns non-zero otherwise
- */
-int ufshcd_pltfrm_suspend(struct device *dev)
-{
- return ufshcd_system_suspend(dev_get_drvdata(dev));
-}
-EXPORT_SYMBOL_GPL(ufshcd_pltfrm_suspend);
-
-/**
- * ufshcd_pltfrm_resume - resume power management function
- * @dev: pointer to device handle
- *
- * Returns 0 if successful
- * Returns non-zero otherwise
- */
-int ufshcd_pltfrm_resume(struct device *dev)
-{
- return ufshcd_system_resume(dev_get_drvdata(dev));
-}
-EXPORT_SYMBOL_GPL(ufshcd_pltfrm_resume);
-
-int ufshcd_pltfrm_runtime_suspend(struct device *dev)
-{
- return ufshcd_runtime_suspend(dev_get_drvdata(dev));
-}
-EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_suspend);
-
-int ufshcd_pltfrm_runtime_resume(struct device *dev)
-{
- return ufshcd_runtime_resume(dev_get_drvdata(dev));
-}
-EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_resume);
-
-int ufshcd_pltfrm_runtime_idle(struct device *dev)
-{
- return ufshcd_runtime_idle(dev_get_drvdata(dev));
-}
-EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_idle);
-
-#endif /* CONFIG_PM */
-
void ufshcd_pltfrm_shutdown(struct platform_device *pdev)
{
ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev));
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.h b/drivers/scsi/ufs/ufshcd-pltfrm.h
index 772a8e848098..c33e28ac6ef6 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.h
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.h
@@ -33,22 +33,4 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,
const struct ufs_hba_variant_ops *vops);
void ufshcd_pltfrm_shutdown(struct platform_device *pdev);
-#ifdef CONFIG_PM
-
-int ufshcd_pltfrm_suspend(struct device *dev);
-int ufshcd_pltfrm_resume(struct device *dev);
-int ufshcd_pltfrm_runtime_suspend(struct device *dev);
-int ufshcd_pltfrm_runtime_resume(struct device *dev);
-int ufshcd_pltfrm_runtime_idle(struct device *dev);
-
-#else /* !CONFIG_PM */
-
-#define ufshcd_pltfrm_suspend NULL
-#define ufshcd_pltfrm_resume NULL
-#define ufshcd_pltfrm_runtime_suspend NULL
-#define ufshcd_pltfrm_runtime_resume NULL
-#define ufshcd_pltfrm_runtime_idle NULL
-
-#endif /* CONFIG_PM */
-
#endif /* UFSHCD_PLTFRM_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 708b3b62fc4d..3841ab49f556 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -17,15 +17,18 @@
#include <linux/blk-pm.h>
#include <linux/blkdev.h>
#include <scsi/scsi_driver.h>
+#include <scsi/scsi_transport.h>
+#include "../scsi_transport_api.h"
#include "ufshcd.h"
#include "ufs_quirks.h"
#include "unipro.h"
#include "ufs-sysfs.h"
#include "ufs-debugfs.h"
+#include "ufs-fault-injection.h"
#include "ufs_bsg.h"
#include "ufshcd-crypto.h"
+#include "ufshpb.h"
#include <asm/unaligned.h>
-#include "../sd.h"
#define CREATE_TRACE_POINTS
#include <trace/events/ufs.h>
@@ -128,15 +131,6 @@ enum {
UFSHCD_CAN_QUEUE = 32,
};
-/* UFSHCD states */
-enum {
- UFSHCD_STATE_RESET,
- UFSHCD_STATE_ERROR,
- UFSHCD_STATE_OPERATIONAL,
- UFSHCD_STATE_EH_SCHEDULED_FATAL,
- UFSHCD_STATE_EH_SCHEDULED_NON_FATAL,
-};
-
/* UFSHCD error handling flags */
enum {
UFSHCD_EH_IN_PROGRESS = (1 << 0),
@@ -205,7 +199,8 @@ ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state,
static struct ufs_dev_fix ufs_fixups[] = {
/* UFS cards deviations table */
UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
+ UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
+ UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ),
UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE |
@@ -242,7 +237,6 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up);
static irqreturn_t ufshcd_intr(int irq, void *__hba);
static int ufshcd_change_power_mode(struct ufs_hba *hba,
struct ufs_pa_layer_attr *pwr_mode);
-static void ufshcd_schedule_eh_work(struct ufs_hba *hba);
static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on);
static int ufshcd_setup_vreg(struct ufs_hba *hba, bool on);
static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
@@ -253,11 +247,6 @@ static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable);
static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba);
static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba);
-static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
-{
- return tag >= 0 && tag < hba->nutrs;
-}
-
static inline void ufshcd_enable_irq(struct ufs_hba *hba)
{
if (!hba->is_irq_enabled) {
@@ -371,26 +360,24 @@ static void ufshcd_add_uic_command_trace(struct ufs_hba *hba,
static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,
enum ufs_trace_str_t str_t)
{
- u64 lba = -1;
+ u64 lba;
u8 opcode = 0, group_id = 0;
u32 intr, doorbell;
struct ufshcd_lrb *lrbp = &hba->lrb[tag];
struct scsi_cmnd *cmd = lrbp->cmd;
+ struct request *rq = scsi_cmd_to_rq(cmd);
int transfer_len = -1;
if (!cmd)
return;
- if (!trace_ufshcd_command_enabled()) {
- /* trace UPIU W/O tracing command */
- ufshcd_add_cmd_upiu_trace(hba, tag, str_t);
- return;
- }
-
/* trace UPIU also */
ufshcd_add_cmd_upiu_trace(hba, tag, str_t);
+ if (!trace_ufshcd_command_enabled())
+ return;
+
opcode = cmd->cmnd[0];
- lba = sectors_to_logical(cmd->device, blk_rq_pos(cmd->request));
+ lba = scsi_get_lba(cmd);
if (opcode == READ_10 || opcode == WRITE_10) {
/*
@@ -404,7 +391,7 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag,
/*
* The number of Bytes to be unmapped beginning with the lba.
*/
- transfer_len = blk_rq_bytes(cmd->request);
+ transfer_len = blk_rq_bytes(rq);
}
intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
@@ -758,16 +745,6 @@ static inline void ufshcd_utmrl_clear(struct ufs_hba *hba, u32 pos)
}
/**
- * ufshcd_outstanding_req_clear - Clear a bit in outstanding request field
- * @hba: per adapter instance
- * @tag: position of the bit to be cleared
- */
-static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int tag)
-{
- clear_bit(tag, &hba->outstanding_reqs);
-}
-
-/**
* ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
* @reg: Register value of host controller status
*
@@ -2078,7 +2055,7 @@ static void ufshcd_update_monitor(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
spin_lock_irqsave(hba->host->host_lock, flags);
if (dir >= 0 && hba->monitor.nr_queued[dir] > 0) {
- struct request *req = lrbp->cmd->request;
+ struct request *req = scsi_cmd_to_rq(lrbp->cmd);
struct ufs_hba_monitor *m = &hba->monitor;
ktime_t now, inc, lat;
@@ -2112,27 +2089,22 @@ static inline
void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
{
struct ufshcd_lrb *lrbp = &hba->lrb[task_tag];
+ unsigned long flags;
lrbp->issue_time_stamp = ktime_get();
lrbp->compl_time_stamp = ktime_set(0, 0);
- ufshcd_vops_setup_xfer_req(hba, task_tag, (lrbp->cmd ? true : false));
ufshcd_add_command_trace(hba, task_tag, UFS_CMD_SEND);
ufshcd_clk_scaling_start_busy(hba);
if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
ufshcd_start_monitor(hba, lrbp);
- if (ufshcd_has_utrlcnr(hba)) {
- set_bit(task_tag, &hba->outstanding_reqs);
- ufshcd_writel(hba, 1 << task_tag,
- REG_UTP_TRANSFER_REQ_DOOR_BELL);
- } else {
- unsigned long flags;
- spin_lock_irqsave(hba->host->host_lock, flags);
- set_bit(task_tag, &hba->outstanding_reqs);
- ufshcd_writel(hba, 1 << task_tag,
- REG_UTP_TRANSFER_REQ_DOOR_BELL);
- spin_unlock_irqrestore(hba->host->host_lock, flags);
- }
+ spin_lock_irqsave(&hba->outstanding_lock, flags);
+ if (hba->vops && hba->vops->setup_xfer_req)
+ hba->vops->setup_xfer_req(hba, task_tag, !!lrbp->cmd);
+ __set_bit(task_tag, &hba->outstanding_reqs);
+ ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ spin_unlock_irqrestore(&hba->outstanding_lock, flags);
+
/* Make sure that doorbell is committed immediately */
wmb();
}
@@ -2247,15 +2219,15 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
}
/**
- * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
+ * ufshcd_dispatch_uic_cmd - Dispatch an UIC command to the Unipro layer
* @hba: per adapter instance
* @uic_cmd: UIC command
- *
- * Mutex must be held.
*/
static inline void
ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
{
+ lockdep_assert_held(&hba->uic_cmd_mutex);
+
WARN_ON(hba->active_uic_cmd);
hba->active_uic_cmd = uic_cmd;
@@ -2273,11 +2245,10 @@ ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
}
/**
- * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
+ * ufshcd_wait_for_uic_cmd - Wait for completion of an UIC command
* @hba: per adapter instance
* @uic_cmd: UIC command
*
- * Must be called with mutex held.
* Returns 0 only if success.
*/
static int
@@ -2286,6 +2257,8 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
int ret;
unsigned long flags;
+ lockdep_assert_held(&hba->uic_cmd_mutex);
+
if (wait_for_completion_timeout(&uic_cmd->done,
msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
@@ -2315,14 +2288,15 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
* @uic_cmd: UIC command
* @completion: initialize the completion only if this is set to true
*
- * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
- * with mutex held and host_lock locked.
* Returns 0 only if success.
*/
static int
__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
bool completion)
{
+ lockdep_assert_held(&hba->uic_cmd_mutex);
+ lockdep_assert_held(hba->host->host_lock);
+
if (!ufshcd_ready_for_uic_cmd(hba)) {
dev_err(hba->dev,
"Controller not ready to accept UIC commands\n");
@@ -2701,20 +2675,12 @@ static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i)
*/
static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
{
+ struct ufs_hba *hba = shost_priv(host);
+ int tag = scsi_cmd_to_rq(cmd)->tag;
struct ufshcd_lrb *lrbp;
- struct ufs_hba *hba;
- int tag;
int err = 0;
- hba = shost_priv(host);
-
- tag = cmd->request->tag;
- if (!ufshcd_valid_tag(hba, tag)) {
- dev_err(hba->dev,
- "%s: invalid command tag %d: cmd=0x%p, cmd->request=0x%p",
- __func__, tag, cmd, cmd->request);
- BUG();
- }
+ WARN_ONCE(tag < 0, "Invalid tag %d\n", tag);
if (!down_read_trylock(&hba->clk_scaling_lock))
return SCSI_MLQUEUE_HOST_BUSY;
@@ -2748,12 +2714,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
set_host_byte(cmd, DID_ERROR);
cmd->scsi_done(cmd);
goto out;
- default:
- dev_WARN_ONCE(hba->dev, 1, "%s: invalid state %d\n",
- __func__, hba->ufshcd_state);
- set_host_byte(cmd, DID_BAD_TARGET);
- cmd->scsi_done(cmd);
- goto out;
}
hba->req_abort_count = 0;
@@ -2766,15 +2726,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
WARN_ON(ufshcd_is_clkgating_allowed(hba) &&
(hba->clk_gating.state != CLKS_ON));
- if (unlikely(test_bit(tag, &hba->outstanding_reqs))) {
- if (hba->pm_op_in_progress)
- set_host_byte(cmd, DID_BAD_TARGET);
- else
- err = SCSI_MLQUEUE_HOST_BUSY;
- ufshcd_release(hba);
- goto out;
- }
-
lrbp = &hba->lrb[tag];
WARN_ON(lrbp->cmd);
lrbp->cmd = cmd;
@@ -2784,10 +2735,17 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba) ? true : false;
- ufshcd_prepare_lrbp_crypto(cmd->request, lrbp);
+ ufshcd_prepare_lrbp_crypto(scsi_cmd_to_rq(cmd), lrbp);
lrbp->req_abort_skip = false;
+ err = ufshpb_prep(hba, lrbp);
+ if (err == -EAGAIN) {
+ lrbp->cmd = NULL;
+ ufshcd_release(hba);
+ goto out;
+ }
+
ufshcd_comp_scsi_upiu(hba, lrbp);
err = ufshcd_map_sg(hba, lrbp);
@@ -2796,12 +2754,14 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
ufshcd_release(hba);
goto out;
}
- /* Make sure descriptors are ready before ringing the doorbell */
- wmb();
ufshcd_send_command(hba, tag);
out:
up_read(&hba->clk_scaling_lock);
+
+ if (ufs_trigger_eh())
+ scsi_schedule_eh(hba->host);
+
return err;
}
@@ -2907,8 +2867,6 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
time_left = wait_for_completion_timeout(hba->dev_cmd.complete,
msecs_to_jiffies(max_timeout));
- /* Make sure descriptors are ready before ringing the doorbell */
- wmb();
spin_lock_irqsave(hba->host->host_lock, flags);
hba->dev_cmd.complete = NULL;
if (likely(time_left)) {
@@ -2930,7 +2888,9 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
* we also need to clear the outstanding_request
* field in hba
*/
- ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
+ spin_lock_irqsave(&hba->outstanding_lock, flags);
+ __clear_bit(lrbp->task_tag, &hba->outstanding_reqs);
+ spin_unlock_irqrestore(&hba->outstanding_lock, flags);
}
return err;
@@ -2949,11 +2909,11 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
enum dev_cmd_type cmd_type, int timeout)
{
struct request_queue *q = hba->cmd_queue;
+ DECLARE_COMPLETION_ONSTACK(wait);
struct request *req;
struct ufshcd_lrb *lrbp;
int err;
int tag;
- struct completion wait;
down_read(&hba->clk_scaling_lock);
@@ -2968,17 +2928,11 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
goto out_unlock;
}
tag = req->tag;
- WARN_ON_ONCE(!ufshcd_valid_tag(hba, tag));
+ WARN_ONCE(tag < 0, "Invalid tag %d\n", tag);
/* Set the timeout such that the SCSI error handler is not activated. */
req->timeout = msecs_to_jiffies(2 * timeout);
blk_mq_start_request(req);
- if (unlikely(test_bit(tag, &hba->outstanding_reqs))) {
- err = -EBUSY;
- goto out;
- }
-
- init_completion(&wait);
lrbp = &hba->lrb[tag];
WARN_ON(lrbp->cmd);
err = ufshcd_compose_dev_cmd(hba, lrbp, cmd_type, tag);
@@ -2988,8 +2942,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
hba->dev_cmd.complete = &wait;
ufshcd_add_query_upiu_trace(hba, UFS_QUERY_SEND, lrbp->ucd_req_ptr);
- /* Make sure descriptors are ready before ringing the doorbell */
- wmb();
ufshcd_send_command(hba, tag);
err = ufshcd_wait_for_dev_cmd(hba, lrbp, timeout);
@@ -3194,7 +3146,7 @@ out_unlock:
*
* Returns 0 for success, non-zero in case of failure
*/
-static int ufshcd_query_attr_retry(struct ufs_hba *hba,
+int ufshcd_query_attr_retry(struct ufs_hba *hba,
enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector,
u32 *attr_val)
{
@@ -3419,9 +3371,11 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
if (is_kmalloc) {
/* Make sure we don't copy more data than available */
- if (param_offset + param_size > buff_len)
- param_size = buff_len - param_offset;
- memcpy(param_read_buf, &desc_buf[param_offset], param_size);
+ if (param_offset >= buff_len)
+ ret = -EINVAL;
+ else
+ memcpy(param_read_buf, &desc_buf[param_offset],
+ min_t(u32, param_size, buff_len - param_offset));
}
out:
if (is_kmalloc)
@@ -3965,6 +3919,35 @@ out:
}
EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
+static inline bool ufshcd_is_saved_err_fatal(struct ufs_hba *hba)
+{
+ lockdep_assert_held(hba->host->host_lock);
+
+ return (hba->saved_uic_err & UFSHCD_UIC_DL_PA_INIT_ERROR) ||
+ (hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK));
+}
+
+static void ufshcd_schedule_eh(struct ufs_hba *hba)
+{
+ bool schedule_eh = false;
+ unsigned long flags;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ /* handle fatal errors only when link is not in error state */
+ if (hba->ufshcd_state != UFSHCD_STATE_ERROR) {
+ if (hba->force_reset || ufshcd_is_link_broken(hba) ||
+ ufshcd_is_saved_err_fatal(hba))
+ hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED_FATAL;
+ else
+ hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED_NON_FATAL;
+ schedule_eh = true;
+ }
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ if (schedule_eh)
+ scsi_schedule_eh(hba->host);
+}
+
/**
* ufshcd_uic_pwr_ctrl - executes UIC commands (which affects the link power
* state) and waits for it to take effect.
@@ -3983,14 +3966,14 @@ EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
*/
static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
{
- struct completion uic_async_done;
+ DECLARE_COMPLETION_ONSTACK(uic_async_done);
unsigned long flags;
+ bool schedule_eh = false;
u8 status;
int ret;
bool reenable_intr = false;
mutex_lock(&hba->uic_cmd_mutex);
- init_completion(&uic_async_done);
ufshcd_add_delay_before_dme_cmd(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
@@ -4055,10 +4038,14 @@ out:
ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
if (ret) {
ufshcd_set_link_broken(hba);
- ufshcd_schedule_eh_work(hba);
+ schedule_eh = true;
}
+
out_unlock:
spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ if (schedule_eh)
+ ufshcd_schedule_eh(hba);
mutex_unlock(&hba->uic_cmd_mutex);
return ret;
@@ -4987,6 +4974,26 @@ static int ufshcd_change_queue_depth(struct scsi_device *sdev, int depth)
return scsi_change_queue_depth(sdev, depth);
}
+static void ufshcd_hpb_destroy(struct ufs_hba *hba, struct scsi_device *sdev)
+{
+ /* skip well-known LU */
+ if ((sdev->lun >= UFS_UPIU_MAX_UNIT_NUM_ID) ||
+ !(hba->dev_info.hpb_enabled) || !ufshpb_is_allowed(hba))
+ return;
+
+ ufshpb_destroy_lu(hba, sdev);
+}
+
+static void ufshcd_hpb_configure(struct ufs_hba *hba, struct scsi_device *sdev)
+{
+ /* skip well-known LU */
+ if ((sdev->lun >= UFS_UPIU_MAX_UNIT_NUM_ID) ||
+ !(hba->dev_info.hpb_enabled) || !ufshpb_is_allowed(hba))
+ return;
+
+ ufshpb_init_hpb_lu(hba, sdev);
+}
+
/**
* ufshcd_slave_configure - adjust SCSI device configurations
* @sdev: pointer to SCSI device
@@ -4996,6 +5003,8 @@ static int ufshcd_slave_configure(struct scsi_device *sdev)
struct ufs_hba *hba = shost_priv(sdev->host);
struct request_queue *q = sdev->request_queue;
+ ufshcd_hpb_configure(hba, sdev);
+
blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1);
if (hba->quirks & UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE)
blk_queue_update_dma_alignment(q, PAGE_SIZE - 1);
@@ -5020,15 +5029,37 @@ static int ufshcd_slave_configure(struct scsi_device *sdev)
static void ufshcd_slave_destroy(struct scsi_device *sdev)
{
struct ufs_hba *hba;
+ unsigned long flags;
hba = shost_priv(sdev->host);
+
+ ufshcd_hpb_destroy(hba, sdev);
+
/* Drop the reference as it won't be needed anymore */
if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) {
- unsigned long flags;
-
spin_lock_irqsave(hba->host->host_lock, flags);
hba->sdev_ufs_device = NULL;
spin_unlock_irqrestore(hba->host->host_lock, flags);
+ } else if (hba->sdev_ufs_device) {
+ struct device *supplier = NULL;
+
+ /* Ensure UFS Device WLUN exists and does not disappear */
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ if (hba->sdev_ufs_device) {
+ supplier = &hba->sdev_ufs_device->sdev_gendev;
+ get_device(supplier);
+ }
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ if (supplier) {
+ /*
+ * If a LUN fails to probe (e.g. absent BOOT WLUN), the
+ * device will not have been registered but can still
+ * have a device link holding a reference to the device.
+ */
+ device_link_remove(&sdev->sdev_gendev, supplier);
+ put_device(supplier);
+ }
}
}
@@ -5124,6 +5155,9 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
/* Flushed in suspend */
schedule_work(&hba->eeh_work);
+
+ if (scsi_status == SAM_STAT_GOOD)
+ ufshpb_rsp_upiu(hba, lrbp);
break;
case UPIU_TRANSACTION_REJECT_UPIU:
/* TODO: handle Reject UPIU Response */
@@ -5232,10 +5266,12 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
/**
* __ufshcd_transfer_req_compl - handle SCSI and query command completion
* @hba: per adapter instance
- * @completed_reqs: requests to complete
+ * @completed_reqs: bitmask that indicates which requests to complete
+ * @retry_requests: whether to ask the SCSI core to retry completed requests
*/
static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
- unsigned long completed_reqs)
+ unsigned long completed_reqs,
+ bool retry_requests)
{
struct ufshcd_lrb *lrbp;
struct scsi_cmnd *cmd;
@@ -5244,8 +5280,6 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
bool update_scaling = false;
for_each_set_bit(index, &completed_reqs, hba->nutrs) {
- if (!test_and_clear_bit(index, &hba->outstanding_reqs))
- continue;
lrbp = &hba->lrb[index];
lrbp->compl_time_stamp = ktime_get();
cmd = lrbp->cmd;
@@ -5253,7 +5287,8 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
ufshcd_update_monitor(hba, lrbp);
ufshcd_add_command_trace(hba, index, UFS_CMD_COMP);
- result = ufshcd_transfer_rsp_status(hba, lrbp);
+ result = retry_requests ? DID_BUS_BUSY << 16 :
+ ufshcd_transfer_rsp_status(hba, lrbp);
scsi_dma_unmap(cmd);
cmd->result = result;
/* Mark completed command as NULL in LRB */
@@ -5277,17 +5312,19 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
}
/**
- * ufshcd_trc_handler - handle transfer requests completion
+ * ufshcd_transfer_req_compl - handle SCSI and query command completion
* @hba: per adapter instance
- * @use_utrlcnr: get completed requests from UTRLCNR
+ * @retry_requests: whether or not to ask to retry requests
*
* Returns
* IRQ_HANDLED - If interrupt is valid
* IRQ_NONE - If invalid interrupt
*/
-static irqreturn_t ufshcd_trc_handler(struct ufs_hba *hba, bool use_utrlcnr)
+static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba,
+ bool retry_requests)
{
- unsigned long completed_reqs = 0;
+ unsigned long completed_reqs, flags;
+ u32 tr_doorbell;
/* Resetting interrupt aggregation counters first and reading the
* DOOR_BELL afterward allows us to handle all the completed requests.
@@ -5300,27 +5337,21 @@ static irqreturn_t ufshcd_trc_handler(struct ufs_hba *hba, bool use_utrlcnr)
!(hba->quirks & UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR))
ufshcd_reset_intr_aggr(hba);
- if (use_utrlcnr) {
- u32 utrlcnr;
-
- utrlcnr = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_LIST_COMPL);
- if (utrlcnr) {
- ufshcd_writel(hba, utrlcnr,
- REG_UTP_TRANSFER_REQ_LIST_COMPL);
- completed_reqs = utrlcnr;
- }
- } else {
- unsigned long flags;
- u32 tr_doorbell;
+ if (ufs_fail_completion())
+ return IRQ_HANDLED;
- spin_lock_irqsave(hba->host->host_lock, flags);
- tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
- completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
- spin_unlock_irqrestore(hba->host->host_lock, flags);
- }
+ spin_lock_irqsave(&hba->outstanding_lock, flags);
+ tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ completed_reqs = ~tr_doorbell & hba->outstanding_reqs;
+ WARN_ONCE(completed_reqs & ~hba->outstanding_reqs,
+ "completed: %#lx; outstanding: %#lx\n", completed_reqs,
+ hba->outstanding_reqs);
+ hba->outstanding_reqs &= ~completed_reqs;
+ spin_unlock_irqrestore(&hba->outstanding_lock, flags);
if (completed_reqs) {
- __ufshcd_transfer_req_compl(hba, completed_reqs);
+ __ufshcd_transfer_req_compl(hba, completed_reqs,
+ retry_requests);
return IRQ_HANDLED;
} else {
return IRQ_NONE;
@@ -5799,7 +5830,13 @@ out:
/* Complete requests that have door-bell cleared */
static void ufshcd_complete_requests(struct ufs_hba *hba)
{
- ufshcd_trc_handler(hba, false);
+ ufshcd_transfer_req_compl(hba, /*retry_requests=*/false);
+ ufshcd_tmc_handler(hba);
+}
+
+static void ufshcd_retry_aborted_requests(struct ufs_hba *hba)
+{
+ ufshcd_transfer_req_compl(hba, /*retry_requests=*/true);
ufshcd_tmc_handler(hba);
}
@@ -5874,27 +5911,6 @@ out:
return err_handling;
}
-/* host lock must be held before calling this func */
-static inline bool ufshcd_is_saved_err_fatal(struct ufs_hba *hba)
-{
- return (hba->saved_uic_err & UFSHCD_UIC_DL_PA_INIT_ERROR) ||
- (hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK));
-}
-
-/* host lock must be held before calling this func */
-static inline void ufshcd_schedule_eh_work(struct ufs_hba *hba)
-{
- /* handle fatal errors only when link is not in error state */
- if (hba->ufshcd_state != UFSHCD_STATE_ERROR) {
- if (hba->force_reset || ufshcd_is_link_broken(hba) ||
- ufshcd_is_saved_err_fatal(hba))
- hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED_FATAL;
- else
- hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED_NON_FATAL;
- queue_work(hba->eh_wq, &hba->eh_work);
- }
-}
-
static void ufshcd_clk_scaling_allow(struct ufs_hba *hba, bool allow)
{
down_write(&hba->clk_scaling_lock);
@@ -6028,11 +6044,11 @@ static bool ufshcd_is_pwr_mode_restore_needed(struct ufs_hba *hba)
/**
* ufshcd_err_handler - handle UFS errors that require s/w attention
- * @work: pointer to work structure
+ * @host: SCSI host pointer
*/
-static void ufshcd_err_handler(struct work_struct *work)
+static void ufshcd_err_handler(struct Scsi_Host *host)
{
- struct ufs_hba *hba;
+ struct ufs_hba *hba = shost_priv(host);
unsigned long flags;
bool err_xfer = false;
bool err_tm = false;
@@ -6040,10 +6056,9 @@ static void ufshcd_err_handler(struct work_struct *work)
int tag;
bool needs_reset = false, needs_restore = false;
- hba = container_of(work, struct ufs_hba, eh_work);
-
down(&hba->host_sem);
spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->host->host_eh_scheduled = 0;
if (ufshcd_err_handling_should_stop(hba)) {
if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
@@ -6141,8 +6156,7 @@ static void ufshcd_err_handler(struct work_struct *work)
}
lock_skip_pending_xfer_clear:
- /* Complete the requests that are cleared by s/w */
- ufshcd_complete_requests(hba);
+ ufshcd_retry_aborted_requests(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
hba->silence_err_logs = false;
@@ -6357,7 +6371,6 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
"host_regs: ");
ufshcd_print_pwr_info(hba);
}
- ufshcd_schedule_eh_work(hba);
retval |= IRQ_HANDLED;
}
/*
@@ -6369,6 +6382,10 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
hba->errors = 0;
hba->uic_error = 0;
spin_unlock(hba->host->host_lock);
+
+ if (queue_eh_work)
+ ufshcd_schedule_eh(hba);
+
return retval;
}
@@ -6440,7 +6457,7 @@ static irqreturn_t ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
retval |= ufshcd_tmc_handler(hba);
if (intr_status & UTP_TRANSFER_REQ_COMPL)
- retval |= ufshcd_trc_handler(hba, ufshcd_has_utrlcnr(hba));
+ retval |= ufshcd_transfer_req_compl(hba, /*retry_requests=*/false);
return retval;
}
@@ -6548,9 +6565,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
/* send command to the controller */
__set_bit(task_tag, &hba->outstanding_tasks);
- /* Make sure descriptors are ready before ringing the task doorbell */
- wmb();
-
ufshcd_writel(hba, 1 << task_tag, REG_UTP_TASK_REQ_DOOR_BELL);
/* Make sure that doorbell is committed immediately */
wmb();
@@ -6663,11 +6677,11 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
enum query_opcode desc_op)
{
struct request_queue *q = hba->cmd_queue;
+ DECLARE_COMPLETION_ONSTACK(wait);
struct request *req;
struct ufshcd_lrb *lrbp;
int err = 0;
int tag;
- struct completion wait;
u8 upiu_flags;
down_read(&hba->clk_scaling_lock);
@@ -6678,14 +6692,13 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
goto out_unlock;
}
tag = req->tag;
- WARN_ON_ONCE(!ufshcd_valid_tag(hba, tag));
+ WARN_ONCE(tag < 0, "Invalid tag %d\n", tag);
if (unlikely(test_bit(tag, &hba->outstanding_reqs))) {
err = -EBUSY;
goto out;
}
- init_completion(&wait);
lrbp = &hba->lrb[tag];
WARN_ON(lrbp->cmd);
lrbp->cmd = NULL;
@@ -6723,8 +6736,6 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
hba->dev_cmd.complete = &wait;
ufshcd_add_query_upiu_trace(hba, UFS_QUERY_SEND, lrbp->ucd_req_ptr);
- /* Make sure descriptors are ready before ringing the doorbell */
- wmb();
ufshcd_send_command(hba, tag);
/*
@@ -6865,7 +6876,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
err = ufshcd_clear_cmd(hba, pos);
if (err)
break;
- __ufshcd_transfer_req_compl(hba, pos);
+ __ufshcd_transfer_req_compl(hba, pos, /*retry_requests=*/true);
}
}
@@ -6981,33 +6992,24 @@ out:
*/
static int ufshcd_abort(struct scsi_cmnd *cmd)
{
- struct Scsi_Host *host;
- struct ufs_hba *hba;
+ struct Scsi_Host *host = cmd->device->host;
+ struct ufs_hba *hba = shost_priv(host);
+ int tag = scsi_cmd_to_rq(cmd)->tag;
+ struct ufshcd_lrb *lrbp = &hba->lrb[tag];
unsigned long flags;
- unsigned int tag;
- int err = 0;
- struct ufshcd_lrb *lrbp;
+ int err = FAILED;
u32 reg;
- host = cmd->device->host;
- hba = shost_priv(host);
- tag = cmd->request->tag;
- lrbp = &hba->lrb[tag];
- if (!ufshcd_valid_tag(hba, tag)) {
- dev_err(hba->dev,
- "%s: invalid command tag %d: cmd=0x%p, cmd->request=0x%p",
- __func__, tag, cmd, cmd->request);
- BUG();
- }
+ WARN_ONCE(tag < 0, "Invalid tag %d\n", tag);
ufshcd_hold(hba, false);
reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
- /* If command is already aborted/completed, return SUCCESS */
+ /* If command is already aborted/completed, return FAILED. */
if (!(test_bit(tag, &hba->outstanding_reqs))) {
dev_err(hba->dev,
"%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n",
__func__, tag, hba->outstanding_reqs, reg);
- goto out;
+ goto release;
}
/* Print Transfer Request of aborted task */
@@ -7036,7 +7038,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
dev_err(hba->dev,
"%s: cmd was completed, but without a notifying intr, tag = %d",
__func__, tag);
- goto cleanup;
+ __ufshcd_transfer_req_compl(hba, 1UL << tag, /*retry_requests=*/false);
+ goto release;
}
/*
@@ -7045,40 +7048,39 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
* will be to send LU reset which, again, is a spec violation.
* To avoid these unnecessary/illegal steps, first we clean up
* the lrb taken by this cmd and re-set it in outstanding_reqs,
- * then queue the eh_work and bail.
+ * then queue the error handler and bail.
*/
if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) {
ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, lrbp->lun);
- __ufshcd_transfer_req_compl(hba, (1UL << tag));
- set_bit(tag, &hba->outstanding_reqs);
+
spin_lock_irqsave(host->host_lock, flags);
hba->force_reset = true;
- ufshcd_schedule_eh_work(hba);
spin_unlock_irqrestore(host->host_lock, flags);
- goto out;
+
+ ufshcd_schedule_eh(hba);
+
+ goto release;
}
/* Skip task abort in case previous aborts failed and report failure */
- if (lrbp->req_abort_skip)
- err = -EIO;
- else
- err = ufshcd_try_to_abort_task(hba, tag);
+ if (lrbp->req_abort_skip) {
+ dev_err(hba->dev, "%s: skipping abort\n", __func__);
+ ufshcd_set_req_abort_skip(hba, hba->outstanding_reqs);
+ goto release;
+ }
- if (!err) {
-cleanup:
- __ufshcd_transfer_req_compl(hba, (1UL << tag));
-out:
- err = SUCCESS;
- } else {
+ err = ufshcd_try_to_abort_task(hba, tag);
+ if (err) {
dev_err(hba->dev, "%s: failed with err %d\n", __func__, err);
ufshcd_set_req_abort_skip(hba, hba->outstanding_reqs);
err = FAILED;
+ goto release;
}
- /*
- * This ufshcd_release() corresponds to the original scsi cmd that got
- * aborted here (as we won't get any IRQ for it).
- */
+ err = SUCCESS;
+
+release:
+ /* Matches the ufshcd_hold() call at the start of this function. */
ufshcd_release(hba);
return err;
}
@@ -7101,9 +7103,10 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
* Stop the host controller and complete the requests
* cleared by h/w
*/
+ ufshpb_reset_host(hba);
ufshcd_hba_stop(hba);
hba->silence_err_logs = true;
- ufshcd_complete_requests(hba);
+ ufshcd_retry_aborted_requests(hba);
hba->silence_err_logs = false;
/* scale up clocks to max frequency before full reinitialization */
@@ -7188,11 +7191,10 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd)
spin_lock_irqsave(hba->host->host_lock, flags);
hba->force_reset = true;
- ufshcd_schedule_eh_work(hba);
dev_err(hba->dev, "%s: reset in progress - 1\n", __func__);
spin_unlock_irqrestore(hba->host->host_lock, flags);
- flush_work(&hba->eh_work);
+ ufshcd_err_handler(hba->host);
spin_lock_irqsave(hba->host->host_lock, flags);
if (hba->ufshcd_state == UFSHCD_STATE_ERROR)
@@ -7499,6 +7501,7 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
{
int err;
u8 model_index;
+ u8 b_ufs_feature_sup;
u8 *desc_buf;
struct ufs_dev_info *dev_info = &hba->dev_info;
@@ -7526,9 +7529,26 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
/* getting Specification Version in big endian format */
dev_info->wspecversion = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 |
desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1];
+ b_ufs_feature_sup = desc_buf[DEVICE_DESC_PARAM_UFS_FEAT];
model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
+ if (dev_info->wspecversion >= UFS_DEV_HPB_SUPPORT_VERSION &&
+ (b_ufs_feature_sup & UFS_DEV_HPB_SUPPORT)) {
+ bool hpb_en = false;
+
+ ufshpb_get_dev_info(hba, desc_buf);
+
+ if (!ufshpb_is_legacy(hba))
+ err = ufshcd_query_flag_retry(hba,
+ UPIU_QUERY_OPCODE_READ_FLAG,
+ QUERY_FLAG_IDN_HPB_EN, 0,
+ &hpb_en);
+
+ if (ufshpb_is_legacy(hba) || (!err && hpb_en))
+ dev_info->hpb_enabled = true;
+ }
+
err = ufshcd_read_string_desc(hba, model_index,
&dev_info->model, SD_ASCII_STD);
if (err < 0) {
@@ -7760,6 +7780,10 @@ static int ufshcd_device_geo_params_init(struct ufs_hba *hba)
else if (desc_buf[GEOMETRY_DESC_PARAM_MAX_NUM_LUN] == 0)
hba->dev_info.max_lu_supported = 8;
+ if (hba->desc_size[QUERY_DESC_IDN_GEOMETRY] >=
+ GEOMETRY_DESC_PARAM_HPB_MAX_ACTIVE_REGS)
+ ufshpb_get_geo_info(hba, desc_buf);
+
out:
kfree(desc_buf);
return err;
@@ -7902,6 +7926,7 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
}
ufs_bsg_probe(hba);
+ ufshpb_init(hba);
scsi_scan_host(hba->host);
pm_runtime_put_sync(hba->dev);
@@ -7909,8 +7934,61 @@ out:
return ret;
}
+static void ufshcd_request_sense_done(struct request *rq, blk_status_t error)
+{
+ if (error != BLK_STS_OK)
+ pr_err("%s: REQUEST SENSE failed (%d)\n", __func__, error);
+ kfree(rq->end_io_data);
+ blk_put_request(rq);
+}
+
static int
-ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp);
+ufshcd_request_sense_async(struct ufs_hba *hba, struct scsi_device *sdev)
+{
+ /*
+ * Some UFS devices clear unit attention condition only if the sense
+ * size used (UFS_SENSE_SIZE in this case) is non-zero.
+ */
+ static const u8 cmd[6] = {REQUEST_SENSE, 0, 0, 0, UFS_SENSE_SIZE, 0};
+ struct scsi_request *rq;
+ struct request *req;
+ char *buffer;
+ int ret;
+
+ buffer = kzalloc(UFS_SENSE_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ req = blk_get_request(sdev->request_queue, REQ_OP_DRV_IN,
+ /*flags=*/BLK_MQ_REQ_PM);
+ if (IS_ERR(req)) {
+ ret = PTR_ERR(req);
+ goto out_free;
+ }
+
+ ret = blk_rq_map_kern(sdev->request_queue, req,
+ buffer, UFS_SENSE_SIZE, GFP_NOIO);
+ if (ret)
+ goto out_put;
+
+ rq = scsi_req(req);
+ rq->cmd_len = ARRAY_SIZE(cmd);
+ memcpy(rq->cmd, cmd, rq->cmd_len);
+ rq->retries = 3;
+ req->timeout = 1 * HZ;
+ req->rq_flags |= RQF_PM | RQF_QUIET;
+ req->end_io_data = buffer;
+
+ blk_execute_rq_nowait(/*bd_disk=*/NULL, req, /*at_head=*/true,
+ ufshcd_request_sense_done);
+ return 0;
+
+out_put:
+ blk_put_request(req);
+out_free:
+ kfree(buffer);
+ return ret;
+}
static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun)
{
@@ -7938,7 +8016,7 @@ static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun)
if (ret)
goto out_err;
- ret = ufshcd_send_request_sense(hba, sdp);
+ ret = ufshcd_request_sense_async(hba, sdp);
scsi_device_put(sdp);
out_err:
if (ret)
@@ -7967,13 +8045,13 @@ out:
}
/**
- * ufshcd_probe_hba - probe hba to detect device and initialize
+ * ufshcd_probe_hba - probe hba to detect device and initialize it
* @hba: per-adapter instance
- * @async: asynchronous execution or not
+ * @init_dev_params: whether or not to call ufshcd_device_params_init().
*
* Execute link-startup and verify device initialization
*/
-static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
+static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
{
int ret;
unsigned long flags;
@@ -8005,7 +8083,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
* Initialize UFS device parameters used by driver, these
* parameters are associated with UFS descriptors.
*/
- if (async) {
+ if (init_dev_params) {
ret = ufshcd_device_params_init(hba);
if (ret)
goto out;
@@ -8050,6 +8128,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
/* Enable Auto-Hibernate if configured */
ufshcd_auto_hibern8_enable(hba);
+ ufshpb_reset(hba);
out:
spin_lock_irqsave(hba->host->host_lock, flags);
if (ret)
@@ -8097,6 +8176,10 @@ out:
static const struct attribute_group *ufshcd_driver_groups[] = {
&ufs_sysfs_unit_descriptor_group,
&ufs_sysfs_lun_attributes_group,
+#ifdef CONFIG_SCSI_UFS_HPB
+ &ufs_sysfs_hpb_stat_group,
+ &ufs_sysfs_hpb_param_group,
+#endif
NULL,
};
@@ -8521,8 +8604,6 @@ static void ufshcd_hba_exit(struct ufs_hba *hba)
if (hba->is_powered) {
ufshcd_exit_clk_scaling(hba);
ufshcd_exit_clk_gating(hba);
- if (hba->eh_wq)
- destroy_workqueue(hba->eh_wq);
ufs_debugfs_hba_exit(hba);
ufshcd_variant_hba_exit(hba);
ufshcd_setup_vreg(hba, false);
@@ -8533,35 +8614,6 @@ static void ufshcd_hba_exit(struct ufs_hba *hba)
}
}
-static int
-ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp)
-{
- unsigned char cmd[6] = {REQUEST_SENSE,
- 0,
- 0,
- 0,
- UFS_SENSE_SIZE,
- 0};
- char *buffer;
- int ret;
-
- buffer = kzalloc(UFS_SENSE_SIZE, GFP_KERNEL);
- if (!buffer) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = scsi_execute(sdp, cmd, DMA_FROM_DEVICE, buffer,
- UFS_SENSE_SIZE, NULL, NULL,
- msecs_to_jiffies(1000), 3, 0, RQF_PM, NULL);
- if (ret)
- pr_err("%s: failed with err %d\n", __func__, ret);
-
- kfree(buffer);
-out:
- return ret;
-}
-
/**
* ufshcd_set_dev_pwr_mode - sends START STOP UNIT command to set device
* power mode
@@ -8739,6 +8791,7 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
usleep_range(5000, 5100);
}
+#ifdef CONFIG_PM
static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)
{
int ret = 0;
@@ -8766,6 +8819,7 @@ vcc_disable:
out:
return ret;
}
+#endif /* CONFIG_PM */
static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba)
{
@@ -8798,6 +8852,8 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
req_link_state = UIC_LINK_OFF_STATE;
}
+ ufshpb_suspend(hba);
+
/*
* If we can't transition into any of the low power modes
* just gate the clocks.
@@ -8921,6 +8977,7 @@ out:
ufshcd_update_evt_hist(hba, UFS_EVT_WL_SUSP_ERR, (u32)ret);
hba->clk_gating.is_suspended = false;
ufshcd_release(hba);
+ ufshpb_resume(hba);
}
hba->pm_op_in_progress = false;
return ret;
@@ -8999,6 +9056,8 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
/* Enable Auto-Hibernate if configured */
ufshcd_auto_hibern8_enable(hba);
+
+ ufshpb_resume(hba);
goto out;
set_old_link_state:
@@ -9168,6 +9227,7 @@ static int ufshcd_suspend(struct ufs_hba *hba)
return ret;
}
+#ifdef CONFIG_PM
/**
* ufshcd_resume - helper function for resume operations
* @hba: per adapter instance
@@ -9205,17 +9265,21 @@ out:
ufshcd_update_evt_hist(hba, UFS_EVT_RESUME_ERR, (u32)ret);
return ret;
}
+#endif /* CONFIG_PM */
+#ifdef CONFIG_PM_SLEEP
/**
- * ufshcd_system_suspend - system suspend routine
- * @hba: per adapter instance
+ * ufshcd_system_suspend - system suspend callback
+ * @dev: Device associated with the UFS controller.
*
- * Check the description of ufshcd_suspend() function for more details.
+ * Executed before putting the system into a sleep state in which the contents
+ * of main memory are preserved.
*
* Returns 0 for success and non-zero for failure
*/
-int ufshcd_system_suspend(struct ufs_hba *hba)
+int ufshcd_system_suspend(struct device *dev)
{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
int ret = 0;
ktime_t start = ktime_get();
@@ -9232,16 +9296,19 @@ out:
EXPORT_SYMBOL(ufshcd_system_suspend);
/**
- * ufshcd_system_resume - system resume routine
- * @hba: per adapter instance
+ * ufshcd_system_resume - system resume callback
+ * @dev: Device associated with the UFS controller.
+ *
+ * Executed after waking the system up from a sleep state in which the contents
+ * of main memory were preserved.
*
* Returns 0 for success and non-zero for failure
*/
-
-int ufshcd_system_resume(struct ufs_hba *hba)
+int ufshcd_system_resume(struct device *dev)
{
- int ret = 0;
+ struct ufs_hba *hba = dev_get_drvdata(dev);
ktime_t start = ktime_get();
+ int ret = 0;
if (pm_runtime_suspended(hba->dev))
goto out;
@@ -9256,17 +9323,20 @@ out:
return ret;
}
EXPORT_SYMBOL(ufshcd_system_resume);
+#endif /* CONFIG_PM_SLEEP */
+#ifdef CONFIG_PM
/**
- * ufshcd_runtime_suspend - runtime suspend routine
- * @hba: per adapter instance
+ * ufshcd_runtime_suspend - runtime suspend callback
+ * @dev: Device associated with the UFS controller.
*
* Check the description of ufshcd_suspend() function for more details.
*
* Returns 0 for success and non-zero for failure
*/
-int ufshcd_runtime_suspend(struct ufs_hba *hba)
+int ufshcd_runtime_suspend(struct device *dev)
{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
int ret;
ktime_t start = ktime_get();
@@ -9281,7 +9351,7 @@ EXPORT_SYMBOL(ufshcd_runtime_suspend);
/**
* ufshcd_runtime_resume - runtime resume routine
- * @hba: per adapter instance
+ * @dev: Device associated with the UFS controller.
*
* This function basically brings controller
* to active state. Following operations are done in this function:
@@ -9289,8 +9359,9 @@ EXPORT_SYMBOL(ufshcd_runtime_suspend);
* 1. Turn on all the controller related clocks
* 2. Turn ON VCC rail
*/
-int ufshcd_runtime_resume(struct ufs_hba *hba)
+int ufshcd_runtime_resume(struct device *dev)
{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
int ret;
ktime_t start = ktime_get();
@@ -9302,12 +9373,7 @@ int ufshcd_runtime_resume(struct ufs_hba *hba)
return ret;
}
EXPORT_SYMBOL(ufshcd_runtime_resume);
-
-int ufshcd_runtime_idle(struct ufs_hba *hba)
-{
- return 0;
-}
-EXPORT_SYMBOL(ufshcd_runtime_idle);
+#endif /* CONFIG_PM */
/**
* ufshcd_shutdown - shutdown routine
@@ -9343,6 +9409,7 @@ void ufshcd_remove(struct ufs_hba *hba)
if (hba->sdev_ufs_device)
ufshcd_rpm_get_sync(hba);
ufs_bsg_remove(hba);
+ ufshpb_remove(hba);
ufs_sysfs_remove_nodes(hba->dev);
blk_cleanup_queue(hba->tmf_queue);
blk_mq_free_tag_set(&hba->tmf_tag_set);
@@ -9381,6 +9448,10 @@ static int ufshcd_set_dma_mask(struct ufs_hba *hba)
return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32));
}
+static struct scsi_transport_template ufshcd_transport_template = {
+ .eh_strategy_handler = ufshcd_err_handler,
+};
+
/**
* ufshcd_alloc_host - allocate Host Bus Adapter (HBA)
* @dev: pointer to device handle
@@ -9407,13 +9478,15 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle)
err = -ENOMEM;
goto out_error;
}
+ host->transportt = &ufshcd_transport_template;
hba = shost_priv(host);
hba->host = host;
hba->dev = dev;
- *hba_handle = hba;
hba->dev_ref_clk_freq = REF_CLK_FREQ_INVAL;
-
INIT_LIST_HEAD(&hba->clk_list_head);
+ spin_lock_init(&hba->outstanding_lock);
+
+ *hba_handle = hba;
out_error:
return err;
@@ -9444,7 +9517,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
int err;
struct Scsi_Host *host = hba->host;
struct device *dev = hba->dev;
- char eh_wq_name[sizeof("ufs_eh_wq_00")];
if (!mmio_base) {
dev_err(hba->dev,
@@ -9498,17 +9570,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
hba->max_pwr_info.is_valid = false;
- /* Initialize work queues */
- snprintf(eh_wq_name, sizeof(eh_wq_name), "ufs_eh_wq_%d",
- hba->host->host_no);
- hba->eh_wq = create_singlethread_workqueue(eh_wq_name);
- if (!hba->eh_wq) {
- dev_err(hba->dev, "%s: failed to create eh workqueue\n",
- __func__);
- err = -ENOMEM;
- goto out_disable;
- }
- INIT_WORK(&hba->eh_work, ufshcd_err_handler);
INIT_WORK(&hba->eeh_work, ufshcd_exception_event_handler);
sema_init(&hba->host_sem, 1);
@@ -9627,6 +9688,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
async_schedule(ufshcd_async_scan, hba);
ufs_sysfs_add_nodes(hba->dev);
+ device_enable_async_suspend(dev);
return 0;
free_tmf_queue:
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 194755c9ddfe..52ea6f350b18 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -476,6 +476,27 @@ struct ufs_stats {
struct ufs_event_hist event[UFS_EVT_CNT];
};
+/**
+ * enum ufshcd_state - UFS host controller state
+ * @UFSHCD_STATE_RESET: Link is not operational. Postpone SCSI command
+ * processing.
+ * @UFSHCD_STATE_OPERATIONAL: The host controller is operational and can process
+ * SCSI commands.
+ * @UFSHCD_STATE_EH_SCHEDULED_NON_FATAL: The error handler has been scheduled.
+ * SCSI commands may be submitted to the controller.
+ * @UFSHCD_STATE_EH_SCHEDULED_FATAL: The error handler has been scheduled. Fail
+ * newly submitted SCSI commands with error code DID_BAD_TARGET.
+ * @UFSHCD_STATE_ERROR: An unrecoverable error occurred, e.g. link recovery
+ * failed. Fail all SCSI commands with error code DID_ERROR.
+ */
+enum ufshcd_state {
+ UFSHCD_STATE_RESET,
+ UFSHCD_STATE_OPERATIONAL,
+ UFSHCD_STATE_EH_SCHEDULED_NON_FATAL,
+ UFSHCD_STATE_EH_SCHEDULED_FATAL,
+ UFSHCD_STATE_ERROR,
+};
+
enum ufshcd_quirks {
/* Interrupt aggregation support is broken */
UFSHCD_QUIRK_BROKEN_INTR_AGGR = 1 << 0,
@@ -641,6 +662,31 @@ struct ufs_hba_variant_params {
u32 wb_flush_threshold;
};
+#ifdef CONFIG_SCSI_UFS_HPB
+/**
+ * struct ufshpb_dev_info - UFSHPB device related info
+ * @num_lu: the number of user logical unit to check whether all lu finished
+ * initialization
+ * @rgn_size: device reported HPB region size
+ * @srgn_size: device reported HPB sub-region size
+ * @slave_conf_cnt: counter to check all lu finished initialization
+ * @hpb_disabled: flag to check if HPB is disabled
+ * @max_hpb_single_cmd: device reported bMAX_DATA_SIZE_FOR_SINGLE_CMD value
+ * @is_legacy: flag to check HPB 1.0
+ * @control_mode: either host or device
+ */
+struct ufshpb_dev_info {
+ int num_lu;
+ int rgn_size;
+ int srgn_size;
+ atomic_t slave_conf_cnt;
+ bool hpb_disabled;
+ u8 max_hpb_single_cmd;
+ bool is_legacy;
+ u8 control_mode;
+};
+#endif
+
struct ufs_hba_monitor {
unsigned long chunk_size;
@@ -674,6 +720,7 @@ struct ufs_hba_monitor {
* @lrb: local reference block
* @cmd_queue: Used to allocate command tags from hba->host->tag_set.
* @outstanding_tasks: Bits representing outstanding task requests
+ * @outstanding_lock: Protects @outstanding_reqs.
* @outstanding_reqs: Bits representing outstanding transfer requests
* @capabilities: UFS Controller Capabilities
* @nutrs: Transfer Request Queue depth supported by controller
@@ -683,19 +730,17 @@ struct ufs_hba_monitor {
* @priv: pointer to variant specific private data
* @irq: Irq number of the controller
* @active_uic_cmd: handle of active UIC command
- * @uic_cmd_mutex: mutex for uic command
+ * @uic_cmd_mutex: mutex for UIC command
* @tmf_tag_set: TMF tag set.
* @tmf_queue: Used to allocate TMF tags.
* @pwr_done: completion for power mode change
- * @ufshcd_state: UFSHCD states
+ * @ufshcd_state: UFSHCD state
* @eh_flags: Error handling flags
* @intr_mask: Interrupt Mask Bits
* @ee_ctrl_mask: Exception event control mask
* @is_powered: flag to check if HBA is powered
* @shutting_down: flag to check if shutdown has been invoked
* @host_sem: semaphore used to serialize concurrent contexts
- * @eh_wq: Workqueue that eh_work works on
- * @eh_work: Worker to handle UFS errors that require s/w attention
* @eeh_work: Worker to handle exception events
* @errors: HBA errors
* @uic_error: UFS interconnect layer error status
@@ -760,6 +805,7 @@ struct ufs_hba {
struct ufshcd_lrb *lrb;
unsigned long outstanding_tasks;
+ spinlock_t outstanding_lock;
unsigned long outstanding_reqs;
u32 capabilities;
@@ -785,7 +831,7 @@ struct ufs_hba {
struct mutex uic_cmd_mutex;
struct completion *uic_async_done;
- u32 ufshcd_state;
+ enum ufshcd_state ufshcd_state;
u32 eh_flags;
u32 intr_mask;
u16 ee_ctrl_mask; /* Exception event mask */
@@ -797,8 +843,6 @@ struct ufs_hba {
struct semaphore host_sem;
/* Work Queues */
- struct workqueue_struct *eh_wq;
- struct work_struct eh_work;
struct work_struct eeh_work;
/* HBA Errors */
@@ -851,6 +895,10 @@ struct ufs_hba {
struct request_queue *bsg_queue;
struct delayed_work rpm_dev_flush_recheck_work;
+#ifdef CONFIG_SCSI_UFS_HPB
+ struct ufshpb_dev_info ufshpb_dev;
+#endif
+
struct ufs_hba_monitor monitor;
#ifdef CONFIG_SCSI_UFS_CRYPTO
@@ -893,16 +941,8 @@ static inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba)
static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba)
{
-/* DWC UFS Core has the Interrupt aggregation feature but is not detectable*/
-#ifndef CONFIG_SCSI_UFS_DWC
- if ((hba->caps & UFSHCD_CAP_INTR_AGGR) &&
- !(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR))
- return true;
- else
- return false;
-#else
-return true;
-#endif
+ return (hba->caps & UFSHCD_CAP_INTR_AGGR) &&
+ !(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR);
}
static inline bool ufshcd_can_aggressive_pc(struct ufs_hba *hba)
@@ -1009,11 +1049,14 @@ static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
return 0;
}
-extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
-extern int ufshcd_runtime_resume(struct ufs_hba *hba);
-extern int ufshcd_runtime_idle(struct ufs_hba *hba);
-extern int ufshcd_system_suspend(struct ufs_hba *hba);
-extern int ufshcd_system_resume(struct ufs_hba *hba);
+#ifdef CONFIG_PM
+extern int ufshcd_runtime_suspend(struct device *dev);
+extern int ufshcd_runtime_resume(struct device *dev);
+#endif
+#ifdef CONFIG_PM_SLEEP
+extern int ufshcd_system_suspend(struct device *dev);
+extern int ufshcd_system_resume(struct device *dev);
+#endif
extern int ufshcd_shutdown(struct ufs_hba *hba);
extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba,
int agreed_gear,
@@ -1096,6 +1139,9 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
u8 param_offset,
u8 *param_read_buf,
u8 param_size);
+int ufshcd_query_attr_retry(struct ufs_hba *hba, enum query_opcode opcode,
+ enum attr_idn idn, u8 index, u8 selector,
+ u32 *attr_val);
int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
@@ -1160,11 +1206,6 @@ static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba)
return ufshcd_readl(hba, REG_UFS_VERSION);
}
-static inline bool ufshcd_has_utrlcnr(struct ufs_hba *hba)
-{
- return (hba->ufs_version >= ufshci_version(3, 0));
-}
-
static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba,
bool up, enum ufs_notify_change_status status)
{
@@ -1226,18 +1267,6 @@ static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
return -ENOTSUPP;
}
-static inline void ufshcd_vops_setup_xfer_req(struct ufs_hba *hba, int tag,
- bool is_scsi_cmd)
-{
- if (hba->vops && hba->vops->setup_xfer_req) {
- unsigned long flags;
-
- spin_lock_irqsave(hba->host->host_lock, flags);
- hba->vops->setup_xfer_req(hba, tag, is_scsi_cmd);
- spin_unlock_irqrestore(hba->host->host_lock, flags);
- }
-}
-
static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba,
int tag, u8 tm_function)
{
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 5affb1fce5ad..de95be5d11d4 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -39,7 +39,6 @@ enum {
REG_UTP_TRANSFER_REQ_DOOR_BELL = 0x58,
REG_UTP_TRANSFER_REQ_LIST_CLEAR = 0x5C,
REG_UTP_TRANSFER_REQ_LIST_RUN_STOP = 0x60,
- REG_UTP_TRANSFER_REQ_LIST_COMPL = 0x64,
REG_UTP_TASK_REQ_LIST_BASE_L = 0x70,
REG_UTP_TASK_REQ_LIST_BASE_H = 0x74,
REG_UTP_TASK_REQ_DOOR_BELL = 0x78,
diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c
new file mode 100644
index 000000000000..02fb51ae8b25
--- /dev/null
+++ b/drivers/scsi/ufs/ufshpb.c
@@ -0,0 +1,2933 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Universal Flash Storage Host Performance Booster
+ *
+ * Copyright (C) 2017-2021 Samsung Electronics Co., Ltd.
+ *
+ * Authors:
+ * Yongmyung Lee <ymhungry.lee@samsung.com>
+ * Jinyoung Choi <j-young.choi@samsung.com>
+ */
+
+#include <asm/unaligned.h>
+#include <linux/async.h>
+
+#include "ufshcd.h"
+#include "ufshpb.h"
+#include "../sd.h"
+
+#define ACTIVATION_THRESHOLD 8 /* 8 IOs */
+#define READ_TO_MS 1000
+#define READ_TO_EXPIRIES 100
+#define POLLING_INTERVAL_MS 200
+#define THROTTLE_MAP_REQ_DEFAULT 1
+
+/* memory management */
+static struct kmem_cache *ufshpb_mctx_cache;
+static mempool_t *ufshpb_mctx_pool;
+static mempool_t *ufshpb_page_pool;
+/* A cache size of 2MB can cache ppn in the 1GB range. */
+static unsigned int ufshpb_host_map_kbytes = 2048;
+static int tot_active_srgn_pages;
+
+static struct workqueue_struct *ufshpb_wq;
+
+static void ufshpb_update_active_info(struct ufshpb_lu *hpb, int rgn_idx,
+ int srgn_idx);
+
+bool ufshpb_is_allowed(struct ufs_hba *hba)
+{
+ return !(hba->ufshpb_dev.hpb_disabled);
+}
+
+/* HPB version 1.0 is called as legacy version. */
+bool ufshpb_is_legacy(struct ufs_hba *hba)
+{
+ return hba->ufshpb_dev.is_legacy;
+}
+
+static struct ufshpb_lu *ufshpb_get_hpb_data(struct scsi_device *sdev)
+{
+ return sdev->hostdata;
+}
+
+static int ufshpb_get_state(struct ufshpb_lu *hpb)
+{
+ return atomic_read(&hpb->hpb_state);
+}
+
+static void ufshpb_set_state(struct ufshpb_lu *hpb, int state)
+{
+ atomic_set(&hpb->hpb_state, state);
+}
+
+static int ufshpb_is_valid_srgn(struct ufshpb_region *rgn,
+ struct ufshpb_subregion *srgn)
+{
+ return rgn->rgn_state != HPB_RGN_INACTIVE &&
+ srgn->srgn_state == HPB_SRGN_VALID;
+}
+
+static bool ufshpb_is_read_cmd(struct scsi_cmnd *cmd)
+{
+ return req_op(scsi_cmd_to_rq(cmd)) == REQ_OP_READ;
+}
+
+static bool ufshpb_is_write_or_discard(struct scsi_cmnd *cmd)
+{
+ return op_is_write(req_op(scsi_cmd_to_rq(cmd))) ||
+ op_is_discard(req_op(scsi_cmd_to_rq(cmd)));
+}
+
+static bool ufshpb_is_supported_chunk(struct ufshpb_lu *hpb, int transfer_len)
+{
+ return transfer_len <= hpb->pre_req_max_tr_len;
+}
+
+/*
+ * In this driver, WRITE_BUFFER CMD support 36KB (len=9) ~ 1MB (len=256) as
+ * default. It is possible to change range of transfer_len through sysfs.
+ */
+static inline bool ufshpb_is_required_wb(struct ufshpb_lu *hpb, int len)
+{
+ return len > hpb->pre_req_min_tr_len &&
+ len <= hpb->pre_req_max_tr_len;
+}
+
+static bool ufshpb_is_general_lun(int lun)
+{
+ return lun < UFS_UPIU_MAX_UNIT_NUM_ID;
+}
+
+static bool ufshpb_is_pinned_region(struct ufshpb_lu *hpb, int rgn_idx)
+{
+ if (hpb->lu_pinned_end != PINNED_NOT_SET &&
+ rgn_idx >= hpb->lu_pinned_start &&
+ rgn_idx <= hpb->lu_pinned_end)
+ return true;
+
+ return false;
+}
+
+static void ufshpb_kick_map_work(struct ufshpb_lu *hpb)
+{
+ bool ret = false;
+ unsigned long flags;
+
+ if (ufshpb_get_state(hpb) != HPB_PRESENT)
+ return;
+
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ if (!list_empty(&hpb->lh_inact_rgn) || !list_empty(&hpb->lh_act_srgn))
+ ret = true;
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+
+ if (ret)
+ queue_work(ufshpb_wq, &hpb->map_work);
+}
+
+static bool ufshpb_is_hpb_rsp_valid(struct ufs_hba *hba,
+ struct ufshcd_lrb *lrbp,
+ struct utp_hpb_rsp *rsp_field)
+{
+ /* Check HPB_UPDATE_ALERT */
+ if (!(lrbp->ucd_rsp_ptr->header.dword_2 &
+ UPIU_HEADER_DWORD(0, 2, 0, 0)))
+ return false;
+
+ if (be16_to_cpu(rsp_field->sense_data_len) != DEV_SENSE_SEG_LEN ||
+ rsp_field->desc_type != DEV_DES_TYPE ||
+ rsp_field->additional_len != DEV_ADDITIONAL_LEN ||
+ rsp_field->active_rgn_cnt > MAX_ACTIVE_NUM ||
+ rsp_field->inactive_rgn_cnt > MAX_INACTIVE_NUM ||
+ rsp_field->hpb_op == HPB_RSP_NONE ||
+ (rsp_field->hpb_op == HPB_RSP_REQ_REGION_UPDATE &&
+ !rsp_field->active_rgn_cnt && !rsp_field->inactive_rgn_cnt))
+ return false;
+
+ if (!ufshpb_is_general_lun(rsp_field->lun)) {
+ dev_warn(hba->dev, "ufshpb: lun(%d) not supported\n",
+ lrbp->lun);
+ return false;
+ }
+
+ return true;
+}
+
+static void ufshpb_iterate_rgn(struct ufshpb_lu *hpb, int rgn_idx, int srgn_idx,
+ int srgn_offset, int cnt, bool set_dirty)
+{
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn, *prev_srgn = NULL;
+ int set_bit_len;
+ int bitmap_len;
+ unsigned long flags;
+
+next_srgn:
+ rgn = hpb->rgn_tbl + rgn_idx;
+ srgn = rgn->srgn_tbl + srgn_idx;
+
+ if (likely(!srgn->is_last))
+ bitmap_len = hpb->entries_per_srgn;
+ else
+ bitmap_len = hpb->last_srgn_entries;
+
+ if ((srgn_offset + cnt) > bitmap_len)
+ set_bit_len = bitmap_len - srgn_offset;
+ else
+ set_bit_len = cnt;
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ if (rgn->rgn_state != HPB_RGN_INACTIVE) {
+ if (set_dirty) {
+ if (srgn->srgn_state == HPB_SRGN_VALID)
+ bitmap_set(srgn->mctx->ppn_dirty, srgn_offset,
+ set_bit_len);
+ } else if (hpb->is_hcm) {
+ /* rewind the read timer for lru regions */
+ rgn->read_timeout = ktime_add_ms(ktime_get(),
+ rgn->hpb->params.read_timeout_ms);
+ rgn->read_timeout_expiries =
+ rgn->hpb->params.read_timeout_expiries;
+ }
+ }
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+
+ if (hpb->is_hcm && prev_srgn != srgn) {
+ bool activate = false;
+
+ spin_lock(&rgn->rgn_lock);
+ if (set_dirty) {
+ rgn->reads -= srgn->reads;
+ srgn->reads = 0;
+ set_bit(RGN_FLAG_DIRTY, &rgn->rgn_flags);
+ } else {
+ srgn->reads++;
+ rgn->reads++;
+ if (srgn->reads == hpb->params.activation_thld)
+ activate = true;
+ }
+ spin_unlock(&rgn->rgn_lock);
+
+ if (activate ||
+ test_and_clear_bit(RGN_FLAG_UPDATE, &rgn->rgn_flags)) {
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ ufshpb_update_active_info(hpb, rgn_idx, srgn_idx);
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+ dev_dbg(&hpb->sdev_ufs_lu->sdev_dev,
+ "activate region %d-%d\n", rgn_idx, srgn_idx);
+ }
+
+ prev_srgn = srgn;
+ }
+
+ srgn_offset = 0;
+ if (++srgn_idx == hpb->srgns_per_rgn) {
+ srgn_idx = 0;
+ rgn_idx++;
+ }
+
+ cnt -= set_bit_len;
+ if (cnt > 0)
+ goto next_srgn;
+}
+
+static bool ufshpb_test_ppn_dirty(struct ufshpb_lu *hpb, int rgn_idx,
+ int srgn_idx, int srgn_offset, int cnt)
+{
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn;
+ int bitmap_len;
+ int bit_len;
+
+next_srgn:
+ rgn = hpb->rgn_tbl + rgn_idx;
+ srgn = rgn->srgn_tbl + srgn_idx;
+
+ if (likely(!srgn->is_last))
+ bitmap_len = hpb->entries_per_srgn;
+ else
+ bitmap_len = hpb->last_srgn_entries;
+
+ if (!ufshpb_is_valid_srgn(rgn, srgn))
+ return true;
+
+ /*
+ * If the region state is active, mctx must be allocated.
+ * In this case, check whether the region is evicted or
+ * mctx allocation fail.
+ */
+ if (unlikely(!srgn->mctx)) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "no mctx in region %d subregion %d.\n",
+ srgn->rgn_idx, srgn->srgn_idx);
+ return true;
+ }
+
+ if ((srgn_offset + cnt) > bitmap_len)
+ bit_len = bitmap_len - srgn_offset;
+ else
+ bit_len = cnt;
+
+ if (find_next_bit(srgn->mctx->ppn_dirty, bit_len + srgn_offset,
+ srgn_offset) < bit_len + srgn_offset)
+ return true;
+
+ srgn_offset = 0;
+ if (++srgn_idx == hpb->srgns_per_rgn) {
+ srgn_idx = 0;
+ rgn_idx++;
+ }
+
+ cnt -= bit_len;
+ if (cnt > 0)
+ goto next_srgn;
+
+ return false;
+}
+
+static inline bool is_rgn_dirty(struct ufshpb_region *rgn)
+{
+ return test_bit(RGN_FLAG_DIRTY, &rgn->rgn_flags);
+}
+
+static int ufshpb_fill_ppn_from_page(struct ufshpb_lu *hpb,
+ struct ufshpb_map_ctx *mctx, int pos,
+ int len, __be64 *ppn_buf)
+{
+ struct page *page;
+ int index, offset;
+ int copied;
+
+ index = pos / (PAGE_SIZE / HPB_ENTRY_SIZE);
+ offset = pos % (PAGE_SIZE / HPB_ENTRY_SIZE);
+
+ if ((offset + len) <= (PAGE_SIZE / HPB_ENTRY_SIZE))
+ copied = len;
+ else
+ copied = (PAGE_SIZE / HPB_ENTRY_SIZE) - offset;
+
+ page = mctx->m_page[index];
+ if (unlikely(!page)) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "error. cannot find page in mctx\n");
+ return -ENOMEM;
+ }
+
+ memcpy(ppn_buf, page_address(page) + (offset * HPB_ENTRY_SIZE),
+ copied * HPB_ENTRY_SIZE);
+
+ return copied;
+}
+
+static void
+ufshpb_get_pos_from_lpn(struct ufshpb_lu *hpb, unsigned long lpn, int *rgn_idx,
+ int *srgn_idx, int *offset)
+{
+ int rgn_offset;
+
+ *rgn_idx = lpn >> hpb->entries_per_rgn_shift;
+ rgn_offset = lpn & hpb->entries_per_rgn_mask;
+ *srgn_idx = rgn_offset >> hpb->entries_per_srgn_shift;
+ *offset = rgn_offset & hpb->entries_per_srgn_mask;
+}
+
+static void
+ufshpb_set_hpb_read_to_upiu(struct ufs_hba *hba, struct ufshpb_lu *hpb,
+ struct ufshcd_lrb *lrbp, u32 lpn, __be64 ppn,
+ u8 transfer_len, int read_id)
+{
+ unsigned char *cdb = lrbp->cmd->cmnd;
+ __be64 ppn_tmp = ppn;
+ cdb[0] = UFSHPB_READ;
+
+ if (hba->dev_quirks & UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ)
+ ppn_tmp = swab64(ppn);
+
+ /* ppn value is stored as big-endian in the host memory */
+ memcpy(&cdb[6], &ppn_tmp, sizeof(__be64));
+ cdb[14] = transfer_len;
+ cdb[15] = read_id;
+
+ lrbp->cmd->cmd_len = UFS_CDB_SIZE;
+}
+
+static inline void ufshpb_set_write_buf_cmd(unsigned char *cdb,
+ unsigned long lpn, unsigned int len,
+ int read_id)
+{
+ cdb[0] = UFSHPB_WRITE_BUFFER;
+ cdb[1] = UFSHPB_WRITE_BUFFER_PREFETCH_ID;
+
+ put_unaligned_be32(lpn, &cdb[2]);
+ cdb[6] = read_id;
+ put_unaligned_be16(len * HPB_ENTRY_SIZE, &cdb[7]);
+
+ cdb[9] = 0x00; /* Control = 0x00 */
+}
+
+static struct ufshpb_req *ufshpb_get_pre_req(struct ufshpb_lu *hpb)
+{
+ struct ufshpb_req *pre_req;
+
+ if (hpb->num_inflight_pre_req >= hpb->throttle_pre_req) {
+ dev_info(&hpb->sdev_ufs_lu->sdev_dev,
+ "pre_req throttle. inflight %d throttle %d",
+ hpb->num_inflight_pre_req, hpb->throttle_pre_req);
+ return NULL;
+ }
+
+ pre_req = list_first_entry_or_null(&hpb->lh_pre_req_free,
+ struct ufshpb_req, list_req);
+ if (!pre_req) {
+ dev_info(&hpb->sdev_ufs_lu->sdev_dev, "There is no pre_req");
+ return NULL;
+ }
+
+ list_del_init(&pre_req->list_req);
+ hpb->num_inflight_pre_req++;
+
+ return pre_req;
+}
+
+static inline void ufshpb_put_pre_req(struct ufshpb_lu *hpb,
+ struct ufshpb_req *pre_req)
+{
+ pre_req->req = NULL;
+ bio_reset(pre_req->bio);
+ list_add_tail(&pre_req->list_req, &hpb->lh_pre_req_free);
+ hpb->num_inflight_pre_req--;
+}
+
+static void ufshpb_pre_req_compl_fn(struct request *req, blk_status_t error)
+{
+ struct ufshpb_req *pre_req = (struct ufshpb_req *)req->end_io_data;
+ struct ufshpb_lu *hpb = pre_req->hpb;
+ unsigned long flags;
+
+ if (error) {
+ struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
+ struct scsi_sense_hdr sshdr;
+
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev, "block status %d", error);
+ scsi_command_normalize_sense(cmd, &sshdr);
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "code %x sense_key %x asc %x ascq %x",
+ sshdr.response_code,
+ sshdr.sense_key, sshdr.asc, sshdr.ascq);
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "byte4 %x byte5 %x byte6 %x additional_len %x",
+ sshdr.byte4, sshdr.byte5,
+ sshdr.byte6, sshdr.additional_length);
+ }
+
+ blk_mq_free_request(req);
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ ufshpb_put_pre_req(pre_req->hpb, pre_req);
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+}
+
+static int ufshpb_prep_entry(struct ufshpb_req *pre_req, struct page *page)
+{
+ struct ufshpb_lu *hpb = pre_req->hpb;
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn;
+ __be64 *addr;
+ int offset = 0;
+ int copied;
+ unsigned long lpn = pre_req->wb.lpn;
+ int rgn_idx, srgn_idx, srgn_offset;
+ unsigned long flags;
+
+ addr = page_address(page);
+ ufshpb_get_pos_from_lpn(hpb, lpn, &rgn_idx, &srgn_idx, &srgn_offset);
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+
+next_offset:
+ rgn = hpb->rgn_tbl + rgn_idx;
+ srgn = rgn->srgn_tbl + srgn_idx;
+
+ if (!ufshpb_is_valid_srgn(rgn, srgn))
+ goto mctx_error;
+
+ if (!srgn->mctx)
+ goto mctx_error;
+
+ copied = ufshpb_fill_ppn_from_page(hpb, srgn->mctx, srgn_offset,
+ pre_req->wb.len - offset,
+ &addr[offset]);
+
+ if (copied < 0)
+ goto mctx_error;
+
+ offset += copied;
+ srgn_offset += copied;
+
+ if (srgn_offset == hpb->entries_per_srgn) {
+ srgn_offset = 0;
+
+ if (++srgn_idx == hpb->srgns_per_rgn) {
+ srgn_idx = 0;
+ rgn_idx++;
+ }
+ }
+
+ if (offset < pre_req->wb.len)
+ goto next_offset;
+
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ return 0;
+mctx_error:
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ return -ENOMEM;
+}
+
+static int ufshpb_pre_req_add_bio_page(struct ufshpb_lu *hpb,
+ struct request_queue *q,
+ struct ufshpb_req *pre_req)
+{
+ struct page *page = pre_req->wb.m_page;
+ struct bio *bio = pre_req->bio;
+ int entries_bytes, ret;
+
+ if (!page)
+ return -ENOMEM;
+
+ if (ufshpb_prep_entry(pre_req, page))
+ return -ENOMEM;
+
+ entries_bytes = pre_req->wb.len * sizeof(__be64);
+
+ ret = bio_add_pc_page(q, bio, page, entries_bytes, 0);
+ if (ret != entries_bytes) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "bio_add_pc_page fail: %d", ret);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static inline int ufshpb_get_read_id(struct ufshpb_lu *hpb)
+{
+ if (++hpb->cur_read_id >= MAX_HPB_READ_ID)
+ hpb->cur_read_id = 1;
+ return hpb->cur_read_id;
+}
+
+static int ufshpb_execute_pre_req(struct ufshpb_lu *hpb, struct scsi_cmnd *cmd,
+ struct ufshpb_req *pre_req, int read_id)
+{
+ struct scsi_device *sdev = cmd->device;
+ struct request_queue *q = sdev->request_queue;
+ struct request *req;
+ struct scsi_request *rq;
+ struct bio *bio = pre_req->bio;
+
+ pre_req->hpb = hpb;
+ pre_req->wb.lpn = sectors_to_logical(cmd->device,
+ blk_rq_pos(scsi_cmd_to_rq(cmd)));
+ pre_req->wb.len = sectors_to_logical(cmd->device,
+ blk_rq_sectors(scsi_cmd_to_rq(cmd)));
+ if (ufshpb_pre_req_add_bio_page(hpb, q, pre_req))
+ return -ENOMEM;
+
+ req = pre_req->req;
+
+ /* 1. request setup */
+ blk_rq_append_bio(req, bio);
+ req->rq_disk = NULL;
+ req->end_io_data = (void *)pre_req;
+ req->end_io = ufshpb_pre_req_compl_fn;
+
+ /* 2. scsi_request setup */
+ rq = scsi_req(req);
+ rq->retries = 1;
+
+ ufshpb_set_write_buf_cmd(rq->cmd, pre_req->wb.lpn, pre_req->wb.len,
+ read_id);
+ rq->cmd_len = scsi_command_size(rq->cmd);
+
+ if (blk_insert_cloned_request(q, req) != BLK_STS_OK)
+ return -EAGAIN;
+
+ hpb->stats.pre_req_cnt++;
+
+ return 0;
+}
+
+static int ufshpb_issue_pre_req(struct ufshpb_lu *hpb, struct scsi_cmnd *cmd,
+ int *read_id)
+{
+ struct ufshpb_req *pre_req;
+ struct request *req = NULL;
+ unsigned long flags;
+ int _read_id;
+ int ret = 0;
+
+ req = blk_get_request(cmd->device->request_queue,
+ REQ_OP_DRV_OUT | REQ_SYNC, BLK_MQ_REQ_NOWAIT);
+ if (IS_ERR(req))
+ return -EAGAIN;
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ pre_req = ufshpb_get_pre_req(hpb);
+ if (!pre_req) {
+ ret = -EAGAIN;
+ goto unlock_out;
+ }
+ _read_id = ufshpb_get_read_id(hpb);
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+
+ pre_req->req = req;
+
+ ret = ufshpb_execute_pre_req(hpb, cmd, pre_req, _read_id);
+ if (ret)
+ goto free_pre_req;
+
+ *read_id = _read_id;
+
+ return ret;
+free_pre_req:
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ ufshpb_put_pre_req(hpb, pre_req);
+unlock_out:
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ blk_put_request(req);
+ return ret;
+}
+
+/*
+ * This function will set up HPB read command using host-side L2P map data.
+ */
+int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+{
+ struct ufshpb_lu *hpb;
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn;
+ struct scsi_cmnd *cmd = lrbp->cmd;
+ u32 lpn;
+ __be64 ppn;
+ unsigned long flags;
+ int transfer_len, rgn_idx, srgn_idx, srgn_offset;
+ int read_id = 0;
+ int err = 0;
+
+ hpb = ufshpb_get_hpb_data(cmd->device);
+ if (!hpb)
+ return -ENODEV;
+
+ if (ufshpb_get_state(hpb) == HPB_INIT)
+ return -ENODEV;
+
+ if (ufshpb_get_state(hpb) != HPB_PRESENT) {
+ dev_notice(&hpb->sdev_ufs_lu->sdev_dev,
+ "%s: ufshpb state is not PRESENT", __func__);
+ return -ENODEV;
+ }
+
+ if (blk_rq_is_passthrough(scsi_cmd_to_rq(cmd)) ||
+ (!ufshpb_is_write_or_discard(cmd) &&
+ !ufshpb_is_read_cmd(cmd)))
+ return 0;
+
+ transfer_len = sectors_to_logical(cmd->device,
+ blk_rq_sectors(scsi_cmd_to_rq(cmd)));
+ if (unlikely(!transfer_len))
+ return 0;
+
+ lpn = sectors_to_logical(cmd->device, blk_rq_pos(scsi_cmd_to_rq(cmd)));
+ ufshpb_get_pos_from_lpn(hpb, lpn, &rgn_idx, &srgn_idx, &srgn_offset);
+ rgn = hpb->rgn_tbl + rgn_idx;
+ srgn = rgn->srgn_tbl + srgn_idx;
+
+ /* If command type is WRITE or DISCARD, set bitmap as drity */
+ if (ufshpb_is_write_or_discard(cmd)) {
+ ufshpb_iterate_rgn(hpb, rgn_idx, srgn_idx, srgn_offset,
+ transfer_len, true);
+ return 0;
+ }
+
+ if (!ufshpb_is_supported_chunk(hpb, transfer_len))
+ return 0;
+
+ WARN_ON_ONCE(transfer_len > HPB_MULTI_CHUNK_HIGH);
+
+ if (hpb->is_hcm) {
+ /*
+ * in host control mode, reads are the main source for
+ * activation trials.
+ */
+ ufshpb_iterate_rgn(hpb, rgn_idx, srgn_idx, srgn_offset,
+ transfer_len, false);
+
+ /* keep those counters normalized */
+ if (rgn->reads > hpb->entries_per_srgn)
+ schedule_work(&hpb->ufshpb_normalization_work);
+ }
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ if (ufshpb_test_ppn_dirty(hpb, rgn_idx, srgn_idx, srgn_offset,
+ transfer_len)) {
+ hpb->stats.miss_cnt++;
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ return 0;
+ }
+
+ err = ufshpb_fill_ppn_from_page(hpb, srgn->mctx, srgn_offset, 1, &ppn);
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ if (unlikely(err < 0)) {
+ /*
+ * In this case, the region state is active,
+ * but the ppn table is not allocated.
+ * Make sure that ppn table must be allocated on
+ * active state.
+ */
+ dev_err(hba->dev, "get ppn failed. err %d\n", err);
+ return err;
+ }
+ if (!ufshpb_is_legacy(hba) &&
+ ufshpb_is_required_wb(hpb, transfer_len)) {
+ err = ufshpb_issue_pre_req(hpb, cmd, &read_id);
+ if (err) {
+ unsigned long timeout;
+
+ timeout = cmd->jiffies_at_alloc + msecs_to_jiffies(
+ hpb->params.requeue_timeout_ms);
+
+ if (time_before(jiffies, timeout))
+ return -EAGAIN;
+
+ hpb->stats.miss_cnt++;
+ return 0;
+ }
+ }
+
+ ufshpb_set_hpb_read_to_upiu(hba, hpb, lrbp, lpn, ppn, transfer_len,
+ read_id);
+
+ hpb->stats.hit_cnt++;
+ return 0;
+}
+
+static struct ufshpb_req *ufshpb_get_req(struct ufshpb_lu *hpb,
+ int rgn_idx, enum req_opf dir,
+ bool atomic)
+{
+ struct ufshpb_req *rq;
+ struct request *req;
+ int retries = HPB_MAP_REQ_RETRIES;
+
+ rq = kmem_cache_alloc(hpb->map_req_cache, GFP_KERNEL);
+ if (!rq)
+ return NULL;
+
+retry:
+ req = blk_get_request(hpb->sdev_ufs_lu->request_queue, dir,
+ BLK_MQ_REQ_NOWAIT);
+
+ if (!atomic && (PTR_ERR(req) == -EWOULDBLOCK) && (--retries > 0)) {
+ usleep_range(3000, 3100);
+ goto retry;
+ }
+
+ if (IS_ERR(req))
+ goto free_rq;
+
+ rq->hpb = hpb;
+ rq->req = req;
+ rq->rb.rgn_idx = rgn_idx;
+
+ return rq;
+
+free_rq:
+ kmem_cache_free(hpb->map_req_cache, rq);
+ return NULL;
+}
+
+static void ufshpb_put_req(struct ufshpb_lu *hpb, struct ufshpb_req *rq)
+{
+ blk_put_request(rq->req);
+ kmem_cache_free(hpb->map_req_cache, rq);
+}
+
+static struct ufshpb_req *ufshpb_get_map_req(struct ufshpb_lu *hpb,
+ struct ufshpb_subregion *srgn)
+{
+ struct ufshpb_req *map_req;
+ struct bio *bio;
+ unsigned long flags;
+
+ if (hpb->is_hcm &&
+ hpb->num_inflight_map_req >= hpb->params.inflight_map_req) {
+ dev_info(&hpb->sdev_ufs_lu->sdev_dev,
+ "map_req throttle. inflight %d throttle %d",
+ hpb->num_inflight_map_req,
+ hpb->params.inflight_map_req);
+ return NULL;
+ }
+
+ map_req = ufshpb_get_req(hpb, srgn->rgn_idx, REQ_OP_DRV_IN, false);
+ if (!map_req)
+ return NULL;
+
+ bio = bio_alloc(GFP_KERNEL, hpb->pages_per_srgn);
+ if (!bio) {
+ ufshpb_put_req(hpb, map_req);
+ return NULL;
+ }
+
+ map_req->bio = bio;
+
+ map_req->rb.srgn_idx = srgn->srgn_idx;
+ map_req->rb.mctx = srgn->mctx;
+
+ spin_lock_irqsave(&hpb->param_lock, flags);
+ hpb->num_inflight_map_req++;
+ spin_unlock_irqrestore(&hpb->param_lock, flags);
+
+ return map_req;
+}
+
+static void ufshpb_put_map_req(struct ufshpb_lu *hpb,
+ struct ufshpb_req *map_req)
+{
+ unsigned long flags;
+
+ bio_put(map_req->bio);
+ ufshpb_put_req(hpb, map_req);
+
+ spin_lock_irqsave(&hpb->param_lock, flags);
+ hpb->num_inflight_map_req--;
+ spin_unlock_irqrestore(&hpb->param_lock, flags);
+}
+
+static int ufshpb_clear_dirty_bitmap(struct ufshpb_lu *hpb,
+ struct ufshpb_subregion *srgn)
+{
+ struct ufshpb_region *rgn;
+ u32 num_entries = hpb->entries_per_srgn;
+
+ if (!srgn->mctx) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "no mctx in region %d subregion %d.\n",
+ srgn->rgn_idx, srgn->srgn_idx);
+ return -1;
+ }
+
+ if (unlikely(srgn->is_last))
+ num_entries = hpb->last_srgn_entries;
+
+ bitmap_zero(srgn->mctx->ppn_dirty, num_entries);
+
+ rgn = hpb->rgn_tbl + srgn->rgn_idx;
+ clear_bit(RGN_FLAG_DIRTY, &rgn->rgn_flags);
+
+ return 0;
+}
+
+static void ufshpb_update_active_info(struct ufshpb_lu *hpb, int rgn_idx,
+ int srgn_idx)
+{
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn;
+
+ rgn = hpb->rgn_tbl + rgn_idx;
+ srgn = rgn->srgn_tbl + srgn_idx;
+
+ list_del_init(&rgn->list_inact_rgn);
+
+ if (list_empty(&srgn->list_act_srgn))
+ list_add_tail(&srgn->list_act_srgn, &hpb->lh_act_srgn);
+
+ hpb->stats.rb_active_cnt++;
+}
+
+static void ufshpb_update_inactive_info(struct ufshpb_lu *hpb, int rgn_idx)
+{
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn;
+ int srgn_idx;
+
+ rgn = hpb->rgn_tbl + rgn_idx;
+
+ for_each_sub_region(rgn, srgn_idx, srgn)
+ list_del_init(&srgn->list_act_srgn);
+
+ if (list_empty(&rgn->list_inact_rgn))
+ list_add_tail(&rgn->list_inact_rgn, &hpb->lh_inact_rgn);
+
+ hpb->stats.rb_inactive_cnt++;
+}
+
+static void ufshpb_activate_subregion(struct ufshpb_lu *hpb,
+ struct ufshpb_subregion *srgn)
+{
+ struct ufshpb_region *rgn;
+
+ /*
+ * If there is no mctx in subregion
+ * after I/O progress for HPB_READ_BUFFER, the region to which the
+ * subregion belongs was evicted.
+ * Make sure the region must not evict in I/O progress
+ */
+ if (!srgn->mctx) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "no mctx in region %d subregion %d.\n",
+ srgn->rgn_idx, srgn->srgn_idx);
+ srgn->srgn_state = HPB_SRGN_INVALID;
+ return;
+ }
+
+ rgn = hpb->rgn_tbl + srgn->rgn_idx;
+
+ if (unlikely(rgn->rgn_state == HPB_RGN_INACTIVE)) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "region %d subregion %d evicted\n",
+ srgn->rgn_idx, srgn->srgn_idx);
+ srgn->srgn_state = HPB_SRGN_INVALID;
+ return;
+ }
+ srgn->srgn_state = HPB_SRGN_VALID;
+}
+
+static void ufshpb_umap_req_compl_fn(struct request *req, blk_status_t error)
+{
+ struct ufshpb_req *umap_req = (struct ufshpb_req *)req->end_io_data;
+
+ ufshpb_put_req(umap_req->hpb, umap_req);
+}
+
+static void ufshpb_map_req_compl_fn(struct request *req, blk_status_t error)
+{
+ struct ufshpb_req *map_req = (struct ufshpb_req *) req->end_io_data;
+ struct ufshpb_lu *hpb = map_req->hpb;
+ struct ufshpb_subregion *srgn;
+ unsigned long flags;
+
+ srgn = hpb->rgn_tbl[map_req->rb.rgn_idx].srgn_tbl +
+ map_req->rb.srgn_idx;
+
+ ufshpb_clear_dirty_bitmap(hpb, srgn);
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ ufshpb_activate_subregion(hpb, srgn);
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+
+ ufshpb_put_map_req(map_req->hpb, map_req);
+}
+
+static void ufshpb_set_unmap_cmd(unsigned char *cdb, struct ufshpb_region *rgn)
+{
+ cdb[0] = UFSHPB_WRITE_BUFFER;
+ cdb[1] = rgn ? UFSHPB_WRITE_BUFFER_INACT_SINGLE_ID :
+ UFSHPB_WRITE_BUFFER_INACT_ALL_ID;
+ if (rgn)
+ put_unaligned_be16(rgn->rgn_idx, &cdb[2]);
+ cdb[9] = 0x00;
+}
+
+static void ufshpb_set_read_buf_cmd(unsigned char *cdb, int rgn_idx,
+ int srgn_idx, int srgn_mem_size)
+{
+ cdb[0] = UFSHPB_READ_BUFFER;
+ cdb[1] = UFSHPB_READ_BUFFER_ID;
+
+ put_unaligned_be16(rgn_idx, &cdb[2]);
+ put_unaligned_be16(srgn_idx, &cdb[4]);
+ put_unaligned_be24(srgn_mem_size, &cdb[6]);
+
+ cdb[9] = 0x00;
+}
+
+static void ufshpb_execute_umap_req(struct ufshpb_lu *hpb,
+ struct ufshpb_req *umap_req,
+ struct ufshpb_region *rgn)
+{
+ struct request *req;
+ struct scsi_request *rq;
+
+ req = umap_req->req;
+ req->timeout = 0;
+ req->end_io_data = (void *)umap_req;
+ rq = scsi_req(req);
+ ufshpb_set_unmap_cmd(rq->cmd, rgn);
+ rq->cmd_len = HPB_WRITE_BUFFER_CMD_LENGTH;
+
+ blk_execute_rq_nowait(NULL, req, 1, ufshpb_umap_req_compl_fn);
+
+ hpb->stats.umap_req_cnt++;
+}
+
+static int ufshpb_execute_map_req(struct ufshpb_lu *hpb,
+ struct ufshpb_req *map_req, bool last)
+{
+ struct request_queue *q;
+ struct request *req;
+ struct scsi_request *rq;
+ int mem_size = hpb->srgn_mem_size;
+ int ret = 0;
+ int i;
+
+ q = hpb->sdev_ufs_lu->request_queue;
+ for (i = 0; i < hpb->pages_per_srgn; i++) {
+ ret = bio_add_pc_page(q, map_req->bio, map_req->rb.mctx->m_page[i],
+ PAGE_SIZE, 0);
+ if (ret != PAGE_SIZE) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "bio_add_pc_page fail %d - %d\n",
+ map_req->rb.rgn_idx, map_req->rb.srgn_idx);
+ return ret;
+ }
+ }
+
+ req = map_req->req;
+
+ blk_rq_append_bio(req, map_req->bio);
+
+ req->end_io_data = map_req;
+
+ rq = scsi_req(req);
+
+ if (unlikely(last))
+ mem_size = hpb->last_srgn_entries * HPB_ENTRY_SIZE;
+
+ ufshpb_set_read_buf_cmd(rq->cmd, map_req->rb.rgn_idx,
+ map_req->rb.srgn_idx, mem_size);
+ rq->cmd_len = HPB_READ_BUFFER_CMD_LENGTH;
+
+ blk_execute_rq_nowait(NULL, req, 1, ufshpb_map_req_compl_fn);
+
+ hpb->stats.map_req_cnt++;
+ return 0;
+}
+
+static struct ufshpb_map_ctx *ufshpb_get_map_ctx(struct ufshpb_lu *hpb,
+ bool last)
+{
+ struct ufshpb_map_ctx *mctx;
+ u32 num_entries = hpb->entries_per_srgn;
+ int i, j;
+
+ mctx = mempool_alloc(ufshpb_mctx_pool, GFP_KERNEL);
+ if (!mctx)
+ return NULL;
+
+ mctx->m_page = kmem_cache_alloc(hpb->m_page_cache, GFP_KERNEL);
+ if (!mctx->m_page)
+ goto release_mctx;
+
+ if (unlikely(last))
+ num_entries = hpb->last_srgn_entries;
+
+ mctx->ppn_dirty = bitmap_zalloc(num_entries, GFP_KERNEL);
+ if (!mctx->ppn_dirty)
+ goto release_m_page;
+
+ for (i = 0; i < hpb->pages_per_srgn; i++) {
+ mctx->m_page[i] = mempool_alloc(ufshpb_page_pool, GFP_KERNEL);
+ if (!mctx->m_page[i]) {
+ for (j = 0; j < i; j++)
+ mempool_free(mctx->m_page[j], ufshpb_page_pool);
+ goto release_ppn_dirty;
+ }
+ clear_page(page_address(mctx->m_page[i]));
+ }
+
+ return mctx;
+
+release_ppn_dirty:
+ bitmap_free(mctx->ppn_dirty);
+release_m_page:
+ kmem_cache_free(hpb->m_page_cache, mctx->m_page);
+release_mctx:
+ mempool_free(mctx, ufshpb_mctx_pool);
+ return NULL;
+}
+
+static void ufshpb_put_map_ctx(struct ufshpb_lu *hpb,
+ struct ufshpb_map_ctx *mctx)
+{
+ int i;
+
+ for (i = 0; i < hpb->pages_per_srgn; i++)
+ mempool_free(mctx->m_page[i], ufshpb_page_pool);
+
+ bitmap_free(mctx->ppn_dirty);
+ kmem_cache_free(hpb->m_page_cache, mctx->m_page);
+ mempool_free(mctx, ufshpb_mctx_pool);
+}
+
+static int ufshpb_check_srgns_issue_state(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn)
+{
+ struct ufshpb_subregion *srgn;
+ int srgn_idx;
+
+ for_each_sub_region(rgn, srgn_idx, srgn)
+ if (srgn->srgn_state == HPB_SRGN_ISSUED)
+ return -EPERM;
+
+ return 0;
+}
+
+static void ufshpb_read_to_handler(struct work_struct *work)
+{
+ struct ufshpb_lu *hpb = container_of(work, struct ufshpb_lu,
+ ufshpb_read_to_work.work);
+ struct victim_select_info *lru_info = &hpb->lru_info;
+ struct ufshpb_region *rgn, *next_rgn;
+ unsigned long flags;
+ unsigned int poll;
+ LIST_HEAD(expired_list);
+
+ if (test_and_set_bit(TIMEOUT_WORK_RUNNING, &hpb->work_data_bits))
+ return;
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+
+ list_for_each_entry_safe(rgn, next_rgn, &lru_info->lh_lru_rgn,
+ list_lru_rgn) {
+ bool timedout = ktime_after(ktime_get(), rgn->read_timeout);
+
+ if (timedout) {
+ rgn->read_timeout_expiries--;
+ if (is_rgn_dirty(rgn) ||
+ rgn->read_timeout_expiries == 0)
+ list_add(&rgn->list_expired_rgn, &expired_list);
+ else
+ rgn->read_timeout = ktime_add_ms(ktime_get(),
+ hpb->params.read_timeout_ms);
+ }
+ }
+
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+
+ list_for_each_entry_safe(rgn, next_rgn, &expired_list,
+ list_expired_rgn) {
+ list_del_init(&rgn->list_expired_rgn);
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ ufshpb_update_inactive_info(hpb, rgn->rgn_idx);
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+ }
+
+ ufshpb_kick_map_work(hpb);
+
+ clear_bit(TIMEOUT_WORK_RUNNING, &hpb->work_data_bits);
+
+ poll = hpb->params.timeout_polling_interval_ms;
+ schedule_delayed_work(&hpb->ufshpb_read_to_work,
+ msecs_to_jiffies(poll));
+}
+
+static void ufshpb_add_lru_info(struct victim_select_info *lru_info,
+ struct ufshpb_region *rgn)
+{
+ rgn->rgn_state = HPB_RGN_ACTIVE;
+ list_add_tail(&rgn->list_lru_rgn, &lru_info->lh_lru_rgn);
+ atomic_inc(&lru_info->active_cnt);
+ if (rgn->hpb->is_hcm) {
+ rgn->read_timeout =
+ ktime_add_ms(ktime_get(),
+ rgn->hpb->params.read_timeout_ms);
+ rgn->read_timeout_expiries =
+ rgn->hpb->params.read_timeout_expiries;
+ }
+}
+
+static void ufshpb_hit_lru_info(struct victim_select_info *lru_info,
+ struct ufshpb_region *rgn)
+{
+ list_move_tail(&rgn->list_lru_rgn, &lru_info->lh_lru_rgn);
+}
+
+static struct ufshpb_region *ufshpb_victim_lru_info(struct ufshpb_lu *hpb)
+{
+ struct victim_select_info *lru_info = &hpb->lru_info;
+ struct ufshpb_region *rgn, *victim_rgn = NULL;
+
+ list_for_each_entry(rgn, &lru_info->lh_lru_rgn, list_lru_rgn) {
+ if (!rgn) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "%s: no region allocated\n",
+ __func__);
+ return NULL;
+ }
+ if (ufshpb_check_srgns_issue_state(hpb, rgn))
+ continue;
+
+ /*
+ * in host control mode, verify that the exiting region
+ * has fewer reads
+ */
+ if (hpb->is_hcm &&
+ rgn->reads > hpb->params.eviction_thld_exit)
+ continue;
+
+ victim_rgn = rgn;
+ break;
+ }
+
+ return victim_rgn;
+}
+
+static void ufshpb_cleanup_lru_info(struct victim_select_info *lru_info,
+ struct ufshpb_region *rgn)
+{
+ list_del_init(&rgn->list_lru_rgn);
+ rgn->rgn_state = HPB_RGN_INACTIVE;
+ atomic_dec(&lru_info->active_cnt);
+}
+
+static void ufshpb_purge_active_subregion(struct ufshpb_lu *hpb,
+ struct ufshpb_subregion *srgn)
+{
+ if (srgn->srgn_state != HPB_SRGN_UNUSED) {
+ ufshpb_put_map_ctx(hpb, srgn->mctx);
+ srgn->srgn_state = HPB_SRGN_UNUSED;
+ srgn->mctx = NULL;
+ }
+}
+
+static int ufshpb_issue_umap_req(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn,
+ bool atomic)
+{
+ struct ufshpb_req *umap_req;
+ int rgn_idx = rgn ? rgn->rgn_idx : 0;
+
+ umap_req = ufshpb_get_req(hpb, rgn_idx, REQ_OP_DRV_OUT, atomic);
+ if (!umap_req)
+ return -ENOMEM;
+
+ ufshpb_execute_umap_req(hpb, umap_req, rgn);
+
+ return 0;
+}
+
+static int ufshpb_issue_umap_single_req(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn)
+{
+ return ufshpb_issue_umap_req(hpb, rgn, true);
+}
+
+static int ufshpb_issue_umap_all_req(struct ufshpb_lu *hpb)
+{
+ return ufshpb_issue_umap_req(hpb, NULL, false);
+}
+
+static void __ufshpb_evict_region(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn)
+{
+ struct victim_select_info *lru_info;
+ struct ufshpb_subregion *srgn;
+ int srgn_idx;
+
+ lru_info = &hpb->lru_info;
+
+ dev_dbg(&hpb->sdev_ufs_lu->sdev_dev, "evict region %d\n", rgn->rgn_idx);
+
+ ufshpb_cleanup_lru_info(lru_info, rgn);
+
+ for_each_sub_region(rgn, srgn_idx, srgn)
+ ufshpb_purge_active_subregion(hpb, srgn);
+}
+
+static int ufshpb_evict_region(struct ufshpb_lu *hpb, struct ufshpb_region *rgn)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ if (rgn->rgn_state == HPB_RGN_PINNED) {
+ dev_warn(&hpb->sdev_ufs_lu->sdev_dev,
+ "pinned region cannot drop-out. region %d\n",
+ rgn->rgn_idx);
+ goto out;
+ }
+
+ if (!list_empty(&rgn->list_lru_rgn)) {
+ if (ufshpb_check_srgns_issue_state(hpb, rgn)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (hpb->is_hcm) {
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ ret = ufshpb_issue_umap_single_req(hpb, rgn);
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ if (ret)
+ goto out;
+ }
+
+ __ufshpb_evict_region(hpb, rgn);
+ }
+out:
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ return ret;
+}
+
+static int ufshpb_issue_map_req(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn,
+ struct ufshpb_subregion *srgn)
+{
+ struct ufshpb_req *map_req;
+ unsigned long flags;
+ int ret;
+ int err = -EAGAIN;
+ bool alloc_required = false;
+ enum HPB_SRGN_STATE state = HPB_SRGN_INVALID;
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+
+ if (ufshpb_get_state(hpb) != HPB_PRESENT) {
+ dev_notice(&hpb->sdev_ufs_lu->sdev_dev,
+ "%s: ufshpb state is not PRESENT\n", __func__);
+ goto unlock_out;
+ }
+
+ if ((rgn->rgn_state == HPB_RGN_INACTIVE) &&
+ (srgn->srgn_state == HPB_SRGN_INVALID)) {
+ err = 0;
+ goto unlock_out;
+ }
+
+ if (srgn->srgn_state == HPB_SRGN_UNUSED)
+ alloc_required = true;
+
+ /*
+ * If the subregion is already ISSUED state,
+ * a specific event (e.g., GC or wear-leveling, etc.) occurs in
+ * the device and HPB response for map loading is received.
+ * In this case, after finishing the HPB_READ_BUFFER,
+ * the next HPB_READ_BUFFER is performed again to obtain the latest
+ * map data.
+ */
+ if (srgn->srgn_state == HPB_SRGN_ISSUED)
+ goto unlock_out;
+
+ srgn->srgn_state = HPB_SRGN_ISSUED;
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+
+ if (alloc_required) {
+ srgn->mctx = ufshpb_get_map_ctx(hpb, srgn->is_last);
+ if (!srgn->mctx) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "get map_ctx failed. region %d - %d\n",
+ rgn->rgn_idx, srgn->srgn_idx);
+ state = HPB_SRGN_UNUSED;
+ goto change_srgn_state;
+ }
+ }
+
+ map_req = ufshpb_get_map_req(hpb, srgn);
+ if (!map_req)
+ goto change_srgn_state;
+
+
+ ret = ufshpb_execute_map_req(hpb, map_req, srgn->is_last);
+ if (ret) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "%s: issue map_req failed: %d, region %d - %d\n",
+ __func__, ret, srgn->rgn_idx, srgn->srgn_idx);
+ goto free_map_req;
+ }
+ return 0;
+
+free_map_req:
+ ufshpb_put_map_req(hpb, map_req);
+change_srgn_state:
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ srgn->srgn_state = state;
+unlock_out:
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ return err;
+}
+
+static int ufshpb_add_region(struct ufshpb_lu *hpb, struct ufshpb_region *rgn)
+{
+ struct ufshpb_region *victim_rgn = NULL;
+ struct victim_select_info *lru_info = &hpb->lru_info;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+ /*
+ * If region belongs to lru_list, just move the region
+ * to the front of lru list because the state of the region
+ * is already active-state.
+ */
+ if (!list_empty(&rgn->list_lru_rgn)) {
+ ufshpb_hit_lru_info(lru_info, rgn);
+ goto out;
+ }
+
+ if (rgn->rgn_state == HPB_RGN_INACTIVE) {
+ if (atomic_read(&lru_info->active_cnt) ==
+ lru_info->max_lru_active_cnt) {
+ /*
+ * If the maximum number of active regions
+ * is exceeded, evict the least recently used region.
+ * This case may occur when the device responds
+ * to the eviction information late.
+ * It is okay to evict the least recently used region,
+ * because the device could detect this region
+ * by not issuing HPB_READ
+ *
+ * in host control mode, verify that the entering
+ * region has enough reads
+ */
+ if (hpb->is_hcm &&
+ rgn->reads < hpb->params.eviction_thld_enter) {
+ ret = -EACCES;
+ goto out;
+ }
+
+ victim_rgn = ufshpb_victim_lru_info(hpb);
+ if (!victim_rgn) {
+ dev_warn(&hpb->sdev_ufs_lu->sdev_dev,
+ "cannot get victim region %s\n",
+ hpb->is_hcm ? "" : "error");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_dbg(&hpb->sdev_ufs_lu->sdev_dev,
+ "LRU full (%d), choose victim %d\n",
+ atomic_read(&lru_info->active_cnt),
+ victim_rgn->rgn_idx);
+
+ if (hpb->is_hcm) {
+ spin_unlock_irqrestore(&hpb->rgn_state_lock,
+ flags);
+ ret = ufshpb_issue_umap_single_req(hpb,
+ victim_rgn);
+ spin_lock_irqsave(&hpb->rgn_state_lock,
+ flags);
+ if (ret)
+ goto out;
+ }
+
+ __ufshpb_evict_region(hpb, victim_rgn);
+ }
+
+ /*
+ * When a region is added to lru_info list_head,
+ * it is guaranteed that the subregion has been
+ * assigned all mctx. If failed, try to receive mctx again
+ * without being added to lru_info list_head
+ */
+ ufshpb_add_lru_info(lru_info, rgn);
+ }
+out:
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+ return ret;
+}
+
+static void ufshpb_rsp_req_region_update(struct ufshpb_lu *hpb,
+ struct utp_hpb_rsp *rsp_field)
+{
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn;
+ int i, rgn_i, srgn_i;
+
+ BUILD_BUG_ON(sizeof(struct ufshpb_active_field) != HPB_ACT_FIELD_SIZE);
+ /*
+ * If the active region and the inactive region are the same,
+ * we will inactivate this region.
+ * The device could check this (region inactivated) and
+ * will response the proper active region information
+ */
+ for (i = 0; i < rsp_field->active_rgn_cnt; i++) {
+ rgn_i =
+ be16_to_cpu(rsp_field->hpb_active_field[i].active_rgn);
+ srgn_i =
+ be16_to_cpu(rsp_field->hpb_active_field[i].active_srgn);
+
+ rgn = hpb->rgn_tbl + rgn_i;
+ if (hpb->is_hcm &&
+ (rgn->rgn_state != HPB_RGN_ACTIVE || is_rgn_dirty(rgn))) {
+ /*
+ * in host control mode, subregion activation
+ * recommendations are only allowed to active regions.
+ * Also, ignore recommendations for dirty regions - the
+ * host will make decisions concerning those by himself
+ */
+ continue;
+ }
+
+ dev_dbg(&hpb->sdev_ufs_lu->sdev_dev,
+ "activate(%d) region %d - %d\n", i, rgn_i, srgn_i);
+
+ spin_lock(&hpb->rsp_list_lock);
+ ufshpb_update_active_info(hpb, rgn_i, srgn_i);
+ spin_unlock(&hpb->rsp_list_lock);
+
+ srgn = rgn->srgn_tbl + srgn_i;
+
+ /* blocking HPB_READ */
+ spin_lock(&hpb->rgn_state_lock);
+ if (srgn->srgn_state == HPB_SRGN_VALID)
+ srgn->srgn_state = HPB_SRGN_INVALID;
+ spin_unlock(&hpb->rgn_state_lock);
+ }
+
+ if (hpb->is_hcm) {
+ /*
+ * in host control mode the device is not allowed to inactivate
+ * regions
+ */
+ goto out;
+ }
+
+ for (i = 0; i < rsp_field->inactive_rgn_cnt; i++) {
+ rgn_i = be16_to_cpu(rsp_field->hpb_inactive_field[i]);
+ dev_dbg(&hpb->sdev_ufs_lu->sdev_dev,
+ "inactivate(%d) region %d\n", i, rgn_i);
+
+ spin_lock(&hpb->rsp_list_lock);
+ ufshpb_update_inactive_info(hpb, rgn_i);
+ spin_unlock(&hpb->rsp_list_lock);
+
+ rgn = hpb->rgn_tbl + rgn_i;
+
+ spin_lock(&hpb->rgn_state_lock);
+ if (rgn->rgn_state != HPB_RGN_INACTIVE) {
+ for (srgn_i = 0; srgn_i < rgn->srgn_cnt; srgn_i++) {
+ srgn = rgn->srgn_tbl + srgn_i;
+ if (srgn->srgn_state == HPB_SRGN_VALID)
+ srgn->srgn_state = HPB_SRGN_INVALID;
+ }
+ }
+ spin_unlock(&hpb->rgn_state_lock);
+
+ }
+
+out:
+ dev_dbg(&hpb->sdev_ufs_lu->sdev_dev, "Noti: #ACT %u #INACT %u\n",
+ rsp_field->active_rgn_cnt, rsp_field->inactive_rgn_cnt);
+
+ if (ufshpb_get_state(hpb) == HPB_PRESENT)
+ queue_work(ufshpb_wq, &hpb->map_work);
+}
+
+static void ufshpb_dev_reset_handler(struct ufshpb_lu *hpb)
+{
+ struct victim_select_info *lru_info = &hpb->lru_info;
+ struct ufshpb_region *rgn;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hpb->rgn_state_lock, flags);
+
+ list_for_each_entry(rgn, &lru_info->lh_lru_rgn, list_lru_rgn)
+ set_bit(RGN_FLAG_UPDATE, &rgn->rgn_flags);
+
+ spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
+}
+
+/*
+ * This function will parse recommended active subregion information in sense
+ * data field of response UPIU with SAM_STAT_GOOD state.
+ */
+void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+{
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(lrbp->cmd->device);
+ struct utp_hpb_rsp *rsp_field = &lrbp->ucd_rsp_ptr->hr;
+ int data_seg_len;
+
+ if (unlikely(lrbp->lun != rsp_field->lun)) {
+ struct scsi_device *sdev;
+ bool found = false;
+
+ __shost_for_each_device(sdev, hba->host) {
+ hpb = ufshpb_get_hpb_data(sdev);
+
+ if (!hpb)
+ continue;
+
+ if (rsp_field->lun == hpb->lun) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return;
+ }
+
+ if (!hpb)
+ return;
+
+ if (ufshpb_get_state(hpb) == HPB_INIT)
+ return;
+
+ if ((ufshpb_get_state(hpb) != HPB_PRESENT) &&
+ (ufshpb_get_state(hpb) != HPB_SUSPEND)) {
+ dev_notice(&hpb->sdev_ufs_lu->sdev_dev,
+ "%s: ufshpb state is not PRESENT/SUSPEND\n",
+ __func__);
+ return;
+ }
+
+ data_seg_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2)
+ & MASK_RSP_UPIU_DATA_SEG_LEN;
+
+ /* To flush remained rsp_list, we queue the map_work task */
+ if (!data_seg_len) {
+ if (!ufshpb_is_general_lun(hpb->lun))
+ return;
+
+ ufshpb_kick_map_work(hpb);
+ return;
+ }
+
+ BUILD_BUG_ON(sizeof(struct utp_hpb_rsp) != UTP_HPB_RSP_SIZE);
+
+ if (!ufshpb_is_hpb_rsp_valid(hba, lrbp, rsp_field))
+ return;
+
+ hpb->stats.rb_noti_cnt++;
+
+ switch (rsp_field->hpb_op) {
+ case HPB_RSP_REQ_REGION_UPDATE:
+ if (data_seg_len != DEV_DATA_SEG_LEN)
+ dev_warn(&hpb->sdev_ufs_lu->sdev_dev,
+ "%s: data seg length is not same.\n",
+ __func__);
+ ufshpb_rsp_req_region_update(hpb, rsp_field);
+ break;
+ case HPB_RSP_DEV_RESET:
+ dev_warn(&hpb->sdev_ufs_lu->sdev_dev,
+ "UFS device lost HPB information during PM.\n");
+
+ if (hpb->is_hcm) {
+ struct scsi_device *sdev;
+
+ __shost_for_each_device(sdev, hba->host) {
+ struct ufshpb_lu *h = sdev->hostdata;
+
+ if (h)
+ ufshpb_dev_reset_handler(h);
+ }
+ }
+
+ break;
+ default:
+ dev_notice(&hpb->sdev_ufs_lu->sdev_dev,
+ "hpb_op is not available: %d\n",
+ rsp_field->hpb_op);
+ break;
+ }
+}
+
+static void ufshpb_add_active_list(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn,
+ struct ufshpb_subregion *srgn)
+{
+ if (!list_empty(&rgn->list_inact_rgn))
+ return;
+
+ if (!list_empty(&srgn->list_act_srgn)) {
+ list_move(&srgn->list_act_srgn, &hpb->lh_act_srgn);
+ return;
+ }
+
+ list_add(&srgn->list_act_srgn, &hpb->lh_act_srgn);
+}
+
+static void ufshpb_add_pending_evict_list(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn,
+ struct list_head *pending_list)
+{
+ struct ufshpb_subregion *srgn;
+ int srgn_idx;
+
+ if (!list_empty(&rgn->list_inact_rgn))
+ return;
+
+ for_each_sub_region(rgn, srgn_idx, srgn)
+ if (!list_empty(&srgn->list_act_srgn))
+ return;
+
+ list_add_tail(&rgn->list_inact_rgn, pending_list);
+}
+
+static void ufshpb_run_active_subregion_list(struct ufshpb_lu *hpb)
+{
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ while ((srgn = list_first_entry_or_null(&hpb->lh_act_srgn,
+ struct ufshpb_subregion,
+ list_act_srgn))) {
+ if (ufshpb_get_state(hpb) == HPB_SUSPEND)
+ break;
+
+ list_del_init(&srgn->list_act_srgn);
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+
+ rgn = hpb->rgn_tbl + srgn->rgn_idx;
+ ret = ufshpb_add_region(hpb, rgn);
+ if (ret)
+ goto active_failed;
+
+ ret = ufshpb_issue_map_req(hpb, rgn, srgn);
+ if (ret) {
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev,
+ "issue map_req failed. ret %d, region %d - %d\n",
+ ret, rgn->rgn_idx, srgn->srgn_idx);
+ goto active_failed;
+ }
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ }
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+ return;
+
+active_failed:
+ dev_err(&hpb->sdev_ufs_lu->sdev_dev, "failed to activate region %d - %d, will retry\n",
+ rgn->rgn_idx, srgn->srgn_idx);
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ ufshpb_add_active_list(hpb, rgn, srgn);
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+}
+
+static void ufshpb_run_inactive_region_list(struct ufshpb_lu *hpb)
+{
+ struct ufshpb_region *rgn;
+ unsigned long flags;
+ int ret;
+ LIST_HEAD(pending_list);
+
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ while ((rgn = list_first_entry_or_null(&hpb->lh_inact_rgn,
+ struct ufshpb_region,
+ list_inact_rgn))) {
+ if (ufshpb_get_state(hpb) == HPB_SUSPEND)
+ break;
+
+ list_del_init(&rgn->list_inact_rgn);
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+
+ ret = ufshpb_evict_region(hpb, rgn);
+ if (ret) {
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ ufshpb_add_pending_evict_list(hpb, rgn, &pending_list);
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+ }
+
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ }
+
+ list_splice(&pending_list, &hpb->lh_inact_rgn);
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+}
+
+static void ufshpb_normalization_work_handler(struct work_struct *work)
+{
+ struct ufshpb_lu *hpb = container_of(work, struct ufshpb_lu,
+ ufshpb_normalization_work);
+ int rgn_idx;
+ u8 factor = hpb->params.normalization_factor;
+
+ for (rgn_idx = 0; rgn_idx < hpb->rgns_per_lu; rgn_idx++) {
+ struct ufshpb_region *rgn = hpb->rgn_tbl + rgn_idx;
+ int srgn_idx;
+
+ spin_lock(&rgn->rgn_lock);
+ rgn->reads = 0;
+ for (srgn_idx = 0; srgn_idx < hpb->srgns_per_rgn; srgn_idx++) {
+ struct ufshpb_subregion *srgn = rgn->srgn_tbl + srgn_idx;
+
+ srgn->reads >>= factor;
+ rgn->reads += srgn->reads;
+ }
+ spin_unlock(&rgn->rgn_lock);
+
+ if (rgn->rgn_state != HPB_RGN_ACTIVE || rgn->reads)
+ continue;
+
+ /* if region is active but has no reads - inactivate it */
+ spin_lock(&hpb->rsp_list_lock);
+ ufshpb_update_inactive_info(hpb, rgn->rgn_idx);
+ spin_unlock(&hpb->rsp_list_lock);
+ }
+}
+
+static void ufshpb_map_work_handler(struct work_struct *work)
+{
+ struct ufshpb_lu *hpb = container_of(work, struct ufshpb_lu, map_work);
+
+ if (ufshpb_get_state(hpb) != HPB_PRESENT) {
+ dev_notice(&hpb->sdev_ufs_lu->sdev_dev,
+ "%s: ufshpb state is not PRESENT\n", __func__);
+ return;
+ }
+
+ ufshpb_run_inactive_region_list(hpb);
+ ufshpb_run_active_subregion_list(hpb);
+}
+
+/*
+ * this function doesn't need to hold lock due to be called in init.
+ * (rgn_state_lock, rsp_list_lock, etc..)
+ */
+static int ufshpb_init_pinned_active_region(struct ufs_hba *hba,
+ struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn)
+{
+ struct ufshpb_subregion *srgn;
+ int srgn_idx, i;
+ int err = 0;
+
+ for_each_sub_region(rgn, srgn_idx, srgn) {
+ srgn->mctx = ufshpb_get_map_ctx(hpb, srgn->is_last);
+ srgn->srgn_state = HPB_SRGN_INVALID;
+ if (!srgn->mctx) {
+ err = -ENOMEM;
+ dev_err(hba->dev,
+ "alloc mctx for pinned region failed\n");
+ goto release;
+ }
+
+ list_add_tail(&srgn->list_act_srgn, &hpb->lh_act_srgn);
+ }
+
+ rgn->rgn_state = HPB_RGN_PINNED;
+ return 0;
+
+release:
+ for (i = 0; i < srgn_idx; i++) {
+ srgn = rgn->srgn_tbl + i;
+ ufshpb_put_map_ctx(hpb, srgn->mctx);
+ }
+ return err;
+}
+
+static void ufshpb_init_subregion_tbl(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn, bool last)
+{
+ int srgn_idx;
+ struct ufshpb_subregion *srgn;
+
+ for_each_sub_region(rgn, srgn_idx, srgn) {
+ INIT_LIST_HEAD(&srgn->list_act_srgn);
+
+ srgn->rgn_idx = rgn->rgn_idx;
+ srgn->srgn_idx = srgn_idx;
+ srgn->srgn_state = HPB_SRGN_UNUSED;
+ }
+
+ if (unlikely(last && hpb->last_srgn_entries))
+ srgn->is_last = true;
+}
+
+static int ufshpb_alloc_subregion_tbl(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn, int srgn_cnt)
+{
+ rgn->srgn_tbl = kvcalloc(srgn_cnt, sizeof(struct ufshpb_subregion),
+ GFP_KERNEL);
+ if (!rgn->srgn_tbl)
+ return -ENOMEM;
+
+ rgn->srgn_cnt = srgn_cnt;
+ return 0;
+}
+
+static void ufshpb_lu_parameter_init(struct ufs_hba *hba,
+ struct ufshpb_lu *hpb,
+ struct ufshpb_dev_info *hpb_dev_info,
+ struct ufshpb_lu_info *hpb_lu_info)
+{
+ u32 entries_per_rgn;
+ u64 rgn_mem_size, tmp;
+
+ /* for pre_req */
+ hpb->pre_req_min_tr_len = hpb_dev_info->max_hpb_single_cmd + 1;
+
+ if (ufshpb_is_legacy(hba))
+ hpb->pre_req_max_tr_len = HPB_LEGACY_CHUNK_HIGH;
+ else
+ hpb->pre_req_max_tr_len = HPB_MULTI_CHUNK_HIGH;
+
+ hpb->cur_read_id = 0;
+
+ hpb->lu_pinned_start = hpb_lu_info->pinned_start;
+ hpb->lu_pinned_end = hpb_lu_info->num_pinned ?
+ (hpb_lu_info->pinned_start + hpb_lu_info->num_pinned - 1)
+ : PINNED_NOT_SET;
+ hpb->lru_info.max_lru_active_cnt =
+ hpb_lu_info->max_active_rgns - hpb_lu_info->num_pinned;
+
+ rgn_mem_size = (1ULL << hpb_dev_info->rgn_size) * HPB_RGN_SIZE_UNIT
+ * HPB_ENTRY_SIZE;
+ do_div(rgn_mem_size, HPB_ENTRY_BLOCK_SIZE);
+ hpb->srgn_mem_size = (1ULL << hpb_dev_info->srgn_size)
+ * HPB_RGN_SIZE_UNIT / HPB_ENTRY_BLOCK_SIZE * HPB_ENTRY_SIZE;
+
+ tmp = rgn_mem_size;
+ do_div(tmp, HPB_ENTRY_SIZE);
+ entries_per_rgn = (u32)tmp;
+ hpb->entries_per_rgn_shift = ilog2(entries_per_rgn);
+ hpb->entries_per_rgn_mask = entries_per_rgn - 1;
+
+ hpb->entries_per_srgn = hpb->srgn_mem_size / HPB_ENTRY_SIZE;
+ hpb->entries_per_srgn_shift = ilog2(hpb->entries_per_srgn);
+ hpb->entries_per_srgn_mask = hpb->entries_per_srgn - 1;
+
+ tmp = rgn_mem_size;
+ do_div(tmp, hpb->srgn_mem_size);
+ hpb->srgns_per_rgn = (int)tmp;
+
+ hpb->rgns_per_lu = DIV_ROUND_UP(hpb_lu_info->num_blocks,
+ entries_per_rgn);
+ hpb->srgns_per_lu = DIV_ROUND_UP(hpb_lu_info->num_blocks,
+ (hpb->srgn_mem_size / HPB_ENTRY_SIZE));
+ hpb->last_srgn_entries = hpb_lu_info->num_blocks
+ % (hpb->srgn_mem_size / HPB_ENTRY_SIZE);
+
+ hpb->pages_per_srgn = DIV_ROUND_UP(hpb->srgn_mem_size, PAGE_SIZE);
+
+ if (hpb_dev_info->control_mode == HPB_HOST_CONTROL)
+ hpb->is_hcm = true;
+}
+
+static int ufshpb_alloc_region_tbl(struct ufs_hba *hba, struct ufshpb_lu *hpb)
+{
+ struct ufshpb_region *rgn_table, *rgn;
+ int rgn_idx, i;
+ int ret = 0;
+
+ rgn_table = kvcalloc(hpb->rgns_per_lu, sizeof(struct ufshpb_region),
+ GFP_KERNEL);
+ if (!rgn_table)
+ return -ENOMEM;
+
+ for (rgn_idx = 0; rgn_idx < hpb->rgns_per_lu; rgn_idx++) {
+ int srgn_cnt = hpb->srgns_per_rgn;
+ bool last_srgn = false;
+
+ rgn = rgn_table + rgn_idx;
+ rgn->rgn_idx = rgn_idx;
+
+ spin_lock_init(&rgn->rgn_lock);
+
+ INIT_LIST_HEAD(&rgn->list_inact_rgn);
+ INIT_LIST_HEAD(&rgn->list_lru_rgn);
+ INIT_LIST_HEAD(&rgn->list_expired_rgn);
+
+ if (rgn_idx == hpb->rgns_per_lu - 1) {
+ srgn_cnt = ((hpb->srgns_per_lu - 1) %
+ hpb->srgns_per_rgn) + 1;
+ last_srgn = true;
+ }
+
+ ret = ufshpb_alloc_subregion_tbl(hpb, rgn, srgn_cnt);
+ if (ret)
+ goto release_srgn_table;
+ ufshpb_init_subregion_tbl(hpb, rgn, last_srgn);
+
+ if (ufshpb_is_pinned_region(hpb, rgn_idx)) {
+ ret = ufshpb_init_pinned_active_region(hba, hpb, rgn);
+ if (ret)
+ goto release_srgn_table;
+ } else {
+ rgn->rgn_state = HPB_RGN_INACTIVE;
+ }
+
+ rgn->rgn_flags = 0;
+ rgn->hpb = hpb;
+ }
+
+ hpb->rgn_tbl = rgn_table;
+
+ return 0;
+
+release_srgn_table:
+ for (i = 0; i <= rgn_idx; i++)
+ kvfree(rgn_table[i].srgn_tbl);
+
+ kvfree(rgn_table);
+ return ret;
+}
+
+static void ufshpb_destroy_subregion_tbl(struct ufshpb_lu *hpb,
+ struct ufshpb_region *rgn)
+{
+ int srgn_idx;
+ struct ufshpb_subregion *srgn;
+
+ for_each_sub_region(rgn, srgn_idx, srgn)
+ if (srgn->srgn_state != HPB_SRGN_UNUSED) {
+ srgn->srgn_state = HPB_SRGN_UNUSED;
+ ufshpb_put_map_ctx(hpb, srgn->mctx);
+ }
+}
+
+static void ufshpb_destroy_region_tbl(struct ufshpb_lu *hpb)
+{
+ int rgn_idx;
+
+ for (rgn_idx = 0; rgn_idx < hpb->rgns_per_lu; rgn_idx++) {
+ struct ufshpb_region *rgn;
+
+ rgn = hpb->rgn_tbl + rgn_idx;
+ if (rgn->rgn_state != HPB_RGN_INACTIVE) {
+ rgn->rgn_state = HPB_RGN_INACTIVE;
+
+ ufshpb_destroy_subregion_tbl(hpb, rgn);
+ }
+
+ kvfree(rgn->srgn_tbl);
+ }
+
+ kvfree(hpb->rgn_tbl);
+}
+
+/* SYSFS functions */
+#define ufshpb_sysfs_attr_show_func(__name) \
+static ssize_t __name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev); \
+ \
+ if (!hpb) \
+ return -ENODEV; \
+ \
+ return sysfs_emit(buf, "%llu\n", hpb->stats.__name); \
+} \
+\
+static DEVICE_ATTR_RO(__name)
+
+ufshpb_sysfs_attr_show_func(hit_cnt);
+ufshpb_sysfs_attr_show_func(miss_cnt);
+ufshpb_sysfs_attr_show_func(rb_noti_cnt);
+ufshpb_sysfs_attr_show_func(rb_active_cnt);
+ufshpb_sysfs_attr_show_func(rb_inactive_cnt);
+ufshpb_sysfs_attr_show_func(map_req_cnt);
+ufshpb_sysfs_attr_show_func(umap_req_cnt);
+
+static struct attribute *hpb_dev_stat_attrs[] = {
+ &dev_attr_hit_cnt.attr,
+ &dev_attr_miss_cnt.attr,
+ &dev_attr_rb_noti_cnt.attr,
+ &dev_attr_rb_active_cnt.attr,
+ &dev_attr_rb_inactive_cnt.attr,
+ &dev_attr_map_req_cnt.attr,
+ &dev_attr_umap_req_cnt.attr,
+ NULL,
+};
+
+struct attribute_group ufs_sysfs_hpb_stat_group = {
+ .name = "hpb_stats",
+ .attrs = hpb_dev_stat_attrs,
+};
+
+/* SYSFS functions */
+#define ufshpb_sysfs_param_show_func(__name) \
+static ssize_t __name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev); \
+ \
+ if (!hpb) \
+ return -ENODEV; \
+ \
+ return sysfs_emit(buf, "%d\n", hpb->params.__name); \
+}
+
+ufshpb_sysfs_param_show_func(requeue_timeout_ms);
+static ssize_t
+requeue_timeout_ms_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ if (val < 0)
+ return -EINVAL;
+
+ hpb->params.requeue_timeout_ms = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(requeue_timeout_ms);
+
+ufshpb_sysfs_param_show_func(activation_thld);
+static ssize_t
+activation_thld_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (!hpb->is_hcm)
+ return -EOPNOTSUPP;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ if (val <= 0)
+ return -EINVAL;
+
+ hpb->params.activation_thld = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(activation_thld);
+
+ufshpb_sysfs_param_show_func(normalization_factor);
+static ssize_t
+normalization_factor_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (!hpb->is_hcm)
+ return -EOPNOTSUPP;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ if (val <= 0 || val > ilog2(hpb->entries_per_srgn))
+ return -EINVAL;
+
+ hpb->params.normalization_factor = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(normalization_factor);
+
+ufshpb_sysfs_param_show_func(eviction_thld_enter);
+static ssize_t
+eviction_thld_enter_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (!hpb->is_hcm)
+ return -EOPNOTSUPP;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ if (val <= hpb->params.eviction_thld_exit)
+ return -EINVAL;
+
+ hpb->params.eviction_thld_enter = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(eviction_thld_enter);
+
+ufshpb_sysfs_param_show_func(eviction_thld_exit);
+static ssize_t
+eviction_thld_exit_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (!hpb->is_hcm)
+ return -EOPNOTSUPP;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ if (val <= hpb->params.activation_thld)
+ return -EINVAL;
+
+ hpb->params.eviction_thld_exit = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(eviction_thld_exit);
+
+ufshpb_sysfs_param_show_func(read_timeout_ms);
+static ssize_t
+read_timeout_ms_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (!hpb->is_hcm)
+ return -EOPNOTSUPP;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ /* read_timeout >> timeout_polling_interval */
+ if (val < hpb->params.timeout_polling_interval_ms * 2)
+ return -EINVAL;
+
+ hpb->params.read_timeout_ms = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(read_timeout_ms);
+
+ufshpb_sysfs_param_show_func(read_timeout_expiries);
+static ssize_t
+read_timeout_expiries_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (!hpb->is_hcm)
+ return -EOPNOTSUPP;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ if (val <= 0)
+ return -EINVAL;
+
+ hpb->params.read_timeout_expiries = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(read_timeout_expiries);
+
+ufshpb_sysfs_param_show_func(timeout_polling_interval_ms);
+static ssize_t
+timeout_polling_interval_ms_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (!hpb->is_hcm)
+ return -EOPNOTSUPP;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ /* timeout_polling_interval << read_timeout */
+ if (val <= 0 || val > hpb->params.read_timeout_ms / 2)
+ return -EINVAL;
+
+ hpb->params.timeout_polling_interval_ms = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(timeout_polling_interval_ms);
+
+ufshpb_sysfs_param_show_func(inflight_map_req);
+static ssize_t inflight_map_req_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+ int val;
+
+ if (!hpb)
+ return -ENODEV;
+
+ if (!hpb->is_hcm)
+ return -EOPNOTSUPP;
+
+ if (kstrtouint(buf, 0, &val))
+ return -EINVAL;
+
+ if (val <= 0 || val > hpb->sdev_ufs_lu->queue_depth - 1)
+ return -EINVAL;
+
+ hpb->params.inflight_map_req = val;
+
+ return count;
+}
+static DEVICE_ATTR_RW(inflight_map_req);
+
+static void ufshpb_hcm_param_init(struct ufshpb_lu *hpb)
+{
+ hpb->params.activation_thld = ACTIVATION_THRESHOLD;
+ hpb->params.normalization_factor = 1;
+ hpb->params.eviction_thld_enter = (ACTIVATION_THRESHOLD << 5);
+ hpb->params.eviction_thld_exit = (ACTIVATION_THRESHOLD << 4);
+ hpb->params.read_timeout_ms = READ_TO_MS;
+ hpb->params.read_timeout_expiries = READ_TO_EXPIRIES;
+ hpb->params.timeout_polling_interval_ms = POLLING_INTERVAL_MS;
+ hpb->params.inflight_map_req = THROTTLE_MAP_REQ_DEFAULT;
+}
+
+static struct attribute *hpb_dev_param_attrs[] = {
+ &dev_attr_requeue_timeout_ms.attr,
+ &dev_attr_activation_thld.attr,
+ &dev_attr_normalization_factor.attr,
+ &dev_attr_eviction_thld_enter.attr,
+ &dev_attr_eviction_thld_exit.attr,
+ &dev_attr_read_timeout_ms.attr,
+ &dev_attr_read_timeout_expiries.attr,
+ &dev_attr_timeout_polling_interval_ms.attr,
+ &dev_attr_inflight_map_req.attr,
+ NULL,
+};
+
+struct attribute_group ufs_sysfs_hpb_param_group = {
+ .name = "hpb_params",
+ .attrs = hpb_dev_param_attrs,
+};
+
+static int ufshpb_pre_req_mempool_init(struct ufshpb_lu *hpb)
+{
+ struct ufshpb_req *pre_req = NULL, *t;
+ int qd = hpb->sdev_ufs_lu->queue_depth / 2;
+ int i;
+
+ INIT_LIST_HEAD(&hpb->lh_pre_req_free);
+
+ hpb->pre_req = kcalloc(qd, sizeof(struct ufshpb_req), GFP_KERNEL);
+ hpb->throttle_pre_req = qd;
+ hpb->num_inflight_pre_req = 0;
+
+ if (!hpb->pre_req)
+ goto release_mem;
+
+ for (i = 0; i < qd; i++) {
+ pre_req = hpb->pre_req + i;
+ INIT_LIST_HEAD(&pre_req->list_req);
+ pre_req->req = NULL;
+
+ pre_req->bio = bio_alloc(GFP_KERNEL, 1);
+ if (!pre_req->bio)
+ goto release_mem;
+
+ pre_req->wb.m_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!pre_req->wb.m_page) {
+ bio_put(pre_req->bio);
+ goto release_mem;
+ }
+
+ list_add_tail(&pre_req->list_req, &hpb->lh_pre_req_free);
+ }
+
+ return 0;
+release_mem:
+ list_for_each_entry_safe(pre_req, t, &hpb->lh_pre_req_free, list_req) {
+ list_del_init(&pre_req->list_req);
+ bio_put(pre_req->bio);
+ __free_page(pre_req->wb.m_page);
+ }
+
+ kfree(hpb->pre_req);
+ return -ENOMEM;
+}
+
+static void ufshpb_pre_req_mempool_destroy(struct ufshpb_lu *hpb)
+{
+ struct ufshpb_req *pre_req = NULL;
+ int i;
+
+ for (i = 0; i < hpb->throttle_pre_req; i++) {
+ pre_req = hpb->pre_req + i;
+ bio_put(hpb->pre_req[i].bio);
+ if (!pre_req->wb.m_page)
+ __free_page(hpb->pre_req[i].wb.m_page);
+ list_del_init(&pre_req->list_req);
+ }
+
+ kfree(hpb->pre_req);
+}
+
+static void ufshpb_stat_init(struct ufshpb_lu *hpb)
+{
+ hpb->stats.hit_cnt = 0;
+ hpb->stats.miss_cnt = 0;
+ hpb->stats.rb_noti_cnt = 0;
+ hpb->stats.rb_active_cnt = 0;
+ hpb->stats.rb_inactive_cnt = 0;
+ hpb->stats.map_req_cnt = 0;
+ hpb->stats.umap_req_cnt = 0;
+}
+
+static void ufshpb_param_init(struct ufshpb_lu *hpb)
+{
+ hpb->params.requeue_timeout_ms = HPB_REQUEUE_TIME_MS;
+ if (hpb->is_hcm)
+ ufshpb_hcm_param_init(hpb);
+}
+
+static int ufshpb_lu_hpb_init(struct ufs_hba *hba, struct ufshpb_lu *hpb)
+{
+ int ret;
+
+ spin_lock_init(&hpb->rgn_state_lock);
+ spin_lock_init(&hpb->rsp_list_lock);
+ spin_lock_init(&hpb->param_lock);
+
+ INIT_LIST_HEAD(&hpb->lru_info.lh_lru_rgn);
+ INIT_LIST_HEAD(&hpb->lh_act_srgn);
+ INIT_LIST_HEAD(&hpb->lh_inact_rgn);
+ INIT_LIST_HEAD(&hpb->list_hpb_lu);
+
+ INIT_WORK(&hpb->map_work, ufshpb_map_work_handler);
+ if (hpb->is_hcm) {
+ INIT_WORK(&hpb->ufshpb_normalization_work,
+ ufshpb_normalization_work_handler);
+ INIT_DELAYED_WORK(&hpb->ufshpb_read_to_work,
+ ufshpb_read_to_handler);
+ }
+
+ hpb->map_req_cache = kmem_cache_create("ufshpb_req_cache",
+ sizeof(struct ufshpb_req), 0, 0, NULL);
+ if (!hpb->map_req_cache) {
+ dev_err(hba->dev, "ufshpb(%d) ufshpb_req_cache create fail",
+ hpb->lun);
+ return -ENOMEM;
+ }
+
+ hpb->m_page_cache = kmem_cache_create("ufshpb_m_page_cache",
+ sizeof(struct page *) * hpb->pages_per_srgn,
+ 0, 0, NULL);
+ if (!hpb->m_page_cache) {
+ dev_err(hba->dev, "ufshpb(%d) ufshpb_m_page_cache create fail",
+ hpb->lun);
+ ret = -ENOMEM;
+ goto release_req_cache;
+ }
+
+ ret = ufshpb_pre_req_mempool_init(hpb);
+ if (ret) {
+ dev_err(hba->dev, "ufshpb(%d) pre_req_mempool init fail",
+ hpb->lun);
+ goto release_m_page_cache;
+ }
+
+ ret = ufshpb_alloc_region_tbl(hba, hpb);
+ if (ret)
+ goto release_pre_req_mempool;
+
+ ufshpb_stat_init(hpb);
+ ufshpb_param_init(hpb);
+
+ if (hpb->is_hcm) {
+ unsigned int poll;
+
+ poll = hpb->params.timeout_polling_interval_ms;
+ schedule_delayed_work(&hpb->ufshpb_read_to_work,
+ msecs_to_jiffies(poll));
+ }
+
+ return 0;
+
+release_pre_req_mempool:
+ ufshpb_pre_req_mempool_destroy(hpb);
+release_m_page_cache:
+ kmem_cache_destroy(hpb->m_page_cache);
+release_req_cache:
+ kmem_cache_destroy(hpb->map_req_cache);
+ return ret;
+}
+
+static struct ufshpb_lu *
+ufshpb_alloc_hpb_lu(struct ufs_hba *hba, struct scsi_device *sdev,
+ struct ufshpb_dev_info *hpb_dev_info,
+ struct ufshpb_lu_info *hpb_lu_info)
+{
+ struct ufshpb_lu *hpb;
+ int ret;
+
+ hpb = kzalloc(sizeof(struct ufshpb_lu), GFP_KERNEL);
+ if (!hpb)
+ return NULL;
+
+ hpb->lun = sdev->lun;
+ hpb->sdev_ufs_lu = sdev;
+
+ ufshpb_lu_parameter_init(hba, hpb, hpb_dev_info, hpb_lu_info);
+
+ ret = ufshpb_lu_hpb_init(hba, hpb);
+ if (ret) {
+ dev_err(hba->dev, "hpb lu init failed. ret %d", ret);
+ goto release_hpb;
+ }
+
+ sdev->hostdata = hpb;
+ return hpb;
+
+release_hpb:
+ kfree(hpb);
+ return NULL;
+}
+
+static void ufshpb_discard_rsp_lists(struct ufshpb_lu *hpb)
+{
+ struct ufshpb_region *rgn, *next_rgn;
+ struct ufshpb_subregion *srgn, *next_srgn;
+ unsigned long flags;
+
+ /*
+ * If the device reset occurred, the remaining HPB region information
+ * may be stale. Therefore, by discarding the lists of HPB response
+ * that remained after reset, we prevent unnecessary work.
+ */
+ spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+ list_for_each_entry_safe(rgn, next_rgn, &hpb->lh_inact_rgn,
+ list_inact_rgn)
+ list_del_init(&rgn->list_inact_rgn);
+
+ list_for_each_entry_safe(srgn, next_srgn, &hpb->lh_act_srgn,
+ list_act_srgn)
+ list_del_init(&srgn->list_act_srgn);
+ spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
+}
+
+static void ufshpb_cancel_jobs(struct ufshpb_lu *hpb)
+{
+ if (hpb->is_hcm) {
+ cancel_delayed_work_sync(&hpb->ufshpb_read_to_work);
+ cancel_work_sync(&hpb->ufshpb_normalization_work);
+ }
+ cancel_work_sync(&hpb->map_work);
+}
+
+static bool ufshpb_check_hpb_reset_query(struct ufs_hba *hba)
+{
+ int err = 0;
+ bool flag_res = true;
+ int try;
+
+ /* wait for the device to complete HPB reset query */
+ for (try = 0; try < HPB_RESET_REQ_RETRIES; try++) {
+ dev_dbg(hba->dev,
+ "%s start flag reset polling %d times\n",
+ __func__, try);
+
+ /* Poll fHpbReset flag to be cleared */
+ err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,
+ QUERY_FLAG_IDN_HPB_RESET, 0, &flag_res);
+
+ if (err) {
+ dev_err(hba->dev,
+ "%s reading fHpbReset flag failed with error %d\n",
+ __func__, err);
+ return flag_res;
+ }
+
+ if (!flag_res)
+ goto out;
+
+ usleep_range(1000, 1100);
+ }
+ if (flag_res) {
+ dev_err(hba->dev,
+ "%s fHpbReset was not cleared by the device\n",
+ __func__);
+ }
+out:
+ return flag_res;
+}
+
+void ufshpb_reset(struct ufs_hba *hba)
+{
+ struct ufshpb_lu *hpb;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, hba->host) {
+ hpb = ufshpb_get_hpb_data(sdev);
+ if (!hpb)
+ continue;
+
+ if (ufshpb_get_state(hpb) != HPB_RESET)
+ continue;
+
+ ufshpb_set_state(hpb, HPB_PRESENT);
+ }
+}
+
+void ufshpb_reset_host(struct ufs_hba *hba)
+{
+ struct ufshpb_lu *hpb;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, hba->host) {
+ hpb = ufshpb_get_hpb_data(sdev);
+ if (!hpb)
+ continue;
+
+ if (ufshpb_get_state(hpb) != HPB_PRESENT)
+ continue;
+ ufshpb_set_state(hpb, HPB_RESET);
+ ufshpb_cancel_jobs(hpb);
+ ufshpb_discard_rsp_lists(hpb);
+ }
+}
+
+void ufshpb_suspend(struct ufs_hba *hba)
+{
+ struct ufshpb_lu *hpb;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, hba->host) {
+ hpb = ufshpb_get_hpb_data(sdev);
+ if (!hpb)
+ continue;
+
+ if (ufshpb_get_state(hpb) != HPB_PRESENT)
+ continue;
+ ufshpb_set_state(hpb, HPB_SUSPEND);
+ ufshpb_cancel_jobs(hpb);
+ }
+}
+
+void ufshpb_resume(struct ufs_hba *hba)
+{
+ struct ufshpb_lu *hpb;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, hba->host) {
+ hpb = ufshpb_get_hpb_data(sdev);
+ if (!hpb)
+ continue;
+
+ if ((ufshpb_get_state(hpb) != HPB_PRESENT) &&
+ (ufshpb_get_state(hpb) != HPB_SUSPEND))
+ continue;
+ ufshpb_set_state(hpb, HPB_PRESENT);
+ ufshpb_kick_map_work(hpb);
+ if (hpb->is_hcm) {
+ unsigned int poll =
+ hpb->params.timeout_polling_interval_ms;
+
+ schedule_delayed_work(&hpb->ufshpb_read_to_work,
+ msecs_to_jiffies(poll));
+ }
+ }
+}
+
+static int ufshpb_get_lu_info(struct ufs_hba *hba, int lun,
+ struct ufshpb_lu_info *hpb_lu_info)
+{
+ u16 max_active_rgns;
+ u8 lu_enable;
+ int size;
+ int ret;
+ char desc_buf[QUERY_DESC_MAX_SIZE];
+
+ ufshcd_map_desc_id_to_length(hba, QUERY_DESC_IDN_UNIT, &size);
+
+ pm_runtime_get_sync(hba->dev);
+ ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
+ QUERY_DESC_IDN_UNIT, lun, 0,
+ desc_buf, &size);
+ pm_runtime_put_sync(hba->dev);
+
+ if (ret) {
+ dev_err(hba->dev,
+ "%s: idn: %d lun: %d query request failed",
+ __func__, QUERY_DESC_IDN_UNIT, lun);
+ return ret;
+ }
+
+ lu_enable = desc_buf[UNIT_DESC_PARAM_LU_ENABLE];
+ if (lu_enable != LU_ENABLED_HPB_FUNC)
+ return -ENODEV;
+
+ max_active_rgns = get_unaligned_be16(
+ desc_buf + UNIT_DESC_PARAM_HPB_LU_MAX_ACTIVE_RGNS);
+ if (!max_active_rgns) {
+ dev_err(hba->dev,
+ "lun %d wrong number of max active regions\n", lun);
+ return -ENODEV;
+ }
+
+ hpb_lu_info->num_blocks = get_unaligned_be64(
+ desc_buf + UNIT_DESC_PARAM_LOGICAL_BLK_COUNT);
+ hpb_lu_info->pinned_start = get_unaligned_be16(
+ desc_buf + UNIT_DESC_PARAM_HPB_PIN_RGN_START_OFF);
+ hpb_lu_info->num_pinned = get_unaligned_be16(
+ desc_buf + UNIT_DESC_PARAM_HPB_NUM_PIN_RGNS);
+ hpb_lu_info->max_active_rgns = max_active_rgns;
+
+ return 0;
+}
+
+void ufshpb_destroy_lu(struct ufs_hba *hba, struct scsi_device *sdev)
+{
+ struct ufshpb_lu *hpb = ufshpb_get_hpb_data(sdev);
+
+ if (!hpb)
+ return;
+
+ ufshpb_set_state(hpb, HPB_FAILED);
+
+ sdev = hpb->sdev_ufs_lu;
+ sdev->hostdata = NULL;
+
+ ufshpb_cancel_jobs(hpb);
+
+ ufshpb_pre_req_mempool_destroy(hpb);
+ ufshpb_destroy_region_tbl(hpb);
+
+ kmem_cache_destroy(hpb->map_req_cache);
+ kmem_cache_destroy(hpb->m_page_cache);
+
+ list_del_init(&hpb->list_hpb_lu);
+
+ kfree(hpb);
+}
+
+static void ufshpb_hpb_lu_prepared(struct ufs_hba *hba)
+{
+ int pool_size;
+ struct ufshpb_lu *hpb;
+ struct scsi_device *sdev;
+ bool init_success;
+
+ if (tot_active_srgn_pages == 0) {
+ ufshpb_remove(hba);
+ return;
+ }
+
+ init_success = !ufshpb_check_hpb_reset_query(hba);
+
+ pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * 1024) / PAGE_SIZE;
+ if (pool_size > tot_active_srgn_pages) {
+ mempool_resize(ufshpb_mctx_pool, tot_active_srgn_pages);
+ mempool_resize(ufshpb_page_pool, tot_active_srgn_pages);
+ }
+
+ shost_for_each_device(sdev, hba->host) {
+ hpb = ufshpb_get_hpb_data(sdev);
+ if (!hpb)
+ continue;
+
+ if (init_success) {
+ ufshpb_set_state(hpb, HPB_PRESENT);
+ if ((hpb->lu_pinned_end - hpb->lu_pinned_start) > 0)
+ queue_work(ufshpb_wq, &hpb->map_work);
+ if (!hpb->is_hcm)
+ ufshpb_issue_umap_all_req(hpb);
+ } else {
+ dev_err(hba->dev, "destroy HPB lu %d\n", hpb->lun);
+ ufshpb_destroy_lu(hba, sdev);
+ }
+ }
+
+ if (!init_success)
+ ufshpb_remove(hba);
+}
+
+void ufshpb_init_hpb_lu(struct ufs_hba *hba, struct scsi_device *sdev)
+{
+ struct ufshpb_lu *hpb;
+ int ret;
+ struct ufshpb_lu_info hpb_lu_info = { 0 };
+ int lun = sdev->lun;
+
+ if (lun >= hba->dev_info.max_lu_supported)
+ goto out;
+
+ ret = ufshpb_get_lu_info(hba, lun, &hpb_lu_info);
+ if (ret)
+ goto out;
+
+ hpb = ufshpb_alloc_hpb_lu(hba, sdev, &hba->ufshpb_dev,
+ &hpb_lu_info);
+ if (!hpb)
+ goto out;
+
+ tot_active_srgn_pages += hpb_lu_info.max_active_rgns *
+ hpb->srgns_per_rgn * hpb->pages_per_srgn;
+
+out:
+ /* All LUs are initialized */
+ if (atomic_dec_and_test(&hba->ufshpb_dev.slave_conf_cnt))
+ ufshpb_hpb_lu_prepared(hba);
+}
+
+static int ufshpb_init_mem_wq(struct ufs_hba *hba)
+{
+ int ret;
+ unsigned int pool_size;
+
+ ufshpb_mctx_cache = kmem_cache_create("ufshpb_mctx_cache",
+ sizeof(struct ufshpb_map_ctx),
+ 0, 0, NULL);
+ if (!ufshpb_mctx_cache) {
+ dev_err(hba->dev, "ufshpb: cannot init mctx cache\n");
+ return -ENOMEM;
+ }
+
+ pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * 1024) / PAGE_SIZE;
+ dev_info(hba->dev, "%s:%d ufshpb_host_map_kbytes %u pool_size %u\n",
+ __func__, __LINE__, ufshpb_host_map_kbytes, pool_size);
+
+ ufshpb_mctx_pool = mempool_create_slab_pool(pool_size,
+ ufshpb_mctx_cache);
+ if (!ufshpb_mctx_pool) {
+ dev_err(hba->dev, "ufshpb: cannot init mctx pool\n");
+ ret = -ENOMEM;
+ goto release_mctx_cache;
+ }
+
+ ufshpb_page_pool = mempool_create_page_pool(pool_size, 0);
+ if (!ufshpb_page_pool) {
+ dev_err(hba->dev, "ufshpb: cannot init page pool\n");
+ ret = -ENOMEM;
+ goto release_mctx_pool;
+ }
+
+ ufshpb_wq = alloc_workqueue("ufshpb-wq",
+ WQ_UNBOUND | WQ_MEM_RECLAIM, 0);
+ if (!ufshpb_wq) {
+ dev_err(hba->dev, "ufshpb: alloc workqueue failed\n");
+ ret = -ENOMEM;
+ goto release_page_pool;
+ }
+
+ return 0;
+
+release_page_pool:
+ mempool_destroy(ufshpb_page_pool);
+release_mctx_pool:
+ mempool_destroy(ufshpb_mctx_pool);
+release_mctx_cache:
+ kmem_cache_destroy(ufshpb_mctx_cache);
+ return ret;
+}
+
+void ufshpb_get_geo_info(struct ufs_hba *hba, u8 *geo_buf)
+{
+ struct ufshpb_dev_info *hpb_info = &hba->ufshpb_dev;
+ int max_active_rgns = 0;
+ int hpb_num_lu;
+
+ hpb_num_lu = geo_buf[GEOMETRY_DESC_PARAM_HPB_NUMBER_LU];
+ if (hpb_num_lu == 0) {
+ dev_err(hba->dev, "No HPB LU supported\n");
+ hpb_info->hpb_disabled = true;
+ return;
+ }
+
+ hpb_info->rgn_size = geo_buf[GEOMETRY_DESC_PARAM_HPB_REGION_SIZE];
+ hpb_info->srgn_size = geo_buf[GEOMETRY_DESC_PARAM_HPB_SUBREGION_SIZE];
+ max_active_rgns = get_unaligned_be16(geo_buf +
+ GEOMETRY_DESC_PARAM_HPB_MAX_ACTIVE_REGS);
+
+ if (hpb_info->rgn_size == 0 || hpb_info->srgn_size == 0 ||
+ max_active_rgns == 0) {
+ dev_err(hba->dev, "No HPB supported device\n");
+ hpb_info->hpb_disabled = true;
+ return;
+ }
+}
+
+void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
+{
+ struct ufshpb_dev_info *hpb_dev_info = &hba->ufshpb_dev;
+ int version, ret;
+ u32 max_hpb_single_cmd = HPB_MULTI_CHUNK_LOW;
+
+ hpb_dev_info->control_mode = desc_buf[DEVICE_DESC_PARAM_HPB_CONTROL];
+
+ version = get_unaligned_be16(desc_buf + DEVICE_DESC_PARAM_HPB_VER);
+ if ((version != HPB_SUPPORT_VERSION) &&
+ (version != HPB_SUPPORT_LEGACY_VERSION)) {
+ dev_err(hba->dev, "%s: HPB %x version is not supported.\n",
+ __func__, version);
+ hpb_dev_info->hpb_disabled = true;
+ return;
+ }
+
+ if (version == HPB_SUPPORT_LEGACY_VERSION)
+ hpb_dev_info->is_legacy = true;
+
+ pm_runtime_get_sync(hba->dev);
+ ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_MAX_HPB_SINGLE_CMD, 0, 0, &max_hpb_single_cmd);
+ pm_runtime_put_sync(hba->dev);
+
+ if (ret)
+ dev_err(hba->dev, "%s: idn: read max size of single hpb cmd query request failed",
+ __func__);
+ hpb_dev_info->max_hpb_single_cmd = max_hpb_single_cmd;
+
+ /*
+ * Get the number of user logical unit to check whether all
+ * scsi_device finish initialization
+ */
+ hpb_dev_info->num_lu = desc_buf[DEVICE_DESC_PARAM_NUM_LU];
+}
+
+void ufshpb_init(struct ufs_hba *hba)
+{
+ struct ufshpb_dev_info *hpb_dev_info = &hba->ufshpb_dev;
+ int try;
+ int ret;
+
+ if (!ufshpb_is_allowed(hba) || !hba->dev_info.hpb_enabled)
+ return;
+
+ if (ufshpb_init_mem_wq(hba)) {
+ hpb_dev_info->hpb_disabled = true;
+ return;
+ }
+
+ atomic_set(&hpb_dev_info->slave_conf_cnt, hpb_dev_info->num_lu);
+ tot_active_srgn_pages = 0;
+ /* issue HPB reset query */
+ for (try = 0; try < HPB_RESET_REQ_RETRIES; try++) {
+ ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
+ QUERY_FLAG_IDN_HPB_RESET, 0, NULL);
+ if (!ret)
+ break;
+ }
+}
+
+void ufshpb_remove(struct ufs_hba *hba)
+{
+ mempool_destroy(ufshpb_page_pool);
+ mempool_destroy(ufshpb_mctx_pool);
+ kmem_cache_destroy(ufshpb_mctx_cache);
+
+ destroy_workqueue(ufshpb_wq);
+}
+
+module_param(ufshpb_host_map_kbytes, uint, 0644);
+MODULE_PARM_DESC(ufshpb_host_map_kbytes,
+ "ufshpb host mapping memory kilo-bytes for ufshpb memory-pool");
diff --git a/drivers/scsi/ufs/ufshpb.h b/drivers/scsi/ufs/ufshpb.h
new file mode 100644
index 000000000000..a79e07398970
--- /dev/null
+++ b/drivers/scsi/ufs/ufshpb.h
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Universal Flash Storage Host Performance Booster
+ *
+ * Copyright (C) 2017-2021 Samsung Electronics Co., Ltd.
+ *
+ * Authors:
+ * Yongmyung Lee <ymhungry.lee@samsung.com>
+ * Jinyoung Choi <j-young.choi@samsung.com>
+ */
+
+#ifndef _UFSHPB_H_
+#define _UFSHPB_H_
+
+/* hpb response UPIU macro */
+#define HPB_RSP_NONE 0x0
+#define HPB_RSP_REQ_REGION_UPDATE 0x1
+#define HPB_RSP_DEV_RESET 0x2
+#define MAX_ACTIVE_NUM 2
+#define MAX_INACTIVE_NUM 2
+#define DEV_DATA_SEG_LEN 0x14
+#define DEV_SENSE_SEG_LEN 0x12
+#define DEV_DES_TYPE 0x80
+#define DEV_ADDITIONAL_LEN 0x10
+
+/* hpb map & entries macro */
+#define HPB_RGN_SIZE_UNIT 512
+#define HPB_ENTRY_BLOCK_SIZE 4096
+#define HPB_ENTRY_SIZE 0x8
+#define PINNED_NOT_SET U32_MAX
+
+/* hpb support chunk size */
+#define HPB_LEGACY_CHUNK_HIGH 1
+#define HPB_MULTI_CHUNK_LOW 7
+#define HPB_MULTI_CHUNK_HIGH 255
+
+/* hpb vender defined opcode */
+#define UFSHPB_READ 0xF8
+#define UFSHPB_READ_BUFFER 0xF9
+#define UFSHPB_READ_BUFFER_ID 0x01
+#define UFSHPB_WRITE_BUFFER 0xFA
+#define UFSHPB_WRITE_BUFFER_INACT_SINGLE_ID 0x01
+#define UFSHPB_WRITE_BUFFER_PREFETCH_ID 0x02
+#define UFSHPB_WRITE_BUFFER_INACT_ALL_ID 0x03
+#define HPB_WRITE_BUFFER_CMD_LENGTH 10
+#define MAX_HPB_READ_ID 0x7F
+#define HPB_READ_BUFFER_CMD_LENGTH 10
+#define LU_ENABLED_HPB_FUNC 0x02
+
+#define HPB_RESET_REQ_RETRIES 10
+#define HPB_MAP_REQ_RETRIES 5
+#define HPB_REQUEUE_TIME_MS 0
+
+#define HPB_SUPPORT_VERSION 0x200
+#define HPB_SUPPORT_LEGACY_VERSION 0x100
+
+enum UFSHPB_MODE {
+ HPB_HOST_CONTROL,
+ HPB_DEVICE_CONTROL,
+};
+
+enum UFSHPB_STATE {
+ HPB_INIT = 0,
+ HPB_PRESENT = 1,
+ HPB_SUSPEND,
+ HPB_FAILED,
+ HPB_RESET,
+};
+
+enum HPB_RGN_STATE {
+ HPB_RGN_INACTIVE,
+ HPB_RGN_ACTIVE,
+ /* pinned regions are always active */
+ HPB_RGN_PINNED,
+};
+
+enum HPB_SRGN_STATE {
+ HPB_SRGN_UNUSED,
+ HPB_SRGN_INVALID,
+ HPB_SRGN_VALID,
+ HPB_SRGN_ISSUED,
+};
+
+/**
+ * struct ufshpb_lu_info - UFSHPB logical unit related info
+ * @num_blocks: the number of logical block
+ * @pinned_start: the start region number of pinned region
+ * @num_pinned: the number of pinned regions
+ * @max_active_rgns: maximum number of active regions
+ */
+struct ufshpb_lu_info {
+ int num_blocks;
+ int pinned_start;
+ int num_pinned;
+ int max_active_rgns;
+};
+
+struct ufshpb_map_ctx {
+ struct page **m_page;
+ unsigned long *ppn_dirty;
+};
+
+struct ufshpb_subregion {
+ struct ufshpb_map_ctx *mctx;
+ enum HPB_SRGN_STATE srgn_state;
+ int rgn_idx;
+ int srgn_idx;
+ bool is_last;
+
+ /* subregion reads - for host mode */
+ unsigned int reads;
+
+ /* below information is used by rsp_list */
+ struct list_head list_act_srgn;
+};
+
+struct ufshpb_region {
+ struct ufshpb_lu *hpb;
+ struct ufshpb_subregion *srgn_tbl;
+ enum HPB_RGN_STATE rgn_state;
+ int rgn_idx;
+ int srgn_cnt;
+
+ /* below information is used by rsp_list */
+ struct list_head list_inact_rgn;
+
+ /* below information is used by lru */
+ struct list_head list_lru_rgn;
+ unsigned long rgn_flags;
+#define RGN_FLAG_DIRTY 0
+#define RGN_FLAG_UPDATE 1
+
+ /* region reads - for host mode */
+ spinlock_t rgn_lock;
+ unsigned int reads;
+ /* region "cold" timer - for host mode */
+ ktime_t read_timeout;
+ unsigned int read_timeout_expiries;
+ struct list_head list_expired_rgn;
+};
+
+#define for_each_sub_region(rgn, i, srgn) \
+ for ((i) = 0; \
+ ((i) < (rgn)->srgn_cnt) && ((srgn) = &(rgn)->srgn_tbl[i]); \
+ (i)++)
+
+/**
+ * struct ufshpb_req - HPB related request structure (write/read buffer)
+ * @req: block layer request structure
+ * @bio: bio for this request
+ * @hpb: ufshpb_lu structure that related to
+ * @list_req: ufshpb_req mempool list
+ * @sense: store its sense data
+ * @mctx: L2P map information
+ * @rgn_idx: target region index
+ * @srgn_idx: target sub-region index
+ * @lun: target logical unit number
+ * @m_page: L2P map information data for pre-request
+ * @len: length of host-side cached L2P map in m_page
+ * @lpn: start LPN of L2P map in m_page
+ */
+struct ufshpb_req {
+ struct request *req;
+ struct bio *bio;
+ struct ufshpb_lu *hpb;
+ struct list_head list_req;
+ union {
+ struct {
+ struct ufshpb_map_ctx *mctx;
+ unsigned int rgn_idx;
+ unsigned int srgn_idx;
+ unsigned int lun;
+ } rb;
+ struct {
+ struct page *m_page;
+ unsigned int len;
+ unsigned long lpn;
+ } wb;
+ };
+};
+
+struct victim_select_info {
+ struct list_head lh_lru_rgn; /* LRU list of regions */
+ int max_lru_active_cnt; /* supported hpb #region - pinned #region */
+ atomic_t active_cnt;
+};
+
+/**
+ * ufshpb_params - ufs hpb parameters
+ * @requeue_timeout_ms - requeue threshold of wb command (0x2)
+ * @activation_thld - min reads [IOs] to activate/update a region
+ * @normalization_factor - shift right the region's reads
+ * @eviction_thld_enter - min reads [IOs] for the entering region in eviction
+ * @eviction_thld_exit - max reads [IOs] for the exiting region in eviction
+ * @read_timeout_ms - timeout [ms] from the last read IO to the region
+ * @read_timeout_expiries - amount of allowable timeout expireis
+ * @timeout_polling_interval_ms - frequency in which timeouts are checked
+ * @inflight_map_req - number of inflight map requests
+ */
+struct ufshpb_params {
+ unsigned int requeue_timeout_ms;
+ unsigned int activation_thld;
+ unsigned int normalization_factor;
+ unsigned int eviction_thld_enter;
+ unsigned int eviction_thld_exit;
+ unsigned int read_timeout_ms;
+ unsigned int read_timeout_expiries;
+ unsigned int timeout_polling_interval_ms;
+ unsigned int inflight_map_req;
+};
+
+struct ufshpb_stats {
+ u64 hit_cnt;
+ u64 miss_cnt;
+ u64 rb_noti_cnt;
+ u64 rb_active_cnt;
+ u64 rb_inactive_cnt;
+ u64 map_req_cnt;
+ u64 pre_req_cnt;
+ u64 umap_req_cnt;
+};
+
+struct ufshpb_lu {
+ int lun;
+ struct scsi_device *sdev_ufs_lu;
+
+ spinlock_t rgn_state_lock; /* for protect rgn/srgn state */
+ struct ufshpb_region *rgn_tbl;
+
+ atomic_t hpb_state;
+
+ spinlock_t rsp_list_lock;
+ struct list_head lh_act_srgn; /* hold rsp_list_lock */
+ struct list_head lh_inact_rgn; /* hold rsp_list_lock */
+
+ /* pre request information */
+ struct ufshpb_req *pre_req;
+ int num_inflight_pre_req;
+ int throttle_pre_req;
+ int num_inflight_map_req; /* hold param_lock */
+ spinlock_t param_lock;
+
+ struct list_head lh_pre_req_free;
+ int cur_read_id;
+ int pre_req_min_tr_len;
+ int pre_req_max_tr_len;
+
+ /* cached L2P map management worker */
+ struct work_struct map_work;
+
+ /* for selecting victim */
+ struct victim_select_info lru_info;
+ struct work_struct ufshpb_normalization_work;
+ struct delayed_work ufshpb_read_to_work;
+ unsigned long work_data_bits;
+#define TIMEOUT_WORK_RUNNING 0
+
+ /* pinned region information */
+ u32 lu_pinned_start;
+ u32 lu_pinned_end;
+
+ /* HPB related configuration */
+ u32 rgns_per_lu;
+ u32 srgns_per_lu;
+ u32 last_srgn_entries;
+ int srgns_per_rgn;
+ u32 srgn_mem_size;
+ u32 entries_per_rgn_mask;
+ u32 entries_per_rgn_shift;
+ u32 entries_per_srgn;
+ u32 entries_per_srgn_mask;
+ u32 entries_per_srgn_shift;
+ u32 pages_per_srgn;
+
+ bool is_hcm;
+
+ struct ufshpb_stats stats;
+ struct ufshpb_params params;
+
+ struct kmem_cache *map_req_cache;
+ struct kmem_cache *m_page_cache;
+
+ struct list_head list_hpb_lu;
+};
+
+struct ufs_hba;
+struct ufshcd_lrb;
+
+#ifndef CONFIG_SCSI_UFS_HPB
+static int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { return 0; }
+static void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) {}
+static void ufshpb_resume(struct ufs_hba *hba) {}
+static void ufshpb_suspend(struct ufs_hba *hba) {}
+static void ufshpb_reset(struct ufs_hba *hba) {}
+static void ufshpb_reset_host(struct ufs_hba *hba) {}
+static void ufshpb_init(struct ufs_hba *hba) {}
+static void ufshpb_init_hpb_lu(struct ufs_hba *hba, struct scsi_device *sdev) {}
+static void ufshpb_destroy_lu(struct ufs_hba *hba, struct scsi_device *sdev) {}
+static void ufshpb_remove(struct ufs_hba *hba) {}
+static bool ufshpb_is_allowed(struct ufs_hba *hba) { return false; }
+static void ufshpb_get_geo_info(struct ufs_hba *hba, u8 *geo_buf) {}
+static void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf) {}
+static bool ufshpb_is_legacy(struct ufs_hba *hba) { return false; }
+#else
+int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp);
+void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp);
+void ufshpb_resume(struct ufs_hba *hba);
+void ufshpb_suspend(struct ufs_hba *hba);
+void ufshpb_reset(struct ufs_hba *hba);
+void ufshpb_reset_host(struct ufs_hba *hba);
+void ufshpb_init(struct ufs_hba *hba);
+void ufshpb_init_hpb_lu(struct ufs_hba *hba, struct scsi_device *sdev);
+void ufshpb_destroy_lu(struct ufs_hba *hba, struct scsi_device *sdev);
+void ufshpb_remove(struct ufs_hba *hba);
+bool ufshpb_is_allowed(struct ufs_hba *hba);
+void ufshpb_get_geo_info(struct ufs_hba *hba, u8 *geo_buf);
+void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf);
+bool ufshpb_is_legacy(struct ufs_hba *hba);
+extern struct attribute_group ufs_sysfs_hpb_stat_group;
+extern struct attribute_group ufs_sysfs_hpb_param_group;
+#endif
+
+#endif /* End of Header */
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index b0deaf4af5a3..c25ce8f0e0af 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -519,7 +519,7 @@ static void virtio_scsi_init_hdr_pi(struct virtio_device *vdev,
struct virtio_scsi_cmd_req_pi *cmd_pi,
struct scsi_cmnd *sc)
{
- struct request *rq = sc->request;
+ struct request *rq = scsi_cmd_to_rq(sc);
struct blk_integrity *bi;
virtio_scsi_init_hdr(vdev, (struct virtio_scsi_cmd_req *)cmd_pi, sc);
@@ -543,7 +543,7 @@ static void virtio_scsi_init_hdr_pi(struct virtio_device *vdev,
static struct virtio_scsi_vq *virtscsi_pick_vq_mq(struct virtio_scsi *vscsi,
struct scsi_cmnd *sc)
{
- u32 tag = blk_mq_unique_tag(sc->request);
+ u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(sc));
u16 hwq = blk_mq_unique_tag_to_hwq(tag);
return &vscsi->req_vqs[hwq];
diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c
index edc8a139a60d..6f10a43510fb 100644
--- a/drivers/scsi/wd719x.c
+++ b/drivers/scsi/wd719x.c
@@ -466,14 +466,16 @@ static int wd719x_abort(struct scsi_cmnd *cmd)
unsigned long flags;
struct wd719x_scb *scb = scsi_cmd_priv(cmd);
struct wd719x *wd = shost_priv(cmd->device->host);
+ struct device *dev = &wd->pdev->dev;
- dev_info(&wd->pdev->dev, "abort command, tag: %x\n", cmd->tag);
+ dev_info(dev, "abort command, tag: %x\n", scsi_cmd_to_rq(cmd)->tag);
- action = /*cmd->tag ? WD719X_CMD_ABORT_TAG : */WD719X_CMD_ABORT;
+ action = WD719X_CMD_ABORT;
spin_lock_irqsave(wd->sh->host_lock, flags);
result = wd719x_direct_cmd(wd, action, cmd->device->id,
- cmd->device->lun, cmd->tag, scb->phys, 0);
+ cmd->device->lun, scsi_cmd_to_rq(cmd)->tag,
+ scb->phys, 0);
wd719x_finish_cmd(scb, DID_ABORT);
spin_unlock_irqrestore(wd->sh->host_lock, flags);
if (result)
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
index ec9d399fbbd8..0204e314b482 100644
--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -212,7 +212,7 @@ static int scsifront_do_request(struct vscsifrnt_info *info,
memcpy(ring_req->cmnd, sc->cmnd, sc->cmd_len);
ring_req->sc_data_direction = (uint8_t)sc->sc_data_direction;
- ring_req->timeout_per_command = sc->request->timeout / HZ;
+ ring_req->timeout_per_command = scsi_cmd_to_rq(sc)->timeout / HZ;
for (i = 0; i < (shadow->nr_segments & ~VSCSIIF_SG_GRANT); i++)
ring_req->seg[i] = shadow->seg[i];
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 7eac76cccc4c..f1e5cf8a17d9 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -168,15 +168,13 @@ static const struct parisc_device_id zalon_tbl[] __initconst = {
MODULE_DEVICE_TABLE(parisc, zalon_tbl);
-static int __exit zalon_remove(struct parisc_device *dev)
+static void __exit zalon_remove(struct parisc_device *dev)
{
struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
scsi_remove_host(host);
ncr53c8xx_release(host);
free_irq(dev->irq, host);
-
- return 0;
}
static struct parisc_driver zalon_driver __refdata = {
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index 348836b90605..44324abe21da 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -150,17 +150,13 @@ static int superhyway_device_probe(struct device *dev)
return -ENODEV;
}
-static int superhyway_device_remove(struct device *dev)
+static void superhyway_device_remove(struct device *dev)
{
struct superhyway_device *shyway_dev = to_superhyway_device(dev);
struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
- if (shyway_drv && shyway_drv->remove) {
+ if (shyway_drv->remove)
shyway_drv->remove(shyway_dev);
- return 0;
- }
-
- return -ENODEV;
}
/**
diff --git a/drivers/siox/siox-core.c b/drivers/siox/siox-core.c
index 1794ff0106bc..7c4f32d76966 100644
--- a/drivers/siox/siox-core.c
+++ b/drivers/siox/siox-core.c
@@ -520,7 +520,7 @@ static int siox_probe(struct device *dev)
return sdriver->probe(sdevice);
}
-static int siox_remove(struct device *dev)
+static void siox_remove(struct device *dev)
{
struct siox_driver *sdriver =
container_of(dev->driver, struct siox_driver, driver);
@@ -528,8 +528,6 @@ static int siox_remove(struct device *dev)
if (sdriver->remove)
sdriver->remove(sdevice);
-
- return 0;
}
static void siox_shutdown(struct device *dev)
diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c
index 1d2bc181da05..78480e332ab8 100644
--- a/drivers/slimbus/core.c
+++ b/drivers/slimbus/core.c
@@ -81,7 +81,7 @@ static int slim_device_probe(struct device *dev)
return ret;
}
-static int slim_device_remove(struct device *dev)
+static void slim_device_remove(struct device *dev)
{
struct slim_device *sbdev = to_slim_device(dev);
struct slim_driver *sbdrv;
@@ -91,8 +91,6 @@ static int slim_device_remove(struct device *dev)
if (sbdrv->remove)
sbdrv->remove(sbdev);
}
-
- return 0;
}
static int slim_device_uevent(struct device *dev, struct kobj_uevent_env *env)
diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
index c557ffd0992c..72771e018c42 100644
--- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c
+++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
@@ -37,6 +37,7 @@ struct aspeed_lpc_ctrl {
u32 pnor_size;
u32 pnor_base;
bool fwh2ahb;
+ struct regmap *scu;
};
static struct aspeed_lpc_ctrl *file_aspeed_lpc_ctrl(struct file *file)
@@ -51,7 +52,7 @@ static int aspeed_lpc_ctrl_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long vsize = vma->vm_end - vma->vm_start;
pgprot_t prot = vma->vm_page_prot;
- if (vma->vm_pgoff + vsize > lpc_ctrl->mem_base + lpc_ctrl->mem_size)
+ if (vma->vm_pgoff + vma_pages(vma) > lpc_ctrl->mem_size >> PAGE_SHIFT)
return -EINVAL;
/* ast2400/2500 AHB accesses are not cache coherent */
@@ -183,13 +184,22 @@ static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd,
/*
* Switch to FWH2AHB mode, AST2600 only.
- *
- * The other bits in this register are interrupt status bits
- * that are cleared by writing 1. As we don't want to clear
- * them, set only the bit of interest.
*/
- if (lpc_ctrl->fwh2ahb)
+ if (lpc_ctrl->fwh2ahb) {
+ /*
+ * Enable FWH2AHB in SCU debug control register 2. This
+ * does not turn it on, but makes it available for it
+ * to be configured in HICR6.
+ */
+ regmap_update_bits(lpc_ctrl->scu, 0x0D8, BIT(2), 0);
+
+ /*
+ * The other bits in this register are interrupt status bits
+ * that are cleared by writing 1. As we don't want to clear
+ * them, set only the bit of interest.
+ */
regmap_write(lpc_ctrl->regmap, HICR6, SW_FWH2AHB);
+ }
/*
* Enable LPC FHW cycles. This is required for the host to
@@ -285,6 +295,16 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
return -ENODEV;
}
+ if (of_device_is_compatible(dev->of_node, "aspeed,ast2600-lpc-ctrl")) {
+ lpc_ctrl->fwh2ahb = true;
+
+ lpc_ctrl->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2600-scu");
+ if (IS_ERR(lpc_ctrl->scu)) {
+ dev_err(dev, "couldn't find scu\n");
+ return PTR_ERR(lpc_ctrl->scu);
+ }
+ }
+
lpc_ctrl->clk = devm_clk_get(dev, NULL);
if (IS_ERR(lpc_ctrl->clk)) {
dev_err(dev, "couldn't get clock\n");
@@ -296,9 +316,6 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
return rc;
}
- if (of_device_is_compatible(dev->of_node, "aspeed,ast2600-lpc-ctrl"))
- lpc_ctrl->fwh2ahb = true;
-
lpc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR;
lpc_ctrl->miscdev.name = DEVICE_NAME;
lpc_ctrl->miscdev.fops = &aspeed_lpc_ctrl_fops;
diff --git a/drivers/soc/aspeed/aspeed-p2a-ctrl.c b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
index b60fbeaffcbd..20b5fb2a207c 100644
--- a/drivers/soc/aspeed/aspeed-p2a-ctrl.c
+++ b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
@@ -110,7 +110,7 @@ static int aspeed_p2a_mmap(struct file *file, struct vm_area_struct *vma)
vsize = vma->vm_end - vma->vm_start;
prot = vma->vm_page_prot;
- if (vma->vm_pgoff + vsize > ctrl->mem_base + ctrl->mem_size)
+ if (vma->vm_pgoff + vma_pages(vma) > ctrl->mem_size >> PAGE_SHIFT)
return -EINVAL;
/* ast2400/2500 AHB accesses are not cache coherent */
diff --git a/drivers/soc/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c
index e3215f826d17..1ca140356a08 100644
--- a/drivers/soc/aspeed/aspeed-socinfo.c
+++ b/drivers/soc/aspeed/aspeed-socinfo.c
@@ -26,6 +26,7 @@ static struct {
{ "AST2600", 0x05000303 },
{ "AST2620", 0x05010203 },
{ "AST2605", 0x05030103 },
+ { "AST2625", 0x05030403 },
};
static const char *siliconid_to_name(u32 siliconid)
diff --git a/drivers/soc/mediatek/mt8173-pm-domains.h b/drivers/soc/mediatek/mt8173-pm-domains.h
index 654c717e5467..714fa92575df 100644
--- a/drivers/soc/mediatek/mt8173-pm-domains.h
+++ b/drivers/soc/mediatek/mt8173-pm-domains.h
@@ -71,6 +71,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = {
.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = 0,
+ .caps = MTK_SCPD_DOMAIN_SUPPLY,
},
[MT8173_POWER_DOMAIN_MFG_2D] = {
.name = "mfg_2d",
diff --git a/drivers/soc/mediatek/mt8183-mmsys.h b/drivers/soc/mediatek/mt8183-mmsys.h
index 579dfc8dc8fc..9dee485807c9 100644
--- a/drivers/soc/mediatek/mt8183-mmsys.h
+++ b/drivers/soc/mediatek/mt8183-mmsys.h
@@ -28,25 +28,32 @@
static const struct mtk_mmsys_routes mmsys_mt8183_routing_table[] = {
{
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL_2L0,
- MT8183_DISP_OVL0_MOUT_EN, MT8183_OVL0_MOUT_EN_OVL0_2L
+ MT8183_DISP_OVL0_MOUT_EN, MT8183_OVL0_MOUT_EN_OVL0_2L,
+ MT8183_OVL0_MOUT_EN_OVL0_2L
}, {
DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0,
- MT8183_DISP_OVL0_2L_MOUT_EN, MT8183_OVL0_2L_MOUT_EN_DISP_PATH0
+ MT8183_DISP_OVL0_2L_MOUT_EN, MT8183_OVL0_2L_MOUT_EN_DISP_PATH0,
+ MT8183_OVL0_2L_MOUT_EN_DISP_PATH0
}, {
DDP_COMPONENT_OVL_2L1, DDP_COMPONENT_RDMA1,
- MT8183_DISP_OVL1_2L_MOUT_EN, MT8183_OVL1_2L_MOUT_EN_RDMA1
+ MT8183_DISP_OVL1_2L_MOUT_EN, MT8183_OVL1_2L_MOUT_EN_RDMA1,
+ MT8183_OVL1_2L_MOUT_EN_RDMA1
}, {
DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0,
- MT8183_DISP_DITHER0_MOUT_EN, MT8183_DITHER0_MOUT_IN_DSI0
+ MT8183_DISP_DITHER0_MOUT_EN, MT8183_DITHER0_MOUT_IN_DSI0,
+ MT8183_DITHER0_MOUT_IN_DSI0
}, {
DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0,
- MT8183_DISP_PATH0_SEL_IN, MT8183_DISP_PATH0_SEL_IN_OVL0_2L
+ MT8183_DISP_PATH0_SEL_IN, MT8183_DISP_PATH0_SEL_IN_OVL0_2L,
+ MT8183_DISP_PATH0_SEL_IN_OVL0_2L
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8183_DISP_DPI0_SEL_IN, MT8183_DPI0_SEL_IN_RDMA1
+ MT8183_DISP_DPI0_SEL_IN, MT8183_DPI0_SEL_IN_RDMA1,
+ MT8183_DPI0_SEL_IN_RDMA1
}, {
DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
- MT8183_DISP_RDMA0_SOUT_SEL_IN, MT8183_RDMA0_SOUT_COLOR0
+ MT8183_DISP_RDMA0_SOUT_SEL_IN, MT8183_RDMA0_SOUT_COLOR0,
+ MT8183_RDMA0_SOUT_COLOR0
}
};
diff --git a/drivers/soc/mediatek/mt8365-mmsys.h b/drivers/soc/mediatek/mt8365-mmsys.h
new file mode 100644
index 000000000000..690e3fe2dee0
--- /dev/null
+++ b/drivers/soc/mediatek/mt8365-mmsys.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8365_MMSYS_H
+#define __SOC_MEDIATEK_MT8365_MMSYS_H
+
+#define MT8365_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0xf3c
+#define MT8365_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL 0xf4c
+#define MT8365_DISP_REG_CONFIG_DISP_DITHER0_MOUT_EN 0xf50
+#define MT8365_DISP_REG_CONFIG_DISP_RDMA0_SEL_IN 0xf54
+#define MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN 0xf60
+#define MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0xf64
+#define MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN 0xf68
+
+#define MT8365_RDMA0_SOUT_COLOR0 0x1
+#define MT8365_DITHER_MOUT_EN_DSI0 0x1
+#define MT8365_DSI0_SEL_IN_DITHER 0x1
+#define MT8365_RDMA0_SEL_IN_OVL0 0x0
+#define MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 0x0
+#define MT8365_DISP_COLOR_SEL_IN_COLOR0 0x0
+#define MT8365_OVL0_MOUT_PATH0_SEL BIT(0)
+
+static const struct mtk_mmsys_routes mt8365_mmsys_routing_table[] = {
+ {
+ DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
+ MT8365_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN,
+ MT8365_OVL0_MOUT_PATH0_SEL, MT8365_OVL0_MOUT_PATH0_SEL
+ },
+ {
+ DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
+ MT8365_DISP_REG_CONFIG_DISP_RDMA0_SEL_IN,
+ MT8365_RDMA0_SEL_IN_OVL0, MT8365_RDMA0_SEL_IN_OVL0
+ },
+ {
+ DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
+ MT8365_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL,
+ MT8365_RDMA0_SOUT_COLOR0, MT8365_RDMA0_SOUT_COLOR0
+ },
+ {
+ DDP_COMPONENT_COLOR0, DDP_COMPONENT_CCORR,
+ MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN,
+ MT8365_DISP_COLOR_SEL_IN_COLOR0,MT8365_DISP_COLOR_SEL_IN_COLOR0
+ },
+ {
+ DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0,
+ MT8365_DISP_REG_CONFIG_DISP_DITHER0_MOUT_EN,
+ MT8365_DITHER_MOUT_EN_DSI0, MT8365_DITHER_MOUT_EN_DSI0
+ },
+ {
+ DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0,
+ MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN,
+ MT8365_DSI0_SEL_IN_DITHER, MT8365_DSI0_SEL_IN_DITHER
+ },
+ {
+ DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
+ MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN,
+ MT8365_RDMA0_RSZ0_SEL_IN_RDMA0, MT8365_RDMA0_RSZ0_SEL_IN_RDMA0
+ },
+};
+
+#endif /* __SOC_MEDIATEK_MT8365_MMSYS_H */
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index 080660ef11bf..a78e88f27b62 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -13,6 +13,7 @@
#include "mtk-mmsys.h"
#include "mt8167-mmsys.h"
#include "mt8183-mmsys.h"
+#include "mt8365-mmsys.h"
static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
.clk_driver = "clk-mt2701-mm",
@@ -52,6 +53,12 @@ static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
.num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table),
};
+static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
+ .clk_driver = "clk-mt8365-mm",
+ .routes = mt8365_mmsys_routing_table,
+ .num_routes = ARRAY_SIZE(mt8365_mmsys_routing_table),
+};
+
struct mtk_mmsys {
void __iomem *regs;
const struct mtk_mmsys_driver_data *data;
@@ -68,7 +75,9 @@ void mtk_mmsys_ddp_connect(struct device *dev,
for (i = 0; i < mmsys->data->num_routes; i++)
if (cur == routes[i].from_comp && next == routes[i].to_comp) {
- reg = readl_relaxed(mmsys->regs + routes[i].addr) | routes[i].val;
+ reg = readl_relaxed(mmsys->regs + routes[i].addr);
+ reg &= ~routes[i].mask;
+ reg |= routes[i].val;
writel_relaxed(reg, mmsys->regs + routes[i].addr);
}
}
@@ -85,7 +94,8 @@ void mtk_mmsys_ddp_disconnect(struct device *dev,
for (i = 0; i < mmsys->data->num_routes; i++)
if (cur == routes[i].from_comp && next == routes[i].to_comp) {
- reg = readl_relaxed(mmsys->regs + routes[i].addr) & ~routes[i].val;
+ reg = readl_relaxed(mmsys->regs + routes[i].addr);
+ reg &= ~routes[i].mask;
writel_relaxed(reg, mmsys->regs + routes[i].addr);
}
}
@@ -157,6 +167,10 @@ static const struct of_device_id of_match_mtk_mmsys[] = {
.compatible = "mediatek,mt8183-mmsys",
.data = &mt8183_mmsys_driver_data,
},
+ {
+ .compatible = "mediatek,mt8365-mmsys",
+ .data = &mt8365_mmsys_driver_data,
+ },
{ }
};
diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h
index a760a34e6eca..9e2b81bd38db 100644
--- a/drivers/soc/mediatek/mtk-mmsys.h
+++ b/drivers/soc/mediatek/mtk-mmsys.h
@@ -35,41 +35,54 @@
#define RDMA0_SOUT_DSI1 0x1
#define RDMA0_SOUT_DSI2 0x4
#define RDMA0_SOUT_DSI3 0x5
+#define RDMA0_SOUT_MASK 0x7
#define RDMA1_SOUT_DPI0 0x2
#define RDMA1_SOUT_DPI1 0x3
#define RDMA1_SOUT_DSI1 0x1
#define RDMA1_SOUT_DSI2 0x4
#define RDMA1_SOUT_DSI3 0x5
+#define RDMA1_SOUT_MASK 0x7
#define RDMA2_SOUT_DPI0 0x2
#define RDMA2_SOUT_DPI1 0x3
#define RDMA2_SOUT_DSI1 0x1
#define RDMA2_SOUT_DSI2 0x4
#define RDMA2_SOUT_DSI3 0x5
+#define RDMA2_SOUT_MASK 0x7
#define DPI0_SEL_IN_RDMA1 0x1
#define DPI0_SEL_IN_RDMA2 0x3
+#define DPI0_SEL_IN_MASK 0x3
#define DPI1_SEL_IN_RDMA1 (0x1 << 8)
#define DPI1_SEL_IN_RDMA2 (0x3 << 8)
+#define DPI1_SEL_IN_MASK (0x3 << 8)
#define DSI0_SEL_IN_RDMA1 0x1
#define DSI0_SEL_IN_RDMA2 0x4
+#define DSI0_SEL_IN_MASK 0x7
#define DSI1_SEL_IN_RDMA1 0x1
#define DSI1_SEL_IN_RDMA2 0x4
+#define DSI1_SEL_IN_MASK 0x7
#define DSI2_SEL_IN_RDMA1 (0x1 << 16)
#define DSI2_SEL_IN_RDMA2 (0x4 << 16)
+#define DSI2_SEL_IN_MASK (0x7 << 16)
#define DSI3_SEL_IN_RDMA1 (0x1 << 16)
#define DSI3_SEL_IN_RDMA2 (0x4 << 16)
+#define DSI3_SEL_IN_MASK (0x7 << 16)
#define COLOR1_SEL_IN_OVL1 0x1
#define OVL_MOUT_EN_RDMA 0x1
#define BLS_TO_DSI_RDMA1_TO_DPI1 0x8
#define BLS_TO_DPI_RDMA1_TO_DSI 0x2
+#define BLS_RDMA1_DSI_DPI_MASK 0xf
#define DSI_SEL_IN_BLS 0x0
#define DPI_SEL_IN_BLS 0x0
+#define DPI_SEL_IN_MASK 0x1
#define DSI_SEL_IN_RDMA 0x1
+#define DSI_SEL_IN_MASK 0x1
struct mtk_mmsys_routes {
u32 from_comp;
u32 to_comp;
u32 addr;
+ u32 mask;
u32 val;
};
@@ -91,124 +104,168 @@ struct mtk_mmsys_driver_data {
static const struct mtk_mmsys_routes mmsys_default_routing_table[] = {
{
DDP_COMPONENT_BLS, DDP_COMPONENT_DSI0,
- DISP_REG_CONFIG_OUT_SEL, BLS_TO_DSI_RDMA1_TO_DPI1
+ DISP_REG_CONFIG_OUT_SEL, BLS_RDMA1_DSI_DPI_MASK,
+ BLS_TO_DSI_RDMA1_TO_DPI1
}, {
DDP_COMPONENT_BLS, DDP_COMPONENT_DSI0,
- DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_BLS
+ DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_MASK,
+ DSI_SEL_IN_BLS
}, {
DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0,
- DISP_REG_CONFIG_OUT_SEL, BLS_TO_DPI_RDMA1_TO_DSI
+ DISP_REG_CONFIG_OUT_SEL, BLS_RDMA1_DSI_DPI_MASK,
+ BLS_TO_DPI_RDMA1_TO_DSI
}, {
DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0,
- DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_RDMA
+ DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_MASK,
+ DSI_SEL_IN_RDMA
}, {
DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0,
- DISP_REG_CONFIG_DPI_SEL, DPI_SEL_IN_BLS
+ DISP_REG_CONFIG_DPI_SEL, DPI_SEL_IN_MASK,
+ DPI_SEL_IN_BLS
}, {
DDP_COMPONENT_GAMMA, DDP_COMPONENT_RDMA1,
- DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN, GAMMA_MOUT_EN_RDMA1
+ DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN, GAMMA_MOUT_EN_RDMA1,
+ GAMMA_MOUT_EN_RDMA1
}, {
DDP_COMPONENT_OD0, DDP_COMPONENT_RDMA0,
- DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD_MOUT_EN_RDMA0
+ DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD_MOUT_EN_RDMA0,
+ OD_MOUT_EN_RDMA0
}, {
DDP_COMPONENT_OD1, DDP_COMPONENT_RDMA1,
- DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD1_MOUT_EN_RDMA1
+ DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD1_MOUT_EN_RDMA1,
+ OD1_MOUT_EN_RDMA1
}, {
DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
- DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0
+ DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0,
+ OVL0_MOUT_EN_COLOR0
}, {
DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
- DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0
+ DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0,
+ COLOR0_SEL_IN_OVL0
}, {
DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- DISP_REG_CONFIG_DISP_OVL_MOUT_EN, OVL_MOUT_EN_RDMA
+ DISP_REG_CONFIG_DISP_OVL_MOUT_EN, OVL_MOUT_EN_RDMA,
+ OVL_MOUT_EN_RDMA
}, {
DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1,
- DISP_REG_CONFIG_DISP_OVL1_MOUT_EN, OVL1_MOUT_EN_COLOR1
+ DISP_REG_CONFIG_DISP_OVL1_MOUT_EN, OVL1_MOUT_EN_COLOR1,
+ OVL1_MOUT_EN_COLOR1
}, {
DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1,
- DISP_REG_CONFIG_DISP_COLOR1_SEL_IN, COLOR1_SEL_IN_OVL1
+ DISP_REG_CONFIG_DISP_COLOR1_SEL_IN, COLOR1_SEL_IN_OVL1,
+ COLOR1_SEL_IN_OVL1
}, {
DDP_COMPONENT_RDMA0, DDP_COMPONENT_DPI0,
- DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DPI0
+ DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK,
+ RDMA0_SOUT_DPI0
}, {
DDP_COMPONENT_RDMA0, DDP_COMPONENT_DPI1,
- DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DPI1
+ DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK,
+ RDMA0_SOUT_DPI1
}, {
DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI1,
- DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI1
+ DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK,
+ RDMA0_SOUT_DSI1
}, {
DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI2,
- DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI2
+ DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK,
+ RDMA0_SOUT_DSI2
}, {
DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI3,
- DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI3
+ DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK,
+ RDMA0_SOUT_DSI3
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DPI0
+ DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK,
+ RDMA1_SOUT_DPI0
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_RDMA1
+ DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_MASK,
+ DPI0_SEL_IN_RDMA1
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI1,
- DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DPI1
+ DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK,
+ RDMA1_SOUT_DPI1
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI1,
- DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_RDMA1
+ DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_MASK,
+ DPI1_SEL_IN_RDMA1
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI0,
- DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_RDMA1
+ DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_MASK,
+ DSI0_SEL_IN_RDMA1
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI1,
- DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI1
+ DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK,
+ RDMA1_SOUT_DSI1
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI1,
- DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_RDMA1
+ DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_MASK,
+ DSI1_SEL_IN_RDMA1
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI2,
- DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI2
+ DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK,
+ RDMA1_SOUT_DSI2
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI2,
- DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_RDMA1
+ DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_MASK,
+ DSI2_SEL_IN_RDMA1
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI3,
- DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI3
+ DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK,
+ RDMA1_SOUT_DSI3
}, {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI3,
- DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_RDMA1
+ DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_MASK,
+ DSI3_SEL_IN_RDMA1
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI0,
- DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DPI0
+ DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK,
+ RDMA2_SOUT_DPI0
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI0,
- DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_RDMA2
+ DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_MASK,
+ DPI0_SEL_IN_RDMA2
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI1,
- DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DPI1
+ DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK,
+ RDMA2_SOUT_DPI1
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI1,
- DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_RDMA2
+ DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_MASK,
+ DPI1_SEL_IN_RDMA2
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI0,
- DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_RDMA2
+ DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_MASK,
+ DSI0_SEL_IN_RDMA2
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI1,
- DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI1
+ DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK,
+ RDMA2_SOUT_DSI1
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI1,
- DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_RDMA2
+ DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_MASK,
+ DSI1_SEL_IN_RDMA2
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI2,
- DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI2
+ DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK,
+ RDMA2_SOUT_DSI2
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI2,
- DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_RDMA2
+ DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_MASK,
+ DSI2_SEL_IN_RDMA2
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI3,
- DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI3
+ DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK,
+ RDMA2_SOUT_DSI3
}, {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI3,
- DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_RDMA2
+ DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_MASK,
+ DSI3_SEL_IN_RDMA2
+ }, {
+ DDP_COMPONENT_UFOE, DDP_COMPONENT_DSI0,
+ DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, UFOE_MOUT_EN_DSI0,
+ UFOE_MOUT_EN_DSI0
}
};
diff --git a/drivers/soc/mediatek/mtk-pm-domains.h b/drivers/soc/mediatek/mtk-pm-domains.h
index 21a4e113bbec..c5ac649ae51b 100644
--- a/drivers/soc/mediatek/mtk-pm-domains.h
+++ b/drivers/soc/mediatek/mtk-pm-domains.h
@@ -60,7 +60,7 @@
#define BUS_PROT_UPDATE_TOPAXI(_mask) \
BUS_PROT_UPDATE(_mask, \
INFRA_TOPAXI_PROTECTEN, \
- INFRA_TOPAXI_PROTECTEN_CLR, \
+ INFRA_TOPAXI_PROTECTEN, \
INFRA_TOPAXI_PROTECTSTA1)
struct scpsys_bus_prot_data {
diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
index 7abfc8c4fdc7..475a57b435b2 100644
--- a/drivers/soc/qcom/apr.c
+++ b/drivers/soc/qcom/apr.c
@@ -217,7 +217,7 @@ static int apr_device_probe(struct device *dev)
return adrv->probe(adev);
}
-static int apr_device_remove(struct device *dev)
+static void apr_device_remove(struct device *dev)
{
struct apr_device *adev = to_apr_device(dev);
struct apr_driver *adrv;
@@ -231,8 +231,6 @@ static int apr_device_remove(struct device *dev)
idr_remove(&apr->svcs_idr, adev->svc_id);
spin_unlock(&apr->svcs_lock);
}
-
- return 0;
}
static int apr_uevent(struct device *dev, struct kobj_uevent_env *env)
diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c
index b24cc77d1889..4ce8e816154f 100644
--- a/drivers/soc/qcom/cpr.c
+++ b/drivers/soc/qcom/cpr.c
@@ -801,38 +801,6 @@ unlock:
return ret;
}
-static int cpr_read_efuse(struct device *dev, const char *cname, u32 *data)
-{
- struct nvmem_cell *cell;
- ssize_t len;
- char *ret;
- int i;
-
- *data = 0;
-
- cell = nvmem_cell_get(dev, cname);
- if (IS_ERR(cell)) {
- if (PTR_ERR(cell) != -EPROBE_DEFER)
- dev_err(dev, "undefined cell %s\n", cname);
- return PTR_ERR(cell);
- }
-
- ret = nvmem_cell_read(cell, &len);
- nvmem_cell_put(cell);
- if (IS_ERR(ret)) {
- dev_err(dev, "can't read cell %s\n", cname);
- return PTR_ERR(ret);
- }
-
- for (i = 0; i < len; i++)
- *data |= ret[i] << (8 * i);
-
- kfree(ret);
- dev_dbg(dev, "efuse read(%s) = %x, bytes %zd\n", cname, *data, len);
-
- return 0;
-}
-
static int
cpr_populate_ring_osc_idx(struct cpr_drv *drv)
{
@@ -843,8 +811,7 @@ cpr_populate_ring_osc_idx(struct cpr_drv *drv)
int ret;
for (; fuse < end; fuse++, fuses++) {
- ret = cpr_read_efuse(drv->dev, fuses->ring_osc,
- &data);
+ ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data);
if (ret)
return ret;
fuse->ring_osc_idx = data;
@@ -863,7 +830,7 @@ static int cpr_read_fuse_uV(const struct cpr_desc *desc,
u32 bits = 0;
int ret;
- ret = cpr_read_efuse(drv->dev, init_v_efuse, &bits);
+ ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits);
if (ret)
return ret;
@@ -932,7 +899,7 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
}
/* Populate target quotient by scaling */
- ret = cpr_read_efuse(drv->dev, fuses->quotient, &fuse->quot);
+ ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot);
if (ret)
return ret;
@@ -1001,7 +968,7 @@ static int cpr_calculate_scaling(const char *quot_offset,
prev_fuse = fuse - 1;
if (quot_offset) {
- ret = cpr_read_efuse(drv->dev, quot_offset, &quot_diff);
+ ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, &quot_diff);
if (ret)
return ret;
@@ -1701,7 +1668,7 @@ static int cpr_probe(struct platform_device *pdev)
* initialized after attaching to the power domain,
* since it depends on the CPU's OPP table.
*/
- ret = cpr_read_efuse(dev, "cpr_fuse_revision", &cpr_rev);
+ ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev);
if (ret)
return ret;
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index eba7f76f9d61..bda170d7b4a2 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -166,6 +166,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
metadata = qcom_mdt_read_metadata(fw, &metadata_len);
if (IS_ERR(metadata)) {
ret = PTR_ERR(metadata);
+ dev_err(dev, "error %d reading firmware %s metadata\n",
+ ret, fw_name);
goto out;
}
@@ -173,7 +175,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
kfree(metadata);
if (ret) {
- dev_err(dev, "invalid firmware metadata\n");
+ /* Invalid firmware metadata */
+ dev_err(dev, "error %d initializing firmware %s\n",
+ ret, fw_name);
goto out;
}
}
@@ -199,7 +203,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys,
max_addr - min_addr);
if (ret) {
- dev_err(dev, "unable to setup relocation\n");
+ /* Unable to set up relocation */
+ dev_err(dev, "error %d setting up firmware %s\n",
+ ret, fw_name);
goto out;
}
}
@@ -243,9 +249,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (phdr->p_filesz && phdr->p_offset < fw->size) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
- dev_err(dev,
- "failed to load segment %d from truncated file %s\n",
- i, firmware);
+ dev_err(dev, "file %s segment %d would be truncated\n",
+ fw_name, i);
ret = -EINVAL;
break;
}
@@ -257,7 +262,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ret = request_firmware_into_buf(&seg_fw, fw_name, dev,
ptr, phdr->p_filesz);
if (ret) {
- dev_err(dev, "failed to load %s\n", fw_name);
+ dev_err(dev, "error %d loading %s\n",
+ ret, fw_name);
break;
}
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index 5bdfb1565c14..7d649d2cf31e 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -104,7 +104,6 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config",
#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
@@ -322,6 +321,30 @@ static void geni_se_select_dma_mode(struct geni_se *se)
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
}
+static void geni_se_select_gpi_mode(struct geni_se *se)
+{
+ u32 val;
+
+ geni_se_irq_clear(se);
+
+ writel(0, se->base + SE_IRQ_EN);
+
+ val = readl(se->base + SE_GENI_S_IRQ_EN);
+ val &= ~S_CMD_DONE_EN;
+ writel(val, se->base + SE_GENI_S_IRQ_EN);
+
+ val = readl(se->base + SE_GENI_M_IRQ_EN);
+ val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN |
+ M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
+ writel(val, se->base + SE_GENI_M_IRQ_EN);
+
+ writel(GENI_DMA_MODE_EN, se->base + SE_GENI_DMA_MODE_EN);
+
+ val = readl(se->base + SE_GSI_EVENT_EN);
+ val |= (DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | GENI_M_EVENT_EN | GENI_S_EVENT_EN);
+ writel(val, se->base + SE_GSI_EVENT_EN);
+}
+
/**
* geni_se_select_mode() - Select the serial engine transfer mode
* @se: Pointer to the concerned serial engine.
@@ -329,7 +352,7 @@ static void geni_se_select_dma_mode(struct geni_se *se)
*/
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);
+ WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA && mode != GENI_GPI_DMA);
switch (mode) {
case GENI_SE_FIFO:
@@ -338,6 +361,9 @@ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode)
case GENI_SE_DMA:
geni_se_select_dma_mode(se);
break;
+ case GENI_GPI_DMA:
+ geni_se_select_gpi_mode(se);
+ break;
case GENI_SE_INVALID:
default:
break;
diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index 934fcc4d2b05..536c3e4114fb 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -476,12 +476,12 @@ static int qmp_cooling_device_add(struct qmp *qmp,
static int qmp_cooling_devices_register(struct qmp *qmp)
{
struct device_node *np, *child;
- int count = QMP_NUM_COOLING_RESOURCES;
+ int count = 0;
int ret;
np = qmp->dev->of_node;
- qmp->cooling_devs = devm_kcalloc(qmp->dev, count,
+ qmp->cooling_devs = devm_kcalloc(qmp->dev, QMP_NUM_COOLING_RESOURCES,
sizeof(*qmp->cooling_devs),
GFP_KERNEL);
@@ -497,12 +497,16 @@ static int qmp_cooling_devices_register(struct qmp *qmp)
goto unroll;
}
+ if (!count)
+ devm_kfree(qmp->dev, qmp->cooling_devs);
+
return 0;
unroll:
while (--count >= 0)
thermal_cooling_device_unregister
(qmp->cooling_devs[count].cdev);
+ devm_kfree(qmp->dev, qmp->cooling_devs);
return ret;
}
@@ -602,6 +606,7 @@ static const struct of_device_id qmp_dt_match[] = {
{ .compatible = "qcom,sm8150-aoss-qmp", },
{ .compatible = "qcom,sm8250-aoss-qmp", },
{ .compatible = "qcom,sm8350-aoss-qmp", },
+ { .compatible = "qcom,aoss-qmp", },
{}
};
MODULE_DEVICE_TABLE(of, qmp_dt_match);
diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
index 2daa17ba54a3..fa209b479ab3 100644
--- a/drivers/soc/qcom/rpmhpd.c
+++ b/drivers/soc/qcom/rpmhpd.c
@@ -403,12 +403,11 @@ static int rpmhpd_power_on(struct generic_pm_domain *domain)
static int rpmhpd_power_off(struct generic_pm_domain *domain)
{
struct rpmhpd *pd = domain_to_rpmhpd(domain);
- int ret = 0;
+ int ret;
mutex_lock(&rpmhpd_lock);
- ret = rpmhpd_aggregate_corner(pd, pd->level[0]);
-
+ ret = rpmhpd_aggregate_corner(pd, 0);
if (!ret)
pd->enabled = false;
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index 0b532a892d60..dbf494e92574 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -346,6 +346,33 @@ static const struct rpmpd_desc sdm660_desc = {
.max_state = RPM_SMD_LEVEL_TURBO,
};
+/* sm4250/6115 RPM Power domains */
+DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0);
+DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0);
+
+DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0);
+DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0);
+
+DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0);
+DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0);
+
+static struct rpmpd *sm6115_rpmpds[] = {
+ [SM6115_VDDCX] = &sm6115_vddcx,
+ [SM6115_VDDCX_AO] = &sm6115_vddcx_ao,
+ [SM6115_VDDCX_VFL] = &sm6115_vddcx_vfl,
+ [SM6115_VDDMX] = &sm6115_vddmx,
+ [SM6115_VDDMX_AO] = &sm6115_vddmx_ao,
+ [SM6115_VDDMX_VFL] = &sm6115_vddmx_vfl,
+ [SM6115_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
+ [SM6115_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
+};
+
+static const struct rpmpd_desc sm6115_desc = {
+ .rpmpds = sm6115_rpmpds,
+ .num_pds = ARRAY_SIZE(sm6115_rpmpds),
+ .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
+};
+
static const struct of_device_id rpmpd_match_table[] = {
{ .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
@@ -356,6 +383,7 @@ static const struct of_device_id rpmpd_match_table[] = {
{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
+ { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
{ }
};
MODULE_DEVICE_TABLE(of, rpmpd_match_table);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index bc0be1d4be5f..dfdd4f20f5fd 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -242,6 +242,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-msm8996" },
{ .compatible = "qcom,rpm-msm8998" },
{ .compatible = "qcom,rpm-sdm660" },
+ { .compatible = "qcom,rpm-sm6115" },
{ .compatible = "qcom,rpm-sm6125" },
{ .compatible = "qcom,rpm-qcs404" },
{}
diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c
index 1d3d5e3ec2b0..ef15d014c03a 100644
--- a/drivers/soc/qcom/smsm.c
+++ b/drivers/soc/qcom/smsm.c
@@ -109,7 +109,7 @@ struct smsm_entry {
DECLARE_BITMAP(irq_enabled, 32);
DECLARE_BITMAP(irq_rising, 32);
DECLARE_BITMAP(irq_falling, 32);
- u32 last_value;
+ unsigned long last_value;
u32 *remote_state;
u32 *subscription;
@@ -204,8 +204,7 @@ static irqreturn_t smsm_intr(int irq, void *data)
u32 val;
val = readl(entry->remote_state);
- changed = val ^ entry->last_value;
- entry->last_value = val;
+ changed = val ^ xchg(&entry->last_value, val);
for_each_set_bit(i, entry->irq_enabled, 32) {
if (!(changed & BIT(i)))
@@ -264,6 +263,12 @@ static void smsm_unmask_irq(struct irq_data *irqd)
struct qcom_smsm *smsm = entry->smsm;
u32 val;
+ /* Make sure our last cached state is up-to-date */
+ if (readl(entry->remote_state) & BIT(irq))
+ set_bit(irq, &entry->last_value);
+ else
+ clear_bit(irq, &entry->last_value);
+
set_bit(irq, entry->irq_enabled);
if (entry->subscription) {
@@ -299,11 +304,28 @@ static int smsm_set_irq_type(struct irq_data *irqd, unsigned int type)
return 0;
}
+static int smsm_get_irqchip_state(struct irq_data *irqd,
+ enum irqchip_irq_state which, bool *state)
+{
+ struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd);
+ irq_hw_number_t irq = irqd_to_hwirq(irqd);
+ u32 val;
+
+ if (which != IRQCHIP_STATE_LINE_LEVEL)
+ return -EINVAL;
+
+ val = readl(entry->remote_state);
+ *state = !!(val & BIT(irq));
+
+ return 0;
+}
+
static struct irq_chip smsm_irq_chip = {
.name = "smsm",
.irq_mask = smsm_mask_irq,
.irq_unmask = smsm_unmask_irq,
.irq_set_type = smsm_set_irq_type,
+ .irq_get_irqchip_state = smsm_get_irqchip_state,
};
/**
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index b2f049faa3df..9faf48302f4b 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -417,8 +417,8 @@ QCOM_OPEN(chip_id, qcom_show_chip_id);
static int show_image_##type(struct seq_file *seq, void *p) \
{ \
struct smem_image_version *image_version = seq->private; \
- seq_puts(seq, image_version->type); \
- seq_putc(seq, '\n'); \
+ if (image_version->type[0] != '\0') \
+ seq_printf(seq, "%s\n", image_version->type); \
return 0; \
} \
static int open_image_##type(struct inode *inode, struct file *file) \
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 71b44c31b012..07e0ecd64319 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -208,6 +208,7 @@ config ARCH_R8A77951
help
This enables support for the Renesas R-Car H3 SoC (revisions 2.0 and
later).
+ This includes different gradings like R-Car H3e-2G.
config ARCH_R8A77965
bool "ARM64 Platform support for R-Car M3-N"
@@ -229,6 +230,7 @@ config ARCH_R8A77961
select SYSC_R8A77961
help
This enables support for the Renesas R-Car M3-W+ SoC.
+ This includes different gradings like R-Car M3e-2G.
config ARCH_R8A77980
bool "ARM64 Platform support for R-Car V3H"
diff --git a/drivers/soc/renesas/r8a779a0-sysc.c b/drivers/soc/renesas/r8a779a0-sysc.c
index d464ffa1be33..7410b9fa9846 100644
--- a/drivers/soc/renesas/r8a779a0-sysc.c
+++ b/drivers/soc/renesas/r8a779a0-sysc.c
@@ -404,19 +404,21 @@ static int __init r8a779a0_sysc_pd_init(void)
for (i = 0; i < info->num_areas; i++) {
const struct r8a779a0_sysc_area *area = &info->areas[i];
struct r8a779a0_sysc_pd *pd;
+ size_t n;
if (!area->name) {
/* Skip NULLified area */
continue;
}
- pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
+ n = strlen(area->name) + 1;
+ pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL);
if (!pd) {
error = -ENOMEM;
goto out_put;
}
- strcpy(pd->name, area->name);
+ memcpy(pd->name, area->name, n);
pd->genpd.name = pd->name;
pd->pdr = area->pdr;
pd->flags = area->flags;
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index 53387a72ca00..b0a80de34c98 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -396,19 +396,21 @@ static int __init rcar_sysc_pd_init(void)
for (i = 0; i < info->num_areas; i++) {
const struct rcar_sysc_area *area = &info->areas[i];
struct rcar_sysc_pd *pd;
+ size_t n;
if (!area->name) {
/* Skip NULLified area */
continue;
}
- pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
+ n = strlen(area->name) + 1;
+ pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL);
if (!pd) {
error = -ENOMEM;
goto out_put;
}
- strcpy(pd->name, area->name);
+ memcpy(pd->name, area->name, n);
pd->genpd.name = pd->name;
pd->ch.chan_offs = area->chan_offs;
pd->ch.chan_bit = area->chan_bit;
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index 8310fce7714e..dab9f5a0aad0 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -284,11 +284,15 @@ static const struct of_device_id renesas_socs[] __initconst = {
#if defined(CONFIG_ARCH_R8A77950) || defined(CONFIG_ARCH_R8A77951)
{ .compatible = "renesas,r8a7795", .data = &soc_rcar_h3 },
#endif
+#ifdef CONFIG_ARCH_R8A77951
+ { .compatible = "renesas,r8a779m1", .data = &soc_rcar_h3 },
+#endif
#ifdef CONFIG_ARCH_R8A77960
{ .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w },
#endif
#ifdef CONFIG_ARCH_R8A77961
{ .compatible = "renesas,r8a77961", .data = &soc_rcar_m3_w },
+ { .compatible = "renesas,r8a779m3", .data = &soc_rcar_m3_w },
#endif
#ifdef CONFIG_ARCH_R8A77965
{ .compatible = "renesas,r8a77965", .data = &soc_rcar_m3_n },
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
index 2c13bf4dd5db..25eb2c1e31bb 100644
--- a/drivers/soc/rockchip/Kconfig
+++ b/drivers/soc/rockchip/Kconfig
@@ -6,8 +6,8 @@ if ARCH_ROCKCHIP || COMPILE_TEST
#
config ROCKCHIP_GRF
- bool
- default y
+ bool "Rockchip General Register Files support" if COMPILE_TEST
+ default y if ARCH_ROCKCHIP
help
The General Register Files are a central component providing
special additional settings registers for a lot of soc-components.
diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c
index cf8182fc3642..9df513d1219b 100644
--- a/drivers/soc/rockchip/io-domain.c
+++ b/drivers/soc/rockchip/io-domain.c
@@ -51,13 +51,11 @@
#define RK3399_PMUGRF_CON0_VSEL BIT(8)
#define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9
-struct rockchip_iodomain;
+#define RK3568_PMU_GRF_IO_VSEL0 (0x0140)
+#define RK3568_PMU_GRF_IO_VSEL1 (0x0144)
+#define RK3568_PMU_GRF_IO_VSEL2 (0x0148)
-struct rockchip_iodomain_soc_data {
- int grf_offset;
- const char *supply_names[MAX_SUPPLIES];
- void (*init)(struct rockchip_iodomain *iod);
-};
+struct rockchip_iodomain;
struct rockchip_iodomain_supply {
struct rockchip_iodomain *iod;
@@ -66,13 +64,62 @@ struct rockchip_iodomain_supply {
int idx;
};
+struct rockchip_iodomain_soc_data {
+ int grf_offset;
+ const char *supply_names[MAX_SUPPLIES];
+ void (*init)(struct rockchip_iodomain *iod);
+ int (*write)(struct rockchip_iodomain_supply *supply, int uV);
+};
+
struct rockchip_iodomain {
struct device *dev;
struct regmap *grf;
const struct rockchip_iodomain_soc_data *soc_data;
struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
+ int (*write)(struct rockchip_iodomain_supply *supply, int uV);
};
+static int rk3568_iodomain_write(struct rockchip_iodomain_supply *supply, int uV)
+{
+ struct rockchip_iodomain *iod = supply->iod;
+ u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
+ u32 val0, val1;
+ int b;
+
+ switch (supply->idx) {
+ case 0: /* pmuio1 */
+ break;
+ case 1: /* pmuio2 */
+ b = supply->idx;
+ val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
+ b = supply->idx + 4;
+ val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
+
+ regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val0);
+ regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val1);
+ break;
+ case 3: /* vccio2 */
+ break;
+ case 2: /* vccio1 */
+ case 4: /* vccio3 */
+ case 5: /* vccio4 */
+ case 6: /* vccio5 */
+ case 7: /* vccio6 */
+ case 8: /* vccio7 */
+ b = supply->idx - 1;
+ val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
+ val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
+
+ regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL0, val0);
+ regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL1, val1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
int uV)
{
@@ -136,7 +183,7 @@ static int rockchip_iodomain_notify(struct notifier_block *nb,
return NOTIFY_BAD;
}
- ret = rockchip_iodomain_write(supply, uV);
+ ret = supply->iod->write(supply, uV);
if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
return NOTIFY_BAD;
@@ -398,6 +445,22 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
.init = rk3399_pmu_iodomain_init,
};
+static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
+ .grf_offset = 0x140,
+ .supply_names = {
+ "pmuio1",
+ "pmuio2",
+ "vccio1",
+ "vccio2",
+ "vccio3",
+ "vccio4",
+ "vccio5",
+ "vccio6",
+ "vccio7",
+ },
+ .write = rk3568_iodomain_write,
+};
+
static const struct rockchip_iodomain_soc_data soc_data_rv1108 = {
.grf_offset = 0x404,
.supply_names = {
@@ -470,6 +533,10 @@ static const struct of_device_id rockchip_iodomain_match[] = {
.data = &soc_data_rk3399_pmu
},
{
+ .compatible = "rockchip,rk3568-pmu-io-voltage-domain",
+ .data = &soc_data_rk3568_pmu
+ },
+ {
.compatible = "rockchip,rv1108-io-voltage-domain",
.data = &soc_data_rv1108
},
@@ -502,6 +569,11 @@ static int rockchip_iodomain_probe(struct platform_device *pdev)
match = of_match_node(rockchip_iodomain_match, np);
iod->soc_data = match->data;
+ if (iod->soc_data->write)
+ iod->write = iod->soc_data->write;
+ else
+ iod->write = rockchip_iodomain_write;
+
parent = pdev->dev.parent;
if (parent && parent->of_node) {
iod->grf = syscon_node_to_regmap(parent->of_node);
@@ -562,7 +634,7 @@ static int rockchip_iodomain_probe(struct platform_device *pdev)
supply->reg = reg;
supply->nb.notifier_call = rockchip_iodomain_notify;
- ret = rockchip_iodomain_write(supply, uV);
+ ret = iod->write(supply, uV);
if (ret) {
supply->reg = NULL;
goto unreg_notify;
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index 3d9da3d359da..f2151815db58 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -13,6 +13,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
@@ -210,6 +211,8 @@ static int tegra_fuse_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, fuse);
fuse->dev = &pdev->dev;
+ pm_runtime_enable(&pdev->dev);
+
if (fuse->soc->probe) {
err = fuse->soc->probe(fuse);
if (err < 0)
@@ -246,14 +249,71 @@ static int tegra_fuse_probe(struct platform_device *pdev)
return 0;
restore:
+ fuse->clk = NULL;
fuse->base = base;
+ pm_runtime_disable(&pdev->dev);
return err;
}
+static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
+{
+ int err;
+
+ err = clk_prepare_enable(fuse->clk);
+ if (err < 0) {
+ dev_err(dev, "failed to enable FUSE clock: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused tegra_fuse_runtime_suspend(struct device *dev)
+{
+ clk_disable_unprepare(fuse->clk);
+
+ return 0;
+}
+
+static int __maybe_unused tegra_fuse_suspend(struct device *dev)
+{
+ int ret;
+
+ /*
+ * Critical for RAM re-repair operation, which must occur on resume
+ * from LP1 system suspend and as part of CCPLEX cluster switching.
+ */
+ if (fuse->soc->clk_suspend_on)
+ ret = pm_runtime_resume_and_get(dev);
+ else
+ ret = pm_runtime_force_suspend(dev);
+
+ return ret;
+}
+
+static int __maybe_unused tegra_fuse_resume(struct device *dev)
+{
+ int ret = 0;
+
+ if (fuse->soc->clk_suspend_on)
+ pm_runtime_put(dev);
+ else
+ ret = pm_runtime_force_resume(dev);
+
+ return ret;
+}
+
+static const struct dev_pm_ops tegra_fuse_pm = {
+ SET_RUNTIME_PM_OPS(tegra_fuse_runtime_suspend, tegra_fuse_runtime_resume,
+ NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(tegra_fuse_suspend, tegra_fuse_resume)
+};
+
static struct platform_driver tegra_fuse_driver = {
.driver = {
.name = "tegra-fuse",
.of_match_table = tegra_fuse_match,
+ .pm = &tegra_fuse_pm,
.suppress_bind_attrs = true,
},
.probe = tegra_fuse_probe,
diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c
index 16aaa28573ac..8ec9fc5e5e4b 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra20.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
@@ -16,6 +16,7 @@
#include <linux/kobject.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/random.h>
#include <soc/tegra/fuse.h>
@@ -46,6 +47,10 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
u32 value = 0;
int err;
+ err = pm_runtime_resume_and_get(fuse->dev);
+ if (err)
+ return err;
+
mutex_lock(&fuse->apbdma.lock);
fuse->apbdma.config.src_addr = fuse->phys + FUSE_BEGIN + offset;
@@ -66,8 +71,6 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
reinit_completion(&fuse->apbdma.wait);
- clk_prepare_enable(fuse->clk);
-
dmaengine_submit(dma_desc);
dma_async_issue_pending(fuse->apbdma.chan);
time_left = wait_for_completion_timeout(&fuse->apbdma.wait,
@@ -78,10 +81,9 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
else
value = *fuse->apbdma.virt;
- clk_disable_unprepare(fuse->clk);
-
out:
mutex_unlock(&fuse->apbdma.lock);
+ pm_runtime_put(fuse->dev);
return value;
}
@@ -165,4 +167,5 @@ const struct tegra_fuse_soc tegra20_fuse_soc = {
.probe = tegra20_fuse_probe,
.info = &tegra20_fuse_info,
.soc_attr_group = &tegra_soc_attr_group,
+ .clk_suspend_on = false,
};
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
index c1aa7815bd6e..b071d433d74f 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra30.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
@@ -12,6 +12,7 @@
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/random.h>
#include <soc/tegra/fuse.h>
@@ -52,15 +53,13 @@ static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
u32 value;
int err;
- err = clk_prepare_enable(fuse->clk);
- if (err < 0) {
- dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err);
+ err = pm_runtime_resume_and_get(fuse->dev);
+ if (err)
return 0;
- }
value = readl_relaxed(fuse->base + FUSE_BEGIN + offset);
- clk_disable_unprepare(fuse->clk);
+ pm_runtime_put(fuse->dev);
return value;
}
@@ -113,6 +112,7 @@ const struct tegra_fuse_soc tegra30_fuse_soc = {
.speedo_init = tegra30_init_speedo_data,
.info = &tegra30_fuse_info,
.soc_attr_group = &tegra_soc_attr_group,
+ .clk_suspend_on = false,
};
#endif
@@ -128,6 +128,7 @@ const struct tegra_fuse_soc tegra114_fuse_soc = {
.speedo_init = tegra114_init_speedo_data,
.info = &tegra114_fuse_info,
.soc_attr_group = &tegra_soc_attr_group,
+ .clk_suspend_on = false,
};
#endif
@@ -209,6 +210,7 @@ const struct tegra_fuse_soc tegra124_fuse_soc = {
.lookups = tegra124_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra124_fuse_lookups),
.soc_attr_group = &tegra_soc_attr_group,
+ .clk_suspend_on = true,
};
#endif
@@ -295,6 +297,7 @@ const struct tegra_fuse_soc tegra210_fuse_soc = {
.lookups = tegra210_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra210_fuse_lookups),
.soc_attr_group = &tegra_soc_attr_group,
+ .clk_suspend_on = false,
};
#endif
@@ -325,6 +328,7 @@ const struct tegra_fuse_soc tegra186_fuse_soc = {
.lookups = tegra186_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra186_fuse_lookups),
.soc_attr_group = &tegra_soc_attr_group,
+ .clk_suspend_on = false,
};
#endif
@@ -355,6 +359,7 @@ const struct tegra_fuse_soc tegra194_fuse_soc = {
.lookups = tegra194_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra194_fuse_lookups),
.soc_attr_group = &tegra194_soc_attr_group,
+ .clk_suspend_on = false,
};
#endif
@@ -385,5 +390,6 @@ const struct tegra_fuse_soc tegra234_fuse_soc = {
.lookups = tegra234_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra234_fuse_lookups),
.soc_attr_group = &tegra194_soc_attr_group,
+ .clk_suspend_on = false,
};
#endif
diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
index e057a58e2060..de58feba0435 100644
--- a/drivers/soc/tegra/fuse/fuse.h
+++ b/drivers/soc/tegra/fuse/fuse.h
@@ -34,6 +34,8 @@ struct tegra_fuse_soc {
unsigned int num_lookups;
const struct attribute_group *soc_attr_group;
+
+ bool clk_suspend_on;
};
struct tegra_fuse {
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index ea62f84d1c8b..50091c4ec948 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -436,7 +436,7 @@ struct tegra_pmc {
static struct tegra_pmc *pmc = &(struct tegra_pmc) {
.base = NULL,
- .suspend_mode = TEGRA_SUSPEND_NONE,
+ .suspend_mode = TEGRA_SUSPEND_NOT_READY,
};
static inline struct tegra_powergate *
@@ -1812,6 +1812,7 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
u32 value, values[2];
if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
+ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
} else {
switch (value) {
case 0:
@@ -2785,6 +2786,11 @@ static int tegra_pmc_regmap_init(struct tegra_pmc *pmc)
return 0;
}
+static void tegra_pmc_reset_suspend_mode(void *data)
+{
+ pmc->suspend_mode = TEGRA_SUSPEND_NOT_READY;
+}
+
static int tegra_pmc_probe(struct platform_device *pdev)
{
void __iomem *base;
@@ -2803,6 +2809,11 @@ static int tegra_pmc_probe(struct platform_device *pdev)
if (err < 0)
return err;
+ err = devm_add_action_or_reset(&pdev->dev, tegra_pmc_reset_suspend_mode,
+ NULL);
+ if (err)
+ return err;
+
/* take over the memory region from the early initialization */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
@@ -2909,6 +2920,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
tegra_pmc_clock_register(pmc, pdev->dev.of_node);
platform_set_drvdata(pdev, pmc);
+ tegra_pm_init_suspend();
return 0;
diff --git a/drivers/soc/tegra/powergate-bpmp.c b/drivers/soc/tegra/powergate-bpmp.c
index 06c792bafca5..8eaf50d0b6af 100644
--- a/drivers/soc/tegra/powergate-bpmp.c
+++ b/drivers/soc/tegra/powergate-bpmp.c
@@ -7,7 +7,6 @@
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/slab.h>
-#include <linux/version.h>
#include <soc/tegra/bpmp.h>
#include <soc/tegra/bpmp-abi.h>
diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c
index f22ac1edbdd0..49da387d7749 100644
--- a/drivers/soc/ti/pruss.c
+++ b/drivers/soc/ti/pruss.c
@@ -338,6 +338,7 @@ static const struct of_device_id pruss_of_match[] = {
{ .compatible = "ti,k2g-pruss" },
{ .compatible = "ti,am654-icssg", .data = &am65x_j721e_pruss_data, },
{ .compatible = "ti,j721e-icssg", .data = &am65x_j721e_pruss_data, },
+ { .compatible = "ti,am642-icssg", .data = &am65x_j721e_pruss_data, },
{},
};
MODULE_DEVICE_TABLE(of, pruss_of_match);
diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c
index 06cbee5fd254..b5b2fa538d5c 100644
--- a/drivers/soc/ti/smartreflex.c
+++ b/drivers/soc/ti/smartreflex.c
@@ -126,23 +126,13 @@ static irqreturn_t sr_interrupt(int irq, void *data)
static void sr_set_clk_length(struct omap_sr *sr)
{
- struct clk *fck;
u32 fclk_speed;
/* Try interconnect target module fck first if it already exists */
- fck = clk_get(sr->pdev->dev.parent, "fck");
- if (IS_ERR(fck)) {
- fck = clk_get(&sr->pdev->dev, "fck");
- if (IS_ERR(fck)) {
- dev_err(&sr->pdev->dev,
- "%s: unable to get fck for device %s\n",
- __func__, dev_name(&sr->pdev->dev));
- return;
- }
- }
+ if (IS_ERR(sr->fck))
+ return;
- fclk_speed = clk_get_rate(fck);
- clk_put(fck);
+ fclk_speed = clk_get_rate(sr->fck);
switch (fclk_speed) {
case 12000000:
@@ -587,21 +577,25 @@ int sr_enable(struct omap_sr *sr, unsigned long volt)
/* errminlimit is opp dependent and hence linked to voltage */
sr->err_minlimit = nvalue_row->errminlimit;
- pm_runtime_get_sync(&sr->pdev->dev);
+ clk_enable(sr->fck);
/* Check if SR is already enabled. If yes do nothing */
if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
- return 0;
+ goto out_enabled;
/* Configure SR */
ret = sr_class->configure(sr);
if (ret)
- return ret;
+ goto out_enabled;
sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
/* SRCONFIG - enable SR */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
+
+out_enabled:
+ sr->enabled = 1;
+
return 0;
}
@@ -621,7 +615,7 @@ void sr_disable(struct omap_sr *sr)
}
/* Check if SR clocks are already disabled. If yes do nothing */
- if (pm_runtime_suspended(&sr->pdev->dev))
+ if (!sr->enabled)
return;
/*
@@ -642,7 +636,8 @@ void sr_disable(struct omap_sr *sr)
}
}
- pm_runtime_put_sync_suspend(&sr->pdev->dev);
+ clk_disable(sr->fck);
+ sr->enabled = 0;
}
/**
@@ -851,8 +846,12 @@ static int omap_sr_probe(struct platform_device *pdev)
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ sr_info->fck = devm_clk_get(pdev->dev.parent, "fck");
+ if (IS_ERR(sr_info->fck))
+ return PTR_ERR(sr_info->fck);
+ clk_prepare(sr_info->fck);
+
pm_runtime_enable(&pdev->dev);
- pm_runtime_irq_safe(&pdev->dev);
snprintf(sr_info->name, SMARTREFLEX_NAME_LEN, "%s", pdata->name);
@@ -878,12 +877,6 @@ static int omap_sr_probe(struct platform_device *pdev)
list_add(&sr_info->node, &sr_list);
- ret = pm_runtime_get_sync(&pdev->dev);
- if (ret < 0) {
- pm_runtime_put_noidle(&pdev->dev);
- goto err_list_del;
- }
-
/*
* Call into late init to do initializations that require
* both sr driver and sr class driver to be initiallized.
@@ -933,16 +926,13 @@ static int omap_sr_probe(struct platform_device *pdev)
}
- pm_runtime_put_sync(&pdev->dev);
-
return ret;
err_debugfs:
debugfs_remove_recursive(sr_info->dbg_dir);
err_list_del:
list_del(&sr_info->node);
-
- pm_runtime_put_sync(&pdev->dev);
+ clk_unprepare(sr_info->fck);
return ret;
}
@@ -950,6 +940,7 @@ err_list_del:
static int omap_sr_remove(struct platform_device *pdev)
{
struct omap_sr_data *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
struct omap_sr *sr_info;
if (!pdata) {
@@ -968,7 +959,8 @@ static int omap_sr_remove(struct platform_device *pdev)
sr_stop_vddautocomp(sr_info);
debugfs_remove_recursive(sr_info->dbg_dir);
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(dev);
+ clk_unprepare(sr_info->fck);
list_del(&sr_info->node);
return 0;
}
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 3e6d4addac2f..1b115734a8f6 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -390,7 +390,10 @@ sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
if (ret < 0)
return ret;
- return sdw_transfer(slave->bus, &msg);
+ ret = sdw_transfer(slave->bus, &msg);
+ if (slave->is_mockup_device)
+ ret = 0;
+ return ret;
}
static int
@@ -404,7 +407,10 @@ sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val)
if (ret < 0)
return ret;
- return sdw_transfer(slave->bus, &msg);
+ ret = sdw_transfer(slave->bus, &msg);
+ if (slave->is_mockup_device)
+ ret = 0;
+ return ret;
}
int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value)
@@ -896,7 +902,8 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num)
do {
val = sdw_bread_no_pm(bus, dev_num, SDW_SCP_STAT);
if (val < 0) {
- dev_err(bus->dev, "SDW_SCP_STAT bread failed:%d\n", val);
+ if (val != -ENODATA)
+ dev_err(bus->dev, "SDW_SCP_STAT bread failed:%d\n", val);
return val;
}
val &= SDW_SCP_STAT_CLK_STP_NF;
@@ -1853,6 +1860,7 @@ void sdw_clear_slave_status(struct sdw_bus *bus, u32 request)
if (slave->status != SDW_SLAVE_UNATTACHED) {
sdw_modify_slave_status(slave, SDW_SLAVE_UNATTACHED);
slave->first_interrupt_done = false;
+ sdw_update_slave_status(slave, SDW_SLAVE_UNATTACHED);
}
/* keep track of request, used in pm_runtime resume */
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index 25950422b085..4fcc3ba93004 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -450,6 +450,40 @@ static int cdns_parity_error_injection(void *data, u64 value)
DEFINE_DEBUGFS_ATTRIBUTE(cdns_parity_error_fops, NULL,
cdns_parity_error_injection, "%llu\n");
+static int cdns_set_pdi_loopback_source(void *data, u64 value)
+{
+ struct sdw_cdns *cdns = data;
+ unsigned int pdi_out_num = cdns->pcm.num_bd + cdns->pcm.num_out;
+
+ if (value > pdi_out_num)
+ return -EINVAL;
+
+ /* Userspace changed the hardware state behind the kernel's back */
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+
+ cdns->pdi_loopback_source = value;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(cdns_pdi_loopback_source_fops, NULL, cdns_set_pdi_loopback_source, "%llu\n");
+
+static int cdns_set_pdi_loopback_target(void *data, u64 value)
+{
+ struct sdw_cdns *cdns = data;
+ unsigned int pdi_in_num = cdns->pcm.num_bd + cdns->pcm.num_in;
+
+ if (value > pdi_in_num)
+ return -EINVAL;
+
+ /* Userspace changed the hardware state behind the kernel's back */
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+
+ cdns->pdi_loopback_target = value;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(cdns_pdi_loopback_target_fops, NULL, cdns_set_pdi_loopback_target, "%llu\n");
+
/**
* sdw_cdns_debugfs_init() - Cadence debugfs init
* @cdns: Cadence instance
@@ -464,6 +498,16 @@ void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
debugfs_create_file("cdns-parity-error-injection", 0200, root, cdns,
&cdns_parity_error_fops);
+
+ cdns->pdi_loopback_source = -1;
+ cdns->pdi_loopback_target = -1;
+
+ debugfs_create_file("cdns-pdi-loopback-source", 0200, root, cdns,
+ &cdns_pdi_loopback_source_fops);
+
+ debugfs_create_file("cdns-pdi-loopback-target", 0200, root, cdns,
+ &cdns_pdi_loopback_target_fops);
+
}
EXPORT_SYMBOL_GPL(sdw_cdns_debugfs_init);
@@ -822,7 +866,6 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
{
struct sdw_cdns *cdns = dev_id;
u32 int_status;
- int ret = IRQ_HANDLED;
/* Check if the link is up */
if (!cdns->link_up)
@@ -900,7 +943,7 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
}
cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status);
- return ret;
+ return IRQ_HANDLED;
}
EXPORT_SYMBOL(sdw_cdns_irq);
@@ -936,6 +979,49 @@ static void cdns_update_slave_status_work(struct work_struct *work)
}
+/* paranoia check to make sure self-cleared bits are indeed cleared */
+void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string,
+ bool initial_delay, int reset_iterations)
+{
+ u32 mcp_control;
+ u32 mcp_config_update;
+ int i;
+
+ if (initial_delay)
+ usleep_range(1000, 1500);
+
+ mcp_control = cdns_readl(cdns, CDNS_MCP_CONTROL);
+
+ /* the following bits should be cleared immediately */
+ if (mcp_control & CDNS_MCP_CONTROL_CMD_RST)
+ dev_err(cdns->dev, "%s failed: MCP_CONTROL_CMD_RST is not cleared\n", string);
+ if (mcp_control & CDNS_MCP_CONTROL_SOFT_RST)
+ dev_err(cdns->dev, "%s failed: MCP_CONTROL_SOFT_RST is not cleared\n", string);
+ if (mcp_control & CDNS_MCP_CONTROL_SW_RST)
+ dev_err(cdns->dev, "%s failed: MCP_CONTROL_SW_RST is not cleared\n", string);
+ if (mcp_control & CDNS_MCP_CONTROL_CLK_STOP_CLR)
+ dev_err(cdns->dev, "%s failed: MCP_CONTROL_CLK_STOP_CLR is not cleared\n", string);
+ mcp_config_update = cdns_readl(cdns, CDNS_MCP_CONFIG_UPDATE);
+ if (mcp_config_update & CDNS_MCP_CONFIG_UPDATE_BIT)
+ dev_err(cdns->dev, "%s failed: MCP_CONFIG_UPDATE_BIT is not cleared\n", string);
+
+ i = 0;
+ while (mcp_control & CDNS_MCP_CONTROL_HW_RST) {
+ if (i == reset_iterations) {
+ dev_err(cdns->dev, "%s failed: MCP_CONTROL_HW_RST is not cleared\n", string);
+ break;
+ }
+
+ dev_dbg(cdns->dev, "%s: MCP_CONTROL_HW_RST is not cleared at iteration %d\n", string, i);
+ i++;
+
+ usleep_range(1000, 1500);
+ mcp_control = cdns_readl(cdns, CDNS_MCP_CONTROL);
+ }
+
+}
+EXPORT_SYMBOL(sdw_cdns_check_self_clearing_bits);
+
/*
* init routines
*/
@@ -946,10 +1032,7 @@ static void cdns_update_slave_status_work(struct work_struct *work)
*/
int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
{
- /* program maximum length reset to be safe */
- cdns_updatel(cdns, CDNS_MCP_CONTROL,
- CDNS_MCP_CONTROL_RST_DELAY,
- CDNS_MCP_CONTROL_RST_DELAY);
+ /* keep reset delay unchanged to 4096 cycles */
/* use hardware generated reset */
cdns_updatel(cdns, CDNS_MCP_CONTROL,
@@ -1213,6 +1296,8 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
cdns_init_clock_ctrl(cdns);
+ sdw_cdns_check_self_clearing_bits(cdns, __func__, false, 0);
+
/* reset msg_count to default value of FIFOLEVEL */
cdns->msg_count = cdns_readl(cdns, CDNS_MCP_FIFOLEVEL);
@@ -1286,20 +1371,37 @@ static int cdns_port_params(struct sdw_bus *bus,
struct sdw_port_params *p_params, unsigned int bank)
{
struct sdw_cdns *cdns = bus_to_cdns(bus);
- int dpn_config = 0, dpn_config_off;
+ int dpn_config_off_source;
+ int dpn_config_off_target;
+ int target_num = p_params->num;
+ int source_num = p_params->num;
+ bool override = false;
+ int dpn_config;
+
+ if (target_num == cdns->pdi_loopback_target &&
+ cdns->pdi_loopback_source != -1) {
+ source_num = cdns->pdi_loopback_source;
+ override = true;
+ }
- if (bank)
- dpn_config_off = CDNS_DPN_B1_CONFIG(p_params->num);
- else
- dpn_config_off = CDNS_DPN_B0_CONFIG(p_params->num);
+ if (bank) {
+ dpn_config_off_source = CDNS_DPN_B1_CONFIG(source_num);
+ dpn_config_off_target = CDNS_DPN_B1_CONFIG(target_num);
+ } else {
+ dpn_config_off_source = CDNS_DPN_B0_CONFIG(source_num);
+ dpn_config_off_target = CDNS_DPN_B0_CONFIG(target_num);
+ }
- dpn_config = cdns_readl(cdns, dpn_config_off);
+ dpn_config = cdns_readl(cdns, dpn_config_off_source);
- u32p_replace_bits(&dpn_config, (p_params->bps - 1), CDNS_DPN_CONFIG_WL);
- u32p_replace_bits(&dpn_config, p_params->flow_mode, CDNS_DPN_CONFIG_PORT_FLOW);
- u32p_replace_bits(&dpn_config, p_params->data_mode, CDNS_DPN_CONFIG_PORT_DAT);
+ /* use port params if there is no loopback, otherwise use source as is */
+ if (!override) {
+ u32p_replace_bits(&dpn_config, p_params->bps - 1, CDNS_DPN_CONFIG_WL);
+ u32p_replace_bits(&dpn_config, p_params->flow_mode, CDNS_DPN_CONFIG_PORT_FLOW);
+ u32p_replace_bits(&dpn_config, p_params->data_mode, CDNS_DPN_CONFIG_PORT_DAT);
+ }
- cdns_writel(cdns, dpn_config_off, dpn_config);
+ cdns_writel(cdns, dpn_config_off_target, dpn_config);
return 0;
}
@@ -1309,11 +1411,27 @@ static int cdns_transport_params(struct sdw_bus *bus,
enum sdw_reg_bank bank)
{
struct sdw_cdns *cdns = bus_to_cdns(bus);
- int dpn_offsetctrl = 0, dpn_offsetctrl_off;
- int dpn_config = 0, dpn_config_off;
- int dpn_hctrl = 0, dpn_hctrl_off;
- int num = t_params->port_num;
- int dpn_samplectrl_off;
+ int dpn_config;
+ int dpn_config_off_source;
+ int dpn_config_off_target;
+ int dpn_hctrl;
+ int dpn_hctrl_off_source;
+ int dpn_hctrl_off_target;
+ int dpn_offsetctrl;
+ int dpn_offsetctrl_off_source;
+ int dpn_offsetctrl_off_target;
+ int dpn_samplectrl;
+ int dpn_samplectrl_off_source;
+ int dpn_samplectrl_off_target;
+ int source_num = t_params->port_num;
+ int target_num = t_params->port_num;
+ bool override = false;
+
+ if (target_num == cdns->pdi_loopback_target &&
+ cdns->pdi_loopback_source != -1) {
+ source_num = cdns->pdi_loopback_source;
+ override = true;
+ }
/*
* Note: Only full data port is supported on the Master side for
@@ -1321,32 +1439,59 @@ static int cdns_transport_params(struct sdw_bus *bus,
*/
if (bank) {
- dpn_config_off = CDNS_DPN_B1_CONFIG(num);
- dpn_samplectrl_off = CDNS_DPN_B1_SAMPLE_CTRL(num);
- dpn_hctrl_off = CDNS_DPN_B1_HCTRL(num);
- dpn_offsetctrl_off = CDNS_DPN_B1_OFFSET_CTRL(num);
+ dpn_config_off_source = CDNS_DPN_B1_CONFIG(source_num);
+ dpn_hctrl_off_source = CDNS_DPN_B1_HCTRL(source_num);
+ dpn_offsetctrl_off_source = CDNS_DPN_B1_OFFSET_CTRL(source_num);
+ dpn_samplectrl_off_source = CDNS_DPN_B1_SAMPLE_CTRL(source_num);
+
+ dpn_config_off_target = CDNS_DPN_B1_CONFIG(target_num);
+ dpn_hctrl_off_target = CDNS_DPN_B1_HCTRL(target_num);
+ dpn_offsetctrl_off_target = CDNS_DPN_B1_OFFSET_CTRL(target_num);
+ dpn_samplectrl_off_target = CDNS_DPN_B1_SAMPLE_CTRL(target_num);
+
} else {
- dpn_config_off = CDNS_DPN_B0_CONFIG(num);
- dpn_samplectrl_off = CDNS_DPN_B0_SAMPLE_CTRL(num);
- dpn_hctrl_off = CDNS_DPN_B0_HCTRL(num);
- dpn_offsetctrl_off = CDNS_DPN_B0_OFFSET_CTRL(num);
+ dpn_config_off_source = CDNS_DPN_B0_CONFIG(source_num);
+ dpn_hctrl_off_source = CDNS_DPN_B0_HCTRL(source_num);
+ dpn_offsetctrl_off_source = CDNS_DPN_B0_OFFSET_CTRL(source_num);
+ dpn_samplectrl_off_source = CDNS_DPN_B0_SAMPLE_CTRL(source_num);
+
+ dpn_config_off_target = CDNS_DPN_B0_CONFIG(target_num);
+ dpn_hctrl_off_target = CDNS_DPN_B0_HCTRL(target_num);
+ dpn_offsetctrl_off_target = CDNS_DPN_B0_OFFSET_CTRL(target_num);
+ dpn_samplectrl_off_target = CDNS_DPN_B0_SAMPLE_CTRL(target_num);
}
- dpn_config = cdns_readl(cdns, dpn_config_off);
- u32p_replace_bits(&dpn_config, t_params->blk_grp_ctrl, CDNS_DPN_CONFIG_BGC);
- u32p_replace_bits(&dpn_config, t_params->blk_pkg_mode, CDNS_DPN_CONFIG_BPM);
- cdns_writel(cdns, dpn_config_off, dpn_config);
+ dpn_config = cdns_readl(cdns, dpn_config_off_source);
+ if (!override) {
+ u32p_replace_bits(&dpn_config, t_params->blk_grp_ctrl, CDNS_DPN_CONFIG_BGC);
+ u32p_replace_bits(&dpn_config, t_params->blk_pkg_mode, CDNS_DPN_CONFIG_BPM);
+ }
+ cdns_writel(cdns, dpn_config_off_target, dpn_config);
- u32p_replace_bits(&dpn_offsetctrl, t_params->offset1, CDNS_DPN_OFFSET_CTRL_1);
- u32p_replace_bits(&dpn_offsetctrl, t_params->offset2, CDNS_DPN_OFFSET_CTRL_2);
- cdns_writel(cdns, dpn_offsetctrl_off, dpn_offsetctrl);
+ if (!override) {
+ dpn_offsetctrl = 0;
+ u32p_replace_bits(&dpn_offsetctrl, t_params->offset1, CDNS_DPN_OFFSET_CTRL_1);
+ u32p_replace_bits(&dpn_offsetctrl, t_params->offset2, CDNS_DPN_OFFSET_CTRL_2);
+ } else {
+ dpn_offsetctrl = cdns_readl(cdns, dpn_offsetctrl_off_source);
+ }
+ cdns_writel(cdns, dpn_offsetctrl_off_target, dpn_offsetctrl);
- u32p_replace_bits(&dpn_hctrl, t_params->hstart, CDNS_DPN_HCTRL_HSTART);
- u32p_replace_bits(&dpn_hctrl, t_params->hstop, CDNS_DPN_HCTRL_HSTOP);
- u32p_replace_bits(&dpn_hctrl, t_params->lane_ctrl, CDNS_DPN_HCTRL_LCTRL);
+ if (!override) {
+ dpn_hctrl = 0;
+ u32p_replace_bits(&dpn_hctrl, t_params->hstart, CDNS_DPN_HCTRL_HSTART);
+ u32p_replace_bits(&dpn_hctrl, t_params->hstop, CDNS_DPN_HCTRL_HSTOP);
+ u32p_replace_bits(&dpn_hctrl, t_params->lane_ctrl, CDNS_DPN_HCTRL_LCTRL);
+ } else {
+ dpn_hctrl = cdns_readl(cdns, dpn_hctrl_off_source);
+ }
+ cdns_writel(cdns, dpn_hctrl_off_target, dpn_hctrl);
- cdns_writel(cdns, dpn_hctrl_off, dpn_hctrl);
- cdns_writel(cdns, dpn_samplectrl_off, (t_params->sample_interval - 1));
+ if (!override)
+ dpn_samplectrl = t_params->sample_interval - 1;
+ else
+ dpn_samplectrl = cdns_readl(cdns, dpn_samplectrl_off_source);
+ cdns_writel(cdns, dpn_samplectrl_off_target, dpn_samplectrl);
return 0;
}
@@ -1397,6 +1542,8 @@ int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake)
struct sdw_slave *slave;
int ret;
+ sdw_cdns_check_self_clearing_bits(cdns, __func__, false, 0);
+
/* Check suspend status */
if (sdw_cdns_is_clock_stop(cdns)) {
dev_dbg(cdns->dev, "Clock is already stopped\n");
diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h
index 0e7f8b35bb21..e587aede63bf 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -129,6 +129,9 @@ struct sdw_cdns {
struct sdw_cdns_streams pcm;
struct sdw_cdns_streams pdm;
+ int pdi_loopback_source;
+ int pdi_loopback_target;
+
void __iomem *registers;
bool link_up;
@@ -184,4 +187,8 @@ int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params);
int cdns_set_sdw_stream(struct snd_soc_dai *dai,
void *stream, bool pcm, int direction);
+
+void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string,
+ bool initial_delay, int reset_iterations);
+
#endif /* __SDW_CADENCE_H */
diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
index 5db0a2443a1d..0ca2a3e3a02e 100644
--- a/drivers/soundwire/dmi-quirks.c
+++ b/drivers/soundwire/dmi-quirks.c
@@ -16,18 +16,18 @@ struct adr_remap {
};
/*
- * HP Spectre 360 Convertible devices do not expose the correct _ADR
- * in the DSDT.
+ * Some TigerLake devices based on an initial Intel BIOS do not expose
+ * the correct _ADR in the DSDT.
* Remap the bad _ADR values to the ones reported by hardware
*/
-static const struct adr_remap hp_spectre_360[] = {
+static const struct adr_remap intel_tgl_bios[] = {
{
- 0x000010025D070100,
- 0x000020025D071100
+ 0x000010025D070100ull,
+ 0x000020025D071100ull
},
{
- 0x000110025d070100,
- 0x000120025D130800
+ 0x000110025d070100ull,
+ 0x000120025D130800ull
},
{}
};
@@ -39,18 +39,18 @@ static const struct adr_remap hp_spectre_360[] = {
static const struct adr_remap dell_sku_0A3E[] = {
/* rt715 on link0 */
{
- 0x00020025d071100,
- 0x00021025d071500
+ 0x00020025d071100ull,
+ 0x00021025d071500ull
},
/* rt711 on link1 */
{
- 0x000120025d130800,
- 0x000120025d071100,
+ 0x000120025d130800ull,
+ 0x000120025d071100ull,
},
/* rt1308 on link2 */
{
- 0x000220025d071500,
- 0x000220025d130800
+ 0x000220025d071500ull,
+ 0x000220025d130800ull
},
{}
};
@@ -61,7 +61,15 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"),
},
- .driver_data = (void *)hp_spectre_360,
+ .driver_data = (void *)intel_tgl_bios,
+ },
+ {
+ /* quirk used for NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
+ },
+ .driver_data = (void *)intel_tgl_bios,
},
{
.matches = {
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index c11e3d8cd308..78037ffdb09b 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -23,6 +23,7 @@
#include "intel.h"
#define INTEL_MASTER_SUSPEND_DELAY_MS 3000
+#define INTEL_MASTER_RESET_ITERATIONS 10
/*
* debug/config flags for the Intel SoundWire Master.
@@ -40,80 +41,6 @@ static int md_flags;
module_param_named(sdw_md_flags, md_flags, int, 0444);
MODULE_PARM_DESC(sdw_md_flags, "SoundWire Intel Master device flags (0x0 all off)");
-/* Intel SHIM Registers Definition */
-#define SDW_SHIM_LCAP 0x0
-#define SDW_SHIM_LCTL 0x4
-#define SDW_SHIM_IPPTR 0x8
-#define SDW_SHIM_SYNC 0xC
-
-#define SDW_SHIM_CTLSCAP(x) (0x010 + 0x60 * (x))
-#define SDW_SHIM_CTLS0CM(x) (0x012 + 0x60 * (x))
-#define SDW_SHIM_CTLS1CM(x) (0x014 + 0x60 * (x))
-#define SDW_SHIM_CTLS2CM(x) (0x016 + 0x60 * (x))
-#define SDW_SHIM_CTLS3CM(x) (0x018 + 0x60 * (x))
-#define SDW_SHIM_PCMSCAP(x) (0x020 + 0x60 * (x))
-
-#define SDW_SHIM_PCMSYCHM(x, y) (0x022 + (0x60 * (x)) + (0x2 * (y)))
-#define SDW_SHIM_PCMSYCHC(x, y) (0x042 + (0x60 * (x)) + (0x2 * (y)))
-#define SDW_SHIM_PDMSCAP(x) (0x062 + 0x60 * (x))
-#define SDW_SHIM_IOCTL(x) (0x06C + 0x60 * (x))
-#define SDW_SHIM_CTMCTL(x) (0x06E + 0x60 * (x))
-
-#define SDW_SHIM_WAKEEN 0x190
-#define SDW_SHIM_WAKESTS 0x192
-
-#define SDW_SHIM_LCTL_SPA BIT(0)
-#define SDW_SHIM_LCTL_SPA_MASK GENMASK(3, 0)
-#define SDW_SHIM_LCTL_CPA BIT(8)
-#define SDW_SHIM_LCTL_CPA_MASK GENMASK(11, 8)
-
-#define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
-#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
-#define SDW_SHIM_SYNC_SYNCPRD GENMASK(14, 0)
-#define SDW_SHIM_SYNC_SYNCCPU BIT(15)
-#define SDW_SHIM_SYNC_CMDSYNC_MASK GENMASK(19, 16)
-#define SDW_SHIM_SYNC_CMDSYNC BIT(16)
-#define SDW_SHIM_SYNC_SYNCGO BIT(24)
-
-#define SDW_SHIM_PCMSCAP_ISS GENMASK(3, 0)
-#define SDW_SHIM_PCMSCAP_OSS GENMASK(7, 4)
-#define SDW_SHIM_PCMSCAP_BSS GENMASK(12, 8)
-
-#define SDW_SHIM_PCMSYCM_LCHN GENMASK(3, 0)
-#define SDW_SHIM_PCMSYCM_HCHN GENMASK(7, 4)
-#define SDW_SHIM_PCMSYCM_STREAM GENMASK(13, 8)
-#define SDW_SHIM_PCMSYCM_DIR BIT(15)
-
-#define SDW_SHIM_PDMSCAP_ISS GENMASK(3, 0)
-#define SDW_SHIM_PDMSCAP_OSS GENMASK(7, 4)
-#define SDW_SHIM_PDMSCAP_BSS GENMASK(12, 8)
-#define SDW_SHIM_PDMSCAP_CPSS GENMASK(15, 13)
-
-#define SDW_SHIM_IOCTL_MIF BIT(0)
-#define SDW_SHIM_IOCTL_CO BIT(1)
-#define SDW_SHIM_IOCTL_COE BIT(2)
-#define SDW_SHIM_IOCTL_DO BIT(3)
-#define SDW_SHIM_IOCTL_DOE BIT(4)
-#define SDW_SHIM_IOCTL_BKE BIT(5)
-#define SDW_SHIM_IOCTL_WPDD BIT(6)
-#define SDW_SHIM_IOCTL_CIBD BIT(8)
-#define SDW_SHIM_IOCTL_DIBD BIT(9)
-
-#define SDW_SHIM_CTMCTL_DACTQE BIT(0)
-#define SDW_SHIM_CTMCTL_DODS BIT(1)
-#define SDW_SHIM_CTMCTL_DOAIS GENMASK(4, 3)
-
-#define SDW_SHIM_WAKEEN_ENABLE BIT(0)
-#define SDW_SHIM_WAKESTS_STATUS BIT(0)
-
-/* Intel ALH Register definitions */
-#define SDW_ALH_STRMZCFG(x) (0x000 + (0x4 * (x)))
-#define SDW_ALH_NUM_STREAMS 64
-
-#define SDW_ALH_STRMZCFG_DMAT_VAL 0x3
-#define SDW_ALH_STRMZCFG_DMAT GENMASK(7, 0)
-#define SDW_ALH_STRMZCFG_CHN GENMASK(19, 16)
-
enum intel_pdi_type {
INTEL_PDI_IN = 0,
INTEL_PDI_OUT = 1,
@@ -537,12 +464,14 @@ static int intel_link_power_down(struct sdw_intel *sdw)
mutex_lock(sdw->link_res->shim_lock);
- intel_shim_master_ip_to_glue(sdw);
-
if (!(*shim_mask & BIT(link_id)))
dev_err(sdw->cdns.dev,
"%s: Unbalanced power-up/down calls\n", __func__);
+ sdw->cdns.link_up = false;
+
+ intel_shim_master_ip_to_glue(sdw);
+
*shim_mask &= ~BIT(link_id);
if (!*shim_mask) {
@@ -559,18 +488,19 @@ static int intel_link_power_down(struct sdw_intel *sdw)
link_control &= spa_mask;
ret = intel_clear_bit(shim, SDW_SHIM_LCTL, link_control, cpa_mask);
+ if (ret < 0) {
+ dev_err(sdw->cdns.dev, "%s: could not power down link\n", __func__);
+
+ /*
+ * we leave the sdw->cdns.link_up flag as false since we've disabled
+ * the link at this point and cannot handle interrupts any longer.
+ */
+ }
}
mutex_unlock(sdw->link_res->shim_lock);
- if (ret < 0) {
- dev_err(sdw->cdns.dev, "%s: could not power down link\n", __func__);
-
- return ret;
- }
-
- sdw->cdns.link_up = false;
- return 0;
+ return ret;
}
static void intel_shim_sync_arm(struct sdw_intel *sdw)
@@ -1467,6 +1397,8 @@ int intel_link_startup(struct auxiliary_device *auxdev)
goto err_interrupt;
}
}
+ sdw_cdns_check_self_clearing_bits(cdns, __func__,
+ true, INTEL_MASTER_RESET_ITERATIONS);
/* Register DAIs */
ret = intel_register_dai(sdw);
@@ -1519,6 +1451,7 @@ int intel_link_startup(struct auxiliary_device *auxdev)
if (!(link_flags & SDW_INTEL_MASTER_DISABLE_PM_RUNTIME_IDLE))
pm_runtime_idle(dev);
+ sdw->startup_done = true;
return 0;
err_interrupt:
@@ -1558,8 +1491,9 @@ int intel_link_process_wakeen_event(struct auxiliary_device *auxdev)
sdw = dev_get_drvdata(dev);
bus = &sdw->cdns.bus;
- if (bus->prop.hw_disabled) {
- dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n", bus->link_id);
+ if (bus->prop.hw_disabled || !sdw->startup_done) {
+ dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n",
+ bus->link_id);
return 0;
}
@@ -1588,6 +1522,87 @@ int intel_link_process_wakeen_event(struct auxiliary_device *auxdev)
* PM calls
*/
+static int intel_resume_child_device(struct device *dev, void *data)
+{
+ int ret;
+ struct sdw_slave *slave = dev_to_sdw_dev(dev);
+
+ if (!slave->probed) {
+ dev_dbg(dev, "%s: skipping device, no probed driver\n", __func__);
+ return 0;
+ }
+ if (!slave->dev_num_sticky) {
+ dev_dbg(dev, "%s: skipping device, never detected on bus\n", __func__);
+ return 0;
+ }
+
+ ret = pm_request_resume(dev);
+ if (ret < 0)
+ dev_err(dev, "%s: pm_request_resume failed: %d\n", __func__, ret);
+
+ return ret;
+}
+
+static int __maybe_unused intel_pm_prepare(struct device *dev)
+{
+ struct sdw_cdns *cdns = dev_get_drvdata(dev);
+ struct sdw_intel *sdw = cdns_to_intel(cdns);
+ struct sdw_bus *bus = &cdns->bus;
+ u32 clock_stop_quirks;
+ int ret = 0;
+
+ if (bus->prop.hw_disabled || !sdw->startup_done) {
+ dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n",
+ bus->link_id);
+ return 0;
+ }
+
+ clock_stop_quirks = sdw->link_res->clock_stop_quirks;
+
+ if (pm_runtime_suspended(dev) &&
+ pm_runtime_suspended(dev->parent) &&
+ ((clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET) ||
+ !clock_stop_quirks)) {
+ /*
+ * if we've enabled clock stop, and the parent is suspended, the SHIM registers
+ * are not accessible and the shim wake cannot be disabled.
+ * The only solution is to resume the entire bus to full power
+ */
+
+ /*
+ * If any operation in this block fails, we keep going since we don't want
+ * to prevent system suspend from happening and errors should be recoverable
+ * on resume.
+ */
+
+ /*
+ * first resume the device for this link. This will also by construction
+ * resume the PCI parent device.
+ */
+ ret = pm_request_resume(dev);
+ if (ret < 0) {
+ dev_err(dev, "%s: pm_request_resume failed: %d\n", __func__, ret);
+ return 0;
+ }
+
+ /*
+ * Continue resuming the entire bus (parent + child devices) to exit
+ * the clock stop mode. If there are no devices connected on this link
+ * this is a no-op.
+ * The resume to full power could have been implemented with a .prepare
+ * step in SoundWire codec drivers. This would however require a lot
+ * of code to handle an Intel-specific corner case. It is simpler in
+ * practice to add a loop at the link level.
+ */
+ ret = device_for_each_child(bus->dev, NULL, intel_resume_child_device);
+
+ if (ret < 0)
+ dev_err(dev, "%s: intel_resume_child_device failed: %d\n", __func__, ret);
+ }
+
+ return 0;
+}
+
static int __maybe_unused intel_suspend(struct device *dev)
{
struct sdw_cdns *cdns = dev_get_drvdata(dev);
@@ -1596,8 +1611,8 @@ static int __maybe_unused intel_suspend(struct device *dev)
u32 clock_stop_quirks;
int ret;
- if (bus->prop.hw_disabled) {
- dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
+ if (bus->prop.hw_disabled || !sdw->startup_done) {
+ dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n",
bus->link_id);
return 0;
}
@@ -1607,19 +1622,18 @@ static int __maybe_unused intel_suspend(struct device *dev)
clock_stop_quirks = sdw->link_res->clock_stop_quirks;
- if ((clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET ||
- !clock_stop_quirks) &&
- !pm_runtime_suspended(dev->parent)) {
-
- /*
- * if we've enabled clock stop, and the parent
- * is still active, disable shim wake. The
- * SHIM registers are not accessible if the
- * parent is already pm_runtime suspended so
- * it's too late to change that configuration
- */
-
- intel_shim_wake(sdw, false);
+ if ((clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET) ||
+ !clock_stop_quirks) {
+
+ if (pm_runtime_suspended(dev->parent)) {
+ /*
+ * paranoia check: this should not happen with the .prepare
+ * resume to full power
+ */
+ dev_err(dev, "%s: invalid config: parent is suspended\n", __func__);
+ } else {
+ intel_shim_wake(sdw, false);
+ }
}
return 0;
@@ -1650,8 +1664,8 @@ static int __maybe_unused intel_suspend_runtime(struct device *dev)
u32 clock_stop_quirks;
int ret;
- if (bus->prop.hw_disabled) {
- dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
+ if (bus->prop.hw_disabled || !sdw->startup_done) {
+ dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n",
bus->link_id);
return 0;
}
@@ -1715,8 +1729,8 @@ static int __maybe_unused intel_resume(struct device *dev)
bool multi_link;
int ret;
- if (bus->prop.hw_disabled) {
- dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
+ if (bus->prop.hw_disabled || !sdw->startup_done) {
+ dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n",
bus->link_id);
return 0;
}
@@ -1783,6 +1797,8 @@ static int __maybe_unused intel_resume(struct device *dev)
return ret;
}
}
+ sdw_cdns_check_self_clearing_bits(cdns, __func__,
+ true, INTEL_MASTER_RESET_ITERATIONS);
/*
* after system resume, the pm_runtime suspend() may kick in
@@ -1811,8 +1827,8 @@ static int __maybe_unused intel_resume_runtime(struct device *dev)
int status;
int ret;
- if (bus->prop.hw_disabled) {
- dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
+ if (bus->prop.hw_disabled || !sdw->startup_done) {
+ dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n",
bus->link_id);
return 0;
}
@@ -1867,6 +1883,9 @@ static int __maybe_unused intel_resume_runtime(struct device *dev)
return ret;
}
}
+ sdw_cdns_check_self_clearing_bits(cdns, "intel_resume_runtime TEARDOWN",
+ true, INTEL_MASTER_RESET_ITERATIONS);
+
} else if (clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET) {
ret = intel_init(sdw);
if (ret) {
@@ -1940,6 +1959,9 @@ static int __maybe_unused intel_resume_runtime(struct device *dev)
}
}
}
+ sdw_cdns_check_self_clearing_bits(cdns, "intel_resume_runtime BUS_RESET",
+ true, INTEL_MASTER_RESET_ITERATIONS);
+
} else if (!clock_stop_quirks) {
clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns);
@@ -1963,6 +1985,9 @@ static int __maybe_unused intel_resume_runtime(struct device *dev)
dev_err(dev, "unable to resume master during resume\n");
return ret;
}
+
+ sdw_cdns_check_self_clearing_bits(cdns, "intel_resume_runtime no_quirks",
+ true, INTEL_MASTER_RESET_ITERATIONS);
} else {
dev_err(dev, "%s clock_stop_quirks %x unsupported\n",
__func__, clock_stop_quirks);
@@ -1973,6 +1998,7 @@ static int __maybe_unused intel_resume_runtime(struct device *dev)
}
static const struct dev_pm_ops intel_pm = {
+ .prepare = intel_pm_prepare,
SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)
SET_RUNTIME_PM_OPS(intel_suspend_runtime, intel_resume_runtime, NULL)
};
diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h
index 0b47b148da3f..cd93a44dba9a 100644
--- a/drivers/soundwire/intel.h
+++ b/drivers/soundwire/intel.h
@@ -41,6 +41,7 @@ struct sdw_intel {
struct sdw_cdns cdns;
int instance;
struct sdw_intel_link_res *link_res;
+ bool startup_done;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
#endif
diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c
index 9e283bef53d2..e329022e1669 100644
--- a/drivers/soundwire/intel_init.c
+++ b/drivers/soundwire/intel_init.c
@@ -18,12 +18,6 @@
#include "cadence_master.h"
#include "intel.h"
-#define SDW_SHIM_LCAP 0x0
-#define SDW_SHIM_BASE 0x2C000
-#define SDW_ALH_BASE 0x2C800
-#define SDW_LINK_BASE 0x30000
-#define SDW_LINK_SIZE 0x10000
-
static void intel_link_dev_release(struct device *dev)
{
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
@@ -69,8 +63,8 @@ static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *
link->mmio_base = res->mmio_base;
link->registers = res->mmio_base + SDW_LINK_BASE
+ (SDW_LINK_SIZE * link_id);
- link->shim = res->mmio_base + SDW_SHIM_BASE;
- link->alh = res->mmio_base + SDW_ALH_BASE;
+ link->shim = res->mmio_base + res->shim_base;
+ link->alh = res->mmio_base + res->alh_base;
link->ops = res->ops;
link->dev = res->dev;
@@ -220,6 +214,8 @@ static struct sdw_intel_ctx
}
ctx->mmio_base = res->mmio_base;
+ ctx->shim_base = res->shim_base;
+ ctx->alh_base = res->alh_base;
ctx->link_mask = res->link_mask;
ctx->handle = res->handle;
mutex_init(&ctx->shim_lock);
@@ -308,7 +304,7 @@ sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
return -EINVAL;
/* Check SNDWLCAP.LCOUNT */
- caps = ioread32(ctx->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP);
+ caps = ioread32(ctx->mmio_base + ctx->shim_base + SDW_SHIM_LCAP);
caps &= GENMASK(2, 0);
/* Check HW supported vs property value */
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index 1a18308f4ef4..5d4f6b308ef7 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -133,6 +133,9 @@ static int sdw_program_slave_port_params(struct sdw_bus *bus,
int ret;
u8 wbuf;
+ if (s_rt->slave->is_mockup_device)
+ return 0;
+
dpn_prop = sdw_get_slave_dpn_prop(s_rt->slave,
s_rt->direction,
t_params->port_num);
@@ -697,7 +700,7 @@ static int sdw_bank_switch(struct sdw_bus *bus, int m_rt_count)
else
ret = sdw_transfer(bus, wr_msg);
- if (ret < 0) {
+ if (ret < 0 && ret != -ENODATA) {
dev_err(bus->dev, "Slave frame_ctrl reg write failed\n");
goto error;
}
diff --git a/drivers/spi/spi-altera-dfl.c b/drivers/spi/spi-altera-dfl.c
index 39a3e1a032e0..44fc9ee13fc7 100644
--- a/drivers/spi/spi-altera-dfl.c
+++ b/drivers/spi/spi-altera-dfl.c
@@ -104,13 +104,6 @@ static const struct regmap_config indirect_regbus_cfg = {
.reg_read = indirect_bus_reg_read,
};
-static struct spi_board_info m10_bmc_info = {
- .modalias = "m10-d5005",
- .max_speed_hz = 12500000,
- .bus_num = 0,
- .chip_select = 0,
-};
-
static void config_spi_master(void __iomem *base, struct spi_master *master)
{
u64 v;
@@ -130,6 +123,7 @@ static void config_spi_master(void __iomem *base, struct spi_master *master)
static int dfl_spi_altera_probe(struct dfl_device *dfl_dev)
{
+ struct spi_board_info board_info = { 0 };
struct device *dev = &dfl_dev->dev;
struct spi_master *master;
struct altera_spi *hw;
@@ -170,9 +164,18 @@ static int dfl_spi_altera_probe(struct dfl_device *dfl_dev)
goto exit;
}
- if (!spi_new_device(master, &m10_bmc_info)) {
+ if (dfl_dev->revision == FME_FEATURE_REV_MAX10_SPI_N5010)
+ strscpy(board_info.modalias, "m10-n5010", SPI_NAME_SIZE);
+ else
+ strscpy(board_info.modalias, "m10-d5005", SPI_NAME_SIZE);
+
+ board_info.max_speed_hz = 12500000;
+ board_info.bus_num = 0;
+ board_info.chip_select = 0;
+
+ if (!spi_new_device(master, &board_info)) {
dev_err(dev, "%s failed to create SPI device: %s\n",
- __func__, m10_bmc_info.modalias);
+ __func__, board_info.modalias);
}
return 0;
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 8d8df51c5466..b2dd0a4d2446 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -77,6 +77,11 @@ struct spi_imx_devtype_data {
bool has_slavemode;
unsigned int fifo_size;
bool dynamic_burst;
+ /*
+ * ERR009165 fixed or not:
+ * https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf
+ */
+ bool tx_glitch_fixed;
enum spi_imx_devtype devtype;
};
@@ -622,8 +627,14 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->spi_bus_clk, &clk);
spi_imx->spi_bus_clk = clk;
- if (spi_imx->usedma)
+ /*
+ * ERR009165: work in XHC mode instead of SMC as PIO on the chips
+ * before i.mx6ul.
+ */
+ if (spi_imx->usedma && spi_imx->devtype_data->tx_glitch_fixed)
ctrl |= MX51_ECSPI_CTRL_SMC;
+ else
+ ctrl &= ~MX51_ECSPI_CTRL_SMC;
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
@@ -632,12 +643,16 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
static void mx51_setup_wml(struct spi_imx_data *spi_imx)
{
+ u32 tx_wml = 0;
+
+ if (spi_imx->devtype_data->tx_glitch_fixed)
+ tx_wml = spi_imx->wml;
/*
* Configure the DMA register: setup the watermark
* and enable DMA request.
*/
writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) |
- MX51_ECSPI_DMA_TX_WML(spi_imx->wml) |
+ MX51_ECSPI_DMA_TX_WML(tx_wml) |
MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) |
MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN |
MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA);
@@ -1028,6 +1043,23 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
.devtype = IMX53_ECSPI,
};
+static struct spi_imx_devtype_data imx6ul_ecspi_devtype_data = {
+ .intctrl = mx51_ecspi_intctrl,
+ .prepare_message = mx51_ecspi_prepare_message,
+ .prepare_transfer = mx51_ecspi_prepare_transfer,
+ .trigger = mx51_ecspi_trigger,
+ .rx_available = mx51_ecspi_rx_available,
+ .reset = mx51_ecspi_reset,
+ .setup_wml = mx51_setup_wml,
+ .fifo_size = 64,
+ .has_dmamode = true,
+ .dynamic_burst = true,
+ .has_slavemode = true,
+ .tx_glitch_fixed = true,
+ .disable = mx51_ecspi_disable,
+ .devtype = IMX51_ECSPI,
+};
+
static const struct of_device_id spi_imx_dt_ids[] = {
{ .compatible = "fsl,imx1-cspi", .data = &imx1_cspi_devtype_data, },
{ .compatible = "fsl,imx21-cspi", .data = &imx21_cspi_devtype_data, },
@@ -1036,6 +1068,7 @@ static const struct of_device_id spi_imx_dt_ids[] = {
{ .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, },
{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
{ .compatible = "fsl,imx53-ecspi", .data = &imx53_ecspi_devtype_data, },
+ { .compatible = "fsl,imx6ul-ecspi", .data = &imx6ul_ecspi_devtype_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spi_imx_dt_ids);
@@ -1249,10 +1282,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
{
int ret;
- /* use pio mode for i.mx6dl chip TKT238285 */
- if (of_machine_is_compatible("fsl,imx6dl"))
- return 0;
-
spi_imx->wml = spi_imx->devtype_data->fifo_size / 2;
/* Prepare for TX DMA: */
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 65d14af9c015..57e2499ec1ed 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -409,7 +409,7 @@ static int spi_probe(struct device *dev)
return ret;
}
-static int spi_remove(struct device *dev)
+static void spi_remove(struct device *dev)
{
const struct spi_driver *sdrv = to_spi_driver(dev->driver);
@@ -424,8 +424,6 @@ static int spi_remove(struct device *dev)
}
dev_pm_domain_detach(dev, true);
-
- return 0;
}
static void spi_shutdown(struct device *dev)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 24e9469ea35b..6dc29ce3b4bf 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -677,7 +677,6 @@ static struct class *spidev_class;
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
- { .compatible = "ge,achc" },
{ .compatible = "semtech,sx1301" },
{ .compatible = "lwn,bk4" },
{ .compatible = "dh,dhcom-board" },
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 51f5aeb65b3b..b37ead9e2fad 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -345,7 +345,7 @@ fail_probe:
return err;
}
-static int spmi_drv_remove(struct device *dev)
+static void spmi_drv_remove(struct device *dev)
{
const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
@@ -356,7 +356,6 @@ static int spmi_drv_remove(struct device *dev)
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
pm_runtime_put_noidle(dev);
- return 0;
}
static void spmi_drv_shutdown(struct device *dev)
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 3a29b5570f9f..8a93c83cb6f8 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -283,7 +283,7 @@ static void ssb_device_shutdown(struct device *dev)
ssb_drv->shutdown(ssb_dev);
}
-static int ssb_device_remove(struct device *dev)
+static void ssb_device_remove(struct device *dev)
{
struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
struct ssb_driver *ssb_drv = drv_to_ssb_drv(dev->driver);
@@ -291,8 +291,6 @@ static int ssb_device_remove(struct device *dev)
if (ssb_drv && ssb_drv->remove)
ssb_drv->remove(ssb_dev);
ssb_device_put(ssb_dev);
-
- return 0;
}
static int ssb_device_probe(struct device *dev)
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index c8eaae6412bb..e03627ad4460 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -36,7 +36,7 @@ source "drivers/staging/rtl8723bs/Kconfig"
source "drivers/staging/rtl8712/Kconfig"
-source "drivers/staging/rtl8188eu/Kconfig"
+source "drivers/staging/r8188eu/Kconfig"
source "drivers/staging/rts5208/Kconfig"
@@ -102,6 +102,4 @@ source "drivers/staging/qlge/Kconfig"
source "drivers/staging/wfx/Kconfig"
-source "drivers/staging/hikey9xx/Kconfig"
-
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 818b6f964369..c7f8d8d8dd11 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_RTL8723BS) += rtl8723bs/
obj-$(CONFIG_R8712U) += rtl8712/
-obj-$(CONFIG_R8188EU) += rtl8188eu/
+obj-$(CONFIG_R8188EU) += r8188eu/
obj-$(CONFIG_RTS5208) += rts5208/
obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
@@ -41,4 +41,3 @@ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/
obj-$(CONFIG_QLGE) += qlge/
obj-$(CONFIG_WFX) += wfx/
-obj-y += hikey9xx/
diff --git a/drivers/staging/board/board.c b/drivers/staging/board/board.c
index cb6feb34dd40..f980af037345 100644
--- a/drivers/staging/board/board.c
+++ b/drivers/staging/board/board.c
@@ -136,6 +136,7 @@ int __init board_staging_register_clock(const struct board_staging_clk *bsc)
static int board_staging_add_dev_domain(struct platform_device *pdev,
const char *domain)
{
+ struct device *dev = &pdev->dev;
struct of_phandle_args pd_args;
struct device_node *np;
@@ -148,7 +149,11 @@ static int board_staging_add_dev_domain(struct platform_device *pdev,
pd_args.np = np;
pd_args.args_count = 0;
- return of_genpd_add_device(&pd_args, &pdev->dev);
+ /* Initialization similar to device_pm_init_common() */
+ spin_lock_init(&dev->power.lock);
+ dev->power.early_init = true;
+
+ return of_genpd_add_device(&pd_args, dev);
}
#else
static inline int board_staging_add_dev_domain(struct platform_device *pdev,
diff --git a/drivers/staging/clocking-wizard/Kconfig b/drivers/staging/clocking-wizard/Kconfig
index 69cf51445f08..2324b5d73788 100644
--- a/drivers/staging/clocking-wizard/Kconfig
+++ b/drivers/staging/clocking-wizard/Kconfig
@@ -5,6 +5,6 @@
config COMMON_CLK_XLNX_CLKWZRD
tristate "Xilinx Clocking Wizard"
- depends on COMMON_CLK && OF && IOMEM
+ depends on COMMON_CLK && OF && HAS_IOMEM
help
Support for the Xilinx Clocking Wizard IP core clock generator.
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 3723269890d5..ed992ca605eb 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -992,9 +992,7 @@ out_free:
int fbtft_init_display(struct fbtft_par *par)
{
int buf[64];
- char msg[128];
- char str[16];
- int i = 0;
+ int i;
int j;
/* sanity check */
@@ -1005,9 +1003,11 @@ int fbtft_init_display(struct fbtft_par *par)
}
/* make sure stop marker exists */
- for (i = 0; i < FBTFT_MAX_INIT_SEQUENCE; i++)
+ for (i = 0; i < FBTFT_MAX_INIT_SEQUENCE; i++) {
if (par->init_sequence[i] == -3)
break;
+ }
+
if (i == FBTFT_MAX_INIT_SEQUENCE) {
dev_err(par->info->device,
"missing stop marker at end of init sequence\n");
@@ -1036,17 +1036,14 @@ int fbtft_init_display(struct fbtft_par *par)
switch (par->init_sequence[i]) {
case -1:
i++;
+
/* make debug message */
- strcpy(msg, "");
- j = i + 1;
- while (par->init_sequence[j] >= 0) {
- sprintf(str, "0x%02X ", par->init_sequence[j]);
- strcat(msg, str);
- j++;
- }
+ for (j = 0; par->init_sequence[i + 1 + j] >= 0; j++);
+
fbtft_par_dbg(DEBUG_INIT_DISPLAY, par,
- "init: write(0x%02X) %s\n",
- par->init_sequence[i], msg);
+ "init: write(0x%02X) %*ph\n",
+ par->init_sequence[i], j,
+ &par->init_sequence[i + 1]);
/* Write */
j = 0;
diff --git a/drivers/staging/fieldbus/anybuss/host.c b/drivers/staging/fieldbus/anybuss/host.c
index 0f730efe9a6d..8a75f6642c78 100644
--- a/drivers/staging/fieldbus/anybuss/host.c
+++ b/drivers/staging/fieldbus/anybuss/host.c
@@ -1186,15 +1186,13 @@ static int anybus_bus_probe(struct device *dev)
return adrv->probe(adev);
}
-static int anybus_bus_remove(struct device *dev)
+static void anybus_bus_remove(struct device *dev)
{
struct anybuss_client_driver *adrv =
to_anybuss_client_driver(dev->driver);
if (adrv->remove)
adrv->remove(to_anybuss_client(dev));
-
- return 0;
}
static struct bus_type anybus_bus = {
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index 38a280e876c2..e8fa7f53cd5e 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -2852,11 +2852,11 @@ unregister_loop:
tty_unregister_driver(fwloop_driver);
put_loop:
if (create_loop_dev)
- put_tty_driver(fwloop_driver);
+ tty_driver_kref_put(fwloop_driver);
unregister_driver:
tty_unregister_driver(fwtty_driver);
put_tty:
- put_tty_driver(fwtty_driver);
+ tty_driver_kref_put(fwtty_driver);
remove_debugfs:
debugfs_remove_recursive(fwserial_debugfs);
@@ -2871,10 +2871,10 @@ static void __exit fwserial_exit(void)
kmem_cache_destroy(fwtty_txn_cache);
if (create_loop_dev) {
tty_unregister_driver(fwloop_driver);
- put_tty_driver(fwloop_driver);
+ tty_driver_kref_put(fwloop_driver);
}
tty_unregister_driver(fwtty_driver);
- put_tty_driver(fwtty_driver);
+ tty_driver_kref_put(fwtty_driver);
debugfs_remove_recursive(fwserial_debugfs);
}
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
index 279de2cd9c4a..04df6f9f5403 100644
--- a/drivers/staging/gdm724x/gdm_tty.c
+++ b/drivers/staging/gdm724x/gdm_tty.c
@@ -281,9 +281,10 @@ int register_lte_tty_driver(void)
int ret;
for (i = 0; i < TTY_MAX_COUNT; i++) {
- tty_driver = alloc_tty_driver(GDM_TTY_MINOR);
- if (!tty_driver)
- return -ENOMEM;
+ tty_driver = tty_alloc_driver(GDM_TTY_MINOR,
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(tty_driver))
+ return PTR_ERR(tty_driver);
tty_driver->owner = THIS_MODULE;
tty_driver->driver_name = DRIVER_STRING[i];
@@ -291,8 +292,6 @@ int register_lte_tty_driver(void)
tty_driver->major = GDM_TTY_MAJOR;
tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
tty_driver->subtype = SERIAL_TYPE_NORMAL;
- tty_driver->flags = TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV;
tty_driver->init_termios = tty_std_termios;
tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
@@ -300,7 +299,7 @@ int register_lte_tty_driver(void)
ret = tty_register_driver(tty_driver);
if (ret) {
- put_tty_driver(tty_driver);
+ tty_driver_kref_put(tty_driver);
return ret;
}
@@ -319,7 +318,7 @@ void unregister_lte_tty_driver(void)
tty_driver = gdm_driver[i];
if (tty_driver) {
tty_unregister_driver(tty_driver);
- put_tty_driver(tty_driver);
+ tty_driver_kref_put(tty_driver);
}
}
}
diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c
index 7902e52a699b..8f39cc5617aa 100644
--- a/drivers/staging/gdm724x/netlink_k.c
+++ b/drivers/staging/gdm724x/netlink_k.c
@@ -19,8 +19,8 @@ static DEFINE_MUTEX(netlink_mutex);
#define ND_NLMSG_SPACE(len) (NLMSG_SPACE(len) + ND_IFINDEX_LEN)
#define ND_NLMSG_DATA(nlh) ((void *)((char *)NLMSG_DATA(nlh) + \
ND_IFINDEX_LEN))
-#define ND_NLMSG_S_LEN(len) (len + ND_IFINDEX_LEN)
-#define ND_NLMSG_R_LEN(nlh) (nlh->nlmsg_len - ND_IFINDEX_LEN)
+#define ND_NLMSG_S_LEN(len) ((len) + ND_IFINDEX_LEN)
+#define ND_NLMSG_R_LEN(nlh) ((nlh)->nlmsg_len - ND_IFINDEX_LEN)
#define ND_NLMSG_IFIDX(nlh) NLMSG_DATA(nlh)
#define ND_MAX_MSG_LEN (1024 * 32)
diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c
index 13d319860da5..5a5c17a4519b 100644
--- a/drivers/staging/greybus/gbphy.c
+++ b/drivers/staging/greybus/gbphy.c
@@ -169,7 +169,7 @@ static int gbphy_dev_probe(struct device *dev)
return ret;
}
-static int gbphy_dev_remove(struct device *dev)
+static void gbphy_dev_remove(struct device *dev)
{
struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver);
struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
@@ -180,8 +180,6 @@ static int gbphy_dev_remove(struct device *dev)
pm_runtime_set_suspended(dev);
pm_runtime_put_noidle(dev);
pm_runtime_dont_use_autosuspend(dev);
-
- return 0;
}
static struct bus_type gbphy_bus_type = {
diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c
index 73f01ed1e5b7..e6d860a9678e 100644
--- a/drivers/staging/greybus/uart.c
+++ b/drivers/staging/greybus/uart.c
@@ -973,7 +973,7 @@ static int gb_tty_init(void)
return 0;
fail_put_gb_tty:
- put_tty_driver(gb_tty_driver);
+ tty_driver_kref_put(gb_tty_driver);
fail_unregister_dev:
return retval;
}
@@ -981,7 +981,7 @@ fail_unregister_dev:
static void gb_tty_exit(void)
{
tty_unregister_driver(gb_tty_driver);
- put_tty_driver(gb_tty_driver);
+ tty_driver_kref_put(gb_tty_driver);
idr_destroy(&tty_minors);
}
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
deleted file mode 100644
index 9f53df9068fe..000000000000
--- a/drivers/staging/hikey9xx/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-# to be placed at drivers/mfd
-config MFD_HI6421_SPMI
- tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC"
- depends on HAS_IOMEM
- depends on OF
- depends on SPMI
- select MFD_CORE
- select REGMAP_SPMI
- help
- Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes
- multi-functions, such as regulators, RTC, codec, Coulomb counter,
- etc.
-
- This driver includes core APIs _only_. You have to select
- individual components like voltage regulators under corresponding
- menus in order to enable them.
- We communicate with the Hi6421v600 via a SPMI bus.
diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile
deleted file mode 100644
index e3108d7dd849..000000000000
--- a/drivers/staging/hikey9xx/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o
diff --git a/drivers/staging/hikey9xx/TODO b/drivers/staging/hikey9xx/TODO
deleted file mode 100644
index 65e7996a3066..000000000000
--- a/drivers/staging/hikey9xx/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-ToDo list:
-
-- Port other drivers needed by Hikey 960/970;
-- Test drivers on Hikey 960;
-- Validate device tree bindings.
diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
deleted file mode 100644
index 35ef3d4c760b..000000000000
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ /dev/null
@@ -1,311 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Device driver for regulators in HISI PMIC IC
- *
- * Copyright (c) 2013 Linaro Ltd.
- * Copyright (c) 2011 Hisilicon.
- * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
- */
-
-#include <linux/bitops.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/hi6421-spmi-pmic.h>
-#include <linux/module.h>
-#include <linux/of_gpio.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/spmi.h>
-
-enum hi6421_spmi_pmic_irq_list {
- OTMP = 0,
- VBUS_CONNECT,
- VBUS_DISCONNECT,
- ALARMON_R,
- HOLD_6S,
- HOLD_1S,
- POWERKEY_UP,
- POWERKEY_DOWN,
- OCP_SCP_R,
- COUL_R,
- SIM0_HPD_R,
- SIM0_HPD_F,
- SIM1_HPD_R,
- SIM1_HPD_F,
-
- PMIC_IRQ_LIST_MAX
-};
-
-#define HISI_IRQ_BANK_SIZE 2
-
-/*
- * IRQ number for the power key button and mask for both UP and DOWN IRQs
- */
-#define HISI_POWERKEY_IRQ_NUM 0
-#define HISI_IRQ_POWERKEY_UP_DOWN (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
-
-/*
- * Registers for IRQ address and IRQ mask bits
- *
- * Please notice that we need to regmap a larger region, as other
- * registers are used by the regulators.
- * See drivers/regulator/hi6421-regulator.c.
- */
-#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202
-#define SOC_PMIC_IRQ0_ADDR 0x0212
-
-/*
- * The IRQs are mapped as:
- *
- * ====================== ============= ============ =====
- * IRQ MASK REGISTER IRQ REGISTER BIT
- * ====================== ============= ============ =====
- * OTMP 0x0202 0x212 bit 0
- * VBUS_CONNECT 0x0202 0x212 bit 1
- * VBUS_DISCONNECT 0x0202 0x212 bit 2
- * ALARMON_R 0x0202 0x212 bit 3
- * HOLD_6S 0x0202 0x212 bit 4
- * HOLD_1S 0x0202 0x212 bit 5
- * POWERKEY_UP 0x0202 0x212 bit 6
- * POWERKEY_DOWN 0x0202 0x212 bit 7
- *
- * OCP_SCP_R 0x0203 0x213 bit 0
- * COUL_R 0x0203 0x213 bit 1
- * SIM0_HPD_R 0x0203 0x213 bit 2
- * SIM0_HPD_F 0x0203 0x213 bit 3
- * SIM1_HPD_R 0x0203 0x213 bit 4
- * SIM1_HPD_F 0x0203 0x213 bit 5
- * ====================== ============= ============ =====
- *
- * Each mask register contains 8 bits. The ancillary macros below
- * convert a number from 0 to 14 into a register address and a bit mask
- */
-#define HISI_IRQ_MASK_REG(irq_data) (SOC_PMIC_IRQ_MASK_0_ADDR + \
- (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
-#define HISI_IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
-#define HISI_8BITS_MASK 0xff
-
-static const struct mfd_cell hi6421v600_devs[] = {
- { .name = "hi6421v600-regulator", },
-};
-
-static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
-{
- struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
- unsigned long pending;
- unsigned int in;
- int i, offset;
-
- for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
- regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
-
- /* Mark pending IRQs as handled */
- regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, in);
-
- pending = in & HISI_8BITS_MASK;
-
- if (i == HISI_POWERKEY_IRQ_NUM &&
- (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
- /*
- * If both powerkey down and up IRQs are received,
- * handle them at the right order
- */
- generic_handle_irq(ddata->irqs[POWERKEY_DOWN]);
- generic_handle_irq(ddata->irqs[POWERKEY_UP]);
- pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
- }
-
- if (!pending)
- continue;
-
- for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
- generic_handle_irq(ddata->irqs[offset + i * BITS_PER_BYTE]);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static void hi6421_spmi_irq_mask(struct irq_data *d)
-{
- struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
- unsigned long flags;
- unsigned int data;
- u32 offset;
-
- offset = HISI_IRQ_MASK_REG(d);
-
- spin_lock_irqsave(&ddata->lock, flags);
-
- regmap_read(ddata->regmap, offset, &data);
- data |= HISI_IRQ_MASK_BIT(d);
- regmap_write(ddata->regmap, offset, data);
-
- spin_unlock_irqrestore(&ddata->lock, flags);
-}
-
-static void hi6421_spmi_irq_unmask(struct irq_data *d)
-{
- struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
- u32 data, offset;
- unsigned long flags;
-
- offset = HISI_IRQ_MASK_REG(d);
-
- spin_lock_irqsave(&ddata->lock, flags);
-
- regmap_read(ddata->regmap, offset, &data);
- data &= ~HISI_IRQ_MASK_BIT(d);
- regmap_write(ddata->regmap, offset, data);
-
- spin_unlock_irqrestore(&ddata->lock, flags);
-}
-
-static struct irq_chip hi6421_spmi_pmu_irqchip = {
- .name = "hi6421v600-irq",
- .irq_mask = hi6421_spmi_irq_mask,
- .irq_unmask = hi6421_spmi_irq_unmask,
- .irq_disable = hi6421_spmi_irq_mask,
- .irq_enable = hi6421_spmi_irq_unmask,
-};
-
-static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct hi6421_spmi_pmic *ddata = d->host_data;
-
- irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
- handle_simple_irq, "hi6421v600");
- irq_set_chip_data(virq, ddata);
- irq_set_irq_type(virq, IRQ_TYPE_NONE);
-
- return 0;
-}
-
-static const struct irq_domain_ops hi6421_spmi_domain_ops = {
- .map = hi6421_spmi_irq_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
-static void hi6421_spmi_pmic_irq_init(struct hi6421_spmi_pmic *ddata)
-{
- int i;
- unsigned int pending;
-
- /* Mask all IRQs */
- for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
- regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
- HISI_8BITS_MASK);
-
- /* Mark all IRQs as handled */
- for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
- regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
- regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i,
- HISI_8BITS_MASK);
- }
-}
-
-static const struct regmap_config regmap_config = {
- .reg_bits = 16,
- .val_bits = BITS_PER_BYTE,
- .max_register = 0xffff,
- .fast_io = true
-};
-
-static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- struct hi6421_spmi_pmic *ddata;
- unsigned int virq;
- int ret, i;
-
- ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
- if (!ddata)
- return -ENOMEM;
-
- ddata->regmap = devm_regmap_init_spmi_ext(pdev, &regmap_config);
- if (IS_ERR(ddata->regmap))
- return PTR_ERR(ddata->regmap);
-
- spin_lock_init(&ddata->lock);
-
- ddata->dev = dev;
-
- ddata->gpio = of_get_gpio(np, 0);
- if (ddata->gpio < 0)
- return ddata->gpio;
-
- if (!gpio_is_valid(ddata->gpio))
- return -EINVAL;
-
- ret = devm_gpio_request_one(dev, ddata->gpio, GPIOF_IN, "pmic");
- if (ret < 0) {
- dev_err(dev, "Failed to request gpio%d\n", ddata->gpio);
- return ret;
- }
-
- ddata->irq = gpio_to_irq(ddata->gpio);
-
- hi6421_spmi_pmic_irq_init(ddata);
-
- ddata->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
- if (!ddata->irqs)
- return -ENOMEM;
-
- ddata->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
- &hi6421_spmi_domain_ops, ddata);
- if (!ddata->domain) {
- dev_err(dev, "Failed to create IRQ domain\n");
- return -ENODEV;
- }
-
- for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
- virq = irq_create_mapping(ddata->domain, i);
- if (!virq) {
- dev_err(dev, "Failed to map H/W IRQ\n");
- return -ENODEV;
- }
- ddata->irqs[i] = virq;
- }
-
- ret = devm_request_threaded_irq(dev,
- ddata->irq, hi6421_spmi_irq_handler,
- NULL,
- IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
- "pmic", ddata);
- if (ret < 0) {
- dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
- ret);
- return ret;
- }
-
- dev_set_drvdata(&pdev->dev, ddata);
-
- ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
- hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
- NULL, 0, NULL);
- if (ret < 0)
- dev_err(dev, "Failed to add child devices: %d\n", ret);
-
- return ret;
-}
-
-static const struct of_device_id pmic_spmi_id_table[] = {
- { .compatible = "hisilicon,hi6421-spmi" },
- { }
-};
-MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
-
-static struct spmi_driver hi6421_spmi_pmic_driver = {
- .driver = {
- .name = "hi6421-spmi-pmic",
- .of_match_table = pmic_spmi_id_table,
- },
- .probe = hi6421_spmi_pmic_probe,
-};
-module_spmi_driver(hi6421_spmi_pmic_driver);
-
-MODULE_DESCRIPTION("HiSilicon Hi6421v600 SPMI PMIC driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c
index cbc0032c1604..98d759e7cc95 100644
--- a/drivers/staging/ks7010/ks7010_sdio.c
+++ b/drivers/staging/ks7010/ks7010_sdio.c
@@ -939,9 +939,9 @@ static void ks7010_private_init(struct ks_wlan_private *priv,
memset(&priv->wstats, 0, sizeof(priv->wstats));
/* sleep mode */
+ atomic_set(&priv->sleepstatus.status, 0);
atomic_set(&priv->sleepstatus.doze_request, 0);
atomic_set(&priv->sleepstatus.wakeup_request, 0);
- atomic_set(&priv->sleepstatus.wakeup_request, 0);
trx_device_init(priv);
hostif_init(priv);
diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c
index 09e7b4cd0138..631ad769c3d5 100644
--- a/drivers/staging/ks7010/ks_wlan_net.c
+++ b/drivers/staging/ks7010/ks_wlan_net.c
@@ -158,13 +158,13 @@ static int ks_wlan_get_name(struct net_device *dev,
/* for SLEEP MODE */
if (priv->dev_state < DEVICE_STATE_READY)
- strcpy(cwrq->name, "NOT READY!");
+ strscpy(cwrq->name, "NOT READY!", sizeof(cwrq->name));
else if (priv->reg.phy_type == D_11B_ONLY_MODE)
- strcpy(cwrq->name, "IEEE 802.11b");
+ strscpy(cwrq->name, "IEEE 802.11b", sizeof(cwrq->name));
else if (priv->reg.phy_type == D_11G_ONLY_MODE)
- strcpy(cwrq->name, "IEEE 802.11g");
+ strscpy(cwrq->name, "IEEE 802.11g", sizeof(cwrq->name));
else
- strcpy(cwrq->name, "IEEE 802.11b/g");
+ strscpy(cwrq->name, "IEEE 802.11b/g", sizeof(cwrq->name));
return 0;
}
@@ -1808,8 +1808,8 @@ static int ks_wlan_get_firmware_version(struct net_device *dev,
{
struct ks_wlan_private *priv = netdev_priv(dev);
- strcpy(extra, priv->firmware_version);
dwrq->length = priv->version_size + 1;
+ strscpy(extra, priv->firmware_version, dwrq->length);
return 0;
}
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
index 9363c1a52ae9..4d769590f2d3 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
@@ -849,21 +849,14 @@ static int gc2235_get_fmt(struct v4l2_subdev *sd,
static int gc2235_detect(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
- u16 high, low;
- int ret;
+ u16 high = 0, low = 0;
u16 id;
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
return -ENODEV;
- ret = gc2235_read_reg(client, GC2235_8BIT,
- GC2235_SENSOR_ID_H, &high);
- if (ret) {
- dev_err(&client->dev, "sensor_id_high = 0x%x\n", high);
- return -ENODEV;
- }
- ret = gc2235_read_reg(client, GC2235_8BIT,
- GC2235_SENSOR_ID_L, &low);
+ gc2235_read_reg(client, GC2235_8BIT, GC2235_SENSOR_ID_H, &high);
+ gc2235_read_reg(client, GC2235_8BIT, GC2235_SENSOR_ID_L, &low);
id = ((high << 8) | low);
if (id != GC2235_ID) {
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
index 11196180a206..49f4090856d3 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
@@ -570,14 +570,13 @@ static int power_down(struct v4l2_subdev *sd)
static int mt9m114_s_power(struct v4l2_subdev *sd, int power)
{
- if (power == 0) {
+ if (power == 0)
return power_down(sd);
- } else {
- if (power_up(sd))
- return -EINVAL;
- return mt9m114_init_common(sd);
- }
+ if (power_up(sd))
+ return -EINVAL;
+
+ return mt9m114_init_common(sd);
}
/*
@@ -1545,16 +1544,19 @@ static struct v4l2_ctrl_config mt9m114_controls[] = {
static int mt9m114_detect(struct mt9m114_device *dev, struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
- u32 retvalue;
+ u32 model;
+ int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "%s: i2c error", __func__);
return -ENODEV;
}
- mt9m114_read_reg(client, MISENSOR_16BIT, (u32)MT9M114_PID, &retvalue);
- dev->real_model_id = retvalue;
+ ret = mt9m114_read_reg(client, MISENSOR_16BIT, MT9M114_PID, &model);
+ if (ret)
+ return ret;
+ dev->real_model_id = model;
- if (retvalue != MT9M114_MOD_ID) {
+ if (model != MT9M114_MOD_ID) {
dev_err(&client->dev, "%s: failed: client->addr = %x\n",
__func__, client->addr);
return -ENODEV;
diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h
index 4d43b45915e5..874115f35fca 100644
--- a/drivers/staging/media/atomisp/i2c/ov2680.h
+++ b/drivers/staging/media/atomisp/i2c/ov2680.h
@@ -627,7 +627,7 @@ static struct ov2680_reg const ov2680_1296x976_30fps[] = {
{0x5706, 0x0c},
{0x5707, 0x78},
{0x3820, 0xc0},
- {0x3821, 0x00}, //miror/flip
+ {0x3821, 0x00}, //mirror/flip
// {0x5090, 0x0c},
{}
};
diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
index 0828ca9ab6f2..5e3670c4fc29 100644
--- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
+++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
@@ -932,7 +932,7 @@ err:
static int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- int ret = -EINVAL;
+ int ret;
u8 vcm_code;
ret = ad5823_i2c_read(client, AD5823_REG_VCM_CODE_MSB, &vcm_code);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h
index a60551450c45..c16eaf3d126f 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_compat.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h
@@ -83,8 +83,6 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
void ia_css_mmu_invalidate_cache(void);
-void ia_css_mmu_invalidate_cache(void);
-
int atomisp_css_start(struct atomisp_sub_device *asd,
enum ia_css_pipe_id pipe_id, bool in_reset);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
index f60198bb8a1a..99a632f33d2d 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
@@ -2102,9 +2102,6 @@ void atomisp_css_stop(struct atomisp_sub_device *asd,
enum ia_css_pipe_id pipe_id, bool in_reset)
{
struct atomisp_device *isp = asd->isp;
- struct atomisp_s3a_buf *s3a_buf;
- struct atomisp_dis_buf *dis_buf;
- struct atomisp_metadata_buf *md_buf;
unsigned long irqflags;
unsigned int i;
@@ -2144,42 +2141,17 @@ void atomisp_css_stop(struct atomisp_sub_device *asd,
}
/* move stats buffers to free queue list */
- while (!list_empty(&asd->s3a_stats_in_css)) {
- s3a_buf = list_entry(asd->s3a_stats_in_css.next,
- struct atomisp_s3a_buf, list);
- list_del(&s3a_buf->list);
- list_add_tail(&s3a_buf->list, &asd->s3a_stats);
- }
- while (!list_empty(&asd->s3a_stats_ready)) {
- s3a_buf = list_entry(asd->s3a_stats_ready.next,
- struct atomisp_s3a_buf, list);
- list_del(&s3a_buf->list);
- list_add_tail(&s3a_buf->list, &asd->s3a_stats);
- }
+ list_splice_init(&asd->s3a_stats_in_css, &asd->s3a_stats);
+ list_splice_init(&asd->s3a_stats_ready, &asd->s3a_stats);
spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
- while (!list_empty(&asd->dis_stats_in_css)) {
- dis_buf = list_entry(asd->dis_stats_in_css.next,
- struct atomisp_dis_buf, list);
- list_del(&dis_buf->list);
- list_add_tail(&dis_buf->list, &asd->dis_stats);
- }
+ list_splice_init(&asd->dis_stats_in_css, &asd->dis_stats);
asd->params.dis_proj_data_valid = false;
spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
- while (!list_empty(&asd->metadata_in_css[i])) {
- md_buf = list_entry(asd->metadata_in_css[i].next,
- struct atomisp_metadata_buf, list);
- list_del(&md_buf->list);
- list_add_tail(&md_buf->list, &asd->metadata[i]);
- }
- while (!list_empty(&asd->metadata_ready[i])) {
- md_buf = list_entry(asd->metadata_ready[i].next,
- struct atomisp_metadata_buf, list);
- list_del(&md_buf->list);
- list_add_tail(&md_buf->list, &asd->metadata[i]);
- }
+ list_splice_init(&asd->metadata_in_css[i], &asd->metadata[i]);
+ list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]);
}
atomisp_flush_params_queue(&asd->video_out_capture);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp_csi2.c
index 56456e59bf89..11b6b1216473 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_csi2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.c
@@ -28,7 +28,8 @@ static struct v4l2_mbus_framefmt *__csi2_get_format(struct
struct v4l2_subdev_state *sd_state,
enum
v4l2_subdev_format_whence
- which, unsigned int pad) {
+ which, unsigned int pad)
+{
if (which == V4L2_SUBDEV_FORMAT_TRY)
return v4l2_subdev_get_try_format(&csi2->subdev, sd_state,
pad);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c
index f670faf978e6..dcb571f515a7 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c
@@ -96,7 +96,7 @@ opt_err:
static ssize_t iunit_dbglvl_show(struct device_driver *drv, char *buf)
{
iunit_debug.dbglvl = dbg_level;
- return sprintf(buf, "dtrace level:%u\n", iunit_debug.dbglvl);
+ return sysfs_emit(buf, "dtrace level:%u\n", iunit_debug.dbglvl);
}
static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf,
@@ -115,7 +115,7 @@ static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf,
static ssize_t iunit_dbgfun_show(struct device_driver *drv, char *buf)
{
iunit_debug.dbgfun = atomisp_get_css_dbgfunc();
- return sprintf(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun);
+ return sysfs_emit(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun);
}
static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf,
@@ -139,7 +139,7 @@ static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf,
static ssize_t iunit_dbgopt_show(struct device_driver *drv, char *buf)
{
- return sprintf(buf, "option:0x%x\n", iunit_debug.dbgopt);
+ return sysfs_emit(buf, "option:0x%x\n", iunit_debug.dbgopt);
}
static ssize_t iunit_dbgopt_store(struct device_driver *drv, const char *buf,
diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
index 135994d44802..d8c9e31314b2 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
@@ -1040,10 +1040,10 @@ static struct camera_sensor_platform_data acpi_gmin_plat = {
.get_vcm_ctrl = gmin_get_vcm_ctrl,
};
-struct camera_sensor_platform_data *gmin_camera_platform_data(
- struct v4l2_subdev *subdev,
- enum atomisp_input_format csi_format,
- enum atomisp_bayer_order csi_bayer)
+struct camera_sensor_platform_data *
+gmin_camera_platform_data(struct v4l2_subdev *subdev,
+ enum atomisp_input_format csi_format,
+ enum atomisp_bayer_order csi_bayer)
{
u8 pmic_i2c_addr = gmin_detect_pmic(subdev);
struct gmin_subdev *gs;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
index 948769ca6539..1e324f1f656e 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
@@ -1763,7 +1763,8 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
if (err < 0)
goto register_entities_fail;
/* init atomisp wdts */
- if (init_atomisp_wdts(isp) != 0)
+ err = init_atomisp_wdts(isp);
+ if (err != 0)
goto wdt_work_queue_fail;
/* save the iunit context only once after all the values are init'ed. */
@@ -1815,6 +1816,7 @@ request_irq_fail:
hmm_cleanup();
hmm_pool_unregister(HMM_POOL_TYPE_RESERVED);
hmm_pool_fail:
+ pm_runtime_get_noresume(&pdev->dev);
destroy_workqueue(isp->wdt_work_queue);
wdt_work_queue_fail:
atomisp_acc_cleanup(isp);
diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c b/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c
index 0f5a231672a8..8e085dda0c18 100644
--- a/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c
+++ b/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c
@@ -174,8 +174,6 @@ void input_system_get_state(
ctrl_unit_get_state(ID, sub_id,
&state->ctrl_unit_state[sub_id - CTRL_UNIT0_ID]);
}
-
- return;
}
void receiver_get_state(
@@ -246,8 +244,6 @@ void receiver_get_state(
_HRT_CSS_RECEIVER_BE_IRQ_STATUS_REG_IDX);
state->be_irq_clear = receiver_reg_load(ID,
_HRT_CSS_RECEIVER_BE_IRQ_CLEAR_REG_IDX);
-
- return;
}
bool is_mipi_format_yuv420(
@@ -310,8 +306,6 @@ void receiver_set_compression(
reg = ((field_id < 6) ? (val << (field_id * 5)) : (val << ((
field_id - 6) * 5)));
receiver_reg_store(ID, addr, reg);
-
- return;
}
void receiver_port_enable(
@@ -330,7 +324,6 @@ void receiver_port_enable(
receiver_port_reg_store(ID, port_ID,
_HRT_CSS_RECEIVER_DEVICE_READY_REG_IDX, reg);
- return;
}
bool is_receiver_port_enabled(
@@ -349,7 +342,6 @@ void receiver_irq_enable(
{
receiver_port_reg_store(ID,
port_ID, _HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX, irq_info);
- return;
}
rx_irq_info_t receiver_get_irq_info(
@@ -367,7 +359,6 @@ void receiver_irq_clear(
{
receiver_port_reg_store(ID,
port_ID, _HRT_CSS_RECEIVER_IRQ_STATUS_REG_IDX, irq_info);
- return;
}
static inline void capture_unit_get_state(
@@ -428,8 +419,6 @@ static inline void capture_unit_get_state(
state->FSM_State_Info = input_system_sub_system_reg_load(ID,
sub_id,
CAPT_FSM_STATE_INFO_REG_ID);
-
- return;
}
static inline void acquisition_unit_get_state(
@@ -478,8 +467,6 @@ static inline void acquisition_unit_get_state(
state->Int_Cntr_Info = input_system_sub_system_reg_load(ID,
sub_id,
ACQ_INT_CNTR_INFO_REG_ID);
-
- return;
}
static inline void ctrl_unit_get_state(
@@ -561,8 +548,6 @@ static inline void ctrl_unit_get_state(
state->capt_reserve_one_mem_region = input_system_sub_system_reg_load(ID,
sub_id,
ISYS_CTRL_CAPT_RESERVE_ONE_MEM_REGION_REG_ID);
-
- return;
}
static inline void mipi_port_get_state(
@@ -597,8 +582,6 @@ static inline void mipi_port_get_state(
state->lane_sync_count[i] = (uint8_t)((state->sync_count) >> (i * 8));
state->lane_rx_count[i] = (uint8_t)((state->rx_count) >> (i * 8));
}
-
- return;
}
static inline void rx_channel_get_state(
@@ -652,8 +635,6 @@ static inline void rx_channel_get_state(
state->comp[i] = (mipi_compressor_t)(val & 0x07);
state->pred[i] = (mipi_predictor_t)((val & 0x18) >> 3);
}
-
- return;
}
// MW: "2400" in the name is not good, but this is to avoid a naming conflict
@@ -672,8 +653,6 @@ static void receiver_rst(
}
// AM: Additional actions for stopping receiver?
-
- return;
}
//Single function to reset all the devices mapped via GP_DEVICE.
@@ -722,8 +701,6 @@ static void gp_device_rst(const gp_device_ID_t ID)
// gp_device_reg_store(ID, _REG_GP_SYNCGEN_FRAME_CNT_ADDR, ZERO);
gp_device_reg_store(ID, _REG_GP_SOFT_RESET_ADDR,
ZERO); // AM: Maybe this soft reset is not safe.
-
- return;
}
static void input_selector_cfg_for_sensor(const gp_device_ID_t ID)
@@ -740,8 +717,6 @@ static void input_selector_cfg_for_sensor(const gp_device_ID_t ID)
gp_device_reg_store(ID, _REG_GP_ISEL_SBAND_SEL_ADDR, ZERO);
gp_device_reg_store(ID, _REG_GP_ISEL_SYNC_SEL_ADDR, ZERO);
gp_device_reg_store(ID, _REG_GP_SOFT_RESET_ADDR, ZERO);
-
- return;
}
static void input_switch_rst(const gp_device_ID_t ID)
@@ -760,8 +735,6 @@ static void input_switch_rst(const gp_device_ID_t ID)
gp_device_reg_store(ID,
_REG_GP_IFMT_input_switch_fsync_lut,
ZERO);
-
- return;
}
static void input_switch_cfg(
@@ -786,8 +759,6 @@ static void input_switch_cfg(
gp_device_reg_store(ID,
_REG_GP_IFMT_input_switch_fsync_lut,
cfg->vsync_data_reg);
-
- return;
}
static void input_system_network_rst(const input_system_ID_t ID)
@@ -843,8 +814,6 @@ static void input_system_network_rst(const input_system_ID_t ID)
ISYS_CTRL_INIT_REG_ID,
1U); //AM: Is there any named constant?
}
-
- return;
}
// Function that resets current configuration.
@@ -903,17 +872,10 @@ static input_system_err_t input_system_configure_channel(
error = input_system_configure_channel_sensor(channel);
break;
case INPUT_SYSTEM_SOURCE_TPG:
- return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
case INPUT_SYSTEM_SOURCE_PRBS:
- return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
case INPUT_SYSTEM_SOURCE_FIFO:
- return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
default:
return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
}
if (error != INPUT_SYSTEM_ERR_NO_ERROR) return error;
@@ -995,7 +957,6 @@ static input_system_err_t input_buffer_configuration(void)
default:
config.csi_buffer_flags[port] |= INPUT_SYSTEM_CFG_FLAG_CONFLICT;
return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
}
// Check acquisition buffer specified but set it later since it has to be unique.
@@ -1032,7 +993,6 @@ static input_system_err_t input_buffer_configuration(void)
default:
return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
}
} else {
config.csi_buffer_flags[port] = INPUT_SYSTEM_CFG_FLAG_BLOCKED;
@@ -1081,8 +1041,6 @@ static void capture_unit_configure(
sub_id,
CAPT_NUM_MEM_REGIONS_REG_ID,
cfg->nof_mem_regs);
-
- return;
}
static void acquisition_unit_configure(
@@ -1106,8 +1064,6 @@ static void acquisition_unit_configure(
sub_id,
ACQ_MEM_REGION_SIZE_REG_ID,
cfg->mem_reg_size);
-
- return;
}
static void ctrl_unit_configure(
@@ -1174,7 +1130,6 @@ static void ctrl_unit_configure(
sub_id,
ISYS_CTRL_CAPT_RESERVE_ONE_MEM_REGION_REG_ID,
0);
- return;
}
static void input_system_network_configure(
@@ -1232,8 +1187,6 @@ static void input_system_network_configure(
sub_id,
&cfg->ctrl_unit_cfg[sub_id - CTRL_UNIT0_ID]);
}
-
- return;
}
static input_system_err_t configuration_to_registers(void)
@@ -1307,19 +1260,12 @@ static input_system_err_t configuration_to_registers(void)
break;
case INPUT_SYSTEM_SOURCE_TPG:
-
- break;
-
case INPUT_SYSTEM_SOURCE_PRBS:
-
- break;
-
case INPUT_SYSTEM_SOURCE_FIFO:
break;
default:
return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
} // end of switch (source_type)
@@ -1695,19 +1641,11 @@ static input_system_err_t input_system_configure_channel_sensor(
break;
case INPUT_SYSTEM_FIFO_CAPTURE_WITH_COUNTING:
- return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
case INPUT_SYSTEM_XMEM_CAPTURE:
- return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
case INPUT_SYSTEM_XMEM_ACQUIRE:
- return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
default:
return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED;
- break;
}
- return INPUT_SYSTEM_ERR_NO_ERROR;
}
// Test flags and set structure.
diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp_local.h b/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp_local.h
index eceeb5d160ad..4dbec4063b3d 100644
--- a/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp_local.h
+++ b/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp_local.h
@@ -16,8 +16,6 @@
#ifndef __ISP_LOCAL_H_INCLUDED__
#define __ISP_LOCAL_H_INCLUDED__
-#include <stdbool.h>
-
#include "isp_global.h"
#include <isp2400_support.h>
diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/print_support.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/print_support.h
index 540b405cc0f7..a3c7f3de6d17 100644
--- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/print_support.h
+++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/print_support.h
@@ -16,7 +16,7 @@
#ifndef __PRINT_SUPPORT_H_INCLUDED__
#define __PRINT_SUPPORT_H_INCLUDED__
-#include <stdarg.h>
+#include <linux/stdarg.h>
extern int (*sh_css_printf)(const char *fmt, va_list args);
/* depends on host supplied print function in ia_css_init() */
diff --git a/drivers/staging/media/atomisp/pci/ia_css_env.h b/drivers/staging/media/atomisp/pci/ia_css_env.h
index 6b38723b27cd..3b89bbd837a0 100644
--- a/drivers/staging/media/atomisp/pci/ia_css_env.h
+++ b/drivers/staging/media/atomisp/pci/ia_css_env.h
@@ -17,7 +17,7 @@
#define __IA_CSS_ENV_H
#include <type_support.h>
-#include <stdarg.h> /* va_list */
+#include <linux/stdarg.h> /* va_list */
#include "ia_css_types.h"
#include "ia_css_acc_types.h"
diff --git a/drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h b/drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h
index c801ddd71192..b2076a96987c 100644
--- a/drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h
+++ b/drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h
@@ -27,7 +27,7 @@
// Number of registers
#define ISYS_CTRL_NOF_REGS 23
-// Register id's of MMIO slave accesible registers
+// Register id's of MMIO slave accessible registers
#define ISYS_CTRL_CAPT_START_ADDR_A_REG_ID 0
#define ISYS_CTRL_CAPT_START_ADDR_B_REG_ID 1
#define ISYS_CTRL_CAPT_START_ADDR_C_REG_ID 2
diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h
index be3534e46c15..9b22f2da45d5 100644
--- a/drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h
+++ b/drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h
@@ -17,8 +17,8 @@
#define __IA_CSS_ANR_TYPES_H
/* @file
-* CSS-API header file for Advanced Noise Reduction kernel v1
-*/
+ * CSS-API header file for Advanced Noise Reduction kernel v1
+ */
/* Application specific DMA settings */
#define ANR_BPP 10
diff --git a/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h b/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h
index 072a92199e05..2614b89b8e34 100644
--- a/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h
+++ b/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h
@@ -356,41 +356,13 @@ struct rx_cfg_s {
};
/* NOTE: The base has already an offset of 0x0100 */
-static const hrt_address MIPI_PORT_OFFSET[N_MIPI_PORT_ID] = {
+static const hrt_address __maybe_unused MIPI_PORT_OFFSET[N_MIPI_PORT_ID] = {
0x00000000UL,
0x00000100UL,
0x00000200UL
};
-static const mipi_lane_cfg_t MIPI_PORT_MAXLANES[N_MIPI_PORT_ID] = {
- MIPI_4LANE_CFG,
- MIPI_1LANE_CFG,
- MIPI_2LANE_CFG
-};
-
-static const bool MIPI_PORT_ACTIVE[N_RX_MODE][N_MIPI_PORT_ID] = {
- {true, true, false},
- {true, true, false},
- {true, true, false},
- {true, true, false},
- {true, true, true},
- {true, true, true},
- {true, true, true},
- {true, true, true}
-};
-
-static const mipi_lane_cfg_t MIPI_PORT_LANES[N_RX_MODE][N_MIPI_PORT_ID] = {
- {MIPI_4LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
- {MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
- {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
- {MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
- {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_2LANE_CFG},
- {MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG},
- {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG},
- {MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG}
-};
-
-static const hrt_address SUB_SYSTEM_OFFSET[N_SUB_SYSTEM_ID] = {
+static const hrt_address __maybe_unused SUB_SYSTEM_OFFSET[N_SUB_SYSTEM_ID] = {
0x00001000UL,
0x00002000UL,
0x00003000UL,
diff --git a/drivers/staging/media/atomisp/pci/isp_acquisition_defs.h b/drivers/staging/media/atomisp/pci/isp_acquisition_defs.h
index 8e4bddc3790d..7e8f6f2178aa 100644
--- a/drivers/staging/media/atomisp/pci/isp_acquisition_defs.h
+++ b/drivers/staging/media/atomisp/pci/isp_acquisition_defs.h
@@ -35,7 +35,7 @@
#define NOF_ACQ_REGS 12
-// Register id's of MMIO slave accesible registers
+// Register id's of MMIO slave accessible registers
#define ACQ_START_ADDR_REG_ID 0
#define ACQ_MEM_REGION_SIZE_REG_ID 1
#define ACQ_NUM_MEM_REGIONS_REG_ID 2
diff --git a/drivers/staging/media/atomisp/pci/isp_capture_defs.h b/drivers/staging/media/atomisp/pci/isp_capture_defs.h
index 14cbb6390d3e..b9e5ed932702 100644
--- a/drivers/staging/media/atomisp/pci/isp_capture_defs.h
+++ b/drivers/staging/media/atomisp/pci/isp_capture_defs.h
@@ -33,7 +33,7 @@
// Number of registers
#define CAPT_NOF_REGS 16
-// Register id's of MMIO slave accesible registers
+// Register id's of MMIO slave accessible registers
#define CAPT_START_MODE_REG_ID 0
#define CAPT_START_ADDR_REG_ID 1
#define CAPT_MEM_REGION_SIZE_REG_ID 2
diff --git a/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h b/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h
index 5e6e7447ae00..e37ef4232c55 100644
--- a/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h
+++ b/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h
@@ -19,7 +19,7 @@
/*! \file */
#include <type_support.h>
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include "ia_css_types.h"
#include "ia_css_binary.h"
#include "ia_css_frame_public.h"
diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c
index 4a18da6bf0c1..af153c3fb86d 100644
--- a/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c
+++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c
@@ -476,10 +476,20 @@ unsigned int ia_css_csi2_calculate_input_system_alignment(
#endif
#if !defined(ISP2401)
+static const mipi_lane_cfg_t MIPI_PORT_LANES[N_RX_MODE][N_MIPI_PORT_ID] = {
+ {MIPI_4LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
+ {MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
+ {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
+ {MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
+ {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_2LANE_CFG},
+ {MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG},
+ {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG},
+ {MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG}
+};
+
void ia_css_isys_rx_configure(const rx_cfg_t *config,
const enum ia_css_input_mode input_mode)
{
- bool port_enabled[N_MIPI_PORT_ID];
bool any_port_enabled = false;
enum mipi_port_id port;
@@ -516,8 +526,6 @@ void ia_css_isys_rx_configure(const rx_cfg_t *config,
_HRT_CSS_RECEIVER_2400_RX_COUNT_REG_IDX,
config->rxcount);
- port_enabled[port] = true;
-
if (input_mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
/* MW: A bit of a hack, straight wiring of the capture
* units,assuming they are linearly enumerated. */
diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c
index d26b1301eeb7..c4b35cbab373 100644
--- a/drivers/staging/media/atomisp/pci/sh_css.c
+++ b/drivers/staging/media/atomisp/pci/sh_css.c
@@ -3224,24 +3224,22 @@ init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
#ifdef ISP2401
static unsigned int
-get_crop_lines_for_bayer_order(
- const struct ia_css_stream_config *config)
+get_crop_lines_for_bayer_order(const struct ia_css_stream_config *config)
{
assert(config);
- if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR)
- || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
+ if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR) ||
+ (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
return 1;
return 0;
}
static unsigned int
-get_crop_columns_for_bayer_order(
- const struct ia_css_stream_config *config)
+get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config)
{
assert(config);
- if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB)
- || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
+ if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB) ||
+ (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
return 1;
return 0;
@@ -5170,7 +5168,7 @@ sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
if (binary) {
err = ia_css_binary_3a_grid_info(binary, info, pipe);
if (err)
- goto ERR;
+ goto err;
} else {
memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
}
@@ -5181,10 +5179,7 @@ sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
ia_css_binary_dvs_grid_info(binary, info, pipe);
ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
} else {
- memset(&info->dvs_grid.dvs_grid_info, 0,
- sizeof(info->dvs_grid.dvs_grid_info));
- memset(&info->dvs_grid.dvs_stat_grid_info, 0,
- sizeof(info->dvs_grid.dvs_stat_grid_info));
+ memset(&info->dvs_grid, 0, sizeof(info->dvs_grid));
}
if (binary) {
@@ -5195,7 +5190,7 @@ sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
info->vamem_type = IA_CSS_VAMEM_TYPE_2;
-ERR :
+err:
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
@@ -5328,14 +5323,15 @@ static int load_video_binaries(struct ia_css_pipe *pipe)
if (err)
return err;
mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
- mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
- sizeof(struct ia_css_binary), GFP_KERNEL);
+ mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
+ sizeof(struct ia_css_binary),
+ GFP_KERNEL);
if (!mycs->yuv_scaler_binary) {
err = -ENOMEM;
return err;
}
- mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
- * sizeof(bool), GFP_KERNEL);
+ mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
+ sizeof(bool), GFP_KERNEL);
if (!mycs->is_output_stage) {
err = -ENOMEM;
return err;
@@ -5938,14 +5934,15 @@ static int load_primary_binaries(
return err;
}
mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
- mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
- sizeof(struct ia_css_binary), GFP_KERNEL);
+ mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
+ sizeof(struct ia_css_binary),
+ GFP_KERNEL);
if (!mycs->yuv_scaler_binary) {
err = -ENOMEM;
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
- mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
+ mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
sizeof(bool), GFP_KERNEL);
if (!mycs->is_output_stage) {
err = -ENOMEM;
@@ -6989,14 +6986,14 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe)
goto ERR;
mycs->num_output = cas_scaler_descr.num_output_stage;
mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
- mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
+ mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
sizeof(struct ia_css_binary),
GFP_KERNEL);
if (!mycs->yuv_scaler_binary) {
err = -ENOMEM;
goto ERR;
}
- mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
+ mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
sizeof(bool), GFP_KERNEL);
if (!mycs->is_output_stage) {
err = -ENOMEM;
@@ -7097,7 +7094,7 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe)
mycs->num_vf_pp = 1;
}
- mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp *
+ mycs->vf_pp_binary = kcalloc(mycs->num_vf_pp,
sizeof(struct ia_css_binary),
GFP_KERNEL);
if (!mycs->vf_pp_binary) {
@@ -10162,7 +10159,7 @@ ia_css_stop_sp(void)
timeout--;
udelay(1);
}
- if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
+ if (ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED)
IA_CSS_WARNING("SP has not terminated (SW)");
if (timeout == 0) {
diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c
index f4ce8ace9d50..e1a16a50e588 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c
@@ -363,10 +363,8 @@ void sh_css_unload_firmware(void)
unsigned int i = 0;
for (i = 0; i < sh_css_num_binaries; i++) {
- if (fw_minibuffer[i].name)
- kfree((void *)fw_minibuffer[i].name);
- if (fw_minibuffer[i].buffer)
- kvfree(fw_minibuffer[i].buffer);
+ kfree(fw_minibuffer[i].name);
+ kvfree(fw_minibuffer[i].buffer);
}
kfree(fw_minibuffer);
fw_minibuffer = NULL;
diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h
index 3c669ec79b68..496faa7297a5 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_internal.h
+++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h
@@ -20,7 +20,7 @@
#include <math_support.h>
#include <type_support.h>
#include <platform_support.h>
-#include <stdarg.h>
+#include <linux/stdarg.h>
#if !defined(ISP2401)
#include "input_formatter.h"
diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c
index 3f34cc81be87..75489f7d75ee 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c
@@ -91,7 +91,8 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
const enum atomisp_input_format format,
const bool hasSOLandEOL,
const unsigned int embedded_data_size_words,
- unsigned int *size_mem_words) {
+ unsigned int *size_mem_words)
+{
int err = 0;
unsigned int bits_per_pixel = 0;
@@ -118,8 +119,7 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
IA_CSS_ENTER("padded_width=%d, height=%d, format=%d, hasSOLandEOL=%d, embedded_data_size_words=%d\n",
width_padded, height, format, hasSOLandEOL, embedded_data_size_words);
- switch (format)
- {
+ switch (format) {
case ATOMISP_INPUT_FORMAT_RAW_6: /* 4p, 3B, 24bits */
bits_per_pixel = 6;
break;
@@ -178,12 +178,10 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
/* Even lines for YUV420 formats are double in bits_per_pixel. */
if (format == ATOMISP_INPUT_FORMAT_YUV420_8
|| format == ATOMISP_INPUT_FORMAT_YUV420_10
- || format == ATOMISP_INPUT_FORMAT_YUV420_16)
- {
+ || format == ATOMISP_INPUT_FORMAT_YUV420_16) {
even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >>
3; /* ceil ( bits per line / 8) */
- } else
- {
+ } else {
even_line_bytes = odd_line_bytes;
}
@@ -236,7 +234,8 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
#if !defined(ISP2401)
int
ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port,
- const unsigned int size_mem_words) {
+ const unsigned int size_mem_words)
+{
u32 idx;
int err = -EBUSY;
@@ -246,11 +245,9 @@ ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port,
for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT &&
my_css.mipi_sizes_for_check[port][idx] != 0;
- idx++) /* do nothing */
- {
+ idx++) { /* do nothing */
}
- if (idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT)
- {
+ if (idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT) {
my_css.mipi_sizes_for_check[port][idx] = size_mem_words;
err = 0;
}
@@ -271,7 +268,8 @@ mipi_init(void)
int
calculate_mipi_buff_size(
struct ia_css_stream_config *stream_cfg,
- unsigned int *size_mem_words) {
+ unsigned int *size_mem_words)
+{
#if !defined(ISP2401)
int err = -EINVAL;
(void)stream_cfg;
@@ -346,12 +344,10 @@ calculate_mipi_buff_size(
/* Even lines for YUV420 formats are double in bits_per_pixel. */
if (format == ATOMISP_INPUT_FORMAT_YUV420_8
- || format == ATOMISP_INPUT_FORMAT_YUV420_10)
- {
+ || format == ATOMISP_INPUT_FORMAT_YUV420_10) {
even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >>
3; /* ceil ( bits per line / 8) */
- } else
- {
+ } else {
even_line_bytes = odd_line_bytes;
}
@@ -393,7 +389,8 @@ static bool buffers_needed(struct ia_css_pipe *pipe)
int
allocate_mipi_frames(struct ia_css_pipe *pipe,
- struct ia_css_stream_info *info) {
+ struct ia_css_stream_info *info)
+{
int err = -EINVAL;
unsigned int port;
@@ -402,8 +399,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
assert(pipe);
assert(pipe->stream);
- if ((!pipe) || (!pipe->stream))
- {
+ if ((!pipe) || (!pipe->stream)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"allocate_mipi_frames(%p) exit: pipe or stream is null.\n",
pipe);
@@ -411,8 +407,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
}
#ifdef ISP2401
- if (pipe->stream->config.online)
- {
+ if (pipe->stream->config.online) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n",
pipe);
@@ -449,8 +444,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
#endif
#if !defined(ISP2401)
- if (ref_count_mipi_allocation[port] != 0)
- {
+ if (ref_count_mipi_allocation[port] != 0) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n",
pipe, port);
@@ -462,8 +456,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
* TODO AM: Once that is changed (removed) this code should be removed as well.
* In that case only 2400 related code should remain.
*/
- if (ref_count_mipi_allocation[port] != 0)
- {
+ if (ref_count_mipi_allocation[port] != 0) {
ref_count_mipi_allocation[port]++;
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"allocate_mipi_frames(%p) leave: nothing to do, already allocated for this port (port=%d).\n",
@@ -481,8 +474,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
{ /* limit the scope of i,j */
unsigned int i, j;
- for (i = 0; i < my_css.num_mipi_frames[port]; i++)
- {
+ for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
/* free previous frame */
if (my_css.mipi_frames[port][i]) {
ia_css_frame_free(my_css.mipi_frames[port][i]);
@@ -535,7 +527,8 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
}
int
-free_mipi_frames(struct ia_css_pipe *pipe) {
+free_mipi_frames(struct ia_css_pipe *pipe)
+{
int err = -EINVAL;
unsigned int port;
@@ -543,8 +536,7 @@ free_mipi_frames(struct ia_css_pipe *pipe) {
"free_mipi_frames(%p) enter:\n", pipe);
/* assert(pipe != NULL); TEMP: TODO: Should be assert only. */
- if (pipe)
- {
+ if (pipe) {
assert(pipe->stream);
if ((!pipe) || (!pipe->stream)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
@@ -620,8 +612,7 @@ free_mipi_frames(struct ia_css_pipe *pipe) {
}
#endif
}
- } else /* pipe ==NULL */
- {
+ } else { /* pipe ==NULL */
/* AM TEMP: free-ing all mipi buffers just like a legacy code. */
for (port = CSI_PORT0_ID; port < N_CSI_PORTS; port++) {
unsigned int i;
@@ -645,7 +636,8 @@ free_mipi_frames(struct ia_css_pipe *pipe) {
}
int
-send_mipi_frames(struct ia_css_pipe *pipe) {
+send_mipi_frames(struct ia_css_pipe *pipe)
+{
int err = -EINVAL;
unsigned int i;
#ifndef ISP2401
@@ -658,8 +650,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) {
assert(pipe);
assert(pipe->stream);
- if (!pipe || !pipe->stream)
- {
+ if (!pipe || !pipe->stream) {
IA_CSS_ERROR("pipe or stream is null");
return -EINVAL;
}
@@ -686,8 +677,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) {
}
/* Hand-over the SP-internal mipi buffers */
- for (i = 0; i < my_css.num_mipi_frames[port]; i++)
- {
+ for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
/* Need to include the ofset for port. */
sh_css_update_host2sp_mipi_frame(port * NUM_MIPI_FRAMES_PER_STREAM + i,
my_css.mipi_frames[port][i]);
@@ -700,8 +690,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) {
* Send an event to inform the SP
* that all MIPI frames are passed.
**********************************/
- if (!sh_css_sp_is_running())
- {
+ if (!sh_css_sp_is_running()) {
/* SP is not running. The queues are not valid */
IA_CSS_ERROR("sp is not running");
return err;
diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c
index 644e14575987..dbd3bfe3d343 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_params.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_params.c
@@ -813,15 +813,15 @@ convert_allocate_fpntbl(struct ia_css_isp_parameters *params)
}
static int
-store_fpntbl(struct ia_css_isp_parameters *params, ia_css_ptr ptr) {
+store_fpntbl(struct ia_css_isp_parameters *params, ia_css_ptr ptr)
+{
struct ia_css_host_data *isp_data;
assert(params);
assert(ptr != mmgr_NULL);
isp_data = convert_allocate_fpntbl(params);
- if (!isp_data)
- {
+ if (!isp_data) {
IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
return -ENOMEM;
}
@@ -894,7 +894,8 @@ ia_css_process_kernel(struct ia_css_stream *stream,
static int
sh_css_select_dp_10bpp_config(const struct ia_css_pipe *pipe,
- bool *is_dp_10bpp) {
+ bool *is_dp_10bpp)
+{
int err = 0;
/* Currently we check if 10bpp DPC configuration is required based
* on the use case,i.e. if BDS and DPC is both enabled. The more cleaner
@@ -903,12 +904,10 @@ sh_css_select_dp_10bpp_config(const struct ia_css_pipe *pipe,
* implementation. (This is because the configuration is set before a
* binary is selected, and the binary info is not available)
*/
- if ((!pipe) || (!is_dp_10bpp))
- {
+ if ((!pipe) || (!is_dp_10bpp)) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
err = -EINVAL;
- } else
- {
+ } else {
*is_dp_10bpp = false;
/* check if DPC is enabled from the host */
@@ -936,7 +935,8 @@ sh_css_select_dp_10bpp_config(const struct ia_css_pipe *pipe,
int
sh_css_set_black_frame(struct ia_css_stream *stream,
- const struct ia_css_frame *raw_black_frame) {
+ const struct ia_css_frame *raw_black_frame)
+{
struct ia_css_isp_parameters *params;
/* this function desperately needs to be moved to the ISP or SP such
* that it can use the DMA.
@@ -957,13 +957,11 @@ sh_css_set_black_frame(struct ia_css_stream *stream,
IA_CSS_ENTER_PRIVATE("black_frame=%p", raw_black_frame);
if (params->fpn_config.data &&
- (params->fpn_config.width != width || params->fpn_config.height != height))
- {
+ (params->fpn_config.width != width || params->fpn_config.height != height)) {
kvfree(params->fpn_config.data);
params->fpn_config.data = NULL;
}
- if (!params->fpn_config.data)
- {
+ if (!params->fpn_config.data) {
params->fpn_config.data = kvmalloc(height * width *
sizeof(short), GFP_KERNEL);
if (!params->fpn_config.data) {
@@ -977,8 +975,7 @@ sh_css_set_black_frame(struct ia_css_stream *stream,
}
/* store raw to fpntbl */
- for (y = 0; y < height; y++)
- {
+ for (y = 0; y < height; y++) {
for (x = 0; x < width; x += (ISP_VEC_NELEMS * 2)) {
int ofs = y * width + x;
@@ -1181,7 +1178,8 @@ sh_css_enable_pipeline(const struct ia_css_binary *binary)
static int
ia_css_process_zoom_and_motion(
struct ia_css_isp_parameters *params,
- const struct ia_css_pipeline_stage *first_stage) {
+ const struct ia_css_pipeline_stage *first_stage)
+{
/* first_stage can be NULL */
const struct ia_css_pipeline_stage *stage;
int err = 0;
@@ -1195,8 +1193,7 @@ ia_css_process_zoom_and_motion(
IA_CSS_ENTER_PRIVATE("");
/* Go through all stages to udate uds and cropping */
- for (stage = first_stage; stage; stage = stage->next)
- {
+ for (stage = first_stage; stage; stage = stage->next) {
struct ia_css_binary *binary;
/* note: the var below is made static as it is quite large;
if it is not static it ends up on the stack which could
@@ -1581,7 +1578,8 @@ err:
int
ia_css_get_3a_statistics(struct ia_css_3a_statistics *host_stats,
- const struct ia_css_isp_3a_statistics *isp_stats) {
+ const struct ia_css_isp_3a_statistics *isp_stats)
+{
struct ia_css_isp_3a_statistics_map *map;
int ret = 0;
@@ -1591,13 +1589,11 @@ ia_css_get_3a_statistics(struct ia_css_3a_statistics *host_stats,
assert(isp_stats);
map = ia_css_isp_3a_statistics_map_allocate(isp_stats, NULL);
- if (map)
- {
+ if (map) {
hmm_load(isp_stats->data_ptr, map->data_ptr, isp_stats->size);
ia_css_translate_3a_statistics(host_stats, map);
ia_css_isp_3a_statistics_map_free(map);
- } else
- {
+ } else {
IA_CSS_ERROR("out of memory");
ret = -ENOMEM;
}
@@ -1894,7 +1890,8 @@ sh_css_pipe_isp_config_get(struct ia_css_pipe *pipe)
int
ia_css_stream_set_isp_config(
struct ia_css_stream *stream,
- const struct ia_css_isp_config *config) {
+ const struct ia_css_isp_config *config)
+{
return ia_css_stream_set_isp_config_on_pipe(stream, config, NULL);
}
@@ -1902,7 +1899,8 @@ int
ia_css_stream_set_isp_config_on_pipe(
struct ia_css_stream *stream,
const struct ia_css_isp_config *config,
- struct ia_css_pipe *pipe) {
+ struct ia_css_pipe *pipe)
+{
int err = 0;
if ((!stream) || (!config))
@@ -1923,7 +1921,8 @@ ia_css_stream_set_isp_config_on_pipe(
int
ia_css_pipe_set_isp_config(struct ia_css_pipe *pipe,
- struct ia_css_isp_config *config) {
+ struct ia_css_isp_config *config)
+{
struct ia_css_pipe *pipe_in = pipe;
int err = 0;
@@ -1948,7 +1947,8 @@ static int
sh_css_set_global_isp_config_on_pipe(
struct ia_css_pipe *curr_pipe,
const struct ia_css_isp_config *config,
- struct ia_css_pipe *pipe) {
+ struct ia_css_pipe *pipe)
+{
int err = 0;
int err1 = 0;
int err2 = 0;
@@ -1977,7 +1977,8 @@ static int
sh_css_set_per_frame_isp_config_on_pipe(
struct ia_css_stream *stream,
const struct ia_css_isp_config *config,
- struct ia_css_pipe *pipe) {
+ struct ia_css_pipe *pipe)
+{
unsigned int i;
bool per_frame_config_created = false;
int err = 0;
@@ -1991,8 +1992,7 @@ sh_css_set_per_frame_isp_config_on_pipe(
IA_CSS_ENTER_PRIVATE("stream=%p, config=%p, pipe=%p", stream, config, pipe);
- if (!pipe)
- {
+ if (!pipe) {
err = -EINVAL;
goto exit;
}
@@ -2000,8 +2000,7 @@ sh_css_set_per_frame_isp_config_on_pipe(
/* create per-frame ISP params object with default values
* from stream->isp_params_configs if one doesn't already exist
*/
- if (!stream->per_frame_isp_params_configs)
- {
+ if (!stream->per_frame_isp_params_configs) {
err = sh_css_create_isp_params(stream,
&stream->per_frame_isp_params_configs);
if (err)
@@ -2012,15 +2011,13 @@ sh_css_set_per_frame_isp_config_on_pipe(
params = stream->per_frame_isp_params_configs;
/* update new ISP params object with the new config */
- if (!sh_css_init_isp_params_from_global(stream, params, false, pipe))
- {
+ if (!sh_css_init_isp_params_from_global(stream, params, false, pipe)) {
err1 = -EINVAL;
}
err2 = sh_css_init_isp_params_from_config(stream->pipes[0], params, config, pipe);
- if (per_frame_config_created)
- {
+ if (per_frame_config_created) {
ddr_ptrs = &params->ddr_ptrs;
ddr_ptrs_size = &params->ddr_ptrs_size;
/* create per pipe reference to general ddr_ptrs */
@@ -2051,7 +2048,8 @@ static int
sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe,
struct ia_css_isp_parameters *params,
const struct ia_css_isp_config *config,
- struct ia_css_pipe *pipe_in) {
+ struct ia_css_pipe *pipe_in)
+{
int err = 0;
bool is_dp_10bpp = true;
@@ -2096,8 +2094,7 @@ sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe,
}
if (0 ==
- sh_css_select_dp_10bpp_config(pipe, &is_dp_10bpp))
- {
+ sh_css_select_dp_10bpp_config(pipe, &is_dp_10bpp)) {
/* return an error when both DPC and BDS is enabled by the
* user. */
/* we do not exit from this point immediately to allow internal
@@ -2105,8 +2102,7 @@ sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe,
if (is_dp_10bpp) {
err = -EINVAL;
}
- } else
- {
+ } else {
err = -EINVAL;
goto exit;
}
@@ -2359,7 +2355,8 @@ static unsigned int g_param_buffer_dequeue_count;
static unsigned int g_param_buffer_enqueue_count;
int
-ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) {
+ia_css_stream_isp_parameters_init(struct ia_css_stream *stream)
+{
int err = 0;
unsigned int i;
struct sh_css_ddr_address_map *ddr_ptrs;
@@ -2369,8 +2366,7 @@ ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) {
assert(stream);
IA_CSS_ENTER_PRIVATE("void");
- if (!stream)
- {
+ if (!stream) {
IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
return -EINVAL;
}
@@ -2385,8 +2381,7 @@ ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) {
goto ERR;
params = stream->isp_params_configs;
- if (!sh_css_init_isp_params_from_global(stream, params, true, NULL))
- {
+ if (!sh_css_init_isp_params_from_global(stream, params, true, NULL)) {
/* we do not return the error immediately to enable internal
* firmware feature testing */
err = -EINVAL;
@@ -2396,8 +2391,7 @@ ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) {
ddr_ptrs_size = &params->ddr_ptrs_size;
/* create per pipe reference to general ddr_ptrs */
- for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
- {
+ for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
ref_sh_css_ddr_address_map(ddr_ptrs, &params->pipe_ddr_ptrs[i]);
params->pipe_ddr_ptrs_size[i] = *ddr_ptrs_size;
}
@@ -2431,7 +2425,8 @@ ia_css_set_sdis2_config(
static int
sh_css_create_isp_params(struct ia_css_stream *stream,
- struct ia_css_isp_parameters **isp_params_out) {
+ struct ia_css_isp_parameters **isp_params_out)
+{
bool succ = true;
unsigned int i;
struct sh_css_ddr_address_map *ddr_ptrs;
@@ -2441,23 +2436,20 @@ sh_css_create_isp_params(struct ia_css_stream *stream,
struct ia_css_isp_parameters *params =
kvmalloc(sizeof(struct ia_css_isp_parameters), GFP_KERNEL);
- if (!params)
- {
+ if (!params) {
*isp_params_out = NULL;
err = -ENOMEM;
IA_CSS_ERROR("%s:%d error: cannot allocate memory", __FILE__, __LINE__);
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
- } else
- {
+ } else {
memset(params, 0, sizeof(struct ia_css_isp_parameters));
}
ddr_ptrs = &params->ddr_ptrs;
ddr_ptrs_size = &params->ddr_ptrs_size;
- for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
- {
+ for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
memset(&params->pipe_ddr_ptrs[i], 0,
sizeof(params->pipe_ddr_ptrs[i]));
memset(&params->pipe_ddr_ptrs_size[i], 0,
@@ -2714,7 +2706,8 @@ exit:
}
int
-sh_css_params_init(void) {
+sh_css_params_init(void)
+{
int i, p;
IA_CSS_ENTER_PRIVATE("void");
@@ -2723,8 +2716,7 @@ sh_css_params_init(void) {
g_param_buffer_dequeue_count = 0;
g_param_buffer_enqueue_count = 0;
- for (p = 0; p < IA_CSS_PIPE_ID_NUM; p++)
- {
+ for (p = 0; p < IA_CSS_PIPE_ID_NUM; p++) {
for (i = 0; i < SH_CSS_MAX_STAGES; i++) {
xmem_sp_stage_ptrs[p][i] =
ia_css_refcount_increment(-1,
@@ -2762,8 +2754,7 @@ sh_css_params_init(void) {
ATOMISP_MAP_FLAG_CLEARED));
if ((sp_ddr_ptrs == mmgr_NULL) ||
- (xmem_sp_group_ptrs == mmgr_NULL))
- {
+ (xmem_sp_group_ptrs == mmgr_NULL)) {
ia_css_uninit();
IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
return -ENOMEM;
@@ -3094,14 +3085,14 @@ store_morph_plane(
unsigned int width,
unsigned int height,
ia_css_ptr dest,
- unsigned int aligned_width) {
+ unsigned int aligned_width)
+{
struct ia_css_host_data *isp_data;
assert(dest != mmgr_NULL);
isp_data = convert_allocate_morph_plane(data, width, height, aligned_width);
- if (!isp_data)
- {
+ if (!isp_data) {
IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
return -ENOMEM;
}
@@ -3221,7 +3212,8 @@ int
sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe,
struct ia_css_isp_parameters *params,
bool commit,
- struct ia_css_pipe *pipe_in) {
+ struct ia_css_pipe *pipe_in)
+{
int err = 0;
ia_css_ptr cpy;
int i;
@@ -3238,15 +3230,13 @@ sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe,
raw_bit_depth = ia_css_stream_input_format_bits_per_pixel(curr_pipe->stream);
/* now make the map available to the sp */
- if (!commit)
- {
+ if (!commit) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
/* enqueue a copies of the mem_map to
the designated pipelines */
- for (i = 0; i < curr_pipe->stream->num_pipes; i++)
- {
+ for (i = 0; i < curr_pipe->stream->num_pipes; i++) {
struct ia_css_pipe *pipe;
struct sh_css_ddr_address_map *cur_map;
struct sh_css_ddr_address_map_size *cur_map_size;
@@ -3430,7 +3420,8 @@ sh_css_params_write_to_ddr_internal(
struct ia_css_isp_parameters *params,
const struct ia_css_pipeline_stage *stage,
struct sh_css_ddr_address_map *ddr_map,
- struct sh_css_ddr_address_map_size *ddr_map_size) {
+ struct sh_css_ddr_address_map_size *ddr_map_size)
+{
int err;
const struct ia_css_binary *binary;
@@ -3452,8 +3443,7 @@ sh_css_params_write_to_ddr_internal(
stage_num = stage->stage_num;
- if (binary->info->sp.enable.fpnr)
- {
+ if (binary->info->sp.enable.fpnr) {
buff_realloced = reallocate_buffer(&ddr_map->fpn_tbl,
&ddr_map_size->fpn_tbl,
(size_t)(FPNTBL_BYTES(binary)),
@@ -3474,8 +3464,7 @@ sh_css_params_write_to_ddr_internal(
}
}
- if (binary->info->sp.enable.sc)
- {
+ if (binary->info->sp.enable.sc) {
u32 enable_conv;
size_t bytes;
@@ -3577,8 +3566,7 @@ sh_css_params_write_to_ddr_internal(
* DPC kernel. The code below sets the pipe specific configuration to
* individual binaries. */
if (IS_ISP2401 &&
- params->pipe_dpc_config_changed[pipe_id] && binary->info->sp.enable.dpc)
- {
+ params->pipe_dpc_config_changed[pipe_id] && binary->info->sp.enable.dpc) {
unsigned int size =
stage->binary->info->mem_offsets.offsets.param->dmem.dp.size;
@@ -3596,8 +3584,7 @@ sh_css_params_write_to_ddr_internal(
}
}
- if (params->config_changed[IA_CSS_MACC_ID] && binary->info->sp.enable.macc)
- {
+ if (params->config_changed[IA_CSS_MACC_ID] && binary->info->sp.enable.macc) {
unsigned int i, j, idx;
unsigned int idx_map[] = {
0, 1, 3, 2, 6, 7, 5, 4, 12, 13, 15, 14, 10, 11, 9, 8
@@ -3646,8 +3633,7 @@ sh_css_params_write_to_ddr_internal(
sizeof(converted_macc_table.data));
}
- if (binary->info->sp.enable.dvs_6axis)
- {
+ if (binary->info->sp.enable.dvs_6axis) {
/* because UV is packed into the Y plane, calc total
* YYU size = /2 gives size of UV-only,
* total YYU size = UV-only * 3.
@@ -3705,8 +3691,7 @@ sh_css_params_write_to_ddr_internal(
}
}
- if (binary->info->sp.enable.ca_gdc)
- {
+ if (binary->info->sp.enable.ca_gdc) {
unsigned int i;
ia_css_ptr *virt_addr_tetra_x[
@@ -3811,8 +3796,7 @@ sh_css_params_write_to_ddr_internal(
}
/* After special cases like SC, FPN since they may change parameters */
- for (mem = 0; mem < N_IA_CSS_MEMORIES; mem++)
- {
+ for (mem = 0; mem < N_IA_CSS_MEMORIES; mem++) {
const struct ia_css_isp_data *isp_data =
ia_css_isp_param_get_isp_mem_init(&binary->info->sp.mem_initializers,
IA_CSS_PARAM_CLASS_PARAM, mem);
@@ -4025,7 +4009,8 @@ static int write_ia_css_isp_parameter_set_info_to_ddr(
static int
free_ia_css_isp_parameter_set_info(
- ia_css_ptr ptr) {
+ ia_css_ptr ptr)
+{
int err = 0;
struct ia_css_isp_parameter_set_info isp_params_info;
unsigned int i;
@@ -4034,8 +4019,7 @@ free_ia_css_isp_parameter_set_info(
IA_CSS_ENTER_PRIVATE("ptr = %u", ptr);
/* sanity check - ptr must be valid */
- if (!ia_css_refcount_is_valid(ptr))
- {
+ if (!ia_css_refcount_is_valid(ptr)) {
IA_CSS_ERROR("%s: IA_CSS_REFCOUNT_PARAM_SET_POOL(0x%x) invalid arg", __func__,
ptr);
err = -EINVAL;
@@ -4046,8 +4030,7 @@ free_ia_css_isp_parameter_set_info(
hmm_load(ptr, &isp_params_info.mem_map, sizeof(struct sh_css_ddr_address_map));
/* copy map using size info */
for (i = 0; i < (sizeof(struct sh_css_ddr_address_map_size) /
- sizeof(size_t)); i++)
- {
+ sizeof(size_t)); i++) {
if (addrs[i] == mmgr_NULL)
continue;
@@ -4254,7 +4237,8 @@ sh_css_update_uds_and_crop_info_based_on_zoom_region(
struct sh_css_uds_info *uds, /* out */
struct sh_css_crop_pos *sp_out_crop_pos, /* out */
struct ia_css_resolution pipe_in_res,
- bool enable_zoom) {
+ bool enable_zoom)
+{
unsigned int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
int err = 0;
/* Note:
@@ -4285,19 +4269,16 @@ sh_css_update_uds_and_crop_info_based_on_zoom_region(
if ((x0 > x1) || (y0 > y1) || (x1 > pipe_in_res.width) || (y1 > pipe_in_res.height))
return -EINVAL;
- if (!enable_zoom)
- {
+ if (!enable_zoom) {
uds->curr_dx = HRT_GDC_N;
uds->curr_dy = HRT_GDC_N;
}
- if (info->enable.dvs_envelope)
- {
+ if (info->enable.dvs_envelope) {
/* Zoom region is only supported by the UDS module on ISP
* 2 and higher. It is not supported in video mode on ISP 1 */
return -EINVAL;
- } else
- {
+ } else {
if (enable_zoom) {
/* A. Calculate dx/dy based on crop region using in_frame_info
* Scale the crop region if in_frame_info to the stage is not same as
diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c
index 02f5a73b4096..a73e8ca1e225 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_sp.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c
@@ -535,12 +535,12 @@ sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out,
}
static int
-set_input_frame_buffer(const struct ia_css_frame *frame) {
+set_input_frame_buffer(const struct ia_css_frame *frame)
+{
if (!frame)
return -EINVAL;
- switch (frame->info.format)
- {
+ switch (frame->info.format) {
case IA_CSS_FRAME_FORMAT_QPLANE6:
case IA_CSS_FRAME_FORMAT_YUV420_16:
case IA_CSS_FRAME_FORMAT_RAW_PACKED:
@@ -566,12 +566,12 @@ set_input_frame_buffer(const struct ia_css_frame *frame) {
static int
set_output_frame_buffer(const struct ia_css_frame *frame,
- unsigned int idx) {
+ unsigned int idx)
+{
if (!frame)
return -EINVAL;
- switch (frame->info.format)
- {
+ switch (frame->info.format) {
case IA_CSS_FRAME_FORMAT_YUV420:
case IA_CSS_FRAME_FORMAT_YUV422:
case IA_CSS_FRAME_FORMAT_YUV444:
@@ -607,12 +607,12 @@ set_output_frame_buffer(const struct ia_css_frame *frame,
}
static int
-set_view_finder_buffer(const struct ia_css_frame *frame) {
+set_view_finder_buffer(const struct ia_css_frame *frame)
+{
if (!frame)
return -EINVAL;
- switch (frame->info.format)
- {
+ switch (frame->info.format) {
/* the dual output pin */
case IA_CSS_FRAME_FORMAT_NV12:
case IA_CSS_FRAME_FORMAT_NV12_16:
@@ -732,7 +732,8 @@ sh_css_sp_set_disable_continuous_viewfinder(bool flag)
}
static int
-sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) {
+sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args)
+{
int err = 0;
int i;
@@ -742,8 +743,7 @@ sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) {
err = set_input_frame_buffer(args->in_frame);
if (!err && args->out_vf_frame)
err = set_view_finder_buffer(args->out_vf_frame);
- for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
- {
+ for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
if (!err && args->out_frame[i])
err = set_output_frame_buffer(args->out_frame[i], i);
}
@@ -786,7 +786,8 @@ sh_css_stage_write_binary_info(struct ia_css_binary_info *info)
}
static int
-copy_isp_mem_if_to_ddr(struct ia_css_binary *binary) {
+copy_isp_mem_if_to_ddr(struct ia_css_binary *binary)
+{
int err;
err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
@@ -817,7 +818,8 @@ configure_isp_from_args(
const struct ia_css_binary *binary,
const struct sh_css_binary_args *args,
bool two_ppc,
- bool deinterleaved) {
+ bool deinterleaved)
+{
ia_css_fpn_configure(binary, &binary->in_frame_info);
ia_css_crop_configure(binary, &args->delay_frames[0]->info);
ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info);
@@ -896,7 +898,8 @@ sh_css_sp_init_stage(struct ia_css_binary *binary,
bool xnr,
const struct ia_css_isp_param_css_segments *isp_mem_if,
unsigned int if_config_index,
- bool two_ppc) {
+ bool two_ppc)
+{
const struct ia_css_binary_xinfo *xinfo;
const struct ia_css_binary_info *info;
int err = 0;
@@ -928,8 +931,7 @@ sh_css_sp_init_stage(struct ia_css_binary *binary,
ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
- if (!info)
- {
+ if (!info) {
sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL;
return 0;
}
@@ -961,8 +963,7 @@ sh_css_sp_init_stage(struct ia_css_binary *binary,
ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.in.info,
&binary->in_frame_info);
- for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
- {
+ for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info,
&binary->out_frame_info[i]);
}
@@ -996,16 +997,14 @@ sh_css_sp_init_stage(struct ia_css_binary *binary,
err = sh_css_sp_write_frame_pointers(args);
/* TODO: move it to a better place */
- if (binary->info->sp.enable.s3a)
- {
+ if (binary->info->sp.enable.s3a) {
ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id,
&queue_id);
sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id,
mmgr_EXCEPTION,
IA_CSS_BUFFER_TYPE_3A_STATISTICS);
}
- if (binary->info->sp.enable.dis)
- {
+ if (binary->info->sp.enable.dis) {
ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id,
&queue_id);
sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id,
@@ -1046,8 +1045,7 @@ sh_css_sp_init_stage(struct ia_css_binary *binary,
* the original out res. for video pipe, it has two output pins --- out and
* vf_out, so it can keep these two resolutions already. */
if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW &&
- (binary->vf_downscale_log2 > 0))
- {
+ (binary->vf_downscale_log2 > 0)) {
/* TODO: Remove this after preview output decimation is fixed
* by configuring out&vf info fiels properly */
sh_css_sp_stage.frames.out[0].info.padded_width
@@ -1069,7 +1067,8 @@ sp_init_stage(struct ia_css_pipeline_stage *stage,
unsigned int pipe_num,
bool xnr,
unsigned int if_config_index,
- bool two_ppc) {
+ bool two_ppc)
+{
struct ia_css_binary *binary;
const struct ia_css_fw_info *firmware;
const struct sh_css_binary_args *args;
@@ -1105,14 +1104,12 @@ sp_init_stage(struct ia_css_pipeline_stage *stage,
args = &stage->args;
stage_num = stage->stage_num;
- if (binary)
- {
+ if (binary) {
info = binary->info;
binary_name = (const char *)(info->blob->name);
blob_info = &info->blob->header.blob;
ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params);
- } else if (firmware)
- {
+ } else if (firmware) {
const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
if (args->out_frame[0])
@@ -1133,8 +1130,7 @@ sp_init_stage(struct ia_css_pipeline_stage *stage,
binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware);
blob_info = &firmware->blob;
mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers;
- } else
- {
+ } else {
/* SP stage */
assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
/* binary and blob_info are now NULL.
@@ -1205,7 +1201,8 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
*internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame
positioned on shading table at shading correction in ISP. */
const struct ia_css_isp_parameters *params
- ) {
+ )
+{
/* Get first stage */
struct ia_css_pipeline_stage *stage = NULL;
struct ia_css_binary *first_binary = NULL;
@@ -1223,17 +1220,14 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
first_binary = me->stages->binary;
if (input_mode == IA_CSS_INPUT_MODE_SENSOR ||
- input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
- {
+ input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
assert(port_id < N_MIPI_PORT_ID);
if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */
return; /* we should be able to return an error */
if_config_index = (uint8_t)(port_id - MIPI_PORT0_ID);
- } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY)
- {
+ } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY) {
if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
- } else
- {
+ } else {
if_config_index = 0x0;
}
@@ -1241,15 +1235,13 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));
/* Count stages */
- for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
- {
+ for (stage = me->stages, num = 0; stage; stage = stage->next, num++) {
stage->stage_num = num;
ia_css_debug_pipe_graph_dump_stage(stage, id);
}
me->num_stages = num;
- if (first_binary)
- {
+ if (first_binary) {
/* Init pipeline data */
sh_css_sp_init_group(two_ppc, first_binary->input_format,
offline, if_config_index);
@@ -1277,8 +1269,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
/* TODO: next indicates from which queues parameters need to be
sampled, needs checking/improvement */
- if (ia_css_pipeline_uses_params(me))
- {
+ if (ia_css_pipeline_uses_params(me)) {
sh_css_sp_group.pipe[thread_id].pipe_config =
SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id;
}
@@ -1292,15 +1283,13 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
pipe = find_pipe_by_num(pipe_num);
assert(pipe);
- if (!pipe)
- {
+ if (!pipe) {
return;
}
sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe);
#if defined(SH_CSS_ENABLE_METADATA)
- if (md_info && md_info->size > 0)
- {
+ if (md_info && md_info->size > 0) {
sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width;
sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height;
sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride;
@@ -1316,8 +1305,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID;
- if (pipe_id != IA_CSS_PIPE_ID_COPY)
- {
+ if (pipe_id != IA_CSS_PIPE_ID_COPY) {
ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id,
(enum sh_css_queue_id *)(
&sh_css_sp_group.pipe[thread_id].output_frame_queue_id));
@@ -1329,14 +1317,12 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
* the parameters are passed to the isp for the shading table centering.
*/
if (internal_frame_origin_bqs_on_sctbl &&
- params && params->shading_settings.enable_shading_table_conversion == 0)
- {
+ params && params->shading_settings.enable_shading_table_conversion == 0) {
sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl
= (uint32_t)internal_frame_origin_bqs_on_sctbl->x;
sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl
= (uint32_t)internal_frame_origin_bqs_on_sctbl->y;
- } else
- {
+ } else {
sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl =
0;
sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl =
@@ -1347,8 +1333,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
IA_CSS_LOG("pipe_id %d port_config %08x",
pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config);
- for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
- {
+ for (stage = me->stages, num = 0; stage; stage = stage->next, num++) {
sh_css_sp_group.pipe[thread_id].num_stages++;
if (is_sp_stage(stage)) {
sp_init_sp_stage(stage, pipe_num, two_ppc,
@@ -1400,7 +1385,8 @@ bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command)
}
enum host2sp_commands
-sh_css_read_host2sp_command(void) {
+sh_css_read_host2sp_command(void)
+{
unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command)
/ sizeof(int);
@@ -1586,7 +1572,8 @@ sh_css_event_init_irq_mask(void)
int
ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe,
unsigned int or_mask,
- unsigned int and_mask) {
+ unsigned int and_mask)
+{
unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
unsigned int offset;
struct sh_css_event_irq_mask event_irq_mask;
@@ -1625,7 +1612,8 @@ ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe,
int
ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe,
unsigned int *or_mask,
- unsigned int *and_mask) {
+ unsigned int *and_mask)
+{
unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
unsigned int offset;
struct sh_css_event_irq_mask event_irq_mask;
diff --git a/drivers/staging/media/atomisp/pci/sh_css_version.c b/drivers/staging/media/atomisp/pci/sh_css_version.c
index fa6de61e4995..f5ff8ca66b50 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_version.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_version.c
@@ -21,7 +21,8 @@
#include "sh_css_firmware.h"
int
-ia_css_get_version(char *version, int max_size) {
+ia_css_get_version(char *version, int max_size)
+{
char *css_version;
if (!IS_ISP2401)
diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile
index 287370188d2a..90036831fec4 100644
--- a/drivers/staging/media/hantro/Makefile
+++ b/drivers/staging/media/hantro/Makefile
@@ -13,6 +13,7 @@ hantro-vpu-y += \
hantro_g2_hevc_dec.o \
hantro_g1_vp8_dec.o \
rockchip_vpu2_hw_jpeg_enc.o \
+ rockchip_vpu2_hw_h264_dec.o \
rockchip_vpu2_hw_mpeg2_dec.o \
rockchip_vpu2_hw_vp8_dec.o \
hantro_jpeg.o \
diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h
index a70c386de6f1..c2e2dca38628 100644
--- a/drivers/staging/media/hantro/hantro.h
+++ b/drivers/staging/media/hantro/hantro.h
@@ -61,8 +61,8 @@ struct hantro_irq {
* @num_postproc_fmts: Number of post-processor formats.
* @codec: Supported codecs
* @codec_ops: Codec ops.
- * @init: Initialize hardware.
- * @runtime_resume: reenable hardware after power gating
+ * @init: Initialize hardware, optional.
+ * @runtime_resume: reenable hardware after power gating, optional.
* @irqs: array of irq names and interrupt handlers
* @num_irqs: number of irqs in the array
* @clk_names: array of clock names
diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
index 31d8449ca1d2..8a2edd67f2c6 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -582,6 +582,7 @@ static const struct v4l2_file_operations hantro_fops = {
static const struct of_device_id of_hantro_match[] = {
#ifdef CONFIG_VIDEO_HANTRO_ROCKCHIP
+ { .compatible = "rockchip,px30-vpu", .data = &px30_vpu_variant, },
{ .compatible = "rockchip,rk3036-vpu", .data = &rk3036_vpu_variant, },
{ .compatible = "rockchip,rk3066-vpu", .data = &rk3066_vpu_variant, },
{ .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, },
@@ -942,10 +943,12 @@ static int hantro_probe(struct platform_device *pdev)
}
}
- ret = vpu->variant->init(vpu);
- if (ret) {
- dev_err(&pdev->dev, "Failed to init VPU hardware\n");
- return ret;
+ if (vpu->variant->init) {
+ ret = vpu->variant->init(vpu);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to init VPU hardware\n");
+ return ret;
+ }
}
pm_runtime_set_autosuspend_delay(vpu->dev, 100);
diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
index 5c792b7bcb79..236ce24ca00c 100644
--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c
+++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
@@ -19,13 +19,12 @@
#include "hantro_hw.h"
#include "hantro_v4l2.h"
-static void set_params(struct hantro_ctx *ctx)
+static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
- struct vb2_v4l2_buffer *src_buf = hantro_get_src_buf(ctx);
struct hantro_dev *vpu = ctx->dev;
u32 reg;
@@ -127,28 +126,14 @@ static void set_params(struct hantro_ctx *ctx)
static void set_ref(struct hantro_ctx *ctx)
{
- struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
const u8 *b0_reflist, *b1_reflist, *p_reflist;
struct hantro_dev *vpu = ctx->dev;
- u32 dpb_longterm = 0;
- u32 dpb_valid = 0;
int reg_num;
u32 reg;
int i;
- /*
- * Set up bit maps of valid and long term DPBs.
- * NOTE: The bits are reversed, i.e. MSb is DPB 0.
- */
- for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) {
- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
- dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i);
-
- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
- dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i);
- }
- vdpu_write_relaxed(vpu, dpb_valid << 16, G1_REG_VALID_REF);
- vdpu_write_relaxed(vpu, dpb_longterm << 16, G1_REG_LT_REF);
+ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF);
+ vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF);
/*
* Set up reference frame picture numbers.
@@ -157,17 +142,8 @@ static void set_ref(struct hantro_ctx *ctx)
* subsequential reference pictures.
*/
for (i = 0; i < HANTRO_H264_DPB_SIZE; i += 2) {
- reg = 0;
- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
- reg |= G1_REG_REF_PIC_REFER0_NBR(dpb[i].pic_num);
- else
- reg |= G1_REG_REF_PIC_REFER0_NBR(dpb[i].frame_num);
-
- if (dpb[i + 1].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
- reg |= G1_REG_REF_PIC_REFER1_NBR(dpb[i + 1].pic_num);
- else
- reg |= G1_REG_REF_PIC_REFER1_NBR(dpb[i + 1].frame_num);
-
+ reg = G1_REG_REF_PIC_REFER0_NBR(hantro_h264_get_ref_nbr(ctx, i)) |
+ G1_REG_REF_PIC_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, i + 1));
vdpu_write_relaxed(vpu, reg, G1_REG_REF_PIC(i / 2));
}
@@ -226,22 +202,20 @@ static void set_ref(struct hantro_ctx *ctx)
}
}
-static void set_buffers(struct hantro_ctx *ctx)
+static void set_buffers(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ struct vb2_v4l2_buffer *dst_buf;
struct hantro_dev *vpu = ctx->dev;
dma_addr_t src_dma, dst_dma;
size_t offset = 0;
- src_buf = hantro_get_src_buf(ctx);
- dst_buf = hantro_get_dst_buf(ctx);
-
/* Source (stream) buffer. */
src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
vdpu_write_relaxed(vpu, src_dma, G1_REG_ADDR_STR);
/* Destination (decoded frame) buffer. */
+ dst_buf = hantro_get_dst_buf(ctx);
dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf);
/* Adjust dma addr to start at second line for bottom field */
if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
@@ -276,6 +250,7 @@ static void set_buffers(struct hantro_ctx *ctx)
int hantro_g1_h264_dec_run(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
+ struct vb2_v4l2_buffer *src_buf;
int ret;
/* Prepare the H264 decoder context. */
@@ -284,9 +259,10 @@ int hantro_g1_h264_dec_run(struct hantro_ctx *ctx)
return ret;
/* Configure hardware registers. */
- set_params(ctx);
+ src_buf = hantro_get_src_buf(ctx);
+ set_params(ctx, src_buf);
set_ref(ctx);
- set_buffers(ctx);
+ set_buffers(ctx, src_buf);
hantro_end_prepare_run(ctx);
diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c
index 96622a7f8279..6180b23e7d94 100644
--- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c
+++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c
@@ -367,21 +367,25 @@ static void cfg_tap(struct hantro_ctx *ctx,
}
static void cfg_ref(struct hantro_ctx *ctx,
- const struct v4l2_ctrl_vp8_frame *hdr)
+ const struct v4l2_ctrl_vp8_frame *hdr,
+ struct vb2_v4l2_buffer *vb2_dst)
{
struct hantro_dev *vpu = ctx->dev;
- struct vb2_v4l2_buffer *vb2_dst;
dma_addr_t ref;
- vb2_dst = hantro_get_dst_buf(ctx);
ref = hantro_get_ref(ctx, hdr->last_frame_ts);
- if (!ref)
+ if (!ref) {
+ vpu_debug(0, "failed to find last frame ts=%llu\n",
+ hdr->last_frame_ts);
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
+ }
vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(0));
ref = hantro_get_ref(ctx, hdr->golden_frame_ts);
- WARN_ON(!ref && hdr->golden_frame_ts);
+ if (!ref && hdr->golden_frame_ts)
+ vpu_debug(0, "failed to find golden frame ts=%llu\n",
+ hdr->golden_frame_ts);
if (!ref)
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN)
@@ -389,7 +393,9 @@ static void cfg_ref(struct hantro_ctx *ctx,
vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(4));
ref = hantro_get_ref(ctx, hdr->alt_frame_ts);
- WARN_ON(!ref && hdr->alt_frame_ts);
+ if (!ref && hdr->alt_frame_ts)
+ vpu_debug(0, "failed to find alt frame ts=%llu\n",
+ hdr->alt_frame_ts);
if (!ref)
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT)
@@ -398,16 +404,14 @@ static void cfg_ref(struct hantro_ctx *ctx,
}
static void cfg_buffers(struct hantro_ctx *ctx,
- const struct v4l2_ctrl_vp8_frame *hdr)
+ const struct v4l2_ctrl_vp8_frame *hdr,
+ struct vb2_v4l2_buffer *vb2_dst)
{
const struct v4l2_vp8_segment *seg = &hdr->segment;
struct hantro_dev *vpu = ctx->dev;
- struct vb2_v4l2_buffer *vb2_dst;
dma_addr_t dst_dma;
u32 reg;
- vb2_dst = hantro_get_dst_buf(ctx);
-
/* Set probability table buffer address */
vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma,
G1_REG_ADDR_QTABLE);
@@ -429,6 +433,7 @@ int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_vp8_frame *hdr;
struct hantro_dev *vpu = ctx->dev;
+ struct vb2_v4l2_buffer *vb2_dst;
size_t height = ctx->dst_fmt.height;
size_t width = ctx->dst_fmt.width;
u32 mb_width, mb_height;
@@ -492,8 +497,10 @@ int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx)
cfg_qp(ctx, hdr);
cfg_parts(ctx, hdr);
cfg_tap(ctx, hdr);
- cfg_ref(ctx, hdr);
- cfg_buffers(ctx, hdr);
+
+ vb2_dst = hantro_get_dst_buf(ctx);
+ cfg_ref(ctx, hdr, vb2_dst);
+ cfg_buffers(ctx, hdr, vb2_dst);
hantro_end_prepare_run(ctx);
diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c
index ed6eaf11d96f..0b4d2491be3b 100644
--- a/drivers/staging/media/hantro/hantro_h264.c
+++ b/drivers/staging/media/hantro/hantro_h264.c
@@ -229,12 +229,25 @@ static void prepare_table(struct hantro_ctx *ctx)
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu;
const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
+ u32 dpb_longterm = 0;
+ u32 dpb_valid = 0;
int i;
for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) {
tbl->poc[i * 2] = dpb[i].top_field_order_cnt;
tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt;
+
+ /*
+ * Set up bit maps of valid and long term DPBs.
+ * NOTE: The bits are reversed, i.e. MSb is DPB 0.
+ */
+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
+ dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i);
+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
+ dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i);
}
+ ctx->h264_dec.dpb_valid = dpb_valid << 16;
+ ctx->h264_dec.dpb_longterm = dpb_longterm << 16;
tbl->poc[32] = dec_param->top_field_order_cnt;
tbl->poc[33] = dec_param->bottom_field_order_cnt;
@@ -335,6 +348,17 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
return dma_addr;
}
+u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, unsigned int dpb_idx)
+{
+ const struct v4l2_h264_dpb_entry *dpb = &ctx->h264_dec.dpb[dpb_idx];
+
+ if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
+ return 0;
+ if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
+ return dpb->pic_num;
+ return dpb->frame_num;
+}
+
int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
{
struct hantro_h264_dec_hw_ctx *h264_ctx = &ctx->h264_dec;
diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h
index 5dcf65805396..df7b5e3a57b9 100644
--- a/drivers/staging/media/hantro/hantro_hw.h
+++ b/drivers/staging/media/hantro/hantro_hw.h
@@ -89,12 +89,16 @@ struct hantro_h264_dec_reflists {
* @dpb: DPB
* @reflists: P/B0/B1 reflists
* @ctrls: V4L2 controls attached to a run
+ * @dpb_longterm: DPB long-term
+ * @dpb_valid: DPB valid
*/
struct hantro_h264_dec_hw_ctx {
struct hantro_aux_buf priv;
struct v4l2_h264_dpb_entry dpb[HANTRO_H264_DPB_SIZE];
struct hantro_h264_dec_reflists reflists;
struct hantro_h264_dec_ctrls ctrls;
+ u32 dpb_longterm;
+ u32 dpb_valid;
};
/**
@@ -205,6 +209,7 @@ enum hantro_enc_fmt {
extern const struct hantro_variant imx8mq_vpu_g2_variant;
extern const struct hantro_variant imx8mq_vpu_variant;
+extern const struct hantro_variant px30_vpu_variant;
extern const struct hantro_variant rk3036_vpu_variant;
extern const struct hantro_variant rk3066_vpu_variant;
extern const struct hantro_variant rk3288_vpu_variant;
@@ -234,7 +239,10 @@ void hantro_jpeg_enc_done(struct hantro_ctx *ctx);
dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
unsigned int dpb_idx);
+u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx,
+ unsigned int dpb_idx);
int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx);
+int rockchip_vpu2_h264_dec_run(struct hantro_ctx *ctx);
int hantro_g1_h264_dec_run(struct hantro_ctx *ctx);
int hantro_h264_dec_init(struct hantro_ctx *ctx);
void hantro_h264_dec_exit(struct hantro_ctx *ctx);
diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c
new file mode 100644
index 000000000000..64a6330475eb
--- /dev/null
+++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c
@@ -0,0 +1,491 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hantro VPU codec driver
+ *
+ * Copyright (c) 2014 Rockchip Electronics Co., Ltd.
+ * Hertz Wong <hertz.wong@rock-chips.com>
+ * Herman Chen <herman.chen@rock-chips.com>
+ *
+ * Copyright (C) 2014 Google, Inc.
+ * Tomasz Figa <tfiga@chromium.org>
+ */
+
+#include <linux/types.h>
+#include <linux/sort.h>
+
+#include <media/v4l2-mem2mem.h>
+
+#include "hantro_hw.h"
+#include "hantro_v4l2.h"
+
+#define VDPU_SWREG(nr) ((nr) * 4)
+
+#define VDPU_REG_DEC_OUT_BASE VDPU_SWREG(63)
+#define VDPU_REG_RLC_VLC_BASE VDPU_SWREG(64)
+#define VDPU_REG_QTABLE_BASE VDPU_SWREG(61)
+#define VDPU_REG_DIR_MV_BASE VDPU_SWREG(62)
+#define VDPU_REG_REFER_BASE(i) (VDPU_SWREG(84 + (i)))
+#define VDPU_REG_DEC_E(v) ((v) ? BIT(0) : 0)
+
+#define VDPU_REG_DEC_ADV_PRE_DIS(v) ((v) ? BIT(11) : 0)
+#define VDPU_REG_DEC_SCMD_DIS(v) ((v) ? BIT(10) : 0)
+#define VDPU_REG_FILTERING_DIS(v) ((v) ? BIT(8) : 0)
+#define VDPU_REG_PIC_FIXED_QUANT(v) ((v) ? BIT(7) : 0)
+#define VDPU_REG_DEC_LATENCY(v) (((v) << 1) & GENMASK(6, 1))
+
+#define VDPU_REG_INIT_QP(v) (((v) << 25) & GENMASK(30, 25))
+#define VDPU_REG_STREAM_LEN(v) (((v) << 0) & GENMASK(23, 0))
+
+#define VDPU_REG_APF_THRESHOLD(v) (((v) << 17) & GENMASK(30, 17))
+#define VDPU_REG_STARTMB_X(v) (((v) << 8) & GENMASK(16, 8))
+#define VDPU_REG_STARTMB_Y(v) (((v) << 0) & GENMASK(7, 0))
+
+#define VDPU_REG_DEC_MODE(v) (((v) << 0) & GENMASK(3, 0))
+
+#define VDPU_REG_DEC_STRENDIAN_E(v) ((v) ? BIT(5) : 0)
+#define VDPU_REG_DEC_STRSWAP32_E(v) ((v) ? BIT(4) : 0)
+#define VDPU_REG_DEC_OUTSWAP32_E(v) ((v) ? BIT(3) : 0)
+#define VDPU_REG_DEC_INSWAP32_E(v) ((v) ? BIT(2) : 0)
+#define VDPU_REG_DEC_OUT_ENDIAN(v) ((v) ? BIT(1) : 0)
+#define VDPU_REG_DEC_IN_ENDIAN(v) ((v) ? BIT(0) : 0)
+
+#define VDPU_REG_DEC_DATA_DISC_E(v) ((v) ? BIT(22) : 0)
+#define VDPU_REG_DEC_MAX_BURST(v) (((v) << 16) & GENMASK(20, 16))
+#define VDPU_REG_DEC_AXI_WR_ID(v) (((v) << 8) & GENMASK(15, 8))
+#define VDPU_REG_DEC_AXI_RD_ID(v) (((v) << 0) & GENMASK(7, 0))
+
+#define VDPU_REG_START_CODE_E(v) ((v) ? BIT(22) : 0)
+#define VDPU_REG_CH_8PIX_ILEAV_E(v) ((v) ? BIT(21) : 0)
+#define VDPU_REG_RLC_MODE_E(v) ((v) ? BIT(20) : 0)
+#define VDPU_REG_PIC_INTERLACE_E(v) ((v) ? BIT(17) : 0)
+#define VDPU_REG_PIC_FIELDMODE_E(v) ((v) ? BIT(16) : 0)
+#define VDPU_REG_PIC_TOPFIELD_E(v) ((v) ? BIT(13) : 0)
+#define VDPU_REG_WRITE_MVS_E(v) ((v) ? BIT(10) : 0)
+#define VDPU_REG_SEQ_MBAFF_E(v) ((v) ? BIT(7) : 0)
+#define VDPU_REG_PICORD_COUNT_E(v) ((v) ? BIT(6) : 0)
+#define VDPU_REG_DEC_TIMEOUT_E(v) ((v) ? BIT(5) : 0)
+#define VDPU_REG_DEC_CLK_GATE_E(v) ((v) ? BIT(4) : 0)
+
+#define VDPU_REG_PRED_BC_TAP_0_0(v) (((v) << 22) & GENMASK(31, 22))
+#define VDPU_REG_PRED_BC_TAP_0_1(v) (((v) << 12) & GENMASK(21, 12))
+#define VDPU_REG_PRED_BC_TAP_0_2(v) (((v) << 2) & GENMASK(11, 2))
+
+#define VDPU_REG_REFBU_E(v) ((v) ? BIT(31) : 0)
+
+#define VDPU_REG_PINIT_RLIST_F9(v) (((v) << 25) & GENMASK(29, 25))
+#define VDPU_REG_PINIT_RLIST_F8(v) (((v) << 20) & GENMASK(24, 20))
+#define VDPU_REG_PINIT_RLIST_F7(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_PINIT_RLIST_F6(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_PINIT_RLIST_F5(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_PINIT_RLIST_F4(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_PINIT_RLIST_F15(v) (((v) << 25) & GENMASK(29, 25))
+#define VDPU_REG_PINIT_RLIST_F14(v) (((v) << 20) & GENMASK(24, 20))
+#define VDPU_REG_PINIT_RLIST_F13(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_PINIT_RLIST_F12(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_PINIT_RLIST_F11(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_PINIT_RLIST_F10(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_REFER1_NBR(v) (((v) << 16) & GENMASK(31, 16))
+#define VDPU_REG_REFER0_NBR(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_REFER3_NBR(v) (((v) << 16) & GENMASK(31, 16))
+#define VDPU_REG_REFER2_NBR(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_REFER5_NBR(v) (((v) << 16) & GENMASK(31, 16))
+#define VDPU_REG_REFER4_NBR(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_REFER7_NBR(v) (((v) << 16) & GENMASK(31, 16))
+#define VDPU_REG_REFER6_NBR(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_REFER9_NBR(v) (((v) << 16) & GENMASK(31, 16))
+#define VDPU_REG_REFER8_NBR(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_REFER11_NBR(v) (((v) << 16) & GENMASK(31, 16))
+#define VDPU_REG_REFER10_NBR(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_REFER13_NBR(v) (((v) << 16) & GENMASK(31, 16))
+#define VDPU_REG_REFER12_NBR(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_REFER15_NBR(v) (((v) << 16) & GENMASK(31, 16))
+#define VDPU_REG_REFER14_NBR(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_BINIT_RLIST_F5(v) (((v) << 25) & GENMASK(29, 25))
+#define VDPU_REG_BINIT_RLIST_F4(v) (((v) << 20) & GENMASK(24, 20))
+#define VDPU_REG_BINIT_RLIST_F3(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_BINIT_RLIST_F2(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_BINIT_RLIST_F1(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_BINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_BINIT_RLIST_F11(v) (((v) << 25) & GENMASK(29, 25))
+#define VDPU_REG_BINIT_RLIST_F10(v) (((v) << 20) & GENMASK(24, 20))
+#define VDPU_REG_BINIT_RLIST_F9(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_BINIT_RLIST_F8(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_BINIT_RLIST_F7(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_BINIT_RLIST_F6(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_BINIT_RLIST_F15(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_BINIT_RLIST_F14(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_BINIT_RLIST_F13(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_BINIT_RLIST_F12(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_BINIT_RLIST_B5(v) (((v) << 25) & GENMASK(29, 25))
+#define VDPU_REG_BINIT_RLIST_B4(v) (((v) << 20) & GENMASK(24, 20))
+#define VDPU_REG_BINIT_RLIST_B3(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_BINIT_RLIST_B2(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_BINIT_RLIST_B1(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_BINIT_RLIST_B0(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_BINIT_RLIST_B11(v) (((v) << 25) & GENMASK(29, 25))
+#define VDPU_REG_BINIT_RLIST_B10(v) (((v) << 20) & GENMASK(24, 20))
+#define VDPU_REG_BINIT_RLIST_B9(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_BINIT_RLIST_B8(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_BINIT_RLIST_B7(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_BINIT_RLIST_B6(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_BINIT_RLIST_B15(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_BINIT_RLIST_B14(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_BINIT_RLIST_B13(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_BINIT_RLIST_B12(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_PINIT_RLIST_F3(v) (((v) << 15) & GENMASK(19, 15))
+#define VDPU_REG_PINIT_RLIST_F2(v) (((v) << 10) & GENMASK(14, 10))
+#define VDPU_REG_PINIT_RLIST_F1(v) (((v) << 5) & GENMASK(9, 5))
+#define VDPU_REG_PINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_REFER_LTERM_E(v) (((v) << 0) & GENMASK(31, 0))
+
+#define VDPU_REG_REFER_VALID_E(v) (((v) << 0) & GENMASK(31, 0))
+
+#define VDPU_REG_STRM_START_BIT(v) (((v) << 0) & GENMASK(5, 0))
+
+#define VDPU_REG_CH_QP_OFFSET2(v) (((v) << 22) & GENMASK(26, 22))
+#define VDPU_REG_CH_QP_OFFSET(v) (((v) << 17) & GENMASK(21, 17))
+#define VDPU_REG_PIC_MB_HEIGHT_P(v) (((v) << 9) & GENMASK(16, 9))
+#define VDPU_REG_PIC_MB_WIDTH(v) (((v) << 0) & GENMASK(8, 0))
+
+#define VDPU_REG_WEIGHT_BIPR_IDC(v) (((v) << 16) & GENMASK(17, 16))
+#define VDPU_REG_REF_FRAMES(v) (((v) << 0) & GENMASK(4, 0))
+
+#define VDPU_REG_FILT_CTRL_PRES(v) ((v) ? BIT(31) : 0)
+#define VDPU_REG_RDPIC_CNT_PRES(v) ((v) ? BIT(30) : 0)
+#define VDPU_REG_FRAMENUM_LEN(v) (((v) << 16) & GENMASK(20, 16))
+#define VDPU_REG_FRAMENUM(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_REFPIC_MK_LEN(v) (((v) << 16) & GENMASK(26, 16))
+#define VDPU_REG_IDR_PIC_ID(v) (((v) << 0) & GENMASK(15, 0))
+
+#define VDPU_REG_PPS_ID(v) (((v) << 24) & GENMASK(31, 24))
+#define VDPU_REG_REFIDX1_ACTIVE(v) (((v) << 19) & GENMASK(23, 19))
+#define VDPU_REG_REFIDX0_ACTIVE(v) (((v) << 14) & GENMASK(18, 14))
+#define VDPU_REG_POC_LENGTH(v) (((v) << 0) & GENMASK(7, 0))
+
+#define VDPU_REG_IDR_PIC_E(v) ((v) ? BIT(8) : 0)
+#define VDPU_REG_DIR_8X8_INFER_E(v) ((v) ? BIT(7) : 0)
+#define VDPU_REG_BLACKWHITE_E(v) ((v) ? BIT(6) : 0)
+#define VDPU_REG_CABAC_E(v) ((v) ? BIT(5) : 0)
+#define VDPU_REG_WEIGHT_PRED_E(v) ((v) ? BIT(4) : 0)
+#define VDPU_REG_CONST_INTRA_E(v) ((v) ? BIT(3) : 0)
+#define VDPU_REG_8X8TRANS_FLAG_E(v) ((v) ? BIT(2) : 0)
+#define VDPU_REG_TYPE1_QUANT_E(v) ((v) ? BIT(1) : 0)
+#define VDPU_REG_FIELDPIC_FLAG_E(v) ((v) ? BIT(0) : 0)
+
+static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
+{
+ const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
+ const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
+ const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
+ const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
+ struct hantro_dev *vpu = ctx->dev;
+ u32 reg;
+
+ reg = VDPU_REG_DEC_ADV_PRE_DIS(0) |
+ VDPU_REG_DEC_SCMD_DIS(0) |
+ VDPU_REG_FILTERING_DIS(0) |
+ VDPU_REG_PIC_FIXED_QUANT(0) |
+ VDPU_REG_DEC_LATENCY(0);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(50));
+
+ reg = VDPU_REG_INIT_QP(pps->pic_init_qp_minus26 + 26) |
+ VDPU_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(51));
+
+ reg = VDPU_REG_APF_THRESHOLD(8) |
+ VDPU_REG_STARTMB_X(0) |
+ VDPU_REG_STARTMB_Y(0);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(52));
+
+ reg = VDPU_REG_DEC_MODE(0);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(53));
+
+ reg = VDPU_REG_DEC_STRENDIAN_E(1) |
+ VDPU_REG_DEC_STRSWAP32_E(1) |
+ VDPU_REG_DEC_OUTSWAP32_E(1) |
+ VDPU_REG_DEC_INSWAP32_E(1) |
+ VDPU_REG_DEC_OUT_ENDIAN(1) |
+ VDPU_REG_DEC_IN_ENDIAN(0);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(54));
+
+ reg = VDPU_REG_DEC_DATA_DISC_E(0) |
+ VDPU_REG_DEC_MAX_BURST(16) |
+ VDPU_REG_DEC_AXI_WR_ID(0) |
+ VDPU_REG_DEC_AXI_RD_ID(0xff);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(56));
+
+ reg = VDPU_REG_START_CODE_E(1) |
+ VDPU_REG_CH_8PIX_ILEAV_E(0) |
+ VDPU_REG_RLC_MODE_E(0) |
+ VDPU_REG_PIC_INTERLACE_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) &&
+ (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD ||
+ dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) |
+ VDPU_REG_PIC_FIELDMODE_E(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) |
+ VDPU_REG_PIC_TOPFIELD_E(!(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)) |
+ VDPU_REG_WRITE_MVS_E((sps->profile_idc > 66) && dec_param->nal_ref_idc) |
+ VDPU_REG_SEQ_MBAFF_E(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) |
+ VDPU_REG_PICORD_COUNT_E(sps->profile_idc > 66) |
+ VDPU_REG_DEC_TIMEOUT_E(1) |
+ VDPU_REG_DEC_CLK_GATE_E(1);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(57));
+
+ reg = VDPU_REG_PRED_BC_TAP_0_0(1) |
+ VDPU_REG_PRED_BC_TAP_0_1((u32)-5) |
+ VDPU_REG_PRED_BC_TAP_0_2(20);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(59));
+
+ reg = VDPU_REG_REFBU_E(0);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(65));
+
+ reg = VDPU_REG_STRM_START_BIT(0);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(109));
+
+ reg = VDPU_REG_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset) |
+ VDPU_REG_CH_QP_OFFSET(pps->chroma_qp_index_offset) |
+ VDPU_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) |
+ VDPU_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(110));
+
+ reg = VDPU_REG_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc) |
+ VDPU_REG_REF_FRAMES(sps->max_num_ref_frames);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(111));
+
+ reg = VDPU_REG_FILT_CTRL_PRES(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT) |
+ VDPU_REG_RDPIC_CNT_PRES(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT) |
+ VDPU_REG_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) |
+ VDPU_REG_FRAMENUM(dec_param->frame_num);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(112));
+
+ reg = VDPU_REG_REFPIC_MK_LEN(dec_param->dec_ref_pic_marking_bit_size) |
+ VDPU_REG_IDR_PIC_ID(dec_param->idr_pic_id);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(113));
+
+ reg = VDPU_REG_PPS_ID(pps->pic_parameter_set_id) |
+ VDPU_REG_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) |
+ VDPU_REG_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) |
+ VDPU_REG_POC_LENGTH(dec_param->pic_order_cnt_bit_size);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(114));
+
+ reg = VDPU_REG_IDR_PIC_E(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) |
+ VDPU_REG_DIR_8X8_INFER_E(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) |
+ VDPU_REG_BLACKWHITE_E(sps->profile_idc >= 100 && sps->chroma_format_idc == 0) |
+ VDPU_REG_CABAC_E(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) |
+ VDPU_REG_WEIGHT_PRED_E(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) |
+ VDPU_REG_CONST_INTRA_E(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED) |
+ VDPU_REG_8X8TRANS_FLAG_E(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE) |
+ VDPU_REG_TYPE1_QUANT_E(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT) |
+ VDPU_REG_FIELDPIC_FLAG_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(115));
+}
+
+static void set_ref(struct hantro_ctx *ctx)
+{
+ const u8 *b0_reflist, *b1_reflist, *p_reflist;
+ struct hantro_dev *vpu = ctx->dev;
+ u32 reg;
+ int i;
+
+ b0_reflist = ctx->h264_dec.reflists.b0;
+ b1_reflist = ctx->h264_dec.reflists.b1;
+ p_reflist = ctx->h264_dec.reflists.p;
+
+ reg = VDPU_REG_PINIT_RLIST_F9(p_reflist[9]) |
+ VDPU_REG_PINIT_RLIST_F8(p_reflist[8]) |
+ VDPU_REG_PINIT_RLIST_F7(p_reflist[7]) |
+ VDPU_REG_PINIT_RLIST_F6(p_reflist[6]) |
+ VDPU_REG_PINIT_RLIST_F5(p_reflist[5]) |
+ VDPU_REG_PINIT_RLIST_F4(p_reflist[4]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(74));
+
+ reg = VDPU_REG_PINIT_RLIST_F15(p_reflist[15]) |
+ VDPU_REG_PINIT_RLIST_F14(p_reflist[14]) |
+ VDPU_REG_PINIT_RLIST_F13(p_reflist[13]) |
+ VDPU_REG_PINIT_RLIST_F12(p_reflist[12]) |
+ VDPU_REG_PINIT_RLIST_F11(p_reflist[11]) |
+ VDPU_REG_PINIT_RLIST_F10(p_reflist[10]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(75));
+
+ reg = VDPU_REG_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, 1)) |
+ VDPU_REG_REFER0_NBR(hantro_h264_get_ref_nbr(ctx, 0));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(76));
+
+ reg = VDPU_REG_REFER3_NBR(hantro_h264_get_ref_nbr(ctx, 3)) |
+ VDPU_REG_REFER2_NBR(hantro_h264_get_ref_nbr(ctx, 2));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(77));
+
+ reg = VDPU_REG_REFER5_NBR(hantro_h264_get_ref_nbr(ctx, 5)) |
+ VDPU_REG_REFER4_NBR(hantro_h264_get_ref_nbr(ctx, 4));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(78));
+
+ reg = VDPU_REG_REFER7_NBR(hantro_h264_get_ref_nbr(ctx, 7)) |
+ VDPU_REG_REFER6_NBR(hantro_h264_get_ref_nbr(ctx, 6));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(79));
+
+ reg = VDPU_REG_REFER9_NBR(hantro_h264_get_ref_nbr(ctx, 9)) |
+ VDPU_REG_REFER8_NBR(hantro_h264_get_ref_nbr(ctx, 8));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(80));
+
+ reg = VDPU_REG_REFER11_NBR(hantro_h264_get_ref_nbr(ctx, 11)) |
+ VDPU_REG_REFER10_NBR(hantro_h264_get_ref_nbr(ctx, 10));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(81));
+
+ reg = VDPU_REG_REFER13_NBR(hantro_h264_get_ref_nbr(ctx, 13)) |
+ VDPU_REG_REFER12_NBR(hantro_h264_get_ref_nbr(ctx, 12));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(82));
+
+ reg = VDPU_REG_REFER15_NBR(hantro_h264_get_ref_nbr(ctx, 15)) |
+ VDPU_REG_REFER14_NBR(hantro_h264_get_ref_nbr(ctx, 14));
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(83));
+
+ reg = VDPU_REG_BINIT_RLIST_F5(b0_reflist[5]) |
+ VDPU_REG_BINIT_RLIST_F4(b0_reflist[4]) |
+ VDPU_REG_BINIT_RLIST_F3(b0_reflist[3]) |
+ VDPU_REG_BINIT_RLIST_F2(b0_reflist[2]) |
+ VDPU_REG_BINIT_RLIST_F1(b0_reflist[1]) |
+ VDPU_REG_BINIT_RLIST_F0(b0_reflist[0]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(100));
+
+ reg = VDPU_REG_BINIT_RLIST_F11(b0_reflist[11]) |
+ VDPU_REG_BINIT_RLIST_F10(b0_reflist[10]) |
+ VDPU_REG_BINIT_RLIST_F9(b0_reflist[9]) |
+ VDPU_REG_BINIT_RLIST_F8(b0_reflist[8]) |
+ VDPU_REG_BINIT_RLIST_F7(b0_reflist[7]) |
+ VDPU_REG_BINIT_RLIST_F6(b0_reflist[6]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(101));
+
+ reg = VDPU_REG_BINIT_RLIST_F15(b0_reflist[15]) |
+ VDPU_REG_BINIT_RLIST_F14(b0_reflist[14]) |
+ VDPU_REG_BINIT_RLIST_F13(b0_reflist[13]) |
+ VDPU_REG_BINIT_RLIST_F12(b0_reflist[12]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(102));
+
+ reg = VDPU_REG_BINIT_RLIST_B5(b1_reflist[5]) |
+ VDPU_REG_BINIT_RLIST_B4(b1_reflist[4]) |
+ VDPU_REG_BINIT_RLIST_B3(b1_reflist[3]) |
+ VDPU_REG_BINIT_RLIST_B2(b1_reflist[2]) |
+ VDPU_REG_BINIT_RLIST_B1(b1_reflist[1]) |
+ VDPU_REG_BINIT_RLIST_B0(b1_reflist[0]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(103));
+
+ reg = VDPU_REG_BINIT_RLIST_B11(b1_reflist[11]) |
+ VDPU_REG_BINIT_RLIST_B10(b1_reflist[10]) |
+ VDPU_REG_BINIT_RLIST_B9(b1_reflist[9]) |
+ VDPU_REG_BINIT_RLIST_B8(b1_reflist[8]) |
+ VDPU_REG_BINIT_RLIST_B7(b1_reflist[7]) |
+ VDPU_REG_BINIT_RLIST_B6(b1_reflist[6]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(104));
+
+ reg = VDPU_REG_BINIT_RLIST_B15(b1_reflist[15]) |
+ VDPU_REG_BINIT_RLIST_B14(b1_reflist[14]) |
+ VDPU_REG_BINIT_RLIST_B13(b1_reflist[13]) |
+ VDPU_REG_BINIT_RLIST_B12(b1_reflist[12]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(105));
+
+ reg = VDPU_REG_PINIT_RLIST_F3(p_reflist[3]) |
+ VDPU_REG_PINIT_RLIST_F2(p_reflist[2]) |
+ VDPU_REG_PINIT_RLIST_F1(p_reflist[1]) |
+ VDPU_REG_PINIT_RLIST_F0(p_reflist[0]);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(106));
+
+ reg = VDPU_REG_REFER_LTERM_E(ctx->h264_dec.dpb_longterm);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(107));
+
+ reg = VDPU_REG_REFER_VALID_E(ctx->h264_dec.dpb_valid);
+ vdpu_write_relaxed(vpu, reg, VDPU_SWREG(108));
+
+ /* Set up addresses of DPB buffers. */
+ for (i = 0; i < HANTRO_H264_DPB_SIZE; i++) {
+ dma_addr_t dma_addr = hantro_h264_get_ref_buf(ctx, i);
+
+ vdpu_write_relaxed(vpu, dma_addr, VDPU_REG_REFER_BASE(i));
+ }
+}
+
+static void set_buffers(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
+{
+ const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
+ struct vb2_v4l2_buffer *dst_buf;
+ struct hantro_dev *vpu = ctx->dev;
+ dma_addr_t src_dma, dst_dma;
+ size_t offset = 0;
+
+ /* Source (stream) buffer. */
+ src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+ vdpu_write_relaxed(vpu, src_dma, VDPU_REG_RLC_VLC_BASE);
+
+ /* Destination (decoded frame) buffer. */
+ dst_buf = hantro_get_dst_buf(ctx);
+ dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf);
+ /* Adjust dma addr to start at second line for bottom field */
+ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
+ offset = ALIGN(ctx->src_fmt.width, MB_DIM);
+ vdpu_write_relaxed(vpu, dst_dma + offset, VDPU_REG_DEC_OUT_BASE);
+
+ /* Higher profiles require DMV buffer appended to reference frames. */
+ if (ctrls->sps->profile_idc > 66 && ctrls->decode->nal_ref_idc) {
+ unsigned int bytes_per_mb = 384;
+
+ /* DMV buffer for monochrome start directly after Y-plane */
+ if (ctrls->sps->profile_idc >= 100 &&
+ ctrls->sps->chroma_format_idc == 0)
+ bytes_per_mb = 256;
+ offset = bytes_per_mb * MB_WIDTH(ctx->src_fmt.width) *
+ MB_HEIGHT(ctx->src_fmt.height);
+
+ /*
+ * DMV buffer is split in two for field encoded frames,
+ * adjust offset for bottom field
+ */
+ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)
+ offset += 32 * MB_WIDTH(ctx->src_fmt.width) *
+ MB_HEIGHT(ctx->src_fmt.height);
+ vdpu_write_relaxed(vpu, dst_dma + offset, VDPU_REG_DIR_MV_BASE);
+ }
+
+ /* Auxiliary buffer prepared in hantro_g1_h264_dec_prepare_table(). */
+ vdpu_write_relaxed(vpu, ctx->h264_dec.priv.dma, VDPU_REG_QTABLE_BASE);
+}
+
+int rockchip_vpu2_h264_dec_run(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct vb2_v4l2_buffer *src_buf;
+ u32 reg;
+ int ret;
+
+ /* Prepare the H264 decoder context. */
+ ret = hantro_h264_dec_prepare_run(ctx);
+ if (ret)
+ return ret;
+
+ src_buf = hantro_get_src_buf(ctx);
+ set_params(ctx, src_buf);
+ set_ref(ctx);
+ set_buffers(ctx, src_buf);
+
+ hantro_end_prepare_run(ctx);
+
+ /* Start decoding! */
+ reg = vdpu_read(vpu, VDPU_SWREG(57)) | VDPU_REG_DEC_E(1);
+ vdpu_write(vpu, reg, VDPU_SWREG(57));
+
+ return 0;
+}
diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c
index 951b55f58a61..d079075448c9 100644
--- a/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c
+++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c
@@ -444,21 +444,24 @@ static void cfg_tap(struct hantro_ctx *ctx,
}
static void cfg_ref(struct hantro_ctx *ctx,
- const struct v4l2_ctrl_vp8_frame *hdr)
+ const struct v4l2_ctrl_vp8_frame *hdr,
+ struct vb2_v4l2_buffer *vb2_dst)
{
struct hantro_dev *vpu = ctx->dev;
- struct vb2_v4l2_buffer *vb2_dst;
dma_addr_t ref;
- vb2_dst = hantro_get_dst_buf(ctx);
-
ref = hantro_get_ref(ctx, hdr->last_frame_ts);
- if (!ref)
+ if (!ref) {
+ vpu_debug(0, "failed to find last frame ts=%llu\n",
+ hdr->last_frame_ts);
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
+ }
vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF0);
ref = hantro_get_ref(ctx, hdr->golden_frame_ts);
- WARN_ON(!ref && hdr->golden_frame_ts);
+ if (!ref && hdr->golden_frame_ts)
+ vpu_debug(0, "failed to find golden frame ts=%llu\n",
+ hdr->golden_frame_ts);
if (!ref)
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN)
@@ -466,7 +469,9 @@ static void cfg_ref(struct hantro_ctx *ctx,
vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF2_5(2));
ref = hantro_get_ref(ctx, hdr->alt_frame_ts);
- WARN_ON(!ref && hdr->alt_frame_ts);
+ if (!ref && hdr->alt_frame_ts)
+ vpu_debug(0, "failed to find alt frame ts=%llu\n",
+ hdr->alt_frame_ts);
if (!ref)
ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT)
@@ -475,16 +480,14 @@ static void cfg_ref(struct hantro_ctx *ctx,
}
static void cfg_buffers(struct hantro_ctx *ctx,
- const struct v4l2_ctrl_vp8_frame *hdr)
+ const struct v4l2_ctrl_vp8_frame *hdr,
+ struct vb2_v4l2_buffer *vb2_dst)
{
const struct v4l2_vp8_segment *seg = &hdr->segment;
struct hantro_dev *vpu = ctx->dev;
- struct vb2_v4l2_buffer *vb2_dst;
dma_addr_t dst_dma;
u32 reg;
- vb2_dst = hantro_get_dst_buf(ctx);
-
/* Set probability table buffer address */
vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma,
VDPU_REG_ADDR_QTABLE);
@@ -507,6 +510,7 @@ int rockchip_vpu2_vp8_dec_run(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_vp8_frame *hdr;
struct hantro_dev *vpu = ctx->dev;
+ struct vb2_v4l2_buffer *vb2_dst;
size_t height = ctx->dst_fmt.height;
size_t width = ctx->dst_fmt.width;
u32 mb_width, mb_height;
@@ -583,8 +587,10 @@ int rockchip_vpu2_vp8_dec_run(struct hantro_ctx *ctx)
cfg_qp(ctx, hdr);
cfg_parts(ctx, hdr);
cfg_tap(ctx, hdr);
- cfg_ref(ctx, hdr);
- cfg_buffers(ctx, hdr);
+
+ vb2_dst = hantro_get_dst_buf(ctx);
+ cfg_ref(ctx, hdr, vb2_dst);
+ cfg_buffers(ctx, hdr, vb2_dst);
hantro_end_prepare_run(ctx);
diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c
index 3ccc16413f42..d4f52957cc53 100644
--- a/drivers/staging/media/hantro/rockchip_vpu_hw.c
+++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c
@@ -163,6 +163,19 @@ static const struct hantro_fmt rk3399_vpu_dec_fmts[] = {
.codec_mode = HANTRO_MODE_NONE,
},
{
+ .fourcc = V4L2_PIX_FMT_H264_SLICE,
+ .codec_mode = HANTRO_MODE_H264_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 1920,
+ .step_width = MB_DIM,
+ .min_height = 48,
+ .max_height = 1088,
+ .step_height = MB_DIM,
+ },
+ },
+ {
.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
.codec_mode = HANTRO_MODE_MPEG2_DEC,
.max_depth = 2,
@@ -388,6 +401,12 @@ static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = {
.init = hantro_jpeg_enc_init,
.exit = hantro_jpeg_enc_exit,
},
+ [HANTRO_MODE_H264_DEC] = {
+ .run = rockchip_vpu2_h264_dec_run,
+ .reset = rockchip_vpu2_dec_reset,
+ .init = hantro_h264_dec_init,
+ .exit = hantro_h264_dec_exit,
+ },
[HANTRO_MODE_MPEG2_DEC] = {
.run = rockchip_vpu2_mpeg2_dec_run,
.reset = rockchip_vpu2_dec_reset,
@@ -433,6 +452,8 @@ static const char * const rockchip_vpu_clk_names[] = {
"aclk", "hclk"
};
+/* VDPU1/VEPU1 */
+
const struct hantro_variant rk3036_vpu_variant = {
.dec_offset = 0x400,
.dec_fmts = rk3066_vpu_dec_fmts,
@@ -495,11 +516,14 @@ const struct hantro_variant rk3288_vpu_variant = {
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
+/* VDPU2/VEPU2 */
+
const struct hantro_variant rk3328_vpu_variant = {
.dec_offset = 0x400,
.dec_fmts = rk3399_vpu_dec_fmts,
.num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts),
- .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER,
+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
+ HANTRO_H264_DECODER,
.codec_ops = rk3399_vpu_codec_ops,
.irqs = rockchip_vdpu2_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vdpu2_irqs),
@@ -524,3 +548,20 @@ const struct hantro_variant rk3399_vpu_variant = {
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
+
+const struct hantro_variant px30_vpu_variant = {
+ .enc_offset = 0x0,
+ .enc_fmts = rockchip_vpu_enc_fmts,
+ .num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts),
+ .dec_offset = 0x400,
+ .dec_fmts = rk3399_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts),
+ .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER |
+ HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
+ .codec_ops = rk3399_vpu_codec_ops,
+ .irqs = rockchip_vpu2_irqs,
+ .num_irqs = ARRAY_SIZE(rockchip_vpu2_irqs),
+ .init = rk3036_vpu_hw_init,
+ .clk_names = rockchip_vpu_clk_names,
+ .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
+};
diff --git a/drivers/staging/media/hantro/sama5d4_vdec_hw.c b/drivers/staging/media/hantro/sama5d4_vdec_hw.c
index 58ae72c2b723..9c3b8cd0b239 100644
--- a/drivers/staging/media/hantro/sama5d4_vdec_hw.c
+++ b/drivers/staging/media/hantro/sama5d4_vdec_hw.c
@@ -64,11 +64,6 @@ static const struct hantro_fmt sama5d4_vdec_fmts[] = {
},
};
-static int sama5d4_hw_init(struct hantro_dev *vpu)
-{
- return 0;
-}
-
/*
* Supported codec ops.
*/
@@ -109,7 +104,6 @@ const struct hantro_variant sama5d4_vdec_variant = {
.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER,
.codec_ops = sama5d4_vdec_codec_ops,
- .init = sama5d4_hw_init,
.irqs = sama5d4_irqs,
.num_irqs = ARRAY_SIZE(sama5d4_irqs),
.clk_names = sama5d4_clk_names,
diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile
index 6ac33275cc97..19c2fc54d424 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-mipi-csis.o
+obj-$(CONFIG_VIDEO_IMX7_CSI) += imx8mq-mipi-csi2.o
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
index 894c4de31790..127183732912 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -361,6 +361,7 @@ static void imx7_csi_dma_unsetup_vb2_buf(struct imx7_csi *csi,
vb->timestamp = ktime_get_ns();
vb2_buffer_done(vb, return_status);
+ csi->active_vb2_buf[i] = NULL;
}
}
}
@@ -386,9 +387,10 @@ static int imx7_csi_dma_setup(struct imx7_csi *csi)
return 0;
}
-static void imx7_csi_dma_cleanup(struct imx7_csi *csi)
+static void imx7_csi_dma_cleanup(struct imx7_csi *csi,
+ enum vb2_buffer_state return_status)
{
- imx7_csi_dma_unsetup_vb2_buf(csi, VB2_BUF_STATE_ERROR);
+ imx7_csi_dma_unsetup_vb2_buf(csi, return_status);
imx_media_free_dma_buf(csi->dev, &csi->underrun_buf);
}
@@ -421,6 +423,7 @@ static void imx7_csi_configure(struct imx7_csi *csi)
struct v4l2_pix_format *out_pix = &vdev->fmt;
int width = out_pix->width;
u32 stride = 0;
+ u32 cr3 = BIT_FRMCNT_RST;
u32 cr1, cr18;
cr18 = imx7_csi_reg_read(csi, CSI_CSICR18);
@@ -464,6 +467,7 @@ static void imx7_csi_configure(struct imx7_csi *csi)
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
+ cr3 |= BIT_TWO_8BIT_SENSOR;
cr18 |= BIT_MIPI_DATA_FORMAT_RAW10;
break;
case MEDIA_BUS_FMT_Y12_1X12:
@@ -471,6 +475,7 @@ static void imx7_csi_configure(struct imx7_csi *csi)
case MEDIA_BUS_FMT_SGBRG12_1X12:
case MEDIA_BUS_FMT_SGRBG12_1X12:
case MEDIA_BUS_FMT_SRGGB12_1X12:
+ cr3 |= BIT_TWO_8BIT_SENSOR;
cr18 |= BIT_MIPI_DATA_FORMAT_RAW12;
break;
case MEDIA_BUS_FMT_Y14_1X14:
@@ -478,6 +483,7 @@ static void imx7_csi_configure(struct imx7_csi *csi)
case MEDIA_BUS_FMT_SGBRG14_1X14:
case MEDIA_BUS_FMT_SGRBG14_1X14:
case MEDIA_BUS_FMT_SRGGB14_1X14:
+ cr3 |= BIT_TWO_8BIT_SENSOR;
cr18 |= BIT_MIPI_DATA_FORMAT_RAW14;
break;
/*
@@ -491,26 +497,11 @@ static void imx7_csi_configure(struct imx7_csi *csi)
cr18 |= BIT_MIPI_DATA_FORMAT_YUV422_8B;
break;
}
-
- switch (out_pix->pixelformat) {
- case V4L2_PIX_FMT_Y10:
- case V4L2_PIX_FMT_Y12:
- case V4L2_PIX_FMT_SBGGR8:
- case V4L2_PIX_FMT_SGBRG8:
- case V4L2_PIX_FMT_SGRBG8:
- case V4L2_PIX_FMT_SRGGB8:
- case V4L2_PIX_FMT_SBGGR16:
- case V4L2_PIX_FMT_SGBRG16:
- case V4L2_PIX_FMT_SGRBG16:
- case V4L2_PIX_FMT_SRGGB16:
- cr1 |= BIT_PIXEL_BIT;
- break;
- }
}
imx7_csi_reg_write(csi, cr1, CSI_CSICR1);
imx7_csi_reg_write(csi, BIT_DMA_BURST_TYPE_RFF_INCR16, CSI_CSICR2);
- imx7_csi_reg_write(csi, BIT_FRMCNT_RST, CSI_CSICR3);
+ imx7_csi_reg_write(csi, cr3, CSI_CSICR3);
imx7_csi_reg_write(csi, cr18, CSI_CSICR18);
imx7_csi_reg_write(csi, (width * out_pix->height) >> 2, CSI_CSIRXCNT);
@@ -537,9 +528,10 @@ static int imx7_csi_init(struct imx7_csi *csi)
return 0;
}
-static void imx7_csi_deinit(struct imx7_csi *csi)
+static void imx7_csi_deinit(struct imx7_csi *csi,
+ enum vb2_buffer_state return_status)
{
- imx7_csi_dma_cleanup(csi);
+ imx7_csi_dma_cleanup(csi, return_status);
imx7_csi_init_default(csi);
imx7_csi_dmareq_rff_disable(csi);
clk_disable_unprepare(csi->mclk);
@@ -702,7 +694,7 @@ static int imx7_csi_s_stream(struct v4l2_subdev *sd, int enable)
ret = v4l2_subdev_call(csi->src_sd, video, s_stream, 1);
if (ret < 0) {
- imx7_csi_deinit(csi);
+ imx7_csi_deinit(csi, VB2_BUF_STATE_QUEUED);
goto out_unlock;
}
@@ -712,7 +704,7 @@ static int imx7_csi_s_stream(struct v4l2_subdev *sd, int enable)
v4l2_subdev_call(csi->src_sd, video, s_stream, 0);
- imx7_csi_deinit(csi);
+ imx7_csi_deinit(csi, VB2_BUF_STATE_ERROR);
}
csi->is_streaming = !!enable;
diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
index ead696eb4610..41e33535de55 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -1019,10 +1019,8 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
case 6:
align = 2;
break;
- case 1:
- case 3:
- case 5:
- case 7:
+ default:
+ /* 1, 3, 5, 7 */
align = 3;
break;
}
diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
new file mode 100644
index 000000000000..a6f562009b9a
--- /dev/null
+++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
@@ -0,0 +1,991 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * NXP i.MX8MQ SoC series MIPI-CSI2 receiver driver
+ *
+ * Copyright (C) 2021 Purism SPC
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interconnect.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+
+#define MIPI_CSI2_DRIVER_NAME "imx8mq-mipi-csi2"
+#define MIPI_CSI2_SUBDEV_NAME MIPI_CSI2_DRIVER_NAME
+
+#define MIPI_CSI2_PAD_SINK 0
+#define MIPI_CSI2_PAD_SOURCE 1
+#define MIPI_CSI2_PADS_NUM 2
+
+#define MIPI_CSI2_DEF_PIX_WIDTH 640
+#define MIPI_CSI2_DEF_PIX_HEIGHT 480
+
+/* Register map definition */
+
+/* i.MX8MQ CSI-2 controller CSR */
+#define CSI2RX_CFG_NUM_LANES 0x100
+#define CSI2RX_CFG_DISABLE_DATA_LANES 0x104
+#define CSI2RX_BIT_ERR 0x108
+#define CSI2RX_IRQ_STATUS 0x10c
+#define CSI2RX_IRQ_MASK 0x110
+#define CSI2RX_IRQ_MASK_ALL 0x1ff
+#define CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE 0x8
+#define CSI2RX_ULPS_STATUS 0x114
+#define CSI2RX_PPI_ERRSOT_HS 0x118
+#define CSI2RX_PPI_ERRSOTSYNC_HS 0x11c
+#define CSI2RX_PPI_ERRESC 0x120
+#define CSI2RX_PPI_ERRSYNCESC 0x124
+#define CSI2RX_PPI_ERRCONTROL 0x128
+#define CSI2RX_CFG_DISABLE_PAYLOAD_0 0x12c
+#define CSI2RX_CFG_VID_VC_IGNORE 0x180
+#define CSI2RX_CFG_VID_VC 0x184
+#define CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL 0x188
+#define CSI2RX_CFG_DISABLE_PAYLOAD_1 0x130
+
+enum {
+ ST_POWERED = 1,
+ ST_STREAMING = 2,
+ ST_SUSPENDED = 4,
+};
+
+enum imx8mq_mipi_csi_clk {
+ CSI2_CLK_CORE,
+ CSI2_CLK_ESC,
+ CSI2_CLK_UI,
+ CSI2_NUM_CLKS,
+};
+
+static const char * const imx8mq_mipi_csi_clk_id[CSI2_NUM_CLKS] = {
+ [CSI2_CLK_CORE] = "core",
+ [CSI2_CLK_ESC] = "esc",
+ [CSI2_CLK_UI] = "ui",
+};
+
+#define CSI2_NUM_CLKS ARRAY_SIZE(imx8mq_mipi_csi_clk_id)
+
+#define GPR_CSI2_1_RX_ENABLE BIT(13)
+#define GPR_CSI2_1_VID_INTFC_ENB BIT(12)
+#define GPR_CSI2_1_HSEL BIT(10)
+#define GPR_CSI2_1_CONT_CLK_MODE BIT(8)
+#define GPR_CSI2_1_S_PRG_RXHS_SETTLE(x) (((x) & 0x3f) << 2)
+
+/*
+ * The send level configures the number of entries that must accumulate in
+ * the Pixel FIFO before the data will be transferred to the video output.
+ * The exact value needed for this configuration is dependent on the rate at
+ * which the sensor transfers data to the CSI-2 Controller and the user
+ * video clock.
+ *
+ * The calculation is the classical rate-in rate-out type of problem: If the
+ * video bandwidth is 10% faster than the incoming mipi data and the video
+ * line length is 500 pixels, then the fifo should be allowed to fill
+ * 10% of the line length or 50 pixels. If the gap data is ok, then the level
+ * can be set to 16 and ignored.
+ */
+#define CSI2RX_SEND_LEVEL 64
+
+struct csi_state {
+ struct device *dev;
+ void __iomem *regs;
+ struct clk_bulk_data clks[CSI2_NUM_CLKS];
+ struct reset_control *rst;
+ struct regulator *mipi_phy_regulator;
+
+ struct v4l2_subdev sd;
+ struct media_pad pads[MIPI_CSI2_PADS_NUM];
+ struct v4l2_async_notifier notifier;
+ struct v4l2_subdev *src_sd;
+
+ struct v4l2_fwnode_bus_mipi_csi2 bus;
+
+ struct mutex lock; /* Protect csi2_fmt, format_mbus, state, hs_settle */
+ const struct csi2_pix_format *csi2_fmt;
+ struct v4l2_mbus_framefmt format_mbus[MIPI_CSI2_PADS_NUM];
+ u32 state;
+ u32 hs_settle;
+
+ struct regmap *phy_gpr;
+ u8 phy_gpr_reg;
+
+ struct icc_path *icc_path;
+ s32 icc_path_bw;
+};
+
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+struct csi2_pix_format {
+ u32 code;
+ u8 width;
+};
+
+static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = {
+ /* RAW (Bayer and greyscale) formats. */
+ {
+ .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .width = 8,
+ }, {
+ .code = MEDIA_BUS_FMT_SGBRG8_1X8,
+ .width = 8,
+ }, {
+ .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .width = 8,
+ }, {
+ .code = MEDIA_BUS_FMT_SRGGB8_1X8,
+ .width = 8,
+ }, {
+ .code = MEDIA_BUS_FMT_Y8_1X8,
+ .width = 8,
+ }, {
+ .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .width = 10,
+ }, {
+ .code = MEDIA_BUS_FMT_SGBRG10_1X10,
+ .width = 10,
+ }, {
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .width = 10,
+ }, {
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .width = 10,
+ }, {
+ .code = MEDIA_BUS_FMT_Y10_1X10,
+ .width = 10,
+ }, {
+ .code = MEDIA_BUS_FMT_SBGGR12_1X12,
+ .width = 12,
+ }, {
+ .code = MEDIA_BUS_FMT_SGBRG12_1X12,
+ .width = 12,
+ }, {
+ .code = MEDIA_BUS_FMT_SGRBG12_1X12,
+ .width = 12,
+ }, {
+ .code = MEDIA_BUS_FMT_SRGGB12_1X12,
+ .width = 12,
+ }, {
+ .code = MEDIA_BUS_FMT_Y12_1X12,
+ .width = 12,
+ }, {
+ .code = MEDIA_BUS_FMT_SBGGR14_1X14,
+ .width = 14,
+ }, {
+ .code = MEDIA_BUS_FMT_SGBRG14_1X14,
+ .width = 14,
+ }, {
+ .code = MEDIA_BUS_FMT_SGRBG14_1X14,
+ .width = 14,
+ }, {
+ .code = MEDIA_BUS_FMT_SRGGB14_1X14,
+ .width = 14,
+ }, {
+ /* YUV formats */
+ .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .width = 16,
+ }, {
+ .code = MEDIA_BUS_FMT_YUYV8_1X16,
+ .width = 16,
+ }
+};
+
+static const struct csi2_pix_format *find_csi2_format(u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(imx8mq_mipi_csi_formats); i++)
+ if (code == imx8mq_mipi_csi_formats[i].code)
+ return &imx8mq_mipi_csi_formats[i];
+ return NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration
+ */
+
+static inline void imx8mq_mipi_csi_write(struct csi_state *state, u32 reg, u32 val)
+{
+ writel(val, state->regs + reg);
+}
+
+static int imx8mq_mipi_csi_sw_reset(struct csi_state *state)
+{
+ int ret;
+
+ /*
+ * these are most likely self-clearing reset bits. to make it
+ * more clear, the reset-imx7 driver should implement the
+ * .reset() operation.
+ */
+ ret = reset_control_assert(state->rst);
+ if (ret < 0) {
+ dev_err(state->dev, "Failed to assert resets: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void imx8mq_mipi_csi_system_enable(struct csi_state *state, int on)
+{
+ if (!on) {
+ imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, 0xf);
+ return;
+ }
+
+ regmap_update_bits(state->phy_gpr,
+ state->phy_gpr_reg,
+ 0x3fff,
+ GPR_CSI2_1_RX_ENABLE |
+ GPR_CSI2_1_VID_INTFC_ENB |
+ GPR_CSI2_1_HSEL |
+ GPR_CSI2_1_CONT_CLK_MODE |
+ GPR_CSI2_1_S_PRG_RXHS_SETTLE(state->hs_settle));
+}
+
+static void imx8mq_mipi_csi_set_params(struct csi_state *state)
+{
+ int lanes = state->bus.num_data_lanes;
+
+ imx8mq_mipi_csi_write(state, CSI2RX_CFG_NUM_LANES, lanes - 1);
+ imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES,
+ (0xf << lanes) & 0xf);
+ imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK, CSI2RX_IRQ_MASK_ALL);
+ /*
+ * 0x180 bit 0 controls the Virtual Channel behaviour: when set the
+ * interface ignores the Virtual Channel (VC) field in received packets;
+ * when cleared it causes the interface to only accept packets whose VC
+ * matches the value to which VC is set at offset 0x184.
+ */
+ imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_VC_IGNORE, 1);
+ imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL,
+ CSI2RX_SEND_LEVEL);
+}
+
+static int imx8mq_mipi_csi_clk_enable(struct csi_state *state)
+{
+ return clk_bulk_prepare_enable(CSI2_NUM_CLKS, state->clks);
+}
+
+static void imx8mq_mipi_csi_clk_disable(struct csi_state *state)
+{
+ clk_bulk_disable_unprepare(CSI2_NUM_CLKS, state->clks);
+}
+
+static int imx8mq_mipi_csi_clk_get(struct csi_state *state)
+{
+ unsigned int i;
+
+ for (i = 0; i < CSI2_NUM_CLKS; i++)
+ state->clks[i].id = imx8mq_mipi_csi_clk_id[i];
+
+ return devm_clk_bulk_get(state->dev, CSI2_NUM_CLKS, state->clks);
+}
+
+static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state)
+{
+ s64 link_freq;
+ u32 lane_rate;
+ unsigned long esc_clk_rate;
+ u32 min_ths_settle, max_ths_settle, ths_settle_ns, esc_clk_period_ns;
+
+ /* Calculate the line rate from the pixel rate. */
+ link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler,
+ state->csi2_fmt->width,
+ state->bus.num_data_lanes * 2);
+ if (link_freq < 0) {
+ dev_err(state->dev, "Unable to obtain link frequency: %d\n",
+ (int)link_freq);
+ return link_freq;
+ }
+
+ lane_rate = link_freq * 2;
+ if (lane_rate < 80000000 || lane_rate > 1500000000) {
+ dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
+ return -EINVAL;
+ }
+
+ /*
+ * The D-PHY specification requires Ths-settle to be in the range
+ * 85ns + 6*UI to 140ns + 10*UI, with the unit interval UI being half
+ * the clock period.
+ *
+ * The Ths-settle value is expressed in the hardware as a multiple of
+ * the Esc clock period:
+ *
+ * Ths-settle = (PRG_RXHS_SETTLE + 1) * Tperiod of RxClkInEsc
+ *
+ * Due to the one cycle inaccuracy introduced by rounding, the
+ * documentation recommends picking a value away from the boundaries.
+ * Let's pick the average.
+ */
+ esc_clk_rate = clk_get_rate(state->clks[CSI2_CLK_ESC].clk);
+ if (!esc_clk_rate) {
+ dev_err(state->dev, "Could not get esc clock rate.\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(state->dev, "esc clk rate: %lu\n", esc_clk_rate);
+ esc_clk_period_ns = 1000000000 / esc_clk_rate;
+
+ min_ths_settle = 85 + 6 * 1000000 / (lane_rate / 1000);
+ max_ths_settle = 140 + 10 * 1000000 / (lane_rate / 1000);
+ ths_settle_ns = (min_ths_settle + max_ths_settle) / 2;
+
+ state->hs_settle = ths_settle_ns / esc_clk_period_ns - 1;
+
+ dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n",
+ lane_rate, ths_settle_ns, state->hs_settle);
+
+ return 0;
+}
+
+static int imx8mq_mipi_csi_start_stream(struct csi_state *state)
+{
+ int ret;
+
+ ret = imx8mq_mipi_csi_sw_reset(state);
+ if (ret)
+ return ret;
+
+ imx8mq_mipi_csi_set_params(state);
+ ret = imx8mq_mipi_csi_calc_hs_settle(state);
+ if (ret)
+ return ret;
+
+ imx8mq_mipi_csi_system_enable(state, true);
+
+ return 0;
+}
+
+static void imx8mq_mipi_csi_stop_stream(struct csi_state *state)
+{
+ imx8mq_mipi_csi_system_enable(state, false);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static struct csi_state *mipi_sd_to_csi2_state(struct v4l2_subdev *sdev)
+{
+ return container_of(sdev, struct csi_state, sd);
+}
+
+static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ int ret = 0;
+
+ imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK,
+ CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE);
+
+ if (enable) {
+ ret = pm_runtime_resume_and_get(state->dev);
+ if (ret < 0)
+ return ret;
+ }
+
+ mutex_lock(&state->lock);
+
+ if (enable) {
+ if (state->state & ST_SUSPENDED) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ ret = imx8mq_mipi_csi_start_stream(state);
+ if (ret < 0)
+ goto unlock;
+
+ ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1);
+ if (ret < 0)
+ goto unlock;
+
+ state->state |= ST_STREAMING;
+ } else {
+ v4l2_subdev_call(state->src_sd, video, s_stream, 0);
+ imx8mq_mipi_csi_stop_stream(state);
+ state->state &= ~ST_STREAMING;
+ }
+
+unlock:
+ mutex_unlock(&state->lock);
+
+ if (!enable || ret < 0)
+ pm_runtime_put(state->dev);
+
+ return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+imx8mq_mipi_csi_get_format(struct csi_state *state,
+ struct v4l2_subdev_state *sd_state,
+ enum v4l2_subdev_format_whence which,
+ unsigned int pad)
+{
+ if (which == V4L2_SUBDEV_FORMAT_TRY)
+ return v4l2_subdev_get_try_format(&state->sd, sd_state, pad);
+
+ return &state->format_mbus[pad];
+}
+
+static int imx8mq_mipi_csi_init_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ struct v4l2_mbus_framefmt *fmt_sink;
+ struct v4l2_mbus_framefmt *fmt_source;
+ enum v4l2_subdev_format_whence which;
+
+ which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+ fmt_sink = imx8mq_mipi_csi_get_format(state, sd_state, which,
+ MIPI_CSI2_PAD_SINK);
+
+ fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10;
+ fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH;
+ fmt_sink->height = MIPI_CSI2_DEF_PIX_HEIGHT;
+ fmt_sink->field = V4L2_FIELD_NONE;
+
+ fmt_sink->colorspace = V4L2_COLORSPACE_RAW;
+ fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
+ fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
+ fmt_sink->quantization =
+ V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
+ fmt_sink->ycbcr_enc);
+
+ fmt_source = imx8mq_mipi_csi_get_format(state, sd_state, which,
+ MIPI_CSI2_PAD_SOURCE);
+ *fmt_source = *fmt_sink;
+
+ return 0;
+}
+
+static int imx8mq_mipi_csi_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *sdformat)
+{
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ struct v4l2_mbus_framefmt *fmt;
+
+ fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
+ sdformat->pad);
+
+ mutex_lock(&state->lock);
+
+ sdformat->format = *fmt;
+
+ mutex_unlock(&state->lock);
+
+ return 0;
+}
+
+static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+
+ /*
+ * We can't transcode in any way, the source format is identical
+ * to the sink format.
+ */
+ if (code->pad == MIPI_CSI2_PAD_SOURCE) {
+ struct v4l2_mbus_framefmt *fmt;
+
+ if (code->index > 0)
+ return -EINVAL;
+
+ fmt = imx8mq_mipi_csi_get_format(state, sd_state, code->which,
+ code->pad);
+ code->code = fmt->code;
+ return 0;
+ }
+
+ if (code->pad != MIPI_CSI2_PAD_SINK)
+ return -EINVAL;
+
+ if (code->index >= ARRAY_SIZE(imx8mq_mipi_csi_formats))
+ return -EINVAL;
+
+ code->code = imx8mq_mipi_csi_formats[code->index].code;
+
+ return 0;
+}
+
+static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *sdformat)
+{
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ struct csi2_pix_format const *csi2_fmt;
+ struct v4l2_mbus_framefmt *fmt;
+
+ /*
+ * The device can't transcode in any way, the source format can't be
+ * modified.
+ */
+ if (sdformat->pad == MIPI_CSI2_PAD_SOURCE)
+ return imx8mq_mipi_csi_get_fmt(sd, sd_state, sdformat);
+
+ if (sdformat->pad != MIPI_CSI2_PAD_SINK)
+ return -EINVAL;
+
+ csi2_fmt = find_csi2_format(sdformat->format.code);
+ if (!csi2_fmt)
+ csi2_fmt = &imx8mq_mipi_csi_formats[0];
+
+ fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
+ sdformat->pad);
+
+ mutex_lock(&state->lock);
+
+ fmt->code = csi2_fmt->code;
+ fmt->width = sdformat->format.width;
+ fmt->height = sdformat->format.height;
+
+ sdformat->format = *fmt;
+
+ /* Propagate the format from sink to source. */
+ fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
+ MIPI_CSI2_PAD_SOURCE);
+ *fmt = sdformat->format;
+
+ /* Store the CSI2 format descriptor for active formats. */
+ if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ state->csi2_fmt = csi2_fmt;
+
+ mutex_unlock(&state->lock);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops imx8mq_mipi_csi_video_ops = {
+ .s_stream = imx8mq_mipi_csi_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops imx8mq_mipi_csi_pad_ops = {
+ .init_cfg = imx8mq_mipi_csi_init_cfg,
+ .enum_mbus_code = imx8mq_mipi_csi_enum_mbus_code,
+ .get_fmt = imx8mq_mipi_csi_get_fmt,
+ .set_fmt = imx8mq_mipi_csi_set_fmt,
+};
+
+static const struct v4l2_subdev_ops imx8mq_mipi_csi_subdev_ops = {
+ .video = &imx8mq_mipi_csi_video_ops,
+ .pad = &imx8mq_mipi_csi_pad_ops,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+static const struct media_entity_operations imx8mq_mipi_csi_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+ .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
+};
+
+/* -----------------------------------------------------------------------------
+ * Async subdev notifier
+ */
+
+static struct csi_state *
+mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n)
+{
+ return container_of(n, struct csi_state, notifier);
+}
+
+static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+ struct csi_state *state = mipi_notifier_to_csi2_state(notifier);
+ struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK];
+
+ state->src_sd = sd;
+
+ return v4l2_create_fwnode_links_to_pad(sd, sink, MEDIA_LNK_FL_ENABLED |
+ MEDIA_LNK_FL_IMMUTABLE);
+}
+
+static const struct v4l2_async_notifier_operations imx8mq_mipi_csi_notify_ops = {
+ .bound = imx8mq_mipi_csi_notify_bound,
+};
+
+static int imx8mq_mipi_csi_async_register(struct csi_state *state)
+{
+ struct v4l2_fwnode_endpoint vep = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY,
+ };
+ struct v4l2_async_subdev *asd;
+ struct fwnode_handle *ep;
+ unsigned int i;
+ int ret;
+
+ v4l2_async_notifier_init(&state->notifier);
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (!ep)
+ return -ENOTCONN;
+
+ ret = v4l2_fwnode_endpoint_parse(ep, &vep);
+ if (ret)
+ goto err_parse;
+
+ for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
+ if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
+ dev_err(state->dev,
+ "data lanes reordering is not supported");
+ ret = -EINVAL;
+ goto err_parse;
+ }
+ }
+
+ state->bus = vep.bus.mipi_csi2;
+
+ dev_dbg(state->dev, "data lanes: %d flags: 0x%08x\n",
+ state->bus.num_data_lanes,
+ state->bus.flags);
+
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(&state->notifier,
+ ep, struct v4l2_async_subdev);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ goto err_parse;
+ }
+
+ fwnode_handle_put(ep);
+
+ state->notifier.ops = &imx8mq_mipi_csi_notify_ops;
+
+ ret = v4l2_async_subdev_notifier_register(&state->sd, &state->notifier);
+ if (ret)
+ return ret;
+
+ return v4l2_async_register_subdev(&state->sd);
+
+err_parse:
+ fwnode_handle_put(ep);
+
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+static int imx8mq_mipi_csi_pm_suspend(struct device *dev, bool runtime)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ int ret = 0;
+
+ mutex_lock(&state->lock);
+
+ if (state->state & ST_POWERED) {
+ imx8mq_mipi_csi_stop_stream(state);
+ imx8mq_mipi_csi_clk_disable(state);
+ state->state &= ~ST_POWERED;
+ if (!runtime)
+ state->state |= ST_SUSPENDED;
+ }
+
+ mutex_unlock(&state->lock);
+
+ ret = icc_set_bw(state->icc_path, 0, 0);
+ if (ret)
+ dev_err(dev, "icc_set_bw failed with %d\n", ret);
+
+ return ret ? -EAGAIN : 0;
+}
+
+static int imx8mq_mipi_csi_pm_resume(struct device *dev, bool runtime)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ int ret = 0;
+
+ ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw);
+ if (ret) {
+ dev_err(dev, "icc_set_bw failed with %d\n", ret);
+ return ret;
+ }
+
+ mutex_lock(&state->lock);
+
+ if (!runtime && !(state->state & ST_SUSPENDED))
+ goto unlock;
+
+ if (!(state->state & ST_POWERED)) {
+ state->state |= ST_POWERED;
+ ret = imx8mq_mipi_csi_clk_enable(state);
+ }
+ if (state->state & ST_STREAMING) {
+ ret = imx8mq_mipi_csi_start_stream(state);
+ if (ret)
+ goto unlock;
+ }
+
+ state->state &= ~ST_SUSPENDED;
+
+unlock:
+ mutex_unlock(&state->lock);
+
+ return ret ? -EAGAIN : 0;
+}
+
+static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev)
+{
+ return imx8mq_mipi_csi_pm_suspend(dev, false);
+}
+
+static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev)
+{
+ return imx8mq_mipi_csi_pm_resume(dev, false);
+}
+
+static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev)
+{
+ return imx8mq_mipi_csi_pm_suspend(dev, true);
+}
+
+static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev)
+{
+ return imx8mq_mipi_csi_pm_resume(dev, true);
+}
+
+static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = {
+ SET_RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend,
+ imx8mq_mipi_csi_runtime_resume,
+ NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume)
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe/remove & platform driver
+ */
+
+static int imx8mq_mipi_csi_subdev_init(struct csi_state *state)
+{
+ struct v4l2_subdev *sd = &state->sd;
+
+ v4l2_subdev_init(sd, &imx8mq_mipi_csi_subdev_ops);
+ sd->owner = THIS_MODULE;
+ snprintf(sd->name, sizeof(sd->name), "%s %s",
+ MIPI_CSI2_SUBDEV_NAME, dev_name(state->dev));
+
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+ sd->entity.ops = &imx8mq_mipi_csi_entity_ops;
+
+ sd->dev = state->dev;
+
+ state->csi2_fmt = &imx8mq_mipi_csi_formats[0];
+ imx8mq_mipi_csi_init_cfg(sd, NULL);
+
+ state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+ | MEDIA_PAD_FL_MUST_CONNECT;
+ state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
+ | MEDIA_PAD_FL_MUST_CONNECT;
+ return media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM,
+ state->pads);
+}
+
+static void imx8mq_mipi_csi_release_icc(struct platform_device *pdev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+
+ icc_put(state->icc_path);
+}
+
+static int imx8mq_mipi_csi_init_icc(struct platform_device *pdev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+
+ /* Optional interconnect request */
+ state->icc_path = of_icc_get(&pdev->dev, "dram");
+ if (IS_ERR_OR_NULL(state->icc_path))
+ return PTR_ERR_OR_ZERO(state->icc_path);
+
+ state->icc_path_bw = MBps_to_icc(700);
+
+ return 0;
+}
+
+static int imx8mq_mipi_csi_parse_dt(struct csi_state *state)
+{
+ struct device *dev = state->dev;
+ struct device_node *np = state->dev->of_node;
+ struct device_node *node;
+ phandle ph;
+ u32 out_val[2];
+ int ret = 0;
+
+ state->rst = devm_reset_control_array_get_exclusive(dev);
+ if (IS_ERR(state->rst)) {
+ dev_err(dev, "Failed to get reset: %pe\n", state->rst);
+ return PTR_ERR(state->rst);
+ }
+
+ ret = of_property_read_u32_array(np, "fsl,mipi-phy-gpr", out_val,
+ ARRAY_SIZE(out_val));
+ if (ret) {
+ dev_err(dev, "no fsl,mipi-phy-gpr property found: %d\n", ret);
+ return ret;
+ }
+
+ ph = *out_val;
+
+ node = of_find_node_by_phandle(ph);
+ if (!node) {
+ dev_err(dev, "Error finding node by phandle\n");
+ return -ENODEV;
+ }
+ state->phy_gpr = syscon_node_to_regmap(node);
+ of_node_put(node);
+ if (IS_ERR(state->phy_gpr)) {
+ dev_err(dev, "failed to get gpr regmap: %pe\n", state->phy_gpr);
+ return PTR_ERR(state->phy_gpr);
+ }
+
+ state->phy_gpr_reg = out_val[1];
+ dev_dbg(dev, "phy gpr register set to 0x%x\n", state->phy_gpr_reg);
+
+ return ret;
+}
+
+static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct csi_state *state;
+ int ret;
+
+ state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->dev = dev;
+
+ ret = imx8mq_mipi_csi_parse_dt(state);
+ if (ret < 0) {
+ dev_err(dev, "Failed to parse device tree: %d\n", ret);
+ return ret;
+ }
+
+ /* Acquire resources. */
+ state->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(state->regs))
+ return PTR_ERR(state->regs);
+
+ ret = imx8mq_mipi_csi_clk_get(state);
+ if (ret < 0)
+ return ret;
+
+ platform_set_drvdata(pdev, &state->sd);
+
+ mutex_init(&state->lock);
+
+ ret = imx8mq_mipi_csi_subdev_init(state);
+ if (ret < 0)
+ goto mutex;
+
+ ret = imx8mq_mipi_csi_init_icc(pdev);
+ if (ret)
+ goto mutex;
+
+ /* Enable runtime PM. */
+ pm_runtime_enable(dev);
+ if (!pm_runtime_enabled(dev)) {
+ ret = imx8mq_mipi_csi_pm_resume(dev, true);
+ if (ret < 0)
+ goto icc;
+ }
+
+ ret = imx8mq_mipi_csi_async_register(state);
+ if (ret < 0)
+ goto cleanup;
+
+ return 0;
+
+cleanup:
+ pm_runtime_disable(&pdev->dev);
+ imx8mq_mipi_csi_pm_suspend(&pdev->dev, true);
+
+ media_entity_cleanup(&state->sd.entity);
+ v4l2_async_notifier_unregister(&state->notifier);
+ v4l2_async_notifier_cleanup(&state->notifier);
+ v4l2_async_unregister_subdev(&state->sd);
+icc:
+ imx8mq_mipi_csi_release_icc(pdev);
+mutex:
+ mutex_destroy(&state->lock);
+
+ return ret;
+}
+
+static int imx8mq_mipi_csi_remove(struct platform_device *pdev)
+{
+ struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+
+ v4l2_async_notifier_unregister(&state->notifier);
+ v4l2_async_notifier_cleanup(&state->notifier);
+ v4l2_async_unregister_subdev(&state->sd);
+
+ pm_runtime_disable(&pdev->dev);
+ imx8mq_mipi_csi_pm_suspend(&pdev->dev, true);
+ media_entity_cleanup(&state->sd.entity);
+ mutex_destroy(&state->lock);
+ pm_runtime_set_suspended(&pdev->dev);
+ imx8mq_mipi_csi_release_icc(pdev);
+
+ return 0;
+}
+
+static const struct of_device_id imx8mq_mipi_csi_of_match[] = {
+ { .compatible = "fsl,imx8mq-mipi-csi2", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match);
+
+static struct platform_driver imx8mq_mipi_csi_driver = {
+ .probe = imx8mq_mipi_csi_probe,
+ .remove = imx8mq_mipi_csi_remove,
+ .driver = {
+ .of_match_table = imx8mq_mipi_csi_of_match,
+ .name = MIPI_CSI2_DRIVER_NAME,
+ .pm = &imx8mq_mipi_csi_pm_ops,
+ },
+};
+
+module_platform_driver(imx8mq_mipi_csi_driver);
+
+MODULE_DESCRIPTION("i.MX8MQ MIPI CSI-2 receiver driver");
+MODULE_AUTHOR("Martin Kepplinger <martin.kepplinger@puri.sm>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx8mq-mipi-csi2");
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 6821e3d05d34..ef0311a16d01 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -247,6 +247,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
const struct v4l2_ctrl_hevc_slice_params *slice_params;
const struct v4l2_ctrl_hevc_decode_params *decode_params;
const struct v4l2_hevc_pred_weight_table *pred_weight_table;
+ unsigned int width_in_ctb_luma, ctb_size_luma;
+ unsigned int log2_max_luma_coding_block_size;
dma_addr_t src_buf_addr;
dma_addr_t src_buf_end_addr;
u32 chroma_log2_weight_denom;
@@ -260,15 +262,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
decode_params = run->h265.decode_params;
pred_weight_table = &slice_params->pred_weight_table;
+ log2_max_luma_coding_block_size =
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
+ sps->log2_diff_max_min_luma_coding_block_size;
+ ctb_size_luma = 1UL << log2_max_luma_coding_block_size;
+ width_in_ctb_luma =
+ DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
+
/* MV column buffer size and allocation. */
if (!ctx->codec.h265.mv_col_buf_size) {
unsigned int num_buffers =
run->dst->vb2_buf.vb2_queue->num_buffers;
- unsigned int log2_max_luma_coding_block_size =
- sps->log2_min_luma_coding_block_size_minus3 + 3 +
- sps->log2_diff_max_min_luma_coding_block_size;
- unsigned int ctb_size_luma =
- 1UL << log2_max_luma_coding_block_size;
/*
* Each CTB requires a MV col buffer with a specific unit size.
@@ -322,15 +326,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
- /* Coding tree block address: start at the beginning. */
- reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0);
+ /* Coding tree block address */
+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma);
+ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma);
cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
/* Clear the number of correctly-decoded coding tree blocks. */
- cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
+ if (ctx->fh.m2m_ctx->new_frame)
+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
/* Initialize bitstream access. */
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
@@ -482,8 +488,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT,
slice_params->flags);
- /* FIXME: For multi-slice support. */
- reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
+ if (ctx->fh.m2m_ctx->new_frame)
+ reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 32c13ecb22d8..c589fe9dae70 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -340,6 +340,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void *priv,
switch (ctx->src_fmt.pixelformat) {
case V4L2_PIX_FMT_H264_SLICE:
+ case V4L2_PIX_FMT_HEVC_SLICE:
vq->subsystem_flags |=
VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
break;
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 89709cd06d4d..d321790b07d9 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -508,8 +508,8 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
return -ENODEV;
sd_state = v4l2_subdev_alloc_state(subdev);
- if (!sd_state)
- return -ENOMEM;
+ if (IS_ERR(sd_state))
+ return PTR_ERR(sd_state);
/*
* Retrieve the format information and if requested format isn't
* supported, keep the current format.
diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c
index 90933d78c332..b7858e47145f 100644
--- a/drivers/staging/most/video/video.c
+++ b/drivers/staging/most/video/video.c
@@ -258,7 +258,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (f->index)
return -EINVAL;
- strcpy(f->description, "MPEG");
+ strscpy(f->description, "MPEG", sizeof(f->description));
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
f->flags = V4L2_FMT_FLAG_COMPRESSED;
f->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -306,7 +306,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
if (input->index >= V4L2_CMP_MAX_INPUT)
return -EINVAL;
- strcpy(input->name, "MOST Video");
+ strscpy(input->name, "MOST Video", sizeof(input->name));
input->type |= V4L2_INPUT_TYPE_CAMERA;
input->audioset = 0;
diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c
index f9bdf4e33134..6acfc94a16e7 100644
--- a/drivers/staging/mt7621-pci/pci-mt7621.c
+++ b/drivers/staging/mt7621-pci/pci-mt7621.c
@@ -56,6 +56,7 @@
#define PCIE_BAR_ENABLE BIT(0)
#define PCIE_PORT_INT_EN(x) BIT(20 + (x))
#define PCIE_PORT_LINKUP BIT(0)
+#define PCIE_PORT_CNT 3
#define PERST_DELAY_MS 100
@@ -388,10 +389,11 @@ static void mt7621_pcie_reset_ep_deassert(struct mt7621_pcie *pcie)
msleep(PERST_DELAY_MS);
}
-static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
+static int mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
{
struct device *dev = pcie->dev;
struct mt7621_pcie_port *port, *tmp;
+ u8 num_disabled = 0;
int err;
mt7621_pcie_reset_assert(pcie);
@@ -423,6 +425,7 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
slot);
mt7621_control_assert(port);
port->enabled = false;
+ num_disabled++;
if (slot == 0) {
tmp = port;
@@ -433,6 +436,8 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
phy_power_off(tmp->phy);
}
}
+
+ return (num_disabled != PCIE_PORT_CNT) ? 0 : -ENODEV;
}
static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port)
@@ -540,7 +545,11 @@ static int mt7621_pci_probe(struct platform_device *pdev)
return err;
}
- mt7621_pcie_init_ports(pcie);
+ err = mt7621_pcie_init_ports(pcie);
+ if (err) {
+ dev_err(dev, "Nothing connected in virtual bridges\n");
+ return 0;
+ }
err = mt7621_pcie_enable_ports(bridge);
if (err) {
diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c
index 37e593f0fd82..66d28358342f 100644
--- a/drivers/staging/qlge/qlge_dbg.c
+++ b/drivers/staging/qlge/qlge_dbg.c
@@ -733,7 +733,7 @@ int qlge_core_dump(struct qlge_adapter *qdev, struct qlge_mpi_coredump *mpi_core
}
/* Insert the global header */
- memset(&(mpi_coredump->mpi_global_header), 0,
+ memset(&mpi_coredump->mpi_global_header, 0,
sizeof(struct mpi_coredump_global_header));
mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE;
mpi_coredump->mpi_global_header.header_size =
@@ -1221,7 +1221,7 @@ static void qlge_gen_reg_dump(struct qlge_adapter *qdev,
{
int i, status;
- memset(&(mpi_coredump->mpi_global_header), 0,
+ memset(&mpi_coredump->mpi_global_header, 0,
sizeof(struct mpi_coredump_global_header));
mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE;
mpi_coredump->mpi_global_header.header_size =
diff --git a/drivers/staging/rtl8188eu/Kconfig b/drivers/staging/r8188eu/Kconfig
index 970d5abd6336..dc1719d3f2e4 100644
--- a/drivers/staging/rtl8188eu/Kconfig
+++ b/drivers/staging/r8188eu/Kconfig
@@ -9,14 +9,15 @@ config R8188EU
select LIB80211_CRYPT_WEP
select LIB80211_CRYPT_CCMP
help
- This option adds the Realtek RTL8188EU USB device such as TP-Link TL-WN725N.
- If built as a module, it will be called r8188eu.
+ This option adds support for the Realtek RTL8188EU chipset, used in USB
+ devices such as the ASUS USB-N10 Nano. This newer driver is based on GitHub
+ sources for version v4.1.4_6773.20130222, and contains modifications for
+ newer kernel features. If built as a module, it will be called r8188eu.
if R8188EU
config 88EU_AP_MODE
bool "Realtek RTL8188EU AP mode"
- default y
help
This option enables Access Point mode. Unless you know that your system
will never be used as an AP, or the target system has limited memory,
diff --git a/drivers/staging/r8188eu/Makefile b/drivers/staging/r8188eu/Makefile
new file mode 100644
index 000000000000..aebaf29990fd
--- /dev/null
+++ b/drivers/staging/r8188eu/Makefile
@@ -0,0 +1,105 @@
+SHELL := /bin/bash
+EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS)
+EXTRA_CFLAGS += -O1
+
+ccflags-y += -D__CHECK_ENDIAN__
+
+CONFIG_BT_COEXIST = n
+CONFIG_WOWLAN = n
+
+OUTSRC_FILES := \
+ hal/HalHWImg8188E_MAC.o \
+ hal/HalHWImg8188E_BB.o \
+ hal/HalHWImg8188E_RF.o \
+ hal/HalPhyRf_8188e.o \
+ hal/HalPwrSeqCmd.o \
+ hal/Hal8188EPwrSeq.o \
+ hal/Hal8188ERateAdaptive.o\
+ hal/hal_intf.o \
+ hal/hal_com.o \
+ hal/odm.o \
+ hal/odm_debug.o \
+ hal/odm_interface.o \
+ hal/odm_HWConfig.o \
+ hal/odm_RegConfig8188E.o\
+ hal/odm_RTL8188E.o \
+ hal/rtl8188e_cmd.o \
+ hal/rtl8188e_dm.o \
+ hal/rtl8188e_hal_init.o \
+ hal/rtl8188e_mp.o \
+ hal/rtl8188e_phycfg.o \
+ hal/rtl8188e_rf6052.o \
+ hal/rtl8188e_rxdesc.o \
+ hal/rtl8188e_sreset.o \
+ hal/rtl8188e_xmit.o \
+ hal/rtl8188eu_led.o \
+ hal/rtl8188eu_recv.o \
+ hal/rtl8188eu_xmit.o \
+ hal/usb_halinit.o \
+ hal/usb_ops_linux.o
+
+RTL871X = rtl8188e
+
+HCI_NAME = usb
+
+_OS_INTFS_FILES := \
+ os_dep/ioctl_linux.o \
+ os_dep/mlme_linux.o \
+ os_dep/os_intfs.o \
+ os_dep/osdep_service.o \
+ os_dep/recv_linux.o \
+ os_dep/usb_intf.o \
+ os_dep/usb_ops_linux.o \
+ os_dep/xmit_linux.o
+
+_HAL_INTFS_FILES += $(OUTSRC_FILES)
+
+ifeq ($(CONFIG_BT_COEXIST), y)
+EXTRA_CFLAGS += -DCONFIG_BT_COEXIST
+endif
+
+ifeq ($(CONFIG_WOWLAN), y)
+EXTRA_CFLAGS += -DCONFIG_WOWLAN
+endif
+
+SUBARCH := $(shell uname -m | sed -e "s/i.86/i386/; s/ppc.*/powerpc/; s/armv.l/arm/; s/aarch64/arm64/;")
+
+ARCH ?= $(SUBARCH)
+CROSS_COMPILE ?=
+KVER ?= $(if $(KERNELRELEASE),$(KERNELRELEASE),$(shell uname -r))
+KSRC ?= $(if $(KERNEL_SRC),$(KERNEL_SRC),/lib/modules/$(KVER)/build)
+MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless
+INSTALL_PREFIX :=
+
+rtk_core := \
+ core/rtw_ap.o \
+ core/rtw_br_ext.o \
+ core/rtw_cmd.o \
+ core/rtw_debug.o \
+ core/rtw_efuse.o \
+ core/rtw_ieee80211.o \
+ core/rtw_io.o \
+ core/rtw_ioctl_set.o \
+ core/rtw_iol.o \
+ core/rtw_led.o \
+ core/rtw_mlme.o \
+ core/rtw_mlme_ext.o \
+ core/rtw_mp.o \
+ core/rtw_mp_ioctl.o \
+ core/rtw_pwrctrl.o \
+ core/rtw_p2p.o \
+ core/rtw_recv.o \
+ core/rtw_rf.o \
+ core/rtw_security.o \
+ core/rtw_sreset.o \
+ core/rtw_sta_mgt.o \
+ core/rtw_wlan_util.o \
+ core/rtw_xmit.o
+
+r8188eu-y += $(rtk_core)
+
+r8188eu-y += $(_HAL_INTFS_FILES)
+
+r8188eu-y += $(_OS_INTFS_FILES)
+
+obj-$(CONFIG_R8188EU) := r8188eu.o
diff --git a/drivers/staging/r8188eu/TODO b/drivers/staging/r8188eu/TODO
new file mode 100644
index 000000000000..ab9d5d145b3b
--- /dev/null
+++ b/drivers/staging/r8188eu/TODO
@@ -0,0 +1,16 @@
+To-do list:
+
+* Correct the coding style according to Linux guidelines; please read the document
+ at https://www.kernel.org/doc/html/latest/process/coding-style.html.
+* Remove unnecessary debugging/printing macros; for those that are still needed
+ use the proper kernel API (pr_debug(), dev_dbg(), netdev_dbg()).
+* Remove dead code such as unusued functions, variables, fields, etc..
+* Use in-kernel API and remove unnecessary wrappers where possible.
+* Fix bugs due to code that sleeps in atomic context.
+* Remove the HAL layer and migrate its functionality into the relevant parts of
+ the driver.
+* Switch to use LIB80211.
+* Switch to use MAC80211.
+* Switch to use CFG80211.
+* Improve the error handling of various functions, particularly those that use
+ existing kernel APIs.
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/r8188eu/core/rtw_ap.c
index b817aa8b9de4..1c07ad28b242 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/r8188eu/core/rtw_ap.c
@@ -1,18 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTW_AP_C_
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
-#include <linux/ieee80211.h>
+#define _RTW_AP_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <wifi.h>
-#include <ieee80211.h>
-#include <asm/unaligned.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/wifi.h"
+#include "../include/ieee80211.h"
#ifdef CONFIG_88EU_AP_MODE
@@ -61,86 +55,86 @@ static void update_BCNTIM(struct adapter *padapter)
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
- unsigned char *pie = pnetwork_mlmeext->ies;
- u8 *p, *dst_ie, *premainder_ie = NULL;
- u8 *pbackup_remainder_ie = NULL;
- uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
+ unsigned char *pie = pnetwork_mlmeext->IEs;
/* update TIM IE */
- p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, WLAN_EID_TIM, &tim_ielen,
- pnetwork_mlmeext->ie_length - _FIXED_IE_LENGTH_);
- if (p && tim_ielen > 0) {
- tim_ielen += 2;
- premainder_ie = p + tim_ielen;
- tim_ie_offset = (int)(p - pie);
- remainder_ielen = pnetwork_mlmeext->ie_length -
- tim_ie_offset - tim_ielen;
- /* append TIM IE from dst_ie offset */
- dst_ie = p;
- } else {
- tim_ielen = 0;
+ if (true) {
+ u8 *p, *dst_ie, *premainder_ie = NULL;
+ u8 *pbackup_remainder_ie = NULL;
+ __le16 tim_bitmap_le;
+ uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
+
+ tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
+
+ p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
+ if (p && tim_ielen > 0) {
+ tim_ielen += 2;
+ premainder_ie = p + tim_ielen;
+ tim_ie_offset = (int)(p - pie);
+ remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
+ /* append TIM IE from dst_ie offset */
+ dst_ie = p;
+ } else {
+ tim_ielen = 0;
- /* calculate head_len */
- offset = _FIXED_IE_LENGTH_;
- offset += pnetwork_mlmeext->ssid.ssid_length + 2;
+ /* calculate head_len */
+ offset = _FIXED_IE_LENGTH_;
+ offset += pnetwork_mlmeext->Ssid.SsidLength + 2;
- /* get supported rates len */
- p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES,
- &tmp_len, (pnetwork_mlmeext->ie_length -
- _BEACON_IE_OFFSET_));
- if (p)
- offset += tmp_len + 2;
+ /* get supported rates len */
+ p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
+ if (p)
+ offset += tmp_len + 2;
- /* DS Parameter Set IE, len = 3 */
- offset += 3;
+ /* DS Parameter Set IE, len = 3 */
+ offset += 3;
- premainder_ie = pie + offset;
+ premainder_ie = pie + offset;
- remainder_ielen = pnetwork_mlmeext->ie_length -
- offset - tim_ielen;
+ remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
- /* append TIM IE from offset */
- dst_ie = pie + offset;
- }
+ /* append TIM IE from offset */
+ dst_ie = pie + offset;
+ }
- if (remainder_ielen > 0) {
- pbackup_remainder_ie = rtw_malloc(remainder_ielen);
- if (pbackup_remainder_ie && premainder_ie)
- memcpy(pbackup_remainder_ie, premainder_ie,
- remainder_ielen);
- }
- *dst_ie++ = WLAN_EID_TIM;
+ if (remainder_ielen > 0) {
+ pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC);
+ if (pbackup_remainder_ie && premainder_ie)
+ memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+ }
+ *dst_ie++ = _TIM_IE_;
- if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fc))
- tim_ielen = 5;
- else
- tim_ielen = 4;
+ if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fc))
+ tim_ielen = 5;
+ else
+ tim_ielen = 4;
- *dst_ie++ = tim_ielen;
+ *dst_ie++ = tim_ielen;
- *dst_ie++ = 0;/* DTIM count */
- *dst_ie++ = 1;/* DTIM period */
+ *dst_ie++ = 0;/* DTIM count */
+ *dst_ie++ = 1;/* DTIM period */
- if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */
- *dst_ie++ = BIT(0);/* bitmap ctrl */
- else
- *dst_ie++ = 0;
+ if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */
+ *dst_ie++ = BIT(0);/* bitmap ctrl */
+ else
+ *dst_ie++ = 0;
- if (tim_ielen == 4) {
- *dst_ie++ = pstapriv->tim_bitmap & 0xff;
- } else if (tim_ielen == 5) {
- put_unaligned_le16(pstapriv->tim_bitmap, dst_ie);
- dst_ie += 2;
- }
+ if (tim_ielen == 4) {
+ *dst_ie++ = *(u8 *)&tim_bitmap_le;
+ } else if (tim_ielen == 5) {
+ memcpy(dst_ie, &tim_bitmap_le, 2);
+ dst_ie += 2;
+ }
- /* copy remainder IE */
- if (pbackup_remainder_ie) {
- memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+ /* copy remainder IE */
+ if (pbackup_remainder_ie) {
+ memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
- kfree(pbackup_remainder_ie);
+ kfree(pbackup_remainder_ie);
+ }
+ offset = (uint)(dst_ie - pie);
+ pnetwork_mlmeext->IELength = offset + remainder_ielen;
}
- offset = (uint)(dst_ie - pie);
- pnetwork_mlmeext->ie_length = offset + remainder_ielen;
set_tx_beacon_cmd(padapter);
}
@@ -149,10 +143,8 @@ static u8 chk_sta_is_alive(struct sta_info *psta)
{
u8 ret = false;
- if ((psta->sta_stats.last_rx_data_pkts +
- psta->sta_stats.last_rx_ctrl_pkts) ==
- (psta->sta_stats.rx_data_pkts +
- psta->sta_stats.rx_ctrl_pkts))
+ if ((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) ==
+ (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts))
;
else
ret = true;
@@ -162,11 +154,11 @@ static u8 chk_sta_is_alive(struct sta_info *psta)
return ret;
}
-void expire_timeout_chk(struct adapter *padapter)
+void expire_timeout_chk(struct adapter *padapter)
{
- struct list_head *phead;
+ struct list_head *phead, *plist;
u8 updated = 0;
- struct sta_info *psta, *temp;
+ struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
u8 chk_alive_num = 0;
char chk_alive_list[NUM_STA];
@@ -175,14 +167,22 @@ void expire_timeout_chk(struct adapter *padapter)
spin_lock_bh(&pstapriv->auth_list_lock);
phead = &pstapriv->auth_list;
+ plist = phead->next;
+
/* check auth_queue */
- list_for_each_entry_safe(psta, temp, phead, auth_list) {
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, auth_list);
+ plist = plist->next;
+
if (psta->expire_to > 0) {
psta->expire_to--;
if (psta->expire_to == 0) {
list_del_init(&psta->auth_list);
pstapriv->auth_list_cnt--;
+ DBG_88E("auth expire %6ph\n",
+ psta->hwaddr);
+
spin_unlock_bh(&pstapriv->auth_list_lock);
spin_lock_bh(&pstapriv->sta_hash_lock);
@@ -192,6 +192,7 @@ void expire_timeout_chk(struct adapter *padapter)
spin_lock_bh(&pstapriv->auth_list_lock);
}
}
+
}
spin_unlock_bh(&pstapriv->auth_list_lock);
@@ -200,8 +201,13 @@ void expire_timeout_chk(struct adapter *padapter)
spin_lock_bh(&pstapriv->asoc_list_lock);
phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
/* check asoc_queue */
- list_for_each_entry_safe(psta, temp, phead, asoc_list) {
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+ plist = plist->next;
+
if (chk_sta_is_alive(psta) || !psta->expire_to) {
psta->expire_to = pstapriv->expire_to;
psta->keep_alive_trycnt = 0;
@@ -220,18 +226,13 @@ void expire_timeout_chk(struct adapter *padapter)
if (psta->state & WIFI_SLEEP_STATE) {
if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
- /* to check if alive by another methods
- * if station is at ps mode.
- */
+ /* to check if alive by another methods if station is at ps mode. */
psta->expire_to = pstapriv->expire_to;
psta->state |= WIFI_STA_ALIVE_CHK_STATE;
- /* to update bcn with tim_bitmap
- * for this station
- */
+ /* to update bcn with tim_bitmap for this station */
pstapriv->tim_bitmap |= BIT(psta->aid);
- update_beacon(padapter, WLAN_EID_TIM, NULL,
- false);
+ update_beacon(padapter, _TIM_IE_, NULL, false);
if (!pmlmeext->active_keep_alive_check)
continue;
@@ -240,24 +241,27 @@ void expire_timeout_chk(struct adapter *padapter)
if (pmlmeext->active_keep_alive_check) {
int stainfo_offset;
- stainfo_offset =
- rtw_stainfo_offset(pstapriv, psta);
+ stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
if (stainfo_offset_valid(stainfo_offset))
- chk_alive_list[chk_alive_num++] =
- stainfo_offset;
+ chk_alive_list[chk_alive_num++] = stainfo_offset;
continue;
}
list_del_init(&psta->asoc_list);
pstapriv->asoc_list_cnt--;
- updated = ap_free_sta(padapter, psta, true,
- WLAN_REASON_DEAUTH_LEAVING);
+ DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
+ updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
} else {
/* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) &&
- padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2))
+ padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2)) {
+ DBG_88E("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__,
+ (psta->hwaddr), psta->sleepq_len,
+ padapter->xmitpriv.free_xmitframe_cnt,
+ pstapriv->asoc_list_cnt);
wakeup_sta_to_xmit(padapter, psta);
+ }
}
}
@@ -276,34 +280,32 @@ void expire_timeout_chk(struct adapter *padapter)
for (i = 0; i < chk_alive_num; i++) {
int ret = _FAIL;
- psta = rtw_get_stainfo_by_offset(pstapriv,
- chk_alive_list[i]);
+ psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
- if (psta->state & WIFI_SLEEP_STATE) {
- ret = issue_nulldata(padapter, psta->hwaddr,
- 0, 1, 50);
- } else {
- ret = issue_nulldata(padapter, psta->hwaddr,
- 0, 3, 50);
- }
+ if (psta->state & WIFI_SLEEP_STATE)
+ ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
+ else
+ ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);
psta->keep_alive_trycnt++;
if (ret == _SUCCESS) {
+ DBG_88E("asoc check, sta(%pM) is alive\n", (psta->hwaddr));
psta->expire_to = pstapriv->expire_to;
psta->keep_alive_trycnt = 0;
continue;
} else if (psta->keep_alive_trycnt <= 3) {
+ DBG_88E("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt);
psta->expire_to = 1;
continue;
}
psta->keep_alive_trycnt = 0;
+ DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
spin_lock_bh(&pstapriv->asoc_list_lock);
list_del_init(&psta->asoc_list);
pstapriv->asoc_list_cnt--;
- updated = ap_free_sta(padapter, psta, true,
- WLAN_REASON_DEAUTH_LEAVING);
+ updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
spin_unlock_bh(&pstapriv->asoc_list_lock);
}
@@ -317,10 +319,14 @@ void expire_timeout_chk(struct adapter *padapter)
void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
{
int i;
+ u8 rf_type;
u32 init_rate = 0;
unsigned char sta_band = 0, raid, shortGIrate = false;
+ unsigned char limit;
unsigned int tx_ra_bitmap = 0;
struct ht_priv *psta_ht = NULL;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
if (psta)
psta_ht = &psta->htpriv;
@@ -337,20 +343,31 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
}
/* n mode ra_bitmap */
if (psta_ht->ht_option) {
- for (i = 0; i < 8; i++)
- if (psta_ht->ht_cap.mcs.rx_mask[0] & BIT(i))
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ if (rf_type == RF_2T2R)
+ limit = 16;/* 2R */
+ else
+ limit = 8;/* 1R */
+
+ for (i = 0; i < limit; i++) {
+ if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8))
tx_ra_bitmap |= BIT(i + 12);
+ }
/* max short GI rate */
shortGIrate = psta_ht->sgi;
}
- if (tx_ra_bitmap & 0xffff000)
- sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
- else if (tx_ra_bitmap & 0xff0)
- sta_band |= WIRELESS_11G | WIRELESS_11B;
- else
- sta_band |= WIRELESS_11B;
+ if (pcur_network->Configuration.DSConfig > 14) {
+ sta_band |= WIRELESS_INVALID;
+ } else {
+ if (tx_ra_bitmap & 0xffff000)
+ sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
+ else if (tx_ra_bitmap & 0xff0)
+ sta_band |= WIRELESS_11G | WIRELESS_11B;
+ else
+ sta_band |= WIRELESS_11B;
+ }
psta->wireless_mode = sta_band;
@@ -369,6 +386,9 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
tx_ra_bitmap |= ((raid << 28) & 0xf0000000);
+ DBG_88E("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = 0x%x\n",
+ __func__, psta->mac_id, raid, tx_ra_bitmap, arg);
+
/* bitmap[0:27] = tx_rate_bitmap */
/* bitmap[28:31]= Rate Adaptive id */
/* arg[0:4] = macid */
@@ -382,17 +402,19 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
psta->raid = raid;
psta->init_rate = init_rate;
+ } else {
+ DBG_88E("station aid %d exceed the max number\n", psta->aid);
}
}
-static void update_bmc_sta(struct adapter *padapter)
+void update_bmc_sta(struct adapter *padapter)
{
u32 init_rate = 0;
unsigned char network_type, raid;
int i, supportRateNum = 0;
unsigned int tx_ra_bitmap = 0;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_network = &pmlmepriv->cur_network.network;
+ struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
if (psta) {
@@ -404,14 +426,13 @@ static void update_bmc_sta(struct adapter *padapter)
psta->ieee8021x_blocked = 0;
- memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+ memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
/* prepare for add_RATid */
supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
- network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates);
+ network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates, supportRateNum, 1);
- memcpy(psta->bssrateset, &pcur_network->SupportedRates,
- supportRateNum);
+ memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum);
psta->bssratelen = supportRateNum;
/* b/g mode ra_bitmap */
@@ -420,13 +441,16 @@ static void update_bmc_sta(struct adapter *padapter)
tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f);
}
- /* force to b mode */
- network_type = WIRELESS_11B;
- tx_ra_bitmap = 0xf;
+ if (pcur_network->Configuration.DSConfig > 14) {
+ network_type = WIRELESS_INVALID;
+ } else {
+ /* force to b mode */
+ network_type = WIRELESS_11B;
+ tx_ra_bitmap = 0xf;
+ }
raid = networktype_to_raid(network_type);
- init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) &
- 0x3f;
+ init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f;
/* ap mode */
rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
@@ -437,6 +461,7 @@ static void update_bmc_sta(struct adapter *padapter)
arg = psta->mac_id & 0x1f;
arg |= BIT(7);
tx_ra_bitmap |= ((raid << 28) & 0xf0000000);
+ DBG_88E("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg);
/* bitmap[0:27] = tx_rate_bitmap */
/* bitmap[28:31]= Rate Adaptive id */
@@ -448,12 +473,14 @@ static void update_bmc_sta(struct adapter *padapter)
psta->raid = raid;
psta->init_rate = init_rate;
- rtw_stassoc_hw_rpt(padapter, psta);
+ rtw_sta_media_status_rpt(padapter, psta, 1);
spin_lock_bh(&psta->lock);
psta->state = _FW_LINKED;
spin_unlock_bh(&psta->lock);
+ } else {
+ DBG_88E("add_RATid_bmc_sta error!\n");
}
}
@@ -471,8 +498,11 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
struct ht_priv *phtpriv_sta = &psta->htpriv;
+ u16 sta_cap_info;
+ u16 ap_cap_info;
psta->mac_id = psta->aid + 1;
+ DBG_88E("%s\n", __func__);
/* ap mode */
rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
@@ -490,17 +520,16 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
if (phtpriv_sta->ht_option) {
/* check if sta supports rx ampdu */
phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
+ sta_cap_info = le16_to_cpu(phtpriv_sta->ht_cap.cap_info);
+ ap_cap_info = le16_to_cpu(phtpriv_ap->ht_cap.cap_info);
/* check if sta support s Short GI */
- if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info &
- phtpriv_ap->ht_cap.cap_info) &
+ if ((sta_cap_info & ap_cap_info) &
(IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40))
phtpriv_sta->sgi = true;
/* bwmode */
- if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info &
- phtpriv_ap->ht_cap.cap_info) &
- IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+ if ((sta_cap_info & ap_cap_info) & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
}
@@ -522,7 +551,7 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
/* todo: init other variables */
- memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+ memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
spin_lock_bh(&psta->lock);
psta->state |= _FW_LINKED;
@@ -531,23 +560,32 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
static void update_hw_ht_param(struct adapter *padapter)
{
- u8 max_ampdu_len;
- u8 min_mpdu_spacing;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ unsigned char max_AMPDU_len;
+ unsigned char min_MPDU_spacing;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- /* handle A-MPDU parameter field
- * ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
- * ampdu_params_info [4:2]:Min MPDU Start Spacing
- */
- max_ampdu_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03;
- min_mpdu_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2;
+ DBG_88E("%s\n", __func__);
+
+ /* handle A-MPDU parameter field */
+ /*
+ AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+ AMPDU_para [4:2]:Min MPDU Start Spacing
+ */
+ max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
- rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, &min_mpdu_spacing);
- rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, &max_ampdu_len);
+ min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
- /* Config SM Power Save setting */
- pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2;
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+
+ /* */
+ /* Config SM Power Save setting */
+ /* */
+ pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2;
+ if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
+ DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
}
static void start_bss_network(struct adapter *padapter, u8 *pbuf)
@@ -556,27 +594,28 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
u16 bcn_interval;
u32 acparm;
- uint ie_len;
+ int ie_len;
struct registry_priv *pregpriv = &padapter->registrypriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct wlan_bssid_ex *pnetwork = &pmlmepriv->cur_network.network;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
struct HT_info_element *pht_info = NULL;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
cur_channel = pnetwork->Configuration.DSConfig;
cur_bwmode = HT_CHANNEL_WIDTH_20;
cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- /* check if there is wps ie,
- * if there is wpsie in beacon, the hostapd will update
- * beacon twice when stating hostapd, and at first time the
- * security ie (RSN/WPA IE) will not include in beacon.
- */
- if (!rtw_get_wps_ie(pnetwork->ies + _FIXED_IE_LENGTH_, pnetwork->ie_length - _FIXED_IE_LENGTH_, NULL, NULL))
+ /* check if there is wps ie, */
+ /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
+ /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
+ if (!rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL))
pmlmeext->bstart_bss = true;
/* todo: update wmm, ht cap */
@@ -589,11 +628,8 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
update_hw_ht_param(padapter);
}
- /* setting only at first time */
- if (!pmlmepriv->cur_network.join_res) {
- /* WEP Key will be set before this function, do not
- * clear CAM.
- */
+ if (pmlmepriv->cur_network.join_res != true) { /* setting only at first time */
+ /* WEP Key will be set before this function, do not clear CAM. */
if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) &&
(psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
flush_all_cam_entry(padapter); /* clear CAM */
@@ -620,8 +656,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
/* Beacon Control related register */
- rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL,
- (u8 *)(&bcn_interval));
+ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
UpdateBrateTbl(padapter, pnetwork->SupportedRates);
rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
@@ -631,10 +666,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
}
/* set channel, bwmode */
- p = rtw_get_ie(pnetwork->ies + sizeof(struct ndis_802_11_fixed_ie),
- WLAN_EID_HT_OPERATION, &ie_len,
- pnetwork->ie_length -
- sizeof(struct ndis_802_11_fixed_ie));
+ p = rtw_get_ie((pnetwork->IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(struct ndis_802_11_fixed_ie)));
if (p && ie_len) {
pht_info = (struct HT_info_element *)(p + 2);
@@ -654,11 +686,11 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
}
}
}
- /* TODO: need to judge the phy parameters on concurrent
- * mode for single phy
- */
+ /* TODO: need to judge the phy parameters on concurrent mode for single phy */
set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
+ DBG_88E("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, cur_ch_offset);
+
/* */
pmlmeext->cur_channel = cur_channel;
pmlmeext->cur_bwmode = cur_bwmode;
@@ -668,17 +700,23 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
/* update cur_wireless_mode */
update_wireless_mode(padapter);
- /* update capability after cur_wireless_mode updated */
- update_capinfo(padapter, rtw_get_capability(pnetwork));
+ /* udpate capability after cur_wireless_mode updated */
+ update_capinfo(padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork));
/* let pnetwork_mlmeext == pnetwork_mlme. */
memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
+#ifdef CONFIG_88EU_P2P
+ memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.Ssid, pnetwork->Ssid.SsidLength);
+ pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.SsidLength;
+#endif /* CONFIG_88EU_P2P */
+
if (pmlmeext->bstart_bss) {
- update_beacon(padapter, WLAN_EID_TIM, NULL, false);
+ update_beacon(padapter, _TIM_IE_, NULL, false);
/* issue beacon frame */
- send_beacon(padapter);
+ if (send_beacon(padapter) == _FAIL)
+ DBG_88E("issue_beacon, fail!\n");
}
/* update bc/mc sta_info */
@@ -702,8 +740,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
struct registry_priv *pregistrypriv = &padapter->registrypriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network;
- u8 *ie = pbss_network->ies;
+ struct wlan_bssid_ex *pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
+ u8 *ie = pbss_network->IEs;
/* SSID */
/* Supported rates */
@@ -716,24 +754,26 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
/* ht_capab, ht_oper */
/* WPS IE */
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ DBG_88E("%s, len =%d\n", __func__, len);
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
return _FAIL;
- if (len < 0 || len > MAX_IE_SZ)
+ if (len > MAX_IE_SZ)
return _FAIL;
- pbss_network->ie_length = len;
+ pbss_network->IELength = len;
memset(ie, 0, MAX_IE_SZ);
- memcpy(ie, pbuf, pbss_network->ie_length);
+ memcpy(ie, pbuf, pbss_network->IELength);
if (pbss_network->InfrastructureMode != Ndis802_11APMode)
return _FAIL;
pbss_network->Rssi = 0;
- ether_addr_copy(pbss_network->MacAddress, myid(&padapter->eeprompriv));
+ memcpy(pbss_network->MacAddress, myid(&padapter->eeprompriv), ETH_ALEN);
/* beacon interval */
p = rtw_get_beacon_interval_from_ie(ie);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
@@ -743,20 +783,17 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
cap = get_unaligned_le16(ie);
/* SSID */
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_SSID, &ie_len,
- pbss_network->ie_length - _BEACON_IE_OFFSET_);
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
if (p && ie_len > 0) {
- ie_len = min_t(int, ie_len, sizeof(pbss_network->ssid.ssid));
- memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid));
- memcpy(pbss_network->ssid.ssid, p + 2, ie_len);
- pbss_network->ssid.ssid_length = ie_len;
+ memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
+ memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
+ pbss_network->Ssid.SsidLength = ie_len;
}
/* channel */
channel = 0;
pbss_network->Configuration.Length = 0;
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_DS_PARAMS, &ie_len,
- (pbss_network->ie_length - _BEACON_IE_OFFSET_));
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
if (p && ie_len > 0)
channel = *(p + 2);
@@ -764,31 +801,25 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
/* get supported rates */
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES, &ie_len,
- pbss_network->ie_length - _BEACON_IE_OFFSET_);
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
if (p) {
- ie_len = min_t(int, ie_len, NDIS_802_11_LENGTH_RATES_EX);
memcpy(supportRate, p + 2, ie_len);
supportRateNum = ie_len;
}
/* get ext_supported rates */
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES,
- &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_);
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
if (p) {
- ie_len = min_t(int, ie_len,
- NDIS_802_11_LENGTH_RATES_EX - supportRateNum);
memcpy(supportRate + supportRateNum, p + 2, ie_len);
supportRateNum += ie_len;
}
- network_type = rtw_check_network_type(supportRate);
+ network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
/* parsing ERP_IE */
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_ERP_INFO, &ie_len,
- pbss_network->ie_length - _BEACON_IE_OFFSET_);
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
if (p && ie_len > 0)
ERP_IE_handler(padapter, (struct ndis_802_11_var_ie *)p);
@@ -805,8 +836,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
pairwise_cipher = 0;
psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len,
- pbss_network->ie_length - _BEACON_IE_OFFSET_);
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
if (p && ie_len > 0) {
if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
@@ -825,8 +855,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
- p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len,
- pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2));
+ p = rtw_get_ie(p, _SSN_IE_1_, &ie_len,
+ (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
if ((p) && (!memcmp(p + 2, OUI1, 4))) {
if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher,
&pairwise_cipher, NULL) == _SUCCESS) {
@@ -841,7 +871,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
}
break;
}
- if ((!p) || (ie_len == 0))
+ if (!p || ie_len == 0)
break;
}
@@ -850,17 +880,14 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
pmlmepriv->qospriv.qos_option = 0;
if (pregistrypriv->wmm_enable) {
for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
- p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len,
- pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2));
+ p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len,
+ (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) {
pmlmepriv->qospriv.qos_option = 1;
- /* QoS Info, support U-APSD */
- *(p + 8) |= BIT(7);
+ *(p + 8) |= BIT(7);/* QoS Info, support U-APSD */
- /* disable all ACM bits since the WMM
- * admission control is not supported
- */
+ /* disable all ACM bits since the WMM admission control is not supported */
*(p + 10) &= ~BIT(4); /* BE */
*(p + 14) &= ~BIT(4); /* BK */
*(p + 18) &= ~BIT(4); /* VI */
@@ -868,20 +895,23 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
break;
}
- if ((!p) || (ie_len == 0))
+ if (!p || ie_len == 0)
break;
}
}
/* parsing HT_CAP_IE */
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len,
- pbss_network->ie_length - _BEACON_IE_OFFSET_);
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len,
+ (pbss_network->IELength - _BEACON_IE_OFFSET_));
if (p && ie_len > 0) {
+ u8 rf_type;
struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2);
pHT_caps_ie = p;
ht_cap = true;
network_type |= WIRELESS_11_24N;
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
(psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07 << 2));
@@ -891,15 +921,16 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
/* set Max Rx AMPDU size to 64K */
pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_FACTOR & 0x03);
- pht_cap->mcs.rx_mask[0] = 0xff;
- pht_cap->mcs.rx_mask[1] = 0x0;
- ie_len = min_t(int, ie_len, sizeof(pmlmepriv->htpriv.ht_cap));
+ if (rf_type == RF_1T1R) {
+ pht_cap->mcs.rx_mask[0] = 0xff;
+ pht_cap->mcs.rx_mask[1] = 0x0;
+ }
memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len);
}
/* parsing HT_INFO_IE */
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len,
- pbss_network->ie_length - _BEACON_IE_OFFSET_);
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len,
+ (pbss_network->IELength - _BEACON_IE_OFFSET_));
if (p && ie_len > 0)
pHT_info_ie = p;
switch (network_type) {
@@ -912,9 +943,6 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
case WIRELESS_11BG_24N:
pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
break;
- case WIRELESS_11A:
- pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
- break;
default:
pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
break;
@@ -942,7 +970,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
HT_info_handler(padapter, (struct ndis_802_11_var_ie *)pHT_info_ie);
}
- pbss_network->Length = get_wlan_bssid_ex_sz(pbss_network);
+ pbss_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pbss_network);
/* issue beacon to start bss network */
start_bss_network(padapter, (u8 *)pbss_network);
@@ -967,6 +995,8 @@ void rtw_set_macaddr_acl(struct adapter *padapter, int mode)
struct sta_priv *pstapriv = &padapter->stapriv;
struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ DBG_88E("%s, mode =%d\n", __func__, mode);
+
pacl_list->mode = mode;
}
@@ -980,18 +1010,24 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
struct __queue *pacl_node_q = &pacl_list->acl_node_q;
+ DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr));
+
if ((NUM_ACL - 1) < pacl_list->num)
return -1;
spin_lock_bh(&pacl_node_q->lock);
phead = get_list_head(pacl_node_q);
- list_for_each(plist, phead) {
- paclnode = list_entry(plist, struct rtw_wlan_acl_node, list);
+ plist = phead->next;
+
+ while (phead != plist) {
+ paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+ plist = plist->next;
if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
if (paclnode->valid) {
added = true;
+ DBG_88E("%s, sta has been added\n", __func__);
break;
}
}
@@ -1010,7 +1046,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
if (!paclnode->valid) {
INIT_LIST_HEAD(&paclnode->list);
- ether_addr_copy(paclnode->addr, addr);
+ memcpy(paclnode->addr, addr, ETH_ALEN);
paclnode->valid = true;
@@ -1022,6 +1058,8 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
}
}
+ DBG_88E("%s, acl_num =%d\n", __func__, pacl_list->num);
+
spin_unlock_bh(&pacl_node_q->lock);
return ret;
@@ -1029,16 +1067,24 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr)
{
- struct list_head *phead;
- struct rtw_wlan_acl_node *paclnode, *temp;
+ struct list_head *plist, *phead;
+ int ret = 0;
+ struct rtw_wlan_acl_node *paclnode;
struct sta_priv *pstapriv = &padapter->stapriv;
struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
struct __queue *pacl_node_q = &pacl_list->acl_node_q;
+ DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr));
+
spin_lock_bh(&pacl_node_q->lock);
phead = get_list_head(pacl_node_q);
- list_for_each_entry_safe(paclnode, temp, phead, list) {
+ plist = phead->next;
+
+ while (phead != plist) {
+ paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+ plist = plist->next;
+
if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
if (paclnode->valid) {
paclnode->valid = false;
@@ -1052,7 +1098,13 @@ int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr)
spin_unlock_bh(&pacl_node_q->lock);
- return 0;
+ DBG_88E("%s, acl_num =%d\n", __func__, pacl_list->num);
+ return ret;
+}
+
+static void update_bcn_fixed_ie(struct adapter *padapter)
+{
+ DBG_88E("%s\n", __func__);
}
static void update_bcn_erpinfo_ie(struct adapter *padapter)
@@ -1061,24 +1113,24 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter)
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- unsigned char *p, *ie = pnetwork->ies;
+ unsigned char *p, *ie = pnetwork->IEs;
u32 len = 0;
+ DBG_88E("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable);
+
if (!pmlmeinfo->ERP_enable)
return;
/* parsing ERP_IE */
- p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_ERP_INFO, &len,
- (pnetwork->ie_length - _BEACON_IE_OFFSET_));
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len,
+ (pnetwork->IELength - _BEACON_IE_OFFSET_));
if (p && len > 0) {
struct ndis_802_11_var_ie *pIE = (struct ndis_802_11_var_ie *)p;
if (pmlmepriv->num_sta_non_erp == 1)
- pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT |
- RTW_ERP_INFO_USE_PROTECTION;
+ pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION;
else
- pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT |
- RTW_ERP_INFO_USE_PROTECTION);
+ pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION);
if (pmlmepriv->num_sta_no_short_preamble > 0)
pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
@@ -1089,6 +1141,31 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter)
}
}
+static void update_bcn_htcap_ie(struct adapter *padapter)
+{
+ DBG_88E("%s\n", __func__);
+}
+
+static void update_bcn_htinfo_ie(struct adapter *padapter)
+{
+ DBG_88E("%s\n", __func__);
+}
+
+static void update_bcn_rsn_ie(struct adapter *padapter)
+{
+ DBG_88E("%s\n", __func__);
+}
+
+static void update_bcn_wpa_ie(struct adapter *padapter)
+{
+ DBG_88E("%s\n", __func__);
+}
+
+static void update_bcn_wmm_ie(struct adapter *padapter)
+{
+ DBG_88E("%s\n", __func__);
+}
+
static void update_bcn_wps_ie(struct adapter *padapter)
{
u8 *pwps_ie = NULL, *pwps_ie_src;
@@ -1098,15 +1175,12 @@ static void update_bcn_wps_ie(struct adapter *padapter)
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- unsigned char *ie = pnetwork->ies;
- u32 ielen = pnetwork->ie_length;
+ unsigned char *ie = pnetwork->IEs;
+ u32 ielen = pnetwork->IELength;
- pwps_ie_src = pmlmepriv->wps_beacon_ie;
- if (!pwps_ie_src)
- return;
+ DBG_88E("%s\n", __func__);
- pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_,
- ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
+ pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_, ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
if (!pwps_ie || wps_ielen == 0)
return;
@@ -1118,31 +1192,49 @@ static void update_bcn_wps_ie(struct adapter *padapter)
remainder_ielen = ielen - wps_offset - wps_ielen;
if (remainder_ielen > 0) {
- pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+ pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC);
if (pbackup_remainder_ie)
memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
}
+ pwps_ie_src = pmlmepriv->wps_beacon_ie;
+ if (!pwps_ie_src)
+ goto exit;
+
wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
- if (wps_offset + wps_ielen + 2 + remainder_ielen <= MAX_IE_SZ) {
+ if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2);
- pwps_ie += wps_ielen + 2;
+ pwps_ie += (wps_ielen + 2);
if (pbackup_remainder_ie)
memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
- /* update ie_length */
- pnetwork->ie_length = wps_offset + wps_ielen + 2 + remainder_ielen;
+ /* update IELength */
+ pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen;
}
+exit:
kfree(pbackup_remainder_ie);
}
+static void update_bcn_p2p_ie(struct adapter *padapter)
+{
+}
+
static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui)
{
+ DBG_88E("%s\n", __func__);
- if (!memcmp(WPS_OUI, oui, 4))
+ if (!memcmp(RTW_WPA_OUI, oui, 4))
+ update_bcn_wpa_ie(padapter);
+ else if (!memcmp(WMM_OUI, oui, 4))
+ update_bcn_wmm_ie(padapter);
+ else if (!memcmp(WPS_OUI, oui, 4))
update_bcn_wps_ie(padapter);
+ else if (!memcmp(P2P_OUI, oui, 4))
+ update_bcn_p2p_ie(padapter);
+ else
+ DBG_88E("unknown OUI type!\n");
}
void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
@@ -1162,13 +1254,25 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
spin_lock_bh(&pmlmepriv->bcn_update_lock);
switch (ie_id) {
- case WLAN_EID_TIM:
+ case 0xFF:
+ update_bcn_fixed_ie(padapter);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
+ break;
+ case _TIM_IE_:
update_BCNTIM(padapter);
break;
- case WLAN_EID_ERP_INFO:
+ case _ERPINFO_IE_:
update_bcn_erpinfo_ie(padapter);
break;
- case WLAN_EID_VENDOR_SPECIFIC:
+ case _HT_CAPABILITY_IE_:
+ update_bcn_htcap_ie(padapter);
+ break;
+ case _RSN_IE_2_:
+ update_bcn_rsn_ie(padapter);
+ break;
+ case _HT_ADD_INFO_IE_:
+ update_bcn_htinfo_ie(padapter);
+ break;
+ case _VENDOR_SPECIFIC_IE_:
update_bcn_vendor_spec_ie(padapter, oui);
break;
default:
@@ -1184,17 +1288,17 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
}
/*
- * op_mode
- * Set to 0 (HT pure) under the following conditions
- * - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
- * - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
- * Set to 1 (HT non-member protection) if there may be non-HT STAs
- * in both the primary and the secondary channel
- * Set to 2 if only HT STAs are associated in BSS,
- * however and at least one 20 MHz HT STA is associated
- * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
- * (currently non-GF HT station is considered as non-HT STA also)
- */
+op_mode
+Set to 0 (HT pure) under the followign conditions
+ - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
+ - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
+Set to 1 (HT non-member protection) if there may be non-HT STAs
+ in both the primary and the secondary channel
+Set to 2 if only HT STAs are associated in BSS,
+ however and at least one 20 MHz HT STA is associated
+Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
+ (currently non-GF HT station is considered as non-HT STA also)
+*/
static int rtw_ht_operation_update(struct adapter *padapter)
{
u16 cur_op_mode, new_op_mode;
@@ -1205,6 +1309,9 @@ static int rtw_ht_operation_update(struct adapter *padapter)
if (pmlmepriv->htpriv.ht_option)
return 0;
+ DBG_88E("%s current operation mode = 0x%X\n",
+ __func__, pmlmepriv->ht_op_mode);
+
if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
pmlmepriv->num_sta_ht_no_gf) {
pmlmepriv->ht_op_mode |=
@@ -1254,12 +1361,15 @@ static int rtw_ht_operation_update(struct adapter *padapter)
op_mode_changes++;
}
+ DBG_88E("%s new operation mode = 0x%X changes =%d\n",
+ __func__, pmlmepriv->ht_op_mode, op_mode_changes);
+
return op_mode_changes;
}
void associated_clients_update(struct adapter *padapter, u8 updated)
{
- /* update associated stations cap. */
+ /* update associcated stations cap. */
if (updated) {
struct list_head *phead, *plist;
struct sta_info *psta = NULL;
@@ -1268,9 +1378,13 @@ void associated_clients_update(struct adapter *padapter, u8 updated)
spin_lock_bh(&pstapriv->asoc_list_lock);
phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
/* check asoc_queue */
- list_for_each(plist, phead) {
- psta = list_entry(plist, struct sta_info, asoc_list);
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+
+ plist = plist->next;
VCS_update(padapter, psta);
}
@@ -1319,7 +1433,7 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
if (pmlmepriv->num_sta_non_erp == 1) {
beacon_updated = true;
- update_beacon(padapter, WLAN_EID_ERP_INFO, NULL, true);
+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
}
}
} else {
@@ -1330,12 +1444,12 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
if (pmlmepriv->num_sta_non_erp == 0) {
beacon_updated = true;
- update_beacon(padapter, WLAN_EID_ERP_INFO, NULL, true);
+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
}
}
}
- if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) {
+ if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) {
if (!psta->no_short_slot_time_set) {
psta->no_short_slot_time_set = 1;
@@ -1364,6 +1478,9 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
if (psta->flags & WLAN_STA_HT) {
u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
+ DBG_88E("HT: STA %pM HT Capabilities Info: 0x%04x\n",
+ (psta->hwaddr), ht_capab);
+
if (psta->no_ht_set) {
psta->no_ht_set = 0;
pmlmepriv->num_sta_no_ht--;
@@ -1374,6 +1491,9 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
psta->no_ht_gf_set = 1;
pmlmepriv->num_sta_ht_no_gf++;
}
+ DBG_88E("%s STA %pM - no greenfield, num of non-gf stations %d\n",
+ __func__, (psta->hwaddr),
+ pmlmepriv->num_sta_ht_no_gf);
}
if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) {
@@ -1381,21 +1501,31 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
psta->ht_20mhz_set = 1;
pmlmepriv->num_sta_ht_20mhz++;
}
+ DBG_88E("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n",
+ __func__, (psta->hwaddr),
+ pmlmepriv->num_sta_ht_20mhz);
}
} else {
if (!psta->no_ht_set) {
psta->no_ht_set = 1;
pmlmepriv->num_sta_no_ht++;
}
+ if (pmlmepriv->htpriv.ht_option) {
+ DBG_88E("%s STA %pM - no HT, num of non-HT stations %d\n",
+ __func__, (psta->hwaddr),
+ pmlmepriv->num_sta_no_ht);
+ }
}
if (rtw_ht_operation_update(padapter) > 0) {
- update_beacon(padapter, WLAN_EID_HT_CAPABILITY, NULL, false);
- update_beacon(padapter, WLAN_EID_HT_OPERATION, NULL, true);
+ update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false);
+ update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
}
- /* update associated stations cap. */
+ /* update associcated stations cap. */
associated_clients_update(padapter, beacon_updated);
+
+ DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
}
u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
@@ -1422,7 +1552,7 @@ u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
pmlmepriv->num_sta_non_erp--;
if (pmlmepriv->num_sta_non_erp == 0) {
beacon_updated = true;
- update_beacon(padapter, WLAN_EID_ERP_INFO, NULL, true);
+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
}
}
@@ -1452,11 +1582,13 @@ u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
}
if (rtw_ht_operation_update(padapter) > 0) {
- update_beacon(padapter, WLAN_EID_HT_CAPABILITY, NULL, false);
- update_beacon(padapter, WLAN_EID_HT_OPERATION, NULL, true);
+ update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false);
+ update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
}
- /* update associated stations cap. */
+ /* update associcated stations cap. */
+
+ DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
return beacon_updated;
}
@@ -1501,22 +1633,66 @@ u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta,
return beacon_updated;
}
+int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset)
+{
+ struct list_head *phead, *plist;
+ int ret = 0;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ return ret;
+
+ DBG_88E(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
+ FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
+ /* for each sta in asoc_queue */
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+ plist = plist->next;
+
+ issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
+ psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
+
+ return ret;
+}
+
int rtw_sta_flush(struct adapter *padapter)
{
- struct list_head *phead;
- struct sta_info *psta, *temp;
+ struct list_head *phead, *plist;
+ int ret = 0;
+ struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
+
if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- return 0;
+ return ret;
spin_lock_bh(&pstapriv->asoc_list_lock);
phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
/* free sta asoc_queue */
- list_for_each_entry_safe(psta, temp, phead, asoc_list) {
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+
+ plist = plist->next;
+
list_del_init(&psta->asoc_list);
pstapriv->asoc_list_cnt--;
@@ -1528,7 +1704,7 @@ int rtw_sta_flush(struct adapter *padapter)
associated_clients_update(padapter, true);
- return 0;
+ return ret;
}
/* called > TSR LEVEL for USB or SDIO Interface*/
@@ -1604,6 +1780,9 @@ void start_ap_mode(struct adapter *padapter)
pmlmepriv->wps_probe_resp_ie = NULL;
pmlmepriv->wps_assoc_resp_ie = NULL;
+ pmlmepriv->p2p_beacon_ie = NULL;
+ pmlmepriv->p2p_probe_resp_ie = NULL;
+
/* for ACL */
INIT_LIST_HEAD(&pacl_list->acl_node_q.queue);
pacl_list->num = 0;
@@ -1616,7 +1795,8 @@ void start_ap_mode(struct adapter *padapter)
void stop_ap_mode(struct adapter *padapter)
{
- struct rtw_wlan_acl_node *paclnode, *n;
+ struct list_head *phead, *plist;
+ struct rtw_wlan_acl_node *paclnode;
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -1627,16 +1807,19 @@ void stop_ap_mode(struct adapter *padapter)
pmlmepriv->update_bcn = false;
pmlmeext->bstart_bss = false;
- /* reset and init security priv , this can refine with
- * rtw_reset_securitypriv
- */
+ /* reset and init security priv , this can refine with rtw_reset_securitypriv */
memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
/* for ACL */
spin_lock_bh(&pacl_node_q->lock);
- list_for_each_entry_safe(paclnode, n, &pacl_node_q->queue, list) {
+ phead = get_list_head(pacl_node_q);
+ plist = phead->next;
+ while (phead != plist) {
+ paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+ plist = plist->next;
+
if (paclnode->valid) {
paclnode->valid = false;
@@ -1647,6 +1830,8 @@ void stop_ap_mode(struct adapter *padapter)
}
spin_unlock_bh(&pacl_node_q->lock);
+ DBG_88E("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num);
+
rtw_sta_flush(padapter);
/* free_assoc_sta_resources */
diff --git a/drivers/staging/r8188eu/core/rtw_br_ext.c b/drivers/staging/r8188eu/core/rtw_br_ext.c
new file mode 100644
index 000000000000..62a672243696
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_br_ext.c
@@ -0,0 +1,717 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. i*/
+
+#define _RTW_BR_EXT_C_
+
+#include "../include/linux/if_arp.h"
+#include "../include/net/ip.h"
+#include "../include/linux/atalk.h"
+#include "../include/linux/udp.h"
+#include "../include/linux/if_pppox.h"
+
+#include "../include/drv_types.h"
+#include "../include/rtw_br_ext.h"
+#include "../include/usb_osintf.h"
+#include "../include/recv_osdep.h"
+
+#ifndef csum_ipv6_magic
+#include "../include/net/ip6_checksum.h"
+#endif
+
+#include "../include/linux/ipv6.h"
+#include "../include/linux/icmpv6.h"
+#include "../include/net/ndisc.h"
+#include "../include/net/checksum.h"
+
+#define NAT25_IPV4 01
+#define NAT25_IPV6 02
+#define NAT25_IPX 03
+#define NAT25_APPLE 04
+#define NAT25_PPPOE 05
+
+#define RTL_RELAY_TAG_LEN (ETH_ALEN)
+#define TAG_HDR_LEN 4
+
+#define MAGIC_CODE 0x8186
+#define MAGIC_CODE_LEN 2
+#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */
+
+/*-----------------------------------------------------------------
+ How database records network address:
+ 0 1 2 3 4 5 6 7 8 9 10
+ |----|----|----|----|----|----|----|----|----|----|----|
+ IPv4 |type| | IP addr |
+ IPX |type| Net addr | Node addr |
+ IPX |type| Net addr |Sckt addr|
+ Apple |type| Network |node|
+ PPPoE |type| SID | AC MAC |
+-----------------------------------------------------------------*/
+
+/* Find a tag in pppoe frame and return the pointer */
+static unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type)
+{
+ unsigned char *cur_ptr, *start_ptr;
+ unsigned short tagLen, tagType;
+
+ start_ptr = cur_ptr = (unsigned char *)ph->tag;
+ while ((cur_ptr - start_ptr) < ntohs(ph->length)) {
+ /* prevent un-alignment access */
+ tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]);
+ tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]);
+ if (tagType == type)
+ return cur_ptr;
+ cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen;
+ }
+ return NULL;
+}
+
+static int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag)
+{
+ struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
+ int data_len;
+
+ data_len = tag->tag_len + TAG_HDR_LEN;
+ if (skb_tailroom(skb) < data_len) {
+ _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n");
+ return -1;
+ }
+
+ skb_put(skb, data_len);
+ /* have a room for new tag */
+ memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length));
+ ph->length = htons(ntohs(ph->length) + data_len);
+ memcpy((unsigned char *)ph->tag, tag, data_len);
+ return data_len;
+}
+
+static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len)
+{
+ int tail_len;
+ unsigned long end, tail;
+
+ if ((src+len) > skb_tail_pointer(skb) || skb->len < len)
+ return -1;
+
+ tail = (unsigned long)skb_tail_pointer(skb);
+ end = (unsigned long)src+len;
+ if (tail < end)
+ return -1;
+
+ tail_len = (int)(tail-end);
+ if (tail_len > 0)
+ memmove(src, src+len, tail_len);
+
+ skb_trim(skb, skb->len-len);
+ return 0;
+}
+
+static unsigned long __nat25_timeout(struct adapter *priv)
+{
+ unsigned long timeout;
+
+ timeout = jiffies - NAT25_AGEING_TIME*HZ;
+
+ return timeout;
+}
+
+static int __nat25_has_expired(struct adapter *priv,
+ struct nat25_network_db_entry *fdb)
+{
+ if (time_before_eq(fdb->ageing_timer, __nat25_timeout(priv)))
+ return 1;
+
+ return 0;
+}
+
+static void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr,
+ unsigned int *ipAddr)
+{
+ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+ networkAddr[0] = NAT25_IPV4;
+ memcpy(networkAddr+7, (unsigned char *)ipAddr, 4);
+}
+
+static void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr,
+ unsigned char *ac_mac, __be16 *sid)
+{
+ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+ networkAddr[0] = NAT25_PPPOE;
+ memcpy(networkAddr+1, (unsigned char *)sid, 2);
+ memcpy(networkAddr+3, (unsigned char *)ac_mac, 6);
+}
+
+static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr,
+ unsigned int *ipAddr)
+{
+ memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+ networkAddr[0] = NAT25_IPV6;
+ memcpy(networkAddr+1, (unsigned char *)ipAddr, 16);
+}
+
+static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b)
+{
+ while (len > 0) {
+ if (*data == tag && *(data+1) == len8b && len >= len8b*8)
+ return data+2;
+
+ len -= (*(data+1))*8;
+ data += (*(data+1))*8;
+ }
+ return NULL;
+}
+
+static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac)
+{
+ struct icmp6hdr *icmphdr = (struct icmp6hdr *)data;
+ unsigned char *mac;
+
+ if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) {
+ if (len >= 8) {
+ mac = scan_tlv(&data[8], len-8, 1, 1);
+ if (mac) {
+ _DEBUG_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
+ memcpy(mac, replace_mac, 6);
+ return 1;
+ }
+ }
+ } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) {
+ if (len >= 16) {
+ mac = scan_tlv(&data[16], len-16, 1, 1);
+ if (mac) {
+ _DEBUG_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
+ memcpy(mac, replace_mac, 6);
+ return 1;
+ }
+ }
+ } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
+ if (len >= 24) {
+ mac = scan_tlv(&data[24], len-24, 1, 1);
+ if (mac) {
+ _DEBUG_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
+ memcpy(mac, replace_mac, 6);
+ return 1;
+ }
+ }
+ } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
+ if (len >= 24) {
+ mac = scan_tlv(&data[24], len-24, 2, 1);
+ if (mac) {
+ _DEBUG_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
+ memcpy(mac, replace_mac, 6);
+ return 1;
+ }
+ }
+ } else if (icmphdr->icmp6_type == NDISC_REDIRECT) {
+ if (len >= 40) {
+ mac = scan_tlv(&data[40], len-40, 2, 1);
+ if (mac) {
+ _DEBUG_INFO("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
+ memcpy(mac, replace_mac, 6);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int __nat25_network_hash(unsigned char *networkAddr)
+{
+ if (networkAddr[0] == NAT25_IPV4) {
+ unsigned long x;
+
+ x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
+
+ return x & (NAT25_HASH_SIZE - 1);
+ } else if (networkAddr[0] == NAT25_IPX) {
+ unsigned long x;
+
+ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
+ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
+
+ return x & (NAT25_HASH_SIZE - 1);
+ } else if (networkAddr[0] == NAT25_APPLE) {
+ unsigned long x;
+
+ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3];
+
+ return x & (NAT25_HASH_SIZE - 1);
+ } else if (networkAddr[0] == NAT25_PPPOE) {
+ unsigned long x;
+
+ x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8];
+
+ return x & (NAT25_HASH_SIZE - 1);
+ } else if (networkAddr[0] == NAT25_IPV6) {
+ unsigned long x;
+
+ x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
+ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^
+ networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^
+ networkAddr[16];
+
+ return x & (NAT25_HASH_SIZE - 1);
+ } else {
+ unsigned long x = 0;
+ int i;
+
+ for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++)
+ x ^= networkAddr[i];
+
+ return x & (NAT25_HASH_SIZE - 1);
+ }
+}
+
+static void __network_hash_link(struct adapter *priv,
+ struct nat25_network_db_entry *ent, int hash)
+{
+ /* Caller must spin_lock already! */
+ ent->next_hash = priv->nethash[hash];
+ if (ent->next_hash)
+ ent->next_hash->pprev_hash = &ent->next_hash;
+ priv->nethash[hash] = ent;
+ ent->pprev_hash = &priv->nethash[hash];
+}
+
+static void __network_hash_unlink(struct nat25_network_db_entry *ent)
+{
+ /* Caller must spin_lock already! */
+ *ent->pprev_hash = ent->next_hash;
+ if (ent->next_hash)
+ ent->next_hash->pprev_hash = ent->pprev_hash;
+ ent->next_hash = NULL;
+ ent->pprev_hash = NULL;
+}
+
+static void __nat25_db_network_insert(struct adapter *priv,
+ unsigned char *macAddr, unsigned char *networkAddr)
+{
+ struct nat25_network_db_entry *db;
+ int hash;
+
+ spin_lock_bh(&priv->br_ext_lock);
+ hash = __nat25_network_hash(networkAddr);
+ db = priv->nethash[hash];
+ while (db) {
+ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
+ memcpy(db->macAddr, macAddr, ETH_ALEN);
+ db->ageing_timer = jiffies;
+ spin_unlock_bh(&priv->br_ext_lock);
+ return;
+ }
+ db = db->next_hash;
+ }
+ db = kmalloc(sizeof(*db), GFP_ATOMIC);
+ if (!db) {
+ spin_unlock_bh(&priv->br_ext_lock);
+ return;
+ }
+ memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN);
+ memcpy(db->macAddr, macAddr, ETH_ALEN);
+ atomic_set(&db->use_count, 1);
+ db->ageing_timer = jiffies;
+
+ __network_hash_link(priv, db, hash);
+
+ spin_unlock_bh(&priv->br_ext_lock);
+}
+
+static void __nat25_db_print(struct adapter *priv)
+{
+}
+
+/*
+ * NAT2.5 interface
+ */
+
+void nat25_db_cleanup(struct adapter *priv)
+{
+ int i;
+
+ spin_lock_bh(&priv->br_ext_lock);
+
+ for (i = 0; i < NAT25_HASH_SIZE; i++) {
+ struct nat25_network_db_entry *f;
+ f = priv->nethash[i];
+ while (f) {
+ struct nat25_network_db_entry *g;
+
+ g = f->next_hash;
+ if (priv->scdb_entry == f) {
+ memset(priv->scdb_mac, 0, ETH_ALEN);
+ memset(priv->scdb_ip, 0, 4);
+ priv->scdb_entry = NULL;
+ }
+ __network_hash_unlink(f);
+ kfree(f);
+ f = g;
+ }
+ }
+ spin_unlock_bh(&priv->br_ext_lock);
+}
+
+void nat25_db_expire(struct adapter *priv)
+{
+ int i;
+
+ spin_lock_bh(&priv->br_ext_lock);
+
+ for (i = 0; i < NAT25_HASH_SIZE; i++) {
+ struct nat25_network_db_entry *f;
+ f = priv->nethash[i];
+
+ while (f) {
+ struct nat25_network_db_entry *g;
+ g = f->next_hash;
+
+ if (__nat25_has_expired(priv, f)) {
+ if (atomic_dec_and_test(&f->use_count)) {
+ if (priv->scdb_entry == f) {
+ memset(priv->scdb_mac, 0, ETH_ALEN);
+ memset(priv->scdb_ip, 0, 4);
+ priv->scdb_entry = NULL;
+ }
+ __network_hash_unlink(f);
+ kfree(f);
+ }
+ }
+ f = g;
+ }
+ }
+ spin_unlock_bh(&priv->br_ext_lock);
+}
+
+int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
+{
+ unsigned short protocol;
+ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
+ unsigned int tmp;
+
+ if (!skb)
+ return -1;
+
+ if ((method <= NAT25_MIN) || (method >= NAT25_MAX))
+ return -1;
+
+ protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));
+
+ /*---------------------------------------------------*/
+ /* Handle IP frame */
+ /*---------------------------------------------------*/
+ if (protocol == ETH_P_IP) {
+ struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
+
+ if (((unsigned char *)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len)) {
+ DEBUG_WARN("NAT25: malformed IP packet !\n");
+ return -1;
+ }
+
+ switch (method) {
+ case NAT25_CHECK:
+ return -1;
+ case NAT25_INSERT:
+ /* some multicast with source IP is all zero, maybe other case is illegal */
+ /* in class A, B, C, host address is all zero or all one is illegal */
+ if (iph->saddr == 0)
+ return 0;
+ tmp = be32_to_cpu(iph->saddr);
+ DEBUG_INFO("NAT25: Insert IP, SA =%08x, DA =%08x\n", tmp, iph->daddr);
+ __nat25_generate_ipv4_network_addr(networkAddr, &tmp);
+ /* record source IP address and , source mac address into db */
+ __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+
+ __nat25_db_print(priv);
+ return 0;
+ default:
+ return -1;
+ }
+ } else if (protocol == ETH_P_ARP) {
+ /*---------------------------------------------------*/
+ /* Handle ARP frame */
+ /*---------------------------------------------------*/
+ struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
+ unsigned char *arp_ptr = (unsigned char *)(arp + 1);
+ unsigned int *sender;
+
+ if (arp->ar_pro != __constant_htons(ETH_P_IP)) {
+ DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", be16_to_cpu(arp->ar_pro));
+ return -1;
+ }
+
+ switch (method) {
+ case NAT25_CHECK:
+ return 0; /* skb_copy for all ARP frame */
+ case NAT25_INSERT:
+ DEBUG_INFO("NAT25: Insert ARP, MAC =%02x%02x%02x%02x%02x%02x\n", arp_ptr[0],
+ arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]);
+
+ /* change to ARP sender mac address to wlan STA address */
+ memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN);
+ arp_ptr += arp->ar_hln;
+ sender = (unsigned int *)arp_ptr;
+ __nat25_generate_ipv4_network_addr(networkAddr, sender);
+ __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+ __nat25_db_print(priv);
+ return 0;
+ default:
+ return -1;
+ }
+ } else if ((protocol == ETH_P_PPP_DISC) ||
+ (protocol == ETH_P_PPP_SES)) {
+ /*---------------------------------------------------*/
+ /* Handle PPPoE frame */
+ /*---------------------------------------------------*/
+ struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
+ unsigned short *pMagic;
+
+ switch (method) {
+ case NAT25_CHECK:
+ if (ph->sid == 0)
+ return 0;
+ return 1;
+ case NAT25_INSERT:
+ if (ph->sid == 0) { /* Discovery phase according to tag */
+ if (ph->code == PADI_CODE || ph->code == PADR_CODE) {
+ if (priv->ethBrExtInfo.addPPPoETag) {
+ struct pppoe_tag *tag, *pOldTag;
+ unsigned char tag_buf[40];
+ int old_tag_len = 0;
+
+ tag = (struct pppoe_tag *)tag_buf;
+ pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
+ if (pOldTag) { /* if SID existed, copy old value and delete it */
+ old_tag_len = ntohs(pOldTag->tag_len);
+ if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) {
+ DEBUG_ERR("SID tag length too long!\n");
+ return -1;
+ }
+
+ memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN,
+ pOldTag->tag_data, old_tag_len);
+
+ if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) {
+ DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
+ return -1;
+ }
+ ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len);
+ }
+
+ tag->tag_type = PTT_RELAY_SID;
+ tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len);
+
+ /* insert the magic_code+client mac in relay tag */
+ pMagic = (unsigned short *)tag->tag_data;
+ *pMagic = htons(MAGIC_CODE);
+ memcpy(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN, ETH_ALEN);
+
+ /* Add relay tag */
+ if (__nat25_add_pppoe_tag(skb, tag) < 0)
+ return -1;
+
+ DEBUG_INFO("NAT25: Insert PPPoE, forward %s packet\n",
+ (ph->code == PADI_CODE ? "PADI" : "PADR"));
+ } else { /* not add relay tag */
+ if (priv->pppoe_connection_in_progress &&
+ memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) {
+ DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
+ return -2;
+ }
+
+ if (priv->pppoe_connection_in_progress == 0)
+ memcpy(priv->pppoe_addr, skb->data+ETH_ALEN, ETH_ALEN);
+
+ priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
+ }
+ } else {
+ return -1;
+ }
+ } else { /* session phase */
+ DEBUG_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name);
+
+ __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &ph->sid);
+
+ __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+
+ __nat25_db_print(priv);
+
+ if (!priv->ethBrExtInfo.addPPPoETag &&
+ priv->pppoe_connection_in_progress &&
+ !memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))
+ priv->pppoe_connection_in_progress = 0;
+ }
+ return 0;
+ default:
+ return -1;
+ }
+ } else if (protocol == 0x888e) {
+ /*---------------------------------------------------*/
+ /* Handle EAP frame */
+ /*---------------------------------------------------*/
+ switch (method) {
+ case NAT25_CHECK:
+ return -1;
+ case NAT25_INSERT:
+ return 0;
+ default:
+ return -1;
+ }
+ } else if ((protocol == 0xe2ae) || (protocol == 0xe2af)) {
+ /*---------------------------------------------------*/
+ /* Handle C-Media proprietary frame */
+ /*---------------------------------------------------*/
+ switch (method) {
+ case NAT25_CHECK:
+ return -1;
+ case NAT25_INSERT:
+ return 0;
+ default:
+ return -1;
+ }
+ } else if (protocol == ETH_P_IPV6) {
+ /*------------------------------------------------*/
+ /* Handle IPV6 frame */
+ /*------------------------------------------------*/
+ struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
+
+ if (sizeof(*iph) >= (skb->len - ETH_HLEN)) {
+ DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
+ return -1;
+ }
+
+ switch (method) {
+ case NAT25_CHECK:
+ if (skb->data[0] & 1)
+ return 0;
+ return -1;
+ case NAT25_INSERT:
+ DEBUG_INFO("NAT25: Insert IP, SA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
+ " DA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
+ iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
+ iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
+ iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
+ iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
+
+ if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
+ __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr);
+ __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+ __nat25_db_print(priv);
+
+ if (iph->nexthdr == IPPROTO_ICMPV6 &&
+ skb->len > (ETH_HLEN + sizeof(*iph) + 4)) {
+ if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph),
+ skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) {
+ struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph));
+ hdr->icmp6_cksum = 0;
+ hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr,
+ iph->payload_len,
+ IPPROTO_ICMPV6,
+ csum_partial((__u8 *)hdr, iph->payload_len, 0));
+ }
+ }
+ }
+ return 0;
+ default:
+ return -1;
+ }
+ }
+ return -1;
+}
+
+#define SERVER_PORT 67
+#define CLIENT_PORT 68
+#define DHCP_MAGIC 0x63825363
+#define BROADCAST_FLAG 0x8000
+
+struct dhcpMessage {
+ u_int8_t op;
+ u_int8_t htype;
+ u_int8_t hlen;
+ u_int8_t hops;
+ u_int32_t xid;
+ __be16 secs;
+ __be16 flags;
+ __be32 ciaddr;
+ __be32 yiaddr;
+ __be32 siaddr;
+ __be32 giaddr;
+ u_int8_t chaddr[16];
+ u_int8_t sname[64];
+ u_int8_t file[128];
+ __be32 cookie;
+ u_int8_t options[308]; /* 312 - cookie */
+};
+
+void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb)
+{
+ if (!skb)
+ return;
+
+ if (!priv->ethBrExtInfo.dhcp_bcst_disable) {
+ __be16 protocol = *((__be16 *)(skb->data + 2 * ETH_ALEN));
+
+ if (protocol == __constant_htons(ETH_P_IP)) { /* IP */
+ struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
+
+ if (iph->protocol == IPPROTO_UDP) { /* UDP */
+ struct udphdr *udph = (struct udphdr *)((size_t)iph + (iph->ihl << 2));
+
+ if ((udph->source == __constant_htons(CLIENT_PORT)) &&
+ (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */
+ struct dhcpMessage *dhcph =
+ (struct dhcpMessage *)((size_t)udph + sizeof(struct udphdr));
+ u32 cookie = be32_to_cpu((__be32)dhcph->cookie);
+
+ if (cookie == DHCP_MAGIC) { /* match magic word */
+ if (!(dhcph->flags & htons(BROADCAST_FLAG))) {
+ /* if not broadcast */
+ register int sum = 0;
+
+ DEBUG_INFO("DHCP: change flag of DHCP request to broadcast.\n");
+ /* or BROADCAST flag */
+ dhcph->flags |= htons(BROADCAST_FLAG);
+ /* recalculate checksum */
+ sum = ~(udph->check) & 0xffff;
+ sum += be16_to_cpu(dhcph->flags);
+ while (sum >> 16)
+ sum = (sum & 0xffff) + (sum >> 16);
+ udph->check = ~sum;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void *scdb_findEntry(struct adapter *priv, unsigned char *macAddr,
+ unsigned char *ipAddr)
+{
+ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
+ struct nat25_network_db_entry *db;
+ int hash;
+
+ __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr);
+ hash = __nat25_network_hash(networkAddr);
+ db = priv->nethash[hash];
+ while (db) {
+ if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
+ return (void *)db;
+ }
+
+ db = db->next_hash;
+ }
+
+ return NULL;
+}
diff --git a/drivers/staging/r8188eu/core/rtw_cmd.c b/drivers/staging/r8188eu/core/rtw_cmd.c
new file mode 100644
index 000000000000..ce73ac7cf973
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_cmd.c
@@ -0,0 +1,2128 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#define _RTW_CMD_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/mlme_osdep.h"
+#include "../include/rtw_br_ext.h"
+#include "../include/rtw_mlme_ext.h"
+
+/*
+Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
+No irqsave is necessary.
+*/
+
+static int _rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
+{
+ int res = _SUCCESS;
+
+ sema_init(&pcmdpriv->cmd_queue_sema, 0);
+ /* sema_init(&(pcmdpriv->cmd_done_sema), 0); */
+ sema_init(&pcmdpriv->terminate_cmdthread_sema, 0);
+
+ _rtw_init_queue(&pcmdpriv->cmd_queue);
+
+ /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
+
+ pcmdpriv->cmd_seq = 1;
+
+ pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
+ GFP_KERNEL);
+
+ if (!pcmdpriv->cmd_allocated_buf) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((size_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1));
+
+ pcmdpriv->rsp_allocated_buf = kzalloc(MAX_RSPSZ + 4, GFP_KERNEL);
+
+ if (!pcmdpriv->rsp_allocated_buf) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((size_t)(pcmdpriv->rsp_allocated_buf) & 3);
+
+ pcmdpriv->cmd_issued_cnt = 0;
+ pcmdpriv->cmd_done_cnt = 0;
+ pcmdpriv->rsp_cnt = 0;
+exit:
+
+ return res;
+}
+
+static void c2h_wk_callback(struct work_struct *work);
+
+static int _rtw_init_evt_priv(struct evt_priv *pevtpriv)
+{
+ int res = _SUCCESS;
+
+ /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
+ atomic_set(&pevtpriv->event_seq, 0);
+ pevtpriv->evt_done_cnt = 0;
+
+ _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
+ pevtpriv->c2h_wk_alive = false;
+ pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN + 1);
+
+ return res;
+}
+
+void rtw_free_evt_priv(struct evt_priv *pevtpriv)
+{
+ _cancel_workitem_sync(&pevtpriv->c2h_wk);
+ while (pevtpriv->c2h_wk_alive)
+ msleep(10);
+
+ while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
+ void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
+ if (c2h && c2h != (void *)pevtpriv)
+ kfree(c2h);
+ }
+}
+
+static void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
+{
+ if (pcmdpriv) {
+ kfree(pcmdpriv->cmd_allocated_buf);
+ kfree(pcmdpriv->rsp_allocated_buf);
+ }
+}
+
+/*
+Calling Context:
+
+rtw_enqueue_cmd can only be called between kernel thread,
+since only spin_lock is used.
+
+ISR/Call-Back functions can't call this sub-function.
+
+*/
+
+static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
+{
+ unsigned long flags;
+
+ if (!obj)
+ goto exit;
+
+ spin_lock_irqsave(&queue->lock, flags);
+
+ list_add_tail(&obj->list, &queue->queue);
+
+ spin_unlock_irqrestore(&queue->lock, flags);
+
+exit:
+
+ return _SUCCESS;
+}
+
+static struct cmd_obj *_rtw_dequeue_cmd(struct __queue *queue)
+{
+ struct cmd_obj *obj;
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->lock, flags);
+ if (list_empty(&queue->queue)) {
+ obj = NULL;
+ } else {
+ obj = container_of((&queue->queue)->next, struct cmd_obj, list);
+ rtw_list_delete(&obj->list);
+ }
+
+ spin_unlock_irqrestore(&queue->lock, flags);
+
+ return obj;
+}
+
+u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
+{
+ u32 res;
+
+ res = _rtw_init_cmd_priv(pcmdpriv);
+
+ return res;
+}
+
+u32 rtw_init_evt_priv(struct evt_priv *pevtpriv)
+{
+ int res;
+
+ res = _rtw_init_evt_priv(pevtpriv);
+
+ return res;
+}
+
+void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
+{
+ _rtw_free_cmd_priv(pcmdpriv);
+}
+
+static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+{
+ u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
+
+ /* To decide allow or not */
+ if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) &&
+ (!pcmdpriv->padapter->registrypriv.usbss_enable)) {
+ if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
+ if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
+ bAllow = true;
+ }
+ }
+
+ if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
+ bAllow = true;
+
+ if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) ||
+ !pcmdpriv->cmdthd_running) /* com_thread not running */
+ return _FAIL;
+ return _SUCCESS;
+}
+
+u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+{
+ int res = _FAIL;
+ struct adapter *padapter = pcmdpriv->padapter;
+
+ if (!cmd_obj)
+ goto exit;
+
+ cmd_obj->padapter = padapter;
+
+ res = rtw_cmd_filter(pcmdpriv, cmd_obj);
+ if (_FAIL == res) {
+ rtw_free_cmd_obj(cmd_obj);
+ goto exit;
+ }
+
+ res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
+
+ if (res == _SUCCESS)
+ up(&pcmdpriv->cmd_queue_sema);
+
+exit:
+
+ return res;
+}
+
+struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
+{
+ struct cmd_obj *cmd_obj;
+
+ cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
+
+ return cmd_obj;
+}
+
+void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv)
+{
+
+ pcmdpriv->cmd_done_cnt++;
+ /* up(&(pcmdpriv->cmd_done_sema)); */
+
+}
+
+void rtw_free_cmd_obj(struct cmd_obj *pcmd)
+{
+
+ if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
+ /* free parmbuf in cmd_obj */
+ kfree(pcmd->parmbuf);
+ }
+
+ if (pcmd->rsp) {
+ if (pcmd->rspsz != 0) {
+ /* free rsp in cmd_obj */
+ kfree(pcmd->rsp);
+ }
+ }
+
+ /* free cmd_obj */
+ kfree(pcmd);
+
+}
+
+int rtw_cmd_thread(void *context)
+{
+ u8 ret;
+ struct cmd_obj *pcmd;
+ u8 *pcmdbuf;
+ u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
+ void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
+ struct adapter *padapter = (struct adapter *)context;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ thread_enter("RTW_CMD_THREAD");
+
+ pcmdbuf = pcmdpriv->cmd_buf;
+
+ pcmdpriv->cmdthd_running = true;
+ up(&pcmdpriv->terminate_cmdthread_sema);
+
+ while (1) {
+ if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL)
+ break;
+
+ if (padapter->bDriverStopped ||
+ padapter->bSurpriseRemoved) {
+ DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
+ __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
+ break;
+ }
+_next:
+ if (padapter->bDriverStopped ||
+ padapter->bSurpriseRemoved) {
+ DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
+ __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
+ break;
+ }
+
+ pcmd = rtw_dequeue_cmd(pcmdpriv);
+ if (!pcmd)
+ continue;
+
+ if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
+ pcmd->res = H2C_DROPPED;
+ goto post_process;
+ }
+
+ pcmdpriv->cmd_issued_cnt++;
+
+ pcmd->cmdsz = _RND4((pcmd->cmdsz));/* _RND4 */
+
+ memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
+
+ if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
+ cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
+
+ if (cmd_hdl) {
+ ret = cmd_hdl(pcmd->padapter, pcmdbuf);
+ pcmd->res = ret;
+ }
+
+ pcmdpriv->cmd_seq++;
+ } else {
+ pcmd->res = H2C_PARAMETERS_ERROR;
+ }
+
+ cmd_hdl = NULL;
+
+post_process:
+
+ /* call callback function for post-processed */
+ if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
+ pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
+ if (!pcmd_callback)
+ rtw_free_cmd_obj(pcmd);
+ else
+ /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
+ pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
+ } else {
+ rtw_free_cmd_obj(pcmd);
+ }
+
+ flush_signals_thread();
+
+ goto _next;
+ }
+ pcmdpriv->cmdthd_running = false;
+
+ /* free all cmd_obj resources */
+ do {
+ pcmd = rtw_dequeue_cmd(pcmdpriv);
+ if (!pcmd)
+ break;
+
+ /* DBG_88E("%s: leaving... drop cmdcode:%u\n", __func__, pcmd->cmdcode); */
+
+ rtw_free_cmd_obj(pcmd);
+ } while (1);
+
+ up(&pcmdpriv->terminate_cmdthread_sema);
+
+ thread_exit();
+}
+
+u8 rtw_setstandby_cmd(struct adapter *padapter, uint action)
+{
+ struct cmd_obj *ph2c;
+ struct usb_suspend_parm *psetusbsuspend;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 ret = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ psetusbsuspend = kzalloc(sizeof(struct usb_suspend_parm), GFP_ATOMIC);
+ if (!psetusbsuspend) {
+ kfree(ph2c);
+ ret = _FAIL;
+ goto exit;
+ }
+
+ psetusbsuspend->action = action;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));
+
+ ret = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return ret;
+}
+
+/*
+rtw_sitesurvey_cmd(~)
+ ### NOTE:#### (!!!!)
+ MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
+*/
+u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
+ struct rtw_ieee80211_channel *ch, int ch_num)
+{
+ u8 res = _FAIL;
+ struct cmd_obj *ph2c;
+ struct sitesurvey_parm *psurveyPara;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
+ }
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
+ }
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c)
+ return _FAIL;
+
+ psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
+ if (!psurveyPara) {
+ kfree(ph2c);
+ return _FAIL;
+ }
+
+ rtw_free_network_queue(padapter, false);
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
+
+ /* psurveyPara->bsslimit = 48; */
+ psurveyPara->scan_mode = pmlmepriv->scan_mode;
+
+ /* prepare ssid list */
+ if (ssid) {
+ int i;
+ for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
+ if (ssid[i].SsidLength) {
+ memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
+ psurveyPara->ssid_num++;
+ }
+ }
+ }
+
+ /* prepare channel list */
+ if (ch) {
+ int i;
+ for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
+ if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
+ memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
+ psurveyPara->ch_num++;
+ }
+ }
+ }
+
+ set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+ if (res == _SUCCESS) {
+ pmlmepriv->scan_start_time = jiffies;
+
+ _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
+
+ rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
+
+ pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
+ } else {
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+ }
+
+ return res;
+}
+
+u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
+{
+ struct cmd_obj *ph2c;
+ struct setdatarate_parm *pbsetdataratepara;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pbsetdataratepara = kzalloc(sizeof(struct setdatarate_parm), GFP_ATOMIC);
+ if (!pbsetdataratepara) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
+ pbsetdataratepara->mac_id = 5;
+ memcpy(pbsetdataratepara->datarates, rateset, NumRates);
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+u8 rtw_setbasicrate_cmd(struct adapter *padapter, u8 *rateset)
+{
+ struct cmd_obj *ph2c;
+ struct setbasicrate_parm *pssetbasicratepara;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+ pssetbasicratepara = kzalloc(sizeof(struct setbasicrate_parm), GFP_ATOMIC);
+
+ if (!pssetbasicratepara) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_);
+
+ memcpy(pssetbasicratepara->basicrates, rateset, NumRates);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+/*
+unsigned char rtw_setphy_cmd(unsigned char *adapter)
+
+1. be called only after rtw_update_registrypriv_dev_network(~) or mp testing program
+2. for AdHoc/Ap mode or mp mode?
+
+*/
+u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch)
+{
+ struct cmd_obj *ph2c;
+ struct setphy_parm *psetphypara;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+ psetphypara = kzalloc(sizeof(struct setphy_parm), GFP_ATOMIC);
+
+ if (!psetphypara) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);
+
+ psetphypara->modem = modem;
+ psetphypara->rfchannel = ch;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+u8 rtw_setbbreg_cmd(struct adapter *padapter, u8 offset, u8 val)
+{
+ struct cmd_obj *ph2c;
+ struct writeBB_parm *pwritebbparm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+ pwritebbparm = kzalloc(sizeof(struct writeBB_parm), GFP_ATOMIC);
+
+ if (!pwritebbparm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));
+
+ pwritebbparm->offset = offset;
+ pwritebbparm->value = val;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+u8 rtw_getbbreg_cmd(struct adapter *padapter, u8 offset, u8 *pval)
+{
+ struct cmd_obj *ph2c;
+ struct readBB_parm *prdbbparm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+ prdbbparm = kzalloc(sizeof(struct readBB_parm), GFP_ATOMIC);
+
+ if (!prdbbparm) {
+ kfree(ph2c);
+ return _FAIL;
+ }
+
+ INIT_LIST_HEAD(&ph2c->list);
+ ph2c->cmdcode = GEN_CMD_CODE(_GetBBReg);
+ ph2c->parmbuf = (unsigned char *)prdbbparm;
+ ph2c->cmdsz = sizeof(struct readBB_parm);
+ ph2c->rsp = pval;
+ ph2c->rspsz = sizeof(struct readBB_rsp);
+
+ prdbbparm->offset = offset;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+u8 rtw_setrfreg_cmd(struct adapter *padapter, u8 offset, u32 val)
+{
+ struct cmd_obj *ph2c;
+ struct writeRF_parm *pwriterfparm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+ pwriterfparm = kzalloc(sizeof(struct writeRF_parm), GFP_ATOMIC);
+
+ if (!pwriterfparm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
+
+ pwriterfparm->offset = offset;
+ pwriterfparm->value = val;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+u8 rtw_getrfreg_cmd(struct adapter *padapter, u8 offset, u8 *pval)
+{
+ struct cmd_obj *ph2c;
+ struct readRF_parm *prdrfparm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ prdrfparm = kzalloc(sizeof(struct readRF_parm), GFP_ATOMIC);
+ if (!prdrfparm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ INIT_LIST_HEAD(&ph2c->list);
+ ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
+ ph2c->parmbuf = (unsigned char *)prdrfparm;
+ ph2c->cmdsz = sizeof(struct readRF_parm);
+ ph2c->rsp = pval;
+ ph2c->rspsz = sizeof(struct readRF_rsp);
+
+ prdrfparm->offset = offset;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+
+void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+
+
+ kfree(pcmd->parmbuf);
+ kfree(pcmd);
+
+ if (padapter->registrypriv.mp_mode == 1)
+ padapter->mppriv.workparam.bcompleted = true;
+
+}
+
+void rtw_readtssi_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+
+
+ kfree(pcmd->parmbuf);
+ kfree(pcmd);
+
+ if (padapter->registrypriv.mp_mode == 1)
+ padapter->mppriv.workparam.bcompleted = true;
+
+}
+
+u8 rtw_createbss_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *pcmd;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
+ u8 res = _SUCCESS;
+
+ rtw_led_control(padapter, LED_CTL_START_TO_LINK);
+
+ pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ INIT_LIST_HEAD(&pcmd->list);
+ pcmd->cmdcode = _CreateBss_CMD_;
+ pcmd->parmbuf = (unsigned char *)pdev_network;
+ pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+ pdev_network->Length = pcmd->cmdsz;
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+exit:
+
+ return res;
+}
+
+u8 rtw_createbss_cmd_ex(struct adapter *padapter, unsigned char *pbss, unsigned int sz)
+{
+ struct cmd_obj *pcmd;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ INIT_LIST_HEAD(&pcmd->list);
+ pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
+ pcmd->parmbuf = pbss;
+ pcmd->cmdsz = sz;
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
+{
+ u8 res = _SUCCESS;
+ uint t_len = 0;
+ struct wlan_bssid_ex *psecnetwork;
+ struct cmd_obj *pcmd;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ rtw_led_control(padapter, LED_CTL_START_TO_LINK);
+
+ pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+ /* for IEs is fix buf size */
+ t_len = sizeof(struct wlan_bssid_ex);
+
+ /* for hidden ap to set fw_state here */
+ if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
+ switch (ndis_network_mode) {
+ case Ndis802_11IBSS:
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ break;
+ case Ndis802_11Infrastructure:
+ set_fwstate(pmlmepriv, WIFI_STATION_STATE);
+ break;
+ case Ndis802_11APMode:
+ case Ndis802_11AutoUnknown:
+ case Ndis802_11InfrastructureMax:
+ break;
+ }
+ }
+
+ psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
+ if (!psecnetwork) {
+ kfree(pcmd);
+ res = _FAIL;
+ goto exit;
+ }
+
+ memset(psecnetwork, 0, t_len);
+
+ memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
+
+ psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
+
+ if (psecnetwork->IELength - 12 < 255) {
+ memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);
+ } else {
+ memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], 255);
+ }
+
+ psecnetwork->IELength = 0;
+ /* Added by Albert 2009/02/18 */
+ /* If the the driver wants to use the bssid to create the connection. */
+ /* If not, we have to copy the connecting AP's MAC address to it so that */
+ /* the driver just has the bssid information for PMKIDList searching. */
+
+ if (!pmlmepriv->assoc_by_bssid)
+ memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
+
+ psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
+
+ pqospriv->qos_option = 0;
+
+ if (pregistrypriv->wmm_enable) {
+ u32 tmp_len;
+
+ tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
+
+ if (psecnetwork->IELength != tmp_len) {
+ psecnetwork->IELength = tmp_len;
+ pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
+ } else {
+ pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
+ }
+ }
+
+ phtpriv->ht_option = false;
+ if (pregistrypriv->ht_enable) {
+ /* Added by Albert 2010/06/23 */
+ /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
+ /* Especially for Realtek 8192u SoftAP. */
+ if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
+ (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
+ (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
+ /* rtw_restructure_ht_ie */
+ rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
+ pnetwork->network.IELength, &psecnetwork->IELength);
+ }
+ }
+
+ pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
+
+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
+ padapter->pwrctrlpriv.smart_ps = 0;
+ else
+ padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
+
+ DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps);
+
+ pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
+
+ INIT_LIST_HEAD(&pcmd->list);
+ pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
+ pcmd->parmbuf = (unsigned char *)psecnetwork;
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
+{
+ struct cmd_obj *cmdobj = NULL;
+ struct disconnect_parm *param = NULL;
+ struct cmd_priv *cmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ /* prepare cmd parameter */
+ param = kzalloc(sizeof(*param), GFP_ATOMIC);
+ if (!param) {
+ res = _FAIL;
+ goto exit;
+ }
+ param->deauth_timeout_ms = deauth_timeout_ms;
+
+ if (enqueue) {
+ /* need enqueue, prepare cmd_obj and enqueue */
+ cmdobj = kzalloc(sizeof(*cmdobj), GFP_ATOMIC);
+ if (!cmdobj) {
+ res = _FAIL;
+ kfree(param);
+ goto exit;
+ }
+ init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
+ res = rtw_enqueue_cmd(cmdpriv, cmdobj);
+ } else {
+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+ if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param))
+ res = _FAIL;
+ kfree(param);
+ }
+
+exit:
+
+ return res;
+}
+
+u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra networktype)
+{
+ struct cmd_obj *ph2c;
+ struct setopmode_parm *psetop;
+
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!ph2c) {
+ res = false;
+ goto exit;
+ }
+ psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
+
+ if (!psetop) {
+ kfree(ph2c);
+ res = false;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
+ psetop->mode = (u8)networktype;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
+{
+ struct cmd_obj *ph2c;
+ struct set_stakey_parm *psetstakey_para;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct set_stakey_rsp *psetstakey_rsp = NULL;
+
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct sta_info *sta = (struct sta_info *)psta;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
+ if (!psetstakey_para) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
+ if (!psetstakey_rsp) {
+ kfree(ph2c);
+ kfree(psetstakey_para);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
+ ph2c->rsp = (u8 *)psetstakey_rsp;
+ ph2c->rspsz = sizeof(struct set_stakey_rsp);
+
+ memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
+ else
+ GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
+
+ if (unicast_key)
+ memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
+ else
+ memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
+
+ /* jeff: set this because at least sw key is ready */
+ padapter->securitypriv.busetkipkey = true;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
+{
+ struct cmd_obj *ph2c;
+ struct set_stakey_parm *psetstakey_para;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct set_stakey_rsp *psetstakey_rsp = NULL;
+ struct sta_info *sta = (struct sta_info *)psta;
+ u8 res = _SUCCESS;
+
+ if (!enqueue) {
+ clear_cam_entry(padapter, entry);
+ } else {
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_para = kzalloc(sizeof(struct set_stakey_parm),
+ GFP_ATOMIC);
+ if (!psetstakey_para) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp),
+ GFP_ATOMIC);
+ if (!psetstakey_rsp) {
+ kfree(ph2c);
+ kfree(psetstakey_para);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
+ ph2c->rsp = (u8 *)psetstakey_rsp;
+ ph2c->rspsz = sizeof(struct set_stakey_rsp);
+
+ memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
+
+ psetstakey_para->algorithm = _NO_PRIVACY_;
+
+ psetstakey_para->id = entry;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+ }
+exit:
+
+ return res;
+}
+
+u8 rtw_setrttbl_cmd(struct adapter *padapter, struct setratable_parm *prate_table)
+{
+ struct cmd_obj *ph2c;
+ struct setratable_parm *psetrttblparm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+ psetrttblparm = kzalloc(sizeof(struct setratable_parm), GFP_KERNEL);
+
+ if (!psetrttblparm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
+
+ memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+u8 rtw_getrttbl_cmd(struct adapter *padapter, struct getratable_rsp *pval)
+{
+ struct cmd_obj *ph2c;
+ struct getratable_parm *pgetrttblparm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+ pgetrttblparm = kzalloc(sizeof(struct getratable_parm), GFP_KERNEL);
+
+ if (!pgetrttblparm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+/* init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable)); */
+
+ INIT_LIST_HEAD(&ph2c->list);
+ ph2c->cmdcode = GEN_CMD_CODE(_GetRaTable);
+ ph2c->parmbuf = (unsigned char *)pgetrttblparm;
+ ph2c->cmdsz = sizeof(struct getratable_parm);
+ ph2c->rsp = (u8 *)pval;
+ ph2c->rspsz = sizeof(struct getratable_rsp);
+
+ pgetrttblparm->rsvd = 0x0;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+u8 rtw_setassocsta_cmd(struct adapter *padapter, u8 *mac_addr)
+{
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct cmd_obj *ph2c;
+ struct set_assocsta_parm *psetassocsta_para;
+ struct set_stakey_rsp *psetassocsta_rsp = NULL;
+
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetassocsta_para = kzalloc(sizeof(struct set_assocsta_parm), GFP_ATOMIC);
+ if (!psetassocsta_para) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetassocsta_rsp = kzalloc(sizeof(struct set_assocsta_rsp), GFP_ATOMIC);
+ if (!psetassocsta_rsp) {
+ kfree(ph2c);
+ kfree(psetassocsta_para);
+ return _FAIL;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
+ ph2c->rsp = (u8 *)psetassocsta_rsp;
+ ph2c->rspsz = sizeof(struct set_assocsta_rsp);
+
+ memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+ }
+
+u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
+{
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct cmd_obj *ph2c;
+ struct addBaReq_parm *paddbareq_parm;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC);
+ if (!paddbareq_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ paddbareq_parm->tid = tid;
+ memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
+
+ /* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */
+
+ /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
+ pdrvextra_cmd_parm->type_size = 0;
+ pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+ /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+u8 rtw_set_ch_cmd(struct adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue)
+{
+ struct cmd_obj *pcmdobj;
+ struct set_ch_parm *set_ch_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 res = _SUCCESS;
+
+ DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
+ FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
+
+ /* check input parameter */
+
+ /* prepare cmd parameter */
+ set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_ATOMIC);
+ if (!set_ch_parm) {
+ res = _FAIL;
+ goto exit;
+ }
+ set_ch_parm->ch = ch;
+ set_ch_parm->bw = bw;
+ set_ch_parm->ch_offset = ch_offset;
+
+ if (enqueue) {
+ /* need enqueue, prepare cmd_obj and enqueue */
+ pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmdobj) {
+ kfree(set_ch_parm);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));
+ res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+ } else {
+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+ if (H2C_SUCCESS != set_ch_hdl(padapter, (u8 *)set_ch_parm))
+ res = _FAIL;
+
+ kfree(set_ch_parm);
+ }
+
+ /* do something based on res... */
+
+exit:
+
+ DBG_88E(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
+
+ return res;
+}
+
+u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
+{
+ struct cmd_obj *pcmdobj;
+ struct SetChannelPlan_param *setChannelPlan_param;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 res = _SUCCESS;
+
+ /* check input parameter */
+ if (!rtw_is_channel_plan_valid(chplan)) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ /* prepare cmd parameter */
+ setChannelPlan_param = kzalloc(sizeof(struct SetChannelPlan_param),
+ GFP_KERNEL);
+ if (!setChannelPlan_param) {
+ res = _FAIL;
+ goto exit;
+ }
+ setChannelPlan_param->channel_plan = chplan;
+
+ if (enqueue) {
+ /* need enqueue, prepare cmd_obj and enqueue */
+ pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmdobj) {
+ kfree(setChannelPlan_param);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
+ res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+ } else {
+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+ if (H2C_SUCCESS != set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param))
+ res = _FAIL;
+
+ kfree(setChannelPlan_param);
+ }
+
+ /* do something based on res... */
+ if (res == _SUCCESS)
+ padapter->mlmepriv.ChannelPlan = chplan;
+
+exit:
+
+ return res;
+}
+
+u8 rtw_led_blink_cmd(struct adapter *padapter, struct LED_871x *pLed)
+{
+ struct cmd_obj *pcmdobj;
+ struct LedBlink_param *ledBlink_param;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 res = _SUCCESS;
+
+ pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmdobj) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ ledBlink_param = kzalloc(sizeof(struct LedBlink_param), GFP_ATOMIC);
+ if (!ledBlink_param) {
+ kfree(pcmdobj);
+ res = _FAIL;
+ goto exit;
+ }
+
+ ledBlink_param->pLed = pLed;
+
+ init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, GEN_CMD_CODE(_LedBlink));
+ res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_set_csa_cmd(struct adapter *padapter, u8 new_ch_no)
+{
+ struct cmd_obj *pcmdobj;
+ struct SetChannelSwitch_param *setChannelSwitch_param;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 res = _SUCCESS;
+
+ pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmdobj) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ setChannelSwitch_param = kzalloc(sizeof(struct SetChannelSwitch_param),
+ GFP_ATOMIC);
+ if (!setChannelSwitch_param) {
+ kfree(pcmdobj);
+ res = _FAIL;
+ goto exit;
+ }
+
+ setChannelSwitch_param->new_ch_no = new_ch_no;
+
+ init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch));
+ res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_tdls_cmd(struct adapter *padapter, u8 *addr, u8 option)
+{
+ return _SUCCESS;
+}
+
+static void traffic_status_watchdog(struct adapter *padapter)
+{
+ u8 bEnterPS;
+ u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
+ u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ /* */
+ /* Determine if our traffic is busy now */
+ /* */
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
+ bBusyTraffic = true;
+
+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
+ bRxBusyTraffic = true;
+ else
+ bTxBusyTraffic = true;
+ }
+
+ /* Higher Tx/Rx data. */
+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
+ bHigherBusyTraffic = true;
+
+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
+ bHigherBusyRxTraffic = true;
+ else
+ bHigherBusyTxTraffic = true;
+ }
+
+ /* check traffic for powersaving. */
+ if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
+ (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
+ bEnterPS = false;
+ else
+ bEnterPS = true;
+
+ /* LeisurePS only work in infra mode. */
+ if (bEnterPS)
+ LPS_Enter(padapter);
+ else
+ LPS_Leave(padapter);
+ } else {
+ LPS_Leave(padapter);
+ }
+
+ pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
+ pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
+ pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
+ pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
+ pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
+ pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
+ pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
+}
+
+static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
+{
+ struct mlme_priv *pmlmepriv;
+
+ padapter = (struct adapter *)pbuf;
+ pmlmepriv = &padapter->mlmepriv;
+
+#ifdef CONFIG_88EU_AP_MODE
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ expire_timeout_chk(padapter);
+#endif
+
+ rtw_hal_sreset_xmit_status_check(padapter);
+
+ linked_status_chk(padapter);
+ traffic_status_watchdog(padapter);
+
+ rtw_hal_dm_watchdog(padapter);
+}
+
+static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 mstatus;
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
+ return;
+
+ switch (lps_ctrl_type) {
+ case LPS_CTRL_SCAN:
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ /* connect */
+ LPS_Leave(padapter);
+ }
+ break;
+ case LPS_CTRL_JOINBSS:
+ LPS_Leave(padapter);
+ break;
+ case LPS_CTRL_CONNECT:
+ mstatus = 1;/* connect */
+ /* Reset LPS Setting */
+ padapter->pwrctrlpriv.LpsIdleCount = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
+ break;
+ case LPS_CTRL_DISCONNECT:
+ mstatus = 0;/* disconnect */
+ LPS_Leave(padapter);
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
+ break;
+ case LPS_CTRL_SPECIAL_PACKET:
+ /* DBG_88E("LPS_CTRL_SPECIAL_PACKET\n"); */
+ pwrpriv->DelayLPSLastTimeStamp = jiffies;
+ LPS_Leave(padapter);
+ break;
+ case LPS_CTRL_LEAVE:
+ LPS_Leave(padapter);
+ break;
+ default:
+ break;
+ }
+
+}
+
+u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ /* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */
+ u8 res = _SUCCESS;
+
+ /* if (!pwrctrlpriv->bLeisurePs) */
+ /* return res; */
+
+ if (enqueue) {
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
+ GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
+ pdrvextra_cmd_parm->type_size = lps_ctrl_type;
+ pdrvextra_cmd_parm->pbuf = NULL;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+ } else {
+ lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
+ }
+
+exit:
+
+ return res;
+}
+
+static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
+{
+ rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
+}
+
+u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
+ GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
+ pdrvextra_cmd_parm->type_size = min_time;
+ pdrvextra_cmd_parm->pbuf = NULL;
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
+{
+ rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
+}
+
+u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 support_ant_div;
+ u8 res = _SUCCESS;
+
+ rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
+ if (!support_ant_div)
+ return res;
+
+ if (enqueue) {
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
+ GFP_KERNEL);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
+ pdrvextra_cmd_parm->type_size = antenna;
+ pdrvextra_cmd_parm->pbuf = NULL;
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+ } else {
+ antenna_select_wk_hdl(padapter, antenna);
+ }
+exit:
+
+ return res;
+}
+
+static void power_saving_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
+{
+ rtw_ps_processor(padapter);
+}
+
+#ifdef CONFIG_88EU_P2P
+u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return res;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
+ pdrvextra_cmd_parm->type_size = intCmdType; /* As the command tppe. */
+ pdrvextra_cmd_parm->pbuf = NULL; /* Must be NULL here */
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+#endif /* CONFIG_88EU_P2P */
+
+u8 rtw_ps_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *ppscmd;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 res = _SUCCESS;
+
+ ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ppscmd) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ppscmd);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
+ pdrvextra_cmd_parm->pbuf = NULL;
+ init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
+
+exit:
+
+ return res;
+}
+
+#ifdef CONFIG_88EU_AP_MODE
+
+static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
+{
+ int cnt = 0;
+ struct sta_info *psta_bmc;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+ if (!psta_bmc)
+ return;
+
+ if (psta_bmc->sleepq_len == 0) {
+ u8 val = 0;
+
+ /* while ((rtw_read32(padapter, 0x414)&0x00ffff00)!= 0) */
+ /* while ((rtw_read32(padapter, 0x414)&0x0000ff00)!= 0) */
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
+
+ while (!val) {
+ msleep(100);
+
+ cnt++;
+
+ if (cnt > 10)
+ break;
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
+ }
+
+ if (cnt <= 10) {
+ pstapriv->tim_bitmap &= ~BIT(0);
+ pstapriv->sta_dz_bitmap &= ~BIT(0);
+
+ update_beacon(padapter, _TIM_IE_, NULL, false);
+ } else { /* re check again */
+ rtw_chk_hi_queue_cmd(padapter);
+ }
+ }
+}
+
+u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
+ pdrvextra_cmd_parm->type_size = 0;
+ pdrvextra_cmd_parm->pbuf = NULL;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+ return res;
+}
+#endif
+
+u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
+ pdrvextra_cmd_parm->type_size = c2h_evt ? 16 : 0;
+ pdrvextra_cmd_parm->pbuf = c2h_evt;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+
+static s32 c2h_evt_hdl(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter)
+{
+ s32 ret = _FAIL;
+ u8 buf[16];
+
+ if (!c2h_evt) {
+ /* No c2h event in cmd_obj, read c2h event before handling*/
+ if (c2h_evt_read(adapter, buf) == _SUCCESS) {
+ c2h_evt = (struct c2h_evt_hdr *)buf;
+
+ if (filter && !filter(c2h_evt->id))
+ goto exit;
+
+ ret = rtw_hal_c2h_handler(adapter, c2h_evt);
+ }
+ } else {
+ if (filter && !filter(c2h_evt->id))
+ goto exit;
+
+ ret = rtw_hal_c2h_handler(adapter, c2h_evt);
+ }
+exit:
+ return ret;
+}
+
+static void c2h_wk_callback(struct work_struct *work)
+{
+ struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
+ struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv);
+ struct c2h_evt_hdr *c2h_evt;
+ c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter);
+
+ evtpriv->c2h_wk_alive = true;
+
+ while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
+ if ((c2h_evt = (struct c2h_evt_hdr *)rtw_cbuf_pop(evtpriv->c2h_queue)) != NULL) {
+ /* This C2H event is read, clear it */
+ c2h_evt_clear(adapter);
+ } else {
+ c2h_evt = kmalloc(16, GFP_KERNEL);
+ if (c2h_evt) {
+ /* This C2H event is not read, read & clear now */
+ if (c2h_evt_read(adapter, (u8 *)c2h_evt) != _SUCCESS) {
+ kfree(c2h_evt);
+ continue;
+ }
+ } else {
+ return;
+ }
+ }
+
+ /* Special pointer to trigger c2h_evt_clear only */
+ if ((void *)c2h_evt == (void *)evtpriv)
+ continue;
+
+ if (!c2h_evt_exist(c2h_evt)) {
+ kfree(c2h_evt);
+ continue;
+ }
+
+ if (ccx_id_filter(c2h_evt->id)) {
+ /* Handle CCX report here */
+ rtw_hal_c2h_handler(adapter, c2h_evt);
+ kfree(c2h_evt);
+ } else {
+#ifdef CONFIG_88EU_P2P
+ /* Enqueue into cmd_thread for others */
+ rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
+#endif
+ }
+ }
+
+ evtpriv->c2h_wk_alive = false;
+}
+
+u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct drvextra_cmd_parm *pdrvextra_cmd;
+
+ if (!pbuf)
+ return H2C_PARAMETERS_ERROR;
+
+ pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
+
+ switch (pdrvextra_cmd->ec_id) {
+ case DYNAMIC_CHK_WK_CID:
+ dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
+ break;
+ case POWER_SAVING_CTRL_WK_CID:
+ power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
+ break;
+ case LPS_CTRL_WK_CID:
+ lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
+ break;
+ case RTP_TIMER_CFG_WK_CID:
+ rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
+ break;
+ case ANT_SELECT_WK_CID:
+ antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
+ break;
+#ifdef CONFIG_88EU_P2P
+ case P2P_PS_WK_CID:
+ p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type_size);
+ break;
+ case P2P_PROTO_WK_CID:
+ /* Commented by Albert 2011/07/01 */
+ /* I used the type_size as the type command */
+ p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type_size);
+ break;
+#endif
+#ifdef CONFIG_88EU_AP_MODE
+ case CHECK_HIQ_WK_CID:
+ rtw_chk_hi_queue_hdl(padapter);
+ break;
+#endif /* CONFIG_88EU_AP_MODE */
+ case C2H_WK_CID:
+ c2h_evt_hdl(padapter, (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL);
+ break;
+ default:
+ break;
+ }
+
+ if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
+ kfree(pdrvextra_cmd->pbuf);
+
+ return H2C_SUCCESS;
+}
+
+void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (pcmd->res == H2C_DROPPED) {
+ /* TODO: cancel timer and do timeout handler directly... */
+ /* need to make timeout handlerOS independent */
+ _set_timer(&pmlmepriv->scan_to_timer, 1);
+ } else if (pcmd->res != H2C_SUCCESS) {
+ _set_timer(&pmlmepriv->scan_to_timer, 1);
+ }
+
+ /* free cmd */
+ rtw_free_cmd_obj(pcmd);
+
+}
+void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (pcmd->res != H2C_SUCCESS) {
+ spin_lock_bh(&pmlmepriv->lock);
+ set_fwstate(pmlmepriv, _FW_LINKED);
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ return;
+ } else /* clear bridge database */
+ nat25_db_cleanup(padapter);
+
+ /* free cmd */
+ rtw_free_cmd_obj(pcmd);
+}
+
+void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (pcmd->res == H2C_DROPPED) {
+ /* TODO: cancel timer and do timeout handler directly... */
+ /* need to make timeout handlerOS independent */
+ _set_timer(&pmlmepriv->assoc_timer, 1);
+ } else if (pcmd->res != H2C_SUCCESS) {
+ _set_timer(&pmlmepriv->assoc_timer, 1);
+ }
+
+ rtw_free_cmd_obj(pcmd);
+}
+
+void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ u8 timer_cancelled;
+ struct sta_info *psta = NULL;
+ struct wlan_network *pwlan = NULL;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+
+ if (pcmd->res != H2C_SUCCESS)
+ _set_timer(&pmlmepriv->assoc_timer, 1);
+
+ _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
+ if (!psta) {
+ psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
+ if (!psta)
+ goto createbss_cmd_fail;
+ }
+
+ rtw_indicate_connect(padapter);
+ } else {
+
+ pwlan = _rtw_alloc_network(pmlmepriv);
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ if (!pwlan) {
+ pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
+ if (!pwlan) {
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ goto createbss_cmd_fail;
+ }
+ pwlan->last_scanned = jiffies;
+ } else {
+ list_add_tail(&pwlan->list, &pmlmepriv->scanned_queue.queue);
+ }
+
+ pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
+ memcpy(&pwlan->network, pnetwork, pnetwork->Length);
+
+ memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
+ }
+
+createbss_cmd_fail:
+
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ rtw_free_cmd_obj(pcmd);
+
+}
+
+void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
+ struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
+
+ if (!psta)
+ goto exit;
+exit:
+ rtw_free_cmd_obj(pcmd);
+
+}
+
+void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
+ struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
+ struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
+
+ if (!psta)
+ goto exit;
+
+ psta->aid = passocsta_rsp->cam_id;
+ psta->mac_id = passocsta_rsp->cam_id;
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+ set_fwstate(pmlmepriv, _FW_LINKED);
+ spin_unlock_bh(&pmlmepriv->lock);
+
+exit:
+ rtw_free_cmd_obj(pcmd);
+
+}
diff --git a/drivers/staging/r8188eu/core/rtw_debug.c b/drivers/staging/r8188eu/core/rtw_debug.c
new file mode 100644
index 000000000000..2ee64cef73f7
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_debug.c
@@ -0,0 +1,904 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#define _RTW_DEBUG_C_
+
+#include "../include/rtw_debug.h"
+#include "../include/drv_types.h"
+
+int proc_get_drv_version(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "%s\n", DRIVERVERSION);
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_write_reg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ *eof = 1;
+ return 0;
+}
+
+int proc_set_write_reg(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ char tmp[32];
+ u32 addr, val, len;
+
+ if (count < 3) {
+ DBG_88E("argument size is less than 3\n");
+ return -EFAULT;
+ }
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ int num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
+
+ if (num != 3) {
+ DBG_88E("invalid write_reg parameter!\n");
+ return count;
+ }
+ switch (len) {
+ case 1:
+ rtw_write8(padapter, addr, (u8)val);
+ break;
+ case 2:
+ rtw_write16(padapter, addr, (u16)val);
+ break;
+ case 4:
+ rtw_write32(padapter, addr, val);
+ break;
+ default:
+ DBG_88E("error write length =%d", len);
+ break;
+ }
+ }
+ return count;
+}
+
+static u32 proc_get_read_addr = 0xeeeeeeee;
+static u32 proc_get_read_len = 0x4;
+
+int proc_get_read_reg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ int len = 0;
+
+ if (proc_get_read_addr == 0xeeeeeeee) {
+ *eof = 1;
+ return len;
+ }
+
+ switch (proc_get_read_len) {
+ case 1:
+ len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+ break;
+ case 2:
+ len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
+ break;
+ case 4:
+ len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
+ break;
+ default:
+ len += snprintf(page + len, count - len, "error read length=%d\n", proc_get_read_len);
+ break;
+ }
+
+ *eof = 1;
+ return len;
+}
+
+int proc_set_read_reg(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ char tmp[16];
+ u32 addr, len;
+
+ if (count < 2) {
+ DBG_88E("argument size is less than 2\n");
+ return -EFAULT;
+ }
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ int num = sscanf(tmp, "%x %x", &addr, &len);
+
+ if (num != 2) {
+ DBG_88E("invalid read_reg parameter!\n");
+ return count;
+ }
+
+ proc_get_read_addr = addr;
+
+ proc_get_read_len = len;
+ }
+
+ return count;
+}
+
+int proc_get_fwstate(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "fwstate=0x%x\n", get_fwstate(pmlmepriv));
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_sec_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",
+ psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
+ psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_mlmext_state(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_qos_option(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "qos_option=%d\n", pmlmepriv->qospriv.qos_option);
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_ht_option(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ int len = 0;
+ len += snprintf(page + len, count - len, "ht_option=%d\n", pmlmepriv->htpriv.ht_option);
+ *eof = 1;
+ return len;
+}
+
+int proc_get_rf_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offet=%d\n",
+ pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
+ *eof = 1;
+ return len;
+}
+
+int proc_get_ap_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct sta_info *psta;
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ int len = 0;
+
+ psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
+ if (psta) {
+ int i;
+ struct recv_reorder_ctrl *preorder_ctrl;
+
+ len += snprintf(page + len, count - len, "SSID=%s\n", cur_network->network.Ssid.Ssid);
+ len += snprintf(page + len, count - len, "sta's macaddr:%pM\n", psta->hwaddr);
+ len += snprintf(page + len, count - len, "cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
+ len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
+ len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+ len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
+ len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
+ len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
+ len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+
+ for (i = 0; i < 16; i++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
+ if (preorder_ctrl->enable)
+ len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", i, preorder_ctrl->indicate_seq);
+ }
+ } else {
+ len += snprintf(page + len, count - len, "can't get sta's macaddr, cur_network's macaddr: %pM\n", cur_network->network.MacAddress);
+ }
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_adapter_state(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "bSurpriseRemoved=%d, bDriverStopped=%d\n",
+ padapter->bSurpriseRemoved, padapter->bDriverStopped);
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_trx_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d, free_ext_xmitbuf_cnt=%d, free_recvframe_cnt=%d\n",
+ pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt, precvpriv->free_recvframe_cnt);
+ len += snprintf(page + len, count - len, "rx_urb_pending_cn=%d\n", precvpriv->rx_pending_cnt);
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_mac_reg_dump1(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1;
+
+ len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
+
+ for (i = 0x0; i < 0x300; i += 4) {
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_mac_reg_dump2(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1;
+
+ len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
+ memset(page, 0, count);
+ for (i = 0x300; i < 0x600; i += 4) {
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_mac_reg_dump3(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1;
+
+ len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
+
+ for (i = 0x600; i < 0x800; i += 4) {
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_bb_reg_dump1(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1;
+
+ len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
+ for (i = 0x800; i < 0xB00; i += 4) {
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+ *eof = 1;
+ return len;
+}
+
+int proc_get_bb_reg_dump2(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1;
+
+ len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
+ for (i = 0xB00; i < 0xE00; i += 4) {
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+ *eof = 1;
+ return len;
+}
+
+int proc_get_bb_reg_dump3(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1;
+
+ len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
+ for (i = 0xE00; i < 0x1000; i += 4) {
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+ *eof = 1;
+ return len;
+}
+
+int proc_get_rf_reg_dump1(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1, path;
+ u32 value;
+
+ len += snprintf(page + len, count - len, "\n======= RF REG =======\n");
+ path = 1;
+ len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path);
+ for (i = 0; i < 0xC0; i++) {
+ value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x ", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", value);
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+ *eof = 1;
+ return len;
+}
+
+int proc_get_rf_reg_dump2(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1, path;
+ u32 value;
+
+ len += snprintf(page + len, count - len, "\n======= RF REG =======\n");
+ path = 1;
+ len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path);
+ for (i = 0xC0; i < 0x100; i++) {
+ value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x ", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", value);
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+ *eof = 1;
+ return len;
+}
+
+int proc_get_rf_reg_dump3(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1, path;
+ u32 value;
+
+ len += snprintf(page + len, count - len, "\n======= RF REG =======\n");
+ path = 2;
+ len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path);
+ for (i = 0; i < 0xC0; i++) {
+ value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x ", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", value);
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_rf_reg_dump4(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+ int i, j = 1, path;
+ u32 value;
+
+ len += snprintf(page + len, count - len, "\n======= RF REG =======\n");
+ path = 2;
+ len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path);
+ for (i = 0xC0; i < 0x100; i++) {
+ value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
+ if (j % 4 == 1)
+ len += snprintf(page + len, count - len, "0x%02x ", i);
+ len += snprintf(page + len, count - len, " 0x%08x ", value);
+ if ((j++) % 4 == 0)
+ len += snprintf(page + len, count - len, "\n");
+ }
+ *eof = 1;
+ return len;
+}
+
+int proc_get_rx_signal(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+
+ len = snprintf(page + len, count,
+ "rssi:%d\n"
+ "rxpwdb:%d\n"
+ "signal_strength:%u\n"
+ "signal_qual:%u\n"
+ "noise:%u\n",
+ padapter->recvpriv.rssi,
+ padapter->recvpriv.rxpwdb,
+ padapter->recvpriv.signal_strength,
+ padapter->recvpriv.signal_qual,
+ padapter->recvpriv.noise
+ );
+
+ *eof = 1;
+ return len;
+}
+
+int proc_set_rx_signal(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ char tmp[32];
+ u32 is_signal_dbg;
+ s32 signal_strength;
+
+ if (count < 1)
+ return -EFAULT;
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength);
+ is_signal_dbg = is_signal_dbg == 0 ? 0 : 1;
+ if (is_signal_dbg && num != 2)
+ return count;
+
+ signal_strength = signal_strength > 100 ? 100 : signal_strength;
+ signal_strength = signal_strength < 0 ? 0 : signal_strength;
+
+ padapter->recvpriv.is_signal_dbg = is_signal_dbg;
+ padapter->recvpriv.signal_strength_dbg = signal_strength;
+
+ if (is_signal_dbg)
+ DBG_88E("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength);
+ else
+ DBG_88E("set %s\n", "HW_SIGNAL_STRENGTH");
+ }
+ return count;
+}
+
+int proc_get_ht_enable(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ int len = 0;
+
+ if (pregpriv)
+ len += snprintf(page + len, count - len,
+ "%d\n",
+ pregpriv->ht_enable
+ );
+ *eof = 1;
+ return len;
+}
+
+int proc_set_ht_enable(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ char tmp[32];
+ s32 mode = 0;
+
+ if (count < 1)
+ return -EFAULT;
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ if (pregpriv) {
+ pregpriv->ht_enable = mode;
+ pr_info("ht_enable=%d\n", pregpriv->ht_enable);
+ }
+ }
+
+ return count;
+}
+
+int proc_get_cbw40_enable(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+
+ int len = 0;
+
+ if (pregpriv)
+ len += snprintf(page + len, count - len,
+ "%d\n",
+ pregpriv->cbw40_enable
+ );
+
+ *eof = 1;
+ return len;
+}
+
+int proc_set_cbw40_enable(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ char tmp[32];
+ s32 mode = 0;
+
+ if (count < 1)
+ return -EFAULT;
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ if (pregpriv) {
+ pregpriv->cbw40_enable = mode;
+ pr_info("cbw40_enable=%d\n", mode);
+ }
+ }
+ return count;
+}
+
+int proc_get_ampdu_enable(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+
+ int len = 0;
+
+ if (pregpriv)
+ len += snprintf(page + len, count - len,
+ "%d\n",
+ pregpriv->ampdu_enable
+ );
+
+ *eof = 1;
+ return len;
+}
+
+int proc_set_ampdu_enable(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ char tmp[32];
+ s32 mode = 0;
+
+ if (count < 1)
+ return -EFAULT;
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ if (pregpriv) {
+ pregpriv->ampdu_enable = mode;
+ pr_info("ampdu_enable=%d\n", mode);
+ }
+ }
+ return count;
+}
+
+int proc_get_two_path_rssi(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ int len = 0;
+
+ if (padapter)
+ len += snprintf(page + len, count - len,
+ "%d %d\n",
+ padapter->recvpriv.RxRssi[0],
+ padapter->recvpriv.RxRssi[1]
+ );
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_rx_stbc(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+
+ int len = 0;
+
+ if (pregpriv)
+ len += snprintf(page + len, count - len,
+ "%d\n",
+ pregpriv->rx_stbc
+ );
+
+ *eof = 1;
+ return len;
+}
+
+int proc_set_rx_stbc(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ char tmp[32];
+ u32 mode = 0;
+
+ if (count < 1)
+ return -EFAULT;
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ if (pregpriv) {
+ pregpriv->rx_stbc = mode;
+ printk("rx_stbc=%d\n", mode);
+ }
+ }
+ return count;
+}
+
+int proc_get_rssi_disp(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ *eof = 1;
+ return 0;
+}
+
+int proc_set_rssi_disp(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ char tmp[32];
+ u32 enable = 0;
+
+ if (count < 1) {
+ DBG_88E("argument size is less than 1\n");
+ return -EFAULT;
+ }
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ int num = sscanf(tmp, "%x", &enable);
+
+ if (num != 1) {
+ DBG_88E("invalid set_rssi_disp parameter!\n");
+ return count;
+ }
+
+ if (enable) {
+ DBG_88E("Turn On Rx RSSI Display Function\n");
+ padapter->bRxRSSIDisplay = enable;
+ } else {
+ DBG_88E("Turn Off Rx RSSI Display Function\n");
+ padapter->bRxRSSIDisplay = 0;
+ }
+ }
+ return count;
+}
+
+#ifdef CONFIG_88EU_AP_MODE
+
+int proc_get_all_sta_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct sta_info *psta;
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ int i, j;
+ struct list_head *plist, *phead;
+ struct recv_reorder_ctrl *preorder_ctrl;
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
+
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+
+ for (i = 0; i < NUM_STA; i++) {
+ phead = &pstapriv->sta_hash[i];
+ plist = phead->next;
+
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, hash_list);
+
+ plist = plist->next;
+
+ len += snprintf(page + len, count - len, "sta's macaddr: %pM\n", psta->hwaddr);
+ len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
+ len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+ len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
+ len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
+ len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
+ len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+ len += snprintf(page + len, count - len, "sleepq_len=%d\n", psta->sleepq_len);
+ len += snprintf(page + len, count - len, "capability=0x%x\n", psta->capability);
+ len += snprintf(page + len, count - len, "flags=0x%x\n", psta->flags);
+ len += snprintf(page + len, count - len, "wpa_psk=0x%x\n", psta->wpa_psk);
+ len += snprintf(page + len, count - len, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
+ len += snprintf(page + len, count - len, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
+ len += snprintf(page + len, count - len, "qos_info=0x%x\n", psta->qos_info);
+ len += snprintf(page + len, count - len, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
+
+ for (j = 0; j < 16; j++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[j];
+ if (preorder_ctrl->enable)
+ len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq);
+ }
+ }
+ }
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ *eof = 1;
+ return len;
+}
+#endif
+
+int proc_get_best_channel(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ int len = 0;
+ u32 i, best_channel_24G = 1, index_24G = 0;
+
+ for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
+ if (pmlmeext->channel_set[i].ChannelNum == 1)
+ index_24G = i;
+ }
+
+ for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
+ /* 2.4G */
+ if (pmlmeext->channel_set[i].ChannelNum == 6) {
+ if (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_24G].rx_count) {
+ index_24G = i;
+ best_channel_24G = pmlmeext->channel_set[i].ChannelNum;
+ }
+ }
+
+ /* debug */
+ len += snprintf(page + len, count - len, "The rx cnt of channel %3d = %d\n",
+ pmlmeext->channel_set[i].ChannelNum, pmlmeext->channel_set[i].rx_count);
+ }
+
+ len += snprintf(page + len, count - len, "best_channel_24G = %d\n", best_channel_24G);
+
+ *eof = 1;
+ return len;
+}
diff --git a/drivers/staging/r8188eu/core/rtw_efuse.c b/drivers/staging/r8188eu/core/rtw_efuse.c
new file mode 100644
index 000000000000..c1c70648f5bc
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_efuse.c
@@ -0,0 +1,848 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTW_EFUSE_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtw_efuse.h"
+
+/*------------------------Define local variable------------------------------*/
+u8 fakeEfuseBank;
+u32 fakeEfuseUsedBytes;
+u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
+u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
+u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
+
+u32 BTEfuseUsedBytes;
+u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
+u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
+
+u32 fakeBTEfuseUsedBytes;
+u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
+u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
+/*------------------------Define local variable------------------------------*/
+
+/* */
+#define REG_EFUSE_CTRL 0x0030
+#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
+/* */
+static bool Efuse_Read1ByteFromFakeContent(struct adapter *pAdapter,
+ u16 Offset,
+ u8 *Value)
+{
+ if (Offset >= EFUSE_MAX_HW_SIZE)
+ return false;
+ if (fakeEfuseBank == 0)
+ *Value = fakeEfuseContent[Offset];
+ else
+ *Value = fakeBTEfuseContent[fakeEfuseBank - 1][Offset];
+ return true;
+}
+
+static bool
+Efuse_Write1ByteToFakeContent(
+ struct adapter *pAdapter,
+ u16 Offset,
+ u8 Value)
+{
+ if (Offset >= EFUSE_MAX_HW_SIZE)
+ return false;
+ if (fakeEfuseBank == 0) {
+ fakeEfuseContent[Offset] = Value;
+ } else {
+ fakeBTEfuseContent[fakeEfuseBank - 1][Offset] = Value;
+ }
+ return true;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: Efuse_PowerSwitch
+ *
+ * Overview: When we want to enable write operation, we should change to
+ * pwr on state. When we stop write, we should switch to 500k mode
+ * and disable LDO 2.5V.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/17/2008 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+void
+Efuse_PowerSwitch(
+ struct adapter *pAdapter,
+ u8 write,
+ u8 PwrState)
+{
+ pAdapter->HalFunc.EfusePowerSwitch(pAdapter, write, PwrState);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: efuse_GetCurrentSize
+ *
+ * Overview: Get current efuse size!!!
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/16/2008 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+u16
+Efuse_GetCurrentSize(
+ struct adapter *pAdapter,
+ u8 efuseType,
+ bool pseudo)
+{
+ u16 ret = 0;
+
+ ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType, pseudo);
+
+ return ret;
+}
+
+/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
+u8
+Efuse_CalculateWordCnts(u8 word_en)
+{
+ u8 word_cnts = 0;
+ if (!(word_en & BIT(0)))
+ word_cnts++; /* 0 : write enable */
+ if (!(word_en & BIT(1)))
+ word_cnts++;
+ if (!(word_en & BIT(2)))
+ word_cnts++;
+ if (!(word_en & BIT(3)))
+ word_cnts++;
+ return word_cnts;
+}
+
+/* */
+/* Description: */
+/* Execute E-Fuse read byte operation. */
+/* Referred from SD1 Richard. */
+/* */
+/* Assumption: */
+/* 1. Boot from E-Fuse and successfully auto-load. */
+/* 2. PASSIVE_LEVEL (USB interface) */
+/* */
+/* Created by Roger, 2008.10.21. */
+/* */
+void
+ReadEFuseByte(
+ struct adapter *Adapter,
+ u16 _offset,
+ u8 *pbuf,
+ bool pseudo)
+{
+ u32 value32;
+ u8 readbyte;
+ u16 retry;
+
+ if (pseudo) {
+ Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
+ return;
+ }
+
+ /* Write Address */
+ rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
+ readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2);
+ rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
+
+ /* Write bit 32 0 */
+ readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3);
+ rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
+
+ /* Check bit 32 read-ready */
+ retry = 0;
+ value32 = rtw_read32(Adapter, EFUSE_CTRL);
+ while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) {
+ value32 = rtw_read32(Adapter, EFUSE_CTRL);
+ retry++;
+ }
+
+ /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
+ /* This fix the problem that Efuse read error in high temperature condition. */
+ /* Designer says that there shall be some delay after ready bit is set, or the */
+ /* result will always stay on last data we read. */
+ udelay(50);
+ value32 = rtw_read32(Adapter, EFUSE_CTRL);
+
+ *pbuf = (u8)(value32 & 0xff);
+}
+
+/* */
+/* Description: */
+/* 1. Execute E-Fuse read byte operation according as map offset and */
+/* save to E-Fuse table. */
+/* 2. Referred from SD1 Richard. */
+/* */
+/* Assumption: */
+/* 1. Boot from E-Fuse and successfully auto-load. */
+/* 2. PASSIVE_LEVEL (USB interface) */
+/* */
+/* Created by Roger, 2008.10.21. */
+/* */
+/* 2008/12/12 MH 1. Reorganize code flow and reserve bytes. and add description. */
+/* 2. Add efuse utilization collect. */
+/* 2008/12/22 MH Read Efuse must check if we write section 1 data again!!! Sec1 */
+/* write addr must be after sec5. */
+/* */
+
+static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
+{
+ Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
+}
+
+void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
+ )
+{
+ pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, pseudo);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: EFUSE_Read1Byte
+ *
+ * Overview: Copy from WMAC fot EFUSE read 1 byte.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 09/23/2008 MHC Copy from WMAC.
+ *
+ *---------------------------------------------------------------------------*/
+u8 EFUSE_Read1Byte(struct adapter *Adapter, u16 Address)
+{
+ u8 data;
+ u8 Bytetemp = {0x00};
+ u8 temp = {0x00};
+ u32 k = 0;
+ u16 contentLen = 0;
+
+ EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
+
+ if (Address < contentLen) { /* E-fuse 512Byte */
+ /* Write E-fuse Register address bit0~7 */
+ temp = Address & 0xFF;
+ rtw_write8(Adapter, EFUSE_CTRL + 1, temp);
+ Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 2);
+ /* Write E-fuse Register address bit8~9 */
+ temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
+ rtw_write8(Adapter, EFUSE_CTRL + 2, temp);
+
+ /* Write 0x30[31]= 0 */
+ Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
+ temp = Bytetemp & 0x7F;
+ rtw_write8(Adapter, EFUSE_CTRL + 3, temp);
+
+ /* Wait Write-ready (0x30[31]= 1) */
+ Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
+ while (!(Bytetemp & 0x80)) {
+ Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
+ k++;
+ if (k == 1000) {
+ k = 0;
+ break;
+ }
+ }
+ data = rtw_read8(Adapter, EFUSE_CTRL);
+ return data;
+ } else {
+ return 0xFF;
+ }
+
+} /* EFUSE_Read1Byte */
+
+/* 11/16/2008 MH Read one byte from real Efuse. */
+u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
+{
+ u8 tmpidx = 0;
+ u8 result;
+
+ if (pseudo) {
+ result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
+ return result;
+ }
+ /* -----------------e-fuse reg ctrl --------------------------------- */
+ /* address */
+ rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
+ rtw_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
+ (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
+
+ rtw_write8(pAdapter, EFUSE_CTRL + 3, 0x72);/* read cmd */
+
+ while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
+ tmpidx++;
+ if (tmpidx < 100) {
+ *data = rtw_read8(pAdapter, EFUSE_CTRL);
+ result = true;
+ } else {
+ *data = 0xff;
+ result = false;
+ }
+ return result;
+}
+
+/* 11/16/2008 MH Write one byte to reald Efuse. */
+u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
+{
+ u8 tmpidx = 0;
+ u8 result;
+
+ if (pseudo) {
+ result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
+ return result;
+ }
+
+ /* -----------------e-fuse reg ctrl --------------------------------- */
+ /* address */
+ rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
+ rtw_write8(pAdapter, EFUSE_CTRL + 2,
+ (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
+ (u8)((addr >> 8) & 0x03));
+ rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
+
+ rtw_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */
+
+ while ((0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
+ tmpidx++;
+
+ if (tmpidx < 100)
+ result = true;
+ else
+ result = false;
+
+ return result;
+}
+
+int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool pseudo)
+{
+ int ret = 0;
+
+ ret = pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, pseudo);
+
+ return ret;
+}
+
+int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
+{
+ int ret;
+
+ ret = pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
+
+ return ret;
+}
+
+static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
+{
+ int ret;
+
+ ret = pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: efuse_WordEnableDataRead
+ *
+ * Overview: Read allowed word in current efuse section data.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/16/2008 MHC Create Version 0.
+ * 11/21/2008 MHC Fix Write bug when we only enable late word.
+ *
+ *---------------------------------------------------------------------------*/
+void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
+{
+ if (!(word_en & BIT(0))) {
+ targetdata[0] = sourdata[0];
+ targetdata[1] = sourdata[1];
+ }
+ if (!(word_en & BIT(1))) {
+ targetdata[2] = sourdata[2];
+ targetdata[3] = sourdata[3];
+ }
+ if (!(word_en & BIT(2))) {
+ targetdata[4] = sourdata[4];
+ targetdata[5] = sourdata[5];
+ }
+ if (!(word_en & BIT(3))) {
+ targetdata[6] = sourdata[6];
+ targetdata[7] = sourdata[7];
+ }
+}
+
+u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool pseudo)
+{
+ u8 ret = 0;
+
+ ret = pAdapter->HalFunc.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, pseudo);
+
+ return ret;
+}
+
+static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
+{
+ return efuse_OneByteRead(padapter, address, value, false);
+}
+
+static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
+{
+ return efuse_OneByteWrite(padapter, address, *value, false);
+}
+
+/*
+ * read/wirte raw efuse data
+ */
+u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts, u8 *data)
+{
+ int i = 0;
+ u16 real_content_len = 0, max_available_size = 0;
+ u8 res = _FAIL;
+ u8 (*rw8)(struct adapter *, u16, u8*);
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len, false);
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+
+ if (start_addr > real_content_len)
+ return _FAIL;
+
+ if (write) {
+ if ((start_addr + cnts) > max_available_size)
+ return _FAIL;
+ rw8 = &efuse_write8;
+ } else {
+ rw8 = &efuse_read8;
+ }
+
+ Efuse_PowerSwitch(padapter, write, true);
+
+ /* e-fuse one byte read / write */
+ for (i = 0; i < cnts; i++) {
+ if (start_addr >= real_content_len) {
+ res = _FAIL;
+ break;
+ }
+
+ res = rw8(padapter, start_addr++, data++);
+ if (_FAIL == res)
+ break;
+ }
+
+ Efuse_PowerSwitch(padapter, write, false);
+
+ return res;
+}
+/* */
+u16 efuse_GetMaxSize(struct adapter *padapter)
+{
+ u16 max_size;
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size, false);
+ return max_size;
+}
+/* */
+u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
+{
+ Efuse_PowerSwitch(padapter, false, true);
+ *size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, false);
+ Efuse_PowerSwitch(padapter, false, false);
+
+ return _SUCCESS;
+}
+/* */
+u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
+{
+ u16 mapLen = 0;
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+
+ if ((addr + cnts) > mapLen)
+ return _FAIL;
+
+ Efuse_PowerSwitch(padapter, false, true);
+
+ efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+
+ Efuse_PowerSwitch(padapter, false, false);
+
+ return _SUCCESS;
+}
+
+u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
+{
+ u16 mapLen = 0;
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+
+ if ((addr + cnts) > mapLen)
+ return _FAIL;
+
+ Efuse_PowerSwitch(padapter, false, true);
+
+ efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+
+ Efuse_PowerSwitch(padapter, false, false);
+
+ return _SUCCESS;
+}
+/* */
+u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
+{
+ u8 offset, word_en;
+ u8 *map;
+ u8 newdata[PGPKT_DATA_SIZE + 1];
+ s32 i, idx;
+ u8 ret = _SUCCESS;
+ u16 mapLen = 0;
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+
+ if ((addr + cnts) > mapLen)
+ return _FAIL;
+
+ map = kzalloc(mapLen, GFP_KERNEL);
+ if (!map)
+ return _FAIL;
+
+ ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
+ if (ret == _FAIL)
+ goto exit;
+
+ Efuse_PowerSwitch(padapter, true, true);
+
+ offset = (addr >> 3);
+ word_en = 0xF;
+ memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
+ i = addr & 0x7; /* index of one package */
+ idx = 0; /* data index */
+
+ if (i & 0x1) {
+ /* odd start */
+ if (data[idx] != map[addr + idx]) {
+ word_en &= ~BIT(i >> 1);
+ newdata[i - 1] = map[addr + idx - 1];
+ newdata[i] = data[idx];
+ }
+ i++;
+ idx++;
+ }
+ do {
+ for (; i < PGPKT_DATA_SIZE; i += 2) {
+ if (cnts == idx)
+ break;
+ if ((cnts - idx) == 1) {
+ if (data[idx] != map[addr + idx]) {
+ word_en &= ~BIT(i >> 1);
+ newdata[i] = data[idx];
+ newdata[i + 1] = map[addr + idx + 1];
+ }
+ idx++;
+ break;
+ } else {
+ if ((data[idx] != map[addr + idx]) ||
+ (data[idx + 1] != map[addr + idx + 1])) {
+ word_en &= ~BIT(i >> 1);
+ newdata[i] = data[idx];
+ newdata[i + 1] = data[idx + 1];
+ }
+ idx += 2;
+ }
+ if (idx == cnts)
+ break;
+ }
+
+ if (word_en != 0xF) {
+ ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
+ DBG_88E("offset=%x\n", offset);
+ DBG_88E("word_en=%x\n", word_en);
+
+ for (i = 0; i < PGPKT_DATA_SIZE; i++)
+ DBG_88E("data=%x \t", newdata[i]);
+ if (ret == _FAIL)
+ break;
+ }
+
+ if (idx == cnts)
+ break;
+
+ offset++;
+ i = 0;
+ word_en = 0xF;
+ memset(newdata, 0xFF, PGPKT_DATA_SIZE);
+ } while (1);
+
+ Efuse_PowerSwitch(padapter, true, false);
+exit:
+ kfree(map);
+ return ret;
+}
+
+/* */
+u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
+{
+ u8 offset, word_en;
+ u8 *map;
+ u8 newdata[PGPKT_DATA_SIZE + 1];
+ s32 i, idx;
+ u8 ret = _SUCCESS;
+ u16 mapLen = 0;
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+
+ if ((addr + cnts) > mapLen)
+ return _FAIL;
+
+ map = kzalloc(mapLen, GFP_KERNEL);
+ if (!map)
+ return _FAIL;
+
+ ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
+ if (ret == _FAIL)
+ goto exit;
+
+ Efuse_PowerSwitch(padapter, true, true);
+
+ offset = (addr >> 3);
+ word_en = 0xF;
+ memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
+ i = addr & 0x7; /* index of one package */
+ idx = 0; /* data index */
+
+ if (i & 0x1) {
+ /* odd start */
+ if (data[idx] != map[addr + idx]) {
+ word_en &= ~BIT(i >> 1);
+ newdata[i - 1] = map[addr + idx - 1];
+ newdata[i] = data[idx];
+ }
+ i++;
+ idx++;
+ }
+ do {
+ for (; i < PGPKT_DATA_SIZE; i += 2) {
+ if (cnts == idx)
+ break;
+ if ((cnts - idx) == 1) {
+ if (data[idx] != map[addr + idx]) {
+ word_en &= ~BIT(i >> 1);
+ newdata[i] = data[idx];
+ newdata[i + 1] = map[addr + idx + 1];
+ }
+ idx++;
+ break;
+ } else {
+ if ((data[idx] != map[addr + idx]) ||
+ (data[idx + 1] != map[addr + idx + 1])) {
+ word_en &= ~BIT(i >> 1);
+ newdata[i] = data[idx];
+ newdata[i + 1] = data[idx + 1];
+ }
+ idx += 2;
+ }
+ if (idx == cnts)
+ break;
+ }
+
+ if (word_en != 0xF) {
+ DBG_88E("%s: offset=%#X\n", __func__, offset);
+ DBG_88E("%s: word_en=%#X\n", __func__, word_en);
+ DBG_88E("%s: data=", __func__);
+ for (i = 0; i < PGPKT_DATA_SIZE; i++)
+ DBG_88E("0x%02X ", newdata[i]);
+ DBG_88E("\n");
+
+ ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
+ if (ret == _FAIL)
+ break;
+ }
+
+ if (idx == cnts)
+ break;
+
+ offset++;
+ i = 0;
+ word_en = 0xF;
+ memset(newdata, 0xFF, PGPKT_DATA_SIZE);
+ } while (1);
+
+ Efuse_PowerSwitch(padapter, true, false);
+
+exit:
+
+ kfree(map);
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: efuse_ShadowRead1Byte
+ * efuse_ShadowRead2Byte
+ * efuse_ShadowRead4Byte
+ *
+ * Overview: Read from efuse init map by one/two/four bytes !!!!!
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/12/2008 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+static void
+efuse_ShadowRead1Byte(
+ struct adapter *pAdapter,
+ u16 Offset,
+ u8 *Value)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
+
+ *Value = pEEPROM->efuse_eeprom_data[Offset];
+
+} /* EFUSE_ShadowRead1Byte */
+
+/* Read Two Bytes */
+static void
+efuse_ShadowRead2Byte(
+ struct adapter *pAdapter,
+ u16 Offset,
+ u16 *Value)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
+
+ *Value = pEEPROM->efuse_eeprom_data[Offset];
+ *Value |= pEEPROM->efuse_eeprom_data[Offset + 1] << 8;
+
+} /* EFUSE_ShadowRead2Byte */
+
+/* Read Four Bytes */
+static void
+efuse_ShadowRead4Byte(
+ struct adapter *pAdapter,
+ u16 Offset,
+ u32 *Value)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
+
+ *Value = pEEPROM->efuse_eeprom_data[Offset];
+ *Value |= pEEPROM->efuse_eeprom_data[Offset + 1] << 8;
+ *Value |= pEEPROM->efuse_eeprom_data[Offset + 2] << 16;
+ *Value |= pEEPROM->efuse_eeprom_data[Offset + 3] << 24;
+
+} /* efuse_ShadowRead4Byte */
+
+/*-----------------------------------------------------------------------------
+ * Function: Efuse_ReadAllMap
+ *
+ * Overview: Read All Efuse content
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/11/2008 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
+{
+ u16 mapLen = 0;
+
+ Efuse_PowerSwitch(pAdapter, false, true);
+
+ EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
+
+ efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+
+ Efuse_PowerSwitch(pAdapter, false, false);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: EFUSE_ShadowMapUpdate
+ *
+ * Overview: Transfer current EFUSE content to shadow init and modify map.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/13/2008 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+void EFUSE_ShadowMapUpdate(
+ struct adapter *pAdapter,
+ u8 efuseType,
+ bool pseudo)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
+ u16 mapLen = 0;
+
+ EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
+
+ if (pEEPROM->bautoload_fail_flag)
+ memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
+ else
+ Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
+} /* EFUSE_ShadowMapUpdate */
+
+/*-----------------------------------------------------------------------------
+ * Function: EFUSE_ShadowRead
+ *
+ * Overview: Read from efuse init map !!!!!
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/12/2008 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
+{
+ if (Type == 1)
+ efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
+ else if (Type == 2)
+ efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
+ else if (Type == 4)
+ efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
+
+} /* EFUSE_ShadowRead */
diff --git a/drivers/staging/r8188eu/core/rtw_ieee80211.c b/drivers/staging/r8188eu/core/rtw_ieee80211.c
new file mode 100644
index 000000000000..b3a74198596a
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_ieee80211.c
@@ -0,0 +1,1539 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _IEEE80211_C
+
+#include "../include/drv_types.h"
+#include "../include/ieee80211.h"
+#include "../include/wifi.h"
+#include "../include/osdep_service.h"
+#include "../include/wlan_bssdef.h"
+#include "../include/usb_osintf.h"
+
+u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
+u16 RTW_WPA_VERSION = 1;
+u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
+u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
+u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
+u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
+u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
+u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
+u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
+u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
+u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
+
+u16 RSN_VERSION_BSD = 1;
+u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
+u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
+u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
+u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
+u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
+u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
+u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
+u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
+/* */
+/* for adhoc-master to generate ie and provide supported-rate to fw */
+/* */
+
+static u8 WIFI_CCKRATES[] = {
+ (IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
+ (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
+ (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
+ (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)
+ };
+
+static u8 WIFI_OFDMRATES[] = {
+ (IEEE80211_OFDM_RATE_6MB),
+ (IEEE80211_OFDM_RATE_9MB),
+ (IEEE80211_OFDM_RATE_12MB),
+ (IEEE80211_OFDM_RATE_18MB),
+ (IEEE80211_OFDM_RATE_24MB),
+ IEEE80211_OFDM_RATE_36MB,
+ IEEE80211_OFDM_RATE_48MB,
+ IEEE80211_OFDM_RATE_54MB
+ };
+
+int rtw_get_bit_value_from_ieee_value(u8 val)
+{
+ unsigned char dot11_rate_table[] = {
+ 2, 4, 11, 22, 12, 18, 24, 36, 48,
+ 72, 96, 108, 0}; /* last element must be zero!! */
+
+ int i = 0;
+ while (dot11_rate_table[i] != 0) {
+ if (dot11_rate_table[i] == val)
+ return BIT(i);
+ i++;
+ }
+ return 0;
+}
+
+uint rtw_is_cckrates_included(u8 *rate)
+{
+ u32 i = 0;
+
+ while (rate[i] != 0) {
+ if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
+ (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
+ return true;
+ i++;
+ }
+ return false;
+}
+
+uint rtw_is_cckratesonly_included(u8 *rate)
+{
+ u32 i = 0;
+
+ while (rate[i] != 0) {
+ if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
+ (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
+ return false;
+ i++;
+ }
+
+ return true;
+}
+
+int rtw_check_network_type(unsigned char *rate, int ratelen, int channel)
+{
+ if (channel > 14) {
+ return WIRELESS_INVALID;
+ } else { /* could be pure B, pure G, or B/G */
+ if (rtw_is_cckratesonly_included(rate))
+ return WIRELESS_11B;
+ else if (rtw_is_cckrates_included(rate))
+ return WIRELESS_11BG;
+ else
+ return WIRELESS_11G;
+ }
+}
+
+u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source,
+ unsigned int *frlen)
+{
+ memcpy((void *)pbuf, (void *)source, len);
+ *frlen = *frlen + len;
+ return pbuf + len;
+}
+
+/* rtw_set_ie will update frame length */
+u8 *rtw_set_ie
+(
+ u8 *pbuf,
+ int index,
+ uint len,
+ u8 *source,
+ uint *frlen /* frame length */
+)
+{
+
+ *pbuf = (u8)index;
+
+ *(pbuf + 1) = (u8)len;
+
+ if (len > 0)
+ memcpy((void *)(pbuf + 2), (void *)source, len);
+
+ *frlen = *frlen + (len + 2);
+
+ return pbuf + len + 2;
+}
+
+inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode,
+ u8 new_ch, u8 ch_switch_cnt)
+{
+ u8 ie_data[3];
+
+ ie_data[0] = ch_switch_mode;
+ ie_data[1] = new_ch;
+ ie_data[2] = ch_switch_cnt;
+ return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len);
+}
+
+inline u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset)
+{
+ if (ch_offset == SCN)
+ return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ else if (ch_offset == SCA)
+ return HAL_PRIME_CHNL_OFFSET_UPPER;
+ else if (ch_offset == SCB)
+ return HAL_PRIME_CHNL_OFFSET_LOWER;
+
+ return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+}
+
+inline u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset)
+{
+ if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
+ return SCN;
+ else if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
+ return SCB;
+ else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
+ return SCA;
+
+ return SCN;
+}
+
+inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset)
+{
+ return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len);
+}
+
+inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl,
+ u8 flags, u16 reason, u16 precedence)
+{
+ u8 ie_data[6];
+
+ ie_data[0] = ttl;
+ ie_data[1] = flags;
+ *(u16 *)(ie_data + 2) = cpu_to_le16(reason);
+ *(u16 *)(ie_data + 4) = cpu_to_le16(precedence);
+
+ return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len);
+}
+
+/*----------------------------------------------------------------------------
+index: the information element id index, limit is the limit for search
+-----------------------------------------------------------------------------*/
+u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit)
+{
+ int tmp, i;
+ u8 *p;
+
+ if (limit < 1) {
+
+ return NULL;
+ }
+
+ p = pbuf;
+ i = 0;
+ *len = 0;
+ while (1) {
+ if (*p == index) {
+ *len = *(p + 1);
+ return p;
+ } else {
+ tmp = *(p + 1);
+ p += (tmp + 2);
+ i += (tmp + 2);
+ }
+ if (i >= limit)
+ break;
+ }
+
+ return NULL;
+}
+
+/**
+ * rtw_get_ie_ex - Search specific IE from a series of IEs
+ * @in_ie: Address of IEs to search
+ * @in_len: Length limit from in_ie
+ * @eid: Element ID to match
+ * @oui: OUI to match
+ * @oui_len: OUI length
+ * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE
+ * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE
+ *
+ * Returns: The address of the specific IE found, or NULL
+ */
+u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen)
+{
+ uint cnt;
+ u8 *target_ie = NULL;
+
+ if (ielen)
+ *ielen = 0;
+
+ if (!in_ie || in_len <= 0)
+ return target_ie;
+
+ cnt = 0;
+
+ while (cnt < in_len) {
+ if (eid == in_ie[cnt] && (!oui || !memcmp(&in_ie[cnt + 2], oui, oui_len))) {
+ target_ie = &in_ie[cnt];
+
+ if (ie)
+ memcpy(ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+ if (ielen)
+ *ielen = in_ie[cnt + 1] + 2;
+
+ break;
+ } else {
+ cnt += in_ie[cnt + 1] + 2; /* goto next */
+ }
+ }
+ return target_ie;
+}
+
+/**
+ * rtw_ies_remove_ie - Find matching IEs and remove
+ * @ies: Address of IEs to search
+ * @ies_len: Pointer of length of ies, will update to new length
+ * @offset: The offset to start scarch
+ * @eid: Element ID to match
+ * @oui: OUI to match
+ * @oui_len: OUI length
+ *
+ * Returns: _SUCCESS: ies is updated, _FAIL: not updated
+ */
+int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len)
+{
+ int ret = _FAIL;
+ u8 *target_ie;
+ u32 target_ielen;
+ u8 *start;
+ uint search_len;
+
+ if (!ies || !ies_len || *ies_len <= offset)
+ goto exit;
+
+ start = ies + offset;
+ search_len = *ies_len - offset;
+
+ while (1) {
+ target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen);
+ if (target_ie && target_ielen) {
+ u8 buf[MAX_IE_SZ] = {0};
+ u8 *remain_ies = target_ie + target_ielen;
+ uint remain_len = search_len - (remain_ies - start);
+
+ memcpy(buf, remain_ies, remain_len);
+ memcpy(target_ie, buf, remain_len);
+ *ies_len = *ies_len - target_ielen;
+ ret = _SUCCESS;
+
+ start = target_ie;
+ search_len = remain_len;
+ } else {
+ break;
+ }
+ }
+exit:
+ return ret;
+}
+
+void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
+{
+
+ memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+
+ switch (mode) {
+ case WIRELESS_11B:
+ memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+ break;
+ case WIRELESS_11G:
+ memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
+ break;
+ case WIRELESS_11BG:
+ case WIRELESS_11G_24N:
+ case WIRELESS_11_24N:
+ case WIRELESS_11BG_24N:
+ memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+ memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
+ break;
+ }
+
+}
+
+uint rtw_get_rateset_len(u8 *rateset)
+{
+ uint i = 0;
+
+ while (1) {
+ if ((rateset[i]) == 0)
+ break;
+ if (i > 12)
+ break;
+ i++;
+ }
+
+ return i;
+}
+
+int rtw_generate_ie(struct registry_priv *pregistrypriv)
+{
+ u8 wireless_mode;
+ int sz = 0, rateLen;
+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
+ u8 *ie = pdev_network->IEs;
+
+ /* timestamp will be inserted by hardware */
+ sz += 8;
+ ie += sz;
+
+ /* beacon interval : 2bytes */
+ *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */
+ sz += 2;
+ ie += 2;
+
+ /* capability info */
+ *(u16 *)ie = 0;
+
+ *(__le16 *)ie |= cpu_to_le16(cap_IBSS);
+
+ if (pregistrypriv->preamble == PREAMBLE_SHORT)
+ *(__le16 *)ie |= cpu_to_le16(cap_ShortPremble);
+
+ if (pdev_network->Privacy)
+ *(__le16 *)ie |= cpu_to_le16(cap_Privacy);
+
+ sz += 2;
+ ie += 2;
+
+ /* SSID */
+ ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz);
+
+ /* supported rates */
+ wireless_mode = pregistrypriv->wireless_mode;
+
+ rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode);
+
+ rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
+
+ if (rateLen > 8) {
+ ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz);
+ /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
+ } else {
+ ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz);
+ }
+
+ /* DS parameter set */
+ ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&pdev_network->Configuration.DSConfig, &sz);
+
+ /* IBSS Parameter Set */
+
+ ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&pdev_network->Configuration.ATIMWindow, &sz);
+
+ if (rateLen > 8)
+ ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
+
+ return sz;
+}
+
+unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit)
+{
+ int len;
+ u16 val16;
+ __le16 le_tmp;
+ unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
+ u8 *pbuf = pie;
+ int limit_new = limit;
+
+ while (1) {
+ pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new);
+
+ if (pbuf) {
+ /* check if oui matches... */
+ if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type)))
+ goto check_next_ie;
+
+ /* check version... */
+ memcpy((u8 *)&le_tmp, (pbuf + 6), sizeof(val16));
+
+ val16 = le16_to_cpu(le_tmp);
+ if (val16 != 0x0001)
+ goto check_next_ie;
+ *wpa_ie_len = *(pbuf + 1);
+ return pbuf;
+ } else {
+ *wpa_ie_len = 0;
+ return NULL;
+ }
+
+check_next_ie:
+ limit_new = limit - (pbuf - pie) - 2 - len;
+ if (limit_new <= 0)
+ break;
+ pbuf += (2 + len);
+ }
+ *wpa_ie_len = 0;
+ return NULL;
+}
+
+unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit)
+{
+
+ return rtw_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
+}
+
+int rtw_get_wpa_cipher_suite(u8 *s)
+{
+ if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_NONE;
+ if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_WEP40;
+ if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_TKIP;
+ if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_CCMP;
+ if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_WEP104;
+
+ return 0;
+}
+
+int rtw_get_wpa2_cipher_suite(u8 *s)
+{
+ if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_NONE;
+ if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_WEP40;
+ if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_TKIP;
+ if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_CCMP;
+ if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_WEP104;
+
+ return 0;
+}
+
+int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
+{
+ int i, ret = _SUCCESS;
+ int left, count;
+ u8 *pos;
+ u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
+
+ if (wpa_ie_len <= 0) {
+ /* No WPA IE - fail silently */
+ return _FAIL;
+ }
+
+ if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) ||
+ (memcmp(wpa_ie + 2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN)))
+ return _FAIL;
+
+ pos = wpa_ie;
+
+ pos += 8;
+ left = wpa_ie_len - 8;
+
+ /* group_cipher */
+ if (left >= WPA_SELECTOR_LEN) {
+ *group_cipher = rtw_get_wpa_cipher_suite(pos);
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ } else if (left > 0) {
+ return _FAIL;
+ }
+
+ /* pairwise_cipher */
+ if (left >= 2) {
+ count = get_unaligned_le16(pos);
+ pos += 2;
+ left -= 2;
+
+ if (count == 0 || left < count * WPA_SELECTOR_LEN)
+ return _FAIL;
+
+ for (i = 0; i < count; i++) {
+ *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
+
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ }
+ } else if (left == 1) {
+ return _FAIL;
+ }
+
+ if (is_8021x) {
+ if (left >= 6) {
+ pos += 2;
+ if (!memcmp(pos, SUITE_1X, 4))
+ *is_8021x = 1;
+ }
+ }
+
+ return ret;
+}
+
+int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
+{
+ int i, ret = _SUCCESS;
+ int left, count;
+ u8 *pos;
+ u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
+
+ if (rsn_ie_len <= 0) {
+ /* No RSN IE - fail silently */
+ return _FAIL;
+ }
+
+ if ((*rsn_ie != _WPA2_IE_ID_) || (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2)))
+ return _FAIL;
+
+ pos = rsn_ie;
+ pos += 4;
+ left = rsn_ie_len - 4;
+
+ /* group_cipher */
+ if (left >= RSN_SELECTOR_LEN) {
+ *group_cipher = rtw_get_wpa2_cipher_suite(pos);
+
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+
+ } else if (left > 0) {
+ return _FAIL;
+ }
+
+ /* pairwise_cipher */
+ if (left >= 2) {
+ count = get_unaligned_le16(pos);
+ pos += 2;
+ left -= 2;
+
+ if (count == 0 || left < count * RSN_SELECTOR_LEN)
+ return _FAIL;
+
+ for (i = 0; i < count; i++) {
+ *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
+
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+ }
+
+ } else if (left == 1) {
+ return _FAIL;
+ }
+
+ if (is_8021x) {
+ if (left >= 6) {
+ pos += 2;
+ if (!memcmp(pos, SUITE_1X, 4))
+ *is_8021x = 1;
+ }
+ }
+ return ret;
+}
+
+int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len)
+{
+ u8 authmode;
+ u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
+ uint cnt;
+
+ /* Search required WPA or WPA2 IE and copy to sec_ie[] */
+
+ cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
+
+ while (cnt < in_len) {
+ authmode = in_ie[cnt];
+
+ if ((authmode == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
+ if (wpa_ie)
+ memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+ *wpa_len = in_ie[cnt + 1] + 2;
+ cnt += in_ie[cnt + 1] + 2; /* get next */
+ } else {
+ if (authmode == _WPA2_IE_ID_) {
+ if (rsn_ie)
+ memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+ *rsn_len = in_ie[cnt + 1] + 2;
+ cnt += in_ie[cnt + 1] + 2; /* get next */
+ } else {
+ cnt += in_ie[cnt + 1] + 2; /* get next */
+ }
+ }
+ }
+
+ return *rsn_len + *wpa_len;
+}
+
+u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
+{
+ u8 match = false;
+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ if (!ie_ptr)
+ return match;
+
+ eid = ie_ptr[0];
+
+ if ((eid == _WPA_IE_ID_) && (!memcmp(&ie_ptr[2], wps_oui, 4))) {
+ *wps_ielen = ie_ptr[1] + 2;
+ match = true;
+ }
+ return match;
+}
+
+/**
+ * rtw_get_wps_ie - Search WPS IE from a series of IEs
+ * @in_ie: Address of IEs to search
+ * @in_len: Length limit from in_ie
+ * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
+ * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
+ *
+ * Returns: The address of the WPS IE found, or NULL
+ */
+u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
+{
+ uint cnt;
+ u8 *wpsie_ptr = NULL;
+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ if (wps_ielen)
+ *wps_ielen = 0;
+
+ if (!in_ie || in_len <= 0)
+ return wpsie_ptr;
+
+ cnt = 0;
+
+ while (cnt < in_len) {
+ eid = in_ie[cnt];
+
+ if ((eid == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
+ wpsie_ptr = &in_ie[cnt];
+
+ if (wps_ie)
+ memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+ if (wps_ielen)
+ *wps_ielen = in_ie[cnt + 1] + 2;
+
+ cnt += in_ie[cnt + 1] + 2;
+
+ break;
+ } else {
+ cnt += in_ie[cnt + 1] + 2; /* goto next */
+ }
+ }
+ return wpsie_ptr;
+}
+
+/**
+ * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
+ * @wps_ie: Address of WPS IE to search
+ * @wps_ielen: Length limit from wps_ie
+ * @target_attr_id: The attribute ID of WPS attribute to search
+ * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
+ * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
+ *
+ * Returns: the address of the specific WPS attribute found, or NULL
+ */
+u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr)
+{
+ u8 *attr_ptr = NULL;
+ u8 *target_attr_ptr = NULL;
+ u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
+
+ if (len_attr)
+ *len_attr = 0;
+
+ if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
+ (memcmp(wps_ie + 2, wps_oui, 4)))
+ return attr_ptr;
+
+ /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
+ attr_ptr = wps_ie + 6; /* goto first attr */
+
+ while (attr_ptr - wps_ie < wps_ielen) {
+ /* 4 = 2(Attribute ID) + 2(Length) */
+ u16 attr_id = RTW_GET_BE16(attr_ptr);
+ u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2);
+ u16 attr_len = attr_data_len + 4;
+
+ if (attr_id == target_attr_id) {
+ target_attr_ptr = attr_ptr;
+ if (buf_attr)
+ memcpy(buf_attr, attr_ptr, attr_len);
+ if (len_attr)
+ *len_attr = attr_len;
+ break;
+ } else {
+ attr_ptr += attr_len; /* goto next */
+ }
+ }
+ return target_attr_ptr;
+}
+
+/**
+ * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
+ * @wps_ie: Address of WPS IE to search
+ * @wps_ielen: Length limit from wps_ie
+ * @target_attr_id: The attribute ID of WPS attribute to search
+ * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
+ * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
+ *
+ * Returns: the address of the specific WPS attribute content found, or NULL
+ */
+u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content)
+{
+ u8 *attr_ptr;
+ u32 attr_len;
+
+ if (len_content)
+ *len_content = 0;
+
+ attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
+
+ if (attr_ptr && attr_len) {
+ if (buf_content)
+ memcpy(buf_content, attr_ptr + 4, attr_len - 4);
+
+ if (len_content)
+ *len_content = attr_len - 4;
+
+ return attr_ptr + 4;
+ }
+
+ return NULL;
+}
+
+static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
+ struct rtw_ieee802_11_elems *elems,
+ int show_errors)
+{
+ unsigned int oui;
+
+ /* first 3 bytes in vendor specific information element are the IEEE
+ * OUI of the vendor. The following byte is used a vendor specific
+ * sub-type. */
+ if (elen < 4) {
+ if (show_errors) {
+ DBG_88E("short vendor specific information element ignored (len=%lu)\n",
+ (unsigned long)elen);
+ }
+ return -1;
+ }
+
+ oui = RTW_GET_BE24(pos);
+ switch (oui) {
+ case OUI_MICROSOFT:
+ /* Microsoft/Wi-Fi information elements are further typed and
+ * subtyped */
+ switch (pos[3]) {
+ case 1:
+ /* Microsoft OUI (00:50:F2) with OUI Type 1:
+ * real WPA information element */
+ elems->wpa_ie = pos;
+ elems->wpa_ie_len = elen;
+ break;
+ case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
+ if (elen < 5) {
+ DBG_88E("short WME information element ignored (len=%lu)\n",
+ (unsigned long)elen);
+ return -1;
+ }
+ switch (pos[4]) {
+ case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
+ case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
+ elems->wme = pos;
+ elems->wme_len = elen;
+ break;
+ case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
+ elems->wme_tspec = pos;
+ elems->wme_tspec_len = elen;
+ break;
+ default:
+ DBG_88E("unknown WME information element ignored (subtype=%d len=%lu)\n",
+ pos[4], (unsigned long)elen);
+ return -1;
+ }
+ break;
+ case 4:
+ /* Wi-Fi Protected Setup (WPS) IE */
+ elems->wps_ie = pos;
+ elems->wps_ie_len = elen;
+ break;
+ default:
+ DBG_88E("Unknown Microsoft information element ignored (type=%d len=%lu)\n",
+ pos[3], (unsigned long)elen);
+ return -1;
+ }
+ break;
+
+ case OUI_BROADCOM:
+ switch (pos[3]) {
+ case VENDOR_HT_CAPAB_OUI_TYPE:
+ elems->vendor_ht_cap = pos;
+ elems->vendor_ht_cap_len = elen;
+ break;
+ default:
+ DBG_88E("Unknown Broadcom information element ignored (type=%d len=%lu)\n",
+ pos[3], (unsigned long)elen);
+ return -1;
+ }
+ break;
+ default:
+ DBG_88E("unknown vendor specific information element ignored (vendor OUI %02x:%02x:%02x len=%lu)\n",
+ pos[0], pos[1], pos[2], (unsigned long)elen);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * ieee802_11_parse_elems - Parse information elements in management frames
+ * @start: Pointer to the start of IEs
+ * @len: Length of IE buffer in octets
+ * @elems: Data structure for parsed elements
+ * @show_errors: Whether to show parsing errors in debug log
+ * Returns: Parsing result
+ */
+enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len,
+ struct rtw_ieee802_11_elems *elems,
+ int show_errors)
+{
+ uint left = len;
+ u8 *pos = start;
+ int unknown = 0;
+
+ memset(elems, 0, sizeof(*elems));
+
+ while (left >= 2) {
+ u8 id, elen;
+
+ id = *pos++;
+ elen = *pos++;
+ left -= 2;
+
+ if (elen > left) {
+ if (show_errors) {
+ DBG_88E("IEEE 802.11 element parse failed (id=%d elen=%d left=%lu)\n",
+ id, elen, (unsigned long)left);
+ }
+ return ParseFailed;
+ }
+
+ switch (id) {
+ case WLAN_EID_SSID:
+ elems->ssid = pos;
+ elems->ssid_len = elen;
+ break;
+ case WLAN_EID_SUPP_RATES:
+ elems->supp_rates = pos;
+ elems->supp_rates_len = elen;
+ break;
+ case WLAN_EID_FH_PARAMS:
+ elems->fh_params = pos;
+ elems->fh_params_len = elen;
+ break;
+ case WLAN_EID_DS_PARAMS:
+ elems->ds_params = pos;
+ elems->ds_params_len = elen;
+ break;
+ case WLAN_EID_CF_PARAMS:
+ elems->cf_params = pos;
+ elems->cf_params_len = elen;
+ break;
+ case WLAN_EID_TIM:
+ elems->tim = pos;
+ elems->tim_len = elen;
+ break;
+ case WLAN_EID_IBSS_PARAMS:
+ elems->ibss_params = pos;
+ elems->ibss_params_len = elen;
+ break;
+ case WLAN_EID_CHALLENGE:
+ elems->challenge = pos;
+ elems->challenge_len = elen;
+ break;
+ case WLAN_EID_ERP_INFO:
+ elems->erp_info = pos;
+ elems->erp_info_len = elen;
+ break;
+ case WLAN_EID_EXT_SUPP_RATES:
+ elems->ext_supp_rates = pos;
+ elems->ext_supp_rates_len = elen;
+ break;
+ case WLAN_EID_VENDOR_SPECIFIC:
+ if (rtw_ieee802_11_parse_vendor_specific(pos, elen, elems, show_errors))
+ unknown++;
+ break;
+ case WLAN_EID_RSN:
+ elems->rsn_ie = pos;
+ elems->rsn_ie_len = elen;
+ break;
+ case WLAN_EID_PWR_CAPABILITY:
+ elems->power_cap = pos;
+ elems->power_cap_len = elen;
+ break;
+ case WLAN_EID_SUPPORTED_CHANNELS:
+ elems->supp_channels = pos;
+ elems->supp_channels_len = elen;
+ break;
+ case WLAN_EID_MOBILITY_DOMAIN:
+ elems->mdie = pos;
+ elems->mdie_len = elen;
+ break;
+ case WLAN_EID_FAST_BSS_TRANSITION:
+ elems->ftie = pos;
+ elems->ftie_len = elen;
+ break;
+ case WLAN_EID_TIMEOUT_INTERVAL:
+ elems->timeout_int = pos;
+ elems->timeout_int_len = elen;
+ break;
+ case WLAN_EID_HT_CAP:
+ elems->ht_capabilities = pos;
+ elems->ht_capabilities_len = elen;
+ break;
+ case WLAN_EID_HT_OPERATION:
+ elems->ht_operation = pos;
+ elems->ht_operation_len = elen;
+ break;
+ default:
+ unknown++;
+ if (!show_errors)
+ break;
+ DBG_88E("IEEE 802.11 element parse ignored unknown element (id=%d elen=%d)\n",
+ id, elen);
+ break;
+ }
+ left -= elen;
+ pos += elen;
+ }
+ if (left)
+ return ParseFailed;
+ return unknown ? ParseUnknown : ParseOK;
+}
+
+u8 key_char2num(u8 ch)
+{
+ if ((ch >= '0') && (ch <= '9'))
+ return ch - '0';
+ else if ((ch >= 'a') && (ch <= 'f'))
+ return ch - 'a' + 10;
+ else if ((ch >= 'A') && (ch <= 'F'))
+ return ch - 'A' + 10;
+ else
+ return 0xff;
+}
+
+u8 str_2char2num(u8 hch, u8 lch)
+{
+ return (key_char2num(hch) * 10) + key_char2num(lch);
+}
+
+u8 key_2char2num(u8 hch, u8 lch)
+{
+ return (key_char2num(hch) << 4) | key_char2num(lch);
+}
+
+void rtw_macaddr_cfg(u8 *mac_addr)
+{
+ u8 mac[ETH_ALEN];
+ if (!mac_addr)
+ return;
+
+ if (rtw_initmac) { /* Users specify the mac address */
+ int jj, kk;
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ mac[jj] = key_2char2num(rtw_initmac[kk], rtw_initmac[kk + 1]);
+ memcpy(mac_addr, mac, ETH_ALEN);
+ } else { /* Use the mac address stored in the Efuse */
+ memcpy(mac, mac_addr, ETH_ALEN);
+ }
+
+ if (((mac[0] == 0xff) && (mac[1] == 0xff) && (mac[2] == 0xff) &&
+ (mac[3] == 0xff) && (mac[4] == 0xff) && (mac[5] == 0xff)) ||
+ ((mac[0] == 0x0) && (mac[1] == 0x0) && (mac[2] == 0x0) &&
+ (mac[3] == 0x0) && (mac[4] == 0x0) && (mac[5] == 0x0))) {
+ mac[0] = 0x00;
+ mac[1] = 0xe0;
+ mac[2] = 0x4c;
+ mac[3] = 0x87;
+ mac[4] = 0x00;
+ mac[5] = 0x00;
+ /* use default mac addresss */
+ memcpy(mac_addr, mac, ETH_ALEN);
+ DBG_88E("MAC Address from efuse error, assign default one !!!\n");
+ }
+
+ DBG_88E("rtw_macaddr_cfg MAC Address = %pM\n", (mac_addr));
+}
+
+void dump_ies(u8 *buf, u32 buf_len)
+{
+ u8 *pos = (u8 *)buf;
+ u8 id, len;
+
+ while (pos - buf <= buf_len) {
+ id = *pos;
+ len = *(pos + 1);
+
+ DBG_88E("%s ID:%u, LEN:%u\n", __func__, id, len);
+ #ifdef CONFIG_88EU_P2P
+ dump_p2p_ie(pos, len);
+ #endif
+ dump_wps_ie(pos, len);
+
+ pos += (2 + len);
+ }
+}
+
+void dump_wps_ie(u8 *ie, u32 ie_len)
+{
+ u8 *pos = (u8 *)ie;
+ u16 id;
+ u16 len;
+ u8 *wps_ie;
+ uint wps_ielen;
+
+ wps_ie = rtw_get_wps_ie(ie, ie_len, NULL, &wps_ielen);
+ if (wps_ie != ie || wps_ielen == 0)
+ return;
+
+ pos += 6;
+ while (pos - ie < ie_len) {
+ id = RTW_GET_BE16(pos);
+ len = RTW_GET_BE16(pos + 2);
+ DBG_88E("%s ID:0x%04x, LEN:%u\n", __func__, id, len);
+ pos += (4 + len);
+ }
+}
+
+#ifdef CONFIG_88EU_P2P
+void dump_p2p_ie(u8 *ie, u32 ie_len)
+{
+ u8 *pos = (u8 *)ie;
+ u8 id;
+ u16 len;
+ u8 *p2p_ie;
+ uint p2p_ielen;
+
+ p2p_ie = rtw_get_p2p_ie(ie, ie_len, NULL, &p2p_ielen);
+ if (p2p_ie != ie || p2p_ielen == 0)
+ return;
+
+ pos += 6;
+ while (pos - ie < ie_len) {
+ id = *pos;
+ len = get_unaligned_le16(pos + 1);
+ DBG_88E("%s ID:%u, LEN:%u\n", __func__, id, len);
+ pos += (3 + len);
+ }
+}
+
+/**
+ * rtw_get_p2p_ie - Search P2P IE from a series of IEs
+ * @in_ie: Address of IEs to search
+ * @in_len: Length limit from in_ie
+ * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the buf starting from p2p_ie
+ * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of the entire P2P IE
+ *
+ * Returns: The address of the P2P IE found, or NULL
+ */
+u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
+{
+ uint cnt = 0;
+ u8 *p2p_ie_ptr;
+ u8 eid, p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09};
+
+ if (p2p_ielen)
+ *p2p_ielen = 0;
+
+ while (cnt < in_len) {
+ eid = in_ie[cnt];
+ if ((in_len < 0) || (cnt > MAX_IE_SZ)) {
+ dump_stack();
+ return NULL;
+ }
+ if ((eid == _VENDOR_SPECIFIC_IE_) && !memcmp(&in_ie[cnt + 2], p2p_oui, 4)) {
+ p2p_ie_ptr = in_ie + cnt;
+
+ if (p2p_ie)
+ memcpy(p2p_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+ if (p2p_ielen)
+ *p2p_ielen = in_ie[cnt + 1] + 2;
+ return p2p_ie_ptr;
+ } else {
+ cnt += in_ie[cnt + 1] + 2; /* goto next */
+ }
+ }
+ return NULL;
+}
+
+/**
+ * rtw_get_p2p_attr - Search a specific P2P attribute from a given P2P IE
+ * @p2p_ie: Address of P2P IE to search
+ * @p2p_ielen: Length limit from p2p_ie
+ * @target_attr_id: The attribute ID of P2P attribute to search
+ * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will be copied to the buf starting from buf_attr
+ * @len_attr: If not NULL and the P2P attribute is found, will set to the length of the entire P2P attribute
+ *
+ * Returns: the address of the specific WPS attribute found, or NULL
+ */
+u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id, u8 *buf_attr, u32 *len_attr)
+{
+ u8 *attr_ptr = NULL;
+ u8 *target_attr_ptr = NULL;
+ u8 p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09};
+
+ if (len_attr)
+ *len_attr = 0;
+
+ if (!p2p_ie || (p2p_ie[0] != _VENDOR_SPECIFIC_IE_) ||
+ memcmp(p2p_ie + 2, p2p_oui, 4))
+ return attr_ptr;
+
+ /* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
+ attr_ptr = p2p_ie + 6; /* goto first attr */
+
+ while (attr_ptr - p2p_ie < p2p_ielen) {
+ /* 3 = 1(Attribute ID) + 2(Length) */
+ u8 attr_id = *attr_ptr;
+ u16 attr_data_len = get_unaligned_le16(attr_ptr + 1);
+ u16 attr_len = attr_data_len + 3;
+
+ if (attr_id == target_attr_id) {
+ target_attr_ptr = attr_ptr;
+
+ if (buf_attr)
+ memcpy(buf_attr, attr_ptr, attr_len);
+ if (len_attr)
+ *len_attr = attr_len;
+ break;
+ } else {
+ attr_ptr += attr_len; /* goto next */
+ }
+ }
+ return target_attr_ptr;
+}
+
+/**
+ * rtw_get_p2p_attr_content - Search a specific P2P attribute content from a given P2P IE
+ * @p2p_ie: Address of P2P IE to search
+ * @p2p_ielen: Length limit from p2p_ie
+ * @target_attr_id: The attribute ID of P2P attribute to search
+ * @buf_content: If not NULL and the P2P attribute is found, P2P attribute content will be copied to the buf starting from buf_content
+ * @len_content: If not NULL and the P2P attribute is found, will set to the length of the P2P attribute content
+ *
+ * Returns: the address of the specific P2P attribute content found, or NULL
+ */
+u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id, u8 *buf_content, uint *len_content)
+{
+ u8 *attr_ptr;
+ u32 attr_len;
+
+ if (len_content)
+ *len_content = 0;
+
+ attr_ptr = rtw_get_p2p_attr(p2p_ie, p2p_ielen, target_attr_id, NULL, &attr_len);
+
+ if (attr_ptr && attr_len) {
+ if (buf_content)
+ memcpy(buf_content, attr_ptr + 3, attr_len - 3);
+
+ if (len_content)
+ *len_content = attr_len - 3;
+
+ return attr_ptr + 3;
+ }
+
+ return NULL;
+}
+
+u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr)
+{
+ u32 a_len;
+
+ *pbuf = attr_id;
+
+ /* u16*)(pbuf + 1) = cpu_to_le16(attr_len); */
+ RTW_PUT_LE16(pbuf + 1, attr_len);
+
+ if (pdata_attr)
+ memcpy(pbuf + 3, pdata_attr, attr_len);
+
+ a_len = attr_len + 3;
+
+ return a_len;
+}
+
+static uint rtw_p2p_attr_remove(u8 *ie, uint ielen_ori, u8 attr_id)
+{
+ u8 *target_attr;
+ u32 target_attr_len;
+ uint ielen = ielen_ori;
+
+ while (1) {
+ target_attr = rtw_get_p2p_attr(ie, ielen, attr_id, NULL, &target_attr_len);
+ if (target_attr && target_attr_len) {
+ u8 *next_attr = target_attr + target_attr_len;
+ uint remain_len = ielen - (next_attr - ie);
+
+ memset(target_attr, 0, target_attr_len);
+ memcpy(target_attr, next_attr, remain_len);
+ memset(target_attr + remain_len, 0, target_attr_len);
+ *(ie + 1) -= target_attr_len;
+ ielen -= target_attr_len;
+ } else {
+ break;
+ }
+ }
+ return ielen;
+}
+
+void rtw_wlan_bssid_ex_remove_p2p_attr(struct wlan_bssid_ex *bss_ex, u8 attr_id)
+{
+ u8 *p2p_ie;
+ uint p2p_ielen, p2p_ielen_ori;
+
+ p2p_ie = rtw_get_p2p_ie(bss_ex->IEs + _FIXED_IE_LENGTH_, bss_ex->IELength - _FIXED_IE_LENGTH_, NULL, &p2p_ielen_ori);
+ if (p2p_ie) {
+ p2p_ielen = rtw_p2p_attr_remove(p2p_ie, p2p_ielen_ori, attr_id);
+ if (p2p_ielen != p2p_ielen_ori) {
+ u8 *next_ie_ori = p2p_ie + p2p_ielen_ori;
+ u8 *next_ie = p2p_ie + p2p_ielen;
+ uint remain_len = bss_ex->IELength - (next_ie_ori - bss_ex->IEs);
+
+ memcpy(next_ie, next_ie_ori, remain_len);
+ memset(next_ie + remain_len, 0, p2p_ielen_ori - p2p_ielen);
+ bss_ex->IELength -= p2p_ielen_ori - p2p_ielen;
+ }
+ }
+}
+
+#endif /* CONFIG_88EU_P2P */
+
+/* Baron adds to avoid FreeBSD warning */
+int ieee80211_is_empty_essid(const char *essid, int essid_len)
+{
+ /* Single white space is for Linksys APs */
+ if (essid_len == 1 && essid[0] == ' ')
+ return 1;
+
+ /* Otherwise, if the entire essid is 0, we assume it is hidden */
+ while (essid_len) {
+ essid_len--;
+ if (essid[essid_len] != '\0')
+ return 0;
+ }
+
+ return 1;
+}
+
+int ieee80211_get_hdrlen(u16 fc)
+{
+ int hdrlen = 24;
+
+ switch (WLAN_FC_GET_TYPE(fc)) {
+ case RTW_IEEE80211_FTYPE_DATA:
+ if (fc & RTW_IEEE80211_STYPE_QOS_DATA)
+ hdrlen += 2;
+ if ((fc & RTW_IEEE80211_FCTL_FROMDS) && (fc & RTW_IEEE80211_FCTL_TODS))
+ hdrlen += 6; /* Addr4 */
+ break;
+ case RTW_IEEE80211_FTYPE_CTL:
+ switch (WLAN_FC_GET_STYPE(fc)) {
+ case RTW_IEEE80211_STYPE_CTS:
+ case RTW_IEEE80211_STYPE_ACK:
+ hdrlen = 10;
+ break;
+ default:
+ hdrlen = 16;
+ break;
+ }
+ break;
+ }
+
+ return hdrlen;
+}
+
+static int rtw_get_cipher_info(struct wlan_network *pnetwork)
+{
+ u32 wpa_ielen;
+ unsigned char *pbuf;
+ int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
+ int ret = _FAIL;
+ pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
+
+ if (pbuf && (wpa_ielen > 0)) {
+ if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x)) {
+ pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
+ pnetwork->BcnInfo.group_cipher = group_cipher;
+ pnetwork->BcnInfo.is_8021x = is8021x;
+ ret = _SUCCESS;
+ }
+ } else {
+ pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
+
+ if (pbuf && (wpa_ielen > 0)) {
+ if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x)) {
+ pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
+ pnetwork->BcnInfo.group_cipher = group_cipher;
+ pnetwork->BcnInfo.is_8021x = is8021x;
+ ret = _SUCCESS;
+ }
+ }
+ }
+
+ return ret;
+}
+
+void rtw_get_bcn_info(struct wlan_network *pnetwork)
+{
+ unsigned short cap = 0;
+ u8 bencrypt = 0;
+ __le16 le_tmp;
+ u16 wpa_len = 0, rsn_len = 0;
+ struct HT_info_element *pht_info = NULL;
+ struct ieee80211_ht_cap *pht_cap = NULL;
+ unsigned int len;
+ unsigned char *p;
+
+ memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
+ cap = le16_to_cpu(le_tmp);
+ if (cap & WLAN_CAPABILITY_PRIVACY) {
+ bencrypt = 1;
+ pnetwork->network.Privacy = 1;
+ } else {
+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
+ }
+ rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &rsn_len, NULL, &wpa_len);
+
+ if (rsn_len > 0) {
+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
+ } else if (wpa_len > 0) {
+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
+ } else {
+ if (bencrypt)
+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
+ }
+ rtw_get_cipher_info(pnetwork);
+
+ /* get bwmode and ch_offset */
+ /* parsing HT_CAP_IE */
+ p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
+ if (p && len > 0) {
+ pht_cap = (struct ieee80211_ht_cap *)(p + 2);
+ pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(pht_cap->cap_info);
+ } else {
+ pnetwork->BcnInfo.ht_cap_info = 0;
+ }
+ /* parsing HT_INFO_IE */
+ p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
+ if (p && len > 0) {
+ pht_info = (struct HT_info_element *)(p + 2);
+ pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
+ } else {
+ pnetwork->BcnInfo.ht_info_infos_0 = 0;
+ }
+}
+
+/* show MCS rate, unit: 100Kbps */
+u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate)
+{
+ u16 max_rate = 0;
+
+ if (rf_type == RF_1T1R) {
+ if (MCS_rate[0] & BIT(7))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
+ else if (MCS_rate[0] & BIT(6))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
+ else if (MCS_rate[0] & BIT(5))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
+ else if (MCS_rate[0] & BIT(4))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
+ else if (MCS_rate[0] & BIT(3))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
+ else if (MCS_rate[0] & BIT(2))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
+ else if (MCS_rate[0] & BIT(1))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
+ else if (MCS_rate[0] & BIT(0))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
+ } else {
+ if (MCS_rate[1]) {
+ if (MCS_rate[1] & BIT(7))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 3000 : 2700) : ((short_GI_20) ? 1444 : 1300);
+ else if (MCS_rate[1] & BIT(6))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 2700 : 2430) : ((short_GI_20) ? 1300 : 1170);
+ else if (MCS_rate[1] & BIT(5))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 2400 : 2160) : ((short_GI_20) ? 1156 : 1040);
+ else if (MCS_rate[1] & BIT(4))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1800 : 1620) : ((short_GI_20) ? 867 : 780);
+ else if (MCS_rate[1] & BIT(3))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
+ else if (MCS_rate[1] & BIT(2))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
+ else if (MCS_rate[1] & BIT(1))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
+ else if (MCS_rate[1] & BIT(0))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
+ } else {
+ if (MCS_rate[0] & BIT(7))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
+ else if (MCS_rate[0] & BIT(6))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
+ else if (MCS_rate[0] & BIT(5))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
+ else if (MCS_rate[0] & BIT(4))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
+ else if (MCS_rate[0] & BIT(3))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
+ else if (MCS_rate[0] & BIT(2))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
+ else if (MCS_rate[0] & BIT(1))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
+ else if (MCS_rate[0] & BIT(0))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
+ }
+ }
+ return max_rate;
+}
+
+int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action)
+{
+ const u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
+ u16 fc;
+ u8 c, a = 0;
+
+ fc = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)frame)->frame_ctl);
+
+ if ((fc & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE)) !=
+ (RTW_IEEE80211_FTYPE_MGMT | RTW_IEEE80211_STYPE_ACTION))
+ return false;
+
+ c = frame_body[0];
+
+ switch (c) {
+ case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */
+ break;
+ default:
+ a = frame_body[1];
+ }
+
+ if (category)
+ *category = c;
+ if (action)
+ *action = a;
+
+ return true;
+}
+
+static const char *_action_public_str[] = {
+ "ACT_PUB_BSSCOEXIST",
+ "ACT_PUB_DSE_ENABLE",
+ "ACT_PUB_DSE_DEENABLE",
+ "ACT_PUB_DSE_REG_LOCATION",
+ "ACT_PUB_EXT_CHL_SWITCH",
+ "ACT_PUB_DSE_MSR_REQ",
+ "ACT_PUB_DSE_MSR_RPRT",
+ "ACT_PUB_MP",
+ "ACT_PUB_DSE_PWR_CONSTRAINT",
+ "ACT_PUB_VENDOR",
+ "ACT_PUB_GAS_INITIAL_REQ",
+ "ACT_PUB_GAS_INITIAL_RSP",
+ "ACT_PUB_GAS_COMEBACK_REQ",
+ "ACT_PUB_GAS_COMEBACK_RSP",
+ "ACT_PUB_TDLS_DISCOVERY_RSP",
+ "ACT_PUB_LOCATION_TRACK",
+ "ACT_PUB_RSVD",
+};
+
+const char *action_public_str(u8 action)
+{
+ action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
+ return _action_public_str[action];
+}
diff --git a/drivers/staging/r8188eu/core/rtw_io.c b/drivers/staging/r8188eu/core/rtw_io.c
new file mode 100644
index 000000000000..cde0205816b1
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_io.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+/*
+
+The purpose of rtw_io.c
+
+a. provides the API
+
+b. provides the protocol engine
+
+c. provides the software interface between caller and the hardware interface
+
+Compiler Flag Option:
+
+USB:
+ a. USE_ASYNC_IRP: Both sync/async operations are provided.
+
+Only sync read/rtw_write_mem operations are provided.
+
+jackson@realtek.com.tw
+
+*/
+
+#define _RTW_IO_C_
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtw_io.h"
+#include "../include/osdep_intf.h"
+#include "../include/usb_ops.h"
+
+#define rtw_le16_to_cpu(val) le16_to_cpu(val)
+#define rtw_le32_to_cpu(val) le32_to_cpu(val)
+#define rtw_cpu_to_le16(val) cpu_to_le16(val)
+#define rtw_cpu_to_le32(val) cpu_to_le32(val)
+
+u8 _rtw_read8(struct adapter *adapter, u32 addr)
+{
+ u8 r_val;
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+
+
+ _read8 = pintfhdl->io_ops._read8;
+ r_val = _read8(pintfhdl, addr);
+
+ return r_val;
+}
+
+u16 _rtw_read16(struct adapter *adapter, u32 addr)
+{
+ u16 r_val;
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+
+ _read16 = pintfhdl->io_ops._read16;
+
+ r_val = _read16(pintfhdl, addr);
+
+ return r_val;
+}
+
+u32 _rtw_read32(struct adapter *adapter, u32 addr)
+{
+ u32 r_val;
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+
+ _read32 = pintfhdl->io_ops._read32;
+
+ r_val = _read32(pintfhdl, addr);
+
+ return r_val;
+}
+
+int _rtw_write8(struct adapter *adapter, u32 addr, u8 val)
+{
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+ int ret;
+
+ _write8 = pintfhdl->io_ops._write8;
+
+ ret = _write8(pintfhdl, addr, val);
+
+
+ return RTW_STATUS_CODE(ret);
+}
+
+int _rtw_write16(struct adapter *adapter, u32 addr, u16 val)
+{
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+ int ret;
+
+ _write16 = pintfhdl->io_ops._write16;
+
+ ret = _write16(pintfhdl, addr, val);
+
+
+ return RTW_STATUS_CODE(ret);
+}
+int _rtw_write32(struct adapter *adapter, u32 addr, u32 val)
+{
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
+ int ret;
+
+ _write32 = pintfhdl->io_ops._write32;
+
+ ret = _write32(pintfhdl, addr, val);
+
+
+ return RTW_STATUS_CODE(ret);
+}
+
+int _rtw_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata)
+{
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = (struct intf_hdl *)(&pio_priv->intf);
+ int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata);
+ int ret;
+
+ _writeN = pintfhdl->io_ops._writeN;
+
+ ret = _writeN(pintfhdl, addr, length, pdata);
+
+
+ return RTW_STATUS_CODE(ret);
+}
+int _rtw_write8_async(struct adapter *adapter, u32 addr, u8 val)
+{
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+ int ret;
+
+ _write8_async = pintfhdl->io_ops._write8_async;
+
+ ret = _write8_async(pintfhdl, addr, val);
+
+
+ return RTW_STATUS_CODE(ret);
+}
+
+int _rtw_write16_async(struct adapter *adapter, u32 addr, u16 val)
+{
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+ int ret;
+
+ _write16_async = pintfhdl->io_ops._write16_async;
+ ret = _write16_async(pintfhdl, addr, val);
+
+ return RTW_STATUS_CODE(ret);
+}
+
+int _rtw_write32_async(struct adapter *adapter, u32 addr, u32 val)
+{
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
+ int ret;
+
+ _write32_async = pintfhdl->io_ops._write32_async;
+ ret = _write32_async(pintfhdl, addr, val);
+
+ return RTW_STATUS_CODE(ret);
+}
+
+void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+{
+ void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+
+
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
+ return;
+ _read_mem = pintfhdl->io_ops._read_mem;
+ _read_mem(pintfhdl, addr, cnt, pmem);
+
+}
+
+void _rtw_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+{
+ void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+
+
+
+ _write_mem = pintfhdl->io_ops._write_mem;
+
+ _write_mem(pintfhdl, addr, cnt, pmem);
+
+
+}
+
+void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+{
+ u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+
+
+
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
+ return;
+
+ _read_port = pintfhdl->io_ops._read_port;
+
+ _read_port(pintfhdl, addr, cnt, pmem);
+
+
+}
+
+void _rtw_read_port_cancel(struct adapter *adapter)
+{
+ void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+
+ _read_port_cancel = pintfhdl->io_ops._read_port_cancel;
+
+ if (_read_port_cancel)
+ _read_port_cancel(pintfhdl);
+}
+
+u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+{
+ u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+ u32 ret = _SUCCESS;
+
+
+
+ _write_port = pintfhdl->io_ops._write_port;
+
+ ret = _write_port(pintfhdl, addr, cnt, pmem);
+
+
+
+ return ret;
+}
+
+u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem, int timeout_ms)
+{
+ int ret = _SUCCESS;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)pmem;
+ struct submit_ctx sctx;
+
+ rtw_sctx_init(&sctx, timeout_ms);
+ pxmitbuf->sctx = &sctx;
+
+ ret = _rtw_write_port(adapter, addr, cnt, pmem);
+
+ if (ret == _SUCCESS)
+ ret = rtw_sctx_wait(&sctx);
+
+ return ret;
+}
+
+void _rtw_write_port_cancel(struct adapter *adapter)
+{
+ void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
+ struct io_priv *pio_priv = &adapter->iopriv;
+ struct intf_hdl *pintfhdl = &pio_priv->intf;
+
+ _write_port_cancel = pintfhdl->io_ops._write_port_cancel;
+
+ if (_write_port_cancel)
+ _write_port_cancel(pintfhdl);
+}
+
+int rtw_init_io_priv(struct adapter *padapter, void (*set_intf_ops)(struct _io_ops *pops))
+{
+ struct io_priv *piopriv = &padapter->iopriv;
+ struct intf_hdl *pintf = &piopriv->intf;
+
+ if (!set_intf_ops)
+ return _FAIL;
+
+ piopriv->padapter = padapter;
+ pintf->padapter = padapter;
+ pintf->pintf_dev = adapter_to_dvobj(padapter);
+
+ set_intf_ops(&pintf->io_ops);
+
+ return _SUCCESS;
+}
diff --git a/drivers/staging/r8188eu/core/rtw_ioctl_set.c b/drivers/staging/r8188eu/core/rtw_ioctl_set.c
new file mode 100644
index 000000000000..c187de78b4ac
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_ioctl_set.c
@@ -0,0 +1,891 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#define _RTW_IOCTL_SET_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtw_ioctl_set.h"
+#include "../include/hal_intf.h"
+
+#include "../include/usb_osintf.h"
+#include "../include/usb_ops.h"
+
+extern void indicate_wx_scan_complete_event(struct adapter *padapter);
+
+u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
+{
+ u8 i;
+ u8 ret = true;
+
+ if (ssid->SsidLength > 32) {
+ ret = false;
+ goto exit;
+ }
+
+ for (i = 0; i < ssid->SsidLength; i++) {
+ /* wifi, printable ascii code must be supported */
+ if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e))) {
+ ret = false;
+ break;
+ }
+ }
+
+exit:
+
+ return ret;
+}
+
+u8 rtw_do_join(struct adapter *padapter)
+{
+ struct list_head *plist, *phead;
+ u8 *pibss = NULL;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ u8 ret = _SUCCESS;
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ pmlmepriv->cur_network.join_res = -2;
+
+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+
+ pmlmepriv->pscanned = plist;
+
+ pmlmepriv->to_join = true;
+
+ if (list_empty(&queue->queue)) {
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+ /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
+ /* we try to issue sitesurvey firstly */
+
+ if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
+ pmlmepriv->to_roaming > 0) {
+ /* submit site_survey_cmd */
+ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
+ if (_SUCCESS != ret)
+ pmlmepriv->to_join = false;
+ } else {
+ pmlmepriv->to_join = false;
+ ret = _FAIL;
+ }
+
+ goto exit;
+ } else {
+ int select_ret;
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
+ if (select_ret == _SUCCESS) {
+ pmlmepriv->to_join = false;
+ _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
+ } else {
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ /* submit createbss_cmd to change to a ADHOC_MASTER */
+
+ /* pmlmepriv->lock has been acquired by caller... */
+ struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
+
+ pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+
+ pibss = padapter->registrypriv.dev_network.MacAddress;
+
+ memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+
+ rtw_update_registrypriv_dev_network(padapter);
+
+ rtw_generate_random_ibss(pibss);
+
+ if (rtw_createbss_cmd(padapter) != _SUCCESS) {
+ ret = false;
+ goto exit;
+ }
+ pmlmepriv->to_join = false;
+ } else {
+ /* can't associate ; reset under-linking */
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+ /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
+ /* we try to issue sitesurvey firstly */
+ if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
+ pmlmepriv->to_roaming > 0) {
+ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
+ if (_SUCCESS != ret)
+ pmlmepriv->to_join = false;
+ } else {
+ ret = _FAIL;
+ pmlmepriv->to_join = false;
+ }
+ }
+ }
+ }
+
+exit:
+
+ return ret;
+}
+
+u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
+{
+ u8 status = _SUCCESS;
+ u32 cur_time = 0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ DBG_88E_LEVEL(_drv_info_, "set bssid:%pM\n", bssid);
+
+ if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 &&
+ bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
+ (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF &&
+ bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
+ status = _FAIL;
+ goto exit;
+ }
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ DBG_88E("Set BSSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ goto handle_tkip_countermeasure;
+ else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
+ goto release_mlme_lock;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
+ if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
+ if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
+ } else {
+ rtw_disassoc_cmd(padapter, 0, true);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_indicate_disconnect(padapter);
+
+ rtw_free_assoc_resources(padapter, 1);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ }
+ }
+ }
+
+handle_tkip_countermeasure:
+ /* should we add something here...? */
+
+ if (padapter->securitypriv.btkip_countermeasure) {
+ cur_time = jiffies;
+
+ if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
+ padapter->securitypriv.btkip_countermeasure = false;
+ padapter->securitypriv.btkip_countermeasure_time = 0;
+ } else {
+ status = _FAIL;
+ goto release_mlme_lock;
+ }
+ }
+
+ memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
+ pmlmepriv->assoc_by_bssid = true;
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ pmlmepriv->to_join = true;
+ else
+ status = rtw_do_join(padapter);
+
+release_mlme_lock:
+ spin_unlock_bh(&pmlmepriv->lock);
+
+exit:
+ return status;
+}
+
+u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
+{
+ u8 status = _SUCCESS;
+ u32 cur_time = 0;
+
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *pnetwork = &pmlmepriv->cur_network;
+
+ DBG_88E_LEVEL(_drv_info_, "set ssid [%s] fw_state=0x%08x\n",
+ ssid->Ssid, get_fwstate(pmlmepriv));
+
+ if (!padapter->hw_init_completed) {
+ status = _FAIL;
+ goto exit;
+ }
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ DBG_88E("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
+ goto handle_tkip_countermeasure;
+ } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
+ goto release_mlme_lock;
+ }
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
+ if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
+ (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
+ if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ if (!rtw_is_same_ibss(padapter, pnetwork)) {
+ /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
+ rtw_disassoc_cmd(padapter, 0, true);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_indicate_disconnect(padapter);
+
+ rtw_free_assoc_resources(padapter, 1);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ }
+ } else {
+ goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
+ }
+ } else {
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
+ }
+ } else {
+ rtw_disassoc_cmd(padapter, 0, true);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_indicate_disconnect(padapter);
+
+ rtw_free_assoc_resources(padapter, 1);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ }
+ }
+ }
+
+handle_tkip_countermeasure:
+
+ if (padapter->securitypriv.btkip_countermeasure) {
+ cur_time = jiffies;
+
+ if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
+ padapter->securitypriv.btkip_countermeasure = false;
+ padapter->securitypriv.btkip_countermeasure_time = 0;
+ } else {
+ status = _FAIL;
+ goto release_mlme_lock;
+ }
+ }
+
+ memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
+ pmlmepriv->assoc_by_bssid = false;
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
+ pmlmepriv->to_join = true;
+ } else {
+ status = rtw_do_join(padapter);
+ }
+
+release_mlme_lock:
+ spin_unlock_bh(&pmlmepriv->lock);
+
+exit:
+ return status;
+}
+
+u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
+ enum ndis_802_11_network_infra networktype)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode;
+
+ if (*pold_state != networktype) {
+ spin_lock_bh(&pmlmepriv->lock);
+
+ /* DBG_88E("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
+
+ if (*pold_state == Ndis802_11APMode) {
+ /* change to other mode from Ndis802_11APMode */
+ cur_network->join_res = -1;
+
+#ifdef CONFIG_88EU_AP_MODE
+ stop_ap_mode(padapter);
+#endif
+ }
+
+ if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
+ (*pold_state == Ndis802_11IBSS))
+ rtw_disassoc_cmd(padapter, 0, true);
+
+ if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
+ rtw_free_assoc_resources(padapter, 1);
+
+ if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether issue dis-assoc_cmd or not */
+ }
+
+ *pold_state = networktype;
+
+ _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
+
+ switch (networktype) {
+ case Ndis802_11IBSS:
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ break;
+ case Ndis802_11Infrastructure:
+ set_fwstate(pmlmepriv, WIFI_STATION_STATE);
+ break;
+ case Ndis802_11APMode:
+ set_fwstate(pmlmepriv, WIFI_AP_STATE);
+#ifdef CONFIG_88EU_AP_MODE
+ start_ap_mode(padapter);
+#endif
+ break;
+ case Ndis802_11AutoUnknown:
+ case Ndis802_11InfrastructureMax:
+ break;
+ }
+ spin_unlock_bh(&pmlmepriv->lock);
+ }
+
+ return true;
+}
+
+u8 rtw_set_802_11_disassociate(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ rtw_disassoc_cmd(padapter, 0, true);
+ rtw_indicate_disconnect(padapter);
+ rtw_free_assoc_resources(padapter, 1);
+ rtw_pwr_wakeup(padapter);
+ }
+
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ return true;
+}
+
+u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 res = true;
+
+ if (!padapter) {
+ res = false;
+ goto exit;
+ }
+ if (!padapter->hw_init_completed) {
+ res = false;
+ goto exit;
+ }
+
+ if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
+ (pmlmepriv->LinkDetectInfo.bBusyTraffic)) {
+ /* Scan or linking is in progress, do nothing. */
+ res = true;
+ } else {
+ if (rtw_is_scan_deny(padapter)) {
+ DBG_88E(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter));
+ indicate_wx_scan_complete_event(padapter);
+ return _SUCCESS;
+ }
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
+
+ spin_unlock_bh(&pmlmepriv->lock);
+ }
+exit:
+
+ return res;
+}
+
+u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode)
+{
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ int res;
+ u8 ret;
+
+ psecuritypriv->ndisauthtype = authmode;
+
+ if (psecuritypriv->ndisauthtype > 3)
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+
+ res = rtw_set_auth(padapter, psecuritypriv);
+
+ if (res == _SUCCESS)
+ ret = true;
+ else
+ ret = false;
+
+ return ret;
+}
+
+u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
+{
+ int keyid, res;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ u8 ret = _SUCCESS;
+
+ keyid = wep->KeyIndex & 0x3fffffff;
+
+ if (keyid >= 4) {
+ ret = false;
+ goto exit;
+ }
+
+ switch (wep->KeyLength) {
+ case 5:
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+ break;
+ case 13:
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+ break;
+ default:
+ psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ break;
+ }
+
+ memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0], &wep->KeyMaterial, wep->KeyLength);
+
+ psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
+
+ psecuritypriv->dot11PrivacyKeyIndex = keyid;
+
+ res = rtw_set_key(padapter, psecuritypriv, keyid, 1);
+
+ if (res == _FAIL)
+ ret = false;
+exit:
+
+ return ret;
+}
+
+u8 rtw_set_802_11_remove_wep(struct adapter *padapter, u32 keyindex)
+{
+ u8 ret = _SUCCESS;
+
+ if (keyindex >= 0x80000000 || !padapter) {
+ ret = false;
+ goto exit;
+ } else {
+ int res;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ if (keyindex < 4) {
+ memset(&psecuritypriv->dot11DefKey[keyindex], 0, 16);
+ res = rtw_set_key(padapter, psecuritypriv, keyindex, 0);
+ psecuritypriv->dot11DefKeylen[keyindex] = 0;
+ if (res == _FAIL)
+ ret = _FAIL;
+ } else {
+ ret = _FAIL;
+ }
+ }
+exit:
+
+ return ret;
+}
+
+u8 rtw_set_802_11_add_key(struct adapter *padapter, struct ndis_802_11_key *key)
+{
+ uint encryptionalgo;
+ u8 *pbssid;
+ struct sta_info *stainfo;
+ u8 bgroup = false;
+ u8 bgrouptkey = false;/* can be removed later */
+ u8 ret = _SUCCESS;
+
+ if (((key->KeyIndex & 0x80000000) == 0) && ((key->KeyIndex & 0x40000000) > 0)) {
+ /* It is invalid to clear bit 31 and set bit 30. If the miniport driver encounters this combination, */
+ /* it must fail the request and return NDIS_STATUS_INVALID_DATA. */
+ ret = _FAIL;
+ goto exit;
+ }
+
+ if (key->KeyIndex & 0x40000000) {
+ /* Pairwise key */
+
+ pbssid = get_bssid(&padapter->mlmepriv);
+ stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
+
+ if (stainfo && padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
+ encryptionalgo = stainfo->dot118021XPrivacy;
+ else
+ encryptionalgo = padapter->securitypriv.dot11PrivacyAlgrthm;
+
+ if (key->KeyIndex & 0x000000FF) {
+ /* The key index is specified in the lower 8 bits by values of zero to 255. */
+ /* The key index should be set to zero for a Pairwise key, and the driver should fail with */
+ /* NDIS_STATUS_INVALID_DATA if the lower 8 bits is not zero */
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* check BSSID */
+ if (is_broadcast_ether_addr(key->BSSID)) {
+ ret = false;
+ goto exit;
+ }
+
+ /* Check key length for TKIP. */
+ if ((encryptionalgo == _TKIP_) && (key->KeyLength != 32)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* Check key length for AES. */
+ if ((encryptionalgo == _AES_) && (key->KeyLength != 16)) {
+ /* For our supplicant, EAPPkt9x.vxd, cannot differentiate TKIP and AES case. */
+ if (key->KeyLength == 32) {
+ key->KeyLength = 16;
+ } else {
+ ret = _FAIL;
+ goto exit;
+ }
+ }
+
+ /* Check key length for WEP. For NDTEST, 2005.01.27, by rcnjko. */
+ if ((encryptionalgo == _WEP40_ || encryptionalgo == _WEP104_) &&
+ (key->KeyLength != 5 && key->KeyLength != 13)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ bgroup = false;
+ } else {
+ /* Group key - KeyIndex(BIT(30) == 0) */
+ /* when add wep key through add key and didn't assigned encryption type before */
+ if ((padapter->securitypriv.ndisauthtype <= 3) &&
+ (padapter->securitypriv.dot118021XGrpPrivacy == 0)) {
+ switch (key->KeyLength) {
+ case 5:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ break;
+ case 13:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+ break;
+ default:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ break;
+ }
+
+ encryptionalgo = padapter->securitypriv.dot11PrivacyAlgrthm;
+ } else {
+ encryptionalgo = padapter->securitypriv.dot118021XGrpPrivacy;
+ }
+
+ if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE) && !is_broadcast_ether_addr(key->BSSID)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* Check key length for TKIP */
+ if ((encryptionalgo == _TKIP_) && (key->KeyLength != 32)) {
+ ret = _FAIL;
+ goto exit;
+ } else if (encryptionalgo == _AES_ && (key->KeyLength != 16 && key->KeyLength != 32)) {
+ /* Check key length for AES */
+ /* For NDTEST, we allow keylen = 32 in this case. 2005.01.27, by rcnjko. */
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* Change the key length for EAPPkt9x.vxd. Added by Annie, 2005-11-03. */
+ if ((encryptionalgo == _AES_) && (key->KeyLength == 32))
+ key->KeyLength = 16;
+
+ if (key->KeyIndex & 0x8000000) {/* error ??? 0x8000_0000 */
+ bgrouptkey = true;
+ }
+
+ if ((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE)) &&
+ (check_fwstate(&padapter->mlmepriv, _FW_LINKED)))
+ bgrouptkey = true;
+ bgroup = true;
+ }
+
+ /* If WEP encryption algorithm, just call rtw_set_802_11_add_wep(). */
+ if ((padapter->securitypriv.dot11AuthAlgrthm != dot11AuthAlgrthm_8021X) &&
+ (encryptionalgo == _WEP40_ || encryptionalgo == _WEP104_)) {
+ u32 keyindex;
+ u32 len = FIELD_OFFSET(struct ndis_802_11_key, KeyMaterial) + key->KeyLength;
+ struct ndis_802_11_wep *wep = &padapter->securitypriv.ndiswep;
+
+ wep->Length = len;
+ keyindex = key->KeyIndex & 0x7fffffff;
+ wep->KeyIndex = keyindex;
+ wep->KeyLength = key->KeyLength;
+
+ memcpy(wep->KeyMaterial, key->KeyMaterial, key->KeyLength);
+ memcpy(&padapter->securitypriv.dot11DefKey[keyindex].skey[0], key->KeyMaterial, key->KeyLength);
+
+ padapter->securitypriv.dot11DefKeylen[keyindex] = key->KeyLength;
+ padapter->securitypriv.dot11PrivacyKeyIndex = keyindex;
+
+ ret = rtw_set_802_11_add_wep(padapter, wep);
+ goto exit;
+ }
+ if (key->KeyIndex & 0x20000000) {
+ /* SetRSC */
+ if (bgroup) {
+ unsigned long long keysrc = key->KeyRSC & 0x00FFFFFFFFFFFFULL;
+ memcpy(&padapter->securitypriv.dot11Grprxpn, &keysrc, 8);
+ } else {
+ unsigned long long keysrc = key->KeyRSC & 0x00FFFFFFFFFFFFULL;
+ memcpy(&padapter->securitypriv.dot11Grptxpn, &keysrc, 8);
+ }
+ }
+
+ /* Indicate this key idx is used for TX */
+ /* Save the key in KeyMaterial */
+ if (bgroup) { /* Group transmit key */
+ int res;
+
+ if (bgrouptkey)
+ padapter->securitypriv.dot118021XGrpKeyid = (u8)key->KeyIndex;
+ if ((key->KeyIndex & 0x3) == 0) {
+ ret = _FAIL;
+ goto exit;
+ }
+ memset(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+ memset(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+ memset(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+
+ if ((key->KeyIndex & 0x10000000)) {
+ memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
+ memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
+ } else {
+ memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
+ memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
+ }
+
+ /* set group key by index */
+ memcpy(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial, key->KeyLength);
+
+ key->KeyIndex = key->KeyIndex & 0x03;
+
+ padapter->securitypriv.binstallGrpkey = true;
+
+ padapter->securitypriv.bcheck_grpkey = false;
+
+ res = rtw_set_key(padapter, &padapter->securitypriv, key->KeyIndex, 1);
+
+ if (res == _FAIL)
+ ret = _FAIL;
+
+ goto exit;
+
+ } else { /* Pairwise Key */
+ u8 res;
+
+ pbssid = get_bssid(&padapter->mlmepriv);
+ stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
+
+ if (stainfo) {
+ memset(&stainfo->dot118021x_UncstKey, 0, 16);/* clear keybuffer */
+
+ memcpy(&stainfo->dot118021x_UncstKey, key->KeyMaterial, 16);
+
+ if (encryptionalgo == _TKIP_) {
+ padapter->securitypriv.busetkipkey = false;
+
+ /* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
+
+ /* if TKIP, save the Receive/Transmit MIC key in KeyMaterial[128-255] */
+ if ((key->KeyIndex & 0x10000000)) {
+ memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 16, 8);
+ memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 24, 8);
+
+ } else {
+ memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 24, 8);
+ memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 16, 8);
+ }
+ }
+
+ /* Set key to CAM through H2C command */
+ if (bgrouptkey) /* never go to here */
+ res = rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, false);
+ else
+ res = rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, true);
+ if (!res)
+ ret = _FAIL;
+ }
+ }
+exit:
+
+ return ret;
+}
+
+u8 rtw_set_802_11_remove_key(struct adapter *padapter, struct ndis_802_11_remove_key *key)
+{
+ u8 *pbssid;
+ struct sta_info *stainfo;
+ u8 bgroup = (key->KeyIndex & 0x4000000) > 0 ? false : true;
+ u8 keyIndex = (u8)key->KeyIndex & 0x03;
+ u8 ret = _SUCCESS;
+
+ if ((key->KeyIndex & 0xbffffffc) > 0) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ if (bgroup) {
+ /* clear group key by index */
+
+ memset(&padapter->securitypriv.dot118021XGrpKey[keyIndex], 0, 16);
+
+ /* \todo Send a H2C Command to Firmware for removing this Key in CAM Entry. */
+ } else {
+ pbssid = get_bssid(&padapter->mlmepriv);
+ stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
+ if (stainfo) {
+ /* clear key by BSSID */
+ memset(&stainfo->dot118021x_UncstKey, 0, 16);
+
+ /* \todo Send a H2C Command to Firmware for disable this Key in CAM Entry. */
+ } else {
+ ret = _FAIL;
+ goto exit;
+ }
+ }
+exit:
+
+ return ret;
+}
+
+/*
+* rtw_get_cur_max_rate -
+* @adapter: pointer to struct adapter structure
+*
+* Return 0 or 100Kbps
+*/
+u16 rtw_get_cur_max_rate(struct adapter *adapter)
+{
+ int i = 0;
+ u8 *p;
+ u16 rate = 0, max_rate = 0;
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct registry_priv *pregistrypriv = &adapter->registrypriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ struct ieee80211_ht_cap *pht_capie;
+ u8 rf_type = 0;
+ u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
+ u16 mcs_rate = 0;
+ u32 ht_ielen = 0;
+
+ if (adapter->registrypriv.mp_mode == 1) {
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
+ return 0;
+ }
+
+ if ((!check_fwstate(pmlmepriv, _FW_LINKED)) &&
+ (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
+ return 0;
+
+ if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N)) {
+ p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
+ if (p && ht_ielen > 0) {
+ pht_capie = (struct ieee80211_ht_cap *)(p + 2);
+
+ memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
+
+ /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */
+ bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0;
+
+ short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
+ short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
+
+ rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ max_rate = rtw_mcs_rate(
+ rf_type,
+ bw_40MHz & (pregistrypriv->cbw40_enable),
+ short_GI_20,
+ short_GI_40,
+ pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate
+ );
+ }
+ } else {
+ while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
+ rate = pcur_bss->SupportedRates[i] & 0x7F;
+ if (rate > max_rate)
+ max_rate = rate;
+ i++;
+ }
+
+ max_rate *= 5;
+ }
+
+ return max_rate;
+}
+
+/*
+* rtw_set_scan_mode -
+* @adapter: pointer to struct adapter structure
+* @scan_mode:
+*
+* Return _SUCCESS or _FAIL
+*/
+int rtw_set_scan_mode(struct adapter *adapter, enum rt_scan_type scan_mode)
+{
+ if (scan_mode != SCAN_ACTIVE && scan_mode != SCAN_PASSIVE)
+ return _FAIL;
+
+ adapter->mlmepriv.scan_mode = scan_mode;
+
+ return _SUCCESS;
+}
+
+/*
+* rtw_set_channel_plan -
+* @adapter: pointer to struct adapter structure
+* @channel_plan:
+*
+* Return _SUCCESS or _FAIL
+*/
+int rtw_set_channel_plan(struct adapter *adapter, u8 channel_plan)
+{
+ /* handle by cmd_thread to sync with scan operation */
+ return rtw_set_chplan_cmd(adapter, channel_plan, 1);
+}
+
+/*
+* rtw_set_country -
+* @adapter: pointer to struct adapter structure
+* @country_code: string of country code
+*
+* Return _SUCCESS or _FAIL
+*/
+int rtw_set_country(struct adapter *adapter, const char *country_code)
+{
+ int channel_plan = RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G;
+
+ DBG_88E("%s country_code:%s\n", __func__, country_code);
+
+ /* TODO: should have a table to match country code and RT_CHANNEL_DOMAIN */
+ /* TODO: should consider 2-character and 3-character country code */
+ if (0 == strcmp(country_code, "US"))
+ channel_plan = RT_CHANNEL_DOMAIN_FCC;
+ else if (0 == strcmp(country_code, "EU"))
+ channel_plan = RT_CHANNEL_DOMAIN_ETSI;
+ else if (0 == strcmp(country_code, "JP"))
+ channel_plan = RT_CHANNEL_DOMAIN_MKK;
+ else if (0 == strcmp(country_code, "CN"))
+ channel_plan = RT_CHANNEL_DOMAIN_CHINA;
+ else
+ DBG_88E("%s unknown country_code:%s\n", __func__, country_code);
+
+ return rtw_set_channel_plan(adapter, channel_plan);
+}
diff --git a/drivers/staging/r8188eu/core/rtw_iol.c b/drivers/staging/r8188eu/core/rtw_iol.c
new file mode 100644
index 000000000000..5c1b19679cad
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_iol.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/rtw_iol.h"
+
+struct xmit_frame *rtw_IOL_accquire_xmit_frame(struct adapter *adapter)
+{
+ struct xmit_frame *xmit_frame;
+ struct xmit_buf *xmitbuf;
+ struct pkt_attrib *pattrib;
+ struct xmit_priv *pxmitpriv = &adapter->xmitpriv;
+
+ xmit_frame = rtw_alloc_xmitframe(pxmitpriv);
+ if (!xmit_frame) {
+ DBG_88E("%s rtw_alloc_xmitframe return null\n", __func__);
+ goto exit;
+ }
+
+ xmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
+ if (!xmitbuf) {
+ DBG_88E("%s rtw_alloc_xmitbuf return null\n", __func__);
+ rtw_free_xmitframe(pxmitpriv, xmit_frame);
+ xmit_frame = NULL;
+ goto exit;
+ }
+
+ xmit_frame->frame_tag = MGNT_FRAMETAG;
+ xmit_frame->pxmitbuf = xmitbuf;
+ xmit_frame->buf_addr = xmitbuf->pbuf;
+ xmitbuf->priv_data = xmit_frame;
+
+ pattrib = &xmit_frame->attrib;
+ update_mgntframe_attrib(adapter, pattrib);
+ pattrib->qsel = 0x10;/* Beacon */
+ pattrib->subtype = WIFI_BEACON;
+ pattrib->pktlen = 0;
+ pattrib->last_txcmdsz = 0;
+exit:
+ return xmit_frame;
+}
+
+int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len)
+{
+ struct pkt_attrib *pattrib = &xmit_frame->attrib;
+ u16 buf_offset;
+ u32 ori_len;
+
+ buf_offset = TXDESC_OFFSET;
+ ori_len = buf_offset + pattrib->pktlen;
+
+ /* check if the io_buf can accommodate new cmds */
+ if (ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) {
+ DBG_88E("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate new cmds\n",
+ __func__, ori_len + cmd_len + 8, MAX_XMITBUF_SZ);
+ return _FAIL;
+ }
+
+ memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len);
+ pattrib->pktlen += cmd_len;
+ pattrib->last_txcmdsz += cmd_len;
+
+ return _SUCCESS;
+}
+
+bool rtw_IOL_applied(struct adapter *adapter)
+{
+ if (1 == adapter->registrypriv.fw_iol)
+ return true;
+
+ if ((2 == adapter->registrypriv.fw_iol) && (!adapter_to_dvobj(adapter)->ishighspeed))
+ return true;
+ return false;
+}
+
+int rtw_IOL_exec_cmds_sync(struct adapter *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
+{
+ return rtw_hal_iol_cmd(adapter, xmit_frame, max_wating_ms, bndy_cnt);
+}
+
+int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
+{
+ return _SUCCESS;
+}
+
+int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, u8 mask)
+{
+ struct ioreg_cfg cmd = {8, IOREG_CMD_WB_REG, 0x0, 0x0, 0x0};
+
+ cmd.address = cpu_to_le16(addr);
+ cmd.data = cpu_to_le32(value);
+
+ if (mask != 0xFF) {
+ cmd.length = 12;
+ cmd.mask = cpu_to_le32(mask);
+ }
+ return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
+}
+
+int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask)
+{
+ struct ioreg_cfg cmd = {8, IOREG_CMD_WW_REG, 0x0, 0x0, 0x0};
+
+ cmd.address = cpu_to_le16(addr);
+ cmd.data = cpu_to_le32(value);
+
+ if (mask != 0xFFFF) {
+ cmd.length = 12;
+ cmd.mask = cpu_to_le32(mask);
+ }
+ return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
+}
+
+int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask)
+{
+ struct ioreg_cfg cmd = {8, IOREG_CMD_WD_REG, 0x0, 0x0, 0x0};
+
+ cmd.address = cpu_to_le16(addr);
+ cmd.data = cpu_to_le32(value);
+
+ if (mask != 0xFFFFFFFF) {
+ cmd.length = 12;
+ cmd.mask = cpu_to_le32(mask);
+ }
+ return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
+}
+
+int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, u16 addr, u32 value, u32 mask)
+{
+ struct ioreg_cfg cmd = {8, IOREG_CMD_W_RF, 0x0, 0x0, 0x0};
+
+ cmd.address = cpu_to_le16((rf_path << 8) | ((addr) & 0xFF));
+ cmd.data = cpu_to_le32(value);
+
+ if (mask != 0x000FFFFF) {
+ cmd.length = 12;
+ cmd.mask = cpu_to_le32(mask);
+ }
+ return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
+}
+
+int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
+{
+ struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
+ cmd.address = cpu_to_le16(us);
+
+ return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
+}
+
+int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
+{
+ struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
+
+ cmd.address = cpu_to_le16(ms);
+ return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
+}
+
+int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
+{
+ struct ioreg_cfg cmd = {4, IOREG_CMD_END, cpu_to_le16(0xFFFF), cpu_to_le32(0xFF), 0x0};
+
+ return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
+}
+
+u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame)
+{
+ u8 is_cmd_bndy = false;
+ if (((pxmit_frame->attrib.pktlen + 32) % 256) + 8 >= 256) {
+ rtw_IOL_append_END_cmd(pxmit_frame);
+ pxmit_frame->attrib.pktlen = ((((pxmit_frame->attrib.pktlen + 32) / 256) + 1) * 256);
+
+ pxmit_frame->attrib.last_txcmdsz = pxmit_frame->attrib.pktlen;
+ is_cmd_bndy = true;
+ }
+ return is_cmd_bndy;
+}
+
+void rtw_IOL_cmd_buf_dump(struct adapter *Adapter, int buf_len, u8 *pbuf)
+{
+ int i;
+ int j = 1;
+
+ pr_info("###### %s ######\n", __func__);
+ for (i = 0; i < buf_len; i++) {
+ printk("%02x-", *(pbuf + i));
+
+ if (j % 32 == 0)
+ printk("\n");
+ j++;
+ }
+ printk("\n");
+ pr_info("=============ioreg_cmd len=%d===============\n", buf_len);
+}
diff --git a/drivers/staging/r8188eu/core/rtw_led.c b/drivers/staging/r8188eu/core/rtw_led.c
new file mode 100644
index 000000000000..b33e34cce12e
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_led.c
@@ -0,0 +1,1612 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#include "../include/drv_types.h"
+#include "../include/rtw_led.h"
+
+/* */
+/* Description: */
+/* Callback function of LED BlinkTimer, */
+/* it just schedules to corresponding BlinkWorkItem/led_blink_hdl */
+/* */
+void BlinkTimerCallback(struct timer_list *t)
+{
+ struct LED_871x *pLed = from_timer(pLed, t, BlinkTimer);
+ struct adapter *padapter = pLed->padapter;
+
+ if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
+ return;
+
+ _set_workitem(&pLed->BlinkWorkItem);
+}
+
+/* */
+/* Description: */
+/* Callback function of LED BlinkWorkItem. */
+/* We dispatch acture LED blink action according to LedStrategy. */
+/* */
+void BlinkWorkItemCallback(struct work_struct *work)
+{
+ struct LED_871x *pLed = container_of(work, struct LED_871x, BlinkWorkItem);
+ BlinkHandler(pLed);
+}
+
+/* */
+/* Description: */
+/* Reset status of LED_871x object. */
+/* */
+void ResetLedStatus(struct LED_871x *pLed)
+{
+ pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */
+ pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */
+
+ pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */
+ pLed->bLedWPSBlinkInProgress = false;
+
+ pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */
+ pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
+
+ pLed->bLedNoLinkBlinkInProgress = false;
+ pLed->bLedLinkBlinkInProgress = false;
+ pLed->bLedStartToLinkBlinkInProgress = false;
+ pLed->bLedScanBlinkInProgress = false;
+}
+
+/*Description: */
+/* Initialize an LED_871x object. */
+void InitLed871x(struct adapter *padapter, struct LED_871x *pLed, enum LED_PIN_871x LedPin)
+{
+ pLed->padapter = padapter;
+ pLed->LedPin = LedPin;
+
+ ResetLedStatus(pLed);
+
+ timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0);
+ _init_workitem(&pLed->BlinkWorkItem, BlinkWorkItemCallback, pLed);
+}
+
+/* */
+/* Description: */
+/* DeInitialize an LED_871x object. */
+/* */
+void DeInitLed871x(struct LED_871x *pLed)
+{
+ _cancel_workitem_sync(&pLed->BlinkWorkItem);
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ ResetLedStatus(pLed);
+}
+
+/* */
+/* Description: */
+/* Implementation of LED blinking behavior. */
+/* It toggle off LED and schedule corresponding timer if necessary. */
+/* */
+
+static void SwLedBlink(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 bStopBlinking = false;
+
+ /* Change LED according to BlinkingLedState specified. */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ SwLedOn(padapter, pLed);
+ else
+ SwLedOff(padapter, pLed);
+
+ /* Determine if we shall change LED state again. */
+ pLed->BlinkTimes--;
+ switch (pLed->CurrLedState) {
+ case LED_BLINK_NORMAL:
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ break;
+ case LED_BLINK_StartToBlink:
+ if (check_fwstate(pmlmepriv, _FW_LINKED) && check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ bStopBlinking = true;
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
+ bStopBlinking = true;
+ else if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ break;
+ case LED_BLINK_WPS:
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ break;
+ default:
+ bStopBlinking = true;
+ break;
+ }
+
+ if (bStopBlinking) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED) && !pLed->bLedOn) {
+ SwLedOn(padapter, pLed);
+ } else if (check_fwstate(pmlmepriv, _FW_LINKED) && pLed->bLedOn) {
+ SwLedOff(padapter, pLed);
+ }
+ pLed->BlinkTimes = 0;
+ pLed->bLedBlinkInProgress = false;
+ } else {
+ /* Assign LED state to toggle. */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ /* Schedule a timer to toggle LED state. */
+ switch (pLed->CurrLedState) {
+ case LED_BLINK_NORMAL:
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ break;
+ case LED_BLINK_SLOWLY:
+ case LED_BLINK_StartToBlink:
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SLOWLY_INTERVAL);
+ break;
+ case LED_BLINK_WPS:
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_LONG_INTERVAL);
+ break;
+ default:
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SLOWLY_INTERVAL);
+ break;
+ }
+ }
+}
+
+static void SwLedBlink1(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 bStopBlinking = false;
+
+ /* Change LED according to BlinkingLedState specified. */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ SwLedOn(padapter, pLed);
+ else
+ SwLedOff(padapter, pLed);
+
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ ResetLedStatus(pLed);
+ return;
+ }
+
+ switch (pLed->CurrLedState) {
+ case LED_BLINK_SLOWLY:
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ break;
+ case LED_BLINK_NORMAL:
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_LINK_INTERVAL_ALPHA);
+ break;
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->bLedLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_LINK_INTERVAL_ALPHA);
+ } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ pLed->bLedScanBlinkInProgress = false;
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->bLedLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_LINK_INTERVAL_ALPHA);
+ } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ pLed->BlinkTimes = 0;
+ pLed->bLedBlinkInProgress = false;
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_BLINK_WPS:
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ break;
+ case LED_BLINK_WPS_STOP: /* WPS success */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ bStopBlinking = false;
+ else
+ bStopBlinking = true;
+
+ if (bStopBlinking) {
+ pLed->bLedLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_LINK_INTERVAL_ALPHA);
+
+ pLed->bLedWPSBlinkInProgress = false;
+ } else {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void SwLedBlink2(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 bStopBlinking = false;
+
+ /* Change LED according to BlinkingLedState specified. */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ SwLedOn(padapter, pLed);
+ else
+ SwLedOff(padapter, pLed);
+
+ switch (pLed->CurrLedState) {
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ SwLedOn(padapter, pLed);
+ } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ SwLedOff(padapter, pLed);
+ }
+ pLed->bLedScanBlinkInProgress = false;
+ } else {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ }
+ break;
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ SwLedOn(padapter, pLed);
+ } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ SwLedOff(padapter, pLed);
+ }
+ pLed->bLedBlinkInProgress = false;
+ } else {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void SwLedBlink3(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 bStopBlinking = false;
+
+ /* Change LED according to BlinkingLedState specified. */
+ if (pLed->BlinkingLedState == RTW_LED_ON) {
+ SwLedOn(padapter, pLed);
+ } else {
+ if (pLed->CurrLedState != LED_BLINK_WPS_STOP)
+ SwLedOff(padapter, pLed);
+ }
+
+ switch (pLed->CurrLedState) {
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if (!pLed->bLedOn)
+ SwLedOn(padapter, pLed);
+ } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if (pLed->bLedOn)
+ SwLedOff(padapter, pLed);
+ }
+ pLed->bLedScanBlinkInProgress = false;
+ } else {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ }
+ break;
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if (!pLed->bLedOn)
+ SwLedOn(padapter, pLed);
+ } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+
+ if (pLed->bLedOn)
+ SwLedOff(padapter, pLed);
+ }
+ pLed->bLedBlinkInProgress = false;
+ } else {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ }
+ break;
+ case LED_BLINK_WPS:
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ break;
+ case LED_BLINK_WPS_STOP: /* WPS success */
+ if (pLed->BlinkingLedState == RTW_LED_ON) {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+ bStopBlinking = false;
+ } else {
+ bStopBlinking = true;
+ }
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ SwLedOn(padapter, pLed);
+ }
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void SwLedBlink4(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct LED_871x *pLed1 = &ledpriv->SwLed1;
+ u8 bStopBlinking = false;
+
+ /* Change LED according to BlinkingLedState specified. */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ SwLedOn(padapter, pLed);
+ else
+ SwLedOff(padapter, pLed);
+
+ if (!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN) {
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ pLed1->CurrLedState = RTW_LED_OFF;
+ SwLedOff(padapter, pLed1);
+ }
+
+ switch (pLed->CurrLedState) {
+ case LED_BLINK_SLOWLY:
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ break;
+ case LED_BLINK_StartToBlink:
+ if (pLed->bLedOn) {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SLOWLY_INTERVAL);
+ } else {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ }
+ break;
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = false;
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
+ SwLedOff(padapter, pLed);
+ } else {
+ pLed->bLedNoLinkBlinkInProgress = false;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ pLed->bLedScanBlinkInProgress = false;
+ } else {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
+ SwLedOff(padapter, pLed);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ }
+ break;
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
+ SwLedOff(padapter, pLed);
+ } else {
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ pLed->bLedBlinkInProgress = false;
+ } else {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
+ SwLedOff(padapter, pLed);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ }
+ break;
+ case LED_BLINK_WPS:
+ if (pLed->bLedOn) {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SLOWLY_INTERVAL);
+ } else {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ }
+ break;
+ case LED_BLINK_WPS_STOP: /* WPS authentication fail */
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ break;
+ case LED_BLINK_WPS_STOP_OVERLAP: /* WPS session overlap */
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0) {
+ if (pLed->bLedOn)
+ pLed->BlinkTimes = 1;
+ else
+ bStopBlinking = true;
+ }
+
+ if (bStopBlinking) {
+ pLed->BlinkTimes = 10;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_LINK_INTERVAL_ALPHA);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void SwLedBlink5(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+ u8 bStopBlinking = false;
+
+ /* Change LED according to BlinkingLedState specified. */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ SwLedOn(padapter, pLed);
+ else
+ SwLedOff(padapter, pLed);
+
+ switch (pLed->CurrLedState) {
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if (pLed->bLedOn)
+ SwLedOff(padapter, pLed);
+ } else {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if (!pLed->bLedOn)
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+
+ pLed->bLedScanBlinkInProgress = false;
+ } else {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
+ SwLedOff(padapter, pLed);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ }
+ break;
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+
+ if (bStopBlinking) {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if (pLed->bLedOn)
+ SwLedOff(padapter, pLed);
+ } else {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if (!pLed->bLedOn)
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+
+ pLed->bLedBlinkInProgress = false;
+ } else {
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
+ SwLedOff(padapter, pLed);
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void SwLedBlink6(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+
+ /* Change LED according to BlinkingLedState specified. */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ SwLedOn(padapter, pLed);
+ else
+ SwLedOff(padapter, pLed);
+}
+
+ /* ALPHA, added by chiyoko, 20090106 */
+static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAction)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct LED_871x *pLed = &ledpriv->SwLed0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ switch (LedAction) {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_START_TO_LINK:
+ case LED_CTL_NO_LINK:
+ if (!pLed->bLedNoLinkBlinkInProgress) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_LINK:
+ if (!pLed->bLedLinkBlinkInProgress) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_LINK_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_SITE_SURVEY:
+ if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED))) {
+ ;
+ } else if (!pLed->bLedScanBlinkInProgress) {
+ if (IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedScanBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if (!pLed->bLedBlinkInProgress) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ pLed->bLedBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_START_WPS: /* wait until xinpin finish */
+ case LED_CTL_START_WPS_BOTTON:
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ pLed->bLedWPSBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_WPS;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_STOP_WPS:
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ if (pLed->bLedWPSBlinkInProgress)
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ else
+ pLed->bLedWPSBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_WPS_STOP;
+ if (pLed->bLedOn) {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+ } else {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+ break;
+ case LED_CTL_STOP_WPS_FAIL:
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ break;
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ SwLedOff(padapter, pLed);
+ break;
+ default:
+ break;
+ }
+}
+
+ /* Arcadyan/Sitecom , added by chiyoko, 20090216 */
+static void SwLedControlMode2(struct adapter *padapter, enum LED_CTL_MODE LedAction)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct LED_871x *pLed = &ledpriv->SwLed0;
+
+ switch (LedAction) {
+ case LED_CTL_SITE_SURVEY:
+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
+ } else if (!pLed->bLedScanBlinkInProgress) {
+ if (IS_LED_WPS_BLINKING(pLed))
+ return;
+
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedScanBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if ((!pLed->bLedBlinkInProgress) && (check_fwstate(pmlmepriv, _FW_LINKED))) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ return;
+ pLed->bLedBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_LINK:
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ _set_timer(&pLed->BlinkTimer, 0);
+ break;
+ case LED_CTL_START_WPS: /* wait until xinpin finish */
+ case LED_CTL_START_WPS_BOTTON:
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ pLed->bLedWPSBlinkInProgress = true;
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+ break;
+ case LED_CTL_STOP_WPS:
+ pLed->bLedWPSBlinkInProgress = false;
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+ break;
+ case LED_CTL_STOP_WPS_FAIL:
+ pLed->bLedWPSBlinkInProgress = false;
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ SwLedOff(padapter, pLed);
+ } else {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+ break;
+ case LED_CTL_START_TO_LINK:
+ case LED_CTL_NO_LINK:
+ if (!IS_LED_BLINKING(pLed)) {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+ break;
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+
+ _set_timer(&pLed->BlinkTimer, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+ /* COREGA, added by chiyoko, 20090316 */
+ static void SwLedControlMode3(struct adapter *padapter, enum LED_CTL_MODE LedAction)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct LED_871x *pLed = &ledpriv->SwLed0;
+
+ switch (LedAction) {
+ case LED_CTL_SITE_SURVEY:
+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
+ } else if (!pLed->bLedScanBlinkInProgress) {
+ if (IS_LED_WPS_BLINKING(pLed))
+ return;
+
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedScanBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if ((!pLed->bLedBlinkInProgress) && (check_fwstate(pmlmepriv, _FW_LINKED))) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ return;
+ pLed->bLedBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_LINK:
+ if (IS_LED_WPS_BLINKING(pLed))
+ return;
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+
+ _set_timer(&pLed->BlinkTimer, 0);
+ break;
+ case LED_CTL_START_WPS: /* wait until xinpin finish */
+ case LED_CTL_START_WPS_BOTTON:
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ pLed->bLedWPSBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_WPS;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_STOP_WPS:
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ } else {
+ pLed->bLedWPSBlinkInProgress = true;
+ }
+
+ pLed->CurrLedState = LED_BLINK_WPS_STOP;
+ if (pLed->bLedOn) {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+ } else {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+ break;
+ case LED_CTL_STOP_WPS_FAIL:
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, 0);
+ break;
+ case LED_CTL_START_TO_LINK:
+ case LED_CTL_NO_LINK:
+ if (!IS_LED_BLINKING(pLed)) {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+ break;
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+
+ _set_timer(&pLed->BlinkTimer, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+ /* Edimax-Belkin, added by chiyoko, 20090413 */
+static void SwLedControlMode4(struct adapter *padapter, enum LED_CTL_MODE LedAction)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct LED_871x *pLed = &ledpriv->SwLed0;
+ struct LED_871x *pLed1 = &ledpriv->SwLed1;
+
+ switch (LedAction) {
+ case LED_CTL_START_TO_LINK:
+ if (pLed1->bLedWPSBlinkInProgress) {
+ pLed1->bLedWPSBlinkInProgress = false;
+ _cancel_timer_ex(&pLed1->BlinkTimer);
+
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ pLed1->CurrLedState = RTW_LED_OFF;
+
+ if (pLed1->bLedOn)
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+
+ if (!pLed->bLedStartToLinkBlinkInProgress) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+
+ pLed->bLedStartToLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_StartToBlink;
+ if (pLed->bLedOn) {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SLOWLY_INTERVAL);
+ } else {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ }
+ }
+ break;
+ case LED_CTL_LINK:
+ case LED_CTL_NO_LINK:
+ /* LED1 settings */
+ if (LedAction == LED_CTL_LINK) {
+ if (pLed1->bLedWPSBlinkInProgress) {
+ pLed1->bLedWPSBlinkInProgress = false;
+ _cancel_timer_ex(&pLed1->BlinkTimer);
+
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ pLed1->CurrLedState = RTW_LED_OFF;
+
+ if (pLed1->bLedOn)
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+ }
+
+ if (!pLed->bLedNoLinkBlinkInProgress) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_SITE_SURVEY:
+ if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED))) {
+ } else if (!pLed->bLedScanBlinkInProgress) {
+ if (IS_LED_WPS_BLINKING(pLed))
+ return;
+
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedScanBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if (!pLed->bLedBlinkInProgress) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ pLed->bLedBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_START_WPS: /* wait until xinpin finish */
+ case LED_CTL_START_WPS_BOTTON:
+ if (pLed1->bLedWPSBlinkInProgress) {
+ pLed1->bLedWPSBlinkInProgress = false;
+ _cancel_timer_ex(&pLed1->BlinkTimer);
+
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ pLed1->CurrLedState = RTW_LED_OFF;
+
+ if (pLed1->bLedOn)
+ _set_timer(&pLed->BlinkTimer, 0);
+ }
+
+ if (!pLed->bLedWPSBlinkInProgress) {
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ pLed->bLedWPSBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_WPS;
+ if (pLed->bLedOn) {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SLOWLY_INTERVAL);
+ } else {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ }
+ }
+ break;
+ case LED_CTL_STOP_WPS: /* WPS connect success */
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+
+ break;
+ case LED_CTL_STOP_WPS_FAIL: /* WPS authentication fail */
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+
+ /* LED1 settings */
+ if (pLed1->bLedWPSBlinkInProgress)
+ _cancel_timer_ex(&pLed1->BlinkTimer);
+ else
+ pLed1->bLedWPSBlinkInProgress = true;
+ pLed1->CurrLedState = LED_BLINK_WPS_STOP;
+ if (pLed1->bLedOn)
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed1->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ break;
+ case LED_CTL_STOP_WPS_FAIL_OVERLAP: /* WPS session overlap */
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+
+ /* LED1 settings */
+ if (pLed1->bLedWPSBlinkInProgress)
+ _cancel_timer_ex(&pLed1->BlinkTimer);
+ else
+ pLed1->bLedWPSBlinkInProgress = true;
+ pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
+ pLed1->BlinkTimes = 10;
+ if (pLed1->bLedOn)
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed1->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_NORMAL_INTERVAL);
+ break;
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ if (pLed->bLedStartToLinkBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedStartToLinkBlinkInProgress = false;
+ }
+ if (pLed1->bLedWPSBlinkInProgress) {
+ _cancel_timer_ex(&pLed1->BlinkTimer);
+ pLed1->bLedWPSBlinkInProgress = false;
+ }
+ pLed1->BlinkingLedState = LED_UNKNOWN;
+ SwLedOff(padapter, pLed);
+ SwLedOff(padapter, pLed1);
+ break;
+ default:
+ break;
+ }
+}
+
+ /* Sercomm-Belkin, added by chiyoko, 20090415 */
+static void
+SwLedControlMode5(
+ struct adapter *padapter,
+ enum LED_CTL_MODE LedAction
+)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct LED_871x *pLed = &ledpriv->SwLed0;
+
+ switch (LedAction) {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_NO_LINK:
+ case LED_CTL_LINK: /* solid blue */
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ _set_timer(&pLed->BlinkTimer, 0);
+ break;
+ case LED_CTL_SITE_SURVEY:
+ if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED))) {
+ } else if (!pLed->bLedScanBlinkInProgress) {
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedScanBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if (!pLed->bLedBlinkInProgress) {
+ if (pLed->CurrLedState == LED_BLINK_SCAN)
+ return;
+ pLed->bLedBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed->BlinkTimer, LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+
+ if (pLed->bLedBlinkInProgress) {
+ _cancel_timer_ex(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ SwLedOff(padapter, pLed);
+ break;
+ default:
+ break;
+ }
+}
+
+ /* WNC-Corega, added by chiyoko, 20090902 */
+static void
+SwLedControlMode6(
+ struct adapter *padapter,
+ enum LED_CTL_MODE LedAction
+)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct LED_871x *pLed0 = &ledpriv->SwLed0;
+
+ switch (LedAction) {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_LINK:
+ case LED_CTL_NO_LINK:
+ _cancel_timer_ex(&pLed0->BlinkTimer);
+ pLed0->CurrLedState = RTW_LED_ON;
+ pLed0->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&pLed0->BlinkTimer, 0);
+ break;
+ case LED_CTL_POWER_OFF:
+ SwLedOff(padapter, pLed0);
+ break;
+ default:
+ break;
+ }
+}
+
+/* */
+/* Description: */
+/* Handler function of LED Blinking. */
+/* We dispatch acture LED blink action according to LedStrategy. */
+/* */
+void BlinkHandler(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+ struct led_priv *ledpriv = &padapter->ledpriv;
+
+ if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
+ return;
+
+ switch (ledpriv->LedStrategy) {
+ case SW_LED_MODE0:
+ SwLedBlink(pLed);
+ break;
+ case SW_LED_MODE1:
+ SwLedBlink1(pLed);
+ break;
+ case SW_LED_MODE2:
+ SwLedBlink2(pLed);
+ break;
+ case SW_LED_MODE3:
+ SwLedBlink3(pLed);
+ break;
+ case SW_LED_MODE4:
+ SwLedBlink4(pLed);
+ break;
+ case SW_LED_MODE5:
+ SwLedBlink5(pLed);
+ break;
+ case SW_LED_MODE6:
+ SwLedBlink6(pLed);
+ break;
+ default:
+ break;
+ }
+}
+
+void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct registry_priv *registry_par;
+
+ if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped) ||
+ (!padapter->hw_init_completed))
+ return;
+
+ if (!ledpriv->bRegUseLed)
+ return;
+
+ registry_par = &padapter->registrypriv;
+ if (!registry_par->led_enable)
+ return;
+
+ if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
+ padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
+ (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
+ LedAction == LED_CTL_SITE_SURVEY ||
+ LedAction == LED_CTL_LINK ||
+ LedAction == LED_CTL_NO_LINK ||
+ LedAction == LED_CTL_POWER_ON))
+ return;
+
+ switch (ledpriv->LedStrategy) {
+ case SW_LED_MODE0:
+ break;
+ case SW_LED_MODE1:
+ SwLedControlMode1(padapter, LedAction);
+ break;
+ case SW_LED_MODE2:
+ SwLedControlMode2(padapter, LedAction);
+ break;
+ case SW_LED_MODE3:
+ SwLedControlMode3(padapter, LedAction);
+ break;
+ case SW_LED_MODE4:
+ SwLedControlMode4(padapter, LedAction);
+ break;
+ case SW_LED_MODE5:
+ SwLedControlMode5(padapter, LedAction);
+ break;
+ case SW_LED_MODE6:
+ SwLedControlMode6(padapter, LedAction);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/r8188eu/core/rtw_mlme.c
index 71d205f3d73d..1115ff5d865a 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/r8188eu/core/rtw_mlme.c
@@ -1,50 +1,61 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTW_MLME_C_
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
-#include <linux/ieee80211.h>
+#define _RTW_MLME_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <xmit_osdep.h>
-#include <hal_intf.h>
-#include <mlme_osdep.h>
-#include <sta_info.h>
-#include <wifi.h>
-#include <wlan_bssdef.h>
-#include <rtw_ioctl_set.h>
-#include <linux/vmalloc.h>
-#include <linux/etherdevice.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/xmit_osdep.h"
+#include "../include/hal_intf.h"
+#include "../include/mlme_osdep.h"
+#include "../include/sta_info.h"
+#include "../include/wifi.h"
+#include "../include/wlan_bssdef.h"
+#include "../include/rtw_ioctl_set.h"
+#include "../include/usb_osintf.h"
+
+extern unsigned char MCS_rate_2R[16];
+extern unsigned char MCS_rate_1R[16];
+
+void rtw_set_roaming(struct adapter *adapter, u8 to_roaming)
+{
+ if (to_roaming == 0)
+ adapter->mlmepriv.to_join = false;
+ adapter->mlmepriv.to_roaming = to_roaming;
+}
-extern const u8 MCS_rate_1R[16];
+u8 rtw_to_roaming(struct adapter *adapter)
+{
+ return adapter->mlmepriv.to_roaming;
+}
-int rtw_init_mlme_priv(struct adapter *padapter)
+int _rtw_init_mlme_priv(struct adapter *padapter)
{
- int i;
- u8 *pbuf;
- struct wlan_network *pnetwork;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- int res = _SUCCESS;
+ int i;
+ u8 *pbuf;
+ struct wlan_network *pnetwork;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ int res = _SUCCESS;
/* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
+ pmlmepriv->nic_hdl = (u8 *)padapter;
+
pmlmepriv->pscanned = NULL;
pmlmepriv->fw_state = 0;
pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
- pmlmepriv->scan_mode = SCAN_ACTIVE;/* 1: active, 0: passive. Maybe someday we should rename this variable to "active_mode" (Jeff) */
+ pmlmepriv->scan_mode = SCAN_ACTIVE;/* 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
spin_lock_init(&pmlmepriv->lock);
_rtw_init_queue(&pmlmepriv->free_bss_pool);
_rtw_init_queue(&pmlmepriv->scanned_queue);
+ set_scanned_network_val(pmlmepriv, 0);
+
memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
- pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network)));
+ pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
if (!pbuf) {
res = _FAIL;
@@ -69,9 +80,14 @@ int rtw_init_mlme_priv(struct adapter *padapter)
rtw_init_mlme_timer(padapter);
exit:
+
return res;
}
+static void rtw_mfree_mlme_priv_lock(struct mlme_priv *pmlmepriv)
+{
+}
+
#if defined(CONFIG_88EU_AP_MODE)
static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
{
@@ -82,12 +98,18 @@ static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
{
- rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
- rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
+ kfree(pmlmepriv->assoc_req);
+ kfree(pmlmepriv->assoc_rsp);
rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
+
+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
}
#else
void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
@@ -95,25 +117,70 @@ void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
}
#endif
-void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
+void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
{
+
+ rtw_free_mlme_priv_ie_data(pmlmepriv);
+
if (pmlmepriv) {
- rtw_free_mlme_priv_ie_data(pmlmepriv);
+ rtw_mfree_mlme_priv_lock(pmlmepriv);
+
vfree(pmlmepriv->free_bss_buf);
}
+
+}
+
+int _rtw_enqueue_network(struct __queue *queue, struct wlan_network *pnetwork)
+{
+
+ if (!pnetwork)
+ goto exit;
+
+ spin_lock_bh(&queue->lock);
+
+ list_add_tail(&pnetwork->list, &queue->queue);
+
+ spin_unlock_bh(&queue->lock);
+
+exit:
+
+ return _SUCCESS;
}
-struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
- /* _queue *free_queue) */
+struct wlan_network *_rtw_dequeue_network(struct __queue *queue)
{
struct wlan_network *pnetwork;
+
+ spin_lock_bh(&queue->lock);
+
+ if (list_empty(&queue->queue)) {
+ pnetwork = NULL;
+ } else {
+ pnetwork = container_of((&queue->queue)->next, struct wlan_network, list);
+
+ list_del_init(&pnetwork->list);
+ }
+
+ spin_unlock_bh(&queue->lock);
+
+ return pnetwork;
+}
+
+struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv)/* _queue *free_queue) */
+{
+ struct wlan_network *pnetwork;
struct __queue *free_queue = &pmlmepriv->free_bss_pool;
+ struct list_head *plist = NULL;
spin_lock_bh(&free_queue->lock);
- pnetwork = list_first_entry_or_null(&free_queue->queue,
- struct wlan_network, list);
- if (!pnetwork)
+
+ if (list_empty(&free_queue->queue)) {
+ pnetwork = NULL;
goto exit;
+ }
+ plist = (&free_queue->queue)->next;
+
+ pnetwork = container_of(plist, struct wlan_network, list);
list_del_init(&pnetwork->list);
@@ -123,16 +190,17 @@ struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
pnetwork->aid = 0;
pnetwork->join_res = 0;
+ pmlmepriv->num_of_scanned++;
+
exit:
spin_unlock_bh(&free_queue->lock);
return pnetwork;
}
-static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
+void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
{
- unsigned long curr_time;
- u32 delta_time;
+ u32 curr_time, delta_time;
u32 lifetime = SCANQUEUE_LIFETIME;
struct __queue *free_queue = &pmlmepriv->free_bss_pool;
@@ -153,11 +221,11 @@ static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *
spin_lock_bh(&free_queue->lock);
list_del_init(&pnetwork->list);
list_add_tail(&pnetwork->list, &free_queue->queue);
+ pmlmepriv->num_of_scanned--;
spin_unlock_bh(&free_queue->lock);
}
-static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
- struct wlan_network *pnetwork)
+void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
{
struct __queue *free_queue = &pmlmepriv->free_bss_pool;
@@ -167,48 +235,61 @@ static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
return;
list_del_init(&pnetwork->list);
list_add_tail(&pnetwork->list, get_list_head(free_queue));
+ pmlmepriv->num_of_scanned--;
}
/*
- * return the wlan_network with the matching addr
- *
- * Shall be called under atomic context... to avoid possible racing condition...
- */
-struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
+ return the wlan_network with the matching addr
+
+ Shall be calle under atomic context... to avoid possible racing condition...
+*/
+struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr)
{
struct list_head *phead, *plist;
- struct wlan_network *pnetwork = NULL;
+ struct wlan_network *pnetwork = NULL;
+ u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
- if (is_zero_ether_addr(addr)) {
+ if (!memcmp(zero_addr, addr, ETH_ALEN)) {
pnetwork = NULL;
goto exit;
}
phead = get_list_head(scanned_queue);
- list_for_each(plist, phead) {
- pnetwork = list_entry(plist, struct wlan_network, list);
+ plist = phead->next;
+
+ while (plist != phead) {
+ pnetwork = container_of(plist, struct wlan_network, list);
if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
break;
+ plist = plist->next;
}
if (plist == phead)
pnetwork = NULL;
exit:
+
return pnetwork;
}
-void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
+void _rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
{
- struct list_head *phead;
- struct wlan_network *pnetwork, *temp;
+ struct list_head *phead, *plist;
+ struct wlan_network *pnetwork;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
spin_lock_bh(&scanned_queue->lock);
phead = get_list_head(scanned_queue);
- list_for_each_entry_safe(pnetwork, temp, phead, list)
- _rtw_free_network(pmlmepriv, pnetwork, isfreeall);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ plist = plist->next;
+ _rtw_free_network(pmlmepriv, pnetwork, isfreeall);
+ }
spin_unlock_bh(&scanned_queue->lock);
+
}
int rtw_if_up(struct adapter *padapter)
@@ -220,12 +301,13 @@ int rtw_if_up(struct adapter *padapter)
res = false;
else
res = true;
+
return res;
}
void rtw_generate_random_ibss(u8 *pibss)
{
- unsigned long curtime = jiffies;
+ u32 curtime = jiffies;
pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
pibss[1] = 0x11;
@@ -242,18 +324,73 @@ u8 *rtw_get_capability_from_ie(u8 *ie)
u16 rtw_get_capability(struct wlan_bssid_ex *bss)
{
- __le16 val;
+ __le16 val;
- memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->ies), 2);
+ memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->IEs), 2);
return le16_to_cpu(val);
}
+u8 *rtw_get_timestampe_from_ie(u8 *ie)
+{
+ return ie + 0;
+}
+
u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
{
return ie + 8;
}
+int rtw_init_mlme_priv(struct adapter *padapter)/* struct mlme_priv *pmlmepriv) */
+{
+ int res;
+
+ res = _rtw_init_mlme_priv(padapter);/* (pmlmepriv); */
+
+ return res;
+}
+
+void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
+{
+ _rtw_free_mlme_priv(pmlmepriv);
+}
+
+static struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
+{
+ struct wlan_network *pnetwork;
+
+ pnetwork = _rtw_alloc_network(pmlmepriv);
+
+ return pnetwork;
+}
+
+static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
+ struct wlan_network *pnetwork)
+{
+
+ _rtw_free_network_nolock(pmlmepriv, pnetwork);
+
+}
+
+void rtw_free_network_queue(struct adapter *dev, u8 isfreeall)
+{
+
+ _rtw_free_network_queue(dev, isfreeall);
+
+}
+
+/*
+ return the wlan_network with the matching addr
+
+ Shall be calle under atomic context... to avoid possible racing condition...
+*/
+struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
+{
+ struct wlan_network *pnetwork = _rtw_find_network(scanned_queue, addr);
+
+ return pnetwork;
+}
+
int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
{
int ret = true;
@@ -272,8 +409,8 @@ int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
static int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
{
- return (a->ssid.ssid_length == b->ssid.ssid_length) &&
- !memcmp(a->ssid.ssid, b->ssid.ssid, a->ssid.ssid_length);
+ return (a->Ssid.SsidLength == b->Ssid.SsidLength) &&
+ !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength);
}
int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
@@ -281,42 +418,50 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
u16 s_cap, d_cap;
__le16 le_scap, le_dcap;
- memcpy((u8 *)&le_scap, rtw_get_capability_from_ie(src->ies), 2);
- memcpy((u8 *)&le_dcap, rtw_get_capability_from_ie(dst->ies), 2);
+ memcpy((u8 *)&le_scap, rtw_get_capability_from_ie(src->IEs), 2);
+ memcpy((u8 *)&le_dcap, rtw_get_capability_from_ie(dst->IEs), 2);
s_cap = le16_to_cpu(le_scap);
d_cap = le16_to_cpu(le_dcap);
- return ((src->ssid.ssid_length == dst->ssid.ssid_length) &&
- (!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) &&
- (!memcmp(src->ssid.ssid, dst->ssid.ssid, src->ssid.ssid_length)) &&
+ return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
+ ((!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN))) &&
+ ((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength))) &&
((s_cap & WLAN_CAPABILITY_IBSS) ==
(d_cap & WLAN_CAPABILITY_IBSS)) &&
- ((s_cap & WLAN_CAPABILITY_ESS) ==
- (d_cap & WLAN_CAPABILITY_ESS)));
+ ((s_cap & WLAN_CAPABILITY_BSS) ==
+ (d_cap & WLAN_CAPABILITY_BSS)));
}
-struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
+struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
{
struct list_head *plist, *phead;
- struct wlan_network *pwlan = NULL;
- struct wlan_network *oldest = NULL;
+ struct wlan_network *pwlan = NULL;
+ struct wlan_network *oldest = NULL;
phead = get_list_head(scanned_queue);
- for (plist = phead->next; plist != phead; plist = plist->next) {
+ plist = phead->next;
+
+ while (1) {
+ if (phead == plist)
+ break;
+
pwlan = container_of(plist, struct wlan_network, list);
if (!pwlan->fixed) {
if (!oldest || time_after(oldest->last_scanned, pwlan->last_scanned))
oldest = pwlan;
}
+
+ plist = plist->next;
}
+
return oldest;
}
void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
- struct adapter *padapter, bool update_ie)
+ struct adapter *padapter, bool update_ie)
{
long rssi_ori = dst->Rssi;
u8 sq_smp = src->PhyInfo.SignalQuality;
@@ -327,82 +472,86 @@ void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
rtw_hal_antdiv_rssi_compared(padapter, dst, src); /* this will update src.Rssi, need consider again */
/* The rule below is 1/5 for sample value, 4/5 for history value */
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
- is_same_network(&padapter->mlmepriv.cur_network.network, src)) {
+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&padapter->mlmepriv.cur_network.network, src)) {
/* Take the recvpriv's value for the connected AP*/
ss_final = padapter->recvpriv.signal_strength;
sq_final = padapter->recvpriv.signal_qual;
/* the rssi value here is undecorated, and will be used for antenna diversity */
if (sq_smp != 101) /* from the right channel */
- rssi_final = (src->Rssi + dst->Rssi * 4) / 5;
+ rssi_final = dst->Rssi; //(src->Rssi+dst->Rssi*4)/5;
else
rssi_final = rssi_ori;
} else {
- if (sq_smp != 101) { /* from the right channel */
- ss_final = ((u32)(src->PhyInfo.SignalStrength) + (u32)(dst->PhyInfo.SignalStrength) * 4) / 5;
- sq_final = ((u32)(src->PhyInfo.SignalQuality) + (u32)(dst->PhyInfo.SignalQuality) * 4) / 5;
- rssi_final = (src->Rssi + dst->Rssi * 4) / 5;
- } else {
- /* bss info not receiving from the right channel, use the original RX signal infos */
- ss_final = dst->PhyInfo.SignalStrength;
- sq_final = dst->PhyInfo.SignalQuality;
- rssi_final = dst->Rssi;
- }
+// if (sq_smp != 101) { /* from the right channel */
+ ss_final = (u32)dst->PhyInfo.SignalStrength; //((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
+ sq_final = (u32)dst->PhyInfo.SignalQuality; //((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
+ rssi_final = dst->Rssi; //(src->Rssi+dst->Rssi*4)/5;
+// } else {
+// /* bss info not receiving from the right channel, use the original RX signal infos */
+// ss_final = dst->PhyInfo.SignalStrength;
+// sq_final = dst->PhyInfo.SignalQuality;
+// rssi_final = dst->Rssi;
+// }
}
- if (update_ie)
+ if (update_ie) {
+ dst->Reserved[0] = src->Reserved[0];
+ dst->Reserved[1] = src->Reserved[1];
memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
+ }
dst->PhyInfo.SignalStrength = ss_final;
dst->PhyInfo.SignalQuality = sq_final;
dst->Rssi = rssi_final;
+
}
static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
{
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
if (check_fwstate(pmlmepriv, _FW_LINKED) &&
is_same_network(&pmlmepriv->cur_network.network, pnetwork)) {
update_network(&pmlmepriv->cur_network.network, pnetwork, adapter, true);
- rtw_update_protection(adapter, (pmlmepriv->cur_network.network.ies) + sizeof(struct ndis_802_11_fixed_ie),
- pmlmepriv->cur_network.network.ie_length);
+ rtw_update_protection(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof(struct ndis_802_11_fixed_ie),
+ pmlmepriv->cur_network.network.IELength);
}
+
}
/*
- * Caller must hold pmlmepriv->lock first.
- */
+Caller must hold pmlmepriv->lock first.
+*/
void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target)
{
struct list_head *plist, *phead;
- u32 bssid_ex_sz;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- struct wlan_network *oldest = NULL;
+ u32 bssid_ex_sz;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ struct wlan_network *oldest = NULL;
spin_lock_bh(&queue->lock);
phead = get_list_head(queue);
- list_for_each(plist, phead) {
- pnetwork = list_entry(plist, struct wlan_network, list);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
if (is_same_network(&pnetwork->network, target))
break;
if ((oldest == ((struct wlan_network *)0)) ||
time_after(oldest->last_scanned, pnetwork->last_scanned))
oldest = pnetwork;
+ plist = plist->next;
}
/* If we didn't find a match, then get a new network slot to initialize
- * with this beacon's information
- */
+ * with this beacon's information */
if (phead == plist) {
if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
/* If there are no more slots, expire the oldest */
pnetwork = oldest;
- rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA,
- &target->PhyInfo.Optimum_antenna);
- memcpy(&pnetwork->network, target,
- get_wlan_bssid_ex_sz(target));
+ rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &target->PhyInfo.Optimum_antenna);
+ memcpy(&pnetwork->network, target, get_wlan_bssid_ex_sz(target));
/* variable initialize */
pnetwork->fixed = false;
pnetwork->last_scanned = jiffies;
@@ -424,8 +573,7 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
bssid_ex_sz = get_wlan_bssid_ex_sz(target);
target->Length = bssid_ex_sz;
- rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA,
- &target->PhyInfo.Optimum_antenna);
+ rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &target->PhyInfo.Optimum_antenna);
memcpy(&pnetwork->network, target, bssid_ex_sz);
pnetwork->last_scanned = jiffies;
@@ -436,40 +584,47 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
list_add_tail(&pnetwork->list, &queue->queue);
}
} else {
- /* we have an entry and we are going to update it. But this
- * entry may be already expired. In this case we do the same
- * as we found a new net and call the new_net handler
+ /* we have an entry and we are going to update it. But this entry may
+ * be already expired. In this case we do the same as we found a new
+ * net and call the new_net handler
*/
bool update_ie = true;
pnetwork->last_scanned = jiffies;
/* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
- if ((pnetwork->network.ie_length > target->ie_length) && (target->Reserved[0] == 1))
+ /* probe resp(3) > beacon(1) > probe req(2) */
+ if ((target->Reserved[0] != 2) &&
+ (target->Reserved[0] >= pnetwork->network.Reserved[0]))
+ update_ie = true;
+ else
update_ie = false;
-
update_network(&pnetwork->network, target, adapter, update_ie);
}
exit:
spin_unlock_bh(&queue->lock);
+
}
static void rtw_add_network(struct adapter *adapter,
struct wlan_bssid_ex *pnetwork)
{
+
+#if defined(CONFIG_88EU_P2P)
+ rtw_wlan_bssid_ex_remove_p2p_attr(pnetwork, P2P_ATTR_GROUP_INFO);
+#endif
update_current_network(adapter, pnetwork);
rtw_update_scanned_network(adapter, pnetwork);
+
}
-/*
- * select the desired network based on the capability of the (i)bss.
- * check items: (1) security
- * (2) network_type
- * (3) WMM
- * (4) HT
- * (5) others
- */
+/* select the desired network based on the capability of the (i)bss. */
+/* check items: (1) security */
+/* (2) network_type */
+/* (3) WMM */
+/* (4) HT */
+/* (5) others */
static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork)
{
struct security_priv *psecuritypriv = &adapter->securitypriv;
@@ -486,18 +641,33 @@ static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *
privacy = pnetwork->network.Privacy;
if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
- if (rtw_get_wps_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, pnetwork->network.ie_length - _FIXED_IE_LENGTH_, NULL, &wps_ielen))
+ if (rtw_get_wps_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, pnetwork->network.IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen))
return true;
else
return false;
}
if (adapter->registrypriv.wifi_spec == 1) { /* for correct flow of 8021X to do.... */
+ u8 *p = NULL;
+ uint ie_len = 0;
+
if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
bselected = false;
+ if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
+ p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_,
+ _RSN_IE_2_, &ie_len,
+ (pnetwork->network.IELength -
+ _BEACON_IE_OFFSET_));
+ if (p && ie_len > 0)
+ bselected = true;
+ else
+ bselected = false;
+ }
}
- if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0))
+ if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
+ DBG_88E("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
bselected = false;
+ }
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
@@ -511,7 +681,7 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
{
u32 len;
struct wlan_bssid_ex *pnetwork;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
pnetwork = (struct wlan_bssid_ex *)pbuf;
@@ -525,11 +695,11 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, pnetwork->MacAddress, ETH_ALEN)) {
struct wlan_network *ibss_wlan = NULL;
- memcpy(pmlmepriv->cur_network.network.ies, pnetwork->ies, 8);
+ memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
spin_lock_bh(&pmlmepriv->scanned_queue.lock);
ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->MacAddress);
if (ibss_wlan) {
- memcpy(ibss_wlan->network.ies, pnetwork->ies, 8);
+ memcpy(ibss_wlan->network.IEs, pnetwork->IEs, 8);
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
goto exit;
}
@@ -539,18 +709,20 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
/* lock pmlmepriv->lock when you accessing network_q */
if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
- if (pnetwork->ssid.ssid[0] == 0)
- pnetwork->ssid.ssid_length = 0;
+ if (pnetwork->Ssid.Ssid[0] == 0)
+ pnetwork->Ssid.SsidLength = 0;
rtw_add_network(adapter, pnetwork);
}
exit:
+
spin_unlock_bh(&pmlmepriv->lock);
}
void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
{
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ u8 timer_cancelled = 0;
spin_lock_bh(&pmlmepriv->lock);
@@ -561,10 +733,17 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
}
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
- del_timer_sync(&pmlmepriv->scan_to_timer);
+ timer_cancelled = 1;
+
_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
}
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ if (timer_cancelled)
+ _cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled);
+
+ spin_lock_bh(&pmlmepriv->lock);
rtw_set_signal_stat_timer(&adapter->recvpriv);
if (pmlmepriv->to_join) {
@@ -573,15 +752,15 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+ _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
} else {
- struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network;
+ struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network;
u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
- memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+ memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
rtw_update_registrypriv_dev_network(adapter);
rtw_generate_random_ibss(pibss);
@@ -594,26 +773,28 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
}
} else {
int s_ret;
-
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
pmlmepriv->to_join = false;
s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
- if (s_ret == _SUCCESS) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+ if (_SUCCESS == s_ret) {
+ _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
} else if (s_ret == 2) { /* there is no need to wait for join */
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
rtw_indicate_connect(adapter);
} else {
- if (pmlmepriv->to_roaming != 0) {
+ DBG_88E("try_to_join, but select scanning queue fail, to_roaming:%d\n",
+ pmlmepriv->to_roaming);
+ if (rtw_to_roaming(adapter) != 0) {
if (--pmlmepriv->to_roaming == 0 ||
- rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0) != _SUCCESS) {
- pmlmepriv->to_roaming = 0;
- rtw_free_assoc_resources(adapter);
+ _SUCCESS != rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) {
+ rtw_set_roaming(adapter, 0);
+ rtw_free_assoc_resources(adapter, 1);
rtw_indicate_disconnect(adapter);
} else {
pmlmepriv->to_join = true;
}
+ } else {
+ rtw_indicate_disconnect(adapter);
}
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
}
@@ -624,6 +805,9 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
spin_unlock_bh(&pmlmepriv->lock);
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ p2p_ps_wk_cmd(adapter, P2P_PS_SCAN_DONE, 0);
+
rtw_os_xmit_schedule(adapter);
}
@@ -652,6 +836,7 @@ static void free_scanqueue(struct mlme_priv *pmlmepriv)
list_del_init(plist);
list_add_tail(plist, &free_queue->queue);
plist = ptemp;
+ pmlmepriv->num_of_scanned--;
}
spin_unlock_bh(&free_queue->lock);
@@ -659,25 +844,13 @@ static void free_scanqueue(struct mlme_priv *pmlmepriv)
}
/*
- * rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
- */
-void rtw_free_assoc_resources(struct adapter *adapter)
-{
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- spin_lock_bh(&pmlmepriv->scanned_queue.lock);
- rtw_free_assoc_resources_locked(adapter);
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-}
-
-/*
- * rtw_free_assoc_resources_locked: the caller has to lock pmlmepriv->lock
- */
-void rtw_free_assoc_resources_locked(struct adapter *adapter)
+*rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
+*/
+void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
{
struct wlan_network *pwlan = NULL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct sta_priv *pstapriv = &adapter->stapriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct sta_priv *pstapriv = &adapter->stapriv;
struct wlan_network *tgt_network = &pmlmepriv->cur_network;
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
@@ -703,6 +876,9 @@ void rtw_free_assoc_resources_locked(struct adapter *adapter)
rtw_init_bcmc_stainfo(adapter);
}
+ if (lock_scanned_queue)
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
if (pwlan)
pwlan->fixed = false;
@@ -710,22 +886,25 @@ void rtw_free_assoc_resources_locked(struct adapter *adapter)
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1)))
rtw_free_network_nolock(pmlmepriv, pwlan);
+ if (lock_scanned_queue)
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
pmlmepriv->key_mask = 0;
+
}
/*
- * rtw_indicate_connect: the caller has to lock pmlmepriv->lock
- */
+*rtw_indicate_connect: the caller has to lock pmlmepriv->lock
+*/
void rtw_indicate_connect(struct adapter *padapter)
{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
pmlmepriv->to_join = false;
if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
set_fwstate(pmlmepriv, _FW_LINKED);
- led_control_8188eu(padapter, LED_CTL_LINK);
+ rtw_led_control(padapter, LED_CTL_LINK);
rtw_os_indicate_connect(padapter);
}
@@ -736,11 +915,11 @@ void rtw_indicate_connect(struct adapter *padapter)
}
/*
- * rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
- */
+*rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
+*/
void rtw_indicate_disconnect(struct adapter *padapter)
{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS);
@@ -752,16 +931,41 @@ void rtw_indicate_disconnect(struct adapter *padapter)
rtw_os_indicate_disconnect(padapter);
_clr_fwstate_(pmlmepriv, _FW_LINKED);
- led_control_8188eu(padapter, LED_CTL_NO_LINK);
+ rtw_led_control(padapter, LED_CTL_NO_LINK);
rtw_clear_scan_deny(padapter);
}
+ p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
+
}
inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
{
- indicate_wx_scan_complete_event(padapter);
+ rtw_os_indicate_scan_done(padapter, aborted);
+}
+
+void rtw_scan_abort(struct adapter *adapter)
+{
+ u32 start;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+
+ start = jiffies;
+ pmlmeext->scan_abort = true;
+ while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
+ rtw_get_passing_time_ms(start) <= 200) {
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
+ break;
+ DBG_88E(FUNC_NDEV_FMT"fw_state=_FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
+ msleep(20);
+ }
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
+ if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
+ DBG_88E(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
+ rtw_indicate_scan_done(adapter, true);
+ }
+ pmlmeext->scan_abort = false;
}
static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork)
@@ -776,6 +980,7 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
if (psta) { /* update ptarget_sta */
+ DBG_88E("%s\n", __func__);
psta->aid = pnetwork->join_res;
psta->mac_id = 0;
/* sta mode */
@@ -793,12 +998,9 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
}
- /*
- * Commented by Albert 2012/07/21
- * When doing the WPS, the wps_ie_len won't equal to 0
- * And the Wi-Fi driver shouldn't allow the data
- * packet to be transmitted.
- */
+ /* Commented by Albert 2012/07/21 */
+ /* When doing the WPS, the wps_ie_len won't equal to 0 */
+ /* And the Wi-Fi driver shouldn't allow the data packet to be tramsmitted. */
if (padapter->securitypriv.wps_ie_len != 0) {
psta->ieee8021x_blocked = true;
padapter->securitypriv.wps_ie_len = 0;
@@ -835,14 +1037,16 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
/* ptarget_wlan: found from scanned_queue */
static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network *pnetwork)
{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+
+ DBG_88E("%s\n", __func__);
/* why not use ptarget_wlan?? */
memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
- /* some ies in pnetwork is wrong, so we should use ptarget_wlan ies */
- cur_network->network.ie_length = ptarget_wlan->network.ie_length;
- memcpy(&cur_network->network.ies[0], &ptarget_wlan->network.ies[0], MAX_IE_SZ);
+ /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
+ cur_network->network.IELength = ptarget_wlan->network.IELength;
+ memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
cur_network->aid = pnetwork->join_res;
@@ -869,10 +1073,10 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
break;
}
- rtw_update_protection(padapter, (cur_network->network.ies) +
+ rtw_update_protection(padapter, (cur_network->network.IEs) +
sizeof(struct ndis_802_11_fixed_ie),
- (cur_network->network.ie_length));
- rtw_update_ht_cap(padapter, cur_network->network.ies, cur_network->network.ie_length);
+ (cur_network->network.IELength));
+ rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength);
}
/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
@@ -884,13 +1088,14 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
{
+ u8 timer_cancelled;
struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
- struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
- unsigned int the_same_macaddr = false;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
+ unsigned int the_same_macaddr = false;
rtw_get_encrypt_decrypt_from_registrypriv(adapter);
@@ -954,11 +1159,12 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
/* s4. indicate connect */
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ pmlmepriv->cur_network_scanned = ptarget_wlan;
rtw_indicate_connect(adapter);
}
- /* s5. Cancel assoc_timer */
- del_timer_sync(&pmlmepriv->assoc_timer);
+ /* s5. Cancle assoc_timer */
+ _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
} else {
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
goto ignore_joinbss_callback;
@@ -968,14 +1174,12 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
} else if (pnetwork->join_res == -4) {
rtw_reset_securitypriv(adapter);
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(1));
+ _set_timer(&pmlmepriv->assoc_timer, 1);
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
} else { /* if join_res < 0 (join fails), then try again */
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(1));
+ _set_timer(&pmlmepriv->assoc_timer, 1);
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
}
@@ -985,11 +1189,12 @@ ignore_joinbss_callback:
void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf)
{
- struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
+ struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
mlmeext_joinbss_event_callback(adapter, pnetwork->join_res);
rtw_os_xmit_schedule(adapter);
+
}
static u8 search_max_mac_id(struct adapter *padapter)
@@ -1001,11 +1206,11 @@ static u8 search_max_mac_id(struct adapter *padapter)
struct sta_priv *pstapriv = &padapter->stapriv;
#endif
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
#if defined(CONFIG_88EU_AP_MODE)
if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- for (aid = pstapriv->max_num_sta; aid > 0; aid--) {
+ for (aid = (pstapriv->max_num_sta); aid > 0; aid--) {
if (pstapriv->sta_aid[aid - 1])
break;
}
@@ -1013,7 +1218,7 @@ static u8 search_max_mac_id(struct adapter *padapter)
} else
#endif
{/* adhoc id = 31~2 */
- for (mac_id = NUM_STA - 1; mac_id >= IBSS_START_MAC_ID; mac_id--) {
+ for (mac_id = (NUM_STA - 1); mac_id >= IBSS_START_MAC_ID; mac_id--) {
if (pmlmeinfo->FW_sta_info[mac_id].status == 1)
break;
}
@@ -1022,9 +1227,10 @@ static u8 search_max_mac_id(struct adapter *padapter)
}
/* FOR AP , AD-HOC mode */
-void rtw_stassoc_hw_rpt(struct adapter *adapter, struct sta_info *psta)
+void rtw_sta_media_status_rpt(struct adapter *adapter, struct sta_info *psta,
+ u32 mstatus)
{
- u16 media_status;
+ u16 media_status_rpt;
u8 macid;
if (!psta)
@@ -1032,17 +1238,19 @@ void rtw_stassoc_hw_rpt(struct adapter *adapter, struct sta_info *psta)
macid = search_max_mac_id(adapter);
rtw_hal_set_hwreg(adapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&macid);
- media_status = (psta->mac_id << 8) | 1; /* MACID|OPMODE:1 connect */
- rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
+ /* MACID|OPMODE:1 connect */
+ media_status_rpt = (u16)((psta->mac_id << 8) | mstatus);
+ rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT,
+ (u8 *)&media_status_rpt);
}
void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
{
struct sta_info *psta;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
- struct wlan_network *ptarget_wlan = NULL;
+ struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct wlan_network *ptarget_wlan = NULL;
if (!rtw_access_ctrl(adapter, pstassoc->macaddr))
return;
@@ -1050,10 +1258,8 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
#if defined(CONFIG_88EU_AP_MODE)
if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
- if (psta) {
- ap_sta_info_defer_update(adapter, psta);
- rtw_stassoc_hw_rpt(adapter, psta);
- }
+ if (psta)
+ rtw_indicate_sta_assoc_event(adapter, psta);
return;
}
#endif
@@ -1065,13 +1271,13 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
if (!psta)
return;
-
/* to do: init sta_info variable */
psta->qos_option = 0;
psta->mac_id = (uint)pstassoc->cam_id;
+ DBG_88E("%s\n", __func__);
/* for ad-hoc mode */
rtw_hal_set_odm_var(adapter, HAL_ODM_STA_INFO, psta, true);
- rtw_stassoc_hw_rpt(adapter, psta);
+ rtw_sta_media_status_rpt(adapter, psta, 1);
if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
psta->ieee8021x_blocked = false;
@@ -1081,6 +1287,7 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
if (adapter->stapriv.asoc_sta_count == 2) {
spin_lock_bh(&pmlmepriv->scanned_queue.lock);
ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+ pmlmepriv->cur_network_scanned = ptarget_wlan;
if (ptarget_wlan)
ptarget_wlan->fixed = true;
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
@@ -1099,9 +1306,9 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
struct wlan_network *pwlan = NULL;
struct wlan_bssid_ex *pdev_network = NULL;
u8 *pibss = NULL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct stadel_event *pstadel = (struct stadel_event *)pbuf;
- struct sta_priv *pstapriv = &adapter->stapriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct stadel_event *pstadel = (struct stadel_event *)pbuf;
+ struct sta_priv *pstapriv = &adapter->stapriv;
struct wlan_network *tgt_network = &pmlmepriv->cur_network;
psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
@@ -1110,9 +1317,10 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
else
mac_id = pstadel->mac_id;
+ DBG_88E("%s(mac_id=%d)=%pM\n", __func__, mac_id, pstadel->macaddr);
+
if (mac_id >= 0) {
u16 media_status;
-
media_status = (mac_id << 8) | 0; /* MACID|OPMODE:0 means disconnect */
/* for STA, AP, ADHOC mode, report disconnect stauts to FW */
rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
@@ -1126,17 +1334,20 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
spin_lock_bh(&pmlmepriv->lock);
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- if (pmlmepriv->to_roaming > 0)
- pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */
- else if (pmlmepriv->to_roaming == 0)
- pmlmepriv->to_roaming = adapter->registrypriv.max_roaming_times;
+ if (adapter->registrypriv.wifi_spec == 1)
+ rtw_set_roaming(adapter, 0); /* don't roam */
+ else if (rtw_to_roaming(adapter) > 0)
+ pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */
+ else if (rtw_to_roaming(adapter) == 0)
+ rtw_set_roaming(adapter,
+ adapter->registrypriv.max_roaming_times);
if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK)
- pmlmepriv->to_roaming = 0; /* don't roam */
+ rtw_set_roaming(adapter, 0); /* don't roam */
rtw_free_uc_swdec_pending_queue(adapter);
- rtw_free_assoc_resources(adapter);
+ rtw_free_assoc_resources(adapter, 1);
rtw_indicate_disconnect(adapter);
spin_lock_bh(&pmlmepriv->scanned_queue.lock);
/* remove the network entry in scanned_queue */
@@ -1169,7 +1380,8 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
- memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+ memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
rtw_update_registrypriv_dev_network(adapter);
@@ -1184,52 +1396,59 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
}
}
spin_unlock_bh(&pmlmepriv->lock);
+
}
/*
- * _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss
- * @adapter: pointer to struct adapter structure
- */
-void _rtw_join_timeout_handler (struct timer_list *t)
+* _rtw_join_timeout_handler - Timeout/faliure handler for CMD JoinBss
+* @adapter: pointer to struct adapter structure
+*/
+void _rtw_join_timeout_handler (struct adapter *adapter)
{
- struct adapter *adapter = from_timer(adapter, t, mlmepriv.assoc_timer);
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
int do_join_r;
+ DBG_88E("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
+
if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
return;
spin_lock_bh(&pmlmepriv->lock);
- if (pmlmepriv->to_roaming > 0) { /* join timeout caused by roaming */
+ if (rtw_to_roaming(adapter) > 0) { /* join timeout caused by roaming */
while (1) {
pmlmepriv->to_roaming--;
- if (pmlmepriv->to_roaming != 0) { /* try another , */
+ if (rtw_to_roaming(adapter) != 0) { /* try another */
+ DBG_88E("%s try another roaming\n", __func__);
do_join_r = rtw_do_join(adapter);
- if (do_join_r != _SUCCESS)
+ if (_SUCCESS != do_join_r) {
+ DBG_88E("%s roaming do_join return %d\n", __func__, do_join_r);
continue;
+ }
+ break;
+ } else {
+ DBG_88E("%s We've try roaming but fail\n", __func__);
+ rtw_indicate_disconnect(adapter);
break;
}
- rtw_indicate_disconnect(adapter);
- break;
}
} else {
rtw_indicate_disconnect(adapter);
free_scanqueue(pmlmepriv);/* */
}
spin_unlock_bh(&pmlmepriv->lock);
+
}
/*
- * rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey
- * @adapter: pointer to struct adapter structure
- */
-void rtw_scan_timeout_handler (struct timer_list *t)
+* rtw_scan_timeout_handler - Timeout/Faliure handler for CMD SiteSurvey
+* @adapter: pointer to struct adapter structure
+*/
+void rtw_scan_timeout_handler (struct adapter *adapter)
{
- struct adapter *adapter = from_timer(adapter, t,
- mlmepriv.scan_to_timer);
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ DBG_88E(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
spin_lock_bh(&pmlmepriv->lock);
_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
spin_unlock_bh(&pmlmepriv->lock);
@@ -1244,51 +1463,71 @@ static void rtw_auto_scan_handler(struct adapter *padapter)
if (pmlmepriv->scan_interval > 0) {
pmlmepriv->scan_interval--;
if (pmlmepriv->scan_interval == 0) {
+ DBG_88E("%s\n", __func__);
rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
}
}
}
-void rtw_dynamic_check_timer_handlder(struct timer_list *t)
+void rtw_dynamic_check_timer_handlder(struct adapter *adapter)
{
- struct adapter *adapter = from_timer(adapter, t,
- mlmepriv.dynamic_chk_timer);
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
struct registry_priv *pregistrypriv = &adapter->registrypriv;
if (!adapter)
return;
if (!adapter->hw_init_completed)
- goto exit;
+ return;
if ((adapter->bDriverStopped) || (adapter->bSurpriseRemoved))
- goto exit;
+ return;
if (adapter->net_closed)
- goto exit;
+ return;
rtw_dynamic_chk_wk_cmd(adapter);
if (pregistrypriv->wifi_spec == 1) {
- /* auto site survey */
- rtw_auto_scan_handler(adapter);
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+#endif
+ {
+ /* auto site survey */
+ rtw_auto_scan_handler(adapter);
+ }
}
-exit:
- mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
- jiffies + msecs_to_jiffies(2000));
+
+ rcu_read_lock();
+
+ if (rcu_dereference(adapter->pnetdev->rx_handler_data) &&
+ check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
+ /* expire NAT2.5 entry */
+ nat25_db_expire(adapter);
+
+ if (adapter->pppoe_connection_in_progress > 0) {
+ adapter->pppoe_connection_in_progress--;
+ }
+
+ /* due to rtw_dynamic_check_timer_handlder() is called every 2 seconds */
+ if (adapter->pppoe_connection_in_progress > 0) {
+ adapter->pppoe_connection_in_progress--;
+ }
+ }
+
+ rcu_read_unlock();
}
#define RTW_SCAN_RESULT_EXPIRE 2000
/*
- * Select a new join candidate from the original @param candidate and @param competitor
- * @return true: candidate is updated
- * @return false: candidate is not updated
- */
+* Select a new join candidate from the original @param candidate and @param competitor
+* @return true: candidate is updated
+* @return false: candidate is not updated
+*/
static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
, struct wlan_network **candidate, struct wlan_network *competitor)
{
int updated = false;
- unsigned long since_scan;
- struct adapter *adapter = container_of(pmlmepriv, struct adapter,
- mlmepriv);
+ struct adapter *adapter = container_of(pmlmepriv, struct adapter, mlmepriv);
/* check bssid, if needed */
if (pmlmepriv->assoc_by_bssid) {
@@ -1297,18 +1536,17 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
}
/* check ssid, if needed */
- if (pmlmepriv->assoc_ssid.ssid_length) {
- if (competitor->network.ssid.ssid_length != pmlmepriv->assoc_ssid.ssid_length ||
- memcmp(competitor->network.ssid.ssid, pmlmepriv->assoc_ssid.ssid, pmlmepriv->assoc_ssid.ssid_length))
+ if (pmlmepriv->assoc_ssid.SsidLength) {
+ if (competitor->network.Ssid.SsidLength != pmlmepriv->assoc_ssid.SsidLength ||
+ memcmp(competitor->network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength))
goto exit;
}
if (!rtw_is_desired_network(adapter, competitor))
goto exit;
- if (pmlmepriv->to_roaming) {
- since_scan = jiffies - competitor->last_scanned;
- if (jiffies_to_msecs(since_scan) >= RTW_SCAN_RESULT_EXPIRE ||
+ if (rtw_to_roaming(adapter) > 0) {
+ if (rtw_get_passing_time_ms((u32)competitor->last_scanned) >= RTW_SCAN_RESULT_EXPIRE ||
!is_same_ess(&competitor->network, &pmlmepriv->cur_network.network))
goto exit;
}
@@ -1317,67 +1555,93 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
*candidate = competitor;
updated = true;
}
+ if (updated) {
+ DBG_88E("[by_bssid:%u][assoc_ssid:%s]new candidate: %s(%pM rssi:%d\n",
+ pmlmepriv->assoc_by_bssid,
+ pmlmepriv->assoc_ssid.Ssid,
+ (*candidate)->network.Ssid.Ssid,
+ (*candidate)->network.MacAddress,
+ (int)(*candidate)->network.Rssi);
+ DBG_88E("[to_roaming:%u]\n", rtw_to_roaming(adapter));
+ }
exit:
return updated;
}
/*
- * Calling context:
- * The caller of the sub-routine will be in critical section...
- * The caller must hold the following spinlock
- * pmlmepriv->lock
- */
+Calling context:
+The caller of the sub-routine will be in critical section...
+The caller must hold the following spinlock
+pmlmepriv->lock
+*/
int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
{
int ret;
struct list_head *phead;
- struct adapter *adapter = container_of(pmlmepriv, struct adapter, mlmepriv);
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- struct wlan_network *candidate = NULL;
- u8 supp_ant_div = false;
+ struct adapter *adapter;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ struct wlan_network *candidate = NULL;
+ u8 supp_ant_div = false;
spin_lock_bh(&pmlmepriv->scanned_queue.lock);
phead = get_list_head(queue);
- list_for_each(pmlmepriv->pscanned, phead) {
- pnetwork = list_entry(pmlmepriv->pscanned,
- struct wlan_network, list);
+ adapter = (struct adapter *)pmlmepriv->nic_hdl;
+ pmlmepriv->pscanned = phead->next;
+ while (phead != pmlmepriv->pscanned) {
+ pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
+ if (!pnetwork) {
+ ret = _FAIL;
+ goto exit;
+ }
+ pmlmepriv->pscanned = pmlmepriv->pscanned->next;
rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
}
if (!candidate) {
+ DBG_88E("%s: return _FAIL(candidate==NULL)\n", __func__);
ret = _FAIL;
goto exit;
+ } else {
+ DBG_88E("%s: candidate: %s(%pM ch:%u)\n", __func__,
+ candidate->network.Ssid.Ssid, candidate->network.MacAddress,
+ candidate->network.Configuration.DSConfig);
}
/* check for situation of _FW_LINKED */
if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ DBG_88E("%s: _FW_LINKED while ask_for_joinbss!!!\n", __func__);
+
rtw_disassoc_cmd(adapter, 0, true);
rtw_indicate_disconnect(adapter);
- rtw_free_assoc_resources_locked(adapter);
+ rtw_free_assoc_resources(adapter, 0);
}
rtw_hal_get_def_var(adapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(supp_ant_div));
if (supp_ant_div) {
u8 cur_ant;
-
rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(cur_ant));
+ DBG_88E("#### Opt_Ant_(%s), cur_Ant(%s)\n",
+ (2 == candidate->network.PhyInfo.Optimum_antenna) ? "A" : "B",
+ (2 == cur_ant) ? "A" : "B"
+ );
}
ret = rtw_joinbss_cmd(adapter, candidate);
exit:
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
return ret;
}
int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
{
- struct cmd_obj *pcmd;
- struct setauth_parm *psetauthparm;
- struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
- int res = _SUCCESS;
+ struct cmd_obj *pcmd;
+ struct setauth_parm *psetauthparm;
+ struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+ int res = _SUCCESS;
pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
if (!pcmd) {
@@ -1391,37 +1655,43 @@ int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
res = _FAIL;
goto exit;
}
+ memset(psetauthparm, 0, sizeof(struct setauth_parm));
psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
pcmd->cmdcode = _SetAuth_CMD_;
pcmd->parmbuf = (unsigned char *)psetauthparm;
- pcmd->cmdsz = sizeof(struct setauth_parm);
+ pcmd->cmdsz = (sizeof(struct setauth_parm));
pcmd->rsp = NULL;
pcmd->rspsz = 0;
INIT_LIST_HEAD(&pcmd->list);
res = rtw_enqueue_cmd(pcmdpriv, pcmd);
exit:
+
return res;
}
int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, int keyid, u8 set_tx)
{
- u8 keylen;
- struct cmd_obj *pcmd;
- struct setkey_parm *psetkeyparm;
- struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- int res = _SUCCESS;
+ u8 keylen;
+ struct cmd_obj *pcmd;
+ struct setkey_parm *psetkeyparm;
+ struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ int res = _SUCCESS;
pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
- if (!pcmd)
- return _FAIL; /* try again */
-
+ if (!pcmd) {
+ res = _FAIL; /* try again */
+ goto exit;
+ }
psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
if (!psetkeyparm) {
+ kfree(pcmd);
res = _FAIL;
- goto err_free_cmd;
+ goto exit;
}
+ memset(psetkeyparm, 0, sizeof(struct setkey_parm));
+
if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy;
else
@@ -1429,17 +1699,17 @@ int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, in
psetkeyparm->keyid = (u8)keyid;/* 0~3 */
psetkeyparm->set_tx = set_tx;
pmlmepriv->key_mask |= BIT(psetkeyparm->keyid);
+ DBG_88E("==> rtw_set_key algorithm(%x), keyid(%x), key_mask(%x)\n",
+ psetkeyparm->algorithm, psetkeyparm->keyid, pmlmepriv->key_mask);
switch (psetkeyparm->algorithm) {
case _WEP40_:
keylen = 5;
- memcpy(&psetkeyparm->key[0],
- &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
+ memcpy(&psetkeyparm->key[0], &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
break;
case _WEP104_:
keylen = 13;
- memcpy(&psetkeyparm->key[0],
- &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
+ memcpy(&psetkeyparm->key[0], &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
break;
case _TKIP_:
keylen = 16;
@@ -1453,31 +1723,27 @@ int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, in
break;
default:
res = _FAIL;
- goto err_free_parm;
+ goto exit;
}
pcmd->cmdcode = _SetKey_CMD_;
pcmd->parmbuf = (u8 *)psetkeyparm;
- pcmd->cmdsz = sizeof(struct setkey_parm);
+ pcmd->cmdsz = (sizeof(struct setkey_parm));
pcmd->rsp = NULL;
pcmd->rspsz = 0;
INIT_LIST_HEAD(&pcmd->list);
- return rtw_enqueue_cmd(pcmdpriv, pcmd);
-
-err_free_parm:
- kfree(psetkeyparm);
-err_free_cmd:
- kfree(pcmd);
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+exit:
return res;
}
-/* adjust ies for rtw_joinbss_cmd in WMM */
+/* adjust IEs for rtw_joinbss_cmd in WMM */
int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
{
- unsigned int ielength = 0;
+ unsigned int ielength = 0;
unsigned int i, j;
- /* i = 12; after the fixed IE */
- for (i = 12; i < in_len; i += (in_ie[i + 1] + 2) /* to the next IE element */) {
+ i = 12; /* after the fixed IE */
+ while (i < in_len) {
ielength = initial_out_len;
if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 && in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 && in_ie[i + 5] == 0x02 && i + 5 < in_len) {
@@ -1493,33 +1759,43 @@ int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_
out_ie[initial_out_len + 8] = 0x00;
break;
}
+ i += (in_ie[i + 1] + 2); /* to the next IE element */
}
return ielength;
}
-/*
- * Ported from 8185: IsInPreAuthKeyList().
- * (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.)
- * Added by Annie, 2006-05-07.
- * Search by BSSID,
- * Return Value:
- * -1 :if there is no pre-auth key in the table
- * >= 0 :if there is pre-auth key, and return the entry id
- */
+/* */
+/* Ported from 8185: IsInPreAuthKeyList(). (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
+/* Added by Annie, 2006-05-07. */
+/* */
+/* Search by BSSID, */
+/* Return Value: */
+/* -1 :if there is no pre-auth key in the table */
+/* >= 0 :if there is pre-auth key, and return the entry id */
+/* */
+/* */
+
static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid)
{
struct security_priv *psecuritypriv = &Adapter->securitypriv;
int i = 0;
do {
- if ((psecuritypriv->PMKIDList[i].used) &&
- (!memcmp(psecuritypriv->PMKIDList[i].bssid, bssid, ETH_ALEN)))
+ if ((psecuritypriv->PMKIDList[i].bUsed) &&
+ (!memcmp(psecuritypriv->PMKIDList[i].Bssid, bssid, ETH_ALEN))) {
break;
- } while (++i < NUM_PMKID_CACHE);
+ } else {
+ i++;
+ /* continue; */
+ }
- if (i == NUM_PMKID_CACHE)
- i = -1;/* Could not find. */
+ } while (i < NUM_PMKID_CACHE);
+ if (i == NUM_PMKID_CACHE) {
+ i = -1;/* Could not find. */
+ } else {
+ /* There is one Pre-Authentication Key for the specific BSSID. */
+ }
return i;
}
@@ -1551,30 +1827,28 @@ static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie
int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len)
{
- u8 authmode;
- uint ielength;
+ u8 authmode = 0;
+ uint ielength;
int iEntry;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
struct security_priv *psecuritypriv = &adapter->securitypriv;
- uint ndisauthmode = psecuritypriv->ndisauthtype;
+ uint ndisauthmode = psecuritypriv->ndisauthtype;
/* copy fixed ie only */
memcpy(out_ie, in_ie, 12);
ielength = 12;
if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
(ndisauthmode == Ndis802_11AuthModeWPAPSK))
- authmode = WLAN_EID_VENDOR_SPECIFIC;
- else if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
- (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
- authmode = WLAN_EID_RSN;
- else
- authmode = 0x0;
+ authmode = _WPA_IE_ID_;
+ if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
+ (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
+ authmode = _WPA2_IE_ID_;
if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
memcpy(out_ie + ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
ielength += psecuritypriv->wps_ie_len;
- } else if ((authmode == WLAN_EID_VENDOR_SPECIFIC) || (authmode == WLAN_EID_RSN)) {
+ } else if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
/* copy RSN or SSN */
memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1] + 2);
ielength += psecuritypriv->supplicant_ie[1] + 2;
@@ -1582,8 +1856,12 @@ int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_
}
iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
- if (iEntry >= 0 && authmode == WLAN_EID_RSN)
- ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
+ if (iEntry < 0) {
+ return ielength;
+ } else {
+ if (authmode == _WPA2_IE_ID_)
+ ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
+ }
return ielength;
}
@@ -1592,12 +1870,12 @@ void rtw_init_registrypriv_dev_network(struct adapter *adapter)
{
struct registry_priv *pregistrypriv = &adapter->registrypriv;
struct eeprom_priv *peepriv = &adapter->eeprompriv;
- struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
u8 *myhwaddr = myid(peepriv);
memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
- memcpy(&pdev_network->ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
pdev_network->Configuration.Length = sizeof(struct ndis_802_11_config);
pdev_network->Configuration.BeaconPeriod = 100;
@@ -1605,64 +1883,67 @@ void rtw_init_registrypriv_dev_network(struct adapter *adapter)
pdev_network->Configuration.FHConfig.HopPattern = 0;
pdev_network->Configuration.FHConfig.HopSet = 0;
pdev_network->Configuration.FHConfig.DwellTime = 0;
+
}
void rtw_update_registrypriv_dev_network(struct adapter *adapter)
{
int sz = 0;
struct registry_priv *pregistrypriv = &adapter->registrypriv;
- struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
- struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
+ struct security_priv *psecuritypriv = &adapter->securitypriv;
+ struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
- pdev_network->Privacy = psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0; /* adhoc no 802.1x */
+ pdev_network->Privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0); /* adhoc no 802.1x */
pdev_network->Rssi = 0;
switch (pregistrypriv->wireless_mode) {
case WIRELESS_11B:
- pdev_network->NetworkTypeInUse = Ndis802_11DS;
+ pdev_network->NetworkTypeInUse = (Ndis802_11DS);
break;
case WIRELESS_11G:
case WIRELESS_11BG:
case WIRELESS_11_24N:
case WIRELESS_11G_24N:
case WIRELESS_11BG_24N:
- pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
break;
default:
- pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ /* TODO */
break;
}
- pdev_network->Configuration.DSConfig = pregistrypriv->channel;
+ pdev_network->Configuration.DSConfig = (pregistrypriv->channel);
if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
- pdev_network->Configuration.ATIMWindow = 0;
+ pdev_network->Configuration.ATIMWindow = (0);
- pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
+ pdev_network->InfrastructureMode = (cur_network->network.InfrastructureMode);
/* 1. Supported rates */
/* 2. IE */
sz = rtw_generate_ie(pregistrypriv);
- pdev_network->ie_length = sz;
- pdev_network->Length = get_wlan_bssid_ex_sz(pdev_network);
+ pdev_network->IELength = sz;
+ pdev_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
+
+ /* notes: translate IELength & Length after assign the Length to cmdsz in createbss_cmd(); */
+ /* pdev_network->IELength = cpu_to_le32(sz); */
- /* notes: translate ie_length & Length after assign the Length to cmdsz in createbss_cmd(); */
- /* pdev_network->ie_length = cpu_to_le32(sz); */
}
void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
{
+
}
/* the function is at passive_level */
void rtw_joinbss_reset(struct adapter *padapter)
{
- u8 threshold;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ u8 threshold;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
/* todo: if you want to do something io/reg/hw setting before join_bss, please add code here */
pmlmepriv->num_FortyMHzIntolerant = 0;
@@ -1691,22 +1972,21 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
u32 ielen, out_len;
enum ht_cap_ampdu_factor max_rx_ampdu_factor;
unsigned char *p;
+ struct ieee80211_ht_cap ht_capie;
unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
u32 rx_packet_offset, max_recvbuf_sz;
phtpriv->ht_option = false;
- p = rtw_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
+ p = rtw_get_ie(in_ie + 12, _HT_CAPABILITY_IE_, &ielen, in_len - 12);
if (p && ielen > 0) {
- struct ieee80211_ht_cap ht_cap;
-
if (pqospriv->qos_option == 0) {
out_len = *pout_len;
- rtw_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
+ rtw_set_ie(out_ie + out_len, _VENDOR_SPECIFIC_IE_,
_WMM_IE_Length_, WMM_IE, pout_len);
pqospriv->qos_option = 1;
@@ -1714,40 +1994,39 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
out_len = *pout_len;
- memset(&ht_cap, 0, sizeof(struct ieee80211_ht_cap));
+ memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
- ht_cap.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
- IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40 |
- IEEE80211_HT_CAP_TX_STBC |
- IEEE80211_HT_CAP_DSSSCCK40);
+ ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+ IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_TX_STBC |
+ IEEE80211_HT_CAP_DSSSCCK40);
rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
/*
- * ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
- * ampdu_params_info [4:2]:Min MPDU Start Spacing
- */
+ AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+ AMPDU_para [4:2]:Min MPDU Start Spacing
+ */
rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
- ht_cap.ampdu_params_info = max_rx_ampdu_factor & 0x03;
+ ht_capie.ampdu_params_info = (max_rx_ampdu_factor & 0x03);
if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
- ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07 << 2);
+ ht_capie.ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07 << 2));
else
- ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00;
+ ht_capie.ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
- rtw_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
- sizeof(struct ieee80211_ht_cap),
- (unsigned char *)&ht_cap, pout_len);
+ rtw_set_ie(out_ie + out_len, _HT_CAPABILITY_IE_,
+ sizeof(struct ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len);
phtpriv->ht_option = true;
- p = rtw_get_ie(in_ie + 12, WLAN_EID_HT_OPERATION, &ielen, in_len - 12);
+ p = rtw_get_ie(in_ie + 12, _HT_ADD_INFO_IE_, &ielen, in_len - 12);
if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
out_len = *pout_len;
- rtw_set_ie(out_ie + out_len, WLAN_EID_HT_OPERATION, ielen, p + 2, pout_len);
+ rtw_set_ie(out_ie + out_len, _HT_ADD_INFO_IE_, ielen, p + 2, pout_len);
}
}
return phtpriv->ht_option;
@@ -1756,11 +2035,14 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
/* the function is > passive_level (in critical_section) */
void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ u8 *p, max_ampdu_sz;
+ int len;
+ struct ieee80211_ht_cap *pht_capie;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
if (!phtpriv->ht_option)
return;
@@ -1768,6 +2050,8 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
return;
+ DBG_88E("+rtw_update_ht_cap()\n");
+
/* maybe needs check if ap supports rx ampdu. */
if ((!phtpriv->ampdu_enable) && (pregistrypriv->ampdu_enable == 1)) {
if (pregistrypriv->wifi_spec == 1)
@@ -1778,15 +2062,34 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
phtpriv->ampdu_enable = true;
}
+ /* check Max Rx A-MPDU Size */
+ len = 0;
+ p = rtw_get_ie(pie + sizeof(struct ndis_802_11_fixed_ie), _HT_CAPABILITY_IE_, &len, ie_len - sizeof(struct ndis_802_11_fixed_ie));
+ if (p && len > 0) {
+ pht_capie = (struct ieee80211_ht_cap *)(p + 2);
+ max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR);
+ max_ampdu_sz = 1 << (max_ampdu_sz + 3); /* max_ampdu_sz (kbytes); */
+ phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
+ }
+ len = 0;
+ p = rtw_get_ie(pie + sizeof(struct ndis_802_11_fixed_ie), _HT_ADD_INFO_IE_, &len, ie_len - sizeof(struct ndis_802_11_fixed_ie));
+
/* update cur_bwmode & cur_ch_offset */
if ((pregistrypriv->cbw40_enable) &&
- (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & BIT(1)) &&
+ (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & BIT(1)) &&
(pmlmeinfo->HT_info.infos[0] & BIT(2))) {
int i;
+ u8 rf_type;
+
+ padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
/* update the MCS rates */
- for (i = 0; i < 16; i++)
- ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i];
+ for (i = 0; i < 16; i++) {
+ if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
+ pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
+ else
+ pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i];
+ }
/* switch to the 40M Hz mode according to the AP */
pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
@@ -1803,7 +2106,9 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
}
/* Config SM Power Save setting */
- pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2;
+ pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2;
+ if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
+ DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
/* Config current HT Protection mode. */
pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
@@ -1814,7 +2119,7 @@ void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitfr
u8 issued;
int priority;
struct sta_info *psta = NULL;
- struct ht_priv *phtpriv;
+ struct ht_priv *phtpriv;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
if (is_multicast_ether_addr(pattrib->ra) ||
@@ -1837,7 +2142,8 @@ void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitfr
issued = (phtpriv->agg_enable_bitmap >> priority) & 0x1;
issued |= (phtpriv->candidate_tid_bitmap >> priority) & 0x1;
- if (issued == 0) {
+ if (0 == issued) {
+ DBG_88E("rtw_issue_addbareq_cmd, p=%d\n", priority);
psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
rtw_addbareq_cmd(padapter, (u8)priority, pattrib->ra);
}
@@ -1846,17 +2152,17 @@ void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitfr
void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
spin_lock_bh(&pmlmepriv->lock);
_rtw_roaming(padapter, tgt_network);
spin_unlock_bh(&pmlmepriv->lock);
}
-
void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int do_join_r;
+
struct wlan_network *pnetwork;
if (tgt_network)
@@ -1864,23 +2170,29 @@ void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
else
pnetwork = &pmlmepriv->cur_network;
- if (pmlmepriv->to_roaming > 0) {
- memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.ssid, sizeof(struct ndis_802_11_ssid));
+ if (0 < rtw_to_roaming(padapter)) {
+ DBG_88E("roaming from %s(%pM length:%d\n",
+ pnetwork->network.Ssid.Ssid, pnetwork->network.MacAddress,
+ pnetwork->network.Ssid.SsidLength);
+ memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
pmlmepriv->assoc_by_bssid = false;
while (1) {
do_join_r = rtw_do_join(padapter);
- if (do_join_r == _SUCCESS)
+ if (_SUCCESS == do_join_r) {
break;
-
- pmlmepriv->to_roaming--;
-
- if (pmlmepriv->to_roaming > 0) {
- continue;
} else {
- rtw_indicate_disconnect(padapter);
- break;
+ DBG_88E("roaming do_join return %d\n", do_join_r);
+ pmlmepriv->to_roaming--;
+
+ if (0 < pmlmepriv->to_roaming) {
+ continue;
+ } else {
+ DBG_88E("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
+ rtw_indicate_disconnect(padapter);
+ break;
+ }
}
}
}
diff --git a/drivers/staging/r8188eu/core/rtw_mlme_ext.c b/drivers/staging/r8188eu/core/rtw_mlme_ext.c
new file mode 100644
index 000000000000..5a472a4954b0
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_mlme_ext.c
@@ -0,0 +1,8327 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#define _RTW_MLME_EXT_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/wifi.h"
+#include "../include/rtw_mlme_ext.h"
+#include "../include/wlan_bssdef.h"
+#include "../include/mlme_osdep.h"
+#include "../include/recv_osdep.h"
+
+static struct mlme_handler mlme_sta_tbl[] = {
+ {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},
+ {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},
+ {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},
+ {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},
+ {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq},
+ {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp},
+
+ /*----------------------------------------------------------
+ below 2 are reserved
+ -----------------------------------------------------------*/
+ {0, "DoReserved", &DoReserved},
+ {0, "DoReserved", &DoReserved},
+ {WIFI_BEACON, "OnBeacon", &OnBeacon},
+ {WIFI_ATIM, "OnATIM", &OnAtim},
+ {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc},
+ {WIFI_AUTH, "OnAuth", &OnAuthClient},
+ {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth},
+ {WIFI_ACTION, "OnAction", &OnAction},
+};
+
+static struct action_handler OnAction_tbl[] = {
+ {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct},
+ {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
+ {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
+ {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
+ {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
+ {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
+ {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved},
+ {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht},
+ {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
+ {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
+ {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
+};
+
+static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+
+/**************************************************
+OUI definitions for the vendor specific IE
+***************************************************/
+unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
+unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
+unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
+unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
+unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
+
+unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+
+unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
+unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
+
+extern unsigned char REALTEK_96B_IE[];
+
+/********************************************************
+MCS rate definitions
+*********************************************************/
+unsigned char MCS_rate_2R[16] = {0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+unsigned char MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+/********************************************************
+ChannelPlan definitions
+*********************************************************/
+static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
+ {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
+ {{}, 0}, /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
+};
+
+static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
+ /* 0x00 ~ 0x1F , Old Define ===== */
+ {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
+ {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
+ {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
+ {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
+ {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
+ {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
+ {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
+ {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
+ {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
+ {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
+ {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
+ {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
+ {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
+ {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
+ {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
+ {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
+ {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
+ {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
+ {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
+ {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
+ {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
+ {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
+ {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
+ {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
+ {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
+ {0x00}, /* 0x1A, */
+ {0x00}, /* 0x1B, */
+ {0x00}, /* 0x1C, */
+ {0x00}, /* 0x1D, */
+ {0x00}, /* 0x1E, */
+ /* 0x20 ~ 0x7F , New Define ===== */
+ {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
+ {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
+ {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
+ {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
+ {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
+ {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
+ {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
+ {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
+ {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
+ {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
+ {0x00}, /* 0x2A, */
+ {0x00}, /* 0x2B, */
+ {0x00}, /* 0x2C, */
+ {0x00}, /* 0x2D, */
+ {0x00}, /* 0x2E, */
+ {0x00}, /* 0x2F, */
+ {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
+ {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
+ {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
+ {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
+ {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
+ {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
+ {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
+ {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
+ {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
+ {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
+ {0x00}, /* 0x3A, */
+ {0x00}, /* 0x3B, */
+ {0x00}, /* 0x3C, */
+ {0x00}, /* 0x3D, */
+ {0x00}, /* 0x3E, */
+ {0x00}, /* 0x3F, */
+ {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
+ {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
+};
+
+static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the conbination for max channel numbers */
+
+/*
+ * Search the @param channel_num in given @param channel_set
+ * @ch_set: the given channel set
+ * @ch: the given channel number
+ *
+ * return the index of channel_num in channel_set, -1 if not found
+ */
+int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
+{
+ int i;
+ for (i = 0; ch_set[i].ChannelNum != 0; i++) {
+ if (ch == ch_set[i].ChannelNum)
+ break;
+ }
+
+ if (i >= ch_set[i].ChannelNum)
+ return -1;
+ return i;
+}
+
+/****************************************************************************
+
+Following are the initialization functions for WiFi MLME
+
+*****************************************************************************/
+
+int init_hw_mlme_ext(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+ return _SUCCESS;
+}
+
+static void init_mlme_ext_priv_value(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ unsigned char mixed_datarate[NumRates] = {
+ _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
+ _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
+ _48M_RATE_, _54M_RATE_, 0xff
+ };
+ unsigned char mixed_basicrate[NumRates] = {
+ _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
+ _12M_RATE_, _24M_RATE_, 0xff,
+ };
+
+ atomic_set(&pmlmeext->event_seq, 0);
+ pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
+
+ pmlmeext->cur_channel = padapter->registrypriv.channel;
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pmlmeext->retry = 0;
+
+ pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
+
+ memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
+ memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
+
+ pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
+
+ pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
+ pmlmeext->sitesurvey_res.channel_idx = 0;
+ pmlmeext->sitesurvey_res.bss_cnt = 0;
+ pmlmeext->scan_abort = false;
+
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ pmlmeinfo->reauth_count = 0;
+ pmlmeinfo->reassoc_count = 0;
+ pmlmeinfo->link_count = 0;
+ pmlmeinfo->auth_seq = 0;
+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
+ pmlmeinfo->key_index = 0;
+ pmlmeinfo->iv = 0;
+
+ pmlmeinfo->enc_algo = _NO_PRIVACY_;
+ pmlmeinfo->authModeToggle = 0;
+
+ memset(pmlmeinfo->chg_txt, 0, 128);
+
+ pmlmeinfo->slotTime = SHORT_SLOT_TIME;
+ pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
+
+ pmlmeinfo->dialogToken = 0;
+
+ pmlmeext->action_public_rxseq = 0xffff;
+ pmlmeext->action_public_dialog_token = 0xff;
+}
+
+static int has_channel(struct rt_channel_info *channel_set,
+ u8 chanset_size,
+ u8 chan) {
+ int i;
+
+ for (i = 0; i < chanset_size; i++) {
+ if (channel_set[i].ChannelNum == chan)
+ return 1;
+ }
+ return 0;
+}
+
+static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
+ u8 chanset_size,
+ struct p2p_channels *channel_list) {
+ struct p2p_oper_class_map op_class[] = {
+ { IEEE80211G, 81, 1, 13, 1, BW20 },
+ { IEEE80211G, 82, 14, 14, 1, BW20 },
+ { -1, 0, 0, 0, 0, BW20 }
+ };
+
+ int cla, op;
+
+ cla = 0;
+
+ for (op = 0; op_class[op].op_class; op++) {
+ u8 ch;
+ struct p2p_oper_class_map *o = &op_class[op];
+ struct p2p_reg_class *reg = NULL;
+
+ for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
+ if (!has_channel(channel_set, chanset_size, ch)) {
+ continue;
+ }
+
+ if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
+ continue;
+
+ if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
+ ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
+ continue;
+
+ if (!reg) {
+ reg = &channel_list->reg_class[cla];
+ cla++;
+ reg->reg_class = o->op_class;
+ reg->channels = 0;
+ }
+ reg->channel[reg->channels] = ch;
+ reg->channels++;
+ }
+ }
+ channel_list->reg_classes = cla;
+}
+
+static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
+{
+ u8 index, chanset_size = 0;
+ u8 b2_4GBand = false;
+ u8 Index2G = 0;
+
+ memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
+
+ if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
+ DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
+ return chanset_size;
+ }
+
+ if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
+ b2_4GBand = true;
+ if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
+ Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
+ else
+ Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
+ }
+
+ if (b2_4GBand) {
+ for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
+ channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
+
+ if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
+ (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)) {
+ if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+ else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14))
+ channel_set[chanset_size].ScanType = SCAN_PASSIVE;
+ } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
+ RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {/* channel 12~13, passive scan */
+ if (channel_set[chanset_size].ChannelNum <= 11)
+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+ else
+ channel_set[chanset_size].ScanType = SCAN_PASSIVE;
+ } else {
+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+ }
+
+ chanset_size++;
+ }
+ }
+ return chanset_size;
+}
+
+int init_mlme_ext_priv(struct adapter *padapter)
+{
+ int res = _SUCCESS;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ pmlmeext->padapter = padapter;
+
+ init_mlme_ext_priv_value(padapter);
+ pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
+
+ init_mlme_ext_timer(padapter);
+
+#ifdef CONFIG_88EU_AP_MODE
+ init_mlme_ap_info(padapter);
+#endif
+
+ pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
+ init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
+
+ pmlmeext->chan_scan_time = SURVEY_TO;
+ pmlmeext->mlmeext_init = true;
+
+ pmlmeext->active_keep_alive_check = true;
+
+ return res;
+}
+
+void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
+{
+ struct adapter *padapter = pmlmeext->padapter;
+
+ if (!padapter)
+ return;
+
+ if (padapter->bDriverStopped) {
+ _cancel_timer_ex(&pmlmeext->survey_timer);
+ _cancel_timer_ex(&pmlmeext->link_timer);
+ /* _cancel_timer_ex(&pmlmeext->ADDBA_timer); */
+ }
+}
+
+static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, struct recv_frame *precv_frame)
+{
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u8 *pframe = precv_frame->rx_data;
+
+ if (ptable->func) {
+ /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
+ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
+ memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
+ return;
+ ptable->func(padapter, precv_frame);
+ }
+}
+
+void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ int index;
+ struct mlme_handler *ptable;
+#ifdef CONFIG_88EU_AP_MODE
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+#endif /* CONFIG_88EU_AP_MODE */
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u8 *pframe = precv_frame->rx_data;
+ struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
+
+ if (GetFrameType(pframe) != WIFI_MGT_TYPE)
+ return;
+
+ /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
+ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
+ memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
+ return;
+
+ ptable = mlme_sta_tbl;
+
+ index = GetFrameSubType(pframe) >> 4;
+
+ if (index > 13)
+ return;
+ ptable += index;
+
+ if (psta) {
+ if (GetRetry(pframe)) {
+ if (precv_frame->attrib.seq_num == psta->RxMgmtFrameSeqNum) {
+ /* drop the duplicate management frame */
+ DBG_88E("Drop duplicate management frame with seq_num=%d.\n", precv_frame->attrib.seq_num);
+ return;
+ }
+ }
+ psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
+ }
+
+#ifdef CONFIG_88EU_AP_MODE
+ switch (GetFrameSubType(pframe)) {
+ case WIFI_AUTH:
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ ptable->func = &OnAuth;
+ else
+ ptable->func = &OnAuthClient;
+ fallthrough;
+ case WIFI_ASSOCREQ:
+ case WIFI_REASSOCREQ:
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+ break;
+ case WIFI_PROBEREQ:
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+ else
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+ break;
+ case WIFI_BEACON:
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+ break;
+ case WIFI_ACTION:
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+ break;
+ default:
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ rtw_hostapd_mlme_rx(padapter, precv_frame);
+ break;
+ }
+#else
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+#endif
+}
+
+#ifdef CONFIG_88EU_P2P
+static u32 p2p_listen_state_process(struct adapter *padapter, unsigned char *da)
+{
+ bool response = true;
+
+ /* do nothing if the device name is empty */
+ if (!padapter->wdinfo.device_name_len)
+ response = false;
+
+ if (response)
+ issue_probersp_p2p(padapter, da);
+
+ return _SUCCESS;
+}
+#endif /* CONFIG_88EU_P2P */
+
+/****************************************************************************
+
+Following are the callback functions for each subtype of the management frames
+
+*****************************************************************************/
+
+unsigned int OnProbeReq(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ unsigned int ielen;
+ unsigned char *p;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur = &pmlmeinfo->network;
+ u8 *pframe = precv_frame->rx_data;
+ uint len = precv_frame->len;
+ u8 is_valid_p2p_probereq = false;
+
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 wifi_test_chk_rate = 1;
+
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
+ !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
+ !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
+ !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
+ !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
+ /* mcs_rate = 0 -> CCK 1M rate */
+ /* mcs_rate = 1 -> CCK 2M rate */
+ /* mcs_rate = 2 -> CCK 5.5M rate */
+ /* mcs_rate = 3 -> CCK 11M rate */
+ /* In the P2P mode, the driver should not support the CCK rate */
+
+ /* Commented by Kurt 2012/10/16 */
+ /* IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */
+ if (wifi_test_chk_rate == 1) {
+ is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len);
+ if (is_valid_p2p_probereq) {
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
+ /* FIXME */
+ report_survey_event(padapter, precv_frame);
+ p2p_listen_state_process(padapter, get_sa(pframe));
+
+ return _SUCCESS;
+ }
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+ goto _continue;
+ }
+ }
+ }
+
+_continue:
+#endif /* CONFIG_88EU_P2P */
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ return _SUCCESS;
+
+ if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
+ !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
+ return _SUCCESS;
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
+ len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
+
+ /* check (wildcard) SSID */
+ if (p) {
+ if (is_valid_p2p_probereq)
+ goto _issue_probersp;
+
+ if ((ielen != 0 && memcmp((void *)(p + 2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
+ (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
+ return _SUCCESS;
+
+_issue_probersp:
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+ (pmlmepriv->cur_network.join_res ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
+ issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
+ }
+ return _SUCCESS;
+}
+
+unsigned int OnProbeRsp(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 *pframe = precv_frame->rx_data;
+#endif
+
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
+ if (pwdinfo->tx_prov_disc_info.benable) {
+ if (!memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
+ pwdinfo->tx_prov_disc_info.benable = false;
+ issue_p2p_provision_request(padapter,
+ pwdinfo->tx_prov_disc_info.ssid.Ssid,
+ pwdinfo->tx_prov_disc_info.ssid.SsidLength,
+ pwdinfo->tx_prov_disc_info.peerDevAddr);
+ } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ pwdinfo->tx_prov_disc_info.benable = false;
+ issue_p2p_provision_request(padapter, NULL, 0,
+ pwdinfo->tx_prov_disc_info.peerDevAddr);
+ }
+ }
+ }
+ return _SUCCESS;
+ } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
+ if (pwdinfo->nego_req_info.benable) {
+ DBG_88E("[%s] P2P State is GONEGO ING!\n", __func__);
+ if (!memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
+ pwdinfo->nego_req_info.benable = false;
+ issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);
+ }
+ }
+ } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
+ if (pwdinfo->invitereq_info.benable) {
+ DBG_88E("[%s] P2P_STATE_TX_INVITE_REQ!\n", __func__);
+ if (!memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
+ pwdinfo->invitereq_info.benable = false;
+ issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);
+ }
+ }
+ }
+#endif
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
+ report_survey_event(padapter, precv_frame);
+ return _SUCCESS;
+ }
+
+ return _SUCCESS;
+}
+
+unsigned int OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ int cam_idx;
+ struct sta_info *psta;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *pframe = precv_frame->rx_data;
+ uint len = precv_frame->len;
+ struct wlan_bssid_ex *pbss;
+ int ret = _SUCCESS;
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
+ report_survey_event(padapter, precv_frame);
+ return _SUCCESS;
+ }
+
+ if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
+ if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
+ /* we should update current network before auth, or some IE is wrong */
+ pbss = kmalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
+ if (pbss) {
+ if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
+ update_network(&pmlmepriv->cur_network.network, pbss, padapter, true);
+ rtw_get_bcn_info(&pmlmepriv->cur_network);
+ }
+ kfree(pbss);
+ }
+
+ /* check the vendor of the assoc AP */
+ pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct rtw_ieee80211_hdr_3addr), len - sizeof(struct rtw_ieee80211_hdr_3addr));
+
+ /* update TSF Value */
+ update_TSF(pmlmeext, pframe, len);
+
+ /* start auth */
+ start_clnt_auth(padapter);
+
+ return _SUCCESS;
+ }
+
+ if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (psta) {
+ ret = rtw_check_bcn_info(padapter, pframe, len);
+ if (!ret) {
+ DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n ");
+ receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0);
+ return _SUCCESS;
+ }
+ /* update WMM, ERP in the beacon */
+ /* todo: the timer is used instead of the number of the beacon received */
+ if ((sta_rx_pkts(psta) & 0xf) == 0)
+ update_beacon_info(padapter, pframe, len, psta);
+ process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
+ }
+ } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (psta) {
+ /* update WMM, ERP in the beacon */
+ /* todo: the timer is used instead of the number of the beacon received */
+ if ((sta_rx_pkts(psta) & 0xf) == 0)
+ update_beacon_info(padapter, pframe, len, psta);
+ } else {
+ /* allocate a new CAM entry for IBSS station */
+ cam_idx = allocate_fw_sta_entry(padapter);
+ if (cam_idx == NUM_STA)
+ goto _END_ONBEACON_;
+
+ /* get supported rate */
+ if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
+ pmlmeinfo->FW_sta_info[cam_idx].status = 0;
+ goto _END_ONBEACON_;
+ }
+
+ /* update TSF Value */
+ update_TSF(pmlmeext, pframe, len);
+
+ /* report sta add event */
+ report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
+ }
+ }
+ }
+
+_END_ONBEACON_:
+
+ return _SUCCESS;
+}
+
+unsigned int OnAuth(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+#ifdef CONFIG_88EU_AP_MODE
+ unsigned int auth_mode, ie_len;
+ u16 seq;
+ unsigned char *sa, *p;
+ u16 algorithm;
+ int status;
+ static struct sta_info stat;
+ struct sta_info *pstat = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->rx_data;
+ uint len = precv_frame->len;
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ return _FAIL;
+
+ DBG_88E("+OnAuth\n");
+
+ sa = GetAddr2Ptr(pframe);
+
+ auth_mode = psecuritypriv->dot11AuthAlgrthm;
+ seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
+ algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
+
+ DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq);
+
+ if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
+ psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
+ auth_mode = 0;
+
+ if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */
+ (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */
+ DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
+ algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
+
+ status = _STATS_NO_SUPP_ALG_;
+
+ goto auth_fail;
+ }
+
+ if (!rtw_access_ctrl(padapter, sa)) {
+ status = _STATS_UNABLE_HANDLE_STA_;
+ goto auth_fail;
+ }
+
+ pstat = rtw_get_stainfo(pstapriv, sa);
+ if (!pstat) {
+ /* allocate a new one */
+ DBG_88E("going to alloc stainfo for sa=%pM\n", sa);
+ pstat = rtw_alloc_stainfo(pstapriv, sa);
+ if (!pstat) {
+ DBG_88E(" Exceed the upper limit of supported clients...\n");
+ status = _STATS_UNABLE_HANDLE_STA_;
+ goto auth_fail;
+ }
+
+ pstat->state = WIFI_FW_AUTH_NULL;
+ pstat->auth_seq = 0;
+ } else {
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (!list_empty(&pstat->asoc_list)) {
+ list_del_init(&pstat->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ if (seq == 1) {
+ /* TODO: STA re_auth and auth timeout */
+ }
+ }
+
+ spin_lock_bh(&pstapriv->auth_list_lock);
+ if (list_empty(&pstat->auth_list)) {
+ list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
+ pstapriv->auth_list_cnt++;
+ }
+ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ if (pstat->auth_seq == 0)
+ pstat->expire_to = pstapriv->auth_to;
+
+ if ((pstat->auth_seq + 1) != seq) {
+ DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+ seq, pstat->auth_seq + 1);
+ status = _STATS_OUT_OF_AUTH_SEQ_;
+ goto auth_fail;
+ }
+
+ if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
+ if (seq == 1) {
+ pstat->state &= ~WIFI_FW_AUTH_NULL;
+ pstat->state |= WIFI_FW_AUTH_SUCCESS;
+ pstat->expire_to = pstapriv->assoc_to;
+ pstat->authalg = algorithm;
+ } else {
+ DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+ seq, pstat->auth_seq + 1);
+ status = _STATS_OUT_OF_AUTH_SEQ_;
+ goto auth_fail;
+ }
+ } else { /* shared system or auto authentication */
+ if (seq == 1) {
+ /* prepare for the challenging txt... */
+
+ pstat->state &= ~WIFI_FW_AUTH_NULL;
+ pstat->state |= WIFI_FW_AUTH_STATE;
+ pstat->authalg = algorithm;
+ pstat->auth_seq = 2;
+ } else if (seq == 3) {
+ /* checking for challenging txt... */
+ DBG_88E("checking for challenging txt...\n");
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len,
+ len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
+
+ if (!p || ie_len <= 0) {
+ DBG_88E("auth rejected because challenge failure!(1)\n");
+ status = _STATS_CHALLENGE_FAIL_;
+ goto auth_fail;
+ }
+
+ if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
+ pstat->state &= (~WIFI_FW_AUTH_STATE);
+ pstat->state |= WIFI_FW_AUTH_SUCCESS;
+ /* challenging txt is correct... */
+ pstat->expire_to = pstapriv->assoc_to;
+ } else {
+ DBG_88E("auth rejected because challenge failure!\n");
+ status = _STATS_CHALLENGE_FAIL_;
+ goto auth_fail;
+ }
+ } else {
+ DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+ seq, pstat->auth_seq + 1);
+ status = _STATS_OUT_OF_AUTH_SEQ_;
+ goto auth_fail;
+ }
+ }
+
+ /* Now, we are going to issue_auth... */
+ pstat->auth_seq = seq + 1;
+
+#ifdef CONFIG_88EU_AP_MODE
+ issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
+#endif
+
+ if (pstat->state & WIFI_FW_AUTH_SUCCESS)
+ pstat->auth_seq = 0;
+
+ return _SUCCESS;
+
+auth_fail:
+
+ if (pstat)
+ rtw_free_stainfo(padapter, pstat);
+
+ pstat = &stat;
+ memset((char *)pstat, '\0', sizeof(stat));
+ pstat->auth_seq = 2;
+ memcpy(pstat->hwaddr, sa, 6);
+
+#ifdef CONFIG_88EU_AP_MODE
+ issue_auth(padapter, pstat, (unsigned short)status);
+#endif
+
+#endif
+ return _FAIL;
+}
+
+unsigned int OnAuthClient(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ unsigned int seq, len, status, offset;
+ unsigned char *p;
+ unsigned int go2asoc = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->rx_data;
+ uint pkt_len = precv_frame->len;
+
+ DBG_88E("%s\n", __func__);
+
+ /* check A1 matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), get_da(pframe), ETH_ALEN))
+ return _SUCCESS;
+
+ if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
+ return _SUCCESS;
+
+ offset = (GetPrivacy(pframe)) ? 4 : 0;
+
+ seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
+ status = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
+
+ if (status != 0) {
+ DBG_88E("clnt auth fail, status: %d\n", status);
+ if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
+ else
+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
+ }
+
+ set_link_timer(pmlmeext, 1);
+ goto authclnt_fail;
+ }
+
+ if (seq == 2) {
+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
+ /* legendary shared system */
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
+ pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
+
+ if (!p)
+ goto authclnt_fail;
+
+ memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
+ pmlmeinfo->auth_seq = 3;
+ issue_auth(padapter, NULL, 0);
+ set_link_timer(pmlmeext, REAUTH_TO);
+
+ return _SUCCESS;
+ } else {
+ /* open system */
+ go2asoc = 1;
+ }
+ } else if (seq == 4) {
+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
+ go2asoc = 1;
+ else
+ goto authclnt_fail;
+ } else {
+ /* this is also illegal */
+ goto authclnt_fail;
+ }
+
+ if (go2asoc) {
+ DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n");
+ start_clnt_assoc(padapter);
+ return _SUCCESS;
+ }
+authclnt_fail:
+ return _FAIL;
+}
+
+unsigned int OnAssocReq(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+#ifdef CONFIG_88EU_AP_MODE
+ u16 capab_info;
+ struct rtw_ieee802_11_elems elems;
+ struct sta_info *pstat;
+ unsigned char reassoc, *p, *pos, *wpa_ie;
+ unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+ int i, ie_len, wpa_ie_len, left;
+ unsigned char supportRate[16];
+ int supportRateNum;
+ unsigned short status = _STATS_SUCCESSFUL_;
+ unsigned short frame_type, ie_offset = 0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur = &pmlmeinfo->network;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *pframe = precv_frame->rx_data;
+ uint pkt_len = precv_frame->len;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 p2p_status_code = P2P_STATUS_SUCCESS;
+ u8 *p2pie;
+ u32 p2pielen = 0;
+#endif /* CONFIG_88EU_P2P */
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ return _FAIL;
+
+ frame_type = GetFrameSubType(pframe);
+ if (frame_type == WIFI_ASSOCREQ) {
+ reassoc = 0;
+ ie_offset = _ASOCREQ_IE_OFFSET_;
+ } else { /* WIFI_REASSOCREQ */
+ reassoc = 1;
+ ie_offset = _REASOCREQ_IE_OFFSET_;
+ }
+
+ if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
+ DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
+ "\n", reassoc, (unsigned long)pkt_len);
+ return _FAIL;
+ }
+
+ pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (pstat == (struct sta_info *)NULL) {
+ status = _RSON_CLS2_;
+ goto asoc_class2_error;
+ }
+
+ capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
+
+ left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
+ pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
+
+ DBG_88E("%s\n", __func__);
+
+ /* check if this stat has been successfully authenticated/assocated */
+ if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
+ if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
+ status = _RSON_CLS2_;
+ goto asoc_class2_error;
+ } else {
+ pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
+ pstat->state |= WIFI_FW_ASSOC_STATE;
+ }
+ } else {
+ pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
+ pstat->state |= WIFI_FW_ASSOC_STATE;
+ }
+ pstat->capability = capab_info;
+ /* now parse all ieee802_11 ie to point to elems */
+ if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
+ !elems.ssid) {
+ DBG_88E("STA %pM sent invalid association request\n",
+ pstat->hwaddr);
+ status = _STATS_FAILURE_;
+ goto OnAssocReqFail;
+ }
+
+ /* now we should check all the fields... */
+ /* checking SSID */
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
+ pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+ if (!p)
+ status = _STATS_FAILURE_;
+
+ if (ie_len == 0) { /* broadcast ssid, however it is not allowed in assocreq */
+ status = _STATS_FAILURE_;
+ } else {
+ /* check if ssid match */
+ if (memcmp((void *)(p + 2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
+ status = _STATS_FAILURE_;
+
+ if (ie_len != cur->Ssid.SsidLength)
+ status = _STATS_FAILURE_;
+ }
+
+ if (_STATS_SUCCESSFUL_ != status)
+ goto OnAssocReqFail;
+
+ /* check if the supported rate is ok */
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+ if (!p) {
+ DBG_88E("Rx a sta assoc-req which supported rate is empty!\n");
+ /* use our own rate set as statoin used */
+ /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
+ /* supportRateNum = AP_BSSRATE_LEN; */
+
+ status = _STATS_FAILURE_;
+ goto OnAssocReqFail;
+ } else {
+ memcpy(supportRate, p + 2, ie_len);
+ supportRateNum = ie_len;
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
+ pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+ if (p) {
+ if (supportRateNum <= sizeof(supportRate)) {
+ memcpy(supportRate + supportRateNum, p + 2, ie_len);
+ supportRateNum += ie_len;
+ }
+ }
+ }
+
+ /* todo: mask supportRate between AP & STA -> move to update raid */
+ /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
+
+ /* update station supportRate */
+ pstat->bssratelen = supportRateNum;
+ memcpy(pstat->bssrateset, supportRate, supportRateNum);
+ UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
+
+ /* check RSN/WPA/WPS */
+ pstat->dot8021xalg = 0;
+ pstat->wpa_psk = 0;
+ pstat->wpa_group_cipher = 0;
+ pstat->wpa2_group_cipher = 0;
+ pstat->wpa_pairwise_cipher = 0;
+ pstat->wpa2_pairwise_cipher = 0;
+ memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
+ if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
+ int group_cipher = 0, pairwise_cipher = 0;
+
+ wpa_ie = elems.rsn_ie;
+ wpa_ie_len = elems.rsn_ie_len;
+
+ if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ pstat->dot8021xalg = 1;/* psk, todo:802.1x */
+ pstat->wpa_psk |= BIT(1);
+
+ pstat->wpa2_group_cipher = group_cipher & psecuritypriv->wpa2_group_cipher;
+ pstat->wpa2_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa2_pairwise_cipher;
+
+ if (!pstat->wpa2_group_cipher)
+ status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+
+ if (!pstat->wpa2_pairwise_cipher)
+ status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+ } else {
+ status = WLAN_STATUS_INVALID_IE;
+ }
+ } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
+ int group_cipher = 0, pairwise_cipher = 0;
+
+ wpa_ie = elems.wpa_ie;
+ wpa_ie_len = elems.wpa_ie_len;
+
+ if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ pstat->dot8021xalg = 1;/* psk, todo:802.1x */
+ pstat->wpa_psk |= BIT(0);
+
+ pstat->wpa_group_cipher = group_cipher & psecuritypriv->wpa_group_cipher;
+ pstat->wpa_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa_pairwise_cipher;
+
+ if (!pstat->wpa_group_cipher)
+ status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+
+ if (!pstat->wpa_pairwise_cipher)
+ status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+ } else {
+ status = WLAN_STATUS_INVALID_IE;
+ }
+ } else {
+ wpa_ie = NULL;
+ wpa_ie_len = 0;
+ }
+
+ if (_STATS_SUCCESSFUL_ != status)
+ goto OnAssocReqFail;
+
+ pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+ if (!wpa_ie) {
+ if (elems.wps_ie) {
+ DBG_88E("STA included WPS IE in "
+ "(Re)Association Request - assume WPS is "
+ "used\n");
+ pstat->flags |= WLAN_STA_WPS;
+ /* wpabuf_free(sta->wps_ie); */
+ /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
+ /* elems.wps_ie_len - 4); */
+ } else {
+ DBG_88E("STA did not include WPA/RSN IE "
+ "in (Re)Association Request - possible WPS "
+ "use\n");
+ pstat->flags |= WLAN_STA_MAYBE_WPS;
+ }
+
+ /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
+ /* that the selected registrar of AP is _FLASE */
+ if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
+ if (pmlmepriv->wps_beacon_ie) {
+ u8 selected_registrar = 0;
+
+ rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
+
+ if (!selected_registrar) {
+ DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n");
+
+ status = _STATS_UNABLE_HANDLE_STA_;
+
+ goto OnAssocReqFail;
+ }
+ }
+ }
+ } else {
+ int copy_len;
+
+ if (psecuritypriv->wpa_psk == 0) {
+ DBG_88E("STA %pM: WPA/RSN IE in association "
+ "request, but AP don't support WPA/RSN\n", pstat->hwaddr);
+
+ status = WLAN_STATUS_INVALID_IE;
+
+ goto OnAssocReqFail;
+ }
+
+ if (elems.wps_ie) {
+ DBG_88E("STA included WPS IE in "
+ "(Re)Association Request - WPS is "
+ "used\n");
+ pstat->flags |= WLAN_STA_WPS;
+ copy_len = 0;
+ } else {
+ copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len + 2);
+ }
+ if (copy_len > 0)
+ memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
+ }
+ /* check if there is WMM IE & support WWM-PS */
+ pstat->flags &= ~WLAN_STA_WME;
+ pstat->qos_option = 0;
+ pstat->qos_info = 0;
+ pstat->has_legacy_ac = true;
+ pstat->uapsd_vo = 0;
+ pstat->uapsd_vi = 0;
+ pstat->uapsd_be = 0;
+ pstat->uapsd_bk = 0;
+ if (pmlmepriv->qospriv.qos_option) {
+ p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
+ for (;;) {
+ p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+ if (p) {
+ if (!memcmp(p + 2, WMM_IE, 6)) {
+ pstat->flags |= WLAN_STA_WME;
+
+ pstat->qos_option = 1;
+ pstat->qos_info = *(p + 8);
+
+ pstat->max_sp_len = (pstat->qos_info >> 5) & 0x3;
+
+ if ((pstat->qos_info & 0xf) != 0xf)
+ pstat->has_legacy_ac = true;
+ else
+ pstat->has_legacy_ac = false;
+
+ if (pstat->qos_info & 0xf) {
+ if (pstat->qos_info & BIT(0))
+ pstat->uapsd_vo = BIT(0) | BIT(1);
+ else
+ pstat->uapsd_vo = 0;
+
+ if (pstat->qos_info & BIT(1))
+ pstat->uapsd_vi = BIT(0) | BIT(1);
+ else
+ pstat->uapsd_vi = 0;
+
+ if (pstat->qos_info & BIT(2))
+ pstat->uapsd_bk = BIT(0) | BIT(1);
+ else
+ pstat->uapsd_bk = 0;
+
+ if (pstat->qos_info & BIT(3))
+ pstat->uapsd_be = BIT(0) | BIT(1);
+ else
+ pstat->uapsd_be = 0;
+ }
+ break;
+ }
+ } else {
+ break;
+ }
+ p = p + ie_len + 2;
+ }
+ }
+
+ /* save HT capabilities in the sta object */
+ memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
+ if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
+ pstat->flags |= WLAN_STA_HT;
+
+ pstat->flags |= WLAN_STA_WME;
+
+ memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
+ } else {
+ pstat->flags &= ~WLAN_STA_HT;
+ }
+ if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags & WLAN_STA_HT)) {
+ status = _STATS_FAILURE_;
+ goto OnAssocReqFail;
+ }
+
+ if ((pstat->flags & WLAN_STA_HT) &&
+ ((pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||
+ (pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP))) {
+ DBG_88E("HT: %pM tried to "
+ "use TKIP with HT association\n", pstat->hwaddr);
+
+ /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
+ /* goto OnAssocReqFail; */
+ }
+
+ pstat->flags |= WLAN_STA_NONERP;
+ for (i = 0; i < pstat->bssratelen; i++) {
+ if ((pstat->bssrateset[i] & 0x7f) > 22) {
+ pstat->flags &= ~WLAN_STA_NONERP;
+ break;
+ }
+ }
+
+ if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+ pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
+ else
+ pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
+
+ if (status != _STATS_SUCCESSFUL_)
+ goto OnAssocReqFail;
+
+#ifdef CONFIG_88EU_P2P
+ pstat->is_p2p_device = false;
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset, NULL, &p2pielen);
+ if (p2pie) {
+ pstat->is_p2p_device = true;
+ p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat);
+ if (p2p_status_code > 0) {
+ pstat->p2p_status_code = p2p_status_code;
+ status = _STATS_CAP_FAIL_;
+ goto OnAssocReqFail;
+ }
+ }
+ }
+ pstat->p2p_status_code = p2p_status_code;
+#endif /* CONFIG_88EU_P2P */
+
+ /* TODO: identify_proprietary_vendor_ie(); */
+ /* Realtek proprietary IE */
+ /* identify if this is Broadcom sta */
+ /* identify if this is ralink sta */
+ /* Customer proprietary IE */
+
+ /* get a unique AID */
+ if (pstat->aid > 0) {
+ DBG_88E(" old AID %d\n", pstat->aid);
+ } else {
+ for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
+ if (!pstapriv->sta_aid[pstat->aid - 1])
+ break;
+
+ /* if (pstat->aid > NUM_STA) { */
+ if (pstat->aid > pstapriv->max_num_sta) {
+ pstat->aid = 0;
+
+ DBG_88E(" no room for more AIDs\n");
+
+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+
+ goto OnAssocReqFail;
+ } else {
+ pstapriv->sta_aid[pstat->aid - 1] = pstat;
+ DBG_88E("allocate new AID=(%d)\n", pstat->aid);
+ }
+ }
+
+ pstat->state &= (~WIFI_FW_ASSOC_STATE);
+ pstat->state |= WIFI_FW_ASSOC_SUCCESS;
+
+ spin_lock_bh(&pstapriv->auth_list_lock);
+ if (!list_empty(&pstat->auth_list)) {
+ list_del_init(&pstat->auth_list);
+ pstapriv->auth_list_cnt--;
+ }
+ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (list_empty(&pstat->asoc_list)) {
+ pstat->expire_to = pstapriv->expire_to;
+ list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
+ pstapriv->asoc_list_cnt++;
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ /* now the station is qualified to join our BSS... */
+ if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
+#ifdef CONFIG_88EU_AP_MODE
+ /* 1 bss_cap_update & sta_info_update */
+ bss_cap_update_on_sta_join(padapter, pstat);
+ sta_info_update(padapter, pstat);
+
+ /* issue assoc rsp before notify station join event. */
+ if (frame_type == WIFI_ASSOCREQ)
+ issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
+ else
+ issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
+
+ /* 2 - report to upper layer */
+ DBG_88E("indicate_sta_join_event to upper layer - hostapd\n");
+ rtw_indicate_sta_assoc_event(padapter, pstat);
+
+ /* 3-(1) report sta add event */
+ report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
+#endif
+ }
+
+ return _SUCCESS;
+
+asoc_class2_error:
+
+#ifdef CONFIG_88EU_AP_MODE
+ issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
+#endif
+
+ return _FAIL;
+
+OnAssocReqFail:
+
+#ifdef CONFIG_88EU_AP_MODE
+ pstat->aid = 0;
+ if (frame_type == WIFI_ASSOCREQ)
+ issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
+ else
+ issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
+#endif
+
+#endif /* CONFIG_88EU_AP_MODE */
+
+ return _FAIL;
+}
+
+unsigned int OnAssocRsp(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ uint i;
+ int res;
+ unsigned short status;
+ struct ndis_802_11_var_ie *pIE;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
+ u8 *pframe = precv_frame->rx_data;
+ uint pkt_len = precv_frame->len;
+
+ DBG_88E("%s\n", __func__);
+
+ /* check A1 matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), get_da(pframe), ETH_ALEN))
+ return _SUCCESS;
+
+ if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
+ return _SUCCESS;
+
+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+ return _SUCCESS;
+
+ _cancel_timer_ex(&pmlmeext->link_timer);
+
+ /* status */
+ status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
+ if (status > 0) {
+ DBG_88E("assoc reject, status code: %d\n", status);
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ res = -4;
+ goto report_assoc_result;
+ }
+
+ /* get capabilities */
+ pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
+
+ /* set slot time */
+ pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
+
+ /* AID */
+ pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4)) & 0x3fff);
+ res = pmlmeinfo->aid;
+
+ /* following are moved to join event callback function */
+ /* to handle HT, WMM, rate adaptive, update MAC reg */
+ /* for not to handle the synchronous IO in the tasklet */
+ for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
+ pIE = (struct ndis_802_11_var_ie *)(pframe + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:
+ if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
+ WMM_param_handler(padapter, pIE);
+ break;
+ case _HT_CAPABILITY_IE_: /* HT caps */
+ HT_caps_handler(padapter, pIE);
+ break;
+ case _HT_EXTRA_INFO_IE_: /* HT info */
+ HT_info_handler(padapter, pIE);
+ break;
+ case _ERPINFO_IE_:
+ ERP_IE_handler(padapter, pIE);
+ break;
+ default:
+ break;
+ }
+
+ i += (pIE->Length + 2);
+ }
+
+ pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+
+ /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
+ UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
+
+report_assoc_result:
+ if (res > 0)
+ rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
+ else
+ kfree(pmlmepriv->assoc_rsp);
+
+ report_join_res(padapter, res);
+
+ return _SUCCESS;
+}
+
+unsigned int OnDeAuth(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ unsigned short reason;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->rx_data;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ /* check A3 */
+ if (!(!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+ return _SUCCESS;
+
+#ifdef CONFIG_88EU_P2P
+ if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
+ _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
+ _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
+
+ DBG_88E("%s Reason code(%d)\n", __func__, reason);
+
+#ifdef CONFIG_88EU_AP_MODE
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
+ reason, GetAddr2Ptr(pframe));
+
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (psta) {
+ u8 updated = 0;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (!list_empty(&psta->asoc_list)) {
+ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, false, reason);
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ associated_clients_update(padapter, updated);
+ }
+
+ return _SUCCESS;
+ } else
+#endif
+ {
+ int ignore_received_deauth = 0;
+
+ /* Before sending the auth frame to start the STA/GC mode connection with AP/GO,
+ * we will send the deauth first.
+ * However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth.
+ * Added the following code to avoid this case.
+ */
+ if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
+ (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
+ if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
+ ignore_received_deauth = 1;
+ } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
+ // TODO: 802.11r
+ ignore_received_deauth = 1;
+ }
+ }
+
+ DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n",
+ reason, GetAddr3Ptr(pframe), ignore_received_deauth);
+
+ if (!ignore_received_deauth)
+ receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
+ }
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+ return _SUCCESS;
+}
+
+unsigned int OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ u16 reason;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->rx_data;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ /* check A3 */
+ if (!(!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+ return _SUCCESS;
+
+#ifdef CONFIG_88EU_P2P
+ if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
+ _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
+ _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
+
+ DBG_88E("%s Reason code(%d)\n", __func__, reason);
+
+#ifdef CONFIG_88EU_AP_MODE
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
+ reason, GetAddr2Ptr(pframe));
+
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (psta) {
+ u8 updated = 0;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (!list_empty(&psta->asoc_list)) {
+ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, false, reason);
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ associated_clients_update(padapter, updated);
+ }
+
+ return _SUCCESS;
+ } else
+#endif
+ {
+ DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
+ reason, GetAddr3Ptr(pframe));
+
+ receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
+ }
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+ return _SUCCESS;
+}
+
+unsigned int OnAtim(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ DBG_88E("%s\n", __func__);
+ return _SUCCESS;
+}
+
+unsigned int on_action_spct(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ unsigned int ret = _FAIL;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *pframe = precv_frame->rx_data;
+ u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+ u8 category;
+ u8 action;
+
+ DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
+
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+
+ if (!psta)
+ goto exit;
+
+ category = frame_body[0];
+ if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
+ goto exit;
+
+ action = frame_body[1];
+ switch (action) {
+ case RTW_WLAN_ACTION_SPCT_MSR_REQ:
+ case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
+ case RTW_WLAN_ACTION_SPCT_TPC_REQ:
+ case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
+ break;
+ case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
+ break;
+ default:
+ break;
+ }
+
+exit:
+ return ret;
+}
+
+unsigned int OnAction_qos(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+unsigned int OnAction_dls(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+unsigned int OnAction_back(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ u8 *addr;
+ struct sta_info *psta = NULL;
+ struct recv_reorder_ctrl *preorder_ctrl;
+ unsigned char *frame_body;
+ unsigned char category, action;
+ unsigned short tid, status, reason_code = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->rx_data;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ /* check RA matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
+ return _SUCCESS;
+
+ DBG_88E("%s\n", __func__);
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
+ return _SUCCESS;
+
+ addr = GetAddr2Ptr(pframe);
+ psta = rtw_get_stainfo(pstapriv, addr);
+
+ if (!psta)
+ return _SUCCESS;
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+ category = frame_body[0];
+ if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */
+ if (!pmlmeinfo->HT_enable)
+ return _SUCCESS;
+ action = frame_body[1];
+ DBG_88E("%s, action=%d\n", __func__, action);
+ switch (action) {
+ case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
+ memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2], sizeof(struct ADDBA_request));
+ process_addba_req(padapter, (u8 *)&pmlmeinfo->ADDBA_req, addr);
+
+ if (pmlmeinfo->bAcceptAddbaReq)
+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
+ else
+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
+ break;
+ case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
+ status = get_unaligned_le16(&frame_body[3]);
+ tid = ((frame_body[5] >> 2) & 0x7);
+ if (status == 0) { /* successful */
+ DBG_88E("agg_enable for TID=%d\n", tid);
+ psta->htpriv.agg_enable_bitmap |= 1 << tid;
+ psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
+ } else {
+ psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
+ }
+ break;
+ case RTW_WLAN_ACTION_DELBA: /* DELBA */
+ if ((frame_body[3] & BIT(3)) == 0) {
+ psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
+ psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
+ reason_code = get_unaligned_le16(&frame_body[4]);
+ } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
+ tid = (frame_body[3] >> 4) & 0x0F;
+ preorder_ctrl = &psta->recvreorder_ctrl[tid];
+ preorder_ctrl->enable = false;
+ preorder_ctrl->indicate_seq = 0xffff;
+ }
+ DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
+ /* todo: how to notify the host while receiving DELETE BA */
+ break;
+ default:
+ break;
+ }
+ }
+ return _SUCCESS;
+}
+
+#ifdef CONFIG_88EU_P2P
+
+static int get_reg_classes_full_count(struct p2p_channels *channel_list)
+{
+ int cnt = 0;
+ int i;
+
+ for (i = 0; i < channel_list->reg_classes; i++) {
+ cnt += channel_list->reg_class[i].channels;
+ }
+
+ return cnt;
+}
+
+void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
+{
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_GO_NEGO_REQ;
+ u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
+ u8 wpsielen = 0, p2pielen = 0;
+ u16 len_channellist_attr = 0;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ DBG_88E("[%s] In\n", __func__);
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pwdinfo->negotiation_dialog_token = 1; /* Initialize the dialog value */
+ pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
+
+ /* WPS Section */
+ wpsielen = 0;
+ /* WPS OUI */
+ *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
+ wpsielen += 4;
+
+ /* WPS version */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+ wpsielen += 2;
+
+ /* Value: */
+ wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
+
+ /* Device Password ID */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
+ wpsielen += 2;
+
+ /* Value: */
+
+ if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
+ else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
+ else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
+
+ wpsielen += 2;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
+
+ /* P2P IE Section. */
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20110306 */
+ /* According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
+ /* 1. P2P Capability */
+ /* 2. Group Owner Intent */
+ /* 3. Configuration Timeout */
+ /* 4. Listen Channel */
+ /* 5. Extended Listen Timing */
+ /* 6. Intended P2P Interface Address */
+ /* 7. Channel List */
+ /* 8. P2P Device Info */
+ /* 9. Operating Channel */
+
+ /* P2P Capability */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Device Capability Bitmap, 1 byte */
+ p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
+
+ /* Group Capability Bitmap, 1 byte */
+ if (pwdinfo->persistent_supported)
+ p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
+ else
+ p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
+
+ /* Group Owner Intent */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Todo the tie breaker bit. */
+ p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
+
+ /* Configuration Timeout */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
+ p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
+
+ /* Listen Channel */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
+
+ /* Channel Number */
+ p2pie[p2pielen++] = pwdinfo->listen_channel; /* listening channel number */
+
+ /* Extended Listen Timing ATTR */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Availability Period */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
+ p2pielen += 2;
+
+ /* Availability Interval */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
+ p2pielen += 2;
+
+ /* Intended P2P Interface Address */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* Channel List */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
+
+ /* Length: */
+ /* Country String(3) */
+ /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
+ /* + number of channels in all classes */
+ len_channellist_attr = 3
+ + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
+ + get_reg_classes_full_count(&pmlmeext->channel_list);
+
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Channel Entry List */
+
+ {
+ int i, j;
+ for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+ /* Operating Class */
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+ /* Number of Channels */
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+ /* Channel List */
+ for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+ }
+ }
+ }
+
+ /* Device Info */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
+
+ /* Length: */
+ /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
+ /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address */
+ memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* Config Method */
+ /* This field should be big endian. Noted by P2P specification. */
+
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
+
+ p2pielen += 2;
+
+ /* Primary Device Type */
+ /* Category ID */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
+ p2pielen += 2;
+
+ /* OUI */
+ *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
+ p2pielen += 4;
+
+ /* Sub Category ID */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
+ p2pielen += 2;
+
+ /* Number of Secondary Device Types */
+ p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
+
+ /* Device Name */
+ /* Type: */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
+ p2pielen += 2;
+
+ /* Length: */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
+ p2pielen += pwdinfo->device_name_len;
+
+ /* Operating Channel */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51;
+
+ /* Channel Number */
+ p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result)
+{
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_GO_NEGO_RESP;
+ u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
+ u8 p2pielen = 0;
+ uint wpsielen = 0;
+ u16 wps_devicepassword_id = 0x0000;
+ __be16 be_tmp;
+ uint wps_devicepassword_id_len = 0;
+ u16 len_channellist_attr = 0;
+
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ DBG_88E("[%s] In, result=%d\n", __func__, result);
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pwdinfo->negotiation_dialog_token = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
+ pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
+
+ /* Commented by Albert 20110328 */
+ /* Try to get the device password ID from the WPS IE of group negotiation request frame */
+ /* WiFi Direct test plan 5.1.15 */
+ rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
+ rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
+ wps_devicepassword_id = be16_to_cpu(be_tmp);
+
+ memset(wpsie, 0x00, 255);
+ wpsielen = 0;
+
+ /* WPS Section */
+ wpsielen = 0;
+ /* WPS OUI */
+ *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
+ wpsielen += 4;
+
+ /* WPS version */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+ wpsielen += 2;
+
+ /* Value: */
+ wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
+
+ /* Device Password ID */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
+ wpsielen += 2;
+
+ /* Value: */
+ if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
+ else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
+ else
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
+ wpsielen += 2;
+
+ /* Commented by Kurt 20120113 */
+ /* If some device wants to do p2p handshake without sending prov_disc_req */
+ /* We have to get peer_req_cm from here. */
+ if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
+ if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
+ else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
+ else
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
+ }
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
+
+ /* P2P IE Section. */
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20100908 */
+ /* According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
+ /* 1. Status */
+ /* 2. P2P Capability */
+ /* 3. Group Owner Intent */
+ /* 4. Configuration Timeout */
+ /* 5. Operating Channel */
+ /* 6. Intended P2P Interface Address */
+ /* 7. Channel List */
+ /* 8. Device Info */
+ /* 9. Group ID (Only GO) */
+
+ /* ToDo: */
+
+ /* P2P Status */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_STATUS;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
+ p2pielen += 2;
+
+ /* Value: */
+ p2pie[p2pielen++] = result;
+
+ /* P2P Capability */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Device Capability Bitmap, 1 byte */
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
+ /* Commented by Albert 2011/03/08 */
+ /* According to the P2P specification */
+ /* if the sending device will be client, the P2P Capability should be reserved of group negotiation response frame */
+ p2pie[p2pielen++] = 0;
+ } else {
+ /* Be group owner or meet the error case */
+ p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
+ }
+
+ /* Group Capability Bitmap, 1 byte */
+ if (pwdinfo->persistent_supported) {
+ p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
+ } else {
+ p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
+ }
+
+ /* Group Owner Intent */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
+ p2pielen += 2;
+
+ /* Value: */
+ if (pwdinfo->peer_intent & 0x01) {
+ /* Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
+ p2pie[p2pielen++] = (pwdinfo->intent << 1);
+ } else {
+ /* Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
+ p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
+ }
+
+ /* Configuration Timeout */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
+ p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
+
+ /* Operating Channel */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51;
+
+ /* Channel Number */
+ p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
+
+ /* Intended P2P Interface Address */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* Channel List */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
+
+ /* Country String(3) */
+ /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
+ /* + number of channels in all classes */
+ len_channellist_attr = 3
+ + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
+ + get_reg_classes_full_count(&pmlmeext->channel_list);
+
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
+
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Channel Entry List */
+
+ {
+ int i, j;
+ for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+ /* Operating Class */
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+ /* Number of Channels */
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+ /* Channel List */
+ for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+ }
+ }
+ }
+
+ /* Device Info */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
+
+ /* Length: */
+ /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
+ /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address */
+ memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* Config Method */
+ /* This field should be big endian. Noted by P2P specification. */
+
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
+
+ p2pielen += 2;
+
+ /* Primary Device Type */
+ /* Category ID */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
+ p2pielen += 2;
+
+ /* OUI */
+ *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
+ p2pielen += 4;
+
+ /* Sub Category ID */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
+ p2pielen += 2;
+
+ /* Number of Secondary Device Types */
+ p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
+
+ /* Device Name */
+ /* Type: */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
+ p2pielen += 2;
+
+ /* Length: */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
+ p2pielen += pwdinfo->device_name_len;
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ /* Group ID Attribute */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
+ p2pielen += 2;
+
+ /* Value: */
+ /* p2P Device Address */
+ memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* SSID */
+ memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
+ p2pielen += pwdinfo->nego_ssidlen;
+ }
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result)
+{
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_GO_NEGO_CONF;
+ u8 p2pie[255] = { 0x00 };
+ u8 p2pielen = 0;
+
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ DBG_88E("[%s] In\n", __func__);
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
+
+ /* P2P IE Section. */
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20110306 */
+ /* According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
+ /* 1. Status */
+ /* 2. P2P Capability */
+ /* 3. Operating Channel */
+ /* 4. Channel List */
+ /* 5. Group ID (if this WiFi is GO) */
+
+ /* P2P Status */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_STATUS;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
+ p2pielen += 2;
+
+ /* Value: */
+ p2pie[p2pielen++] = result;
+
+ /* P2P Capability */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Device Capability Bitmap, 1 byte */
+ p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
+
+ /* Group Capability Bitmap, 1 byte */
+ if (pwdinfo->persistent_supported)
+ p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
+ else
+ p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
+
+ /* Operating Channel */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51;
+ p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
+ } else {
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51;
+
+ /* Channel Number */
+ p2pie[p2pielen++] = pwdinfo->operating_channel; /* Use the listen channel as the operating channel */
+ }
+
+ /* Channel List */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(pwdinfo->channel_list_attr_len);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len);
+ p2pielen += pwdinfo->channel_list_attr_len;
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ /* Group ID Attribute */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
+ p2pielen += 2;
+
+ /* Value: */
+ /* p2P Device Address */
+ memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* SSID */
+ memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
+ p2pielen += pwdinfo->nego_ssidlen;
+ }
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
+ pattrib->last_txcmdsz = pattrib->pktlen;
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr)
+{
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_INVIT_REQ;
+ u8 p2pie[255] = { 0x00 };
+ u8 p2pielen = 0;
+ u8 dialogToken = 3;
+ u16 len_channellist_attr = 0;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, raddr, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
+
+ /* P2P IE Section. */
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20101011 */
+ /* According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */
+ /* 1. Configuration Timeout */
+ /* 2. Invitation Flags */
+ /* 3. Operating Channel (Only GO) */
+ /* 4. P2P Group BSSID (Should be included if I am the GO) */
+ /* 5. Channel List */
+ /* 6. P2P Group ID */
+ /* 7. P2P Device Info */
+
+ /* Configuration Timeout */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
+ p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
+
+ /* Invitation Flags */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
+ p2pielen += 2;
+
+ /* Value: */
+ p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
+
+ /* Operating Channel */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51;
+
+ /* Channel Number */
+ p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch; /* operating channel number */
+
+ if (!memcmp(myid(&padapter->eeprompriv), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
+ /* P2P Group BSSID */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address for GO */
+ memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
+ p2pielen += ETH_ALEN;
+ }
+
+ /* Channel List */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
+
+ /* Length: */
+ /* Country String(3) */
+ /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
+ /* + number of channels in all classes */
+ len_channellist_attr = 3
+ + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
+ + get_reg_classes_full_count(&pmlmeext->channel_list);
+
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
+
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Channel Entry List */
+ {
+ int i, j;
+ for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+ /* Operating Class */
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+ /* Number of Channels */
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+ /* Channel List */
+ for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+ }
+ }
+ }
+
+ /* P2P Group ID */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address for GO */
+ memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* SSID */
+ memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen);
+ p2pielen += pwdinfo->invitereq_info.ssidlen;
+
+ /* Device Info */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
+
+ /* Length: */
+ /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
+ /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address */
+ memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* Config Method */
+ /* This field should be big endian. Noted by P2P specification. */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
+ p2pielen += 2;
+
+ /* Primary Device Type */
+ /* Category ID */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
+ p2pielen += 2;
+
+ /* OUI */
+ *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
+ p2pielen += 4;
+
+ /* Sub Category ID */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
+ p2pielen += 2;
+
+ /* Number of Secondary Device Types */
+ p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
+
+ /* Device Name */
+ /* Type: */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
+ p2pielen += 2;
+
+ /* Length: */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
+ p2pielen += pwdinfo->device_name_len;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code)
+{
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_INVIT_RESP;
+ u8 p2pie[255] = { 0x00 };
+ u8 p2pielen = 0;
+ u16 len_channellist_attr = 0;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, raddr, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
+
+ /* P2P IE Section. */
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20101005 */
+ /* According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
+ /* 1. Status */
+ /* 2. Configuration Timeout */
+ /* 3. Operating Channel (Only GO) */
+ /* 4. P2P Group BSSID (Only GO) */
+ /* 5. Channel List */
+
+ /* P2P Status */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_STATUS;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
+ p2pielen += 2;
+
+ /* Value: */
+ /* When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
+ /* Sent the event receiving the P2P Invitation Req frame to DMP UI. */
+ /* DMP had to compare the MAC address to find out the profile. */
+ /* So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
+ /* If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */
+ /* to NB to rebuild the persistent group. */
+ p2pie[p2pielen++] = status_code;
+
+ /* Configuration Timeout */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
+ p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
+
+ if (status_code == P2P_STATUS_SUCCESS) {
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ /* The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
+ /* In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
+ /* First one is operating channel attribute. */
+ /* Second one is P2P Group BSSID attribute. */
+
+ /* Operating Channel */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
+
+ /* Channel Number */
+ p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
+
+ /* P2P Group BSSID */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address for GO */
+ memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ p2pielen += ETH_ALEN;
+ }
+
+ /* Channel List */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
+
+ /* Length: */
+ /* Country String(3) */
+ /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
+ /* + number of channels in all classes */
+ len_channellist_attr = 3
+ + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
+ + get_reg_classes_full_count(&pmlmeext->channel_list);
+
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Channel Entry List */
+ {
+ int i, j;
+ for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+ /* Operating Class */
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+ /* Number of Channels */
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+ /* Channel List */
+ for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+ p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+ }
+ }
+ }
+ }
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
+{
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ u8 dialogToken = 1;
+ u8 oui_subtype = P2P_PROVISION_DISC_REQ;
+ u8 wpsie[100] = { 0x00 };
+ u8 wpsielen = 0;
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u32 p2pielen = 0;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ DBG_88E("[%s] In\n", __func__);
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
+
+ p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr);
+
+ pframe += p2pielen;
+ pattrib->pktlen += p2pielen;
+
+ wpsielen = 0;
+ /* WPS OUI */
+ *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
+ wpsielen += 4;
+
+ /* WPS version */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+ wpsielen += 2;
+
+ /* Value: */
+ wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
+
+ /* Config Method */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
+ wpsielen += 2;
+
+ /* Value: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
+ wpsielen += 2;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo)
+{
+ u8 i, match_result = 0;
+
+ DBG_88E("[%s] peermac=%.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
+ peermacaddr[0], peermacaddr[1], peermacaddr[2], peermacaddr[3], peermacaddr[4], peermacaddr[5]);
+
+ for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
+ DBG_88E("[%s] profileinfo_mac=%.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
+ profileinfo->peermac[0], profileinfo->peermac[1], profileinfo->peermac[2],
+ profileinfo->peermac[3], profileinfo->peermac[4], profileinfo->peermac[5]);
+ if (!memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
+ match_result = 1;
+ DBG_88E("[%s] Match!\n", __func__);
+ break;
+ }
+ }
+ return match_result;
+}
+
+void issue_probersp_p2p(struct adapter *padapter, unsigned char *da)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned char *mac;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ u16 beacon_interval = 100;
+ u16 capInfo = 0;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 wpsie[255] = { 0x00 };
+ u32 wpsielen = 0, p2pielen = 0;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ mac = myid(&padapter->eeprompriv);
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+
+ /* Use the device address for BSSID field. */
+ memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(fctrl, WIFI_PROBERSP);
+
+ pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = pattrib->hdrlen;
+ pframe += pattrib->hdrlen;
+
+ /* timestamp will be inserted by hardware */
+ pframe += 8;
+ pattrib->pktlen += 8;
+
+ /* beacon interval: 2 bytes */
+ memcpy(pframe, (unsigned char *)&beacon_interval, 2);
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* capability info: 2 bytes */
+ /* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
+ capInfo |= cap_ShortPremble;
+ capInfo |= cap_ShortSlot;
+
+ memcpy(pframe, (unsigned char *)&capInfo, 2);
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
+
+ /* supported rates... */
+ /* Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
+
+ /* DS parameter set */
+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
+
+ /* Todo: WPS IE */
+ /* Noted by Albert 20100907 */
+ /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */
+
+ wpsielen = 0;
+ /* WPS OUI */
+ *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
+ wpsielen += 4;
+
+ /* WPS version */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+ wpsielen += 2;
+
+ /* Value: */
+ wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
+
+ /* WiFi Simple Config State */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+ wpsielen += 2;
+
+ /* Value: */
+ wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG; /* Not Configured. */
+
+ /* Response Type */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+ wpsielen += 2;
+
+ /* Value: */
+ wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
+
+ /* UUID-E */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
+ wpsielen += 2;
+
+ /* Value: */
+ memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ wpsielen += 0x10;
+
+ /* Manufacturer */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);
+ wpsielen += 2;
+
+ /* Value: */
+ memcpy(wpsie + wpsielen, "Realtek", 7);
+ wpsielen += 7;
+
+ /* Model Name */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);
+ wpsielen += 2;
+
+ /* Value: */
+ memcpy(wpsie + wpsielen, "8188EU", 6);
+ wpsielen += 6;
+
+ /* Model Number */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+ wpsielen += 2;
+
+ /* Value: */
+ wpsie[wpsielen++] = 0x31; /* character 1 */
+
+ /* Serial Number */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
+ wpsielen += 2;
+
+ /* Value: */
+ memcpy(wpsie + wpsielen, "123456", ETH_ALEN);
+ wpsielen += ETH_ALEN;
+
+ /* Primary Device Type */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
+ wpsielen += 2;
+
+ /* Value: */
+ /* Category ID */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
+ wpsielen += 2;
+
+ /* OUI */
+ *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
+ wpsielen += 4;
+
+ /* Sub Category ID */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
+ wpsielen += 2;
+
+ /* Device Name */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
+ wpsielen += 2;
+
+ /* Value: */
+ if (pwdinfo->device_name_len) {
+ memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
+ wpsielen += pwdinfo->device_name_len;
+ }
+
+ /* Config Method */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
+ wpsielen += 2;
+
+ /* Value: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
+ wpsielen += 2;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
+
+ p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
+ pframe += p2pielen;
+ pattrib->pktlen += p2pielen;
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static int _issue_probereq_p2p(struct adapter *padapter, u8 *da, int wait_ack)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned char *mac;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
+ u16 wpsielen = 0, p2pielen = 0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ mac = myid(&padapter->eeprompriv);
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ if (da) {
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, da, ETH_ALEN);
+ } else {
+ if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
+ /* This two flags will be set when this is only the P2P client mode. */
+ memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
+ } else {
+ /* broadcast probe request frame */
+ memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
+ }
+ }
+ memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_PROBEREQ);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
+ pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &pattrib->pktlen);
+ else
+ pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
+
+ /* Use the OFDM rate in the P2P probe request frame. (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
+
+ /* WPS IE */
+ /* Noted by Albert 20110221 */
+ /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */
+
+ wpsielen = 0;
+ /* WPS OUI */
+ *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
+ wpsielen += 4;
+
+ /* WPS version */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
+ wpsielen += 2;
+
+ /* Value: */
+ wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
+
+ if (!pmlmepriv->wps_probe_req_ie) {
+ /* UUID-E */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
+ wpsielen += 2;
+
+ /* Value: */
+ memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ wpsielen += 0x10;
+
+ /* Config Method */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
+ wpsielen += 2;
+
+ /* Value: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
+ wpsielen += 2;
+ }
+
+ /* Device Name */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
+ wpsielen += 2;
+
+ /* Value: */
+ memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
+ wpsielen += pwdinfo->device_name_len;
+
+ /* Primary Device Type */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
+ wpsielen += 2;
+
+ /* Value: */
+ /* Category ID */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
+ wpsielen += 2;
+
+ /* OUI */
+ *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
+ wpsielen += 4;
+
+ /* Sub Category ID */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
+ wpsielen += 2;
+
+ /* Device Password ID */
+ /* Type: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
+ wpsielen += 2;
+
+ /* Length: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
+ wpsielen += 2;
+
+ /* Value: */
+ *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); /* Registrar-specified */
+ wpsielen += 2;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20110221 */
+ /* According to the P2P Specification, the probe request frame should contain 5 P2P attributes */
+ /* 1. P2P Capability */
+ /* 2. P2P Device ID if this probe request wants to find the specific P2P device */
+ /* 3. Listen Channel */
+ /* 4. Extended Listen Timing */
+ /* 5. Operating Channel if this WiFi is working as the group owner now */
+
+ /* P2P Capability */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Device Capability Bitmap, 1 byte */
+ p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
+
+ /* Group Capability Bitmap, 1 byte */
+ if (pwdinfo->persistent_supported)
+ p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
+ else
+ p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
+
+ /* Listen Channel */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
+
+ /* Channel Number */
+ p2pie[p2pielen++] = pwdinfo->listen_channel; /* listen channel */
+
+ /* Extended Listen Timing */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Availability Period */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
+ p2pielen += 2;
+
+ /* Availability Interval */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
+ p2pielen += 2;
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ /* Operating Channel (if this WiFi is working as the group owner now) */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Country String */
+ p2pie[p2pielen++] = 'X';
+ p2pie[p2pielen++] = 'X';
+
+ /* The third byte should be set to 0x04. */
+ /* Described in the "Operating Channel Attribute" section. */
+ p2pie[p2pielen++] = 0x04;
+
+ /* Operating Class */
+ p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
+
+ /* Channel Number */
+ p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
+ }
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
+
+ if (pmlmepriv->wps_probe_req_ie) {
+ /* WPS IE */
+ memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
+ pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
+ pframe += pmlmepriv->wps_probe_req_ie_len;
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+inline void issue_probereq_p2p(struct adapter *adapter, u8 *da)
+{
+ _issue_probereq_p2p(adapter, da, false);
+}
+
+int issue_probereq_p2p_ex(struct adapter *adapter, u8 *da, int try_cnt, int wait_ms)
+{
+ int ret;
+ int i = 0;
+ u32 start = jiffies;
+
+ do {
+ ret = _issue_probereq_p2p(adapter, da, wait_ms > 0);
+
+ i++;
+
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ msleep(wait_ms);
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(adapter), da, rtw_get_oper_ch(adapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ }
+exit:
+ return ret;
+}
+
+#endif /* CONFIG_88EU_P2P */
+
+static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
+{
+ struct adapter *adapter = recv_frame->adapter;
+ struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+ u8 *frame = recv_frame->rx_data;
+ u16 seq_ctrl = ((recv_frame->attrib.seq_num & 0xffff) << 4) |
+ (recv_frame->attrib.frag_num & 0xf);
+
+ if (GetRetry(frame)) {
+ if (token >= 0) {
+ if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) {
+ DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
+ FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
+ return _FAIL;
+ }
+ } else {
+ if (seq_ctrl == mlmeext->action_public_rxseq) {
+ DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
+ FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
+ return _FAIL;
+ }
+ }
+ }
+
+ mlmeext->action_public_rxseq = seq_ctrl;
+
+ if (token >= 0)
+ mlmeext->action_public_dialog_token = token;
+
+ return _SUCCESS;
+}
+
+static unsigned int on_action_public_p2p(struct recv_frame *precv_frame)
+{
+ u8 *pframe = precv_frame->rx_data;
+ u8 *frame_body;
+ u8 dialogToken = 0;
+#ifdef CONFIG_88EU_P2P
+ struct adapter *padapter = precv_frame->adapter;
+ uint len = precv_frame->len;
+ u8 *p2p_ie;
+ u32 p2p_ielen;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 result = P2P_STATUS_SUCCESS;
+ u8 empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+#endif /* CONFIG_88EU_P2P */
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+ dialogToken = frame_body[7];
+
+ if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
+ return _FAIL;
+
+#ifdef CONFIG_88EU_P2P
+ _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
+ /* Do nothing if the driver doesn't enable the P2P function. */
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
+ return _SUCCESS;
+
+ len -= sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ switch (frame_body[6]) { /* OUI Subtype */
+ case P2P_GO_NEGO_REQ:
+ DBG_88E("[%s] Got GO Nego Req Frame\n", __func__);
+ memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
+ rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) {
+ /* Commented by Albert 20110526 */
+ /* In this case, this means the previous nego fail doesn't be reset yet. */
+ _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+ /* Restore the previous p2p state */
+ rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+ DBG_88E("[%s] Restore the previous p2p state to %d\n", __func__, rtw_p2p_state(pwdinfo));
+ }
+
+ /* Commented by Kurt 20110902 */
+ /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+
+ /* Commented by Kurt 20120113 */
+ /* Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
+ if (!memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))
+ memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
+
+ result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);
+ issue_p2p_GO_response(padapter, GetAddr2Ptr(pframe), frame_body, len, result);
+
+ /* Commented by Albert 20110718 */
+ /* No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
+ _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
+ break;
+ case P2P_GO_NEGO_RESP:
+ DBG_88E("[%s] Got GO Nego Resp Frame\n", __func__);
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
+ /* Commented by Albert 20110425 */
+ /* The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
+ _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+ pwdinfo->nego_req_info.benable = false;
+ result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len);
+ issue_p2p_GO_confirm(pwdinfo->padapter, GetAddr2Ptr(pframe), result);
+ if (P2P_STATUS_SUCCESS == result) {
+ if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
+ pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
+ pwdinfo->p2p_info.scan_op_ch_only = 1;
+ _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
+ }
+ }
+ /* Reset the dialog token for group negotiation frames. */
+ pwdinfo->negotiation_dialog_token = 1;
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
+ _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
+ } else {
+ DBG_88E("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __func__);
+ }
+ break;
+ case P2P_GO_NEGO_CONF:
+ DBG_88E("[%s] Got GO Nego Confirm Frame\n", __func__);
+ result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len);
+ if (P2P_STATUS_SUCCESS == result) {
+ if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
+ pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
+ pwdinfo->p2p_info.scan_op_ch_only = 1;
+ _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
+ }
+ }
+ break;
+ case P2P_INVIT_REQ:
+ /* Added by Albert 2010/10/05 */
+ /* Received the P2P Invite Request frame. */
+
+ DBG_88E("[%s] Got invite request frame!\n", __func__);
+ p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
+ if (p2p_ie) {
+ /* Parse the necessary information from the P2P Invitation Request frame. */
+ /* For example: The MAC address of sending this P2P Invitation Request frame. */
+ u32 attr_contentlen = 0;
+ u8 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+ struct group_id_info group_id;
+ u8 invitation_flag = 0;
+
+ rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
+ if (attr_contentlen) {
+ rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
+ /* Commented by Albert 20120510 */
+ /* Copy to the pwdinfo->p2p_peer_interface_addr. */
+ /* So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
+ /* #> iwpriv wlan0 p2p_get peer_ifa */
+ /* After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
+
+ if (attr_contentlen) {
+ DBG_88E("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
+ pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
+ pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
+ pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
+ }
+
+ if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) {
+ /* Re-invoke the persistent group. */
+
+ memset(&group_id, 0x00, sizeof(struct group_id_info));
+ rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
+ if (attr_contentlen) {
+ if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
+ /* The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ status_code = P2P_STATUS_SUCCESS;
+ } else {
+ /* The p2p device sending this p2p invitation request wants to be the persistent GO. */
+ if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) {
+ u8 operatingch_info[5] = { 0x00 };
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
+ if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4])) {
+ /* The operating channel is acceptable for this device. */
+ pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4];
+ pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
+ _set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ status_code = P2P_STATUS_SUCCESS;
+ } else {
+ /* The operating channel isn't supported by this device. */
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
+ _set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
+ }
+ } else {
+ /* Commented by Albert 20121130 */
+ /* Intel will use the different P2P IE to store the operating channel information */
+ /* Workaround for Intel WiDi 3.5 */
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ status_code = P2P_STATUS_SUCCESS;
+ }
+ } else {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
+ status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
+ }
+ }
+ } else {
+ DBG_88E("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
+ status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+ }
+ } else {
+ /* Received the invitation to join a P2P group. */
+
+ memset(&group_id, 0x00, sizeof(struct group_id_info));
+ rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
+ if (attr_contentlen) {
+ if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
+ /* In this case, the GO can't be myself. */
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
+ status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+ } else {
+ /* The p2p device sending this p2p invitation request wants to join an existing P2P group */
+ /* Commented by Albert 2012/06/28 */
+ /* In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
+ /* The peer device address should be the destination address for the provisioning discovery request. */
+ /* Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
+ /* The peer interface address should be the address for WPS mac address */
+ memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr, ETH_ALEN);
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
+ status_code = P2P_STATUS_SUCCESS;
+ }
+ } else {
+ DBG_88E("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
+ status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+ }
+ }
+ } else {
+ DBG_88E("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __func__);
+ status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+ }
+
+ DBG_88E("[%s] status_code = %d\n", __func__, status_code);
+
+ pwdinfo->inviteresp_info.token = frame_body[7];
+ issue_p2p_invitation_response(padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code);
+ }
+ break;
+ case P2P_INVIT_RESP: {
+ u8 attr_content = 0x00;
+ u32 attr_contentlen = 0;
+
+ DBG_88E("[%s] Got invite response frame!\n", __func__);
+ _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+ p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
+ if (p2p_ie) {
+ rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
+
+ if (attr_contentlen == 1) {
+ DBG_88E("[%s] Status = %d\n", __func__, attr_content);
+ pwdinfo->invitereq_info.benable = false;
+
+ if (attr_content == P2P_STATUS_SUCCESS) {
+ if (!memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ } else {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ }
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
+ } else {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
+ }
+ } else {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
+ }
+ } else {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
+ }
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL))
+ _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
+ break;
+ }
+ case P2P_DEVDISC_REQ:
+ process_p2p_devdisc_req(pwdinfo, pframe, len);
+ break;
+ case P2P_DEVDISC_RESP:
+ process_p2p_devdisc_resp(pwdinfo, pframe, len);
+ break;
+ case P2P_PROVISION_DISC_REQ:
+ DBG_88E("[%s] Got Provisioning Discovery Request Frame\n", __func__);
+ process_p2p_provdisc_req(pwdinfo, pframe, len);
+ memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
+
+ /* 20110902 Kurt */
+ /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
+ _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
+ break;
+ case P2P_PROVISION_DISC_RESP:
+ /* Commented by Albert 20110707 */
+ /* Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
+ DBG_88E("[%s] Got Provisioning Discovery Response Frame\n", __func__);
+ /* Commented by Albert 20110426 */
+ /* The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
+ _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
+ process_p2p_provdisc_resp(pwdinfo, pframe);
+ _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
+ break;
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ return _SUCCESS;
+}
+
+static unsigned int on_action_public_vendor(struct recv_frame *precv_frame)
+{
+ unsigned int ret = _FAIL;
+ u8 *pframe = precv_frame->rx_data;
+ u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ if (!memcmp(frame_body + 2, P2P_OUI, 4)) {
+ ret = on_action_public_p2p(precv_frame);
+ }
+
+ return ret;
+}
+
+static unsigned int on_action_public_default(struct recv_frame *precv_frame, u8 action)
+{
+ unsigned int ret = _FAIL;
+ u8 *pframe = precv_frame->rx_data;
+ u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+ u8 token;
+
+ token = frame_body[2];
+
+ if (rtw_action_public_decache(precv_frame, token) == _FAIL)
+ goto exit;
+
+ ret = _SUCCESS;
+
+exit:
+ return ret;
+}
+
+unsigned int on_action_public(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ unsigned int ret = _FAIL;
+ u8 *pframe = precv_frame->rx_data;
+ u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+ u8 category, action;
+
+ /* check RA matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))
+ goto exit;
+
+ category = frame_body[0];
+ if (category != RTW_WLAN_CATEGORY_PUBLIC)
+ goto exit;
+
+ action = frame_body[1];
+ switch (action) {
+ case ACT_PUBLIC_VENDOR:
+ ret = on_action_public_vendor(precv_frame);
+ break;
+ default:
+ ret = on_action_public_default(precv_frame, action);
+ break;
+ }
+
+exit:
+ return ret;
+}
+
+unsigned int OnAction_ht(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+unsigned int OnAction_wmm(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+unsigned int OnAction_p2p(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+#ifdef CONFIG_88EU_P2P
+ u8 *frame_body;
+ u8 category, OUI_Subtype;
+ u8 *pframe = precv_frame->rx_data;
+ uint len = precv_frame->len;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("%s\n", __func__);
+
+ /* check RA matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
+ return _SUCCESS;
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+ category = frame_body[0];
+ if (category != RTW_WLAN_CATEGORY_P2P)
+ return _SUCCESS;
+
+ if (be32_to_cpu(*((__be32 *)(frame_body + 1))) != P2POUI)
+ return _SUCCESS;
+
+ len -= sizeof(struct rtw_ieee80211_hdr_3addr);
+ OUI_Subtype = frame_body[5];
+
+ switch (OUI_Subtype) {
+ case P2P_NOTICE_OF_ABSENCE:
+ break;
+ case P2P_PRESENCE_REQUEST:
+ process_p2p_presence_req(pwdinfo, pframe, len);
+ break;
+ case P2P_PRESENCE_RESPONSE:
+ break;
+ case P2P_GO_DISC_REQUEST:
+ break;
+ default:
+ break;
+ }
+#endif /* CONFIG_88EU_P2P */
+ return _SUCCESS;
+}
+
+unsigned int OnAction(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ int i;
+ unsigned char category;
+ struct action_handler *ptable;
+ unsigned char *frame_body;
+ u8 *pframe = precv_frame->rx_data;
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+ category = frame_body[0];
+
+ for (i = 0; i < sizeof(OnAction_tbl) / sizeof(struct action_handler); i++) {
+ ptable = &OnAction_tbl[i];
+ if (category == ptable->num)
+ ptable->func(padapter, precv_frame);
+ }
+ return _SUCCESS;
+}
+
+unsigned int DoReserved(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
+{
+ struct xmit_frame *pmgntframe;
+ struct xmit_buf *pxmitbuf;
+
+ pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
+ if (!pmgntframe) {
+ DBG_88E("%s, alloc xmitframe fail\n", __func__);
+ return NULL;
+ }
+
+ pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
+ if (!pxmitbuf) {
+ DBG_88E("%s, alloc xmitbuf fail\n", __func__);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ return NULL;
+ }
+ pmgntframe->frame_tag = MGNT_FRAMETAG;
+ pmgntframe->pxmitbuf = pxmitbuf;
+ pmgntframe->buf_addr = pxmitbuf->pbuf;
+ pxmitbuf->priv_data = pmgntframe;
+ return pmgntframe;
+}
+
+/****************************************************************************
+
+Following are some TX fuctions for WiFi MLME
+
+*****************************************************************************/
+
+void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ pmlmeext->tx_rate = rate;
+ DBG_88E("%s(): rate = %x\n", __func__, rate);
+}
+
+void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
+
+ pattrib->hdrlen = 24;
+ pattrib->nr_frags = 1;
+ pattrib->priority = 7;
+ pattrib->mac_id = 0;
+ pattrib->qsel = 0x12;
+
+ pattrib->pktlen = 0;
+
+ if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
+ pattrib->raid = 6;/* b mode */
+ else
+ pattrib->raid = 5;/* a/g mode */
+
+ pattrib->encrypt = _NO_PRIVACY_;
+ pattrib->bswenc = false;
+
+ pattrib->qos_en = false;
+ pattrib->ht_en = false;
+ pattrib->bwmode = HT_CHANNEL_WIDTH_20;
+ pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pattrib->sgi = false;
+
+ pattrib->seqnum = pmlmeext->mgnt_seq;
+
+ pattrib->retry_ctrl = true;
+}
+
+void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
+{
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return;
+
+ rtw_hal_mgnt_xmit(padapter, pmgntframe);
+}
+
+s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
+{
+ s32 ret = _FAIL;
+ struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
+ struct submit_ctx sctx;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return ret;
+
+ rtw_sctx_init(&sctx, timeout_ms);
+ pxmitbuf->sctx = &sctx;
+
+ ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
+
+ if (ret == _SUCCESS)
+ ret = rtw_sctx_wait(&sctx);
+
+ return ret;
+}
+
+s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
+{
+ s32 ret = _FAIL;
+ u32 timeout_ms = 500;/* 500ms */
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return -1;
+
+ _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+ pxmitpriv->ack_tx = true;
+
+ pmgntframe->ack_report = 1;
+ if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
+ ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
+ }
+
+ pxmitpriv->ack_tx = false;
+ _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+
+ return ret;
+}
+
+static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
+{
+ u8 *ssid_ie;
+ int ssid_len_ori;
+ int len_diff = 0;
+
+ ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
+
+ if (ssid_ie && ssid_len_ori > 0) {
+ switch (hidden_ssid_mode) {
+ case 1: {
+ u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
+ u32 remain_len = 0;
+
+ remain_len = ies_len - (next_ie - ies);
+
+ ssid_ie[1] = 0;
+ memcpy(ssid_ie + 2, next_ie, remain_len);
+ len_diff -= ssid_len_ori;
+
+ break;
+ }
+ case 2:
+ memset(&ssid_ie[2], 0, ssid_len_ori);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return len_diff;
+}
+
+void issue_beacon(struct adapter *padapter, int timeout_ms)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned int rate_len;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe) {
+ DBG_88E("%s, alloc mgnt frame fail\n", __func__);
+ return;
+ }
+#if defined(CONFIG_88EU_AP_MODE)
+ spin_lock_bh(&pmlmepriv->bcn_update_lock);
+#endif /* if defined (CONFIG_88EU_AP_MODE) */
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->qsel = 0x10;
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
+ /* pmlmeext->mgnt_seq++; */
+ SetFrameSubType(pframe, WIFI_BEACON);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+#ifdef CONFIG_88EU_P2P
+ /* for P2P : Primary Device Type & Device Name */
+ u32 wpsielen = 0, insert_len = 0;
+ u8 *wpsie = NULL;
+ wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {
+ uint wps_offset, remainder_ielen;
+ u8 *premainder_ie, *pframe_wscie;
+
+ wps_offset = (uint)(wpsie - cur_network->IEs);
+ premainder_ie = wpsie + wpsielen;
+ remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
+ pframe_wscie = pframe + wps_offset;
+ memcpy(pframe, cur_network->IEs, wps_offset + wpsielen);
+ pframe += (wps_offset + wpsielen);
+ pattrib->pktlen += (wps_offset + wpsielen);
+
+ /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
+ /* Primary Device Type */
+ /* Type: */
+ *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
+ insert_len += 2;
+
+ /* Length: */
+ *(__be16 *)(pframe + insert_len) = cpu_to_be16(0x0008);
+ insert_len += 2;
+
+ /* Value: */
+ /* Category ID */
+ *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
+ insert_len += 2;
+
+ /* OUI */
+ *(__be32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);
+ insert_len += 4;
+
+ /* Sub Category ID */
+ *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
+ insert_len += 2;
+
+ /* Device Name */
+ /* Type: */
+ *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
+ insert_len += 2;
+
+ /* Length: */
+ *(__be16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);
+ insert_len += 2;
+
+ /* Value: */
+ memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);
+ insert_len += pwdinfo->device_name_len;
+
+ /* update wsc ie length */
+ *(pframe_wscie + 1) = (wpsielen - 2) + insert_len;
+
+ /* pframe move to end */
+ pframe += insert_len;
+ pattrib->pktlen += insert_len;
+
+ /* copy remainder_ie to pframe */
+ memcpy(pframe, premainder_ie, remainder_ielen);
+ pframe += remainder_ielen;
+ pattrib->pktlen += remainder_ielen;
+ } else
+#endif /* CONFIG_88EU_P2P */
+ {
+ int len_diff;
+ memcpy(pframe, cur_network->IEs, cur_network->IELength);
+ len_diff = update_hidden_ssid(
+ pframe + _BEACON_IE_OFFSET_
+ , cur_network->IELength - _BEACON_IE_OFFSET_
+ , pmlmeinfo->hidden_ssid_mode
+ );
+ pframe += (cur_network->IELength + len_diff);
+ pattrib->pktlen += (cur_network->IELength + len_diff);
+ }
+
+ {
+ u8 *wps_ie;
+ uint wps_ielen;
+ u8 sr = 0;
+ wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_,
+ pattrib->pktlen - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen);
+ if (wps_ie && wps_ielen > 0)
+ rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
+ if (sr != 0)
+ set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
+ else
+ _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
+ }
+
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ u32 len;
+ len = build_beacon_p2p_ie(pwdinfo, pframe);
+
+ pframe += len;
+ pattrib->pktlen += len;
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ goto _issue_bcn;
+ }
+
+ /* below for ad-hoc mode */
+
+ /* timestamp will be inserted by hardware */
+ pframe += 8;
+ pattrib->pktlen += 8;
+
+ /* beacon interval: 2 bytes */
+
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* capability info: 2 bytes */
+
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
+
+ /* supported rates... */
+ rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
+
+ /* DS parameter set */
+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
+
+ {
+ u8 erpinfo = 0;
+ u32 ATIMWindow;
+ /* IBSS Parameter Set... */
+ ATIMWindow = 0;
+ pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
+
+ /* ERP IE */
+ pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
+ }
+
+ /* EXTERNDED SUPPORTED RATE */
+ if (rate_len > 8)
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
+ /* todo:HT for adhoc */
+_issue_bcn:
+
+#if defined(CONFIG_88EU_AP_MODE)
+ pmlmepriv->update_bcn = false;
+
+ spin_unlock_bh(&pmlmepriv->bcn_update_lock);
+#endif /* if defined (CONFIG_88EU_AP_MODE) */
+
+ if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
+ DBG_88E("beacon frame too large\n");
+ return;
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ /* DBG_88E("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
+ if (timeout_ms > 0)
+ dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
+ else
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned char *mac, *bssid;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+#if defined(CONFIG_88EU_AP_MODE)
+ u8 *pwps_ie;
+ uint wps_ielen;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+#endif /* if defined (CONFIG_88EU_AP_MODE) */
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ unsigned int rate_len;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe) {
+ DBG_88E("%s, alloc mgnt frame fail\n", __func__);
+ return;
+ }
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ mac = myid(&padapter->eeprompriv);
+ bssid = cur_network->MacAddress;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(fctrl, WIFI_PROBERSP);
+
+ pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = pattrib->hdrlen;
+ pframe += pattrib->hdrlen;
+
+ if (cur_network->IELength > MAX_IE_SZ)
+ return;
+
+#if defined(CONFIG_88EU_AP_MODE)
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+ pwps_ie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
+
+ /* inerset & update wps_probe_resp_ie */
+ if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
+ uint wps_offset, remainder_ielen;
+ u8 *premainder_ie;
+
+ wps_offset = (uint)(pwps_ie - cur_network->IEs);
+
+ premainder_ie = pwps_ie + wps_ielen;
+
+ remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
+
+ memcpy(pframe, cur_network->IEs, wps_offset);
+ pframe += wps_offset;
+ pattrib->pktlen += wps_offset;
+
+ wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
+ if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) {
+ memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2);
+ pframe += wps_ielen + 2;
+ pattrib->pktlen += wps_ielen + 2;
+ }
+
+ if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
+ memcpy(pframe, premainder_ie, remainder_ielen);
+ pframe += remainder_ielen;
+ pattrib->pktlen += remainder_ielen;
+ }
+ } else {
+ memcpy(pframe, cur_network->IEs, cur_network->IELength);
+ pframe += cur_network->IELength;
+ pattrib->pktlen += cur_network->IELength;
+ }
+ } else
+#endif
+ {
+ /* timestamp will be inserted by hardware */
+ pframe += 8;
+ pattrib->pktlen += 8;
+
+ /* beacon interval: 2 bytes */
+
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* capability info: 2 bytes */
+
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* below for ad-hoc mode */
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
+
+ /* supported rates... */
+ rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
+
+ /* DS parameter set */
+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+ u8 erpinfo = 0;
+ u32 ATIMWindow;
+ /* IBSS Parameter Set... */
+ /* ATIMWindow = cur->Configuration.ATIMWindow; */
+ ATIMWindow = 0;
+ pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
+
+ /* ERP IE */
+ pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
+ }
+
+ /* EXTERNDED SUPPORTED RATE */
+ if (rate_len > 8)
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
+ /* todo:HT for adhoc */
+ }
+
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
+ u32 len;
+ len = build_probe_resp_p2p_ie(pwdinfo, pframe);
+
+ pframe += len;
+ pattrib->pktlen += len;
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, int wait_ack)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned char *mac;
+ unsigned char bssrate[NumRates];
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ int bssrate_len = 0;
+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ mac = myid(&padapter->eeprompriv);
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ if (da) {
+ /* unicast probe request frame */
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, da, ETH_ALEN);
+ } else {
+ /* broadcast probe request frame */
+ memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
+ }
+
+ memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_PROBEREQ);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ if (pssid)
+ pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &pattrib->pktlen);
+ else
+ pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pattrib->pktlen);
+
+ get_rate_set(padapter, bssrate, &bssrate_len);
+
+ if (bssrate_len > 8) {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
+ } else {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
+ }
+
+ /* add wps_ie for wps2.0 */
+ if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
+ memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
+ pframe += pmlmepriv->wps_probe_req_ie_len;
+ pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
+{
+ _issue_probereq(padapter, pssid, da, false);
+}
+
+int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da,
+ int try_cnt, int wait_ms)
+{
+ int ret;
+ int i = 0;
+ u32 start = jiffies;
+
+ do {
+ ret = _issue_probereq(padapter, pssid, da, wait_ms > 0);
+
+ i++;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ msleep(wait_ms);
+
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ }
+exit:
+ return ret;
+}
+
+/* if psta == NULL, indiate we are station(client) now... */
+void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned int val32;
+ u16 val16;
+#ifdef CONFIG_88EU_AP_MODE
+ __le16 le_val16;
+#endif
+ int use_shared_key = 0;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_AUTH);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ if (psta) {/* for AP mode */
+#ifdef CONFIG_88EU_AP_MODE
+
+ memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
+
+ /* setting auth algo number */
+ val16 = (u16)psta->authalg;
+
+ if (status != _STATS_SUCCESSFUL_)
+ val16 = 0;
+
+ if (val16) {
+ le_val16 = cpu_to_le16(val16);
+ use_shared_key = 1;
+ } else {
+ le_val16 = 0;
+ }
+
+ pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_val16, &pattrib->pktlen);
+
+ /* setting auth seq number */
+ val16 = (u16)psta->auth_seq;
+ le_val16 = cpu_to_le16(val16);
+ pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_val16, &pattrib->pktlen);
+
+ /* setting status code... */
+ val16 = status;
+ le_val16 = cpu_to_le16(val16);
+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_val16, &pattrib->pktlen);
+
+ /* added challenging text... */
+ if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
+ pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &pattrib->pktlen);
+#endif
+ } else {
+ __le32 le_tmp32;
+ __le16 le_tmp16;
+ memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+
+ /* setting auth algo number */
+ val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */
+ if (val16)
+ use_shared_key = 1;
+
+ /* setting IV for auth seq #3 */
+ if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
+ val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
+ le_tmp32 = cpu_to_le32(val32);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &pattrib->pktlen);
+
+ pattrib->iv_len = 4;
+ }
+
+ le_tmp16 = cpu_to_le16(val16);
+ pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
+
+ /* setting auth seq number */
+ val16 = pmlmeinfo->auth_seq;
+ le_tmp16 = cpu_to_le16(val16);
+ pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
+
+ /* setting status code... */
+ le_tmp16 = cpu_to_le16(status);
+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
+
+ /* then checking to see if sending challenging text... */
+ if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
+ pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &pattrib->pktlen);
+
+ SetPrivacy(fctrl);
+
+ pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pattrib->encrypt = _WEP40_;
+
+ pattrib->icv_len = 4;
+
+ pattrib->pktlen += pattrib->icv_len;
+ }
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
+ DBG_88E("%s\n", __func__);
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
+{
+#ifdef CONFIG_88EU_AP_MODE
+ struct xmit_frame *pmgntframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ struct pkt_attrib *pattrib;
+ unsigned char *pbuf, *pframe;
+ unsigned short val;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+ u8 *ie = pnetwork->IEs;
+ __le16 lestatus, leval;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ DBG_88E("%s\n", __func__);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
+ memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
+ SetFrameSubType(pwlanhdr, pkt_type);
+ else
+ return;
+
+ pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen += pattrib->hdrlen;
+ pframe += pattrib->hdrlen;
+
+ /* capability */
+ val = *(unsigned short *)rtw_get_capability_from_ie(ie);
+
+ pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &pattrib->pktlen);
+
+ lestatus = cpu_to_le16(status);
+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &pattrib->pktlen);
+
+ leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
+ pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&leval, &pattrib->pktlen);
+
+ if (pstat->bssratelen <= 8) {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &pattrib->pktlen);
+ } else {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, pstat->bssratelen - 8, pstat->bssrateset + 8, &pattrib->pktlen);
+ }
+
+ if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
+ uint ie_len = 0;
+
+ /* FILL HT CAP INFO IE */
+ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+ if (pbuf && ie_len > 0) {
+ memcpy(pframe, pbuf, ie_len + 2);
+ pframe += (ie_len + 2);
+ pattrib->pktlen += (ie_len + 2);
+ }
+
+ /* FILL HT ADD INFO IE */
+ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+ if (pbuf && ie_len > 0) {
+ memcpy(pframe, pbuf, ie_len + 2);
+ pframe += (ie_len + 2);
+ pattrib->pktlen += (ie_len + 2);
+ }
+ }
+
+ /* FILL WMM IE */
+ if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
+ uint ie_len = 0;
+ unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+
+ for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
+ pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
+ if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
+ memcpy(pframe, pbuf, ie_len + 2);
+ pframe += (ie_len + 2);
+ pattrib->pktlen += (ie_len + 2);
+ break;
+ }
+
+ if (!pbuf || ie_len == 0)
+ break;
+ }
+ }
+
+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
+
+ /* add WPS IE ie for wps 2.0 */
+ if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
+ memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
+
+ pframe += pmlmepriv->wps_assoc_resp_ie_len;
+ pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
+ }
+
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device)) {
+ u32 len;
+
+ len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
+
+ pframe += len;
+ pattrib->pktlen += len;
+ }
+#endif /* CONFIG_88EU_P2P */
+ pattrib->last_txcmdsz = pattrib->pktlen;
+ dump_mgntframe(padapter, pmgntframe);
+#endif
+}
+
+void issue_assocreq(struct adapter *padapter)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe, *p;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ __le16 le_tmp;
+ unsigned int i, j, ie_len, index = 0;
+ unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
+ struct ndis_802_11_var_ie *pIE;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ int bssrate_len = 0, sta_bssrate_len = 0;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 p2pie[255] = { 0x00 };
+ u16 p2pielen = 0;
+#endif /* CONFIG_88EU_P2P */
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+ memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ASSOCREQ);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ /* caps */
+
+ memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* listen interval */
+ /* todo: listen interval for power saving */
+ le_tmp = cpu_to_le16(3);
+ memcpy(pframe, (unsigned char *)&le_tmp, 2);
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &pattrib->pktlen);
+
+ /* supported rate & extended supported rate */
+
+ /* Check if the AP's supported rates are also supported by STA. */
+ get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
+
+ if (pmlmeext->cur_channel == 14)/* for JAPAN, channel 14 can only uses B Mode(CCK) */
+ sta_bssrate_len = 4;
+
+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+ if (pmlmeinfo->network.SupportedRates[i] == 0)
+ break;
+ DBG_88E("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
+ }
+
+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+ if (pmlmeinfo->network.SupportedRates[i] == 0)
+ break;
+
+ /* Check if the AP's supported rates are also supported by STA. */
+ for (j = 0; j < sta_bssrate_len; j++) {
+ /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
+ if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)
+ == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
+ break;
+ }
+
+ if (j == sta_bssrate_len) {
+ /* the rate is not supported by STA */
+ DBG_88E("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
+ } else {
+ /* the rate is supported by STA */
+ bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
+ }
+ }
+
+ bssrate_len = index;
+ DBG_88E("bssrate_len=%d\n", bssrate_len);
+
+ if (bssrate_len == 0) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit; /* don't connect to AP if no joint supported rate */
+ }
+
+ if (bssrate_len > 8) {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
+ } else {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
+ }
+
+ /* RSN */
+ p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
+ if (p)
+ pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, p + 2, &pattrib->pktlen);
+
+ /* HT caps */
+ if (padapter->mlmepriv.htpriv.ht_option) {
+ p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
+ if (p && !is_ap_in_tkip(padapter)) {
+ memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct HT_caps_element));
+
+ /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
+ if (pregpriv->cbw40_enable == 0)
+ pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
+ else
+ pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1));
+
+ /* todo: disable SM power save mode */
+ pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c);
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ switch (rf_type) {
+ case RF_1T1R:
+ if (pregpriv->rx_stbc)
+ pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
+ memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16);
+ break;
+ case RF_2T2R:
+ case RF_1T2R:
+ default:
+ if ((pregpriv->rx_stbc == 0x3) ||/* enable for 2.4/5 GHz */
+ ((pmlmeext->cur_wireless_mode & WIRELESS_11_24N) && (pregpriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */
+ (pregpriv->wifi_spec == 1)) {
+ DBG_88E("declare supporting RX STBC\n");
+ pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
+ }
+ memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R, 16);
+ break;
+ }
+ pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len, (u8 *)(&pmlmeinfo->HT_caps), &pattrib->pktlen);
+ }
+ }
+
+ /* vendor specific IE, such as WPA, WMM, WPS */
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
+ pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:
+ if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
+ (!memcmp(pIE->data, WMM_OUI, 4)) ||
+ (!memcmp(pIE->data, WPS_OUI, 4))) {
+ if (!padapter->registrypriv.wifi_spec) {
+ /* Commented by Kurt 20110629 */
+ /* In some older APs, WPS handshake */
+ /* would be fail if we append vender extensions informations to AP */
+ if (!memcmp(pIE->data, WPS_OUI, 4))
+ pIE->Length = 14;
+ }
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &pattrib->pktlen);
+ }
+ break;
+ default:
+ break;
+ }
+ i += (pIE->Length + 2);
+ }
+
+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
+
+#ifdef CONFIG_88EU_P2P
+
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
+ /* Should add the P2P IE in the association request frame. */
+ /* P2P OUI */
+
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20101109 */
+ /* According to the P2P Specification, the association request frame should contain 3 P2P attributes */
+ /* 1. P2P Capability */
+ /* 2. Extended Listen Timing */
+ /* 3. Device Info */
+ /* Commented by Albert 20110516 */
+ /* 4. P2P Interface */
+
+ /* P2P Capability */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Device Capability Bitmap, 1 byte */
+ p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
+
+ /* Group Capability Bitmap, 1 byte */
+ if (pwdinfo->persistent_supported)
+ p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
+ else
+ p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
+
+ /* Extended Listen Timing */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Availability Period */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
+ p2pielen += 2;
+
+ /* Availability Interval */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
+ p2pielen += 2;
+
+ /* Device Info */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
+
+ /* Length: */
+ /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
+ /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address */
+ memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* Config Method */
+ /* This field should be big endian. Noted by P2P specification. */
+ if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
+ (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
+ else
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC);
+
+ p2pielen += 2;
+
+ /* Primary Device Type */
+ /* Category ID */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
+ p2pielen += 2;
+
+ /* OUI */
+ *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
+ p2pielen += 4;
+
+ /* Sub Category ID */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
+ p2pielen += 2;
+
+ /* Number of Secondary Device Types */
+ p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
+
+ /* Device Name */
+ /* Type: */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
+ p2pielen += 2;
+
+ /* Length: */
+ *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
+ p2pielen += pwdinfo->device_name_len;
+
+ /* P2P Interface */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
+
+ /* Length: */
+ *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Device Address */
+ p2pielen += ETH_ALEN;
+
+ p2pie[p2pielen++] = 1; /* P2P Interface Address Count */
+
+ memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Interface Address List */
+ p2pielen += ETH_ALEN;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
+ }
+
+#endif /* CONFIG_88EU_P2P */
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+ dump_mgntframe(padapter, pmgntframe);
+
+ ret = _SUCCESS;
+
+exit:
+ if (ret == _SUCCESS)
+ rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
+ else
+ kfree(pmlmepriv->assoc_req);
+}
+
+/* when wait_ack is ture, this function shoule be called at process context */
+static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv;
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
+
+ if (!padapter)
+ goto exit;
+
+ pxmitpriv = &padapter->xmitpriv;
+ pmlmeext = &padapter->mlmeextpriv;
+ pmlmeinfo = &pmlmeext->mlmext_info;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->retry_ctrl = false;
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
+ SetFrDs(fctrl);
+ else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+ SetToDs(fctrl);
+
+ if (power_mode)
+ SetPwrMgt(fctrl);
+
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_DATA_NULL);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+/* when wait_ms > 0 , this function shoule be called at process context */
+/* da == NULL for station mode */
+int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
+{
+ int ret;
+ int i = 0;
+ u32 start = jiffies;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ /* da == NULL, assum it's null data for sta to ap*/
+ if (!da)
+ da = get_my_bssid(&pmlmeinfo->network);
+
+ do {
+ ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
+
+ i++;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ msleep(wait_ms);
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ }
+exit:
+ return ret;
+}
+
+/* when wait_ack is ture, this function shoule be called at process context */
+static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned short *qc;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ DBG_88E("%s\n", __func__);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ pattrib->hdrlen += 2;
+ pattrib->qos_en = true;
+ pattrib->eosp = 1;
+ pattrib->ack_policy = 0;
+ pattrib->mdata = 0;
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
+ SetFrDs(fctrl);
+ else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+ SetToDs(fctrl);
+
+ if (pattrib->mdata)
+ SetMData(fctrl);
+
+ qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
+
+ SetPriority(qc, tid);
+
+ SetEOSP(qc, pattrib->eosp);
+
+ SetAckpolicy(qc, pattrib->ack_policy);
+
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+/* when wait_ms > 0 , this function shoule be called at process context */
+/* da == NULL for station mode */
+int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
+{
+ int ret;
+ int i = 0;
+ u32 start = jiffies;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ /* da == NULL, assum it's null data for sta to ap*/
+ if (!da)
+ da = get_my_bssid(&pmlmeinfo->network);
+
+ do {
+ ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
+
+ i++;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ msleep(wait_ms);
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ }
+exit:
+ return ret;
+}
+
+static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ int ret = _FAIL;
+ __le16 le_tmp;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+#ifdef CONFIG_88EU_P2P
+ if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
+ _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
+ _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->retry_ctrl = false;
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_DEAUTH);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ le_tmp = cpu_to_le16(reason);
+ pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
+{
+ DBG_88E("%s to %pM\n", __func__, da);
+ return _issue_deauth(padapter, da, reason, false);
+}
+
+int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
+ int wait_ms)
+{
+ int ret;
+ int i = 0;
+ u32 start = jiffies;
+
+ do {
+ ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
+
+ i++;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ msleep(wait_ms);
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
+ }
+exit:
+ return ret;
+}
+
+void issue_action_spct_ch_switch(struct adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ DBG_88E(FUNC_NDEV_FMT" ra =%pM, ch:%u, offset:%u\n",
+ FUNC_NDEV_ARG(padapter->pnetdev), ra, new_ch, ch_offset);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); /* TA */
+ memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ /* category, action */
+ {
+ u8 category, action;
+ category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
+ action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ }
+
+ pframe = rtw_set_ie_ch_switch(pframe, &pattrib->pktlen, 0, new_ch, 0);
+ pframe = rtw_set_ie_secondary_ch_offset(pframe, &pattrib->pktlen,
+ hal_ch_offset_to_secondary_ch_offset(ch_offset));
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
+{
+ u8 category = RTW_WLAN_CATEGORY_BACK;
+ u16 start_seq;
+ u16 BA_para_set;
+ u16 reason_code;
+ u16 BA_timeout_value;
+ __le16 le_tmp;
+ u16 BA_starting_seqctrl = 0;
+ enum ht_cap_ampdu_factor max_rx_ampdu_factor;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ u8 *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+
+ DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &pattrib->pktlen);
+
+ if (category == 3) {
+ switch (action) {
+ case 0: /* ADDBA req */
+ do {
+ pmlmeinfo->dialogToken++;
+ } while (pmlmeinfo->dialogToken == 0);
+ pframe = rtw_set_fixed_ie(pframe, 1, &pmlmeinfo->dialogToken, &pattrib->pktlen);
+
+ BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
+ le_tmp = cpu_to_le16(BA_para_set);
+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
+
+ BA_timeout_value = 5000;/* 5ms */
+ le_tmp = cpu_to_le16(BA_timeout_value);
+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
+
+ psta = rtw_get_stainfo(pstapriv, raddr);
+ if (psta) {
+ start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] & 0xfff) + 1;
+
+ DBG_88E("BA_starting_seqctrl=%d for TID=%d\n", start_seq, status & 0x07);
+
+ psta->BA_starting_seqctrl[status & 0x07] = start_seq;
+
+ BA_starting_seqctrl = start_seq << 4;
+ }
+ le_tmp = cpu_to_le16(BA_starting_seqctrl);
+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
+ break;
+ case 1: /* ADDBA rsp */
+ pframe = rtw_set_fixed_ie(pframe, 1, &pmlmeinfo->ADDBA_req.dialog_token, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&status, &pattrib->pktlen);
+ BA_para_set = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
+ rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
+ switch (max_rx_ampdu_factor) {
+ case MAX_AMPDU_FACTOR_64K:
+ BA_para_set |= 0x1000; /* 64 buffer size */
+ break;
+ case MAX_AMPDU_FACTOR_32K:
+ BA_para_set |= 0x0800; /* 32 buffer size */
+ break;
+ case MAX_AMPDU_FACTOR_16K:
+ BA_para_set |= 0x0400; /* 16 buffer size */
+ break;
+ case MAX_AMPDU_FACTOR_8K:
+ BA_para_set |= 0x0200; /* 8 buffer size */
+ break;
+ default:
+ BA_para_set |= 0x1000; /* 64 buffer size */
+ break;
+ }
+
+ if (pregpriv->ampdu_amsdu == 0)/* disabled */
+ BA_para_set = BA_para_set & ~BIT(0);
+ else if (pregpriv->ampdu_amsdu == 1)/* enabled */
+ BA_para_set = BA_para_set | BIT(0);
+ le_tmp = cpu_to_le16(BA_para_set);
+
+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeinfo->ADDBA_req.BA_timeout_value, &pattrib->pktlen);
+ break;
+ case 2:/* DELBA */
+ BA_para_set = (status & 0x1F) << 3;
+ le_tmp = cpu_to_le16(BA_para_set);
+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
+
+ reason_code = 37;/* Requested from peer STA as it does not want to use the mechanism */
+ le_tmp = cpu_to_le16(reason_code);
+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static void issue_action_BSSCoexistPacket(struct adapter *padapter)
+{
+ struct list_head *plist, *phead;
+ unsigned char category, action;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct wlan_network *pnetwork = NULL;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ u8 InfoContent[16] = {0};
+ u8 ICS[8][15];
+ if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
+ return;
+
+ if (pmlmeinfo->bwmode_updated)
+ return;
+
+ DBG_88E("%s\n", __func__);
+
+ category = RTW_WLAN_CATEGORY_PUBLIC;
+ action = ACT_PUBLIC_BSSCOEXIST;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+
+ /* */
+ if (pmlmepriv->num_FortyMHzIntolerant > 0) {
+ u8 iedata = 0;
+
+ iedata |= BIT(2);/* 20 MHz BSS Width Request */
+
+ pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &pattrib->pktlen);
+ }
+
+ /* */
+ memset(ICS, 0, sizeof(ICS));
+ if (pmlmepriv->num_sta_no_ht > 0) {
+ int i;
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ int len;
+ u8 *p;
+ struct wlan_bssid_ex *pbss_network;
+
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ plist = plist->next;
+
+ pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
+
+ p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
+ if (!p || len == 0) { /* non-HT */
+ if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
+ continue;
+
+ ICS[0][pbss_network->Configuration.DSConfig] = 1;
+
+ if (ICS[0][0] == 0)
+ ICS[0][0] = 1;
+ }
+ }
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ for (i = 0; i < 8; i++) {
+ if (ICS[i][0] == 1) {
+ int j, k = 0;
+
+ InfoContent[k] = i;
+ /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
+ k++;
+
+ for (j = 1; j <= 14; j++) {
+ if (ICS[i][j] == 1) {
+ if (k < 16) {
+ InfoContent[k] = j; /* channel number */
+ /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
+ k++;
+ }
+ }
+ }
+
+ pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &pattrib->pktlen);
+ }
+ }
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *psta = NULL;
+ /* struct recv_reorder_ctrl *preorder_ctrl; */
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u16 tid;
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
+ return _SUCCESS;
+
+ psta = rtw_get_stainfo(pstapriv, addr);
+ if (!psta)
+ return _SUCCESS;
+
+ if (initiator == 0) { /* recipient */
+ for (tid = 0; tid < MAXTID; tid++) {
+ if (psta->recvreorder_ctrl[tid].enable) {
+ DBG_88E("rx agg disable tid(%d)\n", tid);
+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
+ psta->recvreorder_ctrl[tid].enable = false;
+ psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
+ }
+ }
+ } else if (initiator == 1) { /* originator */
+ for (tid = 0; tid < MAXTID; tid++) {
+ if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
+ DBG_88E("tx agg disable tid(%d)\n", tid);
+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
+ psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
+ psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
+ }
+ }
+ }
+
+ return _SUCCESS;
+}
+
+unsigned int send_beacon(struct adapter *padapter)
+{
+ u8 bxmitok = false;
+ int issue = 0;
+ int poll = 0;
+
+ u32 start = jiffies;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
+ do {
+ issue_beacon(padapter, 100);
+ issue++;
+ do {
+ yield();
+ rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
+ poll++;
+ } while ((poll % 10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
+ } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return _FAIL;
+ if (!bxmitok) {
+ DBG_88E("%s fail! %u ms\n", __func__, rtw_get_passing_time_ms(start));
+ return _FAIL;
+ } else {
+ u32 passing_time = rtw_get_passing_time_ms(start);
+
+ if (passing_time > 100 || issue > 3)
+ DBG_88E("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, rtw_get_passing_time_ms(start));
+ return _SUCCESS;
+ }
+}
+
+/****************************************************************************
+
+Following are some utitity fuctions for WiFi MLME
+
+*****************************************************************************/
+
+void site_survey(struct adapter *padapter)
+{
+ unsigned char survey_channel = 0, val8;
+ enum rt_scan_type ScanType = SCAN_PASSIVE;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u32 initialgain = 0;
+
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
+ if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
+ survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
+ } else {
+ survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
+ }
+ ScanType = SCAN_ACTIVE;
+ } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
+ /* Commented by Albert 2011/06/03 */
+ /* The driver is in the find phase, it should go through the social channel. */
+ int ch_set_idx;
+ survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
+ ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
+ if (ch_set_idx >= 0)
+ ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
+ else
+ ScanType = SCAN_ACTIVE;
+ } else
+#endif /* CONFIG_88EU_P2P */
+ {
+ struct rtw_ieee80211_channel *ch;
+ if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
+ ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
+ survey_channel = ch->hw_value;
+ ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
+ }
+ }
+
+ if (survey_channel != 0) {
+ /* PAUSE 4-AC Queue when site_survey */
+ /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
+ /* val8 |= 0x0f; */
+ /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
+ if (pmlmeext->sitesurvey_res.channel_idx == 0)
+ set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ else
+ SelectChannel(padapter, survey_channel);
+
+ if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
+ #ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
+ rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
+ issue_probereq_p2p(padapter, NULL);
+ issue_probereq_p2p(padapter, NULL);
+ issue_probereq_p2p(padapter, NULL);
+ } else
+ #endif /* CONFIG_88EU_P2P */
+ {
+ int i;
+ for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
+ if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
+ /* todo: to issue two probe req??? */
+ issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
+ /* msleep(SURVEY_TO>>1); */
+ issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
+ }
+ }
+
+ if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+ /* todo: to issue two probe req??? */
+ issue_probereq(padapter, NULL, NULL);
+ /* msleep(SURVEY_TO>>1); */
+ issue_probereq(padapter, NULL, NULL);
+ }
+ }
+ }
+
+ set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
+ } else {
+ /* channel number is 0 or this channel is not valid. */
+
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
+ if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
+ /* Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
+ /* This will let the following flow to run the scanning end. */
+ rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
+ }
+ }
+
+ if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
+ /* Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
+ set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
+ pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
+
+ initialgain = 0xff; /* restore RX GAIN */
+ rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
+ /* turn on dynamic functions */
+ Restore_DM_Func_Flag(padapter);
+ /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
+
+ _set_timer(&pwdinfo->find_phase_timer, (u32)((u32)(pwdinfo->listen_dwell) * 100));
+ } else
+#endif /* CONFIG_88EU_P2P */
+ {
+ /* 20100721:Interrupt scan operation here. */
+ /* For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
+ /* It compares the scan result and select beter one to do connection. */
+ if (rtw_hal_antdiv_before_linked(padapter)) {
+ pmlmeext->sitesurvey_res.bss_cnt = 0;
+ pmlmeext->sitesurvey_res.channel_idx = -1;
+ pmlmeext->chan_scan_time = SURVEY_TO / 2;
+ set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
+ return;
+ }
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
+ rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+ rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
+#endif /* CONFIG_88EU_P2P */
+
+ pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
+
+ /* switch back to the original channel */
+
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
+ set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ else
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+#endif /* CONFIG_88EU_P2P */
+
+ /* flush 4-AC Queue after site_survey */
+ /* val8 = 0; */
+ /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
+
+ /* config MSR */
+ Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+
+ initialgain = 0xff; /* restore RX GAIN */
+ rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
+ /* turn on dynamic functions */
+ Restore_DM_Func_Flag(padapter);
+ /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
+
+ if (is_client_associated_to_ap(padapter))
+ issue_nulldata(padapter, NULL, 0, 3, 500);
+
+ val8 = 0; /* survey done */
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+
+ report_surveydone_event(padapter);
+
+ pmlmeext->chan_scan_time = SURVEY_TO;
+ pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
+
+ issue_action_BSSCoexistPacket(padapter);
+ issue_action_BSSCoexistPacket(padapter);
+ issue_action_BSSCoexistPacket(padapter);
+ }
+ }
+}
+
+/* collect bss info from Beacon and Probe request/response frames. */
+u8 collect_bss_info(struct adapter *padapter, struct recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
+{
+ int i;
+ u32 len;
+ u8 *p;
+ u16 val16, subtype;
+ u8 *pframe = precv_frame->rx_data;
+ u32 packet_len = precv_frame->len;
+ u8 ie_offset;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ __le32 le32_tmp;
+
+ len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ if (len > MAX_IE_SZ)
+ return _FAIL;
+
+ memset(bssid, 0, sizeof(struct wlan_bssid_ex));
+
+ subtype = GetFrameSubType(pframe);
+
+ if (subtype == WIFI_BEACON) {
+ bssid->Reserved[0] = 1;
+ ie_offset = _BEACON_IE_OFFSET_;
+ } else {
+ /* FIXME : more type */
+ if (subtype == WIFI_PROBEREQ) {
+ ie_offset = _PROBEREQ_IE_OFFSET_;
+ bssid->Reserved[0] = 2;
+ } else if (subtype == WIFI_PROBERSP) {
+ ie_offset = _PROBERSP_IE_OFFSET_;
+ bssid->Reserved[0] = 3;
+ } else {
+ bssid->Reserved[0] = 0;
+ ie_offset = _FIXED_IE_LENGTH_;
+ }
+ }
+
+ bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
+
+ /* below is to copy the information element */
+ bssid->IELength = len;
+ memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
+
+ /* get the signal strength */
+ bssid->Rssi = precv_frame->attrib.phy_info.recvpower; /* in dBM.raw data */
+ bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
+ bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
+ rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA, &bssid->PhyInfo.Optimum_antenna);
+
+ /* checking SSID */
+ p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
+ if (!p) {
+ DBG_88E("marc: cannot find SSID for survey event\n");
+ return _FAIL;
+ }
+
+ if (*(p + 1)) {
+ if (len > NDIS_802_11_LENGTH_SSID) {
+ DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
+ return _FAIL;
+ }
+ memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
+ bssid->Ssid.SsidLength = *(p + 1);
+ } else {
+ bssid->Ssid.SsidLength = 0;
+ }
+
+ memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+
+ /* checking rate info... */
+ i = 0;
+ p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
+ if (p) {
+ if (len > NDIS_802_11_LENGTH_RATES_EX) {
+ DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
+ return _FAIL;
+ }
+ memcpy(bssid->SupportedRates, (p + 2), len);
+ i = len;
+ }
+
+ p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
+ if (p) {
+ if (len > (NDIS_802_11_LENGTH_RATES_EX - i)) {
+ DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
+ return _FAIL;
+ }
+ memcpy(bssid->SupportedRates + i, (p + 2), len);
+ }
+
+ /* todo: */
+ bssid->NetworkTypeInUse = Ndis802_11OFDM24;
+
+ if (bssid->IELength < 12)
+ return _FAIL;
+
+ /* Checking for DSConfig */
+ p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
+
+ bssid->Configuration.DSConfig = 0;
+ bssid->Configuration.Length = 0;
+
+ if (p) {
+ bssid->Configuration.DSConfig = *(p + 2);
+ } else {/* In 5G, some ap do not have DSSET IE */
+ /* checking HT info for channel */
+ p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
+ if (p) {
+ struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
+ bssid->Configuration.DSConfig = HT_info->primary_channel;
+ } else { /* use current channel */
+ bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
+ }
+ }
+
+ memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
+ bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
+
+ val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
+
+ if (val16 & BIT(0)) {
+ bssid->InfrastructureMode = Ndis802_11Infrastructure;
+ memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
+ } else {
+ bssid->InfrastructureMode = Ndis802_11IBSS;
+ memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
+ }
+
+ if (val16 & BIT(4))
+ bssid->Privacy = 1;
+ else
+ bssid->Privacy = 0;
+
+ bssid->Configuration.ATIMWindow = 0;
+
+ /* 20/40 BSS Coexistence check */
+ if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
+ if (p && len > 0) {
+ struct HT_caps_element *pHT_caps;
+ pHT_caps = (struct HT_caps_element *)(p + 2);
+
+ if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
+ pmlmepriv->num_FortyMHzIntolerant++;
+ } else {
+ pmlmepriv->num_sta_no_ht++;
+ }
+ }
+
+ /* mark bss info receiving from nearby channel as SignalQuality 101 */
+ if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
+ bssid->PhyInfo.SignalQuality = 101;
+ return _SUCCESS;
+}
+
+void start_create_ibss(struct adapter *padapter)
+{
+ unsigned short caps;
+ u8 val8;
+ u8 join_type;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
+ pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
+
+ /* update wireless mode */
+ update_wireless_mode(padapter);
+
+ /* udpate capability */
+ caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
+ update_capinfo(padapter, caps);
+ if (caps & cap_IBSS) {/* adhoc master */
+ val8 = 0xcf;
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ /* switch channel */
+ /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+
+ beacon_timing_control(padapter);
+
+ /* set msr to WIFI_FW_ADHOC_STATE */
+ pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
+ Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+
+ /* issue beacon */
+ if (send_beacon(padapter) == _FAIL) {
+ report_join_res(padapter, -1);
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ } else {
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
+ join_type = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+
+ report_join_res(padapter, 1);
+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+ rtw_indicate_connect(padapter);
+ }
+ } else {
+ DBG_88E("start_create_ibss, invalid cap:%x\n", caps);
+ return;
+ }
+ /* update bc/mc sta_info */
+ update_bmc_sta(padapter);
+}
+
+void start_clnt_join(struct adapter *padapter)
+{
+ unsigned short caps;
+ u8 val8;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ int beacon_timeout;
+
+ pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
+ pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
+
+ /* update wireless mode */
+ update_wireless_mode(padapter);
+
+ /* udpate capability */
+ caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
+ update_capinfo(padapter, caps);
+ if (caps & cap_ESS) {
+ Set_MSR(padapter, WIFI_FW_STATION_STATE);
+
+ val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ /* switch channel */
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ /* here wait for receiving the beacon to start auth */
+ /* and enable a timer */
+ beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
+ set_link_timer(pmlmeext, beacon_timeout);
+ _set_timer(&padapter->mlmepriv.assoc_timer,
+ (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout);
+
+ pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
+ } else if (caps & cap_IBSS) { /* adhoc client */
+ Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
+
+ val8 = 0xcf;
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ /* switch channel */
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ beacon_timing_control(padapter);
+
+ pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
+
+ report_join_res(padapter, 1);
+ } else {
+ return;
+ }
+}
+
+void start_clnt_auth(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ _cancel_timer_ex(&pmlmeext->link_timer);
+
+ pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
+ pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
+
+ pmlmeinfo->auth_seq = 1;
+ pmlmeinfo->reauth_count = 0;
+ pmlmeinfo->reassoc_count = 0;
+ pmlmeinfo->link_count = 0;
+ pmlmeext->retry = 0;
+
+ /* Because of AP's not receiving deauth before */
+ /* AP may: 1)not response auth or 2)deauth us after link is complete */
+ /* issue deauth before issuing auth to deal with the situation */
+ /* Commented by Albert 2012/07/21 */
+ /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
+ issue_deauth(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
+
+ DBG_88E_LEVEL(_drv_info_, "start auth\n");
+ issue_auth(padapter, NULL, 0);
+
+ set_link_timer(pmlmeext, REAUTH_TO);
+}
+
+void start_clnt_assoc(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ _cancel_timer_ex(&pmlmeext->link_timer);
+
+ pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
+ pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
+
+ issue_assocreq(padapter);
+
+ set_link_timer(pmlmeext, REASSOC_TO);
+}
+
+unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ /* check A3 */
+ if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+ return _SUCCESS;
+
+ DBG_88E("%s\n", __func__);
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ report_del_sta_event(padapter, MacAddr, reason);
+ } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ report_join_res(padapter, -2);
+ }
+ }
+ return _SUCCESS;
+}
+
+static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
+{
+ struct registry_priv *pregistrypriv;
+ struct mlme_ext_priv *pmlmeext;
+ struct rt_channel_info *chplan_new;
+ u8 channel;
+ u8 i;
+
+ pregistrypriv = &padapter->registrypriv;
+ pmlmeext = &padapter->mlmeextpriv;
+
+ /* Adjust channel plan by AP Country IE */
+ if (pregistrypriv->enable80211d &&
+ (!pmlmeext->update_channel_plan_by_ap_done)) {
+ u8 *ie, *p;
+ u32 len;
+ struct rt_channel_plan chplan_ap;
+ struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
+ u8 country[4];
+ u8 fcn; /* first channel number */
+ u8 noc; /* number of channel */
+ u8 j, k;
+
+ ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ if (!ie)
+ return;
+ if (len < 6)
+ return;
+ ie += 2;
+ p = ie;
+ ie += len;
+
+ memset(country, 0, 4);
+ memcpy(country, p, 3);
+ p += 3;
+
+ i = 0;
+ while ((ie - p) >= 3) {
+ fcn = *(p++);
+ noc = *(p++);
+ p++;
+
+ for (j = 0; j < noc; j++) {
+ channel = fcn + j;
+ chplan_ap.Channel[i++] = channel;
+ }
+ }
+ chplan_ap.Len = i;
+
+ memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
+
+ memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
+ chplan_new = pmlmeext->channel_set;
+
+ i = 0;
+ j = 0;
+ k = 0;
+ if (pregistrypriv->wireless_mode & WIRELESS_11G) {
+ do {
+ if ((i == MAX_CHANNEL_NUM) ||
+ (chplan_sta[i].ChannelNum == 0))
+ break;
+
+ if (j == chplan_ap.Len)
+ break;
+
+ if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+ chplan_new[k].ScanType = SCAN_ACTIVE;
+ i++;
+ j++;
+ k++;
+ } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+ chplan_new[k].ScanType = SCAN_PASSIVE;
+ i++;
+ k++;
+ } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+ chplan_new[k].ScanType = SCAN_ACTIVE;
+ j++;
+ k++;
+ }
+ } while (1);
+
+ /* change AP not support channel to Passive scan */
+ while ((i < MAX_CHANNEL_NUM) &&
+ (chplan_sta[i].ChannelNum != 0) &&
+ (chplan_sta[i].ChannelNum <= 14)) {
+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+ chplan_new[k].ScanType = SCAN_PASSIVE;
+ i++;
+ k++;
+ }
+
+ /* add channel AP supported */
+ while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+ chplan_new[k].ScanType = SCAN_ACTIVE;
+ j++;
+ k++;
+ }
+ } else {
+ /* keep original STA 2.4G channel plan */
+ while ((i < MAX_CHANNEL_NUM) &&
+ (chplan_sta[i].ChannelNum != 0) &&
+ (chplan_sta[i].ChannelNum <= 14)) {
+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+ chplan_new[k].ScanType = chplan_sta[i].ScanType;
+ i++;
+ k++;
+ }
+
+ /* skip AP 2.4G channel plan */
+ while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
+ j++;
+ }
+
+ /* keep original STA 5G channel plan */
+ while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+ chplan_new[k].ScanType = chplan_sta[i].ScanType;
+ i++;
+ k++;
+ }
+
+ pmlmeext->update_channel_plan_by_ap_done = 1;
+ }
+
+ /* If channel is used by AP, set channel scan type to active */
+ channel = bssid->Configuration.DSConfig;
+ chplan_new = pmlmeext->channel_set;
+ i = 0;
+ while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
+ if (chplan_new[i].ChannelNum == channel) {
+ if (chplan_new[i].ScanType == SCAN_PASSIVE)
+ chplan_new[i].ScanType = SCAN_ACTIVE;
+ break;
+ }
+ i++;
+ }
+}
+
+/****************************************************************************
+
+Following are the functions to report events
+
+*****************************************************************************/
+
+void report_survey_event(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct survey_event *psurvey_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext;
+ struct cmd_priv *pcmdpriv;
+ /* u8 *pframe = precv_frame->rx_data; */
+ /* uint len = precv_frame->len; */
+
+ if (!padapter)
+ return;
+
+ pmlmeext = &padapter->mlmeextpriv;
+ pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
+ pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct survey_event);
+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+
+ if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
+ kfree(pcmd_obj);
+ kfree(pevtcmd);
+ return;
+ }
+
+ process_80211d(padapter, &psurvey_evt->bss);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+ pmlmeext->sitesurvey_res.bss_cnt++;
+}
+
+void report_surveydone_event(struct adapter *padapter)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct surveydone_event *psurveydone_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
+ pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct surveydone_event);
+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+ psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
+
+ DBG_88E("survey done event(%x)\n", psurveydone_evt->bss_cnt);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+}
+
+void report_join_res(struct adapter *padapter, int res)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct joinbss_event *pjoinbss_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
+ pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct joinbss_event);
+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+ memcpy((unsigned char *)(&pjoinbss_evt->network.network), &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
+ pjoinbss_evt->network.join_res = res;
+ pjoinbss_evt->network.aid = res;
+
+ DBG_88E("report_join_res(%d)\n", res);
+
+ rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+}
+
+void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct sta_info *psta;
+ int mac_id;
+ struct stadel_event *pdel_sta_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
+ pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct stadel_event);
+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+ memcpy((unsigned char *)(&pdel_sta_evt->macaddr), MacAddr, ETH_ALEN);
+ memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
+
+ psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
+ if (psta)
+ mac_id = (int)psta->mac_id;
+ else
+ mac_id = (-1);
+
+ pdel_sta_evt->mac_id = mac_id;
+
+ DBG_88E("report_del_sta_event: delete STA, mac_id =%d\n", mac_id);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+}
+
+void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct stassoc_event *padd_sta_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
+ pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct stassoc_event);
+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+ memcpy((unsigned char *)(&padd_sta_evt->macaddr), MacAddr, ETH_ALEN);
+ padd_sta_evt->cam_id = cam_idx;
+
+ DBG_88E("report_add_sta_event: add STA\n");
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+}
+
+/****************************************************************************
+
+Following are the event callback functions
+
+*****************************************************************************/
+
+/* for sta/adhoc mode */
+void update_sta_info(struct adapter *padapter, struct sta_info *psta)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ /* ERP */
+ VCS_update(padapter, psta);
+
+ /* HT */
+ if (pmlmepriv->htpriv.ht_option) {
+ psta->htpriv.ht_option = true;
+
+ psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
+
+ if (support_short_GI(padapter, &pmlmeinfo->HT_caps))
+ psta->htpriv.sgi = true;
+
+ psta->qos_option = true;
+ } else {
+ psta->htpriv.ht_option = false;
+
+ psta->htpriv.ampdu_enable = false;
+
+ psta->htpriv.sgi = false;
+ psta->qos_option = false;
+ }
+ psta->htpriv.bwmode = pmlmeext->cur_bwmode;
+ psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
+
+ psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
+ psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
+
+ /* QoS */
+ if (pmlmepriv->qospriv.qos_option)
+ psta->qos_option = true;
+
+ psta->state = _FW_LINKED;
+}
+
+void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
+{
+ struct sta_info *psta, *psta_bmc;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 join_type;
+ u16 media_status;
+
+ if (join_res < 0) {
+ join_type = 1;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
+
+ /* restore to initial setting. */
+ update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
+
+ goto exit_mlmeext_joinbss_event_callback;
+ }
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+ /* for bc/mc */
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+ if (psta_bmc) {
+ pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
+ update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
+ Update_RA_Entry(padapter, psta_bmc->mac_id);
+ }
+ }
+
+ /* turn on dynamic functions */
+ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
+
+ /* update IOT-releated issue */
+ update_IOT_info(padapter);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
+
+ /* BCN interval */
+ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
+
+ /* udpate capability */
+ update_capinfo(padapter, pmlmeinfo->capability);
+
+ /* WMM, Update EDCA param */
+ WMMOnAssocRsp(padapter);
+
+ /* HT */
+ HTOnAssocRsp(padapter);
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
+ if (psta) { /* only for infra. mode */
+ pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
+
+ psta->wireless_mode = pmlmeext->cur_wireless_mode;
+
+ /* set per sta rate after updating HT cap. */
+ set_sta_rate(padapter, psta);
+ rtw_hal_set_hwreg(padapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&psta->mac_id);
+ media_status = (psta->mac_id << 8) | 1; /* MACID|OPMODE: 1 means connect */
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
+ }
+
+ join_type = 2;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
+ /* correcting TSF */
+ correct_TSF(padapter, pmlmeext);
+ }
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
+
+exit_mlmeext_joinbss_event_callback:
+
+ DBG_88E("=>%s\n", __func__);
+}
+
+void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 join_type;
+
+ DBG_88E("%s\n", __func__);
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
+ /* nothing to do */
+ } else { /* adhoc client */
+ /* correcting TSF */
+ correct_TSF(padapter, pmlmeext);
+
+ /* start beacon */
+ if (send_beacon(padapter) == _FAIL) {
+ pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
+ pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
+ return;
+ }
+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+ }
+
+ join_type = 2;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+ }
+
+ pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
+
+ /* rate radaptive */
+ Update_RA_Entry(padapter, psta->mac_id);
+
+ /* update adhoc sta_info */
+ update_sta_info(padapter, psta);
+}
+
+void mlmeext_sta_del_event_callback(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
+
+ /* restore to initial setting. */
+ update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
+
+ /* switch to the 20M Hz mode after disconnect */
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+ /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ flush_all_cam_entry(padapter);
+
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+
+ /* set MSR to no link state -> infra. mode */
+ Set_MSR(padapter, _HW_STATE_STATION_);
+
+ _cancel_timer_ex(&pmlmeext->link_timer);
+ }
+}
+
+/****************************************************************************
+
+Following are the functions for the timer handlers
+
+*****************************************************************************/
+void _linked_rx_signal_strehgth_display(struct adapter *padapter);
+void _linked_rx_signal_strehgth_display(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 mac_id;
+ int UndecoratedSmoothedPWDB;
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+ mac_id = 0;
+ else if ((pmlmeinfo->state & 0x03) == _HW_STATE_AP_)
+ mac_id = 2;
+
+ rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &mac_id);
+
+ rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
+ DBG_88E("UndecoratedSmoothedPWDB:%d\n", UndecoratedSmoothedPWDB);
+}
+
+static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
+{
+ u8 ret = false;
+
+ if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
+ sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
+ sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
+ ret = false;
+ else
+ ret = true;
+
+ sta_update_last_rx_pkts(psta);
+
+ return ret;
+}
+
+void linked_status_chk(struct adapter *padapter)
+{
+ u32 i;
+ struct sta_info *psta;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (padapter->bRxRSSIDisplay)
+ _linked_rx_signal_strehgth_display(padapter);
+
+ rtw_hal_sreset_linked_status_check(padapter);
+
+ if (is_client_associated_to_ap(padapter)) {
+ /* linked infrastructure client mode */
+
+ int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
+ int rx_chk_limit;
+
+ rx_chk_limit = 4;
+ psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
+ if (psta) {
+ bool is_p2p_enable = false;
+ #ifdef CONFIG_88EU_P2P
+ is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
+ #endif
+
+ if (!chk_ap_is_alive(padapter, psta))
+ rx_chk = _FAIL;
+
+ if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
+ tx_chk = _FAIL;
+
+ if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
+ u8 backup_oper_channel = 0;
+
+ /* switch to correct channel of current network before issue keep-alive frames */
+ if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
+ backup_oper_channel = rtw_get_oper_ch(padapter);
+ SelectChannel(padapter, pmlmeext->cur_channel);
+ }
+
+ if (rx_chk != _SUCCESS)
+ issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
+
+ if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
+ tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
+ /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
+ if (tx_chk == _SUCCESS && !is_p2p_enable)
+ rx_chk = _SUCCESS;
+ }
+
+ /* back to the original operation channel */
+ if (backup_oper_channel > 0)
+ SelectChannel(padapter, backup_oper_channel);
+ } else {
+ if (rx_chk != _SUCCESS) {
+ if (pmlmeext->retry == 0) {
+ issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
+ issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
+ issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
+ }
+ }
+
+ if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) {
+ tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
+ }
+ }
+
+ if (rx_chk == _FAIL) {
+ pmlmeext->retry++;
+ if (pmlmeext->retry > rx_chk_limit) {
+ DBG_88E_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
+ FUNC_ADPT_ARG(padapter));
+ receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
+ WLAN_REASON_EXPIRATION_CHK);
+ return;
+ }
+ } else {
+ pmlmeext->retry = 0;
+ }
+
+ if (tx_chk == _FAIL) {
+ pmlmeinfo->link_count &= 0xf;
+ } else {
+ pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
+ pmlmeinfo->link_count = 0;
+ }
+ } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
+ } else if (is_client_associated_to_ibss(padapter)) {
+ /* linked IBSS mode */
+ /* for each assoc list entry to check the rx pkt counter */
+ for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
+ if (pmlmeinfo->FW_sta_info[i].status == 1) {
+ psta = pmlmeinfo->FW_sta_info[i].psta;
+
+ if (NULL == psta)
+ continue;
+ if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
+ if (pmlmeinfo->FW_sta_info[i].retry < 3) {
+ pmlmeinfo->FW_sta_info[i].retry++;
+ } else {
+ pmlmeinfo->FW_sta_info[i].retry = 0;
+ pmlmeinfo->FW_sta_info[i].status = 0;
+ report_del_sta_event(padapter, psta->hwaddr
+ , 65535/* indicate disconnect caused by no rx */
+ );
+ }
+ } else {
+ pmlmeinfo->FW_sta_info[i].retry = 0;
+ pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
+ }
+ }
+ }
+ }
+}
+
+void survey_timer_hdl(struct adapter *padapter)
+{
+ struct cmd_obj *ph2c;
+ struct sitesurvey_parm *psurveyPara;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif
+
+ /* issue rtw_sitesurvey_cmd */
+ if (pmlmeext->sitesurvey_res.state > SCAN_START) {
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
+ pmlmeext->sitesurvey_res.channel_idx++;
+
+ if (pmlmeext->scan_abort) {
+ #ifdef CONFIG_88EU_P2P
+ if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) {
+ rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
+ pmlmeext->sitesurvey_res.channel_idx = 3;
+ DBG_88E("%s idx:%d, cnt:%u\n", __func__
+ , pmlmeext->sitesurvey_res.channel_idx
+ , pwdinfo->find_phase_state_exchange_cnt
+ );
+ } else
+ #endif
+ {
+ pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
+ DBG_88E("%s idx:%d\n", __func__
+ , pmlmeext->sitesurvey_res.channel_idx
+ );
+ }
+
+ pmlmeext->scan_abort = false;/* reset */
+ }
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c)
+ goto exit_survey_timer_hdl;
+
+ psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
+ if (!psurveyPara) {
+ kfree(ph2c);
+ goto exit_survey_timer_hdl;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
+ rtw_enqueue_cmd(pcmdpriv, ph2c);
+ }
+
+exit_survey_timer_hdl:
+ return;
+}
+
+void link_timer_hdl(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
+ DBG_88E("link_timer_hdl:no beacon while connecting\n");
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ report_join_res(padapter, -3);
+ } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
+ /* re-auth timer */
+ if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
+ pmlmeinfo->state = 0;
+ report_join_res(padapter, -1);
+ return;
+ }
+
+ DBG_88E("link_timer_hdl: auth timeout and try again\n");
+ pmlmeinfo->auth_seq = 1;
+ issue_auth(padapter, NULL, 0);
+ set_link_timer(pmlmeext, REAUTH_TO);
+ } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
+ /* re-assoc timer */
+ if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ report_join_res(padapter, -2);
+ return;
+ }
+
+ DBG_88E("link_timer_hdl: assoc timeout and try again\n");
+ issue_assocreq(padapter);
+ set_link_timer(pmlmeext, REASSOC_TO);
+ }
+}
+
+void addba_timer_hdl(struct sta_info *psta)
+{
+ struct ht_priv *phtpriv;
+
+ if (!psta)
+ return;
+
+ phtpriv = &psta->htpriv;
+
+ if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
+ if (phtpriv->candidate_tid_bitmap)
+ phtpriv->candidate_tid_bitmap = 0x0;
+ }
+}
+
+u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ return H2C_SUCCESS;
+}
+
+u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ u8 type;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
+
+ if (psetop->mode == Ndis802_11APMode) {
+ pmlmeinfo->state = WIFI_FW_AP_STATE;
+ type = _HW_STATE_AP_;
+ } else if (psetop->mode == Ndis802_11Infrastructure) {
+ pmlmeinfo->state &= ~(BIT(0) | BIT(1));/* clear state */
+ pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
+ type = _HW_STATE_STATION_;
+ } else if (psetop->mode == Ndis802_11IBSS) {
+ type = _HW_STATE_ADHOC_;
+ } else {
+ type = _HW_STATE_NOLINK_;
+ }
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
+ /* Set_NETYPE0_MSR(padapter, type); */
+
+ return H2C_SUCCESS;
+}
+
+u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
+ /* u32 initialgain; */
+
+ if (pparm->network.InfrastructureMode == Ndis802_11APMode) {
+#ifdef CONFIG_88EU_AP_MODE
+
+ if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
+ /* todo: */
+ return H2C_SUCCESS;
+ }
+#endif
+ }
+
+ /* below is for ad-hoc master */
+ if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
+ rtw_joinbss_reset(padapter);
+
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pmlmeinfo->ERP_enable = 0;
+ pmlmeinfo->WMM_enable = 0;
+ pmlmeinfo->HT_enable = 0;
+ pmlmeinfo->HT_caps_enable = 0;
+ pmlmeinfo->HT_info_enable = 0;
+ pmlmeinfo->agg_enable_bitmap = 0;
+ pmlmeinfo->candidate_tid_bitmap = 0;
+
+ /* disable dynamic functions, such as high power, DIG */
+ Save_DM_Func_Flag(padapter);
+ Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
+
+ /* config the initial gain under linking, need to write the BB registers */
+ /* initialgain = 0x1E; */
+ /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
+
+ /* cancel link timer */
+ _cancel_timer_ex(&pmlmeext->link_timer);
+
+ /* clear CAM */
+ flush_all_cam_entry(padapter);
+
+ memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
+ pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
+
+ if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
+ return H2C_PARAMETERS_ERROR;
+
+ memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
+
+ start_create_ibss(padapter);
+ }
+
+ return H2C_SUCCESS;
+}
+
+u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ u8 join_type;
+ struct ndis_802_11_var_ie *pIE;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
+ u32 i;
+
+ /* check already connecting to AP or not */
+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
+ if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
+ issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
+
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+
+ /* clear CAM */
+ flush_all_cam_entry(padapter);
+
+ _cancel_timer_ex(&pmlmeext->link_timer);
+
+ /* set MSR to nolink -> infra. mode */
+ Set_MSR(padapter, _HW_STATE_STATION_);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
+ }
+
+ rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, false);
+
+ rtw_joinbss_reset(padapter);
+
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pmlmeinfo->ERP_enable = 0;
+ pmlmeinfo->WMM_enable = 0;
+ pmlmeinfo->HT_enable = 0;
+ pmlmeinfo->HT_caps_enable = 0;
+ pmlmeinfo->HT_info_enable = 0;
+ pmlmeinfo->agg_enable_bitmap = 0;
+ pmlmeinfo->candidate_tid_bitmap = 0;
+ pmlmeinfo->bwmode_updated = false;
+
+ memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
+ pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
+
+ if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
+ return H2C_PARAMETERS_ERROR;
+
+ memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
+
+ /* Check AP vendor to move rtw_joinbss_cmd() */
+
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->IELength;) {
+ pIE = (struct ndis_802_11_var_ie *)(pnetwork->IEs + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
+ if (!memcmp(pIE->data, WMM_OUI, 4))
+ pmlmeinfo->WMM_enable = 1;
+ break;
+ case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */
+ pmlmeinfo->HT_caps_enable = 1;
+ break;
+ case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */
+ pmlmeinfo->HT_info_enable = 1;
+
+ /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
+ {
+ struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
+
+ if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
+ /* switch to the 40M Hz mode according to the AP */
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
+ switch (pht_info->infos[0] & 0x3) {
+ case 1:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+ break;
+ case 3:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+ break;
+ default:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ break;
+ }
+
+ DBG_88E("set ch/bw before connected\n");
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ i += (pIE->Length + 2);
+ }
+ /* disable dynamic functions, such as high power, DIG */
+
+ /* config the initial gain under linking, need to write the BB registers */
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
+ join_type = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+
+ /* cancel link timer */
+ _cancel_timer_ex(&pmlmeext->link_timer);
+
+ start_clnt_join(padapter);
+
+ return H2C_SUCCESS;
+}
+
+u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ u8 val8;
+
+ if (is_client_associated_to_ap(padapter))
+ issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
+
+ /* restore to initial setting. */
+ update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
+
+ if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
+ /* Stop BCN */
+ val8 = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
+ }
+
+ /* set MSR to no link state -> infra. mode */
+ Set_MSR(padapter, _HW_STATE_STATION_);
+
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+
+ /* switch to the 20M Hz mode after disconnect */
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ flush_all_cam_entry(padapter);
+
+ _cancel_timer_ex(&pmlmeext->link_timer);
+
+ rtw_free_uc_swdec_pending_queue(padapter);
+
+ return H2C_SUCCESS;
+}
+
+static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
+ u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
+{
+ int i, j;
+ int set_idx;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ /* clear out first */
+ memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num);
+
+ /* acquire channels from in */
+ j = 0;
+ for (i = 0; i < in_num; i++) {
+ set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
+ if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
+ set_idx >= 0) {
+ memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
+
+ if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
+ out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
+
+ j++;
+ }
+ if (j >= out_num)
+ break;
+ }
+
+ /* if out is empty, use channel_set as default */
+ if (j == 0) {
+ for (i = 0; i < pmlmeext->max_chan_nums; i++) {
+ out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
+
+ if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
+ out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
+
+ j++;
+ }
+ }
+
+ return j;
+}
+
+u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
+ u8 bdelayscan = false;
+ u8 val8;
+ u32 initialgain;
+ u32 i;
+
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
+ /* for first time sitesurvey_cmd */
+ rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, NULL);
+
+ pmlmeext->sitesurvey_res.state = SCAN_START;
+ pmlmeext->sitesurvey_res.bss_cnt = 0;
+ pmlmeext->sitesurvey_res.channel_idx = 0;
+
+ for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
+ if (pparm->ssid[i].SsidLength) {
+ memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
+ pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
+ } else {
+ pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
+ }
+ }
+
+ pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
+ , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
+ , pparm->ch, pparm->ch_num
+ );
+
+ pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
+
+ /* issue null data if associating to the AP */
+ if (is_client_associated_to_ap(padapter)) {
+ pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
+
+ issue_nulldata(padapter, NULL, 1, 3, 500);
+
+ bdelayscan = true;
+ }
+ if (bdelayscan) {
+ /* delay 50ms to protect nulldata(1). */
+ set_survey_timer(pmlmeext, 50);
+ return H2C_SUCCESS;
+ }
+ }
+
+ if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
+ /* disable dynamic functions, such as high power, DIG */
+ Save_DM_Func_Flag(padapter);
+ Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
+
+ /* config the initial gain under scanning, need to write the BB registers */
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ initialgain = 0x1E;
+ else
+ initialgain = 0x28;
+#else /* CONFIG_88EU_P2P */
+ initialgain = 0x1E;
+#endif /* CONFIG_88EU_P2P */
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
+
+ /* set MSR to no link state */
+ Set_MSR(padapter, _HW_STATE_NOLINK_);
+
+ val8 = 1; /* under site survey */
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+
+ pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
+ }
+
+ site_survey(padapter);
+
+ return H2C_SUCCESS;
+}
+
+u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pparm->mode < 4)
+ pmlmeinfo->auth_algo = pparm->mode;
+ return H2C_SUCCESS;
+}
+
+u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ unsigned short ctrl;
+ struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ /* main tx key for wep. */
+ if (pparm->set_tx)
+ pmlmeinfo->key_index = pparm->keyid;
+
+ /* write cam */
+ ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
+
+ DBG_88E_LEVEL(_drv_info_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
+ "keyid:%d\n", pparm->algorithm, pparm->keyid);
+ write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
+
+ return H2C_SUCCESS;
+}
+
+u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ u16 ctrl = 0;
+ u8 cam_id;/* cam_entry */
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
+
+ /* cam_entry: */
+ /* 0~3 for default key */
+
+ /* for concurrent mode (ap+sta): */
+ /* default key is disable, using sw encrypt/decrypt */
+ /* cam_entry = 4 for sta mode (macid = 0) */
+ /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
+
+ /* for concurrent mode (sta+sta): */
+ /* default key is disable, using sw encrypt/decrypt */
+ /* cam_entry = 4 mapping to macid = 0 */
+ /* cam_entry = 5 mapping to macid = 2 */
+
+ cam_id = 4;
+
+ DBG_88E_LEVEL(_drv_info_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
+ pparm->algorithm, cam_id);
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */ {
+ clear_cam_entry(padapter, pparm->id);
+ return H2C_SUCCESS_RSP;
+ }
+
+ psta = rtw_get_stainfo(pstapriv, pparm->addr);
+ if (psta) {
+ ctrl = (BIT(15) | ((pparm->algorithm) << 2));
+
+ DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm);
+
+ if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA - 4))) {
+ DBG_88E("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id);
+ return H2C_REJECTED;
+ }
+
+ cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
+
+ DBG_88E("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, cam_entry=%d\n", pparm->addr[0],
+ pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
+ pparm->addr[5], cam_id);
+
+ write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
+
+ return H2C_SUCCESS_RSP;
+ } else {
+ DBG_88E("r871x_set_stakey_hdl(): sta has been free\n");
+ return H2C_REJECTED;
+ }
+ }
+
+ /* below for sta mode */
+
+ if (pparm->algorithm == _NO_PRIVACY_) { /* clear cam entry */
+ clear_cam_entry(padapter, pparm->id);
+ return H2C_SUCCESS;
+ }
+ ctrl = BIT(15) | ((pparm->algorithm) << 2);
+ write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
+ pmlmeinfo->enc_algo = pparm->algorithm;
+ return H2C_SUCCESS;
+}
+
+u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
+
+ if (!psta)
+ return H2C_SUCCESS;
+
+ if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
+ ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
+ issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
+ _set_timer(&psta->addba_retry_timer, ADDBA_TO);
+ } else {
+ psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
+ }
+ return H2C_SUCCESS;
+}
+
+u8 set_tx_beacon_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *ph2c;
+ struct Tx_Beacon_param *ptxBeacon_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 res = _SUCCESS;
+ int len_diff = 0;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
+ if (!ptxBeacon_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
+
+ len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs + _BEACON_IE_OFFSET_,
+ ptxBeacon_parm->network.IELength - _BEACON_IE_OFFSET_,
+ pmlmeinfo->hidden_ssid_mode);
+ ptxBeacon_parm->network.IELength += len_diff;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+
+u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ u8 evt_code;
+ u16 evt_sz;
+ uint *peventbuf;
+ void (*event_callback)(struct adapter *dev, u8 *pbuf);
+ struct evt_priv *pevt_priv = &padapter->evtpriv;
+
+ peventbuf = (uint *)pbuf;
+ evt_sz = (u16)(*peventbuf & 0xffff);
+ evt_code = (u8)((*peventbuf >> 16) & 0xff);
+
+ /* checking if event code is valid */
+ if (evt_code >= MAX_C2HEVT)
+ goto _abort_event_;
+
+ /* checking if event size match the event parm size */
+ if ((wlanevents[evt_code].parmsize != 0) &&
+ (wlanevents[evt_code].parmsize != evt_sz))
+ goto _abort_event_;
+
+ atomic_inc(&pevt_priv->event_seq);
+
+ peventbuf += 2;
+
+ if (peventbuf) {
+ event_callback = wlanevents[evt_code].event_callback;
+ event_callback(padapter, (u8 *)peventbuf);
+
+ pevt_priv->evt_done_cnt++;
+ }
+
+_abort_event_:
+ return H2C_SUCCESS;
+}
+
+u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ if (!pbuf)
+ return H2C_PARAMETERS_ERROR;
+
+ return H2C_SUCCESS;
+}
+
+u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ if (send_beacon(padapter) == _FAIL) {
+ DBG_88E("issue_beacon, fail!\n");
+ return H2C_PARAMETERS_ERROR;
+ }
+#ifdef CONFIG_88EU_AP_MODE
+ else { /* tx bc/mc frames after update TIM */
+ struct sta_info *psta_bmc;
+ struct list_head *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ /* for BC/MC Frames */
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+ if (!psta_bmc)
+ return H2C_SUCCESS;
+
+ if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) {
+ msleep(10);/* 10ms, ATIM(HIQ) Windows */
+ spin_lock_bh(&psta_bmc->sleep_q.lock);
+
+ xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
+ list_del_init(&pxmitframe->list);
+
+ psta_bmc->sleepq_len--;
+ if (psta_bmc->sleepq_len > 0)
+ pxmitframe->attrib.mdata = 1;
+ else
+ pxmitframe->attrib.mdata = 0;
+
+ pxmitframe->attrib.triggered = 1;
+
+ pxmitframe->attrib.qsel = 0x11;/* HIQ */
+
+ spin_unlock_bh(&psta_bmc->sleep_q.lock);
+ if (rtw_hal_xmit(padapter, pxmitframe))
+ rtw_os_xmit_complete(padapter, pxmitframe);
+ spin_lock_bh(&psta_bmc->sleep_q.lock);
+ }
+ spin_unlock_bh(&psta_bmc->sleep_q.lock);
+ }
+ }
+#endif
+ return H2C_SUCCESS;
+}
+
+u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ struct set_ch_parm *set_ch_parm;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (!pbuf)
+ return H2C_PARAMETERS_ERROR;
+
+ set_ch_parm = (struct set_ch_parm *)pbuf;
+
+ DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
+ FUNC_NDEV_ARG(padapter->pnetdev),
+ set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
+
+ pmlmeext->cur_channel = set_ch_parm->ch;
+ pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
+ pmlmeext->cur_bwmode = set_ch_parm->bw;
+
+ set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
+
+ return H2C_SUCCESS;
+}
+
+u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct SetChannelPlan_param *setChannelPlan_param;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (!pbuf)
+ return H2C_PARAMETERS_ERROR;
+
+ setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
+
+ pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
+ init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
+
+ return H2C_SUCCESS;
+}
+
+u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ if (!pbuf)
+ return H2C_PARAMETERS_ERROR;
+ return H2C_SUCCESS;
+}
+
+u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ return H2C_REJECTED;
+}
+
+/* TDLS_WRCR : write RCR DATA BIT */
+/* TDLS_SD_PTI : issue peer traffic indication */
+/* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */
+/* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */
+/* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
+/* TDLS_OFF_CH : first time set channel to off channel */
+/* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */
+/* TDLS_P_OFF_CH : periodically go to off channel */
+/* TDLS_P_BASE_CH : periodically go back to base channel */
+/* TDLS_RS_RCR : restore RCR */
+/* TDLS_CKALV_PH1 : check alive timer phase1 */
+/* TDLS_CKALV_PH2 : check alive timer phase2 */
+/* TDLS_FREE_STA : free tdls sta */
+u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ return H2C_REJECTED;
+}
diff --git a/drivers/staging/r8188eu/core/rtw_mp.c b/drivers/staging/r8188eu/core/rtw_mp.c
new file mode 100644
index 000000000000..dabdd0406f30
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_mp.c
@@ -0,0 +1,935 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTW_MP_C_
+
+#include "../include/drv_types.h"
+#include "../include/odm_precomp.h"
+#include "../include/rtl8188e_hal.h"
+
+u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask)
+{
+ return rtw_hal_read_bbreg(padapter, addr, bitmask);
+}
+
+void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val)
+{
+ rtw_hal_write_bbreg(padapter, addr, bitmask, val);
+}
+
+u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask)
+{
+ return rtw_hal_read_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bitmask);
+}
+
+void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val)
+{
+ rtw_hal_write_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bitmask, val);
+}
+
+u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr)
+{
+ return _read_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bRFRegOffsetMask);
+}
+
+void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val)
+{
+ _write_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bRFRegOffsetMask, val);
+}
+
+static void _init_mp_priv_(struct mp_priv *pmp_priv)
+{
+ struct wlan_bssid_ex *pnetwork;
+
+ memset(pmp_priv, 0, sizeof(struct mp_priv));
+
+ pmp_priv->mode = MP_OFF;
+
+ pmp_priv->channel = 1;
+ pmp_priv->bandwidth = HT_CHANNEL_WIDTH_20;
+ pmp_priv->prime_channel_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pmp_priv->rateidx = MPT_RATE_1M;
+ pmp_priv->txpoweridx = 0x2A;
+
+ pmp_priv->antenna_tx = ANTENNA_A;
+ pmp_priv->antenna_rx = ANTENNA_AB;
+
+ pmp_priv->check_mp_pkt = 0;
+
+ pmp_priv->tx_pktcount = 0;
+
+ pmp_priv->rx_pktcount = 0;
+ pmp_priv->rx_crcerrpktcount = 0;
+
+ pmp_priv->network_macaddr[0] = 0x00;
+ pmp_priv->network_macaddr[1] = 0xE0;
+ pmp_priv->network_macaddr[2] = 0x4C;
+ pmp_priv->network_macaddr[3] = 0x87;
+ pmp_priv->network_macaddr[4] = 0x66;
+ pmp_priv->network_macaddr[5] = 0x55;
+
+ pnetwork = &pmp_priv->mp_network.network;
+ memcpy(pnetwork->MacAddress, pmp_priv->network_macaddr, ETH_ALEN);
+
+ pnetwork->Ssid.SsidLength = 8;
+ memcpy(pnetwork->Ssid.Ssid, "mp_871x", pnetwork->Ssid.SsidLength);
+}
+
+static void mp_init_xmit_attrib(struct mp_tx *pmptx, struct adapter *padapter)
+{
+ struct pkt_attrib *pattrib;
+ struct tx_desc *desc;
+
+ /* init xmitframe attribute */
+ pattrib = &pmptx->attrib;
+ memset(pattrib, 0, sizeof(struct pkt_attrib));
+ desc = &pmptx->desc;
+ memset(desc, 0, TXDESC_SIZE);
+
+ pattrib->ether_type = 0x8712;
+ memset(pattrib->dst, 0xFF, ETH_ALEN);
+ pattrib->ack_policy = 0;
+ pattrib->hdrlen = WLAN_HDR_A3_LEN;
+ pattrib->subtype = WIFI_DATA;
+ pattrib->priority = 0;
+ pattrib->qsel = pattrib->priority;
+ pattrib->nr_frags = 1;
+ pattrib->encrypt = 0;
+ pattrib->bswenc = false;
+ pattrib->qos_en = false;
+}
+
+s32 init_mp_priv(struct adapter *padapter)
+{
+ struct mp_priv *pmppriv = &padapter->mppriv;
+
+ _init_mp_priv_(pmppriv);
+ pmppriv->papdater = padapter;
+
+ pmppriv->tx.stop = 1;
+ mp_init_xmit_attrib(&pmppriv->tx, padapter);
+
+ switch (padapter->registrypriv.rf_config) {
+ case RF_1T1R:
+ pmppriv->antenna_tx = ANTENNA_A;
+ pmppriv->antenna_rx = ANTENNA_A;
+ break;
+ case RF_1T2R:
+ default:
+ pmppriv->antenna_tx = ANTENNA_A;
+ pmppriv->antenna_rx = ANTENNA_AB;
+ break;
+ case RF_2T2R:
+ case RF_2T2R_GREEN:
+ pmppriv->antenna_tx = ANTENNA_AB;
+ pmppriv->antenna_rx = ANTENNA_AB;
+ break;
+ case RF_2T4R:
+ pmppriv->antenna_tx = ANTENNA_AB;
+ pmppriv->antenna_rx = ANTENNA_ABCD;
+ break;
+ }
+
+ return _SUCCESS;
+}
+
+void free_mp_priv(struct mp_priv *pmp_priv)
+{
+ kfree(pmp_priv->pallocated_mp_xmitframe_buf);
+ pmp_priv->pallocated_mp_xmitframe_buf = NULL;
+ pmp_priv->pmp_xmtframe_buf = NULL;
+}
+
+#define PHY_IQCalibrate(a, b) PHY_IQCalibrate_8188E(a, b)
+#define PHY_LCCalibrate(a) PHY_LCCalibrate_8188E(a)
+#define PHY_SetRFPathSwitch(a, b) PHY_SetRFPathSwitch_8188E(a, b)
+
+s32 MPT_InitializeAdapter(struct adapter *pAdapter, u8 Channel)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+ s32 rtStatus = _SUCCESS;
+ struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
+ struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv;
+
+ /* HW Initialization for 8190 MPT. */
+ /* SW Initialization for 8190 MP. */
+ pMptCtx->bMptDrvUnload = false;
+ pMptCtx->bMassProdTest = false;
+ pMptCtx->bMptIndexEven = true; /* default gain index is -6.0db */
+ pMptCtx->h2cReqNum = 0x0;
+ /* Init mpt event. */
+ /* init for BT MP */
+
+ pMptCtx->bMptWorkItemInProgress = false;
+ pMptCtx->CurrMptAct = NULL;
+ /* */
+
+ /* Don't accept any packets */
+ rtw_write32(pAdapter, REG_RCR, 0);
+
+ PHY_IQCalibrate(pAdapter, false);
+ dm_CheckTXPowerTracking(&pHalData->odmpriv); /* trigger thermal meter */
+ PHY_LCCalibrate(pAdapter);
+
+ pMptCtx->backup0xc50 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_XAAGCCore1, bMaskByte0);
+ pMptCtx->backup0xc58 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_XBAGCCore1, bMaskByte0);
+ pMptCtx->backup0xc30 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_RxDetector1, bMaskByte0);
+ pMptCtx->backup0x52_RF_A = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
+ pMptCtx->backup0x52_RF_B = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
+
+ /* set ant to wifi side in mp mode */
+ rtw_write16(pAdapter, 0x870, 0x300);
+ rtw_write16(pAdapter, 0x860, 0x110);
+
+ if (pAdapter->registrypriv.mp_mode == 1)
+ pmlmepriv->fw_state = WIFI_MP_STATE;
+
+ return rtStatus;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: MPT_DeInitAdapter()
+ *
+ * Overview: Extra DeInitialization for Mass Production Test.
+ *
+ * Input: struct adapter * pAdapter
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 05/08/2007 MHC Create Version 0.
+ * 05/18/2007 MHC Add normal driver MPHalt code.
+ *
+ *---------------------------------------------------------------------------*/
+void MPT_DeInitAdapter(struct adapter *pAdapter)
+{
+ struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
+
+ pMptCtx->bMptDrvUnload = true;
+}
+
+static u8 mpt_ProStartTest(struct adapter *padapter)
+{
+ struct mpt_context *pMptCtx = &padapter->mppriv.MptCtx;
+
+ pMptCtx->bMassProdTest = true;
+ pMptCtx->bStartContTx = false;
+ pMptCtx->bCckContTx = false;
+ pMptCtx->bOfdmContTx = false;
+ pMptCtx->bSingleCarrier = false;
+ pMptCtx->bCarrierSuppression = false;
+ pMptCtx->bSingleTone = false;
+
+ return _SUCCESS;
+}
+
+/*
+ * General use
+ */
+s32 SetPowerTracking(struct adapter *padapter, u8 enable)
+{
+ Hal_SetPowerTracking(padapter, enable);
+ return 0;
+}
+
+void GetPowerTracking(struct adapter *padapter, u8 *enable)
+{
+ Hal_GetPowerTracking(padapter, enable);
+}
+
+static void disable_dm(struct adapter *padapter)
+{
+ u8 v8;
+
+ /* 3 1. disable firmware dynamic mechanism */
+ /* disable Power Training, Rate Adaptive */
+ v8 = rtw_read8(padapter, REG_BCN_CTRL);
+ v8 &= ~EN_BCN_FUNCTION;
+ rtw_write8(padapter, REG_BCN_CTRL, v8);
+
+ /* 3 2. disable driver dynamic mechanism */
+ /* disable Dynamic Initial Gain */
+ /* disable High Power */
+ /* disable Power Tracking */
+ Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
+
+ /* enable APK, LCK and IQK but disable power tracking */
+ Switch_DM_Func(padapter, DYNAMIC_RF_CALIBRATION, true);
+}
+
+/* This function initializes the DUT to the MP test mode */
+s32 mp_start_test(struct adapter *padapter)
+{
+ struct wlan_bssid_ex bssid;
+ struct sta_info *psta;
+ u32 length;
+ u8 val8;
+ s32 res = _SUCCESS;
+ struct mp_priv *pmppriv = &padapter->mppriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+
+ padapter->registrypriv.mp_mode = 1;
+ pmppriv->bSetTxPower = 0; /* for manually set tx power */
+
+ /* 3 disable dynamic mechanism */
+ disable_dm(padapter);
+
+ /* 3 0. update mp_priv */
+
+ if (padapter->registrypriv.rf_config == RF_819X_MAX_TYPE) {
+ switch (GET_RF_TYPE(padapter)) {
+ case RF_1T1R:
+ pmppriv->antenna_tx = ANTENNA_A;
+ pmppriv->antenna_rx = ANTENNA_A;
+ break;
+ case RF_1T2R:
+ default:
+ pmppriv->antenna_tx = ANTENNA_A;
+ pmppriv->antenna_rx = ANTENNA_AB;
+ break;
+ case RF_2T2R:
+ case RF_2T2R_GREEN:
+ pmppriv->antenna_tx = ANTENNA_AB;
+ pmppriv->antenna_rx = ANTENNA_AB;
+ break;
+ case RF_2T4R:
+ pmppriv->antenna_tx = ANTENNA_AB;
+ pmppriv->antenna_rx = ANTENNA_ABCD;
+ break;
+ }
+ }
+
+ mpt_ProStartTest(padapter);
+
+ /* 3 1. initialize a new struct wlan_bssid_ex */
+/* memset(&bssid, 0, sizeof(struct wlan_bssid_ex)); */
+ memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);
+ bssid.Ssid.SsidLength = strlen("mp_pseudo_adhoc");
+ memcpy(bssid.Ssid.Ssid, (u8 *)"mp_pseudo_adhoc", bssid.Ssid.SsidLength);
+ bssid.InfrastructureMode = Ndis802_11IBSS;
+ bssid.NetworkTypeInUse = Ndis802_11DS;
+ bssid.IELength = 0;
+
+ length = get_wlan_bssid_ex_sz(&bssid);
+ if (length % 4)
+ bssid.Length = ((length >> 2) + 1) << 2; /* round up to multiple of 4 bytes. */
+ else
+ bssid.Length = length;
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
+ goto end_of_mp_start_test;
+
+ /* init mp_start_test status */
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ rtw_disassoc_cmd(padapter, 500, true);
+ rtw_indicate_disconnect(padapter);
+ rtw_free_assoc_resources(padapter, 1);
+ }
+ pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
+ if (padapter->registrypriv.mp_mode == 1)
+ pmlmepriv->fw_state = WIFI_MP_STATE;
+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+
+ /* 3 2. create a new psta for mp driver */
+ /* clear psta in the cur_network, if any */
+ psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
+ if (psta)
+ rtw_free_stainfo(padapter, psta);
+
+ psta = rtw_alloc_stainfo(&padapter->stapriv, bssid.MacAddress);
+ if (!psta) {
+ pmlmepriv->fw_state = pmppriv->prev_fw_state;
+ res = _FAIL;
+ goto end_of_mp_start_test;
+ }
+
+ /* 3 3. join psudo AdHoc */
+ tgt_network->join_res = 1;
+ tgt_network->aid = 1;
+ psta->aid = 1;
+ memcpy(&tgt_network->network, &bssid, length);
+
+ rtw_indicate_connect(padapter);
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+end_of_mp_start_test:
+
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ if (res == _SUCCESS) {
+ /* set MSR to WIFI_FW_ADHOC_STATE */
+ val8 = rtw_read8(padapter, MSR) & 0xFC; /* 0x0102 */
+ val8 |= WIFI_FW_ADHOC_STATE;
+ rtw_write8(padapter, MSR, val8); /* Link in ad hoc network */
+ }
+ return res;
+}
+/* */
+/* This function change the DUT from the MP test mode into normal mode */
+void mp_stop_test(struct adapter *padapter)
+{
+ struct mp_priv *pmppriv = &padapter->mppriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+ struct sta_info *psta;
+
+ if (pmppriv->mode == MP_ON) {
+ pmppriv->bSetTxPower = 0;
+ spin_lock_bh(&pmlmepriv->lock);
+ if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
+ goto end_of_mp_stop_test;
+
+ /* 3 1. disconnect psudo AdHoc */
+ rtw_indicate_disconnect(padapter);
+
+ /* 3 2. clear psta used in mp test mode. */
+ psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
+ if (psta)
+ rtw_free_stainfo(padapter, psta);
+
+ /* 3 3. return to normal state (default:station mode) */
+ pmlmepriv->fw_state = pmppriv->prev_fw_state; /* WIFI_STATION_STATE; */
+
+ /* flush the cur_network */
+ memset(tgt_network, 0, sizeof(struct wlan_network));
+
+ _clr_fwstate_(pmlmepriv, WIFI_MP_STATE);
+
+end_of_mp_stop_test:
+
+ spin_unlock_bh(&pmlmepriv->lock);
+ }
+}
+
+/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
+/*
+ * SetChannel
+ * Description
+ * Use H2C command to change channel,
+ * not only modify rf register, but also other setting need to be done.
+ */
+void SetChannel(struct adapter *pAdapter)
+{
+ Hal_SetChannel(pAdapter);
+}
+
+/*
+ * Notice
+ * Switch bandwitdth may change center frequency(channel)
+ */
+void SetBandwidth(struct adapter *pAdapter)
+{
+ Hal_SetBandwidth(pAdapter);
+}
+
+void SetAntenna(struct adapter *pAdapter)
+{
+ Hal_SetAntenna(pAdapter);
+}
+
+void SetAntennaPathPower(struct adapter *pAdapter)
+{
+ Hal_SetAntennaPathPower(pAdapter);
+}
+
+void SetTxPower(struct adapter *pAdapter)
+{
+ Hal_SetTxPower(pAdapter);
+ }
+
+void SetDataRate(struct adapter *pAdapter)
+{
+ Hal_SetDataRate(pAdapter);
+}
+
+void MP_PHY_SetRFPathSwitch(struct adapter *pAdapter, bool bMain)
+{
+ PHY_SetRFPathSwitch(pAdapter, bMain);
+}
+
+s32 SetThermalMeter(struct adapter *pAdapter, u8 target_ther)
+{
+ return Hal_SetThermalMeter(pAdapter, target_ther);
+}
+
+void GetThermalMeter(struct adapter *pAdapter, u8 *value)
+{
+ Hal_GetThermalMeter(pAdapter, value);
+}
+
+void SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart)
+{
+ PhySetTxPowerLevel(pAdapter);
+ Hal_SetSingleCarrierTx(pAdapter, bStart);
+}
+
+void SetSingleToneTx(struct adapter *pAdapter, u8 bStart)
+{
+ PhySetTxPowerLevel(pAdapter);
+ Hal_SetSingleToneTx(pAdapter, bStart);
+}
+
+void SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart)
+{
+ PhySetTxPowerLevel(pAdapter);
+ Hal_SetCarrierSuppressionTx(pAdapter, bStart);
+}
+
+void SetContinuousTx(struct adapter *pAdapter, u8 bStart)
+{
+ PhySetTxPowerLevel(pAdapter);
+ Hal_SetContinuousTx(pAdapter, bStart);
+}
+
+void PhySetTxPowerLevel(struct adapter *pAdapter)
+{
+ struct mp_priv *pmp_priv = &pAdapter->mppriv;
+
+ if (pmp_priv->bSetTxPower == 0) /* for NO manually set power index */
+ PHY_SetTxPowerLevel8188E(pAdapter, pmp_priv->channel);
+}
+
+/* */
+static void dump_mpframe(struct adapter *padapter, struct xmit_frame *pmpframe)
+{
+ rtw_hal_mgnt_xmit(padapter, pmpframe);
+}
+
+static struct xmit_frame *alloc_mp_xmitframe(struct xmit_priv *pxmitpriv)
+{
+ struct xmit_frame *pmpframe;
+ struct xmit_buf *pxmitbuf;
+
+ pmpframe = rtw_alloc_xmitframe(pxmitpriv);
+ if (!pmpframe)
+ return NULL;
+
+ pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
+ if (!pxmitbuf) {
+ rtw_free_xmitframe(pxmitpriv, pmpframe);
+ return NULL;
+ }
+
+ pmpframe->frame_tag = MP_FRAMETAG;
+
+ pmpframe->pxmitbuf = pxmitbuf;
+
+ pmpframe->buf_addr = pxmitbuf->pbuf;
+
+ pxmitbuf->priv_data = pmpframe;
+
+ return pmpframe;
+}
+
+static int mp_xmit_packet_thread(void *context)
+{
+ struct xmit_frame *pxmitframe;
+ struct mp_tx *pmptx;
+ struct mp_priv *pmp_priv;
+ struct xmit_priv *pxmitpriv;
+ struct adapter *padapter;
+
+ pmp_priv = (struct mp_priv *)context;
+ pmptx = &pmp_priv->tx;
+ padapter = pmp_priv->papdater;
+ pxmitpriv = &padapter->xmitpriv;
+
+ thread_enter("RTW_MP_THREAD");
+
+ /* DBG_88E("%s:pkTx Start\n", __func__); */
+ while (1) {
+ pxmitframe = alloc_mp_xmitframe(pxmitpriv);
+ if (!pxmitframe) {
+ if (pmptx->stop ||
+ padapter->bSurpriseRemoved ||
+ padapter->bDriverStopped) {
+ goto exit;
+ } else {
+ msleep(1);
+ continue;
+ }
+ }
+
+ memcpy((u8 *)(pxmitframe->buf_addr + TXDESC_OFFSET), pmptx->buf, pmptx->write_size);
+ memcpy(&pxmitframe->attrib, &pmptx->attrib, sizeof(struct pkt_attrib));
+
+ dump_mpframe(padapter, pxmitframe);
+
+ pmptx->sended++;
+ pmp_priv->tx_pktcount++;
+
+ if (pmptx->stop ||
+ padapter->bSurpriseRemoved ||
+ padapter->bDriverStopped)
+ goto exit;
+ if ((pmptx->count != 0) &&
+ (pmptx->count == pmptx->sended))
+ goto exit;
+
+ flush_signals_thread();
+ }
+
+exit:
+ kfree(pmptx->pallocated_buf);
+ pmptx->pallocated_buf = NULL;
+ pmptx->stop = 1;
+
+ thread_exit();
+}
+
+void fill_txdesc_for_mp(struct adapter *padapter, struct tx_desc *ptxdesc)
+{
+ struct mp_priv *pmp_priv = &padapter->mppriv;
+ memcpy(ptxdesc, &pmp_priv->tx.desc, TXDESC_SIZE);
+}
+
+void SetPacketTx(struct adapter *padapter)
+{
+ u8 *ptr, *pkt_start, *pkt_end;
+ u32 pkt_size;
+ struct tx_desc *desc;
+ struct rtw_ieee80211_hdr *hdr;
+ u8 payload;
+ bool bmcast;
+ struct pkt_attrib *pattrib;
+ struct mp_priv *pmp_priv;
+
+ pmp_priv = &padapter->mppriv;
+ if (pmp_priv->tx.stop)
+ return;
+ pmp_priv->tx.sended = 0;
+ pmp_priv->tx.stop = 0;
+ pmp_priv->tx_pktcount = 0;
+
+ /* 3 1. update_attrib() */
+ pattrib = &pmp_priv->tx.attrib;
+ memcpy(pattrib->src, padapter->eeprompriv.mac_addr, ETH_ALEN);
+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+ bmcast = is_multicast_ether_addr(pattrib->ra);
+ if (bmcast) {
+ pattrib->mac_id = 1;
+ pattrib->psta = rtw_get_bcmc_stainfo(padapter);
+ } else {
+ pattrib->mac_id = 0;
+ pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
+ }
+
+ pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
+
+ /* 3 2. allocate xmit buffer */
+ pkt_size = pattrib->last_txcmdsz;
+
+ kfree(pmp_priv->tx.pallocated_buf);
+ pmp_priv->tx.write_size = pkt_size;
+ pmp_priv->tx.buf_size = pkt_size + XMITBUF_ALIGN_SZ;
+ pmp_priv->tx.pallocated_buf = kzalloc(pmp_priv->tx.buf_size, GFP_KERNEL);
+ if (!pmp_priv->tx.pallocated_buf) {
+ DBG_88E("%s: malloc(%d) fail!!\n", __func__, pmp_priv->tx.buf_size);
+ return;
+ }
+ pmp_priv->tx.buf = (u8 *)N_BYTE_ALIGMENT((size_t)(pmp_priv->tx.pallocated_buf), XMITBUF_ALIGN_SZ);
+ ptr = pmp_priv->tx.buf;
+
+ desc = &pmp_priv->tx.desc;
+ memset(desc, 0, TXDESC_SIZE);
+ pkt_start = ptr;
+ pkt_end = pkt_start + pkt_size;
+
+ /* 3 3. init TX descriptor */
+ /* offset 0 */
+ desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
+ desc->txdw0 |= cpu_to_le32(pkt_size & 0x0000FFFF); /* packet size */
+ desc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00FF0000); /* 32 bytes for TX Desc */
+ if (bmcast)
+ desc->txdw0 |= cpu_to_le32(BMC); /* broadcast packet */
+
+ desc->txdw1 |= cpu_to_le32((0x01 << 26) & 0xff000000);
+ /* offset 4 */
+ desc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x3F); /* CAM_ID(MAC_ID) */
+ desc->txdw1 |= cpu_to_le32((pattrib->qsel << QSEL_SHT) & 0x00001F00); /* Queue Select, TID */
+
+ desc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000); /* Rate Adaptive ID */
+ /* offset 8 */
+ /* offset 12 */
+
+ desc->txdw3 |= cpu_to_le32((pattrib->seqnum << 16) & 0x0fff0000);
+
+ /* offset 16 */
+ desc->txdw4 |= cpu_to_le32(HW_SSN);
+ desc->txdw4 |= cpu_to_le32(USERATE);
+ desc->txdw4 |= cpu_to_le32(DISDATAFB);
+
+ if (pmp_priv->preamble) {
+ if (pmp_priv->rateidx <= MPT_RATE_54M)
+ desc->txdw4 |= cpu_to_le32(DATA_SHORT); /* CCK Short Preamble */
+ }
+ if (pmp_priv->bandwidth == HT_CHANNEL_WIDTH_40)
+ desc->txdw4 |= cpu_to_le32(DATA_BW);
+
+ /* offset 20 */
+ desc->txdw5 |= cpu_to_le32(pmp_priv->rateidx & 0x0000001F);
+
+ if (pmp_priv->preamble) {
+ if (pmp_priv->rateidx > MPT_RATE_54M)
+ desc->txdw5 |= cpu_to_le32(SGI); /* MCS Short Guard Interval */
+ }
+ desc->txdw5 |= cpu_to_le32(RTY_LMT_EN); /* retry limit enable */
+ desc->txdw5 |= cpu_to_le32(0x00180000); /* DATA/RTS Rate Fallback Limit */
+
+ /* 3 4. make wlan header, make_wlanhdr() */
+ hdr = (struct rtw_ieee80211_hdr *)pkt_start;
+ SetFrameSubType(&hdr->frame_ctl, pattrib->subtype);
+ memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); /* DA */
+ memcpy(hdr->addr2, pattrib->src, ETH_ALEN); /* SA */
+ memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); /* RA, BSSID */
+
+ /* 3 5. make payload */
+ ptr = pkt_start + pattrib->hdrlen;
+
+ switch (pmp_priv->tx.payload) {
+ case 0:
+ payload = 0x00;
+ break;
+ case 1:
+ payload = 0x5a;
+ break;
+ case 2:
+ payload = 0xa5;
+ break;
+ case 3:
+ payload = 0xff;
+ break;
+ default:
+ payload = 0x00;
+ break;
+ }
+
+ memset(ptr, payload, pkt_end - ptr);
+
+ /* 3 6. start thread */
+ pmp_priv->tx.PktTxThread = kthread_run(mp_xmit_packet_thread, pmp_priv, "RTW_MP_THREAD");
+ if (IS_ERR(pmp_priv->tx.PktTxThread))
+ DBG_88E("Create PktTx Thread Fail !!!!!\n");
+}
+
+void SetPacketRx(struct adapter *pAdapter, u8 bStartRx)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+
+ if (bStartRx) {
+ /* Accept CRC error and destination address */
+ pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV |
+ AMF | ADF | APP_FCS | HTC_LOC_CTRL |
+ APP_MIC | APP_PHYSTS;
+
+ pHalData->ReceiveConfig |= (RCR_ACRC32 | RCR_AAP);
+
+ rtw_write32(pAdapter, REG_RCR, pHalData->ReceiveConfig);
+
+ /* Accept all data frames */
+ rtw_write16(pAdapter, REG_RXFLTMAP2, 0xFFFF);
+ } else {
+ rtw_write32(pAdapter, REG_RCR, 0);
+ }
+}
+
+void ResetPhyRxPktCount(struct adapter *pAdapter)
+{
+ u32 i, phyrx_set = 0;
+
+ for (i = 0; i <= 0xF; i++) {
+ phyrx_set = 0;
+ phyrx_set |= _RXERR_RPT_SEL(i); /* select */
+ phyrx_set |= RXERR_RPT_RST; /* set counter to zero */
+ rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
+ }
+}
+
+static u32 GetPhyRxPktCounts(struct adapter *pAdapter, u32 selbit)
+{
+ /* selection */
+ u32 phyrx_set = 0, count = 0;
+
+ phyrx_set = _RXERR_RPT_SEL(selbit & 0xF);
+ rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
+
+ /* Read packet count */
+ count = rtw_read32(pAdapter, REG_RXERR_RPT) & RXERR_COUNTER_MASK;
+
+ return count;
+}
+
+u32 GetPhyRxPktReceived(struct adapter *pAdapter)
+{
+ u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
+
+ OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_OK);
+ CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_OK);
+ HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_OK);
+
+ return OFDM_cnt + CCK_cnt + HT_cnt;
+}
+
+u32 GetPhyRxPktCRC32Error(struct adapter *pAdapter)
+{
+ u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
+
+ OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_FAIL);
+ CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_FAIL);
+ HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_FAIL);
+
+ return OFDM_cnt + CCK_cnt + HT_cnt;
+}
+
+/* reg 0x808[9:0]: FFT data x */
+/* reg 0x808[22]: 0 --> 1 to get 1 FFT data y */
+/* reg 0x8B4[15:0]: FFT data y report */
+static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
+{
+ int psd_val;
+
+ psd_val = rtw_read32(pAdapter, 0x808);
+ psd_val &= 0xFFBFFC00;
+ psd_val |= point;
+
+ rtw_write32(pAdapter, 0x808, psd_val);
+ mdelay(1);
+ psd_val |= 0x00400000;
+
+ rtw_write32(pAdapter, 0x808, psd_val);
+ mdelay(1);
+ psd_val = rtw_read32(pAdapter, 0x8B4);
+
+ psd_val &= 0x0000FFFF;
+
+ return psd_val;
+}
+
+/*
+ *pts start_point_min stop_point_max
+ * 128 64 64 + 128 = 192
+ * 256 128 128 + 256 = 384
+ * 512 256 256 + 512 = 768
+ * 1024 512 512 + 1024 = 1536
+ */
+u32 mp_query_psd(struct adapter *pAdapter, u8 *data)
+{
+ u32 i, psd_pts = 0, psd_start = 0, psd_stop = 0;
+ u32 psd_data = 0;
+
+ if (!netif_running(pAdapter->pnetdev))
+ return 0;
+
+ if (!check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE))
+ return 0;
+
+ if (strlen(data) == 0) { /* default value */
+ psd_pts = 128;
+ psd_start = 64;
+ psd_stop = 128;
+ } else {
+ sscanf(data, "pts =%d, start =%d, stop =%d", &psd_pts, &psd_start, &psd_stop);
+ }
+
+ memset(data, '\0', sizeof(*data));
+
+ i = psd_start;
+ while (i < psd_stop) {
+ if (i >= psd_pts) {
+ psd_data = rtw_GetPSDData(pAdapter, i - psd_pts);
+ } else {
+ psd_data = rtw_GetPSDData(pAdapter, i);
+ }
+ sprintf(data + strlen(data), "%x ", psd_data);
+ i++;
+ }
+
+ msleep(100);
+ return strlen(data) + 1;
+}
+
+void _rtw_mp_xmit_priv(struct xmit_priv *pxmitpriv)
+{
+ int i, res;
+ struct adapter *padapter = pxmitpriv->adapter;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
+ u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
+ u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
+
+ if (padapter->registrypriv.mp_mode == 0) {
+ max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
+ num_xmit_extbuf = NR_XMIT_EXTBUFF;
+ } else {
+ max_xmit_extbuf_size = 6000;
+ num_xmit_extbuf = 8;
+ }
+
+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+ for (i = 0; i < num_xmit_extbuf; i++) {
+ rtw_os_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ));
+
+ pxmitbuf++;
+ }
+
+ vfree(pxmitpriv->pallocated_xmit_extbuf);
+
+ if (padapter->registrypriv.mp_mode == 0) {
+ max_xmit_extbuf_size = 6000;
+ num_xmit_extbuf = 8;
+ } else {
+ max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
+ num_xmit_extbuf = NR_XMIT_EXTBUFF;
+ }
+
+ /* Init xmit extension buff */
+ _rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
+
+ pxmitpriv->pallocated_xmit_extbuf = vzalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
+
+ if (!pxmitpriv->pallocated_xmit_extbuf) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4);
+
+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+
+ for (i = 0; i < num_xmit_extbuf; i++) {
+ INIT_LIST_HEAD(&pxmitbuf->list);
+
+ pxmitbuf->priv_data = NULL;
+ pxmitbuf->padapter = padapter;
+ pxmitbuf->ext_tag = true;
+
+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
+ if (res == _FAIL) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ list_add_tail(&pxmitbuf->list, &pxmitpriv->free_xmit_extbuf_queue.queue);
+ pxmitbuf++;
+ }
+
+ pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
+
+exit:
+ ;
+}
+
+void Hal_ProSetCrystalCap(struct adapter *pAdapter, u32 CrystalCapVal)
+{
+ CrystalCapVal = CrystalCapVal & 0x3F;
+
+ // write 0x24[16:11] = 0x24[22:17] = CrystalCap
+ PHY_SetBBReg(pAdapter, REG_AFE_XTAL_CTRL, 0x7FF800,
+ (CrystalCapVal | (CrystalCapVal << 6)));
+}
diff --git a/drivers/staging/r8188eu/core/rtw_mp_ioctl.c b/drivers/staging/r8188eu/core/rtw_mp_ioctl.c
new file mode 100644
index 000000000000..c85f8e467337
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_mp_ioctl.c
@@ -0,0 +1,1170 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTW_MP_IOCTL_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/mlme_osdep.h"
+#include "../include/rtw_mp_ioctl.h"
+
+/* rtl8188eu_oid_rtl_seg_81_85 section start **************** */
+int rtl8188eu_oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->information_buf_len < sizeof(u8))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ if (poid_par_priv->type_of_oid == SET_OID) {
+ Adapter->registrypriv.wireless_mode = *(u8 *)poid_par_priv->information_buf;
+ } else if (poid_par_priv->type_of_oid == QUERY_OID) {
+ *(u8 *)poid_par_priv->information_buf = Adapter->registrypriv.wireless_mode;
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+ } else {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ return status;
+}
+/* rtl8188eu_oid_rtl_seg_81_87_80 section start **************** */
+int rtl8188eu_oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct bb_reg_param *pbbreg;
+ u16 offset;
+ u32 value;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
+
+ offset = (u16)(pbbreg->offset) & 0xFFF; /* 0ffset :0x800~0xfff */
+ if (offset < BB_REG_BASE_ADDR)
+ offset |= BB_REG_BASE_ADDR;
+
+ value = pbbreg->value;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ write_bbreg(Adapter, offset, 0xFFFFFFFF, value);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct bb_reg_param *pbbreg;
+ u16 offset;
+ u32 value;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
+
+ offset = (u16)(pbbreg->offset) & 0xFFF; /* 0ffset :0x800~0xfff */
+ if (offset < BB_REG_BASE_ADDR)
+ offset |= BB_REG_BASE_ADDR;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ value = read_bbreg(Adapter, offset, 0xFFFFFFFF);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ pbbreg->value = value;
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct rf_reg_param *pbbreg;
+ u8 path;
+ u8 offset;
+ u32 value;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
+
+ if (pbbreg->path >= RF_PATH_MAX)
+ return NDIS_STATUS_NOT_ACCEPTED;
+ if (pbbreg->offset > 0xFF)
+ return NDIS_STATUS_NOT_ACCEPTED;
+ if (pbbreg->value > 0xFFFFF)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ path = (u8)pbbreg->path;
+ offset = (u8)pbbreg->offset;
+ value = pbbreg->value;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ write_rfreg(Adapter, path, offset, value);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct rf_reg_param *pbbreg;
+ u8 path;
+ u8 offset;
+ u32 value;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+ int status = NDIS_STATUS_SUCCESS;
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
+
+ if (pbbreg->path >= RF_PATH_MAX)
+ return NDIS_STATUS_NOT_ACCEPTED;
+ if (pbbreg->offset > 0xFF)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ path = (u8)pbbreg->path;
+ offset = (u8)pbbreg->offset;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ value = read_rfreg(Adapter, path, offset);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ pbbreg->value = value;
+
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+ return status;
+}
+/* rtl8188eu_oid_rtl_seg_81_87_00 section end**************** */
+/* */
+
+/* rtl8188eu_oid_rtl_seg_81_80_00 section start **************** */
+/* */
+int rtl8188eu_oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 ratevalue;/* 4 */
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len != sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ ratevalue = *((u32 *)poid_par_priv->information_buf);/* 4 */
+ if (ratevalue >= MPT_RATE_LAST)
+ return NDIS_STATUS_INVALID_DATA;
+
+ Adapter->mppriv.rateidx = ratevalue;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetDataRate(Adapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 mode;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (Adapter->registrypriv.mp_mode == 0)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+
+ /* IQCalibrateBcut(Adapter); */
+
+ mode = *((u32 *)poid_par_priv->information_buf);
+ Adapter->mppriv.mode = mode;/* 1 for loopback */
+
+ if (mp_start_test(Adapter) == _FAIL) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ goto exit;
+ }
+
+exit:
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ mp_stop_test(Adapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 Channel;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->information_buf_len != sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ if (poid_par_priv->type_of_oid == QUERY_OID) {
+ *((u32 *)poid_par_priv->information_buf) = Adapter->mppriv.channel;
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ Channel = *((u32 *)poid_par_priv->information_buf);
+ if (Channel > 14)
+ return NDIS_STATUS_NOT_ACCEPTED;
+ Adapter->mppriv.channel = Channel;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetChannel(Adapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u16 bandwidth;
+ u16 channel_offset;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *padapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ bandwidth = *((u32 *)poid_par_priv->information_buf);/* 4 */
+ channel_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+ if (bandwidth != HT_CHANNEL_WIDTH_40)
+ bandwidth = HT_CHANNEL_WIDTH_20;
+ padapter->mppriv.bandwidth = (u8)bandwidth;
+ padapter->mppriv.prime_channel_offset = (u8)channel_offset;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetBandwidth(padapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 antenna;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->information_buf_len != sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ if (poid_par_priv->type_of_oid == SET_OID) {
+ antenna = *(u32 *)poid_par_priv->information_buf;
+
+ Adapter->mppriv.antenna_tx = (u16)((antenna & 0xFFFF0000) >> 16);
+ Adapter->mppriv.antenna_rx = (u16)(antenna & 0x0000FFFF);
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetAntenna(Adapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+ } else {
+ antenna = (Adapter->mppriv.antenna_tx << 16) | Adapter->mppriv.antenna_rx;
+ *(u32 *)poid_par_priv->information_buf = antenna;
+ }
+
+ return status;
+}
+
+int rtl8188eu_oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 tx_pwr_idx;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len != sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ tx_pwr_idx = *((u32 *)poid_par_priv->information_buf);
+ if (tx_pwr_idx > MAX_TX_PWR_INDEX_N_MODE)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ Adapter->mppriv.txpoweridx = (u8)tx_pwr_idx;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetTxPower(Adapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+
+/* */
+/* rtl8188eu_oid_rtl_seg_81_80_20 section start **************** */
+/* */
+int rtl8188eu_oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ return status;
+ }
+
+ if (poid_par_priv->information_buf_len == sizeof(u32)) {
+ *(u32 *)poid_par_priv->information_buf = Adapter->mppriv.tx_pktcount;
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+ } else {
+ status = NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ return status;
+ }
+ if (poid_par_priv->information_buf_len == sizeof(u32)) {
+ *(u32 *)poid_par_priv->information_buf = Adapter->mppriv.rx_pktcount;
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+ } else {
+ status = NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ return status;
+ }
+ if (poid_par_priv->information_buf_len == sizeof(u32)) {
+ *(u32 *)poid_par_priv->information_buf = Adapter->mppriv.rx_crcerrpktcount;
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+ } else {
+ status = NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ return status;
+}
+/* */
+
+int rtl8188eu_oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ return status;
+ }
+
+ Adapter->mppriv.tx_pktcount = 0;
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ return status;
+ }
+
+ if (poid_par_priv->information_buf_len == sizeof(u32)) {
+ Adapter->mppriv.rx_pktcount = 0;
+ Adapter->mppriv.rx_crcerrpktcount = 0;
+ } else {
+ status = NDIS_STATUS_INVALID_LENGTH;
+ }
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ return status;
+ }
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ ResetPhyRxPktCount(Adapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len != sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ *(u32 *)poid_par_priv->information_buf = GetPhyRxPktReceived(Adapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len != sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ *(u32 *)poid_par_priv->information_buf = GetPhyRxPktCRC32Error(Adapter);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+ return status;
+}
+/* rtl8188eu_oid_rtl_seg_81_80_20 section end **************** */
+int rtl8188eu_oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 bStartTest;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ bStartTest = *((u32 *)poid_par_priv->information_buf);
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetContinuousTx(Adapter, (u8)bStartTest);
+ if (bStartTest) {
+ struct mp_priv *pmp_priv = &Adapter->mppriv;
+ if (pmp_priv->tx.stop == 0) {
+ pmp_priv->tx.stop = 1;
+ DBG_88E("%s: pkt tx is running...\n", __func__);
+ msleep(5);
+ }
+ pmp_priv->tx.stop = 0;
+ pmp_priv->tx.count = 1;
+ SetPacketTx(Adapter);
+ }
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+
+int rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 bStartTest;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ bStartTest = *((u32 *)poid_par_priv->information_buf);
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetSingleCarrierTx(Adapter, (u8)bStartTest);
+ if (bStartTest) {
+ struct mp_priv *pmp_priv = &Adapter->mppriv;
+ if (pmp_priv->tx.stop == 0) {
+ pmp_priv->tx.stop = 1;
+ DBG_88E("%s: pkt tx is running...\n", __func__);
+ msleep(5);
+ }
+ pmp_priv->tx.stop = 0;
+ pmp_priv->tx.count = 1;
+ SetPacketTx(Adapter);
+ }
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+
+int rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 bStartTest;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ bStartTest = *((u32 *)poid_par_priv->information_buf);
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetCarrierSuppressionTx(Adapter, (u8)bStartTest);
+ if (bStartTest) {
+ struct mp_priv *pmp_priv = &Adapter->mppriv;
+ if (pmp_priv->tx.stop == 0) {
+ pmp_priv->tx.stop = 1;
+ DBG_88E("%s: pkt tx is running...\n", __func__);
+ msleep(5);
+ }
+ pmp_priv->tx.stop = 0;
+ pmp_priv->tx.count = 1;
+ SetPacketTx(Adapter);
+ }
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+
+int rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u32 bStartTest;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ bStartTest = *((u32 *)poid_par_priv->information_buf);
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ SetSingleToneTx(Adapter, (u8)bStartTest);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+
+int rtl8188eu_oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+int rtl8188eu_oid_rt_pro_trigger_gpio_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+ int status = NDIS_STATUS_SUCCESS;
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ rtw_hal_set_hwreg(Adapter, HW_VAR_TRIGGER_GPIO_0, NULL);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* rtl8188eu_oid_rtl_seg_81_80_00 section end **************** */
+/* */
+int rtl8188eu_oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct mp_rw_reg *RegRWStruct;
+ u32 offset, width;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
+ offset = RegRWStruct->offset;
+ width = RegRWStruct->width;
+
+ if (offset > 0xFFF)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+
+ switch (width) {
+ case 1:
+ RegRWStruct->value = rtw_read8(Adapter, offset);
+ break;
+ case 2:
+ RegRWStruct->value = rtw_read16(Adapter, offset);
+ break;
+ default:
+ width = 4;
+ RegRWStruct->value = rtw_read32(Adapter, offset);
+ break;
+ }
+
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ *poid_par_priv->bytes_rw = width;
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct mp_rw_reg *RegRWStruct;
+ u32 offset, value;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *padapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
+ offset = RegRWStruct->offset;
+ value = RegRWStruct->value;
+
+ if (offset > 0xFFF)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+
+ switch (RegRWStruct->width) {
+ case 1:
+ if (value > 0xFF) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ break;
+ }
+ rtw_write8(padapter, offset, (u8)value);
+ break;
+ case 2:
+ if (value > 0xFFFF) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ break;
+ }
+ rtw_write16(padapter, offset, (u16)value);
+ break;
+ case 4:
+ rtw_write32(padapter, offset, value);
+ break;
+ default:
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ break;
+ }
+
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_burst_read_register_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_burst_write_register_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+/* */
+int rtl8188eu_oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+/* */
+int rtl8188eu_oid_rt_pro_write16_eeprom_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_wr_attrib_mem_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_cfg_debug_message_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_set_data_rate_ex_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ int status = NDIS_STATUS_SUCCESS;
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+
+ if (rtw_setdatarate_cmd(Adapter, poid_par_priv->information_buf) != _SUCCESS)
+ status = NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ u8 thermal = 0;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ GetThermalMeter(Adapter, &thermal);
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ *(u32 *)poid_par_priv->information_buf = (u32)thermal;
+ *poid_par_priv->bytes_rw = sizeof(u32);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_read_tssi_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_set_power_tracking_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->information_buf_len < sizeof(u8))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ if (poid_par_priv->type_of_oid == SET_OID) {
+ u8 enable;
+
+ enable = *(u8 *)poid_par_priv->information_buf;
+
+ SetPowerTracking(Adapter, enable);
+ } else {
+ GetPowerTracking(Adapter, (u8 *)poid_par_priv->information_buf);
+ }
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_set_basic_rate_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_qry_pwrstate_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_set_pwrstate_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_h2c_set_rate_table_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+/* */
+int rtl8188eu_oid_rt_pro_h2c_get_rate_table_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+/* rtl8188eu_oid_rtl_seg_87_12_00 section start **************** */
+int rtl8188eu_oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+int rtl8188eu_oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+int rtl8188eu_oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+int rtl8188eu_oid_rt_pro_query_dr_variable_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+int rtl8188eu_oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return NDIS_STATUS_SUCCESS;
+}
+/* */
+int rtl8188eu_oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct efuse_access_struct *pefuse;
+ u8 *data;
+ u16 addr = 0, cnts = 0, max_available_size = 0;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(struct efuse_access_struct))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ pefuse = (struct efuse_access_struct *)poid_par_priv->information_buf;
+ addr = pefuse->start_addr;
+ cnts = pefuse->cnts;
+ data = pefuse->data;
+
+ EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+
+ if ((addr + cnts) > max_available_size)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ if (rtw_efuse_access(Adapter, false, addr, cnts, data) == _FAIL)
+ status = NDIS_STATUS_FAILURE;
+ else
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct efuse_access_struct *pefuse;
+ u8 *data;
+ u16 addr = 0, cnts = 0, max_available_size = 0;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ pefuse = (struct efuse_access_struct *)poid_par_priv->information_buf;
+ addr = pefuse->start_addr;
+ cnts = pefuse->cnts;
+ data = pefuse->data;
+
+ EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+
+ if ((addr + cnts) > max_available_size)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ if (rtw_efuse_access(Adapter, true, addr, cnts, data) == _FAIL)
+ status = NDIS_STATUS_FAILURE;
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct pgpkt *ppgpkt;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ *poid_par_priv->bytes_rw = 0;
+
+ if (poid_par_priv->information_buf_len < sizeof(struct pgpkt *))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ ppgpkt = (struct pgpkt *)poid_par_priv->information_buf;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+
+ if (poid_par_priv->type_of_oid == QUERY_OID) {
+ Efuse_PowerSwitch(Adapter, false, true);
+ if (Efuse_PgPacketRead(Adapter, ppgpkt->offset, ppgpkt->data, false))
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+ else
+ status = NDIS_STATUS_FAILURE;
+ Efuse_PowerSwitch(Adapter, false, false);
+ } else {
+ Efuse_PowerSwitch(Adapter, true, true);
+ if (Efuse_PgPacketWrite(Adapter, ppgpkt->offset, ppgpkt->word_en, ppgpkt->data, false))
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+ else
+ status = NDIS_STATUS_FAILURE;
+ Efuse_PowerSwitch(Adapter, true, false);
+ }
+
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u16 size;
+ u8 ret;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+ ret = efuse_GetCurrentSize(Adapter, &size);
+ _irqlevel_changed_(&oldirql, RAISE);
+ if (ret == _SUCCESS) {
+ *(u32 *)poid_par_priv->information_buf = size;
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+ } else {
+ status = NDIS_STATUS_FAILURE;
+ }
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+
+ if (poid_par_priv->type_of_oid != QUERY_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(u32))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ *(u32 *)poid_par_priv->information_buf = efuse_GetMaxSize(Adapter);
+ *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status;
+
+ if (poid_par_priv->type_of_oid == QUERY_OID)
+ status = rtl8188eu_oid_rt_pro_read_efuse_hdl(poid_par_priv);
+ else
+ status = rtl8188eu_oid_rt_pro_write_efuse_hdl(poid_par_priv);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
+{
+ u8 *data;
+ int status = NDIS_STATUS_SUCCESS;
+ struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+ u16 maplen = 0;
+
+ EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&maplen, false);
+
+ *poid_par_priv->bytes_rw = 0;
+
+ if (poid_par_priv->information_buf_len < maplen)
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ data = (u8 *)poid_par_priv->information_buf;
+
+ _irqlevel_changed_(&oldirql, LOWER);
+
+ if (poid_par_priv->type_of_oid == QUERY_OID) {
+ if (rtw_efuse_map_read(Adapter, 0, maplen, data) == _SUCCESS)
+ *poid_par_priv->bytes_rw = maplen;
+ else
+ status = NDIS_STATUS_FAILURE;
+ } else {
+ /* SET_OID */
+ if (rtw_efuse_map_write(Adapter, 0, maplen, data) == _SUCCESS)
+ *poid_par_priv->bytes_rw = maplen;
+ else
+ status = NDIS_STATUS_FAILURE;
+ }
+
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+
+int rtl8188eu_oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+ return status;
+}
+
+int rtl8188eu_oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+
+ if (poid_par_priv->type_of_oid != SET_OID)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ if (poid_par_priv->information_buf_len < sizeof(u8))
+ return NDIS_STATUS_INVALID_LENGTH;
+
+ return status;
+}
+
+int rtl8188eu_oid_rt_pro_set_tx_agc_offset_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+int rtl8188eu_oid_rt_pro_set_pkt_test_mode_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
+
+int rtl8188eu_mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv)
+{
+ struct mp_xmit_parm *pparm;
+ struct adapter *padapter;
+ struct mp_priv *pmp_priv;
+ struct pkt_attrib *pattrib;
+
+ pparm = (struct mp_xmit_parm *)poid_par_priv->information_buf;
+ padapter = (struct adapter *)poid_par_priv->adapter_context;
+ pmp_priv = &padapter->mppriv;
+
+ if (poid_par_priv->type_of_oid == QUERY_OID) {
+ pparm->enable = !pmp_priv->tx.stop;
+ pparm->count = pmp_priv->tx.sended;
+ } else {
+ if (pparm->enable == 0) {
+ pmp_priv->tx.stop = 1;
+ } else if (pmp_priv->tx.stop == 1) {
+ pmp_priv->tx.stop = 0;
+ pmp_priv->tx.count = pparm->count;
+ pmp_priv->tx.payload = pparm->payload_type;
+ pattrib = &pmp_priv->tx.attrib;
+ pattrib->pktlen = pparm->length;
+ memcpy(pattrib->dst, pparm->da, ETH_ALEN);
+ SetPacketTx(padapter);
+ } else {
+ return NDIS_STATUS_FAILURE;
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+/* */
+int rtl8188eu_oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv)
+{
+ int status = NDIS_STATUS_SUCCESS;
+
+ if (poid_par_priv->type_of_oid != SET_OID) {
+ status = NDIS_STATUS_NOT_ACCEPTED;
+ return status;
+ }
+
+ _irqlevel_changed_(&oldirql, LOWER);
+
+ /* CALL the power_down function */
+ _irqlevel_changed_(&oldirql, RAISE);
+
+ return status;
+}
+/* */
+int rtl8188eu_oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv)
+{
+ return 0;
+}
diff --git a/drivers/staging/r8188eu/core/rtw_p2p.c b/drivers/staging/r8188eu/core/rtw_p2p.c
new file mode 100644
index 000000000000..e2b6cf2386e0
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_p2p.c
@@ -0,0 +1,1997 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTW_P2P_C_
+
+#include "../include/drv_types.h"
+#include "../include/rtw_p2p.h"
+#include "../include/wifi.h"
+
+#ifdef CONFIG_88EU_P2P
+
+static int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8 *ch_list, u8 ch_cnt)
+{
+ int found = 0, i = 0;
+
+ for (i = 0; i < ch_cnt; i++) {
+ if (ch_list[i] == desired_ch) {
+ found = 1;
+ break;
+ }
+ }
+ return found;
+}
+
+static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+ struct list_head *phead, *plist;
+ u32 len = 0;
+ u16 attr_len = 0;
+ u8 tmplen, *pdata_attr, *pstart, *pcur;
+ struct sta_info *psta = NULL;
+ struct adapter *padapter = pwdinfo->padapter;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_88E("%s\n", __func__);
+
+ pdata_attr = kzalloc(MAX_P2P_IE_LEN, GFP_KERNEL);
+
+ pstart = pdata_attr;
+ pcur = pdata_attr;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
+ /* look up sta asoc_queue */
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+
+ plist = plist->next;
+
+ if (psta->is_p2p_device) {
+ tmplen = 0;
+
+ pcur++;
+
+ /* P2P device address */
+ memcpy(pcur, psta->dev_addr, ETH_ALEN);
+ pcur += ETH_ALEN;
+
+ /* P2P interface address */
+ memcpy(pcur, psta->hwaddr, ETH_ALEN);
+ pcur += ETH_ALEN;
+
+ *pcur = psta->dev_cap;
+ pcur++;
+
+ /* u16*)(pcur) = cpu_to_be16(psta->config_methods); */
+ RTW_PUT_BE16(pcur, psta->config_methods);
+ pcur += 2;
+
+ memcpy(pcur, psta->primary_dev_type, 8);
+ pcur += 8;
+
+ *pcur = psta->num_of_secdev_type;
+ pcur++;
+
+ memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type * 8);
+ pcur += psta->num_of_secdev_type * 8;
+
+ if (psta->dev_name_len > 0) {
+ /* u16*)(pcur) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
+ RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);
+ pcur += 2;
+
+ /* u16*)(pcur) = cpu_to_be16(psta->dev_name_len); */
+ RTW_PUT_BE16(pcur, psta->dev_name_len);
+ pcur += 2;
+
+ memcpy(pcur, psta->dev_name, psta->dev_name_len);
+ pcur += psta->dev_name_len;
+ }
+
+ tmplen = (u8)(pcur - pstart);
+
+ *pstart = (tmplen - 1);
+
+ attr_len += tmplen;
+
+ /* pstart += tmplen; */
+ pstart = pcur;
+ }
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ if (attr_len > 0)
+ len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
+
+ kfree(pdata_attr);
+ return len;
+}
+
+static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct adapter *padapter = pwdinfo->padapter;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_GO_DISC_REQUEST;
+ u8 dialogToken = 0;
+
+ DBG_88E("[%s]\n", __func__);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ /* Build P2P action frame header */
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
+
+ /* there is no IE in this P2P action frame */
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct adapter *padapter = pwdinfo->padapter;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_DEVDISC_RESP;
+ u8 p2pie[8] = { 0x00 };
+ u32 p2pielen = 0;
+
+ DBG_88E("[%s]\n", __func__);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ /* Build P2P public action frame header */
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
+
+ /* Build P2P IE */
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* P2P_ATTR_STATUS */
+ p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8 *raddr, u8 *frame_body, u16 config_method)
+{
+ struct adapter *padapter = pwdinfo->padapter;
+ unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = P2P_PUB_ACTION_ACTION;
+ u8 dialogToken = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_PROVISION_DISC_RESP;
+ u8 wpsie[100] = { 0x00 };
+ u8 wpsielen = 0;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
+
+ wpsielen = 0;
+ /* WPS OUI */
+ RTW_PUT_BE32(wpsie, WPSOUI);
+ wpsielen += 4;
+
+ /* Config Method */
+ /* Type: */
+ RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
+ wpsielen += 2;
+
+ /* Length: */
+ RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
+ wpsielen += 2;
+
+ /* Value: */
+ RTW_PUT_BE16(wpsie + wpsielen, config_method);
+ wpsielen += 2;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct adapter *padapter = pwdinfo->padapter;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
+ __be32 p2poui = cpu_to_be32(P2POUI);
+ u8 oui_subtype = P2P_PRESENCE_RESPONSE;
+ u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
+ u8 noa_attr_content[32] = { 0x00 };
+ u32 p2pielen = 0;
+
+ DBG_88E("[%s]\n", __func__);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_ctl;
+ *(fctrl) = 0;
+
+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ /* Build P2P action frame header */
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
+
+ /* Add P2P IE header */
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Add Status attribute in P2P IE */
+ p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
+
+ /* Add NoA attribute in P2P IE */
+ noa_attr_content[0] = 0x1;/* index */
+ noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
+
+ /* todo: Notice of Absence Descriptor(s) */
+
+ p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+ u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
+ u16 capability = 0;
+ u32 len = 0, p2pielen = 0;
+ __le16 le_tmp;
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
+ /* 1. P2P Capability */
+ /* 2. P2P Device ID */
+ /* 3. Notice of Absence (NOA) */
+
+ /* P2P Capability ATTR */
+ /* Type: */
+ /* Length: */
+ /* Value: */
+ /* Device Capability Bitmap, 1 byte */
+ /* Be able to participate in additional P2P Groups and */
+ /* support the P2P Invitation Procedure */
+ /* Group Capability Bitmap, 1 byte */
+ capability = P2P_DEVCAP_INVITATION_PROC | P2P_DEVCAP_CLIENT_DISCOVERABILITY;
+ capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+ capability |= (P2P_GRPCAP_GROUP_FORMATION << 8);
+
+ le_tmp = cpu_to_le16(capability);
+ p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8 *)&le_tmp);
+
+ /* P2P Device ID ATTR */
+ p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
+
+ /* Notice of Absence ATTR */
+ /* Type: */
+ /* Length: */
+ /* Value: */
+
+ pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
+ return len;
+}
+
+u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+ u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
+ u32 len = 0, p2pielen = 0;
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20100907 */
+ /* According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
+ /* 1. P2P Capability */
+ /* 2. Extended Listen Timing */
+ /* 3. Notice of Absence (NOA) (Only GO needs this) */
+ /* 4. Device Info */
+ /* 5. Group Info (Only GO need this) */
+
+ /* P2P Capability ATTR */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
+
+ /* Length: */
+ /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
+ RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Device Capability Bitmap, 1 byte */
+ p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
+
+ /* Group Capability Bitmap, 1 byte */
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ p2pie[p2pielen] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+ p2pie[p2pielen] |= P2P_GRPCAP_GROUP_FORMATION;
+
+ p2pielen++;
+ } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
+ /* Group Capability Bitmap, 1 byte */
+ if (pwdinfo->persistent_supported)
+ p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
+ else
+ p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
+ }
+
+ /* Extended Listen Timing ATTR */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
+
+ /* Length: */
+ /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004); */
+ RTW_PUT_LE16(p2pie + p2pielen, 0x0004);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Availability Period */
+ /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
+ RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
+ p2pielen += 2;
+
+ /* Availability Interval */
+ /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
+ RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
+ p2pielen += 2;
+
+ /* Notice of Absence ATTR */
+ /* Type: */
+ /* Length: */
+ /* Value: */
+
+ /* Device Info ATTR */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
+
+ /* Length: */
+ /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
+ /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
+ /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
+ RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address */
+ memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* Config Method */
+ /* This field should be big endian. Noted by P2P specification. */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); */
+ RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);
+ p2pielen += 2;
+
+ /* Primary Device Type */
+ /* Category ID */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
+ RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
+ p2pielen += 2;
+
+ /* OUI */
+ /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
+ RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
+ p2pielen += 4;
+
+ /* Sub Category ID */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
+ RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
+ p2pielen += 2;
+
+ /* Number of Secondary Device Types */
+ p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
+
+ /* Device Name */
+ /* Type: */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
+ RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
+ p2pielen += 2;
+
+ /* Length: */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
+ RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
+ p2pielen += pwdinfo->device_name_len;
+
+ /* Group Info ATTR */
+ /* Type: */
+ /* Length: */
+ /* Value: */
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+ p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
+
+ pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
+
+ return len;
+}
+
+u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
+{
+ u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
+ u32 len = 0, p2pielen = 0;
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* Commented by Albert 20110301 */
+ /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
+ /* 1. P2P Capability */
+ /* 2. Device Info */
+ /* 3. Group ID (When joining an operating P2P Group) */
+
+ /* P2P Capability ATTR */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
+
+ /* Length: */
+ /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
+ RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
+ p2pielen += 2;
+
+ /* Value: */
+ /* Device Capability Bitmap, 1 byte */
+ p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
+
+ /* Group Capability Bitmap, 1 byte */
+ if (pwdinfo->persistent_supported)
+ p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
+ else
+ p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
+
+ /* Device Info ATTR */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
+
+ /* Length: */
+ /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
+ /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
+ /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
+ RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ /* P2P Device Address */
+ memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ /* Config Method */
+ /* This field should be big endian. Noted by P2P specification. */
+ if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) {
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); */
+ RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);
+ } else {
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); */
+ RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);
+ }
+
+ p2pielen += 2;
+
+ /* Primary Device Type */
+ /* Category ID */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
+ RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
+ p2pielen += 2;
+
+ /* OUI */
+ /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
+ RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
+ p2pielen += 4;
+
+ /* Sub Category ID */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
+ RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
+ p2pielen += 2;
+
+ /* Number of Secondary Device Types */
+ p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
+
+ /* Device Name */
+ /* Type: */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
+ RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
+ p2pielen += 2;
+
+ /* Length: */
+ /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
+ RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
+ p2pielen += pwdinfo->device_name_len;
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
+ /* Added by Albert 2011/05/19 */
+ /* In this case, the pdev_raddr is the device address of the group owner. */
+
+ /* P2P Group ID ATTR */
+ /* Type: */
+ p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
+
+ /* Length: */
+ /* u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + ussidlen); */
+ RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);
+ p2pielen += 2;
+
+ /* Value: */
+ memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
+ p2pielen += ETH_ALEN;
+
+ memcpy(p2pie + p2pielen, pssid, ussidlen);
+ p2pielen += ussidlen;
+ }
+
+ pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
+
+ return len;
+}
+
+u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
+{
+ u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
+ u32 len = 0, p2pielen = 0;
+
+ /* P2P OUI */
+ p2pielen = 0;
+ p2pie[p2pielen++] = 0x50;
+ p2pie[p2pielen++] = 0x6F;
+ p2pie[p2pielen++] = 0x9A;
+ p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
+
+ /* According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
+ /* 1. Status */
+ /* 2. Extended Listen Timing (optional) */
+
+ /* Status ATTR */
+ p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
+
+ /* Extended Listen Timing ATTR */
+ /* Type: */
+ /* Length: */
+ /* Value: */
+
+ pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
+
+ return len;
+}
+
+u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+ u32 len = 0;
+
+ return len;
+}
+
+u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+ u8 *p;
+ u32 ret = false;
+ u8 *p2pie;
+ u32 p2pielen = 0;
+ int ssid_len = 0, rate_cnt = 0;
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
+ len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
+
+ if (rate_cnt <= 4) {
+ int i, g_rate = 0;
+
+ for (i = 0; i < rate_cnt; i++) {
+ if (((*(p + 2 + i) & 0xff) != 0x02) &&
+ ((*(p + 2 + i) & 0xff) != 0x04) &&
+ ((*(p + 2 + i) & 0xff) != 0x0B) &&
+ ((*(p + 2 + i) & 0xff) != 0x16))
+ g_rate = 1;
+ }
+
+ if (g_rate == 0) {
+ /* There is no OFDM rate included in SupportedRates IE of this probe request frame */
+ /* The driver should response this probe request. */
+ return ret;
+ }
+ } else {
+ /* rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
+ /* We should proceed the following check for this probe request. */
+ }
+
+ /* Added comments by Albert 20100906 */
+ /* There are several items we should check here. */
+ /* 1. This probe request frame must contain the P2P IE. (Done) */
+ /* 2. This probe request frame must contain the wildcard SSID. (Done) */
+ /* 3. Wildcard BSSID. (Todo) */
+ /* 4. Destination Address. (Done in mgt_dispatcher function) */
+ /* 5. Requested Device Type in WSC IE. (Todo) */
+ /* 6. Device ID attribute in P2P IE. (Todo) */
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
+ len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
+
+ ssid_len &= 0xff; /* Just last 1 byte is valid for ssid len of the probe request */
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_, NULL, &p2pielen);
+ if (p2pie) {
+ if (p && !memcmp((void *)(p + 2), (void *)pwdinfo->p2p_wildcard_ssid, 7)) {
+ /* todo: */
+ /* Check Requested Device Type attributes in WSC IE. */
+ /* Check Device ID attribute in P2P IE */
+
+ ret = true;
+ } else if (p && ssid_len == 0) {
+ ret = true;
+ }
+ } else {
+ /* non -p2p device */
+ }
+ }
+
+ return ret;
+}
+
+u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
+{
+ u8 status_code = P2P_STATUS_SUCCESS;
+ u8 *pbuf, *pattr_content = NULL;
+ u32 attr_contentlen = 0;
+ u16 cap_attr = 0;
+ unsigned short frame_type, ie_offset = 0;
+ u8 *ies;
+ u32 ies_len;
+ u8 *p2p_ie;
+ u32 p2p_ielen = 0;
+ __be16 be_tmp;
+ __le16 le_tmp;
+
+ if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+ return P2P_STATUS_FAIL_REQUEST_UNABLE;
+
+ frame_type = GetFrameSubType(pframe);
+ if (frame_type == WIFI_ASSOCREQ)
+ ie_offset = _ASOCREQ_IE_OFFSET_;
+ else /* WIFI_REASSOCREQ */
+ ie_offset = _REASOCREQ_IE_OFFSET_;
+
+ ies = pframe + WLAN_HDR_A3_LEN + ie_offset;
+ ies_len = len - WLAN_HDR_A3_LEN - ie_offset;
+
+ p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
+
+ if (!p2p_ie) {
+ DBG_88E("[%s] P2P IE not Found!!\n", __func__);
+ status_code = P2P_STATUS_FAIL_INVALID_PARAM;
+ } else {
+ DBG_88E("[%s] P2P IE Found!!\n", __func__);
+ }
+
+ while (p2p_ie) {
+ /* Check P2P Capability ATTR */
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&le_tmp, (uint *)&attr_contentlen)) {
+ DBG_88E("[%s] Got P2P Capability Attr!!\n", __func__);
+ cap_attr = le16_to_cpu(le_tmp);
+ psta->dev_cap = cap_attr & 0xff;
+ }
+
+ /* Check Extended Listen Timing ATTR */
+
+ /* Check P2P Device Info ATTR */
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) {
+ DBG_88E("[%s] Got P2P DEVICE INFO Attr!!\n", __func__);
+ pattr_content = kzalloc(attr_contentlen, GFP_KERNEL);
+ pbuf = pattr_content;
+ if (pattr_content) {
+ u8 num_of_secdev_type;
+ u16 dev_name_len;
+
+ rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, pattr_content, (uint *)&attr_contentlen);
+
+ memcpy(psta->dev_addr, pattr_content, ETH_ALEN);/* P2P Device Address */
+
+ pattr_content += ETH_ALEN;
+
+ memcpy(&be_tmp, pattr_content, 2);/* Config Methods */
+ psta->config_methods = be16_to_cpu(be_tmp);
+
+ pattr_content += 2;
+
+ memcpy(psta->primary_dev_type, pattr_content, 8);
+
+ pattr_content += 8;
+
+ num_of_secdev_type = *pattr_content;
+ pattr_content += 1;
+
+ if (num_of_secdev_type == 0) {
+ psta->num_of_secdev_type = 0;
+ } else {
+ u32 len;
+
+ psta->num_of_secdev_type = num_of_secdev_type;
+
+ len = (sizeof(psta->secdev_types_list) < (num_of_secdev_type * 8)) ?
+ (sizeof(psta->secdev_types_list)) : (num_of_secdev_type * 8);
+
+ memcpy(psta->secdev_types_list, pattr_content, len);
+
+ pattr_content += (num_of_secdev_type * 8);
+ }
+
+ psta->dev_name_len = 0;
+ if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(__be16 *)pattr_content)) {
+ dev_name_len = be16_to_cpu(*(__be16 *)(pattr_content + 2));
+
+ psta->dev_name_len = (sizeof(psta->dev_name) < dev_name_len) ? sizeof(psta->dev_name) : dev_name_len;
+
+ memcpy(psta->dev_name, pattr_content + 4, psta->dev_name_len);
+ }
+ kfree(pbuf);
+ }
+ }
+
+ /* Get the next P2P IE */
+ p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
+ }
+
+ return status_code;
+}
+
+u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+ u8 *frame_body;
+ u8 status, dialogToken;
+ struct sta_info *psta = NULL;
+ struct adapter *padapter = pwdinfo->padapter;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *p2p_ie;
+ u32 p2p_ielen = 0;
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+ dialogToken = frame_body[7];
+ status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
+
+ p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
+ if (p2p_ie) {
+ u8 groupid[38] = { 0x00 };
+ u8 dev_addr[ETH_ALEN] = { 0x00 };
+ u32 attr_contentlen = 0;
+
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
+ if (!memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
+ !memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN, pwdinfo->p2p_group_ssid_len)) {
+ attr_contentlen = 0;
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) {
+ struct list_head *phead, *plist;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
+ /* look up sta asoc_queue */
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+
+ plist = plist->next;
+
+ if (psta->is_p2p_device && (psta->dev_cap & P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
+ !memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {
+ /* issue GO Discoverability Request */
+ issue_group_disc_req(pwdinfo, psta->hwaddr);
+ status = P2P_STATUS_SUCCESS;
+ break;
+ } else {
+ status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+ }
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+ } else {
+ status = P2P_STATUS_FAIL_INVALID_PARAM;
+ }
+ } else {
+ status = P2P_STATUS_FAIL_INVALID_PARAM;
+ }
+ }
+ }
+
+ /* issue Device Discoverability Response */
+ issue_p2p_devdisc_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
+
+ return (status == P2P_STATUS_SUCCESS) ? true : false;
+}
+
+u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+ return true;
+}
+
+u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+ u8 *frame_body;
+ u8 *wpsie;
+ uint wps_ielen = 0, attr_contentlen = 0;
+ u16 uconfig_method = 0;
+ __be16 be_tmp;
+
+ frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+ wpsie = rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
+ if (wpsie) {
+ if (rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD, (u8 *)&be_tmp, &attr_contentlen)) {
+ uconfig_method = be16_to_cpu(be_tmp);
+ switch (uconfig_method) {
+ case WPS_CM_DISPLYA:
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
+ break;
+ case WPS_CM_LABEL:
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3);
+ break;
+ case WPS_CM_PUSH_BUTTON:
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
+ break;
+ case WPS_CM_KEYPAD:
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
+ break;
+ }
+ issue_p2p_provision_resp(pwdinfo, GetAddr2Ptr(pframe), frame_body, uconfig_method);
+ }
+ }
+ DBG_88E("[%s] config method = %s\n", __func__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
+ return true;
+}
+
+u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe)
+{
+ return true;
+}
+
+static u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
+{
+ u8 i = 0, j = 0;
+ u8 temp = 0;
+ u8 ch_no = 0;
+ ch_content += 3;
+ ch_cnt -= 3;
+
+ while (ch_cnt > 0) {
+ ch_content += 1;
+ ch_cnt -= 1;
+ temp = *ch_content;
+ for (i = 0 ; i < temp ; i++, j++)
+ peer_ch_list[j] = *(ch_content + 1 + i);
+ ch_content += (temp + 1);
+ ch_cnt -= (temp + 1);
+ ch_no += temp;
+ }
+
+ return ch_no;
+}
+
+static u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
+{
+ int i = 0, j = 0, temp = 0;
+ u8 ch_no = 0;
+
+ for (i = 0; i < peer_ch_num; i++) {
+ for (j = temp; j < pmlmeext->max_chan_nums; j++) {
+ if (*(peer_ch_list + i) == pmlmeext->channel_set[j].ChannelNum) {
+ ch_list_inclusioned[ch_no++] = *(peer_ch_list + i);
+ temp = j;
+ break;
+ }
+ }
+ }
+
+ return ch_no;
+}
+
+u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+ struct adapter *padapter = pwdinfo->padapter;
+ u8 result = P2P_STATUS_SUCCESS;
+ u32 p2p_ielen = 0, wps_ielen = 0;
+ u8 *ies;
+ u32 ies_len;
+ u8 *p2p_ie;
+ u8 *wpsie;
+ u16 wps_devicepassword_id = 0x0000;
+ uint wps_devicepassword_id_len = 0;
+ __be16 be_tmp;
+
+ wpsie = rtw_get_wps_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
+ if (wpsie) {
+ /* Commented by Kurt 20120113 */
+ /* If some device wants to do p2p handshake without sending prov_disc_req */
+ /* We have to get peer_req_cm from here. */
+ if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
+ rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
+ wps_devicepassword_id = be16_to_cpu(be_tmp);
+
+ if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
+ else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
+ else
+ memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
+ }
+ } else {
+ DBG_88E("[%s] WPS IE not Found!!\n", __func__);
+ result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ return result;
+ }
+
+ if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {
+ result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
+ return result;
+ }
+
+ ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
+ ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+ p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
+
+ if (!p2p_ie) {
+ DBG_88E("[%s] P2P IE not Found!!\n", __func__);
+ result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ }
+
+ while (p2p_ie) {
+ u8 attr_content = 0x00;
+ u32 attr_contentlen = 0;
+ u8 ch_content[50] = { 0x00 };
+ uint ch_cnt = 0;
+ u8 peer_ch_list[50] = { 0x00 };
+ u8 peer_ch_num = 0;
+ u8 ch_list_inclusioned[50] = { 0x00 };
+ u8 ch_num_inclusioned = 0;
+
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
+
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen)) {
+ DBG_88E("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
+ pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
+
+ if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
+ /* Try to match the tie breaker value */
+ if (pwdinfo->intent == P2P_MAX_INTENT) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
+ } else {
+ if (attr_content & 0x01)
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ else
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ }
+ } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ } else {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ }
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ /* Store the group id information. */
+ memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
+ memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
+ }
+ }
+
+ attr_contentlen = 0;
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
+ if (attr_contentlen != ETH_ALEN)
+ memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
+ }
+
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt)) {
+ peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
+ ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
+
+ if (ch_num_inclusioned == 0) {
+ DBG_88E("[%s] No common channel in channel list!\n", __func__);
+ result = P2P_STATUS_FAIL_NO_COMMON_CH;
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ break;
+ }
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
+ ch_list_inclusioned, ch_num_inclusioned)) {
+ u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
+ attr_contentlen = 0;
+
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
+ peer_operating_ch = operatingch_info[4];
+
+ if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
+ ch_list_inclusioned, ch_num_inclusioned)) {
+ /**
+ * Change our operating channel as peer's for compatibility.
+ */
+ pwdinfo->operating_channel = peer_operating_ch;
+ DBG_88E("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
+ } else {
+ /* Take first channel of ch_list_inclusioned as operating channel */
+ pwdinfo->operating_channel = ch_list_inclusioned[0];
+ DBG_88E("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
+ }
+ }
+ }
+ }
+
+ /* Get the next P2P IE */
+ p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
+ }
+ return result;
+}
+
+u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+ struct adapter *padapter = pwdinfo->padapter;
+ u8 result = P2P_STATUS_SUCCESS;
+ u32 p2p_ielen, wps_ielen;
+ u8 *ies;
+ u32 ies_len;
+ u8 *p2p_ie;
+
+ ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
+ ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+ /* Be able to know which one is the P2P GO and which one is P2P client. */
+
+ if (rtw_get_wps_ie(ies, ies_len, NULL, &wps_ielen)) {
+ } else {
+ DBG_88E("[%s] WPS IE not Found!!\n", __func__);
+ result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ }
+
+ p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
+ if (!p2p_ie) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
+ } else {
+ u8 attr_content = 0x00;
+ u32 attr_contentlen = 0;
+ u8 operatingch_info[5] = { 0x00 };
+ u8 groupid[38];
+ u8 peer_ch_list[50] = { 0x00 };
+ u8 peer_ch_num = 0;
+ u8 ch_list_inclusioned[50] = { 0x00 };
+ u8 ch_num_inclusioned = 0;
+
+ while (p2p_ie) { /* Found the P2P IE. */
+ rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
+ if (attr_contentlen == 1) {
+ DBG_88E("[%s] Status = %d\n", __func__, attr_content);
+ if (attr_content == P2P_STATUS_SUCCESS) {
+ /* Do nothing. */
+ } else {
+ if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content) {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
+ } else {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ }
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ result = attr_content;
+ break;
+ }
+ }
+
+ /* Try to get the peer's interface address */
+ attr_contentlen = 0;
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
+ if (attr_contentlen != ETH_ALEN)
+ memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
+ }
+
+ /* Try to get the peer's intent and tie breaker value. */
+ attr_content = 0x00;
+ attr_contentlen = 0;
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen)) {
+ DBG_88E("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
+ pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
+
+ if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
+ /* Try to match the tie breaker value */
+ if (pwdinfo->intent == P2P_MAX_INTENT) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ } else {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ if (attr_content & 0x01)
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ else
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ }
+ } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ } else {
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ }
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ /* Store the group id information. */
+ memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
+ memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
+ }
+ }
+
+ /* Try to get the operation channel information */
+
+ attr_contentlen = 0;
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
+ DBG_88E("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
+ pwdinfo->peer_operating_ch = operatingch_info[4];
+ }
+
+ /* Try to get the channel list information */
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len)) {
+ DBG_88E("[%s] channel list attribute found, len = %d\n", __func__, pwdinfo->channel_list_attr_len);
+
+ peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
+ ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
+
+ if (ch_num_inclusioned == 0) {
+ DBG_88E("[%s] No common channel in channel list!\n", __func__);
+ result = P2P_STATUS_FAIL_NO_COMMON_CH;
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ break;
+ }
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
+ ch_list_inclusioned, ch_num_inclusioned)) {
+ u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
+ attr_contentlen = 0;
+
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
+ peer_operating_ch = operatingch_info[4];
+
+ if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
+ ch_list_inclusioned, ch_num_inclusioned)) {
+ /**
+ * Change our operating channel as peer's for compatibility.
+ */
+ pwdinfo->operating_channel = peer_operating_ch;
+ DBG_88E("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
+ } else {
+ /* Take first channel of ch_list_inclusioned as operating channel */
+ pwdinfo->operating_channel = ch_list_inclusioned[0];
+ DBG_88E("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
+ }
+ }
+ }
+ } else {
+ DBG_88E("[%s] channel list attribute not found!\n", __func__);
+ }
+
+ /* Try to get the group id information if peer is GO */
+ attr_contentlen = 0;
+ memset(groupid, 0x00, 38);
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
+ memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
+ memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
+ }
+
+ /* Get the next P2P IE */
+ p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
+ }
+ }
+ return result;
+}
+
+u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+ u8 *ies;
+ u32 ies_len;
+ u8 *p2p_ie;
+ u32 p2p_ielen = 0;
+ u8 result = P2P_STATUS_SUCCESS;
+ ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
+ ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+ p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
+ while (p2p_ie) { /* Found the P2P IE. */
+ u8 attr_content = 0x00, operatingch_info[5] = { 0x00 };
+ u8 groupid[38] = { 0x00 };
+ u32 attr_contentlen = 0;
+
+ pwdinfo->negotiation_dialog_token = 1;
+ rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
+ if (attr_contentlen == 1) {
+ DBG_88E("[%s] Status = %d\n", __func__, attr_content);
+ result = attr_content;
+
+ if (attr_content == P2P_STATUS_SUCCESS) {
+ u8 bcancelled = 0;
+
+ _cancel_timer(&pwdinfo->restore_p2p_state_timer, &bcancelled);
+
+ /* Commented by Albert 20100911 */
+ /* Todo: Need to handle the case which both Intents are the same. */
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1)) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ } else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1)) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ } else {
+ /* Have to compare the Tie Breaker */
+ if (pwdinfo->peer_intent & 0x01)
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ else
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ }
+ } else {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+ break;
+ }
+ }
+
+ /* Try to get the group id information */
+ attr_contentlen = 0;
+ memset(groupid, 0x00, 38);
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
+ DBG_88E("[%s] Ssid = %s, ssidlen = %zu\n", __func__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
+ memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
+ memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
+ }
+
+ attr_contentlen = 0;
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
+ DBG_88E("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
+ pwdinfo->peer_operating_ch = operatingch_info[4];
+ }
+
+ /* Get the next P2P IE */
+ p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
+ }
+ return result;
+}
+
+u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+ u8 *frame_body;
+ u8 dialogToken = 0;
+ u8 status = P2P_STATUS_SUCCESS;
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+ dialogToken = frame_body[6];
+
+ /* todo: check NoA attribute */
+
+ issue_p2p_presence_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
+
+ return true;
+}
+
+static void find_phase_handler(struct adapter *padapter)
+{
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ndis_802_11_ssid ssid;
+
+ memset((unsigned char *)&ssid, 0, sizeof(struct ndis_802_11_ssid));
+ memcpy(ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
+ ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
+
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+
+ spin_lock_bh(&pmlmepriv->lock);
+ spin_unlock_bh(&pmlmepriv->lock);
+
+}
+
+void p2p_concurrent_handler(struct adapter *padapter);
+
+static void restore_p2p_state_handler(struct adapter *padapter)
+{
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
+ /* In the P2P client mode, the driver should not switch back to its listen channel */
+ /* because this P2P client should stay at the operating channel of P2P GO. */
+ set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ }
+
+}
+
+static void pre_tx_invitereq_handler(struct adapter *padapter)
+{
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 val8 = 1;
+
+ set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+ issue_probereq_p2p(padapter, NULL);
+ _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+
+}
+
+static void pre_tx_provdisc_handler(struct adapter *padapter)
+{
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 val8 = 1;
+
+ set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+ issue_probereq_p2p(padapter, NULL);
+ _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+
+}
+
+static void pre_tx_negoreq_handler(struct adapter *padapter)
+{
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 val8 = 1;
+
+ set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+ issue_probereq_p2p(padapter, NULL);
+ _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+
+}
+
+void p2p_protocol_wk_hdl(struct adapter *padapter, int intCmdType)
+{
+
+ switch (intCmdType) {
+ case P2P_FIND_PHASE_WK:
+ find_phase_handler(padapter);
+ break;
+ case P2P_RESTORE_STATE_WK:
+ restore_p2p_state_handler(padapter);
+ break;
+ case P2P_PRE_TX_PROVDISC_PROCESS_WK:
+ pre_tx_provdisc_handler(padapter);
+ break;
+ case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
+ pre_tx_invitereq_handler(padapter);
+ break;
+ case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
+ pre_tx_negoreq_handler(padapter);
+ break;
+ }
+
+}
+
+void process_p2p_ps_ie(struct adapter *padapter, u8 *IEs, u32 IELength)
+{
+ u8 *ies;
+ u32 ies_len;
+ u8 *p2p_ie;
+ u32 p2p_ielen = 0;
+ u8 noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
+ u32 attr_contentlen = 0;
+
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 find_p2p = false, find_p2p_ps = false;
+ u8 noa_offset, noa_num, noa_index;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return;
+ if (IELength <= _BEACON_IE_OFFSET_)
+ return;
+
+ ies = IEs + _BEACON_IE_OFFSET_;
+ ies_len = IELength - _BEACON_IE_OFFSET_;
+
+ p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
+
+ while (p2p_ie) {
+ find_p2p = true;
+ /* Get Notice of Absence IE. */
+ if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen)) {
+ find_p2p_ps = true;
+ noa_index = noa_attr[0];
+
+ if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
+ (noa_index != pwdinfo->noa_index)) { /* if index change, driver should reconfigure related setting. */
+ pwdinfo->noa_index = noa_index;
+ pwdinfo->opp_ps = noa_attr[1] >> 7;
+ pwdinfo->ctwindow = noa_attr[1] & 0x7F;
+
+ noa_offset = 2;
+ noa_num = 0;
+ /* NoA length should be n*(13) + 2 */
+ if (attr_contentlen > 2) {
+ while (noa_offset < attr_contentlen) {
+ /* memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
+ pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
+ noa_offset += 1;
+
+ memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
+ noa_offset += 4;
+
+ memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
+ noa_offset += 4;
+
+ memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
+ noa_offset += 4;
+
+ noa_num++;
+ }
+ }
+ pwdinfo->noa_num = noa_num;
+
+ if (pwdinfo->opp_ps == 1) {
+ pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
+ /* driver should wait LPS for entering CTWindow */
+ if (padapter->pwrctrlpriv.bFwCurrentInPSMode)
+ p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
+ } else if (pwdinfo->noa_num > 0) {
+ pwdinfo->p2p_ps_mode = P2P_PS_NOA;
+ p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
+ } else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
+ p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
+ }
+ }
+
+ break; /* find target, just break. */
+ }
+
+ /* Get the next P2P IE */
+ p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
+ }
+
+ if (find_p2p) {
+ if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && !find_p2p_ps)
+ p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
+ }
+
+}
+
+void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ /* Pre action for p2p state */
+ switch (p2p_ps_state) {
+ case P2P_PS_DISABLE:
+ pwdinfo->p2p_ps_state = p2p_ps_state;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
+
+ pwdinfo->noa_index = 0;
+ pwdinfo->ctwindow = 0;
+ pwdinfo->opp_ps = 0;
+ pwdinfo->noa_num = 0;
+ pwdinfo->p2p_ps_mode = P2P_PS_NONE;
+ if (padapter->pwrctrlpriv.bFwCurrentInPSMode) {
+ if (pwrpriv->smart_ps == 0) {
+ pwrpriv->smart_ps = 2;
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&padapter->pwrctrlpriv.pwr_mode));
+ }
+ }
+ break;
+ case P2P_PS_ENABLE:
+ if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
+ pwdinfo->p2p_ps_state = p2p_ps_state;
+
+ if (pwdinfo->ctwindow > 0) {
+ if (pwrpriv->smart_ps != 0) {
+ pwrpriv->smart_ps = 0;
+ DBG_88E("%s(): Enter CTW, change SmartPS\n", __func__);
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&padapter->pwrctrlpriv.pwr_mode));
+ }
+ }
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
+ }
+ break;
+ case P2P_PS_SCAN:
+ case P2P_PS_SCAN_DONE:
+ case P2P_PS_ALLSTASLEEP:
+ if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
+ pwdinfo->p2p_ps_state = p2p_ps_state;
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
+ }
+ break;
+ default:
+ break;
+ }
+
+}
+
+u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return res;
+
+ if (enqueue) {
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
+ pdrvextra_cmd_parm->type_size = p2p_ps_state;
+ pdrvextra_cmd_parm->pbuf = NULL;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+ } else {
+ p2p_ps_wk_hdl(padapter, p2p_ps_state);
+ }
+
+exit:
+
+ return res;
+}
+
+static void reset_ch_sitesurvey_timer_process(struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, pwrctrlpriv.pwr_state_check_timer);
+ struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return;
+
+ DBG_88E("[%s] In\n", __func__);
+ /* Reset the operation channel information */
+ pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
+ pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
+}
+
+static void reset_ch_sitesurvey_timer_process2(struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, pwrctrlpriv.pwr_state_check_timer);
+ struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return;
+
+ DBG_88E("[%s] In\n", __func__);
+ /* Reset the operation channel information */
+ pwdinfo->p2p_info.operation_ch[0] = 0;
+ pwdinfo->p2p_info.scan_op_ch_only = 0;
+}
+
+static void restore_p2p_state_timer_process(struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, wdinfo.restore_p2p_state_timer);
+ struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return;
+
+ p2p_protocol_wk_cmd(adapter, P2P_RESTORE_STATE_WK);
+}
+
+static void pre_tx_scan_timer_process(struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, wdinfo.pre_tx_scan_timer);
+ struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return;
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
+ if (pwdinfo->tx_prov_disc_info.benable) { /* the provision discovery request frame is trigger to send or not */
+ p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
+ /* issue_probereq_p2p(adapter, NULL); */
+ /* _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); */
+ }
+ } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
+ if (pwdinfo->nego_req_info.benable)
+ p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
+ } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
+ if (pwdinfo->invitereq_info.benable)
+ p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
+ } else {
+ DBG_88E("[%s] p2p_state is %d, ignore!!\n", __func__, rtw_p2p_state(pwdinfo));
+ }
+
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+static void find_phase_timer_process(struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, wdinfo.find_phase_timer);
+ struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return;
+
+ adapter->wdinfo.find_phase_state_exchange_cnt++;
+
+ p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK);
+}
+
+void reset_global_wifidirect_info(struct adapter *padapter)
+{
+ struct wifidirect_info *pwdinfo;
+
+ pwdinfo = &padapter->wdinfo;
+ pwdinfo->persistent_supported = 0;
+ pwdinfo->session_available = true;
+ pwdinfo->wfd_tdls_enable = 0;
+ pwdinfo->wfd_tdls_weaksec = 0;
+}
+
+void rtw_init_wifidirect_timers(struct adapter *padapter)
+{
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ timer_setup(&pwdinfo->find_phase_timer, find_phase_timer_process, 0);
+ timer_setup(&pwdinfo->restore_p2p_state_timer, restore_p2p_state_timer_process, 0);
+ timer_setup(&pwdinfo->pre_tx_scan_timer, pre_tx_scan_timer_process, 0);
+ timer_setup(&pwdinfo->reset_ch_sitesurvey, reset_ch_sitesurvey_timer_process, 0);
+ timer_setup(&pwdinfo->reset_ch_sitesurvey2, reset_ch_sitesurvey_timer_process2, 0);
+}
+
+void rtw_init_wifidirect_addrs(struct adapter *padapter, u8 *dev_addr, u8 *iface_addr)
+{
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ /*init device&interface address */
+ if (dev_addr)
+ memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
+ if (iface_addr)
+ memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
+#endif
+}
+
+void init_wifidirect_info(struct adapter *padapter, enum P2P_ROLE role)
+{
+ struct wifidirect_info *pwdinfo;
+
+ pwdinfo = &padapter->wdinfo;
+ pwdinfo->padapter = padapter;
+
+ /* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */
+ pwdinfo->social_chan[0] = 1;
+ pwdinfo->social_chan[1] = 6;
+ pwdinfo->social_chan[2] = 11;
+ pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */
+
+ /* Use the channel 11 as the listen channel */
+ pwdinfo->listen_channel = 11;
+
+ if (role == P2P_ROLE_DEVICE) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+ pwdinfo->intent = 1;
+ rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
+ } else if (role == P2P_ROLE_CLIENT) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ pwdinfo->intent = 1;
+ rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ } else if (role == P2P_ROLE_GO) {
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ pwdinfo->intent = 15;
+ rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+ }
+
+/* Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
+ pwdinfo->support_rate[0] = 0x8c; /* 6(B) */
+ pwdinfo->support_rate[1] = 0x92; /* 9(B) */
+ pwdinfo->support_rate[2] = 0x18; /* 12 */
+ pwdinfo->support_rate[3] = 0x24; /* 18 */
+ pwdinfo->support_rate[4] = 0x30; /* 24 */
+ pwdinfo->support_rate[5] = 0x48; /* 36 */
+ pwdinfo->support_rate[6] = 0x60; /* 48 */
+ pwdinfo->support_rate[7] = 0x6c; /* 54 */
+
+ memcpy(pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
+
+ memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
+ pwdinfo->device_name_len = 0;
+
+ memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
+ pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */
+
+ memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
+ pwdinfo->inviteresp_info.token = 0;
+
+ pwdinfo->profileindex = 0;
+ memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
+
+ rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
+
+ pwdinfo->listen_dwell = (u8)((jiffies % 3) + 1);
+
+ memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
+
+ memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
+
+ pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
+ pwdinfo->negotiation_dialog_token = 1;
+
+ memset(pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN);
+ pwdinfo->nego_ssidlen = 0;
+
+ pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
+ pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
+ pwdinfo->channel_list_attr_len = 0;
+ memset(pwdinfo->channel_list_attr, 0x00, 100);
+
+ memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
+ memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
+ memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
+ pwdinfo->wfd_tdls_enable = 0;
+ memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
+ memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
+
+ pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
+ pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
+ pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
+ pwdinfo->p2p_info.operation_ch[0] = 0;
+ pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
+ pwdinfo->p2p_info.scan_op_ch_only = 0;
+}
+
+int rtw_p2p_enable(struct adapter *padapter, enum P2P_ROLE role)
+{
+ int ret = _SUCCESS;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {
+ /* leave IPS/Autosuspend */
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* Added by Albert 2011/03/22 */
+ /* In the P2P mode, the driver should not support the b mode. */
+ /* So, the Tx packet shouldn't use the CCK rate */
+ update_tx_basic_rate(padapter, (WIRELESS_11G | WIRELESS_11_24N));
+
+ /* Enable P2P function */
+ init_wifidirect_info(padapter, role);
+
+ rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, true);
+ } else if (role == P2P_ROLE_DISABLE) {
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* Disable P2P function */
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+ _cancel_timer_ex(&pwdinfo->find_phase_timer);
+ _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+ _cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);
+ _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
+ _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey2);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
+ rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
+ memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
+ }
+
+ rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, false);
+
+ /* Restore to initial setting. */
+ update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
+ }
+
+exit:
+ return ret;
+}
+
+#else
+u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue)
+{
+ return _FAIL;
+}
+
+void process_p2p_ps_ie(struct adapter *padapter, u8 *IEs, u32 IELength)
+{
+}
+
+#endif /* CONFIG_88EU_P2P */
diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/r8188eu/core/rtw_pwrctrl.c
index cbb34b920ab9..c3897b29121c 100644
--- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
+++ b/drivers/staging/r8188eu/core/rtw_pwrctrl.c
@@ -1,107 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTW_PWRCTRL_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <osdep_intf.h>
-#include <usb_ops_linux.h>
-#include <linux/usb.h>
-
-static int rtw_hw_suspend(struct adapter *padapter)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- struct net_device *pnetdev = padapter->pnetdev;
-
- if ((!padapter->bup) || (padapter->bDriverStopped) ||
- (padapter->bSurpriseRemoved))
- goto error_exit;
-
- /* system suspend */
- LeaveAllPowerSaveMode(padapter);
-
- mutex_lock(&pwrpriv->mutex_lock);
- pwrpriv->bips_processing = true;
- /* s1. */
- if (pnetdev) {
- netif_carrier_off(pnetdev);
- netif_tx_stop_all_queues(pnetdev);
- }
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
- /* s2. */
- rtw_disassoc_cmd(padapter, 500, false);
-
- /* s2-2. indicate disconnect to os */
- {
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- _clr_fwstate_(pmlmepriv, _FW_LINKED);
-
- led_control_8188eu(padapter, LED_CTL_NO_LINK);
-
- rtw_os_indicate_disconnect(padapter);
-
- /* donnot enqueue cmd */
- rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0);
- }
- }
- /* s2-3. */
- rtw_free_assoc_resources(padapter);
-
- /* s2-4. */
- rtw_free_network_queue(padapter, true);
- rtw_ips_dev_unload(padapter);
- pwrpriv->rf_pwrstate = rf_off;
- pwrpriv->bips_processing = false;
-
- mutex_unlock(&pwrpriv->mutex_lock);
-
- return 0;
-
-error_exit:
- return -1;
-}
-
-static int rtw_hw_resume(struct adapter *padapter)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- struct net_device *pnetdev = padapter->pnetdev;
-
- /* system resume */
- mutex_lock(&pwrpriv->mutex_lock);
- pwrpriv->bips_processing = true;
- rtw_reset_drv_sw(padapter);
-
- if (ips_netdrv_open(netdev_priv(pnetdev)) != _SUCCESS) {
- mutex_unlock(&pwrpriv->mutex_lock);
- goto error_exit;
- }
-
- netif_device_attach(pnetdev);
- netif_carrier_on(pnetdev);
-
- if (!netif_queue_stopped(pnetdev))
- netif_start_queue(pnetdev);
- else
- netif_wake_queue(pnetdev);
-
- pwrpriv->bkeepfwalive = false;
- pwrpriv->brfoffbyhw = false;
-
- pwrpriv->rf_pwrstate = rf_on;
- pwrpriv->bips_processing = false;
+#define _RTW_PWRCTRL_C_
- mutex_unlock(&pwrpriv->mutex_lock);
-
- return 0;
-error_exit:
- return -1;
-}
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/osdep_intf.h"
+#include "../include/linux/usb.h"
void ips_enter(struct adapter *padapter)
{
@@ -112,10 +17,14 @@ void ips_enter(struct adapter *padapter)
return;
if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
- pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF)
+ pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
+ DBG_88E_LEVEL(_drv_info_, "There are some pkts to transmit\n");
+ DBG_88E_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
+ pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
return;
+ }
- mutex_lock(&pwrpriv->mutex_lock);
+ _enter_pwrlock(&pwrpriv->lock);
pwrpriv->bips_processing = true;
@@ -123,8 +32,10 @@ void ips_enter(struct adapter *padapter)
pwrpriv->ips_mode = pwrpriv->ips_mode_req;
pwrpriv->ips_enter_cnts++;
+ DBG_88E("==>ips_enter cnts:%d\n", pwrpriv->ips_enter_cnts);
if (rf_off == pwrpriv->change_rfpwrstate) {
pwrpriv->bpower_saving = true;
+ DBG_88E_LEVEL(_drv_info_, "nolinked power save enter\n");
if (pwrpriv->ips_mode == IPS_LEVEL_2)
pwrpriv->bkeepfwalive = true;
@@ -134,7 +45,7 @@ void ips_enter(struct adapter *padapter)
}
pwrpriv->bips_processing = false;
- mutex_unlock(&pwrpriv->mutex_lock);
+ _exit_pwrlock(&pwrpriv->lock);
}
int ips_leave(struct adapter *padapter)
@@ -145,18 +56,22 @@ int ips_leave(struct adapter *padapter)
int result = _SUCCESS;
int keyid;
- mutex_lock(&pwrpriv->mutex_lock);
+ _enter_pwrlock(&pwrpriv->lock);
if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) {
pwrpriv->bips_processing = true;
pwrpriv->change_rfpwrstate = rf_on;
pwrpriv->ips_leave_cnts++;
+ DBG_88E("==>ips_leave cnts:%d\n", pwrpriv->ips_leave_cnts);
result = rtw_ips_pwr_up(padapter);
- if (result == _SUCCESS)
+ if (result == _SUCCESS) {
pwrpriv->rf_pwrstate = rf_on;
+ }
+ DBG_88E_LEVEL(_drv_info_, "nolinked power save leave\n");
- if ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_)) {
+ if ((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) || (_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm)) {
+ DBG_88E("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing);
set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
for (keyid = 0; keyid < 4; keyid++) {
if (pmlmepriv->key_mask & BIT(keyid)) {
@@ -168,36 +83,71 @@ int ips_leave(struct adapter *padapter)
}
}
+ DBG_88E("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
pwrpriv->bips_processing = false;
pwrpriv->bkeepfwalive = false;
pwrpriv->bpower_saving = false;
}
- mutex_unlock(&pwrpriv->mutex_lock);
+ _exit_pwrlock(&pwrpriv->lock);
return result;
}
static bool rtw_pwr_unassociated_idle(struct adapter *adapter)
{
+ struct adapter *buddy = adapter->pbuddy_adapter;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+#endif
- if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies))
- return false;
+ bool ret = false;
+
+ if (adapter->pwrctrlpriv.ips_deny_time >= jiffies)
+ goto exit;
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_SITE_MONITOR) ||
check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS) ||
+ check_fwstate(pmlmepriv, WIFI_UNDER_WPS) ||
check_fwstate(pmlmepriv, WIFI_AP_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
- return false;
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE) ||
+#if defined(CONFIG_88EU_P2P)
+ !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+#else
+ 0)
+#endif
+ goto exit;
- return true;
+ /* consider buddy, if exist */
+ if (buddy) {
+ struct mlme_priv *b_pmlmepriv = &buddy->mlmepriv;
+ #ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *b_pwdinfo = &buddy->wdinfo;
+ #endif
+
+ if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE | WIFI_SITE_MONITOR) ||
+ check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS) ||
+ check_fwstate(b_pmlmepriv, WIFI_AP_STATE) ||
+ check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE) ||
+#if defined(CONFIG_88EU_P2P)
+ !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE))
+#else
+ 0)
+#endif
+ goto exit;
+ }
+ ret = true;
+
+exit:
+ return ret;
}
void rtw_ps_processor(struct adapter *padapter)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
enum rt_rf_power_state rfpwrstate;
pwrpriv->ps_processing = true;
@@ -207,16 +157,19 @@ void rtw_ps_processor(struct adapter *padapter)
if (padapter->pwrctrlpriv.bHWPwrPindetect) {
rfpwrstate = RfOnOffDetect(padapter);
+ DBG_88E("@@@@- #2 %s==> rfstate:%s\n", __func__, (rfpwrstate == rf_on) ? "rf_on" : "rf_off");
if (rfpwrstate != pwrpriv->rf_pwrstate) {
if (rfpwrstate == rf_off) {
pwrpriv->change_rfpwrstate = rf_off;
pwrpriv->brfoffbyhw = true;
+ padapter->bCardDisableWOHSM = true;
rtw_hw_suspend(padapter);
} else {
pwrpriv->change_rfpwrstate = rf_on;
rtw_hw_resume(padapter);
}
+ DBG_88E("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off) ? "rf_off" : "rf_on");
}
pwrpriv->pwr_state_check_cnts++;
}
@@ -228,6 +181,7 @@ void rtw_ps_processor(struct adapter *padapter)
goto exit;
if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts % 4) == 0)) {
+ DBG_88E("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv));
pwrpriv->change_rfpwrstate = rf_off;
ips_enter(padapter);
@@ -242,7 +196,6 @@ static void pwr_state_check_handler(struct timer_list *t)
struct adapter *padapter =
from_timer(padapter, t,
pwrctrlpriv.pwr_state_check_timer);
-
rtw_ps_cmd(padapter);
}
@@ -255,7 +208,7 @@ static void pwr_state_check_handler(struct timer_list *t)
*/
void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
{
- u8 rpwm;
+ u8 rpwm;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
pslv = PS_STATE(pslv);
@@ -288,13 +241,14 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
pwrpriv->tog += 0x80;
pwrpriv->cpwm = pslv;
+
}
static u8 PS_RDY_CHECK(struct adapter *padapter)
{
- unsigned long curr_time, delta_time;
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u32 curr_time, delta_time;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
curr_time = jiffies;
delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp;
@@ -302,29 +256,33 @@ static u8 PS_RDY_CHECK(struct adapter *padapter)
if (delta_time < LPS_DELAY_TIME)
return false;
- if ((!check_fwstate(pmlmepriv, _FW_LINKED)) ||
- (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) ||
- (check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
+ if (!check_fwstate(pmlmepriv, _FW_LINKED) ||
+ check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) ||
+ check_fwstate(pmlmepriv, WIFI_AP_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
return false;
if (pwrpriv->bInSuspend)
return false;
- if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X &&
- !padapter->securitypriv.binstallGrpkey)
+ if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && !padapter->securitypriv.binstallGrpkey) {
+ DBG_88E("Group handshake still in progress !!!\n");
return false;
+ }
return true;
}
void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
if (ps_mode > PM_Card_Disable)
return;
if (pwrpriv->pwr_mode == ps_mode) {
- if (ps_mode == PS_MODE_ACTIVE)
+ if (PS_MODE_ACTIVE == ps_mode)
return;
if ((pwrpriv->smart_ps == smart_ps) &&
@@ -334,15 +292,34 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a
/* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
if (ps_mode == PS_MODE_ACTIVE) {
+#ifdef CONFIG_88EU_P2P
+ if (pwdinfo->opp_ps == 0) {
+ DBG_88E("rtw_set_ps_mode: Leave 802.11 power save\n");
+ pwrpriv->pwr_mode = ps_mode;
+ rtw_set_rpwm(padapter, PS_STATE_S4);
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
+ pwrpriv->bFwCurrentInPSMode = false;
+ }
+ } else {
+#endif /* CONFIG_88EU_P2P */
if (PS_RDY_CHECK(padapter)) {
+ DBG_88E("%s: Enter 802.11 power save\n", __func__);
pwrpriv->bFwCurrentInPSMode = true;
pwrpriv->pwr_mode = ps_mode;
pwrpriv->smart_ps = smart_ps;
pwrpriv->bcn_ant_mode = bcn_ant_mode;
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
+
+#ifdef CONFIG_88EU_P2P
+ /* Set CTWindow after LPS */
+ if (pwdinfo->opp_ps == 1)
+ p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
+#endif /* CONFIG_88EU_P2P */
+
rtw_set_rpwm(padapter, PS_STATE_S2);
}
}
+
}
/*
@@ -353,7 +330,7 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a
*/
s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
{
- unsigned long start_time;
+ u32 start_time;
u8 bAwake = false;
s32 err = 0;
@@ -365,14 +342,16 @@ s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
if (padapter->bSurpriseRemoved) {
err = -2;
+ DBG_88E("%s: device surprise removed!!\n", __func__);
break;
}
- if (jiffies_to_msecs(jiffies - start_time) > delay_ms) {
+ if (rtw_get_passing_time_ms(start_time) > delay_ms) {
err = -1;
+ DBG_88E("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
break;
}
- msleep(1);
+ rtw_usleep_os(100);
}
return err;
@@ -384,7 +363,7 @@ s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
/* */
void LPS_Enter(struct adapter *padapter)
{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
if (!PS_RDY_CHECK(padapter))
return;
@@ -394,13 +373,16 @@ void LPS_Enter(struct adapter *padapter)
if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */
if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
pwrpriv->bpower_saving = true;
+ DBG_88E("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
/* For Tenda W311R IOT issue */
- rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0);
+ rtw_set_ps_mode(padapter, pwrpriv->power_mgnt,
+ pwrpriv->smart_ps, 0x40);
}
} else {
pwrpriv->LpsIdleCount++;
}
}
+
}
#define LPS_LEAVE_TIMEOUT_MS 100
@@ -409,11 +391,11 @@ void LPS_Enter(struct adapter *padapter)
/* Leave the leisure power save mode. */
void LPS_Leave(struct adapter *padapter)
{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
if (pwrpriv->bLeisurePs) {
if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
- rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0);
+ rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0x40);
if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
@@ -421,6 +403,7 @@ void LPS_Leave(struct adapter *padapter)
}
pwrpriv->bpower_saving = false;
+
}
/* */
@@ -429,17 +412,22 @@ void LPS_Leave(struct adapter *padapter)
/* */
void LeaveAllPowerSaveMode(struct adapter *Adapter)
{
- struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+ u8 enqueue = 0;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */
+ p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
+
+ rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
+ }
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, 0);
}
void rtw_init_pwrctrl_priv(struct adapter *padapter)
{
struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
- mutex_init(&pwrctrlpriv->mutex_lock);
+ _init_pwrlock(&pwrctrlpriv->lock);
pwrctrlpriv->rf_pwrstate = rf_on;
pwrctrlpriv->ips_enter_cnts = 0;
pwrctrlpriv->ips_leave_cnts = 0;
@@ -459,7 +447,7 @@ void rtw_init_pwrctrl_priv(struct adapter *padapter)
pwrctrlpriv->power_mgnt = PS_MODE_ACTIVE;
else
pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/* PS_MODE_MIN; */
- pwrctrlpriv->bLeisurePs = (pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE);
+ pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? true : false;
pwrctrlpriv->bFwCurrentInPSMode = false;
@@ -474,40 +462,68 @@ void rtw_init_pwrctrl_priv(struct adapter *padapter)
pwrctrlpriv->btcoex_rfon = false;
- timer_setup(&pwrctrlpriv->pwr_state_check_timer,
- pwr_state_check_handler, 0);
+ timer_setup(&pwrctrlpriv->pwr_state_check_timer, pwr_state_check_handler, 0);
+}
+
+void rtw_free_pwrctrl_priv(struct adapter *adapter)
+{
+ struct pwrctrl_priv *pwrctrlpriv = &adapter->pwrctrlpriv;
+
+ _free_pwrlock(&pwrctrlpriv->lock);
+
+}
+
+u8 rtw_interface_ps_func(struct adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val)
+{
+ u8 bResult = true;
+ rtw_hal_intf_ps_func(padapter, efunc_id, val);
+
+ return bResult;
+}
+
+inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ms);
}
/*
- * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
- * @adapter: pointer to struct adapter structure
- * @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup
- * Return _SUCCESS or _FAIL
- */
+* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
+* @adapter: pointer to struct adapter structure
+* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
+* Return _SUCCESS or _FAIL
+*/
int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- unsigned long expires;
- unsigned long start;
int ret = _SUCCESS;
+ u32 start = jiffies;
- expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
- if (time_before(pwrpriv->ips_deny_time, expires))
- pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
+ if (pwrpriv->ips_deny_time < jiffies + rtw_ms_to_systime(ips_deffer_ms))
+ pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
- start = jiffies;
if (pwrpriv->ps_processing) {
- while (pwrpriv->ps_processing &&
- jiffies_to_msecs(jiffies - start) <= 3000)
- udelay(1500);
+ DBG_88E("%s wait ps_processing...\n", __func__);
+ while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
+ msleep(10);
+ if (pwrpriv->ps_processing)
+ DBG_88E("%s wait ps_processing timeout\n", __func__);
+ else
+ DBG_88E("%s wait ps_processing done\n", __func__);
}
/* System suspend is not allowed to wakeup */
- if ((!pwrpriv->bInternalAutoSuspend) && (pwrpriv->bInSuspend)) {
- ret = _FAIL;
- goto exit;
+ if ((!pwrpriv->bInternalAutoSuspend) && pwrpriv->bInSuspend) {
+ while (pwrpriv->bInSuspend &&
+ (rtw_get_passing_time_ms(start) <= 3000 ||
+ (rtw_get_passing_time_ms(start) <= 500)))
+ msleep(10);
+ if (pwrpriv->bInSuspend)
+ DBG_88E("%s wait bInSuspend timeout\n", __func__);
+ else
+ DBG_88E("%s wait bInSuspend done\n", __func__);
}
/* block??? */
@@ -522,7 +538,9 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal
goto exit;
}
if (rf_off == pwrpriv->rf_pwrstate) {
- if (ips_leave(padapter) == _FAIL) {
+ DBG_88E("%s call ips_leave....\n", __func__);
+ if (_FAIL == ips_leave(padapter)) {
+ DBG_88E("======> ips_leave fail.............\n");
ret = _FAIL;
goto exit;
}
@@ -531,30 +549,34 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal
/* TODO: the following checking need to be merged... */
if (padapter->bDriverStopped || !padapter->bup ||
!padapter->hw_init_completed) {
+ DBG_88E("%s: bDriverStopped=%d, bup=%d, hw_init_completed =%u\n"
+ , caller
+ , padapter->bDriverStopped
+ , padapter->bup
+ , padapter->hw_init_completed);
ret = false;
goto exit;
}
exit:
- expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
- if (time_before(pwrpriv->ips_deny_time, expires))
- pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
+ if (pwrpriv->ips_deny_time < jiffies + rtw_ms_to_systime(ips_deffer_ms))
+ pwrpriv->ips_deny_time = jiffies + rtw_ms_to_systime(ips_deffer_ms);
return ret;
}
int rtw_pm_set_lps(struct adapter *padapter, u8 mode)
{
- int ret = 0;
+ int ret = 0;
struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
if (mode < PS_MODE_NUM) {
if (pwrctrlpriv->power_mgnt != mode) {
- if (mode == PS_MODE_ACTIVE)
+ if (PS_MODE_ACTIVE == mode)
LeaveAllPowerSaveMode(padapter);
else
pwrctrlpriv->LpsIdleCount = 2;
pwrctrlpriv->power_mgnt = mode;
- pwrctrlpriv->bLeisurePs = (pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE);
+ pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? true : false;
}
} else {
ret = -EINVAL;
@@ -569,10 +591,12 @@ int rtw_pm_set_ips(struct adapter *padapter, u8 mode)
if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
rtw_ips_mode_req(pwrctrlpriv, mode);
+ DBG_88E("%s %s\n", __func__, mode == IPS_NORMAL ? "IPS_NORMAL" : "IPS_LEVEL_2");
return 0;
} else if (mode == IPS_NONE) {
rtw_ips_mode_req(pwrctrlpriv, mode);
- if ((padapter->bSurpriseRemoved == 0) && (rtw_pwr_wakeup(padapter) == _FAIL))
+ DBG_88E("%s %s\n", __func__, "IPS_NONE");
+ if ((padapter->bSurpriseRemoved == 0) && (_FAIL == rtw_pwr_wakeup(padapter)))
return -EFAULT;
} else {
return -EINVAL;
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/r8188eu/core/rtw_recv.c
index ff2ef36604e1..e082edfbaad8 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/r8188eu/core/rtw_recv.c
@@ -1,38 +1,38 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTW_RECV_C_
-
-#include <linux/ieee80211.h>
-#include <linux/if_ether.h>
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <mlme_osdep.h>
-#include <mon.h>
-#include <wifi.h>
-#include <linux/vmalloc.h>
-#include <linux/etherdevice.h>
-#include <net/cfg80211.h>
+#define _RTW_RECV_C_
-#define LLC_HEADER_SIZE 6 /* LLC Header Length */
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/mlme_osdep.h"
+#include "../include/usb_ops.h"
+#include "../include/wifi.h"
static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
-static void rtw_signal_stat_timer_hdl(struct timer_list *t);
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static u8 rtw_bridge_tunnel_header[] = {
+ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8
+};
+
+static u8 rtw_rfc1042_header[] = {
+ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
+};
+
+void rtw_signal_stat_timer_hdl(struct timer_list *);
void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
{
+
memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));
spin_lock_init(&psta_recvpriv->lock);
_rtw_init_queue(&psta_recvpriv->defrag_q);
+
}
int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
@@ -43,38 +43,52 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
int res = _SUCCESS;
+ spin_lock_init(&precvpriv->lock);
+
_rtw_init_queue(&precvpriv->free_recv_queue);
_rtw_init_queue(&precvpriv->recv_pending_queue);
_rtw_init_queue(&precvpriv->uc_swdec_pending_queue);
precvpriv->adapter = padapter;
+ precvpriv->free_recvframe_cnt = NR_RECVFRAME;
+
+ rtw_os_recv_resource_init(precvpriv, padapter);
+
precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(struct recv_frame) + RXFRAME_ALIGN_SZ);
- if (!precvpriv->pallocated_frame_buf)
- return _FAIL;
+ if (!precvpriv->pallocated_frame_buf) {
+ res = _FAIL;
+ goto exit;
+ }
- precvframe = PTR_ALIGN(precvpriv->pallocated_frame_buf, RXFRAME_ALIGN_SZ);
+ precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ);
+
+ precvframe = (struct recv_frame *)precvpriv->precv_frame_buf;
for (i = 0; i < NR_RECVFRAME; i++) {
INIT_LIST_HEAD(&precvframe->list);
- list_add_tail(&precvframe->list,
- &precvpriv->free_recv_queue.queue);
+ list_add_tail(&precvframe->list, &precvpriv->free_recv_queue.queue);
- precvframe->pkt = NULL;
+ res = rtw_os_recv_resource_alloc(padapter, precvframe);
+
+ precvframe->len = 0;
precvframe->adapter = padapter;
precvframe++;
}
- res = rtw_hal_init_recv_priv(padapter);
+ precvpriv->rx_pending_cnt = 1;
- timer_setup(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl,
- 0);
+ sema_init(&precvpriv->allrxreturnevt, 0);
+ res = rtw_hal_init_recv_priv(padapter);
+
+ timer_setup(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl, 0);
precvpriv->signal_stat_sampling_interval = 1000; /* ms */
rtw_set_signal_stat_timer(precvpriv);
+exit:
return res;
}
@@ -85,6 +99,8 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv)
rtw_free_uc_swdec_pending_queue(padapter);
+ rtw_os_recv_resource_free(precvpriv);
+
vfree(precvpriv->pallocated_frame_buf);
rtw_hal_free_recv_priv(padapter);
@@ -93,13 +109,29 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv)
struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
{
struct recv_frame *hdr;
+ struct list_head *plist, *phead;
+ struct adapter *padapter;
+ struct recv_priv *precvpriv;
+
+ if (list_empty(&pfree_recv_queue->queue)) {
+ hdr = NULL;
+ } else {
+ phead = get_list_head(pfree_recv_queue);
+
+ plist = phead->next;
+
+ hdr = container_of(plist, struct recv_frame, list);
- hdr = list_first_entry_or_null(&pfree_recv_queue->queue,
- struct recv_frame, list);
- if (hdr)
list_del_init(&hdr->list);
+ padapter = hdr->adapter;
+ if (padapter) {
+ precvpriv = &padapter->recvpriv;
+ if (pfree_recv_queue == &precvpriv->free_recv_queue)
+ precvpriv->free_recvframe_cnt--;
+ }
+ }
- return hdr;
+ return (struct recv_frame *)hdr;
}
struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
@@ -115,11 +147,23 @@ struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
return precvframe;
}
-void rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_recv_queue)
+void rtw_init_recvframe(struct recv_frame *precvframe, struct recv_priv *precvpriv)
{
- if (!precvframe)
- return;
+ /* Perry: This can be removed */
+ INIT_LIST_HEAD(&precvframe->list);
+ precvframe->len = 0;
+}
+
+int rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_recv_queue)
+{
+ struct adapter *padapter;
+ struct recv_priv *precvpriv;
+
+ if (!precvframe)
+ return _FAIL;
+ padapter = precvframe->adapter;
+ precvpriv = &padapter->recvpriv;
if (precvframe->pkt) {
dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */
precvframe->pkt = NULL;
@@ -129,16 +173,33 @@ void rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_rec
list_del_init(&precvframe->list);
+ precvframe->len = 0;
+
list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue));
+ if (padapter) {
+ if (pfree_recv_queue == &precvpriv->free_recv_queue)
+ precvpriv->free_recvframe_cnt++;
+ }
+
spin_unlock_bh(&pfree_recv_queue->lock);
+
+ return _SUCCESS;
}
int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue)
{
+ struct adapter *padapter = precvframe->adapter;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
list_del_init(&precvframe->list);
list_add_tail(&precvframe->list, get_list_head(queue));
+ if (padapter) {
+ if (queue == &precvpriv->free_recv_queue)
+ precvpriv->free_recvframe_cnt++;
+ }
+
return _SUCCESS;
}
@@ -154,12 +215,12 @@ int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue)
}
/*
- * caller : defrag ; recvframe_chk_defrag in recv_thread (passive)
- * pframequeue: defrag_queue : will be accessed in recv_thread (passive)
- *
- * using spinlock to protect
- *
- */
+caller : defrag ; recvframe_chk_defrag in recv_thread (passive)
+pframequeue: defrag_queue : will be accessed in recv_thread (passive)
+
+using spinlock to protect
+
+*/
void rtw_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue)
{
@@ -172,31 +233,81 @@ void rtw_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfre
plist = phead->next;
while (phead != plist) {
- hdr = list_entry(plist, struct recv_frame, list);
+ hdr = container_of(plist, struct recv_frame, list);
plist = plist->next;
- rtw_free_recvframe(hdr, pfree_recv_queue);
+ rtw_free_recvframe((struct recv_frame *)hdr, pfree_recv_queue);
}
spin_unlock(&pframequeue->lock);
+
}
u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter)
{
u32 cnt = 0;
struct recv_frame *pending_frame;
-
while ((pending_frame = rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) {
rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue);
+ DBG_88E("%s: dequeue uc_swdec_pending_queue\n", __func__);
cnt++;
}
return cnt;
}
-static int recvframe_chkmic(struct adapter *adapter,
- struct recv_frame *precvframe)
+int rtw_enqueue_recvbuf_to_head(struct recv_buf *precvbuf, struct __queue *queue)
+{
+ spin_lock_bh(&queue->lock);
+
+ list_del_init(&precvbuf->list);
+ list_add(&precvbuf->list, get_list_head(queue));
+
+ spin_unlock_bh(&queue->lock);
+
+ return _SUCCESS;
+}
+
+int rtw_enqueue_recvbuf(struct recv_buf *precvbuf, struct __queue *queue)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->lock, flags);
+
+ list_del_init(&precvbuf->list);
+
+ list_add_tail(&precvbuf->list, get_list_head(queue));
+ spin_unlock_irqrestore(&queue->lock, flags);
+ return _SUCCESS;
+}
+
+struct recv_buf *rtw_dequeue_recvbuf(struct __queue *queue)
+{
+ struct recv_buf *precvbuf;
+ struct list_head *plist, *phead;
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->lock, flags);
+
+ if (list_empty(&queue->queue)) {
+ precvbuf = NULL;
+ } else {
+ phead = get_list_head(queue);
+
+ plist = phead->next;
+
+ precvbuf = container_of(plist, struct recv_buf, list);
+
+ list_del_init(&precvbuf->list);
+ }
+
+ spin_unlock_irqrestore(&queue->lock, flags);
+
+ return precvbuf;
+}
+
+static int recvframe_chkmic(struct adapter *adapter, struct recv_frame *precvframe)
{
int i, res = _SUCCESS;
u32 datalen;
@@ -217,19 +328,19 @@ static int recvframe_chkmic(struct adapter *adapter,
/* calculate mic code */
if (stainfo) {
if (is_multicast_ether_addr(prxattrib->ra)) {
+ mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
+
if (!psecuritypriv) {
res = _FAIL;
+ DBG_88E("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n");
goto exit;
}
- mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
} else {
mickey = &stainfo->dot11tkiprxmickey.skey[0];
}
- /* icv_len included the mic code */
- datalen = precvframe->pkt->len - prxattrib->hdrlen -
- prxattrib->iv_len - prxattrib->icv_len - 8;
- pframe = precvframe->pkt->data;
+ datalen = precvframe->len - prxattrib->hdrlen - prxattrib->iv_len - prxattrib->icv_len - 8;/* icv_len included the mic code */
+ pframe = precvframe->rx_data;
payload = pframe + prxattrib->hdrlen + prxattrib->iv_len;
rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0],
@@ -250,18 +361,21 @@ static int recvframe_chkmic(struct adapter *adapter,
if (is_multicast_ether_addr(prxattrib->ra) && prxattrib->key_index != pmlmeinfo->key_index)
brpt_micerror = false;
- if ((prxattrib->bdecrypted) && (brpt_micerror))
+ if ((prxattrib->bdecrypted) && (brpt_micerror)) {
rtw_handle_tkip_mic_err(adapter, (u8)is_multicast_ether_addr(prxattrib->ra));
+ DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted);
+ } else {
+ DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted);
+ }
res = _FAIL;
} else {
/* mic checked ok */
- if (!psecuritypriv->bcheck_grpkey &&
- is_multicast_ether_addr(prxattrib->ra))
+ if (!psecuritypriv->bcheck_grpkey && is_multicast_ether_addr(prxattrib->ra))
psecuritypriv->bcheck_grpkey = true;
}
}
- skb_trim(precvframe->pkt, precvframe->pkt->len - 8);
+ recvframe_pull_tail(precvframe, 8);
}
exit:
@@ -270,8 +384,7 @@ exit:
}
/* decrypt and set the ivlen, icvlen of the recv_frame */
-static struct recv_frame *decryptor(struct adapter *padapter,
- struct recv_frame *precv_frame)
+static struct recv_frame *decryptor(struct adapter *padapter, struct recv_frame *precv_frame)
{
struct rx_pkt_attrib *prxattrib = &precv_frame->attrib;
struct security_priv *psecuritypriv = &padapter->securitypriv;
@@ -279,11 +392,12 @@ static struct recv_frame *decryptor(struct adapter *padapter,
u32 res = _SUCCESS;
if (prxattrib->encrypt > 0) {
- u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen;
-
+ u8 *iv = precv_frame->rx_data + prxattrib->hdrlen;
prxattrib->key_index = (((iv[3]) >> 6) & 0x3);
if (prxattrib->key_index > WEP_KEYS) {
+ DBG_88E("prxattrib->key_index(%d)>WEP_KEYS\n", prxattrib->key_index);
+
switch (prxattrib->encrypt) {
case _WEP40_:
case _WEP104_:
@@ -298,19 +412,19 @@ static struct recv_frame *decryptor(struct adapter *padapter,
}
}
- if ((prxattrib->encrypt > 0) && (prxattrib->bdecrypted == 0)) {
+ if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) || (psecuritypriv->sw_decrypt))) {
psecuritypriv->hw_decrypted = false;
switch (prxattrib->encrypt) {
case _WEP40_:
case _WEP104_:
- res = rtw_wep_decrypt(padapter, precv_frame);
+ rtw_wep_decrypt(padapter, (u8 *)precv_frame);
break;
case _TKIP_:
- res = rtw_tkip_decrypt(padapter, precv_frame);
+ res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame);
break;
case _AES_:
- res = rtw_aes_decrypt(padapter, precv_frame);
+ res = rtw_aes_decrypt(padapter, (u8 *)precv_frame);
break;
default:
break;
@@ -322,14 +436,15 @@ static struct recv_frame *decryptor(struct adapter *padapter,
if (res == _FAIL) {
rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);
return_packet = NULL;
+ } else {
+ prxattrib->bdecrypted = true;
}
return return_packet;
}
/* set the security information in the recv_frame */
-static struct recv_frame *portctrl(struct adapter *adapter,
- struct recv_frame *precv_frame)
+static struct recv_frame *portctrl(struct adapter *adapter, struct recv_frame *precv_frame)
{
u8 *psta_addr, *ptr;
uint auth_alg;
@@ -337,7 +452,7 @@ static struct recv_frame *portctrl(struct adapter *adapter,
struct sta_info *psta;
struct sta_priv *pstapriv;
struct recv_frame *prtnframe;
- u16 ether_type;
+ u16 ether_type = 0;
u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */
struct rx_pkt_attrib *pattrib;
__be16 be_tmp;
@@ -346,23 +461,26 @@ static struct recv_frame *portctrl(struct adapter *adapter,
auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
- ptr = precv_frame->pkt->data;
+ ptr = precv_frame->rx_data;
pfhdr = precv_frame;
pattrib = &pfhdr->attrib;
psta_addr = pattrib->ta;
- psta = rtw_get_stainfo(pstapriv, psta_addr);
prtnframe = NULL;
- if (auth_alg == 2) {
- /* get ether_type */
- ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE + pfhdr->attrib.iv_len;
- memcpy(&be_tmp, ptr, 2);
- ether_type = ntohs(be_tmp);
+ psta = rtw_get_stainfo(pstapriv, psta_addr);
- if (psta && (psta->ieee8021x_blocked)) {
+ if (auth_alg == 2) {
+ if (psta && psta->ieee8021x_blocked) {
/* blocked */
/* only accept EAPOL frame */
+ prtnframe = precv_frame;
+
+ /* get ether_type */
+ ptr = ptr + pfhdr->attrib.hdrlen + pfhdr->attrib.iv_len + LLC_HEADER_SIZE;
+ memcpy(&be_tmp, ptr, 2);
+ ether_type = ntohs(be_tmp);
+
if (ether_type == eapol_type) {
prtnframe = precv_frame;
} else {
@@ -374,10 +492,6 @@ static struct recv_frame *portctrl(struct adapter *adapter,
/* allowed */
/* check decryption status, and decrypt the frame if needed */
prtnframe = precv_frame;
- /* check is the EAPOL frame or not (Rekey) */
- if (ether_type == eapol_type)
- /* check Rekey */
- prtnframe = precv_frame;
}
} else {
prtnframe = precv_frame;
@@ -386,8 +500,7 @@ static struct recv_frame *portctrl(struct adapter *adapter,
return prtnframe;
}
-static int recv_decache(struct recv_frame *precv_frame, u8 bretry,
- struct stainfo_rxcache *prxcache)
+static int recv_decache(struct recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache)
{
int tid = precv_frame->attrib.priority;
@@ -397,20 +510,22 @@ static int recv_decache(struct recv_frame *precv_frame, u8 bretry,
if (tid > 15)
return _FAIL;
- if (seq_ctrl == prxcache->tid_rxseq[tid])
- return _FAIL;
+ if (1) {/* if (bretry) */
+ if (seq_ctrl == prxcache->tid_rxseq[tid])
+ return _FAIL;
+ }
prxcache->tid_rxseq[tid] = seq_ctrl;
return _SUCCESS;
}
-static void process_pwrbit_data(struct adapter *padapter,
- struct recv_frame *precv_frame)
+void process_pwrbit_data(struct adapter *padapter, struct recv_frame *precv_frame);
+void process_pwrbit_data(struct adapter *padapter, struct recv_frame *precv_frame)
{
#ifdef CONFIG_88EU_AP_MODE
unsigned char pwrbit;
- u8 *ptr = precv_frame->pkt->data;
+ u8 *ptr = precv_frame->rx_data;
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *psta = NULL;
@@ -432,8 +547,7 @@ static void process_pwrbit_data(struct adapter *padapter,
#endif
}
-static void process_wmmps_data(struct adapter *padapter,
- struct recv_frame *precv_frame)
+static void process_wmmps_data(struct adapter *padapter, struct recv_frame *precv_frame)
{
#ifdef CONFIG_88EU_AP_MODE
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
@@ -488,9 +602,7 @@ static void process_wmmps_data(struct adapter *padapter,
#endif
}
-static void count_rx_stats(struct adapter *padapter,
- struct recv_frame *prframe,
- struct sta_info *sta)
+static void count_rx_stats(struct adapter *padapter, struct recv_frame *prframe, struct sta_info *sta)
{
int sz;
struct sta_info *psta = NULL;
@@ -498,12 +610,12 @@ static void count_rx_stats(struct adapter *padapter,
struct rx_pkt_attrib *pattrib = &prframe->attrib;
struct recv_priv *precvpriv = &padapter->recvpriv;
- sz = prframe->pkt->len;
+ sz = get_recvframe_len(prframe);
precvpriv->rx_bytes += sz;
padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
- if (!is_multicast_ether_addr(pattrib->dst))
+ if (!is_broadcast_ether_addr(pattrib->dst) && !is_multicast_ether_addr(pattrib->dst))
padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;
if (sta)
@@ -519,10 +631,15 @@ static void count_rx_stats(struct adapter *padapter,
}
}
-static int sta2sta_data_frame(struct adapter *adapter,
- struct recv_frame *precv_frame,
- struct sta_info **psta)
+int sta2sta_data_frame(
+ struct adapter *adapter,
+ struct recv_frame *precv_frame,
+ struct sta_info **psta
+);
+
+int sta2sta_data_frame(struct adapter *adapter, struct recv_frame *precv_frame, struct sta_info **psta)
{
+ u8 *ptr = precv_frame->rx_data;
int ret = _SUCCESS;
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
struct sta_priv *pstapriv = &adapter->stapriv;
@@ -530,7 +647,7 @@ static int sta2sta_data_frame(struct adapter *adapter,
u8 *mybssid = get_bssid(pmlmepriv);
u8 *myhwaddr = myid(&adapter->eeprompriv);
u8 *sta_addr = NULL;
- bool mcast = is_multicast_ether_addr(pattrib->dst);
+ bool bmcast = is_multicast_ether_addr(pattrib->dst);
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
@@ -540,13 +657,13 @@ static int sta2sta_data_frame(struct adapter *adapter,
goto exit;
}
- if (memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) {
+ if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
ret = _FAIL;
goto exit;
}
- if (is_zero_ether_addr(pattrib->bssid) ||
- is_zero_ether_addr(mybssid) ||
+ if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+ !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
ret = _FAIL;
goto exit;
@@ -561,11 +678,11 @@ static int sta2sta_data_frame(struct adapter *adapter,
}
sta_addr = pattrib->bssid;
} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- if (mcast) {
+ if (bmcast) {
/* For AP mode, if DA == MCAST, then BSSID should be also MCAST */
if (!is_multicast_ether_addr(pattrib->bssid)) {
- ret = _FAIL;
- goto exit;
+ ret = _FAIL;
+ goto exit;
}
} else { /* not mc-frame */
/* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */
@@ -576,36 +693,50 @@ static int sta2sta_data_frame(struct adapter *adapter,
sta_addr = pattrib->src;
}
+ } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
+ memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
+ memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
+ memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ sta_addr = mybssid;
} else {
ret = _FAIL;
}
- if (mcast)
+ if (bmcast)
*psta = rtw_get_bcmc_stainfo(adapter);
else
*psta = rtw_get_stainfo(pstapriv, sta_addr); /* get ap_info */
if (!*psta) {
+ if (adapter->registrypriv.mp_mode == 1) {
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
+ adapter->mppriv.rx_pktloss++;
+ }
ret = _FAIL;
goto exit;
}
exit:
+
return ret;
}
-static int ap2sta_data_frame(struct adapter *adapter,
- struct recv_frame *precv_frame,
- struct sta_info **psta)
+static int ap2sta_data_frame(
+ struct adapter *adapter,
+ struct recv_frame *precv_frame,
+ struct sta_info **psta)
{
- u8 *ptr = precv_frame->pkt->data;
+ u8 *ptr = precv_frame->rx_data;
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
int ret = _SUCCESS;
struct sta_priv *pstapriv = &adapter->stapriv;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
u8 *mybssid = get_bssid(pmlmepriv);
u8 *myhwaddr = myid(&adapter->eeprompriv);
- bool mcast = is_multicast_ether_addr(pattrib->dst);
+ bool bmcast = is_multicast_ether_addr(pattrib->dst);
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
(check_fwstate(pmlmepriv, _FW_LINKED) ||
@@ -617,23 +748,25 @@ static int ap2sta_data_frame(struct adapter *adapter,
}
/* da should be for me */
- if (memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) {
+ if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
ret = _FAIL;
goto exit;
}
/* check BSSID */
- if (is_zero_ether_addr(pattrib->bssid) ||
- is_zero_ether_addr(mybssid) ||
- (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
- if (!mcast)
+ if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+ !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+ (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
+ if (!bmcast) {
+ DBG_88E("issue_deauth to the nonassociated ap=%pM for the reason(7)\n", (pattrib->bssid));
issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ }
ret = _FAIL;
goto exit;
}
- if (mcast)
+ if (bmcast)
*psta = rtw_get_bcmc_stainfo(adapter);
else
*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get ap_info */
@@ -652,15 +785,34 @@ static int ap2sta_data_frame(struct adapter *adapter,
ret = RTW_RX_HANDLED;
goto exit;
}
+ } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
+ check_fwstate(pmlmepriv, _FW_LINKED)) {
+ memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
+ memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
+ memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ /* */
+ memcpy(pattrib->bssid, mybssid, ETH_ALEN);
+
+ *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */
+ if (!*psta) {
+ ret = _FAIL;
+ goto exit;
+ }
} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
/* Special case */
ret = RTW_RX_HANDLED;
goto exit;
} else {
- if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) {
+ if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && (!bmcast)) {
*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */
- if (!*psta)
+ if (!*psta) {
+ DBG_88E("issue_deauth to the ap =%pM for the reason(7)\n", (pattrib->bssid));
+
issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ }
}
ret = _FAIL;
@@ -678,7 +830,7 @@ static int sta2ap_data_frame(struct adapter *adapter,
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
struct sta_priv *pstapriv = &adapter->stapriv;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- u8 *ptr = precv_frame->pkt->data;
+ u8 *ptr = precv_frame->rx_data;
unsigned char *mybssid = get_bssid(pmlmepriv);
int ret = _SUCCESS;
@@ -691,6 +843,8 @@ static int sta2ap_data_frame(struct adapter *adapter,
*psta = rtw_get_stainfo(pstapriv, pattrib->src);
if (!*psta) {
+ DBG_88E("issue_deauth to sta=%pM for the reason(7)\n", (pattrib->src));
+
issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
ret = RTW_RX_HANDLED;
@@ -699,8 +853,9 @@ static int sta2ap_data_frame(struct adapter *adapter,
process_pwrbit_data(adapter, precv_frame);
- if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE)
+ if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {
process_wmmps_data(adapter, precv_frame);
+ }
if (GetFrameSubType(ptr) & BIT(6)) {
/* No data, will not indicate to upper layer, temporily count it here */
@@ -710,11 +865,11 @@ static int sta2ap_data_frame(struct adapter *adapter,
}
} else {
u8 *myhwaddr = myid(&adapter->eeprompriv);
-
if (memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) {
ret = RTW_RX_HANDLED;
goto exit;
}
+ DBG_88E("issue_deauth to sta=%pM for the reason(7)\n", (pattrib->src));
issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
ret = RTW_RX_HANDLED;
goto exit;
@@ -731,7 +886,8 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
#ifdef CONFIG_88EU_AP_MODE
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
struct sta_priv *pstapriv = &padapter->stapriv;
- u8 *pframe = precv_frame->pkt->data;
+ u8 *pframe = precv_frame->rx_data;
+ /* uint len = precv_frame->len; */
if (GetFrameType(pframe) != WIFI_CTRL_TYPE)
return _FAIL;
@@ -741,7 +897,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
return _FAIL;
/* only handle ps-poll */
- if (GetFrameSubType(pframe) == (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL)) {
+ if (GetFrameSubType(pframe) == WIFI_PSPOLL) {
u16 aid;
u8 wmmps_ac = 0;
struct sta_info *psta = NULL;
@@ -749,7 +905,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
aid = GetAid(pframe);
psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if ((!psta) || (psta->aid != aid))
+ if (!psta || psta->aid != aid)
return _FAIL;
/* for rx pkt statistics */
@@ -779,6 +935,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
return _FAIL;
if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
+ DBG_88E("%s alive check-rx ps-poll\n", __func__);
psta->expire_to = pstapriv->expire_to;
psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
}
@@ -786,14 +943,15 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
if ((psta->state & WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap & BIT(psta->aid))) {
struct list_head *xmitframe_plist, *xmitframe_phead;
struct xmit_frame *pxmitframe = NULL;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- spin_lock_bh(&psta->sleep_q.lock);
+ spin_lock_bh(&pxmitpriv->lock);
xmitframe_phead = get_list_head(&psta->sleep_q);
xmitframe_plist = xmitframe_phead->next;
if (xmitframe_phead != xmitframe_plist) {
- pxmitframe = list_entry(xmitframe_plist, struct xmit_frame, list);
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
xmitframe_plist = xmitframe_plist->next;
@@ -808,35 +966,35 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
pxmitframe->attrib.triggered = 1;
- spin_unlock_bh(&psta->sleep_q.lock);
- if (rtw_hal_xmit(padapter, pxmitframe))
- rtw_os_xmit_complete(padapter, pxmitframe);
- spin_lock_bh(&psta->sleep_q.lock);
+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
if (psta->sleepq_len == 0) {
pstapriv->tim_bitmap &= ~BIT(psta->aid);
- /* update BCN for TIM IE */
+ /* upate BCN for TIM IE */
/* update_BCNTIM(padapter); */
- update_beacon(padapter, WLAN_EID_TIM, NULL, false);
+ update_beacon(padapter, _TIM_IE_, NULL, false);
}
} else {
if (pstapriv->tim_bitmap & BIT(psta->aid)) {
- if (psta->sleepq_len == 0)
+ if (psta->sleepq_len == 0) {
+ DBG_88E("no buffered packets to xmit\n");
+
/* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
issue_nulldata(padapter, psta->hwaddr, 0, 0, 0);
- else
+ } else {
+ DBG_88E("error!psta->sleepq_len=%d\n", psta->sleepq_len);
psta->sleepq_len = 0;
+ }
pstapriv->tim_bitmap &= ~BIT(psta->aid);
- /* update BCN for TIM IE */
+ /* upate BCN for TIM IE */
/* update_BCNTIM(padapter); */
- update_beacon(padapter, WLAN_EID_TIM, NULL, false);
+ update_beacon(padapter, _TIM_IE_, NULL, false);
}
}
-
- spin_unlock_bh(&psta->sleep_q.lock);
+ spin_unlock_bh(&pxmitpriv->lock);
}
}
@@ -845,8 +1003,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter,
return _FAIL;
}
-struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
- struct recv_frame *precv_frame);
+struct recv_frame *recvframe_chk_defrag(struct adapter *padapter, struct recv_frame *precv_frame);
static int validate_recv_mgnt_frame(struct adapter *padapter,
struct recv_frame *precv_frame)
@@ -858,19 +1015,18 @@ static int validate_recv_mgnt_frame(struct adapter *padapter,
return _SUCCESS;
/* for rx pkt statistics */
- psta = rtw_get_stainfo(&padapter->stapriv,
- GetAddr2Ptr(precv_frame->pkt->data));
+ psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(precv_frame->rx_data));
if (psta) {
psta->sta_stats.rx_mgnt_pkts++;
- if (GetFrameSubType(precv_frame->pkt->data) == IEEE80211_STYPE_BEACON) {
+ if (GetFrameSubType(precv_frame->rx_data) == WIFI_BEACON) {
psta->sta_stats.rx_beacon_pkts++;
- } else if (GetFrameSubType(precv_frame->pkt->data) == IEEE80211_STYPE_PROBE_REQ) {
+ } else if (GetFrameSubType(precv_frame->rx_data) == WIFI_PROBEREQ) {
psta->sta_stats.rx_probereq_pkts++;
- } else if (GetFrameSubType(precv_frame->pkt->data) == IEEE80211_STYPE_PROBE_RESP) {
- if (!memcmp(padapter->eeprompriv.mac_addr,
- GetAddr1Ptr(precv_frame->pkt->data), ETH_ALEN))
+ } else if (GetFrameSubType(precv_frame->rx_data) == WIFI_PROBERSP) {
+ if (!memcmp(padapter->eeprompriv.mac_addr, GetAddr1Ptr(precv_frame->rx_data), ETH_ALEN))
psta->sta_stats.rx_probersp_pkts++;
- else if (is_multicast_ether_addr(GetAddr1Ptr(precv_frame->pkt->data)))
+ else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->rx_data)) ||
+ is_multicast_mac_addr(GetAddr1Ptr(precv_frame->rx_data)))
psta->sta_stats.rx_probersp_bm_pkts++;
else
psta->sta_stats.rx_probersp_uo_pkts++;
@@ -888,14 +1044,14 @@ static int validate_recv_data_frame(struct adapter *adapter,
u8 bretry;
u8 *psa, *pda, *pbssid;
struct sta_info *psta = NULL;
- u8 *ptr = precv_frame->pkt->data;
+ u8 *ptr = precv_frame->rx_data;
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
struct security_priv *psecuritypriv = &adapter->securitypriv;
int ret = _SUCCESS;
bretry = GetRetry(ptr);
- pda = ieee80211_get_DA((struct ieee80211_hdr *)ptr);
- psa = ieee80211_get_SA((struct ieee80211_hdr *)ptr);
+ pda = get_da(ptr);
+ psa = get_sa(ptr);
pbssid = get_hdr_bssid(ptr);
if (!pbssid) {
@@ -934,10 +1090,11 @@ static int validate_recv_data_frame(struct adapter *adapter,
break;
}
- if (ret == _FAIL)
+ if (ret == _FAIL) {
goto exit;
- else if (ret == RTW_RX_HANDLED)
+ } else if (ret == RTW_RX_HANDLED) {
goto exit;
+ }
if (!psta) {
ret = _FAIL;
@@ -977,6 +1134,7 @@ static int validate_recv_data_frame(struct adapter *adapter,
if (pattrib->privacy) {
GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, is_multicast_ether_addr(pattrib->ra));
+
SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
} else {
pattrib->encrypt = 0;
@@ -989,8 +1147,7 @@ exit:
return ret;
}
-static int validate_recv_frame(struct adapter *adapter,
- struct recv_frame *precv_frame)
+static int validate_recv_frame(struct adapter *adapter, struct recv_frame *precv_frame)
{
/* shall check frame subtype, to / from ds, da, bssid */
@@ -1001,13 +1158,12 @@ static int validate_recv_frame(struct adapter *adapter,
int retval = _SUCCESS;
u8 bDumpRxPkt;
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
- u8 *ptr = precv_frame->pkt->data;
+ u8 *ptr = precv_frame->rx_data;
u8 ver = (unsigned char)(*ptr) & 0x3;
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter));
-
if (ch_set_idx >= 0)
pmlmeext->channel_set[ch_set_idx].rx_count++;
}
@@ -1032,23 +1188,52 @@ static int validate_recv_frame(struct adapter *adapter,
pattrib->privacy = GetPrivacy(ptr);
pattrib->order = GetOrder(ptr);
+ /* Dump rx packets */
rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
+ if (bDumpRxPkt == 1) {/* dump all rx packets */
+ int i;
+ DBG_88E("#############################\n");
+
+ for (i = 0; i < 64; i = i + 8)
+ DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr + i),
+ *(ptr + i + 1), *(ptr + i + 2), *(ptr + i + 3), *(ptr + i + 4), *(ptr + i + 5), *(ptr + i + 6), *(ptr + i + 7));
+ DBG_88E("#############################\n");
+ } else if (bDumpRxPkt == 2) {
+ if (type == WIFI_MGT_TYPE) {
+ int i;
+ DBG_88E("#############################\n");
+
+ for (i = 0; i < 64; i = i + 8)
+ DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr + i),
+ *(ptr + i + 1), *(ptr + i + 2), *(ptr + i + 3), *(ptr + i + 4), *(ptr + i + 5), *(ptr + i + 6), *(ptr + i + 7));
+ DBG_88E("#############################\n");
+ }
+ } else if (bDumpRxPkt == 3) {
+ if (type == WIFI_DATA_TYPE) {
+ int i;
+ DBG_88E("#############################\n");
+
+ for (i = 0; i < 64; i = i + 8)
+ DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr + i),
+ *(ptr + i + 1), *(ptr + i + 2), *(ptr + i + 3), *(ptr + i + 4), *(ptr + i + 5), *(ptr + i + 6), *(ptr + i + 7));
+ DBG_88E("#############################\n");
+ }
+ }
switch (type) {
case WIFI_MGT_TYPE: /* mgnt */
- retval = validate_recv_mgnt_frame(adapter, precv_frame);
+ validate_recv_mgnt_frame(adapter, precv_frame);
retval = _FAIL; /* only data frame return _SUCCESS */
break;
case WIFI_CTRL_TYPE: /* ctrl */
- retval = validate_recv_ctrl_frame(adapter, precv_frame);
+ validate_recv_ctrl_frame(adapter, precv_frame);
retval = _FAIL; /* only data frame return _SUCCESS */
break;
case WIFI_DATA_TYPE: /* data */
- led_control_8188eu(adapter, LED_CTL_RX);
+ rtw_led_control(adapter, LED_CTL_RX);
pattrib->qos = (subtype & BIT(7)) ? 1 : 0;
retval = validate_recv_data_frame(adapter, precv_frame);
if (retval == _FAIL) {
struct recv_priv *precvpriv = &adapter->recvpriv;
-
precvpriv->rx_drop++;
}
break;
@@ -1057,19 +1242,6 @@ static int validate_recv_frame(struct adapter *adapter,
break;
}
- /*
- * This is the last moment before management and control frames get
- * discarded. So we need to forward them to the monitor now or never.
- *
- * At the same time data frames can still be encrypted if software
- * decryption is in use. However, decryption can occur not until later
- * (see recv_func()).
- *
- * Hence forward the frame to the monitor anyway to preserve the order
- * in which frames were received.
- */
- rtl88eu_mon_recv_hook(adapter->pmondev, precv_frame);
-
exit:
return retval;
@@ -1086,19 +1258,23 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
u8 *psnap_type;
struct ieee80211_snap_hdr *psnap;
- u8 *ptr = precvframe->pkt->data;
+ int ret = _SUCCESS;
+ struct adapter *adapter = precvframe->adapter;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+ u8 *ptr = get_recvframe_data(precvframe); /* point to frame_ctrl field */
struct rx_pkt_attrib *pattrib = &precvframe->attrib;
if (pattrib->encrypt)
- skb_trim(precvframe->pkt, precvframe->pkt->len - pattrib->icv_len);
+ recvframe_pull_tail(precvframe, pattrib->icv_len);
psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen + pattrib->iv_len);
psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;
/* convert hdr + possible LLC headers into Ethernet header */
- if ((!memcmp(psnap, rfc1042_header, SNAP_SIZE) &&
+ if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) &&
- memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)) ||
- !memcmp(psnap, bridge_tunnel_header, SNAP_SIZE)) {
+ memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)) ||
+ !memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) {
/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
bsnaphdr = true;
} else {
@@ -1107,15 +1283,25 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
}
rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0);
- len = precvframe->pkt->len - rmv_len;
+ len = precvframe->len - rmv_len;
memcpy(&be_tmp, ptr + rmv_len, 2);
eth_type = ntohs(be_tmp); /* pattrib->ether_type */
pattrib->eth_type = eth_type;
- ptr = skb_pull(precvframe->pkt, rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0));
- if (!ptr)
- return _FAIL;
+ if ((check_fwstate(pmlmepriv, WIFI_MP_STATE))) {
+ ptr += rmv_len;
+ *ptr = 0x87;
+ *(ptr + 1) = 0x12;
+
+ eth_type = 0x8712;
+ /* append rx status for mp test packets */
+ ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + 2) - 24);
+ memcpy(ptr, get_rxmem(precvframe), 24);
+ ptr += 24;
+ } else {
+ ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
+ }
memcpy(ptr, pattrib->dst, ETH_ALEN);
memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
@@ -1125,17 +1311,16 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
memcpy(ptr + 12, &be_tmp, 2);
}
- return _SUCCESS;
+ return ret;
}
/* perform defrag */
-static struct recv_frame *recvframe_defrag(struct adapter *adapter,
- struct __queue *defrag_q)
+static struct recv_frame *recvframe_defrag(struct adapter *adapter, struct __queue *defrag_q)
{
struct list_head *plist, *phead;
u8 wlanhdr_offset;
u8 curfragnum;
- struct recv_frame *pnfhdr;
+ struct recv_frame *pfhdr, *pnfhdr;
struct recv_frame *prframe, *pnextrframe;
struct __queue *pfree_recv_queue;
@@ -1144,10 +1329,11 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
phead = get_list_head(defrag_q);
plist = phead->next;
- prframe = list_entry(plist, struct recv_frame, list);
+ pfhdr = container_of(plist, struct recv_frame, list);
+ prframe = (struct recv_frame *)pfhdr;
list_del_init(&prframe->list);
- if (curfragnum != prframe->attrib.frag_num) {
+ if (curfragnum != pfhdr->attrib.frag_num) {
/* the first fragment number must be 0 */
/* free the whole queue */
rtw_free_recvframe(prframe, pfree_recv_queue);
@@ -1159,12 +1345,16 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
curfragnum++;
plist = get_list_head(defrag_q);
+ plist = phead->next;
+ pfhdr = container_of(plist, struct recv_frame, list);
+ prframe = (struct recv_frame *)pfhdr;
+ list_del_init(&prframe->list);
plist = plist->next;
while (phead != plist) {
- pnfhdr = list_entry(plist, struct recv_frame, list);
- pnextrframe = pnfhdr;
+ pnfhdr = container_of(plist, struct recv_frame, list);
+ pnextrframe = (struct recv_frame *)pnfhdr;
/* check the fragment sequence (2nd ~n fragment frame) */
@@ -1183,14 +1373,17 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
- skb_pull(pnextrframe->pkt, wlanhdr_offset);
+ recvframe_pull(pnextrframe, wlanhdr_offset);
/* append to first fragment frame's tail (if privacy frame, pull the ICV) */
- skb_trim(prframe->pkt, prframe->pkt->len - prframe->attrib.icv_len);
+ recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);
- skb_put_data(prframe->pkt, pnfhdr->pkt->data, pnfhdr->pkt->len);
+ /* memcpy */
+ memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
- prframe->attrib.icv_len = pnfhdr->attrib.icv_len;
+ recvframe_put(prframe, pnfhdr->len);
+
+ pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
plist = plist->next;
}
@@ -1201,8 +1394,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
}
/* check if need to defrag, if needed queue the frame to defrag_q */
-struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
- struct recv_frame *precv_frame)
+struct recv_frame *recvframe_chk_defrag(struct adapter *padapter, struct recv_frame *precv_frame)
{
u8 ismfrag;
u8 fragnum;
@@ -1227,8 +1419,7 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
psta_addr = pfhdr->attrib.ta;
psta = rtw_get_stainfo(pstapriv, psta_addr);
if (!psta) {
- u8 type = GetFrameType(pfhdr->pkt->data);
-
+ u8 type = GetFrameType(pfhdr->rx_data);
if (type != WIFI_DATA_TYPE) {
psta = rtw_get_bcmc_stainfo(padapter);
pdefrag_q = &psta->sta_recvpriv.defrag_q;
@@ -1248,9 +1439,10 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
if (pdefrag_q) {
if (fragnum == 0) {
/* the first fragment */
- if (!list_empty(&pdefrag_q->queue))
+ if (!list_empty(&pdefrag_q->queue)) {
/* free current defrag_q */
rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
+ }
}
/* Then enqueue the 0~(n-1) fragment into the defrag_q */
@@ -1261,7 +1453,8 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
prtnframe = NULL;
} else {
/* can't find this ta's defrag_queue, so free this recv_frame */
- rtw_free_recvframe(precv_frame, pfree_recv_queue);
+ if (precv_frame && pfree_recv_queue)
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
prtnframe = NULL;
}
}
@@ -1278,15 +1471,17 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
prtnframe = precv_frame;
} else {
/* can't find this ta's defrag_queue, so free this recv_frame */
- rtw_free_recvframe(precv_frame, pfree_recv_queue);
+ if (precv_frame && pfree_recv_queue)
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
prtnframe = NULL;
}
}
- if (prtnframe && (prtnframe->attrib.privacy)) {
+ if (prtnframe && prtnframe->attrib.privacy) {
/* after defrag we must check tkip mic code */
if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {
- rtw_free_recvframe(prtnframe, pfree_recv_queue);
+ if (precv_frame && pfree_recv_queue)
+ rtw_free_recvframe(prtnframe, pfree_recv_queue);
prtnframe = NULL;
}
}
@@ -1301,28 +1496,32 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
u8 nr_subframes, i;
unsigned char *pdata;
struct rx_pkt_attrib *pattrib;
+ unsigned char *data_ptr;
struct sk_buff *sub_skb, *subframes[MAX_SUBFRAME_COUNT];
struct recv_priv *precvpriv = &padapter->recvpriv;
struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
-
+ int ret = _SUCCESS;
nr_subframes = 0;
+
pattrib = &prframe->attrib;
- skb_pull(prframe->pkt, prframe->attrib.hdrlen);
+ recvframe_pull(prframe, prframe->attrib.hdrlen);
if (prframe->attrib.iv_len > 0)
- skb_pull(prframe->pkt, prframe->attrib.iv_len);
+ recvframe_pull(prframe, prframe->attrib.iv_len);
- a_len = prframe->pkt->len;
+ a_len = prframe->len;
- pdata = prframe->pkt->data;
+ pdata = prframe->rx_data;
while (a_len > ETH_HLEN) {
/* Offset 12 denote 2 mac address */
- nSubframe_Length = get_unaligned_be16(pdata + 12);
+ nSubframe_Length = RTW_GET_BE16(pdata + 12);
- if (a_len < (ETH_HLEN + nSubframe_Length))
+ if (a_len < ETH_HLEN + nSubframe_Length) {
+ DBG_88E("nRemain_Length is %d and nSubframe_Length is : %d\n", a_len, nSubframe_Length);
goto exit;
+ }
/* move the data point to data content */
pdata += ETH_HLEN;
@@ -1330,27 +1529,40 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
/* Allocate new skb for releasing to upper layer */
sub_skb = dev_alloc_skb(nSubframe_Length + 12);
- if (!sub_skb)
- break;
-
- skb_reserve(sub_skb, 12);
- skb_put_data(sub_skb, pdata, nSubframe_Length);
+ if (sub_skb) {
+ skb_reserve(sub_skb, 12);
+ data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
+ memcpy(data_ptr, pdata, nSubframe_Length);
+ } else {
+ sub_skb = skb_clone(prframe->pkt, GFP_ATOMIC);
+ if (sub_skb) {
+ sub_skb->data = pdata;
+ sub_skb->len = nSubframe_Length;
+ skb_set_tail_pointer(sub_skb, nSubframe_Length);
+ } else {
+ DBG_88E("skb_clone() Fail!!! , nr_subframes=%d\n", nr_subframes);
+ break;
+ }
+ }
subframes[nr_subframes++] = sub_skb;
- if (nr_subframes >= MAX_SUBFRAME_COUNT)
+ if (nr_subframes >= MAX_SUBFRAME_COUNT) {
+ DBG_88E("ParseSubframe(): Too many Subframes! Packets dropped!\n");
break;
+ }
pdata += nSubframe_Length;
a_len -= nSubframe_Length;
if (a_len != 0) {
padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4 - 1));
- if (padding_len == 4)
+ if (padding_len == 4) {
padding_len = 0;
+ }
- if (a_len < padding_len)
+ if (a_len < padding_len) {
goto exit;
-
+ }
pdata += padding_len;
a_len -= padding_len;
}
@@ -1359,11 +1571,11 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
for (i = 0; i < nr_subframes; i++) {
sub_skb = subframes[i];
/* convert hdr + possible LLC headers into Ethernet header */
- eth_type = get_unaligned_be16(&sub_skb->data[6]);
+ eth_type = RTW_GET_BE16(&sub_skb->data[6]);
if (sub_skb->len >= 8 &&
- ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) &&
+ ((!memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) &&
eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
- !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) {
+ !memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE))) {
/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
skb_pull(sub_skb, SNAP_SIZE);
memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN);
@@ -1378,7 +1590,7 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
}
/* Indicate the packets to upper layer */
- /* Insert NAT2.5 RX here! */
+ /* Insert NAT2.5 RX here! */
sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
sub_skb->dev = padapter->pnetdev;
@@ -1388,9 +1600,11 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
}
exit:
+
+ prframe->len = 0;
rtw_free_recvframe(prframe, pfree_recv_queue);/* free this recv_frame */
- return _SUCCESS;
+ return ret;
}
static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)
@@ -1423,8 +1637,8 @@ static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_n
return true;
}
-static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
- struct recv_frame *prframe)
+int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, struct recv_frame *prframe);
+int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, struct recv_frame *prframe)
{
struct rx_pkt_attrib *pattrib = &prframe->attrib;
struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
@@ -1436,7 +1650,7 @@ static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
plist = phead->next;
while (phead != plist) {
- hdr = list_entry(plist, struct recv_frame, list);
+ hdr = container_of(plist, struct recv_frame, list);
pnextattrib = &hdr->attrib;
if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
@@ -1457,7 +1671,6 @@ static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reor
{
struct list_head *phead, *plist;
struct recv_frame *prframe;
- struct recv_frame *prhdr;
struct rx_pkt_attrib *pattrib;
int bPktInBuf = false;
struct recv_priv *precvpriv = &padapter->recvpriv;
@@ -1471,16 +1684,15 @@ static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reor
if (list_empty(phead))
return true;
- prhdr = list_entry(plist, struct recv_frame, list);
- pattrib = &prhdr->attrib;
+ prframe = container_of(plist, struct recv_frame, list);
+ pattrib = &prframe->attrib;
preorder_ctrl->indicate_seq = pattrib->seq_num;
}
/* Prepare indication list and indication. */
/* Check if there is any packet need indicate. */
while (!list_empty(phead)) {
- prhdr = list_entry(plist, struct recv_frame, list);
- prframe = prhdr;
+ prframe = container_of(plist, struct recv_frame, list);
pattrib = &prframe->attrib;
if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
@@ -1514,8 +1726,7 @@ static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reor
return bPktInBuf;
}
-static int recv_indicatepkt_reorder(struct adapter *padapter,
- struct recv_frame *prframe)
+static int recv_indicatepkt_reorder(struct adapter *padapter, struct recv_frame *prframe)
{
int retval = _SUCCESS;
struct rx_pkt_attrib *pattrib = &prframe->attrib;
@@ -1526,10 +1737,9 @@ static int recv_indicatepkt_reorder(struct adapter *padapter,
/* s1. */
wlanhdr_to_ethhdr(prframe);
- if ((pattrib->qos != 1) || (pattrib->eth_type == 0x0806) ||
- (pattrib->ack_policy != 0)) {
- if ((!padapter->bDriverStopped) &&
- (!padapter->bSurpriseRemoved)) {
+ if (pattrib->qos != 1) {
+ if (!padapter->bDriverStopped &&
+ !padapter->bSurpriseRemoved) {
rtw_recv_indicatepkt(padapter, prframe);
return _SUCCESS;
}
@@ -1542,8 +1752,7 @@ static int recv_indicatepkt_reorder(struct adapter *padapter,
preorder_ctrl->indicate_seq = pattrib->seq_num;
rtw_recv_indicatepkt(padapter, prframe);
- preorder_ctrl->indicate_seq =
- (preorder_ctrl->indicate_seq + 1) % 4096;
+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) % 4096;
return _SUCCESS;
}
} else if (pattrib->amsdu == 1) { /* temp filter -> means didn't support A-MSDUs in a A-MPDU */
@@ -1551,8 +1760,7 @@ static int recv_indicatepkt_reorder(struct adapter *padapter,
preorder_ctrl->indicate_seq = pattrib->seq_num;
retval = amsdu_to_msdu(padapter, prframe);
- preorder_ctrl->indicate_seq =
- (preorder_ctrl->indicate_seq + 1) % 4096;
+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) % 4096;
return retval;
}
}
@@ -1560,13 +1768,8 @@ static int recv_indicatepkt_reorder(struct adapter *padapter,
spin_lock_bh(&ppending_recvframe_queue->lock);
/* s2. check if winstart_b(indicate_seq) needs to been updated */
- if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {
- rtw_recv_indicatepkt(padapter, prframe);
-
- spin_unlock_bh(&ppending_recvframe_queue->lock);
-
- goto _success_exit;
- }
+ if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num))
+ goto _err_exit;
/* s3. Insert all packet into Reorder Queue to maintain its ordering. */
if (!enqueue_reorder_recvframe(preorder_ctrl, prframe))
@@ -1584,16 +1787,13 @@ static int recv_indicatepkt_reorder(struct adapter *padapter,
/* recv_indicatepkts_in_order(padapter, preorder_ctrl, true); */
if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) {
- mod_timer(&preorder_ctrl->reordering_ctrl_timer,
- jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
+ _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
spin_unlock_bh(&ppending_recvframe_queue->lock);
} else {
spin_unlock_bh(&ppending_recvframe_queue->lock);
- del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
+ _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
}
-_success_exit:
-
return _SUCCESS;
_err_exit:
@@ -1603,10 +1803,9 @@ _err_exit:
return _FAIL;
}
-void rtw_reordering_ctrl_timeout_handler(struct timer_list *t)
+void rtw_reordering_ctrl_timeout_handler(void *pcontext)
{
- struct recv_reorder_ctrl *preorder_ctrl = from_timer(preorder_ctrl, t,
- reordering_ctrl_timer);
+ struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)pcontext;
struct adapter *padapter = preorder_ctrl->padapter;
struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
@@ -1616,25 +1815,28 @@ void rtw_reordering_ctrl_timeout_handler(struct timer_list *t)
spin_lock_bh(&ppending_recvframe_queue->lock);
if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true))
- mod_timer(&preorder_ctrl->reordering_ctrl_timer,
- jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
+ _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
spin_unlock_bh(&ppending_recvframe_queue->lock);
}
-static int process_recv_indicatepkts(struct adapter *padapter,
- struct recv_frame *prframe)
+static int process_recv_indicatepkts(struct adapter *padapter, struct recv_frame *prframe)
{
int retval = _SUCCESS;
+ /* struct recv_priv *precvpriv = &padapter->recvpriv; */
+ /* struct rx_pkt_attrib *pattrib = &prframe->attrib; */
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct ht_priv *phtpriv = &pmlmepriv->htpriv;
if (phtpriv->ht_option) { /* B/G/N Mode */
+ /* prframe->preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */
+
if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) {
/* including perform A-MPDU Rx Ordering Buffer Control */
if ((!padapter->bDriverStopped) &&
(!padapter->bSurpriseRemoved)) {
- return _FAIL;
+ retval = _FAIL;
+ return retval;
}
}
} else { /* B/G mode */
@@ -1643,21 +1845,37 @@ static int process_recv_indicatepkts(struct adapter *padapter,
return retval;
if ((!padapter->bDriverStopped) &&
- (!padapter->bSurpriseRemoved))
+ (!padapter->bSurpriseRemoved)) {
/* indicate this recv_frame */
rtw_recv_indicatepkt(padapter, prframe);
- else
- return _FAIL;
+ } else {
+ retval = _FAIL;
+ return retval;
+ }
}
return retval;
}
-static int recv_func_prehandle(struct adapter *padapter,
- struct recv_frame *rframe)
+static int recv_func_prehandle(struct adapter *padapter, struct recv_frame *rframe)
{
int ret = _SUCCESS;
+ struct rx_pkt_attrib *pattrib = &rframe->attrib;
struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (padapter->registrypriv.mp_mode == 1) {
+ if (pattrib->crc_err == 1)
+ padapter->mppriv.rx_crcerrpktcount++;
+ else
+ padapter->mppriv.rx_pktcount++;
+
+ if (!check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE)) {
+ ret = _FAIL;
+ rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
+ goto exit;
+ }
+ }
/* check the frame crtl field and decache */
ret = validate_recv_frame(padapter, rframe);
@@ -1670,8 +1888,7 @@ exit:
return ret;
}
-static int recv_func_posthandle(struct adapter *padapter,
- struct recv_frame *prframe)
+static int recv_func_posthandle(struct adapter *padapter, struct recv_frame *prframe)
{
int ret = _SUCCESS;
struct recv_frame *orig_prframe = prframe;
@@ -1679,7 +1896,7 @@ static int recv_func_posthandle(struct adapter *padapter,
struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
/* DATA FRAME */
- led_control_8188eu(padapter, LED_CTL_RX);
+ rtw_led_control(padapter, LED_CTL_RX);
prframe = decryptor(padapter, prframe);
if (!prframe) {
@@ -1717,13 +1934,19 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
struct rx_pkt_attrib *prxattrib = &rframe->attrib;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+ struct recv_priv *recvpriv = &padapter->recvpriv;
/* check if need to handle uc_swdec_pending_queue*/
- if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
+ if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
+ psecuritypriv->busetkipkey) {
struct recv_frame *pending_frame;
+ int cnt = 0;
- while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue)))
+ pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue);
+ while (pending_frame) {
+ cnt++;
recv_func_posthandle(padapter, pending_frame);
+ }
}
ret = recv_func_prehandle(padapter, rframe);
@@ -1731,15 +1954,23 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
if (ret == _SUCCESS) {
/* check if need to enqueue into uc_swdec_pending_queue*/
if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
- !is_multicast_ether_addr(prxattrib->ra) &&
- prxattrib->encrypt > 0 &&
- prxattrib->bdecrypted == 0 &&
- !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) &&
- !psecuritypriv->busetkipkey) {
+ !is_multicast_ether_addr(prxattrib->ra) && prxattrib->encrypt > 0 &&
+ (prxattrib->bdecrypted == 0 || psecuritypriv->sw_decrypt) &&
+ psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPAPSK &&
+ !psecuritypriv->busetkipkey) {
rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
+ DBG_88E("%s: no key, enqueue uc_swdec_pending_queue\n", __func__);
+ if (recvpriv->free_recvframe_cnt < NR_RECVFRAME / 4) {
+ /* to prevent from recvframe starvation,
+ * get recvframe from uc_swdec_pending_queue to
+ * free_recvframe_cnt */
+ rframe = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue);
+ if (rframe)
+ goto do_posthandle;
+ }
goto exit;
}
-
+do_posthandle:
ret = recv_func_posthandle(padapter, rframe);
}
@@ -1747,23 +1978,35 @@ exit:
return ret;
}
-int rtw_recv_entry(struct recv_frame *precvframe)
+s32 rtw_recv_entry(struct recv_frame *precvframe)
{
- struct adapter *padapter = precvframe->adapter;
- struct recv_priv *precvpriv = &padapter->recvpriv;
- int ret;
+ struct adapter *padapter;
+ struct recv_priv *precvpriv;
+ s32 ret = _SUCCESS;
+
+ padapter = precvframe->adapter;
+
+ precvpriv = &padapter->recvpriv;
ret = recv_func(padapter, precvframe);
- if (ret == _SUCCESS)
- precvpriv->rx_pkts++;
+ if (ret == _FAIL)
+ goto _recv_entry_drop;
+
+ precvpriv->rx_pkts++;
+
+ return ret;
+
+_recv_entry_drop:
+
+ if (padapter->registrypriv.mp_mode == 1)
+ padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
return ret;
}
-static void rtw_signal_stat_timer_hdl(struct timer_list *t)
+void rtw_signal_stat_timer_hdl(struct timer_list *t)
{
- struct adapter *adapter =
- from_timer(adapter, t, recvpriv.signal_stat_timer);
+ struct adapter *adapter = from_timer(adapter, t, recvpriv.signal_stat_timer);
struct recv_priv *recvpriv = &adapter->recvpriv;
u32 tmp_s, tmp_q;
@@ -1771,42 +2014,45 @@ static void rtw_signal_stat_timer_hdl(struct timer_list *t)
u8 avg_signal_qual = 0;
u8 _alpha = 3; /* this value is based on converging_constant = 5000 and sampling_interval = 1000 */
- if (recvpriv->signal_strength_data.update_req == 0) {
- /* update_req is clear, means we got rx */
- avg_signal_strength = recvpriv->signal_strength_data.avg_val;
- /* after avg_vals are acquired, we can re-stat the signal
- * values
- */
- recvpriv->signal_strength_data.update_req = 1;
- }
+ if (adapter->recvpriv.is_signal_dbg) {
+ /* update the user specific value, signal_strength_dbg, to signal_strength, rssi */
+ adapter->recvpriv.signal_strength = adapter->recvpriv.signal_strength_dbg;
+ adapter->recvpriv.rssi = (s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg);
+ } else {
+ if (recvpriv->signal_strength_data.update_req == 0) {/* update_req is clear, means we got rx */
+ avg_signal_strength = recvpriv->signal_strength_data.avg_val;
+ /* after avg_vals are accquired, we can re-stat the signal values */
+ recvpriv->signal_strength_data.update_req = 1;
+ }
- if (recvpriv->signal_qual_data.update_req == 0) {
- /* update_req is clear, means we got rx */
- avg_signal_qual = recvpriv->signal_qual_data.avg_val;
- /* after avg_vals are acquired, we can re-stat the signal
- * values
- */
- recvpriv->signal_qual_data.update_req = 1;
- }
+ if (recvpriv->signal_qual_data.update_req == 0) {/* update_req is clear, means we got rx */
+ avg_signal_qual = recvpriv->signal_qual_data.avg_val;
+ /* after avg_vals are accquired, we can re-stat the signal values */
+ recvpriv->signal_qual_data.update_req = 1;
+ }
- /* update value of signal_strength, rssi, signal_qual */
- if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) {
- tmp_s = avg_signal_strength +
- (_alpha - 1) * recvpriv->signal_strength;
- tmp_s = DIV_ROUND_UP(tmp_s, _alpha);
- if (tmp_s > 100)
- tmp_s = 100;
-
- tmp_q = avg_signal_qual +
- (_alpha - 1) * recvpriv->signal_qual;
- tmp_q = DIV_ROUND_UP(tmp_q, _alpha);
- if (tmp_q > 100)
- tmp_q = 100;
-
- recvpriv->signal_strength = tmp_s;
- recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);
- recvpriv->signal_qual = tmp_q;
- }
+ /* update value of signal_strength, rssi, signal_qual */
+ if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) {
+ tmp_s = (avg_signal_strength + (_alpha - 1) * recvpriv->signal_strength);
+ if (tmp_s % _alpha)
+ tmp_s = tmp_s / _alpha + 1;
+ else
+ tmp_s = tmp_s / _alpha;
+ if (tmp_s > 100)
+ tmp_s = 100;
+
+ tmp_q = (avg_signal_qual + (_alpha - 1) * recvpriv->signal_qual);
+ if (tmp_q % _alpha)
+ tmp_q = tmp_q / _alpha + 1;
+ else
+ tmp_q = tmp_q / _alpha;
+ if (tmp_q > 100)
+ tmp_q = 100;
+ recvpriv->signal_strength = tmp_s;
+ recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);
+ recvpriv->signal_qual = tmp_q;
+ }
+ }
rtw_set_signal_stat_timer(recvpriv);
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_rf.c b/drivers/staging/r8188eu/core/rtw_rf.c
index 094aa15efe44..321546c40446 100644
--- a/drivers/staging/rtl8188eu/core/rtw_rf.c
+++ b/drivers/staging/r8188eu/core/rtw_rf.c
@@ -1,15 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#define _RTW_RF_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <xmit_osdep.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/xmit_osdep.h"
struct ch_freq {
u32 channel;
@@ -38,7 +35,7 @@ static struct ch_freq ch_freq_map[] = {
{216, 5080},/* Japan, means J16 */
};
-static int ch_freq_map_num = ARRAY_SIZE(ch_freq_map);
+static int ch_freq_map_num = (sizeof(ch_freq_map) / sizeof(struct ch_freq));
u32 rtw_ch2freq(u32 channel)
{
@@ -56,3 +53,20 @@ u32 rtw_ch2freq(u32 channel)
return freq;
}
+
+u32 rtw_freq2ch(u32 freq)
+{
+ u8 i;
+ u32 ch = 0;
+
+ for (i = 0; i < ch_freq_map_num; i++) {
+ if (freq == ch_freq_map[i].frequency) {
+ ch = ch_freq_map[i].channel;
+ break;
+ }
+ }
+ if (i == ch_freq_map_num)
+ ch = 1;
+
+ return ch;
+}
diff --git a/drivers/staging/r8188eu/core/rtw_security.c b/drivers/staging/r8188eu/core/rtw_security.c
new file mode 100644
index 000000000000..5aa893ab46e9
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_security.c
@@ -0,0 +1,1656 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTW_SECURITY_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/wifi.h"
+#include "../include/osdep_intf.h"
+
+/* WEP related ===== */
+
+#define CRC32_POLY 0x04c11db7
+
+struct arc4context {
+ u32 x;
+ u32 y;
+ u8 state[256];
+};
+
+static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len)
+{
+ u32 t, u;
+ u32 keyindex;
+ u32 stateindex;
+ u8 *state;
+ u32 counter;
+
+ state = parc4ctx->state;
+ parc4ctx->x = 0;
+ parc4ctx->y = 0;
+ for (counter = 0; counter < 256; counter++)
+ state[counter] = (u8)counter;
+ keyindex = 0;
+ stateindex = 0;
+ for (counter = 0; counter < 256; counter++) {
+ t = state[counter];
+ stateindex = (stateindex + key[keyindex] + t) & 0xff;
+ u = state[stateindex];
+ state[stateindex] = (u8)t;
+ state[counter] = (u8)u;
+ if (++keyindex >= key_len)
+ keyindex = 0;
+ }
+
+}
+
+static u32 arcfour_byte(struct arc4context *parc4ctx)
+{
+ u32 x;
+ u32 y;
+ u32 sx, sy;
+ u8 *state;
+
+ state = parc4ctx->state;
+ x = (parc4ctx->x + 1) & 0xff;
+ sx = state[x];
+ y = (sx + parc4ctx->y) & 0xff;
+ sy = state[y];
+ parc4ctx->x = x;
+ parc4ctx->y = y;
+ state[y] = (u8)sx;
+ state[x] = (u8)sy;
+
+ return state[(sx + sy) & 0xff];
+}
+
+static void arcfour_encrypt(struct arc4context *parc4ctx, u8 *dest, u8 *src, u32 len)
+{
+ u32 i;
+
+ for (i = 0; i < len; i++)
+ dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
+
+}
+
+/*
+ Need to consider the fragment situation
+*/
+void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
+{ /* exclude ICV */
+ union {
+ __le32 f0;
+ u8 f1[4];
+ } crc;
+ struct arc4context mycontext;
+
+ int curfragnum, length;
+ u32 keylength;
+
+ u8 *pframe, *payload, *iv; /* wepkey */
+ u8 wepkey[16];
+ u8 hw_hdr_offset = 0;
+ struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ if (!((struct xmit_frame *)pxmitframe)->buf_addr)
+ return;
+
+ hw_hdr_offset = TXDESC_SIZE +
+ (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);
+
+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
+
+ /* start to encrypt each fragment */
+ if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
+ keylength = psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex];
+
+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
+ iv = pframe + pattrib->hdrlen;
+ memcpy(&wepkey[0], iv, 3);
+ memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength);
+ payload = pframe + pattrib->iv_len + pattrib->hdrlen;
+
+ if ((curfragnum + 1) == pattrib->nr_frags) { /* the last fragment */
+ length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
+
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
+
+ arcfour_init(&mycontext, wepkey, 3 + keylength);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+ arcfour_encrypt(&mycontext, payload + length, crc.f1, 4);
+ } else {
+ length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
+ arcfour_init(&mycontext, wepkey, 3 + keylength);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+ arcfour_encrypt(&mycontext, payload + length, crc.f1, 4);
+
+ pframe += pxmitpriv->frag_len;
+ pframe = (u8 *)RND4((size_t)(pframe));
+ }
+ }
+ }
+
+}
+
+void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe)
+{
+ /* exclude ICV */
+ struct arc4context mycontext;
+ int length;
+ u32 keylength;
+ u8 *pframe, *payload, *iv, wepkey[16];
+ u8 keyindex;
+ struct rx_pkt_attrib *prxattrib = &(((struct recv_frame *)precvframe)->attrib);
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ pframe = (unsigned char *)((struct recv_frame *)precvframe)->rx_data;
+
+ /* start to decrypt recvframe */
+ if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
+ iv = pframe + prxattrib->hdrlen;
+ keyindex = prxattrib->key_index;
+ keylength = psecuritypriv->dot11DefKeylen[keyindex];
+ memcpy(&wepkey[0], iv, 3);
+ memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength);
+ length = ((struct recv_frame *)precvframe)->len - prxattrib->hdrlen - prxattrib->iv_len;
+
+ payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
+
+ /* decrypt payload include icv */
+ arcfour_init(&mycontext, wepkey, 3 + keylength);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+ }
+}
+
+/* 3 ===== TKIP related ===== */
+
+static u32 secmicgetuint32(u8 *p)
+/* Convert from Byte[] to Us3232 in a portable way */
+{
+ s32 i;
+ u32 res = 0;
+
+ for (i = 0; i < 4; i++)
+ res |= ((u32)(*p++)) << (8 * i);
+
+ return res;
+}
+
+static void secmicputuint32(u8 *p, u32 val)
+/* Convert from Us3232 to Byte[] in a portable way */
+{
+ long i;
+
+ for (i = 0; i < 4; i++) {
+ *p++ = (u8)(val & 0xff);
+ val >>= 8;
+ }
+
+}
+
+static void secmicclear(struct mic_data *pmicdata)
+{
+/* Reset the state to the empty message. */
+
+ pmicdata->L = pmicdata->K0;
+ pmicdata->R = pmicdata->K1;
+ pmicdata->nBytesInM = 0;
+ pmicdata->M = 0;
+
+}
+
+void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key)
+{
+ /* Set the key */
+
+ pmicdata->K0 = secmicgetuint32(key);
+ pmicdata->K1 = secmicgetuint32(key + 4);
+ /* and reset the message */
+ secmicclear(pmicdata);
+
+}
+
+void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b)
+{
+
+ /* Append the byte to our word-sized buffer */
+ pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM);
+ pmicdata->nBytesInM++;
+ /* Process the word if it is full. */
+ if (pmicdata->nBytesInM >= 4) {
+ pmicdata->L ^= pmicdata->M;
+ pmicdata->R ^= ROL32(pmicdata->L, 17);
+ pmicdata->L += pmicdata->R;
+ pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
+ pmicdata->L += pmicdata->R;
+ pmicdata->R ^= ROL32(pmicdata->L, 3);
+ pmicdata->L += pmicdata->R;
+ pmicdata->R ^= ROR32(pmicdata->L, 2);
+ pmicdata->L += pmicdata->R;
+ /* Clear the buffer */
+ pmicdata->M = 0;
+ pmicdata->nBytesInM = 0;
+ }
+
+}
+
+void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
+{
+
+ /* This is simple */
+ while (nbytes > 0) {
+ rtw_secmicappendbyte(pmicdata, *src++);
+ nbytes--;
+ }
+
+}
+
+void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst)
+{
+
+ /* Append the minimum padding */
+ rtw_secmicappendbyte(pmicdata, 0x5a);
+ rtw_secmicappendbyte(pmicdata, 0);
+ rtw_secmicappendbyte(pmicdata, 0);
+ rtw_secmicappendbyte(pmicdata, 0);
+ rtw_secmicappendbyte(pmicdata, 0);
+ /* and then zeroes until the length is a multiple of 4 */
+ while (pmicdata->nBytesInM != 0)
+ rtw_secmicappendbyte(pmicdata, 0);
+ /* The appendByte function has already computed the result. */
+ secmicputuint32(dst, pmicdata->L);
+ secmicputuint32(dst + 4, pmicdata->R);
+ /* Reset to the empty message. */
+ secmicclear(pmicdata);
+
+}
+
+void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
+{
+ struct mic_data micdata;
+ u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
+
+ rtw_secmicsetkey(&micdata, key);
+ priority[0] = pri;
+
+ /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
+ if (header[1] & 1) { /* ToDS == 1 */
+ rtw_secmicappend(&micdata, &header[16], 6); /* DA */
+ if (header[1] & 2) /* From Ds == 1 */
+ rtw_secmicappend(&micdata, &header[24], 6);
+ else
+ rtw_secmicappend(&micdata, &header[10], 6);
+ } else { /* ToDS == 0 */
+ rtw_secmicappend(&micdata, &header[4], 6); /* DA */
+ if (header[1] & 2) /* From Ds == 1 */
+ rtw_secmicappend(&micdata, &header[16], 6);
+ else
+ rtw_secmicappend(&micdata, &header[10], 6);
+ }
+ rtw_secmicappend(&micdata, &priority[0], 4);
+
+ rtw_secmicappend(&micdata, data, data_len);
+
+ rtw_secgetmic(&micdata, mic_code);
+
+}
+
+/* macros for extraction/creation of unsigned char/unsigned short values */
+#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
+#define Lo8(v16) ((u8)((v16) & 0x00FF))
+#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF))
+#define Lo16(v32) ((u16)((v32) & 0xFFFF))
+#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF))
+#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
+
+/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
+#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)])
+
+/* S-box lookup: 16 bits --> 16 bits */
+#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
+
+/* fixed algorithm "parameters" */
+#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
+#define TA_SIZE 6 /* 48-bit transmitter address */
+#define TK_SIZE 16 /* 128-bit temporal key */
+#define P1K_SIZE 10 /* 80-bit Phase1 key */
+#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
+
+/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
+static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in ROM) */
+{
+ 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+ 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+ 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+ 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+ 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+ 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+ 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+ 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+ 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+ 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+ 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+ 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+ 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+ 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+ 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+ 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+ 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+ 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+ 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+ 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+ 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+ 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+ 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+ 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+ 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+ 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+ 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+ 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+ 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+ 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+ 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+ 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+ },
+
+ { /* second half of table is unsigned char-reversed version of first! */
+ 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
+ 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
+ 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
+ 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
+ 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
+ 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
+ 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
+ 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
+ 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
+ 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
+ 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
+ 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
+ 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
+ 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
+ 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
+ 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
+ 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
+ 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
+ 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
+ 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
+ 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
+ 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
+ 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
+ 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
+ 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
+ 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
+ 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
+ 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
+ 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
+ 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
+ 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
+ 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
+ }
+};
+
+ /*
+**********************************************************************
+* Routine: Phase 1 -- generate P1K, given TA, TK, IV32
+*
+* Inputs:
+* tk[] = temporal key [128 bits]
+* ta[] = transmitter's MAC address [ 48 bits]
+* iv32 = upper 32 bits of IV [ 32 bits]
+* Output:
+* p1k[] = Phase 1 key [ 80 bits]
+*
+* Note:
+* This function only needs to be called every 2**16 packets,
+* although in theory it could be called every packet.
+*
+**********************************************************************
+*/
+static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
+{
+ int i;
+
+ /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
+ p1k[0] = Lo16(iv32);
+ p1k[1] = Hi16(iv32);
+ p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
+ p1k[3] = Mk16(ta[3], ta[2]);
+ p1k[4] = Mk16(ta[5], ta[4]);
+
+ /* Now compute an unbalanced Feistel cipher with 80-bit block */
+ /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
+ for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add operation here is mod 2**16 */
+ p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0));
+ p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2));
+ p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4));
+ p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6));
+ p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0));
+ p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
+ }
+
+}
+
+/*
+**********************************************************************
+* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
+*
+* Inputs:
+* tk[] = Temporal key [128 bits]
+* p1k[] = Phase 1 output key [ 80 bits]
+* iv16 = low 16 bits of IV counter [ 16 bits]
+* Output:
+* rc4key[] = the key used to encrypt the packet [128 bits]
+*
+* Note:
+* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique
+* across all packets using the same key TK value. Then, for a
+* given value of TK[], this TKIP48 construction guarantees that
+* the final RC4KEY value is unique across all packets.
+*
+* Suggested implementation optimization: if PPK[] is "overlaid"
+* appropriately on RC4KEY[], there is no need for the final
+* for loop below that copies the PPK[] result into RC4KEY[].
+*
+**********************************************************************
+*/
+static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
+{
+ int i;
+ u16 PPK[6]; /* temporary key for mixing */
+
+ /* Note: all adds in the PPK[] equations below are mod 2**16 */
+ for (i = 0; i < 5; i++)
+ PPK[i] = p1k[i]; /* first, copy P1K to PPK */
+ PPK[5] = p1k[4] + iv16; /* next, add in IV16 */
+
+ /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
+ PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
+ PPK[1] += _S_(PPK[0] ^ TK16(1));
+ PPK[2] += _S_(PPK[1] ^ TK16(2));
+ PPK[3] += _S_(PPK[2] ^ TK16(3));
+ PPK[4] += _S_(PPK[3] ^ TK16(4));
+ PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
+
+ /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
+ PPK[0] += RotR1(PPK[5] ^ TK16(6));
+ PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
+ PPK[2] += RotR1(PPK[1]);
+ PPK[3] += RotR1(PPK[2]);
+ PPK[4] += RotR1(PPK[3]);
+ PPK[5] += RotR1(PPK[4]);
+ /* Note: At this point, for a given key TK[0..15], the 96-bit output */
+ /* value PPK[0..5] is guaranteed to be unique, as a function */
+ /* of the 96-bit "input" value {TA, IV32, IV16}. That is, P1K */
+ /* is now a keyed permutation of {TA, IV32, IV16}. */
+
+ /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */
+ rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */
+ rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
+ rc4key[2] = Lo8(iv16);
+ rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
+
+ /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */
+ for (i = 0; i < 6; i++) {
+ rc4key[4 + 2 * i] = Lo8(PPK[i]);
+ rc4key[5 + 2 * i] = Hi8(PPK[i]);
+ }
+
+}
+
+/* The hlen isn't include the IV */
+u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
+{ /* exclude ICV */
+ u16 pnl;
+ u32 pnh;
+ u8 rc4key[16];
+ u8 ttkey[16];
+ union {
+ __le32 f0;
+ u8 f1[4];
+ } crc;
+ u8 hw_hdr_offset = 0;
+ struct arc4context mycontext;
+ int curfragnum, length;
+
+ u8 *pframe, *payload, *iv, *prwskey;
+ union pn48 dot11txpn;
+ struct sta_info *stainfo;
+ struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ u32 res = _SUCCESS;
+
+ if (!((struct xmit_frame *)pxmitframe)->buf_addr)
+ return _FAIL;
+
+ hw_hdr_offset = TXDESC_SIZE +
+ (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);
+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
+ /* 4 start to encrypt each fragment */
+ if (pattrib->encrypt == _TKIP_) {
+ if (pattrib->psta)
+ stainfo = pattrib->psta;
+ else
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]);
+
+ if (stainfo) {
+ if (is_multicast_ether_addr(pattrib->ra))
+ prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+ else
+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+
+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
+ iv = pframe + pattrib->hdrlen;
+ payload = pframe + pattrib->iv_len + pattrib->hdrlen;
+
+ GET_TKIP_PN(iv, dot11txpn);
+
+ pnl = (u16)(dot11txpn.val);
+ pnh = (u32)(dot11txpn.val >> 16);
+ phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh);
+ phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
+
+ if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */
+ length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
+
+ arcfour_init(&mycontext, rc4key, 16);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+ arcfour_encrypt(&mycontext, payload + length, crc.f1, 4);
+ } else {
+ length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
+
+ arcfour_init(&mycontext, rc4key, 16);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+ arcfour_encrypt(&mycontext, payload + length, crc.f1, 4);
+
+ pframe += pxmitpriv->frag_len;
+ pframe = (u8 *)RND4((size_t)(pframe));
+ }
+ }
+ } else {
+ res = _FAIL;
+ }
+ }
+
+ return res;
+}
+
+/* The hlen isn't include the IV */
+u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
+{ /* exclude ICV */
+ u16 pnl;
+ u32 pnh;
+ u8 rc4key[16];
+ u8 ttkey[16];
+ union {
+ __le32 f0;
+ u8 f1[4];
+ } crc;
+ struct arc4context mycontext;
+ int length;
+
+ u8 *pframe, *payload, *iv, *prwskey;
+ union pn48 dot11txpn;
+ struct sta_info *stainfo;
+ struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ u32 res = _SUCCESS;
+
+ pframe = (unsigned char *)((struct recv_frame *)precvframe)->rx_data;
+
+ /* 4 start to decrypt recvframe */
+ if (prxattrib->encrypt == _TKIP_) {
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
+ if (stainfo) {
+ if (is_multicast_ether_addr(prxattrib->ra)) {
+ if (!psecuritypriv->binstallGrpkey) {
+ res = _FAIL;
+ DBG_88E("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
+ goto exit;
+ }
+ prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
+ } else {
+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+ }
+
+ iv = pframe + prxattrib->hdrlen;
+ payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
+ length = ((struct recv_frame *)precvframe)->len - prxattrib->hdrlen - prxattrib->iv_len;
+
+ GET_TKIP_PN(iv, dot11txpn);
+
+ pnl = (u16)(dot11txpn.val);
+ pnh = (u32)(dot11txpn.val >> 16);
+
+ phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh);
+ phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
+
+ /* 4 decrypt payload include icv */
+
+ arcfour_init(&mycontext, rc4key, 16);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
+
+ if (crc.f1[3] != payload[length - 1] ||
+ crc.f1[2] != payload[length - 2] ||
+ crc.f1[1] != payload[length - 3] ||
+ crc.f1[0] != payload[length - 4])
+ res = _FAIL;
+ } else {
+ res = _FAIL;
+ }
+ }
+
+exit:
+ return res;
+}
+
+/* 3 ===== AES related ===== */
+
+#define MAX_MSG_SIZE 2048
+/*****************************/
+/******** SBOX Table *********/
+/*****************************/
+
+static u8 sbox_table[256] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+/*****************************/
+/**** Function Prototypes ****/
+/*****************************/
+
+static void bitwise_xor(u8 *ina, u8 *inb, u8 *out);
+static void construct_mic_iv(u8 *mic_header1, int qc_exists, int a4_exists, u8 *mpdu, uint payload_length, u8 *pn_vector);
+static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu);
+static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int qc_exists);
+static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, u8 *mpdu, u8 *pn_vector, int c);
+static void xor_128(u8 *a, u8 *b, u8 *out);
+static void xor_32(u8 *a, u8 *b, u8 *out);
+static u8 sbox(u8 a);
+static void next_key(u8 *key, int round);
+static void byte_sub(u8 *in, u8 *out);
+static void shift_row(u8 *in, u8 *out);
+static void mix_column(u8 *in, u8 *out);
+static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext);
+
+/****************************************/
+/* aes128k128d() */
+/* Performs a 128 bit AES encrypt with */
+/* 128 bit data. */
+/****************************************/
+static void xor_128(u8 *a, u8 *b, u8 *out)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ out[i] = a[i] ^ b[i];
+
+}
+
+static void xor_32(u8 *a, u8 *b, u8 *out)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ out[i] = a[i] ^ b[i];
+
+}
+
+static u8 sbox(u8 a)
+{
+ return sbox_table[(int)a];
+}
+
+static void next_key(u8 *key, int round)
+{
+ u8 rcon;
+ u8 sbox_key[4];
+ u8 rcon_table[12] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+ 0x1b, 0x36, 0x36, 0x36
+ };
+
+ sbox_key[0] = sbox(key[13]);
+ sbox_key[1] = sbox(key[14]);
+ sbox_key[2] = sbox(key[15]);
+ sbox_key[3] = sbox(key[12]);
+
+ rcon = rcon_table[round];
+
+ xor_32(&key[0], sbox_key, &key[0]);
+ key[0] = key[0] ^ rcon;
+
+ xor_32(&key[4], &key[0], &key[4]);
+ xor_32(&key[8], &key[4], &key[8]);
+ xor_32(&key[12], &key[8], &key[12]);
+
+}
+
+static void byte_sub(u8 *in, u8 *out)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ out[i] = sbox(in[i]);
+
+}
+
+static void shift_row(u8 *in, u8 *out)
+{
+
+ out[0] = in[0];
+ out[1] = in[5];
+ out[2] = in[10];
+ out[3] = in[15];
+ out[4] = in[4];
+ out[5] = in[9];
+ out[6] = in[14];
+ out[7] = in[3];
+ out[8] = in[8];
+ out[9] = in[13];
+ out[10] = in[2];
+ out[11] = in[7];
+ out[12] = in[12];
+ out[13] = in[1];
+ out[14] = in[6];
+ out[15] = in[11];
+
+}
+
+static void mix_column(u8 *in, u8 *out)
+{
+ int i;
+ u8 add1b[4];
+ u8 add1bf7[4];
+ u8 rotl[4];
+ u8 swap_halfs[4];
+ u8 andf7[4];
+ u8 rotr[4];
+ u8 temp[4];
+ u8 tempb[4];
+
+ for (i = 0 ; i < 4; i++) {
+ if ((in[i] & 0x80) == 0x80)
+ add1b[i] = 0x1b;
+ else
+ add1b[i] = 0x00;
+ }
+
+ swap_halfs[0] = in[2]; /* Swap halves */
+ swap_halfs[1] = in[3];
+ swap_halfs[2] = in[0];
+ swap_halfs[3] = in[1];
+
+ rotl[0] = in[3]; /* Rotate left 8 bits */
+ rotl[1] = in[0];
+ rotl[2] = in[1];
+ rotl[3] = in[2];
+
+ andf7[0] = in[0] & 0x7f;
+ andf7[1] = in[1] & 0x7f;
+ andf7[2] = in[2] & 0x7f;
+ andf7[3] = in[3] & 0x7f;
+
+ for (i = 3; i > 0; i--) { /* logical shift left 1 bit */
+ andf7[i] = andf7[i] << 1;
+ if ((andf7[i - 1] & 0x80) == 0x80)
+ andf7[i] = (andf7[i] | 0x01);
+ }
+ andf7[0] = andf7[0] << 1;
+ andf7[0] = andf7[0] & 0xfe;
+
+ xor_32(add1b, andf7, add1bf7);
+
+ xor_32(in, add1bf7, rotr);
+
+ temp[0] = rotr[0]; /* Rotate right 8 bits */
+ rotr[0] = rotr[1];
+ rotr[1] = rotr[2];
+ rotr[2] = rotr[3];
+ rotr[3] = temp[0];
+
+ xor_32(add1bf7, rotr, temp);
+ xor_32(swap_halfs, rotl, tempb);
+ xor_32(temp, tempb, out);
+
+}
+
+static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
+{
+ int round;
+ int i;
+ u8 intermediatea[16];
+ u8 intermediateb[16];
+ u8 round_key[16];
+
+ for (i = 0; i < 16; i++)
+ round_key[i] = key[i];
+ for (round = 0; round < 11; round++) {
+ if (round == 0) {
+ xor_128(round_key, data, ciphertext);
+ next_key(round_key, round);
+ } else if (round == 10) {
+ byte_sub(ciphertext, intermediatea);
+ shift_row(intermediatea, intermediateb);
+ xor_128(intermediateb, round_key, ciphertext);
+ } else { /* 1 - 9 */
+ byte_sub(ciphertext, intermediatea);
+ shift_row(intermediatea, intermediateb);
+ mix_column(&intermediateb[0], &intermediatea[0]);
+ mix_column(&intermediateb[4], &intermediatea[4]);
+ mix_column(&intermediateb[8], &intermediatea[8]);
+ mix_column(&intermediateb[12], &intermediatea[12]);
+ xor_128(intermediatea, round_key, ciphertext);
+ next_key(round_key, round);
+ }
+ }
+
+}
+
+/************************************************/
+/* construct_mic_iv() */
+/* Builds the MIC IV from header fields and PN */
+/************************************************/
+static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu,
+ uint payload_length, u8 *pn_vector)
+{
+ int i;
+
+ mic_iv[0] = 0x59;
+ if (qc_exists && a4_exists)
+ mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
+ if (qc_exists && !a4_exists)
+ mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
+ if (!qc_exists)
+ mic_iv[1] = 0x00;
+ for (i = 2; i < 8; i++)
+ mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
+ for (i = 8; i < 14; i++)
+ mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
+ mic_iv[14] = (unsigned char)(payload_length / 256);
+ mic_iv[15] = (unsigned char)(payload_length % 256);
+
+}
+
+/************************************************/
+/* construct_mic_header1() */
+/* Builds the first MIC header block from */
+/* header fields. */
+/************************************************/
+static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu)
+{
+
+ mic_header1[0] = (u8)((header_length - 2) / 256);
+ mic_header1[1] = (u8)((header_length - 2) % 256);
+ mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
+ mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
+ mic_header1[4] = mpdu[4]; /* A1 */
+ mic_header1[5] = mpdu[5];
+ mic_header1[6] = mpdu[6];
+ mic_header1[7] = mpdu[7];
+ mic_header1[8] = mpdu[8];
+ mic_header1[9] = mpdu[9];
+ mic_header1[10] = mpdu[10]; /* A2 */
+ mic_header1[11] = mpdu[11];
+ mic_header1[12] = mpdu[12];
+ mic_header1[13] = mpdu[13];
+ mic_header1[14] = mpdu[14];
+ mic_header1[15] = mpdu[15];
+
+}
+
+/************************************************/
+/* construct_mic_header2() */
+/* Builds the last MIC header block from */
+/* header fields. */
+/************************************************/
+static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int qc_exists)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ mic_header2[i] = 0x00;
+
+ mic_header2[0] = mpdu[16]; /* A3 */
+ mic_header2[1] = mpdu[17];
+ mic_header2[2] = mpdu[18];
+ mic_header2[3] = mpdu[19];
+ mic_header2[4] = mpdu[20];
+ mic_header2[5] = mpdu[21];
+
+ mic_header2[6] = 0x00;
+ mic_header2[7] = 0x00; /* mpdu[23]; */
+
+ if (!qc_exists && a4_exists) {
+ for (i = 0; i < 6; i++)
+ mic_header2[8 + i] = mpdu[24 + i]; /* A4 */
+ }
+
+ if (qc_exists && !a4_exists) {
+ mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
+ mic_header2[9] = mpdu[25] & 0x00;
+ }
+
+ if (qc_exists && a4_exists) {
+ for (i = 0; i < 6; i++)
+ mic_header2[8 + i] = mpdu[24 + i]; /* A4 */
+
+ mic_header2[14] = mpdu[30] & 0x0f;
+ mic_header2[15] = mpdu[31] & 0x00;
+ }
+
+}
+
+/************************************************/
+/* construct_mic_header2() */
+/* Builds the last MIC header block from */
+/* header fields. */
+/************************************************/
+static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, u8 *mpdu, u8 *pn_vector, int c)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ ctr_preload[i] = 0x00;
+ i = 0;
+
+ ctr_preload[0] = 0x01; /* flag */
+ if (qc_exists && a4_exists)
+ ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
+ if (qc_exists && !a4_exists)
+ ctr_preload[1] = mpdu[24] & 0x0f;
+
+ for (i = 2; i < 8; i++)
+ ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
+ for (i = 8; i < 14; i++)
+ ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */
+ ctr_preload[14] = (unsigned char)(c / 256); /* Ctr */
+ ctr_preload[15] = (unsigned char)(c % 256);
+
+}
+
+/************************************/
+/* bitwise_xor() */
+/* A 128 bit, bitwise exclusive or */
+/************************************/
+static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ out[i] = ina[i] ^ inb[i];
+
+}
+
+static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
+{
+ uint qc_exists, a4_exists, i, j, payload_remainder,
+ num_blocks, payload_index;
+
+ u8 pn_vector[6];
+ u8 mic_iv[16];
+ u8 mic_header1[16];
+ u8 mic_header2[16];
+ u8 ctr_preload[16];
+
+ /* Intermediate Buffers */
+ u8 chain_buffer[16];
+ u8 aes_out[16];
+ u8 padded_buffer[16];
+ u8 mic[8];
+ uint frtype = GetFrameType(pframe);
+ uint frsubtype = GetFrameSubType(pframe);
+
+ frsubtype = frsubtype >> 4;
+
+ memset((void *)mic_iv, 0, 16);
+ memset((void *)mic_header1, 0, 16);
+ memset((void *)mic_header2, 0, 16);
+ memset((void *)ctr_preload, 0, 16);
+ memset((void *)chain_buffer, 0, 16);
+ memset((void *)aes_out, 0, 16);
+ memset((void *)padded_buffer, 0, 16);
+
+ if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
+ a4_exists = 0;
+ else
+ a4_exists = 1;
+
+ if ((frtype == WIFI_DATA_CFACK) || (frtype == WIFI_DATA_CFPOLL) || (frtype == WIFI_DATA_CFACKPOLL)) {
+ qc_exists = 1;
+ if (hdrlen != WLAN_HDR_A3_QOS_LEN)
+ hdrlen += 2;
+ } else if ((frsubtype == 0x08) || (frsubtype == 0x09) || (frsubtype == 0x0a) || (frsubtype == 0x0b)) {
+ if (hdrlen != WLAN_HDR_A3_QOS_LEN)
+ hdrlen += 2;
+ qc_exists = 1;
+ } else {
+ qc_exists = 0;
+ }
+
+ pn_vector[0] = pframe[hdrlen];
+ pn_vector[1] = pframe[hdrlen + 1];
+ pn_vector[2] = pframe[hdrlen + 4];
+ pn_vector[3] = pframe[hdrlen + 5];
+ pn_vector[4] = pframe[hdrlen + 6];
+ pn_vector[5] = pframe[hdrlen + 7];
+
+ construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector);
+
+ construct_mic_header1(mic_header1, hdrlen, pframe);
+ construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists);
+
+ payload_remainder = plen % 16;
+ num_blocks = plen / 16;
+
+ /* Find start of payload */
+ payload_index = (hdrlen + 8);
+
+ /* Calculate MIC */
+ aes128k128d(key, mic_iv, aes_out);
+ bitwise_xor(aes_out, mic_header1, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+ bitwise_xor(aes_out, mic_header2, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+
+ for (i = 0; i < num_blocks; i++) {
+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */
+
+ payload_index += 16;
+ aes128k128d(key, chain_buffer, aes_out);
+ }
+
+ /* Add on the final payload block if it needs padding */
+ if (payload_remainder > 0) {
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < payload_remainder; j++)
+ padded_buffer[j] = pframe[payload_index++];/* padded_buffer[j] = message[payload_index++]; */
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+ }
+
+ for (j = 0; j < 8; j++)
+ mic[j] = aes_out[j];
+
+ /* Insert MIC into payload */
+ for (j = 0; j < 8; j++)
+ pframe[payload_index + j] = mic[j]; /* message[payload_index+j] = mic[j]; */
+
+ payload_index = hdrlen + 8;
+ for (i = 0; i < num_blocks; i++) {
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, i + 1);
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
+ for (j = 0; j < 16; j++)
+ pframe[payload_index++] = chain_buffer[j];
+ }
+
+ if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/
+ /* encrypt it and copy the unpadded part back */
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, num_blocks + 1);
+
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < payload_remainder; j++)
+ padded_buffer[j] = pframe[payload_index + j];
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ for (j = 0; j < payload_remainder; j++)
+ pframe[payload_index++] = chain_buffer[j];
+ }
+ /* Encrypt the MIC */
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, 0);
+
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < 8; j++)
+ padded_buffer[j] = pframe[j + hdrlen + 8 + plen];
+
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ for (j = 0; j < 8; j++)
+ pframe[payload_index++] = chain_buffer[j];
+
+ return _SUCCESS;
+}
+
+u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
+{ /* exclude ICV */
+
+ /*static*/
+/* unsigned char message[MAX_MSG_SIZE]; */
+
+ /* Intermediate Buffers */
+ int curfragnum, length;
+ u8 *pframe, *prwskey; /* *payload,*iv */
+ u8 hw_hdr_offset = 0;
+ struct sta_info *stainfo;
+ struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+/* uint offset = 0; */
+ u32 res = _SUCCESS;
+
+ if (!((struct xmit_frame *)pxmitframe)->buf_addr)
+ return _FAIL;
+
+ hw_hdr_offset = TXDESC_SIZE +
+ (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);
+
+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
+
+ /* 4 start to encrypt each fragment */
+ if (pattrib->encrypt == _AES_) {
+ if (pattrib->psta)
+ stainfo = pattrib->psta;
+ else
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]);
+
+ if (stainfo) {
+ if (is_multicast_ether_addr(pattrib->ra))
+ prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+ else
+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
+ if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */
+ length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
+
+ aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
+ } else {
+ length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
+
+ aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
+ pframe += pxmitpriv->frag_len;
+ pframe = (u8 *)RND4((size_t)(pframe));
+ }
+ }
+ } else {
+ res = _FAIL;
+ }
+ }
+
+ return res;
+}
+
+static int aes_decipher(u8 *key, uint hdrlen,
+ u8 *pframe, uint plen)
+{
+ static u8 message[MAX_MSG_SIZE];
+ uint qc_exists, a4_exists, i, j, payload_remainder,
+ num_blocks, payload_index;
+ int res = _SUCCESS;
+ u8 pn_vector[6];
+ u8 mic_iv[16];
+ u8 mic_header1[16];
+ u8 mic_header2[16];
+ u8 ctr_preload[16];
+
+ /* Intermediate Buffers */
+ u8 chain_buffer[16];
+ u8 aes_out[16];
+ u8 padded_buffer[16];
+ u8 mic[8];
+
+/* uint offset = 0; */
+ uint frtype = GetFrameType(pframe);
+ uint frsubtype = GetFrameSubType(pframe);
+
+ frsubtype = frsubtype >> 4;
+
+ memset((void *)mic_iv, 0, 16);
+ memset((void *)mic_header1, 0, 16);
+ memset((void *)mic_header2, 0, 16);
+ memset((void *)ctr_preload, 0, 16);
+ memset((void *)chain_buffer, 0, 16);
+ memset((void *)aes_out, 0, 16);
+ memset((void *)padded_buffer, 0, 16);
+
+ /* start to decrypt the payload */
+
+ num_blocks = (plen - 8) / 16; /* plen including llc, payload_length and mic) */
+
+ payload_remainder = (plen - 8) % 16;
+
+ pn_vector[0] = pframe[hdrlen];
+ pn_vector[1] = pframe[hdrlen + 1];
+ pn_vector[2] = pframe[hdrlen + 4];
+ pn_vector[3] = pframe[hdrlen + 5];
+ pn_vector[4] = pframe[hdrlen + 6];
+ pn_vector[5] = pframe[hdrlen + 7];
+
+ if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
+ a4_exists = 0;
+ else
+ a4_exists = 1;
+
+ if ((frtype == WIFI_DATA_CFACK) || (frtype == WIFI_DATA_CFPOLL) ||
+ (frtype == WIFI_DATA_CFACKPOLL)) {
+ qc_exists = 1;
+ if (hdrlen != WLAN_HDR_A3_QOS_LEN)
+ hdrlen += 2;
+ } else if ((frsubtype == 0x08) || (frsubtype == 0x09) ||
+ (frsubtype == 0x0a) || (frsubtype == 0x0b)) {
+ if (hdrlen != WLAN_HDR_A3_QOS_LEN)
+ hdrlen += 2;
+ qc_exists = 1;
+ } else {
+ qc_exists = 0;
+ }
+
+ /* now, decrypt pframe with hdrlen offset and plen long */
+
+ payload_index = hdrlen + 8; /* 8 is for extiv */
+
+ for (i = 0; i < num_blocks; i++) {
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, i + 1);
+
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
+
+ for (j = 0; j < 16; j++)
+ pframe[payload_index++] = chain_buffer[j];
+ }
+
+ if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/
+ /* encrypt it and copy the unpadded part back */
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, num_blocks + 1);
+
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < payload_remainder; j++)
+ padded_buffer[j] = pframe[payload_index + j];
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ for (j = 0; j < payload_remainder; j++)
+ pframe[payload_index++] = chain_buffer[j];
+ }
+
+ /* start to calculate the mic */
+ if ((hdrlen + plen + 8) <= MAX_MSG_SIZE)
+ memcpy(message, pframe, (hdrlen + plen + 8)); /* 8 is for ext iv len */
+
+ pn_vector[0] = pframe[hdrlen];
+ pn_vector[1] = pframe[hdrlen + 1];
+ pn_vector[2] = pframe[hdrlen + 4];
+ pn_vector[3] = pframe[hdrlen + 5];
+ pn_vector[4] = pframe[hdrlen + 6];
+ pn_vector[5] = pframe[hdrlen + 7];
+ construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen - 8, pn_vector);
+
+ construct_mic_header1(mic_header1, hdrlen, message);
+ construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
+
+ payload_remainder = (plen - 8) % 16;
+ num_blocks = (plen - 8) / 16;
+
+ /* Find start of payload */
+ payload_index = (hdrlen + 8);
+
+ /* Calculate MIC */
+ aes128k128d(key, mic_iv, aes_out);
+ bitwise_xor(aes_out, mic_header1, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+ bitwise_xor(aes_out, mic_header2, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+
+ for (i = 0; i < num_blocks; i++) {
+ bitwise_xor(aes_out, &message[payload_index], chain_buffer);
+
+ payload_index += 16;
+ aes128k128d(key, chain_buffer, aes_out);
+ }
+
+ /* Add on the final payload block if it needs padding */
+ if (payload_remainder > 0) {
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < payload_remainder; j++)
+ padded_buffer[j] = message[payload_index++];
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+ }
+
+ for (j = 0 ; j < 8; j++)
+ mic[j] = aes_out[j];
+
+ /* Insert MIC into payload */
+ for (j = 0; j < 8; j++)
+ message[payload_index + j] = mic[j];
+
+ payload_index = hdrlen + 8;
+ for (i = 0; i < num_blocks; i++) {
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, i + 1);
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, &message[payload_index], chain_buffer);
+ for (j = 0; j < 16; j++)
+ message[payload_index++] = chain_buffer[j];
+ }
+
+ if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/
+ /* encrypt it and copy the unpadded part back */
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, num_blocks + 1);
+
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < payload_remainder; j++)
+ padded_buffer[j] = message[payload_index + j];
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ for (j = 0; j < payload_remainder; j++)
+ message[payload_index++] = chain_buffer[j];
+ }
+
+ /* Encrypt the MIC */
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, 0);
+
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < 8; j++)
+ padded_buffer[j] = message[j + hdrlen + 8 + plen - 8];
+
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ for (j = 0; j < 8; j++)
+ message[payload_index++] = chain_buffer[j];
+
+ /* compare the mic */
+ for (i = 0; i < 8; i++) {
+ if (pframe[hdrlen + 8 + plen - 8 + i] != message[hdrlen + 8 + plen - 8 + i]) {
+ DBG_88E("aes_decipher:mic check error mic[%d]: pframe(%x)!=message(%x)\n",
+ i, pframe[hdrlen + 8 + plen - 8 + i], message[hdrlen + 8 + plen - 8 + i]);
+ res = _FAIL;
+ }
+ }
+
+ return res;
+}
+
+u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
+{ /* exclude ICV */
+ /* Intermediate Buffers */
+ int length;
+ u8 *pframe, *prwskey; /* *payload,*iv */
+ struct sta_info *stainfo;
+ struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ u32 res = _SUCCESS;
+
+ pframe = (unsigned char *)((struct recv_frame *)precvframe)->rx_data;
+ /* 4 start to encrypt each fragment */
+ if (prxattrib->encrypt == _AES_) {
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
+ if (stainfo) {
+ if (is_multicast_ether_addr(prxattrib->ra)) {
+ /* in concurrent we should use sw descrypt in group key, so we remove this message */
+ if (!psecuritypriv->binstallGrpkey) {
+ res = _FAIL;
+ DBG_88E("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
+ goto exit;
+ }
+ prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
+ if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) {
+ DBG_88E("not match packet_index=%d, install_index=%d\n",
+ prxattrib->key_index, psecuritypriv->dot118021XGrpKeyid);
+ res = _FAIL;
+ goto exit;
+ }
+ } else {
+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+ }
+ length = ((struct recv_frame *)precvframe)->len - prxattrib->hdrlen - prxattrib->iv_len;
+ res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length);
+ } else {
+ res = _FAIL;
+ }
+ }
+
+exit:
+ return res;
+}
+
+/* AES tables*/
+const u32 Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+
+const u32 Td0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+
+const u8 Td4s[256] = {
+ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+ 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+ 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+ 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+ 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+ 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+ 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+ 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+ 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+ 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+ 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+ 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+ 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+ 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+ 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+ 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+ 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+const u8 rcons[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+#define ROUND(i, d, s) \
+do { \
+ d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+ d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+ d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+ d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]; \
+} while (0);
+
+/**
+ * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
+ * @key: 128-bit key for the hash operation
+ * @data: Data buffer for which a MAC is determined
+ * @data_len: Length of data buffer in bytes
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is a mode for using block cipher (AES in this case) for authentication.
+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
+ * (SP) 800-38B.
+ */
+void rtw_use_tkipkey_handler(void *FunctionContext)
+{
+ struct adapter *padapter = (struct adapter *)FunctionContext;
+
+ padapter->securitypriv.busetkipkey = true;
+}
diff --git a/drivers/staging/r8188eu/core/rtw_sreset.c b/drivers/staging/r8188eu/core/rtw_sreset.c
new file mode 100644
index 000000000000..c831033d20a9
--- /dev/null
+++ b/drivers/staging/r8188eu/core/rtw_sreset.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#include "../include/rtw_sreset.h"
+
+void sreset_init_value(struct adapter *padapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+ _rtw_mutex_init(&psrtpriv->silentreset_mutex);
+ psrtpriv->silent_reset_inprogress = false;
+ psrtpriv->wifi_error_status = WIFI_STATUS_SUCCESS;
+ psrtpriv->last_tx_time = 0;
+ psrtpriv->last_tx_complete_time = 0;
+}
+void sreset_reset_value(struct adapter *padapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+ psrtpriv->silent_reset_inprogress = false;
+ psrtpriv->wifi_error_status = WIFI_STATUS_SUCCESS;
+ psrtpriv->last_tx_time = 0;
+ psrtpriv->last_tx_complete_time = 0;
+}
+
+u8 sreset_get_wifi_status(struct adapter *padapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+ u8 status = WIFI_STATUS_SUCCESS;
+ u32 val32 = 0;
+
+ if (psrtpriv->silent_reset_inprogress)
+ return status;
+ val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
+ if (val32 == 0xeaeaeaea) {
+ psrtpriv->wifi_error_status = WIFI_IF_NOT_EXIST;
+ } else if (val32 != 0) {
+ DBG_88E("txdmastatu(%x)\n", val32);
+ psrtpriv->wifi_error_status = WIFI_MAC_TXDMA_ERROR;
+ }
+
+ if (WIFI_STATUS_SUCCESS != psrtpriv->wifi_error_status) {
+ DBG_88E("==>%s error_status(0x%x)\n", __func__, psrtpriv->wifi_error_status);
+ status = (psrtpriv->wifi_error_status & (~(USB_READ_PORT_FAIL | USB_WRITE_PORT_FAIL)));
+ }
+ DBG_88E("==> %s wifi_status(0x%x)\n", __func__, status);
+
+ /* status restore */
+ psrtpriv->wifi_error_status = WIFI_STATUS_SUCCESS;
+
+ return status;
+}
+
+void sreset_set_wifi_error_status(struct adapter *padapter, u32 status)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ pHalData->srestpriv.wifi_error_status = status;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/r8188eu/core/rtw_sta_mgt.c
index 19eddf573fd8..f6dffed53a60 100644
--- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
+++ b/drivers/staging/r8188eu/core/rtw_sta_mgt.c
@@ -1,21 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#define _RTW_STA_MGT_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <xmit_osdep.h>
-#include <mlme_osdep.h>
-#include <sta_info.h>
-#include <linux/vmalloc.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/xmit_osdep.h"
+#include "../include/mlme_osdep.h"
+#include "../include/sta_info.h"
static void _rtw_init_stainfo(struct sta_info *psta)
{
+
memset((u8 *)psta, 0, sizeof(struct sta_info));
spin_lock_init(&psta->lock);
@@ -41,21 +38,24 @@ static void _rtw_init_stainfo(struct sta_info *psta)
psta->bpairwise_key_installed = false;
+#ifdef CONFIG_88EU_AP_MODE
psta->nonerp_set = 0;
psta->no_short_slot_time_set = 0;
psta->no_short_preamble_set = 0;
psta->no_ht_gf_set = 0;
psta->no_ht_set = 0;
psta->ht_20mhz_set = 0;
+#endif
psta->under_exist_checking = 0;
psta->keep_alive_trycnt = 0;
#endif /* CONFIG_88EU_AP_MODE */
+
}
-u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
+u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
{
struct sta_info *psta;
s32 i;
@@ -83,8 +83,7 @@ u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
INIT_LIST_HEAD(&pstapriv->sta_hash[i]);
- list_add_tail(&psta->list,
- get_list_head(&pstapriv->free_sta_queue));
+ list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
psta++;
}
@@ -114,130 +113,142 @@ inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
{
int offset = (((u8 *)sta) - stapriv->pstainfo_buf) / sizeof(struct sta_info);
+ if (!stainfo_offset_valid(offset))
+ DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
+
return offset;
}
inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
{
+ if (!stainfo_offset_valid(offset))
+ DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
+
return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
}
-u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
+u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
{
struct list_head *phead, *plist;
struct sta_info *psta = NULL;
struct recv_reorder_ctrl *preorder_ctrl;
- int index;
-
- if (!pstapriv)
- return _SUCCESS;
-
- /* delete all reordering_ctrl_timer */
- spin_lock_bh(&pstapriv->sta_hash_lock);
- for (index = 0; index < NUM_STA; index++) {
- phead = &pstapriv->sta_hash[index];
- list_for_each(plist, phead) {
- int i;
-
- psta = list_entry(plist, struct sta_info, hash_list);
-
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
+ int index;
+
+ if (pstapriv) {
+ /* delete all reordering_ctrl_timer */
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ for (index = 0; index < NUM_STA; index++) {
+ phead = &pstapriv->sta_hash[index];
+ plist = phead->next;
+
+ while (phead != plist) {
+ int i;
+ psta = container_of(plist, struct sta_info, hash_list);
+ plist = plist->next;
+
+ for (i = 0; i < 16; i++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
+ _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
+ }
}
}
- }
- spin_unlock_bh(&pstapriv->sta_hash_lock);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+ /*===============================*/
- vfree(pstapriv->pallocated_stainfo_buf);
+ if (pstapriv->pallocated_stainfo_buf)
+ vfree(pstapriv->pallocated_stainfo_buf);
+ }
return _SUCCESS;
}
-struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
+struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
{
- s32 index;
+ s32 index;
struct list_head *phash_list;
- struct sta_info *psta;
+ struct sta_info *psta;
struct __queue *pfree_sta_queue;
struct recv_reorder_ctrl *preorder_ctrl;
int i = 0;
- u16 wRxSeqInitialValue = 0xffff;
+ u16 wRxSeqInitialValue = 0xffff;
pfree_sta_queue = &pstapriv->free_sta_queue;
spin_lock_bh(&pfree_sta_queue->lock);
- psta = list_first_entry_or_null(&pfree_sta_queue->queue,
- struct sta_info, list);
- if (!psta) {
+
+ if (list_empty(&pfree_sta_queue->queue)) {
spin_unlock_bh(&pfree_sta_queue->lock);
- return NULL;
- }
+ psta = NULL;
+ } else {
+ psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
+ list_del_init(&psta->list);
+ spin_unlock_bh(&pfree_sta_queue->lock);
+ _rtw_init_stainfo(psta);
+ memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
+ index = wifi_mac_hash(hwaddr);
+ if (index >= NUM_STA) {
+ psta = NULL;
+ goto exit;
+ }
+ phash_list = &pstapriv->sta_hash[index];
- list_del_init(&psta->list);
- spin_unlock_bh(&pfree_sta_queue->lock);
- _rtw_init_stainfo(psta);
- memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
- index = wifi_mac_hash(hwaddr);
- if (index >= NUM_STA)
- return NULL;
- phash_list = &pstapriv->sta_hash[index];
+ spin_lock_bh(&pstapriv->sta_hash_lock);
- spin_lock_bh(&pstapriv->sta_hash_lock);
- list_add_tail(&psta->hash_list, phash_list);
- pstapriv->asoc_sta_count++;
- spin_unlock_bh(&pstapriv->sta_hash_lock);
+ list_add_tail(&psta->hash_list, phash_list);
- /* Commented by Albert 2009/08/13
- * For the SMC router, the sequence number of first packet of
- * WPS handshake will be 0. In this case, this packet will be
- * dropped by recv_decache function if we use the 0x00 as the
- * default value for tid_rxseq variable. So, we initialize the
- * tid_rxseq variable as the 0xffff.
- */
+ pstapriv->asoc_sta_count++;
- for (i = 0; i < 16; i++)
- memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
- &wRxSeqInitialValue, 2);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
- init_addba_retry_timer(pstapriv->padapter, psta);
+/* Commented by Albert 2009/08/13 */
+/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
+/* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
+/* So, we initialize the tid_rxseq variable as the 0xffff. */
- /* for A-MPDU Rx reordering buffer control */
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
+ for (i = 0; i < 16; i++)
+ memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
- preorder_ctrl->padapter = pstapriv->padapter;
+ init_addba_retry_timer(pstapriv->padapter, psta);
- preorder_ctrl->enable = false;
+ /* for A-MPDU Rx reordering buffer control */
+ for (i = 0; i < 16; i++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
- preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->wend_b = 0xffff;
- preorder_ctrl->wsize_b = 64;/* 64; */
+ preorder_ctrl->padapter = pstapriv->padapter;
- _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
+ preorder_ctrl->enable = false;
- rtw_init_recv_timer(preorder_ctrl);
- }
+ preorder_ctrl->indicate_seq = 0xffff;
+ preorder_ctrl->wend_b = 0xffff;
+ preorder_ctrl->wsize_b = 64;/* 64; */
- /* init for DM */
- psta->rssi_stat.UndecoratedSmoothedPWDB = -1;
- psta->rssi_stat.UndecoratedSmoothedCCK = -1;
+ _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
- /* init for the sequence number of received management frame */
- psta->RxMgmtFrameSeqNum = 0xffff;
+ rtw_init_recv_timer(preorder_ctrl);
+ }
+
+ /* init for DM */
+ psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
+ psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
+
+ /* init for the sequence number of received management frame */
+ psta->RxMgmtFrameSeqNum = 0xffff;
+ }
+
+exit:
return psta;
}
/* using pstapriv->sta_hash_lock to protect */
-u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
+u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
{
int i;
struct __queue *pfree_sta_queue;
struct recv_reorder_ctrl *preorder_ctrl;
- struct sta_xmit_priv *pstaxmitpriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_xmit_priv *pstaxmitpriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
if (!psta)
goto exit;
@@ -276,12 +287,10 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
- del_timer_sync(&psta->addba_retry_timer);
+ _cancel_timer_ex(&psta->addba_retry_timer);
- /* for A-MPDU Rx reordering buffer control, cancel
- * reordering_ctrl_timer
- */
- for (i = 0; i < 16; i++) {
+ /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
+ for (i = 0; i < 16 ; i++) {
struct list_head *phead, *plist;
struct recv_frame *prframe;
struct __queue *ppending_recvframe_queue;
@@ -289,13 +298,13 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
preorder_ctrl = &psta->recvreorder_ctrl[i];
- del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
+ _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
spin_lock_bh(&ppending_recvframe_queue->lock);
- phead = get_list_head(ppending_recvframe_queue);
+ phead = get_list_head(ppending_recvframe_queue);
plist = phead->next;
while (!list_empty(phead)) {
@@ -359,10 +368,10 @@ exit:
/* free all stainfo which in sta_hash[all] */
void rtw_free_all_stainfo(struct adapter *padapter)
{
- struct list_head *phead;
- s32 index;
- struct sta_info *psta, *temp;
- struct sta_priv *pstapriv = &padapter->stapriv;
+ struct list_head *plist, *phead;
+ s32 index;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
if (pstapriv->asoc_sta_count == 1)
@@ -372,7 +381,13 @@ void rtw_free_all_stainfo(struct adapter *padapter)
for (index = 0; index < NUM_STA; index++) {
phead = &pstapriv->sta_hash[index];
- list_for_each_entry_safe(psta, temp, phead, hash_list) {
+ plist = phead->next;
+
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, hash_list);
+
+ plist = plist->next;
+
if (pbcmc_stainfo != psta)
rtw_free_stainfo(padapter, psta);
}
@@ -385,14 +400,14 @@ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
{
struct list_head *plist, *phead;
struct sta_info *psta = NULL;
- u32 index;
+ u32 index;
u8 *addr;
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if (!hwaddr)
return NULL;
- if (is_multicast_ether_addr(hwaddr))
+ if (IS_MCAST(hwaddr))
addr = bc_addr;
else
addr = hwaddr;
@@ -402,60 +417,74 @@ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
spin_lock_bh(&pstapriv->sta_hash_lock);
phead = &pstapriv->sta_hash[index];
- list_for_each(plist, phead) {
- psta = list_entry(plist, struct sta_info, hash_list);
+ plist = phead->next;
+
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, hash_list);
- if (!memcmp(psta->hwaddr, addr, ETH_ALEN)) {
+ if ((!memcmp(psta->hwaddr, addr, ETH_ALEN))) {
/* if found the matched address */
break;
}
psta = NULL;
+ plist = plist->next;
}
spin_unlock_bh(&pstapriv->sta_hash_lock);
+
return psta;
}
u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
{
- struct sta_info *psta;
- u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *psta;
+ u32 res = _SUCCESS;
+ unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ struct sta_priv *pstapriv = &padapter->stapriv;
- psta = rtw_alloc_stainfo(pstapriv, bc_addr);
+ psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
- if (!psta)
- return _FAIL;
+ if (!psta) {
+ res = _FAIL;
+ goto exit;
+ }
/* default broadcast & multicast use macid 1 */
psta->mac_id = 1;
- return _SUCCESS;
+exit:
+
+ return res;
}
struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
{
- struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- return rtw_get_stainfo(pstapriv, bc_addr);
+ psta = rtw_get_stainfo(pstapriv, bc_addr);
+
+ return psta;
}
-bool rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
+u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
{
- bool res = true;
+ u8 res = true;
#ifdef CONFIG_88EU_AP_MODE
struct list_head *plist, *phead;
struct rtw_wlan_acl_node *paclnode;
- bool match = false;
+ u8 match = false;
struct sta_priv *pstapriv = &padapter->stapriv;
struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
struct __queue *pacl_node_q = &pacl_list->acl_node_q;
spin_lock_bh(&pacl_node_q->lock);
phead = get_list_head(pacl_node_q);
- list_for_each(plist, phead) {
- paclnode = list_entry(plist, struct rtw_wlan_acl_node, list);
+ plist = phead->next;
+ while (phead != plist) {
+ paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+ plist = plist->next;
if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
if (paclnode->valid) {
@@ -467,9 +496,9 @@ bool rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
spin_unlock_bh(&pacl_node_q->lock);
if (pacl_list->mode == 1)/* accept unless in deny list */
- res = !match;
+ res = (match) ? false : true;
else if (pacl_list->mode == 2)/* deny unless in accept list */
- res = match;
+ res = (match) ? true : false;
else
res = true;
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/r8188eu/core/rtw_wlan_util.c
index 2d4776debb97..a3a5e1c64c4a 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/r8188eu/core/rtw_wlan_util.c
@@ -1,133 +1,173 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
#define _RTW_WLAN_UTIL_C_
-#include <linux/ieee80211.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/wifi.h"
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <wifi.h>
+static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
+static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
-static const u8 ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
-static const u8 ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
+static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
+static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
-static const u8 BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
-static const u8 BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
+static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96};
+static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43};
+static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43};
+static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
+static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
+static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c};
-static const u8 CISCO_OUI[] = {0x00, 0x40, 0x96};
-static const u8 MARVELL_OUI[] = {0x00, 0x50, 0x43};
-static const u8 RALINK_OUI[] = {0x00, 0x0c, 0x43};
-static const u8 REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
-static const u8 AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
-static const u8 EPIGRAM_OUI[] = {0x00, 0x90, 0x4c};
+unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
-u8 REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
+#define R2T_PHY_DELAY (0)
+/* define WAIT_FOR_BCN_TO_M (3000) */
#define WAIT_FOR_BCN_TO_MIN (6000)
#define WAIT_FOR_BCN_TO_MAX (20000)
-static const u8 rtw_basic_rate_cck[4] = {
- IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
+static u8 rtw_basic_rate_cck[4] = {
+ IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
};
-static const u8 rtw_basic_rate_ofdm[3] = {
- IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
+static u8 rtw_basic_rate_ofdm[3] = {
+ IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
};
-static const u8 rtw_basic_rate_mix[7] = {
- IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
+static u8 rtw_basic_rate_mix[7] = {
+ IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
};
+int cckrates_included(unsigned char *rate, int ratelen)
+{
+ int i;
+
+ for (i = 0; i < ratelen; i++) {
+ if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
+ (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
+ return true;
+ }
+ return false;
+}
+
+int cckratesonly_included(unsigned char *rate, int ratelen)
+{
+ int i;
+
+ for (i = 0; i < ratelen; i++) {
+ if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
+ (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
+ return false;
+ }
+
+ return true;
+}
+
unsigned char networktype_to_raid(unsigned char network_type)
{
+ unsigned char raid;
+
switch (network_type) {
case WIRELESS_11B:
- return RATR_INX_WIRELESS_B;
- case WIRELESS_11A:
+ raid = RATR_INX_WIRELESS_B;
+ break;
case WIRELESS_11G:
- return RATR_INX_WIRELESS_G;
+ raid = RATR_INX_WIRELESS_G;
+ break;
case WIRELESS_11BG:
- return RATR_INX_WIRELESS_GB;
+ raid = RATR_INX_WIRELESS_GB;
+ break;
case WIRELESS_11_24N:
- case WIRELESS_11_5N:
- return RATR_INX_WIRELESS_N;
- case WIRELESS_11A_5N:
+ raid = RATR_INX_WIRELESS_N;
+ break;
case WIRELESS_11G_24N:
- return RATR_INX_WIRELESS_NG;
+ raid = RATR_INX_WIRELESS_NG;
+ break;
case WIRELESS_11BG_24N:
- return RATR_INX_WIRELESS_NGB;
+ raid = RATR_INX_WIRELESS_NGB;
+ break;
default:
- return RATR_INX_WIRELESS_GB;
+ raid = RATR_INX_WIRELESS_GB;
+ break;
}
+ return raid;
}
-u8 judge_network_type(struct adapter *padapter, unsigned char *rate)
+u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int ratelen)
{
u8 network_type = 0;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- if (pmlmeinfo->HT_enable)
- network_type = WIRELESS_11_24N;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- if (rtw_is_cckratesonly_included(rate))
- network_type |= WIRELESS_11B;
- else if (rtw_is_cckrates_included(rate))
- network_type |= WIRELESS_11BG;
- else
- network_type |= WIRELESS_11G;
-
- return network_type;
+ if (pmlmeext->cur_channel > 14) {
+ network_type |= WIRELESS_INVALID;
+ } else {
+ if (pmlmeinfo->HT_enable)
+ network_type = WIRELESS_11_24N;
+
+ if (cckratesonly_included(rate, ratelen))
+ network_type |= WIRELESS_11B;
+ else if (cckrates_included(rate, ratelen))
+ network_type |= WIRELESS_11BG;
+ else
+ network_type |= WIRELESS_11G;
+ }
+ return network_type;
}
static unsigned char ratetbl_val_2wifirate(unsigned char rate)
{
+ unsigned char val = 0;
+
switch (rate & 0x7f) {
case 0:
- return IEEE80211_CCK_RATE_1MB;
+ val = IEEE80211_CCK_RATE_1MB;
+ break;
case 1:
- return IEEE80211_CCK_RATE_2MB;
+ val = IEEE80211_CCK_RATE_2MB;
+ break;
case 2:
- return IEEE80211_CCK_RATE_5MB;
+ val = IEEE80211_CCK_RATE_5MB;
+ break;
case 3:
- return IEEE80211_CCK_RATE_11MB;
+ val = IEEE80211_CCK_RATE_11MB;
+ break;
case 4:
- return IEEE80211_OFDM_RATE_6MB;
+ val = IEEE80211_OFDM_RATE_6MB;
+ break;
case 5:
- return IEEE80211_OFDM_RATE_9MB;
+ val = IEEE80211_OFDM_RATE_9MB;
+ break;
case 6:
- return IEEE80211_OFDM_RATE_12MB;
+ val = IEEE80211_OFDM_RATE_12MB;
+ break;
case 7:
- return IEEE80211_OFDM_RATE_18MB;
+ val = IEEE80211_OFDM_RATE_18MB;
+ break;
case 8:
- return IEEE80211_OFDM_RATE_24MB;
+ val = IEEE80211_OFDM_RATE_24MB;
+ break;
case 9:
- return IEEE80211_OFDM_RATE_36MB;
+ val = IEEE80211_OFDM_RATE_36MB;
+ break;
case 10:
- return IEEE80211_OFDM_RATE_48MB;
+ val = IEEE80211_OFDM_RATE_48MB;
+ break;
case 11:
- return IEEE80211_OFDM_RATE_54MB;
- default:
- return 0;
+ val = IEEE80211_OFDM_RATE_54MB;
+ break;
}
+ return val;
}
-static bool is_basicrate(struct adapter *padapter, unsigned char rate)
+static int is_basicrate(struct adapter *padapter, unsigned char rate)
{
int i;
unsigned char val;
@@ -148,7 +188,7 @@ static unsigned int ratetbl2rateset(struct adapter *padapter, unsigned char *rat
{
int i;
unsigned char rate;
- unsigned int len = 0;
+ unsigned int len = 0;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
for (i = 0; i < NumRates; i++) {
@@ -184,8 +224,8 @@ void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *bssrat
void UpdateBrateTbl(struct adapter *Adapter, u8 *mbrate)
{
- u8 i;
- u8 rate;
+ u8 i;
+ u8 rate;
/* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
@@ -206,8 +246,8 @@ void UpdateBrateTbl(struct adapter *Adapter, u8 *mbrate)
void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
{
- u8 i;
- u8 rate;
+ u8 i;
+ u8 rate;
for (i = 0; i < bssratelen; i++) {
rate = bssrateset[i] & 0x7f;
@@ -224,14 +264,14 @@ void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
void Save_DM_Func_Flag(struct adapter *padapter)
{
- u8 saveflag = true;
+ u8 saveflag = true;
rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&saveflag));
}
void Restore_DM_Func_Flag(struct adapter *padapter)
{
- u8 saveflag = false;
+ u8 saveflag = false;
rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&saveflag));
}
@@ -244,11 +284,16 @@ void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable)
rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
}
-void Set_MSR(struct adapter *padapter, u8 type)
+static void Set_NETYPE0_MSR(struct adapter *padapter, u8 type)
{
rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
}
+void Set_MSR(struct adapter *padapter, u8 type)
+{
+ Set_NETYPE0_MSR(padapter, type);
+}
+
inline u8 rtw_get_oper_ch(struct adapter *adapter)
{
return adapter->mlmeextpriv.oper_channel;
@@ -259,11 +304,21 @@ inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch)
adapter->mlmeextpriv.oper_channel = ch;
}
+inline u8 rtw_get_oper_bw(struct adapter *adapter)
+{
+ return adapter->mlmeextpriv.oper_bwmode;
+}
+
inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw)
{
adapter->mlmeextpriv.oper_bwmode = bw;
}
+inline u8 rtw_get_oper_choffset(struct adapter *adapter)
+{
+ return adapter->mlmeextpriv.oper_ch_offset;
+}
+
inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset)
{
adapter->mlmeextpriv.oper_ch_offset = offset;
@@ -290,6 +345,9 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigne
{
u8 center_ch;
+ if (padapter->bNotifyChannelChange)
+ DBG_88E("[%s] ch = %d, offset = %d, bwmode = %d\n", __func__, channel, channel_offset, bwmode);
+
if ((bwmode == HT_CHANNEL_WIDTH_20) ||
(channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {
/* SelectChannel(padapter, channel); */
@@ -315,19 +373,33 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigne
SetBWMode(padapter, bwmode, channel_offset);
}
+int get_bsstype(unsigned short capability)
+{
+ if (capability & BIT(0))
+ return WIFI_FW_AP_STATE;
+ else if (capability & BIT(1))
+ return WIFI_FW_ADHOC_STATE;
+ else
+ return 0;
+}
+
+__inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork)
+{
+ return pnetwork->MacAddress;
+}
+
u16 get_beacon_interval(struct wlan_bssid_ex *bss)
{
__le16 val;
-
- memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->ies), 2);
+ memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->IEs), 2);
return le16_to_cpu(val);
}
int is_client_associated_to_ap(struct adapter *padapter)
{
- struct mlme_ext_priv *pmlmeext;
- struct mlme_ext_info *pmlmeinfo;
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
if (!padapter)
return _FAIL;
@@ -335,8 +407,7 @@ int is_client_associated_to_ap(struct adapter *padapter)
pmlmeext = &padapter->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
- if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
- (pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+ if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE))
return true;
else
return _FAIL;
@@ -344,11 +415,10 @@ int is_client_associated_to_ap(struct adapter *padapter)
int is_client_associated_to_ibss(struct adapter *padapter)
{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
- (pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)
+ if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE))
return true;
else
return _FAIL;
@@ -357,8 +427,8 @@ int is_client_associated_to_ibss(struct adapter *padapter)
int is_IBSS_empty(struct adapter *padapter)
{
unsigned int i;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
if (pmlmeinfo->FW_sta_info[i].status == 1)
@@ -377,6 +447,11 @@ unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval)
return bcn_interval << 2;
}
+void CAM_empty_entry(struct adapter *Adapter, u8 ucIndex)
+{
+ rtw_hal_set_hwreg(Adapter, HW_VAR_CAM_EMPTY_ENTRY, (u8 *)(&ucIndex));
+}
+
void invalidate_cam_all(struct adapter *padapter)
{
rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
@@ -384,24 +459,23 @@ void invalidate_cam_all(struct adapter *padapter)
void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
{
- unsigned int i, val, addr;
+ unsigned int i, val, addr;
int j;
- u32 cam_val[2];
+ u32 cam_val[2];
addr = entry << 3;
for (j = 5; j >= 0; j--) {
switch (j) {
case 0:
- val = ctrl | (mac[0] << 16) | (mac[1] << 24);
+ val = (ctrl | (mac[0] << 16) | (mac[1] << 24));
break;
case 1:
- val = mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24);
+ val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
break;
default:
i = (j - 2) << 2;
- val = key[i] | (key[i + 1] << 8) | (key[i + 2] << 16) |
- (key[i + 3] << 24);
+ val = (key[i] | (key[i + 1] << 8) | (key[i + 2] << 16) | (key[i + 3] << 24));
break;
}
@@ -414,8 +488,9 @@ void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
void clear_cam_entry(struct adapter *padapter, u8 entry)
{
- u8 null_sta[ETH_ALEN] = {};
- u8 null_key[16] = {};
+ unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
write_cam(padapter, entry, 0, null_sta, null_key);
}
@@ -423,8 +498,8 @@ void clear_cam_entry(struct adapter *padapter, u8 entry)
int allocate_fw_sta_entry(struct adapter *padapter)
{
unsigned int mac_id;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
@@ -439,8 +514,8 @@ int allocate_fw_sta_entry(struct adapter *padapter)
void flush_all_cam_entry(struct adapter *padapter)
{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
@@ -449,9 +524,10 @@ void flush_all_cam_entry(struct adapter *padapter)
int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ /* struct registry_priv *pregpriv = &padapter->registrypriv; */
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
if (pmlmepriv->qospriv.qos_option == 0) {
pmlmeinfo->WMM_enable = 0;
@@ -465,15 +541,15 @@ int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
void WMMOnAssocRsp(struct adapter *padapter)
{
- u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
- u8 acm_mask;
- u16 TXOP;
- u32 acParm, i;
- u32 edca[4], inx[4];
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct registry_priv *pregpriv = &padapter->registrypriv;
+ u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
+ u8 acm_mask;
+ u16 TXOP;
+ u32 acParm, i;
+ u32 edca[4], inx[4];
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
if (pmlmeinfo->WMM_enable == 0) {
padapter->mlmepriv.acm_mask = 0;
@@ -494,7 +570,7 @@ void WMMOnAssocRsp(struct adapter *padapter)
/* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
- ECWMin = pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f;
+ ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f);
ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
@@ -521,6 +597,8 @@ void WMMOnAssocRsp(struct adapter *padapter)
edca[XMIT_VO_QUEUE] = acParm;
break;
}
+
+ DBG_88E("WMM(%x): %x, %x\n", ACI, ACM, acParm);
}
if (padapter->registrypriv.acm_method == 1)
@@ -531,7 +609,7 @@ void WMMOnAssocRsp(struct adapter *padapter)
inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
if (pregpriv->wifi_spec == 1) {
- u32 j, change_inx = false;
+ u32 j, tmp, change_inx = false;
/* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
for (i = 0; i < 4; i++) {
@@ -546,28 +624,36 @@ void WMMOnAssocRsp(struct adapter *padapter)
}
if (change_inx) {
- swap(edca[i], edca[j]);
- swap(inx[i], inx[j]);
+ tmp = edca[i];
+ edca[i] = edca[j];
+ edca[j] = tmp;
+
+ tmp = inx[i];
+ inx[i] = inx[j];
+ inx[j] = tmp;
+
change_inx = false;
}
}
}
}
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++) {
pxmitpriv->wmm_para_seq[i] = inx[i];
+ DBG_88E("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
+ }
}
static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
{
- unsigned char new_bwmode;
- unsigned char new_ch_offset;
- struct HT_info_element *pHT_info;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ unsigned char new_bwmode;
+ unsigned char new_ch_offset;
+ struct HT_info_element *pHT_info;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
if (!pIE)
return;
@@ -617,6 +703,8 @@ static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var
struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
struct sta_priv *pstapriv = &padapter->stapriv;
+ /* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
+
/* update ap's stainfo */
psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
if (psta) {
@@ -636,13 +724,13 @@ static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var
void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
{
- unsigned int i;
- u8 max_ampdu_len, min_mpdu_spacing;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- u8 *HT_cap = (u8 *)(&pmlmeinfo->HT_caps);
+ unsigned int i;
+ u8 rf_type;
+ u8 max_AMPDU_len, min_MPDU_spacing;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
if (!pIE)
return;
@@ -654,35 +742,41 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
for (i = 0; i < (pIE->Length); i++) {
if (i != 2) {
- /* Got the endian issue here. */
- HT_cap[i] &= (pIE->data[i]);
+ /* Got the endian issue here. */
+ pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
} else {
/* modify from fw by Thomas 2010/11/17 */
- if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x3) > (pIE->data[i] & 0x3))
- max_ampdu_len = pIE->data[i] & 0x3;
+ if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3))
+ max_AMPDU_len = (pIE->data[i] & 0x3);
else
- max_ampdu_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x3;
+ max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
- if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) > (pIE->data[i] & 0x1c))
- min_mpdu_spacing = pmlmeinfo->HT_caps.ampdu_params_info & 0x1c;
+ if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c))
+ min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
else
- min_mpdu_spacing = pIE->data[i] & 0x1c;
+ min_MPDU_spacing = (pIE->data[i] & 0x1c);
- pmlmeinfo->HT_caps.ampdu_params_info = max_ampdu_len | min_mpdu_spacing;
+ pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
}
}
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
/* update the MCS rates */
- for (i = 0; i < 16; i++)
- ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i];
+ for (i = 0; i < 16; i++) {
+ if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
+ pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
+ else
+ pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i];
+ }
}
void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
if (!pIE)
return;
@@ -699,10 +793,13 @@ void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
void HTOnAssocRsp(struct adapter *padapter)
{
- u8 max_ampdu_len;
- u8 min_mpdu_spacing;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ unsigned char max_AMPDU_len;
+ unsigned char min_MPDU_spacing;
+ /* struct registry_priv *pregpriv = &padapter->registrypriv; */
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ DBG_88E("%s\n", __func__);
if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) {
pmlmeinfo->HT_enable = 1;
@@ -711,22 +808,24 @@ void HTOnAssocRsp(struct adapter *padapter)
return;
}
- /* handle A-MPDU parameter field
- *
- * AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
- * AMPDU_para [4:2]:Min MPDU Start Spacing
- */
- max_ampdu_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03;
- min_mpdu_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2;
+ /* handle A-MPDU parameter field */
+ /*
+ AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+ AMPDU_para [4:2]:Min MPDU Start Spacing
+ */
+ max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
+
+ min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
- rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, &min_mpdu_spacing);
- rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, &max_ampdu_len);
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
}
void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
if (pIE->Length > 1)
return;
@@ -737,9 +836,9 @@ void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
void VCS_update(struct adapter *padapter, struct sta_info *psta)
{
- struct registry_priv *pregpriv = &padapter->registrypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */
case 0: /* off */
@@ -775,10 +874,11 @@ void VCS_update(struct adapter *padapter, struct sta_info *psta)
int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
{
- unsigned int len;
- unsigned char *p;
- unsigned short val16, subtype;
+ unsigned int len;
+ unsigned char *p;
+ unsigned short val16, subtype;
struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
+ /* u8 wpa_ie[255], rsn_ie[255]; */
u16 wpa_len = 0, rsn_len = 0;
u8 encryp_protocol = 0;
struct wlan_bssid_ex *bssid;
@@ -786,22 +886,28 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
unsigned char *pbuf;
u32 wpa_ielen = 0;
u8 *pbssid = GetAddr3Ptr(pframe);
+ u32 hidden_ssid = 0;
struct HT_info_element *pht_info = NULL;
+ struct ieee80211_ht_cap *pht_cap = NULL;
u32 bcn_channel;
- unsigned short ht_cap_info;
- unsigned char ht_info_infos_0;
- int ssid_len;
+ unsigned short ht_cap_info;
+ unsigned char ht_info_infos_0;
if (!is_client_associated_to_ap(Adapter))
return true;
- len = packet_len - sizeof(struct ieee80211_hdr_3addr);
+ len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
- if (len > MAX_IE_SZ)
+ if (len > MAX_IE_SZ) {
+ DBG_88E("%s IE too long for survey event\n", __func__);
return _FAIL;
+ }
- if (memcmp(cur_network->network.MacAddress, pbssid, 6))
+ if (memcmp(cur_network->network.MacAddress, pbssid, 6)) {
+ DBG_88E("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n%pM %pM\n",
+ (pbssid), (cur_network->network.MacAddress));
return true;
+ }
bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
if (!bssid)
@@ -809,86 +915,104 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
subtype = GetFrameSubType(pframe) >> 4;
- if (subtype == IEEE80211_STYPE_BEACON)
+ if (subtype == WIFI_BEACON)
bssid->Reserved[0] = 1;
bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
/* below is to copy the information element */
- bssid->ie_length = len;
- memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
+ bssid->IELength = len;
+ memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
/* check bw and channel offset */
/* parsing HT_CAP_IE */
- p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
if (p && len > 0) {
- struct ieee80211_ht_cap *ht_cap =
- (struct ieee80211_ht_cap *)(p + 2);
-
- ht_cap_info = le16_to_cpu(ht_cap->cap_info);
+ pht_cap = (struct ieee80211_ht_cap *)(p + 2);
+ ht_cap_info = le16_to_cpu(pht_cap->cap_info);
} else {
ht_cap_info = 0;
}
/* parsing HT_INFO_IE */
- p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
if (p && len > 0) {
- pht_info = (struct HT_info_element *)(p + 2);
- ht_info_infos_0 = pht_info->infos[0];
+ pht_info = (struct HT_info_element *)(p + 2);
+ ht_info_infos_0 = pht_info->infos[0];
} else {
- ht_info_infos_0 = 0;
+ ht_info_infos_0 = 0;
}
if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
((ht_info_infos_0 & 0x03) != (cur_network->BcnInfo.ht_info_infos_0 & 0x03))) {
- /* bcn_info_update */
- cur_network->BcnInfo.ht_cap_info = ht_cap_info;
- cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
- /* to do : need to check that whether modify related register of BB or not */
- /* goto _mismatch; */
+ DBG_88E("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
+ ht_cap_info, ht_info_infos_0);
+ DBG_88E("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
+ cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
+ DBG_88E("%s bw mode change, disconnect\n", __func__);
+ /* bcn_info_update */
+ cur_network->BcnInfo.ht_cap_info = ht_cap_info;
+ cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
+ /* to do : need to check that whether modify related register of BB or not */
+ /* goto _mismatch; */
}
/* Checking for channel */
- p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_DS_PARAMS, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
if (p) {
- bcn_channel = *(p + 2);
+ bcn_channel = *(p + 2);
} else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
- p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
- if (pht_info)
- bcn_channel = pht_info->primary_channel;
- else /* we don't find channel IE, so don't check it */
- bcn_channel = Adapter->mlmeextpriv.cur_channel;
+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ if (pht_info) {
+ bcn_channel = pht_info->primary_channel;
+ } else { /* we don't find channel IE, so don't check it */
+ DBG_88E("Oops: %s we don't find channel IE, so don't check it\n", __func__);
+ bcn_channel = Adapter->mlmeextpriv.cur_channel;
+ }
+ }
+ if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
+ DBG_88E("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
+ bcn_channel, Adapter->mlmeextpriv.cur_channel);
+ goto _mismatch;
}
- if (bcn_channel != Adapter->mlmeextpriv.cur_channel)
- goto _mismatch;
/* checking SSID */
- ssid_len = 0;
- p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_SSID, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
- if (p) {
- ssid_len = *(p + 1);
- if (ssid_len > NDIS_802_11_LENGTH_SSID)
- ssid_len = 0;
+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ if (!p) {
+ DBG_88E("%s marc: cannot find SSID for survey event\n", __func__);
+ hidden_ssid = true;
+ } else {
+ hidden_ssid = false;
+ }
+
+ if ((NULL != p) && (false == hidden_ssid && (*(p + 1)))) {
+ memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
+ bssid->Ssid.SsidLength = *(p + 1);
+ } else {
+ bssid->Ssid.SsidLength = 0;
+ bssid->Ssid.Ssid[0] = '\0';
}
- memcpy(bssid->ssid.ssid, (p + 2), ssid_len);
- bssid->ssid.ssid_length = ssid_len;
- if (memcmp(bssid->ssid.ssid, cur_network->network.ssid.ssid, 32) ||
- bssid->ssid.ssid_length != cur_network->network.ssid.ssid_length) {
- if (bssid->ssid.ssid[0] != '\0' && bssid->ssid.ssid_length != 0) /* not hidden ssid */
+ if (memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) ||
+ bssid->Ssid.SsidLength != cur_network->network.Ssid.SsidLength) {
+ if (bssid->Ssid.Ssid[0] != '\0' && bssid->Ssid.SsidLength != 0) { /* not hidden ssid */
+ DBG_88E("%s(), SSID is not match return FAIL\n", __func__);
goto _mismatch;
+ }
}
/* check encryption info */
- val16 = rtw_get_capability(bssid);
+ val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
if (val16 & BIT(4))
bssid->Privacy = 1;
else
bssid->Privacy = 0;
- if (cur_network->network.Privacy != bssid->Privacy)
+ if (cur_network->network.Privacy != bssid->Privacy) {
+ DBG_88E("%s(), privacy is not match return FAIL\n", __func__);
goto _mismatch;
+ }
- rtw_get_sec_ie(bssid->ies, bssid->ie_length, NULL, &rsn_len, NULL, &wpa_len);
+ rtw_get_sec_ie(bssid->IEs, bssid->IELength, NULL, &rsn_len, NULL, &wpa_len);
if (rsn_len > 0) {
encryp_protocol = ENCRYP_PROTOCOL_WPA2;
@@ -899,36 +1023,42 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
encryp_protocol = ENCRYP_PROTOCOL_WEP;
}
- if (cur_network->BcnInfo.encryp_protocol != encryp_protocol)
+ if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
+ DBG_88E("%s(): enctyp is not match , return FAIL\n", __func__);
goto _mismatch;
+ }
if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
- pbuf = rtw_get_wpa_ie(&bssid->ies[12], &wpa_ielen,
- bssid->ie_length - 12);
+ pbuf = rtw_get_wpa_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength - 12);
if (pbuf && (wpa_ielen > 0)) {
- rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher,
- &pairwise_cipher, &is_8021x);
+ rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x);
} else {
- pbuf = rtw_get_wpa2_ie(&bssid->ies[12], &wpa_ielen,
- bssid->ie_length - 12);
+ pbuf = rtw_get_wpa2_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength - 12);
if (pbuf && (wpa_ielen > 0))
- rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher,
- &pairwise_cipher, &is_8021x);
+ rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x);
}
- if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher)
+ if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
+ DBG_88E("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match , return FAIL\n", __func__,
+ pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
+ group_cipher, cur_network->BcnInfo.group_cipher);
goto _mismatch;
+ }
- if (is_8021x != cur_network->BcnInfo.is_8021x)
+ if (is_8021x != cur_network->BcnInfo.is_8021x) {
+ DBG_88E("%s authentication is not match , return FAIL\n", __func__);
goto _mismatch;
+ }
}
kfree(bssid);
+
return _SUCCESS;
_mismatch:
kfree(bssid);
+
return _FAIL;
}
@@ -944,10 +1074,11 @@ void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, stru
pIE = (struct ndis_802_11_var_ie *)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
switch (pIE->ElementID) {
- case WLAN_EID_HT_OPERATION: /* HT info */
+ case _HT_EXTRA_INFO_IE_: /* HT info */
+ /* HT_info_handler(padapter, pIE); */
bwmode_update_check(padapter, pIE);
break;
- case WLAN_EID_ERP_INFO:
+ case _ERPINFO_IE_:
ERP_IE_handler(padapter, pIE);
VCS_update(padapter, psta);
break;
@@ -964,19 +1095,19 @@ unsigned int is_ap_in_tkip(struct adapter *padapter)
u32 i;
struct ndis_802_11_var_ie *pIE;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
- if (rtw_get_capability(cur_network) & WLAN_CAPABILITY_PRIVACY) {
- for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.ie_length;) {
- pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.ies + i);
+ if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
+ pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
switch (pIE->ElementID) {
- case WLAN_EID_VENDOR_SPECIFIC:
+ case _VENDOR_SPECIFIC_IE_:
if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
return true;
break;
- case WLAN_EID_RSN:
+ case _RSN_IE_2_:
if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
return true;
break;
@@ -992,38 +1123,116 @@ unsigned int is_ap_in_tkip(struct adapter *padapter)
}
}
-static int wifirate2_ratetbl_inx(unsigned char rate)
+unsigned int should_forbid_n_rate(struct adapter *padapter)
+{
+ u32 i;
+ struct ndis_802_11_var_ie *pIE;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *cur_network = &pmlmepriv->cur_network.network;
+
+ if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < cur_network->IELength;) {
+ pIE = (struct ndis_802_11_var_ie *)(cur_network->IEs + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:
+ if (!memcmp(pIE->data, RTW_WPA_OUI, 4) &&
+ ((!memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP, 4)) ||
+ (!memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP, 4))))
+ return false;
+ break;
+ case _RSN_IE_2_:
+ if ((!memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP, 4)) ||
+ (!memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP, 4)))
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ i += (pIE->Length + 2);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+unsigned int is_ap_in_wep(struct adapter *padapter)
+{
+ u32 i;
+ struct ndis_802_11_var_ie *pIE;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+
+ if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
+ pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:
+ if (!memcmp(pIE->data, RTW_WPA_OUI, 4))
+ return false;
+ break;
+ case _RSN_IE_2_:
+ return false;
+ default:
+ break;
+ }
+ i += (pIE->Length + 2);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int wifirate2_ratetbl_inx(unsigned char rate)
{
+ int inx = 0;
rate = rate & 0x7f;
switch (rate) {
- case 108:
- return 11;
- case 96:
- return 10;
- case 72:
- return 9;
- case 48:
- return 8;
- case 36:
- return 7;
- case 24:
- return 6;
- case 18:
- return 5;
- case 12:
- return 4;
- case 22:
- return 3;
+ case 54 * 2:
+ inx = 11;
+ break;
+ case 48 * 2:
+ inx = 10;
+ break;
+ case 36 * 2:
+ inx = 9;
+ break;
+ case 24 * 2:
+ inx = 8;
+ break;
+ case 18 * 2:
+ inx = 7;
+ break;
+ case 12 * 2:
+ inx = 6;
+ break;
+ case 9 * 2:
+ inx = 5;
+ break;
+ case 6 * 2:
+ inx = 4;
+ break;
+ case 11 * 2:
+ inx = 3;
+ break;
case 11:
- return 2;
- case 4:
- return 1;
- case 2:
- return 0;
- default:
- return 0;
+ inx = 2;
+ break;
+ case 2 * 2:
+ inx = 1;
+ break;
+ case 1 * 2:
+ inx = 0;
+ break;
}
+ return inx;
}
unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz)
@@ -1031,7 +1240,7 @@ unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz)
unsigned int i, num_of_rate;
unsigned int mask = 0;
- num_of_rate = min_t(unsigned int, ptn_sz, NumRates);
+ num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz;
for (i = 0; i < num_of_rate; i++) {
if ((*(ptn + i)) & 0x80)
@@ -1045,24 +1254,27 @@ unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz)
unsigned int i, num_of_rate;
unsigned int mask = 0;
- num_of_rate = min_t(unsigned int, ptn_sz, NumRates);
+ num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz;
for (i = 0; i < num_of_rate; i++)
mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
return mask;
}
-unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps)
+unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps)
{
- return (pHT_caps->mcs.rx_mask[0] << 12) |
- (pHT_caps->mcs.rx_mask[1] << 20);
+ unsigned int mask = 0;
+
+ mask = ((pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20));
+
+ return mask;
}
-int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *pHT_caps)
+int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps)
{
- unsigned char bit_offset;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ unsigned char bit_offset;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
if (!(pmlmeinfo->HT_enable))
return _FAIL;
@@ -1072,7 +1284,7 @@ int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *pHT_caps
bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40) ? 6 : 5;
- if (__le16_to_cpu(pHT_caps->cap_info) & (0x1 << bit_offset))
+ if (__le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & (0x1 << bit_offset))
return _SUCCESS;
else
return _FAIL;
@@ -1097,17 +1309,30 @@ void Update_RA_Entry(struct adapter *padapter, u32 mac_id)
rtw_hal_update_ra_mask(padapter, mac_id, 0);
}
+static void enable_rate_adaptive(struct adapter *padapter, u32 mac_id)
+{
+ Update_RA_Entry(padapter, mac_id);
+}
+
void set_sta_rate(struct adapter *padapter, struct sta_info *psta)
{
/* rate adaptive */
- Update_RA_Entry(padapter, psta->mac_id);
+ enable_rate_adaptive(padapter, psta->mac_id);
}
/* Update RRSR and Rate for USERATE */
void update_tx_basic_rate(struct adapter *padapter, u8 wirelessmode)
{
unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ /* Added by Albert 2011/03/22 */
+ /* In the P2P mode, the driver should not support the b mode. */
+ /* So, the Tx packet shouldn't use the CCK rate */
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ return;
+#endif /* CONFIG_88EU_P2P */
memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B))
@@ -1129,9 +1354,8 @@ unsigned char check_assoc_AP(u8 *pframe, uint len)
{
unsigned int i;
struct ndis_802_11_var_ie *pIE;
- u8 epigram_vendor_flag;
- u8 ralink_vendor_flag;
-
+ u8 epigram_vendor_flag;
+ u8 ralink_vendor_flag;
epigram_vendor_flag = 0;
ralink_vendor_flag = 0;
@@ -1139,30 +1363,43 @@ unsigned char check_assoc_AP(u8 *pframe, uint len)
pIE = (struct ndis_802_11_var_ie *)(pframe + i);
switch (pIE->ElementID) {
- case WLAN_EID_VENDOR_SPECIFIC:
+ case _VENDOR_SPECIFIC_IE_:
if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
(!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
+ DBG_88E("link to Artheros AP\n");
return HT_IOT_PEER_ATHEROS;
} else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
+ (!memcmp(pIE->data, BROADCOM_OUI2, 3)) ||
(!memcmp(pIE->data, BROADCOM_OUI2, 3))) {
+ DBG_88E("link to Broadcom AP\n");
return HT_IOT_PEER_BROADCOM;
} else if (!memcmp(pIE->data, MARVELL_OUI, 3)) {
+ DBG_88E("link to Marvell AP\n");
return HT_IOT_PEER_MARVELL;
} else if (!memcmp(pIE->data, RALINK_OUI, 3)) {
- if (!ralink_vendor_flag)
+ if (!ralink_vendor_flag) {
ralink_vendor_flag = 1;
- else
+ } else {
+ DBG_88E("link to Ralink AP\n");
return HT_IOT_PEER_RALINK;
+ }
} else if (!memcmp(pIE->data, CISCO_OUI, 3)) {
+ DBG_88E("link to Cisco AP\n");
return HT_IOT_PEER_CISCO;
} else if (!memcmp(pIE->data, REALTEK_OUI, 3)) {
+ DBG_88E("link to Realtek 96B\n");
return HT_IOT_PEER_REALTEK;
} else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
+ DBG_88E("link to Airgo Cap\n");
return HT_IOT_PEER_AIRGO;
} else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) {
epigram_vendor_flag = 1;
- if (ralink_vendor_flag)
+ if (ralink_vendor_flag) {
+ DBG_88E("link to Tenda W311R AP\n");
return HT_IOT_PEER_TENDA;
+ } else {
+ DBG_88E("Capture EPIGRAM_OUI\n");
+ }
} else {
break;
}
@@ -1174,17 +1411,22 @@ unsigned char check_assoc_AP(u8 *pframe, uint len)
i += (pIE->Length + 2);
}
- if (ralink_vendor_flag && !epigram_vendor_flag)
+ if (ralink_vendor_flag && !epigram_vendor_flag) {
+ DBG_88E("link to Ralink AP\n");
return HT_IOT_PEER_RALINK;
- else if (ralink_vendor_flag && epigram_vendor_flag)
+ } else if (ralink_vendor_flag && epigram_vendor_flag) {
+ DBG_88E("link to Tenda W311R AP\n");
return HT_IOT_PEER_TENDA;
- return HT_IOT_PEER_UNKNOWN;
+ } else {
+ DBG_88E("link to new AP\n");
+ return HT_IOT_PEER_UNKNOWN;
+ }
}
void update_IOT_info(struct adapter *padapter)
{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
switch (pmlmeinfo->assoc_AP_vendor) {
case HT_IOT_PEER_MARVELL:
@@ -1195,13 +1437,13 @@ void update_IOT_info(struct adapter *padapter)
pmlmeinfo->turboMode_cts2self = 0;
pmlmeinfo->turboMode_rtsen = 1;
/* disable high power */
- Switch_DM_Func(padapter, (u32)(~DYNAMIC_BB_DYNAMIC_TXPWR),
- false);
+ Switch_DM_Func(padapter, (~DYNAMIC_BB_DYNAMIC_TXPWR), false);
break;
case HT_IOT_PEER_REALTEK:
+ /* rtw_write16(padapter, 0x4cc, 0xffff); */
+ /* rtw_write16(padapter, 0x546, 0x01c0); */
/* disable high power */
- Switch_DM_Func(padapter, (u32)(~DYNAMIC_BB_DYNAMIC_TXPWR),
- false);
+ Switch_DM_Func(padapter, (~DYNAMIC_BB_DYNAMIC_TXPWR), false);
break;
default:
pmlmeinfo->turboMode_cts2self = 0;
@@ -1212,9 +1454,9 @@ void update_IOT_info(struct adapter *padapter)
void update_capinfo(struct adapter *Adapter, u16 updateCap)
{
- struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- bool ShortPreamble;
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ bool ShortPreamble;
/* Check preamble mode, 2005.01.06, by rcnjko. */
/* Mark to update preamble value forever, 2008.03.18 by lanhsin */
@@ -1245,8 +1487,6 @@ void update_capinfo(struct adapter *Adapter, u16 updateCap)
if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME)
pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
}
- } else if (pmlmeext->cur_wireless_mode & (WIRELESS_11A | WIRELESS_11_5N)) {
- pmlmeinfo->slotTime = SHORT_SLOT_TIME;
} else {
/* B Mode */
pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
@@ -1258,42 +1498,49 @@ void update_capinfo(struct adapter *Adapter, u16 updateCap)
void update_wireless_mode(struct adapter *padapter)
{
- int network_type = 0;
+ int ratelen, network_type = 0;
u32 SIFS_Timer;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
- unsigned char *rate = cur_network->SupportedRates;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ unsigned char *rate = cur_network->SupportedRates;
- if (pmlmeinfo->HT_info_enable && pmlmeinfo->HT_caps_enable)
- pmlmeinfo->HT_enable = 1;
+ ratelen = rtw_get_rateset_len(cur_network->SupportedRates);
- if (pmlmeinfo->HT_enable)
- network_type = WIRELESS_11_24N;
+ if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
+ pmlmeinfo->HT_enable = 1;
- if (rtw_is_cckratesonly_included(rate))
- network_type |= WIRELESS_11B;
- else if (rtw_is_cckrates_included(rate))
- network_type |= WIRELESS_11BG;
- else
- network_type |= WIRELESS_11G;
+ if (pmlmeext->cur_channel > 14) {
+ network_type |= WIRELESS_INVALID;
+ } else {
+ if (pmlmeinfo->HT_enable)
+ network_type = WIRELESS_11_24N;
+
+ if (cckratesonly_included(rate, ratelen))
+ network_type |= WIRELESS_11B;
+ else if (cckrates_included(rate, ratelen))
+ network_type |= WIRELESS_11BG;
+ else
+ network_type |= WIRELESS_11G;
+ }
pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
SIFS_Timer = 0x0a0a0808;/* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
/* change this value if having IOT issues. */
- rtw_hal_set_hwreg(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
- update_mgnt_tx_rate(padapter,
- pmlmeext->cur_wireless_mode & WIRELESS_11B ?
- IEEE80211_CCK_RATE_1MB : IEEE80211_OFDM_RATE_6MB);
+ if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
+ update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
+ else
+ update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB);
}
void update_bmc_sta_support_rate(struct adapter *padapter, u32 mac_id)
{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
/* Only B, B/G, and B/G/N AP could use CCK rate */
@@ -1305,27 +1552,22 @@ void update_bmc_sta_support_rate(struct adapter *padapter, u32 mac_id)
int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
{
- unsigned int ie_len;
+ unsigned int ie_len;
struct ndis_802_11_var_ie *pIE;
- int supportRateNum = 0;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ int supportRateNum = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, WLAN_EID_SUPP_RATES, &ie_len, var_ie_len);
+ pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
if (!pIE)
return _FAIL;
- if (ie_len > NDIS_802_11_LENGTH_RATES_EX)
- return _FAIL;
memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
supportRateNum = ie_len;
- pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, WLAN_EID_EXT_SUPP_RATES, &ie_len, var_ie_len);
- if (pIE) {
- if (supportRateNum + ie_len > NDIS_802_11_LENGTH_RATES_EX)
- return _FAIL;
+ pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
+ if (pIE)
memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
- }
return _SUCCESS;
}
@@ -1337,9 +1579,9 @@ void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr)
u16 param;
struct recv_reorder_ctrl *preorder_ctrl;
struct sta_priv *pstapriv = &padapter->stapriv;
- struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
psta = rtw_get_stainfo(pstapriv, addr);
@@ -1348,7 +1590,7 @@ void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr)
tid = (param >> 2) & 0x0f;
preorder_ctrl = &psta->recvreorder_ctrl[tid];
preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->enable = pmlmeinfo->accept_addba_req;
+ preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq) ? true : false;
}
}
@@ -1357,7 +1599,7 @@ void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
u8 *pIE;
__le32 *pbuf;
- pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
+ pIE = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
pbuf = (__le32 *)pIE;
pmlmeext->TSFValue = le32_to_cpu(*(pbuf + 1));
@@ -1371,3 +1613,31 @@ void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext)
{
rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, NULL);
}
+
+void beacon_timing_control(struct adapter *padapter)
+{
+ rtw_hal_bcn_related_reg_setting(padapter);
+}
+
+static struct adapter *pbuddy_padapter;
+
+int rtw_handle_dualmac(struct adapter *adapter, bool init)
+{
+ int status = _SUCCESS;
+
+ if (init) {
+ if (!pbuddy_padapter) {
+ pbuddy_padapter = adapter;
+ DBG_88E("%s(): pbuddy_padapter == NULL, Set pbuddy_padapter\n", __func__);
+ } else {
+ adapter->pbuddy_adapter = pbuddy_padapter;
+ pbuddy_padapter->pbuddy_adapter = adapter;
+ /* clear global value */
+ pbuddy_padapter = NULL;
+ DBG_88E("%s(): pbuddy_padapter exist, Exchange Information\n", __func__);
+ }
+ } else {
+ pbuddy_padapter = NULL;
+ }
+ return status;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/r8188eu/core/rtw_xmit.c
index d5fc59417ec6..46fe62c7c32c 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/r8188eu/core/rtw_xmit.c
@@ -1,30 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
#define _RTW_XMIT_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <mon.h>
-#include <wifi.h>
-#include <osdep_intf.h>
-#include <linux/vmalloc.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/wifi.h"
+#include "../include/osdep_intf.h"
+#include "../include/usb_ops.h"
+#include "../include/usb_osintf.h"
static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
static void _init_txservq(struct tx_servq *ptxservq)
{
+
INIT_LIST_HEAD(&ptxservq->tx_pending);
_rtw_init_queue(&ptxservq->sta_pending);
ptxservq->qcnt = 0;
+
}
-void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
+void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
{
+
memset((unsigned char *)psta_xmitpriv, 0, sizeof(struct sta_xmit_priv));
spin_lock_init(&psta_xmitpriv->lock);
_init_txservq(&psta_xmitpriv->be_q);
@@ -33,27 +33,27 @@ void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
_init_txservq(&psta_xmitpriv->vo_q);
INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
INIT_LIST_HEAD(&psta_xmitpriv->apsd);
+
}
-s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
+s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
{
int i;
struct xmit_buf *pxmitbuf;
struct xmit_frame *pxframe;
- int res = _SUCCESS;
+ int res = _SUCCESS;
u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
- /*
- * We don't need to memset padapter->XXX to zero because adapter is
- * allocated by alloc_etherdev_mq, which eventually calls kvzalloc.
- */
+ /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
spin_lock_init(&pxmitpriv->lock);
+ sema_init(&pxmitpriv->xmit_sema, 0);
+ sema_init(&pxmitpriv->terminate_xmitthread_sema, 0);
/*
- * Please insert all the queue initializaiton using _rtw_init_queue below
- */
+ Please insert all the queue initializaiton using _rtw_init_queue below
+ */
pxmitpriv->adapter = padapter;
@@ -66,10 +66,10 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
_rtw_init_queue(&pxmitpriv->free_xmit_queue);
/*
- * Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
- * and initialize free_xmit_frame below.
- * Please also apply free_txobj to link_up all the xmit_frames...
- */
+ Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
+ and initialize free_xmit_frame below.
+ Please also apply free_txobj to link_up all the xmit_frames...
+ */
pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
@@ -78,7 +78,9 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
res = _FAIL;
goto exit;
}
- pxmitpriv->pxmit_frame_buf = PTR_ALIGN(pxmitpriv->pallocated_frame_buf, 4);
+ pxmitpriv->pxmit_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_frame_buf), 4);
+ /* pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - */
+ /* ((size_t) (pxmitpriv->pallocated_frame_buf) &3); */
pxframe = (struct xmit_frame *)pxmitpriv->pxmit_frame_buf;
@@ -113,7 +115,9 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
goto exit;
}
- pxmitpriv->pxmitbuf = PTR_ALIGN(pxmitpriv->pallocated_xmitbuf, 4);
+ pxmitpriv->pxmitbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmitbuf), 4);
+ /* pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - */
+ /* ((size_t) (pxmitpriv->pallocated_xmitbuf) &3); */
pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
@@ -125,12 +129,13 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitbuf->ext_tag = false;
/* Tx buf allocation may fail sometimes, so sleep and retry. */
- res = rtw_os_xmit_resource_alloc(pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
if (res == _FAIL) {
msleep(10);
- res = rtw_os_xmit_resource_alloc(pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
- if (res == _FAIL)
+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
+ if (res == _FAIL) {
goto exit;
+ }
}
pxmitbuf->flags = XMIT_VO_QUEUE;
@@ -151,7 +156,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
goto exit;
}
- pxmitpriv->pxmit_extbuf = PTR_ALIGN(pxmitpriv->pallocated_xmit_extbuf, 4);
+ pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4);
pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
@@ -162,7 +167,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitbuf->padapter = padapter;
pxmitbuf->ext_tag = true;
- res = rtw_os_xmit_resource_alloc(pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
if (res == _FAIL) {
res = _FAIL;
goto exit;
@@ -174,9 +179,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
- res = rtw_alloc_hwxmits(padapter);
- if (res == _FAIL)
- goto exit;
+ rtw_alloc_hwxmits(padapter);
rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
for (i = 0; i < 4; i++)
@@ -184,6 +187,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitpriv->txirp_cnt = 1;
+ sema_init(&pxmitpriv->tx_retevt, 0);
+
/* per AC pending irp */
pxmitpriv->beq_cnt = 0;
pxmitpriv->bkq_cnt = 0;
@@ -191,12 +196,13 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitpriv->voq_cnt = 0;
pxmitpriv->ack_tx = false;
- mutex_init(&pxmitpriv->ack_tx_mutex);
+ _rtw_mutex_init(&pxmitpriv->ack_tx_mutex);
rtw_sctx_init(&pxmitpriv->ack_tx_ops, 0);
rtw_hal_init_xmit_priv(padapter);
exit:
+
return res;
}
@@ -206,6 +212,7 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv)
struct adapter *padapter = pxmitpriv->adapter;
struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitpriv->pxmit_frame_buf;
struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
+ u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
if (!pxmitpriv->pxmit_frame_buf)
@@ -218,17 +225,17 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv)
}
for (i = 0; i < NR_XMITBUFF; i++) {
- rtw_os_xmit_resource_free(pxmitbuf);
+ rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
pxmitbuf++;
}
vfree(pxmitpriv->pallocated_frame_buf);
+
vfree(pxmitpriv->pallocated_xmitbuf);
- /* free xmit extension buff */
pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
for (i = 0; i < num_xmit_extbuf; i++) {
- rtw_os_xmit_resource_free(pxmitbuf);
+ rtw_os_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ));
pxmitbuf++;
}
@@ -236,7 +243,7 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv)
rtw_free_hwxmits(padapter);
- mutex_destroy(&pxmitpriv->ack_tx_mutex);
+ _rtw_mutex_free(&pxmitpriv->ack_tx_mutex);
}
static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *pxmitframe)
@@ -252,12 +259,10 @@ static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *
else /* no frag */
sz = pattrib->last_txcmdsz;
- /* (1) RTS_Threshold is compared to the MPDU, not MSDU.
- * (2) If there are more than one frag in this MSDU,
- * only the first frag uses protection frame.
- * Other fragments are protected by previous fragment.
- * So we only need to check the length of first fragment.
- */
+ /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */
+ /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */
+ /* Other fragments are protected by previous fragment. */
+ /* So we only need to check the length of first fragment. */
if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) {
if (sz > padapter->registrypriv.rts_thresh) {
pattrib->vcs_mode = RTS_CTS;
@@ -291,7 +296,6 @@ static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *
/* check HT op mode */
if (pattrib->ht_en) {
u8 htopmode = pmlmeinfo->HT_protection;
-
if ((pmlmeext->cur_bwmode && (htopmode == 2 || htopmode == 3)) ||
(!pmlmeext->cur_bwmode && htopmode == 3)) {
pattrib->vcs_mode = RTS_CTS;
@@ -321,6 +325,13 @@ static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *
static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta)
{
+ /*if (psta->rtsen)
+ pattrib->vcs_mode = RTS_CTS;
+ else if (psta->cts2self)
+ pattrib->vcs_mode = CTS_TO_SELF;
+ else
+ pattrib->vcs_mode = NONE_VCS;*/
+
pattrib->mdata = 0;
pattrib->eosp = 0;
pattrib->triggered = 0;
@@ -337,9 +348,9 @@ static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *
pattrib->retry_ctrl = false;
}
-u8 qos_acm(u8 acm_mask, u8 priority)
+u8 qos_acm(u8 acm_mask, u8 priority)
{
- u8 change_priority = priority;
+ u8 change_priority = priority;
switch (priority) {
case 0:
@@ -361,46 +372,55 @@ u8 qos_acm(u8 acm_mask, u8 priority)
change_priority = 5;
break;
default:
+ DBG_88E("qos_acm(): invalid pattrib->priority: %d!!!\n", priority);
break;
}
return change_priority;
}
-static void set_qos(struct sk_buff *skb, struct pkt_attrib *pattrib)
+static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
{
+ struct ethhdr etherhdr;
+ struct iphdr ip_hdr;
+ s32 user_prio = 0;
+
+ _rtw_open_pktfile(ppktfile->pkt, ppktfile);
+ _rtw_pktfile_read(ppktfile, (unsigned char *)&etherhdr, ETH_HLEN);
+
+ /* get user_prio from IP hdr */
if (pattrib->ether_type == 0x0800) {
- struct iphdr ip_hdr;
-
- skb_copy_bits(skb, ETH_HLEN, &ip_hdr, sizeof(ip_hdr));
- pattrib->priority = ip_hdr.tos >> 5;
- } else if (pattrib->ether_type == ETH_P_PAE) {
- /* When priority processing of data frames is supported,
- * a STA's SME should send EAPOL-Key frames at the highest
- * priority.
- */
- pattrib->priority = 7;
- } else {
- pattrib->priority = 0;
+ _rtw_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr));
+/* user_prio = (ntohs(ip_hdr.tos) >> 5) & 0x3; */
+ user_prio = ip_hdr.tos >> 5;
+ } else if (pattrib->ether_type == 0x888e) {
+ /* "When priority processing of data frames is supported, */
+ /* a STA's SME should send EAPOL-Key frames at the highest priority." */
+ user_prio = 7;
}
+ pattrib->priority = user_prio;
pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
pattrib->subtype = WIFI_QOS_DATA_TYPE;
}
static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct pkt_attrib *pattrib)
{
+ struct pkt_file pktfile;
struct sta_info *psta = NULL;
struct ethhdr etherhdr;
- bool mcast;
+ bool bmcast;
struct sta_priv *pstapriv = &padapter->stapriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct qos_priv *pqospriv = &pmlmepriv->qospriv;
int res = _SUCCESS;
- skb_copy_bits(pkt, 0, &etherhdr, ETH_HLEN);
+
+
+ _rtw_open_pktfile(pkt, &pktfile);
+ _rtw_pktfile_read(&pktfile, (u8 *)&etherhdr, ETH_HLEN);
pattrib->ether_type = ntohs(etherhdr.h_proto);
@@ -421,20 +441,16 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
}
- pattrib->pktlen = pkt->len - ETH_HLEN;
+ pattrib->pktlen = pktfile.pkt_len;
- if (pattrib->ether_type == ETH_P_IP) {
- /* The following is for DHCP and ARP packet, we use
- * cck1M to tx these packets and let LPS awake some
- * time to prevent DHCP protocol fail.
- */
+ if (ETH_P_IP == pattrib->ether_type) {
+ /* The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time */
+ /* to prevent DHCP protocol fail */
u8 tmp[24];
-
- skb_copy_bits(pkt, ETH_HLEN, tmp, 24);
-
+ _rtw_pktfile_read(&pktfile, &tmp[0], 24);
pattrib->dhcp_pkt = 0;
- if (pkt->len > ETH_HLEN + 24 + 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */
- if (pattrib->ether_type == ETH_P_IP) {/* IP header */
+ if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */
+ if (ETH_P_IP == pattrib->ether_type) {/* IP header */
if (((tmp[21] == 68) && (tmp[23] == 67)) ||
((tmp[21] == 67) && (tmp[23] == 68))) {
/* 68 : UDP BOOTP client */
@@ -444,27 +460,28 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
}
}
}
+ } else if (0x888e == pattrib->ether_type) {
+ DBG_88E_LEVEL(_drv_info_, "send eapol packet\n");
}
- if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1))
+ if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1))
rtw_set_scan_deny(padapter, 3000);
/* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */
- if ((pattrib->ether_type == ETH_P_ARP) || (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1))
+ if ((pattrib->ether_type == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1))
rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
- mcast = is_multicast_ether_addr(pattrib->ra);
+ bmcast = is_multicast_ether_addr(pattrib->ra);
/* get sta_info */
- if (mcast) {
+ if (bmcast) {
psta = rtw_get_bcmc_stainfo(padapter);
} else {
psta = rtw_get_stainfo(pstapriv, pattrib->ra);
if (!psta) { /* if we cannot get psta => drrp the pkt */
res = _FAIL;
goto exit;
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) &&
- !(psta->state & _FW_LINKED)) {
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && !(psta->state & _FW_LINKED)) {
res = _FAIL;
goto exit;
}
@@ -472,6 +489,7 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
if (psta) {
pattrib->mac_id = psta->mac_id;
+ /* DBG_88E("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */
pattrib->psta = psta;
} else {
/* if we cannot get psta => drop the pkt */
@@ -480,18 +498,19 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
}
pattrib->ack_policy = 0;
+ /* get ether_hdr_len */
+ pattrib->pkt_hdrlen = ETH_HLEN;/* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */
pattrib->hdrlen = WLAN_HDR_A3_LEN;
pattrib->subtype = WIFI_DATA_TYPE;
pattrib->priority = 0;
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE |
- WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
if (psta->qos_option)
- set_qos(pkt, pattrib);
+ set_qos(&pktfile, pattrib);
} else {
if (pqospriv->qos_option) {
- set_qos(pkt, pattrib);
+ set_qos(&pktfile, pattrib);
if (pmlmepriv->acm_mask != 0)
pattrib->priority = qos_acm(pmlmepriv->acm_mask, pattrib->priority);
@@ -501,12 +520,12 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
if (psta->ieee8021x_blocked) {
pattrib->encrypt = 0;
- if (pattrib->ether_type != ETH_P_PAE) {
+ if ((pattrib->ether_type != 0x888e) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
res = _FAIL;
goto exit;
}
} else {
- GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, mcast);
+ GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
switch (psecuritypriv->dot11AuthAlgrthm) {
case dot11AuthAlgrthm_Open:
@@ -515,7 +534,7 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex;
break;
case dot11AuthAlgrthm_8021X:
- if (mcast)
+ if (bmcast)
pattrib->key_idx = (u8)psecuritypriv->dot118021XGrpKeyid;
else
pattrib->key_idx = 0;
@@ -551,14 +570,18 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p
break;
}
- if (pattrib->encrypt && !psecuritypriv->hw_decrypted)
+ if (pattrib->encrypt &&
+ (padapter->securitypriv.sw_encrypt || !psecuritypriv->hw_decrypted))
pattrib->bswenc = true;
else
pattrib->bswenc = false;
+ rtw_set_tx_chksum_offload(pkt, pattrib);
+
update_attrib_phy_info(pattrib, psta);
exit:
+
return res;
}
@@ -571,7 +594,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u8 priority[4] = {};
+ u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
u8 hw_hdr_offset = 0;
if (pattrib->psta)
@@ -581,10 +604,12 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
- if (pattrib->encrypt == _TKIP_) {
+ if (pattrib->encrypt == _TKIP_) {/* if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_PRIVACY_) */
/* encode mic code */
if (stainfo) {
- u8 null_key[16] = {};
+ u8 null_key[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0};
pframe = pxmitframe->buf_addr + hw_hdr_offset;
@@ -594,8 +619,10 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
/* start to calculate the mic code */
rtw_secmicsetkey(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);
} else {
- if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], null_key, 16))
+ if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], null_key, 16)) {
+ /* msleep(10); */
return _FAIL;
+ }
/* start to calculate the mic code */
rtw_secmicsetkey(&micdata, &stainfo->dot11tkiptxmickey.skey[0]);
}
@@ -605,7 +632,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
if (pframe[1] & 2) /* From Ds == 1 */
rtw_secmicappend(&micdata, &pframe[24], 6);
else
- rtw_secmicappend(&micdata, &pframe[10], 6);
+ rtw_secmicappend(&micdata, &pframe[10], 6);
} else { /* ToDS == 0 */
rtw_secmicappend(&micdata, &pframe[4], 6); /* DA */
if (pframe[1] & 2) /* From Ds == 1 */
@@ -622,25 +649,17 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
payload = pframe;
for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
- payload = (u8 *)round_up((size_t)(payload), 4);
-
- payload += pattrib->hdrlen + pattrib->iv_len;
- if (curfragnum + 1 == pattrib->nr_frags) {
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- ((pattrib->bswenc) ?
- pattrib->icv_len : 0);
+ payload = (u8 *)RND4((size_t)(payload));
+
+ payload = payload + pattrib->hdrlen + pattrib->iv_len;
+ if ((curfragnum + 1) == pattrib->nr_frags) {
+ length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - ((pattrib->bswenc) ? pattrib->icv_len : 0);
rtw_secmicappend(&micdata, payload, length);
- payload += length;
+ payload = payload + length;
} else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen -
- pattrib->iv_len -
- ((pattrib->bswenc) ?
- pattrib->icv_len : 0);
+ length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - ((pattrib->bswenc) ? pattrib->icv_len : 0);
rtw_secmicappend(&micdata, payload, length);
- payload += length + pattrib->icv_len;
+ payload = payload + length + pattrib->icv_len;
}
}
rtw_secgetmic(&micdata, &mic[0]);
@@ -649,7 +668,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr
memcpy(payload, &mic[0], 8);
pattrib->last_txcmdsz += 8;
- payload -= pattrib->last_txcmdsz + 8;
+ payload = payload - pattrib->last_txcmdsz + 8;
}
}
@@ -664,13 +683,13 @@ static s32 xmitframe_swencrypt(struct adapter *padapter, struct xmit_frame *pxmi
switch (pattrib->encrypt) {
case _WEP40_:
case _WEP104_:
- rtw_wep_encrypt(padapter, pxmitframe);
+ rtw_wep_encrypt(padapter, (u8 *)pxmitframe);
break;
case _TKIP_:
- rtw_tkip_encrypt(padapter, pxmitframe);
+ rtw_tkip_encrypt(padapter, (u8 *)pxmitframe);
break;
case _AES_:
- rtw_aes_encrypt(padapter, pxmitframe);
+ rtw_aes_encrypt(padapter, (u8 *)pxmitframe);
break;
default:
break;
@@ -684,23 +703,24 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
{
u16 *qc;
- struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
+ struct rtw_ieee80211_hdr *pwlanhdr = (struct rtw_ieee80211_hdr *)hdr;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct qos_priv *pqospriv = &pmlmepriv->qospriv;
u8 qos_option = false;
int res = _SUCCESS;
- __le16 *fctrl = &pwlanhdr->frame_control;
+ __le16 *fctrl = &pwlanhdr->frame_ctl;
struct sta_info *psta;
if (pattrib->psta) {
psta = pattrib->psta;
} else {
- if (is_multicast_ether_addr(pattrib->ra))
+ if (is_multicast_ether_addr(pattrib->ra)) {
psta = rtw_get_bcmc_stainfo(padapter);
- else
+ } else {
psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+ }
}
memset(hdr, 0, WLANHDR_OFFSET);
@@ -708,7 +728,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
SetFrameSubType(fctrl, pattrib->subtype);
if (pattrib->subtype & WIFI_DATA_TYPE) {
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
/* to_ds = 1, fr_ds = 0; */
/* Data transfer to AP */
SetToDs(fctrl);
@@ -725,7 +745,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN);
memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
- if (psta && psta->qos_option)
+ if (psta->qos_option)
qos_option = true;
} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
@@ -733,7 +753,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
- if (psta && psta->qos_option)
+ if (psta->qos_option)
qos_option = true;
} else {
res = _FAIL;
@@ -804,9 +824,9 @@ s32 rtw_txframes_pending(struct adapter *padapter)
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
return (!list_empty(&pxmitpriv->be_pending.queue) ||
- !list_empty(&pxmitpriv->bk_pending.queue) ||
- !list_empty(&pxmitpriv->vi_pending.queue) ||
- !list_empty(&pxmitpriv->vo_pending.queue));
+ !list_empty(&pxmitpriv->bk_pending.queue) ||
+ !list_empty(&pxmitpriv->vi_pending.queue) ||
+ !list_empty(&pxmitpriv->vo_pending.queue));
}
s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, struct pkt_attrib *pattrib)
@@ -837,23 +857,44 @@ s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, struct pkt_attrib *pat
break;
}
- return ptxservq->qcnt;
+ if (ptxservq)
+ return ptxservq->qcnt;
+ return 0;
}
/*
- *
- * This sub-routine will perform all the following:
- *
- * 1. remove 802.3 header.
- * 2. create wlan_header, based on the info in pxmitframe
- * 3. append sta's iv/ext-iv
- * 4. append LLC
- * 5. move frag chunk from pframe to pxmitframe->mem
- * 6. apply sw-encrypt, if necessary.
- *
+ * Calculate wlan 802.11 packet MAX size from pkt_attrib
+ * This function doesn't consider fragment case
*/
+u32 rtw_calculate_wlan_pkt_size_by_attribue(struct pkt_attrib *pattrib)
+{
+ u32 len = 0;
+
+ len = pattrib->hdrlen + pattrib->iv_len; /* WLAN Header and IV */
+ len += SNAP_SIZE + sizeof(u16); /* LLC */
+ len += pattrib->pktlen;
+ if (pattrib->encrypt == _TKIP_)
+ len += 8; /* MIC */
+ len += ((pattrib->bswenc) ? pattrib->icv_len : 0); /* ICV */
+
+ return len;
+}
+
+/*
+
+This sub-routine will perform all the following:
+
+1. remove 802.3 header.
+2. create wlan_header, based on the info in pxmitframe
+3. append sta's iv/ext-iv
+4. append LLC
+5. move frag chunk from pframe to pxmitframe->mem
+6. apply sw-encrypt, if necessary.
+
+*/
s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct xmit_frame *pxmitframe)
{
+ struct pkt_file pktfile;
s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
size_t addr;
u8 *pframe, *mem_start;
@@ -862,17 +903,21 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
u8 *pbuf_start;
- bool mcast = is_multicast_ether_addr(pattrib->ra);
+ bool bmcst = is_multicast_ether_addr(pattrib->ra);
s32 res = _SUCCESS;
- size_t remainder = pkt->len - ETH_HLEN;
+
+ if (!pkt)
+ return _FAIL;
psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
if (!psta)
return _FAIL;
- if (!pxmitframe->buf_addr)
+ if (!pxmitframe->buf_addr) {
+ DBG_88E("==> %s buf_addr == NULL\n", __func__);
return _FAIL;
+ }
pbuf_start = pxmitframe->buf_addr;
@@ -881,10 +926,14 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct
mem_start = pbuf_start + hw_hdr_offset;
if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) {
+ DBG_88E("rtw_xmitframe_coalesce: rtw_make_wlanhdr fail; drop pkt\n");
res = _FAIL;
goto exit;
}
+ _rtw_open_pktfile(pkt, &pktfile);
+ _rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen);
+
frg_inx = 0;
frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */
@@ -902,23 +951,25 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct
/* adding icv, if necessary... */
if (pattrib->iv_len) {
- switch (pattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
- break;
- case _TKIP_:
- if (mcast)
- TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
- else
- TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
- break;
- case _AES_:
- if (mcast)
- AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
- else
- AES_IV(pattrib->iv, psta->dot11txpn, 0);
- break;
+ if (psta) {
+ switch (pattrib->encrypt) {
+ case _WEP40_:
+ case _WEP104_:
+ WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ break;
+ case _TKIP_:
+ if (bmcst)
+ TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ else
+ TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
+ break;
+ case _AES_:
+ if (bmcst)
+ AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ else
+ AES_IV(pattrib->iv, psta->dot11txpn, 0);
+ break;
+ }
}
memcpy(pframe, pattrib->iv, pattrib->iv_len);
@@ -934,12 +985,16 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct
mpdu_len -= llc_sz;
}
- if ((pattrib->icv_len > 0) && (pattrib->bswenc))
+ if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
mpdu_len -= pattrib->icv_len;
+ }
- mem_sz = min_t(size_t, mcast ? pattrib->pktlen : mpdu_len, remainder);
- skb_copy_bits(pkt, pkt->len - remainder, pframe, mem_sz);
- remainder -= mem_sz;
+ if (bmcst) {
+ /* don't do fragment to broadcat/multicast packets */
+ mem_sz = _rtw_pktfile_read(&pktfile, pframe, pattrib->pktlen);
+ } else {
+ mem_sz = _rtw_pktfile_read(&pktfile, pframe, mpdu_len);
+ }
pframe += mem_sz;
@@ -950,7 +1005,7 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct
frg_inx++;
- if (mcast || remainder == 0) {
+ if (bmcst || rtw_endofpktfile(&pktfile)) {
pattrib->nr_frags = frg_inx;
pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + ((pattrib->nr_frags == 1) ? llc_sz : 0) +
@@ -963,26 +1018,25 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct
addr = (size_t)(pframe);
- mem_start = (unsigned char *)round_up(addr, 4) + hw_hdr_offset;
+ mem_start = (unsigned char *)RND4(addr) + hw_hdr_offset;
memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);
}
- /* Frame is about to be encrypted. Forward it to the monitor first. */
- rtl88eu_mon_xmit_hook(padapter->pmondev, pxmitframe, frg_len);
-
if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {
+ DBG_88E("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
res = _FAIL;
goto exit;
}
xmitframe_swencrypt(padapter, pxmitframe);
- if (!mcast)
+ if (!bmcst)
update_attrib_vcs_info(padapter, pxmitframe);
else
pattrib->vcs_mode = NONE_VCS;
exit:
+
return res;
}
@@ -1019,8 +1073,9 @@ s32 rtw_put_snap(u8 *data, u16 h_proto)
void rtw_update_protection(struct adapter *padapter, u8 *ie, uint ie_len)
{
- uint protection, erp_len;
+ uint protection;
u8 *perp;
+ int erp_len;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
@@ -1032,7 +1087,7 @@ void rtw_update_protection(struct adapter *padapter, u8 *ie, uint ie_len)
break;
case AUTO_VCS:
default:
- perp = rtw_get_ie(ie, WLAN_EID_ERP_INFO, &erp_len, ie_len);
+ perp = rtw_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);
if (!perp) {
pxmitpriv->vcs = NONE_VCS;
} else {
@@ -1048,6 +1103,7 @@ void rtw_update_protection(struct adapter *padapter, u8 *ie, uint ie_len)
}
break;
}
+
}
void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe, int sz)
@@ -1072,130 +1128,173 @@ void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe,
struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv)
{
- unsigned long irql;
- struct xmit_buf *pxmitbuf;
+ struct xmit_buf *pxmitbuf = NULL;
+ struct list_head *plist, *phead;
struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pfree_queue->lock, flags);
+
+ if (list_empty(&pfree_queue->queue)) {
+ pxmitbuf = NULL;
+ } else {
+ phead = get_list_head(pfree_queue);
+
+ plist = phead->next;
+
+ pxmitbuf = container_of(plist, struct xmit_buf, list);
- spin_lock_irqsave(&pfree_queue->lock, irql);
- pxmitbuf = list_first_entry_or_null(&pfree_queue->queue,
- struct xmit_buf, list);
- if (pxmitbuf) {
list_del_init(&pxmitbuf->list);
+ }
+
+ if (pxmitbuf) {
pxmitpriv->free_xmit_extbuf_cnt--;
+
pxmitbuf->priv_data = NULL;
- if (pxmitbuf->sctx)
+ /* pxmitbuf->ext_tag = true; */
+
+ if (pxmitbuf->sctx) {
+ DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__);
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
+ }
}
- spin_unlock_irqrestore(&pfree_queue->lock, irql);
+
+ spin_unlock_irqrestore(&pfree_queue->lock, flags);
return pxmitbuf;
}
s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
{
- unsigned long irql;
struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
+ unsigned long flags;
if (!pxmitbuf)
return _FAIL;
- spin_lock_irqsave(&pfree_queue->lock, irql);
+ spin_lock_irqsave(&pfree_queue->lock, flags);
list_del_init(&pxmitbuf->list);
list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue));
pxmitpriv->free_xmit_extbuf_cnt++;
- spin_unlock_irqrestore(&pfree_queue->lock, irql);
+ spin_unlock_irqrestore(&pfree_queue->lock, flags);
return _SUCCESS;
}
struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
{
- unsigned long irql;
- struct xmit_buf *pxmitbuf;
+ struct xmit_buf *pxmitbuf = NULL;
+ struct list_head *plist, *phead;
struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
+ unsigned long flags;
+
+ /* DBG_88E("+rtw_alloc_xmitbuf\n"); */
+
+ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, flags);
+
+ if (list_empty(&pfree_xmitbuf_queue->queue)) {
+ pxmitbuf = NULL;
+ } else {
+ phead = get_list_head(pfree_xmitbuf_queue);
+
+ plist = phead->next;
+
+ pxmitbuf = container_of(plist, struct xmit_buf, list);
- spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql);
- pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue,
- struct xmit_buf, list);
- if (pxmitbuf) {
list_del_init(&pxmitbuf->list);
+ }
+
+ if (pxmitbuf) {
pxmitpriv->free_xmitbuf_cnt--;
pxmitbuf->priv_data = NULL;
if (pxmitbuf->sctx) {
+ DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__);
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
}
}
- spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql);
+ spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, flags);
return pxmitbuf;
}
s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
{
- unsigned long irql;
struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
+ unsigned long flags;
if (!pxmitbuf)
return _FAIL;
- if (pxmitbuf->sctx)
+ if (pxmitbuf->sctx) {
+ DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__);
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE);
+ }
if (pxmitbuf->ext_tag) {
rtw_free_xmitbuf_ext(pxmitpriv, pxmitbuf);
} else {
- spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql);
+ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, flags);
list_del_init(&pxmitbuf->list);
list_add_tail(&pxmitbuf->list, get_list_head(pfree_xmitbuf_queue));
pxmitpriv->free_xmitbuf_cnt++;
- spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql);
+ spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, flags);
}
return _SUCCESS;
}
/*
- * Calling context:
- * 1. OS_TXENTRY
- * 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
- *
- * If we turn on USE_RXTHREAD, then, no need for critical section.
- * Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
- *
- * Must be very, very cautious...
- *
- */
+Calling context:
+1. OS_TXENTRY
+2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
-struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)
- /* _queue *pfree_xmit_queue) */
+If we turn on USE_RXTHREAD, then, no need for critical section.
+Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
+
+Must be very very cautious...
+
+*/
+
+struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */
{
/*
- * Please remember to use all the osdep_service api,
- * and lock/unlock or _enter/_exit critical to protect
- * pfree_xmit_queue
- */
- struct xmit_frame *pxframe;
+ Please remember to use all the osdep_service api,
+ and lock/unlock or _enter/_exit critical to protect
+ pfree_xmit_queue
+ */
+
+ struct xmit_frame *pxframe = NULL;
+ struct list_head *plist, *phead;
struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
spin_lock_bh(&pfree_xmit_queue->lock);
- pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue,
- struct xmit_frame, list);
- if (pxframe) {
+
+ if (list_empty(&pfree_xmit_queue->queue)) {
+ pxframe = NULL;
+ } else {
+ phead = get_list_head(pfree_xmit_queue);
+
+ plist = phead->next;
+
+ pxframe = container_of(plist, struct xmit_frame, list);
+
list_del_init(&pxframe->list);
+ }
- /* default value setting */
+ if (pxframe) { /* default value setting */
pxmitpriv->free_xmitframe_cnt--;
pxframe->buf_addr = NULL;
pxframe->pxmitbuf = NULL;
memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
+ /* pxframe->attrib.psta = NULL; */
pxframe->frame_tag = DATA_FRAMETAG;
@@ -1205,6 +1304,7 @@ struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)
pxframe->agg_num = 1;
pxframe->ack_report = 0;
}
+
spin_unlock_bh(&pfree_xmit_queue->lock);
return pxframe;
@@ -1238,27 +1338,37 @@ s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitfram
rtw_os_pkt_complete(padapter, pndis_pkt);
exit:
+
return _SUCCESS;
}
void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pframequeue)
{
- struct list_head *phead;
- struct xmit_frame *pxmitframe, *temp;
+ struct list_head *plist, *phead;
+ struct xmit_frame *pxmitframe;
spin_lock_bh(&pframequeue->lock);
phead = get_list_head(pframequeue);
- list_for_each_entry_safe(pxmitframe, temp, phead, list)
- rtw_free_xmitframe(pxmitpriv, pxmitframe);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pxmitframe = container_of(plist, struct xmit_frame, list);
+
+ plist = plist->next;
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+ }
spin_unlock_bh(&pframequeue->lock);
+
}
s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
{
- if (rtw_xmit_classifier(padapter, pxmitframe) == _FAIL)
+ if (rtw_xmit_classifier(padapter, pxmitframe) == _FAIL) {
+/* pxmitframe->pkt = NULL; */
return _FAIL;
+ }
return _SUCCESS;
}
@@ -1309,9 +1419,10 @@ struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmi
phwxmit = phwxmit_i + inx[i];
sta_phead = get_list_head(phwxmit->sta_queue);
- list_for_each(sta_plist, sta_phead) {
- ptxservq = list_entry(sta_plist, struct tx_servq,
- tx_pending);
+ sta_plist = sta_phead->next;
+
+ while (sta_phead != sta_plist) {
+ ptxservq = container_of(sta_plist, struct tx_servq, tx_pending);
pframe_queue = &ptxservq->sta_pending;
@@ -1325,15 +1436,17 @@ struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmi
list_del_init(&ptxservq->tx_pending);
goto exit;
}
+
+ sta_plist = sta_plist->next;
}
}
exit:
spin_unlock_bh(&pxmitpriv->lock);
+
return pxmitframe;
}
-struct tx_servq *rtw_get_sta_pending(struct adapter *padapter,
- struct sta_info *psta, int up, u8 *ac)
+struct tx_servq *rtw_get_sta_pending(struct adapter *padapter, struct sta_info *psta, int up, u8 *ac)
{
struct tx_servq *ptxservq;
@@ -1378,13 +1491,15 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
int res = _SUCCESS;
- if (pattrib->psta)
+ if (pattrib->psta) {
psta = pattrib->psta;
- else
+ } else {
psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+ }
if (!psta) {
res = _FAIL;
+ DBG_88E("rtw_xmit_classifier: psta == NULL\n");
goto exit;
}
@@ -1397,28 +1512,34 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
ptxservq->qcnt++;
phwxmits[ac_index].accnt++;
exit:
+
return res;
}
-s32 rtw_alloc_hwxmits(struct adapter *padapter)
+void rtw_alloc_hwxmits(struct adapter *padapter)
{
struct hw_xmit *hwxmits;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
- pxmitpriv->hwxmits = kcalloc(pxmitpriv->hwxmit_entry,
- sizeof(struct hw_xmit), GFP_KERNEL);
- if (!pxmitpriv->hwxmits)
- return _FAIL;
+ pxmitpriv->hwxmits = kzalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry, GFP_KERNEL);
hwxmits = pxmitpriv->hwxmits;
- hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
- hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
- hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
- hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
- return _SUCCESS;
+ if (pxmitpriv->hwxmit_entry == 5) {
+ hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
+ hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
+ hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
+ hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
+ hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
+ } else if (pxmitpriv->hwxmit_entry == 4) {
+ hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
+ hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
+ hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
+ hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
+ } else {
+ }
}
void rtw_free_hwxmits(struct adapter *padapter)
@@ -1436,6 +1557,128 @@ void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry)
for (i = 0; i < entry; i++, phwxmit++)
phwxmit->accnt = 0;
+
+}
+
+static int rtw_br_client_tx(struct adapter *padapter, struct sk_buff **pskb)
+{
+ struct sk_buff *skb = *pskb;
+ int res, is_vlan_tag = 0, i, do_nat25 = 1;
+ unsigned short vlan_hdr = 0;
+ void *br_port = NULL;
+
+ rcu_read_lock();
+ br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
+ rcu_read_unlock();
+ spin_lock_bh(&padapter->br_ext_lock);
+ if (!(skb->data[0] & 1) && br_port &&
+ memcmp(skb->data + MACADDRLEN, padapter->br_mac, MACADDRLEN) &&
+ *((__be16 *)(skb->data + MACADDRLEN * 2)) != __constant_htons(ETH_P_8021Q) &&
+ *((__be16 *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP) &&
+ !memcmp(padapter->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN) && padapter->scdb_entry) {
+ memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);
+ padapter->scdb_entry->ageing_timer = jiffies;
+ spin_unlock_bh(&padapter->br_ext_lock);
+ } else {
+ if (*((__be16 *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q)) {
+ is_vlan_tag = 1;
+ vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2));
+ for (i = 0; i < 6; i++)
+ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2));
+ skb_pull(skb, 4);
+ }
+ if (!memcmp(skb->data + MACADDRLEN, padapter->br_mac, MACADDRLEN) &&
+ (*((__be16 *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP)))
+ memcpy(padapter->br_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4);
+
+ if (*((__be16 *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP)) {
+ if (memcmp(padapter->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN)) {
+ padapter->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(padapter,
+ skb->data + MACADDRLEN, skb->data + WLAN_ETHHDR_LEN + 12);
+ if (padapter->scdb_entry) {
+ memcpy(padapter->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN);
+ memcpy(padapter->scdb_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4);
+ padapter->scdb_entry->ageing_timer = jiffies;
+ do_nat25 = 0;
+ }
+ } else {
+ if (padapter->scdb_entry) {
+ padapter->scdb_entry->ageing_timer = jiffies;
+ do_nat25 = 0;
+ } else {
+ memset(padapter->scdb_mac, 0, MACADDRLEN);
+ memset(padapter->scdb_ip, 0, 4);
+ }
+ }
+ }
+ spin_unlock_bh(&padapter->br_ext_lock);
+ if (do_nat25) {
+ if (nat25_db_handle(padapter, skb, NAT25_CHECK) == 0) {
+ struct sk_buff *newskb;
+
+ if (is_vlan_tag) {
+ skb_push(skb, 4);
+ for (i = 0; i < 6; i++)
+ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2));
+ *((__be16 *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q);
+ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr;
+ }
+
+ newskb = skb_copy(skb, GFP_ATOMIC);
+ if (!newskb) {
+ DEBUG_ERR("TX DROP: skb_copy fail!\n");
+ return -1;
+ }
+ dev_kfree_skb_any(skb);
+
+ *pskb = skb = newskb;
+ if (is_vlan_tag) {
+ vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2));
+ for (i = 0; i < 6; i++)
+ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2));
+ skb_pull(skb, 4);
+ }
+ }
+
+ if (skb_is_nonlinear(skb))
+ DEBUG_ERR("%s(): skb_is_nonlinear!!\n", __func__);
+
+ res = skb_linearize(skb);
+ if (res < 0) {
+ DEBUG_ERR("TX DROP: skb_linearize fail!\n");
+ return -1;
+ }
+
+ res = nat25_db_handle(padapter, skb, NAT25_INSERT);
+ if (res < 0) {
+ if (res == -2) {
+ DEBUG_ERR("TX DROP: nat25_db_handle fail!\n");
+ return -1;
+ }
+ return 0;
+ }
+ }
+
+ memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);
+
+ dhcp_flag_bcast(padapter, skb);
+
+ if (is_vlan_tag) {
+ skb_push(skb, 4);
+ for (i = 0; i < 6; i++)
+ *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2));
+ *((__be16 *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q);
+ *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr;
+ }
+ }
+
+ /* check if SA is equal to our MAC */
+ if (memcmp(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN)) {
+ DEBUG_ERR("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n",
+ skb->data[6], skb->data[7], skb->data[8], skb->data[9], skb->data[10], skb->data[11]);
+ return -1;
+ }
+ return 0;
}
u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe)
@@ -1475,6 +1718,15 @@ u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe)
return addr;
}
+static void do_queue_select(struct adapter *padapter, struct pkt_attrib *pattrib)
+{
+ u8 qsel;
+
+ qsel = pattrib->priority;
+
+ pattrib->qsel = qsel;
+}
+
/*
* The main transmit(tx) entry
*
@@ -1487,11 +1739,27 @@ s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct xmit_frame *pxmitframe = NULL;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ void *br_port = NULL;
s32 res;
pxmitframe = rtw_alloc_xmitframe(pxmitpriv);
- if (!pxmitframe)
+ if (!pxmitframe) {
+ DBG_88E("DBG_TX_DROP_FRAME %s no more pxmitframe\n", __func__);
return -1;
+ }
+
+ rcu_read_lock();
+ br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
+ rcu_read_unlock();
+
+ if (br_port && check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
+ res = rtw_br_client_tx(padapter, ppkt);
+ if (res == -1) {
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+ return -1;
+ }
+ }
res = update_attrib(padapter, *ppkt, &pxmitframe->attrib);
@@ -1501,9 +1769,9 @@ s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt)
}
pxmitframe->pkt = *ppkt;
- led_control_8188eu(padapter, LED_CTL_TX);
+ rtw_led_control(padapter, LED_CTL_TX);
- pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
+ do_queue_select(padapter, &pxmitframe->attrib);
#ifdef CONFIG_88EU_AP_MODE
spin_lock_bh(&pxmitpriv->lock);
@@ -1529,10 +1797,10 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
struct sta_priv *pstapriv = &padapter->stapriv;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- bool mcast = is_multicast_ether_addr(pattrib->ra);
+ bool bmcst = is_multicast_ether_addr(pattrib->ra);
if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return ret;
+ return ret;
if (pattrib->psta)
psta = pattrib->psta;
@@ -1543,12 +1811,12 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
return ret;
if (pattrib->triggered == 1) {
- if (mcast)
+ if (bmcst)
pattrib->qsel = 0x11;/* HIQ */
return ret;
}
- if (mcast) {
+ if (bmcst) {
spin_lock_bh(&psta->sleep_q.lock);
if (pstapriv->sta_dz_bitmap) {/* if any one sta is in ps mode */
@@ -1561,7 +1829,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
pstapriv->tim_bitmap |= BIT(0);/* */
pstapriv->sta_dz_bitmap |= BIT(0);
- update_beacon(padapter, WLAN_EID_TIM, NULL, false);/* tx bc/mc packets after update bcn */
+ update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after upate bcn */
ret = true;
}
@@ -1611,8 +1879,8 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
pstapriv->tim_bitmap |= BIT(psta->aid);
if (psta->sleepq_len == 1) {
- /* update BCN for TIM IE */
- update_beacon(padapter, WLAN_EID_TIM, NULL, false);
+ /* upate BCN for TIM IE */
+ update_beacon(padapter, _TIM_IE_, NULL, false);
}
}
ret = true;
@@ -1626,15 +1894,21 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
static void dequeue_xmitframes_to_sleeping_queue(struct adapter *padapter, struct sta_info *psta, struct __queue *pframequeue)
{
- struct list_head *phead;
+ struct list_head *plist, *phead;
u8 ac_index;
struct tx_servq *ptxservq;
struct pkt_attrib *pattrib;
- struct xmit_frame *pxmitframe, *n;
+ struct xmit_frame *pxmitframe;
struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
phead = get_list_head(pframequeue);
- list_for_each_entry_safe(pxmitframe, n, phead, list) {
+ plist = phead->next;
+
+ while (phead != plist) {
+ pxmitframe = container_of(plist, struct xmit_frame, list);
+
+ plist = plist->next;
+
xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe);
pattrib = &pxmitframe->attrib;
@@ -1664,26 +1938,21 @@ void stop_sta_xmit(struct adapter *padapter, struct sta_info *psta)
pstapriv->sta_dz_bitmap |= BIT(psta->aid);
- dequeue_xmitframes_to_sleeping_queue(padapter, psta,
- &pstaxmitpriv->vo_q.sta_pending);
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
list_del_init(&pstaxmitpriv->vo_q.tx_pending);
- dequeue_xmitframes_to_sleeping_queue(padapter, psta,
- &pstaxmitpriv->vi_q.sta_pending);
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);
list_del_init(&pstaxmitpriv->vi_q.tx_pending);
- dequeue_xmitframes_to_sleeping_queue(padapter, psta,
- &pstaxmitpriv->be_q.sta_pending);
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->be_q.sta_pending);
list_del_init(&pstaxmitpriv->be_q.tx_pending);
- dequeue_xmitframes_to_sleeping_queue(padapter, psta,
- &pstaxmitpriv->bk_q.sta_pending);
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->bk_q.sta_pending);
list_del_init(&pstaxmitpriv->bk_q.tx_pending);
/* for BC/MC Frames */
pstaxmitpriv = &psta_bmc->sta_xmitpriv;
- dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc,
- &pstaxmitpriv->be_q.sta_pending);
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->be_q.sta_pending);
list_del_init(&pstaxmitpriv->be_q.tx_pending);
spin_unlock_bh(&pxmitpriv->lock);
@@ -1693,14 +1962,20 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
{
u8 update_mask = 0, wmmps_ac = 0;
struct sta_info *psta_bmc;
- struct list_head *xmitframe_phead;
- struct xmit_frame *pxmitframe, *n;
+ struct list_head *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
spin_lock_bh(&psta->sleep_q.lock);
xmitframe_phead = get_list_head(&psta->sleep_q);
- list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, list) {
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
list_del_init(&pxmitframe->list);
switch (pxmitframe->attrib.priority) {
@@ -1775,7 +2050,13 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
spin_lock_bh(&psta_bmc->sleep_q.lock);
xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
- list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, list) {
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
list_del_init(&pxmitframe->list);
psta_bmc->sleepq_len--;
@@ -1803,20 +2084,26 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
}
if (update_mask)
- update_beacon(padapter, WLAN_EID_TIM, NULL, false);
+ update_beacon(padapter, _TIM_IE_, NULL, false);
}
void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *psta)
{
u8 wmmps_ac = 0;
- struct list_head *xmitframe_phead;
- struct xmit_frame *pxmitframe, *n;
+ struct list_head *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
spin_lock_bh(&psta->sleep_q.lock);
xmitframe_phead = get_list_head(&psta->sleep_q);
- list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, list) {
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
switch (pxmitframe->attrib.priority) {
case 1:
case 2:
@@ -1861,8 +2148,8 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst
if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) {
pstapriv->tim_bitmap &= ~BIT(psta->aid);
- /* update BCN for TIM IE */
- update_beacon(padapter, WLAN_EID_TIM, NULL, false);
+ /* upate BCN for TIM IE */
+ update_beacon(padapter, _TIM_IE_, NULL, false);
}
}
@@ -1889,6 +2176,7 @@ int rtw_sctx_wait(struct submit_ctx *sctx)
if (!wait_for_completion_timeout(&sctx->done, expire)) {
/* timeout, do something?? */
status = RTW_SCTX_DONE_TIMEOUT;
+ DBG_88E("%s timeout\n", __func__);
} else {
status = sctx->status;
}
@@ -1899,15 +2187,37 @@ int rtw_sctx_wait(struct submit_ctx *sctx)
return ret;
}
+static bool rtw_sctx_chk_waring_status(int status)
+{
+ switch (status) {
+ case RTW_SCTX_DONE_UNKNOWN:
+ case RTW_SCTX_DONE_BUF_ALLOC:
+ case RTW_SCTX_DONE_BUF_FREE:
+
+ case RTW_SCTX_DONE_DRV_STOP:
+ case RTW_SCTX_DONE_DEV_REMOVE:
+ return true;
+ default:
+ return false;
+ }
+}
+
void rtw_sctx_done_err(struct submit_ctx **sctx, int status)
{
if (*sctx) {
+ if (rtw_sctx_chk_waring_status(status))
+ DBG_88E("%s status:%d\n", __func__, status);
(*sctx)->status = status;
complete(&((*sctx)->done));
*sctx = NULL;
}
}
+void rtw_sctx_done(struct submit_ctx **sctx)
+{
+ rtw_sctx_done_err(sctx, RTW_SCTX_DONE_SUCCESS);
+}
+
int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms)
{
struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
@@ -1925,4 +2235,6 @@ void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status)
if (pxmitpriv->ack_tx)
rtw_sctx_done_err(&pack_tx_ops, status);
+ else
+ DBG_88E("%s ack_tx not set\n", __func__);
}
diff --git a/drivers/staging/r8188eu/hal/Hal8188EPwrSeq.c b/drivers/staging/r8188eu/hal/Hal8188EPwrSeq.c
new file mode 100644
index 000000000000..48ede610cd28
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/Hal8188EPwrSeq.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/Hal8188EPwrSeq.h"
+#include "../include/rtl8188e_hal.h"
+
+/*
+ drivers should parse below arrays and do the corresponding actions
+*/
+/* 3 Power on Array */
+struct wl_pwr_cfg rtl8188E_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_CARDEMU_TO_ACT
+ RTL8188E_TRANS_END
+};
+
+/* 3Radio off Array */
+struct wl_pwr_cfg rtl8188E_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_ACT_TO_CARDEMU
+ RTL8188E_TRANS_END
+};
+
+/* 3Card Disable Array */
+struct wl_pwr_cfg rtl8188E_card_disable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_ACT_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_CARDDIS
+ RTL8188E_TRANS_END
+};
+
+/* 3 Card Enable Array */
+struct wl_pwr_cfg rtl8188E_card_enable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_CARDDIS_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_ACT
+ RTL8188E_TRANS_END
+};
+
+/* 3Suspend Array */
+struct wl_pwr_cfg rtl8188E_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_ACT_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_SUS
+ RTL8188E_TRANS_END
+};
+
+/* 3 Resume Array */
+struct wl_pwr_cfg rtl8188E_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_SUS_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_ACT
+ RTL8188E_TRANS_END
+};
+
+/* 3HWPDN Array */
+struct wl_pwr_cfg rtl8188E_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_ACT_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_PDN
+ RTL8188E_TRANS_END
+};
+
+/* 3 Enter LPS */
+struct wl_pwr_cfg rtl8188E_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ /* FW behavior */
+ RTL8188E_TRANS_ACT_TO_LPS
+ RTL8188E_TRANS_END
+};
+
+/* 3 Leave LPS */
+struct wl_pwr_cfg rtl8188E_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS] = {
+ /* FW behavior */
+ RTL8188E_TRANS_LPS_TO_ACT
+ RTL8188E_TRANS_END
+};
diff --git a/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c b/drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c
index 74fff76af16d..d873672feb27 100644
--- a/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c
+++ b/drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c
@@ -1,9 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
- */
+/* Copyright (c) Realtek Semiconductor Corp.
+Module Name:
+ RateAdaptive.c
-#include "odm_precomp.h"
+Abstract:
+ Implement Rate Adaptive functions for common operations.
+
+Major Change History:
+ When Who What
+ ---------- --------------- -------------------------------
+ 2011-08-12 Page Create.
+
+--*/
+#include "../include/odm_precomp.h"
/* Rate adaptive parameters */
@@ -81,8 +90,11 @@ static u16 DynamicTxRPTTiming[6] = {
/* End Rate adaptive parameters */
-static void odm_SetTxRPTTiming_8188E(struct odm_dm_struct *dm_odm,
- struct odm_ra_info *pRaInfo, u8 extend)
+static void odm_SetTxRPTTiming_8188E(
+ struct odm_dm_struct *dm_odm,
+ struct odm_ra_info *pRaInfo,
+ u8 extend
+ )
{
u8 idx = 0;
@@ -103,15 +115,13 @@ static void odm_SetTxRPTTiming_8188E(struct odm_dm_struct *dm_odm,
pRaInfo->RptTime = DynamicTxRPTTiming[idx];
}
-static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm,
- struct odm_ra_info *pRaInfo)
+static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo)
{
u8 RateID, LowestRate, HighestRate;
u8 i;
- if (!pRaInfo)
+ if (NULL == pRaInfo)
return -1;
-
RateID = pRaInfo->PreRate;
LowestRate = pRaInfo->LowestRate;
HighestRate = pRaInfo->HighestRate;
@@ -151,15 +161,16 @@ RateDownFinish:
return 0;
}
-static int odm_RateUp_8188E(struct odm_dm_struct *dm_odm,
- struct odm_ra_info *pRaInfo)
+static int odm_RateUp_8188E(
+ struct odm_dm_struct *dm_odm,
+ struct odm_ra_info *pRaInfo
+ )
{
u8 RateID, HighestRate;
u8 i;
- if (!pRaInfo)
+ if (NULL == pRaInfo)
return -1;
-
RateID = pRaInfo->PreRate;
HighestRate = pRaInfo->HighestRate;
if (pRaInfo->RAWaitingCounter == 1) {
@@ -187,8 +198,7 @@ static int odm_RateUp_8188E(struct odm_dm_struct *dm_odm,
RateID = HighestRate;
}
RateUpfinish:
- if (pRaInfo->RAWaitingCounter ==
- (4 + PendingForRateUpFail[pRaInfo->RAPendingCounter]))
+ if (pRaInfo->RAWaitingCounter == (4 + PendingForRateUpFail[pRaInfo->RAPendingCounter]))
pRaInfo->RAWaitingCounter = 0;
else
pRaInfo->RAWaitingCounter++;
@@ -202,16 +212,15 @@ static void odm_ResetRaCounter_8188E(struct odm_ra_info *pRaInfo)
u8 RateID;
RateID = pRaInfo->DecisionRate;
- pRaInfo->NscUp = (N_THRESHOLD_HIGH[RateID] +
- N_THRESHOLD_LOW[RateID]) >> 1;
- pRaInfo->NscDown = (N_THRESHOLD_HIGH[RateID] +
- N_THRESHOLD_LOW[RateID]) >> 1;
+ pRaInfo->NscUp = (N_THRESHOLD_HIGH[RateID] + N_THRESHOLD_LOW[RateID]) >> 1;
+ pRaInfo->NscDown = (N_THRESHOLD_HIGH[RateID] + N_THRESHOLD_LOW[RateID]) >> 1;
}
static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
- struct odm_ra_info *pRaInfo)
+ struct odm_ra_info *pRaInfo
+ )
{
- u8 RateID = 0, RtyPtID = 0, PenaltyID1 = 0, PenaltyID2 = 0, i = 0;
+ u8 RateID = 0, RtyPtID = 0, PenaltyID1 = 0, PenaltyID2 = 0;
/* u32 pool_retry; */
static u8 DynamicTxRPTTimingCounter;
@@ -232,9 +241,11 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
RtyPtID = 1;
PenaltyID1 = RETRY_PENALTY_IDX[RtyPtID][RateID]; /* TODO by page */
- for (i = 0 ; i <= 4 ; i++)
- pRaInfo->NscDown += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID1][i];
-
+ pRaInfo->NscDown += pRaInfo->RTY[0] * RETRY_PENALTY[PenaltyID1][0];
+ pRaInfo->NscDown += pRaInfo->RTY[1] * RETRY_PENALTY[PenaltyID1][1];
+ pRaInfo->NscDown += pRaInfo->RTY[2] * RETRY_PENALTY[PenaltyID1][2];
+ pRaInfo->NscDown += pRaInfo->RTY[3] * RETRY_PENALTY[PenaltyID1][3];
+ pRaInfo->NscDown += pRaInfo->RTY[4] * RETRY_PENALTY[PenaltyID1][4];
if (pRaInfo->NscDown > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5]))
pRaInfo->NscDown -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5];
else
@@ -242,10 +253,11 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
/* rate up */
PenaltyID2 = RETRY_PENALTY_UP_IDX[RateID];
-
- for (i = 0 ; i <= 4 ; i++)
- pRaInfo->NscUp += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID2][i];
-
+ pRaInfo->NscUp += pRaInfo->RTY[0] * RETRY_PENALTY[PenaltyID2][0];
+ pRaInfo->NscUp += pRaInfo->RTY[1] * RETRY_PENALTY[PenaltyID2][1];
+ pRaInfo->NscUp += pRaInfo->RTY[2] * RETRY_PENALTY[PenaltyID2][2];
+ pRaInfo->NscUp += pRaInfo->RTY[3] * RETRY_PENALTY[PenaltyID2][3];
+ pRaInfo->NscUp += pRaInfo->RTY[4] * RETRY_PENALTY[PenaltyID2][4];
if (pRaInfo->NscUp > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5]))
pRaInfo->NscUp -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5];
else
@@ -278,47 +290,46 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo)
{ /* Wilson 2011/10/26 */
- struct adapter *adapt = dm_odm->Adapter;
u32 MaskFromReg;
s8 i;
switch (pRaInfo->RateID) {
case RATR_INX_WIRELESS_NGB:
- pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0f8ff015;
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0f8ff015;
break;
case RATR_INX_WIRELESS_NG:
- pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0f8ff010;
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0f8ff010;
break;
case RATR_INX_WIRELESS_NB:
- pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0f8ff005;
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0f8ff005;
break;
case RATR_INX_WIRELESS_N:
- pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0f8ff000;
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0f8ff000;
break;
case RATR_INX_WIRELESS_GB:
- pRaInfo->RAUseRate = pRaInfo->RateMask & 0x00000ff5;
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x00000ff5;
break;
case RATR_INX_WIRELESS_G:
- pRaInfo->RAUseRate = pRaInfo->RateMask & 0x00000ff0;
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x00000ff0;
break;
case RATR_INX_WIRELESS_B:
- pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0000000d;
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0000000d;
break;
case 12:
- MaskFromReg = usb_read32(adapt, REG_ARFR0);
- pRaInfo->RAUseRate = pRaInfo->RateMask & MaskFromReg;
+ MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR0);
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
break;
case 13:
- MaskFromReg = usb_read32(adapt, REG_ARFR1);
- pRaInfo->RAUseRate = pRaInfo->RateMask & MaskFromReg;
+ MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR1);
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
break;
case 14:
- MaskFromReg = usb_read32(adapt, REG_ARFR2);
- pRaInfo->RAUseRate = pRaInfo->RateMask & MaskFromReg;
+ MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR2);
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
break;
case 15:
- MaskFromReg = usb_read32(adapt, REG_ARFR3);
- pRaInfo->RAUseRate = pRaInfo->RateMask & MaskFromReg;
+ MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR3);
+ pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
break;
default:
pRaInfo->RAUseRate = (pRaInfo->RateMask);
@@ -327,7 +338,7 @@ static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_inf
/* Highest rate */
if (pRaInfo->RAUseRate) {
for (i = RATESIZE; i >= 0; i--) {
- if (pRaInfo->RAUseRate & BIT(i)) {
+ if ((pRaInfo->RAUseRate) & BIT(i)) {
pRaInfo->HighestRate = i;
break;
}
@@ -346,7 +357,6 @@ static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_inf
} else {
pRaInfo->LowestRate = 0;
}
-
if (pRaInfo->HighestRate > 0x13)
pRaInfo->PTModeSS = 3;
else if (pRaInfo->HighestRate > 0x0b)
@@ -430,16 +440,14 @@ static void odm_PTDecision_8188E(struct odm_ra_info *pRaInfo)
break;
}
- j >>= 1;
+ j = j >> 1;
temp_stage = (pRaInfo->PTStage + 1) >> 1;
if (temp_stage > j)
stage_id = temp_stage - j;
else
stage_id = 0;
- pRaInfo->PTSmoothFactor = (pRaInfo->PTSmoothFactor >> 1) +
- (pRaInfo->PTSmoothFactor >> 2) +
- stage_id * 16 + 2;
+ pRaInfo->PTSmoothFactor = (pRaInfo->PTSmoothFactor >> 1) + (pRaInfo->PTSmoothFactor >> 2) + stage_id * 16 + 2;
if (pRaInfo->PTSmoothFactor > 192)
pRaInfo->PTSmoothFactor = 192;
stage_id = pRaInfo->PTSmoothFactor >> 6;
@@ -451,8 +459,11 @@ static void odm_PTDecision_8188E(struct odm_ra_info *pRaInfo)
pRaInfo->PTStage = temp_stage;
}
-static void odm_RATxRPTTimerSetting(struct odm_dm_struct *dm_odm,
- u16 minRptTime)
+static void
+odm_RATxRPTTimerSetting(
+ struct odm_dm_struct *dm_odm,
+ u16 minRptTime
+)
{
if (dm_odm->CurrminRptTime != minRptTime) {
rtw_rpt_timer_cfg_cmd(dm_odm->Adapter, minRptTime);
@@ -460,12 +471,21 @@ static void odm_RATxRPTTimerSetting(struct odm_dm_struct *dm_odm,
}
}
+void
+ODM_RASupport_Init(
+ struct odm_dm_struct *dm_odm
+ )
+{
+ /* 2012/02/14 MH Be noticed, the init must be after IC type is recognized!!!!! */
+ if (dm_odm->SupportICType == ODM_RTL8188E)
+ dm_odm->RaSupport88E = true;
+}
+
int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid)
{
struct odm_ra_info *pRaInfo = &dm_odm->RAInfo[macid];
u8 WirelessMode = 0xFF; /* invalid value */
u8 max_rate_idx = 0x13; /* MCS7 */
-
if (dm_odm->pWirelessMode)
WirelessMode = *dm_odm->pWirelessMode;
@@ -528,7 +548,7 @@ int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm)
u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 macid)
{
- if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return 0;
return dm_odm->RAInfo[macid].RateSGI;
}
@@ -537,9 +557,9 @@ u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 macid)
{
u8 DecisionRate = 0;
- if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return 0;
- DecisionRate = dm_odm->RAInfo[macid].DecisionRate;
+ DecisionRate = (dm_odm->RAInfo[macid].DecisionRate);
return DecisionRate;
}
@@ -547,9 +567,9 @@ u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 macid)
{
u8 PTStage = 5;
- if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return 0;
- PTStage = dm_odm->RAInfo[macid].PTStage;
+ PTStage = (dm_odm->RAInfo[macid].PTStage);
return PTStage;
}
@@ -557,7 +577,7 @@ void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rate
{
struct odm_ra_info *pRaInfo = NULL;
- if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return;
pRaInfo = &dm_odm->RAInfo[macid];
@@ -571,7 +591,7 @@ void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi)
{
struct odm_ra_info *pRaInfo = NULL;
- if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return;
pRaInfo = &dm_odm->RAInfo[macid];
@@ -580,9 +600,7 @@ void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi)
void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime)
{
- struct adapter *adapt = dm_odm->Adapter;
-
- usb_write16(adapt, REG_TX_RPT_TIME, minRptTime);
+ ODM_Write2Byte(dm_odm, REG_TX_RPT_TIME, minRptTime);
}
void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 TxRPT_Len, u32 macid_entry0, u32 macid_entry1)
@@ -608,7 +626,7 @@ void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16
if (valid) {
pRAInfo->RTY[0] = (u16)GET_TX_REPORT_TYPE1_RERTY_0(pBuffer);
pRAInfo->RTY[1] = (u16)GET_TX_REPORT_TYPE1_RERTY_1(pBuffer);
- pRAInfo->RTY[2] = (u16)GET_TX_REPORT_TYPE1_RERTY_2(pBuffer);
+ pRAInfo->RTY[2] = (u16)GET_TX_REPORT_TYPE1_RERTY_2((u8 *)pBuffer);
pRAInfo->RTY[3] = (u16)GET_TX_REPORT_TYPE1_RERTY_3(pBuffer);
pRAInfo->RTY[4] = (u16)GET_TX_REPORT_TYPE1_RERTY_4(pBuffer);
pRAInfo->DROP = (u16)GET_TX_REPORT_TYPE1_DROP_0(pBuffer);
diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/r8188eu/hal/HalHWImg8188E_BB.c
index 51882858fcf0..55aa20a30342 100644
--- a/drivers/staging/rtl8188eu/hal/bb_cfg.c
+++ b/drivers/staging/r8188eu/hal/HalHWImg8188E_BB.c
@@ -1,15 +1,45 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
-#include "odm_precomp.h"
+#include "../include/odm_precomp.h"
+#include "../include/rtw_iol.h"
-#include <phy.h>
+#define read_next_pair(array, v1, v2, i) \
+ do { \
+ i += 2; \
+ v1 = array[i]; \
+ v2 = array[i + 1]; \
+ } while (0)
-/* AGC_TAB_1T.TXT */
+static bool CheckCondition(const u32 condition, const u32 hex)
+{
+ u32 _board = (hex & 0x000000FF);
+ u32 _interface = (hex & 0x0000FF00) >> 8;
+ u32 _platform = (hex & 0x00FF0000) >> 16;
+ u32 cond = condition;
+
+ if (condition == 0xCDCDCDCD)
+ return true;
+
+ cond = condition & 0x000000FF;
+ if ((_board == cond) && cond != 0x00)
+ return false;
+
+ cond = condition & 0x0000FF00;
+ cond = cond >> 8;
+ if ((_interface & cond) == 0 && cond != 0x07)
+ return false;
+
+ cond = condition & 0x00FF0000;
+ cond = cond >> 16;
+ if ((_platform & cond) == 0 && cond != 0x0F)
+ return false;
+ return true;
+}
+
+/******************************************************************************
+* AGC_TAB_1T.TXT
+******************************************************************************/
static u32 array_agc_tab_1t_8188e[] = {
0xC78, 0xFB000001,
@@ -142,25 +172,91 @@ static u32 array_agc_tab_1t_8188e[] = {
0xC78, 0x407F0001,
};
-static bool set_baseband_agc_config(struct adapter *adapt)
+enum HAL_STATUS ODM_ReadAndConfig_AGC_TAB_1T_8188E(struct odm_dm_struct *dm_odm)
{
- u32 i;
- const u32 arraylen = ARRAY_SIZE(array_agc_tab_1t_8188e);
- u32 *array = array_agc_tab_1t_8188e;
+ u32 hex = 0;
+ u32 i = 0;
+ u8 platform = dm_odm->SupportPlatform;
+ u8 interfaceValue = dm_odm->SupportInterface;
+ u8 board = dm_odm->BoardType;
+ u32 arraylen = sizeof(array_agc_tab_1t_8188e) / sizeof(u32);
+ u32 *array = array_agc_tab_1t_8188e;
+ bool biol = false;
+ struct adapter *adapter = dm_odm->Adapter;
+ struct xmit_frame *pxmit_frame = NULL;
+ u8 bndy_cnt = 1;
+ enum HAL_STATUS rst = HAL_STATUS_SUCCESS;
+
+ hex += board;
+ hex += interfaceValue << 8;
+ hex += platform << 16;
+ hex += 0xFF000000;
+ biol = rtw_IOL_applied(adapter);
+
+ if (biol) {
+ pxmit_frame = rtw_IOL_accquire_xmit_frame(adapter);
+ if (!pxmit_frame) {
+ pr_info("rtw_IOL_accquire_xmit_frame failed\n");
+ return HAL_STATUS_FAILURE;
+ }
+ }
for (i = 0; i < arraylen; i += 2) {
u32 v1 = array[i];
u32 v2 = array[i + 1];
+ /* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
- phy_set_bb_reg(adapt, v1, bMaskDWord, v2);
- udelay(1);
+ if (biol) {
+ if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
+ bndy_cnt++;
+ rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord);
+ } else {
+ odm_ConfigBB_AGC_8188E(dm_odm, v1, bMaskDWord, v2);
+ }
+ continue;
+ } else {
+ /* This line is the start line of branch. */
+ if (!CheckCondition(array[i], hex)) {
+ /* Discard the following (offset, data) pairs. */
+ read_next_pair(array, v1, v2, i);
+ while (v2 != 0xDEAD &&
+ v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < arraylen - 2)
+ read_next_pair(array, v1, v2, i);
+ i -= 2; /* prevent from for-loop += 2 */
+ } else { /* Configure matched pairs and skip to end of if-else. */
+ read_next_pair(array, v1, v2, i);
+ while (v2 != 0xDEAD &&
+ v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < arraylen - 2) {
+ if (biol) {
+ if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
+ bndy_cnt++;
+ rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord);
+ } else {
+ odm_ConfigBB_AGC_8188E(dm_odm, v1, bMaskDWord, v2);
+ }
+ read_next_pair(array, v1, v2, i);
+ }
+
+ while (v2 != 0xDEAD && i < arraylen - 2)
+ read_next_pair(array, v1, v2, i);
+ }
}
}
- return true;
+ if (biol) {
+ if (!rtw_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
+ printk("~~~ %s IOL_exec_cmds Failed !!!\n", __func__);
+ rst = HAL_STATUS_FAILURE;
+ }
+ }
+ return rst;
}
-/* PHY_REG_1T.TXT */
+/******************************************************************************
+* PHY_REG_1T.TXT
+******************************************************************************/
static u32 array_phy_reg_1t_8188e[] = {
0x800, 0x80040000,
@@ -356,44 +452,122 @@ static u32 array_phy_reg_1t_8188e[] = {
0xF00, 0x00000300,
};
-static void rtl_bb_delay(struct adapter *adapt, u32 addr, u32 data)
+enum HAL_STATUS ODM_ReadAndConfig_PHY_REG_1T_8188E(struct odm_dm_struct *dm_odm)
{
- if (addr == 0xfe) {
- msleep(50);
- } else if (addr == 0xfd) {
- mdelay(5);
- } else if (addr == 0xfc) {
- mdelay(1);
- } else if (addr == 0xfb) {
- udelay(50);
- } else if (addr == 0xfa) {
- udelay(5);
- } else if (addr == 0xf9) {
- udelay(1);
- } else {
- phy_set_bb_reg(adapt, addr, bMaskDWord, data);
- /* Add 1us delay between BB/RF register setting. */
- udelay(1);
+ u32 hex = 0;
+ u32 i = 0;
+ u8 platform = dm_odm->SupportPlatform;
+ u8 interfaceValue = dm_odm->SupportInterface;
+ u8 board = dm_odm->BoardType;
+ u32 arraylen = sizeof(array_phy_reg_1t_8188e) / sizeof(u32);
+ u32 *array = array_phy_reg_1t_8188e;
+ bool biol = false;
+ struct adapter *adapter = dm_odm->Adapter;
+ struct xmit_frame *pxmit_frame = NULL;
+ u8 bndy_cnt = 1;
+ enum HAL_STATUS rst = HAL_STATUS_SUCCESS;
+ hex += board;
+ hex += interfaceValue << 8;
+ hex += platform << 16;
+ hex += 0xFF000000;
+ biol = rtw_IOL_applied(adapter);
+
+ if (biol) {
+ pxmit_frame = rtw_IOL_accquire_xmit_frame(adapter);
+ if (!pxmit_frame) {
+ pr_info("rtw_IOL_accquire_xmit_frame failed\n");
+ return HAL_STATUS_FAILURE;
+ }
}
-}
-
-static bool set_baseband_phy_config(struct adapter *adapt)
-{
- u32 i;
- const u32 arraylen = ARRAY_SIZE(array_phy_reg_1t_8188e);
- u32 *array = array_phy_reg_1t_8188e;
for (i = 0; i < arraylen; i += 2) {
u32 v1 = array[i];
u32 v2 = array[i + 1];
- if (v1 < 0xCDCDCDCD)
- rtl_bb_delay(adapt, v1, v2);
+ /* This (offset, data) pair meets the condition. */
+ if (v1 < 0xCDCDCDCD) {
+ if (biol) {
+ if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
+ bndy_cnt++;
+ if (v1 == 0xfe) {
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
+ } else if (v1 == 0xfd) {
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
+ } else if (v1 == 0xfc) {
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
+ } else if (v1 == 0xfb) {
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
+ } else if (v1 == 0xfa) {
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
+ } else if (v1 == 0xf9) {
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
+ } else {
+ if (v1 == 0xa24)
+ dm_odm->RFCalibrateInfo.RegA24 = v2;
+ rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord);
+ }
+ } else {
+ odm_ConfigBB_PHY_8188E(dm_odm, v1, bMaskDWord, v2);
+ }
+ continue;
+ } else { /* This line is the start line of branch. */
+ if (!CheckCondition(array[i], hex)) {
+ /* Discard the following (offset, data) pairs. */
+ read_next_pair(array, v1, v2, i);
+ while (v2 != 0xDEAD &&
+ v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < arraylen - 2)
+ read_next_pair(array, v1, v2, i);
+ i -= 2; /* prevent from for-loop += 2 */
+ } else { /* Configure matched pairs and skip to end of if-else. */
+ read_next_pair(array, v1, v2, i);
+ while (v2 != 0xDEAD &&
+ v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < arraylen - 2) {
+ if (biol) {
+ if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
+ bndy_cnt++;
+ if (v1 == 0xfe) {
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
+ } else if (v1 == 0xfd) {
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
+ } else if (v1 == 0xfc) {
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
+ } else if (v1 == 0xfb) {
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
+ } else if (v1 == 0xfa) {
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
+ } else if (v1 == 0xf9) {
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
+ } else {
+ if (v1 == 0xa24)
+ dm_odm->RFCalibrateInfo.RegA24 = v2;
+
+ rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord);
+ }
+ } else {
+ odm_ConfigBB_PHY_8188E(dm_odm, v1, bMaskDWord, v2);
+ }
+ read_next_pair(array, v1, v2, i);
+ }
+
+ while (v2 != 0xDEAD && i < arraylen - 2)
+ read_next_pair(array, v1, v2, i);
+ }
+ }
}
- return true;
+ if (biol) {
+ if (!rtw_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
+ rst = HAL_STATUS_FAILURE;
+ pr_info("~~~ IOL Config %s Failed !!!\n", __func__);
+ }
+ }
+ return rst;
}
-/* PHY_REG_PG.TXT */
+/******************************************************************************
+* PHY_REG_PG.TXT
+******************************************************************************/
static u32 array_phy_reg_pg_8188e[] = {
0xE00, 0xFFFFFFFF, 0x06070809,
@@ -487,195 +661,42 @@ static u32 array_phy_reg_pg_8188e[] = {
};
-static void store_pwrindex_offset(struct adapter *adapter,
- u32 regaddr, u32 bitmask, u32 data)
-{
- struct hal_data_8188e *hal_data = adapter->HalData;
- u32 * const power_level_offset =
- hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt];
-
- if (regaddr == rTxAGC_A_Rate18_06)
- power_level_offset[0] = data;
- if (regaddr == rTxAGC_A_Rate54_24)
- power_level_offset[1] = data;
- if (regaddr == rTxAGC_A_CCK1_Mcs32)
- power_level_offset[6] = data;
- if (regaddr == rTxAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00)
- power_level_offset[7] = data;
- if (regaddr == rTxAGC_A_Mcs03_Mcs00)
- power_level_offset[2] = data;
- if (regaddr == rTxAGC_A_Mcs07_Mcs04)
- power_level_offset[3] = data;
- if (regaddr == rTxAGC_A_Mcs11_Mcs08)
- power_level_offset[4] = data;
- if (regaddr == rTxAGC_A_Mcs15_Mcs12) {
- power_level_offset[5] = data;
- hal_data->pwrGroupCnt++;
- }
- if (regaddr == rTxAGC_B_Rate18_06)
- power_level_offset[8] = data;
- if (regaddr == rTxAGC_B_Rate54_24)
- power_level_offset[9] = data;
- if (regaddr == rTxAGC_B_CCK1_55_Mcs32)
- power_level_offset[14] = data;
- if (regaddr == rTxAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff)
- power_level_offset[15] = data;
- if (regaddr == rTxAGC_B_Mcs03_Mcs00)
- power_level_offset[10] = data;
- if (regaddr == rTxAGC_B_Mcs07_Mcs04)
- power_level_offset[11] = data;
- if (regaddr == rTxAGC_B_Mcs11_Mcs08)
- power_level_offset[12] = data;
- if (regaddr == rTxAGC_B_Mcs15_Mcs12)
- power_level_offset[13] = data;
-}
-
-static void rtl_addr_delay(struct adapter *adapt,
- u32 addr, u32 bit_mask, u32 data)
+void ODM_ReadAndConfig_PHY_REG_PG_8188E(struct odm_dm_struct *dm_odm)
{
- switch (addr) {
- case 0xfe:
- msleep(50);
- break;
- case 0xfd:
- mdelay(5);
- break;
- case 0xfc:
- mdelay(1);
- break;
- case 0xfb:
- udelay(50);
- break;
- case 0xfa:
- udelay(5);
- break;
- case 0xf9:
- udelay(1);
- break;
- default:
- store_pwrindex_offset(adapt, addr, bit_mask, data);
- }
-}
+ u32 hex;
+ u32 i = 0;
+ u8 platform = dm_odm->SupportPlatform;
+ u8 interfaceValue = dm_odm->SupportInterface;
+ u8 board = dm_odm->BoardType;
+ u32 arraylen = sizeof(array_phy_reg_pg_8188e) / sizeof(u32);
+ u32 *array = array_phy_reg_pg_8188e;
-static bool config_bb_with_pgheader(struct adapter *adapt)
-{
- u32 i;
- const u32 arraylen = ARRAY_SIZE(array_phy_reg_pg_8188e);
- u32 *array = array_phy_reg_pg_8188e;
+ hex = board + (interfaceValue << 8);
+ hex += (platform << 16) + 0xFF000000;
for (i = 0; i < arraylen; i += 3) {
u32 v1 = array[i];
u32 v2 = array[i + 1];
u32 v3 = array[i + 2];
- if (v1 < 0xCDCDCDCD)
- rtl_addr_delay(adapt, v1, v2, v3);
- }
- return true;
-}
-
-static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *adapter)
-{
- struct bb_reg_def *reg[4];
-
- reg[RF_PATH_A] = &adapter->HalData->PHYRegDef[RF_PATH_A];
- reg[RF_PATH_B] = &adapter->HalData->PHYRegDef[RF_PATH_B];
-
- reg[RF_PATH_A]->rfintfs = rFPGA0_XAB_RFInterfaceSW;
- reg[RF_PATH_B]->rfintfs = rFPGA0_XAB_RFInterfaceSW;
-
- reg[RF_PATH_A]->rfintfi = rFPGA0_XAB_RFInterfaceRB;
- reg[RF_PATH_B]->rfintfi = rFPGA0_XAB_RFInterfaceRB;
-
- reg[RF_PATH_A]->rfintfo = rFPGA0_XA_RFInterfaceOE;
- reg[RF_PATH_B]->rfintfo = rFPGA0_XB_RFInterfaceOE;
-
- reg[RF_PATH_A]->rfintfe = rFPGA0_XA_RFInterfaceOE;
- reg[RF_PATH_B]->rfintfe = rFPGA0_XB_RFInterfaceOE;
-
- reg[RF_PATH_A]->rf3wireOffset = rFPGA0_XA_LSSIParameter;
- reg[RF_PATH_B]->rf3wireOffset = rFPGA0_XB_LSSIParameter;
-
- reg[RF_PATH_A]->rfLSSI_Select = rFPGA0_XAB_RFParameter;
- reg[RF_PATH_B]->rfLSSI_Select = rFPGA0_XAB_RFParameter;
-
- reg[RF_PATH_A]->rfTxGainStage = rFPGA0_TxGainStage;
- reg[RF_PATH_B]->rfTxGainStage = rFPGA0_TxGainStage;
-
- reg[RF_PATH_A]->rfHSSIPara1 = rFPGA0_XA_HSSIParameter1;
- reg[RF_PATH_B]->rfHSSIPara1 = rFPGA0_XB_HSSIParameter1;
-
- reg[RF_PATH_A]->rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;
- reg[RF_PATH_B]->rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;
-
- reg[RF_PATH_A]->rfSwitchControl = rFPGA0_XAB_SwitchControl;
- reg[RF_PATH_B]->rfSwitchControl = rFPGA0_XAB_SwitchControl;
-
- reg[RF_PATH_A]->rfAGCControl1 = rOFDM0_XAAGCCore1;
- reg[RF_PATH_B]->rfAGCControl1 = rOFDM0_XBAGCCore1;
-
- reg[RF_PATH_A]->rfAGCControl2 = rOFDM0_XAAGCCore2;
- reg[RF_PATH_B]->rfAGCControl2 = rOFDM0_XBAGCCore2;
-
- reg[RF_PATH_A]->rfRxIQImbalance = rOFDM0_XARxIQImbalance;
- reg[RF_PATH_B]->rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
-
- reg[RF_PATH_A]->rfRxAFE = rOFDM0_XARxAFE;
- reg[RF_PATH_B]->rfRxAFE = rOFDM0_XBRxAFE;
-
- reg[RF_PATH_A]->rfTxIQImbalance = rOFDM0_XATxIQImbalance;
- reg[RF_PATH_B]->rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
-
- reg[RF_PATH_A]->rfTxAFE = rOFDM0_XATxAFE;
- reg[RF_PATH_B]->rfTxAFE = rOFDM0_XBTxAFE;
-
- reg[RF_PATH_A]->rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
- reg[RF_PATH_B]->rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
-
- reg[RF_PATH_A]->rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
- reg[RF_PATH_B]->rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
-}
-
-static bool config_parafile(struct adapter *adapt)
-{
- struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(adapt);
-
- set_baseband_phy_config(adapt);
-
- /* If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */
- if (!eeprom->bautoload_fail_flag) {
- adapt->HalData->pwrGroupCnt = 0;
- config_bb_with_pgheader(adapt);
+ /* this line is a line of pure_body */
+ if (v1 < 0xCDCDCDCD) {
+ odm_ConfigBB_PHY_REG_PG_8188E(dm_odm, v1, v2, v3);
+ continue;
+ } else { /* this line is the start of branch */
+ if (!CheckCondition(array[i], hex)) {
+ /* don't need the hw_body */
+ i += 2; /* skip the pair of expression */
+ v1 = array[i];
+ v2 = array[i + 1];
+ v3 = array[i + 2];
+ while (v2 != 0xDEAD) {
+ i += 3;
+ v1 = array[i];
+ v2 = array[i + 1];
+ v3 = array[i + 1];
+ }
+ }
+ }
}
- set_baseband_agc_config(adapt);
- return true;
-}
-
-bool rtl88eu_phy_bb_config(struct adapter *adapt)
-{
- bool rtstatus;
- u32 regval;
- u8 crystal_cap;
-
- rtl88e_phy_init_bb_rf_register_definition(adapt);
-
- /* Enable BB and RF */
- regval = usb_read16(adapt, REG_SYS_FUNC_EN);
- usb_write16(adapt, REG_SYS_FUNC_EN,
- (u16)(regval | BIT(13) | BIT(0) | BIT(1)));
-
- usb_write8(adapt, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
-
- usb_write8(adapt, REG_SYS_FUNC_EN, FEN_USBA |
- FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB);
-
- /* Config BB and AGC */
- rtstatus = config_parafile(adapt);
-
- /* write 0x24[16:11] = 0x24[22:17] = crystal_cap */
- crystal_cap = adapt->HalData->CrystalCap & 0x3F;
- phy_set_bb_reg(adapt, REG_AFE_XTAL_CTRL, 0x7ff800,
- (crystal_cap | (crystal_cap << 6)));
-
- return rtstatus;
}
diff --git a/drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c b/drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c
new file mode 100644
index 000000000000..0ff2609c26bb
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/odm_precomp.h"
+#include "../include/rtw_iol.h"
+
+static bool Checkcondition(const u32 condition, const u32 hex)
+{
+ u32 _board = (hex & 0x000000FF);
+ u32 _interface = (hex & 0x0000FF00) >> 8;
+ u32 _platform = (hex & 0x00FF0000) >> 16;
+ u32 cond = condition;
+
+ if (condition == 0xCDCDCDCD)
+ return true;
+
+ cond = condition & 0x000000FF;
+ if ((_board == cond) && cond != 0x00)
+ return false;
+
+ cond = condition & 0x0000FF00;
+ cond = cond >> 8;
+ if ((_interface & cond) == 0 && cond != 0x07)
+ return false;
+
+ cond = condition & 0x00FF0000;
+ cond = cond >> 16;
+ if ((_platform & cond) == 0 && cond != 0x0F)
+ return false;
+ return true;
+}
+
+/******************************************************************************
+* MAC_REG.TXT
+******************************************************************************/
+
+static u32 array_MAC_REG_8188E[] = {
+ 0x026, 0x00000041,
+ 0x027, 0x00000035,
+ 0x428, 0x0000000A,
+ 0x429, 0x00000010,
+ 0x430, 0x00000000,
+ 0x431, 0x00000001,
+ 0x432, 0x00000002,
+ 0x433, 0x00000004,
+ 0x434, 0x00000005,
+ 0x435, 0x00000006,
+ 0x436, 0x00000007,
+ 0x437, 0x00000008,
+ 0x438, 0x00000000,
+ 0x439, 0x00000000,
+ 0x43A, 0x00000001,
+ 0x43B, 0x00000002,
+ 0x43C, 0x00000004,
+ 0x43D, 0x00000005,
+ 0x43E, 0x00000006,
+ 0x43F, 0x00000007,
+ 0x440, 0x0000005D,
+ 0x441, 0x00000001,
+ 0x442, 0x00000000,
+ 0x444, 0x00000015,
+ 0x445, 0x000000F0,
+ 0x446, 0x0000000F,
+ 0x447, 0x00000000,
+ 0x458, 0x00000041,
+ 0x459, 0x000000A8,
+ 0x45A, 0x00000072,
+ 0x45B, 0x000000B9,
+ 0x460, 0x00000066,
+ 0x461, 0x00000066,
+ 0x480, 0x00000008,
+ 0x4C8, 0x000000FF,
+ 0x4C9, 0x00000008,
+ 0x4CC, 0x000000FF,
+ 0x4CD, 0x000000FF,
+ 0x4CE, 0x00000001,
+ 0x4D3, 0x00000001,
+ 0x500, 0x00000026,
+ 0x501, 0x000000A2,
+ 0x502, 0x0000002F,
+ 0x503, 0x00000000,
+ 0x504, 0x00000028,
+ 0x505, 0x000000A3,
+ 0x506, 0x0000005E,
+ 0x507, 0x00000000,
+ 0x508, 0x0000002B,
+ 0x509, 0x000000A4,
+ 0x50A, 0x0000005E,
+ 0x50B, 0x00000000,
+ 0x50C, 0x0000004F,
+ 0x50D, 0x000000A4,
+ 0x50E, 0x00000000,
+ 0x50F, 0x00000000,
+ 0x512, 0x0000001C,
+ 0x514, 0x0000000A,
+ 0x516, 0x0000000A,
+ 0x525, 0x0000004F,
+ 0x550, 0x00000010,
+ 0x551, 0x00000010,
+ 0x559, 0x00000002,
+ 0x55D, 0x000000FF,
+ 0x605, 0x00000030,
+ 0x608, 0x0000000E,
+ 0x609, 0x0000002A,
+ 0x620, 0x000000FF,
+ 0x621, 0x000000FF,
+ 0x622, 0x000000FF,
+ 0x623, 0x000000FF,
+ 0x624, 0x000000FF,
+ 0x625, 0x000000FF,
+ 0x626, 0x000000FF,
+ 0x627, 0x000000FF,
+ 0x652, 0x00000020,
+ 0x63C, 0x0000000A,
+ 0x63D, 0x0000000A,
+ 0x63E, 0x0000000E,
+ 0x63F, 0x0000000E,
+ 0x640, 0x00000040,
+ 0x66E, 0x00000005,
+ 0x700, 0x00000021,
+ 0x701, 0x00000043,
+ 0x702, 0x00000065,
+ 0x703, 0x00000087,
+ 0x708, 0x00000021,
+ 0x709, 0x00000043,
+ 0x70A, 0x00000065,
+ 0x70B, 0x00000087,
+};
+
+enum HAL_STATUS ODM_ReadAndConfig_MAC_REG_8188E(struct odm_dm_struct *dm_odm)
+{
+ #define READ_NEXT_PAIR(v1, v2, i) do { i += 2; v1 = array[i]; v2 = array[i + 1]; } while (0)
+
+ u32 hex = 0;
+ u32 i;
+ u8 platform = dm_odm->SupportPlatform;
+ u8 interface_val = dm_odm->SupportInterface;
+ u8 board = dm_odm->BoardType;
+ u32 array_len = sizeof(array_MAC_REG_8188E) / sizeof(u32);
+ u32 *array = array_MAC_REG_8188E;
+ bool biol = false;
+
+ struct adapter *adapt = dm_odm->Adapter;
+ struct xmit_frame *pxmit_frame = NULL;
+ u8 bndy_cnt = 1;
+ enum HAL_STATUS rst = HAL_STATUS_SUCCESS;
+ hex += board;
+ hex += interface_val << 8;
+ hex += platform << 16;
+ hex += 0xFF000000;
+
+ biol = rtw_IOL_applied(adapt);
+
+ if (biol) {
+ pxmit_frame = rtw_IOL_accquire_xmit_frame(adapt);
+ if (!pxmit_frame) {
+ pr_info("rtw_IOL_accquire_xmit_frame failed\n");
+ return HAL_STATUS_FAILURE;
+ }
+ }
+
+ for (i = 0; i < array_len; i += 2) {
+ u32 v1 = array[i];
+ u32 v2 = array[i + 1];
+
+ /* This (offset, data) pair meets the condition. */
+ if (v1 < 0xCDCDCDCD) {
+ if (biol) {
+ if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
+ bndy_cnt++;
+ rtw_IOL_append_WB_cmd(pxmit_frame, (u16)v1, (u8)v2, 0xFF);
+ } else {
+ odm_ConfigMAC_8188E(dm_odm, v1, (u8)v2);
+ }
+ continue;
+ } else { /* This line is the start line of branch. */
+ if (!Checkcondition(array[i], hex)) {
+ /* Discard the following (offset, data) pairs. */
+ READ_NEXT_PAIR(v1, v2, i);
+ while (v2 != 0xDEAD &&
+ v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < array_len - 2) {
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+ i -= 2; /* prevent from for-loop += 2 */
+ } else { /* Configure matched pairs and skip to end of if-else. */
+ READ_NEXT_PAIR(v1, v2, i);
+ while (v2 != 0xDEAD &&
+ v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < array_len - 2) {
+ if (biol) {
+ if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
+ bndy_cnt++;
+ rtw_IOL_append_WB_cmd(pxmit_frame, (u16)v1, (u8)v2, 0xFF);
+ } else {
+ odm_ConfigMAC_8188E(dm_odm, v1, (u8)v2);
+ }
+
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+ while (v2 != 0xDEAD && i < array_len - 2)
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+ }
+ }
+ if (biol) {
+ if (!rtw_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
+ pr_info("~~~ MAC IOL_exec_cmds Failed !!!\n");
+ rst = HAL_STATUS_FAILURE;
+ }
+ }
+ return rst;
+}
diff --git a/drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c b/drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c
new file mode 100644
index 000000000000..55e4b4a877a4
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/odm_precomp.h"
+#include "../include/rtw_iol.h"
+
+static bool CheckCondition(const u32 Condition, const u32 Hex)
+{
+ u32 _board = (Hex & 0x000000FF);
+ u32 _interface = (Hex & 0x0000FF00) >> 8;
+ u32 _platform = (Hex & 0x00FF0000) >> 16;
+ u32 cond = Condition;
+
+ if (Condition == 0xCDCDCDCD)
+ return true;
+
+ cond = Condition & 0x000000FF;
+ if ((_board == cond) && cond != 0x00)
+ return false;
+
+ cond = Condition & 0x0000FF00;
+ cond = cond >> 8;
+ if ((_interface & cond) == 0 && cond != 0x07)
+ return false;
+
+ cond = Condition & 0x00FF0000;
+ cond = cond >> 16;
+ if ((_platform & cond) == 0 && cond != 0x0F)
+ return false;
+ return true;
+}
+
+/******************************************************************************
+* RadioA_1T.TXT
+******************************************************************************/
+
+static u32 Array_RadioA_1T_8188E[] = {
+ 0x000, 0x00030000,
+ 0x008, 0x00084000,
+ 0x018, 0x00000407,
+ 0x019, 0x00000012,
+ 0x01E, 0x00080009,
+ 0x01F, 0x00000880,
+ 0x02F, 0x0001A060,
+ 0x03F, 0x00000000,
+ 0x042, 0x000060C0,
+ 0x057, 0x000D0000,
+ 0x058, 0x000BE180,
+ 0x067, 0x00001552,
+ 0x083, 0x00000000,
+ 0x0B0, 0x000FF8FC,
+ 0x0B1, 0x00054400,
+ 0x0B2, 0x000CCC19,
+ 0x0B4, 0x00043003,
+ 0x0B6, 0x0004953E,
+ 0x0B7, 0x0001C718,
+ 0x0B8, 0x000060FF,
+ 0x0B9, 0x00080001,
+ 0x0BA, 0x00040000,
+ 0x0BB, 0x00000400,
+ 0x0BF, 0x000C0000,
+ 0x0C2, 0x00002400,
+ 0x0C3, 0x00000009,
+ 0x0C4, 0x00040C91,
+ 0x0C5, 0x00099999,
+ 0x0C6, 0x000000A3,
+ 0x0C7, 0x00088820,
+ 0x0C8, 0x00076C06,
+ 0x0C9, 0x00000000,
+ 0x0CA, 0x00080000,
+ 0x0DF, 0x00000180,
+ 0x0EF, 0x000001A0,
+ 0x051, 0x0006B27D,
+ 0xFF0F041F, 0xABCD,
+ 0x052, 0x0007E4DD,
+ 0xCDCDCDCD, 0xCDCD,
+ 0x052, 0x0007E49D,
+ 0xFF0F041F, 0xDEAD,
+ 0x053, 0x00000073,
+ 0x056, 0x00051FF3,
+ 0x035, 0x00000086,
+ 0x035, 0x00000186,
+ 0x035, 0x00000286,
+ 0x036, 0x00001C25,
+ 0x036, 0x00009C25,
+ 0x036, 0x00011C25,
+ 0x036, 0x00019C25,
+ 0x0B6, 0x00048538,
+ 0x018, 0x00000C07,
+ 0x05A, 0x0004BD00,
+ 0x019, 0x000739D0,
+ 0x034, 0x0000ADF3,
+ 0x034, 0x00009DF0,
+ 0x034, 0x00008DED,
+ 0x034, 0x00007DEA,
+ 0x034, 0x00006DE7,
+ 0x034, 0x000054EE,
+ 0x034, 0x000044EB,
+ 0x034, 0x000034E8,
+ 0x034, 0x0000246B,
+ 0x034, 0x00001468,
+ 0x034, 0x0000006D,
+ 0x000, 0x00030159,
+ 0x084, 0x00068200,
+ 0x086, 0x000000CE,
+ 0x087, 0x00048A00,
+ 0x08E, 0x00065540,
+ 0x08F, 0x00088000,
+ 0x0EF, 0x000020A0,
+ 0x03B, 0x000F02B0,
+ 0x03B, 0x000EF7B0,
+ 0x03B, 0x000D4FB0,
+ 0x03B, 0x000CF060,
+ 0x03B, 0x000B0090,
+ 0x03B, 0x000A0080,
+ 0x03B, 0x00090080,
+ 0x03B, 0x0008F780,
+ 0x03B, 0x000722B0,
+ 0x03B, 0x0006F7B0,
+ 0x03B, 0x00054FB0,
+ 0x03B, 0x0004F060,
+ 0x03B, 0x00030090,
+ 0x03B, 0x00020080,
+ 0x03B, 0x00010080,
+ 0x03B, 0x0000F780,
+ 0x0EF, 0x000000A0,
+ 0x000, 0x00010159,
+ 0x018, 0x0000F407,
+ 0xFFE, 0x00000000,
+ 0xFFE, 0x00000000,
+ 0x01F, 0x00080003,
+ 0xFFE, 0x00000000,
+ 0xFFE, 0x00000000,
+ 0x01E, 0x00000001,
+ 0x01F, 0x00080000,
+ 0x000, 0x00033E60,
+};
+
+enum HAL_STATUS ODM_ReadAndConfig_RadioA_1T_8188E(struct odm_dm_struct *pDM_Odm)
+{
+ #define READ_NEXT_PAIR(v1, v2, i) do \
+ { i += 2; v1 = Array[i]; \
+ v2 = Array[i + 1]; } while (0)
+
+ u32 hex = 0;
+ u32 i = 0;
+ u8 platform = pDM_Odm->SupportPlatform;
+ u8 interfaceValue = pDM_Odm->SupportInterface;
+ u8 board = pDM_Odm->BoardType;
+ u32 ArrayLen = sizeof(Array_RadioA_1T_8188E) / sizeof(u32);
+ u32 *Array = Array_RadioA_1T_8188E;
+ bool biol = false;
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct xmit_frame *pxmit_frame = NULL;
+ u8 bndy_cnt = 1;
+ enum HAL_STATUS rst = HAL_STATUS_SUCCESS;
+
+ hex += board;
+ hex += interfaceValue << 8;
+ hex += platform << 16;
+ hex += 0xFF000000;
+ biol = rtw_IOL_applied(Adapter);
+
+ if (biol) {
+ pxmit_frame = rtw_IOL_accquire_xmit_frame(Adapter);
+ if (!pxmit_frame) {
+ pr_info("rtw_IOL_accquire_xmit_frame failed\n");
+ return HAL_STATUS_FAILURE;
+ }
+ }
+
+ for (i = 0; i < ArrayLen; i += 2) {
+ u32 v1 = Array[i];
+ u32 v2 = Array[i + 1];
+
+ /* This (offset, data) pair meets the condition. */
+ if (v1 < 0xCDCDCDCD) {
+ if (biol) {
+ if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
+ bndy_cnt++;
+
+ if (v1 == 0xffe)
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
+ else if (v1 == 0xfd)
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
+ else if (v1 == 0xfc)
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
+ else if (v1 == 0xfb)
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
+ else if (v1 == 0xfa)
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
+ else if (v1 == 0xf9)
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
+ else
+ rtw_IOL_append_WRF_cmd(pxmit_frame, RF_PATH_A, (u16)v1, v2, bRFRegOffsetMask);
+ } else {
+ odm_ConfigRF_RadioA_8188E(pDM_Odm, v1, v2);
+ }
+ continue;
+ } else { /* This line is the start line of branch. */
+ if (!CheckCondition(Array[i], hex)) {
+ /* Discard the following (offset, data) pairs. */
+ READ_NEXT_PAIR(v1, v2, i);
+ while (v2 != 0xDEAD &&
+ v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < ArrayLen - 2)
+ READ_NEXT_PAIR(v1, v2, i);
+ i -= 2; /* prevent from for-loop += 2 */
+ } else { /* Configure matched pairs and skip to end of if-else. */
+ READ_NEXT_PAIR(v1, v2, i);
+ while (v2 != 0xDEAD &&
+ v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < ArrayLen - 2) {
+ if (biol) {
+ if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
+ bndy_cnt++;
+
+ if (v1 == 0xffe)
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
+ else if (v1 == 0xfd)
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
+ else if (v1 == 0xfc)
+ rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
+ else if (v1 == 0xfb)
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
+ else if (v1 == 0xfa)
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
+ else if (v1 == 0xf9)
+ rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
+ else
+ rtw_IOL_append_WRF_cmd(pxmit_frame, RF_PATH_A, (u16)v1, v2, bRFRegOffsetMask);
+ } else {
+ odm_ConfigRF_RadioA_8188E(pDM_Odm, v1, v2);
+ }
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ while (v2 != 0xDEAD && i < ArrayLen - 2)
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+ }
+ }
+ if (biol) {
+ if (!rtw_IOL_exec_cmds_sync(pDM_Odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
+ rst = HAL_STATUS_FAILURE;
+ pr_info("~~~ IOL Config %s Failed !!!\n", __func__);
+ }
+ }
+ return rst;
+}
diff --git a/drivers/staging/r8188eu/hal/HalPhyRf_8188e.c b/drivers/staging/r8188eu/hal/HalPhyRf_8188e.c
new file mode 100644
index 000000000000..356885e27edd
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/HalPhyRf_8188e.c
@@ -0,0 +1,1264 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/odm_precomp.h"
+
+/*---------------------------Define Local Constant---------------------------*/
+/* 2010/04/25 MH Define the max tx power tracking tx agc power. */
+#define ODM_TXPWRTRACK_MAX_IDX_88E 6
+
+/*---------------------------Define Local Constant---------------------------*/
+
+/* 3============================================================ */
+/* 3 Tx Power Tracking */
+/* 3============================================================ */
+/*-----------------------------------------------------------------------------
+ * Function: ODM_TxPwrTrackAdjust88E()
+ *
+ * Overview: 88E we can not write 0xc80/c94/c4c/ 0xa2x. Instead of write TX agc.
+ * No matter OFDM & CCK use the same method.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 04/23/2012 MHC Create Version 0.
+ * 04/23/2012 MHC Adjust TX agc directly not throughput BB digital.
+ *
+ *---------------------------------------------------------------------------*/
+void ODM_TxPwrTrackAdjust88E(struct odm_dm_struct *dm_odm, u8 Type,/* 0 = OFDM, 1 = CCK */
+ u8 *pDirection, /* 1 = +(increase) 2 = -(decrease) */
+ u32 *pOutWriteVal /* Tx tracking CCK/OFDM BB swing index adjust */
+ )
+{
+ u8 pwr_value = 0;
+ /* Tx power tracking BB swing table. */
+ /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
+ if (Type == 0) { /* For OFDM afjust */
+ if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
+ *pDirection = 1;
+ pwr_value = (dm_odm->BbSwingIdxOfdmBase - dm_odm->BbSwingIdxOfdm);
+ } else {
+ *pDirection = 2;
+ pwr_value = (dm_odm->BbSwingIdxOfdm - dm_odm->BbSwingIdxOfdmBase);
+ }
+ } else if (Type == 1) { /* For CCK adjust. */
+ if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
+ *pDirection = 1;
+ pwr_value = (dm_odm->BbSwingIdxCckBase - dm_odm->BbSwingIdxCck);
+ } else {
+ *pDirection = 2;
+ pwr_value = (dm_odm->BbSwingIdxCck - dm_odm->BbSwingIdxCckBase);
+ }
+ }
+
+ /* */
+ /* 2012/04/25 MH According to Ed/Luke.Lees estimate for EVM the max tx power tracking */
+ /* need to be less than 6 power index for 88E. */
+ /* */
+ if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *pDirection == 1)
+ pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
+
+ *pOutWriteVal = pwr_value | (pwr_value << 8) | (pwr_value << 16) | (pwr_value << 24);
+} /* ODM_TxPwrTrackAdjust88E */
+
+/*-----------------------------------------------------------------------------
+ * Function: odm_TxPwrTrackSetPwr88E()
+ *
+ * Overview: 88E change all channel tx power accordign to flag.
+ * OFDM & CCK are all different.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 04/23/2012 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+static void odm_TxPwrTrackSetPwr88E(struct odm_dm_struct *dm_odm)
+{
+ if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
+ PHY_SetTxPowerLevel8188E(dm_odm->Adapter, *dm_odm->pChannel);
+ dm_odm->BbSwingFlagOfdm = false;
+ dm_odm->BbSwingFlagCck = false;
+ }
+} /* odm_TxPwrTrackSetPwr88E */
+
+/* 091212 chiyokolin */
+void
+odm_TXPowerTrackingCallback_ThermalMeter_8188E(
+ struct adapter *Adapter
+ )
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, offset;
+ u8 ThermalValue_AVG_count = 0;
+ u32 ThermalValue_AVG = 0;
+ s32 ele_A = 0, ele_D, TempCCk, X, value32;
+ s32 Y, ele_C = 0;
+ s8 OFDM_index[2], CCK_index = 0;
+ s8 OFDM_index_old[2] = {0, 0}, CCK_index_old = 0;
+ u32 i = 0, j = 0;
+ bool is2t = false;
+
+ u8 OFDM_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
+ u8 Indexforchannel = 0/*GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/;
+ s8 OFDM_index_mapping[2][index_mapping_NUM_88E] = {
+ {0, 0, 2, 3, 4, 4, /* 2.4G, decrease power */
+ 5, 6, 7, 7, 8, 9,
+ 10, 10, 11}, /* For lower temperature, 20120220 updated on 20120220. */
+ {0, 0, -1, -2, -3, -4, /* 2.4G, increase power */
+ -4, -4, -4, -5, -7, -8,
+ -9, -9, -10},
+ };
+ u8 Thermal_mapping[2][index_mapping_NUM_88E] = {
+ {0, 2, 4, 6, 8, 10, /* 2.4G, decrease power */
+ 12, 14, 16, 18, 20, 22,
+ 24, 26, 27},
+ {0, 2, 4, 6, 8, 10, /* 2.4G,, increase power */
+ 12, 14, 16, 18, 20, 22,
+ 25, 25, 25},
+ };
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ /* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
+ odm_TxPwrTrackSetPwr88E(dm_odm);
+
+ dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++; /* cosa add for debug */
+ dm_odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
+
+ /* <Kordan> RFCalibrateInfo.RegA24 will be initialized when ODM HW configuring, but MP configures with para files. */
+ dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
+
+ ThermalValue = (u8)ODM_GetRFReg(dm_odm, RF_PATH_A, RF_T_METER_88E, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
+
+ if (is2t)
+ rf = 2;
+ else
+ rf = 1;
+
+ if (ThermalValue) {
+ /* Query OFDM path A default setting */
+ ele_D = ODM_GetBBReg(dm_odm, rOFDM0_XATxIQImbalance, bMaskDWord) & bMaskOFDM_D;
+ for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { /* find the index */
+ if (ele_D == (OFDMSwingTable[i] & bMaskOFDM_D)) {
+ OFDM_index_old[0] = (u8)i;
+ dm_odm->BbSwingIdxOfdmBase = (u8)i;
+ break;
+ }
+ }
+
+ /* Query OFDM path B default setting */
+ if (is2t) {
+ ele_D = ODM_GetBBReg(dm_odm, rOFDM0_XBTxIQImbalance, bMaskDWord) & bMaskOFDM_D;
+ for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { /* find the index */
+ if (ele_D == (OFDMSwingTable[i] & bMaskOFDM_D)) {
+ OFDM_index_old[1] = (u8)i;
+ break;
+ }
+ }
+ }
+
+ /* Query CCK default setting From 0xa24 */
+ TempCCk = dm_odm->RFCalibrateInfo.RegA24;
+
+ for (i = 0; i < CCK_TABLE_SIZE; i++) {
+ if (dm_odm->RFCalibrateInfo.bCCKinCH14) {
+ if (ODM_CompareMemory(dm_odm, (void *)&TempCCk, (void *)&CCKSwingTable_Ch14[i][2], 4) == 0) {
+ CCK_index_old = (u8)i;
+ dm_odm->BbSwingIdxCckBase = (u8)i;
+ break;
+ }
+ } else {
+ if (ODM_CompareMemory(dm_odm, (void *)&TempCCk, (void *)&CCKSwingTable_Ch1_Ch13[i][2], 4) == 0) {
+ CCK_index_old = (u8)i;
+ dm_odm->BbSwingIdxCckBase = (u8)i;
+ break;
+ }
+ }
+ }
+
+ if (!dm_odm->RFCalibrateInfo.ThermalValue) {
+ dm_odm->RFCalibrateInfo.ThermalValue = pHalData->EEPROMThermalMeter;
+ dm_odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
+ dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue;
+
+ for (i = 0; i < rf; i++)
+ dm_odm->RFCalibrateInfo.OFDM_index[i] = OFDM_index_old[i];
+ dm_odm->RFCalibrateInfo.CCK_index = CCK_index_old;
+ }
+
+ /* calculate average thermal meter */
+ dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = ThermalValue;
+ dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
+ if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
+ dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
+
+ for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
+ if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
+ ThermalValue_AVG += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
+ ThermalValue_AVG_count++;
+ }
+ }
+
+ if (ThermalValue_AVG_count)
+ ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count);
+
+ if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
+ delta = ThermalValue > pHalData->EEPROMThermalMeter ?
+ (ThermalValue - pHalData->EEPROMThermalMeter) :
+ (pHalData->EEPROMThermalMeter - ThermalValue);
+ dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
+ dm_odm->RFCalibrateInfo.bDoneTxpower = false;
+ } else if (dm_odm->RFCalibrateInfo.bDoneTxpower) {
+ delta = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue) ?
+ (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue) :
+ (dm_odm->RFCalibrateInfo.ThermalValue - ThermalValue);
+ } else {
+ delta = ThermalValue > pHalData->EEPROMThermalMeter ?
+ (ThermalValue - pHalData->EEPROMThermalMeter) :
+ (pHalData->EEPROMThermalMeter - ThermalValue);
+ }
+ delta_LCK = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue_LCK) ?
+ (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue_LCK) :
+ (dm_odm->RFCalibrateInfo.ThermalValue_LCK - ThermalValue);
+ delta_IQK = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue_IQK) ?
+ (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue_IQK) :
+ (dm_odm->RFCalibrateInfo.ThermalValue_IQK - ThermalValue);
+
+ if ((delta_LCK >= 8)) { /* Delta temperature is equal to or larger than 20 centigrade. */
+ dm_odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
+ PHY_LCCalibrate_8188E(Adapter);
+ }
+
+ if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
+ delta = ThermalValue > pHalData->EEPROMThermalMeter ?
+ (ThermalValue - pHalData->EEPROMThermalMeter) :
+ (pHalData->EEPROMThermalMeter - ThermalValue);
+ /* calculate new OFDM / CCK offset */
+ if (ThermalValue > pHalData->EEPROMThermalMeter)
+ j = 1;
+ else
+ j = 0;
+ for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
+ if (delta < Thermal_mapping[j][offset]) {
+ if (offset != 0)
+ offset--;
+ break;
+ }
+ }
+ if (offset >= index_mapping_NUM_88E)
+ offset = index_mapping_NUM_88E - 1;
+ for (i = 0; i < rf; i++)
+ OFDM_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + OFDM_index_mapping[j][offset];
+ CCK_index = dm_odm->RFCalibrateInfo.CCK_index + OFDM_index_mapping[j][offset];
+
+ for (i = 0; i < rf; i++) {
+ if (OFDM_index[i] > OFDM_TABLE_SIZE_92D - 1)
+ OFDM_index[i] = OFDM_TABLE_SIZE_92D - 1;
+ else if (OFDM_index[i] < OFDM_min_index)
+ OFDM_index[i] = OFDM_min_index;
+ }
+
+ if (CCK_index > CCK_TABLE_SIZE - 1)
+ CCK_index = CCK_TABLE_SIZE - 1;
+ else if (CCK_index < 0)
+ CCK_index = 0;
+
+ /* 2 temporarily remove bNOPG */
+ /* Config by SwingTable */
+ if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
+ dm_odm->RFCalibrateInfo.bDoneTxpower = true;
+
+ /* Adujst OFDM Ant_A according to IQK result */
+ ele_D = (OFDMSwingTable[(u8)OFDM_index[0]] & 0xFFC00000) >> 22;
+ X = dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[Indexforchannel].Value[0][0];
+ Y = dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[Indexforchannel].Value[0][1];
+
+ /* Revse TX power table. */
+ dm_odm->BbSwingIdxOfdm = (u8)OFDM_index[0];
+ dm_odm->BbSwingIdxCck = (u8)CCK_index;
+
+ if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
+ dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
+ dm_odm->BbSwingFlagOfdm = true;
+ }
+
+ if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
+ dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
+ dm_odm->BbSwingFlagCck = true;
+ }
+
+ if (X != 0) {
+ if ((X & 0x00000200) != 0)
+ X = X | 0xFFFFFC00;
+ ele_A = ((X * ele_D) >> 8) & 0x000003FF;
+
+ /* new element C = element D x Y */
+ if ((Y & 0x00000200) != 0)
+ Y = Y | 0xFFFFFC00;
+ ele_C = ((Y * ele_D) >> 8) & 0x000003FF;
+
+ /* 2012/04/23 MH According to Luke's suggestion, we can not write BB digital */
+ /* to increase TX power. Otherwise, EVM will be bad. */
+ }
+
+ if (is2t) {
+ ele_D = (OFDMSwingTable[(u8)OFDM_index[1]] & 0xFFC00000) >> 22;
+
+ /* new element A = element D x X */
+ X = dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[Indexforchannel].Value[0][4];
+ Y = dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[Indexforchannel].Value[0][5];
+
+ if ((X != 0) && (*dm_odm->pBandType == ODM_BAND_2_4G)) {
+ if ((X & 0x00000200) != 0) /* consider minus */
+ X = X | 0xFFFFFC00;
+ ele_A = ((X * ele_D) >> 8) & 0x000003FF;
+
+ /* new element C = element D x Y */
+ if ((Y & 0x00000200) != 0)
+ Y = Y | 0xFFFFFC00;
+ ele_C = ((Y * ele_D) >> 8) & 0x00003FF;
+
+ /* wtite new elements A, C, D to regC88 and regC9C, element B is always 0 */
+ value32 = (ele_D << 22) | ((ele_C & 0x3F) << 16) | ele_A;
+ ODM_SetBBReg(dm_odm, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
+
+ value32 = (ele_C & 0x000003C0) >> 6;
+ ODM_SetBBReg(dm_odm, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
+
+ value32 = ((X * ele_D) >> 7) & 0x01;
+ ODM_SetBBReg(dm_odm, rOFDM0_ECCAThreshold, BIT(28), value32);
+ } else {
+ ODM_SetBBReg(dm_odm, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable[(u8)OFDM_index[1]]);
+ ODM_SetBBReg(dm_odm, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
+ ODM_SetBBReg(dm_odm, rOFDM0_ECCAThreshold, BIT(28), 0x00);
+ }
+ }
+ }
+ }
+
+ if (delta_IQK >= 8) { /* Delta temperature is equal to or larger than 20 centigrade. */
+ dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue;
+ PHY_IQCalibrate_8188E(Adapter, false);
+ }
+ /* update thermal meter value */
+ if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
+ dm_odm->RFCalibrateInfo.ThermalValue = ThermalValue;
+ }
+ dm_odm->RFCalibrateInfo.TXPowercount = 0;
+}
+
+/* 1 7. IQK */
+#define MAX_TOLERANCE 5
+#define IQK_DELAY_TIME 1 /* ms */
+
+static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+phy_PathA_IQK_8188E(struct adapter *adapt, bool configPathB)
+{
+ u32 regeac, regE94, regE9C;
+ u8 result = 0x00;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ /* 1 Tx IQK */
+ /* path-A IQK setting */
+ ODM_SetBBReg(dm_odm, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
+ ODM_SetBBReg(dm_odm, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
+ ODM_SetBBReg(dm_odm, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
+ ODM_SetBBReg(dm_odm, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
+
+ /* LO calibration setting */
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
+
+ /* One shot, path A LOK & IQK */
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
+ ODM_delay_ms(IQK_DELAY_TIME_88E);
+
+ /* Check failed */
+ regeac = ODM_GetBBReg(dm_odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regE94 = ODM_GetBBReg(dm_odm, rTx_Power_Before_IQK_A, bMaskDWord);
+ regE9C = ODM_GetBBReg(dm_odm, rTx_Power_After_IQK_A, bMaskDWord);
+
+ if (!(regeac & BIT(28)) &&
+ (((regE94 & 0x03FF0000) >> 16) != 0x142) &&
+ (((regE9C & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ return result;
+}
+
+static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+phy_PathA_RxIQK(struct adapter *adapt, bool configPathB)
+{
+ u32 regeac, regE94, regE9C, regEA4, u4tmp;
+ u8 result = 0x00;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ /* 1 Get TXIMR setting */
+ /* modify RXIQK mode table */
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
+
+ /* PA,PAD off */
+ ODM_SetRFReg(dm_odm, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
+
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x80800000);
+
+ /* IQK setting */
+ ODM_SetBBReg(dm_odm, rTx_IQK, bMaskDWord, 0x01007c00);
+ ODM_SetBBReg(dm_odm, rRx_IQK, bMaskDWord, 0x81004800);
+
+ /* path-A IQK setting */
+ ODM_SetBBReg(dm_odm, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
+ ODM_SetBBReg(dm_odm, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
+ ODM_SetBBReg(dm_odm, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
+ ODM_SetBBReg(dm_odm, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
+
+ /* LO calibration setting */
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
+
+ /* One shot, path A LOK & IQK */
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ ODM_delay_ms(IQK_DELAY_TIME_88E);
+
+ /* Check failed */
+ regeac = ODM_GetBBReg(dm_odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regE94 = ODM_GetBBReg(dm_odm, rTx_Power_Before_IQK_A, bMaskDWord);
+ regE9C = ODM_GetBBReg(dm_odm, rTx_Power_After_IQK_A, bMaskDWord);
+
+ if (!(regeac & BIT(28)) &&
+ (((regE94 & 0x03FF0000) >> 16) != 0x142) &&
+ (((regE9C & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ else /* if Tx not OK, ignore Rx */
+ return result;
+
+ u4tmp = 0x80007C00 | (regE94 & 0x3FF0000) | ((regE9C & 0x3FF0000) >> 16);
+ ODM_SetBBReg(dm_odm, rTx_IQK, bMaskDWord, u4tmp);
+
+ /* 1 RX IQK */
+ /* modify RXIQK mode table */
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x80800000);
+
+ /* IQK setting */
+ ODM_SetBBReg(dm_odm, rRx_IQK, bMaskDWord, 0x01004800);
+
+ /* path-A IQK setting */
+ ODM_SetBBReg(dm_odm, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+ ODM_SetBBReg(dm_odm, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+ ODM_SetBBReg(dm_odm, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
+ ODM_SetBBReg(dm_odm, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
+
+ /* LO calibration setting */
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
+
+ /* One shot, path A LOK & IQK */
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
+ ODM_delay_ms(IQK_DELAY_TIME_88E);
+
+ /* Check failed */
+ regeac = ODM_GetBBReg(dm_odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regE94 = ODM_GetBBReg(dm_odm, rTx_Power_Before_IQK_A, bMaskDWord);
+ regE9C = ODM_GetBBReg(dm_odm, rTx_Power_After_IQK_A, bMaskDWord);
+ regEA4 = ODM_GetBBReg(dm_odm, rRx_Power_Before_IQK_A_2, bMaskDWord);
+
+ /* reload RF 0xdf */
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
+
+ if (!(regeac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
+ (((regEA4 & 0x03FF0000) >> 16) != 0x132) &&
+ (((regeac & 0x03FF0000) >> 16) != 0x36))
+ result |= 0x02;
+
+ return result;
+}
+
+static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+phy_PathB_IQK_8188E(struct adapter *adapt)
+{
+ u32 regeac, regeb4, regebc, regec4, regecc;
+ u8 result = 0x00;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ /* One shot, path B LOK & IQK */
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
+ ODM_SetBBReg(dm_odm, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
+
+ /* delay x ms */
+ ODM_delay_ms(IQK_DELAY_TIME_88E);
+
+ /* Check failed */
+ regeac = ODM_GetBBReg(dm_odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regeb4 = ODM_GetBBReg(dm_odm, rTx_Power_Before_IQK_B, bMaskDWord);
+ regebc = ODM_GetBBReg(dm_odm, rTx_Power_After_IQK_B, bMaskDWord);
+ regec4 = ODM_GetBBReg(dm_odm, rRx_Power_Before_IQK_B_2, bMaskDWord);
+ regecc = ODM_GetBBReg(dm_odm, rRx_Power_After_IQK_B_2, bMaskDWord);
+
+ if (!(regeac & BIT(31)) &&
+ (((regeb4 & 0x03FF0000) >> 16) != 0x142) &&
+ (((regebc & 0x03FF0000) >> 16) != 0x42))
+ result |= 0x01;
+ else
+ return result;
+
+ if (!(regeac & BIT(30)) &&
+ (((regec4 & 0x03FF0000) >> 16) != 0x132) &&
+ (((regecc & 0x03FF0000) >> 16) != 0x36))
+ result |= 0x02;
+
+ return result;
+}
+
+static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8], u8 final_candidate, bool txonly)
+{
+ u32 Oldval_0, X, TX0_A, reg;
+ s32 Y, TX0_C;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqkok) {
+ Oldval_0 = (ODM_GetBBReg(dm_odm, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+
+ X = result[final_candidate][0];
+ if ((X & 0x00000200) != 0)
+ X = X | 0xFFFFFC00;
+ TX0_A = (X * Oldval_0) >> 8;
+ ODM_SetBBReg(dm_odm, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
+
+ ODM_SetBBReg(dm_odm, rOFDM0_ECCAThreshold, BIT(31), ((X * Oldval_0 >> 7) & 0x1));
+
+ Y = result[final_candidate][1];
+ if ((Y & 0x00000200) != 0)
+ Y = Y | 0xFFFFFC00;
+
+ TX0_C = (Y * Oldval_0) >> 8;
+ ODM_SetBBReg(dm_odm, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C & 0x3C0) >> 6));
+ ODM_SetBBReg(dm_odm, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C & 0x3F));
+
+ ODM_SetBBReg(dm_odm, rOFDM0_ECCAThreshold, BIT(29), ((Y * Oldval_0 >> 7) & 0x1));
+
+ if (txonly)
+ return;
+
+ reg = result[final_candidate][2];
+ ODM_SetBBReg(dm_odm, rOFDM0_XARxIQImbalance, 0x3FF, reg);
+
+ reg = result[final_candidate][3] & 0x3F;
+ ODM_SetBBReg(dm_odm, rOFDM0_XARxIQImbalance, 0xFC00, reg);
+
+ reg = (result[final_candidate][3] >> 6) & 0xF;
+ ODM_SetBBReg(dm_odm, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
+ }
+}
+
+static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8], u8 final_candidate, bool txonly)
+{
+ u32 Oldval_1, X, TX1_A, reg;
+ s32 Y, TX1_C;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqkok) {
+ Oldval_1 = (ODM_GetBBReg(dm_odm, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+
+ X = result[final_candidate][4];
+ if ((X & 0x00000200) != 0)
+ X = X | 0xFFFFFC00;
+ TX1_A = (X * Oldval_1) >> 8;
+ ODM_SetBBReg(dm_odm, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A);
+
+ ODM_SetBBReg(dm_odm, rOFDM0_ECCAThreshold, BIT(27), ((X * Oldval_1 >> 7) & 0x1));
+
+ Y = result[final_candidate][5];
+ if ((Y & 0x00000200) != 0)
+ Y = Y | 0xFFFFFC00;
+
+ TX1_C = (Y * Oldval_1) >> 8;
+ ODM_SetBBReg(dm_odm, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C & 0x3C0) >> 6));
+ ODM_SetBBReg(dm_odm, rOFDM0_XBTxIQImbalance, 0x003F0000, (TX1_C & 0x3F));
+
+ ODM_SetBBReg(dm_odm, rOFDM0_ECCAThreshold, BIT(25), ((Y * Oldval_1 >> 7) & 0x1));
+
+ if (txonly)
+ return;
+
+ reg = result[final_candidate][6];
+ ODM_SetBBReg(dm_odm, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
+
+ reg = result[final_candidate][7] & 0x3F;
+ ODM_SetBBReg(dm_odm, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
+
+ reg = (result[final_candidate][7] >> 6) & 0xF;
+ ODM_SetBBReg(dm_odm, rOFDM0_AGCRSSITable, 0x0000F000, reg);
+ }
+}
+
+/* */
+/* 2011/07/26 MH Add an API for testing IQK fail case. */
+/* */
+/* MP Already declare in odm.c */
+static bool ODM_CheckPowerStatus(struct adapter *Adapter)
+{
+ return true;
+}
+
+void _PHY_SaveADDARegisters(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum)
+{
+ u32 i;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ if (!ODM_CheckPowerStatus(adapt))
+ return;
+
+ for (i = 0; i < RegisterNum; i++) {
+ ADDABackup[i] = ODM_GetBBReg(dm_odm, ADDAReg[i], bMaskDWord);
+ }
+}
+
+static void _PHY_SaveMACRegisters(
+ struct adapter *adapt,
+ u32 *MACReg,
+ u32 *MACBackup
+ )
+{
+ u32 i;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
+ MACBackup[i] = ODM_Read1Byte(dm_odm, MACReg[i]);
+ }
+ MACBackup[i] = ODM_Read4Byte(dm_odm, MACReg[i]);
+}
+
+static void reload_adda_reg(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
+{
+ u32 i;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ for (i = 0; i < RegiesterNum; i++)
+ ODM_SetBBReg(dm_odm, ADDAReg[i], bMaskDWord, ADDABackup[i]);
+}
+
+static void
+_PHY_ReloadMACRegisters(
+ struct adapter *adapt,
+ u32 *MACReg,
+ u32 *MACBackup
+ )
+{
+ u32 i;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
+ ODM_Write1Byte(dm_odm, MACReg[i], (u8)MACBackup[i]);
+ }
+ ODM_Write4Byte(dm_odm, MACReg[i], MACBackup[i]);
+}
+
+void
+_PHY_PathADDAOn(
+ struct adapter *adapt,
+ u32 *ADDAReg,
+ bool isPathAOn,
+ bool is2t
+ )
+{
+ u32 pathOn;
+ u32 i;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4;
+ if (!is2t) {
+ pathOn = 0x0bdb25a0;
+ ODM_SetBBReg(dm_odm, ADDAReg[0], bMaskDWord, 0x0b1b25a0);
+ } else {
+ ODM_SetBBReg(dm_odm, ADDAReg[0], bMaskDWord, pathOn);
+ }
+
+ for (i = 1; i < IQK_ADDA_REG_NUM; i++)
+ ODM_SetBBReg(dm_odm, ADDAReg[i], bMaskDWord, pathOn);
+}
+
+void
+_PHY_MACSettingCalibration(
+ struct adapter *adapt,
+ u32 *MACReg,
+ u32 *MACBackup
+ )
+{
+ u32 i = 0;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ ODM_Write1Byte(dm_odm, MACReg[i], 0x3F);
+
+ for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
+ ODM_Write1Byte(dm_odm, MACReg[i], (u8)(MACBackup[i] & (~BIT(3))));
+ }
+ ODM_Write1Byte(dm_odm, MACReg[i], (u8)(MACBackup[i] & (~BIT(5))));
+}
+
+void
+_PHY_PathAStandBy(
+ struct adapter *adapt
+ )
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x0);
+ ODM_SetBBReg(dm_odm, 0x840, bMaskDWord, 0x00010000);
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x80800000);
+}
+
+static void _PHY_PIModeSwitch(
+ struct adapter *adapt,
+ bool PIMode
+ )
+{
+ u32 mode;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ mode = PIMode ? 0x01000100 : 0x01000000;
+ ODM_SetBBReg(dm_odm, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
+ ODM_SetBBReg(dm_odm, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
+}
+
+static bool phy_SimularityCompare_8188E(
+ struct adapter *adapt,
+ s32 resulta[][8],
+ u8 c1,
+ u8 c2
+ )
+{
+ u32 i, j, diff, sim_bitmap, bound = 0;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+ u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
+ bool result = true;
+ bool is2t;
+ s32 tmp1 = 0, tmp2 = 0;
+
+ if ((dm_odm->RFType == ODM_2T2R) || (dm_odm->RFType == ODM_2T3R) || (dm_odm->RFType == ODM_2T4R))
+ is2t = true;
+ else
+ is2t = false;
+
+ if (is2t)
+ bound = 8;
+ else
+ bound = 4;
+
+ sim_bitmap = 0;
+
+ for (i = 0; i < bound; i++) {
+ if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
+ if ((resulta[c1][i] & 0x00000200) != 0)
+ tmp1 = resulta[c1][i] | 0xFFFFFC00;
+ else
+ tmp1 = resulta[c1][i];
+
+ if ((resulta[c2][i] & 0x00000200) != 0)
+ tmp2 = resulta[c2][i] | 0xFFFFFC00;
+ else
+ tmp2 = resulta[c2][i];
+ } else {
+ tmp1 = resulta[c1][i];
+ tmp2 = resulta[c2][i];
+ }
+
+ diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1);
+
+ if (diff > MAX_TOLERANCE) {
+ if ((i == 2 || i == 6) && !sim_bitmap) {
+ if (resulta[c1][i] + resulta[c1][i + 1] == 0)
+ final_candidate[(i / 4)] = c2;
+ else if (resulta[c2][i] + resulta[c2][i + 1] == 0)
+ final_candidate[(i / 4)] = c1;
+ else
+ sim_bitmap = sim_bitmap | (1 << i);
+ } else {
+ sim_bitmap = sim_bitmap | (1 << i);
+ }
+ }
+ }
+
+ if (sim_bitmap == 0) {
+ for (i = 0; i < (bound / 4); i++) {
+ if (final_candidate[i] != 0xFF) {
+ for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+ resulta[3][j] = resulta[final_candidate[i]][j];
+ result = false;
+ }
+ }
+ return result;
+ } else {
+ if (!(sim_bitmap & 0x03)) { /* path A TX OK */
+ for (i = 0; i < 2; i++)
+ resulta[3][i] = resulta[c1][i];
+ }
+ if (!(sim_bitmap & 0x0c)) { /* path A RX OK */
+ for (i = 2; i < 4; i++)
+ resulta[3][i] = resulta[c1][i];
+ }
+
+ if (!(sim_bitmap & 0x30)) { /* path B TX OK */
+ for (i = 4; i < 6; i++)
+ resulta[3][i] = resulta[c1][i];
+ }
+
+ if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
+ for (i = 6; i < 8; i++)
+ resulta[3][i] = resulta[c1][i];
+ }
+ return false;
+ }
+}
+
+static void phy_IQCalibrate_8188E(struct adapter *adapt, s32 result[][8], u8 t, bool is2t)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+ u32 i;
+ u8 PathAOK, PathBOK;
+ u32 ADDA_REG[IQK_ADDA_REG_NUM] = {
+ rFPGA0_XCD_SwitchControl, rBlue_Tooth,
+ rRx_Wait_CCA, rTx_CCK_RFON,
+ rTx_CCK_BBON, rTx_OFDM_RFON,
+ rTx_OFDM_BBON, rTx_To_Rx,
+ rTx_To_Tx, rRx_CCK,
+ rRx_OFDM, rRx_Wait_RIFS,
+ rRx_TO_Rx, rStandby,
+ rSleep, rPMPD_ANAEN };
+ u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = {
+ REG_TXPAUSE, REG_BCN_CTRL,
+ REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
+
+ /* since 92C & 92D have the different define in IQK_BB_REG */
+ u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
+ rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
+ rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
+ rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
+ rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD
+ };
+
+ u32 retryCount = 9;
+ if (*dm_odm->mp_mode == 1)
+ retryCount = 9;
+ else
+ retryCount = 2;
+ /* Note: IQ calibration must be performed after loading */
+ /* PHY_REG.txt , and radio_a, radio_b.txt */
+
+ if (t == 0) {
+ /* Save ADDA parameters, turn Path A ADDA on */
+ _PHY_SaveADDARegisters(adapt, ADDA_REG, dm_odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM);
+ _PHY_SaveMACRegisters(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
+ _PHY_SaveADDARegisters(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
+ }
+
+ _PHY_PathADDAOn(adapt, ADDA_REG, true, is2t);
+ if (t == 0)
+ dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)ODM_GetBBReg(dm_odm, rFPGA0_XA_HSSIParameter1, BIT(8));
+
+ if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
+ /* Switch BB to PI mode to do IQ Calibration. */
+ _PHY_PIModeSwitch(adapt, true);
+ }
+
+ /* BB setting */
+ ODM_SetBBReg(dm_odm, rFPGA0_RFMOD, BIT(24), 0x00);
+ ODM_SetBBReg(dm_odm, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
+ ODM_SetBBReg(dm_odm, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
+ ODM_SetBBReg(dm_odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
+
+ ODM_SetBBReg(dm_odm, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
+ ODM_SetBBReg(dm_odm, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
+ ODM_SetBBReg(dm_odm, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
+ ODM_SetBBReg(dm_odm, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
+
+ if (is2t) {
+ ODM_SetBBReg(dm_odm, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00010000);
+ ODM_SetBBReg(dm_odm, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00010000);
+ }
+
+ /* MAC settings */
+ _PHY_MACSettingCalibration(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
+
+ /* Page B init */
+ /* AP or IQK */
+ ODM_SetBBReg(dm_odm, rConfig_AntA, bMaskDWord, 0x0f600000);
+
+ if (is2t)
+ ODM_SetBBReg(dm_odm, rConfig_AntB, bMaskDWord, 0x0f600000);
+
+ /* IQ calibration setting */
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x80800000);
+ ODM_SetBBReg(dm_odm, rTx_IQK, bMaskDWord, 0x01007c00);
+ ODM_SetBBReg(dm_odm, rRx_IQK, bMaskDWord, 0x81004800);
+
+ for (i = 0; i < retryCount; i++) {
+ PathAOK = phy_PathA_IQK_8188E(adapt, is2t);
+ if (PathAOK == 0x01) {
+ result[t][0] = (ODM_GetBBReg(dm_odm, rTx_Power_Before_IQK_A, bMaskDWord) & 0x3FF0000) >> 16;
+ result[t][1] = (ODM_GetBBReg(dm_odm, rTx_Power_After_IQK_A, bMaskDWord) & 0x3FF0000) >> 16;
+ break;
+ }
+ }
+
+ for (i = 0; i < retryCount; i++) {
+ PathAOK = phy_PathA_RxIQK(adapt, is2t);
+ if (PathAOK == 0x03) {
+ result[t][2] = (ODM_GetBBReg(dm_odm, rRx_Power_Before_IQK_A_2, bMaskDWord) & 0x3FF0000) >> 16;
+ result[t][3] = (ODM_GetBBReg(dm_odm, rRx_Power_After_IQK_A_2, bMaskDWord) & 0x3FF0000) >> 16;
+ break;
+ }
+ }
+
+ if (is2t) {
+ _PHY_PathAStandBy(adapt);
+
+ /* Turn Path B ADDA on */
+ _PHY_PathADDAOn(adapt, ADDA_REG, false, is2t);
+
+ for (i = 0; i < retryCount; i++) {
+ PathBOK = phy_PathB_IQK_8188E(adapt);
+ if (PathBOK == 0x03) {
+ result[t][4] = (ODM_GetBBReg(dm_odm, rTx_Power_Before_IQK_B, bMaskDWord) & 0x3FF0000) >> 16;
+ result[t][5] = (ODM_GetBBReg(dm_odm, rTx_Power_After_IQK_B, bMaskDWord) & 0x3FF0000) >> 16;
+ result[t][6] = (ODM_GetBBReg(dm_odm, rRx_Power_Before_IQK_B_2, bMaskDWord) & 0x3FF0000) >> 16;
+ result[t][7] = (ODM_GetBBReg(dm_odm, rRx_Power_After_IQK_B_2, bMaskDWord) & 0x3FF0000) >> 16;
+ break;
+ } else if (i == (retryCount - 1) && PathBOK == 0x01) { /* Tx IQK OK */
+ result[t][4] = (ODM_GetBBReg(dm_odm, rTx_Power_Before_IQK_B, bMaskDWord) & 0x3FF0000) >> 16;
+ result[t][5] = (ODM_GetBBReg(dm_odm, rTx_Power_After_IQK_B, bMaskDWord) & 0x3FF0000) >> 16;
+ }
+ }
+ }
+
+ /* Back to BB mode, load original value */
+ ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0);
+
+ if (t != 0) {
+ if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
+ /* Switch back BB to SI mode after finish IQ Calibration. */
+ _PHY_PIModeSwitch(adapt, false);
+ }
+
+ /* Reload ADDA power saving parameters */
+ reload_adda_reg(adapt, ADDA_REG, dm_odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM);
+
+ /* Reload MAC parameters */
+ _PHY_ReloadMACRegisters(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
+
+ reload_adda_reg(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
+
+ /* Restore RX initial gain */
+ ODM_SetBBReg(dm_odm, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3);
+ if (is2t)
+ ODM_SetBBReg(dm_odm, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00032ed3);
+
+ /* load 0xe30 IQC default value */
+ ODM_SetBBReg(dm_odm, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+ ODM_SetBBReg(dm_odm, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+ }
+}
+
+static void phy_LCCalibrate_8188E(struct adapter *adapt, bool is2t)
+{
+ u8 tmpreg;
+ u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ /* Check continuous TX and Packet TX */
+ tmpreg = ODM_Read1Byte(dm_odm, 0xd03);
+
+ if ((tmpreg & 0x70) != 0) /* Deal with contisuous TX case */
+ ODM_Write1Byte(dm_odm, 0xd03, tmpreg & 0x8F); /* disable all continuous TX */
+ else /* Deal with Packet TX case */
+ ODM_Write1Byte(dm_odm, REG_TXPAUSE, 0xFF); /* block all queues */
+
+ if ((tmpreg & 0x70) != 0) {
+ /* 1. Read original RF mode */
+ /* Path-A */
+ RF_Amode = PHY_QueryRFReg(adapt, RF_PATH_A, RF_AC, bMask12Bits);
+
+ /* Path-B */
+ if (is2t)
+ RF_Bmode = PHY_QueryRFReg(adapt, RF_PATH_B, RF_AC, bMask12Bits);
+
+ /* 2. Set RF mode = standby mode */
+ /* Path-A */
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode & 0x8FFFF) | 0x10000);
+
+ /* Path-B */
+ if (is2t)
+ ODM_SetRFReg(dm_odm, RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode & 0x8FFFF) | 0x10000);
+ }
+
+ /* 3. Read RF reg18 */
+ LC_Cal = PHY_QueryRFReg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
+
+ /* 4. Set LC calibration begin bit15 */
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal | 0x08000);
+
+ ODM_sleep_ms(100);
+
+ /* Restore original situation */
+ if ((tmpreg & 0x70) != 0) {
+ /* Deal with continuous TX case */
+ /* Path-A */
+ ODM_Write1Byte(dm_odm, 0xd03, tmpreg);
+ ODM_SetRFReg(dm_odm, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
+
+ /* Path-B */
+ if (is2t)
+ ODM_SetRFReg(dm_odm, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
+ } else {
+ /* Deal with Packet TX case */
+ ODM_Write1Byte(dm_odm, REG_TXPAUSE, 0x00);
+ }
+}
+
+void PHY_IQCalibrate_8188E(struct adapter *adapt, bool recovery)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+ struct mpt_context *pMptCtx = &adapt->mppriv.MptCtx;
+ s32 result[4][8]; /* last is final result */
+ u8 i, final_candidate;
+ bool pathaok, pathbok;
+ s32 RegE94, RegE9C, RegEA4, RegEB4, RegEBC, RegEC4;
+ bool is12simular, is13simular, is23simular;
+ bool singletone = false, carrier_sup = false;
+ u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
+ rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
+ rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
+ rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
+ rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
+ rOFDM0_RxIQExtAnta};
+ bool is2t;
+
+ is2t = (dm_odm->RFType == ODM_2T2R) ? true : false;
+ if (!ODM_CheckPowerStatus(adapt))
+ return;
+
+ if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
+ return;
+
+ if (*dm_odm->mp_mode == 1) {
+ singletone = pMptCtx->bSingleTone;
+ carrier_sup = pMptCtx->bCarrierSuppression;
+ }
+
+ /* 20120213<Kordan> Turn on when continuous Tx to pass lab testing. (required by Edlu) */
+ if (singletone || carrier_sup)
+ return;
+
+ if (recovery) {
+ reload_adda_reg(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
+ return;
+ }
+
+ for (i = 0; i < 8; i++) {
+ result[0][i] = 0;
+ result[1][i] = 0;
+ result[2][i] = 0;
+ if ((i == 0) || (i == 2) || (i == 4) || (i == 6))
+ result[3][i] = 0x100;
+ else
+ result[3][i] = 0;
+ }
+ final_candidate = 0xff;
+ pathaok = false;
+ pathbok = false;
+ is12simular = false;
+ is23simular = false;
+ is13simular = false;
+
+ for (i = 0; i < 3; i++) {
+ phy_IQCalibrate_8188E(adapt, result, i, is2t);
+
+ if (i == 1) {
+ is12simular = phy_SimularityCompare_8188E(adapt, result, 0, 1);
+ if (is12simular) {
+ final_candidate = 0;
+ break;
+ }
+ }
+
+ if (i == 2) {
+ is13simular = phy_SimularityCompare_8188E(adapt, result, 0, 2);
+ if (is13simular) {
+ final_candidate = 0;
+
+ break;
+ }
+ is23simular = phy_SimularityCompare_8188E(adapt, result, 1, 2);
+ if (is23simular) {
+ final_candidate = 1;
+ } else {
+ final_candidate = 3;
+ }
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ RegE94 = result[i][0];
+ RegE9C = result[i][1];
+ RegEA4 = result[i][2];
+ RegEB4 = result[i][4];
+ RegEBC = result[i][5];
+ RegEC4 = result[i][6];
+ }
+
+ if (final_candidate != 0xff) {
+ RegE94 = result[final_candidate][0];
+ RegE9C = result[final_candidate][1];
+ RegEA4 = result[final_candidate][2];
+ RegEB4 = result[final_candidate][4];
+ RegEBC = result[final_candidate][5];
+ dm_odm->RFCalibrateInfo.RegE94 = RegE94;
+ dm_odm->RFCalibrateInfo.RegE9C = RegE9C;
+ dm_odm->RFCalibrateInfo.RegEB4 = RegEB4;
+ dm_odm->RFCalibrateInfo.RegEBC = RegEBC;
+ RegEC4 = result[final_candidate][6];
+ pathaok = true;
+ pathbok = true;
+ } else {
+ dm_odm->RFCalibrateInfo.RegE94 = 0x100;
+ dm_odm->RFCalibrateInfo.RegEB4 = 0x100; /* X default value */
+ dm_odm->RFCalibrateInfo.RegE9C = 0x0;
+ dm_odm->RFCalibrateInfo.RegEBC = 0x0; /* Y default value */
+ }
+ if (RegE94 != 0)
+ patha_fill_iqk(adapt, pathaok, result, final_candidate, (RegEA4 == 0));
+ if (is2t) {
+ if (RegEB4 != 0)
+ pathb_fill_iqk(adapt, pathbok, result, final_candidate, (RegEC4 == 0));
+ }
+
+/* To Fix BSOD when final_candidate is 0xff */
+/* by sherry 20120321 */
+ if (final_candidate < 4) {
+ for (i = 0; i < IQK_Matrix_REG_NUM; i++)
+ dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[0].Value[0][i] = result[final_candidate][i];
+ dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[0].bIQKDone = true;
+ }
+
+ _PHY_SaveADDARegisters(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
+}
+
+void PHY_LCCalibrate_8188E(struct adapter *adapt)
+{
+ bool singletone = false, carrier_sup = false;
+ u32 timeout = 2000, timecount = 0;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+ struct mpt_context *pMptCtx = &adapt->mppriv.MptCtx;
+
+ if (*dm_odm->mp_mode == 1) {
+ singletone = pMptCtx->bSingleTone;
+ carrier_sup = pMptCtx->bCarrierSuppression;
+ }
+ if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
+ return;
+ /* 20120213<Kordan> Turn on when continuous Tx to pass lab testing. (required by Edlu) */
+ if (singletone || carrier_sup)
+ return;
+
+ while (*dm_odm->pbScanInProcess && timecount < timeout) {
+ ODM_delay_ms(50);
+ timecount += 50;
+ }
+
+ dm_odm->RFCalibrateInfo.bLCKInProgress = true;
+
+ if (dm_odm->RFType == ODM_2T2R) {
+ phy_LCCalibrate_8188E(adapt, true);
+ } else {
+ /* For 88C 1T1R */
+ phy_LCCalibrate_8188E(adapt, false);
+ }
+
+ dm_odm->RFCalibrateInfo.bLCKInProgress = false;
+}
+
+static void phy_setrfpathswitch_8188e(struct adapter *adapt, bool main, bool is2t)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ if (!adapt->hw_init_completed) {
+ u8 u1btmp;
+ u1btmp = ODM_Read1Byte(dm_odm, REG_LEDCFG2) | BIT(7);
+ ODM_Write1Byte(dm_odm, REG_LEDCFG2, u1btmp);
+ ODM_SetBBReg(dm_odm, rFPGA0_XAB_RFParameter, BIT(13), 0x01);
+ }
+
+ if (is2t) { /* 92C */
+ if (main)
+ ODM_SetBBReg(dm_odm, rFPGA0_XB_RFInterfaceOE, BIT(5) | BIT(6), 0x1); /* 92C_Path_A */
+ else
+ ODM_SetBBReg(dm_odm, rFPGA0_XB_RFInterfaceOE, BIT(5) | BIT(6), 0x2); /* BT */
+ } else { /* 88C */
+ if (main)
+ ODM_SetBBReg(dm_odm, rFPGA0_XA_RFInterfaceOE, BIT(8) | BIT(9), 0x2); /* Main */
+ else
+ ODM_SetBBReg(dm_odm, rFPGA0_XA_RFInterfaceOE, BIT(8) | BIT(9), 0x1); /* Aux */
+ }
+}
+
+void PHY_SetRFPathSwitch_8188E(struct adapter *adapt, bool main)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
+ struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+
+ if (dm_odm->RFType == ODM_2T2R) {
+ phy_setrfpathswitch_8188e(adapt, main, true);
+ } else {
+ /* For 88C 1T1R */
+ phy_setrfpathswitch_8188e(adapt, main, false);
+ }
+}
diff --git a/drivers/staging/r8188eu/hal/HalPwrSeqCmd.c b/drivers/staging/r8188eu/hal/HalPwrSeqCmd.c
new file mode 100644
index 000000000000..0fd11aca7ac7
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/HalPwrSeqCmd.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+/*++
+
+Module Name:
+ HalPwrSeqCmd.c
+
+Abstract:
+ Implement HW Power sequence configuration CMD handling routine for Realtek devices.
+
+Major Change History:
+ When Who What
+ ---------- --------------- -------------------------------
+ 2011-10-26 Lucas Modify to be compatible with SD4-CE driver.
+ 2011-07-07 Roger Create.
+
+--*/
+
+#include "../include/HalPwrSeqCmd.h"
+
+/* Description: */
+/* This routine deals with the Power Configuration CMDs parsing
+ * for RTL8723/RTL8188E Series IC.
+ * Assumption:
+ * We should follow specific format which was released from HW SD.
+ */
+u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
+ u8 ifacetype, struct wl_pwr_cfg pwrseqcmd[])
+{
+ struct wl_pwr_cfg pwrcfgcmd = {0};
+ u8 poll_bit = false;
+ u32 aryidx = 0;
+ u8 value = 0;
+ u32 offset = 0;
+ u32 poll_count = 0; /* polling autoload done. */
+ u32 max_poll_count = 5000;
+
+ do {
+ pwrcfgcmd = pwrseqcmd[aryidx];
+
+ /* 2 Only Handle the command whose FAB, CUT, and Interface are matched */
+ if ((GET_PWR_CFG_FAB_MASK(pwrcfgcmd) & fab_vers) &&
+ (GET_PWR_CFG_CUT_MASK(pwrcfgcmd) & cut_vers) &&
+ (GET_PWR_CFG_INTF_MASK(pwrcfgcmd) & ifacetype)) {
+ switch (GET_PWR_CFG_CMD(pwrcfgcmd)) {
+ case PWR_CMD_WRITE:
+ offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
+
+ /* Read the value from system register */
+ value = rtw_read8(padapter, offset);
+
+ value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
+ value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
+
+ /* Write the value back to system register */
+ rtw_write8(padapter, offset, value);
+ break;
+ case PWR_CMD_POLLING:
+ poll_bit = false;
+ offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
+ do {
+ value = rtw_read8(padapter, offset);
+
+ value &= GET_PWR_CFG_MASK(pwrcfgcmd);
+ if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd)))
+ poll_bit = true;
+ else
+ udelay(10);
+
+ if (poll_count++ > max_poll_count) {
+ DBG_88E("Fail to polling Offset[%#x]\n", offset);
+ return false;
+ }
+ } while (!poll_bit);
+ break;
+ case PWR_CMD_DELAY:
+ if (GET_PWR_CFG_VALUE(pwrcfgcmd) == PWRSEQ_DELAY_US)
+ udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd));
+ else
+ udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd) * 1000);
+ break;
+ case PWR_CMD_END:
+ /* When this command is parsed, end the process */
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ aryidx++;/* Add Array Index */
+ } while (1);
+ return true;
+}
diff --git a/drivers/staging/rtl8188eu/hal/hal_com.c b/drivers/staging/r8188eu/hal/hal_com.c
index ebe19e076ff2..f09d4d49b159 100644
--- a/drivers/staging/rtl8188eu/hal/hal_com.c
+++ b/drivers/staging/r8188eu/hal/hal_com.c
@@ -1,15 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#include <osdep_service.h>
-#include <drv_types.h>
-
-#include <hal_intf.h>
-#include <hal_com.h>
-#include <rtl8188e_hal.h>
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+
+#include "../include/hal_intf.h"
+#include "../include/hal_com.h"
+#include "../include/rtl8188e_hal.h"
#define _HAL_INIT_C_
@@ -18,35 +15,57 @@ void dump_chip_info(struct HAL_VERSION chip_vers)
uint cnt = 0;
char buf[128];
- cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8188E_");
- cnt += sprintf((buf + cnt), "%s_", chip_vers.ChipType == NORMAL_CHIP ?
+ if (IS_81XXC(chip_vers)) {
+ cnt += sprintf((buf + cnt), "Chip Version Info: %s_",
+ IS_92C_SERIAL(chip_vers) ?
+ "CHIP_8192C" : "CHIP_8188C");
+ } else if (IS_92D(chip_vers)) {
+ cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8192D_");
+ } else if (IS_8723_SERIES(chip_vers)) {
+ cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723A_");
+ } else if (IS_8188E(chip_vers)) {
+ cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8188E_");
+ }
+
+ cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(chip_vers) ?
"Normal_Chip" : "Test_Chip");
- cnt += sprintf((buf + cnt), "%s_", chip_vers.VendorType == CHIP_VENDOR_TSMC ?
+ cnt += sprintf((buf + cnt), "%s_", IS_CHIP_VENDOR_TSMC(chip_vers) ?
"TSMC" : "UMC");
- if (chip_vers.CUTVersion == A_CUT_VERSION)
+ if (IS_A_CUT(chip_vers))
cnt += sprintf((buf + cnt), "A_CUT_");
- else if (chip_vers.CUTVersion == B_CUT_VERSION)
+ else if (IS_B_CUT(chip_vers))
cnt += sprintf((buf + cnt), "B_CUT_");
- else if (chip_vers.CUTVersion == C_CUT_VERSION)
+ else if (IS_C_CUT(chip_vers))
cnt += sprintf((buf + cnt), "C_CUT_");
- else if (chip_vers.CUTVersion == D_CUT_VERSION)
+ else if (IS_D_CUT(chip_vers))
cnt += sprintf((buf + cnt), "D_CUT_");
- else if (chip_vers.CUTVersion == E_CUT_VERSION)
+ else if (IS_E_CUT(chip_vers))
cnt += sprintf((buf + cnt), "E_CUT_");
else
cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_",
chip_vers.CUTVersion);
- cnt += sprintf((buf + cnt), "1T1R_");
- cnt += sprintf((buf + cnt), "RomVer(0)\n");
+
+ if (IS_1T1R(chip_vers))
+ cnt += sprintf((buf + cnt), "1T1R_");
+ else if (IS_1T2R(chip_vers))
+ cnt += sprintf((buf + cnt), "1T2R_");
+ else if (IS_2T2R(chip_vers))
+ cnt += sprintf((buf + cnt), "2T2R_");
+ else
+ cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_",
+ chip_vers.RFType);
+
+ cnt += sprintf((buf + cnt), "RomVer(%d)\n", chip_vers.ROMVer);
pr_info("%s", buf);
}
#define CHAN_PLAN_HW 0x80
-/* return the final channel plan decision */
-u8 hal_com_get_channel_plan(u8 hw_channel_plan, u8 sw_channel_plan,
- u8 def_channel_plan, bool load_fail)
+u8 /* return the final channel plan decision */
+hal_com_get_channel_plan(struct adapter *padapter, u8 hw_channel_plan,
+ u8 sw_channel_plan, u8 def_channel_plan,
+ bool load_fail)
{
u8 sw_cfg;
u8 chnlplan;
@@ -118,7 +137,7 @@ u8 MRateToHwRate(u8 rate)
return ret;
}
-void hal_set_brate_cfg(u8 *brates, u16 *rate_cfg)
+void HalSetBrateCfg(struct adapter *adapt, u8 *brates, u16 *rate_cfg)
{
u8 i, is_brate, brate;
@@ -188,13 +207,11 @@ static void two_out_pipe(struct adapter *adapter, bool wifi_cfg)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
- if (wifi_cfg) {
- /*
- * WMM
- * BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA
- * 0, 1, 0, 1, 0, 0, 0, 0, 0
- * 0:H, 1:L
- */
+ if (wifi_cfg) { /* WMM */
+ /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
+ /* 0, 1, 0, 1, 0, 0, 0, 0, 0}; */
+ /* 0:H, 1:L */
+
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
@@ -204,13 +221,12 @@ static void two_out_pipe(struct adapter *adapter, bool wifi_cfg)
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
- } else {
- /*
- * typical setting
- * BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA
- * 1, 1, 0, 0, 0, 0, 0, 0, 0
- * 0:H, 1:L
- */
+
+ } else {/* typical setting */
+ /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
+ /* 1, 1, 0, 0, 0, 0, 0, 0, 0}; */
+ /* 0:H, 1:L */
+
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
@@ -227,13 +243,11 @@ static void three_out_pipe(struct adapter *adapter, bool wifi_cfg)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
- if (wifi_cfg) {
- /*
- * for WMM
- * BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA
- * 1, 2, 1, 0, 0, 0, 0, 0, 0
- * 0:H, 1:N, 2:L
- */
+ if (wifi_cfg) {/* for WMM */
+ /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
+ /* 1, 2, 1, 0, 0, 0, 0, 0, 0}; */
+ /* 0:H, 1:N, 2:L */
+
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
@@ -243,13 +257,12 @@ static void three_out_pipe(struct adapter *adapter, bool wifi_cfg)
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
- } else {
- /*
- * typical setting
- * BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA
- * 2, 2, 1, 0, 0, 0, 0, 0, 0
- * 0:H, 1:N, 2:L
- */
+
+ } else {/* typical setting */
+ /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
+ /* 2, 2, 1, 0, 0, 0, 0, 0, 0}; */
+ /* 0:H, 1:N, 2:L */
+
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
@@ -262,24 +275,84 @@ static void three_out_pipe(struct adapter *adapter, bool wifi_cfg)
}
}
-bool hal_mapping_out_pipe(struct adapter *adapter, u8 numoutpipe)
+bool Hal_MappingOutPipe(struct adapter *adapter, u8 numoutpipe)
{
struct registry_priv *pregistrypriv = &adapter->registrypriv;
- bool wifi_cfg = (pregistrypriv->wifi_spec) ? true : false;
+ bool wifi_cfg = (pregistrypriv->wifi_spec) ? true : false;
bool result = true;
switch (numoutpipe) {
- case 1:
- one_out_pipe(adapter);
- break;
case 2:
two_out_pipe(adapter, wifi_cfg);
break;
case 3:
three_out_pipe(adapter, wifi_cfg);
break;
+ case 1:
+ one_out_pipe(adapter);
+ break;
default:
result = false;
+ break;
}
return result;
}
+
+void hal_init_macaddr(struct adapter *adapter)
+{
+ rtw_hal_set_hwreg(adapter, HW_VAR_MAC_ADDR,
+ adapter->eeprompriv.mac_addr);
+}
+
+/*
+* C2H event format:
+* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID
+* BITS [127:120] [119:16] [15:8] [7:4] [3:0]
+*/
+
+void c2h_evt_clear(struct adapter *adapter)
+{
+ rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
+}
+
+s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
+{
+ s32 ret = _FAIL;
+ struct c2h_evt_hdr *c2h_evt;
+ int i;
+ u8 trigger;
+
+ if (!buf)
+ goto exit;
+
+ trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
+
+ if (trigger == C2H_EVT_HOST_CLOSE)
+ goto exit; /* Not ready */
+ else if (trigger != C2H_EVT_FW_CLOSE)
+ goto clear_evt; /* Not a valid value */
+
+ c2h_evt = (struct c2h_evt_hdr *)buf;
+
+ memset(c2h_evt, 0, 16);
+
+ *buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
+ *(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
+
+ /* Read the content */
+ for (i = 0; i < c2h_evt->plen; i++)
+ c2h_evt->payload[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL +
+ sizeof(*c2h_evt) + i);
+
+ ret = _SUCCESS;
+
+clear_evt:
+ /*
+ * Clear event to notify FW we have read the command.
+ * If this field isn't clear, the FW won't update the next
+ * command message.
+ */
+ c2h_evt_clear(adapter);
+exit:
+ return ret;
+}
diff --git a/drivers/staging/r8188eu/hal/hal_intf.c b/drivers/staging/r8188eu/hal/hal_intf.c
new file mode 100644
index 000000000000..a6d589e89aeb
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/hal_intf.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#define _HAL_INTF_C_
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/hal_intf.h"
+
+void rtw_hal_chip_configure(struct adapter *adapt)
+{
+ if (adapt->HalFunc.intf_chip_configure)
+ adapt->HalFunc.intf_chip_configure(adapt);
+}
+
+void rtw_hal_read_chip_info(struct adapter *adapt)
+{
+ if (adapt->HalFunc.read_adapter_info)
+ adapt->HalFunc.read_adapter_info(adapt);
+}
+
+void rtw_hal_read_chip_version(struct adapter *adapt)
+{
+ if (adapt->HalFunc.read_chip_version)
+ adapt->HalFunc.read_chip_version(adapt);
+}
+
+void rtw_hal_def_value_init(struct adapter *adapt)
+{
+ if (adapt->HalFunc.init_default_value)
+ adapt->HalFunc.init_default_value(adapt);
+}
+
+void rtw_hal_free_data(struct adapter *adapt)
+{
+ if (adapt->HalFunc.free_hal_data)
+ adapt->HalFunc.free_hal_data(adapt);
+}
+
+void rtw_hal_dm_init(struct adapter *adapt)
+{
+ if (adapt->HalFunc.dm_init)
+ adapt->HalFunc.dm_init(adapt);
+}
+
+void rtw_hal_dm_deinit(struct adapter *adapt)
+{
+ /* cancel dm timer */
+ if (adapt->HalFunc.dm_deinit)
+ adapt->HalFunc.dm_deinit(adapt);
+}
+
+void rtw_hal_sw_led_init(struct adapter *adapt)
+{
+ if (adapt->HalFunc.InitSwLeds)
+ adapt->HalFunc.InitSwLeds(adapt);
+}
+
+void rtw_hal_sw_led_deinit(struct adapter *adapt)
+{
+ if (adapt->HalFunc.DeInitSwLeds)
+ adapt->HalFunc.DeInitSwLeds(adapt);
+}
+
+u32 rtw_hal_power_on(struct adapter *adapt)
+{
+ if (adapt->HalFunc.hal_power_on)
+ return adapt->HalFunc.hal_power_on(adapt);
+ return _FAIL;
+}
+
+uint rtw_hal_init(struct adapter *adapt)
+{
+ uint status = _SUCCESS;
+
+ adapt->hw_init_completed = false;
+
+ status = adapt->HalFunc.hal_init(adapt);
+
+ if (status == _SUCCESS) {
+ adapt->hw_init_completed = true;
+
+ if (adapt->registrypriv.notch_filter == 1)
+ rtw_hal_notch_filter(adapt, 1);
+
+ rtw_hal_reset_security_engine(adapt);
+ } else {
+ adapt->hw_init_completed = false;
+ DBG_88E("rtw_hal_init: hal__init fail\n");
+ }
+
+ return status;
+}
+
+uint rtw_hal_deinit(struct adapter *adapt)
+{
+ uint status = _SUCCESS;
+
+ status = adapt->HalFunc.hal_deinit(adapt);
+
+ if (status == _SUCCESS)
+ adapt->hw_init_completed = false;
+ else
+ DBG_88E("\n rtw_hal_deinit: hal_init fail\n");
+
+ return status;
+}
+
+void rtw_hal_set_hwreg(struct adapter *adapt, u8 variable, u8 *val)
+{
+ if (adapt->HalFunc.SetHwRegHandler)
+ adapt->HalFunc.SetHwRegHandler(adapt, variable, val);
+}
+
+void rtw_hal_get_hwreg(struct adapter *adapt, u8 variable, u8 *val)
+{
+ if (adapt->HalFunc.GetHwRegHandler)
+ adapt->HalFunc.GetHwRegHandler(adapt, variable, val);
+}
+
+u8 rtw_hal_set_def_var(struct adapter *adapt, enum hal_def_variable var,
+ void *val)
+{
+ if (adapt->HalFunc.SetHalDefVarHandler)
+ return adapt->HalFunc.SetHalDefVarHandler(adapt, var, val);
+ return _FAIL;
+}
+
+u8 rtw_hal_get_def_var(struct adapter *adapt,
+ enum hal_def_variable var, void *val)
+{
+ if (adapt->HalFunc.GetHalDefVarHandler)
+ return adapt->HalFunc.GetHalDefVarHandler(adapt, var, val);
+ return _FAIL;
+}
+
+void rtw_hal_set_odm_var(struct adapter *adapt,
+ enum hal_odm_variable var, void *val1,
+ bool set)
+{
+ if (adapt->HalFunc.SetHalODMVarHandler)
+ adapt->HalFunc.SetHalODMVarHandler(adapt, var,
+ val1, set);
+}
+
+void rtw_hal_get_odm_var(struct adapter *adapt,
+ enum hal_odm_variable var, void *val1,
+ bool set)
+{
+ if (adapt->HalFunc.GetHalODMVarHandler)
+ adapt->HalFunc.GetHalODMVarHandler(adapt, var,
+ val1, set);
+}
+
+void rtw_hal_enable_interrupt(struct adapter *adapt)
+{
+ if (adapt->HalFunc.enable_interrupt)
+ adapt->HalFunc.enable_interrupt(adapt);
+ else
+ DBG_88E("%s: HalFunc.enable_interrupt is NULL!\n", __func__);
+}
+
+void rtw_hal_disable_interrupt(struct adapter *adapt)
+{
+ if (adapt->HalFunc.disable_interrupt)
+ adapt->HalFunc.disable_interrupt(adapt);
+ else
+ DBG_88E("%s: HalFunc.disable_interrupt is NULL!\n", __func__);
+}
+
+u32 rtw_hal_inirp_init(struct adapter *adapt)
+{
+ u32 rst = _FAIL;
+
+ if (adapt->HalFunc.inirp_init)
+ rst = adapt->HalFunc.inirp_init(adapt);
+ else
+ DBG_88E(" %s HalFunc.inirp_init is NULL!!!\n", __func__);
+ return rst;
+}
+
+u32 rtw_hal_inirp_deinit(struct adapter *adapt)
+{
+ if (adapt->HalFunc.inirp_deinit)
+ return adapt->HalFunc.inirp_deinit(adapt);
+
+ return _FAIL;
+}
+
+u8 rtw_hal_intf_ps_func(struct adapter *adapt,
+ enum hal_intf_ps_func efunc_id, u8 *val)
+{
+ if (adapt->HalFunc.interface_ps_func)
+ return adapt->HalFunc.interface_ps_func(adapt, efunc_id,
+ val);
+ return _FAIL;
+}
+
+s32 rtw_hal_xmitframe_enqueue(struct adapter *padapter,
+ struct xmit_frame *pxmitframe)
+{
+ if (padapter->HalFunc.hal_xmitframe_enqueue)
+ return padapter->HalFunc.hal_xmitframe_enqueue(padapter, pxmitframe);
+ return false;
+}
+
+s32 rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
+{
+ if (adapt->HalFunc.hal_xmit)
+ return adapt->HalFunc.hal_xmit(adapt, pxmitframe);
+
+ return false;
+}
+
+s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe)
+{
+ s32 ret = _FAIL;
+ if (adapt->HalFunc.mgnt_xmit)
+ ret = adapt->HalFunc.mgnt_xmit(adapt, pmgntframe);
+ return ret;
+}
+
+s32 rtw_hal_init_xmit_priv(struct adapter *adapt)
+{
+ if (adapt->HalFunc.init_xmit_priv)
+ return adapt->HalFunc.init_xmit_priv(adapt);
+ return _FAIL;
+}
+
+s32 rtw_hal_init_recv_priv(struct adapter *adapt)
+{
+ if (adapt->HalFunc.init_recv_priv)
+ return adapt->HalFunc.init_recv_priv(adapt);
+
+ return _FAIL;
+}
+
+void rtw_hal_free_recv_priv(struct adapter *adapt)
+{
+ if (adapt->HalFunc.free_recv_priv)
+ adapt->HalFunc.free_recv_priv(adapt);
+}
+
+void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level)
+{
+ struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+#ifdef CONFIG_88EU_AP_MODE
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &adapt->stapriv;
+ if ((mac_id - 1) > 0)
+ psta = pstapriv->sta_aid[(mac_id - 1) - 1];
+ if (psta)
+ add_RATid(adapt, psta, 0);/* todo: based on rssi_level*/
+#endif
+ } else {
+ if (adapt->HalFunc.UpdateRAMaskHandler)
+ adapt->HalFunc.UpdateRAMaskHandler(adapt, mac_id,
+ rssi_level);
+ }
+}
+
+void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg,
+ u8 rssi_level)
+{
+ if (adapt->HalFunc.Add_RateATid)
+ adapt->HalFunc.Add_RateATid(adapt, bitmap, arg,
+ rssi_level);
+}
+
+/* Start specifical interface thread */
+void rtw_hal_start_thread(struct adapter *adapt)
+{
+ if (adapt->HalFunc.run_thread)
+ adapt->HalFunc.run_thread(adapt);
+}
+
+/* Start specifical interface thread */
+void rtw_hal_stop_thread(struct adapter *adapt)
+{
+ if (adapt->HalFunc.cancel_thread)
+ adapt->HalFunc.cancel_thread(adapt);
+}
+
+u32 rtw_hal_read_bbreg(struct adapter *adapt, u32 regaddr, u32 bitmask)
+{
+ u32 data = 0;
+
+ if (adapt->HalFunc.read_bbreg)
+ data = adapt->HalFunc.read_bbreg(adapt, regaddr, bitmask);
+ return data;
+}
+
+void rtw_hal_write_bbreg(struct adapter *adapt, u32 regaddr, u32 bitmask,
+ u32 data)
+{
+ if (adapt->HalFunc.write_bbreg)
+ adapt->HalFunc.write_bbreg(adapt, regaddr, bitmask, data);
+}
+
+u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rfpath,
+ u32 regaddr, u32 bitmask)
+{
+ u32 data = 0;
+
+ if (adapt->HalFunc.read_rfreg)
+ data = adapt->HalFunc.read_rfreg(adapt, rfpath, regaddr,
+ bitmask);
+ return data;
+}
+
+void rtw_hal_write_rfreg(struct adapter *adapt, enum rf_radio_path rfpath,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ if (adapt->HalFunc.write_rfreg)
+ adapt->HalFunc.write_rfreg(adapt, rfpath, regaddr,
+ bitmask, data);
+}
+
+s32 rtw_hal_interrupt_handler(struct adapter *adapt)
+{
+ if (adapt->HalFunc.interrupt_handler)
+ return adapt->HalFunc.interrupt_handler(adapt);
+ return _FAIL;
+}
+
+void rtw_hal_set_bwmode(struct adapter *adapt,
+ enum ht_channel_width bandwidth, u8 offset)
+{
+ if (adapt->HalFunc.set_bwmode_handler)
+ adapt->HalFunc.set_bwmode_handler(adapt, bandwidth,
+ offset);
+}
+
+void rtw_hal_set_chan(struct adapter *adapt, u8 channel)
+{
+ if (adapt->HalFunc.set_channel_handler)
+ adapt->HalFunc.set_channel_handler(adapt, channel);
+}
+
+void rtw_hal_dm_watchdog(struct adapter *adapt)
+{
+ if (adapt->HalFunc.hal_dm_watchdog)
+ adapt->HalFunc.hal_dm_watchdog(adapt);
+}
+
+void rtw_hal_bcn_related_reg_setting(struct adapter *adapt)
+{
+ if (adapt->HalFunc.SetBeaconRelatedRegistersHandler)
+ adapt->HalFunc.SetBeaconRelatedRegistersHandler(adapt);
+}
+
+u8 rtw_hal_antdiv_before_linked(struct adapter *adapt)
+{
+ if (adapt->HalFunc.AntDivBeforeLinkHandler)
+ return adapt->HalFunc.AntDivBeforeLinkHandler(adapt);
+ return false;
+}
+
+void rtw_hal_antdiv_rssi_compared(struct adapter *adapt,
+ struct wlan_bssid_ex *dst,
+ struct wlan_bssid_ex *src)
+{
+ if (adapt->HalFunc.AntDivCompareHandler)
+ adapt->HalFunc.AntDivCompareHandler(adapt, dst, src);
+}
+
+void rtw_hal_sreset_init(struct adapter *adapt)
+{
+ if (adapt->HalFunc.sreset_init_value)
+ adapt->HalFunc.sreset_init_value(adapt);
+}
+
+void rtw_hal_sreset_reset(struct adapter *adapt)
+{
+ if (adapt->HalFunc.silentreset)
+ adapt->HalFunc.silentreset(adapt);
+}
+
+void rtw_hal_sreset_reset_value(struct adapter *adapt)
+{
+ if (adapt->HalFunc.sreset_reset_value)
+ adapt->HalFunc.sreset_reset_value(adapt);
+}
+
+void rtw_hal_sreset_xmit_status_check(struct adapter *adapt)
+{
+ if (adapt->HalFunc.sreset_xmit_status_check)
+ adapt->HalFunc.sreset_xmit_status_check(adapt);
+}
+
+void rtw_hal_sreset_linked_status_check(struct adapter *adapt)
+{
+ if (adapt->HalFunc.sreset_linked_status_check)
+ adapt->HalFunc.sreset_linked_status_check(adapt);
+}
+
+u8 rtw_hal_sreset_get_wifi_status(struct adapter *adapt)
+{
+ u8 status = 0;
+
+ if (adapt->HalFunc.sreset_get_wifi_status)
+ status = adapt->HalFunc.sreset_get_wifi_status(adapt);
+ return status;
+}
+
+int rtw_hal_iol_cmd(struct adapter *adapter, struct xmit_frame *xmit_frame,
+ u32 max_wating_ms, u32 bndy_cnt)
+{
+ if (adapter->HalFunc.IOL_exec_cmds_sync)
+ return adapter->HalFunc.IOL_exec_cmds_sync(adapter, xmit_frame,
+ max_wating_ms,
+ bndy_cnt);
+ return _FAIL;
+}
+
+void rtw_hal_notch_filter(struct adapter *adapter, bool enable)
+{
+ if (adapter->HalFunc.hal_notch_filter)
+ adapter->HalFunc.hal_notch_filter(adapter, enable);
+}
+
+void rtw_hal_reset_security_engine(struct adapter *adapter)
+{
+ if (adapter->HalFunc.hal_reset_security_engine)
+ adapter->HalFunc.hal_reset_security_engine(adapter);
+}
+
+s32 rtw_hal_c2h_handler(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt)
+{
+ s32 ret = _FAIL;
+
+ if (adapter->HalFunc.c2h_handler)
+ ret = adapter->HalFunc.c2h_handler(adapter, c2h_evt);
+ return ret;
+}
+
+c2h_id_filter rtw_hal_c2h_id_filter_ccx(struct adapter *adapter)
+{
+ return adapter->HalFunc.c2h_id_filter_ccx;
+}
diff --git a/drivers/staging/r8188eu/hal/odm.c b/drivers/staging/r8188eu/hal/odm.c
new file mode 100644
index 000000000000..ed94f64d878d
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/odm.c
@@ -0,0 +1,1968 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+/* include files */
+
+#include "../include/odm_precomp.h"
+
+static const u16 dB_Invert_Table[8][12] = {
+ {1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4},
+ {4, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16},
+ {18, 20, 22, 25, 28, 32, 35, 40, 45, 50, 56, 63},
+ {71, 79, 89, 100, 112, 126, 141, 158, 178, 200, 224, 251},
+ {282, 316, 355, 398, 447, 501, 562, 631, 708, 794, 891, 1000},
+ {1122, 1259, 1413, 1585, 1778, 1995, 2239, 2512, 2818, 3162, 3548, 3981},
+ {4467, 5012, 5623, 6310, 7079, 7943, 8913, 10000, 11220, 12589, 14125, 15849},
+ {17783, 19953, 22387, 25119, 28184, 31623, 35481, 39811, 44668, 50119, 56234, 65535}
+};
+
+/* avoid to warn in FreeBSD ==> To DO modify */
+static u32 EDCAParam[HT_IOT_PEER_MAX][3] = {
+ /* UL DL */
+ {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */
+ {0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */
+ {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */
+ {0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */
+ {0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */
+ {0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */
+ {0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */
+ {0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */
+ {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP=> 92U AP */
+ {0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */
+};
+
+/* Global var */
+u32 OFDMSwingTable[OFDM_TABLE_SIZE_92D] = {
+ 0x7f8001fe, /* 0, +6.0dB */
+ 0x788001e2, /* 1, +5.5dB */
+ 0x71c001c7, /* 2, +5.0dB */
+ 0x6b8001ae, /* 3, +4.5dB */
+ 0x65400195, /* 4, +4.0dB */
+ 0x5fc0017f, /* 5, +3.5dB */
+ 0x5a400169, /* 6, +3.0dB */
+ 0x55400155, /* 7, +2.5dB */
+ 0x50800142, /* 8, +2.0dB */
+ 0x4c000130, /* 9, +1.5dB */
+ 0x47c0011f, /* 10, +1.0dB */
+ 0x43c0010f, /* 11, +0.5dB */
+ 0x40000100, /* 12, +0dB */
+ 0x3c8000f2, /* 13, -0.5dB */
+ 0x390000e4, /* 14, -1.0dB */
+ 0x35c000d7, /* 15, -1.5dB */
+ 0x32c000cb, /* 16, -2.0dB */
+ 0x300000c0, /* 17, -2.5dB */
+ 0x2d4000b5, /* 18, -3.0dB */
+ 0x2ac000ab, /* 19, -3.5dB */
+ 0x288000a2, /* 20, -4.0dB */
+ 0x26000098, /* 21, -4.5dB */
+ 0x24000090, /* 22, -5.0dB */
+ 0x22000088, /* 23, -5.5dB */
+ 0x20000080, /* 24, -6.0dB */
+ 0x1e400079, /* 25, -6.5dB */
+ 0x1c800072, /* 26, -7.0dB */
+ 0x1b00006c, /* 27. -7.5dB */
+ 0x19800066, /* 28, -8.0dB */
+ 0x18000060, /* 29, -8.5dB */
+ 0x16c0005b, /* 30, -9.0dB */
+ 0x15800056, /* 31, -9.5dB */
+ 0x14400051, /* 32, -10.0dB */
+ 0x1300004c, /* 33, -10.5dB */
+ 0x12000048, /* 34, -11.0dB */
+ 0x11000044, /* 35, -11.5dB */
+ 0x10000040, /* 36, -12.0dB */
+ 0x0f00003c,/* 37, -12.5dB */
+ 0x0e400039,/* 38, -13.0dB */
+ 0x0d800036,/* 39, -13.5dB */
+ 0x0cc00033,/* 40, -14.0dB */
+ 0x0c000030,/* 41, -14.5dB */
+ 0x0b40002d,/* 42, -15.0dB */
+};
+
+u8 CCKSwingTable_Ch1_Ch13[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */
+ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */
+};
+
+u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */
+ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */
+};
+
+#define RxDefaultAnt1 0x65a9
+#define RxDefaultAnt2 0x569a
+
+/* 3 Export Interface */
+
+/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */
+void ODM_DMInit(struct odm_dm_struct *pDM_Odm)
+{
+ /* 2012.05.03 Luke: For all IC series */
+ odm_CommonInfoSelfInit(pDM_Odm);
+ odm_DIGInit(pDM_Odm);
+ odm_RateAdaptiveMaskInit(pDM_Odm);
+
+ if (pDM_Odm->SupportICType & ODM_IC_11AC_SERIES) {
+ ;
+ } else if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
+ odm_PrimaryCCA_Init(pDM_Odm); /* Gary */
+ odm_DynamicBBPowerSavingInit(pDM_Odm);
+ odm_DynamicTxPowerInit(pDM_Odm);
+ odm_TXPowerTrackingInit(pDM_Odm);
+ ODM_EdcaTurboInit(pDM_Odm);
+ ODM_RAInfo_Init_all(pDM_Odm);
+ if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
+ (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
+ (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
+ odm_InitHybridAntDiv(pDM_Odm);
+ else if (pDM_Odm->AntDivType == CGCS_RX_SW_ANTDIV)
+ odm_SwAntDivInit(pDM_Odm);
+ }
+}
+
+/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */
+/* You can not add any dummy function here, be care, you can only use DM structure */
+/* to perform any new ODM_DM. */
+void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm)
+{
+ /* 2012.05.03 Luke: For all IC series */
+ odm_GlobalAdapterCheck();
+ odm_CommonInfoSelfUpdate(pDM_Odm);
+ odm_FalseAlarmCounterStatistics(pDM_Odm);
+ odm_RSSIMonitorCheck(pDM_Odm);
+
+ /* For CE Platform(SPRD or Tablet) */
+ /* 8723A or 8189ES platform */
+ /* NeilChen--2012--08--24-- */
+ /* Fix Leave LPS issue */
+ if ((pDM_Odm->Adapter->pwrctrlpriv.pwr_mode != PS_MODE_ACTIVE) &&/* in LPS mode */
+ ((pDM_Odm->SupportICType & (ODM_RTL8723A)) ||
+ (pDM_Odm->SupportICType & (ODM_RTL8188E) &&
+ ((pDM_Odm->SupportInterface == ODM_ITRF_SDIO)))))
+ odm_DIGbyRSSI_LPS(pDM_Odm);
+ else
+ odm_DIG(pDM_Odm);
+ odm_CCKPacketDetectionThresh(pDM_Odm);
+
+ if (*pDM_Odm->pbPowerSaving)
+ return;
+
+ odm_RefreshRateAdaptiveMask(pDM_Odm);
+
+ odm_DynamicBBPowerSaving(pDM_Odm);
+ if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
+ (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
+ (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
+ odm_HwAntDiv(pDM_Odm);
+ else if (pDM_Odm->AntDivType == CGCS_RX_SW_ANTDIV)
+ odm_SwAntDivChkAntSwitch(pDM_Odm, SWAW_STEP_PEAK);
+
+ if (pDM_Odm->SupportICType & ODM_IC_11AC_SERIES) {
+ ;
+ } else if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
+ ODM_TXPowerTrackingCheck(pDM_Odm);
+ odm_EdcaTurboCheck(pDM_Odm);
+ odm_DynamicTxPower(pDM_Odm);
+ }
+ odm_dtc(pDM_Odm);
+}
+
+/* Init /.. Fixed HW value. Only init time. */
+void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u32 Value)
+{
+ /* This section is used for init value */
+ switch (CmnInfo) {
+ /* Fixed ODM value. */
+ case ODM_CMNINFO_ABILITY:
+ pDM_Odm->SupportAbility = (u32)Value;
+ break;
+ case ODM_CMNINFO_PLATFORM:
+ pDM_Odm->SupportPlatform = (u8)Value;
+ break;
+ case ODM_CMNINFO_INTERFACE:
+ pDM_Odm->SupportInterface = (u8)Value;
+ break;
+ case ODM_CMNINFO_MP_TEST_CHIP:
+ pDM_Odm->bIsMPChip = (u8)Value;
+ break;
+ case ODM_CMNINFO_IC_TYPE:
+ pDM_Odm->SupportICType = Value;
+ break;
+ case ODM_CMNINFO_CUT_VER:
+ pDM_Odm->CutVersion = (u8)Value;
+ break;
+ case ODM_CMNINFO_FAB_VER:
+ pDM_Odm->FabVersion = (u8)Value;
+ break;
+ case ODM_CMNINFO_RF_TYPE:
+ pDM_Odm->RFType = (u8)Value;
+ break;
+ case ODM_CMNINFO_RF_ANTENNA_TYPE:
+ pDM_Odm->AntDivType = (u8)Value;
+ break;
+ case ODM_CMNINFO_BOARD_TYPE:
+ pDM_Odm->BoardType = (u8)Value;
+ break;
+ case ODM_CMNINFO_EXT_LNA:
+ pDM_Odm->ExtLNA = (u8)Value;
+ break;
+ case ODM_CMNINFO_EXT_PA:
+ pDM_Odm->ExtPA = (u8)Value;
+ break;
+ case ODM_CMNINFO_EXT_TRSW:
+ pDM_Odm->ExtTRSW = (u8)Value;
+ break;
+ case ODM_CMNINFO_PATCH_ID:
+ pDM_Odm->PatchID = (u8)Value;
+ break;
+ case ODM_CMNINFO_BINHCT_TEST:
+ pDM_Odm->bInHctTest = (bool)Value;
+ break;
+ case ODM_CMNINFO_BWIFI_TEST:
+ pDM_Odm->bWIFITest = (bool)Value;
+ break;
+ case ODM_CMNINFO_SMART_CONCURRENT:
+ pDM_Odm->bDualMacSmartConcurrent = (bool)Value;
+ break;
+ /* To remove the compiler warning, must add an empty default statement to handle the other values. */
+ default:
+ /* do nothing */
+ break;
+ }
+
+ /* Tx power tracking BB swing table. */
+ /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
+ pDM_Odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */
+ pDM_Odm->BbSwingIdxOfdmCurrent = 12;
+ pDM_Odm->BbSwingFlagOfdm = false;
+}
+
+void ODM_CmnInfoHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, void *pValue)
+{
+ /* */
+ /* Hook call by reference pointer. */
+ /* */
+ switch (CmnInfo) {
+ /* Dynamic call by reference pointer. */
+ case ODM_CMNINFO_MAC_PHY_MODE:
+ pDM_Odm->pMacPhyMode = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_TX_UNI:
+ pDM_Odm->pNumTxBytesUnicast = (u64 *)pValue;
+ break;
+ case ODM_CMNINFO_RX_UNI:
+ pDM_Odm->pNumRxBytesUnicast = (u64 *)pValue;
+ break;
+ case ODM_CMNINFO_WM_MODE:
+ pDM_Odm->pWirelessMode = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_BAND:
+ pDM_Odm->pBandType = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_SEC_CHNL_OFFSET:
+ pDM_Odm->pSecChOffset = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_SEC_MODE:
+ pDM_Odm->pSecurity = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_BW:
+ pDM_Odm->pBandWidth = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_CHNL:
+ pDM_Odm->pChannel = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_DMSP_GET_VALUE:
+ pDM_Odm->pbGetValueFromOtherMac = (bool *)pValue;
+ break;
+ case ODM_CMNINFO_BUDDY_ADAPTOR:
+ pDM_Odm->pBuddyAdapter = (struct adapter **)pValue;
+ break;
+ case ODM_CMNINFO_DMSP_IS_MASTER:
+ pDM_Odm->pbMasterOfDMSP = (bool *)pValue;
+ break;
+ case ODM_CMNINFO_SCAN:
+ pDM_Odm->pbScanInProcess = (bool *)pValue;
+ break;
+ case ODM_CMNINFO_POWER_SAVING:
+ pDM_Odm->pbPowerSaving = (bool *)pValue;
+ break;
+ case ODM_CMNINFO_ONE_PATH_CCA:
+ pDM_Odm->pOnePathCCA = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_DRV_STOP:
+ pDM_Odm->pbDriverStopped = (bool *)pValue;
+ break;
+ case ODM_CMNINFO_PNP_IN:
+ pDM_Odm->pbDriverIsGoingToPnpSetPowerSleep = (bool *)pValue;
+ break;
+ case ODM_CMNINFO_INIT_ON:
+ pDM_Odm->pinit_adpt_in_progress = (bool *)pValue;
+ break;
+ case ODM_CMNINFO_ANT_TEST:
+ pDM_Odm->pAntennaTest = (u8 *)pValue;
+ break;
+ case ODM_CMNINFO_NET_CLOSED:
+ pDM_Odm->pbNet_closed = (bool *)pValue;
+ break;
+ case ODM_CMNINFO_MP_MODE:
+ pDM_Odm->mp_mode = (u8 *)pValue;
+ break;
+ /* To remove the compiler warning, must add an empty default statement to handle the other values. */
+ default:
+ /* do nothing */
+ break;
+ }
+}
+
+void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u16 Index, void *pValue)
+{
+ /* Hook call by reference pointer. */
+ switch (CmnInfo) {
+ /* Dynamic call by reference pointer. */
+ case ODM_CMNINFO_STA_STATUS:
+ pDM_Odm->pODM_StaInfo[Index] = (struct sta_info *)pValue;
+ break;
+ /* To remove the compiler warning, must add an empty default statement to handle the other values. */
+ default:
+ /* do nothing */
+ break;
+ }
+}
+
+/* Update Band/CHannel/.. The values are dynamic but non-per-packet. */
+void ODM_CmnInfoUpdate(struct odm_dm_struct *pDM_Odm, u32 CmnInfo, u64 Value)
+{
+ /* */
+ /* This init variable may be changed in run time. */
+ /* */
+ switch (CmnInfo) {
+ case ODM_CMNINFO_ABILITY:
+ pDM_Odm->SupportAbility = (u32)Value;
+ break;
+ case ODM_CMNINFO_RF_TYPE:
+ pDM_Odm->RFType = (u8)Value;
+ break;
+ case ODM_CMNINFO_WIFI_DIRECT:
+ pDM_Odm->bWIFI_Direct = (bool)Value;
+ break;
+ case ODM_CMNINFO_WIFI_DISPLAY:
+ pDM_Odm->bWIFI_Display = (bool)Value;
+ break;
+ case ODM_CMNINFO_LINK:
+ pDM_Odm->bLinked = (bool)Value;
+ break;
+ case ODM_CMNINFO_RSSI_MIN:
+ pDM_Odm->RSSI_Min = (u8)Value;
+ break;
+ case ODM_CMNINFO_RA_THRESHOLD_HIGH:
+ pDM_Odm->RateAdaptive.HighRSSIThresh = (u8)Value;
+ break;
+ case ODM_CMNINFO_RA_THRESHOLD_LOW:
+ pDM_Odm->RateAdaptive.LowRSSIThresh = (u8)Value;
+ break;
+ }
+}
+
+void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm)
+{
+ pDM_Odm->bCckHighPower = (bool)ODM_GetBBReg(pDM_Odm, 0x824, BIT(9));
+ pDM_Odm->RFPathRxEnable = (u8)ODM_GetBBReg(pDM_Odm, 0xc04, 0x0F);
+ if (pDM_Odm->SupportICType & (ODM_RTL8192C | ODM_RTL8192D))
+ pDM_Odm->AntDivType = CG_TRX_HW_ANTDIV;
+ if (pDM_Odm->SupportICType & (ODM_RTL8723A))
+ pDM_Odm->AntDivType = CGCS_RX_SW_ANTDIV;
+}
+
+void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm)
+{
+ u8 EntryCnt = 0;
+ u8 i;
+ struct sta_info *pEntry;
+
+ if (*pDM_Odm->pBandWidth == ODM_BW40M) {
+ if (*pDM_Odm->pSecChOffset == 1)
+ pDM_Odm->ControlChannel = *pDM_Odm->pChannel - 2;
+ else if (*pDM_Odm->pSecChOffset == 2)
+ pDM_Odm->ControlChannel = *pDM_Odm->pChannel + 2;
+ } else {
+ pDM_Odm->ControlChannel = *pDM_Odm->pChannel;
+ }
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ pEntry = pDM_Odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(pEntry))
+ EntryCnt++;
+ }
+ if (EntryCnt == 1)
+ pDM_Odm->bOneEntryOnly = true;
+ else
+ pDM_Odm->bOneEntryOnly = false;
+}
+
+static int getIGIForDiff(int value_IGI)
+{
+ #define ONERCCA_LOW_TH 0x30
+ #define ONERCCA_LOW_DIFF 8
+
+ if (value_IGI < ONERCCA_LOW_TH) {
+ if ((ONERCCA_LOW_TH - value_IGI) < ONERCCA_LOW_DIFF)
+ return ONERCCA_LOW_TH;
+ else
+ return value_IGI + ONERCCA_LOW_DIFF;
+ } else {
+ return value_IGI;
+ }
+}
+
+void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI)
+{
+ struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+
+ if (pDM_DigTable->CurIGValue != CurrentIGI) {
+ if (pDM_Odm->SupportPlatform & (ODM_CE | ODM_MP)) {
+ ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+ if (pDM_Odm->SupportICType != ODM_RTL8188E)
+ ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+ } else if (pDM_Odm->SupportPlatform & (ODM_AP | ODM_ADSL)) {
+ switch (*pDM_Odm->pOnePathCCA) {
+ case ODM_CCA_2R:
+ ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+ if (pDM_Odm->SupportICType != ODM_RTL8188E)
+ ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+ break;
+ case ODM_CCA_1R_A:
+ ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+ if (pDM_Odm->SupportICType != ODM_RTL8188E)
+ ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), getIGIForDiff(CurrentIGI));
+ break;
+ case ODM_CCA_1R_B:
+ ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), getIGIForDiff(CurrentIGI));
+ if (pDM_Odm->SupportICType != ODM_RTL8188E)
+ ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+ break;
+ }
+ }
+ /* pDM_DigTable->PreIGValue = pDM_DigTable->CurIGValue; */
+ pDM_DigTable->CurIGValue = CurrentIGI;
+ }
+/* Add by Neil Chen to enable edcca to MP Platform */
+}
+
+/* Need LPS mode for CE platform --2012--08--24--- */
+/* 8723AS/8189ES */
+void odm_DIGbyRSSI_LPS(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *pAdapter = pDM_Odm->Adapter;
+ struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+
+ u8 RSSI_Lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */
+ u8 bFwCurrentInPSMode = false;
+ u8 CurrentIGI = pDM_Odm->RSSI_Min;
+
+ if (!(pDM_Odm->SupportICType & (ODM_RTL8723A | ODM_RTL8188E)))
+ return;
+
+ CurrentIGI = CurrentIGI + RSSI_OFFSET_DIG;
+ bFwCurrentInPSMode = pAdapter->pwrctrlpriv.bFwCurrentInPSMode;
+
+ /* Using FW PS mode to make IGI */
+ if (bFwCurrentInPSMode) {
+ /* Adjust by FA in LPS MODE */
+ if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
+ CurrentIGI = CurrentIGI + 2;
+ else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS)
+ CurrentIGI = CurrentIGI + 1;
+ else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS)
+ CurrentIGI = CurrentIGI - 1;
+ } else {
+ CurrentIGI = RSSI_Lower;
+ }
+
+ /* Lower bound checking */
+
+ /* RSSI Lower bound check */
+ if ((pDM_Odm->RSSI_Min - 10) > DM_DIG_MIN_NIC)
+ RSSI_Lower = (pDM_Odm->RSSI_Min - 10);
+ else
+ RSSI_Lower = DM_DIG_MIN_NIC;
+
+ /* Upper and Lower Bound checking */
+ if (CurrentIGI > DM_DIG_MAX_NIC)
+ CurrentIGI = DM_DIG_MAX_NIC;
+ else if (CurrentIGI < RSSI_Lower)
+ CurrentIGI = RSSI_Lower;
+
+ ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
+}
+
+void odm_DIGInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+
+ pDM_DigTable->CurIGValue = (u8)ODM_GetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
+ pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW;
+ pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH;
+ pDM_DigTable->FALowThresh = DM_false_ALARM_THRESH_LOW;
+ pDM_DigTable->FAHighThresh = DM_false_ALARM_THRESH_HIGH;
+ if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) {
+ pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
+ pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
+ } else {
+ pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
+ pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
+ }
+ pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
+ pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
+ pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
+ pDM_DigTable->PreCCK_CCAThres = 0xFF;
+ pDM_DigTable->CurCCK_CCAThres = 0x83;
+ pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
+ pDM_DigTable->LargeFAHit = 0;
+ pDM_DigTable->Recover_cnt = 0;
+ pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
+ pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
+ pDM_DigTable->bMediaConnect_0 = false;
+ pDM_DigTable->bMediaConnect_1 = false;
+
+ /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
+ pDM_Odm->bDMInitialGainEnable = true;
+}
+
+void odm_DIG(struct odm_dm_struct *pDM_Odm)
+{
+ struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+ struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+ u8 DIG_Dynamic_MIN;
+ u8 DIG_MaxOfMin;
+ bool FirstConnect, FirstDisConnect;
+ u8 dm_dig_max, dm_dig_min;
+ u8 CurrentIGI = pDM_DigTable->CurIGValue;
+
+ if ((!(pDM_Odm->SupportAbility & ODM_BB_DIG)) || (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)))
+ return;
+
+ if (*pDM_Odm->pbScanInProcess)
+ return;
+
+ /* add by Neil Chen to avoid PSD is processing */
+ if (!pDM_Odm->bDMInitialGainEnable)
+ return;
+
+ if (pDM_Odm->SupportICType == ODM_RTL8192D) {
+ if (*pDM_Odm->pMacPhyMode == ODM_DMSP) {
+ if (*pDM_Odm->pbMasterOfDMSP) {
+ DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
+ FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0);
+ FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0);
+ } else {
+ DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_1;
+ FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_1);
+ FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_1);
+ }
+ } else {
+ DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_1;
+ FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_1);
+ FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_1);
+ }
+ } else {
+ DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
+ FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0);
+ FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0);
+ }
+
+ /* 1 Boundary Decision */
+ if ((pDM_Odm->SupportICType & (ODM_RTL8192C | ODM_RTL8723A)) &&
+ ((pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) || pDM_Odm->ExtLNA)) {
+ if (pDM_Odm->SupportPlatform & (ODM_AP | ODM_ADSL)) {
+ dm_dig_max = DM_DIG_MAX_AP_HP;
+ dm_dig_min = DM_DIG_MIN_AP_HP;
+ } else {
+ dm_dig_max = DM_DIG_MAX_NIC_HP;
+ dm_dig_min = DM_DIG_MIN_NIC_HP;
+ }
+ DIG_MaxOfMin = DM_DIG_MAX_AP_HP;
+ } else {
+ if (pDM_Odm->SupportPlatform & (ODM_AP | ODM_ADSL)) {
+ dm_dig_max = DM_DIG_MAX_AP;
+ dm_dig_min = DM_DIG_MIN_AP;
+ DIG_MaxOfMin = dm_dig_max;
+ } else {
+ dm_dig_max = DM_DIG_MAX_NIC;
+ dm_dig_min = DM_DIG_MIN_NIC;
+ DIG_MaxOfMin = DM_DIG_MAX_AP;
+ }
+ }
+ if (pDM_Odm->bLinked) {
+ /* 2 8723A Series, offset need to be 10 */
+ if (pDM_Odm->SupportICType == (ODM_RTL8723A)) {
+ /* 2 Upper Bound */
+ if ((pDM_Odm->RSSI_Min + 10) > DM_DIG_MAX_NIC)
+ pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
+ else if ((pDM_Odm->RSSI_Min + 10) < DM_DIG_MIN_NIC)
+ pDM_DigTable->rx_gain_range_max = DM_DIG_MIN_NIC;
+ else
+ pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 10;
+ /* 2 If BT is Concurrent, need to set Lower Bound */
+ DIG_Dynamic_MIN = DM_DIG_MIN_NIC;
+ } else {
+ /* 2 Modify DIG upper bound */
+ if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max)
+ pDM_DigTable->rx_gain_range_max = dm_dig_max;
+ else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min)
+ pDM_DigTable->rx_gain_range_max = dm_dig_min;
+ else
+ pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20;
+ /* 2 Modify DIG lower bound */
+ if (pDM_Odm->bOneEntryOnly) {
+ if (pDM_Odm->RSSI_Min < dm_dig_min)
+ DIG_Dynamic_MIN = dm_dig_min;
+ else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
+ DIG_Dynamic_MIN = DIG_MaxOfMin;
+ else
+ DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
+ } else if ((pDM_Odm->SupportICType == ODM_RTL8188E) &&
+ (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) {
+ /* 1 Lower Bound for 88E AntDiv */
+ if (pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV)
+ DIG_Dynamic_MIN = (u8)pDM_DigTable->AntDiv_RSSI_max;
+ } else {
+ DIG_Dynamic_MIN = dm_dig_min;
+ }
+ }
+ } else {
+ pDM_DigTable->rx_gain_range_max = dm_dig_max;
+ DIG_Dynamic_MIN = dm_dig_min;
+ }
+
+ /* 1 Modify DIG lower bound, deal with abnormally large false alarm */
+ if (pFalseAlmCnt->Cnt_all > 10000) {
+ if (pDM_DigTable->LargeFAHit != 3)
+ pDM_DigTable->LargeFAHit++;
+ if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
+ pDM_DigTable->ForbiddenIGI = CurrentIGI;
+ pDM_DigTable->LargeFAHit = 1;
+ }
+
+ if (pDM_DigTable->LargeFAHit >= 3) {
+ if ((pDM_DigTable->ForbiddenIGI + 1) > pDM_DigTable->rx_gain_range_max)
+ pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
+ else
+ pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
+ pDM_DigTable->Recover_cnt = 3600; /* 3600=2hr */
+ }
+
+ } else {
+ /* Recovery mechanism for IGI lower bound */
+ if (pDM_DigTable->Recover_cnt != 0) {
+ pDM_DigTable->Recover_cnt--;
+ } else {
+ if (pDM_DigTable->LargeFAHit < 3) {
+ if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */
+ pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
+ pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
+ } else {
+ pDM_DigTable->ForbiddenIGI--;
+ pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
+ }
+ } else {
+ pDM_DigTable->LargeFAHit = 0;
+ }
+ }
+ }
+
+ /* 1 Adjust initial gain by false alarm */
+ if (pDM_Odm->bLinked) {
+ if (FirstConnect) {
+ CurrentIGI = pDM_Odm->RSSI_Min;
+ } else {
+ if (pDM_Odm->SupportICType == ODM_RTL8192D) {
+ if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_92D)
+ CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
+ else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_92D)
+ CurrentIGI = CurrentIGI + 1; /* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
+ else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_92D)
+ CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */
+ } else {
+ if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2)
+ CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
+ else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1)
+ CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
+ else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0)
+ CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */
+ }
+ }
+ } else {
+ if (FirstDisConnect) {
+ CurrentIGI = pDM_DigTable->rx_gain_range_min;
+ } else {
+ /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */
+ if (pFalseAlmCnt->Cnt_all > 10000)
+ CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
+ else if (pFalseAlmCnt->Cnt_all > 8000)
+ CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
+ else if (pFalseAlmCnt->Cnt_all < 500)
+ CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */
+ }
+ }
+ /* 1 Check initial gain by upper/lower bound */
+ if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
+ CurrentIGI = pDM_DigTable->rx_gain_range_max;
+ if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
+ CurrentIGI = pDM_DigTable->rx_gain_range_min;
+
+ /* 2 High power RSSI threshold */
+
+ ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
+ pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
+ pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
+}
+
+/* 3============================================================ */
+/* 3 FASLE ALARM CHECK */
+/* 3============================================================ */
+
+void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
+{
+ u32 ret_value;
+ struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
+ return;
+
+ if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
+ /* hold ofdm counter */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */
+
+ ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Fast_Fsync = (ret_value & 0xffff);
+ FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_OFDM_CCA = (ret_value & 0xffff);
+ FalseAlmCnt->Cnt_Parity_Fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Rate_Illegal = (ret_value & 0xffff);
+ FalseAlmCnt->Cnt_Crc8_fail = ((ret_value & 0xffff0000) >> 16);
+ ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Mcs_fail = (ret_value & 0xffff);
+
+ FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal +
+ FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail +
+ FalseAlmCnt->Cnt_Fast_Fsync + FalseAlmCnt->Cnt_SB_Search_fail;
+
+ if (pDM_Odm->SupportICType == ODM_RTL8188E) {
+ ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_SC_CNT_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_BW_LSC = (ret_value & 0xffff);
+ FalseAlmCnt->Cnt_BW_USC = ((ret_value & 0xffff0000) >> 16);
+ }
+
+ /* hold cck counter */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(12), 1);
+ ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(14), 1);
+
+ ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
+ FalseAlmCnt->Cnt_Cck_fail = ret_value;
+ ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_MSB_11N, bMaskByte3);
+ FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff) << 8;
+
+ ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_CCK_CCA = ((ret_value & 0xFF) << 8) | ((ret_value & 0xFF00) >> 8);
+
+ FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync +
+ FalseAlmCnt->Cnt_SB_Search_fail +
+ FalseAlmCnt->Cnt_Parity_Fail +
+ FalseAlmCnt->Cnt_Rate_Illegal +
+ FalseAlmCnt->Cnt_Crc8_fail +
+ FalseAlmCnt->Cnt_Mcs_fail +
+ FalseAlmCnt->Cnt_Cck_fail);
+
+ FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
+
+ if (pDM_Odm->SupportICType >= ODM_RTL8723A) {
+ /* reset false alarm counter registers */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
+ /* update ofdm counter */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0); /* update page C counter */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 0); /* update page D counter */
+
+ /* reset CCK CCA counter */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
+ ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
+ /* reset CCK FA counter */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
+ ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
+ }
+ } else { /* FOR ODM_IC_11AC_SERIES */
+ /* read OFDM FA counter */
+ FalseAlmCnt->Cnt_Ofdm_fail = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_11AC, bMaskLWord);
+ FalseAlmCnt->Cnt_Cck_fail = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_11AC, bMaskLWord);
+ FalseAlmCnt->Cnt_all = FalseAlmCnt->Cnt_Ofdm_fail + FalseAlmCnt->Cnt_Cck_fail;
+
+ /* reset OFDM FA coutner */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
+ ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
+ /* reset CCK FA counter */
+ ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0);
+ ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1);
+ }
+}
+
+/* 3============================================================ */
+/* 3 CCK Packet Detect Threshold */
+/* 3============================================================ */
+
+void odm_CCKPacketDetectionThresh(struct odm_dm_struct *pDM_Odm)
+{
+ u8 CurCCK_CCAThres;
+ struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+
+ if (!(pDM_Odm->SupportAbility & (ODM_BB_CCK_PD | ODM_BB_FA_CNT)))
+ return;
+ if (pDM_Odm->ExtLNA)
+ return;
+ if (pDM_Odm->bLinked) {
+ if (pDM_Odm->RSSI_Min > 25) {
+ CurCCK_CCAThres = 0xcd;
+ } else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) {
+ CurCCK_CCAThres = 0x83;
+ } else {
+ if (FalseAlmCnt->Cnt_Cck_fail > 1000)
+ CurCCK_CCAThres = 0x83;
+ else
+ CurCCK_CCAThres = 0x40;
+ }
+ } else {
+ if (FalseAlmCnt->Cnt_Cck_fail > 1000)
+ CurCCK_CCAThres = 0x83;
+ else
+ CurCCK_CCAThres = 0x40;
+ }
+ ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres);
+}
+
+void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres)
+{
+ struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+
+ if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) /* modify by Guo.Mingzhi 2012-01-03 */
+ ODM_Write1Byte(pDM_Odm, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
+ pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
+ pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
+}
+
+/* 3============================================================ */
+/* 3 BB Power Save */
+/* 3============================================================ */
+void odm_DynamicBBPowerSavingInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable;
+
+ pDM_PSTable->pre_cca_state = CCA_MAX;
+ pDM_PSTable->cur_cca_state = CCA_MAX;
+ pDM_PSTable->pre_rf_state = RF_MAX;
+ pDM_PSTable->cur_rf_state = RF_MAX;
+ pDM_PSTable->rssi_val_min = 0;
+ pDM_PSTable->initialize = 0;
+}
+
+void odm_DynamicBBPowerSaving(struct odm_dm_struct *pDM_Odm)
+{
+ if ((pDM_Odm->SupportICType != ODM_RTL8192C) && (pDM_Odm->SupportICType != ODM_RTL8723A))
+ return;
+ if (!(pDM_Odm->SupportAbility & ODM_BB_PWR_SAVE))
+ return;
+ if (!(pDM_Odm->SupportPlatform & (ODM_MP | ODM_CE)))
+ return;
+
+ /* 1 2.Power Saving for 92C */
+ if ((pDM_Odm->SupportICType == ODM_RTL8192C) && (pDM_Odm->RFType == ODM_2T2R)) {
+ odm_1R_CCA(pDM_Odm);
+ } else {
+ /* 20100628 Joseph: Turn off BB power save for 88CE because it makesthroughput unstable. */
+ /* 20100831 Joseph: Turn ON BB power save again after modifying AGC delay from 900ns ot 600ns. */
+ /* 1 3.Power Saving for 88C */
+ ODM_RF_Saving(pDM_Odm, false);
+ }
+}
+
+void odm_1R_CCA(struct odm_dm_struct *pDM_Odm)
+{
+ struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable;
+
+ if (pDM_Odm->RSSI_Min != 0xFF) {
+ if (pDM_PSTable->pre_cca_state == CCA_2R) {
+ if (pDM_Odm->RSSI_Min >= 35)
+ pDM_PSTable->cur_cca_state = CCA_1R;
+ else
+ pDM_PSTable->cur_cca_state = CCA_2R;
+ } else {
+ if (pDM_Odm->RSSI_Min <= 30)
+ pDM_PSTable->cur_cca_state = CCA_2R;
+ else
+ pDM_PSTable->cur_cca_state = CCA_1R;
+ }
+ } else {
+ pDM_PSTable->cur_cca_state = CCA_MAX;
+ }
+
+ if (pDM_PSTable->pre_cca_state != pDM_PSTable->cur_cca_state) {
+ if (pDM_PSTable->cur_cca_state == CCA_1R) {
+ if (pDM_Odm->RFType == ODM_2T2R)
+ ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x13);
+ else
+ ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x23);
+ } else {
+ ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x33);
+ }
+ pDM_PSTable->pre_cca_state = pDM_PSTable->cur_cca_state;
+ }
+}
+
+void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal)
+{
+ struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable;
+ u8 Rssi_Up_bound = 30;
+ u8 Rssi_Low_bound = 25;
+
+ if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */
+ Rssi_Up_bound = 50;
+ Rssi_Low_bound = 45;
+ }
+ if (pDM_PSTable->initialize == 0) {
+ pDM_PSTable->reg_874 = (ODM_GetBBReg(pDM_Odm, 0x874, bMaskDWord) & 0x1CC000) >> 14;
+ pDM_PSTable->reg_c70 = (ODM_GetBBReg(pDM_Odm, 0xc70, bMaskDWord) & BIT(3)) >> 3;
+ pDM_PSTable->reg_85c = (ODM_GetBBReg(pDM_Odm, 0x85c, bMaskDWord) & 0xFF000000) >> 24;
+ pDM_PSTable->reg_a74 = (ODM_GetBBReg(pDM_Odm, 0xa74, bMaskDWord) & 0xF000) >> 12;
+ pDM_PSTable->initialize = 1;
+ }
+
+ if (!bForceInNormal) {
+ if (pDM_Odm->RSSI_Min != 0xFF) {
+ if (pDM_PSTable->pre_rf_state == RF_Normal) {
+ if (pDM_Odm->RSSI_Min >= Rssi_Up_bound)
+ pDM_PSTable->cur_rf_state = RF_Save;
+ else
+ pDM_PSTable->cur_rf_state = RF_Normal;
+ } else {
+ if (pDM_Odm->RSSI_Min <= Rssi_Low_bound)
+ pDM_PSTable->cur_rf_state = RF_Normal;
+ else
+ pDM_PSTable->cur_rf_state = RF_Save;
+ }
+ } else {
+ pDM_PSTable->cur_rf_state = RF_MAX;
+ }
+ } else {
+ pDM_PSTable->cur_rf_state = RF_Normal;
+ }
+
+ if (pDM_PSTable->pre_rf_state != pDM_PSTable->cur_rf_state) {
+ if (pDM_PSTable->cur_rf_state == RF_Save) {
+ /* <tynli_note> 8723 RSSI report will be wrong. Set 0x874[5]=1 when enter BB power saving mode. */
+ /* Suggested by SD3 Yu-Nan. 2011.01.20. */
+ if (pDM_Odm->SupportICType == ODM_RTL8723A)
+ ODM_SetBBReg(pDM_Odm, 0x874, BIT(5), 0x1); /* Reg874[5]=1b'1 */
+ ODM_SetBBReg(pDM_Odm, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]=3'b010 */
+ ODM_SetBBReg(pDM_Odm, 0xc70, BIT(3), 0); /* RegC70[3]=1'b0 */
+ ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]=0x63 */
+ ODM_SetBBReg(pDM_Odm, 0x874, 0xC000, 0x2); /* Reg874[15:14]=2'b10 */
+ ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, 0x3); /* RegA75[7:4]=0x3 */
+ ODM_SetBBReg(pDM_Odm, 0x818, BIT(28), 0x0); /* Reg818[28]=1'b0 */
+ ODM_SetBBReg(pDM_Odm, 0x818, BIT(28), 0x1); /* Reg818[28]=1'b1 */
+ } else {
+ ODM_SetBBReg(pDM_Odm, 0x874, 0x1CC000, pDM_PSTable->reg_874);
+ ODM_SetBBReg(pDM_Odm, 0xc70, BIT(3), pDM_PSTable->reg_c70);
+ ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, pDM_PSTable->reg_85c);
+ ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, pDM_PSTable->reg_a74);
+ ODM_SetBBReg(pDM_Odm, 0x818, BIT(28), 0x0);
+
+ if (pDM_Odm->SupportICType == ODM_RTL8723A)
+ ODM_SetBBReg(pDM_Odm, 0x874, BIT(5), 0x0); /* Reg874[5]=1b'0 */
+ }
+ pDM_PSTable->pre_rf_state = pDM_PSTable->cur_rf_state;
+ }
+}
+
+/* 3============================================================ */
+/* 3 RATR MASK */
+/* 3============================================================ */
+/* 3============================================================ */
+/* 3 Rate Adaptive */
+/* 3============================================================ */
+
+void odm_RateAdaptiveMaskInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive;
+
+ pOdmRA->Type = DM_Type_ByDriver;
+ if (pOdmRA->Type == DM_Type_ByDriver)
+ pDM_Odm->bUseRAMask = true;
+ else
+ pDM_Odm->bUseRAMask = false;
+
+ pOdmRA->RATRState = DM_RATR_STA_INIT;
+ pOdmRA->HighRSSIThresh = 50;
+ pOdmRA->LowRSSIThresh = 20;
+}
+
+u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, u32 ra_mask, u8 rssi_level)
+{
+ struct sta_info *pEntry;
+ u32 rate_bitmap = 0x0fffffff;
+ u8 WirelessMode;
+
+ pEntry = pDM_Odm->pODM_StaInfo[macid];
+ if (!IS_STA_VALID(pEntry))
+ return ra_mask;
+
+ WirelessMode = pEntry->wireless_mode;
+
+ switch (WirelessMode) {
+ case ODM_WM_B:
+ if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */
+ rate_bitmap = 0x0000000d;
+ else
+ rate_bitmap = 0x0000000f;
+ break;
+ case (ODM_WM_B | ODM_WM_G):
+ if (rssi_level == DM_RATR_STA_HIGH)
+ rate_bitmap = 0x00000f00;
+ else if (rssi_level == DM_RATR_STA_MIDDLE)
+ rate_bitmap = 0x00000ff0;
+ else
+ rate_bitmap = 0x00000ff5;
+ break;
+ case (ODM_WM_B | ODM_WM_G | ODM_WM_N24G):
+ if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) {
+ if (rssi_level == DM_RATR_STA_HIGH) {
+ rate_bitmap = 0x000f0000;
+ } else if (rssi_level == DM_RATR_STA_MIDDLE) {
+ rate_bitmap = 0x000ff000;
+ } else {
+ if (*pDM_Odm->pBandWidth == ODM_BW40M)
+ rate_bitmap = 0x000ff015;
+ else
+ rate_bitmap = 0x000ff005;
+ }
+ } else {
+ if (rssi_level == DM_RATR_STA_HIGH) {
+ rate_bitmap = 0x0f8f0000;
+ } else if (rssi_level == DM_RATR_STA_MIDDLE) {
+ rate_bitmap = 0x0f8ff000;
+ } else {
+ if (*pDM_Odm->pBandWidth == ODM_BW40M)
+ rate_bitmap = 0x0f8ff015;
+ else
+ rate_bitmap = 0x0f8ff005;
+ }
+ }
+ break;
+ default:
+ /* case WIRELESS_11_24N: */
+ if (pDM_Odm->RFType == RF_1T2R)
+ rate_bitmap = 0x000fffff;
+ else
+ rate_bitmap = 0x0fffffff;
+ break;
+ }
+
+ return rate_bitmap;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: odm_RefreshRateAdaptiveMask()
+ *
+ * Overview: Update rate table mask according to rssi
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 05/27/2009 hpfan Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+void odm_RefreshRateAdaptiveMask(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK))
+ return;
+ /* */
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ /* */
+ switch (pDM_Odm->SupportPlatform) {
+ case ODM_MP:
+ odm_RefreshRateAdaptiveMaskMP(pDM_Odm);
+ break;
+ case ODM_CE:
+ odm_RefreshRateAdaptiveMaskCE(pDM_Odm);
+ break;
+ case ODM_AP:
+ case ODM_ADSL:
+ odm_RefreshRateAdaptiveMaskAPADSL(pDM_Odm);
+ break;
+ }
+}
+
+void odm_RefreshRateAdaptiveMaskMP(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+void odm_RefreshRateAdaptiveMaskCE(struct odm_dm_struct *pDM_Odm)
+{
+ u8 i;
+ struct adapter *pAdapter = pDM_Odm->Adapter;
+
+ if (pAdapter->bDriverStopped)
+ return;
+
+ if (!pDM_Odm->bUseRAMask)
+ return;
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(pstat)) {
+ if (ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level))
+ rtw_hal_update_ra_mask(pAdapter, i, pstat->rssi_level);
+ }
+ }
+}
+
+void odm_RefreshRateAdaptiveMaskAPADSL(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+/* Return Value: bool */
+/* - true: RATRState is changed. */
+bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate, u8 *pRATRState)
+{
+ struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive;
+ const u8 GoUpGap = 5;
+ u8 HighRSSIThreshForRA = pRA->HighRSSIThresh;
+ u8 LowRSSIThreshForRA = pRA->LowRSSIThresh;
+ u8 RATRState;
+
+ /* Threshold Adjustment: */
+ /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */
+ /* Here GoUpGap is added to solve the boundary's level alternation issue. */
+ switch (*pRATRState) {
+ case DM_RATR_STA_INIT:
+ case DM_RATR_STA_HIGH:
+ break;
+ case DM_RATR_STA_MIDDLE:
+ HighRSSIThreshForRA += GoUpGap;
+ break;
+ case DM_RATR_STA_LOW:
+ HighRSSIThreshForRA += GoUpGap;
+ LowRSSIThreshForRA += GoUpGap;
+ break;
+ default:
+ break;
+ }
+
+ /* Decide RATRState by RSSI. */
+ if (RSSI > HighRSSIThreshForRA)
+ RATRState = DM_RATR_STA_HIGH;
+ else if (RSSI > LowRSSIThreshForRA)
+ RATRState = DM_RATR_STA_MIDDLE;
+ else
+ RATRState = DM_RATR_STA_LOW;
+
+ if (*pRATRState != RATRState || bForceUpdate) {
+ *pRATRState = RATRState;
+ return true;
+ }
+ return false;
+}
+
+/* 3============================================================ */
+/* 3 Dynamic Tx Power */
+/* 3============================================================ */
+
+void odm_DynamicTxPowerInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ pdmpriv->bDynamicTxPowerEnable = false;
+ pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal;
+ pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
+}
+
+void odm_DynamicTxPower(struct odm_dm_struct *pDM_Odm)
+{
+ /* For AP/ADSL use struct rtl8192cd_priv * */
+ /* For CE/NIC use struct adapter * */
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_DYNAMIC_TXPWR))
+ return;
+
+ /* 2012/01/12 MH According to Luke's suggestion, only high power will support the feature. */
+ if (!pDM_Odm->ExtPA)
+ return;
+
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ switch (pDM_Odm->SupportPlatform) {
+ case ODM_MP:
+ case ODM_CE:
+ odm_DynamicTxPowerNIC(pDM_Odm);
+ break;
+ case ODM_AP:
+ odm_DynamicTxPowerAP(pDM_Odm);
+ break;
+ case ODM_ADSL:
+ break;
+ }
+}
+
+void odm_DynamicTxPowerNIC(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_DYNAMIC_TXPWR))
+ return;
+
+ if (pDM_Odm->SupportICType == ODM_RTL8188E) {
+ /* ??? */
+ /* This part need to be redefined. */
+ }
+}
+
+void odm_DynamicTxPowerAP(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+/* 3============================================================ */
+/* 3 RSSI Monitor */
+/* 3============================================================ */
+
+void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
+ return;
+
+ /* */
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ /* */
+ switch (pDM_Odm->SupportPlatform) {
+ case ODM_MP:
+ odm_RSSIMonitorCheckMP(pDM_Odm);
+ break;
+ case ODM_CE:
+ odm_RSSIMonitorCheckCE(pDM_Odm);
+ break;
+ case ODM_AP:
+ odm_RSSIMonitorCheckAP(pDM_Odm);
+ break;
+ case ODM_ADSL:
+ /* odm_DIGAP(pDM_Odm); */
+ break;
+ }
+
+} /* odm_RSSIMonitorCheck */
+
+void odm_RSSIMonitorCheckMP(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+static void FindMinimumRSSI(struct adapter *pAdapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv;
+
+ /* 1 1.Determine the minimum RSSI */
+ if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
+ pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0)
+ pdmpriv->MinUndecoratedPWDBForDM = 0;
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) /* Default port */
+ pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
+ else /* associated entry pwdb */
+ pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
+}
+
+void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ int i;
+ int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff;
+ u8 sta_cnt = 0;
+ u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */
+ struct sta_info *psta;
+ u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ if (!check_fwstate(&Adapter->mlmepriv, _FW_LINKED))
+ return;
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ psta = pDM_Odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(psta) &&
+ (psta->state & WIFI_ASOC_STATE) &&
+ memcmp(psta->hwaddr, bcast_addr, ETH_ALEN) &&
+ memcmp(psta->hwaddr, myid(&Adapter->eeprompriv), ETH_ALEN)) {
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
+ tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB)
+ tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1))
+ PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB << 16));
+ }
+ }
+
+ for (i = 0; i < sta_cnt; i++) {
+ if (PWDB_rssi[i] != (0)) {
+ if (pHalData->fw_ractrl) {
+ /* Report every sta's RSSI to FW */
+ } else {
+ ODM_RA_SetRSSI_8188E(
+ &pHalData->odmpriv, (PWDB_rssi[i] & 0xFF), (u8)((PWDB_rssi[i] >> 16) & 0xFF));
+ }
+ }
+ }
+
+ if (tmpEntryMaxPWDB != 0) /* If associated entry is found */
+ pdmpriv->EntryMaxUndecoratedSmoothedPWDB = tmpEntryMaxPWDB;
+ else
+ pdmpriv->EntryMaxUndecoratedSmoothedPWDB = 0;
+
+ if (tmpEntryMinPWDB != 0xff) /* If associated entry is found */
+ pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB;
+ else
+ pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0;
+
+ FindMinimumRSSI(Adapter);
+ ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM);
+}
+
+void odm_RSSIMonitorCheckAP(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+void ODM_InitAllTimers(struct odm_dm_struct *pDM_Odm)
+{
+ timer_setup(&pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer, odm_SwAntDivChkAntSwitchCallback, 0);
+}
+
+void ODM_CancelAllTimers(struct odm_dm_struct *pDM_Odm)
+{
+ ODM_CancelTimer(pDM_Odm, &pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer);
+}
+
+void ODM_ReleaseAllTimers(struct odm_dm_struct *pDM_Odm)
+{
+ ODM_ReleaseTimer(pDM_Odm, &pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer);
+
+ ODM_ReleaseTimer(pDM_Odm, &pDM_Odm->FastAntTrainingTimer);
+}
+
+/* 3============================================================ */
+/* 3 Tx Power Tracking */
+/* 3============================================================ */
+
+void odm_TXPowerTrackingInit(struct odm_dm_struct *pDM_Odm)
+{
+ odm_TXPowerTrackingThermalMeterInit(pDM_Odm);
+}
+
+void odm_TXPowerTrackingThermalMeterInit(struct odm_dm_struct *pDM_Odm)
+{
+ pDM_Odm->RFCalibrateInfo.bTXPowerTracking = true;
+ pDM_Odm->RFCalibrateInfo.TXPowercount = 0;
+ pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = false;
+ if (*pDM_Odm->mp_mode != 1)
+ pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
+ MSG_88E("pDM_Odm TxPowerTrackControl = %d\n", pDM_Odm->RFCalibrateInfo.TxPowerTrackControl);
+
+ pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
+}
+
+void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm)
+{
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ switch (pDM_Odm->SupportPlatform) {
+ case ODM_MP:
+ odm_TXPowerTrackingCheckMP(pDM_Odm);
+ break;
+ case ODM_CE:
+ odm_TXPowerTrackingCheckCE(pDM_Odm);
+ break;
+ case ODM_AP:
+ odm_TXPowerTrackingCheckAP(pDM_Odm);
+ break;
+ case ODM_ADSL:
+ break;
+ }
+}
+
+void odm_TXPowerTrackingCheckCE(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+
+ if (!(pDM_Odm->SupportAbility & ODM_RF_TX_PWR_TRACK))
+ return;
+
+ if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) { /* at least delay 1 sec */
+ PHY_SetRFReg(Adapter, RF_PATH_A, RF_T_METER_88E, BIT(17) | BIT(16), 0x03);
+
+ pDM_Odm->RFCalibrateInfo.TM_Trigger = 1;
+ return;
+ } else {
+ odm_TXPowerTrackingCallback_ThermalMeter_8188E(Adapter);
+ pDM_Odm->RFCalibrateInfo.TM_Trigger = 0;
+ }
+}
+
+void odm_TXPowerTrackingCheckMP(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+void odm_TXPowerTrackingCheckAP(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+/* antenna mapping info */
+/* 1: right-side antenna */
+/* 2/0: left-side antenna */
+/* PDM_SWAT_Table->CCK_Ant1_Cnt /OFDM_Ant1_Cnt: for right-side antenna: Ant:1 RxDefaultAnt1 */
+/* PDM_SWAT_Table->CCK_Ant2_Cnt /OFDM_Ant2_Cnt: for left-side antenna: Ant:0 RxDefaultAnt2 */
+/* We select left antenna as default antenna in initial process, modify it as needed */
+/* */
+
+/* 3============================================================ */
+/* 3 SW Antenna Diversity */
+/* 3============================================================ */
+void odm_SwAntDivInit(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+void ODM_SwAntDivChkPerPktRssi(struct odm_dm_struct *pDM_Odm, u8 StationID, struct odm_phy_status_info *pPhyInfo)
+{
+}
+
+void odm_SwAntDivChkAntSwitch(struct odm_dm_struct *pDM_Odm, u8 Step)
+{
+}
+
+void ODM_SwAntDivRestAfterLink(struct odm_dm_struct *pDM_Odm)
+{
+}
+
+void odm_SwAntDivChkAntSwitchCallback(struct timer_list *t)
+{
+}
+
+/* 3============================================================ */
+/* 3 SW Antenna Diversity */
+/* 3============================================================ */
+
+void odm_InitHybridAntDiv(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV))
+ return;
+
+ if (pDM_Odm->SupportICType & (ODM_RTL8192C | ODM_RTL8192D))
+ ;
+ else if (pDM_Odm->SupportICType == ODM_RTL8188E)
+ ODM_AntennaDiversityInit_88E(pDM_Odm);
+}
+
+void ODM_AntselStatistics_88C(struct odm_dm_struct *pDM_Odm, u8 MacId, u32 PWDBAll, bool isCCKrate)
+{
+ struct sw_ant_switch *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+
+ if (pDM_SWAT_Table->antsel == 1) {
+ if (isCCKrate) {
+ pDM_SWAT_Table->CCK_Ant1_Cnt[MacId]++;
+ } else {
+ pDM_SWAT_Table->OFDM_Ant1_Cnt[MacId]++;
+ pDM_SWAT_Table->RSSI_Ant1_Sum[MacId] += PWDBAll;
+ }
+ } else {
+ if (isCCKrate) {
+ pDM_SWAT_Table->CCK_Ant2_Cnt[MacId]++;
+ } else {
+ pDM_SWAT_Table->OFDM_Ant2_Cnt[MacId]++;
+ pDM_SWAT_Table->RSSI_Ant2_Sum[MacId] += PWDBAll;
+ }
+ }
+}
+
+void odm_HwAntDiv(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV))
+ return;
+
+ if (pDM_Odm->SupportICType == ODM_RTL8188E)
+ ODM_AntennaDiversity_88E(pDM_Odm);
+}
+
+/* EDCA Turbo */
+void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
+ pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
+ Adapter->recvpriv.bIsAnyNonBEPkts = false;
+
+} /* ODM_InitEdcaTurbo */
+
+void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm)
+{
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO))
+ return;
+
+ switch (pDM_Odm->SupportPlatform) {
+ case ODM_MP:
+ break;
+ case ODM_CE:
+ odm_EdcaTurboCheckCE(pDM_Odm);
+ break;
+ case ODM_AP:
+ case ODM_ADSL:
+ break;
+ }
+} /* odm_CheckEdcaTurbo */
+
+void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ u32 trafficIndex;
+ u32 edca_param;
+ u64 cur_tx_bytes = 0;
+ u64 cur_rx_bytes = 0;
+ u8 bbtchange = false;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct xmit_priv *pxmitpriv = &Adapter->xmitpriv;
+ struct recv_priv *precvpriv = &Adapter->recvpriv;
+ struct registry_priv *pregpriv = &Adapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pregpriv->wifi_spec == 1)
+ goto dm_CheckEdcaTurbo_EXIT;
+
+ if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX)
+ goto dm_CheckEdcaTurbo_EXIT;
+
+ /* Check if the status needs to be changed. */
+ if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) {
+ cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes;
+ cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes;
+
+ /* traffic, TX or RX */
+ if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) ||
+ (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) {
+ if (cur_tx_bytes > (cur_rx_bytes << 2)) {
+ /* Uplink TP is present. */
+ trafficIndex = UP_LINK;
+ } else {
+ /* Balance TP is present. */
+ trafficIndex = DOWN_LINK;
+ }
+ } else {
+ if (cur_rx_bytes > (cur_tx_bytes << 2)) {
+ /* Downlink TP is present. */
+ trafficIndex = DOWN_LINK;
+ } else {
+ /* Balance TP is present. */
+ trafficIndex = UP_LINK;
+ }
+ }
+
+ if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) || (!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) {
+ if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) && (pmlmeext->cur_wireless_mode & WIRELESS_11_24N))
+ edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex];
+ else
+ edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex];
+
+ rtw_write32(Adapter, REG_EDCA_BE_PARAM, edca_param);
+
+ pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex;
+ }
+
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true;
+ } else {
+ /* Turn Off EDCA turbo here. */
+ /* Restore original EDCA according to the declaration of AP. */
+ if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) {
+ rtw_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE);
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
+ }
+ }
+
+dm_CheckEdcaTurbo_EXIT:
+ /* Set variables for next time. */
+ precvpriv->bIsAnyNonBEPkts = false;
+ pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes;
+ precvpriv->last_rx_bytes = precvpriv->rx_bytes;
+}
+
+/* need to ODM CE Platform */
+/* move to here for ANT detection mechanism using */
+
+u32 GetPSDData(struct odm_dm_struct *pDM_Odm, unsigned int point, u8 initial_gain_psd)
+{
+ u32 psd_report;
+
+ /* Set DCO frequency index, offset=(40MHz/SamplePts)*point */
+ ODM_SetBBReg(pDM_Odm, 0x808, 0x3FF, point);
+
+ /* Start PSD calculation, Reg808[22]=0->1 */
+ ODM_SetBBReg(pDM_Odm, 0x808, BIT(22), 1);
+ /* Need to wait for HW PSD report */
+ ODM_StallExecution(30);
+ ODM_SetBBReg(pDM_Odm, 0x808, BIT(22), 0);
+ /* Read PSD report, Reg8B4[15:0] */
+ psd_report = ODM_GetBBReg(pDM_Odm, 0x8B4, bMaskDWord) & 0x0000FFFF;
+
+ psd_report = (u32)(ConvertTo_dB(psd_report)) + (u32)(initial_gain_psd - 0x1c);
+
+ return psd_report;
+}
+
+u32 ConvertTo_dB(u32 Value)
+{
+ u8 i;
+ u8 j;
+ u32 dB;
+
+ Value = Value & 0xFFFF;
+ for (i = 0; i < 8; i++) {
+ if (Value <= dB_Invert_Table[i][11])
+ break;
+ }
+
+ if (i >= 8)
+ return 96; /* maximum 96 dB */
+
+ for (j = 0; j < 12; j++) {
+ if (Value <= dB_Invert_Table[i][j])
+ break;
+ }
+
+ dB = i * 12 + j + 1;
+
+ return dB;
+}
+
+/* 2011/09/22 MH Add for 92D global spin lock utilization. */
+void odm_GlobalAdapterCheck(void)
+{
+} /* odm_GlobalAdapterCheck */
+
+/* Description: */
+/* Set Single/Dual Antenna default setting for products that do not do detection in advance. */
+/* Added by Joseph, 2012.03.22 */
+void ODM_SingleDualAntennaDefaultSetting(struct odm_dm_struct *pDM_Odm)
+{
+ struct sw_ant_switch *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+
+ pDM_SWAT_Table->ANTA_ON = true;
+ pDM_SWAT_Table->ANTB_ON = true;
+}
+
+/* 2 8723A ANT DETECT */
+
+static void odm_PHY_SaveAFERegisters(struct odm_dm_struct *pDM_Odm, u32 *AFEReg, u32 *AFEBackup, u32 RegisterNum)
+{
+ u32 i;
+
+ /* RTPRINT(FINIT, INIT_IQK, ("Save ADDA parameters.\n")); */
+ for (i = 0; i < RegisterNum; i++)
+ AFEBackup[i] = ODM_GetBBReg(pDM_Odm, AFEReg[i], bMaskDWord);
+}
+
+static void odm_PHY_ReloadAFERegisters(struct odm_dm_struct *pDM_Odm, u32 *AFEReg, u32 *AFEBackup, u32 RegiesterNum)
+{
+ u32 i;
+
+ for (i = 0; i < RegiesterNum; i++)
+ ODM_SetBBReg(pDM_Odm, AFEReg[i], bMaskDWord, AFEBackup[i]);
+}
+
+/* 2 8723A ANT DETECT */
+/* Description: */
+/* Implement IQK single tone for RF DPK loopback and BB PSD scanning. */
+/* This function is cooperated with BB team Neil. */
+bool ODM_SingleDualAntennaDetection(struct odm_dm_struct *pDM_Odm, u8 mode)
+{
+ struct sw_ant_switch *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+ u32 CurrentChannel, RfLoopReg;
+ u8 n;
+ u32 Reg88c, Regc08, Reg874, Regc50;
+ u8 initial_gain = 0x5a;
+ u32 PSD_report_tmp;
+ u32 AntA_report = 0x0, AntB_report = 0x0, AntO_report = 0x0;
+ bool bResult = true;
+ u32 AFE_Backup[16];
+ u32 AFE_REG_8723A[16] = {
+ rRx_Wait_CCA, rTx_CCK_RFON,
+ rTx_CCK_BBON, rTx_OFDM_RFON,
+ rTx_OFDM_BBON, rTx_To_Rx,
+ rTx_To_Tx, rRx_CCK,
+ rRx_OFDM, rRx_Wait_RIFS,
+ rRx_TO_Rx, rStandby,
+ rSleep, rPMPD_ANAEN,
+ rFPGA0_XCD_SwitchControl, rBlue_Tooth};
+
+ if (!(pDM_Odm->SupportICType & (ODM_RTL8723A | ODM_RTL8192C)))
+ return bResult;
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV))
+ return bResult;
+
+ if (pDM_Odm->SupportICType == ODM_RTL8192C) {
+ /* Which path in ADC/DAC is turnned on for PSD: both I/Q */
+ ODM_SetBBReg(pDM_Odm, 0x808, BIT(10) | BIT(11), 0x3);
+ /* Ageraged number: 8 */
+ ODM_SetBBReg(pDM_Odm, 0x808, BIT(12) | BIT(13), 0x1);
+ /* pts = 128; */
+ ODM_SetBBReg(pDM_Odm, 0x808, BIT(14) | BIT(15), 0x0);
+ }
+
+ /* 1 Backup Current RF/BB Settings */
+
+ CurrentChannel = ODM_GetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask);
+ RfLoopReg = ODM_GetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask);
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, ODM_DPDT, Antenna_A); /* change to Antenna A */
+ /* Step 1: USE IQK to transmitter single tone */
+
+ ODM_StallExecution(10);
+
+ /* Store A Path Register 88c, c08, 874, c50 */
+ Reg88c = ODM_GetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord);
+ Regc08 = ODM_GetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord);
+ Reg874 = ODM_GetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord);
+ Regc50 = ODM_GetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord);
+
+ /* Store AFE Registers */
+ odm_PHY_SaveAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16);
+
+ /* Set PSD 128 pts */
+ ODM_SetBBReg(pDM_Odm, rFPGA0_PSDFunction, BIT(14) | BIT(15), 0x0); /* 128 pts */
+
+ /* To SET CH1 to do */
+ ODM_SetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask, 0x01); /* Channel 1 */
+
+ /* AFE all on step */
+ ODM_SetBBReg(pDM_Odm, rRx_Wait_CCA, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rTx_CCK_RFON, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rTx_CCK_BBON, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rTx_OFDM_RFON, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rTx_OFDM_BBON, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rTx_To_Rx, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rTx_To_Tx, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rRx_CCK, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rRx_OFDM, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rRx_Wait_RIFS, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rRx_TO_Rx, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rStandby, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rSleep, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rPMPD_ANAEN, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_SwitchControl, bMaskDWord, 0x6FDB25A4);
+ ODM_SetBBReg(pDM_Odm, rBlue_Tooth, bMaskDWord, 0x6FDB25A4);
+
+ /* 3 wire Disable */
+ ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, 0xCCF000C0);
+
+ /* BB IQK Setting */
+ ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, 0x000800E4);
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22208000);
+
+ /* IQK setting tone@ 4.34Mhz */
+ ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x10008C1C);
+ ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
+
+ /* Page B init */
+ ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x00080000);
+ ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x0f600000);
+ ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
+ ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
+ ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82150008);
+ ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28150008);
+ ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x001028d0);
+
+ /* RF loop Setting */
+ ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x0, 0xFFFFF, 0x50008);
+
+ /* IQK Single tone start */
+ ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskDWord, 0x80800000);
+ ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+ ODM_StallExecution(1000);
+ PSD_report_tmp = 0x0;
+
+ for (n = 0; n < 2; n++) {
+ PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
+ if (PSD_report_tmp > AntA_report)
+ AntA_report = PSD_report_tmp;
+ }
+
+ PSD_report_tmp = 0x0;
+
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_B); /* change to Antenna B */
+ ODM_StallExecution(10);
+
+ for (n = 0; n < 2; n++) {
+ PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
+ if (PSD_report_tmp > AntB_report)
+ AntB_report = PSD_report_tmp;
+ }
+
+ /* change to open case */
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, 0); /* change to Ant A and B all open case */
+ ODM_StallExecution(10);
+
+ for (n = 0; n < 2; n++) {
+ PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
+ if (PSD_report_tmp > AntO_report)
+ AntO_report = PSD_report_tmp;
+ }
+
+ /* Close IQK Single Tone function */
+ ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
+ PSD_report_tmp = 0x0;
+
+ /* 1 Return to antanna A */
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_A);
+ ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, Reg88c);
+ ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, Regc08);
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, Reg874);
+ ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, 0x7F, 0x40);
+ ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord, Regc50);
+ ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, CurrentChannel);
+ ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask, RfLoopReg);
+
+ /* Reload AFE Registers */
+ odm_PHY_ReloadAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16);
+
+ if (pDM_Odm->SupportICType == ODM_RTL8723A) {
+ /* 2 Test Ant B based on Ant A is ON */
+ if (mode == ANTTESTB) {
+ if (AntA_report >= 100) {
+ if (AntB_report > (AntA_report + 1))
+ pDM_SWAT_Table->ANTB_ON = false;
+ else
+ pDM_SWAT_Table->ANTB_ON = true;
+ } else {
+ pDM_SWAT_Table->ANTB_ON = false; /* Set Antenna B off as default */
+ bResult = false;
+ }
+ } else if (mode == ANTTESTALL) {
+ /* 2 Test Ant A and B based on DPDT Open */
+ if ((AntO_report >= 100) & (AntO_report < 118)) {
+ if (AntA_report > (AntO_report + 1))
+ pDM_SWAT_Table->ANTA_ON = false;
+ else
+ pDM_SWAT_Table->ANTA_ON = true;
+
+ if (AntB_report > (AntO_report + 2))
+ pDM_SWAT_Table->ANTB_ON = false;
+ else
+ pDM_SWAT_Table->ANTB_ON = true;
+ }
+ }
+ } else if (pDM_Odm->SupportICType == ODM_RTL8192C) {
+ if (AntA_report >= 100) {
+ if (AntB_report > (AntA_report + 2)) {
+ pDM_SWAT_Table->ANTA_ON = false;
+ pDM_SWAT_Table->ANTB_ON = true;
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_B);
+ } else if (AntA_report > (AntB_report + 2)) {
+ pDM_SWAT_Table->ANTA_ON = true;
+ pDM_SWAT_Table->ANTB_ON = false;
+ ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_A);
+ } else {
+ pDM_SWAT_Table->ANTA_ON = true;
+ pDM_SWAT_Table->ANTB_ON = true;
+ }
+ } else {
+ pDM_SWAT_Table->ANTA_ON = true; /* Set Antenna A on as default */
+ pDM_SWAT_Table->ANTB_ON = false; /* Set Antenna B off as default */
+ bResult = false;
+ }
+ }
+ return bResult;
+}
+
+/* Justin: According to the current RRSI to adjust Response Frame TX power, 2012/11/05 */
+void odm_dtc(struct odm_dm_struct *pDM_Odm)
+{
+}
diff --git a/drivers/staging/r8188eu/hal/odm_HWConfig.c b/drivers/staging/r8188eu/hal/odm_HWConfig.c
new file mode 100644
index 000000000000..ada22a526fee
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/odm_HWConfig.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/odm_precomp.h"
+
+#define READ_AND_CONFIG READ_AND_CONFIG_MP
+
+#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig##txt##ic(dm_odm))
+#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(dm_odm))
+
+static u8 odm_QueryRxPwrPercentage(s8 AntPower)
+{
+ if ((AntPower <= -100) || (AntPower >= 20))
+ return 0;
+ else if (AntPower >= 0)
+ return 100;
+ else
+ return 100 + AntPower;
+}
+
+/* 2012/01/12 MH MOve some signal strength smooth method to MP HAL layer. */
+/* IF other SW team do not support the feature, remove this section.?? */
+static s32 odm_sig_patch_lenove(struct odm_dm_struct *dm_odm, s32 CurrSig)
+{
+ return 0;
+}
+
+static s32 odm_sig_patch_netcore(struct odm_dm_struct *dm_odm, s32 CurrSig)
+{
+ return 0;
+}
+
+static s32 odm_SignalScaleMapping_92CSeries(struct odm_dm_struct *dm_odm, s32 CurrSig)
+{
+ s32 RetSig = 0;
+
+ if ((dm_odm->SupportInterface == ODM_ITRF_USB) ||
+ (dm_odm->SupportInterface == ODM_ITRF_SDIO)) {
+ if (CurrSig >= 51 && CurrSig <= 100)
+ RetSig = 100;
+ else if (CurrSig >= 41 && CurrSig <= 50)
+ RetSig = 80 + ((CurrSig - 40) * 2);
+ else if (CurrSig >= 31 && CurrSig <= 40)
+ RetSig = 66 + (CurrSig - 30);
+ else if (CurrSig >= 21 && CurrSig <= 30)
+ RetSig = 54 + (CurrSig - 20);
+ else if (CurrSig >= 10 && CurrSig <= 20)
+ RetSig = 42 + (((CurrSig - 10) * 2) / 3);
+ else if (CurrSig >= 5 && CurrSig <= 9)
+ RetSig = 22 + (((CurrSig - 5) * 3) / 2);
+ else if (CurrSig >= 1 && CurrSig <= 4)
+ RetSig = 6 + (((CurrSig - 1) * 3) / 2);
+ else
+ RetSig = CurrSig;
+ }
+ return RetSig;
+}
+
+static s32 odm_SignalScaleMapping(struct odm_dm_struct *dm_odm, s32 CurrSig)
+{
+ if ((dm_odm->SupportPlatform == ODM_MP) &&
+ (dm_odm->SupportInterface != ODM_ITRF_PCIE) && /* USB & SDIO */
+ (dm_odm->PatchID == 10))
+ return odm_sig_patch_netcore(dm_odm, CurrSig);
+ else if ((dm_odm->SupportPlatform == ODM_MP) &&
+ (dm_odm->SupportInterface == ODM_ITRF_PCIE) &&
+ (dm_odm->PatchID == 19))
+ return odm_sig_patch_lenove(dm_odm, CurrSig);
+ else
+ return odm_SignalScaleMapping_92CSeries(dm_odm, CurrSig);
+}
+
+/* pMgntInfo->CustomerID == RT_CID_819x_Lenovo */
+static u8 odm_SQ_process_patch_RT_CID_819x_Lenovo(struct odm_dm_struct *dm_odm,
+ u8 isCCKrate, u8 PWDB_ALL, u8 path, u8 RSSI)
+{
+ return 0;
+}
+
+static u8 odm_evm_db_to_percentage(s8 value)
+{
+ /* -33dB~0dB to 0%~99% */
+ s8 ret_val = clamp(-value, 0, 33) * 3;
+
+ if (ret_val == 99)
+ ret_val = 100;
+
+ return ret_val;
+}
+
+static void odm_RxPhyStatus92CSeries_Parsing(struct odm_dm_struct *dm_odm,
+ struct odm_phy_status_info *pPhyInfo,
+ u8 *pPhyStatus,
+ struct odm_per_pkt_info *pPktinfo,
+ struct adapter *adapt)
+{
+ struct sw_ant_switch *pDM_SWAT_Table = &dm_odm->DM_SWAT_Table;
+ u8 i, Max_spatial_stream;
+ s8 rx_pwr[4], rx_pwr_all = 0;
+ u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT;
+ u8 RSSI, total_rssi = 0;
+ u8 isCCKrate = 0;
+ u8 rf_rx_num = 0;
+ u8 cck_highpwr = 0;
+ u8 LNA_idx, VGA_idx;
+
+ struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus;
+
+ isCCKrate = ((pPktinfo->Rate >= DESC92C_RATE1M) && (pPktinfo->Rate <= DESC92C_RATE11M)) ? true : false;
+
+ pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1;
+ pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
+
+ if (isCCKrate) {
+ u8 report;
+ u8 cck_agc_rpt;
+
+ dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++;
+ /* (1)Hardware does not provide RSSI for CCK */
+ /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
+
+ cck_highpwr = dm_odm->bCckHighPower;
+
+ cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a;
+
+ /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */
+ /* The RSSI formula should be modified according to the gain table */
+ /* In 88E, cck_highpwr is always set to 1 */
+ if (dm_odm->SupportICType & (ODM_RTL8188E | ODM_RTL8812)) {
+ LNA_idx = ((cck_agc_rpt & 0xE0) >> 5);
+ VGA_idx = (cck_agc_rpt & 0x1F);
+ switch (LNA_idx) {
+ case 7:
+ if (VGA_idx <= 27)
+ rx_pwr_all = -100 + 2 * (27 - VGA_idx); /* VGA_idx = 27~2 */
+ else
+ rx_pwr_all = -100;
+ break;
+ case 6:
+ rx_pwr_all = -48 + 2 * (2 - VGA_idx); /* VGA_idx = 2~0 */
+ break;
+ case 5:
+ rx_pwr_all = -42 + 2 * (7 - VGA_idx); /* VGA_idx = 7~5 */
+ break;
+ case 4:
+ rx_pwr_all = -36 + 2 * (7 - VGA_idx); /* VGA_idx = 7~4 */
+ break;
+ case 3:
+ rx_pwr_all = -24 + 2 * (7 - VGA_idx); /* VGA_idx = 7~0 */
+ break;
+ case 2:
+ if (cck_highpwr)
+ rx_pwr_all = -12 + 2 * (5 - VGA_idx); /* VGA_idx = 5~0 */
+ else
+ rx_pwr_all = -6 + 2 * (5 - VGA_idx);
+ break;
+ case 1:
+ rx_pwr_all = 8 - 2 * VGA_idx;
+ break;
+ case 0:
+ rx_pwr_all = 14 - 2 * VGA_idx;
+ break;
+ default:
+ break;
+ }
+ rx_pwr_all += 6;
+ PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
+ if (!cck_highpwr) {
+ if (PWDB_ALL >= 80)
+ PWDB_ALL = ((PWDB_ALL - 80) << 1) + ((PWDB_ALL - 80) >> 1) + 80;
+ else if ((PWDB_ALL <= 78) && (PWDB_ALL >= 20))
+ PWDB_ALL += 3;
+ if (PWDB_ALL > 100)
+ PWDB_ALL = 100;
+ }
+ } else {
+ if (!cck_highpwr) {
+ report = (cck_agc_rpt & 0xc0) >> 6;
+ switch (report) {
+ /* 03312009 modified by cosa */
+ /* Modify the RF RNA gain value to -40, -20, -2, 14 by Jenyu's suggestion */
+ /* Note: different RF with the different RNA gain. */
+ case 0x3:
+ rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x2:
+ rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x1:
+ rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x0:
+ rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+ break;
+ }
+ } else {
+ report = (cck_agc_rpt & 0x60) >> 5;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x2:
+ rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x1:
+ rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ case 0x0:
+ rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
+ break;
+ }
+ }
+
+ PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
+
+ /* Modification for ext-LNA board */
+ if (dm_odm->BoardType == ODM_BOARD_HIGHPWR) {
+ if ((cck_agc_rpt >> 7) == 0) {
+ PWDB_ALL = (PWDB_ALL > 94) ? 100 : (PWDB_ALL + 6);
+ } else {
+ if (PWDB_ALL > 38)
+ PWDB_ALL -= 16;
+ else
+ PWDB_ALL = (PWDB_ALL <= 16) ? (PWDB_ALL >> 2) : (PWDB_ALL - 12);
+ }
+
+ /* CCK modification */
+ if (PWDB_ALL > 25 && PWDB_ALL <= 60)
+ PWDB_ALL += 6;
+ } else {/* Modification for int-LNA board */
+ if (PWDB_ALL > 99)
+ PWDB_ALL -= 8;
+ else if (PWDB_ALL > 50 && PWDB_ALL <= 68)
+ PWDB_ALL += 4;
+ }
+ }
+
+ pPhyInfo->RxPWDBAll = PWDB_ALL;
+ pPhyInfo->BTRxRSSIPercentage = PWDB_ALL;
+ pPhyInfo->RecvSignalPower = rx_pwr_all;
+ /* (3) Get Signal Quality (EVM) */
+ if (pPktinfo->bPacketMatchBSSID) {
+ u8 SQ, SQ_rpt;
+
+ if ((dm_odm->SupportPlatform == ODM_MP) && (dm_odm->PatchID == 19)) {
+ SQ = odm_SQ_process_patch_RT_CID_819x_Lenovo(dm_odm, isCCKrate, PWDB_ALL, 0, 0);
+ } else if (pPhyInfo->RxPWDBAll > 40 && !dm_odm->bInHctTest) {
+ SQ = 100;
+ } else {
+ SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all;
+
+ if (SQ_rpt > 64)
+ SQ = 0;
+ else if (SQ_rpt < 20)
+ SQ = 100;
+ else
+ SQ = ((64 - SQ_rpt) * 100) / 44;
+ }
+ pPhyInfo->SignalQuality = SQ;
+ pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ;
+ pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
+ }
+ } else { /* is OFDM rate */
+ dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
+
+ /* (1)Get RSSI for HT rate */
+
+ for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
+ /* 2008/01/30 MH we will judge RF RX path now. */
+ if (dm_odm->RFPathRxEnable & BIT(i))
+ rf_rx_num++;
+
+ rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F) * 2) - 110;
+ if (i == RF_PATH_A)
+ adapt->signal_strength = rx_pwr[i];
+
+ pPhyInfo->RxPwr[i] = rx_pwr[i];
+
+ /* Translate DBM to percentage. */
+ RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]);
+ total_rssi += RSSI;
+
+ /* Modification for ext-LNA board */
+ if (dm_odm->BoardType == ODM_BOARD_HIGHPWR) {
+ if ((pPhyStaRpt->path_agc[i].trsw) == 1)
+ RSSI = (RSSI > 94) ? 100 : (RSSI + 6);
+ else
+ RSSI = (RSSI <= 16) ? (RSSI >> 3) : (RSSI - 16);
+
+ if ((RSSI <= 34) && (RSSI >= 4))
+ RSSI -= 4;
+ }
+
+ pPhyInfo->RxMIMOSignalStrength[i] = (u8)RSSI;
+
+ /* Get Rx snr value in DB */
+ pPhyInfo->RxSNR[i] = (s32)(pPhyStaRpt->path_rxsnr[i] / 2);
+ dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i] / 2);
+
+ /* Record Signal Strength for next packet */
+ if (pPktinfo->bPacketMatchBSSID) {
+ if ((dm_odm->SupportPlatform == ODM_MP) && (dm_odm->PatchID == 19)) {
+ if (i == RF_PATH_A)
+ pPhyInfo->SignalQuality = odm_SQ_process_patch_RT_CID_819x_Lenovo(dm_odm, isCCKrate, PWDB_ALL, i, RSSI);
+ }
+ }
+ }
+ /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
+ rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f) - 110;
+
+ PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
+ PWDB_ALL_BT = PWDB_ALL;
+
+ pPhyInfo->RxPWDBAll = PWDB_ALL;
+ pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT;
+ pPhyInfo->RxPower = rx_pwr_all;
+ pPhyInfo->RecvSignalPower = rx_pwr_all;
+
+ if ((dm_odm->SupportPlatform == ODM_MP) && (dm_odm->PatchID == 19)) {
+ /* do nothing */
+ } else {
+ /* (3)EVM of HT rate */
+ if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15)
+ Max_spatial_stream = 2; /* both spatial stream make sense */
+ else
+ Max_spatial_stream = 1; /* only spatial stream 1 makes sense */
+
+ for (i = 0; i < Max_spatial_stream; i++) {
+ /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */
+ /* fill most significant bit to "zero" when doing shifting operation which may change a negative */
+ /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */
+ EVM = odm_evm_db_to_percentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */
+
+ if (pPktinfo->bPacketMatchBSSID) {
+ if (i == RF_PATH_A) /* Fill value in RFD, Get the first spatial stream only */
+ pPhyInfo->SignalQuality = (u8)(EVM & 0xff);
+ pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff);
+ }
+ }
+ }
+ }
+ /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */
+ /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */
+ if (isCCKrate) {
+ pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(dm_odm, PWDB_ALL));/* PWDB_ALL; */
+ } else {
+ if (rf_rx_num != 0)
+ pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(dm_odm, total_rssi /= rf_rx_num));
+ }
+
+ /* For 92C/92D HW (Hybrid) Antenna Diversity */
+ pDM_SWAT_Table->antsel = pPhyStaRpt->ant_sel;
+ /* For 88E HW Antenna Diversity */
+ dm_odm->DM_FatTable.antsel_rx_keep_0 = pPhyStaRpt->ant_sel;
+ dm_odm->DM_FatTable.antsel_rx_keep_1 = pPhyStaRpt->ant_sel_b;
+ dm_odm->DM_FatTable.antsel_rx_keep_2 = pPhyStaRpt->antsel_rx_keep_2;
+}
+
+void odm_Init_RSSIForDM(struct odm_dm_struct *dm_odm)
+{
+}
+
+static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
+ struct odm_phy_status_info *pPhyInfo,
+ struct odm_per_pkt_info *pPktinfo)
+{
+ s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK;
+ s32 UndecoratedSmoothedOFDM, RSSI_Ave;
+ u8 isCCKrate = 0;
+ u8 RSSI_max, RSSI_min, i;
+ u32 OFDM_pkt = 0;
+ u32 Weighting = 0;
+ struct sta_info *pEntry;
+
+ if (pPktinfo->StationID == 0xFF)
+ return;
+ pEntry = dm_odm->pODM_StaInfo[pPktinfo->StationID];
+ if (!IS_STA_VALID(pEntry))
+ return;
+ if ((!pPktinfo->bPacketMatchBSSID))
+ return;
+
+ isCCKrate = ((pPktinfo->Rate >= DESC92C_RATE1M) && (pPktinfo->Rate <= DESC92C_RATE11M)) ? true : false;
+
+ /* Smart Antenna Debug Message------------------ */
+ if (dm_odm->SupportICType == ODM_RTL8188E) {
+ u8 antsel_tr_mux;
+ struct fast_ant_train *pDM_FatTable = &dm_odm->DM_FatTable;
+
+ if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV) {
+ if (pDM_FatTable->FAT_State == FAT_TRAINING_STATE) {
+ if (pPktinfo->bPacketToSelf) {
+ antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2 << 2) |
+ (pDM_FatTable->antsel_rx_keep_1 << 1) |
+ pDM_FatTable->antsel_rx_keep_0;
+ pDM_FatTable->antSumRSSI[antsel_tr_mux] += pPhyInfo->RxPWDBAll;
+ pDM_FatTable->antRSSIcnt[antsel_tr_mux]++;
+ }
+ }
+ } else if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)) {
+ if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
+ antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2 << 2) |
+ (pDM_FatTable->antsel_rx_keep_1 << 1) | pDM_FatTable->antsel_rx_keep_0;
+ ODM_AntselStatistics_88E(dm_odm, antsel_tr_mux, pPktinfo->StationID, pPhyInfo->RxPWDBAll);
+ }
+ }
+ }
+ /* Smart Antenna Debug Message------------------ */
+
+ UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK;
+ UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM;
+ UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
+
+ if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
+ if (!isCCKrate) { /* ofdm rate */
+ if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) {
+ RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
+ } else {
+ if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) {
+ RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
+ RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
+ } else {
+ RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
+ RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
+ }
+ if ((RSSI_max - RSSI_min) < 3)
+ RSSI_Ave = RSSI_max;
+ else if ((RSSI_max - RSSI_min) < 6)
+ RSSI_Ave = RSSI_max - 1;
+ else if ((RSSI_max - RSSI_min) < 10)
+ RSSI_Ave = RSSI_max - 2;
+ else
+ RSSI_Ave = RSSI_max - 3;
+ }
+
+ /* 1 Process OFDM RSSI */
+ if (UndecoratedSmoothedOFDM <= 0) { /* initialize */
+ UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll;
+ } else {
+ if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) {
+ UndecoratedSmoothedOFDM =
+ (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor - 1)) +
+ (RSSI_Ave)) / (Rx_Smooth_Factor);
+ UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1;
+ } else {
+ UndecoratedSmoothedOFDM =
+ (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor - 1)) +
+ (RSSI_Ave)) / (Rx_Smooth_Factor);
+ }
+ }
+
+ pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap << 1) | BIT(0);
+
+ } else {
+ RSSI_Ave = pPhyInfo->RxPWDBAll;
+
+ /* 1 Process CCK RSSI */
+ if (UndecoratedSmoothedCCK <= 0) { /* initialize */
+ UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll;
+ } else {
+ if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) {
+ UndecoratedSmoothedCCK =
+ ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor - 1)) +
+ pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
+ UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
+ } else {
+ UndecoratedSmoothedCCK =
+ ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor - 1)) +
+ pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
+ }
+ }
+ pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap << 1;
+ }
+ /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */
+ if (pEntry->rssi_stat.ValidBit >= 64)
+ pEntry->rssi_stat.ValidBit = 64;
+ else
+ pEntry->rssi_stat.ValidBit++;
+
+ for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
+ OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap >> i) & BIT(0);
+
+ if (pEntry->rssi_stat.ValidBit == 64) {
+ Weighting = ((OFDM_pkt << 4) > 64) ? 64 : (OFDM_pkt << 4);
+ UndecoratedSmoothedPWDB = (Weighting * UndecoratedSmoothedOFDM + (64 - Weighting) * UndecoratedSmoothedCCK) >> 6;
+ } else {
+ if (pEntry->rssi_stat.ValidBit != 0)
+ UndecoratedSmoothedPWDB = (OFDM_pkt * UndecoratedSmoothedOFDM +
+ (pEntry->rssi_stat.ValidBit - OFDM_pkt) *
+ UndecoratedSmoothedCCK) / pEntry->rssi_stat.ValidBit;
+ else
+ UndecoratedSmoothedPWDB = 0;
+ }
+ pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
+ pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM;
+ pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
+ }
+}
+
+/* Endianness before calling this API */
+static void ODM_PhyStatusQuery_92CSeries(struct odm_dm_struct *dm_odm,
+ struct odm_phy_status_info *pPhyInfo,
+ u8 *pPhyStatus,
+ struct odm_per_pkt_info *pPktinfo,
+ struct adapter *adapt)
+{
+ odm_RxPhyStatus92CSeries_Parsing(dm_odm, pPhyInfo, pPhyStatus,
+ pPktinfo, adapt);
+ if (dm_odm->RSSI_test) {
+ /* Select the packets to do RSSI checking for antenna switching. */
+ if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon)
+ ODM_SwAntDivChkPerPktRssi(dm_odm, pPktinfo->StationID, pPhyInfo);
+ } else {
+ odm_Process_RSSIForDM(dm_odm, pPhyInfo, pPktinfo);
+ }
+}
+
+void ODM_PhyStatusQuery(struct odm_dm_struct *dm_odm,
+ struct odm_phy_status_info *pPhyInfo,
+ u8 *pPhyStatus, struct odm_per_pkt_info *pPktinfo,
+ struct adapter *adapt)
+{
+ ODM_PhyStatusQuery_92CSeries(dm_odm, pPhyInfo, pPhyStatus, pPktinfo, adapt);
+}
+
+/* For future use. */
+void ODM_MacStatusQuery(struct odm_dm_struct *dm_odm, u8 *mac_stat,
+ u8 macid, bool pkt_match_bssid,
+ bool pkttoself, bool pkt_beacon)
+{
+ /* 2011/10/19 Driver team will handle in the future. */
+}
+
+enum HAL_STATUS ODM_ConfigRFWithHeaderFile(struct odm_dm_struct *dm_odm,
+ enum rf_radio_path content,
+ enum rf_radio_path rfpath)
+{
+ if (dm_odm->SupportICType == ODM_RTL8188E) {
+ if (rfpath == RF_PATH_A)
+ READ_AND_CONFIG(8188E, _RadioA_1T_);
+ }
+
+ return HAL_STATUS_SUCCESS;
+}
+
+enum HAL_STATUS ODM_ConfigBBWithHeaderFile(struct odm_dm_struct *dm_odm,
+ enum odm_bb_config_type config_tp)
+{
+ if (dm_odm->SupportICType == ODM_RTL8188E) {
+ if (config_tp == CONFIG_BB_PHY_REG) {
+ READ_AND_CONFIG(8188E, _PHY_REG_1T_);
+ } else if (config_tp == CONFIG_BB_AGC_TAB) {
+ READ_AND_CONFIG(8188E, _AGC_TAB_1T_);
+ } else if (config_tp == CONFIG_BB_PHY_REG_PG) {
+ READ_AND_CONFIG(8188E, _PHY_REG_PG_);
+ }
+ }
+ return HAL_STATUS_SUCCESS;
+}
+
+enum HAL_STATUS ODM_ConfigMACWithHeaderFile(struct odm_dm_struct *dm_odm)
+{
+ u8 result = HAL_STATUS_SUCCESS;
+ if (dm_odm->SupportICType == ODM_RTL8188E)
+ result = READ_AND_CONFIG(8188E, _MAC_REG_);
+ return result;
+}
diff --git a/drivers/staging/r8188eu/hal/odm_RTL8188E.c b/drivers/staging/r8188eu/hal/odm_RTL8188E.c
new file mode 100644
index 000000000000..c64a291f9966
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/odm_RTL8188E.c
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/odm_precomp.h"
+
+void ODM_DIG_LowerBound_88E(struct odm_dm_struct *dm_odm)
+{
+ struct rtw_dig *pDM_DigTable = &dm_odm->DM_DigTable;
+
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ pDM_DigTable->rx_gain_range_min = (u8)pDM_DigTable->AntDiv_RSSI_max;
+ /* If only one Entry connected */
+}
+
+static void odm_RX_HWAntDivInit(struct odm_dm_struct *dm_odm)
+{
+ u32 value32;
+
+ if (*dm_odm->mp_mode == 1) {
+ dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
+ ODM_SetBBReg(dm_odm, ODM_REG_IGI_A_11N, BIT(7), 0); /* disable HW AntDiv */
+ ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(31), 1); /* 1:CG, 0:CS */
+ return;
+ }
+
+ /* MAC Setting */
+ value32 = ODM_GetMACReg(dm_odm, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
+ ODM_SetMACReg(dm_odm, ODM_REG_ANTSEL_PIN_11N, bMaskDWord, value32 | (BIT(23) | BIT(25))); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */
+ /* Pin Settings */
+ ODM_SetBBReg(dm_odm, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0); /* Reg864[10]=1'b0 antsel2 by HW */
+ ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(22), 1); /* Regb2c[22]=1'b0 disable CS/CG switch */
+ ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(31), 1); /* Regb2c[31]=1'b1 output at CG only */
+ /* OFDM Settings */
+ ODM_SetBBReg(dm_odm, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord, 0x000000a0);
+ /* CCK Settings */
+ ODM_SetBBReg(dm_odm, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1); /* Fix CCK PHY status report issue */
+ ODM_SetBBReg(dm_odm, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); /* CCK complete HW AntDiv within 64 samples */
+ ODM_UpdateRxIdleAnt_88E(dm_odm, MAIN_ANT);
+ ODM_SetBBReg(dm_odm, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201); /* antenna mapping table */
+}
+
+static void odm_TRX_HWAntDivInit(struct odm_dm_struct *dm_odm)
+{
+ u32 value32;
+
+ if (*dm_odm->mp_mode == 1) {
+ dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
+ ODM_SetBBReg(dm_odm, ODM_REG_IGI_A_11N, BIT(7), 0); /* disable HW AntDiv */
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), 0); /* Default RX (0/1) */
+ return;
+ }
+
+ /* MAC Setting */
+ value32 = ODM_GetMACReg(dm_odm, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
+ ODM_SetMACReg(dm_odm, ODM_REG_ANTSEL_PIN_11N, bMaskDWord, value32 | (BIT(23) | BIT(25))); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */
+ /* Pin Settings */
+ ODM_SetBBReg(dm_odm, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0); /* Reg864[10]=1'b0 antsel2 by HW */
+ ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(22), 0); /* Regb2c[22]=1'b0 disable CS/CG switch */
+ ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(31), 1); /* Regb2c[31]=1'b1 output at CG only */
+ /* OFDM Settings */
+ ODM_SetBBReg(dm_odm, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord, 0x000000a0);
+ /* CCK Settings */
+ ODM_SetBBReg(dm_odm, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1); /* Fix CCK PHY status report issue */
+ ODM_SetBBReg(dm_odm, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); /* CCK complete HW AntDiv within 64 samples */
+ /* Tx Settings */
+ ODM_SetBBReg(dm_odm, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0); /* Reg80c[21]=1'b0 from TX Reg */
+ ODM_UpdateRxIdleAnt_88E(dm_odm, MAIN_ANT);
+
+ /* antenna mapping table */
+ if (!dm_odm->bIsMPChip) { /* testchip */
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_DEFUALT_A_11N, BIT(10) | BIT(9) | BIT(8), 1); /* Reg858[10:8]=3'b001 */
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_DEFUALT_A_11N, BIT(13) | BIT(12) | BIT(11), 2); /* Reg858[13:11]=3'b010 */
+ } else { /* MPchip */
+ ODM_SetBBReg(dm_odm, ODM_REG_ANT_MAPPING1_11N, bMaskDWord, 0x0201); /* Reg914=3'b010, Reg915=3'b001 */
+ }
+}
+
+static void odm_FastAntTrainingInit(struct odm_dm_struct *dm_odm)
+{
+ u32 value32, i;
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ u32 AntCombination = 2;
+
+ if (*dm_odm->mp_mode == 1)
+ return;
+
+ for (i = 0; i < 6; i++) {
+ dm_fat_tbl->Bssid[i] = 0;
+ dm_fat_tbl->antSumRSSI[i] = 0;
+ dm_fat_tbl->antRSSIcnt[i] = 0;
+ dm_fat_tbl->antAveRSSI[i] = 0;
+ }
+ dm_fat_tbl->TrainIdx = 0;
+ dm_fat_tbl->FAT_State = FAT_NORMAL_STATE;
+
+ /* MAC Setting */
+ value32 = ODM_GetMACReg(dm_odm, 0x4c, bMaskDWord);
+ ODM_SetMACReg(dm_odm, 0x4c, bMaskDWord, value32 | (BIT(23) | BIT(25))); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */
+ value32 = ODM_GetMACReg(dm_odm, 0x7B4, bMaskDWord);
+ ODM_SetMACReg(dm_odm, 0x7b4, bMaskDWord, value32 | (BIT(16) | BIT(17))); /* Reg7B4[16]=1 enable antenna training, Reg7B4[17]=1 enable A2 match */
+
+ /* Match MAC ADDR */
+ ODM_SetMACReg(dm_odm, 0x7b4, 0xFFFF, 0);
+ ODM_SetMACReg(dm_odm, 0x7b0, bMaskDWord, 0);
+
+ ODM_SetBBReg(dm_odm, 0x870, BIT(9) | BIT(8), 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */
+ ODM_SetBBReg(dm_odm, 0x864, BIT(10), 0); /* Reg864[10]=1'b0 antsel2 by HW */
+ ODM_SetBBReg(dm_odm, 0xb2c, BIT(22), 0); /* Regb2c[22]=1'b0 disable CS/CG switch */
+ ODM_SetBBReg(dm_odm, 0xb2c, BIT(31), 1); /* Regb2c[31]=1'b1 output at CG only */
+ ODM_SetBBReg(dm_odm, 0xca4, bMaskDWord, 0x000000a0);
+
+ /* antenna mapping table */
+ if (AntCombination == 2) {
+ if (!dm_odm->bIsMPChip) { /* testchip */
+ ODM_SetBBReg(dm_odm, 0x858, BIT(10) | BIT(9) | BIT(8), 1); /* Reg858[10:8]=3'b001 */
+ ODM_SetBBReg(dm_odm, 0x858, BIT(13) | BIT(12) | BIT(11), 2); /* Reg858[13:11]=3'b010 */
+ } else { /* MPchip */
+ ODM_SetBBReg(dm_odm, 0x914, bMaskByte0, 1);
+ ODM_SetBBReg(dm_odm, 0x914, bMaskByte1, 2);
+ }
+ } else if (AntCombination == 7) {
+ if (!dm_odm->bIsMPChip) { /* testchip */
+ ODM_SetBBReg(dm_odm, 0x858, BIT(10) | BIT(9) | BIT(8), 0); /* Reg858[10:8]=3'b000 */
+ ODM_SetBBReg(dm_odm, 0x858, BIT(13) | BIT(12) | BIT(11), 1); /* Reg858[13:11]=3'b001 */
+ ODM_SetBBReg(dm_odm, 0x878, BIT(16), 0);
+ ODM_SetBBReg(dm_odm, 0x858, BIT(15) | BIT(14), 2); /* Reg878[0],Reg858[14:15])=3'b010 */
+ ODM_SetBBReg(dm_odm, 0x878, BIT(19) | BIT(18) | BIT(17), 3);/* Reg878[3:1]=3b'011 */
+ ODM_SetBBReg(dm_odm, 0x878, BIT(22) | BIT(21) | BIT(20), 4);/* Reg878[6:4]=3b'100 */
+ ODM_SetBBReg(dm_odm, 0x878, BIT(25) | BIT(24) | BIT(23), 5);/* Reg878[9:7]=3b'101 */
+ ODM_SetBBReg(dm_odm, 0x878, BIT(28) | BIT(27) | BIT(26), 6);/* Reg878[12:10]=3b'110 */
+ ODM_SetBBReg(dm_odm, 0x878, BIT(31) | BIT(30) | BIT(29), 7);/* Reg878[15:13]=3b'111 */
+ } else { /* MPchip */
+ ODM_SetBBReg(dm_odm, 0x914, bMaskByte0, 0);
+ ODM_SetBBReg(dm_odm, 0x914, bMaskByte1, 1);
+ ODM_SetBBReg(dm_odm, 0x914, bMaskByte2, 2);
+ ODM_SetBBReg(dm_odm, 0x914, bMaskByte3, 3);
+ ODM_SetBBReg(dm_odm, 0x918, bMaskByte0, 4);
+ ODM_SetBBReg(dm_odm, 0x918, bMaskByte1, 5);
+ ODM_SetBBReg(dm_odm, 0x918, bMaskByte2, 6);
+ ODM_SetBBReg(dm_odm, 0x918, bMaskByte3, 7);
+ }
+ }
+
+ /* Default Ant Setting when no fast training */
+ ODM_SetBBReg(dm_odm, 0x80c, BIT(21), 1); /* Reg80c[21]=1'b1 from TX Info */
+ ODM_SetBBReg(dm_odm, 0x864, BIT(5) | BIT(4) | BIT(3), 0); /* Default RX */
+ ODM_SetBBReg(dm_odm, 0x864, BIT(8) | BIT(7) | BIT(6), 1); /* Optional RX */
+
+ /* Enter Traing state */
+ ODM_SetBBReg(dm_odm, 0x864, BIT(2) | BIT(1) | BIT(0), (AntCombination - 1)); /* Reg864[2:0]=3'd6 ant combination=reg864[2:0]+1 */
+ ODM_SetBBReg(dm_odm, 0xc50, BIT(7), 1); /* RegC50[7]=1'b1 enable HW AntDiv */
+}
+
+void ODM_AntennaDiversityInit_88E(struct odm_dm_struct *dm_odm)
+{
+ if (dm_odm->SupportICType != ODM_RTL8188E)
+ return;
+
+ if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)
+ odm_RX_HWAntDivInit(dm_odm);
+ else if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ odm_TRX_HWAntDivInit(dm_odm);
+ else if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)
+ odm_FastAntTrainingInit(dm_odm);
+}
+
+void ODM_UpdateRxIdleAnt_88E(struct odm_dm_struct *dm_odm, u8 Ant)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ u32 DefaultAnt, OptionalAnt;
+
+ if (dm_fat_tbl->RxIdleAnt != Ant) {
+ if (Ant == MAIN_ANT) {
+ DefaultAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
+ OptionalAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
+ } else {
+ DefaultAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
+ OptionalAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
+ }
+
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), DefaultAnt); /* Default RX */
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), OptionalAnt); /* Optional RX */
+ ODM_SetBBReg(dm_odm, ODM_REG_ANTSEL_CTRL_11N, BIT(14) | BIT(13) | BIT(12), DefaultAnt); /* Default TX */
+ ODM_SetMACReg(dm_odm, ODM_REG_RESP_TX_11N, BIT(6) | BIT(7), DefaultAnt); /* Resp Tx */
+ } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), DefaultAnt); /* Default RX */
+ ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), OptionalAnt); /* Optional RX */
+ }
+ }
+ dm_fat_tbl->RxIdleAnt = Ant;
+ if (Ant != MAIN_ANT)
+ pr_info("RxIdleAnt=AUX_ANT\n");
+}
+
+static void odm_UpdateTxAnt_88E(struct odm_dm_struct *dm_odm, u8 Ant, u32 MacId)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ u8 TargetAnt;
+
+ if (Ant == MAIN_ANT)
+ TargetAnt = MAIN_ANT_CG_TRX;
+ else
+ TargetAnt = AUX_ANT_CG_TRX;
+ dm_fat_tbl->antsel_a[MacId] = TargetAnt & BIT(0);
+ dm_fat_tbl->antsel_b[MacId] = (TargetAnt & BIT(1)) >> 1;
+ dm_fat_tbl->antsel_c[MacId] = (TargetAnt & BIT(2)) >> 2;
+}
+
+void ODM_SetTxAntByTxInfo_88E(struct odm_dm_struct *dm_odm, u8 *pDesc, u8 macId)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+
+ if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)) {
+ SET_TX_DESC_ANTSEL_A_88E(pDesc, dm_fat_tbl->antsel_a[macId]);
+ SET_TX_DESC_ANTSEL_B_88E(pDesc, dm_fat_tbl->antsel_b[macId]);
+ SET_TX_DESC_ANTSEL_C_88E(pDesc, dm_fat_tbl->antsel_c[macId]);
+ }
+}
+
+void ODM_AntselStatistics_88E(struct odm_dm_struct *dm_odm, u8 antsel_tr_mux, u32 MacId, u8 RxPWDBAll)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
+ if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
+ dm_fat_tbl->MainAnt_Sum[MacId] += RxPWDBAll;
+ dm_fat_tbl->MainAnt_Cnt[MacId]++;
+ } else {
+ dm_fat_tbl->AuxAnt_Sum[MacId] += RxPWDBAll;
+ dm_fat_tbl->AuxAnt_Cnt[MacId]++;
+ }
+ } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
+ if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
+ dm_fat_tbl->MainAnt_Sum[MacId] += RxPWDBAll;
+ dm_fat_tbl->MainAnt_Cnt[MacId]++;
+ } else {
+ dm_fat_tbl->AuxAnt_Sum[MacId] += RxPWDBAll;
+ dm_fat_tbl->AuxAnt_Cnt[MacId]++;
+ }
+ }
+}
+
+static void odm_HWAntDiv(struct odm_dm_struct *dm_odm)
+{
+ u32 i, MinRSSI = 0xFF, AntDivMaxRSSI = 0, MaxRSSI = 0, LocalMinRSSI, LocalMaxRSSI;
+ u32 Main_RSSI, Aux_RSSI;
+ u8 RxIdleAnt = 0, TargetAnt = 7;
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ struct rtw_dig *pDM_DigTable = &dm_odm->DM_DigTable;
+ struct sta_info *pEntry;
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ pEntry = dm_odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(pEntry)) {
+ /* 2 Caculate RSSI per Antenna */
+ Main_RSSI = (dm_fat_tbl->MainAnt_Cnt[i] != 0) ? (dm_fat_tbl->MainAnt_Sum[i] / dm_fat_tbl->MainAnt_Cnt[i]) : 0;
+ Aux_RSSI = (dm_fat_tbl->AuxAnt_Cnt[i] != 0) ? (dm_fat_tbl->AuxAnt_Sum[i] / dm_fat_tbl->AuxAnt_Cnt[i]) : 0;
+ TargetAnt = (Main_RSSI >= Aux_RSSI) ? MAIN_ANT : AUX_ANT;
+ /* 2 Select MaxRSSI for DIG */
+ LocalMaxRSSI = (Main_RSSI > Aux_RSSI) ? Main_RSSI : Aux_RSSI;
+ if ((LocalMaxRSSI > AntDivMaxRSSI) && (LocalMaxRSSI < 40))
+ AntDivMaxRSSI = LocalMaxRSSI;
+ if (LocalMaxRSSI > MaxRSSI)
+ MaxRSSI = LocalMaxRSSI;
+
+ /* 2 Select RX Idle Antenna */
+ if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) && (Main_RSSI == 0))
+ Main_RSSI = Aux_RSSI;
+ else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) && (Aux_RSSI == 0))
+ Aux_RSSI = Main_RSSI;
+
+ LocalMinRSSI = (Main_RSSI > Aux_RSSI) ? Aux_RSSI : Main_RSSI;
+ if (LocalMinRSSI < MinRSSI) {
+ MinRSSI = LocalMinRSSI;
+ RxIdleAnt = TargetAnt;
+ }
+ /* 2 Select TRX Antenna */
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ odm_UpdateTxAnt_88E(dm_odm, TargetAnt, i);
+ }
+ dm_fat_tbl->MainAnt_Sum[i] = 0;
+ dm_fat_tbl->AuxAnt_Sum[i] = 0;
+ dm_fat_tbl->MainAnt_Cnt[i] = 0;
+ dm_fat_tbl->AuxAnt_Cnt[i] = 0;
+ }
+
+ /* 2 Set RX Idle Antenna */
+ ODM_UpdateRxIdleAnt_88E(dm_odm, RxIdleAnt);
+
+ pDM_DigTable->AntDiv_RSSI_max = AntDivMaxRSSI;
+ pDM_DigTable->RSSI_max = MaxRSSI;
+}
+
+void ODM_AntennaDiversity_88E(struct odm_dm_struct *dm_odm)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ if ((dm_odm->SupportICType != ODM_RTL8188E) || (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV)))
+ return;
+ if (!dm_odm->bLinked) {
+ if (dm_fat_tbl->bBecomeLinked) {
+ ODM_SetBBReg(dm_odm, ODM_REG_IGI_A_11N, BIT(7), 0); /* RegC50[7]=1'b1 enable HW AntDiv */
+ ODM_SetBBReg(dm_odm, ODM_REG_CCK_ANTDIV_PARA1_11N, BIT(15), 0); /* Enable CCK AntDiv */
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ ODM_SetBBReg(dm_odm, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0); /* Reg80c[21]=1'b0 from TX Reg */
+ dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
+ }
+ return;
+ } else {
+ if (!dm_fat_tbl->bBecomeLinked) {
+ /* Because HW AntDiv is disabled before Link, we enable HW AntDiv after link */
+ ODM_SetBBReg(dm_odm, ODM_REG_IGI_A_11N, BIT(7), 1); /* RegC50[7]=1'b1 enable HW AntDiv */
+ ODM_SetBBReg(dm_odm, ODM_REG_CCK_ANTDIV_PARA1_11N, BIT(15), 1); /* Enable CCK AntDiv */
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ ODM_SetBBReg(dm_odm, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 1); /* Reg80c[21]=1'b1 from TX Info */
+ dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
+ }
+ }
+ if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV))
+ odm_HWAntDiv(dm_odm);
+}
+
+/* 3============================================================ */
+/* 3 Dynamic Primary CCA */
+/* 3============================================================ */
+
+void odm_PrimaryCCA_Init(struct odm_dm_struct *dm_odm)
+{
+ struct dyn_primary_cca *PrimaryCCA = &dm_odm->DM_PriCCA;
+
+ PrimaryCCA->dup_rts_flag = 0;
+ PrimaryCCA->intf_flag = 0;
+ PrimaryCCA->intf_type = 0;
+ PrimaryCCA->monitor_flag = 0;
+ PrimaryCCA->pri_cca_flag = 0;
+}
diff --git a/drivers/staging/r8188eu/hal/odm_RegConfig8188E.c b/drivers/staging/r8188eu/hal/odm_RegConfig8188E.c
new file mode 100644
index 000000000000..1bc3b49cd67f
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/odm_RegConfig8188E.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/odm_precomp.h"
+
+void odm_ConfigRFReg_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr,
+ u32 Data, enum rf_radio_path RF_PATH,
+ u32 RegAddr)
+{
+ if (Addr == 0xffe) {
+ ODM_sleep_ms(50);
+ } else if (Addr == 0xfd) {
+ ODM_delay_ms(5);
+ } else if (Addr == 0xfc) {
+ ODM_delay_ms(1);
+ } else if (Addr == 0xfb) {
+ ODM_delay_us(50);
+ } else if (Addr == 0xfa) {
+ ODM_delay_us(5);
+ } else if (Addr == 0xf9) {
+ ODM_delay_us(1);
+ } else {
+ ODM_SetRFReg(pDM_Odm, RF_PATH, RegAddr, bRFRegOffsetMask, Data);
+ /* Add 1us delay between BB/RF register setting. */
+ ODM_delay_us(1);
+ }
+}
+
+void odm_ConfigRF_RadioA_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Data)
+{
+ u32 content = 0x1000; /* RF_Content: radioa_txt */
+ u32 maskforPhySet = (u32)(content & 0xE000);
+
+ odm_ConfigRFReg_8188E(pDM_Odm, Addr, Data, RF_PATH_A, Addr | maskforPhySet);
+}
+
+void odm_ConfigRF_RadioB_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Data)
+{
+ u32 content = 0x1001; /* RF_Content: radiob_txt */
+ u32 maskforPhySet = (u32)(content & 0xE000);
+
+ odm_ConfigRFReg_8188E(pDM_Odm, Addr, Data, RF_PATH_B, Addr | maskforPhySet);
+}
+
+void odm_ConfigMAC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u8 Data)
+{
+ ODM_Write1Byte(pDM_Odm, Addr, Data);
+}
+
+void odm_ConfigBB_AGC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data)
+{
+ ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
+ /* Add 1us delay between BB/RF register setting. */
+ ODM_delay_us(1);
+}
+
+void odm_ConfigBB_PHY_REG_PG_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr,
+ u32 Bitmask, u32 Data)
+{
+ if (Addr == 0xfe)
+ ODM_sleep_ms(50);
+ else if (Addr == 0xfd)
+ ODM_delay_ms(5);
+ else if (Addr == 0xfc)
+ ODM_delay_ms(1);
+ else if (Addr == 0xfb)
+ ODM_delay_us(50);
+ else if (Addr == 0xfa)
+ ODM_delay_us(5);
+ else if (Addr == 0xf9)
+ ODM_delay_us(1);
+ else
+ storePwrIndexDiffRateOffset(pDM_Odm->Adapter, Addr, Bitmask, Data);
+}
+
+void odm_ConfigBB_PHY_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data)
+{
+ if (Addr == 0xfe) {
+ ODM_sleep_ms(50);
+ } else if (Addr == 0xfd) {
+ ODM_delay_ms(5);
+ } else if (Addr == 0xfc) {
+ ODM_delay_ms(1);
+ } else if (Addr == 0xfb) {
+ ODM_delay_us(50);
+ } else if (Addr == 0xfa) {
+ ODM_delay_us(5);
+ } else if (Addr == 0xf9) {
+ ODM_delay_us(1);
+ } else {
+ if (Addr == 0xa24)
+ pDM_Odm->RFCalibrateInfo.RegA24 = Data;
+ ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
+
+ /* Add 1us delay between BB/RF register setting. */
+ ODM_delay_us(1);
+ }
+}
diff --git a/drivers/staging/r8188eu/hal/odm_debug.c b/drivers/staging/r8188eu/hal/odm_debug.c
new file mode 100644
index 000000000000..7029ec4f771e
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/odm_debug.c
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/odm_precomp.h"
+
+u32 GlobalDebugLevel;
diff --git a/drivers/staging/r8188eu/hal/odm_interface.c b/drivers/staging/r8188eu/hal/odm_interface.c
new file mode 100644
index 000000000000..5a01495d74bc
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/odm_interface.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/odm_precomp.h"
+/* ODM IO Relative API. */
+
+u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ return rtw_read8(Adapter, RegAddr);
+}
+
+u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ return rtw_read16(Adapter, RegAddr);
+}
+
+u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ return rtw_read32(Adapter, RegAddr);
+}
+
+void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ rtw_write8(Adapter, RegAddr, Data);
+}
+
+void ODM_Write2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 Data)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ rtw_write16(Adapter, RegAddr, Data);
+}
+
+void ODM_Write4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 Data)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ rtw_write32(Adapter, RegAddr, Data);
+}
+
+void ODM_SetMACReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
+}
+
+u32 ODM_GetMACReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
+}
+
+void ODM_SetBBReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
+}
+
+u32 ODM_GetBBReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
+}
+
+void ODM_SetRFReg(struct odm_dm_struct *pDM_Odm, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ PHY_SetRFReg(Adapter, (enum rf_radio_path)eRFPath, RegAddr, BitMask, Data);
+}
+
+u32 ODM_GetRFReg(struct odm_dm_struct *pDM_Odm, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ return PHY_QueryRFReg(Adapter, (enum rf_radio_path)eRFPath, RegAddr, BitMask);
+}
+
+/* ODM Memory relative API. */
+void ODM_AllocateMemory(struct odm_dm_struct *pDM_Odm, void **pPtr, u32 length)
+{
+ *pPtr = vzalloc(length);
+}
+
+/* length could be ignored, used to detect memory leakage. */
+void ODM_FreeMemory(struct odm_dm_struct *pDM_Odm, void *pPtr, u32 length)
+{
+ vfree(pPtr);
+}
+
+s32 ODM_CompareMemory(struct odm_dm_struct *pDM_Odm, void *pBuf1, void *pBuf2, u32 length)
+{
+ return !memcmp(pBuf1, pBuf2, length);
+}
+
+/* ODM MISC relative API. */
+void ODM_AcquireSpinLock(struct odm_dm_struct *pDM_Odm, enum RT_SPINLOCK_TYPE type)
+{
+}
+
+void ODM_ReleaseSpinLock(struct odm_dm_struct *pDM_Odm, enum RT_SPINLOCK_TYPE type)
+{
+}
+
+/* Work item relative API. FOr MP driver only~! */
+void ODM_InitializeWorkItem(struct odm_dm_struct *pDM_Odm, void *pRtWorkItem,
+ RT_WORKITEM_CALL_BACK RtWorkItemCallback,
+ void *pContext, const char *szID)
+{
+}
+
+void ODM_StartWorkItem(void *pRtWorkItem)
+{
+}
+
+void ODM_StopWorkItem(void *pRtWorkItem)
+{
+}
+
+void ODM_FreeWorkItem(void *pRtWorkItem)
+{
+}
+
+void ODM_ScheduleWorkItem(void *pRtWorkItem)
+{
+}
+
+void ODM_IsWorkItemScheduled(void *pRtWorkItem)
+{
+}
+
+/* ODM Timer relative API. */
+void ODM_StallExecution(u32 usDelay)
+{
+ udelay(usDelay);
+}
+
+void ODM_delay_ms(u32 ms)
+{
+ mdelay(ms);
+}
+
+void ODM_delay_us(u32 us)
+{
+ udelay(us);
+}
+
+void ODM_sleep_ms(u32 ms)
+{
+ msleep(ms);
+}
+
+void ODM_sleep_us(u32 us)
+{
+ rtw_usleep_os(us);
+}
+
+void ODM_SetTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer, u32 msDelay)
+{
+ _set_timer(pTimer, msDelay); /* ms */
+}
+
+void ODM_CancelTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer)
+{
+ _cancel_timer_ex(pTimer);
+}
+
+void ODM_ReleaseTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer)
+{
+}
+
+/* ODM FW relative API. */
+u32 ODM_FillH2CCmd(u8 *pH2CBuffer, u32 H2CBufferLen, u32 CmdNum,
+ u32 *pElementID, u32 *pCmdLen,
+ u8 **pCmbBuffer, u8 *CmdStartSeq)
+{
+ return true;
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/r8188eu/hal/rtl8188e_cmd.c
index f2969e160ac3..7d50d64cf34d 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+++ b/drivers/staging/r8188eu/hal/rtl8188e_cmd.c
@@ -1,18 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#define _RTL8188E_CMD_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <mlme_osdep.h>
-#include <rtw_ioctl_set.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/mlme_osdep.h"
+#include "../include/rtw_ioctl_set.h"
-#include <rtl8188e_hal.h>
+#include "../include/rtl8188e_hal.h"
#define RTL88E_MAX_H2C_BOX_NUMS 4
#define RTL88E_MAX_CMD_LEN 7
@@ -22,13 +19,13 @@
static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
{
u8 read_down = false;
- int retry_cnts = 100;
+ int retry_cnts = 100;
u8 valid;
do {
- valid = usb_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
- if (valid == 0)
+ valid = rtw_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
+ if (0 == valid)
read_down = true;
} while ((!read_down) && (retry_cnts--));
@@ -47,16 +44,21 @@ static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
******************************************/
static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
{
+ u8 bcmd_down = false;
+ s32 retry_cnts = 100;
u8 h2c_box_num;
u32 msgbox_addr;
u32 msgbox_ex_addr;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
u8 cmd_idx, ext_cmd_len;
u32 h2c_cmd = 0;
u32 h2c_cmd_ex = 0;
s32 ret = _FAIL;
- if (!adapt->bFWReady)
+ if (!adapt->bFWReady) {
+ DBG_88E("FillH2CCmd_88E(): return H2C cmd because fw is not ready\n");
return ret;
+ }
if (!pCmdBuffer)
goto exit;
@@ -66,47 +68,93 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p
goto exit;
/* pay attention to if race condition happened in H2C cmd setting. */
- h2c_box_num = adapt->HalData->LastHMEBoxNum;
+ do {
+ h2c_box_num = haldata->LastHMEBoxNum;
- if (!_is_fw_read_cmd_down(adapt, h2c_box_num))
- goto exit;
+ if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) {
+ DBG_88E(" fw read cmd failed...\n");
+ goto exit;
+ }
- *(u8 *)(&h2c_cmd) = ElementID;
+ *(u8 *)(&h2c_cmd) = ElementID;
- if (CmdLen <= 3) {
- memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, CmdLen);
- } else {
- memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, 3);
- ext_cmd_len = CmdLen - 3;
- memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer + 3, ext_cmd_len);
-
- /* Write Ext command */
- msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE);
- for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++)
- usb_write8(adapt, msgbox_ex_addr + cmd_idx, *((u8 *)(&h2c_cmd_ex) + cmd_idx));
- }
- /* Write command */
- msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE);
- for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++)
- usb_write8(adapt, msgbox_addr + cmd_idx, *((u8 *)(&h2c_cmd) + cmd_idx));
+ if (CmdLen <= 3) {
+ memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, CmdLen);
+ } else {
+ memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, 3);
+ ext_cmd_len = CmdLen - 3;
+ memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer + 3, ext_cmd_len);
+
+ /* Write Ext command */
+ msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE);
+ for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++) {
+ rtw_write8(adapt, msgbox_ex_addr + cmd_idx, *((u8 *)(&h2c_cmd_ex) + cmd_idx));
+ }
+ }
+ /* Write command */
+ msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE);
+ for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++) {
+ rtw_write8(adapt, msgbox_addr + cmd_idx, *((u8 *)(&h2c_cmd) + cmd_idx));
+ }
+ bcmd_down = true;
- adapt->HalData->LastHMEBoxNum =
- (h2c_box_num + 1) % RTL88E_MAX_H2C_BOX_NUMS;
+ haldata->LastHMEBoxNum = (h2c_box_num + 1) % RTL88E_MAX_H2C_BOX_NUMS;
+
+ } while ((!bcmd_down) && (retry_cnts--));
ret = _SUCCESS;
exit:
+
return ret;
}
+u8 rtl8188e_set_rssi_cmd(struct adapter *adapt, u8 *param)
+{
+ u8 res = _SUCCESS;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+
+ if (haldata->fw_ractrl) {
+ ;
+ } else {
+ DBG_88E("==>%s fw dont support RA\n", __func__);
+ res = _FAIL;
+ }
+
+ return res;
+}
+
+u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask)
+{
+ u8 buf[3];
+ u8 res = _SUCCESS;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+
+ if (haldata->fw_ractrl) {
+ __le32 lmask;
+
+ memset(buf, 0, 3);
+ lmask = cpu_to_le32(mask);
+ memcpy(buf, &lmask, 3);
+
+ FillH2CCmd_88E(adapt, H2C_DM_MACID_CFG, 3, buf);
+ } else {
+ DBG_88E("==>%s fw dont support RA\n", __func__);
+ res = _FAIL;
+ }
+
+ return res;
+}
+
/* bitmap[0:27] = tx_rate_bitmap */
/* bitmap[28:31]= Rate Adaptive id */
/* arg[0:4] = macid */
/* arg[5] = Short GI */
-void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
+void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
{
- struct odm_dm_struct *odmpriv = &pAdapter->HalData->odmpriv;
- u8 macid, init_rate, raid, shortGIrate = false;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(pAdapter);
+
+ u8 macid, raid, short_gi_rate = false;
macid = arg & 0x1f;
@@ -114,22 +162,17 @@ void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_le
bitmap &= 0x0fffffff;
if (rssi_level != DM_RATR_STA_INIT)
- bitmap = ODM_Get_Rate_Bitmap(odmpriv, macid, bitmap, rssi_level);
+ bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, macid, bitmap, rssi_level);
bitmap |= ((raid << 28) & 0xf0000000);
- init_rate = get_highest_rate_idx(bitmap & 0x0fffffff) & 0x3f;
-
- shortGIrate = (arg & BIT(5)) ? true : false;
-
- if (shortGIrate)
- init_rate |= BIT(6);
+ short_gi_rate = (arg & BIT(5)) ? true : false;
raid = (bitmap >> 28) & 0x0f;
bitmap &= 0x0fffffff;
- ODM_RA_UpdateRateInfo_8188E(odmpriv, macid, raid, bitmap, shortGIrate);
+ ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv, macid, raid, bitmap, short_gi_rate);
}
void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode)
@@ -138,6 +181,9 @@ void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode)
struct pwrctrl_priv *pwrpriv = &adapt->pwrctrlpriv;
u8 RLBM = 0; /* 0:Min, 1:Max, 2:User define */
+ DBG_88E("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __func__,
+ Mode, pwrpriv->smart_ps, adapt->registrypriv.uapsd_enable);
+
switch (Mode) {
case PS_MODE_ACTIVE:
H2CSetPwrMode.Mode = 0;
@@ -173,59 +219,64 @@ void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode)
H2CSetPwrMode.PwrState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
FillH2CCmd_88E(adapt, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
+
}
void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt)
{
+ u8 opmode, macid;
u16 mst_rpt = le16_to_cpu(mstatus_rpt);
+ opmode = (u8)mst_rpt;
+ macid = (u8)(mst_rpt >> 8);
+ DBG_88E("### %s: MStatus=%x MACID=%d\n", __func__, opmode, macid);
FillH2CCmd_88E(adapt, H2C_COM_MEDIA_STATUS_RPT, sizeof(mst_rpt), (u8 *)&mst_rpt);
}
static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
{
- struct ieee80211_hdr *pwlanhdr;
+ struct rtw_ieee80211_hdr *pwlanhdr;
__le16 *fctrl;
u32 rate_len, pktlen;
struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- pwlanhdr = (struct ieee80211_hdr *)pframe;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &pwlanhdr->frame_control;
+ fctrl = &pwlanhdr->frame_ctl;
*(fctrl) = 0;
- ether_addr_copy(pwlanhdr->addr1, bc_addr);
- ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
+ memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&adapt->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
- SetFrameSubType(pframe, IEEE80211_STYPE_BEACON);
+ SetFrameSubType(pframe, WIFI_BEACON);
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pktlen = sizeof(struct ieee80211_hdr_3addr);
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
/* timestamp will be inserted by hardware */
pframe += 8;
pktlen += 8;
/* beacon interval: 2 bytes */
- memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
pframe += 2;
pktlen += 2;
/* capability info: 2 bytes */
- memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
pframe += 2;
pktlen += 2;
if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
- pktlen += cur_network->ie_length - sizeof(struct ndis_802_11_fixed_ie);
- memcpy(pframe, cur_network->ies + sizeof(struct ndis_802_11_fixed_ie), pktlen);
+ pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fixed_ie);
+ memcpy(pframe, cur_network->IEs + sizeof(struct ndis_802_11_fixed_ie), pktlen);
goto _ConstructBeacon;
}
@@ -233,62 +284,63 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
/* below for ad-hoc mode */
/* SSID */
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pktlen);
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
/* supported rates... */
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, min_t(u32, rate_len, 8), cur_network->SupportedRates, &pktlen);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen);
/* DS parameter set */
- pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pktlen);
+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pktlen);
if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
u32 ATIMWindow;
/* IBSS Parameter Set... */
ATIMWindow = 0;
- pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pktlen);
+ pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
}
/* todo: ERP IE */
/* EXTERNDED SUPPORTED RATE */
if (rate_len > 8)
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
/* todo:HT for adhoc */
_ConstructBeacon:
- if ((pktlen + TXDESC_SIZE) > 512)
+ if ((pktlen + TXDESC_SIZE) > 512) {
+ DBG_88E("beacon frame too large\n");
return;
+ }
*pLength = pktlen;
}
static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength)
{
- struct ieee80211_hdr *pwlanhdr;
+ struct rtw_ieee80211_hdr *pwlanhdr;
struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
__le16 *fctrl;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
/* Frame control. */
- fctrl = &pwlanhdr->frame_control;
+ fctrl = &pwlanhdr->frame_ctl;
*(fctrl) = 0;
SetPwrMgt(fctrl);
- SetFrameSubType(pframe, IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
+ SetFrameSubType(pframe, WIFI_PSPOLL);
/* AID. */
SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
/* BSSID. */
- ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
+ memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
/* TA. */
- ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
+ memcpy(pwlanhdr->addr2, myid(&adapt->eeprompriv), ETH_ALEN);
*pLength = 16;
}
@@ -301,18 +353,17 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe,
u8 bEosp,
u8 bForcePowerSave)
{
- struct ieee80211_hdr *pwlanhdr;
+ struct rtw_ieee80211_hdr *pwlanhdr;
__le16 *fctrl;
u32 pktlen;
struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &pwlanhdr->frame_control;
+ fctrl = &pwlanhdr->frame_ctl;
*(fctrl) = 0;
if (bForcePowerSave)
SetPwrMgt(fctrl);
@@ -320,40 +371,40 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe,
switch (cur_network->network.InfrastructureMode) {
case Ndis802_11Infrastructure:
SetToDs(fctrl);
- ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
- ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, StaAddr);
+ memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&adapt->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
break;
case Ndis802_11APMode:
SetFrDs(fctrl);
- ether_addr_copy(pwlanhdr->addr1, StaAddr);
- ether_addr_copy(pwlanhdr->addr2, pnetwork->MacAddress);
- ether_addr_copy(pwlanhdr->addr3, myid(&adapt->eeprompriv));
+ memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, myid(&adapt->eeprompriv), ETH_ALEN);
break;
case Ndis802_11IBSS:
default:
- ether_addr_copy(pwlanhdr->addr1, StaAddr);
- ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
+ memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, myid(&adapt->eeprompriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
break;
}
SetSeqNum(pwlanhdr, 0);
if (bQoS) {
- struct ieee80211_qos_hdr *pwlanqoshdr;
+ struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;
- SetFrameSubType(pframe, IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
+ SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
- pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
- SetPriority(&pwlanqoshdr->qos_ctrl, AC);
- SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
+ pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe;
+ SetPriority(&pwlanqoshdr->qc, AC);
+ SetEOSP(&pwlanqoshdr->qc, bEosp);
- pktlen = sizeof(struct ieee80211_qos_hdr);
+ pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
} else {
- SetFrameSubType(pframe, IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC);
+ SetFrameSubType(pframe, WIFI_DATA_NULL);
- pktlen = sizeof(struct ieee80211_hdr_3addr);
+ pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
}
*pLength = pktlen;
@@ -361,41 +412,47 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe,
static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
{
- struct ieee80211_hdr *pwlanhdr;
+ struct rtw_ieee80211_hdr *pwlanhdr;
__le16 *fctrl;
u8 *mac, *bssid;
u32 pktlen;
struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
mac = myid(&adapt->eeprompriv);
bssid = cur_network->MacAddress;
- fctrl = &pwlanhdr->frame_control;
+ fctrl = &pwlanhdr->frame_ctl;
*(fctrl) = 0;
- ether_addr_copy(pwlanhdr->addr1, StaAddr);
- ether_addr_copy(pwlanhdr->addr2, mac);
- ether_addr_copy(pwlanhdr->addr3, bssid);
+ memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
SetSeqNum(pwlanhdr, 0);
- SetFrameSubType(fctrl, IEEE80211_STYPE_PROBE_RESP);
+ SetFrameSubType(fctrl, WIFI_PROBERSP);
- pktlen = sizeof(struct ieee80211_hdr_3addr);
+ pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
pframe += pktlen;
- if (cur_network->ie_length > MAX_IE_SZ)
+ if (cur_network->IELength > MAX_IE_SZ)
return;
- memcpy(pframe, cur_network->ies, cur_network->ie_length);
- pframe += cur_network->ie_length;
- pktlen += cur_network->ie_length;
+ memcpy(pframe, cur_network->IEs, cur_network->IELength);
+ pframe += cur_network->IELength;
+ pktlen += cur_network->IELength;
*pLength = pktlen;
}
+/* To check if reserved page content is destroyed by beacon because beacon is too large. */
+/* 2010.06.23. Added by tynli. */
+void CheckFwRsvdPageContent(struct adapter *Adapter)
+{
+}
+
/* */
/* Description: Fill the reserved packets that FW will use to RSVD page. */
/* Now we just send 4 types packet to rsvd page. */
@@ -408,11 +465,12 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u
/* 2009.10.15 by tynli. */
static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
{
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
+ struct hal_data_8188e *haldata;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv;
struct mlme_ext_priv *pmlmeext;
- struct mlme_ext_info *pmlmeinfo;
+ struct mlme_ext_info *pmlmeinfo;
u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
u32 NullDataLength, QosNullLength;
u8 *ReservedPagePacket;
@@ -420,16 +478,18 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
u16 BufIndex;
u32 TotalPacketLen;
struct rsvdpage_loc RsvdPageLoc;
- struct wlan_bssid_ex *pnetwork;
+ DBG_88E("%s\n", __func__);
ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
- if (!ReservedPagePacket)
+ if (!ReservedPagePacket) {
+ DBG_88E("%s: alloc ReservedPagePacket fail!\n", __func__);
return;
+ }
+ haldata = GET_HAL_DATA(adapt);
pxmitpriv = &adapt->xmitpriv;
pmlmeext = &adapt->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
- pnetwork = &pmlmeinfo->network;
TxDescLen = TXDESC_SIZE;
PageNum = 0;
@@ -445,6 +505,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
if (PageNeed == 1)
PageNeed += 1;
PageNum += PageNeed;
+ haldata->FwRsvdPageStartOffset = PageNum;
BufIndex += PageNeed * 128;
@@ -460,7 +521,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
/* 3 (3) null data * 1 page */
RsvdPageLoc.LocNullData = PageNum;
- ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, pnetwork->MacAddress, false, 0, 0, false);
+ ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, get_my_bssid(&pmlmeinfo->network), false, 0, 0, false);
rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex - TxDescLen], NullDataLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
@@ -470,7 +531,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
/* 3 (4) probe response * 1page */
RsvdPageLoc.LocProbeRsp = PageNum;
- ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, pnetwork->MacAddress, false);
+ ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, get_my_bssid(&pmlmeinfo->network), false);
rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex - TxDescLen], ProbeRspLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
@@ -481,7 +542,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
/* 3 (5) Qos null data */
RsvdPageLoc.LocQosNull = PageNum;
ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex],
- &QosNullLength, pnetwork->MacAddress, true, 0, 0, false);
+ &QosNullLength, get_my_bssid(&pmlmeinfo->network), true, 0, 0, false);
rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex - TxDescLen], QosNullLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
@@ -502,6 +563,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
rtw_hal_mgnt_xmit(adapt, pmgntframe);
+ DBG_88E("%s: Set RSVD page location to Fw\n", __func__);
FillH2CCmd_88E(adapt, H2C_COM_RSVD_PAGE, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
exit:
@@ -510,35 +572,39 @@ exit:
void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
{
- struct hal_data_8188e *haldata = adapt->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- bool bSendBeacon = false;
- bool bcn_valid = false;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ bool bSendBeacon = false;
+ bool bcn_valid = false;
u8 DLBcnCount = 0;
u32 poll = 0;
+ DBG_88E("%s mstatus(%x)\n", __func__, mstatus);
+
if (mstatus == 1) {
/* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
/* Suggested by filen. Added by tynli. */
- usb_write16(adapt, REG_BCN_PSR_RPT, (0xC000 | pmlmeinfo->aid));
+ rtw_write16(adapt, REG_BCN_PSR_RPT, (0xC000 | pmlmeinfo->aid));
/* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
/* Set REG_CR bit 8. DMA beacon by SW. */
haldata->RegCR_1 |= BIT(0);
- usb_write8(adapt, REG_CR + 1, haldata->RegCR_1);
+ rtw_write8(adapt, REG_CR + 1, haldata->RegCR_1);
/* Disable Hw protection for a time which revserd for Hw sending beacon. */
/* Fix download reserved page packet fail that access collision with the protection time. */
/* 2010.05.11. Added by tynli. */
- usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) & (~BIT(3)));
- usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(4));
+ rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) & (~BIT(3)));
+ rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) | BIT(4));
- if (haldata->RegFwHwTxQCtrl & BIT(6))
+ if (haldata->RegFwHwTxQCtrl & BIT(6)) {
+ DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
bSendBeacon = true;
+ }
/* Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */
- usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl & (~BIT(6))));
+ rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl & (~BIT(6))));
haldata->RegFwHwTxQCtrl &= (~BIT(6));
/* Clear beacon valid check bit. */
@@ -558,6 +624,12 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
} while (!bcn_valid && (poll % 10) != 0 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped);
} while (!bcn_valid && DLBcnCount <= 100 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped);
+ if (adapt->bSurpriseRemoved || adapt->bDriverStopped)
+ ;
+ else if (!bcn_valid)
+ DBG_88E("%s: 1 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
+ else
+ DBG_88E("%s: 1 Download RSVD success! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
/* */
/* We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower) */
/* because we need to free the Tx BCN Desc which is used by the first reserved page packet. */
@@ -566,8 +638,8 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
/* */
/* Enable Bcn */
- usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(3));
- usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) & (~BIT(4)));
+ rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) | BIT(3));
+ rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) & (~BIT(4)));
/* To make sure that if there exists an adapter which would like to send beacon. */
/* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
@@ -575,17 +647,91 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
/* the beacon cannot be sent by HW. */
/* 2010.06.23. Added by tynli. */
if (bSendBeacon) {
- usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl | BIT(6)));
+ rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl | BIT(6)));
haldata->RegFwHwTxQCtrl |= BIT(6);
}
/* Update RSVD page location H2C to Fw. */
- if (bcn_valid)
+ if (bcn_valid) {
rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
+ DBG_88E("Set RSVD page location to Fw.\n");
+ }
/* Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */
/* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
haldata->RegCR_1 &= (~BIT(0));
- usb_write8(adapt, REG_CR + 1, haldata->RegCR_1);
+ rtw_write8(adapt, REG_CR + 1, haldata->RegCR_1);
}
+
+}
+
+void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state)
+{
+#ifdef CONFIG_88EU_P2P
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+ struct wifidirect_info *pwdinfo = &adapt->wdinfo;
+ struct P2P_PS_Offload_t *p2p_ps_offload = &haldata->p2p_ps_offload;
+ u8 i;
+
+ switch (p2p_ps_state) {
+ case P2P_PS_DISABLE:
+ DBG_88E("P2P_PS_DISABLE\n");
+ memset(p2p_ps_offload, 0, 1);
+ break;
+ case P2P_PS_ENABLE:
+ DBG_88E("P2P_PS_ENABLE\n");
+ /* update CTWindow value. */
+ if (pwdinfo->ctwindow > 0) {
+ p2p_ps_offload->CTWindow_En = 1;
+ rtw_write8(adapt, REG_P2P_CTWIN, pwdinfo->ctwindow);
+ }
+
+ /* hw only support 2 set of NoA */
+ for (i = 0; i < pwdinfo->noa_num; i++) {
+ /* To control the register setting for which NOA */
+ rtw_write8(adapt, REG_NOA_DESC_SEL, (i << 4));
+ if (i == 0)
+ p2p_ps_offload->NoA0_En = 1;
+ else
+ p2p_ps_offload->NoA1_En = 1;
+
+ /* config P2P NoA Descriptor Register */
+ rtw_write32(adapt, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
+ rtw_write32(adapt, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
+ rtw_write32(adapt, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
+ rtw_write8(adapt, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
+ }
+
+ if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
+ /* rst p2p circuit */
+ rtw_write8(adapt, REG_DUAL_TSF_RST, BIT(4));
+
+ p2p_ps_offload->Offload_En = 1;
+
+ if (pwdinfo->role == P2P_ROLE_GO) {
+ p2p_ps_offload->role = 1;
+ p2p_ps_offload->AllStaSleep = 0;
+ } else {
+ p2p_ps_offload->role = 0;
+ }
+
+ p2p_ps_offload->discovery = 0;
+ }
+ break;
+ case P2P_PS_SCAN:
+ DBG_88E("P2P_PS_SCAN\n");
+ p2p_ps_offload->discovery = 1;
+ break;
+ case P2P_PS_SCAN_DONE:
+ DBG_88E("P2P_PS_SCAN_DONE\n");
+ p2p_ps_offload->discovery = 0;
+ pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
+ break;
+ default:
+ break;
+ }
+
+ FillH2CCmd_88E(adapt, H2C_PS_P2P_OFFLOAD, 1, (u8 *)p2p_ps_offload);
+#endif
+
}
diff --git a/drivers/staging/r8188eu/hal/rtl8188e_dm.c b/drivers/staging/r8188eu/hal/rtl8188e_dm.c
new file mode 100644
index 000000000000..78552303c990
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/rtl8188e_dm.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+/* This file is for 92CE/92CU dynamic mechanism only */
+#define _RTL8188E_DM_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtl8188e_hal.h"
+
+static void dm_CheckStatistics(struct adapter *Adapter)
+{
+}
+
+/* Initialize GPIO setting registers */
+static void dm_InitGPIOSetting(struct adapter *Adapter)
+{
+ u8 tmp1byte;
+
+ tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG);
+ tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
+
+ rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
+}
+
+/* */
+/* functions */
+/* */
+static void Init_ODM_ComInfo_88E(struct adapter *Adapter)
+{
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &hal_data->dmpriv;
+ struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
+ u8 cut_ver, fab_ver;
+
+ /* Init Value */
+ memset(dm_odm, 0, sizeof(*dm_odm));
+
+ dm_odm->Adapter = Adapter;
+
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PLATFORM, ODM_CE);
+
+ if (Adapter->interface_type == RTW_GSPI)
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_INTERFACE, ODM_ITRF_SDIO);
+ else
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_INTERFACE, Adapter->interface_type);/* RTL871X_HCI_TYPE */
+
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8188E);
+
+ fab_ver = ODM_TSMC;
+ cut_ver = ODM_CUT_A;
+
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_FAB_VER, fab_ver);
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_CUT_VER, cut_ver);
+
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(hal_data->VersionID));
+
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PATCH_ID, hal_data->CustomerID);
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
+
+ if (hal_data->rf_type == RF_1T1R)
+ ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
+ else if (hal_data->rf_type == RF_2T2R)
+ ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
+ else if (hal_data->rf_type == RF_1T2R)
+ ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
+
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType);
+
+ pdmpriv->InitODMFlag = ODM_RF_CALIBRATION |
+ ODM_RF_TX_PWR_TRACK;
+
+ ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
+}
+
+static void Update_ODM_ComInfo_88E(struct adapter *Adapter)
+{
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+ struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+ struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
+ struct dm_priv *pdmpriv = &hal_data->dmpriv;
+ int i;
+
+ pdmpriv->InitODMFlag = ODM_BB_DIG |
+ ODM_BB_RA_MASK |
+ ODM_BB_DYNAMIC_TXPWR |
+ ODM_BB_FA_CNT |
+ ODM_BB_RSSI_MONITOR |
+ ODM_BB_CCK_PD |
+ ODM_BB_PWR_SAVE |
+ ODM_MAC_EDCA_TURBO |
+ ODM_RF_CALIBRATION |
+ ODM_RF_TX_PWR_TRACK;
+ if (hal_data->AntDivCfg)
+ pdmpriv->InitODMFlag |= ODM_BB_ANT_DIV;
+
+ if (Adapter->registrypriv.mp_mode == 1) {
+ pdmpriv->InitODMFlag = ODM_RF_CALIBRATION |
+ ODM_RF_TX_PWR_TRACK;
+ }
+
+ ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
+
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_TX_UNI, &Adapter->xmitpriv.tx_bytes);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_RX_UNI, &Adapter->recvpriv.rx_bytes);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_WM_MODE, &pmlmeext->cur_wireless_mode);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SEC_CHNL_OFFSET, &hal_data->nCur40MhzPrimeSC);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SEC_MODE, &Adapter->securitypriv.dot11PrivacyAlgrthm);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_BW, &hal_data->CurrentChannelBW);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_CHNL, &hal_data->CurrentChannel);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_NET_CLOSED, &Adapter->net_closed);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_MP_MODE, &Adapter->registrypriv.mp_mode);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SCAN, &pmlmepriv->bScanInProcess);
+ ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_POWER_SAVING, &pwrctrlpriv->bpower_saving);
+ ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType);
+
+ for (i = 0; i < NUM_STA; i++)
+ ODM_CmnInfoPtrArrayHook(dm_odm, ODM_CMNINFO_STA_STATUS, i, NULL);
+}
+
+void rtl8188e_InitHalDm(struct adapter *Adapter)
+{
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &hal_data->dmpriv;
+ struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
+
+ dm_InitGPIOSetting(Adapter);
+ pdmpriv->DM_Type = DM_Type_ByDriver;
+ pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
+ Update_ODM_ComInfo_88E(Adapter);
+ ODM_DMInit(dm_odm);
+ Adapter->fix_rate = 0xFF;
+}
+
+void rtl8188e_HalDmWatchDog(struct adapter *Adapter)
+{
+ bool fw_cur_in_ps = false;
+ bool fw_ps_awake = true;
+ u8 hw_init_completed = false;
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+
+
+ hw_init_completed = Adapter->hw_init_completed;
+
+ if (!hw_init_completed)
+ return;
+
+ fw_cur_in_ps = Adapter->pwrctrlpriv.bFwCurrentInPSMode;
+ rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&fw_ps_awake));
+
+ /* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */
+ /* modifed by thomas. 2011.06.11. */
+ if (Adapter->wdinfo.p2p_ps_mode)
+ fw_ps_awake = false;
+
+ if (hw_init_completed && ((!fw_cur_in_ps) && fw_ps_awake)) {
+ /* Calculate Tx/Rx statistics. */
+ dm_CheckStatistics(Adapter);
+
+
+ }
+
+ /* ODM */
+ if (hw_init_completed) {
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+ u8 bLinked = false;
+
+ if ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))) {
+ if (Adapter->stapriv.asoc_sta_count > 2)
+ bLinked = true;
+ } else {/* Station mode */
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ bLinked = true;
+ }
+
+ ODM_CmnInfoUpdate(&hal_data->odmpriv, ODM_CMNINFO_LINK, bLinked);
+ ODM_DMWatchdog(&hal_data->odmpriv);
+ }
+}
+
+void rtl8188e_init_dm_priv(struct adapter *Adapter)
+{
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &hal_data->dmpriv;
+
+ memset(pdmpriv, 0, sizeof(struct dm_priv));
+ Init_ODM_ComInfo_88E(Adapter);
+}
+
+void rtl8188e_deinit_dm_priv(struct adapter *Adapter)
+{
+}
+
+/* Add new function to reset the state of antenna diversity before link. */
+/* Compare RSSI for deciding antenna */
+void AntDivCompare8188E(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src)
+{
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+
+ if (0 != hal_data->AntDivCfg) {
+ /* select optimum_antenna for before linked =>For antenna diversity */
+ if (dst->Rssi >= src->Rssi) {/* keep org parameter */
+ src->Rssi = dst->Rssi;
+ src->PhyInfo.Optimum_antenna = dst->PhyInfo.Optimum_antenna;
+ }
+ }
+}
+
+/* Add new function to reset the state of antenna diversity before link. */
+u8 AntDivBeforeLink8188E(struct adapter *Adapter)
+{
+ struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+ struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
+ struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table;
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+
+ /* Condition that does not need to use antenna diversity. */
+ if (hal_data->AntDivCfg == 0)
+ return false;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ return false;
+
+ if (dm_swat_tbl->SWAS_NoLink_State == 0) {
+ /* switch channel */
+ dm_swat_tbl->SWAS_NoLink_State = 1;
+ dm_swat_tbl->CurAntenna = (dm_swat_tbl->CurAntenna == Antenna_A) ? Antenna_B : Antenna_A;
+
+ rtw_antenna_select_cmd(Adapter, dm_swat_tbl->CurAntenna, false);
+ return true;
+ } else {
+ dm_swat_tbl->SWAS_NoLink_State = 0;
+ return false;
+ }
+}
diff --git a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
new file mode 100644
index 000000000000..14758361960c
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
@@ -0,0 +1,2304 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _HAL_INIT_C_
+
+#include "../include/linux/firmware.h"
+#include "../include/drv_types.h"
+#include "../include/rtw_efuse.h"
+#include "../include/rtl8188e_hal.h"
+#include "../include/rtw_iol.h"
+#include "../include/usb_ops.h"
+
+static void iol_mode_enable(struct adapter *padapter, u8 enable)
+{
+ u8 reg_0xf0 = 0;
+
+ if (enable) {
+ /* Enable initial offload */
+ reg_0xf0 = rtw_read8(padapter, REG_SYS_CFG);
+ rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 | SW_OFFLOAD_EN);
+
+ if (!padapter->bFWReady) {
+ DBG_88E("bFWReady == false call reset 8051...\n");
+ _8051Reset88E(padapter);
+ }
+
+ } else {
+ /* disable initial offload */
+ reg_0xf0 = rtw_read8(padapter, REG_SYS_CFG);
+ rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 & ~SW_OFFLOAD_EN);
+ }
+}
+
+static s32 iol_execute(struct adapter *padapter, u8 control)
+{
+ s32 status = _FAIL;
+ u8 reg_0x88 = 0;
+ u32 start = 0, passing_time = 0;
+
+ control = control & 0x0f;
+ reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0);
+ rtw_write8(padapter, REG_HMEBOX_E0, reg_0x88 | control);
+
+ start = jiffies;
+ while ((reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0)) & control &&
+ (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
+ ;
+ }
+
+ reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0);
+ status = (reg_0x88 & control) ? _FAIL : _SUCCESS;
+ if (reg_0x88 & control << 4)
+ status = _FAIL;
+ return status;
+}
+
+static s32 iol_InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy)
+{
+ s32 rst = _SUCCESS;
+ iol_mode_enable(padapter, 1);
+ rtw_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy);
+ rst = iol_execute(padapter, CMD_INIT_LLT);
+ iol_mode_enable(padapter, 0);
+ return rst;
+}
+
+static void
+efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf)
+{
+ u8 *efuseTbl = NULL;
+ u8 rtemp8;
+ u16 eFuse_Addr = 0;
+ u8 offset, wren;
+ u16 i, j;
+ u16 **eFuseWord = NULL;
+ u16 efuse_utilized = 0;
+ u8 u1temp = 0;
+
+ efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
+ if (!efuseTbl) {
+ DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
+ goto exit;
+ }
+
+ eFuseWord = rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
+ if (!eFuseWord) {
+ DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
+ goto exit;
+ }
+
+ /* 0. Refresh efuse init map as all oxFF. */
+ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
+ for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
+ eFuseWord[i][j] = 0xFFFF;
+
+ /* */
+ /* 1. Read the first byte to check if efuse is empty!!! */
+ /* */
+ /* */
+ rtemp8 = *(phymap + eFuse_Addr);
+ if (rtemp8 != 0xFF) {
+ efuse_utilized++;
+ eFuse_Addr++;
+ } else {
+ DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8);
+ goto exit;
+ }
+
+ /* */
+ /* 2. Read real efuse content. Filter PG header and every section data. */
+ /* */
+ while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+ /* Check PG header for section num. */
+ if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */
+ u1temp = ((rtemp8 & 0xE0) >> 5);
+ rtemp8 = *(phymap + eFuse_Addr);
+ if ((rtemp8 & 0x0F) == 0x0F) {
+ eFuse_Addr++;
+ rtemp8 = *(phymap + eFuse_Addr);
+
+ if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
+ eFuse_Addr++;
+ continue;
+ } else {
+ offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
+ wren = (rtemp8 & 0x0F);
+ eFuse_Addr++;
+ }
+ } else {
+ offset = ((rtemp8 >> 4) & 0x0f);
+ wren = (rtemp8 & 0x0f);
+ }
+
+ if (offset < EFUSE_MAX_SECTION_88E) {
+ /* Get word enable value from PG header */
+ for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+ /* Check word enable condition in the section */
+ if (!(wren & 0x01)) {
+ rtemp8 = *(phymap + eFuse_Addr);
+ eFuse_Addr++;
+ efuse_utilized++;
+ eFuseWord[offset][i] = (rtemp8 & 0xff);
+ if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+ break;
+ rtemp8 = *(phymap + eFuse_Addr);
+ eFuse_Addr++;
+ efuse_utilized++;
+ eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
+
+ if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+ break;
+ }
+ wren >>= 1;
+ }
+ }
+ /* Read next PG header */
+ rtemp8 = *(phymap + eFuse_Addr);
+
+ if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+ efuse_utilized++;
+ eFuse_Addr++;
+ }
+ }
+
+ /* */
+ /* 3. Collect 16 sections and 4 word unit into Efuse map. */
+ /* */
+ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
+ for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
+ efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff);
+ efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff);
+ }
+ }
+
+ /* */
+ /* 4. Copy from Efuse map to output pointer memory!!! */
+ /* */
+ for (i = 0; i < _size_byte; i++)
+ pbuf[i] = efuseTbl[_offset + i];
+
+ /* */
+ /* 5. Calculate Efuse utilization. */
+ /* */
+
+exit:
+ kfree(efuseTbl);
+ kfree(eFuseWord);
+}
+
+static void efuse_read_phymap_from_txpktbuf(
+ struct adapter *adapter,
+ int bcnhead, /* beacon head, where FW store len(2-byte) and efuse physical map. */
+ u8 *content, /* buffer to store efuse physical map */
+ u16 *size /* for efuse content: the max byte to read. will update to byte read */
+ )
+{
+ u16 dbg_addr = 0;
+ u32 start = 0, passing_time = 0;
+ u8 reg_0x143 = 0;
+ __le32 lo32 = 0, hi32 = 0;
+ u16 len = 0, count = 0;
+ int i = 0;
+ u16 limit = *size;
+
+ u8 *pos = content;
+
+ if (bcnhead < 0) /* if not valid */
+ bcnhead = rtw_read8(adapter, REG_TDECTRL + 1);
+
+ DBG_88E("%s bcnhead:%d\n", __func__, bcnhead);
+
+ rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+
+ dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */
+
+ while (1) {
+ rtw_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr + i);
+
+ rtw_write8(adapter, REG_TXPKTBUF_DBG, 0);
+ start = jiffies;
+ while (!(reg_0x143 = rtw_read8(adapter, REG_TXPKTBUF_DBG)) &&
+ (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
+ DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, rtw_read8(adapter, 0x106));
+ rtw_usleep_os(100);
+ }
+
+ /* data from EEPROM needs to be in LE */
+ lo32 = cpu_to_le32(rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L));
+ hi32 = cpu_to_le32(rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H));
+
+ if (i == 0) {
+ /* Although lenc is only used in a debug statement,
+ * do not remove it as the rtw_read16() call consumes
+ * 2 bytes from the EEPROM source.
+ */
+ u16 lenc = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L);
+
+ len = le32_to_cpu(lo32) & 0x0000ffff;
+
+ limit = (len - 2 < limit) ? len - 2 : limit;
+
+ DBG_88E("%s len:%u, lenc:%u\n", __func__, len, lenc);
+
+ memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count);
+ count += (limit >= count + 2) ? 2 : limit - count;
+ pos = content + count;
+ } else {
+ memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count);
+ count += (limit >= count + 4) ? 4 : limit - count;
+ pos = content + count;
+ }
+
+ if (limit > count && len - 2 > count) {
+ memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count);
+ count += (limit >= count + 4) ? 4 : limit - count;
+ pos = content + count;
+ }
+
+ if (limit <= count || len - 2 <= count)
+ break;
+ i++;
+ }
+ rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
+ DBG_88E("%s read count:%u\n", __func__, count);
+ *size = count;
+}
+
+static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
+{
+ s32 status = _FAIL;
+ u8 physical_map[512];
+ u16 size = 512;
+
+ rtw_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy);
+ memset(physical_map, 0xFF, 512);
+ rtw_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+ status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
+ if (status == _SUCCESS)
+ efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
+ efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
+ return status;
+}
+
+s32 rtl8188e_iol_efuse_patch(struct adapter *padapter)
+{
+ s32 result = _SUCCESS;
+
+ DBG_88E("==> %s\n", __func__);
+ if (rtw_IOL_applied(padapter)) {
+ iol_mode_enable(padapter, 1);
+ result = iol_execute(padapter, CMD_READ_EFUSE_MAP);
+ if (result == _SUCCESS)
+ result = iol_execute(padapter, CMD_EFUSE_PATCH);
+
+ iol_mode_enable(padapter, 0);
+ }
+ return result;
+}
+
+static s32 iol_ioconfig(struct adapter *padapter, u8 iocfg_bndy)
+{
+ s32 rst = _SUCCESS;
+
+ rtw_write8(padapter, REG_TDECTRL + 1, iocfg_bndy);
+ rst = iol_execute(padapter, CMD_IOCONFIG);
+ return rst;
+}
+
+static int rtl8188e_IOL_exec_cmds_sync(struct adapter *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
+{
+ struct pkt_attrib *pattrib = &xmit_frame->attrib;
+ u8 i;
+ int ret = _FAIL;
+
+ if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS)
+ goto exit;
+ if (rtw_usb_bulk_size_boundary(adapter, TXDESC_SIZE + pattrib->last_txcmdsz)) {
+ if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS)
+ goto exit;
+ }
+
+ dump_mgntframe_and_wait(adapter, xmit_frame, max_wating_ms);
+
+ iol_mode_enable(adapter, 1);
+ for (i = 0; i < bndy_cnt; i++) {
+ u8 page_no = 0;
+ page_no = i * 2;
+ ret = iol_ioconfig(adapter, page_no);
+ if (ret != _SUCCESS)
+ break;
+ }
+ iol_mode_enable(adapter, 0);
+exit:
+ /* restore BCN_HEAD */
+ rtw_write8(adapter, REG_TDECTRL + 1, 0);
+ return ret;
+}
+
+void rtw_IOL_cmd_tx_pkt_buf_dump(struct adapter *Adapter, int data_len)
+{
+ u32 fifo_data, reg_140;
+ u32 addr, rstatus, loop = 0;
+ u16 data_cnts = (data_len / 8) + 1;
+ u8 *pbuf = vzalloc(data_len + 10);
+ DBG_88E("###### %s ######\n", __func__);
+
+ rtw_write8(Adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+ if (pbuf) {
+ for (addr = 0; addr < data_cnts; addr++) {
+ rtw_write32(Adapter, 0x140, addr);
+ rtw_usleep_os(2);
+ loop = 0;
+ do {
+ rstatus = (reg_140 = rtw_read32(Adapter, REG_PKTBUF_DBG_CTRL) & BIT(24));
+ if (rstatus) {
+ fifo_data = rtw_read32(Adapter, REG_PKTBUF_DBG_DATA_L);
+ memcpy(pbuf + (addr * 8), &fifo_data, 4);
+
+ fifo_data = rtw_read32(Adapter, REG_PKTBUF_DBG_DATA_H);
+ memcpy(pbuf + (addr * 8 + 4), &fifo_data, 4);
+ }
+ rtw_usleep_os(2);
+ } while (!rstatus && (loop++ < 10));
+ }
+ rtw_IOL_cmd_buf_dump(Adapter, data_len, pbuf);
+ vfree(pbuf);
+ }
+ DBG_88E("###### %s ######\n", __func__);
+}
+
+static void _FWDownloadEnable(struct adapter *padapter, bool enable)
+{
+ u8 tmp;
+
+ if (enable) {
+ /* MCU firmware download enable. */
+ tmp = rtw_read8(padapter, REG_MCUFWDL);
+ rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01);
+
+ /* 8051 reset */
+ tmp = rtw_read8(padapter, REG_MCUFWDL + 2);
+ rtw_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7);
+ } else {
+ /* MCU firmware download disable. */
+ tmp = rtw_read8(padapter, REG_MCUFWDL);
+ rtw_write8(padapter, REG_MCUFWDL, tmp & 0xfe);
+
+ /* Reserved for fw extension. */
+ rtw_write8(padapter, REG_MCUFWDL + 1, 0x00);
+ }
+}
+
+#define MAX_REG_BOLCK_SIZE 196
+
+static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
+{
+ int ret = _SUCCESS;
+ u32 blockSize_p1 = 4; /* (Default) Phase #1 : PCI muse use 4-byte write to download FW */
+ u32 blockSize_p2 = 8; /* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
+ u32 blockSize_p3 = 1; /* Phase #3 : Use 1-byte, the remnant of FW image. */
+ u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
+ u32 remainSize_p1 = 0, remainSize_p2 = 0;
+ u8 *bufferPtr = (u8 *)buffer;
+ u32 i = 0, offset = 0;
+
+ blockSize_p1 = MAX_REG_BOLCK_SIZE;
+
+ /* 3 Phase #1 */
+ blockCount_p1 = buffSize / blockSize_p1;
+ remainSize_p1 = buffSize % blockSize_p1;
+
+ for (i = 0; i < blockCount_p1; i++) {
+ ret = rtw_writeN(padapter, (FW_8188E_START_ADDRESS + i * blockSize_p1), blockSize_p1, (bufferPtr + i * blockSize_p1));
+ if (ret == _FAIL)
+ goto exit;
+ }
+
+ /* 3 Phase #2 */
+ if (remainSize_p1) {
+ offset = blockCount_p1 * blockSize_p1;
+
+ blockCount_p2 = remainSize_p1 / blockSize_p2;
+ remainSize_p2 = remainSize_p1 % blockSize_p2;
+
+ for (i = 0; i < blockCount_p2; i++) {
+ ret = rtw_writeN(padapter, (FW_8188E_START_ADDRESS + offset + i * blockSize_p2), blockSize_p2, (bufferPtr + offset + i * blockSize_p2));
+
+ if (ret == _FAIL)
+ goto exit;
+ }
+ }
+
+ /* 3 Phase #3 */
+ if (remainSize_p2) {
+ offset = (blockCount_p1 * blockSize_p1) + (blockCount_p2 * blockSize_p2);
+
+ blockCount_p3 = remainSize_p2 / blockSize_p3;
+
+ for (i = 0; i < blockCount_p3; i++) {
+ ret = rtw_write8(padapter, (FW_8188E_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
+
+ if (ret == _FAIL)
+ goto exit;
+ }
+ }
+
+exit:
+ return ret;
+}
+
+static int _PageWrite(struct adapter *padapter, u32 page, void *buffer, u32 size)
+{
+ u8 value8;
+ u8 u8Page = (u8)(page & 0x07);
+
+ value8 = (rtw_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page;
+ rtw_write8(padapter, REG_MCUFWDL + 2, value8);
+
+ return _BlockWrite(padapter, buffer, size);
+}
+
+static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
+{
+ /* Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. */
+ /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
+ int ret = _SUCCESS;
+ u32 pageNums, remainSize;
+ u32 page, offset;
+ u8 *bufferPtr = (u8 *)buffer;
+
+ pageNums = size / MAX_PAGE_SIZE;
+ remainSize = size % MAX_PAGE_SIZE;
+
+ for (page = 0; page < pageNums; page++) {
+ offset = page * MAX_PAGE_SIZE;
+ ret = _PageWrite(padapter, page, bufferPtr + offset, MAX_PAGE_SIZE);
+
+ if (ret == _FAIL)
+ goto exit;
+ }
+ if (remainSize) {
+ offset = pageNums * MAX_PAGE_SIZE;
+ page = pageNums;
+ ret = _PageWrite(padapter, page, bufferPtr + offset, remainSize);
+
+ if (ret == _FAIL)
+ goto exit;
+ }
+exit:
+ return ret;
+}
+
+void _8051Reset88E(struct adapter *padapter)
+{
+ u8 u1bTmp;
+
+ u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
+ rtw_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp & (~BIT(2)));
+ rtw_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp | (BIT(2)));
+ DBG_88E("=====> _8051Reset88E(): 8051 reset success .\n");
+}
+
+static s32 _FWFreeToGo(struct adapter *padapter)
+{
+ u32 counter = 0;
+ u32 value32;
+
+ /* polling CheckSum report */
+ do {
+ value32 = rtw_read32(padapter, REG_MCUFWDL);
+ if (value32 & FWDL_ChkSum_rpt)
+ break;
+ } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
+
+ if (counter >= POLLING_READY_TIMEOUT_COUNT) {
+ DBG_88E("%s: chksum report fail! REG_MCUFWDL:0x%08x\n", __func__, value32);
+ return _FAIL;
+ }
+ DBG_88E("%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__, value32);
+
+ value32 = rtw_read32(padapter, REG_MCUFWDL);
+ value32 |= MCUFWDL_RDY;
+ value32 &= ~WINTINI_RDY;
+ rtw_write32(padapter, REG_MCUFWDL, value32);
+
+ _8051Reset88E(padapter);
+
+ /* polling for FW ready */
+ counter = 0;
+ do {
+ value32 = rtw_read32(padapter, REG_MCUFWDL);
+ if (value32 & WINTINI_RDY) {
+ DBG_88E("%s: Polling FW ready success!! REG_MCUFWDL:0x%08x\n", __func__, value32);
+ return _SUCCESS;
+ }
+ udelay(5);
+ } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
+
+ DBG_88E("%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n", __func__, value32);
+ return _FAIL;
+}
+
+#define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
+
+static int load_firmware(struct rt_firmware *pFirmware, struct device *device)
+{
+ s32 rtStatus = _SUCCESS;
+ const struct firmware *fw;
+ const char *fw_name = "rtlwifi/rtl8188eufw.bin";
+ int err = request_firmware(&fw, fw_name, device);
+
+ if (err) {
+ pr_err("Request firmware failed with error 0x%x\n", err);
+ rtStatus = _FAIL;
+ goto Exit;
+ }
+ if (!fw) {
+ pr_err("Firmware %s not available\n", fw_name);
+ rtStatus = _FAIL;
+ goto Exit;
+ }
+ if (fw->size > FW_8188E_SIZE) {
+ rtStatus = _FAIL;
+ goto Exit;
+ }
+
+ pFirmware->szFwBuffer = kzalloc(FW_8188E_SIZE, GFP_KERNEL);
+ if (!pFirmware->szFwBuffer) {
+ pr_err("Failed to allocate pFirmware->szFwBuffer\n");
+ rtStatus = _FAIL;
+ goto Exit;
+ }
+ memcpy(pFirmware->szFwBuffer, fw->data, fw->size);
+ pFirmware->ulFwLength = fw->size;
+ release_firmware(fw);
+ DBG_88E_LEVEL(_drv_info_, "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__, pFirmware->ulFwLength);
+
+Exit:
+ return rtStatus;
+}
+
+s32 rtl8188e_FirmwareDownload(struct adapter *padapter)
+{
+ s32 rtStatus = _SUCCESS;
+ u8 writeFW_retry = 0;
+ u32 fwdl_start_time;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+ struct device *device = dvobj_to_dev(dvobj);
+ struct rt_firmware_hdr *pFwHdr = NULL;
+ u8 *pFirmwareBuf;
+ u32 FirmwareLen;
+ static int log_version;
+
+ if (!dvobj->firmware.szFwBuffer)
+ rtStatus = load_firmware(&dvobj->firmware, device);
+ if (rtStatus == _FAIL) {
+ dvobj->firmware.szFwBuffer = NULL;
+ goto Exit;
+ }
+ pFirmwareBuf = dvobj->firmware.szFwBuffer;
+ FirmwareLen = dvobj->firmware.ulFwLength;
+
+ /* To Check Fw header. Added by tynli. 2009.12.04. */
+ pFwHdr = (struct rt_firmware_hdr *)dvobj->firmware.szFwBuffer;
+
+ pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version);
+ pHalData->FirmwareSubVersion = pFwHdr->Subversion;
+ pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature);
+
+ if (!log_version++)
+ pr_info("%sFirmware Version %d, SubVersion %d, Signature 0x%x\n",
+ DRIVER_PREFIX, pHalData->FirmwareVersion,
+ pHalData->FirmwareSubVersion, pHalData->FirmwareSignature);
+
+ if (IS_FW_HEADER_EXIST(pFwHdr)) {
+ /* Shift 32 bytes for FW header */
+ pFirmwareBuf = pFirmwareBuf + 32;
+ FirmwareLen = FirmwareLen - 32;
+ }
+
+ /* Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */
+ /* or it will cause download Fw fail. 2010.02.01. by tynli. */
+ if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
+ rtw_write8(padapter, REG_MCUFWDL, 0x00);
+ _8051Reset88E(padapter);
+ }
+
+ _FWDownloadEnable(padapter, true);
+ fwdl_start_time = jiffies;
+ while (1) {
+ /* reset the FWDL chksum */
+ rtw_write8(padapter, REG_MCUFWDL, rtw_read8(padapter, REG_MCUFWDL) | FWDL_ChkSum_rpt);
+
+ rtStatus = _WriteFW(padapter, pFirmwareBuf, FirmwareLen);
+
+ if (rtStatus == _SUCCESS ||
+ (rtw_get_passing_time_ms(fwdl_start_time) > 500 && writeFW_retry++ >= 3))
+ break;
+
+ DBG_88E("%s writeFW_retry:%u, time after fwdl_start_time:%ums\n",
+ __func__, writeFW_retry, rtw_get_passing_time_ms(fwdl_start_time)
+ );
+ }
+ _FWDownloadEnable(padapter, false);
+ if (_SUCCESS != rtStatus) {
+ DBG_88E("DL Firmware failed!\n");
+ goto Exit;
+ }
+
+ rtStatus = _FWFreeToGo(padapter);
+ if (_SUCCESS != rtStatus) {
+ DBG_88E("DL Firmware failed!\n");
+ goto Exit;
+ }
+
+Exit:
+ return rtStatus;
+}
+
+void rtl8188e_InitializeFirmwareVars(struct adapter *padapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+
+ /* Init Fw LPS related. */
+ padapter->pwrctrlpriv.bFwCurrentInPSMode = false;
+
+ /* Init H2C counter. by tynli. 2009.12.09. */
+ pHalData->LastHMEBoxNum = 0;
+}
+
+static void rtl8188e_free_hal_data(struct adapter *padapter)
+{
+
+ kfree(padapter->HalData);
+ padapter->HalData = NULL;
+
+}
+
+/* */
+/* Efuse related code */
+/* */
+enum{
+ VOLTAGE_V25 = 0x03,
+ LDOE25_SHIFT = 28,
+ };
+
+static bool
+hal_EfusePgPacketWrite2ByteHeader(
+ struct adapter *pAdapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt *pTargetPkt,
+ bool bPseudoTest);
+static bool
+hal_EfusePgPacketWrite1ByteHeader(
+ struct adapter *pAdapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt *pTargetPkt,
+ bool bPseudoTest);
+static bool
+hal_EfusePgPacketWriteData(
+ struct adapter *pAdapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt *pTargetPkt,
+ bool bPseudoTest);
+
+static void
+hal_EfusePowerSwitch_RTL8188E(
+ struct adapter *pAdapter,
+ u8 bWrite,
+ u8 PwrState)
+{
+ u8 tempval;
+ u16 tmpV16;
+
+ if (PwrState) {
+ rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
+
+ /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
+ tmpV16 = rtw_read16(pAdapter, REG_SYS_ISO_CTRL);
+ if (!(tmpV16 & PWC_EV12V)) {
+ tmpV16 |= PWC_EV12V;
+ rtw_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
+ }
+ /* Reset: 0x0000h[28], default valid */
+ tmpV16 = rtw_read16(pAdapter, REG_SYS_FUNC_EN);
+ if (!(tmpV16 & FEN_ELDR)) {
+ tmpV16 |= FEN_ELDR;
+ rtw_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
+ }
+
+ /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
+ tmpV16 = rtw_read16(pAdapter, REG_SYS_CLKR);
+ if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
+ tmpV16 |= (LOADER_CLK_EN | ANA8M);
+ rtw_write16(pAdapter, REG_SYS_CLKR, tmpV16);
+ }
+
+ if (bWrite) {
+ /* Enable LDO 2.5V before read/write action */
+ tempval = rtw_read8(pAdapter, EFUSE_TEST + 3);
+ tempval &= 0x0F;
+ tempval |= (VOLTAGE_V25 << 4);
+ rtw_write8(pAdapter, EFUSE_TEST + 3, (tempval | 0x80));
+ }
+ } else {
+ rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
+
+ if (bWrite) {
+ /* Disable LDO 2.5V after read/write action */
+ tempval = rtw_read8(pAdapter, EFUSE_TEST + 3);
+ rtw_write8(pAdapter, EFUSE_TEST + 3, (tempval & 0x7F));
+ }
+ }
+}
+
+static void
+rtl8188e_EfusePowerSwitch(
+ struct adapter *pAdapter,
+ u8 bWrite,
+ u8 PwrState)
+{
+ hal_EfusePowerSwitch_RTL8188E(pAdapter, bWrite, PwrState);
+}
+
+static void Hal_EfuseReadEFuse88E(struct adapter *Adapter,
+ u16 _offset,
+ u16 _size_byte,
+ u8 *pbuf,
+ bool bPseudoTest
+ )
+{
+ u8 *efuseTbl = NULL;
+ u8 rtemp8[1];
+ u16 eFuse_Addr = 0;
+ u8 offset, wren;
+ u16 i, j;
+ u16 **eFuseWord = NULL;
+ u16 efuse_utilized = 0;
+ u8 u1temp = 0;
+
+ /* */
+ /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
+ /* */
+ if ((_offset + _size_byte) > EFUSE_MAP_LEN_88E) {/* total E-Fuse table is 512bytes */
+ DBG_88E("Hal_EfuseReadEFuse88E(): Invalid offset(%#x) with read bytes(%#x)!!\n", _offset, _size_byte);
+ goto exit;
+ }
+
+ efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
+ if (!efuseTbl) {
+ DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
+ goto exit;
+ }
+
+ eFuseWord = rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
+ if (!eFuseWord) {
+ DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
+ goto exit;
+ }
+
+ /* 0. Refresh efuse init map as all oxFF. */
+ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
+ for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
+ eFuseWord[i][j] = 0xFFFF;
+
+ /* */
+ /* 1. Read the first byte to check if efuse is empty!!! */
+ /* */
+ /* */
+ ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
+ if (*rtemp8 != 0xFF) {
+ efuse_utilized++;
+ eFuse_Addr++;
+ } else {
+ DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, *rtemp8);
+ goto exit;
+ }
+
+ /* */
+ /* 2. Read real efuse content. Filter PG header and every section data. */
+ /* */
+ while ((*rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+ /* Check PG header for section num. */
+ if ((*rtemp8 & 0x1F) == 0x0F) { /* extended header */
+ u1temp = ((*rtemp8 & 0xE0) >> 5);
+
+ ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
+
+ if ((*rtemp8 & 0x0F) == 0x0F) {
+ eFuse_Addr++;
+ ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
+
+ if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
+ eFuse_Addr++;
+ continue;
+ } else {
+ offset = ((*rtemp8 & 0xF0) >> 1) | u1temp;
+ wren = (*rtemp8 & 0x0F);
+ eFuse_Addr++;
+ }
+ } else {
+ offset = ((*rtemp8 >> 4) & 0x0f);
+ wren = (*rtemp8 & 0x0f);
+ }
+
+ if (offset < EFUSE_MAX_SECTION_88E) {
+ /* Get word enable value from PG header */
+
+ for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+ /* Check word enable condition in the section */
+ if (!(wren & 0x01)) {
+ ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
+ eFuse_Addr++;
+ efuse_utilized++;
+ eFuseWord[offset][i] = (*rtemp8 & 0xff);
+ if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+ break;
+ ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
+ eFuse_Addr++;
+ efuse_utilized++;
+ eFuseWord[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00);
+ if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+ break;
+ }
+ wren >>= 1;
+ }
+ }
+
+ /* Read next PG header */
+ ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
+
+ if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+ efuse_utilized++;
+ eFuse_Addr++;
+ }
+ }
+
+ /* 3. Collect 16 sections and 4 word unit into Efuse map. */
+ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
+ for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
+ efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff);
+ efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff);
+ }
+ }
+
+ /* 4. Copy from Efuse map to output pointer memory!!! */
+ for (i = 0; i < _size_byte; i++)
+ pbuf[i] = efuseTbl[_offset + i];
+
+ /* 5. Calculate Efuse utilization. */
+ rtw_hal_set_hwreg(Adapter, HW_VAR_EFUSE_BYTES, (u8 *)&eFuse_Addr);
+
+exit:
+ kfree(efuseTbl);
+ kfree(eFuseWord);
+}
+
+static void ReadEFuseByIC(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest)
+{
+ if (!bPseudoTest) {
+ int ret = _FAIL;
+ if (rtw_IOL_applied(Adapter)) {
+ rtw_hal_power_on(Adapter);
+
+ iol_mode_enable(Adapter, 1);
+ ret = iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
+ iol_mode_enable(Adapter, 0);
+
+ if (_SUCCESS == ret)
+ goto exit;
+ }
+ }
+ Hal_EfuseReadEFuse88E(Adapter, _offset, _size_byte, pbuf, bPseudoTest);
+
+exit:
+ return;
+}
+
+static void ReadEFuse_Pseudo(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest)
+{
+ Hal_EfuseReadEFuse88E(Adapter, _offset, _size_byte, pbuf, bPseudoTest);
+}
+
+static void rtl8188e_ReadEFuse(struct adapter *Adapter, u8 efuseType,
+ u16 _offset, u16 _size_byte, u8 *pbuf,
+ bool bPseudoTest)
+{
+ if (bPseudoTest)
+ ReadEFuse_Pseudo(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
+ else
+ ReadEFuseByIC(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
+}
+
+/* Do not support BT */
+static void Hal_EFUSEGetEfuseDefinition88E(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
+{
+ switch (type) {
+ case TYPE_EFUSE_MAX_SECTION:
+ {
+ u8 *pMax_section;
+ pMax_section = (u8 *)pOut;
+ *pMax_section = EFUSE_MAX_SECTION_88E;
+ }
+ break;
+ case TYPE_EFUSE_REAL_CONTENT_LEN:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
+ }
+ break;
+ case TYPE_EFUSE_CONTENT_LEN_BANK:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
+ }
+ break;
+ case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E);
+ }
+ break;
+ case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E);
+ }
+ break;
+ case TYPE_EFUSE_MAP_LEN:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
+ }
+ break;
+ case TYPE_EFUSE_PROTECT_BYTES_BANK:
+ {
+ u8 *pu1Tmp;
+ pu1Tmp = (u8 *)pOut;
+ *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
+ }
+ break;
+ default:
+ {
+ u8 *pu1Tmp;
+ pu1Tmp = (u8 *)pOut;
+ *pu1Tmp = 0;
+ }
+ break;
+ }
+}
+
+static void Hal_EFUSEGetEfuseDefinition_Pseudo88E(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
+{
+ switch (type) {
+ case TYPE_EFUSE_MAX_SECTION:
+ {
+ u8 *pMax_section;
+ pMax_section = (u8 *)pOut;
+ *pMax_section = EFUSE_MAX_SECTION_88E;
+ }
+ break;
+ case TYPE_EFUSE_REAL_CONTENT_LEN:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
+ }
+ break;
+ case TYPE_EFUSE_CONTENT_LEN_BANK:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
+ }
+ break;
+ case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E);
+ }
+ break;
+ case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E);
+ }
+ break;
+ case TYPE_EFUSE_MAP_LEN:
+ {
+ u16 *pu2Tmp;
+ pu2Tmp = (u16 *)pOut;
+ *pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
+ }
+ break;
+ case TYPE_EFUSE_PROTECT_BYTES_BANK:
+ {
+ u8 *pu1Tmp;
+ pu1Tmp = (u8 *)pOut;
+ *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
+ }
+ break;
+ default:
+ {
+ u8 *pu1Tmp;
+ pu1Tmp = (u8 *)pOut;
+ *pu1Tmp = 0;
+ }
+ break;
+ }
+}
+
+static void rtl8188e_EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest)
+{
+ if (bPseudoTest)
+ Hal_EFUSEGetEfuseDefinition_Pseudo88E(pAdapter, efuseType, type, pOut);
+ else
+ Hal_EFUSEGetEfuseDefinition88E(pAdapter, efuseType, type, pOut);
+}
+
+static u8 Hal_EfuseWordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
+{
+ u16 tmpaddr = 0;
+ u16 start_addr = efuse_addr;
+ u8 badworden = 0x0F;
+ u8 tmpdata[8];
+
+ memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
+
+ if (!(word_en & BIT(0))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(pAdapter, start_addr++, data[0], bPseudoTest);
+ efuse_OneByteWrite(pAdapter, start_addr++, data[1], bPseudoTest);
+
+ efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0], bPseudoTest);
+ efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[1], bPseudoTest);
+ if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
+ badworden &= (~BIT(0));
+ }
+ if (!(word_en & BIT(1))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(pAdapter, start_addr++, data[2], bPseudoTest);
+ efuse_OneByteWrite(pAdapter, start_addr++, data[3], bPseudoTest);
+
+ efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2], bPseudoTest);
+ efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[3], bPseudoTest);
+ if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
+ badworden &= (~BIT(1));
+ }
+ if (!(word_en & BIT(2))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(pAdapter, start_addr++, data[4], bPseudoTest);
+ efuse_OneByteWrite(pAdapter, start_addr++, data[5], bPseudoTest);
+
+ efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4], bPseudoTest);
+ efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[5], bPseudoTest);
+ if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
+ badworden &= (~BIT(2));
+ }
+ if (!(word_en & BIT(3))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(pAdapter, start_addr++, data[6], bPseudoTest);
+ efuse_OneByteWrite(pAdapter, start_addr++, data[7], bPseudoTest);
+
+ efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6], bPseudoTest);
+ efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[7], bPseudoTest);
+ if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
+ badworden &= (~BIT(3));
+ }
+ return badworden;
+}
+
+static u8 Hal_EfuseWordEnableDataWrite_Pseudo(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
+{
+ u8 ret;
+
+ ret = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest);
+ return ret;
+}
+
+static u8 rtl8188e_Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
+{
+ u8 ret = 0;
+
+ if (bPseudoTest)
+ ret = Hal_EfuseWordEnableDataWrite_Pseudo(pAdapter, efuse_addr, word_en, data, bPseudoTest);
+ else
+ ret = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest);
+ return ret;
+}
+
+static u16 hal_EfuseGetCurrentSize_8188e(struct adapter *pAdapter, bool bPseudoTest)
+{
+ int bContinual = true;
+ u16 efuse_addr = 0;
+ u8 hoffset = 0, hworden = 0;
+ u8 efuse_data, word_cnts = 0;
+
+ if (bPseudoTest)
+ efuse_addr = (u16)(fakeEfuseUsedBytes);
+ else
+ rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
+
+ while (bContinual &&
+ efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest) &&
+ AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+ if (efuse_data != 0xFF) {
+ if ((efuse_data & 0x1F) == 0x0F) { /* extended header */
+ hoffset = efuse_data;
+ efuse_addr++;
+ efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest);
+ if ((efuse_data & 0x0F) == 0x0F) {
+ efuse_addr++;
+ continue;
+ } else {
+ hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+ hworden = efuse_data & 0x0F;
+ }
+ } else {
+ hoffset = (efuse_data >> 4) & 0x0F;
+ hworden = efuse_data & 0x0F;
+ }
+ word_cnts = Efuse_CalculateWordCnts(hworden);
+ /* read next header */
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
+ } else {
+ bContinual = false;
+ }
+ }
+
+ if (bPseudoTest)
+ fakeEfuseUsedBytes = efuse_addr;
+ else
+ rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
+
+ return efuse_addr;
+}
+
+static u16 Hal_EfuseGetCurrentSize_Pseudo(struct adapter *pAdapter, bool bPseudoTest)
+{
+ u16 ret = 0;
+
+ ret = hal_EfuseGetCurrentSize_8188e(pAdapter, bPseudoTest);
+ return ret;
+}
+
+static u16 rtl8188e_EfuseGetCurrentSize(struct adapter *pAdapter, u8 efuseType, bool bPseudoTest)
+{
+ u16 ret = 0;
+
+ if (bPseudoTest)
+ ret = Hal_EfuseGetCurrentSize_Pseudo(pAdapter, bPseudoTest);
+ else
+ ret = hal_EfuseGetCurrentSize_8188e(pAdapter, bPseudoTest);
+ return ret;
+}
+
+static int hal_EfusePgPacketRead_8188e(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
+{
+ u8 ReadState = PG_STATE_HEADER;
+ int bContinual = true;
+ int bDataEmpty = true;
+ u8 efuse_data, word_cnts = 0;
+ u16 efuse_addr = 0;
+ u8 hoffset = 0, hworden = 0;
+ u8 tmpidx = 0;
+ u8 tmpdata[8];
+ u8 max_section = 0;
+ u8 tmp_header = 0;
+
+ EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section, bPseudoTest);
+
+ if (!data)
+ return false;
+ if (offset > max_section)
+ return false;
+
+ memset((void *)data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
+ memset((void *)tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
+
+ /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
+ /* Skip dummy parts to prevent unexpected data read from Efuse. */
+ /* By pass right now. 2009.02.19. */
+ while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+ /* Header Read ------------- */
+ if (ReadState & PG_STATE_HEADER) {
+ if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
+ if (EXT_HEADER(efuse_data)) {
+ tmp_header = efuse_data;
+ efuse_addr++;
+ efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest);
+ if (!ALL_WORDS_DISABLED(efuse_data)) {
+ hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+ hworden = efuse_data & 0x0F;
+ } else {
+ DBG_88E("Error, All words disabled\n");
+ efuse_addr++;
+ continue;
+ }
+ } else {
+ hoffset = (efuse_data >> 4) & 0x0F;
+ hworden = efuse_data & 0x0F;
+ }
+ word_cnts = Efuse_CalculateWordCnts(hworden);
+ bDataEmpty = true;
+
+ if (hoffset == offset) {
+ for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) {
+ if (efuse_OneByteRead(pAdapter, efuse_addr + 1 + tmpidx, &efuse_data, bPseudoTest)) {
+ tmpdata[tmpidx] = efuse_data;
+ if (efuse_data != 0xff)
+ bDataEmpty = false;
+ }
+ }
+ if (!bDataEmpty) {
+ ReadState = PG_STATE_DATA;
+ } else {/* read next header */
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
+ ReadState = PG_STATE_HEADER;
+ }
+ } else {/* read next header */
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
+ ReadState = PG_STATE_HEADER;
+ }
+ } else {
+ bContinual = false;
+ }
+ } else if (ReadState & PG_STATE_DATA) {
+ /* Data section Read ------------- */
+ efuse_WordEnableDataRead(hworden, tmpdata, data);
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
+ ReadState = PG_STATE_HEADER;
+ }
+
+ }
+
+ if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) &&
+ (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff))
+ return false;
+ else
+ return true;
+}
+
+static int Hal_EfusePgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
+{
+ int ret;
+
+ ret = hal_EfusePgPacketRead_8188e(pAdapter, offset, data, bPseudoTest);
+ return ret;
+}
+
+static int Hal_EfusePgPacketRead_Pseudo(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
+{
+ int ret;
+
+ ret = hal_EfusePgPacketRead_8188e(pAdapter, offset, data, bPseudoTest);
+ return ret;
+}
+
+static int rtl8188e_Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
+{
+ int ret;
+
+ if (bPseudoTest)
+ ret = Hal_EfusePgPacketRead_Pseudo(pAdapter, offset, data, bPseudoTest);
+ else
+ ret = Hal_EfusePgPacketRead(pAdapter, offset, data, bPseudoTest);
+ return ret;
+}
+
+static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr, bool bPseudoTest)
+{
+ u8 originaldata[8], badworden = 0;
+ u16 efuse_addr = *pAddr;
+ u32 PgWriteSuccess = 0;
+
+ memset((void *)originaldata, 0xff, 8);
+
+ if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata, bPseudoTest)) {
+ /* check if data exist */
+ badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pFixPkt->word_en, originaldata, bPseudoTest);
+
+ if (badworden != 0xf) { /* write fail */
+ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata, bPseudoTest);
+
+ if (!PgWriteSuccess)
+ return false;
+ else
+ efuse_addr = Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest);
+ } else {
+ efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1;
+ }
+ } else {
+ efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1;
+ }
+ *pAddr = efuse_addr;
+ return true;
+}
+
+static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
+{
+ bool bRet = false;
+ u16 efuse_addr = *pAddr, efuse_max_available_len = 0;
+ u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
+ u8 repeatcnt = 0;
+
+ EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len, bPseudoTest);
+
+ while (efuse_addr < efuse_max_available_len) {
+ pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
+
+ while (tmp_header == 0xFF) {
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
+ }
+
+ /* to write ext_header */
+ if (tmp_header == pg_header) {
+ efuse_addr++;
+ pg_header_temp = pg_header;
+ pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
+
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
+
+ while (tmp_header == 0xFF) {
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
+ }
+
+ if ((tmp_header & 0x0F) == 0x0F) { /* word_en PG fail */
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
+ return false;
+ } else {
+ efuse_addr++;
+ continue;
+ }
+ } else if (pg_header != tmp_header) { /* offset PG fail */
+ struct pgpkt fixPkt;
+ fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
+ fixPkt.word_en = tmp_header & 0x0F;
+ fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
+ if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr, bPseudoTest))
+ return false;
+ } else {
+ bRet = true;
+ break;
+ }
+ } else if ((tmp_header & 0x1F) == 0x0F) { /* wrong extended header */
+ efuse_addr += 2;
+ continue;
+ }
+ }
+
+ *pAddr = efuse_addr;
+ return bRet;
+}
+
+static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
+{
+ bool bRet = false;
+ u8 pg_header = 0, tmp_header = 0;
+ u16 efuse_addr = *pAddr;
+ u8 repeatcnt = 0;
+
+ pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
+
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
+
+ while (tmp_header == 0xFF) {
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
+ }
+
+ if (pg_header == tmp_header) {
+ bRet = true;
+ } else {
+ struct pgpkt fixPkt;
+ fixPkt.offset = (tmp_header >> 4) & 0x0F;
+ fixPkt.word_en = tmp_header & 0x0F;
+ fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
+ if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr, bPseudoTest))
+ return false;
+ }
+
+ *pAddr = efuse_addr;
+ return bRet;
+}
+
+static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
+{
+ u16 efuse_addr = *pAddr;
+ u8 badworden = 0;
+ u32 PgWriteSuccess = 0;
+
+ badworden = 0x0f;
+ badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest);
+ if (badworden == 0x0F) {
+ /* write ok */
+ return true;
+ } else {
+ /* reorganize other pg packet */
+ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
+ if (!PgWriteSuccess)
+ return false;
+ else
+ return true;
+ }
+}
+
+static bool
+hal_EfusePgPacketWriteHeader(
+ struct adapter *pAdapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt *pTargetPkt,
+ bool bPseudoTest)
+{
+ bool bRet = false;
+
+ if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
+ bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
+ else
+ bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
+
+ return bRet;
+}
+
+static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
+ u8 *pWden)
+{
+ u8 match_word_en = 0x0F; /* default all words are disabled */
+
+ /* check if the same words are enabled both target and current PG packet */
+ if (((pTargetPkt->word_en & BIT(0)) == 0) &&
+ ((pCurPkt->word_en & BIT(0)) == 0))
+ match_word_en &= ~BIT(0); /* enable word 0 */
+ if (((pTargetPkt->word_en & BIT(1)) == 0) &&
+ ((pCurPkt->word_en & BIT(1)) == 0))
+ match_word_en &= ~BIT(1); /* enable word 1 */
+ if (((pTargetPkt->word_en & BIT(2)) == 0) &&
+ ((pCurPkt->word_en & BIT(2)) == 0))
+ match_word_en &= ~BIT(2); /* enable word 2 */
+ if (((pTargetPkt->word_en & BIT(3)) == 0) &&
+ ((pCurPkt->word_en & BIT(3)) == 0))
+ match_word_en &= ~BIT(3); /* enable word 3 */
+
+ *pWden = match_word_en;
+
+ if (match_word_en != 0xf)
+ return true;
+ else
+ return false;
+}
+
+static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr, bool bPseudoTest)
+{
+ bool bRet = false;
+ u8 i, efuse_data;
+
+ for (i = 0; i < (word_cnts * 2); i++) {
+ if (efuse_OneByteRead(pAdapter, (startAddr + i), &efuse_data, bPseudoTest) && (efuse_data != 0xFF))
+ bRet = true;
+ }
+ return bRet;
+}
+
+static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
+{
+ bool bRet = false;
+ u8 i, efuse_data = 0, cur_header = 0;
+ u8 matched_wden = 0, badworden = 0;
+ u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
+ struct pgpkt curPkt;
+
+ EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len, bPseudoTest);
+ EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max, bPseudoTest);
+
+ if (efuseType == EFUSE_WIFI) {
+ if (bPseudoTest) {
+ startAddr = (u16)(fakeEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN);
+ } else {
+ rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
+ startAddr %= EFUSE_REAL_CONTENT_LEN;
+ }
+ } else {
+ if (bPseudoTest)
+ startAddr = (u16)(fakeBTEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN);
+ else
+ startAddr = (u16)(BTEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN);
+ }
+
+ while (1) {
+ if (startAddr >= efuse_max_available_len) {
+ bRet = false;
+ break;
+ }
+
+ if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
+ if (EXT_HEADER(efuse_data)) {
+ cur_header = efuse_data;
+ startAddr++;
+ efuse_OneByteRead(pAdapter, startAddr, &efuse_data, bPseudoTest);
+ if (ALL_WORDS_DISABLED(efuse_data)) {
+ bRet = false;
+ break;
+ } else {
+ curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+ curPkt.word_en = efuse_data & 0x0F;
+ }
+ } else {
+ cur_header = efuse_data;
+ curPkt.offset = (cur_header >> 4) & 0x0F;
+ curPkt.word_en = cur_header & 0x0F;
+ }
+
+ curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
+ /* if same header is found but no data followed */
+ /* write some part of data followed by the header. */
+ if ((curPkt.offset == pTargetPkt->offset) &&
+ (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr + 1, bPseudoTest)) &&
+ wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
+ /* Here to write partial data */
+ badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr + 1, matched_wden, pTargetPkt->data, bPseudoTest);
+ if (badworden != 0x0F) {
+ u32 PgWriteSuccess = 0;
+ /* if write fail on some words, write these bad words again */
+
+ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
+
+ if (!PgWriteSuccess) {
+ bRet = false; /* write fail, return */
+ break;
+ }
+ }
+ /* partial write ok, update the target packet for later use */
+ for (i = 0; i < 4; i++) {
+ if ((matched_wden & (0x1 << i)) == 0) /* this word has been written */
+ pTargetPkt->word_en |= (0x1 << i); /* disable the word */
+ }
+ pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+ }
+ /* read from next header */
+ startAddr = startAddr + (curPkt.word_cnts * 2) + 1;
+ } else {
+ /* not used header, 0xff */
+ *pAddr = startAddr;
+ bRet = true;
+ break;
+ }
+ }
+ return bRet;
+}
+
+static bool
+hal_EfusePgCheckAvailableAddr(
+ struct adapter *pAdapter,
+ u8 efuseType,
+ bool bPseudoTest
+ )
+{
+ u16 efuse_max_available_len = 0;
+
+ /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
+ EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len, false);
+
+ if (Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest) >= efuse_max_available_len)
+ return false;
+ return true;
+}
+
+static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
+{
+ memset((void *)pTargetPkt->data, 0xFF, sizeof(u8) * 8);
+ pTargetPkt->offset = offset;
+ pTargetPkt->word_en = word_en;
+ efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
+ pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+}
+
+static bool hal_EfusePgPacketWrite_8188e(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData, bool bPseudoTest)
+{
+ struct pgpkt targetPkt;
+ u16 startAddr = 0;
+ u8 efuseType = EFUSE_WIFI;
+
+ if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType, bPseudoTest))
+ return false;
+
+ hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
+
+ if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
+ return false;
+
+ return true;
+}
+
+static int Hal_EfusePgPacketWrite_Pseudo(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
+{
+ int ret;
+
+ ret = hal_EfusePgPacketWrite_8188e(pAdapter, offset, word_en, data, bPseudoTest);
+ return ret;
+}
+
+static int Hal_EfusePgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
+{
+ int ret = 0;
+ ret = hal_EfusePgPacketWrite_8188e(pAdapter, offset, word_en, data, bPseudoTest);
+
+ return ret;
+}
+
+static int rtl8188e_Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
+{
+ int ret;
+
+ if (bPseudoTest)
+ ret = Hal_EfusePgPacketWrite_Pseudo(pAdapter, offset, word_en, data, bPseudoTest);
+ else
+ ret = Hal_EfusePgPacketWrite(pAdapter, offset, word_en, data, bPseudoTest);
+ return ret;
+}
+
+static struct HAL_VERSION ReadChipVersion8188E(struct adapter *padapter)
+{
+ u32 value32;
+ struct HAL_VERSION ChipVersion;
+ struct hal_data_8188e *pHalData;
+
+ pHalData = GET_HAL_DATA(padapter);
+
+ value32 = rtw_read32(padapter, REG_SYS_CFG);
+ ChipVersion.ICType = CHIP_8188E;
+ ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
+
+ ChipVersion.RFType = RF_TYPE_1T1R;
+ ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
+ ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
+
+ /* For regulator mode. by tynli. 2011.01.14 */
+ pHalData->RegulatorMode = ((value32 & TRP_BT_EN) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
+
+ ChipVersion.ROMVer = 0; /* ROM code version. */
+ pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
+
+ dump_chip_info(ChipVersion);
+
+ pHalData->VersionID = ChipVersion;
+
+ if (IS_1T2R(ChipVersion)) {
+ pHalData->rf_type = RF_1T2R;
+ pHalData->NumTotalRFPath = 2;
+ } else if (IS_2T2R(ChipVersion)) {
+ pHalData->rf_type = RF_2T2R;
+ pHalData->NumTotalRFPath = 2;
+ } else {
+ pHalData->rf_type = RF_1T1R;
+ pHalData->NumTotalRFPath = 1;
+ }
+
+ MSG_88E("RF_Type is %x!!\n", pHalData->rf_type);
+
+ return ChipVersion;
+}
+
+static void rtl8188e_read_chip_version(struct adapter *padapter)
+{
+ ReadChipVersion8188E(padapter);
+}
+
+static void rtl8188e_GetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
+{
+}
+
+static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct odm_dm_struct *podmpriv = &pHalData->odmpriv;
+ switch (eVariable) {
+ case HAL_ODM_STA_INFO:
+ {
+ struct sta_info *psta = (struct sta_info *)pValue1;
+ if (bSet) {
+ DBG_88E("### Set STA_(%d) info\n", psta->mac_id);
+ ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, psta);
+ ODM_RAInfo_Init(podmpriv, psta->mac_id);
+ } else {
+ DBG_88E("### Clean STA_(%d) info\n", psta->mac_id);
+ ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, NULL);
+ }
+ }
+ break;
+ case HAL_ODM_P2P_STATE:
+ ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet);
+ break;
+ case HAL_ODM_WIFI_DISPLAY_STATE:
+ ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet);
+ break;
+ default:
+ break;
+ }
+}
+
+void rtl8188e_clone_haldata(struct adapter *dst_adapter, struct adapter *src_adapter)
+{
+ memcpy(dst_adapter->HalData, src_adapter->HalData, dst_adapter->hal_data_sz);
+}
+
+void rtl8188e_start_thread(struct adapter *padapter)
+{
+}
+
+void rtl8188e_stop_thread(struct adapter *padapter)
+{
+}
+
+static void hal_notch_filter_8188e(struct adapter *adapter, bool enable)
+{
+ if (enable) {
+ DBG_88E("Enable notch filter\n");
+ rtw_write8(adapter, rOFDM0_RxDSP + 1, rtw_read8(adapter, rOFDM0_RxDSP + 1) | BIT(1));
+ } else {
+ DBG_88E("Disable notch filter\n");
+ rtw_write8(adapter, rOFDM0_RxDSP + 1, rtw_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT(1));
+ }
+}
+void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc)
+{
+ pHalFunc->free_hal_data = &rtl8188e_free_hal_data;
+
+ pHalFunc->dm_init = &rtl8188e_init_dm_priv;
+ pHalFunc->dm_deinit = &rtl8188e_deinit_dm_priv;
+
+ pHalFunc->read_chip_version = &rtl8188e_read_chip_version;
+
+ pHalFunc->set_bwmode_handler = &PHY_SetBWMode8188E;
+ pHalFunc->set_channel_handler = &PHY_SwChnl8188E;
+
+ pHalFunc->hal_dm_watchdog = &rtl8188e_HalDmWatchDog;
+
+ pHalFunc->Add_RateATid = &rtl8188e_Add_RateATid;
+ pHalFunc->run_thread = &rtl8188e_start_thread;
+ pHalFunc->cancel_thread = &rtl8188e_stop_thread;
+
+ pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E;
+ pHalFunc->AntDivCompareHandler = &AntDivCompare8188E;
+ pHalFunc->read_bbreg = &rtl8188e_PHY_QueryBBReg;
+ pHalFunc->write_bbreg = &rtl8188e_PHY_SetBBReg;
+ pHalFunc->read_rfreg = &rtl8188e_PHY_QueryRFReg;
+ pHalFunc->write_rfreg = &rtl8188e_PHY_SetRFReg;
+
+ /* Efuse related function */
+ pHalFunc->EfusePowerSwitch = &rtl8188e_EfusePowerSwitch;
+ pHalFunc->ReadEFuse = &rtl8188e_ReadEFuse;
+ pHalFunc->EFUSEGetEfuseDefinition = &rtl8188e_EFUSE_GetEfuseDefinition;
+ pHalFunc->EfuseGetCurrentSize = &rtl8188e_EfuseGetCurrentSize;
+ pHalFunc->Efuse_PgPacketRead = &rtl8188e_Efuse_PgPacketRead;
+ pHalFunc->Efuse_PgPacketWrite = &rtl8188e_Efuse_PgPacketWrite;
+ pHalFunc->Efuse_WordEnableDataWrite = &rtl8188e_Efuse_WordEnableDataWrite;
+
+ pHalFunc->sreset_init_value = &sreset_init_value;
+ pHalFunc->sreset_reset_value = &sreset_reset_value;
+ pHalFunc->silentreset = &rtl8188e_silentreset_for_specific_platform;
+ pHalFunc->sreset_xmit_status_check = &rtl8188e_sreset_xmit_status_check;
+ pHalFunc->sreset_linked_status_check = &rtl8188e_sreset_linked_status_check;
+ pHalFunc->sreset_get_wifi_status = &sreset_get_wifi_status;
+
+ pHalFunc->GetHalODMVarHandler = &rtl8188e_GetHalODMVar;
+ pHalFunc->SetHalODMVarHandler = &rtl8188e_SetHalODMVar;
+
+ pHalFunc->IOL_exec_cmds_sync = &rtl8188e_IOL_exec_cmds_sync;
+
+ pHalFunc->hal_notch_filter = &hal_notch_filter_8188e;
+}
+
+u8 GetEEPROMSize8188E(struct adapter *padapter)
+{
+ u8 size = 0;
+ u32 cr;
+
+ cr = rtw_read16(padapter, REG_9346CR);
+ /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
+ size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
+
+ MSG_88E("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46");
+
+ return size;
+}
+
+/* */
+/* */
+/* LLT R/W/Init function */
+/* */
+/* */
+static s32 _LLTWrite(struct adapter *padapter, u32 address, u32 data)
+{
+ s32 status = _SUCCESS;
+ s32 count = 0;
+ u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
+ u16 LLTReg = REG_LLT_INIT;
+
+ rtw_write32(padapter, LLTReg, value);
+
+ /* polling */
+ do {
+ value = rtw_read32(padapter, LLTReg);
+ if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
+ break;
+
+ if (count > POLLING_LLT_THRESHOLD) {
+ status = _FAIL;
+ break;
+ }
+ } while (count++);
+
+ return status;
+}
+
+s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy)
+{
+ s32 status = _FAIL;
+ u32 i;
+ u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;/* 176, 22k */
+
+ if (rtw_IOL_applied(padapter)) {
+ status = iol_InitLLTTable(padapter, txpktbuf_bndy);
+ } else {
+ for (i = 0; i < (txpktbuf_bndy - 1); i++) {
+ status = _LLTWrite(padapter, i, i + 1);
+ if (_SUCCESS != status)
+ return status;
+ }
+
+ /* end of list */
+ status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
+ if (_SUCCESS != status)
+ return status;
+
+ /* Make the other pages as ring buffer */
+ /* This ring buffer is used as beacon buffer if we config this MAC as two MAC transfer. */
+ /* Otherwise used as local loopback buffer. */
+ for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
+ status = _LLTWrite(padapter, i, (i + 1));
+ if (_SUCCESS != status)
+ return status;
+ }
+
+ /* Let last entry point to the start entry of ring buffer */
+ status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
+ if (_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ return status;
+}
+
+void
+Hal_InitPGData88E(struct adapter *padapter)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+
+ if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */
+ if (!is_boot_from_eeprom(padapter)) {
+ /* Read EFUSE real map to shadow. */
+ EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
+ }
+ } else {/* autoload fail */
+ /* update to default value 0xFF */
+ if (!is_boot_from_eeprom(padapter))
+ EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
+ }
+}
+
+void
+Hal_EfuseParseIDCode88E(
+ struct adapter *padapter,
+ u8 *hwinfo
+ )
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+ u16 EEPROMId;
+
+ /* Check 0x8129 again for making sure autoload status!! */
+ EEPROMId = le16_to_cpu(*((__le16 *)hwinfo));
+ if (EEPROMId != RTL_EEPROM_ID) {
+ pr_err("EEPROM ID(%#x) is invalid!!\n", EEPROMId);
+ pEEPROM->bautoload_fail_flag = true;
+ } else {
+ pEEPROM->bautoload_fail_flag = false;
+ }
+
+ pr_info("EEPROM ID = 0x%04x\n", EEPROMId);
+}
+
+static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G, u8 *PROMContent, bool AutoLoadFail)
+{
+ u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_88E, group, TxCount = 0;
+
+ memset(pwrInfo24G, 0, sizeof(struct txpowerinfo24g));
+
+ if (AutoLoadFail) {
+ for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
+ /* 2.4G default value */
+ for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ if (TxCount == 0) {
+ pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF;
+ pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF;
+ } else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ }
+ }
+ }
+ return;
+ }
+
+ for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
+ /* 2.4G default value */
+ for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = PROMContent[eeAddr++];
+ if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF)
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+ for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) {
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = PROMContent[eeAddr++];
+ if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF)
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ if (TxCount == 0) {
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0;
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
+ } else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4;
+ if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF;
+ } else {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f);
+ if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
+ eeAddr++;
+ } else {
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ } else {
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4;
+ if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ } else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f);
+ if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ eeAddr++;
+
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ } else {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4;
+ if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ } else {
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f);
+ if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ eeAddr++;
+ }
+ }
+ }
+}
+
+static void hal_get_chnl_group_88e(u8 chnl, u8 *group)
+{
+ if (chnl < 3) /* Channel 1-2 */
+ *group = 0;
+ else if (chnl < 6) /* Channel 3-5 */
+ *group = 1;
+ else if (chnl < 9) /* Channel 6-8 */
+ *group = 2;
+ else if (chnl < 12) /* Channel 9-11 */
+ *group = 3;
+ else if (chnl < 14) /* Channel 12-13 */
+ *group = 4;
+ else if (chnl == 14) /* Channel 14 */
+ *group = 5;
+}
+
+void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ if (AutoLoadFail) {
+ padapter->pwrctrlpriv.bHWPowerdown = false;
+ padapter->pwrctrlpriv.bSupportRemoteWakeup = false;
+ } else {
+ /* hw power down mode selection , 0:rf-off / 1:power down */
+
+ if (padapter->registrypriv.hwpdn_mode == 2)
+ padapter->pwrctrlpriv.bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT(4));
+ else
+ padapter->pwrctrlpriv.bHWPowerdown = padapter->registrypriv.hwpdn_mode;
+
+ /* decide hw if support remote wakeup function */
+ /* if hw supported, 8051 (SIE) will generate WeakUP signal(D+/D- toggle) when autoresume */
+ padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT(1)) ? true : false;
+
+ DBG_88E("%s...bHWPwrPindetect(%x)-bHWPowerdown(%x) , bSupportRemoteWakeup(%x)\n", __func__,
+ padapter->pwrctrlpriv.bHWPwrPindetect, padapter->pwrctrlpriv.bHWPowerdown, padapter->pwrctrlpriv.bSupportRemoteWakeup);
+
+ DBG_88E("### PS params => power_mgnt(%x), usbss_enable(%x) ###\n", padapter->registrypriv.power_mgnt, padapter->registrypriv.usbss_enable);
+ }
+}
+
+void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ struct txpowerinfo24g pwrInfo24G;
+ u8 rfPath, ch, group;
+ u8 TxCount;
+
+ Hal_ReadPowerValueFromPROM_8188E(&pwrInfo24G, PROMContent, AutoLoadFail);
+
+ if (!AutoLoadFail)
+ pHalData->bTXPowerDataReadFromEEPORM = true;
+
+ for (rfPath = 0; rfPath < pHalData->NumTotalRFPath; rfPath++) {
+ for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
+ hal_get_chnl_group_88e(ch, &group);
+
+ pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group];
+ if (ch == 14)
+ pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][4];
+ else
+ pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
+
+ DBG_88E("======= Path %d, Channel %d =======\n", rfPath, ch);
+ DBG_88E("Index24G_CCK_Base[%d][%d] = 0x%x\n", rfPath, ch, pHalData->Index24G_CCK_Base[rfPath][ch]);
+ DBG_88E("Index24G_BW40_Base[%d][%d] = 0x%x\n", rfPath, ch, pHalData->Index24G_BW40_Base[rfPath][ch]);
+ }
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ pHalData->CCK_24G_Diff[rfPath][TxCount] = pwrInfo24G.CCK_Diff[rfPath][TxCount];
+ pHalData->OFDM_24G_Diff[rfPath][TxCount] = pwrInfo24G.OFDM_Diff[rfPath][TxCount];
+ pHalData->BW20_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW20_Diff[rfPath][TxCount];
+ pHalData->BW40_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW40_Diff[rfPath][TxCount];
+ DBG_88E("======= TxCount %d =======\n", TxCount);
+ DBG_88E("CCK_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->CCK_24G_Diff[rfPath][TxCount]);
+ DBG_88E("OFDM_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->OFDM_24G_Diff[rfPath][TxCount]);
+ DBG_88E("BW20_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->BW20_24G_Diff[rfPath][TxCount]);
+ DBG_88E("BW40_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->BW40_24G_Diff[rfPath][TxCount]);
+ }
+ }
+
+ /* 2010/10/19 MH Add Regulator recognize for CU. */
+ if (!AutoLoadFail) {
+ pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x7); /* bit0~2 */
+ if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
+ pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION & 0x7); /* bit0~2 */
+ } else {
+ pHalData->EEPROMRegulatory = 0;
+ }
+ DBG_88E("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory);
+}
+
+void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+
+ if (!AutoLoadFail) {
+ pHalData->CrystalCap = hwinfo[EEPROM_XTAL_88E];
+ if (pHalData->CrystalCap == 0xFF)
+ pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E;
+ } else {
+ pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E;
+ }
+ DBG_88E("CrystalCap: 0x%2x\n", pHalData->CrystalCap);
+}
+
+void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+
+ if (!AutoLoadFail)
+ pHalData->BoardType = ((hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0xE0) >> 5);
+ else
+ pHalData->BoardType = 0;
+ DBG_88E("Board Type: 0x%2x\n", pHalData->BoardType);
+}
+
+void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+
+ if (!AutoLoadFail) {
+ pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_88E];
+ if (pHalData->EEPROMVersion == 0xFF)
+ pHalData->EEPROMVersion = EEPROM_Default_Version;
+ } else {
+ pHalData->EEPROMVersion = 1;
+ }
+}
+
+void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ padapter->mlmepriv.ChannelPlan =
+ hal_com_get_channel_plan(padapter,
+ hwinfo ? hwinfo[EEPROM_ChannelPlan_88E] : 0xFF,
+ padapter->registrypriv.channel_plan,
+ RT_CHANNEL_DOMAIN_WORLD_WIDE_13, AutoLoadFail);
+
+ DBG_88E("mlmepriv.ChannelPlan = 0x%02x\n", padapter->mlmepriv.ChannelPlan);
+}
+
+void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+
+ if (!AutoLoadFail) {
+ pHalData->EEPROMCustomerID = hwinfo[EEPROM_CUSTOMERID_88E];
+ } else {
+ pHalData->EEPROMCustomerID = 0;
+ pHalData->EEPROMSubCustomerID = 0;
+ }
+ DBG_88E("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID);
+}
+
+void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+ struct registry_priv *registry_par = &pAdapter->registrypriv;
+
+ if (!AutoLoadFail) {
+ /* Antenna Diversity setting. */
+ if (registry_par->antdiv_cfg == 2) { /* 2:By EFUSE */
+ pHalData->AntDivCfg = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x18) >> 3;
+ if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
+ pHalData->AntDivCfg = (EEPROM_DEFAULT_BOARD_OPTION & 0x18) >> 3;
+ } else {
+ pHalData->AntDivCfg = registry_par->antdiv_cfg; /* 0:OFF , 1:ON, 2:By EFUSE */
+ }
+
+ if (registry_par->antdiv_type == 0) {
+ /* If TRxAntDivType is AUTO in advanced setting, use EFUSE value instead. */
+ pHalData->TRxAntDivType = PROMContent[EEPROM_RF_ANTENNA_OPT_88E];
+ if (pHalData->TRxAntDivType == 0xFF)
+ pHalData->TRxAntDivType = CG_TRX_HW_ANTDIV; /* For 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */
+ } else {
+ pHalData->TRxAntDivType = registry_par->antdiv_type;
+ }
+
+ if (pHalData->TRxAntDivType == CG_TRX_HW_ANTDIV || pHalData->TRxAntDivType == CGCS_RX_HW_ANTDIV)
+ pHalData->AntDivCfg = 1; /* 0xC1[3] is ignored. */
+ } else {
+ pHalData->AntDivCfg = 0;
+ pHalData->TRxAntDivType = pHalData->TRxAntDivType; /* The value in the driver setting of device manager. */
+ }
+ DBG_88E("EEPROM : AntDivCfg = %x, TRxAntDivType = %x\n", pHalData->AntDivCfg, pHalData->TRxAntDivType);
+}
+
+void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+
+ /* ThermalMeter from EEPROM */
+ if (!AutoloadFail)
+ pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_88E];
+ else
+ pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E;
+
+ if (pHalData->EEPROMThermalMeter == 0xff || AutoloadFail) {
+ pHalData->bAPKThermalMeterIgnore = true;
+ pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E;
+ }
+ DBG_88E("ThermalMeter = 0x%x\n", pHalData->EEPROMThermalMeter);
+}
+
+void Hal_InitChannelPlan(struct adapter *padapter)
+{
+}
+
+bool HalDetectPwrDownMode88E(struct adapter *Adapter)
+{
+ u8 tmpvalue = 0;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
+
+ EFUSE_ShadowRead(Adapter, 1, EEPROM_RF_FEATURE_OPTION_88E, (u32 *)&tmpvalue);
+
+ /* 2010/08/25 MH INF priority > PDN Efuse value. */
+ if (tmpvalue & BIT(4) && pwrctrlpriv->reg_pdnmode)
+ pHalData->pwrdown = true;
+ else
+ pHalData->pwrdown = false;
+
+ DBG_88E("HalDetectPwrDownMode(): PDN =%d\n", pHalData->pwrdown);
+
+ return pHalData->pwrdown;
+} /* HalDetectPwrDownMode */
+
+/* This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */
+/* We just reserve the value of the register in variable pHalData->RegBcnCtrlVal and then operate */
+/* the value of the register via atomic operation. */
+/* This prevents from race condition when setting this register. */
+/* The value of pHalData->RegBcnCtrlVal is initialized in HwConfigureRTL8192CE() function. */
+
+void SetBcnCtrlReg(struct adapter *padapter, u8 SetBits, u8 ClearBits)
+{
+ struct hal_data_8188e *pHalData;
+
+ pHalData = GET_HAL_DATA(padapter);
+
+ pHalData->RegBcnCtrlVal |= SetBits;
+ pHalData->RegBcnCtrlVal &= ~ClearBits;
+
+ rtw_write8(padapter, REG_BCN_CTRL, (u8)pHalData->RegBcnCtrlVal);
+}
diff --git a/drivers/staging/r8188eu/hal/rtl8188e_mp.c b/drivers/staging/r8188eu/hal/rtl8188e_mp.c
new file mode 100644
index 000000000000..fc13db705511
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/rtl8188e_mp.c
@@ -0,0 +1,798 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTL8188E_MP_C_
+
+#include "../include/drv_types.h"
+#include "../include/rtw_mp.h"
+#include "../include/rtl8188e_hal.h"
+#include "../include/rtl8188e_dm.h"
+
+s32 Hal_SetPowerTracking(struct adapter *padapter, u8 enable)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ struct odm_dm_struct *pDM_Odm = &pHalData->odmpriv;
+
+ if (!netif_running(padapter->pnetdev))
+ return _FAIL;
+
+ if (!check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE))
+ return _FAIL;
+
+ if (enable)
+ pDM_Odm->RFCalibrateInfo.bTXPowerTracking = true;
+ else
+ pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = false;
+
+ return _SUCCESS;
+}
+
+void Hal_GetPowerTracking(struct adapter *padapter, u8 *enable)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ struct odm_dm_struct *pDM_Odm = &pHalData->odmpriv;
+
+ *enable = pDM_Odm->RFCalibrateInfo.TxPowerTrackControl;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: mpt_SwitchRfSetting
+ *
+ * Overview: Change RF Setting when we siwthc channel/rate/BW for MP.
+ *
+ * Input: struct adapter * pAdapter
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 01/08/2009 MHC Suggestion from SD3 Willis for 92S series.
+ * 01/09/2009 MHC Add CCK modification for 40MHZ. Suggestion from SD3.
+ *
+ *---------------------------------------------------------------------------*/
+void Hal_mpt_SwitchRfSetting(struct adapter *pAdapter)
+{
+ struct mp_priv *pmp = &pAdapter->mppriv;
+
+ /* <20120525, Kordan> Dynamic mechanism for APK, asked by Dennis. */
+ pmp->MptCtx.backup0x52_RF_A = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
+ pmp->MptCtx.backup0x52_RF_B = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_0x52, 0x000F0);
+ PHY_SetRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0, 0xD);
+ PHY_SetRFReg(pAdapter, RF_PATH_B, RF_0x52, 0x000F0, 0xD);
+}
+/*---------------------------hal\rtl8192c\MPT_Phy.c---------------------------*/
+
+/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
+void Hal_MPT_CCKTxPowerAdjust(struct adapter *Adapter, bool bInCH14)
+{
+ u32 TempVal = 0, TempVal2 = 0, TempVal3 = 0;
+ u32 CurrCCKSwingVal = 0, CCKSwingIndex = 12;
+ u8 i;
+
+ /* get current cck swing value and check 0xa22 & 0xa23 later to match the table. */
+ CurrCCKSwingVal = read_bbreg(Adapter, rCCK0_TxFilter1, bMaskHWord);
+
+ if (!bInCH14) {
+ /* Readback the current bb cck swing value and compare with the table to */
+ /* get the current swing index */
+ for (i = 0; i < CCK_TABLE_SIZE; i++) {
+ if (((CurrCCKSwingVal & 0xff) == (u32)CCKSwingTable_Ch1_Ch13[i][0]) &&
+ (((CurrCCKSwingVal & 0xff00) >> 8) == (u32)CCKSwingTable_Ch1_Ch13[i][1])) {
+ CCKSwingIndex = i;
+ break;
+ }
+ }
+
+ /* Write 0xa22 0xa23 */
+ TempVal = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][0] +
+ (CCKSwingTable_Ch1_Ch13[CCKSwingIndex][1] << 8);
+
+ /* Write 0xa24 ~ 0xa27 */
+ TempVal2 = 0;
+ TempVal2 = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][2] +
+ (CCKSwingTable_Ch1_Ch13[CCKSwingIndex][3] << 8) +
+ (CCKSwingTable_Ch1_Ch13[CCKSwingIndex][4] << 16) +
+ (CCKSwingTable_Ch1_Ch13[CCKSwingIndex][5] << 24);
+
+ /* Write 0xa28 0xa29 */
+ TempVal3 = 0;
+ TempVal3 = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][6] +
+ (CCKSwingTable_Ch1_Ch13[CCKSwingIndex][7] << 8);
+ } else {
+ for (i = 0; i < CCK_TABLE_SIZE; i++) {
+ if (((CurrCCKSwingVal & 0xff) == (u32)CCKSwingTable_Ch14[i][0]) &&
+ (((CurrCCKSwingVal & 0xff00) >> 8) == (u32)CCKSwingTable_Ch14[i][1])) {
+ CCKSwingIndex = i;
+ break;
+ }
+ }
+
+ /* Write 0xa22 0xa23 */
+ TempVal = CCKSwingTable_Ch14[CCKSwingIndex][0] +
+ (CCKSwingTable_Ch14[CCKSwingIndex][1] << 8);
+
+ /* Write 0xa24 ~ 0xa27 */
+ TempVal2 = 0;
+ TempVal2 = CCKSwingTable_Ch14[CCKSwingIndex][2] +
+ (CCKSwingTable_Ch14[CCKSwingIndex][3] << 8) +
+ (CCKSwingTable_Ch14[CCKSwingIndex][4] << 16) +
+ (CCKSwingTable_Ch14[CCKSwingIndex][5] << 24);
+
+ /* Write 0xa28 0xa29 */
+ TempVal3 = 0;
+ TempVal3 = CCKSwingTable_Ch14[CCKSwingIndex][6] +
+ (CCKSwingTable_Ch14[CCKSwingIndex][7] << 8);
+ }
+
+ write_bbreg(Adapter, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ write_bbreg(Adapter, rCCK0_TxFilter2, bMaskDWord, TempVal2);
+ write_bbreg(Adapter, rCCK0_DebugPort, bMaskLWord, TempVal3);
+}
+
+void Hal_MPT_CCKTxPowerAdjustbyIndex(struct adapter *pAdapter, bool beven)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+ struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
+ struct odm_dm_struct *pDM_Odm = &pHalData->odmpriv;
+ s32 TempCCk;
+ u8 CCK_index, CCK_index_old = 0;
+ u8 Action = 0; /* 0: no action, 1: even->odd, 2:odd->even */
+ s32 i = 0;
+
+ if (!IS_92C_SERIAL(pHalData->VersionID))
+ return;
+ if (beven && !pMptCtx->bMptIndexEven) {
+ /* odd->even */
+ Action = 2;
+ pMptCtx->bMptIndexEven = true;
+ } else if (!beven && pMptCtx->bMptIndexEven) {
+ /* even->odd */
+ Action = 1;
+ pMptCtx->bMptIndexEven = false;
+ }
+
+ if (Action != 0) {
+ /* Query CCK default setting From 0xa24 */
+ TempCCk = read_bbreg(pAdapter, rCCK0_TxFilter2, bMaskDWord) & bMaskCCK;
+ for (i = 0; i < CCK_TABLE_SIZE; i++) {
+ if (pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
+ if (!memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch14[i][2], 4)) {
+ CCK_index_old = (u8)i;
+ break;
+ }
+ } else {
+ if (!memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch1_Ch13[i][2], 4)) {
+ CCK_index_old = (u8)i;
+ break;
+ }
+ }
+ }
+
+ if (Action == 1)
+ CCK_index = CCK_index_old - 1;
+ else
+ CCK_index = CCK_index_old + 1;
+
+ /* Adjust CCK according to gain index */
+ if (!pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
+ rtw_write8(pAdapter, 0xa22, CCKSwingTable_Ch1_Ch13[CCK_index][0]);
+ rtw_write8(pAdapter, 0xa23, CCKSwingTable_Ch1_Ch13[CCK_index][1]);
+ rtw_write8(pAdapter, 0xa24, CCKSwingTable_Ch1_Ch13[CCK_index][2]);
+ rtw_write8(pAdapter, 0xa25, CCKSwingTable_Ch1_Ch13[CCK_index][3]);
+ rtw_write8(pAdapter, 0xa26, CCKSwingTable_Ch1_Ch13[CCK_index][4]);
+ rtw_write8(pAdapter, 0xa27, CCKSwingTable_Ch1_Ch13[CCK_index][5]);
+ rtw_write8(pAdapter, 0xa28, CCKSwingTable_Ch1_Ch13[CCK_index][6]);
+ rtw_write8(pAdapter, 0xa29, CCKSwingTable_Ch1_Ch13[CCK_index][7]);
+ } else {
+ rtw_write8(pAdapter, 0xa22, CCKSwingTable_Ch14[CCK_index][0]);
+ rtw_write8(pAdapter, 0xa23, CCKSwingTable_Ch14[CCK_index][1]);
+ rtw_write8(pAdapter, 0xa24, CCKSwingTable_Ch14[CCK_index][2]);
+ rtw_write8(pAdapter, 0xa25, CCKSwingTable_Ch14[CCK_index][3]);
+ rtw_write8(pAdapter, 0xa26, CCKSwingTable_Ch14[CCK_index][4]);
+ rtw_write8(pAdapter, 0xa27, CCKSwingTable_Ch14[CCK_index][5]);
+ rtw_write8(pAdapter, 0xa28, CCKSwingTable_Ch14[CCK_index][6]);
+ rtw_write8(pAdapter, 0xa29, CCKSwingTable_Ch14[CCK_index][7]);
+ }
+ }
+}
+/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
+
+/*
+ * SetChannel
+ * Description
+ * Use H2C command to change channel,
+ * not only modify rf register, but also other setting need to be done.
+ */
+void Hal_SetChannel(struct adapter *pAdapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+ struct mp_priv *pmp = &pAdapter->mppriv;
+ struct odm_dm_struct *pDM_Odm = &pHalData->odmpriv;
+ u8 eRFPath;
+ u8 channel = pmp->channel;
+
+ /* set RF channel register */
+ for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
+ _write_rfreg(pAdapter, eRFPath, ODM_CHANNEL, 0x3FF, channel);
+ Hal_mpt_SwitchRfSetting(pAdapter);
+
+ SelectChannel(pAdapter, channel);
+
+ if (pHalData->CurrentChannel == 14 && !pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
+ pDM_Odm->RFCalibrateInfo.bCCKinCH14 = true;
+ Hal_MPT_CCKTxPowerAdjust(pAdapter, pDM_Odm->RFCalibrateInfo.bCCKinCH14);
+ } else if (pHalData->CurrentChannel != 14 && pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
+ pDM_Odm->RFCalibrateInfo.bCCKinCH14 = false;
+ Hal_MPT_CCKTxPowerAdjust(pAdapter, pDM_Odm->RFCalibrateInfo.bCCKinCH14);
+ }
+}
+
+/*
+ * Notice
+ * Switch bandwitdth may change center frequency(channel)
+ */
+void Hal_SetBandwidth(struct adapter *pAdapter)
+{
+ struct mp_priv *pmp = &pAdapter->mppriv;
+
+ SetBWMode(pAdapter, pmp->bandwidth, pmp->prime_channel_offset);
+ Hal_mpt_SwitchRfSetting(pAdapter);
+}
+
+void Hal_SetCCKTxPower(struct adapter *pAdapter, u8 *TxPower)
+{
+ u32 tmpval = 0;
+
+ /* rf-A cck tx power */
+ write_bbreg(pAdapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, TxPower[RF_PATH_A]);
+ tmpval = (TxPower[RF_PATH_A] << 16) | (TxPower[RF_PATH_A] << 8) | TxPower[RF_PATH_A];
+ write_bbreg(pAdapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+
+ /* rf-B cck tx power */
+ write_bbreg(pAdapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, TxPower[RF_PATH_B]);
+ tmpval = (TxPower[RF_PATH_B] << 16) | (TxPower[RF_PATH_B] << 8) | TxPower[RF_PATH_B];
+ write_bbreg(pAdapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
+}
+
+void Hal_SetOFDMTxPower(struct adapter *pAdapter, u8 *TxPower)
+{
+ u32 TxAGC = 0;
+ u8 tmpval = 0;
+
+ /* HT Tx-rf(A) */
+ tmpval = TxPower[RF_PATH_A];
+ TxAGC = (tmpval << 24) | (tmpval << 16) | (tmpval << 8) | tmpval;
+
+ write_bbreg(pAdapter, rTxAGC_A_Rate18_06, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_A_Rate54_24, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_A_Mcs03_Mcs00, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_A_Mcs07_Mcs04, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_A_Mcs11_Mcs08, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_A_Mcs15_Mcs12, bMaskDWord, TxAGC);
+
+ /* HT Tx-rf(B) */
+ tmpval = TxPower[RF_PATH_B];
+ TxAGC = (tmpval << 24) | (tmpval << 16) | (tmpval << 8) | tmpval;
+
+ write_bbreg(pAdapter, rTxAGC_B_Rate18_06, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_B_Rate54_24, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_B_Mcs03_Mcs00, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_B_Mcs07_Mcs04, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_B_Mcs11_Mcs08, bMaskDWord, TxAGC);
+ write_bbreg(pAdapter, rTxAGC_B_Mcs15_Mcs12, bMaskDWord, TxAGC);
+}
+
+void Hal_SetAntennaPathPower(struct adapter *pAdapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+ u8 TxPowerLevel[RF_PATH_MAX];
+ u8 rfPath;
+
+ TxPowerLevel[RF_PATH_A] = pAdapter->mppriv.txpoweridx;
+ TxPowerLevel[RF_PATH_B] = pAdapter->mppriv.txpoweridx_b;
+
+ switch (pAdapter->mppriv.antenna_tx) {
+ case ANTENNA_A:
+ default:
+ rfPath = RF_PATH_A;
+ break;
+ case ANTENNA_B:
+ rfPath = RF_PATH_B;
+ break;
+ case ANTENNA_C:
+ rfPath = RF_PATH_C;
+ break;
+ }
+
+ switch (pHalData->rf_chip) {
+ case RF_8225:
+ case RF_8256:
+ case RF_6052:
+ Hal_SetCCKTxPower(pAdapter, TxPowerLevel);
+ if (pAdapter->mppriv.rateidx < MPT_RATE_6M) /* CCK rate */
+ Hal_MPT_CCKTxPowerAdjustbyIndex(pAdapter, TxPowerLevel[rfPath] % 2 == 0);
+ Hal_SetOFDMTxPower(pAdapter, TxPowerLevel);
+ break;
+ default:
+ break;
+ }
+}
+
+void Hal_SetTxPower(struct adapter *pAdapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+ u8 TxPower = pAdapter->mppriv.txpoweridx;
+ u8 TxPowerLevel[RF_PATH_MAX];
+ u8 rf, rfPath;
+
+ for (rf = 0; rf < RF_PATH_MAX; rf++)
+ TxPowerLevel[rf] = TxPower;
+
+ switch (pAdapter->mppriv.antenna_tx) {
+ case ANTENNA_A:
+ default:
+ rfPath = RF_PATH_A;
+ break;
+ case ANTENNA_B:
+ rfPath = RF_PATH_B;
+ break;
+ case ANTENNA_C:
+ rfPath = RF_PATH_C;
+ break;
+ }
+
+ switch (pHalData->rf_chip) {
+ /* 2008/09/12 MH Test only !! We enable the TX power tracking for MP!!!!! */
+ /* We should call normal driver API later!! */
+ case RF_8225:
+ case RF_8256:
+ case RF_6052:
+ Hal_SetCCKTxPower(pAdapter, TxPowerLevel);
+ if (pAdapter->mppriv.rateidx < MPT_RATE_6M) /* CCK rate */
+ Hal_MPT_CCKTxPowerAdjustbyIndex(pAdapter, TxPowerLevel[rfPath] % 2 == 0);
+ Hal_SetOFDMTxPower(pAdapter, TxPowerLevel);
+ break;
+ default:
+ break;
+ }
+}
+
+void Hal_SetDataRate(struct adapter *pAdapter)
+{
+ Hal_mpt_SwitchRfSetting(pAdapter);
+}
+
+void Hal_SetAntenna(struct adapter *pAdapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+
+ struct ant_sel_ofdm *p_ofdm_tx; /* OFDM Tx register */
+ struct ant_sel_cck *p_cck_txrx;
+ u8 r_rx_antenna_ofdm = 0, r_ant_select_cck_val = 0;
+ u8 chgTx = 0, chgRx = 0;
+ u32 r_ant_select_ofdm_val = 0, r_ofdm_tx_en_val = 0;
+
+ p_ofdm_tx = (struct ant_sel_ofdm *)&r_ant_select_ofdm_val;
+ p_cck_txrx = (struct ant_sel_cck *)&r_ant_select_cck_val;
+
+ p_ofdm_tx->r_ant_ht1 = 0x1;
+ p_ofdm_tx->r_ant_ht2 = 0x2; /* Second TX RF path is A */
+ p_ofdm_tx->r_ant_non_ht = 0x3; /* 0x1+0x2=0x3 */
+
+ switch (pAdapter->mppriv.antenna_tx) {
+ case ANTENNA_A:
+ p_ofdm_tx->r_tx_antenna = 0x1;
+ r_ofdm_tx_en_val = 0x1;
+ p_ofdm_tx->r_ant_l = 0x1;
+ p_ofdm_tx->r_ant_ht_s1 = 0x1;
+ p_ofdm_tx->r_ant_non_ht_s1 = 0x1;
+ p_cck_txrx->r_ccktx_enable = 0x8;
+ chgTx = 1;
+
+ /* From SD3 Willis suggestion !!! Set RF A=TX and B as standby */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 1);
+ r_ofdm_tx_en_val = 0x3;
+
+ /* Power save */
+
+ /* We need to close RFB by SW control */
+ if (pHalData->rf_type == RF_2T2R) {
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(26), 1);
+ PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT(10), 0);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT(1), 1);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT(17), 0);
+ }
+ break;
+ case ANTENNA_B:
+ p_ofdm_tx->r_tx_antenna = 0x2;
+ r_ofdm_tx_en_val = 0x2;
+ p_ofdm_tx->r_ant_l = 0x2;
+ p_ofdm_tx->r_ant_ht_s1 = 0x2;
+ p_ofdm_tx->r_ant_non_ht_s1 = 0x2;
+ p_cck_txrx->r_ccktx_enable = 0x4;
+ chgTx = 1;
+ /* From SD3 Willis suggestion !!! Set RF A as standby */
+ PHY_SetBBReg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 1);
+ PHY_SetBBReg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
+
+ /* Power save */
+ /* cosa r_ant_select_ofdm_val = 0x22222222; */
+
+ /* 2008/10/31 MH From SD3 Willi's suggestion. We must read RF 1T table. */
+ /* 2009/01/08 MH From Sd3 Willis. We need to close RFA by SW control */
+ if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_1T2R) {
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(10), 1);
+ PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT(10), 0);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT(1), 0);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT(17), 1);
+ }
+ break;
+ case ANTENNA_AB: /* For 8192S */
+ p_ofdm_tx->r_tx_antenna = 0x3;
+ r_ofdm_tx_en_val = 0x3;
+ p_ofdm_tx->r_ant_l = 0x3;
+ p_ofdm_tx->r_ant_ht_s1 = 0x3;
+ p_ofdm_tx->r_ant_non_ht_s1 = 0x3;
+ p_cck_txrx->r_ccktx_enable = 0xC;
+ chgTx = 1;
+
+ /* From SD3 Willis suggestion !!! Set RF B as standby */
+ PHY_SetBBReg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
+ PHY_SetBBReg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
+
+ /* Disable Power save */
+ /* cosa r_ant_select_ofdm_val = 0x3321333; */
+ /* 2009/01/08 MH From Sd3 Willis. We need to enable RFA/B by SW control */
+ if (pHalData->rf_type == RF_2T2R) {
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT(1), 1);
+ PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT(17), 1);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* r_rx_antenna_ofdm, bit0=A, bit1=B, bit2=C, bit3=D */
+ /* r_cckrx_enable : CCK default, 0=A, 1=B, 2=C, 3=D */
+ /* r_cckrx_enable_2 : CCK option, 0=A, 1=B, 2=C, 3=D */
+ switch (pAdapter->mppriv.antenna_rx) {
+ case ANTENNA_A:
+ r_rx_antenna_ofdm = 0x1; /* A */
+ p_cck_txrx->r_cckrx_enable = 0x0; /* default: A */
+ p_cck_txrx->r_cckrx_enable_2 = 0x0; /* option: A */
+ chgRx = 1;
+ break;
+ case ANTENNA_B:
+ r_rx_antenna_ofdm = 0x2; /* B */
+ p_cck_txrx->r_cckrx_enable = 0x1; /* default: B */
+ p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option: B */
+ chgRx = 1;
+ break;
+ case ANTENNA_AB:
+ r_rx_antenna_ofdm = 0x3; /* AB */
+ p_cck_txrx->r_cckrx_enable = 0x0; /* default:A */
+ p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option:B */
+ chgRx = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (chgTx && chgRx) {
+ switch (pHalData->rf_chip) {
+ case RF_8225:
+ case RF_8256:
+ case RF_6052:
+ /* r_ant_sel_cck_val = r_ant_select_cck_val; */
+ PHY_SetBBReg(pAdapter, rFPGA1_TxInfo, 0x7fffffff, r_ant_select_ofdm_val); /* OFDM Tx */
+ PHY_SetBBReg(pAdapter, rFPGA0_TxInfo, 0x0000000f, r_ofdm_tx_en_val); /* OFDM Tx */
+ PHY_SetBBReg(pAdapter, rOFDM0_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm); /* OFDM Rx */
+ PHY_SetBBReg(pAdapter, rOFDM1_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm); /* OFDM Rx */
+ PHY_SetBBReg(pAdapter, rCCK0_AFESetting, bMaskByte3, r_ant_select_cck_val); /* CCK TxRx */
+
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+s32 Hal_SetThermalMeter(struct adapter *pAdapter, u8 target_ther)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+
+ if (!netif_running(pAdapter->pnetdev))
+ return _FAIL;
+
+ if (!check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE))
+ return _FAIL;
+
+ target_ther &= 0xff;
+ if (target_ther < 0x07)
+ target_ther = 0x07;
+ else if (target_ther > 0x1d)
+ target_ther = 0x1d;
+
+ pHalData->EEPROMThermalMeter = target_ther;
+
+ return _SUCCESS;
+}
+
+void Hal_TriggerRFThermalMeter(struct adapter *pAdapter)
+{
+ _write_rfreg(pAdapter, RF_PATH_A, RF_T_METER_88E, BIT(17) | BIT(16), 0x03);
+}
+
+u8 Hal_ReadRFThermalMeter(struct adapter *pAdapter)
+{
+ u32 ThermalValue = 0;
+
+ ThermalValue = _read_rfreg(pAdapter, RF_PATH_A, RF_T_METER_88E, 0xfc00);
+ return (u8)ThermalValue;
+}
+
+void Hal_GetThermalMeter(struct adapter *pAdapter, u8 *value)
+{
+ Hal_TriggerRFThermalMeter(pAdapter);
+ msleep(1000);
+ *value = Hal_ReadRFThermalMeter(pAdapter);
+}
+
+void Hal_SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart)
+{
+ pAdapter->mppriv.MptCtx.bSingleCarrier = bStart;
+ if (bStart) {
+ /* Start Single Carrier. */
+ /* 1. if OFDM block on? */
+ if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn))
+ write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);/* set OFDM block on */
+
+ /* 2. set CCK test mode off, set to CCK normal mode */
+ write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
+ /* 3. turn on scramble setting */
+ write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
+ /* 4. Turn On Single Carrier Tx and turn off the other test modes. */
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+ /* for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
+ } else {
+ /* Stop Single Carrier. */
+ /* Turn off all test modes. */
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+ msleep(10);
+
+ /* BB Reset */
+ write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
+ write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
+
+ /* Stop for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
+ }
+}
+
+void Hal_SetSingleToneTx(struct adapter *pAdapter, u8 bStart)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
+ bool is92C = IS_92C_SERIAL(pHalData->VersionID);
+
+ u8 rfPath;
+ u32 reg58 = 0x0;
+ switch (pAdapter->mppriv.antenna_tx) {
+ case ANTENNA_A:
+ default:
+ rfPath = RF_PATH_A;
+ break;
+ case ANTENNA_B:
+ rfPath = RF_PATH_B;
+ break;
+ case ANTENNA_C:
+ rfPath = RF_PATH_C;
+ break;
+ }
+
+ pAdapter->mppriv.MptCtx.bSingleTone = bStart;
+ if (bStart) {
+ /* Start Single Tone. */
+ /* <20120326, Kordan> To amplify the power of tone for Xtal calibration. (asked by Edlu) */
+ if (IS_HARDWARE_TYPE_8188E(pAdapter)) {
+ reg58 = PHY_QueryRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask);
+ reg58 &= 0xFFFFFFF0;
+ reg58 += 2;
+ PHY_SetRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask, reg58);
+ }
+ PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, bCCKEn, 0x0);
+ PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 0x0);
+
+ if (is92C) {
+ _write_rfreg(pAdapter, RF_PATH_A, 0x21, BIT(19), 0x01);
+ rtw_usleep_os(100);
+ if (rfPath == RF_PATH_A)
+ write_rfreg(pAdapter, RF_PATH_B, 0x00, 0x10000); /* PAD all on. */
+ else if (rfPath == RF_PATH_B)
+ write_rfreg(pAdapter, RF_PATH_A, 0x00, 0x10000); /* PAD all on. */
+ write_rfreg(pAdapter, rfPath, 0x00, 0x2001f); /* PAD all on. */
+ rtw_usleep_os(100);
+ } else {
+ write_rfreg(pAdapter, rfPath, 0x21, 0xd4000);
+ rtw_usleep_os(100);
+ write_rfreg(pAdapter, rfPath, 0x00, 0x2001f); /* PAD all on. */
+ rtw_usleep_os(100);
+ }
+
+ /* for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
+
+ } else {
+ /* Stop Single Tone. */
+ /* <20120326, Kordan> To amplify the power of tone for Xtal calibration. (asked by Edlu) */
+ /* <20120326, Kordan> Only in single tone mode. (asked by Edlu) */
+ if (IS_HARDWARE_TYPE_8188E(pAdapter)) {
+ reg58 = PHY_QueryRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask);
+ reg58 &= 0xFFFFFFF0;
+ PHY_SetRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask, reg58);
+ }
+ write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, 0x1);
+ write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 0x1);
+ if (is92C) {
+ _write_rfreg(pAdapter, RF_PATH_A, 0x21, BIT(19), 0x00);
+ rtw_usleep_os(100);
+ write_rfreg(pAdapter, RF_PATH_A, 0x00, 0x32d75); /* PAD all on. */
+ write_rfreg(pAdapter, RF_PATH_B, 0x00, 0x32d75); /* PAD all on. */
+ rtw_usleep_os(100);
+ } else {
+ write_rfreg(pAdapter, rfPath, 0x21, 0x54000);
+ rtw_usleep_os(100);
+ write_rfreg(pAdapter, rfPath, 0x00, 0x30000); /* PAD all on. */
+ rtw_usleep_os(100);
+ }
+
+ /* Stop for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
+ }
+}
+
+void Hal_SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart)
+{
+ pAdapter->mppriv.MptCtx.bCarrierSuppression = bStart;
+ if (bStart) {
+ /* Start Carrier Suppression. */
+ if (pAdapter->mppriv.rateidx <= MPT_RATE_11M) {
+ /* 1. if CCK block on? */
+ if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn))
+ write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);/* set CCK block on */
+
+ /* Turn Off All Test Mode */
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+
+ write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); /* transmit mode */
+ write_bbreg(pAdapter, rCCK0_System, bCCKScramble, 0x0); /* turn off scramble setting */
+
+ /* Set CCK Tx Test Rate */
+ write_bbreg(pAdapter, rCCK0_System, bCCKTxRate, 0x0); /* Set FTxRate to 1Mbps */
+ }
+
+ /* for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
+ } else {
+ /* Stop Carrier Suppression. */
+ if (pAdapter->mppriv.rateidx <= MPT_RATE_11M) {
+ write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); /* normal mode */
+ write_bbreg(pAdapter, rCCK0_System, bCCKScramble, 0x1); /* turn on scramble setting */
+
+ /* BB Reset */
+ write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
+ write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
+ }
+
+ /* Stop for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
+ }
+}
+
+void Hal_SetCCKContinuousTx(struct adapter *pAdapter, u8 bStart)
+{
+ u32 cckrate;
+
+ if (bStart) {
+ /* 1. if CCK block on? */
+ if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn))
+ write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);/* set CCK block on */
+
+ /* Turn Off All Test Mode */
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+ /* Set CCK Tx Test Rate */
+ cckrate = pAdapter->mppriv.rateidx;
+ write_bbreg(pAdapter, rCCK0_System, bCCKTxRate, cckrate);
+ write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); /* transmit mode */
+ write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable); /* turn on scramble setting */
+
+ /* for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
+ } else {
+ write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); /* normal mode */
+ write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable); /* turn on scramble setting */
+
+ /* BB Reset */
+ write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
+ write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
+
+ /* Stop for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
+ }
+
+ pAdapter->mppriv.MptCtx.bCckContTx = bStart;
+ pAdapter->mppriv.MptCtx.bOfdmContTx = false;
+} /* mpt_StartCckContTx */
+
+void Hal_SetOFDMContinuousTx(struct adapter *pAdapter, u8 bStart)
+{
+ if (bStart) {
+ /* 1. if OFDM block on? */
+ if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn))
+ write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);/* set OFDM block on */
+
+ /* 2. set CCK test mode off, set to CCK normal mode */
+ write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
+
+ /* 3. turn on scramble setting */
+ write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
+ /* 4. Turn On Continue Tx and turn off the other test modes. */
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bEnable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+
+ /* for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
+
+ } else {
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+ write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+ /* Delay 10 ms */
+ msleep(10);
+ /* BB Reset */
+ write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
+ write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
+
+ /* Stop for dynamic set Power index. */
+ write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
+ write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
+ }
+
+ pAdapter->mppriv.MptCtx.bCckContTx = false;
+ pAdapter->mppriv.MptCtx.bOfdmContTx = bStart;
+} /* mpt_StartOfdmContTx */
+
+void Hal_SetContinuousTx(struct adapter *pAdapter, u8 bStart)
+{
+ pAdapter->mppriv.MptCtx.bStartContTx = bStart;
+ if (pAdapter->mppriv.rateidx <= MPT_RATE_11M)
+ Hal_SetCCKContinuousTx(pAdapter, bStart);
+ else if ((pAdapter->mppriv.rateidx >= MPT_RATE_6M) &&
+ (pAdapter->mppriv.rateidx <= MPT_RATE_MCS15))
+ Hal_SetOFDMContinuousTx(pAdapter, bStart);
+}
diff --git a/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c b/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c
new file mode 100644
index 000000000000..30a9dca8f453
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c
@@ -0,0 +1,1105 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTL8188E_PHYCFG_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtw_iol.h"
+#include "../include/rtl8188e_hal.h"
+
+/*---------------------------Define Local Constant---------------------------*/
+/* Channel switch:The size of command tables for switch channel*/
+#define MAX_PRECMD_CNT 16
+#define MAX_RFDEPENDCMD_CNT 16
+#define MAX_POSTCMD_CNT 16
+
+#define MAX_DOZE_WAITING_TIMES_9x 64
+
+/*---------------------------Define Local Constant---------------------------*/
+
+/*------------------------Define global variable-----------------------------*/
+
+/*------------------------Define local variable------------------------------*/
+
+/*--------------------Define export function prototype-----------------------*/
+/* Please refer to header file */
+/*--------------------Define export function prototype-----------------------*/
+
+/*----------------------------Function Body----------------------------------*/
+/* */
+/* 1. BB register R/W API */
+/* */
+
+/**
+* Function: phy_CalculateBitShift
+*
+* OverView: Get shifted position of the BitMask
+*
+* Input:
+* u32 BitMask,
+*
+* Output: none
+* Return: u32 Return the shift bit bit position of the mask
+*/
+static u32 phy_CalculateBitShift(u32 BitMask)
+{
+ u32 i;
+
+ for (i = 0; i <= 31; i++) {
+ if (((BitMask >> i) & 0x1) == 1)
+ break;
+ }
+ return i;
+}
+
+/**
+* Function: PHY_QueryBBReg
+*
+* OverView: Read "sepcific bits" from BB register
+*
+* Input:
+* struct adapter *Adapter,
+* u32 RegAddr, The target address to be readback
+* u32 BitMask The target bit position in the target address
+* to be readback
+* Output: None
+* Return: u32 Data The readback register value
+* Note: This function is equal to "GetRegSetting" in PHY programming guide
+*/
+u32
+rtl8188e_PHY_QueryBBReg(
+ struct adapter *Adapter,
+ u32 RegAddr,
+ u32 BitMask
+ )
+{
+ u32 ReturnValue = 0, OriginalValue, BitShift;
+
+ OriginalValue = rtw_read32(Adapter, RegAddr);
+ BitShift = phy_CalculateBitShift(BitMask);
+ ReturnValue = (OriginalValue & BitMask) >> BitShift;
+ return ReturnValue;
+}
+
+/**
+* Function: PHY_SetBBReg
+*
+* OverView: Write "Specific bits" to BB register (page 8~)
+*
+* Input:
+* struct adapter *Adapter,
+* u32 RegAddr, The target address to be modified
+* u32 BitMask The target bit position in the target address
+* to be modified
+* u32 Data The new register value in the target bit position
+* of the target address
+*
+* Output: None
+* Return: None
+* Note: This function is equal to "PutRegSetting" in PHY programming guide
+*/
+
+void rtl8188e_PHY_SetBBReg(struct adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ u32 OriginalValue, BitShift;
+
+ if (BitMask != bMaskDWord) { /* if not "double word" write */
+ OriginalValue = rtw_read32(Adapter, RegAddr);
+ BitShift = phy_CalculateBitShift(BitMask);
+ Data = ((OriginalValue & (~BitMask)) | (Data << BitShift));
+ }
+
+ rtw_write32(Adapter, RegAddr, Data);
+}
+
+/* */
+/* 2. RF register R/W API */
+/* */
+/**
+* Function: phy_RFSerialRead
+*
+* OverView: Read regster from RF chips
+*
+* Input:
+* struct adapter *Adapter,
+* enum rf_radio_path eRFPath, Radio path of A/B/C/D
+* u32 Offset, The target address to be read
+*
+* Output: None
+* Return: u32 reback value
+* Note: Threre are three types of serial operations:
+* 1. Software serial write
+* 2. Hardware LSSI-Low Speed Serial Interface
+* 3. Hardware HSSI-High speed
+* serial write. Driver need to implement (1) and (2).
+* This function is equal to the combination of RF_ReadReg() and RFLSSIRead()
+*/
+static u32
+phy_RFSerialRead(
+ struct adapter *Adapter,
+ enum rf_radio_path eRFPath,
+ u32 Offset
+ )
+{
+ u32 retValue = 0;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct bb_reg_def *pPhyReg = &pHalData->PHYRegDef[eRFPath];
+ u32 NewOffset;
+ u32 tmplong, tmplong2;
+ u8 RfPiEnable = 0;
+ /* */
+ /* Make sure RF register offset is correct */
+ /* */
+ Offset &= 0xff;
+
+ /* */
+ /* Switch page for 8256 RF IC */
+ /* */
+ NewOffset = Offset;
+
+ /* For 92S LSSI Read RFLSSIRead */
+ /* For RF A/B write 0x824/82c(does not work in the future) */
+ /* We must use 0x824 for RF A and B to execute read trigger */
+ tmplong = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord);
+ if (eRFPath == RF_PATH_A)
+ tmplong2 = tmplong;
+ else
+ tmplong2 = PHY_QueryBBReg(Adapter, pPhyReg->rfHSSIPara2, bMaskDWord);
+
+ tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset << 23) | bLSSIReadEdge; /* T65 RF */
+
+ PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong & (~bLSSIReadEdge));
+ udelay(10);/* PlatformStallExecution(10); */
+
+ PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, bMaskDWord, tmplong2);
+ udelay(100);/* PlatformStallExecution(100); */
+
+ udelay(10);/* PlatformStallExecution(10); */
+
+ if (eRFPath == RF_PATH_A)
+ RfPiEnable = (u8)PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter1, BIT(8));
+ else if (eRFPath == RF_PATH_B)
+ RfPiEnable = (u8)PHY_QueryBBReg(Adapter, rFPGA0_XB_HSSIParameter1, BIT(8));
+
+ if (RfPiEnable) { /* Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */
+ retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBackPi, bLSSIReadBackData);
+ } else { /* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */
+ retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBack, bLSSIReadBackData);
+ }
+ return retValue;
+}
+
+/**
+* Function: phy_RFSerialWrite
+*
+* OverView: Write data to RF register (page 8~)
+*
+* Input:
+* struct adapter *Adapter,
+* enum rf_radio_path eRFPath, Radio path of A/B/C/D
+* u32 Offset, The target address to be read
+* u32 Data The new register Data in the target bit position
+* of the target to be read
+*
+* Output: None
+* Return: None
+* Note: Threre are three types of serial operations:
+* 1. Software serial write
+* 2. Hardware LSSI-Low Speed Serial Interface
+* 3. Hardware HSSI-High speed
+* serial write. Driver need to implement (1) and (2).
+* This function is equal to the combination of RF_ReadReg() and RFLSSIRead()
+ *
+ * Note: For RF8256 only
+ * The total count of RTL8256(Zebra4) register is around 36 bit it only employs
+ * 4-bit RF address. RTL8256 uses "register mode control bit" (Reg00[12], Reg00[10])
+ * to access register address bigger than 0xf. See "Appendix-4 in PHY Configuration
+ * programming guide" for more details.
+ * Thus, we define a sub-finction for RTL8526 register address conversion
+ * ===========================================================
+ * Register Mode RegCTL[1] RegCTL[0] Note
+ * (Reg00[12]) (Reg00[10])
+ * ===========================================================
+ * Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf)
+ * ------------------------------------------------------------------
+ * Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf)
+ * ------------------------------------------------------------------
+ * Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf)
+ * ------------------------------------------------------------------
+ *
+ * 2008/09/02 MH Add 92S RF definition
+ *
+ *
+ *
+*/
+static void
+phy_RFSerialWrite(
+ struct adapter *Adapter,
+ enum rf_radio_path eRFPath,
+ u32 Offset,
+ u32 Data
+ )
+{
+ u32 DataAndAddr = 0;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct bb_reg_def *pPhyReg = &pHalData->PHYRegDef[eRFPath];
+ u32 NewOffset;
+
+ /* 2009/06/17 MH We can not execute IO for power save or other accident mode. */
+
+ Offset &= 0xff;
+
+ /* */
+ /* Switch page for 8256 RF IC */
+ /* */
+ NewOffset = Offset;
+
+ /* */
+ /* Put write addr in [5:0] and write data in [31:16] */
+ /* */
+ DataAndAddr = ((NewOffset << 20) | (Data & 0x000fffff)) & 0x0fffffff; /* T65 RF */
+
+ /* */
+ /* Write Operation */
+ /* */
+ PHY_SetBBReg(Adapter, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
+}
+
+/**
+* Function: PHY_QueryRFReg
+*
+* OverView: Query "Specific bits" to RF register (page 8~)
+*
+* Input:
+* struct adapter *Adapter,
+* enum rf_radio_path eRFPath, Radio path of A/B/C/D
+* u32 RegAddr, The target address to be read
+* u32 BitMask The target bit position in the target address
+* to be read
+*
+* Output: None
+* Return: u32 Readback value
+* Note: This function is equal to "GetRFRegSetting" in PHY programming guide
+*/
+u32 rtl8188e_PHY_QueryRFReg(struct adapter *Adapter, enum rf_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask)
+{
+ u32 Original_Value, Readback_Value, BitShift;
+
+ Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr);
+
+ BitShift = phy_CalculateBitShift(BitMask);
+ Readback_Value = (Original_Value & BitMask) >> BitShift;
+ return Readback_Value;
+}
+
+/**
+* Function: PHY_SetRFReg
+*
+* OverView: Write "Specific bits" to RF register (page 8~)
+*
+* Input:
+* struct adapter *Adapter,
+* enum rf_radio_path eRFPath, Radio path of A/B/C/D
+* u32 RegAddr, The target address to be modified
+* u32 BitMask The target bit position in the target address
+* to be modified
+* u32 Data The new register Data in the target bit position
+* of the target address
+*
+* Output: None
+* Return: None
+* Note: This function is equal to "PutRFRegSetting" in PHY programming guide
+*/
+void
+rtl8188e_PHY_SetRFReg(
+ struct adapter *Adapter,
+ enum rf_radio_path eRFPath,
+ u32 RegAddr,
+ u32 BitMask,
+ u32 Data
+ )
+{
+ u32 Original_Value, BitShift;
+
+ /* RF data is 12 bits only */
+ if (BitMask != bRFRegOffsetMask) {
+ Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr);
+ BitShift = phy_CalculateBitShift(BitMask);
+ Data = ((Original_Value & (~BitMask)) | (Data << BitShift));
+ }
+
+ phy_RFSerialWrite(Adapter, eRFPath, RegAddr, Data);
+}
+
+/* */
+/* 3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. */
+/* */
+
+/*-----------------------------------------------------------------------------
+ * Function: PHY_MACConfig8192C
+ *
+ * Overview: Condig MAC by header file or parameter file.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 08/12/2008 MHC Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+s32 PHY_MACConfig8188E(struct adapter *Adapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ int rtStatus = _SUCCESS;
+
+ /* */
+ /* Config MAC */
+ /* */
+ if (HAL_STATUS_FAILURE == ODM_ConfigMACWithHeaderFile(&pHalData->odmpriv))
+ rtStatus = _FAIL;
+
+ /* 2010.07.13 AMPDU aggregation number B */
+ rtw_write16(Adapter, REG_MAX_AGGR_NUM, MAX_AGGR_NUM);
+
+ return rtStatus;
+}
+
+/**
+* Function: phy_InitBBRFRegisterDefinition
+*
+* OverView: Initialize Register definition offset for Radio Path A/B/C/D
+*
+* Input:
+* struct adapter *Adapter,
+*
+* Output: None
+* Return: None
+* Note: The initialization value is constant and it should never be changes
+*/
+static void
+phy_InitBBRFRegisterDefinition(
+ struct adapter *Adapter
+)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+
+ /* RF Interface Sowrtware Control */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 LSBs if read 32-bit from 0x870 */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
+ pHalData->PHYRegDef[RF_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;/* 16 LSBs if read 32-bit from 0x874 */
+ pHalData->PHYRegDef[RF_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW;/* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */
+
+ /* RF Interface Readback Value */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB; /* 16 LSBs if read 32-bit from 0x8E0 */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;/* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */
+ pHalData->PHYRegDef[RF_PATH_C].rfintfi = rFPGA0_XCD_RFInterfaceRB;/* 16 LSBs if read 32-bit from 0x8E4 */
+ pHalData->PHYRegDef[RF_PATH_D].rfintfi = rFPGA0_XCD_RFInterfaceRB;/* 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) */
+
+ /* RF Interface Output (and Enable) */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x860 */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x864 */
+
+ /* RF Interface (Output and) Enable */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
+
+ /* Addr of LSSI. Wirte RF register by driver */
+ pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; /* LSSI Parameter */
+ pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
+
+ /* RF parameter */
+ pHalData->PHYRegDef[RF_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter; /* BB Band Select */
+ pHalData->PHYRegDef[RF_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter;
+ pHalData->PHYRegDef[RF_PATH_C].rfLSSI_Select = rFPGA0_XCD_RFParameter;
+ pHalData->PHYRegDef[RF_PATH_D].rfLSSI_Select = rFPGA0_XCD_RFParameter;
+
+ /* Tx AGC Gain Stage (same for all path. Should we remove this?) */
+ pHalData->PHYRegDef[RF_PATH_A].rfTxGainStage = rFPGA0_TxGainStage; /* Tx gain stage */
+ pHalData->PHYRegDef[RF_PATH_B].rfTxGainStage = rFPGA0_TxGainStage; /* Tx gain stage */
+ pHalData->PHYRegDef[RF_PATH_C].rfTxGainStage = rFPGA0_TxGainStage; /* Tx gain stage */
+ pHalData->PHYRegDef[RF_PATH_D].rfTxGainStage = rFPGA0_TxGainStage; /* Tx gain stage */
+
+ /* Tranceiver A~D HSSI Parameter-1 */
+ pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1; /* wire control parameter1 */
+ pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1; /* wire control parameter1 */
+
+ /* Tranceiver A~D HSSI Parameter-2 */
+ pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; /* wire control parameter2 */
+ pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; /* wire control parameter2 */
+
+ /* RF switch Control */
+ pHalData->PHYRegDef[RF_PATH_A].rfSwitchControl = rFPGA0_XAB_SwitchControl; /* TR/Ant switch control */
+ pHalData->PHYRegDef[RF_PATH_B].rfSwitchControl = rFPGA0_XAB_SwitchControl;
+ pHalData->PHYRegDef[RF_PATH_C].rfSwitchControl = rFPGA0_XCD_SwitchControl;
+ pHalData->PHYRegDef[RF_PATH_D].rfSwitchControl = rFPGA0_XCD_SwitchControl;
+
+ /* AGC control 1 */
+ pHalData->PHYRegDef[RF_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1;
+ pHalData->PHYRegDef[RF_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1;
+ pHalData->PHYRegDef[RF_PATH_C].rfAGCControl1 = rOFDM0_XCAGCCore1;
+ pHalData->PHYRegDef[RF_PATH_D].rfAGCControl1 = rOFDM0_XDAGCCore1;
+
+ /* AGC control 2 */
+ pHalData->PHYRegDef[RF_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2;
+ pHalData->PHYRegDef[RF_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2;
+ pHalData->PHYRegDef[RF_PATH_C].rfAGCControl2 = rOFDM0_XCAGCCore2;
+ pHalData->PHYRegDef[RF_PATH_D].rfAGCControl2 = rOFDM0_XDAGCCore2;
+
+ /* RX AFE control 1 */
+ pHalData->PHYRegDef[RF_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance;
+ pHalData->PHYRegDef[RF_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
+ pHalData->PHYRegDef[RF_PATH_C].rfRxIQImbalance = rOFDM0_XCRxIQImbalance;
+ pHalData->PHYRegDef[RF_PATH_D].rfRxIQImbalance = rOFDM0_XDRxIQImbalance;
+
+ /* RX AFE control 1 */
+ pHalData->PHYRegDef[RF_PATH_A].rfRxAFE = rOFDM0_XARxAFE;
+ pHalData->PHYRegDef[RF_PATH_B].rfRxAFE = rOFDM0_XBRxAFE;
+ pHalData->PHYRegDef[RF_PATH_C].rfRxAFE = rOFDM0_XCRxAFE;
+ pHalData->PHYRegDef[RF_PATH_D].rfRxAFE = rOFDM0_XDRxAFE;
+
+ /* Tx AFE control 1 */
+ pHalData->PHYRegDef[RF_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance;
+ pHalData->PHYRegDef[RF_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
+ pHalData->PHYRegDef[RF_PATH_C].rfTxIQImbalance = rOFDM0_XCTxIQImbalance;
+ pHalData->PHYRegDef[RF_PATH_D].rfTxIQImbalance = rOFDM0_XDTxIQImbalance;
+
+ /* Tx AFE control 2 */
+ pHalData->PHYRegDef[RF_PATH_A].rfTxAFE = rOFDM0_XATxAFE;
+ pHalData->PHYRegDef[RF_PATH_B].rfTxAFE = rOFDM0_XBTxAFE;
+ pHalData->PHYRegDef[RF_PATH_C].rfTxAFE = rOFDM0_XCTxAFE;
+ pHalData->PHYRegDef[RF_PATH_D].rfTxAFE = rOFDM0_XDTxAFE;
+
+ /* Tranceiver LSSI Readback SI mode */
+ pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
+ pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
+ pHalData->PHYRegDef[RF_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack;
+ pHalData->PHYRegDef[RF_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack;
+
+ /* Tranceiver LSSI Readback PI mode */
+ pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
+ pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
+}
+
+void storePwrIndexDiffRateOffset(struct adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+
+ if (RegAddr == rTxAGC_A_Rate18_06)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][0] = Data;
+ if (RegAddr == rTxAGC_A_Rate54_24)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][1] = Data;
+ if (RegAddr == rTxAGC_A_CCK1_Mcs32)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][6] = Data;
+ if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0xffffff00)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][7] = Data;
+ if (RegAddr == rTxAGC_A_Mcs03_Mcs00)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][2] = Data;
+ if (RegAddr == rTxAGC_A_Mcs07_Mcs04)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][3] = Data;
+ if (RegAddr == rTxAGC_A_Mcs11_Mcs08)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][4] = Data;
+ if (RegAddr == rTxAGC_A_Mcs15_Mcs12) {
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][5] = Data;
+ if (pHalData->rf_type == RF_1T1R)
+ pHalData->pwrGroupCnt++;
+ }
+ if (RegAddr == rTxAGC_B_Rate18_06)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][8] = Data;
+ if (RegAddr == rTxAGC_B_Rate54_24)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][9] = Data;
+ if (RegAddr == rTxAGC_B_CCK1_55_Mcs32)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][14] = Data;
+ if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0x000000ff)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][15] = Data;
+ if (RegAddr == rTxAGC_B_Mcs03_Mcs00)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][10] = Data;
+ if (RegAddr == rTxAGC_B_Mcs07_Mcs04)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][11] = Data;
+ if (RegAddr == rTxAGC_B_Mcs11_Mcs08)
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][12] = Data;
+ if (RegAddr == rTxAGC_B_Mcs15_Mcs12) {
+ pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][13] = Data;
+ if (pHalData->rf_type != RF_1T1R)
+ pHalData->pwrGroupCnt++;
+ }
+}
+
+static int phy_BB8188E_Config_ParaFile(struct adapter *Adapter)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter);
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ int rtStatus = _SUCCESS;
+
+ /* */
+ /* 1. Read PHY_REG.TXT BB INIT!! */
+ /* We will separate as 88C / 92C according to chip version */
+ /* */
+ if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG))
+ rtStatus = _FAIL;
+ if (rtStatus != _SUCCESS)
+ goto phy_BB8190_Config_ParaFile_Fail;
+
+ /* 2. If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */
+ if (!pEEPROM->bautoload_fail_flag) {
+ pHalData->pwrGroupCnt = 0;
+
+ if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG_PG))
+ rtStatus = _FAIL;
+ }
+
+ if (rtStatus != _SUCCESS)
+ goto phy_BB8190_Config_ParaFile_Fail;
+
+ /* 3. BB AGC table Initialization */
+ if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_AGC_TAB))
+ rtStatus = _FAIL;
+
+ if (rtStatus != _SUCCESS)
+ goto phy_BB8190_Config_ParaFile_Fail;
+
+phy_BB8190_Config_ParaFile_Fail:
+
+ return rtStatus;
+}
+
+int
+PHY_BBConfig8188E(
+ struct adapter *Adapter
+ )
+{
+ int rtStatus = _SUCCESS;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u32 RegVal;
+ u8 CrystalCap;
+
+ phy_InitBBRFRegisterDefinition(Adapter);
+
+ /* Enable BB and RF */
+ RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN);
+ rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal | BIT(13) | BIT(0) | BIT(1)));
+
+ /* 20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. */
+
+ rtw_write8(Adapter, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
+
+ rtw_write8(Adapter, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB);
+
+ /* Config BB and AGC */
+ rtStatus = phy_BB8188E_Config_ParaFile(Adapter);
+
+ /* write 0x24[16:11] = 0x24[22:17] = CrystalCap */
+ CrystalCap = pHalData->CrystalCap & 0x3F;
+ PHY_SetBBReg(Adapter, REG_AFE_XTAL_CTRL, 0x7ff800, (CrystalCap | (CrystalCap << 6)));
+
+ return rtStatus;
+}
+
+int PHY_RFConfig8188E(struct adapter *Adapter)
+{
+ int rtStatus = _SUCCESS;
+
+ /* RF config */
+ rtStatus = PHY_RF6052_Config8188E(Adapter);
+ return rtStatus;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: PHY_ConfigRFWithParaFile()
+ *
+ * Overview: This function read RF parameters from general file format, and do RF 3-wire
+ *
+ * Input: struct adapter *Adapter
+ * ps8 pFileName
+ * enum rf_radio_path eRFPath
+ *
+ * Output: NONE
+ *
+ * Return: RT_STATUS_SUCCESS: configuration file exist
+ *
+ * Note: Delay may be required for RF configuration
+ *---------------------------------------------------------------------------*/
+int rtl8188e_PHY_ConfigRFWithParaFile(struct adapter *Adapter, u8 *pFileName, enum rf_radio_path eRFPath)
+{
+ return _SUCCESS;
+}
+
+void
+rtl8192c_PHY_GetHWRegOriginalValue(
+ struct adapter *Adapter
+ )
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+
+ /* read rx initial gain */
+ pHalData->DefaultInitialGain[0] = (u8)PHY_QueryBBReg(Adapter, rOFDM0_XAAGCCore1, bMaskByte0);
+ pHalData->DefaultInitialGain[1] = (u8)PHY_QueryBBReg(Adapter, rOFDM0_XBAGCCore1, bMaskByte0);
+ pHalData->DefaultInitialGain[2] = (u8)PHY_QueryBBReg(Adapter, rOFDM0_XCAGCCore1, bMaskByte0);
+ pHalData->DefaultInitialGain[3] = (u8)PHY_QueryBBReg(Adapter, rOFDM0_XDAGCCore1, bMaskByte0);
+
+ /* read framesync */
+ pHalData->framesync = (u8)PHY_QueryBBReg(Adapter, rOFDM0_RxDetector3, bMaskByte0);
+ pHalData->framesyncC34 = PHY_QueryBBReg(Adapter, rOFDM0_RxDetector2, bMaskDWord);
+}
+
+/* */
+/* Description: */
+/* Map dBm into Tx power index according to */
+/* current HW model, for example, RF and PA, and */
+/* current wireless mode. */
+/* By Bruce, 2008-01-29. */
+/* */
+static u8 phy_DbmToTxPwrIdx(struct adapter *Adapter, enum wireless_mode WirelessMode, int PowerInDbm)
+{
+ u8 TxPwrIdx = 0;
+ int Offset = 0;
+
+ /* */
+ /* Tested by MP, we found that CCK Index 0 equals to 8dbm, OFDM legacy equals to */
+ /* 3dbm, and OFDM HT equals to 0dbm respectively. */
+ /* Note: */
+ /* The mapping may be different by different NICs. Do not use this formula for what needs accurate result. */
+ /* By Bruce, 2008-01-29. */
+ /* */
+ switch (WirelessMode) {
+ case WIRELESS_MODE_B:
+ Offset = -7;
+ break;
+
+ case WIRELESS_MODE_G:
+ case WIRELESS_MODE_N_24G:
+ default:
+ Offset = -8;
+ break;
+ }
+
+ if ((PowerInDbm - Offset) > 0)
+ TxPwrIdx = (u8)((PowerInDbm - Offset) * 2);
+ else
+ TxPwrIdx = 0;
+
+ /* Tx Power Index is too large. */
+ if (TxPwrIdx > MAX_TXPWR_IDX_NMODE_92S)
+ TxPwrIdx = MAX_TXPWR_IDX_NMODE_92S;
+
+ return TxPwrIdx;
+}
+
+/* */
+/* Description: */
+/* Map Tx power index into dBm according to */
+/* current HW model, for example, RF and PA, and */
+/* current wireless mode. */
+/* By Bruce, 2008-01-29. */
+/* */
+static int phy_TxPwrIdxToDbm(struct adapter *Adapter, enum wireless_mode WirelessMode, u8 TxPwrIdx)
+{
+ int Offset = 0;
+ int PwrOutDbm = 0;
+
+ /* */
+ /* Tested by MP, we found that CCK Index 0 equals to -7dbm, OFDM legacy equals to -8dbm. */
+ /* Note: */
+ /* The mapping may be different by different NICs. Do not use this formula for what needs accurate result. */
+ /* By Bruce, 2008-01-29. */
+ /* */
+ switch (WirelessMode) {
+ case WIRELESS_MODE_B:
+ Offset = -7;
+ break;
+ case WIRELESS_MODE_G:
+ case WIRELESS_MODE_N_24G:
+ default:
+ Offset = -8;
+ break;
+ }
+
+ PwrOutDbm = TxPwrIdx / 2 + Offset; /* Discard the decimal part. */
+
+ return PwrOutDbm;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: GetTxPowerLevel8190()
+ *
+ * Overview: This function is export to "common" moudule
+ *
+ * Input: struct adapter *Adapter
+ * psByte Power Level
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ *---------------------------------------------------------------------------*/
+void PHY_GetTxPowerLevel8188E(struct adapter *Adapter, u32 *powerlevel)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u8 TxPwrLevel = 0;
+ int TxPwrDbm;
+
+ /* */
+ /* Because the Tx power indexes are different, we report the maximum of them to */
+ /* meet the CCX TPC request. By Bruce, 2008-01-31. */
+ /* */
+
+ /* CCK */
+ TxPwrLevel = pHalData->CurrentCckTxPwrIdx;
+ TxPwrDbm = phy_TxPwrIdxToDbm(Adapter, WIRELESS_MODE_B, TxPwrLevel);
+
+ /* Legacy OFDM */
+ TxPwrLevel = pHalData->CurrentOfdm24GTxPwrIdx + pHalData->LegacyHTTxPowerDiff;
+
+ /* Compare with Legacy OFDM Tx power. */
+ if (phy_TxPwrIdxToDbm(Adapter, WIRELESS_MODE_G, TxPwrLevel) > TxPwrDbm)
+ TxPwrDbm = phy_TxPwrIdxToDbm(Adapter, WIRELESS_MODE_G, TxPwrLevel);
+
+ /* HT OFDM */
+ TxPwrLevel = pHalData->CurrentOfdm24GTxPwrIdx;
+
+ /* Compare with HT OFDM Tx power. */
+ if (phy_TxPwrIdxToDbm(Adapter, WIRELESS_MODE_N_24G, TxPwrLevel) > TxPwrDbm)
+ TxPwrDbm = phy_TxPwrIdxToDbm(Adapter, WIRELESS_MODE_N_24G, TxPwrLevel);
+
+ *powerlevel = TxPwrDbm;
+}
+
+static void getTxPowerIndex88E(struct adapter *Adapter, u8 channel, u8 *cckPowerLevel,
+ u8 *ofdmPowerLevel, u8 *BW20PowerLevel,
+ u8 *BW40PowerLevel)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u8 index = (channel - 1);
+ u8 TxCount = 0, path_nums;
+
+ if ((RF_1T2R == pHalData->rf_type) || (RF_1T1R == pHalData->rf_type))
+ path_nums = 1;
+ else
+ path_nums = 2;
+
+ for (TxCount = 0; TxCount < path_nums; TxCount++) {
+ if (TxCount == RF_PATH_A) {
+ /* 1. CCK */
+ cckPowerLevel[TxCount] = pHalData->Index24G_CCK_Base[TxCount][index];
+ /* 2. OFDM */
+ ofdmPowerLevel[TxCount] = pHalData->Index24G_BW40_Base[RF_PATH_A][index] +
+ pHalData->OFDM_24G_Diff[TxCount][RF_PATH_A];
+ /* 1. BW20 */
+ BW20PowerLevel[TxCount] = pHalData->Index24G_BW40_Base[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[TxCount][RF_PATH_A];
+ /* 2. BW40 */
+ BW40PowerLevel[TxCount] = pHalData->Index24G_BW40_Base[TxCount][index];
+ } else if (TxCount == RF_PATH_B) {
+ /* 1. CCK */
+ cckPowerLevel[TxCount] = pHalData->Index24G_CCK_Base[TxCount][index];
+ /* 2. OFDM */
+ ofdmPowerLevel[TxCount] = pHalData->Index24G_BW40_Base[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[TxCount][index];
+ /* 1. BW20 */
+ BW20PowerLevel[TxCount] = pHalData->Index24G_BW40_Base[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[TxCount][RF_PATH_A] +
+ pHalData->BW20_24G_Diff[TxCount][index];
+ /* 2. BW40 */
+ BW40PowerLevel[TxCount] = pHalData->Index24G_BW40_Base[TxCount][index];
+ } else if (TxCount == RF_PATH_C) {
+ /* 1. CCK */
+ cckPowerLevel[TxCount] = pHalData->Index24G_CCK_Base[TxCount][index];
+ /* 2. OFDM */
+ ofdmPowerLevel[TxCount] = pHalData->Index24G_BW40_Base[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_B][index] +
+ pHalData->BW20_24G_Diff[TxCount][index];
+ /* 1. BW20 */
+ BW20PowerLevel[TxCount] = pHalData->Index24G_BW40_Base[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_B][index] +
+ pHalData->BW20_24G_Diff[TxCount][index];
+ /* 2. BW40 */
+ BW40PowerLevel[TxCount] = pHalData->Index24G_BW40_Base[TxCount][index];
+ } else if (TxCount == RF_PATH_D) {
+ /* 1. CCK */
+ cckPowerLevel[TxCount] = pHalData->Index24G_CCK_Base[TxCount][index];
+ /* 2. OFDM */
+ ofdmPowerLevel[TxCount] = pHalData->Index24G_BW40_Base[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_B][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_C][index] +
+ pHalData->BW20_24G_Diff[TxCount][index];
+
+ /* 1. BW20 */
+ BW20PowerLevel[TxCount] = pHalData->Index24G_BW40_Base[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_A][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_B][index] +
+ pHalData->BW20_24G_Diff[RF_PATH_C][index] +
+ pHalData->BW20_24G_Diff[TxCount][index];
+
+ /* 2. BW40 */
+ BW40PowerLevel[TxCount] = pHalData->Index24G_BW40_Base[TxCount][index];
+ }
+ }
+}
+
+static void phy_PowerIndexCheck88E(struct adapter *Adapter, u8 channel, u8 *cckPowerLevel,
+ u8 *ofdmPowerLevel, u8 *BW20PowerLevel, u8 *BW40PowerLevel)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+
+ pHalData->CurrentCckTxPwrIdx = cckPowerLevel[0];
+ pHalData->CurrentOfdm24GTxPwrIdx = ofdmPowerLevel[0];
+ pHalData->CurrentBW2024GTxPwrIdx = BW20PowerLevel[0];
+ pHalData->CurrentBW4024GTxPwrIdx = BW40PowerLevel[0];
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: SetTxPowerLevel8190()
+ *
+ * Overview: This function is export to "HalCommon" moudule
+ * We must consider RF path later!!!!!!!
+ *
+ * Input: struct adapter *Adapter
+ * u8 channel
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ * 2008/11/04 MHC We remove EEPROM_93C56.
+ * We need to move CCX relative code to independet file.
+ * 2009/01/21 MHC Support new EEPROM format from SD3 requirement.
+ *
+ *---------------------------------------------------------------------------*/
+void
+PHY_SetTxPowerLevel8188E(
+ struct adapter *Adapter,
+ u8 channel
+ )
+{
+ u8 cckPowerLevel[MAX_TX_COUNT] = {0};
+ u8 ofdmPowerLevel[MAX_TX_COUNT] = {0};/* [0]:RF-A, [1]:RF-B */
+ u8 BW20PowerLevel[MAX_TX_COUNT] = {0};
+ u8 BW40PowerLevel[MAX_TX_COUNT] = {0};
+
+ getTxPowerIndex88E(Adapter, channel, &cckPowerLevel[0], &ofdmPowerLevel[0], &BW20PowerLevel[0], &BW40PowerLevel[0]);
+
+ phy_PowerIndexCheck88E(Adapter, channel, &cckPowerLevel[0], &ofdmPowerLevel[0], &BW20PowerLevel[0], &BW40PowerLevel[0]);
+
+ rtl8188e_PHY_RF6052SetCckTxPower(Adapter, &cckPowerLevel[0]);
+ rtl8188e_PHY_RF6052SetOFDMTxPower(Adapter, &ofdmPowerLevel[0], &BW20PowerLevel[0], &BW40PowerLevel[0], channel);
+}
+
+/* */
+/* Description: */
+/* Update transmit power level of all channel supported. */
+/* */
+/* TODO: */
+/* A mode. */
+/* By Bruce, 2008-02-04. */
+/* */
+bool
+PHY_UpdateTxPowerDbm8188E(
+ struct adapter *Adapter,
+ int powerInDbm
+ )
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u8 idx;
+ u8 rf_path;
+
+ /* TODO: A mode Tx power. */
+ u8 CckTxPwrIdx = phy_DbmToTxPwrIdx(Adapter, WIRELESS_MODE_B, powerInDbm);
+ u8 OfdmTxPwrIdx = phy_DbmToTxPwrIdx(Adapter, WIRELESS_MODE_N_24G, powerInDbm);
+
+ if (OfdmTxPwrIdx - pHalData->LegacyHTTxPowerDiff > 0)
+ OfdmTxPwrIdx -= pHalData->LegacyHTTxPowerDiff;
+ else
+ OfdmTxPwrIdx = 0;
+
+ for (idx = 0; idx < 14; idx++) {
+ for (rf_path = 0; rf_path < 2; rf_path++) {
+ pHalData->TxPwrLevelCck[rf_path][idx] = CckTxPwrIdx;
+ pHalData->TxPwrLevelHT40_1S[rf_path][idx] =
+ pHalData->TxPwrLevelHT40_2S[rf_path][idx] = OfdmTxPwrIdx;
+ }
+ }
+ return true;
+}
+
+void
+PHY_ScanOperationBackup8188E(
+ struct adapter *Adapter,
+ u8 Operation
+ )
+{
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: PHY_SetBWModeCallback8192C()
+ *
+ * Overview: Timer callback function for SetSetBWMode
+ *
+ * Input: PRT_TIMER pTimer
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Note: (1) We do not take j mode into consideration now
+ * (2) Will two workitem of "switch channel" and "switch channel bandwidth" run
+ * concurrently?
+ *---------------------------------------------------------------------------*/
+static void
+_PHY_SetBWMode92C(
+ struct adapter *Adapter
+)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u8 regBwOpMode;
+ u8 regRRSR_RSC;
+
+ if (pHalData->rf_chip == RF_PSEUDO_11N)
+ return;
+
+ /* There is no 40MHz mode in RF_8225. */
+ if (pHalData->rf_chip == RF_8225)
+ return;
+
+ if (Adapter->bDriverStopped)
+ return;
+
+ /* 3 */
+ /* 3<1>Set MAC register */
+ /* 3 */
+
+ regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE);
+ regRRSR_RSC = rtw_read8(Adapter, REG_RRSR + 2);
+
+ switch (pHalData->CurrentChannelBW) {
+ case HT_CHANNEL_WIDTH_20:
+ regBwOpMode |= BW_OPMODE_20MHZ;
+ /* 2007/02/07 Mark by Emily because we have not verify whether this register works */
+ rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
+ break;
+ case HT_CHANNEL_WIDTH_40:
+ regBwOpMode &= ~BW_OPMODE_20MHZ;
+ /* 2007/02/07 Mark by Emily because we have not verify whether this register works */
+ rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
+ regRRSR_RSC = (regRRSR_RSC & 0x90) | (pHalData->nCur40MhzPrimeSC << 5);
+ rtw_write8(Adapter, REG_RRSR + 2, regRRSR_RSC);
+ break;
+ default:
+ break;
+ }
+
+ /* 3 */
+ /* 3 <2>Set PHY related register */
+ /* 3 */
+ switch (pHalData->CurrentChannelBW) {
+ /* 20 MHz channel*/
+ case HT_CHANNEL_WIDTH_20:
+ PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0);
+ PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0);
+ break;
+ /* 40 MHz channel*/
+ case HT_CHANNEL_WIDTH_40:
+ PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1);
+ PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1);
+ /* Set Control channel to upper or lower. These settings are required only for 40MHz */
+ PHY_SetBBReg(Adapter, rCCK0_System, bCCKSideBand, (pHalData->nCur40MhzPrimeSC >> 1));
+ PHY_SetBBReg(Adapter, rOFDM1_LSTF, 0xC00, pHalData->nCur40MhzPrimeSC);
+ PHY_SetBBReg(Adapter, 0x818, (BIT(26) | BIT(27)),
+ (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+ break;
+ default:
+ break;
+ }
+ /* Skip over setting of J-mode in BB register here. Default value is "None J mode". Emily 20070315 */
+
+ /* 3<3>Set RF related register */
+ switch (pHalData->rf_chip) {
+ case RF_8225:
+ break;
+ case RF_8256:
+ /* Please implement this function in Hal8190PciPhy8256.c */
+ break;
+ case RF_PSEUDO_11N:
+ break;
+ case RF_6052:
+ rtl8188e_PHY_RF6052SetBandwidth(Adapter, pHalData->CurrentChannelBW);
+ break;
+ default:
+ break;
+ }
+}
+
+ /*-----------------------------------------------------------------------------
+ * Function: SetBWMode8190Pci()
+ *
+ * Overview: This function is export to "HalCommon" moudule
+ *
+ * Input: struct adapter *Adapter
+ * enum ht_channel_width Bandwidth 20M or 40M
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Note: We do not take j mode into consideration now
+ *---------------------------------------------------------------------------*/
+void PHY_SetBWMode8188E(struct adapter *Adapter, enum ht_channel_width Bandwidth, /* 20M or 40M */
+ unsigned char Offset) /* Upper, Lower, or Don't care */
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ enum ht_channel_width tmpBW = pHalData->CurrentChannelBW;
+
+ pHalData->CurrentChannelBW = Bandwidth;
+
+ pHalData->nCur40MhzPrimeSC = Offset;
+
+ if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved))
+ _PHY_SetBWMode92C(Adapter);
+ else
+ pHalData->CurrentChannelBW = tmpBW;
+}
+
+static void _PHY_SwChnl8192C(struct adapter *Adapter, u8 channel)
+{
+ u8 eRFPath;
+ u32 param1, param2;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+
+ if (Adapter->bNotifyChannelChange)
+ DBG_88E("[%s] ch = %d\n", __func__, channel);
+
+ /* s1. pre common command - CmdID_SetTxPowerLevel */
+ PHY_SetTxPowerLevel8188E(Adapter, channel);
+
+ /* s2. RF dependent command - CmdID_RF_WriteReg, param1=RF_CHNLBW, param2=channel */
+ param1 = RF_CHNLBW;
+ param2 = channel;
+ for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
+ pHalData->RfRegChnlVal[eRFPath] = ((pHalData->RfRegChnlVal[eRFPath] & 0xfffffc00) | param2);
+ PHY_SetRFReg(Adapter, (enum rf_radio_path)eRFPath, param1, bRFRegOffsetMask, pHalData->RfRegChnlVal[eRFPath]);
+ }
+}
+
+void PHY_SwChnl8188E(struct adapter *Adapter, u8 channel)
+{
+ /* Call after initialization */
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+
+ if (pHalData->rf_chip == RF_PSEUDO_11N)
+ return; /* return immediately if it is peudo-phy */
+
+ if (channel == 0)
+ channel = 1;
+
+ if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) {
+ pHalData->CurrentChannel = channel;
+ _PHY_SwChnl8192C(Adapter, channel);
+ }
+}
diff --git a/drivers/staging/r8188eu/hal/rtl8188e_rf6052.c b/drivers/staging/r8188eu/hal/rtl8188e_rf6052.c
new file mode 100644
index 000000000000..ad0782259654
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/rtl8188e_rf6052.c
@@ -0,0 +1,550 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+/******************************************************************************
+ *
+ *
+ * Module: rtl8192c_rf6052.c ( Source C File)
+ *
+ * Note: Provide RF 6052 series relative API.
+ *
+ * Function:
+ *
+ * Export:
+ *
+ * Abbrev:
+ *
+ * History:
+ * Data Who Remark
+ *
+ * 09/25/2008 MHC Create initial version.
+ * 11/05/2008 MHC Add API for tw power setting.
+ *
+ *
+******************************************************************************/
+
+#define _RTL8188E_RF6052_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtl8188e_hal.h"
+
+/*---------------------------Define Local Constant---------------------------*/
+/* Define local structure for debug!!!!! */
+struct rf_shadow {
+ /* Shadow register value */
+ u32 Value;
+ /* Compare or not flag */
+ u8 Compare;
+ /* Record If it had ever modified unpredicted */
+ u8 ErrorOrNot;
+ /* Recorver Flag */
+ u8 Recorver;
+ /* */
+ u8 Driver_Write;
+};
+
+/*---------------------------Define Local Constant---------------------------*/
+
+/*------------------------Define global variable-----------------------------*/
+
+/*------------------------Define local variable------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Function: RF_ChangeTxPath
+ *
+ * Overview: For RL6052, we must change some RF settign for 1T or 2T.
+ *
+ * Input: u16 DataRate 0x80-8f, 0x90-9f
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 09/25/2008 MHC Create Version 0.
+ * Firmwaer support the utility later.
+ *
+ *---------------------------------------------------------------------------*/
+void rtl8188e_RF_ChangeTxPath(struct adapter *Adapter, u16 DataRate)
+{
+/* We do not support gain table change inACUT now !!!! Delete later !!! */
+} /* RF_ChangeTxPath */
+
+/*-----------------------------------------------------------------------------
+ * Function: PHY_RF6052SetBandwidth()
+ *
+ * Overview: This function is called by SetBWModeCallback8190Pci() only
+ *
+ * Input: struct adapter *Adapter
+ * WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Note: For RF type 0222D
+ *---------------------------------------------------------------------------*/
+void rtl8188e_PHY_RF6052SetBandwidth(struct adapter *Adapter,
+ enum ht_channel_width Bandwidth)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+
+ switch (Bandwidth) {
+ case HT_CHANNEL_WIDTH_20:
+ pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10) | BIT(11));
+ PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ break;
+ case HT_CHANNEL_WIDTH_40:
+ pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10));
+ PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ break;
+ default:
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: PHY_RF6052SetCckTxPower
+ *
+ * Overview:
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/05/2008 MHC Simulate 8192series..
+ *
+ *---------------------------------------------------------------------------*/
+
+void
+rtl8188e_PHY_RF6052SetCckTxPower(
+ struct adapter *Adapter,
+ u8 *pPowerlevel)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ u32 TxAGC[2] = {0, 0}, tmpval = 0, pwrtrac_value;
+ bool TurboScanOff = false;
+ u8 idx1, idx2;
+ u8 *ptr;
+ u8 direction;
+ /* FOR CE ,must disable turbo scan */
+ TurboScanOff = true;
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
+ TxAGC[RF_PATH_A] = 0x3f3f3f3f;
+ TxAGC[RF_PATH_B] = 0x3f3f3f3f;
+
+ TurboScanOff = true;/* disable turbo scan */
+
+ if (TurboScanOff) {
+ for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
+ TxAGC[idx1] =
+ pPowerlevel[idx1] | (pPowerlevel[idx1] << 8) |
+ (pPowerlevel[idx1] << 16) | (pPowerlevel[idx1] << 24);
+ /* 2010/10/18 MH For external PA module. We need to limit power index to be less than 0x20. */
+ if (TxAGC[idx1] > 0x20 && pHalData->ExternalPA)
+ TxAGC[idx1] = 0x20;
+ }
+ }
+ } else {
+ /* Driver dynamic Tx power shall not affect Tx power.
+ * It shall be determined by power training mechanism.
+i * Currently, we cannot fully disable driver dynamic
+ * tx power mechanism because it is referenced by BT
+ * coexist mechanism.
+ * In the future, two mechanism shall be separated from
+ * each other and maintained independently. */
+ if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
+ TxAGC[RF_PATH_A] = 0x10101010;
+ TxAGC[RF_PATH_B] = 0x10101010;
+ } else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
+ TxAGC[RF_PATH_A] = 0x00000000;
+ TxAGC[RF_PATH_B] = 0x00000000;
+ } else {
+ for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
+ TxAGC[idx1] =
+ pPowerlevel[idx1] | (pPowerlevel[idx1] << 8) |
+ (pPowerlevel[idx1] << 16) | (pPowerlevel[idx1] << 24);
+ }
+ if (pHalData->EEPROMRegulatory == 0) {
+ tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) +
+ (pHalData->MCSTxPowerLevelOriginalOffset[0][7] << 8);
+ TxAGC[RF_PATH_A] += tmpval;
+
+ tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) +
+ (pHalData->MCSTxPowerLevelOriginalOffset[0][15] << 24);
+ TxAGC[RF_PATH_B] += tmpval;
+ }
+ }
+ }
+ for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
+ ptr = (u8 *)(&TxAGC[idx1]);
+ for (idx2 = 0; idx2 < 4; idx2++) {
+ if (*ptr > RF6052_MAX_TX_PWR)
+ *ptr = RF6052_MAX_TX_PWR;
+ ptr++;
+ }
+ }
+ ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 1, &direction, &pwrtrac_value);
+
+ if (direction == 1) {
+ /* Increase TX power */
+ TxAGC[0] += pwrtrac_value;
+ TxAGC[1] += pwrtrac_value;
+ } else if (direction == 2) {
+ /* Decrease TX power */
+ TxAGC[0] -= pwrtrac_value;
+ TxAGC[1] -= pwrtrac_value;
+ }
+
+ /* rf-A cck tx power */
+ tmpval = TxAGC[RF_PATH_A] & 0xff;
+ PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
+ tmpval = TxAGC[RF_PATH_A] >> 8;
+ PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+
+ /* rf-B cck tx power */
+ tmpval = TxAGC[RF_PATH_B] >> 24;
+ PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
+ tmpval = TxAGC[RF_PATH_B] & 0x00ffffff;
+ PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
+} /* PHY_RF6052SetCckTxPower */
+
+/* */
+/* powerbase0 for OFDM rates */
+/* powerbase1 for HT MCS rates */
+/* */
+static void getpowerbase88e(struct adapter *Adapter, u8 *pPowerLevelOFDM,
+ u8 *pPowerLevelBW20, u8 *pPowerLevelBW40, u8 Channel, u32 *OfdmBase, u32 *MCSBase)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u32 powerBase0, powerBase1;
+ u8 i, powerlevel[2];
+
+ for (i = 0; i < 2; i++) {
+ powerBase0 = pPowerLevelOFDM[i];
+
+ powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | (powerBase0 << 8) | powerBase0;
+ *(OfdmBase + i) = powerBase0;
+ }
+ for (i = 0; i < pHalData->NumTotalRFPath; i++) {
+ /* Check HT20 to HT40 diff */
+ if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+ powerlevel[i] = pPowerLevelBW20[i];
+ else
+ powerlevel[i] = pPowerLevelBW40[i];
+ powerBase1 = powerlevel[i];
+ powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
+ *(MCSBase + i) = powerBase1;
+ }
+}
+static void get_rx_power_val_by_reg(struct adapter *Adapter, u8 Channel,
+ u8 index, u32 *powerBase0, u32 *powerBase1,
+ u32 *pOutWriteVal)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ struct dm_priv *pdmpriv = &pHalData->dmpriv;
+ u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit;
+ s8 pwr_diff = 0;
+ u32 writeVal, customer_limit, rf;
+ u8 Regulatory = pHalData->EEPROMRegulatory;
+
+ /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
+
+ for (rf = 0; rf < 2; rf++) {
+ switch (Regulatory) {
+ case 0: /* Realtek better performance */
+ /* increase power diff defined by Realtek for large power */
+ chnlGroup = 0;
+ writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ break;
+ case 1: /* Realtek regulatory */
+ /* increase power diff defined by Realtek for regulatory */
+ if (pHalData->pwrGroupCnt == 1)
+ chnlGroup = 0;
+ if (pHalData->pwrGroupCnt >= pHalData->PGMaxGroup) {
+ if (Channel < 3) /* Channel 1-2 */
+ chnlGroup = 0;
+ else if (Channel < 6) /* Channel 3-5 */
+ chnlGroup = 1;
+ else if (Channel < 9) /* Channel 6-8 */
+ chnlGroup = 2;
+ else if (Channel < 12) /* Channel 9-11 */
+ chnlGroup = 3;
+ else if (Channel < 14) /* Channel 12-13 */
+ chnlGroup = 4;
+ else if (Channel == 14) /* Channel 14 */
+ chnlGroup = 5;
+ }
+ writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ break;
+ case 2: /* Better regulatory */
+ /* don't increase any power diff */
+ writeVal = ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ break;
+ case 3: /* Customer defined power diff. */
+ /* increase power diff defined by customer. */
+ chnlGroup = 0;
+
+ if (index < 2)
+ pwr_diff = pHalData->TxPwrLegacyHtDiff[rf][Channel - 1];
+ else if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+ pwr_diff = pHalData->TxPwrHt20Diff[rf][Channel - 1];
+
+ if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40)
+ customer_pwr_limit = pHalData->PwrGroupHT40[rf][Channel - 1];
+ else
+ customer_pwr_limit = pHalData->PwrGroupHT20[rf][Channel - 1];
+
+ if (pwr_diff >= customer_pwr_limit)
+ pwr_diff = 0;
+ else
+ pwr_diff = customer_pwr_limit - pwr_diff;
+
+ for (i = 0; i < 4; i++) {
+ pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] & (0x7f << (i * 8))) >> (i * 8));
+
+ if (pwr_diff_limit[i] > pwr_diff)
+ pwr_diff_limit[i] = pwr_diff;
+ }
+ customer_limit = (pwr_diff_limit[3] << 24) | (pwr_diff_limit[2] << 16) |
+ (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
+ writeVal = customer_limit + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ break;
+ default:
+ chnlGroup = 0;
+ writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+ break;
+ }
+/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
+/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
+/* In the future, two mechanism shall be separated from each other and maintained independently. Thanks for Lanhsin's reminder. */
+ /* 92d do not need this */
+ if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
+ writeVal = 0x14141414;
+ else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
+ writeVal = 0x00000000;
+
+ /* 20100628 Joseph: High power mode for BT-Coexist mechanism. */
+ /* This mechanism is only applied when Driver-Highpower-Mechanism is OFF. */
+ if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT1)
+ writeVal = writeVal - 0x06060606;
+ *(pOutWriteVal + rf) = writeVal;
+ }
+}
+static void writeOFDMPowerReg88E(struct adapter *Adapter, u8 index, u32 *pValue)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u16 regoffset_a[6] = {
+ rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
+ rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
+ rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12};
+ u16 regoffset_b[6] = {
+ rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
+ rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
+ rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12};
+ u8 i, rf, pwr_val[4];
+ u32 writeVal;
+ u16 regoffset;
+
+ for (rf = 0; rf < 2; rf++) {
+ writeVal = pValue[rf];
+ for (i = 0; i < 4; i++) {
+ pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >> (i * 8));
+ if (pwr_val[i] > RF6052_MAX_TX_PWR)
+ pwr_val[i] = RF6052_MAX_TX_PWR;
+ }
+ writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | (pwr_val[1] << 8) | pwr_val[0];
+
+ if (rf == 0)
+ regoffset = regoffset_a[index];
+ else
+ regoffset = regoffset_b[index];
+
+ PHY_SetBBReg(Adapter, regoffset, bMaskDWord, writeVal);
+
+ /* 201005115 Joseph: Set Tx Power diff for Tx power training mechanism. */
+ if (((pHalData->rf_type == RF_2T2R) &&
+ (regoffset == rTxAGC_A_Mcs15_Mcs12 || regoffset == rTxAGC_B_Mcs15_Mcs12)) ||
+ ((pHalData->rf_type != RF_2T2R) &&
+ (regoffset == rTxAGC_A_Mcs07_Mcs04 || regoffset == rTxAGC_B_Mcs07_Mcs04))) {
+ writeVal = pwr_val[3];
+ if (regoffset == rTxAGC_A_Mcs15_Mcs12 || regoffset == rTxAGC_A_Mcs07_Mcs04)
+ regoffset = 0xc90;
+ if (regoffset == rTxAGC_B_Mcs15_Mcs12 || regoffset == rTxAGC_B_Mcs07_Mcs04)
+ regoffset = 0xc98;
+ for (i = 0; i < 3; i++) {
+ if (i != 2)
+ writeVal = (writeVal > 8) ? (writeVal - 8) : 0;
+ else
+ writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
+ rtw_write8(Adapter, (u32)(regoffset + i), (u8)writeVal);
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: PHY_RF6052SetOFDMTxPower
+ *
+ * Overview: For legacy and HY OFDM, we must read EEPROM TX power index for
+ * different channel and read original value in TX power register area from
+ * 0xe00. We increase offset and original value to be correct tx pwr.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 11/05/2008 MHC Simulate 8192 series method.
+ * 01/06/2009 MHC 1. Prevent Path B tx power overflow or underflow dure to
+ * A/B pwr difference or legacy/HT pwr diff.
+ * 2. We concern with path B legacy/HT OFDM difference.
+ * 01/22/2009 MHC Support new EPRO format from SD3.
+ *
+ *---------------------------------------------------------------------------*/
+
+void
+rtl8188e_PHY_RF6052SetOFDMTxPower(
+ struct adapter *Adapter,
+ u8 *pPowerLevelOFDM,
+ u8 *pPowerLevelBW20,
+ u8 *pPowerLevelBW40,
+ u8 Channel)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u32 writeVal[2], powerBase0[2], powerBase1[2], pwrtrac_value;
+ u8 direction;
+ u8 index = 0;
+
+ getpowerbase88e(Adapter, pPowerLevelOFDM, pPowerLevelBW20, pPowerLevelBW40, Channel, &powerBase0[0], &powerBase1[0]);
+
+ /* 2012/04/23 MH According to power tracking value, we need to revise OFDM tx power. */
+ /* This is ued to fix unstable power tracking mode. */
+ ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 0, &direction, &pwrtrac_value);
+
+ for (index = 0; index < 6; index++) {
+ get_rx_power_val_by_reg(Adapter, Channel, index,
+ &powerBase0[0], &powerBase1[0],
+ &writeVal[0]);
+
+ if (direction == 1) {
+ writeVal[0] += pwrtrac_value;
+ writeVal[1] += pwrtrac_value;
+ } else if (direction == 2) {
+ writeVal[0] -= pwrtrac_value;
+ writeVal[1] -= pwrtrac_value;
+ }
+ writeOFDMPowerReg88E(Adapter, index, &writeVal[0]);
+ }
+}
+
+static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
+{
+ struct bb_reg_def *pPhyReg;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ u32 u4RegValue = 0;
+ u8 eRFPath;
+ int rtStatus = _SUCCESS;
+
+ /* 3----------------------------------------------------------------- */
+ /* 3 <2> Initialize RF */
+ /* 3----------------------------------------------------------------- */
+ for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
+ pPhyReg = &pHalData->PHYRegDef[eRFPath];
+
+ /*----Store original RFENV control type----*/
+ switch (eRFPath) {
+ case RF_PATH_A:
+ case RF_PATH_C:
+ u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
+ break;
+ case RF_PATH_B:
+ case RF_PATH_D:
+ u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16);
+ break;
+ }
+ /*----Set RF_ENV enable----*/
+ PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1);
+ udelay(1);/* PlatformStallExecution(1); */
+
+ /*----Set RF_ENV output high----*/
+ PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
+ udelay(1);/* PlatformStallExecution(1); */
+
+ /* Set bit number of Address and Data for RF register */
+ PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */
+ udelay(1);/* PlatformStallExecution(1); */
+
+ PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */
+ udelay(1);/* PlatformStallExecution(1); */
+
+ /*----Initialize RF fom connfiguration file----*/
+ switch (eRFPath) {
+ case RF_PATH_A:
+ if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, (enum rf_radio_path)eRFPath, (enum rf_radio_path)eRFPath))
+ rtStatus = _FAIL;
+ break;
+ case RF_PATH_B:
+ if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, (enum rf_radio_path)eRFPath, (enum rf_radio_path)eRFPath))
+ rtStatus = _FAIL;
+ break;
+ case RF_PATH_C:
+ break;
+ case RF_PATH_D:
+ break;
+ }
+ /*----Restore RFENV control type----*/;
+ switch (eRFPath) {
+ case RF_PATH_A:
+ case RF_PATH_C:
+ PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
+ break;
+ case RF_PATH_B:
+ case RF_PATH_D:
+ PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue);
+ break;
+ }
+ if (rtStatus != _SUCCESS)
+ goto phy_RF6052_Config_ParaFile_Fail;
+ }
+ return rtStatus;
+
+phy_RF6052_Config_ParaFile_Fail:
+ return rtStatus;
+}
+
+int PHY_RF6052_Config8188E(struct adapter *Adapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
+ int rtStatus = _SUCCESS;
+
+ /* */
+ /* Initialize general global value */
+ /* */
+ /* TODO: Extend RF_PATH_C and RF_PATH_D in the future */
+ if (pHalData->rf_type == RF_1T1R)
+ pHalData->NumTotalRFPath = 1;
+ else
+ pHalData->NumTotalRFPath = 2;
+
+ /* */
+ /* Config BB and RF */
+ /* */
+ rtStatus = phy_RF6052_Config_ParaFile(Adapter);
+ return rtStatus;
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c
index 05dbd3f08328..244286789b6d 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
+++ b/drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c
@@ -1,14 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#define _RTL8188E_REDESC_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtl8188e_hal.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtl8188e_hal.h"
static void process_rssi(struct adapter *padapter, struct recv_frame *prframe)
{
@@ -26,8 +23,7 @@ static void process_rssi(struct adapter *padapter, struct recv_frame *prframe)
signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
} /* Process_UI_RSSI_8192C */
-static void process_link_qual(struct adapter *padapter,
- struct recv_frame *prframe)
+static void process_link_qual(struct adapter *padapter, struct recv_frame *prframe)
{
struct rx_pkt_attrib *pattrib;
struct signal_stat *signal_stat;
@@ -49,17 +45,17 @@ static void process_link_qual(struct adapter *padapter,
signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
}
-void rtl8188e_process_phy_info(struct adapter *padapter,
- struct recv_frame *precvframe)
+void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe)
{
+ struct recv_frame *precvframe = (struct recv_frame *)prframe;
+
/* Check RSSI */
process_rssi(padapter, precvframe);
/* Check EVM */
process_link_qual(padapter, precvframe);
}
-void update_recvframe_attrib_88e(struct recv_frame *precvframe,
- struct recv_stat *prxstat)
+void update_recvframe_attrib_88e(struct recv_frame *precvframe, struct recv_stat *prxstat)
{
struct rx_pkt_attrib *pattrib;
struct recv_stat report;
@@ -126,15 +122,13 @@ void update_recvframe_attrib_88e(struct recv_frame *precvframe,
* Before calling this function,
* precvframe->rx_data should be ready!
*/
-void update_recvframe_phyinfo_88e(struct recv_frame *precvframe,
- struct phy_stat *pphy_status)
+void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, struct phy_stat *pphy_status)
{
struct adapter *padapter = precvframe->adapter;
struct rx_pkt_attrib *pattrib = &precvframe->attrib;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
struct odm_phy_status_info *pPHYInfo = (struct odm_phy_status_info *)(&pattrib->phy_info);
u8 *wlanhdr;
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *)precvframe->pkt->data;
struct odm_per_pkt_info pkt_info;
u8 *sa = NULL;
struct sta_priv *pstapriv;
@@ -144,26 +138,26 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe,
pkt_info.bPacketToSelf = false;
pkt_info.bPacketBeacon = false;
- wlanhdr = precvframe->pkt->data;
+ wlanhdr = get_recvframe_data(precvframe);
- pkt_info.bPacketMatchBSSID = (!ieee80211_is_ctl(hdr->frame_control) &&
+ pkt_info.bPacketMatchBSSID = ((!IsFrameTypeCtrl(wlanhdr)) &&
!pattrib->icv_err && !pattrib->crc_err &&
!memcmp(get_hdr_bssid(wlanhdr),
get_bssid(&padapter->mlmepriv), ETH_ALEN));
pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
- (!memcmp(ieee80211_get_DA(hdr),
+ (!memcmp(get_da(wlanhdr),
myid(&padapter->eeprompriv), ETH_ALEN));
pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
- (GetFrameSubType(wlanhdr) == IEEE80211_STYPE_BEACON);
+ (GetFrameSubType(wlanhdr) == WIFI_BEACON);
if (pkt_info.bPacketBeacon) {
if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE))
sa = padapter->mlmepriv.cur_network.network.MacAddress;
/* to do Ad-hoc */
} else {
- sa = ieee80211_get_SA(hdr);
+ sa = get_sa(wlanhdr);
}
pstapriv = &padapter->stapriv;
@@ -173,8 +167,7 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe,
pkt_info.StationID = psta->mac_id;
pkt_info.Rate = pattrib->mcs_rate;
- odm_phy_status_query(&padapter->HalData->odmpriv, pPHYInfo,
- (u8 *)pphy_status, &(pkt_info));
+ ODM_PhyStatusQuery(&pHalData->odmpriv, pPHYInfo, (u8 *)pphy_status, &(pkt_info), padapter);
precvframe->psta = NULL;
if (pkt_info.bPacketMatchBSSID &&
diff --git a/drivers/staging/r8188eu/hal/rtl8188e_sreset.c b/drivers/staging/r8188eu/hal/rtl8188e_sreset.c
new file mode 100644
index 000000000000..16fa249e35d3
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/rtl8188e_sreset.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTL8188E_SRESET_C_
+
+#include "../include/rtl8188e_sreset.h"
+#include "../include/rtl8188e_hal.h"
+
+void rtl8188e_silentreset_for_specific_platform(struct adapter *padapter)
+{
+}
+
+void rtl8188e_sreset_xmit_status_check(struct adapter *padapter)
+{
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+ struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+ unsigned long current_time;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ unsigned int diff_time;
+ u32 txdma_status;
+
+ txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
+ if (txdma_status != 0x00) {
+ DBG_88E("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
+ rtw_write32(padapter, REG_TXDMA_STATUS, txdma_status);
+ rtl8188e_silentreset_for_specific_platform(padapter);
+ }
+ /* total xmit irp = 4 */
+ current_time = jiffies;
+ if (0 == pxmitpriv->free_xmitbuf_cnt) {
+ diff_time = jiffies_to_msecs(current_time - psrtpriv->last_tx_time);
+
+ if (diff_time > 2000) {
+ if (psrtpriv->last_tx_complete_time == 0) {
+ psrtpriv->last_tx_complete_time = current_time;
+ } else {
+ diff_time = jiffies_to_msecs(current_time - psrtpriv->last_tx_complete_time);
+ if (diff_time > 4000) {
+ DBG_88E("%s tx hang\n", __func__);
+ rtl8188e_silentreset_for_specific_platform(padapter);
+ }
+ }
+ }
+ }
+}
+
+void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
+{
+ u32 rx_dma_status = 0;
+ u8 fw_status = 0;
+ rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS);
+ if (rx_dma_status != 0x00) {
+ DBG_88E("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status);
+ rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
+ }
+ fw_status = rtw_read8(padapter, REG_FMETHR);
+ if (fw_status != 0x00) {
+ if (fw_status == 1)
+ DBG_88E("%s REG_FW_STATUS (0x%02x), Read_Efuse_Fail !!\n", __func__, fw_status);
+ else if (fw_status == 2)
+ DBG_88E("%s REG_FW_STATUS (0x%02x), Condition_No_Match !!\n", __func__, fw_status);
+ }
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c b/drivers/staging/r8188eu/hal/rtl8188e_xmit.c
index efa8960a7eb5..46b871f3f631 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c
+++ b/drivers/staging/r8188eu/hal/rtl8188e_xmit.c
@@ -1,14 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#define _RTL8188E_XMIT_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtl8188e_hal.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtl8188e_hal.h"
void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf)
{
diff --git a/drivers/staging/r8188eu/hal/rtl8188eu_led.c b/drivers/staging/r8188eu/hal/rtl8188eu_led.c
new file mode 100644
index 000000000000..452d4bb87aba
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/rtl8188eu_led.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtl8188e_hal.h"
+#include "../include/rtl8188e_led.h"
+
+/* LED object. */
+
+/* LED_819xUsb routines. */
+/* Description: */
+/* Turn on LED according to LedPin specified. */
+void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
+{
+ u8 LedCfg;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return;
+ LedCfg = rtw_read8(padapter, REG_LEDCFG2);
+ switch (pLed->LedPin) {
+ case LED_PIN_LED0:
+ rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0xf0) | BIT(5) | BIT(6)); /* SW control led0 on. */
+ break;
+ case LED_PIN_LED1:
+ rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0x0f) | BIT(5)); /* SW control led1 on. */
+ break;
+ default:
+ break;
+ }
+ pLed->bLedOn = true;
+}
+
+/* Description: */
+/* Turn off LED according to LedPin specified. */
+void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
+{
+ u8 LedCfg;
+ struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ goto exit;
+
+ LedCfg = rtw_read8(padapter, REG_LEDCFG2);/* 0x4E */
+
+ switch (pLed->LedPin) {
+ case LED_PIN_LED0:
+ if (pHalData->bLedOpenDrain) {
+ /* Open-drain arrangement for controlling the LED) */
+ LedCfg &= 0x90; /* Set to software control. */
+ rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3)));
+ LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG);
+ LedCfg &= 0xFE;
+ rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
+ } else {
+ rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3) | BIT(5) | BIT(6)));
+ }
+ break;
+ case LED_PIN_LED1:
+ LedCfg &= 0x0f; /* Set to software control. */
+ rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3)));
+ break;
+ default:
+ break;
+ }
+exit:
+ pLed->bLedOn = false;
+}
+
+/* Interface to manipulate LED objects. */
+/* Default LED behavior. */
+
+/* Description: */
+/* Initialize all LED_871x objects. */
+void rtl8188eu_InitSwLeds(struct adapter *padapter)
+{
+ struct led_priv *pledpriv = &padapter->ledpriv;
+
+ pledpriv->LedControlHandler = LedControl8188eu;
+
+ InitLed871x(padapter, &pledpriv->SwLed0, LED_PIN_LED0);
+
+ InitLed871x(padapter, &pledpriv->SwLed1, LED_PIN_LED1);
+}
+
+/* Description: */
+/* DeInitialize all LED_819xUsb objects. */
+void rtl8188eu_DeInitSwLeds(struct adapter *padapter)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+
+ DeInitLed871x(&ledpriv->SwLed0);
+ DeInitLed871x(&ledpriv->SwLed1);
+}
diff --git a/drivers/staging/r8188eu/hal/rtl8188eu_recv.c b/drivers/staging/r8188eu/hal/rtl8188eu_recv.c
new file mode 100644
index 000000000000..2da7bde80cc0
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/rtl8188eu_recv.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _RTL8188EU_RECV_C_
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/mlme_osdep.h"
+
+#include "../include/usb_ops.h"
+#include "../include/wifi.h"
+
+#include "../include/rtl8188e_hal.h"
+
+void rtl8188eu_init_recvbuf(struct adapter *padapter, struct recv_buf *precvbuf)
+{
+ precvbuf->transfer_len = 0;
+
+ precvbuf->len = 0;
+
+ precvbuf->ref_cnt = 0;
+
+ if (precvbuf->pbuf) {
+ precvbuf->pdata = precvbuf->pbuf;
+ precvbuf->phead = precvbuf->pbuf;
+ precvbuf->ptail = precvbuf->pbuf;
+ precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ;
+ }
+}
+
+int rtl8188eu_init_recv_priv(struct adapter *padapter)
+{
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+ int i, res = _SUCCESS;
+ struct recv_buf *precvbuf;
+
+ tasklet_init(&precvpriv->recv_tasklet,
+ rtl8188eu_recv_tasklet,
+ (unsigned long)padapter);
+
+ /* init recv_buf */
+ _rtw_init_queue(&precvpriv->free_recv_buf_queue);
+
+ precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4,
+ GFP_KERNEL);
+ if (!precvpriv->pallocated_recv_buf) {
+ res = _FAIL;
+ goto exit;
+ }
+ memset(precvpriv->pallocated_recv_buf, 0, NR_RECVBUFF * sizeof(struct recv_buf) + 4);
+
+ precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_recv_buf), 4);
+
+ precvbuf = (struct recv_buf *)precvpriv->precv_buf;
+
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ INIT_LIST_HEAD(&precvbuf->list);
+ spin_lock_init(&precvbuf->recvbuf_lock);
+ precvbuf->alloc_sz = MAX_RECVBUF_SZ;
+ res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
+ if (res == _FAIL)
+ break;
+ precvbuf->ref_cnt = 0;
+ precvbuf->adapter = padapter;
+ precvbuf++;
+ }
+ precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
+ skb_queue_head_init(&precvpriv->rx_skb_queue);
+ {
+ int i;
+ size_t tmpaddr = 0;
+ size_t alignment = 0;
+ struct sk_buff *pskb = NULL;
+
+ skb_queue_head_init(&precvpriv->free_recv_skb_queue);
+
+ for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
+ pskb = __netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL);
+ if (pskb) {
+ pskb->dev = padapter->pnetdev;
+ tmpaddr = (size_t)pskb->data;
+ alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
+ skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
+
+ skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
+ }
+ pskb = NULL;
+ }
+ }
+exit:
+ return res;
+}
+
+void rtl8188eu_free_recv_priv(struct adapter *padapter)
+{
+ int i;
+ struct recv_buf *precvbuf;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
+ precvbuf = (struct recv_buf *)precvpriv->precv_buf;
+
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ rtw_os_recvbuf_resource_free(padapter, precvbuf);
+ precvbuf++;
+ }
+
+ kfree(precvpriv->pallocated_recv_buf);
+
+ if (skb_queue_len(&precvpriv->rx_skb_queue))
+ DBG_88E(KERN_WARNING "rx_skb_queue not empty\n");
+ skb_queue_purge(&precvpriv->rx_skb_queue);
+
+ if (skb_queue_len(&precvpriv->free_recv_skb_queue))
+ DBG_88E(KERN_WARNING "free_recv_skb_queue not empty, %d\n", skb_queue_len(&precvpriv->free_recv_skb_queue));
+
+ skb_queue_purge(&precvpriv->free_recv_skb_queue);
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/r8188eu/hal/rtl8188eu_xmit.c
index 1fa558e0de38..17be67ac5fae 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
+++ b/drivers/staging/r8188eu/hal/rtl8188eu_xmit.c
@@ -1,35 +1,37 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#define _RTL8188E_XMIT_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <mon.h>
-#include <wifi.h>
-#include <osdep_intf.h>
-#include <usb_ops_linux.h>
-#include <rtl8188e_hal.h>
-
-s32 rtw_hal_init_xmit_priv(struct adapter *adapt)
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/wifi.h"
+#include "../include/osdep_intf.h"
+#include "../include/usb_ops.h"
+#include "../include/rtl8188e_hal.h"
+
+s32 rtl8188eu_init_xmit_priv(struct adapter *adapt)
{
- struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
+ struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
- tasklet_setup(&pxmitpriv->xmit_tasklet, rtl8188eu_xmit_tasklet);
+ tasklet_init(&pxmitpriv->xmit_tasklet,
+ rtl8188eu_xmit_tasklet,
+ (unsigned long)adapt);
return _SUCCESS;
}
static u8 urb_zero_packet_chk(struct adapter *adapt, int sz)
{
- return !((sz + TXDESC_SIZE) % adapt->HalData->UsbBulkOutSize);
+ u8 set_tx_desc_offset;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+ set_tx_desc_offset = (((sz + TXDESC_SIZE) % haldata->UsbBulkOutSize) == 0) ? 1 : 0;
+
+ return set_tx_desc_offset;
}
static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
{
- u16 *usptr = (u16 *)ptxdesc;
- u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
+ u16 *usptr = (u16 *)ptxdesc;
+ u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
u32 index;
u16 checksum = 0;
@@ -41,11 +43,9 @@ static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff & checksum);
}
-/*
- * In normal chip, we should send some packet to Hw which will be used by Fw
- * in FW LPS mode. The function is to fill the Tx descriptor of this packets,
- * then Fw can tell Hw to send these packet derectly.
- */
+/* Description: In normal chip, we should send some packet to Hw which will be used by Fw */
+/* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */
+/* Fw can tell Hw to send these packet derectly. */
void rtl8188e_fill_fake_txdesc(struct adapter *adapt, u8 *desc, u32 BufferLen, u8 ispspoll, u8 is_btqosnull)
{
struct tx_desc *ptxdesc;
@@ -126,7 +126,7 @@ static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw)
*pdw |= cpu_to_le32(HW_RTS_EN);
/* Set RTS BW */
if (pattrib->ht_en) {
- *pdw |= (pattrib->bwmode & HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
+ *pdw |= (pattrib->bwmode & HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
*pdw |= cpu_to_le32((0x01 << 28) & 0x30000000);
@@ -143,7 +143,7 @@ static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw)
static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw)
{
if (pattrib->ht_en) {
- *pdw |= (pattrib->bwmode & HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
+ *pdw |= (pattrib->bwmode & HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
*pdw |= cpu_to_le32((0x01 << DATA_SC_SHT) & 0x003f0000);
@@ -158,15 +158,15 @@ static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw)
static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
{
- int pull = 0;
- uint qsel;
+ int pull = 0;
+ uint qsel;
u8 data_rate, pwr_status, offset;
- struct adapter *adapt = pxmitframe->padapter;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct odm_dm_struct *odmpriv = &adapt->HalData->odmpriv;
- struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
- struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct adapter *adapt = pxmitframe->padapter;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+ struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
if (adapt->registrypriv.mp_mode == 0) {
if ((!bagg_pkt) && (urb_zero_packet_chk(adapt, sz) == 0)) {
@@ -246,12 +246,12 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag
ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */
if (pattrib->ht_en) {
- if (ODM_RA_GetShortGI_8188E(odmpriv, pattrib->mac_id))
+ if (ODM_RA_GetShortGI_8188E(&haldata->odmpriv, pattrib->mac_id))
ptxdesc->txdw5 |= cpu_to_le32(SGI);/* SGI */
}
- data_rate = ODM_RA_GetDecisionRate_8188E(odmpriv, pattrib->mac_id);
+ data_rate = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, pattrib->mac_id);
ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F);
- pwr_status = ODM_RA_GetHwPwrStatus_8188E(odmpriv, pattrib->mac_id);
+ pwr_status = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, pattrib->mac_id);
ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT);
} else {
/* EAP data packet and ARP packet and DHCP. */
@@ -287,7 +287,14 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag
ptxdesc->txdw5 |= cpu_to_le32(0x00300000);/* retry limit = 12 */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
+ } else if ((pxmitframe->frame_tag & 0x0f) == TXAGG_FRAMETAG) {
+ DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
+ } else if (((pxmitframe->frame_tag & 0x0f) == MP_FRAMETAG) &&
+ (adapt->registrypriv.mp_mode == 1)) {
+ fill_txdesc_for_mp(adapt, ptxdesc);
} else {
+ DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
+
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f);/* CAM_ID(MAC_ID) */
@@ -315,13 +322,13 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag
ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */
}
- rtl88eu_dm_set_tx_ant_by_tx_info(odmpriv, pmem, pattrib->mac_id);
+ ODM_SetTxAntByTxInfo_88E(&haldata->odmpriv, pmem, pattrib->mac_id);
rtl8188eu_cal_txdesc_chksum(ptxdesc);
return pull;
}
-/* for non-agg data frame or management frame */
+/* for non-agg data frame or management frame */
static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
{
s32 ret = _SUCCESS;
@@ -332,7 +339,7 @@ static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
-
+ struct security_priv *psecuritypriv = &adapt->securitypriv;
if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
(pxmitframe->attrib.ether_type != 0x0806) &&
(pxmitframe->attrib.ether_type != 0x888e) &&
@@ -347,7 +354,7 @@ static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
if (t != (pattrib->nr_frags - 1)) {
sz = pxmitpriv->frag_len;
- sz = sz - 4 - pattrib->icv_len;
+ sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);
} else {
/* no frag */
sz = pattrib->last_txcmdsz;
@@ -364,13 +371,13 @@ static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
}
ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
- inner_ret = usb_write_port(adapt, ff_hwaddr, w_sz, pxmitbuf);
+ inner_ret = rtw_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf);
rtw_count_tx_stats(adapt, pxmitframe, sz);
mem_addr += w_sz;
- mem_addr = (u8 *)round_up((size_t)mem_addr, 4);
+ mem_addr = (u8 *)RND4(((size_t)(mem_addr)));
}
rtw_free_xmitframe(pxmitpriv, pxmitframe);
@@ -385,7 +392,7 @@ static u32 xmitframe_need_length(struct xmit_frame *pxmitframe)
{
struct pkt_attrib *pattrib = &pxmitframe->attrib;
- u32 len;
+ u32 len = 0;
/* no consider fragement */
len = pattrib->hdrlen + pattrib->iv_len +
@@ -399,60 +406,67 @@ static u32 xmitframe_need_length(struct xmit_frame *pxmitframe)
return len;
}
-bool rtl8188eu_xmitframe_complete(struct adapter *adapt,
- struct xmit_priv *pxmitpriv)
+s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
{
- struct xmit_frame *pxmitframe, *n;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+ struct xmit_frame *pxmitframe = NULL;
struct xmit_frame *pfirstframe = NULL;
- struct xmit_buf *pxmitbuf;
/* aggregate variable */
struct hw_xmit *phwxmit;
struct sta_info *psta = NULL;
struct tx_servq *ptxservq = NULL;
-
- struct list_head *xmitframe_phead = NULL;
+ struct list_head *xmitframe_plist = NULL, *xmitframe_phead = NULL;
u32 pbuf; /* next pkt address */
u32 pbuf_tail; /* last pkt tail */
u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */
- u32 bulksize = adapt->HalData->UsbBulkOutSize;
+ u32 bulksize = haldata->UsbBulkOutSize;
u8 desc_cnt;
u32 bulkptr;
/* dump frame variable */
u32 ff_hwaddr;
- pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
- if (!pxmitbuf)
- return false;
+ /* check xmitbuffer is ok */
+ if (!pxmitbuf) {
+ pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
+ if (!pxmitbuf)
+ return false;
+ }
/* 3 1. pick up first frame */
- pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
- if (!pxmitframe) {
- /* no more xmit frame, release xmit buffer */
- rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
- return false;
- }
+ do {
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
- pxmitframe->pxmitbuf = pxmitbuf;
- pxmitframe->buf_addr = pxmitbuf->pbuf;
- pxmitbuf->priv_data = pxmitframe;
+ pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
+ if (!pxmitframe) {
+ /* no more xmit frame, release xmit buffer */
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ return false;
+ }
+
+ pxmitframe->pxmitbuf = pxmitbuf;
+ pxmitframe->buf_addr = pxmitbuf->pbuf;
+ pxmitbuf->priv_data = pxmitframe;
- pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */
- pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */
+ pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */
+ pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */
+
+ rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
- rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
+ /* always return ndis_packet after rtw_xmitframe_coalesce */
+ rtw_os_xmit_complete(adapt, pxmitframe);
- /* always return ndis_packet after rtw_xmitframe_coalesce */
- rtw_os_xmit_complete(adapt, pxmitframe);
+ break;
+ } while (1);
/* 3 2. aggregate same priority and same DA(AP or STA) frames */
pfirstframe = pxmitframe;
len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset * PACKET_OFFSET_SZ);
pbuf_tail = len;
- pbuf = round_up(pbuf_tail, 8);
+ pbuf = _RND8(pbuf_tail);
/* check pkt amount in one bulk */
desc_cnt = 0;
@@ -492,13 +506,18 @@ bool rtl8188eu_xmitframe_complete(struct adapter *adapt,
spin_lock_bh(&pxmitpriv->lock);
xmitframe_phead = get_list_head(&ptxservq->sta_pending);
- list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, list) {
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+ xmitframe_plist = xmitframe_plist->next;
+
pxmitframe->agg_num = 0; /* not first frame of aggregation */
pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */
len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
- if (round_up(pbuf + len, 8) > MAX_XMITBUF_SZ) {
+ if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) {
pxmitframe->agg_num = 1;
pxmitframe->pkt_offset = 1;
break;
@@ -521,15 +540,15 @@ bool rtl8188eu_xmitframe_complete(struct adapter *adapt,
/* handle pointer and stop condition */
pbuf_tail = pbuf + len;
- pbuf = round_up(pbuf_tail, 8);
+ pbuf = _RND8(pbuf_tail);
pfirstframe->agg_num++;
- if (pfirstframe->agg_num == MAX_TX_AGG_PACKET_NUMBER)
+ if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num)
break;
if (pbuf < bulkptr) {
desc_cnt++;
- if (desc_cnt == adapt->HalData->UsbTxAggDescNum)
+ if (desc_cnt == haldata->UsbTxAggDescNum)
break;
} else {
desc_cnt = 0;
@@ -558,7 +577,7 @@ bool rtl8188eu_xmitframe_complete(struct adapter *adapt,
/* 3 4. write xmit buffer to USB FIFO */
ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe);
- usb_write_port(adapt, ff_hwaddr, pbuf_tail, pxmitbuf);
+ rtw_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf);
/* 3 5. update statisitc */
pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE);
@@ -571,12 +590,24 @@ bool rtl8188eu_xmitframe_complete(struct adapter *adapt,
return true;
}
+static s32 xmitframe_direct(struct adapter *adapt, struct xmit_frame *pxmitframe)
+{
+ s32 res = _SUCCESS;
+
+ res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
+ if (res == _SUCCESS)
+ rtw_dump_xframe(adapt, pxmitframe);
+ else
+ DBG_88E("==> %s xmitframe_coalsece failed\n", __func__);
+ return res;
+}
+
/*
* Return
* true dump packet directly
* false enqueue packet
*/
-bool rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
+static s32 pre_xmitframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
{
s32 res;
struct xmit_buf *pxmitbuf = NULL;
@@ -602,11 +633,7 @@ bool rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
pxmitframe->buf_addr = pxmitbuf->pbuf;
pxmitbuf->priv_data = pxmitframe;
- res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
-
- if (res == _SUCCESS) {
- rtw_dump_xframe(adapt, pxmitframe);
- } else {
+ if (xmitframe_direct(adapt, pxmitframe) != _SUCCESS) {
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
rtw_free_xmitframe(pxmitpriv, pxmitframe);
}
@@ -629,10 +656,17 @@ enqueue:
return false;
}
-s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe)
+s32 rtl8188eu_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe)
{
- struct xmit_priv *xmitpriv = &adapt->xmitpriv;
-
- rtl88eu_mon_xmit_hook(adapt->pmondev, pmgntframe, xmitpriv->frag_len);
return rtw_dump_xframe(adapt, pmgntframe);
}
+
+/*
+ * Return
+ * true dump packet directly ok
+ * false temporary can't transmit packets to hardware
+ */
+s32 rtl8188eu_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
+{
+ return pre_xmitframe(adapt, pxmitframe);
+}
diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/r8188eu/hal/usb_halinit.c
index 05c67e7d23ad..5cdabf43d4fd 100644
--- a/drivers/staging/rtl8188eu/hal/usb_halinit.c
+++ b/drivers/staging/r8188eu/hal/usb_halinit.c
@@ -1,23 +1,25 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#define _HCI_HAL_INIT_C_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtw_efuse.h>
-#include <fw.h>
-#include <rtl8188e_hal.h>
-#include <phy.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/rtw_efuse.h"
+
+#include "../include/rtl8188e_hal.h"
+#include "../include/rtl8188e_led.h"
+#include "../include/rtw_iol.h"
+#include "../include/usb_ops.h"
+#include "../include/usb_osintf.h"
+#define HAL_MAC_ENABLE 1
#define HAL_BB_ENABLE 1
+#define HAL_RF_ENABLE 1
static void _ConfigNormalChipOutEP_8188E(struct adapter *adapt, u8 NumOutPipe)
{
- struct hal_data_8188e *haldata = adapt->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
switch (NumOutPipe) {
case 3:
@@ -35,30 +37,32 @@ static void _ConfigNormalChipOutEP_8188E(struct adapter *adapt, u8 NumOutPipe)
default:
break;
}
+ DBG_88E("%s OutEpQueueSel(0x%02x), OutEpNumber(%d)\n", __func__, haldata->OutEpQueueSel, haldata->OutEpNumber);
}
static bool HalUsbSetQueuePipeMapping8188EUsb(struct adapter *adapt, u8 NumInPipe, u8 NumOutPipe)
{
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
bool result = false;
_ConfigNormalChipOutEP_8188E(adapt, NumOutPipe);
/* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */
- if (adapt->HalData->OutEpNumber == 1) {
- if (NumInPipe != 1)
+ if (1 == haldata->OutEpNumber) {
+ if (1 != NumInPipe)
return result;
}
/* All config other than above support one Bulk IN and one Interrupt IN. */
- result = hal_mapping_out_pipe(adapt, NumOutPipe);
+ result = Hal_MappingOutPipe(adapt, NumOutPipe);
return result;
}
-void rtw_hal_chip_configure(struct adapter *adapt)
+static void rtl8188eu_interface_configure(struct adapter *adapt)
{
- struct hal_data_8188e *haldata = adapt->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapt);
if (pdvobjpriv->ishighspeed)
@@ -77,33 +81,35 @@ void rtw_hal_chip_configure(struct adapter *adapt)
haldata->UsbRxAggPageCount = 48; /* uint :128 b 0x0A; 10 = MAX_RX_DMA_BUFFER_SIZE/2/haldata->UsbBulkOutSize */
haldata->UsbRxAggPageTimeout = 0x4; /* 6, absolute time = 34ms/(2^6) */
- HalUsbSetQueuePipeMapping8188EUsb(adapt, pdvobjpriv->RtNumInPipes,
- pdvobjpriv->RtNumOutPipes);
+ HalUsbSetQueuePipeMapping8188EUsb(adapt,
+ pdvobjpriv->RtNumInPipes, pdvobjpriv->RtNumOutPipes);
}
-u32 rtw_hal_power_on(struct adapter *adapt)
+static u32 rtl8188eu_InitPowerOn(struct adapter *adapt)
{
u16 value16;
/* HW Power on sequence */
- if (adapt->HalData->bMacPwrCtrlOn)
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+ if (haldata->bMacPwrCtrlOn)
return _SUCCESS;
- if (!rtl88eu_pwrseqcmdparsing(adapt, PWR_CUT_ALL_MSK,
- Rtl8188E_NIC_PWR_ON_FLOW))
+ if (!HalPwrSeqCmdParsing(adapt, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, Rtl8188E_NIC_PWR_ON_FLOW)) {
+ DBG_88E(KERN_ERR "%s: run power on flow fail\n", __func__);
return _FAIL;
+ }
/* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
/* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
- usb_write16(adapt, REG_CR, 0x00); /* suggseted by zhouzhou, by page, 20111230 */
+ rtw_write16(adapt, REG_CR, 0x00); /* suggseted by zhouzhou, by page, 20111230 */
/* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
- value16 = usb_read16(adapt, REG_CR);
+ value16 = rtw_read16(adapt, REG_CR);
value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN
| PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN);
/* for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
- usb_write16(adapt, REG_CR, value16);
- adapt->HalData->bMacPwrCtrlOn = true;
+ rtw_write16(adapt, REG_CR, value16);
+ haldata->bMacPwrCtrlOn = true;
return _SUCCESS;
}
@@ -113,33 +119,35 @@ static void _InitInterrupt(struct adapter *Adapter)
{
u32 imr, imr_ex;
u8 usb_opt;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
/* HISR write one to clear */
- usb_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF);
+ rtw_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF);
/* HIMR - */
imr = IMR_PSTIMEOUT_88E | IMR_TBDER_88E | IMR_CPWM_88E | IMR_CPWM2_88E;
- usb_write32(Adapter, REG_HIMR_88E, imr);
- Adapter->HalData->IntrMask[0] = imr;
+ rtw_write32(Adapter, REG_HIMR_88E, imr);
+ haldata->IntrMask[0] = imr;
imr_ex = IMR_TXERR_88E | IMR_RXERR_88E | IMR_TXFOVW_88E | IMR_RXFOVW_88E;
- usb_write32(Adapter, REG_HIMRE_88E, imr_ex);
- Adapter->HalData->IntrMask[1] = imr_ex;
+ rtw_write32(Adapter, REG_HIMRE_88E, imr_ex);
+ haldata->IntrMask[1] = imr_ex;
/* REG_USB_SPECIAL_OPTION - BIT(4) */
/* 0; Use interrupt endpoint to upload interrupt pkt */
/* 1; Use bulk endpoint to upload interrupt pkt, */
- usb_opt = usb_read8(Adapter, REG_USB_SPECIAL_OPTION);
+ usb_opt = rtw_read8(Adapter, REG_USB_SPECIAL_OPTION);
if (!adapter_to_dvobj(Adapter)->ishighspeed)
usb_opt = usb_opt & (~INT_BULK_SEL);
else
usb_opt = usb_opt | (INT_BULK_SEL);
- usb_write8(Adapter, REG_USB_SPECIAL_OPTION, usb_opt);
+ rtw_write8(Adapter, REG_USB_SPECIAL_OPTION, usb_opt);
}
static void _InitQueueReservedPage(struct adapter *Adapter)
{
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
u32 numHQ = 0;
u32 numLQ = 0;
@@ -150,37 +158,37 @@ static void _InitQueueReservedPage(struct adapter *Adapter)
bool bWiFiConfig = pregistrypriv->wifi_spec;
if (bWiFiConfig) {
- if (Adapter->HalData->OutEpQueueSel & TX_SELE_HQ)
+ if (haldata->OutEpQueueSel & TX_SELE_HQ)
numHQ = 0x29;
- if (Adapter->HalData->OutEpQueueSel & TX_SELE_LQ)
+ if (haldata->OutEpQueueSel & TX_SELE_LQ)
numLQ = 0x1C;
- /* NOTE: This step shall be proceed before writing REG_RQPN. */
- if (Adapter->HalData->OutEpQueueSel & TX_SELE_NQ)
+ /* NOTE: This step shall be proceed before writting REG_RQPN. */
+ if (haldata->OutEpQueueSel & TX_SELE_NQ)
numNQ = 0x1C;
value8 = (u8)_NPQ(numNQ);
- usb_write8(Adapter, REG_RQPN_NPQ, value8);
+ rtw_write8(Adapter, REG_RQPN_NPQ, value8);
numPubQ = 0xA8 - numHQ - numLQ - numNQ;
/* TX DMA */
value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
- usb_write32(Adapter, REG_RQPN, value32);
+ rtw_write32(Adapter, REG_RQPN, value32);
} else {
- usb_write16(Adapter, REG_RQPN_NPQ, 0x0000);/* Just follow MP Team,??? Georgia 03/28 */
- usb_write16(Adapter, REG_RQPN_NPQ, 0x0d);
- usb_write32(Adapter, REG_RQPN, 0x808E000d);/* reserve 7 page for LPS */
+ rtw_write16(Adapter, REG_RQPN_NPQ, 0x0000);/* Just follow MP Team,??? Georgia 03/28 */
+ rtw_write16(Adapter, REG_RQPN_NPQ, 0x0d);
+ rtw_write32(Adapter, REG_RQPN, 0x808E000d);/* reserve 7 page for LPS */
}
}
static void _InitTxBufferBoundary(struct adapter *Adapter, u8 txpktbuf_bndy)
{
- usb_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
- usb_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
- usb_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
- usb_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy);
- usb_write8(Adapter, REG_TDECTRL + 1, txpktbuf_bndy);
+ rtw_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+ rtw_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+ rtw_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
+ rtw_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy);
+ rtw_write8(Adapter, REG_TDECTRL + 1, txpktbuf_bndy);
}
static void _InitPageBoundary(struct adapter *Adapter)
@@ -189,27 +197,28 @@ static void _InitPageBoundary(struct adapter *Adapter)
/* */
u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E - 1;
- usb_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
+ rtw_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
}
static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ,
u16 bkQ, u16 viQ, u16 voQ, u16 mgtQ,
u16 hiQ)
{
- u16 value16 = (usb_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
+ u16 value16 = (rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) |
_TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) |
_TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ);
- usb_write16(Adapter, REG_TRXDMA_CTRL, value16);
+ rtw_write16(Adapter, REG_TRXDMA_CTRL, value16);
}
static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter)
{
- u16 value = 0;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
- switch (Adapter->HalData->OutEpQueueSel) {
+ u16 value = 0;
+ switch (haldata->OutEpQueueSel) {
case TX_SELE_HQ:
value = QUEUE_HIGH;
break;
@@ -228,12 +237,13 @@ static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter)
static void _InitNormalChipTwoOutEpPriority(struct adapter *Adapter)
{
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
u16 valueHi = 0;
u16 valueLow = 0;
- switch (Adapter->HalData->OutEpQueueSel) {
+ switch (haldata->OutEpQueueSel) {
case (TX_SELE_HQ | TX_SELE_LQ):
valueHi = QUEUE_HIGH;
valueLow = QUEUE_LOW;
@@ -293,7 +303,9 @@ static void _InitNormalChipThreeOutEpPriority(struct adapter *Adapter)
static void _InitQueuePriority(struct adapter *Adapter)
{
- switch (Adapter->HalData->OutEpNumber) {
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
+
+ switch (haldata->OutEpNumber) {
case 1:
_InitNormalChipOneOutEpPriority(Adapter);
break;
@@ -312,11 +324,11 @@ static void _InitNetworkType(struct adapter *Adapter)
{
u32 value32;
- value32 = usb_read32(Adapter, REG_CR);
+ value32 = rtw_read32(Adapter, REG_CR);
/* TODO: use the other function to set network type */
value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP);
- usb_write32(Adapter, REG_CR, value32);
+ rtw_write32(Adapter, REG_CR, value32);
}
static void _InitTransferPageSize(struct adapter *Adapter)
@@ -324,19 +336,18 @@ static void _InitTransferPageSize(struct adapter *Adapter)
/* Tx page size is always 128. */
u8 value8;
-
value8 = _PSRX(PBP_128) | _PSTX(PBP_128);
- usb_write8(Adapter, REG_PBP, value8);
+ rtw_write8(Adapter, REG_PBP, value8);
}
static void _InitDriverInfoSize(struct adapter *Adapter, u8 drvInfoSize)
{
- usb_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize);
+ rtw_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize);
}
static void _InitWMACSetting(struct adapter *Adapter)
{
- struct hal_data_8188e *haldata = Adapter->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
haldata->ReceiveConfig = RCR_AAP | RCR_APM | RCR_AM | RCR_AB |
RCR_CBSSID_DATA | RCR_CBSSID_BCN |
@@ -344,11 +355,11 @@ static void _InitWMACSetting(struct adapter *Adapter)
RCR_APP_MIC | RCR_APP_PHYSTS;
/* some REG_RCR will be modified later by phy_ConfigMACWithHeaderFile() */
- usb_write32(Adapter, REG_RCR, haldata->ReceiveConfig);
+ rtw_write32(Adapter, REG_RCR, haldata->ReceiveConfig);
/* Accept all multicast address */
- usb_write32(Adapter, REG_MAR, 0xFFFFFFFF);
- usb_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF);
+ rtw_write32(Adapter, REG_MAR, 0xFFFFFFFF);
+ rtw_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF);
}
static void _InitAdaptiveCtrl(struct adapter *Adapter)
@@ -357,64 +368,80 @@ static void _InitAdaptiveCtrl(struct adapter *Adapter)
u32 value32;
/* Response Rate Set */
- value32 = usb_read32(Adapter, REG_RRSR);
+ value32 = rtw_read32(Adapter, REG_RRSR);
value32 &= ~RATE_BITMAP_ALL;
value32 |= RATE_RRSR_CCK_ONLY_1M;
- usb_write32(Adapter, REG_RRSR, value32);
+ rtw_write32(Adapter, REG_RRSR, value32);
/* CF-END Threshold */
/* SIFS (used in NAV) */
value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
- usb_write16(Adapter, REG_SPEC_SIFS, value16);
+ rtw_write16(Adapter, REG_SPEC_SIFS, value16);
/* Retry Limit */
value16 = _LRL(0x30) | _SRL(0x30);
- usb_write16(Adapter, REG_RL, value16);
+ rtw_write16(Adapter, REG_RL, value16);
}
static void _InitEDCA(struct adapter *Adapter)
{
/* Set Spec SIFS (used in NAV) */
- usb_write16(Adapter, REG_SPEC_SIFS, 0x100a);
- usb_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a);
+ rtw_write16(Adapter, REG_SPEC_SIFS, 0x100a);
+ rtw_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a);
/* Set SIFS for CCK */
- usb_write16(Adapter, REG_SIFS_CTX, 0x100a);
+ rtw_write16(Adapter, REG_SIFS_CTX, 0x100a);
/* Set SIFS for OFDM */
- usb_write16(Adapter, REG_SIFS_TRX, 0x100a);
+ rtw_write16(Adapter, REG_SIFS_TRX, 0x100a);
/* TXOP */
- usb_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B);
- usb_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F);
- usb_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324);
- usb_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226);
+ rtw_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B);
+ rtw_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F);
+ rtw_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324);
+ rtw_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226);
+}
+
+static void _InitBeaconMaxError(struct adapter *Adapter, bool InfraMode)
+{
+}
+
+static void _InitHWLed(struct adapter *Adapter)
+{
+ struct led_priv *pledpriv = &Adapter->ledpriv;
+
+ if (pledpriv->LedStrategy != HW_LED)
+ return;
+
+/* HW led control */
+/* to do .... */
+/* must consider cases of antenna diversity/ commbo card/solo card/mini card */
}
static void _InitRDGSetting(struct adapter *Adapter)
{
- usb_write8(Adapter, REG_RD_CTRL, 0xFF);
- usb_write16(Adapter, REG_RD_NAV_NXT, 0x200);
- usb_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05);
+ rtw_write8(Adapter, REG_RD_CTRL, 0xFF);
+ rtw_write16(Adapter, REG_RD_NAV_NXT, 0x200);
+ rtw_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05);
}
static void _InitRxSetting(struct adapter *Adapter)
{
- usb_write32(Adapter, REG_MACID, 0x87654321);
- usb_write32(Adapter, 0x0700, 0x87654321);
+ rtw_write32(Adapter, REG_MACID, 0x87654321);
+ rtw_write32(Adapter, 0x0700, 0x87654321);
}
static void _InitRetryFunction(struct adapter *Adapter)
{
u8 value8;
- value8 = usb_read8(Adapter, REG_FWHW_TXQ_CTRL);
+ value8 = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL);
value8 |= EN_AMPDU_RTY_NEW;
- usb_write8(Adapter, REG_FWHW_TXQ_CTRL, value8);
+ rtw_write8(Adapter, REG_FWHW_TXQ_CTRL, value8);
/* Set ACK timeout */
- usb_write8(Adapter, REG_ACKTO, 0x40);
+ rtw_write8(Adapter, REG_ACKTO, 0x40);
}
/*-----------------------------------------------------------------------------
@@ -431,22 +458,21 @@ static void _InitRetryFunction(struct adapter *Adapter)
* When Who Remark
* 12/10/2010 MHC Separate to smaller function.
*
- *---------------------------------------------------------------------------
- */
+ *---------------------------------------------------------------------------*/
static void usb_AggSettingTxUpdate(struct adapter *Adapter)
{
- struct hal_data_8188e *haldata = Adapter->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
u32 value32;
if (Adapter->registrypriv.wifi_spec)
haldata->UsbTxAggMode = false;
if (haldata->UsbTxAggMode) {
- value32 = usb_read32(Adapter, REG_TDECTRL);
+ value32 = rtw_read32(Adapter, REG_TDECTRL);
value32 = value32 & ~(BLK_DESC_NUM_MASK << BLK_DESC_NUM_SHIFT);
value32 |= ((haldata->UsbTxAggDescNum & BLK_DESC_NUM_MASK) << BLK_DESC_NUM_SHIFT);
- usb_write32(Adapter, REG_TDECTRL, value32);
+ rtw_write32(Adapter, REG_TDECTRL, value32);
}
} /* usb_AggSettingTxUpdate */
@@ -464,16 +490,18 @@ static void usb_AggSettingTxUpdate(struct adapter *Adapter)
* When Who Remark
* 12/10/2010 MHC Separate to smaller function.
*
- *---------------------------------------------------------------------------
- */
-static void usb_AggSettingRxUpdate(struct adapter *Adapter)
+ *---------------------------------------------------------------------------*/
+static void
+usb_AggSettingRxUpdate(
+ struct adapter *Adapter
+ )
{
- struct hal_data_8188e *haldata = Adapter->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
u8 valueDMA;
u8 valueUSB;
- valueDMA = usb_read8(Adapter, REG_TRXDMA_CTRL);
- valueUSB = usb_read8(Adapter, REG_USB_SPECIAL_OPTION);
+ valueDMA = rtw_read8(Adapter, REG_TRXDMA_CTRL);
+ valueUSB = rtw_read8(Adapter, REG_USB_SPECIAL_OPTION);
switch (haldata->UsbRxAggMode) {
case USB_RX_AGG_DMA:
@@ -495,23 +523,23 @@ static void usb_AggSettingRxUpdate(struct adapter *Adapter)
break;
}
- usb_write8(Adapter, REG_TRXDMA_CTRL, valueDMA);
- usb_write8(Adapter, REG_USB_SPECIAL_OPTION, valueUSB);
+ rtw_write8(Adapter, REG_TRXDMA_CTRL, valueDMA);
+ rtw_write8(Adapter, REG_USB_SPECIAL_OPTION, valueUSB);
switch (haldata->UsbRxAggMode) {
case USB_RX_AGG_DMA:
- usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
- usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, haldata->UsbRxAggPageTimeout);
+ rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
+ rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, haldata->UsbRxAggPageTimeout);
break;
case USB_RX_AGG_USB:
- usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
- usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
+ rtw_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
+ rtw_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
break;
case USB_RX_AGG_MIX:
- usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
- usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */
- usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
- usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
+ rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
+ rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */
+ rtw_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
+ rtw_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
break;
case USB_RX_AGG_DISABLE:
default:
@@ -542,115 +570,157 @@ static void usb_AggSettingRxUpdate(struct adapter *Adapter)
static void InitUsbAggregationSetting(struct adapter *Adapter)
{
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
+
/* Tx aggregation setting */
usb_AggSettingTxUpdate(Adapter);
/* Rx aggregation setting */
usb_AggSettingRxUpdate(Adapter);
+
+ /* 201/12/10 MH Add for USB agg mode dynamic switch. */
+ haldata->UsbRxHighSpeedMode = false;
+}
+
+static void _InitOperationMode(struct adapter *Adapter)
+{
}
static void _InitBeaconParameters(struct adapter *Adapter)
{
- struct hal_data_8188e *haldata = Adapter->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
- usb_write16(Adapter, REG_BCN_CTRL, 0x1010);
+ rtw_write16(Adapter, REG_BCN_CTRL, 0x1010);
/* TODO: Remove these magic number */
- usb_write16(Adapter, REG_TBTT_PROHIBIT, 0x6404);/* ms */
- usb_write8(Adapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/* 5ms */
- usb_write8(Adapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); /* 2ms */
+ rtw_write16(Adapter, REG_TBTT_PROHIBIT, 0x6404);/* ms */
+ rtw_write8(Adapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/* 5ms */
+ rtw_write8(Adapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); /* 2ms */
/* Suggested by designer timchen. Change beacon AIFS to the largest number */
/* beacause test chip does not contension before sending beacon. by tynli. 2009.11.03 */
- usb_write16(Adapter, REG_BCNTCFG, 0x660F);
+ rtw_write16(Adapter, REG_BCNTCFG, 0x660F);
- haldata->RegBcnCtrlVal = usb_read8(Adapter, REG_BCN_CTRL);
- haldata->RegTxPause = usb_read8(Adapter, REG_TXPAUSE);
- haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL + 2);
- haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT + 2);
- haldata->RegCR_1 = usb_read8(Adapter, REG_CR + 1);
+ haldata->RegBcnCtrlVal = rtw_read8(Adapter, REG_BCN_CTRL);
+ haldata->RegTxPause = rtw_read8(Adapter, REG_TXPAUSE);
+ haldata->RegFwHwTxQCtrl = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL + 2);
+ haldata->RegReg542 = rtw_read8(Adapter, REG_TBTT_PROHIBIT + 2);
+ haldata->RegCR_1 = rtw_read8(Adapter, REG_CR + 1);
}
-static void _BeaconFunctionEnable(struct adapter *Adapter)
+static void _BeaconFunctionEnable(struct adapter *Adapter,
+ bool Enable, bool Linked)
{
- usb_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1)));
+ rtw_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1)));
- usb_write8(Adapter, REG_RD_CTRL + 1, 0x6F);
+ rtw_write8(Adapter, REG_RD_CTRL + 1, 0x6F);
}
/* Set CCK and OFDM Block "ON" */
static void _BBTurnOnBlock(struct adapter *Adapter)
{
- phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1);
- phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1);
+ PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1);
+ PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1);
}
+enum {
+ Antenna_Lfet = 1,
+ Antenna_Right = 2,
+};
+
static void _InitAntenna_Selection(struct adapter *Adapter)
{
- struct hal_data_8188e *haldata = Adapter->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
if (haldata->AntDivCfg == 0)
return;
+ DBG_88E("==> %s ....\n", __func__);
- usb_write32(Adapter, REG_LEDCFG0, usb_read32(Adapter, REG_LEDCFG0) | BIT(23));
- phy_set_bb_reg(Adapter, rFPGA0_XAB_RFParameter, BIT(13), 0x01);
+ rtw_write32(Adapter, REG_LEDCFG0, rtw_read32(Adapter, REG_LEDCFG0) | BIT(23));
+ PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, BIT(13), 0x01);
- if (phy_query_bb_reg(Adapter, rFPGA0_XA_RFInterfaceOE, 0x300) == Antenna_A)
+ if (PHY_QueryBBReg(Adapter, rFPGA0_XA_RFInterfaceOE, 0x300) == Antenna_A)
haldata->CurAntenna = Antenna_A;
else
haldata->CurAntenna = Antenna_B;
+ DBG_88E("%s,Cur_ant:(%x)%s\n", __func__, haldata->CurAntenna, (haldata->CurAntenna == Antenna_A) ? "Antenna_A" : "Antenna_B");
}
+/*-----------------------------------------------------------------------------
+ * Function: HwSuspendModeEnable92Cu()
+ *
+ * Overview: HW suspend mode switch.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 08/23/2010 MHC HW suspend mode switch test..
+ *---------------------------------------------------------------------------*/
enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt)
{
u8 val8;
enum rt_rf_power_state rfpowerstate = rf_off;
if (adapt->pwrctrlpriv.bHWPowerdown) {
- val8 = usb_read8(adapt, REG_HSISR);
+ val8 = rtw_read8(adapt, REG_HSISR);
+ DBG_88E("pwrdown, 0x5c(BIT(7))=%02x\n", val8);
rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on;
} else { /* rf on/off */
- usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG) & ~(BIT(3)));
- val8 = usb_read8(adapt, REG_GPIO_IO_SEL);
+ rtw_write8(adapt, REG_MAC_PINMUX_CFG, rtw_read8(adapt, REG_MAC_PINMUX_CFG) & ~(BIT(3)));
+ val8 = rtw_read8(adapt, REG_GPIO_IO_SEL);
+ DBG_88E("GPIO_IN=%02x\n", val8);
rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off;
}
return rfpowerstate;
} /* HalDetectPwrDownMode */
-u32 rtl8188eu_hal_init(struct adapter *Adapter)
+static u32 rtl8188eu_hal_init(struct adapter *Adapter)
{
u8 value8 = 0;
u16 value16;
u8 txpktbuf_bndy;
u32 status = _SUCCESS;
- struct hal_data_8188e *haldata = Adapter->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
+ u32 init_start_time = jiffies;
+
+ #define HAL_INIT_PROFILE_TAG(stage) do {} while (0)
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BEGIN);
if (Adapter->pwrctrlpriv.bkeepfwalive) {
+ _ps_open_RF(Adapter);
+
if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) {
- rtl88eu_phy_iq_calibrate(Adapter, true);
+ PHY_IQCalibrate_8188E(Adapter, true);
} else {
- rtl88eu_phy_iq_calibrate(Adapter, false);
+ PHY_IQCalibrate_8188E(Adapter, false);
haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true;
}
ODM_TXPowerTrackingCheck(&haldata->odmpriv);
- rtl88eu_phy_lc_calibrate(Adapter);
+ PHY_LCCalibrate_8188E(Adapter);
goto exit;
}
- status = rtw_hal_power_on(Adapter);
- if (status == _FAIL) {
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON);
+ status = rtl8188eu_InitPowerOn(Adapter);
+ if (status == _FAIL)
goto exit;
- }
/* Save target channel */
haldata->CurrentChannel = 6;/* default set to 6 */
- if (pwrctrlpriv->reg_rfoff)
+ if (pwrctrlpriv->reg_rfoff) {
pwrctrlpriv->rf_pwrstate = rf_off;
+ }
/* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */
/* HW GPIO pin. Before PHY_RFConfig8192C. */
@@ -663,6 +733,7 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter)
txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY_88E;
}
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC01);
_InitQueueReservedPage(Adapter);
_InitQueuePriority(Adapter);
_InitPageBoundary(Adapter);
@@ -670,84 +741,127 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter)
_InitTxBufferBoundary(Adapter, 0);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_DOWNLOAD_FW);
if (Adapter->registrypriv.mp_mode == 1) {
_InitRxSetting(Adapter);
Adapter->bFWReady = false;
+ haldata->fw_ractrl = false;
} else {
- status = rtl88eu_download_fw(Adapter);
+ status = rtl8188e_FirmwareDownload(Adapter);
- if (status) {
+ if (status != _SUCCESS) {
+ DBG_88E("%s: Download Firmware failed!!\n", __func__);
Adapter->bFWReady = false;
+ haldata->fw_ractrl = false;
return status;
+ } else {
+ Adapter->bFWReady = true;
+ haldata->fw_ractrl = false;
}
- Adapter->bFWReady = true;
}
rtl8188e_InitializeFirmwareVars(Adapter);
- rtl88eu_phy_mac_config(Adapter);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MAC);
+#if (HAL_MAC_ENABLE == 1)
+ status = PHY_MACConfig8188E(Adapter);
+ if (status == _FAIL) {
+ DBG_88E(" ### Failed to init MAC ......\n ");
+ goto exit;
+ }
+#endif
- rtl88eu_phy_bb_config(Adapter);
+ /* */
+ /* d. Initialize BB related configurations. */
+ /* */
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BB);
+#if (HAL_BB_ENABLE == 1)
+ status = PHY_BBConfig8188E(Adapter);
+ if (status == _FAIL) {
+ DBG_88E(" ### Failed to init BB ......\n ");
+ goto exit;
+ }
+#endif
- rtl88eu_phy_rf_config(Adapter);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_RF);
+#if (HAL_RF_ENABLE == 1)
+ status = PHY_RFConfig8188E(Adapter);
+ if (status == _FAIL) {
+ DBG_88E(" ### Failed to init RF ......\n ");
+ goto exit;
+ }
+#endif
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_EFUSE_PATCH);
status = rtl8188e_iol_efuse_patch(Adapter);
- if (status == _FAIL)
+ if (status == _FAIL) {
+ DBG_88E("%s rtl8188e_iol_efuse_patch failed\n", __func__);
goto exit;
+ }
_InitTxBufferBoundary(Adapter, txpktbuf_bndy);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_LLTT);
status = InitLLTTable(Adapter, txpktbuf_bndy);
- if (status == _FAIL) {
+ if (status == _FAIL)
goto exit;
- }
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC02);
/* Get Rx PHY status in order to report RSSI and others. */
_InitDriverInfoSize(Adapter, DRVINFO_SZ);
_InitInterrupt(Adapter);
- rtw_hal_set_hwreg(Adapter, HW_VAR_MAC_ADDR,
- Adapter->eeprompriv.mac_addr);
+ hal_init_macaddr(Adapter);/* set mac_address */
_InitNetworkType(Adapter);/* set msr */
_InitWMACSetting(Adapter);
_InitAdaptiveCtrl(Adapter);
_InitEDCA(Adapter);
_InitRetryFunction(Adapter);
InitUsbAggregationSetting(Adapter);
+ _InitOperationMode(Adapter);/* todo */
_InitBeaconParameters(Adapter);
+ _InitBeaconMaxError(Adapter, true);
+
+ /* */
/* Init CR MACTXEN, MACRXEN after setting RxFF boundary REG_TRXFF_BNDY to patch */
/* Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */
+ /* */
/* Enable MACTXEN/MACRXEN block */
- value16 = usb_read16(Adapter, REG_CR);
+ value16 = rtw_read16(Adapter, REG_CR);
value16 |= (MACTXEN | MACRXEN);
- usb_write8(Adapter, REG_CR, value16);
+ rtw_write8(Adapter, REG_CR, value16);
if (haldata->bRDGEnable)
_InitRDGSetting(Adapter);
/* Enable TX Report */
/* Enable Tx Report Timer */
- value8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
- usb_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0)));
+ value8 = rtw_read8(Adapter, REG_TX_RPT_CTRL);
+ rtw_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0)));
/* Set MAX RPT MACID */
- usb_write8(Adapter, REG_TX_RPT_CTRL + 1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */
+ rtw_write8(Adapter, REG_TX_RPT_CTRL + 1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */
/* Tx RPT Timer. Unit: 32us */
- usb_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0);
+ rtw_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0);
+
+ rtw_write8(Adapter, REG_EARLY_MODE_CONTROL, 0);
- usb_write8(Adapter, REG_EARLY_MODE_CONTROL, 0);
+ rtw_write16(Adapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
+ rtw_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
- usb_write16(Adapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
- usb_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
+ _InitHWLed(Adapter);
/* Keep RfRegChnlVal for later use. */
- haldata->RfRegChnlVal[0] = rtw_hal_read_rfreg(Adapter, (enum rf_radio_path)0, RF_CHNLBW, bRFRegOffsetMask);
- haldata->RfRegChnlVal[1] = rtw_hal_read_rfreg(Adapter, (enum rf_radio_path)1, RF_CHNLBW, bRFRegOffsetMask);
+ haldata->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, (enum rf_radio_path)0, RF_CHNLBW, bRFRegOffsetMask);
+ haldata->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, (enum rf_radio_path)1, RF_CHNLBW, bRFRegOffsetMask);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_TURN_ON_BLOCK);
_BBTurnOnBlock(Adapter);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_SECURITY);
invalidate_cam_all(Adapter);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC11);
/* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */
- phy_set_tx_power_level(Adapter, haldata->CurrentChannel);
+ PHY_SetTxPowerLevel8188E(Adapter, haldata->CurrentChannel);
/* Move by Neo for USB SS to below setp */
/* _RfPowerSave(Adapter); */
@@ -758,139 +872,168 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter)
/* Disable BAR, suggested by Scott */
/* 2010.04.09 add by hpfan */
/* */
- usb_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff);
+ rtw_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff);
/* HW SEQ CTRL */
/* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */
- usb_write8(Adapter, REG_HWSEQ_CTRL, 0xFF);
+ rtw_write8(Adapter, REG_HWSEQ_CTRL, 0xFF);
if (pregistrypriv->wifi_spec)
- usb_write16(Adapter, REG_FAST_EDCA_CTRL, 0);
+ rtw_write16(Adapter, REG_FAST_EDCA_CTRL, 0);
/* Nav limit , suggest by scott */
- usb_write8(Adapter, 0x652, 0x0);
+ rtw_write8(Adapter, 0x652, 0x0);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_HAL_DM);
rtl8188e_InitHalDm(Adapter);
- /* 2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */
- /* and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */
- /* call initstruct adapter. May cause some problem?? */
- /* Fix the bug that Hw/Sw radio off before S3/S4, the RF off action will not be executed */
- /* in MgntActSet_RF_State() after wake up, because the value of haldata->eRFPowerState */
- /* is the same as eRfOff, we should change it to eRfOn after we config RF parameters. */
- /* Added by tynli. 2010.03.30. */
- pwrctrlpriv->rf_pwrstate = rf_on;
-
- /* enable Tx report. */
- usb_write8(Adapter, REG_FWHW_TXQ_CTRL + 1, 0x0F);
-
- /* Suggested by SD1 pisa. Added by tynli. 2011.10.21. */
- usb_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x01);/* Pretx_en, for WEP/TKIP SEC */
+ if (Adapter->registrypriv.mp_mode == 1) {
+ Adapter->mppriv.channel = haldata->CurrentChannel;
+ MPT_InitializeAdapter(Adapter, Adapter->mppriv.channel);
+ } else {
+ /* 2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */
+ /* and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */
+ /* call initstruct adapter. May cause some problem?? */
+ /* Fix the bug that Hw/Sw radio off before S3/S4, the RF off action will not be executed */
+ /* in MgntActSet_RF_State() after wake up, because the value of haldata->eRFPowerState */
+ /* is the same as eRfOff, we should change it to eRfOn after we config RF parameters. */
+ /* Added by tynli. 2010.03.30. */
+ pwrctrlpriv->rf_pwrstate = rf_on;
+
+ /* enable Tx report. */
+ rtw_write8(Adapter, REG_FWHW_TXQ_CTRL + 1, 0x0F);
+
+ /* Suggested by SD1 pisa. Added by tynli. 2011.10.21. */
+ rtw_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x01);/* Pretx_en, for WEP/TKIP SEC */
+
+ /* tynli_test_tx_report. */
+ rtw_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0);
+
+ /* enable tx DMA to drop the redundate data of packet */
+ rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN));
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK);
+ /* 2010/08/26 MH Merge from 8192CE. */
+ if (pwrctrlpriv->rf_pwrstate == rf_on) {
+ if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) {
+ PHY_IQCalibrate_8188E(Adapter, true);
+ } else {
+ PHY_IQCalibrate_8188E(Adapter, false);
+ haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true;
+ }
- /* tynli_test_tx_report. */
- usb_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0);
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_PW_TRACK);
- /* enable tx DMA to drop the redundate data of packet */
- usb_write16(Adapter, REG_TXDMA_OFFSET_CHK, (usb_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN));
+ ODM_TXPowerTrackingCheck(&haldata->odmpriv);
- /* 2010/08/26 MH Merge from 8192CE. */
- if (pwrctrlpriv->rf_pwrstate == rf_on) {
- if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) {
- rtl88eu_phy_iq_calibrate(Adapter, true);
- } else {
- rtl88eu_phy_iq_calibrate(Adapter, false);
- haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true;
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK);
+ PHY_LCCalibrate_8188E(Adapter);
}
-
- ODM_TXPowerTrackingCheck(&haldata->odmpriv);
-
- rtl88eu_phy_lc_calibrate(Adapter);
}
+/* HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PABIAS); */
/* _InitPABias(Adapter); */
- usb_write8(Adapter, REG_USB_HRPWM, 0);
+ rtw_write8(Adapter, REG_USB_HRPWM, 0);
/* ack for xmit mgmt frames. */
- usb_write32(Adapter, REG_FWHW_TXQ_CTRL, usb_read32(Adapter, REG_FWHW_TXQ_CTRL) | BIT(12));
+ rtw_write32(Adapter, REG_FWHW_TXQ_CTRL, rtw_read32(Adapter, REG_FWHW_TXQ_CTRL) | BIT(12));
exit:
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END);
+
+ DBG_88E("%s in %dms\n", __func__, rtw_get_passing_time_ms(init_start_time));
return status;
}
+void _ps_open_RF(struct adapter *adapt)
+{
+ /* here call with bRegSSPwrLvl 1, bRegSSPwrLvl 2 needs to be verified */
+ /* phy_SsPwrSwitch92CU(adapt, rf_on, 1); */
+}
+
+static void _ps_close_RF(struct adapter *adapt)
+{
+ /* here call with bRegSSPwrLvl 1, bRegSSPwrLvl 2 needs to be verified */
+ /* phy_SsPwrSwitch92CU(adapt, rf_off, 1); */
+}
+
static void CardDisableRTL8188EU(struct adapter *Adapter)
{
u8 val8;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
/* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */
- val8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
- usb_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT(1)));
+ val8 = rtw_read8(Adapter, REG_TX_RPT_CTRL);
+ rtw_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT(1)));
/* stop rx */
- usb_write8(Adapter, REG_CR, 0x0);
+ rtw_write8(Adapter, REG_CR, 0x0);
/* Run LPS WL RFOFF flow */
- rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK,
- Rtl8188E_NIC_LPS_ENTER_FLOW);
+ HalPwrSeqCmdParsing(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, Rtl8188E_NIC_LPS_ENTER_FLOW);
/* 2. 0x1F[7:0] = 0 turn off RF */
- val8 = usb_read8(Adapter, REG_MCUFWDL);
+ val8 = rtw_read8(Adapter, REG_MCUFWDL);
if ((val8 & RAM_DL_SEL) && Adapter->bFWReady) { /* 8051 RAM code */
/* Reset MCU 0x2[10]=0. */
- val8 = usb_read8(Adapter, REG_SYS_FUNC_EN + 1);
+ val8 = rtw_read8(Adapter, REG_SYS_FUNC_EN + 1);
val8 &= ~BIT(2); /* 0x2[10], FEN_CPUEN */
- usb_write8(Adapter, REG_SYS_FUNC_EN + 1, val8);
+ rtw_write8(Adapter, REG_SYS_FUNC_EN + 1, val8);
}
/* reset MCU ready status */
- usb_write8(Adapter, REG_MCUFWDL, 0);
+ rtw_write8(Adapter, REG_MCUFWDL, 0);
/* YJ,add,111212 */
/* Disable 32k */
- val8 = usb_read8(Adapter, REG_32K_CTRL);
- usb_write8(Adapter, REG_32K_CTRL, val8 & (~BIT(0)));
+ val8 = rtw_read8(Adapter, REG_32K_CTRL);
+ rtw_write8(Adapter, REG_32K_CTRL, val8 & (~BIT(0)));
/* Card disable power action flow */
- rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK,
- Rtl8188E_NIC_DISABLE_FLOW);
+ HalPwrSeqCmdParsing(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, Rtl8188E_NIC_DISABLE_FLOW);
/* Reset MCU IO Wrapper */
- val8 = usb_read8(Adapter, REG_RSV_CTRL + 1);
- usb_write8(Adapter, REG_RSV_CTRL + 1, (val8 & (~BIT(3))));
- val8 = usb_read8(Adapter, REG_RSV_CTRL + 1);
- usb_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3));
+ val8 = rtw_read8(Adapter, REG_RSV_CTRL + 1);
+ rtw_write8(Adapter, REG_RSV_CTRL + 1, (val8 & (~BIT(3))));
+ val8 = rtw_read8(Adapter, REG_RSV_CTRL + 1);
+ rtw_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3));
/* YJ,test add, 111207. For Power Consumption. */
- val8 = usb_read8(Adapter, GPIO_IN);
- usb_write8(Adapter, GPIO_OUT, val8);
- usb_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */
-
- val8 = usb_read8(Adapter, REG_GPIO_IO_SEL);
- usb_write8(Adapter, REG_GPIO_IO_SEL, (val8 << 4));
- val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1);
- usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */
- usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */
- Adapter->HalData->bMacPwrCtrlOn = false;
+ val8 = rtw_read8(Adapter, GPIO_IN);
+ rtw_write8(Adapter, GPIO_OUT, val8);
+ rtw_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */
+
+ val8 = rtw_read8(Adapter, REG_GPIO_IO_SEL);
+ rtw_write8(Adapter, REG_GPIO_IO_SEL, (val8 << 4));
+ val8 = rtw_read8(Adapter, REG_GPIO_IO_SEL + 1);
+ rtw_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */
+ rtw_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */
+ haldata->bMacPwrCtrlOn = false;
Adapter->bFWReady = false;
}
-
static void rtl8192cu_hw_power_down(struct adapter *adapt)
{
/* 2010/-8/09 MH For power down module, we need to enable register block contrl reg at 0x1c. */
- /* Then enable power down control bit of register 0x04 BIT4 and BIT15 as 1. */
+ /* Then enable power down control bit of register 0x04 BIT(4) and BIT(15) as 1. */
/* Enable register area 0x0-0xc. */
- usb_write8(adapt, REG_RSV_CTRL, 0x0);
- usb_write16(adapt, REG_APS_FSMCO, 0x8812);
+ rtw_write8(adapt, REG_RSV_CTRL, 0x0);
+ rtw_write16(adapt, REG_APS_FSMCO, 0x8812);
}
-u32 rtl8188eu_hal_deinit(struct adapter *Adapter)
+static u32 rtl8188eu_hal_deinit(struct adapter *Adapter)
{
- usb_write32(Adapter, REG_HIMR_88E, IMR_DISABLED_88E);
- usb_write32(Adapter, REG_HIMRE_88E, IMR_DISABLED_88E);
+ DBG_88E("==> %s\n", __func__);
+
+ rtw_write32(Adapter, REG_HIMR_88E, IMR_DISABLED_88E);
+ rtw_write32(Adapter, REG_HIMRE_88E, IMR_DISABLED_88E);
+
+ DBG_88E("bkeepfwalive(%x)\n", Adapter->pwrctrlpriv.bkeepfwalive);
if (Adapter->pwrctrlpriv.bkeepfwalive) {
+ _ps_close_RF(Adapter);
if ((Adapter->pwrctrlpriv.bHWPwrPindetect) && (Adapter->pwrctrlpriv.bHWPowerdown))
rtl8192cu_hw_power_down(Adapter);
} else {
@@ -902,40 +1045,64 @@ u32 rtl8188eu_hal_deinit(struct adapter *Adapter)
}
}
return _SUCCESS;
-}
+ }
-u32 rtw_hal_inirp_init(struct adapter *Adapter)
+static unsigned int rtl8188eu_inirp_init(struct adapter *Adapter)
{
u8 i;
struct recv_buf *precvbuf;
uint status;
+ struct intf_hdl *pintfhdl = &Adapter->iopriv.intf;
struct recv_priv *precvpriv = &Adapter->recvpriv;
+ u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+
+ _read_port = pintfhdl->io_ops._read_port;
status = _SUCCESS;
+ precvpriv->ff_hwaddr = RECV_BULK_IN_ADDR;
+
/* issue Rx irp to receive data */
- precvbuf = precvpriv->precv_buf;
+ precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF; i++) {
- if (!usb_read_port(Adapter, RECV_BULK_IN_ADDR, precvbuf)) {
+ if (!_read_port(pintfhdl, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf)) {
status = _FAIL;
goto exit;
}
precvbuf++;
+ precvpriv->free_recv_buf_queue_cnt--;
}
exit:
return status;
}
+static unsigned int rtl8188eu_inirp_deinit(struct adapter *Adapter)
+{
+ rtw_read_port_cancel(Adapter);
+
+ return _SUCCESS;
+}
+
/* */
/* */
/* EEPROM/EFUSE Content Parsing */
/* */
/* */
+static void _ReadLEDSetting(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail)
+{
+ struct led_priv *pledpriv = &Adapter->ledpriv;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
+
+ pledpriv->bRegUseLed = true;
+ pledpriv->LedStrategy = SW_LED_MODE1;
+ haldata->bLedOpenDrain = true;/* Support Open-drain arrangement for controlling the LED. */
+}
+
static void Hal_EfuseParsePIDVID_8188EU(struct adapter *adapt, u8 *hwinfo, bool AutoLoadFail)
{
- struct hal_data_8188e *haldata = adapt->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
if (!AutoLoadFail) {
/* VID, PID */
@@ -953,6 +1120,9 @@ static void Hal_EfuseParsePIDVID_8188EU(struct adapter *adapt, u8 *hwinfo, bool
haldata->EEPROMCustomerID = EEPROM_Default_CustomerID;
haldata->EEPROMSubCustomerID = EEPROM_Default_SubCustomerID;
}
+
+ DBG_88E("VID = 0x%04X, PID = 0x%04X\n", haldata->EEPROMVID, haldata->EEPROMPID);
+ DBG_88E("Customer ID: 0x%02X, SubCustomer ID: 0x%02X\n", haldata->EEPROMCustomerID, haldata->EEPROMSubCustomerID);
}
static void Hal_EfuseParseMACAddr_8188EU(struct adapter *adapt, u8 *hwinfo, bool AutoLoadFail)
@@ -970,7 +1140,14 @@ static void Hal_EfuseParseMACAddr_8188EU(struct adapter *adapt, u8 *hwinfo, bool
}
}
-static void readAdapterInfo_8188EU(struct adapter *adapt)
+static void Hal_CustomizeByCustomerID_8188EU(struct adapter *adapt)
+{
+}
+
+static void
+readAdapterInfo_8188EU(
+ struct adapter *adapt
+ )
{
struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(adapt);
@@ -988,25 +1165,62 @@ static void readAdapterInfo_8188EU(struct adapter *adapt)
Hal_ReadAntennaDiversity88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
Hal_EfuseParseBoardType88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
Hal_ReadThermalMeter_88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+
+ /* */
+ /* The following part initialize some vars by PG info. */
+ /* */
+ Hal_InitChannelPlan(adapt);
+ Hal_CustomizeByCustomerID_8188EU(adapt);
+
+ _ReadLEDSetting(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
}
-static void _ReadPROMContent(struct adapter *Adapter)
+static void _ReadPROMContent(
+ struct adapter *Adapter
+ )
{
struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(Adapter);
u8 eeValue;
/* check system boot selection */
- eeValue = usb_read8(Adapter, REG_9346CR);
+ eeValue = rtw_read8(Adapter, REG_9346CR);
eeprom->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false;
eeprom->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true;
+ DBG_88E("Boot from %s, Autoload %s !\n", (eeprom->EepromOrEfuse ? "EEPROM" : "EFUSE"),
+ (eeprom->bautoload_fail_flag ? "Fail" : "OK"));
+
Hal_InitPGData88E(Adapter);
readAdapterInfo_8188EU(Adapter);
}
-void rtw_hal_read_chip_info(struct adapter *Adapter)
+static void _ReadRFType(struct adapter *Adapter)
{
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
+
+ haldata->rf_chip = RF_6052;
+}
+
+static int _ReadAdapterInfo8188EU(struct adapter *Adapter)
+{
+ u32 start = jiffies;
+
+ MSG_88E("====> %s\n", __func__);
+
+ _ReadRFType(Adapter);/* rf_chip -> _InitRFType() */
_ReadPROMContent(Adapter);
+
+ MSG_88E("<==== %s in %d ms\n", __func__, rtw_get_passing_time_ms(start));
+
+ return _SUCCESS;
+}
+
+static void ReadAdapterInfo8188EU(struct adapter *Adapter)
+{
+ /* Read EEPROM size before call any EEPROM function */
+ Adapter->EepromAddressSize = GetEEPROMSize8188E(Adapter);
+
+ _ReadAdapterInfo8188EU(Adapter);
}
#define GPIO_DEBUG_PORT_NUM 0
@@ -1016,30 +1230,30 @@ static void rtl8192cu_trigger_gpio_0(struct adapter *adapt)
static void ResumeTxBeacon(struct adapter *adapt)
{
- struct hal_data_8188e *haldata = adapt->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
/* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
/* which should be read from register to a global variable. */
- usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6));
+ rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6));
haldata->RegFwHwTxQCtrl |= BIT(6);
- usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff);
+ rtw_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff);
haldata->RegReg542 |= BIT(0);
- usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
+ rtw_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
}
static void StopTxBeacon(struct adapter *adapt)
{
- struct hal_data_8188e *haldata = adapt->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
/* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
/* which should be read from register to a global variable. */
- usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6)));
+ rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6)));
haldata->RegFwHwTxQCtrl &= (~BIT(6));
- usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64);
+ rtw_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64);
haldata->RegReg542 &= ~(BIT(0));
- usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
+ rtw_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
/* todo: CheckFwRsvdPageContent(Adapter); 2010.06.23. Added by tynli. */
}
@@ -1050,52 +1264,54 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val)
u8 mode = *((u8 *)val);
/* disable Port0 TSF update */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+ rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) | BIT(4));
/* set net_type */
- val8 = usb_read8(Adapter, MSR) & 0x0c;
+ val8 = rtw_read8(Adapter, MSR) & 0x0c;
val8 |= mode;
- usb_write8(Adapter, MSR, val8);
+ rtw_write8(Adapter, MSR, val8);
+
+ DBG_88E("%s()-%d mode = %d\n", __func__, __LINE__, mode);
if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
StopTxBeacon(Adapter);
- usb_write8(Adapter, REG_BCN_CTRL, 0x19);/* disable atim wnd */
+ rtw_write8(Adapter, REG_BCN_CTRL, 0x19);/* disable atim wnd */
} else if (mode == _HW_STATE_ADHOC_) {
ResumeTxBeacon(Adapter);
- usb_write8(Adapter, REG_BCN_CTRL, 0x1a);
+ rtw_write8(Adapter, REG_BCN_CTRL, 0x1a);
} else if (mode == _HW_STATE_AP_) {
ResumeTxBeacon(Adapter);
- usb_write8(Adapter, REG_BCN_CTRL, 0x12);
+ rtw_write8(Adapter, REG_BCN_CTRL, 0x12);
/* Set RCR */
- usb_write32(Adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */
+ rtw_write32(Adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */
/* enable to rx data frame */
- usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+ rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
/* enable to rx ps-poll */
- usb_write16(Adapter, REG_RXFLTMAP1, 0x0400);
+ rtw_write16(Adapter, REG_RXFLTMAP1, 0x0400);
/* Beacon Control related register for first time */
- usb_write8(Adapter, REG_BCNDMATIM, 0x02); /* 2ms */
+ rtw_write8(Adapter, REG_BCNDMATIM, 0x02); /* 2ms */
- usb_write8(Adapter, REG_ATIMWND, 0x0a); /* 10ms */
- usb_write16(Adapter, REG_BCNTCFG, 0x00);
- usb_write16(Adapter, REG_TBTT_PROHIBIT, 0xff04);
- usb_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */
+ rtw_write8(Adapter, REG_ATIMWND, 0x0a); /* 10ms */
+ rtw_write16(Adapter, REG_BCNTCFG, 0x00);
+ rtw_write16(Adapter, REG_TBTT_PROHIBIT, 0xff04);
+ rtw_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */
/* reset TSF */
- usb_write8(Adapter, REG_DUAL_TSF_RST, BIT(0));
+ rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(0));
- /* BIT3 - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */
- usb_write8(Adapter, REG_MBID_NUM, usb_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4));
+ /* BIT(3) - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */
+ rtw_write8(Adapter, REG_MBID_NUM, rtw_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4));
/* enable BCN0 Function for if1 */
/* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
- usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1)));
+ rtw_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1)));
/* dis BCN1 ATIM WND if if2 is station */
- usb_write8(Adapter, REG_BCN_CTRL_1, usb_read8(Adapter, REG_BCN_CTRL_1) | BIT(0));
+ rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1) | BIT(0));
}
}
@@ -1107,7 +1323,7 @@ static void hw_var_set_macaddr(struct adapter *Adapter, u8 variable, u8 *val)
reg_macid = REG_MACID;
for (idx = 0; idx < 6; idx++)
- usb_write8(Adapter, (reg_macid + idx), val[idx]);
+ rtw_write8(Adapter, (reg_macid + idx), val[idx]);
}
static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val)
@@ -1118,7 +1334,7 @@ static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val)
reg_bssid = REG_BSSID;
for (idx = 0; idx < 6; idx++)
- usb_write8(Adapter, (reg_bssid + idx), val[idx]);
+ rtw_write8(Adapter, (reg_bssid + idx), val[idx]);
}
static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val)
@@ -1128,14 +1344,14 @@ static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val)
bcn_ctrl_reg = REG_BCN_CTRL;
if (*((u8 *)val))
- usb_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
+ rtw_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
else
- usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg) & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT)));
+ rtw_write8(Adapter, bcn_ctrl_reg, rtw_read8(Adapter, bcn_ctrl_reg) & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT)));
}
-void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
+static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
{
- struct hal_data_8188e *haldata = Adapter->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &haldata->dmpriv;
struct odm_dm_struct *podmpriv = &haldata->odmpriv;
@@ -1144,18 +1360,18 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
{
u8 val8;
- val8 = usb_read8(Adapter, MSR) & 0x0c;
+ val8 = rtw_read8(Adapter, MSR) & 0x0c;
val8 |= *((u8 *)val);
- usb_write8(Adapter, MSR, val8);
+ rtw_write8(Adapter, MSR, val8);
}
break;
case HW_VAR_MEDIA_STATUS1:
{
u8 val8;
- val8 = usb_read8(Adapter, MSR) & 0x03;
+ val8 = rtw_read8(Adapter, MSR) & 0x03;
val8 |= *((u8 *)val) << 2;
- usb_write8(Adapter, MSR, val8);
+ rtw_write8(Adapter, MSR, val8);
}
break;
case HW_VAR_SET_OPMODE:
@@ -1176,7 +1392,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
/* Select RRSR (in Legacy-OFDM and CCK) */
/* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, and 1M from the Basic rate. */
/* We do not use other rates. */
- hal_set_brate_cfg(val, &BrateCfg);
+ HalSetBrateCfg(Adapter, val, &BrateCfg);
+ DBG_88E("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", BrateCfg);
/* 2011.03.30 add by Luke Lee */
/* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
@@ -1188,21 +1405,21 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
BrateCfg |= 0x01; /* default enable 1M ACK rate */
/* Set RRSR rate table. */
- usb_write8(Adapter, REG_RRSR, BrateCfg & 0xff);
- usb_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff);
- usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2) & 0xf0);
+ rtw_write8(Adapter, REG_RRSR, BrateCfg & 0xff);
+ rtw_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff);
+ rtw_write8(Adapter, REG_RRSR + 2, rtw_read8(Adapter, REG_RRSR + 2) & 0xf0);
/* Set RTS initial rate */
while (BrateCfg > 0x1) {
- BrateCfg >>= 1;
+ BrateCfg = (BrateCfg >> 1);
RateIndex++;
}
/* Ziv - Check */
- usb_write8(Adapter, REG_INIRTS_RATE_SEL, RateIndex);
+ rtw_write8(Adapter, REG_INIRTS_RATE_SEL, RateIndex);
}
break;
case HW_VAR_TXPAUSE:
- usb_write8(Adapter, REG_TXPAUSE, *((u8 *)val));
+ rtw_write8(Adapter, REG_TXPAUSE, *((u8 *)val));
break;
case HW_VAR_BCN_FUNC:
hw_var_set_bcn_func(Adapter, variable, val);
@@ -1213,19 +1430,20 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */
+ tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue,
+ pmlmeinfo->bcn_interval * 1024) - 1024; /* us */
if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
StopTxBeacon(Adapter);
/* disable related TSF function */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(3)));
+ rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) & (~BIT(3)));
- usb_write32(Adapter, REG_TSFTR, tsf);
- usb_write32(Adapter, REG_TSFTR + 4, tsf >> 32);
+ rtw_write32(Adapter, REG_TSFTR, tsf);
+ rtw_write32(Adapter, REG_TSFTR + 4, tsf >> 32);
/* enable related TSF function */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3));
+ rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) | BIT(3));
if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
ResumeTxBeacon(Adapter);
@@ -1233,40 +1451,39 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
break;
case HW_VAR_CHECK_BSSID:
if (*((u8 *)val)) {
- usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
} else {
u32 val32;
- val32 = usb_read32(Adapter, REG_RCR);
+ val32 = rtw_read32(Adapter, REG_RCR);
val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
- usb_write32(Adapter, REG_RCR, val32);
+ rtw_write32(Adapter, REG_RCR, val32);
}
break;
case HW_VAR_MLME_DISCONNECT:
/* Set RCR to not to receive data frame when NO LINK state */
/* reject all data frames */
- usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
+ rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
/* reset TSF */
- usb_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+ rtw_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
/* disable update TSF */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+ rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) | BIT(4));
break;
case HW_VAR_MLME_SITESURVEY:
if (*((u8 *)val)) { /* under sitesurvey */
/* config RCR to receive different BSSID & not to receive data frame */
- u32 v = usb_read32(Adapter, REG_RCR);
-
+ u32 v = rtw_read32(Adapter, REG_RCR);
v &= ~(RCR_CBSSID_BCN);
- usb_write32(Adapter, REG_RCR, v);
+ rtw_write32(Adapter, REG_RCR, v);
/* reject all data frame */
- usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
+ rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
/* disable update TSF */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+ rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) | BIT(4));
} else { /* sitesurvey done */
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -1274,17 +1491,26 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
if ((is_client_associated_to_ap(Adapter)) ||
((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {
/* enable to rx data frame */
- usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+ rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
/* enable update TSF */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
+ rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
} else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
- usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+ rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
/* enable update TSF */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
+ rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
+ }
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+ rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN);
+ } else {
+ if (Adapter->in_cta_test) {
+ u32 v = rtw_read32(Adapter, REG_RCR);
+ v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */
+ rtw_write32(Adapter, REG_RCR, v);
+ } else {
+ rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN);
+ }
}
-
- usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN);
}
break;
case HW_VAR_MLME_JOIN:
@@ -1295,9 +1521,15 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
if (type == 0) { /* prepare to join */
/* enable to rx data frame.Accept all data frame */
- usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
-
- usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+
+ if (Adapter->in_cta_test) {
+ u32 v = rtw_read32(Adapter, REG_RCR);
+ v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */
+ rtw_write32(Adapter, REG_RCR, v);
+ } else {
+ rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ }
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
RetryLimit = (haldata->CustomerID == RT_CID_CCX) ? 7 : 48;
@@ -1305,20 +1537,20 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
RetryLimit = 0x7;
} else if (type == 1) {
/* joinbss_event call back when join res < 0 */
- usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
+ rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
} else if (type == 2) {
/* sta add event call back */
/* enable update TSF */
- usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
+ rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))
RetryLimit = 0x7;
}
- usb_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT);
+ rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT);
}
break;
case HW_VAR_BEACON_INTERVAL:
- usb_write16(Adapter, REG_BCN_INTERVAL, *((u16 *)val));
+ rtw_write16(Adapter, REG_BCN_INTERVAL, *((u16 *)val));
break;
case HW_VAR_SLOT_TIME:
{
@@ -1326,7 +1558,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- usb_write8(Adapter, REG_SLOT, val[0]);
+ rtw_write8(Adapter, REG_SLOT, val[0]);
if (pmlmeinfo->WMM_enable == 0) {
if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
@@ -1337,20 +1569,20 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
/* <Roger_EXP> Temporary removed, 2008.06.20. */
- usb_write8(Adapter, REG_EDCA_VO_PARAM, u1bAIFS);
- usb_write8(Adapter, REG_EDCA_VI_PARAM, u1bAIFS);
- usb_write8(Adapter, REG_EDCA_BE_PARAM, u1bAIFS);
- usb_write8(Adapter, REG_EDCA_BK_PARAM, u1bAIFS);
+ rtw_write8(Adapter, REG_EDCA_VO_PARAM, u1bAIFS);
+ rtw_write8(Adapter, REG_EDCA_VI_PARAM, u1bAIFS);
+ rtw_write8(Adapter, REG_EDCA_BE_PARAM, u1bAIFS);
+ rtw_write8(Adapter, REG_EDCA_BK_PARAM, u1bAIFS);
}
}
break;
case HW_VAR_RESP_SIFS:
/* RESP_SIFS for CCK */
- usb_write8(Adapter, REG_R2T_SIFS, val[0]); /* SIFS_T2T_CCK (0x08) */
- usb_write8(Adapter, REG_R2T_SIFS + 1, val[1]); /* SIFS_R2T_CCK(0x08) */
+ rtw_write8(Adapter, REG_R2T_SIFS, val[0]); /* SIFS_T2T_CCK (0x08) */
+ rtw_write8(Adapter, REG_R2T_SIFS + 1, val[1]); /* SIFS_R2T_CCK(0x08) */
/* RESP_SIFS for OFDM */
- usb_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */
- usb_write8(Adapter, REG_T2T_SIFS + 1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
+ rtw_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */
+ rtw_write8(Adapter, REG_T2T_SIFS + 1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
break;
case HW_VAR_ACK_PREAMBLE:
{
@@ -1361,11 +1593,14 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
if (bShortPreamble)
regTmp |= 0x80;
- usb_write8(Adapter, REG_RRSR + 2, regTmp);
+ rtw_write8(Adapter, REG_RRSR + 2, regTmp);
}
break;
case HW_VAR_SEC_CFG:
- usb_write8(Adapter, REG_SECCFG, *((u8 *)val));
+ rtw_write8(Adapter, REG_SECCFG, *((u8 *)val));
+ break;
+ case HW_VAR_DM_FLAG:
+ podmpriv->SupportAbility = *((u8 *)val);
break;
case HW_VAR_DM_FUNC_OP:
if (val[0])
@@ -1400,45 +1635,43 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
ulContent = 0;
/* polling bit, and No Write enable, and address */
ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
- ulCommand = ulCommand | CAM_POLLINIG |
- CAM_WRITE;
+ ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
/* write content 0 is equall to mark invalid */
- usb_write32(Adapter, WCAMI, ulContent); /* delay_ms(40); */
- usb_write32(Adapter, RWCAM, ulCommand); /* delay_ms(40); */
+ rtw_write32(Adapter, WCAMI, ulContent); /* delay_ms(40); */
+ rtw_write32(Adapter, RWCAM, ulCommand); /* delay_ms(40); */
}
}
break;
case HW_VAR_CAM_INVALID_ALL:
- usb_write32(Adapter, RWCAM, BIT(31) | BIT(30));
+ rtw_write32(Adapter, RWCAM, BIT(31) | BIT(30));
break;
case HW_VAR_CAM_WRITE:
{
u32 cmd;
u32 *cam_val = (u32 *)val;
-
- usb_write32(Adapter, WCAMI, cam_val[0]);
+ rtw_write32(Adapter, WCAMI, cam_val[0]);
cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
- usb_write32(Adapter, RWCAM, cmd);
+ rtw_write32(Adapter, RWCAM, cmd);
}
break;
case HW_VAR_AC_PARAM_VO:
- usb_write32(Adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]);
+ rtw_write32(Adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]);
break;
case HW_VAR_AC_PARAM_VI:
- usb_write32(Adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]);
+ rtw_write32(Adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]);
break;
case HW_VAR_AC_PARAM_BE:
haldata->AcParam_BE = ((u32 *)(val))[0];
- usb_write32(Adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]);
+ rtw_write32(Adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]);
break;
case HW_VAR_AC_PARAM_BK:
- usb_write32(Adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]);
+ rtw_write32(Adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]);
break;
case HW_VAR_ACM_CTRL:
{
u8 acm_ctrl = *((u8 *)val);
- u8 AcmCtrl = usb_read8(Adapter, REG_ACMHWCTRL);
+ u8 AcmCtrl = rtw_read8(Adapter, REG_ACMHWCTRL);
if (acm_ctrl > 1)
AcmCtrl = AcmCtrl | 0x1;
@@ -1458,7 +1691,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
else
AcmCtrl &= (~AcmHw_BeqEn);
- usb_write8(Adapter, REG_ACMHWCTRL, AcmCtrl);
+ DBG_88E("[HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
+ rtw_write8(Adapter, REG_ACMHWCTRL, AcmCtrl);
}
break;
case HW_VAR_AMPDU_MIN_SPACE:
@@ -1485,7 +1719,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
}
if (MinSpacingToSet < SecMinSpace)
MinSpacingToSet = SecMinSpace;
- usb_write8(Adapter, REG_AMPDU_MIN_SPACE, (usb_read8(Adapter, REG_AMPDU_MIN_SPACE) & 0xf8) | MinSpacingToSet);
+ rtw_write8(Adapter, REG_AMPDU_MIN_SPACE, (rtw_read8(Adapter, REG_AMPDU_MIN_SPACE) & 0xf8) | MinSpacingToSet);
}
}
break;
@@ -1499,7 +1733,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
pRegToSet = RegToSet_Normal; /* 0xb972a841; */
FactorToSet = *((u8 *)val);
if (FactorToSet <= 3) {
- FactorToSet = 1 << (FactorToSet + 2);
+ FactorToSet = (1 << (FactorToSet + 2));
if (FactorToSet > 0xf)
FactorToSet = 0xf;
@@ -1510,7 +1744,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
if ((pRegToSet[index] & 0x0f) > FactorToSet)
pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet);
- usb_write8(Adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]);
+ rtw_write8(Adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]);
}
}
}
@@ -1518,10 +1752,9 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
case HW_VAR_RXDMA_AGG_PG_TH:
{
u8 threshold = *((u8 *)val);
-
if (threshold == 0)
threshold = haldata->UsbRxAggPageCount;
- usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, threshold);
+ rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, threshold);
}
break;
case HW_VAR_SET_RPWM:
@@ -1532,7 +1765,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
/* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
/* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
- if (psmode != PS_MODE_ACTIVE)
+ if ((psmode != PS_MODE_ACTIVE) && (!IS_92C_SERIAL(haldata->VersionID)))
ODM_RF_Saving(podmpriv, true);
rtl8188e_set_FwPwrMode_cmd(Adapter, psmode);
}
@@ -1540,10 +1773,17 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
case HW_VAR_H2C_FW_JOINBSSRPT:
{
u8 mstatus = (*(u8 *)val);
-
rtl8188e_set_FwJoinBssReport_cmd(Adapter, mstatus);
}
break;
+#ifdef CONFIG_88EU_P2P
+ case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
+ {
+ u8 p2p_ps_state = (*(u8 *)val);
+ rtl8188e_set_p2p_ps_offload_cmd(Adapter, p2p_ps_state);
+ }
+ break;
+#endif
case HW_VAR_INITIAL_GAIN:
{
struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
@@ -1563,7 +1803,6 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
case HW_VAR_RPT_TIMER_SETTING:
{
u16 min_rpt_time = (*(u16 *)val);
-
ODM_RA_Set_TxRPT_Time(podmpriv, min_rpt_time);
}
break;
@@ -1574,7 +1813,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
/* switch antenna to Optimum_antenna */
if (haldata->CurAntenna != Optimum_antenna) {
Ant = (Optimum_antenna == 2) ? MAIN_ANT : AUX_ANT;
- rtl88eu_dm_update_rx_idle_ant(&haldata->odmpriv, Ant);
+ ODM_UpdateRxIdleAnt_88E(&haldata->odmpriv, Ant);
haldata->CurAntenna = Optimum_antenna;
}
@@ -1589,22 +1828,24 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
u8 trycnt = 100;
/* pause tx */
- usb_write8(Adapter, REG_TXPAUSE, 0xff);
+ rtw_write8(Adapter, REG_TXPAUSE, 0xff);
/* keep sn */
- Adapter->xmitpriv.nqos_ssn = usb_read16(Adapter, REG_NQOS_SEQ);
+ Adapter->xmitpriv.nqos_ssn = rtw_read16(Adapter, REG_NQOS_SEQ);
if (!pwrpriv->bkeepfwalive) {
/* RX DMA stop */
- usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM) | RW_RELEASE_EN));
+ rtw_write32(Adapter, REG_RXPKT_NUM, (rtw_read32(Adapter, REG_RXPKT_NUM) | RW_RELEASE_EN));
do {
- if (!(usb_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE))
+ if (!(rtw_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE))
break;
- } while (--trycnt);
+ } while (trycnt--);
+ if (trycnt == 0)
+ DBG_88E("Stop RX DMA failed......\n");
/* RQPN Load 0 */
- usb_write16(Adapter, REG_RQPN_NPQ, 0x0);
- usb_write32(Adapter, REG_RQPN, 0x80000000);
+ rtw_write16(Adapter, REG_RQPN_NPQ, 0x0);
+ rtw_write32(Adapter, REG_RQPN, 0x80000000);
mdelay(10);
}
}
@@ -1613,38 +1854,49 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
break;
case HW_VAR_APFM_ON_MAC:
haldata->bMacPwrCtrlOn = *val;
+ DBG_88E("%s: bMacPwrCtrlOn=%d\n", __func__, haldata->bMacPwrCtrlOn);
break;
case HW_VAR_TX_RPT_MAX_MACID:
{
u8 maxMacid = *val;
-
- usb_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1);
+ DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1);
+ rtw_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1);
}
break;
case HW_VAR_H2C_MEDIA_STATUS_RPT:
rtl8188e_set_FwMediaStatus_cmd(Adapter, (*(__le16 *)val));
break;
case HW_VAR_BCN_VALID:
- /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
- usb_write8(Adapter, REG_TDECTRL + 2, usb_read8(Adapter, REG_TDECTRL + 2) | BIT(0));
+ /* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
+ rtw_write8(Adapter, REG_TDECTRL + 2, rtw_read8(Adapter, REG_TDECTRL + 2) | BIT(0));
break;
default:
break;
}
+
}
-void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
+static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
{
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
+ struct odm_dm_struct *podmpriv = &haldata->odmpriv;
+
switch (variable) {
case HW_VAR_BASIC_RATE:
- *((u16 *)(val)) = Adapter->HalData->BasicRateSet;
+ *((u16 *)(val)) = haldata->BasicRateSet;
fallthrough;
case HW_VAR_TXPAUSE:
- val[0] = usb_read8(Adapter, REG_TXPAUSE);
+ val[0] = rtw_read8(Adapter, REG_TXPAUSE);
break;
case HW_VAR_BCN_VALID:
- /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
- val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL + 2)) ? true : false;
+ /* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2 */
+ val[0] = (BIT(0) & rtw_read8(Adapter, REG_TDECTRL + 2)) ? true : false;
+ break;
+ case HW_VAR_DM_FLAG:
+ val[0] = podmpriv->SupportAbility;
+ break;
+ case HW_VAR_RF_TYPE:
+ val[0] = haldata->rf_type;
break;
case HW_VAR_FWLPS_RF_ON:
{
@@ -1655,8 +1907,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
val[0] = true;
} else {
u32 valRCR;
-
- valRCR = usb_read32(Adapter, REG_RCR);
+ valRCR = rtw_read32(Adapter, REG_RCR);
valRCR &= 0x00070000;
if (valRCR)
val[0] = false;
@@ -1666,30 +1917,35 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
}
break;
case HW_VAR_CURRENT_ANTENNA:
- val[0] = Adapter->HalData->CurAntenna;
+ val[0] = haldata->CurAntenna;
break;
case HW_VAR_EFUSE_BYTES: /* To get EFUE total used bytes, added by Roger, 2008.12.22. */
- *((u16 *)(val)) = Adapter->HalData->EfuseUsedBytes;
+ *((u16 *)(val)) = haldata->EfuseUsedBytes;
break;
case HW_VAR_APFM_ON_MAC:
- *val = Adapter->HalData->bMacPwrCtrlOn;
+ *val = haldata->bMacPwrCtrlOn;
break;
case HW_VAR_CHK_HI_QUEUE_EMPTY:
- *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION) & 0x0000ff00) == 0) ? true : false;
+ *val = ((rtw_read32(Adapter, REG_HGQ_INFORMATION) & 0x0000ff00) == 0) ? true : false;
break;
default:
break;
}
+
}
/* */
/* Description: */
/* Query setting of specified variable. */
/* */
-u8 rtw_hal_get_def_var(struct adapter *Adapter, enum hal_def_variable eVariable,
- void *pValue)
+static u8
+GetHalDefVar8188EUsb(
+ struct adapter *Adapter,
+ enum hal_def_variable eVariable,
+ void *pValue
+ )
{
- struct hal_data_8188e *haldata = Adapter->HalData;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
u8 bResult = _SUCCESS;
switch (eVariable) {
@@ -1698,7 +1954,6 @@ u8 rtw_hal_get_def_var(struct adapter *Adapter, enum hal_def_variable eVariable,
struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
struct sta_priv *pstapriv = &Adapter->stapriv;
struct sta_info *psta;
-
psta = rtw_get_stainfo(pstapriv, pmlmepriv->cur_network.network.MacAddress);
if (psta)
*((int *)pValue) = psta->rssi_stat.UndecoratedSmoothedPWDB;
@@ -1725,21 +1980,18 @@ u8 rtw_hal_get_def_var(struct adapter *Adapter, enum hal_def_variable eVariable,
case HAL_DEF_RA_DECISION_RATE:
{
u8 MacID = *((u8 *)pValue);
-
*((u8 *)pValue) = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, MacID);
}
break;
case HAL_DEF_RA_SGI:
{
u8 MacID = *((u8 *)pValue);
-
*((u8 *)pValue) = ODM_RA_GetShortGI_8188E(&haldata->odmpriv, MacID);
}
break;
case HAL_DEF_PT_PWR_STATUS:
{
u8 MacID = *((u8 *)pValue);
-
*((u8 *)pValue) = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, MacID);
}
break;
@@ -1747,6 +1999,19 @@ u8 rtw_hal_get_def_var(struct adapter *Adapter, enum hal_def_variable eVariable,
*((u32 *)pValue) = MAX_AMPDU_FACTOR_64K;
break;
case HW_DEF_RA_INFO_DUMP:
+ {
+ u8 entry_id = *((u8 *)pValue);
+ if (check_fwstate(&Adapter->mlmepriv, _FW_LINKED)) {
+ DBG_88E("============ RA status check ===================\n");
+ DBG_88E("Mac_id:%d , RateID = %d, RAUseRate = 0x%08x, RateSGI = %d, DecisionRate = 0x%02x ,PTStage = %d\n",
+ entry_id,
+ haldata->odmpriv.RAInfo[entry_id].RateID,
+ haldata->odmpriv.RAInfo[entry_id].RAUseRate,
+ haldata->odmpriv.RAInfo[entry_id].RateSGI,
+ haldata->odmpriv.RAInfo[entry_id].DecisionRate,
+ haldata->odmpriv.RAInfo[entry_id].PTStage);
+ }
+ }
break;
case HAL_DEF_DBG_DUMP_RXPKT:
*((u8 *)pValue) = haldata->bDumpRxPkt;
@@ -1762,7 +2027,59 @@ u8 rtw_hal_get_def_var(struct adapter *Adapter, enum hal_def_variable eVariable,
return bResult;
}
-void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
+/* */
+/* Description: */
+/* Change default setting of specified variable. */
+/* */
+static u8 SetHalDefVar8188EUsb(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue)
+{
+ struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
+ u8 bResult = _SUCCESS;
+
+ switch (eVariable) {
+ case HAL_DEF_DBG_DM_FUNC:
+ {
+ u8 dm_func = *((u8 *)pValue);
+ struct odm_dm_struct *podmpriv = &haldata->odmpriv;
+
+ if (dm_func == 0) { /* disable all dynamic func */
+ podmpriv->SupportAbility = DYNAMIC_FUNC_DISABLE;
+ DBG_88E("==> Disable all dynamic function...\n");
+ } else if (dm_func == 1) {/* disable DIG */
+ podmpriv->SupportAbility &= (~DYNAMIC_BB_DIG);
+ DBG_88E("==> Disable DIG...\n");
+ } else if (dm_func == 2) {/* disable High power */
+ podmpriv->SupportAbility &= (~DYNAMIC_BB_DYNAMIC_TXPWR);
+ } else if (dm_func == 3) {/* disable tx power tracking */
+ podmpriv->SupportAbility &= (~DYNAMIC_RF_CALIBRATION);
+ DBG_88E("==> Disable tx power tracking...\n");
+ } else if (dm_func == 5) {/* disable antenna diversity */
+ podmpriv->SupportAbility &= (~DYNAMIC_BB_ANT_DIV);
+ } else if (dm_func == 6) {/* turn on all dynamic func */
+ if (!(podmpriv->SupportAbility & DYNAMIC_BB_DIG)) {
+ struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
+ pDigTable->CurIGValue = rtw_read8(Adapter, 0xc50);
+ }
+ podmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE;
+ DBG_88E("==> Turn on all dynamic function...\n");
+ }
+ }
+ break;
+ case HAL_DEF_DBG_DUMP_RXPKT:
+ haldata->bDumpRxPkt = *((u8 *)pValue);
+ break;
+ case HAL_DEF_DBG_DUMP_TXPKT:
+ haldata->bDumpTxPkt = *((u8 *)pValue);
+ break;
+ default:
+ bResult = _FAIL;
+ break;
+ }
+
+ return bResult;
+}
+
+static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
{
u8 init_rate = 0;
u8 networkType, raid;
@@ -1770,7 +2087,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
u8 shortGIrate = false;
int supportRateNum = 0;
struct sta_info *psta;
- struct odm_dm_struct *odmpriv = &adapt->HalData->odmpriv;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
@@ -1783,7 +2100,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
switch (mac_id) {
case 0:/* for infra mode */
supportRateNum = rtw_get_rateset_len(cur_network->SupportedRates);
- networkType = judge_network_type(adapt, cur_network->SupportedRates) & 0xf;
+ networkType = judge_network_type(adapt, cur_network->SupportedRates, supportRateNum) & 0xf;
raid = networktype_to_raid(networkType);
mask = update_supported_rate(cur_network->SupportedRates, supportRateNum);
mask |= (pmlmeinfo->HT_enable) ? update_MSC_rate(&pmlmeinfo->HT_caps) : 0;
@@ -1801,7 +2118,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
break;
default: /* for each sta in IBSS */
supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
- networkType = judge_network_type(adapt, pmlmeinfo->FW_sta_info[mac_id].SupportedRates) & 0xf;
+ networkType = judge_network_type(adapt, pmlmeinfo->FW_sta_info[mac_id].SupportedRates, supportRateNum) & 0xf;
raid = networktype_to_raid(networkType);
mask = update_supported_rate(cur_network->SupportedRates, supportRateNum);
@@ -1809,20 +2126,43 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
break;
}
- rate_bitmap = ODM_Get_Rate_Bitmap(odmpriv, mac_id, mask, rssi_level);
+ rate_bitmap = 0x0fffffff;
+ rate_bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, mac_id, mask, rssi_level);
+ DBG_88E("%s => mac_id:%d, networkType:0x%02x, mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n",
+ __func__, mac_id, networkType, mask, rssi_level, rate_bitmap);
mask &= rate_bitmap;
init_rate = get_highest_rate_idx(mask) & 0x3f;
- ODM_RA_UpdateRateInfo_8188E(odmpriv, mac_id, raid, mask, shortGIrate);
+ if (haldata->fw_ractrl) {
+ u8 arg;
+
+ arg = mac_id & 0x1f;/* MACID */
+ arg |= BIT(7);
+ if (shortGIrate)
+ arg |= BIT(5);
+ mask |= ((raid << 28) & 0xf0000000);
+ DBG_88E("update raid entry, mask=0x%x, arg=0x%x\n", mask, arg);
+ psta->ra_mask = mask;
+ mask |= ((raid << 28) & 0xf0000000);
+ /* to do ,for 8188E-SMIC */
+ rtl8188e_set_raid_cmd(adapt, mask);
+ } else {
+ ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv,
+ mac_id,
+ raid,
+ mask,
+ shortGIrate
+ );
+ }
/* set ra_id */
psta->raid = raid;
psta->init_rate = init_rate;
}
-void beacon_timing_control(struct adapter *adapt)
+static void SetBeaconRelatedRegisters8188EUsb(struct adapter *adapt)
{
u32 value32;
struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
@@ -1831,40 +2171,42 @@ void beacon_timing_control(struct adapter *adapt)
/* reset TSF, enable update TSF, correcting TSF On Beacon */
/* BCN interval */
- usb_write16(adapt, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
- usb_write8(adapt, REG_ATIMWND, 0x02);/* 2ms */
+ rtw_write16(adapt, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
+ rtw_write8(adapt, REG_ATIMWND, 0x02);/* 2ms */
_InitBeaconParameters(adapt);
- usb_write8(adapt, REG_SLOT, 0x09);
+ rtw_write8(adapt, REG_SLOT, 0x09);
- value32 = usb_read32(adapt, REG_TCR);
+ value32 = rtw_read32(adapt, REG_TCR);
value32 &= ~TSFRST;
- usb_write32(adapt, REG_TCR, value32);
+ rtw_write32(adapt, REG_TCR, value32);
value32 |= TSFRST;
- usb_write32(adapt, REG_TCR, value32);
+ rtw_write32(adapt, REG_TCR, value32);
/* NOTE: Fix test chip's bug (about contention windows's randomness) */
- usb_write8(adapt, REG_RXTSF_OFFSET_CCK, 0x50);
- usb_write8(adapt, REG_RXTSF_OFFSET_OFDM, 0x50);
+ rtw_write8(adapt, REG_RXTSF_OFFSET_CCK, 0x50);
+ rtw_write8(adapt, REG_RXTSF_OFFSET_OFDM, 0x50);
- _BeaconFunctionEnable(adapt);
+ _BeaconFunctionEnable(adapt, true, true);
ResumeTxBeacon(adapt);
- usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg) | BIT(1));
+ rtw_write8(adapt, bcn_ctrl_reg, rtw_read8(adapt, bcn_ctrl_reg) | BIT(1));
}
-void rtw_hal_def_value_init(struct adapter *adapt)
+static void rtl8188eu_init_default_value(struct adapter *adapt)
{
- struct hal_data_8188e *haldata = adapt->HalData;
+ struct hal_data_8188e *haldata;
struct pwrctrl_priv *pwrctrlpriv;
u8 i;
+ haldata = GET_HAL_DATA(adapt);
pwrctrlpriv = &adapt->pwrctrlpriv;
/* init default value */
+ haldata->fw_ractrl = false;
if (!pwrctrlpriv->bkeepfwalive)
haldata->LastHMEBoxNum = 0;
@@ -1877,3 +2219,53 @@ void rtw_hal_def_value_init(struct adapter *adapt)
for (i = 0; i < HP_THERMAL_NUM; i++)
haldata->odmpriv.RFCalibrateInfo.ThermalValue_HP[i] = 0;
}
+
+static u8 rtl8188eu_ps_func(struct adapter *Adapter, enum hal_intf_ps_func efunc_id, u8 *val)
+{
+ u8 bResult = true;
+ return bResult;
+}
+
+void rtl8188eu_set_hal_ops(struct adapter *adapt)
+{
+ struct hal_ops *halfunc = &adapt->HalFunc;
+
+ adapt->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL);
+ if (!adapt->HalData)
+ DBG_88E("cant not alloc memory for HAL DATA\n");
+ adapt->hal_data_sz = sizeof(struct hal_data_8188e);
+
+ halfunc->hal_power_on = rtl8188eu_InitPowerOn;
+ halfunc->hal_init = &rtl8188eu_hal_init;
+ halfunc->hal_deinit = &rtl8188eu_hal_deinit;
+
+ halfunc->inirp_init = &rtl8188eu_inirp_init;
+ halfunc->inirp_deinit = &rtl8188eu_inirp_deinit;
+
+ halfunc->init_xmit_priv = &rtl8188eu_init_xmit_priv;
+
+ halfunc->init_recv_priv = &rtl8188eu_init_recv_priv;
+ halfunc->free_recv_priv = &rtl8188eu_free_recv_priv;
+ halfunc->InitSwLeds = &rtl8188eu_InitSwLeds;
+ halfunc->DeInitSwLeds = &rtl8188eu_DeInitSwLeds;
+
+ halfunc->init_default_value = &rtl8188eu_init_default_value;
+ halfunc->intf_chip_configure = &rtl8188eu_interface_configure;
+ halfunc->read_adapter_info = &ReadAdapterInfo8188EU;
+
+ halfunc->SetHwRegHandler = &SetHwReg8188EU;
+ halfunc->GetHwRegHandler = &GetHwReg8188EU;
+ halfunc->GetHalDefVarHandler = &GetHalDefVar8188EUsb;
+ halfunc->SetHalDefVarHandler = &SetHalDefVar8188EUsb;
+
+ halfunc->UpdateRAMaskHandler = &UpdateHalRAMask8188EUsb;
+ halfunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188EUsb;
+
+ halfunc->hal_xmit = &rtl8188eu_hal_xmit;
+ halfunc->mgnt_xmit = &rtl8188eu_mgnt_xmit;
+
+ halfunc->interface_ps_func = &rtl8188eu_ps_func;
+
+ rtl8188e_set_hal_ops(halfunc);
+
+}
diff --git a/drivers/staging/r8188eu/hal/usb_ops_linux.c b/drivers/staging/r8188eu/hal/usb_ops_linux.c
new file mode 100644
index 000000000000..0cf69033c529
--- /dev/null
+++ b/drivers/staging/r8188eu/hal/usb_ops_linux.c
@@ -0,0 +1,562 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/osdep_intf.h"
+#include "../include/usb_ops.h"
+#include "../include/recv_osdep.h"
+#include "../include/rtl8188e_hal.h"
+
+static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata, u16 len, u8 requesttype)
+{
+ struct adapter *adapt = pintfhdl->padapter;
+ struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt);
+ struct usb_device *udev = dvobjpriv->pusbdev;
+ unsigned int pipe;
+ int status = 0;
+ u8 *pIo_buf;
+ int vendorreq_times = 0;
+
+ if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) {
+ status = -EPERM;
+ goto exit;
+ }
+
+ if (len > MAX_VENDOR_REQ_CMD_SIZE) {
+ DBG_88E("[%s] Buffer len error ,vendor request failed\n", __func__);
+ status = -EINVAL;
+ goto exit;
+ }
+
+ _enter_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
+
+ /* Acquire IO memory for vendorreq */
+ pIo_buf = dvobjpriv->usb_vendor_req_buf;
+
+ if (!pIo_buf) {
+ DBG_88E("[%s] pIo_buf == NULL\n", __func__);
+ status = -ENOMEM;
+ goto release_mutex;
+ }
+
+ if (requesttype == REALTEK_USB_VENQT_READ)
+ pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
+ else
+ pipe = usb_sndctrlpipe(udev, 0);/* write_out */
+
+ while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
+ if (requesttype == REALTEK_USB_VENQT_READ)
+ memset(pIo_buf, 0, len);
+ else
+ memcpy(pIo_buf, pdata, len);
+
+ status = usb_control_msg(udev, pipe, REALTEK_USB_VENQT_CMD_REQ,
+ requesttype, value, REALTEK_USB_VENQT_CMD_IDX,
+ pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
+
+ if (status == len) { /* Success this control transfer. */
+ rtw_reset_continual_urb_error(dvobjpriv);
+ if (requesttype == REALTEK_USB_VENQT_READ)
+ memcpy(pdata, pIo_buf, len);
+ } else { /* error cases */
+ DBG_88E("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n",
+ value, (requesttype == REALTEK_USB_VENQT_READ) ? "read" : "write",
+ len, status, *(u32 *)pdata, vendorreq_times);
+
+ if (status < 0) {
+ if (status == (-ESHUTDOWN) || status == -ENODEV) {
+ adapt->bSurpriseRemoved = true;
+ } else {
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+ haldata->srestpriv.wifi_error_status = USB_VEN_REQ_CMD_FAIL;
+ }
+ } else { /* status != len && status >= 0 */
+ if (status > 0) {
+ if (requesttype == REALTEK_USB_VENQT_READ) {
+ /* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
+ memcpy(pdata, pIo_buf, len);
+ }
+ }
+ }
+
+ if (rtw_inc_and_chk_continual_urb_error(dvobjpriv)) {
+ adapt->bSurpriseRemoved = true;
+ break;
+ }
+
+ }
+
+ /* firmware download is checksumed, don't retry */
+ if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len)
+ break;
+ }
+release_mutex:
+ _exit_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
+exit:
+ return status;
+}
+
+static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
+{
+ u16 wvalue = (u16)(addr & 0x0000ffff);
+ u8 data;
+
+ usbctrl_vendorreq(pintfhdl, wvalue, &data, 1, REALTEK_USB_VENQT_READ);
+
+ return data;
+}
+
+static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
+{
+ u16 wvalue = (u16)(addr & 0x0000ffff);
+ __le32 data;
+
+ usbctrl_vendorreq(pintfhdl, wvalue, &data, 2, REALTEK_USB_VENQT_READ);
+
+ return (u16)(le32_to_cpu(data) & 0xffff);
+}
+
+static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+{
+ u16 wvalue = (u16)(addr & 0x0000ffff);
+ __le32 data;
+
+ usbctrl_vendorreq(pintfhdl, wvalue, &data, 4, REALTEK_USB_VENQT_READ);
+
+ return le32_to_cpu(data);
+}
+
+static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
+{
+ u16 wvalue = (u16)(addr & 0x0000ffff);
+
+ return usbctrl_vendorreq(pintfhdl, wvalue, &val, 1, REALTEK_USB_VENQT_WRITE);
+}
+
+static int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
+{
+ u16 wvalue = (u16)(addr & 0x0000ffff);
+ __le32 data = cpu_to_le32(val & 0x0000ffff);
+
+ return usbctrl_vendorreq(pintfhdl, wvalue, &data, 2, REALTEK_USB_VENQT_WRITE);
+}
+
+static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
+{
+ u16 wvalue = (u16)(addr & 0x0000ffff);
+ __le32 data = cpu_to_le32(val);
+
+ return usbctrl_vendorreq(pintfhdl, wvalue, &data, 4, REALTEK_USB_VENQT_WRITE);
+}
+
+static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
+{
+ u16 wvalue = (u16)(addr & 0x0000ffff);
+ u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
+
+ if (length > VENDOR_CMD_MAX_DATA_LEN)
+ return -EINVAL;
+
+ memcpy(buf, pdata, length);
+
+ return usbctrl_vendorreq(pintfhdl, wvalue, buf, (length & 0xffff), REALTEK_USB_VENQT_WRITE);
+}
+
+static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf)
+{
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+
+ if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) {
+ DBG_88E("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len);
+ return;
+ }
+
+ /* HISR */
+ memcpy(&haldata->IntArray[0], &pbuf[USB_INTR_CONTENT_HISR_OFFSET], 4);
+ memcpy(&haldata->IntArray[1], &pbuf[USB_INTR_CONTENT_HISRE_OFFSET], 4);
+
+ /* C2H Event */
+ if (pbuf[0] != 0)
+ memcpy(&haldata->C2hArray[0], &pbuf[USB_INTR_CONTENT_C2H_OFFSET], 16);
+}
+
+static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
+{
+ u8 *pbuf;
+ u8 shift_sz = 0;
+ u16 pkt_cnt;
+ u32 pkt_offset, skb_len, alloc_sz;
+ s32 transfer_len;
+ struct recv_stat *prxstat;
+ struct phy_stat *pphy_status = NULL;
+ struct sk_buff *pkt_copy = NULL;
+ struct recv_frame *precvframe = NULL;
+ struct rx_pkt_attrib *pattrib = NULL;
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+ struct recv_priv *precvpriv = &adapt->recvpriv;
+ struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
+
+ transfer_len = (s32)pskb->len;
+ pbuf = pskb->data;
+
+ prxstat = (struct recv_stat *)pbuf;
+ pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
+
+ do {
+ prxstat = (struct recv_stat *)pbuf;
+
+ precvframe = rtw_alloc_recvframe(pfree_recv_queue);
+ if (!precvframe) {
+ DBG_88E("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __func__, __LINE__);
+ goto _exit_recvbuf2recvframe;
+ }
+
+ INIT_LIST_HEAD(&precvframe->list);
+ precvframe->precvbuf = NULL; /* can't access the precvbuf for new arch. */
+ precvframe->len = 0;
+
+ update_recvframe_attrib_88e(precvframe, prxstat);
+
+ pattrib = &precvframe->attrib;
+
+ if ((pattrib->crc_err) || (pattrib->icv_err)) {
+ DBG_88E("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
+
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ goto _exit_recvbuf2recvframe;
+ }
+
+ if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX))
+ pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
+
+ pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
+
+ if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
+ DBG_88E("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfoer_len\n", __func__, __LINE__);
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ goto _exit_recvbuf2recvframe;
+ }
+
+ /* Modified by Albert 20101213 */
+ /* For 8 bytes IP header alignment. */
+ if (pattrib->qos) /* Qos data, wireless lan header length is 26 */
+ shift_sz = 6;
+ else
+ shift_sz = 0;
+
+ skb_len = pattrib->pkt_len;
+
+ /* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
+ /* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
+ if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
+ if (skb_len <= 1650)
+ alloc_sz = 1664;
+ else
+ alloc_sz = skb_len + 14;
+ } else {
+ alloc_sz = skb_len;
+ /* 6 is for IP header 8 bytes alignment in QoS packet case. */
+ /* 8 is for skb->data 4 bytes alignment. */
+ alloc_sz += 14;
+ }
+
+ pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
+ if (pkt_copy) {
+ pkt_copy->dev = adapt->pnetdev;
+ precvframe->pkt = pkt_copy;
+ precvframe->rx_head = pkt_copy->data;
+ precvframe->rx_end = pkt_copy->data + alloc_sz;
+ skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
+ skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
+ memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
+ precvframe->rx_tail = pkt_copy->data;
+ precvframe->rx_data = pkt_copy->data;
+ } else {
+ if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
+ DBG_88E("recvbuf2recvframe: alloc_skb fail , drop frag frame\n");
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ goto _exit_recvbuf2recvframe;
+ }
+ precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
+ if (precvframe->pkt) {
+ precvframe->rx_tail = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE;
+ precvframe->rx_head = precvframe->rx_tail;
+ precvframe->rx_data = precvframe->rx_tail;
+ precvframe->rx_end = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE + alloc_sz;
+ } else {
+ DBG_88E("recvbuf2recvframe: skb_clone fail\n");
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ goto _exit_recvbuf2recvframe;
+ }
+ }
+
+ recvframe_put(precvframe, skb_len);
+
+ switch (haldata->UsbRxAggMode) {
+ case USB_RX_AGG_DMA:
+ case USB_RX_AGG_MIX:
+ pkt_offset = (u16)_RND128(pkt_offset);
+ break;
+ case USB_RX_AGG_USB:
+ pkt_offset = (u16)_RND4(pkt_offset);
+ break;
+ case USB_RX_AGG_DISABLE:
+ default:
+ break;
+ }
+ if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
+ if (pattrib->physt)
+ update_recvframe_phyinfo_88e(precvframe, (struct phy_stat *)pphy_status);
+ rtw_recv_entry(precvframe);
+ } else {
+ /* enqueue recvframe to txrtp queue */
+ if (pattrib->pkt_rpt_type == TX_REPORT1) {
+ /* CCX-TXRPT ack for xmit mgmt frames. */
+ handle_txrpt_ccx_88e(adapt, precvframe->rx_data);
+ } else if (pattrib->pkt_rpt_type == TX_REPORT2) {
+ ODM_RA_TxRPT2Handle_8188E(
+ &haldata->odmpriv,
+ precvframe->rx_data,
+ pattrib->pkt_len,
+ pattrib->MacIDValidEntry[0],
+ pattrib->MacIDValidEntry[1]
+ );
+ } else if (pattrib->pkt_rpt_type == HIS_REPORT) {
+ interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->rx_data);
+ }
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ }
+ pkt_cnt--;
+ transfer_len -= pkt_offset;
+ pbuf += pkt_offset;
+ precvframe = NULL;
+ pkt_copy = NULL;
+
+ if (transfer_len > 0 && pkt_cnt == 0)
+ pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
+
+ } while ((transfer_len > 0) && (pkt_cnt > 0));
+
+_exit_recvbuf2recvframe:
+
+ return _SUCCESS;
+}
+
+void rtl8188eu_recv_tasklet(unsigned long priv)
+{
+ struct sk_buff *pskb;
+ struct adapter *adapt = (struct adapter *)priv;
+ struct recv_priv *precvpriv = &adapt->recvpriv;
+
+ while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
+ if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) {
+ DBG_88E("recv_tasklet => bDriverStopped or bSurpriseRemoved\n");
+ dev_kfree_skb_any(pskb);
+ break;
+ }
+ recvbuf2recvframe(adapt, pskb);
+ skb_reset_tail_pointer(pskb);
+ pskb->len = 0;
+ skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
+ }
+}
+
+static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+ struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
+ struct adapter *adapt = (struct adapter *)precvbuf->adapter;
+ struct recv_priv *precvpriv = &adapt->recvpriv;
+
+ precvpriv->rx_pending_cnt--;
+
+ if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) {
+ precvbuf->reuse = true;
+ DBG_88E("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
+ __func__, adapt->bDriverStopped,
+ adapt->bSurpriseRemoved, adapt->bReadPortCancel);
+ return;
+ }
+
+ if (purb->status == 0) { /* SUCCESS */
+ if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
+ precvbuf->reuse = true;
+ rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+ DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__);
+ } else {
+ rtw_reset_continual_urb_error(adapter_to_dvobj(adapt));
+
+ precvbuf->transfer_len = purb->actual_length;
+ skb_put(precvbuf->pskb, purb->actual_length);
+ skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
+
+ if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
+ tasklet_schedule(&precvpriv->recv_tasklet);
+
+ precvbuf->pskb = NULL;
+ precvbuf->reuse = false;
+ rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+ }
+ } else {
+ DBG_88E("###=> usb_read_port_complete => urb status(%d)\n", purb->status);
+ skb_put(precvbuf->pskb, purb->actual_length);
+ precvbuf->pskb = NULL;
+
+ if (rtw_inc_and_chk_continual_urb_error(adapter_to_dvobj(adapt)))
+ adapt->bSurpriseRemoved = true;
+
+ switch (purb->status) {
+ case -EINVAL:
+ case -EPIPE:
+ case -ENODEV:
+ case -ESHUTDOWN:
+ case -ENOENT:
+ adapt->bDriverStopped = true;
+ break;
+ case -EPROTO:
+ case -EOVERFLOW:
+ {
+ struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
+ haldata->srestpriv.wifi_error_status = USB_READ_PORT_FAIL;
+ }
+ precvbuf->reuse = true;
+ rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
+ break;
+ case -EINPROGRESS:
+ DBG_88E("ERROR: URB IS IN PROGRESS!/n");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
+{
+ struct urb *purb = NULL;
+ struct recv_buf *precvbuf = (struct recv_buf *)rmem;
+ struct adapter *adapter = pintfhdl->padapter;
+ struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
+ struct recv_priv *precvpriv = &adapter->recvpriv;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+ int err;
+ unsigned int pipe;
+ size_t tmpaddr = 0;
+ size_t alignment = 0;
+ u32 ret = _SUCCESS;
+
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
+ adapter->pwrctrlpriv.pnp_bstop_trx)
+ return _FAIL;
+
+ if (!precvbuf)
+ return _FAIL;
+
+ if (!precvbuf->reuse || !precvbuf->pskb) {
+ precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
+ if (precvbuf->pskb)
+ precvbuf->reuse = true;
+ }
+
+ rtl8188eu_init_recvbuf(adapter, precvbuf);
+
+ /* re-assign for linux based on skb */
+ if (!precvbuf->reuse || !precvbuf->pskb) {
+ precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
+ if (!precvbuf->pskb) {
+ DBG_88E("#### usb_read_port() alloc_skb fail!#####\n");
+ return _FAIL;
+ }
+
+ tmpaddr = (size_t)precvbuf->pskb->data;
+ alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
+ skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
+
+ precvbuf->phead = precvbuf->pskb->head;
+ precvbuf->pdata = precvbuf->pskb->data;
+ precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
+ precvbuf->pend = skb_end_pointer(precvbuf->pskb);
+ precvbuf->pbuf = precvbuf->pskb->data;
+ } else { /* reuse skb */
+ precvbuf->phead = precvbuf->pskb->head;
+ precvbuf->pdata = precvbuf->pskb->data;
+ precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
+ precvbuf->pend = skb_end_pointer(precvbuf->pskb);
+ precvbuf->pbuf = precvbuf->pskb->data;
+
+ precvbuf->reuse = false;
+ }
+
+ precvpriv->rx_pending_cnt++;
+
+ purb = precvbuf->purb;
+
+ /* translate DMA FIFO addr to pipehandle */
+ pipe = ffaddr2pipehdl(pdvobj, addr);
+
+ usb_fill_bulk_urb(purb, pusbd, pipe,
+ precvbuf->pbuf,
+ MAX_RECVBUF_SZ,
+ usb_read_port_complete,
+ precvbuf);/* context is precvbuf */
+
+ err = usb_submit_urb(purb, GFP_ATOMIC);
+ if ((err) && (err != (-EPERM))) {
+ DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
+ err, purb->status);
+ ret = _FAIL;
+ }
+
+ return ret;
+}
+
+void rtl8188eu_xmit_tasklet(unsigned long priv)
+{
+ int ret = false;
+ struct adapter *adapt = (struct adapter *)priv;
+ struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
+
+ if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY))
+ return;
+
+ while (1) {
+ if ((adapt->bDriverStopped) ||
+ (adapt->bSurpriseRemoved) ||
+ (adapt->bWritePortCancel)) {
+ DBG_88E("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n");
+ break;
+ }
+
+ ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv, NULL);
+
+ if (!ret)
+ break;
+ }
+}
+
+void rtl8188eu_set_intf_ops(struct _io_ops *pops)
+{
+
+ memset((u8 *)pops, 0, sizeof(struct _io_ops));
+ pops->_read8 = &usb_read8;
+ pops->_read16 = &usb_read16;
+ pops->_read32 = &usb_read32;
+ pops->_read_mem = &usb_read_mem;
+ pops->_read_port = &usb_read_port;
+ pops->_write8 = &usb_write8;
+ pops->_write16 = &usb_write16;
+ pops->_write32 = &usb_write32;
+ pops->_writeN = &usb_writeN;
+ pops->_write_mem = &usb_write_mem;
+ pops->_write_port = &usb_write_port;
+ pops->_read_port_cancel = &usb_read_port_cancel;
+ pops->_write_port_cancel = &usb_write_port_cancel;
+
+}
+
+void rtl8188eu_set_hw_type(struct adapter *adapt)
+{
+ adapt->chip_type = RTL8188E;
+ adapt->HardwareType = HARDWARE_TYPE_RTL8188EU;
+ DBG_88E("CHIP TYPE: RTL8188E\n");
+}
diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h b/drivers/staging/r8188eu/include/Hal8188EPhyCfg.h
index a1055ceb7206..4370ec2fa981 100644
--- a/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h
+++ b/drivers/staging/r8188eu/include/Hal8188EPhyCfg.h
@@ -1,20 +1,26 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __INC_HAL8188EPHYCFG_H__
#define __INC_HAL8188EPHYCFG_H__
+/*--------------------------Define Parameters-------------------------------*/
#define LOOP_LIMIT 5
#define MAX_STALL_TIME 50 /* us */
#define AntennaDiversityValue 0x80
#define MAX_TXPWR_IDX_NMODE_92S 63
#define Reset_Cnt_Limit 3
+#define IQK_MAC_REG_NUM 4
+#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM 9
+#define HP_THERMAL_NUM 8
+
#define MAX_AGGR_NUM 0x07
+/*--------------------------Define Parameters-------------------------------*/
+
+/*------------------------------Define structure----------------------------*/
enum sw_chnl_cmd_id {
CmdID_End,
CmdID_SetTxPowerLevel,
@@ -44,30 +50,27 @@ enum hw90_block {
enum rf_radio_path {
RF_PATH_A = 0, /* Radio Path A */
RF_PATH_B = 1, /* Radio Path B */
+ RF_PATH_C = 2, /* Radio Path C */
+ RF_PATH_D = 3, /* Radio Path D */
};
#define MAX_PG_GROUP 13
-#define RF_PATH_MAX 2
-#define MAX_RF_PATH RF_PATH_MAX
+#define RF_PATH_MAX 3
#define MAX_TX_COUNT 4 /* path numbers */
#define CHANNEL_MAX_NUMBER 14 /* 14 is the max chnl number */
#define MAX_CHNL_GROUP_24G 6 /* ch1~2, ch3~5, ch6~8,
*ch9~11, ch12~13, CH 14
- * total three groups
- */
+ * total three groups */
#define CHANNEL_GROUP_MAX_88E 6
enum wireless_mode {
WIRELESS_MODE_UNKNOWN = 0x00,
- WIRELESS_MODE_A = BIT(2),
WIRELESS_MODE_B = BIT(0),
WIRELESS_MODE_G = BIT(1),
WIRELESS_MODE_AUTO = BIT(5),
WIRELESS_MODE_N_24G = BIT(3),
- WIRELESS_MODE_N_5G = BIT(4),
- WIRELESS_MODE_AC = BIT(6)
};
enum phy_rate_tx_offset_area {
@@ -80,6 +83,16 @@ enum phy_rate_tx_offset_area {
RA_OFFSET_HT_CCK,
};
+/* BB/RF related */
+enum RF_TYPE_8190P {
+ RF_TYPE_MIN, /* 0 */
+ RF_8225 = 1, /* 1 11b/g RF for verification only */
+ RF_8256 = 2, /* 2 11b/g/n */
+ RF_6052 = 4, /* 4 11b/g/n RF */
+ /* TODO: We should remove this psudo PHY RF after we get new RF. */
+ RF_PSEUDO_11N = 5, /* 5, It is a temporality RF. */
+};
+
struct bb_reg_def {
u32 rfintfs; /* set software control: */
/* 0x870~0x877[8 bytes] */
@@ -97,55 +110,103 @@ struct bb_reg_def {
/* 0x80c~0x80f [4 bytes] */
u32 rfHSSIPara1; /* wire parameter control1 : */
/* 0x820~0x823,0x828~0x82b,
- * 0x830~0x833, 0x838~0x83b [16 bytes]
- */
+ * 0x830~0x833, 0x838~0x83b [16 bytes] */
u32 rfHSSIPara2; /* wire parameter control2 : */
/* 0x824~0x827,0x82c~0x82f, 0x834~0x837,
- * 0x83c~0x83f [16 bytes]
- */
+ * 0x83c~0x83f [16 bytes] */
u32 rfSwitchControl; /* Tx Rx antenna control : */
/* 0x858~0x85f [16 bytes] */
u32 rfAGCControl1; /* AGC parameter control1 : */
/* 0xc50~0xc53,0xc58~0xc5b, 0xc60~0xc63,
- * 0xc68~0xc6b [16 bytes]
- */
+ * 0xc68~0xc6b [16 bytes] */
u32 rfAGCControl2; /* AGC parameter control2 : */
/* 0xc54~0xc57,0xc5c~0xc5f, 0xc64~0xc67,
- * 0xc6c~0xc6f [16 bytes]
- */
+ * 0xc6c~0xc6f [16 bytes] */
u32 rfRxIQImbalance; /* OFDM Rx IQ imbalance matrix : */
/* 0xc14~0xc17,0xc1c~0xc1f, 0xc24~0xc27,
- * 0xc2c~0xc2f [16 bytes]
- */
+ * 0xc2c~0xc2f [16 bytes] */
u32 rfRxAFE; /* Rx IQ DC ofset and Rx digital filter,
- * Rx DC notch filter :
- */
+ * Rx DC notch filter : */
/* 0xc10~0xc13,0xc18~0xc1b, 0xc20~0xc23,
- * 0xc28~0xc2b [16 bytes]
- */
+ * 0xc28~0xc2b [16 bytes] */
u32 rfTxIQImbalance; /* OFDM Tx IQ imbalance matrix */
/* 0xc80~0xc83,0xc88~0xc8b, 0xc90~0xc93,
- * 0xc98~0xc9b [16 bytes]
- */
+ * 0xc98~0xc9b [16 bytes] */
u32 rfTxAFE; /* Tx IQ DC Offset and Tx DFIR type */
/* 0xc84~0xc87,0xc8c~0xc8f, 0xc94~0xc97,
- * 0xc9c~0xc9f [16 bytes]
- */
+ * 0xc9c~0xc9f [16 bytes] */
u32 rfLSSIReadBack; /* LSSI RF readback data SI mode */
/* 0x8a0~0x8af [16 bytes] */
u32 rfLSSIReadBackPi; /* LSSI RF readback data PI mode 0x8b8-8bc for
- * Path A and B
- */
+ * Path A and B */
+};
+
+struct ant_sel_ofdm {
+ u32 r_tx_antenna:4;
+ u32 r_ant_l:4;
+ u32 r_ant_non_ht:4;
+ u32 r_ant_ht1:4;
+ u32 r_ant_ht2:4;
+ u32 r_ant_ht_s1:4;
+ u32 r_ant_non_ht_s1:4;
+ u32 OFDM_TXSC:2;
+ u32 reserved:2;
+};
+
+struct ant_sel_cck {
+ u8 r_cckrx_enable_2:2;
+ u8 r_cckrx_enable:2;
+ u8 r_ccktx_enable:4;
};
+/*------------------------------Define structure----------------------------*/
+
+/*------------------------Export global variable----------------------------*/
+/*------------------------Export global variable----------------------------*/
+
+/*------------------------Export Marco Definition---------------------------*/
+/*------------------------Export Marco Definition---------------------------*/
+
+/*--------------------------Exported Function prototype---------------------*/
+/* */
+/* BB and RF register read/write */
+/* */
+u32 rtl8188e_PHY_QueryBBReg(struct adapter *adapter, u32 regaddr, u32 mask);
+void rtl8188e_PHY_SetBBReg(struct adapter *Adapter, u32 RegAddr,
+ u32 mask, u32 data);
+u32 rtl8188e_PHY_QueryRFReg(struct adapter *adapter, enum rf_radio_path rfpath,
+ u32 regaddr, u32 mask);
+void rtl8188e_PHY_SetRFReg(struct adapter *adapter, enum rf_radio_path rfpath,
+ u32 regaddr, u32 mask, u32 data);
+
+/* Initialization related function */
+/* MAC/BB/RF HAL config */
+int PHY_MACConfig8188E(struct adapter *adapter);
+int PHY_BBConfig8188E(struct adapter *adapter);
+int PHY_RFConfig8188E(struct adapter *adapter);
+
+/* RF config */
+int rtl8188e_PHY_ConfigRFWithParaFile(struct adapter *adapter, u8 *filename,
+ enum rf_radio_path rfpath);
+int rtl8188e_PHY_ConfigRFWithHeaderFile(struct adapter *adapter,
+ enum rf_radio_path rfpath);
+
/* Read initi reg value for tx power setting. */
void rtl8192c_PHY_GetHWRegOriginalValue(struct adapter *adapter);
/* BB TX Power R/W */
void PHY_GetTxPowerLevel8188E(struct adapter *adapter, u32 *powerlevel);
+void PHY_SetTxPowerLevel8188E(struct adapter *adapter, u8 channel);
+bool PHY_UpdateTxPowerDbm8188E(struct adapter *adapter, int power);
void PHY_ScanOperationBackup8188E(struct adapter *Adapter, u8 Operation);
+/* Switch bandwidth for 8192S */
+void PHY_SetBWMode8188E(struct adapter *adapter,
+ enum ht_channel_width chnlwidth, unsigned char offset);
+
+/* channel switch related funciton */
+void PHY_SwChnl8188E(struct adapter *adapter, u8 channel);
/* Call after initialization */
void ChkFwCmdIoDone(struct adapter *adapter);
@@ -158,6 +219,19 @@ void PHY_EnableHostClkReq(struct adapter *adapter);
bool SetAntennaConfig92C(struct adapter *adapter, u8 defaultant);
+void storePwrIndexDiffRateOffset(struct adapter *adapter, u32 regaddr,
+ u32 mask, u32 data);
+/*--------------------------Exported Function prototype---------------------*/
+
+#define PHY_QueryBBReg(adapt, regaddr, mask) \
+ rtl8188e_PHY_QueryBBReg((adapt), (regaddr), (mask))
+#define PHY_SetBBReg(adapt, regaddr, bitmask, data) \
+ rtl8188e_PHY_SetBBReg((adapt), (regaddr), (bitmask), (data))
+#define PHY_QueryRFReg(adapt, rfpath, regaddr, bitmask) \
+ rtl8188e_PHY_QueryRFReg((adapt), (rfpath), (regaddr), (bitmask))
+#define PHY_SetRFReg(adapt, rfpath, regaddr, bitmask, data) \
+ rtl8188e_PHY_SetRFReg((adapt), (rfpath), (regaddr), (bitmask), (data))
+
#define PHY_SetMacReg PHY_SetBBReg
#define SIC_HW_SUPPORT 0
diff --git a/drivers/staging/r8188eu/include/Hal8188EPhyReg.h b/drivers/staging/r8188eu/include/Hal8188EPhyReg.h
new file mode 100644
index 000000000000..8b8c75a1f149
--- /dev/null
+++ b/drivers/staging/r8188eu/include/Hal8188EPhyReg.h
@@ -0,0 +1,1072 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __INC_HAL8188EPHYREG_H__
+#define __INC_HAL8188EPHYREG_H__
+/*--------------------------Define Parameters-------------------------------*/
+/* */
+/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */
+/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */
+/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
+/* 3. RF register 0x00-2E */
+/* 4. Bit Mask for BB/RF register */
+/* 5. Other definition for BB/RF R/W */
+/* */
+
+/* */
+/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */
+/* 1. Page1(0x100) */
+/* */
+#define rPMAC_Reset 0x100
+#define rPMAC_TxStart 0x104
+#define rPMAC_TxLegacySIG 0x108
+#define rPMAC_TxHTSIG1 0x10c
+#define rPMAC_TxHTSIG2 0x110
+#define rPMAC_PHYDebug 0x114
+#define rPMAC_TxPacketNum 0x118
+#define rPMAC_TxIdle 0x11c
+#define rPMAC_TxMACHeader0 0x120
+#define rPMAC_TxMACHeader1 0x124
+#define rPMAC_TxMACHeader2 0x128
+#define rPMAC_TxMACHeader3 0x12c
+#define rPMAC_TxMACHeader4 0x130
+#define rPMAC_TxMACHeader5 0x134
+#define rPMAC_TxDataType 0x138
+#define rPMAC_TxRandomSeed 0x13c
+#define rPMAC_CCKPLCPPreamble 0x140
+#define rPMAC_CCKPLCPHeader 0x144
+#define rPMAC_CCKCRC16 0x148
+#define rPMAC_OFDMRxCRC32OK 0x170
+#define rPMAC_OFDMRxCRC32Er 0x174
+#define rPMAC_OFDMRxParityEr 0x178
+#define rPMAC_OFDMRxCRC8Er 0x17c
+#define rPMAC_CCKCRxRC16Er 0x180
+#define rPMAC_CCKCRxRC32Er 0x184
+#define rPMAC_CCKCRxRC32OK 0x188
+#define rPMAC_TxStatus 0x18c
+
+/* 2. Page2(0x200) */
+/* The following two definition are only used for USB interface. */
+#define RF_BB_CMD_ADDR 0x02c0 /* RF/BB r/w cmd address. */
+#define RF_BB_CMD_DATA 0x02c4 /* RF/BB r/w cmd data. */
+
+/* 3. Page8(0x800) */
+#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting */
+
+#define rFPGA0_TxInfo 0x804 /* Status report?? */
+#define rFPGA0_PSDFunction 0x808
+
+#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */
+
+#define rFPGA0_RFTiming1 0x810 /* Useless now */
+#define rFPGA0_RFTiming2 0x814
+
+#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */
+#define rFPGA0_XA_HSSIParameter2 0x824
+#define rFPGA0_XB_HSSIParameter1 0x828
+#define rFPGA0_XB_HSSIParameter2 0x82c
+
+#define rFPGA0_XA_LSSIParameter 0x840
+#define rFPGA0_XB_LSSIParameter 0x844
+
+#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */
+#define rFPGA0_RFSleepUpParameter 0x854
+
+#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */
+#define rFPGA0_XCD_SwitchControl 0x85c
+
+#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */
+#define rFPGA0_XB_RFInterfaceOE 0x864
+
+#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Iface Software Control */
+#define rFPGA0_XCD_RFInterfaceSW 0x874
+
+#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */
+#define rFPGA0_XCD_RFParameter 0x87c
+
+/* Crystal cap setting RF-R/W protection for parameter4?? */
+#define rFPGA0_AnalogParameter1 0x880
+#define rFPGA0_AnalogParameter2 0x884
+#define rFPGA0_AnalogParameter3 0x888
+/* enable ad/da clock1 for dual-phy */
+#define rFPGA0_AdDaClockEn 0x888
+#define rFPGA0_AnalogParameter4 0x88c
+
+#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */
+#define rFPGA0_XB_LSSIReadBack 0x8a4
+#define rFPGA0_XC_LSSIReadBack 0x8a8
+#define rFPGA0_XD_LSSIReadBack 0x8ac
+
+#define rFPGA0_PSDReport 0x8b4 /* Useless now */
+/* Transceiver A HSPI Readback */
+#define TransceiverA_HSPI_Readback 0x8b8
+/* Transceiver B HSPI Readback */
+#define TransceiverB_HSPI_Readback 0x8bc
+/* Useless now RF Interface Readback Value */
+#define rFPGA0_XAB_RFInterfaceRB 0x8e0
+#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */
+
+/* 4. Page9(0x900) */
+/* RF mode & OFDM TxSC RF BW Setting?? */
+#define rFPGA1_RFMOD 0x900
+
+#define rFPGA1_TxBlock 0x904 /* Useless now */
+#define rFPGA1_DebugSelect 0x908 /* Useless now */
+#define rFPGA1_TxInfo 0x90c /* Useless now Status report */
+
+/* 5. PageA(0xA00) */
+/* Set Control channel to upper or lower - required only for 40MHz */
+#define rCCK0_System 0xa00
+
+/* Disable init gain now Select RX path by RSSI */
+#define rCCK0_AFESetting 0xa04
+/* Disable init gain now Init gain */
+#define rCCK0_CCA 0xa08
+
+/* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold,
+ * RX LNA Threshold useless now. Not the same as 90 series */
+#define rCCK0_RxAGC1 0xa0c
+#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */
+
+#define rCCK0_RxHP 0xa14
+
+/* Timing recovery & Channel estimation threshold */
+#define rCCK0_DSPParameter1 0xa18
+#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */
+
+#define rCCK0_TxFilter1 0xa20
+#define rCCK0_TxFilter2 0xa24
+#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */
+#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now */
+#define rCCK0_TRSSIReport 0xa50
+#define rCCK0_RxReport 0xa54 /* 0xa57 */
+#define rCCK0_FACounterLower 0xa5c /* 0xa5b */
+#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */
+
+/* */
+/* PageB(0xB00) */
+/* */
+#define rPdp_AntA 0xb00
+#define rPdp_AntA_4 0xb04
+#define rConfig_Pmpd_AntA 0xb28
+#define rConfig_AntA 0xb68
+#define rConfig_AntB 0xb6c
+#define rPdp_AntB 0xb70
+#define rPdp_AntB_4 0xb74
+#define rConfig_Pmpd_AntB 0xb98
+#define rAPK 0xbd8
+
+/* */
+/* 6. PageC(0xC00) */
+/* */
+#define rOFDM0_LSTF 0xc00
+
+#define rOFDM0_TRxPathEnable 0xc04
+#define rOFDM0_TRMuxPar 0xc08
+#define rOFDM0_TRSWIsolation 0xc0c
+
+/* RxIQ DC offset, Rx digital filter, DC notch filter */
+#define rOFDM0_XARxAFE 0xc10
+#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imblance matrix */
+#define rOFDM0_XBRxAFE 0xc18
+#define rOFDM0_XBRxIQImbalance 0xc1c
+#define rOFDM0_XCRxAFE 0xc20
+#define rOFDM0_XCRxIQImbalance 0xc24
+#define rOFDM0_XDRxAFE 0xc28
+#define rOFDM0_XDRxIQImbalance 0xc2c
+
+#define rOFDM0_RxDetector1 0xc30 /*PD,BW & SBD DM tune init gain*/
+#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */
+#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */
+#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */
+
+#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */
+#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */
+#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */
+#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */
+
+#define rOFDM0_XAAGCCore1 0xc50 /* DIG */
+#define rOFDM0_XAAGCCore2 0xc54
+#define rOFDM0_XBAGCCore1 0xc58
+#define rOFDM0_XBAGCCore2 0xc5c
+#define rOFDM0_XCAGCCore1 0xc60
+#define rOFDM0_XCAGCCore2 0xc64
+#define rOFDM0_XDAGCCore1 0xc68
+#define rOFDM0_XDAGCCore2 0xc6c
+
+#define rOFDM0_AGCParameter1 0xc70
+#define rOFDM0_AGCParameter2 0xc74
+#define rOFDM0_AGCRSSITable 0xc78
+#define rOFDM0_HTSTFAGC 0xc7c
+
+#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */
+#define rOFDM0_XATxAFE 0xc84
+#define rOFDM0_XBTxIQImbalance 0xc88
+#define rOFDM0_XBTxAFE 0xc8c
+#define rOFDM0_XCTxIQImbalance 0xc90
+#define rOFDM0_XCTxAFE 0xc94
+#define rOFDM0_XDTxIQImbalance 0xc98
+#define rOFDM0_XDTxAFE 0xc9c
+
+#define rOFDM0_RxIQExtAnta 0xca0
+#define rOFDM0_TxCoeff1 0xca4
+#define rOFDM0_TxCoeff2 0xca8
+#define rOFDM0_TxCoeff3 0xcac
+#define rOFDM0_TxCoeff4 0xcb0
+#define rOFDM0_TxCoeff5 0xcb4
+#define rOFDM0_TxCoeff6 0xcb8
+#define rOFDM0_RxHPParameter 0xce0
+#define rOFDM0_TxPseudoNoiseWgt 0xce4
+#define rOFDM0_FrameSync 0xcf0
+#define rOFDM0_DFSReport 0xcf4
+
+/* */
+/* 7. PageD(0xD00) */
+/* */
+#define rOFDM1_LSTF 0xd00
+#define rOFDM1_TRxPathEnable 0xd04
+
+#define rOFDM1_CFO 0xd08 /* No setting now */
+#define rOFDM1_CSI1 0xd10
+#define rOFDM1_SBD 0xd14
+#define rOFDM1_CSI2 0xd18
+#define rOFDM1_CFOTracking 0xd2c
+#define rOFDM1_TRxMesaure1 0xd34
+#define rOFDM1_IntfDet 0xd3c
+#define rOFDM1_PseudoNoiseStateAB 0xd50
+#define rOFDM1_PseudoNoiseStateCD 0xd54
+#define rOFDM1_RxPseudoNoiseWgt 0xd58
+
+#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */
+#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */
+#define rOFDM_PHYCounter3 0xda8 /* MCS not support */
+
+#define rOFDM_ShortCFOAB 0xdac /* No setting now */
+#define rOFDM_ShortCFOCD 0xdb0
+#define rOFDM_LongCFOAB 0xdb4
+#define rOFDM_LongCFOCD 0xdb8
+#define rOFDM_TailCFOAB 0xdbc
+#define rOFDM_TailCFOCD 0xdc0
+#define rOFDM_PWMeasure1 0xdc4
+#define rOFDM_PWMeasure2 0xdc8
+#define rOFDM_BWReport 0xdcc
+#define rOFDM_AGCReport 0xdd0
+#define rOFDM_RxSNR 0xdd4
+#define rOFDM_RxEVMCSI 0xdd8
+#define rOFDM_SIGReport 0xddc
+
+/* */
+/* 8. PageE(0xE00) */
+/* */
+#define rTxAGC_A_Rate18_06 0xe00
+#define rTxAGC_A_Rate54_24 0xe04
+#define rTxAGC_A_CCK1_Mcs32 0xe08
+#define rTxAGC_A_Mcs03_Mcs00 0xe10
+#define rTxAGC_A_Mcs07_Mcs04 0xe14
+#define rTxAGC_A_Mcs11_Mcs08 0xe18
+#define rTxAGC_A_Mcs15_Mcs12 0xe1c
+
+#define rTxAGC_B_Rate18_06 0x830
+#define rTxAGC_B_Rate54_24 0x834
+#define rTxAGC_B_CCK1_55_Mcs32 0x838
+#define rTxAGC_B_Mcs03_Mcs00 0x83c
+#define rTxAGC_B_Mcs07_Mcs04 0x848
+#define rTxAGC_B_Mcs11_Mcs08 0x84c
+#define rTxAGC_B_Mcs15_Mcs12 0x868
+#define rTxAGC_B_CCK11_A_CCK2_11 0x86c
+
+#define rFPGA0_IQK 0xe28
+#define rTx_IQK_Tone_A 0xe30
+#define rRx_IQK_Tone_A 0xe34
+#define rTx_IQK_PI_A 0xe38
+#define rRx_IQK_PI_A 0xe3c
+
+#define rTx_IQK 0xe40
+#define rRx_IQK 0xe44
+#define rIQK_AGC_Pts 0xe48
+#define rIQK_AGC_Rsp 0xe4c
+#define rTx_IQK_Tone_B 0xe50
+#define rRx_IQK_Tone_B 0xe54
+#define rTx_IQK_PI_B 0xe58
+#define rRx_IQK_PI_B 0xe5c
+#define rIQK_AGC_Cont 0xe60
+
+#define rBlue_Tooth 0xe6c
+#define rRx_Wait_CCA 0xe70
+#define rTx_CCK_RFON 0xe74
+#define rTx_CCK_BBON 0xe78
+#define rTx_OFDM_RFON 0xe7c
+#define rTx_OFDM_BBON 0xe80
+#define rTx_To_Rx 0xe84
+#define rTx_To_Tx 0xe88
+#define rRx_CCK 0xe8c
+
+#define rTx_Power_Before_IQK_A 0xe94
+#define rTx_Power_After_IQK_A 0xe9c
+
+#define rRx_Power_Before_IQK_A 0xea0
+#define rRx_Power_Before_IQK_A_2 0xea4
+#define rRx_Power_After_IQK_A 0xea8
+#define rRx_Power_After_IQK_A_2 0xeac
+
+#define rTx_Power_Before_IQK_B 0xeb4
+#define rTx_Power_After_IQK_B 0xebc
+
+#define rRx_Power_Before_IQK_B 0xec0
+#define rRx_Power_Before_IQK_B_2 0xec4
+#define rRx_Power_After_IQK_B 0xec8
+#define rRx_Power_After_IQK_B_2 0xecc
+
+#define rRx_OFDM 0xed0
+#define rRx_Wait_RIFS 0xed4
+#define rRx_TO_Rx 0xed8
+#define rStandby 0xedc
+#define rSleep 0xee0
+#define rPMPD_ANAEN 0xeec
+
+/* */
+/* 7. RF Register 0x00-0x2E (RF 8256) */
+/* RF-0222D 0x00-3F */
+/* */
+/* Zebra1 */
+#define rZebra1_HSSIEnable 0x0 /* Useless now */
+#define rZebra1_TRxEnable1 0x1
+#define rZebra1_TRxEnable2 0x2
+#define rZebra1_AGC 0x4
+#define rZebra1_ChargePump 0x5
+#define rZebra1_Channel 0x7 /* RF channel switch */
+
+/* endif */
+#define rZebra1_TxGain 0x8 /* Useless now */
+#define rZebra1_TxLPF 0x9
+#define rZebra1_RxLPF 0xb
+#define rZebra1_RxHPFCorner 0xc
+
+/* Zebra4 */
+#define rGlobalCtrl 0 /* Useless now */
+#define rRTL8256_TxLPF 19
+#define rRTL8256_RxLPF 11
+
+/* RTL8258 */
+#define rRTL8258_TxLPF 0x11 /* Useless now */
+#define rRTL8258_RxLPF 0x13
+#define rRTL8258_RSSILPF 0xa
+
+/* */
+/* RL6052 Register definition */
+/* */
+#define RF_AC 0x00 /* */
+
+#define RF_IQADJ_G1 0x01 /* */
+#define RF_IQADJ_G2 0x02 /* */
+
+#define RF_POW_TRSW 0x05 /* */
+
+#define RF_GAIN_RX 0x06 /* */
+#define RF_GAIN_TX 0x07 /* */
+
+#define RF_TXM_IDAC 0x08 /* */
+#define RF_IPA_G 0x09 /* */
+#define RF_TXBIAS_G 0x0A
+#define RF_TXPA_AG 0x0B
+#define RF_IPA_A 0x0C /* */
+#define RF_TXBIAS_A 0x0D
+#define RF_BS_PA_APSET_G9_G11 0x0E
+#define RF_BS_IQGEN 0x0F /* */
+
+#define RF_MODE1 0x10 /* */
+#define RF_MODE2 0x11 /* */
+
+#define RF_RX_AGC_HP 0x12 /* */
+#define RF_TX_AGC 0x13 /* */
+#define RF_BIAS 0x14 /* */
+#define RF_IPA 0x15 /* */
+#define RF_TXBIAS 0x16
+#define RF_POW_ABILITY 0x17 /* */
+#define RF_CHNLBW 0x18 /* RF channel and BW switch */
+#define RF_TOP 0x19 /* */
+
+#define RF_RX_G1 0x1A /* */
+#define RF_RX_G2 0x1B /* */
+
+#define RF_RX_BB2 0x1C /* */
+#define RF_RX_BB1 0x1D /* */
+
+#define RF_RCK1 0x1E /* */
+#define RF_RCK2 0x1F /* */
+
+#define RF_TX_G1 0x20 /* */
+#define RF_TX_G2 0x21 /* */
+#define RF_TX_G3 0x22 /* */
+
+#define RF_TX_BB1 0x23 /* */
+
+#define RF_T_METER_92D 0x42 /* */
+#define RF_T_METER_88E 0x42 /* */
+#define RF_T_METER 0x24 /* */
+
+#define RF_SYN_G1 0x25 /* RF TX Power control */
+#define RF_SYN_G2 0x26 /* RF TX Power control */
+#define RF_SYN_G3 0x27 /* RF TX Power control */
+#define RF_SYN_G4 0x28 /* RF TX Power control */
+#define RF_SYN_G5 0x29 /* RF TX Power control */
+#define RF_SYN_G6 0x2A /* RF TX Power control */
+#define RF_SYN_G7 0x2B /* RF TX Power control */
+#define RF_SYN_G8 0x2C /* RF TX Power control */
+
+#define RF_RCK_OS 0x30 /* RF TX PA control */
+#define RF_TXPA_G1 0x31 /* RF TX PA control */
+#define RF_TXPA_G2 0x32 /* RF TX PA control */
+#define RF_TXPA_G3 0x33 /* RF TX PA control */
+#define RF_TX_BIAS_A 0x35
+#define RF_TX_BIAS_D 0x36
+#define RF_LOBF_9 0x38
+#define RF_RXRF_A3 0x3C /* */
+#define RF_TRSW 0x3F
+
+#define RF_TXRF_A2 0x41
+#define RF_TXPA_G4 0x46
+#define RF_TXPA_A4 0x4B
+#define RF_0x52 0x52
+#define RF_WE_LUT 0xEF
+
+/* */
+/* Bit Mask */
+/* */
+/* 1. Page1(0x100) */
+#define bBBResetB 0x100 /* Useless now? */
+#define bGlobalResetB 0x200
+#define bOFDMTxStart 0x4
+#define bCCKTxStart 0x8
+#define bCRC32Debug 0x100
+#define bPMACLoopback 0x10
+#define bTxLSIG 0xffffff
+#define bOFDMTxRate 0xf
+#define bOFDMTxReserved 0x10
+#define bOFDMTxLength 0x1ffe0
+#define bOFDMTxParity 0x20000
+#define bTxHTSIG1 0xffffff
+#define bTxHTMCSRate 0x7f
+#define bTxHTBW 0x80
+#define bTxHTLength 0xffff00
+#define bTxHTSIG2 0xffffff
+#define bTxHTSmoothing 0x1
+#define bTxHTSounding 0x2
+#define bTxHTReserved 0x4
+#define bTxHTAggreation 0x8
+#define bTxHTSTBC 0x30
+#define bTxHTAdvanceCoding 0x40
+#define bTxHTShortGI 0x80
+#define bTxHTNumberHT_LTF 0x300
+#define bTxHTCRC8 0x3fc00
+#define bCounterReset 0x10000
+#define bNumOfOFDMTx 0xffff
+#define bNumOfCCKTx 0xffff0000
+#define bTxIdleInterval 0xffff
+#define bOFDMService 0xffff0000
+#define bTxMACHeader 0xffffffff
+#define bTxDataInit 0xff
+#define bTxHTMode 0x100
+#define bTxDataType 0x30000
+#define bTxRandomSeed 0xffffffff
+#define bCCKTxPreamble 0x1
+#define bCCKTxSFD 0xffff0000
+#define bCCKTxSIG 0xff
+#define bCCKTxService 0xff00
+#define bCCKLengthExt 0x8000
+#define bCCKTxLength 0xffff0000
+#define bCCKTxCRC16 0xffff
+#define bCCKTxStatus 0x1
+#define bOFDMTxStatus 0x2
+
+#define IS_BB_REG_OFFSET_92S(_Offset) \
+ ((_Offset >= 0x800) && (_Offset <= 0xfff))
+
+/* 2. Page8(0x800) */
+#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */
+#define bJapanMode 0x2
+#define bCCKTxSC 0x30
+#define bCCKEn 0x1000000
+#define bOFDMEn 0x2000000
+
+#define bOFDMRxADCPhase 0x10000 /* Useless now */
+#define bOFDMTxDACPhase 0x40000
+#define bXATxAGC 0x3f
+
+#define bAntennaSelect 0x0300
+
+#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */
+#define bXCTxAGC 0xf000
+#define bXDTxAGC 0xf0000
+
+#define bPAStart 0xf0000000 /* Useless now */
+#define bTRStart 0x00f00000
+#define bRFStart 0x0000f000
+#define bBBStart 0x000000f0
+#define bBBCCKStart 0x0000000f
+#define bPAEnd 0xf /* Reg0x814 */
+#define bTREnd 0x0f000000
+#define bRFEnd 0x000f0000
+#define bCCAMask 0x000000f0 /* T2R */
+#define bR2RCCAMask 0x00000f00
+#define bHSSI_R2TDelay 0xf8000000
+#define bHSSI_T2RDelay 0xf80000
+#define bContTxHSSI 0x400 /* change gain at continue Tx */
+#define bIGFromCCK 0x200
+#define bAGCAddress 0x3f
+#define bRxHPTx 0x7000
+#define bRxHPT2R 0x38000
+#define bRxHPCCKIni 0xc0000
+#define bAGCTxCode 0xc00000
+#define bAGCRxCode 0x300000
+
+/* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */
+#define b3WireDataLength 0x800
+#define b3WireAddressLength 0x400
+
+#define b3WireRFPowerDown 0x1 /* Useless now */
+#define b5GPAPEPolarity 0x40000000
+#define b2GPAPEPolarity 0x80000000
+#define bRFSW_TxDefaultAnt 0x3
+#define bRFSW_TxOptionAnt 0x30
+#define bRFSW_RxDefaultAnt 0x300
+#define bRFSW_RxOptionAnt 0x3000
+#define bRFSI_3WireData 0x1
+#define bRFSI_3WireClock 0x2
+#define bRFSI_3WireLoad 0x4
+#define bRFSI_3WireRW 0x8
+#define bRFSI_3Wire 0xf
+
+#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */
+
+#define bRFSI_TRSW 0x20 /* Useless now */
+#define bRFSI_TRSWB 0x40
+#define bRFSI_ANTSW 0x100
+#define bRFSI_ANTSWB 0x200
+#define bRFSI_PAPE 0x400
+#define bRFSI_PAPE5G 0x800
+#define bBandSelect 0x1
+#define bHTSIG2_GI 0x80
+#define bHTSIG2_Smoothing 0x01
+#define bHTSIG2_Sounding 0x02
+#define bHTSIG2_Aggreaton 0x08
+#define bHTSIG2_STBC 0x30
+#define bHTSIG2_AdvCoding 0x40
+#define bHTSIG2_NumOfHTLTF 0x300
+#define bHTSIG2_CRC8 0x3fc
+#define bHTSIG1_MCS 0x7f
+#define bHTSIG1_BandWidth 0x80
+#define bHTSIG1_HTLength 0xffff
+#define bLSIG_Rate 0xf
+#define bLSIG_Reserved 0x10
+#define bLSIG_Length 0x1fffe
+#define bLSIG_Parity 0x20
+#define bCCKRxPhase 0x4
+
+#define bLSSIReadAddress 0x7f800000 /* T65 RF */
+
+#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */
+
+#define bLSSIReadBackData 0xfffff /* T65 RF */
+
+#define bLSSIReadOKFlag 0x1000 /* Useless now */
+#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */
+#define bRegulator0Standby 0x1
+#define bRegulatorPLLStandby 0x2
+#define bRegulator1Standby 0x4
+#define bPLLPowerUp 0x8
+#define bDPLLPowerUp 0x10
+#define bDA10PowerUp 0x20
+#define bAD7PowerUp 0x200
+#define bDA6PowerUp 0x2000
+#define bXtalPowerUp 0x4000
+#define b40MDClkPowerUP 0x8000
+#define bDA6DebugMode 0x20000
+#define bDA6Swing 0x380000
+
+/* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */
+#define bADClkPhase 0x4000000
+
+#define b80MClkDelay 0x18000000 /* Useless */
+#define bAFEWatchDogEnable 0x20000000
+
+/* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */
+#define bXtalCap01 0xc0000000
+#define bXtalCap23 0x3
+#define bXtalCap92x 0x0f000000
+#define bXtalCap 0x0f000000
+
+#define bIntDifClkEnable 0x400 /* Useless */
+#define bExtSigClkEnable 0x800
+#define bBandgapMbiasPowerUp 0x10000
+#define bAD11SHGain 0xc0000
+#define bAD11InputRange 0x700000
+#define bAD11OPCurrent 0x3800000
+#define bIPathLoopback 0x4000000
+#define bQPathLoopback 0x8000000
+#define bAFELoopback 0x10000000
+#define bDA10Swing 0x7e0
+#define bDA10Reverse 0x800
+#define bDAClkSource 0x1000
+#define bAD7InputRange 0x6000
+#define bAD7Gain 0x38000
+#define bAD7OutputCMMode 0x40000
+#define bAD7InputCMMode 0x380000
+#define bAD7Current 0xc00000
+#define bRegulatorAdjust 0x7000000
+#define bAD11PowerUpAtTx 0x1
+#define bDA10PSAtTx 0x10
+#define bAD11PowerUpAtRx 0x100
+#define bDA10PSAtRx 0x1000
+#define bCCKRxAGCFormat 0x200
+#define bPSDFFTSamplepPoint 0xc000
+#define bPSDAverageNum 0x3000
+#define bIQPathControl 0xc00
+#define bPSDFreq 0x3ff
+#define bPSDAntennaPath 0x30
+#define bPSDIQSwitch 0x40
+#define bPSDRxTrigger 0x400000
+#define bPSDTxTrigger 0x80000000
+#define bPSDSineToneScale 0x7f000000
+#define bPSDReport 0xffff
+
+/* 3. Page9(0x900) */
+#define bOFDMTxSC 0x30000000 /* Useless */
+#define bCCKTxOn 0x1
+#define bOFDMTxOn 0x2
+#define bDebugPage 0xfff /* reset debug page and HWord, LWord */
+#define bDebugItem 0xff /* reset debug page and LWord */
+#define bAntL 0x10
+#define bAntNonHT 0x100
+#define bAntHT1 0x1000
+#define bAntHT2 0x10000
+#define bAntHT1S1 0x100000
+#define bAntNonHTS1 0x1000000
+
+/* 4. PageA(0xA00) */
+#define bCCKBBMode 0x3 /* Useless */
+#define bCCKTxPowerSaving 0x80
+#define bCCKRxPowerSaving 0x40
+
+#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 */
+
+#define bCCKScramble 0x8 /* Useless */
+#define bCCKAntDiversity 0x8000
+#define bCCKCarrierRecovery 0x4000
+#define bCCKTxRate 0x3000
+#define bCCKDCCancel 0x0800
+#define bCCKISICancel 0x0400
+#define bCCKMatchFilter 0x0200
+#define bCCKEqualizer 0x0100
+#define bCCKPreambleDetect 0x800000
+#define bCCKFastFalseCCA 0x400000
+#define bCCKChEstStart 0x300000
+#define bCCKCCACount 0x080000
+#define bCCKcs_lim 0x070000
+#define bCCKBistMode 0x80000000
+#define bCCKCCAMask 0x40000000
+#define bCCKTxDACPhase 0x4
+#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */
+#define bCCKr_cp_mode0 0x0100
+#define bCCKTxDCOffset 0xf0
+#define bCCKRxDCOffset 0xf
+#define bCCKCCAMode 0xc000
+#define bCCKFalseCS_lim 0x3f00
+#define bCCKCS_ratio 0xc00000
+#define bCCKCorgBit_sel 0x300000
+#define bCCKPD_lim 0x0f0000
+#define bCCKNewCCA 0x80000000
+#define bCCKRxHPofIG 0x8000
+#define bCCKRxIG 0x7f00
+#define bCCKLNAPolarity 0x800000
+#define bCCKRx1stGain 0x7f0000
+#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */
+#define bCCKRxAGCSatLevel 0x1f000000
+#define bCCKRxAGCSatCount 0xe0
+#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */
+#define bCCKFixedRxAGC 0x8000
+#define bCCKAntennaPolarity 0x2000
+#define bCCKTxFilterType 0x0c00
+#define bCCKRxAGCReportType 0x0300
+#define bCCKRxDAGCEn 0x80000000
+#define bCCKRxDAGCPeriod 0x20000000
+#define bCCKRxDAGCSatLevel 0x1f000000
+#define bCCKTimingRecovery 0x800000
+#define bCCKTxC0 0x3f0000
+#define bCCKTxC1 0x3f000000
+#define bCCKTxC2 0x3f
+#define bCCKTxC3 0x3f00
+#define bCCKTxC4 0x3f0000
+#define bCCKTxC5 0x3f000000
+#define bCCKTxC6 0x3f
+#define bCCKTxC7 0x3f00
+#define bCCKDebugPort 0xff0000
+#define bCCKDACDebug 0x0f000000
+#define bCCKFalseAlarmEnable 0x8000
+#define bCCKFalseAlarmRead 0x4000
+#define bCCKTRSSI 0x7f
+#define bCCKRxAGCReport 0xfe
+#define bCCKRxReport_AntSel 0x80000000
+#define bCCKRxReport_MFOff 0x40000000
+#define bCCKRxRxReport_SQLoss 0x20000000
+#define bCCKRxReport_Pktloss 0x10000000
+#define bCCKRxReport_Lockedbit 0x08000000
+#define bCCKRxReport_RateError 0x04000000
+#define bCCKRxReport_RxRate 0x03000000
+#define bCCKRxFACounterLower 0xff
+#define bCCKRxFACounterUpper 0xff000000
+#define bCCKRxHPAGCStart 0xe000
+#define bCCKRxHPAGCFinal 0x1c00
+#define bCCKRxFalseAlarmEnable 0x8000
+#define bCCKFACounterFreeze 0x4000
+#define bCCKTxPathSel 0x10000000
+#define bCCKDefaultRxPath 0xc000000
+#define bCCKOptionRxPath 0x3000000
+
+/* 5. PageC(0xC00) */
+#define bNumOfSTF 0x3 /* Useless */
+#define bShift_L 0xc0
+#define bGI_TH 0xc
+#define bRxPathA 0x1
+#define bRxPathB 0x2
+#define bRxPathC 0x4
+#define bRxPathD 0x8
+#define bTxPathA 0x1
+#define bTxPathB 0x2
+#define bTxPathC 0x4
+#define bTxPathD 0x8
+#define bTRSSIFreq 0x200
+#define bADCBackoff 0x3000
+#define bDFIRBackoff 0xc000
+#define bTRSSILatchPhase 0x10000
+#define bRxIDCOffset 0xff
+#define bRxQDCOffset 0xff00
+#define bRxDFIRMode 0x1800000
+#define bRxDCNFType 0xe000000
+#define bRXIQImb_A 0x3ff
+#define bRXIQImb_B 0xfc00
+#define bRXIQImb_C 0x3f0000
+#define bRXIQImb_D 0xffc00000
+#define bDC_dc_Notch 0x60000
+#define bRxNBINotch 0x1f000000
+#define bPD_TH 0xf
+#define bPD_TH_Opt2 0xc000
+#define bPWED_TH 0x700
+#define bIfMF_Win_L 0x800
+#define bPD_Option 0x1000
+#define bMF_Win_L 0xe000
+#define bBW_Search_L 0x30000
+#define bwin_enh_L 0xc0000
+#define bBW_TH 0x700000
+#define bED_TH2 0x3800000
+#define bBW_option 0x4000000
+#define bRatio_TH 0x18000000
+#define bWindow_L 0xe0000000
+#define bSBD_Option 0x1
+#define bFrame_TH 0x1c
+#define bFS_Option 0x60
+#define bDC_Slope_check 0x80
+#define bFGuard_Counter_DC_L 0xe00
+#define bFrame_Weight_Short 0x7000
+#define bSub_Tune 0xe00000
+#define bFrame_DC_Length 0xe000000
+#define bSBD_start_offset 0x30000000
+#define bFrame_TH_2 0x7
+#define bFrame_GI2_TH 0x38
+#define bGI2_Sync_en 0x40
+#define bSarch_Short_Early 0x300
+#define bSarch_Short_Late 0xc00
+#define bSarch_GI2_Late 0x70000
+#define bCFOAntSum 0x1
+#define bCFOAcc 0x2
+#define bCFOStartOffset 0xc
+#define bCFOLookBack 0x70
+#define bCFOSumWeight 0x80
+#define bDAGCEnable 0x10000
+#define bTXIQImb_A 0x3ff
+#define bTXIQImb_B 0xfc00
+#define bTXIQImb_C 0x3f0000
+#define bTXIQImb_D 0xffc00000
+#define bTxIDCOffset 0xff
+#define bTxQDCOffset 0xff00
+#define bTxDFIRMode 0x10000
+#define bTxPesudoNoiseOn 0x4000000
+#define bTxPesudoNoise_A 0xff
+#define bTxPesudoNoise_B 0xff00
+#define bTxPesudoNoise_C 0xff0000
+#define bTxPesudoNoise_D 0xff000000
+#define bCCADropOption 0x20000
+#define bCCADropThres 0xfff00000
+#define bEDCCA_H 0xf
+#define bEDCCA_L 0xf0
+#define bLambda_ED 0x300
+#define bRxInitialGain 0x7f
+#define bRxAntDivEn 0x80
+#define bRxAGCAddressForLNA 0x7f00
+#define bRxHighPowerFlow 0x8000
+#define bRxAGCFreezeThres 0xc0000
+#define bRxFreezeStep_AGC1 0x300000
+#define bRxFreezeStep_AGC2 0xc00000
+#define bRxFreezeStep_AGC3 0x3000000
+#define bRxFreezeStep_AGC0 0xc000000
+#define bRxRssi_Cmp_En 0x10000000
+#define bRxQuickAGCEn 0x20000000
+#define bRxAGCFreezeThresMode 0x40000000
+#define bRxOverFlowCheckType 0x80000000
+#define bRxAGCShift 0x7f
+#define bTRSW_Tri_Only 0x80
+#define bPowerThres 0x300
+#define bRxAGCEn 0x1
+#define bRxAGCTogetherEn 0x2
+#define bRxAGCMin 0x4
+#define bRxHP_Ini 0x7
+#define bRxHP_TRLNA 0x70
+#define bRxHP_RSSI 0x700
+#define bRxHP_BBP1 0x7000
+#define bRxHP_BBP2 0x70000
+#define bRxHP_BBP3 0x700000
+#define bRSSI_H 0x7f0000 /* threshold for high power */
+#define bRSSI_Gen 0x7f000000 /* threshold for ant diversity */
+#define bRxSettle_TRSW 0x7
+#define bRxSettle_LNA 0x38
+#define bRxSettle_RSSI 0x1c0
+#define bRxSettle_BBP 0xe00
+#define bRxSettle_RxHP 0x7000
+#define bRxSettle_AntSW_RSSI 0x38000
+#define bRxSettle_AntSW 0xc0000
+#define bRxProcessTime_DAGC 0x300000
+#define bRxSettle_HSSI 0x400000
+#define bRxProcessTime_BBPPW 0x800000
+#define bRxAntennaPowerShift 0x3000000
+#define bRSSITableSelect 0xc000000
+#define bRxHP_Final 0x7000000
+#define bRxHTSettle_BBP 0x7
+#define bRxHTSettle_HSSI 0x8
+#define bRxHTSettle_RxHP 0x70
+#define bRxHTSettle_BBPPW 0x80
+#define bRxHTSettle_Idle 0x300
+#define bRxHTSettle_Reserved 0x1c00
+#define bRxHTRxHPEn 0x8000
+#define bRxHTAGCFreezeThres 0x30000
+#define bRxHTAGCTogetherEn 0x40000
+#define bRxHTAGCMin 0x80000
+#define bRxHTAGCEn 0x100000
+#define bRxHTDAGCEn 0x200000
+#define bRxHTRxHP_BBP 0x1c00000
+#define bRxHTRxHP_Final 0xe0000000
+#define bRxPWRatioTH 0x3
+#define bRxPWRatioEn 0x4
+#define bRxMFHold 0x3800
+#define bRxPD_Delay_TH1 0x38
+#define bRxPD_Delay_TH2 0x1c0
+#define bRxPD_DC_COUNT_MAX 0x600
+#define bRxPD_Delay_TH 0x8000
+#define bRxProcess_Delay 0xf0000
+#define bRxSearchrange_GI2_Early 0x700000
+#define bRxFrame_Guard_Counter_L 0x3800000
+#define bRxSGI_Guard_L 0xc000000
+#define bRxSGI_Search_L 0x30000000
+#define bRxSGI_TH 0xc0000000
+#define bDFSCnt0 0xff
+#define bDFSCnt1 0xff00
+#define bDFSFlag 0xf0000
+#define bMFWeightSum 0x300000
+#define bMinIdxTH 0x7f000000
+#define bDAFormat 0x40000
+#define bTxChEmuEnable 0x01000000
+#define bTRSWIsolation_A 0x7f
+#define bTRSWIsolation_B 0x7f00
+#define bTRSWIsolation_C 0x7f0000
+#define bTRSWIsolation_D 0x7f000000
+#define bExtLNAGain 0x7c00
+
+/* 6. PageE(0xE00) */
+#define bSTBCEn 0x4 /* Useless */
+#define bAntennaMapping 0x10
+#define bNss 0x20
+#define bCFOAntSumD 0x200
+#define bPHYCounterReset 0x8000000
+#define bCFOReportGet 0x4000000
+#define bOFDMContinueTx 0x10000000
+#define bOFDMSingleCarrier 0x20000000
+#define bOFDMSingleTone 0x40000000
+#define bHTDetect 0x100
+#define bCFOEn 0x10000
+#define bCFOValue 0xfff00000
+#define bSigTone_Re 0x3f
+#define bSigTone_Im 0x7f00
+#define bCounter_CCA 0xffff
+#define bCounter_ParityFail 0xffff0000
+#define bCounter_RateIllegal 0xffff
+#define bCounter_CRC8Fail 0xffff0000
+#define bCounter_MCSNoSupport 0xffff
+#define bCounter_FastSync 0xffff
+#define bShortCFO 0xfff
+#define bShortCFOTLength 12 /* total */
+#define bShortCFOFLength 11 /* fraction */
+#define bLongCFO 0x7ff
+#define bLongCFOTLength 11
+#define bLongCFOFLength 11
+#define bTailCFO 0x1fff
+#define bTailCFOTLength 13
+#define bTailCFOFLength 12
+#define bmax_en_pwdB 0xffff
+#define bCC_power_dB 0xffff0000
+#define bnoise_pwdB 0xffff
+#define bPowerMeasTLength 10
+#define bPowerMeasFLength 3
+#define bRx_HT_BW 0x1
+#define bRxSC 0x6
+#define bRx_HT 0x8
+#define bNB_intf_det_on 0x1
+#define bIntf_win_len_cfg 0x30
+#define bNB_Intf_TH_cfg 0x1c0
+#define bRFGain 0x3f
+#define bTableSel 0x40
+#define bTRSW 0x80
+#define bRxSNR_A 0xff
+#define bRxSNR_B 0xff00
+#define bRxSNR_C 0xff0000
+#define bRxSNR_D 0xff000000
+#define bSNREVMTLength 8
+#define bSNREVMFLength 1
+#define bCSI1st 0xff
+#define bCSI2nd 0xff00
+#define bRxEVM1st 0xff0000
+#define bRxEVM2nd 0xff000000
+#define bSIGEVM 0xff
+#define bPWDB 0xff00
+#define bSGIEN 0x10000
+
+#define bSFactorQAM1 0xf /* Useless */
+#define bSFactorQAM2 0xf0
+#define bSFactorQAM3 0xf00
+#define bSFactorQAM4 0xf000
+#define bSFactorQAM5 0xf0000
+#define bSFactorQAM6 0xf0000
+#define bSFactorQAM7 0xf00000
+#define bSFactorQAM8 0xf000000
+#define bSFactorQAM9 0xf0000000
+#define bCSIScheme 0x100000
+
+#define bNoiseLvlTopSet 0x3 /* Useless */
+#define bChSmooth 0x4
+#define bChSmoothCfg1 0x38
+#define bChSmoothCfg2 0x1c0
+#define bChSmoothCfg3 0xe00
+#define bChSmoothCfg4 0x7000
+#define bMRCMode 0x800000
+#define bTHEVMCfg 0x7000000
+
+#define bLoopFitType 0x1 /* Useless */
+#define bUpdCFO 0x40
+#define bUpdCFOOffData 0x80
+#define bAdvUpdCFO 0x100
+#define bAdvTimeCtrl 0x800
+#define bUpdClko 0x1000
+#define bFC 0x6000
+#define bTrackingMode 0x8000
+#define bPhCmpEnable 0x10000
+#define bUpdClkoLTF 0x20000
+#define bComChCFO 0x40000
+#define bCSIEstiMode 0x80000
+#define bAdvUpdEqz 0x100000
+#define bUChCfg 0x7000000
+#define bUpdEqz 0x8000000
+
+/* Rx Pseduo noise */
+#define bRxPesudoNoiseOn 0x20000000 /* Useless */
+#define bRxPesudoNoise_A 0xff
+#define bRxPesudoNoise_B 0xff00
+#define bRxPesudoNoise_C 0xff0000
+#define bRxPesudoNoise_D 0xff000000
+#define bPesudoNoiseState_A 0xffff
+#define bPesudoNoiseState_B 0xffff0000
+#define bPesudoNoiseState_C 0xffff
+#define bPesudoNoiseState_D 0xffff0000
+
+/* 7. RF Register */
+/* Zebra1 */
+#define bZebra1_HSSIEnable 0x8 /* Useless */
+#define bZebra1_TRxControl 0xc00
+#define bZebra1_TRxGainSetting 0x07f
+#define bZebra1_RxCorner 0xc00
+#define bZebra1_TxChargePump 0x38
+#define bZebra1_RxChargePump 0x7
+#define bZebra1_ChannelNum 0xf80
+#define bZebra1_TxLPFBW 0x400
+#define bZebra1_RxLPFBW 0x600
+
+/* Zebra4 */
+#define bRTL8256RegModeCtrl1 0x100 /* Useless */
+#define bRTL8256RegModeCtrl0 0x40
+#define bRTL8256_TxLPFBW 0x18
+#define bRTL8256_RxLPFBW 0x600
+
+/* RTL8258 */
+#define bRTL8258_TxLPFBW 0xc /* Useless */
+#define bRTL8258_RxLPFBW 0xc00
+#define bRTL8258_RSSILPFBW 0xc0
+
+/* */
+/* Other Definition */
+/* */
+
+/* byte endable for sb_write */
+#define bByte0 0x1 /* Useless */
+#define bByte1 0x2
+#define bByte2 0x4
+#define bByte3 0x8
+#define bWord0 0x3
+#define bWord1 0xc
+#define bDWord 0xf
+
+/* for PutRegsetting & GetRegSetting BitMask */
+#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */
+#define bMaskByte1 0xff00
+#define bMaskByte2 0xff0000
+#define bMaskByte3 0xff000000
+#define bMaskHWord 0xffff0000
+#define bMaskLWord 0x0000ffff
+#define bMaskDWord 0xffffffff
+#define bMask12Bits 0xfff
+#define bMaskH4Bits 0xf0000000
+#define bMaskOFDM_D 0xffc00000
+#define bMaskCCK 0x3f3f3f3f
+
+/* for PutRFRegsetting & GetRFRegSetting BitMask */
+#define bRFRegOffsetMask 0xfffff
+
+#define bEnable 0x1 /* Useless */
+#define bDisable 0x0
+
+#define LeftAntenna 0x0 /* Useless */
+#define RightAntenna 0x1
+
+#define tCheckTxStatus 500 /* 500ms Useless */
+#define tUpdateRxCounter 100 /* 100ms */
+
+#define rateCCK 0 /* Useless */
+#define rateOFDM 1
+#define rateHT 2
+
+/* define Register-End */
+#define bPMAC_End 0x1ff /* Useless */
+#define bFPGAPHY0_End 0x8ff
+#define bFPGAPHY1_End 0x9ff
+#define bCCKPHY0_End 0xaff
+#define bOFDMPHY0_End 0xcff
+#define bOFDMPHY1_End 0xdff
+
+#define bPMACControl 0x0 /* Useless */
+#define bWMACControl 0x1
+#define bWNICControl 0x2
+
+#define PathA 0x0 /* Useless */
+#define PathB 0x1
+#define PathC 0x2
+#define PathD 0x3
+
+/*--------------------------Define Parameters-------------------------------*/
+
+#endif
diff --git a/drivers/staging/r8188eu/include/Hal8188EPwrSeq.h b/drivers/staging/r8188eu/include/Hal8188EPwrSeq.h
new file mode 100644
index 000000000000..a73bd1a5d57b
--- /dev/null
+++ b/drivers/staging/r8188eu/include/Hal8188EPwrSeq.h
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __HAL8188EPWRSEQ_H__
+#define __HAL8188EPWRSEQ_H__
+
+#include "HalPwrSeqCmd.h"
+
+/*
+ Check document WM-20110607-Paul-RTL8188E_Power_Architecture-R02.vsd
+ There are 6 HW Power States:
+ 0: POFF--Power Off
+ 1: PDN--Power Down
+ 2: CARDEMU--Card Emulation
+ 3: ACT--Active Mode
+ 4: LPS--Low Power State
+ 5: SUS--Suspend
+
+ The transision from different states are defined below
+ TRANS_CARDEMU_TO_ACT
+ TRANS_ACT_TO_CARDEMU
+ TRANS_CARDEMU_TO_SUS
+ TRANS_SUS_TO_CARDEMU
+ TRANS_CARDEMU_TO_PDN
+ TRANS_ACT_TO_LPS
+ TRANS_LPS_TO_ACT
+
+ TRANS_END
+
+ PWR SEQ Version: rtl8188E_PwrSeq_V09.h
+*/
+#define RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS 10
+#define RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS 10
+#define RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS 10
+#define RTL8188E_TRANS_SUS_TO_CARDEMU_STEPS 10
+#define RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS 10
+#define RTL8188E_TRANS_PDN_TO_CARDEMU_STEPS 10
+#define RTL8188E_TRANS_ACT_TO_LPS_STEPS 15
+#define RTL8188E_TRANS_LPS_TO_ACT_STEPS 15
+#define RTL8188E_TRANS_END_STEPS 1
+
+#define RTL8188E_TRANS_CARDEMU_TO_ACT \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \
+ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},/* wait till 0x04[17] = 1 power ready*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0)|BIT(1), 0}, /* 0x02[1:0] = 0 reset BB*/ \
+ {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, /*0x24[23] = 2b'01 schmit trigger */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, /* 0x04[15] = 0 disable HWPDN (control by DRV)*/\
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), 0}, /*0x04[12:11] = 2b'00 disable WL suspend*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x04[8] = 1 polling until return 0*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, /*wait till 0x04[8] = 0*/ \
+ {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*LDO normal mode*/ \
+ {0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*SDIO Driving*/ \
+
+#define RTL8188E_TRANS_ACT_TO_CARDEMU \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \
+ {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/ \
+ {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*LDO Sleep mode*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, /*0x04[9] = 1 turn off MAC by HW state machine*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \
+
+#define RTL8188E_TRANS_CARDEMU_TO_SUS \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01enable WL suspend*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)}, /*0x04[12:11] = 2b'11enable WL suspend for PCIe*/ \
+ {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, BIT(7)}, /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */ \
+ {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*Clear SIC_EN register 0x40[12] = 1'b0 */ \
+ {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*Set USB suspend enable local register 0xfe10[4]=1 */ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*Set SDIO suspend local register*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/
+
+#define RTL8188E_TRANS_SUS_TO_CARDEMU \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/
+
+#define RTL8188E_TRANS_CARDEMU_TO_CARDDIS \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \
+ {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, /*0x24[23] = 2b'01 schmit trigger */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \
+ {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */ \
+ {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*Clear SIC_EN register 0x40[12] = 1'b0 */ \
+ {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*Set USB suspend enable local register 0xfe10[4]=1 */ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*Set SDIO suspend local register*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/
+
+#define RTL8188E_TRANS_CARDDIS_TO_CARDEMU \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \
+ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/
+
+#define RTL8188E_TRANS_CARDEMU_TO_PDN \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \
+ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/\
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/
+
+#define RTL8188E_TRANS_PDN_TO_CARDEMU \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/
+
+/* This is used by driver for LPSRadioOff Procedure, not for FW LPS Step */
+#define RTL8188E_TRANS_ACT_TO_LPS \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here */ \
+ {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \
+ {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \
+ {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \
+ {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \
+ {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/*CCK and OFDM are disabled,and clock are gated*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/ \
+ {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/ \
+ {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/ \
+ {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)},/*Respond TxOK to scheduler*/ \
+
+#define RTL8188E_TRANS_LPS_TO_ACT \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here */ \
+ {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/\
+ {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\
+ {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/\
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\
+ {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*. 0x08[4] = 0 switch TSF to 40M*/\
+ {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, /*Polling 0x109[7]=0 TSF in 40M*/\
+ {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, /*. 0x29[7:6] = 2b'00 enable BB clock*/\
+ {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, /*. 0x101[1] = 1*/\
+ {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\
+ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)}, /*. 0x02[1:0] = 2b'11 enable BB macro*/\
+ {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/
+
+#define RTL8188E_TRANS_END \
+ /* format */ \
+ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \
+ {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,0, PWR_CMD_END, 0, 0}, /* */
+
+extern struct wl_pwr_cfg rtl8188E_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS+RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_card_disable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_card_enable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS+RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS+RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS+RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS+RTL8188E_TRANS_END_STEPS];
+
+#endif /* __HAL8188EPWRSEQ_H__ */
diff --git a/drivers/staging/r8188eu/include/Hal8188ERateAdaptive.h b/drivers/staging/r8188eu/include/Hal8188ERateAdaptive.h
new file mode 100644
index 000000000000..d5ced507a648
--- /dev/null
+++ b/drivers/staging/r8188eu/include/Hal8188ERateAdaptive.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright (c) 2011 Realtek Semiconductor Corp. */
+
+#ifndef __INC_RA_H
+#define __INC_RA_H
+/* Module Name: RateAdaptive.h
+ * Abstract: Prototype of RA and related data structure.
+ */
+
+#include <linux/bitfield.h>
+
+/* Rate adaptive define */
+#define PERENTRY 23
+#define RETRYSIZE 5
+#define RATESIZE 28
+#define TX_RPT2_ITEM_SIZE 8
+
+/* TX report 2 format in Rx desc */
+#define GET_TX_RPT2_DESC_PKT_LEN_88E(__rxstatusdesc) \
+ le32_get_bits(*(__le32 *)__rxstatusdesc, GENMASK(8, 0))
+#define GET_TX_RPT2_DESC_MACID_VALID_1_88E(__rxstatusdesc) \
+ le32_to_cpu((*(__le32 *)(__rxstatusdesc + 16))
+#define GET_TX_RPT2_DESC_MACID_VALID_2_88E(__rxstatusdesc) \
+ le32_to_cpu((*(__le32 *)(__rxstatusdesc + 20))
+
+#define GET_TX_REPORT_TYPE1_RERTY_0(__paddr) \
+ le16_get_bits(*(__le16 *)__paddr, GENMASK(15, 0))
+#define GET_TX_REPORT_TYPE1_RERTY_1(__paddr) \
+ LE_BITS_TO_1BYTE(__paddr + 2, 0, 8)
+#define GET_TX_REPORT_TYPE1_RERTY_2(__paddr) \
+ LE_BITS_TO_1BYTE(__paddr + 3, 0, 8)
+#define GET_TX_REPORT_TYPE1_RERTY_3(__paddr) \
+ LE_BITS_TO_1BYTE(__paddr + 4, 0, 8)
+#define GET_TX_REPORT_TYPE1_RERTY_4(__paddr) \
+ LE_BITS_TO_1BYTE(__paddr + 5, 0, 8)
+#define GET_TX_REPORT_TYPE1_DROP_0(__paddr) \
+ LE_BITS_TO_1BYTE(__paddr + 6, 0, 8)
+/* End rate adaptive define */
+
+void ODM_RASupport_Init(struct odm_dm_struct *dm_odm);
+
+int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm);
+
+int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 MacID);
+
+u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
+
+u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
+
+u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
+void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 MacID,
+ u8 RateID, u32 RateMask,
+ u8 SGIEnable);
+
+void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid,
+ u8 rssi);
+
+void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm,
+ u8 *txrpt_buf, u16 txrpt_len,
+ u32 validentry0, u32 validentry1);
+
+void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/HalHWImg8188E_BB.h b/drivers/staging/r8188eu/include/HalHWImg8188E_BB.h
new file mode 100644
index 000000000000..8270fdbc2844
--- /dev/null
+++ b/drivers/staging/r8188eu/include/HalHWImg8188E_BB.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __INC_BB_8188E_HW_IMG_H
+#define __INC_BB_8188E_HW_IMG_H
+
+/* static bool CheckCondition(const u32 Condition, const u32 Hex); */
+
+/******************************************************************************
+* AGC_TAB_1T.TXT
+******************************************************************************/
+
+enum HAL_STATUS ODM_ReadAndConfig_AGC_TAB_1T_8188E(struct odm_dm_struct *odm);
+
+/******************************************************************************
+* PHY_REG_1T.TXT
+******************************************************************************/
+
+enum HAL_STATUS ODM_ReadAndConfig_PHY_REG_1T_8188E(struct odm_dm_struct *odm);
+
+/******************************************************************************
+* PHY_REG_PG.TXT
+******************************************************************************/
+
+void ODM_ReadAndConfig_PHY_REG_PG_8188E(struct odm_dm_struct *dm_odm);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/HalHWImg8188E_FW.h b/drivers/staging/r8188eu/include/HalHWImg8188E_FW.h
new file mode 100644
index 000000000000..5ddcd283097b
--- /dev/null
+++ b/drivers/staging/r8188eu/include/HalHWImg8188E_FW.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __INC_FW_8188E_HW_IMG_H
+#define __INC_FW_8188E_HW_IMG_H
+
+/******************************************************************************
+* FW_AP.TXT
+******************************************************************************/
+/******************************************************************************
+* FW_WoWLAN.TXT
+******************************************************************************/
+#define ArrayLength_8188E_FW_WoWLAN 15764
+extern const u8 Array_8188E_FW_WoWLAN[ArrayLength_8188E_FW_WoWLAN];
+
+#endif
diff --git a/drivers/staging/r8188eu/include/HalHWImg8188E_MAC.h b/drivers/staging/r8188eu/include/HalHWImg8188E_MAC.h
new file mode 100644
index 000000000000..391c1754b0b6
--- /dev/null
+++ b/drivers/staging/r8188eu/include/HalHWImg8188E_MAC.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __INC_MAC_8188E_HW_IMG_H
+#define __INC_MAC_8188E_HW_IMG_H
+
+/******************************************************************************
+* MAC_REG.TXT
+******************************************************************************/
+
+enum HAL_STATUS ODM_ReadAndConfig_MAC_REG_8188E(struct odm_dm_struct *pDM_Odm);
+
+#endif /* end of HWIMG_SUPPORT */
diff --git a/drivers/staging/r8188eu/include/HalHWImg8188E_RF.h b/drivers/staging/r8188eu/include/HalHWImg8188E_RF.h
new file mode 100644
index 000000000000..0c67c3df20b9
--- /dev/null
+++ b/drivers/staging/r8188eu/include/HalHWImg8188E_RF.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __INC_RF_8188E_HW_IMG_H
+#define __INC_RF_8188E_HW_IMG_H
+
+/******************************************************************************
+ * RadioA_1T.TXT
+ ******************************************************************************/
+
+enum HAL_STATUS ODM_ReadAndConfig_RadioA_1T_8188E(struct odm_dm_struct *odm);
+
+#endif /* end of HWIMG_SUPPORT */
diff --git a/drivers/staging/r8188eu/include/HalPhyRf_8188e.h b/drivers/staging/r8188eu/include/HalPhyRf_8188e.h
new file mode 100644
index 000000000000..d4a27662309f
--- /dev/null
+++ b/drivers/staging/r8188eu/include/HalPhyRf_8188e.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __HAL_PHY_RF_8188E_H__
+#define __HAL_PHY_RF_8188E_H__
+
+/*--------------------------Define Parameters-------------------------------*/
+#define IQK_DELAY_TIME_88E 10 /* ms */
+#define index_mapping_NUM_88E 15
+#define AVG_THERMAL_NUM_88E 4
+
+void ODM_TxPwrTrackAdjust88E(struct odm_dm_struct *pDM_Odm,
+ u8 Type, /* 0 = OFDM, 1 = CCK */
+ u8 *pDirection,/* 1 = +(incr) 2 = -(decr) */
+ u32 *pOutWriteVal); /* Tx tracking CCK/OFDM BB
+ * swing index adjust */
+
+void odm_TXPowerTrackingCallback_ThermalMeter_8188E(struct adapter *Adapter);
+
+/* 1 7. IQK */
+
+void PHY_IQCalibrate_8188E(struct adapter *Adapter, bool ReCovery);
+
+/* LC calibrate */
+void PHY_LCCalibrate_8188E(struct adapter *pAdapter);
+
+/* AP calibrate */
+void PHY_DigitalPredistortion_8188E(struct adapter *pAdapter);
+
+void _PHY_SaveADDARegisters(struct adapter *pAdapter, u32 *ADDAReg,
+ u32 *ADDABackup, u32 RegisterNum);
+
+void _PHY_PathADDAOn(struct adapter *pAdapter, u32 *ADDAReg,
+ bool isPathAOn, bool is2T);
+
+void _PHY_MACSettingCalibration(struct adapter *pAdapter, u32 *MACReg,
+ u32 *MACBackup);
+
+void _PHY_PathAStandBy(struct adapter *pAdapter);
+
+#endif /* #ifndef __HAL_PHY_RF_8188E_H__ */
diff --git a/drivers/staging/r8188eu/include/HalPwrSeqCmd.h b/drivers/staging/r8188eu/include/HalPwrSeqCmd.h
new file mode 100644
index 000000000000..fe7ac910beb8
--- /dev/null
+++ b/drivers/staging/r8188eu/include/HalPwrSeqCmd.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __HALPWRSEQCMD_H__
+#define __HALPWRSEQCMD_H__
+
+#include "drv_types.h"
+
+/*---------------------------------------------*/
+/* 3 The value of cmd: 4 bits */
+/*---------------------------------------------*/
+#define PWR_CMD_READ 0x00
+ /* offset: the read register offset */
+ /* msk: the mask of the read value */
+ /* value: N/A, left by 0 */
+ /* note: dirver shall implement this function by read & msk */
+
+#define PWR_CMD_WRITE 0x01
+ /* offset: the read register offset */
+ /* msk: the mask of the write bits */
+ /* value: write value */
+ /* note: driver shall implement this cmd by read & msk after write */
+
+#define PWR_CMD_POLLING 0x02
+ /* offset: the read register offset */
+ /* msk: the mask of the polled value */
+ /* value: the value to be polled, masked by the msd field. */
+ /* note: driver shall implement this cmd by */
+ /* do{ */
+ /* if ( (Read(offset) & msk) == (value & msk) ) */
+ /* break; */
+ /* } while (not timeout); */
+
+#define PWR_CMD_DELAY 0x03
+ /* offset: the value to delay */
+ /* msk: N/A */
+ /* value: the unit of delay, 0: us, 1: ms */
+
+#define PWR_CMD_END 0x04
+ /* offset: N/A */
+ /* msk: N/A */
+ /* value: N/A */
+
+/*---------------------------------------------*/
+/* 3 The value of base: 4 bits */
+/*---------------------------------------------*/
+ /* define the base address of each block */
+#define PWR_BASEADDR_MAC 0x00
+#define PWR_BASEADDR_USB 0x01
+#define PWR_BASEADDR_PCIE 0x02
+#define PWR_BASEADDR_SDIO 0x03
+
+/*---------------------------------------------*/
+/* 3 The value of interface_msk: 4 bits */
+/*---------------------------------------------*/
+#define PWR_INTF_SDIO_MSK BIT(0)
+#define PWR_INTF_USB_MSK BIT(1)
+#define PWR_INTF_PCI_MSK BIT(2)
+#define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
+
+/*---------------------------------------------*/
+/* 3 The value of fab_msk: 4 bits */
+/*---------------------------------------------*/
+#define PWR_FAB_TSMC_MSK BIT(0)
+#define PWR_FAB_UMC_MSK BIT(1)
+#define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
+
+/*---------------------------------------------*/
+/* 3 The value of cut_msk: 8 bits */
+/*---------------------------------------------*/
+#define PWR_CUT_TESTCHIP_MSK BIT(0)
+#define PWR_CUT_A_MSK BIT(1)
+#define PWR_CUT_B_MSK BIT(2)
+#define PWR_CUT_C_MSK BIT(3)
+#define PWR_CUT_D_MSK BIT(4)
+#define PWR_CUT_E_MSK BIT(5)
+#define PWR_CUT_F_MSK BIT(6)
+#define PWR_CUT_G_MSK BIT(7)
+#define PWR_CUT_ALL_MSK 0xFF
+
+enum pwrseq_cmd_delat_unit {
+ PWRSEQ_DELAY_US,
+ PWRSEQ_DELAY_MS,
+};
+
+struct wl_pwr_cfg {
+ u16 offset;
+ u8 cut_msk;
+ u8 fab_msk:4;
+ u8 interface_msk:4;
+ u8 base:4;
+ u8 cmd:4;
+ u8 msk;
+ u8 value;
+};
+
+#define GET_PWR_CFG_OFFSET(__PWR_CMD) __PWR_CMD.offset
+#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) __PWR_CMD.cut_msk
+#define GET_PWR_CFG_FAB_MASK(__PWR_CMD) __PWR_CMD.fab_msk
+#define GET_PWR_CFG_INTF_MASK(__PWR_CMD) __PWR_CMD.interface_msk
+#define GET_PWR_CFG_BASE(__PWR_CMD) __PWR_CMD.base
+#define GET_PWR_CFG_CMD(__PWR_CMD) __PWR_CMD.cmd
+#define GET_PWR_CFG_MASK(__PWR_CMD) __PWR_CMD.msk
+#define GET_PWR_CFG_VALUE(__PWR_CMD) __PWR_CMD.value
+
+/* Prototype of protected function. */
+u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 CutVersion, u8 FabVersion,
+ u8 InterfaceType, struct wl_pwr_cfg PwrCfgCmd[]);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/HalVerDef.h b/drivers/staging/r8188eu/include/HalVerDef.h
new file mode 100644
index 000000000000..a0f5bf52e75a
--- /dev/null
+++ b/drivers/staging/r8188eu/include/HalVerDef.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+#ifndef __HAL_VERSION_DEF_H__
+#define __HAL_VERSION_DEF_H__
+
+enum HAL_IC_TYPE {
+ CHIP_8192S = 0,
+ CHIP_8188C = 1,
+ CHIP_8192C = 2,
+ CHIP_8192D = 3,
+ CHIP_8723A = 4,
+ CHIP_8188E = 5,
+ CHIP_8881A = 6,
+ CHIP_8812A = 7,
+ CHIP_8821A = 8,
+ CHIP_8723B = 9,
+ CHIP_8192E = 10,
+};
+
+enum HAL_CHIP_TYPE {
+ TEST_CHIP = 0,
+ NORMAL_CHIP = 1,
+ FPGA = 2,
+};
+
+enum HAL_CUT_VERSION {
+ A_CUT_VERSION = 0,
+ B_CUT_VERSION = 1,
+ C_CUT_VERSION = 2,
+ D_CUT_VERSION = 3,
+ E_CUT_VERSION = 4,
+ F_CUT_VERSION = 5,
+ G_CUT_VERSION = 6,
+};
+
+enum HAL_VENDOR {
+ CHIP_VENDOR_TSMC = 0,
+ CHIP_VENDOR_UMC = 1,
+};
+
+enum HAL_RF_TYPE {
+ RF_TYPE_1T1R = 0,
+ RF_TYPE_1T2R = 1,
+ RF_TYPE_2T2R = 2,
+ RF_TYPE_2T3R = 3,
+ RF_TYPE_2T4R = 4,
+ RF_TYPE_3T3R = 5,
+ RF_TYPE_3T4R = 6,
+ RF_TYPE_4T4R = 7,
+};
+
+struct HAL_VERSION {
+ enum HAL_IC_TYPE ICType;
+ enum HAL_CHIP_TYPE ChipType;
+ enum HAL_CUT_VERSION CUTVersion;
+ enum HAL_VENDOR VendorType;
+ enum HAL_RF_TYPE RFType;
+ u8 ROMVer;
+};
+
+/* Get element */
+#define GET_CVID_IC_TYPE(version) (((version).ICType))
+#define GET_CVID_CHIP_TYPE(version) (((version).ChipType))
+#define GET_CVID_RF_TYPE(version) (((version).RFType))
+#define GET_CVID_MANUFACTUER(version) (((version).VendorType))
+#define GET_CVID_CUT_VERSION(version) (((version).CUTVersion))
+#define GET_CVID_ROM_VERSION(version) (((version).ROMVer) & ROM_VERSION_MASK)
+
+/* Common Macro. -- */
+/* HAL_VERSION VersionID */
+
+/* HAL_IC_TYPE_E */
+#define IS_81XXC(version) \
+ (((GET_CVID_IC_TYPE(version) == CHIP_8192C) || \
+ (GET_CVID_IC_TYPE(version) == CHIP_8188C)) ? true : false)
+#define IS_8723_SERIES(version) \
+ ((GET_CVID_IC_TYPE(version) == CHIP_8723A) ? true : false)
+#define IS_92D(version) \
+ ((GET_CVID_IC_TYPE(version) == CHIP_8192D) ? true : false)
+#define IS_8188E(version) \
+ ((GET_CVID_IC_TYPE(version) == CHIP_8188E) ? true : false)
+
+/* HAL_CHIP_TYPE_E */
+#define IS_TEST_CHIP(version) \
+ ((GET_CVID_CHIP_TYPE(version) == TEST_CHIP) ? true : false)
+#define IS_NORMAL_CHIP(version) \
+ ((GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) ? true : false)
+
+/* HAL_CUT_VERSION_E */
+#define IS_A_CUT(version) \
+ ((GET_CVID_CUT_VERSION(version) == A_CUT_VERSION) ? true : false)
+#define IS_B_CUT(version) \
+ ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true : false)
+#define IS_C_CUT(version) \
+ ((GET_CVID_CUT_VERSION(version) == C_CUT_VERSION) ? true : false)
+#define IS_D_CUT(version) \
+ ((GET_CVID_CUT_VERSION(version) == D_CUT_VERSION) ? true : false)
+#define IS_E_CUT(version) \
+ ((GET_CVID_CUT_VERSION(version) == E_CUT_VERSION) ? true : false)
+
+/* HAL_VENDOR_E */
+#define IS_CHIP_VENDOR_TSMC(version) \
+ ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_TSMC) ? true : false)
+#define IS_CHIP_VENDOR_UMC(version) \
+ ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false)
+
+/* HAL_RF_TYPE_E */
+#define IS_1T1R(version) \
+ ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T1R) ? true : false)
+#define IS_1T2R(version) \
+ ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false)
+#define IS_2T2R(version) \
+ ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false)
+
+/* Chip version Macro. -- */
+#define IS_81XXC_TEST_CHIP(version) \
+ ((IS_81XXC(version) && (!IS_NORMAL_CHIP(version))) ? true : false)
+
+#define IS_92C_SERIAL(version) \
+ ((IS_81XXC(version) && IS_2T2R(version)) ? true : false)
+#define IS_81xxC_VENDOR_UMC_A_CUT(version) \
+ (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
+ (IS_A_CUT(version) ? true : false) : false) : false)
+#define IS_81xxC_VENDOR_UMC_B_CUT(version) \
+ (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
+ (IS_B_CUT(version) ? true : false) : false) : false)
+#define IS_81xxC_VENDOR_UMC_C_CUT(version) \
+ (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
+ (IS_C_CUT(version) ? true : false) : false) : false)
+
+#define IS_NORMAL_CHIP92D(version) \
+ ((IS_92D(version)) ? \
+ ((GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) ? true : false) : false)
+
+#define IS_92D_SINGLEPHY(version) \
+ ((IS_92D(version)) ? (IS_2T2R(version) ? true : false) : false)
+#define IS_92D_C_CUT(version) \
+ ((IS_92D(version)) ? (IS_C_CUT(version) ? true : false) : false)
+#define IS_92D_D_CUT(version) \
+ ((IS_92D(version)) ? (IS_D_CUT(version) ? true : false) : false)
+#define IS_92D_E_CUT(version) \
+ ((IS_92D(version)) ? (IS_E_CUT(version) ? true : false) : false)
+
+#define IS_8723A_A_CUT(version) \
+ ((IS_8723_SERIES(version)) ? (IS_A_CUT(version) ? true : false) : false)
+#define IS_8723A_B_CUT(version) \
+ ((IS_8723_SERIES(version)) ? (IS_B_CUT(version) ? true : false) : false)
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/basic_types.h b/drivers/staging/r8188eu/include/basic_types.h
index b69b45d95402..d82b2171d584 100644
--- a/drivers/staging/rtl8188eu/include/basic_types.h
+++ b/drivers/staging/r8188eu/include/basic_types.h
@@ -1,26 +1,32 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __BASIC_TYPES_H__
#define __BASIC_TYPES_H__
+#define SUCCESS 0
+#define FAIL (-1)
+
#include <linux/types.h>
#define NDIS_OID uint
+typedef void (*proc_t)(void *);
+
+#define FIELD_OFFSET(s, field) ((ssize_t)&((s *)(0))->field)
+
+#define MEM_ALIGNMENT_OFFSET (sizeof(size_t))
+#define MEM_ALIGNMENT_PADDING (sizeof(size_t) - 1)
+
/* port from fw */
/* TODO: Macros Below are Sync from SD7-Driver. It is necessary
- * to check correctness
- */
+ * to check correctness */
/*
* Call endian free function when
* 1. Read/write packet content.
* 2. Before write integer to IO.
* 3. After read integer from IO.
- */
+*/
/* Convert little data endian to host ordering */
#define EF1BYTE(_val) \
@@ -30,6 +36,31 @@
#define EF4BYTE(_val) \
(le32_to_cpu(_val))
+/* Read data from memory */
+#define READEF1BYTE(_ptr) \
+ EF1BYTE(*((u8 *)(_ptr)))
+/* Read le16 data from memory and convert to host ordering */
+#define READEF2BYTE(_ptr) \
+ EF2BYTE(*(_ptr))
+#define READEF4BYTE(_ptr) \
+ EF4BYTE(*(_ptr))
+
+/* Write data to memory */
+#define WRITEEF1BYTE(_ptr, _val) \
+ do { \
+ (*((u8 *)(_ptr))) = EF1BYTE(_val) \
+ } while (0)
+/* Write le data to memory in host ordering */
+#define WRITEEF2BYTE(_ptr, _val) \
+ do { \
+ (*((u16 *)(_ptr))) = EF2BYTE(_val) \
+ } while (0)
+
+#define WRITEEF4BYTE(_ptr, _val) \
+ do { \
+ (*((u32 *)(_ptr))) = EF2BYTE(_val) \
+ } while (0)
+
/* Create a bit mask
* Examples:
* BIT_LEN_MASK_32(0) => 0x00000000
@@ -67,10 +98,9 @@
#define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \
(EF1BYTE(*((u8 *)(__pstart))))
-/* Description:
- * Translate subfield (continuous bits in little-endian) of 4-byte
- * value to host byte ordering.
- */
+/*Description:
+Translate subfield (continuous bits in little-endian) of 4-byte
+value to host byte ordering.*/
#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
( \
(LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \
@@ -87,48 +117,7 @@
BIT_LEN_MASK_8(__bitlen) \
)
-/* Description:
- * Mask subfield (continuous bits in little-endian) of 4-byte value
- * and return the result in 4-byte value in host byte ordering.
- */
-#define LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
- ( \
- LE_P4BYTE_TO_HOST_4BYTE(__pstart) & \
- (~BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen)) \
- )
-#define LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) \
- ( \
- LE_P2BYTE_TO_HOST_2BYTE(__pstart) & \
- (~BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen)) \
- )
-#define LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) \
- ( \
- LE_P1BYTE_TO_HOST_1BYTE(__pstart) & \
- (~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen)) \
- )
-
-/* Description:
- * Set subfield of little-endian 4-byte value to specified value.
- */
-#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \
- *((u32 *)(__pstart)) = \
- ( \
- LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \
- ((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \
- )
-
-#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \
- *((u16 *)(__pstart)) = \
- ( \
- LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \
- ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \
- );
-
-#define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \
- *((u8 *)(__pstart)) = EF1BYTE \
- ( \
- LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) | \
- ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \
- )
+#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \
+ (__value) : (((__value + __aligment - 1) / __aligment) * __aligment))
#endif /* __BASIC_TYPES_H__ */
diff --git a/drivers/staging/r8188eu/include/drv_types.h b/drivers/staging/r8188eu/include/drv_types.h
new file mode 100644
index 000000000000..04f4224c11de
--- /dev/null
+++ b/drivers/staging/r8188eu/include/drv_types.h
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+/*-----------------------------------------------------------------------------
+
+ For type defines and data structure defines
+
+------------------------------------------------------------------------------*/
+
+#ifndef __DRV_TYPES_H__
+#define __DRV_TYPES_H__
+
+#define DRV_NAME "r8188eu"
+#define CONFIG_88EU_AP_MODE 1
+#define CONFIG_88EU_P2P 1
+
+#include "osdep_service.h"
+#include "wlan_bssdef.h"
+#include "rtw_ht.h"
+#include "rtw_cmd.h"
+#include "rtw_xmit.h"
+#include "rtw_recv.h"
+#include "hal_intf.h"
+#include "hal_com.h"
+#include "rtw_security.h"
+#include "rtw_pwrctrl.h"
+#include "rtw_io.h"
+#include "rtw_eeprom.h"
+#include "sta_info.h"
+#include "rtw_mlme.h"
+#include "rtw_debug.h"
+#include "rtw_rf.h"
+#include "rtw_event.h"
+#include "rtw_led.h"
+#include "rtw_mlme_ext.h"
+#include "rtw_p2p.h"
+#include "rtw_ap.h"
+#include "rtw_mp.h"
+#include "rtw_br_ext.h"
+
+#define DRIVERVERSION "v4.1.4_6773.20130222"
+
+#define SPEC_DEV_ID_NONE BIT(0)
+#define SPEC_DEV_ID_DISABLE_HT BIT(1)
+#define SPEC_DEV_ID_ENABLE_PS BIT(2)
+#define SPEC_DEV_ID_RF_CONFIG_1T1R BIT(3)
+#define SPEC_DEV_ID_RF_CONFIG_2T2R BIT(4)
+#define SPEC_DEV_ID_ASSIGN_IFNAME BIT(5)
+
+struct specific_device_id {
+ u32 flags;
+ u16 idVendor;
+ u16 idProduct;
+};
+
+struct registry_priv {
+ u8 chip_version;
+ u8 rfintfs;
+ u8 lbkmode;
+ u8 hci;
+ struct ndis_802_11_ssid ssid;
+ u8 network_mode; /* infra, ad-hoc, auto */
+ u8 channel;/* ad-hoc support requirement */
+ u8 wireless_mode;/* A, B, G, auto */
+ u8 scan_mode;/* active, passive */
+ u8 radio_enable;
+ u8 preamble;/* long, short, auto */
+ u8 vrtl_carrier_sense;/* Enable, Disable, Auto */
+ u8 vcs_type;/* RTS/CTS, CTS-to-self */
+ u16 rts_thresh;
+ u16 frag_thresh;
+ u8 adhoc_tx_pwr;
+ u8 soft_ap;
+ u8 power_mgnt;
+ u8 ips_mode;
+ u8 smart_ps;
+ u8 long_retry_lmt;
+ u8 short_retry_lmt;
+ u16 busy_thresh;
+ u8 ack_policy;
+ u8 mp_mode;
+ u8 software_encrypt;
+ u8 software_decrypt;
+ u8 acm_method;
+ /* UAPSD */
+ u8 wmm_enable;
+ u8 uapsd_enable;
+ u8 uapsd_max_sp;
+ u8 uapsd_acbk_en;
+ u8 uapsd_acbe_en;
+ u8 uapsd_acvi_en;
+ u8 uapsd_acvo_en;
+
+ u8 led_enable;
+
+ struct wlan_bssid_ex dev_network;
+
+ u8 ht_enable;
+ u8 cbw40_enable;
+ u8 ampdu_enable;/* for tx */
+ u8 rx_stbc;
+ u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */
+ u8 lowrate_two_xmit;
+
+ u8 rf_config;
+ u8 low_power;
+
+ u8 wifi_spec;/* !turbo_mode */
+
+ u8 channel_plan;
+ bool bAcceptAddbaReq;
+
+ u8 antdiv_cfg;
+ u8 antdiv_type;
+
+ u8 usbss_enable;/* 0:disable,1:enable */
+ u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */
+ u8 hwpwrp_detect;/* 0:disable,1:enable */
+
+ u8 hw_wps_pbc;/* 0:disable,1:enable */
+
+ u8 max_roaming_times; /* the max number driver will try */
+
+ u8 fw_iol; /* enable iol without other concern */
+
+ u8 enable80211d;
+
+ u8 ifname[16];
+ u8 if2name[16];
+
+ u8 notch_filter;
+};
+
+/* For registry parameters */
+#define RGTRY_OFT(field) ((u32)FIELD_OFFSET(struct registry_priv, field))
+#define RGTRY_SZ(field) sizeof(((struct registry_priv *)0)->field)
+#define BSSID_OFT(field) ((u32)FIELD_OFFSET(struct wlan_bssid_ex, field))
+#define BSSID_SZ(field) sizeof(((struct wlan_bssid_ex *)0)->field)
+
+#define MAX_CONTINUAL_URB_ERR 4
+
+struct rt_firmware {
+ u8 *szFwBuffer;
+ u32 ulFwLength;
+};
+
+struct dvobj_priv {
+ struct adapter *if1;
+ struct adapter *if2;
+
+ /* For 92D, DMDP have 2 interface. */
+ u8 InterfaceNumber;
+ u8 NumInterfaces;
+
+ /* In /Out Pipe information */
+ int RtInPipe[2];
+ int RtOutPipe[3];
+ u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */
+
+ u8 irq_alloc;
+
+ struct rt_firmware firmware;
+
+/*-------- below is for USB INTERFACE --------*/
+
+ u8 nr_endpoint;
+ u8 ishighspeed;
+ u8 RtNumInPipes;
+ u8 RtNumOutPipes;
+ int ep_num[5]; /* endpoint number */
+ int RegUsbSS;
+ struct semaphore usb_suspend_sema;
+ struct mutex usb_vendor_req_mutex;
+
+ u8 *usb_alloc_vendor_req_buf;
+ u8 *usb_vendor_req_buf;
+
+ struct usb_interface *pusbintf;
+ struct usb_device *pusbdev;
+
+ atomic_t continual_urb_error;
+ u8 signal_strength;
+};
+
+static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj)
+{
+ /* todo: get interface type from dvobj and the return
+ * the dev accordingly */
+ return &dvobj->pusbintf->dev;
+};
+
+enum _IFACE_TYPE {
+ IFACE_PORT0, /* mapping to port0 for C/D series chips */
+ IFACE_PORT1, /* mapping to port1 for C/D series chip */
+ MAX_IFACE_PORT,
+};
+
+enum _ADAPTER_TYPE {
+ PRIMARY_ADAPTER,
+ SECONDARY_ADAPTER,
+ MAX_ADAPTER,
+};
+
+enum driver_state {
+ DRIVER_NORMAL = 0,
+ DRIVER_DISAPPEAR = 1,
+ DRIVER_REPLACE_DONGLE = 2,
+};
+
+struct adapter {
+ int DriverState;/* for disable driver using module, use dongle toi
+ * replace module. */
+ int pid[3];/* process id from UI, 0:wps, 1:hostapd, 2:dhcpcd */
+ int bDongle;/* build-in module or external dongle */
+ u16 chip_type;
+ u16 HardwareType;
+ u16 interface_type;/* USB,SDIO,SPI,PCI */
+
+ struct dvobj_priv *dvobj;
+ struct mlme_priv mlmepriv;
+ struct mlme_ext_priv mlmeextpriv;
+ struct cmd_priv cmdpriv;
+ struct evt_priv evtpriv;
+ struct io_priv iopriv;
+ struct xmit_priv xmitpriv;
+ struct recv_priv recvpriv;
+ struct sta_priv stapriv;
+ struct security_priv securitypriv;
+ struct registry_priv registrypriv;
+ struct pwrctrl_priv pwrctrlpriv;
+ struct eeprom_priv eeprompriv;
+ struct led_priv ledpriv;
+ struct mp_priv mppriv;
+
+#ifdef CONFIG_88EU_AP_MODE
+ struct hostapd_priv *phostapdpriv;
+#endif
+
+ struct wifidirect_info wdinfo;
+
+ void *HalData;
+ u32 hal_data_sz;
+ struct hal_ops HalFunc;
+
+ s32 bDriverStopped;
+ s32 bSurpriseRemoved;
+ s32 bCardDisableWOHSM;
+
+ u32 IsrContent;
+ u32 ImrContent;
+
+ u8 EepromAddressSize;
+ u8 hw_init_completed;
+ u8 bDriverIsGoingToUnload;
+ u8 init_adpt_in_progress;
+ u8 bHaltInProgress;
+ s8 signal_strength;
+
+ void *cmdThread;
+ void *evtThread;
+ void *xmitThread;
+ void *recvThread;
+ void (*intf_start)(struct adapter *adapter);
+ void (*intf_stop)(struct adapter *adapter);
+ struct net_device *pnetdev;
+
+ /* used by rtw_rereg_nd_name related function */
+ struct rereg_nd_name_data {
+ struct net_device *old_pnetdev;
+ char old_ifname[IFNAMSIZ];
+ u8 old_ips_mode;
+ u8 old_bRegUseLed;
+ } rereg_nd_name_priv;
+
+ int bup;
+ struct net_device_stats stats;
+ struct iw_statistics iwstats;
+ struct proc_dir_entry *dir_dev;/* for proc directory */
+
+ int net_closed;
+ u8 bFWReady;
+ u8 bBTFWReady;
+ u8 bReadPortCancel;
+ u8 bWritePortCancel;
+ u8 bRxRSSIDisplay;
+ /* The driver will show up the desired channel number
+ * when this flag is 1. */
+ u8 bNotifyChannelChange;
+#ifdef CONFIG_88EU_P2P
+ /* The driver will show the current P2P status when the
+ * upper application reads it. */
+ u8 bShowGetP2PState;
+#endif
+ struct adapter *pbuddy_adapter;
+
+ struct mutex *hw_init_mutex;
+
+ spinlock_t br_ext_lock;
+ struct nat25_network_db_entry *nethash[NAT25_HASH_SIZE];
+ int pppoe_connection_in_progress;
+ unsigned char pppoe_addr[MACADDRLEN];
+ unsigned char scdb_mac[MACADDRLEN];
+ unsigned char scdb_ip[4];
+ struct nat25_network_db_entry *scdb_entry;
+ unsigned char br_mac[MACADDRLEN];
+ unsigned char br_ip[4];
+ struct br_ext_info ethBrExtInfo;
+
+ u8 fix_rate;
+
+ unsigned char in_cta_test;
+};
+
+#define adapter_to_dvobj(adapter) (adapter->dvobj)
+
+int rtw_handle_dualmac(struct adapter *adapter, bool init);
+
+static inline u8 *myid(struct eeprom_priv *peepriv)
+{
+ return peepriv->mac_addr;
+}
+
+#endif /* __DRV_TYPES_H__ */
diff --git a/drivers/staging/rtl8188eu/include/hal_com.h b/drivers/staging/r8188eu/include/hal_com.h
index c2019772bef0..95167f0b327f 100644
--- a/drivers/staging/rtl8188eu/include/hal_com.h
+++ b/drivers/staging/r8188eu/include/hal_com.h
@@ -1,9 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __HAL_COMMON_H__
#define __HAL_COMMON_H__
@@ -81,7 +78,7 @@
#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \
RATR_24M | RATR_36M | RATR_48M | RATR_54M)
#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \
- RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | RATR_MCS6 | \
+ RATR_MCS3 | RATR_MCS4 | RATR_MCS5|RATR_MCS6 | \
RATR_MCS7)
#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \
RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \
@@ -138,13 +135,22 @@
void dump_chip_info(struct HAL_VERSION ChipVersion);
/* return the final channel plan decision */
-u8 hal_com_get_channel_plan(u8 hw_channel_plan, u8 sw_channel_plan,
- u8 def_channel_plan, bool load_fail);
+u8 hal_com_get_channel_plan(struct adapter *padapter,
+ u8 hw_channel_plan,
+ u8 sw_channel_plan,
+ u8 def_channel_plan,
+ bool AutoLoadFail
+);
u8 MRateToHwRate(u8 rate);
-void hal_set_brate_cfg(u8 *brates, u16 *rate_cfg);
+void HalSetBrateCfg(struct adapter *Adapter, u8 *mBratesOS, u16 *pBrateCfg);
+
+bool Hal_MappingOutPipe(struct adapter *pAdapter, u8 NumOutPipe);
+
+void hal_init_macaddr(struct adapter *adapter);
-bool hal_mapping_out_pipe(struct adapter *adapter, u8 numoutpipe);
+void c2h_evt_clear(struct adapter *adapter);
+s32 c2h_evt_read(struct adapter *adapter, u8 *buf);
#endif /* __HAL_COMMON_H__ */
diff --git a/drivers/staging/r8188eu/include/hal_intf.h b/drivers/staging/r8188eu/include/hal_intf.h
new file mode 100644
index 000000000000..fa252540e596
--- /dev/null
+++ b/drivers/staging/r8188eu/include/hal_intf.h
@@ -0,0 +1,411 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#ifndef __HAL_INTF_H__
+#define __HAL_INTF_H__
+
+#include "osdep_service.h"
+#include "drv_types.h"
+#include "Hal8188EPhyCfg.h"
+
+enum RTL871X_HCI_TYPE {
+ RTW_PCIE = BIT(0),
+ RTW_USB = BIT(1),
+ RTW_SDIO = BIT(2),
+ RTW_GSPI = BIT(3),
+};
+
+enum _CHIP_TYPE {
+ NULL_CHIP_TYPE,
+ RTL8712_8188S_8191S_8192S,
+ RTL8188C_8192C,
+ RTL8192D,
+ RTL8723A,
+ RTL8188E,
+ MAX_CHIP_TYPE
+};
+
+enum hw_variables {
+ HW_VAR_MEDIA_STATUS,
+ HW_VAR_MEDIA_STATUS1,
+ HW_VAR_SET_OPMODE,
+ HW_VAR_MAC_ADDR,
+ HW_VAR_BSSID,
+ HW_VAR_INIT_RTS_RATE,
+ HW_VAR_BASIC_RATE,
+ HW_VAR_TXPAUSE,
+ HW_VAR_BCN_FUNC,
+ HW_VAR_CORRECT_TSF,
+ HW_VAR_CHECK_BSSID,
+ HW_VAR_MLME_DISCONNECT,
+ HW_VAR_MLME_SITESURVEY,
+ HW_VAR_MLME_JOIN,
+ HW_VAR_BEACON_INTERVAL,
+ HW_VAR_SLOT_TIME,
+ HW_VAR_RESP_SIFS,
+ HW_VAR_ACK_PREAMBLE,
+ HW_VAR_SEC_CFG,
+ HW_VAR_BCN_VALID,
+ HW_VAR_RF_TYPE,
+ HW_VAR_DM_FLAG,
+ HW_VAR_DM_FUNC_OP,
+ HW_VAR_DM_FUNC_SET,
+ HW_VAR_DM_FUNC_CLR,
+ HW_VAR_CAM_EMPTY_ENTRY,
+ HW_VAR_CAM_INVALID_ALL,
+ HW_VAR_CAM_WRITE,
+ HW_VAR_CAM_READ,
+ HW_VAR_AC_PARAM_VO,
+ HW_VAR_AC_PARAM_VI,
+ HW_VAR_AC_PARAM_BE,
+ HW_VAR_AC_PARAM_BK,
+ HW_VAR_ACM_CTRL,
+ HW_VAR_AMPDU_MIN_SPACE,
+ HW_VAR_AMPDU_FACTOR,
+ HW_VAR_RXDMA_AGG_PG_TH,
+ HW_VAR_SET_RPWM,
+ HW_VAR_H2C_FW_PWRMODE,
+ HW_VAR_H2C_FW_JOINBSSRPT,
+ HW_VAR_FWLPS_RF_ON,
+ HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
+ HW_VAR_TDLS_WRCR,
+ HW_VAR_TDLS_INIT_CH_SEN,
+ HW_VAR_TDLS_RS_RCR,
+ HW_VAR_TDLS_DONE_CH_SEN,
+ HW_VAR_INITIAL_GAIN,
+ HW_VAR_TRIGGER_GPIO_0,
+ HW_VAR_BT_SET_COEXIST,
+ HW_VAR_BT_ISSUE_DELBA,
+ HW_VAR_CURRENT_ANTENNA,
+ HW_VAR_ANTENNA_DIVERSITY_LINK,
+ HW_VAR_ANTENNA_DIVERSITY_SELECT,
+ HW_VAR_SWITCH_EPHY_WoWLAN,
+ HW_VAR_EFUSE_USAGE,
+ HW_VAR_EFUSE_BYTES,
+ HW_VAR_EFUSE_BT_USAGE,
+ HW_VAR_EFUSE_BT_BYTES,
+ HW_VAR_FIFO_CLEARN_UP,
+ HW_VAR_CHECK_TXBUF,
+ HW_VAR_APFM_ON_MAC, /* Auto FSM to Turn On, include clock, isolation,
+ * power control for MAC only */
+ /* The valid upper nav range for the HW updating, if the true value is
+ * larger than the upper range, the HW won't update it. */
+ /* Unit in microsecond. 0 means disable this function. */
+ HW_VAR_NAV_UPPER,
+ HW_VAR_RPT_TIMER_SETTING,
+ HW_VAR_TX_RPT_MAX_MACID,
+ HW_VAR_H2C_MEDIA_STATUS_RPT,
+ HW_VAR_CHK_HI_QUEUE_EMPTY,
+};
+
+enum hal_def_variable {
+ HAL_DEF_UNDERCORATEDSMOOTHEDPWDB,
+ HAL_DEF_IS_SUPPORT_ANT_DIV,
+ HAL_DEF_CURRENT_ANTENNA,
+ HAL_DEF_DRVINFO_SZ,
+ HAL_DEF_MAX_RECVBUF_SZ,
+ HAL_DEF_RX_PACKET_OFFSET,
+ HAL_DEF_DBG_DUMP_RXPKT,/* for dbg */
+ HAL_DEF_DBG_DM_FUNC,/* for dbg */
+ HAL_DEF_RA_DECISION_RATE,
+ HAL_DEF_RA_SGI,
+ HAL_DEF_PT_PWR_STATUS,
+ HW_VAR_MAX_RX_AMPDU_FACTOR,
+ HW_DEF_RA_INFO_DUMP,
+ HAL_DEF_DBG_DUMP_TXPKT,
+};
+
+enum hal_odm_variable {
+ HAL_ODM_STA_INFO,
+ HAL_ODM_P2P_STATE,
+ HAL_ODM_WIFI_DISPLAY_STATE,
+};
+
+enum hal_intf_ps_func {
+ HAL_USB_SELECT_SUSPEND,
+ HAL_MAX_ID,
+};
+
+typedef s32 (*c2h_id_filter)(u8 id);
+
+struct hal_ops {
+ u32 (*hal_power_on)(struct adapter *padapter);
+ u32 (*hal_init)(struct adapter *padapter);
+ u32 (*hal_deinit)(struct adapter *padapter);
+
+ void (*free_hal_data)(struct adapter *padapter);
+
+ u32 (*inirp_init)(struct adapter *padapter);
+ u32 (*inirp_deinit)(struct adapter *padapter);
+
+ s32 (*init_xmit_priv)(struct adapter *padapter);
+
+ s32 (*init_recv_priv)(struct adapter *padapter);
+ void (*free_recv_priv)(struct adapter *padapter);
+
+ void (*InitSwLeds)(struct adapter *padapter);
+ void (*DeInitSwLeds)(struct adapter *padapter);
+
+ void (*dm_init)(struct adapter *padapter);
+ void (*dm_deinit)(struct adapter *padapter);
+ void (*read_chip_version)(struct adapter *padapter);
+
+ void (*init_default_value)(struct adapter *padapter);
+
+ void (*intf_chip_configure)(struct adapter *padapter);
+
+ void (*read_adapter_info)(struct adapter *padapter);
+
+ void (*enable_interrupt)(struct adapter *padapter);
+ void (*disable_interrupt)(struct adapter *padapter);
+ s32 (*interrupt_handler)(struct adapter *padapter);
+
+ void (*set_bwmode_handler)(struct adapter *padapter,
+ enum ht_channel_width Bandwidth,
+ u8 Offset);
+ void (*set_channel_handler)(struct adapter *padapter, u8 channel);
+
+ void (*hal_dm_watchdog)(struct adapter *padapter);
+
+ void (*SetHwRegHandler)(struct adapter *padapter, u8 variable,
+ u8 *val);
+ void (*GetHwRegHandler)(struct adapter *padapter, u8 variable,
+ u8 *val);
+
+ u8 (*GetHalDefVarHandler)(struct adapter *padapter,
+ enum hal_def_variable eVariable,
+ void *pValue);
+ u8 (*SetHalDefVarHandler)(struct adapter *padapter,
+ enum hal_def_variable eVariable,
+ void *pValue);
+
+ void (*GetHalODMVarHandler)(struct adapter *padapter,
+ enum hal_odm_variable eVariable,
+ void *pValue1, bool bSet);
+ void (*SetHalODMVarHandler)(struct adapter *padapter,
+ enum hal_odm_variable eVariable,
+ void *pValue1, bool bSet);
+
+ void (*UpdateRAMaskHandler)(struct adapter *padapter,
+ u32 mac_id, u8 rssi_level);
+ void (*SetBeaconRelatedRegistersHandler)(struct adapter *padapter);
+
+ void (*Add_RateATid)(struct adapter *adapter, u32 bitmap, u8 arg,
+ u8 rssi_level);
+ void (*run_thread)(struct adapter *adapter);
+ void (*cancel_thread)(struct adapter *adapter);
+
+ u8 (*AntDivBeforeLinkHandler)(struct adapter *adapter);
+ void (*AntDivCompareHandler)(struct adapter *adapter,
+ struct wlan_bssid_ex *dst,
+ struct wlan_bssid_ex *src);
+ u8 (*interface_ps_func)(struct adapter *padapter,
+ enum hal_intf_ps_func efunc_id, u8 *val);
+
+ s32 (*hal_xmit)(struct adapter *padapter,
+ struct xmit_frame *pxmitframe);
+ s32 (*mgnt_xmit)(struct adapter *padapter,
+ struct xmit_frame *pmgntframe);
+ s32 (*hal_xmitframe_enqueue)(struct adapter *padapter,
+ struct xmit_frame *pxmitframe);
+
+ u32 (*read_bbreg)(struct adapter *padapter, u32 RegAddr,
+ u32 BitMask);
+ void (*write_bbreg)(struct adapter *padapter, u32 RegAddr,
+ u32 BitMask, u32 Data);
+ u32 (*read_rfreg)(struct adapter *padapter,
+ enum rf_radio_path eRFPath, u32 RegAddr,
+ u32 BitMask);
+ void (*write_rfreg)(struct adapter *padapter,
+ enum rf_radio_path eRFPath, u32 RegAddr,
+ u32 BitMask, u32 Data);
+
+ void (*EfusePowerSwitch)(struct adapter *padapter, u8 bWrite,
+ u8 PwrState);
+ void (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset,
+ u16 _size_byte, u8 *pbuf, bool bPseudoTest);
+ void (*EFUSEGetEfuseDefinition)(struct adapter *padapter, u8 efuseType,
+ u8 type, void *pOut, bool bPseudoTest);
+ u16 (*EfuseGetCurrentSize)(struct adapter *padapter, u8 efuseType,
+ bool bPseudoTest);
+ int (*Efuse_PgPacketRead)(struct adapter *adapter, u8 offset,
+ u8 *data, bool bPseudoTest);
+ int (*Efuse_PgPacketWrite)(struct adapter *padapter, u8 offset,
+ u8 word_en, u8 *data, bool bPseudoTest);
+ u8 (*Efuse_WordEnableDataWrite)(struct adapter *padapter,
+ u16 efuse_addr, u8 word_en,
+ u8 *data, bool bPseudoTest);
+ bool (*Efuse_PgPacketWrite_BT)(struct adapter *padapter, u8 offset,
+ u8 word_en, u8 *data, bool test);
+
+ void (*sreset_init_value)(struct adapter *padapter);
+ void (*sreset_reset_value)(struct adapter *padapter);
+ void (*silentreset)(struct adapter *padapter);
+ void (*sreset_xmit_status_check)(struct adapter *padapter);
+ void (*sreset_linked_status_check) (struct adapter *padapter);
+ u8 (*sreset_get_wifi_status)(struct adapter *padapter);
+
+ int (*IOL_exec_cmds_sync)(struct adapter *padapter,
+ struct xmit_frame *frame, u32 max_wait,
+ u32 bndy_cnt);
+
+ void (*hal_notch_filter)(struct adapter *adapter, bool enable);
+ void (*hal_reset_security_engine)(struct adapter *adapter);
+ s32 (*c2h_handler)(struct adapter *padapter,
+ struct c2h_evt_hdr *c2h_evt);
+ c2h_id_filter c2h_id_filter_ccx;
+};
+
+enum rt_eeprom_type {
+ EEPROM_93C46,
+ EEPROM_93C56,
+ EEPROM_BOOT_EFUSE,
+};
+
+#define RF_CHANGE_BY_INIT 0
+#define RF_CHANGE_BY_IPS BIT(28)
+#define RF_CHANGE_BY_PS BIT(29)
+#define RF_CHANGE_BY_HW BIT(30)
+#define RF_CHANGE_BY_SW BIT(31)
+
+enum hardware_type {
+ HARDWARE_TYPE_RTL8180,
+ HARDWARE_TYPE_RTL8185,
+ HARDWARE_TYPE_RTL8187,
+ HARDWARE_TYPE_RTL8188,
+ HARDWARE_TYPE_RTL8190P,
+ HARDWARE_TYPE_RTL8192E,
+ HARDWARE_TYPE_RTL819xU,
+ HARDWARE_TYPE_RTL8192SE,
+ HARDWARE_TYPE_RTL8192SU,
+ HARDWARE_TYPE_RTL8192CE,
+ HARDWARE_TYPE_RTL8192CU,
+ HARDWARE_TYPE_RTL8192DE,
+ HARDWARE_TYPE_RTL8192DU,
+ HARDWARE_TYPE_RTL8723AE,
+ HARDWARE_TYPE_RTL8723AU,
+ HARDWARE_TYPE_RTL8723AS,
+ HARDWARE_TYPE_RTL8188EE,
+ HARDWARE_TYPE_RTL8188EU,
+ HARDWARE_TYPE_RTL8188ES,
+ HARDWARE_TYPE_MAX,
+};
+
+/* RTL8188E Series */
+#define IS_HARDWARE_TYPE_8188EE(_Adapter) \
+(((struct adapter *)_Adapter)->HardwareType == HARDWARE_TYPE_RTL8188EE)
+#define IS_HARDWARE_TYPE_8188EU(_Adapter) \
+(((struct adapter *)_Adapter)->HardwareType == HARDWARE_TYPE_RTL8188EU)
+#define IS_HARDWARE_TYPE_8188ES(_Adapter) \
+(((struct adapter *)_Adapter)->HardwareType == HARDWARE_TYPE_RTL8188ES)
+#define IS_HARDWARE_TYPE_8188E(_Adapter) \
+(IS_HARDWARE_TYPE_8188EE(_Adapter) || IS_HARDWARE_TYPE_8188EU(_Adapter) || \
+ IS_HARDWARE_TYPE_8188ES(_Adapter))
+
+#define GET_EEPROM_EFUSE_PRIV(adapter) (&adapter->eeprompriv)
+
+#define is_boot_from_eeprom(adapter) (adapter->eeprompriv.EepromOrEfuse)
+
+void rtl8188eu_set_hal_ops(struct adapter *padapter);
+void rtw_hal_def_value_init(struct adapter *padapter);
+
+void rtw_hal_free_data(struct adapter *padapter);
+
+void rtw_hal_dm_init(struct adapter *padapter);
+void rtw_hal_dm_deinit(struct adapter *padapter);
+void rtw_hal_sw_led_init(struct adapter *padapter);
+void rtw_hal_sw_led_deinit(struct adapter *padapter);
+
+u32 rtw_hal_power_on(struct adapter *padapter);
+uint rtw_hal_init(struct adapter *padapter);
+uint rtw_hal_deinit(struct adapter *padapter);
+void rtw_hal_stop(struct adapter *padapter);
+void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val);
+void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val);
+
+void rtw_hal_chip_configure(struct adapter *padapter);
+void rtw_hal_read_chip_info(struct adapter *padapter);
+void rtw_hal_read_chip_version(struct adapter *padapter);
+
+u8 rtw_hal_set_def_var(struct adapter *padapter,
+ enum hal_def_variable eVariable, void *pValue);
+u8 rtw_hal_get_def_var(struct adapter *padapter,
+ enum hal_def_variable eVariable, void *pValue);
+
+void rtw_hal_set_odm_var(struct adapter *padapter,
+ enum hal_odm_variable eVariable, void *pValue1,
+ bool bSet);
+void rtw_hal_get_odm_var(struct adapter *padapter,
+ enum hal_odm_variable eVariable,
+ void *pValue1, bool bSet);
+
+void rtw_hal_enable_interrupt(struct adapter *padapter);
+void rtw_hal_disable_interrupt(struct adapter *padapter);
+
+u32 rtw_hal_inirp_init(struct adapter *padapter);
+u32 rtw_hal_inirp_deinit(struct adapter *padapter);
+
+u8 rtw_hal_intf_ps_func(struct adapter *padapter,
+ enum hal_intf_ps_func efunc_id, u8 *val);
+s32 rtw_hal_xmitframe_enqueue(struct adapter *padapter,
+ struct xmit_frame *pxmitframe);
+
+s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe);
+s32 rtw_hal_mgnt_xmit(struct adapter *padapter,
+ struct xmit_frame *pmgntframe);
+
+s32 rtw_hal_init_xmit_priv(struct adapter *padapter);
+
+s32 rtw_hal_init_recv_priv(struct adapter *padapter);
+void rtw_hal_free_recv_priv(struct adapter *padapter);
+
+void rtw_hal_update_ra_mask(struct adapter *padapter, u32 mac_id, u8 level);
+void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, u8 level);
+void rtw_hal_clone_data(struct adapter *dst_adapt,
+ struct adapter *src_adapt);
+void rtw_hal_start_thread(struct adapter *padapter);
+void rtw_hal_stop_thread(struct adapter *padapter);
+
+void rtw_hal_bcn_related_reg_setting(struct adapter *padapter);
+
+u32 rtw_hal_read_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask);
+void rtw_hal_write_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask,
+ u32 Data);
+u32 rtw_hal_read_rfreg(struct adapter *padapter, enum rf_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask);
+void rtw_hal_write_rfreg(struct adapter *padapter,
+ enum rf_radio_path eRFPath, u32 RegAddr,
+ u32 BitMask, u32 Data);
+
+s32 rtw_hal_interrupt_handler(struct adapter *padapter);
+
+void rtw_hal_set_bwmode(struct adapter *padapter,
+ enum ht_channel_width Bandwidth, u8 Offset);
+void rtw_hal_set_chan(struct adapter *padapter, u8 channel);
+void rtw_hal_dm_watchdog(struct adapter *padapter);
+
+u8 rtw_hal_antdiv_before_linked(struct adapter *padapter);
+void rtw_hal_antdiv_rssi_compared(struct adapter *padapter,
+ struct wlan_bssid_ex *dst,
+ struct wlan_bssid_ex *src);
+
+void rtw_hal_sreset_init(struct adapter *padapter);
+void rtw_hal_sreset_reset(struct adapter *padapter);
+void rtw_hal_sreset_reset_value(struct adapter *padapter);
+void rtw_hal_sreset_xmit_status_check(struct adapter *padapter);
+void rtw_hal_sreset_linked_status_check(struct adapter *padapter);
+u8 rtw_hal_sreset_get_wifi_status(struct adapter *padapter);
+
+int rtw_hal_iol_cmd(struct adapter *adapter, struct xmit_frame *xmit_frame,
+ u32 max_wating_ms, u32 bndy_cnt);
+
+void rtw_hal_notch_filter(struct adapter *adapter, bool enable);
+void rtw_hal_reset_security_engine(struct adapter *adapter);
+
+s32 rtw_hal_c2h_handler(struct adapter *adapter,
+ struct c2h_evt_hdr *c2h_evt);
+c2h_id_filter rtw_hal_c2h_id_filter_ccx(struct adapter *adapter);
+void indicate_wx_scan_complete_event(struct adapter *padapter);
+u8 rtw_do_join(struct adapter *padapter);
+
+#endif /* __HAL_INTF_H__ */
diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/r8188eu/include/ieee80211.h
index da6245a77d5d..bc5b030e9c40 100644
--- a/drivers/staging/rtl8188eu/include/ieee80211.h
+++ b/drivers/staging/r8188eu/include/ieee80211.h
@@ -1,17 +1,20 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __IEEE80211_H
#define __IEEE80211_H
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "osdep_service.h"
+#include "drv_types.h"
#include "wifi.h"
#include <linux/wireless.h>
+#define MGMT_QUEUE_NUM 5
+
+#define ETH_ALEN 6
+#define ETH_TYPE_LEN 2
+#define PAYLOAD_TYPE_LEN 1
+
#ifdef CONFIG_88EU_AP_MODE
#define RTL_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 28)
@@ -98,8 +101,10 @@ enum {
#define WPA_CIPHER_TKIP BIT(3)
#define WPA_CIPHER_CCMP BIT(4)
+
#define WPA_SELECTOR_LEN 4
extern u8 RTW_WPA_OUI_TYPE[];
+extern u16 RTW_WPA_VERSION;
extern u8 WPA_AUTH_KEY_MGMT_NONE[];
extern u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[];
extern u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[];
@@ -140,53 +145,34 @@ enum NETWORK_TYPE {
/* Sub-Element */
WIRELESS_11B = BIT(0), /* tx:cck only, rx:cck only, hw: cck */
WIRELESS_11G = BIT(1), /* tx:ofdm only, rx:ofdm & cck, hw:cck & ofdm*/
- WIRELESS_11A = BIT(2), /* tx:ofdm only, rx: ofdm only, hw:ofdm only */
WIRELESS_11_24N = BIT(3), /* tx:MCS only, rx:MCS & cck, hw:MCS & cck */
- WIRELESS_11_5N = BIT(4), /* tx:MCS only, rx:MCS & ofdm, hw:ofdm only */
- WIRELESS_AC = BIT(6),
/* Combination */
/* tx: cck & ofdm, rx: cck & ofdm & MCS, hw: cck & ofdm */
WIRELESS_11BG = (WIRELESS_11B | WIRELESS_11G),
/* tx: ofdm & MCS, rx: ofdm & cck & MCS, hw: cck & ofdm */
WIRELESS_11G_24N = (WIRELESS_11G | WIRELESS_11_24N),
- /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */
- WIRELESS_11A_5N = (WIRELESS_11A | WIRELESS_11_5N),
/* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */
WIRELESS_11BG_24N = (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N),
- /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */
- WIRELESS_11AGN = (WIRELESS_11A | WIRELESS_11G | WIRELESS_11_24N |
- WIRELESS_11_5N),
- WIRELESS_11ABGN = (WIRELESS_11A | WIRELESS_11B | WIRELESS_11G |
- WIRELESS_11_24N | WIRELESS_11_5N),
};
#define SUPPORTED_24G_NETTYPE_MSK \
(WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N)
-#define SUPPORTED_5G_NETTYPE_MSK \
- (WIRELESS_11A | WIRELESS_11_5N)
#define IsSupported24G(NetType) \
((NetType) & SUPPORTED_24G_NETTYPE_MSK ? true : false)
-#define IsSupported5G(NetType) \
- ((NetType) & SUPPORTED_5G_NETTYPE_MSK ? true : false)
#define IsEnableHWCCK(NetType) \
IsSupported24G(NetType)
-#define IsEnableHWOFDM(NetType) \
- ((NetType) & (WIRELESS_11G | WIRELESS_11_24N | \
- SUPPORTED_5G_NETTYPE_MSK) ? true : false)
#define IsSupportedRxCCK(NetType) IsEnableHWCCK(NetType)
-#define IsSupportedRxOFDM(NetType) IsEnableHWOFDM(NetType)
-#define IsSupportedRxMCS(NetType) IsEnableHWOFDM(NetType)
#define IsSupportedTxCCK(NetType) \
((NetType) & (WIRELESS_11B) ? true : false)
#define IsSupportedTxOFDM(NetType) \
- ((NetType) & (WIRELESS_11G | WIRELESS_11A) ? true : false)
+ ((NetType) & (WIRELESS_11G) ? true : false)
#define IsSupportedTxMCS(NetType) \
- ((NetType) & (WIRELESS_11_24N | WIRELESS_11_5N) ? true : false)
+ ((NetType) & (WIRELESS_11_24N) ? true : false)
struct ieee_param {
u32 cmd;
@@ -257,13 +243,12 @@ struct sta_data {
#define IEEE80211_DATA_LEN 2304
/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
- * 6.2.1.1.2.
+ 6.2.1.1.2.
- * The figure in section 7.1.2 suggests a body size of up to 2312
- * bytes is allowed, which is a bit confusing, I suspect this
- * represents the 2304 bytes of real data, plus a possible 8 bytes of
- * WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro)
- */
+ The figure in section 7.1.2 suggests a body size of up to 2312
+ bytes is allowed, which is a bit confusing, I suspect this
+ represents the 2304 bytes of real data, plus a possible 8 bytes of
+ WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
#define IEEE80211_HLEN 30
#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
@@ -271,6 +256,62 @@ struct sta_data {
/* this is stolen from ipw2200 driver */
#define IEEE_IBSS_MAC_HASH_SIZE 31
+struct ieee_ibss_seq {
+ u8 mac[ETH_ALEN];
+ u16 seq_num;
+ u16 frag_num;
+ unsigned long packet_time;
+ struct list_head list;
+};
+
+struct rtw_ieee80211_hdr {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ u16 seq_ctl;
+ u8 addr4[ETH_ALEN];
+} __packed;
+
+struct rtw_ieee80211_hdr_3addr {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ u16 seq_ctl;
+} __packed;
+
+struct rtw_ieee80211_hdr_qos {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ u16 seq_ctl;
+ u8 addr4[ETH_ALEN];
+ u16 qc;
+} __packed;
+
+struct rtw_ieee80211_hdr_3addr_qos {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ u16 seq_ctl;
+ u16 qc;
+} __packed;
+
+struct eapol {
+ u8 snap[6];
+ u16 ethertype;
+ u8 version;
+ u8 type;
+ u16 length;
+} __packed;
+
enum eap_type {
EAP_PACKET = 0,
EAPOL_START,
@@ -286,6 +327,68 @@ enum eap_type {
#define MIN_FRAG_THRESHOLD 256U
#define MAX_FRAG_THRESHOLD 2346U
+/* Frame control field constants */
+#define RTW_IEEE80211_FCTL_VERS 0x0003
+#define RTW_IEEE80211_FCTL_FTYPE 0x000c
+#define RTW_IEEE80211_FCTL_STYPE 0x00f0
+#define RTW_IEEE80211_FCTL_TODS 0x0100
+#define RTW_IEEE80211_FCTL_FROMDS 0x0200
+#define RTW_IEEE80211_FCTL_MOREFRAGS 0x0400
+#define RTW_IEEE80211_FCTL_RETRY 0x0800
+#define RTW_IEEE80211_FCTL_PM 0x1000
+#define RTW_IEEE80211_FCTL_MOREDATA 0x2000
+#define RTW_IEEE80211_FCTL_PROTECTED 0x4000
+#define RTW_IEEE80211_FCTL_ORDER 0x8000
+#define RTW_IEEE80211_FCTL_CTL_EXT 0x0f00
+
+#define RTW_IEEE80211_FTYPE_MGMT 0x0000
+#define RTW_IEEE80211_FTYPE_CTL 0x0004
+#define RTW_IEEE80211_FTYPE_DATA 0x0008
+#define RTW_IEEE80211_FTYPE_EXT 0x000c
+
+/* management */
+#define RTW_IEEE80211_STYPE_ASSOC_REQ 0x0000
+#define RTW_IEEE80211_STYPE_ASSOC_RESP 0x0010
+#define RTW_IEEE80211_STYPE_REASSOC_REQ 0x0020
+#define RTW_IEEE80211_STYPE_REASSOC_RESP 0x0030
+#define RTW_IEEE80211_STYPE_PROBE_REQ 0x0040
+#define RTW_IEEE80211_STYPE_PROBE_RESP 0x0050
+#define RTW_IEEE80211_STYPE_BEACON 0x0080
+#define RTW_IEEE80211_STYPE_ATIM 0x0090
+#define RTW_IEEE80211_STYPE_DISASSOC 0x00A0
+#define RTW_IEEE80211_STYPE_AUTH 0x00B0
+#define RTW_IEEE80211_STYPE_DEAUTH 0x00C0
+#define RTW_IEEE80211_STYPE_ACTION 0x00D0
+
+/* control */
+#define RTW_IEEE80211_STYPE_CTL_EXT 0x0060
+#define RTW_IEEE80211_STYPE_BACK_REQ 0x0080
+#define RTW_IEEE80211_STYPE_BACK 0x0090
+#define RTW_IEEE80211_STYPE_PSPOLL 0x00A0
+#define RTW_IEEE80211_STYPE_RTS 0x00B0
+#define RTW_IEEE80211_STYPE_CTS 0x00C0
+#define RTW_IEEE80211_STYPE_ACK 0x00D0
+#define RTW_IEEE80211_STYPE_CFEND 0x00E0
+#define RTW_IEEE80211_STYPE_CFENDACK 0x00F0
+
+/* data */
+#define RTW_IEEE80211_STYPE_DATA 0x0000
+#define RTW_IEEE80211_STYPE_DATA_CFACK 0x0010
+#define RTW_IEEE80211_STYPE_DATA_CFPOLL 0x0020
+#define RTW_IEEE80211_STYPE_DATA_CFACKPOLL 0x0030
+#define RTW_IEEE80211_STYPE_NULLFUNC 0x0040
+#define RTW_IEEE80211_STYPE_CFACK 0x0050
+#define RTW_IEEE80211_STYPE_CFPOLL 0x0060
+#define RTW_IEEE80211_STYPE_CFACKPOLL 0x0070
+#define RTW_IEEE80211_STYPE_QOS_DATA 0x0080
+#define RTW_IEEE80211_STYPE_QOS_DATA_CFACK 0x0090
+#define RTW_IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0
+#define RTW_IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0
+#define RTW_IEEE80211_STYPE_QOS_NULLFUNC 0x00C0
+#define RTW_IEEE80211_STYPE_QOS_CFACK 0x00D0
+#define RTW_IEEE80211_STYPE_QOS_CFPOLL 0x00E0
+#define RTW_IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0
+
/* sequence control field */
#define RTW_IEEE80211_SCTL_FRAG 0x000F
#define RTW_IEEE80211_SCTL_SEQ 0xFFF0
@@ -325,23 +428,113 @@ struct ieee80211_snap_hdr {
#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
+#define WLAN_FC_GET_TYPE(fc) ((fc) & RTW_IEEE80211_FCTL_FTYPE)
+#define WLAN_FC_GET_STYPE(fc) ((fc) & RTW_IEEE80211_FCTL_STYPE)
+
#define WLAN_QC_GET_TID(qc) ((qc) & 0x0f)
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTW_IEEE80211_SCTL_FRAG)
#define WLAN_GET_SEQ_SEQ(seq) ((seq) & RTW_IEEE80211_SCTL_SEQ)
-/* Non standard? Not in <linux/ieee80211.h> */
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_BSS (1<<0)
+#define WLAN_CAPABILITY_IBSS (1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
+#define WLAN_CAPABILITY_PRIVACY (1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
+#define WLAN_CAPABILITY_PBCC (1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
+#define WLAN_CAPABILITY_SHORT_SLOT (1<<10)
+
+/* Status codes */
+#define WLAN_STATUS_SUCCESS 0
+#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
+#define WLAN_STATUS_CAPS_UNSUPPORTED 10
+#define WLAN_STATUS_REASSOC_NO_ASSOC 11
+#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
+#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
+#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
+#define WLAN_STATUS_CHALLENGE_FAIL 15
+#define WLAN_STATUS_AUTH_TIMEOUT 16
+#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
+#define WLAN_STATUS_ASSOC_DENIED_RATES 18
+/* 802.11b */
+#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
+#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
+#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
+
+/* Reason codes */
+#define WLAN_REASON_UNSPECIFIED 1
+#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define WLAN_REASON_DEAUTH_LEAVING 3
+#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define WLAN_REASON_DISASSOC_AP_BUSY 5
+#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
+#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
+#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
+#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
+#define WLAN_REASON_JOIN_WRONG_CHANNEL 65534
#define WLAN_REASON_EXPIRATION_CHK 65535
+/* Information Element IDs */
+#define WLAN_EID_SSID 0
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_FH_PARAMS 2
+#define WLAN_EID_DS_PARAMS 3
+#define WLAN_EID_CF_PARAMS 4
+#define WLAN_EID_TIM 5
+#define WLAN_EID_IBSS_PARAMS 6
+#define WLAN_EID_CHALLENGE 16
+/* EIDs defined by IEEE 802.11h - START */
+#define WLAN_EID_PWR_CONSTRAINT 32
+#define WLAN_EID_PWR_CAPABILITY 33
+#define WLAN_EID_TPC_REQUEST 34
+#define WLAN_EID_TPC_REPORT 35
+#define WLAN_EID_SUPPORTED_CHANNELS 36
+#define WLAN_EID_CHANNEL_SWITCH 37
+#define WLAN_EID_MEASURE_REQUEST 38
+#define WLAN_EID_MEASURE_REPORT 39
+#define WLAN_EID_QUITE 40
+#define WLAN_EID_IBSS_DFS 41
+/* EIDs defined by IEEE 802.11h - END */
+#define WLAN_EID_ERP_INFO 42
+#define WLAN_EID_HT_CAP 45
+#define WLAN_EID_RSN 48
+#define WLAN_EID_EXT_SUPP_RATES 50
+#define WLAN_EID_MOBILITY_DOMAIN 54
+#define WLAN_EID_FAST_BSS_TRANSITION 55
+#define WLAN_EID_TIMEOUT_INTERVAL 56
+#define WLAN_EID_RIC_DATA 57
+#define WLAN_EID_HT_OPERATION 61
+#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
+#define WLAN_EID_20_40_BSS_COEXISTENCE 72
+#define WLAN_EID_20_40_BSS_INTOLERANT 73
+#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
+#define WLAN_EID_MMIE 76
+#define WLAN_EID_VENDOR_SPECIFIC 221
+#define WLAN_EID_GENERIC (WLAN_EID_VENDOR_SPECIFIC)
+
#define IEEE80211_MGMT_HDR_LEN 24
#define IEEE80211_DATA_HDR3_LEN 24
#define IEEE80211_DATA_HDR4_LEN 30
-#define IEEE80211_CCK_MODULATION BIT(0)
-#define IEEE80211_OFDM_MODULATION BIT(1)
+#define IEEE80211_STATMASK_SIGNAL (1<<0)
+#define IEEE80211_STATMASK_RSSI (1<<1)
+#define IEEE80211_STATMASK_NOISE (1<<2)
+#define IEEE80211_STATMASK_RATE (1<<3)
+#define IEEE80211_STATMASK_WEMASK 0x7
+
+#define IEEE80211_CCK_MODULATION (1<<0)
+#define IEEE80211_OFDM_MODULATION (1<<1)
-#define IEEE80211_24GHZ_BAND BIT(0)
-#define IEEE80211_52GHZ_BAND BIT(1)
+#define IEEE80211_24GHZ_BAND (1<<0)
+#define IEEE80211_52GHZ_BAND (1<<1)
#define IEEE80211_CCK_RATE_LEN 4
#define IEEE80211_NUM_OFDM_RATESLEN 8
@@ -361,18 +554,18 @@ struct ieee80211_snap_hdr {
#define IEEE80211_OFDM_RATE_54MB 0x6C
#define IEEE80211_BASIC_RATE_MASK 0x80
-#define IEEE80211_CCK_RATE_1MB_MASK BIT(0)
-#define IEEE80211_CCK_RATE_2MB_MASK BIT(1)
-#define IEEE80211_CCK_RATE_5MB_MASK BIT(2)
-#define IEEE80211_CCK_RATE_11MB_MASK BIT(3)
-#define IEEE80211_OFDM_RATE_6MB_MASK BIT(4)
-#define IEEE80211_OFDM_RATE_9MB_MASK BIT(5)
-#define IEEE80211_OFDM_RATE_12MB_MASK BIT(6)
-#define IEEE80211_OFDM_RATE_18MB_MASK BIT(7)
-#define IEEE80211_OFDM_RATE_24MB_MASK BIT(8)
-#define IEEE80211_OFDM_RATE_36MB_MASK BIT(9)
-#define IEEE80211_OFDM_RATE_48MB_MASK BIT(10)
-#define IEEE80211_OFDM_RATE_54MB_MASK BIT(11)
+#define IEEE80211_CCK_RATE_1MB_MASK (1<<0)
+#define IEEE80211_CCK_RATE_2MB_MASK (1<<1)
+#define IEEE80211_CCK_RATE_5MB_MASK (1<<2)
+#define IEEE80211_CCK_RATE_11MB_MASK (1<<3)
+#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4)
+#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5)
+#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6)
+#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7)
+#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8)
+#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9)
+#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10)
+#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11)
#define IEEE80211_CCK_RATES_MASK 0x0000000F
#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
@@ -393,27 +586,100 @@ struct ieee80211_snap_hdr {
IEEE80211_OFDM_RATE_36MB_MASK | \
IEEE80211_OFDM_RATE_48MB_MASK | \
IEEE80211_OFDM_RATE_54MB_MASK)
+#define IEEE80211_DEFAULT_RATES_MASK \
+ (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
+ IEEE80211_CCK_DEFAULT_RATES_MASK)
#define IEEE80211_NUM_OFDM_RATES 8
#define IEEE80211_NUM_CCK_RATES 4
#define IEEE80211_OFDM_SHIFT_MASK_A 4
+/* NOTE: This data is for statistical purposes; not all hardware provides this
+ * information for frames received. Not setting these will not cause
+ * any adverse affects. */
+struct ieee80211_rx_stats {
+ /* u32 mac_time[2]; */
+ s8 rssi;
+ u8 signal;
+ u8 noise;
+ u8 received_channel;
+ u16 rate; /* in 100 kbps */
+ /* u8 control; */
+ u8 mask;
+ u8 freq;
+ u16 len;
+};
+
/* IEEE 802.11 requires that STA supports concurrent reception of at least
* three fragmented frames. This define can be increased to support more
* concurrent frames, but it should be noted that each entry can consume about
- * 2 kB of RAM and increasing cache size will slow down frame reassembly.
- */
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
#define IEEE80211_FRAG_CACHE_LEN 4
-#define SEC_KEY_1 BIT(0)
-#define SEC_KEY_2 BIT(1)
-#define SEC_KEY_3 BIT(2)
-#define SEC_KEY_4 BIT(3)
-#define SEC_ACTIVE_KEY BIT(4)
-#define SEC_AUTH_MODE BIT(5)
-#define SEC_UNICAST_GROUP BIT(6)
-#define SEC_LEVEL BIT(7)
-#define SEC_ENABLED BIT(8)
+struct ieee80211_frag_entry {
+ u32 first_frag_time;
+ uint seq;
+ uint last_frag;
+ uint qos; /* jackson */
+ uint tid; /* jackson */
+ struct sk_buff *skb;
+ u8 src_addr[ETH_ALEN];
+ u8 dst_addr[ETH_ALEN];
+};
+
+struct ieee80211_stats {
+ uint tx_unicast_frames;
+ uint tx_multicast_frames;
+ uint tx_fragments;
+ uint tx_unicast_octets;
+ uint tx_multicast_octets;
+ uint tx_deferred_transmissions;
+ uint tx_single_retry_frames;
+ uint tx_multiple_retry_frames;
+ uint tx_retry_limit_exceeded;
+ uint tx_discards;
+ uint rx_unicast_frames;
+ uint rx_multicast_frames;
+ uint rx_fragments;
+ uint rx_unicast_octets;
+ uint rx_multicast_octets;
+ uint rx_fcs_errors;
+ uint rx_discards_no_buffer;
+ uint tx_discards_wrong_sa;
+ uint rx_discards_undecryptable;
+ uint rx_message_in_msg_fragments;
+ uint rx_message_in_bad_msg_fragments;
+};
+
+struct ieee80211_softmac_stats {
+ uint rx_ass_ok;
+ uint rx_ass_err;
+ uint rx_probe_rq;
+ uint tx_probe_rs;
+ uint tx_beacons;
+ uint rx_auth_rq;
+ uint rx_auth_rs_ok;
+ uint rx_auth_rs_err;
+ uint tx_auth_rq;
+ uint no_auth_rs;
+ uint no_ass_rs;
+ uint tx_ass_rq;
+ uint rx_ass_rq;
+ uint tx_probe_rq;
+ uint reassoc;
+ uint swtxstop;
+ uint swtxawake;
+};
+
+#define SEC_KEY_1 (1<<0)
+#define SEC_KEY_2 (1<<1)
+#define SEC_KEY_3 (1<<2)
+#define SEC_KEY_4 (1<<3)
+#define SEC_ACTIVE_KEY (1<<4)
+#define SEC_AUTH_MODE (1<<5)
+#define SEC_UNICAST_GROUP (1<<6)
+#define SEC_LEVEL (1<<7)
+#define SEC_ENABLED (1<<8)
#define SEC_LEVEL_0 0 /* None */
#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */
@@ -424,14 +690,139 @@ struct ieee80211_snap_hdr {
#define WEP_KEYS 4
#define WEP_KEY_LEN 13
+struct ieee80211_security {
+ u16 active_key:2,
+ enabled:1,
+ auth_mode:2,
+ auth_algo:4,
+ unicast_uses_group:1;
+ u8 key_sizes[WEP_KEYS];
+ u8 keys[WEP_KEYS][WEP_KEY_LEN];
+ u8 level;
+ u16 flags;
+} __packed;
+
+/*
+
+ 802.11 data frame from AP
+
+ ,-------------------------------------------------------------------.
+Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
+ |------|------|---------|---------|---------|------|---------|------|
+Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs |
+ | | tion | (BSSID) | | | ence | data | |
+ `-------------------------------------------------------------------'
+
+Total: 28-2340 bytes
+
+*/
+
+struct ieee80211_header_data {
+ u16 frame_ctl;
+ u16 duration_id;
+ u8 addr1[6];
+ u8 addr2[6];
+ u8 addr3[6];
+ u16 seq_ctrl;
+};
+
+#define BEACON_PROBE_SSID_ID_POSITION 12
+
+/* Management Frame Information Element Types */
+#define MFIE_TYPE_SSID 0
+#define MFIE_TYPE_RATES 1
+#define MFIE_TYPE_FH_SET 2
+#define MFIE_TYPE_DS_SET 3
+#define MFIE_TYPE_CF_SET 4
+#define MFIE_TYPE_TIM 5
+#define MFIE_TYPE_IBSS_SET 6
+#define MFIE_TYPE_CHALLENGE 16
+#define MFIE_TYPE_ERP 42
+#define MFIE_TYPE_RSN 48
+#define MFIE_TYPE_RATES_EX 50
+#define MFIE_TYPE_GENERIC 221
+
+struct ieee80211_info_element_hdr {
+ u8 id;
+ u8 len;
+} __packed;
+
+struct ieee80211_info_element {
+ u8 id;
+ u8 len;
+ u8 data[0];
+} __packed;
+
+/*
+ * These are the data types that can make up management packets
+ *
+ u16 auth_algorithm;
+ u16 auth_sequence;
+ u16 beacon_interval;
+ u16 capability;
+ u8 current_ap[ETH_ALEN];
+ u16 listen_interval;
+ struct {
+ u16 association_id:14, reserved:2;
+ } __packed;
+ u32 time_stamp[2];
+ u16 reason;
+ u16 status;
+*/
+
+#define IEEE80211_DEFAULT_TX_ESSID "Penguin"
+#define IEEE80211_DEFAULT_BASIC_RATE 10
+
+struct ieee80211_authentication {
+ struct ieee80211_header_data header;
+ u16 algorithm;
+ u16 transaction;
+ u16 status;
+ /* struct ieee80211_info_element_hdr info_element; */
+} __packed;
+
+struct ieee80211_probe_response {
+ struct ieee80211_header_data header;
+ u32 time_stamp[2];
+ u16 beacon_interval;
+ u16 capability;
+ struct ieee80211_info_element info_element;
+} __packed;
+
+struct ieee80211_probe_request {
+ struct ieee80211_header_data header;
+} __packed;
+
+struct ieee80211_assoc_request_frame {
+ struct rtw_ieee80211_hdr_3addr header;
+ u16 capability;
+ u16 listen_interval;
+ struct ieee80211_info_element_hdr info_element;
+} __packed;
+
+struct ieee80211_assoc_response_frame {
+ struct rtw_ieee80211_hdr_3addr header;
+ u16 capability;
+ u16 status;
+ u16 aid;
+} __packed;
+
+struct ieee80211_txb {
+ u8 nr_frags;
+ u8 encrypted;
+ u16 reserved;
+ u16 frag_size;
+ u16 payload_size;
+ struct sk_buff *fragments[0];
+};
+
/* SWEEP TABLE ENTRIES NUMBER*/
#define MAX_SWEEP_TAB_ENTRIES 42
#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7
/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
* only use 8, and then use extended rates for the remaining supported
* rates. Other APs, however, stick all of their supported rates on the
- * main rates information element...
- */
+ * main rates information element... */
#define MAX_RATES_LENGTH ((u8)12)
#define MAX_RATES_EX_LENGTH ((u8)16)
#define MAX_NETWORK_COUNT 128
@@ -447,17 +838,25 @@ struct ieee80211_snap_hdr {
#define MAX_P2P_IE_LEN (256)
#define MAX_WFD_IE_LEN (128)
-#define NETWORK_EMPTY_ESSID BIT(0)
-#define NETWORK_HAS_OFDM BIT(1)
-#define NETWORK_HAS_CCK BIT(2)
+#define NETWORK_EMPTY_ESSID (1<<0)
+#define NETWORK_HAS_OFDM (1<<1)
+#define NETWORK_HAS_CCK (1<<2)
+#define IEEE80211_DTIM_MBCAST 4
+#define IEEE80211_DTIM_UCAST 2
+#define IEEE80211_DTIM_VALID 1
+#define IEEE80211_DTIM_INVALID 0
+
+#define IEEE80211_PS_DISABLED 0
+#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST
+#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST
#define IW_ESSID_MAX_SIZE 32
/*
- * join_res:
- * -1: authentication fail
- * -2: association fail
- * > 0: TID
- */
+join_res:
+-1: authentication fail
+-2: association fail
+> 0: TID
+*/
enum ieee80211_state {
/* the card is not linked at all */
@@ -500,15 +899,35 @@ enum ieee80211_state {
#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
#define DEFAULT_FTS 2346
-#define CFG_IEEE80211_RESERVE_FCS BIT(0)
-#define CFG_IEEE80211_COMPUTE_FCS BIT(1)
+static inline int is_multicast_mac_addr(const u8 *addr)
+{
+ return ((addr[0] != 0xff) && (0x01 & addr[0]));
+}
+
+static inline int is_broadcast_mac_addr(const u8 *addr)
+{
+ return (addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
+ (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff);
+}
+
+#define CFG_IEEE80211_RESERVE_FCS (1<<0)
+#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
+
+struct tx_pending {
+ int frag;
+ struct ieee80211_txb *txb;
+};
#define MAXTID 16
-#define IEEE_A BIT(0)
-#define IEEE_B BIT(1)
-#define IEEE_G BIT(2)
-#define IEEE_MODE_MASK (IEEE_A | IEEE_B | IEEE_G)
+#define IEEE_A (1<<0)
+#define IEEE_B (1<<1)
+#define IEEE_G (1<<2)
+#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
+
+/* Baron move to ieee80211.c */
+int ieee80211_is_empty_essid(const char *essid, int essid_len);
+int ieee80211_get_hdrlen(u16 fc);
/* Action category code */
enum rtw_ieee80211_category {
@@ -526,6 +945,16 @@ enum rtw_ieee80211_category {
RTW_WLAN_CATEGORY_P2P = 0x7f,/* P2P action frames */
};
+/* SPECTRUM_MGMT action code */
+enum rtw_ieee80211_spectrum_mgmt_actioncode {
+ RTW_WLAN_ACTION_SPCT_MSR_REQ = 0,
+ RTW_WLAN_ACTION_SPCT_MSR_RPRT = 1,
+ RTW_WLAN_ACTION_SPCT_TPC_REQ = 2,
+ RTW_WLAN_ACTION_SPCT_TPC_RPRT = 3,
+ RTW_WLAN_ACTION_SPCT_CHL_SWITCH = 4,
+ RTW_WLAN_ACTION_SPCT_EXT_CHL_SWITCH = 5,
+};
+
enum _PUBLIC_ACTION {
ACT_PUBLIC_BSSCOEXIST = 0, /* 20/40 BSS Coexistence */
ACT_PUBLIC_DSE_ENABLE = 1,
@@ -546,6 +975,13 @@ enum _PUBLIC_ACTION {
ACT_PUBLIC_MAX
};
+/* BACK action code */
+enum rtw_ieee80211_back_actioncode {
+ RTW_WLAN_ACTION_ADDBA_REQ = 0,
+ RTW_WLAN_ACTION_ADDBA_RESP = 1,
+ RTW_WLAN_ACTION_DELBA = 2,
+};
+
/* HT features action code */
enum rtw_ieee80211_ht_actioncode {
RTW_WLAN_ACTION_NOTIFY_CH_WIDTH = 0,
@@ -559,9 +995,15 @@ enum rtw_ieee80211_ht_actioncode {
RTW_WLAN_ACTION_HI_INFO_EXCHG = 8,
};
+/* BACK (block-ack) parties */
+enum rtw_ieee80211_back_parties {
+ RTW_WLAN_BACK_RECIPIENT = 0,
+ RTW_WLAN_BACK_INITIATOR = 1,
+ RTW_WLAN_BACK_TIMER = 2,
+};
+
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
- * 00:50:F2
- */
+ * 00:50:F2 */
#define WME_OUI_TYPE 2
#define WME_OUI_SUBTYPE_INFORMATION_ELEMENT 0
#define WME_OUI_SUBTYPE_PARAMETER_ELEMENT 1
@@ -600,12 +1042,12 @@ enum rtw_ieee80211_ht_actioncode {
* is not permitted.
*/
enum rtw_ieee80211_channel_flags {
- RTW_IEEE80211_CHAN_DISABLED = BIT(0),
- RTW_IEEE80211_CHAN_PASSIVE_SCAN = BIT(1),
- RTW_IEEE80211_CHAN_NO_IBSS = BIT(2),
- RTW_IEEE80211_CHAN_RADAR = BIT(3),
- RTW_IEEE80211_CHAN_NO_HT40PLUS = BIT(4),
- RTW_IEEE80211_CHAN_NO_HT40MINUS = BIT(5),
+ RTW_IEEE80211_CHAN_DISABLED = 1<<0,
+ RTW_IEEE80211_CHAN_PASSIVE_SCAN = 1<<1,
+ RTW_IEEE80211_CHAN_NO_IBSS = 1<<2,
+ RTW_IEEE80211_CHAN_RADAR = 1<<3,
+ RTW_IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
+ RTW_IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
};
#define RTW_IEEE80211_CHAN_NO_HT40 \
@@ -685,8 +1127,8 @@ enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len,
struct rtw_ieee802_11_elems *elems,
int show_errors);
-u8 *rtw_set_fixed_ie(void *pbuf, unsigned int len,
- void *source, unsigned int *frlen);
+u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len,
+ unsigned char *source, unsigned int *frlen);
u8 *rtw_set_ie(u8 *pbuf, int index, uint len, u8 *source, uint *frlen);
enum secondary_ch_offset {
@@ -694,13 +1136,25 @@ enum secondary_ch_offset {
SCA = 1, /* secondary channel above */
SCB = 3, /* secondary channel below */
};
-
-u8 *rtw_get_ie(u8 *pbuf, int index, uint *len, int limit);
+u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset);
+u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset);
+u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode,
+ u8 new_ch, u8 ch_switch_cnt);
+u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len,
+ u8 secondary_ch_offset);
+u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl,
+ u8 flags, u16 reason, u16 precedence);
+
+u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit);
+u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui,
+ u8 oui_len, u8 *ie, uint *ielen);
+int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset,
+ u8 eid, u8 *oui, u8 oui_len);
void rtw_set_supported_rate(u8 *SupportedRates, uint mode);
-unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit);
-unsigned char *rtw_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len, int limit);
+unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit);
+unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit);
int rtw_get_wpa_cipher_suite(u8 *s);
int rtw_get_wpa2_cipher_suite(u8 *s);
int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len);
@@ -709,8 +1163,8 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
int rtw_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
int *pairwise_cipher, int *is_8021x);
-void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
- u8 *wpa_ie, u16 *wpa_len);
+int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
+ u8 *wpa_ie, u16 *wpa_len);
u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen);
u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen);
@@ -719,6 +1173,32 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
u8 *buf_content, uint *len_content);
+/**
+ * for_each_ie - iterate over continuous IEs
+ * @ie:
+ * @buf:
+ * @buf_len:
+ */
+#define for_each_ie(ie, buf, buf_len) \
+ for (ie = (void *)buf; (((u8 *)ie) - ((u8 *)buf) + 1) < buf_len; \
+ ie = (void *)(((u8 *)ie) + *(((u8 *)ie)+1) + 2))
+
+void dump_ies(u8 *buf, u32 buf_len);
+void dump_wps_ie(u8 *ie, u32 ie_len);
+
+#ifdef CONFIG_88EU_P2P
+void dump_p2p_ie(u8 *ie, u32 ie_len);
+u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen);
+u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
+ u8 *buf_attr, u32 *len_attr);
+u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
+ u8 *buf_content, uint *len_content);
+u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len,
+ u8 *pdata_attr);
+void rtw_wlan_bssid_ex_remove_p2p_attr(struct wlan_bssid_ex *bss_ex,
+ u8 attr_id);
+#endif
+
uint rtw_get_rateset_len(u8 *rateset);
struct registry_priv;
@@ -726,11 +1206,11 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv);
int rtw_get_bit_value_from_ieee_value(u8 val);
-bool rtw_is_cckrates_included(u8 *rate);
+uint rtw_is_cckrates_included(u8 *rate);
-bool rtw_is_cckratesonly_included(u8 *rate);
+uint rtw_is_cckratesonly_included(u8 *rate);
-int rtw_check_network_type(unsigned char *rate);
+int rtw_check_network_type(unsigned char *rate, int ratelen, int channel);
void rtw_get_bcn_info(struct wlan_network *pnetwork);
@@ -739,4 +1219,8 @@ void rtw_macaddr_cfg(u8 *mac_addr);
u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40,
unsigned char *MCS_rate);
+int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category,
+ u8 *action);
+const char *action_public_str(u8 action);
+
#endif /* IEEE80211_H */
diff --git a/drivers/staging/r8188eu/include/ieee80211_ext.h b/drivers/staging/r8188eu/include/ieee80211_ext.h
new file mode 100644
index 000000000000..e7ade835d478
--- /dev/null
+++ b/drivers/staging/r8188eu/include/ieee80211_ext.h
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __IEEE80211_EXT_H
+#define __IEEE80211_EXT_H
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+#define WMM_OUI_TYPE 2
+#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
+#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
+#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2
+#define WMM_VERSION 1
+
+#define WPA_PROTO_WPA BIT(0)
+#define WPA_PROTO_RSN BIT(1)
+
+#define WPA_KEY_MGMT_IEEE8021X BIT(0)
+#define WPA_KEY_MGMT_PSK BIT(1)
+#define WPA_KEY_MGMT_NONE BIT(2)
+#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
+#define WPA_KEY_MGMT_WPA_NONE BIT(4)
+
+#define WPA_CAPABILITY_PREAUTH BIT(0)
+#define WPA_CAPABILITY_MGMT_FRAME_PROTECTION BIT(6)
+#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9)
+
+#define PMKID_LEN 16
+
+struct wpa_ie_hdr {
+ u8 elem_id;
+ u8 len;
+ u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */
+ u8 version[2]; /* little endian */
+} __packed;
+
+struct rsn_ie_hdr {
+ u8 elem_id; /* WLAN_EID_RSN */
+ u8 len;
+ u8 version[2]; /* little endian */
+} __packed;
+
+struct wme_ac_parameter {
+#if defined(__LITTLE_ENDIAN)
+ /* byte 1 */
+ u8 aifsn:4,
+ acm:1,
+ aci:2,
+ reserved:1;
+
+ /* byte 2 */
+ u8 eCWmin:4,
+ eCWmax:4;
+#elif defined(__BIG_ENDIAN)
+ /* byte 1 */
+ u8 reserved:1,
+ aci:2,
+ acm:1,
+ aifsn:4;
+
+ /* byte 2 */
+ u8 eCWmax:4,
+ eCWmin:4;
+#else
+#error "Please fix <endian.h>"
+#endif
+
+ /* bytes 3 & 4 */
+ u16 txopLimit;
+} __packed;
+
+struct wme_parameter_element {
+ /* required fields for WME version 1 */
+ u8 oui[3];
+ u8 oui_type;
+ u8 oui_subtype;
+ u8 version;
+ u8 acInfo;
+ u8 reserved;
+ struct wme_ac_parameter ac[4];
+
+} __packed;
+
+#define WPA_PUT_LE16(a, val) \
+ do { \
+ (a)[1] = ((u16) (val)) >> 8; \
+ (a)[0] = ((u16) (val)) & 0xff; \
+ } while (0)
+
+#define WPA_PUT_BE32(a, val) \
+ do { \
+ (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \
+ (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \
+ (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \
+ (a)[3] = (u8) (((u32) (val)) & 0xff); \
+ } while (0)
+
+#define WPA_PUT_LE32(a, val) \
+ do { \
+ (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \
+ (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \
+ (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \
+ (a)[0] = (u8) (((u32) (val)) & 0xff); \
+ } while (0)
+
+#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *)(a), (val))
+
+/* Action category code */
+enum ieee80211_category {
+ WLAN_CATEGORY_SPECTRUM_MGMT = 0,
+ WLAN_CATEGORY_QOS = 1,
+ WLAN_CATEGORY_DLS = 2,
+ WLAN_CATEGORY_BACK = 3,
+ WLAN_CATEGORY_HT = 7,
+ WLAN_CATEGORY_WMM = 17,
+};
+
+/* SPECTRUM_MGMT action code */
+enum ieee80211_spectrum_mgmt_actioncode {
+ WLAN_ACTION_SPCT_MSR_REQ = 0,
+ WLAN_ACTION_SPCT_MSR_RPRT = 1,
+ WLAN_ACTION_SPCT_TPC_REQ = 2,
+ WLAN_ACTION_SPCT_TPC_RPRT = 3,
+ WLAN_ACTION_SPCT_CHL_SWITCH = 4,
+ WLAN_ACTION_SPCT_EXT_CHL_SWITCH = 5,
+};
+
+/* BACK action code */
+enum ieee80211_back_actioncode {
+ WLAN_ACTION_ADDBA_REQ = 0,
+ WLAN_ACTION_ADDBA_RESP = 1,
+ WLAN_ACTION_DELBA = 2,
+};
+
+/* HT features action code */
+enum ieee80211_ht_actioncode {
+ WLAN_ACTION_NOTIFY_CH_WIDTH = 0,
+ WLAN_ACTION_SM_PS = 1,
+ WLAN_ACTION_PSPM = 2,
+ WLAN_ACTION_PCO_PHASE = 3,
+ WLAN_ACTION_MIMO_CSI_MX = 4,
+ WLAN_ACTION_MIMO_NONCP_BF = 5,
+ WLAN_ACTION_MIMP_CP_BF = 6,
+ WLAN_ACTION_ASEL_INDICATES_FB = 7,
+ WLAN_ACTION_HI_INFO_EXCHG = 8,
+};
+
+/* BACK (block-ack) parties */
+enum ieee80211_back_parties {
+ WLAN_BACK_RECIPIENT = 0,
+ WLAN_BACK_INITIATOR = 1,
+ WLAN_BACK_TIMER = 2,
+};
+
+struct ieee80211_mgmt {
+ u16 frame_control;
+ u16 duration;
+ u8 da[6];
+ u8 sa[6];
+ u8 bssid[6];
+ u16 seq_ctrl;
+ union {
+ struct {
+ u16 auth_alg;
+ u16 auth_transaction;
+ u16 status_code;
+ /* possibly followed by Challenge text */
+ u8 variable[0];
+ } __packed auth;
+ struct {
+ u16 reason_code;
+ } __packed deauth;
+ struct {
+ u16 capab_info;
+ u16 listen_interval;
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+ } __packed assoc_req;
+ struct {
+ u16 capab_info;
+ u16 status_code;
+ u16 aid;
+ /* followed by Supported rates */
+ u8 variable[0];
+ } __packed assoc_resp, reassoc_resp;
+ struct {
+ u16 capab_info;
+ u16 listen_interval;
+ u8 current_ap[6];
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+ } __packed reassoc_req;
+ struct {
+ u16 reason_code;
+ } __packed disassoc;
+ struct {
+ __le64 timestamp;
+ u16 beacon_int;
+ u16 capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params, TIM */
+ u8 variable[0];
+ } __packed beacon;
+ struct {
+ /* only variable items: SSID, Supported rates */
+ u8 variable[0];
+ } __packed probe_req;
+ struct {
+ __le64 timestamp;
+ u16 beacon_int;
+ u16 capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params */
+ u8 variable[0];
+ } __packed probe_resp;
+ struct {
+ u8 category;
+ union {
+ struct {
+ u8 action_code;
+ u8 dialog_token;
+ u8 status_code;
+ u8 variable[0];
+ } __packed wme_action;
+ struct {
+ u8 action_code;
+ u8 dialog_token;
+ u16 capab;
+ u16 timeout;
+ u16 start_seq_num;
+ } __packed addba_req;
+ struct {
+ u8 action_code;
+ u8 dialog_token;
+ u16 status;
+ u16 capab;
+ u16 timeout;
+ } __packed addba_resp;
+ struct {
+ u8 action_code;
+ u16 params;
+ u16 reason_code;
+ } __packed delba;
+ structi {
+ u8 action_code;
+ /* capab_info for open and confirm,
+ * reason for close
+ */
+ u16 aux;
+ /* Followed in plink_confirm by status
+ * code, AID and supported rates,
+ * and directly by supported rates in
+ * plink_open and plink_close
+ */
+ u8 variable[0];
+ } __packed plink_action;
+ struct{
+ u8 action_code;
+ u8 variable[0];
+ } __packed mesh_action;
+ } __packed u;
+ } __packed action;
+ } __packed u;
+} __packed;
+
+/* mgmt header + 1 byte category code */
+#define IEEE80211_MIN_ACTION_SIZE \
+ FIELD_OFFSET(struct ieee80211_mgmt, u.action.u)
+
+#endif
diff --git a/drivers/staging/r8188eu/include/ioctl_cfg80211.h b/drivers/staging/r8188eu/include/ioctl_cfg80211.h
new file mode 100644
index 000000000000..e22481050ef8
--- /dev/null
+++ b/drivers/staging/r8188eu/include/ioctl_cfg80211.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. i*/
+
+#ifndef __IOCTL_CFG80211_H__
+#define __IOCTL_CFG80211_H__
+
+struct rtw_wdev_invit_info {
+ u8 token;
+ u8 flags;
+ u8 status;
+ u8 req_op_ch;
+ u8 rsp_op_ch;
+};
+
+#define rtw_wdev_invit_info_init(invit_info) \
+ do { \
+ (invit_info)->token = 0; \
+ (invit_info)->flags = 0x00; \
+ (invit_info)->status = 0xff; \
+ (invit_info)->req_op_ch = 0; \
+ (invit_info)->rsp_op_ch = 0; \
+ } while (0)
+
+struct rtw_wdev_priv {
+ struct wireless_dev *rtw_wdev;
+
+ struct adapter *padapter;
+
+ struct cfg80211_scan_request *scan_request;
+ spinlock_t scan_req_lock;
+
+ struct net_device *pmon_ndev;/* for monitor interface */
+ char ifname_mon[IFNAMSIZ + 1]; /* name of monitor interface */
+
+ u8 p2p_enabled;
+
+ u8 provdisc_req_issued;
+
+ struct rtw_wdev_invit_info invit_info;
+
+ u8 bandroid_scan;
+ bool block;
+ bool power_mgmt;
+};
+
+#define wdev_to_priv(w) ((struct rtw_wdev_priv *)(wdev_priv(w)))
+
+#define wiphy_to_wdev(x) \
+((struct wireless_dev *)(((struct rtw_wdev_priv *)wiphy_priv(x))->rtw_wdev))
+
+int rtw_wdev_alloc(struct adapter *padapter, struct device *dev);
+void rtw_wdev_free(struct wireless_dev *wdev);
+void rtw_wdev_unregister(struct wireless_dev *wdev);
+
+void rtw_cfg80211_init_wiphy(struct adapter *padapter);
+
+void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter);
+
+void rtw_cfg80211_indicate_connect(struct adapter *padapter);
+void rtw_cfg80211_indicate_disconnect(struct adapter *padapter);
+void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
+ bool aborted);
+
+#ifdef CONFIG_88EU_AP_MODE
+void rtw_cfg80211_indicate_sta_assoc(struct adapter *padapter,
+ u8 *pmgmt_frame, uint frame_len);
+void rtw_cfg80211_indicate_sta_disassoc(struct adapter *padapter,
+ unsigned char *da,
+ unsigned short reason);
+#endif /* CONFIG_88EU_AP_MODE */
+
+void rtw_cfg80211_issue_p2p_provision_request(struct adapter *padapter,
+ const u8 *buf, size_t len);
+void rtw_cfg80211_rx_p2p_action_public(struct adapter *padapter,
+ u8 *pmgmt_frame, uint frame_len);
+void rtw_cfg80211_rx_action_p2p(struct adapter *padapter, u8 *pmgmt_frame,
+ uint frame_len);
+void rtw_cfg80211_rx_action(struct adapter *adapter, u8 *frame,
+ uint frame_len, const char *msg);
+
+int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net,
+ char *buf, int len, int type);
+
+bool rtw_cfg80211_pwr_mgmt(struct adapter *adapter);
+
+#define rtw_cfg80211_rx_mgmt(dev, freq, sig_dbm, buf, len, gfp) \
+ cfg80211_rx_mgmt(dev, freq, sig_dbm, buf, len, gfp)
+#define rtw_cfg80211_send_rx_assoc(dev, bss, buf, len) \
+ cfg80211_send_rx_assoc(dev, bss, buf, len)
+
+#endif /* __IOCTL_CFG80211_H__ */
diff --git a/drivers/staging/rtl8188eu/include/mlme_osdep.h b/drivers/staging/r8188eu/include/mlme_osdep.h
index 8e919441c2aa..5b9f688f9424 100644
--- a/drivers/staging/rtl8188eu/include/mlme_osdep.h
+++ b/drivers/staging/r8188eu/include/mlme_osdep.h
@@ -1,18 +1,16 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __MLME_OSDEP_H_
#define __MLME_OSDEP_H_
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "osdep_service.h"
+#include "drv_types.h"
void rtw_init_mlme_timer(struct adapter *padapter);
void rtw_os_indicate_disconnect(struct adapter *adapter);
void rtw_os_indicate_connect(struct adapter *adapter);
+void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted);
void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie);
void rtw_reset_securitypriv(struct adapter *adapter);
diff --git a/drivers/staging/r8188eu/include/mp_custom_oid.h b/drivers/staging/r8188eu/include/mp_custom_oid.h
new file mode 100644
index 000000000000..7bcb857c795d
--- /dev/null
+++ b/drivers/staging/r8188eu/include/mp_custom_oid.h
@@ -0,0 +1,333 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __CUSTOM_OID_H
+#define __CUSTOM_OID_H
+
+/* by Owen */
+/* 0xFF818000 - 0xFF81802F RTL8180 Mass Production Kit */
+/* 0xFF818500 - 0xFF81850F RTL8185 Setup Utility */
+/* 0xFF818580 - 0xFF81858F RTL8185 Phy Status Utility */
+
+/* */
+
+/* by Owen for Production Kit */
+/* For Production Kit with Agilent Equipments */
+/* in order to make our custom oids hopefully somewhat unique */
+/* we will use 0xFF (indicating implementation specific OID) */
+/* 81(first byte of non zero Realtek unique identifier) */
+/* 80 (second byte of non zero Realtek unique identifier) */
+/* XX (the custom OID number - providing 255 possible custom oids) */
+
+#define OID_RT_PRO_RESET_DUT 0xFF818000
+#define OID_RT_PRO_SET_DATA_RATE 0xFF818001
+#define OID_RT_PRO_START_TEST 0xFF818002
+#define OID_RT_PRO_STOP_TEST 0xFF818003
+#define OID_RT_PRO_SET_PREAMBLE 0xFF818004
+#define OID_RT_PRO_SET_SCRAMBLER 0xFF818005
+#define OID_RT_PRO_SET_FILTER_BB 0xFF818006
+#define OID_RT_PRO_SET_MANUAL_DIVERSITY_BB 0xFF818007
+#define OID_RT_PRO_SET_CHANNEL_DIRECT_CALL 0xFF818008
+#define OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL 0xFF818009
+#define OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL 0xFF81800A
+
+#define OID_RT_PRO_SET_TX_ANTENNA_BB 0xFF81800D
+#define OID_RT_PRO_SET_ANTENNA_BB 0xFF81800E
+#define OID_RT_PRO_SET_CR_SCRAMBLER 0xFF81800F
+#define OID_RT_PRO_SET_CR_NEW_FILTER 0xFF818010
+#define OID_RT_PRO_SET_TX_POWER_CONTROL 0xFF818011
+#define OID_RT_PRO_SET_CR_TX_CONFIG 0xFF818012
+#define OID_RT_PRO_GET_TX_POWER_CONTROL 0xFF818013
+#define OID_RT_PRO_GET_CR_SIGNAL_QUALITY 0xFF818014
+#define OID_RT_PRO_SET_CR_SETPOINT 0xFF818015
+#define OID_RT_PRO_SET_INTEGRATOR 0xFF818016
+#define OID_RT_PRO_SET_SIGNAL_QUALITY 0xFF818017
+#define OID_RT_PRO_GET_INTEGRATOR 0xFF818018
+#define OID_RT_PRO_GET_SIGNAL_QUALITY 0xFF818019
+#define OID_RT_PRO_QUERY_EEPROM_TYPE 0xFF81801A
+#define OID_RT_PRO_WRITE_MAC_ADDRESS 0xFF81801B
+#define OID_RT_PRO_READ_MAC_ADDRESS 0xFF81801C
+#define OID_RT_PRO_WRITE_CIS_DATA 0xFF81801D
+#define OID_RT_PRO_READ_CIS_DATA 0xFF81801E
+#define OID_RT_PRO_WRITE_POWER_CONTROL 0xFF81801F
+#define OID_RT_PRO_READ_POWER_CONTROL 0xFF818020
+#define OID_RT_PRO_WRITE_EEPROM 0xFF818021
+#define OID_RT_PRO_READ_EEPROM 0xFF818022
+#define OID_RT_PRO_RESET_TX_PACKET_SENT 0xFF818023
+#define OID_RT_PRO_QUERY_TX_PACKET_SENT 0xFF818024
+#define OID_RT_PRO_RESET_RX_PACKET_RECEIVED 0xFF818025
+#define OID_RT_PRO_QUERY_RX_PACKET_RECEIVED 0xFF818026
+#define OID_RT_PRO_QUERY_RX_PACKET_CRC32_ERROR 0xFF818027
+#define OID_RT_PRO_QUERY_CURRENT_ADDRESS 0xFF818028
+#define OID_RT_PRO_QUERY_PERMANENT_ADDRESS 0xFF818029
+#define OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS 0xFF81802A
+#define OID_RT_PRO_RECEIVE_PACKET 0xFF81802C
+/* added by Owen on 04/08/03 for Cameo's request */
+#define OID_RT_PRO_WRITE_EEPROM_BYTE 0xFF81802D
+#define OID_RT_PRO_READ_EEPROM_BYTE 0xFF81802E
+#define OID_RT_PRO_SET_MODULATION 0xFF81802F
+/* */
+
+/* Sean */
+#define OID_RT_DRIVER_OPTION 0xFF818080
+#define OID_RT_RF_OFF 0xFF818081
+#define OID_RT_AUTH_STATUS 0xFF818082
+
+/* */
+#define OID_RT_PRO_SET_CONTINUOUS_TX 0xFF81800B
+#define OID_RT_PRO_SET_SINGLE_CARRIER_TX 0xFF81800C
+#define OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX 0xFF81802B
+#define OID_RT_PRO_SET_SINGLE_TONE_TX 0xFF818043
+/* */
+
+/* by Owen for RTL8185 Phy Status Report Utility */
+#define OID_RT_UTILITY_false_ALARM_COUNTERS 0xFF818580
+#define OID_RT_UTILITY_SELECT_DEBUG_MODE 0xFF818581
+#define OID_RT_UTILITY_SELECT_SUBCARRIER_NUMBER 0xFF818582
+#define OID_RT_UTILITY_GET_RSSI_STATUS 0xFF818583
+#define OID_RT_UTILITY_GET_FRAME_DETECTION_STATUS 0xFF818584
+#define OID_RT_UTILITY_GET_AGC_AND_FREQUENCY_OFFSET_ESTIMATION_STATUS \
+ 0xFF818585
+#define OID_RT_UTILITY_GET_CHANNEL_ESTIMATION_STATUS 0xFF818586
+/* */
+
+/* by Owen on 03/09/19-03/09/22 for RTL8185 */
+#define OID_RT_WIRELESS_MODE 0xFF818500
+#define OID_RT_SUPPORTED_RATES 0xFF818501
+#define OID_RT_DESIRED_RATES 0xFF818502
+#define OID_RT_WIRELESS_MODE_STARTING_ADHOC 0xFF818503
+/* */
+
+#define OID_RT_GET_CONNECT_STATE 0xFF030001
+#define OID_RT_RESCAN 0xFF030002
+#define OID_RT_SET_KEY_LENGTH 0xFF030003
+#define OID_RT_SET_DEFAULT_KEY_ID 0xFF030004
+
+#define OID_RT_SET_CHANNEL 0xFF010182
+#define OID_RT_SET_SNIFFER_MODE 0xFF010183
+#define OID_RT_GET_SIGNAL_QUALITY 0xFF010184
+#define OID_RT_GET_SMALL_PACKET_CRC 0xFF010185
+#define OID_RT_GET_MIDDLE_PACKET_CRC 0xFF010186
+#define OID_RT_GET_LARGE_PACKET_CRC 0xFF010187
+#define OID_RT_GET_TX_RETRY 0xFF010188
+#define OID_RT_GET_RX_RETRY 0xFF010189
+#define OID_RT_PRO_SET_FW_DIG_STATE 0xFF01018A/* S */
+#define OID_RT_PRO_SET_FW_RA_STATE 0xFF01018B/* S */
+
+#define OID_RT_GET_RX_TOTAL_PACKET 0xFF010190
+#define OID_RT_GET_TX_BEACON_OK 0xFF010191
+#define OID_RT_GET_TX_BEACON_ERR 0xFF010192
+#define OID_RT_GET_RX_ICV_ERR 0xFF010193
+#define OID_RT_SET_ENCRYPTION_ALGORITHM 0xFF010194
+#define OID_RT_SET_NO_AUTO_RESCAN 0xFF010195
+#define OID_RT_GET_PREAMBLE_MODE 0xFF010196
+#define OID_RT_GET_DRIVER_UP_DELTA_TIME 0xFF010197
+#define OID_RT_GET_AP_IP 0xFF010198
+#define OID_RT_GET_CHANNELPLAN 0xFF010199
+#define OID_RT_SET_PREAMBLE_MODE 0xFF01019A
+#define OID_RT_SET_BCN_INTVL 0xFF01019B
+#define OID_RT_GET_RF_VENDER 0xFF01019C
+#define OID_RT_DEDICATE_PROBE 0xFF01019D
+#define OID_RT_PRO_RX_FILTER_PATTERN 0xFF01019E
+
+#define OID_RT_GET_DCST_CURRENT_THRESHOLD 0xFF01019F
+
+#define OID_RT_GET_CCA_ERR 0xFF0101A0
+#define OID_RT_GET_CCA_UPGRADE_THRESHOLD 0xFF0101A1
+#define OID_RT_GET_CCA_FALLBACK_THRESHOLD 0xFF0101A2
+
+#define OID_RT_GET_CCA_UPGRADE_EVALUATE_TIMES 0xFF0101A3
+#define OID_RT_GET_CCA_FALLBACK_EVALUATE_TIMES 0xFF0101A4
+
+/* by Owen on 03/31/03 for Cameo's request */
+#define OID_RT_SET_RATE_ADAPTIVE 0xFF0101A5
+/* */
+#define OID_RT_GET_DCST_EVALUATE_PERIOD 0xFF0101A5
+#define OID_RT_GET_DCST_TIME_UNIT_INDEX 0xFF0101A6
+#define OID_RT_GET_TOTAL_TX_BYTES 0xFF0101A7
+#define OID_RT_GET_TOTAL_RX_BYTES 0xFF0101A8
+#define OID_RT_CURRENT_TX_POWER_LEVEL 0xFF0101A9
+#define OID_RT_GET_ENC_KEY_MISMATCH_COUNT 0xFF0101AA
+#define OID_RT_GET_ENC_KEY_MATCH_COUNT 0xFF0101AB
+#define OID_RT_GET_CHANNEL 0xFF0101AC
+
+#define OID_RT_SET_CHANNELPLAN 0xFF0101AD
+#define OID_RT_GET_HARDWARE_RADIO_OFF 0xFF0101AE
+#define OID_RT_CHANNELPLAN_BY_COUNTRY 0xFF0101AF
+#define OID_RT_SCAN_AVAILABLE_BSSID 0xFF0101B0
+#define OID_RT_GET_HARDWARE_VERSION 0xFF0101B1
+#define OID_RT_GET_IS_ROAMING 0xFF0101B2
+#define OID_RT_GET_IS_PRIVACY 0xFF0101B3
+#define OID_RT_GET_KEY_MISMATCH 0xFF0101B4
+#define OID_RT_SET_RSSI_ROAM_TRAFFIC_TH 0xFF0101B5
+#define OID_RT_SET_RSSI_ROAM_SIGNAL_TH 0xFF0101B6
+#define OID_RT_RESET_LOG 0xFF0101B7
+#define OID_RT_GET_LOG 0xFF0101B8
+#define OID_RT_SET_INDICATE_HIDDEN_AP 0xFF0101B9
+#define OID_RT_GET_HEADER_FAIL 0xFF0101BA
+#define OID_RT_SUPPORTED_WIRELESS_MODE 0xFF0101BB
+#define OID_RT_GET_CHANNEL_LIST 0xFF0101BC
+#define OID_RT_GET_SCAN_IN_PROGRESS 0xFF0101BD
+#define OID_RT_GET_TX_INFO 0xFF0101BE
+#define OID_RT_RF_READ_WRITE_OFFSET 0xFF0101BF
+#define OID_RT_RF_READ_WRITE 0xFF0101C0
+
+/* For Netgear request. 2005.01.13, by rcnjko. */
+#define OID_RT_FORCED_DATA_RATE 0xFF0101C1
+#define OID_RT_WIRELESS_MODE_FOR_SCAN_LIST 0xFF0101C2
+/* For Netgear request. 2005.02.17, by rcnjko. */
+#define OID_RT_GET_BSS_WIRELESS_MODE 0xFF0101C3
+/* For AZ project. 2005.06.27, by rcnjko. */
+#define OID_RT_SCAN_WITH_MAGIC_PACKET 0xFF0101C4
+
+/* Vincent 8185MP */
+#define OID_RT_PRO_RX_FILTER 0xFF0111C0
+
+#define OID_CE_USB_WRITE_REGISTRY 0xFF0111C1
+#define OID_CE_USB_READ_REGISTRY 0xFF0111C2
+
+#define OID_RT_PRO_SET_INITIAL_GA 0xFF0111C3
+#define OID_RT_PRO_SET_BB_RF_STANDBY_MODE 0xFF0111C4
+#define OID_RT_PRO_SET_BB_RF_SHUTDOWN_MODE 0xFF0111C5
+#define OID_RT_PRO_SET_TX_CHARGE_PUMP 0xFF0111C6
+#define OID_RT_PRO_SET_RX_CHARGE_PUMP 0xFF0111C7
+#define OID_RT_PRO_RF_WRITE_REGISTRY 0xFF0111C8
+#define OID_RT_PRO_RF_READ_REGISTRY 0xFF0111C9
+#define OID_RT_PRO_QUERY_RF_TYPE 0xFF0111CA
+
+/* AP OID */
+#define OID_RT_AP_GET_ASSOCIATED_STATION_LIST 0xFF010300
+#define OID_RT_AP_GET_CURRENT_TIME_STAMP 0xFF010301
+#define OID_RT_AP_SWITCH_INTO_AP_MODE 0xFF010302
+#define OID_RT_AP_SET_DTIM_PERIOD 0xFF010303
+/* Determine if driver supports AP mode. */
+#define OID_RT_AP_SUPPORTED 0xFF010304
+/* Set WPA-PSK passphrase into authenticator. */
+#define OID_RT_AP_SET_PASSPHRASE 0xFF010305
+
+/* 8187MP. 2004.09.06, by rcnjko. */
+#define OID_RT_PRO8187_WI_POLL 0xFF818780
+#define OID_RT_PRO_WRITE_BB_REG 0xFF818781
+#define OID_RT_PRO_READ_BB_REG 0xFF818782
+#define OID_RT_PRO_WRITE_RF_REG 0xFF818783
+#define OID_RT_PRO_READ_RF_REG 0xFF818784
+
+/* Meeting House. added by Annie, 2005-07-20. */
+#define OID_RT_MH_VENDER_ID 0xFFEDC100
+
+/* 8711 MP OID added 20051230. */
+#define OID_RT_PRO8711_JOIN_BSS 0xFF871100/* S */
+
+#define OID_RT_PRO_READ_REGISTER 0xFF871101 /* Q */
+#define OID_RT_PRO_WRITE_REGISTER 0xFF871102 /* S */
+
+#define OID_RT_PRO_BURST_READ_REGISTER 0xFF871103 /* Q */
+#define OID_RT_PRO_BURST_WRITE_REGISTER 0xFF871104 /* S */
+
+#define OID_RT_PRO_WRITE_TXCMD 0xFF871105 /* S */
+
+#define OID_RT_PRO_READ16_EEPROM 0xFF871106 /* Q */
+#define OID_RT_PRO_WRITE16_EEPROM 0xFF871107 /* S */
+
+#define OID_RT_PRO_H2C_SET_COMMAND 0xFF871108 /* S */
+#define OID_RT_PRO_H2C_QUERY_RESULT 0xFF871109 /* Q */
+
+#define OID_RT_PRO8711_WI_POLL 0xFF87110A /* Q */
+#define OID_RT_PRO8711_PKT_LOSS 0xFF87110B /* Q */
+#define OID_RT_RD_ATTRIB_MEM 0xFF87110C/* Q */
+#define OID_RT_WR_ATTRIB_MEM 0xFF87110D/* S */
+
+/* Method 2 for H2C/C2H */
+#define OID_RT_PRO_H2C_CMD_MODE 0xFF871110 /* S */
+#define OID_RT_PRO_H2C_CMD_RSP_MODE 0xFF871111 /* Q */
+#define OID_RT_PRO_H2C_CMD_EVENT_MODE 0xFF871112 /* S */
+#define OID_RT_PRO_WAIT_C2H_EVENT 0xFF871113 /* Q */
+#define OID_RT_PRO_RW_ACCESS_PROTOCOL_TEST 0xFF871114/* Q */
+
+#define OID_RT_PRO_SCSI_ACCESS_TEST 0xFF871115 /* Q, S */
+
+#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_OUT 0xFF871116 /* S */
+#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_IN 0xFF871117 /* Q,S */
+#define OID_RT_RRO_RX_PKT_VIA_IOCTRL 0xFF871118 /* Q */
+#define OID_RT_RRO_RX_PKTARRAY_VIA_IOCTRL 0xFF871119 /* Q */
+
+#define OID_RT_RPO_SET_PWRMGT_TEST 0xFF87111A /* S */
+#define OID_RT_PRO_QRY_PWRMGT_TEST 0XFF87111B /* Q */
+#define OID_RT_RPO_ASYNC_RWIO_TEST 0xFF87111C /* S */
+#define OID_RT_RPO_ASYNC_RWIO_POLL 0xFF87111D /* Q */
+#define OID_RT_PRO_SET_RF_INTFS 0xFF87111E /* S */
+#define OID_RT_POLL_RX_STATUS 0xFF87111F /* Q */
+
+#define OID_RT_PRO_CFG_DEBUG_MESSAGE 0xFF871120 /* Q,S */
+#define OID_RT_PRO_SET_DATA_RATE_EX 0xFF871121/* S */
+#define OID_RT_PRO_SET_BASIC_RATE 0xFF871122/* S */
+#define OID_RT_PRO_READ_TSSI 0xFF871123/* S */
+#define OID_RT_PRO_SET_POWER_TRACKING 0xFF871124/* S */
+
+#define OID_RT_PRO_QRY_PWRSTATE 0xFF871150 /* Q */
+#define OID_RT_PRO_SET_PWRSTATE 0xFF871151 /* S */
+
+/* Method 2 , using workitem */
+#define OID_RT_SET_READ_REG 0xFF871181 /* S */
+#define OID_RT_SET_WRITE_REG 0xFF871182 /* S */
+#define OID_RT_SET_BURST_READ_REG 0xFF871183 /* S */
+#define OID_RT_SET_BURST_WRITE_REG 0xFF871184 /* S */
+#define OID_RT_SET_WRITE_TXCMD 0xFF871185 /* S */
+#define OID_RT_SET_READ16_EEPROM 0xFF871186 /* S */
+#define OID_RT_SET_WRITE16_EEPROM 0xFF871187 /* S */
+#define OID_RT_QRY_POLL_WKITEM 0xFF871188 /* Q */
+
+/* For SDIO INTERFACE only */
+#define OID_RT_PRO_SYNCPAGERW_SRAM 0xFF8711A0 /* Q, S */
+#define OID_RT_PRO_871X_DRV_EXT 0xFF8711A1
+
+/* For USB INTERFACE only */
+#define OID_RT_PRO_USB_VENDOR_REQ 0xFF8711B0 /* Q, S */
+#define OID_RT_PRO_SCSI_AUTO_TEST 0xFF8711B1 /* S */
+#define OID_RT_PRO_USB_MAC_AC_FIFO_WRITE 0xFF8711B2 /* S */
+#define OID_RT_PRO_USB_MAC_RX_FIFO_READ 0xFF8711B3 /* Q */
+#define OID_RT_PRO_USB_MAC_RX_FIFO_POLLING 0xFF8711B4 /* Q */
+
+#define OID_RT_PRO_H2C_SET_RATE_TABLE 0xFF8711FB /* S */
+#define OID_RT_PRO_H2C_GET_RATE_TABLE 0xFF8711FC /* S */
+#define OID_RT_PRO_H2C_C2H_LBK_TEST 0xFF8711FE
+
+#define OID_RT_PRO_ENCRYPTION_CTRL 0xFF871200 /* Q, S */
+#define OID_RT_PRO_ADD_STA_INFO 0xFF871201 /* S */
+#define OID_RT_PRO_DELE_STA_INFO 0xFF871202 /* S */
+#define OID_RT_PRO_QUERY_DR_VARIABLE 0xFF871203 /* Q */
+
+#define OID_RT_PRO_RX_PACKET_TYPE 0xFF871204 /* Q, S */
+
+#define OID_RT_PRO_READ_EFUSE 0xFF871205 /* Q */
+#define OID_RT_PRO_WRITE_EFUSE 0xFF871206 /* S */
+#define OID_RT_PRO_RW_EFUSE_PGPKT 0xFF871207 /* Q, S */
+#define OID_RT_GET_EFUSE_CURRENT_SIZE 0xFF871208 /* Q */
+
+#define OID_RT_SET_BANDWIDTH 0xFF871209 /* S */
+#define OID_RT_SET_CRYSTAL_CAP 0xFF87120A /* S */
+
+#define OID_RT_SET_RX_PACKET_TYPE 0xFF87120B /* S */
+
+#define OID_RT_GET_EFUSE_MAX_SIZE 0xFF87120C /* Q */
+
+#define OID_RT_PRO_SET_TX_AGC_OFFSET 0xFF87120D /* S */
+
+#define OID_RT_PRO_SET_PKT_TEST_MODE 0xFF87120E /* S */
+
+#define OID_RT_PRO_FOR_EVM_TEST_SETTING 0xFF87120F /* S */
+
+#define OID_RT_PRO_GET_THERMAL_METER 0xFF871210 /* Q */
+
+#define OID_RT_RESET_PHY_RX_PACKET_COUNT 0xFF871211 /* S */
+#define OID_RT_GET_PHY_RX_PACKET_RECEIVED 0xFF871212 /* Q */
+#define OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR 0xFF871213 /* Q */
+
+#define OID_RT_SET_POWER_DOWN 0xFF871214 /* S */
+
+#define OID_RT_GET_POWER_MODE 0xFF871215 /* Q */
+
+#define OID_RT_PRO_EFUSE 0xFF871216 /* Q, S */
+#define OID_RT_PRO_EFUSE_MAP 0xFF871217 /* Q, S */
+
+#endif /* ifndef __CUSTOM_OID_H */
diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/r8188eu/include/odm.h
index 98402cfb1168..d9041ee576bb 100644
--- a/drivers/staging/rtl8188eu/include/odm.h
+++ b/drivers/staging/r8188eu/include/odm.h
@@ -1,9 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
#ifndef __HALDMOUTSRC_H__
#define __HALDMOUTSRC_H__
@@ -27,8 +23,7 @@
/* Mainly, it just retains last scan result and scan again. */
/* After that, it compares the scan result to see which one gets better
* RSSI. It selects antenna with better receiving power and returns better
- * scan result.
- */
+ * scan result. */
#define TP_MODE 0
#define RSSI_MODE 1
@@ -71,6 +66,19 @@
#define DM_DIG_FA_TH2_LPS 30 /* 30 lps */
#define RSSI_OFFSET_DIG 0x05;
+/* ANT Test */
+#define ANTTESTALL 0x00 /* Ant A or B will be Testing */
+#define ANTTESTA 0x01 /* Ant A will be Testing */
+#define ANTTESTB 0x02 /* Ant B will be testing */
+
+/* structure and define */
+
+/* Add for AP/ADSLpseudo DM structuer requirement. */
+/* We need to remove to other position??? */
+struct rtl8192cd_priv {
+ u8 temp;
+};
+
struct rtw_dig {
u8 Dig_Enable_Flag;
u8 Dig_Ext_Port_Stage;
@@ -115,16 +123,19 @@ struct rtw_dig {
};
struct rtl_ps {
- u8 PreCCAState;
- u8 CurCCAState;
+ u8 pre_cca_state;
+ u8 cur_cca_state;
- u8 PreRFState;
- u8 CurRFState;
+ u8 pre_rf_state;
+ u8 cur_rf_state;
- int Rssi_val_min;
+ int rssi_val_min;
u8 initialize;
- u32 Reg874, RegC70, Reg85C, RegA74;
+ u32 reg_874;
+ u32 reg_c70;
+ u32 reg_85c;
+ u32 reg_a74;
};
@@ -145,6 +156,14 @@ struct false_alarm_stats {
u32 Cnt_BW_LSC; /* Gary */
};
+struct dyn_primary_cca {
+ u8 pri_cca_flag;
+ u8 intf_flag;
+ u8 intf_type;
+ u8 dup_rts_flag;
+ u8 monitor_flag;
+};
+
struct rx_hpc {
u8 RXHP_flag;
u8 PSD_func_trigger;
@@ -164,12 +183,10 @@ struct rx_hpc {
/* This indicates two different steps. */
/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to
- * the signal on the air.
- */
+ * the signal on the air. */
/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in
* SWAW_STEP_PEAK with original RSSI to determine if it is necessary to
- * switch antenna.
- */
+ * switch antenna. */
#define SWAW_STEP_PEAK 0
#define SWAW_STEP_DETERMINE 1
@@ -237,12 +254,13 @@ struct odm_rate_adapt {
#define IQK_MAC_REG_NUM 4
#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM_MAX 10
#define IQK_BB_REG_NUM 9
#define HP_THERMAL_NUM 8
#define AVG_THERMAL_NUM 8
#define IQK_Matrix_REG_NUM 8
-#define IQK_Matrix_Settings_NUM (1 + 24 + 21)
+#define IQK_Matrix_Settings_NUM 1+24+21
#define DM_Type_ByFWi 0
#define DM_Type_ByDriver 1
@@ -257,8 +275,7 @@ struct odm_phy_status_info {
s8 RxPower; /* in dBm Translate from PWdB */
s8 RecvSignalPower;/* Real power in dBm for this packet, no
* beautification and aggregation. Keep this raw
- * info to be used for the other procedures.
- */
+ * info to be used for the other procedures. */
u8 BTRxRSSIPercentage;
u8 SignalStrength; /* in 0-100 index. */
u8 RxPwr[MAX_PATH_NUM_92CS];/* per-path's pwdb */
@@ -303,6 +320,22 @@ enum odm_ability {
ODM_PSD2AFH = 0x00000800
};
+/* 2011/20/20 MH For MP driver RT_WLAN_STA = struct sta_info */
+/* Please declare below ODM relative info in your STA info structure. */
+
+struct odm_sta_info {
+ /* Driver Write */
+ bool bUsed; /* record the sta status link or not? */
+ u8 IOTPeer; /* Enum value. HT_IOT_PEER_E */
+
+ /* ODM Write */
+ /* 1 PHY_STATUS_INFO */
+ u8 RSSI_Path[4]; /* */
+ u8 RSSI_Ave;
+ u8 RXEVM[4];
+ u8 RXSNR[4];
+};
+
/* 2011/10/20 MH Define Common info enum for all team. */
enum odm_common_info_def {
@@ -315,7 +348,8 @@ enum odm_common_info_def {
ODM_CMNINFO_MP_TEST_CHIP,
ODM_CMNINFO_IC_TYPE, /* ODM_IC_TYPE_E */
ODM_CMNINFO_CUT_VER, /* ODM_CUT_VERSION_E */
- ODM_CMNINFO_RF_TYPE, /* ODM_RF_PATH_E or ODM_RF_TYPE_E? */
+ ODM_CMNINFO_FAB_VER, /* ODM_FAB_E */
+ ODM_CMNINFO_RF_TYPE, /* RF_PATH_E or ODM_RF_TYPE_E? */
ODM_CMNINFO_BOARD_TYPE, /* ODM_BOARD_TYPE_E */
ODM_CMNINFO_EXT_LNA, /* true */
ODM_CMNINFO_EXT_PA,
@@ -357,8 +391,6 @@ enum odm_common_info_def {
ODM_CMNINFO_WIFI_DISPLAY,
ODM_CMNINFO_LINK,
ODM_CMNINFO_RSSI_MIN,
- ODM_CMNINFO_DBG_COMP, /* u64 */
- ODM_CMNINFO_DBG_LEVEL, /* u32 */
ODM_CMNINFO_RA_THRESHOLD_HIGH, /* u8 */
ODM_CMNINFO_RA_THRESHOLD_LOW, /* u8 */
ODM_CMNINFO_RF_ANTENNA_TYPE, /* u8 */
@@ -404,7 +436,29 @@ enum odm_ability_def {
ODM_RF_CALIBRATION = BIT(26),
};
-#define ODM_RTL8188E BIT(4)
+/* ODM_CMNINFO_INTERFACE */
+enum odm_interface_def {
+ ODM_ITRF_PCIE = 0x1,
+ ODM_ITRF_USB = 0x2,
+ ODM_ITRF_SDIO = 0x4,
+ ODM_ITRF_ALL = 0x7,
+};
+
+/* ODM_CMNINFO_IC_TYPE */
+enum odm_ic_type {
+ ODM_RTL8192S = BIT(0),
+ ODM_RTL8192C = BIT(1),
+ ODM_RTL8192D = BIT(2),
+ ODM_RTL8723A = BIT(3),
+ ODM_RTL8188E = BIT(4),
+ ODM_RTL8812 = BIT(5),
+ ODM_RTL8821 = BIT(6),
+};
+
+#define ODM_IC_11N_SERIES \
+ (ODM_RTL8192S | ODM_RTL8192C | ODM_RTL8192D | \
+ ODM_RTL8723A | ODM_RTL8188E)
+#define ODM_IC_11AC_SERIES (ODM_RTL8812)
/* ODM_CMNINFO_CUT_VER */
enum odm_cut_version {
@@ -417,8 +471,14 @@ enum odm_cut_version {
ODM_CUT_TEST = 7,
};
+/* ODM_CMNINFO_FAB_VER */
+enum odm_fab_Version {
+ ODM_TSMC = 0,
+ ODM_UMC = 1,
+};
+
/* ODM_CMNINFO_RF_TYPE */
-/* For example 1T2R (A+AB = BIT0|BIT4|BIT5) */
+/* For example 1T2R (A+AB = BIT(0)|BIT(4)|BIT(5)) */
enum odm_rf_path {
ODM_RF_TX_A = BIT(0),
ODM_RF_TX_B = BIT(1),
@@ -471,20 +531,16 @@ enum odm_operation_mode {
/* ODM_CMNINFO_WM_MODE */
enum odm_wireless_mode {
- ODM_WM_UNKNOWN = 0x0,
+ ODM_WM_UNKNOW = 0x0,
ODM_WM_B = BIT(0),
ODM_WM_G = BIT(1),
- ODM_WM_A = BIT(2),
ODM_WM_N24G = BIT(3),
- ODM_WM_N5G = BIT(4),
ODM_WM_AUTO = BIT(5),
- ODM_WM_AC = BIT(6),
};
/* ODM_CMNINFO_BAND */
enum odm_band_type {
ODM_BAND_2_4G = BIT(0),
- ODM_BAND_5G = BIT(1),
};
/* ODM_CMNINFO_SEC_CHNL_OFFSET */
@@ -502,7 +558,7 @@ enum odm_security {
ODM_SEC_RESERVE = 3,
ODM_SEC_AESCCMP = 4,
ODM_SEC_WEP104 = 5,
- ODM_WEP_WPA_MIXED = 6, /* WEP + WPA */
+ ODM_WEP_WPA_MIXED = 6, /* WEP + WPA */
ODM_SEC_SMS4 = 7,
};
@@ -510,9 +566,6 @@ enum odm_security {
enum odm_bw {
ODM_BW20M = 0,
ODM_BW40M = 1,
- ODM_BW80M = 2,
- ODM_BW160M = 3,
- ODM_BW10M = 4,
};
/* ODM_CMNINFO_BOARD_TYPE */
@@ -560,8 +613,7 @@ struct odm_ra_info {
u8 PTPreRssi; /* if RSSI change 5% do PT */
u8 PTModeSS; /* decide whitch rate should do PT */
u8 RAstage; /* StageRA, decide how many times RA will be done
- * between PT
- */
+ * between PT */
u8 PTSmoothFactor;
};
@@ -579,16 +631,15 @@ struct odm_rf_cal {
s32 RegEBC;
u8 TXPowercount;
+ bool bTXPowerTrackingInit;
bool bTXPowerTracking;
u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking
- * as default
- */
+ * as default */
u8 TM_Trigger;
u8 InternalPA5G[2]; /* pathA / pathB */
u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0,
- * and 1 for RFIC1
- */
+ * and 1 for RFIC1 */
u8 ThermalValue;
u8 ThermalValue_LCK;
u8 ThermalValue_IQK;
@@ -684,7 +735,7 @@ enum ant_div_type {
/* Copy from SD4 defined structure. We use to support PHY DM integration. */
struct odm_dm_struct {
- /* Add for different team use temporarily */
+ /* Add for different team use temporarily */
struct adapter *Adapter; /* For CE/NIC team */
struct rtl8192cd_priv *priv; /* For AP/ADSL team */
/* WHen you use above pointers, they must be initialized. */
@@ -703,16 +754,19 @@ struct odm_dm_struct {
/* HOOK BEFORE REG INIT----------- */
/* ODM Platform info AP/ADSL/CE/MP = 1/2/3/4 */
u8 SupportPlatform;
- /* ODM Support Ability DIG/RATR/TX_PWR_TRACK/... = 1/2/3/... */
+ /* ODM Support Ability DIG/RATR/TX_PWR_TRACK/ �K�K = 1/2/3/�K */
u32 SupportAbility;
/* ODM PCIE/USB/SDIO/GSPI = 0/1/2/3 */
u8 SupportInterface;
/* ODM composite or independent. Bit oriented/ 92C+92D+ .... or any
- * other type = 1/2/3/...
- */
+ * other type = 1/2/3/... */
u32 SupportICType;
/* Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */
u8 CutVersion;
+ /* Fab Version TSMC/UMC = 0/1 */
+ u8 FabVersion;
+ /* RF Type 4T4R/3T3R/2T2R/1T2R/1T1R/... */
+ u8 RFType;
/* Board Type Normal/HighPower/MiniCard/SLIM/Combo/. = 0/1/2/3/4/. */
u8 BoardType;
/* with external LNA NO/Yes = 0/1 */
@@ -743,7 +797,7 @@ struct odm_dm_struct {
u64 *pNumTxBytesUnicast;
/* RX Unicast byte count */
u64 *pNumRxBytesUnicast;
- /* Wireless mode B/G/A/N = BIT0/BIT1/BIT2/BIT3 */
+ /* Wireless mode B/G/A/N = BIT(0)/BIT(1)/BIT(2)/BIT(3) */
u8 *pWirelessMode; /* ODM_WIRELESS_MODE_E */
/* Frequence band 2.4G/5G = 0/1 */
u8 *pBandType;
@@ -783,21 +837,19 @@ struct odm_dm_struct {
bool bBtHsOperation; /* BT HS mode is under progress */
u8 btHsDigVal; /* use BT rssi to decide the DIG value */
bool bBtDisableEdcaTurbo;/* Under some condition, don't enable the
- * EDCA Turbo
- */
+ * EDCA Turbo */
bool bBtBusy; /* BT is busy. */
/* CALL BY VALUE------------- */
/* 2 Define STA info. */
/* _ODM_STA_INFO */
- /* For MP, we need to reduce one array pointer for default port.??*/
+ /* For MP, we need to reduce one array pointer for default port.?? */
struct sta_info *pODM_StaInfo[ODM_ASSOCIATE_ENTRY_NUM];
u16 CurrminRptTime;
struct odm_ra_info RAInfo[ODM_ASSOCIATE_ENTRY_NUM]; /* Use MacID as
- * array index. STA MacID=0,
- * VWiFi Client MacID={1, ODM_ASSOCIATE_ENTRY_NUM-1}
- */
+ * array index. STA MacID=0,
+ * VWiFi Client MacID={1, ODM_ASSOCIATE_ENTRY_NUM-1} */
/* */
/* 2012/02/14 MH Add to share 88E ra with other SW team. */
/* We need to colelct all support abilit to a proper area. */
@@ -818,6 +870,7 @@ struct odm_dm_struct {
struct fast_ant_train DM_FatTable;
struct rtw_dig DM_DigTable;
struct rtl_ps DM_PSTable;
+ struct dyn_primary_cca DM_PriCCA;
struct rx_hpc DM_RXHP_Table;
struct false_alarm_stats FalseAlmCnt;
struct false_alarm_stats FlaseAlmCntBuddyAdapter;
@@ -868,8 +921,6 @@ struct odm_dm_struct {
struct timer_list FastAntTrainingTimer;
}; /* DM_Dynamic_Mechanism_Structure */
-#define ODM_RF_PATH_MAX 3
-
enum ODM_RF_CONTENT {
odm_radioa_txt = 0x1000,
odm_radiob_txt = 0x1001,
@@ -877,6 +928,13 @@ enum ODM_RF_CONTENT {
odm_radiod_txt = 0x1003
};
+enum odm_bb_config_type {
+ CONFIG_BB_PHY_REG,
+ CONFIG_BB_AGC_TAB,
+ CONFIG_BB_AGC_TAB_2G,
+ CONFIG_BB_PHY_REG_PG,
+};
+
/* Status code */
enum rt_status {
RT_STATUS_SUCCESS,
@@ -1017,43 +1075,80 @@ enum dm_swas {
extern u32 OFDMSwingTable[OFDM_TABLE_SIZE_92D];
extern u8 CCKSwingTable_Ch1_Ch13[CCK_TABLE_SIZE][8];
-extern u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8];
+extern u8 CCKSwingTable_Ch14 [CCK_TABLE_SIZE][8];
/* check Sta pointer valid or not */
#define IS_STA_VALID(pSta) (pSta)
/* 20100514 Joseph: Add definition for antenna switching test after link. */
/* This indicates two different the steps. */
/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the
- * signal on the air.
- */
+ * signal on the air. */
/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in
- * SWAW_STEP_PEAK
- */
+ * SWAW_STEP_PEAK */
/* with original RSSI to determine if it is necessary to switch antenna. */
#define SWAW_STEP_PEAK 0
#define SWAW_STEP_DETERMINE 1
-#define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck
-#define dm_RF_Saving ODM_RF_Saving
+void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI);
+void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres);
+void ODM_SetAntenna(struct odm_dm_struct *pDM_Odm, u8 Antenna);
+
+#define dm_RF_Saving ODM_RF_Saving
void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal);
+
+#define SwAntDivRestAfterLink ODM_SwAntDivRestAfterLink
+void ODM_SwAntDivRestAfterLink(struct odm_dm_struct *pDM_Odm);
+
+#define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck
void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm);
-void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres);
+
bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI,
bool bForceUpdate, u8 *pRATRState);
+
+#define dm_SWAW_RSSI_Check ODM_SwAntDivChkPerPktRssi
+void ODM_SwAntDivChkPerPktRssi(struct odm_dm_struct *pDM_Odm, u8 StationID,
+ struct odm_phy_status_info *pPhyInfo);
+
u32 ConvertTo_dB(u32 Value);
+
+u32 GetPSDData(struct odm_dm_struct *pDM_Odm, unsigned int point,
+ u8 initial_gain_psd);
+
+void odm_DIGbyRSSI_LPS(struct odm_dm_struct *pDM_Odm);
+
u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid,
u32 ra_mask, u8 rssi_level);
+
+void ODM_DMInit(struct odm_dm_struct *pDM_Odm);
+
+void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm);
+
void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm,
enum odm_common_info_def CmnInfo, u32 Value);
-void ODM_CmnInfoUpdate(struct odm_dm_struct *pDM_Odm, u32 CmnInfo, u64 Value);
+
void ODM_CmnInfoHook(struct odm_dm_struct *pDM_Odm,
enum odm_common_info_def CmnInfo, void *pValue);
+
void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm,
enum odm_common_info_def CmnInfo,
u16 Index, void *pValue);
-void ODM_DMInit(struct odm_dm_struct *pDM_Odm);
-void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm);
-void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI);
+
+void ODM_CmnInfoUpdate(struct odm_dm_struct *pDM_Odm, u32 CmnInfo, u64 Value);
+
+void ODM_InitAllTimers(struct odm_dm_struct *pDM_Odm);
+
+void ODM_CancelAllTimers(struct odm_dm_struct *pDM_Odm);
+
+void ODM_ReleaseAllTimers(struct odm_dm_struct *pDM_Odm);
+
+void ODM_AntselStatistics_88C(struct odm_dm_struct *pDM_Odm, u8 MacId,
+ u32 PWDBAll, bool isCCKrate);
+
+void ODM_SingleDualAntennaDefaultSetting(struct odm_dm_struct *pDM_Odm);
+
+bool ODM_SingleDualAntennaDetection(struct odm_dm_struct *pDM_Odm, u8 mode);
+
+void odm_dtc(struct odm_dm_struct *pDM_Odm);
#endif
diff --git a/drivers/staging/rtl8188eu/include/odm_hwconfig.h b/drivers/staging/r8188eu/include/odm_HWConfig.h
index 4f4d3cfb6c77..9b2ab3bcf992 100644
--- a/drivers/staging/rtl8188eu/include/odm_hwconfig.h
+++ b/drivers/staging/r8188eu/include/odm_HWConfig.h
@@ -1,9 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
#ifndef __HALHWOUTSRC_H__
#define __HALHWOUTSRC_H__
@@ -56,7 +52,7 @@ struct phy_rx_agc_info {
};
struct phy_status_rpt {
- struct phy_rx_agc_info path_agc[RF_PATH_MAX];
+ struct phy_rx_agc_info path_agc[3];
u8 ch_corr[2];
u8 cck_sig_qual_ofdm_pwdb_all;
u8 cck_agc_rpt_ofdm_cfosho_a;
@@ -93,9 +89,28 @@ struct phy_status_rpt {
#endif
};
-void odm_phy_status_query(struct odm_dm_struct *dm_odm,
- struct odm_phy_status_info *phy_info,
- u8 *phy_status,
- struct odm_per_pkt_info *pkt_info);
+void odm_Init_RSSIForDM(struct odm_dm_struct *pDM_Odm);
+
+void ODM_PhyStatusQuery(struct odm_dm_struct *pDM_Odm,
+ struct odm_phy_status_info *pPhyInfo,
+ u8 *pPhyStatus,
+ struct odm_per_pkt_info *pPktinfo,
+ struct adapter *adapt);
+
+void ODM_MacStatusQuery(struct odm_dm_struct *pDM_Odm,
+ u8 *pMacStatus,
+ u8 MacID,
+ bool bPacketMatchBSSID,
+ bool bPacketToSelf,
+ bool bPacketBeacon);
+
+enum HAL_STATUS ODM_ConfigRFWithHeaderFile(struct odm_dm_struct *pDM_Odm,
+ enum rf_radio_path Content,
+ enum rf_radio_path eRFPath);
+
+enum HAL_STATUS ODM_ConfigBBWithHeaderFile(struct odm_dm_struct *pDM_Odm,
+ enum odm_bb_config_type ConfigType);
+
+enum HAL_STATUS ODM_ConfigMACWithHeaderFile(struct odm_dm_struct *pDM_Odm);
#endif
diff --git a/drivers/staging/r8188eu/include/odm_RTL8188E.h b/drivers/staging/r8188eu/include/odm_RTL8188E.h
new file mode 100644
index 000000000000..00d2678532f8
--- /dev/null
+++ b/drivers/staging/r8188eu/include/odm_RTL8188E.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __ODM_RTL8188E_H__
+#define __ODM_RTL8188E_H__
+
+#define MAIN_ANT 0
+#define AUX_ANT 1
+#define MAIN_ANT_CG_TRX 1
+#define AUX_ANT_CG_TRX 0
+#define MAIN_ANT_CGCS_RX 0
+#define AUX_ANT_CGCS_RX 1
+
+void ODM_DIG_LowerBound_88E(struct odm_dm_struct *pDM_Odm);
+
+void ODM_AntennaDiversityInit_88E(struct odm_dm_struct *pDM_Odm);
+
+void ODM_AntennaDiversity_88E(struct odm_dm_struct *pDM_Odm);
+
+void ODM_SetTxAntByTxInfo_88E(struct odm_dm_struct *pDM_Odm, u8 *pDesc,
+ u8 macId);
+
+void ODM_UpdateRxIdleAnt_88E(struct odm_dm_struct *pDM_Odm, u8 Ant);
+
+void ODM_AntselStatistics_88E(struct odm_dm_struct *pDM_Odm, u8 antsel_tr_mux,
+ u32 MacId, u8 RxPWDBAll);
+
+void odm_FastAntTraining(struct odm_dm_struct *pDM_Odm);
+
+void odm_FastAntTrainingCallback(struct odm_dm_struct *pDM_Odm);
+
+void odm_FastAntTrainingWorkItemCallback(struct odm_dm_struct *pDM_Odm);
+
+void odm_PrimaryCCA_Init(struct odm_dm_struct *pDM_Odm);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/odm_RegConfig8188E.h b/drivers/staging/r8188eu/include/odm_RegConfig8188E.h
new file mode 100644
index 000000000000..86b5b2d24210
--- /dev/null
+++ b/drivers/staging/r8188eu/include/odm_RegConfig8188E.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __INC_ODM_REGCONFIG_H_8188E
+#define __INC_ODM_REGCONFIG_H_8188E
+
+void odm_ConfigRFReg_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Data,
+ enum rf_radio_path RF_PATH, u32 RegAddr);
+
+void odm_ConfigRF_RadioA_8188E(struct odm_dm_struct *pDM_Odm,
+ u32 Addr, u32 Data);
+
+void odm_ConfigRF_RadioB_8188E(struct odm_dm_struct *pDM_Odm,
+ u32 Addr, u32 Data);
+
+void odm_ConfigMAC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u8 Data);
+
+void odm_ConfigBB_AGC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr,
+ u32 Bitmask, u32 Data);
+
+void odm_ConfigBB_PHY_REG_PG_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr,
+ u32 Bitmask, u32 Data);
+
+void odm_ConfigBB_PHY_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr,
+ u32 Bitmask, u32 Data);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/odm_RegDefine11AC.h b/drivers/staging/r8188eu/include/odm_RegDefine11AC.h
new file mode 100644
index 000000000000..bba7511cf244
--- /dev/null
+++ b/drivers/staging/r8188eu/include/odm_RegDefine11AC.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __ODM_REGDEFINE11AC_H__
+#define __ODM_REGDEFINE11AC_H__
+
+/* 2 RF REG LIST */
+
+/* 2 BB REG LIST */
+/* PAGE 8 */
+/* PAGE 9 */
+#define ODM_REG_OFDM_FA_RST_11AC 0x9A4
+/* PAGE A */
+#define ODM_REG_CCK_CCA_11AC 0xA0A
+#define ODM_REG_CCK_FA_RST_11AC 0xA2C
+#define ODM_REG_CCK_FA_11AC 0xA5C
+/* PAGE C */
+#define ODM_REG_IGI_A_11AC 0xC50
+/* PAGE E */
+#define ODM_REG_IGI_B_11AC 0xE50
+/* PAGE F */
+#define ODM_REG_OFDM_FA_11AC 0xF48
+
+/* 2 MAC REG LIST */
+
+/* DIG Related */
+#define ODM_BIT_IGI_11AC 0xFFFFFFFF
+
+#endif
diff --git a/drivers/staging/r8188eu/include/odm_RegDefine11N.h b/drivers/staging/r8188eu/include/odm_RegDefine11N.h
new file mode 100644
index 000000000000..5d1d73490c1c
--- /dev/null
+++ b/drivers/staging/r8188eu/include/odm_RegDefine11N.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __ODM_REGDEFINE11N_H__
+#define __ODM_REGDEFINE11N_H__
+
+/* 2 RF REG LIST */
+#define ODM_REG_RF_MODE_11N 0x00
+#define ODM_REG_RF_0B_11N 0x0B
+#define ODM_REG_CHNBW_11N 0x18
+#define ODM_REG_T_METER_11N 0x24
+#define ODM_REG_RF_25_11N 0x25
+#define ODM_REG_RF_26_11N 0x26
+#define ODM_REG_RF_27_11N 0x27
+#define ODM_REG_RF_2B_11N 0x2B
+#define ODM_REG_RF_2C_11N 0x2C
+#define ODM_REG_RXRF_A3_11N 0x3C
+#define ODM_REG_T_METER_92D_11N 0x42
+#define ODM_REG_T_METER_88E_11N 0x42
+
+/* 2 BB REG LIST */
+/* PAGE 8 */
+#define ODM_REG_BB_CTRL_11N 0x800
+#define ODM_REG_RF_PIN_11N 0x804
+#define ODM_REG_PSD_CTRL_11N 0x808
+#define ODM_REG_TX_ANT_CTRL_11N 0x80C
+#define ODM_REG_BB_PWR_SAV5_11N 0x818
+#define ODM_REG_CCK_RPT_FORMAT_11N 0x824
+#define ODM_REG_RX_DEFUALT_A_11N 0x858
+#define ODM_REG_RX_DEFUALT_B_11N 0x85A
+#define ODM_REG_BB_PWR_SAV3_11N 0x85C
+#define ODM_REG_ANTSEL_CTRL_11N 0x860
+#define ODM_REG_RX_ANT_CTRL_11N 0x864
+#define ODM_REG_PIN_CTRL_11N 0x870
+#define ODM_REG_BB_PWR_SAV1_11N 0x874
+#define ODM_REG_ANTSEL_PATH_11N 0x878
+#define ODM_REG_BB_3WIRE_11N 0x88C
+#define ODM_REG_SC_CNT_11N 0x8C4
+#define ODM_REG_PSD_DATA_11N 0x8B4
+/* PAGE 9 */
+#define ODM_REG_ANT_MAPPING1_11N 0x914
+#define ODM_REG_ANT_MAPPING2_11N 0x918
+/* PAGE A */
+#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00
+#define ODM_REG_CCK_CCA_11N 0xA0A
+#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C
+#define ODM_REG_CCK_ANTDIV_PARA3_11N 0xA10
+#define ODM_REG_CCK_ANTDIV_PARA4_11N 0xA14
+#define ODM_REG_CCK_FILTER_PARA1_11N 0xA22
+#define ODM_REG_CCK_FILTER_PARA2_11N 0xA23
+#define ODM_REG_CCK_FILTER_PARA3_11N 0xA24
+#define ODM_REG_CCK_FILTER_PARA4_11N 0xA25
+#define ODM_REG_CCK_FILTER_PARA5_11N 0xA26
+#define ODM_REG_CCK_FILTER_PARA6_11N 0xA27
+#define ODM_REG_CCK_FILTER_PARA7_11N 0xA28
+#define ODM_REG_CCK_FILTER_PARA8_11N 0xA29
+#define ODM_REG_CCK_FA_RST_11N 0xA2C
+#define ODM_REG_CCK_FA_MSB_11N 0xA58
+#define ODM_REG_CCK_FA_LSB_11N 0xA5C
+#define ODM_REG_CCK_CCA_CNT_11N 0xA60
+#define ODM_REG_BB_PWR_SAV4_11N 0xA74
+/* PAGE B */
+#define ODM_REG_LNA_SWITCH_11N 0xB2C
+#define ODM_REG_PATH_SWITCH_11N 0xB30
+#define ODM_REG_RSSI_CTRL_11N 0xB38
+#define ODM_REG_CONFIG_ANTA_11N 0xB68
+#define ODM_REG_RSSI_BT_11N 0xB9C
+/* PAGE C */
+#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00
+#define ODM_REG_RX_PATH_11N 0xC04
+#define ODM_REG_TRMUX_11N 0xC08
+#define ODM_REG_OFDM_FA_RSTC_11N 0xC0C
+#define ODM_REG_RXIQI_MATRIX_11N 0xC14
+#define ODM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C
+#define ODM_REG_IGI_A_11N 0xC50
+#define ODM_REG_ANTDIV_PARA2_11N 0xC54
+#define ODM_REG_IGI_B_11N 0xC58
+#define ODM_REG_ANTDIV_PARA3_11N 0xC5C
+#define ODM_REG_BB_PWR_SAV2_11N 0xC70
+#define ODM_REG_RX_OFF_11N 0xC7C
+#define ODM_REG_TXIQK_MATRIXA_11N 0xC80
+#define ODM_REG_TXIQK_MATRIXB_11N 0xC88
+#define ODM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94
+#define ODM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C
+#define ODM_REG_RXIQK_MATRIX_LSB_11N 0xCA0
+#define ODM_REG_ANTDIV_PARA1_11N 0xCA4
+#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0
+/* PAGE D */
+#define ODM_REG_OFDM_FA_RSTD_11N 0xD00
+#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0
+#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4
+#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8
+/* PAGE E */
+#define ODM_REG_TXAGC_A_6_18_11N 0xE00
+#define ODM_REG_TXAGC_A_24_54_11N 0xE04
+#define ODM_REG_TXAGC_A_1_MCS32_11N 0xE08
+#define ODM_REG_TXAGC_A_MCS0_3_11N 0xE10
+#define ODM_REG_TXAGC_A_MCS4_7_11N 0xE14
+#define ODM_REG_TXAGC_A_MCS8_11_11N 0xE18
+#define ODM_REG_TXAGC_A_MCS12_15_11N 0xE1C
+#define ODM_REG_FPGA0_IQK_11N 0xE28
+#define ODM_REG_TXIQK_TONE_A_11N 0xE30
+#define ODM_REG_RXIQK_TONE_A_11N 0xE34
+#define ODM_REG_TXIQK_PI_A_11N 0xE38
+#define ODM_REG_RXIQK_PI_A_11N 0xE3C
+#define ODM_REG_TXIQK_11N 0xE40
+#define ODM_REG_RXIQK_11N 0xE44
+#define ODM_REG_IQK_AGC_PTS_11N 0xE48
+#define ODM_REG_IQK_AGC_RSP_11N 0xE4C
+#define ODM_REG_BLUETOOTH_11N 0xE6C
+#define ODM_REG_RX_WAIT_CCA_11N 0xE70
+#define ODM_REG_TX_CCK_RFON_11N 0xE74
+#define ODM_REG_TX_CCK_BBON_11N 0xE78
+#define ODM_REG_OFDM_RFON_11N 0xE7C
+#define ODM_REG_OFDM_BBON_11N 0xE80
+#define ODM_REG_TX2RX_11N 0xE84
+#define ODM_REG_TX2TX_11N 0xE88
+#define ODM_REG_RX_CCK_11N 0xE8C
+#define ODM_REG_RX_OFDM_11N 0xED0
+#define ODM_REG_RX_WAIT_RIFS_11N 0xED4
+#define ODM_REG_RX2RX_11N 0xED8
+#define ODM_REG_STANDBY_11N 0xEDC
+#define ODM_REG_SLEEP_11N 0xEE0
+#define ODM_REG_PMPD_ANAEN_11N 0xEEC
+
+/* 2 MAC REG LIST */
+#define ODM_REG_BB_RST_11N 0x02
+#define ODM_REG_ANTSEL_PIN_11N 0x4C
+#define ODM_REG_EARLY_MODE_11N 0x4D0
+#define ODM_REG_RSSI_MONITOR_11N 0x4FE
+#define ODM_REG_EDCA_VO_11N 0x500
+#define ODM_REG_EDCA_VI_11N 0x504
+#define ODM_REG_EDCA_BE_11N 0x508
+#define ODM_REG_EDCA_BK_11N 0x50C
+#define ODM_REG_TXPAUSE_11N 0x522
+#define ODM_REG_RESP_TX_11N 0x6D8
+#define ODM_REG_ANT_TRAIN_PARA1_11N 0x7b0
+#define ODM_REG_ANT_TRAIN_PARA2_11N 0x7b4
+
+/* DIG Related */
+#define ODM_BIT_IGI_11N 0x0000007F
+
+#endif
diff --git a/drivers/staging/r8188eu/include/odm_interface.h b/drivers/staging/r8188eu/include/odm_interface.h
new file mode 100644
index 000000000000..6b589413d56c
--- /dev/null
+++ b/drivers/staging/r8188eu/include/odm_interface.h
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __ODM_INTERFACE_H__
+#define __ODM_INTERFACE_H__
+
+/* */
+/* =========== Constant/Structure/Enum/... Define */
+/* */
+
+/* */
+/* =========== Macro Define */
+/* */
+
+#define _reg_all(_name) ODM_##_name
+#define _reg_ic(_name, _ic) ODM_##_name##_ic
+#define _bit_all(_name) BIT_##_name
+#define _bit_ic(_name, _ic) BIT_##_name##_ic
+
+/* _cat: implemented by Token-Pasting Operator. */
+
+/*===================================
+
+#define ODM_REG_DIG_11N 0xC50
+#define ODM_REG_DIG_11AC 0xDDD
+
+ODM_REG(DIG,_pDM_Odm)
+=====================================*/
+
+#define _reg_11N(_name) ODM_REG_##_name##_11N
+#define _reg_11AC(_name) ODM_REG_##_name##_11AC
+#define _bit_11N(_name) ODM_BIT_##_name##_11N
+#define _bit_11AC(_name) ODM_BIT_##_name##_11AC
+
+#define _cat(_name, _ic_type, _func) \
+ ( \
+ ((_ic_type) & ODM_IC_11N_SERIES) ? _func##_11N(_name) : \
+ _func##_11AC(_name) \
+ )
+
+/* _name: name of register or bit. */
+/* Example: "ODM_REG(R_A_AGC_CORE1, pDM_Odm)" */
+/* gets "ODM_R_A_AGC_CORE1" or "ODM_R_A_AGC_CORE1_8192C",
+ * depends on SupportICType. */
+#define ODM_REG(_name, _pDM_Odm) _cat(_name, _pDM_Odm->SupportICType, _reg)
+#define ODM_BIT(_name, _pDM_Odm) _cat(_name, _pDM_Odm->SupportICType, _bit)
+
+enum odm_h2c_cmd {
+ ODM_H2C_RSSI_REPORT = 0,
+ ODM_H2C_PSD_RESULT= 1,
+ ODM_H2C_PathDiv = 2,
+ ODM_MAX_H2CCMD
+};
+
+/* 2012/02/17 MH For non-MP compile pass only. Linux does not support workitem. */
+/* Suggest HW team to use thread instead of workitem. Windows also support the feature. */
+typedef void (*RT_WORKITEM_CALL_BACK)(void *pContext);
+
+/* =========== Extern Variable ??? It should be forbidden. */
+
+/* =========== EXtern Function Prototype */
+
+u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+
+u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+
+u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+
+void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data);
+
+void ODM_Write2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 Data);
+
+void ODM_Write4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 Data);
+
+void ODM_SetMACReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr,
+ u32 BitMask, u32 Data);
+
+u32 ODM_GetMACReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask);
+
+void ODM_SetBBReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr,
+ u32 BitMask, u32 Data);
+
+u32 ODM_GetBBReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask);
+
+void ODM_SetRFReg(struct odm_dm_struct *pDM_Odm, enum rf_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask, u32 Data);
+
+u32 ODM_GetRFReg(struct odm_dm_struct *pDM_Odm, enum rf_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask);
+
+/* Memory Relative Function. */
+void ODM_AllocateMemory(struct odm_dm_struct *pDM_Odm, void **pPtr, u32 length);
+void ODM_FreeMemory(struct odm_dm_struct *pDM_Odm, void *pPtr, u32 length);
+
+s32 ODM_CompareMemory(struct odm_dm_struct *pDM_Odm, void *pBuf1, void *pBuf2,
+ u32 length);
+
+/* ODM MISC-spin lock relative API. */
+void ODM_AcquireSpinLock(struct odm_dm_struct *pDM_Odm,
+ enum RT_SPINLOCK_TYPE type);
+
+void ODM_ReleaseSpinLock(struct odm_dm_struct *pDM_Odm,
+ enum RT_SPINLOCK_TYPE type);
+
+/* ODM MISC-workitem relative API. */
+void ODM_InitializeWorkItem(struct odm_dm_struct *pDM_Odm, void *pRtWorkItem,
+ RT_WORKITEM_CALL_BACK RtWorkItemCallback,
+ void *pContext, const char *szID);
+
+void ODM_StartWorkItem(void *pRtWorkItem);
+
+void ODM_StopWorkItem(void *pRtWorkItem);
+
+void ODM_FreeWorkItem(void *pRtWorkItem);
+
+void ODM_ScheduleWorkItem(void *pRtWorkItem);
+
+void ODM_IsWorkItemScheduled(void *pRtWorkItem);
+
+/* ODM Timer relative API. */
+void ODM_StallExecution(u32 usDelay);
+
+void ODM_delay_ms(u32 ms);
+
+void ODM_delay_us(u32 us);
+
+void ODM_sleep_ms(u32 ms);
+
+void ODM_sleep_us(u32 us);
+
+void ODM_SetTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer,
+ u32 msDelay);
+
+void ODM_InitializeTimer(struct odm_dm_struct *pDM_Odm,
+ struct timer_list *pTimer, void *CallBackFunc,
+ void *pContext, const char *szID);
+
+void ODM_CancelTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer);
+
+void ODM_ReleaseTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer);
+
+/* ODM FW relative API. */
+u32 ODM_FillH2CCmd(u8 *pH2CBuffer, u32 H2CBufferLen, u32 CmdNum,
+ u32 *pElementID, u32 *pCmdLen, u8 **pCmbBuffer,
+ u8 *CmdStartSeq);
+
+#endif /* __ODM_INTERFACE_H__ */
diff --git a/drivers/staging/rtl8188eu/include/odm_precomp.h b/drivers/staging/r8188eu/include/odm_precomp.h
index eb2b8b613aad..a1d6d674bda6 100644
--- a/drivers/staging/rtl8188eu/include/odm_precomp.h
+++ b/drivers/staging/r8188eu/include/odm_precomp.h
@@ -1,9 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. i*/
#ifndef __ODM_PRECOMP_H__
#define __ODM_PRECOMP_H__
@@ -14,23 +10,30 @@
/* 2 Config Flags and Structs - defined by each ODM Type */
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <hal_intf.h>
-#include <usb_ops_linux.h>
+#include "osdep_service.h"
+#include "drv_types.h"
+#include "hal_intf.h"
/* 2 OutSrc Header Files */
#include "odm.h"
-#include "odm_hwconfig.h"
-#include "phydm_regdefine11n.h"
+#include "odm_HWConfig.h"
+#include "odm_RegDefine11AC.h"
+#include "odm_RegDefine11N.h"
-#include "hal8188e_rate_adaptive.h" /* for RA,Power training */
+#include "HalPhyRf_8188e.h"/* for IQK,LCK,Power-tracking */
+#include "Hal8188ERateAdaptive.h"/* for RA,Power training */
#include "rtl8188e_hal.h"
-#include "phydm_reg.h"
+#include "odm_interface.h"
+#include "odm_reg.h"
-#include "odm_rtl8188e.h"
+#include "HalHWImg8188E_MAC.h"
+#include "HalHWImg8188E_RF.h"
+#include "HalHWImg8188E_BB.h"
+
+#include "odm_RegConfig8188E.h"
+#include "odm_RTL8188E.h"
void odm_DIGInit(struct odm_dm_struct *pDM_Odm);
void odm_RateAdaptiveMaskInit(struct odm_dm_struct *pDM_Odm);
@@ -39,6 +42,7 @@ void odm_DynamicTxPowerInit(struct odm_dm_struct *pDM_Odm);
void odm_TXPowerTrackingInit(struct odm_dm_struct *pDM_Odm);
void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm);
void odm_SwAntDivInit_NIC(struct odm_dm_struct *pDM_Odm);
+void odm_GlobalAdapterCheck(void);
void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm);
void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm);
void odm_DIG(struct odm_dm_struct *pDM_Odm);
@@ -47,16 +51,25 @@ void odm_RefreshRateAdaptiveMaskMP(struct odm_dm_struct *pDM_Odm);
void odm_DynamicBBPowerSaving(struct odm_dm_struct *pDM_Odm);
void odm_SwAntDivChkAntSwitch(struct odm_dm_struct *pDM_Odm, u8 Step);
void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm);
+void odm_DynamicTxPower(struct odm_dm_struct *pDM_Odm);
void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm);
+void odm_SwAntDivInit(struct odm_dm_struct *pDM_Odm);
void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm);
void odm_RefreshRateAdaptiveMask(struct odm_dm_struct *pDM_Odm);
void odm_1R_CCA(struct odm_dm_struct *pDM_Odm);
void odm_RefreshRateAdaptiveMaskCE(struct odm_dm_struct *pDM_Odm);
void odm_RefreshRateAdaptiveMaskAPADSL(struct odm_dm_struct *pDM_Odm);
void odm_DynamicTxPowerNIC(struct odm_dm_struct *pDM_Odm);
+void odm_DynamicTxPowerAP(struct odm_dm_struct *pDM_Odm);
+void odm_RSSIMonitorCheckMP(struct odm_dm_struct *pDM_Odm);
void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm);
+void odm_RSSIMonitorCheckAP(struct odm_dm_struct *pDM_Odm);
+void odm_TXPowerTrackingThermalMeterInit(struct odm_dm_struct *pDM_Odm);
void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm);
-void odm_SwAntDivChkAntSwitchCallback(void *FunctionContext);
+void odm_TXPowerTrackingCheckCE(struct odm_dm_struct *pDM_Odm);
+void odm_TXPowerTrackingCheckMP(struct odm_dm_struct *pDM_Odm);
+void odm_TXPowerTrackingCheckAP(struct odm_dm_struct *pDM_Odm);
+void odm_SwAntDivChkAntSwitchCallback(struct timer_list *t);
void odm_InitHybridAntDiv(struct odm_dm_struct *pDM_Odm);
void odm_HwAntDiv(struct odm_dm_struct *pDM_Odm);
diff --git a/drivers/staging/r8188eu/include/odm_reg.h b/drivers/staging/r8188eu/include/odm_reg.h
new file mode 100644
index 000000000000..78d7e904947c
--- /dev/null
+++ b/drivers/staging/r8188eu/include/odm_reg.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. i*/
+
+#ifndef __HAL_ODM_REG_H__
+#define __HAL_ODM_REG_H__
+
+/* Register Definition */
+
+/* MAC REG */
+#define ODM_BB_RESET 0x002
+#define ODM_DUMMY 0x4fe
+#define ODM_EDCA_VO_PARAM 0x500
+#define ODM_EDCA_VI_PARAM 0x504
+#define ODM_EDCA_BE_PARAM 0x508
+#define ODM_EDCA_BK_PARAM 0x50C
+#define ODM_TXPAUSE 0x522
+
+/* BB REG */
+#define ODM_FPGA_PHY0_PAGE8 0x800
+#define ODM_PSD_SETTING 0x808
+#define ODM_AFE_SETTING 0x818
+#define ODM_TXAGC_B_6_18 0x830
+#define ODM_TXAGC_B_24_54 0x834
+#define ODM_TXAGC_B_MCS32_5 0x838
+#define ODM_TXAGC_B_MCS0_MCS3 0x83c
+#define ODM_TXAGC_B_MCS4_MCS7 0x848
+#define ODM_TXAGC_B_MCS8_MCS11 0x84c
+#define ODM_ANALOG_REGISTER 0x85c
+#define ODM_RF_INTERFACE_OUTPUT 0x860
+#define ODM_TXAGC_B_MCS12_MCS15 0x868
+#define ODM_TXAGC_B_11_A_2_11 0x86c
+#define ODM_AD_DA_LSB_MASK 0x874
+#define ODM_ENABLE_3_WIRE 0x88c
+#define ODM_PSD_REPORT 0x8b4
+#define ODM_R_ANT_SELECT 0x90c
+#define ODM_CCK_ANT_SELECT 0xa07
+#define ODM_CCK_PD_THRESH 0xa0a
+#define ODM_CCK_RF_REG1 0xa11
+#define ODM_CCK_MATCH_FILTER 0xa20
+#define ODM_CCK_RAKE_MAC 0xa2e
+#define ODM_CCK_CNT_RESET 0xa2d
+#define ODM_CCK_TX_DIVERSITY 0xa2f
+#define ODM_CCK_FA_CNT_MSB 0xa5b
+#define ODM_CCK_FA_CNT_LSB 0xa5c
+#define ODM_CCK_NEW_FUNCTION 0xa75
+#define ODM_OFDM_PHY0_PAGE_C 0xc00
+#define ODM_OFDM_RX_ANT 0xc04
+#define ODM_R_A_RXIQI 0xc14
+#define ODM_R_A_AGC_CORE1 0xc50
+#define ODM_R_A_AGC_CORE2 0xc54
+#define ODM_R_B_AGC_CORE1 0xc58
+#define ODM_R_AGC_PAR 0xc70
+#define ODM_R_HTSTF_AGC_PAR 0xc7c
+#define ODM_TX_PWR_TRAINING_A 0xc90
+#define ODM_TX_PWR_TRAINING_B 0xc98
+#define ODM_OFDM_FA_CNT1 0xcf0
+#define ODM_OFDM_PHY0_PAGE_D 0xd00
+#define ODM_OFDM_FA_CNT2 0xda0
+#define ODM_OFDM_FA_CNT3 0xda4
+#define ODM_OFDM_FA_CNT4 0xda8
+#define ODM_TXAGC_A_6_18 0xe00
+#define ODM_TXAGC_A_24_54 0xe04
+#define ODM_TXAGC_A_1_MCS32 0xe08
+#define ODM_TXAGC_A_MCS0_MCS3 0xe10
+#define ODM_TXAGC_A_MCS4_MCS7 0xe14
+#define ODM_TXAGC_A_MCS8_MCS11 0xe18
+#define ODM_TXAGC_A_MCS12_MCS15 0xe1c
+
+/* RF REG */
+#define ODM_GAIN_SETTING 0x00
+#define ODM_CHANNEL 0x18
+
+/* Ant Detect Reg */
+#define ODM_DPDT 0x300
+
+/* PSD Init */
+#define ODM_PSDREG 0x808
+
+/* 92D Path Div */
+#define PATHDIV_REG 0xB30
+#define PATHDIV_TRI 0xBA0
+
+/* */
+/* Bitmap Definition */
+/* */
+
+#define BIT_FA_RESET BIT(0)
+
+#endif
diff --git a/drivers/staging/r8188eu/include/odm_types.h b/drivers/staging/r8188eu/include/odm_types.h
new file mode 100644
index 000000000000..6f4a4bd37ec1
--- /dev/null
+++ b/drivers/staging/r8188eu/include/odm_types.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __ODM_TYPES_H__
+#define __ODM_TYPES_H__
+
+/* */
+/* Define Different SW team support */
+/* */
+#define ODM_AP 0x01 /* BIT(0) */
+#define ODM_ADSL 0x02 /* BIT(1) */
+#define ODM_CE 0x04 /* BIT(2) */
+#define ODM_MP 0x08 /* BIT(3) */
+
+#define RT_PCI_INTERFACE 1
+#define RT_USB_INTERFACE 2
+#define RT_SDIO_INTERFACE 3
+
+enum HAL_STATUS {
+ HAL_STATUS_SUCCESS,
+ HAL_STATUS_FAILURE,
+};
+
+enum RT_SPINLOCK_TYPE {
+ RT_TEMP = 1,
+};
+
+#include "basic_types.h"
+
+#define DEV_BUS_TYPE RT_USB_INTERFACE
+
+#define SET_TX_DESC_ANTSEL_A_88E(__ptxdesc, __value) \
+ le32p_replace_bits((__le32 *)(__ptxdesc + 8), __value, BIT(24))
+#define SET_TX_DESC_ANTSEL_B_88E(__ptxdesc, __value) \
+ le32p_replace_bits((__le32 *)(__ptxdesc + 8), __value, BIT(25))
+#define SET_TX_DESC_ANTSEL_C_88E(__ptxdesc, __value) \
+ le32p_replace_bits((__le32 *)(__ptxdesc + 28), __value, BIT(29))
+
+/* define useless flag to avoid compile warning */
+#define USE_WORKITEM 0
+#define FOR_BRAZIL_PRETEST 0
+#define BT_30_SUPPORT 0
+#define FPGA_TWO_MAC_VERIFICATION 0
+
+#endif /* __ODM_TYPES_H__ */
diff --git a/drivers/staging/r8188eu/include/osdep_intf.h b/drivers/staging/r8188eu/include/osdep_intf.h
new file mode 100644
index 000000000000..3ea60feee2db
--- /dev/null
+++ b/drivers/staging/r8188eu/include/osdep_intf.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __OSDEP_INTF_H_
+#define __OSDEP_INTF_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+struct intf_priv {
+ u8 *intf_dev;
+ u32 max_iosz; /* USB2.0: 128, USB1.1: 64, SDIO:64 */
+ u32 max_xmitsz; /* USB2.0: unlimited, SDIO:512 */
+ u32 max_recvsz; /* USB2.0: unlimited, SDIO:512 */
+
+ u8 *io_rwmem;
+ u8 *allocated_io_rwmem;
+ u32 io_wsz; /* unit: 4bytes */
+ u32 io_rsz;/* unit: 4bytes */
+ u8 intf_status;
+
+ void (*_bus_io)(u8 *priv);
+
+/*
+Under Sync. IRP (SDIO/USB)
+A protection mechanism is necessary for the io_rwmem(read/write protocol)
+
+Under Async. IRP (SDIO/USB)
+The protection mechanism is through the pending queue.
+*/
+ struct mutex ioctl_mutex;
+ /* when in USB, IO is through interrupt in/out endpoints */
+ struct usb_device *udev;
+ struct urb *piorw_urb;
+ u8 io_irp_cnt;
+ u8 bio_irp_pending;
+ struct semaphore io_retevt;
+ struct timer_list io_timer;
+ u8 bio_irp_timeout;
+ u8 bio_timer_cancel;
+};
+
+u8 rtw_init_drv_sw(struct adapter *padapter);
+u8 rtw_free_drv_sw(struct adapter *padapter);
+u8 rtw_reset_drv_sw(struct adapter *padapter);
+
+u32 rtw_start_drv_threads(struct adapter *padapter);
+void rtw_stop_drv_threads (struct adapter *padapter);
+void rtw_cancel_all_timer(struct adapter *padapter);
+
+int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname);
+struct net_device *rtw_init_netdev(struct adapter *padapter);
+u16 rtw_recv_select_queue(struct sk_buff *skb);
+void rtw_proc_init_one(struct net_device *dev);
+void rtw_proc_remove_one(struct net_device *dev);
+
+void rtw_ips_dev_unload(struct adapter *padapter);
+
+int rtw_ips_pwr_up(struct adapter *padapter);
+void rtw_ips_pwr_down(struct adapter *padapter);
+int rtw_hw_suspend(struct adapter *padapter);
+int rtw_hw_resume(struct adapter *padapter);
+
+#endif /* _OSDEP_INTF_H_ */
diff --git a/drivers/staging/r8188eu/include/osdep_service.h b/drivers/staging/r8188eu/include/osdep_service.h
new file mode 100644
index 000000000000..029aa4e92c9b
--- /dev/null
+++ b/drivers/staging/r8188eu/include/osdep_service.h
@@ -0,0 +1,315 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __OSDEP_SERVICE_H_
+#define __OSDEP_SERVICE_H_
+
+#include <linux/sched/signal.h>
+#include "basic_types.h"
+
+#define _FAIL 0
+#define _SUCCESS 1
+#define RTW_RX_HANDLED 2
+
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/circ_buf.h>
+#include <linux/uaccess.h>
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/sem.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h> /* Necessary because we use the proc fs */
+#include <linux/interrupt.h> /* for struct tasklet_struct */
+#include <linux/ip.h>
+#include <linux/kthread.h>
+#include <linux/vmalloc.h>
+
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+
+struct __queue {
+ struct list_head queue;
+ spinlock_t lock;
+};
+
+#define thread_exit() complete_and_exit(NULL, 0)
+
+static inline struct list_head *get_list_head(struct __queue *queue)
+{
+ return (&(queue->queue));
+}
+
+static inline int _enter_critical_mutex(struct mutex *pmutex, unsigned long *pirqL)
+{
+ int ret;
+
+ ret = mutex_lock_interruptible(pmutex);
+ return ret;
+}
+
+static inline void _exit_critical_mutex(struct mutex *pmutex, unsigned long *pirqL)
+{
+ mutex_unlock(pmutex);
+}
+
+static inline void rtw_list_delete(struct list_head *plist)
+{
+ list_del_init(plist);
+}
+
+static inline void _set_timer(struct timer_list *ptimer,u32 delay_time)
+{
+ mod_timer(ptimer , (jiffies+(delay_time*HZ/1000)));
+}
+
+static inline void _cancel_timer(struct timer_list *ptimer,u8 *bcancelled)
+{
+ del_timer_sync(ptimer);
+ *bcancelled= true;/* true ==1; false==0 */
+}
+
+#define RTW_TIMER_HDL_ARGS void *FunctionContext
+#define RTW_TIMER_HDL_NAME(name) rtw_##name##_timer_hdl
+#define RTW_DECLARE_TIMER_HDL(name) void RTW_TIMER_HDL_NAME(name)(RTW_TIMER_HDL_ARGS)
+
+static inline void _init_workitem(struct work_struct *pwork, void *pfunc, void * cntx)
+{
+ INIT_WORK(pwork, pfunc);
+}
+
+static inline void _set_workitem(struct work_struct *pwork)
+{
+ schedule_work(pwork);
+}
+
+static inline void _cancel_workitem_sync(struct work_struct *pwork)
+{
+ cancel_work_sync(pwork);
+}
+/* */
+/* Global Mutex: can only be used at PASSIVE level. */
+/* */
+
+#define ACQUIRE_GLOBAL_MUTEX(_MutexCounter) \
+{ \
+ while (atomic_inc_return((atomic_t *)&(_MutexCounter)) != 1)\
+ { \
+ atomic_dec((atomic_t *)&(_MutexCounter)); \
+ msleep(10); \
+ } \
+}
+
+#define RELEASE_GLOBAL_MUTEX(_MutexCounter) \
+{ \
+ atomic_dec((atomic_t *)&(_MutexCounter)); \
+}
+
+static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
+{
+ return netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) &&
+ netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 1)) &&
+ netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 2)) &&
+ netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3));
+}
+
+static inline void rtw_netif_wake_queue(struct net_device *pnetdev)
+{
+ netif_tx_wake_all_queues(pnetdev);
+}
+
+static inline void rtw_netif_start_queue(struct net_device *pnetdev)
+{
+ netif_tx_start_all_queues(pnetdev);
+}
+
+static inline void rtw_netif_stop_queue(struct net_device *pnetdev)
+{
+ netif_tx_stop_all_queues(pnetdev);
+}
+
+extern int RTW_STATUS_CODE(int error_code);
+
+extern unsigned char MCS_rate_2R[16];
+extern unsigned char MCS_rate_1R[16];
+extern unsigned char RTW_WPA_OUI[];
+extern unsigned char WPA_TKIP_CIPHER[4];
+extern unsigned char RSN_TKIP_CIPHER[4];
+
+void *rtw_malloc2d(int h, int w, int size);
+
+u32 _rtw_down_sema(struct semaphore *sema);
+void _rtw_mutex_init(struct mutex *pmutex);
+void _rtw_mutex_free(struct mutex *pmutex);
+
+void _rtw_init_queue(struct __queue *pqueue);
+
+u32 rtw_systime_to_ms(u32 systime);
+u32 rtw_ms_to_systime(u32 ms);
+s32 rtw_get_passing_time_ms(u32 start);
+
+void rtw_usleep_os(int us);
+
+u32 rtw_atoi(u8 *s);
+
+static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer)
+{
+ return del_timer_sync(ptimer);
+}
+
+static __inline void thread_enter(char *name)
+{
+#ifdef daemonize
+ daemonize("%s", name);
+#endif
+ allow_signal(SIGTERM);
+}
+
+static inline void flush_signals_thread(void)
+{
+ if (signal_pending (current))
+ flush_signals(current);
+}
+
+static inline int res_to_status(int res)
+{
+ return res;
+}
+
+#define _RND(sz, r) ((((sz)+((r)-1))/(r))*(r))
+#define RND4(x) (((x >> 2) + (((x & 3) == 0) ? 0: 1)) << 2)
+
+static inline u32 _RND4(u32 sz)
+{
+ u32 val;
+
+ val = ((sz >> 2) + ((sz & 3) ? 1: 0)) << 2;
+ return val;
+}
+
+static inline u32 _RND8(u32 sz)
+{
+ u32 val;
+
+ val = ((sz >> 3) + ((sz & 7) ? 1: 0)) << 3;
+ return val;
+}
+
+static inline u32 _RND128(u32 sz)
+{
+ u32 val;
+
+ val = ((sz >> 7) + ((sz & 127) ? 1: 0)) << 7;
+ return val;
+}
+
+static inline u32 _RND256(u32 sz)
+{
+ u32 val;
+
+ val = ((sz >> 8) + ((sz & 255) ? 1: 0)) << 8;
+ return val;
+}
+
+static inline u32 _RND512(u32 sz)
+{
+ u32 val;
+
+ val = ((sz >> 9) + ((sz & 511) ? 1: 0)) << 9;
+ return val;
+}
+
+static inline u32 bitshift(u32 bitmask)
+{
+ u32 i;
+
+ for (i = 0; i <= 31; i++)
+ if (((bitmask>>i) & 0x1) == 1) break;
+ return i;
+}
+
+/* limitation of path length */
+#define PATH_LENGTH_MAX PATH_MAX
+
+struct rtw_netdev_priv_indicator {
+ void *priv;
+ u32 sizeof_priv;
+};
+struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv,
+ void *old_priv);
+struct net_device *rtw_alloc_etherdev(int sizeof_priv);
+
+#define rtw_netdev_priv(netdev) \
+ (((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv)
+void rtw_free_netdev(struct net_device *netdev);
+
+#define NDEV_FMT "%s"
+#define NDEV_ARG(ndev) ndev->name
+#define ADPT_FMT "%s"
+#define ADPT_ARG(adapter) adapter->pnetdev->name
+#define FUNC_NDEV_FMT "%s(%s)"
+#define FUNC_NDEV_ARG(ndev) __func__, ndev->name
+#define FUNC_ADPT_FMT "%s(%s)"
+#define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name
+
+#define rtw_signal_process(pid, sig) kill_pid(find_vpid((pid)),(sig), 1)
+
+/* Macros for handling unaligned memory accesses */
+
+#define RTW_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
+#define RTW_PUT_BE16(a, val) \
+ do { \
+ (a)[0] = ((u16) (val)) >> 8; \
+ (a)[1] = ((u16) (val)) & 0xff; \
+ } while (0)
+
+#define RTW_PUT_LE16(a, val) \
+ do { \
+ (a)[1] = ((u16) (val)) >> 8; \
+ (a)[0] = ((u16) (val)) & 0xff; \
+ } while (0)
+
+#define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
+ ((u32) (a)[2]))
+
+#define RTW_PUT_BE32(a, val) \
+ do { \
+ (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \
+ (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \
+ (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \
+ (a)[3] = (u8) (((u32) (val)) & 0xff); \
+ } while (0)
+
+void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len);
+
+struct rtw_cbuf {
+ u32 write;
+ u32 read;
+ u32 size;
+ void *bufs[0];
+};
+
+bool rtw_cbuf_full(struct rtw_cbuf *cbuf);
+bool rtw_cbuf_empty(struct rtw_cbuf *cbuf);
+bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf);
+void *rtw_cbuf_pop(struct rtw_cbuf *cbuf);
+struct rtw_cbuf *rtw_cbuf_alloc(u32 size);
+int wifirate2_ratetbl_inx(unsigned char rate);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/recv_osdep.h b/drivers/staging/r8188eu/include/recv_osdep.h
new file mode 100644
index 000000000000..72ddf515071e
--- /dev/null
+++ b/drivers/staging/r8188eu/include/recv_osdep.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RECV_OSDEP_H_
+#define __RECV_OSDEP_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter);
+void _rtw_free_recv_priv(struct recv_priv *precvpriv);
+
+s32 rtw_recv_entry(struct recv_frame *precv_frame);
+int rtw_recv_indicatepkt(struct adapter *adapter, struct recv_frame *recv_frame);
+void rtw_recv_returnpacket(struct net_device *cnxt, struct sk_buff *retpkt);
+
+void rtw_hostapd_mlme_rx(struct adapter *padapter, struct recv_frame *recv_fr);
+void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup);
+
+int rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter);
+void rtw_free_recv_priv(struct recv_priv *precvpriv);
+
+int rtw_os_recv_resource_init(struct recv_priv *recvpr, struct adapter *adapt);
+int rtw_os_recv_resource_alloc(struct adapter *adapt, struct recv_frame *recvfr);
+void rtw_os_recv_resource_free(struct recv_priv *precvpriv);
+
+int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf);
+int rtw_os_recvbuf_resource_free(struct adapter *adapt, struct recv_buf *buf);
+
+void rtw_os_read_port(struct adapter *padapter, struct recv_buf *precvbuf);
+
+void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl);
+int _netdev_open(struct net_device *pnetdev);
+int netdev_open(struct net_device *pnetdev);
+int netdev_close(struct net_device *pnetdev);
+
+#endif /* */
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/r8188eu/include/rtl8188e_cmd.h
index e588656f1de9..6fbf9a47430b 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h
+++ b/drivers/staging/r8188eu/include/rtl8188e_cmd.h
@@ -1,9 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTL8188E_CMD_H__
#define __RTL8188E_CMD_H__
@@ -41,6 +38,12 @@ enum RTL8188E_H2C_CMD_ID {
H2C_RESET_TSF = 0xc0,
};
+struct cmd_msg_parm {
+ u8 eid; /* element id */
+ u8 sz; /* sz */
+ u8 buf[6];
+};
+
enum {
PWRS
};
@@ -53,6 +56,15 @@ struct setpwrmode_parm {
u8 PwrState;/* AllON(0x0c),RFON(0x04),RFOFF(0x00) */
};
+struct H2C_SS_RFOFF_PARAM {
+ u8 ROFOn; /* 1: on, 0:off */
+ u16 gpio_period; /* unit: 1024 us */
+} __packed;
+
+struct joinbssrpt_parm {
+ u8 OpMode; /* RT_MEDIA_STATUS */
+};
+
struct rsvdpage_loc {
u8 LocProbeRsp;
u8 LocPsPoll;
@@ -61,10 +73,34 @@ struct rsvdpage_loc {
u8 LocBTQosNull;
};
+struct P2P_PS_Offload_t {
+ u8 Offload_En:1;
+ u8 role:1; /* 1: Owner, 0: Client */
+ u8 CTWindow_En:1;
+ u8 NoA0_En:1;
+ u8 NoA1_En:1;
+ u8 AllStaSleep:1; /* Only valid in Owner */
+ u8 discovery:1;
+ u8 rsvd:1;
+};
+
+struct P2P_PS_CTWPeriod_t {
+ u8 CTWPeriod; /* TU */
+};
+
/* host message to firmware cmd */
void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode);
void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus);
+u8 rtl8188e_set_rssi_cmd(struct adapter *padapter, u8 *param);
+u8 rtl8188e_set_raid_cmd(struct adapter *padapter, u32 mask);
+void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg,
+ u8 rssi_level);
+
+#ifdef CONFIG_88EU_P2P
+void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state);
+#endif /* CONFIG_88EU_P2P */
+void CheckFwRsvdPageContent(struct adapter *adapt);
void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt);
#endif/* __RTL8188E_CMD_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h b/drivers/staging/r8188eu/include/rtl8188e_dm.h
index 910b982ab775..3ead20b321a9 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h
+++ b/drivers/staging/r8188eu/include/rtl8188e_dm.h
@@ -1,16 +1,19 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTL8188E_DM_H__
#define __RTL8188E_DM_H__
+
enum{
UP_LINK,
DOWN_LINK,
};
-
+/* duplicate code,will move to ODM ######### */
+#define IQK_MAC_REG_NUM 4
+#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM 9
+#define HP_THERMAL_NUM 8
+/* duplicate code,will move to ODM ######### */
struct dm_priv {
u8 DM_Type;
u8 DMFlag;
@@ -32,9 +35,13 @@ struct dm_priv {
u8 PowerIndex_backup[6];
};
+void rtl8188e_init_dm_priv(struct adapter *adapt);
+void rtl8188e_deinit_dm_priv(struct adapter *adapt);
void rtl8188e_InitHalDm(struct adapter *adapt);
+void rtl8188e_HalDmWatchDog(struct adapter *adapt);
void AntDivCompare8188E(struct adapter *adapt, struct wlan_bssid_ex *dst,
struct wlan_bssid_ex *src);
+u8 AntDivBeforeLink8188E(struct adapter *adapt);
#endif
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/r8188eu/include/rtl8188e_hal.h
index 2c16d3f33e1c..3939bf053de1 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
+++ b/drivers/staging/r8188eu/include/rtl8188e_hal.h
@@ -1,26 +1,38 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTL8188E_HAL_H__
#define __RTL8188E_HAL_H__
/* include HAL Related header after HAL Related compiling flags */
#include "rtl8188e_spec.h"
-#include "hal8188e_phy_reg.h"
-#include "hal8188e_phy_cfg.h"
+#include "Hal8188EPhyReg.h"
+#include "Hal8188EPhyCfg.h"
+#include "rtl8188e_rf.h"
#include "rtl8188e_dm.h"
#include "rtl8188e_recv.h"
#include "rtl8188e_xmit.h"
#include "rtl8188e_cmd.h"
-#include "pwrseq.h"
+#include "Hal8188EPwrSeq.h"
+#include "rtl8188e_sreset.h"
#include "rtw_efuse.h"
-#include "rtw_sreset.h"
+
#include "odm_precomp.h"
-/* RTL8188E Power Configuration CMDs for USB/SDIO interfaces */
+/* Fw Array */
+#define Rtl8188E_FwImageArray Rtl8188EFwImgArray
+#define Rtl8188E_FWImgArrayLength Rtl8188EFWImgArrayLength
+
+#define RTL8188E_FW_UMC_IMG "rtl8188E\\rtl8188efw.bin"
+#define RTL8188E_PHY_REG "rtl8188E\\PHY_REG_1T.txt"
+#define RTL8188E_PHY_RADIO_A "rtl8188E\\radio_a_1T.txt"
+#define RTL8188E_PHY_RADIO_B "rtl8188E\\radio_b_1T.txt"
+#define RTL8188E_AGC_TAB "rtl8188E\\AGC_TAB_1T.txt"
+#define RTL8188E_PHY_MACREG "rtl8188E\\MAC_REG.txt"
+#define RTL8188E_PHY_REG_PG "rtl8188E\\PHY_REG_PG.txt"
+#define RTL8188E_PHY_REG_MP "rtl8188E\\PHY_REG_MP.txt"
+
+/* RTL8188E Power Configuration CMDs for USB/SDIO interfaces */
#define Rtl8188E_NIC_PWR_ON_FLOW rtl8188E_power_on_flow
#define Rtl8188E_NIC_RF_OFF_FLOW rtl8188E_radio_off_flow
#define Rtl8188E_NIC_DISABLE_FLOW rtl8188E_card_disable_flow
@@ -32,7 +44,7 @@
#define Rtl8188E_NIC_LPS_LEAVE_FLOW rtl8188E_leave_lps_flow
#define DRVINFO_SZ 4 /* unit is 8bytes */
-#define PageNum_128(_Len) (u32)(((_Len) >> 7) + ((_Len) & 0x7F ? 1 : 0))
+#define PageNum_128(_Len) (u32)(((_Len)>>7) + ((_Len) & 0x7F ? 1 : 0))
/* download firmware related data structure */
#define FW_8188E_SIZE 0x4000 /* 16384,16k */
@@ -41,11 +53,46 @@
#define MAX_PAGE_SIZE 4096 /* @ page : 4k bytes */
-#define IS_FW_HEADER_EXIST(_pFwHdr) \
- ((le16_to_cpu(_pFwHdr->signature) & 0xFFF0) == 0x92C0 || \
- (le16_to_cpu(_pFwHdr->signature) & 0xFFF0) == 0x88C0 || \
- (le16_to_cpu(_pFwHdr->signature) & 0xFFF0) == 0x2300 || \
- (le16_to_cpu(_pFwHdr->signature) & 0xFFF0) == 0x88E0)
+#define IS_FW_HEADER_EXIST(_pFwHdr) \
+ ((le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x92C0 || \
+ (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x88C0 || \
+ (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x2300 || \
+ (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x88E0)
+
+/* This structure must be careful with byte-ordering */
+
+struct rt_firmware_hdr {
+ /* 8-byte alinment required */
+ /* LONG WORD 0 ---- */
+ __le16 Signature; /* 92C0: test chip; 92C,
+ * 88C0: test chip; 88C1: MP A-cut;
+ * 92C1: MP A-cut */
+ u8 Category; /* AP/NIC and USB/PCI */
+ u8 Function; /* Reserved for different FW function
+ * indcation, for further use when
+ * driver needs to download different
+ * FW for different conditions */
+ __le16 Version; /* FW Version */
+ u8 Subversion; /* FW Subversion, default 0x00 */
+ u16 Rsvd1;
+
+ /* LONG WORD 1 ---- */
+ u8 Month; /* Release time Month field */
+ u8 Date; /* Release time Date field */
+ u8 Hour; /* Release time Hour field */
+ u8 Minute; /* Release time Minute field */
+ __le16 RamCodeSize; /* The size of RAM code */
+ u8 Foundry;
+ u8 Rsvd2;
+
+ /* LONG WORD 2 ---- */
+ __le32 SvnIdx; /* The SVN entry index */
+ u32 Rsvd3;
+
+ /* LONG WORD 3 ---- */
+ u32 Rsvd4;
+ u32 Rsvd5;
+};
#define DRIVER_EARLY_INT_TIME 0x05
#define BCN_DMA_ATIME_INT_TIME 0x02
@@ -59,8 +106,7 @@ enum usb_rx_agg_mode {
#define MAX_RX_DMA_BUFFER_SIZE_88E \
0x2400 /* 9k for 88E nornal chip , MaxRxBuff=10k-max(TxReportSize(64*8),
- * WOLPattern(16*24))
- */
+ * WOLPattern(16*24)) */
#define MAX_TX_REPORT_BUFFER_SIZE 0x0400 /* 1k */
@@ -72,13 +118,11 @@ enum usb_rx_agg_mode {
#define TX_SELE_NQ BIT(2) /* Normal Queue */
/* Note: We will divide number of page equally for each queue other
- * than public queue!
- */
+ * than public queue! */
/* 22k = 22528 bytes = 176 pages (@page = 128 bytes) */
/* must reserved about 7 pages for LPS => 176-7 = 169 (0xA9) */
/* 2*BCN / 1*ps-poll / 1*null-data /1*prob_rsp /1*QOS null-data /1*BT QOS
- * null-data
- */
+ * null-data */
#define TX_TOTAL_PAGE_NUMBER_88E 0xA9/* 169 (21632=> 21k) */
@@ -90,15 +134,15 @@ enum usb_rx_agg_mode {
#define WMM_NORMAL_TX_PAGE_BOUNDARY_88E \
(WMM_NORMAL_TX_TOTAL_PAGE_NUMBER + 1) /* 0xA9 */
-/* Chip specific */
-#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3)
+/* Chip specific */
+#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3)
#define CHIP_BONDING_92C_1T2R 0x1
#define CHIP_BONDING_88C_USB_MCARD 0x2
#define CHIP_BONDING_88C_USB_HP 0x1
#include "HalVerDef.h"
#include "hal_com.h"
-/* Channel Plan */
+/* Channel Plan */
enum ChannelPlan {
CHPL_FCC = 0,
CHPL_IC = 1,
@@ -114,13 +158,13 @@ enum ChannelPlan {
};
struct txpowerinfo24g {
- u8 IndexCCK_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G];
- u8 IndexBW40_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G];
+ u8 IndexCCK_Base[RF_PATH_MAX][MAX_CHNL_GROUP_24G];
+ u8 IndexBW40_Base[RF_PATH_MAX][MAX_CHNL_GROUP_24G];
/* If only one tx, only BW20 and OFDM are used. */
- s8 CCK_Diff[MAX_RF_PATH][MAX_TX_COUNT];
- s8 OFDM_Diff[MAX_RF_PATH][MAX_TX_COUNT];
- s8 BW20_Diff[MAX_RF_PATH][MAX_TX_COUNT];
- s8 BW40_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+ s8 CCK_Diff[RF_PATH_MAX][MAX_TX_COUNT];
+ s8 OFDM_Diff[RF_PATH_MAX][MAX_TX_COUNT];
+ s8 BW20_Diff[RF_PATH_MAX][MAX_TX_COUNT];
+ s8 BW40_Diff[RF_PATH_MAX][MAX_TX_COUNT];
};
#define EFUSE_REAL_CONTENT_LEN 512
@@ -134,7 +178,7 @@ struct txpowerinfo24g {
/* | 1byte|----8bytes----|1byte|--5bytes--| */
/* | | Reserved(14bytes) | */
-/* PG data exclude header, dummy 6 bytes from CP test and reserved 1byte. */
+/* PG data exclude header, dummy 6 bytes frome CP test and reserved 1byte. */
#define EFUSE_OOB_PROTECT_BYTES 15
#define HWSET_MAX_SIZE_88E 512
@@ -148,25 +192,41 @@ struct txpowerinfo24g {
#define AVAILABLE_EFUSE_ADDR_88E(addr) \
(addr < EFUSE_REAL_CONTENT_LEN_88E)
/* To prevent out of boundary programming case, leave 1byte and program
- * full section
- */
+ * full section */
/* 9bytes + 1byt + 5bytes and pre 1byte. */
/* For worst case: */
/* | 2byte|----8bytes----|1byte|--7bytes--| 92D */
-/* PG data exclude header, dummy 7 bytes from CP test and reserved 1byte. */
+/* PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte. */
#define EFUSE_OOB_PROTECT_BYTES_88E 18
#define EFUSE_PROTECT_BYTES_BANK_88E 16
-/* EFUSE for BT definition */
+/* EFUSE for BT definition */
#define EFUSE_BT_REAL_CONTENT_LEN 1536 /* 512*3 */
#define EFUSE_BT_MAP_LEN 1024 /* 1k bytes */
#define EFUSE_BT_MAX_SECTION 128 /* 1024/8 */
#define EFUSE_PROTECT_BYTES_BANK 16
+/* For RTL8723 WiFi/BT/GPS multi-function configuration. */
+enum rt_multi_func {
+ RT_MULTI_FUNC_NONE = 0x00,
+ RT_MULTI_FUNC_WIFI = 0x01,
+ RT_MULTI_FUNC_BT = 0x02,
+ RT_MULTI_FUNC_GPS = 0x04,
+};
+
+/* For RTL8723 regulator mode. */
+enum rt_regulator_mode {
+ RT_SWITCHING_REGULATOR = 0,
+ RT_LDO_REGULATOR = 1,
+};
+
struct hal_data_8188e {
struct HAL_VERSION VersionID;
+ enum rt_multi_func MultiFunc; /* For multi-function consideration. */
+ enum rt_regulator_mode RegulatorMode; /* switching regulator or LDO */
u16 CustomerID;
+
u16 FirmwareVersion;
u16 FirmwareVersionRev;
u16 FirmwareSubVersion;
@@ -181,6 +241,11 @@ struct hal_data_8188e {
u16 BasicRateSet;
+ /* rf_ctrl */
+ u8 rf_chip;
+ u8 rf_type;
+ u8 NumTotalRFPath;
+
u8 BoardType;
/* EEPROM setting. */
@@ -195,16 +260,18 @@ struct hal_data_8188e {
u8 bTXPowerDataReadFromEEPORM;
u8 EEPROMThermalMeter;
+ u8 bAPKThermalMeterIgnore;
bool EepromOrEfuse;
+ struct efuse_hal EfuseHal;
- u8 Index24G_CCK_Base[MAX_RF_PATH][CHANNEL_MAX_NUMBER];
- u8 Index24G_BW40_Base[MAX_RF_PATH][CHANNEL_MAX_NUMBER];
+ u8 Index24G_CCK_Base[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+ u8 Index24G_BW40_Base[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
/* If only one tx, only BW20 and OFDM are used. */
- s8 CCK_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT];
- s8 OFDM_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT];
- s8 BW20_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT];
- s8 BW40_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+ s8 CCK_24G_Diff[RF_PATH_MAX][MAX_TX_COUNT];
+ s8 OFDM_24G_Diff[RF_PATH_MAX][MAX_TX_COUNT];
+ s8 BW20_24G_Diff[RF_PATH_MAX][MAX_TX_COUNT];
+ s8 BW40_24G_Diff[RF_PATH_MAX][MAX_TX_COUNT];
u8 TxPwrLevelCck[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
/* For HT 40MHZ pwr */
@@ -219,12 +286,31 @@ struct hal_data_8188e {
u8 PwrGroupHT20[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
u8 PwrGroupHT40[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+ u8 LegacyHTTxPowerDiff;/* Legacy to HT rate power diff */
+ /* The current Tx Power Level */
+ u8 CurrentCckTxPwrIdx;
+ u8 CurrentOfdm24GTxPwrIdx;
+ u8 CurrentBW2024GTxPwrIdx;
+ u8 CurrentBW4024GTxPwrIdx;
+
/* Read/write are allow for following hardware information variables */
u8 framesync;
+ u32 framesyncC34;
+ u8 framesyncMonitor;
+ u8 DefaultInitialGain[4];
u8 pwrGroupCnt;
u32 MCSTxPowerLevelOriginalOffset[MAX_PG_GROUP][16];
+ u32 CCKTxPowerLevelOriginalOffset;
u8 CrystalCap;
+ u32 AntennaTxPath; /* Antenna path Tx */
+ u32 AntennaRxPath; /* Antenna path Rx */
+ u8 BluetoothCoexist;
+ u8 ExternalPA;
+
+ u8 bLedOpenDrain; /* Open-drain support for controlling the LED.*/
+
+ u8 b1x1RecvCombine; /* for 1T1R receive combining */
u32 AcParam_BE; /* Original parameter for BE, use for EDCA turbo. */
@@ -238,6 +324,7 @@ struct hal_data_8188e {
/* for host message to fw */
u8 LastHMEBoxNum;
+ u8 fw_ractrl;
u8 RegTxPause;
/* Beacon function related global variable. */
u32 RegBcnCtrlVal;
@@ -255,6 +342,11 @@ struct hal_data_8188e {
u8 bDumpRxPkt;/* for debug */
u8 bDumpTxPkt;/* for debug */
+ u8 FwRsvdPageStartOffset; /* Reserve page start offset except
+ * beacon in TxQ. */
+
+ /* 2010/08/09 MH Add CU power down mode. */
+ bool pwrdown;
/* Add for dual MAC 0--Mac0 1--Mac1 */
u32 interfaceIndex;
@@ -262,11 +354,22 @@ struct hal_data_8188e {
u8 OutEpQueueSel;
u8 OutEpNumber;
+ /* Add for USB aggreation mode dynamic shceme. */
+ bool UsbRxHighSpeedMode;
+
+ /* 2010/11/22 MH Add for slim combo debug mode selective. */
+ /* This is used for fix the drawback of CU TSMC-A/UMC-A cut.
+ * HW auto suspend ability. Close BT clock. */
+ bool SlimComboDbg;
+
u16 EfuseUsedBytes;
+#ifdef CONFIG_88EU_P2P
+ struct P2P_PS_Offload_t p2p_ps_offload;
+#endif
+
/* Auto FSM to Turn On, include clock, isolation, power control
- * for MAC only
- */
+ * for MAC only */
u8 bMacPwrCtrlOn;
u32 UsbBulkOutSize;
@@ -278,26 +381,35 @@ struct hal_data_8188e {
u8 UsbTxAggMode;
u8 UsbTxAggDescNum;
u16 HwRxPageSize; /* Hardware setting */
+ u32 MaxUsbRxAggBlock;
enum usb_rx_agg_mode UsbRxAggMode;
u8 UsbRxAggBlockCount; /* USB Block count. Block size is
* 512-byte in high speed and 64-byte
- * in full speed
- */
+ * in full speed */
u8 UsbRxAggBlockTimeout;
u8 UsbRxAggPageCount; /* 8192C DMA page count */
u8 UsbRxAggPageTimeout;
};
-void Hal_GetChnlGroup88E(u8 chnl, u8 *group);
+#define GET_HAL_DATA(__pAdapter) \
+ ((struct hal_data_8188e *)((__pAdapter)->HalData))
+#define GET_RF_TYPE(priv) (GET_HAL_DATA(priv)->rf_type)
+
+#define INCLUDE_MULTI_FUNC_BT(_Adapter) \
+ (GET_HAL_DATA(_Adapter)->MultiFunc & RT_MULTI_FUNC_BT)
+#define INCLUDE_MULTI_FUNC_GPS(_Adapter) \
+ (GET_HAL_DATA(_Adapter)->MultiFunc & RT_MULTI_FUNC_GPS)
/* rtl8188e_hal_init.c */
+s32 rtl8188e_FirmwareDownload(struct adapter *padapter);
void _8051Reset88E(struct adapter *padapter);
void rtl8188e_InitializeFirmwareVars(struct adapter *padapter);
s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy);
/* EFuse */
+u8 GetEEPROMSize8188E(struct adapter *padapter);
void Hal_InitPGData88E(struct adapter *padapter);
void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo);
void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *hwinfo,
@@ -309,9 +421,9 @@ void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo,
bool AutoLoadFail);
void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo,
bool AutoLoadFail);
-void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent,
+void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter,u8 *PROMContent,
bool AutoLoadFail);
-void Hal_ReadThermalMeter_88E(struct adapter *dapter, u8 *PROMContent,
+void Hal_ReadThermalMeter_88E(struct adapter * dapter, u8 *PROMContent,
bool AutoloadFail);
void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo,
bool AutoLoadFail);
@@ -320,14 +432,21 @@ void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo,
void Hal_ReadPowerSavingMode88E(struct adapter *pAdapter, u8 *hwinfo,
bool AutoLoadFail);
+bool HalDetectPwrDownMode88E(struct adapter *Adapter);
+
+void Hal_InitChannelPlan(struct adapter *padapter);
+void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc);
+
/* register */
+void SetBcnCtrlReg(struct adapter *padapter, u8 SetBits, u8 ClearBits);
+void rtl8188e_clone_haldata(struct adapter *dst, struct adapter *src);
void rtl8188e_start_thread(struct adapter *padapter);
void rtl8188e_stop_thread(struct adapter *padapter);
-s32 iol_execute(struct adapter *padapter, u8 control);
-void iol_mode_enable(struct adapter *padapter, u8 enable);
+void rtw_IOL_cmd_tx_pkt_buf_dump(struct adapter *Adapter, int len);
s32 rtl8188e_iol_efuse_patch(struct adapter *padapter);
void rtw_cancel_all_timer(struct adapter *padapter);
+void _ps_open_RF(struct adapter *adapt);
#endif /* __RTL8188E_HAL_H__ */
diff --git a/drivers/staging/r8188eu/include/rtl8188e_led.h b/drivers/staging/r8188eu/include/rtl8188e_led.h
new file mode 100644
index 000000000000..b00954198764
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtl8188e_led.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTL8188E_LED_H__
+#define __RTL8188E_LED_H__
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+/* */
+/* Interface to manipulate LED objects. */
+/* */
+void rtl8188eu_InitSwLeds(struct adapter *padapter);
+void rtl8188eu_DeInitSwLeds(struct adapter *padapter);
+void SwLedOn(struct adapter *padapter, struct LED_871x *pLed);
+void SwLedOff(struct adapter *padapter, struct LED_871x *pLed);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/r8188eu/include/rtl8188e_recv.h
index fea1119c426e..a91daf84d6c3 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h
+++ b/drivers/staging/r8188eu/include/rtl8188e_recv.h
@@ -1,9 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTL8188E_RECV_H__
#define __RTL8188E_RECV_H__
@@ -43,11 +40,14 @@ enum rx_packet_type {
};
#define INTERRUPT_MSG_FORMAT_LEN 60
-void rtl8188eu_recv_tasklet(struct tasklet_struct *t);
-void rtl8188e_process_phy_info(struct adapter *padapter,
- struct recv_frame *prframe);
+void rtl8188eu_init_recvbuf(struct adapter *padapter, struct recv_buf *buf);
+s32 rtl8188eu_init_recv_priv(struct adapter *padapter);
+void rtl8188eu_free_recv_priv(struct adapter * padapter);
+void rtl8188eu_recv_hdl(struct adapter * padapter, struct recv_buf *precvbuf);
+void rtl8188eu_recv_tasklet(unsigned long priv);
+void rtl8188e_query_rx_phy_status(struct recv_frame *fr, struct phy_stat *phy);
+void rtl8188e_process_phy_info(struct adapter * padapter, void *prframe);
void update_recvframe_phyinfo_88e(struct recv_frame *fra, struct phy_stat *phy);
-void update_recvframe_attrib_88e(struct recv_frame *fra,
- struct recv_stat *stat);
+void update_recvframe_attrib_88e(struct recv_frame *fra, struct recv_stat *stat);
#endif
diff --git a/drivers/staging/r8188eu/include/rtl8188e_rf.h b/drivers/staging/r8188eu/include/rtl8188e_rf.h
new file mode 100644
index 000000000000..da6b7f8212a3
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtl8188e_rf.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTL8188E_RF_H__
+#define __RTL8188E_RF_H__
+
+#define RF6052_MAX_TX_PWR 0x3F
+#define RF6052_MAX_REG 0x3F
+#define RF6052_MAX_PATH 2
+
+int PHY_RF6052_Config8188E(struct adapter *Adapter);
+void rtl8188e_RF_ChangeTxPath(struct adapter *Adapter, u16 DataRate);
+void rtl8188e_PHY_RF6052SetBandwidth(struct adapter *Adapter,
+ enum ht_channel_width Bandwidth);
+void rtl8188e_PHY_RF6052SetCckTxPower(struct adapter *Adapter, u8 *level);
+void rtl8188e_PHY_RF6052SetOFDMTxPower(struct adapter *Adapter, u8 *ofdm,
+ u8 *pwrbw20, u8 *pwrbw40, u8 channel);
+
+#endif/* __RTL8188E_RF_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h b/drivers/staging/r8188eu/include/rtl8188e_spec.h
index fe0871bbb95f..1c96f7b81245 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
+++ b/drivers/staging/r8188eu/include/rtl8188e_spec.h
@@ -1,17 +1,21 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- *******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTL8188E_SPEC_H__
#define __RTL8188E_SPEC_H__
+/* 8192C Regsiter offset definition */
+
+#define HAL_PS_TIMER_INT_DELAY 50 /* 50 microseconds */
+#define HAL_92C_NAV_UPPER_UNIT 128 /* micro-second */
+
+#define MAC_ADDR_LEN 6
/* 8188E PKT_BUFF_ACCESS_CTRL value */
#define TXPKT_BUF_SELECT 0x69
+#define RXPKT_BUF_SELECT 0xA5
#define DISABLE_TRXPKT_BUF_ACCESS 0x0
-/* 0x0000h ~ 0x00FFh System Configuration */
+/* 0x0000h ~ 0x00FFh System Configuration */
#define REG_SYS_ISO_CTRL 0x0000
#define REG_SYS_FUNC_EN 0x0002
#define REG_APS_FSMCO 0x0004
@@ -45,7 +49,16 @@
#define REG_FSISR 0x0054
#define REG_HSIMR 0x0058
#define REG_HSISR 0x005c
+#define REG_GPIO_PIN_CTRL_2 0x0060 /* RTL8723 WIFI/BT/GPS
+ * Multi-Function GPIO Pin Control. */
+#define REG_GPIO_IO_SEL_2 0x0062 /* RTL8723 WIFI/BT/GPS
+ * Multi-Function GPIO Select. */
#define REG_BB_PAD_CTRL 0x0064
+#define REG_MULTI_FUNC_CTRL 0x0068 /* RTL8723 WIFI/BT/GPS
+ * Multi-Function control source. */
+#define REG_GPIO_OUTPUT 0x006c
+#define REG_AFE_XTAL_CTRL_EXT 0x0078 /* RTL8188E */
+#define REG_XCK_OUT_CTRL 0x007c /* RTL8188E */
#define REG_MCUFWDL 0x0080
#define REG_WOL_EVENT 0x0081 /* RTL8188E */
#define REG_MCUTSTCFG 0x0084
@@ -62,8 +75,7 @@
#define REG_HIMRE_88E 0x00B8
#define REG_HISRE_88E 0x00BC
#define REG_EFUSE_ACCESS 0x00CF /* Efuse access protection
- * for RTL8723
- */
+ * for RTL8723 */
#define REG_BIST_SCAN 0x00D0
#define REG_BIST_RPT 0x00D4
#define REG_BIST_ROM_RPT 0x00D8
@@ -77,7 +89,7 @@
#define REG_MAC_PHY_CTRL_NORMAL 0x00f8
-/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
#define REG_CR 0x0100
#define REG_PBP 0x0104
#define REG_PKT_BUFF_ACCESS_CTRL 0x0106
@@ -95,9 +107,9 @@
#define REG_FWISR 0x0134
#define REG_PKTBUF_DBG_CTRL 0x0140
#define REG_PKTBUF_DBG_ADDR (REG_PKTBUF_DBG_CTRL)
-#define REG_RXPKTBUF_DBG (REG_PKTBUF_DBG_CTRL + 2)
-#define REG_TXPKTBUF_DBG (REG_PKTBUF_DBG_CTRL + 3)
-#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL + 2)
+#define REG_RXPKTBUF_DBG (REG_PKTBUF_DBG_CTRL+2)
+#define REG_TXPKTBUF_DBG (REG_PKTBUF_DBG_CTRL+3)
+#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2)
#define REG_PKTBUF_DBG_DATA_L 0x0144
#define REG_PKTBUF_DBG_DATA_H 0x0148
@@ -123,7 +135,7 @@
#define REG_LLT_INIT 0x01E0
-/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
#define REG_RQPN 0x0200
#define REG_FIFOPAGE 0x0204
#define REG_TDECTRL 0x0208
@@ -131,12 +143,12 @@
#define REG_TXDMA_STATUS 0x0210
#define REG_RQPN_NPQ 0x0214
-/* 0x0280h ~ 0x02FFh RXDMA Configuration */
+/* 0x0280h ~ 0x02FFh RXDMA Configuration */
#define REG_RXDMA_AGG_PG_TH 0x0280
#define REG_RXPKT_NUM 0x0284
#define REG_RXDMA_STATUS 0x0288
-/* 0x0300h ~ 0x03FFh PCIe */
+/* 0x0300h ~ 0x03FFh PCIe */
#define REG_PCIE_CTRL_REG 0x0300
#define REG_INT_MIG 0x0304 /* Interrupt Migration */
#define REG_BCNQ_DESA 0x0308 /* TX Beacon Descr Address */
@@ -153,8 +165,11 @@
#define REG_PCIE_HCPWM 0x0363 /* PCIe CPWM */
#define REG_WATCH_DOG 0x0368
+/* RTL8723 series ------------------------------ */
+#define REG_PCIE_HISR 0x03A0
+
/* spec version 11 */
-/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
#define REG_VOQ_INFORMATION 0x0400
#define REG_VIQ_INFORMATION 0x0404
#define REG_BEQ_INFORMATION 0x0408
@@ -208,7 +223,7 @@
#define REG_TX_RPT_TIME 0x04F0 /* 2 byte */
#define REG_DUMMY 0x04FC
-/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
#define REG_EDCA_VO_PARAM 0x0500
#define REG_EDCA_VI_PARAM 0x0504
#define REG_EDCA_BE_PARAM 0x0508
@@ -225,24 +240,21 @@
#define REG_TXPAUSE 0x0522
#define REG_DIS_TXREQ_CLR 0x0523
#define REG_RD_CTRL 0x0524
-/* Format for offset 540h-542h:
- * [3:0]: TBTT prohibit setup in unit of 32us. The time for HW getting
- * beacon content before TBTT.
- *
- * [7:4]: Reserved.
- * [19:8]: TBTT prohibit hold in unit of 32us. The time for HW holding
- * to send the beacon packet.
- *
- * [23:20]: Reserved
- * Description:
- * |
- * |<--Setup--|--Hold------------>|
- * --------------|----------------------
- * |
- * TBTT
- * Note: We cannot update beacon content to HW or send any AC packets during
- * the time between Setup and Hold.
- */
+/* Format for offset 540h-542h: */
+/* [3:0]: TBTT prohibit setup in unit of 32us. The time for HW getting
+ * beacon content before TBTT. */
+/* [7:4]: Reserved. */
+/* [19:8]: TBTT prohibit hold in unit of 32us. The time for HW holding
+ * to send the beacon packet. */
+/* [23:20]: Reserved */
+/* Description: */
+/* | */
+/* |<--Setup--|--Hold------------>| */
+/* --------------|---------------------- */
+/* | */
+/* TBTT */
+/* Note: We cannot update beacon content to HW or send any AC packets during
+ * the time between Setup and Hold. */
#define REG_TBTT_PROHIBIT 0x0540
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
@@ -270,7 +282,7 @@
#define REG_FW_RESET_TSF_CNT_0 0x05FD
#define REG_FW_BCN_DIS_CNT 0x05FE
-/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
#define REG_APSD_CTRL 0x0600
#define REG_BWOPMODE 0x0603
#define REG_TCR 0x0604
@@ -316,14 +328,13 @@
#define RXERR_RPT_RST BIT(27)
#define _RXERR_RPT_SEL(type) ((type) << 28)
-/* Note:
- * The NAV upper value is very important to WiFi 11n 5.2.3 NAV test.
+/* Note: */
+/* The NAV upper value is very important to WiFi 11n 5.2.3 NAV test.
* The default value is always too small, but the WiFi TestPlan test
* by 25,000 microseconds of NAV through sending CTS in the air.
* We must update this value greater than 25,000 microseconds to pass
* the item. The offset of NAV_UPPER in 8192C Spec is incorrect, and
- * the offset should be 0x0652.
- */
+ * the offset should be 0x0652. */
#define REG_NAV_UPPER 0x0652 /* unit of 128 */
/* WMA, BA, CCX */
@@ -358,7 +369,7 @@
#define REG_MACID1 0x0700
#define REG_BSSID1 0x0708
-/* 0xFE00h ~ 0xFE55h USB Configuration */
+/* 0xFE00h ~ 0xFE55h USB Configuration */
#define REG_USB_INFO 0xFE17
#define REG_USB_SPECIAL_OPTION 0xFE55
#define REG_USB_DMA_AGG_TO 0xFE5B
@@ -430,12 +441,39 @@
/* GPIO pins input value */
#define GPIO_IN REG_GPIO_PIN_CTRL
/* GPIO pins output value */
-#define GPIO_OUT (REG_GPIO_PIN_CTRL + 1)
+#define GPIO_OUT (REG_GPIO_PIN_CTRL+1)
/* GPIO pins output enable when a bit is set to "1"; otherwise,
- * input is configured.
- */
-#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL + 2)
-#define GPIO_MOD (REG_GPIO_PIN_CTRL + 3)
+ * input is configured. */
+#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2)
+#define GPIO_MOD (REG_GPIO_PIN_CTRL+3)
+
+/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */
+#define HSIMR_GPIO12_0_INT_EN BIT(0)
+#define HSIMR_SPS_OCP_INT_EN BIT(5)
+#define HSIMR_RON_INT_EN BIT(6)
+#define HSIMR_PDN_INT_EN BIT(7)
+#define HSIMR_GPIO9_INT_EN BIT(25)
+
+/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */
+#define HSISR_GPIO12_0_INT BIT(0)
+#define HSISR_SPS_OCP_INT BIT(5)
+#define HSISR_RON_INT_EN BIT(6)
+#define HSISR_PDNINT BIT(7)
+#define HSISR_GPIO9_INT BIT(25)
+
+/* 8192C (MSR) Media Status Register (Offset 0x4C, 8 bits) */
+/*
+Network Type
+00: No link
+01: Link in ad hoc network
+10: Link in infrastructure network
+11: AP mode
+Default: 00b.
+*/
+#define MSR_NOLINK 0x00
+#define MSR_ADHOC 0x01
+#define MSR_INFRA 0x02
+#define MSR_AP 0x03
/* 88EU (MSR) Media Status Register (Offset 0x4C, 8 bits) */
#define USB_INTR_CONTENT_C2H_OFFSET 0
@@ -455,9 +493,36 @@
#define CMD_EFUSE_PATCH_ERR BIT(6)
#define CMD_IOCONFIG_ERR BIT(7)
+/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */
+/* 8192C Response Rate Set Register (offset 0x181, 24bits) */
+#define RRSR_1M BIT(0)
+#define RRSR_2M BIT(1)
+#define RRSR_5_5M BIT(2)
+#define RRSR_11M BIT(3)
+#define RRSR_6M BIT(4)
+#define RRSR_9M BIT(5)
+#define RRSR_12M BIT(6)
+#define RRSR_18M BIT(7)
+#define RRSR_24M BIT(8)
+#define RRSR_36M BIT(9)
+#define RRSR_48M BIT(10)
+#define RRSR_54M BIT(11)
+#define RRSR_MCS0 BIT(12)
+#define RRSR_MCS1 BIT(13)
+#define RRSR_MCS2 BIT(14)
+#define RRSR_MCS3 BIT(15)
+#define RRSR_MCS4 BIT(16)
+#define RRSR_MCS5 BIT(17)
+#define RRSR_MCS6 BIT(18)
+#define RRSR_MCS7 BIT(19)
+
+/* 8192C Response Rate Set Register (offset 0x1BF, 8bits) */
+/* WOL bit information */
+#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0)
+#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1)
+
/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */
#define BW_OPMODE_20MHZ BIT(2)
-#define BW_OPMODE_5G BIT(1)
/* 8192C CAM Config Setting (offset 0x250, 1 byte) */
#define CAM_VALID BIT(15)
@@ -487,6 +552,12 @@
#define SCR_TxSecEnable 0x02
#define SCR_RxSecEnable 0x04
+/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */
+#define WOW_PMEN BIT(0) /* Power management Enable. */
+#define WOW_WOMEN BIT(1) /* WoW function on or off. */
+#define WOW_MAGIC BIT(2) /* Magic packet */
+#define WOW_UWF BIT(3) /* Unicast Wakeup frame. */
+
/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */
/* 8188 IMR/ISR bits */
#define IMR_DISABLED_88E 0x0
@@ -551,19 +622,33 @@ So the following defines for 92C is not entire!!!!!!
=====================================================================
=====================================================================*/
/*
- * Based on Datasheet V33---090401
- * Register Summary
- * Current IOREG MAP
- * 0x0000h ~ 0x00FFh System Configuration (256 Bytes)
- * 0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes)
- * 0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes)
- * 0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes)
- * 0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes)
- * 0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes)
- * 0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes)
- * 0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes)
- * 0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes)
- */
+Based on Datasheet V33---090401
+Register Summary
+Current IOREG MAP
+0x0000h ~ 0x00FFh System Configuration (256 Bytes)
+0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes)
+0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes)
+0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes)
+0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes)
+0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes)
+0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes)
+0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes)
+0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes)
+*/
+/* 8192C (TXPAUSE) transmission pause (Offset 0x522, 8 bits) */
+/* Note: */
+/* The bits of stopping AC(VO/VI/BE/BK) queue in datasheet
+ * RTL8192S/RTL8192C are wrong, */
+/* the correct arragement is VO - Bit0, VI - Bit1, BE - Bit2,
+ * and BK - Bit3. */
+/* 8723 and 88E may be not correct either in the earlier version. */
+#define StopBecon BIT(6)
+#define StopHigh BIT(5)
+#define StopMgt BIT(4)
+#define StopBK BIT(3)
+#define StopBE BIT(2)
+#define StopVI BIT(1)
+#define StopVO BIT(0)
/* 8192C (RCR) Receive Configuration Register(Offset 0x608, 32 bits) */
#define RCR_APPFCS BIT(31) /* WMAC append FCS after payload */
@@ -582,8 +667,7 @@ So the following defines for 92C is not entire!!!!!!
#define RCR_AICV BIT(9) /* Accept ICV error packet */
#define RCR_ACRC32 BIT(8) /* Accept CRC32 error packet */
#define RCR_CBSSID_BCN BIT(7) /* Accept BSSID match packet
- * (Rx beacon, probe rsp)
- */
+ * (Rx beacon, probe rsp) */
#define RCR_CBSSID_DATA BIT(6) /* Accept BSSID match (Data)*/
#define RCR_CBSSID RCR_CBSSID_DATA /* Accept BSSID match */
#define RCR_APWRMGT BIT(5) /* Accept power management pkt*/
@@ -595,11 +679,17 @@ So the following defines for 92C is not entire!!!!!!
#define RCR_MXDMA_OFFSET 8
#define RCR_FIFO_OFFSET 13
-/* 0xFE00h ~ 0xFE55h USB Configuration */
-#define REG_USB_HRPWM 0xFE58
+/* 0xFE00h ~ 0xFE55h USB Configuration */
+#define REG_USB_INFO 0xFE17
+#define REG_USB_SPECIAL_OPTION 0xFE55
+#define REG_USB_DMA_AGG_TO 0xFE5B
+#define REG_USB_AGG_TO 0xFE5C
+#define REG_USB_AGG_TH 0xFE5D
-/* 8192C Register Bit and Content definition */
-/* 0x0000h ~ 0x00FFh System Configuration */
+#define REG_USB_HRPWM 0xFE58
+#define REG_USB_HCPWM 0xFE57
+/* 8192C Regsiter Bit and Content definition */
+/* 0x0000h ~ 0x00FFh System Configuration */
/* 2 SYS_ISO_CTRL */
#define ISO_MD2PP BIT(0)
@@ -695,7 +785,7 @@ So the following defines for 92C is not entire!!!!!!
/* 2 EFUSE_TEST (For RTL8723 partially) */
#define EF_TRPT BIT(7)
/* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */
-#define EF_CELL_SEL (BIT(8) | BIT(9))
+#define EF_CELL_SEL (BIT(8)|BIT(9))
#define LDOE25_EN BIT(31)
#define EFUSE_SEL(x) (((x) & 0x3) << 8)
#define EFUSE_SEL_MASK 0x300
@@ -711,7 +801,7 @@ So the following defines for 92C is not entire!!!!!!
/* 2 MCUFWDL */
#define MCUFWDL_EN BIT(0)
#define MCUFWDL_RDY BIT(1)
-#define FWDL_CHKSUM_RPT BIT(2)
+#define FWDL_ChkSum_rpt BIT(2)
#define MACINI_RDY BIT(3)
#define BBINI_RDY BIT(4)
#define RFINI_RDY BIT(5)
@@ -732,7 +822,7 @@ So the following defines for 92C is not entire!!!!!!
#define BD_MAC2 BIT(9)
#define BD_MAC1 BIT(10)
#define IC_MACPHY_MODE BIT(11)
-#define CHIP_VER (BIT(12) | BIT(13) | BIT(14) | BIT(15))
+#define CHIP_VER (BIT(12)|BIT(13)|BIT(14)|BIT(15))
#define BT_FUNC BIT(16)
#define VENDOR_ID BIT(19)
#define PAD_HWPD_IDN BIT(22)
@@ -746,9 +836,9 @@ So the following defines for 92C is not entire!!!!!!
#define CHIP_VER_RTL_SHIFT 12
/* 2REG_GPIO_OUTSTS (For RTL8723 only) */
-#define EFS_HCI_SEL (BIT(0) | BIT(1))
-#define PAD_HCI_SEL (BIT(2) | BIT(3))
-#define HCI_SEL (BIT(4) | BIT(5))
+#define EFS_HCI_SEL (BIT(0)|BIT(1))
+#define PAD_HCI_SEL (BIT(2)|BIT(3))
+#define HCI_SEL (BIT(4)|BIT(5))
#define PKG_SEL_HCI BIT(6)
#define FEN_GPS BIT(7)
#define FEN_BT BIT(8)
@@ -765,12 +855,12 @@ So the following defines for 92C is not entire!!!!!!
#define UPHY_SUSB BIT(21)
#define PCI_SUSEN BIT(22)
#define USB_SUSEN BIT(23)
-#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28))
+#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28))
/* 2SYS_CFG */
#define RTL_ID BIT(23) /* TestChip ID, 1:Test(RLE); 0:MP(RL) */
-/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
/* 2 Function Enable Registers */
/* 2 CR */
@@ -828,12 +918,12 @@ So the following defines for 92C is not entire!!!!!!
#define HQSEL_HIQ BIT(5)
/* For normal driver, 0x10C */
-#define _TXDMA_HIQ_MAP(x) (((x) & 0x3) << 14)
-#define _TXDMA_MGQ_MAP(x) (((x) & 0x3) << 12)
-#define _TXDMA_BKQ_MAP(x) (((x) & 0x3) << 10)
-#define _TXDMA_BEQ_MAP(x) (((x) & 0x3) << 8)
-#define _TXDMA_VIQ_MAP(x) (((x) & 0x3) << 6)
-#define _TXDMA_VOQ_MAP(x) (((x) & 0x3) << 4)
+#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14)
+#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12)
+#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10)
+#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8 )
+#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6 )
+#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4 )
#define QUEUE_LOW 1
#define QUEUE_NORMAL 2
@@ -851,7 +941,7 @@ So the following defines for 92C is not entire!!!!!!
#define _LLT_OP(x) (((x) & 0x3) << 30)
#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3)
-/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
/* 2RQPN */
#define _HPQ(x) ((x) & 0xFF)
#define _LPQ(x) (((x) & 0xFF) << 8)
@@ -875,7 +965,7 @@ So the following defines for 92C is not entire!!!!!!
/* 2 TXDMA_OFFSET_CHK */
#define DROP_DATA_EN BIT(9)
-/* 0x0280h ~ 0x028Bh RX DMA Configuration */
+/* 0x0280h ~ 0x028Bh RX DMA Configuration */
/* REG_RXDMA_CONTROL, 0x0286h */
@@ -884,7 +974,7 @@ So the following defines for 92C is not entire!!!!!!
#define RXDMA_IDLE BIT(17)
#define RW_RELEASE_EN BIT(18)
-/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
/* 2 FWHW_TXQ_CTRL */
#define EN_AMPDU_RTY_NEW BIT(7)
@@ -896,7 +986,7 @@ So the following defines for 92C is not entire!!!!!!
#define RETRY_LIMIT_SHORT_SHIFT 8
#define RETRY_LIMIT_LONG_SHIFT 0
-/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
/* 2 EDCA setting */
#define AC_PARAM_TXOP_LIMIT_OFFSET 16
@@ -927,7 +1017,7 @@ So the following defines for 92C is not entire!!!!!!
#define AcmHw_ViqStatus BIT(5)
#define AcmHw_VoqStatus BIT(6)
-/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
/* 2APSD_CTRL */
#define APSDOFF BIT(6)
#define APSDOFF_STATUS BIT(7)
@@ -984,7 +1074,143 @@ So the following defines for 92C is not entire!!!!!!
#define SCR_TXBCUSEDK BIT(6) /* Force Tx Bcast pkt Use Default Key */
#define SCR_RXBCUSEDK BIT(7) /* Force Rx Bcast pkt Use Default Key */
-/* 0xFE00h ~ 0xFE55h USB Configuration */
+/* RTL8188E SDIO Configuration */
+
+/* I/O bus domain address mapping */
+#define SDIO_LOCAL_BASE 0x10250000
+#define WLAN_IOREG_BASE 0x10260000
+#define FIRMWARE_FIFO_BASE 0x10270000
+#define TX_HIQ_BASE 0x10310000
+#define TX_MIQ_BASE 0x10320000
+#define TX_LOQ_BASE 0x10330000
+#define RX_RX0FF_BASE 0x10340000
+
+/* SDIO host local register space mapping. */
+#define SDIO_LOCAL_MSK 0x0FFF
+#define WLAN_IOREG_MSK 0x7FFF
+#define WLAN_FIFO_MSK 0x1FFF /* Aggregation Length[12:0] */
+#define WLAN_RX0FF_MSK 0x0003
+
+/* Without ref to the SDIO Device ID */
+#define SDIO_WITHOUT_REF_DEVICE_ID 0
+#define SDIO_LOCAL_DEVICE_ID 0 /* 0b[16], 000b[15:13] */
+#define WLAN_TX_HIQ_DEVICE_ID 4 /* 0b[16], 100b[15:13] */
+#define WLAN_TX_MIQ_DEVICE_ID 5 /* 0b[16], 101b[15:13] */
+#define WLAN_TX_LOQ_DEVICE_ID 6 /* 0b[16], 110b[15:13] */
+#define WLAN_RX0FF_DEVICE_ID 7 /* 0b[16], 111b[15:13] */
+#define WLAN_IOREG_DEVICE_ID 8 /* 1b[16] */
+
+/* SDIO Tx Free Page Index */
+#define HI_QUEUE_IDX 0
+#define MID_QUEUE_IDX 1
+#define LOW_QUEUE_IDX 2
+#define PUBLIC_QUEUE_IDX 3
+
+#define SDIO_MAX_TX_QUEUE 3 /* HIQ, MIQ and LOQ */
+#define SDIO_MAX_RX_QUEUE 1
+
+/* SDIO Tx Control */
+#define SDIO_REG_TX_CTRL 0x0000
+/* SDIO Host Interrupt Mask */
+#define SDIO_REG_HIMR 0x0014
+/* SDIO Host Interrupt Service Routine */
+#define SDIO_REG_HISR 0x0018
+/* HCI Current Power Mode */
+#define SDIO_REG_HCPWM 0x0019
+/* RXDMA Request Length */
+#define SDIO_REG_RX0_REQ_LEN 0x001C
+/* Free Tx Buffer Page */
+#define SDIO_REG_FREE_TXPG 0x0020
+/* HCI Current Power Mode 1 */
+#define SDIO_REG_HCPWM1 0x0024
+/* HCI Current Power Mode 2 */
+#define SDIO_REG_HCPWM2 0x0026
+/* HTSF Informaion */
+#define SDIO_REG_HTSFR_INFO 0x0030
+/* HCI Request Power Mode 1 */
+#define SDIO_REG_HRPWM1 0x0080
+/* HCI Request Power Mode 2 */
+#define SDIO_REG_HRPWM2 0x0082
+/* HCI Power Save Clock */
+#define SDIO_REG_HPS_CLKR 0x0084
+/* SDIO HCI Suspend Control */
+#define SDIO_REG_HSUS_CTRL 0x0086
+/* SDIO Host Extension Interrupt Mask Always */
+#define SDIO_REG_HIMR_ON 0x0090
+/* SDIO Host Extension Interrupt Status Always */
+#define SDIO_REG_HISR_ON 0x0091
+
+#define SDIO_HIMR_DISABLED 0
+
+/* RTL8188E SDIO Host Interrupt Mask Register */
+#define SDIO_HIMR_RX_REQUEST_MSK BIT(0)
+#define SDIO_HIMR_AVAL_MSK BIT(1)
+#define SDIO_HIMR_TXERR_MSK BIT(2)
+#define SDIO_HIMR_RXERR_MSK BIT(3)
+#define SDIO_HIMR_TXFOVW_MSK BIT(4)
+#define SDIO_HIMR_RXFOVW_MSK BIT(5)
+#define SDIO_HIMR_TXBCNOK_MSK BIT(6)
+#define SDIO_HIMR_TXBCNERR_MSK BIT(7)
+#define SDIO_HIMR_BCNERLY_INT_MSK BIT(16)
+#define SDIO_HIMR_C2HCMD_MSK BIT(17)
+#define SDIO_HIMR_CPWM1_MSK BIT(18)
+#define SDIO_HIMR_CPWM2_MSK BIT(19)
+#define SDIO_HIMR_HSISR_IND_MSK BIT(20)
+#define SDIO_HIMR_GTINT3_IND_MSK BIT(21)
+#define SDIO_HIMR_GTINT4_IND_MSK BIT(22)
+#define SDIO_HIMR_PSTIMEOUT_MSK BIT(23)
+#define SDIO_HIMR_OCPINT_MSK BIT(24)
+#define SDIO_HIMR_ATIMEND_MSK BIT(25)
+#define SDIO_HIMR_ATIMEND_E_MSK BIT(26)
+#define SDIO_HIMR_CTWEND_MSK BIT(27)
+
+/* RTL8188E SDIO Specific */
+#define SDIO_HIMR_MCU_ERR_MSK BIT(28)
+#define SDIO_HIMR_TSF_BIT32_TOGGLE_MSK BIT(29)
+
+/* SDIO Host Interrupt Service Routine */
+#define SDIO_HISR_RX_REQUEST BIT(0)
+#define SDIO_HISR_AVAL BIT(1)
+#define SDIO_HISR_TXERR BIT(2)
+#define SDIO_HISR_RXERR BIT(3)
+#define SDIO_HISR_TXFOVW BIT(4)
+#define SDIO_HISR_RXFOVW BIT(5)
+#define SDIO_HISR_TXBCNOK BIT(6)
+#define SDIO_HISR_TXBCNERR BIT(7)
+#define SDIO_HISR_BCNERLY_INT BIT(16)
+#define SDIO_HISR_C2HCMD BIT(17)
+#define SDIO_HISR_CPWM1 BIT(18)
+#define SDIO_HISR_CPWM2 BIT(19)
+#define SDIO_HISR_HSISR_IND BIT(20)
+#define SDIO_HISR_GTINT3_IND BIT(21)
+#define SDIO_HISR_GTINT4_IND BIT(22)
+#define SDIO_HISR_PSTIME BIT(23)
+#define SDIO_HISR_OCPINT BIT(24)
+#define SDIO_HISR_ATIMEND BIT(25)
+#define SDIO_HISR_ATIMEND_E BIT(26)
+#define SDIO_HISR_CTWEND BIT(27)
+
+/* RTL8188E SDIO Specific */
+#define SDIO_HISR_MCU_ERR BIT(28)
+#define SDIO_HISR_TSF_BIT32_TOGGLE BIT(29)
+
+#define MASK_SDIO_HISR_CLEAR \
+ (SDIO_HISR_TXERR | SDIO_HISR_RXERR | SDIO_HISR_TXFOVW |\
+ SDIO_HISR_RXFOVW | SDIO_HISR_TXBCNOK | SDIO_HISR_TXBCNERR |\
+ SDIO_HISR_C2HCMD | SDIO_HISR_CPWM1 | SDIO_HISR_CPWM2 |\
+ SDIO_HISR_HSISR_IND | SDIO_HISR_GTINT3_IND | SDIO_HISR_GTINT4_IND |\
+ SDIO_HISR_PSTIMEOUT | SDIO_HISR_OCPINT)
+
+/* SDIO HCI Suspend Control Register */
+#define HCI_RESUME_PWR_RDY BIT(1)
+#define HCI_SUS_CTRL BIT(0)
+
+/* SDIO Tx FIFO related */
+/* The number of Tx FIFO free page */
+#define SDIO_TX_FREE_PG_QUEUE 4
+#define SDIO_TX_FIFO_PAGE_SZ 128
+
+/* 0xFE00h ~ 0xFE55h USB Configuration */
/* 2 USB Information (0xFE17) */
#define USB_IS_HIGH_SPEED 0
@@ -1003,12 +1229,10 @@ So the following defines for 92C is not entire!!!!!!
/* 2REG_C2HEVT_CLEAR */
/* Set by driver and notify FW that the driver has read
- * the C2H command message
- */
+ * the C2H command message */
#define C2H_EVT_HOST_CLOSE 0x00
/* Set by FW indicating that FW had set the C2H command
- * message and it's not yet read by driver.
- */
+ * message and it's not yet read by driver. */
#define C2H_EVT_FW_CLOSE 0xFF
/* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */
@@ -1035,6 +1259,14 @@ So the following defines for 92C is not entire!!!!!!
/* GPS function enable */
#define GPS_FUNC_EN BIT(22)
+/* 3 REG_LIFECTRL_CTRL */
+#define HAL92C_EN_PKT_LIFE_TIME_BK BIT(3)
+#define HAL92C_EN_PKT_LIFE_TIME_BE BIT(2)
+#define HAL92C_EN_PKT_LIFE_TIME_VI BIT(1)
+#define HAL92C_EN_PKT_LIFE_TIME_VO BIT(0)
+
+#define HAL92C_MSDU_LIFE_TIME_UNIT 128 /* in us */
+
/* General definitions */
#define LAST_ENTRY_OF_TX_PKT_BUFFER 176 /* 22k 22528 bytes */
@@ -1045,7 +1277,7 @@ So the following defines for 92C is not entire!!!!!!
/* 8192C EEPROM/EFUSE share register definition. */
-/* EEPROM/Efuse PG Offset for 88EE/88EU/88ES */
+/* EEPROM/Efuse PG Offset for 88EE/88EU/88ES */
#define EEPROM_TX_PWR_INX_88E 0x10
#define EEPROM_ChannelPlan_88E 0xB8
@@ -1060,27 +1292,56 @@ So the following defines for 92C is not entire!!!!!!
#define EEPROM_CUSTOMERID_88E 0xC5
#define EEPROM_RF_ANTENNA_OPT_88E 0xC9
+/* RTL88EE */
+#define EEPROM_MAC_ADDR_88EE 0xD0
+#define EEPROM_VID_88EE 0xD6
+#define EEPROM_DID_88EE 0xD8
+#define EEPROM_SVID_88EE 0xDA
+#define EEPROM_SMID_88EE 0xDC
+
/* RTL88EU */
#define EEPROM_MAC_ADDR_88EU 0xD7
#define EEPROM_VID_88EU 0xD0
#define EEPROM_PID_88EU 0xD2
#define EEPROM_USB_OPTIONAL_FUNCTION0 0xD4
-/* EEPROM/Efuse Value Type */
+/* RTL88ES */
+#define EEPROM_MAC_ADDR_88ES 0x11A
+
+/* EEPROM/Efuse Value Type */
#define EETYPE_TX_PWR 0x0
+/* Default Value for EEPROM or EFUSE!!! */
+#define EEPROM_Default_TSSI 0x0
+#define EEPROM_Default_TxPowerDiff 0x0
+#define EEPROM_Default_CrystalCap 0x5
+/* Default: 2X2, RTL8192CE(QFPN68) */
+#define EEPROM_Default_BoardType 0x02
+#define EEPROM_Default_TxPower 0x1010
+#define EEPROM_Default_HT2T_TxPwr 0x10
+
+#define EEPROM_Default_LegacyHTTxPowerDiff 0x3
+#define EEPROM_Default_ThermalMeter 0x12
+
+#define EEPROM_Default_AntTxPowerDiff 0x0
+#define EEPROM_Default_TxPwDiff_CrystalCap 0x5
+#define EEPROM_Default_TxPowerLevel 0x2A
+
+#define EEPROM_Default_HT40_2SDiff 0x0
+/* HT20<->40 default Tx Power Index Difference */
+#define EEPROM_Default_HT20_Diff 2
+#define EEPROM_Default_LegacyHTTxPowerDiff 0x3
+#define EEPROM_Default_HT40_PwrMaxOffset 0
+#define EEPROM_Default_HT20_PwrMaxOffset 0
+
#define EEPROM_Default_CrystalCap_88E 0x20
#define EEPROM_Default_ThermalMeter_88E 0x18
-/* New EFUSE default value */
+/* New EFUSE deafult value */
#define EEPROM_DEFAULT_24G_INDEX 0x2D
#define EEPROM_DEFAULT_24G_HT20_DIFF 0X02
#define EEPROM_DEFAULT_24G_OFDM_DIFF 0X04
-#define EEPROM_DEFAULT_5G_INDEX 0X2A
-#define EEPROM_DEFAULT_5G_HT20_DIFF 0X00
-#define EEPROM_DEFAULT_5G_OFDM_DIFF 0X04
-
#define EEPROM_DEFAULT_DIFF 0XFE
#define EEPROM_DEFAULT_CHANNEL_PLAN 0x7F
#define EEPROM_DEFAULT_BOARD_OPTION 0x00
diff --git a/drivers/staging/r8188eu/include/rtl8188e_sreset.h b/drivers/staging/r8188eu/include/rtl8188e_sreset.h
new file mode 100644
index 000000000000..880c5792d5dd
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtl8188e_sreset.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _RTL8188E_SRESET_H_
+#define _RTL8188E_SRESET_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+#include "rtw_sreset.h"
+
+void rtl8188e_silentreset_for_specific_platform(struct adapter *padapter);
+void rtl8188e_sreset_xmit_status_check(struct adapter *padapter);
+void rtl8188e_sreset_linked_status_check(struct adapter *padapter);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/r8188eu/include/rtl8188e_xmit.h
index 72a2bb812c9a..f1f2ccfc765e 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h
+++ b/drivers/staging/r8188eu/include/rtl8188e_xmit.h
@@ -1,9 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTL8188E_XMIT_H__
#define __RTL8188E_XMIT_H__
@@ -21,24 +18,22 @@
#define QSLT_CMD 0x13
/* For 88e early mode */
-#define SET_EARLYMODE_PKTNUM(__pAddr, __Value) \
- SET_BITS_TO_LE_4BYTE(__pAddr, 0, 3, __Value)
+#define SET_EARLYMODE_PKTNUM(__paddr, __value) \
+ le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(2, 0))
#define SET_EARLYMODE_LEN0(__pAddr, __Value) \
- SET_BITS_TO_LE_4BYTE(__pAddr, 4, 12, __Value)
-#define SET_EARLYMODE_LEN1(__pAddr, __Value) \
- SET_BITS_TO_LE_4BYTE(__pAddr, 16, 12, __Value)
-#define SET_EARLYMODE_LEN2_1(__pAddr, __Value) \
- SET_BITS_TO_LE_4BYTE(__pAddr, 28, 4, __Value)
-#define SET_EARLYMODE_LEN2_2(__pAddr, __Value) \
- SET_BITS_TO_LE_4BYTE(__pAddr + 4, 0, 8, __Value)
+ le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(15, 4))
+#define SET_EARLYMODE_LEN1(__paddr, __value) \
+ le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(27, 16))
+#define SET_EARLYMODE_LEN2_1(__pdr, __vValue) \
+ le32p_replace_bits((__le32 *)__paddr, __value, GENMASK(31, 28))
+#define SET_EARLYMODE_LEN2_2(__paddr, __value) \
+ le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(7, 0))
#define SET_EARLYMODE_LEN3(__pAddr, __Value) \
- SET_BITS_TO_LE_4BYTE(__pAddr + 4, 8, 12, __Value)
-#define SET_EARLYMODE_LEN4(__pAddr, __Value) \
- SET_BITS_TO_LE_4BYTE(__pAddr + 4, 20, 12, __Value)
+ le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(19, 8))
+#define SET_EARLYMODE_LEN4(__paAddr, __vValue) \
+ le32p_replace_bits((__le32 *)(__paddr + 4), __value, GENMASK(31, 20))
-/* */
/* defined for TX DESC Operation */
-/* */
#define MAX_TID (15)
@@ -94,14 +89,13 @@ enum TXDESC_SC {
SC_LOWER = 0x02,
SC_DUPLICATE = 0x03
};
-
/* OFFSET 20 */
#define SGI BIT(6)
#define USB_TXAGG_NUM_SHT 24
#define txdesc_set_ccx_sw_88e(txdesc, value) \
do { \
- ((struct txdesc_88e *)(txdesc))->sw1 = (((value) >> 8) & 0x0f); \
+ ((struct txdesc_88e *)(txdesc))->sw1 = (((value)>>8) & 0x0f); \
((struct txdesc_88e *)(txdesc))->sw0 = ((value) & 0xff); \
} while (0)
@@ -139,18 +133,17 @@ struct txrpt_ccx_88e {
u8 sw0;
};
-#define txrpt_ccx_sw_88e(txrpt_ccx) ((txrpt_ccx)->sw0 + ((txrpt_ccx)->sw1 << 8))
-#define txrpt_ccx_qtime_88e(txrpt_ccx) \
- ((txrpt_ccx)->ccx_qtime0 + ((txrpt_ccx)->ccx_qtime1 << 8))
-
void rtl8188e_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc,
u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull);
s32 rtl8188eu_init_xmit_priv(struct adapter *padapter);
+s32 rtl8188eu_hal_xmit(struct adapter *padapter, struct xmit_frame *frame);
+s32 rtl8188eu_mgnt_xmit(struct adapter *padapter, struct xmit_frame *frame);
s32 rtl8188eu_xmit_buf_handler(struct adapter *padapter);
#define hal_xmit_handler rtl8188eu_xmit_buf_handler
-void rtl8188eu_xmit_tasklet(struct tasklet_struct *t);
-bool rtl8188eu_xmitframe_complete(struct adapter *padapter,
- struct xmit_priv *pxmitpriv);
+void rtl8188eu_xmit_tasklet(unsigned long priv);
+s32 rtl8188eu_xmitframe_complete(struct adapter *padapter,
+ struct xmit_priv *pxmitpriv,
+ struct xmit_buf *pxmitbuf);
void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf);
diff --git a/drivers/staging/rtl8188eu/include/rtw_ap.h b/drivers/staging/r8188eu/include/rtw_ap.h
index 7a4203bce473..2eb556968509 100644
--- a/drivers/staging/rtl8188eu/include/rtw_ap.h
+++ b/drivers/staging/r8188eu/include/rtw_ap.h
@@ -1,14 +1,11 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
#ifndef __RTW_AP_H_
#define __RTW_AP_H_
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "osdep_service.h"
+#include "drv_types.h"
#ifdef CONFIG_88EU_AP_MODE
@@ -26,10 +23,12 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta,
void expire_timeout_chk(struct adapter *padapter);
void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta);
int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len);
+void rtw_ap_restore_network(struct adapter *padapter);
void rtw_set_macaddr_acl(struct adapter *padapter, int mode);
int rtw_acl_add_sta(struct adapter *padapter, u8 *addr);
int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr);
+#ifdef CONFIG_88EU_AP_MODE
void associated_clients_update(struct adapter *padapter, u8 updated);
void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta);
u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta);
@@ -38,8 +37,11 @@ void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta);
u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta,
bool active, u16 reason);
int rtw_sta_flush(struct adapter *padapter);
+int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset);
void start_ap_mode(struct adapter *padapter);
void stop_ap_mode(struct adapter *padapter);
+#endif
#endif /* end of CONFIG_88EU_AP_MODE */
+void update_bmc_sta(struct adapter *padapter);
#endif
diff --git a/drivers/staging/r8188eu/include/rtw_br_ext.h b/drivers/staging/r8188eu/include/rtw_br_ext.h
new file mode 100644
index 000000000000..69905d30c191
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_br_ext.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _RTW_BR_EXT_H_
+#define _RTW_BR_EXT_H_
+
+#define MACADDRLEN 6
+#define _DEBUG_ERR DBG_88E
+#define _DEBUG_INFO DBG_88E
+#define DEBUG_WARN DBG_88E
+#define DEBUG_INFO DBG_88E
+#define DEBUG_ERR DBG_88E
+#define GET_MY_HWADDR(padapter) ((padapter)->eeprompriv.mac_addr)
+
+#define NAT25_HASH_BITS 4
+#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS)
+#define NAT25_AGEING_TIME 300
+
+#define MAX_NETWORK_ADDR_LEN 17
+
+struct nat25_network_db_entry {
+ struct nat25_network_db_entry *next_hash;
+ struct nat25_network_db_entry **pprev_hash;
+ atomic_t use_count;
+ unsigned char macAddr[6];
+ unsigned long ageing_timer;
+ unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
+};
+
+enum NAT25_METHOD {
+ NAT25_MIN,
+ NAT25_CHECK,
+ NAT25_INSERT,
+ NAT25_PARSE,
+ NAT25_MAX
+};
+
+struct br_ext_info {
+ unsigned int nat25_disable;
+ unsigned int macclone_enable;
+ unsigned int dhcp_bcst_disable;
+ int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */
+ unsigned char nat25_dmzMac[MACADDRLEN];
+ unsigned int nat25sc_disable;
+};
+
+void nat25_db_cleanup(struct adapter *priv);
+
+#endif /* _RTW_BR_EXT_H_ */
diff --git a/drivers/staging/r8188eu/include/rtw_cmd.h b/drivers/staging/r8188eu/include/rtw_cmd.h
new file mode 100644
index 000000000000..c14d9052b997
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_cmd.h
@@ -0,0 +1,975 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTW_CMD_H_
+#define __RTW_CMD_H_
+
+#include "wlan_bssdef.h"
+#include "rtw_rf.h"
+#include "rtw_led.h"
+
+#define C2H_MEM_SZ (16*1024)
+
+#include "osdep_service.h"
+#include "ieee80211.h" /* <ieee80211/ieee80211.h> */
+
+#define FREE_CMDOBJ_SZ 128
+
+#define MAX_CMDSZ 1024
+#define MAX_RSPSZ 512
+#define MAX_EVTSZ 1024
+
+#define CMDBUFF_ALIGN_SZ 512
+
+struct cmd_obj {
+ struct adapter *padapter;
+ u16 cmdcode;
+ u8 res;
+ u8 *parmbuf;
+ u32 cmdsz;
+ u8 *rsp;
+ u32 rspsz;
+ struct list_head list;
+};
+
+struct cmd_priv {
+ struct semaphore cmd_queue_sema;
+ struct semaphore terminate_cmdthread_sema;
+ struct __queue cmd_queue;
+ u8 cmd_seq;
+ u8 *cmd_buf; /* shall be non-paged, and 4 bytes aligned */
+ u8 *cmd_allocated_buf;
+ u8 *rsp_buf; /* shall be non-paged, and 4 bytes aligned */
+ u8 *rsp_allocated_buf;
+ u32 cmd_issued_cnt;
+ u32 cmd_done_cnt;
+ u32 rsp_cnt;
+ u8 cmdthd_running;
+ struct adapter *padapter;
+};
+
+struct evt_priv {
+ struct work_struct c2h_wk;
+ bool c2h_wk_alive;
+ struct rtw_cbuf *c2h_queue;
+ #define C2H_QUEUE_MAX_LEN 10
+ atomic_t event_seq;
+ u8 *evt_buf; /* shall be non-paged, and 4 bytes aligned */
+ u8 *evt_allocated_buf;
+ u32 evt_done_cnt;
+};
+
+#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \
+do {\
+ INIT_LIST_HEAD(&pcmd->list);\
+ pcmd->cmdcode = code;\
+ pcmd->parmbuf = (u8 *)(pparm);\
+ pcmd->cmdsz = sizeof(*pparm);\
+ pcmd->rsp = NULL;\
+ pcmd->rspsz = 0;\
+} while (0)
+
+struct c2h_evt_hdr {
+ u8 id:4;
+ u8 plen:4;
+ u8 seq;
+ u8 payload[0];
+};
+
+#define c2h_evt_exist(c2h_evt) ((c2h_evt)->id || (c2h_evt)->plen)
+
+u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
+struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv);
+void rtw_free_cmd_obj(struct cmd_obj *pcmd);
+
+int rtw_cmd_thread(void *context);
+
+u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv);
+void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv);
+
+u32 rtw_init_evt_priv(struct evt_priv *pevtpriv);
+void rtw_free_evt_priv(struct evt_priv *pevtpriv);
+void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv);
+void rtw_evt_notify_isr(struct evt_priv *pevtpriv);
+#ifdef CONFIG_88EU_P2P
+u8 p2p_protocol_wk_cmd(struct adapter *padapter, int intCmdType);
+#endif /* CONFIG_88EU_P2P */
+
+enum rtw_drvextra_cmd_id {
+ NONE_WK_CID,
+ DYNAMIC_CHK_WK_CID,
+ DM_CTRL_WK_CID,
+ PBC_POLLING_WK_CID,
+ POWER_SAVING_CTRL_WK_CID,/* IPS,AUTOSuspend */
+ LPS_CTRL_WK_CID,
+ ANT_SELECT_WK_CID,
+ P2P_PS_WK_CID,
+ P2P_PROTO_WK_CID,
+ CHECK_HIQ_WK_CID,/* for softap mode, check hi queue if empty */
+ INTEl_WIDI_WK_CID,
+ C2H_WK_CID,
+ RTP_TIMER_CFG_WK_CID,
+ MAX_WK_CID
+};
+
+enum LPS_CTRL_TYPE {
+ LPS_CTRL_SCAN = 0,
+ LPS_CTRL_JOINBSS = 1,
+ LPS_CTRL_CONNECT = 2,
+ LPS_CTRL_DISCONNECT = 3,
+ LPS_CTRL_SPECIAL_PACKET = 4,
+ LPS_CTRL_LEAVE = 5,
+};
+
+enum RFINTFS {
+ SWSI,
+ HWSI,
+ HWPI,
+};
+
+/*
+Caller Mode: Infra, Ad-HoC(C)
+
+Notes: To enter USB suspend mode
+
+Command Mode
+
+*/
+struct usb_suspend_parm {
+ u32 action;/* 1: sleep, 0:resume */
+};
+
+/*
+Caller Mode: Infra, Ad-HoC
+
+Notes: To join a known BSS.
+
+Command-Event Mode
+
+*/
+
+/*
+Caller Mode: Infra, Ad-Hoc
+
+Notes: To join the specified bss
+
+Command Event Mode
+
+*/
+struct joinbss_parm {
+ struct wlan_bssid_ex network;
+};
+
+/*
+Caller Mode: Infra, Ad-HoC(C)
+
+Notes: To disconnect the current associated BSS
+
+Command Mode
+
+*/
+struct disconnect_parm {
+ u32 deauth_timeout_ms;
+};
+
+/*
+Caller Mode: AP, Ad-HoC(M)
+
+Notes: To create a BSS
+
+Command Mode
+*/
+struct createbss_parm {
+ struct wlan_bssid_ex network;
+};
+
+struct setopmode_parm {
+ u8 mode;
+ u8 rsvd[3];
+};
+
+/*
+Caller Mode: AP, Ad-HoC, Infra
+
+Notes: To ask RTL8711 performing site-survey
+
+Command-Event Mode
+
+*/
+
+#define RTW_SSID_SCAN_AMOUNT 9 /* for WEXT_CSCAN_AMOUNT 9 */
+#define RTW_CHANNEL_SCAN_AMOUNT (14+37)
+struct sitesurvey_parm {
+ int scan_mode; /* active: 1, passive: 0 */
+ u8 ssid_num;
+ u8 ch_num;
+ struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
+ struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
+};
+
+/*
+Caller Mode: Any
+
+Notes: To set the auth type of RTL8711. open/shared/802.1x
+
+Command Mode
+
+*/
+struct setauth_parm {
+ u8 mode; /* 0: legacy open, 1: legacy shared 2: 802.1x */
+ u8 _1x; /* 0: PSK, 1: TLS */
+ u8 rsvd[2];
+};
+
+/*
+Caller Mode: Infra
+
+a. algorithm: wep40, wep104, tkip & aes
+b. keytype: grp key/unicast key
+c. key contents
+
+when shared key ==> keyid is the camid
+when 802.1x ==> keyid [0:1] ==> grp key
+when 802.1x ==> keyid > 2 ==> unicast key
+
+*/
+struct setkey_parm {
+ u8 algorithm; /* could be none, wep40, TKIP, CCMP, wep104 */
+ u8 keyid;
+ u8 grpkey; /* 1: this is the grpkey for 802.1x.
+ * 0: this is the unicast key for 802.1x */
+ u8 set_tx; /* 1: main tx key for wep. 0: other key. */
+ u8 key[16]; /* this could be 40 or 104 */
+};
+
+/*
+When in AP or Ad-Hoc mode, this is used to
+allocate an sw/hw entry for a newly associated sta.
+
+Command
+
+when shared key ==> algorithm/keyid
+
+*/
+struct set_stakey_parm {
+ u8 addr[ETH_ALEN];
+ u8 algorithm;
+ u8 id;/* currently for erasing cam entry if
+ * algorithm == _NO_PRIVACY_ */
+ u8 key[16];
+};
+
+struct set_stakey_rsp {
+ u8 addr[ETH_ALEN];
+ u8 keyid;
+ u8 rsvd;
+};
+
+/*
+Caller Ad-Hoc/AP
+
+Command -Rsp(AID == CAMID) mode
+
+This is to force fw to add an sta_data entry per driver's request.
+
+FW will write an cam entry associated with it.
+
+*/
+struct set_assocsta_parm {
+ u8 addr[ETH_ALEN];
+};
+
+struct set_assocsta_rsp {
+ u8 cam_id;
+ u8 rsvd[3];
+};
+
+/*
+ Caller Ad-Hoc/AP
+
+ Command mode
+
+ This is to force fw to del an sta_data entry per driver's request
+
+ FW will invalidate the cam entry associated with it.
+
+*/
+struct del_assocsta_parm {
+ u8 addr[ETH_ALEN];
+};
+
+/*
+Caller Mode: AP/Ad-HoC(M)
+
+Notes: To notify fw that given staid has changed its power state
+
+Command Mode
+
+*/
+struct setstapwrstate_parm {
+ u8 staid;
+ u8 status;
+ u8 hwaddr[6];
+};
+
+/*
+Caller Mode: Any
+
+Notes: To setup the basic rate of RTL8711
+
+Command Mode
+
+*/
+struct setbasicrate_parm {
+ u8 basicrates[NumRates];
+};
+
+/*
+Caller Mode: Any
+
+Notes: To read the current basic rate
+
+Command-Rsp Mode
+
+*/
+struct getbasicrate_parm {
+ u32 rsvd;
+};
+
+struct getbasicrate_rsp {
+ u8 basicrates[NumRates];
+};
+
+/*
+Caller Mode: Any
+
+Notes: To setup the data rate of RTL8711
+
+Command Mode
+
+*/
+struct setdatarate_parm {
+ u8 mac_id;
+ u8 datarates[NumRates];
+};
+
+/*
+Caller Mode: Any
+
+Notes: To read the current data rate
+
+Command-Rsp Mode
+
+*/
+struct getdatarate_parm {
+ u32 rsvd;
+
+};
+struct getdatarate_rsp {
+ u8 datarates[NumRates];
+};
+
+/*
+Caller Mode: Any
+AP: AP can use the info for the contents of beacon frame
+Infra: STA can use the info when sitesurveying
+Ad-HoC(M): Like AP
+Ad-HoC(C): Like STA
+
+Notes: To set the phy capability of the NIC
+
+Command Mode
+
+*/
+
+struct setphyinfo_parm {
+ struct regulatory_class class_sets[NUM_REGULATORYS];
+ u8 status;
+};
+
+struct getphyinfo_parm {
+ u32 rsvd;
+};
+
+struct getphyinfo_rsp {
+ struct regulatory_class class_sets[NUM_REGULATORYS];
+ u8 status;
+};
+
+/*
+Caller Mode: Any
+
+Notes: To set the channel/modem/band
+This command will be used when channel/modem/band is changed.
+
+Command Mode
+
+*/
+struct setphy_parm {
+ u8 rfchannel;
+ u8 modem;
+};
+
+/*
+Caller Mode: Any
+
+Notes: To get the current setting of channel/modem/band
+
+Command-Rsp Mode
+
+*/
+struct getphy_parm {
+ u32 rsvd;
+
+};
+struct getphy_rsp {
+ u8 rfchannel;
+ u8 modem;
+};
+
+struct readBB_parm {
+ u8 offset;
+};
+struct readBB_rsp {
+ u8 value;
+};
+
+struct readTSSI_parm {
+ u8 offset;
+};
+struct readTSSI_rsp {
+ u8 value;
+};
+
+struct writeBB_parm {
+ u8 offset;
+ u8 value;
+};
+
+struct readRF_parm {
+ u8 offset;
+};
+struct readRF_rsp {
+ u32 value;
+};
+
+struct writeRF_parm {
+ u32 offset;
+ u32 value;
+};
+
+struct getrfintfs_parm {
+ u8 rfintfs;
+};
+
+struct Tx_Beacon_param
+{
+ struct wlan_bssid_ex network;
+};
+
+/*
+ Notes: This command is used for H2C/C2H loopback testing
+
+ mac[0] == 0
+ ==> CMD mode, return H2C_SUCCESS.
+ The following condition must be ture under CMD mode
+ mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0;
+ s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7;
+ s2 == (b1 << 8 | b0);
+
+ mac[0] == 1
+ ==> CMD_RSP mode, return H2C_SUCCESS_RSP
+
+ The rsp layout shall be:
+ rsp: parm:
+ mac[0] = mac[5];
+ mac[1] = mac[4];
+ mac[2] = mac[3];
+ mac[3] = mac[2];
+ mac[4] = mac[1];
+ mac[5] = mac[0];
+ s0 = s1;
+ s1 = swap16(s0);
+ w0 = swap32(w1);
+ b0 = b1
+ s2 = s0 + s1
+ b1 = b0
+ w1 = w0
+
+ mac[0] == 2
+ ==> CMD_EVENT mode, return H2C_SUCCESS
+ The event layout shall be:
+ event: parm:
+ mac[0] = mac[5];
+ mac[1] = mac[4];
+ mac[2] = event's seq no, starting from 1 to parm's marc[3]
+ mac[3] = mac[2];
+ mac[4] = mac[1];
+ mac[5] = mac[0];
+ s0 = swap16(s0) - event.mac[2];
+ s1 = s1 + event.mac[2];
+ w0 = swap32(w0);
+ b0 = b1
+ s2 = s0 + event.mac[2]
+ b1 = b0
+ w1 = swap32(w1) - event.mac[2];
+
+ parm->mac[3] is the total event counts that host requested.
+ event will be the same with the cmd's param.
+*/
+
+/* CMD param Format for driver extra cmd handler */
+struct drvextra_cmd_parm {
+ int ec_id; /* extra cmd id */
+ int type_size; /* Can use this field as the type id or command size */
+ unsigned char *pbuf;
+};
+
+/*------------------- Below are used for RF/BB tunning ---------------------*/
+
+struct setantenna_parm {
+ u8 tx_antset;
+ u8 rx_antset;
+ u8 tx_antenna;
+ u8 rx_antenna;
+};
+
+struct enrateadaptive_parm {
+ u32 en;
+};
+
+struct settxagctbl_parm {
+ u32 txagc[MAX_RATES_LENGTH];
+};
+
+struct gettxagctbl_parm {
+ u32 rsvd;
+};
+struct gettxagctbl_rsp {
+ u32 txagc[MAX_RATES_LENGTH];
+};
+
+struct setagcctrl_parm {
+ u32 agcctrl; /* 0: pure hw, 1: fw */
+};
+
+struct setssup_parm {
+ u32 ss_ForceUp[MAX_RATES_LENGTH];
+};
+
+struct getssup_parm {
+ u32 rsvd;
+};
+
+struct getssup_rsp {
+ u8 ss_ForceUp[MAX_RATES_LENGTH];
+};
+
+struct setssdlevel_parm {
+ u8 ss_DLevel[MAX_RATES_LENGTH];
+};
+
+struct getssdlevel_parm {
+ u32 rsvd;
+};
+
+struct getssdlevel_rsp {
+ u8 ss_DLevel[MAX_RATES_LENGTH];
+};
+
+struct setssulevel_parm {
+ u8 ss_ULevel[MAX_RATES_LENGTH];
+};
+
+struct getssulevel_parm {
+ u32 rsvd;
+};
+
+struct getssulevel_rsp {
+ u8 ss_ULevel[MAX_RATES_LENGTH];
+};
+
+struct setcountjudge_parm {
+ u8 count_judge[MAX_RATES_LENGTH];
+};
+
+struct getcountjudge_parm {
+ u32 rsvd;
+};
+
+struct getcountjudge_rsp {
+ u8 count_judge[MAX_RATES_LENGTH];
+};
+
+struct setratable_parm {
+ u8 ss_ForceUp[NumRates];
+ u8 ss_ULevel[NumRates];
+ u8 ss_DLevel[NumRates];
+ u8 count_judge[NumRates];
+};
+
+struct getratable_parm {
+ uint rsvd;
+};
+
+struct getratable_rsp {
+ u8 ss_ForceUp[NumRates];
+ u8 ss_ULevel[NumRates];
+ u8 ss_DLevel[NumRates];
+ u8 count_judge[NumRates];
+};
+
+/* to get TX,RX retry count */
+
+struct gettxretrycnt_parm {
+ unsigned int rsvd;
+};
+
+struct gettxretrycnt_rsp {
+ unsigned long tx_retrycnt;
+};
+
+struct getrxretrycnt_parm {
+ unsigned int rsvd;
+};
+
+struct getrxretrycnt_rsp {
+ unsigned long rx_retrycnt;
+};
+
+/* to get BCNOK,BCNERR count */
+struct getbcnokcnt_parm {
+ unsigned int rsvd;
+};
+
+struct getbcnokcnt_rsp {
+ unsigned long bcnokcnt;
+};
+
+struct getbcnerrcnt_parm {
+ unsigned int rsvd;
+};
+
+struct getbcnerrcnt_rsp {
+ unsigned long bcnerrcnt;
+};
+
+/* to get current TX power level */
+struct getcurtxpwrlevel_parm {
+ unsigned int rsvd;
+};
+struct getcurtxpwrlevel_rspi {
+ unsigned short tx_power;
+};
+
+struct setprobereqextraie_parm {
+ unsigned char e_id;
+ unsigned char ie_len;
+ unsigned char ie[0];
+};
+
+struct setassocreqextraie_parm {
+ unsigned char e_id;
+ unsigned char ie_len;
+ unsigned char ie[0];
+};
+
+struct setproberspextraie_parm {
+ unsigned char e_id;
+ unsigned char ie_len;
+ unsigned char ie[0];
+};
+
+struct setassocrspextraie_parm {
+ unsigned char e_id;
+ unsigned char ie_len;
+ unsigned char ie[0];
+};
+
+struct addBaReq_parm {
+ unsigned int tid;
+ u8 addr[ETH_ALEN];
+};
+
+/*H2C Handler index: 46 */
+struct set_ch_parm {
+ u8 ch;
+ u8 bw;
+ u8 ch_offset;
+};
+
+/*H2C Handler index: 59 */
+struct SetChannelPlan_param
+{
+ u8 channel_plan;
+};
+
+/*H2C Handler index: 60 */
+struct LedBlink_param
+{
+ struct LED_871x *pLed;
+};
+
+/*H2C Handler index: 61 */
+struct SetChannelSwitch_param
+{
+ u8 new_ch_no;
+};
+
+/*H2C Handler index: 62 */
+struct TDLSoption_param
+{
+ u8 addr[ETH_ALEN];
+ u8 option;
+};
+
+#define GEN_CMD_CODE(cmd) cmd ## _CMD_
+
+/*
+
+Result:
+0x00: success
+0x01: success, and check Response.
+0x02: cmd ignored due to duplicated sequcne number
+0x03: cmd dropped due to invalid cmd code
+0x04: reserved.
+
+*/
+
+#define H2C_RSP_OFFSET 512
+
+#define H2C_SUCCESS 0x00
+#define H2C_SUCCESS_RSP 0x01
+#define H2C_DUPLICATED 0x02
+#define H2C_DROPPED 0x03
+#define H2C_PARAMETERS_ERROR 0x04
+#define H2C_REJECTED 0x05
+#define H2C_CMD_OVERFLOW 0x06
+#define H2C_RESERVED 0x07
+
+u8 rtw_setassocsta_cmd(struct adapter *padapter, u8 *mac_addr);
+u8 rtw_setstandby_cmd(struct adapter *padapter, uint action);
+u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid,
+ int ssid_num, struct rtw_ieee80211_channel *ch,
+ int ch_num);
+u8 rtw_createbss_cmd(struct adapter *padapter);
+u8 rtw_createbss_cmd_ex(struct adapter *padapter, unsigned char *pbss,
+ unsigned int sz);
+u8 rtw_setphy_cmd(struct adapter *padapter, u8 modem, u8 ch);
+u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key);
+u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue);
+u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network* pnetwork);
+u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue);
+u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra networktype);
+u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset);
+u8 rtw_setbasicrate_cmd(struct adapter *padapter, u8 *rateset);
+u8 rtw_setbbreg_cmd(struct adapter * padapter, u8 offset, u8 val);
+u8 rtw_setrfreg_cmd(struct adapter * padapter, u8 offset, u32 val);
+u8 rtw_getbbreg_cmd(struct adapter * padapter, u8 offset, u8 * pval);
+u8 rtw_getrfreg_cmd(struct adapter * padapter, u8 offset, u8 * pval);
+u8 rtw_setrfintfs_cmd(struct adapter *padapter, u8 mode);
+u8 rtw_setrttbl_cmd(struct adapter *padapter, struct setratable_parm *prate_table);
+u8 rtw_getrttbl_cmd(struct adapter *padapter, struct getratable_rsp *pval);
+
+u8 rtw_gettssi_cmd(struct adapter *padapter, u8 offset,u8 *pval);
+u8 rtw_setfwdig_cmd(struct adapter*padapter, u8 type);
+u8 rtw_setfwra_cmd(struct adapter*padapter, u8 type);
+
+u8 rtw_addbareq_cmd(struct adapter*padapter, u8 tid, u8 *addr);
+
+u8 rtw_dynamic_chk_wk_cmd(struct adapter *adapter);
+
+u8 rtw_lps_ctrl_wk_cmd(struct adapter*padapter, u8 lps_ctrl_type, u8 enqueue);
+u8 rtw_rpt_timer_cfg_cmd(struct adapter*padapter, u16 minRptTime);
+
+ u8 rtw_antenna_select_cmd(struct adapter*padapter, u8 antenna,u8 enqueue);
+u8 rtw_ps_cmd(struct adapter*padapter);
+
+#ifdef CONFIG_88EU_AP_MODE
+u8 rtw_chk_hi_queue_cmd(struct adapter*padapter);
+#endif
+
+u8 rtw_set_ch_cmd(struct adapter*padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue);
+u8 rtw_set_chplan_cmd(struct adapter*padapter, u8 chplan, u8 enqueue);
+u8 rtw_led_blink_cmd(struct adapter*padapter, struct LED_871x * pLed);
+u8 rtw_set_csa_cmd(struct adapter*padapter, u8 new_ch_no);
+u8 rtw_tdls_cmd(struct adapter *padapter, u8 *addr, u8 option);
+
+u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt);
+
+u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf);
+
+void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
+void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
+void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
+void rtw_createbss_cmd_callback(struct adapter *adapt, struct cmd_obj *pcmd);
+void rtw_getbbrfreg_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
+void rtw_readtssi_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
+
+void rtw_setstaKey_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
+void rtw_setassocsta_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cm);
+void rtw_getrttbl_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
+
+struct _cmd_callback {
+ u32 cmd_code;
+ void (*callback)(struct adapter *padapter, struct cmd_obj *cmd);
+};
+
+enum rtw_h2c_cmd {
+ GEN_CMD_CODE(_Read_MACREG), /*0*/
+ GEN_CMD_CODE(_Write_MACREG),
+ GEN_CMD_CODE(_Read_BBREG),
+ GEN_CMD_CODE(_Write_BBREG),
+ GEN_CMD_CODE(_Read_RFREG),
+ GEN_CMD_CODE(_Write_RFREG), /*5*/
+ GEN_CMD_CODE(_Read_EEPROM),
+ GEN_CMD_CODE(_Write_EEPROM),
+ GEN_CMD_CODE(_Read_EFUSE),
+ GEN_CMD_CODE(_Write_EFUSE),
+
+ GEN_CMD_CODE(_Read_CAM), /*10*/
+ GEN_CMD_CODE(_Write_CAM),
+ GEN_CMD_CODE(_setBCNITV),
+ GEN_CMD_CODE(_setMBIDCFG),
+ GEN_CMD_CODE(_JoinBss), /*14*/
+ GEN_CMD_CODE(_DisConnect), /*15*/
+ GEN_CMD_CODE(_CreateBss),
+ GEN_CMD_CODE(_SetOpMode),
+ GEN_CMD_CODE(_SiteSurvey), /*18*/
+ GEN_CMD_CODE(_SetAuth),
+
+ GEN_CMD_CODE(_SetKey), /*20*/
+ GEN_CMD_CODE(_SetStaKey),
+ GEN_CMD_CODE(_SetAssocSta),
+ GEN_CMD_CODE(_DelAssocSta),
+ GEN_CMD_CODE(_SetStaPwrState),
+ GEN_CMD_CODE(_SetBasicRate), /*25*/
+ GEN_CMD_CODE(_GetBasicRate),
+ GEN_CMD_CODE(_SetDataRate),
+ GEN_CMD_CODE(_GetDataRate),
+ GEN_CMD_CODE(_SetPhyInfo),
+
+ GEN_CMD_CODE(_GetPhyInfo), /*30*/
+ GEN_CMD_CODE(_SetPhy),
+ GEN_CMD_CODE(_GetPhy),
+ GEN_CMD_CODE(_readRssi),
+ GEN_CMD_CODE(_readGain),
+ GEN_CMD_CODE(_SetAtim), /*35*/
+ GEN_CMD_CODE(_SetPwrMode),
+ GEN_CMD_CODE(_JoinbssRpt),
+ GEN_CMD_CODE(_SetRaTable),
+ GEN_CMD_CODE(_GetRaTable),
+
+ GEN_CMD_CODE(_GetCCXReport), /*40*/
+ GEN_CMD_CODE(_GetDTMReport),
+ GEN_CMD_CODE(_GetTXRateStatistics),
+ GEN_CMD_CODE(_SetUsbSuspend),
+ GEN_CMD_CODE(_SetH2cLbk),
+ GEN_CMD_CODE(_AddBAReq), /*45*/
+ GEN_CMD_CODE(_SetChannel), /*46*/
+ GEN_CMD_CODE(_SetTxPower),
+ GEN_CMD_CODE(_SwitchAntenna),
+ GEN_CMD_CODE(_SetCrystalCap),
+ GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/
+
+ GEN_CMD_CODE(_SetSingleToneTx),/*51*/
+ GEN_CMD_CODE(_SetCarrierSuppressionTx),
+ GEN_CMD_CODE(_SetContinuousTx),
+ GEN_CMD_CODE(_SwitchBandwidth), /*54*/
+ GEN_CMD_CODE(_TX_Beacon), /*55*/
+
+ GEN_CMD_CODE(_Set_MLME_EVT), /*56*/
+ GEN_CMD_CODE(_Set_Drv_Extra), /*57*/
+ GEN_CMD_CODE(_Set_H2C_MSG), /*58*/
+
+ GEN_CMD_CODE(_SetChannelPlan), /*59*/
+ GEN_CMD_CODE(_LedBlink), /*60*/
+
+ GEN_CMD_CODE(_SetChannelSwitch), /*61*/
+ GEN_CMD_CODE(_TDLS), /*62*/
+
+ MAX_H2CCMD
+};
+
+#define _GetBBReg_CMD_ _Read_BBREG_CMD_
+#define _SetBBReg_CMD_ _Write_BBREG_CMD_
+#define _GetRFReg_CMD_ _Read_RFREG_CMD_
+#define _SetRFReg_CMD_ _Write_RFREG_CMD_
+
+#ifdef _RTW_CMD_C_
+static struct _cmd_callback rtw_cmd_callback[] =
+{
+ {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
+ {GEN_CMD_CODE(_Write_MACREG), NULL},
+ {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback},
+ {GEN_CMD_CODE(_Write_BBREG), NULL},
+ {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback},
+ {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
+ {GEN_CMD_CODE(_Read_EEPROM), NULL},
+ {GEN_CMD_CODE(_Write_EEPROM), NULL},
+ {GEN_CMD_CODE(_Read_EFUSE), NULL},
+ {GEN_CMD_CODE(_Write_EFUSE), NULL},
+
+ {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/
+ {GEN_CMD_CODE(_Write_CAM), NULL},
+ {GEN_CMD_CODE(_setBCNITV), NULL},
+ {GEN_CMD_CODE(_setMBIDCFG), NULL},
+ {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback}, /*14*/
+ {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, /*15*/
+ {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback},
+ {GEN_CMD_CODE(_SetOpMode), NULL},
+ {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, /*18*/
+ {GEN_CMD_CODE(_SetAuth), NULL},
+
+ {GEN_CMD_CODE(_SetKey), NULL}, /*20*/
+ {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback},
+ {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback},
+ {GEN_CMD_CODE(_DelAssocSta), NULL},
+ {GEN_CMD_CODE(_SetStaPwrState), NULL},
+ {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
+ {GEN_CMD_CODE(_GetBasicRate), NULL},
+ {GEN_CMD_CODE(_SetDataRate), NULL},
+ {GEN_CMD_CODE(_GetDataRate), NULL},
+ {GEN_CMD_CODE(_SetPhyInfo), NULL},
+
+ {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
+ {GEN_CMD_CODE(_SetPhy), NULL},
+ {GEN_CMD_CODE(_GetPhy), NULL},
+ {GEN_CMD_CODE(_readRssi), NULL},
+ {GEN_CMD_CODE(_readGain), NULL},
+ {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
+ {GEN_CMD_CODE(_SetPwrMode), NULL},
+ {GEN_CMD_CODE(_JoinbssRpt), NULL},
+ {GEN_CMD_CODE(_SetRaTable), NULL},
+ {GEN_CMD_CODE(_GetRaTable), NULL},
+
+ {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
+ {GEN_CMD_CODE(_GetDTMReport), NULL},
+ {GEN_CMD_CODE(_GetTXRateStatistics), NULL},
+ {GEN_CMD_CODE(_SetUsbSuspend), NULL},
+ {GEN_CMD_CODE(_SetH2cLbk), NULL},
+ {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
+ {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/
+ {GEN_CMD_CODE(_SetTxPower), NULL},
+ {GEN_CMD_CODE(_SwitchAntenna), NULL},
+ {GEN_CMD_CODE(_SetCrystalCap), NULL},
+ {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/
+
+ {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/
+ {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
+ {GEN_CMD_CODE(_SetContinuousTx), NULL},
+ {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/
+ {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/
+
+ {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/
+ {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/
+ {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/
+ {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/
+ {GEN_CMD_CODE(_LedBlink), NULL},/*60*/
+
+ {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/
+ {GEN_CMD_CODE(_TDLS), NULL},/*62*/
+};
+#endif
+
+#endif /* _CMD_H_ */
diff --git a/drivers/staging/r8188eu/include/rtw_debug.h b/drivers/staging/r8188eu/include/rtw_debug.h
new file mode 100644
index 000000000000..3c3bf2a4f30e
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_debug.h
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTW_DEBUG_H__
+#define __RTW_DEBUG_H__
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+#define _drv_always_ 1
+#define _drv_emerg_ 2
+#define _drv_alert_ 3
+#define _drv_crit_ 4
+#define _drv_err_ 5
+#define _drv_warning_ 6
+#define _drv_notice_ 7
+#define _drv_info_ 8
+#define _drv_debug_ 9
+
+#define _module_rtl871x_xmit_c_ BIT(0)
+#define _module_xmit_osdep_c_ BIT(1)
+#define _module_rtl871x_recv_c_ BIT(2)
+#define _module_recv_osdep_c_ BIT(3)
+#define _module_rtl871x_mlme_c_ BIT(4)
+#define _module_mlme_osdep_c_ BIT(5)
+#define _module_rtl871x_sta_mgt_c_ BIT(6)
+#define _module_rtl871x_cmd_c_ BIT(7)
+#define _module_cmd_osdep_c_ BIT(8)
+#define _module_rtl871x_io_c_ BIT(9)
+#define _module_io_osdep_c_ BIT(10)
+#define _module_os_intfs_c_ BIT(11)
+#define _module_rtl871x_security_c_ BIT(12)
+#define _module_rtl871x_eeprom_c_ BIT(13)
+#define _module_hal_init_c_ BIT(14)
+#define _module_hci_hal_init_c_ BIT(15)
+#define _module_rtl871x_ioctl_c_ BIT(16)
+#define _module_rtl871x_ioctl_set_c_ BIT(17)
+#define _module_rtl871x_ioctl_query_c_ BIT(18)
+#define _module_rtl871x_pwrctrl_c_ BIT(19)
+#define _module_hci_intfs_c_ BIT(20)
+#define _module_hci_ops_c_ BIT(21)
+#define _module_osdep_service_c_ BIT(22)
+#define _module_mp_ BIT(23)
+#define _module_hci_ops_os_c_ BIT(24)
+#define _module_rtl871x_ioctl_os_c BIT(25)
+#define _module_rtl8712_cmd_c_ BIT(26)
+#define _module_rtl8192c_xmit_c_ BIT(27)
+#define _module_hal_xmit_c_ BIT(28)
+#define _module_efuse_ BIT(29)
+#define _module_rtl8712_recv_c_ BIT(30)
+#define _module_rtl8712_led_c_ BIT(31)
+
+#define DRIVER_PREFIX "R8188EU: "
+
+extern u32 GlobalDebugLevel;
+
+#define DBG_88E_LEVEL(_level, fmt, arg...) \
+ do { \
+ if (_level <= GlobalDebugLevel) \
+ pr_info(DRIVER_PREFIX"INFO " fmt, ##arg); \
+ } while (0)
+
+#define DBG_88E(...) \
+ do { \
+ if (_drv_err_ <= GlobalDebugLevel) \
+ pr_info(DRIVER_PREFIX __VA_ARGS__); \
+ } while (0)
+
+#define MSG_88E(...) \
+ do { \
+ if (_drv_err_ <= GlobalDebugLevel) \
+ pr_info(DRIVER_PREFIX __VA_ARGS__); \
+ } while (0)
+
+int proc_get_drv_version(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_write_reg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_write_reg(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+int proc_get_read_reg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_read_reg(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+
+int proc_get_fwstate(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+int proc_get_sec_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+int proc_get_mlmext_state(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_qos_option(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+int proc_get_ht_option(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+int proc_get_rf_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+int proc_get_ap_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_adapter_state(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_trx_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_mac_reg_dump1(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_mac_reg_dump2(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_mac_reg_dump3(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_bb_reg_dump1(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_bb_reg_dump2(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_bb_reg_dump3(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_rf_reg_dump1(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_rf_reg_dump2(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_rf_reg_dump3(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_rf_reg_dump4(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+#ifdef CONFIG_88EU_AP_MODE
+
+int proc_get_all_sta_info(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+#endif
+
+int proc_get_best_channel(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_rx_signal(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_rx_signal(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+
+int proc_get_ht_enable(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_ht_enable(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+
+int proc_get_cbw40_enable(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_cbw40_enable(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+
+int proc_get_ampdu_enable(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_ampdu_enable(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+
+int proc_get_rx_stbc(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_rx_stbc(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+
+int proc_get_two_path_rssi(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_rssi_disp(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_rssi_disp(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+
+#ifdef CONFIG_BT_COEXIST
+int proc_get_btcoex_dbg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_btcoex_dbg(struct file *file, const char *buffer,
+ signed long count, void *data);
+
+#endif /* CONFIG_BT_COEXIST */
+
+#endif /* __RTW_DEBUG_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_eeprom.h b/drivers/staging/r8188eu/include/rtw_eeprom.h
index 10525493129b..9f8a9c070339 100644
--- a/drivers/staging/rtl8188eu/include/rtw_eeprom.h
+++ b/drivers/staging/r8188eu/include/rtw_eeprom.h
@@ -1,14 +1,11 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTW_EEPROM_H__
#define __RTW_EEPROM_H__
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "osdep_service.h"
+#include "drv_types.h"
#define RTL8712_EEPROM_ID 0x8712
@@ -47,8 +44,7 @@
/* This variable is initiailzed through EEPROM or registry, */
/* however, its definition may be different with that in EEPROM for */
/* EEPROM size consideration. So, we have to perform proper translation
- * between them.
- */
+ * between them. */
/* Besides, CustomerID of registry has precedence of that of EEPROM. */
/* defined below. 060703, by rcnjko. */
enum RT_CUSTOMER_ID {
@@ -72,8 +68,7 @@ enum RT_CUSTOMER_ID {
RT_CID_819x_Sitecom = 17,
RT_CID_CCX = 18, /* It's set under CCX logo test and isn't demanded
* for CCX functions, but for test behavior like retry
- * limit and tx report. By Bruce, 2009-02-17.
- */
+ * limit and tx report. By Bruce, 2009-02-17. */
RT_CID_819x_Lenovo = 19,
RT_CID_819x_QMI = 20,
RT_CID_819x_Edimax_Belkin = 21,
@@ -83,8 +78,7 @@ enum RT_CUSTOMER_ID {
RT_CID_819x_Acer = 25,
RT_CID_819x_AzWave_ASUS = 26,
RT_CID_819x_AzWave = 27, /* For AzWave in PCIe,i
- * The ID is AzWave use and not only Asus
- */
+ * The ID is AzWave use and not only Asus */
RT_CID_819x_HP = 28,
RT_CID_819x_WNC_COREGA = 29,
RT_CID_819x_Arcadyan_Belkin = 30,
@@ -98,7 +92,7 @@ enum RT_CUSTOMER_ID {
RT_CID_CC_C = 38,
RT_CID_819x_Xavi = 39,
RT_CID_819x_FUNAI_TV = 40,
- RT_CID_819x_ALPHA_WD = 41,
+ RT_CID_819x_ALPHA_WD=41,
};
struct eeprom_priv {
@@ -108,7 +102,13 @@ struct eeprom_priv {
u8 mac_addr[6]; /* PermanentAddress */
u16 channel_plan;
u8 EepromOrEfuse;
- u8 efuse_eeprom_data[HWSET_MAX_SIZE_512];
+ u8 efuse_eeprom_data[HWSET_MAX_SIZE_512] __aligned(4);
};
+void eeprom_write16(struct adapter *padapter, u16 reg, u16 data);
+u16 eeprom_read16(struct adapter *padapter, u16 reg);
+void read_eeprom_content(struct adapter *padapter);
+void eeprom_read_sz(struct adapter *adapt, u16 reg, u8 *data, u32 sz);
+void read_eeprom_content_by_attrib(struct adapter *padapter);
+
#endif /* __RTL871X_EEPROM_H__ */
diff --git a/drivers/staging/r8188eu/include/rtw_efuse.h b/drivers/staging/r8188eu/include/rtw_efuse.h
new file mode 100644
index 000000000000..b3ff46db2091
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_efuse.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTW_EFUSE_H__
+#define __RTW_EFUSE_H__
+
+#include "osdep_service.h"
+
+#define EFUSE_ERROE_HANDLE 1
+
+#define PG_STATE_HEADER 0x01
+#define PG_STATE_WORD_0 0x02
+#define PG_STATE_WORD_1 0x04
+#define PG_STATE_WORD_2 0x08
+#define PG_STATE_WORD_3 0x10
+#define PG_STATE_DATA 0x20
+
+#define PG_SWBYTE_H 0x01
+#define PG_SWBYTE_L 0x02
+
+#define PGPKT_DATA_SIZE 8
+
+#define EFUSE_WIFI 0
+#define EFUSE_BT 1
+
+enum _EFUSE_DEF_TYPE {
+ TYPE_EFUSE_MAX_SECTION = 0,
+ TYPE_EFUSE_REAL_CONTENT_LEN = 1,
+ TYPE_AVAILABLE_EFUSE_BYTES_BANK = 2,
+ TYPE_AVAILABLE_EFUSE_BYTES_TOTAL = 3,
+ TYPE_EFUSE_MAP_LEN = 4,
+ TYPE_EFUSE_PROTECT_BYTES_BANK = 5,
+ TYPE_EFUSE_CONTENT_LEN_BANK = 6,
+};
+
+/* E-Fuse */
+#define EFUSE_MAP_SIZE 512
+#define EFUSE_MAX_SIZE 256
+/* end of E-Fuse */
+
+#define EFUSE_MAX_MAP_LEN 512
+#define EFUSE_MAX_HW_SIZE 512
+#define EFUSE_MAX_SECTION_BASE 16
+
+#define EXT_HEADER(header) ((header & 0x1F) == 0x0F)
+#define ALL_WORDS_DISABLED(wde) ((wde & 0x0F) == 0x0F)
+#define GET_HDR_OFFSET_2_0(header) ((header & 0xE0) >> 5)
+
+#define EFUSE_REPEAT_THRESHOLD_ 3
+
+/* The following is for BT Efuse definition */
+#define EFUSE_BT_MAX_MAP_LEN 1024
+#define EFUSE_MAX_BANK 4
+#define EFUSE_MAX_BT_BANK (EFUSE_MAX_BANK-1)
+/*--------------------------Define Parameters-------------------------------*/
+#define EFUSE_MAX_WORD_UNIT 4
+
+/*------------------------------Define structure----------------------------*/
+struct pgpkt {
+ u8 offset;
+ u8 word_en;
+ u8 data[8];
+ u8 word_cnts;
+};
+
+/*------------------------------Define structure----------------------------*/
+struct efuse_hal {
+ u8 fakeEfuseBank;
+ u32 fakeEfuseUsedBytes;
+ u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE];
+ u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN];
+ u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN];
+
+ u16 BTEfuseUsedBytes;
+ u8 BTEfuseUsedPercentage;
+ u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+ u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN];
+ u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN];
+
+ u16 fakeBTEfuseUsedBytes;
+ u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+ u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN];
+ u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN];
+};
+
+/*------------------------Export global variable----------------------------*/
+extern u8 fakeEfuseBank;
+extern u32 fakeEfuseUsedBytes;
+extern u8 fakeEfuseContent[];
+extern u8 fakeEfuseInitMap[];
+extern u8 fakeEfuseModifiedMap[];
+
+extern u32 BTEfuseUsedBytes;
+extern u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+extern u8 BTEfuseInitMap[];
+extern u8 BTEfuseModifiedMap[];
+
+extern u32 fakeBTEfuseUsedBytes;
+extern u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+extern u8 fakeBTEfuseInitMap[];
+extern u8 fakeBTEfuseModifiedMap[];
+/*------------------------Export global variable----------------------------*/
+
+u8 efuse_GetCurrentSize(struct adapter *adapter, u16 *size);
+u16 efuse_GetMaxSize(struct adapter *adapter);
+u8 rtw_efuse_access(struct adapter *adapter, u8 read, u16 start_addr,
+ u16 cnts, u8 *data);
+u8 rtw_efuse_map_read(struct adapter *adapter, u16 addr, u16 cnts, u8 *data);
+u8 rtw_efuse_map_write(struct adapter *adapter, u16 addr, u16 cnts, u8 *data);
+u8 rtw_BT_efuse_map_read(struct adapter *adapter, u16 addr,
+ u16 cnts, u8 *data);
+u8 rtw_BT_efuse_map_write(struct adapter *adapter, u16 addr,
+ u16 cnts, u8 *data);
+u16 Efuse_GetCurrentSize(struct adapter *adapter, u8 efusetype, bool test);
+u8 Efuse_CalculateWordCnts(u8 word_en);
+void ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf, bool test);
+void EFUSE_GetEfuseDefinition(struct adapter *adapt, u8 type, u8 type1,
+ void *out, bool bPseudoTest);
+u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data, bool test);
+u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data, bool test);
+
+void Efuse_PowerSwitch(struct adapter *adapt,u8 bWrite,u8 PwrState);
+int Efuse_PgPacketRead(struct adapter *adapt, u8 offset, u8 *data, bool test);
+int Efuse_PgPacketWrite(struct adapter *adapter, u8 offset, u8 word, u8 *data,
+ bool test);
+void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata);
+u8 Efuse_WordEnableDataWrite(struct adapter *adapter, u16 efuse_addr,
+ u8 word_en, u8 *data, bool test);
+
+u8 EFUSE_Read1Byte(struct adapter *adapter, u16 address);
+void EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype, bool test);
+void EFUSE_ShadowRead(struct adapter *adapt, u8 type, u16 offset, u32 *val);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/rtw_event.h b/drivers/staging/r8188eu/include/rtw_event.h
new file mode 100644
index 000000000000..54dc1ea437fc
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_event.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _RTW_EVENT_H_
+#define _RTW_EVENT_H_
+
+#include "osdep_service.h"
+
+#include "wlan_bssdef.h"
+#include <linux/semaphore.h>
+#include <linux/sem.h>
+
+/*
+Used to report a bss has been scanned
+*/
+struct survey_event {
+ struct wlan_bssid_ex bss;
+};
+
+/*
+Used to report that the requested site survey has been done.
+
+bss_cnt indicates the number of bss that has been reported.
+
+*/
+struct surveydone_event {
+ unsigned int bss_cnt;
+
+};
+
+/*
+Used to report the link result of joinning the given bss
+
+join_res:
+-1: authentication fail
+-2: association fail
+> 0: TID
+
+*/
+struct joinbss_event {
+ struct wlan_network network;
+};
+
+/*
+Used to report a given STA has joinned the created BSS.
+It is used in AP/Ad-HoC(M) mode.
+*/
+
+struct stassoc_event {
+ unsigned char macaddr[6];
+ unsigned char rsvd[2];
+ int cam_id;
+};
+
+struct stadel_event {
+ unsigned char macaddr[6];
+ unsigned char rsvd[2]; /* for reason */
+ int mac_id;
+};
+
+struct addba_event {
+ unsigned int tid;
+};
+
+#define GEN_EVT_CODE(event) event ## _EVT_
+
+struct fwevent {
+ u32 parmsize;
+ void (*event_callback)(struct adapter *dev, u8 *pbuf);
+};
+
+#define C2HEVENT_SZ 32
+
+struct event_node {
+ unsigned char *node;
+ unsigned char evt_code;
+ unsigned short evt_sz;
+ int *caller_ff_tail;
+ int caller_ff_sz;
+};
+
+struct c2hevent_queue {
+ int head;
+ int tail;
+ struct event_node nodes[C2HEVENT_SZ];
+ unsigned char seq;
+};
+
+#define NETWORK_QUEUE_SZ 4
+
+struct network_queue {
+ int head;
+ int tail;
+ struct wlan_bssid_ex networks[NETWORK_QUEUE_SZ];
+};
+
+#endif /* _WLANEVENT_H_ */
diff --git a/drivers/staging/r8188eu/include/rtw_ht.h b/drivers/staging/r8188eu/include/rtw_ht.h
new file mode 100644
index 000000000000..2b56b7c38c86
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_ht.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _RTW_HT_H_
+#define _RTW_HT_H_
+
+#include "osdep_service.h"
+#include "wifi.h"
+
+struct ht_priv {
+ u32 ht_option;
+ u32 ampdu_enable;/* for enable Tx A-MPDU */
+ u32 tx_amsdu_enable;/* for enable Tx A-MSDU */
+ u32 tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */
+ u32 rx_ampdu_maxlen; /* for rx reordering ctrl win_sz,
+ * updated when join_callback. */
+ u8 bwmode;/* */
+ u8 ch_offset;/* PRIME_CHNL_OFFSET */
+ u8 sgi;/* short GI */
+
+ /* for processing Tx A-MPDU */
+ u8 agg_enable_bitmap;
+ u8 candidate_tid_bitmap;
+
+ struct ieee80211_ht_cap ht_cap;
+};
+
+#endif /* _RTL871X_HT_H_ */
diff --git a/drivers/staging/r8188eu/include/rtw_io.h b/drivers/staging/r8188eu/include/rtw_io.h
new file mode 100644
index 000000000000..4b41c7b03972
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_io.h
@@ -0,0 +1,367 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _RTW_IO_H_
+#define _RTW_IO_H_
+
+#include "osdep_service.h"
+#include "osdep_intf.h"
+
+#include <asm/byteorder.h>
+#include <linux/semaphore.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+
+#define rtw_usb_buffer_alloc(dev, size, dma) \
+ usb_alloc_coherent((dev), (size), (in_interrupt() ? \
+ GFP_ATOMIC : GFP_KERNEL), (dma))
+#define rtw_usb_buffer_free(dev, size, addr, dma) \
+ usb_free_coherent((dev), (size), (addr), (dma))
+
+#define NUM_IOREQ 8
+
+#define MAX_PROT_SZ (64-16)
+
+#define _IOREADY 0
+#define _IO_WAIT_COMPLETE 1
+#define _IO_WAIT_RSP 2
+
+/* IO COMMAND TYPE */
+#define _IOSZ_MASK_ (0x7F)
+#define _IO_WRITE_ BIT(7)
+#define _IO_FIXED_ BIT(8)
+#define _IO_BURST_ BIT(9)
+#define _IO_BYTE_ BIT(10)
+#define _IO_HW_ BIT(11)
+#define _IO_WORD_ BIT(12)
+#define _IO_SYNC_ BIT(13)
+#define _IO_CMDMASK_ (0x1F80)
+
+/*
+ For prompt mode accessing, caller shall free io_req
+ Otherwise, io_handler will free io_req
+*/
+
+/* IO STATUS TYPE */
+#define _IO_ERR_ BIT(2)
+#define _IO_SUCCESS_ BIT(1)
+#define _IO_DONE_ BIT(0)
+
+#define IO_RD32 (_IO_SYNC_ | _IO_WORD_)
+#define IO_RD16 (_IO_SYNC_ | _IO_HW_)
+#define IO_RD8 (_IO_SYNC_ | _IO_BYTE_)
+
+#define IO_RD32_ASYNC (_IO_WORD_)
+#define IO_RD16_ASYNC (_IO_HW_)
+#define IO_RD8_ASYNC (_IO_BYTE_)
+
+#define IO_WR32 (_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_)
+#define IO_WR16 (_IO_WRITE_ | _IO_SYNC_ | _IO_HW_)
+#define IO_WR8 (_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_)
+
+#define IO_WR32_ASYNC (_IO_WRITE_ | _IO_WORD_)
+#define IO_WR16_ASYNC (_IO_WRITE_ | _IO_HW_)
+#define IO_WR8_ASYNC (_IO_WRITE_ | _IO_BYTE_)
+
+/*
+ Only Sync. burst accessing is provided.
+*/
+
+#define IO_WR_BURST(x) \
+ (_IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_))
+#define IO_RD_BURST(x) \
+ (_IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_))
+
+/* below is for the intf_option bit defition... */
+
+#define _INTF_ASYNC_ BIT(0) /* support async io */
+
+struct intf_priv;
+struct intf_hdl;
+struct io_queue;
+
+struct _io_ops {
+ u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+ u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+ u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+ int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+ int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+ int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
+ int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr, u32 length,
+ u8 *pdata);
+ int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+ int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+ int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
+ void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
+ u8 *pmem);
+ void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
+ u8 *pmem);
+ u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
+ u8 *pmem);
+ u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
+ u8 *pmem);
+ void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
+ void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
+};
+
+struct io_req {
+ struct list_head list;
+ u32 addr;
+ u32 val;
+ u32 command;
+ u32 status;
+ u8 *pbuf;
+ struct semaphore sema;
+
+ void (*_async_io_callback)(struct adapter *padater,
+ struct io_req *pio_req, u8 *cnxt);
+ u8 *cnxt;
+};
+
+struct intf_hdl {
+ struct adapter *padapter;
+ struct dvobj_priv *pintf_dev;
+ struct _io_ops io_ops;
+};
+
+struct reg_protocol_rd {
+#ifdef __LITTLE_ENDIAN
+ /* DW1 */
+ u32 NumOfTrans:4;
+ u32 Reserved1:4;
+ u32 Reserved2:24;
+ /* DW2 */
+ u32 ByteCount:7;
+ u32 WriteEnable:1; /* 0:read, 1:write */
+ u32 FixOrContinuous:1; /* 0:continuous, 1: Fix */
+ u32 BurstMode:1;
+ u32 Byte1Access:1;
+ u32 Byte2Access:1;
+ u32 Byte4Access:1;
+ u32 Reserved3:3;
+ u32 Reserved4:16;
+ /* DW3 */
+ u32 BusAddress;
+ /* DW4 */
+ /* u32 Value; */
+#else
+/* DW1 */
+ u32 Reserved1:4;
+ u32 NumOfTrans:4;
+ u32 Reserved2:24;
+ /* DW2 */
+ u32 WriteEnable:1;
+ u32 ByteCount:7;
+ u32 Reserved3:3;
+ u32 Byte4Access:1;
+
+ u32 Byte2Access:1;
+ u32 Byte1Access:1;
+ u32 BurstMode:1;
+ u32 FixOrContinuous:1;
+ u32 Reserved4:16;
+ /* DW3 */
+ u32 BusAddress;
+
+ /* DW4 */
+#endif
+};
+
+struct reg_protocol_wt {
+#ifdef __LITTLE_ENDIAN
+ /* DW1 */
+ u32 NumOfTrans:4;
+ u32 Reserved1:4;
+ u32 Reserved2:24;
+ /* DW2 */
+ u32 ByteCount:7;
+ u32 WriteEnable:1; /* 0:read, 1:write */
+ u32 FixOrContinuous:1; /* 0:continuous, 1: Fix */
+ u32 BurstMode:1;
+ u32 Byte1Access:1;
+ u32 Byte2Access:1;
+ u32 Byte4Access:1;
+ u32 Reserved3:3;
+ u32 Reserved4:16;
+ /* DW3 */
+ u32 BusAddress;
+ /* DW4 */
+ u32 Value;
+#else
+ /* DW1 */
+ u32 Reserved1 :4;
+ u32 NumOfTrans:4;
+ u32 Reserved2:24;
+ /* DW2 */
+ u32 WriteEnable:1;
+ u32 ByteCount:7;
+ u32 Reserved3:3;
+ u32 Byte4Access:1;
+ u32 Byte2Access:1;
+ u32 Byte1Access:1;
+ u32 BurstMode:1;
+ u32 FixOrContinuous:1;
+ u32 Reserved4:16;
+ /* DW3 */
+ u32 BusAddress;
+ /* DW4 */
+ u32 Value;
+#endif
+};
+
+/*
+Below is the data structure used by _io_handler
+*/
+
+struct io_queue {
+ spinlock_t lock;
+ struct list_head free_ioreqs;
+ struct list_head pending; /* The io_req list that will be served
+ * in the single protocol read/write.*/
+ struct list_head processing;
+ u8 *free_ioreqs_buf; /* 4-byte aligned */
+ u8 *pallocated_free_ioreqs_buf;
+ struct intf_hdl intf;
+};
+
+struct io_priv {
+ struct adapter *padapter;
+ struct intf_hdl intf;
+};
+
+uint ioreq_flush(struct adapter *adapter, struct io_queue *ioqueue);
+void sync_ioreq_enqueue(struct io_req *preq,struct io_queue *ioqueue);
+uint sync_ioreq_flush(struct adapter *adapter, struct io_queue *ioqueue);
+uint free_ioreq(struct io_req *preq, struct io_queue *pio_queue);
+struct io_req *alloc_ioreq(struct io_queue *pio_q);
+
+uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl);
+void unregister_intf_hdl(struct intf_hdl *pintfhdl);
+
+void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+
+u8 _rtw_read8(struct adapter *adapter, u32 addr);
+u16 _rtw_read16(struct adapter *adapter, u32 addr);
+u32 _rtw_read32(struct adapter *adapter, u32 addr);
+void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+void _rtw_read_port_cancel(struct adapter *adapter);
+
+int _rtw_write8(struct adapter *adapter, u32 addr, u8 val);
+int _rtw_write16(struct adapter *adapter, u32 addr, u16 val);
+int _rtw_write32(struct adapter *adapter, u32 addr, u32 val);
+int _rtw_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata);
+
+int _rtw_write8_async(struct adapter *adapter, u32 addr, u8 val);
+int _rtw_write16_async(struct adapter *adapter, u32 addr, u16 val);
+int _rtw_write32_async(struct adapter *adapter, u32 addr, u32 val);
+
+void _rtw_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt,
+ u8 *pmem, int timeout_ms);
+void _rtw_write_port_cancel(struct adapter *adapter);
+
+#define rtw_read8(adapter, addr) _rtw_read8((adapter), (addr))
+#define rtw_read16(adapter, addr) _rtw_read16((adapter), (addr))
+#define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
+#define rtw_read_mem(adapter, addr, cnt, mem) \
+ _rtw_read_mem((adapter), (addr), (cnt), (mem))
+#define rtw_read_port(adapter, addr, cnt, mem) \
+ _rtw_read_port((adapter), (addr), (cnt), (mem))
+#define rtw_read_port_cancel(adapter) _rtw_read_port_cancel((adapter))
+
+#define rtw_write8(adapter, addr, val) \
+ _rtw_write8((adapter), (addr), (val))
+#define rtw_write16(adapter, addr, val) \
+ _rtw_write16((adapter), (addr), (val))
+#define rtw_write32(adapter, addr, val) \
+ _rtw_write32((adapter), (addr), (val))
+#define rtw_writeN(adapter, addr, length, data) \
+ _rtw_writeN((adapter), (addr), (length), (data))
+#define rtw_write8_async(adapter, addr, val) \
+ _rtw_write8_async((adapter), (addr), (val))
+#define rtw_write16_async(adapter, addr, val) \
+ _rtw_write16_async((adapter), (addr), (val))
+#define rtw_write32_async(adapter, addr, val) \
+ _rtw_write32_async((adapter), (addr), (val))
+#define rtw_write_mem(adapter, addr, cnt, mem) \
+ _rtw_write_mem((adapter), (addr), (cnt), (mem))
+#define rtw_write_port(adapter, addr, cnt, mem) \
+ _rtw_write_port((adapter), (addr), (cnt), (mem))
+#define rtw_write_port_and_wait(adapter, addr, cnt, mem, timeout_ms) \
+ _rtw_write_port_and_wait((adapter), (addr), (cnt), (mem), (timeout_ms))
+#define rtw_write_port_cancel(adapter) _rtw_write_port_cancel((adapter))
+
+void rtw_write_scsi(struct adapter *adapter, u32 cnt, u8 *pmem);
+
+/* ioreq */
+void ioreq_read8(struct adapter *adapter, u32 addr, u8 *pval);
+void ioreq_read16(struct adapter *adapter, u32 addr, u16 *pval);
+void ioreq_read32(struct adapter *adapter, u32 addr, u32 *pval);
+void ioreq_write8(struct adapter *adapter, u32 addr, u8 val);
+void ioreq_write16(struct adapter *adapter, u32 addr, u16 val);
+void ioreq_write32(struct adapter *adapter, u32 addr, u32 val);
+
+uint async_read8(struct adapter *adapter, u32 addr, u8 *pbuff,
+ void (*_async_io_callback)(struct adapter *padater,
+ struct io_req *pio_req,
+ u8 *cnxt), u8 *cnxt);
+uint async_read16(struct adapter *adapter, u32 addr, u8 *pbuff,
+ void (*_async_io_callback)(struct adapter *padater,
+ struct io_req *pio_req,
+ u8 *cnxt), u8 *cnxt);
+uint async_read32(struct adapter *adapter, u32 addr, u8 *pbuff,
+ void (*_async_io_callback)(struct adapter *padater,
+ struct io_req *pio_req,
+ u8 *cnxt), u8 *cnxt);
+
+void async_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+void async_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+
+void async_write8(struct adapter *adapter, u32 addr, u8 val,
+ void (*_async_io_callback)(struct adapter *padater,
+ struct io_req *pio_req,
+ u8 *cnxt), u8 *cnxt);
+void async_write16(struct adapter *adapter, u32 addr, u16 val,
+ void (*_async_io_callback)(struct adapter *padater,
+ struct io_req *pio_req,
+ u8 *cnxt), u8 *cnxt);
+void async_write32(struct adapter *adapter, u32 addr, u32 val,
+ void (*_async_io_callback)(struct adapter *padater,
+ struct io_req *pio_req,
+ u8 *cnxt), u8 *cnxt);
+
+void async_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+void async_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
+
+int rtw_init_io_priv(struct adapter *padapter,
+ void (*set_intf_ops)(struct _io_ops *pops));
+
+uint alloc_io_queue(struct adapter *adapter);
+void free_io_queue(struct adapter *adapter);
+void async_bus_io(struct io_queue *pio_q);
+void bus_sync_io(struct io_queue *pio_q);
+u32 _ioreq2rwmem(struct io_queue *pio_q);
+void dev_power_down(struct adapter * Adapter, u8 bpwrup);
+
+#define PlatformEFIOWrite1Byte(_a,_b,_c) \
+ rtw_write8(_a,_b,_c)
+#define PlatformEFIOWrite2Byte(_a,_b,_c) \
+ rtw_write16(_a,_b,_c)
+#define PlatformEFIOWrite4Byte(_a,_b,_c) \
+ rtw_write32(_a,_b,_c)
+
+#define PlatformEFIORead1Byte(_a,_b) \
+ rtw_read8(_a,_b)
+#define PlatformEFIORead2Byte(_a,_b) \
+ rtw_read16(_a,_b)
+#define PlatformEFIORead4Byte(_a,_b) \
+ rtw_read32(_a,_b)
+
+#endif /* _RTL8711_IO_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl.h b/drivers/staging/r8188eu/include/rtw_ioctl.h
index f681f9ebeafe..a36bd7313755 100644
--- a/drivers/staging/rtl8188eu/include/rtw_ioctl.h
+++ b/drivers/staging/r8188eu/include/rtw_ioctl.h
@@ -1,14 +1,11 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef _RTW_IOCTL_H_
#define _RTW_IOCTL_H_
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "osdep_service.h"
+#include "drv_types.h"
#ifndef OID_802_11_CAPABILITY
#define OID_802_11_CAPABILITY 0x0d010122
@@ -53,6 +50,15 @@ enum oid_type {
SET_OID
};
+struct oid_funs_node {
+ unsigned int oid_start; /* the starting number for OID */
+ unsigned int oid_end; /* the ending number for OID */
+ struct oid_obj_priv *node_array;
+ unsigned int array_sz; /* the size of node_array */
+ int query_counter; /* count the number of query hits for this segment */
+ int set_counter; /* count the number of set hits for this segment */
+};
+
struct oid_par_priv {
void *adapter_context;
NDIS_OID oid;
@@ -64,12 +70,11 @@ struct oid_par_priv {
u32 dbg;
};
-#if defined(_RTW_MP_IOCTL_C_)
-static int oid_null_function(struct oid_par_priv *poid_par_priv)
-{
- return NDIS_STATUS_SUCCESS;
-}
-#endif
+struct oid_obj_priv {
+ unsigned char dbg; /* 0: without OID debug message
+ * 1: with OID debug message */
+ int (*oidfuns)(struct oid_par_priv *poid_par_priv);
+};
extern struct iw_handler_def rtw_handlers_def;
@@ -82,4 +87,6 @@ int drv_set_info(struct net_device *MiniportAdapterContext,
u32 informationbufferlength, u32 *bytesread,
u32 *bytesneeded);
+extern int ui_pid[3];
+
#endif /* #ifndef __INC_CEINFO_ */
diff --git a/drivers/staging/r8188eu/include/rtw_ioctl_rtl.h b/drivers/staging/r8188eu/include/rtw_ioctl_rtl.h
new file mode 100644
index 000000000000..6d3d1ef923f6
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_ioctl_rtl.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _RTW_IOCTL_RTL_H_
+#define _RTW_IOCTL_RTL_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+/* oid_rtl_seg_01_01 ************** */
+int oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv);/* 84 */
+int oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv);
+
+int oid_rt_pro_set_fw_dig_state_hdl(struct oid_par_priv *poid_par_priv);/* 8a */
+int oid_rt_pro_set_fw_ra_state_hdl(struct oid_par_priv *poid_par_priv); /* 8b */
+
+int oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv);/* 93 */
+int oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_set_channelplan_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_set_preamble_mode_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_dedicate_probe_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_current_tx_power_level_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_supported_wireless_mode_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv *poid_par_priv);
+
+/* oid_rtl_seg_01_03 section start ************** */
+int oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv *priv);
+int oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv);
+
+/* oid_rtl_seg_01_11 */
+int oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv);
+
+/* oid_rtl_seg_03_00 section start ************** */
+int oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv);
+int oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/rtw_ioctl_set.h b/drivers/staging/r8188eu/include/rtw_ioctl_set.h
new file mode 100644
index 000000000000..6216b8ab3a79
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_ioctl_set.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTW_IOCTL_SET_H_
+#define __RTW_IOCTL_SET_H_
+
+#include "drv_types.h"
+
+typedef u8 NDIS_802_11_PMKID_VALUE[16];
+
+u8 rtw_set_802_11_add_key(struct adapter *adapt, struct ndis_802_11_key *key);
+u8 rtw_set_802_11_authentication_mode(struct adapter *adapt,
+ enum ndis_802_11_auth_mode authmode);
+u8 rtw_set_802_11_bssid(struct adapter*adapter, u8 *bssid);
+u8 rtw_set_802_11_add_wep(struct adapter *adapter, struct ndis_802_11_wep *wep);
+u8 rtw_set_802_11_disassociate(struct adapter *adapter);
+u8 rtw_set_802_11_bssid_list_scan(struct adapter*adapter,
+ struct ndis_802_11_ssid *pssid,
+ int ssid_max_num);
+u8 rtw_set_802_11_infrastructure_mode(struct adapter *adapter,
+ enum ndis_802_11_network_infra type);
+u8 rtw_set_802_11_remove_wep(struct adapter *adapter, u32 keyindex);
+u8 rtw_set_802_11_ssid(struct adapter *adapt, struct ndis_802_11_ssid *ssid);
+u8 rtw_set_802_11_remove_key(struct adapter *adapt,
+ struct ndis_802_11_remove_key *key);
+u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid);
+u16 rtw_get_cur_max_rate(struct adapter *adapter);
+int rtw_set_scan_mode(struct adapter *adapter, enum rt_scan_type scan_mode);
+int rtw_set_channel_plan(struct adapter *adapter, u8 channel_plan);
+int rtw_set_country(struct adapter *adapter, const char *country_code);
+int rtw_change_ifname(struct adapter *padapter, const char *ifname);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/rtw_iol.h b/drivers/staging/r8188eu/include/rtw_iol.h
new file mode 100644
index 000000000000..471f9ca092a8
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_iol.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTW_IOL_H_
+#define __RTW_IOL_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+#define IOREG_CMD_END_LEN 4
+
+struct ioreg_cfg {
+ u8 length;
+ u8 cmd_id;
+ __le16 address;
+ __le32 data;
+ __le32 mask;
+};
+
+enum ioreg_cmd {
+ IOREG_CMD_LLT = 0x01,
+ IOREG_CMD_REFUSE = 0x02,
+ IOREG_CMD_EFUSE_PATH = 0x03,
+ IOREG_CMD_WB_REG = 0x04,
+ IOREG_CMD_WW_REG = 0x05,
+ IOREG_CMD_WD_REG = 0x06,
+ IOREG_CMD_W_RF = 0x07,
+ IOREG_CMD_DELAY_US = 0x10,
+ IOREG_CMD_DELAY_MS = 0x11,
+ IOREG_CMD_END = 0xFF,
+};
+
+struct xmit_frame *rtw_IOL_accquire_xmit_frame(struct adapter *adapter);
+int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds,
+ u32 cmd_len);
+int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary);
+int rtw_IOL_exec_cmds_sync(struct adapter *adapter,
+ struct xmit_frame *xmit_frame, u32 max_wating_ms,
+ u32 bndy_cnt);
+bool rtw_IOL_applied(struct adapter *adapter);
+int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us);
+int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms);
+int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame);
+
+void read_efuse_from_txpktbuf(struct adapter *adapter, int bcnhead,
+ u8 *content, u16 *size);
+
+int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr,
+ u8 value, u8 mask);
+int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr,
+ u16 value, u16 mask);
+int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr,
+ u32 value, u32 mask);
+int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path,
+ u16 addr, u32 value, u32 mask);
+#define rtw_IOL_append_WB_cmd(xmit_frame, addr, value, mask) \
+ _rtw_IOL_append_WB_cmd((xmit_frame), (addr), (value) ,(mask))
+#define rtw_IOL_append_WW_cmd(xmit_frame, addr, value, mask) \
+ _rtw_IOL_append_WW_cmd((xmit_frame), (addr), (value),(mask))
+#define rtw_IOL_append_WD_cmd(xmit_frame, addr, value, mask) \
+ _rtw_IOL_append_WD_cmd((xmit_frame), (addr), (value), (mask))
+#define rtw_IOL_append_WRF_cmd(xmit_frame, rf_path, addr, value, mask) \
+ _rtw_IOL_append_WRF_cmd((xmit_frame),(rf_path), (addr), (value), (mask))
+
+u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame);
+void rtw_IOL_cmd_buf_dump(struct adapter *Adapter,int buf_len,u8 *pbuf);
+
+#endif /* __RTW_IOL_H_ */
diff --git a/drivers/staging/r8188eu/include/rtw_led.h b/drivers/staging/r8188eu/include/rtw_led.h
new file mode 100644
index 000000000000..f0965aa5b470
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_led.h
@@ -0,0 +1,181 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTW_LED_H_
+#define __RTW_LED_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+#define MSECS(t) (HZ * ((t) / 1000) + (HZ * ((t) % 1000)) / 1000)
+
+#define LED_BLINK_NORMAL_INTERVAL 100
+#define LED_BLINK_SLOWLY_INTERVAL 200
+#define LED_BLINK_LONG_INTERVAL 400
+
+#define LED_BLINK_NO_LINK_INTERVAL_ALPHA 1000
+#define LED_BLINK_LINK_INTERVAL_ALPHA 500 /* 500 */
+#define LED_BLINK_SCAN_INTERVAL_ALPHA 180 /* 150 */
+#define LED_BLINK_FASTER_INTERVAL_ALPHA 50
+#define LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA 5000
+
+#define LED_BLINK_NORMAL_INTERVAL_NETTRONIX 100
+#define LED_BLINK_SLOWLY_INTERVAL_NETTRONIX 2000
+
+#define LED_BLINK_SLOWLY_INTERVAL_PORNET 1000
+#define LED_BLINK_NORMAL_INTERVAL_PORNET 100
+
+#define LED_BLINK_FAST_INTERVAL_BITLAND 30
+
+/* 060403, rcnjko: Customized for AzWave. */
+#define LED_CM2_BLINK_ON_INTERVAL 250
+#define LED_CM2_BLINK_OFF_INTERVAL 4750
+
+#define LED_CM8_BLINK_INTERVAL 500 /* for QMI */
+#define LED_CM8_BLINK_OFF_INTERVAL 3750 /* for QMI */
+
+/* 080124, lanhsin: Customized for RunTop */
+#define LED_RunTop_BLINK_INTERVAL 300
+
+/* 060421, rcnjko: Customized for Sercomm Printer Server case. */
+#define LED_CM3_BLINK_INTERVAL 1500
+
+enum LED_CTL_MODE {
+ LED_CTL_POWER_ON = 1,
+ LED_CTL_LINK = 2,
+ LED_CTL_NO_LINK = 3,
+ LED_CTL_TX = 4,
+ LED_CTL_RX = 5,
+ LED_CTL_SITE_SURVEY = 6,
+ LED_CTL_POWER_OFF = 7,
+ LED_CTL_START_TO_LINK = 8,
+ LED_CTL_START_WPS = 9,
+ LED_CTL_STOP_WPS = 10,
+ LED_CTL_START_WPS_BOTTON = 11, /* added for runtop */
+ LED_CTL_STOP_WPS_FAIL = 12, /* added for ALPHA */
+ LED_CTL_STOP_WPS_FAIL_OVERLAP = 13, /* added for BELKIN */
+ LED_CTL_CONNECTION_NO_TRANSFER = 14,
+};
+
+enum LED_STATE_871x {
+ LED_UNKNOWN = 0,
+ RTW_LED_ON = 1,
+ RTW_LED_OFF = 2,
+ LED_BLINK_NORMAL = 3,
+ LED_BLINK_SLOWLY = 4,
+ LED_BLINK_POWER_ON = 5,
+ LED_BLINK_SCAN = 6, /* LED is blinking during scanning period,
+ * the # of times to blink is depend on time
+ * for scanning. */
+ LED_BLINK_NO_LINK = 7, /* LED is blinking during no link state. */
+ LED_BLINK_StartToBlink = 8,/* Customzied for Sercomm Printer
+ * Server case */
+ LED_BLINK_TXRX = 9,
+ LED_BLINK_WPS = 10, /* LED is blinkg during WPS communication */
+ LED_BLINK_WPS_STOP = 11, /* for ALPHA */
+ LED_BLINK_WPS_STOP_OVERLAP = 12, /* for BELKIN */
+ LED_BLINK_RUNTOP = 13, /* Customized for RunTop */
+ LED_BLINK_CAMEO = 14,
+ LED_BLINK_XAVI = 15,
+ LED_BLINK_ALWAYS_ON = 16,
+};
+
+enum LED_PIN_871x {
+ LED_PIN_NULL = 0,
+ LED_PIN_LED0 = 1,
+ LED_PIN_LED1 = 2,
+ LED_PIN_LED2 = 3,
+ LED_PIN_GPIO0 = 4,
+};
+
+struct LED_871x {
+ struct adapter *padapter;
+
+ enum LED_PIN_871x LedPin; /* Identify how to implement this
+ * SW led. */
+ enum LED_STATE_871x CurrLedState; /* Current LED state. */
+ enum LED_STATE_871x BlinkingLedState; /* Next state for blinking,
+ * either RTW_LED_ON or RTW_LED_OFF are. */
+
+ u8 bLedOn; /* true if LED is ON, false if LED is OFF. */
+
+ u8 bLedBlinkInProgress; /* true if it is blinking, false o.w.. */
+
+ u8 bLedWPSBlinkInProgress;
+
+ u32 BlinkTimes; /* Number of times to toggle led state for blinking. */
+
+ struct timer_list BlinkTimer; /* Timer object for led blinking. */
+
+ u8 bSWLedCtrl;
+
+ /* ALPHA, added by chiyoko, 20090106 */
+ u8 bLedNoLinkBlinkInProgress;
+ u8 bLedLinkBlinkInProgress;
+ u8 bLedStartToLinkBlinkInProgress;
+ u8 bLedScanBlinkInProgress;
+ struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer to
+ * manipulate H/W to blink LED. */
+};
+
+#define IS_LED_WPS_BLINKING(_LED_871x) \
+ (((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS || \
+ ((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS_STOP || \
+ ((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress)
+
+#define IS_LED_BLINKING(_LED_871x) \
+ (((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress || \
+ ((struct LED_871x *)_LED_871x)->bLedScanBlinkInProgress)
+
+/* LED customization. */
+
+enum LED_STRATEGY_871x {
+ SW_LED_MODE0 = 0, /* SW control 1 LED via GPIO0. It is default option.*/
+ SW_LED_MODE1= 1, /* 2 LEDs, through LED0 and LED1. For ALPHA. */
+ SW_LED_MODE2 = 2, /* SW control 1 LED via GPIO0, customized for AzWave
+ * 8187 minicard. */
+ SW_LED_MODE3 = 3, /* SW control 1 LED via GPIO0, customized for Sercomm
+ * Printer Server case. */
+ SW_LED_MODE4 = 4, /* for Edimax / Belkin */
+ SW_LED_MODE5 = 5, /* for Sercomm / Belkin */
+ SW_LED_MODE6 = 6, /* for 88CU minicard, porting from ce SW_LED_MODE7 */
+ HW_LED = 50, /* HW control 2 LEDs, LED0 and LED1 (there are 4
+ * different control modes, see MAC.CONFIG1 for details.)*/
+ LED_ST_NONE = 99,
+};
+
+void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction);
+
+struct led_priv{
+ /* add for led control */
+ struct LED_871x SwLed0;
+ struct LED_871x SwLed1;
+ enum LED_STRATEGY_871x LedStrategy;
+ u8 bRegUseLed;
+ void (*LedControlHandler)(struct adapter *padapter,
+ enum LED_CTL_MODE LedAction);
+ /* add for led control */
+};
+
+#define rtw_led_control(adapt, action) \
+ do { \
+ if ((adapt)->ledpriv.LedControlHandler) \
+ (adapt)->ledpriv.LedControlHandler((adapt), (action)); \
+ } while (0)
+
+void BlinkTimerCallback(struct timer_list *t);
+void BlinkWorkItemCallback(struct work_struct *work);
+
+void ResetLedStatus(struct LED_871x * pLed);
+
+void InitLed871x(struct adapter *padapter, struct LED_871x *pLed,
+ enum LED_PIN_871x LedPin);
+
+void DeInitLed871x(struct LED_871x *pLed);
+
+/* hal... */
+void BlinkHandler(struct LED_871x * pLed);
+void SwLedOn(struct adapter *padapter, struct LED_871x *pLed);
+void SwLedOff(struct adapter *padapter, struct LED_871x *pLed);
+
+#endif /* __RTW_LED_H_ */
diff --git a/drivers/staging/r8188eu/include/rtw_mlme.h b/drivers/staging/r8188eu/include/rtw_mlme.h
new file mode 100644
index 000000000000..bbb41471472d
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_mlme.h
@@ -0,0 +1,632 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTW_MLME_H_
+#define __RTW_MLME_H_
+
+#include "osdep_service.h"
+#include "mlme_osdep.h"
+#include "drv_types.h"
+#include "wlan_bssdef.h"
+
+#define MAX_BSS_CNT 128
+#define MAX_JOIN_TIMEOUT 6500
+
+/* Increase the scanning timeout because of increasing the SURVEY_TO value. */
+
+#define SCANNING_TIMEOUT 8000
+
+#define SCAN_INTERVAL (30) /* unit:2sec, 30*2=60sec */
+
+#define SCANQUEUE_LIFETIME 20 /* unit:sec */
+
+#define WIFI_NULL_STATE 0x00000000
+
+#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state */
+#define WIFI_REASOC_STATE 0x00000002
+#define WIFI_SLEEP_STATE 0x00000004
+#define WIFI_STATION_STATE 0x00000008
+
+#define WIFI_AP_STATE 0x00000010
+#define WIFI_ADHOC_STATE 0x00000020
+#define WIFI_ADHOC_MASTER_STATE 0x00000040
+#define WIFI_UNDER_LINKING 0x00000080
+
+#define WIFI_UNDER_WPS 0x00000100
+#define WIFI_STA_ALIVE_CHK_STATE 0x00000400
+#define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station is under site surveying */
+
+#define WIFI_MP_STATE 0x00010000
+#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in continuous tx background */
+#define WIFI_MP_CTX_ST 0x00040000 /* in continuous tx with single-tone */
+#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in continuous tx background due to out of skb */
+#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx */
+#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in continuous tx with carrier suppression */
+#define WIFI_MP_LPBK_STATE 0x00400000
+
+#define _FW_UNDER_LINKING WIFI_UNDER_LINKING
+#define _FW_LINKED WIFI_ASOC_STATE
+#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR
+
+enum dot11AuthAlgrthmNum {
+ dot11AuthAlgrthm_Open = 0,
+ dot11AuthAlgrthm_Shared,
+ dot11AuthAlgrthm_8021X,
+ dot11AuthAlgrthm_Auto,
+ dot11AuthAlgrthm_WAPI,
+ dot11AuthAlgrthm_MaxNum
+};
+
+/* Scan type including active and passive scan. */
+enum rt_scan_type {
+ SCAN_PASSIVE,
+ SCAN_ACTIVE,
+ SCAN_MIX,
+};
+
+enum SCAN_RESULT_TYPE {
+ SCAN_RESULT_P2P_ONLY = 0, /* Will return all the P2P devices. */
+ SCAN_RESULT_ALL = 1, /* Will return all the scanned device,
+ * include AP. */
+ SCAN_RESULT_WFD_TYPE = 2 /* Will just return the correct WFD
+ * device. */
+ /* If this device is Miracast sink
+ * device, it will just return all the
+ * Miracast source devices. */
+};
+
+/*
+there are several "locks" in mlme_priv,
+since mlme_priv is a shared resource between many threads,
+like ISR/Call-Back functions, the OID handlers, and even timer functions.
+
+Each _queue has its own locks, already.
+Other items are protected by mlme_priv.lock.
+
+To avoid possible dead lock, any thread trying to modifiying mlme_priv
+SHALL not lock up more than one lock at a time!
+*/
+
+#define traffic_threshold 10
+#define traffic_scan_period 500
+
+struct sitesurvey_ctrl {
+ u64 last_tx_pkts;
+ uint last_rx_pkts;
+ int traffic_busy;
+ struct timer_list sitesurvey_ctrl_timer;
+};
+
+struct rt_link_detect {
+ u32 NumTxOkInPeriod;
+ u32 NumRxOkInPeriod;
+ u32 NumRxUnicastOkInPeriod;
+ bool bBusyTraffic;
+ bool bTxBusyTraffic;
+ bool bRxBusyTraffic;
+ bool bHigherBusyTraffic; /* For interrupt migration purpose. */
+ bool bHigherBusyRxTraffic; /* We may disable Tx interrupt according
+ * to Rx traffic. */
+ bool bHigherBusyTxTraffic; /* We may disable Tx interrupt according
+ * to Tx traffic. */
+};
+
+struct profile_info {
+ u8 ssidlen;
+ u8 ssid[ WLAN_SSID_MAXLEN ];
+ u8 peermac[ ETH_ALEN ];
+};
+
+struct tx_invite_req_info {
+ u8 token;
+ u8 benable;
+ u8 go_ssid[ WLAN_SSID_MAXLEN ];
+ u8 ssidlen;
+ u8 go_bssid[ ETH_ALEN ];
+ u8 peer_macaddr[ ETH_ALEN ];
+ u8 operating_ch; /* This information will be set by using the
+ * p2p_set op_ch=x */
+ u8 peer_ch; /* The listen channel for peer P2P device */
+};
+
+struct tx_invite_resp_info {
+ u8 token; /* Used to record the dialog token of p2p invitation
+ * request frame. */
+};
+
+struct tx_provdisc_req_info {
+ u16 wps_config_method_request; /* Used when sending the
+ * provisioning request frame*/
+ u16 peer_channel_num[2]; /* The channel number which the
+ * receiver stands. */
+ struct ndis_802_11_ssid ssid;
+ u8 peerDevAddr[ETH_ALEN]; /* Peer device address */
+ u8 peerIFAddr[ETH_ALEN]; /* Peer interface address */
+ u8 benable; /* This provision discovery
+ * request frame is trigger
+ * to send or not */
+};
+
+/* When peer device issue prov_disc_req first, we should store the following
+ * information */
+/* The UI must know this information to know which config method the
+ * remote p2p device needs. */
+struct rx_provdisc_req_info {
+ u8 peerDevAddr[ETH_ALEN]; /* Peer device address */
+ u8 strconfig_method_desc_of_prov_disc_req[4]; /* description
+ * for the config method located in the provisioning
+ * discovery request frame. */
+};
+
+struct tx_nego_req_info {
+ u16 peer_channel_num[2]; /* The channel number. */
+ u8 peerDevAddr[ETH_ALEN]; /* Peer device address */
+ u8 benable; /* This negotiation request frame is
+ * trigger to send or not */
+};
+
+struct group_id_info {
+ u8 go_device_addr[ ETH_ALEN ]; /* The GO's device address of
+ * this P2P group */
+ u8 ssid[ WLAN_SSID_MAXLEN ]; /* The SSID of this P2P group */
+};
+
+struct scan_limit_info {
+ u8 scan_op_ch_only; /* When this flag is set, the driver
+ * should only scan the op. channel */
+ u8 operation_ch[2]; /* Store the op. chan of invitation */
+};
+
+struct wifidirect_info {
+ struct adapter *padapter;
+ struct timer_list find_phase_timer;
+ struct timer_list restore_p2p_state_timer;
+
+ /* Used to do the scanning. After confirming the peer is availalble,
+ * the driver transmits the P2P frame to peer. */
+ struct timer_list pre_tx_scan_timer;
+ struct timer_list reset_ch_sitesurvey;
+ struct timer_list reset_ch_sitesurvey2; /* Just for resetting the scan
+ * limit function by using p2p nego */
+ struct tx_provdisc_req_info tx_prov_disc_info;
+ struct rx_provdisc_req_info rx_prov_disc_info;
+ struct tx_invite_req_info invitereq_info;
+ /* Store the profile information of persistent group */
+ struct profile_info profileinfo[P2P_MAX_PERSISTENT_GROUP_NUM];
+ struct tx_invite_resp_info inviteresp_info;
+ struct tx_nego_req_info nego_req_info;
+ /* Store the group id info when doing the group negot handshake. */
+ struct group_id_info groupid_info;
+ /* Used for get the limit scan channel from the Invitation procedure */
+ struct scan_limit_info rx_invitereq_info;
+ /* Used for get the limit scan chan from the P2P negotiation handshake*/
+ struct scan_limit_info p2p_info;
+ enum P2P_ROLE role;
+ enum P2P_STATE pre_p2p_state;
+ enum P2P_STATE p2p_state;
+ /* The device address should be the mac address of this device. */
+ u8 device_addr[ETH_ALEN];
+ u8 interface_addr[ETH_ALEN];
+ u8 social_chan[4];
+ u8 listen_channel;
+ u8 operating_channel;
+ u8 listen_dwell; /* This value should be between 1 and 3 */
+ u8 support_rate[8];
+ u8 p2p_wildcard_ssid[P2P_WILDCARD_SSID_LEN];
+ u8 intent; /* should only include the intent value. */
+ u8 p2p_peer_interface_addr[ETH_ALEN];
+ u8 p2p_peer_device_addr[ETH_ALEN];
+ u8 peer_intent; /* Included the intent value and tie breaker value. */
+ /* Device name for displaying on searching device screen */
+ u8 device_name[WPS_MAX_DEVICE_NAME_LEN];
+ u8 device_name_len;
+ u8 profileindex; /* Used to point to the index of profileinfo array */
+ u8 peer_operating_ch;
+ u8 find_phase_state_exchange_cnt;
+ /* The device password ID for group negotiation */
+ u16 device_password_id_for_nego;
+ u8 negotiation_dialog_token;
+ /* SSID information for group negotitation */
+ u8 nego_ssid[WLAN_SSID_MAXLEN];
+ u8 nego_ssidlen;
+ u8 p2p_group_ssid[WLAN_SSID_MAXLEN];
+ u8 p2p_group_ssid_len;
+ /* Flag to know if the persistent function should be supported or not.*/
+ u8 persistent_supported;
+ /* In the Sigma test, the Sigma will provide this enable from the
+ * sta_set_p2p CAPI. */
+ /* 0: disable */
+ /* 1: enable */
+ u8 session_available; /* Flag to set the WFD session available to
+ * enable or disable "by Sigma" */
+ /* In the Sigma test, the Sigma will disable the session available
+ * by using the sta_preset CAPI. */
+ /* 0: disable */
+ /* 1: enable */
+ u8 wfd_tdls_enable; /* Flag to enable or disable the TDLS by WFD Sigma*/
+ /* 0: disable */
+ /* 1: enable */
+ u8 wfd_tdls_weaksec; /* Flag to enable or disable the weak security
+ * function for TDLS by WFD Sigma */
+ /* 0: disable */
+ /* In this case, the driver can't issue the tdsl
+ * setup request frame. */
+ /* 1: enable */
+ /* In this case, the driver can issue the tdls
+ * setup request frame */
+ /* even the current security is weak security. */
+
+ /* This field will store the WPS value (PIN value or PBC) that UI had
+ * got from the user. */
+ enum P2P_WPSINFO ui_got_wps_info;
+ u16 supported_wps_cm; /* This field describes the WPS config method
+ * which this driver supported. */
+ /* The value should be the combination of config
+ * method defined in page104 of WPS v2.0 spec.*/
+ /* This field will contain the length of body of P2P Channel List
+ * attribute of group negotiation response frame. */
+ uint channel_list_attr_len;
+ /* This field will contain the body of P2P Channel List attribute of
+ * group negotitation response frame. */
+ /* We will use the channel_cnt and channel_list fields when constructing
+ * the group negotiation confirm frame. */
+ u8 channel_list_attr[100];
+ enum P2P_PS_MODE p2p_ps_mode; /* indicate p2p ps mode */
+ enum P2P_PS_STATE p2p_ps_state; /* indicate p2p ps state */
+ u8 noa_index; /* Identifies and instance of Notice of Absence timing. */
+ u8 ctwindow; /* Client traffic window. A period of time in TU after TBTT. */
+ u8 opp_ps; /* opportunistic power save. */
+ u8 noa_num; /* number of NoA descriptor in P2P IE. */
+ u8 noa_count[P2P_MAX_NOA_NUM]; /* Count for owner, Type of client. */
+ /* Max duration for owner, preferred or min acceptable duration for
+ * client. */
+ u32 noa_duration[P2P_MAX_NOA_NUM];
+ /* Length of interval for owner, preferred or max acceptable interval
+ * of client. */
+ u32 noa_interval[P2P_MAX_NOA_NUM];
+ /* schedule expressed in terms of the lower 4 bytes of the TSF timer. */
+ u32 noa_start_time[P2P_MAX_NOA_NUM];
+};
+
+struct tdls_ss_record { /* signal strength record */
+ u8 macaddr[ETH_ALEN];
+ u8 RxPWDBAll;
+ u8 is_tdls_sta; /* true: direct link sta, false: else */
+};
+
+struct tdls_info {
+ u8 ap_prohibited;
+ uint setup_state;
+ u8 sta_cnt;
+ u8 sta_maximum; /* 1:tdls sta is equal (NUM_STA-1), reach max direct link number; 0: else; */
+ struct tdls_ss_record ss_record;
+ u8 macid_index; /* macid entry that is ready to write */
+ u8 clear_cam; /* cam entry that is trying to clear, using it in direct link teardown */
+ u8 ch_sensing;
+ u8 cur_channel;
+ u8 candidate_ch;
+ u8 collect_pkt_num[MAX_CHANNEL_NUM];
+ spinlock_t cmd_lock;
+ spinlock_t hdl_lock;
+ u8 watchdog_count;
+ u8 dev_discovered; /* WFD_TDLS: for sigma test */
+ u8 enable;
+};
+
+struct qos_priv {
+ /* bit mask option: u-apsd,
+ * s-apsd, ts, block ack... */
+ unsigned int qos_option;
+};
+
+struct mlme_priv {
+ spinlock_t lock;
+ int fw_state; /* shall we protect this variable? maybe not necessarily... */
+ u8 bScanInProcess;
+ u8 to_join; /* flag */
+ u8 to_roaming; /* roaming trying times */
+
+ u8 *nic_hdl;
+
+ u8 not_indic_disco;
+ struct list_head *pscanned;
+ struct __queue free_bss_pool;
+ struct __queue scanned_queue;
+ u8 *free_bss_buf;
+ u8 key_mask; /* use to restore wep key after hal_init */
+ u32 num_of_scanned;
+
+ struct ndis_802_11_ssid assoc_ssid;
+ u8 assoc_bssid[6];
+
+ struct wlan_network cur_network;
+ struct wlan_network *cur_network_scanned;
+
+ u32 scan_interval;
+
+ struct timer_list assoc_timer;
+
+ uint assoc_by_bssid;
+ uint assoc_by_rssi;
+
+ struct timer_list scan_to_timer; /* driver itself handles scan_timeout status. */
+ u32 scan_start_time; /* used to evaluate the time spent in scanning */
+
+ struct qos_priv qospriv;
+
+ /* Number of non-HT AP/stations */
+ int num_sta_no_ht;
+
+ /* Number of HT AP/stations 20 MHz */
+ /* int num_sta_ht_20mhz; */
+
+ int num_FortyMHzIntolerant;
+ struct ht_priv htpriv;
+ struct rt_link_detect LinkDetectInfo;
+ struct timer_list dynamic_chk_timer; /* dynamic/periodic check timer */
+
+ u8 acm_mask; /* for wmm acm mask */
+ u8 ChannelPlan;
+ enum rt_scan_type scan_mode; /* active: 1, passive: 0 */
+
+ /* u8 probereq_wpsie[MAX_WPS_IE_LEN];added in probe req */
+ /* int probereq_wpsie_len; */
+ u8 *wps_probe_req_ie;
+ u32 wps_probe_req_ie_len;
+
+ u8 *assoc_req;
+ u32 assoc_req_len;
+ u8 *assoc_rsp;
+ u32 assoc_rsp_len;
+
+#if defined (CONFIG_88EU_AP_MODE)
+ /* Number of associated Non-ERP stations (i.e., stations using 802.11b
+ * in 802.11g BSS) */
+ int num_sta_non_erp;
+
+ /* Number of associated stations that do not support Short Slot Time */
+ int num_sta_no_short_slot_time;
+
+ /* Number of associated stations that do not support Short Preamble */
+ int num_sta_no_short_preamble;
+
+ int olbc; /* Overlapping Legacy BSS Condition */
+
+ /* Number of HT assoc sta that do not support greenfield */
+ int num_sta_ht_no_gf;
+
+ /* Number of associated non-HT stations */
+ /* int num_sta_no_ht; */
+
+ /* Number of HT associated stations 20 MHz */
+ int num_sta_ht_20mhz;
+
+ /* Overlapping BSS information */
+ int olbc_ht;
+
+ u16 ht_op_mode;
+
+ u8 *wps_beacon_ie;
+ /* u8 *wps_probe_req_ie; */
+ u8 *wps_probe_resp_ie;
+ u8 *wps_assoc_resp_ie;
+
+ u32 wps_beacon_ie_len;
+ u32 wps_probe_resp_ie_len;
+ u32 wps_assoc_resp_ie_len;
+
+ u8 *p2p_beacon_ie;
+ u8 *p2p_probe_req_ie;
+ u8 *p2p_probe_resp_ie;
+ u8 *p2p_go_probe_resp_ie; /* for GO */
+ u8 *p2p_assoc_req_ie;
+
+ u32 p2p_beacon_ie_len;
+ u32 p2p_probe_req_ie_len;
+ u32 p2p_probe_resp_ie_len;
+ u32 p2p_go_probe_resp_ie_len; /* for GO */
+ u32 p2p_assoc_req_ie_len;
+ spinlock_t bcn_update_lock;
+ u8 update_bcn;
+#endif /* if defined (CONFIG_88EU_AP_MODE) */
+};
+
+#ifdef CONFIG_88EU_AP_MODE
+
+struct hostapd_priv {
+ struct adapter *padapter;
+};
+
+int hostapd_mode_init(struct adapter *padapter);
+void hostapd_mode_unload(struct adapter *padapter);
+#endif
+
+extern unsigned char WPA_TKIP_CIPHER[4];
+extern unsigned char RSN_TKIP_CIPHER[4];
+extern unsigned char REALTEK_96B_IE[];
+extern unsigned char MCS_rate_2R[16];
+extern unsigned char MCS_rate_1R[16];
+
+void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf);
+void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf);
+void indicate_wx_scan_complete_event(struct adapter *padapter);
+void rtw_indicate_wx_assoc_event(struct adapter *padapter);
+void rtw_indicate_wx_disassoc_event(struct adapter *padapter);
+int event_thread(void *context);
+void rtw_join_timeout_handler (struct timer_list *t);
+void _rtw_scan_timeout_handler (struct timer_list *t);
+void rtw_free_network_queue(struct adapter *adapter, u8 isfreeall);
+int rtw_init_mlme_priv(struct adapter *adapter);
+void rtw_free_mlme_priv (struct mlme_priv *pmlmepriv);
+int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv);
+int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv,
+ int keyid, u8 set_tx);
+int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv);
+
+static inline u8 *get_bssid(struct mlme_priv *pmlmepriv)
+{ /* if sta_mode:pmlmepriv->cur_network.network.MacAddress=> bssid */
+ /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress=> ibss mac address */
+ return pmlmepriv->cur_network.network.MacAddress;
+}
+
+static inline int check_fwstate(struct mlme_priv *pmlmepriv, int state)
+{
+ if (pmlmepriv->fw_state & state)
+ return true;
+
+ return false;
+}
+
+static inline int get_fwstate(struct mlme_priv *pmlmepriv)
+{
+ return pmlmepriv->fw_state;
+}
+
+/*
+ * No Limit on the calling context,
+ * therefore set it to be the critical section...
+ *
+ * ### NOTE:#### (!!!!)
+ * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
+ */
+static inline void set_fwstate(struct mlme_priv *pmlmepriv, int state)
+{
+ pmlmepriv->fw_state |= state;
+ /* FOR HW integration */
+ if (_FW_UNDER_SURVEY==state)
+ pmlmepriv->bScanInProcess = true;
+}
+
+static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, int state)
+{
+ pmlmepriv->fw_state &= ~state;
+ /* FOR HW integration */
+ if (_FW_UNDER_SURVEY==state)
+ pmlmepriv->bScanInProcess = false;
+}
+
+/*
+ * No Limit on the calling context,
+ * therefore set it to be the critical section...
+ */
+static inline void clr_fwstate(struct mlme_priv *pmlmepriv, int state)
+{
+ spin_lock_bh(&pmlmepriv->lock);
+ if (check_fwstate(pmlmepriv, state))
+ pmlmepriv->fw_state ^= state;
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state)
+{
+ spin_lock_bh(&pmlmepriv->lock);
+ _clr_fwstate_(pmlmepriv, state);
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+static inline void up_scanned_network(struct mlme_priv *pmlmepriv)
+{
+ spin_lock_bh(&pmlmepriv->lock);
+ pmlmepriv->num_of_scanned++;
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+static inline void down_scanned_network(struct mlme_priv *pmlmepriv)
+{
+ spin_lock_bh(&pmlmepriv->lock);
+ pmlmepriv->num_of_scanned--;
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv, int val)
+{
+ spin_lock_bh(&pmlmepriv->lock);
+ pmlmepriv->num_of_scanned = val;
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+u16 rtw_get_capability(struct wlan_bssid_ex *bss);
+void rtw_update_scanned_network(struct adapter *adapter,
+ struct wlan_bssid_ex *target);
+void rtw_disconnect_hdl_under_linked(struct adapter *adapter,
+ struct sta_info *psta, u8 free_assoc);
+void rtw_generate_random_ibss(u8 *pibss);
+struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr);
+struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue);
+
+void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue);
+void rtw_indicate_disconnect(struct adapter *adapter);
+void rtw_indicate_connect(struct adapter *adapter);
+void rtw_indicate_scan_done( struct adapter *padapter, bool aborted);
+void rtw_scan_abort(struct adapter *adapter);
+
+int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie,
+ uint in_len);
+int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie,
+ uint in_len, uint initial_out_len);
+void rtw_init_registrypriv_dev_network(struct adapter *adapter);
+
+void rtw_update_registrypriv_dev_network(struct adapter *adapter);
+
+void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter);
+
+void _rtw_join_timeout_handler(struct adapter *adapter);
+void rtw_scan_timeout_handler(struct adapter *adapter);
+
+ void rtw_dynamic_check_timer_handlder(struct adapter *adapter);
+#define rtw_is_scan_deny(adapter) false
+#define rtw_clear_scan_deny(adapter) do {} while (0)
+#define rtw_set_scan_deny_timer_hdl(adapter) do {} while (0)
+#define rtw_set_scan_deny(adapter, ms) do {} while (0)
+
+int _rtw_init_mlme_priv(struct adapter *padapter);
+
+void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv);
+
+void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv);
+
+int _rtw_enqueue_network(struct __queue *queue, struct wlan_network *pnetwork);
+
+struct wlan_network *_rtw_dequeue_network(struct __queue *queue);
+
+ struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv);
+
+void _rtw_free_network(struct mlme_priv *pmlmepriv,
+ struct wlan_network *pnetwork, u8 isfreeall);
+void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
+ struct wlan_network *pnetwork);
+
+struct wlan_network* _rtw_find_network(struct __queue *scanned_queue, u8 *addr);
+
+void _rtw_free_network_queue(struct adapter *padapter, u8 isfreeall);
+
+int rtw_if_up(struct adapter *padapter);
+
+u8 *rtw_get_capability_from_ie(u8 *ie);
+u8 *rtw_get_timestampe_from_ie(u8 *ie);
+u8 *rtw_get_beacon_interval_from_ie(u8 *ie);
+
+void rtw_joinbss_reset(struct adapter *padapter);
+
+unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie,
+ u8 *out_ie, uint in_len, uint *pout_len);
+void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len);
+void rtw_issue_addbareq_cmd(struct adapter *padapter,
+ struct xmit_frame *pxmitframe);
+
+int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork);
+int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst);
+
+void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network);
+void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network);
+void rtw_set_roaming(struct adapter *adapter, u8 to_roaming);
+u8 rtw_to_roaming(struct adapter *adapter);
+
+void rtw_sta_media_status_rpt(struct adapter *adapter, struct sta_info *psta,
+ u32 mstatus);
+
+#endif /* __RTL871X_MLME_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/r8188eu/include/rtw_mlme_ext.h
index c4fcfa986726..d2f4d3ce7b90 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
+++ b/drivers/staging/r8188eu/include/rtw_mlme_ext.h
@@ -1,15 +1,12 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTW_MLME_EXT_H_
#define __RTW_MLME_EXT_H_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <wlan_bssdef.h>
+#include "osdep_service.h"
+#include "drv_types.h"
+#include "wlan_bssdef.h"
/* Commented by Albert 20101105 */
/* Increase the SURVEY_TO value from 100 to 150 ( 100ms to 150ms ) */
@@ -78,17 +75,21 @@
#define _48M_RATE_ 10
#define _54M_RATE_ 11
-extern const u8 RTW_WPA_OUI[];
-extern const u8 WPS_OUI[];
+extern unsigned char RTW_WPA_OUI[];
+extern unsigned char WMM_OUI[];
+extern unsigned char WPS_OUI[];
+extern unsigned char WFD_OUI[];
+extern unsigned char P2P_OUI[];
+
+extern unsigned char WMM_INFO_OUI[];
+extern unsigned char WMM_PARA_OUI[];
/* Channel Plan Type. */
/* Note: */
/* We just add new channel plan when the new channel plan is different
- * from any of the following channel plan.
- */
+ * from any of the following channel plan. */
/* If you just want to customize the actions(scan period or join actions)
- * about one of the channel plan,
- */
+ * about one of the channel plan, */
/* customize them in struct rt_channel_info in the RT_CHANNEL_LIST. */
enum RT_CHANNEL_DOMAIN {
/* old channel plan mapping ===== */
@@ -111,7 +112,6 @@ enum RT_CHANNEL_DOMAIN {
RT_CHANNEL_DOMAIN_JAPAN = 0x10,
RT_CHANNEL_DOMAIN_FCC_NO_DFS = 0x11,
RT_CHANNEL_DOMAIN_JAPAN_NO_DFS = 0x12,
- RT_CHANNEL_DOMAIN_WORLD_WIDE_5G = 0x13,
RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS = 0x14,
/* new channel plan mapping, (2GDOMAIN_5GDOMAIN) ===== */
@@ -214,22 +214,22 @@ enum SCAN_STATE {
};
struct mlme_handler {
- unsigned int num;
- const char *str;
+ unsigned int num;
+ char *str;
unsigned int (*func)(struct adapter *adapt, struct recv_frame *frame);
};
struct action_handler {
- unsigned int num;
- const char *str;
+ unsigned int num;
+ char* str;
unsigned int (*func)(struct adapter *adapt, struct recv_frame *frame);
};
-struct ss_res {
- int state;
- int bss_cnt;
- int channel_idx;
- int scan_mode;
+struct ss_res {
+ int state;
+ int bss_cnt;
+ int channel_idx;
+ int scan_mode;
u8 ssid_num;
u8 ch_num;
struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
@@ -296,8 +296,7 @@ struct mlme_ext_info {
u32 authModeToggle;
u32 enc_algo;/* encrypt algorithm; */
u32 key_index; /* this is only valid for legacy wep,
- * 0~3 for key id.
- */
+ * 0~3 for key id. */
u32 iv;
u8 chg_txt[128];
u16 aid;
@@ -321,29 +320,26 @@ struct mlme_ext_info {
u8 candidate_tid_bitmap;
u8 dialogToken;
/* Accept ADDBA Request */
- bool accept_addba_req;
+ bool bAcceptAddbaReq;
u8 bwmode_updated;
u8 hidden_ssid_mode;
struct ADDBA_request ADDBA_req;
struct WMM_para_element WMM_param;
- struct ieee80211_ht_cap HT_caps;
+ struct HT_caps_element HT_caps;
struct HT_info_element HT_info;
struct wlan_bssid_ex network;/* join network or bss_network,
* if in ap mode, it is the same
- * as cur_network.network
- */
+ * as cur_network.network */
struct FW_Sta_Info FW_sta_info[NUM_STA];
};
/* The channel information about this channel including joining,
- * scanning, and power constraints.
- */
+ * scanning, and power constraints. */
struct rt_channel_info {
u8 ChannelNum; /* The channel number. */
enum rt_scan_type ScanType; /* Scan type such as passive
- * or active scan.
- */
+ * or active scan. */
u32 rx_count;
};
@@ -383,8 +379,9 @@ struct p2p_oper_class_map {
};
struct mlme_ext_priv {
+ struct adapter *padapter;
u8 mlmeext_init;
- atomic_t event_seq;
+ atomic_t event_seq;
u16 mgnt_seq;
unsigned char cur_channel;
@@ -393,8 +390,7 @@ struct mlme_ext_priv {
unsigned char cur_wireless_mode; /* NETWORK_TYPE */
unsigned char oper_channel; /* saved chan info when call
- * set_channel_bw
- */
+ * set_channel_bw */
unsigned char oper_bwmode;
unsigned char oper_ch_offset;/* PRIME_CHNL_OFFSET */
@@ -408,8 +404,7 @@ struct mlme_ext_priv {
struct mlme_ext_info mlmext_info;/* for sta/adhoc mode, including
* current scan/connecting/connected
* related info. For ap mode,
- * network includes ap's cap_info
- */
+ * network includes ap's cap_info*/
struct timer_list survey_timer;
struct timer_list link_timer;
u16 chan_scan_time;
@@ -433,13 +428,13 @@ struct mlme_ext_priv {
int init_mlme_ext_priv(struct adapter *adapter);
int init_hw_mlme_ext(struct adapter *padapter);
-void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext);
-void init_mlme_ext_timer(struct adapter *padapter);
-void init_addba_retry_timer(struct adapter *adapt, struct sta_info *sta);
-struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv);
+void free_mlme_ext_priv (struct mlme_ext_priv *pmlmeext);
+extern void init_mlme_ext_timer(struct adapter *padapter);
+extern void init_addba_retry_timer(struct adapter *adapt, struct sta_info *sta);
+extern struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv);
unsigned char networktype_to_raid(unsigned char network_type);
-u8 judge_network_type(struct adapter *padapter, unsigned char *rate);
+u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int len);
void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *len);
void UpdateBrateTbl(struct adapter *padapter, u8 *mBratesOS);
void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen);
@@ -452,7 +447,9 @@ void Set_MSR(struct adapter *padapter, u8 type);
u8 rtw_get_oper_ch(struct adapter *adapter);
void rtw_set_oper_ch(struct adapter *adapter, u8 ch);
+u8 rtw_get_oper_bw(struct adapter *adapter);
void rtw_set_oper_bw(struct adapter *adapter, u8 bw);
+u8 rtw_get_oper_choffset(struct adapter *adapter);
void rtw_set_oper_choffset(struct adapter *adapter, u8 offset);
void set_channel_bwmode(struct adapter *padapter, unsigned char channel,
@@ -467,13 +464,19 @@ void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key);
void clear_cam_entry(struct adapter *padapter, u8 entry);
void invalidate_cam_all(struct adapter *padapter);
+void CAM_empty_entry(struct adapter * Adapter, u8 ucIndex);
int allocate_fw_sta_entry(struct adapter *padapter);
void flush_all_cam_entry(struct adapter *padapter);
+void site_survey(struct adapter *padapter);
+u8 collect_bss_info(struct adapter *padapter, struct recv_frame *precv_frame,
+ struct wlan_bssid_ex *bssid);
void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
struct adapter *adapter, bool update_ie);
+int get_bsstype(unsigned short capability);
+u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork);
u16 get_beacon_interval(struct wlan_bssid_ex *bss);
int is_client_associated_to_ap(struct adapter *padapter);
@@ -493,7 +496,7 @@ void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE);
void VCS_update(struct adapter *padapter, struct sta_info *psta);
void update_beacon_info(struct adapter *padapter, u8 *pframe, uint len,
- struct sta_info *psta);
+ struct sta_info *psta);
int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len);
void update_IOT_info(struct adapter *padapter);
void update_capinfo(struct adapter *adapter, u16 updatecap);
@@ -507,39 +510,126 @@ int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie,
void update_sta_info(struct adapter *padapter, struct sta_info *psta);
unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz);
unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz);
-unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps);
+unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps);
void Update_RA_Entry(struct adapter *padapter, u32 mac_id);
void set_sta_rate(struct adapter *padapter, struct sta_info *psta);
+unsigned int receive_disconnect(struct adapter *padapter,
+ unsigned char *macaddr, unsigned short reason);
+
unsigned char get_highest_rate_idx(u32 mask);
-int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *caps);
+int support_short_GI(struct adapter *padapter, struct HT_caps_element *caps);
unsigned int is_ap_in_tkip(struct adapter *padapter);
+unsigned int is_ap_in_wep(struct adapter *padapter);
+unsigned int should_forbid_n_rate(struct adapter *padapter);
void report_join_res(struct adapter *padapter, int res);
-void report_survey_event(struct adapter *padapter,
- struct recv_frame *precv_frame);
+void report_survey_event(struct adapter *padapter, struct recv_frame *precv_frame);
void report_surveydone_event(struct adapter *padapter);
void report_del_sta_event(struct adapter *padapter,
unsigned char *addr, unsigned short reason);
-void report_add_sta_event(struct adapter *padapter, unsigned char *addr,
+void report_add_sta_event(struct adapter *padapter, unsigned char* addr,
int cam_idx);
-u8 set_tx_beacon_cmd(struct adapter *padapter);
+void beacon_timing_control(struct adapter *padapter);
+extern u8 set_tx_beacon_cmd(struct adapter*padapter);
unsigned int setup_beacon_frame(struct adapter *padapter,
unsigned char *beacon_frame);
void update_mgnt_tx_rate(struct adapter *padapter, u8 rate);
void update_mgntframe_attrib(struct adapter *padapter,
struct pkt_attrib *pattrib);
-
+void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe);
+s32 dump_mgntframe_and_wait(struct adapter *padapter,
+ struct xmit_frame *pmgntframe, int timeout_ms);
+s32 dump_mgntframe_and_wait_ack(struct adapter *padapter,
+ struct xmit_frame *pmgntframe);
+
+#ifdef CONFIG_88EU_P2P
+void issue_probersp_p2p(struct adapter *padapter, unsigned char *da);
+void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid,
+ u8 ussidlen, u8 *pdev_raddr);
+void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr);
+void issue_probereq_p2p(struct adapter *padapter, u8 *da);
+int issue_probereq_p2p_ex(struct adapter *adapter, u8 *da, int try_cnt,
+ int wait_ms);
+void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr,
+ u8 dialogToken, u8 success);
+void issue_p2p_invitation_request(struct adapter *padapter, u8* raddr);
+#endif /* CONFIG_88EU_P2P */
+void issue_beacon(struct adapter *padapter, int timeout_ms);
+void issue_probersp(struct adapter *padapter, unsigned char *da,
+ u8 is_valid_p2p_probereq);
+void issue_assocreq(struct adapter *padapter);
+void issue_asocrsp(struct adapter *padapter, unsigned short status,
+ struct sta_info *pstat, int pkt_type);
+void issue_auth(struct adapter *padapter, struct sta_info *psta,
+ unsigned short status);
+void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid,
+ u8 *da);
+s32 issue_probereq_ex(struct adapter *adapter, struct ndis_802_11_ssid *pssid,
+ u8* da, int try_cnt, int wait_ms);
int issue_nulldata(struct adapter *padapter, unsigned char *da,
unsigned int power_mode, int try_cnt, int wait_ms);
int issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
u16 tid, int try_cnt, int wait_ms);
int issue_deauth(struct adapter *padapter, unsigned char *da,
unsigned short reason);
+int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason,
+ int try_cnt, int wait_ms);
+void issue_action_spct_ch_switch(struct adapter *padapter, u8 *ra, u8 new_ch,
+ u8 ch_offset);
+void issue_action_BA(struct adapter *padapter, unsigned char *raddr,
+ unsigned char action, unsigned short status);
unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr);
unsigned int send_beacon(struct adapter *padapter);
+void start_clnt_assoc(struct adapter *padapter);
+void start_clnt_auth(struct adapter *padapter);
+void start_clnt_join(struct adapter *padapter);
+void start_create_ibss(struct adapter *padapter);
+
+unsigned int OnAssocReq(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAssocRsp(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnProbeReq(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnProbeRsp(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int DoReserved(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnBeacon(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAtim(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnDisassoc(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAuth(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAuthClient(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnDeAuth(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAction(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+
+unsigned int on_action_spct(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAction_qos(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAction_dls(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAction_back(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int on_action_public(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAction_ht(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAction_wmm(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+unsigned int OnAction_p2p(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+
void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res);
void mlmeext_sta_del_event_callback(struct adapter *padapter);
void mlmeext_sta_add_event_callback(struct adapter *padapter,
@@ -547,17 +637,22 @@ void mlmeext_sta_add_event_callback(struct adapter *padapter,
void linked_status_chk(struct adapter *padapter);
-void survey_timer_hdl(struct timer_list *t);
-void link_timer_hdl(struct timer_list *t);
-void addba_timer_hdl(struct timer_list *t);
+void survey_timer_hdl (struct adapter *padapter);
+void link_timer_hdl (struct adapter *padapter);
+void addba_timer_hdl(struct sta_info *psta);
#define set_survey_timer(mlmeext, ms) \
- mod_timer(&mlmeext->survey_timer, jiffies + \
- msecs_to_jiffies(ms))
+ do { \
+ _set_timer(&(mlmeext)->survey_timer, (ms)); \
+ } while (0)
#define set_link_timer(mlmeext, ms) \
- mod_timer(&mlmeext->link_timer, jiffies + \
- msecs_to_jiffies(ms))
+ do { \
+ _set_timer(&(mlmeext)->link_timer, (ms)); \
+ } while (0)
+
+int cckrates_included(unsigned char *rate, int ratelen);
+int cckratesonly_included(unsigned char *rate, int ratelen);
void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr);
@@ -575,6 +670,7 @@ u8 read_bbreg_hdl(struct adapter *padapter, u8 *pbuf);
u8 write_bbreg_hdl(struct adapter *padapter, u8 *pbuf);
u8 read_rfreg_hdl(struct adapter *padapter, u8 *pbuf);
u8 write_rfreg_hdl(struct adapter *padapter, u8 *pbuf);
+u8 NULL_hdl(struct adapter *padapter, u8 *pbuf);
u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf);
u8 disconnect_hdl(struct adapter *padapter, u8 *pbuf);
u8 createbss_hdl(struct adapter *padapter, u8 *pbuf);
@@ -597,6 +693,88 @@ u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf);
u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf);
u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf);
+#define GEN_DRV_CMD_HANDLER(size, cmd) {size, &cmd ## _hdl},
+#define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd},
+
+#ifdef _RTW_CMD_C_
+
+static struct cmd_hdl wlancmds[] = {
+ GEN_DRV_CMD_HANDLER(0, NULL) /*0*/
+ GEN_DRV_CMD_HANDLER(0, NULL)
+ GEN_DRV_CMD_HANDLER(0, NULL)
+ GEN_DRV_CMD_HANDLER(0, NULL)
+ GEN_DRV_CMD_HANDLER(0, NULL)
+ GEN_DRV_CMD_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL) /*10*/
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct joinbss_parm), join_cmd_hdl) /*14*/
+ GEN_MLME_EXT_HANDLER(sizeof (struct disconnect_parm), disconnect_hdl)
+ GEN_MLME_EXT_HANDLER(sizeof (struct createbss_parm), createbss_hdl)
+ GEN_MLME_EXT_HANDLER(sizeof (struct setopmode_parm), setopmode_hdl)
+ GEN_MLME_EXT_HANDLER(sizeof (struct sitesurvey_parm),
+ sitesurvey_cmd_hdl) /*18*/
+ GEN_MLME_EXT_HANDLER(sizeof (struct setauth_parm), setauth_hdl)
+ GEN_MLME_EXT_HANDLER(sizeof (struct setkey_parm), setkey_hdl) /*20*/
+ GEN_MLME_EXT_HANDLER(sizeof (struct set_stakey_parm), set_stakey_hdl)
+ GEN_MLME_EXT_HANDLER(sizeof (struct set_assocsta_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct del_assocsta_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct setstapwrstate_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct setbasicrate_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct getbasicrate_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct setdatarate_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct getdatarate_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct setphyinfo_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct getphyinfo_parm), NULL) /*30*/
+ GEN_MLME_EXT_HANDLER(sizeof (struct setphy_parm), NULL)
+ GEN_MLME_EXT_HANDLER(sizeof (struct getphy_parm), NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL) /*40*/
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl)
+ GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) /* 46 */
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL) /*50*/
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(0, NULL)
+ GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param),
+ tx_beacon_hdl) /*55*/
+
+ GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) /*56*/
+ GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) /*57*/
+
+ GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl) /*58*/
+ GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param),
+ set_chplan_hdl) /*59*/
+ GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param),
+ led_blink_hdl) /*60*/
+
+ GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param),
+ set_csa_hdl) /*61*/
+ GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param),
+ tdls_hdl) /*62*/
+};
+
+#endif
+
struct C2HEvent_Header {
#ifdef __LITTLE_ENDIAN
unsigned int len:16;
@@ -614,34 +792,33 @@ void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf);
void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf);
enum rtw_c2h_event {
- _Read_MACREG_EVT_ = 0, /*0*/
- _Read_BBREG_EVT_,
- _Read_RFREG_EVT_,
- _Read_EEPROM_EVT_,
- _Read_EFUSE_EVT_,
- _Read_CAM_EVT_, /*5*/
- _Get_BasicRate_EVT_,
- _Get_DataRate_EVT_,
- _Survey_EVT_, /*8*/
- _SurveyDone_EVT_, /*9*/
-
- _JoinBss_EVT_, /*10*/
- _AddSTA_EVT_,
- _DelSTA_EVT_,
- _AtimDone_EVT_,
- _TX_Report_EVT_,
- _CCX_Report_EVT_, /*15*/
- _DTM_Report_EVT_,
- _TX_Rate_Statistics_EVT_,
- _C2HLBK_EVT_,
- _FWDBG_EVT_,
- _C2HFEEDBACK_EVT_, /*20*/
- _ADDBA_EVT_,
- _C2HBCN_EVT_,
- _ReportPwrState_EVT_, /* filen: only for PCIE, USB */
- _CloseRF_EVT_, /* filen: only for PCIE,
- * work around ASPM
- */
+ GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/
+ GEN_EVT_CODE(_Read_BBREG),
+ GEN_EVT_CODE(_Read_RFREG),
+ GEN_EVT_CODE(_Read_EEPROM),
+ GEN_EVT_CODE(_Read_EFUSE),
+ GEN_EVT_CODE(_Read_CAM), /*5*/
+ GEN_EVT_CODE(_Get_BasicRate),
+ GEN_EVT_CODE(_Get_DataRate),
+ GEN_EVT_CODE(_Survey), /*8*/
+ GEN_EVT_CODE(_SurveyDone), /*9*/
+
+ GEN_EVT_CODE(_JoinBss) , /*10*/
+ GEN_EVT_CODE(_AddSTA),
+ GEN_EVT_CODE(_DelSTA),
+ GEN_EVT_CODE(_AtimDone),
+ GEN_EVT_CODE(_TX_Report),
+ GEN_EVT_CODE(_CCX_Report), /*15*/
+ GEN_EVT_CODE(_DTM_Report),
+ GEN_EVT_CODE(_TX_Rate_Statistics),
+ GEN_EVT_CODE(_C2HLBK),
+ GEN_EVT_CODE(_FWDBG),
+ GEN_EVT_CODE(_C2HFEEDBACK), /*20*/
+ GEN_EVT_CODE(_ADDBA),
+ GEN_EVT_CODE(_C2HBCN),
+ GEN_EVT_CODE(_ReportPwrState), /* filen: only for PCIE, USB */
+ GEN_EVT_CODE(_CloseRF), /* filen: only for PCIE,
+ * work around ASPM */
MAX_C2HEVT
};
@@ -657,7 +834,7 @@ static struct fwevent wlanevents[] = {
{0, NULL},
{0, NULL},
{0, &rtw_survey_event_callback}, /*8*/
- {sizeof(struct surveydone_event), &rtw_surveydone_event_callback},/*9*/
+ {sizeof (struct surveydone_event), &rtw_surveydone_event_callback},/*9*/
{0, &rtw_joinbss_event_callback}, /*10*/
{sizeof(struct stassoc_event), &rtw_stassoc_event_callback},
{sizeof(struct stadel_event), &rtw_stadel_event_callback},
diff --git a/drivers/staging/r8188eu/include/rtw_mp.h b/drivers/staging/r8188eu/include/rtw_mp.h
new file mode 100644
index 000000000000..3a259d991348
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_mp.h
@@ -0,0 +1,474 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _RTW_MP_H_
+#define _RTW_MP_H_
+
+/* 00 - Success */
+/* 11 - Error */
+#define STATUS_SUCCESS (0x00000000L)
+#define STATUS_PENDING (0x00000103L)
+
+#define STATUS_UNSUCCESSFUL (0xC0000001L)
+#define STATUS_INSUFFICIENT_RESOURCES (0xC000009AL)
+#define STATUS_NOT_SUPPORTED (0xC00000BBL)
+
+#define NDIS_STATUS_SUCCESS ((int)STATUS_SUCCESS)
+#define NDIS_STATUS_PENDING ((int)STATUS_PENDING)
+#define NDIS_STATUS_NOT_RECOGNIZED ((int)0x00010001L)
+#define NDIS_STATUS_NOT_COPIED ((int)0x00010002L)
+#define NDIS_STATUS_NOT_ACCEPTED ((int)0x00010003L)
+#define NDIS_STATUS_CALL_ACTIVE ((int)0x00010007L)
+
+#define NDIS_STATUS_FAILURE ((int)STATUS_UNSUCCESSFUL)
+#define NDIS_STATUS_RESOURCES ((int)STATUS_INSUFFICIENT_RESOURCES)
+#define NDIS_STATUS_CLOSING ((int)0xC0010002L)
+#define NDIS_STATUS_BAD_VERSION ((int)0xC0010004L)
+#define NDIS_STATUS_BAD_CHARACTERISTICS ((int)0xC0010005L)
+#define NDIS_STATUS_ADAPTER_NOT_FOUND ((int)0xC0010006L)
+#define NDIS_STATUS_OPEN_FAILED ((int)0xC0010007L)
+#define NDIS_STATUS_DEVICE_FAILED ((int)0xC0010008L)
+#define NDIS_STATUS_MULTICAST_FULL ((int)0xC0010009L)
+#define NDIS_STATUS_MULTICAST_EXISTS ((int)0xC001000AL)
+#define NDIS_STATUS_MULTICAST_NOT_FOUND ((int)0xC001000BL)
+#define NDIS_STATUS_REQUEST_ABORTED ((int)0xC001000CL)
+#define NDIS_STATUS_RESET_IN_PROGRESS ((int)0xC001000DL)
+#define NDIS_STATUS_CLOSING_INDICATING ((int)0xC001000EL)
+#define NDIS_STATUS_NOT_SUPPORTED ((int)STATUS_NOT_SUPPORTED)
+#define NDIS_STATUS_INVALID_PACKET ((int)0xC001000FL)
+#define NDIS_STATUS_OPEN_LIST_FULL ((int)0xC0010010L)
+#define NDIS_STATUS_ADAPTER_NOT_READY ((int)0xC0010011L)
+#define NDIS_STATUS_ADAPTER_NOT_OPEN ((int)0xC0010012L)
+#define NDIS_STATUS_NOT_INDICATING ((int)0xC0010013L)
+#define NDIS_STATUS_INVALID_LENGTH ((int)0xC0010014L)
+#define NDIS_STATUS_INVALID_DATA ((int)0xC0010015L)
+#define NDIS_STATUS_BUFFER_TOO_SHORT ((int)0xC0010016L)
+#define NDIS_STATUS_INVALID_OID ((int)0xC0010017L)
+#define NDIS_STATUS_ADAPTER_REMOVED ((int)0xC0010018L)
+#define NDIS_STATUS_UNSUPPORTED_MEDIA ((int)0xC0010019L)
+#define NDIS_STATUS_GROUP_ADDRESS_IN_USE ((int)0xC001001AL)
+#define NDIS_STATUS_FILE_NOT_FOUND ((int)0xC001001BL)
+#define NDIS_STATUS_ERROR_READING_FILE ((int)0xC001001CL)
+#define NDIS_STATUS_ALREADY_MAPPED ((int)0xC001001DL)
+#define NDIS_STATUS_RESOURCE_CONFLICT ((int)0xC001001EL)
+#define NDIS_STATUS_NO_CABLE ((int)0xC001001FL)
+
+#define NDIS_STATUS_INVALID_SAP ((int)0xC0010020L)
+#define NDIS_STATUS_SAP_IN_USE ((int)0xC0010021L)
+#define NDIS_STATUS_INVALID_ADDRESS ((int)0xC0010022L)
+#define NDIS_STATUS_VC_NOT_ACTIVATED ((int)0xC0010023L)
+#define NDIS_STATUS_DEST_OUT_OF_ORDER ((int)0xC0010024L) /*cause 27*/
+#define NDIS_STATUS_VC_NOT_AVAILABLE ((int)0xC0010025L) /*cause 35,45 */
+#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE ((int)0xC0010026L) /*cause 37*/
+#define NDIS_STATUS_INCOMPATABLE_QOS ((int)0xC0010027L) /*cause 49*/
+#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED ((int)0xC0010028L) /*cause 93*/
+#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION ((int)0xC0010029L) /*cause 3 */
+
+enum antenna_path {
+ ANTENNA_NONE = 0x00,
+ ANTENNA_D,
+ ANTENNA_C,
+ ANTENNA_CD,
+ ANTENNA_B,
+ ANTENNA_BD,
+ ANTENNA_BC,
+ ANTENNA_BCD,
+ ANTENNA_A,
+ ANTENNA_AD,
+ ANTENNA_AC,
+ ANTENNA_ACD,
+ ANTENNA_AB,
+ ANTENNA_ABD,
+ ANTENNA_ABC,
+ ANTENNA_ABCD
+};
+
+#define MAX_MP_XMITBUF_SZ 2048
+#define NR_MP_XMITFRAME 8
+
+struct mp_xmit_frame {
+ struct list_head list;
+ struct pkt_attrib attrib;
+ struct sk_buff *pkt;
+ int frame_tag;
+ struct adapter *padapter;
+ struct urb *pxmit_urb[8];
+ /* insert urb, irp, and irpcnt info below... */
+ u8 *mem_addr;
+ u32 sz[8];
+ u8 bpending[8];
+ int ac_tag[8];
+ int last[8];
+ uint irpcnt;
+ uint fragcnt;
+ uint mem[(MAX_MP_XMITBUF_SZ >> 2)];
+};
+
+struct mp_wiparam {
+ u32 bcompleted;
+ u32 act_type;
+ u32 io_offset;
+ u32 io_value;
+};
+
+typedef void(*wi_act_func)(void *padapter);
+
+struct mp_tx {
+ u8 stop;
+ u32 count, sended;
+ u8 payload;
+ struct pkt_attrib attrib;
+ struct tx_desc desc;
+ u8 *pallocated_buf;
+ u8 *buf;
+ u32 buf_size, write_size;
+ void *PktTxThread;
+};
+
+#include "Hal8188EPhyCfg.h"
+
+#define MP_MAX_LINES 1000
+#define MP_MAX_LINES_BYTES 256
+
+typedef void (*MPT_WORK_ITEM_HANDLER)(void *Adapter);
+
+struct mpt_context {
+ /* Indicate if we have started Mass Production Test. */
+ bool bMassProdTest;
+
+ /* Indicate if the driver is unloading or unloaded. */
+ bool bMptDrvUnload;
+
+ struct semaphore MPh2c_Sema;
+ struct timer_list MPh2c_timeout_timer;
+/* Event used to sync H2c for BT control */
+
+ bool MptH2cRspEvent;
+ bool MptBtC2hEvent;
+ bool bMPh2c_timeout;
+
+ /* 8190 PCI does not support NDIS_WORK_ITEM. */
+ /* Work Item for Mass Production Test. */
+ /* Event used to sync the case unloading driver and MptWorkItem
+ * is still in progress. */
+ /* Indicate a MptWorkItem is scheduled and not yet finished. */
+ bool bMptWorkItemInProgress;
+ /* An instance which implements function and context of MptWorkItem. */
+ MPT_WORK_ITEM_HANDLER CurrMptAct;
+
+ /* 1=Start, 0=Stop from UI. */
+ u32 MptTestStart;
+ /* _TEST_MODE, defined in MPT_Req2.h */
+ u32 MptTestItem;
+ /* Variable needed in each implementation of CurrMptAct. */
+ u32 MptActType; /* Type of action performed in CurrMptAct. */
+ /* The Offset of IO operation is depend of MptActType. */
+ u32 MptIoOffset;
+ /* The Value of IO operation is depend of MptActType. */
+ u32 MptIoValue;
+ /* The RfPath of IO operation is depend of MptActType. */
+ u32 MptRfPath;
+
+ enum wireless_mode MptWirelessModeToSw; /* Wireless mode to switch. */
+ u8 MptChannelToSw; /* Channel to switch. */
+ u8 MptInitGainToSet; /* Initial gain to set. */
+ u32 MptBandWidth; /* bandwidth to switch. */
+ u32 MptRateIndex; /* rate index. */
+ /* Register value kept for Single Carrier Tx test. */
+ u8 btMpCckTxPower;
+ /* Register value kept for Single Carrier Tx test. */
+ u8 btMpOfdmTxPower;
+ /* For MP Tx Power index */
+ u8 TxPwrLevel[2]; /* rf-A, rf-B */
+
+ /* Content of RCR Regsiter for Mass Production Test. */
+ u32 MptRCR;
+ /* true if we only receive packets with specific pattern. */
+ bool bMptFilterPattern;
+ /* Rx OK count, statistics used in Mass Production Test. */
+ u32 MptRxOkCnt;
+ /* Rx CRC32 error count, statistics used in Mass Production Test. */
+ u32 MptRxCrcErrCnt;
+
+ bool bCckContTx; /* true if we are in CCK Continuous Tx test. */
+ bool bOfdmContTx; /* true if we are in OFDM Continuous Tx test. */
+ bool bStartContTx; /* true if we have start Continuous Tx test. */
+ /* true if we are in Single Carrier Tx test. */
+ bool bSingleCarrier;
+ /* true if we are in Carrier Suppression Tx Test. */
+ bool bCarrierSuppression;
+ /* true if we are in Single Tone Tx test. */
+ bool bSingleTone;
+
+ /* ACK counter asked by K.Y.. */
+ bool bMptEnableAckCounter;
+ u32 MptAckCounter;
+
+ u8 APK_bound[2]; /* for APK path A/path B */
+ bool bMptIndexEven;
+
+ u8 backup0xc50;
+ u8 backup0xc58;
+ u8 backup0xc30;
+ u8 backup0x52_RF_A;
+ u8 backup0x52_RF_B;
+
+ u8 h2cReqNum;
+ u8 c2hBuf[20];
+
+ u8 btInBuf[100];
+ u32 mptOutLen;
+ u8 mptOutBuf[100];
+};
+
+enum {
+ WRITE_REG = 1,
+ READ_REG,
+ WRITE_RF,
+ READ_RF,
+ MP_START,
+ MP_STOP,
+ MP_RATE,
+ MP_CHANNEL,
+ MP_BANDWIDTH,
+ MP_TXPOWER,
+ MP_ANT_TX,
+ MP_ANT_RX,
+ MP_CTX,
+ MP_QUERY,
+ MP_ARX,
+ MP_PSD,
+ MP_PWRTRK,
+ MP_THER,
+ MP_IOCTL,
+ EFUSE_GET,
+ EFUSE_SET,
+ MP_RESET_STATS,
+ MP_DUMP,
+ MP_PHYPARA,
+ MP_SetRFPathSwh,
+ MP_QueryDrvStats,
+ MP_SetBT,
+ CTA_TEST,
+ MP_NULL,
+};
+
+struct mp_priv {
+ struct adapter *papdater;
+
+ /* Testing Flag */
+ /* 0 for normal type packet, 1 for loopback packet (16bytes TXCMD) */
+ u32 mode;
+
+ u32 prev_fw_state;
+
+ /* OID cmd handler */
+ struct mp_wiparam workparam;
+
+ /* Tx Section */
+ u8 TID;
+ u32 tx_pktcount;
+ struct mp_tx tx;
+
+ /* Rx Section */
+ u32 rx_pktcount;
+ u32 rx_crcerrpktcount;
+ u32 rx_pktloss;
+
+ struct recv_stat rxstat;
+
+ /* RF/BB relative */
+ u8 channel;
+ u8 bandwidth;
+ u8 prime_channel_offset;
+ u8 txpoweridx;
+ u8 txpoweridx_b;
+ u8 rateidx;
+ u32 preamble;
+ u32 CrystalCap;
+
+ u16 antenna_tx;
+ u16 antenna_rx;
+
+ u8 check_mp_pkt;
+
+ u8 bSetTxPower;
+
+ struct wlan_network mp_network;
+ unsigned char network_macaddr[ETH_ALEN];
+
+ u8 *pallocated_mp_xmitframe_buf;
+ u8 *pmp_xmtframe_buf;
+ struct __queue free_mp_xmitqueue;
+ u32 free_mp_xmitframe_cnt;
+
+ struct mpt_context MptCtx;
+};
+
+struct iocmd_struct {
+ u8 cmdclass;
+ u16 value;
+ u8 index;
+};
+
+struct rf_reg_param {
+ u32 path;
+ u32 offset;
+ u32 value;
+};
+
+struct bb_reg_param {
+ u32 offset;
+ u32 value;
+};
+/* */
+
+#define LOWER true
+#define RAISE false
+
+/* Hardware Registers */
+#define BB_REG_BASE_ADDR 0x800
+
+/* MP variables */
+enum mp_mode_{
+ MP_OFF,
+ MP_ON,
+ MP_ERR,
+ MP_CONTINUOUS_TX,
+ MP_SINGLE_CARRIER_TX,
+ MP_CARRIER_SUPPRISSION_TX,
+ MP_SINGLE_TONE_TX,
+ MP_PACKET_TX,
+ MP_PACKET_RX
+};
+
+extern u8 mpdatarate[NumRates];
+
+/* MP set force data rate base on the definition. */
+enum mpt_rate_index {
+ /* CCK rate. */
+ MPT_RATE_1M, /* 0 */
+ MPT_RATE_2M,
+ MPT_RATE_55M,
+ MPT_RATE_11M, /* 3 */
+
+ /* OFDM rate. */
+ MPT_RATE_6M, /* 4 */
+ MPT_RATE_9M,
+ MPT_RATE_12M,
+ MPT_RATE_18M,
+ MPT_RATE_24M,
+ MPT_RATE_36M,
+ MPT_RATE_48M,
+ MPT_RATE_54M, /* 11 */
+
+ /* HT rate. */
+ MPT_RATE_MCS0, /* 12 */
+ MPT_RATE_MCS1,
+ MPT_RATE_MCS2,
+ MPT_RATE_MCS3,
+ MPT_RATE_MCS4,
+ MPT_RATE_MCS5,
+ MPT_RATE_MCS6,
+ MPT_RATE_MCS7, /* 19 */
+ MPT_RATE_MCS8,
+ MPT_RATE_MCS9,
+ MPT_RATE_MCS10,
+ MPT_RATE_MCS11,
+ MPT_RATE_MCS12,
+ MPT_RATE_MCS13,
+ MPT_RATE_MCS14,
+ MPT_RATE_MCS15, /* 27 */
+ MPT_RATE_LAST
+};
+
+#define MAX_TX_PWR_INDEX_N_MODE 64 /* 0x3F */
+
+enum power_mode {
+ POWER_LOW = 0,
+ POWER_NORMAL
+};
+
+#define RX_PKT_BROADCAST 1
+#define RX_PKT_DEST_ADDR 2
+#define RX_PKT_PHY_MATCH 3
+
+enum encry_ctrl_state {
+ HW_CONTROL, /* hw encryption& decryption */
+ SW_CONTROL, /* sw encryption& decryption */
+ HW_ENCRY_SW_DECRY, /* hw encryption & sw decryption */
+ SW_ENCRY_HW_DECRY /* sw encryption & hw decryption */
+};
+
+s32 init_mp_priv(struct adapter *padapter);
+void free_mp_priv(struct mp_priv *pmp_priv);
+s32 MPT_InitializeAdapter(struct adapter *padapter, u8 Channel);
+void MPT_DeInitAdapter(struct adapter *padapter);
+s32 mp_start_test(struct adapter *padapter);
+void mp_stop_test(struct adapter *padapter);
+
+u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask);
+void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val);
+
+u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask);
+void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val);
+u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr);
+void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val);
+
+void SetChannel(struct adapter *pAdapter);
+void SetBandwidth(struct adapter *pAdapter);
+void SetTxPower(struct adapter *pAdapter);
+void SetAntennaPathPower(struct adapter *pAdapter);
+void SetDataRate(struct adapter *pAdapter);
+
+void SetAntenna(struct adapter *pAdapter);
+
+s32 SetThermalMeter(struct adapter *pAdapter, u8 target_ther);
+void GetThermalMeter(struct adapter *pAdapter, u8 *value);
+
+void SetContinuousTx(struct adapter *pAdapter, u8 bStart);
+void SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart);
+void SetSingleToneTx(struct adapter *pAdapter, u8 bStart);
+void SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart);
+void PhySetTxPowerLevel(struct adapter *pAdapter);
+
+void fill_txdesc_for_mp(struct adapter *padapter, struct tx_desc *ptxdesc);
+void SetPacketTx(struct adapter *padapter);
+void SetPacketRx(struct adapter *pAdapter, u8 bStartRx);
+
+void ResetPhyRxPktCount(struct adapter *pAdapter);
+u32 GetPhyRxPktReceived(struct adapter *pAdapter);
+u32 GetPhyRxPktCRC32Error(struct adapter *pAdapter);
+
+s32 SetPowerTracking(struct adapter *padapter, u8 enable);
+void GetPowerTracking(struct adapter *padapter, u8 *enable);
+u32 mp_query_psd(struct adapter *pAdapter, u8 *data);
+void Hal_SetAntenna(struct adapter *pAdapter);
+void Hal_SetBandwidth(struct adapter *pAdapter);
+void Hal_SetTxPower(struct adapter *pAdapter);
+void Hal_SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart);
+void Hal_SetSingleToneTx(struct adapter *pAdapter, u8 bStart);
+void Hal_SetSingleCarrierTx (struct adapter *pAdapter, u8 bStart);
+void Hal_SetContinuousTx (struct adapter *pAdapter, u8 bStart);
+void Hal_SetBandwidth(struct adapter *pAdapter);
+void Hal_SetDataRate(struct adapter *pAdapter);
+void Hal_SetChannel(struct adapter *pAdapter);
+void Hal_SetAntennaPathPower(struct adapter *pAdapter);
+s32 Hal_SetThermalMeter(struct adapter *pAdapter, u8 target_ther);
+s32 Hal_SetPowerTracking(struct adapter *padapter, u8 enable);
+void Hal_GetPowerTracking(struct adapter *padapter, u8 * enable);
+void Hal_GetThermalMeter(struct adapter *pAdapter, u8 *value);
+void Hal_mpt_SwitchRfSetting(struct adapter *pAdapter);
+void Hal_MPT_CCKTxPowerAdjust(struct adapter * Adapter, bool bInCH14);
+void Hal_MPT_CCKTxPowerAdjustbyIndex(struct adapter *pAdapter, bool beven);
+void Hal_SetCCKTxPower(struct adapter *pAdapter, u8 * TxPower);
+void Hal_SetOFDMTxPower(struct adapter *pAdapter, u8 * TxPower);
+void Hal_TriggerRFThermalMeter(struct adapter *pAdapter);
+u8 Hal_ReadRFThermalMeter(struct adapter *pAdapter);
+void Hal_SetCCKContinuousTx(struct adapter *pAdapter, u8 bStart);
+void Hal_SetOFDMContinuousTx(struct adapter *pAdapter, u8 bStart);
+void Hal_ProSetCrystalCap (struct adapter *pAdapter , u32 CrystalCapVal);
+void _rtw_mp_xmit_priv(struct xmit_priv *pxmitpriv);
+void MP_PHY_SetRFPathSwitch(struct adapter *pAdapter ,bool bMain);
+
+#endif /* _RTW_MP_H_ */
diff --git a/drivers/staging/r8188eu/include/rtw_mp_ioctl.h b/drivers/staging/r8188eu/include/rtw_mp_ioctl.h
new file mode 100644
index 000000000000..cf99f39a582e
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_mp_ioctl.h
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _RTW_MP_IOCTL_H_
+#define _RTW_MP_IOCTL_H_
+
+#include "drv_types.h"
+#include "mp_custom_oid.h"
+#include "rtw_ioctl.h"
+#include "rtw_ioctl_rtl.h"
+#include "rtw_efuse.h"
+#include "rtw_mp.h"
+
+struct cfg_dbg_msg_struct {
+ u32 DebugLevel;
+ u32 DebugComponent_H32;
+ u32 DebugComponent_L32;
+};
+
+struct mp_rw_reg {
+ u32 offset;
+ u32 width;
+ u32 value;
+};
+
+struct efuse_access_struct {
+ u16 start_addr;
+ u16 cnts;
+ u8 data[0];
+};
+
+struct burst_rw_reg {
+ u32 offset;
+ u32 len;
+ u8 Data[256];
+};
+
+struct usb_vendor_req {
+ u8 bRequest;
+ u16 wValue;
+ u16 wIndex;
+ u16 wLength;
+ u8 u8Dir;/* 0:OUT, 1:IN */
+ u8 u8InData;
+};
+
+struct dr_variable_struct {
+ u8 offset;
+ u32 variable;
+};
+
+#define _irqlevel_changed_(a, b)
+
+int rtl8188eu_oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv);
+
+int rtl8188eu_oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *par_priv);
+int rtl8188eu_oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *par_priv);
+int rtl8188eu_oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *par_priv);
+int rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv);
+
+/* rtl8188eu_oid_rtl_seg_81_87 */
+int rtl8188eu_oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv);
+
+int rtl8188eu_oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv);
+
+/* rtl8188eu_oid_rtl_seg_87_11_00 */
+int rtl8188eu_oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_burst_read_register_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_burst_write_register_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_write16_eeprom_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_wr_attrib_mem_hdl (struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv);
+/* rtl8188eu_oid_rtl_seg_87_11_20 */
+int rtl8188eu_oid_rt_pro_cfg_debug_message_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_data_rate_ex_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_basic_rate_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_read_tssi_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_power_tracking_hdl(struct oid_par_priv *poid_par_priv);
+/* rtl8188eu_oid_rtl_seg_87_11_50 */
+int rtl8188eu_oid_rt_pro_qry_pwrstate_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_pwrstate_hdl(struct oid_par_priv *poid_par_priv);
+/* rtl8188eu_oid_rtl_seg_87_11_F0 */
+int rtl8188eu_oid_rt_pro_h2c_set_rate_table_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_h2c_get_rate_table_hdl(struct oid_par_priv *poid_par_priv);
+
+/* rtl8188eu_oid_rtl_seg_87_12_00 */
+int rtl8188eu_oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_query_dr_variable_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_tx_agc_offset_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_set_pkt_test_mode_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *par_priv);
+int rtl8188eu_oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv);
+int rtl8188eu_oid_rt_pro_trigger_gpio_hdl(struct oid_par_priv *poid_par_priv);
+
+struct rwreg_param {
+ u32 offset;
+ u32 width;
+ u32 value;
+};
+
+struct bbreg_param {
+ u32 offset;
+ u32 phymask;
+ u32 value;
+};
+
+struct txpower_param {
+ u32 pwr_index;
+};
+
+struct datarate_param {
+ u32 rate_index;
+};
+
+struct rfintfs_parm {
+ u32 rfintfs;
+};
+
+struct mp_xmit_parm {
+ u8 enable;
+ u32 count;
+ u16 length;
+ u8 payload_type;
+ u8 da[ETH_ALEN];
+};
+
+struct mp_xmit_packet {
+ u32 len;
+ u32 mem[MAX_MP_XMITBUF_SZ >> 2];
+};
+
+struct psmode_param {
+ u32 ps_mode;
+ u32 smart_ps;
+};
+
+/* for OID_RT_PRO_READ16_EEPROM & OID_RT_PRO_WRITE16_EEPROM */
+struct eeprom_rw_param {
+ u32 offset;
+ u16 value;
+};
+
+struct mp_ioctl_handler {
+ u32 paramsize;
+ s32 (*handler)(struct oid_par_priv* poid_par_priv);
+ u32 oid;
+};
+
+struct mp_ioctl_param{
+ u32 subcode;
+ u32 len;
+ u8 data[0];
+};
+
+#define GEN_MP_IOCTL_SUBCODE(code) _MP_IOCTL_ ## code ## _CMD_
+
+enum RTL871X_MP_IOCTL_SUBCODE {
+ GEN_MP_IOCTL_SUBCODE(MP_START), /*0*/
+ GEN_MP_IOCTL_SUBCODE(MP_STOP),
+ GEN_MP_IOCTL_SUBCODE(READ_REG),
+ GEN_MP_IOCTL_SUBCODE(WRITE_REG),
+ GEN_MP_IOCTL_SUBCODE(READ_BB_REG),
+ GEN_MP_IOCTL_SUBCODE(WRITE_BB_REG), /*5*/
+ GEN_MP_IOCTL_SUBCODE(READ_RF_REG),
+ GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG),
+ GEN_MP_IOCTL_SUBCODE(SET_CHANNEL),
+ GEN_MP_IOCTL_SUBCODE(SET_TXPOWER),
+ GEN_MP_IOCTL_SUBCODE(SET_DATARATE), /*10*/
+ GEN_MP_IOCTL_SUBCODE(SET_BANDWIDTH),
+ GEN_MP_IOCTL_SUBCODE(SET_ANTENNA),
+ GEN_MP_IOCTL_SUBCODE(CNTU_TX),
+ GEN_MP_IOCTL_SUBCODE(SC_TX),
+ GEN_MP_IOCTL_SUBCODE(CS_TX), /*15*/
+ GEN_MP_IOCTL_SUBCODE(ST_TX),
+ GEN_MP_IOCTL_SUBCODE(IOCTL_XMIT_PACKET),
+ GEN_MP_IOCTL_SUBCODE(SET_RX_PKT_TYPE),
+ GEN_MP_IOCTL_SUBCODE(RESET_PHY_RX_PKT_CNT),
+ GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_RECV), /*20*/
+ GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_ERROR),
+ GEN_MP_IOCTL_SUBCODE(READ16_EEPROM),
+ GEN_MP_IOCTL_SUBCODE(WRITE16_EEPROM),
+ GEN_MP_IOCTL_SUBCODE(EFUSE),
+ GEN_MP_IOCTL_SUBCODE(EFUSE_MAP), /*25*/
+ GEN_MP_IOCTL_SUBCODE(GET_EFUSE_MAX_SIZE),
+ GEN_MP_IOCTL_SUBCODE(GET_EFUSE_CURRENT_SIZE),
+ GEN_MP_IOCTL_SUBCODE(GET_THERMAL_METER),
+ GEN_MP_IOCTL_SUBCODE(SET_PTM),
+ GEN_MP_IOCTL_SUBCODE(SET_POWER_DOWN), /*30*/
+ GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO),
+ GEN_MP_IOCTL_SUBCODE(SET_DM_BT), /*35*/
+ GEN_MP_IOCTL_SUBCODE(DEL_BA), /*36*/
+ GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS), /*37*/
+ MAX_MP_IOCTL_SUBCODE,
+};
+
+s32 rtl8188eu_mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv);
+
+#define GEN_HANDLER(sz, hdl, oid) {sz, hdl, oid},
+
+#define EXT_MP_IOCTL_HANDLER(sz, subcode, oid) \
+ {sz, rtl8188eu_mp_ioctl_##subcode##_hdl, oid},
+
+#endif
diff --git a/drivers/staging/r8188eu/include/rtw_mp_phy_regdef.h b/drivers/staging/r8188eu/include/rtw_mp_phy_regdef.h
new file mode 100644
index 000000000000..c2be770a5f5d
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_mp_phy_regdef.h
@@ -0,0 +1,1063 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+/*****************************************************************************
+ *
+ * Module: __RTW_MP_PHY_REGDEF_H_
+ *
+ *
+ * Note: 1. Define PMAC/BB register map
+ * 2. Define RF register map
+ * 3. PMAC/BB register bit mask.
+ * 4. RF reg bit mask.
+ * 5. Other BB/RF relative definition.
+ *
+ *
+ * Export: Constants, macro, functions(API), global variables(None).
+ *
+ * Abbrev:
+ *
+ * History:
+ * Data Who Remark
+ * 08/07/2007 MHC 1. Porting from 9x series PHYCFG.h.
+ * 2. Reorganize code architecture.
+ * 09/25/2008 MH 1. Add RL6052 register definition
+ *
+ *****************************************************************************/
+#ifndef __RTW_MP_PHY_REGDEF_H_
+#define __RTW_MP_PHY_REGDEF_H_
+
+/*--------------------------Define Parameters-------------------------------*/
+
+/* */
+/* 8192S Regsiter offset definition */
+/* */
+
+/* */
+/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */
+/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */
+/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
+/* 3. RF register 0x00-2E */
+/* 4. Bit Mask for BB/RF register */
+/* 5. Other definition for BB/RF R/W */
+/* */
+
+/* */
+/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */
+/* 1. Page1(0x100) */
+/* */
+#define rPMAC_Reset 0x100
+#define rPMAC_TxStart 0x104
+#define rPMAC_TxLegacySIG 0x108
+#define rPMAC_TxHTSIG1 0x10c
+#define rPMAC_TxHTSIG2 0x110
+#define rPMAC_PHYDebug 0x114
+#define rPMAC_TxPacketNum 0x118
+#define rPMAC_TxIdle 0x11c
+#define rPMAC_TxMACHeader0 0x120
+#define rPMAC_TxMACHeader1 0x124
+#define rPMAC_TxMACHeader2 0x128
+#define rPMAC_TxMACHeader3 0x12c
+#define rPMAC_TxMACHeader4 0x130
+#define rPMAC_TxMACHeader5 0x134
+#define rPMAC_TxDataType 0x138
+#define rPMAC_TxRandomSeed 0x13c
+#define rPMAC_CCKPLCPPreamble 0x140
+#define rPMAC_CCKPLCPHeader 0x144
+#define rPMAC_CCKCRC16 0x148
+#define rPMAC_OFDMRxCRC32OK 0x170
+#define rPMAC_OFDMRxCRC32Er 0x174
+#define rPMAC_OFDMRxParityEr 0x178
+#define rPMAC_OFDMRxCRC8Er 0x17c
+#define rPMAC_CCKCRxRC16Er 0x180
+#define rPMAC_CCKCRxRC32Er 0x184
+#define rPMAC_CCKCRxRC32OK 0x188
+#define rPMAC_TxStatus 0x18c
+
+/* */
+/* 2. Page2(0x200) */
+/* */
+/* The following two definition are only used for USB interface. */
+/* define RF_BB_CMD_ADDR 0x02c0 RF/BB read/write command address. */
+/* define RF_BB_CMD_DATA 0x02c4 RF/BB read/write command data. */
+
+/* */
+/* 3. Page8(0x800) */
+/* */
+#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting?? */
+
+#define rFPGA0_TxInfo 0x804 /* Status report?? */
+#define rFPGA0_PSDFunction 0x808
+
+#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */
+
+#define rFPGA0_RFTiming1 0x810 /* Useless now */
+#define rFPGA0_RFTiming2 0x814
+/* define rFPGA0_XC_RFTiming 0x818 */
+/* define rFPGA0_XD_RFTiming 0x81c */
+
+#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */
+#define rFPGA0_XA_HSSIParameter2 0x824
+#define rFPGA0_XB_HSSIParameter1 0x828
+#define rFPGA0_XB_HSSIParameter2 0x82c
+#define rFPGA0_XC_HSSIParameter1 0x830
+#define rFPGA0_XC_HSSIParameter2 0x834
+#define rFPGA0_XD_HSSIParameter1 0x838
+#define rFPGA0_XD_HSSIParameter2 0x83c
+#define rFPGA0_XA_LSSIParameter 0x840
+#define rFPGA0_XB_LSSIParameter 0x844
+#define rFPGA0_XC_LSSIParameter 0x848
+#define rFPGA0_XD_LSSIParameter 0x84c
+
+#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */
+#define rFPGA0_RFSleepUpParameter 0x854
+
+#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */
+#define rFPGA0_XCD_SwitchControl 0x85c
+
+#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */
+#define rFPGA0_XB_RFInterfaceOE 0x864
+#define rFPGA0_XC_RFInterfaceOE 0x868
+#define rFPGA0_XD_RFInterfaceOE 0x86c
+
+#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Control */
+#define rFPGA0_XCD_RFInterfaceSW 0x874
+
+#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */
+#define rFPGA0_XCD_RFParameter 0x87c
+
+#define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting RF-R/W protection for parameter4?? */
+#define rFPGA0_AnalogParameter2 0x884
+#define rFPGA0_AnalogParameter3 0x888 /* Useless now */
+#define rFPGA0_AnalogParameter4 0x88c
+
+#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */
+#define rFPGA0_XB_LSSIReadBack 0x8a4
+#define rFPGA0_XC_LSSIReadBack 0x8a8
+#define rFPGA0_XD_LSSIReadBack 0x8ac
+
+#define rFPGA0_PSDReport 0x8b4 /* Useless now */
+#define rFPGA0_XAB_RFInterfaceRB 0x8e0 /* Useless now RF Interface Readback Value */
+#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */
+
+/* */
+/* 4. Page9(0x900) */
+/* */
+#define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC RF BW Setting?? */
+
+#define rFPGA1_TxBlock 0x904 /* Useless now */
+#define rFPGA1_DebugSelect 0x908 /* Useless now */
+#define rFPGA1_TxInfo 0x90c /* Useless now Status report?? */
+
+/* */
+/* 5. PageA(0xA00) */
+/* */
+/* Set Control channel to upper or lower. These settings are required only for 40MHz */
+#define rCCK0_System 0xa00
+
+#define rCCK0_AFESetting 0xa04 /* Disable init gain now Select RX path by RSSI */
+#define rCCK0_CCA 0xa08 /* Disable init gain now Init gain */
+
+#define rCCK0_RxAGC1 0xa0c /* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. Not the same as 90 series */
+#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */
+
+#define rCCK0_RxHP 0xa14
+
+#define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel estimation threshold */
+#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */
+
+#define rCCK0_TxFilter1 0xa20
+#define rCCK0_TxFilter2 0xa24
+#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */
+#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now 0xa30-a4f channel report */
+#define rCCK0_TRSSIReport 0xa50
+#define rCCK0_RxReport 0xa54 /* 0xa57 */
+#define rCCK0_FACounterLower 0xa5c /* 0xa5b */
+#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */
+
+/* */
+/* 6. PageC(0xC00) */
+/* */
+#define rOFDM0_LSTF 0xc00
+
+#define rOFDM0_TRxPathEnable 0xc04
+#define rOFDM0_TRMuxPar 0xc08
+#define rOFDM0_TRSWIsolation 0xc0c
+
+#define rOFDM0_XARxAFE 0xc10 /* RxIQ DC offset, Rx digital filter, DC notch filter */
+#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imblance matrix */
+#define rOFDM0_XBRxAFE 0xc18
+#define rOFDM0_XBRxIQImbalance 0xc1c
+#define rOFDM0_XCRxAFE 0xc20
+#define rOFDM0_XCRxIQImbalance 0xc24
+#define rOFDM0_XDRxAFE 0xc28
+#define rOFDM0_XDRxIQImbalance 0xc2c
+
+#define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD DM tune init gain */
+#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */
+#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */
+#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */
+
+#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */
+#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */
+#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */
+#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */
+
+#define rOFDM0_XAAGCCore1 0xc50 /* DIG */
+#define rOFDM0_XAAGCCore2 0xc54
+#define rOFDM0_XBAGCCore1 0xc58
+#define rOFDM0_XBAGCCore2 0xc5c
+#define rOFDM0_XCAGCCore1 0xc60
+#define rOFDM0_XCAGCCore2 0xc64
+#define rOFDM0_XDAGCCore1 0xc68
+#define rOFDM0_XDAGCCore2 0xc6c
+
+#define rOFDM0_AGCParameter1 0xc70
+#define rOFDM0_AGCParameter2 0xc74
+#define rOFDM0_AGCRSSITable 0xc78
+#define rOFDM0_HTSTFAGC 0xc7c
+
+#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */
+#define rOFDM0_XATxAFE 0xc84
+#define rOFDM0_XBTxIQImbalance 0xc88
+#define rOFDM0_XBTxAFE 0xc8c
+#define rOFDM0_XCTxIQImbalance 0xc90
+#define rOFDM0_XCTxAFE 0xc94
+#define rOFDM0_XDTxIQImbalance 0xc98
+#define rOFDM0_XDTxAFE 0xc9c
+#define rOFDM0_RxIQExtAnta 0xca0
+
+#define rOFDM0_RxHPParameter 0xce0
+#define rOFDM0_TxPseudoNoiseWgt 0xce4
+#define rOFDM0_FrameSync 0xcf0
+#define rOFDM0_DFSReport 0xcf4
+#define rOFDM0_TxCoeff1 0xca4
+#define rOFDM0_TxCoeff2 0xca8
+#define rOFDM0_TxCoeff3 0xcac
+#define rOFDM0_TxCoeff4 0xcb0
+#define rOFDM0_TxCoeff5 0xcb4
+#define rOFDM0_TxCoeff6 0xcb8
+
+/* 7. PageD(0xD00) */
+#define rOFDM1_LSTF 0xd00
+#define rOFDM1_TRxPathEnable 0xd04
+
+#define rOFDM1_CFO 0xd08 /* No setting now */
+#define rOFDM1_CSI1 0xd10
+#define rOFDM1_SBD 0xd14
+#define rOFDM1_CSI2 0xd18
+#define rOFDM1_CFOTracking 0xd2c
+#define rOFDM1_TRxMesaure1 0xd34
+#define rOFDM1_IntfDet 0xd3c
+#define rOFDM1_PseudoNoiseStateAB 0xd50
+#define rOFDM1_PseudoNoiseStateCD 0xd54
+#define rOFDM1_RxPseudoNoiseWgt 0xd58
+
+#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */
+#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */
+#define rOFDM_PHYCounter3 0xda8 /* MCS not support */
+
+#define rOFDM_ShortCFOAB 0xdac /* No setting now */
+#define rOFDM_ShortCFOCD 0xdb0
+#define rOFDM_LongCFOAB 0xdb4
+#define rOFDM_LongCFOCD 0xdb8
+#define rOFDM_TailCFOAB 0xdbc
+#define rOFDM_TailCFOCD 0xdc0
+#define rOFDM_PWMeasure1 0xdc4
+#define rOFDM_PWMeasure2 0xdc8
+#define rOFDM_BWReport 0xdcc
+#define rOFDM_AGCReport 0xdd0
+#define rOFDM_RxSNR 0xdd4
+#define rOFDM_RxEVMCSI 0xdd8
+#define rOFDM_SIGReport 0xddc
+
+/* */
+/* 8. PageE(0xE00) */
+/* */
+#define rTxAGC_Rate18_06 0xe00
+#define rTxAGC_Rate54_24 0xe04
+#define rTxAGC_CCK_Mcs32 0xe08
+#define rTxAGC_Mcs03_Mcs00 0xe10
+#define rTxAGC_Mcs07_Mcs04 0xe14
+#define rTxAGC_Mcs11_Mcs08 0xe18
+#define rTxAGC_Mcs15_Mcs12 0xe1c
+
+/* Analog- control in RX_WAIT_CCA : REG: EE0 [Analog- Power & Control Register] */
+#define rRx_Wait_CCCA 0xe70
+#define rAnapar_Ctrl_BB 0xee0
+
+/* */
+/* 7. RF Register 0x00-0x2E (RF 8256) */
+/* RF-0222D 0x00-3F */
+/* */
+/* Zebra1 */
+#define RTL92SE_FPGA_VERIFY 0
+#define rZebra1_HSSIEnable 0x0 /* Useless now */
+#define rZebra1_TRxEnable1 0x1
+#define rZebra1_TRxEnable2 0x2
+#define rZebra1_AGC 0x4
+#define rZebra1_ChargePump 0x5
+/* if (RTL92SE_FPGA_VERIFY == 1) */
+#define rZebra1_Channel 0x7 /* RF channel switch */
+/* else */
+
+/* endif */
+#define rZebra1_TxGain 0x8 /* Useless now */
+#define rZebra1_TxLPF 0x9
+#define rZebra1_RxLPF 0xb
+#define rZebra1_RxHPFCorner 0xc
+
+/* Zebra4 */
+#define rGlobalCtrl 0 /* Useless now */
+#define rRTL8256_TxLPF 19
+#define rRTL8256_RxLPF 11
+
+/* RTL8258 */
+#define rRTL8258_TxLPF 0x11 /* Useless now */
+#define rRTL8258_RxLPF 0x13
+#define rRTL8258_RSSILPF 0xa
+
+/* */
+/* RL6052 Register definition */
+#define RF_AC 0x00 /* */
+
+#define RF_IQADJ_G1 0x01 /* */
+#define RF_IQADJ_G2 0x02 /* */
+#define RF_POW_TRSW 0x05 /* */
+
+#define RF_GAIN_RX 0x06 /* */
+#define RF_GAIN_TX 0x07 /* */
+
+#define RF_TXM_IDAC 0x08 /* */
+#define RF_BS_IQGEN 0x0F /* */
+
+#define RF_MODE1 0x10 /* */
+#define RF_MODE2 0x11 /* */
+
+#define RF_RX_AGC_HP 0x12 /* */
+#define RF_TX_AGC 0x13 /* */
+#define RF_BIAS 0x14 /* */
+#define RF_IPA 0x15 /* */
+#define RF_TXBIAS 0x16 /* */
+#define RF_POW_ABILITY 0x17 /* */
+#define RF_MODE_AG 0x18 /* */
+#define rRfChannel 0x18 /* RF channel and BW switch */
+#define RF_CHNLBW 0x18 /* RF channel and BW switch */
+#define RF_TOP 0x19 /* */
+
+#define RF_RX_G1 0x1A /* */
+#define RF_RX_G2 0x1B /* */
+
+#define RF_RX_BB2 0x1C /* */
+#define RF_RX_BB1 0x1D /* */
+
+#define RF_RCK1 0x1E /* */
+#define RF_RCK2 0x1F /* */
+
+#define RF_TX_G1 0x20 /* */
+#define RF_TX_G2 0x21 /* */
+#define RF_TX_G3 0x22 /* */
+
+#define RF_TX_BB1 0x23 /* */
+
+#define RF_T_METER 0x24 /* */
+
+#define RF_SYN_G1 0x25 /* RF TX Power control */
+#define RF_SYN_G2 0x26 /* RF TX Power control */
+#define RF_SYN_G3 0x27 /* RF TX Power control */
+#define RF_SYN_G4 0x28 /* RF TX Power control */
+#define RF_SYN_G5 0x29 /* RF TX Power control */
+#define RF_SYN_G6 0x2A /* RF TX Power control */
+#define RF_SYN_G7 0x2B /* RF TX Power control */
+#define RF_SYN_G8 0x2C /* RF TX Power control */
+
+#define RF_RCK_OS 0x30 /* RF TX PA control */
+#define RF_TXPA_G1 0x31 /* RF TX PA control */
+#define RF_TXPA_G2 0x32 /* RF TX PA control */
+#define RF_TXPA_G3 0x33 /* RF TX PA control */
+
+/* */
+/* Bit Mask */
+/* */
+/* 1. Page1(0x100) */
+#define bBBResetB 0x100 /* Useless now? */
+#define bGlobalResetB 0x200
+#define bOFDMTxStart 0x4
+#define bCCKTxStart 0x8
+#define bCRC32Debug 0x100
+#define bPMACLoopback 0x10
+#define bTxLSIG 0xffffff
+#define bOFDMTxRate 0xf
+#define bOFDMTxReserved 0x10
+#define bOFDMTxLength 0x1ffe0
+#define bOFDMTxParity 0x20000
+#define bTxHTSIG1 0xffffff
+#define bTxHTMCSRate 0x7f
+#define bTxHTBW 0x80
+#define bTxHTLength 0xffff00
+#define bTxHTSIG2 0xffffff
+#define bTxHTSmoothing 0x1
+#define bTxHTSounding 0x2
+#define bTxHTReserved 0x4
+#define bTxHTAggreation 0x8
+#define bTxHTSTBC 0x30
+#define bTxHTAdvanceCoding 0x40
+#define bTxHTShortGI 0x80
+#define bTxHTNumberHT_LTF 0x300
+#define bTxHTCRC8 0x3fc00
+#define bCounterReset 0x10000
+#define bNumOfOFDMTx 0xffff
+#define bNumOfCCKTx 0xffff0000
+#define bTxIdleInterval 0xffff
+#define bOFDMService 0xffff0000
+#define bTxMACHeader 0xffffffff
+#define bTxDataInit 0xff
+#define bTxHTMode 0x100
+#define bTxDataType 0x30000
+#define bTxRandomSeed 0xffffffff
+#define bCCKTxPreamble 0x1
+#define bCCKTxSFD 0xffff0000
+#define bCCKTxSIG 0xff
+#define bCCKTxService 0xff00
+#define bCCKLengthExt 0x8000
+#define bCCKTxLength 0xffff0000
+#define bCCKTxCRC16 0xffff
+#define bCCKTxStatus 0x1
+#define bOFDMTxStatus 0x2
+
+#define IS_BB_REG_OFFSET_92S(_Offset) ((_Offset >= 0x800) && (_Offset <= 0xfff))
+
+/* 2. Page8(0x800) */
+#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */
+#define bJapanMode 0x2
+#define bCCKTxSC 0x30
+#define bCCKEn 0x1000000
+#define bOFDMEn 0x2000000
+
+#define bOFDMRxADCPhase 0x10000 /* Useless now */
+#define bOFDMTxDACPhase 0x40000
+#define bXATxAGC 0x3f
+
+#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */
+#define bXCTxAGC 0xf000
+#define bXDTxAGC 0xf0000
+
+#define bPAStart 0xf0000000 /* Useless now */
+#define bTRStart 0x00f00000
+#define bRFStart 0x0000f000
+#define bBBStart 0x000000f0
+#define bBBCCKStart 0x0000000f
+#define bPAEnd 0xf /* Reg0x814 */
+#define bTREnd 0x0f000000
+#define bRFEnd 0x000f0000
+#define bCCAMask 0x000000f0 /* T2R */
+#define bR2RCCAMask 0x00000f00
+#define bHSSI_R2TDelay 0xf8000000
+#define bHSSI_T2RDelay 0xf80000
+#define bContTxHSSI 0x400 /* chane gain at continue Tx */
+#define bIGFromCCK 0x200
+#define bAGCAddress 0x3f
+#define bRxHPTx 0x7000
+#define bRxHPT2R 0x38000
+#define bRxHPCCKIni 0xc0000
+#define bAGCTxCode 0xc00000
+#define bAGCRxCode 0x300000
+
+#define b3WireDataLength 0x800 /* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */
+#define b3WireAddressLength 0x400
+
+#define b3WireRFPowerDown 0x1 /* Useless now */
+/* define bHWSISelect 0x8 */
+#define b5GPAPEPolarity 0x40000000
+#define b2GPAPEPolarity 0x80000000
+#define bRFSW_TxDefaultAnt 0x3
+#define bRFSW_TxOptionAnt 0x30
+#define bRFSW_RxDefaultAnt 0x300
+#define bRFSW_RxOptionAnt 0x3000
+#define bRFSI_3WireData 0x1
+#define bRFSI_3WireClock 0x2
+#define bRFSI_3WireLoad 0x4
+#define bRFSI_3WireRW 0x8
+#define bRFSI_3Wire 0xf
+
+#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */
+
+#define bRFSI_TRSW 0x20 /* Useless now */
+#define bRFSI_TRSWB 0x40
+#define bRFSI_ANTSW 0x100
+#define bRFSI_ANTSWB 0x200
+#define bRFSI_PAPE 0x400
+#define bRFSI_PAPE5G 0x800
+#define bBandSelect 0x1
+#define bHTSIG2_GI 0x80
+#define bHTSIG2_Smoothing 0x01
+#define bHTSIG2_Sounding 0x02
+#define bHTSIG2_Aggreaton 0x08
+#define bHTSIG2_STBC 0x30
+#define bHTSIG2_AdvCoding 0x40
+#define bHTSIG2_NumOfHTLTF 0x300
+#define bHTSIG2_CRC8 0x3fc
+#define bHTSIG1_MCS 0x7f
+#define bHTSIG1_BandWidth 0x80
+#define bHTSIG1_HTLength 0xffff
+#define bLSIG_Rate 0xf
+#define bLSIG_Reserved 0x10
+#define bLSIG_Length 0x1fffe
+#define bLSIG_Parity 0x20
+#define bCCKRxPhase 0x4
+#if (RTL92SE_FPGA_VERIFY == 1)
+#define bLSSIReadAddress 0x3f000000 /* LSSI "Read" Address
+ Reg 0x824 rFPGA0_XA_HSSIParameter2 */
+#else
+#define bLSSIReadAddress 0x7f800000 /* T65 RF */
+#endif
+#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */
+#if (RTL92SE_FPGA_VERIFY == 1)
+#define bLSSIReadBackData 0xfff /* Reg 0x8a0
+ rFPGA0_XA_LSSIReadBack */
+#else
+#define bLSSIReadBackData 0xfffff /* T65 RF */
+#endif
+#define bLSSIReadOKFlag 0x1000 /* Useless now */
+#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */
+#define bRegulator0Standby 0x1
+#define bRegulatorPLLStandby 0x2
+#define bRegulator1Standby 0x4
+#define bPLLPowerUp 0x8
+#define bDPLLPowerUp 0x10
+#define bDA10PowerUp 0x20
+#define bAD7PowerUp 0x200
+#define bDA6PowerUp 0x2000
+#define bXtalPowerUp 0x4000
+#define b40MDClkPowerUP 0x8000
+#define bDA6DebugMode 0x20000
+#define bDA6Swing 0x380000
+
+#define bADClkPhase 0x4000000 /* Reg 0x880
+ rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */
+
+#define b80MClkDelay 0x18000000 /* Useless */
+#define bAFEWatchDogEnable 0x20000000
+
+#define bXtalCap01 0xc0000000 /* Reg 0x884
+ rFPGA0_AnalogParameter2 Crystal cap */
+#define bXtalCap23 0x3
+#define bXtalCap92x 0x0f000000
+#define bXtalCap 0x0f000000
+
+#define bIntDifClkEnable 0x400 /* Useless */
+#define bExtSigClkEnable 0x800
+#define bBandgapMbiasPowerUp 0x10000
+#define bAD11SHGain 0xc0000
+#define bAD11InputRange 0x700000
+#define bAD11OPCurrent 0x3800000
+#define bIPathLoopback 0x4000000
+#define bQPathLoopback 0x8000000
+#define bAFELoopback 0x10000000
+#define bDA10Swing 0x7e0
+#define bDA10Reverse 0x800
+#define bDAClkSource 0x1000
+#define bAD7InputRange 0x6000
+#define bAD7Gain 0x38000
+#define bAD7OutputCMMode 0x40000
+#define bAD7InputCMMode 0x380000
+#define bAD7Current 0xc00000
+#define bRegulatorAdjust 0x7000000
+#define bAD11PowerUpAtTx 0x1
+#define bDA10PSAtTx 0x10
+#define bAD11PowerUpAtRx 0x100
+#define bDA10PSAtRx 0x1000
+#define bCCKRxAGCFormat 0x200
+#define bPSDFFTSamplepPoint 0xc000
+#define bPSDAverageNum 0x3000
+#define bIQPathControl 0xc00
+#define bPSDFreq 0x3ff
+#define bPSDAntennaPath 0x30
+#define bPSDIQSwitch 0x40
+#define bPSDRxTrigger 0x400000
+#define bPSDTxTrigger 0x80000000
+#define bPSDSineToneScale 0x7f000000
+#define bPSDReport 0xffff
+
+/* 3. Page9(0x900) */
+#define bOFDMTxSC 0x30000000 /* Useless */
+#define bCCKTxOn 0x1
+#define bOFDMTxOn 0x2
+#define bDebugPage 0xfff /* reset debug page and HWord,
+ * LWord */
+#define bDebugItem 0xff /* reset debug page and LWord */
+#define bAntL 0x10
+#define bAntNonHT 0x100
+#define bAntHT1 0x1000
+#define bAntHT2 0x10000
+#define bAntHT1S1 0x100000
+#define bAntNonHTS1 0x1000000
+
+/* 4. PageA(0xA00) */
+#define bCCKBBMode 0x3 /* Useless */
+#define bCCKTxPowerSaving 0x80
+#define bCCKRxPowerSaving 0x40
+
+#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0 20/40 sw */
+
+#define bCCKScramble 0x8 /* Useless */
+#define bCCKAntDiversity 0x8000
+#define bCCKCarrierRecovery 0x4000
+#define bCCKTxRate 0x3000
+#define bCCKDCCancel 0x0800
+#define bCCKISICancel 0x0400
+#define bCCKMatchFilter 0x0200
+#define bCCKEqualizer 0x0100
+#define bCCKPreambleDetect 0x800000
+#define bCCKFastFalseCCA 0x400000
+#define bCCKChEstStart 0x300000
+#define bCCKCCACount 0x080000
+#define bCCKcs_lim 0x070000
+#define bCCKBistMode 0x80000000
+#define bCCKCCAMask 0x40000000
+#define bCCKTxDACPhase 0x4
+#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */
+#define bCCKr_cp_mode0 0x0100
+#define bCCKTxDCOffset 0xf0
+#define bCCKRxDCOffset 0xf
+#define bCCKCCAMode 0xc000
+#define bCCKFalseCS_lim 0x3f00
+#define bCCKCS_ratio 0xc00000
+#define bCCKCorgBit_sel 0x300000
+#define bCCKPD_lim 0x0f0000
+#define bCCKNewCCA 0x80000000
+#define bCCKRxHPofIG 0x8000
+#define bCCKRxIG 0x7f00
+#define bCCKLNAPolarity 0x800000
+#define bCCKRx1stGain 0x7f0000
+#define bCCKRFExtend 0x20000000 /* CCK Rx init gain polar */
+#define bCCKRxAGCSatLevel 0x1f000000
+#define bCCKRxAGCSatCount 0xe0
+#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */
+#define bCCKFixedRxAGC 0x8000
+#define bCCKAntennaPolarity 0x2000
+#define bCCKTxFilterType 0x0c00
+#define bCCKRxAGCReportType 0x0300
+#define bCCKRxDAGCEn 0x80000000
+#define bCCKRxDAGCPeriod 0x20000000
+#define bCCKRxDAGCSatLevel 0x1f000000
+#define bCCKTimingRecovery 0x800000
+#define bCCKTxC0 0x3f0000
+#define bCCKTxC1 0x3f000000
+#define bCCKTxC2 0x3f
+#define bCCKTxC3 0x3f00
+#define bCCKTxC4 0x3f0000
+#define bCCKTxC5 0x3f000000
+#define bCCKTxC6 0x3f
+#define bCCKTxC7 0x3f00
+#define bCCKDebugPort 0xff0000
+#define bCCKDACDebug 0x0f000000
+#define bCCKFalseAlarmEnable 0x8000
+#define bCCKFalseAlarmRead 0x4000
+#define bCCKTRSSI 0x7f
+#define bCCKRxAGCReport 0xfe
+#define bCCKRxReport_AntSel 0x80000000
+#define bCCKRxReport_MFOff 0x40000000
+#define bCCKRxRxReport_SQLoss 0x20000000
+#define bCCKRxReport_Pktloss 0x10000000
+#define bCCKRxReport_Lockedbit 0x08000000
+#define bCCKRxReport_RateError 0x04000000
+#define bCCKRxReport_RxRate 0x03000000
+#define bCCKRxFACounterLower 0xff
+#define bCCKRxFACounterUpper 0xff000000
+#define bCCKRxHPAGCStart 0xe000
+#define bCCKRxHPAGCFinal 0x1c00
+#define bCCKRxFalseAlarmEnable 0x8000
+#define bCCKFACounterFreeze 0x4000
+#define bCCKTxPathSel 0x10000000
+#define bCCKDefaultRxPath 0xc000000
+#define bCCKOptionRxPath 0x3000000
+
+/* 5. PageC(0xC00) */
+#define bNumOfSTF 0x3 /* Useless */
+#define bShift_L 0xc0
+#define bGI_TH 0xc
+#define bRxPathA 0x1
+#define bRxPathB 0x2
+#define bRxPathC 0x4
+#define bRxPathD 0x8
+#define bTxPathA 0x1
+#define bTxPathB 0x2
+#define bTxPathC 0x4
+#define bTxPathD 0x8
+#define bTRSSIFreq 0x200
+#define bADCBackoff 0x3000
+#define bDFIRBackoff 0xc000
+#define bTRSSILatchPhase 0x10000
+#define bRxIDCOffset 0xff
+#define bRxQDCOffset 0xff00
+#define bRxDFIRMode 0x1800000
+#define bRxDCNFType 0xe000000
+#define bRXIQImb_A 0x3ff
+#define bRXIQImb_B 0xfc00
+#define bRXIQImb_C 0x3f0000
+#define bRXIQImb_D 0xffc00000
+#define bDC_dc_Notch 0x60000
+#define bRxNBINotch 0x1f000000
+#define bPD_TH 0xf
+#define bPD_TH_Opt2 0xc000
+#define bPWED_TH 0x700
+#define bIfMF_Win_L 0x800
+#define bPD_Option 0x1000
+#define bMF_Win_L 0xe000
+#define bBW_Search_L 0x30000
+#define bwin_enh_L 0xc0000
+#define bBW_TH 0x700000
+#define bED_TH2 0x3800000
+#define bBW_option 0x4000000
+#define bRatio_TH 0x18000000
+#define bWindow_L 0xe0000000
+#define bSBD_Option 0x1
+#define bFrame_TH 0x1c
+#define bFS_Option 0x60
+#define bDC_Slope_check 0x80
+#define bFGuard_Counter_DC_L 0xe00
+#define bFrame_Weight_Short 0x7000
+#define bSub_Tune 0xe00000
+#define bFrame_DC_Length 0xe000000
+#define bSBD_start_offset 0x30000000
+#define bFrame_TH_2 0x7
+#define bFrame_GI2_TH 0x38
+#define bGI2_Sync_en 0x40
+#define bSarch_Short_Early 0x300
+#define bSarch_Short_Late 0xc00
+#define bSarch_GI2_Late 0x70000
+#define bCFOAntSum 0x1
+#define bCFOAcc 0x2
+#define bCFOStartOffset 0xc
+#define bCFOLookBack 0x70
+#define bCFOSumWeight 0x80
+#define bDAGCEnable 0x10000
+#define bTXIQImb_A 0x3ff
+#define bTXIQImb_B 0xfc00
+#define bTXIQImb_C 0x3f0000
+#define bTXIQImb_D 0xffc00000
+#define bTxIDCOffset 0xff
+#define bTxQDCOffset 0xff00
+#define bTxDFIRMode 0x10000
+#define bTxPesudoNoiseOn 0x4000000
+#define bTxPesudoNoise_A 0xff
+#define bTxPesudoNoise_B 0xff00
+#define bTxPesudoNoise_C 0xff0000
+#define bTxPesudoNoise_D 0xff000000
+#define bCCADropOption 0x20000
+#define bCCADropThres 0xfff00000
+#define bEDCCA_H 0xf
+#define bEDCCA_L 0xf0
+#define bLambda_ED 0x300
+#define bRxInitialGain 0x7f
+#define bRxAntDivEn 0x80
+#define bRxAGCAddressForLNA 0x7f00
+#define bRxHighPowerFlow 0x8000
+#define bRxAGCFreezeThres 0xc0000
+#define bRxFreezeStep_AGC1 0x300000
+#define bRxFreezeStep_AGC2 0xc00000
+#define bRxFreezeStep_AGC3 0x3000000
+#define bRxFreezeStep_AGC0 0xc000000
+#define bRxRssi_Cmp_En 0x10000000
+#define bRxQuickAGCEn 0x20000000
+#define bRxAGCFreezeThresMode 0x40000000
+#define bRxOverFlowCheckType 0x80000000
+#define bRxAGCShift 0x7f
+#define bTRSW_Tri_Only 0x80
+#define bPowerThres 0x300
+#define bRxAGCEn 0x1
+#define bRxAGCTogetherEn 0x2
+#define bRxAGCMin 0x4
+#define bRxHP_Ini 0x7
+#define bRxHP_TRLNA 0x70
+#define bRxHP_RSSI 0x700
+#define bRxHP_BBP1 0x7000
+#define bRxHP_BBP2 0x70000
+#define bRxHP_BBP3 0x700000
+#define bRSSI_H 0x7f0000 /* thresh for hi power */
+#define bRSSI_Gen 0x7f000000 /* thresh for ant div */
+#define bRxSettle_TRSW 0x7
+#define bRxSettle_LNA 0x38
+#define bRxSettle_RSSI 0x1c0
+#define bRxSettle_BBP 0xe00
+#define bRxSettle_RxHP 0x7000
+#define bRxSettle_AntSW_RSSI 0x38000
+#define bRxSettle_AntSW 0xc0000
+#define bRxProcessTime_DAGC 0x300000
+#define bRxSettle_HSSI 0x400000
+#define bRxProcessTime_BBPPW 0x800000
+#define bRxAntennaPowerShift 0x3000000
+#define bRSSITableSelect 0xc000000
+#define bRxHP_Final 0x7000000
+#define bRxHTSettle_BBP 0x7
+#define bRxHTSettle_HSSI 0x8
+#define bRxHTSettle_RxHP 0x70
+#define bRxHTSettle_BBPPW 0x80
+#define bRxHTSettle_Idle 0x300
+#define bRxHTSettle_Reserved 0x1c00
+#define bRxHTRxHPEn 0x8000
+#define bRxHTAGCFreezeThres 0x30000
+#define bRxHTAGCTogetherEn 0x40000
+#define bRxHTAGCMin 0x80000
+#define bRxHTAGCEn 0x100000
+#define bRxHTDAGCEn 0x200000
+#define bRxHTRxHP_BBP 0x1c00000
+#define bRxHTRxHP_Final 0xe0000000
+#define bRxPWRatioTH 0x3
+#define bRxPWRatioEn 0x4
+#define bRxMFHold 0x3800
+#define bRxPD_Delay_TH1 0x38
+#define bRxPD_Delay_TH2 0x1c0
+#define bRxPD_DC_COUNT_MAX 0x600
+/* define bRxMF_Hold 0x3800 */
+#define bRxPD_Delay_TH 0x8000
+#define bRxProcess_Delay 0xf0000
+#define bRxSearchrange_GI2_Early 0x700000
+#define bRxFrame_Guard_Counter_L 0x3800000
+#define bRxSGI_Guard_L 0xc000000
+#define bRxSGI_Search_L 0x30000000
+#define bRxSGI_TH 0xc0000000
+#define bDFSCnt0 0xff
+#define bDFSCnt1 0xff00
+#define bDFSFlag 0xf0000
+#define bMFWeightSum 0x300000
+#define bMinIdxTH 0x7f000000
+#define bDAFormat 0x40000
+#define bTxChEmuEnable 0x01000000
+#define bTRSWIsolation_A 0x7f
+#define bTRSWIsolation_B 0x7f00
+#define bTRSWIsolation_C 0x7f0000
+#define bTRSWIsolation_D 0x7f000000
+#define bExtLNAGain 0x7c00
+
+/* 6. PageE(0xE00) */
+#define bSTBCEn 0x4 /* Useless */
+#define bAntennaMapping 0x10
+#define bNss 0x20
+#define bCFOAntSumD 0x200
+#define bPHYCounterReset 0x8000000
+#define bCFOReportGet 0x4000000
+#define bOFDMContinueTx 0x10000000
+#define bOFDMSingleCarrier 0x20000000
+#define bOFDMSingleTone 0x40000000
+/* define bRxPath1 0x01 */
+/* define bRxPath2 0x02 */
+/* define bRxPath3 0x04 */
+/* define bRxPath4 0x08 */
+/* define bTxPath1 0x10 */
+/* define bTxPath2 0x20 */
+#define bHTDetect 0x100
+#define bCFOEn 0x10000
+#define bCFOValue 0xfff00000
+#define bSigTone_Re 0x3f
+#define bSigTone_Im 0x7f00
+#define bCounter_CCA 0xffff
+#define bCounter_ParityFail 0xffff0000
+#define bCounter_RateIllegal 0xffff
+#define bCounter_CRC8Fail 0xffff0000
+#define bCounter_MCSNoSupport 0xffff
+#define bCounter_FastSync 0xffff
+#define bShortCFO 0xfff
+#define bShortCFOTLength 12 /* total */
+#define bShortCFOFLength 11 /* fraction */
+#define bLongCFO 0x7ff
+#define bLongCFOTLength 11
+#define bLongCFOFLength 11
+#define bTailCFO 0x1fff
+#define bTailCFOTLength 13
+#define bTailCFOFLength 12
+#define bmax_en_pwdB 0xffff
+#define bCC_power_dB 0xffff0000
+#define bnoise_pwdB 0xffff
+#define bPowerMeasTLength 10
+#define bPowerMeasFLength 3
+#define bRx_HT_BW 0x1
+#define bRxSC 0x6
+#define bRx_HT 0x8
+#define bNB_intf_det_on 0x1
+#define bIntf_win_len_cfg 0x30
+#define bNB_Intf_TH_cfg 0x1c0
+#define bRFGain 0x3f
+#define bTableSel 0x40
+#define bTRSW 0x80
+#define bRxSNR_A 0xff
+#define bRxSNR_B 0xff00
+#define bRxSNR_C 0xff0000
+#define bRxSNR_D 0xff000000
+#define bSNREVMTLength 8
+#define bSNREVMFLength 1
+#define bCSI1st 0xff
+#define bCSI2nd 0xff00
+#define bRxEVM1st 0xff0000
+#define bRxEVM2nd 0xff000000
+#define bSIGEVM 0xff
+#define bPWDB 0xff00
+#define bSGIEN 0x10000
+
+#define bSFactorQAM1 0xf /* Useless */
+#define bSFactorQAM2 0xf0
+#define bSFactorQAM3 0xf00
+#define bSFactorQAM4 0xf000
+#define bSFactorQAM5 0xf0000
+#define bSFactorQAM6 0xf0000
+#define bSFactorQAM7 0xf00000
+#define bSFactorQAM8 0xf000000
+#define bSFactorQAM9 0xf0000000
+#define bCSIScheme 0x100000
+
+#define bNoiseLvlTopSet 0x3 /* Useless */
+#define bChSmooth 0x4
+#define bChSmoothCfg1 0x38
+#define bChSmoothCfg2 0x1c0
+#define bChSmoothCfg3 0xe00
+#define bChSmoothCfg4 0x7000
+#define bMRCMode 0x800000
+#define bTHEVMCfg 0x7000000
+
+#define bLoopFitType 0x1 /* Useless */
+#define bUpdCFO 0x40
+#define bUpdCFOOffData 0x80
+#define bAdvUpdCFO 0x100
+#define bAdvTimeCtrl 0x800
+#define bUpdClko 0x1000
+#define bFC 0x6000
+#define bTrackingMode 0x8000
+#define bPhCmpEnable 0x10000
+#define bUpdClkoLTF 0x20000
+#define bComChCFO 0x40000
+#define bCSIEstiMode 0x80000
+#define bAdvUpdEqz 0x100000
+#define bUChCfg 0x7000000
+#define bUpdEqz 0x8000000
+
+#define bTxAGCRate18_06 0x7f7f7f7f /* Useless */
+#define bTxAGCRate54_24 0x7f7f7f7f
+#define bTxAGCRateMCS32 0x7f
+#define bTxAGCRateCCK 0x7f00
+#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f
+#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f
+#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f
+#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f
+
+/* Rx Pseduo noise */
+#define bRxPesudoNoiseOn 0x20000000 /* Useless */
+#define bRxPesudoNoise_A 0xff
+#define bRxPesudoNoise_B 0xff00
+#define bRxPesudoNoise_C 0xff0000
+#define bRxPesudoNoise_D 0xff000000
+#define bPesudoNoiseState_A 0xffff
+#define bPesudoNoiseState_B 0xffff0000
+#define bPesudoNoiseState_C 0xffff
+#define bPesudoNoiseState_D 0xffff0000
+
+/* 7. RF Register */
+/* Zebra1 */
+#define bZebra1_HSSIEnable 0x8 /* Useless */
+#define bZebra1_TRxControl 0xc00
+#define bZebra1_TRxGainSetting 0x07f
+#define bZebra1_RxCorner 0xc00
+#define bZebra1_TxChargePump 0x38
+#define bZebra1_RxChargePump 0x7
+#define bZebra1_ChannelNum 0xf80
+#define bZebra1_TxLPFBW 0x400
+#define bZebra1_RxLPFBW 0x600
+
+/* Zebra4 */
+#define bRTL8256RegModeCtrl1 0x100 /* Useless */
+#define bRTL8256RegModeCtrl0 0x40
+#define bRTL8256_TxLPFBW 0x18
+#define bRTL8256_RxLPFBW 0x600
+
+/* RTL8258 */
+#define bRTL8258_TxLPFBW 0xc /* Useless */
+#define bRTL8258_RxLPFBW 0xc00
+#define bRTL8258_RSSILPFBW 0xc0
+
+/* */
+/* Other Definition */
+/* */
+
+/* byte endable for sb_write */
+#define bByte0 0x1 /* Useless */
+#define bByte1 0x2
+#define bByte2 0x4
+#define bByte3 0x8
+#define bWord0 0x3
+#define bWord1 0xc
+#define bDWord 0xf
+
+/* for PutRegsetting & GetRegSetting BitMask */
+#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */
+#define bMaskByte1 0xff00
+#define bMaskByte2 0xff0000
+#define bMaskByte3 0xff000000
+#define bMaskHWord 0xffff0000
+#define bMaskLWord 0x0000ffff
+#define bMaskDWord 0xffffffff
+#define bMaskH4Bits 0xf0000000
+#define bMaskOFDM_D 0xffc00000
+#define bMaskCCK 0x3f3f3f3f
+#define bMask12Bits 0xfff
+
+/* for PutRFRegsetting & GetRFRegSetting BitMask */
+#if (RTL92SE_FPGA_VERIFY == 1)
+#define bRFRegOffsetMask 0xfff
+#else
+#define bRFRegOffsetMask 0xfffff
+#endif
+#define bEnable 0x1 /* Useless */
+#define bDisabl 0x0
+
+#define LeftAntenna 0x0 /* Useless */
+#define RightAntenna 0x1
+
+#define tCheckTxStatus 500 /* 500ms Useless */
+#define tUpdateRxCounter 100 /* 100ms */
+
+#define rateCCK 0 /* Useless */
+#define rateOFDM 1
+#define rateHT 2
+
+/* define Register-End */
+#define bPMAC_End 0x1ff /* Useless */
+#define bFPGAPHY0_End 0x8ff
+#define bFPGAPHY1_End 0x9ff
+#define bCCKPHY0_End 0xaff
+#define bOFDMPHY0_End 0xcff
+#define bOFDMPHY1_End 0xdff
+
+/* define max debug item in each debug page */
+/* define bMaxItem_FPGA_PHY0 0x9 */
+/* define bMaxItem_FPGA_PHY1 0x3 */
+/* define bMaxItem_PHY_11B 0x16 */
+/* define bMaxItem_OFDM_PHY0 0x29 */
+/* define bMaxItem_OFDM_PHY1 0x0 */
+
+#define bPMACControl 0x0 /* Useless */
+#define bWMACControl 0x1
+#define bWNICControl 0x2
+
+#define RCR_AAP BIT(0) /* accept all physical address */
+#define RCR_APM BIT(1) /* accept physical match */
+#define RCR_AM BIT(2) /* accept multicast */
+#define RCR_AB BIT(3) /* accept broadcast */
+#define RCR_ACRC32 BIT(5) /* accept error packet */
+#define RCR_9356SEL BIT(6)
+#define RCR_AICV BIT(12) /* Accept ICV error packet */
+#define RCR_RXFTH0 (BIT(13)|BIT(14)|BIT(15)) /* Rx FIFO threshold */
+#define RCR_ADF BIT(18) /* Accept Data(frame type) frame */
+#define RCR_ACF BIT(19) /* Accept control frame */
+#define RCR_AMF BIT(20) /* Accept management frame */
+#define RCR_ADD3 BIT(21)
+#define RCR_APWRMGT BIT(22) /* Accept power management packet */
+#define RCR_CBSSID BIT(23) /* Accept BSSID match packet */
+#define RCR_ENMARP BIT(28) /* enable mac auto reset phy */
+#define RCR_EnCS1 BIT(29) /* enable carrier sense method 1 */
+#define RCR_EnCS2 BIT(30) /* enable carrier sense method 2 */
+#define RCR_OnlyErlPkt BIT(31) /* Rx Early mode is performed for
+ * packet size greater than 1536 */
+
+/*--------------------------Define Parameters-------------------------------*/
+
+#endif /* __INC_HAL8192SPHYREG_H */
diff --git a/drivers/staging/r8188eu/include/rtw_p2p.h b/drivers/staging/r8188eu/include/rtw_p2p.h
new file mode 100644
index 000000000000..92b9bfe3ea0b
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_p2p.h
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __RTW_P2P_H_
+#define __RTW_P2P_H_
+
+#include "drv_types.h"
+
+u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
+u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
+u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo,
+ u8 *pbuf, u8 *pssid, u8 ussidlen,
+ u8 *pdev_raddr);
+u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo,
+ u8 *pbuf, u8 status_code);
+u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
+u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo,
+ u8 *pframe, uint len);
+u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo,
+ u8 *pframe, uint len, struct sta_info *psta);
+u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo,
+ u8 *pframe, uint len);
+u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo,
+ u8 *pframe, uint len);
+u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo,
+ u8 *pframe, uint len);
+u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe);
+u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo,
+ u8 *pframe, uint len);
+u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo,
+ u8 *pframe, uint len);
+u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo,
+ u8 *pframe, uint len);
+u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe,
+ uint len);
+void p2p_protocol_wk_hdl(struct adapter *padapter, int intcmdtype);
+void process_p2p_ps_ie(struct adapter *padapter, u8 *ies, u32 ielength);
+void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state);
+u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue);
+void reset_global_wifidirect_info(struct adapter *padapter);
+int rtw_init_wifi_display_info(struct adapter *padapter);
+void rtw_init_wifidirect_timers(struct adapter *padapter);
+void rtw_init_wifidirect_addrs(struct adapter *padapter, u8 *dev_addr,
+ u8 *iface_addr);
+void init_wifidirect_info(struct adapter *padapter, enum P2P_ROLE role);
+int rtw_p2p_enable(struct adapter *padapter, enum P2P_ROLE role);
+
+static inline void _rtw_p2p_set_state(struct wifidirect_info *wdinfo,
+ enum P2P_STATE state)
+{
+ if (wdinfo->p2p_state != state)
+ wdinfo->p2p_state = state;
+}
+
+static inline void _rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo,
+ enum P2P_STATE state)
+{
+ if (wdinfo->pre_p2p_state != state)
+ wdinfo->pre_p2p_state = state;
+}
+
+static inline void _rtw_p2p_set_role(struct wifidirect_info *wdinfo,
+ enum P2P_ROLE role)
+{
+ if (wdinfo->role != role)
+ wdinfo->role = role;
+}
+
+static inline int _rtw_p2p_state(struct wifidirect_info *wdinfo)
+{
+ return wdinfo->p2p_state;
+}
+
+static inline int _rtw_p2p_pre_state(struct wifidirect_info *wdinfo)
+{
+ return wdinfo->pre_p2p_state;
+}
+
+static inline int _rtw_p2p_role(struct wifidirect_info *wdinfo)
+{
+ return wdinfo->role;
+}
+
+static inline bool _rtw_p2p_chk_state(struct wifidirect_info *wdinfo,
+ enum P2P_STATE state)
+{
+ return wdinfo->p2p_state == state;
+}
+
+static inline bool _rtw_p2p_chk_role(struct wifidirect_info *wdinfo,
+ enum P2P_ROLE role)
+{
+ return wdinfo->role == role;
+}
+
+#define rtw_p2p_set_state(wdinfo, state) _rtw_p2p_set_state(wdinfo, state)
+#define rtw_p2p_set_pre_state(wdinfo, state) \
+ _rtw_p2p_set_pre_state(wdinfo, state)
+#define rtw_p2p_set_role(wdinfo, role) _rtw_p2p_set_role(wdinfo, role)
+
+#define rtw_p2p_state(wdinfo) _rtw_p2p_state(wdinfo)
+#define rtw_p2p_pre_state(wdinfo) _rtw_p2p_pre_state(wdinfo)
+#define rtw_p2p_role(wdinfo) _rtw_p2p_role(wdinfo)
+#define rtw_p2p_chk_state(wdinfo, state) _rtw_p2p_chk_state(wdinfo, state)
+#define rtw_p2p_chk_role(wdinfo, role) _rtw_p2p_chk_role(wdinfo, role)
+
+#define rtw_p2p_findphase_ex_set(wdinfo, value) \
+ ((wdinfo)->find_phase_state_exchange_cnt = (value))
+
+/* is this find phase exchange for social channel scan? */
+#define rtw_p2p_findphase_ex_is_social(wdinfo) \
+((wdinfo)->find_phase_state_exchange_cnt >= P2P_FINDPHASE_EX_SOCIAL_FIRST)
+
+/* should we need find phase exchange anymore? */
+#define rtw_p2p_findphase_ex_is_needed(wdinfo) \
+ ((wdinfo)->find_phase_state_exchange_cnt < P2P_FINDPHASE_EX_MAX && \
+ (wdinfo)->find_phase_state_exchange_cnt != P2P_FINDPHASE_EX_NONE)
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h b/drivers/staging/r8188eu/include/rtw_pwrctrl.h
index 4345dc0c7cf9..543f928e8089 100644
--- a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
+++ b/drivers/staging/r8188eu/include/rtw_pwrctrl.h
@@ -1,14 +1,11 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
#ifndef __RTW_PWRCTRL_H_
#define __RTW_PWRCTRL_H_
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "osdep_service.h"
+#include "drv_types.h"
#define FW_PWR0 0
#define FW_PWR1 1
@@ -43,11 +40,11 @@ enum power_mgnt {
};
/*
- * BIT[2:0] = HW state
- * BIT[3] = Protocol PS state, 0: register active state,
- * 1: register sleep state
- * BIT[4] = sub-state
- */
+ BIT[2:0] = HW state
+ BIT[3] = Protocol PS state, 0: register active state,
+ 1: register sleep state
+ BIT[4] = sub-state
+*/
#define PS_DPS BIT(0)
#define PS_LCLK (PS_DPS)
@@ -84,7 +81,26 @@ struct reportpwrstate_parm {
unsigned short rsvd;
};
-#define LPS_DELAY_TIME 1 * HZ /* 1 sec */
+static inline void _init_pwrlock(struct semaphore *plock)
+{
+ sema_init(plock, 1);
+}
+
+static inline void _free_pwrlock(struct semaphore *plock)
+{
+}
+
+static inline void _enter_pwrlock(struct semaphore *plock)
+{
+ _rtw_down_sema(plock);
+}
+
+static inline void _exit_pwrlock(struct semaphore *plock)
+{
+ up(plock);
+}
+
+#define LPS_DELAY_TIME 1*HZ /* 1 sec */
#define EXE_PWR_NONE 0x01
#define EXE_PWR_IPS 0x02
@@ -107,11 +123,9 @@ enum rt_rf_power_state {
#define RT_RF_OFF_LEVL_FREE_FW BIT(4) /* FW free, re-download the FW*/
#define RT_RF_OFF_LEVL_FW_32K BIT(5) /* FW in 32k */
#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT(6) /* Always enable ASPM and Clock
- * Req in initialization.
- */
+ * Req in initialization. */
#define RT_RF_LPS_DISALBE_2R BIT(30) /* When LPS is on, disable 2R
- * if no packet is RX or TX.
- */
+ * if no packet is RX or TX. */
#define RT_RF_LPS_LEVEL_ASPM BIT(31) /* LPS with ASPM */
#define RT_IN_PS_LEVEL(ppsc, _PS_FLAG) \
@@ -136,11 +150,10 @@ enum { /* for ips_mode */
};
struct pwrctrl_priv {
- struct mutex mutex_lock;
+ struct semaphore lock;
volatile u8 rpwm; /* requested power state for fw */
volatile u8 cpwm; /* fw current power state. updated when
- * 1. read from HCPWM 2. driver lowers power level
- */
+ * 1. read from HCPWM 2. driver lowers power level */
volatile u8 tog; /* toggling */
volatile u8 cpwm_tog; /* toggling */
@@ -165,13 +178,12 @@ struct pwrctrl_priv {
u8 ips_mode;
u8 ips_mode_req; /* used to accept the mode setting request,
- * will update to ipsmode later
- */
+ * will update to ipsmode later */
uint bips_processing;
- unsigned long ips_deny_time; /* will deny IPS when system time less than this */
+ u32 ips_deny_time; /* will deny IPS when system time less than this */
u8 ps_processing; /* temp used to mark whether in rtw_ps_processor */
- bool bLeisurePs;
+ u8 bLeisurePs;
u8 LpsIdleCount;
u8 power_mgnt;
u8 bFwCurrentInPSMode;
@@ -182,6 +194,10 @@ struct pwrctrl_priv {
u8 bInternalAutoSuspend;
u8 bInSuspend;
+#ifdef CONFIG_BT_COEXIST
+ u8 bAutoResume;
+ u8 autopm_cnt;
+#endif
u8 bSupportRemoteWakeup;
struct timer_list pwr_state_check_timer;
int pwr_state_check_interval;
@@ -209,14 +225,16 @@ struct pwrctrl_priv {
#define RTW_PWR_STATE_CHK_INTERVAL 2000
#define _rtw_set_pwr_state_check_timer(pwrctrlpriv, ms) \
- mod_timer(&pwrctrlpriv->pwr_state_check_timer, \
- jiffies + msecs_to_jiffies(ms))
+ do { \
+ _set_timer(&(pwrctrlpriv)->pwr_state_check_timer, (ms)); \
+ } while (0)
#define rtw_set_pwr_state_check_timer(pwrctrl) \
_rtw_set_pwr_state_check_timer((pwrctrl), \
(pwrctrl)->pwr_state_check_interval)
void rtw_init_pwrctrl_priv(struct adapter *adapter);
+void rtw_free_pwrctrl_priv(struct adapter *adapter);
void rtw_set_ps_mode(struct adapter *adapter, u8 ps_mode, u8 smart_ps,
u8 bcn_ant_mode);
@@ -233,6 +251,9 @@ s32 LPS_RF_ON_check(struct adapter *adapter, u32 delay_ms);
void LPS_Enter(struct adapter *adapter);
void LPS_Leave(struct adapter *adapter);
+u8 rtw_interface_ps_func(struct adapter *adapter,
+ enum hal_intf_ps_func efunc_id, u8 *val);
+void rtw_set_ips_deny(struct adapter *adapter, u32 ms);
int _rtw_pwr_wakeup(struct adapter *adapter, u32 ips_defer_ms,
const char *caller);
#define rtw_pwr_wakeup(adapter) \
diff --git a/drivers/staging/r8188eu/include/rtw_recv.h b/drivers/staging/r8188eu/include/rtw_recv.h
new file mode 100644
index 000000000000..d1d1ca0e56d6
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_recv.h
@@ -0,0 +1,413 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#ifndef _RTW_RECV_H_
+#define _RTW_RECV_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+#define NR_RECVFRAME 256
+
+#define RXFRAME_ALIGN 8
+#define RXFRAME_ALIGN_SZ (1<<RXFRAME_ALIGN)
+
+#define MAX_RXFRAME_CNT 512
+#define MAX_RX_NUMBLKS (32)
+#define RECVFRAME_HDR_ALIGN 128
+
+#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
+
+#define MAX_SUBFRAME_COUNT 64
+
+#define LLC_HEADER_SIZE 6
+
+/* for Rx reordering buffer control */
+struct recv_reorder_ctrl {
+ struct adapter *padapter;
+ u8 enable;
+ u16 indicate_seq;/* wstart_b, init_value=0xffff */
+ u16 wend_b;
+ u8 wsize_b;
+ struct __queue pending_recvframe_queue;
+ struct timer_list reordering_ctrl_timer;
+};
+
+struct stainfo_rxcache {
+ u16 tid_rxseq[16];
+/*
+ unsigned short tid0_rxseq;
+ unsigned short tid1_rxseq;
+ unsigned short tid2_rxseq;
+ unsigned short tid3_rxseq;
+ unsigned short tid4_rxseq;
+ unsigned short tid5_rxseq;
+ unsigned short tid6_rxseq;
+ unsigned short tid7_rxseq;
+ unsigned short tid8_rxseq;
+ unsigned short tid9_rxseq;
+ unsigned short tid10_rxseq;
+ unsigned short tid11_rxseq;
+ unsigned short tid12_rxseq;
+ unsigned short tid13_rxseq;
+ unsigned short tid14_rxseq;
+ unsigned short tid15_rxseq;
+*/
+};
+
+struct smooth_rssi_data {
+ u32 elements[100]; /* array to store values */
+ u32 index; /* index to current array to store */
+ u32 total_num; /* num of valid elements */
+ u32 total_val; /* sum of valid elements */
+};
+
+struct signal_stat {
+ u8 update_req; /* used to indicate */
+ u8 avg_val; /* avg of valid elements */
+ u32 total_num; /* num of valid elements */
+ u32 total_val; /* sum of valid elements */
+};
+#define MAX_PATH_NUM_92CS 3
+struct phy_info {
+ u8 RxPWDBAll;
+ u8 SignalQuality; /* in 0-100 index. */
+ u8 RxMIMOSignalQuality[MAX_PATH_NUM_92CS]; /* EVM */
+ u8 RxMIMOSignalStrength[MAX_PATH_NUM_92CS];/* in 0~100 index */
+ s8 RxPower; /* in dBm Translate from PWdB */
+/* Real power in dBm for this packet, no beautification and aggregation.
+ * Keep this raw info to be used for the other procedures. */
+ s8 recvpower;
+ u8 BTRxRSSIPercentage;
+ u8 SignalStrength; /* in 0-100 index. */
+ u8 RxPwr[MAX_PATH_NUM_92CS];/* per-path's pwdb */
+ u8 RxSNR[MAX_PATH_NUM_92CS];/* per-path's SNR */
+};
+
+struct rx_pkt_attrib {
+ u16 pkt_len;
+ u8 physt;
+ u8 drvinfo_sz;
+ u8 shift_sz;
+ u8 hdrlen; /* the WLAN Header Len */
+ u8 to_fr_ds;
+ u8 amsdu;
+ u8 qos;
+ u8 priority;
+ u8 pw_save;
+ u8 mdata;
+ u16 seq_num;
+ u8 frag_num;
+ u8 mfrag;
+ u8 order;
+ u8 privacy; /* in frame_ctrl field */
+ u8 bdecrypted;
+ u8 encrypt; /* when 0 indicate no encrypt. when non-zero,
+ * indicate the encrypt algorith */
+ u8 iv_len;
+ u8 icv_len;
+ u8 crc_err;
+ u8 icv_err;
+
+ u16 eth_type;
+
+ u8 dst[ETH_ALEN] __aligned(2);
+ u8 src[ETH_ALEN] __aligned(2);
+ u8 ta[ETH_ALEN] __aligned(2);
+ u8 ra[ETH_ALEN] __aligned(2);
+ u8 bssid[ETH_ALEN] __aligned(2);
+
+ u8 ack_policy;
+
+ u8 key_index;
+
+ u8 mcs_rate;
+ u8 rxht;
+ u8 sgi;
+ u8 pkt_rpt_type;
+ u32 MacIDValidEntry[2]; /* 64 bits present 64 entry. */
+
+ struct phy_info phy_info;
+};
+
+/* These definition is used for Rx packet reordering. */
+#define SN_LESS(a, b) (((a - b) & 0x800) != 0)
+#define SN_EQUAL(a, b) (a == b)
+#define REORDER_WAIT_TIME (50) /* (ms) */
+
+#define RECVBUFF_ALIGN_SZ 8
+
+#define RXDESC_SIZE 24
+#define RXDESC_OFFSET RXDESC_SIZE
+
+struct recv_stat {
+ __le32 rxdw0;
+ __le32 rxdw1;
+ __le32 rxdw2;
+ __le32 rxdw3;
+ __le32 rxdw4;
+ __le32 rxdw5;
+};
+
+#define EOR BIT(30)
+
+/*
+accesser of recv_priv: rtw_recv_entry(dispatch / passive level);
+recv_thread(passive) ; returnpkt(dispatch)
+; halt(passive) ;
+
+using enter_critical section to protect
+*/
+struct recv_priv {
+ spinlock_t lock;
+ struct __queue free_recv_queue;
+ struct __queue recv_pending_queue;
+ struct __queue uc_swdec_pending_queue;
+ u8 *pallocated_frame_buf;
+ u8 *precv_frame_buf;
+ uint free_recvframe_cnt;
+ struct adapter *adapter;
+ u32 bIsAnyNonBEPkts;
+ u64 rx_bytes;
+ u64 rx_pkts;
+ u64 rx_drop;
+ u64 last_rx_bytes;
+
+ uint rx_icv_err;
+ uint rx_largepacket_crcerr;
+ uint rx_smallpacket_crcerr;
+ uint rx_middlepacket_crcerr;
+ struct semaphore allrxreturnevt;
+ uint ff_hwaddr;
+ u8 rx_pending_cnt;
+
+ struct tasklet_struct irq_prepare_beacon_tasklet;
+ struct tasklet_struct recv_tasklet;
+ struct sk_buff_head free_recv_skb_queue;
+ struct sk_buff_head rx_skb_queue;
+ u8 *pallocated_recv_buf;
+ u8 *precv_buf; /* 4 alignment */
+ struct __queue free_recv_buf_queue;
+ u32 free_recv_buf_queue_cnt;
+ /* For display the phy informatiom */
+ u8 is_signal_dbg; /* for debug */
+ u8 signal_strength_dbg; /* for debug */
+ s8 rssi;
+ s8 rxpwdb;
+ u8 signal_strength;
+ u8 signal_qual;
+ u8 noise;
+ int RxSNRdB[2];
+ s8 RxRssi[2];
+ int FalseAlmCnt_all;
+
+ struct timer_list signal_stat_timer;
+ u32 signal_stat_sampling_interval;
+ struct signal_stat signal_qual_data;
+ struct signal_stat signal_strength_data;
+};
+
+#define rtw_set_signal_stat_timer(recvpriv) \
+ _set_timer(&(recvpriv)->signal_stat_timer, \
+ (recvpriv)->signal_stat_sampling_interval)
+
+struct sta_recv_priv {
+ spinlock_t lock;
+ int option;
+ struct __queue defrag_q; /* keeping the fragment frame until defrag */
+ struct stainfo_rxcache rxcache;
+};
+
+struct recv_buf {
+ struct list_head list;
+ spinlock_t recvbuf_lock;
+ u32 ref_cnt;
+ struct adapter *adapter;
+ u8 *pbuf;
+ u8 *pallocated_buf;
+ u32 len;
+ u8 *phead;
+ u8 *pdata;
+ u8 *ptail;
+ u8 *pend;
+ struct urb *purb;
+ dma_addr_t dma_transfer_addr; /* (in) dma addr for transfer_buffer */
+ u32 alloc_sz;
+ u8 irp_pending;
+ int transfer_len;
+ struct sk_buff *pskb;
+ u8 reuse;
+};
+
+/*
+ head ----->
+
+ data ----->
+
+ payload
+
+ tail ----->
+
+ end ----->
+
+ len = (unsigned int )(tail - data);
+
+*/
+struct recv_frame {
+ struct list_head list;
+ struct sk_buff *pkt;
+ struct sk_buff *pkt_newalloc;
+ struct adapter *adapter;
+ u8 fragcnt;
+ int frame_tag;
+ struct rx_pkt_attrib attrib;
+ uint len;
+ u8 *rx_head;
+ u8 *rx_data;
+ u8 *rx_tail;
+ u8 *rx_end;
+ void *precvbuf;
+ struct sta_info *psta;
+ /* for A-MPDU Rx reordering buffer control */
+ struct recv_reorder_ctrl *preorder_ctrl;
+};
+
+struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
+struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
+void rtw_init_recvframe(struct recv_frame *precvframe,
+ struct recv_priv *precvpriv);
+int rtw_free_recvframe(struct recv_frame *precvframe,
+ struct __queue *pfree_recv_queue);
+#define rtw_dequeue_recvframe(queue) rtw_alloc_recvframe(queue)
+int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue);
+int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue);
+void rtw_free_recvframe_queue(struct __queue *pframequeue,
+ struct __queue *pfree_recv_queue);
+u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter);
+int rtw_enqueue_recvbuf_to_head(struct recv_buf *buf, struct __queue *queue);
+int rtw_enqueue_recvbuf(struct recv_buf *precvbuf, struct __queue *queue);
+struct recv_buf *rtw_dequeue_recvbuf(struct __queue *queue);
+
+void rtw_reordering_ctrl_timeout_handler(void *pcontext);
+
+static inline u8 *get_rxmem(struct recv_frame *precvframe)
+{
+ /* always return rx_head... */
+ if (precvframe == NULL)
+ return NULL;
+ return precvframe->rx_head;
+}
+
+static inline u8 *get_rx_status(struct recv_frame *precvframe)
+{
+ return get_rxmem(precvframe);
+}
+
+static inline u8 *get_recvframe_data(struct recv_frame *precvframe)
+{
+ /* always return rx_data */
+ if (precvframe == NULL)
+ return NULL;
+
+ return precvframe->rx_data;
+}
+
+static inline u8 *recvframe_push(struct recv_frame *precvframe, int sz)
+{
+ /* append data before rx_data */
+
+ /* add data to the start of recv_frame
+ *
+ * This function extends the used data area of the recv_frame at the buffer
+ * start. rx_data must be still larger than rx_head, after pushing.
+ */
+ if (precvframe == NULL)
+ return NULL;
+ precvframe->rx_data -= sz ;
+ if (precvframe->rx_data < precvframe->rx_head) {
+ precvframe->rx_data += sz;
+ return NULL;
+ }
+ precvframe->len += sz;
+ return precvframe->rx_data;
+}
+
+static inline u8 *recvframe_pull(struct recv_frame *precvframe, int sz)
+{
+ /* rx_data += sz; move rx_data sz bytes hereafter */
+
+ /* used for extract sz bytes from rx_data, update rx_data and return
+ * the updated rx_data to the caller */
+
+ if (precvframe == NULL)
+ return NULL;
+ precvframe->rx_data += sz;
+ if (precvframe->rx_data > precvframe->rx_tail) {
+ precvframe->rx_data -= sz;
+ return NULL;
+ }
+ precvframe->len -= sz;
+ return precvframe->rx_data;
+}
+
+static inline u8 *recvframe_put(struct recv_frame *precvframe, int sz)
+{
+ /* used for append sz bytes from ptr to rx_tail, update rx_tail
+ * and return the updated rx_tail to the caller */
+ /* after putting, rx_tail must be still larger than rx_end. */
+
+ if (precvframe == NULL)
+ return NULL;
+
+ precvframe->rx_tail += sz;
+
+ if (precvframe->rx_tail > precvframe->rx_end) {
+ precvframe->rx_tail -= sz;
+ return NULL;
+ }
+ precvframe->len += sz;
+ return precvframe->rx_tail;
+}
+
+static inline u8 *recvframe_pull_tail(struct recv_frame *precvframe, int sz)
+{
+ /* rmv data from rx_tail (by yitsen) */
+
+ /* used for extract sz bytes from rx_end, update rx_end and return
+ * the updated rx_end to the caller */
+ /* after pulling, rx_end must be still larger than rx_data. */
+
+ if (precvframe == NULL)
+ return NULL;
+ precvframe->rx_tail -= sz;
+ if (precvframe->rx_tail < precvframe->rx_data) {
+ precvframe->rx_tail += sz;
+ return NULL;
+ }
+ precvframe->len -= sz;
+ return precvframe->rx_tail;
+}
+
+static inline int get_recvframe_len(struct recv_frame *precvframe)
+{
+ return precvframe->len;
+}
+
+static inline s32 translate_percentage_to_dbm(u32 sig_stren_index)
+{
+ s32 power; /* in dBm. */
+
+ /* Translate to dBm (x=0.5y-95). */
+ power = (s32)((sig_stren_index + 1) >> 1);
+ power -= 95;
+
+ return power;
+}
+
+struct sta_info;
+
+void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv);
+
+void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_rf.h b/drivers/staging/r8188eu/include/rtw_rf.h
index aabacb41bdde..48129da9c93f 100644
--- a/drivers/staging/rtl8188eu/include/rtw_rf.h
+++ b/drivers/staging/r8188eu/include/rtw_rf.h
@@ -1,13 +1,10 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTW_RF_H_
#define __RTW_RF_H_
-#include <rtw_cmd.h>
+#include "rtw_cmd.h"
#define OFDM_PHY 1
#define MIXED_PHY 2
@@ -19,14 +16,18 @@
#define SHORT_SLOT_TIME 9
#define NON_SHORT_SLOT_TIME 20
+#define RTL8711_RF_MAX_SENS 6
+#define RTL8711_RF_DEF_SENS 4
+
/* We now define the following channels as the max channels in each
- * channel plan.
- */
+ * channel plan. */
/* 2G, total 14 chnls */
/* {1,2,3,4,5,6,7,8,9,10,11,12,13,14} */
#define MAX_CHANNEL_NUM_2G 14
#define MAX_CHANNEL_NUM 14 /* 2.4 GHz only */
+#define NUM_REGULATORYS 1
+
/* Country codes */
#define USA 0x555320
#define EUROPE 0x1 /* temp, should be provided later */
@@ -53,8 +54,7 @@ enum capability {
cChannelAgility = 0x0080,
cSpectrumMgnt = 0x0100,
cQos = 0x0200, /* For HCCA, use with CF-Pollable
- * and CF-PollReq
- */
+ * and CF-PollReq */
cShortSlotTime = 0x0400,
cAPSD = 0x0800,
cRM = 0x1000, /* RRM (Radio Request Measurement) */
@@ -69,6 +69,17 @@ enum _REG_PREAMBLE_MODE {
PREAMBLE_SHORT = 3,
};
+enum _RTL8712_RF_MIMO_CONFIG_ {
+ RTL8712_RFCONFIG_1T = 0x10,
+ RTL8712_RFCONFIG_2T = 0x20,
+ RTL8712_RFCONFIG_1R = 0x01,
+ RTL8712_RFCONFIG_2R = 0x02,
+ RTL8712_RFCONFIG_1T1R = 0x11,
+ RTL8712_RFCONFIG_1T2R = 0x12,
+ RTL8712_RFCONFIG_TURBO = 0x92,
+ RTL8712_RFCONFIG_2T2R = 0x22
+};
+
enum rf90_radio_path {
RF90_PATH_A = 0, /* Radio Path A */
RF90_PATH_B = 1, /* Radio Path B */
@@ -86,9 +97,6 @@ enum rf90_radio_path {
enum ht_channel_width {
HT_CHANNEL_WIDTH_20 = 0,
HT_CHANNEL_WIDTH_40 = 1,
- HT_CHANNEL_WIDTH_80 = 2,
- HT_CHANNEL_WIDTH_160 = 3,
- HT_CHANNEL_WIDTH_10 = 4,
};
/* */
@@ -113,5 +121,6 @@ enum rt_rf_type_def {
};
u32 rtw_ch2freq(u32 ch);
+u32 rtw_freq2ch(u32 freq);
#endif /* _RTL8711_RF_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_security.h b/drivers/staging/r8188eu/include/rtw_security.h
index fbb72c570239..ec6ecdb7bc98 100644
--- a/drivers/staging/rtl8188eu/include/rtw_security.h
+++ b/drivers/staging/r8188eu/include/rtw_security.h
@@ -1,14 +1,11 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __RTW_SECURITY_H_
#define __RTW_SECURITY_H_
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "osdep_service.h"
+#include "drv_types.h"
#define _NO_PRIVACY_ 0x0
#define _WEP40_ 0x1
@@ -21,6 +18,9 @@
#define is_wep_enc(alg) (((alg) == _WEP40_) || ((alg) == _WEP104_))
+#define _WPA_IE_ID_ 0xdd
+#define _WPA2_IE_ID_ 0x30
+
#define SHA256_MAC_LEN 32
#define AES_BLOCK_SIZE 16
#define AES_PRIV_SIZE (4 * 44)
@@ -78,8 +78,8 @@ union Keytype {
};
struct rt_pmkid_list {
- u8 used;
- u8 bssid[ETH_ALEN];
+ u8 bUsed;
+ u8 Bssid[6];
u8 PMKID[16];
u8 SsidBuf[33];
u8 *ssid_octet;
@@ -88,26 +88,20 @@ struct rt_pmkid_list {
struct security_priv {
u32 dot11AuthAlgrthm; /* 802.11 auth, could be open,
- * shared, 8021x and authswitch
- */
+ * shared, 8021x and authswitch */
u32 dot11PrivacyAlgrthm; /* This specify the privacy for
- * shared auth. algorithm.
- */
+ * shared auth. algorithm. */
/* WEP */
u32 dot11PrivacyKeyIndex; /* this is only valid for legendary
- * wep, 0~3 for key id.(tx key index)
- */
+ * wep, 0~3 for key id.(tx key index) */
union Keytype dot11DefKey[4]; /* this is only valid for def. key */
u32 dot11DefKeylen[4];
u32 dot118021XGrpPrivacy; /* This specify the privacy algthm.
- * used for Grp key
- */
+ * used for Grp key */
u32 dot118021XGrpKeyid; /* key id used for Grp Key
- * ( tx key index)
- */
+ * ( tx key index) */
union Keytype dot118021XGrpKey[4]; /* 802.1x Group Key,
- * for inx0 and inx1
- */
+ * for inx0 and inx1 */
union Keytype dot118021XGrptxmickey[4];
union Keytype dot118021XGrprxmickey[4];
union pn48 dot11Grptxpn; /* PN48 used for Grp Key xmit.*/
@@ -127,13 +121,13 @@ struct security_priv {
u8 busetkipkey;
u8 bcheck_grpkey;
u8 bgrpkey_handshake;
+ s32 sw_encrypt;/* from registry_priv */
+ s32 sw_decrypt;/* from registry_priv */
s32 hw_decrypted;/* if the rx packets is hw_decrypted==false,i
- * it means the hw has not been ready.
- */
+ * it means the hw has not been ready. */
/* keeps the auth_type & enc_status from upper layer
- * ioctl(wpa_supplicant or wzc)
- */
+ * ioctl(wpa_supplicant or wzc) */
u32 ndisauthtype; /* NDIS_802_11_AUTHENTICATION_MODE */
u32 ndisencryptstatus; /* NDIS_802_11_ENCRYPTION_STATUS */
struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */
@@ -215,8 +209,8 @@ do { \
dot11txpn._byte_.TSC5 = iv[7]; \
} while (0)
-#define ROL32(A, n) (((A) << (n)) | (((A) >> (32 - (n))) & ((1UL << (n)) - 1)))
-#define ROR32(A, n) ROL32((A), 32 - (n))
+#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1)))
+#define ROR32(A, n) ROL32((A), 32-(n))
struct mic_data {
u32 K0, K1; /* Key */
@@ -225,17 +219,123 @@ struct mic_data {
u32 nBytesInM; /* # bytes in M */
};
+extern const u32 Te0[256];
+extern const u32 Te1[256];
+extern const u32 Te2[256];
+extern const u32 Te3[256];
+extern const u32 Te4[256];
+extern const u32 Td0[256];
+extern const u32 Td1[256];
+extern const u32 Td2[256];
+extern const u32 Td3[256];
+extern const u32 Td4[256];
+extern const u32 rcon[10];
+extern const u8 Td4s[256];
+extern const u8 rcons[10];
+
+#define RCON(i) (rcons[(i)] << 24)
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
+#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
+#define TE3(i) rotr(Te0[(i) & 0xff], 24)
+#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
+#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
+#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
+#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
+#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
+#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
+#define TD3(i) rotr(Td0[(i) & 0xff], 24)
+#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
+#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
+#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
+#define TD44(i) (Td4s[(i) & 0xff])
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
+#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
+#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
+
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
+ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
+
+#define PUTU32(ct, st) { \
+(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \
+(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
+
+#define WPA_GET_BE32(a) ((((u32)(a)[0]) << 24) | (((u32)(a)[1]) << 16) | \
+ (((u32)(a)[2]) << 8) | ((u32)(a)[3]))
+
+#define WPA_PUT_LE16(a, val) \
+ do { \
+ (a)[1] = ((u16)(val)) >> 8; \
+ (a)[0] = ((u16)(val)) & 0xff; \
+ } while (0)
+
+#define WPA_PUT_BE32(a, val) \
+ do { \
+ (a)[0] = (u8)((((u32)(val)) >> 24) & 0xff); \
+ (a)[1] = (u8)((((u32)(val)) >> 16) & 0xff); \
+ (a)[2] = (u8)((((u32)(val)) >> 8) & 0xff); \
+ (a)[3] = (u8)(((u32)(val)) & 0xff); \
+ } while (0)
+
+#define WPA_PUT_BE64(a, val) \
+ do { \
+ (a)[0] = (u8)(((u64)(val)) >> 56); \
+ (a)[1] = (u8)(((u64)(val)) >> 48); \
+ (a)[2] = (u8)(((u64)(val)) >> 40); \
+ (a)[3] = (u8)(((u64)(val)) >> 32); \
+ (a)[4] = (u8)(((u64)(val)) >> 24); \
+ (a)[5] = (u8)(((u64)(val)) >> 16); \
+ (a)[6] = (u8)(((u64)(val)) >> 8); \
+ (a)[7] = (u8)(((u64)(val)) & 0xff); \
+ } while (0)
+
+/* ===== start - public domain SHA256 implementation ===== */
+
+/* This is based on SHA256 implementation in LibTomCrypt that was released into
+ * public domain by Tom St Denis. */
+
+/* Various logical functions */
+#define RORc(x, y) \
+ (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y)&31)) | \
+ ((unsigned long)(x) << (unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define Ch(x, y ,z) (z ^ (x & (y ^ z)))
+#define Maj(x, y, z) (((x | y) & z) | (x & y))
+#define S(x, n) RORc((x), (n))
+#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key);
void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b);
void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nBytes);
void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst);
void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len,
u8 *Miccode, u8 priority);
-u32 rtw_aes_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe);
-u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe);
-void rtw_wep_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe);
-u32 rtw_aes_decrypt(struct adapter *padapter, struct recv_frame *precvframe);
-u32 rtw_tkip_decrypt(struct adapter *padapter, struct recv_frame *precvframe);
-int rtw_wep_decrypt(struct adapter *padapter, struct recv_frame *precvframe);
+u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe);
+u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe);
+void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe);
+u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe);
+u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe);
+void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe);
+void rtw_use_tkipkey_handler(void *FunctionContext);
#endif /* __RTL871X_SECURITY_H_ */
diff --git a/drivers/staging/r8188eu/include/rtw_sreset.h b/drivers/staging/r8188eu/include/rtw_sreset.h
new file mode 100644
index 000000000000..4e97997c305b
--- /dev/null
+++ b/drivers/staging/r8188eu/include/rtw_sreset.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#ifndef _RTW_SRESET_C_
+#define _RTW_SRESET_C_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+struct sreset_priv {
+ struct mutex silentreset_mutex;
+ u8 silent_reset_inprogress;
+ u8 wifi_error_status;
+ unsigned long last_tx_time;
+ unsigned long last_tx_complete_time;
+};
+
+#include "rtl8188e_hal.h"
+
+#define WIFI_STATUS_SUCCESS 0
+#define USB_VEN_REQ_CMD_FAIL BIT(0)
+#define USB_READ_PORT_FAIL BIT(1)
+#define USB_WRITE_PORT_FAIL BIT(2)
+#define WIFI_MAC_TXDMA_ERROR BIT(3)
+#define WIFI_TX_HANG BIT(4)
+#define WIFI_RX_HANG BIT(5)
+#define WIFI_IF_NOT_EXIST BIT(6)
+
+void sreset_init_value(struct adapter *padapter);
+void sreset_reset_value(struct adapter *padapter);
+u8 sreset_get_wifi_status(struct adapter *padapter);
+void sreset_set_wifi_error_status(struct adapter *padapter, u32 status);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/r8188eu/include/rtw_xmit.h
index 456fd52717f3..5f6e2402e5c4 100644
--- a/drivers/staging/rtl8188eu/include/rtw_xmit.h
+++ b/drivers/staging/r8188eu/include/rtw_xmit.h
@@ -1,14 +1,11 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef _RTW_XMIT_H_
#define _RTW_XMIT_H_
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "osdep_service.h"
+#include "drv_types.h"
#define MAX_XMITBUF_SZ (20480) /* 20k */
#define NR_XMITBUFF (4)
@@ -42,8 +39,8 @@ do {\
pattrib_iv[0] = dot11txpn._byte_.TSC0;\
pattrib_iv[1] = dot11txpn._byte_.TSC1;\
pattrib_iv[2] = dot11txpn._byte_.TSC2;\
- pattrib_iv[3] = ((keyidx & 0x3) << 6);\
- dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : (dot11txpn.val + 1);\
+ pattrib_iv[3] = ((keyidx & 0x3)<<6);\
+ dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : (dot11txpn.val+1);\
} while (0)
#define TKIP_IV(pattrib_iv, dot11txpn, keyidx)\
@@ -51,12 +48,12 @@ do {\
pattrib_iv[0] = dot11txpn._byte_.TSC1;\
pattrib_iv[1] = (dot11txpn._byte_.TSC1 | 0x20) & 0x7f;\
pattrib_iv[2] = dot11txpn._byte_.TSC0;\
- pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6);\
+ pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6);\
pattrib_iv[4] = dot11txpn._byte_.TSC2;\
pattrib_iv[5] = dot11txpn._byte_.TSC3;\
pattrib_iv[6] = dot11txpn._byte_.TSC4;\
pattrib_iv[7] = dot11txpn._byte_.TSC5;\
- dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val + 1);\
+ dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val+1);\
} while (0)
#define AES_IV(pattrib_iv, dot11txpn, keyidx)\
@@ -64,12 +61,12 @@ do { \
pattrib_iv[0] = dot11txpn._byte_.TSC0; \
pattrib_iv[1] = dot11txpn._byte_.TSC1; \
pattrib_iv[2] = 0; \
- pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6); \
+ pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6); \
pattrib_iv[4] = dot11txpn._byte_.TSC2; \
pattrib_iv[5] = dot11txpn._byte_.TSC3; \
pattrib_iv[6] = dot11txpn._byte_.TSC4; \
pattrib_iv[7] = dot11txpn._byte_.TSC5; \
- dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val + 1);\
+ dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val+1);\
} while (0)
#define HWXMIT_ENTRY 4
@@ -91,6 +88,11 @@ struct tx_desc {
__le32 txdw7;
};
+union txdesc {
+ struct tx_desc txdesc;
+ unsigned int value[TXDESC_SIZE>>2];
+};
+
struct hw_xmit {
struct __queue *sta_queue;
int accnt;
@@ -104,15 +106,14 @@ struct pkt_attrib {
u8 dhcp_pkt;
u16 ether_type;
u16 seqnum;
+ u16 pkt_hdrlen; /* the original 802.3 pkt header len */
u16 hdrlen; /* the WLAN Header Len */
u32 pktlen; /* the original 802.3 pkt raw_data len (not include
- * ether_hdr data)
- */
+ * ether_hdr data) */
u32 last_txcmdsz;
u8 nr_frags;
u8 encrypt; /* when 0 indicate no encrypt. when non-zero,
- * indicate the encrypt algorithm
- */
+ * indicate the encrypt algorith */
u8 iv_len;
u8 icv_len;
u8 iv[18];
@@ -121,10 +122,10 @@ struct pkt_attrib {
u8 ack_policy;
u8 mac_id;
u8 vcs_mode; /* virtual carrier sense method */
- u8 dst[ETH_ALEN];
- u8 src[ETH_ALEN];
- u8 ta[ETH_ALEN];
- u8 ra[ETH_ALEN];
+ u8 dst[ETH_ALEN] __aligned(2);
+ u8 src[ETH_ALEN] __aligned(2);
+ u8 ta[ETH_ALEN] __aligned(2);
+ u8 ra[ETH_ALEN] __aligned(2);
u8 key_idx;
u8 qos_en;
u8 ht_en;
@@ -184,6 +185,7 @@ enum {
void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms);
int rtw_sctx_wait(struct submit_ctx *sctx);
void rtw_sctx_done_err(struct submit_ctx **sctx, int status);
+void rtw_sctx_done(struct submit_ctx **sctx);
struct xmit_buf {
struct list_head list;
@@ -193,9 +195,14 @@ struct xmit_buf {
void *priv_data;
u16 ext_tag; /* 0: Normal xmitbuf, 1: extension xmitbuf. */
u16 flags;
+ u32 alloc_sz;
u32 len;
struct submit_ctx *sctx;
+ u32 ff_hwaddr;
struct urb *pxmit_urb[8];
+ dma_addr_t dma_transfer_addr; /* (in) dma addr for transfer_buffer */
+ u8 bpending[8];
+ int last[8];
};
struct xmit_frame {
@@ -222,8 +229,7 @@ struct sta_xmit_priv {
spinlock_t lock;
int option;
int apsd_setting; /* When bit mask is on, the associated edca
- * queue supports APSD.
- */
+ * queue supports APSD. */
struct tx_servq be_q; /* priority == 0,3 */
struct tx_servq bk_q; /* priority == 1,2 */
struct tx_servq vi_q; /* priority == 4,5 */
@@ -244,8 +250,15 @@ struct hw_txqueue {
int ac_tag;
};
+struct agg_pkt_info {
+ u16 offset;
+ u16 pkt_len;
+};
+
struct xmit_priv {
spinlock_t lock;
+ struct semaphore xmit_sema;
+ struct semaphore terminate_xmitthread_sema;
struct __queue be_pending;
struct __queue bk_pending;
struct __queue vi_pending;
@@ -269,8 +282,8 @@ struct xmit_priv {
u8 hwxmit_entry;
u8 wmm_para_seq[4];/* sequence for wmm ac parameter strength
* from large to small. it's value is 0->vo,
- * 1->vi, 2->be, 3->bk.
- */
+ * 1->vi, 2->be, 3->bk. */
+ struct semaphore tx_retevt;/* all tx return event; */
u8 txirp_cnt;/* */
struct tasklet_struct xmit_tasklet;
/* per AC pending irp */
@@ -320,6 +333,8 @@ struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv,
s32 rtw_xmit_classifier(struct adapter *padapter,
struct xmit_frame *pxmitframe);
+u32 rtw_calculate_wlan_pkt_size_by_attribue(struct pkt_attrib *pattrib);
+#define rtw_wlan_pkt_size(f) rtw_calculate_wlan_pkt_size_by_attribue(&f->attrib)
s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt,
struct xmit_frame *pxmitframe);
s32 _rtw_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag);
@@ -330,7 +345,7 @@ s32 rtw_txframes_sta_ac_pending(struct adapter *padapter,
void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry);
s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter);
void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv);
-s32 rtw_alloc_hwxmits(struct adapter *padapter);
+void rtw_alloc_hwxmits(struct adapter *padapter);
void rtw_free_hwxmits(struct adapter *padapter);
s32 rtw_xmit(struct adapter *padapter, struct sk_buff **pkt);
@@ -347,6 +362,6 @@ int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms);
void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status);
/* include after declaring struct xmit_buf, in order to avoid warning */
-#include <xmit_osdep.h>
+#include "xmit_osdep.h"
#endif /* _RTL871X_XMIT_H_ */
diff --git a/drivers/staging/rtl8188eu/include/sta_info.h b/drivers/staging/r8188eu/include/sta_info.h
index 6165adafc451..8ff99fc6381d 100644
--- a/drivers/staging/rtl8188eu/include/sta_info.h
+++ b/drivers/staging/r8188eu/include/sta_info.h
@@ -1,15 +1,12 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __STA_INFO_H_
#define __STA_INFO_H_
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <wifi.h>
+#include "osdep_service.h"
+#include "drv_types.h"
+#include "wifi.h"
#define IBSS_START_MAC_ID 2
#define NUM_STA 32
@@ -100,6 +97,7 @@ struct sta_info {
u8 raid;
u8 init_rate;
+ u32 ra_mask;
u8 wireless_mode; /* NETWORK_TYPE */
struct stainfo_stats sta_stats;
@@ -118,8 +116,7 @@ struct sta_info {
/* Notes: */
/* STA_Mode: */
/* curr_network(mlme_priv/security_priv/qos/ht) +
- * sta_info: (STA & AP) CAP/INFO
- */
+ * sta_info: (STA & AP) CAP/INFO */
/* scan_q: AP CAP/INFO */
/* AP_Mode: */
@@ -169,6 +166,21 @@ struct sta_info {
unsigned int sleepq_ac_len;
#endif /* CONFIG_88EU_AP_MODE */
+#ifdef CONFIG_88EU_P2P
+ /* p2p priv data */
+ u8 is_p2p_device;
+ u8 p2p_status_code;
+
+ /* p2p client info */
+ u8 dev_addr[ETH_ALEN];
+ u8 dev_cap;
+ u16 config_methods;
+ u8 primary_dev_type[8];
+ u8 num_of_secdev_type;
+ u8 secdev_types_list[32];/* 32/8 == 4; */
+ u16 dev_name_len;
+ u8 dev_name[32];
+#endif /* CONFIG_88EU_P2P */
u8 under_exist_checking;
u8 keep_alive_trycnt;
@@ -177,8 +189,7 @@ struct sta_info {
/* ================ODM Relative Info======================= */
/* Please be careful, don't declare too much structure here.
- * It will cost memory * STA support num.
- */
+ * It will cost memory * STA support num. */
/* 2011/10/20 MH Add for ODM STA info. */
/* Driver Write */
u8 bValid; /* record the sta status link or not? */
@@ -312,11 +323,9 @@ struct sta_priv {
struct sta_info *sta_aid[NUM_STA];
u16 sta_dz_bitmap;/* only support 15 stations, station aid bitmap
- * for sleeping sta.
- */
+ * for sleeping sta. */
u16 tim_bitmap; /* only support 15 stations, aid=0~15 mapping
- * bit0~bit15
- */
+ * bit0~bit15 */
u16 max_num_sta;
@@ -341,19 +350,19 @@ static inline u32 wifi_mac_hash(u8 *mac)
return x;
}
-u32 _rtw_init_sta_priv(struct sta_priv *pstapriv);
-u32 _rtw_free_sta_priv(struct sta_priv *pstapriv);
+extern u32 _rtw_init_sta_priv(struct sta_priv *pstapriv);
+extern u32 _rtw_free_sta_priv(struct sta_priv *pstapriv);
#define stainfo_offset_valid(offset) (offset < NUM_STA && offset >= 0)
int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta);
struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int off);
-struct sta_info *rtw_alloc_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
-u32 rtw_free_stainfo(struct adapter *adapt, struct sta_info *psta);
-void rtw_free_all_stainfo(struct adapter *adapt);
-struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
-u32 rtw_init_bcmc_stainfo(struct adapter *adapt);
-struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter);
-bool rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
+extern struct sta_info *rtw_alloc_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
+extern u32 rtw_free_stainfo(struct adapter *adapt, struct sta_info *psta);
+extern void rtw_free_all_stainfo(struct adapter *adapt);
+extern struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
+extern u32 rtw_init_bcmc_stainfo(struct adapter *adapt);
+extern struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter);
+extern u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
#endif /* _STA_INFO_H_ */
diff --git a/drivers/staging/r8188eu/include/usb_ops.h b/drivers/staging/r8188eu/include/usb_ops.h
new file mode 100644
index 000000000000..c53cc54b6b87
--- /dev/null
+++ b/drivers/staging/r8188eu/include/usb_ops.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __USB_OPS_H_
+#define __USB_OPS_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+#include "osdep_intf.h"
+
+#define REALTEK_USB_VENQT_READ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
+#define REALTEK_USB_VENQT_WRITE (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
+#define REALTEK_USB_VENQT_CMD_REQ 0x05
+#define REALTEK_USB_VENQT_CMD_IDX 0x00
+
+#define ALIGNMENT_UNIT 16
+#define MAX_VENDOR_REQ_CMD_SIZE 254 /* 8188cu SIE Support */
+#define MAX_USB_IO_CTL_SIZE (MAX_VENDOR_REQ_CMD_SIZE + ALIGNMENT_UNIT)
+
+#include "usb_ops_linux.h"
+
+void rtl8188eu_set_hw_type(struct adapter *padapter);
+#define hal_set_hw_type rtl8188eu_set_hw_type
+void rtl8188eu_set_intf_ops(struct _io_ops *pops);
+#define usb_set_intf_ops rtl8188eu_set_intf_ops
+
+/*
+ * Increase and check if the continual_urb_error of this @param dvobjprivei
+ * is larger than MAX_CONTINUAL_URB_ERR
+ * @return true:
+ * @return false:
+ */
+static inline int rtw_inc_and_chk_continual_urb_error(struct dvobj_priv *dvobj)
+{
+ int ret = false;
+ int value;
+ value = atomic_inc_return(&dvobj->continual_urb_error);
+ if (value > MAX_CONTINUAL_URB_ERR) {
+ DBG_88E("[dvobj:%p][ERROR] continual_urb_error:%d > %d\n",
+ dvobj, value, MAX_CONTINUAL_URB_ERR);
+ ret = true;
+ }
+ return ret;
+}
+
+/*
+* Set the continual_urb_error of this @param dvobjprive to 0
+*/
+static inline void rtw_reset_continual_urb_error(struct dvobj_priv *dvobj)
+{
+ atomic_set(&dvobj->continual_urb_error, 0);
+}
+
+#define USB_HIGH_SPEED_BULK_SIZE 512
+#define USB_FULL_SPEED_BULK_SIZE 64
+
+static inline u8 rtw_usb_bulk_size_boundary(struct adapter *padapter,
+ int buf_len)
+{
+ u8 rst = true;
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+
+ if (pdvobjpriv->ishighspeed)
+ rst = (0 == (buf_len) % USB_HIGH_SPEED_BULK_SIZE) ?
+ true : false;
+ else
+ rst = (0 == (buf_len) % USB_FULL_SPEED_BULK_SIZE) ?
+ true : false;
+ return rst;
+}
+
+#endif /* __USB_OPS_H_ */
diff --git a/drivers/staging/r8188eu/include/usb_ops_linux.h b/drivers/staging/r8188eu/include/usb_ops_linux.h
new file mode 100644
index 000000000000..c357a3b1560e
--- /dev/null
+++ b/drivers/staging/r8188eu/include/usb_ops_linux.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __USB_OPS_LINUX_H__
+#define __USB_OPS_LINUX_H__
+
+#define VENDOR_CMD_MAX_DATA_LEN 254
+
+#define RTW_USB_CONTROL_MSG_TIMEOUT_TEST 10/* ms */
+#define RTW_USB_CONTROL_MSG_TIMEOUT 500/* ms */
+
+#define MAX_USBCTRL_VENDORREQ_TIMES 10
+
+#define RTW_USB_BULKOUT_TIME 5000/* ms */
+
+#define _usbctrl_vendorreq_async_callback(urb, regs) \
+ _usbctrl_vendorreq_async_callback(urb)
+#define usb_bulkout_zero_complete(purb, regs) \
+ usb_bulkout_zero_complete(purb)
+#define usb_write_mem_complete(purb, regs) \
+ usb_write_mem_complete(purb)
+#define usb_write_port_complete(purb, regs) \
+ usb_write_port_complete(purb)
+#define usb_read_port_complete(purb, regs) \
+ usb_read_port_complete(purb)
+#define usb_read_interrupt_complete(purb, regs) \
+ usb_read_interrupt_complete(purb)
+
+unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr);
+
+void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem);
+void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem);
+
+void usb_read_port_cancel(struct intf_hdl *pintfhdl);
+
+u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem);
+void usb_write_port_cancel(struct intf_hdl *pintfhdl);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/usb_osintf.h b/drivers/staging/r8188eu/include/usb_osintf.h
new file mode 100644
index 000000000000..d1a1f739309c
--- /dev/null
+++ b/drivers/staging/r8188eu/include/usb_osintf.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __USB_OSINTF_H
+#define __USB_OSINTF_H
+
+#include "osdep_service.h"
+#include "drv_types.h"
+#include "usb_vendor_req.h"
+
+extern char *rtw_initmac;
+extern int rtw_mc2u_disable;
+
+#define USBD_HALTED(Status) ((u32)(Status) >> 30 == 3)
+
+u8 usbvendorrequest(struct dvobj_priv *pdvobjpriv, enum bt_usb_request brequest,
+ enum rt_usb_wvalue wvalue, u8 windex, void *data,
+ u8 datalen, u8 isdirectionin);
+int pm_netdev_open(struct net_device *pnetdev, u8 bnormal);
+void netdev_br_init(struct net_device *netdev);
+void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb);
+void *scdb_findEntry(struct adapter *priv, unsigned char *macAddr,
+ unsigned char *ipAddr);
+void nat25_db_expire(struct adapter *priv);
+int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method);
+
+int rtw_resume_process(struct adapter *padapter);
+
+#endif
diff --git a/drivers/staging/r8188eu/include/usb_vendor_req.h b/drivers/staging/r8188eu/include/usb_vendor_req.h
new file mode 100644
index 000000000000..7337b1b7419f
--- /dev/null
+++ b/drivers/staging/r8188eu/include/usb_vendor_req.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef _USB_VENDOR_REQUEST_H_
+#define _USB_VENDOR_REQUEST_H_
+
+/* 4 Set/Get Register related wIndex/Data */
+#define RT_USB_RESET_MASK_OFF 0
+#define RT_USB_RESET_MASK_ON 1
+#define RT_USB_SLEEP_MASK_OFF 0
+#define RT_USB_SLEEP_MASK_ON 1
+#define RT_USB_LDO_ON 1
+#define RT_USB_LDO_OFF 0
+
+/* 4 Set/Get SYSCLK related wValue or Data */
+#define RT_USB_SYSCLK_32KHZ 0
+#define RT_USB_SYSCLK_40MHZ 1
+#define RT_USB_SYSCLK_60MHZ 2
+
+enum bt_usb_request {
+ RT_USB_SET_REGISTER = 1,
+ RT_USB_SET_SYSCLK = 2,
+ RT_USB_GET_SYSCLK = 3,
+ RT_USB_GET_REGISTER = 4
+};
+
+enum rt_usb_wvalue {
+ RT_USB_RESET_MASK = 1,
+ RT_USB_SLEEP_MASK = 2,
+ RT_USB_USB_HRCPWM = 3,
+ RT_USB_LDO = 4,
+ RT_USB_BOOT_TYPE = 5
+};
+
+#endif
diff --git a/drivers/staging/r8188eu/include/wifi.h b/drivers/staging/r8188eu/include/wifi.h
new file mode 100644
index 000000000000..0b3fd94cea18
--- /dev/null
+++ b/drivers/staging/r8188eu/include/wifi.h
@@ -0,0 +1,1029 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#ifndef _WIFI_H_
+#define _WIFI_H_
+
+#include <linux/ieee80211.h>
+
+#ifdef BIT
+/* error "BIT define occurred earlier elsewhere!\n" */
+#undef BIT
+#endif
+#define BIT(x) (1 << (x))
+
+#define WLAN_ETHHDR_LEN 14
+#define WLAN_ETHADDR_LEN 6
+#define WLAN_IEEE_OUI_LEN 3
+#define WLAN_ADDR_LEN 6
+#define WLAN_CRC_LEN 4
+#define WLAN_BSSID_LEN 6
+#define WLAN_BSS_TS_LEN 8
+#define WLAN_HDR_A3_LEN 24
+#define WLAN_HDR_A4_LEN 30
+#define WLAN_HDR_A3_QOS_LEN 26
+#define WLAN_HDR_A4_QOS_LEN 32
+#define WLAN_SSID_MAXLEN 32
+#define WLAN_DATA_MAXLEN 2312
+
+#define WLAN_A3_PN_OFFSET 24
+#define WLAN_A4_PN_OFFSET 30
+
+#define WLAN_MIN_ETHFRM_LEN 60
+#define WLAN_MAX_ETHFRM_LEN 1514
+#define WLAN_ETHHDR_LEN 14
+
+#define P80211CAPTURE_VERSION 0x80211001
+
+/* This value is tested by WiFi 11n Test Plan 5.2.3. */
+/* This test verifies the WLAN NIC can update the NAV through sending
+ * the CTS with large duration. */
+#define WiFiNavUpperUs 30000 /* 30 ms */
+
+enum WIFI_FRAME_TYPE {
+ WIFI_MGT_TYPE = (0),
+ WIFI_CTRL_TYPE = (BIT(2)),
+ WIFI_DATA_TYPE = (BIT(3)),
+ WIFI_QOS_DATA_TYPE = (BIT(7)|BIT(3)), /* QoS Data */
+};
+
+enum WIFI_FRAME_SUBTYPE {
+ /* below is for mgt frame */
+ WIFI_ASSOCREQ = (0 | WIFI_MGT_TYPE),
+ WIFI_ASSOCRSP = (BIT(4) | WIFI_MGT_TYPE),
+ WIFI_REASSOCREQ = (BIT(5) | WIFI_MGT_TYPE),
+ WIFI_REASSOCRSP = (BIT(5) | BIT(4) | WIFI_MGT_TYPE),
+ WIFI_PROBEREQ = (BIT(6) | WIFI_MGT_TYPE),
+ WIFI_PROBERSP = (BIT(6) | BIT(4) | WIFI_MGT_TYPE),
+ WIFI_BEACON = (BIT(7) | WIFI_MGT_TYPE),
+ WIFI_ATIM = (BIT(7) | BIT(4) | WIFI_MGT_TYPE),
+ WIFI_DISASSOC = (BIT(7) | BIT(5) | WIFI_MGT_TYPE),
+ WIFI_AUTH = (BIT(7) | BIT(5) | BIT(4) | WIFI_MGT_TYPE),
+ WIFI_DEAUTH = (BIT(7) | BIT(6) | WIFI_MGT_TYPE),
+ WIFI_ACTION = (BIT(7) | BIT(6) | BIT(4) | WIFI_MGT_TYPE),
+
+ /* below is for control frame */
+ WIFI_PSPOLL = (BIT(7) | BIT(5) | WIFI_CTRL_TYPE),
+ WIFI_RTS = (BIT(7) | BIT(5) | BIT(4) | WIFI_CTRL_TYPE),
+ WIFI_CTS = (BIT(7) | BIT(6) | WIFI_CTRL_TYPE),
+ WIFI_ACK = (BIT(7) | BIT(6) | BIT(4) | WIFI_CTRL_TYPE),
+ WIFI_CFEND = (BIT(7) | BIT(6) | BIT(5) | WIFI_CTRL_TYPE),
+ WIFI_CFEND_CFACK = (BIT(7) | BIT(6) | BIT(5) | BIT(4) |
+ WIFI_CTRL_TYPE),
+
+ /* below is for data frame */
+ WIFI_DATA = (0 | WIFI_DATA_TYPE),
+ WIFI_DATA_CFACK = (BIT(4) | WIFI_DATA_TYPE),
+ WIFI_DATA_CFPOLL = (BIT(5) | WIFI_DATA_TYPE),
+ WIFI_DATA_CFACKPOLL = (BIT(5) | BIT(4) | WIFI_DATA_TYPE),
+ WIFI_DATA_NULL = (BIT(6) | WIFI_DATA_TYPE),
+ WIFI_CF_ACK = (BIT(6) | BIT(4) | WIFI_DATA_TYPE),
+ WIFI_CF_POLL = (BIT(6) | BIT(5) | WIFI_DATA_TYPE),
+ WIFI_CF_ACKPOLL = (BIT(6) | BIT(5) | BIT(4) | WIFI_DATA_TYPE),
+ WIFI_QOS_DATA_NULL = (BIT(6) | WIFI_QOS_DATA_TYPE),
+};
+
+enum WIFI_REASON_CODE {
+ _RSON_RESERVED_ = 0,
+ _RSON_UNSPECIFIED_ = 1,
+ _RSON_AUTH_NO_LONGER_VALID_ = 2,
+ _RSON_DEAUTH_STA_LEAVING_ = 3,
+ _RSON_INACTIVITY_ = 4,
+ _RSON_UNABLE_HANDLE_ = 5,
+ _RSON_CLS2_ = 6,
+ _RSON_CLS3_ = 7,
+ _RSON_DISAOC_STA_LEAVING_ = 8,
+ _RSON_ASOC_NOT_AUTH_ = 9,
+
+ /* WPA reason */
+ _RSON_INVALID_IE_ = 13,
+ _RSON_MIC_FAILURE_ = 14,
+ _RSON_4WAY_HNDSHK_TIMEOUT_ = 15,
+ _RSON_GROUP_KEY_UPDATE_TIMEOUT_ = 16,
+ _RSON_DIFF_IE_ = 17,
+ _RSON_MLTCST_CIPHER_NOT_VALID_ = 18,
+ _RSON_UNICST_CIPHER_NOT_VALID_ = 19,
+ _RSON_AKMP_NOT_VALID_ = 20,
+ _RSON_UNSUPPORT_RSNE_VER_ = 21,
+ _RSON_INVALID_RSNE_CAP_ = 22,
+ _RSON_IEEE_802DOT1X_AUTH_FAIL_ = 23,
+
+ /* belowing are Realtek definition */
+ _RSON_PMK_NOT_AVAILABLE_ = 24,
+ _RSON_TDLS_TEAR_TOOFAR_ = 25,
+ _RSON_TDLS_TEAR_UN_RSN_ = 26,
+};
+
+/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22)
+
+#define WLAN_REASON_UNSPECIFIED 1
+#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define WLAN_REASON_DEAUTH_LEAVING 3
+#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define WLAN_REASON_DISASSOC_AP_BUSY 5
+#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
+#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
+#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
+#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 */
+/* IEEE 802.11h */
+#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10
+#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
+
+/* IEEE 802.11i
+#define WLAN_REASON_INVALID_IE 13
+#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
+#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
+#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
+#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17
+#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18
+#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19
+#define WLAN_REASON_AKMP_NOT_VALID 20
+#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21
+#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
+#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
+#define WLAN_REASON_CIPHER_SUITE_REJECTED 24 */
+
+enum WIFI_STATUS_CODE {
+ _STATS_SUCCESSFUL_ = 0,
+ _STATS_FAILURE_ = 1,
+ _STATS_CAP_FAIL_ = 10,
+ _STATS_NO_ASOC_ = 11,
+ _STATS_OTHER_ = 12,
+ _STATS_NO_SUPP_ALG_ = 13,
+ _STATS_OUT_OF_AUTH_SEQ_ = 14,
+ _STATS_CHALLENGE_FAIL_ = 15,
+ _STATS_AUTH_TIMEOUT_ = 16,
+ _STATS_UNABLE_HANDLE_STA_ = 17,
+ _STATS_RATE_FAIL_ = 18,
+};
+
+/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23)
+#define WLAN_STATUS_SUCCESS 0
+#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
+#define WLAN_STATUS_CAPS_UNSUPPORTED 10
+#define WLAN_STATUS_REASSOC_NO_ASSOC 11
+#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
+#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
+#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
+#define WLAN_STATUS_CHALLENGE_FAIL 15
+#define WLAN_STATUS_AUTH_TIMEOUT 16
+#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
+#define WLAN_STATUS_ASSOC_DENIED_RATES 18 */
+
+/* entended */
+/* IEEE 802.11b */
+#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
+#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
+#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
+/* IEEE 802.11h */
+#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22
+#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23
+#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
+/* IEEE 802.11g */
+#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
+#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
+#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
+/* IEEE 802.11w */
+#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
+#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
+/* IEEE 802.11i */
+#define WLAN_STATUS_INVALID_IE 40
+#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
+#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
+#define WLAN_STATUS_AKMP_NOT_VALID 43
+#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
+#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45
+#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46
+#define WLAN_STATUS_TS_NOT_CREATED 47
+#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48
+#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
+#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50
+#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
+/* IEEE 802.11r */
+#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
+#define WLAN_STATUS_INVALID_PMKID 53
+#define WLAN_STATUS_INVALID_MDIE 54
+#define WLAN_STATUS_INVALID_FTIE 55
+
+enum WIFI_REG_DOMAIN {
+ DOMAIN_FCC = 1,
+ DOMAIN_IC = 2,
+ DOMAIN_ETSI = 3,
+ DOMAIN_SPA = 4,
+ DOMAIN_FRANCE = 5,
+ DOMAIN_MKK = 6,
+ DOMAIN_ISRAEL = 7,
+ DOMAIN_MKK1 = 8,
+ DOMAIN_MKK2 = 9,
+ DOMAIN_MKK3 = 10,
+ DOMAIN_MAX
+};
+
+#define _TO_DS_ BIT(8)
+#define _FROM_DS_ BIT(9)
+#define _MORE_FRAG_ BIT(10)
+#define _RETRY_ BIT(11)
+#define _PWRMGT_ BIT(12)
+#define _MORE_DATA_ BIT(13)
+#define _PRIVACY_ BIT(14)
+#define _ORDER_ BIT(15)
+
+#define SetToDs(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_TO_DS_)
+
+#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_TO_DS_)) != 0)
+
+#define ClearToDs(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_TO_DS_))
+
+#define SetFrDs(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_FROM_DS_)
+
+#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_FROM_DS_)) != 0)
+
+#define ClearFrDs(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_FROM_DS_))
+
+#define get_tofr_ds(pframe) ((GetToDs(pframe) << 1) | GetFrDs(pframe))
+
+#define SetMFrag(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_FRAG_)
+
+#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_MORE_FRAG_)) != 0)
+
+#define ClearMFrag(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_FRAG_))
+
+#define SetRetry(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_RETRY_)
+
+#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_RETRY_)) != 0)
+
+#define ClearRetry(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_RETRY_))
+
+#define SetPwrMgt(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_PWRMGT_)
+
+#define GetPwrMgt(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_PWRMGT_)) != 0)
+
+#define ClearPwrMgt(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_PWRMGT_))
+
+#define SetMData(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_DATA_)
+
+#define GetMData(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_MORE_DATA_)) != 0)
+
+#define ClearMData(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_DATA_))
+
+#define SetPrivacy(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_PRIVACY_)
+
+#define GetPrivacy(pbuf) \
+ (((*(__le16 *)(pbuf)) & cpu_to_le16(_PRIVACY_)) != 0)
+
+#define ClearPrivacy(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_PRIVACY_))
+
+#define GetOrder(pbuf) \
+ (((*(__le16 *)(pbuf)) & cpu_to_le16(_ORDER_)) != 0)
+
+#define GetFrameType(pbuf) \
+ (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(3) | BIT(2)))
+
+#define SetFrameType(pbuf, type) \
+ do { \
+ *(unsigned short *)(pbuf) &= __constant_cpu_to_le16(~(BIT(3) | BIT(2))); \
+ *(unsigned short *)(pbuf) |= __constant_cpu_to_le16(type); \
+ } while (0)
+
+#define GetFrameSubType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(7) |\
+ BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2)))
+
+#define SetFrameSubType(pbuf, type) \
+ do { \
+ *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(7) | BIT(6) | \
+ BIT(5) | BIT(4) | BIT(3) | BIT(2))); \
+ *(__le16 *)(pbuf) |= cpu_to_le16(type); \
+ } while (0)
+
+#define GetSequence(pbuf) \
+ (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) >> 4)
+
+#define GetFragNum(pbuf) \
+ (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) & 0x0f)
+
+#define GetTupleCache(pbuf) \
+ (cpu_to_le16(*(unsigned short *)((size_t)(pbuf) + 22)))
+
+#define SetFragNum(pbuf, num) \
+ do { \
+ *(unsigned short *)((size_t)(pbuf) + 22) = \
+ ((*(unsigned short *)((size_t)(pbuf) + 22)) & \
+ le16_to_cpu(~(0x000f))) | \
+ cpu_to_le16(0x0f & (num)); \
+ } while (0)
+
+#define SetSeqNum(pbuf, num) \
+ do { \
+ *(__le16 *)((size_t)(pbuf) + 22) = \
+ ((*(__le16 *)((size_t)(pbuf) + 22)) & cpu_to_le16((unsigned short)0x000f)) | \
+ cpu_to_le16((unsigned short)(0xfff0 & (num << 4))); \
+ } while (0)
+
+#define SetDuration(pbuf, dur) \
+ *(__le16 *)((size_t)(pbuf) + 2) = cpu_to_le16(0xffff & (dur))
+
+#define SetPriority(pbuf, tid) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf)
+
+#define GetPriority(pbuf) ((le16_to_cpu(*(__le16 *)(pbuf))) & 0xf)
+
+#define SetEOSP(pbuf, eosp) \
+ *(__le16 *)(pbuf) |= cpu_to_le16((eosp & 1) << 4)
+
+#define SetAckpolicy(pbuf, ack) \
+ *(__le16 *)(pbuf) |= cpu_to_le16((ack & 3) << 5)
+
+#define GetAckpolicy(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 5) & 0x3)
+
+#define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1)
+
+#define SetAMsdu(pbuf, amsdu) \
+ *(__le16 *)(pbuf) |= cpu_to_le16((amsdu & 1) << 7)
+
+#define GetAid(pbuf) (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 2)) & 0x3fff)
+
+#define GetTid(pbuf) (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + \
+ (((GetToDs(pbuf)<<1) | GetFrDs(pbuf)) == 3 ? \
+ 30 : 24))) & 0x000f)
+
+#define GetAddr1Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 4))
+
+#define GetAddr2Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 10))
+
+#define GetAddr3Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 16))
+
+#define GetAddr4Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 24))
+
+static inline int IS_MCAST(unsigned char *da)
+{
+ if ((*da) & 0x01)
+ return true;
+ else
+ return false;
+}
+
+static inline unsigned char *get_da(unsigned char *pframe)
+{
+ unsigned char *da;
+ unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
+
+ switch (to_fr_ds) {
+ case 0x00: /* ToDs=0, FromDs=0 */
+ da = GetAddr1Ptr(pframe);
+ break;
+ case 0x01: /* ToDs=0, FromDs=1 */
+ da = GetAddr1Ptr(pframe);
+ break;
+ case 0x02: /* ToDs=1, FromDs=0 */
+ da = GetAddr3Ptr(pframe);
+ break;
+ default: /* ToDs=1, FromDs=1 */
+ da = GetAddr3Ptr(pframe);
+ break;
+ }
+ return da;
+}
+
+static inline unsigned char *get_sa(unsigned char *pframe)
+{
+ unsigned char *sa;
+ unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
+
+ switch (to_fr_ds) {
+ case 0x00: /* ToDs=0, FromDs=0 */
+ sa = GetAddr2Ptr(pframe);
+ break;
+ case 0x01: /* ToDs=0, FromDs=1 */
+ sa = GetAddr3Ptr(pframe);
+ break;
+ case 0x02: /* ToDs=1, FromDs=0 */
+ sa = GetAddr2Ptr(pframe);
+ break;
+ default: /* ToDs=1, FromDs=1 */
+ sa = GetAddr4Ptr(pframe);
+ break;
+ }
+ return sa;
+}
+
+static inline unsigned char *get_hdr_bssid(unsigned char *pframe)
+{
+ unsigned char *sa;
+ unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
+
+ switch (to_fr_ds) {
+ case 0x00: /* ToDs=0, FromDs=0 */
+ sa = GetAddr3Ptr(pframe);
+ break;
+ case 0x01: /* ToDs=0, FromDs=1 */
+ sa = GetAddr2Ptr(pframe);
+ break;
+ case 0x02: /* ToDs=1, FromDs=0 */
+ sa = GetAddr1Ptr(pframe);
+ break;
+ case 0x03: /* ToDs=1, FromDs=1 */
+ sa = GetAddr1Ptr(pframe);
+ break;
+ default:
+ sa = NULL; /* */
+ break;
+ }
+ return sa;
+}
+
+static inline int IsFrameTypeCtrl(unsigned char *pframe)
+{
+ if (WIFI_CTRL_TYPE == GetFrameType(pframe))
+ return true;
+ else
+ return false;
+}
+/*-----------------------------------------------------------------------------
+ Below is for the security related definition
+------------------------------------------------------------------------------*/
+#define _RESERVED_FRAME_TYPE_ 0
+#define _SKB_FRAME_TYPE_ 2
+#define _PRE_ALLOCMEM_ 1
+#define _PRE_ALLOCHDR_ 3
+#define _PRE_ALLOCLLCHDR_ 4
+#define _PRE_ALLOCICVHDR_ 5
+#define _PRE_ALLOCMICHDR_ 6
+
+#define _SIFSTIME_ \
+ (priv->pmib->dot11BssType.net_work_type = 10)
+#define _ACKCTSLNG_ 14 /* 14 bytes long, including crclng */
+#define _CRCLNG_ 4
+
+#define _ASOCREQ_IE_OFFSET_ 4 /* excluding wlan_hdr */
+#define _ASOCRSP_IE_OFFSET_ 6
+#define _REASOCREQ_IE_OFFSET_ 10
+#define _REASOCRSP_IE_OFFSET_ 6
+#define _PROBEREQ_IE_OFFSET_ 0
+#define _PROBERSP_IE_OFFSET_ 12
+#define _AUTH_IE_OFFSET_ 6
+#define _DEAUTH_IE_OFFSET_ 0
+#define _BEACON_IE_OFFSET_ 12
+#define _PUBLIC_ACTION_IE_OFFSET_ 8
+
+#define _FIXED_IE_LENGTH_ _BEACON_IE_OFFSET_
+
+#define _SSID_IE_ 0
+#define _SUPPORTEDRATES_IE_ 1
+#define _DSSET_IE_ 3
+#define _TIM_IE_ 5
+#define _IBSS_PARA_IE_ 6
+#define _COUNTRY_IE_ 7
+#define _CHLGETXT_IE_ 16
+#define _SUPPORTED_CH_IE_ 36
+#define _CH_SWTICH_ANNOUNCE_ 37 /* Secondary Channel Offset */
+#define _RSN_IE_2_ 48
+#define _SSN_IE_1_ 221
+#define _ERPINFO_IE_ 42
+#define _EXT_SUPPORTEDRATES_IE_ 50
+
+#define _HT_CAPABILITY_IE_ 45
+#define _FTIE_ 55
+#define _TIMEOUT_ITVL_IE_ 56
+#define _SRC_IE_ 59
+#define _HT_EXTRA_INFO_IE_ 61
+#define _HT_ADD_INFO_IE_ 61 /* _HT_EXTRA_INFO_IE_ */
+#define _WAPI_IE_ 68
+
+#define EID_BSSCoexistence 72 /* 20/40 BSS Coexistence */
+#define EID_BSSIntolerantChlReport 73
+#define _RIC_Descriptor_IE_ 75
+
+#define _LINK_ID_IE_ 101
+#define _CH_SWITCH_TIMING_ 104
+#define _PTI_BUFFER_STATUS_ 106
+#define _EXT_CAP_IE_ 127
+#define _VENDOR_SPECIFIC_IE_ 221
+
+#define _RESERVED47_ 47
+
+/* ---------------------------------------------------------------------------
+ Below is the fixed elements...
+-----------------------------------------------------------------------------*/
+#define _AUTH_ALGM_NUM_ 2
+#define _AUTH_SEQ_NUM_ 2
+#define _BEACON_ITERVAL_ 2
+#define _CAPABILITY_ 2
+#define _CURRENT_APADDR_ 6
+#define _LISTEN_INTERVAL_ 2
+#define _RSON_CODE_ 2
+#define _ASOC_ID_ 2
+#define _STATUS_CODE_ 2
+#define _TIMESTAMP_ 8
+
+#define AUTH_ODD_TO 0
+#define AUTH_EVEN_TO 1
+
+#define WLAN_ETHCONV_ENCAP 1
+#define WLAN_ETHCONV_RFC1042 2
+#define WLAN_ETHCONV_8021h 3
+
+#define cap_ESS BIT(0)
+#define cap_IBSS BIT(1)
+#define cap_CFPollable BIT(2)
+#define cap_CFRequest BIT(3)
+#define cap_Privacy BIT(4)
+#define cap_ShortPremble BIT(5)
+#define cap_PBCC BIT(6)
+#define cap_ChAgility BIT(7)
+#define cap_SpecMgmt BIT(8)
+#define cap_QoSi BIT(9)
+#define cap_ShortSlot BIT(10)
+
+/*-----------------------------------------------------------------------------
+ Below is the definition for 802.11i / 802.1x
+------------------------------------------------------------------------------*/
+#define _IEEE8021X_MGT_ 1 /* WPA */
+#define _IEEE8021X_PSK_ 2 /* WPA with pre-shared key */
+
+/*
+#define _NO_PRIVACY_ 0
+#define _WEP_40_PRIVACY_ 1
+#define _TKIP_PRIVACY_ 2
+#define _WRAP_PRIVACY_ 3
+#define _CCMP_PRIVACY_ 4
+#define _WEP_104_PRIVACY_ 5
+#define _WEP_WPA_MIXED_PRIVACY_ 6 WEP + WPA
+*/
+
+/*-----------------------------------------------------------------------------
+ Below is the definition for WMM
+------------------------------------------------------------------------------*/
+#define _WMM_IE_Length_ 7 /* for WMM STA */
+#define _WMM_Para_Element_Length_ 24
+
+/*-----------------------------------------------------------------------------
+ Below is the definition for 802.11n
+------------------------------------------------------------------------------*/
+
+#define SetOrderBit(pbuf) \
+ do { \
+ *(unsigned short *)(pbuf) |= cpu_to_le16(_ORDER_); \
+ } while (0)
+
+#define GetOrderBit(pbuf) \
+ (((*(unsigned short *)(pbuf)) & le16_to_cpu(_ORDER_)) != 0)
+
+/**
+ * struct rtw_ieee80211_bar - HT Block Ack Request
+ *
+ * This structure refers to "HT BlockAckReq" as
+ * described in 802.11n draft section 7.2.1.7.1
+ */
+struct rtw_ieee80211_bar {
+ __le16 frame_control;
+ __le16 duration;
+ unsigned char ra[ETH_ALEN];
+ unsigned char ta[ETH_ALEN];
+ __le16 control;
+ __le16 start_seq_num;
+} __packed;
+
+/**
+ * struct ieee80211_ht_cap - HT additional information
+ *
+ * This structure refers to "HT information element" as
+ * described in 802.11n draft section 7.3.2.53
+ */
+struct ieee80211_ht_addt_info {
+ unsigned char control_chan;
+ unsigned char ht_param;
+ __le16 operation_mode;
+ __le16 stbc_param;
+ unsigned char basic_set[16];
+} __packed;
+
+struct HT_caps_element {
+ union {
+ struct {
+ __le16 HT_caps_info;
+ unsigned char AMPDU_para;
+ unsigned char MCS_rate[16];
+ __le16 HT_ext_caps;
+ __le16 Beamforming_caps;
+ unsigned char ASEL_caps;
+ } HT_cap_element;
+ unsigned char HT_cap[26];
+ } u;
+} __packed;
+
+struct HT_info_element {
+ unsigned char primary_channel;
+ unsigned char infos[5];
+ unsigned char MCS_rate[16];
+} __packed;
+
+struct AC_param {
+ unsigned char ACI_AIFSN;
+ unsigned char CW;
+ __le16 TXOP_limit;
+} __packed;
+
+struct WMM_para_element {
+ unsigned char QoS_info;
+ unsigned char reserved;
+ struct AC_param ac_param[4];
+} __packed;
+
+struct ADDBA_request {
+ unsigned char action_code;
+ unsigned char dialog_token;
+ __le16 BA_para_set;
+ __le16 BA_timeout_value;
+ __le16 BA_starting_seqctrl;
+} __packed;
+
+enum ht_cap_ampdu_factor {
+ MAX_AMPDU_FACTOR_8K = 0,
+ MAX_AMPDU_FACTOR_16K = 1,
+ MAX_AMPDU_FACTOR_32K = 2,
+ MAX_AMPDU_FACTOR_64K = 3,
+};
+
+/* Spatial Multiplexing Power Save Modes */
+#define WLAN_HT_CAP_SM_PS_STATIC 0
+#define WLAN_HT_CAP_SM_PS_DYNAMIC 1
+#define WLAN_HT_CAP_SM_PS_INVALID 2
+#define WLAN_HT_CAP_SM_PS_DISABLED 3
+
+#define OP_MODE_PURE 0
+#define OP_MODE_MAY_BE_LEGACY_STAS 1
+#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
+#define OP_MODE_MIXED 3
+
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1))
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0))
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1))
+#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2))
+#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3))
+#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4))
+#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5))
+
+#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
+ ((u16) (0x0001 | 0x0002))
+#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
+#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2))
+#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))
+#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4))
+
+#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6))
+#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7))
+#define HT_INFO_STBC_PARAM_SECONDARY_BC ((u16) BIT(8))
+#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9))
+#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
+#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
+
+/* ===============WPS Section=============== */
+/* For WPSv1.0 */
+#define WPSOUI 0x0050f204
+/* WPS attribute ID */
+#define WPS_ATTR_VER1 0x104A
+#define WPS_ATTR_SIMPLE_CONF_STATE 0x1044
+#define WPS_ATTR_RESP_TYPE 0x103B
+#define WPS_ATTR_UUID_E 0x1047
+#define WPS_ATTR_MANUFACTURER 0x1021
+#define WPS_ATTR_MODEL_NAME 0x1023
+#define WPS_ATTR_MODEL_NUMBER 0x1024
+#define WPS_ATTR_SERIAL_NUMBER 0x1042
+#define WPS_ATTR_PRIMARY_DEV_TYPE 0x1054
+#define WPS_ATTR_SEC_DEV_TYPE_LIST 0x1055
+#define WPS_ATTR_DEVICE_NAME 0x1011
+#define WPS_ATTR_CONF_METHOD 0x1008
+#define WPS_ATTR_RF_BANDS 0x103C
+#define WPS_ATTR_DEVICE_PWID 0x1012
+#define WPS_ATTR_REQUEST_TYPE 0x103A
+#define WPS_ATTR_ASSOCIATION_STATE 0x1002
+#define WPS_ATTR_CONFIG_ERROR 0x1009
+#define WPS_ATTR_VENDOR_EXT 0x1049
+#define WPS_ATTR_SELECTED_REGISTRAR 0x1041
+
+/* Value of WPS attribute "WPS_ATTR_DEVICE_NAME */
+#define WPS_MAX_DEVICE_NAME_LEN 32
+
+/* Value of WPS Request Type Attribute */
+#define WPS_REQ_TYPE_ENROLLEE_INFO_ONLY 0x00
+#define WPS_REQ_TYPE_ENROLLEE_OPEN_8021X 0x01
+#define WPS_REQ_TYPE_REGISTRAR 0x02
+#define WPS_REQ_TYPE_WLAN_MANAGER_REGISTRAR 0x03
+
+/* Value of WPS Response Type Attribute */
+#define WPS_RESPONSE_TYPE_INFO_ONLY 0x00
+#define WPS_RESPONSE_TYPE_8021X 0x01
+#define WPS_RESPONSE_TYPE_REGISTRAR 0x02
+#define WPS_RESPONSE_TYPE_AP 0x03
+
+/* Value of WPS WiFi Simple Configuration State Attribute */
+#define WPS_WSC_STATE_NOT_CONFIG 0x01
+#define WPS_WSC_STATE_CONFIG 0x02
+
+/* Value of WPS Version Attribute */
+#define WPS_VERSION_1 0x10
+
+/* Value of WPS Configuration Method Attribute */
+#define WPS_CONFIG_METHOD_FLASH 0x0001
+#define WPS_CONFIG_METHOD_ETHERNET 0x0002
+#define WPS_CONFIG_METHOD_LABEL 0x0004
+#define WPS_CONFIG_METHOD_DISPLAY 0x0008
+#define WPS_CONFIG_METHOD_E_NFC 0x0010
+#define WPS_CONFIG_METHOD_I_NFC 0x0020
+#define WPS_CONFIG_METHOD_NFC 0x0040
+#define WPS_CONFIG_METHOD_PBC 0x0080
+#define WPS_CONFIG_METHOD_KEYPAD 0x0100
+#define WPS_CONFIG_METHOD_VPBC 0x0280
+#define WPS_CONFIG_METHOD_PPBC 0x0480
+#define WPS_CONFIG_METHOD_VDISPLAY 0x2008
+#define WPS_CONFIG_METHOD_PDISPLAY 0x4008
+
+/* Value of Category ID of WPS Primary Device Type Attribute */
+#define WPS_PDT_CID_DISPLAYS 0x0007
+#define WPS_PDT_CID_MULIT_MEDIA 0x0008
+#define WPS_PDT_CID_RTK_WIDI WPS_PDT_CID_MULIT_MEDIA
+
+/* Value of Sub Category ID of WPS Primary Device Type Attribute */
+#define WPS_PDT_SCID_MEDIA_SERVER 0x0005
+#define WPS_PDT_SCID_RTK_DMP WPS_PDT_SCID_MEDIA_SERVER
+
+/* Value of Device Password ID */
+#define WPS_DPID_P 0x0000
+#define WPS_DPID_USER_SPEC 0x0001
+#define WPS_DPID_MACHINE_SPEC 0x0002
+#define WPS_DPID_REKEY 0x0003
+#define WPS_DPID_PBC 0x0004
+#define WPS_DPID_REGISTRAR_SPEC 0x0005
+
+/* Value of WPS RF Bands Attribute */
+#define WPS_RF_BANDS_2_4_GHZ 0x01
+#define WPS_RF_BANDS_5_GHZ 0x02
+
+/* Value of WPS Association State Attribute */
+#define WPS_ASSOC_STATE_NOT_ASSOCIATED 0x00
+#define WPS_ASSOC_STATE_CONNECTION_SUCCESS 0x01
+#define WPS_ASSOC_STATE_CONFIGURATION_FAILURE 0x02
+#define WPS_ASSOC_STATE_ASSOCIATION_FAILURE 0x03
+#define WPS_ASSOC_STATE_IP_FAILURE 0x04
+
+/* =====================P2P Section===================== */
+/* For P2P */
+#define P2POUI 0x506F9A09
+
+/* P2P Attribute ID */
+#define P2P_ATTR_STATUS 0x00
+#define P2P_ATTR_MINOR_REASON_CODE 0x01
+#define P2P_ATTR_CAPABILITY 0x02
+#define P2P_ATTR_DEVICE_ID 0x03
+#define P2P_ATTR_GO_INTENT 0x04
+#define P2P_ATTR_CONF_TIMEOUT 0x05
+#define P2P_ATTR_LISTEN_CH 0x06
+#define P2P_ATTR_GROUP_BSSID 0x07
+#define P2P_ATTR_EX_LISTEN_TIMING 0x08
+#define P2P_ATTR_INTENTED_IF_ADDR 0x09
+#define P2P_ATTR_MANAGEABILITY 0x0A
+#define P2P_ATTR_CH_LIST 0x0B
+#define P2P_ATTR_NOA 0x0C
+#define P2P_ATTR_DEVICE_INFO 0x0D
+#define P2P_ATTR_GROUP_INFO 0x0E
+#define P2P_ATTR_GROUP_ID 0x0F
+#define P2P_ATTR_INTERFACE 0x10
+#define P2P_ATTR_OPERATING_CH 0x11
+#define P2P_ATTR_INVITATION_FLAGS 0x12
+
+/* Value of Status Attribute */
+#define P2P_STATUS_SUCCESS 0x00
+#define P2P_STATUS_FAIL_INFO_UNAVAILABLE 0x01
+#define P2P_STATUS_FAIL_INCOMPATIBLE_PARAM 0x02
+#define P2P_STATUS_FAIL_LIMIT_REACHED 0x03
+#define P2P_STATUS_FAIL_INVALID_PARAM 0x04
+#define P2P_STATUS_FAIL_REQUEST_UNABLE 0x05
+#define P2P_STATUS_FAIL_PREVOUS_PROTO_ERR 0x06
+#define P2P_STATUS_FAIL_NO_COMMON_CH 0x07
+#define P2P_STATUS_FAIL_UNKNOWN_P2PGROUP 0x08
+#define P2P_STATUS_FAIL_BOTH_GOINTENT_15 0x09
+#define P2P_STATUS_FAIL_INCOMPATIBLE_PROVSION 0x0A
+#define P2P_STATUS_FAIL_USER_REJECT 0x0B
+
+/* Value of Inviation Flags Attribute */
+#define P2P_INVITATION_FLAGS_PERSISTENT BIT(0)
+
+#define DMP_P2P_DEVCAP_SUPPORT (P2P_DEVCAP_SERVICE_DISCOVERY | \
+ P2P_DEVCAP_CLIENT_DISCOVERABILITY | \
+ P2P_DEVCAP_CONCURRENT_OPERATION | \
+ P2P_DEVCAP_INVITATION_PROC)
+
+#define DMP_P2P_GRPCAP_SUPPORT (P2P_GRPCAP_INTRABSS)
+
+/* Value of Device Capability Bitmap */
+#define P2P_DEVCAP_SERVICE_DISCOVERY BIT(0)
+#define P2P_DEVCAP_CLIENT_DISCOVERABILITY BIT(1)
+#define P2P_DEVCAP_CONCURRENT_OPERATION BIT(2)
+#define P2P_DEVCAP_INFRA_MANAGED BIT(3)
+#define P2P_DEVCAP_DEVICE_LIMIT BIT(4)
+#define P2P_DEVCAP_INVITATION_PROC BIT(5)
+
+/* Value of Group Capability Bitmap */
+#define P2P_GRPCAP_GO BIT(0)
+#define P2P_GRPCAP_PERSISTENT_GROUP BIT(1)
+#define P2P_GRPCAP_GROUP_LIMIT BIT(2)
+#define P2P_GRPCAP_INTRABSS BIT(3)
+#define P2P_GRPCAP_CROSS_CONN BIT(4)
+#define P2P_GRPCAP_PERSISTENT_RECONN BIT(5)
+#define P2P_GRPCAP_GROUP_FORMATION BIT(6)
+
+/* P2P Public Action Frame (Management Frame) */
+#define P2P_PUB_ACTION_ACTION 0x09
+
+/* P2P Public Action Frame Type */
+#define P2P_GO_NEGO_REQ 0
+#define P2P_GO_NEGO_RESP 1
+#define P2P_GO_NEGO_CONF 2
+#define P2P_INVIT_REQ 3
+#define P2P_INVIT_RESP 4
+#define P2P_DEVDISC_REQ 5
+#define P2P_DEVDISC_RESP 6
+#define P2P_PROVISION_DISC_REQ 7
+#define P2P_PROVISION_DISC_RESP 8
+
+/* P2P Action Frame Type */
+#define P2P_NOTICE_OF_ABSENCE 0
+#define P2P_PRESENCE_REQUEST 1
+#define P2P_PRESENCE_RESPONSE 2
+#define P2P_GO_DISC_REQUEST 3
+
+#define P2P_MAX_PERSISTENT_GROUP_NUM 10
+
+#define P2P_PROVISIONING_SCAN_CNT 3
+
+#define P2P_WILDCARD_SSID_LEN 7
+
+/* default value, used when: (1)p2p disabed or (2)p2p enabled
+ * but only do 1 scan phase */
+#define P2P_FINDPHASE_EX_NONE 0
+/* used when p2p enabled and want to do 1 scan phase and
+ * P2P_FINDPHASE_EX_MAX-1 find phase */
+#define P2P_FINDPHASE_EX_FULL 1
+#define P2P_FINDPHASE_EX_SOCIAL_FIRST (P2P_FINDPHASE_EX_FULL+1)
+#define P2P_FINDPHASE_EX_MAX 4
+#define P2P_FINDPHASE_EX_SOCIAL_LAST P2P_FINDPHASE_EX_MAX
+
+/* 5 seconds timeout for sending the provision discovery request */
+#define P2P_PROVISION_TIMEOUT 5000
+/* 3 seconds timeout for sending the prov disc request concurrent mode */
+#define P2P_CONCURRENT_PROVISION_TIME 3000
+/* 5 seconds timeout for receiving the group negotiation response */
+#define P2P_GO_NEGO_TIMEOUT 5000
+/* 3 seconds timeout for sending the negotiation request under concurrent mode */
+#define P2P_CONCURRENT_GO_NEGO_TIME 3000
+/* 100ms */
+#define P2P_TX_PRESCAN_TIMEOUT 100
+/* 5 seconds timeout for sending the invitation request */
+#define P2P_INVITE_TIMEOUT 5000
+/* 3 seconds timeout for sending the invitation request under concurrent mode */
+#define P2P_CONCURRENT_INVITE_TIME 3000
+/* 25 seconds timeout to reset the scan channel (based on channel plan) */
+#define P2P_RESET_SCAN_CH 25000
+#define P2P_MAX_INTENT 15
+
+#define P2P_MAX_NOA_NUM 2
+
+/* WPS Configuration Method */
+#define WPS_CM_NONE 0x0000
+#define WPS_CM_LABEL 0x0004
+#define WPS_CM_DISPLYA 0x0008
+#define WPS_CM_EXTERNAL_NFC_TOKEN 0x0010
+#define WPS_CM_INTEGRATED_NFC_TOKEN 0x0020
+#define WPS_CM_NFC_INTERFACE 0x0040
+#define WPS_CM_PUSH_BUTTON 0x0080
+#define WPS_CM_KEYPAD 0x0100
+#define WPS_CM_SW_PUHS_BUTTON 0x0280
+#define WPS_CM_HW_PUHS_BUTTON 0x0480
+#define WPS_CM_SW_DISPLAY_P 0x2008
+#define WPS_CM_LCD_DISPLAY_P 0x4008
+
+enum P2P_ROLE {
+ P2P_ROLE_DISABLE = 0,
+ P2P_ROLE_DEVICE = 1,
+ P2P_ROLE_CLIENT = 2,
+ P2P_ROLE_GO = 3
+};
+
+enum P2P_STATE {
+ P2P_STATE_NONE = 0, /* P2P disable */
+ /* P2P had enabled and do nothing */
+ P2P_STATE_IDLE = 1,
+ P2P_STATE_LISTEN = 2, /* In pure listen state */
+ P2P_STATE_SCAN = 3, /* In scan phase */
+ /* In the listen state of find phase */
+ P2P_STATE_FIND_PHASE_LISTEN = 4,
+ /* In the search state of find phase */
+ P2P_STATE_FIND_PHASE_SEARCH = 5,
+ /* In P2P provisioning discovery */
+ P2P_STATE_TX_PROVISION_DIS_REQ = 6,
+ P2P_STATE_RX_PROVISION_DIS_RSP = 7,
+ P2P_STATE_RX_PROVISION_DIS_REQ = 8,
+ /* Doing the group owner negoitation handshake */
+ P2P_STATE_GONEGO_ING = 9,
+ /* finish the group negoitation handshake with success */
+ P2P_STATE_GONEGO_OK = 10,
+ /* finish the group negoitation handshake with failure */
+ P2P_STATE_GONEGO_FAIL = 11,
+ /* receiving the P2P Inviation request and match with the profile. */
+ P2P_STATE_RECV_INVITE_REQ_MATCH = 12,
+ /* Doing the P2P WPS */
+ P2P_STATE_PROVISIONING_ING = 13,
+ /* Finish the P2P WPS */
+ P2P_STATE_PROVISIONING_DONE = 14,
+ /* Transmit the P2P Invitation request */
+ P2P_STATE_TX_INVITE_REQ = 15,
+ /* Receiving the P2P Invitation response */
+ P2P_STATE_RX_INVITE_RESP_OK = 16,
+ /* receiving the P2P Inviation request and dismatch with the profile. */
+ P2P_STATE_RECV_INVITE_REQ_DISMATCH = 17,
+ /* receiving the P2P Inviation request and this wifi is GO. */
+ P2P_STATE_RECV_INVITE_REQ_GO = 18,
+ /* receiving the P2P Inviation request to join an existing P2P Group. */
+ P2P_STATE_RECV_INVITE_REQ_JOIN = 19,
+ /* recveing the P2P Inviation response with failure */
+ P2P_STATE_RX_INVITE_RESP_FAIL = 20,
+ /* receiving p2p negoitation response with information is not available */
+ P2P_STATE_RX_INFOR_NOREADY = 21,
+ /* sending p2p negoitation response with information is not available */
+ P2P_STATE_TX_INFOR_NOREADY = 22,
+};
+
+enum P2P_WPSINFO {
+ P2P_NO_WPSINFO = 0,
+ P2P_GOT_WPSINFO_PEER_DISPLAY_PIN = 1,
+ P2P_GOT_WPSINFO_SELF_DISPLAY_PIN = 2,
+ P2P_GOT_WPSINFO_PBC = 3,
+};
+
+#define P2P_PRIVATE_IOCTL_SET_LEN 64
+
+enum P2P_PROTO_WK_ID {
+ P2P_FIND_PHASE_WK = 0,
+ P2P_RESTORE_STATE_WK = 1,
+ P2P_PRE_TX_PROVDISC_PROCESS_WK = 2,
+ P2P_PRE_TX_NEGOREQ_PROCESS_WK = 3,
+ P2P_PRE_TX_INVITEREQ_PROCESS_WK = 4,
+ P2P_AP_P2P_CH_SWITCH_PROCESS_WK =5,
+ P2P_RO_CH_WK = 6,
+};
+
+enum P2P_PS_STATE {
+ P2P_PS_DISABLE = 0,
+ P2P_PS_ENABLE = 1,
+ P2P_PS_SCAN = 2,
+ P2P_PS_SCAN_DONE = 3,
+ P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */
+};
+
+enum P2P_PS_MODE {
+ P2P_PS_NONE = 0,
+ P2P_PS_CTWINDOW = 1,
+ P2P_PS_NOA = 2,
+ P2P_PS_MIX = 3, /* CTWindow and NoA */
+};
+
+/* =====================WFD Section===================== */
+/* For Wi-Fi Display */
+#define WFD_ATTR_DEVICE_INFO 0x00
+#define WFD_ATTR_ASSOC_BSSID 0x01
+#define WFD_ATTR_COUPLED_SINK_INFO 0x06
+#define WFD_ATTR_LOCAL_IP_ADDR 0x08
+#define WFD_ATTR_SESSION_INFO 0x09
+#define WFD_ATTR_ALTER_MAC 0x0a
+
+/* For WFD Device Information Attribute */
+#define WFD_DEVINFO_SOURCE 0x0000
+#define WFD_DEVINFO_PSINK 0x0001
+#define WFD_DEVINFO_SSINK 0x0002
+#define WFD_DEVINFO_DUAL 0x0003
+
+#define WFD_DEVINFO_SESSION_AVAIL 0x0010
+#define WFD_DEVINFO_WSD 0x0040
+#define WFD_DEVINFO_PC_TDLS 0x0080
+#define WFD_DEVINFO_HDCP_SUPPORT 0x0100
+
+#define IP_MCAST_MAC(mac) \
+ ((mac[0] == 0x01) && (mac[1] == 0x00) && (mac[2] == 0x5e))
+#define ICMPV6_MCAST_MAC(mac) \
+ ((mac[0] == 0x33) && (mac[1] == 0x33) && (mac[2] != 0xff))
+
+#endif /* _WIFI_H_ */
diff --git a/drivers/staging/rtl8188eu/include/wlan_bssdef.h b/drivers/staging/r8188eu/include/wlan_bssdef.h
index 350bbf9057b8..99ca097b8edd 100644
--- a/drivers/staging/rtl8188eu/include/wlan_bssdef.h
+++ b/drivers/staging/r8188eu/include/wlan_bssdef.h
@@ -1,9 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
#ifndef __WLAN_BSSDEF_H__
#define __WLAN_BSSDEF_H__
@@ -16,8 +13,8 @@
#define NDIS_802_11_RSSI long /* in dBm */
struct ndis_802_11_ssid {
- u32 ssid_length;
- u8 ssid[32];
+ u32 SsidLength;
+ u8 Ssid[32];
};
enum NDIS_802_11_NETWORK_TYPE {
@@ -64,7 +61,7 @@ struct ndis_802_11_fixed_ie {
struct ndis_802_11_var_ie {
u8 ElementID;
u8 Length;
- u8 data[];
+ u8 data[1];
};
/*
@@ -72,11 +69,10 @@ struct ndis_802_11_var_ie {
* [ETH_ALEN] + 2 + sizeof (struct ndis_802_11_ssid) + sizeof (u32)
* + sizeof (NDIS_802_11_RSSI) + sizeof (enum NDIS_802_11_NETWORK_TYPE)
* + sizeof (struct ndis_802_11_config)
- * + NDIS_802_11_LENGTH_RATES_EX + ie_length
+ * + NDIS_802_11_LENGTH_RATES_EX + IELength
*
- * Except the ie_length, all other fields are fixed length.
- * Therefore, we can define a macro to represent the partial sum.
- */
+ * Except the IELength, all other fields are fixed length.
+ * Therefore, we can define a macro to represent the partial sum. */
enum ndis_802_11_auth_mode {
Ndis802_11AuthModeOpen,
@@ -113,26 +109,74 @@ enum ndis_802_11_wep_status {
#define NDIS_802_11_AI_RESFI_STATUSCODE 2
#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4
+struct ndis_802_11_ai_reqfi {
+ u16 Capabilities;
+ u16 ListenInterval;
+ unsigned char CurrentAPAddress[ETH_ALEN];
+};
+
+struct ndis_802_11_ai_resfi {
+ u16 Capabilities;
+ u16 StatusCode;
+ u16 AssociationId;
+};
+
+struct ndis_802_11_assoc_info {
+ u32 Length;
+ u16 AvailableRequestFixedIEs;
+ struct ndis_802_11_ai_reqfi RequestFixedIEs;
+ u32 RequestIELength;
+ u32 OffsetRequestIEs;
+ u16 AvailableResponseFixedIEs;
+ struct ndis_802_11_ai_resfi ResponseFixedIEs;
+ u32 ResponseIELength;
+ u32 OffsetResponseIEs;
+};
+
enum ndis_802_11_reload_def {
Ndis802_11ReloadWEPKeys
};
+/* Key mapping keys require a BSSID */
+struct ndis_802_11_key {
+ u32 Length; /* Length of this structure */
+ u32 KeyIndex;
+ u32 KeyLength; /* length of key in bytes */
+ unsigned char BSSID[ETH_ALEN];
+ unsigned long long KeyRSC;
+ u8 KeyMaterial[32]; /* var len depending on above field */
+};
+
+struct ndis_802_11_remove_key {
+ u32 Length; /* Length */
+ u32 KeyIndex;
+ unsigned char BSSID[ETH_ALEN];
+};
+
struct ndis_802_11_wep {
u32 Length; /* Length of this structure */
u32 KeyIndex; /* 0 is the per-client key,
- * 1-N are the global keys
- */
+ * 1-N are the global keys */
u32 KeyLength; /* length of key in bytes */
u8 KeyMaterial[16];/* variable len depending on above field */
};
+struct ndis_802_11_auth_req {
+ u32 Length; /* Length of structure */
+ unsigned char Bssid[ETH_ALEN];
+ u32 Flags;
+};
+
enum ndis_802_11_status_type {
Ndis802_11StatusType_Authentication,
Ndis802_11StatusType_MediaStreamMode,
Ndis802_11StatusType_PMKID_CandidateList,
Ndis802_11StatusTypeMax /* not a real type, defined as
- * an upper bound
- */
+ * an upper bound */
+};
+
+struct ndis_802_11_status_ind {
+ enum ndis_802_11_status_type StatusType;
};
/* mask for authentication/integrity fields */
@@ -145,8 +189,22 @@ enum ndis_802_11_status_type {
/* MIC check time, 60 seconds. */
#define MIC_CHECK_TIME 60000000
+struct ndis_802_11_auth_evt {
+ struct ndis_802_11_status_ind Status;
+ struct ndis_802_11_auth_req Request[1];
+};
+
+struct ndis_802_11_test {
+ u32 Length;
+ u32 Type;
+ union {
+ struct ndis_802_11_auth_evt AuthenticationEvent;
+ NDIS_802_11_RSSI RssiTrigger;
+ } tt;
+};
+
#ifndef Ndis802_11APMode
-#define Ndis802_11APMode (Ndis802_11InfrastructureMax + 1)
+#define Ndis802_11APMode (Ndis802_11InfrastructureMax+1)
#endif
struct wlan_phy_info {
@@ -158,8 +216,7 @@ struct wlan_phy_info {
struct wlan_bcn_info {
/* these infor get from rtw_get_encrypt_info when
- * * translate scan to UI
- */
+ * * translate scan to UI */
u8 encryp_protocol;/* ENCRYP_PROTOCOL_E: OPEN/WEP/WPA/WPA2/WAPI */
int group_cipher; /* WPA/WPA2 group cipher */
int pairwise_cipher;/* WPA/WPA2/WEP pairwise cipher */
@@ -171,13 +228,13 @@ struct wlan_bcn_info {
};
/* temporally add #pragma pack for structure alignment issue of
- * struct wlan_bssid_ex and get_struct wlan_bssid_ex_sz()
- */
+* struct wlan_bssid_ex and get_struct wlan_bssid_ex_sz()
+*/
struct wlan_bssid_ex {
u32 Length;
unsigned char MacAddress[ETH_ALEN];
u8 Reserved[2];/* 0]: IS beacon frame */
- struct ndis_802_11_ssid ssid;
+ struct ndis_802_11_ssid Ssid;
u32 Privacy;
NDIS_802_11_RSSI Rssi;/* in dBM,raw data ,get from PHY) */
enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
@@ -185,23 +242,21 @@ struct wlan_bssid_ex {
enum ndis_802_11_network_infra InfrastructureMode;
unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
struct wlan_phy_info PhyInfo;
- u32 ie_length;
- u8 ies[MAX_IE_SZ]; /* timestamp, beacon interval, and
- * capability information)
- */
+ u32 IELength;
+ u8 IEs[MAX_IE_SZ]; /* timestamp, beacon interval, and
+ * capability information) */
} __packed;
static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
{
- return sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->ie_length;
+ return sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->IELength;
}
struct wlan_network {
struct list_head list;
- int network_type; /* refer to ieee80211.h for WIRELESS_11A/B/G */
+ int network_type; /* refer to ieee80211.h for WIRELESS_11B/G */
int fixed; /* set fixed when not to be removed
- * in site-surveying
- */
+ * in site-surveying */
unsigned long last_scanned; /* timestamp for the network */
int aid; /* will only be valid when a BSS is joinned. */
int join_res;
@@ -237,4 +292,36 @@ enum UAPSD_MAX_SP {
#define NUM_PRE_AUTH_KEY 16
#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY
+/*
+* WPA2
+*/
+
+struct pmkid_candidate {
+ unsigned char BSSID[ETH_ALEN];
+ u32 Flags;
+};
+
+struct ndis_802_11_pmkid_list {
+ u32 Version; /* Version of the structure */
+ u32 NumCandidates; /* No. of pmkid candidates */
+ struct pmkid_candidate CandidateList[1];
+};
+
+struct ndis_802_11_auth_encrypt {
+ enum ndis_802_11_auth_mode AuthModeSupported;
+ enum ndis_802_11_wep_status EncryptStatusSupported;
+};
+
+struct ndis_802_11_cap {
+ u32 Length;
+ u32 Version;
+ u32 NoOfPMKIDs;
+ u32 NoOfAuthEncryptPairsSupported;
+ struct ndis_802_11_auth_encrypt AuthenticationEncryptionSupported[1];
+};
+
+u8 key_2char2num(u8 hch, u8 lch);
+u8 key_char2num(u8 ch);
+u8 str_2char2num(u8 hch, u8 lch);
+
#endif /* ifndef WLAN_BSSDEF_H_ */
diff --git a/drivers/staging/r8188eu/include/xmit_osdep.h b/drivers/staging/r8188eu/include/xmit_osdep.h
new file mode 100644
index 000000000000..191c36361b63
--- /dev/null
+++ b/drivers/staging/r8188eu/include/xmit_osdep.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#ifndef __XMIT_OSDEP_H_
+#define __XMIT_OSDEP_H_
+
+#include "osdep_service.h"
+#include "drv_types.h"
+
+struct pkt_file {
+ struct sk_buff *pkt;
+ size_t pkt_len; /* the remainder length of the open_file */
+ unsigned char *cur_buffer;
+ u8 *buf_start;
+ u8 *cur_addr;
+ size_t buf_len;
+};
+
+extern int rtw_ht_enable;
+extern int rtw_cbw40_enable;
+extern int rtw_ampdu_enable;/* for enable tx_ampdu */
+
+#define NR_XMITFRAME 256
+
+struct xmit_priv;
+struct pkt_attrib;
+struct sta_xmit_priv;
+struct xmit_frame;
+struct xmit_buf;
+
+int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev);
+
+void rtw_os_xmit_schedule(struct adapter *padapter);
+
+int rtw_os_xmit_resource_alloc(struct adapter *padapter,
+ struct xmit_buf *pxmitbuf, u32 alloc_sz);
+void rtw_os_xmit_resource_free(struct adapter *padapter,
+ struct xmit_buf *pxmitbuf, u32 free_sz);
+
+void rtw_set_tx_chksum_offload(struct sk_buff *pkt, struct pkt_attrib *pattrib);
+
+uint rtw_remainder_len(struct pkt_file *pfile);
+void _rtw_open_pktfile(struct sk_buff *pkt, struct pkt_file *pfile);
+uint _rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen);
+int rtw_endofpktfile(struct pkt_file *pfile);
+
+void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt);
+void rtw_os_xmit_complete(struct adapter *padapter,
+ struct xmit_frame *pxframe);
+
+#endif /* __XMIT_OSDEP_H_ */
diff --git a/drivers/staging/r8188eu/os_dep/ioctl_linux.c b/drivers/staging/r8188eu/os_dep/ioctl_linux.c
new file mode 100644
index 000000000000..81d4255d1785
--- /dev/null
+++ b/drivers/staging/r8188eu/os_dep/ioctl_linux.c
@@ -0,0 +1,6649 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#define _IOCTL_LINUX_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/wlan_bssdef.h"
+#include "../include/rtw_debug.h"
+#include "../include/wifi.h"
+#include "../include/rtw_mlme.h"
+#include "../include/rtw_mlme_ext.h"
+#include "../include/rtw_ioctl.h"
+#include "../include/rtw_ioctl_set.h"
+#include "../include/rtw_mp_ioctl.h"
+#include "../include/usb_ops.h"
+#include "../include/rtl8188e_hal.h"
+
+#include "../include/rtw_mp.h"
+#include "../include/rtw_iol.h"
+
+#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
+
+#define SCAN_ITEM_SIZE 768
+#define MAX_CUSTOM_LEN 64
+#define RATE_COUNT 4
+
+/* combo scan */
+#define WEXT_CSCAN_AMOUNT 9
+#define WEXT_CSCAN_BUF_LEN 360
+#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
+#define WEXT_CSCAN_HEADER_SIZE 12
+#define WEXT_CSCAN_SSID_SECTION 'S'
+#define WEXT_CSCAN_CHANNEL_SECTION 'C'
+#define WEXT_CSCAN_NPROBE_SECTION 'N'
+#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
+#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
+#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
+#define WEXT_CSCAN_TYPE_SECTION 'T'
+
+static struct mp_ioctl_handler mp_ioctl_hdl[] = {
+/*0*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_start_test_hdl, OID_RT_PRO_START_TEST)
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_stop_test_hdl, OID_RT_PRO_STOP_TEST)
+
+ GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_read_register_hdl, OID_RT_PRO_READ_REGISTER)
+ GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_write_register_hdl, OID_RT_PRO_WRITE_REGISTER)
+ GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_read_bb_reg_hdl, OID_RT_PRO_READ_BB_REG)
+/*5*/ GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_write_bb_reg_hdl, OID_RT_PRO_WRITE_BB_REG)
+ GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_read_rf_reg_hdl, OID_RT_PRO_RF_READ_REGISTRY)
+ GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_write_rf_reg_hdl, OID_RT_PRO_RF_WRITE_REGISTRY)
+
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl, OID_RT_PRO_SET_CHANNEL_DIRECT_CALL)
+ GEN_HANDLER(sizeof(struct txpower_param), rtl8188eu_oid_rt_pro_set_tx_power_control_hdl, OID_RT_PRO_SET_TX_POWER_CONTROL)
+/*10*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_data_rate_hdl, OID_RT_PRO_SET_DATA_RATE)
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_bandwidth_hdl, OID_RT_SET_BANDWIDTH)
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_antenna_bb_hdl, OID_RT_PRO_SET_ANTENNA_BB)
+
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_continuous_tx_hdl, OID_RT_PRO_SET_CONTINUOUS_TX)
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl, OID_RT_PRO_SET_SINGLE_CARRIER_TX)
+/*15*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl, OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX)
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl, OID_RT_PRO_SET_SINGLE_TONE_TX)
+
+ EXT_MP_IOCTL_HANDLER(0, xmit_packet, 0)
+
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_rx_packet_type_hdl, OID_RT_SET_RX_PACKET_TYPE)
+ GEN_HANDLER(0, rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl, OID_RT_RESET_PHY_RX_PACKET_COUNT)
+/*20*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl, OID_RT_GET_PHY_RX_PACKET_RECEIVED)
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl, OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR)
+
+ GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0)
+ GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0)
+ GEN_HANDLER(sizeof(struct efuse_access_struct), rtl8188eu_oid_rt_pro_efuse_hdl, OID_RT_PRO_EFUSE)
+/*25*/ GEN_HANDLER(0, rtl8188eu_oid_rt_pro_efuse_map_hdl, OID_RT_PRO_EFUSE_MAP)
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_max_size_hdl, OID_RT_GET_EFUSE_MAX_SIZE)
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_current_size_hdl, OID_RT_GET_EFUSE_CURRENT_SIZE)
+
+ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_thermal_meter_hdl, OID_RT_PRO_GET_THERMAL_METER)
+ GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_pro_set_power_tracking_hdl, OID_RT_PRO_SET_POWER_TRACKING)
+/*30*/ GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_set_power_down_hdl, OID_RT_SET_POWER_DOWN)
+/*31*/ GEN_HANDLER(0, rtl8188eu_oid_rt_pro_trigger_gpio_hdl, 0)
+};
+
+static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
+ 6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
+ 48000000, 54000000};
+
+void indicate_wx_scan_complete_event(struct adapter *padapter)
+{
+ union iwreq_data wrqu;
+
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+ wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
+void rtw_indicate_wx_assoc_event(struct adapter *padapter)
+{
+ union iwreq_data wrqu;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+
+ memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
+
+ DBG_88E_LEVEL(_drv_always_, "assoc success\n");
+ wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
+}
+
+void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
+{
+ union iwreq_data wrqu;
+
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+
+ DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
+ wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
+}
+
+static char *translate_scan(struct adapter *padapter,
+ struct iw_request_info *info,
+ struct wlan_network *pnetwork,
+ char *start, char *stop)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct iw_event iwe;
+ u16 cap;
+ __le16 le_tmp;
+ u32 ht_ielen = 0;
+ char *custom;
+ char *p;
+ u16 max_rate = 0, rate, ht_cap = false;
+ u32 i = 0;
+ u8 bw_40MHz = 0, short_GI = 0;
+ u16 mcs_rate = 0;
+ u8 ss, sq;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+ u32 blnGotP2PIE = false;
+
+ /* User is doing the P2P device discovery */
+ /* The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */
+ /* If not, the driver should ignore this AP and go to the next AP. */
+
+ /* Verifying the SSID */
+ if (!memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) {
+ u32 p2pielen = 0;
+
+ if (pnetwork->network.Reserved[0] == 2) {/* Probe Request */
+ /* Verifying the P2P IE */
+ if (rtw_get_p2p_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &p2pielen))
+ blnGotP2PIE = true;
+ } else {/* Beacon or Probe Respones */
+ /* Verifying the P2P IE */
+ if (rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen))
+ blnGotP2PIE = true;
+ }
+ }
+
+ if (!blnGotP2PIE)
+ return start;
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ /* AP MAC address */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+
+ memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
+
+ /* Add the ESSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32);
+ start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
+
+ /* parsing HT_CAP_IE */
+ p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - 12);
+
+ if (p && ht_ielen > 0) {
+ struct ieee80211_ht_cap *pht_capie;
+
+ ht_cap = true;
+ pht_capie = (struct ieee80211_ht_cap *)(p + 2);
+ memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
+ bw_40MHz = (le16_to_cpu(pht_capie->cap_info) &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0;
+ short_GI = (le16_to_cpu(pht_capie->cap_info) &
+ (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
+ }
+
+ /* Add the protocol name */
+ iwe.cmd = SIOCGIWNAME;
+ if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
+ if (ht_cap)
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
+ else
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
+ } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
+ if (ht_cap)
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
+ else
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
+ } else {
+ if (ht_cap)
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
+ else
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
+ }
+
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
+
+ /* Add mode */
+ iwe.cmd = SIOCGIWMODE;
+ memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
+
+ cap = le16_to_cpu(le_tmp);
+
+ if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
+ if (cap & WLAN_CAPABILITY_BSS)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
+ }
+
+ if (pnetwork->network.Configuration.DSConfig < 1)
+ pnetwork->network.Configuration.DSConfig = 1;
+
+ /* Add frequency/channel */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
+ iwe.u.freq.e = 1;
+ iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
+
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (cap & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
+
+ /*Add basic and extended rates */
+ max_rate = 0;
+ custom = kzalloc(MAX_CUSTOM_LEN, GFP_ATOMIC);
+ if (!custom)
+ return start;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+ while (pnetwork->network.SupportedRates[i] != 0) {
+ rate = pnetwork->network.SupportedRates[i] & 0x7F;
+ if (rate > max_rate)
+ max_rate = rate;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+ i++;
+ }
+
+ if (ht_cap) {
+ if (mcs_rate & 0x8000)/* MCS15 */
+ max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
+ else if (mcs_rate & 0x0080)/* MCS7 */
+ ;
+ else/* default MCS7 */
+ max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
+
+ max_rate = max_rate * 2;/* Mbps/2; */
+ }
+
+ iwe.cmd = SIOCGIWRATE;
+ iwe.u.bitrate.fixed = 0;
+ iwe.u.bitrate.disabled = 0;
+ iwe.u.bitrate.value = max_rate * 500000;
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
+
+ /* parsing WPA/WPA2 IE */
+ {
+ u8 *buf;
+ u8 *wpa_ie, *rsn_ie;
+ u16 wpa_len = 0, rsn_len = 0;
+ u8 *p;
+
+ buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC);
+ if (!buf)
+ goto exit;
+ wpa_ie = kzalloc(255, GFP_ATOMIC);
+ if (!wpa_ie) {
+ kfree(buf);
+ goto exit;
+ }
+ rsn_ie = kzalloc(255, GFP_ATOMIC);
+ if (!rsn_ie) {
+ kfree(buf);
+ kfree(wpa_ie);
+ goto exit;
+ }
+ rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
+
+ if (wpa_len > 0) {
+ p = buf;
+ memset(buf, 0, MAX_WPA_IE_LEN);
+ p += sprintf(p, "wpa_ie =");
+ for (i = 0; i < wpa_len; i++)
+ p += sprintf(p, "%02x", wpa_ie[i]);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = strlen(buf);
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = wpa_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
+ }
+ if (rsn_len > 0) {
+ p = buf;
+ memset(buf, 0, MAX_WPA_IE_LEN);
+ p += sprintf(p, "rsn_ie =");
+ for (i = 0; i < rsn_len; i++)
+ p += sprintf(p, "%02x", rsn_ie[i]);
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = strlen(buf);
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = rsn_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
+ }
+ kfree(buf);
+ kfree(wpa_ie);
+ kfree(rsn_ie);
+ }
+
+ {/* parsing WPS IE */
+ uint cnt = 0, total_ielen;
+ u8 *wpsie_ptr = NULL;
+ uint wps_ielen = 0;
+
+ u8 *ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
+ total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
+
+ while (cnt < total_ielen) {
+ if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
+ wpsie_ptr = &ie_ptr[cnt];
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = (u16)wps_ielen;
+ start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
+ }
+ cnt += ie_ptr[cnt + 1] + 2; /* goto next */
+ }
+ }
+
+ /* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+ is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
+ ss = padapter->recvpriv.signal_strength;
+ sq = padapter->recvpriv.signal_qual;
+ } else {
+ ss = pnetwork->network.PhyInfo.SignalStrength;
+ sq = pnetwork->network.PhyInfo.SignalQuality;
+ }
+
+ iwe.u.qual.level = (u8)ss;
+ iwe.u.qual.qual = (u8)sq; /* signal quality */
+ iwe.u.qual.noise = 0; /* noise level */
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
+exit:
+ kfree(custom);
+ return start;
+}
+
+static int wpa_set_auth_algs(struct net_device *dev, u32 value)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int ret = 0;
+
+ if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
+ DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+ } else if (value & AUTH_ALG_SHARED_KEY) {
+ DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY [value:0x%x]\n", value);
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
+ } else if (value & AUTH_ALG_OPEN_SYSTEM) {
+ DBG_88E("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
+ if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ }
+ } else if (value & AUTH_ALG_LEAP) {
+ DBG_88E("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
+ } else {
+ DBG_88E("wpa_set_auth_algs, error!\n");
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+ int ret = 0;
+ u32 wep_key_idx, wep_key_len, wep_total_len;
+ struct ndis_802_11_wep *pwep = NULL;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+ if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+ if (param->u.crypt.idx >= WEP_KEYS) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ } else {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ DBG_88E("wpa_set_encryption, crypt.alg = WEP\n");
+
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+
+ DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx);
+
+ if (wep_key_idx > WEP_KEYS)
+ return -EINVAL;
+
+ if (wep_key_len > 0) {
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+ wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
+ pwep = kmalloc(wep_total_len, GFP_KERNEL);
+ if (!pwep)
+ goto exit;
+
+ memset(pwep, 0, wep_total_len);
+ pwep->KeyLength = wep_key_len;
+ pwep->Length = wep_total_len;
+ if (wep_key_len == 13) {
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
+ }
+ } else {
+ ret = -EINVAL;
+ goto exit;
+ }
+ pwep->KeyIndex = wep_key_idx;
+ pwep->KeyIndex |= 0x80000000;
+ memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
+ if (param->u.crypt.set_tx) {
+ DBG_88E("wep, set_tx = 1\n");
+ if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
+ ret = -EOPNOTSUPP;
+ } else {
+ DBG_88E("wep, set_tx = 0\n");
+ if (wep_key_idx >= WEP_KEYS) {
+ ret = -EOPNOTSUPP;
+ goto exit;
+ }
+ memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength);
+ psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+ rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
+ }
+ goto exit;
+ }
+
+ if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
+ struct sta_info *psta, *pbcmc_sta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */
+ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+ if (!psta) {
+ ;
+ } else {
+ if (strcmp(param->u.crypt.alg, "none") != 0)
+ psta->ieee8021x_blocked = false;
+
+ if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+ (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
+ psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+
+ if (param->u.crypt.set_tx == 1) { /* pairwise key */
+ memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+ if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
+ memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
+ memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
+ padapter->securitypriv.busetkipkey = false;
+ }
+
+ DBG_88E(" ~~~~set sta key:unicastkey\n");
+
+ rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
+ } else { /* group key */
+ memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[16], 8);
+ memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
+ padapter->securitypriv.binstallGrpkey = true;
+ DBG_88E(" ~~~~set sta key:groupkey\n");
+
+ padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
+
+ rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
+#endif /* CONFIG_88EU_P2P */
+ }
+ }
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+ if (!pbcmc_sta) {
+ ;
+ } else {
+ /* Jeff: don't disable ieee8021x_blocked while clearing key */
+ if (strcmp(param->u.crypt.alg, "none") != 0)
+ pbcmc_sta->ieee8021x_blocked = false;
+
+ if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+ (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
+ pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+ }
+ }
+ }
+
+exit:
+
+ kfree(pwep);
+
+ return ret;
+}
+
+static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
+{
+ u8 *buf = NULL;
+ int group_cipher = 0, pairwise_cipher = 0;
+ int ret = 0;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ if (ielen > MAX_WPA_IE_LEN || !pie) {
+ _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+ if (!pie)
+ return ret;
+ else
+ return -EINVAL;
+ }
+
+ if (ielen) {
+ buf = kzalloc(ielen, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ memcpy(buf, pie, ielen);
+
+ /* dump */
+ {
+ int i;
+ DBG_88E("\n wpa_ie(length:%d):\n", ielen);
+ for (i = 0; i < ielen; i += 8)
+ DBG_88E("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
+ }
+
+ if (ielen < RSN_HEADER_LEN) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
+ memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
+ }
+
+ if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
+ memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
+ }
+
+ switch (group_cipher) {
+ case WPA_CIPHER_NONE:
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ break;
+ case WPA_CIPHER_WEP40:
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ case WPA_CIPHER_TKIP:
+ padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+ break;
+ case WPA_CIPHER_CCMP:
+ padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+ break;
+ case WPA_CIPHER_WEP104:
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ }
+
+ switch (pairwise_cipher) {
+ case WPA_CIPHER_NONE:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ break;
+ case WPA_CIPHER_WEP40:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ case WPA_CIPHER_TKIP:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+ break;
+ case WPA_CIPHER_CCMP:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+ break;
+ case WPA_CIPHER_WEP104:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ }
+
+ _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+ {/* set wps_ie */
+ u16 cnt = 0;
+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ while (cnt < ielen) {
+ eid = buf[cnt];
+ if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
+ DBG_88E("SET WPS_IE\n");
+
+ padapter->securitypriv.wps_ie_len = ((buf[cnt + 1] + 2) < (MAX_WPA_IE_LEN << 2)) ? (buf[cnt + 1] + 2) : (MAX_WPA_IE_LEN << 2);
+
+ memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
+
+ set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
+#ifdef CONFIG_88EU_P2P
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
+#endif /* CONFIG_88EU_P2P */
+ cnt += buf[cnt + 1] + 2;
+ break;
+ } else {
+ cnt += buf[cnt + 1] + 2; /* goto next */
+ }
+ }
+ }
+ }
+
+exit:
+ kfree(buf);
+ return ret;
+}
+
+typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
+
+static int rtw_wx_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u32 ht_ielen = 0;
+ char *p;
+ u8 ht_cap = false;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ NDIS_802_11_RATES_EX *prates = NULL;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
+ /* parsing HT_CAP_IE */
+ p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
+ if (p && ht_ielen > 0)
+ ht_cap = true;
+
+ prates = &pcur_bss->SupportedRates;
+
+ if (rtw_is_cckratesonly_included((u8 *)prates)) {
+ if (ht_cap)
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
+ } else if (rtw_is_cckrates_included((u8 *)prates)) {
+ if (ht_cap)
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
+ } else {
+ if (ht_cap)
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
+ }
+ } else {
+ snprintf(wrqu->name, IFNAMSIZ, "unassociated");
+ }
+
+
+
+ return 0;
+}
+
+static int rtw_wx_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
+ wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
+ wrqu->freq.e = 1;
+ wrqu->freq.i = pcur_bss->Configuration.DSConfig;
+ } else {
+ wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
+ wrqu->freq.e = 1;
+ wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
+ }
+
+ return 0;
+}
+
+static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ enum ndis_802_11_network_infra networkType;
+ int ret = 0;
+
+
+
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = -EPERM;
+ goto exit;
+ }
+
+ if (!padapter->hw_init_completed) {
+ ret = -EPERM;
+ goto exit;
+ }
+
+ switch (wrqu->mode) {
+ case IW_MODE_AUTO:
+ networkType = Ndis802_11AutoUnknown;
+ DBG_88E("set_mode = IW_MODE_AUTO\n");
+ break;
+ case IW_MODE_ADHOC:
+ networkType = Ndis802_11IBSS;
+ DBG_88E("set_mode = IW_MODE_ADHOC\n");
+ break;
+ case IW_MODE_MASTER:
+ networkType = Ndis802_11APMode;
+ DBG_88E("set_mode = IW_MODE_MASTER\n");
+ break;
+ case IW_MODE_INFRA:
+ networkType = Ndis802_11Infrastructure;
+ DBG_88E("set_mode = IW_MODE_INFRA\n");
+ break;
+ default:
+ ret = -EINVAL;
+ goto exit;
+ }
+ if (!rtw_set_802_11_infrastructure_mode(padapter, networkType)) {
+ ret = -EPERM;
+ goto exit;
+ }
+ rtw_setopmode_cmd(padapter, networkType);
+exit:
+
+ return ret;
+}
+
+static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ wrqu->mode = IW_MODE_INFRA;
+ else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
+ wrqu->mode = IW_MODE_ADHOC;
+ else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ wrqu->mode = IW_MODE_MASTER;
+ else
+ wrqu->mode = IW_MODE_AUTO;
+
+
+
+ return 0;
+}
+
+static int rtw_wx_set_pmkid(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u8 j, blInserted = false;
+ int ret = false;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
+ u8 strZeroMacAddress[ETH_ALEN] = {0x00};
+ u8 strIssueBssid[ETH_ALEN] = {0x00};
+
+ memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
+ if (pPMK->cmd == IW_PMKSA_ADD) {
+ DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
+ if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
+ return ret;
+ else
+ ret = true;
+ blInserted = false;
+
+ /* overwrite PMKID */
+ for (j = 0; j < NUM_PMKID_CACHE; j++) {
+ if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
+ /* BSSID is matched, the same AP => rewrite with new PMKID. */
+ DBG_88E("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
+ memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
+ psecuritypriv->PMKIDList[j].bUsed = true;
+ psecuritypriv->PMKIDIndex = j + 1;
+ blInserted = true;
+ break;
+ }
+ }
+
+ if (!blInserted) {
+ /* Find a new entry */
+ DBG_88E("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
+ psecuritypriv->PMKIDIndex);
+
+ memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
+ memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
+
+ psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
+ psecuritypriv->PMKIDIndex++;
+ if (psecuritypriv->PMKIDIndex == 16)
+ psecuritypriv->PMKIDIndex = 0;
+ }
+ } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
+ DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
+ ret = true;
+ for (j = 0; j < NUM_PMKID_CACHE; j++) {
+ if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
+ /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
+ memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
+ psecuritypriv->PMKIDList[j].bUsed = false;
+ break;
+ }
+ }
+ } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
+ DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
+ memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ psecuritypriv->PMKIDIndex = 0;
+ ret = true;
+ }
+ return ret;
+}
+
+static int rtw_wx_get_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wrqu->sens.value = 0;
+ wrqu->sens.fixed = 0; /* no auto select */
+ wrqu->sens.disabled = 1;
+ return 0;
+}
+
+static int rtw_wx_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct iw_range *range = (struct iw_range *)extra;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ u16 val;
+ int i;
+
+ wrqu->data.length = sizeof(*range);
+ memset(range, 0, sizeof(*range));
+
+ /* Let's try to keep this struct in the same order as in
+ * linux/include/wireless.h
+ */
+
+ /* TODO: See what values we can set, and remove the ones we can't
+ * set, or fill them with some default data.
+ */
+
+ /* ~5 Mb/s real (802.11b) */
+ range->throughput = 5 * 1000 * 1000;
+
+ /* signal level threshold range */
+
+ /* percent values between 0 and 100. */
+ range->max_qual.qual = 100;
+ range->max_qual.level = 100;
+ range->max_qual.noise = 100;
+ range->max_qual.updated = 7; /* Updated all three */
+
+ range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
+ /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ range->avg_qual.level = 178; /* -78 dBm */
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = 7; /* Updated all three */
+
+ range->num_bitrates = RATE_COUNT;
+
+ for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
+ range->bitrate[i] = rtw_rates[i];
+
+ range->min_frag = MIN_FRAG_THRESHOLD;
+ range->max_frag = MAX_FRAG_THRESHOLD;
+
+ range->pm_capa = 0;
+
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 16;
+
+ for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
+ /* Include only legal frequencies for some countries */
+ if (pmlmeext->channel_set[i].ChannelNum != 0) {
+ range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
+ range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
+ range->freq[val].e = 1;
+ val++;
+ }
+
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+
+ range->num_channels = val;
+ range->num_frequency = val;
+
+/* The following code will proivde the security capability to network manager. */
+/* If the driver doesn't provide this capability to network manager, */
+/* the WPA/WPA2 routers can't be chosen in the network manager. */
+
+/*
+#define IW_SCAN_CAPA_NONE 0x00
+#define IW_SCAN_CAPA_ESSID 0x01
+#define IW_SCAN_CAPA_BSSID 0x02
+#define IW_SCAN_CAPA_CHANNEL 0x04
+#define IW_SCAN_CAPA_MODE 0x08
+#define IW_SCAN_CAPA_RATE 0x10
+#define IW_SCAN_CAPA_TYPE 0x20
+#define IW_SCAN_CAPA_TIME 0x40
+*/
+
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
+ range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
+ IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
+ IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
+
+
+ return 0;
+}
+
+/* set bssid flow */
+/* s1. rtw_set_802_11_infrastructure_mode() */
+/* s2. rtw_set_802_11_authentication_mode() */
+/* s3. set_802_11_encryption_mode() */
+/* s4. rtw_set_802_11_bssid() */
+static int rtw_wx_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *awrq,
+ char *extra)
+{
+ uint ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct sockaddr *temp = (struct sockaddr *)awrq;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *phead;
+ u8 *dst_bssid, *src_bssid;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ enum ndis_802_11_auth_mode authmode;
+
+
+
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (!padapter->bup) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (temp->sa_family != ARPHRD_ETHER) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ authmode = padapter->securitypriv.ndisauthtype;
+ spin_lock_bh(&queue->lock);
+ phead = get_list_head(queue);
+ pmlmepriv->pscanned = phead->next;
+
+ while (phead != pmlmepriv->pscanned) {
+
+ pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
+
+ pmlmepriv->pscanned = pmlmepriv->pscanned->next;
+
+ dst_bssid = pnetwork->network.MacAddress;
+
+ src_bssid = temp->sa_data;
+
+ if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
+ if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
+ ret = -1;
+ spin_unlock_bh(&queue->lock);
+ goto exit;
+ }
+
+ break;
+ }
+ }
+ spin_unlock_bh(&queue->lock);
+
+ rtw_set_802_11_authentication_mode(padapter, authmode);
+ /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
+ if (!rtw_set_802_11_bssid(padapter, temp->sa_data)) {
+ ret = -1;
+ goto exit;
+ }
+
+exit:
+
+
+
+ return ret;
+}
+
+static int rtw_wx_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+
+ memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
+ else
+ memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+
+
+
+ return 0;
+}
+
+static int rtw_wx_set_mlme(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ u16 reason;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+
+ if (!mlme)
+ return -1;
+
+ DBG_88E("%s\n", __func__);
+
+ reason = mlme->reason_code;
+
+ DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
+
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ if (!rtw_set_802_11_disassociate(padapter))
+ ret = -1;
+ break;
+ case IW_MLME_DISASSOC:
+ if (!rtw_set_802_11_disassociate(padapter))
+ ret = -1;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return ret;
+}
+
+static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ u8 _status = false;
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ if (padapter->registrypriv.mp_mode == 1) {
+ if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
+ ret = -1;
+ goto exit;
+ }
+ }
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (padapter->bDriverStopped) {
+ DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped);
+ ret = -1;
+ goto exit;
+ }
+
+ if (!padapter->bup) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (!padapter->hw_init_completed) {
+ ret = -1;
+ goto exit;
+ }
+
+ /* When Busy Traffic, driver do not site survey. So driver return success. */
+ /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
+ /* modify by thomas 2011-02-22. */
+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
+ indicate_wx_scan_complete_event(padapter);
+ goto exit;
+ }
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
+ indicate_wx_scan_complete_event(padapter);
+ goto exit;
+ }
+
+/* For the DMP WiFi Display project, the driver won't to scan because */
+/* the pmlmepriv->scan_interval is always equal to 3. */
+/* So, the wpa_supplicant won't find out the WPS SoftAP. */
+
+#ifdef CONFIG_88EU_P2P
+ if (pwdinfo->p2p_state != P2P_STATE_NONE) {
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+ rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
+ rtw_free_network_queue(padapter, true);
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ memset(ssid, 0, sizeof(struct ndis_802_11_ssid) * RTW_SSID_SCAN_AMOUNT);
+
+ if (wrqu->data.length == sizeof(struct iw_scan_req)) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+
+ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
+
+ memcpy(ssid[0].Ssid, req->essid, len);
+ ssid[0].SsidLength = len;
+
+ DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
+
+ spin_unlock_bh(&pmlmepriv->lock);
+ } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
+ DBG_88E("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
+ }
+ } else {
+ if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
+ !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
+ int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
+ char *pos = extra + WEXT_CSCAN_HEADER_SIZE;
+ char section;
+ char sec_len;
+ int ssid_index = 0;
+
+ while (len >= 1) {
+ section = *(pos++);
+ len -= 1;
+
+ switch (section) {
+ case WEXT_CSCAN_SSID_SECTION:
+ if (len < 1) {
+ len = 0;
+ break;
+ }
+ sec_len = *(pos++); len -= 1;
+ if (sec_len > 0 && sec_len <= len) {
+ ssid[ssid_index].SsidLength = sec_len;
+ memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
+ ssid_index++;
+ }
+ pos += sec_len;
+ len -= sec_len;
+ break;
+ case WEXT_CSCAN_TYPE_SECTION:
+ case WEXT_CSCAN_CHANNEL_SECTION:
+ pos += 1;
+ len -= 1;
+ break;
+ case WEXT_CSCAN_PASV_DWELL_SECTION:
+ case WEXT_CSCAN_HOME_DWELL_SECTION:
+ case WEXT_CSCAN_ACTV_DWELL_SECTION:
+ pos += 2;
+ len -= 2;
+ break;
+ default:
+ len = 0; /* stop parsing */
+ }
+ }
+
+ /* it has still some scan parameter to parse, we only do this now... */
+ _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
+ } else {
+ _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
+ }
+ }
+
+ if (!_status)
+ ret = -1;
+
+exit:
+
+ return ret;
+}
+
+static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct list_head *plist, *phead;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ char *ev = extra;
+ char *stop = ev + wrqu->data.length;
+ u32 ret = 0;
+ u32 cnt = 0;
+ u32 wait_for_surveydone;
+ int wait_status;
+#ifdef CONFIG_88EU_P2P
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif /* CONFIG_88EU_P2P */
+
+ if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+#ifdef CONFIG_88EU_P2P
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+ /* P2P is enabled */
+ wait_for_surveydone = 200;
+ } else {
+ /* P2P is disabled */
+ wait_for_surveydone = 100;
+ }
+#else
+ {
+ wait_for_surveydone = 100;
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
+
+ while (check_fwstate(pmlmepriv, wait_status)) {
+ msleep(30);
+ cnt++;
+ if (cnt > wait_for_surveydone)
+ break;
+ }
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ if ((stop - ev) < SCAN_ITEM_SIZE) {
+ ret = -E2BIG;
+ break;
+ }
+
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ /* report network only if the current channel set contains the channel to which this network belongs */
+ if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
+ ev = translate_scan(padapter, a, pnetwork, ev, stop);
+
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ wrqu->data.length = ev - extra;
+ wrqu->data.flags = 0;
+
+exit:
+
+ return ret;
+}
+
+/* set ssid flow */
+/* s1. rtw_set_802_11_infrastructure_mode() */
+/* s2. set_802_11_authenticaion_mode() */
+/* s3. set_802_11_encryption_mode() */
+/* s4. rtw_set_802_11_ssid() */
+static int rtw_wx_set_essid(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct list_head *phead;
+ struct wlan_network *pnetwork = NULL;
+ enum ndis_802_11_auth_mode authmode;
+ struct ndis_802_11_ssid ndis_ssid;
+ u8 *dst_ssid, *src_ssid;
+
+ uint ret = 0, len;
+
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (!padapter->bup) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
+ ret = -E2BIG;
+ goto exit;
+ }
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ ret = -1;
+ goto exit;
+ }
+
+ authmode = padapter->securitypriv.ndisauthtype;
+ DBG_88E("=>%s\n", __func__);
+ if (wrqu->essid.flags && wrqu->essid.length) {
+ len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
+
+ if (wrqu->essid.length != 33)
+ DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
+
+ memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
+ ndis_ssid.SsidLength = len;
+ memcpy(ndis_ssid.Ssid, extra, len);
+ src_ssid = ndis_ssid.Ssid;
+
+ spin_lock_bh(&queue->lock);
+ phead = get_list_head(queue);
+ pmlmepriv->pscanned = phead->next;
+
+ while (phead != pmlmepriv->pscanned) {
+ pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
+
+ pmlmepriv->pscanned = pmlmepriv->pscanned->next;
+
+ dst_ssid = pnetwork->network.Ssid.Ssid;
+
+ if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
+ (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
+ continue;
+ }
+
+ if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
+ ret = -1;
+ spin_unlock_bh(&queue->lock);
+ goto exit;
+ }
+
+ break;
+ }
+ }
+ spin_unlock_bh(&queue->lock);
+ rtw_set_802_11_authentication_mode(padapter, authmode);
+ if (!rtw_set_802_11_ssid(padapter, &ndis_ssid)) {
+ ret = -1;
+ goto exit;
+ }
+ }
+
+exit:
+
+ DBG_88E("<=%s, ret %d\n", __func__, ret);
+
+
+
+ return ret;
+}
+
+static int rtw_wx_get_essid(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ u32 len, ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+
+ if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
+ len = pcur_bss->Ssid.SsidLength;
+ memcpy(extra, pcur_bss->Ssid.Ssid, len);
+ } else {
+ len = 0;
+ *extra = 0;
+ }
+ wrqu->essid.length = len;
+ wrqu->essid.flags = 1;
+
+ return ret;
+}
+
+static int rtw_wx_set_rate(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ int i, ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u8 datarates[NumRates];
+ u32 target_rate = wrqu->bitrate.value;
+ u32 fixed = wrqu->bitrate.fixed;
+ u32 ratevalue = 0;
+ u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
+
+ if (target_rate == -1) {
+ ratevalue = 11;
+ goto set_rate;
+ }
+ target_rate = target_rate / 100000;
+
+ switch (target_rate) {
+ case 10:
+ ratevalue = 0;
+ break;
+ case 20:
+ ratevalue = 1;
+ break;
+ case 55:
+ ratevalue = 2;
+ break;
+ case 60:
+ ratevalue = 3;
+ break;
+ case 90:
+ ratevalue = 4;
+ break;
+ case 110:
+ ratevalue = 5;
+ break;
+ case 120:
+ ratevalue = 6;
+ break;
+ case 180:
+ ratevalue = 7;
+ break;
+ case 240:
+ ratevalue = 8;
+ break;
+ case 360:
+ ratevalue = 9;
+ break;
+ case 480:
+ ratevalue = 10;
+ break;
+ case 540:
+ ratevalue = 11;
+ break;
+ default:
+ ratevalue = 11;
+ break;
+ }
+
+set_rate:
+
+ for (i = 0; i < NumRates; i++) {
+ if (ratevalue == mpdatarate[i]) {
+ datarates[i] = mpdatarate[i];
+ if (fixed == 0)
+ break;
+ } else {
+ datarates[i] = 0xff;
+ }
+ }
+
+ if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS)
+ ret = -1;
+
+ return ret;
+}
+
+static int rtw_wx_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ u16 max_rate = 0;
+
+ max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
+
+ if (max_rate == 0)
+ return -EPERM;
+
+ wrqu->bitrate.fixed = 0; /* no auto select */
+ wrqu->bitrate.value = max_rate * 100000;
+
+ return 0;
+}
+
+static int rtw_wx_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+
+
+ if (wrqu->rts.disabled) {
+ padapter->registrypriv.rts_thresh = 2347;
+ } else {
+ if (wrqu->rts.value < 0 ||
+ wrqu->rts.value > 2347)
+ return -EINVAL;
+
+ padapter->registrypriv.rts_thresh = wrqu->rts.value;
+ }
+
+ DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
+
+
+
+ return 0;
+}
+
+static int rtw_wx_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+
+
+ DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
+
+ wrqu->rts.value = padapter->registrypriv.rts_thresh;
+ wrqu->rts.fixed = 0; /* no auto select */
+ /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
+
+
+
+ return 0;
+}
+
+static int rtw_wx_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+
+
+ if (wrqu->frag.disabled) {
+ padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
+ } else {
+ if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+ wrqu->frag.value > MAX_FRAG_THRESHOLD)
+ return -EINVAL;
+
+ padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
+ }
+
+ DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
+
+
+
+ return 0;
+}
+
+static int rtw_wx_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+
+
+ DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
+
+ wrqu->frag.value = padapter->xmitpriv.frag_len;
+ wrqu->frag.fixed = 0; /* no auto select */
+
+
+
+ return 0;
+}
+
+static int rtw_wx_get_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wrqu->retry.value = 7;
+ wrqu->retry.fixed = 0; /* no auto select */
+ wrqu->retry.disabled = 1;
+
+ return 0;
+}
+
+static int rtw_wx_set_enc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ u32 key, ret = 0;
+ u32 keyindex_provided;
+ struct ndis_802_11_wep wep;
+ enum ndis_802_11_auth_mode authmode;
+
+ struct iw_point *erq = &wrqu->encoding;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
+
+ memset(&wep, 0, sizeof(struct ndis_802_11_wep));
+
+ key = erq->flags & IW_ENCODE_INDEX;
+
+
+
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ DBG_88E("EncryptionDisabled\n");
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+ authmode = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.ndisauthtype = authmode;
+
+ goto exit;
+ }
+
+ if (key) {
+ if (key > WEP_KEYS)
+ return -EINVAL;
+ key--;
+ keyindex_provided = 1;
+ } else {
+ keyindex_provided = 0;
+ key = padapter->securitypriv.dot11PrivacyKeyIndex;
+ DBG_88E("rtw_wx_set_enc, key =%d\n", key);
+ }
+
+ /* set authentication mode */
+ if (erq->flags & IW_ENCODE_OPEN) {
+ DBG_88E("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ authmode = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.ndisauthtype = authmode;
+ } else if (erq->flags & IW_ENCODE_RESTRICTED) {
+ DBG_88E("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+ authmode = Ndis802_11AuthModeShared;
+ padapter->securitypriv.ndisauthtype = authmode;
+ } else {
+ DBG_88E("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
+
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ authmode = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.ndisauthtype = authmode;
+ }
+
+ wep.KeyIndex = key;
+ if (erq->length > 0) {
+ wep.KeyLength = erq->length <= 5 ? 5 : 13;
+
+ wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
+ } else {
+ wep.KeyLength = 0;
+
+ if (keyindex_provided == 1) {
+ /* set key_id only, no given KeyMaterial(erq->length == 0). */
+ padapter->securitypriv.dot11PrivacyKeyIndex = key;
+
+ DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
+
+ switch (padapter->securitypriv.dot11DefKeylen[key]) {
+ case 5:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ break;
+ case 13:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+ break;
+ default:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ break;
+ }
+
+ goto exit;
+ }
+ }
+
+ wep.KeyIndex |= 0x80000000;
+
+ memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
+
+ if (!rtw_set_802_11_add_wep(padapter, &wep)) {
+ if (rf_on == pwrpriv->rf_pwrstate)
+ ret = -EOPNOTSUPP;
+ goto exit;
+ }
+
+exit:
+
+
+
+ return ret;
+}
+
+static int rtw_wx_get_enc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ uint key, ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_point *erq = &wrqu->encoding;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
+ if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ return 0;
+ }
+ }
+
+ key = erq->flags & IW_ENCODE_INDEX;
+
+ if (key) {
+ if (key > WEP_KEYS)
+ return -EINVAL;
+ key--;
+ } else {
+ key = padapter->securitypriv.dot11PrivacyKeyIndex;
+ }
+
+ erq->flags = key + 1;
+
+ switch (padapter->securitypriv.ndisencryptstatus) {
+ case Ndis802_11EncryptionNotSupported:
+ case Ndis802_11EncryptionDisabled:
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ break;
+ case Ndis802_11Encryption1Enabled:
+ erq->length = padapter->securitypriv.dot11DefKeylen[key];
+ if (erq->length) {
+ memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
+
+ erq->flags |= IW_ENCODE_ENABLED;
+
+ if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
+ erq->flags |= IW_ENCODE_OPEN;
+ else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
+ erq->flags |= IW_ENCODE_RESTRICTED;
+ } else {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ }
+ break;
+ case Ndis802_11Encryption2Enabled:
+ case Ndis802_11Encryption3Enabled:
+ erq->length = 16;
+ erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
+ break;
+ default:
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ break;
+ }
+
+
+ return ret;
+}
+
+static int rtw_wx_get_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wrqu->power.value = 0;
+ wrqu->power.fixed = 0; /* no auto select */
+ wrqu->power.disabled = 1;
+
+ return 0;
+}
+
+static int rtw_wx_set_gen_ie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
+ return ret;
+}
+
+static int rtw_wx_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_param *param = (struct iw_param *)&wrqu->param;
+ int ret = 0;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ break;
+ case IW_AUTH_CIPHER_PAIRWISE:
+
+ break;
+ case IW_AUTH_CIPHER_GROUP:
+
+ break;
+ case IW_AUTH_KEY_MGMT:
+ /*
+ * ??? does not use these parameters
+ */
+ break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ if (param->value) {
+ /* wpa_supplicant is enabling the tkip countermeasure. */
+ padapter->securitypriv.btkip_countermeasure = true;
+ } else {
+ /* wpa_supplicant is disabling the tkip countermeasure. */
+ padapter->securitypriv.btkip_countermeasure = false;
+ }
+ break;
+ case IW_AUTH_DROP_UNENCRYPTED:
+ /* HACK:
+ *
+ * wpa_supplicant calls set_wpa_enabled when the driver
+ * is loaded and unloaded, regardless of if WPA is being
+ * used. No other calls are made which can be used to
+ * determine if encryption will be used or not prior to
+ * association being expected. If encryption is not being
+ * used, drop_unencrypted is set to false, else true -- we
+ * can use this to determine if the CAP_PRIVACY_ON bit should
+ * be set.
+ */
+
+ if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
+ break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
+ /* then it needn't reset it; */
+
+ if (param->value) {
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+ }
+
+ break;
+ case IW_AUTH_80211_AUTH_ALG:
+ /*
+ * It's the starting point of a link layer connection using wpa_supplicant
+ */
+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+ LeaveAllPowerSaveMode(padapter);
+ rtw_disassoc_cmd(padapter, 500, false);
+ DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
+ rtw_indicate_disconnect(padapter);
+ rtw_free_assoc_resources(padapter, 1);
+ }
+ ret = wpa_set_auth_algs(dev, (u32)param->value);
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ break;
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ break;
+ case IW_AUTH_PRIVACY_INVOKED:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static int rtw_wx_set_enc_ext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ char *alg_name;
+ u32 param_len;
+ struct ieee_param *param = NULL;
+ struct iw_point *pencoding = &wrqu->encoding;
+ struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
+ int ret = 0;
+
+ param_len = sizeof(struct ieee_param) + pext->key_len;
+ param = kzalloc(param_len, GFP_KERNEL);
+ if (!param)
+ return -ENOMEM;
+
+ param->cmd = IEEE_CMD_SET_ENCRYPTION;
+ memset(param->sta_addr, 0xff, ETH_ALEN);
+
+ switch (pext->alg) {
+ case IW_ENCODE_ALG_NONE:
+ /* todo: remove key */
+ /* remove = 1; */
+ alg_name = "none";
+ break;
+ case IW_ENCODE_ALG_WEP:
+ alg_name = "WEP";
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ alg_name = "TKIP";
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ alg_name = "CCMP";
+ break;
+ default:
+ return -1;
+ }
+
+ strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
+
+ if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ param->u.crypt.set_tx = 1;
+
+ /* cliW: WEP does not have group key
+ * just not checking GROUP key setting
+ */
+ if ((pext->alg != IW_ENCODE_ALG_WEP) &&
+ (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
+ param->u.crypt.set_tx = 0;
+
+ param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
+
+ if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
+ memcpy(param->u.crypt.seq, pext->rx_seq, 8);
+
+ if (pext->key_len) {
+ param->u.crypt.key_len = pext->key_len;
+ memcpy(param->u.crypt.key, pext + 1, pext->key_len);
+ }
+
+ ret = wpa_set_encryption(dev, param, param_len);
+
+ kfree(param);
+ return ret;
+}
+
+static int rtw_wx_get_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ if (extra) {
+ wrqu->data.length = 14;
+ wrqu->data.flags = 1;
+ memcpy(extra, "<WIFI@REALTEK>", 14);
+ }
+
+ /* dump debug info here */
+ return 0;
+}
+
+static int rtw_wx_read32(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter;
+ struct iw_point *p;
+ u16 len;
+ u32 addr;
+ u32 data32;
+ u32 bytes;
+ u8 *ptmp;
+
+ padapter = (struct adapter *)rtw_netdev_priv(dev);
+ p = &wrqu->data;
+ len = p->length;
+ ptmp = kmalloc(len, GFP_KERNEL);
+ if (!ptmp)
+ return -ENOMEM;
+
+ if (copy_from_user(ptmp, p->pointer, len)) {
+ kfree(ptmp);
+ return -EFAULT;
+ }
+
+ bytes = 0;
+ addr = 0;
+ sscanf(ptmp, "%d,%x", &bytes, &addr);
+
+ switch (bytes) {
+ case 1:
+ data32 = rtw_read8(padapter, addr);
+ sprintf(extra, "0x%02X", data32);
+ break;
+ case 2:
+ data32 = rtw_read16(padapter, addr);
+ sprintf(extra, "0x%04X", data32);
+ break;
+ case 4:
+ data32 = rtw_read32(padapter, addr);
+ sprintf(extra, "0x%08X", data32);
+ break;
+ default:
+ DBG_88E(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
+ return -EINVAL;
+ }
+ DBG_88E(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra);
+
+ kfree(ptmp);
+ return 0;
+}
+
+static int rtw_wx_write32(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ u32 addr;
+ u32 data32;
+ u32 bytes;
+
+ bytes = 0;
+ addr = 0;
+ data32 = 0;
+ sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
+
+ switch (bytes) {
+ case 1:
+ rtw_write8(padapter, addr, (u8)data32);
+ DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
+ break;
+ case 2:
+ rtw_write16(padapter, addr, (u16)data32);
+ DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
+ break;
+ case 4:
+ rtw_write32(padapter, addr, data32);
+ DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
+ break;
+ default:
+ DBG_88E(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rtw_wx_read_rf(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u32 path, addr, data32;
+
+ path = *(u32 *)extra;
+ addr = *((u32 *)extra + 1);
+ data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
+ /*
+ * IMPORTANT!!
+ * Only when wireless private ioctl is at odd order,
+ * "extra" would be copied to user space.
+ */
+ sprintf(extra, "0x%05x", data32);
+
+ return 0;
+}
+
+static int rtw_wx_write_rf(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u32 path, addr, data32;
+
+ path = *(u32 *)extra;
+ addr = *((u32 *)extra + 1);
+ data32 = *((u32 *)extra + 2);
+ rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
+
+ return 0;
+}
+
+static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ return -1;
+}
+
+static int dummy(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ return -1;
+}
+
+static int rtw_wx_set_channel_plan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 channel_plan_req = (u8)(*((int *)wrqu));
+
+ if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1))
+ DBG_88E("%s set channel_plan = 0x%02X\n", __func__, pmlmepriv->ChannelPlan);
+ else
+ return -EPERM;
+
+ return 0;
+}
+
+static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ return 0;
+}
+
+static int rtw_wx_get_sensitivity(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *buf)
+{
+ return 0;
+}
+
+static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ return 0;
+}
+
+/*
+ * For all data larger than 16 octets, we need to use a
+ * pointer to memory allocated in user space.
+ */
+static int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ return 0;
+}
+
+static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 len)
+{
+ struct mp_rw_reg *RegRWStruct;
+ struct rf_reg_param *prfreg;
+ u8 path;
+ u8 offset;
+ u32 value;
+
+ DBG_88E("%s\n", __func__);
+
+ switch (id) {
+ case GEN_MP_IOCTL_SUBCODE(MP_START):
+ DBG_88E("871x_driver is only for normal mode, can't enter mp mode\n");
+ break;
+ case GEN_MP_IOCTL_SUBCODE(READ_REG):
+ RegRWStruct = (struct mp_rw_reg *)pdata;
+ switch (RegRWStruct->width) {
+ case 1:
+ RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
+ break;
+ case 2:
+ RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
+ break;
+ case 4:
+ RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
+ RegRWStruct = (struct mp_rw_reg *)pdata;
+ switch (RegRWStruct->width) {
+ case 1:
+ rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
+ break;
+ case 2:
+ rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
+ break;
+ case 4:
+ rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
+
+ prfreg = (struct rf_reg_param *)pdata;
+
+ path = (u8)prfreg->path;
+ offset = (u8)prfreg->offset;
+
+ value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
+
+ prfreg->value = value;
+
+ break;
+ case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
+
+ prfreg = (struct rf_reg_param *)pdata;
+
+ path = (u8)prfreg->path;
+ offset = (u8)prfreg->offset;
+ value = prfreg->value;
+
+ rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
+
+ break;
+ case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
+ DBG_88E("==> trigger gpio 0\n");
+ rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, NULL);
+ break;
+ case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
+ *pdata = rtw_hal_sreset_get_wifi_status(padapter);
+ break;
+ default:
+ break;
+ }
+}
+
+static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ u32 BytesRead, BytesWritten, BytesNeeded;
+ struct oid_par_priv oid_par;
+ struct mp_ioctl_handler *phandler;
+ struct mp_ioctl_param *poidparam;
+ uint status = 0;
+ u16 len;
+ u8 *pparmbuf = NULL, bset;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_point *p = &wrqu->data;
+
+ if ((!p->length) || (!p->pointer)) {
+ ret = -EINVAL;
+ goto _rtw_mp_ioctl_hdl_exit;
+ }
+ pparmbuf = NULL;
+ bset = (u8)(p->flags & 0xFFFF);
+ len = p->length;
+ pparmbuf = kmalloc(len, GFP_KERNEL);
+ if (!pparmbuf) {
+ ret = -ENOMEM;
+ goto _rtw_mp_ioctl_hdl_exit;
+ }
+
+ if (copy_from_user(pparmbuf, p->pointer, len)) {
+ ret = -EFAULT;
+ goto _rtw_mp_ioctl_hdl_exit;
+ }
+
+ poidparam = (struct mp_ioctl_param *)pparmbuf;
+
+ if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
+ ret = -EINVAL;
+ goto _rtw_mp_ioctl_hdl_exit;
+ }
+
+ if (padapter->registrypriv.mp_mode == 1) {
+ phandler = mp_ioctl_hdl + poidparam->subcode;
+
+ if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) {
+ ret = -EINVAL;
+ goto _rtw_mp_ioctl_hdl_exit;
+ }
+
+ if (phandler->handler) {
+ oid_par.adapter_context = padapter;
+ oid_par.oid = phandler->oid;
+ oid_par.information_buf = poidparam->data;
+ oid_par.information_buf_len = poidparam->len;
+ oid_par.dbg = 0;
+
+ BytesWritten = 0;
+ BytesNeeded = 0;
+
+ if (bset) {
+ oid_par.bytes_rw = &BytesRead;
+ oid_par.bytes_needed = &BytesNeeded;
+ oid_par.type_of_oid = SET_OID;
+ } else {
+ oid_par.bytes_rw = &BytesWritten;
+ oid_par.bytes_needed = &BytesNeeded;
+ oid_par.type_of_oid = QUERY_OID;
+ }
+
+ status = phandler->handler(&oid_par);
+ } else {
+ DBG_88E("rtw_mp_ioctl_hdl(): err!, subcode =%d, oid =%d, handler =%p\n",
+ poidparam->subcode, phandler->oid, phandler->handler);
+ ret = -EFAULT;
+ goto _rtw_mp_ioctl_hdl_exit;
+ }
+ } else {
+ rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
+ }
+
+ if (bset == 0x00) {/* query info */
+ if (copy_to_user(p->pointer, pparmbuf, len))
+ ret = -EFAULT;
+ }
+
+ if (status) {
+ ret = -EFAULT;
+ goto _rtw_mp_ioctl_hdl_exit;
+ }
+
+_rtw_mp_ioctl_hdl_exit:
+
+ kfree(pparmbuf);
+ return ret;
+}
+
+static int rtw_get_ap_info(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ u32 cnt = 0, wpa_ielen;
+ struct list_head *plist, *phead;
+ unsigned char *pbuf;
+ u8 bssid[ETH_ALEN];
+ char data[32];
+ struct wlan_network *pnetwork = NULL;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct iw_point *pdata = &wrqu->data;
+
+ DBG_88E("+rtw_get_aplist_info\n");
+
+ if (padapter->bDriverStopped || !pdata) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING)))) {
+ msleep(30);
+ cnt++;
+ if (cnt > 100)
+ break;
+ }
+ pdata->flags = 0;
+ if (pdata->length >= 32) {
+ if (copy_from_user(data, pdata->pointer, 32)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ } else {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ if (!mac_pton(data, bssid)) {
+ DBG_88E("Invalid BSSID '%s'.\n", (u8 *)data);
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ return -EINVAL;
+ }
+
+ if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
+ /* BSSID match, then check if supporting wpa/wpa2 */
+ DBG_88E("BSSID:%pM\n", (bssid));
+
+ pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
+ if (pbuf && (wpa_ielen > 0)) {
+ pdata->flags = 1;
+ break;
+ }
+
+ pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
+ if (pbuf && (wpa_ielen > 0)) {
+ pdata->flags = 2;
+ break;
+ }
+ }
+
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (pdata->length >= 34) {
+ if (copy_to_user(pdata->pointer + 32, (u8 *)&pdata->flags, 1)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ }
+
+exit:
+
+ return ret;
+}
+
+static int rtw_set_pid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ int *pdata = (int *)wrqu;
+ int selector;
+
+ if (padapter->bDriverStopped || !pdata) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ selector = *pdata;
+ if (selector < 3 && selector >= 0) {
+ padapter->pid[selector] = *(pdata + 1);
+ ui_pid[selector] = *(pdata + 1);
+ DBG_88E("%s set pid[%d] =%d\n", __func__, selector, padapter->pid[selector]);
+ } else {
+ DBG_88E("%s selector %d error\n", __func__, selector);
+ }
+exit:
+ return ret;
+}
+
+static int rtw_wps_start(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_point *pdata = &wrqu->data;
+ u32 u32wps_start = 0;
+
+ if (!pdata)
+ return -EINVAL;
+ ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
+ if (ret) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (padapter->bDriverStopped) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (u32wps_start == 0)
+ u32wps_start = *extra;
+
+ DBG_88E("[%s] wps_start = %d\n", __func__, u32wps_start);
+
+ if (u32wps_start == 1) /* WPS Start */
+ rtw_led_control(padapter, LED_CTL_START_WPS);
+ else if (u32wps_start == 2) /* WPS Stop because of wps success */
+ rtw_led_control(padapter, LED_CTL_STOP_WPS);
+ else if (u32wps_start == 3) /* WPS Stop because of wps fail */
+ rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
+
+exit:
+ return ret;
+}
+
+#ifdef CONFIG_88EU_P2P
+static int rtw_wext_p2p_enable(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
+
+ if (*extra == '0')
+ init_role = P2P_ROLE_DISABLE;
+ else if (*extra == '1')
+ init_role = P2P_ROLE_DEVICE;
+ else if (*extra == '2')
+ init_role = P2P_ROLE_CLIENT;
+ else if (*extra == '3')
+ init_role = P2P_ROLE_GO;
+
+ if (_FAIL == rtw_p2p_enable(padapter, init_role)) {
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ /* set channel/bandwidth */
+ if (init_role != P2P_ROLE_DISABLE) {
+ u8 channel, ch_offset;
+ u16 bwmode;
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
+ /* Stay at the listen state and wait for discovery. */
+ channel = pwdinfo->listen_channel;
+ pwdinfo->operating_channel = pwdinfo->listen_channel;
+ ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ bwmode = HT_CHANNEL_WIDTH_20;
+ } else {
+ pwdinfo->operating_channel = pmlmeext->cur_channel;
+
+ channel = pwdinfo->operating_channel;
+ ch_offset = pmlmeext->cur_ch_offset;
+ bwmode = pmlmeext->cur_bwmode;
+ }
+
+ set_channel_bwmode(padapter, channel, ch_offset, bwmode);
+ }
+
+exit:
+ return ret;
+}
+
+static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("[%s] ssid = %s, len = %zu\n", __func__, extra, strlen(extra));
+ memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
+ pwdinfo->nego_ssidlen = strlen(extra);
+
+ return ret;
+}
+
+static int rtw_p2p_set_intent(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 intent = pwdinfo->intent;
+
+ switch (wrqu->data.length) {
+ case 1:
+ intent = extra[0] - '0';
+ break;
+ case 2:
+ intent = str_2char2num(extra[0], extra[1]);
+ break;
+ }
+ if (intent <= 15)
+ pwdinfo->intent = intent;
+ else
+ ret = -1;
+ DBG_88E("[%s] intent = %d\n", __func__, intent);
+ return ret;
+}
+
+static int rtw_p2p_set_listen_ch(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 listen_ch = pwdinfo->listen_channel; /* Listen channel number */
+
+ switch (wrqu->data.length) {
+ case 1:
+ listen_ch = extra[0] - '0';
+ break;
+ case 2:
+ listen_ch = str_2char2num(extra[0], extra[1]);
+ break;
+ }
+
+ if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
+ pwdinfo->listen_channel = listen_ch;
+ set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ } else {
+ ret = -1;
+ }
+
+ DBG_88E("[%s] listen_ch = %d\n", __func__, pwdinfo->listen_channel);
+
+ return ret;
+}
+
+static int rtw_p2p_set_op_ch(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+/* Commented by Albert 20110524 */
+/* This function is used to set the operating channel if the driver will become the group owner */
+
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 op_ch = pwdinfo->operating_channel; /* Operating channel number */
+
+ switch (wrqu->data.length) {
+ case 1:
+ op_ch = extra[0] - '0';
+ break;
+ case 2:
+ op_ch = str_2char2num(extra[0], extra[1]);
+ break;
+ }
+
+ if (op_ch > 0)
+ pwdinfo->operating_channel = op_ch;
+ else
+ ret = -1;
+
+ DBG_88E("[%s] op_ch = %d\n", __func__, pwdinfo->operating_channel);
+
+ return ret;
+}
+
+static int rtw_p2p_profilefound(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ /* Comment by Albert 2010/10/13 */
+ /* Input data format: */
+ /* Ex: 0 */
+ /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */
+ /* 0 => Reflush the profile record list. */
+ /* 1 => Add the profile list */
+ /* XX:XX:XX:XX:XX:XX => peer's MAC Address (ex: 00:E0:4C:00:00:01) */
+ /* YY => SSID Length */
+ /* SSID => SSID for persistence group */
+
+ DBG_88E("[%s] In value = %s, len = %d\n", __func__, extra, wrqu->data.length - 1);
+
+ /* The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+ if (extra[0] == '0') {
+ /* Remove all the profile information of wifidirect_info structure. */
+ memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
+ pwdinfo->profileindex = 0;
+ } else {
+ if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM) {
+ ret = -1;
+ } else {
+ int jj, kk;
+
+ /* Add this profile information into pwdinfo->profileinfo */
+ /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */
+ for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
+ pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+ pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = (extra[18] - '0') * 10 + (extra[19] - '0');
+ memcpy(pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen);
+ pwdinfo->profileindex++;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int rtw_p2p_setDN(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
+ memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
+ memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
+ pwdinfo->device_name_len = wrqu->data.length - 1;
+
+ return ret;
+}
+
+static int rtw_p2p_get_status(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ if (padapter->bShowGetP2PState)
+ DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
+ pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
+
+ /* Commented by Albert 2010/10/12 */
+ /* Because of the output size limitation, I had removed the "Role" information. */
+ /* About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
+ sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo));
+ wrqu->data.length = strlen(extra);
+
+ return ret;
+}
+
+/* Commented by Albert 20110520 */
+/* This function will return the config method description */
+/* This config method description will show us which config method the remote P2P device is intended to use */
+/* by sending the provisioning discovery request frame. */
+
+static int rtw_p2p_get_req_cm(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
+ wrqu->data.length = strlen(extra);
+ return ret;
+}
+
+static int rtw_p2p_get_role(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
+ pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
+
+ sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo));
+ wrqu->data.length = strlen(extra);
+ return ret;
+}
+
+static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
+ rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ pwdinfo->p2p_peer_interface_addr);
+ sprintf(extra, "\nMAC %pM",
+ pwdinfo->p2p_peer_interface_addr);
+ wrqu->data.length = strlen(extra);
+ return ret;
+}
+
+static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
+ rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ pwdinfo->rx_prov_disc_info.peerDevAddr);
+ sprintf(extra, "\n%pM",
+ pwdinfo->rx_prov_disc_info.peerDevAddr);
+ wrqu->data.length = strlen(extra);
+ return ret;
+}
+
+static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n",
+ __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
+ pwdinfo->p2p_peer_device_addr);
+ sprintf(extra, "\nMAC %pM",
+ pwdinfo->p2p_peer_device_addr);
+ wrqu->data.length = strlen(extra);
+ return ret;
+}
+
+static int rtw_p2p_get_groupid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
+ pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1],
+ pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3],
+ pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5],
+ pwdinfo->groupid_info.ssid);
+ wrqu->data.length = strlen(extra);
+ return ret;
+}
+
+static int rtw_p2p_get_op_ch(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
+
+ sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel);
+ wrqu->data.length = strlen(extra);
+ return ret;
+}
+
+static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u8 peerMAC[ETH_ALEN] = {0x00};
+ int jj, kk;
+ u8 peerMACStr[17] = {0x00};
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *plist, *phead;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ u8 blnMatch = 0;
+ u16 attr_content = 0;
+ uint attr_contentlen = 0;
+ /* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
+ u8 attr_content_str[6 + 17] = {0x00};
+
+ /* Commented by Albert 20110727 */
+ /* The input data is the MAC address which the application wants to know its WPS config method. */
+ /* After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
+ /* Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
+
+ DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
+ if (copy_from_user(peerMACStr, wrqu->data.pointer + 6, 17))
+ return -EFAULT;
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+ if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+ u8 *wpsie;
+ uint wpsie_len = 0;
+ __be16 be_tmp;
+
+ /* The mac address is matched. */
+ wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
+ if (wpsie) {
+ rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *)&be_tmp, &attr_contentlen);
+ if (attr_contentlen) {
+ attr_content = be16_to_cpu(be_tmp);
+ sprintf(attr_content_str, "\n\nM =%.4d", attr_content);
+ blnMatch = 1;
+ }
+ }
+ break;
+ }
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (!blnMatch)
+ sprintf(attr_content_str, "\n\nM = 0000");
+
+ if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
+ return -EFAULT;
+ return ret;
+}
+
+static int rtw_p2p_get_go_device_address(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u8 peerMAC[ETH_ALEN] = {0x00};
+ int jj, kk;
+ u8 peerMACStr[17] = {0x00};
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *plist, *phead;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ u8 blnMatch = 0;
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+ u8 attr_content[100] = {0x00};
+
+ u8 go_devadd_str[100 + 10] = {0x00};
+ /* +10 is for the str "go_devadd =", we have to clear it at wrqu->data.pointer */
+
+ /* Commented by Albert 20121209 */
+ /* The input data is the GO's interface address which the application wants to know its device address. */
+ /* Format: iwpriv wlanx p2p_get2 go_devadd = 00:E0:4C:00:00:05 */
+
+ DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
+ if (copy_from_user(peerMACStr, wrqu->data.pointer + 10, 17))
+ return -EFAULT;
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+ if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+ /* Commented by Albert 2011/05/18 */
+ /* Match the device address located in the P2P IE */
+ /* This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+ p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
+ if (p2pie) {
+ while (p2pie) {
+ /* The P2P Device ID attribute is included in the Beacon frame. */
+ /* The P2P Device Info attribute is included in the probe response frame. */
+
+ memset(attr_content, 0x00, 100);
+ if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
+ /* Handle the P2P Device ID attribute of Beacon first */
+ blnMatch = 1;
+ break;
+ } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
+ /* Handle the P2P Device Info attribute of probe response */
+ blnMatch = 1;
+ break;
+ }
+
+ /* Get the next P2P IE */
+ p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
+ }
+ }
+ }
+
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (!blnMatch)
+ sprintf(go_devadd_str, "\n\ndev_add = NULL");
+ else
+ sprintf(go_devadd_str, "\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+ attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
+
+ if (copy_to_user(wrqu->data.pointer, go_devadd_str, 10 + 17))
+ return -EFAULT;
+ return ret;
+}
+
+static int rtw_p2p_get_device_type(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u8 peerMAC[ETH_ALEN] = {0x00};
+ int jj, kk;
+ u8 peerMACStr[17] = {0x00};
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *plist, *phead;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ u8 blnMatch = 0;
+ u8 dev_type[8] = {0x00};
+ uint dev_type_len = 0;
+ u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */
+
+ /* Commented by Albert 20121209 */
+ /* The input data is the MAC address which the application wants to know its device type. */
+ /* Such user interface could know the device type. */
+ /* Format: iwpriv wlanx p2p_get2 dev_type = 00:E0:4C:00:00:05 */
+
+ DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
+ if (copy_from_user(peerMACStr, wrqu->data.pointer + 9, 17))
+ return -EFAULT;
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+ if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+ u8 *wpsie;
+ uint wpsie_len = 0;
+
+ /* The mac address is matched. */
+
+ wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12],
+ pnetwork->network.IELength - 12,
+ NULL, &wpsie_len);
+ if (wpsie) {
+ rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
+ if (dev_type_len) {
+ u16 type = 0;
+ __be16 be_tmp;
+
+ memcpy(&be_tmp, dev_type, 2);
+ type = be16_to_cpu(be_tmp);
+ sprintf(dev_type_str, "\n\nN =%.2d", type);
+ blnMatch = 1;
+ }
+ }
+ break;
+ }
+
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (!blnMatch)
+ sprintf(dev_type_str, "\n\nN = 00");
+
+ if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
+static int rtw_p2p_get_device_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u8 peerMAC[ETH_ALEN] = {0x00};
+ int jj, kk;
+ u8 peerMACStr[17] = {0x00};
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *plist, *phead;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ u8 blnMatch = 0;
+ u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
+ uint dev_len = 0;
+ u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */
+
+ /* Commented by Albert 20121225 */
+ /* The input data is the MAC address which the application wants to know its device name. */
+ /* Such user interface could show peer device's device name instead of ssid. */
+ /* Format: iwpriv wlanx p2p_get2 devN = 00:E0:4C:00:00:05 */
+
+ DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
+ if (copy_from_user(peerMACStr, wrqu->data.pointer + 5, 17))
+ return -EFAULT;
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+ if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+ u8 *wpsie;
+ uint wpsie_len = 0;
+
+ /* The mac address is matched. */
+ wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
+ if (wpsie) {
+ rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
+ if (dev_len) {
+ sprintf(dev_name_str, "\n\nN =%s", dev_name);
+ blnMatch = 1;
+ }
+ }
+ break;
+ }
+
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (!blnMatch)
+ sprintf(dev_name_str, "\n\nN = 0000");
+
+ if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
+ return -EFAULT;
+ return ret;
+}
+
+static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u8 peerMAC[ETH_ALEN] = {0x00};
+ int jj, kk;
+ u8 peerMACStr[17] = {0x00};
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *plist, *phead;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ u8 blnMatch = 0;
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+ u8 attr_content[2] = {0x00};
+
+ u8 inv_proc_str[17 + 8] = {0x00};
+ /* +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */
+
+ /* Commented by Ouden 20121226 */
+ /* The application wants to know P2P initiation procedure is supported or not. */
+ /* Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */
+
+ DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
+ if (copy_from_user(peerMACStr, wrqu->data.pointer + 8, 17))
+ return -EFAULT;
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+ if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+ /* Commented by Albert 20121226 */
+ /* Match the device address located in the P2P IE */
+ /* This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+ p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
+ if (p2pie) {
+ while (p2pie) {
+ if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
+ /* Handle the P2P capability attribute */
+ blnMatch = 1;
+ break;
+ }
+
+ /* Get the next P2P IE */
+ p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
+ }
+ }
+ }
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (!blnMatch) {
+ sprintf(inv_proc_str, "\nIP =-1");
+ } else {
+ if (attr_content[0] & 0x20)
+ sprintf(inv_proc_str, "\nIP = 1");
+ else
+ sprintf(inv_proc_str, "\nIP = 0");
+ }
+ if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
+ return -EFAULT;
+ return ret;
+}
+
+static int rtw_p2p_connect(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 peerMAC[ETH_ALEN] = {0x00};
+ int jj, kk;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *plist, *phead;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ uint uintPeerChannel = 0;
+
+ /* Commented by Albert 20110304 */
+ /* The input data contains two informations. */
+ /* 1. First information is the MAC address which wants to formate with */
+ /* 2. Second information is the WPS PINCode or "pbc" string for push button method */
+ /* Format: 00:E0:4C:00:00:05 */
+ /* Format: 00:E0:4C:00:00:05 */
+
+ DBG_88E("[%s] data = %s\n", __func__, extra);
+
+ if (pwdinfo->p2p_state == P2P_STATE_NONE) {
+ DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
+ return ret;
+ }
+
+ if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
+ return -1;
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+ if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
+ uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+ break;
+ }
+
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (uintPeerChannel) {
+ memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
+ memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
+
+ pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel;
+ memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
+ pwdinfo->nego_req_info.benable = true;
+
+ _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+ if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
+ /* Restore to the listen state if the current p2p state is not nego OK */
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+ }
+
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
+
+ DBG_88E("[%s] Start PreTx Procedure!\n", __func__);
+ _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+ _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
+ } else {
+ DBG_88E("[%s] Not Found in Scanning Queue~\n", __func__);
+ ret = -1;
+ }
+ return ret;
+}
+
+static int rtw_p2p_invite_req(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ int jj, kk;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *plist, *phead;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ uint uintPeerChannel = 0;
+ u8 attr_content[50] = {0x00};
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+ struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info;
+
+ /* The input data contains two informations. */
+ /* 1. First information is the P2P device address which you want to send to. */
+ /* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
+ /* Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
+ /* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
+
+ DBG_88E("[%s] data = %s\n", __func__, extra);
+
+ if (wrqu->data.length <= 37) {
+ DBG_88E("[%s] Wrong format!\n", __func__);
+ return ret;
+ }
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+ DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
+ return ret;
+ } else {
+ /* Reset the content of struct tx_invite_req_info */
+ pinvite_req_info->benable = false;
+ memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
+ memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
+ pinvite_req_info->ssidlen = 0x00;
+ pinvite_req_info->operating_ch = pwdinfo->operating_channel;
+ memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
+ pinvite_req_info->token = 3;
+ }
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ /* Commented by Albert 2011/05/18 */
+ /* Match the device address located in the P2P IE */
+ /* This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+ p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
+ if (p2pie) {
+ /* The P2P Device ID attribute is included in the Beacon frame. */
+ /* The P2P Device Info attribute is included in the probe response frame. */
+
+ if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
+ /* Handle the P2P Device ID attribute of Beacon first */
+ if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
+ uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+ break;
+ }
+ } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
+ /* Handle the P2P Device Info attribute of probe response */
+ if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
+ uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+ break;
+ }
+ }
+ }
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (uintPeerChannel) {
+ /* Store the GO's bssid */
+ for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
+ pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+ /* Store the GO's ssid */
+ pinvite_req_info->ssidlen = wrqu->data.length - 36;
+ memcpy(pinvite_req_info->go_ssid, &extra[36], (u32)pinvite_req_info->ssidlen);
+ pinvite_req_info->benable = true;
+ pinvite_req_info->peer_ch = uintPeerChannel;
+
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
+
+ set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+
+ _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+
+ _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
+ } else {
+ DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
+ }
+ return ret;
+}
+
+static int rtw_p2p_set_persistent(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ /* The input data is 0 or 1 */
+ /* 0: disable persistent group functionality */
+ /* 1: enable persistent group founctionality */
+
+ DBG_88E("[%s] data = %s\n", __func__, extra);
+
+ if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+ DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
+ return ret;
+ } else {
+ if (extra[0] == '0') /* Disable the persistent group function. */
+ pwdinfo->persistent_supported = false;
+ else if (extra[0] == '1') /* Enable the persistent group function. */
+ pwdinfo->persistent_supported = true;
+ else
+ pwdinfo->persistent_supported = false;
+ }
+ pr_info("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported);
+ return ret;
+}
+
+static int rtw_p2p_prov_disc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ u8 peerMAC[ETH_ALEN] = {0x00};
+ int jj, kk;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct list_head *plist, *phead;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ uint uintPeerChannel = 0;
+ u8 attr_content[100] = {0x00};
+ u8 *p2pie;
+ uint p2pielen = 0, attr_contentlen = 0;
+
+ /* The input data contains two informations. */
+ /* 1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
+ /* 2. Second information is the WPS configuration method which wants to discovery */
+ /* Format: 00:E0:4C:00:00:05_display */
+ /* Format: 00:E0:4C:00:00:05_keypad */
+ /* Format: 00:E0:4C:00:00:05_pbc */
+ /* Format: 00:E0:4C:00:00:05_label */
+
+ DBG_88E("[%s] data = %s\n", __func__, extra);
+
+ if (pwdinfo->p2p_state == P2P_STATE_NONE) {
+ DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
+ return ret;
+ } else {
+ /* Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
+ memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
+ memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
+ memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(struct ndis_802_11_ssid));
+ pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
+ pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
+ pwdinfo->tx_prov_disc_info.benable = false;
+ }
+
+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+ peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
+
+ if (!memcmp(&extra[18], "display", 7)) {
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
+ } else if (!memcmp(&extra[18], "keypad", 7)) {
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
+ } else if (!memcmp(&extra[18], "pbc", 3)) {
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
+ } else if (!memcmp(&extra[18], "label", 5)) {
+ pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
+ } else {
+ DBG_88E("[%s] Unknown WPS config methodn", __func__);
+ return ret;
+ }
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ if (uintPeerChannel != 0)
+ break;
+
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ /* Commented by Albert 2011/05/18 */
+ /* Match the device address located in the P2P IE */
+ /* This is for the case that the P2P device address is not the same as the P2P interface address. */
+
+ p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
+ if (p2pie) {
+ while (p2pie) {
+ /* The P2P Device ID attribute is included in the Beacon frame. */
+ /* The P2P Device Info attribute is included in the probe response frame. */
+
+ if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
+ /* Handle the P2P Device ID attribute of Beacon first */
+ if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
+ uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+ break;
+ }
+ } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
+ /* Handle the P2P Device Info attribute of probe response */
+ if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
+ uintPeerChannel = pnetwork->network.Configuration.DSConfig;
+ break;
+ }
+ }
+
+ /* Get the next P2P IE */
+ p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
+ }
+ }
+
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ if (uintPeerChannel) {
+ DBG_88E("[%s] peer channel: %d!\n", __func__, uintPeerChannel);
+ memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
+ memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
+ pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16)uintPeerChannel;
+ pwdinfo->tx_prov_disc_info.benable = true;
+ rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
+
+ if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
+ memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
+ } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+ memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
+ pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
+ }
+
+ set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+
+ _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
+
+ _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
+ } else {
+ DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
+ }
+ return ret;
+}
+
+/* This function is used to inform the driver the user had specified the pin code value or pbc */
+/* to application. */
+
+static int rtw_p2p_got_wpsinfo(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+ DBG_88E("[%s] data = %s\n", __func__, extra);
+ /* Added by Albert 20110328 */
+ /* if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
+ /* if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
+ /* if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
+ /* if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
+
+ if (*extra == '0')
+ pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
+ else if (*extra == '1')
+ pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
+ else if (*extra == '2')
+ pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
+ else if (*extra == '3')
+ pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
+ else
+ pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
+ return ret;
+}
+
+#endif /* CONFIG_88EU_P2P */
+
+static int rtw_p2p_set(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+#ifdef CONFIG_88EU_P2P
+ DBG_88E("[%s] extra = %s\n", __func__, extra);
+ if (!memcmp(extra, "enable =", 7)) {
+ rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
+ } else if (!memcmp(extra, "setDN =", 6)) {
+ wrqu->data.length -= 6;
+ rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
+ } else if (!memcmp(extra, "profilefound =", 13)) {
+ wrqu->data.length -= 13;
+ rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
+ } else if (!memcmp(extra, "prov_disc =", 10)) {
+ wrqu->data.length -= 10;
+ rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
+ } else if (!memcmp(extra, "nego =", 5)) {
+ wrqu->data.length -= 5;
+ rtw_p2p_connect(dev, info, wrqu, &extra[5]);
+ } else if (!memcmp(extra, "intent =", 7)) {
+ /* Commented by Albert 2011/03/23 */
+ /* The wrqu->data.length will include the null character */
+ /* So, we will decrease 7 + 1 */
+ wrqu->data.length -= 8;
+ rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
+ } else if (!memcmp(extra, "ssid =", 5)) {
+ wrqu->data.length -= 5;
+ rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
+ } else if (!memcmp(extra, "got_wpsinfo =", 12)) {
+ wrqu->data.length -= 12;
+ rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
+ } else if (!memcmp(extra, "listen_ch =", 10)) {
+ /* Commented by Albert 2011/05/24 */
+ /* The wrqu->data.length will include the null character */
+ /* So, we will decrease (10 + 1) */
+ wrqu->data.length -= 11;
+ rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
+ } else if (!memcmp(extra, "op_ch =", 6)) {
+ /* Commented by Albert 2011/05/24 */
+ /* The wrqu->data.length will include the null character */
+ /* So, we will decrease (6 + 1) */
+ wrqu->data.length -= 7;
+ rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
+ } else if (!memcmp(extra, "invite =", 7)) {
+ wrqu->data.length -= 8;
+ rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
+ } else if (!memcmp(extra, "persistent =", 11)) {
+ wrqu->data.length -= 11;
+ rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
+ }
+#endif /* CONFIG_88EU_P2P */
+
+ return ret;
+}
+
+static int rtw_p2p_get(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+#ifdef CONFIG_88EU_P2P
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ if (padapter->bShowGetP2PState)
+ DBG_88E("[%s] extra = %s\n", __func__, (char *)wrqu->data.pointer);
+ if (!memcmp(wrqu->data.pointer, "status", 6)) {
+ rtw_p2p_get_status(dev, info, wrqu, extra);
+ } else if (!memcmp(wrqu->data.pointer, "role", 4)) {
+ rtw_p2p_get_role(dev, info, wrqu, extra);
+ } else if (!memcmp(wrqu->data.pointer, "peer_ifa", 8)) {
+ rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra);
+ } else if (!memcmp(wrqu->data.pointer, "req_cm", 6)) {
+ rtw_p2p_get_req_cm(dev, info, wrqu, extra);
+ } else if (!memcmp(wrqu->data.pointer, "peer_deva", 9)) {
+ /* Get the P2P device address when receiving the provision discovery request frame. */
+ rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra);
+ } else if (!memcmp(wrqu->data.pointer, "group_id", 8)) {
+ rtw_p2p_get_groupid(dev, info, wrqu, extra);
+ } else if (!memcmp(wrqu->data.pointer, "peer_deva_inv", 9)) {
+ /* Get the P2P device address when receiving the P2P Invitation request frame. */
+ rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
+ } else if (!memcmp(wrqu->data.pointer, "op_ch", 5)) {
+ rtw_p2p_get_op_ch(dev, info, wrqu, extra);
+ }
+#endif /* CONFIG_88EU_P2P */
+ return ret;
+}
+
+static int rtw_p2p_get2(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+#ifdef CONFIG_88EU_P2P
+ DBG_88E("[%s] extra = %s\n", __func__, (char *)wrqu->data.pointer);
+ if (!memcmp(extra, "wpsCM =", 6)) {
+ wrqu->data.length -= 6;
+ rtw_p2p_get_wps_configmethod(dev, info, wrqu, &extra[6]);
+ } else if (!memcmp(extra, "devN =", 5)) {
+ wrqu->data.length -= 5;
+ rtw_p2p_get_device_name(dev, info, wrqu, &extra[5]);
+ } else if (!memcmp(extra, "dev_type =", 9)) {
+ wrqu->data.length -= 9;
+ rtw_p2p_get_device_type(dev, info, wrqu, &extra[9]);
+ } else if (!memcmp(extra, "go_devadd =", 10)) {
+ wrqu->data.length -= 10;
+ rtw_p2p_get_go_device_address(dev, info, wrqu, &extra[10]);
+ } else if (!memcmp(extra, "InvProc =", 8)) {
+ wrqu->data.length -= 8;
+ rtw_p2p_get_invitation_procedure(dev, info, wrqu, &extra[8]);
+ }
+
+#endif /* CONFIG_88EU_P2P */
+
+ return ret;
+}
+
+static int rtw_cta_test_start(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ DBG_88E("%s %s\n", __func__, extra);
+ if (!strcmp(extra, "1"))
+ padapter->in_cta_test = 1;
+ else
+ padapter->in_cta_test = 0;
+
+ if (padapter->in_cta_test) {
+ u32 v = rtw_read32(padapter, REG_RCR);
+ v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */
+ rtw_write32(padapter, REG_RCR, v);
+ DBG_88E("enable RCR_ADF\n");
+ } else {
+ u32 v = rtw_read32(padapter, REG_RCR);
+ v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;/* RCR_ADF */
+ rtw_write32(padapter, REG_RCR, v);
+ DBG_88E("disable RCR_ADF\n");
+ }
+ return ret;
+}
+
+static int rtw_rereg_nd_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
+ char new_ifname[IFNAMSIZ];
+
+ if (rereg_priv->old_ifname[0] == 0) {
+ char *reg_ifname;
+ reg_ifname = padapter->registrypriv.if2name;
+
+ strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
+ rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
+ }
+
+ if (wrqu->data.length > IFNAMSIZ)
+ return -EFAULT;
+
+ if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
+ return -EFAULT;
+
+ if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
+ return ret;
+
+ DBG_88E("%s new_ifname:%s\n", __func__, new_ifname);
+ ret = rtw_change_ifname(padapter, new_ifname);
+ if (0 != ret)
+ goto exit;
+
+ if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
+ padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
+ rtw_hal_sw_led_init(padapter);
+ rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
+ }
+
+ strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
+ rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
+
+ if (!memcmp(new_ifname, "disable%d", 9)) {
+ DBG_88E("%s disable\n", __func__);
+ /* free network queue for Android's timming issue */
+ rtw_free_network_queue(padapter, true);
+
+ /* close led */
+ rtw_led_control(padapter, LED_CTL_POWER_OFF);
+ rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
+ padapter->ledpriv.bRegUseLed = false;
+ rtw_hal_sw_led_deinit(padapter);
+
+ /* the interface is being "disabled", we can do deeper IPS */
+ rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
+ rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
+ }
+exit:
+ return ret;
+}
+
+static void mac_reg_dump(struct adapter *padapter)
+{
+ int i, j = 1;
+ pr_info("\n ======= MAC REG =======\n");
+ for (i = 0x0; i < 0x300; i += 4) {
+ if (j % 4 == 1)
+ pr_info("0x%02x", i);
+ pr_info(" 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ pr_info("\n");
+ }
+ for (i = 0x400; i < 0x800; i += 4) {
+ if (j % 4 == 1)
+ pr_info("0x%02x", i);
+ pr_info(" 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ pr_info("\n");
+ }
+}
+
+static void bb_reg_dump(struct adapter *padapter)
+{
+ int i, j = 1;
+ pr_info("\n ======= BB REG =======\n");
+ for (i = 0x800; i < 0x1000; i += 4) {
+ if (j % 4 == 1)
+ pr_info("0x%02x", i);
+
+ pr_info(" 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ pr_info("\n");
+ }
+}
+
+static void rf_reg_dump(struct adapter *padapter)
+{
+ int i, j = 1, path;
+ u32 value;
+ u8 rf_type, path_nums = 0;
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+ pr_info("\n ======= RF REG =======\n");
+ if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
+ path_nums = 1;
+ else
+ path_nums = 2;
+
+ for (path = 0; path < path_nums; path++) {
+ pr_info("\nRF_Path(%x)\n", path);
+ for (i = 0; i < 0x100; i++) {
+ value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
+ if (j % 4 == 1)
+ pr_info("0x%02x ", i);
+ pr_info(" 0x%08x ", value);
+ if ((j++) % 4 == 0)
+ pr_info("\n");
+ }
+ }
+}
+
+static int rtw_dbg_port(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ u8 major_cmd, minor_cmd;
+ u16 arg;
+ s32 extra_arg;
+ u32 *pdata, val32;
+ struct sta_info *psta;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ pdata = (u32 *)&wrqu->data;
+
+ val32 = *pdata;
+ arg = (u16)(val32 & 0x0000ffff);
+ major_cmd = (u8)(val32 >> 24);
+ minor_cmd = (u8)((val32 >> 16) & 0x00ff);
+
+ extra_arg = *(pdata + 1);
+
+ switch (major_cmd) {
+ case 0x70:/* read_reg */
+ switch (minor_cmd) {
+ case 1:
+ DBG_88E("rtw_read8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
+ break;
+ case 2:
+ DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
+ break;
+ case 4:
+ DBG_88E("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
+ break;
+ }
+ break;
+ case 0x71:/* write_reg */
+ switch (minor_cmd) {
+ case 1:
+ rtw_write8(padapter, arg, extra_arg);
+ DBG_88E("rtw_write8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
+ break;
+ case 2:
+ rtw_write16(padapter, arg, extra_arg);
+ DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
+ break;
+ case 4:
+ rtw_write32(padapter, arg, extra_arg);
+ DBG_88E("rtw_write32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
+ break;
+ }
+ break;
+ case 0x72:/* read_bb */
+ DBG_88E("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
+ break;
+ case 0x73:/* write_bb */
+ rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
+ DBG_88E("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
+ break;
+ case 0x74:/* read_rf */
+ DBG_88E("read RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
+ break;
+ case 0x75:/* write_rf */
+ rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
+ DBG_88E("write RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
+ break;
+
+ case 0x76:
+ switch (minor_cmd) {
+ case 0x00: /* normal mode, */
+ padapter->recvpriv.is_signal_dbg = 0;
+ break;
+ case 0x01: /* dbg mode */
+ padapter->recvpriv.is_signal_dbg = 1;
+ extra_arg = extra_arg > 100 ? 100 : extra_arg;
+ extra_arg = extra_arg < 0 ? 0 : extra_arg;
+ padapter->recvpriv.signal_strength_dbg = extra_arg;
+ break;
+ }
+ break;
+ case 0x78: /* IOL test */
+ switch (minor_cmd) {
+ case 0x04: /* LLT table initialization test */
+ {
+ u8 page_boundary = 0xf9;
+ struct xmit_frame *xmit_frame;
+
+ xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+ if (!xmit_frame) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
+
+ if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0))
+ ret = -EPERM;
+ }
+ break;
+ case 0x05: /* blink LED test */
+ {
+ u16 reg = 0x4c;
+ u32 blink_num = 50;
+ u32 blink_delay_ms = 200;
+ int i;
+ struct xmit_frame *xmit_frame;
+
+ xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+ if (!xmit_frame) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ for (i = 0; i < blink_num; i++) {
+ rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
+ rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
+ rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
+ rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
+ }
+ if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms * blink_num * 2) + 200, 0))
+ ret = -EPERM;
+ }
+ break;
+
+ case 0x06: /* continuous write byte test */
+ {
+ u16 reg = arg;
+ u16 start_value = 0;
+ u32 write_num = extra_arg;
+ int i;
+ u8 final;
+ struct xmit_frame *xmit_frame;
+
+ xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+ if (!xmit_frame) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ for (i = 0; i < write_num; i++)
+ rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value, 0xFF);
+ if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
+ ret = -EPERM;
+
+ final = rtw_read8(padapter, reg);
+ if (start_value + write_num - 1 == final)
+ DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
+ else
+ DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
+ }
+ break;
+
+ case 0x07: /* continuous write word test */
+ {
+ u16 reg = arg;
+ u16 start_value = 200;
+ u32 write_num = extra_arg;
+
+ int i;
+ u16 final;
+ struct xmit_frame *xmit_frame;
+
+ xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+ if (!xmit_frame) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ for (i = 0; i < write_num; i++)
+ rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value, 0xFFFF);
+ if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
+ ret = -EPERM;
+
+ final = rtw_read16(padapter, reg);
+ if (start_value + write_num - 1 == final)
+ DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
+ else
+ DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
+ }
+ break;
+ case 0x08: /* continuous write dword test */
+ {
+ u16 reg = arg;
+ u32 start_value = 0x110000c7;
+ u32 write_num = extra_arg;
+
+ int i;
+ u32 final;
+ struct xmit_frame *xmit_frame;
+
+ xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
+ if (!xmit_frame) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ for (i = 0; i < write_num; i++)
+ rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value, 0xFFFFFFFF);
+ if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
+ ret = -EPERM;
+
+ final = rtw_read32(padapter, reg);
+ if (start_value + write_num - 1 == final)
+ DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n",
+ reg, write_num, start_value, final);
+ else
+ DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n",
+ reg, write_num, start_value, final);
+ }
+ break;
+ }
+ break;
+ case 0x79:
+ {
+ /*
+ * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
+ * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
+ */
+ u8 value = extra_arg & 0x0f;
+ u8 sign = minor_cmd;
+ u16 write_value = 0;
+
+ DBG_88E("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value);
+
+ if (sign)
+ value = value | 0x10;
+
+ write_value = value | (value << 5);
+ rtw_write16(padapter, 0x6d9, write_value);
+ }
+ break;
+ case 0x7a:
+ receive_disconnect(padapter, pmlmeinfo->network.MacAddress
+ , WLAN_REASON_EXPIRATION_CHK);
+ break;
+ case 0x7F:
+ switch (minor_cmd) {
+ case 0x0:
+ DBG_88E("fwstate = 0x%x\n", get_fwstate(pmlmepriv));
+ break;
+ case 0x01:
+ DBG_88E("auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n",
+ psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
+ psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
+ break;
+ case 0x02:
+ DBG_88E("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state);
+ break;
+ case 0x03:
+ DBG_88E("qos_option =%d\n", pmlmepriv->qospriv.qos_option);
+ DBG_88E("ht_option =%d\n", pmlmepriv->htpriv.ht_option);
+ break;
+ case 0x04:
+ DBG_88E("cur_ch =%d\n", pmlmeext->cur_channel);
+ DBG_88E("cur_bw =%d\n", pmlmeext->cur_bwmode);
+ DBG_88E("cur_ch_off =%d\n", pmlmeext->cur_ch_offset);
+ break;
+ case 0x05:
+ psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
+ if (psta) {
+ int i;
+ struct recv_reorder_ctrl *preorder_ctrl;
+
+ DBG_88E("SSID =%s\n", cur_network->network.Ssid.Ssid);
+ DBG_88E("sta's macaddr: %pM\n", psta->hwaddr);
+ DBG_88E("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
+ DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
+ DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+ DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
+ DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
+ DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
+ DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+ for (i = 0; i < 16; i++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
+ if (preorder_ctrl->enable)
+ DBG_88E("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq);
+ }
+ } else {
+ DBG_88E("can't get sta's macaddr, cur_network's macaddr:%pM\n", (cur_network->network.MacAddress));
+ }
+ break;
+ case 0x06:
+ {
+ u32 ODMFlag;
+ rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
+ DBG_88E("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg);
+ ODMFlag = (u32)(0x0f & arg);
+ DBG_88E("(A)DMFlag = 0x%x\n", ODMFlag);
+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
+ }
+ break;
+ case 0x07:
+ DBG_88E("bSurpriseRemoved =%d, bDriverStopped =%d\n",
+ padapter->bSurpriseRemoved, padapter->bDriverStopped);
+ break;
+ case 0x08:
+ {
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
+ DBG_88E("free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d, free_xmit_extbuf_cnt =%d\n",
+ pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt);
+ DBG_88E("rx_urb_pending_cn =%d\n", precvpriv->rx_pending_cnt);
+ }
+ break;
+ case 0x09:
+ {
+ int i, j;
+ struct list_head *plist, *phead;
+ struct recv_reorder_ctrl *preorder_ctrl;
+
+#ifdef CONFIG_88EU_AP_MODE
+ DBG_88E("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
+#endif
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+
+ for (i = 0; i < NUM_STA; i++) {
+ phead = &pstapriv->sta_hash[i];
+ plist = phead->next;
+
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, hash_list);
+
+ plist = plist->next;
+
+ if (extra_arg == psta->aid) {
+ DBG_88E("sta's macaddr:%pM\n", (psta->hwaddr));
+ DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
+ DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+ DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
+ DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
+ DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
+ DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+
+#ifdef CONFIG_88EU_AP_MODE
+ DBG_88E("capability = 0x%x\n", psta->capability);
+ DBG_88E("flags = 0x%x\n", psta->flags);
+ DBG_88E("wpa_psk = 0x%x\n", psta->wpa_psk);
+ DBG_88E("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher);
+ DBG_88E("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher);
+ DBG_88E("qos_info = 0x%x\n", psta->qos_info);
+#endif
+ DBG_88E("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy);
+
+ for (j = 0; j < 16; j++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[j];
+ if (preorder_ctrl->enable)
+ DBG_88E("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq);
+ }
+ }
+ }
+ }
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+ }
+ break;
+ case 0x0c:/* dump rx/tx packet */
+ if (arg == 0) {
+ DBG_88E("dump rx packet (%d)\n", extra_arg);
+ rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
+ } else if (arg == 1) {
+ DBG_88E("dump tx packet (%d)\n", extra_arg);
+ rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
+ }
+ break;
+ case 0x0f:
+ if (extra_arg == 0) {
+ DBG_88E("###### silent reset test.......#####\n");
+ rtw_hal_sreset_reset(padapter);
+ }
+ break;
+ case 0x15:
+ {
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ DBG_88E("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts);
+ }
+ break;
+ case 0x10:/* driver version display */
+ DBG_88E("rtw driver version =%s\n", DRIVERVERSION);
+ break;
+ case 0x11:
+ DBG_88E("turn %s Rx RSSI display function\n", (extra_arg == 1) ? "on" : "off");
+ padapter->bRxRSSIDisplay = extra_arg;
+ break;
+ case 0x12: /* set rx_stbc */
+ {
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
+ /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
+ if (pregpriv &&
+ (extra_arg == 0 ||
+ extra_arg == 1 ||
+ extra_arg == 2 ||
+ extra_arg == 3)) {
+ pregpriv->rx_stbc = extra_arg;
+ DBG_88E("set rx_stbc =%d\n", pregpriv->rx_stbc);
+ } else {
+ DBG_88E("get rx_stbc =%d\n", pregpriv->rx_stbc);
+ }
+ }
+ break;
+ case 0x13: /* set ampdu_enable */
+ {
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
+ if (pregpriv && extra_arg >= 0 && extra_arg < 3) {
+ pregpriv->ampdu_enable = extra_arg;
+ DBG_88E("set ampdu_enable =%d\n", pregpriv->ampdu_enable);
+ } else {
+ DBG_88E("get ampdu_enable =%d\n", pregpriv->ampdu_enable);
+ }
+ }
+ break;
+ case 0x14: /* get wifi_spec */
+ {
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ DBG_88E("get wifi_spec =%d\n", pregpriv->wifi_spec);
+ }
+ break;
+ case 0x23:
+ DBG_88E("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off");
+ padapter->bNotifyChannelChange = extra_arg;
+ break;
+ case 0x24:
+#ifdef CONFIG_88EU_P2P
+ DBG_88E("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off");
+ padapter->bShowGetP2PState = extra_arg;
+#endif /* CONFIG_88EU_P2P */
+ break;
+ case 0xaa:
+ if (extra_arg > 0x13)
+ extra_arg = 0xFF;
+ DBG_88E("chang data rate to :0x%02x\n", extra_arg);
+ padapter->fix_rate = extra_arg;
+ break;
+ case 0xdd:/* registers dump, 0 for mac reg, 1 for bb reg, 2 for rf reg */
+ if (extra_arg == 0)
+ mac_reg_dump(padapter);
+ else if (extra_arg == 1)
+ bb_reg_dump(padapter);
+ else if (extra_arg == 2)
+ rf_reg_dump(padapter);
+ break;
+ case 0xee:/* turn on/off dynamic funcs */
+ {
+ u32 odm_flag;
+
+ if (0xf == extra_arg) {
+ rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
+ DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
+ DBG_88E("extra_arg = 0 - disable all dynamic func\n");
+ DBG_88E("extra_arg = 1 - disable DIG- BIT(0)\n");
+ DBG_88E("extra_arg = 2 - disable High power - BIT(1)\n");
+ DBG_88E("extra_arg = 3 - disable tx power tracking - BIT(2)\n");
+ DBG_88E("extra_arg = 4 - disable BT coexistence - BIT(3)\n");
+ DBG_88E("extra_arg = 5 - disable antenna diversity - BIT(4)\n");
+ DBG_88E("extra_arg = 6 - enable all dynamic func\n");
+ } else {
+ /* extra_arg = 0 - disable all dynamic func
+ extra_arg = 1 - disable DIG
+ extra_arg = 2 - disable tx power tracking
+ extra_arg = 3 - turn on all dynamic func
+ */
+ rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
+ rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
+ DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
+ }
+ }
+ break;
+
+ case 0xfd:
+ rtw_write8(padapter, 0xc50, arg);
+ DBG_88E("wr(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
+ rtw_write8(padapter, 0xc58, arg);
+ DBG_88E("wr(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
+ break;
+ case 0xfe:
+ DBG_88E("rd(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
+ DBG_88E("rd(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
+ break;
+ case 0xff:
+ DBG_88E("dbg(0x210) = 0x%x\n", rtw_read32(padapter, 0x210));
+ DBG_88E("dbg(0x608) = 0x%x\n", rtw_read32(padapter, 0x608));
+ DBG_88E("dbg(0x280) = 0x%x\n", rtw_read32(padapter, 0x280));
+ DBG_88E("dbg(0x284) = 0x%x\n", rtw_read32(padapter, 0x284));
+ DBG_88E("dbg(0x288) = 0x%x\n", rtw_read32(padapter, 0x288));
+
+ DBG_88E("dbg(0x664) = 0x%x\n", rtw_read32(padapter, 0x664));
+
+ DBG_88E("\n");
+
+ DBG_88E("dbg(0x430) = 0x%x\n", rtw_read32(padapter, 0x430));
+ DBG_88E("dbg(0x438) = 0x%x\n", rtw_read32(padapter, 0x438));
+
+ DBG_88E("dbg(0x440) = 0x%x\n", rtw_read32(padapter, 0x440));
+
+ DBG_88E("dbg(0x458) = 0x%x\n", rtw_read32(padapter, 0x458));
+
+ DBG_88E("dbg(0x484) = 0x%x\n", rtw_read32(padapter, 0x484));
+ DBG_88E("dbg(0x488) = 0x%x\n", rtw_read32(padapter, 0x488));
+
+ DBG_88E("dbg(0x444) = 0x%x\n", rtw_read32(padapter, 0x444));
+ DBG_88E("dbg(0x448) = 0x%x\n", rtw_read32(padapter, 0x448));
+ DBG_88E("dbg(0x44c) = 0x%x\n", rtw_read32(padapter, 0x44c));
+ DBG_88E("dbg(0x450) = 0x%x\n", rtw_read32(padapter, 0x450));
+ break;
+ }
+ break;
+ default:
+ DBG_88E("error dbg cmd!\n");
+ break;
+ }
+ return ret;
+}
+
+static int rtw_wx_set_priv(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *awrq,
+ char *extra)
+{
+ int ret = 0;
+ int len = 0;
+ char *ext;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_point *dwrq = (struct iw_point *)awrq;
+
+ if (dwrq->length == 0)
+ return -EFAULT;
+
+ len = dwrq->length;
+ ext = vmalloc(len);
+ if (!ext)
+ return -ENOMEM;
+
+ if (copy_from_user(ext, dwrq->pointer, len)) {
+ vfree(ext);
+ return -EFAULT;
+ }
+
+ /* added for wps2.0 @20110524 */
+ if (dwrq->flags == 0x8766 && len > 8) {
+ u32 cp_sz;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 *probereq_wpsie = ext;
+ int probereq_wpsie_len = len;
+ u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
+ (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
+ cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
+
+ pmlmepriv->wps_probe_req_ie_len = 0;
+ kfree(pmlmepriv->wps_probe_req_ie);
+ pmlmepriv->wps_probe_req_ie = NULL;
+
+ pmlmepriv->wps_probe_req_ie = kmalloc(cp_sz, GFP_KERNEL);
+ if (!pmlmepriv->wps_probe_req_ie) {
+ ret = -EINVAL;
+ goto FREE_EXT;
+ }
+ memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
+ pmlmepriv->wps_probe_req_ie_len = cp_sz;
+ }
+ goto FREE_EXT;
+ }
+
+ if (len >= WEXT_CSCAN_HEADER_SIZE &&
+ !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
+ ret = rtw_wx_set_scan(dev, info, awrq, ext);
+ goto FREE_EXT;
+ }
+
+FREE_EXT:
+
+ vfree(ext);
+
+ return ret;
+}
+
+static int rtw_pm_set(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ unsigned mode = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ DBG_88E("[%s] extra = %s\n", __func__, extra);
+
+ if (!memcmp(extra, "lps =", 4)) {
+ sscanf(extra + 4, "%u", &mode);
+ ret = rtw_pm_set_lps(padapter, mode);
+ } else if (!memcmp(extra, "ips =", 4)) {
+ sscanf(extra + 4, "%u", &mode);
+ ret = rtw_pm_set_ips(padapter, mode);
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int rtw_mp_efuse_get(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wdata, char *extra)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+ struct hal_data_8188e *haldata = GET_HAL_DATA(padapter);
+ struct efuse_hal *pEfuseHal;
+ struct iw_point *wrqu;
+
+ u8 *PROMContent = pEEPROM->efuse_eeprom_data;
+ u8 ips_mode = 0, lps_mode = 0;
+ struct pwrctrl_priv *pwrctrlpriv;
+ u8 *data = NULL;
+ u8 *rawdata = NULL;
+ char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
+ u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
+ u16 max_available_size = 0, raw_cursize = 0, raw_maxsize = 0;
+ int err;
+ u8 org_fw_iol = padapter->registrypriv.fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
+
+ wrqu = (struct iw_point *)wdata;
+ pwrctrlpriv = &padapter->pwrctrlpriv;
+ pEfuseHal = &haldata->EfuseHal;
+
+ err = 0;
+ data = kzalloc(EFUSE_BT_MAX_MAP_LEN, GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ rawdata = kzalloc(EFUSE_BT_MAX_MAP_LEN, GFP_KERNEL);
+ if (!rawdata) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ if (copy_from_user(extra, wrqu->pointer, wrqu->length)) {
+ err = -EFAULT;
+ goto exit;
+ }
+ lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
+ rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+
+ ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
+ rtw_pm_set_ips(padapter, IPS_NONE);
+
+ pch = extra;
+ DBG_88E("%s: in =%s\n", __func__, extra);
+
+ i = 0;
+ /* mac 16 "00e04c871200" rmap, 00, 2 */
+ while ((token = strsep(&pch, ",")) != NULL) {
+ if (i > 2)
+ break;
+ tmp[i] = token;
+ i++;
+ }
+ padapter->registrypriv.fw_iol = 0;/* 0:Disable, 1:enable, 2:by usb speed */
+
+ if (strcmp(tmp[0], "status") == 0) {
+ sprintf(extra, "Load File efuse =%s, Load File MAC =%s", (pEEPROM->bloadfile_fail_flag ? "FAIL" : "OK"), (pEEPROM->bloadmac_fail_flag ? "FAIL" : "OK"));
+
+ goto exit;
+ } else if (strcmp(tmp[0], "filemap") == 0) {
+ mapLen = EFUSE_MAP_SIZE;
+
+ sprintf(extra, "\n");
+ for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
+ sprintf(extra + strlen(extra), "0x%02x\t", i);
+ for (j = 0; j < 8; j++)
+ sprintf(extra + strlen(extra), "%02X ", PROMContent[i + j]);
+ sprintf(extra + strlen(extra), "\t");
+ for (; j < 16; j++)
+ sprintf(extra + strlen(extra), "%02X ", PROMContent[i + j]);
+ sprintf(extra + strlen(extra), "\n");
+ }
+ } else if (strcmp(tmp[0], "realmap") == 0) {
+ mapLen = EFUSE_MAP_SIZE;
+ if (rtw_efuse_map_read(padapter, 0, mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL) {
+ DBG_88E("%s: read realmap Fail!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ sprintf(extra, "\n");
+ for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
+ sprintf(extra + strlen(extra), "0x%02x\t", i);
+ for (j = 0; j < 8; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeEfuseInitMap[i + j]);
+ sprintf(extra + strlen(extra), "\t");
+ for (; j < 16; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeEfuseInitMap[i + j]);
+ sprintf(extra + strlen(extra), "\n");
+ }
+ } else if (strcmp(tmp[0], "rmap") == 0) {
+ if (!tmp[1] || !tmp[2]) {
+ DBG_88E("%s: rmap Fail!! Parameters error!\n", __func__);
+ err = -EINVAL;
+ goto exit;
+ }
+
+ /* rmap addr cnts */
+ addr = simple_strtoul(tmp[1], &ptmp, 16);
+ DBG_88E("%s: addr =%x\n", __func__, addr);
+
+ cnts = simple_strtoul(tmp[2], &ptmp, 10);
+ if (cnts == 0) {
+ DBG_88E("%s: rmap Fail!! cnts error!\n", __func__);
+ err = -EINVAL;
+ goto exit;
+ }
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if ((addr + cnts) > max_available_size) {
+ DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+ err = -EINVAL;
+ goto exit;
+ }
+
+ if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ *extra = 0;
+ for (i = 0; i < cnts; i++)
+ sprintf(extra + strlen(extra), "0x%02X ", data[i]);
+ } else if (strcmp(tmp[0], "realraw") == 0) {
+ addr = 0;
+ mapLen = EFUSE_MAX_SIZE;
+ if (rtw_efuse_access(padapter, false, addr, mapLen, rawdata) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_access Fail!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ sprintf(extra, "\n");
+ for (i = 0; i < mapLen; i++) {
+ sprintf(extra + strlen(extra), "%02X", rawdata[i]);
+
+ if ((i & 0xF) == 0xF)
+ sprintf(extra + strlen(extra), "\n");
+ else if ((i & 0x7) == 0x7)
+ sprintf(extra + strlen(extra), "\t");
+ else
+ sprintf(extra + strlen(extra), " ");
+ }
+ } else if (strcmp(tmp[0], "mac") == 0) {
+ cnts = 6;
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if ((addr + cnts) > max_available_size) {
+ DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ *extra = 0;
+ for (i = 0; i < cnts; i++) {
+ sprintf(extra + strlen(extra), "%02X", data[i]);
+ if (i != (cnts - 1))
+ sprintf(extra + strlen(extra), ":");
+ }
+ } else if (strcmp(tmp[0], "vidpid") == 0) {
+ cnts = 4;
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if ((addr + cnts) > max_available_size) {
+ DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+ err = -EFAULT;
+ goto exit;
+ }
+ if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ *extra = 0;
+ for (i = 0; i < cnts; i++) {
+ sprintf(extra + strlen(extra), "0x%02X", data[i]);
+ if (i != (cnts - 1))
+ sprintf(extra + strlen(extra), ",");
+ }
+ } else if (strcmp(tmp[0], "ableraw") == 0) {
+ efuse_GetCurrentSize(padapter, &raw_cursize);
+ raw_maxsize = efuse_GetMaxSize(padapter);
+ sprintf(extra, "[available raw size] = %d bytes", raw_maxsize - raw_cursize);
+ } else if (strcmp(tmp[0], "btfmap") == 0) {
+ mapLen = EFUSE_BT_MAX_MAP_LEN;
+ if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
+ DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ sprintf(extra, "\n");
+ for (i = 0; i < 512; i += 16) {
+ /* set 512 because the iwpriv's extra size have limit 0x7FF */
+ sprintf(extra + strlen(extra), "0x%03x\t", i);
+ for (j = 0; j < 8; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->BTEfuseInitMap[i + j]);
+ sprintf(extra + strlen(extra), "\t");
+ for (; j < 16; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->BTEfuseInitMap[i + j]);
+ sprintf(extra + strlen(extra), "\n");
+ }
+ } else if (strcmp(tmp[0], "btbmap") == 0) {
+ mapLen = EFUSE_BT_MAX_MAP_LEN;
+ if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
+ DBG_88E("%s: rtw_BT_efuse_map_read Fail!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ sprintf(extra, "\n");
+ for (i = 512; i < 1024; i += 16) {
+ sprintf(extra + strlen(extra), "0x%03x\t", i);
+ for (j = 0; j < 8; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->BTEfuseInitMap[i + j]);
+ sprintf(extra + strlen(extra), "\t");
+ for (; j < 16; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->BTEfuseInitMap[i + j]);
+ sprintf(extra + strlen(extra), "\n");
+ }
+ } else if (strcmp(tmp[0], "btrmap") == 0) {
+ if (!tmp[1] || !tmp[2]) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ /* rmap addr cnts */
+ addr = simple_strtoul(tmp[1], &ptmp, 16);
+ DBG_88E("%s: addr = 0x%X\n", __func__, addr);
+
+ cnts = simple_strtoul(tmp[2], &ptmp, 10);
+ if (cnts == 0) {
+ DBG_88E("%s: btrmap Fail!! cnts error!\n", __func__);
+ err = -EINVAL;
+ goto exit;
+ }
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if ((addr + cnts) > max_available_size) {
+ DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
+ DBG_88E("%s: rtw_BT_efuse_map_read error!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ *extra = 0;
+ for (i = 0; i < cnts; i++)
+ sprintf(extra + strlen(extra), " 0x%02X ", data[i]);
+ } else if (strcmp(tmp[0], "btffake") == 0) {
+ sprintf(extra, "\n");
+ for (i = 0; i < 512; i += 16) {
+ sprintf(extra + strlen(extra), "0x%03x\t", i);
+ for (j = 0; j < 8; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+ sprintf(extra + strlen(extra), "\t");
+ for (; j < 16; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+ sprintf(extra + strlen(extra), "\n");
+ }
+ } else if (strcmp(tmp[0], "btbfake") == 0) {
+ sprintf(extra, "\n");
+ for (i = 512; i < 1024; i += 16) {
+ sprintf(extra + strlen(extra), "0x%03x\t", i);
+ for (j = 0; j < 8; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+ sprintf(extra + strlen(extra), "\t");
+ for (; j < 16; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
+ sprintf(extra + strlen(extra), "\n");
+ }
+ } else if (strcmp(tmp[0], "wlrfkmap") == 0) {
+ sprintf(extra, "\n");
+ for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
+ sprintf(extra + strlen(extra), "0x%02x\t", i);
+ for (j = 0; j < 8; j++)
+ sprintf(extra + strlen(extra), "%02X ", pEfuseHal->fakeEfuseModifiedMap[i + j]);
+ sprintf(extra + strlen(extra), "\t");
+ for (; j < 16; j++)
+ sprintf(extra + strlen(extra), " %02X", pEfuseHal->fakeEfuseModifiedMap[i + j]);
+ sprintf(extra + strlen(extra), "\n");
+ }
+ } else {
+ sprintf(extra, "Command not found!");
+ }
+
+exit:
+ kfree(data);
+ kfree(rawdata);
+ if (!err)
+ wrqu->length = strlen(extra);
+
+ rtw_pm_set_ips(padapter, ips_mode);
+ rtw_pm_set_lps(padapter, lps_mode);
+ padapter->registrypriv.fw_iol = org_fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
+ return err;
+}
+
+static int rtw_mp_efuse_set(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wdata, char *extra)
+{
+ struct adapter *padapter;
+ struct pwrctrl_priv *pwrctrlpriv;
+ struct hal_data_8188e *haldata;
+ struct efuse_hal *pEfuseHal;
+
+ u8 ips_mode = 0, lps_mode = 0;
+ u32 i, jj, kk;
+ u8 *setdata = NULL;
+ u8 *ShadowMapBT = NULL;
+ u8 *ShadowMapWiFi = NULL;
+ u8 *setrawdata = NULL;
+ char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
+ u16 addr = 0, cnts = 0, max_available_size = 0;
+ int err;
+
+ padapter = rtw_netdev_priv(dev);
+ pwrctrlpriv = &padapter->pwrctrlpriv;
+ haldata = GET_HAL_DATA(padapter);
+ pEfuseHal = &haldata->EfuseHal;
+ err = 0;
+ setdata = kzalloc(1024, GFP_KERNEL);
+ if (!setdata) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ ShadowMapBT = kmalloc(EFUSE_BT_MAX_MAP_LEN, GFP_KERNEL);
+ if (!ShadowMapBT) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ ShadowMapWiFi = kmalloc(EFUSE_MAP_SIZE, GFP_KERNEL);
+ if (!ShadowMapWiFi) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ setrawdata = kmalloc(EFUSE_MAX_SIZE, GFP_KERNEL);
+ if (!setrawdata) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
+ rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+
+ ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
+ rtw_pm_set_ips(padapter, IPS_NONE);
+
+ pch = extra;
+ DBG_88E("%s: in =%s\n", __func__, extra);
+
+ i = 0;
+ while ((token = strsep(&pch, ",")) != NULL) {
+ if (i > 2)
+ break;
+ tmp[i] = token;
+ i++;
+ }
+
+ /* tmp[0],[1],[2] */
+ /* wmap, addr, 00e04c871200 */
+ if (strcmp(tmp[0], "wmap") == 0) {
+ if (!tmp[1] || !tmp[2]) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ addr = simple_strtoul(tmp[1], &ptmp, 16);
+ addr &= 0xFFF;
+
+ cnts = strlen(tmp[2]);
+ if (cnts % 2) {
+ err = -EINVAL;
+ goto exit;
+ }
+ cnts /= 2;
+ if (cnts == 0) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ DBG_88E("%s: addr = 0x%X\n", __func__, addr);
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+ DBG_88E("%s: map data =%s\n", __func__, tmp[2]);
+
+ for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+ setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+ /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
+ if ((addr + cnts) > max_available_size) {
+ DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+ } else if (strcmp(tmp[0], "wraw") == 0) {
+ if (!tmp[1] || !tmp[2]) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ addr = simple_strtoul(tmp[1], &ptmp, 16);
+ addr &= 0xFFF;
+
+ cnts = strlen(tmp[2]);
+ if (cnts % 2) {
+ err = -EINVAL;
+ goto exit;
+ }
+ cnts /= 2;
+ if (cnts == 0) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ DBG_88E("%s: addr = 0x%X\n", __func__, addr);
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+ DBG_88E("%s: raw data =%s\n", __func__, tmp[2]);
+
+ for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+ setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+
+ if (rtw_efuse_access(padapter, true, addr, cnts, setrawdata) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+ } else if (strcmp(tmp[0], "mac") == 0) {
+ if (!tmp[1]) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ /* mac, 00e04c871200 */
+ addr = EEPROM_MAC_ADDR_88EU;
+ cnts = strlen(tmp[1]);
+ if (cnts % 2) {
+ err = -EINVAL;
+ goto exit;
+ }
+ cnts /= 2;
+ if (cnts == 0) {
+ err = -EINVAL;
+ goto exit;
+ }
+ if (cnts > 6) {
+ DBG_88E("%s: error data for mac addr =\"%s\"\n", __func__, tmp[1]);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ DBG_88E("%s: addr = 0x%X\n", __func__, addr);
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+ DBG_88E("%s: MAC address =%s\n", __func__, tmp[1]);
+
+ for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+ setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
+ /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
+ if ((addr + cnts) > max_available_size) {
+ DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+ } else if (strcmp(tmp[0], "vidpid") == 0) {
+ if (!tmp[1]) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ /* pidvid, da0b7881 */
+ addr = EEPROM_VID_88EE;
+ cnts = strlen(tmp[1]);
+ if (cnts % 2) {
+ err = -EINVAL;
+ goto exit;
+ }
+ cnts /= 2;
+ if (cnts == 0) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ DBG_88E("%s: addr = 0x%X\n", __func__, addr);
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+ DBG_88E("%s: VID/PID =%s\n", __func__, tmp[1]);
+
+ for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+ setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if ((addr + cnts) > max_available_size) {
+ DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+ } else if (strcmp(tmp[0], "btwmap") == 0) {
+ if (!tmp[1] || !tmp[2]) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ addr = simple_strtoul(tmp[1], &ptmp, 16);
+ addr &= 0xFFF;
+
+ cnts = strlen(tmp[2]);
+ if (cnts % 2) {
+ err = -EINVAL;
+ goto exit;
+ }
+ cnts /= 2;
+ if (cnts == 0) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ DBG_88E("%s: addr = 0x%X\n", __func__, addr);
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+ DBG_88E("%s: BT data =%s\n", __func__, tmp[2]);
+
+ for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+ setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if ((addr + cnts) > max_available_size) {
+ DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
+ DBG_88E("%s: rtw_BT_efuse_map_write error!!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+ } else if (strcmp(tmp[0], "btwfake") == 0) {
+ if (!tmp[1] || !tmp[2]) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ addr = simple_strtoul(tmp[1], &ptmp, 16);
+ addr &= 0xFFF;
+
+ cnts = strlen(tmp[2]);
+ if (cnts % 2) {
+ err = -EINVAL;
+ goto exit;
+ }
+ cnts /= 2;
+ if (cnts == 0) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ DBG_88E("%s: addr = 0x%X\n", __func__, addr);
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+ DBG_88E("%s: BT tmp data =%s\n", __func__, tmp[2]);
+
+ for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+ pEfuseHal->fakeBTEfuseModifiedMap[addr + jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+ } else if (strcmp(tmp[0], "btdumpfake") == 0) {
+ if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS) {
+ DBG_88E("%s: BT read all map success\n", __func__);
+ } else {
+ DBG_88E("%s: BT read all map Fail!\n", __func__);
+ err = -EFAULT;
+ }
+ } else if (strcmp(tmp[0], "wldumpfake") == 0) {
+ if (rtw_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS) {
+ DBG_88E("%s: BT read all map success\n", __func__);
+ } else {
+ DBG_88E("%s: BT read all map Fail\n", __func__);
+ err = -EFAULT;
+ }
+ } else if (strcmp(tmp[0], "btfk2map") == 0) {
+ memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN);
+
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if (max_available_size < 1) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL) {
+ DBG_88E("%s: rtw_BT_efuse_map_write error!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+ } else if (strcmp(tmp[0], "wlfk2map") == 0) {
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if (max_available_size < 1) {
+ err = -EFAULT;
+ goto exit;
+ }
+
+ if (rtw_efuse_map_write(padapter, 0x00, EFUSE_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) {
+ DBG_88E("%s: rtw_efuse_map_write error!\n", __func__);
+ err = -EFAULT;
+ goto exit;
+ }
+ } else if (strcmp(tmp[0], "wlwfake") == 0) {
+ if (!tmp[1] || !tmp[2]) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ addr = simple_strtoul(tmp[1], &ptmp, 16);
+ addr &= 0xFFF;
+
+ cnts = strlen(tmp[2]);
+ if (cnts % 2) {
+ err = -EINVAL;
+ goto exit;
+ }
+ cnts /= 2;
+ if (cnts == 0) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ DBG_88E("%s: addr = 0x%X\n", __func__, addr);
+ DBG_88E("%s: cnts =%d\n", __func__, cnts);
+ DBG_88E("%s: map tmp data =%s\n", __func__, tmp[2]);
+
+ for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
+ pEfuseHal->fakeEfuseModifiedMap[addr + jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
+ }
+
+exit:
+ kfree(setdata);
+ kfree(ShadowMapBT);
+ kfree(ShadowMapWiFi);
+ kfree(setrawdata);
+
+ rtw_pm_set_ips(padapter, ips_mode);
+ rtw_pm_set_lps(padapter, lps_mode);
+
+ return err;
+}
+
+/*
+ * Input Format: %s,%d,%d
+ * %s is width, could be
+ * "b" for 1 byte
+ * "w" for WORD (2 bytes)
+ * "dw" for DWORD (4 bytes)
+ * 1st %d is address(offset)
+ * 2st %d is data to write
+ */
+static int rtw_mp_write_reg(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ char *pch, *pnext, *ptmp;
+ char *width_str;
+ char width;
+ u32 addr, data;
+ int ret;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ pch = extra;
+ pnext = strpbrk(pch, ",.-");
+ if (!pnext)
+ return -EINVAL;
+ *pnext = 0;
+ width_str = pch;
+
+ pch = pnext + 1;
+ pnext = strpbrk(pch, ",.-");
+ if (!pnext)
+ return -EINVAL;
+ *pnext = 0;
+ addr = simple_strtoul(pch, &ptmp, 16);
+ if (addr > 0x3FFF)
+ return -EINVAL;
+
+ pch = pnext + 1;
+ if ((pch - extra) >= wrqu->length)
+ return -EINVAL;
+ data = simple_strtoul(pch, &ptmp, 16);
+
+ ret = 0;
+ width = width_str[0];
+ switch (width) {
+ case 'b':
+ /* 1 byte */
+ if (data > 0xFF) {
+ ret = -EINVAL;
+ break;
+ }
+ rtw_write8(padapter, addr, data);
+ break;
+ case 'w':
+ /* 2 bytes */
+ if (data > 0xFFFF) {
+ ret = -EINVAL;
+ break;
+ }
+ rtw_write16(padapter, addr, data);
+ break;
+ case 'd':
+ /* 4 bytes */
+ rtw_write32(padapter, addr, data);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Input Format: %s,%d
+ * %s is width, could be
+ * "b" for 1 byte
+ * "w" for WORD (2 bytes)
+ * "dw" for DWORD (4 bytes)
+ * %d is address(offset)
+ *
+ * Return:
+ * %d for data readed
+ */
+static int rtw_mp_read_reg(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ char *pch, *pnext, *ptmp;
+ char *width_str;
+ char width;
+ char data[20], tmp[20];
+ u32 addr;
+ u32 ret, i = 0, j = 0, strtout = 0;
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+ memset(data, 0, 20);
+ memset(tmp, 0, 20);
+ memset(extra, 0, wrqu->length);
+
+ pch = input;
+ pnext = strpbrk(pch, ",.-");
+ if (!pnext) {
+ kfree(input);
+ return -EINVAL;
+ }
+ *pnext = 0;
+ width_str = pch;
+
+ pch = pnext + 1;
+ if ((pch - input) >= wrqu->length) {
+ kfree(input);
+ return -EINVAL;
+ }
+ kfree(input);
+ addr = simple_strtoul(pch, &ptmp, 16);
+ if (addr > 0x3FFF)
+ return -EINVAL;
+
+ ret = 0;
+ width = width_str[0];
+ switch (width) {
+ case 'b':
+ /* 1 byte */
+ sprintf(extra, "%d\n", rtw_read8(padapter, addr));
+ wrqu->length = strlen(extra);
+ break;
+ case 'w':
+ /* 2 bytes */
+ sprintf(data, "%04x\n", rtw_read16(padapter, addr));
+ for (i = 0; i <= strlen(data); i++) {
+ if (i % 2 == 0) {
+ tmp[j] = ' ';
+ j++;
+ }
+ if (data[i] != '\0')
+ tmp[j] = data[i];
+ j++;
+ }
+ pch = tmp;
+ DBG_88E("pch =%s", pch);
+
+ while (*pch != '\0') {
+ pnext = strpbrk(pch, " ");
+ if (!pnext)
+ break;
+
+ pnext++;
+ if (*pnext != '\0') {
+ strtout = simple_strtoul(pnext, &ptmp, 16);
+ sprintf(extra, "%s %d", extra, strtout);
+ } else {
+ break;
+ }
+ pch = pnext;
+ }
+ wrqu->length = 6;
+ break;
+ case 'd':
+ /* 4 bytes */
+ sprintf(data, "%08x", rtw_read32(padapter, addr));
+ /* add read data format blank */
+ for (i = 0; i <= strlen(data); i++) {
+ if (i % 2 == 0) {
+ tmp[j] = ' ';
+ j++;
+ }
+ if (data[i] != '\0')
+ tmp[j] = data[i];
+
+ j++;
+ }
+ pch = tmp;
+ DBG_88E("pch =%s", pch);
+
+ while (*pch != '\0') {
+ pnext = strpbrk(pch, " ");
+ if (!pnext)
+ break;
+ pnext++;
+ if (*pnext != '\0') {
+ strtout = simple_strtoul(pnext, &ptmp, 16);
+ sprintf(extra, "%s %d", extra, strtout);
+ } else {
+ break;
+ }
+ pch = pnext;
+ }
+ wrqu->length = strlen(extra);
+ break;
+ default:
+ wrqu->length = 0;
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Input Format: %d,%x,%x
+ * %d is RF path, should be smaller than RF_PATH_MAX
+ * 1st %x is address(offset)
+ * 2st %x is data to write
+ */
+ static int rtw_mp_write_rf(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 path, addr, data;
+ int ret;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ ret = sscanf(extra, "%d,%x,%x", &path, &addr, &data);
+ if (ret < 3)
+ return -EINVAL;
+
+ if (path >= RF_PATH_MAX)
+ return -EINVAL;
+ if (addr > 0xFF)
+ return -EINVAL;
+ if (data > 0xFFFFF)
+ return -EINVAL;
+
+ memset(extra, 0, wrqu->length);
+
+ write_rfreg(padapter, path, addr, data);
+
+ sprintf(extra, "write_rf completed\n");
+ wrqu->length = strlen(extra);
+
+ return 0;
+}
+
+/*
+ * Input Format: %d,%x
+ * %d is RF path, should be smaller than RF_PATH_MAX
+ * %x is address(offset)
+ *
+ * Return:
+ * %d for data readed
+ */
+static int rtw_mp_read_rf(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ char *pch, *pnext, *ptmp;
+ char data[20], tmp[20];
+ u32 path, addr;
+ u32 ret, i = 0, j = 0, strtou = 0;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+ ret = sscanf(input, "%d,%x", &path, &addr);
+ kfree(input);
+ if (ret < 2)
+ return -EINVAL;
+
+ if (path >= RF_PATH_MAX)
+ return -EINVAL;
+ if (addr > 0xFF)
+ return -EINVAL;
+
+ memset(extra, 0, wrqu->length);
+
+ sprintf(data, "%08x", read_rfreg(padapter, path, addr));
+ /* add read data format blank */
+ for (i = 0; i <= strlen(data); i++) {
+ if (i % 2 == 0) {
+ tmp[j] = ' ';
+ j++;
+ }
+ tmp[j] = data[i];
+ j++;
+ }
+ pch = tmp;
+ DBG_88E("pch =%s", pch);
+
+ while (*pch != '\0') {
+ pnext = strpbrk(pch, " ");
+ pnext++;
+ if (*pnext != '\0') {
+ strtou = simple_strtoul(pnext, &ptmp, 16);
+ sprintf(extra, "%s %d", extra, strtou);
+ } else {
+ break;
+ }
+ pch = pnext;
+ }
+ wrqu->length = strlen(extra);
+ return 0;
+}
+
+static int rtw_mp_start(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (padapter->registrypriv.mp_mode == 0) {
+ padapter->registrypriv.mp_mode = 1;
+
+ rtw_pm_set_ips(padapter, IPS_NONE);
+ LeaveAllPowerSaveMode(padapter);
+
+ MPT_InitializeAdapter(padapter, 1);
+ }
+ if (padapter->registrypriv.mp_mode == 0)
+ return -EPERM;
+ if (padapter->mppriv.mode == MP_OFF) {
+ if (mp_start_test(padapter) == _FAIL)
+ return -EPERM;
+ padapter->mppriv.mode = MP_ON;
+ }
+ return 0;
+}
+
+static int rtw_mp_stop(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (padapter->registrypriv.mp_mode == 1) {
+ MPT_DeInitAdapter(padapter);
+ padapter->registrypriv.mp_mode = 0;
+ }
+
+ if (padapter->mppriv.mode != MP_OFF) {
+ mp_stop_test(padapter);
+ padapter->mppriv.mode = MP_OFF;
+ }
+
+ return 0;
+}
+
+extern int wifirate2_ratetbl_inx(unsigned char rate);
+
+static int rtw_mp_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 rate = MPT_RATE_1M;
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+ rate = rtw_atoi(input);
+ sprintf(extra, "Set data rate to %d", rate);
+ kfree(input);
+ if (rate <= 0x7f)
+ rate = wifirate2_ratetbl_inx((u8)rate);
+ else
+ rate = (rate - 0x80 + MPT_RATE_MCS0);
+
+ if (rate >= MPT_RATE_LAST)
+ return -EINVAL;
+
+ padapter->mppriv.rateidx = rate;
+ Hal_SetDataRate(padapter);
+
+ wrqu->length = strlen(extra) + 1;
+ return 0;
+}
+
+static int rtw_mp_channel(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ u32 channel = 1;
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+ channel = rtw_atoi(input);
+ sprintf(extra, "Change channel %d to channel %d", padapter->mppriv.channel, channel);
+
+ padapter->mppriv.channel = channel;
+ Hal_SetChannel(padapter);
+
+ wrqu->length = strlen(extra) + 1;
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_bandwidth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 bandwidth = 0, sg = 0;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ sscanf(extra, "40M =%d, shortGI =%d", &bandwidth, &sg);
+
+ if (bandwidth != HT_CHANNEL_WIDTH_40)
+ bandwidth = HT_CHANNEL_WIDTH_20;
+
+ padapter->mppriv.bandwidth = (u8)bandwidth;
+ padapter->mppriv.preamble = sg;
+
+ SetBandwidth(padapter);
+
+ return 0;
+}
+
+static int rtw_mp_txpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 idx_a = 0, idx_b = 0;
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+ sscanf(input, "patha =%d, pathb =%d", &idx_a, &idx_b);
+
+ sprintf(extra, "Set power level path_A:%d path_B:%d", idx_a, idx_b);
+ padapter->mppriv.txpoweridx = (u8)idx_a;
+ padapter->mppriv.txpoweridx_b = (u8)idx_b;
+ padapter->mppriv.bSetTxPower = 1;
+ Hal_SetAntennaPathPower(padapter);
+
+ wrqu->length = strlen(extra) + 1;
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_ant_tx(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 i;
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ u16 antenna = 0;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+
+ sprintf(extra, "switch Tx antenna to %s", input);
+
+ for (i = 0; i < strlen(input); i++) {
+ switch (input[i]) {
+ case 'a':
+ antenna |= ANTENNA_A;
+ break;
+ case 'b':
+ antenna |= ANTENNA_B;
+ break;
+ }
+ }
+ padapter->mppriv.antenna_tx = antenna;
+
+ Hal_SetAntenna(padapter);
+
+ wrqu->length = strlen(extra) + 1;
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_ant_rx(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 i;
+ u16 antenna = 0;
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+ memset(extra, 0, wrqu->length);
+
+ sprintf(extra, "switch Rx antenna to %s", input);
+
+ for (i = 0; i < strlen(input); i++) {
+ switch (input[i]) {
+ case 'a':
+ antenna |= ANTENNA_A;
+ break;
+ case 'b':
+ antenna |= ANTENNA_B;
+ break;
+ }
+ }
+
+ padapter->mppriv.antenna_rx = antenna;
+ Hal_SetAntenna(padapter);
+ wrqu->length = strlen(extra);
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_ctx(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 pkTx = 1, countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
+ u32 bStartTest = 1;
+ u32 count = 0;
+ struct mp_priv *pmp_priv;
+ struct pkt_attrib *pattrib;
+
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ pmp_priv = &padapter->mppriv;
+
+ if (copy_from_user(extra, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ DBG_88E("%s: in =%s\n", __func__, extra);
+
+ countPkTx = strncmp(extra, "count =", 5); /* strncmp true is 0 */
+ cotuTx = strncmp(extra, "background", 20);
+ CarrSprTx = strncmp(extra, "background, cs", 20);
+ scTx = strncmp(extra, "background, sc", 20);
+ sgleTx = strncmp(extra, "background, stone", 20);
+ pkTx = strncmp(extra, "background, pkt", 20);
+ stop = strncmp(extra, "stop", 4);
+ sscanf(extra, "count =%d, pkt", &count);
+
+ memset(extra, '\0', sizeof(*extra));
+
+ if (stop == 0) {
+ bStartTest = 0; /* To set Stop */
+ pmp_priv->tx.stop = 1;
+ sprintf(extra, "Stop continuous Tx");
+ } else {
+ bStartTest = 1;
+ if (pmp_priv->mode != MP_ON) {
+ if (pmp_priv->tx.stop != 1) {
+ DBG_88E("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
+ return -EFAULT;
+ }
+ }
+ }
+
+ if (pkTx == 0 || countPkTx == 0)
+ pmp_priv->mode = MP_PACKET_TX;
+ if (sgleTx == 0)
+ pmp_priv->mode = MP_SINGLE_TONE_TX;
+ if (cotuTx == 0)
+ pmp_priv->mode = MP_CONTINUOUS_TX;
+ if (CarrSprTx == 0)
+ pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
+ if (scTx == 0)
+ pmp_priv->mode = MP_SINGLE_CARRIER_TX;
+
+ switch (pmp_priv->mode) {
+ case MP_PACKET_TX:
+ if (bStartTest == 0) {
+ pmp_priv->tx.stop = 1;
+ pmp_priv->mode = MP_ON;
+ sprintf(extra, "Stop continuous Tx");
+ } else if (pmp_priv->tx.stop == 1) {
+ sprintf(extra, "Start continuous DA = ffffffffffff len = 1500 count =%u,\n", count);
+ pmp_priv->tx.stop = 0;
+ pmp_priv->tx.count = count;
+ pmp_priv->tx.payload = 2;
+ pattrib = &pmp_priv->tx.attrib;
+ pattrib->pktlen = 1500;
+ memset(pattrib->dst, 0xFF, ETH_ALEN);
+ SetPacketTx(padapter);
+ } else {
+ return -EFAULT;
+ }
+ wrqu->length = strlen(extra);
+ return 0;
+ case MP_SINGLE_TONE_TX:
+ if (bStartTest != 0)
+ sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
+ Hal_SetSingleToneTx(padapter, (u8)bStartTest);
+ break;
+ case MP_CONTINUOUS_TX:
+ if (bStartTest != 0)
+ sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
+ Hal_SetContinuousTx(padapter, (u8)bStartTest);
+ break;
+ case MP_CARRIER_SUPPRISSION_TX:
+ if (bStartTest != 0) {
+ if (pmp_priv->rateidx <= MPT_RATE_11M) {
+ sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
+ Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest);
+ } else {
+ sprintf(extra, "Specify carrier suppression but not CCK rate");
+ }
+ }
+ break;
+ case MP_SINGLE_CARRIER_TX:
+ if (bStartTest != 0)
+ sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
+ Hal_SetSingleCarrierTx(padapter, (u8)bStartTest);
+ break;
+ default:
+ sprintf(extra, "Error! Continuous-Tx is not on-going.");
+ return -EFAULT;
+ }
+
+ if (bStartTest == 1 && pmp_priv->mode != MP_ON) {
+ struct mp_priv *pmp_priv = &padapter->mppriv;
+ if (pmp_priv->tx.stop == 0) {
+ pmp_priv->tx.stop = 1;
+ msleep(5);
+ }
+ pmp_priv->tx.stop = 0;
+ pmp_priv->tx.count = 1;
+ SetPacketTx(padapter);
+ } else {
+ pmp_priv->mode = MP_ON;
+ }
+
+ wrqu->length = strlen(extra);
+ return 0;
+}
+
+static int rtw_mp_arx(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 bStartRx = 0, bStopRx = 0, bQueryPhy;
+ u32 cckok = 0, cckcrc = 0, ofdmok = 0, ofdmcrc = 0, htok = 0, htcrc = 0, OFDM_FA = 0, CCK_FA = 0;
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (!input)
+ return -ENOMEM;
+
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+ DBG_88E("%s: %s\n", __func__, input);
+
+ bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp true is 0 */
+ bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /* strncmp true is 0 */
+ bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp true is 0 */
+
+ if (bStartRx) {
+ sprintf(extra, "start");
+ SetPacketRx(padapter, bStartRx);
+ } else if (bStopRx) {
+ SetPacketRx(padapter, 0);
+ sprintf(extra, "Received packet OK:%d CRC error:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount);
+ } else if (bQueryPhy) {
+ /*
+ OFDM FA
+ RegCF0[15:0]
+ RegCF2[31:16]
+ RegDA0[31:16]
+ RegDA4[15:0]
+ RegDA4[31:16]
+ RegDA8[15:0]
+ CCK FA
+ (RegA5B<<8) | RegA5C
+ */
+ cckok = read_bbreg(padapter, 0xf88, 0xffffffff);
+ cckcrc = read_bbreg(padapter, 0xf84, 0xffffffff);
+ ofdmok = read_bbreg(padapter, 0xf94, 0x0000FFFF);
+ ofdmcrc = read_bbreg(padapter, 0xf94, 0xFFFF0000);
+ htok = read_bbreg(padapter, 0xf90, 0x0000FFFF);
+ htcrc = read_bbreg(padapter, 0xf90, 0xFFFF0000);
+
+ OFDM_FA = read_bbreg(padapter, 0xcf0, 0x0000FFFF);
+ OFDM_FA = read_bbreg(padapter, 0xcf2, 0xFFFF0000);
+ OFDM_FA = read_bbreg(padapter, 0xda0, 0xFFFF0000);
+ OFDM_FA = read_bbreg(padapter, 0xda4, 0x0000FFFF);
+ OFDM_FA = read_bbreg(padapter, 0xda4, 0xFFFF0000);
+ OFDM_FA = read_bbreg(padapter, 0xda8, 0x0000FFFF);
+ CCK_FA = (rtw_read8(padapter, 0xa5b) << 8) | (rtw_read8(padapter, 0xa5c));
+
+ sprintf(extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d", cckok + ofdmok + htok, cckcrc + ofdmcrc + htcrc, OFDM_FA + CCK_FA);
+ }
+ wrqu->length = strlen(extra) + 1;
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_trx_query(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 txok, txfail, rxok, rxfail;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ txok = padapter->mppriv.tx.sended;
+ txfail = 0;
+ rxok = padapter->mppriv.rx_pktcount;
+ rxfail = padapter->mppriv.rx_crcerrpktcount;
+
+ memset(extra, '\0', 128);
+
+ sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ", txok, txfail, rxok, rxfail);
+
+ wrqu->length = strlen(extra) + 1;
+
+ return 0;
+}
+
+static int rtw_mp_pwrtrk(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 enable;
+ u32 thermal;
+ s32 ret;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+ memset(extra, 0, wrqu->length);
+
+ enable = 1;
+ if (wrqu->length > 1) {/* not empty string */
+ if (strncmp(input, "stop", 4) == 0) {
+ enable = 0;
+ sprintf(extra, "mp tx power tracking stop");
+ } else if (sscanf(input, "ther =%d", &thermal)) {
+ ret = Hal_SetThermalMeter(padapter, (u8)thermal);
+ if (ret == _FAIL)
+ return -EPERM;
+ sprintf(extra, "mp tx power tracking start, target value =%d ok ", thermal);
+ } else {
+ kfree(input);
+ return -EINVAL;
+ }
+ }
+
+ kfree(input);
+ ret = Hal_SetPowerTracking(padapter, enable);
+ if (ret == _FAIL)
+ return -EPERM;
+
+ wrqu->length = strlen(extra);
+ return 0;
+}
+
+static int rtw_mp_psd(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+
+ strcpy(extra, input);
+
+ wrqu->length = mp_query_psd(padapter, extra);
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_thermal(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u8 val;
+ u16 bwrite = 1;
+ u16 addr = EEPROM_THERMAL_METER_88E;
+
+ u16 cnt = 1;
+ u16 max_available_size = 0;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (copy_from_user(extra, wrqu->pointer, wrqu->length))
+ return -EFAULT;
+
+ bwrite = strncmp(extra, "write", 6); /* strncmp true is 0 */
+
+ Hal_GetThermalMeter(padapter, &val);
+
+ if (bwrite == 0) {
+ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+ if (2 > max_available_size) {
+ DBG_88E("no available efuse!\n");
+ return -EFAULT;
+ }
+ if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) {
+ DBG_88E("rtw_efuse_map_write error\n");
+ return -EFAULT;
+ } else {
+ sprintf(extra, " efuse write ok :%d", val);
+ }
+ } else {
+ sprintf(extra, "%d", val);
+ }
+ wrqu->length = strlen(extra);
+
+ return 0;
+}
+
+static int rtw_mp_reset_stats(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ struct mp_priv *pmp_priv;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ pmp_priv = &padapter->mppriv;
+
+ pmp_priv->tx.sended = 0;
+ pmp_priv->tx_pktcount = 0;
+ pmp_priv->rx_pktcount = 0;
+ pmp_priv->rx_crcerrpktcount = 0;
+
+ /* reset phy counter */
+ write_bbreg(padapter, 0xf14, BIT(16), 0x1);
+ msleep(10);
+ write_bbreg(padapter, 0xf14, BIT(16), 0x0);
+
+ return 0;
+}
+
+static int rtw_mp_dump(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ u32 value;
+ u8 rf_type, path_nums = 0;
+ u32 i, j = 1, path;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (strncmp(extra, "all", 4) == 0) {
+ DBG_88E("\n ======= MAC REG =======\n");
+ for (i = 0x0; i < 0x300; i += 4) {
+ if (j % 4 == 1)
+ DBG_88E("0x%02x", i);
+ DBG_88E(" 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ DBG_88E("\n");
+ }
+ for (i = 0x400; i < 0x1000; i += 4) {
+ if (j % 4 == 1)
+ DBG_88E("0x%02x", i);
+ DBG_88E(" 0x%08x ", rtw_read32(padapter, i));
+ if ((j++) % 4 == 0)
+ DBG_88E("\n");
+ }
+
+ j = 1;
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+ DBG_88E("\n ======= RF REG =======\n");
+ if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
+ path_nums = 1;
+ else
+ path_nums = 2;
+
+ for (path = 0; path < path_nums; path++) {
+ for (i = 0; i < 0x34; i++) {
+ value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
+ if (j % 4 == 1)
+ DBG_88E("0x%02x ", i);
+ DBG_88E(" 0x%08x ", value);
+ if ((j++) % 4 == 0)
+ DBG_88E("\n");
+ }
+ }
+ }
+ return 0;
+}
+
+static int rtw_mp_phypara(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *wrqu, char *extra)
+{
+ char *input = kmalloc(wrqu->length, GFP_KERNEL);
+ u32 valxcap;
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
+ kfree(input);
+ return -EFAULT;
+ }
+
+ DBG_88E("%s:iwpriv in =%s\n", __func__, input);
+
+ sscanf(input, "xcap =%d", &valxcap);
+
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_SetRFPath(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ char *input = kmalloc(wrqu->data.length, GFP_KERNEL);
+ u8 bMain = 1, bTurnoff = 1;
+
+ if (!input)
+ return -ENOMEM;
+ if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
+ return -EFAULT;
+ DBG_88E("%s:iwpriv in =%s\n", __func__, input);
+
+ bMain = strncmp(input, "1", 2); /* strncmp true is 0 */
+ bTurnoff = strncmp(input, "0", 3); /* strncmp true is 0 */
+
+ if (bMain == 0) {
+ MP_PHY_SetRFPathSwitch(padapter, true);
+ DBG_88E("%s:PHY_SetRFPathSwitch = true\n", __func__);
+ } else if (bTurnoff == 0) {
+ MP_PHY_SetRFPathSwitch(padapter, false);
+ DBG_88E("%s:PHY_SetRFPathSwitch = false\n", __func__);
+ }
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_QueryDrv(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ char *input = kmalloc(wrqu->data.length, GFP_KERNEL);
+ u8 qAutoLoad = 1;
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+
+ if (!input)
+ return -ENOMEM;
+
+ if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length))
+ return -EFAULT;
+ DBG_88E("%s:iwpriv in =%s\n", __func__, input);
+
+ qAutoLoad = strncmp(input, "autoload", 8); /* strncmp true is 0 */
+
+ if (qAutoLoad == 0) {
+ DBG_88E("%s:qAutoLoad\n", __func__);
+
+ if (pEEPROM->bautoload_fail_flag)
+ sprintf(extra, "fail");
+ else
+ sprintf(extra, "ok");
+ }
+ wrqu->data.length = strlen(extra) + 1;
+ kfree(input);
+ return 0;
+}
+
+static int rtw_mp_set(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wdata, char *extra)
+{
+ struct iw_point *wrqu = (struct iw_point *)wdata;
+ u32 subcmd = wrqu->flags;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (!padapter)
+ return -ENETDOWN;
+
+ if (!extra) {
+ wrqu->length = 0;
+ return -EIO;
+ }
+
+ switch (subcmd) {
+ case MP_START:
+ DBG_88E("set case mp_start\n");
+ rtw_mp_start(dev, info, wrqu, extra);
+ break;
+ case MP_STOP:
+ DBG_88E("set case mp_stop\n");
+ rtw_mp_stop(dev, info, wrqu, extra);
+ break;
+ case MP_BANDWIDTH:
+ DBG_88E("set case mp_bandwidth\n");
+ rtw_mp_bandwidth(dev, info, wrqu, extra);
+ break;
+ case MP_RESET_STATS:
+ DBG_88E("set case MP_RESET_STATS\n");
+ rtw_mp_reset_stats(dev, info, wrqu, extra);
+ break;
+ case MP_SetRFPathSwh:
+ DBG_88E("set MP_SetRFPathSwitch\n");
+ rtw_mp_SetRFPath(dev, info, wdata, extra);
+ break;
+ case CTA_TEST:
+ DBG_88E("set CTA_TEST\n");
+ rtw_cta_test_start(dev, info, wdata, extra);
+ break;
+ }
+
+ return 0;
+}
+
+static int rtw_mp_get(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wdata, char *extra)
+{
+ struct iw_point *wrqu = (struct iw_point *)wdata;
+ u32 subcmd = wrqu->flags;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+
+ if (!padapter)
+ return -ENETDOWN;
+ if (!extra) {
+ wrqu->length = 0;
+ return -EIO;
+ }
+
+ switch (subcmd) {
+ case WRITE_REG:
+ rtw_mp_write_reg(dev, info, wrqu, extra);
+ break;
+ case WRITE_RF:
+ rtw_mp_write_rf(dev, info, wrqu, extra);
+ break;
+ case MP_PHYPARA:
+ DBG_88E("mp_get MP_PHYPARA\n");
+ rtw_mp_phypara(dev, info, wrqu, extra);
+ break;
+ case MP_CHANNEL:
+ DBG_88E("set case mp_channel\n");
+ rtw_mp_channel(dev, info, wrqu, extra);
+ break;
+ case READ_REG:
+ DBG_88E("mp_get READ_REG\n");
+ rtw_mp_read_reg(dev, info, wrqu, extra);
+ break;
+ case READ_RF:
+ DBG_88E("mp_get READ_RF\n");
+ rtw_mp_read_rf(dev, info, wrqu, extra);
+ break;
+ case MP_RATE:
+ DBG_88E("set case mp_rate\n");
+ rtw_mp_rate(dev, info, wrqu, extra);
+ break;
+ case MP_TXPOWER:
+ DBG_88E("set case MP_TXPOWER\n");
+ rtw_mp_txpower(dev, info, wrqu, extra);
+ break;
+ case MP_ANT_TX:
+ DBG_88E("set case MP_ANT_TX\n");
+ rtw_mp_ant_tx(dev, info, wrqu, extra);
+ break;
+ case MP_ANT_RX:
+ DBG_88E("set case MP_ANT_RX\n");
+ rtw_mp_ant_rx(dev, info, wrqu, extra);
+ break;
+ case MP_QUERY:
+ rtw_mp_trx_query(dev, info, wrqu, extra);
+ break;
+ case MP_CTX:
+ DBG_88E("set case MP_CTX\n");
+ rtw_mp_ctx(dev, info, wrqu, extra);
+ break;
+ case MP_ARX:
+ DBG_88E("set case MP_ARX\n");
+ rtw_mp_arx(dev, info, wrqu, extra);
+ break;
+ case EFUSE_GET:
+ DBG_88E("efuse get EFUSE_GET\n");
+ rtw_mp_efuse_get(dev, info, wdata, extra);
+ break;
+ case MP_DUMP:
+ DBG_88E("set case MP_DUMP\n");
+ rtw_mp_dump(dev, info, wrqu, extra);
+ break;
+ case MP_PSD:
+ DBG_88E("set case MP_PSD\n");
+ rtw_mp_psd(dev, info, wrqu, extra);
+ break;
+ case MP_THER:
+ DBG_88E("set case MP_THER\n");
+ rtw_mp_thermal(dev, info, wrqu, extra);
+ break;
+ case MP_QueryDrvStats:
+ DBG_88E("mp_get MP_QueryDrvStats\n");
+ rtw_mp_QueryDrv(dev, info, wdata, extra);
+ break;
+ case MP_PWRTRK:
+ DBG_88E("set case MP_PWRTRK\n");
+ rtw_mp_pwrtrk(dev, info, wrqu, extra);
+ break;
+ case EFUSE_SET:
+ DBG_88E("set case efuse set\n");
+ rtw_mp_efuse_set(dev, info, wdata, extra);
+ break;
+ }
+
+ msleep(10); /* delay 5ms for sending pkt before exit adb shell operation */
+ return 0;
+}
+
+static int rtw_tdls(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ return 0;
+}
+
+static int rtw_tdls_get(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ return 0;
+}
+
+static int rtw_test(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ u32 len;
+ u8 *pbuf, *pch;
+ char *ptmp;
+ u8 *delim = ",";
+
+ DBG_88E("+%s\n", __func__);
+ len = wrqu->data.length;
+
+ pbuf = kzalloc(len, GFP_KERNEL);
+ if (!pbuf) {
+ DBG_88E("%s: no memory!\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
+ kfree(pbuf);
+ DBG_88E("%s: copy from user fail!\n", __func__);
+ return -EFAULT;
+ }
+ DBG_88E("%s: string =\"%s\"\n", __func__, pbuf);
+
+ ptmp = (char *)pbuf;
+ pch = strsep(&ptmp, delim);
+ if (!pch || strlen(pch) == 0) {
+ kfree(pbuf);
+ DBG_88E("%s: parameter error(level 1)!\n", __func__);
+ return -EFAULT;
+ }
+ kfree(pbuf);
+ return 0;
+}
+
+static iw_handler rtw_handlers[] = {
+ IW_HANDLER(SIOCGIWNAME, rtw_wx_get_name),
+ IW_HANDLER(SIOCSIWNWID, dummy),
+ IW_HANDLER(SIOCGIWNWID, dummy),
+ IW_HANDLER(SIOCGIWFREQ, rtw_wx_get_freq),
+ IW_HANDLER(SIOCSIWMODE, rtw_wx_set_mode),
+ IW_HANDLER(SIOCGIWMODE, rtw_wx_get_mode),
+ IW_HANDLER(SIOCSIWSENS, dummy),
+ IW_HANDLER(SIOCGIWSENS, rtw_wx_get_sens),
+ IW_HANDLER(SIOCGIWRANGE, rtw_wx_get_range),
+ IW_HANDLER(SIOCSIWPRIV, rtw_wx_set_priv),
+ IW_HANDLER(SIOCSIWSPY, dummy),
+ IW_HANDLER(SIOCGIWSPY, dummy),
+ IW_HANDLER(SIOCSIWAP, rtw_wx_set_wap),
+ IW_HANDLER(SIOCGIWAP, rtw_wx_get_wap),
+ IW_HANDLER(SIOCSIWMLME, rtw_wx_set_mlme),
+ IW_HANDLER(SIOCGIWAPLIST, dummy),
+ IW_HANDLER(SIOCSIWSCAN, rtw_wx_set_scan),
+ IW_HANDLER(SIOCGIWSCAN, rtw_wx_get_scan),
+ IW_HANDLER(SIOCSIWESSID, rtw_wx_set_essid),
+ IW_HANDLER(SIOCGIWESSID, rtw_wx_get_essid),
+ IW_HANDLER(SIOCSIWNICKN, dummy),
+ IW_HANDLER(SIOCGIWNICKN, rtw_wx_get_nick),
+ IW_HANDLER(SIOCSIWRATE, rtw_wx_set_rate),
+ IW_HANDLER(SIOCGIWRATE, rtw_wx_get_rate),
+ IW_HANDLER(SIOCSIWRTS, rtw_wx_set_rts),
+ IW_HANDLER(SIOCGIWRTS, rtw_wx_get_rts),
+ IW_HANDLER(SIOCSIWFRAG, rtw_wx_set_frag),
+ IW_HANDLER(SIOCGIWFRAG, rtw_wx_get_frag),
+ IW_HANDLER(SIOCSIWTXPOW, dummy),
+ IW_HANDLER(SIOCGIWTXPOW, dummy),
+ IW_HANDLER(SIOCSIWRETRY, dummy),
+ IW_HANDLER(SIOCGIWRETRY, rtw_wx_get_retry),
+ IW_HANDLER(SIOCSIWENCODE, rtw_wx_set_enc),
+ IW_HANDLER(SIOCGIWENCODE, rtw_wx_get_enc),
+ IW_HANDLER(SIOCSIWPOWER, dummy),
+ IW_HANDLER(SIOCGIWPOWER, rtw_wx_get_power),
+ IW_HANDLER(SIOCSIWGENIE, rtw_wx_set_gen_ie),
+ IW_HANDLER(SIOCSIWAUTH, rtw_wx_set_auth),
+ IW_HANDLER(SIOCSIWENCODEEXT, rtw_wx_set_enc_ext),
+ IW_HANDLER(SIOCSIWPMKSA, rtw_wx_set_pmkid),
+};
+
+static const struct iw_priv_args rtw_private_args[] = {
+ {
+ SIOCIWFIRSTPRIV + 0x0,
+ IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x1,
+ IW_PRIV_TYPE_CHAR | 0x7FF,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x4,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x5,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x6,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x7,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x8,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x9,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
+ },
+
+ {
+ SIOCIWFIRSTPRIV + 0xA,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
+ },
+
+ {
+ SIOCIWFIRSTPRIV + 0xB,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0xC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0xD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x10,
+ IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x11,
+ IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "p2p_get"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x12,
+ IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ, "p2p_get2"
+ },
+ {SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, 0, "NULL"},
+ {
+ SIOCIWFIRSTPRIV + 0x14,
+ IW_PRIV_TYPE_CHAR | 64, 0, "tdls"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x15,
+ IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "tdls_get"
+ },
+ {
+ SIOCIWFIRSTPRIV + 0x16,
+ IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
+ },
+
+ {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
+
+ {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
+ {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
+ {SIOCIWFIRSTPRIV + 0x1D, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
+ },
+
+ {SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0, ""}, /* set */
+ {SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, ""},/* get */
+/* --- sub-ioctls definitions --- */
+
+ {MP_START, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start"}, /* set */
+ {MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara"},/* get */
+ {MP_STOP, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop"}, /* set */
+ {MP_CHANNEL, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel"},/* get */
+ {MP_BANDWIDTH, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"}, /* set */
+ {MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},/* get */
+ {MP_RESET_STATS, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"},
+ {MP_QUERY, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_query"}, /* get */
+ {READ_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg"},
+ {MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},
+ {READ_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf"},
+ {MP_PSD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
+ {MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump"},
+ {MP_TXPOWER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
+ {MP_ANT_TX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
+ {MP_ANT_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
+ {WRITE_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg"},
+ {WRITE_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf"},
+ {MP_CTX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
+ {MP_ARX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
+ {MP_THER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
+ {EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set"},
+ {EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
+ {MP_PWRTRK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"},
+ {MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery"},
+ {MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"}, /* mp_ioctl */
+ {MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_setrfpath"},
+ {CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
+};
+
+static iw_handler rtw_private_handler[] = {
+rtw_wx_write32, /* 0x00 */
+rtw_wx_read32, /* 0x01 */
+rtw_drvext_hdl, /* 0x02 */
+rtw_mp_ioctl_hdl, /* 0x03 */
+
+/* for MM DTV platform */
+ rtw_get_ap_info, /* 0x04 */
+
+ rtw_set_pid, /* 0x05 */
+ rtw_wps_start, /* 0x06 */
+
+ rtw_wx_get_sensitivity, /* 0x07 */
+ rtw_wx_set_mtk_wps_probe_ie, /* 0x08 */
+ rtw_wx_set_mtk_wps_ie, /* 0x09 */
+
+/* Set Channel depend on the country code */
+ rtw_wx_set_channel_plan, /* 0x0A */
+
+ rtw_dbg_port, /* 0x0B */
+ rtw_wx_write_rf, /* 0x0C */
+ rtw_wx_read_rf, /* 0x0D */
+
+ rtw_mp_set, /* 0x0E */
+ rtw_mp_get, /* 0x0F */
+ rtw_p2p_set, /* 0x10 */
+ rtw_p2p_get, /* 0x11 */
+ rtw_p2p_get2, /* 0x12 */
+
+ NULL, /* 0x13 */
+ rtw_tdls, /* 0x14 */
+ rtw_tdls_get, /* 0x15 */
+
+ rtw_pm_set, /* 0x16 */
+ rtw_wx_priv_null, /* 0x17 */
+ rtw_rereg_nd_name, /* 0x18 */
+ rtw_wx_priv_null, /* 0x19 */
+
+ rtw_mp_efuse_set, /* 0x1A */
+ rtw_mp_efuse_get, /* 0x1B */
+ NULL, /* 0x1C is reserved for hostapd */
+ rtw_test, /* 0x1D */
+};
+
+static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_statistics *piwstats = &padapter->iwstats;
+ int tmp_noise = 0;
+ int tmp;
+
+ if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+ piwstats->qual.qual = 0;
+ piwstats->qual.level = 0;
+ piwstats->qual.noise = 0;
+ } else {
+ tmp_noise = padapter->recvpriv.noise;
+
+ piwstats->qual.level = padapter->signal_strength;
+ tmp = 219 + 3 * padapter->signal_strength;
+ tmp = min(100, tmp);
+ tmp = max(0, tmp);
+ piwstats->qual.qual = tmp;
+ piwstats->qual.noise = tmp_noise;
+ }
+ piwstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+ return &padapter->iwstats;
+}
+
+struct iw_handler_def rtw_handlers_def = {
+ .standard = rtw_handlers,
+ .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
+ .private = rtw_private_handler,
+ .private_args = (struct iw_priv_args *)rtw_private_args,
+ .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
+ .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
+ .get_wireless_stats = rtw_get_wireless_stats,
+};
diff --git a/drivers/staging/r8188eu/os_dep/mlme_linux.c b/drivers/staging/r8188eu/os_dep/mlme_linux.c
new file mode 100644
index 000000000000..e3ee9dc7ab90
--- /dev/null
+++ b/drivers/staging/r8188eu/os_dep/mlme_linux.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. i*/
+
+#define _MLME_OSDEP_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/mlme_osdep.h"
+
+void rtw_join_timeout_handler (struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, mlmepriv.assoc_timer);
+
+ _rtw_join_timeout_handler(adapter);
+}
+
+void _rtw_scan_timeout_handler (struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, mlmepriv.scan_to_timer);
+
+ rtw_scan_timeout_handler(adapter);
+}
+
+static void _dynamic_check_timer_handlder(struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, mlmepriv.dynamic_chk_timer);
+
+ if (adapter->registrypriv.mp_mode == 1)
+ return;
+ rtw_dynamic_check_timer_handlder(adapter);
+ _set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000);
+}
+
+void rtw_init_mlme_timer(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ timer_setup(&pmlmepriv->assoc_timer, rtw_join_timeout_handler, 0);
+ timer_setup(&pmlmepriv->scan_to_timer, _rtw_scan_timeout_handler, 0);
+ timer_setup(&pmlmepriv->dynamic_chk_timer, _dynamic_check_timer_handlder, 0);
+}
+
+void rtw_os_indicate_connect(struct adapter *adapter)
+{
+
+ rtw_indicate_wx_assoc_event(adapter);
+ netif_carrier_on(adapter->pnetdev);
+ if (adapter->pid[2] != 0)
+ rtw_signal_process(adapter->pid[2], SIGALRM);
+
+}
+
+void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted)
+{
+ indicate_wx_scan_complete_event(padapter);
+}
+
+static struct rt_pmkid_list backup_pmkid[NUM_PMKID_CACHE];
+
+void rtw_reset_securitypriv(struct adapter *adapter)
+{
+ u8 backup_index = 0;
+ u8 backup_counter = 0x00;
+ u32 backup_time = 0;
+
+ if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
+ /* 802.1x */
+ /* We have to backup the PMK information for WiFi PMK Caching test item. */
+ /* Backup the btkip_countermeasure information. */
+ /* When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds. */
+ memset(&backup_pmkid[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ memcpy(&backup_pmkid[0], &adapter->securitypriv.PMKIDList[0], sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ backup_index = adapter->securitypriv.PMKIDIndex;
+ backup_counter = adapter->securitypriv.btkip_countermeasure;
+ backup_time = adapter->securitypriv.btkip_countermeasure_time;
+ memset((unsigned char *)&adapter->securitypriv, 0, sizeof(struct security_priv));
+
+ /* Restore the PMK information to securitypriv structure for the following connection. */
+ memcpy(&adapter->securitypriv.PMKIDList[0],
+ &backup_pmkid[0],
+ sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ adapter->securitypriv.PMKIDIndex = backup_index;
+ adapter->securitypriv.btkip_countermeasure = backup_counter;
+ adapter->securitypriv.btkip_countermeasure_time = backup_time;
+ adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+ adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
+ } else {
+ /* reset values in securitypriv */
+ struct security_priv *psec_priv = &adapter->securitypriv;
+
+ psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+ psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ psec_priv->dot11PrivacyKeyIndex = 0;
+ psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ psec_priv->dot118021XGrpKeyid = 1;
+ psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
+ psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
+ }
+}
+
+void rtw_os_indicate_disconnect(struct adapter *adapter)
+{
+
+ netif_carrier_off(adapter->pnetdev); /* Do it first for tx broadcast pkt after disconnection issue! */
+ rtw_indicate_wx_disassoc_event(adapter);
+ rtw_reset_securitypriv(adapter);
+}
+
+void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
+{
+ uint len;
+ u8 *buff, *p, i;
+ union iwreq_data wrqu;
+
+ buff = NULL;
+ if (authmode == _WPA_IE_ID_) {
+ buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL);
+ if (!buff)
+ return;
+ p = buff;
+ p += sprintf(p, "ASSOCINFO(ReqIEs =");
+ len = sec_ie[1] + 2;
+ len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
+ for (i = 0; i < len; i++)
+ p += sprintf(p, "%02x", sec_ie[i]);
+ p += sprintf(p, ")");
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = p - buff;
+ wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
+ wrqu.data.length : IW_CUSTOM_MAX;
+ wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
+ kfree(buff);
+ }
+}
+
+static void _survey_timer_hdl(struct timer_list *t)
+{
+ struct adapter *padapter = from_timer(padapter, t, mlmeextpriv.survey_timer);
+
+ survey_timer_hdl(padapter);
+}
+
+static void _link_timer_hdl(struct timer_list *t)
+{
+ struct adapter *padapter = from_timer(padapter, t, mlmeextpriv.link_timer);
+ link_timer_hdl(padapter);
+}
+
+static void _addba_timer_hdl(struct timer_list *t)
+{
+ struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
+ addba_timer_hdl(psta);
+}
+
+void init_addba_retry_timer(struct adapter *padapter, struct sta_info *psta)
+{
+ timer_setup(&psta->addba_retry_timer, _addba_timer_hdl, 0);
+}
+
+void init_mlme_ext_timer(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ timer_setup(&pmlmeext->survey_timer, _survey_timer_hdl, 0);
+ timer_setup(&pmlmeext->link_timer, _link_timer_hdl, 0);
+}
+
+#ifdef CONFIG_88EU_AP_MODE
+
+void rtw_indicate_sta_assoc_event(struct adapter *padapter, struct sta_info *psta)
+{
+ union iwreq_data wrqu;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (!psta)
+ return;
+
+ if (psta->aid > NUM_STA)
+ return;
+
+ if (pstapriv->sta_aid[psta->aid - 1] != psta)
+ return;
+
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
+
+ DBG_88E("+rtw_indicate_sta_assoc_event\n");
+
+ wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL);
+}
+
+void rtw_indicate_sta_disassoc_event(struct adapter *padapter, struct sta_info *psta)
+{
+ union iwreq_data wrqu;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (!psta)
+ return;
+
+ if (psta->aid > NUM_STA)
+ return;
+
+ if (pstapriv->sta_aid[psta->aid - 1] != psta)
+ return;
+
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
+
+ DBG_88E("+rtw_indicate_sta_disassoc_event\n");
+
+ wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL);
+}
+
+#endif
diff --git a/drivers/staging/r8188eu/os_dep/os_intfs.c b/drivers/staging/r8188eu/os_dep/os_intfs.c
new file mode 100644
index 000000000000..8d0158f4a45d
--- /dev/null
+++ b/drivers/staging/r8188eu/os_dep/os_intfs.c
@@ -0,0 +1,1199 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _OS_INTFS_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/xmit_osdep.h"
+#include "../include/recv_osdep.h"
+#include "../include/hal_intf.h"
+#include "../include/rtw_ioctl.h"
+
+#include "../include/usb_osintf.h"
+#include "../include/rtw_br_ext.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
+MODULE_AUTHOR("Realtek Semiconductor Corp.");
+MODULE_VERSION(DRIVERVERSION);
+
+#define CONFIG_BR_EXT_BRNAME "br0"
+#define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */
+
+/* module param defaults */
+static int rtw_chip_version = 0x00;
+static int rtw_rfintfs = HWPI;
+static int rtw_lbkmode;/* RTL8712_AIR_TRX; */
+static int rtw_network_mode = Ndis802_11IBSS;/* Ndis802_11Infrastructure; infra, ad-hoc, auto */
+static int rtw_channel = 1;/* ad-hoc support requirement */
+static int rtw_wireless_mode = WIRELESS_11BG_24N;
+static int rtw_vrtl_carrier_sense = AUTO_VCS;
+static int rtw_vcs_type = RTS_CTS;/* */
+static int rtw_rts_thresh = 2347;/* */
+static int rtw_frag_thresh = 2346;/* */
+static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */
+static int rtw_scan_mode = 1;/* active, passive */
+static int rtw_adhoc_tx_pwr = 1;
+static int rtw_soft_ap;
+static int rtw_power_mgnt = 1;
+static int rtw_ips_mode = IPS_NORMAL;
+
+static int rtw_smart_ps = 2;
+
+module_param(rtw_ips_mode, int, 0644);
+MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode");
+
+static int rtw_debug = 1;
+static int rtw_radio_enable = 1;
+static int rtw_long_retry_lmt = 7;
+static int rtw_short_retry_lmt = 7;
+static int rtw_busy_thresh = 40;
+static int rtw_ack_policy = NORMAL_ACK;
+
+static int rtw_mp_mode;
+
+static int rtw_software_encrypt;
+static int rtw_software_decrypt;
+
+static int rtw_acm_method;/* 0:By SW 1:By HW. */
+
+static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */
+static int rtw_uapsd_enable;
+static int rtw_uapsd_max_sp = NO_LIMIT;
+static int rtw_uapsd_acbk_en;
+static int rtw_uapsd_acbe_en;
+static int rtw_uapsd_acvi_en;
+static int rtw_uapsd_acvo_en;
+
+static int rtw_led_enable = 1;
+
+int rtw_ht_enable = 1;
+int rtw_cbw40_enable = 3; /* 0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */
+int rtw_ampdu_enable = 1;/* for enable tx_ampdu */
+static int rtw_rx_stbc = 1;/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
+static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */
+
+static int rtw_lowrate_two_xmit = 1;/* Use 2 path Tx to transmit MCS0~7 and legacy mode */
+
+static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */
+static int rtw_low_power;
+static int rtw_wifi_spec;
+static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX;
+static int rtw_AcceptAddbaReq = true;/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */
+
+static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */
+static int rtw_antdiv_type; /* 0:decide by efuse 1: for 88EE, 1Tx and 1RxCG are diversity.(2 Ant with SPDT), 2: for 88EE, 1Tx and 2Rx are diversity.(2 Ant, Tx and RxCG are both on aux port, RxCS is on main port), 3: for 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */
+
+static int rtw_enusbss;/* 0:disable, 1:enable */
+
+static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */
+
+static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */
+
+static int rtw_hw_wps_pbc = 1;
+
+int rtw_mc2u_disable;
+
+static int rtw_80211d;
+
+static char *ifname = "wlan%d";
+module_param(ifname, charp, 0644);
+MODULE_PARM_DESC(ifname, "The default name to allocate for first interface");
+
+static char *if2name = "wlan%d";
+module_param(if2name, charp, 0644);
+MODULE_PARM_DESC(if2name, "The default name to allocate for second interface");
+
+char *rtw_initmac; /* temp mac address if users want to use instead of the mac address in Efuse */
+
+module_param(rtw_initmac, charp, 0644);
+module_param(rtw_channel_plan, int, 0644);
+module_param(rtw_chip_version, int, 0644);
+module_param(rtw_rfintfs, int, 0644);
+module_param(rtw_lbkmode, int, 0644);
+module_param(rtw_network_mode, int, 0644);
+module_param(rtw_channel, int, 0644);
+module_param(rtw_mp_mode, int, 0644);
+module_param(rtw_wmm_enable, int, 0644);
+module_param(rtw_vrtl_carrier_sense, int, 0644);
+module_param(rtw_vcs_type, int, 0644);
+module_param(rtw_busy_thresh, int, 0644);
+module_param(rtw_led_enable, int, 0644);
+module_param(rtw_ht_enable, int, 0644);
+module_param(rtw_cbw40_enable, int, 0644);
+module_param(rtw_ampdu_enable, int, 0644);
+module_param(rtw_rx_stbc, int, 0644);
+module_param(rtw_ampdu_amsdu, int, 0644);
+module_param(rtw_lowrate_two_xmit, int, 0644);
+module_param(rtw_rf_config, int, 0644);
+module_param(rtw_power_mgnt, int, 0644);
+module_param(rtw_smart_ps, int, 0644);
+module_param(rtw_low_power, int, 0644);
+module_param(rtw_wifi_spec, int, 0644);
+module_param(rtw_antdiv_cfg, int, 0644);
+module_param(rtw_antdiv_type, int, 0644);
+module_param(rtw_enusbss, int, 0644);
+module_param(rtw_hwpdn_mode, int, 0644);
+module_param(rtw_hwpwrp_detect, int, 0644);
+module_param(rtw_hw_wps_pbc, int, 0644);
+
+static uint rtw_max_roaming_times = 2;
+module_param(rtw_max_roaming_times, uint, 0644);
+MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try");
+
+static int rtw_fw_iol = 1;/* 0:Disable, 1:enable, 2:by usb speed */
+module_param(rtw_fw_iol, int, 0644);
+MODULE_PARM_DESC(rtw_fw_iol, "FW IOL");
+
+module_param(rtw_mc2u_disable, int, 0644);
+
+module_param(rtw_80211d, int, 0644);
+MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism");
+
+static uint rtw_notch_filter = RTW_NOTCH_FILTER;
+module_param(rtw_notch_filter, uint, 0644);
+MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P");
+module_param_named(debug, rtw_debug, int, 0444);
+MODULE_PARM_DESC(debug, "Set debug level (1-9) (default 1)");
+
+/* dummy routines */
+void rtw_proc_remove_one(struct net_device *dev)
+{
+}
+
+void rtw_proc_init_one(struct net_device *dev)
+{
+}
+
+#if 0 /* TODO: Convert these to /sys */
+void rtw_proc_init_one(struct net_device *dev)
+{
+ struct proc_dir_entry *dir_dev = NULL;
+ struct proc_dir_entry *entry = NULL;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ u8 rf_type;
+
+ if (!rtw_proc) {
+ memcpy(rtw_proc_name, DRV_NAME, sizeof(DRV_NAME));
+
+ rtw_proc = create_proc_entry(rtw_proc_name, S_IFDIR, init_net.proc_net);
+ if (!rtw_proc) {
+ DBG_88E(KERN_ERR "Unable to create rtw_proc directory\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("ver_info", S_IFREG | S_IRUGO, rtw_proc, proc_get_drv_version, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ }
+
+ if (!padapter->dir_dev) {
+ padapter->dir_dev = create_proc_entry(dev->name,
+ S_IFDIR | S_IRUGO | S_IXUGO,
+ rtw_proc);
+ dir_dev = padapter->dir_dev;
+ if (!dir_dev) {
+ if (rtw_proc_cnt == 0) {
+ if (rtw_proc) {
+ remove_proc_entry(rtw_proc_name, init_net.proc_net);
+ rtw_proc = NULL;
+ }
+ }
+
+ pr_info("Unable to create dir_dev directory\n");
+ return;
+ }
+ } else {
+ return;
+ }
+
+ rtw_proc_cnt++;
+
+ entry = create_proc_read_entry("write_reg", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_write_reg, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_write_reg;
+
+ entry = create_proc_read_entry("read_reg", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_read_reg, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_read_reg;
+
+ entry = create_proc_read_entry("fwstate", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_fwstate, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("sec_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_sec_info, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("mlmext_state", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_mlmext_state, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("qos_option", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_qos_option, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("ht_option", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_ht_option, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rf_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_info, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("ap_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_ap_info, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("adapter_state", S_IFREG | S_IRUGO,
+ dir_dev, proc_getstruct adapter_state, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("trx_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_trx_info, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("mac_reg_dump1", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_mac_reg_dump1, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("mac_reg_dump2", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_mac_reg_dump2, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("mac_reg_dump3", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_mac_reg_dump3, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("bb_reg_dump1", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_bb_reg_dump1, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("bb_reg_dump2", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_bb_reg_dump2, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("bb_reg_dump3", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_bb_reg_dump3, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rf_reg_dump1", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_reg_dump1, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rf_reg_dump2", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_reg_dump2, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type)) {
+ entry = create_proc_read_entry("rf_reg_dump3", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_reg_dump3, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rf_reg_dump4", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rf_reg_dump4, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ }
+
+#ifdef CONFIG_88EU_AP_MODE
+
+ entry = create_proc_read_entry("all_sta_info", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_all_sta_info, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+#endif
+
+ entry = create_proc_read_entry("best_channel", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_best_channel, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+
+ entry = create_proc_read_entry("rx_signal", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rx_signal, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_rx_signal;
+ entry = create_proc_read_entry("ht_enable", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_ht_enable, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_ht_enable;
+
+ entry = create_proc_read_entry("cbw40_enable", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_cbw40_enable, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_cbw40_enable;
+
+ entry = create_proc_read_entry("ampdu_enable", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_ampdu_enable, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_ampdu_enable;
+
+ entry = create_proc_read_entry("rx_stbc", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rx_stbc, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_rx_stbc;
+
+ entry = create_proc_read_entry("path_rssi", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_two_path_rssi, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry = create_proc_read_entry("rssi_disp", S_IFREG | S_IRUGO,
+ dir_dev, proc_get_rssi_disp, dev);
+ if (!entry) {
+ pr_info("Unable to create_proc_read_entry!\n");
+ return;
+ }
+ entry->write_proc = proc_set_rssi_disp;
+}
+
+void rtw_proc_remove_one(struct net_device *dev)
+{
+ struct proc_dir_entry *dir_dev = NULL;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ u8 rf_type;
+
+ dir_dev = padapter->dir_dev;
+ padapter->dir_dev = NULL;
+
+ if (dir_dev) {
+ remove_proc_entry("write_reg", dir_dev);
+ remove_proc_entry("read_reg", dir_dev);
+ remove_proc_entry("fwstate", dir_dev);
+ remove_proc_entry("sec_info", dir_dev);
+ remove_proc_entry("mlmext_state", dir_dev);
+ remove_proc_entry("qos_option", dir_dev);
+ remove_proc_entry("ht_option", dir_dev);
+ remove_proc_entry("rf_info", dir_dev);
+ remove_proc_entry("ap_info", dir_dev);
+ remove_proc_entry("adapter_state", dir_dev);
+ remove_proc_entry("trx_info", dir_dev);
+ remove_proc_entry("mac_reg_dump1", dir_dev);
+ remove_proc_entry("mac_reg_dump2", dir_dev);
+ remove_proc_entry("mac_reg_dump3", dir_dev);
+ remove_proc_entry("bb_reg_dump1", dir_dev);
+ remove_proc_entry("bb_reg_dump2", dir_dev);
+ remove_proc_entry("bb_reg_dump3", dir_dev);
+ remove_proc_entry("rf_reg_dump1", dir_dev);
+ remove_proc_entry("rf_reg_dump2", dir_dev);
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type)) {
+ remove_proc_entry("rf_reg_dump3", dir_dev);
+ remove_proc_entry("rf_reg_dump4", dir_dev);
+ }
+#ifdef CONFIG_88EU_AP_MODE
+ remove_proc_entry("all_sta_info", dir_dev);
+#endif
+
+ remove_proc_entry("best_channel", dir_dev);
+ remove_proc_entry("rx_signal", dir_dev);
+ remove_proc_entry("cbw40_enable", dir_dev);
+ remove_proc_entry("ht_enable", dir_dev);
+ remove_proc_entry("ampdu_enable", dir_dev);
+ remove_proc_entry("rx_stbc", dir_dev);
+ remove_proc_entry("path_rssi", dir_dev);
+ remove_proc_entry("rssi_disp", dir_dev);
+ remove_proc_entry(dev->name, rtw_proc);
+ dir_dev = NULL;
+ } else {
+ return;
+ }
+ rtw_proc_cnt--;
+
+ if (rtw_proc_cnt == 0) {
+ if (rtw_proc) {
+ remove_proc_entry("ver_info", rtw_proc);
+
+ remove_proc_entry(rtw_proc_name, init_net.proc_net);
+ rtw_proc = NULL;
+ }
+ }
+}
+#endif
+
+static uint loadparam(struct adapter *padapter, struct net_device *pnetdev)
+{
+ struct registry_priv *registry_par = &padapter->registrypriv;
+
+ GlobalDebugLevel = rtw_debug;
+ registry_par->chip_version = (u8)rtw_chip_version;
+ registry_par->rfintfs = (u8)rtw_rfintfs;
+ registry_par->lbkmode = (u8)rtw_lbkmode;
+ registry_par->network_mode = (u8)rtw_network_mode;
+
+ memcpy(registry_par->ssid.Ssid, "ANY", 3);
+ registry_par->ssid.SsidLength = 3;
+
+ registry_par->channel = (u8)rtw_channel;
+ registry_par->wireless_mode = (u8)rtw_wireless_mode;
+ registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense;
+ registry_par->vcs_type = (u8)rtw_vcs_type;
+ registry_par->rts_thresh = (u16)rtw_rts_thresh;
+ registry_par->frag_thresh = (u16)rtw_frag_thresh;
+ registry_par->preamble = (u8)rtw_preamble;
+ registry_par->scan_mode = (u8)rtw_scan_mode;
+ registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr;
+ registry_par->soft_ap = (u8)rtw_soft_ap;
+ registry_par->smart_ps = (u8)rtw_smart_ps;
+ registry_par->power_mgnt = (u8)rtw_power_mgnt;
+ registry_par->ips_mode = (u8)rtw_ips_mode;
+ registry_par->radio_enable = (u8)rtw_radio_enable;
+ registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt;
+ registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt;
+ registry_par->busy_thresh = (u16)rtw_busy_thresh;
+ registry_par->ack_policy = (u8)rtw_ack_policy;
+ registry_par->mp_mode = (u8)rtw_mp_mode;
+ registry_par->software_encrypt = (u8)rtw_software_encrypt;
+ registry_par->software_decrypt = (u8)rtw_software_decrypt;
+ registry_par->acm_method = (u8)rtw_acm_method;
+
+ /* UAPSD */
+ registry_par->wmm_enable = (u8)rtw_wmm_enable;
+ registry_par->uapsd_enable = (u8)rtw_uapsd_enable;
+ registry_par->uapsd_max_sp = (u8)rtw_uapsd_max_sp;
+ registry_par->uapsd_acbk_en = (u8)rtw_uapsd_acbk_en;
+ registry_par->uapsd_acbe_en = (u8)rtw_uapsd_acbe_en;
+ registry_par->uapsd_acvi_en = (u8)rtw_uapsd_acvi_en;
+ registry_par->uapsd_acvo_en = (u8)rtw_uapsd_acvo_en;
+
+ registry_par->led_enable = (u8)rtw_led_enable;
+
+ registry_par->ht_enable = (u8)rtw_ht_enable;
+ registry_par->cbw40_enable = (u8)rtw_cbw40_enable;
+ registry_par->ampdu_enable = (u8)rtw_ampdu_enable;
+ registry_par->rx_stbc = (u8)rtw_rx_stbc;
+ registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu;
+ registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit;
+ registry_par->rf_config = (u8)rtw_rf_config;
+ registry_par->low_power = (u8)rtw_low_power;
+ registry_par->wifi_spec = (u8)rtw_wifi_spec;
+ registry_par->channel_plan = (u8)rtw_channel_plan;
+ registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq;
+ registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg;
+ registry_par->antdiv_type = (u8)rtw_antdiv_type;
+ registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;/* 0:disable, 1:enable, 2:by EFUSE config */
+ registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect;/* 0:disable, 1:enable */
+ registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc;
+
+ registry_par->max_roaming_times = (u8)rtw_max_roaming_times;
+
+ registry_par->fw_iol = rtw_fw_iol;
+
+ registry_par->enable80211d = (u8)rtw_80211d;
+ snprintf(registry_par->ifname, 16, "%s", ifname);
+ snprintf(registry_par->if2name, 16, "%s", if2name);
+ registry_par->notch_filter = (u8)rtw_notch_filter;
+
+ return _SUCCESS;
+}
+
+static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+ struct sockaddr *addr = p;
+
+ if (!padapter->bup)
+ memcpy(padapter->eeprompriv.mac_addr, addr->sa_data, ETH_ALEN);
+
+ return 0;
+}
+
+static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
+ padapter->stats.tx_packets = pxmitpriv->tx_pkts;/* pxmitpriv->tx_pkts++; */
+ padapter->stats.rx_packets = precvpriv->rx_pkts;/* precvpriv->rx_pkts++; */
+ padapter->stats.tx_dropped = pxmitpriv->tx_drop;
+ padapter->stats.rx_dropped = precvpriv->rx_drop;
+ padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
+ padapter->stats.rx_bytes = precvpriv->rx_bytes;
+ return &padapter->stats;
+}
+
+/*
+ * AC to queue mapping
+ *
+ * AC_VO -> queue 0
+ * AC_VI -> queue 1
+ * AC_BE -> queue 2
+ * AC_BK -> queue 3
+ */
+static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+
+/* Given a data frame determine the 802.1p/1d tag to use. */
+static unsigned int rtw_classify8021d(struct sk_buff *skb)
+{
+ unsigned int dscp;
+
+ /* skb->priority values from 256->263 are magic values to
+ * directly indicate a specific 802.1d priority. This is used
+ * to allow 802.1d priority to be passed directly in from VLAN
+ * tags, etc.
+ */
+ if (skb->priority >= 256 && skb->priority <= 263)
+ return skb->priority - 256;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ dscp = ip_hdr(skb)->tos & 0xfc;
+ break;
+ default:
+ return 0;
+ }
+
+ return dscp >> 5;
+}
+
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev)
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ skb->priority = rtw_classify8021d(skb);
+
+ if (pmlmepriv->acm_mask != 0)
+ skb->priority = qos_acm(pmlmepriv->acm_mask, skb->priority);
+
+ return rtw_1d_to_queue[skb->priority];
+}
+
+u16 rtw_recv_select_queue(struct sk_buff *skb)
+{
+ struct iphdr *piphdr;
+ unsigned int dscp;
+ __be16 eth_type;
+ u32 priority;
+ u8 *pdata = skb->data;
+
+ memcpy(&eth_type, pdata + (ETH_ALEN << 1), 2);
+
+ switch (eth_type) {
+ case htons(ETH_P_IP):
+ piphdr = (struct iphdr *)(pdata + ETH_HLEN);
+ dscp = piphdr->tos & 0xfc;
+ priority = dscp >> 5;
+ break;
+ default:
+ priority = 0;
+ }
+
+ return rtw_1d_to_queue[priority];
+}
+
+static const struct net_device_ops rtw_netdev_ops = {
+ .ndo_open = netdev_open,
+ .ndo_stop = netdev_close,
+ .ndo_start_xmit = rtw_xmit_entry,
+ .ndo_select_queue = rtw_select_queue,
+ .ndo_set_mac_address = rtw_net_set_mac_address,
+ .ndo_get_stats = rtw_net_get_stats,
+};
+
+int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname)
+{
+ int err;
+
+ err = dev_alloc_name(pnetdev, ifname);
+ if (err < 0)
+ return err;
+
+ netif_carrier_off(pnetdev);
+ return 0;
+}
+
+static const struct device_type wlan_type = {
+ .name = "wlan",
+};
+
+struct net_device *rtw_init_netdev(struct adapter *old_padapter)
+{
+ struct adapter *padapter;
+ struct net_device *pnetdev;
+
+ if (old_padapter)
+ pnetdev = rtw_alloc_etherdev_with_old_priv(sizeof(struct adapter), (void *)old_padapter);
+ else
+ pnetdev = rtw_alloc_etherdev(sizeof(struct adapter));
+
+ if (!pnetdev)
+ return NULL;
+
+ pnetdev->dev.type = &wlan_type;
+ padapter = rtw_netdev_priv(pnetdev);
+ padapter->pnetdev = pnetdev;
+ DBG_88E("register rtw_netdev_ops to netdev_ops\n");
+ pnetdev->netdev_ops = &rtw_netdev_ops;
+ pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */
+ pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def;
+
+ /* step 2. */
+ loadparam(padapter, pnetdev);
+
+ return pnetdev;
+}
+
+u32 rtw_start_drv_threads(struct adapter *padapter)
+{
+ u32 _status = _SUCCESS;
+
+ padapter->cmdThread = kthread_run(rtw_cmd_thread, padapter, "RTW_CMD_THREAD");
+ if (IS_ERR(padapter->cmdThread))
+ _status = _FAIL;
+ else
+ _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); /* wait for cmd_thread to run */
+
+ rtw_hal_start_thread(padapter);
+ return _status;
+}
+
+void rtw_stop_drv_threads(struct adapter *padapter)
+{
+ /* Below is to termindate rtw_cmd_thread & event_thread... */
+ up(&padapter->cmdpriv.cmd_queue_sema);
+ if (padapter->cmdThread)
+ _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema);
+
+ rtw_hal_stop_thread(padapter);
+}
+
+static u8 rtw_init_default_value(struct adapter *padapter)
+{
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ /* xmit_priv */
+ pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
+ pxmitpriv->vcs = pregistrypriv->vcs_type;
+ pxmitpriv->vcs_type = pregistrypriv->vcs_type;
+ pxmitpriv->frag_len = pregistrypriv->frag_thresh;
+
+ /* mlme_priv */
+ pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
+ pmlmepriv->scan_mode = SCAN_ACTIVE;
+
+ /* ht_priv */
+ pmlmepriv->htpriv.ampdu_enable = false;/* set to disabled */
+
+ /* security_priv */
+ psecuritypriv->binstallGrpkey = _FAIL;
+ psecuritypriv->sw_encrypt = pregistrypriv->software_encrypt;
+ psecuritypriv->sw_decrypt = pregistrypriv->software_decrypt;
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
+ psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ psecuritypriv->dot11PrivacyKeyIndex = 0;
+ psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ psecuritypriv->dot118021XGrpKeyid = 1;
+ psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+ psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled;
+
+ /* registry_priv */
+ rtw_init_registrypriv_dev_network(padapter);
+ rtw_update_registrypriv_dev_network(padapter);
+
+ /* hal_priv */
+ rtw_hal_def_value_init(padapter);
+
+ /* misc. */
+ padapter->bReadPortCancel = false;
+ padapter->bWritePortCancel = false;
+ padapter->bRxRSSIDisplay = 0;
+ padapter->bNotifyChannelChange = 0;
+#ifdef CONFIG_88EU_P2P
+ padapter->bShowGetP2PState = 1;
+#endif
+ return _SUCCESS;
+}
+
+u8 rtw_reset_drv_sw(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ /* hal_priv */
+ rtw_hal_def_value_init(padapter);
+ padapter->bReadPortCancel = false;
+ padapter->bWritePortCancel = false;
+ padapter->bRxRSSIDisplay = 0;
+ pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
+
+ padapter->xmitpriv.tx_pkts = 0;
+ padapter->recvpriv.rx_pkts = 0;
+
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING);
+
+ rtw_hal_sreset_reset_value(padapter);
+ pwrctrlpriv->pwr_state_check_cnts = 0;
+
+ /* mlmeextpriv */
+ padapter->mlmeextpriv.sitesurvey_res.state = SCAN_DISABLE;
+
+ rtw_set_signal_stat_timer(&padapter->recvpriv);
+
+ return _SUCCESS;
+}
+
+u8 rtw_init_drv_sw(struct adapter *padapter)
+{
+ u8 ret8 = _SUCCESS;
+
+ if ((rtw_init_cmd_priv(&padapter->cmdpriv)) == _FAIL) {
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ padapter->cmdpriv.padapter = padapter;
+
+ if ((rtw_init_evt_priv(&padapter->evtpriv)) == _FAIL) {
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ if (rtw_init_mlme_priv(padapter) == _FAIL) {
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+#ifdef CONFIG_88EU_P2P
+ rtw_init_wifidirect_timers(padapter);
+ init_wifidirect_info(padapter, P2P_ROLE_DISABLE);
+ reset_global_wifidirect_info(padapter);
+#endif /* CONFIG_88EU_P2P */
+
+ if (init_mlme_ext_priv(padapter) == _FAIL) {
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) {
+ DBG_88E("Can't _rtw_init_xmit_priv\n");
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ if (_rtw_init_recv_priv(&padapter->recvpriv, padapter) == _FAIL) {
+ DBG_88E("Can't _rtw_init_recv_priv\n");
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ if (_rtw_init_sta_priv(&padapter->stapriv) == _FAIL) {
+ DBG_88E("Can't _rtw_init_sta_priv\n");
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ padapter->stapriv.padapter = padapter;
+
+ rtw_init_bcmc_stainfo(padapter);
+
+ rtw_init_pwrctrl_priv(padapter);
+
+ if (init_mp_priv(padapter) == _FAIL)
+ DBG_88E("%s: initialize MP private data Fail!\n", __func__);
+
+ ret8 = rtw_init_default_value(padapter);
+
+ rtw_hal_dm_init(padapter);
+ rtw_hal_sw_led_init(padapter);
+
+ rtw_hal_sreset_init(padapter);
+
+ spin_lock_init(&padapter->br_ext_lock);
+
+exit:
+ return ret8;
+}
+
+void rtw_cancel_all_timer(struct adapter *padapter)
+{
+ _cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
+
+ _cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
+
+ _cancel_timer_ex(&padapter->mlmepriv.dynamic_chk_timer);
+
+ /* cancel sw led timer */
+ rtw_hal_sw_led_deinit(padapter);
+
+ _cancel_timer_ex(&padapter->pwrctrlpriv.pwr_state_check_timer);
+
+ _cancel_timer_ex(&padapter->recvpriv.signal_stat_timer);
+ /* cancel dm timer */
+ rtw_hal_dm_deinit(padapter);
+}
+
+u8 rtw_free_drv_sw(struct adapter *padapter)
+{
+ /* we can call rtw_p2p_enable here, but: */
+ /* 1. rtw_p2p_enable may have IO operation */
+ /* 2. rtw_p2p_enable is bundled with wext interface */
+ #ifdef CONFIG_88EU_P2P
+ {
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+ _cancel_timer_ex(&pwdinfo->find_phase_timer);
+ _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
+ _cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);
+ rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
+ }
+ }
+ #endif
+
+ free_mlme_ext_priv(&padapter->mlmeextpriv);
+
+ rtw_free_cmd_priv(&padapter->cmdpriv);
+
+ rtw_free_evt_priv(&padapter->evtpriv);
+
+ rtw_free_mlme_priv(&padapter->mlmepriv);
+ _rtw_free_xmit_priv(&padapter->xmitpriv);
+
+ _rtw_free_sta_priv(&padapter->stapriv); /* will free bcmc_stainfo here */
+
+ _rtw_free_recv_priv(&padapter->recvpriv);
+
+ rtw_free_pwrctrl_priv(padapter);
+
+ rtw_hal_free_data(padapter);
+
+ /* free the old_pnetdev */
+ if (padapter->rereg_nd_name_priv.old_pnetdev) {
+ free_netdev(padapter->rereg_nd_name_priv.old_pnetdev);
+ padapter->rereg_nd_name_priv.old_pnetdev = NULL;
+ }
+
+ /* clear pbuddystruct adapter to avoid access wrong pointer. */
+ if (padapter->pbuddy_adapter)
+ padapter->pbuddy_adapter->pbuddy_adapter = NULL;
+
+ return _SUCCESS;
+}
+
+void netdev_br_init(struct net_device *netdev)
+{
+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(netdev);
+
+ rcu_read_lock();
+
+ if (rcu_dereference(adapter->pnetdev->rx_handler_data)) {
+ struct net_device *br_netdev;
+ struct net *devnet = NULL;
+
+ devnet = dev_net(netdev);
+ br_netdev = dev_get_by_name(devnet, CONFIG_BR_EXT_BRNAME);
+ if (br_netdev) {
+ memcpy(adapter->br_mac, br_netdev->dev_addr, ETH_ALEN);
+ dev_put(br_netdev);
+ } else {
+ pr_info("%s()-%d: dev_get_by_name(%s) failed!",
+ __func__, __LINE__, CONFIG_BR_EXT_BRNAME);
+ }
+ }
+ adapter->ethBrExtInfo.addPPPoETag = 1;
+
+ rcu_read_unlock();
+}
+
+int _netdev_open(struct net_device *pnetdev)
+{
+ uint status;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ DBG_88E("+88eu_drv - drv_open, bup =%d\n", padapter->bup);
+
+ if (pwrctrlpriv->ps_flag) {
+ padapter->net_closed = false;
+ goto netdev_open_normal_process;
+ }
+
+ if (!padapter->bup) {
+ padapter->bDriverStopped = false;
+ padapter->bSurpriseRemoved = false;
+ padapter->bCardDisableWOHSM = false;
+
+ status = rtw_hal_init(padapter);
+ if (status == _FAIL)
+ goto netdev_open_error;
+
+ pr_info("MAC Address = %pM\n", pnetdev->dev_addr);
+
+ status = rtw_start_drv_threads(padapter);
+ if (status == _FAIL) {
+ pr_info("Initialize driver software resource Failed!\n");
+ goto netdev_open_error;
+ }
+
+ if (init_hw_mlme_ext(padapter) == _FAIL) {
+ pr_info("can't init mlme_ext_priv\n");
+ goto netdev_open_error;
+ }
+ if (padapter->intf_start)
+ padapter->intf_start(padapter);
+ rtw_proc_init_one(pnetdev);
+
+ rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+ padapter->bup = true;
+ }
+ padapter->net_closed = false;
+
+ _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);
+
+ padapter->pwrctrlpriv.bips_processing = false;
+ rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
+
+ if (!rtw_netif_queue_stopped(pnetdev))
+ rtw_netif_start_queue(pnetdev);
+ else
+ rtw_netif_wake_queue(pnetdev);
+
+ netdev_br_init(pnetdev);
+
+netdev_open_normal_process:
+ DBG_88E("-88eu_drv - drv_open, bup =%d\n", padapter->bup);
+ return 0;
+
+netdev_open_error:
+ padapter->bup = false;
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+ DBG_88E("-88eu_drv - drv_open fail, bup =%d\n", padapter->bup);
+ return -1;
+}
+
+int netdev_open(struct net_device *pnetdev)
+{
+ int ret;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+
+ _enter_critical_mutex(padapter->hw_init_mutex, NULL);
+ ret = _netdev_open(pnetdev);
+ _exit_critical_mutex(padapter->hw_init_mutex, NULL);
+ return ret;
+}
+
+static int ips_netdrv_open(struct adapter *padapter)
+{
+ int status = _SUCCESS;
+ padapter->net_closed = false;
+ DBG_88E("===> %s.........\n", __func__);
+
+ padapter->bDriverStopped = false;
+ padapter->bSurpriseRemoved = false;
+ padapter->bCardDisableWOHSM = false;
+
+ status = rtw_hal_init(padapter);
+ if (status == _FAIL)
+ goto netdev_open_error;
+
+ if (padapter->intf_start)
+ padapter->intf_start(padapter);
+
+ rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
+ _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 5000);
+
+ return _SUCCESS;
+
+netdev_open_error:
+ DBG_88E("-ips_netdrv_open - drv_open failure, bup =%d\n", padapter->bup);
+
+ return _FAIL;
+}
+
+int rtw_ips_pwr_up(struct adapter *padapter)
+{
+ int result;
+ u32 start_time = jiffies;
+ DBG_88E("===> rtw_ips_pwr_up..............\n");
+ rtw_reset_drv_sw(padapter);
+
+ result = ips_netdrv_open(padapter);
+
+ rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+ DBG_88E("<=== rtw_ips_pwr_up.............. in %dms\n", rtw_get_passing_time_ms(start_time));
+ return result;
+}
+
+void rtw_ips_pwr_down(struct adapter *padapter)
+{
+ u32 start_time = jiffies;
+ DBG_88E("===> rtw_ips_pwr_down...................\n");
+
+ padapter->bCardDisableWOHSM = true;
+ padapter->net_closed = true;
+
+ rtw_led_control(padapter, LED_CTL_POWER_OFF);
+
+ rtw_ips_dev_unload(padapter);
+ padapter->bCardDisableWOHSM = false;
+ DBG_88E("<=== rtw_ips_pwr_down..................... in %dms\n", rtw_get_passing_time_ms(start_time));
+}
+
+void rtw_ips_dev_unload(struct adapter *padapter)
+{
+ DBG_88E("====> %s...\n", __func__);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_FIFO_CLEARN_UP, NULL);
+
+ if (padapter->intf_stop)
+ padapter->intf_stop(padapter);
+
+ /* s5. */
+ if (!padapter->bSurpriseRemoved)
+ rtw_hal_deinit(padapter);
+}
+
+int pm_netdev_open(struct net_device *pnetdev, u8 bnormal)
+{
+ int status;
+
+ if (bnormal)
+ status = netdev_open(pnetdev);
+ else
+ status = (_SUCCESS == ips_netdrv_open((struct adapter *)rtw_netdev_priv(pnetdev))) ? (0) : (-1);
+ return status;
+}
+
+int netdev_close(struct net_device *pnetdev)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+
+ if (padapter->pwrctrlpriv.bInternalAutoSuspend) {
+ if (padapter->pwrctrlpriv.rf_pwrstate == rf_off)
+ padapter->pwrctrlpriv.ps_flag = true;
+ }
+ padapter->net_closed = true;
+
+ if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) {
+ DBG_88E("(2)88eu_drv - drv_close, bup =%d, hw_init_completed =%d\n",
+ padapter->bup, padapter->hw_init_completed);
+
+ /* s1. */
+ if (pnetdev) {
+ if (!rtw_netif_queue_stopped(pnetdev))
+ rtw_netif_stop_queue(pnetdev);
+ }
+
+ /* s2. */
+ LeaveAllPowerSaveMode(padapter);
+ rtw_disassoc_cmd(padapter, 500, false);
+ /* s2-2. indicate disconnect to os */
+ rtw_indicate_disconnect(padapter);
+ /* s2-3. */
+ rtw_free_assoc_resources(padapter, 1);
+ /* s2-4. */
+ rtw_free_network_queue(padapter, true);
+ /* Close LED */
+ rtw_led_control(padapter, LED_CTL_POWER_OFF);
+ }
+
+ nat25_db_cleanup(padapter);
+
+#ifdef CONFIG_88EU_P2P
+ rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
+#endif /* CONFIG_88EU_P2P */
+
+ kfree(dvobj->firmware.szFwBuffer);
+ dvobj->firmware.szFwBuffer = NULL;
+
+ DBG_88E("-88eu_drv - drv_close, bup =%d\n", padapter->bup);
+ return 0;
+}
diff --git a/drivers/staging/r8188eu/os_dep/osdep_service.c b/drivers/staging/r8188eu/os_dep/osdep_service.c
new file mode 100644
index 000000000000..95ac6086370b
--- /dev/null
+++ b/drivers/staging/r8188eu/os_dep/osdep_service.c
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#define _OSDEP_SERVICE_C_
+
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/rtw_ioctl_set.h"
+
+/*
+* Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
+* @return: one of RTW_STATUS_CODE
+*/
+inline int RTW_STATUS_CODE(int error_code)
+{
+ if (error_code >= 0)
+ return _SUCCESS;
+ return _FAIL;
+}
+
+u32 rtw_atoi(u8 *s)
+{
+ int num = 0, flag = 0;
+ int i;
+ for (i = 0; i <= strlen(s); i++) {
+ if (s[i] >= '0' && s[i] <= '9')
+ num = num * 10 + s[i] - '0';
+ else if (s[0] == '-' && i == 0)
+ flag = 1;
+ else
+ break;
+ }
+ if (flag == 1)
+ num = num * -1;
+ return num;
+}
+
+void *rtw_malloc2d(int h, int w, int size)
+{
+ int j;
+
+ void **a = kzalloc(h * sizeof(void *) + h * w * size, GFP_KERNEL);
+ if (!a)
+ return NULL;
+
+ for (j = 0; j < h; j++)
+ a[j] = ((char *)(a + h)) + j * w * size;
+
+ return a;
+}
+
+/*
+For the following list_xxx operations,
+caller must guarantee the atomic context.
+Otherwise, there will be racing condition.
+*/
+/*
+Caller must check if the list is empty before calling rtw_list_delete
+*/
+
+u32 _rtw_down_sema(struct semaphore *sema)
+{
+ if (down_interruptible(sema))
+ return _FAIL;
+ else
+ return _SUCCESS;
+}
+
+void _rtw_mutex_init(struct mutex *pmutex)
+{
+ mutex_init(pmutex);
+}
+
+void _rtw_mutex_free(struct mutex *pmutex)
+{
+ mutex_destroy(pmutex);
+}
+
+void _rtw_init_queue(struct __queue *pqueue)
+{
+ INIT_LIST_HEAD(&pqueue->queue);
+ spin_lock_init(&pqueue->lock);
+}
+
+inline u32 rtw_systime_to_ms(u32 systime)
+{
+ return systime * 1000 / HZ;
+}
+
+inline u32 rtw_ms_to_systime(u32 ms)
+{
+ return ms * HZ / 1000;
+}
+
+/* the input parameter start use the same unit as jiffies */
+inline s32 rtw_get_passing_time_ms(u32 start)
+{
+ return rtw_systime_to_ms(jiffies - start);
+}
+
+void rtw_usleep_os(int us)
+{
+ if (1 < (us / 1000))
+ msleep(1);
+ else
+ msleep((us / 1000) + 1);
+}
+
+#define RTW_SUSPEND_LOCK_NAME "rtw_wifi"
+
+static const struct device_type wlan_type = {
+ .name = "wlan",
+};
+
+struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv,
+ void *old_priv)
+{
+ struct net_device *pnetdev;
+ struct rtw_netdev_priv_indicator *pnpi;
+
+ pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
+ if (!pnetdev)
+ goto RETURN;
+
+ pnetdev->dev.type = &wlan_type;
+ pnpi = netdev_priv(pnetdev);
+ pnpi->priv = old_priv;
+ pnpi->sizeof_priv = sizeof_priv;
+
+RETURN:
+ return pnetdev;
+}
+
+struct net_device *rtw_alloc_etherdev(int sizeof_priv)
+{
+ struct net_device *pnetdev;
+ struct rtw_netdev_priv_indicator *pnpi;
+
+ pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
+ if (!pnetdev)
+ goto RETURN;
+
+ pnpi = netdev_priv(pnetdev);
+
+ pnpi->priv = vzalloc(sizeof_priv);
+ if (!pnpi->priv) {
+ free_netdev(pnetdev);
+ pnetdev = NULL;
+ goto RETURN;
+ }
+
+ pnpi->sizeof_priv = sizeof_priv;
+RETURN:
+ return pnetdev;
+}
+
+void rtw_free_netdev(struct net_device *netdev)
+{
+ struct rtw_netdev_priv_indicator *pnpi;
+
+ if (!netdev)
+ goto RETURN;
+
+ pnpi = netdev_priv(netdev);
+
+ if (!pnpi->priv)
+ goto RETURN;
+
+ vfree(pnpi->priv);
+ free_netdev(netdev);
+
+RETURN:
+ return;
+}
+
+int rtw_change_ifname(struct adapter *padapter, const char *ifname)
+{
+ struct net_device *pnetdev;
+ struct net_device *cur_pnetdev;
+ struct rereg_nd_name_data *rereg_priv;
+ int ret;
+
+ if (!padapter)
+ goto error;
+
+ cur_pnetdev = padapter->pnetdev;
+ rereg_priv = &padapter->rereg_nd_name_priv;
+
+ /* free the old_pnetdev */
+ if (rereg_priv->old_pnetdev) {
+ free_netdev(rereg_priv->old_pnetdev);
+ rereg_priv->old_pnetdev = NULL;
+ }
+
+ if (!rtnl_is_locked())
+ unregister_netdev(cur_pnetdev);
+ else
+ unregister_netdevice(cur_pnetdev);
+
+ rtw_proc_remove_one(cur_pnetdev);
+
+ rereg_priv->old_pnetdev = cur_pnetdev;
+
+ pnetdev = rtw_init_netdev(padapter);
+ if (!pnetdev) {
+ ret = -1;
+ goto error;
+ }
+
+ SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
+
+ rtw_init_netdev_name(pnetdev, ifname);
+
+ memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
+
+ if (!rtnl_is_locked())
+ ret = register_netdev(pnetdev);
+ else
+ ret = register_netdevice(pnetdev);
+ if (ret != 0)
+ goto error;
+
+ rtw_proc_init_one(pnetdev);
+ return 0;
+error:
+ return -1;
+}
+
+void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
+{
+ u32 dup_len = 0;
+ u8 *ori = NULL;
+ u8 *dup = NULL;
+
+ if (!buf || !buf_len)
+ return;
+
+ if (!src || !src_len)
+ goto keep_ori;
+
+ /* duplicate src */
+ dup = kmalloc(src_len, GFP_ATOMIC);
+ if (dup) {
+ dup_len = src_len;
+ memcpy(dup, src, dup_len);
+ }
+
+keep_ori:
+ ori = *buf;
+
+ /* replace buf with dup */
+ *buf_len = 0;
+ *buf = dup;
+ *buf_len = dup_len;
+
+ /* free ori */
+ kfree(ori);
+}
+
+/**
+ * rtw_cbuf_full - test if cbuf is full
+ * @cbuf: pointer of struct rtw_cbuf
+ *
+ * Returns: true if cbuf is full
+ */
+inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
+{
+ return (cbuf->write == cbuf->read - 1) ? true : false;
+}
+
+/**
+ * rtw_cbuf_empty - test if cbuf is empty
+ * @cbuf: pointer of struct rtw_cbuf
+ *
+ * Returns: true if cbuf is empty
+ */
+inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
+{
+ return (cbuf->write == cbuf->read) ? true : false;
+}
+
+/**
+ * rtw_cbuf_push - push a pointer into cbuf
+ * @cbuf: pointer of struct rtw_cbuf
+ * @buf: pointer to push in
+ *
+ * Lock free operation, be careful of the use scheme
+ * Returns: true push success
+ */
+bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
+{
+ if (rtw_cbuf_full(cbuf))
+ return _FAIL;
+
+ if (0)
+ DBG_88E("%s on %u\n", __func__, cbuf->write);
+ cbuf->bufs[cbuf->write] = buf;
+ cbuf->write = (cbuf->write + 1) % cbuf->size;
+
+ return _SUCCESS;
+}
+
+/**
+ * rtw_cbuf_pop - pop a pointer from cbuf
+ * @cbuf: pointer of struct rtw_cbuf
+ *
+ * Lock free operation, be careful of the use scheme
+ * Returns: pointer popped out
+ */
+void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
+{
+ void *buf;
+ if (rtw_cbuf_empty(cbuf))
+ return NULL;
+
+ if (0)
+ DBG_88E("%s on %u\n", __func__, cbuf->read);
+ buf = cbuf->bufs[cbuf->read];
+ cbuf->read = (cbuf->read + 1) % cbuf->size;
+
+ return buf;
+}
+
+/**
+ * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
+ * @size: size of pointer
+ *
+ * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
+ */
+struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
+{
+ struct rtw_cbuf *cbuf;
+
+ cbuf = kmalloc(sizeof(*cbuf) + sizeof(void *) * size, GFP_KERNEL);
+
+ if (cbuf) {
+ cbuf->write = 0;
+ cbuf->read = 0;
+ cbuf->size = size;
+ }
+ return cbuf;
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/r8188eu/os_dep/recv_linux.c
index 3460619ae08f..917a63e3e94c 100644
--- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c
+++ b/drivers/staging/r8188eu/os_dep/recv_linux.c
@@ -1,35 +1,75 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#include <osdep_service.h>
-#include <drv_types.h>
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
-#include <wifi.h>
-#include <recv_osdep.h>
+#define _RECV_OSDEP_C_
-#include <osdep_intf.h>
-#include <usb_ops_linux.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+
+#include "../include/wifi.h"
+#include "../include/recv_osdep.h"
+
+#include "../include/osdep_intf.h"
+#include "../include/usb_ops.h"
+
+/* init os related resource in struct recv_priv */
+int rtw_os_recv_resource_init(struct recv_priv *precvpriv,
+ struct adapter *padapter)
+{
+ return _SUCCESS;
+}
+
+/* alloc os related resource in struct recv_frame */
+int rtw_os_recv_resource_alloc(struct adapter *padapter,
+ struct recv_frame *precvframe)
+{
+ precvframe->pkt_newalloc = NULL;
+ precvframe->pkt = NULL;
+ return _SUCCESS;
+}
+
+/* free os related resource in struct recv_frame */
+void rtw_os_recv_resource_free(struct recv_priv *precvpriv)
+{
+}
/* alloc os related resource in struct recv_buf */
-int rtw_os_recvbuf_resource_alloc(struct recv_buf *precvbuf)
+int rtw_os_recvbuf_resource_alloc(struct adapter *padapter,
+ struct recv_buf *precvbuf)
{
- precvbuf->pskb = NULL;
- precvbuf->reuse = false;
+ int res = _SUCCESS;
+
+ precvbuf->irp_pending = false;
precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
if (!precvbuf->purb)
- return _FAIL;
+ res = _FAIL;
+ precvbuf->pskb = NULL;
+ precvbuf->reuse = false;
+ precvbuf->pallocated_buf = NULL;
+ precvbuf->pbuf = NULL;
+ precvbuf->pdata = NULL;
+ precvbuf->phead = NULL;
+ precvbuf->ptail = NULL;
+ precvbuf->pend = NULL;
+ precvbuf->transfer_len = 0;
+ precvbuf->len = 0;
+ return res;
+}
+
+/* free os related resource in struct recv_buf */
+int rtw_os_recvbuf_resource_free(struct adapter *padapter,
+ struct recv_buf *precvbuf)
+{
+ usb_free_urb(precvbuf->purb);
return _SUCCESS;
}
void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup)
{
union iwreq_data wrqu;
- struct iw_michaelmicfailure ev;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct iw_michaelmicfailure ev;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
u32 cur_time = 0;
if (psecuritypriv->last_mic_err_time == 0) {
@@ -60,6 +100,11 @@ void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup)
&wrqu, (char *)&ev);
}
+void rtw_hostapd_mlme_rx(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+}
+
int rtw_recv_indicatepkt(struct adapter *padapter,
struct recv_frame *precv_frame)
{
@@ -75,16 +120,22 @@ int rtw_recv_indicatepkt(struct adapter *padapter,
if (!skb)
goto _recv_indicatepkt_drop;
+ skb->data = precv_frame->rx_data;
+
+ skb_set_tail_pointer(skb, precv_frame->len);
+
+ skb->len = precv_frame->len;
+
if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
struct sk_buff *pskb2 = NULL;
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
- bool mcast = is_multicast_ether_addr(pattrib->dst);
+ bool bmcast = is_multicast_ether_addr(pattrib->dst);
if (memcmp(pattrib->dst, myid(&padapter->eeprompriv),
- ETH_ALEN)) {
- if (mcast) {
+ ETH_ALEN)) {
+ if (bmcast) {
psta = rtw_get_bcmc_stainfo(padapter);
pskb2 = skb_clone(skb, GFP_ATOMIC);
} else {
@@ -100,7 +151,7 @@ int rtw_recv_indicatepkt(struct adapter *padapter,
rtw_xmit_entry(skb, pnetdev);
- if (mcast)
+ if (bmcast)
skb = pskb2;
else
goto _recv_indicatepkt_end;
@@ -108,6 +159,10 @@ int rtw_recv_indicatepkt(struct adapter *padapter,
}
}
+ rcu_read_lock();
+ rcu_dereference(padapter->pnetdev->rx_handler_data);
+ rcu_read_unlock();
+
skb->ip_summed = CHECKSUM_NONE;
skb->dev = padapter->pnetdev;
skb->protocol = eth_type_trans(skb, padapter->pnetdev);
@@ -126,13 +181,34 @@ _recv_indicatepkt_end:
_recv_indicatepkt_drop:
/* enqueue back to free_recv_queue */
- rtw_free_recvframe(precv_frame, pfree_recv_queue);
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
+
+ return _FAIL;
+}
+
+void rtw_os_read_port(struct adapter *padapter, struct recv_buf *precvbuf)
+{
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
+ precvbuf->ref_cnt--;
+ /* free skb in recv_buf */
+ dev_kfree_skb_any(precvbuf->pskb);
+ precvbuf->pskb = NULL;
+ precvbuf->reuse = false;
+ if (!precvbuf->irp_pending)
+ rtw_read_port(padapter, precvpriv->ff_hwaddr, 0,
+ (unsigned char *)precvbuf);
+}
+
+static void _rtw_reordering_ctrl_timeout_handler(struct timer_list *t)
+{
+ struct recv_reorder_ctrl *preorder_ctrl;
- return _FAIL;
+ preorder_ctrl = from_timer(preorder_ctrl, t, reordering_ctrl_timer);
+ rtw_reordering_ctrl_timeout_handler(preorder_ctrl);
}
void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
{
- timer_setup(&preorder_ctrl->reordering_ctrl_timer,
- rtw_reordering_ctrl_timeout_handler, 0);
+ timer_setup(&preorder_ctrl->reordering_ctrl_timer, _rtw_reordering_ctrl_timeout_handler, 0);
}
diff --git a/drivers/staging/r8188eu/os_dep/usb_intf.c b/drivers/staging/r8188eu/os_dep/usb_intf.c
new file mode 100644
index 000000000000..bb85ab77fd26
--- /dev/null
+++ b/drivers/staging/r8188eu/os_dep/usb_intf.c
@@ -0,0 +1,781 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2011 Realtek Corporation. */
+
+#define _HCI_INTF_C_
+
+#include <linux/usb.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/recv_osdep.h"
+#include "../include/xmit_osdep.h"
+#include "../include/hal_intf.h"
+#include "../include/osdep_intf.h"
+#include "../include/usb_vendor_req.h"
+#include "../include/usb_ops.h"
+#include "../include/usb_osintf.h"
+#include "../include/rtw_ioctl.h"
+
+int ui_pid[3] = {0, 0, 0};
+
+static int rtw_suspend(struct usb_interface *intf, pm_message_t message);
+static int rtw_resume(struct usb_interface *intf);
+
+static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid);
+static void rtw_dev_remove(struct usb_interface *pusb_intf);
+
+#define USB_VENDER_ID_REALTEK 0x0bda
+
+/* DID_USB_v916_20130116 */
+static struct usb_device_id rtw_usb_id_tbl[] = {
+ /*=== Realtek demoboard ===*/
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179)}, /* 8188EUS */
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xf179)}, /* 8188FU */
+ /*=== Customer ID ===*/
+ /****** 8188EUS ********/
+ {USB_DEVICE(0x07B8, 0x8179)}, /* Abocom - Abocom */
+ {USB_DEVICE(0x0DF6, 0x0076)}, /* Sitecom N150 v2 */
+ {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
+ {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
+ {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+ {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
+ {USB_DEVICE(0x056E, 0x4008)}, /* Elecom WDC-150SU2M */
+ {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
+ {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */
+ {USB_DEVICE(0x2C4E, 0x0102)}, /* MERCUSYS MW150US v2 */
+ {USB_DEVICE(0x0B05, 0x18F0)}, /* ASUS USB-N10 Nano B1 */
+ {USB_DEVICE(0x7392, 0xb811)}, /* Edimax EW-7811Un V2 */
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
+
+static struct specific_device_id specific_device_id_tbl[] = {
+ {} /* empty table for now */
+};
+
+struct rtw_usb_drv {
+ struct usb_driver usbdrv;
+ int drv_registered;
+ struct mutex hw_init_mutex;
+};
+
+static struct rtw_usb_drv rtl8188e_usb_drv = {
+ .usbdrv.name = "r8188eu",
+ .usbdrv.probe = rtw_drv_init,
+ .usbdrv.disconnect = rtw_dev_remove,
+ .usbdrv.id_table = rtw_usb_id_tbl,
+ .usbdrv.suspend = rtw_suspend,
+ .usbdrv.resume = rtw_resume,
+ .usbdrv.reset_resume = rtw_resume,
+};
+
+static struct rtw_usb_drv *usb_drv = &rtl8188e_usb_drv;
+
+static inline int RT_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+ return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
+}
+
+static inline int RT_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+ return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+}
+
+static inline int RT_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+ return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT;
+}
+
+static inline int RT_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+{
+ return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK;
+}
+
+static inline int RT_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+{
+ return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_in(epd);
+}
+
+static inline int RT_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+{
+ return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_out(epd);
+}
+
+static inline int usb_endpoint_is_int(const struct usb_endpoint_descriptor *epd)
+{
+ return RT_usb_endpoint_xfer_int(epd) && RT_usb_endpoint_dir_in(epd);
+}
+
+static inline int RT_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
+{
+ return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+}
+
+static u8 rtw_init_intf_priv(struct dvobj_priv *dvobj)
+{
+ u8 rst = _SUCCESS;
+
+ _rtw_mutex_init(&dvobj->usb_vendor_req_mutex);
+
+ dvobj->usb_alloc_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE, GFP_KERNEL);
+ if (!dvobj->usb_alloc_vendor_req_buf) {
+ DBG_88E("alloc usb_vendor_req_buf failed... /n");
+ rst = _FAIL;
+ goto exit;
+ }
+ dvobj->usb_vendor_req_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(dvobj->usb_alloc_vendor_req_buf), ALIGNMENT_UNIT);
+exit:
+ return rst;
+}
+
+static void rtw_deinit_intf_priv(struct dvobj_priv *dvobj)
+{
+ kfree(dvobj->usb_alloc_vendor_req_buf);
+ _rtw_mutex_free(&dvobj->usb_vendor_req_mutex);
+}
+
+static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
+{
+ int i;
+ int status = _FAIL;
+ struct dvobj_priv *pdvobjpriv;
+ struct usb_host_config *phost_conf;
+ struct usb_config_descriptor *pconf_desc;
+ struct usb_host_interface *phost_iface;
+ struct usb_interface_descriptor *piface_desc;
+ struct usb_endpoint_descriptor *pendp_desc;
+ struct usb_device *pusbd;
+
+ pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
+ if (!pdvobjpriv)
+ goto exit;
+
+ pdvobjpriv->pusbintf = usb_intf;
+ pusbd = interface_to_usbdev(usb_intf);
+ pdvobjpriv->pusbdev = pusbd;
+ usb_set_intfdata(usb_intf, pdvobjpriv);
+
+ pdvobjpriv->RtNumInPipes = 0;
+ pdvobjpriv->RtNumOutPipes = 0;
+
+ phost_conf = pusbd->actconfig;
+ pconf_desc = &phost_conf->desc;
+
+ phost_iface = &usb_intf->altsetting[0];
+ piface_desc = &phost_iface->desc;
+
+ pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
+ pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
+ pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
+
+ for (i = 0; i < pdvobjpriv->nr_endpoint; i++) {
+ int ep_num;
+ pendp_desc = &phost_iface->endpoint[i].desc;
+
+ ep_num = usb_endpoint_num(pendp_desc);
+
+ if (usb_endpoint_is_bulk_in(pendp_desc)) {
+ pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num;
+ pdvobjpriv->RtNumInPipes++;
+ } else if (usb_endpoint_is_int_in(pendp_desc)) {
+ pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num;
+ pdvobjpriv->RtNumInPipes++;
+ } else if (usb_endpoint_is_bulk_out(pendp_desc)) {
+ pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] =
+ ep_num;
+ pdvobjpriv->RtNumOutPipes++;
+ }
+ pdvobjpriv->ep_num[i] = ep_num;
+ }
+
+ if (pusbd->speed == USB_SPEED_HIGH) {
+ pdvobjpriv->ishighspeed = true;
+ DBG_88E("USB_SPEED_HIGH\n");
+ } else {
+ pdvobjpriv->ishighspeed = false;
+ DBG_88E("NON USB_SPEED_HIGH\n");
+ }
+
+ if (rtw_init_intf_priv(pdvobjpriv) == _FAIL)
+ goto free_dvobj;
+
+ /* 3 misc */
+ sema_init(&pdvobjpriv->usb_suspend_sema, 0);
+ rtw_reset_continual_urb_error(pdvobjpriv);
+
+ usb_get_dev(pusbd);
+
+ status = _SUCCESS;
+
+free_dvobj:
+ if (status != _SUCCESS && pdvobjpriv) {
+ usb_set_intfdata(usb_intf, NULL);
+ kfree(pdvobjpriv);
+ pdvobjpriv = NULL;
+ }
+exit:
+ return pdvobjpriv;
+}
+
+static void usb_dvobj_deinit(struct usb_interface *usb_intf)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
+
+ usb_set_intfdata(usb_intf, NULL);
+ if (dvobj) {
+ /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
+ if ((dvobj->NumInterfaces != 2 &&
+ dvobj->NumInterfaces != 3) ||
+ (dvobj->InterfaceNumber == 1)) {
+ if (interface_to_usbdev(usb_intf)->state !=
+ USB_STATE_NOTATTACHED) {
+ /* If we didn't unplug usb dongle and
+ * remove/insert module, driver fails
+ * on sitesurvey for the first time when
+ * device is up . Reset usb port for sitesurvey
+ * fail issue. */
+ DBG_88E("usb attached..., try to reset usb device\n");
+ usb_reset_device(interface_to_usbdev(usb_intf));
+ }
+ }
+ rtw_deinit_intf_priv(dvobj);
+ kfree(dvobj);
+ }
+
+ usb_put_dev(interface_to_usbdev(usb_intf));
+
+}
+
+static void chip_by_usb_id(struct adapter *padapter)
+{
+ padapter->chip_type = NULL_CHIP_TYPE;
+ hal_set_hw_type(padapter);
+}
+
+static void usb_intf_start(struct adapter *padapter)
+{
+ rtw_hal_inirp_init(padapter);
+}
+
+static void usb_intf_stop(struct adapter *padapter)
+{
+ /* cancel in irp */
+ rtw_hal_inirp_deinit(padapter);
+
+ /* cancel out irp */
+ rtw_write_port_cancel(padapter);
+
+ /* todo:cancel other irps */
+}
+
+static void rtw_dev_unload(struct adapter *padapter)
+{
+ if (padapter->bup) {
+ DBG_88E("===> rtw_dev_unload\n");
+ padapter->bDriverStopped = true;
+ if (padapter->xmitpriv.ack_tx)
+ rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
+ /* s3. */
+ if (padapter->intf_stop)
+ padapter->intf_stop(padapter);
+ /* s4. */
+ if (!padapter->pwrctrlpriv.bInternalAutoSuspend)
+ rtw_stop_drv_threads(padapter);
+
+ /* s5. */
+ if (!padapter->bSurpriseRemoved) {
+ rtw_hal_deinit(padapter);
+ padapter->bSurpriseRemoved = true;
+ }
+
+ padapter->bup = false;
+ }
+
+ DBG_88E("<=== rtw_dev_unload\n");
+}
+
+static void process_spec_devid(const struct usb_device_id *pdid)
+{
+ u16 vid, pid;
+ u32 flags;
+ int i;
+ int num = sizeof(specific_device_id_tbl) /
+ sizeof(struct specific_device_id);
+
+ for (i = 0; i < num; i++) {
+ vid = specific_device_id_tbl[i].idVendor;
+ pid = specific_device_id_tbl[i].idProduct;
+ flags = specific_device_id_tbl[i].flags;
+
+ if ((pdid->idVendor == vid) && (pdid->idProduct == pid) &&
+ (flags & SPEC_DEV_ID_DISABLE_HT)) {
+ rtw_ht_enable = 0;
+ rtw_cbw40_enable = 0;
+ rtw_ampdu_enable = 0;
+ }
+ }
+}
+
+int rtw_hw_suspend(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct net_device *pnetdev = padapter->pnetdev;
+
+
+ if (!padapter)
+ goto error_exit;
+ if ((!padapter->bup) || (padapter->bDriverStopped) ||
+ (padapter->bSurpriseRemoved)) {
+ DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
+ padapter->bup, padapter->bDriverStopped,
+ padapter->bSurpriseRemoved);
+ goto error_exit;
+ }
+
+ LeaveAllPowerSaveMode(padapter);
+
+ DBG_88E("==> rtw_hw_suspend\n");
+ _enter_pwrlock(&pwrpriv->lock);
+ pwrpriv->bips_processing = true;
+ /* s1. */
+ if (pnetdev) {
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+ }
+
+ /* s2. */
+ rtw_disassoc_cmd(padapter, 500, false);
+
+ /* s2-2. indicate disconnect to os */
+ {
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
+
+ rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+ rtw_os_indicate_disconnect(padapter);
+
+ /* donnot enqueue cmd */
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0);
+ }
+ }
+ /* s2-3. */
+ rtw_free_assoc_resources(padapter, 1);
+
+ /* s2-4. */
+ rtw_free_network_queue(padapter, true);
+ rtw_ips_dev_unload(padapter);
+ pwrpriv->rf_pwrstate = rf_off;
+ pwrpriv->bips_processing = false;
+
+ _exit_pwrlock(&pwrpriv->lock);
+ return 0;
+
+error_exit:
+ DBG_88E("%s, failed\n", __func__);
+ return -1;
+}
+
+int rtw_hw_resume(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv;
+ struct net_device *pnetdev = padapter->pnetdev;
+
+ if (!padapter)
+ goto error_exit;
+ pwrpriv = &padapter->pwrctrlpriv;
+ DBG_88E("==> rtw_hw_resume\n");
+ _enter_pwrlock(&pwrpriv->lock);
+ pwrpriv->bips_processing = true;
+ rtw_reset_drv_sw(padapter);
+
+ if (pm_netdev_open(pnetdev, false) != 0) {
+ _exit_pwrlock(&pwrpriv->lock);
+ goto error_exit;
+ }
+
+ netif_device_attach(pnetdev);
+ netif_carrier_on(pnetdev);
+
+ if (!netif_queue_stopped(pnetdev))
+ netif_start_queue(pnetdev);
+ else
+ netif_wake_queue(pnetdev);
+
+ pwrpriv->bkeepfwalive = false;
+ pwrpriv->brfoffbyhw = false;
+
+ pwrpriv->rf_pwrstate = rf_on;
+ pwrpriv->bips_processing = false;
+
+ _exit_pwrlock(&pwrpriv->lock);
+
+ return 0;
+error_exit:
+ DBG_88E("%s, Open net dev failed\n", __func__);
+ return -1;
+}
+
+static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+ struct adapter *padapter = dvobj->if1;
+ struct net_device *pnetdev = padapter->pnetdev;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ int ret = 0;
+ u32 start_time = jiffies;
+
+
+ DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+
+ if ((!padapter->bup) || (padapter->bDriverStopped) ||
+ (padapter->bSurpriseRemoved)) {
+ DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
+ padapter->bup, padapter->bDriverStopped,
+ padapter->bSurpriseRemoved);
+ goto exit;
+ }
+
+ pwrpriv->bInSuspend = true;
+ rtw_cancel_all_timer(padapter);
+ LeaveAllPowerSaveMode(padapter);
+
+ _enter_pwrlock(&pwrpriv->lock);
+ /* s1. */
+ if (pnetdev) {
+ netif_carrier_off(pnetdev);
+ rtw_netif_stop_queue(pnetdev);
+ }
+
+ /* s2. */
+ rtw_disassoc_cmd(padapter, 0, false);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
+ check_fwstate(pmlmepriv, _FW_LINKED)) {
+ DBG_88E("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
+ __func__, __LINE__,
+ pmlmepriv->cur_network.network.Ssid.Ssid,
+ pmlmepriv->cur_network.network.MacAddress,
+ pmlmepriv->cur_network.network.Ssid.SsidLength,
+ pmlmepriv->assoc_ssid.SsidLength);
+
+ pmlmepriv->to_roaming = 1;
+ }
+ /* s2-2. indicate disconnect to os */
+ rtw_indicate_disconnect(padapter);
+ /* s2-3. */
+ rtw_free_assoc_resources(padapter, 1);
+ /* s2-4. */
+ rtw_free_network_queue(padapter, true);
+
+ rtw_dev_unload(padapter);
+ _exit_pwrlock(&pwrpriv->lock);
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ rtw_indicate_scan_done(padapter, 1);
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
+ rtw_indicate_disconnect(padapter);
+
+exit:
+ DBG_88E("<=== %s return %d.............. in %dms\n", __func__
+ , ret, rtw_get_passing_time_ms(start_time));
+
+ return ret;
+}
+
+static int rtw_resume(struct usb_interface *pusb_intf)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+ struct adapter *padapter = dvobj->if1;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ int ret = 0;
+
+ if (pwrpriv->bInternalAutoSuspend)
+ ret = rtw_resume_process(padapter);
+ else
+ ret = rtw_resume_process(padapter);
+ return ret;
+}
+
+int rtw_resume_process(struct adapter *padapter)
+{
+ struct net_device *pnetdev;
+ struct pwrctrl_priv *pwrpriv = NULL;
+ int ret = -1;
+ u32 start_time = jiffies;
+
+ DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+
+ if (padapter) {
+ pnetdev = padapter->pnetdev;
+ pwrpriv = &padapter->pwrctrlpriv;
+ } else {
+ goto exit;
+ }
+
+ _enter_pwrlock(&pwrpriv->lock);
+ rtw_reset_drv_sw(padapter);
+ if (pwrpriv)
+ pwrpriv->bkeepfwalive = false;
+
+ DBG_88E("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
+ if (pm_netdev_open(pnetdev, true) != 0)
+ goto exit;
+
+ netif_device_attach(pnetdev);
+ netif_carrier_on(pnetdev);
+
+ _exit_pwrlock(&pwrpriv->lock);
+
+ if (padapter->pid[1] != 0) {
+ DBG_88E("pid[1]:%d\n", padapter->pid[1]);
+ rtw_signal_process(padapter->pid[1], SIGUSR2);
+ }
+
+ rtw_roaming(padapter, NULL);
+
+ ret = 0;
+exit:
+ if (pwrpriv)
+ pwrpriv->bInSuspend = false;
+ DBG_88E("<=== %s return %d.............. in %dms\n", __func__,
+ ret, rtw_get_passing_time_ms(start_time));
+
+
+ return ret;
+}
+
+/*
+ * drv_init() - a device potentially for us
+ *
+ * notes: drv_init() is called when the bus driver has located
+ * a card for us to support.
+ * We accept the new device by returning 0.
+ */
+
+static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
+ struct usb_interface *pusb_intf)
+{
+ struct adapter *padapter = NULL;
+ struct net_device *pnetdev = NULL;
+ int status = _FAIL;
+
+ padapter = vzalloc(sizeof(*padapter));
+ if (!padapter)
+ goto exit;
+ padapter->dvobj = dvobj;
+ dvobj->if1 = padapter;
+
+ padapter->bDriverStopped = true;
+
+ padapter->hw_init_mutex = &usb_drv->hw_init_mutex;
+
+ /* step 1-1., decide the chip_type via vid/pid */
+ padapter->interface_type = RTW_USB;
+ chip_by_usb_id(padapter);
+
+ if (rtw_handle_dualmac(padapter, 1) != _SUCCESS)
+ goto free_adapter;
+
+ pnetdev = rtw_init_netdev(padapter);
+ if (!pnetdev)
+ goto handle_dualmac;
+ SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
+ padapter = rtw_netdev_priv(pnetdev);
+
+ /* step 2. hook HalFunc, allocate HalData */
+ rtl8188eu_set_hal_ops(padapter);
+
+ padapter->intf_start = &usb_intf_start;
+ padapter->intf_stop = &usb_intf_stop;
+
+ /* step init_io_priv */
+ rtw_init_io_priv(padapter, usb_set_intf_ops);
+
+ /* step read_chip_version */
+ rtw_hal_read_chip_version(padapter);
+
+ /* step usb endpoint mapping */
+ rtw_hal_chip_configure(padapter);
+
+ /* step read efuse/eeprom data and get mac_addr */
+ rtw_hal_read_chip_info(padapter);
+
+ /* step 5. */
+ if (rtw_init_drv_sw(padapter) == _FAIL)
+ goto free_hal_data;
+
+#ifdef CONFIG_PM
+ if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
+ dvobj->pusbdev->do_remote_wakeup = 1;
+ pusb_intf->needs_remote_wakeup = 1;
+ device_init_wakeup(&pusb_intf->dev, 1);
+ DBG_88E("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
+ device_may_wakeup(&pusb_intf->dev));
+ }
+#endif
+
+ /* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto
+ * suspend influence */
+ if (usb_autopm_get_interface(pusb_intf) < 0)
+ DBG_88E("can't get autopm:\n");
+
+ /* alloc dev name after read efuse. */
+ rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
+ rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
+#ifdef CONFIG_88EU_P2P
+ rtw_init_wifidirect_addrs(padapter, padapter->eeprompriv.mac_addr,
+ padapter->eeprompriv.mac_addr);
+#endif
+ memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
+ DBG_88E("MAC Address from pnetdev->dev_addr = %pM\n",
+ pnetdev->dev_addr);
+
+ /* step 6. Tell the network stack we exist */
+ if (register_netdev(pnetdev) != 0)
+ goto free_hal_data;
+
+ DBG_88E("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
+ , padapter->bDriverStopped
+ , padapter->bSurpriseRemoved
+ , padapter->bup
+ , padapter->hw_init_completed
+ );
+
+ status = _SUCCESS;
+
+free_hal_data:
+ if (status != _SUCCESS)
+ kfree(padapter->HalData);
+handle_dualmac:
+ if (status != _SUCCESS)
+ rtw_handle_dualmac(padapter, 0);
+free_adapter:
+ if (status != _SUCCESS) {
+ if (pnetdev)
+ rtw_free_netdev(pnetdev);
+ else if (padapter)
+ vfree(padapter);
+ padapter = NULL;
+ }
+exit:
+ return padapter;
+}
+
+static void rtw_usb_if1_deinit(struct adapter *if1)
+{
+ struct net_device *pnetdev = if1->pnetdev;
+ struct mlme_priv *pmlmepriv = &if1->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_disassoc_cmd(if1, 0, false);
+
+#ifdef CONFIG_88EU_AP_MODE
+ free_mlme_ap_info(if1);
+#endif
+
+ if (if1->DriverState != DRIVER_DISAPPEAR) {
+ if (pnetdev) {
+ /* will call netdev_close() */
+ unregister_netdev(pnetdev);
+ rtw_proc_remove_one(pnetdev);
+ }
+ }
+ rtw_cancel_all_timer(if1);
+
+ rtw_dev_unload(if1);
+ DBG_88E("+r871xu_dev_remove, hw_init_completed=%d\n",
+ if1->hw_init_completed);
+ rtw_handle_dualmac(if1, 0);
+ rtw_free_drv_sw(if1);
+ if (pnetdev)
+ rtw_free_netdev(pnetdev);
+}
+
+static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
+{
+ struct adapter *if1 = NULL;
+ struct dvobj_priv *dvobj;
+
+ /* step 0. */
+ process_spec_devid(pdid);
+
+ /* Initialize dvobj_priv */
+ dvobj = usb_dvobj_init(pusb_intf);
+ if (!dvobj)
+ goto err;
+
+ if1 = rtw_usb_if1_init(dvobj, pusb_intf);
+ if (!if1) {
+ DBG_88E("rtw_init_primarystruct adapter Failed!\n");
+ goto free_dvobj;
+ }
+
+ if (ui_pid[1] != 0) {
+ DBG_88E("ui_pid[1]:%d\n", ui_pid[1]);
+ rtw_signal_process(ui_pid[1], SIGUSR2);
+ }
+
+ return 0;
+
+free_dvobj:
+ usb_dvobj_deinit(pusb_intf);
+err:
+ return -ENODEV;
+}
+
+/*
+ * dev_remove() - our device is being removed
+*/
+/* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both */
+static void rtw_dev_remove(struct usb_interface *pusb_intf)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+ struct adapter *padapter = dvobj->if1;
+
+ DBG_88E("+rtw_dev_remove\n");
+
+ if (usb_drv->drv_registered)
+ padapter->bSurpriseRemoved = true;
+
+ rtw_pm_set_ips(padapter, IPS_NONE);
+ rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+
+ LeaveAllPowerSaveMode(padapter);
+
+ rtw_usb_if1_deinit(padapter);
+
+ usb_dvobj_deinit(pusb_intf);
+
+ DBG_88E("-r871xu_dev_remove, done\n");
+}
+
+static int __init rtw_drv_entry(void)
+{
+ DBG_88E(DRV_NAME " driver version=%s\n", DRIVERVERSION);
+
+ _rtw_mutex_init(&usb_drv->hw_init_mutex);
+
+ usb_drv->drv_registered = true;
+ return usb_register(&usb_drv->usbdrv);
+}
+
+static void __exit rtw_drv_halt(void)
+{
+ DBG_88E("+rtw_drv_halt\n");
+
+ usb_drv->drv_registered = false;
+ usb_deregister(&usb_drv->usbdrv);
+
+ _rtw_mutex_free(&usb_drv->hw_init_mutex);
+ DBG_88E("-rtw_drv_halt\n");
+}
+
+module_init(rtw_drv_entry);
+module_exit(rtw_drv_halt);
diff --git a/drivers/staging/r8188eu/os_dep/usb_ops_linux.c b/drivers/staging/r8188eu/os_dep/usb_ops_linux.c
new file mode 100644
index 000000000000..62dd4a131534
--- /dev/null
+++ b/drivers/staging/r8188eu/os_dep/usb_ops_linux.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
+#define _USB_OPS_LINUX_C_
+
+#include "../include/drv_types.h"
+#include "../include/usb_ops_linux.h"
+#include "../include/rtw_sreset.h"
+
+unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
+{
+ unsigned int pipe = 0, ep_num = 0;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+
+ if (addr == RECV_BULK_IN_ADDR) {
+ pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
+ } else if (addr == RECV_INT_IN_ADDR) {
+ pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
+ } else if (addr < HW_QUEUE_ENTRY) {
+ ep_num = pdvobj->Queue2Pipe[addr];
+ pipe = usb_sndbulkpipe(pusbd, ep_num);
+ }
+
+ return pipe;
+}
+
+struct zero_bulkout_context {
+ void *pbuf;
+ void *purb;
+ void *pirp;
+ void *padapter;
+};
+
+void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
+{
+}
+
+void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+{
+}
+
+void usb_read_port_cancel(struct intf_hdl *pintfhdl)
+{
+ int i;
+ struct recv_buf *precvbuf;
+ struct adapter *padapter = pintfhdl->padapter;
+ precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
+
+ DBG_88E("%s\n", __func__);
+
+ padapter->bReadPortCancel = true;
+
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ precvbuf->reuse = true;
+ if (precvbuf->purb)
+ usb_kill_urb(precvbuf->purb);
+ precvbuf++;
+ }
+}
+
+static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
+ struct adapter *padapter = pxmitbuf->padapter;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct hal_data_8188e *haldata;
+
+ switch (pxmitbuf->flags) {
+ case VO_QUEUE_INX:
+ pxmitpriv->voq_cnt--;
+ break;
+ case VI_QUEUE_INX:
+ pxmitpriv->viq_cnt--;
+ break;
+ case BE_QUEUE_INX:
+ pxmitpriv->beq_cnt--;
+ break;
+ case BK_QUEUE_INX:
+ pxmitpriv->bkq_cnt--;
+ break;
+ case HIGH_QUEUE_INX:
+#ifdef CONFIG_88EU_AP_MODE
+ rtw_chk_hi_queue_cmd(padapter);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
+ padapter->bWritePortCancel) {
+ DBG_88E("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n",
+ __func__, padapter->bDriverStopped,
+ padapter->bSurpriseRemoved, padapter->bReadPortCancel,
+ pxmitbuf->ext_tag);
+
+ goto check_completion;
+ }
+
+ if (purb->status) {
+ DBG_88E("###=> urb_write_port_complete status(%d)\n", purb->status);
+ if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
+ sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
+ } else if (purb->status == -EINPROGRESS) {
+ goto check_completion;
+ } else if (purb->status == -ENOENT) {
+ DBG_88E("%s: -ENOENT\n", __func__);
+ goto check_completion;
+ } else if (purb->status == -ECONNRESET) {
+ DBG_88E("%s: -ECONNRESET\n", __func__);
+ goto check_completion;
+ } else if (purb->status == -ESHUTDOWN) {
+ padapter->bDriverStopped = true;
+ goto check_completion;
+ } else {
+ padapter->bSurpriseRemoved = true;
+ DBG_88E("bSurpriseRemoved = true\n");
+
+ goto check_completion;
+ }
+ }
+
+ haldata = GET_HAL_DATA(padapter);
+ haldata->srestpriv.last_tx_complete_time = jiffies;
+
+check_completion:
+ rtw_sctx_done_err(&pxmitbuf->sctx,
+ purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
+ RTW_SCTX_DONE_SUCCESS);
+
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+
+ tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+
+}
+
+u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
+{
+ unsigned long irqL;
+ unsigned int pipe;
+ int status;
+ u32 ret = _FAIL;
+ struct urb *purb = NULL;
+ struct adapter *padapter = (struct adapter *)pintfhdl->padapter;
+ struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
+ struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+
+ if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
+ (padapter->pwrctrlpriv.pnp_bstop_trx)) {
+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
+ goto exit;
+ }
+
+ spin_lock_irqsave(&pxmitpriv->lock, irqL);
+
+ switch (addr) {
+ case VO_QUEUE_INX:
+ pxmitpriv->voq_cnt++;
+ pxmitbuf->flags = VO_QUEUE_INX;
+ break;
+ case VI_QUEUE_INX:
+ pxmitpriv->viq_cnt++;
+ pxmitbuf->flags = VI_QUEUE_INX;
+ break;
+ case BE_QUEUE_INX:
+ pxmitpriv->beq_cnt++;
+ pxmitbuf->flags = BE_QUEUE_INX;
+ break;
+ case BK_QUEUE_INX:
+ pxmitpriv->bkq_cnt++;
+ pxmitbuf->flags = BK_QUEUE_INX;
+ break;
+ case HIGH_QUEUE_INX:
+ pxmitbuf->flags = HIGH_QUEUE_INX;
+ break;
+ default:
+ pxmitbuf->flags = MGT_QUEUE_INX;
+ break;
+ }
+
+ spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
+
+ purb = pxmitbuf->pxmit_urb[0];
+
+ /* translate DMA FIFO addr to pipehandle */
+ pipe = ffaddr2pipehdl(pdvobj, addr);
+
+ usb_fill_bulk_urb(purb, pusbd, pipe,
+ pxmitframe->buf_addr, /* pxmitbuf->pbuf */
+ cnt,
+ usb_write_port_complete,
+ pxmitbuf);/* context is pxmitbuf */
+
+ status = usb_submit_urb(purb, GFP_ATOMIC);
+ if (!status) {
+ struct hal_data_8188e *haldata = GET_HAL_DATA(padapter);
+
+ haldata->srestpriv.last_tx_time = jiffies;
+ } else {
+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
+ DBG_88E("usb_write_port, status =%d\n", status);
+
+ switch (status) {
+ case -ENODEV:
+ padapter->bDriverStopped = true;
+ break;
+ default:
+ break;
+ }
+ goto exit;
+ }
+
+ ret = _SUCCESS;
+
+/* We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
+
+exit:
+ if (ret != _SUCCESS)
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+
+ return ret;
+}
+
+void usb_write_port_cancel(struct intf_hdl *pintfhdl)
+{
+ int i, j;
+ struct adapter *padapter = pintfhdl->padapter;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
+
+ DBG_88E("%s\n", __func__);
+
+ padapter->bWritePortCancel = true;
+
+ for (i = 0; i < NR_XMITBUFF; i++) {
+ for (j = 0; j < 8; j++) {
+ if (pxmitbuf->pxmit_urb[j])
+ usb_kill_urb(pxmitbuf->pxmit_urb[j]);
+ }
+ pxmitbuf++;
+ }
+
+ pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
+ for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
+ for (j = 0; j < 8; j++) {
+ if (pxmitbuf->pxmit_urb[j])
+ usb_kill_urb(pxmitbuf->pxmit_urb[j]);
+ }
+ pxmitbuf++;
+ }
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/r8188eu/os_dep/xmit_linux.c
index 1b5776ae8eba..565ac5be7db3 100644
--- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
+++ b/drivers/staging/r8188eu/os_dep/xmit_linux.c
@@ -1,20 +1,75 @@
// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
+/* Copyright(c) 2007 - 2012 Realtek Corporation. */
+
#define _XMIT_OSDEP_C_
-#include <osdep_service.h>
-#include <drv_types.h>
+#include "../include/osdep_service.h"
+#include "../include/drv_types.h"
+#include "../include/wifi.h"
+#include "../include/mlme_osdep.h"
+#include "../include/xmit_osdep.h"
+#include "../include/osdep_intf.h"
+#include "../include/usb_osintf.h"
+
+uint rtw_remainder_len(struct pkt_file *pfile)
+{
+ return pfile->buf_len - ((size_t)(pfile->cur_addr) -
+ (size_t)(pfile->buf_start));
+}
+
+void _rtw_open_pktfile(struct sk_buff *pktptr, struct pkt_file *pfile)
+{
+
+ if (!pktptr) {
+ pr_err("8188eu: pktptr is NULL\n");
+ return;
+ }
+ if (!pfile) {
+ pr_err("8188eu: pfile is NULL\n");
+ return;
+ }
+ pfile->pkt = pktptr;
+ pfile->cur_addr = pktptr->data;
+ pfile->buf_start = pktptr->data;
+ pfile->pkt_len = pktptr->len;
+ pfile->buf_len = pktptr->len;
+
+ pfile->cur_buffer = pfile->buf_start;
+
+}
+
+uint _rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
+{
+ uint len = 0;
+
+ len = rtw_remainder_len(pfile);
+ len = (rlen > len) ? len : rlen;
+
+ if (rmem)
+ skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len, rmem, len);
-#include <wifi.h>
-#include <mlme_osdep.h>
-#include <xmit_osdep.h>
-#include <osdep_intf.h>
+ pfile->cur_addr += len;
+ pfile->pkt_len -= len;
-int rtw_os_xmit_resource_alloc(struct xmit_buf *pxmitbuf, u32 alloc_sz)
+ return len;
+}
+
+int rtw_endofpktfile(struct pkt_file *pfile)
+{
+
+ if (pfile->pkt_len == 0) {
+
+ return true;
+ }
+
+ return false;
+}
+
+void rtw_set_tx_chksum_offload(struct sk_buff *pkt, struct pkt_attrib *pattrib)
+{
+}
+
+int rtw_os_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitbuf, u32 alloc_sz)
{
int i;
@@ -22,17 +77,21 @@ int rtw_os_xmit_resource_alloc(struct xmit_buf *pxmitbuf, u32 alloc_sz)
if (!pxmitbuf->pallocated_buf)
return _FAIL;
- pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ);
+ pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
+ pxmitbuf->dma_transfer_addr = 0;
for (i = 0; i < 8; i++) {
pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
- if (!pxmitbuf->pxmit_urb[i])
+ if (!pxmitbuf->pxmit_urb[i]) {
+ DBG_88E("pxmitbuf->pxmit_urb[i]==NULL");
return _FAIL;
+ }
}
return _SUCCESS;
}
-void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf)
+void rtw_os_xmit_resource_free(struct adapter *padapter,
+ struct xmit_buf *pxmitbuf, u32 free_sz)
{
int i;
@@ -46,7 +105,7 @@ void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf)
void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt)
{
- u16 queue;
+ u16 queue;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
queue = skb_get_queue_mapping(pkt);
@@ -86,11 +145,10 @@ void rtw_os_xmit_schedule(struct adapter *padapter)
spin_unlock_bh(&pxmitpriv->lock);
}
-static void rtw_check_xmit_resource(struct adapter *padapter,
- struct sk_buff *pkt)
+static void rtw_check_xmit_resource(struct adapter *padapter, struct sk_buff *pkt)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u16 queue;
+ u16 queue;
queue = skb_get_queue_mapping(pkt);
if (padapter->registrypriv.wifi_spec) {
@@ -107,20 +165,24 @@ static void rtw_check_xmit_resource(struct adapter *padapter,
static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
{
- struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct list_head *phead, *plist;
struct sk_buff *newskb;
struct sta_info *psta = NULL;
- s32 res;
+ s32 res;
spin_lock_bh(&pstapriv->asoc_list_lock);
phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
/* free sta asoc_queue */
- list_for_each(plist, phead) {
- psta = list_entry(plist, struct sta_info, asoc_list);
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
- /* avoid come from STA1 and send back STA1 */
+ plist = plist->next;
+
+ /* avoid come from STA1 and send back STA1 */
if (!memcmp(psta->hwaddr, &skb->data[6], 6))
continue;
@@ -130,20 +192,18 @@ static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
memcpy(newskb->data, psta->hwaddr, 6);
res = rtw_xmit(padapter, &newskb);
if (res < 0) {
+ DBG_88E("%s()-%d: rtw_xmit() return error!\n", __func__, __LINE__);
pxmitpriv->tx_drop++;
dev_kfree_skb_any(newskb);
} else {
pxmitpriv->tx_pkts++;
}
} else {
+ DBG_88E("%s-%d: skb_copy() failed!\n", __func__, __LINE__);
pxmitpriv->tx_drop++;
spin_unlock_bh(&pstapriv->asoc_list_lock);
-
- /* Caller shall tx this multicast frame
- * via normal way.
- */
- return false;
+ return false; /* Caller shall tx this multicast frame via normal way. */
}
}
@@ -152,11 +212,11 @@ static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
return true;
}
-int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
+int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
{
- struct adapter *padapter = netdev_priv(pnetdev);
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
s32 res = 0;
if (!rtw_if_up(padapter))
@@ -167,7 +227,7 @@ int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
if (!rtw_mc2u_disable && check_fwstate(pmlmepriv, WIFI_AP_STATE) &&
(IP_MCAST_MAC(pkt->data) || ICMPV6_MCAST_MAC(pkt->data)) &&
(padapter->registrypriv.wifi_spec == 0)) {
- if (pxmitpriv->free_xmitframe_cnt > NR_XMITFRAME / 4) {
+ if (pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME / 4)) {
res = rtw_mlcst2unicst(padapter, pkt);
if (res)
goto exit;
@@ -184,6 +244,8 @@ int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
drop_packet:
pxmitpriv->tx_drop++;
dev_kfree_skb_any(pkt);
+
exit:
- return NETDEV_TX_OK;
+
+ return 0;
}
diff --git a/drivers/staging/rtl8188eu/Makefile b/drivers/staging/rtl8188eu/Makefile
deleted file mode 100644
index 28b936e8be0a..000000000000
--- a/drivers/staging/rtl8188eu/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-r8188eu-y := \
- core/rtw_ap.o \
- core/rtw_cmd.o \
- core/rtw_efuse.o \
- core/rtw_ieee80211.o \
- core/rtw_ioctl_set.o \
- core/rtw_iol.o \
- core/rtw_led.o \
- core/rtw_mlme.o \
- core/rtw_mlme_ext.o \
- core/rtw_pwrctrl.o \
- core/rtw_recv.o \
- core/rtw_rf.o \
- core/rtw_security.o \
- core/rtw_sreset.o \
- core/rtw_sta_mgt.o \
- core/rtw_wlan_util.o \
- core/rtw_xmit.o \
- hal/fw.o \
- hal/mac_cfg.o \
- hal/bb_cfg.o \
- hal/rf_cfg.o \
- hal/pwrseqcmd.o \
- hal/pwrseq.o \
- hal/hal8188e_rate_adaptive.o \
- hal/hal_intf.o \
- hal/hal_com.o \
- hal/odm.o \
- hal/odm_hwconfig.o \
- hal/odm_rtl8188e.o \
- hal/rtl8188e_cmd.o \
- hal/rtl8188e_dm.o \
- hal/rtl8188e_hal_init.o \
- hal/phy.o \
- hal/rf.o \
- hal/rtl8188e_rxdesc.o \
- hal/rtl8188e_xmit.o \
- hal/rtl8188eu_led.o \
- hal/rtl8188eu_recv.o \
- hal/rtl8188eu_xmit.o \
- hal/usb_halinit.o \
- os_dep/ioctl_linux.o \
- os_dep/mlme_linux.o \
- os_dep/mon.o \
- os_dep/os_intfs.o \
- os_dep/osdep_service.o \
- os_dep/recv_linux.o \
- os_dep/rtw_android.o \
- os_dep/usb_intf.o \
- os_dep/usb_ops_linux.o \
- os_dep/xmit_linux.o
-
-obj-$(CONFIG_R8188EU) := r8188eu.o
-
-ccflags-y += -I$(srctree)/$(src)/include
diff --git a/drivers/staging/rtl8188eu/TODO b/drivers/staging/rtl8188eu/TODO
deleted file mode 100644
index 5faa0a9bba25..000000000000
--- a/drivers/staging/rtl8188eu/TODO
+++ /dev/null
@@ -1,14 +0,0 @@
-TODO:
-- find and remove remaining code valid only for 5 GHz. Most of the obvious
- ones have been removed, but things like channel > 14 still exist.
-- find and remove any code for other chips that is left over
-- convert any remaining unusual variable types
-- find codes that can use %pM and %Nph formatting
-- checkpatch.pl fixes - most of the remaining ones are lines too long. Many
- of them will require refactoring
-- merge Realtek's bugfixes and new features into the driver
-- switch to use LIB80211
-- switch to use MAC80211
-
-Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
-and Larry Finger <Larry.Finger@lwfinger.net>.
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
deleted file mode 100644
index eb89a52aa4e3..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_cmd.c
+++ /dev/null
@@ -1,1219 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <mlme_osdep.h>
-#include <rtw_mlme_ext.h>
-
-static struct cmd_hdl wlancmds[] = {
- {sizeof(struct wlan_bssid_ex), join_cmd_hdl},
- {sizeof(struct disconnect_parm), disconnect_hdl},
- {sizeof(struct wlan_bssid_ex), createbss_hdl},
- {sizeof(struct setopmode_parm), setopmode_hdl},
- {sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl},
- {sizeof(struct setauth_parm), setauth_hdl},
- {sizeof(struct setkey_parm), setkey_hdl},
- {sizeof(struct set_stakey_parm), set_stakey_hdl},
- {sizeof(struct set_assocsta_parm), NULL},
- {sizeof(struct addBaReq_parm), add_ba_hdl},
- {sizeof(struct set_ch_parm), set_ch_hdl},
- {sizeof(struct wlan_bssid_ex), tx_beacon_hdl},
- {0, mlme_evt_hdl},
- {0, rtw_drvextra_cmd_hdl},
- {sizeof(struct SetChannelPlan_param), set_chplan_hdl}
-};
-
-static struct _cmd_callback rtw_cmd_callback[] = {
- {_JoinBss_CMD_, &rtw_joinbss_cmd_callback},
- {_DisConnect_CMD_, &rtw_disassoc_cmd_callback},
- {_CreateBss_CMD_, &rtw_createbss_cmd_callback},
- {_SetOpMode_CMD_, NULL},
- {_SiteSurvey_CMD_, &rtw_survey_cmd_callback},
- {_SetAuth_CMD_, NULL},
- {_SetKey_CMD_, NULL},
- {_SetStaKey_CMD_, NULL},
- {_SetAssocSta_CMD_, &rtw_setassocsta_cmdrsp_callback},
- {_AddBAReq_CMD_, NULL},
- {_SetChannel_CMD_, NULL},
- {_TX_Beacon_CMD_, NULL},
- {_Set_MLME_EVT_CMD_, NULL},
- {_Set_Drv_Extra_CMD_, NULL},
- {_SetChannelPlan_CMD_, NULL},
-};
-
-/*
- * Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
- * No irqsave is necessary.
- */
-
-void rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
-{
- init_completion(&pcmdpriv->cmd_queue_comp);
-
- _rtw_init_queue(&pcmdpriv->cmd_queue);
-}
-
-/*
- * Calling Context:
- *
- * rtw_enqueue_cmd can only be called between kernel thread,
- * since only spin_lock is used.
- *
- * ISR/Call-Back functions can't call this sub-function.
- */
-
-static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
-{
- unsigned long irqL;
-
- spin_lock_irqsave(&queue->lock, irqL);
-
- list_add_tail(&obj->list, &queue->queue);
-
- spin_unlock_irqrestore(&queue->lock, irqL);
-
- return _SUCCESS;
-}
-
-struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue)
-{
- unsigned long irqL;
- struct cmd_obj *obj;
-
- spin_lock_irqsave(&queue->lock, irqL);
- obj = list_first_entry_or_null(&queue->queue, struct cmd_obj, list);
- if (obj)
- list_del_init(&obj->list);
- spin_unlock_irqrestore(&queue->lock, irqL);
-
- return obj;
-}
-
-static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
-{
- struct adapter *padapter = container_of(pcmdpriv, struct adapter, cmdpriv);
- u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
-
- /* To decide allow or not */
- if ((padapter->pwrctrlpriv.bHWPwrPindetect) &&
- (!padapter->registrypriv.usbss_enable)) {
- if (cmd_obj->cmdcode == _Set_Drv_Extra_CMD_) {
- struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
-
- if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
- bAllow = true;
- }
- }
-
- if (cmd_obj->cmdcode == _SetChannelPlan_CMD_)
- bAllow = true;
-
- if ((!padapter->hw_init_completed && !bAllow) ||
- !padapter->cmdThread) /* com_thread not running */
- return _FAIL;
- return _SUCCESS;
-}
-
-u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
-{
- int res = _FAIL;
- struct adapter *padapter = container_of(pcmdpriv, struct adapter, cmdpriv);
-
- if (!cmd_obj)
- goto exit;
-
- cmd_obj->padapter = padapter;
-
- res = rtw_cmd_filter(pcmdpriv, cmd_obj);
- if (res == _FAIL) {
- rtw_free_cmd_obj(cmd_obj);
- goto exit;
- }
-
- res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
-
- if (res == _SUCCESS)
- complete(&pcmdpriv->cmd_queue_comp);
-
-exit:
-
- return res;
-}
-
-void rtw_free_cmd_obj(struct cmd_obj *pcmd)
-{
- if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
- /* free parmbuf in cmd_obj */
- kfree(pcmd->parmbuf);
- }
-
- if (pcmd->rsp) {
- if (pcmd->rspsz != 0) {
- /* free rsp in cmd_obj */
- kfree(pcmd->rsp);
- }
- }
-
- /* free cmd_obj */
- kfree(pcmd);
-}
-
-int rtw_cmd_thread(void *context)
-{
- u8 ret;
- struct cmd_obj *pcmd;
- u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
- void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
- struct adapter *padapter = context;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- allow_signal(SIGTERM);
-
- do {
- if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
- break;
-
- pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
- if (!pcmd) {
- /* The queue is empty. Wait until someone enqueues a command. */
- if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp))
- break;
-
- continue;
- }
-
- if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
- pcmd->res = H2C_DROPPED;
- } else {
- if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
- cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
-
- if (cmd_hdl) {
- ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
- pcmd->res = ret;
- }
- } else {
- pcmd->res = H2C_PARAMETERS_ERROR;
- }
- }
-
- /* call callback function for post-processed */
- if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
- pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
- if (pcmd_callback) {
- /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
- pcmd_callback(pcmd->padapter, pcmd);
- }
- }
- rtw_free_cmd_obj(pcmd);
-
- if (signal_pending(current))
- flush_signals(current);
- } while (!kthread_should_stop());
-
- /* free all cmd_obj resources */
- while ((pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue)))
- rtw_free_cmd_obj(pcmd);
-
- padapter->cmdThread = NULL;
- return 0;
-}
-
-/*
- * rtw_sitesurvey_cmd(~)
- * ### NOTE:#### (!!!!)
- * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE
- * LOCKED pmlmepriv->lock
- */
-u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
- struct rtw_ieee80211_channel *ch, int ch_num)
-{
- u8 res = _FAIL;
- struct cmd_obj *ph2c;
- struct sitesurvey_parm *psurveyPara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
-
- ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return _FAIL;
-
- psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC);
- if (!psurveyPara) {
- kfree(ph2c);
- return _FAIL;
- }
-
- rtw_free_network_queue(padapter, false);
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_);
-
- psurveyPara->scan_mode = pmlmepriv->scan_mode;
-
- /* prepare ssid list */
- if (ssid) {
- int i;
-
- for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (ssid[i].ssid_length) {
- memcpy(&psurveyPara->ssid[i], &ssid[i],
- sizeof(struct ndis_802_11_ssid));
- psurveyPara->ssid_num++;
- }
- }
- }
-
- /* prepare channel list */
- if (ch) {
- int i;
-
- for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
- if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
- memcpy(&psurveyPara->ch[i], &ch[i],
- sizeof(struct rtw_ieee80211_channel));
- psurveyPara->ch_num++;
- }
- }
- }
-
- set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
- if (res == _SUCCESS) {
- mod_timer(&pmlmepriv->scan_to_timer,
- jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
-
- led_control_8188eu(padapter, LED_CTL_SITE_SURVEY);
-
- pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
- } else {
- _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
- }
-
- return res;
-}
-
-void rtw_readtssi_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-{
- kfree(pcmd->parmbuf);
- kfree(pcmd);
-}
-
-u8 rtw_createbss_cmd(struct adapter *padapter)
-{
- struct cmd_obj *pcmd;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
- u8 res = _SUCCESS;
-
- led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
-
- pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd) {
- res = _FAIL;
- goto exit;
- }
-
- INIT_LIST_HEAD(&pcmd->list);
- pcmd->cmdcode = _CreateBss_CMD_;
- pcmd->parmbuf = (unsigned char *)pdev_network;
- pcmd->cmdsz = get_wlan_bssid_ex_sz(pdev_network);
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- pdev_network->Length = pcmd->cmdsz;
- res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-exit:
-
- return res;
-}
-
-u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
-{
- u8 res = _SUCCESS;
- uint t_len = 0;
- struct wlan_bssid_ex *psecnetwork;
- struct cmd_obj *pcmd;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
-
- pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd) {
- res = _FAIL;
- goto exit;
- }
- /* for ies is fix buf size */
- t_len = sizeof(struct wlan_bssid_ex);
-
- /* for hidden ap to set fw_state here */
- if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
- switch (ndis_network_mode) {
- case Ndis802_11IBSS:
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- break;
- case Ndis802_11Infrastructure:
- set_fwstate(pmlmepriv, WIFI_STATION_STATE);
- break;
- case Ndis802_11APMode:
- case Ndis802_11AutoUnknown:
- case Ndis802_11InfrastructureMax:
- break;
- }
- }
-
- psecnetwork = &psecuritypriv->sec_bss;
- if (!psecnetwork) {
- kfree(pcmd);
-
- res = _FAIL;
-
- goto exit;
- }
-
- memset(psecnetwork, 0, t_len);
-
- memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
-
- psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->ie_length;
-
- if (psecnetwork->ie_length - 12 < 255)
- memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12],
- psecnetwork->ie_length - 12);
- else
- memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], 255);
-
- psecnetwork->ie_length = 0;
- /* Added by Albert 2009/02/18 */
- /* If the driver wants to use the bssid to create the connection. */
- /* If not, we have to copy the connecting AP's MAC address to it so that */
- /* the driver just has the bssid information for PMKIDList searching. */
-
- if (!pmlmepriv->assoc_by_bssid)
- memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
-
- psecnetwork->ie_length = rtw_restruct_sec_ie(padapter, &pnetwork->network.ies[0],
- &psecnetwork->ies[0],
- pnetwork->network.ie_length);
-
- pqospriv->qos_option = 0;
-
- if (pregistrypriv->wmm_enable) {
- u32 tmp_len;
-
- tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.ies[0],
- &psecnetwork->ies[0],
- pnetwork->network.ie_length,
- psecnetwork->ie_length);
-
- if (psecnetwork->ie_length != tmp_len) {
- psecnetwork->ie_length = tmp_len;
- pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
- } else {
- pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
- }
- }
-
- phtpriv->ht_option = false;
- if (pregistrypriv->ht_enable) {
- /*
- * Added by Albert 2010/06/23
- * For the WEP mode, we will use the bg mode to do
- * the connection to avoid some IOT issue.
- * Especially for Realtek 8192u SoftAP.
- */
- if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
- (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
- (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
- /* rtw_restructure_ht_ie */
- rtw_restructure_ht_ie(padapter, &pnetwork->network.ies[0],
- &psecnetwork->ies[0],
- pnetwork->network.ie_length, &psecnetwork->ie_length);
- }
- }
-
- pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.ies, pnetwork->network.ie_length);
-
- if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
- padapter->pwrctrlpriv.smart_ps = 0;
- else
- padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
-
- pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
-
- INIT_LIST_HEAD(&pcmd->list);
- pcmd->cmdcode = _JoinBss_CMD_;
- pcmd->parmbuf = (unsigned char *)psecnetwork;
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
-
- res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-
-exit:
-
- return res;
-}
-
-u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
-{
- struct cmd_obj *cmdobj = NULL;
- struct disconnect_parm *param = NULL;
- struct cmd_priv *cmdpriv = &padapter->cmdpriv;
- u8 res = _SUCCESS;
-
- /* prepare cmd parameter */
- param = kzalloc(sizeof(*param), GFP_ATOMIC);
- if (!param) {
- res = _FAIL;
- goto exit;
- }
- param->deauth_timeout_ms = deauth_timeout_ms;
-
- if (enqueue) {
- /* need enqueue, prepare cmd_obj and enqueue */
- cmdobj = kzalloc(sizeof(*cmdobj), GFP_ATOMIC);
- if (!cmdobj) {
- res = _FAIL;
- kfree(param);
- goto exit;
- }
- init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
- res = rtw_enqueue_cmd(cmdpriv, cmdobj);
- } else {
- /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
- if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
- res = _FAIL;
- kfree(param);
- }
-
-exit:
-
- return res;
-}
-
-u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra networktype)
-{
- struct cmd_obj *ph2c;
- struct setopmode_parm *psetop;
-
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
- psetop = kzalloc(sizeof(*psetop), GFP_KERNEL);
- if (!ph2c || !psetop) {
- kfree(ph2c);
- kfree(psetop);
- return false;
- }
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
- psetop->mode = (u8)networktype;
-
- return rtw_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
-{
- struct cmd_obj *ph2c;
- struct set_stakey_parm *psetstakey_para;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct set_stakey_rsp *psetstakey_rsp = NULL;
-
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct sta_info *sta = (struct sta_info *)psta;
-
- ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
- psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_KERNEL);
- psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_KERNEL);
-
- if (!ph2c || !psetstakey_para || !psetstakey_rsp) {
- kfree(ph2c);
- kfree(psetstakey_para);
- kfree(psetstakey_rsp);
- return _FAIL;
- }
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
- ph2c->rsp = (u8 *)psetstakey_rsp;
- ph2c->rspsz = sizeof(struct set_stakey_rsp);
-
- ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
- else
- GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
-
- if (unicast_key)
- memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
- else
- memcpy(&psetstakey_para->key,
- &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
-
- /* jeff: set this because at least sw key is ready */
- padapter->securitypriv.busetkipkey = true;
-
- return rtw_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
-{
- struct cmd_obj *ph2c;
- struct set_stakey_parm *psetstakey_para;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct set_stakey_rsp *psetstakey_rsp = NULL;
- struct sta_info *sta = (struct sta_info *)psta;
- u8 res = _SUCCESS;
-
- if (!enqueue) {
- clear_cam_entry(padapter, entry);
- } else {
- ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c) {
- res = _FAIL;
- goto exit;
- }
-
- psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
- if (!psetstakey_para) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
- psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
- if (!psetstakey_rsp) {
- kfree(ph2c);
- kfree(psetstakey_para);
- res = _FAIL;
- goto exit;
- }
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
- ph2c->rsp = (u8 *)psetstakey_rsp;
- ph2c->rspsz = sizeof(struct set_stakey_rsp);
-
- ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
-
- psetstakey_para->algorithm = _NO_PRIVACY_;
-
- psetstakey_para->id = entry;
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
- }
-exit:
-
- return res;
-}
-
-u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
-{
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct cmd_obj *ph2c;
- struct addBaReq_parm *paddbareq_parm;
- u8 res = _SUCCESS;
-
- ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c) {
- res = _FAIL;
- goto exit;
- }
-
- paddbareq_parm = kzalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
- if (!paddbareq_parm) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
- paddbareq_parm->tid = tid;
- memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, _AddBAReq_CMD_);
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
- return res;
-}
-
-u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
-{
- struct cmd_obj *ph2c;
- struct drvextra_cmd_parm *pdrvextra_cmd_parm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- u8 res = _SUCCESS;
-
- ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c) {
- res = _FAIL;
- goto exit;
- }
-
- pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
- if (!pdrvextra_cmd_parm) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
- pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
- pdrvextra_cmd_parm->type_size = 0;
- pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
- return res;
-}
-
-u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
-{
- struct cmd_obj *pcmdobj;
- struct SetChannelPlan_param *setChannelPlan_param;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- u8 res = _SUCCESS;
-
- /* check input parameter */
- if (!rtw_is_channel_plan_valid(chplan)) {
- res = _FAIL;
- goto exit;
- }
-
- /* prepare cmd parameter */
- setChannelPlan_param = kzalloc(sizeof(*setChannelPlan_param), GFP_KERNEL);
- if (!setChannelPlan_param) {
- res = _FAIL;
- goto exit;
- }
- setChannelPlan_param->channel_plan = chplan;
-
- if (enqueue) {
- /* need enqueue, prepare cmd_obj and enqueue */
- pcmdobj = kzalloc(sizeof(*pcmdobj), GFP_KERNEL);
- if (!pcmdobj) {
- kfree(setChannelPlan_param);
- res = _FAIL;
- goto exit;
- }
-
- init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, _SetChannelPlan_CMD_);
- res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
- } else {
- /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
- if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS)
- res = _FAIL;
-
- kfree(setChannelPlan_param);
- }
-
- if (res == _SUCCESS)
- padapter->mlmepriv.ChannelPlan = chplan;
-
-exit:
-
- return res;
-}
-
-static void traffic_status_watchdog(struct adapter *padapter)
-{
- u8 bEnterPS;
- u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
- u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- /* */
- /* Determine if our traffic is busy now */
- /* */
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
- pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
- bBusyTraffic = true;
-
- if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
- pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
- bRxBusyTraffic = true;
- else
- bTxBusyTraffic = true;
- }
-
- /* Higher Tx/Rx data. */
- if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
- pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
- bHigherBusyTraffic = true;
-
- if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
- pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
- bHigherBusyRxTraffic = true;
- else
- bHigherBusyTxTraffic = true;
- }
-
- /* check traffic for powersaving. */
- if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
- (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
- bEnterPS = false;
- else
- bEnterPS = true;
-
- /* LeisurePS only work in infra mode. */
- if (bEnterPS)
- LPS_Enter(padapter);
- else
- LPS_Leave(padapter);
- } else {
- LPS_Leave(padapter);
- }
-
- pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
- pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
- pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
- pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
- pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
- pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
- pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
- pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
- pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
-}
-
-static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
-{
- struct mlme_priv *pmlmepriv;
-
- padapter = (struct adapter *)pbuf;
- pmlmepriv = &padapter->mlmepriv;
-
-#ifdef CONFIG_88EU_AP_MODE
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
- expire_timeout_chk(padapter);
-#endif
-
- linked_status_chk(padapter);
- traffic_status_watchdog(padapter);
-
- rtw_hal_dm_watchdog(padapter);
-}
-
-static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 mstatus;
-
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
- return;
-
- switch (lps_ctrl_type) {
- case LPS_CTRL_SCAN:
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- /* connect */
- LPS_Leave(padapter);
- }
- break;
- case LPS_CTRL_JOINBSS:
- LPS_Leave(padapter);
- break;
- case LPS_CTRL_CONNECT:
- mstatus = 1;/* connect */
- /* Reset LPS Setting */
- padapter->pwrctrlpriv.LpsIdleCount = 0;
- rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
- break;
- case LPS_CTRL_DISCONNECT:
- mstatus = 0;/* disconnect */
- LPS_Leave(padapter);
- rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
- break;
- case LPS_CTRL_SPECIAL_PACKET:
- pwrpriv->DelayLPSLastTimeStamp = jiffies;
- LPS_Leave(padapter);
- break;
- case LPS_CTRL_LEAVE:
- LPS_Leave(padapter);
- break;
- default:
- break;
- }
-}
-
-u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
-{
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct drvextra_cmd_parm *pdrvextra_cmd_parm;
- struct cmd_obj *ph2c;
-
- if (!enqueue) {
- lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
- return _SUCCESS;
- }
-
- ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
- pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
- if (!ph2c || !pdrvextra_cmd_parm) {
- kfree(ph2c);
- kfree(pdrvextra_cmd_parm);
- return _FAIL;
- }
-
- pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
- pdrvextra_cmd_parm->type_size = lps_ctrl_type;
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
- return rtw_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
-{
- rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
-}
-
-u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
-{
- struct cmd_obj *ph2c;
- struct drvextra_cmd_parm *pdrvextra_cmd_parm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- u8 res = _SUCCESS;
-
- ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c) {
- res = _FAIL;
- goto exit;
- }
-
- pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
- if (!pdrvextra_cmd_parm) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
- pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
- pdrvextra_cmd_parm->type_size = min_time;
- pdrvextra_cmd_parm->pbuf = NULL;
- init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
-
- return res;
-}
-
-static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
-{
- rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
-}
-
-u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
-{
- struct cmd_obj *ph2c;
- struct drvextra_cmd_parm *pdrvextra_cmd_parm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- u8 support_ant_div;
- u8 res = _SUCCESS;
-
- rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
- if (!support_ant_div)
- return res;
-
- if (enqueue) {
- ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
- if (!ph2c) {
- res = _FAIL;
- goto exit;
- }
-
- pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_KERNEL);
- if (!pdrvextra_cmd_parm) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
- pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
- pdrvextra_cmd_parm->type_size = antenna;
- pdrvextra_cmd_parm->pbuf = NULL;
- init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
- } else {
- antenna_select_wk_hdl(padapter, antenna);
- }
-exit:
-
- return res;
-}
-
-u8 rtw_ps_cmd(struct adapter *padapter)
-{
- struct cmd_obj *ppscmd;
- struct drvextra_cmd_parm *pdrvextra_cmd_parm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ppscmd = kzalloc(sizeof(*ppscmd), GFP_ATOMIC);
- pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
- if (!ppscmd || !pdrvextra_cmd_parm) {
- kfree(ppscmd);
- kfree(pdrvextra_cmd_parm);
- return _FAIL;
- }
-
- pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
- pdrvextra_cmd_parm->pbuf = NULL;
- init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
-
- return rtw_enqueue_cmd(pcmdpriv, ppscmd);
-}
-
-#ifdef CONFIG_88EU_AP_MODE
-
-static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
-{
- int cnt = 0;
- struct sta_info *psta_bmc;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- psta_bmc = rtw_get_bcmc_stainfo(padapter);
- if (!psta_bmc)
- return;
-
- if (psta_bmc->sleepq_len == 0) {
- u8 val = 0;
-
- rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
-
- while (!val) {
- msleep(100);
-
- cnt++;
-
- if (cnt > 10)
- break;
-
- rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
- }
-
- if (cnt <= 10) {
- pstapriv->tim_bitmap &= ~BIT(0);
- pstapriv->sta_dz_bitmap &= ~BIT(0);
-
- update_beacon(padapter, WLAN_EID_TIM, NULL, false);
- } else { /* re check again */
- rtw_chk_hi_queue_cmd(padapter);
- }
- }
-}
-
-u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
-{
- struct cmd_obj *ph2c;
- struct drvextra_cmd_parm *pdrvextra_cmd_parm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- u8 res = _SUCCESS;
-
- ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c) {
- res = _FAIL;
- goto exit;
- }
-
- pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
- if (!pdrvextra_cmd_parm) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
- pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
- pdrvextra_cmd_parm->type_size = 0;
- pdrvextra_cmd_parm->pbuf = NULL;
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-exit:
- return res;
-}
-#endif
-
-u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
- struct drvextra_cmd_parm *pdrvextra_cmd;
-
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
-
- pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
-
- switch (pdrvextra_cmd->ec_id) {
- case DYNAMIC_CHK_WK_CID:
- dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
- break;
- case POWER_SAVING_CTRL_WK_CID:
- rtw_ps_processor(padapter);
- break;
- case LPS_CTRL_WK_CID:
- lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
- break;
- case RTP_TIMER_CFG_WK_CID:
- rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
- break;
- case ANT_SELECT_WK_CID:
- antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
- break;
-#ifdef CONFIG_88EU_AP_MODE
- case CHECK_HIQ_WK_CID:
- rtw_chk_hi_queue_hdl(padapter);
- break;
-#endif /* CONFIG_88EU_AP_MODE */
- default:
- break;
- }
-
- if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
- kfree(pdrvextra_cmd->pbuf);
-
- return H2C_SUCCESS;
-}
-
-void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res == H2C_DROPPED) {
- /* TODO: cancel timer and do timeout handler directly... */
- /* need to make timeout handlerOS independent */
- mod_timer(&pmlmepriv->scan_to_timer,
- jiffies + msecs_to_jiffies(1));
- } else if (pcmd->res != H2C_SUCCESS) {
- mod_timer(&pmlmepriv->scan_to_timer,
- jiffies + msecs_to_jiffies(1));
- }
-}
-
-void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res != H2C_SUCCESS) {
- spin_lock_bh(&pmlmepriv->lock);
- set_fwstate(pmlmepriv, _FW_LINKED);
- spin_unlock_bh(&pmlmepriv->lock);
- }
-}
-
-void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res == H2C_DROPPED) {
- /* TODO: cancel timer and do timeout handler directly... */
- /* need to make timeout handlerOS independent */
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(1));
- } else if (pcmd->res != H2C_SUCCESS) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(1));
- }
-}
-
-void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-{
- struct sta_info *psta = NULL;
- struct wlan_network *pwlan = NULL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-
- if (pcmd->res != H2C_SUCCESS) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(1));
- }
-
- del_timer_sync(&pmlmepriv->assoc_timer);
-
- spin_lock_bh(&pmlmepriv->lock);
-
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
- if (!psta) {
- psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
- if (!psta) {
- goto createbss_cmd_fail;
- }
- }
-
- rtw_indicate_connect(padapter);
- } else {
- pwlan = rtw_alloc_network(pmlmepriv);
- spin_lock_bh(&pmlmepriv->scanned_queue.lock);
- if (!pwlan) {
- pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
- if (!pwlan) {
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
- goto createbss_cmd_fail;
- }
- pwlan->last_scanned = jiffies;
- } else {
- list_add_tail(&pwlan->list,
- &pmlmepriv->scanned_queue.queue);
- }
-
- pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
- memcpy(&pwlan->network, pnetwork, pnetwork->Length);
-
- memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
-
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
- /* we will set _FW_LINKED when there is one more sat to
- * join us (rtw_stassoc_event_callback)
- */
- }
-
-createbss_cmd_fail:
-
- spin_unlock_bh(&pmlmepriv->lock);
-}
-
-void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-{
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
- struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
- struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
-
- if (!psta)
- return;
-
- psta->aid = passocsta_rsp->cam_id;
- psta->mac_id = passocsta_rsp->cam_id;
-
- spin_lock_bh(&pmlmepriv->lock);
-
- set_fwstate(pmlmepriv, _FW_LINKED);
- spin_unlock_bh(&pmlmepriv->lock);
-}
diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
deleted file mode 100644
index 80673a73c119..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_efuse.c
+++ /dev/null
@@ -1,876 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTW_EFUSE_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtw_efuse.h>
-#include <usb_ops_linux.h>
-#include <rtl8188e_hal.h>
-#include <rtw_iol.h>
-
-#define REG_EFUSE_CTRL 0x0030
-#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
-
-enum{
- VOLTAGE_V25 = 0x03,
- LDOE25_SHIFT = 28,
- };
-
-/*
- * When we want to enable write operation, we should change to pwr on state.
- * When we stop write, we should switch to 500k mode and disable LDO 2.5V.
- */
-static void efuse_power_switch(struct adapter *pAdapter, u8 write, u8 pwrstate)
-{
- u8 tempval;
- u16 tmpv16;
-
- if (pwrstate) {
- usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
-
- /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), default valid */
- tmpv16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL);
- if (!(tmpv16 & PWC_EV12V)) {
- tmpv16 |= PWC_EV12V;
- usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpv16);
- }
- /* Reset: 0x0000h[28], default valid */
- tmpv16 = usb_read16(pAdapter, REG_SYS_FUNC_EN);
- if (!(tmpv16 & FEN_ELDR)) {
- tmpv16 |= FEN_ELDR;
- usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpv16);
- }
-
- /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
- tmpv16 = usb_read16(pAdapter, REG_SYS_CLKR);
- if ((!(tmpv16 & LOADER_CLK_EN)) || (!(tmpv16 & ANA8M))) {
- tmpv16 |= (LOADER_CLK_EN | ANA8M);
- usb_write16(pAdapter, REG_SYS_CLKR, tmpv16);
- }
-
- if (write) {
- /* Enable LDO 2.5V before read/write action */
- tempval = usb_read8(pAdapter, EFUSE_TEST + 3);
- tempval &= 0x0F;
- tempval |= (VOLTAGE_V25 << 4);
- usb_write8(pAdapter, EFUSE_TEST + 3, (tempval | 0x80));
- }
- } else {
- usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
-
- if (write) {
- /* Disable LDO 2.5V after read/write action */
- tempval = usb_read8(pAdapter, EFUSE_TEST + 3);
- usb_write8(pAdapter, EFUSE_TEST + 3, (tempval & 0x7F));
- }
- }
-}
-
-static void
-efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf)
-{
- u8 *efuseTbl = NULL;
- u8 rtemp8;
- u16 eFuse_Addr = 0;
- u8 offset, wren;
- u16 i, j;
- u16 **eFuseWord = NULL;
- u16 efuse_utilized = 0;
- u8 u1temp = 0;
- void **tmp = NULL;
-
- efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
- if (!efuseTbl)
- return;
-
- tmp = kcalloc(EFUSE_MAX_SECTION_88E,
- sizeof(void *) + EFUSE_MAX_WORD_UNIT * sizeof(u16),
- GFP_KERNEL);
- if (!tmp)
- goto eFuseWord_failed;
- for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
- tmp[i] = ((char *)(tmp + EFUSE_MAX_SECTION_88E)) + i * EFUSE_MAX_WORD_UNIT * sizeof(u16);
- eFuseWord = (u16 **)tmp;
-
- /* 0. Refresh efuse init map as all oxFF. */
- for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
- for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
- eFuseWord[i][j] = 0xFFFF;
-
- /* */
- /* 1. Read the first byte to check if efuse is empty!!! */
- /* */
- /* */
- rtemp8 = *(phymap + eFuse_Addr);
- if (rtemp8 != 0xFF) {
- efuse_utilized++;
- eFuse_Addr++;
- } else {
- goto exit;
- }
-
- /* */
- /* 2. Read real efuse content. Filter PG header and every section data. */
- /* */
- while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
- /* Check PG header for section num. */
- if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */
- u1temp = (rtemp8 & 0xE0) >> 5;
- rtemp8 = *(phymap + eFuse_Addr);
- if ((rtemp8 & 0x0F) == 0x0F) {
- eFuse_Addr++;
- rtemp8 = *(phymap + eFuse_Addr);
-
- if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
- eFuse_Addr++;
- continue;
- } else {
- offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
- wren = rtemp8 & 0x0F;
- eFuse_Addr++;
- }
- } else {
- offset = (rtemp8 >> 4) & 0x0f;
- wren = rtemp8 & 0x0f;
- }
-
- if (offset < EFUSE_MAX_SECTION_88E) {
- /* Get word enable value from PG header */
- for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
- /* Check word enable condition in the section */
- if (!(wren & 0x01)) {
- rtemp8 = *(phymap + eFuse_Addr);
- eFuse_Addr++;
- efuse_utilized++;
- eFuseWord[offset][i] = (rtemp8 & 0xff);
- if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
- break;
- rtemp8 = *(phymap + eFuse_Addr);
- eFuse_Addr++;
- efuse_utilized++;
- eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
-
- if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
- break;
- }
- wren >>= 1;
- }
- }
- /* Read next PG header */
- rtemp8 = *(phymap + eFuse_Addr);
-
- if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
- efuse_utilized++;
- eFuse_Addr++;
- }
- }
-
- /* */
- /* 3. Collect 16 sections and 4 word unit into Efuse map. */
- /* */
- for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
- for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
- efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff);
- efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff);
- }
- }
-
- /* */
- /* 4. Copy from Efuse map to output pointer memory!!! */
- /* */
- for (i = 0; i < _size_byte; i++)
- pbuf[i] = efuseTbl[_offset + i];
-
- /* */
- /* 5. Calculate Efuse utilization. */
- /* */
-
-exit:
- kfree(eFuseWord);
-
-eFuseWord_failed:
- kfree(efuseTbl);
-}
-
-static void efuse_read_phymap_from_txpktbuf(
- struct adapter *adapter,
- int bcnhead, /* beacon head, where FW store len(2-byte) and efuse physical map. */
- u8 *content, /* buffer to store efuse physical map */
- u16 *size /* for efuse content: the max byte to read. will update to byte read */
- )
-{
- u16 dbg_addr = 0;
- unsigned long start = 0;
- u8 reg_0x143 = 0;
- u32 lo32 = 0, hi32 = 0;
- u16 len = 0, count = 0;
- int i = 0;
- u16 limit = *size;
-
- u8 *pos = content;
-
- if (bcnhead < 0) /* if not valid */
- bcnhead = usb_read8(adapter, REG_TDECTRL + 1);
-
- usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
-
- dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */
-
- while (1) {
- usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr + i);
-
- usb_write8(adapter, REG_TXPKTBUF_DBG, 0);
- start = jiffies;
- while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) &&
- jiffies_to_msecs(jiffies - start) < 1000)
- usleep_range(1000, 2000);
-
- lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L);
- hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H);
-
- if (i == 0) {
- usb_read8(adapter, REG_PKTBUF_DBG_DATA_L);
- usb_read8(adapter, REG_PKTBUF_DBG_DATA_L + 1);
-
- len = le16_to_cpu(*((__le16 *)&lo32));
-
- limit = min_t(u16, len - 2, limit);
-
- memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count);
- count += (limit >= count + 2) ? 2 : limit - count;
- pos = content + count;
-
- } else {
- memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count);
- count += (limit >= count + 4) ? 4 : limit - count;
- pos = content + count;
- }
-
- if (limit > count && len - 2 > count) {
- memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count);
- count += (limit >= count + 4) ? 4 : limit - count;
- pos = content + count;
- }
-
- if (limit <= count || len - 2 <= count)
- break;
- i++;
- }
- usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
- *size = count;
-}
-
-static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
-{
- s32 status = _FAIL;
- u8 physical_map[512];
- u16 size = 512;
-
- usb_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy);
- memset(physical_map, 0xFF, 512);
- usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
- status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
- if (status == _SUCCESS)
- efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
- efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
- return status;
-}
-
-static void efuse_ReadEFuse(struct adapter *Adapter, u16 _offset, u16 _size_byte, u8 *pbuf)
-{
- if (rtw_iol_applied(Adapter)) {
- rtw_hal_power_on(Adapter);
- iol_mode_enable(Adapter, 1);
- iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
- iol_mode_enable(Adapter, 0);
- }
-}
-
-u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data)
-{
- u16 tmpaddr = 0;
- u16 start_addr = efuse_addr;
- u8 badworden = 0x0F;
- u8 tmpdata[8];
-
- memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
-
- if (!(word_en & BIT(0))) {
- tmpaddr = start_addr;
- efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
- efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
-
- efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
- efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[1]);
- if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
- badworden &= (~BIT(0));
- }
- if (!(word_en & BIT(1))) {
- tmpaddr = start_addr;
- efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
- efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
-
- efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
- efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[3]);
- if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
- badworden &= (~BIT(1));
- }
- if (!(word_en & BIT(2))) {
- tmpaddr = start_addr;
- efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
- efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
-
- efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
- efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[5]);
- if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
- badworden &= (~BIT(2));
- }
- if (!(word_en & BIT(3))) {
- tmpaddr = start_addr;
- efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
- efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
-
- efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
- efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[7]);
- if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
- badworden &= (~BIT(3));
- }
- return badworden;
-}
-
-static u16 Efuse_GetCurrentSize(struct adapter *pAdapter)
-{
- u16 efuse_addr = 0;
- u8 hoffset = 0, hworden = 0;
- u8 efuse_data, word_cnts = 0;
-
- rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
-
- while (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) &&
- AVAILABLE_EFUSE_ADDR(efuse_addr)) {
- if (efuse_data == 0xFF)
- break;
- if ((efuse_data & 0x1F) == 0x0F) { /* extended header */
- hoffset = efuse_data;
- efuse_addr++;
- efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
- if ((efuse_data & 0x0F) == 0x0F) {
- efuse_addr++;
- continue;
- } else {
- hoffset = ((hoffset & 0xE0) >> 5) |
- ((efuse_data & 0xF0) >> 1);
- hworden = efuse_data & 0x0F;
- }
- } else {
- hoffset = (efuse_data >> 4) & 0x0F;
- hworden = efuse_data & 0x0F;
- }
- word_cnts = Efuse_CalculateWordCnts(hworden);
- /* read next header */
- efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- }
-
- rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
-
- return efuse_addr;
-}
-
-int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data)
-{
- u8 ReadState = PG_STATE_HEADER;
- int bDataEmpty = true;
- u8 efuse_data, word_cnts = 0;
- u16 efuse_addr = 0;
- u8 hoffset = 0, hworden = 0;
- u8 tmpidx = 0;
- u8 tmpdata[8];
- u8 tmp_header = 0;
-
- if (!data)
- return false;
- if (offset > EFUSE_MAX_SECTION_88E)
- return false;
-
- memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
- memset(tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
-
- /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
- /* Skip dummy parts to prevent unexpected data read from Efuse. */
- /* By pass right now. 2009.02.19. */
- while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
- /* Header Read ------------- */
- if (ReadState & PG_STATE_HEADER) {
- if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) {
- if (EXT_HEADER(efuse_data)) {
- tmp_header = efuse_data;
- efuse_addr++;
- efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
- if (!ALL_WORDS_DISABLED(efuse_data)) {
- hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
- hworden = efuse_data & 0x0F;
- } else {
- efuse_addr++;
- continue;
- }
- } else {
- hoffset = (efuse_data >> 4) & 0x0F;
- hworden = efuse_data & 0x0F;
- }
- word_cnts = Efuse_CalculateWordCnts(hworden);
- bDataEmpty = true;
-
- if (hoffset == offset) {
- for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) {
- if (efuse_OneByteRead(pAdapter, efuse_addr + 1 + tmpidx, &efuse_data)) {
- tmpdata[tmpidx] = efuse_data;
- if (efuse_data != 0xff)
- bDataEmpty = false;
- }
- }
- if (!bDataEmpty) {
- ReadState = PG_STATE_DATA;
- } else {/* read next header */
- efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- ReadState = PG_STATE_HEADER;
- }
- } else {/* read next header */
- efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- ReadState = PG_STATE_HEADER;
- }
- } else {
- break;
- }
- } else if (ReadState & PG_STATE_DATA) {
- /* Data section Read ------------- */
- efuse_WordEnableDataRead(hworden, tmpdata, data);
- efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- ReadState = PG_STATE_HEADER;
- }
- }
-
- if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) &&
- (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff))
- return false;
- else
- return true;
-}
-
-static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, struct pgpkt *pFixPkt, u16 *pAddr)
-{
- u8 originaldata[8], badworden = 0;
- u16 efuse_addr = *pAddr;
- u32 PgWriteSuccess = 0;
-
- memset(originaldata, 0xff, 8);
-
- if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) {
- /* check if data exist */
- badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pFixPkt->word_en, originaldata);
-
- if (badworden != 0xf) { /* write fail */
- PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata);
-
- if (!PgWriteSuccess)
- return false;
-
- efuse_addr = Efuse_GetCurrentSize(pAdapter);
- } else {
- efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1;
- }
- } else {
- efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1;
- }
- *pAddr = efuse_addr;
- return true;
-}
-
-static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u16 *pAddr, struct pgpkt *pTargetPkt)
-{
- bool ret = false;
- u16 efuse_addr = *pAddr;
- u16 efuse_max_available_len =
- EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E;
- u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
- u8 repeatcnt = 0;
-
- while (efuse_addr < efuse_max_available_len) {
- pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
- efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
- efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
-
- while (tmp_header == 0xFF) {
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
- efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
- }
-
- /* to write ext_header */
- if (tmp_header == pg_header) {
- efuse_addr++;
- pg_header_temp = pg_header;
- pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
-
- efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
- efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
-
- while (tmp_header == 0xFF) {
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
- efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
- }
-
- if ((tmp_header & 0x0F) == 0x0F) { /* word_en PG fail */
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- efuse_addr++;
- continue;
- } else if (pg_header != tmp_header) { /* offset PG fail */
- struct pgpkt fixPkt;
-
- fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
- fixPkt.word_en = tmp_header & 0x0F;
- fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
- if (!hal_EfuseFixHeaderProcess(pAdapter, &fixPkt, &efuse_addr))
- return false;
- } else {
- ret = true;
- break;
- }
- } else if ((tmp_header & 0x1F) == 0x0F) { /* wrong extended header */
- efuse_addr += 2;
- continue;
- }
- }
-
- *pAddr = efuse_addr;
- return ret;
-}
-
-static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u16 *pAddr, struct pgpkt *pTargetPkt)
-{
- bool ret = false;
- u8 pg_header = 0, tmp_header = 0;
- u16 efuse_addr = *pAddr;
- u8 repeatcnt = 0;
-
- pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
-
- efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
- efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
-
- while (tmp_header == 0xFF) {
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
- efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
- efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
- }
-
- if (pg_header == tmp_header) {
- ret = true;
- } else {
- struct pgpkt fixPkt;
-
- fixPkt.offset = (tmp_header >> 4) & 0x0F;
- fixPkt.word_en = tmp_header & 0x0F;
- fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
- if (!hal_EfuseFixHeaderProcess(pAdapter, &fixPkt, &efuse_addr))
- return false;
- }
-
- *pAddr = efuse_addr;
- return ret;
-}
-
-static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u16 *pAddr, struct pgpkt *pTargetPkt)
-{
- u16 efuse_addr = *pAddr;
- u8 badworden;
- u32 PgWriteSuccess = 0;
-
- badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data);
- if (badworden == 0x0F) {
- /* write ok */
- return true;
- }
- /* reorganize other pg packet */
- PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
- if (!PgWriteSuccess)
- return false;
- else
- return true;
-}
-
-static bool
-hal_EfusePgPacketWriteHeader(
- struct adapter *pAdapter,
- u16 *pAddr,
- struct pgpkt *pTargetPkt)
-{
- bool ret = false;
-
- if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
- ret = hal_EfusePgPacketWrite2ByteHeader(pAdapter, pAddr, pTargetPkt);
- else
- ret = hal_EfusePgPacketWrite1ByteHeader(pAdapter, pAddr, pTargetPkt);
-
- return ret;
-}
-
-static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
- u8 *pWden)
-{
- u8 match_word_en = 0x0F; /* default all words are disabled */
-
- /* check if the same words are enabled both target and current PG packet */
- if (((pTargetPkt->word_en & BIT(0)) == 0) &&
- ((pCurPkt->word_en & BIT(0)) == 0))
- match_word_en &= ~BIT(0); /* enable word 0 */
- if (((pTargetPkt->word_en & BIT(1)) == 0) &&
- ((pCurPkt->word_en & BIT(1)) == 0))
- match_word_en &= ~BIT(1); /* enable word 1 */
- if (((pTargetPkt->word_en & BIT(2)) == 0) &&
- ((pCurPkt->word_en & BIT(2)) == 0))
- match_word_en &= ~BIT(2); /* enable word 2 */
- if (((pTargetPkt->word_en & BIT(3)) == 0) &&
- ((pCurPkt->word_en & BIT(3)) == 0))
- match_word_en &= ~BIT(3); /* enable word 3 */
-
- *pWden = match_word_en;
-
- if (match_word_en != 0xf)
- return true;
- else
- return false;
-}
-
-static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr)
-{
- bool ret = false;
- u8 i, efuse_data;
-
- for (i = 0; i < (word_cnts * 2); i++) {
- if (efuse_OneByteRead(pAdapter, (startAddr + i), &efuse_data) && (efuse_data != 0xFF))
- ret = true;
- }
- return ret;
-}
-
-static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u16 *pAddr, struct pgpkt *pTargetPkt)
-{
- bool ret = false;
- u8 i, efuse_data = 0, cur_header = 0;
- u8 matched_wden = 0, badworden = 0;
- u16 startAddr = 0;
- u16 efuse_max_available_len =
- EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E;
- struct pgpkt curPkt;
-
- rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
- startAddr %= EFUSE_REAL_CONTENT_LEN;
-
- while (1) {
- if (startAddr >= efuse_max_available_len) {
- ret = false;
- break;
- }
-
- if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) {
- if (EXT_HEADER(efuse_data)) {
- cur_header = efuse_data;
- startAddr++;
- efuse_OneByteRead(pAdapter, startAddr, &efuse_data);
- if (ALL_WORDS_DISABLED(efuse_data)) {
- ret = false;
- break;
- }
- curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
- curPkt.word_en = efuse_data & 0x0F;
- } else {
- cur_header = efuse_data;
- curPkt.offset = (cur_header >> 4) & 0x0F;
- curPkt.word_en = cur_header & 0x0F;
- }
-
- curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
- /* if same header is found but no data followed */
- /* write some part of data followed by the header. */
- if ((curPkt.offset == pTargetPkt->offset) &&
- (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr + 1)) &&
- wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
- /* Here to write partial data */
- badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr + 1, matched_wden, pTargetPkt->data);
- if (badworden != 0x0F) {
- u32 PgWriteSuccess = 0;
- /* if write fail on some words, write these bad words again */
-
- PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
-
- if (!PgWriteSuccess) {
- ret = false; /* write fail, return */
- break;
- }
- }
- /* partial write ok, update the target packet for later use */
- for (i = 0; i < 4; i++) {
- if ((matched_wden & (0x1 << i)) == 0) /* this word has been written */
- pTargetPkt->word_en |= (0x1 << i); /* disable the word */
- }
- pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
- }
- /* read from next header */
- startAddr = startAddr + (curPkt.word_cnts * 2) + 1;
- } else {
- /* not used header, 0xff */
- *pAddr = startAddr;
- ret = true;
- break;
- }
- }
- return ret;
-}
-
-static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
-{
- memset((void *)pTargetPkt->data, 0xFF, sizeof(u8) * 8);
- pTargetPkt->offset = offset;
- pTargetPkt->word_en = word_en;
- efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
- pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
-}
-
-bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData)
-{
- struct pgpkt targetPkt;
- u16 startAddr = 0;
-
- if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E)
- return false;
-
- hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
-
- if (!hal_EfusePartialWriteCheck(pAdapter, &startAddr, &targetPkt))
- return false;
-
- if (!hal_EfusePgPacketWriteHeader(pAdapter, &startAddr, &targetPkt))
- return false;
-
- if (!hal_EfusePgPacketWriteData(pAdapter, &startAddr, &targetPkt))
- return false;
-
- return true;
-}
-
-u8 Efuse_CalculateWordCnts(u8 word_en)
-{
- u8 word_cnts = 0;
-
- if (!(word_en & BIT(0)))
- word_cnts++; /* 0 : write enable */
- if (!(word_en & BIT(1)))
- word_cnts++;
- if (!(word_en & BIT(2)))
- word_cnts++;
- if (!(word_en & BIT(3)))
- word_cnts++;
- return word_cnts;
-}
-
-u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data)
-{
- u8 tmpidx = 0;
- u8 result;
-
- usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
- usb_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
- (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
-
- usb_write8(pAdapter, EFUSE_CTRL + 3, 0x72);/* read cmd */
-
- while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100) {
- *data = usb_read8(pAdapter, EFUSE_CTRL);
- result = true;
- } else {
- *data = 0xff;
- result = false;
- }
- return result;
-}
-
-u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
-{
- u8 tmpidx = 0;
- u8 result;
-
- usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
- usb_write8(pAdapter, EFUSE_CTRL + 2,
- (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
- (u8)((addr >> 8) & 0x03));
- usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
-
- usb_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */
-
- while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
- tmpidx++;
-
- if (tmpidx < 100)
- result = true;
- else
- result = false;
-
- return result;
-}
-
-/* Read allowed word in current efuse section data. */
-void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
-{
- if (!(word_en & BIT(0))) {
- targetdata[0] = sourdata[0];
- targetdata[1] = sourdata[1];
- }
- if (!(word_en & BIT(1))) {
- targetdata[2] = sourdata[2];
- targetdata[3] = sourdata[3];
- }
- if (!(word_en & BIT(2))) {
- targetdata[4] = sourdata[4];
- targetdata[5] = sourdata[5];
- }
- if (!(word_en & BIT(3))) {
- targetdata[6] = sourdata[6];
- targetdata[7] = sourdata[7];
- }
-}
-
-/* Read All Efuse content */
-static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 *Efuse)
-{
- efuse_power_switch(pAdapter, false, true);
-
- efuse_ReadEFuse(pAdapter, 0, EFUSE_MAP_LEN_88E, Efuse);
-
- efuse_power_switch(pAdapter, false, false);
-}
-
-/* Transfer current EFUSE content to shadow init and modify map. */
-void EFUSE_ShadowMapUpdate(struct adapter *pAdapter)
-{
- struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
-
- if (pEEPROM->bautoload_fail_flag)
- memset(pEEPROM->efuse_eeprom_data, 0xFF, EFUSE_MAP_LEN_88E);
- else
- Efuse_ReadAllMap(pAdapter, pEEPROM->efuse_eeprom_data);
-}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
deleted file mode 100644
index e431914db008..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
+++ /dev/null
@@ -1,992 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _IEEE80211_C
-
-#include <linux/ieee80211.h>
-
-#include <drv_types.h>
-#include <osdep_intf.h>
-#include <ieee80211.h>
-#include <wifi.h>
-#include <osdep_service.h>
-#include <wlan_bssdef.h>
-
-u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
-u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
-u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
-u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
-u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
-u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
-u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
-u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
-u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
-u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
-
-u16 RSN_VERSION_BSD = 1;
-u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
-u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
-u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
-u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
-u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
-u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
-u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
-u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
-/* */
-/* for adhoc-master to generate ie and provide supported-rate to fw */
-/* */
-
-static u8 WIFI_CCKRATES[] = {
- IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
- IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
-};
-
-static u8 WIFI_OFDMRATES[] = {
- IEEE80211_OFDM_RATE_6MB,
- IEEE80211_OFDM_RATE_9MB,
- IEEE80211_OFDM_RATE_12MB,
- IEEE80211_OFDM_RATE_18MB,
- IEEE80211_OFDM_RATE_24MB,
- IEEE80211_OFDM_RATE_36MB,
- IEEE80211_OFDM_RATE_48MB,
- IEEE80211_OFDM_RATE_54MB
-};
-
-int rtw_get_bit_value_from_ieee_value(u8 val)
-{
- static const unsigned char dot11_rate_table[] = {
- 2, 4, 11, 22, 12, 18, 24, 36, 48,
- 72, 96, 108, 0}; /* last element must be zero!! */
- int i = 0;
-
- while (dot11_rate_table[i] != 0) {
- if (dot11_rate_table[i] == val)
- return BIT(i);
- i++;
- }
- return 0;
-}
-
-bool rtw_is_cckrates_included(u8 *rate)
-{
- while (*rate) {
- u8 r = *rate & 0x7f;
-
- if (r == 2 || r == 4 || r == 11 || r == 22)
- return true;
- rate++;
- }
-
- return false;
-}
-
-bool rtw_is_cckratesonly_included(u8 *rate)
-{
- while (*rate) {
- u8 r = *rate & 0x7f;
-
- if (r != 2 && r != 4 && r != 11 && r != 22)
- return false;
- rate++;
- }
-
- return true;
-}
-
-int rtw_check_network_type(unsigned char *rate)
-{
- /* could be pure B, pure G, or B/G */
- if (rtw_is_cckratesonly_included(rate))
- return WIRELESS_11B;
- else if (rtw_is_cckrates_included(rate))
- return WIRELESS_11BG;
- else
- return WIRELESS_11G;
-}
-
-u8 *rtw_set_fixed_ie(void *pbuf, unsigned int len, void *source,
- unsigned int *frlen)
-{
- memcpy(pbuf, source, len);
- *frlen = *frlen + len;
- return ((u8 *)pbuf) + len;
-}
-
-/* rtw_set_ie will update frame length */
-u8 *rtw_set_ie
-(
- u8 *pbuf,
- int index,
- uint len,
- u8 *source,
- uint *frlen /* frame length */
-)
-{
- *pbuf = (u8)index;
-
- *(pbuf + 1) = (u8)len;
-
- if (len > 0)
- memcpy((void *)(pbuf + 2), (void *)source, len);
-
- *frlen = *frlen + (len + 2);
-
- return pbuf + len + 2;
-}
-
-/*
- * ----------------------------------------------------------------------------
- * index: the information element id index, limit is the limit for search
- * ----------------------------------------------------------------------------
- */
-u8 *rtw_get_ie(u8 *pbuf, int index, uint *len, int limit)
-{
- int tmp, i;
- u8 *p;
-
- if (limit < 1)
- return NULL;
-
- p = pbuf;
- i = 0;
- *len = 0;
- while (1) {
- if (*p == index) {
- *len = *(p + 1);
- return p;
- }
- tmp = *(p + 1);
- p += (tmp + 2);
- i += (tmp + 2);
- if (i >= limit)
- break;
- }
- return NULL;
-}
-
-void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
-{
- memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
-
- switch (mode) {
- case WIRELESS_11B:
- memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
- break;
- case WIRELESS_11G:
- case WIRELESS_11A:
- case WIRELESS_11_5N:
- case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */
- memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
- break;
- case WIRELESS_11BG:
- case WIRELESS_11G_24N:
- case WIRELESS_11_24N:
- case WIRELESS_11BG_24N:
- memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
- memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
- break;
- }
-}
-
-uint rtw_get_rateset_len(u8 *rateset)
-{
- uint i;
-
- for (i = 0; i < 13; i++)
- if (rateset[i] == 0)
- break;
- return i;
-}
-
-int rtw_generate_ie(struct registry_priv *pregistrypriv)
-{
- u8 wireless_mode;
- int rateLen;
- uint sz = 0;
- struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
- u8 *ie = pdev_network->ies;
-
- /* timestamp will be inserted by hardware */
- sz += 8;
- ie += sz;
-
- /* beacon interval : 2bytes */
- *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */
- sz += 2;
- ie += 2;
-
- /* capability info */
- *(u16 *)ie = 0;
-
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_IBSS);
-
- if (pregistrypriv->preamble == PREAMBLE_SHORT)
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
-
- if (pdev_network->Privacy)
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
-
- sz += 2;
- ie += 2;
-
- /* SSID */
- ie = rtw_set_ie(ie, WLAN_EID_SSID, pdev_network->ssid.ssid_length, pdev_network->ssid.ssid, &sz);
-
- /* supported rates */
- if (pregistrypriv->wireless_mode == WIRELESS_11ABGN)
- wireless_mode = WIRELESS_11BG_24N;
- else
- wireless_mode = pregistrypriv->wireless_mode;
-
- rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode);
-
- rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
-
- if (rateLen > 8) {
- ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, 8, pdev_network->SupportedRates, &sz);
- /* ie = rtw_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
- } else {
- ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, rateLen, pdev_network->SupportedRates, &sz);
- }
-
- /* DS parameter set */
- ie = rtw_set_ie(ie, WLAN_EID_DS_PARAMS, 1, (u8 *)&pdev_network->Configuration.DSConfig, &sz);
-
- /* IBSS Parameter Set */
-
- ie = rtw_set_ie(ie, WLAN_EID_IBSS_PARAMS, 2, (u8 *)&pdev_network->Configuration.ATIMWindow, &sz);
-
- if (rateLen > 8)
- ie = rtw_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
-
- return sz;
-}
-
-unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit)
-{
- uint len;
- u16 val16;
- __le16 le_tmp;
- static const unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
- u8 *pbuf = pie;
- int limit_new = limit;
-
- while (1) {
- pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &len, limit_new);
-
- if (pbuf) {
- /* check if oui matches... */
- if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type)))
- goto check_next_ie;
-
- /* check version... */
- memcpy((u8 *)&le_tmp, (pbuf + 6), sizeof(val16));
-
- val16 = le16_to_cpu(le_tmp);
- if (val16 != 0x0001)
- goto check_next_ie;
- *wpa_ie_len = *(pbuf + 1);
- return pbuf;
- }
- *wpa_ie_len = 0;
- return NULL;
-
-check_next_ie:
- limit_new = limit - (pbuf - pie) - 2 - len;
- if (limit_new <= 0)
- break;
- pbuf += (2 + len);
- }
- *wpa_ie_len = 0;
- return NULL;
-}
-
-unsigned char *rtw_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len, int limit)
-{
- return rtw_get_ie(pie, WLAN_EID_RSN, rsn_ie_len, limit);
-}
-
-int rtw_get_wpa_cipher_suite(u8 *s)
-{
- if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
- return WPA_CIPHER_NONE;
- if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
- return WPA_CIPHER_WEP40;
- if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
- return WPA_CIPHER_TKIP;
- if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
- return WPA_CIPHER_CCMP;
- if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
- return WPA_CIPHER_WEP104;
-
- return 0;
-}
-
-int rtw_get_wpa2_cipher_suite(u8 *s)
-{
- if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
- return WPA_CIPHER_NONE;
- if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
- return WPA_CIPHER_WEP40;
- if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
- return WPA_CIPHER_TKIP;
- if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
- return WPA_CIPHER_CCMP;
- if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
- return WPA_CIPHER_WEP104;
-
- return 0;
-}
-
-int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
-{
- int i, ret = _SUCCESS;
- int left, count;
- u8 *pos;
- u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
-
- if (wpa_ie_len <= 0) {
- /* No WPA IE - fail silently */
- return _FAIL;
- }
-
- if ((*wpa_ie != WLAN_EID_VENDOR_SPECIFIC) || (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) ||
- (memcmp(wpa_ie + 2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN)))
- return _FAIL;
-
- pos = wpa_ie;
-
- pos += 8;
- left = wpa_ie_len - 8;
-
- /* group_cipher */
- if (left >= WPA_SELECTOR_LEN) {
- *group_cipher = rtw_get_wpa_cipher_suite(pos);
- pos += WPA_SELECTOR_LEN;
- left -= WPA_SELECTOR_LEN;
- } else if (left > 0) {
- return _FAIL;
- }
-
- /* pairwise_cipher */
- if (left >= 2) {
- count = get_unaligned_le16(pos);
- pos += 2;
- left -= 2;
-
- if (count == 0 || left < count * WPA_SELECTOR_LEN)
- return _FAIL;
-
- for (i = 0; i < count; i++) {
- *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
-
- pos += WPA_SELECTOR_LEN;
- left -= WPA_SELECTOR_LEN;
- }
- } else if (left == 1) {
- return _FAIL;
- }
-
- if (is_8021x) {
- if (left >= 6) {
- pos += 2;
- if (!memcmp(pos, SUITE_1X, 4))
- *is_8021x = 1;
- }
- }
-
- return ret;
-}
-
-int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
-{
- int i, ret = _SUCCESS;
- int left, count;
- u8 *pos;
- u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
-
- if (rsn_ie_len <= 0) {
- /* No RSN IE - fail silently */
- return _FAIL;
- }
-
- if ((*rsn_ie != WLAN_EID_RSN) || (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2)))
- return _FAIL;
-
- pos = rsn_ie;
- pos += 4;
- left = rsn_ie_len - 4;
-
- /* group_cipher */
- if (left >= RSN_SELECTOR_LEN) {
- *group_cipher = rtw_get_wpa2_cipher_suite(pos);
-
- pos += RSN_SELECTOR_LEN;
- left -= RSN_SELECTOR_LEN;
-
- } else if (left > 0) {
- return _FAIL;
- }
-
- /* pairwise_cipher */
- if (left >= 2) {
- count = get_unaligned_le16(pos);
- pos += 2;
- left -= 2;
-
- if (count == 0 || left < count * RSN_SELECTOR_LEN)
- return _FAIL;
-
- for (i = 0; i < count; i++) {
- *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
-
- pos += RSN_SELECTOR_LEN;
- left -= RSN_SELECTOR_LEN;
- }
-
- } else if (left == 1) {
- return _FAIL;
- }
-
- if (is_8021x) {
- if (left >= 6) {
- pos += 2;
- if (!memcmp(pos, SUITE_1X, 4))
- *is_8021x = 1;
- }
- }
- return ret;
-}
-
-void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len)
-{
- u8 authmode, sec_idx;
- u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
- uint cnt;
-
- /* Search required WPA or WPA2 IE and copy to sec_ie[] */
-
- cnt = _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_;
-
- sec_idx = 0;
-
- while (cnt < in_len) {
- authmode = in_ie[cnt];
-
- if ((authmode == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
- if (wpa_ie)
- memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
-
- *wpa_len = in_ie[cnt + 1] + 2;
- cnt += in_ie[cnt + 1] + 2; /* get next */
- } else {
- if (authmode == WLAN_EID_RSN) {
- if (rsn_ie)
- memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
-
- *rsn_len = in_ie[cnt + 1] + 2;
- cnt += in_ie[cnt + 1] + 2; /* get next */
- } else {
- cnt += in_ie[cnt + 1] + 2; /* get next */
- }
- }
- }
-}
-
-u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
-{
- u8 match = false;
- u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- if (!ie_ptr)
- return match;
-
- eid = ie_ptr[0];
-
- if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&ie_ptr[2], wps_oui, 4))) {
- *wps_ielen = ie_ptr[1] + 2;
- match = true;
- }
- return match;
-}
-
-/**
- * rtw_get_wps_ie - Search WPS IE from a series of ies
- * @in_ie: Address of ies to search
- * @in_len: Length limit from in_ie
- * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
- * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
- *
- * Returns: The address of the WPS IE found, or NULL
- */
-u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
-{
- uint cnt;
- u8 *wpsie_ptr = NULL;
- u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- if (wps_ielen)
- *wps_ielen = 0;
-
- if (!in_ie || in_len <= 0)
- return wpsie_ptr;
-
- cnt = 0;
-
- while (cnt < in_len) {
- eid = in_ie[cnt];
-
- if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
- wpsie_ptr = &in_ie[cnt];
-
- if (wps_ie)
- memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
-
- if (wps_ielen)
- *wps_ielen = in_ie[cnt + 1] + 2;
-
- cnt += in_ie[cnt + 1] + 2;
-
- break;
- }
- cnt += in_ie[cnt + 1] + 2; /* goto next */
- }
- return wpsie_ptr;
-}
-
-/**
- * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
- * @wps_ie: Address of WPS IE to search
- * @wps_ielen: Length limit from wps_ie
- * @target_attr_id: The attribute ID of WPS attribute to search
- * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
- * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
- *
- * Returns: the address of the specific WPS attribute found, or NULL
- */
-u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr)
-{
- u8 *attr_ptr = NULL;
- u8 *target_attr_ptr = NULL;
- u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
-
- if (len_attr)
- *len_attr = 0;
-
- if ((wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC) ||
- (memcmp(wps_ie + 2, wps_oui, 4)))
- return attr_ptr;
-
- /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
- attr_ptr = wps_ie + 6; /* goto first attr */
-
- while (attr_ptr - wps_ie < wps_ielen) {
- /* 4 = 2(Attribute ID) + 2(Length) */
- u16 attr_id = get_unaligned_be16(attr_ptr);
- u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
- u16 attr_len = attr_data_len + 4;
-
- if (attr_id == target_attr_id) {
- target_attr_ptr = attr_ptr;
- if (buf_attr)
- memcpy(buf_attr, attr_ptr, attr_len);
- if (len_attr)
- *len_attr = attr_len;
- break;
- }
- attr_ptr += attr_len; /* goto next */
- }
- return target_attr_ptr;
-}
-
-/**
- * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
- * @wps_ie: Address of WPS IE to search
- * @wps_ielen: Length limit from wps_ie
- * @target_attr_id: The attribute ID of WPS attribute to search
- * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
- * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
- *
- * Returns: the address of the specific WPS attribute content found, or NULL
- */
-u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content)
-{
- u8 *attr_ptr;
- u32 attr_len;
-
- if (len_content)
- *len_content = 0;
-
- attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
-
- if (attr_ptr && attr_len) {
- if (buf_content)
- memcpy(buf_content, attr_ptr + 4, attr_len - 4);
-
- if (len_content)
- *len_content = attr_len - 4;
-
- return attr_ptr + 4;
- }
-
- return NULL;
-}
-
-static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
- struct rtw_ieee802_11_elems *elems, int show_errors)
-{
- unsigned int oui;
-
- /*
- * first 3 bytes in vendor specific information element are the IEEE
- * OUI of the vendor. The following byte is used a vendor specific
- * sub-type.
- */
- if (elen < 4)
- return -1;
-
- oui = RTW_GET_BE24(pos);
- switch (oui) {
- case OUI_MICROSOFT:
- /*
- * Microsoft/Wi-Fi information elements are further typed and
- * subtyped
- */
- switch (pos[3]) {
- case 1:
- /*
- * Microsoft OUI (00:50:F2) with OUI Type 1:
- * real WPA information element
- */
- elems->wpa_ie = pos;
- elems->wpa_ie_len = elen;
- break;
- case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
- if (elen < 5)
- return -1;
-
- switch (pos[4]) {
- case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
- case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
- elems->wme = pos;
- elems->wme_len = elen;
- break;
- case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
- elems->wme_tspec = pos;
- elems->wme_tspec_len = elen;
- break;
- default:
- return -1;
- }
- break;
- case 4:
- /* Wi-Fi Protected Setup (WPS) IE */
- elems->wps_ie = pos;
- elems->wps_ie_len = elen;
- break;
- default:
- return -1;
- }
- break;
-
- case OUI_BROADCOM:
- switch (pos[3]) {
- case VENDOR_HT_CAPAB_OUI_TYPE:
- elems->vendor_ht_cap = pos;
- elems->vendor_ht_cap_len = elen;
- break;
- default:
- return -1;
- }
- break;
- default:
- return -1;
- }
- return 0;
-}
-
-/**
- * rtw_ieee802_11_parse_elems - Parse information elements in management frames
- * @start: Pointer to the start of ies
- * @len: Length of IE buffer in octets
- * @elems: Data structure for parsed elements
- * @show_errors: Whether to show parsing errors in debug log
- * Returns: Parsing result
- */
-enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len,
- struct rtw_ieee802_11_elems *elems,
- int show_errors)
-{
- uint left = len;
- u8 *pos = start;
- int unknown = 0;
-
- memset(elems, 0, sizeof(*elems));
-
- while (left >= 2) {
- u8 id, elen;
-
- id = *pos++;
- elen = *pos++;
- left -= 2;
-
- if (elen > left)
- return ParseFailed;
-
- switch (id) {
- case WLAN_EID_SSID:
- elems->ssid = pos;
- elems->ssid_len = elen;
- break;
- case WLAN_EID_SUPP_RATES:
- elems->supp_rates = pos;
- elems->supp_rates_len = elen;
- break;
- case WLAN_EID_FH_PARAMS:
- elems->fh_params = pos;
- elems->fh_params_len = elen;
- break;
- case WLAN_EID_DS_PARAMS:
- elems->ds_params = pos;
- elems->ds_params_len = elen;
- break;
- case WLAN_EID_CF_PARAMS:
- elems->cf_params = pos;
- elems->cf_params_len = elen;
- break;
- case WLAN_EID_TIM:
- elems->tim = pos;
- elems->tim_len = elen;
- break;
- case WLAN_EID_IBSS_PARAMS:
- elems->ibss_params = pos;
- elems->ibss_params_len = elen;
- break;
- case WLAN_EID_CHALLENGE:
- elems->challenge = pos;
- elems->challenge_len = elen;
- break;
- case WLAN_EID_ERP_INFO:
- elems->erp_info = pos;
- elems->erp_info_len = elen;
- break;
- case WLAN_EID_EXT_SUPP_RATES:
- elems->ext_supp_rates = pos;
- elems->ext_supp_rates_len = elen;
- break;
- case WLAN_EID_VENDOR_SPECIFIC:
- if (rtw_ieee802_11_parse_vendor_specific(pos, elen, elems, show_errors))
- unknown++;
- break;
- case WLAN_EID_RSN:
- elems->rsn_ie = pos;
- elems->rsn_ie_len = elen;
- break;
- case WLAN_EID_PWR_CAPABILITY:
- elems->power_cap = pos;
- elems->power_cap_len = elen;
- break;
- case WLAN_EID_SUPPORTED_CHANNELS:
- elems->supp_channels = pos;
- elems->supp_channels_len = elen;
- break;
- case WLAN_EID_MOBILITY_DOMAIN:
- elems->mdie = pos;
- elems->mdie_len = elen;
- break;
- case WLAN_EID_FAST_BSS_TRANSITION:
- elems->ftie = pos;
- elems->ftie_len = elen;
- break;
- case WLAN_EID_TIMEOUT_INTERVAL:
- elems->timeout_int = pos;
- elems->timeout_int_len = elen;
- break;
- case WLAN_EID_HT_CAPABILITY:
- elems->ht_capabilities = pos;
- elems->ht_capabilities_len = elen;
- break;
- case WLAN_EID_HT_OPERATION:
- elems->ht_operation = pos;
- elems->ht_operation_len = elen;
- break;
- default:
- unknown++;
- break;
- }
- left -= elen;
- pos += elen;
- }
- if (left)
- return ParseFailed;
- return unknown ? ParseUnknown : ParseOK;
-}
-
-void rtw_macaddr_cfg(u8 *mac_addr)
-{
- u8 mac[ETH_ALEN];
-
- if (!mac_addr)
- return;
-
- if (rtw_initmac && mac_pton(rtw_initmac, mac)) {
- /* Users specify the mac address */
- ether_addr_copy(mac_addr, mac);
- } else {
- /* Use the mac address stored in the Efuse */
- ether_addr_copy(mac, mac_addr);
- }
-
- if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac))
- eth_random_addr(mac_addr);
-}
-
-static int rtw_get_cipher_info(struct wlan_network *pnetwork)
-{
- uint wpa_ielen;
- unsigned char *pbuf;
- int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
- int ret = _FAIL;
-
- pbuf = rtw_get_wpa_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12);
-
- if (pbuf && (wpa_ielen > 0)) {
- if (rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) {
- pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
- pnetwork->BcnInfo.group_cipher = group_cipher;
- pnetwork->BcnInfo.is_8021x = is8021x;
- ret = _SUCCESS;
- }
- } else {
- pbuf = rtw_get_wpa2_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12);
-
- if (pbuf && (wpa_ielen > 0)) {
- if (rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) {
- pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
- pnetwork->BcnInfo.group_cipher = group_cipher;
- pnetwork->BcnInfo.is_8021x = is8021x;
- ret = _SUCCESS;
- }
- }
- }
-
- return ret;
-}
-
-void rtw_get_bcn_info(struct wlan_network *pnetwork)
-{
- unsigned short cap = 0;
- u8 bencrypt = 0;
- __le16 le_tmp;
- u16 wpa_len = 0, rsn_len = 0;
- struct HT_info_element *pht_info = NULL;
- uint len;
- unsigned char *p;
-
- memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
- cap = le16_to_cpu(le_tmp);
- if (cap & WLAN_CAPABILITY_PRIVACY) {
- bencrypt = 1;
- pnetwork->network.Privacy = 1;
- } else {
- pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
- }
- rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &rsn_len, NULL, &wpa_len);
-
- if (rsn_len > 0) {
- pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
- } else if (wpa_len > 0) {
- pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
- } else {
- if (bencrypt)
- pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
- }
- rtw_get_cipher_info(pnetwork);
-
- /* get bwmode and ch_offset */
- /* parsing HT_CAP_IE */
- p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
- if (p && len > 0) {
- struct ieee80211_ht_cap *ht_cap =
- (struct ieee80211_ht_cap *)(p + 2);
-
- pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(ht_cap->cap_info);
- } else {
- pnetwork->BcnInfo.ht_cap_info = 0;
- }
- /* parsing HT_INFO_IE */
- p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
- if (p && len > 0) {
- pht_info = (struct HT_info_element *)(p + 2);
- pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
- } else {
- pnetwork->BcnInfo.ht_info_infos_0 = 0;
- }
-}
-
-/* show MCS rate, unit: 100Kbps */
-u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate)
-{
- u16 max_rate = 0;
-
- if (rf_type == RF_1T1R) {
- if (MCS_rate[0] & BIT(7))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
- else if (MCS_rate[0] & BIT(6))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
- else if (MCS_rate[0] & BIT(5))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
- else if (MCS_rate[0] & BIT(4))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
- else if (MCS_rate[0] & BIT(3))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
- else if (MCS_rate[0] & BIT(2))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
- else if (MCS_rate[0] & BIT(1))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
- else if (MCS_rate[0] & BIT(0))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
- } else {
- if (MCS_rate[1]) {
- if (MCS_rate[1] & BIT(7))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 3000 : 2700) : ((short_GI_20) ? 1444 : 1300);
- else if (MCS_rate[1] & BIT(6))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 2700 : 2430) : ((short_GI_20) ? 1300 : 1170);
- else if (MCS_rate[1] & BIT(5))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 2400 : 2160) : ((short_GI_20) ? 1156 : 1040);
- else if (MCS_rate[1] & BIT(4))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 1800 : 1620) : ((short_GI_20) ? 867 : 780);
- else if (MCS_rate[1] & BIT(3))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
- else if (MCS_rate[1] & BIT(2))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
- else if (MCS_rate[1] & BIT(1))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
- else if (MCS_rate[1] & BIT(0))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
- } else {
- if (MCS_rate[0] & BIT(7))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
- else if (MCS_rate[0] & BIT(6))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
- else if (MCS_rate[0] & BIT(5))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
- else if (MCS_rate[0] & BIT(4))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
- else if (MCS_rate[0] & BIT(3))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
- else if (MCS_rate[0] & BIT(2))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
- else if (MCS_rate[0] & BIT(1))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
- else if (MCS_rate[0] & BIT(0))
- max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
- }
- }
- return max_rate;
-}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
deleted file mode 100644
index f679a7f8fe75..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
+++ /dev/null
@@ -1,512 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTW_IOCTL_SET_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtw_ioctl_set.h>
-#include <hal_intf.h>
-
-static const struct {
- int channel_plan;
- char *name;
-} channel_table[] = { { RT_CHANNEL_DOMAIN_FCC, "US" },
- { RT_CHANNEL_DOMAIN_ETSI, "EU" },
- { RT_CHANNEL_DOMAIN_MKK, "JP" },
- { RT_CHANNEL_DOMAIN_CHINA, "CN"} };
-
-extern void indicate_wx_scan_complete_event(struct adapter *padapter);
-
-u8 rtw_do_join(struct adapter *padapter)
-{
- struct list_head *plist, *phead;
- u8 *pibss = NULL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- u8 ret = _SUCCESS;
-
- spin_lock_bh(&pmlmepriv->scanned_queue.lock);
- phead = get_list_head(queue);
- plist = phead->next;
-
- pmlmepriv->cur_network.join_res = -2;
-
- set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-
- pmlmepriv->pscanned = plist;
-
- pmlmepriv->to_join = true;
-
- if (list_empty(&queue->queue)) {
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-
- /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
- /* we try to issue sitesurvey firstly */
-
- if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
- pmlmepriv->to_roaming > 0) {
- /* submit site_survey_cmd */
- ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
- if (ret != _SUCCESS)
- pmlmepriv->to_join = false;
- } else {
- pmlmepriv->to_join = false;
- ret = _FAIL;
- }
-
- goto exit;
- } else {
- int select_ret;
-
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
- select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
- if (select_ret == _SUCCESS) {
- pmlmepriv->to_join = false;
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
- } else {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- /* submit createbss_cmd to change to a ADHOC_MASTER */
-
- /* pmlmepriv->lock has been acquired by caller... */
- struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
-
- pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
-
- pibss = padapter->registrypriv.dev_network.MacAddress;
-
- memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
-
- rtw_update_registrypriv_dev_network(padapter);
-
- rtw_generate_random_ibss(pibss);
-
- if (rtw_createbss_cmd(padapter) != _SUCCESS) {
- ret = false;
- goto exit;
- }
- pmlmepriv->to_join = false;
- } else {
- /* can't associate ; reset under-linking */
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-
- /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
- /* we try to issue sitesurvey firstly */
- if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
- pmlmepriv->to_roaming > 0) {
- ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
- if (ret != _SUCCESS)
- pmlmepriv->to_join = false;
- } else {
- ret = _FAIL;
- pmlmepriv->to_join = false;
- }
- }
- }
- }
-
-exit:
- return ret;
-}
-
-u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
-{
- u8 status = _SUCCESS;
- u32 cur_time = 0;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 &&
- bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
- (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF &&
- bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
- status = _FAIL;
- goto exit;
- }
-
- spin_lock_bh(&pmlmepriv->lock);
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- goto handle_tkip_countermeasure;
- else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- goto release_mlme_lock;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
- if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
- } else {
- rtw_disassoc_cmd(padapter, 0, true);
-
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- rtw_indicate_disconnect(padapter);
-
- rtw_free_assoc_resources(padapter);
-
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- }
- }
- }
-
-handle_tkip_countermeasure:
- /* should we add something here...? */
-
- if (padapter->securitypriv.btkip_countermeasure) {
- cur_time = jiffies;
-
- if (cur_time - padapter->securitypriv.btkip_countermeasure_time > 60 * HZ) {
- padapter->securitypriv.btkip_countermeasure = false;
- padapter->securitypriv.btkip_countermeasure_time = 0;
- } else {
- status = _FAIL;
- goto release_mlme_lock;
- }
- }
-
- memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
- pmlmepriv->assoc_by_bssid = true;
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- pmlmepriv->to_join = true;
- else
- status = rtw_do_join(padapter);
-
-release_mlme_lock:
- spin_unlock_bh(&pmlmepriv->lock);
-
-exit:
- return status;
-}
-
-u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
-{
- u8 status = _SUCCESS;
- u32 cur_time = 0;
-
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *pnetwork = &pmlmepriv->cur_network;
-
- if (!padapter->hw_init_completed) {
- status = _FAIL;
- goto exit;
- }
-
- spin_lock_bh(&pmlmepriv->lock);
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- goto handle_tkip_countermeasure;
- else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- goto release_mlme_lock;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- if (pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length &&
- !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length)) {
- if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- if (!rtw_is_same_ibss(padapter, pnetwork)) {
- /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
- rtw_disassoc_cmd(padapter, 0, true);
-
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- rtw_indicate_disconnect(padapter);
-
- rtw_free_assoc_resources(padapter);
-
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- }
- } else {
- goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
- }
- } else {
- rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
- }
- } else {
- rtw_disassoc_cmd(padapter, 0, true);
-
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- rtw_indicate_disconnect(padapter);
-
- rtw_free_assoc_resources(padapter);
-
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- }
- }
- }
-
-handle_tkip_countermeasure:
-
- if (padapter->securitypriv.btkip_countermeasure) {
- cur_time = jiffies;
-
- if (cur_time - padapter->securitypriv.btkip_countermeasure_time > 60 * HZ) {
- padapter->securitypriv.btkip_countermeasure = false;
- padapter->securitypriv.btkip_countermeasure_time = 0;
- } else {
- status = _FAIL;
- goto release_mlme_lock;
- }
- }
-
- memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
- pmlmepriv->assoc_by_bssid = false;
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- pmlmepriv->to_join = true;
- else
- status = rtw_do_join(padapter);
-
-release_mlme_lock:
- spin_unlock_bh(&pmlmepriv->lock);
-
-exit:
- return status;
-}
-
-u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
- enum ndis_802_11_network_infra networktype)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
- enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode;
-
- if (*pold_state != networktype) {
- spin_lock_bh(&pmlmepriv->lock);
-
- if (*pold_state == Ndis802_11APMode) {
- /* change to other mode from Ndis802_11APMode */
- cur_network->join_res = -1;
-
-#ifdef CONFIG_88EU_AP_MODE
- stop_ap_mode(padapter);
-#endif
- }
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- *pold_state == Ndis802_11IBSS)
- rtw_disassoc_cmd(padapter, 0, true);
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
- rtw_free_assoc_resources(padapter);
-
- if (*pold_state == Ndis802_11Infrastructure ||
- *pold_state == Ndis802_11IBSS) {
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */
- }
-
- *pold_state = networktype;
-
- _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
-
- switch (networktype) {
- case Ndis802_11IBSS:
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- break;
- case Ndis802_11Infrastructure:
- set_fwstate(pmlmepriv, WIFI_STATION_STATE);
- break;
- case Ndis802_11APMode:
- set_fwstate(pmlmepriv, WIFI_AP_STATE);
-#ifdef CONFIG_88EU_AP_MODE
- start_ap_mode(padapter);
-#endif
- break;
- case Ndis802_11AutoUnknown:
- case Ndis802_11InfrastructureMax:
- break;
- }
- spin_unlock_bh(&pmlmepriv->lock);
- }
-
- return true;
-}
-
-u8 rtw_set_802_11_disassociate(struct adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- spin_lock_bh(&pmlmepriv->lock);
-
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- rtw_disassoc_cmd(padapter, 0, true);
- rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter);
- rtw_pwr_wakeup(padapter);
- }
-
- spin_unlock_bh(&pmlmepriv->lock);
-
- return true;
-}
-
-u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 res = true;
-
- if (!padapter) {
- res = false;
- goto exit;
- }
- if (!padapter->hw_init_completed) {
- res = false;
- goto exit;
- }
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
- pmlmepriv->LinkDetectInfo.bBusyTraffic) {
- /* Scan or linking is in progress, do nothing. */
- res = true;
- } else {
- if (rtw_is_scan_deny(padapter)) {
- indicate_wx_scan_complete_event(padapter);
- return _SUCCESS;
- }
-
- spin_lock_bh(&pmlmepriv->lock);
-
- res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
-
- spin_unlock_bh(&pmlmepriv->lock);
- }
-exit:
- return res;
-}
-
-u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode)
-{
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- int res;
- u8 ret;
-
- psecuritypriv->ndisauthtype = authmode;
-
- if (psecuritypriv->ndisauthtype > 3)
- psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
-
- res = rtw_set_auth(padapter, psecuritypriv);
-
- if (res == _SUCCESS)
- ret = true;
- else
- ret = false;
-
- return ret;
-}
-
-u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
-{
- int keyid, res;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- u8 ret = _SUCCESS;
-
- keyid = wep->KeyIndex & 0x3fffffff;
-
- if (keyid >= 4) {
- ret = false;
- goto exit;
- }
-
- switch (wep->KeyLength) {
- case 5:
- psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
- break;
- case 13:
- psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
- break;
- default:
- psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
- break;
- }
-
- memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0],
- &wep->KeyMaterial, wep->KeyLength);
-
- psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
-
- psecuritypriv->dot11PrivacyKeyIndex = keyid;
-
- res = rtw_set_key(padapter, psecuritypriv, keyid, 1);
-
- if (res == _FAIL)
- ret = false;
-exit:
- return ret;
-}
-
-/* Return 0 or 100Kbps */
-u16 rtw_get_cur_max_rate(struct adapter *adapter)
-{
- int i = 0;
- u8 *p;
- u16 rate = 0, max_rate = 0;
- struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct registry_priv *pregistrypriv = &adapter->registrypriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
- u32 ht_ielen = 0;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
- !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
- return 0;
-
- if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N | WIRELESS_11_5N)) {
- p = rtw_get_ie(&pcur_bss->ies[12], WLAN_EID_HT_CAPABILITY,
- &ht_ielen, pcur_bss->ie_length - 12);
- if (p && ht_ielen > 0) {
- /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */
- bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0;
-
- short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
- short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
-
- max_rate = rtw_mcs_rate(
- RF_1T1R,
- bw_40MHz & pregistrypriv->cbw40_enable,
- short_GI_20,
- short_GI_40,
- pmlmeinfo->HT_caps.mcs.rx_mask
- );
- }
- } else {
- while (pcur_bss->SupportedRates[i] != 0 &&
- pcur_bss->SupportedRates[i] != 0xFF) {
- rate = pcur_bss->SupportedRates[i] & 0x7F;
- if (rate > max_rate)
- max_rate = rate;
- i++;
- }
-
- max_rate *= 5;
- }
-
- return max_rate;
-}
-
-/* Return _SUCCESS or _FAIL */
-int rtw_set_country(struct adapter *adapter, const char *country_code)
-{
- int i;
- int channel_plan = RT_CHANNEL_DOMAIN_WORLD_WIDE_5G;
-
- for (i = 0; i < ARRAY_SIZE(channel_table); i++) {
- if (strcmp(channel_table[i].name, country_code) == 0) {
- channel_plan = channel_table[i].channel_plan;
- break;
- }
- }
-
- return rtw_set_chplan_cmd(adapter, channel_plan, 1);
-}
diff --git a/drivers/staging/rtl8188eu/core/rtw_iol.c b/drivers/staging/rtl8188eu/core/rtw_iol.c
deleted file mode 100644
index fc3c66201e59..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_iol.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <rtw_iol.h>
-
-bool rtw_iol_applied(struct adapter *adapter)
-{
- if (adapter->registrypriv.fw_iol == 1)
- return true;
-
- if (adapter->registrypriv.fw_iol == 2 &&
- !adapter_to_dvobj(adapter)->ishighspeed)
- return true;
- return false;
-}
diff --git a/drivers/staging/rtl8188eu/core/rtw_led.c b/drivers/staging/rtl8188eu/core/rtw_led.c
deleted file mode 100644
index be868f386204..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_led.c
+++ /dev/null
@@ -1,460 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <drv_types.h>
-#include "rtw_led.h"
-
-/* */
-/* Description: */
-/* Callback function of LED BlinkTimer, */
-/* it just schedules to corresponding BlinkWorkItem/led_blink_hdl */
-/* */
-static void BlinkTimerCallback(struct timer_list *t)
-{
- struct LED_871x *pLed = from_timer(pLed, t, BlinkTimer);
- struct adapter *padapter = pLed->padapter;
-
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
- return;
-
- schedule_work(&pLed->BlinkWorkItem);
-}
-
-/* */
-/* Description: */
-/* Callback function of LED BlinkWorkItem. */
-/* */
-void BlinkWorkItemCallback(struct work_struct *work)
-{
- struct LED_871x *pLed = container_of(work, struct LED_871x,
- BlinkWorkItem);
-
- blink_handler(pLed);
-}
-
-/* */
-/* Description: */
-/* Reset status of LED_871x object. */
-/* */
-void ResetLedStatus(struct LED_871x *pLed)
-{
- pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */
- pLed->led_on = false; /* true if LED is ON, false if LED is OFF. */
-
- pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */
- pLed->bLedWPSBlinkInProgress = false;
-
- pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */
- pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
-
- pLed->bLedNoLinkBlinkInProgress = false;
- pLed->bLedLinkBlinkInProgress = false;
- pLed->bLedScanBlinkInProgress = false;
-}
-
-/*Description: */
-/* Initialize an LED_871x object. */
-void InitLed871x(struct adapter *padapter, struct LED_871x *pLed)
-{
- pLed->padapter = padapter;
-
- ResetLedStatus(pLed);
-
- timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0);
-
- INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
-}
-
-/* */
-/* Description: */
-/* DeInitialize an LED_871x object. */
-/* */
-void DeInitLed871x(struct LED_871x *pLed)
-{
- cancel_work_sync(&pLed->BlinkWorkItem);
- del_timer_sync(&pLed->BlinkTimer);
- ResetLedStatus(pLed);
-}
-
-/* */
-/* Description: */
-/* Implementation of LED blinking behavior. */
-/* It toggle off LED and schedule corresponding timer if necessary. */
-/* */
-
-static void SwLedBlink1(struct LED_871x *pLed)
-{
- struct adapter *padapter = pLed->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == RTW_LED_ON)
- sw_led_on(padapter, pLed);
- else
- sw_led_off(padapter, pLed);
-
- if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
- sw_led_off(padapter, pLed);
- ResetLedStatus(pLed);
- return;
- }
-
- switch (pLed->CurrLedState) {
- case LED_BLINK_SLOWLY:
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_BLINK_NORMAL:
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- break;
- case LED_BLINK_SCAN:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_TXRX:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
- case LED_BLINK_WPS_STOP: /* WPS success */
- if (pLed->BlinkingLedState != RTW_LED_ON) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
-
- pLed->bLedWPSBlinkInProgress = false;
- } else {
- pLed->BlinkingLedState = RTW_LED_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- }
- break;
- default:
- break;
- }
-}
-
- /* ALPHA, added by chiyoko, 20090106 */
-static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct LED_871x *pLed = &ledpriv->sw_led;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- switch (LedAction) {
- case LED_CTL_POWER_ON:
- case LED_CTL_START_TO_LINK:
- case LED_CTL_NO_LINK:
- if (pLed->bLedNoLinkBlinkInProgress)
- break;
- if (pLed->CurrLedState == LED_BLINK_SCAN ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_CTL_LINK:
- if (pLed->bLedLinkBlinkInProgress)
- break;
- if (pLed->CurrLedState == LED_BLINK_SCAN ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- break;
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->LinkDetectInfo.bBusyTraffic &&
- check_fwstate(pmlmepriv, _FW_LINKED))
- break;
- if (pLed->bLedScanBlinkInProgress)
- break;
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SCAN;
- pLed->BlinkTimes = 24;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (pLed->bLedBlinkInProgress)
- break;
- if (pLed->CurrLedState == LED_BLINK_SCAN ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_TXRX;
- pLed->BlinkTimes = 2;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- break;
- case LED_CTL_START_WPS: /* wait until xinpin finish */
- case LED_CTL_START_WPS_BOTTON:
- if (pLed->bLedWPSBlinkInProgress)
- break;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
- case LED_CTL_STOP_WPS:
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress)
- del_timer_sync(&pLed->BlinkTimer);
- else
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS_STOP;
- if (pLed->led_on) {
- pLed->BlinkingLedState = RTW_LED_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- } else {
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_STOP_WPS_FAIL:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->led_on)
- pLed->BlinkingLedState = RTW_LED_OFF;
- else
- pLed->BlinkingLedState = RTW_LED_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = RTW_LED_OFF;
- pLed->BlinkingLedState = RTW_LED_OFF;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- sw_led_off(padapter, pLed);
- break;
- default:
- break;
- }
-}
-
-void blink_handler(struct LED_871x *pLed)
-{
- struct adapter *padapter = pLed->padapter;
-
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
- return;
-
- SwLedBlink1(pLed);
-}
-
-void led_control_8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction)
-{
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
- !padapter->hw_init_completed)
- return;
-
- if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
- padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
- (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
- LedAction == LED_CTL_SITE_SURVEY ||
- LedAction == LED_CTL_LINK ||
- LedAction == LED_CTL_NO_LINK ||
- LedAction == LED_CTL_POWER_ON))
- return;
-
- SwLedControlMode1(padapter, LedAction);
-}
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
deleted file mode 100644
index 25653ebfaafd..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ /dev/null
@@ -1,5172 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTW_MLME_EXT_C_
-
-#include <linux/ieee80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <wifi.h>
-#include <rtw_mlme_ext.h>
-#include <wlan_bssdef.h>
-#include <mlme_osdep.h>
-#include <recv_osdep.h>
-
-static u8 null_addr[ETH_ALEN] = {};
-
-/* OUI definitions for the vendor specific IE */
-const u8 RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
-const u8 WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
-static const u8 WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
-static const u8 P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
-
-static const u8 WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
-
-const u8 WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
-const u8 RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
-
-/* MCS rate definitions */
-const u8 MCS_rate_1R[16] = {
- 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* ChannelPlan definitions */
-static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
- {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
- {{}, 0}, /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
-};
-
-static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
- /* 0x00 ~ 0x1F , Old Define ===== */
- {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
- {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
- {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
- {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
- {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
- {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
- {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
- {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
- {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
- {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
- {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
- {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
- {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
- {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
- {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
- {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
- {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
- {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
- {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
- {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
- {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
- {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
- {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
- {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
- {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
- {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
- {0x00}, /* 0x1A, */
- {0x00}, /* 0x1B, */
- {0x00}, /* 0x1C, */
- {0x00}, /* 0x1D, */
- {0x00}, /* 0x1E, */
- {0x05}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
- /* 0x20 ~ 0x7F , New Define ===== */
- {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
- {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
- {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
- {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
- {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
- {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
- {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
- {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
- {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
- {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
- {0x00}, /* 0x2A, */
- {0x00}, /* 0x2B, */
- {0x00}, /* 0x2C, */
- {0x00}, /* 0x2D, */
- {0x00}, /* 0x2E, */
- {0x00}, /* 0x2F, */
- {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
- {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
- {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
- {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
- {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
- {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
- {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
- {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
- {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
- {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
- {0x00}, /* 0x3A, */
- {0x00}, /* 0x3B, */
- {0x00}, /* 0x3C, */
- {0x00}, /* 0x3D, */
- {0x00}, /* 0x3E, */
- {0x00}, /* 0x3F, */
- {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
- {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
-};
-
-static const struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {
- 0x03
-}; /* use the combination for max channel numbers */
-
-/*
- * Search the @param channel_num in given @param channel_set
- * @ch_set: the given channel set
- * @ch: the given channel number
- *
- * return the index of channel_num in channel_set, -1 if not found
- */
-int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
-{
- int i;
-
- for (i = 0; ch_set[i].ChannelNum != 0; i++) {
- if (ch == ch_set[i].ChannelNum)
- break;
- }
-
- if (i >= ch_set[i].ChannelNum)
- return -1;
- return i;
-}
-
-struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
-{
- struct xmit_frame *pmgntframe;
- struct xmit_buf *pxmitbuf;
-
- pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
- if (!pmgntframe)
- return NULL;
-
- pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
- if (!pxmitbuf) {
- rtw_free_xmitframe(pxmitpriv, pmgntframe);
- return NULL;
- }
- pmgntframe->frame_tag = MGNT_FRAMETAG;
- pmgntframe->pxmitbuf = pxmitbuf;
- pmgntframe->buf_addr = pxmitbuf->pbuf;
- pxmitbuf->priv_data = pmgntframe;
- return pmgntframe;
-}
-
-/****************************************************************************
-
-Following are some TX functions for WiFi MLME
-
-*****************************************************************************/
-
-void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- pmlmeext->tx_rate = rate;
-}
-
-void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
-
- pattrib->hdrlen = 24;
- pattrib->nr_frags = 1;
- pattrib->priority = 7;
- pattrib->mac_id = 0;
- pattrib->qsel = 0x12;
-
- pattrib->pktlen = 0;
-
- if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
- pattrib->raid = 6;/* b mode */
- else
- pattrib->raid = 5;/* a/g mode */
-
- pattrib->encrypt = _NO_PRIVACY_;
- pattrib->bswenc = false;
-
- pattrib->qos_en = false;
- pattrib->ht_en = false;
- pattrib->bwmode = HT_CHANNEL_WIDTH_20;
- pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- pattrib->sgi = false;
-
- pattrib->seqnum = pmlmeext->mgnt_seq;
-
- pattrib->retry_ctrl = true;
-}
-
-static void dump_mgntframe(struct adapter *padapter,
- struct xmit_frame *pmgntframe)
-{
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
- return;
-
- rtw_hal_mgnt_xmit(padapter, pmgntframe);
-}
-
-static s32 dump_mgntframe_and_wait(struct adapter *padapter,
- struct xmit_frame *pmgntframe,
- int timeout_ms)
-{
- s32 ret = _FAIL;
- struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
- struct submit_ctx sctx;
-
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
- return ret;
-
- rtw_sctx_init(&sctx, timeout_ms);
- pxmitbuf->sctx = &sctx;
-
- ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
-
- if (ret == _SUCCESS)
- ret = rtw_sctx_wait(&sctx);
-
- return ret;
-}
-
-static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter,
- struct xmit_frame *pmgntframe)
-{
- s32 ret = _FAIL;
- u32 timeout_ms = 500;/* 500ms */
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
- return -1;
-
- if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex))
- return _FAIL;
- pxmitpriv->ack_tx = true;
-
- pmgntframe->ack_report = 1;
- if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
- ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
-
- pxmitpriv->ack_tx = false;
- mutex_unlock(&pxmitpriv->ack_tx_mutex);
-
- return ret;
-}
-
-static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
-{
- u8 *ssid_ie;
- uint ssid_len_ori;
- int len_diff = 0;
-
- ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
-
- if (ssid_ie && ssid_len_ori > 0) {
- switch (hidden_ssid_mode) {
- case 1: {
- u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
- u32 remain_len = 0;
-
- remain_len = ies_len - (next_ie - ies);
-
- ssid_ie[1] = 0;
- memcpy(ssid_ie + 2, next_ie, remain_len);
- len_diff -= ssid_len_ori;
-
- break;
- }
- case 2:
- memset(&ssid_ie[2], 0, ssid_len_ori);
- break;
- default:
- break;
- }
- }
-
- return len_diff;
-}
-
-static void issue_beacon(struct adapter *padapter, int timeout_ms)
-{
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- unsigned int rate_len;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- return;
-#if defined(CONFIG_88EU_AP_MODE)
- spin_lock_bh(&pmlmepriv->bcn_update_lock);
-#endif
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- pattrib->qsel = 0x10;
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- eth_broadcast_addr(pwlanhdr->addr1);
- ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
-
- SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
- /* pmlmeext->mgnt_seq++; */
- SetFrameSubType(pframe, IEEE80211_STYPE_BEACON);
-
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
- int len_diff;
- u8 *wps_ie;
- uint wps_ielen;
- u8 sr = 0;
-
- memcpy(pframe, cur_network->ies, cur_network->ie_length);
- len_diff = update_hidden_ssid(
- pframe + _BEACON_IE_OFFSET_
- , cur_network->ie_length - _BEACON_IE_OFFSET_
- , pmlmeinfo->hidden_ssid_mode
- );
- pframe += (cur_network->ie_length + len_diff);
- pattrib->pktlen += (cur_network->ie_length + len_diff);
- wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_,
- pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen);
- if (wps_ie && wps_ielen > 0)
- rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
- if (sr != 0)
- set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
- else
- _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
-
- goto _issue_bcn;
- }
-
- /* below for ad-hoc mode */
-
- /* timestamp will be inserted by hardware */
- pframe += 8;
- pattrib->pktlen += 8;
-
- /* beacon interval: 2 bytes */
-
- memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
-
- pframe += 2;
- pattrib->pktlen += 2;
-
- /* capability info: 2 bytes */
-
- memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
-
- pframe += 2;
- pattrib->pktlen += 2;
-
- /* SSID */
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
-
- /* supported rates... */
- rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
-
- /* DS parameter set */
- pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
-
- {
- u8 erpinfo = 0;
- u32 ATIMWindow;
- /* IBSS Parameter Set... */
- ATIMWindow = 0;
- pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
-
- /* ERP IE */
- pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen);
- }
-
- /* EXTERNDED SUPPORTED RATE */
- if (rate_len > 8)
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
- /* todo:HT for adhoc */
-_issue_bcn:
-
-#if defined(CONFIG_88EU_AP_MODE)
- pmlmepriv->update_bcn = false;
-
- spin_unlock_bh(&pmlmepriv->bcn_update_lock);
-#endif
-
- if ((pattrib->pktlen + TXDESC_SIZE) > 512)
- return;
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- if (timeout_ms > 0)
- dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
- else
- dump_mgntframe(padapter, pmgntframe);
-}
-
-static void issue_probersp(struct adapter *padapter, unsigned char *da)
-{
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- unsigned char *mac, *bssid;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-#if defined(CONFIG_88EU_AP_MODE)
- u8 *pwps_ie;
- uint wps_ielen;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-#endif
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
- unsigned int rate_len;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- return;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- mac = myid(&padapter->eeprompriv);
- bssid = cur_network->MacAddress;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
- ether_addr_copy(pwlanhdr->addr1, da);
- ether_addr_copy(pwlanhdr->addr2, mac);
- ether_addr_copy(pwlanhdr->addr3, bssid);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(fctrl, IEEE80211_STYPE_PROBE_RESP);
-
- pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = pattrib->hdrlen;
- pframe += pattrib->hdrlen;
-
- if (cur_network->ie_length > MAX_IE_SZ)
- return;
-
-#if defined(CONFIG_88EU_AP_MODE)
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
- pwps_ie = rtw_get_wps_ie(cur_network->ies + _FIXED_IE_LENGTH_, cur_network->ie_length - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
-
- /* inerset & update wps_probe_resp_ie */
- if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
- uint wps_offset, remainder_ielen;
- u8 *premainder_ie;
-
- wps_offset = (uint)(pwps_ie - cur_network->ies);
-
- premainder_ie = pwps_ie + wps_ielen;
-
- remainder_ielen = cur_network->ie_length - wps_offset - wps_ielen;
-
- memcpy(pframe, cur_network->ies, wps_offset);
- pframe += wps_offset;
- pattrib->pktlen += wps_offset;
-
- wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
- if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) {
- memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2);
- pframe += wps_ielen + 2;
- pattrib->pktlen += wps_ielen + 2;
- }
-
- if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
- memcpy(pframe, premainder_ie, remainder_ielen);
- pframe += remainder_ielen;
- pattrib->pktlen += remainder_ielen;
- }
- } else {
- memcpy(pframe, cur_network->ies, cur_network->ie_length);
- pframe += cur_network->ie_length;
- pattrib->pktlen += cur_network->ie_length;
- }
- } else
-#endif
- {
- /* timestamp will be inserted by hardware */
- pframe += 8;
- pattrib->pktlen += 8;
-
- /* beacon interval: 2 bytes */
-
- memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
-
- pframe += 2;
- pattrib->pktlen += 2;
-
- /* capability info: 2 bytes */
-
- memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
-
- pframe += 2;
- pattrib->pktlen += 2;
-
- /* below for ad-hoc mode */
-
- /* SSID */
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
-
- /* supported rates... */
- rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
-
- /* DS parameter set */
- pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
- u8 erpinfo = 0;
- u32 ATIMWindow;
- /* IBSS Parameter Set... */
- /* ATIMWindow = cur->Configuration.ATIMWindow; */
- ATIMWindow = 0;
- pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
-
- /* ERP IE */
- pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen);
- }
-
- /* EXTERNDED SUPPORTED RATE */
- if (rate_len > 8)
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
- /* todo:HT for adhoc */
- }
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- dump_mgntframe(padapter, pmgntframe);
-}
-
-static int issue_probereq(struct adapter *padapter,
- struct ndis_802_11_ssid *pssid, u8 *da,
- bool wait_ack)
-{
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- unsigned char *mac;
- unsigned char bssrate[NumRates];
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- int bssrate_len = 0;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- goto exit;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- mac = myid(&padapter->eeprompriv);
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- if (da) {
- /* unicast probe request frame */
- ether_addr_copy(pwlanhdr->addr1, da);
- ether_addr_copy(pwlanhdr->addr3, da);
- } else {
- /* broadcast probe request frame */
- eth_broadcast_addr(pwlanhdr->addr1);
- eth_broadcast_addr(pwlanhdr->addr3);
- }
-
- ether_addr_copy(pwlanhdr->addr2, mac);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(pframe, IEEE80211_STYPE_PROBE_REQ);
-
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
- if (pssid)
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->ssid_length, pssid->ssid, &pattrib->pktlen);
- else
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, 0, NULL, &pattrib->pktlen);
-
- get_rate_set(padapter, bssrate, &bssrate_len);
-
- if (bssrate_len > 8) {
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &pattrib->pktlen);
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
- } else {
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &pattrib->pktlen);
- }
-
- /* add wps_ie for wps2.0 */
- if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
- memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
- pframe += pmlmepriv->wps_probe_req_ie_len;
- pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
- }
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- if (wait_ack) {
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- } else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
-
-exit:
- return ret;
-}
-
-static int issue_probereq_ex(struct adapter *padapter,
- struct ndis_802_11_ssid *pssid, u8 *da,
- int try_cnt, int wait_ms)
-{
- int ret;
- int i = 0;
-
- do {
- ret = issue_probereq(padapter, pssid, da, wait_ms > 0);
-
- i++;
-
- if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
- break;
-
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- msleep(wait_ms);
-
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-
- if (ret != _FAIL) {
- ret = _SUCCESS;
- goto exit;
- }
-exit:
- return ret;
-}
-
-/* if psta == NULL, indicate we are station(client) now... */
-static void issue_auth(struct adapter *padapter, struct sta_info *psta,
- unsigned short status)
-{
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- unsigned int val32;
- u16 val16;
-#ifdef CONFIG_88EU_AP_MODE
- __le16 le_val16;
-#endif
- int use_shared_key = 0;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- return;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(pframe, IEEE80211_STYPE_AUTH);
-
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
- if (psta) {/* for AP mode */
-#ifdef CONFIG_88EU_AP_MODE
-
- ether_addr_copy(pwlanhdr->addr1, psta->hwaddr);
- ether_addr_copy(pwlanhdr->addr2,
- myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3,
- myid(&padapter->eeprompriv));
-
- /* setting auth algo number */
- val16 = (u16)psta->authalg;
-
- if (status != WLAN_STATUS_SUCCESS)
- val16 = 0;
-
- if (val16) {
- le_val16 = cpu_to_le16(val16);
- use_shared_key = 1;
- } else {
- le_val16 = 0;
- }
-
- pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, &le_val16,
- &pattrib->pktlen);
-
- /* setting auth seq number */
- val16 = (u16)psta->auth_seq;
- le_val16 = cpu_to_le16(val16);
- pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, &le_val16,
- &pattrib->pktlen);
-
- /* setting status code... */
- val16 = status;
- le_val16 = cpu_to_le16(val16);
- pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_,
- &le_val16, &pattrib->pktlen);
-
- /* added challenging text... */
- if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
- pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, psta->chg_txt, &pattrib->pktlen);
-#endif
- } else {
- __le32 le_tmp32;
- __le16 le_tmp16;
-
- ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
- ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
-
- /* setting auth algo number */
- val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */
- if (val16)
- use_shared_key = 1;
-
- /* setting IV for auth seq #3 */
- if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
- val32 = (pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30);
- le_tmp32 = cpu_to_le32(val32);
- pframe = rtw_set_fixed_ie(pframe, 4, &le_tmp32,
- &pattrib->pktlen);
-
- pattrib->iv_len = 4;
- }
-
- le_tmp16 = cpu_to_le16(val16);
- pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, &le_tmp16,
- &pattrib->pktlen);
-
- /* setting auth seq number */
- val16 = pmlmeinfo->auth_seq;
- le_tmp16 = cpu_to_le16(val16);
- pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, &le_tmp16,
- &pattrib->pktlen);
-
- /* setting status code... */
- le_tmp16 = cpu_to_le16(status);
- pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, &le_tmp16,
- &pattrib->pktlen);
-
- /* then checking to see if sending challenging text... */
- if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
- pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, pmlmeinfo->chg_txt, &pattrib->pktlen);
-
- SetPrivacy(fctrl);
-
- pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
-
- pattrib->encrypt = _WEP40_;
-
- pattrib->icv_len = 4;
-
- pattrib->pktlen += pattrib->icv_len;
- }
- }
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- rtw_wep_encrypt(padapter, pmgntframe);
- dump_mgntframe(padapter, pmgntframe);
-}
-
-#ifdef CONFIG_88EU_AP_MODE
-static void issue_asocrsp(struct adapter *padapter, unsigned short status,
- struct sta_info *pstat, int pkt_type)
-{
- struct xmit_frame *pmgntframe;
- struct ieee80211_hdr *pwlanhdr;
- struct pkt_attrib *pattrib;
- unsigned char *pbuf, *pframe;
- unsigned short val;
- __le16 *fctrl;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- u8 *ie = pnetwork->ies;
- __le16 lestatus, leval;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- return;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- ether_addr_copy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr);
- ether_addr_copy((void *)GetAddr2Ptr(pwlanhdr),
- myid(&padapter->eeprompriv));
- ether_addr_copy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- if ((pkt_type == IEEE80211_STYPE_ASSOC_RESP) || (pkt_type == IEEE80211_STYPE_REASSOC_RESP))
- SetFrameSubType(pwlanhdr, pkt_type);
- else
- return;
-
- pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen += pattrib->hdrlen;
- pframe += pattrib->hdrlen;
-
- /* capability */
- val = *(unsigned short *)rtw_get_capability_from_ie(ie);
-
- pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, &val, &pattrib->pktlen);
-
- lestatus = cpu_to_le16(status);
- pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, &lestatus,
- &pattrib->pktlen);
-
- leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
- pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, &leval, &pattrib->pktlen);
-
- if (pstat->bssratelen <= 8) {
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, pstat->bssratelen, pstat->bssrateset, &pattrib->pktlen);
- } else {
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, pstat->bssrateset, &pattrib->pktlen);
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, pstat->bssratelen - 8, pstat->bssrateset + 8, &pattrib->pktlen);
- }
-
- if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
- uint ie_len = 0;
-
- /* FILL HT CAP INFO IE */
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
- if (pbuf && ie_len > 0) {
- memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- }
-
- /* FILL HT ADD INFO IE */
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
- if (pbuf && ie_len > 0) {
- memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- }
- }
-
- /* FILL WMM IE */
- if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
- uint ie_len = 0;
- unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
-
- for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
- pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
- if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
- memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- break;
- }
-
- if (!pbuf || ie_len == 0)
- break;
- }
- }
-
- if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
- pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &pattrib->pktlen);
-
- /* add WPS IE ie for wps 2.0 */
- if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
- memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
-
- pframe += pmlmepriv->wps_assoc_resp_ie_len;
- pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
- }
-
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
-}
-#endif /* CONFIG_88EU_AP_MODE */
-
-static void issue_assocreq(struct adapter *padapter)
-{
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe, *p;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- unsigned int i, j, ie_len, index = 0;
- unsigned char bssrate[NumRates], sta_bssrate[NumRates];
- struct ndis_802_11_var_ie *pIE;
- struct registry_priv *pregpriv = &padapter->registrypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- int bssrate_len = 0, sta_bssrate_len = 0;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- goto exit;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
- ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
- ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(pframe, IEEE80211_STYPE_ASSOC_REQ);
-
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
- /* caps */
-
- memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.ies), 2);
-
- pframe += 2;
- pattrib->pktlen += 2;
-
- /* listen interval */
- /* todo: listen interval for power saving */
- put_unaligned_le16(3, pframe);
- pframe += 2;
- pattrib->pktlen += 2;
-
- /* SSID */
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pmlmeinfo->network.ssid.ssid_length, pmlmeinfo->network.ssid.ssid, &pattrib->pktlen);
-
- /* supported rate & extended supported rate */
-
- /* Check if the AP's supported rates are also supported by STA. */
- get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
-
- if (pmlmeext->cur_channel == 14)/* for JAPAN, channel 14 can only uses B Mode(CCK) */
- sta_bssrate_len = 4;
-
- for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
- if (pmlmeinfo->network.SupportedRates[i] == 0)
- break;
- }
-
- for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
- if (pmlmeinfo->network.SupportedRates[i] == 0)
- break;
-
- /* Check if the AP's supported rates are also supported by STA. */
- for (j = 0; j < sta_bssrate_len; j++) {
- /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
- if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)
- == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
- break;
- }
-
- if (j != sta_bssrate_len)
- /* the rate is supported by STA */
- bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
- }
-
- bssrate_len = index;
-
- if (bssrate_len == 0) {
- rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
- rtw_free_xmitframe(pxmitpriv, pmgntframe);
- goto exit; /* don't connect to AP if no joint supported rate */
- }
-
- if (bssrate_len > 8) {
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &pattrib->pktlen);
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
- } else {
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &pattrib->pktlen);
- }
-
- /* RSN */
- p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), WLAN_EID_RSN, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie)));
- if (p)
- pframe = rtw_set_ie(pframe, WLAN_EID_RSN, ie_len, p + 2, &pattrib->pktlen);
-
- /* HT caps */
- if (padapter->mlmepriv.htpriv.ht_option) {
- p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), WLAN_EID_HT_CAPABILITY, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie)));
- if (p && !is_ap_in_tkip(padapter)) {
- memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct ieee80211_ht_cap));
-
- /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
- if (pregpriv->cbw40_enable == 0)
- pmlmeinfo->HT_caps.cap_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
- else
- pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(BIT(1));
-
- /* todo: disable SM power save mode */
- pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x000c);
-
- if (pregpriv->rx_stbc)
- pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
- memcpy((u8 *)&pmlmeinfo->HT_caps.mcs, MCS_rate_1R, 16);
- pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, ie_len, (u8 *)(&pmlmeinfo->HT_caps), &pattrib->pktlen);
- }
- }
-
- /* vendor specific IE, such as WPA, WMM, WPS */
- for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.ie_length; i += (pIE->Length + 2)) {
- pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.ies + i);
-
- switch (pIE->ElementID) {
- case WLAN_EID_VENDOR_SPECIFIC:
- if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
- (!memcmp(pIE->data, WMM_OUI, 4)) ||
- (!memcmp(pIE->data, WPS_OUI, 4))) {
- if (!padapter->registrypriv.wifi_spec) {
- /* Commented by Kurt 20110629 */
- /* In some older APs, WPS handshake */
- /* would be fail if we append vender extensions information to AP */
- if (!memcmp(pIE->data, WPS_OUI, 4))
- pIE->Length = 14;
- }
- pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, pIE->Length, pIE->data, &pattrib->pktlen);
- }
- break;
- default:
- break;
- }
- }
-
- if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
- pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &pattrib->pktlen);
-
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
-
- ret = _SUCCESS;
-
-exit:
- if (ret == _SUCCESS)
- rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
- else
- rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
-}
-
-/* when wait_ack is true, this function should be called at process context */
-static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
- unsigned int power_mode, bool wait_ack)
-{
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- struct xmit_priv *pxmitpriv;
- struct mlme_ext_priv *pmlmeext;
- struct mlme_ext_info *pmlmeinfo;
- struct wlan_bssid_ex *pnetwork;
-
- if (!padapter)
- goto exit;
-
- pxmitpriv = &padapter->xmitpriv;
- pmlmeext = &padapter->mlmeextpriv;
- pmlmeinfo = &pmlmeext->mlmext_info;
- pnetwork = &pmlmeinfo->network;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- goto exit;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- pattrib->retry_ctrl = false;
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
- SetFrDs(fctrl);
- else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
- SetToDs(fctrl);
-
- if (power_mode)
- SetPwrMgt(fctrl);
-
- ether_addr_copy(pwlanhdr->addr1, da);
- ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(pframe, IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC);
-
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- if (wait_ack) {
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- } else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
-
-exit:
- return ret;
-}
-
-/* when wait_ms > 0 , this function should be called at process context */
-/* da == NULL for station mode */
-int issue_nulldata(struct adapter *padapter, unsigned char *da,
- unsigned int power_mode, int try_cnt, int wait_ms)
-{
- int ret;
- int i = 0;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- /* da == NULL, assume it's null data for sta to ap*/
- if (!da)
- da = pnetwork->MacAddress;
-
- do {
- ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
-
- i++;
-
- if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
- break;
-
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- msleep(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-
- if (ret != _FAIL) {
- ret = _SUCCESS;
- goto exit;
- }
-exit:
- return ret;
-}
-
-/* when wait_ack is true, this function should be called at process context */
-static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
- u16 tid, bool wait_ack)
-{
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- unsigned short *qc;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- goto exit;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
-
- pattrib->hdrlen += 2;
- pattrib->qos_en = true;
- pattrib->eosp = 1;
- pattrib->ack_policy = 0;
- pattrib->mdata = 0;
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
- SetFrDs(fctrl);
- else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
- SetToDs(fctrl);
-
- if (pattrib->mdata)
- SetMData(fctrl);
-
- qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
-
- SetPriority(qc, tid);
-
- SetEOSP(qc, pattrib->eosp);
-
- SetAckpolicy(qc, pattrib->ack_policy);
-
- ether_addr_copy(pwlanhdr->addr1, da);
- ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(pframe, IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
-
- pframe += sizeof(struct ieee80211_qos_hdr);
- pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- if (wait_ack) {
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- } else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
-
-exit:
- return ret;
-}
-
-/* when wait_ms > 0 , this function should be called at process context */
-/* da == NULL for station mode */
-int issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
- u16 tid, int try_cnt, int wait_ms)
-{
- int ret;
- int i = 0;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- /* da == NULL, assume it's null data for sta to ap*/
- if (!da)
- da = pnetwork->MacAddress;
-
- do {
- ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
-
- i++;
-
- if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
- break;
-
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- msleep(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-
- if (ret != _FAIL) {
- ret = _SUCCESS;
- goto exit;
- }
-exit:
- return ret;
-}
-
-static int _issue_deauth(struct adapter *padapter, unsigned char *da,
- unsigned short reason, bool wait_ack)
-{
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- int ret = _FAIL;
- __le16 le_tmp;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- goto exit;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- pattrib->retry_ctrl = false;
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- ether_addr_copy(pwlanhdr->addr1, da);
- ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(pframe, IEEE80211_STYPE_DEAUTH);
-
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
- le_tmp = cpu_to_le16(reason);
- pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, &le_tmp,
- &pattrib->pktlen);
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- if (wait_ack) {
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- } else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
-
-exit:
- return ret;
-}
-
-int issue_deauth(struct adapter *padapter, unsigned char *da,
- unsigned short reason)
-{
- return _issue_deauth(padapter, da, reason, false);
-}
-
-static int issue_deauth_ex(struct adapter *padapter, u8 *da,
- unsigned short reason, int try_cnt,
- int wait_ms)
-{
- int ret;
- int i = 0;
-
- do {
- ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
-
- i++;
-
- if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
- break;
-
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- mdelay(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-
- if (ret != _FAIL) {
- ret = _SUCCESS;
- goto exit;
- }
-exit:
- return ret;
-}
-
-static void issue_action_BA(struct adapter *padapter, unsigned char *raddr,
- unsigned char action, unsigned short status)
-{
- u8 category = RTW_WLAN_CATEGORY_BACK;
- u16 start_seq;
- u16 BA_para_set;
- u16 reason_code;
- u16 BA_timeout_value;
- __le16 le_tmp;
- u16 BA_starting_seqctrl = 0;
- enum ht_cap_ampdu_factor max_rx_ampdu_factor;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- u8 *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct registry_priv *pregpriv = &padapter->registrypriv;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- return;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- ether_addr_copy(pwlanhdr->addr1, raddr);
- ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(pframe, IEEE80211_STYPE_ACTION);
-
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
- pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
- pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
-
- if (category == 3) {
- switch (action) {
- case 0: /* ADDBA req */
- do {
- pmlmeinfo->dialogToken++;
- } while (pmlmeinfo->dialogToken == 0);
- pframe = rtw_set_fixed_ie(pframe, 1, &pmlmeinfo->dialogToken, &pattrib->pktlen);
-
- BA_para_set = 0x1002 | ((status & 0xf) << 2); /* immediate ack & 64 buffer size */
- le_tmp = cpu_to_le16(BA_para_set);
- pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
- &pattrib->pktlen);
-
- BA_timeout_value = 5000;/* 5ms */
- le_tmp = cpu_to_le16(BA_timeout_value);
- pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
- &pattrib->pktlen);
-
- psta = rtw_get_stainfo(pstapriv, raddr);
- if (psta) {
- start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] & 0xfff) + 1;
-
- psta->BA_starting_seqctrl[status & 0x07] = start_seq;
-
- BA_starting_seqctrl = start_seq << 4;
- }
- le_tmp = cpu_to_le16(BA_starting_seqctrl);
- pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
- &pattrib->pktlen);
- break;
- case 1: /* ADDBA rsp */
- {
- struct ADDBA_request *ADDBA_req = &pmlmeinfo->ADDBA_req;
-
- pframe = rtw_set_fixed_ie(pframe, 1,
- &ADDBA_req->dialog_token,
- &pattrib->pktlen);
- pframe = rtw_set_fixed_ie(pframe, 2, &status,
- &pattrib->pktlen);
-
- BA_para_set = le16_to_cpu(ADDBA_req->BA_para_set) &
- 0x3f;
- rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
- switch (max_rx_ampdu_factor) {
- case MAX_AMPDU_FACTOR_64K:
- BA_para_set |= 0x1000; /* 64 buffer size */
- break;
- case MAX_AMPDU_FACTOR_32K:
- BA_para_set |= 0x0800; /* 32 buffer size */
- break;
- case MAX_AMPDU_FACTOR_16K:
- BA_para_set |= 0x0400; /* 16 buffer size */
- break;
- case MAX_AMPDU_FACTOR_8K:
- BA_para_set |= 0x0200; /* 8 buffer size */
- break;
- default:
- BA_para_set |= 0x1000; /* 64 buffer size */
- break;
- }
-
- if (pregpriv->ampdu_amsdu == 0)/* disabled */
- BA_para_set = BA_para_set & ~BIT(0);
- else if (pregpriv->ampdu_amsdu == 1)/* enabled */
- BA_para_set = BA_para_set | BIT(0);
- le_tmp = cpu_to_le16(BA_para_set);
-
- pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
- &pattrib->pktlen);
- pframe = rtw_set_fixed_ie(pframe, 2,
- &ADDBA_req->BA_timeout_value,
- &pattrib->pktlen);
- break;
- }
- case 2:/* DELBA */
- BA_para_set = (status & 0x1F) << 3;
- le_tmp = cpu_to_le16(BA_para_set);
- pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
- &pattrib->pktlen);
-
- reason_code = 37;/* Requested from peer STA as it does not want to use the mechanism */
- le_tmp = cpu_to_le16(reason_code);
- pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
- &pattrib->pktlen);
- break;
- default:
- break;
- }
- }
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- dump_mgntframe(padapter, pmgntframe);
-}
-
-static void issue_action_BSSCoexistPacket(struct adapter *padapter)
-{
- struct list_head *plist, *phead;
- unsigned char category, action;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct ieee80211_hdr *pwlanhdr;
- __le16 *fctrl;
- struct wlan_network *pnetwork = NULL;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- u8 InfoContent[16] = {0};
- u8 ICS[8][15];
- struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
-
- if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
- return;
-
- if (pmlmeinfo->bwmode_updated)
- return;
-
- category = RTW_WLAN_CATEGORY_PUBLIC;
- action = ACT_PUBLIC_BSSCOEXIST;
-
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (!pmgntframe)
- return;
-
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
-
- memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct ieee80211_hdr *)pframe;
-
- fctrl = &pwlanhdr->frame_control;
- *(fctrl) = 0;
-
- ether_addr_copy(pwlanhdr->addr1, cur_network->MacAddress);
- ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
- ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
-
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- SetFrameSubType(pframe, IEEE80211_STYPE_ACTION);
-
- pframe += sizeof(struct ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
- pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
- pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
-
- /* */
- if (pmlmepriv->num_FortyMHzIntolerant > 0) {
- u8 iedata = 0;
-
- iedata |= BIT(2);/* 20 MHz BSS Width Request */
-
- pframe = rtw_set_ie(pframe, WLAN_EID_BSS_COEX_2040, 1, &iedata, &pattrib->pktlen);
- }
-
- /* */
- memset(ICS, 0, sizeof(ICS));
- if (pmlmepriv->num_sta_no_ht > 0) {
- int i;
-
- spin_lock_bh(&pmlmepriv->scanned_queue.lock);
-
- phead = get_list_head(queue);
- list_for_each(plist, phead) {
- uint len;
- u8 *p;
- struct wlan_bssid_ex *pbss_network;
-
- pnetwork = list_entry(plist, struct wlan_network,
- list);
-
- pbss_network = &pnetwork->network;
-
- p = rtw_get_ie(pbss_network->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->ie_length - _FIXED_IE_LENGTH_);
- if (!p || len == 0) { /* non-HT */
- if (pbss_network->Configuration.DSConfig <= 0)
- continue;
-
- ICS[0][pbss_network->Configuration.DSConfig] = 1;
-
- if (ICS[0][0] == 0)
- ICS[0][0] = 1;
- }
- }
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
- for (i = 0; i < 8; i++) {
- if (ICS[i][0] == 1) {
- int j, k = 0;
-
- InfoContent[k] = i;
- /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
- k++;
-
- for (j = 1; j <= 14; j++) {
- if (ICS[i][j] == 1) {
- if (k < 16) {
- InfoContent[k] = j; /* channel number */
- /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
- k++;
- }
- }
- }
-
- pframe = rtw_set_ie(pframe, WLAN_EID_BSS_INTOLERANT_CHL_REPORT, k, InfoContent, &pattrib->pktlen);
- }
- }
- }
-
- pattrib->last_txcmdsz = pattrib->pktlen;
-
- dump_mgntframe(padapter, pmgntframe);
-}
-
-unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
-{
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct sta_info *psta = NULL;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u16 tid;
-
- if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
- return _SUCCESS;
-
- psta = rtw_get_stainfo(pstapriv, addr);
- if (!psta)
- return _SUCCESS;
-
- if (initiator == 0) { /* recipient */
- for (tid = 0; tid < MAXTID; tid++) {
- if (psta->recvreorder_ctrl[tid].enable) {
- issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
- psta->recvreorder_ctrl[tid].enable = false;
- psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
- }
- }
- } else if (initiator == 1) { /* originator */
- for (tid = 0; tid < MAXTID; tid++) {
- if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
- issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
- psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
- psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
- }
- }
- }
-
- return _SUCCESS;
-}
-
-unsigned int send_beacon(struct adapter *padapter)
-{
- u8 bxmitok = false;
- int issue = 0;
- int poll = 0;
-
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
- do {
- issue_beacon(padapter, 100);
- issue++;
- do {
- yield();
- rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
- poll++;
- } while ((poll % 10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
- } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
-
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
- return _FAIL;
- if (!bxmitok)
- return _FAIL;
-
- return _SUCCESS;
-}
-
-/****************************************************************************
-
-Following are some utility functions for WiFi MLME
-
-*****************************************************************************/
-
-static void site_survey(struct adapter *padapter)
-{
- unsigned char survey_channel = 0, val8;
- enum rt_scan_type ScanType = SCAN_PASSIVE;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u32 initialgain = 0;
- struct rtw_ieee80211_channel *ch;
-
- if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
- ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
- survey_channel = ch->hw_value;
- ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
- }
-
- if (survey_channel != 0) {
- /* PAUSE 4-AC Queue when site_survey */
- /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
- /* val8 |= 0x0f; */
- /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
- if (pmlmeext->sitesurvey_res.channel_idx == 0)
- set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
- else
- SelectChannel(padapter, survey_channel);
-
- if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
- int i;
-
- for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (pmlmeext->sitesurvey_res.ssid[i].ssid_length) {
- /* todo: to issue two probe req??? */
- issue_probereq(padapter,
- &pmlmeext->sitesurvey_res.ssid[i],
- NULL, false);
- /* msleep(SURVEY_TO>>1); */
- issue_probereq(padapter,
- &pmlmeext->sitesurvey_res.ssid[i],
- NULL, false);
- }
- }
-
- if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
- /* todo: to issue two probe req??? */
- issue_probereq(padapter, NULL, NULL, false);
- /* msleep(SURVEY_TO>>1); */
- issue_probereq(padapter, NULL, NULL, false);
- }
-
- if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
- /* todo: to issue two probe req??? */
- issue_probereq(padapter, NULL, NULL, false);
- /* msleep(SURVEY_TO>>1); */
- issue_probereq(padapter, NULL, NULL, false);
- }
- }
-
- set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
- } else {
- /* 20100721:Interrupt scan operation here. */
- /* For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
- /* It compares the scan result and select better one to do connection. */
- if (rtw_hal_antdiv_before_linked(padapter)) {
- pmlmeext->sitesurvey_res.bss_cnt = 0;
- pmlmeext->sitesurvey_res.channel_idx = -1;
- pmlmeext->chan_scan_time = SURVEY_TO / 2;
- set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
- return;
- }
-
- pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
-
- /* switch back to the original channel */
-
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-
- /* flush 4-AC Queue after site_survey */
- /* val8 = 0; */
- /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
-
- /* config MSR */
- Set_MSR(padapter, (pmlmeinfo->state & 0x3));
-
- initialgain = 0xff; /* restore RX GAIN */
- rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
- /* turn on dynamic functions */
- Restore_DM_Func_Flag(padapter);
- /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
-
- if (is_client_associated_to_ap(padapter))
- issue_nulldata(padapter, NULL, 0, 3, 500);
-
- val8 = 0; /* survey done */
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-
- report_surveydone_event(padapter);
-
- pmlmeext->chan_scan_time = SURVEY_TO;
- pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
-
- issue_action_BSSCoexistPacket(padapter);
- issue_action_BSSCoexistPacket(padapter);
- issue_action_BSSCoexistPacket(padapter);
- }
-}
-
-/* collect bss info from Beacon and Probe request/response frames. */
-static u8 collect_bss_info(struct adapter *padapter,
- struct recv_frame *precv_frame,
- struct wlan_bssid_ex *bssid)
-{
- int i;
- u32 len;
- u8 *p;
- u16 val16, subtype;
- u8 *pframe = precv_frame->pkt->data;
- u32 packet_len = precv_frame->pkt->len;
- u8 ie_offset;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- len = packet_len - sizeof(struct ieee80211_hdr_3addr);
-
- if (len > MAX_IE_SZ)
- return _FAIL;
-
- memset(bssid, 0, sizeof(struct wlan_bssid_ex));
-
- subtype = GetFrameSubType(pframe);
-
- if (subtype == IEEE80211_STYPE_BEACON) {
- bssid->Reserved[0] = 1;
- ie_offset = _BEACON_IE_OFFSET_;
- } else {
- /* FIXME : more type */
- if (subtype == IEEE80211_STYPE_PROBE_REQ) {
- ie_offset = _PROBEREQ_IE_OFFSET_;
- bssid->Reserved[0] = 2;
- } else if (subtype == IEEE80211_STYPE_PROBE_RESP) {
- ie_offset = _PROBERSP_IE_OFFSET_;
- bssid->Reserved[0] = 3;
- } else {
- bssid->Reserved[0] = 0;
- ie_offset = _FIXED_IE_LENGTH_;
- }
- }
-
- bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
-
- /* below is to copy the information element */
- bssid->ie_length = len;
- memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
-
- /* get the signal strength in dBM.raw data */
- bssid->Rssi = precv_frame->attrib.phy_info.recvpower;
- bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
- bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
- rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA, &bssid->PhyInfo.Optimum_antenna);
-
- /* checking SSID */
- p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SSID, &len, bssid->ie_length - ie_offset);
- if (!p)
- return _FAIL;
-
- if (len) {
- if (len > NDIS_802_11_LENGTH_SSID)
- return _FAIL;
- memcpy(bssid->ssid.ssid, (p + 2), len);
- bssid->ssid.ssid_length = len;
- } else {
- bssid->ssid.ssid_length = 0;
- }
-
- memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
-
- /* checking rate info... */
- i = 0;
- p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->ie_length - ie_offset);
- if (p) {
- if (len > NDIS_802_11_LENGTH_RATES_EX)
- return _FAIL;
- memcpy(bssid->SupportedRates, (p + 2), len);
- i = len;
- }
-
- p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->ie_length - ie_offset);
- if (p) {
- if (len > (NDIS_802_11_LENGTH_RATES_EX - i))
- return _FAIL;
- memcpy(bssid->SupportedRates + i, (p + 2), len);
- }
-
- /* todo: */
- bssid->NetworkTypeInUse = Ndis802_11OFDM24;
-
- if (bssid->ie_length < 12)
- return _FAIL;
-
- /* Checking for DSConfig */
- p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->ie_length - ie_offset);
-
- bssid->Configuration.DSConfig = 0;
- bssid->Configuration.Length = 0;
-
- if (p) {
- bssid->Configuration.DSConfig = *(p + 2);
- } else {/* In 5G, some ap do not have DSSET IE */
- /* checking HT info for channel */
- p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - ie_offset);
- if (p) {
- struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
-
- bssid->Configuration.DSConfig = HT_info->primary_channel;
- } else { /* use current channel */
- bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
- }
- }
-
- if (subtype == IEEE80211_STYPE_PROBE_REQ) {
- /* FIXME */
- bssid->InfrastructureMode = Ndis802_11Infrastructure;
- ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe));
- bssid->Privacy = 1;
- return _SUCCESS;
- }
-
- bssid->Configuration.BeaconPeriod =
- get_unaligned_le16(rtw_get_beacon_interval_from_ie(bssid->ies));
-
- val16 = rtw_get_capability(bssid);
-
- if (val16 & BIT(0)) {
- bssid->InfrastructureMode = Ndis802_11Infrastructure;
- ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe));
- } else {
- bssid->InfrastructureMode = Ndis802_11IBSS;
- ether_addr_copy(bssid->MacAddress, GetAddr3Ptr(pframe));
- }
-
- if (val16 & BIT(4))
- bssid->Privacy = 1;
- else
- bssid->Privacy = 0;
-
- bssid->Configuration.ATIMWindow = 0;
-
- /* 20/40 BSS Coexistence check */
- if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->ie_length - ie_offset);
- if (p && len > 0) {
- struct ieee80211_ht_cap *pHT_caps =
- (struct ieee80211_ht_cap *)(p + 2);
-
- if (le16_to_cpu(pHT_caps->cap_info) & BIT(14))
- pmlmepriv->num_FortyMHzIntolerant++;
- } else {
- pmlmepriv->num_sta_no_ht++;
- }
- }
-
- /* mark bss info receiving from nearby channel as SignalQuality 101 */
- if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
- bssid->PhyInfo.SignalQuality = 101;
- return _SUCCESS;
-}
-
-static void start_create_ibss(struct adapter *padapter)
-{
- unsigned short caps;
- u8 val8;
- u8 join_type;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
- pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
-
- /* update wireless mode */
- update_wireless_mode(padapter);
-
- /* update capability */
- caps = rtw_get_capability(pnetwork);
- update_capinfo(padapter, caps);
- if (caps & WLAN_CAPABILITY_IBSS) {/* adhoc master */
- val8 = 0xcf;
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
-
- /* switch channel */
- /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
- set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-
- beacon_timing_control(padapter);
-
- /* set msr to WIFI_FW_ADHOC_STATE */
- pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
- Set_MSR(padapter, (pmlmeinfo->state & 0x3));
-
- /* issue beacon */
- if (send_beacon(padapter) == _FAIL) {
- report_join_res(padapter, -1);
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- } else {
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
- join_type = 0;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-
- report_join_res(padapter, 1);
- pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
- }
- } else {
- return;
- }
-}
-
-static void start_clnt_join(struct adapter *padapter)
-{
- unsigned short caps;
- u8 val8;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- int beacon_timeout;
-
- pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
- pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
-
- /* update wireless mode */
- update_wireless_mode(padapter);
-
- /* update capability */
- caps = rtw_get_capability(pnetwork);
- update_capinfo(padapter, caps);
- if (caps & WLAN_CAPABILITY_ESS) {
- Set_MSR(padapter, WIFI_FW_STATION_STATE);
-
- val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
-
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
-
- /* switch channel */
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-
- /* here wait for receiving the beacon to start auth */
- /* and enable a timer */
- beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
- set_link_timer(pmlmeext, beacon_timeout);
- mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
- msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout));
-
- pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
- } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */
- Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
-
- val8 = 0xcf;
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
-
- /* switch channel */
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-
- beacon_timing_control(padapter);
-
- pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
-
- report_join_res(padapter, 1);
- } else {
- return;
- }
-}
-
-static void start_clnt_auth(struct adapter *padapter)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- del_timer_sync(&pmlmeext->link_timer);
-
- pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
- pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
-
- pmlmeinfo->auth_seq = 1;
- pmlmeinfo->reauth_count = 0;
- pmlmeinfo->reassoc_count = 0;
- pmlmeinfo->link_count = 0;
- pmlmeext->retry = 0;
-
- /* Because of AP's not receiving deauth before */
- /* AP may: 1)not response auth or 2)deauth us after link is complete */
- /* issue deauth before issuing auth to deal with the situation */
- /* Commented by Albert 2012/07/21 */
- /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
- issue_deauth(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
-
- issue_auth(padapter, NULL, 0);
-
- set_link_timer(pmlmeext, REAUTH_TO);
-}
-
-static void start_clnt_assoc(struct adapter *padapter)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- del_timer_sync(&pmlmeext->link_timer);
-
- pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
- pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
-
- issue_assocreq(padapter);
-
- set_link_timer(pmlmeext, REASSOC_TO);
-}
-
-static unsigned int receive_disconnect(struct adapter *padapter,
- unsigned char *MacAddr,
- unsigned short reason)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- /* check A3 */
- if (memcmp(MacAddr, pnetwork->MacAddress, ETH_ALEN))
- return _SUCCESS;
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- report_del_sta_event(padapter, MacAddr, reason);
- } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- report_join_res(padapter, -2);
- }
- }
- return _SUCCESS;
-}
-
-static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
-{
- struct registry_priv *pregistrypriv;
- struct mlme_ext_priv *pmlmeext;
- struct rt_channel_info *chplan_new;
- u8 channel;
- u8 i;
-
- pregistrypriv = &padapter->registrypriv;
- pmlmeext = &padapter->mlmeextpriv;
-
- /* Adjust channel plan by AP Country IE */
- if (pregistrypriv->enable80211d &&
- (!pmlmeext->update_channel_plan_by_ap_done)) {
- u8 *ie, *p;
- u32 len;
- struct rt_channel_plan chplan_ap;
- struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
- u8 country[4];
- u8 fcn; /* first channel number */
- u8 noc; /* number of channel */
- u8 j, k;
-
- ie = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
- if (!ie)
- return;
- if (len < 6)
- return;
- ie += 2;
- p = ie;
- ie += len;
-
- memset(country, 0, 4);
- memcpy(country, p, 3);
- p += 3;
- i = 0;
- while ((ie - p) >= 3) {
- fcn = *(p++);
- noc = *(p++);
- p++;
-
- for (j = 0; j < noc; j++) {
- channel = fcn + j;
-
- chplan_ap.Channel[i++] = channel;
- }
- }
- chplan_ap.Len = i;
-
- memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
-
- memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
- chplan_new = pmlmeext->channel_set;
-
- i = 0;
- j = 0;
- k = 0;
- if (pregistrypriv->wireless_mode & WIRELESS_11G) {
- do {
- if ((i == MAX_CHANNEL_NUM) ||
- (chplan_sta[i].ChannelNum == 0) ||
- (chplan_sta[i].ChannelNum > 14))
- break;
-
- if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
- break;
-
- if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- i++;
- j++;
- k++;
- } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- chplan_new[k].ScanType = SCAN_PASSIVE;
- i++;
- k++;
- } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- j++;
- k++;
- }
- } while (1);
-
- /* change AP not support channel to Passive scan */
- while ((i < MAX_CHANNEL_NUM) &&
- (chplan_sta[i].ChannelNum != 0) &&
- (chplan_sta[i].ChannelNum <= 14)) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- chplan_new[k].ScanType = SCAN_PASSIVE;
- i++;
- k++;
- }
-
- /* add channel AP supported */
- while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- j++;
- k++;
- }
- } else {
- /* keep original STA 2.4G channel plan */
- while ((i < MAX_CHANNEL_NUM) &&
- (chplan_sta[i].ChannelNum != 0) &&
- (chplan_sta[i].ChannelNum <= 14)) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- chplan_new[k].ScanType = chplan_sta[i].ScanType;
- i++;
- k++;
- }
-
- /* skip AP 2.4G channel plan */
- while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
- j++;
- }
-
- pmlmeext->update_channel_plan_by_ap_done = 1;
- }
-
- /* If channel is used by AP, set channel scan type to active */
- channel = bssid->Configuration.DSConfig;
- chplan_new = pmlmeext->channel_set;
- i = 0;
- while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
- if (chplan_new[i].ChannelNum == channel) {
- if (chplan_new[i].ScanType == SCAN_PASSIVE)
- chplan_new[i].ScanType = SCAN_ACTIVE;
- break;
- }
- i++;
- }
-}
-
-/****************************************************************************
-
-Following are the callback functions for each subtype of the management frames
-
-*****************************************************************************/
-
-static unsigned int OnProbeReq(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- unsigned int ielen;
- unsigned char *p;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur = &pmlmeinfo->network;
- u8 *pframe = precv_frame->pkt->data;
- uint len = precv_frame->pkt->len;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- return _SUCCESS;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
- !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
- return _SUCCESS;
-
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_SSID, &ielen,
- len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
-
- /* check (wildcard) SSID */
- if (p) {
- if ((ielen != 0 && memcmp((void *)(p + 2), (void *)cur->ssid.ssid, cur->ssid.ssid_length)) ||
- (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
- return _SUCCESS;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) &&
- pmlmepriv->cur_network.join_res)
- issue_probersp(padapter, ieee80211_get_SA((struct ieee80211_hdr *)pframe));
- }
- return _SUCCESS;
-}
-
-static unsigned int OnProbeRsp(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
- report_survey_event(padapter, precv_frame);
- return _SUCCESS;
- }
-
- return _SUCCESS;
-}
-
-static unsigned int OnBeacon(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- int cam_idx;
- struct sta_info *psta;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 *pframe = precv_frame->pkt->data;
- uint len = precv_frame->pkt->len;
- struct wlan_bssid_ex *pbss;
- int ret = _SUCCESS;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
- report_survey_event(padapter, precv_frame);
- return _SUCCESS;
- }
-
- if (!memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) {
- if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
- /* we should update current network before auth, or some IE is wrong */
- pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
- if (pbss) {
- if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
- update_network(&pmlmepriv->cur_network.network, pbss, padapter, true);
- rtw_get_bcn_info(&pmlmepriv->cur_network);
- }
- kfree(pbss);
- }
-
- /* check the vendor of the assoc AP */
- pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct ieee80211_hdr_3addr), len - sizeof(struct ieee80211_hdr_3addr));
-
- /* update TSF Value */
- update_TSF(pmlmeext, pframe, len);
-
- /* start auth */
- start_clnt_auth(padapter);
-
- return _SUCCESS;
- }
-
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
- psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if (psta) {
- ret = rtw_check_bcn_info(padapter, pframe, len);
- if (!ret) {
- receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 65535);
- return _SUCCESS;
- }
- /* update WMM, ERP in the beacon */
- /* todo: the timer is used instead of the number of the beacon received */
- if ((sta_rx_pkts(psta) & 0xf) == 0)
- update_beacon_info(padapter, pframe, len, psta);
- }
- } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
- psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if (psta) {
- /* update WMM, ERP in the beacon */
- /* todo: the timer is used instead of the number of the beacon received */
- if ((sta_rx_pkts(psta) & 0xf) == 0)
- update_beacon_info(padapter, pframe, len, psta);
- } else {
- /* allocate a new CAM entry for IBSS station */
- cam_idx = allocate_fw_sta_entry(padapter);
- if (cam_idx == NUM_STA)
- goto _END_ONBEACON_;
-
- /* get supported rate */
- if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
- pmlmeinfo->FW_sta_info[cam_idx].status = 0;
- goto _END_ONBEACON_;
- }
-
- /* update TSF Value */
- update_TSF(pmlmeext, pframe, len);
-
- /* report sta add event */
- report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
- }
- }
- }
-
-_END_ONBEACON_:
-
- return _SUCCESS;
-}
-
-#ifdef CONFIG_88EU_AP_MODE
-static unsigned int OnAuth(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- unsigned int auth_mode, ie_len;
- u16 seq;
- unsigned char *sa, *p;
- u16 algorithm;
- int status;
- static struct sta_info stat;
- struct sta_info *pstat = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 *pframe = precv_frame->pkt->data;
- uint len = precv_frame->pkt->len;
-
- if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- return _FAIL;
-
- sa = GetAddr2Ptr(pframe);
-
- auth_mode = psecuritypriv->dot11AuthAlgrthm;
- seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
- algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
-
- if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
- psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
- auth_mode = 0;
-
- if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */
- (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */
- status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
-
- goto auth_fail;
- }
-
- if (!rtw_access_ctrl(padapter, sa)) {
- status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
- goto auth_fail;
- }
-
- pstat = rtw_get_stainfo(pstapriv, sa);
- if (!pstat) {
- /* allocate a new one */
- pstat = rtw_alloc_stainfo(pstapriv, sa);
- if (!pstat) {
- status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
- goto auth_fail;
- }
-
- pstat->state = WIFI_FW_AUTH_NULL;
- pstat->auth_seq = 0;
- } else {
- spin_lock_bh(&pstapriv->asoc_list_lock);
- if (!list_empty(&pstat->asoc_list)) {
- list_del_init(&pstat->asoc_list);
- pstapriv->asoc_list_cnt--;
- }
- spin_unlock_bh(&pstapriv->asoc_list_lock);
-
- if (seq == 1) {
- /* TODO: STA re_auth and auth timeout */
- }
- }
-
- spin_lock_bh(&pstapriv->auth_list_lock);
- if (list_empty(&pstat->auth_list)) {
- list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
- pstapriv->auth_list_cnt++;
- }
- spin_unlock_bh(&pstapriv->auth_list_lock);
-
- if (pstat->auth_seq == 0)
- pstat->expire_to = pstapriv->auth_to;
-
- if ((pstat->auth_seq + 1) != seq) {
- status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
- goto auth_fail;
- }
-
- if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
- if (seq == 1) {
- pstat->state &= ~WIFI_FW_AUTH_NULL;
- pstat->state |= WIFI_FW_AUTH_SUCCESS;
- pstat->expire_to = pstapriv->assoc_to;
- pstat->authalg = algorithm;
- } else {
- status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
- goto auth_fail;
- }
- } else { /* shared system or auto authentication */
- if (seq == 1) {
- /* prepare for the challenging txt... */
-
- pstat->state &= ~WIFI_FW_AUTH_NULL;
- pstat->state |= WIFI_FW_AUTH_STATE;
- pstat->authalg = algorithm;
- pstat->auth_seq = 2;
- } else if (seq == 3) {
- /* checking for challenging txt... */
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, &ie_len,
- len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
-
- if (!p || ie_len <= 0) {
- status = WLAN_STATUS_CHALLENGE_FAIL;
- goto auth_fail;
- }
-
- if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
- pstat->state &= (~WIFI_FW_AUTH_STATE);
- pstat->state |= WIFI_FW_AUTH_SUCCESS;
- /* challenging txt is correct... */
- pstat->expire_to = pstapriv->assoc_to;
- } else {
- status = WLAN_STATUS_CHALLENGE_FAIL;
- goto auth_fail;
- }
- } else {
- status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
- goto auth_fail;
- }
- }
-
- /* Now, we are going to issue_auth... */
- pstat->auth_seq = seq + 1;
-
- issue_auth(padapter, pstat, (unsigned short)(WLAN_STATUS_SUCCESS));
-
- if (pstat->state & WIFI_FW_AUTH_SUCCESS)
- pstat->auth_seq = 0;
-
- return _SUCCESS;
-
-auth_fail:
-
- if (pstat)
- rtw_free_stainfo(padapter, pstat);
-
- pstat = &stat;
- memset((char *)pstat, '\0', sizeof(stat));
- pstat->auth_seq = 2;
- memcpy(pstat->hwaddr, sa, 6);
-
- issue_auth(padapter, pstat, (unsigned short)status);
-
- return _FAIL;
-}
-#endif /* CONFIG_88EU_AP_MODE */
-
-static unsigned int OnAuthClient(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- unsigned int seq, len, status, offset;
- unsigned char *p;
- unsigned int go2asoc = 0;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 *pframe = precv_frame->pkt->data;
- uint pkt_len = precv_frame->pkt->len;
-
- /* check A1 matches or not */
- if (memcmp(myid(&padapter->eeprompriv), ieee80211_get_DA((struct ieee80211_hdr *)pframe), ETH_ALEN))
- return _SUCCESS;
-
- if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
- return _SUCCESS;
-
- offset = (GetPrivacy(pframe)) ? 4 : 0;
-
- seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
- status = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
-
- if (status != 0) {
- if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
- if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
- pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
- else
- pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
- }
-
- set_link_timer(pmlmeext, 1);
- goto authclnt_fail;
- }
-
- if (seq == 2) {
- if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
- /* legendary shared system */
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, &len,
- pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
-
- if (!p)
- goto authclnt_fail;
-
- memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
- pmlmeinfo->auth_seq = 3;
- issue_auth(padapter, NULL, 0);
- set_link_timer(pmlmeext, REAUTH_TO);
-
- return _SUCCESS;
- }
- /* open system */
- go2asoc = 1;
- } else if (seq == 4) {
- if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
- go2asoc = 1;
- else
- goto authclnt_fail;
- } else {
- /* this is also illegal */
- goto authclnt_fail;
- }
-
- if (go2asoc) {
- start_clnt_assoc(padapter);
- return _SUCCESS;
- }
-authclnt_fail:
- return _FAIL;
-}
-
-static unsigned int OnAssocReq(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
-#ifdef CONFIG_88EU_AP_MODE
- u16 capab_info;
- struct rtw_ieee802_11_elems elems;
- struct sta_info *pstat;
- unsigned char *p, *pos, *wpa_ie;
- unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
- int i, wpa_ie_len, left;
- unsigned char supportRate[16];
- int supportRateNum;
- unsigned short status = WLAN_STATUS_SUCCESS;
- unsigned short frame_type, ie_offset = 0;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur = &pmlmeinfo->network;
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 *pframe = precv_frame->pkt->data;
- uint ie_len, pkt_len = precv_frame->pkt->len;
-
- if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- return _FAIL;
-
- frame_type = GetFrameSubType(pframe);
- if (frame_type == IEEE80211_STYPE_ASSOC_REQ)
- ie_offset = _ASOCREQ_IE_OFFSET_;
- else /* IEEE80211_STYPE_REASSOC_REQ */
- ie_offset = _REASOCREQ_IE_OFFSET_;
-
- if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset)
- return _FAIL;
-
- pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if (!pstat) {
- status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
- goto asoc_class2_error;
- }
-
- capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
-
- left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
- pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
-
- /* check if this stat has been successfully authenticated/assocated */
- if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
- if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
- status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
- goto asoc_class2_error;
- } else {
- pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
- pstat->state |= WIFI_FW_ASSOC_STATE;
- }
- } else {
- pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
- pstat->state |= WIFI_FW_ASSOC_STATE;
- }
- pstat->capability = capab_info;
- /* now parse all ieee802_11 ie to point to elems */
- if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
- !elems.ssid) {
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
- goto OnAssocReqFail;
- }
-
- /* now we should check all the fields... */
- /* checking SSID */
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SSID, &ie_len,
- pkt_len - WLAN_HDR_A3_LEN - ie_offset);
-
- if (!p || ie_len == 0) {
- /* broadcast ssid, however it is not allowed in assocreq */
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
- goto OnAssocReqFail;
- } else {
- /* check if ssid match */
- if (memcmp((void *)(p + 2), cur->ssid.ssid, cur->ssid.ssid_length))
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
-
- if (ie_len != cur->ssid.ssid_length)
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
- }
-
- if (status != WLAN_STATUS_SUCCESS)
- goto OnAssocReqFail;
-
- /* check if the supported rate is ok */
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SUPP_RATES, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
- if (!p) {
- /* use our own rate set as statoin used */
- /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
- /* supportRateNum = AP_BSSRATE_LEN; */
-
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
- goto OnAssocReqFail;
- } else {
- memcpy(supportRate, p + 2, ie_len);
- supportRateNum = ie_len;
-
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_EXT_SUPP_RATES, &ie_len,
- pkt_len - WLAN_HDR_A3_LEN - ie_offset);
- if (p) {
- if (supportRateNum <= sizeof(supportRate)) {
- memcpy(supportRate + supportRateNum,
- p + 2, ie_len);
- supportRateNum += ie_len;
- }
- }
- }
-
- /* todo: mask supportRate between AP & STA -> move to update raid */
- /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
-
- /* update station supportRate */
- pstat->bssratelen = supportRateNum;
- memcpy(pstat->bssrateset, supportRate, supportRateNum);
- UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
-
- /* check RSN/WPA/WPS */
- pstat->dot8021xalg = 0;
- pstat->wpa_psk = 0;
- pstat->wpa_group_cipher = 0;
- pstat->wpa2_group_cipher = 0;
- pstat->wpa_pairwise_cipher = 0;
- pstat->wpa2_pairwise_cipher = 0;
- memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
- if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
- int group_cipher = 0, pairwise_cipher = 0;
-
- wpa_ie = elems.rsn_ie;
- wpa_ie_len = elems.rsn_ie_len;
-
- if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
- pstat->dot8021xalg = 1;/* psk, todo:802.1x */
- pstat->wpa_psk |= BIT(1);
-
- pstat->wpa2_group_cipher = group_cipher & psecuritypriv->wpa2_group_cipher;
- pstat->wpa2_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa2_pairwise_cipher;
-
- if (!pstat->wpa2_group_cipher)
- status = WLAN_STATUS_INVALID_GROUP_CIPHER;
-
- if (!pstat->wpa2_pairwise_cipher)
- status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
- } else {
- status = WLAN_STATUS_INVALID_IE;
- }
- } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
- int group_cipher = 0, pairwise_cipher = 0;
-
- wpa_ie = elems.wpa_ie;
- wpa_ie_len = elems.wpa_ie_len;
-
- if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
- pstat->dot8021xalg = 1;/* psk, todo:802.1x */
- pstat->wpa_psk |= BIT(0);
-
- pstat->wpa_group_cipher = group_cipher & psecuritypriv->wpa_group_cipher;
- pstat->wpa_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa_pairwise_cipher;
-
- if (!pstat->wpa_group_cipher)
- status = WLAN_STATUS_INVALID_GROUP_CIPHER;
-
- if (!pstat->wpa_pairwise_cipher)
- status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
- } else {
- status = WLAN_STATUS_INVALID_IE;
- }
- } else {
- wpa_ie = NULL;
- wpa_ie_len = 0;
- }
-
- if (status != WLAN_STATUS_SUCCESS)
- goto OnAssocReqFail;
-
- pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
- if (!wpa_ie) {
- if (elems.wps_ie) {
- pstat->flags |= WLAN_STA_WPS;
- /* wpabuf_free(sta->wps_ie); */
- /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
- /* elems.wps_ie_len - 4); */
- } else {
- pstat->flags |= WLAN_STA_MAYBE_WPS;
- }
-
- /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
- /* that the selected registrar of AP is _FLASE */
- if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
- if (pmlmepriv->wps_beacon_ie) {
- u8 selected_registrar = 0;
-
- rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
-
- if (!selected_registrar) {
- status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
-
- goto OnAssocReqFail;
- }
- }
- }
- } else {
- int copy_len;
-
- if (psecuritypriv->wpa_psk == 0) {
- status = WLAN_STATUS_INVALID_IE;
-
- goto OnAssocReqFail;
- }
-
- if (elems.wps_ie) {
- pstat->flags |= WLAN_STA_WPS;
- copy_len = 0;
- } else {
- copy_len = min_t(int, wpa_ie_len + 2, sizeof(pstat->wpa_ie));
- }
- if (copy_len > 0)
- memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
- }
- /* check if there is WMM IE & support WWM-PS */
- pstat->flags &= ~WLAN_STA_WME;
- pstat->qos_option = 0;
- pstat->qos_info = 0;
- pstat->has_legacy_ac = true;
- pstat->uapsd_vo = 0;
- pstat->uapsd_vi = 0;
- pstat->uapsd_be = 0;
- pstat->uapsd_bk = 0;
- if (pmlmepriv->qospriv.qos_option) {
- p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
- for (;;) {
- p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
- if (p) {
- if (!memcmp(p + 2, WMM_IE, 6)) {
- pstat->flags |= WLAN_STA_WME;
-
- pstat->qos_option = 1;
- pstat->qos_info = *(p + 8);
-
- pstat->max_sp_len = (pstat->qos_info >> 5) & 0x3;
-
- if ((pstat->qos_info & 0xf) != 0xf)
- pstat->has_legacy_ac = true;
- else
- pstat->has_legacy_ac = false;
-
- if (pstat->qos_info & 0xf) {
- if (pstat->qos_info & BIT(0))
- pstat->uapsd_vo = BIT(0) | BIT(1);
- else
- pstat->uapsd_vo = 0;
-
- if (pstat->qos_info & BIT(1))
- pstat->uapsd_vi = BIT(0) | BIT(1);
- else
- pstat->uapsd_vi = 0;
-
- if (pstat->qos_info & BIT(2))
- pstat->uapsd_bk = BIT(0) | BIT(1);
- else
- pstat->uapsd_bk = 0;
-
- if (pstat->qos_info & BIT(3))
- pstat->uapsd_be = BIT(0) | BIT(1);
- else
- pstat->uapsd_be = 0;
- }
- break;
- }
- } else {
- break;
- }
- p = p + ie_len + 2;
- }
- }
-
- /* save HT capabilities in the sta object */
- memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
- if (elems.ht_capabilities &&
- elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
- pstat->flags |= WLAN_STA_HT;
-
- pstat->flags |= WLAN_STA_WME;
-
- memcpy(&pstat->htpriv.ht_cap,
- elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
- } else {
- pstat->flags &= ~WLAN_STA_HT;
- }
- if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags & WLAN_STA_HT)) {
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
- goto OnAssocReqFail;
- }
-
- pstat->flags |= WLAN_STA_NONERP;
- for (i = 0; i < pstat->bssratelen; i++) {
- if ((pstat->bssrateset[i] & 0x7f) > 22) {
- pstat->flags &= ~WLAN_STA_NONERP;
- break;
- }
- }
-
- if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
- pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
- else
- pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
-
- if (status != WLAN_STATUS_SUCCESS)
- goto OnAssocReqFail;
-
- /* TODO: identify_proprietary_vendor_ie(); */
- /* Realtek proprietary IE */
- /* identify if this is Broadcom sta */
- /* identify if this is ralink sta */
- /* Customer proprietary IE */
-
- /* get a unique AID */
- if (pstat->aid <= 0) {
- for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
- if (!pstapriv->sta_aid[pstat->aid - 1])
- break;
-
- /* if (pstat->aid > NUM_STA) { */
- if (pstat->aid > pstapriv->max_num_sta) {
- pstat->aid = 0;
-
- status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
-
- goto OnAssocReqFail;
- } else {
- pstapriv->sta_aid[pstat->aid - 1] = pstat;
- }
- }
-
- pstat->state &= (~WIFI_FW_ASSOC_STATE);
- pstat->state |= WIFI_FW_ASSOC_SUCCESS;
-
- spin_lock_bh(&pstapriv->auth_list_lock);
- if (!list_empty(&pstat->auth_list)) {
- list_del_init(&pstat->auth_list);
- pstapriv->auth_list_cnt--;
- }
- spin_unlock_bh(&pstapriv->auth_list_lock);
-
- spin_lock_bh(&pstapriv->asoc_list_lock);
- if (list_empty(&pstat->asoc_list)) {
- pstat->expire_to = pstapriv->expire_to;
- list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
- pstapriv->asoc_list_cnt++;
- }
- spin_unlock_bh(&pstapriv->asoc_list_lock);
-
- /* now the station is qualified to join our BSS... */
- if ((pstat->state & WIFI_FW_ASSOC_SUCCESS) && (status == WLAN_STATUS_SUCCESS)) {
- /* 1 bss_cap_update & sta_info_update */
- bss_cap_update_on_sta_join(padapter, pstat);
- sta_info_update(padapter, pstat);
-
- /* issue assoc rsp before notify station join event. */
- if (frame_type == IEEE80211_STYPE_ASSOC_REQ)
- issue_asocrsp(padapter, status, pstat, IEEE80211_STYPE_ASSOC_RESP);
- else
- issue_asocrsp(padapter, status, pstat, IEEE80211_STYPE_REASSOC_RESP);
-
- /* 2 - report to upper layer */
- rtw_indicate_sta_assoc_event(padapter, pstat);
-
- /* 3-(1) report sta add event */
- report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
- }
-
- return _SUCCESS;
-
-asoc_class2_error:
-
- issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
-
- return _FAIL;
-
-OnAssocReqFail:
-
- pstat->aid = 0;
- if (frame_type == IEEE80211_STYPE_ASSOC_REQ)
- issue_asocrsp(padapter, status, pstat, IEEE80211_STYPE_ASSOC_RESP);
- else
- issue_asocrsp(padapter, status, pstat, IEEE80211_STYPE_REASSOC_RESP);
-
-#endif /* CONFIG_88EU_AP_MODE */
-
- return _FAIL;
-}
-
-static unsigned int OnAssocRsp(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- uint i;
- int res;
- unsigned short status;
- struct ndis_802_11_var_ie *pIE;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 *pframe = precv_frame->pkt->data;
- uint pkt_len = precv_frame->pkt->len;
-
- /* check A1 matches or not */
- if (memcmp(myid(&padapter->eeprompriv), ieee80211_get_DA((struct ieee80211_hdr *)pframe), ETH_ALEN))
- return _SUCCESS;
-
- if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
- return _SUCCESS;
-
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
- return _SUCCESS;
-
- del_timer_sync(&pmlmeext->link_timer);
-
- /* status */
- status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
- if (status > 0) {
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- res = -4;
- goto report_assoc_result;
- }
-
- /* get capabilities */
- pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
-
- /* set slot time */
- pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
-
- /* AID */
- pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4)) & 0x3fff);
- res = pmlmeinfo->aid;
-
- /* following are moved to join event callback function */
- /* to handle HT, WMM, rate adaptive, update MAC reg */
- /* for not to handle the synchronous IO in the tasklet */
- for (i = 6 + WLAN_HDR_A3_LEN; i < pkt_len;) {
- pIE = (struct ndis_802_11_var_ie *)(pframe + i);
-
- switch (pIE->ElementID) {
- case WLAN_EID_VENDOR_SPECIFIC:
- if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
- WMM_param_handler(padapter, pIE);
- break;
- case WLAN_EID_HT_CAPABILITY: /* HT caps */
- HT_caps_handler(padapter, pIE);
- break;
- case WLAN_EID_HT_OPERATION: /* HT info */
- HT_info_handler(padapter, pIE);
- break;
- case WLAN_EID_ERP_INFO:
- ERP_IE_handler(padapter, pIE);
- break;
- default:
- break;
- }
-
- i += (pIE->Length + 2);
- }
-
- pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
- pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
-
- UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
-
-report_assoc_result:
- if (res > 0)
- rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
- else
- rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
-
- report_join_res(padapter, res);
-
- return _SUCCESS;
-}
-
-static unsigned int OnDeAuth(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- unsigned short reason;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 *pframe = precv_frame->pkt->data;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- /* check A3 */
- if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN))
- return _SUCCESS;
-
- reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
-
-#ifdef CONFIG_88EU_AP_MODE
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if (psta) {
- u8 updated = 0;
-
- spin_lock_bh(&pstapriv->asoc_list_lock);
- if (!list_empty(&psta->asoc_list)) {
- list_del_init(&psta->asoc_list);
- pstapriv->asoc_list_cnt--;
- updated = ap_free_sta(padapter, psta, false, reason);
- }
- spin_unlock_bh(&pstapriv->asoc_list_lock);
-
- associated_clients_update(padapter, updated);
- }
-
- return _SUCCESS;
- }
-#endif
- receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
-
- pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
- return _SUCCESS;
-}
-
-static unsigned int OnDisassoc(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- u16 reason;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 *pframe = precv_frame->pkt->data;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-
- /* check A3 */
- if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN))
- return _SUCCESS;
-
- reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
-
-#ifdef CONFIG_88EU_AP_MODE
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if (psta) {
- u8 updated = 0;
-
- spin_lock_bh(&pstapriv->asoc_list_lock);
- if (!list_empty(&psta->asoc_list)) {
- list_del_init(&psta->asoc_list);
- pstapriv->asoc_list_cnt--;
- updated = ap_free_sta(padapter, psta, false, reason);
- }
- spin_unlock_bh(&pstapriv->asoc_list_lock);
-
- associated_clients_update(padapter, updated);
- }
-
- return _SUCCESS;
- }
-#endif
- receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
-
- pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
- return _SUCCESS;
-}
-
-static unsigned int OnAtim(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- return _SUCCESS;
-}
-
-static unsigned int on_action_spct(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- struct sta_info *psta = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 *pframe = precv_frame->pkt->data;
- u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
- u8 category;
- u8 action;
-
- psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
-
- if (!psta)
- goto exit;
-
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
- goto exit;
-
- action = frame_body[1];
- switch (action) {
- case WLAN_ACTION_SPCT_MSR_REQ:
- case WLAN_ACTION_SPCT_MSR_RPRT:
- case WLAN_ACTION_SPCT_TPC_REQ:
- case WLAN_ACTION_SPCT_TPC_RPRT:
- break;
- case WLAN_ACTION_SPCT_CHL_SWITCH:
- break;
- default:
- break;
- }
-
-exit:
- return _FAIL;
-}
-
-static unsigned int OnAction_qos(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- return _SUCCESS;
-}
-
-static unsigned int OnAction_dls(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- return _SUCCESS;
-}
-
-static unsigned int OnAction_back(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- u8 *addr;
- struct sta_info *psta = NULL;
- struct recv_reorder_ctrl *preorder_ctrl;
- unsigned char *frame_body;
- unsigned char category, action;
- unsigned short tid, status;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 *pframe = precv_frame->pkt->data;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- /* check RA matches or not */
- if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe),
- ETH_ALEN))/* for if1, sta/ap mode */
- return _SUCCESS;
-
- if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
- return _SUCCESS;
-
- addr = GetAddr2Ptr(pframe);
- psta = rtw_get_stainfo(pstapriv, addr);
-
- if (!psta)
- return _SUCCESS;
-
- frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
-
- category = frame_body[0];
- if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */
- if (!pmlmeinfo->HT_enable)
- return _SUCCESS;
- action = frame_body[1];
- switch (action) {
- case WLAN_ACTION_ADDBA_REQ:
- memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2], sizeof(struct ADDBA_request));
- process_addba_req(padapter, (u8 *)&pmlmeinfo->ADDBA_req, addr);
-
- /* 37 = reject ADDBA Req */
- issue_action_BA(padapter, addr,
- WLAN_ACTION_ADDBA_RESP,
- pmlmeinfo->accept_addba_req ? 0 : 37);
- break;
- case WLAN_ACTION_ADDBA_RESP:
- status = get_unaligned_le16(&frame_body[3]);
- tid = (frame_body[5] >> 2) & 0x7;
- if (status == 0) { /* successful */
- psta->htpriv.agg_enable_bitmap |= 1 << tid;
- psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
- } else {
- psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
- }
- break;
- case WLAN_ACTION_DELBA:
- if ((frame_body[3] & BIT(3)) == 0) {
- psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
- psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
- } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
- tid = (frame_body[3] >> 4) & 0x0F;
- preorder_ctrl = &psta->recvreorder_ctrl[tid];
- preorder_ctrl->enable = false;
- preorder_ctrl->indicate_seq = 0xffff;
- }
- /* todo: how to notify the host while receiving DELETE BA */
- break;
- default:
- break;
- }
- }
- return _SUCCESS;
-}
-
-static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
-{
- struct adapter *adapter = recv_frame->adapter;
- struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
- u8 *frame = recv_frame->pkt->data;
- u16 seq_ctrl = ((recv_frame->attrib.seq_num & 0xffff) << 4) |
- (recv_frame->attrib.frag_num & 0xf);
-
- if (GetRetry(frame)) {
- if (token >= 0) {
- if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token))
- return _FAIL;
- } else {
- if (seq_ctrl == mlmeext->action_public_rxseq)
- return _FAIL;
- }
- }
-
- mlmeext->action_public_rxseq = seq_ctrl;
-
- if (token >= 0)
- mlmeext->action_public_dialog_token = token;
-
- return _SUCCESS;
-}
-
-static unsigned int on_action_public_p2p(struct recv_frame *precv_frame)
-{
- u8 *pframe = precv_frame->pkt->data;
- u8 *frame_body;
- u8 dialogToken = 0;
-
- frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
- dialogToken = frame_body[7];
-
- if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
- return _FAIL;
-
- return _SUCCESS;
-}
-
-static unsigned int on_action_public_vendor(struct recv_frame *precv_frame)
-{
- unsigned int ret = _FAIL;
- u8 *pframe = precv_frame->pkt->data;
- u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-
- if (!memcmp(frame_body + 2, P2P_OUI, 4))
- ret = on_action_public_p2p(precv_frame);
-
- return ret;
-}
-
-static unsigned int on_action_public_default(struct recv_frame *precv_frame,
- u8 action)
-{
- unsigned int ret = _FAIL;
- u8 *pframe = precv_frame->pkt->data;
- u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
- u8 token;
-
- token = frame_body[2];
-
- if (rtw_action_public_decache(precv_frame, token) == _FAIL)
- goto exit;
-
- ret = _SUCCESS;
-
-exit:
- return ret;
-}
-
-static unsigned int on_action_public(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- unsigned int ret = _FAIL;
- u8 *pframe = precv_frame->pkt->data;
- u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
- u8 category, action;
-
- /* check RA matches or not */
- if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))
- goto exit;
-
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_PUBLIC)
- goto exit;
-
- action = frame_body[1];
- switch (action) {
- case ACT_PUBLIC_VENDOR:
- ret = on_action_public_vendor(precv_frame);
- break;
- default:
- ret = on_action_public_default(precv_frame, action);
- break;
- }
-
-exit:
- return ret;
-}
-
-static unsigned int OnAction_ht(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- return _SUCCESS;
-}
-
-static unsigned int OnAction_wmm(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- return _SUCCESS;
-}
-
-static unsigned int OnAction_p2p(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- return _SUCCESS;
-}
-
-static unsigned int DoReserved(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- return _SUCCESS;
-}
-
-static struct action_handler OnAction_tbl[] = {
- {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct},
- {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
- {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
- {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
- {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
- {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
- {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved},
- {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht},
- {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
- {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
- {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
-};
-
-static unsigned int OnAction(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- int i;
- unsigned char category;
- struct action_handler *ptable;
- unsigned char *frame_body;
- u8 *pframe = precv_frame->pkt->data;
-
- frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
-
- category = frame_body[0];
-
- for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) {
- ptable = &OnAction_tbl[i];
- if (category == ptable->num)
- ptable->func(padapter, precv_frame);
- }
- return _SUCCESS;
-}
-
-/****************************************************************************
-
-Following are the initialization functions for WiFi MLME
-
-*****************************************************************************/
-
-static struct mlme_handler mlme_sta_tbl[] = {
- {IEEE80211_STYPE_ASSOC_REQ, "OnAssocReq", &OnAssocReq},
- {IEEE80211_STYPE_ASSOC_RESP, "OnAssocRsp", &OnAssocRsp},
- {IEEE80211_STYPE_REASSOC_REQ, "OnReAssocReq", &OnAssocReq},
- {IEEE80211_STYPE_REASSOC_RESP, "OnReAssocRsp", &OnAssocRsp},
- {IEEE80211_STYPE_PROBE_REQ, "OnProbeReq", &OnProbeReq},
- {IEEE80211_STYPE_PROBE_RESP, "OnProbeRsp", &OnProbeRsp},
- {0, "DoReserved", &DoReserved},
- {0, "DoReserved", &DoReserved},
- {IEEE80211_STYPE_BEACON, "OnBeacon", &OnBeacon},
- {IEEE80211_STYPE_ATIM, "OnATIM", &OnAtim},
- {IEEE80211_STYPE_DISASSOC, "OnDisassoc", &OnDisassoc},
- {IEEE80211_STYPE_AUTH, "OnAuth", &OnAuthClient},
- {IEEE80211_STYPE_DEAUTH, "OnDeAuth", &OnDeAuth},
- {IEEE80211_STYPE_ACTION, "OnAction", &OnAction},
-};
-
-int init_hw_mlme_ext(struct adapter *padapter)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
- return _SUCCESS;
-}
-
-static void init_mlme_ext_priv_value(struct adapter *padapter)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- unsigned char mixed_datarate[NumRates] = {
- _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
- _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
- _48M_RATE_, _54M_RATE_, 0xff
- };
- unsigned char mixed_basicrate[NumRates] = {
- _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
- _12M_RATE_, _24M_RATE_, 0xff,
- };
-
- atomic_set(&pmlmeext->event_seq, 0);
- pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
-
- pmlmeext->cur_channel = padapter->registrypriv.channel;
- pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- pmlmeext->oper_channel = pmlmeext->cur_channel;
- pmlmeext->oper_bwmode = pmlmeext->cur_bwmode;
- pmlmeext->oper_ch_offset = pmlmeext->cur_ch_offset;
- pmlmeext->retry = 0;
-
- pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
-
- memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
- memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
-
- pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
-
- pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
- pmlmeext->sitesurvey_res.channel_idx = 0;
- pmlmeext->sitesurvey_res.bss_cnt = 0;
- pmlmeext->scan_abort = false;
-
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- pmlmeinfo->reauth_count = 0;
- pmlmeinfo->reassoc_count = 0;
- pmlmeinfo->link_count = 0;
- pmlmeinfo->auth_seq = 0;
- pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
- pmlmeinfo->key_index = 0;
- pmlmeinfo->iv = 0;
-
- pmlmeinfo->enc_algo = _NO_PRIVACY_;
- pmlmeinfo->authModeToggle = 0;
-
- memset(pmlmeinfo->chg_txt, 0, 128);
-
- pmlmeinfo->slotTime = SHORT_SLOT_TIME;
- pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
-
- pmlmeinfo->dialogToken = 0;
-
- pmlmeext->action_public_rxseq = 0xffff;
- pmlmeext->action_public_dialog_token = 0xff;
-}
-
-static int has_channel(struct rt_channel_info *channel_set,
- u8 chanset_size, u8 chan)
-{
- int i;
-
- for (i = 0; i < chanset_size; i++) {
- if (channel_set[i].ChannelNum == chan)
- return 1;
- }
- return 0;
-}
-
-static void init_channel_list(struct adapter *padapter,
- struct rt_channel_info *channel_set,
- u8 chanset_size,
- struct p2p_channels *channel_list)
-{
- struct p2p_oper_class_map op_class[] = {
- { IEEE80211G, 81, 1, 13, 1, BW20 },
- { IEEE80211G, 82, 14, 14, 1, BW20 },
- { -1, 0, 0, 0, 0, BW20 }
- };
-
- int cla, op;
-
- cla = 0;
-
- for (op = 0; op_class[op].op_class; op++) {
- u8 ch;
- struct p2p_oper_class_map *o = &op_class[op];
- struct p2p_reg_class *reg = NULL;
-
- for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
- if (!has_channel(channel_set, chanset_size, ch))
- continue;
-
- if (!padapter->registrypriv.ht_enable && o->inc == 8)
- continue;
-
- if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
- ((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))
- continue;
-
- if (!reg) {
- reg = &channel_list->reg_class[cla];
- cla++;
- reg->reg_class = o->op_class;
- reg->channels = 0;
- }
- reg->channel[reg->channels] = ch;
- reg->channels++;
- }
- }
- channel_list->reg_classes = cla;
-}
-
-static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan,
- struct rt_channel_info *channel_set)
-{
- u8 index, chanset_size = 0;
- u8 b2_4GBand = false;
- u8 Index2G = 0;
-
- memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
-
- if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
- return chanset_size;
-
- if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
- b2_4GBand = true;
- if (ChannelPlan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
- Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
- else
- Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
- }
-
- if (b2_4GBand) {
- for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
- channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
-
- if ((ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN) ||/* Channel 1~11 is active, and 12~14 is passive */
- (ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G)) {
- if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
- channel_set[chanset_size].ScanType = SCAN_ACTIVE;
- else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14))
- channel_set[chanset_size].ScanType = SCAN_PASSIVE;
- } else if (ChannelPlan == RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ||
- Index2G == RT_CHANNEL_DOMAIN_2G_WORLD) {/* channel 12~13, passive scan */
- if (channel_set[chanset_size].ChannelNum <= 11)
- channel_set[chanset_size].ScanType = SCAN_ACTIVE;
- else
- channel_set[chanset_size].ScanType = SCAN_PASSIVE;
- } else {
- channel_set[chanset_size].ScanType = SCAN_ACTIVE;
- }
-
- chanset_size++;
- }
- }
- return chanset_size;
-}
-
-int init_mlme_ext_priv(struct adapter *padapter)
-{
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- init_mlme_ext_priv_value(padapter);
- pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req;
-
- init_mlme_ext_timer(padapter);
-
-#ifdef CONFIG_88EU_AP_MODE
- init_mlme_ap_info(padapter);
-#endif
-
- pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
- init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
-
- pmlmeext->chan_scan_time = SURVEY_TO;
- pmlmeext->mlmeext_init = true;
-
- pmlmeext->active_keep_alive_check = true;
-
- return _SUCCESS;
-}
-
-void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
-{
- struct adapter *padapter = container_of(pmlmeext, struct adapter, mlmeextpriv);
-
- if (padapter->bDriverStopped) {
- del_timer_sync(&pmlmeext->survey_timer);
- del_timer_sync(&pmlmeext->link_timer);
- }
-}
-
-static void _mgt_dispatcher(struct adapter *padapter,
- struct mlme_handler *ptable,
- struct recv_frame *precv_frame)
-{
- u8 *pframe = precv_frame->pkt->data;
-
- if (ptable->func) {
- /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
- if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
- !is_broadcast_ether_addr(GetAddr1Ptr(pframe)))
- return;
- ptable->func(padapter, precv_frame);
- }
-}
-
-void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame)
-{
- int index;
- struct mlme_handler *ptable;
-#ifdef CONFIG_88EU_AP_MODE
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-#endif
- u8 *pframe = precv_frame->pkt->data;
- struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
-
- if (GetFrameType(pframe) != WIFI_MGT_TYPE)
- return;
-
- /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
- if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
- !is_broadcast_ether_addr(GetAddr1Ptr(pframe)))
- return;
-
- ptable = mlme_sta_tbl;
-
- index = GetFrameSubType(pframe) >> 4;
-
- if (index > 13)
- return;
- ptable += index;
-
- if (psta) {
- if (GetRetry(pframe)) {
- if (precv_frame->attrib.seq_num ==
- psta->RxMgmtFrameSeqNum)
- /* drop the duplicate management frame */
- return;
- }
- psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
- }
-
-#ifdef CONFIG_88EU_AP_MODE
- switch (GetFrameSubType(pframe)) {
- case IEEE80211_STYPE_AUTH:
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
- ptable->func = &OnAuth;
- else
- ptable->func = &OnAuthClient;
- fallthrough;
- case IEEE80211_STYPE_ASSOC_REQ:
- case IEEE80211_STYPE_REASSOC_REQ:
- case IEEE80211_STYPE_PROBE_REQ:
- case IEEE80211_STYPE_BEACON:
- case IEEE80211_STYPE_ACTION:
- _mgt_dispatcher(padapter, ptable, precv_frame);
- break;
- default:
- _mgt_dispatcher(padapter, ptable, precv_frame);
- break;
- }
-#else
- _mgt_dispatcher(padapter, ptable, precv_frame);
-#endif
-}
-
-/****************************************************************************
-
-Following are the functions to report events
-
-*****************************************************************************/
-
-void report_survey_event(struct adapter *padapter,
- struct recv_frame *precv_frame)
-{
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct survey_event *psurvey_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext;
- struct cmd_priv *pcmdpriv;
-
- if (!padapter)
- return;
-
- pmlmeext = &padapter->mlmeextpriv;
- pcmdpriv = &padapter->cmdpriv;
-
- pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
- if (!pcmd_obj)
- return;
-
- cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
- pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
- if (!pevtcmd) {
- kfree(pcmd_obj);
- return;
- }
-
- INIT_LIST_HEAD(&pcmd_obj->list);
-
- pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
-
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
-
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct survey_event);
- pc2h_evt_hdr->ID = _Survey_EVT_;
- pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-
- psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
-
- if (collect_bss_info(padapter, precv_frame, &psurvey_evt->bss) == _FAIL) {
- kfree(pcmd_obj);
- kfree(pevtcmd);
- return;
- }
-
- process_80211d(padapter, &psurvey_evt->bss);
-
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-
- pmlmeext->sitesurvey_res.bss_cnt++;
-}
-
-void report_surveydone_event(struct adapter *padapter)
-{
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct surveydone_event *psurveydone_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
- if (!pcmd_obj)
- return;
-
- cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
- pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
- if (!pevtcmd) {
- kfree(pcmd_obj);
- return;
- }
-
- INIT_LIST_HEAD(&pcmd_obj->list);
-
- pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
-
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
-
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct surveydone_event);
- pc2h_evt_hdr->ID = _SurveyDone_EVT_;
- pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-
- psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
-
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-}
-
-void report_join_res(struct adapter *padapter, int res)
-{
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct joinbss_event *pjoinbss_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
- if (!pcmd_obj)
- return;
-
- cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
- pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
- if (!pevtcmd) {
- kfree(pcmd_obj);
- return;
- }
-
- INIT_LIST_HEAD(&pcmd_obj->list);
-
- pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
-
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
-
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct joinbss_event);
- pc2h_evt_hdr->ID = _JoinBss_EVT_;
- pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-
- pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- memcpy((unsigned char *)(&pjoinbss_evt->network.network), &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
- pjoinbss_evt->network.join_res = res;
- pjoinbss_evt->network.aid = res;
-
- rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
-
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-}
-
-void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr,
- unsigned short reason)
-{
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct sta_info *psta;
- int mac_id;
- struct stadel_event *pdel_sta_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
- if (!pcmd_obj)
- return;
-
- cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
- pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
- if (!pevtcmd) {
- kfree(pcmd_obj);
- return;
- }
-
- INIT_LIST_HEAD(&pcmd_obj->list);
-
- pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
-
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
-
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct stadel_event);
- pc2h_evt_hdr->ID = _DelSTA_EVT_;
- pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-
- pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- ether_addr_copy((unsigned char *)(&pdel_sta_evt->macaddr), MacAddr);
- memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
-
- psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
- if (psta)
- mac_id = (int)psta->mac_id;
- else
- mac_id = -1;
-
- pdel_sta_evt->mac_id = mac_id;
-
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-}
-
-void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr,
- int cam_idx)
-{
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct stassoc_event *padd_sta_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
- if (!pcmd_obj)
- return;
-
- cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
- pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
- if (!pevtcmd) {
- kfree(pcmd_obj);
- return;
- }
-
- INIT_LIST_HEAD(&pcmd_obj->list);
-
- pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
-
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
-
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct stassoc_event);
- pc2h_evt_hdr->ID = _AddSTA_EVT_;
- pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-
- padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- ether_addr_copy((unsigned char *)(&padd_sta_evt->macaddr), MacAddr);
- padd_sta_evt->cam_id = cam_idx;
-
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-}
-
-/****************************************************************************
-
-Following are the event callback functions
-
-*****************************************************************************/
-
-/* for sta/adhoc mode */
-void update_sta_info(struct adapter *padapter, struct sta_info *psta)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- /* ERP */
- VCS_update(padapter, psta);
-
- /* HT */
- if (pmlmepriv->htpriv.ht_option) {
- psta->htpriv.ht_option = true;
-
- psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
-
- if (support_short_GI(padapter, &pmlmeinfo->HT_caps))
- psta->htpriv.sgi = true;
-
- psta->qos_option = true;
- } else {
- psta->htpriv.ht_option = false;
-
- psta->htpriv.ampdu_enable = false;
-
- psta->htpriv.sgi = false;
- psta->qos_option = false;
- }
- psta->htpriv.bwmode = pmlmeext->cur_bwmode;
- psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
-
- psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
- psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
-
- /* QoS */
- if (pmlmepriv->qospriv.qos_option)
- psta->qos_option = true;
-
- psta->state = _FW_LINKED;
-}
-
-void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
-{
- struct sta_info *psta, *psta_bmc;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 join_type;
- u16 media_status;
-
- if (join_res < 0) {
- join_type = 1;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
-
- /* restore to initial setting. */
- update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
-
- return;
- }
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
- /* for bc/mc */
- psta_bmc = rtw_get_bcmc_stainfo(padapter);
- if (psta_bmc) {
- pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
- update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
- Update_RA_Entry(padapter, psta_bmc->mac_id);
- }
- }
-
- /* turn on dynamic functions */
- Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
-
- /* update IOT-related issue */
- update_IOT_info(padapter);
-
- rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
-
- /* BCN interval */
- rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
-
- /* update capability */
- update_capinfo(padapter, pmlmeinfo->capability);
-
- /* WMM, Update EDCA param */
- WMMOnAssocRsp(padapter);
-
- /* HT */
- HTOnAssocRsp(padapter);
-
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-
- psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
- if (psta) { /* only for infra. mode */
- pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
-
- psta->wireless_mode = pmlmeext->cur_wireless_mode;
-
- /* set per sta rate after updating HT cap. */
- set_sta_rate(padapter, psta);
- rtw_hal_set_hwreg(padapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&psta->mac_id);
- media_status = (psta->mac_id << 8) | 1; /* MACID|OPMODE: 1 means connect */
- rtw_hal_set_hwreg(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
- }
-
- join_type = 2;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
- /* correcting TSF */
- correct_TSF(padapter, pmlmeext);
- }
- rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
-}
-
-void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 join_type;
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
- /* nothing to do */
- } else { /* adhoc client */
- /* correcting TSF */
- correct_TSF(padapter, pmlmeext);
-
- /* start beacon */
- if (send_beacon(padapter) == _FAIL) {
- pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
- pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
- return;
- }
- pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
- }
-
- join_type = 2;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
- }
-
- pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
-
- /* rate radaptive */
- Update_RA_Entry(padapter, psta->mac_id);
-
- /* update adhoc sta_info */
- update_sta_info(padapter, psta);
-}
-
-void mlmeext_sta_del_event_callback(struct adapter *padapter)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
-
- /* restore to initial setting. */
- update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
-
- /* switch to the 20M Hz mode after disconnect */
- pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-
- /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-
- flush_all_cam_entry(padapter);
-
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
-
- /* set MSR to no link state -> infra. mode */
- Set_MSR(padapter, _HW_STATE_STATION_);
-
- del_timer_sync(&pmlmeext->link_timer);
- }
-}
-
-/****************************************************************************
-
-Following are the functions for the timer handlers
-
-*****************************************************************************/
-
-static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
-{
- u8 ret = false;
-
- if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
- sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
- sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
- ret = false;
- else
- ret = true;
-
- sta_update_last_rx_pkts(psta);
-
- return ret;
-}
-
-void linked_status_chk(struct adapter *padapter)
-{
- u32 i;
- struct sta_info *psta;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (is_client_associated_to_ap(padapter)) {
- /* linked infrastructure client mode */
-
- int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
- int rx_chk_limit;
-
- rx_chk_limit = 4;
- psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
- if (psta) {
- bool is_p2p_enable = false;
-
- if (!chk_ap_is_alive(padapter, psta))
- rx_chk = _FAIL;
-
- if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
- tx_chk = _FAIL;
-
- if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
- u8 backup_oper_channel = 0;
-
- /* switch to correct channel of current network before issue keep-alive frames */
- if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
- backup_oper_channel = rtw_get_oper_ch(padapter);
- SelectChannel(padapter, pmlmeext->cur_channel);
- }
-
- if (rx_chk != _SUCCESS)
- issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, psta->hwaddr, 3, 1);
-
- if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
- tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
- /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
- if (tx_chk == _SUCCESS && !is_p2p_enable)
- rx_chk = _SUCCESS;
- }
-
- /* back to the original operation channel */
- if (backup_oper_channel > 0)
- SelectChannel(padapter, backup_oper_channel);
- } else {
- if (rx_chk != _SUCCESS) {
- if (pmlmeext->retry == 0) {
- issue_probereq(padapter, &pmlmeinfo->network.ssid,
- pmlmeinfo->network.MacAddress,
- false);
- issue_probereq(padapter, &pmlmeinfo->network.ssid,
- pmlmeinfo->network.MacAddress,
- false);
- issue_probereq(padapter, &pmlmeinfo->network.ssid,
- pmlmeinfo->network.MacAddress,
- false);
- }
- }
-
- if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf)
- tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
- }
-
- if (rx_chk == _FAIL) {
- pmlmeext->retry++;
- if (pmlmeext->retry > rx_chk_limit) {
- receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
- WLAN_REASON_EXPIRATION_CHK);
- return;
- }
- } else {
- pmlmeext->retry = 0;
- }
-
- if (tx_chk == _FAIL) {
- pmlmeinfo->link_count &= 0xf;
- } else {
- pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
- pmlmeinfo->link_count = 0;
- }
- } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
- } else if (is_client_associated_to_ibss(padapter)) {
- /* linked IBSS mode */
- /* for each assoc list entry to check the rx pkt counter */
- for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
- if (pmlmeinfo->FW_sta_info[i].status == 1) {
- psta = pmlmeinfo->FW_sta_info[i].psta;
-
- if (!psta)
- continue;
- if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
- if (pmlmeinfo->FW_sta_info[i].retry < 3) {
- pmlmeinfo->FW_sta_info[i].retry++;
- } else {
- pmlmeinfo->FW_sta_info[i].retry = 0;
- pmlmeinfo->FW_sta_info[i].status = 0;
- report_del_sta_event(padapter, psta->hwaddr
- , 65535/* indicate disconnect caused by no rx */
- );
- }
- } else {
- pmlmeinfo->FW_sta_info[i].retry = 0;
- pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
- }
- }
- }
- }
-}
-
-void survey_timer_hdl(struct timer_list *t)
-{
- struct adapter *padapter = from_timer(padapter, t,
- mlmeextpriv.survey_timer);
- struct cmd_obj *ph2c;
- struct sitesurvey_parm *psurveyPara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- /* issue rtw_sitesurvey_cmd */
- if (pmlmeext->sitesurvey_res.state > SCAN_START) {
- if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
- pmlmeext->sitesurvey_res.channel_idx++;
-
- if (pmlmeext->scan_abort) {
- pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
-
- pmlmeext->scan_abort = false;/* reset */
- }
-
- ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
- if (!ph2c)
- goto exit_survey_timer_hdl;
-
- psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
- if (!psurveyPara) {
- kfree(ph2c);
- goto exit_survey_timer_hdl;
- }
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_);
- rtw_enqueue_cmd(pcmdpriv, ph2c);
- }
-
-exit_survey_timer_hdl:
- return;
-}
-
-void link_timer_hdl(struct timer_list *t)
-{
- struct adapter *padapter = from_timer(padapter, t,
- mlmeextpriv.link_timer);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- report_join_res(padapter, -3);
- } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
- /* re-auth timer */
- if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
- pmlmeinfo->state = 0;
- report_join_res(padapter, -1);
- return;
- }
-
- pmlmeinfo->auth_seq = 1;
- issue_auth(padapter, NULL, 0);
- set_link_timer(pmlmeext, REAUTH_TO);
- } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
- /* re-assoc timer */
- if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- report_join_res(padapter, -2);
- return;
- }
-
- issue_assocreq(padapter);
- set_link_timer(pmlmeext, REASSOC_TO);
- }
-}
-
-void addba_timer_hdl(struct timer_list *t)
-{
- struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
- struct ht_priv *phtpriv;
-
- if (!psta)
- return;
-
- phtpriv = &psta->htpriv;
-
- if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
- if (phtpriv->candidate_tid_bitmap)
- phtpriv->candidate_tid_bitmap = 0x0;
- }
-}
-
-u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
-{
- u8 type;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
-
- if (psetop->mode == Ndis802_11APMode) {
- pmlmeinfo->state = WIFI_FW_AP_STATE;
- type = _HW_STATE_AP_;
- } else if (psetop->mode == Ndis802_11Infrastructure) {
- pmlmeinfo->state &= ~(BIT(0) | BIT(1));/* clear state */
- pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
- type = _HW_STATE_STATION_;
- } else if (psetop->mode == Ndis802_11IBSS) {
- type = _HW_STATE_ADHOC_;
- } else {
- type = _HW_STATE_NOLINK_;
- }
-
- rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
- /* Set_MSR(padapter, type); */
-
- return H2C_SUCCESS;
-}
-
-u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
-
- if (pparm->InfrastructureMode == Ndis802_11APMode) {
-#ifdef CONFIG_88EU_AP_MODE
-
- if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
- /* todo: */
- return H2C_SUCCESS;
- }
-#endif
- }
-
- /* below is for ad-hoc master */
- if (pparm->InfrastructureMode == Ndis802_11IBSS) {
- rtw_joinbss_reset(padapter);
-
- pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- pmlmeinfo->ERP_enable = 0;
- pmlmeinfo->WMM_enable = 0;
- pmlmeinfo->HT_enable = 0;
- pmlmeinfo->HT_caps_enable = 0;
- pmlmeinfo->HT_info_enable = 0;
- pmlmeinfo->agg_enable_bitmap = 0;
- pmlmeinfo->candidate_tid_bitmap = 0;
-
- /* disable dynamic functions, such as high power, DIG */
- Save_DM_Func_Flag(padapter);
- Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
-
- /* config the initial gain under linking, need to write the BB registers */
- /* initialgain = 0x1E; */
- /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
-
- /* cancel link timer */
- del_timer_sync(&pmlmeext->link_timer);
-
- /* clear CAM */
- flush_all_cam_entry(padapter);
-
- memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length));
- pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
-
- if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
- return H2C_PARAMETERS_ERROR;
-
- memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
-
- start_create_ibss(padapter);
- }
-
- return H2C_SUCCESS;
-}
-
-u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
-{
- u8 join_type;
- struct ndis_802_11_var_ie *pIE;
- struct registry_priv *pregpriv = &padapter->registrypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
- u32 i;
-
- /* check already connecting to AP or not */
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
- if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
-
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
-
- /* clear CAM */
- flush_all_cam_entry(padapter);
-
- del_timer_sync(&pmlmeext->link_timer);
-
- /* set MSR to nolink -> infra. mode */
- Set_MSR(padapter, _HW_STATE_STATION_);
-
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
- }
-
- rtw_antenna_select_cmd(padapter, pparm->PhyInfo.Optimum_antenna, false);
-
- rtw_joinbss_reset(padapter);
-
- pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- pmlmeinfo->ERP_enable = 0;
- pmlmeinfo->WMM_enable = 0;
- pmlmeinfo->HT_enable = 0;
- pmlmeinfo->HT_caps_enable = 0;
- pmlmeinfo->HT_info_enable = 0;
- pmlmeinfo->agg_enable_bitmap = 0;
- pmlmeinfo->candidate_tid_bitmap = 0;
- pmlmeinfo->bwmode_updated = false;
-
- memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length));
- pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
-
- if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
- return H2C_PARAMETERS_ERROR;
-
- memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
-
- /* Check AP vendor to move rtw_joinbss_cmd() */
-
- for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->ie_length;) {
- pIE = (struct ndis_802_11_var_ie *)(pnetwork->ies + i);
-
- switch (pIE->ElementID) {
- case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
- if (!memcmp(pIE->data, WMM_OUI, 4))
- pmlmeinfo->WMM_enable = 1;
- break;
- case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */
- pmlmeinfo->HT_caps_enable = 1;
- break;
- case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */
- pmlmeinfo->HT_info_enable = 1;
-
- /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
- {
- struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
-
- if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
- /* switch to the 40M Hz mode according to the AP */
- pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
- switch (pht_info->infos[0] & 0x3) {
- case 1:
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
- break;
- case 3:
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
- break;
- default:
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- break;
- }
-
- }
- }
- break;
- default:
- break;
- }
-
- i += (pIE->Length + 2);
- }
- /* disable dynamic functions, such as high power, DIG */
-
- /* config the initial gain under linking, need to write the BB registers */
-
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
- join_type = 0;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-
- /* cancel link timer */
- del_timer_sync(&pmlmeext->link_timer);
-
- start_clnt_join(padapter);
-
- return H2C_SUCCESS;
-}
-
-u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
- struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
- u8 val8;
-
- if (is_client_associated_to_ap(padapter))
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100);
-
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
-
- /* restore to initial setting. */
- update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
-
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
- /* Stop BCN */
- val8 = 0;
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
- }
-
- /* set MSR to no link state -> infra. mode */
- Set_MSR(padapter, _HW_STATE_STATION_);
-
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
-
- /* switch to the 20M Hz mode after disconnect */
- pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-
- flush_all_cam_entry(padapter);
-
- del_timer_sync(&pmlmeext->link_timer);
-
- rtw_free_uc_swdec_pending_queue(padapter);
-
- return H2C_SUCCESS;
-}
-
-static int rtw_scan_ch_decision(struct adapter *padapter,
- struct rtw_ieee80211_channel *out,
- u32 out_num,
- struct rtw_ieee80211_channel *in, u32 in_num)
-{
- int i, j;
- int set_idx;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- /* clear out first */
- memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num);
-
- /* acquire channels from in */
- j = 0;
- for (i = 0; i < in_num; i++) {
- set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
- if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
- set_idx >= 0) {
- out[j] = in[i];
-
- if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
- out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
-
- j++;
- }
- if (j >= out_num)
- break;
- }
-
- /* if out is empty, use channel_set as default */
- if (j == 0) {
- for (i = 0; i < pmlmeext->max_chan_nums; i++) {
- out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
-
- if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
- out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
-
- j++;
- }
- }
-
- return j;
-}
-
-u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
- u8 bdelayscan = false;
- u8 val8;
- u32 initialgain;
- u32 i;
-
- if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
- /* for first time sitesurvey_cmd */
- rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, NULL);
-
- pmlmeext->sitesurvey_res.state = SCAN_START;
- pmlmeext->sitesurvey_res.bss_cnt = 0;
- pmlmeext->sitesurvey_res.channel_idx = 0;
-
- for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (pparm->ssid[i].ssid_length) {
- memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
- pmlmeext->sitesurvey_res.ssid[i].ssid_length = pparm->ssid[i].ssid_length;
- } else {
- pmlmeext->sitesurvey_res.ssid[i].ssid_length = 0;
- }
- }
-
- pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
- , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
- , pparm->ch, pparm->ch_num
- );
-
- pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
-
- /* issue null data if associating to the AP */
- if (is_client_associated_to_ap(padapter)) {
- pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
-
- issue_nulldata(padapter, NULL, 1, 3, 500);
-
- bdelayscan = true;
- }
- if (bdelayscan) {
- /* delay 50ms to protect nulldata(1). */
- set_survey_timer(pmlmeext, 50);
- return H2C_SUCCESS;
- }
- }
-
- if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
- /* disable dynamic functions, such as high power, DIG */
- Save_DM_Func_Flag(padapter);
- Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
-
- /* config the initial gain under scanning, need to write the BB registers */
- initialgain = 0x1E;
-
- rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
-
- /* set MSR to no link state */
- Set_MSR(padapter, _HW_STATE_NOLINK_);
-
- val8 = 1; /* under site survey */
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-
- pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
- }
-
- site_survey(padapter);
-
- return H2C_SUCCESS;
-}
-
-u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
- struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- if (pparm->mode < 4)
- pmlmeinfo->auth_algo = pparm->mode;
- return H2C_SUCCESS;
-}
-
-u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
-{
- unsigned short ctrl;
- struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 null_sta[ETH_ALEN] = {};
-
- /* main tx key for wep. */
- if (pparm->set_tx)
- pmlmeinfo->key_index = pparm->keyid;
-
- /* write cam */
- ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
-
- write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
-
- return H2C_SUCCESS;
-}
-
-u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
-{
- u16 ctrl = 0;
- u8 cam_id;/* cam_entry */
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
-
- /* cam_entry: */
- /* 0~3 for default key */
-
- /* for concurrent mode (ap+sta): */
- /* default key is disable, using sw encrypt/decrypt */
- /* cam_entry = 4 for sta mode (macid = 0) */
- /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
-
- /* for concurrent mode (sta+sta): */
- /* default key is disable, using sw encrypt/decrypt */
- /* cam_entry = 4 mapping to macid = 0 */
- /* cam_entry = 5 mapping to macid = 2 */
-
- cam_id = 4;
-
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */ {
- clear_cam_entry(padapter, pparm->id);
- return H2C_SUCCESS_RSP;
- }
-
- psta = rtw_get_stainfo(pstapriv, pparm->addr);
- if (psta) {
- ctrl = BIT(15) | ((pparm->algorithm) << 2);
-
- if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA - 4)))
- return H2C_REJECTED;
-
- cam_id = psta->mac_id + 3;/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
-
- write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
-
- return H2C_SUCCESS_RSP;
- }
-
- return H2C_REJECTED;
- }
-
- /* below for sta mode */
-
- if (pparm->algorithm == _NO_PRIVACY_) { /* clear cam entry */
- clear_cam_entry(padapter, pparm->id);
- return H2C_SUCCESS;
- }
- ctrl = BIT(15) | ((pparm->algorithm) << 2);
- write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
- pmlmeinfo->enc_algo = pparm->algorithm;
- return H2C_SUCCESS;
-}
-
-u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
- struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
-
- if (!psta)
- return H2C_SUCCESS;
-
- if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
- ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
- issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
- mod_timer(&psta->addba_retry_timer,
- jiffies + msecs_to_jiffies(ADDBA_TO));
- } else {
- psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
- }
- return H2C_SUCCESS;
-}
-
-u8 set_tx_beacon_cmd(struct adapter *padapter)
-{
- struct cmd_obj *ph2c;
- struct wlan_bssid_ex *ptxBeacon_parm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- u8 res;
- int len_diff = 0;
-
- ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
- if (!ph2c) {
- res = _FAIL;
- goto exit;
- }
-
- ptxBeacon_parm = kmemdup(&pmlmeinfo->network,
- sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
- if (!ptxBeacon_parm) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
- len_diff = update_hidden_ssid(ptxBeacon_parm->ies + _BEACON_IE_OFFSET_,
- ptxBeacon_parm->ie_length - _BEACON_IE_OFFSET_,
- pmlmeinfo->hidden_ssid_mode);
- ptxBeacon_parm->ie_length += len_diff;
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, _TX_Beacon_CMD_);
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
- return res;
-}
-
-u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
- u8 evt_code;
- u16 evt_sz;
- uint *peventbuf;
- void (*event_callback)(struct adapter *dev, u8 *pbuf);
-
- peventbuf = (uint *)pbuf;
- evt_sz = (u16)(*peventbuf & 0xffff);
- evt_code = (u8)((*peventbuf >> 16) & 0xff);
-
- /* checking if event code is valid */
- if (evt_code >= MAX_C2HEVT)
- goto _abort_event_;
-
- /* checking if event size match the event parm size */
- if ((wlanevents[evt_code].parmsize != 0) &&
- (wlanevents[evt_code].parmsize != evt_sz))
- goto _abort_event_;
-
- peventbuf += 2;
-
- if (peventbuf) {
- event_callback = wlanevents[evt_code].event_callback;
- event_callback(padapter, (u8 *)peventbuf);
- }
-
-_abort_event_:
- return H2C_SUCCESS;
-}
-
-u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
- if (send_beacon(padapter) == _FAIL)
- return H2C_PARAMETERS_ERROR;
-#ifdef CONFIG_88EU_AP_MODE
- else { /* tx bc/mc frames after update TIM */
- struct sta_info *psta_bmc;
- struct list_head *xmitframe_phead;
- struct xmit_frame *pxmitframe, *n;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- /* for BC/MC Frames */
- psta_bmc = rtw_get_bcmc_stainfo(padapter);
- if (!psta_bmc)
- return H2C_SUCCESS;
-
- if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) {
- msleep(10);/* 10ms, ATIM(HIQ) Windows */
- spin_lock_bh(&psta_bmc->sleep_q.lock);
-
- xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
- list_for_each_entry_safe(pxmitframe, n, xmitframe_phead,
- list) {
- list_del_init(&pxmitframe->list);
-
- psta_bmc->sleepq_len--;
- if (psta_bmc->sleepq_len > 0)
- pxmitframe->attrib.mdata = 1;
- else
- pxmitframe->attrib.mdata = 0;
-
- pxmitframe->attrib.triggered = 1;
-
- pxmitframe->attrib.qsel = 0x11;/* HIQ */
-
- spin_unlock_bh(&psta_bmc->sleep_q.lock);
- if (rtw_hal_xmit(padapter, pxmitframe))
- rtw_os_xmit_complete(padapter, pxmitframe);
- spin_lock_bh(&psta_bmc->sleep_q.lock);
- }
- spin_unlock_bh(&psta_bmc->sleep_q.lock);
- }
- }
-#endif
- return H2C_SUCCESS;
-}
-
-u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
-{
- struct set_ch_parm *set_ch_parm;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
-
- set_ch_parm = (struct set_ch_parm *)pbuf;
-
- pmlmeext->cur_channel = set_ch_parm->ch;
- pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
- pmlmeext->cur_bwmode = set_ch_parm->bw;
-
- set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
-
- return H2C_SUCCESS;
-}
-
-u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
-{
- struct SetChannelPlan_param *setChannelPlan_param;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
-
- setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
-
- pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
- init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
-
- return H2C_SUCCESS;
-}
diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c
deleted file mode 100644
index 1b2cb6196463..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_security.c
+++ /dev/null
@@ -1,869 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTW_SECURITY_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <wifi.h>
-#include <osdep_intf.h>
-#include <net/lib80211.h>
-
-/* WEP related ===== */
-
-#define CRC32_POLY 0x04c11db7
-
-struct arc4context {
- u32 x;
- u32 y;
- u8 state[256];
-};
-
-static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len)
-{
- u32 t, u;
- u32 keyindex;
- u32 stateindex;
- u8 *state;
- u32 counter;
-
- state = parc4ctx->state;
- parc4ctx->x = 0;
- parc4ctx->y = 0;
- for (counter = 0; counter < 256; counter++)
- state[counter] = (u8)counter;
- keyindex = 0;
- stateindex = 0;
- for (counter = 0; counter < 256; counter++) {
- t = state[counter];
- stateindex = (stateindex + key[keyindex] + t) & 0xff;
- u = state[stateindex];
- state[stateindex] = (u8)t;
- state[counter] = (u8)u;
- if (++keyindex >= key_len)
- keyindex = 0;
- }
-}
-
-static u32 arcfour_byte(struct arc4context *parc4ctx)
-{
- u32 x;
- u32 y;
- u32 sx, sy;
- u8 *state;
-
- state = parc4ctx->state;
- x = (parc4ctx->x + 1) & 0xff;
- sx = state[x];
- y = (sx + parc4ctx->y) & 0xff;
- sy = state[y];
- parc4ctx->x = x;
- parc4ctx->y = y;
- state[y] = (u8)sx;
- state[x] = (u8)sy;
- return state[(sx + sy) & 0xff];
-}
-
-static void arcfour_encrypt(struct arc4context *parc4ctx, u8 *dest, u8 *src, u32 len)
-{
- u32 i;
-
- for (i = 0; i < len; i++)
- dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
-}
-
-static int bcrc32initialized;
-static u32 crc32_table[256];
-
-static u8 crc32_reverseBit(u8 data)
-{
- return (u8)((data << 7) & 0x80) | ((data << 5) & 0x40) | ((data << 3) & 0x20) |
- ((data << 1) & 0x10) | ((data >> 1) & 0x08) | ((data >> 3) & 0x04) |
- ((data >> 5) & 0x02) | ((data >> 7) & 0x01);
-}
-
-static void crc32_init(void)
-{
- int i, j;
- u32 c;
- u8 *p = (u8 *)&c, *p1;
- u8 k;
-
- if (bcrc32initialized == 1)
- return;
-
- c = 0x12340000;
-
- for (i = 0; i < 256; ++i) {
- k = crc32_reverseBit((u8)i);
- for (c = ((u32)k) << 24, j = 8; j > 0; --j)
- c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
- p1 = (u8 *)&crc32_table[i];
-
- p1[0] = crc32_reverseBit(p[3]);
- p1[1] = crc32_reverseBit(p[2]);
- p1[2] = crc32_reverseBit(p[1]);
- p1[3] = crc32_reverseBit(p[0]);
- }
- bcrc32initialized = 1;
-}
-
-static __le32 getcrc32(u8 *buf, int len)
-{
- u8 *p;
- u32 crc;
-
- if (bcrc32initialized == 0)
- crc32_init();
-
- crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
-
- for (p = buf; len > 0; ++p, --len)
- crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8);
- return cpu_to_le32(~crc); /* transmit complement, per CRC-32 spec */
-}
-
-/* Need to consider the fragment situation */
-void rtw_wep_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe)
-{
- int curfragnum, length;
- u8 *pframe;
- u8 hw_hdr_offset = 0;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- const int keyindex = psecuritypriv->dot11PrivacyKeyIndex;
- void *crypto_private;
- struct sk_buff *skb;
- struct lib80211_crypto_ops *crypto_ops;
-
- if (!pxmitframe->buf_addr)
- return;
-
- if ((pattrib->encrypt != _WEP40_) && (pattrib->encrypt != _WEP104_))
- return;
-
- hw_hdr_offset = TXDESC_SIZE +
- (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
-
- pframe = pxmitframe->buf_addr + hw_hdr_offset;
-
- crypto_ops = lib80211_get_crypto_ops("WEP");
-
- if (!crypto_ops)
- return;
-
- crypto_private = crypto_ops->init(keyindex);
- if (!crypto_private)
- return;
-
- if (crypto_ops->set_key(psecuritypriv->dot11DefKey[keyindex].skey,
- psecuritypriv->dot11DefKeylen[keyindex], NULL, crypto_private) < 0)
- goto free_crypto_private;
-
- for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
- if (curfragnum + 1 == pattrib->nr_frags)
- length = pattrib->last_txcmdsz;
- else
- length = pxmitpriv->frag_len;
- skb = dev_alloc_skb(length);
- if (!skb)
- goto free_crypto_private;
-
- skb_put_data(skb, pframe, length);
-
- memmove(skb->data + 4, skb->data, pattrib->hdrlen);
- skb_pull(skb, 4);
- skb_trim(skb, skb->len - 4);
-
- if (crypto_ops->encrypt_mpdu(skb, pattrib->hdrlen, crypto_private)) {
- kfree_skb(skb);
- goto free_crypto_private;
- }
-
- memcpy(pframe, skb->data, skb->len);
-
- pframe += skb->len;
- pframe = (u8 *)round_up((size_t)(pframe), 4);
-
- kfree_skb(skb);
- }
-
-free_crypto_private:
- crypto_ops->deinit(crypto_private);
-}
-
-int rtw_wep_decrypt(struct adapter *padapter, struct recv_frame *precvframe)
-{
- struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
-
- if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct sk_buff *skb = precvframe->pkt;
- u8 *pframe = skb->data;
- void *crypto_private = NULL;
- int status = _SUCCESS;
- const int keyindex = prxattrib->key_index;
- struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("WEP");
- char iv[4], icv[4];
-
- if (!crypto_ops) {
- status = _FAIL;
- goto exit;
- }
-
- memcpy(iv, pframe + prxattrib->hdrlen, 4);
- memcpy(icv, pframe + skb->len - 4, 4);
-
- crypto_private = crypto_ops->init(keyindex);
- if (!crypto_private) {
- status = _FAIL;
- goto exit;
- }
- if (crypto_ops->set_key(psecuritypriv->dot11DefKey[keyindex].skey,
- psecuritypriv->dot11DefKeylen[keyindex], NULL, crypto_private) < 0) {
- status = _FAIL;
- goto exit;
- }
- if (crypto_ops->decrypt_mpdu(skb, prxattrib->hdrlen, crypto_private)) {
- status = _FAIL;
- goto exit;
- }
-
- memmove(pframe, pframe + 4, prxattrib->hdrlen);
- skb_push(skb, 4);
- skb_put(skb, 4);
-
- memcpy(pframe + prxattrib->hdrlen, iv, 4);
- memcpy(pframe + skb->len - 4, icv, 4);
-
-exit:
- if (crypto_ops && crypto_private)
- crypto_ops->deinit(crypto_private);
- return status;
- }
-
- return _FAIL;
-}
-
-/* 3 ===== TKIP related ===== */
-
-static u32 secmicgetuint32(u8 *p)
-/* Convert from Byte[] to Us3232 in a portable way */
-{
- s32 i;
- u32 res = 0;
-
- for (i = 0; i < 4; i++)
- res |= ((u32)(*p++)) << (8 * i);
- return res;
-}
-
-static void secmicputuint32(u8 *p, u32 val)
-/* Convert from Us3232 to Byte[] in a portable way */
-{
- long i;
-
- for (i = 0; i < 4; i++) {
- *p++ = (u8)(val & 0xff);
- val >>= 8;
- }
-}
-
-static void secmicclear(struct mic_data *pmicdata)
-{
-/* Reset the state to the empty message. */
- pmicdata->L = pmicdata->K0;
- pmicdata->R = pmicdata->K1;
- pmicdata->nBytesInM = 0;
- pmicdata->M = 0;
-}
-
-void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key)
-{
- /* Set the key */
- pmicdata->K0 = secmicgetuint32(key);
- pmicdata->K1 = secmicgetuint32(key + 4);
- /* and reset the message */
- secmicclear(pmicdata);
-}
-
-void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b)
-{
- /* Append the byte to our word-sized buffer */
- pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM);
- pmicdata->nBytesInM++;
- /* Process the word if it is full. */
- if (pmicdata->nBytesInM >= 4) {
- pmicdata->L ^= pmicdata->M;
- pmicdata->R ^= ROL32(pmicdata->L, 17);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ROL32(pmicdata->L, 3);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ROR32(pmicdata->L, 2);
- pmicdata->L += pmicdata->R;
- /* Clear the buffer */
- pmicdata->M = 0;
- pmicdata->nBytesInM = 0;
- }
-}
-
-void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
-{
- /* This is simple */
- while (nbytes > 0) {
- rtw_secmicappendbyte(pmicdata, *src++);
- nbytes--;
- }
-}
-
-void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst)
-{
- /* Append the minimum padding */
- rtw_secmicappendbyte(pmicdata, 0x5a);
- rtw_secmicappendbyte(pmicdata, 0);
- rtw_secmicappendbyte(pmicdata, 0);
- rtw_secmicappendbyte(pmicdata, 0);
- rtw_secmicappendbyte(pmicdata, 0);
- /* and then zeroes until the length is a multiple of 4 */
- while (pmicdata->nBytesInM != 0)
- rtw_secmicappendbyte(pmicdata, 0);
- /* The appendByte function has already computed the result. */
- secmicputuint32(dst, pmicdata->L);
- secmicputuint32(dst + 4, pmicdata->R);
- /* Reset to the empty message. */
- secmicclear(pmicdata);
-}
-
-void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
-{
- struct mic_data micdata;
- u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
-
- rtw_secmicsetkey(&micdata, key);
- priority[0] = pri;
-
- /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
- if (header[1] & 1) { /* ToDS == 1 */
- rtw_secmicappend(&micdata, &header[16], 6); /* DA */
- if (header[1] & 2) /* From Ds == 1 */
- rtw_secmicappend(&micdata, &header[24], 6);
- else
- rtw_secmicappend(&micdata, &header[10], 6);
- } else { /* ToDS == 0 */
- rtw_secmicappend(&micdata, &header[4], 6); /* DA */
- if (header[1] & 2) /* From Ds == 1 */
- rtw_secmicappend(&micdata, &header[16], 6);
- else
- rtw_secmicappend(&micdata, &header[10], 6);
- }
- rtw_secmicappend(&micdata, &priority[0], 4);
-
- rtw_secmicappend(&micdata, data, data_len);
-
- rtw_secgetmic(&micdata, mic_code);
-}
-
-/* macros for extraction/creation of unsigned char/unsigned short values */
-#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
-#define Lo8(v16) ((u8)((v16) & 0x00FF))
-#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF))
-#define Lo16(v32) ((u16)((v32) & 0xFFFF))
-#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF))
-#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
-
-/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
-#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)])
-
-/* S-box lookup: 16 bits --> 16 bits */
-#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
-
-/* fixed algorithm "parameters" */
-#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
-#define TA_SIZE 6 /* 48-bit transmitter address */
-#define TK_SIZE 16 /* 128-bit temporal key */
-#define P1K_SIZE 10 /* 80-bit Phase1 key */
-#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
-
-/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
-static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in ROM) */
-{
- 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
- 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
- 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
- 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
- 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
- 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
- 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
- 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
- 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
- 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
- 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
- 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
- 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
- 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
- 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
- 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
- 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
- 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
- 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
- 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
- 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
- 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
- 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
- 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
- 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
- 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
- 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
- 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
- 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
- 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
- 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
- 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
- },
-
- { /* second half of table is unsigned char-reversed version of first! */
- 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
- 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
- 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
- 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
- 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
- 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
- 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
- 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
- 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
- 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
- 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
- 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
- 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
- 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
- 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
- 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
- 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
- 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
- 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
- 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
- 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
- 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
- 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
- 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
- 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
- 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
- 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
- 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
- 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
- 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
- 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
- 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
- }
-};
-
-/**
- * phase1() - generate P1K, given TA, TK, IV32
- * @p1k: placeholder for the returned phase 1 key
- * @tk: temporal key [128 bits]
- * @ta: transmitter's MAC address [ 48 bits]
- * @iv32: upper 32 bits of IV [ 32 bits]
- *
- * This function only needs to be called every 2**16 packets,
- * although in theory it could be called every packet.
- *
- * Return: p1k[] - Phase 1 key [ 80 bits]
- */
-static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
-{
- int i;
- /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
- p1k[0] = Lo16(iv32);
- p1k[1] = Hi16(iv32);
- p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
- p1k[3] = Mk16(ta[3], ta[2]);
- p1k[4] = Mk16(ta[5], ta[4]);
-
- /* Now compute an unbalanced Feistel cipher with 80-bit block */
- /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
- for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add operation here is mod 2**16 */
- p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0));
- p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2));
- p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4));
- p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6));
- p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0));
- p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
- }
-}
-
-/**
- * phase2() - generate RC4KEY, given TK, P1K, IV16
- * @rc4key: Placeholder for the returned key
- * @tk: Temporal key [128 bits]
- * @p1k: Phase 1 output key [ 80 bits]
- * @iv16: low 16 bits of IV counter [ 16 bits]
- *
- * The value {TA, IV32, IV16} for Phase1/Phase2 must be unique
- * across all packets using the same key TK value. Then, for a
- * given value of TK[], this TKIP48 construction guarantees that
- * the final RC4KEY value is unique across all packets.
- *
- * Suggested implementation optimization: if PPK[] is "overlaid"
- * appropriately on RC4KEY[], there is no need for the final
- * for loop below that copies the PPK[] result into RC4KEY[].
- *
- * Return: rc4key[] - the key used to encrypt the packet [128 bits]
- */
-static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
-{
- int i;
- u16 PPK[6]; /* temporary key for mixing */
- /* Note: all adds in the PPK[] equations below are mod 2**16 */
- for (i = 0; i < 5; i++)
- PPK[i] = p1k[i]; /* first, copy P1K to PPK */
- PPK[5] = p1k[4] + iv16; /* next, add in IV16 */
-
- /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
- PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
- PPK[1] += _S_(PPK[0] ^ TK16(1));
- PPK[2] += _S_(PPK[1] ^ TK16(2));
- PPK[3] += _S_(PPK[2] ^ TK16(3));
- PPK[4] += _S_(PPK[3] ^ TK16(4));
- PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
-
- /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
- PPK[0] += RotR1(PPK[5] ^ TK16(6));
- PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
- PPK[2] += RotR1(PPK[1]);
- PPK[3] += RotR1(PPK[2]);
- PPK[4] += RotR1(PPK[3]);
- PPK[5] += RotR1(PPK[4]);
- /* Note: At this point, for a given key TK[0..15], the 96-bit output */
- /* value PPK[0..5] is guaranteed to be unique, as a function */
- /* of the 96-bit "input" value {TA, IV32, IV16}. That is, P1K */
- /* is now a keyed permutation of {TA, IV32, IV16}. */
-
- /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */
- rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */
- rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
- rc4key[2] = Lo8(iv16);
- rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
-
- /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */
- for (i = 0; i < 6; i++) {
- rc4key[4 + 2 * i] = Lo8(PPK[i]);
- rc4key[5 + 2 * i] = Hi8(PPK[i]);
- }
-}
-
-/* The hlen isn't include the IV */
-u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe)
-{ /* exclude ICV */
- u16 pnl;
- u32 pnh;
- u8 rc4key[16];
- u8 ttkey[16];
- u8 crc[4];
- u8 hw_hdr_offset = 0;
- struct arc4context mycontext;
- int curfragnum, length;
-
- u8 *pframe, *payload, *iv, *prwskey;
- union pn48 dot11txpn;
- struct sta_info *stainfo;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u32 res = _SUCCESS;
-
- if (!pxmitframe->buf_addr)
- return _FAIL;
-
- hw_hdr_offset = TXDESC_SIZE +
- (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
- pframe = pxmitframe->buf_addr + hw_hdr_offset;
- /* 4 start to encrypt each fragment */
- if (pattrib->encrypt == _TKIP_) {
- if (pattrib->psta)
- stainfo = pattrib->psta;
- else
- stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]);
-
- if (stainfo) {
- if (is_multicast_ether_addr(pattrib->ra))
- prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
- else
- prwskey = &stainfo->dot118021x_UncstKey.skey[0];
-
- for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
- iv = pframe + pattrib->hdrlen;
- payload = pframe + pattrib->iv_len + pattrib->hdrlen;
-
- GET_TKIP_PN(iv, dot11txpn);
-
- pnl = (u16)(dot11txpn.val);
- pnh = (u32)(dot11txpn.val >> 16);
- phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh);
- phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
-
- if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */
- length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
- *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/
-
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload, payload, length);
- arcfour_encrypt(&mycontext, payload + length, crc, 4);
- } else {
- length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
- *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload, payload, length);
- arcfour_encrypt(&mycontext, payload + length, crc, 4);
-
- pframe += pxmitpriv->frag_len;
- pframe = (u8 *)round_up((size_t)(pframe), 4);
- }
- }
- } else {
- res = _FAIL;
- }
- }
- return res;
-}
-
-/* The hlen isn't include the IV */
-u32 rtw_tkip_decrypt(struct adapter *padapter, struct recv_frame *precvframe)
-{ /* exclude ICV */
- u16 pnl;
- u32 pnh;
- u8 rc4key[16];
- u8 ttkey[16];
- u8 crc[4];
- struct arc4context mycontext;
- int length;
- u8 *pframe, *payload, *iv, *prwskey;
- union pn48 dot11txpn;
- struct sta_info *stainfo;
- struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- u32 res = _SUCCESS;
-
- pframe = (unsigned char *)precvframe->pkt->data;
-
- /* 4 start to decrypt recvframe */
- if (prxattrib->encrypt == _TKIP_) {
- stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
- if (stainfo) {
- if (is_multicast_ether_addr(prxattrib->ra)) {
- if (!psecuritypriv->binstallGrpkey) {
- res = _FAIL;
- goto exit;
- }
- prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
- } else {
- prwskey = &stainfo->dot118021x_UncstKey.skey[0];
- }
-
- iv = pframe + prxattrib->hdrlen;
- payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
- length = precvframe->pkt->len - prxattrib->hdrlen - prxattrib->iv_len;
-
- GET_TKIP_PN(iv, dot11txpn);
-
- pnl = (u16)(dot11txpn.val);
- pnh = (u32)(dot11txpn.val >> 16);
-
- phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh);
- phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
-
- /* 4 decrypt payload include icv */
-
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload, payload, length);
-
- *((__le32 *)crc) = getcrc32(payload, length - 4);
-
- if (crc[3] != payload[length - 1] ||
- crc[2] != payload[length - 2] ||
- crc[1] != payload[length - 3] ||
- crc[0] != payload[length - 4])
- res = _FAIL;
- } else {
- res = _FAIL;
- }
- }
-exit:
- return res;
-}
-
-u32 rtw_aes_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe)
-{
- int curfragnum, length;
- u8 *pframe; /* *payload,*iv */
- u8 hw_hdr_offset = 0;
- struct sta_info *stainfo;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u32 res = _SUCCESS;
- void *crypto_private;
- struct sk_buff *skb;
- struct lib80211_crypto_ops *crypto_ops;
- const int key_idx = is_multicast_ether_addr(pattrib->ra) ? psecuritypriv->dot118021XGrpKeyid : 0;
- const int key_length = 16;
- u8 *key;
-
- if (!pxmitframe->buf_addr)
- return _FAIL;
-
- hw_hdr_offset = TXDESC_SIZE +
- (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
-
- pframe = pxmitframe->buf_addr + hw_hdr_offset;
-
- /* 4 start to encrypt each fragment */
- if (pattrib->encrypt != _AES_)
- return res;
-
- if (pattrib->psta)
- stainfo = pattrib->psta;
- else
- stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]);
-
- if (!stainfo)
- return _FAIL;
-
- crypto_ops = lib80211_get_crypto_ops("CCMP");
-
- if (is_multicast_ether_addr(pattrib->ra))
- key = psecuritypriv->dot118021XGrpKey[key_idx].skey;
- else
- key = stainfo->dot118021x_UncstKey.skey;
-
- if (!crypto_ops) {
- res = _FAIL;
- goto exit;
- }
-
- crypto_private = crypto_ops->init(key_idx);
- if (!crypto_private) {
- res = _FAIL;
- goto exit;
- }
-
- if (crypto_ops->set_key(key, key_length, NULL, crypto_private) < 0) {
- res = _FAIL;
- goto exit_crypto_ops_deinit;
- }
-
- for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
- if (curfragnum + 1 == pattrib->nr_frags)
- length = pattrib->last_txcmdsz;
- else
- length = pxmitpriv->frag_len;
-
- skb = dev_alloc_skb(length);
- if (!skb) {
- res = _FAIL;
- goto exit_crypto_ops_deinit;
- }
-
- skb_put_data(skb, pframe, length);
-
- memmove(skb->data + pattrib->iv_len, skb->data, pattrib->hdrlen);
- skb_pull(skb, pattrib->iv_len);
- skb_trim(skb, skb->len - pattrib->icv_len);
-
- if (crypto_ops->encrypt_mpdu(skb, pattrib->hdrlen, crypto_private)) {
- kfree_skb(skb);
- res = _FAIL;
- goto exit_crypto_ops_deinit;
- }
-
- memcpy(pframe, skb->data, skb->len);
-
- pframe += skb->len;
- pframe = (u8 *)round_up((size_t)(pframe), 8);
-
- kfree_skb(skb);
- }
-
-exit_crypto_ops_deinit:
- crypto_ops->deinit(crypto_private);
-
-exit:
- return res;
-}
-
-u32 rtw_aes_decrypt(struct adapter *padapter, struct recv_frame *precvframe)
-{
- struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
- u32 res = _SUCCESS;
-
- /* 4 start to encrypt each fragment */
- if (prxattrib->encrypt == _AES_) {
- struct sta_info *stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
-
- if (stainfo) {
- int key_idx;
- const int key_length = 16, iv_len = 8, icv_len = 8;
- struct sk_buff *skb = precvframe->pkt;
- void *crypto_private = NULL;
- u8 *key, *pframe = skb->data;
- struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("CCMP");
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- char iv[8], icv[8];
-
- if (is_multicast_ether_addr(prxattrib->ra)) {
- /* in concurrent we should use sw descrypt in group key, so we remove this message */
- if (!psecuritypriv->binstallGrpkey) {
- res = _FAIL;
- goto exit;
- }
- key_idx = psecuritypriv->dot118021XGrpKeyid;
- key = psecuritypriv->dot118021XGrpKey[key_idx].skey;
- } else {
- key_idx = 0;
- key = stainfo->dot118021x_UncstKey.skey;
- }
-
- if (!crypto_ops) {
- res = _FAIL;
- goto exit_lib80211_ccmp;
- }
-
- memcpy(iv, pframe + prxattrib->hdrlen, iv_len);
- memcpy(icv, pframe + skb->len - icv_len, icv_len);
-
- crypto_private = crypto_ops->init(key_idx);
- if (!crypto_private) {
- res = _FAIL;
- goto exit_lib80211_ccmp;
- }
- if (crypto_ops->set_key(key, key_length, NULL, crypto_private) < 0) {
- res = _FAIL;
- goto exit_lib80211_ccmp;
- }
- if (crypto_ops->decrypt_mpdu(skb, prxattrib->hdrlen, crypto_private)) {
- res = _FAIL;
- goto exit_lib80211_ccmp;
- }
-
- memmove(pframe, pframe + iv_len, prxattrib->hdrlen);
- skb_push(skb, iv_len);
- skb_put(skb, icv_len);
-
- memcpy(pframe + prxattrib->hdrlen, iv, iv_len);
- memcpy(pframe + skb->len - icv_len, icv, icv_len);
-
-exit_lib80211_ccmp:
- if (crypto_ops && crypto_private)
- crypto_ops->deinit(crypto_private);
- } else {
- res = _FAIL;
- }
- }
-exit:
- return res;
-}
diff --git a/drivers/staging/rtl8188eu/core/rtw_sreset.c b/drivers/staging/rtl8188eu/core/rtw_sreset.c
deleted file mode 100644
index a8397b132002..000000000000
--- a/drivers/staging/rtl8188eu/core/rtw_sreset.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <rtw_sreset.h>
-#include <usb_ops_linux.h>
-
-void rtw_hal_sreset_init(struct adapter *padapter)
-{
- struct sreset_priv *psrtpriv = &padapter->HalData->srestpriv;
-
- psrtpriv->wifi_error_status = WIFI_STATUS_SUCCESS;
-}
-
-void sreset_set_wifi_error_status(struct adapter *padapter, u32 status)
-{
- padapter->HalData->srestpriv.wifi_error_status = status;
-}
diff --git a/drivers/staging/rtl8188eu/hal/fw.c b/drivers/staging/rtl8188eu/hal/fw.c
deleted file mode 100644
index 3d1d29e9f8e0..000000000000
--- a/drivers/staging/rtl8188eu/hal/fw.c
+++ /dev/null
@@ -1,202 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-
-#include "fw.h"
-#include "drv_types.h"
-#include "usb_ops_linux.h"
-#include "rtl8188e_spec.h"
-#include "rtl8188e_hal.h"
-
-#include <linux/firmware.h>
-#include <linux/slab.h>
-
-static void _rtl88e_enable_fw_download(struct adapter *adapt, bool enable)
-{
- u8 tmp;
-
- if (enable) {
- tmp = usb_read8(adapt, REG_MCUFWDL);
- usb_write8(adapt, REG_MCUFWDL, tmp | 0x01);
-
- tmp = usb_read8(adapt, REG_MCUFWDL + 2);
- usb_write8(adapt, REG_MCUFWDL + 2, tmp & 0xf7);
- } else {
- tmp = usb_read8(adapt, REG_MCUFWDL);
- usb_write8(adapt, REG_MCUFWDL, tmp & 0xfe);
-
- usb_write8(adapt, REG_MCUFWDL + 1, 0x00);
- }
-}
-
-static void _rtl88e_fw_block_write(struct adapter *adapt,
- const u8 *buffer, u32 size)
-{
- u32 blk_sz = sizeof(u32);
- const u8 *byte_buffer;
- const u32 *dword_buffer = (u32 *)buffer;
- u32 i, write_address, blk_cnt, remain;
-
- blk_cnt = size / blk_sz;
- remain = size % blk_sz;
-
- write_address = FW_8192C_START_ADDRESS;
-
- for (i = 0; i < blk_cnt; i++, write_address += blk_sz)
- usb_write32(adapt, write_address, dword_buffer[i]);
-
- byte_buffer = buffer + blk_cnt * blk_sz;
- for (i = 0; i < remain; i++, write_address++)
- usb_write8(adapt, write_address, byte_buffer[i]);
-}
-
-static void _rtl88e_fw_page_write(struct adapter *adapt,
- u32 page, const u8 *buffer, u32 size)
-{
- u8 value8;
- u8 u8page = (u8)(page & 0x07);
-
- value8 = (usb_read8(adapt, REG_MCUFWDL + 2) & 0xF8) | u8page;
-
- usb_write8(adapt, (REG_MCUFWDL + 2), value8);
- _rtl88e_fw_block_write(adapt, buffer, size);
-}
-
-static void _rtl88e_write_fw(struct adapter *adapt, u8 *buffer, u32 size)
-{
- u8 *buf_ptr = buffer;
- u32 page_no, remain;
- u32 page, offset;
-
- page_no = size / FW_8192C_PAGE_SIZE;
- remain = size % FW_8192C_PAGE_SIZE;
-
- for (page = 0; page < page_no; page++) {
- offset = page * FW_8192C_PAGE_SIZE;
- _rtl88e_fw_page_write(adapt, page, (buf_ptr + offset),
- FW_8192C_PAGE_SIZE);
- }
-
- if (remain) {
- offset = page_no * FW_8192C_PAGE_SIZE;
- page = page_no;
- _rtl88e_fw_page_write(adapt, page, (buf_ptr + offset), remain);
- }
-}
-
-static void rtl88e_firmware_selfreset(struct adapter *adapt)
-{
- u8 u1b_tmp;
-
- u1b_tmp = usb_read8(adapt, REG_SYS_FUNC_EN + 1);
- usb_write8(adapt, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
- usb_write8(adapt, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
-}
-
-static int _rtl88e_fw_free_to_go(struct adapter *adapt)
-{
- int err = -EIO;
- u32 counter = 0;
- u32 value32;
-
- do {
- value32 = usb_read32(adapt, REG_MCUFWDL);
- if (value32 & FWDL_CHKSUM_RPT)
- break;
- } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
-
- if (counter >= POLLING_READY_TIMEOUT_COUNT)
- goto exit;
-
- value32 = usb_read32(adapt, REG_MCUFWDL);
- value32 |= MCUFWDL_RDY;
- value32 &= ~WINTINI_RDY;
- usb_write32(adapt, REG_MCUFWDL, value32);
-
- rtl88e_firmware_selfreset(adapt);
- counter = 0;
-
- do {
- value32 = usb_read32(adapt, REG_MCUFWDL);
- if (value32 & WINTINI_RDY) {
- err = 0;
- goto exit;
- }
-
- udelay(FW_8192C_POLLING_DELAY);
-
- } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
-
-exit:
- return err;
-}
-
-int rtl88eu_download_fw(struct adapter *adapt)
-{
- struct dvobj_priv *dvobj = adapter_to_dvobj(adapt);
- struct device *device = dvobj_to_dev(dvobj);
- const struct firmware *fw;
- static const char fw_name[] = "rtlwifi/rtl8188eufw.bin";
- struct rtl92c_firmware_header *pfwheader = NULL;
- u8 *download_data, *fw_data;
- size_t download_size;
- unsigned int trailing_zeros_length;
-
- if (request_firmware(&fw, fw_name, device)) {
- dev_err(device, "Firmware %s not available\n", fw_name);
- return -ENOENT;
- }
-
- if (fw->size > FW_8188E_SIZE) {
- dev_err(device, "Firmware size exceed 0x%X. Check it.\n",
- FW_8188E_SIZE);
- release_firmware(fw);
- return -1;
- }
-
- trailing_zeros_length = (4 - fw->size % 4) % 4;
-
- fw_data = kmalloc(fw->size + trailing_zeros_length, GFP_KERNEL);
- if (!fw_data) {
- release_firmware(fw);
- return -ENOMEM;
- }
-
- memcpy(fw_data, fw->data, fw->size);
- memset(fw_data + fw->size, 0, trailing_zeros_length);
-
- pfwheader = (struct rtl92c_firmware_header *)fw_data;
-
- if (IS_FW_HEADER_EXIST(pfwheader)) {
- download_data = fw_data + 32;
- download_size = fw->size + trailing_zeros_length - 32;
- } else {
- download_data = fw_data;
- download_size = fw->size + trailing_zeros_length;
- }
-
- release_firmware(fw);
-
- if (usb_read8(adapt, REG_MCUFWDL) & RAM_DL_SEL) {
- usb_write8(adapt, REG_MCUFWDL, 0);
- rtl88e_firmware_selfreset(adapt);
- }
- _rtl88e_enable_fw_download(adapt, true);
- usb_write8(adapt, REG_MCUFWDL,
- usb_read8(adapt, REG_MCUFWDL) | FWDL_CHKSUM_RPT);
- _rtl88e_write_fw(adapt, download_data, download_size);
- _rtl88e_enable_fw_download(adapt, false);
-
- kfree(fw_data);
- return _rtl88e_fw_free_to_go(adapt);
-}
diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c
deleted file mode 100644
index f09620c54e69..000000000000
--- a/drivers/staging/rtl8188eu/hal/hal_intf.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#define _HAL_INTF_C_
-#include <hal_intf.h>
-
-uint rtw_hal_init(struct adapter *adapt)
-{
- uint status = _SUCCESS;
-
- adapt->hw_init_completed = false;
-
- status = rtl8188eu_hal_init(adapt);
-
- if (status == _SUCCESS) {
- adapt->hw_init_completed = true;
-
- if (adapt->registrypriv.notch_filter == 1)
- rtw_hal_notch_filter(adapt, 1);
- } else {
- adapt->hw_init_completed = false;
- }
-
- return status;
-}
-
-uint rtw_hal_deinit(struct adapter *adapt)
-{
- uint status = _SUCCESS;
-
- status = rtl8188eu_hal_deinit(adapt);
-
- if (status == _SUCCESS)
- adapt->hw_init_completed = false;
-
- return status;
-}
-
-void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level)
-{
- struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
-
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
-#ifdef CONFIG_88EU_AP_MODE
- struct sta_info *psta = NULL;
- struct sta_priv *pstapriv = &adapt->stapriv;
-
- if (mac_id - 1 > 0)
- psta = pstapriv->sta_aid[mac_id - 2];
- if (psta)
- add_RATid(adapt, psta, 0);/* todo: based on rssi_level*/
-#endif
- } else {
- UpdateHalRAMask8188EUsb(adapt, mac_id, rssi_level);
- }
-}
diff --git a/drivers/staging/rtl8188eu/hal/mac_cfg.c b/drivers/staging/rtl8188eu/hal/mac_cfg.c
deleted file mode 100644
index 370aa5cc55a7..000000000000
--- a/drivers/staging/rtl8188eu/hal/mac_cfg.c
+++ /dev/null
@@ -1,120 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include "odm_precomp.h"
-#include "phy.h"
-
-/* MAC_REG.TXT */
-
-static u32 array_MAC_REG_8188E[] = {
- 0x026, 0x00000041,
- 0x027, 0x00000035,
- 0x428, 0x0000000A,
- 0x429, 0x00000010,
- 0x430, 0x00000000,
- 0x431, 0x00000001,
- 0x432, 0x00000002,
- 0x433, 0x00000004,
- 0x434, 0x00000005,
- 0x435, 0x00000006,
- 0x436, 0x00000007,
- 0x437, 0x00000008,
- 0x438, 0x00000000,
- 0x439, 0x00000000,
- 0x43A, 0x00000001,
- 0x43B, 0x00000002,
- 0x43C, 0x00000004,
- 0x43D, 0x00000005,
- 0x43E, 0x00000006,
- 0x43F, 0x00000007,
- 0x440, 0x0000005D,
- 0x441, 0x00000001,
- 0x442, 0x00000000,
- 0x444, 0x00000015,
- 0x445, 0x000000F0,
- 0x446, 0x0000000F,
- 0x447, 0x00000000,
- 0x458, 0x00000041,
- 0x459, 0x000000A8,
- 0x45A, 0x00000072,
- 0x45B, 0x000000B9,
- 0x460, 0x00000066,
- 0x461, 0x00000066,
- 0x480, 0x00000008,
- 0x4C8, 0x000000FF,
- 0x4C9, 0x00000008,
- 0x4CC, 0x000000FF,
- 0x4CD, 0x000000FF,
- 0x4CE, 0x00000001,
- 0x4D3, 0x00000001,
- 0x500, 0x00000026,
- 0x501, 0x000000A2,
- 0x502, 0x0000002F,
- 0x503, 0x00000000,
- 0x504, 0x00000028,
- 0x505, 0x000000A3,
- 0x506, 0x0000005E,
- 0x507, 0x00000000,
- 0x508, 0x0000002B,
- 0x509, 0x000000A4,
- 0x50A, 0x0000005E,
- 0x50B, 0x00000000,
- 0x50C, 0x0000004F,
- 0x50D, 0x000000A4,
- 0x50E, 0x00000000,
- 0x50F, 0x00000000,
- 0x512, 0x0000001C,
- 0x514, 0x0000000A,
- 0x516, 0x0000000A,
- 0x525, 0x0000004F,
- 0x550, 0x00000010,
- 0x551, 0x00000010,
- 0x559, 0x00000002,
- 0x55D, 0x000000FF,
- 0x605, 0x00000030,
- 0x608, 0x0000000E,
- 0x609, 0x0000002A,
- 0x620, 0x000000FF,
- 0x621, 0x000000FF,
- 0x622, 0x000000FF,
- 0x623, 0x000000FF,
- 0x624, 0x000000FF,
- 0x625, 0x000000FF,
- 0x626, 0x000000FF,
- 0x627, 0x000000FF,
- 0x652, 0x00000020,
- 0x63C, 0x0000000A,
- 0x63D, 0x0000000A,
- 0x63E, 0x0000000E,
- 0x63F, 0x0000000E,
- 0x640, 0x00000040,
- 0x66E, 0x00000005,
- 0x700, 0x00000021,
- 0x701, 0x00000043,
- 0x702, 0x00000065,
- 0x703, 0x00000087,
- 0x708, 0x00000021,
- 0x709, 0x00000043,
- 0x70A, 0x00000065,
- 0x70B, 0x00000087,
-};
-
-bool rtl88eu_phy_mac_config(struct adapter *adapt)
-{
- u32 i;
- u32 arraylength;
- u32 *ptrarray;
-
- arraylength = ARRAY_SIZE(array_MAC_REG_8188E);
- ptrarray = array_MAC_REG_8188E;
-
- for (i = 0; i < arraylength; i += 2)
- usb_write8(adapt, ptrarray[i], (u8)ptrarray[i + 1]);
-
- usb_write8(adapt, REG_MAX_AGGR_NUM, MAX_AGGR_NUM);
- return true;
-}
diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c
deleted file mode 100644
index ffc5394d5bb9..000000000000
--- a/drivers/staging/rtl8188eu/hal/odm.c
+++ /dev/null
@@ -1,966 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <linux/etherdevice.h>
-
-#include "odm_precomp.h"
-#include "phy.h"
-
-/* avoid to warn in FreeBSD ==> To DO modify */
-static u32 EDCAParam[HT_IOT_PEER_MAX][3] = {
- /* UL DL */
- {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */
- {0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */
- {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */
- {0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */
- {0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */
- {0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */
- {0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */
- {0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */
- {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP=> 92U AP */
- {0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */
-};
-
-/* Global var */
-u32 OFDMSwingTable[OFDM_TABLE_SIZE_92D] = {
- 0x7f8001fe, /* 0, +6.0dB */
- 0x788001e2, /* 1, +5.5dB */
- 0x71c001c7, /* 2, +5.0dB */
- 0x6b8001ae, /* 3, +4.5dB */
- 0x65400195, /* 4, +4.0dB */
- 0x5fc0017f, /* 5, +3.5dB */
- 0x5a400169, /* 6, +3.0dB */
- 0x55400155, /* 7, +2.5dB */
- 0x50800142, /* 8, +2.0dB */
- 0x4c000130, /* 9, +1.5dB */
- 0x47c0011f, /* 10, +1.0dB */
- 0x43c0010f, /* 11, +0.5dB */
- 0x40000100, /* 12, +0dB */
- 0x3c8000f2, /* 13, -0.5dB */
- 0x390000e4, /* 14, -1.0dB */
- 0x35c000d7, /* 15, -1.5dB */
- 0x32c000cb, /* 16, -2.0dB */
- 0x300000c0, /* 17, -2.5dB */
- 0x2d4000b5, /* 18, -3.0dB */
- 0x2ac000ab, /* 19, -3.5dB */
- 0x288000a2, /* 20, -4.0dB */
- 0x26000098, /* 21, -4.5dB */
- 0x24000090, /* 22, -5.0dB */
- 0x22000088, /* 23, -5.5dB */
- 0x20000080, /* 24, -6.0dB */
- 0x1e400079, /* 25, -6.5dB */
- 0x1c800072, /* 26, -7.0dB */
- 0x1b00006c, /* 27. -7.5dB */
- 0x19800066, /* 28, -8.0dB */
- 0x18000060, /* 29, -8.5dB */
- 0x16c0005b, /* 30, -9.0dB */
- 0x15800056, /* 31, -9.5dB */
- 0x14400051, /* 32, -10.0dB */
- 0x1300004c, /* 33, -10.5dB */
- 0x12000048, /* 34, -11.0dB */
- 0x11000044, /* 35, -11.5dB */
- 0x10000040, /* 36, -12.0dB */
- 0x0f00003c,/* 37, -12.5dB */
- 0x0e400039,/* 38, -13.0dB */
- 0x0d800036,/* 39, -13.5dB */
- 0x0cc00033,/* 40, -14.0dB */
- 0x0c000030,/* 41, -14.5dB */
- 0x0b40002d,/* 42, -15.0dB */
-};
-
-u8 CCKSwingTable_Ch1_Ch13[CCK_TABLE_SIZE][8] = {
- {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
- {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
- {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
- {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
- {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
- {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
- {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
- {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
- {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
- {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
- {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
- {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
- {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */
- {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
- {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
- {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
- {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
- {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
- {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
- {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
- {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */
- {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */
- {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */
- {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */
- {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */
- {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */
- {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */
- {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */
- {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */
- {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */
- {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */
- {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */
- {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */
-};
-
-u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8] = {
- {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
- {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
- {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
- {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
- {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
- {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
- {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
- {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
- {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
- {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
- {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
- {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
- {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */
- {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
- {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
- {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
- {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
- {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
- {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
- {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
- {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */
- {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */
- {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */
- {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */
- {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */
- {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */
- {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */
- {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */
- {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */
- {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */
- {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */
- {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */
- {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */
-};
-
-#define RxDefaultAnt1 0x65a9
-#define RxDefaultAnt2 0x569a
-
-/* 3 Export Interface */
-
-/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */
-void ODM_DMInit(struct odm_dm_struct *pDM_Odm)
-{
- /* 2012.05.03 Luke: For all IC series */
- odm_CommonInfoSelfInit(pDM_Odm);
- odm_DIGInit(pDM_Odm);
- odm_RateAdaptiveMaskInit(pDM_Odm);
-
- odm_DynamicTxPowerInit(pDM_Odm);
- odm_TXPowerTrackingInit(pDM_Odm);
- ODM_EdcaTurboInit(pDM_Odm);
- ODM_RAInfo_Init_all(pDM_Odm);
- if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
- (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
- (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
- odm_InitHybridAntDiv(pDM_Odm);
-}
-
-/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */
-/* You can not add any dummy function here, be care, you can only use DM structure */
-/* to perform any new ODM_DM. */
-void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm)
-{
- /* 2012.05.03 Luke: For all IC series */
- odm_CommonInfoSelfUpdate(pDM_Odm);
- odm_FalseAlarmCounterStatistics(pDM_Odm);
- odm_RSSIMonitorCheck(pDM_Odm);
-
- /* Fix Leave LPS issue */
- odm_DIG(pDM_Odm);
- odm_CCKPacketDetectionThresh(pDM_Odm);
-
- if (*pDM_Odm->pbPowerSaving)
- return;
-
- odm_RefreshRateAdaptiveMask(pDM_Odm);
-
- if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
- (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
- (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
- odm_HwAntDiv(pDM_Odm);
-
- ODM_TXPowerTrackingCheck(pDM_Odm);
- odm_EdcaTurboCheck(pDM_Odm);
-}
-
-void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u16 Index, void *pValue)
-{
- if (CmnInfo == ODM_CMNINFO_STA_STATUS)
- pDM_Odm->pODM_StaInfo[Index] = (struct sta_info *)pValue;
-}
-
-void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm)
-{
- struct adapter *adapter = pDM_Odm->Adapter;
-
- pDM_Odm->bCckHighPower = (bool)phy_query_bb_reg(adapter, 0x824, BIT(9));
- pDM_Odm->RFPathRxEnable = (u8)phy_query_bb_reg(adapter, 0xc04, 0x0F);
-}
-
-void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm)
-{
- u8 EntryCnt = 0;
- u8 i;
- struct sta_info *pEntry;
-
- if (*pDM_Odm->pBandWidth == ODM_BW40M) {
- if (*pDM_Odm->pSecChOffset == 1)
- pDM_Odm->ControlChannel = *pDM_Odm->pChannel - 2;
- else if (*pDM_Odm->pSecChOffset == 2)
- pDM_Odm->ControlChannel = *pDM_Odm->pChannel + 2;
- } else {
- pDM_Odm->ControlChannel = *pDM_Odm->pChannel;
- }
-
- for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
- pEntry = pDM_Odm->pODM_StaInfo[i];
- if (IS_STA_VALID(pEntry))
- EntryCnt++;
- }
- if (EntryCnt == 1)
- pDM_Odm->bOneEntryOnly = true;
- else
- pDM_Odm->bOneEntryOnly = false;
-}
-
-void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI)
-{
- struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
- struct adapter *adapter = pDM_Odm->Adapter;
-
- if (pDM_DigTable->CurIGValue != CurrentIGI) {
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, ODM_BIT_IGI_11N, CurrentIGI);
- pDM_DigTable->CurIGValue = CurrentIGI;
- }
-}
-
-void odm_DIGInit(struct odm_dm_struct *pDM_Odm)
-{
- struct adapter *adapter = pDM_Odm->Adapter;
- struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
-
- pDM_DigTable->CurIGValue = (u8)phy_query_bb_reg(adapter, ODM_REG_IGI_A_11N, ODM_BIT_IGI_11N);
- pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW;
- pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH;
- pDM_DigTable->FALowThresh = DM_false_ALARM_THRESH_LOW;
- pDM_DigTable->FAHighThresh = DM_false_ALARM_THRESH_HIGH;
- pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
- pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
- pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
- pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
- pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
- pDM_DigTable->PreCCK_CCAThres = 0xFF;
- pDM_DigTable->CurCCK_CCAThres = 0x83;
- pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
- pDM_DigTable->LargeFAHit = 0;
- pDM_DigTable->Recover_cnt = 0;
- pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
- pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
- pDM_DigTable->bMediaConnect_0 = false;
- pDM_DigTable->bMediaConnect_1 = false;
-
- /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
- pDM_Odm->bDMInitialGainEnable = true;
-}
-
-void odm_DIG(struct odm_dm_struct *pDM_Odm)
-{
- struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
- struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
- u8 DIG_Dynamic_MIN;
- u8 DIG_MaxOfMin;
- bool FirstConnect, FirstDisConnect;
- u8 dm_dig_max, dm_dig_min;
- u8 CurrentIGI = pDM_DigTable->CurIGValue;
-
- if ((!(pDM_Odm->SupportAbility & ODM_BB_DIG)) || (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)))
- return;
-
- if (*pDM_Odm->pbScanInProcess)
- return;
-
- /* add by Neil Chen to avoid PSD is processing */
- if (!pDM_Odm->bDMInitialGainEnable)
- return;
-
- DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
- FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0);
- FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0);
-
- /* 1 Boundary Decision */
- dm_dig_max = DM_DIG_MAX_NIC;
- dm_dig_min = DM_DIG_MIN_NIC;
- DIG_MaxOfMin = DM_DIG_MAX_AP;
-
- if (pDM_Odm->bLinked) {
- /* 2 Modify DIG upper bound */
- if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max)
- pDM_DigTable->rx_gain_range_max = dm_dig_max;
- else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min)
- pDM_DigTable->rx_gain_range_max = dm_dig_min;
- else
- pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20;
- /* 2 Modify DIG lower bound */
- if (pDM_Odm->bOneEntryOnly) {
- if (pDM_Odm->RSSI_Min < dm_dig_min)
- DIG_Dynamic_MIN = dm_dig_min;
- else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
- DIG_Dynamic_MIN = DIG_MaxOfMin;
- else
- DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
- } else if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) {
- /* 1 Lower Bound for 88E AntDiv */
- if (pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV)
- DIG_Dynamic_MIN = (u8)pDM_DigTable->AntDiv_RSSI_max;
- } else {
- DIG_Dynamic_MIN = dm_dig_min;
- }
- } else {
- pDM_DigTable->rx_gain_range_max = dm_dig_max;
- DIG_Dynamic_MIN = dm_dig_min;
- }
-
- /* 1 Modify DIG lower bound, deal with abnormally large false alarm */
- if (pFalseAlmCnt->Cnt_all > 10000) {
- if (pDM_DigTable->LargeFAHit != 3)
- pDM_DigTable->LargeFAHit++;
- if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
- pDM_DigTable->ForbiddenIGI = CurrentIGI;
- pDM_DigTable->LargeFAHit = 1;
- }
-
- if (pDM_DigTable->LargeFAHit >= 3) {
- if ((pDM_DigTable->ForbiddenIGI + 1) > pDM_DigTable->rx_gain_range_max)
- pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
- else
- pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
- pDM_DigTable->Recover_cnt = 3600; /* 3600=2hr */
- }
-
- } else {
- /* Recovery mechanism for IGI lower bound */
- if (pDM_DigTable->Recover_cnt != 0) {
- pDM_DigTable->Recover_cnt--;
- } else {
- if (pDM_DigTable->LargeFAHit < 3) {
- if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */
- pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
- pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
- } else {
- pDM_DigTable->ForbiddenIGI--;
- pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
- }
- } else {
- pDM_DigTable->LargeFAHit = 0;
- }
- }
- }
-
- /* 1 Adjust initial gain by false alarm */
- if (pDM_Odm->bLinked) {
- if (FirstConnect) {
- CurrentIGI = pDM_Odm->RSSI_Min;
- } else {
- if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2)
- CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
- else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1)
- CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
- else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0)
- CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */
- }
- } else {
- if (FirstDisConnect) {
- CurrentIGI = pDM_DigTable->rx_gain_range_min;
- } else {
- /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */
- if (pFalseAlmCnt->Cnt_all > 10000)
- CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
- else if (pFalseAlmCnt->Cnt_all > 8000)
- CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
- else if (pFalseAlmCnt->Cnt_all < 500)
- CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */
- }
- }
- /* 1 Check initial gain by upper/lower bound */
- if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
- CurrentIGI = pDM_DigTable->rx_gain_range_max;
- if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
- CurrentIGI = pDM_DigTable->rx_gain_range_min;
-
- /* 2 High power RSSI threshold */
- ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
- pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
- pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
-}
-
-/* 3============================================================ */
-/* 3 FASLE ALARM CHECK */
-/* 3============================================================ */
-
-void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
-{
- struct adapter *adapter = pDM_Odm->Adapter;
- u32 ret_value;
- struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
-
- if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
- return;
-
- /* hold ofdm counter */
- phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */
- phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */
-
- ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
- FalseAlmCnt->Cnt_Fast_Fsync = (ret_value & 0xffff);
- FalseAlmCnt->Cnt_SB_Search_fail = (ret_value & 0xffff0000) >> 16;
- ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
- FalseAlmCnt->Cnt_OFDM_CCA = (ret_value & 0xffff);
- FalseAlmCnt->Cnt_Parity_Fail = (ret_value & 0xffff0000) >> 16;
- ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
- FalseAlmCnt->Cnt_Rate_Illegal = (ret_value & 0xffff);
- FalseAlmCnt->Cnt_Crc8_fail = (ret_value & 0xffff0000) >> 16;
- ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
- FalseAlmCnt->Cnt_Mcs_fail = (ret_value & 0xffff);
-
- FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal +
- FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail +
- FalseAlmCnt->Cnt_Fast_Fsync + FalseAlmCnt->Cnt_SB_Search_fail;
-
- ret_value = phy_query_bb_reg(adapter, ODM_REG_SC_CNT_11N, bMaskDWord);
- FalseAlmCnt->Cnt_BW_LSC = (ret_value & 0xffff);
- FalseAlmCnt->Cnt_BW_USC = (ret_value & 0xffff0000) >> 16;
-
- /* hold cck counter */
- phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(12), 1);
- phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(14), 1);
-
- ret_value = phy_query_bb_reg(adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
- FalseAlmCnt->Cnt_Cck_fail = ret_value;
- ret_value = phy_query_bb_reg(adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3);
- FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff) << 8;
-
- ret_value = phy_query_bb_reg(adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
- FalseAlmCnt->Cnt_CCK_CCA = ((ret_value & 0xFF) << 8) | ((ret_value & 0xFF00) >> 8);
-
- FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync +
- FalseAlmCnt->Cnt_SB_Search_fail +
- FalseAlmCnt->Cnt_Parity_Fail +
- FalseAlmCnt->Cnt_Rate_Illegal +
- FalseAlmCnt->Cnt_Crc8_fail +
- FalseAlmCnt->Cnt_Mcs_fail +
- FalseAlmCnt->Cnt_Cck_fail);
-
- FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
-}
-
-/* 3============================================================ */
-/* 3 CCK Packet Detect Threshold */
-/* 3============================================================ */
-
-void odm_CCKPacketDetectionThresh(struct odm_dm_struct *pDM_Odm)
-{
- u8 CurCCK_CCAThres;
- struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
-
- if (!(pDM_Odm->SupportAbility & (ODM_BB_CCK_PD | ODM_BB_FA_CNT)))
- return;
- if (pDM_Odm->ExtLNA)
- return;
- if (pDM_Odm->bLinked) {
- if (pDM_Odm->RSSI_Min > 25) {
- CurCCK_CCAThres = 0xcd;
- } else if (pDM_Odm->RSSI_Min > 10) {
- CurCCK_CCAThres = 0x83;
- } else {
- if (FalseAlmCnt->Cnt_Cck_fail > 1000)
- CurCCK_CCAThres = 0x83;
- else
- CurCCK_CCAThres = 0x40;
- }
- } else {
- if (FalseAlmCnt->Cnt_Cck_fail > 1000)
- CurCCK_CCAThres = 0x83;
- else
- CurCCK_CCAThres = 0x40;
- }
- ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres);
-}
-
-void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres)
-{
- struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
- struct adapter *adapt = pDM_Odm->Adapter;
-
- if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) /* modify by Guo.Mingzhi 2012-01-03 */
- usb_write8(adapt, ODM_REG_CCK_CCA_11N, CurCCK_CCAThres);
- pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
- pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
-}
-
-void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal)
-{
- struct adapter *adapter = pDM_Odm->Adapter;
- struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable;
- u8 Rssi_Up_bound = 30;
- u8 Rssi_Low_bound = 25;
-
- if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */
- Rssi_Up_bound = 50;
- Rssi_Low_bound = 45;
- }
- if (pDM_PSTable->initialize == 0) {
- pDM_PSTable->Reg874 = (phy_query_bb_reg(adapter, 0x874, bMaskDWord) & 0x1CC000) >> 14;
- pDM_PSTable->RegC70 = (phy_query_bb_reg(adapter, 0xc70, bMaskDWord) & BIT(3)) >> 3;
- pDM_PSTable->Reg85C = (phy_query_bb_reg(adapter, 0x85c, bMaskDWord) & 0xFF000000) >> 24;
- pDM_PSTable->RegA74 = (phy_query_bb_reg(adapter, 0xa74, bMaskDWord) & 0xF000) >> 12;
- pDM_PSTable->initialize = 1;
- }
-
- if (!bForceInNormal) {
- if (pDM_Odm->RSSI_Min != 0xFF) {
- if (pDM_PSTable->PreRFState == RF_Normal) {
- if (pDM_Odm->RSSI_Min >= Rssi_Up_bound)
- pDM_PSTable->CurRFState = RF_Save;
- else
- pDM_PSTable->CurRFState = RF_Normal;
- } else {
- if (pDM_Odm->RSSI_Min <= Rssi_Low_bound)
- pDM_PSTable->CurRFState = RF_Normal;
- else
- pDM_PSTable->CurRFState = RF_Save;
- }
- } else {
- pDM_PSTable->CurRFState = RF_MAX;
- }
- } else {
- pDM_PSTable->CurRFState = RF_Normal;
- }
-
- if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) {
- if (pDM_PSTable->CurRFState == RF_Save) {
- phy_set_bb_reg(adapter, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]=3'b010 */
- phy_set_bb_reg(adapter, 0xc70, BIT(3), 0); /* RegC70[3]=1'b0 */
- phy_set_bb_reg(adapter, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]=0x63 */
- phy_set_bb_reg(adapter, 0x874, 0xC000, 0x2); /* Reg874[15:14]=2'b10 */
- phy_set_bb_reg(adapter, 0xa74, 0xF000, 0x3); /* RegA75[7:4]=0x3 */
- phy_set_bb_reg(adapter, 0x818, BIT(28), 0x0); /* Reg818[28]=1'b0 */
- phy_set_bb_reg(adapter, 0x818, BIT(28), 0x1); /* Reg818[28]=1'b1 */
- } else {
- phy_set_bb_reg(adapter, 0x874, 0x1CC000, pDM_PSTable->Reg874);
- phy_set_bb_reg(adapter, 0xc70, BIT(3), pDM_PSTable->RegC70);
- phy_set_bb_reg(adapter, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
- phy_set_bb_reg(adapter, 0xa74, 0xF000, pDM_PSTable->RegA74);
- phy_set_bb_reg(adapter, 0x818, BIT(28), 0x0);
- }
- pDM_PSTable->PreRFState = pDM_PSTable->CurRFState;
- }
-}
-
-/* 3============================================================ */
-/* 3 RATR MASK */
-/* 3============================================================ */
-/* 3============================================================ */
-/* 3 Rate Adaptive */
-/* 3============================================================ */
-
-void odm_RateAdaptiveMaskInit(struct odm_dm_struct *pDM_Odm)
-{
- struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive;
-
- pOdmRA->Type = DM_Type_ByDriver;
- if (pOdmRA->Type == DM_Type_ByDriver)
- pDM_Odm->bUseRAMask = true;
- else
- pDM_Odm->bUseRAMask = false;
-
- pOdmRA->RATRState = DM_RATR_STA_INIT;
- pOdmRA->HighRSSIThresh = 50;
- pOdmRA->LowRSSIThresh = 20;
-}
-
-u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, u32 ra_mask, u8 rssi_level)
-{
- struct sta_info *pEntry;
- u32 rate_bitmap = 0x0fffffff;
- u8 WirelessMode;
-
- pEntry = pDM_Odm->pODM_StaInfo[macid];
- if (!IS_STA_VALID(pEntry))
- return ra_mask;
-
- WirelessMode = pEntry->wireless_mode;
-
- switch (WirelessMode) {
- case ODM_WM_B:
- if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */
- rate_bitmap = 0x0000000d;
- else
- rate_bitmap = 0x0000000f;
- break;
- case (ODM_WM_A | ODM_WM_G):
- if (rssi_level == DM_RATR_STA_HIGH)
- rate_bitmap = 0x00000f00;
- else
- rate_bitmap = 0x00000ff0;
- break;
- case (ODM_WM_B | ODM_WM_G):
- if (rssi_level == DM_RATR_STA_HIGH)
- rate_bitmap = 0x00000f00;
- else if (rssi_level == DM_RATR_STA_MIDDLE)
- rate_bitmap = 0x00000ff0;
- else
- rate_bitmap = 0x00000ff5;
- break;
- case (ODM_WM_B | ODM_WM_G | ODM_WM_N24G):
- case (ODM_WM_A | ODM_WM_B | ODM_WM_G | ODM_WM_N24G):
- if (rssi_level == DM_RATR_STA_HIGH) {
- rate_bitmap = 0x000f0000;
- } else if (rssi_level == DM_RATR_STA_MIDDLE) {
- rate_bitmap = 0x000ff000;
- } else {
- if (*pDM_Odm->pBandWidth == ODM_BW40M)
- rate_bitmap = 0x000ff015;
- else
- rate_bitmap = 0x000ff005;
- }
- break;
- default:
- /* case WIRELESS_11_24N: */
- /* case WIRELESS_11_5N: */
- rate_bitmap = 0x0fffffff;
- break;
- }
-
- return rate_bitmap;
-}
-
-/* Update rate table mask according to rssi */
-void odm_RefreshRateAdaptiveMask(struct odm_dm_struct *pDM_Odm)
-{
- if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK))
- return;
- /* */
- /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
- /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
- /* HW dynamic mechanism. */
- /* */
- odm_RefreshRateAdaptiveMaskCE(pDM_Odm);
-}
-
-void odm_RefreshRateAdaptiveMaskCE(struct odm_dm_struct *pDM_Odm)
-{
- u8 i;
- struct adapter *pAdapter = pDM_Odm->Adapter;
-
- if (pAdapter->bDriverStopped)
- return;
-
- if (!pDM_Odm->bUseRAMask)
- return;
-
- for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
- struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i];
-
- if (IS_STA_VALID(pstat)) {
- if (ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level))
- rtw_hal_update_ra_mask(pAdapter, i, pstat->rssi_level);
- }
- }
-}
-
-/* Return Value: bool */
-/* - true: RATRState is changed. */
-bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate, u8 *pRATRState)
-{
- struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive;
- const u8 GoUpGap = 5;
- u8 HighRSSIThreshForRA = pRA->HighRSSIThresh;
- u8 LowRSSIThreshForRA = pRA->LowRSSIThresh;
- u8 RATRState;
- struct device *dev = dvobj_to_dev(adapter_to_dvobj(pDM_Odm->Adapter));
-
- /* Threshold Adjustment: */
- /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */
- /* Here GoUpGap is added to solve the boundary's level alternation issue. */
- switch (*pRATRState) {
- case DM_RATR_STA_INIT:
- case DM_RATR_STA_HIGH:
- break;
- case DM_RATR_STA_MIDDLE:
- HighRSSIThreshForRA += GoUpGap;
- break;
- case DM_RATR_STA_LOW:
- HighRSSIThreshForRA += GoUpGap;
- LowRSSIThreshForRA += GoUpGap;
- break;
- default:
- dev_err(dev, "%s(): wrong rssi level setting %d!\n", __func__, *pRATRState);
- break;
- }
-
- /* Decide RATRState by RSSI. */
- if (HighRSSIThreshForRA < RSSI)
- RATRState = DM_RATR_STA_HIGH;
- else if (LowRSSIThreshForRA < RSSI)
- RATRState = DM_RATR_STA_MIDDLE;
- else
- RATRState = DM_RATR_STA_LOW;
-
- if (*pRATRState != RATRState || bForceUpdate) {
- *pRATRState = RATRState;
- return true;
- }
- return false;
-}
-
-/* 3============================================================ */
-/* 3 Dynamic Tx Power */
-/* 3============================================================ */
-
-void odm_DynamicTxPowerInit(struct odm_dm_struct *pDM_Odm)
-{
- struct adapter *Adapter = pDM_Odm->Adapter;
- struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv;
-
- pdmpriv->bDynamicTxPowerEnable = false;
- pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal;
- pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
-}
-
-/* 3============================================================ */
-/* 3 RSSI Monitor */
-/* 3============================================================ */
-
-void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm)
-{
- if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
- return;
-
- /* */
- /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
- /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
- /* HW dynamic mechanism. */
- /* */
- odm_RSSIMonitorCheckCE(pDM_Odm);
-} /* odm_RSSIMonitorCheck */
-
-static void FindMinimumRSSI(struct adapter *pAdapter)
-{
- struct dm_priv *pdmpriv = &pAdapter->HalData->dmpriv;
-
- /* 1 1.Unconditionally set RSSI */
- pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
-}
-
-void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm)
-{
- struct adapter *Adapter = pDM_Odm->Adapter;
- struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv;
- int i;
- int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff;
- u8 sta_cnt = 0;
- u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */
- struct sta_info *psta;
-
- if (!check_fwstate(&Adapter->mlmepriv, _FW_LINKED))
- return;
-
- for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
- psta = pDM_Odm->pODM_StaInfo[i];
- if (IS_STA_VALID(psta) &&
- (psta->state & WIFI_ASOC_STATE) &&
- !is_broadcast_ether_addr(psta->hwaddr) &&
- memcmp(psta->hwaddr, myid(&Adapter->eeprompriv), ETH_ALEN)) {
- if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
- tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
-
- if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB)
- tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
- if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1))
- PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB << 16));
- }
- }
-
- for (i = 0; i < sta_cnt; i++) {
- if (PWDB_rssi[i] != 0) {
- ODM_RA_SetRSSI_8188E(&Adapter->HalData->odmpriv,
- PWDB_rssi[i] & 0xFF,
- (PWDB_rssi[i] >> 16) & 0xFF);
- }
- }
-
- if (tmpEntryMaxPWDB != 0) /* If associated entry is found */
- pdmpriv->EntryMaxUndecoratedSmoothedPWDB = tmpEntryMaxPWDB;
- else
- pdmpriv->EntryMaxUndecoratedSmoothedPWDB = 0;
-
- if (tmpEntryMinPWDB != 0xff) /* If associated entry is found */
- pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB;
- else
- pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0;
-
- FindMinimumRSSI(Adapter);
- Adapter->HalData->odmpriv.RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM;
-}
-
-/* 3============================================================ */
-/* 3 Tx Power Tracking */
-/* 3============================================================ */
-
-void odm_TXPowerTrackingInit(struct odm_dm_struct *pDM_Odm)
-{
- pDM_Odm->RFCalibrateInfo.bTXPowerTracking = true;
- pDM_Odm->RFCalibrateInfo.TXPowercount = 0;
- if (*pDM_Odm->mp_mode != 1)
- pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
-
- pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
-}
-
-void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm)
-{
- /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
- /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
- /* HW dynamic mechanism. */
- struct adapter *Adapter = pDM_Odm->Adapter;
-
- if (!(pDM_Odm->SupportAbility & ODM_RF_TX_PWR_TRACK))
- return;
-
- if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) { /* at least delay 1 sec */
- phy_set_rf_reg(Adapter, RF_PATH_A, RF_T_METER_88E, BIT(17) | BIT(16), 0x03);
-
- pDM_Odm->RFCalibrateInfo.TM_Trigger = 1;
- return;
- }
-
- rtl88eu_dm_txpower_tracking_callback_thermalmeter(Adapter);
- pDM_Odm->RFCalibrateInfo.TM_Trigger = 0;
-}
-
-/* 3============================================================ */
-/* 3 SW Antenna Diversity */
-/* 3============================================================ */
-
-void odm_InitHybridAntDiv(struct odm_dm_struct *pDM_Odm)
-{
- if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV))
- return;
-
- rtl88eu_dm_antenna_div_init(pDM_Odm);
-}
-
-void odm_HwAntDiv(struct odm_dm_struct *pDM_Odm)
-{
- if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV))
- return;
-
- rtl88eu_dm_antenna_diversity(pDM_Odm);
-}
-
-/* EDCA Turbo */
-void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm)
-{
- struct adapter *Adapter = pDM_Odm->Adapter;
-
- pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
- pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
- Adapter->recvpriv.bIsAnyNonBEPkts = false;
-} /* ODM_InitEdcaTurbo */
-
-void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm)
-{
- /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
- /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
- /* HW dynamic mechanism. */
- if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO))
- return;
-
- odm_EdcaTurboCheckCE(pDM_Odm);
-} /* odm_CheckEdcaTurbo */
-
-void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm)
-{
- struct adapter *Adapter = pDM_Odm->Adapter;
- u32 trafficIndex;
- u32 edca_param;
- u64 cur_tx_bytes = 0;
- u64 cur_rx_bytes = 0;
- u8 bbtchange = false;
- struct xmit_priv *pxmitpriv = &Adapter->xmitpriv;
- struct recv_priv *precvpriv = &Adapter->recvpriv;
- struct registry_priv *pregpriv = &Adapter->registrypriv;
- struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- if (pregpriv->wifi_spec == 1) /* (pmlmeinfo->HT_enable == 0)) */
- goto dm_CheckEdcaTurbo_EXIT;
-
- if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX)
- goto dm_CheckEdcaTurbo_EXIT;
-
- /* Check if the status needs to be changed. */
- if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) {
- cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes;
- cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes;
-
- /* traffic, TX or RX */
- if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) ||
- (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) {
- if (cur_tx_bytes > (cur_rx_bytes << 2)) {
- /* Uplink TP is present. */
- trafficIndex = UP_LINK;
- } else {
- /* Balance TP is present. */
- trafficIndex = DOWN_LINK;
- }
- } else {
- if (cur_rx_bytes > (cur_tx_bytes << 2)) {
- /* Downlink TP is present. */
- trafficIndex = DOWN_LINK;
- } else {
- /* Balance TP is present. */
- trafficIndex = UP_LINK;
- }
- }
-
- if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) || (!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) {
- if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) && (pmlmeext->cur_wireless_mode & WIRELESS_11_24N))
- edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex];
- else
- edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex];
-
- usb_write32(Adapter, REG_EDCA_BE_PARAM, edca_param);
-
- pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex;
- }
-
- pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true;
- } else {
- /* Turn Off EDCA turbo here. */
- /* Restore original EDCA according to the declaration of AP. */
- if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) {
- usb_write32(Adapter, REG_EDCA_BE_PARAM,
- Adapter->HalData->AcParam_BE);
- pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
- }
- }
-
-dm_CheckEdcaTurbo_EXIT:
- /* Set variables for next time. */
- precvpriv->bIsAnyNonBEPkts = false;
- pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes;
- precvpriv->last_rx_bytes = precvpriv->rx_bytes;
-}
diff --git a/drivers/staging/rtl8188eu/hal/odm_hwconfig.c b/drivers/staging/rtl8188eu/hal/odm_hwconfig.c
deleted file mode 100644
index 684b6cec0f09..000000000000
--- a/drivers/staging/rtl8188eu/hal/odm_hwconfig.c
+++ /dev/null
@@ -1,397 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include "odm_precomp.h"
-
-#define READ_AND_CONFIG READ_AND_CONFIG_MP
-
-#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig##txt##ic(dm_odm))
-#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(dm_odm))
-
-static u8 odm_query_rxpwrpercentage(s8 antpower)
-{
- if ((antpower <= -100) || (antpower >= 20))
- return 0;
- else if (antpower >= 0)
- return 100;
- else
- return 100 + antpower;
-}
-
-/* 2012/01/12 MH MOve some signal strength smooth method to MP HAL layer. */
-/* IF other SW team do not support the feature, remove this section.?? */
-static s32 odm_signal_scale_mapping(struct odm_dm_struct *dm_odm, s32 currsig)
-{
- s32 retsig = 0;
-
- if (currsig >= 51 && currsig <= 100)
- retsig = 100;
- else if (currsig >= 41 && currsig <= 50)
- retsig = 80 + ((currsig - 40) * 2);
- else if (currsig >= 31 && currsig <= 40)
- retsig = 66 + (currsig - 30);
- else if (currsig >= 21 && currsig <= 30)
- retsig = 54 + (currsig - 20);
- else if (currsig >= 10 && currsig <= 20)
- retsig = 42 + (((currsig - 10) * 2) / 3);
- else if (currsig >= 5 && currsig <= 9)
- retsig = 22 + (((currsig - 5) * 3) / 2);
- else if (currsig >= 1 && currsig <= 4)
- retsig = 6 + (((currsig - 1) * 3) / 2);
- else
- retsig = currsig;
-
- return retsig;
-}
-
-static u8 odm_evm_db_to_percentage(s8 value)
-{
- /* -33dB~0dB to 0%~99% */
- s8 ret_val = clamp(-value, 0, 33) * 3;
-
- if (ret_val == 99)
- ret_val = 100;
-
- return ret_val;
-}
-
-static void odm_RxPhyStatus92CSeries_Parsing(struct odm_dm_struct *dm_odm,
- struct odm_phy_status_info *pPhyInfo,
- u8 *pPhyStatus,
- struct odm_per_pkt_info *pPktinfo)
-{
- struct sw_ant_switch *pDM_SWAT_Table = &dm_odm->DM_SWAT_Table;
- u8 i, max_spatial_stream;
- s8 rx_pwr[4], rx_pwr_all = 0;
- u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT;
- u8 RSSI, total_rssi = 0;
- bool is_cck_rate;
- u8 rf_rx_num = 0;
- u8 cck_highpwr = 0;
- u8 LNA_idx, VGA_idx;
-
- struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus;
-
- is_cck_rate = pPktinfo->Rate >= DESC92C_RATE1M &&
- pPktinfo->Rate <= DESC92C_RATE11M;
-
- pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1;
- pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
-
- if (is_cck_rate) {
- u8 cck_agc_rpt;
-
- dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++;
- /* (1)Hardware does not provide RSSI for CCK */
- /* (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */
-
- cck_highpwr = dm_odm->bCckHighPower;
-
- cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a;
-
- /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */
- /* The RSSI formula should be modified according to the gain table */
- /* In 88E, cck_highpwr is always set to 1 */
- LNA_idx = (cck_agc_rpt & 0xE0) >> 5;
- VGA_idx = cck_agc_rpt & 0x1F;
- switch (LNA_idx) {
- case 7:
- if (VGA_idx <= 27)
- rx_pwr_all = -100 + 2 * (27 - VGA_idx); /* VGA_idx = 27~2 */
- else
- rx_pwr_all = -100;
- break;
- case 6:
- rx_pwr_all = -48 + 2 * (2 - VGA_idx); /* VGA_idx = 2~0 */
- break;
- case 5:
- rx_pwr_all = -42 + 2 * (7 - VGA_idx); /* VGA_idx = 7~5 */
- break;
- case 4:
- rx_pwr_all = -36 + 2 * (7 - VGA_idx); /* VGA_idx = 7~4 */
- break;
- case 3:
- rx_pwr_all = -24 + 2 * (7 - VGA_idx); /* VGA_idx = 7~0 */
- break;
- case 2:
- if (cck_highpwr)
- rx_pwr_all = -12 + 2 * (5 - VGA_idx); /* VGA_idx = 5~0 */
- else
- rx_pwr_all = -6 + 2 * (5 - VGA_idx);
- break;
- case 1:
- rx_pwr_all = 8 - 2 * VGA_idx;
- break;
- case 0:
- rx_pwr_all = 14 - 2 * VGA_idx;
- break;
- default:
- break;
- }
- rx_pwr_all += 6;
- PWDB_ALL = odm_query_rxpwrpercentage(rx_pwr_all);
- if (!cck_highpwr) {
- if (PWDB_ALL >= 80)
- PWDB_ALL = ((PWDB_ALL - 80) << 1) + ((PWDB_ALL - 80) >> 1) + 80;
- else if ((PWDB_ALL <= 78) && (PWDB_ALL >= 20))
- PWDB_ALL += 3;
- if (PWDB_ALL > 100)
- PWDB_ALL = 100;
- }
-
- pPhyInfo->RxPWDBAll = PWDB_ALL;
- pPhyInfo->BTRxRSSIPercentage = PWDB_ALL;
- pPhyInfo->RecvSignalPower = rx_pwr_all;
- /* (3) Get Signal Quality (EVM) */
- if (pPktinfo->bPacketMatchBSSID) {
- u8 SQ, SQ_rpt;
-
- if (pPhyInfo->RxPWDBAll > 40 && !dm_odm->bInHctTest) {
- SQ = 100;
- } else {
- SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all;
-
- if (SQ_rpt > 64)
- SQ = 0;
- else if (SQ_rpt < 20)
- SQ = 100;
- else
- SQ = ((64 - SQ_rpt) * 100) / 44;
- }
- pPhyInfo->SignalQuality = SQ;
- pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ;
- pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
- }
- } else { /* is OFDM rate */
- dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
-
- /* (1)Get RSSI for HT rate */
-
- for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
- /* 2008/01/30 MH we will judge RF RX path now. */
- if (dm_odm->RFPathRxEnable & BIT(i))
- rf_rx_num++;
-
- rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F) * 2) - 110;
-
- pPhyInfo->RxPwr[i] = rx_pwr[i];
-
- /* Translate DBM to percentage. */
- RSSI = odm_query_rxpwrpercentage(rx_pwr[i]);
- total_rssi += RSSI;
-
- /* Modification for ext-LNA board */
- if (dm_odm->BoardType == ODM_BOARD_HIGHPWR) {
- if ((pPhyStaRpt->path_agc[i].trsw) == 1)
- RSSI = (RSSI > 94) ? 100 : (RSSI + 6);
- else
- RSSI = (RSSI <= 16) ? (RSSI >> 3) : (RSSI - 16);
-
- if ((RSSI <= 34) && (RSSI >= 4))
- RSSI -= 4;
- }
-
- pPhyInfo->RxMIMOSignalStrength[i] = (u8)RSSI;
-
- /* Get Rx snr value in DB */
- pPhyInfo->RxSNR[i] = (s32)(pPhyStaRpt->path_rxsnr[i] / 2);
- dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i] / 2);
- }
- /* (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */
- rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f) - 110;
-
- PWDB_ALL = odm_query_rxpwrpercentage(rx_pwr_all);
- PWDB_ALL_BT = PWDB_ALL;
-
- pPhyInfo->RxPWDBAll = PWDB_ALL;
- pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT;
- pPhyInfo->RxPower = rx_pwr_all;
- pPhyInfo->RecvSignalPower = rx_pwr_all;
-
- /* (3)EVM of HT rate */
- if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15)
- max_spatial_stream = 2; /* both spatial stream make sense */
- else
- max_spatial_stream = 1; /* only spatial stream 1 makes sense */
-
- for (i = 0; i < max_spatial_stream; i++) {
- /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */
- /* fill most significant bit to "zero" when doing shifting operation which may change a negative */
- /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */
- EVM = odm_evm_db_to_percentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */
-
- if (pPktinfo->bPacketMatchBSSID) {
- if (i == RF_PATH_A) /* Fill value in RFD, Get the first spatial stream only */
- pPhyInfo->SignalQuality = (u8)(EVM & 0xff);
- pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff);
- }
- }
- }
- /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */
- /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */
- if (is_cck_rate) {
- pPhyInfo->SignalStrength = (u8)(odm_signal_scale_mapping(dm_odm, PWDB_ALL));/* PWDB_ALL; */
- } else {
- if (rf_rx_num != 0)
- pPhyInfo->SignalStrength = (u8)(odm_signal_scale_mapping(dm_odm, total_rssi /= rf_rx_num));
- }
-
- /* For 92C/92D HW (Hybrid) Antenna Diversity */
- pDM_SWAT_Table->antsel = pPhyStaRpt->ant_sel;
- /* For 88E HW Antenna Diversity */
- dm_odm->DM_FatTable.antsel_rx_keep_0 = pPhyStaRpt->ant_sel;
- dm_odm->DM_FatTable.antsel_rx_keep_1 = pPhyStaRpt->ant_sel_b;
- dm_odm->DM_FatTable.antsel_rx_keep_2 = pPhyStaRpt->antsel_rx_keep_2;
-}
-
-static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
- struct odm_phy_status_info *pPhyInfo,
- struct odm_per_pkt_info *pPktinfo)
-{
- s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK;
- s32 UndecoratedSmoothedOFDM, RSSI_Ave;
- bool is_cck_rate;
- u8 RSSI_max, RSSI_min, i;
- u32 OFDM_pkt = 0;
- u32 Weighting = 0;
- struct sta_info *pEntry;
- u8 antsel_tr_mux;
- struct fast_ant_train *pDM_FatTable = &dm_odm->DM_FatTable;
-
- if (pPktinfo->StationID == 0xFF)
- return;
- pEntry = dm_odm->pODM_StaInfo[pPktinfo->StationID];
- if (!IS_STA_VALID(pEntry))
- return;
- if ((!pPktinfo->bPacketMatchBSSID))
- return;
-
- is_cck_rate = pPktinfo->Rate >= DESC92C_RATE1M &&
- pPktinfo->Rate <= DESC92C_RATE11M;
-
- /* Smart Antenna Debug Message------------------ */
-
- if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV) {
- if (pDM_FatTable->FAT_State == FAT_TRAINING_STATE) {
- if (pPktinfo->bPacketToSelf) {
- antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2 << 2) |
- (pDM_FatTable->antsel_rx_keep_1 << 1) |
- pDM_FatTable->antsel_rx_keep_0;
- pDM_FatTable->antSumRSSI[antsel_tr_mux] += pPhyInfo->RxPWDBAll;
- pDM_FatTable->antRSSIcnt[antsel_tr_mux]++;
- }
- }
- } else if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)) {
- if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
- antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2 << 2) |
- (pDM_FatTable->antsel_rx_keep_1 << 1) | pDM_FatTable->antsel_rx_keep_0;
- rtl88eu_dm_ant_sel_statistics(dm_odm, antsel_tr_mux, pPktinfo->StationID, pPhyInfo->RxPWDBAll);
- }
- }
- /* Smart Antenna Debug Message------------------ */
-
- UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK;
- UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM;
- UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
-
- if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
- if (!is_cck_rate) { /* ofdm rate */
- if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) {
- RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
- } else {
- if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) {
- RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
- RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
- } else {
- RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
- RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
- }
- if ((RSSI_max - RSSI_min) < 3)
- RSSI_Ave = RSSI_max;
- else if ((RSSI_max - RSSI_min) < 6)
- RSSI_Ave = RSSI_max - 1;
- else if ((RSSI_max - RSSI_min) < 10)
- RSSI_Ave = RSSI_max - 2;
- else
- RSSI_Ave = RSSI_max - 3;
- }
-
- /* 1 Process OFDM RSSI */
- if (UndecoratedSmoothedOFDM <= 0) { /* initialize */
- UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll;
- } else {
- if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) {
- UndecoratedSmoothedOFDM =
- (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor - 1)) +
- (RSSI_Ave)) / (Rx_Smooth_Factor);
- UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1;
- } else {
- UndecoratedSmoothedOFDM =
- (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor - 1)) +
- (RSSI_Ave)) / (Rx_Smooth_Factor);
- }
- }
-
- pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap << 1) | BIT(0);
-
- } else {
- RSSI_Ave = pPhyInfo->RxPWDBAll;
-
- /* 1 Process CCK RSSI */
- if (UndecoratedSmoothedCCK <= 0) { /* initialize */
- UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll;
- } else {
- if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) {
- UndecoratedSmoothedCCK =
- ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor - 1)) +
- pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
- UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
- } else {
- UndecoratedSmoothedCCK =
- ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor - 1)) +
- pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
- }
- }
- pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap << 1;
- }
- /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */
- if (pEntry->rssi_stat.ValidBit >= 64)
- pEntry->rssi_stat.ValidBit = 64;
- else
- pEntry->rssi_stat.ValidBit++;
-
- for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
- OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap >> i) & BIT(0);
-
- if (pEntry->rssi_stat.ValidBit == 64) {
- Weighting = min_t(u32, OFDM_pkt << 4, 64);
- UndecoratedSmoothedPWDB = (Weighting * UndecoratedSmoothedOFDM + (64 - Weighting) * UndecoratedSmoothedCCK) >> 6;
- } else {
- if (pEntry->rssi_stat.ValidBit != 0)
- UndecoratedSmoothedPWDB = (OFDM_pkt * UndecoratedSmoothedOFDM +
- (pEntry->rssi_stat.ValidBit - OFDM_pkt) *
- UndecoratedSmoothedCCK) / pEntry->rssi_stat.ValidBit;
- else
- UndecoratedSmoothedPWDB = 0;
- }
- pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
- pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM;
- pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
- }
-}
-
-/* Endianness before calling this API */
-void odm_phy_status_query(struct odm_dm_struct *dm_odm,
- struct odm_phy_status_info *phy_info,
- u8 *phy_status, struct odm_per_pkt_info *pkt_info)
-{
- odm_RxPhyStatus92CSeries_Parsing(dm_odm, phy_info, phy_status, pkt_info);
- if (dm_odm->RSSI_test)
- ;/* Select the packets to do RSSI checking for antenna switching. */
- else
- odm_Process_RSSIForDM(dm_odm, phy_info, pkt_info);
-}
diff --git a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c
deleted file mode 100644
index e29cd35a5811..000000000000
--- a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c
+++ /dev/null
@@ -1,335 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include "odm_precomp.h"
-#include "phy.h"
-
-static void dm_rx_hw_antena_div_init(struct odm_dm_struct *dm_odm)
-{
- struct adapter *adapter = dm_odm->Adapter;
- u32 value32;
-
- if (*dm_odm->mp_mode == 1) {
- dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
- return;
- }
-
- /* MAC Setting */
- value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
- phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
- value32 | (BIT(23) | BIT(25)));
- /* Pin Settings */
- phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 1);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
- /* OFDM Settings */
- phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
- 0x000000a0);
- /* CCK Settings */
- phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
- phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
- rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
- phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201);
-}
-
-static void dm_trx_hw_antenna_div_init(struct odm_dm_struct *dm_odm)
-{
- struct adapter *adapter = dm_odm->Adapter;
- u32 value32;
-
- if (*dm_odm->mp_mode == 1) {
- dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT(5) | BIT(4) | BIT(3), 0);
- return;
- }
-
- /* MAC Setting */
- value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
- phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
- value32 | (BIT(23) | BIT(25)));
- /* Pin Settings */
- phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 0);
- phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
- /* OFDM Settings */
- phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
- 0x000000a0);
- /* CCK Settings */
- phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
- phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
- /* Tx Settings */
- phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
- rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
-
- /* antenna mapping table */
- if (!dm_odm->bIsMPChip) { /* testchip */
- phy_set_bb_reg(adapter, ODM_REG_RX_DEFAULT_A_11N,
- BIT(10) | BIT(9) | BIT(8), 1);
- phy_set_bb_reg(adapter, ODM_REG_RX_DEFAULT_A_11N,
- BIT(13) | BIT(12) | BIT(11), 2);
- } else { /* MPchip */
- phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, bMaskDWord,
- 0x0201);
- }
-}
-
-static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
-{
- struct adapter *adapter = dm_odm->Adapter;
- u32 value32, i;
- struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
-
- if (*dm_odm->mp_mode == 1)
- return;
-
- for (i = 0; i < 6; i++) {
- dm_fat_tbl->Bssid[i] = 0;
- dm_fat_tbl->antSumRSSI[i] = 0;
- dm_fat_tbl->antRSSIcnt[i] = 0;
- dm_fat_tbl->antAveRSSI[i] = 0;
- }
- dm_fat_tbl->TrainIdx = 0;
- dm_fat_tbl->FAT_State = FAT_NORMAL_STATE;
-
- /* MAC Setting */
- value32 = phy_query_bb_reg(adapter, 0x4c, bMaskDWord);
- phy_set_bb_reg(adapter, 0x4c, bMaskDWord,
- value32 | (BIT(23) | BIT(25)));
- value32 = phy_query_bb_reg(adapter, 0x7B4, bMaskDWord);
- phy_set_bb_reg(adapter, 0x7b4, bMaskDWord,
- value32 | (BIT(16) | BIT(17)));
-
- /* Match MAC ADDR */
- phy_set_bb_reg(adapter, 0x7b4, 0xFFFF, 0);
- phy_set_bb_reg(adapter, 0x7b0, bMaskDWord, 0);
-
- phy_set_bb_reg(adapter, 0x870, BIT(9) | BIT(8), 0);
- phy_set_bb_reg(adapter, 0x864, BIT(10), 0);
- phy_set_bb_reg(adapter, 0xb2c, BIT(22), 0);
- phy_set_bb_reg(adapter, 0xb2c, BIT(31), 1);
- phy_set_bb_reg(adapter, 0xca4, bMaskDWord, 0x000000a0);
-
- /* antenna mapping table */
- if (!dm_odm->bIsMPChip) { /* testchip */
- phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 1);
- phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 2);
- } else { /* MPchip */
- phy_set_bb_reg(adapter, 0x914, bMaskByte0, 1);
- phy_set_bb_reg(adapter, 0x914, bMaskByte1, 2);
- }
-
- /* Default Ant Setting when no fast training */
- phy_set_bb_reg(adapter, 0x80c, BIT(21), 1);
- phy_set_bb_reg(adapter, 0x864, BIT(5) | BIT(4) | BIT(3), 0);
- phy_set_bb_reg(adapter, 0x864, BIT(8) | BIT(7) | BIT(6), 1);
-
- /* Enter Traing state */
- phy_set_bb_reg(adapter, 0x864, BIT(2) | BIT(1) | BIT(0), 1);
- phy_set_bb_reg(adapter, 0xc50, BIT(7), 1);
-}
-
-void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm)
-{
- if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)
- dm_rx_hw_antena_div_init(dm_odm);
- else if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
- dm_trx_hw_antenna_div_init(dm_odm);
- else if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)
- dm_fast_training_init(dm_odm);
-}
-
-void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant)
-{
- struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
- struct adapter *adapter = dm_odm->Adapter;
- u32 default_ant, optional_ant;
-
- if (dm_fat_tbl->RxIdleAnt == ant)
- return;
-
- if (ant == MAIN_ANT) {
- default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
- MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
- optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
- AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
- } else {
- default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
- AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
- optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
- MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
- }
-
- if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT(5) | BIT(4) | BIT(3), default_ant);
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT(8) | BIT(7) | BIT(6), optional_ant);
- phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N,
- BIT(14) | BIT(13) | BIT(12), default_ant);
- phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N,
- BIT(6) | BIT(7), default_ant);
- } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT(5) | BIT(4) | BIT(3), default_ant);
- phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
- BIT(8) | BIT(7) | BIT(6), optional_ant);
- }
-
- dm_fat_tbl->RxIdleAnt = ant;
-}
-
-static void update_tx_ant_88eu(struct odm_dm_struct *dm_odm, u8 ant, u32 mac_id)
-{
- struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
- u8 target_ant;
-
- if (ant == MAIN_ANT)
- target_ant = MAIN_ANT_CG_TRX;
- else
- target_ant = AUX_ANT_CG_TRX;
- dm_fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
- dm_fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1;
- dm_fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2;
-}
-
-void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm,
- u8 *desc, u8 mac_id)
-{
- struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
-
- if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
- (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)) {
- SET_TX_DESC_ANTSEL_A_88E(desc, dm_fat_tbl->antsel_a[mac_id]);
- SET_TX_DESC_ANTSEL_B_88E(desc, dm_fat_tbl->antsel_b[mac_id]);
- SET_TX_DESC_ANTSEL_C_88E(desc, dm_fat_tbl->antsel_c[mac_id]);
- }
-}
-
-void rtl88eu_dm_ant_sel_statistics(struct odm_dm_struct *dm_odm,
- u8 antsel_tr_mux, u32 mac_id, u8 rx_pwdb_all)
-{
- struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
-
- if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
- if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
- dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
- dm_fat_tbl->MainAnt_Cnt[mac_id]++;
- } else {
- dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
- dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
- }
- } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
- if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
- dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
- dm_fat_tbl->MainAnt_Cnt[mac_id]++;
- } else {
- dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
- dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
- }
- }
-}
-
-static void rtl88eu_dm_hw_ant_div(struct odm_dm_struct *dm_odm)
-{
- struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
- struct rtw_dig *dig_table = &dm_odm->DM_DigTable;
- struct sta_info *entry;
- u32 i, min_rssi = 0xFF, ant_div_max_rssi = 0, max_rssi = 0;
- u32 local_min_rssi, local_max_rssi;
- u32 main_rssi, aux_rssi;
- u8 RxIdleAnt = 0, target_ant = 7;
-
- for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
- entry = dm_odm->pODM_StaInfo[i];
- if (IS_STA_VALID(entry)) {
- /* 2 Calculate RSSI per Antenna */
- main_rssi = (dm_fat_tbl->MainAnt_Cnt[i] != 0) ?
- (dm_fat_tbl->MainAnt_Sum[i] /
- dm_fat_tbl->MainAnt_Cnt[i]) : 0;
- aux_rssi = (dm_fat_tbl->AuxAnt_Cnt[i] != 0) ?
- (dm_fat_tbl->AuxAnt_Sum[i] /
- dm_fat_tbl->AuxAnt_Cnt[i]) : 0;
- target_ant = (main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT;
- /* 2 Select max_rssi for DIG */
- local_max_rssi = max(main_rssi, aux_rssi);
- if ((local_max_rssi > ant_div_max_rssi) &&
- (local_max_rssi < 40))
- ant_div_max_rssi = local_max_rssi;
- if (local_max_rssi > max_rssi)
- max_rssi = local_max_rssi;
-
- /* 2 Select RX Idle Antenna */
- if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) &&
- (main_rssi == 0))
- main_rssi = aux_rssi;
- else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) &&
- (aux_rssi == 0))
- aux_rssi = main_rssi;
-
- local_min_rssi = min(main_rssi, aux_rssi);
- if (local_min_rssi < min_rssi) {
- min_rssi = local_min_rssi;
- RxIdleAnt = target_ant;
- }
- /* 2 Select TRX Antenna */
- if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
- update_tx_ant_88eu(dm_odm, target_ant, i);
- }
- dm_fat_tbl->MainAnt_Sum[i] = 0;
- dm_fat_tbl->AuxAnt_Sum[i] = 0;
- dm_fat_tbl->MainAnt_Cnt[i] = 0;
- dm_fat_tbl->AuxAnt_Cnt[i] = 0;
- }
-
- /* 2 Set RX Idle Antenna */
- rtl88eu_dm_update_rx_idle_ant(dm_odm, RxIdleAnt);
-
- dig_table->AntDiv_RSSI_max = ant_div_max_rssi;
- dig_table->RSSI_max = max_rssi;
-}
-
-void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
-{
- struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
- struct adapter *adapter = dm_odm->Adapter;
-
- if (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV))
- return;
-
- if (!dm_odm->bLinked) {
- if (dm_fat_tbl->bBecomeLinked) {
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
- phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
- BIT(15), 0);
- if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
- phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
- BIT(21), 0);
- dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
- }
- return;
- }
-
- if (!dm_fat_tbl->bBecomeLinked) {
- phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1);
- phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
- BIT(15), 1);
- if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
- phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
- BIT(21), 1);
- dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
- }
-
- if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
- (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV))
- rtl88eu_dm_hw_ant_div(dm_odm);
-}
diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c
deleted file mode 100644
index 256f87b9d630..000000000000
--- a/drivers/staging/rtl8188eu/hal/phy.c
+++ /dev/null
@@ -1,1276 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTL8188E_PHYCFG_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtl8188e_hal.h>
-#include <rf.h>
-#include <phy.h>
-
-#define MAX_PRECMD_CNT 16
-#define MAX_RFDEPENDCMD_CNT 16
-#define MAX_POSTCMD_CNT 16
-
-#define MAX_DOZE_WAITING_TIMES_9x 64
-
-static u32 cal_bit_shift(u32 bitmask)
-{
- u32 i;
-
- for (i = 0; i <= 31; i++) {
- if (((bitmask >> i) & 0x1) == 1)
- break;
- }
- return i;
-}
-
-u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask)
-{
- u32 original_value, bit_shift;
-
- original_value = usb_read32(adapt, regaddr);
- bit_shift = cal_bit_shift(bitmask);
- return (original_value & bitmask) >> bit_shift;
-}
-
-void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
-{
- u32 original_value, bit_shift;
-
- if (bitmask != bMaskDWord) { /* if not "double word" write */
- original_value = usb_read32(adapt, regaddr);
- bit_shift = cal_bit_shift(bitmask);
- data = (original_value & (~bitmask)) | (data << bit_shift);
- }
-
- usb_write32(adapt, regaddr, data);
-}
-
-static u32 rf_serial_read(struct adapter *adapt, enum rf_radio_path rfpath, u32 offset)
-{
- u32 ret = 0;
- struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
- u32 tmplong, tmplong2;
- u8 rfpi_enable = 0;
-
- offset &= 0xff;
-
- tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
- if (rfpath == RF_PATH_A)
- tmplong2 = tmplong;
- else
- tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2,
- bMaskDWord);
-
- tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
- (offset << 23) | bLSSIReadEdge;
-
- phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
- tmplong & (~bLSSIReadEdge));
- udelay(10);
-
- phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2);
- udelay(100);
-
- udelay(10);
-
- if (rfpath == RF_PATH_A)
- rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
- else if (rfpath == RF_PATH_B)
- rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
-
- if (rfpi_enable)
- ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
- bLSSIReadBackData);
- else
- ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBack,
- bLSSIReadBackData);
- return ret;
-}
-
-static void rf_serial_write(struct adapter *adapt,
- enum rf_radio_path rfpath, u32 offset,
- u32 data)
-{
- u32 data_and_addr = 0;
- struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
-
- offset &= 0xff;
- data_and_addr = ((offset << 20) | (data & 0x000fffff)) & 0x0fffffff;
- phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
-}
-
-u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path,
- u32 reg_addr, u32 bit_mask)
-{
- u32 original_value, bit_shift;
-
- original_value = rf_serial_read(adapt, rf_path, reg_addr);
- bit_shift = cal_bit_shift(bit_mask);
- return (original_value & bit_mask) >> bit_shift;
-}
-
-void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
- u32 reg_addr, u32 bit_mask, u32 data)
-{
- u32 original_value, bit_shift;
-
- /* RF data is 12 bits only */
- if (bit_mask != bRFRegOffsetMask) {
- original_value = rf_serial_read(adapt, rf_path, reg_addr);
- bit_shift = cal_bit_shift(bit_mask);
- data = (original_value & (~bit_mask)) | (data << bit_shift);
- }
-
- rf_serial_write(adapt, rf_path, reg_addr, data);
-}
-
-static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr,
- u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
- u8 index = (channel - 1);
- u8 TxCount = 0, path_nums;
-
- path_nums = 1;
-
- for (TxCount = 0; TxCount < path_nums; TxCount++) {
- if (TxCount == RF_PATH_A) {
- cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
- ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index] +
- hal_data->OFDM_24G_Diff[TxCount][RF_PATH_A];
-
- bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index] +
- hal_data->BW20_24G_Diff[TxCount][RF_PATH_A];
- bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
- } else if (TxCount == RF_PATH_B) {
- cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
- ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index] +
- hal_data->BW20_24G_Diff[RF_PATH_A][index] +
- hal_data->BW20_24G_Diff[TxCount][index];
-
- bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index] +
- hal_data->BW20_24G_Diff[TxCount][RF_PATH_A] +
- hal_data->BW20_24G_Diff[TxCount][index];
- bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
- }
- }
-}
-
-void phy_set_tx_power_level(struct adapter *adapt, u8 channel)
-{
- u8 cck_pwr[MAX_TX_COUNT] = {0};
- u8 ofdm_pwr[MAX_TX_COUNT] = {0};/* [0]:RF-A, [1]:RF-B */
- u8 bw20_pwr[MAX_TX_COUNT] = {0};
- u8 bw40_pwr[MAX_TX_COUNT] = {0};
-
- get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
- &bw20_pwr[0], &bw40_pwr[0]);
-
- rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]);
- rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0],
- &bw40_pwr[0], channel);
-}
-
-static void phy_set_bw_mode_callback(struct adapter *adapt)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
- u8 reg_bw_opmode;
- u8 reg_prsr_rsc;
-
- if (adapt->bDriverStopped)
- return;
-
- /* Set MAC register */
-
- reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE);
- reg_prsr_rsc = usb_read8(adapt, REG_RRSR + 2);
-
- switch (hal_data->CurrentChannelBW) {
- case HT_CHANNEL_WIDTH_20:
- reg_bw_opmode |= BW_OPMODE_20MHZ;
- usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
- break;
- case HT_CHANNEL_WIDTH_40:
- reg_bw_opmode &= ~BW_OPMODE_20MHZ;
- usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
- reg_prsr_rsc = (reg_prsr_rsc & 0x90) |
- (hal_data->nCur40MhzPrimeSC << 5);
- usb_write8(adapt, REG_RRSR + 2, reg_prsr_rsc);
- break;
- default:
- break;
- }
-
- /* Set PHY related register */
- switch (hal_data->CurrentChannelBW) {
- case HT_CHANNEL_WIDTH_20:
- phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0);
- phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0);
- break;
- case HT_CHANNEL_WIDTH_40:
- phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x1);
- phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x1);
- /* Set Control channel to upper or lower.
- * These settings are required only for 40MHz
- */
- phy_set_bb_reg(adapt, rCCK0_System, bCCKSideBand,
- (hal_data->nCur40MhzPrimeSC >> 1));
- phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
- hal_data->nCur40MhzPrimeSC);
- phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
- (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
- break;
- default:
- break;
- }
-
- /* Set RF related register */
- rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
-}
-
-void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth,
- unsigned char offset)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
- enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW;
-
- hal_data->CurrentChannelBW = bandwidth;
- hal_data->nCur40MhzPrimeSC = offset;
-
- if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
- phy_set_bw_mode_callback(adapt);
- else
- hal_data->CurrentChannelBW = tmp_bw;
-}
-
-static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel)
-{
- u32 param1, param2;
- struct hal_data_8188e *hal_data = adapt->HalData;
-
- phy_set_tx_power_level(adapt, channel);
-
- param1 = RF_CHNLBW;
- param2 = channel;
- hal_data->RfRegChnlVal[0] = (hal_data->RfRegChnlVal[0] &
- 0xfffffc00) | param2;
- phy_set_rf_reg(adapt, 0, param1,
- bRFRegOffsetMask, hal_data->RfRegChnlVal[0]);
-}
-
-void rtw_hal_set_chan(struct adapter *adapt, u8 channel)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
- u8 tmpchannel = hal_data->CurrentChannel;
-
- if (channel == 0)
- channel = 1;
-
- hal_data->CurrentChannel = channel;
-
- if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
- phy_sw_chnl_callback(adapt, channel);
- else
- hal_data->CurrentChannel = tmpchannel;
-}
-
-#define ODM_TXPWRTRACK_MAX_IDX_88E 6
-
-void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
- u8 *direction, u32 *out_write_val)
-{
- u8 pwr_value = 0;
- /* Tx power tracking BB swing table. */
- if (type == 0) { /* For OFDM adjust */
- if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
- *direction = 1;
- pwr_value = dm_odm->BbSwingIdxOfdmBase -
- dm_odm->BbSwingIdxOfdm;
- } else {
- *direction = 2;
- pwr_value = dm_odm->BbSwingIdxOfdm -
- dm_odm->BbSwingIdxOfdmBase;
- }
- } else if (type == 1) { /* For CCK adjust. */
- if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
- *direction = 1;
- pwr_value = dm_odm->BbSwingIdxCckBase -
- dm_odm->BbSwingIdxCck;
- } else {
- *direction = 2;
- pwr_value = dm_odm->BbSwingIdxCck -
- dm_odm->BbSwingIdxCckBase;
- }
- }
-
- if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1)
- pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
-
- *out_write_val = pwr_value | (pwr_value << 8) | (pwr_value << 16) |
- (pwr_value << 24);
-}
-
-static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm)
-{
- if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
- phy_set_tx_power_level(dm_odm->Adapter, *dm_odm->pChannel);
- dm_odm->BbSwingFlagOfdm = false;
- dm_odm->BbSwingFlagCck = false;
- }
-}
-
-void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
- u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
- u8 thermal_avg_count = 0;
- u32 thermal_avg = 0;
- s32 ele_d, temp_cck;
- s8 ofdm_index[2], cck_index = 0;
- s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
- u32 i = 0, j = 0;
-
- u8 ofdm_min_index = 6; /* OFDM BB Swing should be less than +3.0dB */
- s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
- /* 2.4G, decrease power */
- {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
- /* 2.4G, increase power */
- {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10},
- };
- u8 thermal_mapping[2][index_mapping_NUM_88E] = {
- /* 2.4G, decrease power */
- {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
- /* 2.4G, increase power */
- {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25},
- };
- struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
-
- dm_txpwr_track_setpwr(dm_odm);
-
- dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
-
- dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
-
- thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A,
- RF_T_METER_88E, 0xfc00);
-
- if (thermal_val) {
- /* Query OFDM path A default setting */
- ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) & bMaskOFDM_D;
- for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
- if (ele_d == (OFDMSwingTable[i] & bMaskOFDM_D)) {
- ofdm_index_old[0] = (u8)i;
- dm_odm->BbSwingIdxOfdmBase = (u8)i;
- break;
- }
- }
-
- /* Query CCK default setting From 0xa24 */
- temp_cck = dm_odm->RFCalibrateInfo.RegA24;
-
- for (i = 0; i < CCK_TABLE_SIZE; i++) {
- if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
- memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
- memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
- cck_index_old = (u8)i;
- dm_odm->BbSwingIdxCckBase = (u8)i;
- break;
- }
- }
-
- if (!dm_odm->RFCalibrateInfo.ThermalValue) {
- dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter;
- dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
- dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
-
- dm_odm->RFCalibrateInfo.OFDM_index[0] = ofdm_index_old[0];
- dm_odm->RFCalibrateInfo.CCK_index = cck_index_old;
- }
-
- /* calculate average thermal meter */
- dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val;
- dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
- if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
- dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
-
- for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
- if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
- thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
- thermal_avg_count++;
- }
- }
-
- if (thermal_avg_count)
- thermal_val = (u8)(thermal_avg / thermal_avg_count);
-
- if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
- !dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
- delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
- } else {
- delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
- if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
- dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
- dm_odm->RFCalibrateInfo.bDoneTxpower = false;
- }
- }
-
- delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
- delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
-
- /* Delta temperature is equal to or larger than 20 centigrade.*/
- if ((delta_lck >= 8)) {
- dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
- rtl88eu_phy_lc_calibrate(adapt);
- }
-
- if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
- delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
-
- /* calculate new OFDM / CCK offset */
- if (thermal_val > hal_data->EEPROMThermalMeter)
- j = 1;
- else
- j = 0;
- for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
- if (delta < thermal_mapping[j][offset]) {
- if (offset != 0)
- offset--;
- break;
- }
- }
- if (offset >= index_mapping_NUM_88E)
- offset = index_mapping_NUM_88E - 1;
-
- /* Updating ofdm_index values with new OFDM / CCK offset */
- ofdm_index[0] = dm_odm->RFCalibrateInfo.OFDM_index[0] + ofdm_index_mapping[j][offset];
- if (ofdm_index[0] > OFDM_TABLE_SIZE_92D - 1)
- ofdm_index[0] = OFDM_TABLE_SIZE_92D - 1;
- else if (ofdm_index[0] < ofdm_min_index)
- ofdm_index[0] = ofdm_min_index;
-
- cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
- if (cck_index > CCK_TABLE_SIZE - 1)
- cck_index = CCK_TABLE_SIZE - 1;
- else if (cck_index < 0)
- cck_index = 0;
-
- /* 2 temporarily remove bNOPG */
- /* Config by SwingTable */
- if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
- dm_odm->RFCalibrateInfo.bDoneTxpower = true;
-
- /* Revse TX power table. */
- dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
- dm_odm->BbSwingIdxCck = (u8)cck_index;
-
- if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
- dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
- dm_odm->BbSwingFlagOfdm = true;
- }
-
- if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
- dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
- dm_odm->BbSwingFlagCck = true;
- }
- }
- }
-
- /* Delta temperature is equal to or larger than 20 centigrade.*/
- if (delta_iqk >= 8) {
- dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
- rtl88eu_phy_iq_calibrate(adapt, false);
- }
- /* update thermal meter value */
- if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
- dm_odm->RFCalibrateInfo.ThermalValue = thermal_val;
- }
- dm_odm->RFCalibrateInfo.TXPowercount = 0;
-}
-
-#define MAX_TOLERANCE 5
-
-static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
-{
- u32 reg_eac, reg_e94, reg_e9c;
- u8 result = 0x00;
-
- /* 1 Tx IQK */
- /* path-A IQK setting */
- phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
- phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
- phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
- phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
-
- /* LO calibration setting */
- phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
-
- /* One shot, path A LOK & IQK */
- phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
- phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
-
- mdelay(IQK_DELAY_TIME_88E);
-
- reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
- reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
- reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
-
- if (!(reg_eac & BIT(28)) &&
- (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
- (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
- result |= 0x01;
- return result;
-}
-
-static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
-{
- u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp;
- u8 result = 0x00;
-
- /* 1 Get TXIMR setting */
- /* modify RXIQK mode table */
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
-
- /* PA,PAD off */
- phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
- phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
-
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
-
- /* IQK setting */
- phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
- phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
-
- /* path-A IQK setting */
- phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
- phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
- phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
- phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
-
- /* LO calibration setting */
- phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
-
- /* One shot, path A LOK & IQK */
- phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
- phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
-
- /* delay x ms */
- mdelay(IQK_DELAY_TIME_88E);
-
- /* Check failed */
- reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
- reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
- reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
-
- if (!(reg_eac & BIT(28)) &&
- (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
- (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
- result |= 0x01;
- else /* if Tx not OK, ignore Rx */
- return result;
-
- u4tmp = 0x80007C00 | (reg_e94 & 0x3FF0000) | ((reg_e9c & 0x3FF0000) >> 16);
- phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp);
-
- /* 1 RX IQK */
- /* modify RXIQK mode table */
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
-
- /* IQK setting */
- phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
-
- /* path-A IQK setting */
- phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
- phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
- phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
- phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
-
- /* LO calibration setting */
- phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
-
- phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
- phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
-
- mdelay(IQK_DELAY_TIME_88E);
-
- /* Check failed */
- reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
- reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
- reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
- reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
-
- /* reload RF 0xdf */
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
- phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
-
- if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
- (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
- (((reg_eac & 0x03FF0000) >> 16) != 0x36))
- result |= 0x02;
-
- return result;
-}
-
-static u8 phy_path_b_iqk(struct adapter *adapt)
-{
- u32 regeac, regeb4, regebc, regec4, regecc;
- u8 result = 0x00;
-
- /* One shot, path B LOK & IQK */
- phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
- phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
-
- mdelay(IQK_DELAY_TIME_88E);
-
- regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
- regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord);
- regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord);
- regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
- regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
-
- if (!(regeac & BIT(31)) &&
- (((regeb4 & 0x03FF0000) >> 16) != 0x142) &&
- (((regebc & 0x03FF0000) >> 16) != 0x42))
- result |= 0x01;
- else
- return result;
-
- if (!(regeac & BIT(30)) &&
- (((regec4 & 0x03FF0000) >> 16) != 0x132) &&
- (((regecc & 0x03FF0000) >> 16) != 0x36))
- result |= 0x02;
-
- return result;
-}
-
-static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
- u8 final_candidate, bool txonly)
-{
- u32 oldval_0, x, tx0_a, reg;
- s32 y, tx0_c;
-
- if (final_candidate == 0xFF) {
- return;
- } else if (iqkok) {
- oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
-
- x = result[final_candidate][0];
- if ((x & 0x00000200) != 0)
- x = x | 0xFFFFFC00;
-
- tx0_a = (x * oldval_0) >> 8;
- phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a);
- phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31),
- ((x * oldval_0 >> 7) & 0x1));
-
- y = result[final_candidate][1];
- if ((y & 0x00000200) != 0)
- y = y | 0xFFFFFC00;
-
- tx0_c = (y * oldval_0) >> 8;
- phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000,
- ((tx0_c & 0x3C0) >> 6));
- phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000,
- (tx0_c & 0x3F));
- phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29),
- ((y * oldval_0 >> 7) & 0x1));
-
- if (txonly)
- return;
-
- reg = result[final_candidate][2];
- phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
-
- reg = result[final_candidate][3] & 0x3F;
- phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
-
- reg = (result[final_candidate][3] >> 6) & 0xF;
- phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
- }
-}
-
-static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
- u8 final_candidate, bool txonly)
-{
- u32 oldval_1, x, tx1_a, reg;
- s32 y, tx1_c;
-
- if (final_candidate == 0xFF) {
- return;
- } else if (iqkok) {
- oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
-
- x = result[final_candidate][4];
- if ((x & 0x00000200) != 0)
- x = x | 0xFFFFFC00;
- tx1_a = (x * oldval_1) >> 8;
- phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a);
-
- phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27),
- ((x * oldval_1 >> 7) & 0x1));
-
- y = result[final_candidate][5];
- if ((y & 0x00000200) != 0)
- y = y | 0xFFFFFC00;
-
- tx1_c = (y * oldval_1) >> 8;
-
- phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000,
- ((tx1_c & 0x3C0) >> 6));
- phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000,
- (tx1_c & 0x3F));
- phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25),
- ((y * oldval_1 >> 7) & 0x1));
-
- if (txonly)
- return;
-
- reg = result[final_candidate][6];
- phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
-
- reg = result[final_candidate][7] & 0x3F;
- phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
-
- reg = (result[final_candidate][7] >> 6) & 0xF;
- phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg);
- }
-}
-
-static void save_adda_registers(struct adapter *adapt, const u32 *addareg,
- u32 *backup, u32 register_num)
-{
- u32 i;
-
- for (i = 0; i < register_num; i++)
- backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord);
-}
-
-static void save_mac_registers(struct adapter *adapt, const u32 *mac_reg,
- u32 *backup)
-{
- u32 i;
-
- for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
- backup[i] = usb_read8(adapt, mac_reg[i]);
-
- backup[i] = usb_read32(adapt, mac_reg[i]);
-}
-
-static void reload_adda_reg(struct adapter *adapt, const u32 *adda_reg,
- u32 *backup, u32 regiester_num)
-{
- u32 i;
-
- for (i = 0; i < regiester_num; i++)
- phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]);
-}
-
-static void reload_mac_registers(struct adapter *adapt, const u32 *mac_reg,
- u32 *backup)
-{
- u32 i;
-
- for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
- usb_write8(adapt, mac_reg[i], (u8)backup[i]);
-
- usb_write32(adapt, mac_reg[i], backup[i]);
-}
-
-static void path_adda_on(struct adapter *adapt, const u32 *adda_reg,
- bool is_path_a_on, bool is2t)
-{
- u32 path_on;
- u32 i;
-
- if (!is2t) {
- path_on = 0x0bdb25a0;
- phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
- } else {
- path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
- phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
- }
-
- for (i = 1; i < IQK_ADDA_REG_NUM; i++)
- phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on);
-}
-
-static void mac_setting_calibration(struct adapter *adapt, const u32 *mac_reg,
- u32 *backup)
-{
- u32 i = 0;
-
- usb_write8(adapt, mac_reg[i], 0x3F);
-
- for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
- usb_write8(adapt, mac_reg[i], (u8)(backup[i] & (~BIT(3))));
-
- usb_write8(adapt, mac_reg[i], (u8)(backup[i] & (~BIT(5))));
-}
-
-static void path_a_standby(struct adapter *adapt)
-{
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0);
- phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000);
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
-}
-
-static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
-{
- u32 mode;
-
- mode = pi_mode ? 0x01000100 : 0x01000000;
- phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
- phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
-}
-
-static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
- u8 c1, u8 c2)
-{
- u32 i, j, diff, sim_bitmap = 0, bound;
- u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
- bool result = true;
- s32 tmp1 = 0, tmp2 = 0;
-
- bound = 4;
-
- for (i = 0; i < bound; i++) {
- if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
- if ((resulta[c1][i] & 0x00000200) != 0)
- tmp1 = resulta[c1][i] | 0xFFFFFC00;
- else
- tmp1 = resulta[c1][i];
-
- if ((resulta[c2][i] & 0x00000200) != 0)
- tmp2 = resulta[c2][i] | 0xFFFFFC00;
- else
- tmp2 = resulta[c2][i];
- } else {
- tmp1 = resulta[c1][i];
- tmp2 = resulta[c2][i];
- }
-
- diff = abs(tmp1 - tmp2);
-
- if (diff > MAX_TOLERANCE) {
- if ((i == 2 || i == 6) && !sim_bitmap) {
- if (resulta[c1][i] + resulta[c1][i + 1] == 0)
- final_candidate[(i / 4)] = c2;
- else if (resulta[c2][i] + resulta[c2][i + 1] == 0)
- final_candidate[(i / 4)] = c1;
- else
- sim_bitmap = sim_bitmap | (1 << i);
- } else {
- sim_bitmap = sim_bitmap | (1 << i);
- }
- }
- }
-
- if (sim_bitmap == 0) {
- for (i = 0; i < (bound / 4); i++) {
- if (final_candidate[i] != 0xFF) {
- for (j = i * 4; j < (i + 1) * 4 - 2; j++)
- resulta[3][j] = resulta[final_candidate[i]][j];
- result = false;
- }
- }
- return result;
- }
-
- if (!(sim_bitmap & 0x03)) { /* path A TX OK */
- for (i = 0; i < 2; i++)
- resulta[3][i] = resulta[c1][i];
- }
- if (!(sim_bitmap & 0x0c)) { /* path A RX OK */
- for (i = 2; i < 4; i++)
- resulta[3][i] = resulta[c1][i];
- }
-
- if (!(sim_bitmap & 0x30)) { /* path B TX OK */
- for (i = 4; i < 6; i++)
- resulta[3][i] = resulta[c1][i];
- }
-
- if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
- for (i = 6; i < 8; i++)
- resulta[3][i] = resulta[c1][i];
- }
- return false;
-}
-
-static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
- u8 t, bool is2t)
-{
- struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
- u32 i;
- u8 path_a_ok, path_b_ok;
- static const u32 adda_reg[IQK_ADDA_REG_NUM] = {
- rFPGA0_XCD_SwitchControl, rBlue_Tooth,
- rRx_Wait_CCA, rTx_CCK_RFON,
- rTx_CCK_BBON, rTx_OFDM_RFON,
- rTx_OFDM_BBON, rTx_To_Rx,
- rTx_To_Tx, rRx_CCK,
- rRx_OFDM, rRx_Wait_RIFS,
- rRx_TO_Rx, rStandby,
- rSleep, rPMPD_ANAEN
- };
- static const u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
- REG_TXPAUSE, REG_BCN_CTRL,
- REG_BCN_CTRL_1, REG_GPIO_MUXCFG
- };
- /* since 92C & 92D have the different define in IQK_BB_REG */
- static const u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
- rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
- rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
- rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
- rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD
- };
-
- u32 retry_count = 9;
-
- if (*dm_odm->mp_mode == 1)
- retry_count = 9;
- else
- retry_count = 2;
-
- if (t == 0) {
- /* Save ADDA parameters, turn Path A ADDA on */
- save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
- IQK_ADDA_REG_NUM);
- save_mac_registers(adapt, iqk_mac_reg,
- dm_odm->RFCalibrateInfo.IQK_MAC_backup);
- save_adda_registers(adapt, iqk_bb_reg_92c,
- dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
- }
-
- path_adda_on(adapt, adda_reg, true, is2t);
- if (t == 0)
- dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1,
- BIT(8));
-
- if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
- /* Switch BB to PI mode to do IQ Calibration. */
- pi_mode_switch(adapt, true);
- }
-
- /* BB setting */
- phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
- phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
- phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
- phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
-
- phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
- phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
- phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
- phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
-
- if (is2t) {
- phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
- 0x00010000);
- phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord,
- 0x00010000);
- }
-
- /* MAC settings */
- mac_setting_calibration(adapt, iqk_mac_reg,
- dm_odm->RFCalibrateInfo.IQK_MAC_backup);
-
- /* Page B init */
- /* AP or IQK */
- phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
-
- if (is2t)
- phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000);
-
- /* IQ calibration setting */
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
- phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
- phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
-
- for (i = 0; i < retry_count; i++) {
- path_a_ok = phy_path_a_iqk(adapt, is2t);
- if (path_a_ok == 0x01) {
- result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A,
- bMaskDWord) & 0x3FF0000) >> 16;
- result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A,
- bMaskDWord) & 0x3FF0000) >> 16;
- break;
- }
- }
-
- for (i = 0; i < retry_count; i++) {
- path_a_ok = phy_path_a_rx_iqk(adapt, is2t);
- if (path_a_ok == 0x03) {
- result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2,
- bMaskDWord) & 0x3FF0000) >> 16;
- result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2,
- bMaskDWord) & 0x3FF0000) >> 16;
- break;
- }
- }
-
- if (is2t) {
- path_a_standby(adapt);
-
- /* Turn Path B ADDA on */
- path_adda_on(adapt, adda_reg, false, is2t);
-
- for (i = 0; i < retry_count; i++) {
- path_b_ok = phy_path_b_iqk(adapt);
- if (path_b_ok == 0x03) {
- result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
- bMaskDWord) & 0x3FF0000) >> 16;
- result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
- bMaskDWord) & 0x3FF0000) >> 16;
- result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2,
- bMaskDWord) & 0x3FF0000) >> 16;
- result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2,
- bMaskDWord) & 0x3FF0000) >> 16;
- break;
- } else if (i == (retry_count - 1) && path_b_ok == 0x01) { /* Tx IQK OK */
- result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
- bMaskDWord) & 0x3FF0000) >> 16;
- result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
- bMaskDWord) & 0x3FF0000) >> 16;
- }
- }
- }
-
- /* Back to BB mode, load original value */
- phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0);
-
- if (t != 0) {
- if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
- /* Switch back BB to SI mode after
- * finish IQ Calibration.
- */
- pi_mode_switch(adapt, false);
- }
-
- /* Reload ADDA power saving parameters */
- reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
- IQK_ADDA_REG_NUM);
-
- /* Reload MAC parameters */
- reload_mac_registers(adapt, iqk_mac_reg,
- dm_odm->RFCalibrateInfo.IQK_MAC_backup);
-
- reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup,
- IQK_BB_REG_NUM);
-
- /* Restore RX initial gain */
- phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter,
- bMaskDWord, 0x00032ed3);
- if (is2t)
- phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter,
- bMaskDWord, 0x00032ed3);
-
- /* load 0xe30 IQC default value */
- phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
- phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
- }
-}
-
-static void phy_lc_calibrate(struct adapter *adapt, bool is2t)
-{
- u8 tmpreg;
- u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
-
- /* Check continuous TX and Packet TX */
- tmpreg = usb_read8(adapt, 0xd03);
-
- if ((tmpreg & 0x70) != 0)
- usb_write8(adapt, 0xd03, tmpreg & 0x8F);
- else
- usb_write8(adapt, REG_TXPAUSE, 0xFF);
-
- if ((tmpreg & 0x70) != 0) {
- /* 1. Read original RF mode */
- /* Path-A */
- rf_a_mode = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_AC,
- bMask12Bits);
-
- /* Path-B */
- if (is2t)
- rf_b_mode = rtw_hal_read_rfreg(adapt, RF_PATH_B, RF_AC,
- bMask12Bits);
-
- /* 2. Set RF mode = standby mode */
- /* Path-A */
- phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits,
- (rf_a_mode & 0x8FFFF) | 0x10000);
-
- /* Path-B */
- if (is2t)
- phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
- (rf_b_mode & 0x8FFFF) | 0x10000);
- }
-
- /* 3. Read RF reg18 */
- lc_cal = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
-
- /* 4. Set LC calibration begin bit15 */
- phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits,
- lc_cal | 0x08000);
-
- msleep(100);
-
- /* Restore original situation */
- if ((tmpreg & 0x70) != 0) {
- /* Deal with continuous TX case */
- /* Path-A */
- usb_write8(adapt, 0xd03, tmpreg);
- phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode);
-
- /* Path-B */
- if (is2t)
- phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
- rf_b_mode);
- } else {
- /* Deal with Packet TX case */
- usb_write8(adapt, REG_TXPAUSE, 0x00);
- }
-}
-
-void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery)
-{
- struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
- s32 result[4][8];
- u8 i, final;
- bool pathaok, pathbok;
- s32 reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4;
- bool is12simular, is13simular, is23simular;
- u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
- rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
- rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
- rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
- rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
- rOFDM0_RxIQExtAnta};
- bool is2t;
-
- is2t = false;
-
- if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
- return;
-
- if (recovery) {
- reload_adda_reg(adapt, iqk_bb_reg_92c,
- dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
- return;
- }
-
- memset(result, 0, sizeof(result));
- for (i = 0; i < 8; i += 2)
- result[3][i] = 0x100;
-
- final = 0xff;
- pathaok = false;
- pathbok = false;
- is12simular = false;
- is23simular = false;
- is13simular = false;
-
- for (i = 0; i < 3; i++) {
- phy_iq_calibrate(adapt, result, i, is2t);
-
- if (i == 1) {
- is12simular = simularity_compare(adapt, result, 0, 1);
- if (is12simular) {
- final = 0;
- break;
- }
- }
-
- if (i == 2) {
- is13simular = simularity_compare(adapt, result, 0, 2);
- if (is13simular) {
- final = 0;
- break;
- }
- is23simular = simularity_compare(adapt, result, 1, 2);
- if (is23simular)
- final = 1;
- else
- final = 3;
- }
- }
-
- for (i = 0; i < 4; i++) {
- reg_e94 = result[i][0];
- reg_e9c = result[i][1];
- reg_ea4 = result[i][2];
- reg_eb4 = result[i][4];
- reg_ebc = result[i][5];
- reg_ec4 = result[i][6];
- }
-
- if (final != 0xff) {
- reg_e94 = result[final][0];
- reg_e9c = result[final][1];
- reg_ea4 = result[final][2];
- reg_eb4 = result[final][4];
- reg_ebc = result[final][5];
- dm_odm->RFCalibrateInfo.RegE94 = reg_e94;
- dm_odm->RFCalibrateInfo.RegE9C = reg_e9c;
- dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4;
- dm_odm->RFCalibrateInfo.RegEBC = reg_ebc;
- reg_ec4 = result[final][6];
- pathaok = true;
- pathbok = true;
- } else {
- dm_odm->RFCalibrateInfo.RegE94 = 0x100;
- dm_odm->RFCalibrateInfo.RegEB4 = 0x100;
- dm_odm->RFCalibrateInfo.RegE9C = 0x0;
- dm_odm->RFCalibrateInfo.RegEBC = 0x0;
- }
- if (reg_e94 != 0)
- patha_fill_iqk(adapt, pathaok, result, final,
- (reg_ea4 == 0));
- if (is2t) {
- if (reg_eb4 != 0)
- pathb_fill_iqk(adapt, pathbok, result, final,
- (reg_ec4 == 0));
- }
-
- if (final < 4) {
- for (i = 0; i < IQK_Matrix_REG_NUM; i++)
- dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[0].Value[0][i] = result[final][i];
- dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[0].bIQKDone = true;
- }
-
- save_adda_registers(adapt, iqk_bb_reg_92c,
- dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
-}
-
-void rtl88eu_phy_lc_calibrate(struct adapter *adapt)
-{
- u32 timeout = 2000, timecount = 0;
- struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
-
- if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
- return;
-
- while (*dm_odm->pbScanInProcess && timecount < timeout) {
- mdelay(50);
- timecount += 50;
- }
-
- dm_odm->RFCalibrateInfo.bLCKInProgress = true;
-
- phy_lc_calibrate(adapt, false);
-
- dm_odm->RFCalibrateInfo.bLCKInProgress = false;
-}
diff --git a/drivers/staging/rtl8188eu/hal/pwrseq.c b/drivers/staging/rtl8188eu/hal/pwrseq.c
deleted file mode 100644
index f7890a8f4673..000000000000
--- a/drivers/staging/rtl8188eu/hal/pwrseq.c
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include "pwrseq.h"
-#include <rtl8188e_hal.h>
-
-/* drivers should parse below arrays and do the corresponding actions */
-
-/* 3 Power on Array */
-struct wl_pwr_cfg rtl8188E_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- RTL8188E_TRANS_CARDEMU_TO_ACT
- RTL8188E_TRANS_END
-};
-
-/* 3Radio off Array */
-struct wl_pwr_cfg rtl8188E_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- RTL8188E_TRANS_ACT_TO_CARDEMU
- RTL8188E_TRANS_END
-};
-
-/* 3Card Disable Array */
-struct wl_pwr_cfg rtl8188E_card_disable_flow
- [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- RTL8188E_TRANS_ACT_TO_CARDEMU
- RTL8188E_TRANS_CARDEMU_TO_CARDDIS
- RTL8188E_TRANS_END
-};
-
-/* 3 Card Enable Array */
-struct wl_pwr_cfg rtl8188E_card_enable_flow
- [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- RTL8188E_TRANS_CARDDIS_TO_CARDEMU
- RTL8188E_TRANS_CARDEMU_TO_ACT
- RTL8188E_TRANS_END
-};
-
-/* 3Suspend Array */
-struct wl_pwr_cfg rtl8188E_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- RTL8188E_TRANS_ACT_TO_CARDEMU
- RTL8188E_TRANS_CARDEMU_TO_SUS
- RTL8188E_TRANS_END
-};
-
-/* 3 Resume Array */
-struct wl_pwr_cfg rtl8188E_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- RTL8188E_TRANS_SUS_TO_CARDEMU
- RTL8188E_TRANS_CARDEMU_TO_ACT
- RTL8188E_TRANS_END
-};
-
-/* 3HWPDN Array */
-struct wl_pwr_cfg rtl8188E_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- RTL8188E_TRANS_ACT_TO_CARDEMU
- RTL8188E_TRANS_CARDEMU_TO_PDN
- RTL8188E_TRANS_END
-};
-
-/* 3 Enter LPS */
-struct wl_pwr_cfg rtl8188E_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- /* FW behavior */
- RTL8188E_TRANS_ACT_TO_LPS
- RTL8188E_TRANS_END
-};
-
-/* 3 Leave LPS */
-struct wl_pwr_cfg rtl8188E_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS +
- RTL8188E_TRANS_END_STEPS] = {
- /* FW behavior */
- RTL8188E_TRANS_LPS_TO_ACT
- RTL8188E_TRANS_END
-};
diff --git a/drivers/staging/rtl8188eu/hal/pwrseqcmd.c b/drivers/staging/rtl8188eu/hal/pwrseqcmd.c
deleted file mode 100644
index cec2ff879f5d..000000000000
--- a/drivers/staging/rtl8188eu/hal/pwrseqcmd.c
+++ /dev/null
@@ -1,80 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <pwrseqcmd.h>
-#include <usb_ops_linux.h>
-
-/* This routine deals with the Power Configuration CMDs parsing
- * for RTL8723/RTL8188E Series IC.
- */
-u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers,
- struct wl_pwr_cfg pwrseqcmd[])
-{
- struct wl_pwr_cfg pwrcfgcmd;
- u8 poll_bit = false;
- u32 aryidx = 0;
- u8 value = 0;
- u32 offset = 0;
- u32 poll_count = 0; /* polling autoload done. */
- u32 max_poll_count = 5000;
-
- do {
- pwrcfgcmd = pwrseqcmd[aryidx];
-
- /* Only Handle the command whose CUT is matched */
- if (GET_PWR_CFG_CUT_MASK(pwrcfgcmd) & cut_vers) {
- switch (GET_PWR_CFG_CMD(pwrcfgcmd)) {
- case PWR_CMD_READ:
- break;
- case PWR_CMD_WRITE:
- offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
-
- /* Read the value from system register */
- value = usb_read8(padapter, offset);
-
- value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
- value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) &
- GET_PWR_CFG_MASK(pwrcfgcmd));
-
- /* Write the value back to system register */
- usb_write8(padapter, offset, value);
- break;
- case PWR_CMD_POLLING:
- poll_bit = false;
- offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
- do {
- value = usb_read8(padapter, offset);
- value &= GET_PWR_CFG_MASK(pwrcfgcmd);
-
- if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) &
- GET_PWR_CFG_MASK(pwrcfgcmd)))
- poll_bit = true;
- else
- udelay(10);
-
- if (poll_count++ > max_poll_count)
- return false;
- } while (!poll_bit);
- break;
- case PWR_CMD_DELAY:
- if (GET_PWR_CFG_VALUE(pwrcfgcmd) == PWRSEQ_DELAY_US)
- udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd));
- else
- udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd) * 1000);
- break;
- case PWR_CMD_END:
- /* When this command is parsed, end the process */
- return true;
- default:
- break;
- }
- }
-
- aryidx++;/* Add Array Index */
- } while (1);
- return true;
-}
diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c
deleted file mode 100644
index aab0f54a75fc..000000000000
--- a/drivers/staging/rtl8188eu/hal/rf.c
+++ /dev/null
@@ -1,289 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <phy.h>
-#include <rf.h>
-#include <rtl8188e_hal.h>
-
-void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt,
- enum ht_channel_width bandwidth)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
-
- switch (bandwidth) {
- case HT_CHANNEL_WIDTH_20:
- hal_data->RfRegChnlVal[0] = ((hal_data->RfRegChnlVal[0] &
- 0xfffff3ff) | BIT(10) | BIT(11));
- phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
- hal_data->RfRegChnlVal[0]);
- break;
- case HT_CHANNEL_WIDTH_40:
- hal_data->RfRegChnlVal[0] = ((hal_data->RfRegChnlVal[0] &
- 0xfffff3ff) | BIT(10));
- phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
- hal_data->RfRegChnlVal[0]);
- break;
- default:
- break;
- }
-}
-
-void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
- struct dm_priv *pdmpriv = &hal_data->dmpriv;
- struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
- u32 tx_agc[2] = {0, 0}, tmpval = 0, pwrtrac_value;
- u8 idx1, idx2;
- u8 *ptr;
- u8 direction;
-
- if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
- tx_agc[RF_PATH_A] = 0x3f3f3f3f;
- tx_agc[RF_PATH_B] = 0x3f3f3f3f;
- for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
- tx_agc[idx1] = powerlevel[idx1] |
- (powerlevel[idx1] << 8) |
- (powerlevel[idx1] << 16) |
- (powerlevel[idx1] << 24);
- }
- } else {
- if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
- tx_agc[RF_PATH_A] = 0x10101010;
- tx_agc[RF_PATH_B] = 0x10101010;
- } else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
- tx_agc[RF_PATH_A] = 0x00000000;
- tx_agc[RF_PATH_B] = 0x00000000;
- } else {
- for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
- tx_agc[idx1] = powerlevel[idx1] |
- (powerlevel[idx1] << 8) |
- (powerlevel[idx1] << 16) |
- (powerlevel[idx1] << 24);
- }
- if (hal_data->EEPROMRegulatory == 0) {
- tmpval = hal_data->MCSTxPowerLevelOriginalOffset[0][6] +
- (hal_data->MCSTxPowerLevelOriginalOffset[0][7] << 8);
- tx_agc[RF_PATH_A] += tmpval;
-
- tmpval = hal_data->MCSTxPowerLevelOriginalOffset[0][14] +
- (hal_data->MCSTxPowerLevelOriginalOffset[0][15] << 24);
- tx_agc[RF_PATH_B] += tmpval;
- }
- }
- }
- for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
- ptr = (u8 *)(&tx_agc[idx1]);
- for (idx2 = 0; idx2 < 4; idx2++) {
- if (*ptr > RF6052_MAX_TX_PWR)
- *ptr = RF6052_MAX_TX_PWR;
- ptr++;
- }
- }
- rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 1, &direction,
- &pwrtrac_value);
-
- if (direction == 1) {
- /* Increase TX power */
- tx_agc[0] += pwrtrac_value;
- tx_agc[1] += pwrtrac_value;
- } else if (direction == 2) {
- /* Decrease TX power */
- tx_agc[0] -= pwrtrac_value;
- tx_agc[1] -= pwrtrac_value;
- }
-
- /* rf-A cck tx power */
- tmpval = tx_agc[RF_PATH_A] & 0xff;
- phy_set_bb_reg(adapt, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
- tmpval = tx_agc[RF_PATH_A] >> 8;
- phy_set_bb_reg(adapt, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
-
- /* rf-B cck tx power */
- tmpval = tx_agc[RF_PATH_B] >> 24;
- phy_set_bb_reg(adapt, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
- tmpval = tx_agc[RF_PATH_B] & 0x00ffffff;
- phy_set_bb_reg(adapt, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
-}
-
-/* powerbase0 for OFDM rates */
-/* powerbase1 for HT MCS rates */
-static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm,
- u8 *pwr_level_bw20, u8 *pwr_level_bw40,
- u8 channel, u32 *ofdmbase, u32 *mcs_base)
-{
- u32 powerbase0, powerbase1;
- u8 i, powerlevel[2];
-
- for (i = 0; i < 2; i++) {
- powerbase0 = pwr_level_ofdm[i];
-
- powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
- (powerbase0 << 8) | powerbase0;
- *(ofdmbase + i) = powerbase0;
- }
- /* Check HT20 to HT40 diff */
- if (adapt->HalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
- powerlevel[0] = pwr_level_bw20[0];
- else
- powerlevel[0] = pwr_level_bw40[0];
- powerbase1 = powerlevel[0];
- powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) |
- (powerbase1 << 8) | powerbase1;
- *mcs_base = powerbase1;
-}
-
-static void get_rx_power_val_by_reg(struct adapter *adapt, u8 channel,
- u8 index, u32 *powerbase0, u32 *powerbase1,
- u32 *out_val)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
- struct dm_priv *pdmpriv = &hal_data->dmpriv;
- u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit;
- s8 pwr_diff = 0;
- u32 write_val, customer_limit, rf;
- u8 regulatory = hal_data->EEPROMRegulatory;
-
- /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
-
- for (rf = 0; rf < 2; rf++) {
- u8 j = index + (rf ? 8 : 0);
-
- switch (regulatory) {
- case 0:
- chnlGroup = 0;
- write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
- ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
- break;
- case 1: /* Realtek regulatory */
- /* increase power diff defined by Realtek for regulatory */
- if (hal_data->pwrGroupCnt == 1)
- chnlGroup = 0;
- if (hal_data->pwrGroupCnt >= hal_data->PGMaxGroup)
- Hal_GetChnlGroup88E(channel, &chnlGroup);
-
- write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][index + (rf ? 8 : 0)] +
- ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
- break;
- case 2: /* Better regulatory */
- /* don't increase any power diff */
- write_val = (index < 2) ? powerbase0[rf] : powerbase1[rf];
- break;
- case 3: /* Customer defined power diff. */
- /* increase power diff defined by customer. */
- chnlGroup = 0;
-
- if (index < 2)
- pwr_diff = hal_data->TxPwrLegacyHtDiff[rf][channel - 1];
- else if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
- pwr_diff = hal_data->TxPwrHt20Diff[rf][channel - 1];
-
- if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_40)
- customer_pwr_limit = hal_data->PwrGroupHT40[rf][channel - 1];
- else
- customer_pwr_limit = hal_data->PwrGroupHT20[rf][channel - 1];
-
- if (pwr_diff >= customer_pwr_limit)
- pwr_diff = 0;
- else
- pwr_diff = customer_pwr_limit - pwr_diff;
-
- for (i = 0; i < 4; i++) {
- pwr_diff_limit[i] = (u8)((hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][j] &
- (0x7f << (i * 8))) >> (i * 8));
-
- if (pwr_diff_limit[i] > pwr_diff)
- pwr_diff_limit[i] = pwr_diff;
- }
- customer_limit = (pwr_diff_limit[3] << 24) |
- (pwr_diff_limit[2] << 16) |
- (pwr_diff_limit[1] << 8) |
- (pwr_diff_limit[0]);
- write_val = customer_limit + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
- break;
- default:
- chnlGroup = 0;
- write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][j] +
- ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
- break;
- }
-/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
-/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
-/* In the future, two mechanism shall be separated from each other and maintained independently. Thanks for Lanhsin's reminder. */
- /* 92d do not need this */
- if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
- write_val = 0x14141414;
- else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
- write_val = 0x00000000;
-
- *(out_val + rf) = write_val;
- }
-}
-
-static void write_ofdm_pwr_reg(struct adapter *adapt, u8 index, u32 *pvalue)
-{
- u16 regoffset_a[6] = { rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
- rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
- rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12 };
- u16 regoffset_b[6] = { rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
- rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
- rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12 };
- u8 i, rf, pwr_val[4];
- u32 write_val;
- u16 regoffset;
-
- for (rf = 0; rf < 2; rf++) {
- write_val = pvalue[rf];
- for (i = 0; i < 4; i++) {
- pwr_val[i] = (u8)((write_val & (0x7f << (i * 8))) >> (i * 8));
- if (pwr_val[i] > RF6052_MAX_TX_PWR)
- pwr_val[i] = RF6052_MAX_TX_PWR;
- }
- write_val = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
- (pwr_val[1] << 8) | pwr_val[0];
-
- if (rf == 0)
- regoffset = regoffset_a[index];
- else
- regoffset = regoffset_b[index];
-
- phy_set_bb_reg(adapt, regoffset, bMaskDWord, write_val);
- }
-}
-
-void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt,
- u8 *pwr_level_ofdm,
- u8 *pwr_level_bw20,
- u8 *pwr_level_bw40, u8 channel)
-{
- u32 write_val[2], powerbase0[2], powerbase1[2], pwrtrac_value;
- u8 direction;
- u8 index = 0;
-
- getpowerbase88e(adapt, pwr_level_ofdm, pwr_level_bw20, pwr_level_bw40,
- channel, &powerbase0[0], &powerbase1[0]);
-
- rtl88eu_dm_txpower_track_adjust(&adapt->HalData->odmpriv, 0,
- &direction, &pwrtrac_value);
-
- for (index = 0; index < 6; index++) {
- get_rx_power_val_by_reg(adapt, channel, index,
- &powerbase0[0], &powerbase1[0],
- &write_val[0]);
-
- if (direction == 1) {
- write_val[0] += pwrtrac_value;
- write_val[1] += pwrtrac_value;
- } else if (direction == 2) {
- write_val[0] -= pwrtrac_value;
- write_val[1] -= pwrtrac_value;
- }
- write_ofdm_pwr_reg(adapt, index, &write_val[0]);
- }
-}
diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c
deleted file mode 100644
index d39e1bd97f85..000000000000
--- a/drivers/staging/rtl8188eu/hal/rf_cfg.c
+++ /dev/null
@@ -1,247 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include "odm_precomp.h"
-
-#include <phy.h>
-
-static bool check_condition(struct adapter *adapt, const u32 condition)
-{
- struct odm_dm_struct *odm = &adapt->HalData->odmpriv;
- u32 _board = odm->BoardType;
- u32 _platform = odm->SupportPlatform;
- u32 _interface = odm->SupportInterface;
- u32 cond;
-
- if (condition == 0xCDCDCDCD)
- return true;
-
- cond = condition & 0x000000FF;
- if ((_board == cond) && cond != 0x00)
- return false;
-
- cond = condition & 0x0000FF00;
- cond >>= 8;
- if ((_interface & cond) == 0 && cond != 0x07)
- return false;
-
- cond = condition & 0x00FF0000;
- cond >>= 16;
- if ((_platform & cond) == 0 && cond != 0x0F)
- return false;
- return true;
-}
-
-/* RadioA_1T.TXT */
-
-static u32 Array_RadioA_1T_8188E[] = {
- 0x000, 0x00030000,
- 0x008, 0x00084000,
- 0x018, 0x00000407,
- 0x019, 0x00000012,
- 0x01E, 0x00080009,
- 0x01F, 0x00000880,
- 0x02F, 0x0001A060,
- 0x03F, 0x00000000,
- 0x042, 0x000060C0,
- 0x057, 0x000D0000,
- 0x058, 0x000BE180,
- 0x067, 0x00001552,
- 0x083, 0x00000000,
- 0x0B0, 0x000FF8FC,
- 0x0B1, 0x00054400,
- 0x0B2, 0x000CCC19,
- 0x0B4, 0x00043003,
- 0x0B6, 0x0004953E,
- 0x0B7, 0x0001C718,
- 0x0B8, 0x000060FF,
- 0x0B9, 0x00080001,
- 0x0BA, 0x00040000,
- 0x0BB, 0x00000400,
- 0x0BF, 0x000C0000,
- 0x0C2, 0x00002400,
- 0x0C3, 0x00000009,
- 0x0C4, 0x00040C91,
- 0x0C5, 0x00099999,
- 0x0C6, 0x000000A3,
- 0x0C7, 0x00088820,
- 0x0C8, 0x00076C06,
- 0x0C9, 0x00000000,
- 0x0CA, 0x00080000,
- 0x0DF, 0x00000180,
- 0x0EF, 0x000001A0,
- 0x051, 0x0006B27D,
- 0xFF0F041F, 0xABCD,
- 0x052, 0x0007E4DD,
- 0xCDCDCDCD, 0xCDCD,
- 0x052, 0x0007E49D,
- 0xFF0F041F, 0xDEAD,
- 0x053, 0x00000073,
- 0x056, 0x00051FF3,
- 0x035, 0x00000086,
- 0x035, 0x00000186,
- 0x035, 0x00000286,
- 0x036, 0x00001C25,
- 0x036, 0x00009C25,
- 0x036, 0x00011C25,
- 0x036, 0x00019C25,
- 0x0B6, 0x00048538,
- 0x018, 0x00000C07,
- 0x05A, 0x0004BD00,
- 0x019, 0x000739D0,
- 0x034, 0x0000ADF3,
- 0x034, 0x00009DF0,
- 0x034, 0x00008DED,
- 0x034, 0x00007DEA,
- 0x034, 0x00006DE7,
- 0x034, 0x000054EE,
- 0x034, 0x000044EB,
- 0x034, 0x000034E8,
- 0x034, 0x0000246B,
- 0x034, 0x00001468,
- 0x034, 0x0000006D,
- 0x000, 0x00030159,
- 0x084, 0x00068200,
- 0x086, 0x000000CE,
- 0x087, 0x00048A00,
- 0x08E, 0x00065540,
- 0x08F, 0x00088000,
- 0x0EF, 0x000020A0,
- 0x03B, 0x000F02B0,
- 0x03B, 0x000EF7B0,
- 0x03B, 0x000D4FB0,
- 0x03B, 0x000CF060,
- 0x03B, 0x000B0090,
- 0x03B, 0x000A0080,
- 0x03B, 0x00090080,
- 0x03B, 0x0008F780,
- 0x03B, 0x000722B0,
- 0x03B, 0x0006F7B0,
- 0x03B, 0x00054FB0,
- 0x03B, 0x0004F060,
- 0x03B, 0x00030090,
- 0x03B, 0x00020080,
- 0x03B, 0x00010080,
- 0x03B, 0x0000F780,
- 0x0EF, 0x000000A0,
- 0x000, 0x00010159,
- 0x018, 0x0000F407,
- 0xFFE, 0x00000000,
- 0xFFE, 0x00000000,
- 0x01F, 0x00080003,
- 0xFFE, 0x00000000,
- 0xFFE, 0x00000000,
- 0x01E, 0x00000001,
- 0x01F, 0x00080000,
- 0x000, 0x00033E60,
-};
-
-#define READ_NEXT_PAIR(v1, v2, i) \
-do { \
- i += 2; v1 = array[i]; \
- v2 = array[i + 1]; \
-} while (0)
-
-#define RFREG_OFFSET_MASK 0xfffff
-#define B3WIREADDREAALENGTH 0x400
-#define B3WIREDATALENGTH 0x800
-#define BRFSI_RFENV 0x10
-
-static void rtl_rfreg_delay(struct adapter *adapt, enum rf_radio_path rfpath, u32 addr, u32 mask, u32 data)
-{
- if (addr == 0xfe) {
- mdelay(50);
- } else if (addr == 0xfd) {
- mdelay(5);
- } else if (addr == 0xfc) {
- mdelay(1);
- } else if (addr == 0xfb) {
- udelay(50);
- } else if (addr == 0xfa) {
- udelay(5);
- } else if (addr == 0xf9) {
- udelay(1);
- } else {
- phy_set_rf_reg(adapt, rfpath, addr, mask, data);
- udelay(1);
- }
-}
-
-static void rtl8188e_config_rf_reg(struct adapter *adapt, u32 addr, u32 data)
-{
- u32 content = 0x1000; /*RF Content: radio_a_txt*/
- u32 maskforphyset = content & 0xE000;
-
- rtl_rfreg_delay(adapt, RF_PATH_A, addr | maskforphyset,
- RFREG_OFFSET_MASK,
- data);
-}
-
-static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt)
-{
- u32 i;
- u32 array_len = ARRAY_SIZE(Array_RadioA_1T_8188E);
- u32 *array = Array_RadioA_1T_8188E;
-
- for (i = 0; i < array_len; i += 2) {
- u32 v1 = array[i];
- u32 v2 = array[i + 1];
-
- if (v1 < 0xCDCDCDCD) {
- rtl8188e_config_rf_reg(adapt, v1, v2);
- continue;
- } else {
- if (!check_condition(adapt, array[i])) {
- READ_NEXT_PAIR(v1, v2, i);
- while (v2 != 0xDEAD && v2 != 0xCDEF &&
- v2 != 0xCDCD && i < array_len - 2)
- READ_NEXT_PAIR(v1, v2, i);
- i -= 2;
- } else {
- READ_NEXT_PAIR(v1, v2, i);
- while (v2 != 0xDEAD && v2 != 0xCDEF &&
- v2 != 0xCDCD && i < array_len - 2) {
- rtl8188e_config_rf_reg(adapt, v1, v2);
- READ_NEXT_PAIR(v1, v2, i);
- }
-
- while (v2 != 0xDEAD && i < array_len - 2)
- READ_NEXT_PAIR(v1, v2, i);
- }
- }
- }
- return true;
-}
-
-bool rtl88eu_phy_rf_config(struct adapter *adapt)
-{
- struct hal_data_8188e *hal_data = adapt->HalData;
- u32 u4val = 0;
- bool rtstatus;
- struct bb_reg_def *pphyreg;
-
- pphyreg = &hal_data->PHYRegDef[RF90_PATH_A];
- u4val = phy_query_bb_reg(adapt, pphyreg->rfintfs, BRFSI_RFENV);
-
- phy_set_bb_reg(adapt, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
- udelay(1);
-
- phy_set_bb_reg(adapt, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
- udelay(1);
-
- phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2, B3WIREADDREAALENGTH, 0x0);
- udelay(1);
-
- phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2, B3WIREDATALENGTH, 0x0);
- udelay(1);
-
- rtstatus = rtl88e_phy_config_rf_with_headerfile(adapt);
-
- phy_set_bb_reg(adapt, pphyreg->rfintfs, BRFSI_RFENV, u4val);
-
- return rtstatus;
-}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
deleted file mode 100644
index 10e88f976163..000000000000
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
+++ /dev/null
@@ -1,217 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-/* */
-/* Description: */
-/* */
-/* This file is for 92CE/92CU dynamic mechanism only */
-/* */
-/* */
-/* */
-#define _RTL8188E_DM_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-
-#include <rtl8188e_hal.h>
-
-/* Initialize GPIO setting registers */
-static void dm_InitGPIOSetting(struct adapter *Adapter)
-{
- u8 tmp1byte;
-
- tmp1byte = usb_read8(Adapter, REG_GPIO_MUXCFG);
- tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
-
- usb_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
-}
-
-static void Init_ODM_ComInfo_88E(struct adapter *Adapter)
-{
- struct hal_data_8188e *hal_data = Adapter->HalData;
- struct dm_priv *pdmpriv = &hal_data->dmpriv;
- struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
-
- /* Init Value */
- memset(dm_odm, 0, sizeof(*dm_odm));
-
- dm_odm->Adapter = Adapter;
- dm_odm->SupportPlatform = ODM_CE;
- dm_odm->SupportICType = ODM_RTL8188E;
- dm_odm->CutVersion = ODM_CUT_A;
- dm_odm->bIsMPChip = hal_data->VersionID.ChipType == NORMAL_CHIP;
- dm_odm->PatchID = hal_data->CustomerID;
- dm_odm->bWIFITest = Adapter->registrypriv.wifi_spec;
-
- dm_odm->AntDivType = hal_data->TRxAntDivType;
-
- /* Tx power tracking BB swing table.
- * The base index =
- * 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB
- */
- dm_odm->BbSwingIdxOfdm = 12; /* Set default value as index 12. */
- dm_odm->BbSwingIdxOfdmCurrent = 12;
- dm_odm->BbSwingFlagOfdm = false;
-
- pdmpriv->InitODMFlag = ODM_RF_CALIBRATION |
- ODM_RF_TX_PWR_TRACK;
-
- dm_odm->SupportAbility = pdmpriv->InitODMFlag;
-}
-
-static void Update_ODM_ComInfo_88E(struct adapter *Adapter)
-{
- struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
- struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
- struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
- struct hal_data_8188e *hal_data = Adapter->HalData;
- struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
- struct dm_priv *pdmpriv = &hal_data->dmpriv;
- int i;
-
- pdmpriv->InitODMFlag = ODM_BB_DIG |
- ODM_BB_RA_MASK |
- ODM_BB_DYNAMIC_TXPWR |
- ODM_BB_FA_CNT |
- ODM_BB_RSSI_MONITOR |
- ODM_BB_CCK_PD |
- ODM_BB_PWR_SAVE |
- ODM_MAC_EDCA_TURBO |
- ODM_RF_CALIBRATION |
- ODM_RF_TX_PWR_TRACK;
- if (hal_data->AntDivCfg)
- pdmpriv->InitODMFlag |= ODM_BB_ANT_DIV;
-
- if (Adapter->registrypriv.mp_mode == 1) {
- pdmpriv->InitODMFlag = ODM_RF_CALIBRATION |
- ODM_RF_TX_PWR_TRACK;
- }
-
- dm_odm->SupportAbility = pdmpriv->InitODMFlag;
-
- dm_odm->pNumTxBytesUnicast = &Adapter->xmitpriv.tx_bytes;
- dm_odm->pNumRxBytesUnicast = &Adapter->recvpriv.rx_bytes;
- dm_odm->pWirelessMode = &pmlmeext->cur_wireless_mode;
- dm_odm->pSecChOffset = &hal_data->nCur40MhzPrimeSC;
- dm_odm->pSecurity = (u8 *)&Adapter->securitypriv.dot11PrivacyAlgrthm;
- dm_odm->pBandWidth = (u8 *)&hal_data->CurrentChannelBW;
- dm_odm->pChannel = &hal_data->CurrentChannel;
- dm_odm->pbNet_closed = (bool *)&Adapter->net_closed;
- dm_odm->mp_mode = &Adapter->registrypriv.mp_mode;
- dm_odm->pbScanInProcess = (bool *)&pmlmepriv->bScanInProcess;
- dm_odm->pbPowerSaving = (bool *)&pwrctrlpriv->bpower_saving;
- dm_odm->AntDivType = hal_data->TRxAntDivType;
-
- /* Tx power tracking BB swing table.
- * The base index =
- * 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB
- */
- dm_odm->BbSwingIdxOfdm = 12; /* Set default value as index 12. */
- dm_odm->BbSwingIdxOfdmCurrent = 12;
- dm_odm->BbSwingFlagOfdm = false;
-
- for (i = 0; i < NUM_STA; i++)
- ODM_CmnInfoPtrArrayHook(dm_odm, ODM_CMNINFO_STA_STATUS, i,
- NULL);
-}
-
-void rtl8188e_InitHalDm(struct adapter *Adapter)
-{
- struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv;
- struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv;
-
- dm_InitGPIOSetting(Adapter);
- pdmpriv->DM_Type = DM_Type_ByDriver;
- pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
- Update_ODM_ComInfo_88E(Adapter);
- ODM_DMInit(dm_odm);
-}
-
-void rtw_hal_dm_watchdog(struct adapter *Adapter)
-{
- u8 hw_init_completed = false;
- struct mlme_priv *pmlmepriv = NULL;
- u8 bLinked = false;
-
- hw_init_completed = Adapter->hw_init_completed;
-
- if (!hw_init_completed)
- goto skip_dm;
-
- /* ODM */
- pmlmepriv = &Adapter->mlmepriv;
-
- if ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE |
- WIFI_ADHOC_MASTER_STATE))) {
- if (Adapter->stapriv.asoc_sta_count > 2)
- bLinked = true;
- } else {/* Station mode */
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- bLinked = true;
- }
-
- Adapter->HalData->odmpriv.bLinked = bLinked;
- ODM_DMWatchdog(&Adapter->HalData->odmpriv);
-skip_dm:
- /* Check GPIO to determine current RF on/off and Pbc status. */
- /* Check Hardware Radio ON/OFF or not */
- return;
-}
-
-void rtw_hal_dm_init(struct adapter *Adapter)
-{
- struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv;
-
- memset(pdmpriv, 0, sizeof(struct dm_priv));
- Init_ODM_ComInfo_88E(Adapter);
-}
-
-/* Add new function to reset the state of antenna diversity before link. */
-/* Compare RSSI for deciding antenna */
-void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter,
- struct wlan_bssid_ex *dst,
- struct wlan_bssid_ex *src)
-{
- if (Adapter->HalData->AntDivCfg != 0) {
- /* select optimum_antenna for before linked => For antenna
- * diversity
- */
- if (dst->Rssi >= src->Rssi) {/* keep org parameter */
- src->Rssi = dst->Rssi;
- src->PhyInfo.Optimum_antenna =
- dst->PhyInfo.Optimum_antenna;
- }
- }
-}
-
-/* Add new function to reset the state of antenna diversity before link. */
-bool rtw_hal_antdiv_before_linked(struct adapter *Adapter)
-{
- struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv;
- struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table;
- struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
-
- /* Condition that does not need to use antenna diversity. */
- if (Adapter->HalData->AntDivCfg == 0)
- return false;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- return false;
-
- if (dm_swat_tbl->SWAS_NoLink_State != 0) {
- dm_swat_tbl->SWAS_NoLink_State = 0;
- return false;
- }
-
- /* switch channel */
- dm_swat_tbl->SWAS_NoLink_State = 1;
- dm_swat_tbl->CurAntenna = (dm_swat_tbl->CurAntenna == Antenna_A) ?
- Antenna_B : Antenna_A;
-
- rtw_antenna_select_cmd(Adapter, dm_swat_tbl->CurAntenna, false);
- return true;
-}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
deleted file mode 100644
index d1086699f952..000000000000
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+++ /dev/null
@@ -1,523 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _HAL_INIT_C_
-
-#include <linux/firmware.h>
-#include <linux/vmalloc.h>
-#include <drv_types.h>
-#include <rtw_efuse.h>
-#include <phy.h>
-#include <rtl8188e_hal.h>
-
-#include <rtw_iol.h>
-
-void iol_mode_enable(struct adapter *padapter, u8 enable)
-{
- u8 reg_0xf0 = 0;
-
- if (enable) {
- /* Enable initial offload */
- reg_0xf0 = usb_read8(padapter, REG_SYS_CFG);
- usb_write8(padapter, REG_SYS_CFG, reg_0xf0 | SW_OFFLOAD_EN);
-
- if (!padapter->bFWReady)
- _8051Reset88E(padapter);
- } else {
- /* disable initial offload */
- reg_0xf0 = usb_read8(padapter, REG_SYS_CFG);
- usb_write8(padapter, REG_SYS_CFG, reg_0xf0 & ~SW_OFFLOAD_EN);
- }
-}
-
-s32 iol_execute(struct adapter *padapter, u8 control)
-{
- s32 status = _FAIL;
- u8 reg_0x88 = 0;
- unsigned long start = 0;
-
- control = control & 0x0f;
- reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0);
- usb_write8(padapter, REG_HMEBOX_E0, reg_0x88 | control);
-
- start = jiffies;
- while ((reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0)) & control &&
- jiffies_to_msecs(jiffies - start) < 1000) {
- udelay(5);
- }
-
- reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0);
- status = (reg_0x88 & control) ? _FAIL : _SUCCESS;
- if (reg_0x88 & control << 4)
- status = _FAIL;
- return status;
-}
-
-static s32 iol_InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy)
-{
- s32 rst = _SUCCESS;
-
- iol_mode_enable(padapter, 1);
- usb_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy);
- rst = iol_execute(padapter, CMD_INIT_LLT);
- iol_mode_enable(padapter, 0);
- return rst;
-}
-
-s32 rtl8188e_iol_efuse_patch(struct adapter *padapter)
-{
- s32 result = _SUCCESS;
-
- if (rtw_iol_applied(padapter)) {
- iol_mode_enable(padapter, 1);
- result = iol_execute(padapter, CMD_READ_EFUSE_MAP);
- if (result == _SUCCESS)
- result = iol_execute(padapter, CMD_EFUSE_PATCH);
-
- iol_mode_enable(padapter, 0);
- }
- return result;
-}
-
-#define MAX_REG_BOLCK_SIZE 196
-
-void _8051Reset88E(struct adapter *padapter)
-{
- u8 u1bTmp;
-
- u1bTmp = usb_read8(padapter, REG_SYS_FUNC_EN + 1);
- usb_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp & (~BIT(2)));
- usb_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp | (BIT(2)));
-}
-
-void rtl8188e_InitializeFirmwareVars(struct adapter *padapter)
-{
- /* Init Fw LPS related. */
- padapter->pwrctrlpriv.bFwCurrentInPSMode = false;
-
- /* Init H2C counter. by tynli. 2009.12.09. */
- padapter->HalData->LastHMEBoxNum = 0;
-}
-
-void rtw_hal_free_data(struct adapter *padapter)
-{
- kfree(padapter->HalData);
- padapter->HalData = NULL;
-}
-
-void rtw_hal_read_chip_version(struct adapter *padapter)
-{
- u32 value32;
- struct HAL_VERSION ChipVersion;
- struct hal_data_8188e *pHalData = padapter->HalData;
-
- value32 = usb_read32(padapter, REG_SYS_CFG);
- ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
- ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
- ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
-
- dump_chip_info(ChipVersion);
-
- pHalData->VersionID = ChipVersion;
-}
-
-void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
-{
- struct odm_dm_struct *podmpriv = &Adapter->HalData->odmpriv;
-
- switch (eVariable) {
- case HAL_ODM_STA_INFO:
- {
- struct sta_info *psta = pValue1;
-
- if (bSet) {
- ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, psta);
- ODM_RAInfo_Init(podmpriv, psta->mac_id);
- } else {
- ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, NULL);
- }
- }
- break;
- case HAL_ODM_P2P_STATE:
- podmpriv->bWIFI_Direct = bSet;
- break;
- case HAL_ODM_WIFI_DISPLAY_STATE:
- podmpriv->bWIFI_Display = bSet;
- break;
- default:
- break;
- }
-}
-
-void rtw_hal_notch_filter(struct adapter *adapter, bool enable)
-{
- if (enable)
- usb_write8(adapter, rOFDM0_RxDSP + 1, usb_read8(adapter, rOFDM0_RxDSP + 1) | BIT(1));
- else
- usb_write8(adapter, rOFDM0_RxDSP + 1, usb_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT(1));
-}
-
-/* */
-/* */
-/* LLT R/W/Init function */
-/* */
-/* */
-static s32 _LLTWrite(struct adapter *padapter, u32 address, u32 data)
-{
- s32 status = _SUCCESS;
- s32 count = 0;
- u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
- u16 LLTReg = REG_LLT_INIT;
-
- usb_write32(padapter, LLTReg, value);
-
- /* polling */
- do {
- value = usb_read32(padapter, LLTReg);
- if (_LLT_OP_VALUE(value) == _LLT_NO_ACTIVE)
- break;
-
- if (count > POLLING_LLT_THRESHOLD) {
- status = _FAIL;
- break;
- }
- udelay(5);
- } while (count++);
-
- return status;
-}
-
-s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy)
-{
- s32 status = _FAIL;
- u32 i;
- u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;/* 176, 22k */
-
- if (rtw_iol_applied(padapter)) {
- status = iol_InitLLTTable(padapter, txpktbuf_bndy);
- } else {
- for (i = 0; i < (txpktbuf_bndy - 1); i++) {
- status = _LLTWrite(padapter, i, i + 1);
- if (status != _SUCCESS)
- return status;
- }
-
- /* end of list */
- status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
- if (status != _SUCCESS)
- return status;
-
- /* Make the other pages as ring buffer */
- /* This ring buffer is used as beacon buffer if we config this MAC as two MAC transfer. */
- /* Otherwise used as local loopback buffer. */
- for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
- status = _LLTWrite(padapter, i, (i + 1));
- if (status != _SUCCESS)
- return status;
- }
-
- /* Let last entry point to the start entry of ring buffer */
- status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
- if (status != _SUCCESS)
- return status;
- }
-
- return status;
-}
-
-void Hal_InitPGData88E(struct adapter *padapter)
-{
- if (!is_boot_from_eeprom(padapter))
- EFUSE_ShadowMapUpdate(padapter);
-}
-
-void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo)
-{
- struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
- u16 EEPROMId;
-
- /* Checl 0x8129 again for making sure autoload status!! */
- EEPROMId = le16_to_cpu(*((__le16 *)hwinfo));
- if (EEPROMId != RTL_EEPROM_ID)
- pEEPROM->bautoload_fail_flag = true;
- else
- pEEPROM->bautoload_fail_flag = false;
-}
-
-static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G, u8 *PROMContent, bool AutoLoadFail)
-{
- u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_88E, group, TxCount = 0;
-
- memset(pwrInfo24G, 0, sizeof(struct txpowerinfo24g));
-
- if (AutoLoadFail) {
- for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
- /* 2.4G default value */
- for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
- pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
- pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
- }
- for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
- if (TxCount == 0) {
- pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF;
- pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF;
- } else {
- pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
- pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
- pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
- pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
- }
- }
- }
- return;
- }
-
- for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
- /* 2.4G default value */
- for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
- pwrInfo24G->IndexCCK_Base[rfPath][group] = PROMContent[eeAddr++];
- if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF)
- pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
- }
- for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) {
- pwrInfo24G->IndexBW40_Base[rfPath][group] = PROMContent[eeAddr++];
- if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF)
- pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
- }
- for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
- if (TxCount == 0) {
- pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0;
- if (PROMContent[eeAddr] == 0xFF) {
- pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
- } else {
- pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4;
- if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
- pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
- }
-
- if (PROMContent[eeAddr] == 0xFF) {
- pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF;
- } else {
- pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f);
- if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
- pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
- }
- pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
- eeAddr++;
- } else {
- if (PROMContent[eeAddr] == 0xFF) {
- pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
- } else {
- pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4;
- if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
- pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
- }
-
- if (PROMContent[eeAddr] == 0xFF) {
- pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
- } else {
- pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f);
- if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
- pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
- }
- eeAddr++;
-
- if (PROMContent[eeAddr] == 0xFF) {
- pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
- } else {
- pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4;
- if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
- pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
- }
-
- if (PROMContent[eeAddr] == 0xFF) {
- pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
- } else {
- pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f);
- if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
- pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
- }
- eeAddr++;
- }
- }
- }
-}
-
-void Hal_GetChnlGroup88E(u8 chnl, u8 *group)
-{
- if (chnl < 3) /* Channel 1-2 */
- *group = 0;
- else if (chnl < 6) /* Channel 3-5 */
- *group = 1;
- else if (chnl < 9) /* Channel 6-8 */
- *group = 2;
- else if (chnl < 12) /* Channel 9-11 */
- *group = 3;
- else if (chnl < 14) /* Channel 12-13 */
- *group = 4;
- else if (chnl == 14) /* Channel 14 */
- *group = 5;
-}
-
-void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
-{
- if (AutoLoadFail) {
- padapter->pwrctrlpriv.bHWPowerdown = false;
- padapter->pwrctrlpriv.bSupportRemoteWakeup = false;
- } else {
- /* hw power down mode selection , 0:rf-off / 1:power down */
-
- if (padapter->registrypriv.hwpdn_mode == 2)
- padapter->pwrctrlpriv.bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT(4));
- else
- padapter->pwrctrlpriv.bHWPowerdown = padapter->registrypriv.hwpdn_mode;
-
- /* decide hw if support remote wakeup function */
- /* if hw supported, 8051 (SIE) will generate WeakUP signal(D+/D- toggle) when autoresume */
- padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT(1)) ? true : false;
- }
-}
-
-void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail)
-{
- struct hal_data_8188e *pHalData = padapter->HalData;
- struct txpowerinfo24g pwrInfo24G;
- u8 ch, group;
- u8 TxCount;
-
- Hal_ReadPowerValueFromPROM_8188E(&pwrInfo24G, PROMContent, AutoLoadFail);
-
- if (!AutoLoadFail)
- pHalData->bTXPowerDataReadFromEEPORM = true;
-
- for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
- Hal_GetChnlGroup88E(ch, &group);
- pHalData->Index24G_CCK_Base[0][ch] = pwrInfo24G.IndexCCK_Base[0][group];
- if (ch == 14)
- pHalData->Index24G_BW40_Base[0][ch] = pwrInfo24G.IndexBW40_Base[0][4];
- else
- pHalData->Index24G_BW40_Base[0][ch] = pwrInfo24G.IndexBW40_Base[0][group];
- }
- for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
- pHalData->CCK_24G_Diff[0][TxCount] = pwrInfo24G.CCK_Diff[0][TxCount];
- pHalData->OFDM_24G_Diff[0][TxCount] = pwrInfo24G.OFDM_Diff[0][TxCount];
- pHalData->BW20_24G_Diff[0][TxCount] = pwrInfo24G.BW20_Diff[0][TxCount];
- pHalData->BW40_24G_Diff[0][TxCount] = pwrInfo24G.BW40_Diff[0][TxCount];
- }
-
- /* 2010/10/19 MH Add Regulator recognize for CU. */
- if (!AutoLoadFail) {
- pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x7); /* bit0~2 */
- if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
- pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION & 0x7); /* bit0~2 */
- } else {
- pHalData->EEPROMRegulatory = 0;
- }
-}
-
-void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail)
-{
- struct hal_data_8188e *pHalData = pAdapter->HalData;
-
- if (!AutoLoadFail) {
- pHalData->CrystalCap = hwinfo[EEPROM_XTAL_88E];
- if (pHalData->CrystalCap == 0xFF)
- pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E;
- } else {
- pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E;
- }
-}
-
-void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail)
-{
- struct hal_data_8188e *pHalData = pAdapter->HalData;
-
- if (!AutoLoadFail)
- pHalData->BoardType = (hwinfo[EEPROM_RF_BOARD_OPTION_88E]
- & 0xE0) >> 5;
- else
- pHalData->BoardType = 0;
-}
-
-void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
-{
- struct hal_data_8188e *pHalData = padapter->HalData;
-
- if (!AutoLoadFail) {
- pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_88E];
- if (pHalData->EEPROMVersion == 0xFF)
- pHalData->EEPROMVersion = EEPROM_Default_Version;
- } else {
- pHalData->EEPROMVersion = 1;
- }
-}
-
-void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
-{
- padapter->mlmepriv.ChannelPlan =
- hal_com_get_channel_plan(hwinfo ? hwinfo[EEPROM_ChannelPlan_88E] : 0xFF,
- padapter->registrypriv.channel_plan,
- RT_CHANNEL_DOMAIN_WORLD_WIDE_13, AutoLoadFail);
-
-}
-
-void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
-{
- struct hal_data_8188e *pHalData = padapter->HalData;
-
- if (!AutoLoadFail) {
- pHalData->EEPROMCustomerID = hwinfo[EEPROM_CUSTOMERID_88E];
- } else {
- pHalData->EEPROMCustomerID = 0;
- pHalData->EEPROMSubCustomerID = 0;
- }
-}
-
-void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool AutoLoadFail)
-{
- struct hal_data_8188e *pHalData = pAdapter->HalData;
- struct registry_priv *registry_par = &pAdapter->registrypriv;
-
- if (!AutoLoadFail) {
- /* Antenna Diversity setting. */
- if (registry_par->antdiv_cfg == 2) { /* 2:By EFUSE */
- pHalData->AntDivCfg = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x18) >> 3;
- if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
- pHalData->AntDivCfg = (EEPROM_DEFAULT_BOARD_OPTION & 0x18) >> 3;
- } else {
- pHalData->AntDivCfg = registry_par->antdiv_cfg; /* 0:OFF , 1:ON, 2:By EFUSE */
- }
-
- if (registry_par->antdiv_type == 0) {
- /* If TRxAntDivType is AUTO in advanced setting, use EFUSE value instead. */
- pHalData->TRxAntDivType = PROMContent[EEPROM_RF_ANTENNA_OPT_88E];
- if (pHalData->TRxAntDivType == 0xFF)
- pHalData->TRxAntDivType = CG_TRX_HW_ANTDIV; /* For 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */
- } else {
- pHalData->TRxAntDivType = registry_par->antdiv_type;
- }
-
- if (pHalData->TRxAntDivType == CG_TRX_HW_ANTDIV || pHalData->TRxAntDivType == CGCS_RX_HW_ANTDIV)
- pHalData->AntDivCfg = 1; /* 0xC1[3] is ignored. */
- } else {
- pHalData->AntDivCfg = 0;
- }
-}
-
-void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail)
-{
- struct hal_data_8188e *pHalData = Adapter->HalData;
-
- /* ThermalMeter from EEPROM */
- if (!AutoloadFail)
- pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_88E];
- else
- pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E;
-
- if (pHalData->EEPROMThermalMeter == 0xff || AutoloadFail) {
- pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E;
- }
-}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
deleted file mode 100644
index 25ce6db3beae..000000000000
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
+++ /dev/null
@@ -1,55 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <rtl8188e_hal.h>
-#include <usb_ops_linux.h>
-
-void sw_led_on(struct adapter *padapter, struct LED_871x *pLed)
-{
- u8 led_cfg;
-
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
- return;
- led_cfg = usb_read8(padapter, REG_LEDCFG2);
- usb_write8(padapter, REG_LEDCFG2, (led_cfg & 0xf0) | BIT(5) | BIT(6));
- pLed->led_on = true;
-}
-
-void sw_led_off(struct adapter *padapter, struct LED_871x *pLed)
-{
- u8 led_cfg;
-
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
- goto exit;
-
- led_cfg = usb_read8(padapter, REG_LEDCFG2);/* 0x4E */
-
- /* Open-drain arrangement for controlling the LED) */
- led_cfg &= 0x90; /* Set to software control. */
- usb_write8(padapter, REG_LEDCFG2, (led_cfg | BIT(3)));
- led_cfg = usb_read8(padapter, REG_MAC_PINMUX_CFG);
- led_cfg &= 0xFE;
- usb_write8(padapter, REG_MAC_PINMUX_CFG, led_cfg);
-exit:
- pLed->led_on = false;
-}
-
-void rtw_hal_sw_led_init(struct adapter *padapter)
-{
- struct led_priv *pledpriv = &padapter->ledpriv;
-
- InitLed871x(padapter, &pledpriv->sw_led);
-}
-
-void rtw_hal_sw_led_deinit(struct adapter *padapter)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
-
- DeInitLed871x(&ledpriv->sw_led);
-}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
deleted file mode 100644
index aa69fc3880b3..000000000000
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
+++ /dev/null
@@ -1,83 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _RTL8188EU_RECV_C_
-#include <linux/kmemleak.h>
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <mlme_osdep.h>
-
-#include <usb_ops_linux.h>
-#include <wifi.h>
-
-#include <rtl8188e_hal.h>
-
-int rtw_hal_init_recv_priv(struct adapter *padapter)
-{
- struct recv_priv *precvpriv = &padapter->recvpriv;
- int i, res = _SUCCESS;
- struct recv_buf *precvbuf;
-
- tasklet_setup(&precvpriv->recv_tasklet, rtl8188eu_recv_tasklet);
-
- /* init recv_buf */
- _rtw_init_queue(&precvpriv->free_recv_buf_queue);
-
- precvpriv->precv_buf =
- kcalloc(NR_RECVBUFF, sizeof(struct recv_buf), GFP_KERNEL);
- if (!precvpriv->precv_buf) {
- res = _FAIL;
- goto exit;
- }
- precvbuf = precvpriv->precv_buf;
-
- for (i = 0; i < NR_RECVBUFF; i++) {
- res = rtw_os_recvbuf_resource_alloc(precvbuf);
- if (res == _FAIL)
- break;
- precvbuf->adapter = padapter;
- precvbuf++;
- }
- skb_queue_head_init(&precvpriv->rx_skb_queue);
- {
- int i;
- struct sk_buff *pskb = NULL;
-
- skb_queue_head_init(&precvpriv->free_recv_skb_queue);
-
- for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
- pskb = __netdev_alloc_skb(padapter->pnetdev,
- MAX_RECVBUF_SZ, GFP_KERNEL);
- if (pskb) {
- kmemleak_not_leak(pskb);
- skb_queue_tail(&precvpriv->free_recv_skb_queue,
- pskb);
- }
- pskb = NULL;
- }
- }
-exit:
- return res;
-}
-
-void rtw_hal_free_recv_priv(struct adapter *padapter)
-{
- int i;
- struct recv_buf *precvbuf;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- precvbuf = precvpriv->precv_buf;
-
- for (i = 0; i < NR_RECVBUFF; i++) {
- usb_free_urb(precvbuf->purb);
- precvbuf++;
- }
-
- kfree(precvpriv->precv_buf);
- skb_queue_purge(&precvpriv->rx_skb_queue);
- skb_queue_purge(&precvpriv->free_recv_skb_queue);
-}
diff --git a/drivers/staging/rtl8188eu/include/HalVerDef.h b/drivers/staging/rtl8188eu/include/HalVerDef.h
deleted file mode 100644
index 63a144ee2183..000000000000
--- a/drivers/staging/rtl8188eu/include/HalVerDef.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __HAL_VERSION_DEF_H__
-#define __HAL_VERSION_DEF_H__
-
-enum HAL_CHIP_TYPE {
- TEST_CHIP = 0,
- NORMAL_CHIP = 1,
- FPGA = 2,
-};
-
-enum HAL_CUT_VERSION {
- A_CUT_VERSION = 0,
- B_CUT_VERSION = 1,
- C_CUT_VERSION = 2,
- D_CUT_VERSION = 3,
- E_CUT_VERSION = 4,
- F_CUT_VERSION = 5,
- G_CUT_VERSION = 6,
-};
-
-enum HAL_VENDOR {
- CHIP_VENDOR_TSMC = 0,
- CHIP_VENDOR_UMC = 1,
-};
-
-struct HAL_VERSION {
- enum HAL_CHIP_TYPE ChipType;
- enum HAL_CUT_VERSION CUTVersion;
- enum HAL_VENDOR VendorType;
-};
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h
deleted file mode 100644
index 3609a44ed078..000000000000
--- a/drivers/staging/rtl8188eu/include/drv_types.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-/*-----------------------------------------------------------------------------
-
- For type defines and data structure defines
-
-------------------------------------------------------------------------------*/
-
-#ifndef __DRV_TYPES_H__
-#define __DRV_TYPES_H__
-
-#define DRV_NAME "r8188eu"
-
-#include <osdep_service.h>
-#include <wlan_bssdef.h>
-#include <rtw_ht.h>
-#include <rtw_cmd.h>
-#include <rtw_xmit.h>
-#include <rtw_recv.h>
-#include <hal_intf.h>
-#include <hal_com.h>
-#include <rtw_security.h>
-#include <rtw_pwrctrl.h>
-#include <rtw_eeprom.h>
-#include <sta_info.h>
-
-struct qos_priv {
- /* bit mask option: u-apsd, s-apsd, ts, block ack... */
- unsigned int qos_option;
-};
-
-#include <rtw_mlme.h>
-#include <rtw_rf.h>
-#include <rtw_event.h>
-#include <rtw_led.h>
-#include <rtw_mlme_ext.h>
-#include <rtw_ap.h>
-
-#define SPEC_DEV_ID_NONE BIT(0)
-#define SPEC_DEV_ID_DISABLE_HT BIT(1)
-#define SPEC_DEV_ID_ENABLE_PS BIT(2)
-#define SPEC_DEV_ID_RF_CONFIG_1T1R BIT(3)
-#define SPEC_DEV_ID_RF_CONFIG_2T2R BIT(4)
-#define SPEC_DEV_ID_ASSIGN_IFNAME BIT(5)
-
-struct registry_priv {
- struct ndis_802_11_ssid ssid;
- u8 channel;/* ad-hoc support requirement */
- u8 wireless_mode;/* A, B, G, auto */
- u8 preamble;/* long, short, auto */
- u8 vrtl_carrier_sense;/* Enable, Disable, Auto */
- u8 vcs_type;/* RTS/CTS, CTS-to-self */
- u16 rts_thresh;
- u16 frag_thresh;
- u8 power_mgnt;
- u8 ips_mode;
- u8 smart_ps;
- u8 mp_mode;
- u8 acm_method;
- /* UAPSD */
- u8 wmm_enable;
- u8 uapsd_enable;
-
- struct wlan_bssid_ex dev_network;
-
- u8 ht_enable;
- u8 cbw40_enable;
- u8 ampdu_enable;/* for tx */
- u8 rx_stbc;
- u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */
-
- u8 wifi_spec;/* !turbo_mode */
-
- u8 channel_plan;
- bool accept_addba_req; /* true = accept AP's Add BA req */
-
- u8 antdiv_cfg;
- u8 antdiv_type;
-
- u8 usbss_enable;/* 0:disable,1:enable */
- u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */
-
- u8 max_roaming_times; /* the max number driver will try */
-
- u8 fw_iol; /* enable iol without other concern */
-
- u8 enable80211d;
-
- u8 ifname[16];
- u8 if2name[16];
-
- u8 notch_filter;
- bool monitor_enable;
-};
-
-#define MAX_CONTINUAL_URB_ERR 4
-
-struct dvobj_priv {
- struct adapter *if1;
- /* For 92D, DMDP have 2 interface. */
- u8 InterfaceNumber;
- u8 NumInterfaces;
-
- /* In /Out Pipe information */
- int RtInPipe[2];
- int RtOutPipe[3];
- u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */
-
-/*-------- below is for USB INTERFACE --------*/
- u8 ishighspeed;
- u8 RtNumInPipes;
- u8 RtNumOutPipes;
- struct mutex usb_vendor_req_mutex;
-
- struct usb_interface *pusbintf;
- struct usb_device *pusbdev;
-};
-
-static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj)
-{
- /* todo: get interface type from dvobj and the return
- * the dev accordingly
- */
- return &dvobj->pusbintf->dev;
-};
-
-struct adapter {
- struct dvobj_priv *dvobj;
- struct mlme_priv mlmepriv;
- struct mlme_ext_priv mlmeextpriv;
- struct cmd_priv cmdpriv;
- struct xmit_priv xmitpriv;
- struct recv_priv recvpriv;
- struct sta_priv stapriv;
- struct security_priv securitypriv;
- struct registry_priv registrypriv;
- struct pwrctrl_priv pwrctrlpriv;
- struct eeprom_priv eeprompriv;
- struct led_priv ledpriv;
-
- struct hal_data_8188e *HalData;
-
- s32 bDriverStopped;
- s32 bSurpriseRemoved;
-
- u8 hw_init_completed;
-
- struct task_struct *cmdThread;
- struct net_device *pnetdev;
- struct net_device *pmondev;
-
- int bup;
- struct net_device_stats stats;
- struct iw_statistics iwstats;
- struct proc_dir_entry *dir_dev;/* for proc directory */
-
- int net_closed;
- u8 bFWReady;
- u8 bReadPortCancel;
- u8 bWritePortCancel;
-
- struct mutex hw_init_mutex;
-};
-
-#define adapter_to_dvobj(adapter) (adapter->dvobj)
-
-static inline u8 *myid(struct eeprom_priv *peepriv)
-{
- return peepriv->mac_addr;
-}
-
-#endif /* __DRV_TYPES_H__ */
diff --git a/drivers/staging/rtl8188eu/include/fw.h b/drivers/staging/rtl8188eu/include/fw.h
deleted file mode 100644
index 9f010c4b8f9c..000000000000
--- a/drivers/staging/rtl8188eu/include/fw.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2009-2013 Realtek Corporation.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-#include "drv_types.h"
-#include <linux/types.h>
-
-#ifndef __RTL92C__FW__H__
-#define __RTL92C__FW__H__
-
-#define FW_8192C_START_ADDRESS 0x1000
-#define FW_8192C_PAGE_SIZE 4096
-#define FW_8192C_POLLING_DELAY 5
-
-struct rtl92c_firmware_header {
- __le16 signature;
- u8 category;
- u8 function;
- u16 version;
- u8 subversion;
- u8 rsvd1;
- u8 month;
- u8 date;
- u8 hour;
- u8 minute;
- u16 ramcodesize;
- u16 rsvd2;
- u32 svnindex;
- u32 rsvd3;
- u32 rsvd4;
- u32 rsvd5;
-};
-
-int rtl88eu_download_fw(struct adapter *adapt);
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h
deleted file mode 100644
index bd915a1f2511..000000000000
--- a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __INC_HAL8188EPHYREG_H__
-#define __INC_HAL8188EPHYREG_H__
-/*--------------------------Define Parameters-------------------------------*/
-/* */
-/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */
-/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */
-/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
-/* 3. RF register 0x00-2E */
-/* 4. Bit Mask for BB/RF register */
-/* 5. Other definition for BB/RF R/W */
-/* */
-
-/* 3. Page8(0x800) */
-#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting */
-#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */
-
-#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */
-#define rFPGA0_XA_HSSIParameter2 0x824
-#define rFPGA0_XB_HSSIParameter1 0x828
-#define rFPGA0_XB_HSSIParameter2 0x82c
-
-#define rFPGA0_XA_LSSIParameter 0x840
-#define rFPGA0_XB_LSSIParameter 0x844
-
-#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */
-#define rFPGA0_XCD_SwitchControl 0x85c
-
-#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */
-#define rFPGA0_XB_RFInterfaceOE 0x864
-
-#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Iface Software Control */
-#define rFPGA0_XCD_RFInterfaceSW 0x874
-
-#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */
-
-#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */
-#define rFPGA0_XB_LSSIReadBack 0x8a4
-
-#define TransceiverA_HSPI_Readback 0x8b8
-#define TransceiverB_HSPI_Readback 0x8bc
-#define rFPGA0_XAB_RFInterfaceRB 0x8e0
-
-/* 4. Page9(0x900) */
-/* RF mode & OFDM TxSC RF BW Setting?? */
-#define rFPGA1_RFMOD 0x900
-
-/* 5. PageA(0xA00) */
-/* Set Control channel to upper or lower - required only for 40MHz */
-#define rCCK0_System 0xa00
-
-/* */
-/* PageB(0xB00) */
-/* */
-#define rConfig_AntA 0xb68
-#define rConfig_AntB 0xb6c
-
-/* */
-/* 6. PageC(0xC00) */
-/* */
-#define rOFDM0_TRxPathEnable 0xc04
-#define rOFDM0_TRMuxPar 0xc08
-
-/* RxIQ DC offset, Rx digital filter, DC notch filter */
-#define rOFDM0_XARxAFE 0xc10
-#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */
-#define rOFDM0_XBRxAFE 0xc18
-#define rOFDM0_XBRxIQImbalance 0xc1c
-
-#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */
-#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */
-
-#define rOFDM0_XAAGCCore1 0xc50 /* DIG */
-#define rOFDM0_XAAGCCore2 0xc54
-#define rOFDM0_XBAGCCore1 0xc58
-#define rOFDM0_XBAGCCore2 0xc5c
-
-#define rOFDM0_AGCRSSITable 0xc78
-
-#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */
-#define rOFDM0_XATxAFE 0xc84
-#define rOFDM0_XBTxIQImbalance 0xc88
-#define rOFDM0_XBTxAFE 0xc8c
-#define rOFDM0_XCTxAFE 0xc94
-#define rOFDM0_XDTxAFE 0xc9c
-
-#define rOFDM0_RxIQExtAnta 0xca0
-
-/* */
-/* 7. PageD(0xD00) */
-/* */
-#define rOFDM1_LSTF 0xd00
-
-/* */
-/* 8. PageE(0xE00) */
-/* */
-#define rTxAGC_A_Rate18_06 0xe00
-#define rTxAGC_A_Rate54_24 0xe04
-#define rTxAGC_A_CCK1_Mcs32 0xe08
-#define rTxAGC_A_Mcs03_Mcs00 0xe10
-#define rTxAGC_A_Mcs07_Mcs04 0xe14
-#define rTxAGC_A_Mcs11_Mcs08 0xe18
-#define rTxAGC_A_Mcs15_Mcs12 0xe1c
-
-#define rTxAGC_B_Rate18_06 0x830
-#define rTxAGC_B_Rate54_24 0x834
-#define rTxAGC_B_CCK1_55_Mcs32 0x838
-#define rTxAGC_B_Mcs03_Mcs00 0x83c
-#define rTxAGC_B_Mcs07_Mcs04 0x848
-#define rTxAGC_B_Mcs11_Mcs08 0x84c
-#define rTxAGC_B_Mcs15_Mcs12 0x868
-#define rTxAGC_B_CCK11_A_CCK2_11 0x86c
-
-#define rFPGA0_IQK 0xe28
-#define rTx_IQK_Tone_A 0xe30
-#define rRx_IQK_Tone_A 0xe34
-#define rTx_IQK_PI_A 0xe38
-#define rRx_IQK_PI_A 0xe3c
-
-#define rTx_IQK 0xe40
-#define rRx_IQK 0xe44
-#define rIQK_AGC_Pts 0xe48
-#define rIQK_AGC_Rsp 0xe4c
-#define rIQK_AGC_Cont 0xe60
-
-#define rBlue_Tooth 0xe6c
-#define rRx_Wait_CCA 0xe70
-#define rTx_CCK_RFON 0xe74
-#define rTx_CCK_BBON 0xe78
-#define rTx_OFDM_RFON 0xe7c
-#define rTx_OFDM_BBON 0xe80
-#define rTx_To_Rx 0xe84
-#define rTx_To_Tx 0xe88
-#define rRx_CCK 0xe8c
-
-#define rTx_Power_Before_IQK_A 0xe94
-#define rTx_Power_After_IQK_A 0xe9c
-
-#define rRx_Power_Before_IQK_A_2 0xea4
-#define rRx_Power_After_IQK_A_2 0xeac
-
-#define rTx_Power_Before_IQK_B 0xeb4
-#define rTx_Power_After_IQK_B 0xebc
-
-#define rRx_Power_Before_IQK_B_2 0xec4
-#define rRx_Power_After_IQK_B_2 0xecc
-
-#define rRx_OFDM 0xed0
-#define rRx_Wait_RIFS 0xed4
-#define rRx_TO_Rx 0xed8
-#define rStandby 0xedc
-#define rSleep 0xee0
-#define rPMPD_ANAEN 0xeec
-
-/* */
-/* RL6052 Register definition */
-/* */
-#define RF_AC 0x00 /* */
-#define RF_CHNLBW 0x18 /* RF channel and BW switch */
-#define RF_T_METER_88E 0x42 /* */
-#define RF_RCK_OS 0x30 /* RF TX PA control */
-#define RF_TXPA_G1 0x31 /* RF TX PA control */
-#define RF_TXPA_G2 0x32 /* RF TX PA control */
-#define RF_WE_LUT 0xEF
-
-/* */
-/* Bit Mask */
-/* */
-
-/* 2. Page8(0x800) */
-#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */
-#define bCCKEn 0x1000000
-#define bOFDMEn 0x2000000
-
-#define bLSSIReadAddress 0x7f800000 /* T65 RF */
-#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */
-#define bLSSIReadBackData 0xfffff /* T65 RF */
-
-#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 */
-
-/* */
-/* Other Definition */
-/* */
-
-/* for PutRegsetting & GetRegSetting BitMask */
-#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */
-#define bMaskByte1 0xff00
-#define bMaskByte3 0xff000000
-#define bMaskDWord 0xffffffff
-#define bMask12Bits 0xfff
-#define bMaskOFDM_D 0xffc00000
-
-/* for PutRFRegsetting & GetRFRegSetting BitMask */
-#define bRFRegOffsetMask 0xfffff
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h b/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h
deleted file mode 100644
index 646647feae85..000000000000
--- a/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __INC_RA_H
-#define __INC_RA_H
-/*
- * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
- *
- * Module Name:
- * RateAdaptive.h
- *
- * Abstract:
- * Prototype of RA and related data structure.
- *
- * Major Change History:
- * When Who What
- * ---------- --------------- -------------------------------
- * 2011-08-12 Page Create.
- */
-
-/* Rate adaptive define */
-#define PERENTRY 23
-#define RETRYSIZE 5
-#define RATESIZE 28
-#define TX_RPT2_ITEM_SIZE 8
-
-/* */
-/* TX report 2 format in Rx desc */
-/* */
-#define GET_TX_RPT2_DESC_PKT_LEN_88E(__pRxStatusDesc) \
- LE_BITS_TO_4BYTE(__pRxStatusDesc, 0, 9)
-#define GET_TX_RPT2_DESC_MACID_VALID_1_88E(__pRxStatusDesc) \
- LE_BITS_TO_4BYTE(__pRxStatusDesc + 16, 0, 32)
-#define GET_TX_RPT2_DESC_MACID_VALID_2_88E(__pRxStatusDesc) \
- LE_BITS_TO_4BYTE(__pRxStatusDesc + 20, 0, 32)
-
-#define GET_TX_REPORT_TYPE1_RERTY_0(__pAddr) \
- LE_BITS_TO_4BYTE(__pAddr, 0, 16)
-#define GET_TX_REPORT_TYPE1_RERTY_1(__pAddr) \
- LE_BITS_TO_1BYTE(__pAddr + 2, 0, 8)
-#define GET_TX_REPORT_TYPE1_RERTY_2(__pAddr) \
- LE_BITS_TO_1BYTE(__pAddr + 3, 0, 8)
-#define GET_TX_REPORT_TYPE1_RERTY_3(__pAddr) \
- LE_BITS_TO_1BYTE(__pAddr + 4, 0, 8)
-#define GET_TX_REPORT_TYPE1_RERTY_4(__pAddr) \
- LE_BITS_TO_1BYTE(__pAddr + 4 + 1, 0, 8)
-#define GET_TX_REPORT_TYPE1_DROP_0(__pAddr) \
- LE_BITS_TO_1BYTE(__pAddr + 4 + 2, 0, 8)
-#define GET_TX_REPORT_TYPE1_DROP_1(__pAddr) \
- LE_BITS_TO_1BYTE(__pAddr + 4 + 3, 0, 8)
-
-/* End rate adaptive define */
-
-int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm);
-
-int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 MacID);
-
-u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
-
-u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
-
-u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
-void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 MacID,
- u8 RateID, u32 RateMask,
- u8 SGIEnable);
-
-void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid,
- u8 rssi);
-
-void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm,
- u8 *txrpt_buf, u16 txrpt_len,
- u32 validentry0, u32 validentry1);
-
-void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime);
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h
deleted file mode 100644
index 2e3e933781eb..000000000000
--- a/drivers/staging/rtl8188eu/include/hal_intf.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __HAL_INTF_H__
-#define __HAL_INTF_H__
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <hal8188e_phy_cfg.h>
-
-enum RTL871X_HCI_TYPE {
- RTW_PCIE = BIT(0),
- RTW_USB = BIT(1),
- RTW_SDIO = BIT(2),
- RTW_GSPI = BIT(3),
-};
-
-enum _CHIP_TYPE {
- NULL_CHIP_TYPE,
- RTL8712_8188S_8191S_8192S,
- RTL8188C_8192C,
- RTL8192D,
- RTL8723A,
- RTL8188E,
- MAX_CHIP_TYPE
-};
-
-enum hw_variables {
- HW_VAR_MEDIA_STATUS,
- HW_VAR_MEDIA_STATUS1,
- HW_VAR_SET_OPMODE,
- HW_VAR_MAC_ADDR,
- HW_VAR_BSSID,
- HW_VAR_INIT_RTS_RATE,
- HW_VAR_BASIC_RATE,
- HW_VAR_TXPAUSE,
- HW_VAR_BCN_FUNC,
- HW_VAR_CORRECT_TSF,
- HW_VAR_CHECK_BSSID,
- HW_VAR_MLME_DISCONNECT,
- HW_VAR_MLME_SITESURVEY,
- HW_VAR_MLME_JOIN,
- HW_VAR_BEACON_INTERVAL,
- HW_VAR_SLOT_TIME,
- HW_VAR_RESP_SIFS,
- HW_VAR_ACK_PREAMBLE,
- HW_VAR_SEC_CFG,
- HW_VAR_BCN_VALID,
- HW_VAR_DM_FUNC_OP,
- HW_VAR_DM_FUNC_SET,
- HW_VAR_DM_FUNC_CLR,
- HW_VAR_CAM_EMPTY_ENTRY,
- HW_VAR_CAM_INVALID_ALL,
- HW_VAR_CAM_WRITE,
- HW_VAR_CAM_READ,
- HW_VAR_AC_PARAM_VO,
- HW_VAR_AC_PARAM_VI,
- HW_VAR_AC_PARAM_BE,
- HW_VAR_AC_PARAM_BK,
- HW_VAR_ACM_CTRL,
- HW_VAR_AMPDU_MIN_SPACE,
- HW_VAR_AMPDU_FACTOR,
- HW_VAR_RXDMA_AGG_PG_TH,
- HW_VAR_SET_RPWM,
- HW_VAR_H2C_FW_PWRMODE,
- HW_VAR_H2C_FW_JOINBSSRPT,
- HW_VAR_FWLPS_RF_ON,
- HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
- HW_VAR_TDLS_WRCR,
- HW_VAR_TDLS_INIT_CH_SEN,
- HW_VAR_TDLS_RS_RCR,
- HW_VAR_TDLS_DONE_CH_SEN,
- HW_VAR_INITIAL_GAIN,
- HW_VAR_TRIGGER_GPIO_0,
- HW_VAR_BT_SET_COEXIST,
- HW_VAR_BT_ISSUE_DELBA,
- HW_VAR_CURRENT_ANTENNA,
- HW_VAR_ANTENNA_DIVERSITY_LINK,
- HW_VAR_ANTENNA_DIVERSITY_SELECT,
- HW_VAR_SWITCH_EPHY_WoWLAN,
- HW_VAR_EFUSE_USAGE,
- HW_VAR_EFUSE_BYTES,
- HW_VAR_EFUSE_BT_USAGE,
- HW_VAR_EFUSE_BT_BYTES,
- HW_VAR_FIFO_CLEARN_UP,
- HW_VAR_CHECK_TXBUF,
- HW_VAR_APFM_ON_MAC, /* Auto FSM to Turn On, include clock, isolation,
- * power control for MAC only
- */
- /* The valid upper nav range for the HW updating, if the true value is
- * larger than the upper range, the HW won't update it.
- */
- /* Unit in microsecond. 0 means disable this function. */
- HW_VAR_NAV_UPPER,
- HW_VAR_RPT_TIMER_SETTING,
- HW_VAR_TX_RPT_MAX_MACID,
- HW_VAR_H2C_MEDIA_STATUS_RPT,
- HW_VAR_CHK_HI_QUEUE_EMPTY,
-};
-
-enum hal_def_variable {
- HAL_DEF_UNDERCORATEDSMOOTHEDPWDB,
- HAL_DEF_IS_SUPPORT_ANT_DIV,
- HAL_DEF_CURRENT_ANTENNA,
- HAL_DEF_DRVINFO_SZ,
- HAL_DEF_MAX_RECVBUF_SZ,
- HAL_DEF_RX_PACKET_OFFSET,
- HAL_DEF_DBG_DUMP_RXPKT,/* for dbg */
- HAL_DEF_DBG_DM_FUNC,/* for dbg */
- HAL_DEF_RA_DECISION_RATE,
- HAL_DEF_RA_SGI,
- HAL_DEF_PT_PWR_STATUS,
- HW_VAR_MAX_RX_AMPDU_FACTOR,
- HW_DEF_RA_INFO_DUMP,
- HAL_DEF_DBG_DUMP_TXPKT,
- HW_DEF_FA_CNT_DUMP,
-};
-
-enum hal_odm_variable {
- HAL_ODM_STA_INFO,
- HAL_ODM_P2P_STATE,
- HAL_ODM_WIFI_DISPLAY_STATE,
-};
-
-enum hal_intf_ps_func {
- HAL_USB_SELECT_SUSPEND,
- HAL_MAX_ID,
-};
-
-enum rt_eeprom_type {
- EEPROM_93C46,
- EEPROM_93C56,
- EEPROM_BOOT_EFUSE,
-};
-
-#define RF_CHANGE_BY_INIT 0
-#define RF_CHANGE_BY_IPS BIT(28)
-#define RF_CHANGE_BY_PS BIT(29)
-#define RF_CHANGE_BY_HW BIT(30)
-#define RF_CHANGE_BY_SW BIT(31)
-
-enum hardware_type {
- HARDWARE_TYPE_RTL8188EU,
- HARDWARE_TYPE_MAX,
-};
-
-#define GET_EEPROM_EFUSE_PRIV(adapter) (&adapter->eeprompriv)
-
-#define is_boot_from_eeprom(adapter) (adapter->eeprompriv.EepromOrEfuse)
-
-void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level);
-u32 rtl8188eu_hal_deinit(struct adapter *Adapter);
-u32 rtl8188eu_hal_init(struct adapter *Adapter);
-void rtw_hal_def_value_init(struct adapter *padapter);
-
-void rtw_hal_free_data(struct adapter *padapter);
-
-void rtw_hal_dm_init(struct adapter *padapter);
-void rtw_hal_sw_led_init(struct adapter *padapter);
-void rtw_hal_sw_led_deinit(struct adapter *padapter);
-
-u32 rtw_hal_power_on(struct adapter *padapter);
-uint rtw_hal_init(struct adapter *padapter);
-uint rtw_hal_deinit(struct adapter *padapter);
-void rtw_hal_stop(struct adapter *padapter);
-void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val);
-void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val);
-
-void rtw_hal_chip_configure(struct adapter *padapter);
-void rtw_hal_read_chip_info(struct adapter *padapter);
-void rtw_hal_read_chip_version(struct adapter *padapter);
-
-u8 rtw_hal_get_def_var(struct adapter *padapter,
- enum hal_def_variable eVariable, void *pValue);
-
-void rtw_hal_set_odm_var(struct adapter *padapter,
- enum hal_odm_variable eVariable, void *pValue1,
- bool bSet);
-
-u32 rtw_hal_inirp_init(struct adapter *padapter);
-void rtw_hal_inirp_deinit(struct adapter *padapter);
-void usb_intf_stop(struct adapter *padapter);
-
-bool rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe);
-s32 rtw_hal_mgnt_xmit(struct adapter *padapter,
- struct xmit_frame *pmgntframe);
-
-s32 rtw_hal_init_xmit_priv(struct adapter *padapter);
-
-int rtw_hal_init_recv_priv(struct adapter *padapter);
-void rtw_hal_free_recv_priv(struct adapter *padapter);
-
-void rtw_hal_update_ra_mask(struct adapter *padapter, u32 mac_id, u8 level);
-void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, u8 level);
-void rtw_hal_clone_data(struct adapter *dst_adapt,
- struct adapter *src_adapt);
-
-void beacon_timing_control(struct adapter *padapter);
-
-u32 rtw_hal_read_rfreg(struct adapter *padapter, enum rf_radio_path eRFPath,
- u32 RegAddr, u32 BitMask);
-
-void rtw_hal_set_bwmode(struct adapter *padapter,
- enum ht_channel_width Bandwidth, u8 Offset);
-void rtw_hal_set_chan(struct adapter *padapter, u8 channel);
-void rtw_hal_dm_watchdog(struct adapter *padapter);
-
-bool rtw_hal_antdiv_before_linked(struct adapter *padapter);
-void rtw_hal_antdiv_rssi_compared(struct adapter *padapter,
- struct wlan_bssid_ex *dst,
- struct wlan_bssid_ex *src);
-
-void rtw_hal_sreset_init(struct adapter *padapter);
-
-void rtw_hal_notch_filter(struct adapter *adapter, bool enable);
-
-void indicate_wx_scan_complete_event(struct adapter *padapter);
-u8 rtw_do_join(struct adapter *padapter);
-
-#endif /* __HAL_INTF_H__ */
diff --git a/drivers/staging/rtl8188eu/include/mon.h b/drivers/staging/rtl8188eu/include/mon.h
deleted file mode 100644
index 297710626d72..000000000000
--- a/drivers/staging/rtl8188eu/include/mon.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * RTL8188EU monitor interface
- *
- * Copyright (C) 2015 Jakub Sitnicki
- */
-
-/*
- * Monitor interface receives all transmitted and received IEEE 802.11
- * frames, both Data and Management, and passes them up to userspace
- * preserving the WLAN headers.
- */
-
-#ifndef _MON_H_
-#define _MON_H_
-
-struct net_device;
-struct recv_frame;
-struct xmit_frame;
-
-struct net_device *rtl88eu_mon_init(void);
-void rtl88eu_mon_deinit(struct net_device *dev);
-
-void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame);
-void rtl88eu_mon_xmit_hook(struct net_device *dev, struct xmit_frame *frame,
- uint frag_len);
-
-#endif /* _MON_H_ */
diff --git a/drivers/staging/rtl8188eu/include/odm_rtl8188e.h b/drivers/staging/rtl8188eu/include/odm_rtl8188e.h
deleted file mode 100644
index dbf13c48767d..000000000000
--- a/drivers/staging/rtl8188eu/include/odm_rtl8188e.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __ODM_RTL8188E_H__
-#define __ODM_RTL8188E_H__
-
-#define MAIN_ANT 0
-#define AUX_ANT 1
-#define MAIN_ANT_CG_TRX 1
-#define AUX_ANT_CG_TRX 0
-#define MAIN_ANT_CGCS_RX 0
-#define AUX_ANT_CGCS_RX 1
-
-void ODM_DIG_LowerBound_88E(struct odm_dm_struct *pDM_Odm);
-
-void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm);
-
-void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm);
-
-void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm, u8 *desc,
- u8 mac_id);
-
-void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant);
-
-void rtl88eu_dm_ant_sel_statistics(struct odm_dm_struct *dm_odm, u8 antsel_tr_mux,
- u32 mac_id, u8 rx_pwdb_all);
-
-void odm_FastAntTraining(struct odm_dm_struct *pDM_Odm);
-
-void odm_FastAntTrainingCallback(struct odm_dm_struct *pDM_Odm);
-
-void odm_FastAntTrainingWorkItemCallback(struct odm_dm_struct *pDM_Odm);
-
-bool ODM_DynamicPrimaryCCA_DupRTS(struct odm_dm_struct *pDM_Odm);
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/odm_types.h b/drivers/staging/rtl8188eu/include/odm_types.h
deleted file mode 100644
index 2b207f09b56b..000000000000
--- a/drivers/staging/rtl8188eu/include/odm_types.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __ODM_TYPES_H__
-#define __ODM_TYPES_H__
-
-#define ODM_CE 0x04 /* BIT2 */
-
-enum HAL_STATUS {
- HAL_STATUS_SUCCESS,
- HAL_STATUS_FAILURE,
-};
-
-#define SET_TX_DESC_ANTSEL_A_88E(__pTxDesc, __Value) \
- SET_BITS_TO_LE_4BYTE(__pTxDesc + 8, 24, 1, __Value)
-#define SET_TX_DESC_ANTSEL_B_88E(__pTxDesc, __Value) \
- SET_BITS_TO_LE_4BYTE(__pTxDesc + 8, 25, 1, __Value)
-#define SET_TX_DESC_ANTSEL_C_88E(__pTxDesc, __Value) \
- SET_BITS_TO_LE_4BYTE(__pTxDesc + 28, 29, 1, __Value)
-
-#endif /* __ODM_TYPES_H__ */
diff --git a/drivers/staging/rtl8188eu/include/osdep_intf.h b/drivers/staging/rtl8188eu/include/osdep_intf.h
deleted file mode 100644
index 34decb03e92f..000000000000
--- a/drivers/staging/rtl8188eu/include/osdep_intf.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#ifndef __OSDEP_INTF_H_
-#define __OSDEP_INTF_H_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-
-extern char *rtw_initmac;
-extern int rtw_mc2u_disable;
-
-u8 rtw_init_drv_sw(struct adapter *padapter);
-u8 rtw_free_drv_sw(struct adapter *padapter);
-u8 rtw_reset_drv_sw(struct adapter *padapter);
-
-void rtw_stop_drv_threads(struct adapter *padapter);
-void rtw_cancel_all_timer(struct adapter *padapter);
-
-int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-int rtw_android_priv_cmd(struct net_device *dev, struct ifreq *rq,
- void __user *data, int cmd);
-
-struct net_device *rtw_init_netdev(void);
-u16 rtw_recv_select_queue(struct sk_buff *skb);
-
-int netdev_open(struct net_device *pnetdev);
-int ips_netdrv_open(struct adapter *padapter);
-void rtw_ips_dev_unload(struct adapter *padapter);
-int rtw_ips_pwr_up(struct adapter *padapter);
-void rtw_ips_pwr_down(struct adapter *padapter);
-
-#endif /* _OSDEP_INTF_H_ */
diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h
deleted file mode 100644
index efd0833e28c8..000000000000
--- a/drivers/staging/rtl8188eu/include/osdep_service.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __OSDEP_SERVICE_H_
-#define __OSDEP_SERVICE_H_
-
-#include <basic_types.h>
-
-#define _FAIL 0
-#define _SUCCESS 1
-#define RTW_RX_HANDLED 2
-
-#include <linux/spinlock.h>
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/circ_buf.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/atomic.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/sem.h>
-#include <linux/sched/signal.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-#include <net/iw_handler.h>
-#include <linux/if_arp.h>
-#include <linux/rtnetlink.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h> /* for struct tasklet_struct */
-#include <linux/ip.h>
-#include <linux/kthread.h>
-
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-
-struct __queue {
- struct list_head queue;
- spinlock_t lock;
-};
-
-static inline struct list_head *get_list_head(struct __queue *queue)
-{
- return &queue->queue;
-}
-
-static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
-{
- return netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) &&
- netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 1)) &&
- netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 2)) &&
- netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3));
-}
-
-u8 *_rtw_malloc(u32 sz);
-#define rtw_malloc(sz) _rtw_malloc((sz))
-
-void _rtw_init_queue(struct __queue *pqueue);
-
-#define FUNC_NDEV_FMT "%s(%s)"
-#define FUNC_NDEV_ARG(ndev) __func__, ndev->name
-#define FUNC_ADPT_FMT "%s(%s)"
-#define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name
-
-/* Macros for handling unaligned memory accesses */
-
-#define RTW_GET_BE24(a) ((((u32)(a)[0]) << 16) | (((u32)(a)[1]) << 8) | \
- ((u32)(a)[2]))
-
-void rtw_buf_free(u8 **buf, u32 *buf_len);
-void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len);
-#endif
diff --git a/drivers/staging/rtl8188eu/include/phy.h b/drivers/staging/rtl8188eu/include/phy.h
deleted file mode 100644
index 40901d6dcaf5..000000000000
--- a/drivers/staging/rtl8188eu/include/phy.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <odm.h>
-
-#define IQK_DELAY_TIME_88E 10
-#define index_mapping_NUM_88E 15
-#define AVG_THERMAL_NUM_88E 4
-
-bool rtl88eu_phy_mac_config(struct adapter *adapt);
-bool rtl88eu_phy_rf_config(struct adapter *adapt);
-bool rtl88eu_phy_bb_config(struct adapter *adapt);
-
-u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask);
-void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data);
-u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path,
- u32 reg_addr, u32 bit_mask);
-void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
- u32 reg_addr, u32 bit_mask, u32 data);
-
-void phy_set_tx_power_level(struct adapter *adapt, u8 channel);
-
-void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm,
- u8 type, u8 *dir, u32 *out_write);
-
-void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt);
-void rtl88eu_phy_iq_calibrate(struct adapter *adapter, bool recovery);
-void rtl88eu_phy_lc_calibrate(struct adapter *adapter);
diff --git a/drivers/staging/rtl8188eu/include/phydm_reg.h b/drivers/staging/rtl8188eu/include/phydm_reg.h
deleted file mode 100644
index e3ae006487ba..000000000000
--- a/drivers/staging/rtl8188eu/include/phydm_reg.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2016 Realtek Corporation.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-#ifndef __HAL_ODM_REG_H__
-#define __HAL_ODM_REG_H__
-
-#define ODM_EDCA_VO_PARAM 0x500
-#define ODM_EDCA_VI_PARAM 0x504
-#define ODM_EDCA_BE_PARAM 0x508
-#define ODM_EDCA_BK_PARAM 0x50C
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/phydm_regdefine11n.h b/drivers/staging/rtl8188eu/include/phydm_regdefine11n.h
deleted file mode 100644
index 565996828cab..000000000000
--- a/drivers/staging/rtl8188eu/include/phydm_regdefine11n.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2016 Realtek Corporation.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-
-#ifndef __ODM_REGDEFINE11N_H__
-#define __ODM_REGDEFINE11N_H__
-
-#define ODM_REG_TX_ANT_CTRL_11N 0x80C
-#define ODM_REG_RX_DEFAULT_A_11N 0x858
-#define ODM_REG_ANTSEL_CTRL_11N 0x860
-#define ODM_REG_RX_ANT_CTRL_11N 0x864
-#define ODM_REG_PIN_CTRL_11N 0x870
-#define ODM_REG_SC_CNT_11N 0x8C4
-
-#define ODM_REG_ANT_MAPPING1_11N 0x914
-
-#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00
-#define ODM_REG_CCK_CCA_11N 0xA0A
-#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C
-#define ODM_REG_CCK_FA_RST_11N 0xA2C
-#define ODM_REG_CCK_FA_MSB_11N 0xA58
-#define ODM_REG_CCK_FA_LSB_11N 0xA5C
-#define ODM_REG_CCK_CCA_CNT_11N 0xA60
-#define ODM_REG_BB_PWR_SAV4_11N 0xA74
-
-#define ODM_REG_LNA_SWITCH_11N 0xB2C
-
-#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00
-#define ODM_REG_IGI_A_11N 0xC50
-#define ODM_REG_ANTDIV_PARA1_11N 0xCA4
-#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0
-
-#define ODM_REG_OFDM_FA_RSTD_11N 0xD00
-#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0
-#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4
-#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8
-
-#define ODM_REG_ANTSEL_PIN_11N 0x4C
-#define ODM_REG_RESP_TX_11N 0x6D8
-
-#define ODM_BIT_IGI_11N 0x0000007F
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/pwrseq.h b/drivers/staging/rtl8188eu/include/pwrseq.h
deleted file mode 100644
index c4b76064476f..000000000000
--- a/drivers/staging/rtl8188eu/include/pwrseq.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#ifndef __HAL8188EPWRSEQ_H__
-#define __HAL8188EPWRSEQ_H__
-
-#include "pwrseqcmd.h"
-
-/*
- * Check document WM-20110607-Paul-RTL8188E_Power_Architecture-R02.vsd
- * There are 6 HW Power States:
- * 0: POFF--Power Off
- * 1: PDN--Power Down
- * 2: CARDEMU--Card Emulation
- * 3: ACT--Active Mode
- * 4: LPS--Low Power State
- * 5: SUS--Suspend
- *
- * The transition from different states are defined below
- * TRANS_CARDEMU_TO_ACT
- * TRANS_ACT_TO_CARDEMU
- * TRANS_CARDEMU_TO_SUS
- * TRANS_SUS_TO_CARDEMU
- * TRANS_CARDEMU_TO_PDN
- * TRANS_ACT_TO_LPS
- * TRANS_LPS_TO_ACT
- *
- * TRANS_END
- *
- * PWR SEQ Version: rtl8188E_PwrSeq_V09.h
- */
-#define RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS 10
-#define RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS 10
-#define RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS 10
-#define RTL8188E_TRANS_SUS_TO_CARDEMU_STEPS 10
-#define RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS 10
-#define RTL8188E_TRANS_PDN_TO_CARDEMU_STEPS 10
-#define RTL8188E_TRANS_ACT_TO_LPS_STEPS 15
-#define RTL8188E_TRANS_LPS_TO_ACT_STEPS 15
-#define RTL8188E_TRANS_END_STEPS 1
-
-#define RTL8188E_TRANS_CARDEMU_TO_ACT \
- /* format
- * { offset, cut_msk, cmd, msk, value
- * },
- * comment here
- */ \
- {0x0006, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
- /* wait till 0x04[17] = 1 power ready*/ \
- {0x0002, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(0) | BIT(1), 0}, \
- /* 0x02[1:0] = 0 reset BB*/ \
- {0x0026, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
- /*0x24[23] = 2b'01 schmit trigger */ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), 0}, \
- /* 0x04[15] = 0 disable HWPDN (control by DRV)*/ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4) | BIT(3), 0}, \
- /*0x04[12:11] = 2b'00 disable WL suspend*/ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
- /*0x04[8] = 1 polling until return 0*/ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, BIT(0), 0}, \
- /*wait till 0x04[8] = 0*/ \
- {0x0023, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), 0}, \
- /*LDO normal mode*/
-
-#define RTL8188E_TRANS_ACT_TO_CARDEMU \
- /* format
- * { offset, cut_msk, cmd, msk, value
- * },
- * comments here
- */ \
- {0x001F, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0}, \
- /*0x1F[7:0] = 0 turn off RF*/ \
- {0x0023, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
- /*LDO Sleep mode*/ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
- /*0x04[9] = 1 turn off MAC by HW state machine*/ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, BIT(1), 0}, \
- /*wait till 0x04[9] = 0 polling until return 0 to disable*/
-
-#define RTL8188E_TRANS_CARDEMU_TO_SUS \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, \
- /* 0x04[12:11] = 2b'01enable WL suspend */ \
- {0x0007, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, BIT(7)}, \
- /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
- {0x0041, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), 0}, \
- /*Clear SIC_EN register 0x40[12] = 1'b0 */ \
- {0xfe10, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
- /*Set USB suspend enable local register 0xfe10[4]=1 */
-
-#define RTL8188E_TRANS_SUS_TO_CARDEMU \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, \
- /*0x04[12:11] = 2b'01enable WL suspend*/
-
-#define RTL8188E_TRANS_CARDEMU_TO_CARDDIS \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0x0026, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
- /*0x24[23] = 2b'01 schmit trigger */ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, \
- /*0x04[12:11] = 2b'01 enable WL suspend*/ \
- {0x0007, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0}, \
- /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
- {0x0041, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), 0}, \
- /*Clear SIC_EN register 0x40[12] = 1'b0 */ \
- {0xfe10, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
- /*Set USB suspend enable local register 0xfe10[4]=1 */
-
-#define RTL8188E_TRANS_CARDDIS_TO_CARDEMU \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, \
- /*0x04[12:11] = 2b'01enable WL suspend*/
-
-#define RTL8188E_TRANS_CARDEMU_TO_PDN \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0x0006, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(0), 0}, \
- /* 0x04[16] = 0*/ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
- /* 0x04[15] = 1*/
-
-#define RTL8188E_TRANS_PDN_TO_CARDEMU \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), 0}, \
- /* 0x04[15] = 0*/
-
-/* This is used by driver for LPSRadioOff Procedure, not for FW LPS Step */
-#define RTL8188E_TRANS_ACT_TO_LPS \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0x0522, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \
- {0x05F8, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, 0xFF, 0}, \
- /*Should be zero if no packet is transmitting*/ \
- {0x05F9, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, 0xFF, 0}, \
- /*Should be zero if no packet is transmitting*/ \
- {0x05FA, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, 0xFF, 0}, \
- /*Should be zero if no packet is transmitting*/ \
- {0x05FB, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, 0xFF, 0}, \
- /*Should be zero if no packet is transmitting*/ \
- {0x0002, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(0), 0}, \
- /*CCK and OFDM are disabled,and clock are gated*/ \
- {0x0002, PWR_CUT_ALL_MSK, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US}, \
- /*Delay 1us*/ \
- {0x0100, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0x3F}, \
- /*Reset MAC TRX*/ \
- {0x0101, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(1), 0}, \
- /*check if removed later*/\
- {0x0553, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(5), BIT(5)}, \
- /*Respond TxOK to scheduler*/
-
-#define RTL8188E_TRANS_LPS_TO_ACT \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0xFE58, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0x84}, \
- /*USB RPWM*/ \
- {0x0002, PWR_CUT_ALL_MSK, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, \
- /*Delay*/ \
- {0x0008, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), 0}, \
- /* 0x08[4] = 0 switch TSF to 40M */ \
- {0x0109, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, BIT(7), 0}, \
- /* Polling 0x109[7]=0 TSF in 40M */ \
- {0x0029, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(6) | BIT(7), 0}, \
- /* 0x29[7:6] = 2b'00 enable BB clock */ \
- {0x0101, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
- /* 0x101[1] = 1 */ \
- {0x0100, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0xFF}, \
- /* 0x100[7:0] = 0xFF enable WMAC TRX */ \
- {0x0002, PWR_CUT_ALL_MSK, \
- PWR_CMD_WRITE, BIT(1) | BIT(0), BIT(1) | BIT(0)}, \
- /* 0x02[1:0] = 2b'11 enable BB macro */ \
- {0x0522, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/
-
-#define RTL8188E_TRANS_END \
- /* format
- * { offset, cut_msk, cmd, msk,
- * value },
- * comments here
- */ \
- {0xFFFF, PWR_CUT_ALL_MSK, PWR_CMD_END, 0, 0},
-
-extern struct wl_pwr_cfg rtl8188E_power_on_flow
- [RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS];
-extern struct wl_pwr_cfg rtl8188E_radio_off_flow
- [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_END_STEPS];
-extern struct wl_pwr_cfg rtl8188E_card_disable_flow
- [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
- RTL8188E_TRANS_END_STEPS];
-extern struct wl_pwr_cfg rtl8188E_card_enable_flow
- [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
- RTL8188E_TRANS_END_STEPS];
-extern struct wl_pwr_cfg rtl8188E_suspend_flow[
- RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
- RTL8188E_TRANS_END_STEPS];
-extern struct wl_pwr_cfg rtl8188E_resume_flow
- [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
- RTL8188E_TRANS_END_STEPS];
-extern struct wl_pwr_cfg rtl8188E_hwpdn_flow
- [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
- RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS];
-extern struct wl_pwr_cfg rtl8188E_enter_lps_flow
- [RTL8188E_TRANS_ACT_TO_LPS_STEPS + RTL8188E_TRANS_END_STEPS];
-extern struct wl_pwr_cfg rtl8188E_leave_lps_flow
- [RTL8188E_TRANS_LPS_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS];
-
-#endif /* __HAL8188EPWRSEQ_H__ */
diff --git a/drivers/staging/rtl8188eu/include/pwrseqcmd.h b/drivers/staging/rtl8188eu/include/pwrseqcmd.h
deleted file mode 100644
index 05f117e2a105..000000000000
--- a/drivers/staging/rtl8188eu/include/pwrseqcmd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __HALPWRSEQCMD_H__
-#define __HALPWRSEQCMD_H__
-
-#include <drv_types.h>
-
-/* The value of cmd: 4 bits */
-#define PWR_CMD_READ 0x00
-#define PWR_CMD_WRITE 0x01
-#define PWR_CMD_POLLING 0x02
-#define PWR_CMD_DELAY 0x03
-#define PWR_CMD_END 0x04
-
-/* The value of cut_msk: 8 bits */
-#define PWR_CUT_TESTCHIP_MSK BIT(0)
-#define PWR_CUT_A_MSK BIT(1)
-#define PWR_CUT_B_MSK BIT(2)
-#define PWR_CUT_C_MSK BIT(3)
-#define PWR_CUT_D_MSK BIT(4)
-#define PWR_CUT_E_MSK BIT(5)
-#define PWR_CUT_F_MSK BIT(6)
-#define PWR_CUT_G_MSK BIT(7)
-#define PWR_CUT_ALL_MSK 0xFF
-
-enum pwrseq_cmd_delat_unit {
- PWRSEQ_DELAY_US,
- PWRSEQ_DELAY_MS,
-};
-
-struct wl_pwr_cfg {
- u16 offset;
- u8 cut_msk;
- u8 cmd:4;
- u8 msk;
- u8 value;
-};
-
-#define GET_PWR_CFG_OFFSET(__PWR_CMD) __PWR_CMD.offset
-#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) __PWR_CMD.cut_msk
-#define GET_PWR_CFG_CMD(__PWR_CMD) __PWR_CMD.cmd
-#define GET_PWR_CFG_MASK(__PWR_CMD) __PWR_CMD.msk
-#define GET_PWR_CFG_VALUE(__PWR_CMD) __PWR_CMD.value
-
-u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers,
- struct wl_pwr_cfg pwrcfgCmd[]);
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h
deleted file mode 100644
index 614245d4b179..000000000000
--- a/drivers/staging/rtl8188eu/include/recv_osdep.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RECV_OSDEP_H_
-#define __RECV_OSDEP_H_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-
-int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter);
-void _rtw_free_recv_priv(struct recv_priv *precvpriv);
-
-s32 rtw_recv_entry(struct recv_frame *precv_frame);
-int rtw_recv_indicatepkt(struct adapter *adapter,
- struct recv_frame *recv_frame);
-
-void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup);
-
-int rtw_os_recvbuf_resource_alloc(struct recv_buf *precvbuf);
-
-void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl);
-
-#endif /* */
diff --git a/drivers/staging/rtl8188eu/include/rf.h b/drivers/staging/rtl8188eu/include/rf.h
deleted file mode 100644
index ed3241c020ad..000000000000
--- a/drivers/staging/rtl8188eu/include/rf.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#define RF6052_MAX_TX_PWR 0x3F
-#define RF6052_MAX_REG 0x3F
-
-void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt,
- enum ht_channel_width bandwidth);
-void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt,
- u8 *powerlevel);
-void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt,
- u8 *powerlevel_ofdm,
- u8 *powerlevel_bw20,
- u8 *powerlevel_bw40, u8 channel);
diff --git a/drivers/staging/rtl8188eu/include/rtw_android.h b/drivers/staging/rtl8188eu/include/rtw_android.h
deleted file mode 100644
index 3018fc1e8de8..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_android.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#ifndef __RTW_ANDROID_H__
-#define __RTW_ANDROID_H__
-
-#include <linux/module.h>
-#include <linux/netdevice.h>
-
-enum ANDROID_WIFI_CMD {
- ANDROID_WIFI_CMD_START,
- ANDROID_WIFI_CMD_STOP,
- ANDROID_WIFI_CMD_SCAN_ACTIVE,
- ANDROID_WIFI_CMD_SCAN_PASSIVE,
- ANDROID_WIFI_CMD_RSSI,
- ANDROID_WIFI_CMD_LINKSPEED,
- ANDROID_WIFI_CMD_RXFILTER_START,
- ANDROID_WIFI_CMD_RXFILTER_STOP,
- ANDROID_WIFI_CMD_RXFILTER_ADD,
- ANDROID_WIFI_CMD_RXFILTER_REMOVE,
- ANDROID_WIFI_CMD_BTCOEXSCAN_START,
- ANDROID_WIFI_CMD_BTCOEXSCAN_STOP,
- ANDROID_WIFI_CMD_BTCOEXMODE,
- ANDROID_WIFI_CMD_SETSUSPENDOPT,
- ANDROID_WIFI_CMD_P2P_DEV_ADDR,
- ANDROID_WIFI_CMD_SETFWPATH,
- ANDROID_WIFI_CMD_SETBAND,
- ANDROID_WIFI_CMD_GETBAND,
- ANDROID_WIFI_CMD_COUNTRY,
- ANDROID_WIFI_CMD_P2P_SET_NOA,
- ANDROID_WIFI_CMD_P2P_GET_NOA,
- ANDROID_WIFI_CMD_P2P_SET_PS,
- ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE,
- ANDROID_WIFI_CMD_MACADDR,
- ANDROID_WIFI_CMD_BLOCK,
- ANDROID_WIFI_CMD_WFD_ENABLE,
- ANDROID_WIFI_CMD_WFD_DISABLE,
- ANDROID_WIFI_CMD_WFD_SET_TCPPORT,
- ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT,
- ANDROID_WIFI_CMD_WFD_SET_DEVTYPE,
- ANDROID_WIFI_CMD_MAX
-};
-
-int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr,
- void __user *data, int cmd);
-
-#endif /* __RTW_ANDROID_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h
deleted file mode 100644
index 4e9cb93e4b8f..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_cmd.h
+++ /dev/null
@@ -1,361 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTW_CMD_H_
-#define __RTW_CMD_H_
-
-#include <wlan_bssdef.h>
-#include <rtw_rf.h>
-#include <rtw_led.h>
-
-#include <osdep_service.h>
-#include <ieee80211.h> /* <ieee80211/ieee80211.h> */
-
-#define MAX_CMDSZ 1024
-#define MAX_RSPSZ 512
-
-#define CMDBUFF_ALIGN_SZ 512
-
-struct cmd_obj {
- struct adapter *padapter;
- u16 cmdcode;
- u8 res;
- u8 *parmbuf;
- u32 cmdsz;
- u8 *rsp;
- u32 rspsz;
- struct list_head list;
-};
-
-struct cmd_priv {
- struct completion cmd_queue_comp;
- struct __queue cmd_queue;
-};
-
-#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \
-do {\
- INIT_LIST_HEAD(&pcmd->list);\
- pcmd->cmdcode = code;\
- pcmd->parmbuf = (u8 *)(pparm);\
- pcmd->cmdsz = sizeof(*pparm);\
- pcmd->rsp = NULL;\
- pcmd->rspsz = 0;\
-} while (0)
-
-u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
-struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue);
-void rtw_free_cmd_obj(struct cmd_obj *pcmd);
-
-int rtw_cmd_thread(void *context);
-
-void rtw_init_cmd_priv(struct cmd_priv *pcmdpriv);
-
-enum rtw_drvextra_cmd_id {
- NONE_WK_CID,
- DYNAMIC_CHK_WK_CID,
- DM_CTRL_WK_CID,
- PBC_POLLING_WK_CID,
- POWER_SAVING_CTRL_WK_CID,/* IPS,AUTOSuspend */
- LPS_CTRL_WK_CID,
- ANT_SELECT_WK_CID,
- P2P_PS_WK_CID,
- P2P_PROTO_WK_CID,
- CHECK_HIQ_WK_CID,/* for softap mode, check hi queue if empty */
- INTEl_WIDI_WK_CID,
- C2H_WK_CID,
- RTP_TIMER_CFG_WK_CID,
- MAX_WK_CID
-};
-
-enum LPS_CTRL_TYPE {
- LPS_CTRL_SCAN = 0,
- LPS_CTRL_JOINBSS = 1,
- LPS_CTRL_CONNECT = 2,
- LPS_CTRL_DISCONNECT = 3,
- LPS_CTRL_SPECIAL_PACKET = 4,
- LPS_CTRL_LEAVE = 5,
-};
-
-enum RFINTFS {
- SWSI,
- HWSI,
- HWPI,
-};
-
-/*
- * Caller Mode: Infra, Ad-HoC(C)
- *
- * Notes: To disconnect the current associated BSS
- *
- * Command Mode
- *
- */
-struct disconnect_parm {
- u32 deauth_timeout_ms;
-};
-
-struct setopmode_parm {
- u8 mode;
- u8 rsvd[3];
-};
-
-/*
- * Caller Mode: AP, Ad-HoC, Infra
- *
- * Notes: To ask RTL8711 performing site-survey
- *
- * Command-Event Mode
- *
- */
-
-#define RTW_SSID_SCAN_AMOUNT 9 /* for WEXT_CSCAN_AMOUNT 9 */
-#define RTW_CHANNEL_SCAN_AMOUNT (14 + 37)
-struct sitesurvey_parm {
- int scan_mode; /* active: 1, passive: 0 */
- u8 ssid_num;
- u8 ch_num;
- struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
- struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To set the auth type of RTL8711. open/shared/802.1x
- *
- * Command Mode
- *
- */
-struct setauth_parm {
- u8 mode; /* 0: legacy open, 1: legacy shared 2: 802.1x */
- u8 _1x; /* 0: PSK, 1: TLS */
- u8 rsvd[2];
-};
-
-/*
- * Caller Mode: Infra
- *
- * a. algorithm: wep40, wep104, tkip & aes
- * b. keytype: grp key/unicast key
- * c. key contents
- *
- * when shared key ==> keyid is the camid
- * when 802.1x ==> keyid [0:1] ==> grp key
- * when 802.1x ==> keyid > 2 ==> unicast key
- *
- */
-struct setkey_parm {
- u8 algorithm; /* could be none, wep40, TKIP, CCMP, wep104 */
- u8 keyid;
- u8 grpkey; /* 1: this is the grpkey for 802.1x.
- * 0: this is the unicast key for 802.1x
- */
- u8 set_tx; /* 1: main tx key for wep. 0: other key. */
- u8 key[16]; /* this could be 40 or 104 */
-};
-
-/*
- * When in AP or Ad-Hoc mode, this is used to
- * allocate an sw/hw entry for a newly associated sta.
- *
- * Command
- *
- * when shared key ==> algorithm/keyid
- *
- */
-struct set_stakey_parm {
- u8 addr[ETH_ALEN];
- u8 algorithm;
- u8 id;/* currently for erasing cam entry if
- * algorithm == _NO_PRIVACY_
- */
- u8 key[16];
-};
-
-struct set_stakey_rsp {
- u8 addr[ETH_ALEN];
- u8 keyid;
- u8 rsvd;
-};
-
-/*
- * Caller Ad-Hoc/AP
- *
- * Command -Rsp(AID == CAMID) mode
- *
- * This is to force fw to add an sta_data entry per driver's request.
- *
- * FW will write an cam entry associated with it.
- *
- */
-struct set_assocsta_parm {
- u8 addr[ETH_ALEN];
-};
-
-struct set_assocsta_rsp {
- u8 cam_id;
- u8 rsvd[3];
-};
-
-/*
- * Notes: This command is used for H2C/C2H loopback testing
- *
- * mac[0] == 0
- * ==> CMD mode, return H2C_SUCCESS.
- * The following condition must be true under CMD mode
- * mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0;
- * s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7;
- * s2 == (b1 << 8 | b0);
- *
- * mac[0] == 1
- * ==> CMD_RSP mode, return H2C_SUCCESS_RSP
- *
- * The rsp layout shall be:
- * rsp: parm:
- * mac[0] = mac[5];
- * mac[1] = mac[4];
- * mac[2] = mac[3];
- * mac[3] = mac[2];
- * mac[4] = mac[1];
- * mac[5] = mac[0];
- * s0 = s1;
- * s1 = swap16(s0);
- * w0 = swap32(w1);
- * b0 = b1
- * s2 = s0 + s1
- * b1 = b0
- * w1 = w0
- *
- * mac[0] == 2
- * ==> CMD_EVENT mode, return H2C_SUCCESS
- * The event layout shall be:
- * event: parm:
- * mac[0] = mac[5];
- * mac[1] = mac[4];
- * mac[2] = event's seq no, starting from 1 to parm's marc[3]
- * mac[2] = event's seq no, starting from 1 to parm's marc[3]
- * mac[2] = event's seq no, starting from 1 to parm's marc[3]
- * mac[3] = mac[2];
- * mac[4] = mac[1];
- * mac[5] = mac[0];
- * s0 = swap16(s0) - event.mac[2];
- * s1 = s1 + event.mac[2];
- * w0 = swap32(w0);
- * b0 = b1
- * s2 = s0 + event.mac[2]
- * b1 = b0
- * w1 = swap32(w1) - event.mac[2];
- *
- * parm->mac[3] is the total event counts that host requested.
- * event will be the same with the cmd's param.
- */
-
-/* CMD param Format for driver extra cmd handler */
-struct drvextra_cmd_parm {
- int ec_id; /* extra cmd id */
- int type_size; /* Can use this field as the type id or command size */
- unsigned char *pbuf;
-};
-
-struct addBaReq_parm {
- unsigned int tid;
- u8 addr[ETH_ALEN];
-};
-
-/*H2C Handler index: 46 */
-struct set_ch_parm {
- u8 ch;
- u8 bw;
- u8 ch_offset;
-};
-
-/*H2C Handler index: 59 */
-struct SetChannelPlan_param {
- u8 channel_plan;
-};
-
-/*
- *
- * Result:
- * 0x00: success
- * 0x01: success, and check Response.
- * 0x02: cmd ignored due to duplicated sequcne number
- * 0x03: cmd dropped due to invalid cmd code
- * 0x04: reserved.
- *
- */
-
-#define H2C_SUCCESS 0x00
-#define H2C_SUCCESS_RSP 0x01
-#define H2C_DROPPED 0x03
-#define H2C_PARAMETERS_ERROR 0x04
-#define H2C_REJECTED 0x05
-
-u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid,
- int ssid_num, struct rtw_ieee80211_channel *ch,
- int ch_num);
-u8 rtw_createbss_cmd(struct adapter *padapter);
-u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key);
-u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry,
- u8 enqueue);
-u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork);
-u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms,
- bool enqueue);
-u8 rtw_setopmode_cmd(struct adapter *padapter,
- enum ndis_802_11_network_infra networktype);
-u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr);
-
-u8 rtw_dynamic_chk_wk_cmd(struct adapter *adapter);
-
-u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue);
-u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 minRptTime);
-
-u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue);
-u8 rtw_ps_cmd(struct adapter *padapter);
-
-#ifdef CONFIG_88EU_AP_MODE
-u8 rtw_chk_hi_queue_cmd(struct adapter *padapter);
-#endif
-
-u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue);
-u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf);
-
-void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
-void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
-void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
-void rtw_createbss_cmd_callback(struct adapter *adapt, struct cmd_obj *pcmd);
-void rtw_readtssi_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
-
-void rtw_setstaKey_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
-void rtw_setassocsta_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cm);
-void rtw_getrttbl_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
-
-struct _cmd_callback {
- u32 cmd_code;
- void (*callback)(struct adapter *padapter, struct cmd_obj *cmd);
-};
-
-enum rtw_h2c_cmd {
- _JoinBss_CMD_,
- _DisConnect_CMD_,
- _CreateBss_CMD_,
- _SetOpMode_CMD_,
- _SiteSurvey_CMD_,
- _SetAuth_CMD_,
- _SetKey_CMD_,
- _SetStaKey_CMD_,
- _SetAssocSta_CMD_,
- _AddBAReq_CMD_,
- _SetChannel_CMD_,
- _TX_Beacon_CMD_,
- _Set_MLME_EVT_CMD_,
- _Set_Drv_Extra_CMD_,
- _SetChannelPlan_CMD_,
-
- MAX_H2CCMD
-};
-
-#endif /* _CMD_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h
deleted file mode 100644
index bb5e2b5d4bf1..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_efuse.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTW_EFUSE_H__
-#define __RTW_EFUSE_H__
-
-#include <osdep_service.h>
-
-#define EFUSE_ERROE_HANDLE 1
-
-#define PG_STATE_HEADER 0x01
-#define PG_STATE_WORD_0 0x02
-#define PG_STATE_WORD_1 0x04
-#define PG_STATE_WORD_2 0x08
-#define PG_STATE_WORD_3 0x10
-#define PG_STATE_DATA 0x20
-
-#define PG_SWBYTE_H 0x01
-#define PG_SWBYTE_L 0x02
-
-#define PGPKT_DATA_SIZE 8
-
-/* E-Fuse */
-#define EFUSE_MAP_SIZE 512
-#define EFUSE_MAX_SIZE 256
-/* end of E-Fuse */
-
-#define EFUSE_MAX_MAP_LEN 512
-#define EFUSE_MAX_HW_SIZE 512
-#define EFUSE_MAX_SECTION_BASE 16
-
-#define EXT_HEADER(header) ((header & 0x1F) == 0x0F)
-#define ALL_WORDS_DISABLED(wde) ((wde & 0x0F) == 0x0F)
-#define GET_HDR_OFFSET_2_0(header) ((header & 0xE0) >> 5)
-
-#define EFUSE_REPEAT_THRESHOLD_ 3
-
-/* The following is for BT Efuse definition */
-#define EFUSE_BT_MAX_MAP_LEN 1024
-#define EFUSE_MAX_BANK 4
-#define EFUSE_MAX_BT_BANK (EFUSE_MAX_BANK - 1)
-/*--------------------------Define Parameters-------------------------------*/
-#define EFUSE_MAX_WORD_UNIT 4
-
-/*------------------------------Define structure----------------------------*/
-struct pgpkt {
- u8 offset;
- u8 word_en;
- u8 data[8];
- u8 word_cnts;
-};
-
-u8 Efuse_CalculateWordCnts(u8 word_en);
-u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data);
-u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data);
-
-int Efuse_PgPacketRead(struct adapter *adapt, u8 offset, u8 *data);
-bool Efuse_PgPacketWrite(struct adapter *adapter, u8 offset, u8 word, u8 *data);
-void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata);
-u8 Efuse_WordEnableDataWrite(struct adapter *adapter, u16 efuse_addr,
- u8 word_en, u8 *data);
-
-void EFUSE_ShadowMapUpdate(struct adapter *adapter);
-#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_event.h b/drivers/staging/rtl8188eu/include/rtw_event.h
deleted file mode 100644
index bfe774e876d1..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_event.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef _RTW_EVENT_H_
-#define _RTW_EVENT_H_
-
-#include <osdep_service.h>
-
-#include <wlan_bssdef.h>
-#include <linux/mutex.h>
-#include <linux/sem.h>
-
-/*
- * Used to report a bss has been scanned
- */
-struct survey_event {
- struct wlan_bssid_ex bss;
-};
-
-/*
- * Used to report that the requested site survey has been done.
- *
- * bss_cnt indicates the number of bss that has been reported.
- *
- *
- */
-struct surveydone_event {
- unsigned int bss_cnt;
-
-};
-
-/*
- * Used to report the link result of joinning the given bss
- *
- *
- * join_res:
- * -1: authentication fail
- * -2: association fail
- * > 0: TID
- *
- */
-struct joinbss_event {
- struct wlan_network network;
-};
-
-/*
- * Used to report a given STA has joinned the created BSS.
- * It is used in AP/Ad-HoC(M) mode.
- */
-
-struct stassoc_event {
- unsigned char macaddr[6];
- unsigned char rsvd[2];
- int cam_id;
-};
-
-struct stadel_event {
- unsigned char macaddr[6];
- unsigned char rsvd[2]; /* for reason */
- int mac_id;
-};
-
-struct fwevent {
- u32 parmsize;
- void (*event_callback)(struct adapter *dev, u8 *pbuf);
-};
-
-#define C2HEVENT_SZ 32
-
-#define NETWORK_QUEUE_SZ 4
-
-struct network_queue {
- int head;
- int tail;
- struct wlan_bssid_ex networks[NETWORK_QUEUE_SZ];
-};
-
-#endif /* _WLANEVENT_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_ht.h b/drivers/staging/rtl8188eu/include/rtw_ht.h
deleted file mode 100644
index 192fa50c07be..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_ht.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef _RTW_HT_H_
-#define _RTW_HT_H_
-
-#include <linux/ieee80211.h>
-
-struct ht_priv {
- u32 ht_option;
- u32 ampdu_enable;/* for enable Tx A-MPDU */
- u8 bwmode;/* */
- u8 ch_offset;/* PRIME_CHNL_OFFSET */
- u8 sgi;/* short GI */
-
- /* for processing Tx A-MPDU */
- u8 agg_enable_bitmap;
- u8 candidate_tid_bitmap;
-
- struct ieee80211_ht_cap ht_cap;
-};
-
-#endif /* _RTL871X_HT_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h b/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h
deleted file mode 100644
index 7078f8252fa0..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTW_IOCTL_SET_H_
-#define __RTW_IOCTL_SET_H_
-
-#include <drv_types.h>
-
-typedef u8 NDIS_802_11_PMKID_VALUE[16];
-
-u8 rtw_set_802_11_authentication_mode(struct adapter *adapt,
- enum ndis_802_11_auth_mode authmode);
-u8 rtw_set_802_11_bssid(struct adapter *adapter, u8 *bssid);
-u8 rtw_set_802_11_add_wep(struct adapter *adapter, struct ndis_802_11_wep *wep);
-u8 rtw_set_802_11_disassociate(struct adapter *adapter);
-u8 rtw_set_802_11_bssid_list_scan(struct adapter *adapter,
- struct ndis_802_11_ssid *pssid,
- int ssid_max_num);
-u8 rtw_set_802_11_infrastructure_mode(struct adapter *adapter,
- enum ndis_802_11_network_infra type);
-u8 rtw_set_802_11_ssid(struct adapter *adapt, struct ndis_802_11_ssid *ssid);
-u16 rtw_get_cur_max_rate(struct adapter *adapter);
-int rtw_set_country(struct adapter *adapter, const char *country_code);
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_iol.h b/drivers/staging/rtl8188eu/include/rtw_iol.h
deleted file mode 100644
index d713782d5cdc..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_iol.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTW_IOL_H_
-#define __RTW_IOL_H_
-
-#include <drv_types.h>
-
-bool rtw_iol_applied(struct adapter *adapter);
-
-#endif /* __RTW_IOL_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_led.h b/drivers/staging/rtl8188eu/include/rtw_led.h
deleted file mode 100644
index 5f65c3e1e46f..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_led.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTW_LED_H_
-#define __RTW_LED_H_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-
-#define LED_BLINK_NO_LINK_INTERVAL_ALPHA 1000
-#define LED_BLINK_LINK_INTERVAL_ALPHA 500 /* 500 */
-#define LED_BLINK_SCAN_INTERVAL_ALPHA 180 /* 150 */
-#define LED_BLINK_FASTER_INTERVAL_ALPHA 50
-#define LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA 5000
-
-enum LED_CTL_MODE {
- LED_CTL_POWER_ON,
- LED_CTL_LINK,
- LED_CTL_NO_LINK,
- LED_CTL_TX,
- LED_CTL_RX,
- LED_CTL_SITE_SURVEY,
- LED_CTL_POWER_OFF,
- LED_CTL_START_TO_LINK,
- LED_CTL_START_WPS,
- LED_CTL_STOP_WPS,
- LED_CTL_START_WPS_BOTTON,
- LED_CTL_STOP_WPS_FAIL
-};
-
-enum LED_STATE_871x {
- LED_UNKNOWN,
- RTW_LED_ON,
- RTW_LED_OFF,
- LED_BLINK_NORMAL,
- LED_BLINK_SLOWLY,
- LED_BLINK_POWER_ON,
- LED_BLINK_SCAN,
- LED_BLINK_TXRX,
- LED_BLINK_WPS,
- LED_BLINK_WPS_STOP
-};
-
-struct LED_871x {
- struct adapter *padapter;
-
- enum LED_STATE_871x CurrLedState; /* Current LED state. */
- enum LED_STATE_871x BlinkingLedState; /* Next state for blinking,
- * either RTW_LED_ON or RTW_LED_OFF are.
- */
-
- u8 led_on; /* true if LED is ON, false if LED is OFF. */
-
- u8 bLedBlinkInProgress; /* true if it is blinking, false o.w.. */
-
- u8 bLedWPSBlinkInProgress;
-
- u32 BlinkTimes; /* Number of times to toggle led state for blinking. */
-
- struct timer_list BlinkTimer; /* Timer object for led blinking. */
-
- /* ALPHA, added by chiyoko, 20090106 */
- u8 bLedNoLinkBlinkInProgress;
- u8 bLedLinkBlinkInProgress;
- u8 bLedScanBlinkInProgress;
- struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer to
- * manipulate H/W to blink LED.
- */
-};
-
-#define IS_LED_WPS_BLINKING(_LED_871x) \
- (((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS || \
- ((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS_STOP || \
- ((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress)
-
-void led_control_8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction);
-
-struct led_priv {
- struct LED_871x sw_led;
-};
-
-void BlinkWorkItemCallback(struct work_struct *work);
-
-void ResetLedStatus(struct LED_871x *pLed);
-
-void InitLed871x(struct adapter *padapter, struct LED_871x *pLed);
-
-void DeInitLed871x(struct LED_871x *pLed);
-
-/* hal... */
-void blink_handler(struct LED_871x *pLed);
-void sw_led_on(struct adapter *padapter, struct LED_871x *pLed);
-void sw_led_off(struct adapter *padapter, struct LED_871x *pLed);
-
-#endif /* __RTW_LED_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h
deleted file mode 100644
index 2f02316906d0..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_mlme.h
+++ /dev/null
@@ -1,355 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTW_MLME_H_
-#define __RTW_MLME_H_
-
-#include <osdep_service.h>
-#include <mlme_osdep.h>
-#include <drv_types.h>
-#include <wlan_bssdef.h>
-
-#define MAX_BSS_CNT 128
-#define MAX_JOIN_TIMEOUT 6500
-
-/* Increase the scanning timeout because of increasing the SURVEY_TO value. */
-
-#define SCANNING_TIMEOUT 8000
-
-#define SCAN_INTERVAL (30) /* unit:2sec, 30*2=60sec */
-
-#define SCANQUEUE_LIFETIME 20 /* unit:sec */
-
-#define WIFI_NULL_STATE 0x00000000
-
-#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state */
-#define WIFI_REASOC_STATE 0x00000002
-#define WIFI_SLEEP_STATE 0x00000004
-#define WIFI_STATION_STATE 0x00000008
-
-#define WIFI_AP_STATE 0x00000010
-#define WIFI_ADHOC_STATE 0x00000020
-#define WIFI_ADHOC_MASTER_STATE 0x00000040
-#define WIFI_UNDER_LINKING 0x00000080
-
-#define WIFI_UNDER_WPS 0x00000100
-#define WIFI_STA_ALIVE_CHK_STATE 0x00000400
-#define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station is under site surveying */
-
-#define _FW_UNDER_LINKING WIFI_UNDER_LINKING
-#define _FW_LINKED WIFI_ASOC_STATE
-#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR
-
-enum dot11AuthAlgrthmNum {
- dot11AuthAlgrthm_Open = 0, /* open system */
- dot11AuthAlgrthm_Shared,
- dot11AuthAlgrthm_8021X,
- dot11AuthAlgrthm_Auto,
- dot11AuthAlgrthm_WAPI,
- dot11AuthAlgrthm_MaxNum
-};
-
-/* Scan type including active and passive scan. */
-enum rt_scan_type {
- SCAN_PASSIVE,
- SCAN_ACTIVE,
- SCAN_MIX,
-};
-
-enum SCAN_RESULT_TYPE {
- SCAN_RESULT_P2P_ONLY = 0, /* Will return all the P2P devices. */
- SCAN_RESULT_ALL = 1, /* Will return all the scanned device,
- * include AP.
- */
- SCAN_RESULT_WFD_TYPE = 2 /* Will just return the correct WFD
- * device.
- */
- /* If this device is Miracast sink
- * device, it will just return all the
- * Miracast source devices.
- */
-};
-
-/*
- * there are several "locks" in mlme_priv,
- * since mlme_priv is a shared resource between many threads,
- * like ISR/Call-Back functions, the OID handlers, and even timer functions.
- *
- * Each _queue has its own locks, already.
- * Other items are protected by mlme_priv.lock.
- *
- * To avoid possible dead lock, any thread trying to modifiying mlme_priv
- * SHALL not lock up more than one lock at a time!
- */
-
-#define traffic_threshold 10
-#define traffic_scan_period 500
-
-struct rt_link_detect {
- u32 NumTxOkInPeriod;
- u32 NumRxOkInPeriod;
- u32 NumRxUnicastOkInPeriod;
- bool bBusyTraffic;
- bool bTxBusyTraffic;
- bool bRxBusyTraffic;
- bool bHigherBusyTraffic; /* For interrupt migration purpose. */
- bool bHigherBusyRxTraffic; /* We may disable Tx interrupt according
- * to Rx traffic.
- */
- bool bHigherBusyTxTraffic; /* We may disable Tx interrupt according
- * to Tx traffic.
- */
-};
-
-struct mlme_priv {
- spinlock_t lock;
- int fw_state; /* shall we protect this variable? maybe not necessarily... */
- u8 bScanInProcess;
- u8 to_join; /* flag */
- u8 to_roaming; /* roaming trying times */
-
- struct list_head *pscanned;
- struct __queue free_bss_pool;
- struct __queue scanned_queue;
- u8 *free_bss_buf;
-
- struct ndis_802_11_ssid assoc_ssid;
- u8 assoc_bssid[6];
-
- struct wlan_network cur_network;
-
- u32 scan_interval;
-
- struct timer_list assoc_timer;
-
- uint assoc_by_bssid;
-
- struct timer_list scan_to_timer; /* driver itself handles scan_timeout status. */
-
- struct qos_priv qospriv;
-
- /* Number of non-HT AP/stations */
- int num_sta_no_ht;
-
- /* Number of HT AP/stations 20 MHz */
- /* int num_sta_ht_20mhz; */
-
- int num_FortyMHzIntolerant;
- struct ht_priv htpriv;
- struct rt_link_detect LinkDetectInfo;
- struct timer_list dynamic_chk_timer; /* dynamic/periodic check timer */
-
- u8 key_mask; /* use for ips to set wep key after ips_leave */
- u8 acm_mask; /* for wmm acm mask */
- u8 ChannelPlan;
- enum rt_scan_type scan_mode; /* active: 1, passive: 0 */
-
- /* u8 probereq_wpsie[MAX_WPS_IE_LEN];added in probe req */
- /* int probereq_wpsie_len; */
- u8 *wps_probe_req_ie;
- u32 wps_probe_req_ie_len;
-
- u8 *assoc_req;
- u32 assoc_req_len;
- u8 *assoc_rsp;
- u32 assoc_rsp_len;
-
-#if defined(CONFIG_88EU_AP_MODE)
- /* Number of associated Non-ERP stations (i.e., stations using 802.11b
- * in 802.11g BSS)
- */
- int num_sta_non_erp;
-
- /* Number of associated stations that do not support Short Slot Time */
- int num_sta_no_short_slot_time;
-
- /* Number of associated stations that do not support Short Preamble */
- int num_sta_no_short_preamble;
-
- int olbc; /* Overlapping Legacy BSS Condition */
-
- /* Number of HT assoc sta that do not support greenfield */
- int num_sta_ht_no_gf;
-
- /* Number of associated non-HT stations */
- /* int num_sta_no_ht; */
-
- /* Number of HT associated stations 20 MHz */
- int num_sta_ht_20mhz;
-
- /* Overlapping BSS information */
- int olbc_ht;
-
- u16 ht_op_mode;
-
- u8 *wps_beacon_ie;
- /* u8 *wps_probe_req_ie; */
- u8 *wps_probe_resp_ie;
- u8 *wps_assoc_resp_ie;
-
- u32 wps_beacon_ie_len;
- u32 wps_probe_resp_ie_len;
- u32 wps_assoc_resp_ie_len;
-
- spinlock_t bcn_update_lock;
- u8 update_bcn;
-#endif /* if defined (CONFIG_88EU_AP_MODE) */
-};
-
-#ifdef CONFIG_88EU_AP_MODE
-
-struct hostapd_priv {
- struct adapter *padapter;
-};
-
-int hostapd_mode_init(struct adapter *padapter);
-void hostapd_mode_unload(struct adapter *padapter);
-#endif
-
-extern const u8 WPA_TKIP_CIPHER[4];
-extern const u8 RSN_TKIP_CIPHER[4];
-extern u8 REALTEK_96B_IE[];
-extern const u8 MCS_rate_1R[16];
-
-void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf);
-void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf);
-void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf);
-void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf);
-void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf);
-void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf);
-void indicate_wx_scan_complete_event(struct adapter *padapter);
-void rtw_indicate_wx_assoc_event(struct adapter *padapter);
-void rtw_indicate_wx_disassoc_event(struct adapter *padapter);
-int event_thread(void *context);
-void rtw_free_network_queue(struct adapter *adapter, u8 isfreeall);
-int rtw_init_mlme_priv(struct adapter *adapter);
-void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv);
-int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv);
-int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv,
- int keyid, u8 set_tx);
-int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv);
-
-static inline u8 *get_bssid(struct mlme_priv *pmlmepriv)
-{ /* if sta_mode:pmlmepriv->cur_network.network.MacAddress=> bssid */
- /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress=> ibss mac address */
- return pmlmepriv->cur_network.network.MacAddress;
-}
-
-static inline int check_fwstate(struct mlme_priv *pmlmepriv, int state)
-{
- if (pmlmepriv->fw_state & state)
- return true;
-
- return false;
-}
-
-static inline int get_fwstate(struct mlme_priv *pmlmepriv)
-{
- return pmlmepriv->fw_state;
-}
-
-/*
- * No Limit on the calling context,
- * therefore set it to be the critical section...
- *
- * ### NOTE:#### (!!!!)
- * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
- */
-static inline void set_fwstate(struct mlme_priv *pmlmepriv, int state)
-{
- pmlmepriv->fw_state |= state;
- /* FOR HW integration */
- if (state == _FW_UNDER_SURVEY)
- pmlmepriv->bScanInProcess = true;
-}
-
-static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, int state)
-{
- pmlmepriv->fw_state &= ~state;
- /* FOR HW integration */
- if (state == _FW_UNDER_SURVEY)
- pmlmepriv->bScanInProcess = false;
-}
-
-/*
- * No Limit on the calling context,
- * therefore set it to be the critical section...
- */
-static inline void clr_fwstate(struct mlme_priv *pmlmepriv, int state)
-{
- spin_lock_bh(&pmlmepriv->lock);
- if (check_fwstate(pmlmepriv, state))
- pmlmepriv->fw_state ^= state;
- spin_unlock_bh(&pmlmepriv->lock);
-}
-
-static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state)
-{
- spin_lock_bh(&pmlmepriv->lock);
- _clr_fwstate_(pmlmepriv, state);
- spin_unlock_bh(&pmlmepriv->lock);
-}
-
-u16 rtw_get_capability(struct wlan_bssid_ex *bss);
-void rtw_update_scanned_network(struct adapter *adapter,
- struct wlan_bssid_ex *target);
-void rtw_disconnect_hdl_under_linked(struct adapter *adapter,
- struct sta_info *psta, u8 free_assoc);
-void rtw_generate_random_ibss(u8 *pibss);
-struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr);
-struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue);
-
-void rtw_free_assoc_resources(struct adapter *adapter);
-void rtw_free_assoc_resources_locked(struct adapter *adapter);
-void rtw_indicate_disconnect(struct adapter *adapter);
-void rtw_indicate_connect(struct adapter *adapter);
-void rtw_indicate_scan_done(struct adapter *padapter, bool aborted);
-
-int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie,
- uint in_len);
-int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie,
- uint in_len, uint initial_out_len);
-void rtw_init_registrypriv_dev_network(struct adapter *adapter);
-
-void rtw_update_registrypriv_dev_network(struct adapter *adapter);
-
-void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter);
-
-void _rtw_join_timeout_handler(struct timer_list *t);
-void rtw_scan_timeout_handler(struct timer_list *t);
-
-void rtw_dynamic_check_timer_handlder(struct timer_list *t);
-#define rtw_is_scan_deny(adapter) false
-#define rtw_clear_scan_deny(adapter) do {} while (0)
-#define rtw_set_scan_deny_timer_hdl(adapter) do {} while (0)
-#define rtw_set_scan_deny(adapter, ms) do {} while (0)
-
-void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv);
-
-struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv);
-
-int rtw_if_up(struct adapter *padapter);
-
-u8 *rtw_get_capability_from_ie(u8 *ie);
-u8 *rtw_get_beacon_interval_from_ie(u8 *ie);
-
-void rtw_joinbss_reset(struct adapter *padapter);
-
-unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie,
- u8 *out_ie, uint in_len, uint *pout_len);
-void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len);
-void rtw_issue_addbareq_cmd(struct adapter *padapter,
- struct xmit_frame *pxmitframe);
-
-int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork);
-int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst);
-
-void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network);
-void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network);
-
-void rtw_stassoc_hw_rpt(struct adapter *adapter, struct sta_info *psta);
-
-#endif /* __RTL871X_MLME_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h
deleted file mode 100644
index 8c906b666b62..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_recv.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef _RTW_RECV_H_
-#define _RTW_RECV_H_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-
-#define NR_RECVFRAME 256
-
-#define RXFRAME_ALIGN 8
-#define RXFRAME_ALIGN_SZ (1 << RXFRAME_ALIGN)
-
-#define MAX_RXFRAME_CNT 512
-#define MAX_RX_NUMBLKS (32)
-#define RECVFRAME_HDR_ALIGN 128
-
-#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
-
-#define MAX_SUBFRAME_COUNT 64
-
-/* for Rx reordering buffer control */
-struct recv_reorder_ctrl {
- struct adapter *padapter;
- bool enable;
- u16 indicate_seq;/* wstart_b, init_value=0xffff */
- u16 wend_b;
- u8 wsize_b;
- struct __queue pending_recvframe_queue;
- struct timer_list reordering_ctrl_timer;
-};
-
-struct stainfo_rxcache {
- u16 tid_rxseq[16];
-/*
- * unsigned short tid0_rxseq;
- * unsigned short tid1_rxseq;
- * unsigned short tid2_rxseq;
- * unsigned short tid3_rxseq;
- * unsigned short tid4_rxseq;
- * unsigned short tid5_rxseq;
- * unsigned short tid6_rxseq;
- * unsigned short tid7_rxseq;
- * unsigned short tid8_rxseq;
- * unsigned short tid9_rxseq;
- * unsigned short tid10_rxseq;
- * unsigned short tid11_rxseq;
- * unsigned short tid12_rxseq;
- * unsigned short tid13_rxseq;
- * unsigned short tid14_rxseq;
- * unsigned short tid15_rxseq;
- */
-};
-
-struct signal_stat {
- u8 update_req; /* used to indicate */
- u8 avg_val; /* avg of valid elements */
- u32 total_num; /* num of valid elements */
- u32 total_val; /* sum of valid elements */
-};
-
-#define MAX_PATH_NUM_92CS 3
-
-struct phy_info {
- u8 RxPWDBAll;
- u8 SignalQuality; /* in 0-100 index. */
- u8 RxMIMOSignalQuality[MAX_PATH_NUM_92CS]; /* EVM */
- u8 RxMIMOSignalStrength[MAX_PATH_NUM_92CS];/* in 0~100 index */
- s8 RxPower; /* in dBm Translate from PWdB */
-/* Real power in dBm for this packet, no beautification and aggregation.
- * Keep this raw info to be used for the other procedures.
- */
- s8 recvpower;
- u8 BTRxRSSIPercentage;
- u8 SignalStrength; /* in 0-100 index. */
- u8 RxPwr[MAX_PATH_NUM_92CS];/* per-path's pwdb */
- u8 RxSNR[MAX_PATH_NUM_92CS];/* per-path's SNR */
-};
-
-struct rx_pkt_attrib {
- u16 pkt_len;
- u8 physt;
- u8 drvinfo_sz;
- u8 shift_sz;
- u8 hdrlen; /* the WLAN Header Len */
- u8 to_fr_ds;
- u8 amsdu;
- u8 qos;
- u8 priority;
- u8 pw_save;
- u8 mdata;
- u16 seq_num;
- u8 frag_num;
- u8 mfrag;
- u8 order;
- u8 privacy; /* in frame_ctrl field */
- u8 bdecrypted;
- u8 encrypt; /* when 0 indicate no encrypt. when non-zero,
- * indicate the encrypt algorithm
- */
- u8 iv_len;
- u8 icv_len;
- u8 crc_err;
- u8 icv_err;
-
- u16 eth_type;
-
- u8 dst[ETH_ALEN];
- u8 src[ETH_ALEN];
- u8 ta[ETH_ALEN];
- u8 ra[ETH_ALEN];
- u8 bssid[ETH_ALEN];
-
- u8 ack_policy;
-
- u8 key_index;
-
- u8 mcs_rate;
- u8 rxht;
- u8 sgi;
- u8 pkt_rpt_type;
- u32 MacIDValidEntry[2]; /* 64 bits present 64 entry. */
-
- struct phy_info phy_info;
-};
-
-/* These definition is used for Rx packet reordering. */
-#define SN_LESS(a, b) (((a - b) & 0x800) != 0)
-#define SN_EQUAL(a, b) (a == b)
-#define REORDER_WAIT_TIME (50) /* (ms) */
-
-#define RXDESC_SIZE 24
-#define RXDESC_OFFSET RXDESC_SIZE
-
-struct recv_stat {
- __le32 rxdw0;
- __le32 rxdw1;
- __le32 rxdw2;
- __le32 rxdw3;
- __le32 rxdw4;
- __le32 rxdw5;
-};
-
-/*
- * accesser of recv_priv: rtw_recv_entry(dispatch / passive level);
- * recv_thread(passive) ; returnpkt(dispatch)
- * ; halt(passive) ;
- *
- * using enter_critical section to protect
- */
-struct recv_priv {
- struct __queue free_recv_queue;
- struct __queue recv_pending_queue;
- struct __queue uc_swdec_pending_queue;
- void *pallocated_frame_buf;
- struct adapter *adapter;
- u32 bIsAnyNonBEPkts;
- u64 rx_bytes;
- u64 rx_pkts;
- u64 rx_drop;
- u64 last_rx_bytes;
-
- struct tasklet_struct irq_prepare_beacon_tasklet;
- struct tasklet_struct recv_tasklet;
- struct sk_buff_head free_recv_skb_queue;
- struct sk_buff_head rx_skb_queue;
- struct recv_buf *precv_buf; /* 4 alignment */
- struct __queue free_recv_buf_queue;
- /* For display the phy information */
- s8 rssi;
- s8 rxpwdb;
- u8 signal_strength;
- u8 signal_qual;
- u8 noise;
- s8 RxRssi[2];
-
- struct timer_list signal_stat_timer;
- u32 signal_stat_sampling_interval;
- struct signal_stat signal_qual_data;
- struct signal_stat signal_strength_data;
-};
-
-#define rtw_set_signal_stat_timer(recvpriv) \
- mod_timer(&(recvpriv)->signal_stat_timer, jiffies + \
- msecs_to_jiffies((recvpriv)->signal_stat_sampling_interval))
-
-struct sta_recv_priv {
- spinlock_t lock;
- int option;
- struct __queue defrag_q; /* keeping the fragment frame until defrag */
- struct stainfo_rxcache rxcache;
-};
-
-struct recv_buf {
- struct adapter *adapter;
- struct urb *purb;
- struct sk_buff *pskb;
- u8 reuse;
-};
-
-/*
- * head ----->
- *
- * data ----->
- *
- * payload
- *
- * tail ----->
- *
- *
- * end ----->
- *
- * len = (unsigned int )(tail - data);
- *
- */
-struct recv_frame {
- struct list_head list;
- struct sk_buff *pkt;
- struct adapter *adapter;
- struct rx_pkt_attrib attrib;
- struct sta_info *psta;
- /* for A-MPDU Rx reordering buffer control */
- struct recv_reorder_ctrl *preorder_ctrl;
-};
-
-struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
-struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
-void rtw_init_recvframe(struct recv_frame *precvframe,
- struct recv_priv *precvpriv);
-void rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_recv_queue);
-#define rtw_dequeue_recvframe(queue) rtw_alloc_recvframe(queue)
-int _rtw_enqueue_recvframe(struct recv_frame *precvframe,
- struct __queue *queue);
-int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue);
-void rtw_free_recvframe_queue(struct __queue *pframequeue,
- struct __queue *pfree_recv_queue);
-u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter);
-
-void rtw_reordering_ctrl_timeout_handler(struct timer_list *t);
-
-static inline s32 translate_percentage_to_dbm(u32 sig_stren_index)
-{
- s32 power; /* in dBm. */
-
- /* Translate to dBm (x=0.5y-95). */
- power = (s32)((sig_stren_index + 1) >> 1);
- power -= 95;
-
- return power;
-}
-
-struct sta_info;
-
-void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv);
-
-void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame);
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_sreset.h b/drivers/staging/rtl8188eu/include/rtw_sreset.h
deleted file mode 100644
index ea3c0d93bf0b..000000000000
--- a/drivers/staging/rtl8188eu/include/rtw_sreset.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef _RTW_SRESET_C_
-#define _RTW_SRESET_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-
-struct sreset_priv {
- u8 wifi_error_status;
-};
-
-#include <rtl8188e_hal.h>
-
-#define WIFI_STATUS_SUCCESS 0
-#define USB_VEN_REQ_CMD_FAIL BIT(0)
-#define USB_READ_PORT_FAIL BIT(1)
-#define USB_WRITE_PORT_FAIL BIT(2)
-#define WIFI_MAC_TXDMA_ERROR BIT(3)
-#define WIFI_TX_HANG BIT(4)
-#define WIFI_RX_HANG BIT(5)
-#define WIFI_IF_NOT_EXIST BIT(6)
-
-void sreset_set_wifi_error_status(struct adapter *padapter, u32 status);
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h
deleted file mode 100644
index 19c6e76d747e..000000000000
--- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __USB_OPS_LINUX_H__
-#define __USB_OPS_LINUX_H__
-
-#define USB_HIGH_SPEED_BULK_SIZE 512
-#define USB_FULL_SPEED_BULK_SIZE 64
-
-u8 usb_read8(struct adapter *adapter, u32 addr);
-u16 usb_read16(struct adapter *adapter, u32 addr);
-u32 usb_read32(struct adapter *adapter, u32 addr);
-
-u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf);
-
-int usb_write8(struct adapter *adapter, u32 addr, u8 val);
-int usb_write16(struct adapter *adapter, u32 addr, u16 val);
-int usb_write32(struct adapter *adapter, u32 addr, u32 val);
-
-u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, struct xmit_buf *pmem);
-void usb_write_port_cancel(struct adapter *adapter);
-
-#endif
diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h
deleted file mode 100644
index 716fec036e54..000000000000
--- a/drivers/staging/rtl8188eu/include/wifi.h
+++ /dev/null
@@ -1,355 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef _WIFI_H_
-#define _WIFI_H_
-
-#define WLAN_HDR_A3_LEN 24
-#define WLAN_HDR_A3_QOS_LEN 26
-
-#define P80211CAPTURE_VERSION 0x80211001
-
-/* This value is tested by WiFi 11n Test Plan 5.2.3. */
-/* This test verifies the WLAN NIC can update the NAV through sending
- * the CTS with large duration.
- */
-#define WiFiNavUpperUs 30000 /* 30 ms */
-
-enum WIFI_FRAME_TYPE {
- WIFI_MGT_TYPE = (0),
- WIFI_CTRL_TYPE = (BIT(2)),
- WIFI_DATA_TYPE = (BIT(3)),
- WIFI_QOS_DATA_TYPE = (BIT(7) | BIT(3)), /* QoS Data */
-};
-
-#define SetToDs(pbuf) \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS)
-
-#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0)
-
-#define ClearToDs(pbuf) \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_TODS))
-
-#define SetFrDs(pbuf) \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_FROMDS)
-
-#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0)
-
-#define ClearFrDs(pbuf) \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_FROMDS))
-
-#define get_tofr_ds(pframe) ((GetToDs(pframe) << 1) | GetFrDs(pframe))
-
-#define SetMFrag(pbuf) \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)
-
-#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0)
-
-#define ClearMFrag(pbuf) \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS))
-
-#define SetRetry(pbuf) \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_RETRY)
-
-#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0)
-
-#define ClearRetry(pbuf) \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_RETRY))
-
-#define SetPwrMgt(pbuf) \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PM)
-
-#define GetPwrMgt(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_PM)) != 0)
-
-#define ClearPwrMgt(pbuf) \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_PM))
-
-#define SetMData(pbuf) \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREDATA)
-
-#define GetMData(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0)
-
-#define ClearMData(pbuf) \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREDATA))
-
-#define SetPrivacy(pbuf) \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PROTECTED)
-
-#define GetPrivacy(pbuf) \
- (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0)
-
-#define GetOrder(pbuf) \
- (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0)
-
-#define GetFrameType(pbuf) \
- (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(3) | BIT(2)))
-
-#define GetFrameSubType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(7) |\
- BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2)))
-
-#define SetFrameSubType(pbuf, type) \
- do { \
- *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(7) | BIT(6) | \
- BIT(5) | BIT(4) | BIT(3) | BIT(2))); \
- *(__le16 *)(pbuf) |= cpu_to_le16(type); \
- } while (0)
-
-#define GetSequence(pbuf) \
- (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) >> 4)
-
-#define GetFragNum(pbuf) \
- (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) & 0x0f)
-
-#define SetSeqNum(pbuf, num) \
- do { \
- *(__le16 *)((size_t)(pbuf) + 22) = \
- ((*(__le16 *)((size_t)(pbuf) + 22)) & cpu_to_le16((unsigned short)0x000f)) | \
- cpu_to_le16((unsigned short)(0xfff0 & (num << 4))); \
- } while (0)
-
-#define SetDuration(pbuf, dur) \
- *(__le16 *)((size_t)(pbuf) + 2) = cpu_to_le16(0xffff & (dur))
-
-#define SetPriority(pbuf, tid) \
- *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf)
-
-#define GetPriority(pbuf) ((le16_to_cpu(*(__le16 *)(pbuf))) & 0xf)
-
-#define SetEOSP(pbuf, eosp) \
- *(__le16 *)(pbuf) |= cpu_to_le16((eosp & 1) << 4)
-
-#define SetAckpolicy(pbuf, ack) \
- *(__le16 *)(pbuf) |= cpu_to_le16((ack & 3) << 5)
-
-#define GetAckpolicy(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 5) & 0x3)
-
-#define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1)
-
-#define GetAid(pbuf) (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 2)) & 0x3fff)
-
-#define GetAddr1Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 4))
-
-#define GetAddr2Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 10))
-
-#define GetAddr3Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 16))
-
-static inline unsigned char *get_hdr_bssid(unsigned char *pframe)
-{
- unsigned char *sa;
- unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
-
- switch (to_fr_ds) {
- case 0x00: /* ToDs=0, FromDs=0 */
- sa = GetAddr3Ptr(pframe);
- break;
- case 0x01: /* ToDs=0, FromDs=1 */
- sa = GetAddr2Ptr(pframe);
- break;
- case 0x02: /* ToDs=1, FromDs=0 */
- sa = GetAddr1Ptr(pframe);
- break;
- case 0x03: /* ToDs=1, FromDs=1 */
- sa = GetAddr1Ptr(pframe);
- break;
- default:
- sa = NULL; /* */
- break;
- }
- return sa;
-}
-
-/*-----------------------------------------------------------------------------
- Below is for the security related definition
-------------------------------------------------------------------------------*/
-#define _ASOCREQ_IE_OFFSET_ 4 /* excluding wlan_hdr */
-#define _ASOCRSP_IE_OFFSET_ 6
-#define _REASOCREQ_IE_OFFSET_ 10
-#define _REASOCRSP_IE_OFFSET_ 6
-#define _PROBEREQ_IE_OFFSET_ 0
-#define _PROBERSP_IE_OFFSET_ 12
-#define _AUTH_IE_OFFSET_ 6
-#define _DEAUTH_IE_OFFSET_ 0
-#define _BEACON_IE_OFFSET_ 12
-#define _PUBLIC_ACTION_IE_OFFSET_ 8
-
-#define _FIXED_IE_LENGTH_ _BEACON_IE_OFFSET_
-
-/* ---------------------------------------------------------------------------
- Below is the fixed elements...
------------------------------------------------------------------------------*/
-#define _AUTH_ALGM_NUM_ 2
-#define _AUTH_SEQ_NUM_ 2
-#define _BEACON_ITERVAL_ 2
-#define _CAPABILITY_ 2
-#define _CURRENT_APADDR_ 6
-#define _LISTEN_INTERVAL_ 2
-#define _RSON_CODE_ 2
-#define _ASOC_ID_ 2
-#define _STATUS_CODE_ 2
-#define _TIMESTAMP_ 8
-
-#define AUTH_ODD_TO 0
-#define AUTH_EVEN_TO 1
-
-/*-----------------------------------------------------------------------------
- Below is the definition for 802.11i / 802.1x
-------------------------------------------------------------------------------*/
-#define _IEEE8021X_MGT_ 1 /* WPA */
-#define _IEEE8021X_PSK_ 2 /* WPA with pre-shared key */
-
-/*
- * #define _NO_PRIVACY_ 0
- * #define _WEP_40_PRIVACY_ 1
- * #define _TKIP_PRIVACY_ 2
- * #define _WRAP_PRIVACY_ 3
- * #define _CCMP_PRIVACY_ 4
- * #define _WEP_104_PRIVACY_ 5
- * #define _WEP_WPA_MIXED_PRIVACY_ 6 WEP + WPA
- */
-
-/*-----------------------------------------------------------------------------
- Below is the definition for WMM
-------------------------------------------------------------------------------*/
-#define _WMM_IE_Length_ 7 /* for WMM STA */
-
-/*-----------------------------------------------------------------------------
- Below is the definition for 802.11n
-------------------------------------------------------------------------------*/
-
-/**
- * struct rtw_ieee80211_ht_cap - HT additional information
- *
- * This structure refers to "HT information element" as
- * described in 802.11n draft section 7.3.2.53
- */
-struct ieee80211_ht_addt_info {
- unsigned char control_chan;
- unsigned char ht_param;
- unsigned short operation_mode;
- unsigned short stbc_param;
- unsigned char basic_set[16];
-} __packed;
-
-struct HT_info_element {
- unsigned char primary_channel;
- unsigned char infos[5];
- unsigned char MCS_rate[16];
-} __packed;
-
-struct AC_param {
- unsigned char ACI_AIFSN;
- unsigned char CW;
- __le16 TXOP_limit;
-} __packed;
-
-struct WMM_para_element {
- unsigned char QoS_info;
- unsigned char reserved;
- struct AC_param ac_param[4];
-} __packed;
-
-struct ADDBA_request {
- unsigned char dialog_token;
- __le16 BA_para_set;
- unsigned short BA_timeout_value;
- unsigned short BA_starting_seqctrl;
-} __packed;
-
-enum ht_cap_ampdu_factor {
- MAX_AMPDU_FACTOR_8K = 0,
- MAX_AMPDU_FACTOR_16K = 1,
- MAX_AMPDU_FACTOR_32K = 2,
- MAX_AMPDU_FACTOR_64K = 3,
-};
-
-#define OP_MODE_PURE 0
-#define OP_MODE_MAY_BE_LEGACY_STAS 1
-#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
-#define OP_MODE_MIXED 3
-
-#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8)BIT(0) | BIT(1))
-#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8)BIT(0))
-#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8)BIT(0) | BIT(1))
-#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8)BIT(2))
-#define HT_INFO_HT_PARAM_RIFS_MODE ((u8)BIT(3))
-#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8)BIT(4))
-#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8)BIT(5))
-
-#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
- ((u16)(0x0001 | 0x0002))
-#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
-#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8)BIT(2))
-#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8)BIT(3))
-#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8)BIT(4))
-
-/* ===============WPS Section=============== */
-/* For WPSv1.0 */
-#define WPSOUI 0x0050f204
-/* WPS attribute ID */
-#define WPS_ATTR_VER1 0x104A
-#define WPS_ATTR_SIMPLE_CONF_STATE 0x1044
-#define WPS_ATTR_RESP_TYPE 0x103B
-#define WPS_ATTR_UUID_E 0x1047
-#define WPS_ATTR_MANUFACTURER 0x1021
-#define WPS_ATTR_MODEL_NAME 0x1023
-#define WPS_ATTR_MODEL_NUMBER 0x1024
-#define WPS_ATTR_SERIAL_NUMBER 0x1042
-#define WPS_ATTR_PRIMARY_DEV_TYPE 0x1054
-#define WPS_ATTR_SEC_DEV_TYPE_LIST 0x1055
-#define WPS_ATTR_DEVICE_NAME 0x1011
-#define WPS_ATTR_CONF_METHOD 0x1008
-#define WPS_ATTR_RF_BANDS 0x103C
-#define WPS_ATTR_DEVICE_PWID 0x1012
-#define WPS_ATTR_REQUEST_TYPE 0x103A
-#define WPS_ATTR_ASSOCIATION_STATE 0x1002
-#define WPS_ATTR_CONFIG_ERROR 0x1009
-#define WPS_ATTR_VENDOR_EXT 0x1049
-#define WPS_ATTR_SELECTED_REGISTRAR 0x1041
-
-/* Value of WPS Request Type Attribute */
-#define WPS_REQ_TYPE_ENROLLEE_INFO_ONLY 0x00
-#define WPS_REQ_TYPE_ENROLLEE_OPEN_8021X 0x01
-#define WPS_REQ_TYPE_REGISTRAR 0x02
-#define WPS_REQ_TYPE_WLAN_MANAGER_REGISTRAR 0x03
-
-/* Value of WPS Response Type Attribute */
-#define WPS_RESPONSE_TYPE_INFO_ONLY 0x00
-#define WPS_RESPONSE_TYPE_8021X 0x01
-#define WPS_RESPONSE_TYPE_REGISTRAR 0x02
-#define WPS_RESPONSE_TYPE_AP 0x03
-
-/* Value of WPS WiFi Simple Configuration State Attribute */
-#define WPS_WSC_STATE_NOT_CONFIG 0x01
-#define WPS_WSC_STATE_CONFIG 0x02
-
-/* Value of WPS Version Attribute */
-#define WPS_VERSION_1 0x10
-
-/* Value of WPS Configuration Method Attribute */
-#define WPS_CONFIG_METHOD_FLASH 0x0001
-#define WPS_CONFIG_METHOD_ETHERNET 0x0002
-#define WPS_CONFIG_METHOD_LABEL 0x0004
-#define WPS_CONFIG_METHOD_DISPLAY 0x0008
-#define WPS_CONFIG_METHOD_E_NFC 0x0010
-#define WPS_CONFIG_METHOD_I_NFC 0x0020
-#define WPS_CONFIG_METHOD_NFC 0x0040
-#define WPS_CONFIG_METHOD_PBC 0x0080
-#define WPS_CONFIG_METHOD_KEYPAD 0x0100
-#define WPS_CONFIG_METHOD_VPBC 0x0280
-#define WPS_CONFIG_METHOD_PPBC 0x0480
-#define WPS_CONFIG_METHOD_VDISPLAY 0x2008
-#define WPS_CONFIG_METHOD_PDISPLAY 0x4008
-
-/* Value of WPS RF Bands Attribute */
-#define WPS_RF_BANDS_2_4_GHZ 0x01
-#define WPS_RF_BANDS_5_GHZ 0x02
-
-#define IP_MCAST_MAC(mac) \
- ((mac[0] == 0x01) && (mac[1] == 0x00) && (mac[2] == 0x5e))
-#define ICMPV6_MCAST_MAC(mac) \
- ((mac[0] == 0x33) && (mac[1] == 0x33) && (mac[2] != 0xff))
-
-#endif /* _WIFI_H_ */
diff --git a/drivers/staging/rtl8188eu/include/xmit_osdep.h b/drivers/staging/rtl8188eu/include/xmit_osdep.h
deleted file mode 100644
index 5fd8ca51f156..000000000000
--- a/drivers/staging/rtl8188eu/include/xmit_osdep.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __XMIT_OSDEP_H_
-#define __XMIT_OSDEP_H_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-
-#define NR_XMITFRAME 256
-
-struct xmit_priv;
-struct pkt_attrib;
-struct sta_xmit_priv;
-struct xmit_frame;
-struct xmit_buf;
-
-int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev);
-
-void rtw_os_xmit_schedule(struct adapter *padapter);
-
-int rtw_os_xmit_resource_alloc(struct xmit_buf *pxmitbuf, u32 alloc_sz);
-void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf);
-
-void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt);
-void rtw_os_xmit_complete(struct adapter *padapter,
- struct xmit_frame *pxframe);
-
-#endif /* __XMIT_OSDEP_H_ */
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
deleted file mode 100644
index 193a3dde462c..000000000000
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ /dev/null
@@ -1,2777 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _IOCTL_LINUX_C_
-
-#include <linux/ieee80211.h>
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <wlan_bssdef.h>
-#include <wifi.h>
-#include <rtw_mlme.h>
-#include <rtw_mlme_ext.h>
-#include <rtw_ioctl.h>
-#include <rtw_ioctl_set.h>
-#include <rtl8188e_hal.h>
-
-#include <linux/vmalloc.h>
-#include <linux/etherdevice.h>
-
-#include "osdep_intf.h"
-
-#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
-
-#define SCAN_ITEM_SIZE 768
-#define MAX_CUSTOM_LEN 64
-#define RATE_COUNT 4
-
-/* combo scan */
-#define WEXT_CSCAN_AMOUNT 9
-#define WEXT_CSCAN_BUF_LEN 360
-#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
-#define WEXT_CSCAN_HEADER_SIZE 12
-#define WEXT_CSCAN_SSID_SECTION 'S'
-#define WEXT_CSCAN_CHANNEL_SECTION 'C'
-#define WEXT_CSCAN_NPROBE_SECTION 'N'
-#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
-#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
-#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
-#define WEXT_CSCAN_TYPE_SECTION 'T'
-
-static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
- 6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
- 48000000, 54000000};
-
-static const char * const iw_operation_mode[] = {
- "Auto", "Ad-Hoc", "Managed", "Master", "Repeater",
- "Secondary", "Monitor"
-};
-
-void indicate_wx_scan_complete_event(struct adapter *padapter)
-{
- union iwreq_data wrqu;
-
- memset(&wrqu, 0, sizeof(union iwreq_data));
- wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
-}
-
-void rtw_indicate_wx_assoc_event(struct adapter *padapter)
-{
- union iwreq_data wrqu;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- memset(&wrqu, 0, sizeof(union iwreq_data));
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-
- memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
-
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
-}
-
-void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
-{
- union iwreq_data wrqu;
-
- memset(&wrqu, 0, sizeof(union iwreq_data));
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- eth_zero_addr(wrqu.ap_addr.sa_data);
-
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
-}
-
-static char *translate_scan(struct adapter *padapter,
- struct iw_request_info *info,
- struct wlan_network *pnetwork,
- char *start, char *stop)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct iw_event iwe;
- u16 cap;
- __le16 le_tmp;
- u32 ht_ielen = 0;
- char custom[MAX_CUSTOM_LEN];
- char *p;
- u16 max_rate = 0, rate, ht_cap = false;
- u32 i = 0;
- u8 bw_40MHz = 0, short_GI = 0;
- u16 mcs_rate = 0;
- u8 ss, sq;
-
- /* AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-
- memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
-
- /* Add the ESSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.u.data.length = min_t(u16, pnetwork->network.ssid.ssid_length, 32);
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
-
- /* parsing HT_CAP_IE */
- p = rtw_get_ie(&pnetwork->network.ies[12], WLAN_EID_HT_CAPABILITY, &ht_ielen, pnetwork->network.ie_length - 12);
-
- if (p && ht_ielen > 0) {
- struct ieee80211_ht_cap *pht_capie;
-
- ht_cap = true;
-
- pht_capie = (struct ieee80211_ht_cap *)(p + 2);
- memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
- bw_40MHz = !!(le16_to_cpu(pht_capie->cap_info) &
- IEEE80211_HT_CAP_SUP_WIDTH_20_40);
- short_GI = !!(le16_to_cpu(pht_capie->cap_info) &
- (IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40));
- }
-
- /* Add the protocol name */
- iwe.cmd = SIOCGIWNAME;
- if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
- } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
- } else {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
- }
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
-
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
-
- cap = le16_to_cpu(le_tmp);
-
- if (!WLAN_CAPABILITY_IS_STA_BSS(cap)) {
- if (cap & WLAN_CAPABILITY_ESS)
- iwe.u.mode = IW_MODE_MASTER;
- else
- iwe.u.mode = IW_MODE_ADHOC;
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
- }
-
- if (pnetwork->network.Configuration.DSConfig < 1)
- pnetwork->network.Configuration.DSConfig = 1;
-
- /* Add frequency/channel */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
- iwe.u.freq.e = 1;
- iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (cap & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- else
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- iwe.u.data.length = 0;
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
-
- /*Add basic and extended rates */
- max_rate = 0;
- p = custom;
- p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
- while (pnetwork->network.SupportedRates[i] != 0) {
- rate = pnetwork->network.SupportedRates[i] & 0x7F;
- if (rate > max_rate)
- max_rate = rate;
- p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
- "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
- i++;
- }
-
- if (ht_cap) {
- if (mcs_rate & 0x8000)/* MCS15 */
- max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
- else if (mcs_rate & 0x0080)/* MCS7 */
- ;
- else/* default MCS7 */
- max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
-
- max_rate *= 2; /* Mbps/2; */
- }
-
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = 0;
- iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = max_rate * 500000;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
-
- /* parsing WPA/WPA2 IE */
- {
- u8 *buf;
- u8 *wpa_ie, *rsn_ie;
- u16 wpa_len = 0, rsn_len = 0;
- u8 *p;
-
- buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC);
- if (!buf)
- return start;
-
- wpa_ie = kzalloc(255, GFP_ATOMIC);
- if (!wpa_ie)
- return start;
-
- rsn_ie = kzalloc(255, GFP_ATOMIC);
- if (!rsn_ie)
- return start;
-
- rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
-
- if (wpa_len > 0) {
- p = buf;
- p += sprintf(p, "wpa_ie=");
- for (i = 0; i < wpa_len; i++)
- p += sprintf(p, "%02x", wpa_ie[i]);
-
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop, &iwe, buf);
-
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = wpa_len;
- start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
- }
- if (rsn_len > 0) {
- p = buf;
- p += sprintf(p, "rsn_ie=");
- for (i = 0; i < rsn_len; i++)
- p += sprintf(p, "%02x", rsn_ie[i]);
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop, &iwe, buf);
-
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = rsn_len;
- start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
- }
- kfree(buf);
- kfree(wpa_ie);
- kfree(rsn_ie);
- }
-
- {/* parsing WPS IE */
- uint cnt = 0, total_ielen;
- u8 *wpsie_ptr = NULL;
- uint wps_ielen = 0;
- u8 *ie_ptr = pnetwork->network.ies + _FIXED_IE_LENGTH_;
-
- total_ielen = pnetwork->network.ie_length - _FIXED_IE_LENGTH_;
-
- while (cnt < total_ielen) {
- if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
- wpsie_ptr = &ie_ptr[cnt];
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = (u16)wps_ielen;
- start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
- }
- cnt += ie_ptr[cnt + 1] + 2; /* goto next */
- }
- }
-
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) &&
- is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
- ss = padapter->recvpriv.signal_strength;
- sq = padapter->recvpriv.signal_qual;
- } else {
- ss = pnetwork->network.PhyInfo.SignalStrength;
- sq = pnetwork->network.PhyInfo.SignalQuality;
- }
-
- iwe.u.qual.level = (u8)ss;
- iwe.u.qual.qual = (u8)sq; /* signal quality */
- iwe.u.qual.noise = 0; /* noise level */
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
- return start;
-}
-
-static int wpa_set_auth_algs(struct net_device *dev, u32 value)
-{
- struct adapter *padapter = netdev_priv(dev);
- int ret = 0;
-
- if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
- } else if (value & AUTH_ALG_SHARED_KEY) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
-
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
- } else if (value & AUTH_ALG_OPEN_SYSTEM) {
- if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
- }
- } else {
- ret = -EINVAL;
- }
- return ret;
-}
-
-static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
-{
- int ret = 0;
- u32 wep_key_idx, wep_key_len, wep_total_len;
- struct ndis_802_11_wep *pwep = NULL;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
- if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
- ret = -EINVAL;
- goto exit;
- }
-
- if (is_broadcast_ether_addr(param->sta_addr)) {
- if (param->u.crypt.idx >= WEP_KEYS) {
- ret = -EINVAL;
- goto exit;
- }
- } else {
- ret = -EINVAL;
- goto exit;
- }
-
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
-
- wep_key_idx = param->u.crypt.idx;
- wep_key_len = param->u.crypt.key_len;
-
- if (wep_key_idx > WEP_KEYS)
- return -EINVAL;
-
- if (wep_key_len > 0) {
- wep_key_len = wep_key_len <= 5 ? 5 : 13;
- wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
- pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
- if (!pwep)
- goto exit;
- memset(pwep, 0, wep_total_len);
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_total_len;
- if (wep_key_len == 13) {
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
- padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
- }
- } else {
- ret = -EINVAL;
- goto exit;
- }
- pwep->KeyIndex = wep_key_idx;
- pwep->KeyIndex |= 0x80000000;
- memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
- if (param->u.crypt.set_tx) {
- if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
- ret = -EOPNOTSUPP;
- } else {
- if (wep_key_idx >= WEP_KEYS) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
- memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength);
- psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
- rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
- }
- goto exit;
- }
-
- if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
- struct sta_info *psta, *pbcmc_sta;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { /* sta mode */
- psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
- if (!psta) {
- ;
- } else {
- if (strcmp(param->u.crypt.alg, "none") != 0)
- psta->ieee8021x_blocked = false;
-
- if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
- (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
- psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
-
- if (param->u.crypt.set_tx == 1) { /* pairwise key */
- memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
-
- if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
- memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
- memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
- padapter->securitypriv.busetkipkey = false;
- }
-
- rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
- } else { /* group key */
- memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
- memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[16], 8);
- memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
- padapter->securitypriv.binstallGrpkey = true;
-
- padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
-
- rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
- }
- }
- pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
- if (!pbcmc_sta) {
- ;
- } else {
- /* Jeff: don't disable ieee8021x_blocked while clearing key */
- if (strcmp(param->u.crypt.alg, "none") != 0)
- pbcmc_sta->ieee8021x_blocked = false;
-
- if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
- (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
- pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
- }
- }
- }
-
-exit:
-
- kfree(pwep);
- return ret;
-}
-
-static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
-{
- u8 *buf = NULL;
- int group_cipher = 0, pairwise_cipher = 0;
- int ret = 0;
-
- if ((ielen > MAX_WPA_IE_LEN) || (!pie)) {
- _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
- if (!pie)
- return ret;
- else
- return -EINVAL;
- }
-
- if (ielen) {
- buf = kmemdup(pie, ielen, GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- goto exit;
- }
-
- if (ielen < RSN_HEADER_LEN) {
- ret = -1;
- goto exit;
- }
-
- if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
- memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
- }
-
- if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
- memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
- }
-
- switch (group_cipher) {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- }
-
- switch (pairwise_cipher) {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- }
-
- _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
- {/* set wps_ie */
- u16 cnt = 0;
- u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- while (cnt < ielen) {
- eid = buf[cnt];
- if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
- padapter->securitypriv.wps_ie_len = min(buf[cnt + 1] + 2, MAX_WPA_IE_LEN << 2);
-
- memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
-
- set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
- cnt += buf[cnt + 1] + 2;
- break;
- }
- cnt += buf[cnt + 1] + 2; /* goto next */
- }
- }
- }
-exit:
- kfree(buf);
- return ret;
-}
-
-typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
-
-static int rtw_wx_get_name(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
- u32 ht_ielen = 0;
- char *p;
- u8 ht_cap = false;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- NDIS_802_11_RATES_EX *prates = NULL;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- /* parsing HT_CAP_IE */
- p = rtw_get_ie(&pcur_bss->ies[12], WLAN_EID_HT_CAPABILITY, &ht_ielen, pcur_bss->ie_length - 12);
- if (p && ht_ielen > 0)
- ht_cap = true;
-
- prates = &pcur_bss->SupportedRates;
-
- if (rtw_is_cckratesonly_included((u8 *)prates)) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
- } else if (rtw_is_cckrates_included((u8 *)prates)) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
- } else {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
- }
- } else {
- snprintf(wrqu->name, IFNAMSIZ, "unassociated");
- }
- return 0;
-}
-
-static int rtw_wx_get_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
- wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = pcur_bss->Configuration.DSConfig;
- } else {
- wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
- }
-
- return 0;
-}
-
-static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct adapter *padapter = netdev_priv(dev);
- enum ndis_802_11_network_infra networkType;
- int ret = 0;
-
- if (!rtw_pwr_wakeup(padapter)) {
- ret = -EPERM;
- goto exit;
- }
-
- if (!padapter->hw_init_completed) {
- ret = -EPERM;
- goto exit;
- }
-
- switch (wrqu->mode) {
- case IW_MODE_AUTO:
- networkType = Ndis802_11AutoUnknown;
- break;
- case IW_MODE_ADHOC:
- networkType = Ndis802_11IBSS;
- break;
- case IW_MODE_MASTER:
- networkType = Ndis802_11APMode;
- break;
- case IW_MODE_INFRA:
- networkType = Ndis802_11Infrastructure;
- break;
- default:
- ret = -EINVAL;
- goto exit;
- }
- if (!rtw_set_802_11_infrastructure_mode(padapter, networkType)) {
- ret = -EPERM;
- goto exit;
- }
- rtw_setopmode_cmd(padapter, networkType);
-exit:
- return ret;
-}
-
-static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- wrqu->mode = IW_MODE_INFRA;
- else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
- wrqu->mode = IW_MODE_ADHOC;
- else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
- wrqu->mode = IW_MODE_MASTER;
- else
- wrqu->mode = IW_MODE_AUTO;
-
- return 0;
-}
-
-static int rtw_wx_set_pmkid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
- u8 j, blInserted = false;
- int ret = false;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
- u8 strZeroMacAddress[ETH_ALEN] = {0x00};
- u8 strIssueBssid[ETH_ALEN] = {0x00};
-
- memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
- if (pPMK->cmd == IW_PMKSA_ADD) {
- if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
- return ret;
- ret = true;
- blInserted = false;
-
- /* overwrite PMKID */
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(psecuritypriv->PMKIDList[j].bssid, strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => rewrite with new PMKID. */
- memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
- psecuritypriv->PMKIDList[j].used = true;
- psecuritypriv->PMKIDIndex = j + 1;
- blInserted = true;
- break;
- }
- }
-
- if (!blInserted) {
- /* Find a new entry */
- memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bssid, strIssueBssid, ETH_ALEN);
- memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
-
- psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].used = true;
- psecuritypriv->PMKIDIndex++;
- if (psecuritypriv->PMKIDIndex == 16)
- psecuritypriv->PMKIDIndex = 0;
- }
- } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
- ret = true;
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(psecuritypriv->PMKIDList[j].bssid, strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
- eth_zero_addr(psecuritypriv->PMKIDList[j].bssid);
- psecuritypriv->PMKIDList[j].used = false;
- break;
- }
- }
- } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
- memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
- psecuritypriv->PMKIDIndex = 0;
- ret = true;
- }
- return ret;
-}
-
-static int rtw_wx_get_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->sens.value = 0;
- wrqu->sens.fixed = 0; /* no auto select */
- wrqu->sens.disabled = 1;
- return 0;
-}
-
-static int rtw_wx_get_range(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_range *range = (struct iw_range *)extra;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- u16 val;
- int i;
-
- wrqu->data.length = sizeof(*range);
- memset(range, 0, sizeof(*range));
-
- /* Let's try to keep this struct in the same order as in
- * linux/include/wireless.h
- */
-
- /* TODO: See what values we can set, and remove the ones we can't
- * set, or fill them with some default data.
- */
-
- /* ~5 Mb/s real (802.11b) */
- range->throughput = 5 * 1000 * 1000;
-
- /* signal level threshold range */
-
- /* percent values between 0 and 100. */
- range->max_qual.qual = 100;
- range->max_qual.level = 100;
- range->max_qual.noise = 100;
- range->max_qual.updated = 7; /* Updated all three */
-
- range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
- range->avg_qual.level = 178; /* -78 dBm */
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 7; /* Updated all three */
-
- range->num_bitrates = RATE_COUNT;
-
- for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
- range->bitrate[i] = rtw_rates[i];
-
- range->min_frag = MIN_FRAG_THRESHOLD;
- range->max_frag = MAX_FRAG_THRESHOLD;
-
- range->pm_capa = 0;
-
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
-
- for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
- /* Include only legal frequencies for some countries */
- if (pmlmeext->channel_set[i].ChannelNum != 0) {
- range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
- range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
- range->freq[val].e = 1;
- val++;
- }
-
- if (val == IW_MAX_FREQUENCIES)
- break;
- }
-
- range->num_channels = val;
- range->num_frequency = val;
-
-/* The following code will proivde the security capability to network manager. */
-/* If the driver doesn't provide this capability to network manager, */
-/* the WPA/WPA2 routers can't be chosen in the network manager. */
-
- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
-
- range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
- IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
- IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
- return 0;
-}
-
-/* set bssid flow */
-/* s1. rtw_set_802_11_infrastructure_mode() */
-/* s2. rtw_set_802_11_authentication_mode() */
-/* s3. set_802_11_encryption_mode() */
-/* s4. rtw_set_802_11_bssid() */
-static int rtw_wx_set_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq, char *extra)
-{
- uint ret = 0;
- struct adapter *padapter = netdev_priv(dev);
- struct sockaddr *temp = (struct sockaddr *)awrq;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct list_head *phead;
- u8 *dst_bssid, *src_bssid;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- enum ndis_802_11_auth_mode authmode;
-
- if (!rtw_pwr_wakeup(padapter)) {
- ret = -1;
- goto exit;
- }
-
- if (!padapter->bup) {
- ret = -1;
- goto exit;
- }
-
- if (temp->sa_family != ARPHRD_ETHER) {
- ret = -EINVAL;
- goto exit;
- }
-
- authmode = padapter->securitypriv.ndisauthtype;
- spin_lock_bh(&queue->lock);
- phead = get_list_head(queue);
- list_for_each(pmlmepriv->pscanned, phead) {
- pnetwork = list_entry(pmlmepriv->pscanned,
- struct wlan_network, list);
-
- dst_bssid = pnetwork->network.MacAddress;
-
- src_bssid = temp->sa_data;
-
- if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
- if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
- ret = -1;
- spin_unlock_bh(&queue->lock);
- goto exit;
- }
-
- break;
- }
- }
- spin_unlock_bh(&queue->lock);
-
- rtw_set_802_11_authentication_mode(padapter, authmode);
- if (!rtw_set_802_11_bssid(padapter, temp->sa_data)) {
- ret = -1;
- goto exit;
- }
-
-exit:
-
- return ret;
-}
-
-static int rtw_wx_get_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- wrqu->ap_addr.sa_family = ARPHRD_ETHER;
-
- eth_zero_addr(wrqu->ap_addr.sa_data);
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
- check_fwstate(pmlmepriv, WIFI_AP_STATE))
- memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
- else
- eth_zero_addr(wrqu->ap_addr.sa_data);
- return 0;
-}
-
-static int rtw_wx_set_mlme(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct adapter *padapter = netdev_priv(dev);
- struct iw_mlme *mlme = (struct iw_mlme *)extra;
-
- if (!mlme)
- return -1;
-
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- if (!rtw_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- case IW_MLME_DISASSOC:
- if (!rtw_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- default:
- return -EOPNOTSUPP;
- }
- return ret;
-}
-
-static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- u8 _status = false;
- int ret = 0;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
-
- if (!rtw_pwr_wakeup(padapter)) {
- ret = -1;
- goto exit;
- }
-
- if (padapter->bDriverStopped) {
- ret = -1;
- goto exit;
- }
-
- if (!padapter->bup) {
- ret = -1;
- goto exit;
- }
-
- if (!padapter->hw_init_completed) {
- ret = -1;
- goto exit;
- }
-
- /* When Busy Traffic, driver do not site survey. So driver return success. */
- /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
- /* modify by thomas 2011-02-22. */
- if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
- indicate_wx_scan_complete_event(padapter);
- goto exit;
- }
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
- indicate_wx_scan_complete_event(padapter);
- goto exit;
- }
-
-/* For the DMP WiFi Display project, the driver won't to scan because */
-/* the pmlmepriv->scan_interval is always equal to 3. */
-/* So, the wpa_supplicant won't find out the WPS SoftAP. */
-
- memset(ssid, 0, sizeof(struct ndis_802_11_ssid) * RTW_SSID_SCAN_AMOUNT);
-
- if (wrqu->data.length == sizeof(struct iw_scan_req)) {
- struct iw_scan_req *req = (struct iw_scan_req *)extra;
-
- if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- int len = min_t(int, req->essid_len,
- IW_ESSID_MAX_SIZE);
-
- memcpy(ssid[0].ssid, req->essid, len);
- ssid[0].ssid_length = len;
-
- spin_lock_bh(&pmlmepriv->lock);
-
- _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
-
- spin_unlock_bh(&pmlmepriv->lock);
- }
- } else {
- if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
- !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
- int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
- char *pos = extra + WEXT_CSCAN_HEADER_SIZE;
- char section;
- char sec_len;
- int ssid_index = 0;
-
- while (len >= 1) {
- section = *(pos++);
- len -= 1;
-
- switch (section) {
- case WEXT_CSCAN_SSID_SECTION:
- if (len < 1) {
- len = 0;
- break;
- }
- sec_len = *(pos++); len -= 1;
- if (sec_len > 0 &&
- sec_len <= len &&
- sec_len <= 32) {
- ssid[ssid_index].ssid_length = sec_len;
- memcpy(ssid[ssid_index].ssid, pos, sec_len);
- ssid_index++;
- }
- pos += sec_len;
- len -= sec_len;
- break;
- case WEXT_CSCAN_TYPE_SECTION:
- case WEXT_CSCAN_CHANNEL_SECTION:
- pos += 1;
- len -= 1;
- break;
- case WEXT_CSCAN_PASV_DWELL_SECTION:
- case WEXT_CSCAN_HOME_DWELL_SECTION:
- case WEXT_CSCAN_ACTV_DWELL_SECTION:
- pos += 2;
- len -= 2;
- break;
- default:
- len = 0; /* stop parsing */
- }
- }
-
- /* it has still some scan parameter to parse, we only do this now... */
- _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
- } else {
- _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
- }
- }
-
- if (!_status)
- ret = -1;
-
-exit:
-
- return ret;
-}
-
-static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct list_head *plist, *phead;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- char *ev = extra;
- char *stop = ev + wrqu->data.length;
- u32 ret = 0;
- u32 cnt = 0;
- u32 wait_for_surveydone;
- int wait_status;
-
- if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
- ret = -EINVAL;
- goto exit;
- }
-
- wait_for_surveydone = 100;
-
- wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
-
- while (check_fwstate(pmlmepriv, wait_status)) {
- msleep(30);
- cnt++;
- if (cnt > wait_for_surveydone)
- break;
- }
-
- spin_lock_bh(&pmlmepriv->scanned_queue.lock);
-
- phead = get_list_head(queue);
- list_for_each(plist, phead) {
- if ((stop - ev) < SCAN_ITEM_SIZE) {
- ret = -E2BIG;
- break;
- }
-
- pnetwork = list_entry(plist, struct wlan_network, list);
-
- /* report network only if the current channel set contains the channel to which this network belongs */
- if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
- ev = translate_scan(padapter, a, pnetwork, ev, stop);
- }
-
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-
- wrqu->data.length = ev - extra;
- wrqu->data.flags = 0;
-
-exit:
- return ret;
-}
-
-/* set ssid flow */
-/* s1. rtw_set_802_11_infrastructure_mode() */
-/* s2. set_802_11_authenticaion_mode() */
-/* s3. set_802_11_encryption_mode() */
-/* s4. rtw_set_802_11_ssid() */
-static int rtw_wx_set_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct list_head *phead;
- struct wlan_network *pnetwork = NULL;
- enum ndis_802_11_auth_mode authmode;
- struct ndis_802_11_ssid ndis_ssid;
- u8 *dst_ssid, *src_ssid;
-
- uint ret = 0, len;
-
- if (!rtw_pwr_wakeup(padapter)) {
- ret = -1;
- goto exit;
- }
-
- if (!padapter->bup) {
- ret = -1;
- goto exit;
- }
-
- if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
- ret = -E2BIG;
- goto exit;
- }
-
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- ret = -1;
- goto exit;
- }
-
- authmode = padapter->securitypriv.ndisauthtype;
- if (wrqu->essid.flags && wrqu->essid.length) {
- len = min_t(uint, wrqu->essid.length, IW_ESSID_MAX_SIZE);
-
- memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
- ndis_ssid.ssid_length = len;
- memcpy(ndis_ssid.ssid, extra, len);
- src_ssid = ndis_ssid.ssid;
-
- spin_lock_bh(&queue->lock);
- phead = get_list_head(queue);
- list_for_each(pmlmepriv->pscanned, phead) {
- pnetwork = list_entry(pmlmepriv->pscanned,
- struct wlan_network, list);
-
- dst_ssid = pnetwork->network.ssid.ssid;
-
- if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_length)) &&
- (pnetwork->network.ssid.ssid_length == ndis_ssid.ssid_length)) {
-
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
- continue;
- }
-
- if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
- ret = -1;
- spin_unlock_bh(&queue->lock);
- goto exit;
- }
-
- break;
- }
- }
- spin_unlock_bh(&queue->lock);
- rtw_set_802_11_authentication_mode(padapter, authmode);
- if (!rtw_set_802_11_ssid(padapter, &ndis_ssid)) {
- ret = -1;
- goto exit;
- }
- }
-
-exit:
- return ret;
-}
-
-static int rtw_wx_get_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- u32 len;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
- len = pcur_bss->ssid.ssid_length;
- memcpy(extra, pcur_bss->ssid.ssid, len);
- } else {
- len = 0;
- *extra = 0;
- }
- wrqu->essid.length = len;
- wrqu->essid.flags = 1;
-
- return 0;
-}
-
-static int rtw_wx_set_rate(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- int i;
- u8 datarates[NumRates];
- u32 target_rate = wrqu->bitrate.value;
- u32 fixed = wrqu->bitrate.fixed;
- u32 ratevalue = 0;
- u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
-
- if (target_rate == -1) {
- ratevalue = 11;
- goto set_rate;
- }
- target_rate /= 100000;
-
- switch (target_rate) {
- case 10:
- ratevalue = 0;
- break;
- case 20:
- ratevalue = 1;
- break;
- case 55:
- ratevalue = 2;
- break;
- case 60:
- ratevalue = 3;
- break;
- case 90:
- ratevalue = 4;
- break;
- case 110:
- ratevalue = 5;
- break;
- case 120:
- ratevalue = 6;
- break;
- case 180:
- ratevalue = 7;
- break;
- case 240:
- ratevalue = 8;
- break;
- case 360:
- ratevalue = 9;
- break;
- case 480:
- ratevalue = 10;
- break;
- case 540:
- ratevalue = 11;
- break;
- default:
- ratevalue = 11;
- break;
- }
-
-set_rate:
-
- for (i = 0; i < NumRates; i++) {
- if (ratevalue == mpdatarate[i]) {
- datarates[i] = mpdatarate[i];
- if (fixed == 0)
- break;
- } else {
- datarates[i] = 0xff;
- }
- }
-
- return 0;
-}
-
-static int rtw_wx_get_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u16 max_rate = 0;
-
- max_rate = rtw_get_cur_max_rate(netdev_priv(dev));
-
- if (max_rate == 0)
- return -EPERM;
-
- wrqu->bitrate.fixed = 0; /* no auto select */
- wrqu->bitrate.value = max_rate * 100000;
-
- return 0;
-}
-
-static int rtw_wx_set_rts(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
-
- if (wrqu->rts.disabled) {
- padapter->registrypriv.rts_thresh = 2347;
- } else {
- if (wrqu->rts.value < 0 ||
- wrqu->rts.value > 2347)
- return -EINVAL;
-
- padapter->registrypriv.rts_thresh = wrqu->rts.value;
- }
-
- return 0;
-}
-
-static int rtw_wx_get_rts(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
-
- wrqu->rts.value = padapter->registrypriv.rts_thresh;
- wrqu->rts.fixed = 0; /* no auto select */
- /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
-
- return 0;
-}
-
-static int rtw_wx_set_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
-
- if (wrqu->frag.disabled) {
- padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
- } else {
- if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
- wrqu->frag.value > MAX_FRAG_THRESHOLD)
- return -EINVAL;
-
- padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
- }
-
- return 0;
-}
-
-static int rtw_wx_get_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
-
- wrqu->frag.value = padapter->xmitpriv.frag_len;
- wrqu->frag.fixed = 0; /* no auto select */
-
- return 0;
-}
-
-static int rtw_wx_get_retry(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->retry.value = 7;
- wrqu->retry.fixed = 0; /* no auto select */
- wrqu->retry.disabled = 1;
-
- return 0;
-}
-
-static int rtw_wx_set_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- u32 key, ret = 0;
- u32 keyindex_provided;
- struct ndis_802_11_wep wep;
- enum ndis_802_11_auth_mode authmode;
-
- struct iw_point *erq = &wrqu->encoding;
- struct adapter *padapter = netdev_priv(dev);
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- memset(&wep, 0, sizeof(struct ndis_802_11_wep));
-
- key = erq->flags & IW_ENCODE_INDEX;
-
- if (erq->flags & IW_ENCODE_DISABLED) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
-
- goto exit;
- }
-
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- keyindex_provided = 1;
- } else {
- keyindex_provided = 0;
- key = padapter->securitypriv.dot11PrivacyKeyIndex;
- }
-
- /* set authentication mode */
- if (erq->flags & IW_ENCODE_OPEN) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- } else if (erq->flags & IW_ENCODE_RESTRICTED) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
- authmode = Ndis802_11AuthModeShared;
- padapter->securitypriv.ndisauthtype = authmode;
- } else {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- }
-
- wep.KeyIndex = key;
- if (erq->length > 0) {
- wep.KeyLength = erq->length <= 5 ? 5 : 13;
-
- wep.Length = wep.KeyLength + offsetof(struct ndis_802_11_wep, KeyMaterial);
- } else {
- wep.KeyLength = 0;
-
- if (keyindex_provided == 1) {
- /* set key_id only, no given KeyMaterial(erq->length == 0). */
- padapter->securitypriv.dot11PrivacyKeyIndex = key;
-
- switch (padapter->securitypriv.dot11DefKeylen[key]) {
- case 5:
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
- break;
- case 13:
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
- break;
- default:
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- break;
- }
-
- goto exit;
- }
- }
-
- wep.KeyIndex |= 0x80000000;
-
- memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
-
- if (!rtw_set_802_11_add_wep(padapter, &wep)) {
- if (rf_on == pwrpriv->rf_pwrstate)
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
-exit:
- return ret;
-}
-
-static int rtw_wx_get_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- uint key;
- struct adapter *padapter = netdev_priv(dev);
- struct iw_point *erq = &wrqu->encoding;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
- }
-
- key = erq->flags & IW_ENCODE_INDEX;
-
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- } else {
- key = padapter->securitypriv.dot11PrivacyKeyIndex;
- }
-
- erq->flags = key + 1;
-
- switch (padapter->securitypriv.ndisencryptstatus) {
- case Ndis802_11EncryptionNotSupported:
- case Ndis802_11EncryptionDisabled:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- case Ndis802_11Encryption1Enabled:
- erq->length = padapter->securitypriv.dot11DefKeylen[key];
- if (erq->length) {
- memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
-
- erq->flags |= IW_ENCODE_ENABLED;
-
- if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
- erq->flags |= IW_ENCODE_OPEN;
- else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
- erq->flags |= IW_ENCODE_RESTRICTED;
- } else {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- }
- break;
- case Ndis802_11Encryption2Enabled:
- case Ndis802_11Encryption3Enabled:
- erq->length = 16;
- erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
- break;
- default:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- }
-
- return 0;
-}
-
-static int rtw_wx_get_power(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->power.value = 0;
- wrqu->power.fixed = 0; /* no auto select */
- wrqu->power.disabled = 1;
-
- return 0;
-}
-
-static int rtw_wx_set_gen_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
-
- return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
-}
-
-static int rtw_wx_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct iw_param *param = (struct iw_param *)&wrqu->param;
- int ret = 0;
-
- switch (param->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
-
- break;
- case IW_AUTH_CIPHER_GROUP:
-
- break;
- case IW_AUTH_KEY_MGMT:
- /*
- * ??? does not use these parameters
- */
- break;
- case IW_AUTH_TKIP_COUNTERMEASURES:
- if (param->value) {
- /* wpa_supplicant is enabling the tkip countermeasure. */
- padapter->securitypriv.btkip_countermeasure = true;
- } else {
- /* wpa_supplicant is disabling the tkip countermeasure. */
- padapter->securitypriv.btkip_countermeasure = false;
- }
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
-
- if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
- break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
- /* then it needn't reset it; */
-
- if (param->value) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
- }
-
- break;
- case IW_AUTH_80211_AUTH_ALG:
- /* It's the starting point of a link layer connection using wpa_supplicant */
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
- LeaveAllPowerSaveMode(padapter);
- rtw_disassoc_cmd(padapter, 500, false);
- rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter);
- }
- ret = wpa_set_auth_algs(dev, (u32)param->value);
- break;
- case IW_AUTH_WPA_ENABLED:
- break;
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- break;
- case IW_AUTH_PRIVACY_INVOKED:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int rtw_wx_set_enc_ext(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- char *alg_name;
- u32 param_len;
- struct ieee_param *param = NULL;
- struct iw_point *pencoding = &wrqu->encoding;
- struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
- int ret = 0;
-
- param_len = sizeof(struct ieee_param) + pext->key_len;
- param = (struct ieee_param *)rtw_malloc(param_len);
- if (!param)
- return -1;
-
- memset(param, 0, param_len);
-
- param->cmd = IEEE_CMD_SET_ENCRYPTION;
- eth_broadcast_addr(param->sta_addr);
-
- switch (pext->alg) {
- case IW_ENCODE_ALG_NONE:
- /* todo: remove key */
- /* remove = 1; */
- alg_name = "none";
- break;
- case IW_ENCODE_ALG_WEP:
- alg_name = "WEP";
- break;
- case IW_ENCODE_ALG_TKIP:
- alg_name = "TKIP";
- break;
- case IW_ENCODE_ALG_CCMP:
- alg_name = "CCMP";
- break;
- default:
- ret = -1;
- goto exit;
- }
-
- strscpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
-
- if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
- param->u.crypt.set_tx = 1;
-
- /* cliW: WEP does not have group key
- * just not checking GROUP key setting
- */
- if ((pext->alg != IW_ENCODE_ALG_WEP) &&
- (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
- param->u.crypt.set_tx = 0;
-
- param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
-
- if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- memcpy(param->u.crypt.seq, pext->rx_seq, 8);
-
- if (pext->key_len) {
- param->u.crypt.key_len = pext->key_len;
- memcpy(param->u.crypt.key, pext + 1, pext->key_len);
- }
-
- ret = wpa_set_encryption(dev, param, param_len);
-
-exit:
- kfree(param);
- return ret;
-}
-
-static int rtw_wx_get_nick(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- if (extra) {
- wrqu->data.length = 14;
- wrqu->data.flags = 1;
- memcpy(extra, "<WIFI@REALTEK>", 14);
- }
-
- /* dump debug info here */
- return 0;
-}
-
-static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
- uint ret = 0;
- struct adapter *padapter = netdev_priv(dev);
-
- switch (name) {
- case IEEE_PARAM_WPA_ENABLED:
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
- switch (value & 0xff) {
- case 1: /* WPA */
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case 2: /* WPA2 */
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- }
- break;
- case IEEE_PARAM_TKIP_COUNTERMEASURES:
- break;
- case IEEE_PARAM_DROP_UNENCRYPTED: {
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
-
- break;
- }
- case IEEE_PARAM_PRIVACY_INVOKED:
- break;
-
- case IEEE_PARAM_AUTH_ALGS:
- ret = wpa_set_auth_algs(dev, value);
- break;
- case IEEE_PARAM_IEEE_802_1X:
- break;
- case IEEE_PARAM_WPAX_SELECT:
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- return ret;
-}
-
-static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
-{
- int ret = 0;
- struct adapter *padapter = netdev_priv(dev);
-
- switch (command) {
- case IEEE_MLME_STA_DEAUTH:
- if (!rtw_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- case IEEE_MLME_STA_DISASSOC:
- if (!rtw_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
- return ret;
-}
-
-static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
-{
- struct ieee_param *param;
- uint ret = 0;
-
- if (!p->pointer || p->length != sizeof(struct ieee_param))
- return -EINVAL;
-
- param = memdup_user(p->pointer, p->length);
- if (IS_ERR(param))
- return PTR_ERR(param);
-
- switch (param->cmd) {
- case IEEE_CMD_SET_WPA_PARAM:
- ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
- break;
-
- case IEEE_CMD_SET_WPA_IE:
- ret = rtw_set_wpa_ie(netdev_priv(dev),
- (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
- break;
-
- case IEEE_CMD_SET_ENCRYPTION:
- ret = wpa_set_encryption(dev, param, p->length);
- break;
-
- case IEEE_CMD_MLME:
- ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
- break;
-
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
-
- kfree(param);
- return ret;
-}
-
-#ifdef CONFIG_88EU_AP_MODE
-static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
-{
- struct cmd_obj *ph2c;
- struct set_stakey_parm *psetstakey_para;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- u8 res = _SUCCESS;
-
- ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
- if (!ph2c) {
- res = _FAIL;
- goto exit;
- }
-
- psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
- if (!psetstakey_para) {
- kfree(ph2c);
- res = _FAIL;
- goto exit;
- }
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
-
- psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
-
- memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
-
- memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
-
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-
-exit:
-
- return res;
-}
-
-static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
-{
- u8 keylen;
- struct cmd_obj *pcmd;
- struct setkey_parm *psetkeyparm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- int res = _SUCCESS;
-
- pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
- if (!pcmd) {
- res = _FAIL;
- goto exit;
- }
- psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
- if (!psetkeyparm) {
- kfree(pcmd);
- res = _FAIL;
- goto exit;
- }
-
- psetkeyparm->keyid = (u8)keyid;
-
- psetkeyparm->algorithm = alg;
-
- psetkeyparm->set_tx = 1;
-
- switch (alg) {
- case _WEP40_:
- keylen = 5;
- break;
- case _WEP104_:
- keylen = 13;
- break;
- case _TKIP_:
- case _TKIP_WTMIC_:
- case _AES_:
- default:
- keylen = 16;
- }
-
- memcpy(&psetkeyparm->key[0], key, keylen);
-
- pcmd->cmdcode = _SetKey_CMD_;
- pcmd->parmbuf = (u8 *)psetkeyparm;
- pcmd->cmdsz = (sizeof(struct setkey_parm));
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
-
- INIT_LIST_HEAD(&pcmd->list);
-
- res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-
-exit:
-
- return res;
-}
-
-static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
-{
- u8 alg;
-
- switch (keylen) {
- case 5:
- alg = _WEP40_;
- break;
- case 13:
- alg = _WEP104_;
- break;
- default:
- alg = _NO_PRIVACY_;
- }
-
- return set_group_key(padapter, key, alg, keyid);
-}
-
-static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
-{
- int ret = 0;
- u32 wep_key_idx, wep_key_len, wep_total_len;
- struct ndis_802_11_wep *pwep = NULL;
- struct sta_info *psta = NULL, *pbcmc_sta = NULL;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
- if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
- ret = -EINVAL;
- goto exit;
- }
- if (is_broadcast_ether_addr(param->sta_addr)) {
- if (param->u.crypt.idx >= WEP_KEYS) {
- ret = -EINVAL;
- goto exit;
- }
- } else {
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if (!psta)
- goto exit;
- }
-
- if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta))
- /* todo:clear default encryption keys */
- goto exit;
-
- if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) {
- wep_key_idx = param->u.crypt.idx;
- wep_key_len = param->u.crypt.key_len;
- if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
- ret = -EINVAL;
- goto exit;
- }
-
- if (wep_key_len > 0) {
- wep_key_len = wep_key_len <= 5 ? 5 : 13;
- wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
- pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
- if (!pwep)
- goto exit;
-
- memset(pwep, 0, wep_total_len);
-
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_total_len;
- }
-
- pwep->KeyIndex = wep_key_idx;
-
- memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
-
- if (param->u.crypt.set_tx) {
- psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
- psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
- psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
-
- if (pwep->KeyLength == 13) {
- psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
- psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
- }
-
- psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
-
- memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength);
-
- psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
-
- set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
- } else {
- /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
- /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
-
- memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength);
-
- psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
-
- set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
- }
-
- goto exit;
- }
-
- if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */
- if (param->u.crypt.set_tx == 1) {
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
-
- psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
- if (param->u.crypt.key_len == 13)
- psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
- } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
- psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
- memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
- /* set mic key */
- memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[16], 8);
- memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
-
- psecuritypriv->busetkipkey = true;
- } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
- psecuritypriv->dot118021XGrpPrivacy = _AES_;
- memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
- } else {
- psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
- }
- psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
- psecuritypriv->binstallGrpkey = true;
- psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */
- set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
- pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
- if (pbcmc_sta) {
- pbcmc_sta->ieee8021x_blocked = false;
- pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
- }
- }
- goto exit;
- }
-
- if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- if (param->u.crypt.set_tx == 1) {
- memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
-
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- psta->dot118021XPrivacy = _WEP40_;
- if (param->u.crypt.key_len == 13)
- psta->dot118021XPrivacy = _WEP104_;
- } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
- psta->dot118021XPrivacy = _TKIP_;
-
- /* set mic key */
- memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
- memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
-
- psecuritypriv->busetkipkey = true;
- } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
- psta->dot118021XPrivacy = _AES_;
- } else {
- psta->dot118021XPrivacy = _NO_PRIVACY_;
- }
-
- set_pairwise_key(padapter, psta);
-
- psta->ieee8021x_blocked = false;
- } else { /* group key??? */
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
- psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
- if (param->u.crypt.key_len == 13)
- psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
- } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
- psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
-
- memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
-
- /* set mic key */
- memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[16], 8);
- memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
-
- psecuritypriv->busetkipkey = true;
- } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
- psecuritypriv->dot118021XGrpPrivacy = _AES_;
-
- memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
- param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
- } else {
- psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
- }
-
- psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
-
- psecuritypriv->binstallGrpkey = true;
-
- psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */
-
- set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
-
- pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
- if (pbcmc_sta) {
- pbcmc_sta->ieee8021x_blocked = false;
- pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
- }
- }
- }
- }
-
-exit:
-
- kfree(pwep);
-
- return ret;
-}
-
-static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
-{
- int ret = 0;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
- unsigned char *pbuf = param->u.bcn_ie.buf;
-
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return -EINVAL;
-
- memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
-
- if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
- pstapriv->max_num_sta = NUM_STA;
-
- if (rtw_check_beacon_data(padapter, pbuf, len - 12 - 2) == _SUCCESS) /* 12 = param header, 2:no packed */
- ret = 0;
- else
- ret = -EINVAL;
-
- return ret;
-}
-
-static int rtw_hostapd_sta_flush(struct net_device *dev)
-{
- struct adapter *padapter = netdev_priv(dev);
-
- flush_all_cam_entry(padapter); /* clear CAM */
-
- return rtw_sta_flush(padapter);
-}
-
-static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
-{
- int ret = 0;
- struct sta_info *psta = NULL;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (!check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)))
- return -EINVAL;
-
- if (is_broadcast_ether_addr(param->sta_addr))
- return -EINVAL;
-
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if (psta) {
- int flags = param->u.add_sta.flags;
-
- psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
-
- memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
-
- /* check wmm cap. */
- if (WLAN_STA_WME & flags)
- psta->qos_option = 1;
- else
- psta->qos_option = 0;
-
- if (pmlmepriv->qospriv.qos_option == 0)
- psta->qos_option = 0;
-
- /* chec 802.11n ht cap. */
- if (WLAN_STA_HT & flags) {
- psta->htpriv.ht_option = true;
- psta->qos_option = 1;
- memcpy(&psta->htpriv.ht_cap, &param->u.add_sta.ht_cap,
- sizeof(struct ieee80211_ht_cap));
- } else {
- psta->htpriv.ht_option = false;
- }
-
- if (!pmlmepriv->htpriv.ht_option)
- psta->htpriv.ht_option = false;
-
- update_sta_info_apmode(padapter, psta);
- } else {
- ret = -ENOMEM;
- }
-
- return ret;
-}
-
-static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
-{
- struct sta_info *psta = NULL;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
- int updated = 0;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
- return -EINVAL;
-
- if (is_broadcast_ether_addr(param->sta_addr))
- return -EINVAL;
-
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if (psta) {
- spin_lock_bh(&pstapriv->asoc_list_lock);
- if (!list_empty(&psta->asoc_list)) {
- list_del_init(&psta->asoc_list);
- pstapriv->asoc_list_cnt--;
- updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
- }
- spin_unlock_bh(&pstapriv->asoc_list_lock);
- associated_clients_update(padapter, updated);
- psta = NULL;
- }
-
- return 0;
-}
-
-static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
-{
- int ret = 0;
- struct sta_info *psta = NULL;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
- struct sta_data *psta_data = (struct sta_data *)param_ex->data;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
- return -EINVAL;
-
- if (is_broadcast_ether_addr(param_ex->sta_addr))
- return -EINVAL;
-
- psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
- if (psta) {
- psta_data->aid = (u16)psta->aid;
- psta_data->capability = psta->capability;
- psta_data->flags = psta->flags;
-
-/*
- nonerp_set : BIT(0)
- no_short_slot_time_set : BIT(1)
- no_short_preamble_set : BIT(2)
- no_ht_gf_set : BIT(3)
- no_ht_set : BIT(4)
- ht_20mhz_set : BIT(5)
-*/
-
- psta_data->sta_set = ((psta->nonerp_set) |
- (psta->no_short_slot_time_set << 1) |
- (psta->no_short_preamble_set << 2) |
- (psta->no_ht_gf_set << 3) |
- (psta->no_ht_set << 4) |
- (psta->ht_20mhz_set << 5));
- psta_data->tx_supp_rates_len = psta->bssratelen;
- memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
- memcpy(&psta_data->ht_cap,
- &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap));
- psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
- psta_data->rx_bytes = psta->sta_stats.rx_bytes;
- psta_data->rx_drops = psta->sta_stats.rx_drops;
- psta_data->tx_pkts = psta->sta_stats.tx_pkts;
- psta_data->tx_bytes = psta->sta_stats.tx_bytes;
- psta_data->tx_drops = psta->sta_stats.tx_drops;
- } else {
- ret = -1;
- }
-
- return ret;
-}
-
-static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
-{
- int ret = 0;
- struct sta_info *psta = NULL;
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
- return -EINVAL;
-
- if (is_broadcast_ether_addr(param->sta_addr))
- return -EINVAL;
-
- psta = rtw_get_stainfo(pstapriv, param->sta_addr);
- if (psta) {
- if (psta->wpa_ie[0] == WLAN_EID_RSN ||
- psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
- int wpa_ie_len;
- int copy_len;
-
- wpa_ie_len = psta->wpa_ie[1];
- copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
- param->u.wpa_ie.len = copy_len;
- memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
- }
- } else {
- ret = -1;
- }
-
- return ret;
-}
-
-static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
-{
- unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- int ie_len;
-
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return -EINVAL;
-
- ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
-
- kfree(pmlmepriv->wps_beacon_ie);
- pmlmepriv->wps_beacon_ie = NULL;
-
- if (ie_len > 0) {
- pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
- pmlmepriv->wps_beacon_ie_len = ie_len;
- if (!pmlmepriv->wps_beacon_ie)
- return -EINVAL;
-
- memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
-
- update_beacon(padapter, WLAN_EID_VENDOR_SPECIFIC, wps_oui, true);
-
- pmlmeext->bstart_bss = true;
- }
-
- return 0;
-}
-
-static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- int ie_len;
-
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return -EINVAL;
-
- ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
-
- kfree(pmlmepriv->wps_probe_resp_ie);
- pmlmepriv->wps_probe_resp_ie = NULL;
-
- if (ie_len > 0) {
- pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
- pmlmepriv->wps_probe_resp_ie_len = ie_len;
- if (!pmlmepriv->wps_probe_resp_ie)
- return -EINVAL;
- memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
- }
-
- return 0;
-}
-
-static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- int ie_len;
-
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return -EINVAL;
-
- ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
-
- kfree(pmlmepriv->wps_assoc_resp_ie);
- pmlmepriv->wps_assoc_resp_ie = NULL;
-
- if (ie_len > 0) {
- pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
- pmlmepriv->wps_assoc_resp_ie_len = ie_len;
- if (!pmlmepriv->wps_assoc_resp_ie)
- return -EINVAL;
-
- memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
- }
-
- return 0;
-}
-
-static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-
- u8 value;
-
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return -EINVAL;
-
- value = param->u.wpa_param.value;
-
- /* use the same definition of hostapd's ignore_broadcast_ssid */
- if (value != 1 && value != 2)
- value = 0;
- pmlmeinfo->hidden_ssid_mode = value;
- return 0;
-}
-
-static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return -EINVAL;
-
- if (is_broadcast_ether_addr(param->sta_addr))
- return -EINVAL;
-
- return rtw_acl_remove_sta(padapter, param->sta_addr);
-}
-
-static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return -EINVAL;
-
- if (is_broadcast_ether_addr(param->sta_addr))
- return -EINVAL;
-
- return rtw_acl_add_sta(padapter, param->sta_addr);
-}
-
-static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
- return -EINVAL;
-
- rtw_set_macaddr_acl(padapter, param->u.mlme.command);
-
- return 0;
-}
-
-static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
-{
- struct ieee_param *param;
- int ret = 0;
- struct adapter *padapter = netdev_priv(dev);
-
- /*
- * this function is expect to call in master mode, which allows no power saving
- * so, we just check hw_init_completed
- */
-
- if (!padapter->hw_init_completed)
- return -EPERM;
-
- if (!p->pointer || p->length != sizeof(struct ieee_param))
- return -EINVAL;
-
- param = memdup_user(p->pointer, p->length);
- if (IS_ERR(param))
- return PTR_ERR(param);
-
- switch (param->cmd) {
- case RTL871X_HOSTAPD_FLUSH:
- ret = rtw_hostapd_sta_flush(dev);
- break;
- case RTL871X_HOSTAPD_ADD_STA:
- ret = rtw_add_sta(dev, param);
- break;
- case RTL871X_HOSTAPD_REMOVE_STA:
- ret = rtw_del_sta(dev, param);
- break;
- case RTL871X_HOSTAPD_SET_BEACON:
- ret = rtw_set_beacon(dev, param, p->length);
- break;
- case RTL871X_SET_ENCRYPTION:
- ret = rtw_set_encryption(dev, param, p->length);
- break;
- case RTL871X_HOSTAPD_GET_WPAIE_STA:
- ret = rtw_get_sta_wpaie(dev, param);
- break;
- case RTL871X_HOSTAPD_SET_WPS_BEACON:
- ret = rtw_set_wps_beacon(dev, param, p->length);
- break;
- case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
- ret = rtw_set_wps_probe_resp(dev, param, p->length);
- break;
- case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
- ret = rtw_set_wps_assoc_resp(dev, param, p->length);
- break;
- case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
- ret = rtw_set_hidden_ssid(dev, param, p->length);
- break;
- case RTL871X_HOSTAPD_GET_INFO_STA:
- ret = rtw_ioctl_get_sta_data(dev, param, p->length);
- break;
- case RTL871X_HOSTAPD_SET_MACADDR_ACL:
- ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
- break;
- case RTL871X_HOSTAPD_ACL_ADD_STA:
- ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
- break;
- case RTL871X_HOSTAPD_ACL_REMOVE_STA:
- ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
- kfree(param);
- return ret;
-}
-#endif
-
-#include <rtw_android.h>
-static int rtw_wx_set_priv(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq, char *extra)
-{
- int ret = 0;
- int len = 0;
- char *ext;
- struct adapter *padapter = netdev_priv(dev);
- struct iw_point *dwrq = (struct iw_point *)awrq;
-
- if (dwrq->length == 0)
- return -EFAULT;
-
- len = dwrq->length;
- ext = vmalloc(len);
- if (!ext)
- return -ENOMEM;
-
- if (copy_from_user(ext, dwrq->pointer, len)) {
- vfree(ext);
- return -EFAULT;
- }
-
- /* added for wps2.0 @20110524 */
- if (dwrq->flags == 0x8766 && len > 8) {
- u32 cp_sz;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 *probereq_wpsie = ext;
- int probereq_wpsie_len = len;
- u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- if ((probereq_wpsie[0] == WLAN_EID_VENDOR_SPECIFIC) &&
- (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
- cp_sz = min(probereq_wpsie_len, MAX_WPS_IE_LEN);
-
- pmlmepriv->wps_probe_req_ie_len = 0;
- kfree(pmlmepriv->wps_probe_req_ie);
- pmlmepriv->wps_probe_req_ie = NULL;
-
- pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
- if (!pmlmepriv->wps_probe_req_ie) {
- pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
- ret = -EINVAL;
- goto FREE_EXT;
- }
- memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
- pmlmepriv->wps_probe_req_ie_len = cp_sz;
- }
- goto FREE_EXT;
- }
-
- if (len >= WEXT_CSCAN_HEADER_SIZE &&
- !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
- ret = rtw_wx_set_scan(dev, info, awrq, ext);
- goto FREE_EXT;
- }
-
-FREE_EXT:
-
- vfree(ext);
-
- return ret;
-}
-
-static iw_handler rtw_handlers[] = {
- IW_HANDLER(SIOCGIWNAME, rtw_wx_get_name),
- IW_HANDLER(SIOCGIWFREQ, rtw_wx_get_freq),
- IW_HANDLER(SIOCSIWMODE, rtw_wx_set_mode),
- IW_HANDLER(SIOCGIWMODE, rtw_wx_get_mode),
- IW_HANDLER(SIOCGIWSENS, rtw_wx_get_sens),
- IW_HANDLER(SIOCGIWRANGE, rtw_wx_get_range),
- IW_HANDLER(SIOCSIWPRIV, rtw_wx_set_priv),
- IW_HANDLER(SIOCSIWAP, rtw_wx_set_wap),
- IW_HANDLER(SIOCGIWAP, rtw_wx_get_wap),
- IW_HANDLER(SIOCSIWMLME, rtw_wx_set_mlme),
- IW_HANDLER(SIOCSIWSCAN, rtw_wx_set_scan),
- IW_HANDLER(SIOCGIWSCAN, rtw_wx_get_scan),
- IW_HANDLER(SIOCSIWESSID, rtw_wx_set_essid),
- IW_HANDLER(SIOCGIWESSID, rtw_wx_get_essid),
- IW_HANDLER(SIOCGIWNICKN, rtw_wx_get_nick),
- IW_HANDLER(SIOCSIWRATE, rtw_wx_set_rate),
- IW_HANDLER(SIOCGIWRATE, rtw_wx_get_rate),
- IW_HANDLER(SIOCSIWRTS, rtw_wx_set_rts),
- IW_HANDLER(SIOCGIWRTS, rtw_wx_get_rts),
- IW_HANDLER(SIOCSIWFRAG, rtw_wx_set_frag),
- IW_HANDLER(SIOCGIWFRAG, rtw_wx_get_frag),
- IW_HANDLER(SIOCGIWRETRY, rtw_wx_get_retry),
- IW_HANDLER(SIOCSIWENCODE, rtw_wx_set_enc),
- IW_HANDLER(SIOCGIWENCODE, rtw_wx_get_enc),
- IW_HANDLER(SIOCGIWPOWER, rtw_wx_get_power),
- IW_HANDLER(SIOCSIWGENIE, rtw_wx_set_gen_ie),
- IW_HANDLER(SIOCSIWAUTH, rtw_wx_set_auth),
- IW_HANDLER(SIOCSIWENCODEEXT, rtw_wx_set_enc_ext),
- IW_HANDLER(SIOCSIWPMKSA, rtw_wx_set_pmkid),
-};
-
-static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct iw_statistics *piwstats = &padapter->iwstats;
-
- if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
- piwstats->qual.qual = 0;
- piwstats->qual.level = 0;
- piwstats->qual.noise = 0;
- } else {
- piwstats->qual.level = padapter->recvpriv.signal_strength;
- piwstats->qual.qual = padapter->recvpriv.signal_qual;
- piwstats->qual.noise = padapter->recvpriv.noise;
- }
- piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
- return piwstats;
-}
-
-struct iw_handler_def rtw_handlers_def = {
- .standard = rtw_handlers,
- .num_standard = ARRAY_SIZE(rtw_handlers),
- .get_wireless_stats = rtw_get_wireless_stats,
-};
-
-int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct iwreq *wrq = (struct iwreq *)rq;
- int ret = 0;
-
- switch (cmd) {
- case RTL_IOCTL_WPA_SUPPLICANT:
- ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
- break;
-#ifdef CONFIG_88EU_AP_MODE
- case RTL_IOCTL_HOSTAPD:
- ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
- break;
-#endif /* CONFIG_88EU_AP_MODE */
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- return ret;
-}
diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
deleted file mode 100644
index f12d8a707376..000000000000
--- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
+++ /dev/null
@@ -1,167 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#define _MLME_OSDEP_C_
-
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <mlme_osdep.h>
-
-void rtw_init_mlme_timer(struct adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- timer_setup(&pmlmepriv->assoc_timer, _rtw_join_timeout_handler, 0);
- timer_setup(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler, 0);
- timer_setup(&pmlmepriv->dynamic_chk_timer,
- rtw_dynamic_check_timer_handlder, 0);
-}
-
-void rtw_os_indicate_connect(struct adapter *adapter)
-{
- rtw_indicate_wx_assoc_event(adapter);
- netif_carrier_on(adapter->pnetdev);
-}
-
-static struct rt_pmkid_list backup_pmkid[NUM_PMKID_CACHE];
-
-void rtw_reset_securitypriv(struct adapter *adapter)
-{
- u8 backup_index;
- u8 backup_counter;
- u32 backup_time;
- struct security_priv *psec_priv = &adapter->securitypriv;
-
- if (psec_priv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
- /* 802.1x
- * We have to backup the PMK information for WiFi PMK Caching
- * test item. Backup the btkip_countermeasure information. When
- * the countermeasure is trigger, the driver have to disconnect
- * with AP for 60 seconds.
- */
- memcpy(backup_pmkid, psec_priv->PMKIDList,
- sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
- backup_index = psec_priv->PMKIDIndex;
- backup_counter = psec_priv->btkip_countermeasure;
- backup_time = psec_priv->btkip_countermeasure_time;
-
- memset(psec_priv, 0, sizeof(*psec_priv));
-
- /* Restore the PMK information to securitypriv structure
- * for the following connection.
- */
- memcpy(psec_priv->PMKIDList, backup_pmkid,
- sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
- psec_priv->PMKIDIndex = backup_index;
- psec_priv->btkip_countermeasure = backup_counter;
- psec_priv->btkip_countermeasure_time = backup_time;
- psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
- psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
- } else {
- /* reset values in securitypriv */
- psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
- psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
- psec_priv->dot11PrivacyKeyIndex = 0;
- psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
- psec_priv->dot118021XGrpKeyid = 1;
- psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
- psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
- }
-}
-
-void rtw_os_indicate_disconnect(struct adapter *adapter)
-{
- /* Do it first for tx broadcast pkt after disconnection issue! */
- netif_carrier_off(adapter->pnetdev);
- rtw_indicate_wx_disassoc_event(adapter);
- rtw_reset_securitypriv(adapter);
-}
-
-void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
-{
- uint len;
- u8 *buff, *p, i;
- union iwreq_data wrqu;
-
- buff = NULL;
- if (authmode == WLAN_EID_VENDOR_SPECIFIC) {
- buff = rtw_malloc(IW_CUSTOM_MAX);
- if (!buff)
- return;
- memset(buff, 0, IW_CUSTOM_MAX);
- p = buff;
- p += sprintf(p, "ASSOCINFO(ReqIEs =");
- len = sec_ie[1] + 2;
- len = min_t(uint, len, IW_CUSTOM_MAX);
- for (i = 0; i < len; i++)
- p += sprintf(p, "%02x", sec_ie[i]);
- p += sprintf(p, ")");
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = min_t(__u16, p - buff, IW_CUSTOM_MAX);
- wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
- kfree(buff);
- }
-}
-
-void init_addba_retry_timer(struct adapter *padapter, struct sta_info *psta)
-{
- timer_setup(&psta->addba_retry_timer, addba_timer_hdl, 0);
-}
-
-void init_mlme_ext_timer(struct adapter *padapter)
-{
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- timer_setup(&pmlmeext->survey_timer, survey_timer_hdl, 0);
- timer_setup(&pmlmeext->link_timer, link_timer_hdl, 0);
-}
-
-#ifdef CONFIG_88EU_AP_MODE
-
-void rtw_indicate_sta_assoc_event(struct adapter *padapter, struct sta_info *psta)
-{
- union iwreq_data wrqu;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (!psta)
- return;
-
- if (psta->aid > NUM_STA)
- return;
-
- if (pstapriv->sta_aid[psta->aid - 1] != psta)
- return;
-
- wrqu.addr.sa_family = ARPHRD_ETHER;
-
- memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
-
- wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL);
-}
-
-void rtw_indicate_sta_disassoc_event(struct adapter *padapter, struct sta_info *psta)
-{
- union iwreq_data wrqu;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (!psta)
- return;
-
- if (psta->aid > NUM_STA)
- return;
-
- if (pstapriv->sta_aid[psta->aid - 1] != psta)
- return;
-
- wrqu.addr.sa_family = ARPHRD_ETHER;
-
- memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
-
- wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL);
-}
-
-#endif
diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c
deleted file mode 100644
index 6370a3d8881b..000000000000
--- a/drivers/staging/rtl8188eu/os_dep/mon.c
+++ /dev/null
@@ -1,183 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * RTL8188EU monitor interface
- *
- * Copyright (C) 2015 Jakub Sitnicki
- */
-
-#include <linux/ieee80211.h>
-#include <linux/netdevice.h>
-#include <net/cfg80211.h>
-
-#include <drv_types.h>
-#include <rtw_recv.h>
-#include <rtw_xmit.h>
-#include <mon.h>
-
-/*
- * unprotect_frame() - unset Protected flag and strip off IV and ICV/MIC
- */
-static void unprotect_frame(struct sk_buff *skb, int iv_len, int icv_len)
-{
- struct ieee80211_hdr *hdr;
- int hdr_len;
-
- hdr = (struct ieee80211_hdr *)skb->data;
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
-
- if (skb->len < hdr_len + iv_len + icv_len)
- return;
- if (!ieee80211_has_protected(hdr->frame_control))
- return;
-
- hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-
- memmove(skb->data + iv_len, skb->data, hdr_len);
- skb_pull(skb, iv_len);
- skb_trim(skb, skb->len - icv_len);
-}
-
-static void mon_recv_decrypted(struct net_device *dev, const u8 *data,
- int data_len, int iv_len, int icv_len)
-{
- struct sk_buff *skb;
-
- skb = netdev_alloc_skb(dev, data_len);
- if (!skb)
- return;
- skb_put_data(skb, data, data_len);
-
- /*
- * Frame data is not encrypted. Strip off protection so
- * userspace doesn't think that it is.
- */
- unprotect_frame(skb, iv_len, icv_len);
-
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
-}
-
-static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
- int data_len)
-{
- if (net_ratelimit())
- netdev_info(dev, "Encrypted packets are not supported");
-}
-
-/*
- * rtl88eu_mon_recv_hook() - forward received frame to the monitor interface
- *
- * Assumes that the frame contains an IV and an ICV/MIC, and that
- * encrypt field in frame->attrib have been set accordingly.
- */
-void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
-{
- struct rx_pkt_attrib *attr;
- int iv_len, icv_len;
- int data_len;
- u8 *data;
-
- if (!dev || !frame)
- return;
- if (!netif_running(dev))
- return;
-
- attr = &frame->attrib;
- data = frame->pkt->data;
- data_len = frame->pkt->len;
-
- /* Broadcast and multicast frames don't have attr->{iv,icv}_len set */
- SET_ICE_IV_LEN(iv_len, icv_len, attr->encrypt);
-
- if (attr->bdecrypted)
- mon_recv_decrypted(dev, data, data_len, iv_len, icv_len);
- else
- mon_recv_encrypted(dev, data, data_len);
-}
-
-/*
- * rtl88eu_mon_xmit_hook() - forward trasmitted frame to the monitor interface
- *
- * Assumes that:
- * - frame header contains an IV and frame->attrib.iv_len is set accordingly,
- * - data is not encrypted and ICV/MIC has not been appended yet.
- */
-void rtl88eu_mon_xmit_hook(struct net_device *dev, struct xmit_frame *frame,
- uint frag_len)
-{
- struct pkt_attrib *attr;
- u8 *data;
- int i, offset;
-
- if (!dev || !frame)
- return;
- if (!netif_running(dev))
- return;
-
- attr = &frame->attrib;
-
- offset = TXDESC_SIZE + frame->pkt_offset * PACKET_OFFSET_SZ;
- data = frame->buf_addr + offset;
-
- for (i = 0; i < attr->nr_frags - 1; i++) {
- mon_recv_decrypted(dev, data, frag_len, attr->iv_len, 0);
- data += frag_len;
- data = (u8 *)round_up((size_t)data, 4);
- }
- /* Last fragment has different length */
- mon_recv_decrypted(dev, data, attr->last_txcmdsz, attr->iv_len, 0);
-}
-
-static netdev_tx_t mon_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
-}
-
-static const struct net_device_ops mon_netdev_ops = {
- .ndo_start_xmit = mon_xmit,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-static void mon_setup(struct net_device *dev)
-{
- dev->netdev_ops = &mon_netdev_ops;
- dev->needs_free_netdev = true;
- ether_setup(dev);
- dev->priv_flags |= IFF_NO_QUEUE;
- dev->type = ARPHRD_IEEE80211;
- /*
- * Use a locally administered address (IEEE 802)
- * XXX: Copied from mac80211_hwsim driver. Revisit.
- */
- eth_zero_addr(dev->dev_addr);
- dev->dev_addr[0] = 0x12;
-}
-
-struct net_device *rtl88eu_mon_init(void)
-{
- struct net_device *dev;
- int err;
-
- dev = alloc_netdev(0, "mon%d", NET_NAME_UNKNOWN, mon_setup);
- if (!dev)
- return NULL;
-
- err = register_netdev(dev);
- if (err < 0) {
- free_netdev(dev);
- return NULL;
- }
-
- return dev;
-}
-
-void rtl88eu_mon_deinit(struct net_device *dev)
-{
- if (!dev)
- return;
-
- unregister_netdev(dev);
-}
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
deleted file mode 100644
index 596e03e7b286..000000000000
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ /dev/null
@@ -1,658 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _OS_INTFS_C_
-
-#include <osdep_service.h>
-#include <osdep_intf.h>
-#include <drv_types.h>
-#include <xmit_osdep.h>
-#include <recv_osdep.h>
-#include <hal_intf.h>
-#include <rtw_ioctl.h>
-#include <rtl8188e_hal.h>
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
-MODULE_AUTHOR("Realtek Semiconductor Corp.");
-MODULE_VERSION("v4.1.4_6773.20130222");
-MODULE_FIRMWARE("rtlwifi/rtl8188eufw.bin");
-
-#define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */
-
-/* module param defaults */
-/* Ndis802_11Infrastructure; infra, ad-hoc, auto */
-static int rtw_channel = 1;/* ad-hoc support requirement */
-static int rtw_wireless_mode = WIRELESS_11BG_24N;
-static int rtw_vrtl_carrier_sense = AUTO_VCS;
-static int rtw_vcs_type = RTS_CTS;/* */
-static int rtw_rts_thresh = 2347;/* */
-static int rtw_frag_thresh = 2346;/* */
-static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */
-static int rtw_power_mgnt = 1;
-static int rtw_ips_mode = IPS_NORMAL;
-
-static int rtw_smart_ps = 2;
-
-module_param(rtw_ips_mode, int, 0644);
-MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode");
-
-static int rtw_debug = 1;
-
-static int rtw_acm_method;/* 0:By SW 1:By HW. */
-
-static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */
-static int rtw_uapsd_enable;
-
-static int rtw_ht_enable = 1;
-/* 0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */
-static int rtw_cbw40_enable = 3;
-static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */
-
-/* 0: disable
- * bit(0):enable 2.4g
- * bit(1):enable 5g
- * default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ
- */
-static int rtw_rx_stbc = 1;
-static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */
-
-static int rtw_wifi_spec;
-static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX;
-
-static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */
-
-/* 0: decide by efuse
- * 1: for 88EE, 1Tx and 1RxCG are diversity (2 Ant with SPDT)
- * 2: for 88EE, 1Tx and 2Rx are diversity (2 Ant, Tx and RxCG are both on aux
- * port, RxCS is on main port)
- * 3: for 88EE, 1Tx and 1RxCG are fixed (1Ant, Tx and RxCG are both on aux port)
- */
-static int rtw_antdiv_type;
-
-static int rtw_enusbss;/* 0:disable, 1:enable */
-
-static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */
-
-int rtw_mc2u_disable;
-
-static int rtw_80211d;
-
-static char *ifname = "wlan%d";
-module_param(ifname, charp, 0644);
-MODULE_PARM_DESC(ifname, "The default name to allocate for first interface");
-
-static char *if2name = "wlan%d";
-module_param(if2name, charp, 0644);
-MODULE_PARM_DESC(if2name, "The default name to allocate for second interface");
-
-/* temp mac address if users want to use instead of the mac address in Efuse */
-char *rtw_initmac;
-
-module_param(rtw_initmac, charp, 0644);
-module_param(rtw_channel_plan, int, 0644);
-module_param(rtw_channel, int, 0644);
-module_param(rtw_wmm_enable, int, 0644);
-module_param(rtw_vrtl_carrier_sense, int, 0644);
-module_param(rtw_vcs_type, int, 0644);
-module_param(rtw_ht_enable, int, 0644);
-module_param(rtw_cbw40_enable, int, 0644);
-module_param(rtw_ampdu_enable, int, 0644);
-module_param(rtw_rx_stbc, int, 0644);
-module_param(rtw_ampdu_amsdu, int, 0644);
-module_param(rtw_power_mgnt, int, 0644);
-module_param(rtw_smart_ps, int, 0644);
-module_param(rtw_wifi_spec, int, 0644);
-module_param(rtw_antdiv_cfg, int, 0644);
-module_param(rtw_antdiv_type, int, 0644);
-module_param(rtw_enusbss, int, 0644);
-module_param(rtw_hwpdn_mode, int, 0644);
-
-static uint rtw_max_roaming_times = 2;
-module_param(rtw_max_roaming_times, uint, 0644);
-MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try");
-
-static int rtw_fw_iol = 1;/* 0:Disable, 1:enable, 2:by usb speed */
-module_param(rtw_fw_iol, int, 0644);
-MODULE_PARM_DESC(rtw_fw_iol, "FW IOL");
-
-module_param(rtw_mc2u_disable, int, 0644);
-
-module_param(rtw_80211d, int, 0644);
-MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism");
-
-static uint rtw_notch_filter = RTW_NOTCH_FILTER;
-module_param(rtw_notch_filter, uint, 0644);
-MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P");
-module_param_named(debug, rtw_debug, int, 0444);
-MODULE_PARM_DESC(debug, "Set debug level (1-9) (default 1)");
-
-static bool rtw_monitor_enable;
-module_param_named(monitor_enable, rtw_monitor_enable, bool, 0444);
-MODULE_PARM_DESC(monitor_enable, "Enable monitor interface (default: false)");
-
-static int netdev_close(struct net_device *pnetdev);
-
-static void loadparam(struct adapter *padapter)
-{
- struct registry_priv *registry_par = &padapter->registrypriv;
-
- memcpy(registry_par->ssid.ssid, "ANY", 3);
- registry_par->ssid.ssid_length = 3;
-
- registry_par->channel = (u8)rtw_channel;
- registry_par->wireless_mode = (u8)rtw_wireless_mode;
- registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense;
- registry_par->vcs_type = (u8)rtw_vcs_type;
- registry_par->rts_thresh = (u16)rtw_rts_thresh;
- registry_par->frag_thresh = (u16)rtw_frag_thresh;
- registry_par->preamble = (u8)rtw_preamble;
- registry_par->smart_ps = (u8)rtw_smart_ps;
- registry_par->power_mgnt = (u8)rtw_power_mgnt;
- registry_par->ips_mode = (u8)rtw_ips_mode;
- registry_par->mp_mode = 0;
- registry_par->acm_method = (u8)rtw_acm_method;
-
- /* UAPSD */
- registry_par->wmm_enable = (u8)rtw_wmm_enable;
- registry_par->uapsd_enable = (u8)rtw_uapsd_enable;
-
- registry_par->ht_enable = (u8)rtw_ht_enable;
- registry_par->cbw40_enable = (u8)rtw_cbw40_enable;
- registry_par->ampdu_enable = (u8)rtw_ampdu_enable;
- registry_par->rx_stbc = (u8)rtw_rx_stbc;
- registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu;
- registry_par->wifi_spec = (u8)rtw_wifi_spec;
- registry_par->channel_plan = (u8)rtw_channel_plan;
- registry_par->accept_addba_req = true;
- registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg;
- registry_par->antdiv_type = (u8)rtw_antdiv_type;
- registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;
-
- registry_par->max_roaming_times = (u8)rtw_max_roaming_times;
-
- registry_par->fw_iol = rtw_fw_iol;
-
- registry_par->enable80211d = (u8)rtw_80211d;
- snprintf(registry_par->ifname, 16, "%s", ifname);
- snprintf(registry_par->if2name, 16, "%s", if2name);
- registry_par->notch_filter = (u8)rtw_notch_filter;
- registry_par->monitor_enable = rtw_monitor_enable;
-}
-
-static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p)
-{
- struct adapter *padapter = netdev_priv(pnetdev);
- struct sockaddr *addr = p;
-
- if (!padapter->bup)
- memcpy(padapter->eeprompriv.mac_addr, addr->sa_data, ETH_ALEN);
-
- return 0;
-}
-
-static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev)
-{
- struct adapter *padapter = netdev_priv(pnetdev);
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- padapter->stats.tx_packets = pxmitpriv->tx_pkts;
- padapter->stats.rx_packets = precvpriv->rx_pkts;
- padapter->stats.tx_dropped = pxmitpriv->tx_drop;
- padapter->stats.rx_dropped = precvpriv->rx_drop;
- padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
- padapter->stats.rx_bytes = precvpriv->rx_bytes;
- return &padapter->stats;
-}
-
-/*
- * AC to queue mapping
- *
- * AC_VO -> queue 0
- * AC_VI -> queue 1
- * AC_BE -> queue 2
- * AC_BK -> queue 3
- */
-static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
-
-/* Given a data frame determine the 802.1p/1d tag to use. */
-static unsigned int rtw_classify8021d(struct sk_buff *skb)
-{
- unsigned int dscp;
-
- /* skb->priority values from 256->263 are magic values to
- * directly indicate a specific 802.1d priority. This is used
- * to allow 802.1d priority to be passed directly in from VLAN
- * tags, etc.
- */
- if (skb->priority >= 256 && skb->priority <= 263)
- return skb->priority - 256;
-
- switch (skb->protocol) {
- case htons(ETH_P_IP):
- dscp = ip_hdr(skb)->tos & 0xfc;
- break;
- default:
- return 0;
- }
-
- return dscp >> 5;
-}
-
-static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
- struct net_device *sb_dev)
-{
- struct adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- skb->priority = rtw_classify8021d(skb);
-
- if (pmlmepriv->acm_mask != 0)
- skb->priority = qos_acm(pmlmepriv->acm_mask, skb->priority);
-
- return rtw_1d_to_queue[skb->priority];
-}
-
-u16 rtw_recv_select_queue(struct sk_buff *skb)
-{
- struct iphdr *piphdr;
- unsigned int dscp;
- __be16 eth_type;
- u32 priority;
- u8 *pdata = skb->data;
-
- memcpy(&eth_type, pdata + (ETH_ALEN << 1), 2);
-
- switch (eth_type) {
- case htons(ETH_P_IP):
- piphdr = (struct iphdr *)(pdata + ETH_HLEN);
- dscp = piphdr->tos & 0xfc;
- priority = dscp >> 5;
- break;
- default:
- priority = 0;
- }
-
- return rtw_1d_to_queue[priority];
-}
-
-static const struct net_device_ops rtw_netdev_ops = {
- .ndo_open = netdev_open,
- .ndo_stop = netdev_close,
- .ndo_start_xmit = rtw_xmit_entry,
- .ndo_select_queue = rtw_select_queue,
- .ndo_set_mac_address = rtw_net_set_mac_address,
- .ndo_get_stats = rtw_net_get_stats,
- .ndo_do_ioctl = rtw_ioctl,
- .ndo_siocdevprivate = rtw_android_priv_cmd,
-};
-
-static const struct device_type wlan_type = {
- .name = "wlan",
-};
-
-struct net_device *rtw_init_netdev(void)
-{
- struct adapter *padapter;
- struct net_device *pnetdev;
-
- pnetdev = alloc_etherdev_mq(sizeof(struct adapter), 4);
- if (!pnetdev)
- return NULL;
-
- pnetdev->dev.type = &wlan_type;
- padapter = netdev_priv(pnetdev);
- padapter->pnetdev = pnetdev;
- pnetdev->netdev_ops = &rtw_netdev_ops;
- pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */
- pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def;
-
- loadparam(padapter);
- padapter->cmdThread = NULL;
-
- return pnetdev;
-}
-
-static int rtw_start_drv_threads(struct adapter *padapter)
-{
- int err = 0;
-
- padapter->cmdThread = kthread_run(rtw_cmd_thread, padapter, "RTW_CMD_THREAD");
- if (IS_ERR(padapter->cmdThread)) {
- err = PTR_ERR(padapter->cmdThread);
- padapter->cmdThread = NULL;
- }
-
- return err;
-}
-
-void rtw_stop_drv_threads(struct adapter *padapter)
-{
- if (!padapter->cmdThread)
- return;
-
- complete(&padapter->cmdpriv.cmd_queue_comp);
- kthread_stop(padapter->cmdThread);
-}
-
-static u8 rtw_init_default_value(struct adapter *padapter)
-{
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- /* xmit_priv */
- pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
- pxmitpriv->vcs = pregistrypriv->vcs_type;
- pxmitpriv->vcs_type = pregistrypriv->vcs_type;
- pxmitpriv->frag_len = pregistrypriv->frag_thresh;
-
- /* mlme_priv */
- pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
- pmlmepriv->scan_mode = SCAN_ACTIVE;
-
- /* ht_priv */
- pmlmepriv->htpriv.ampdu_enable = false;/* set to disabled */
-
- /* security_priv */
- psecuritypriv->binstallGrpkey = _FAIL;
- psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
- psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
- psecuritypriv->dot11PrivacyKeyIndex = 0;
- psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
- psecuritypriv->dot118021XGrpKeyid = 1;
- psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
- psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled;
-
- /* registry_priv */
- rtw_init_registrypriv_dev_network(padapter);
- rtw_update_registrypriv_dev_network(padapter);
-
- /* hal_priv */
- rtw_hal_def_value_init(padapter);
-
- /* misc. */
- padapter->bReadPortCancel = false;
- padapter->bWritePortCancel = false;
- return _SUCCESS;
-}
-
-u8 rtw_reset_drv_sw(struct adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
-
- /* hal_priv */
- rtw_hal_def_value_init(padapter);
- padapter->bReadPortCancel = false;
- padapter->bWritePortCancel = false;
- pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
-
- padapter->xmitpriv.tx_pkts = 0;
- padapter->recvpriv.rx_pkts = 0;
-
- pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
-
- _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING);
- rtw_hal_sreset_init(padapter);
- pwrctrlpriv->pwr_state_check_cnts = 0;
-
- /* mlmeextpriv */
- padapter->mlmeextpriv.sitesurvey_res.state = SCAN_DISABLE;
-
- rtw_set_signal_stat_timer(&padapter->recvpriv);
-
- return _SUCCESS;
-}
-
-u8 rtw_init_drv_sw(struct adapter *padapter)
-{
- u8 ret8 = _SUCCESS;
-
- rtw_init_cmd_priv(&padapter->cmdpriv);
-
- if (rtw_init_mlme_priv(padapter) == _FAIL) {
- ret8 = _FAIL;
- goto exit;
- }
-
- if (init_mlme_ext_priv(padapter) == _FAIL) {
- ret8 = _FAIL;
- goto exit;
- }
-
- if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) {
- ret8 = _FAIL;
- goto exit;
- }
-
- if (_rtw_init_recv_priv(&padapter->recvpriv, padapter) == _FAIL) {
- ret8 = _FAIL;
- goto exit;
- }
-
- if (_rtw_init_sta_priv(&padapter->stapriv) == _FAIL) {
- ret8 = _FAIL;
- goto exit;
- }
-
- padapter->stapriv.padapter = padapter;
-
- rtw_init_bcmc_stainfo(padapter);
-
- rtw_init_pwrctrl_priv(padapter);
-
- ret8 = rtw_init_default_value(padapter);
-
- rtw_hal_dm_init(padapter);
- rtw_hal_sw_led_init(padapter);
-
- rtw_hal_sreset_init(padapter);
-
-exit:
- return ret8;
-}
-
-void rtw_cancel_all_timer(struct adapter *padapter)
-{
- del_timer_sync(&padapter->mlmepriv.assoc_timer);
-
- del_timer_sync(&padapter->mlmepriv.scan_to_timer);
-
- del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer);
-
- /* cancel sw led timer */
- rtw_hal_sw_led_deinit(padapter);
-
- del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer);
-
- del_timer_sync(&padapter->recvpriv.signal_stat_timer);
-}
-
-u8 rtw_free_drv_sw(struct adapter *padapter)
-{
- free_mlme_ext_priv(&padapter->mlmeextpriv);
-
- rtw_free_mlme_priv(&padapter->mlmepriv);
- _rtw_free_xmit_priv(&padapter->xmitpriv);
-
- /* will free bcmc_stainfo here */
- _rtw_free_sta_priv(&padapter->stapriv);
-
- _rtw_free_recv_priv(&padapter->recvpriv);
-
- rtw_hal_free_data(padapter);
-
- mutex_destroy(&padapter->hw_init_mutex);
-
- return _SUCCESS;
-}
-
-static int _netdev_open(struct net_device *pnetdev)
-{
- uint status;
- int err;
- struct adapter *padapter = netdev_priv(pnetdev);
- struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
-
- if (pwrctrlpriv->ps_flag) {
- padapter->net_closed = false;
- goto netdev_open_normal_process;
- }
-
- if (!padapter->bup) {
- padapter->bDriverStopped = false;
- padapter->bSurpriseRemoved = false;
-
- status = rtw_hal_init(padapter);
- if (status == _FAIL)
- goto netdev_open_error;
-
- pr_info("MAC Address = %pM\n", pnetdev->dev_addr);
-
- err = rtw_start_drv_threads(padapter);
- if (err) {
- pr_info("Initialize driver software resource Failed!\n");
- goto netdev_open_error;
- }
-
- if (init_hw_mlme_ext(padapter) == _FAIL) {
- pr_info("can't init mlme_ext_priv\n");
- goto netdev_open_error;
- }
- rtw_hal_inirp_init(padapter);
-
- led_control_8188eu(padapter, LED_CTL_NO_LINK);
-
- padapter->bup = true;
- }
- padapter->net_closed = false;
-
- mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
- jiffies + msecs_to_jiffies(2000));
-
- padapter->pwrctrlpriv.bips_processing = false;
- rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
-
- if (!rtw_netif_queue_stopped(pnetdev))
- netif_tx_start_all_queues(pnetdev);
- else
- netif_tx_wake_all_queues(pnetdev);
-
-netdev_open_normal_process:
- return 0;
-
-netdev_open_error:
- padapter->bup = false;
- netif_carrier_off(pnetdev);
- netif_tx_stop_all_queues(pnetdev);
- return -1;
-}
-
-int netdev_open(struct net_device *pnetdev)
-{
- int ret;
- struct adapter *padapter = netdev_priv(pnetdev);
-
- if (mutex_lock_interruptible(&padapter->hw_init_mutex))
- return -ERESTARTSYS;
- ret = _netdev_open(pnetdev);
- mutex_unlock(&padapter->hw_init_mutex);
- return ret;
-}
-
-int ips_netdrv_open(struct adapter *padapter)
-{
- int status = _SUCCESS;
-
- padapter->net_closed = false;
-
- padapter->bDriverStopped = false;
- padapter->bSurpriseRemoved = false;
-
- status = rtw_hal_init(padapter);
- if (status == _FAIL)
- goto netdev_open_error;
-
- rtw_hal_inirp_init(padapter);
-
- rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
- mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
- jiffies + msecs_to_jiffies(5000));
-
- return _SUCCESS;
-
-netdev_open_error:
- return _FAIL;
-}
-
-int rtw_ips_pwr_up(struct adapter *padapter)
-{
- int result;
-
- rtw_reset_drv_sw(padapter);
-
- result = ips_netdrv_open(padapter);
-
- led_control_8188eu(padapter, LED_CTL_NO_LINK);
-
- return result;
-}
-
-void rtw_ips_pwr_down(struct adapter *padapter)
-{
- padapter->net_closed = true;
-
- led_control_8188eu(padapter, LED_CTL_POWER_OFF);
-
- rtw_ips_dev_unload(padapter);
-}
-
-void rtw_ips_dev_unload(struct adapter *padapter)
-{
- rtw_hal_set_hwreg(padapter, HW_VAR_FIFO_CLEARN_UP, NULL);
-
- usb_intf_stop(padapter);
-
- /* s5. */
- if (!padapter->bSurpriseRemoved)
- rtw_hal_deinit(padapter);
-}
-
-static int netdev_close(struct net_device *pnetdev)
-{
- struct adapter *padapter = netdev_priv(pnetdev);
-
- if (padapter->pwrctrlpriv.bInternalAutoSuspend) {
- if (padapter->pwrctrlpriv.rf_pwrstate == rf_off)
- padapter->pwrctrlpriv.ps_flag = true;
- }
- padapter->net_closed = true;
-
- if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) {
- /* s1. */
- if (pnetdev) {
- if (!rtw_netif_queue_stopped(pnetdev))
- netif_tx_stop_all_queues(pnetdev);
- }
-
- /* s2. */
- LeaveAllPowerSaveMode(padapter);
- rtw_disassoc_cmd(padapter, 500, false);
- /* s2-2. indicate disconnect to os */
- rtw_indicate_disconnect(padapter);
- /* s2-3. */
- rtw_free_assoc_resources(padapter);
- /* s2-4. */
- rtw_free_network_queue(padapter, true);
- /* Close LED */
- led_control_8188eu(padapter, LED_CTL_POWER_OFF);
- }
-
- return 0;
-}
diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
deleted file mode 100644
index 57453df0ced8..000000000000
--- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _OSDEP_SERVICE_C_
-
-#include <osdep_service.h>
-#include <osdep_intf.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <linux/vmalloc.h>
-#include <rtw_ioctl_set.h>
-
-u8 *_rtw_malloc(u32 sz)
-{
- return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-}
-
-void _rtw_init_queue(struct __queue *pqueue)
-{
- INIT_LIST_HEAD(&pqueue->queue);
- spin_lock_init(&pqueue->lock);
-}
-
-void rtw_buf_free(u8 **buf, u32 *buf_len)
-{
- *buf_len = 0;
- kfree(*buf);
- *buf = NULL;
-}
-
-void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
-{
- u32 dup_len = 0;
- u8 *ori = NULL;
- u8 *dup = NULL;
-
- if (!buf || !buf_len)
- return;
-
- if (!src || !src_len)
- goto keep_ori;
-
- /* duplicate src */
- dup = rtw_malloc(src_len);
- if (dup) {
- dup_len = src_len;
- memcpy(dup, src, dup_len);
- }
-
-keep_ori:
- ori = *buf;
-
- /* replace buf with dup */
- *buf_len = 0;
- *buf = dup;
- *buf_len = dup_len;
-
- /* free ori */
- kfree(ori);
-}
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
deleted file mode 100644
index a13df3880378..000000000000
--- a/drivers/staging/rtl8188eu/os_dep/rtw_android.c
+++ /dev/null
@@ -1,231 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include <linux/compat.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-
-#include <rtw_android.h>
-#include <osdep_service.h>
-#include <rtw_ioctl_set.h>
-
-static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
- "START",
- "STOP",
- "SCAN-ACTIVE",
- "SCAN-PASSIVE",
- "RSSI",
- "LINKSPEED",
- "RXFILTER-START",
- "RXFILTER-STOP",
- "RXFILTER-ADD",
- "RXFILTER-REMOVE",
- "BTCOEXSCAN-START",
- "BTCOEXSCAN-STOP",
- "BTCOEXMODE",
- "SETSUSPENDOPT",
- "P2P_DEV_ADDR",
- "SETFWPATH",
- "SETBAND",
- "GETBAND",
- "COUNTRY",
- "P2P_SET_NOA",
- "P2P_GET_NOA",
- "P2P_SET_PS",
- "SET_AP_WPS_P2P_IE",
- "MACADDR",
- "BLOCK",
- "WFD-ENABLE",
- "WFD-DISABLE",
- "WFD-SET-TCPPORT",
- "WFD-SET-MAXTPUT",
- "WFD-SET-DEVTYPE",
-};
-
-struct android_wifi_priv_cmd {
- const char __user *buf;
- int used_len;
- int total_len;
-};
-
-static int rtw_android_cmdstr_to_num(char *cmdstr)
-{
- int cmd_num;
-
- for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
- if (!strncasecmp(cmdstr, android_wifi_cmd_str[cmd_num],
- strlen(android_wifi_cmd_str[cmd_num])))
- break;
- return cmd_num;
-}
-
-static int rtw_android_get_rssi(struct net_device *net, char *command,
- int total_len)
-{
- struct adapter *padapter = netdev_priv(net);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *pcur_network = &pmlmepriv->cur_network;
- int bytes_written = 0;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- bytes_written += snprintf(&command[bytes_written], total_len,
- "%s rssi %d",
- pcur_network->network.ssid.ssid,
- padapter->recvpriv.rssi);
- }
- return bytes_written;
-}
-
-static int rtw_android_get_link_speed(struct net_device *net, char *command,
- int total_len)
-{
- struct adapter *padapter = netdev_priv(net);
- u16 link_speed;
-
- link_speed = rtw_get_cur_max_rate(padapter) / 10;
- return snprintf(command, total_len, "LinkSpeed %d",
- link_speed);
-}
-
-static int rtw_android_get_macaddr(struct net_device *net, char *command,
- int total_len)
-{
- return snprintf(command, total_len, "Macaddr = %pM",
- net->dev_addr);
-}
-
-static int android_set_cntry(struct net_device *net, char *command,
- int total_len)
-{
- struct adapter *adapter = netdev_priv(net);
- char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
- int ret;
-
- ret = rtw_set_country(adapter, country_code);
- return (ret == _SUCCESS) ? 0 : -1;
-}
-
-static int android_get_p2p_addr(struct net_device *net, char *command,
- int total_len)
-{
- /* We use the same address as our HW MAC address */
- memcpy(command, net->dev_addr, ETH_ALEN);
- return ETH_ALEN;
-}
-
-int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr,
- void __user *data, int cmd)
-{
- int ret = 0;
- char *command;
- int cmd_num;
- int bytes_written = 0;
- struct android_wifi_priv_cmd priv_cmd;
-
- if (cmd != SIOCDEVPRIVATE)
- return -EOPNOTSUPP;
-
- if (in_compat_syscall()) /* to be implemented */
- return -EOPNOTSUPP;
-
- if (!data)
- return -EINVAL;
- if (copy_from_user(&priv_cmd, data, sizeof(priv_cmd)))
- return -EFAULT;
- if (priv_cmd.total_len < 1)
- return -EINVAL;
- command = memdup_user(priv_cmd.buf, priv_cmd.total_len);
- if (IS_ERR(command))
- return PTR_ERR(command);
- command[priv_cmd.total_len - 1] = 0;
- cmd_num = rtw_android_cmdstr_to_num(command);
- switch (cmd_num) {
- case ANDROID_WIFI_CMD_START:
- goto response;
- case ANDROID_WIFI_CMD_SETFWPATH:
- goto response;
- }
- switch (cmd_num) {
- case ANDROID_WIFI_CMD_STOP:
- break;
- case ANDROID_WIFI_CMD_SCAN_ACTIVE:
- break;
- case ANDROID_WIFI_CMD_SCAN_PASSIVE:
- break;
- case ANDROID_WIFI_CMD_RSSI:
- bytes_written = rtw_android_get_rssi(net, command,
- priv_cmd.total_len);
- break;
- case ANDROID_WIFI_CMD_LINKSPEED:
- bytes_written = rtw_android_get_link_speed(net, command,
- priv_cmd.total_len);
- break;
- case ANDROID_WIFI_CMD_MACADDR:
- bytes_written = rtw_android_get_macaddr(net, command,
- priv_cmd.total_len);
- break;
- case ANDROID_WIFI_CMD_BLOCK:
- break;
- case ANDROID_WIFI_CMD_RXFILTER_START:
- break;
- case ANDROID_WIFI_CMD_RXFILTER_STOP:
- break;
- case ANDROID_WIFI_CMD_RXFILTER_ADD:
- break;
- case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
- break;
- case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
- /* TBD: BTCOEXSCAN-START */
- break;
- case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
- /* TBD: BTCOEXSCAN-STOP */
- break;
- case ANDROID_WIFI_CMD_BTCOEXMODE:
- break;
- case ANDROID_WIFI_CMD_SETSUSPENDOPT:
- break;
- case ANDROID_WIFI_CMD_SETBAND:
- break;
- case ANDROID_WIFI_CMD_GETBAND:
- break;
- case ANDROID_WIFI_CMD_COUNTRY:
- bytes_written = android_set_cntry(net, command,
- priv_cmd.total_len);
- break;
- case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
- bytes_written = android_get_p2p_addr(net, command,
- priv_cmd.total_len);
- break;
- case ANDROID_WIFI_CMD_P2P_SET_NOA:
- break;
- case ANDROID_WIFI_CMD_P2P_GET_NOA:
- break;
- case ANDROID_WIFI_CMD_P2P_SET_PS:
- break;
- default:
- snprintf(command, 3, "OK");
- bytes_written = strlen("OK");
- }
-
-response:
- if (bytes_written >= 0) {
- if ((bytes_written == 0) && (priv_cmd.total_len > 0))
- command[0] = '\0';
- if (bytes_written >= priv_cmd.total_len)
- bytes_written = priv_cmd.total_len;
- else
- bytes_written++;
- priv_cmd.used_len = bytes_written;
- if (copy_to_user((char __user *)priv_cmd.buf, command,
- bytes_written))
- ret = -EFAULT;
- } else {
- ret = bytes_written;
- }
- kfree(command);
- return ret;
-}
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
deleted file mode 100644
index b7e2692c35f3..000000000000
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ /dev/null
@@ -1,485 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#define pr_fmt(fmt) "R8188EU: " fmt
-#include <osdep_service.h>
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <xmit_osdep.h>
-#include <hal_intf.h>
-#include <linux/usb.h>
-#include <linux/vmalloc.h>
-#include <mon.h>
-#include <osdep_intf.h>
-
-#include <usb_ops_linux.h>
-#include <rtw_ioctl.h>
-
-#include "rtl8188e_hal.h"
-
-#define USB_VENDER_ID_REALTEK 0x0bda
-
-/* DID_USB_v916_20130116 */
-static const struct usb_device_id rtw_usb_id_tbl[] = {
- /*=== Realtek demoboard ===*/
- {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179)}, /* 8188EUS */
- {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */
- /*=== Customer ID ===*/
- /****** 8188EUS ********/
- {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */
- {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
- {USB_DEVICE(0x0B05, 0x18F0)}, /* ASUS USB-N10 Nano B1 */
- {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
- {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
- {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
- {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
- {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
- {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */
- {USB_DEVICE(0x2C4E, 0x0102)}, /* MERCUSYS MW150US v2 */
- {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
- {USB_DEVICE(0x7392, 0xb811)}, /* Edimax EW-7811UN V2 */
- {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
- {} /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
-
-static int usb_dvobj_init(struct usb_interface *usb_intf)
-{
- int i;
- struct dvobj_priv *pdvobjpriv;
- struct usb_host_config *phost_conf;
- struct usb_config_descriptor *pconf_desc;
- struct usb_host_interface *phost_iface;
- struct usb_interface_descriptor *piface_desc;
- struct usb_endpoint_descriptor *pendp_desc;
- struct usb_device *pusbd;
-
- pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
- if (!pdvobjpriv)
- return -ENOMEM;
-
- pdvobjpriv->pusbintf = usb_intf;
- pusbd = interface_to_usbdev(usb_intf);
- pdvobjpriv->pusbdev = pusbd;
- usb_set_intfdata(usb_intf, pdvobjpriv);
-
- pdvobjpriv->RtNumInPipes = 0;
- pdvobjpriv->RtNumOutPipes = 0;
-
- phost_conf = pusbd->actconfig;
- pconf_desc = &phost_conf->desc;
-
- phost_iface = usb_intf->cur_altsetting;
- piface_desc = &phost_iface->desc;
-
- pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
- pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
-
- for (i = 0; i < piface_desc->bNumEndpoints; i++) {
- int ep_num;
-
- pendp_desc = &phost_iface->endpoint[i].desc;
-
- ep_num = usb_endpoint_num(pendp_desc);
-
- if (usb_endpoint_is_bulk_in(pendp_desc)) {
- pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num;
- pdvobjpriv->RtNumInPipes++;
- } else if (usb_endpoint_is_int_in(pendp_desc)) {
- pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num;
- pdvobjpriv->RtNumInPipes++;
- } else if (usb_endpoint_is_bulk_out(pendp_desc)) {
- pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] =
- ep_num;
- pdvobjpriv->RtNumOutPipes++;
- }
- }
-
- if (pusbd->speed == USB_SPEED_HIGH)
- pdvobjpriv->ishighspeed = true;
- else
- pdvobjpriv->ishighspeed = false;
-
- mutex_init(&pdvobjpriv->usb_vendor_req_mutex);
- usb_get_dev(pusbd);
-
- return 0;
-}
-
-static void usb_dvobj_deinit(struct usb_interface *usb_intf)
-{
- struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
-
- usb_set_intfdata(usb_intf, NULL);
- if (dvobj) {
- /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
- if ((dvobj->NumInterfaces != 2 &&
- dvobj->NumInterfaces != 3) ||
- (dvobj->InterfaceNumber == 1)) {
- if (interface_to_usbdev(usb_intf)->state !=
- USB_STATE_NOTATTACHED) {
- /* If we didn't unplug usb dongle and
- * remove/insert module, driver fails
- * on sitesurvey for the first time when
- * device is up . Reset usb port for sitesurvey
- * fail issue.
- */
- pr_debug("usb attached..., try to reset usb device\n");
- usb_reset_device(interface_to_usbdev(usb_intf));
- }
- }
-
- mutex_destroy(&dvobj->usb_vendor_req_mutex);
- kfree(dvobj);
- }
-
- usb_put_dev(interface_to_usbdev(usb_intf));
-}
-
-void usb_intf_stop(struct adapter *padapter)
-{
- /* cancel in irp */
- rtw_hal_inirp_deinit(padapter);
-
- /* cancel out irp */
- usb_write_port_cancel(padapter);
-
- /* todo:cancel other irps */
-}
-
-static void rtw_dev_unload(struct adapter *padapter)
-{
- if (padapter->bup) {
- pr_debug("===> %s\n", __func__);
- padapter->bDriverStopped = true;
- if (padapter->xmitpriv.ack_tx)
- rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
- /* s3. */
- usb_intf_stop(padapter);
- /* s4. */
- if (!padapter->pwrctrlpriv.bInternalAutoSuspend)
- rtw_stop_drv_threads(padapter);
-
- /* s5. */
- if (!padapter->bSurpriseRemoved) {
- rtw_hal_deinit(padapter);
- padapter->bSurpriseRemoved = true;
- }
-
- padapter->bup = false;
- }
-
- pr_debug("<=== %s\n", __func__);
-}
-
-static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
-{
- struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
- struct adapter *padapter = dvobj->if1;
- struct net_device *pnetdev = padapter->pnetdev;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- unsigned long start_time = jiffies;
-
- pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
-
- if ((!padapter->bup) || (padapter->bDriverStopped) ||
- (padapter->bSurpriseRemoved)) {
- pr_debug("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
- padapter->bup, padapter->bDriverStopped,
- padapter->bSurpriseRemoved);
- goto exit;
- }
-
- pwrpriv->bInSuspend = true;
- rtw_cancel_all_timer(padapter);
- LeaveAllPowerSaveMode(padapter);
-
- mutex_lock(&pwrpriv->mutex_lock);
- /* s1. */
- if (pnetdev) {
- netif_carrier_off(pnetdev);
- netif_tx_stop_all_queues(pnetdev);
- }
-
- /* s2. */
- rtw_disassoc_cmd(padapter, 0, false);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- pr_debug("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
- __func__, __LINE__,
- pmlmepriv->cur_network.network.ssid.ssid,
- pmlmepriv->cur_network.network.MacAddress,
- pmlmepriv->cur_network.network.ssid.ssid_length,
- pmlmepriv->assoc_ssid.ssid_length);
-
- pmlmepriv->to_roaming = 1;
- }
- /* s2-2. indicate disconnect to os */
- rtw_indicate_disconnect(padapter);
- /* s2-3. */
- rtw_free_assoc_resources(padapter);
- /* s2-4. */
- rtw_free_network_queue(padapter, true);
-
- rtw_dev_unload(padapter);
- mutex_unlock(&pwrpriv->mutex_lock);
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- rtw_indicate_scan_done(padapter, 1);
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- rtw_indicate_disconnect(padapter);
-
-exit:
- pr_debug("<=== %s .............. in %dms\n", __func__,
- jiffies_to_msecs(jiffies - start_time));
-
- return 0;
-}
-
-static int rtw_resume_process(struct adapter *padapter)
-{
- struct net_device *pnetdev;
- struct pwrctrl_priv *pwrpriv = NULL;
- int ret = -1;
- unsigned long start_time = jiffies;
-
- pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
-
- if (padapter) {
- pnetdev = padapter->pnetdev;
- pwrpriv = &padapter->pwrctrlpriv;
- } else {
- goto exit;
- }
-
- mutex_lock(&pwrpriv->mutex_lock);
- rtw_reset_drv_sw(padapter);
- pwrpriv->bkeepfwalive = false;
-
- pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
- if (netdev_open(pnetdev) != 0) {
- mutex_unlock(&pwrpriv->mutex_lock);
- goto exit;
- }
-
- netif_device_attach(pnetdev);
- netif_carrier_on(pnetdev);
-
- mutex_unlock(&pwrpriv->mutex_lock);
-
- rtw_roaming(padapter, NULL);
-
- ret = 0;
-exit:
- if (pwrpriv)
- pwrpriv->bInSuspend = false;
- pr_debug("<=== %s return %d.............. in %dms\n", __func__,
- ret, jiffies_to_msecs(jiffies - start_time));
-
- return ret;
-}
-
-static int rtw_resume(struct usb_interface *pusb_intf)
-{
- struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
- struct adapter *padapter = dvobj->if1;
-
- return rtw_resume_process(padapter);
-}
-
-/*
- * drv_init() - a device potentially for us
- *
- * notes: drv_init() is called when the bus driver has located
- * a card for us to support.
- * We accept the new device by returning 0.
- */
-
-static int rtw_usb_if1_init(struct usb_interface *pusb_intf)
-{
- struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
- struct adapter *padapter;
- struct net_device *pnetdev;
- struct net_device *pmondev;
- int err = 0;
-
- pnetdev = rtw_init_netdev();
- if (!pnetdev)
- return -ENOMEM;
- SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
-
- padapter = netdev_priv(pnetdev);
- padapter->dvobj = dvobj;
- dvobj->if1 = padapter;
-
- padapter->bDriverStopped = true;
- mutex_init(&padapter->hw_init_mutex);
-
- if (padapter->registrypriv.monitor_enable) {
- pmondev = rtl88eu_mon_init();
- if (!pmondev)
- netdev_warn(pnetdev, "Failed to initialize monitor interface");
- padapter->pmondev = pmondev;
- }
-
- padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL);
- if (!padapter->HalData) {
- err = -ENOMEM;
- goto free_adapter;
- }
-
- /* step read_chip_version */
- rtw_hal_read_chip_version(padapter);
-
- /* step usb endpoint mapping */
- rtw_hal_chip_configure(padapter);
-
- /* step read efuse/eeprom data and get mac_addr */
- rtw_hal_read_chip_info(padapter);
-
- /* step 5. */
- if (rtw_init_drv_sw(padapter) == _FAIL) {
- err = -ENOMEM;
- goto free_hal_data;
- }
-
-#ifdef CONFIG_PM
- if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
- dvobj->pusbdev->do_remote_wakeup = 1;
- pusb_intf->needs_remote_wakeup = 1;
- device_init_wakeup(&pusb_intf->dev, 1);
- pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
- device_may_wakeup(&pusb_intf->dev));
- }
-#endif
-
- /* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto suspend influence */
- if (usb_autopm_get_interface(pusb_intf) < 0)
- pr_debug("can't get autopm:\n");
-
- /* alloc dev name after read efuse. */
- err = dev_alloc_name(pnetdev, padapter->registrypriv.ifname);
- if (err < 0)
- goto free_hal_data;
-
- netif_carrier_off(pnetdev);
-
- rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
- memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
- pr_debug("MAC Address from pnetdev->dev_addr = %pM\n",
- pnetdev->dev_addr);
-
- /* step 6. Tell the network stack we exist */
- err = register_netdev(pnetdev);
- if (err) {
- goto free_hal_data;
- }
-
- pr_debug("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
- , padapter->bDriverStopped
- , padapter->bSurpriseRemoved
- , padapter->bup
- , padapter->hw_init_completed
- );
-
- return 0;
-
-free_hal_data:
- kfree(padapter->HalData);
-free_adapter:
- free_netdev(pnetdev);
- return err;
-}
-
-static void rtw_usb_if1_deinit(struct adapter *if1)
-{
- struct net_device *pnetdev = if1->pnetdev;
- struct mlme_priv *pmlmepriv = &if1->mlmepriv;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- rtw_disassoc_cmd(if1, 0, false);
-
-#ifdef CONFIG_88EU_AP_MODE
- free_mlme_ap_info(if1);
-#endif
-
- if (pnetdev)
- unregister_netdev(pnetdev); /* will call netdev_close() */
-
- rtl88eu_mon_deinit(if1->pmondev);
- rtw_cancel_all_timer(if1);
-
- rtw_dev_unload(if1);
- pr_debug("+r871xu_dev_remove, hw_init_completed=%d\n",
- if1->hw_init_completed);
- rtw_free_drv_sw(if1);
- if (pnetdev)
- free_netdev(pnetdev);
-}
-
-static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
-{
- int err;
-
- err = usb_dvobj_init(pusb_intf);
- if (err) {
- pr_debug("usb_dvobj_init failed\n");
- return err;
- }
-
- err = rtw_usb_if1_init(pusb_intf);
- if (err) {
- pr_debug("rtw_usb_if1_init failed\n");
- usb_dvobj_deinit(pusb_intf);
- return err;
- }
-
- return 0;
-}
-
-/*
- * dev_remove() - our device is being removed
- *
- * rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both
- */
-static void rtw_dev_remove(struct usb_interface *pusb_intf)
-{
- struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
- struct adapter *padapter = dvobj->if1;
-
- pr_debug("+%s\n", __func__);
-
- if (!pusb_intf->unregistering)
- padapter->bSurpriseRemoved = true;
-
- rtw_pm_set_ips(padapter, IPS_NONE);
- rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
-
- LeaveAllPowerSaveMode(padapter);
-
- rtw_usb_if1_deinit(padapter);
-
- usb_dvobj_deinit(pusb_intf);
-
- pr_debug("-r871xu_dev_remove, done\n");
-}
-
-static struct usb_driver rtl8188e_usb_drv = {
- .name = "r8188eu",
- .probe = rtw_drv_init,
- .disconnect = rtw_dev_remove,
- .id_table = rtw_usb_id_tbl,
- .suspend = rtw_suspend,
- .resume = rtw_resume,
- .reset_resume = rtw_resume,
-};
-
-module_usb_driver(rtl8188e_usb_drv)
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
deleted file mode 100644
index 0ceb05f3884f..000000000000
--- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
+++ /dev/null
@@ -1,644 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#define _USB_OPS_LINUX_C_
-
-#include <drv_types.h>
-#include <recv_osdep.h>
-#include <rtw_sreset.h>
-
-#define RTW_USB_CONTROL_MSG_TIMEOUT 500 /* ms */
-
-#define MAX_USBCTRL_VENDORREQ_TIMES 10
-
-#define ALIGNMENT_UNIT 16
-#define MAX_VENDOR_REQ_CMD_SIZE 254
-#define MAX_USB_IO_CTL_SIZE (MAX_VENDOR_REQ_CMD_SIZE + ALIGNMENT_UNIT)
-
-#define REALTEK_USB_VENQT_READ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
-#define REALTEK_USB_VENQT_WRITE (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
-
-#define REALTEK_USB_VENQT_CMD_REQ 0x05
-#define REALTEK_USB_VENQT_CMD_IDX 0x00
-
-static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf)
-{
- struct hal_data_8188e *haldata = adapt->HalData;
-
- if (pkt_len != INTERRUPT_MSG_FORMAT_LEN)
- return;
-
- /* HISR */
- memcpy(&haldata->IntArray[0], &pbuf[USB_INTR_CONTENT_HISR_OFFSET], 4);
- memcpy(&haldata->IntArray[1], &pbuf[USB_INTR_CONTENT_HISRE_OFFSET], 4);
-
- /* C2H Event */
- if (pbuf[0] != 0)
- memcpy(&haldata->C2hArray[0],
- &pbuf[USB_INTR_CONTENT_C2H_OFFSET], 16);
-}
-
-static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
-{
- u8 *pbuf;
- u8 shift_sz = 0;
- u16 pkt_cnt;
- u32 pkt_offset, skb_len, alloc_sz;
- s32 transfer_len;
- struct recv_stat *prxstat;
- struct phy_stat *pphy_status = NULL;
- struct sk_buff *pkt_copy = NULL;
- struct recv_frame *precvframe = NULL;
- struct rx_pkt_attrib *pattrib = NULL;
- struct hal_data_8188e *haldata = adapt->HalData;
- struct recv_priv *precvpriv = &adapt->recvpriv;
- struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
-
- transfer_len = (s32)pskb->len;
- pbuf = pskb->data;
-
- prxstat = (struct recv_stat *)pbuf;
- pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
-
- do {
- prxstat = (struct recv_stat *)pbuf;
-
- precvframe = rtw_alloc_recvframe(pfree_recv_queue);
- if (!precvframe)
- goto _exit_recvbuf2recvframe;
-
- INIT_LIST_HEAD(&precvframe->list);
-
- update_recvframe_attrib_88e(precvframe, prxstat);
-
- pattrib = &precvframe->attrib;
-
- if ((pattrib->crc_err) || (pattrib->icv_err)) {
- rtw_free_recvframe(precvframe, pfree_recv_queue);
- goto _exit_recvbuf2recvframe;
- }
-
- if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX))
- pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
-
- pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
-
- if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
- rtw_free_recvframe(precvframe, pfree_recv_queue);
- goto _exit_recvbuf2recvframe;
- }
-
- /* Modified by Albert 20101213 */
- /* For 8 bytes IP header alignment. */
- if (pattrib->qos) /* Qos data, wireless lan header length is 26 */
- shift_sz = 6;
- else
- shift_sz = 0;
-
- skb_len = pattrib->pkt_len;
-
- /* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
- /* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
- if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
- if (skb_len <= 1650)
- alloc_sz = 1664;
- else
- alloc_sz = skb_len + 14;
- } else {
- alloc_sz = skb_len;
- /* 6 is for IP header 8 bytes alignment in QoS packet case. */
- /* 8 is for skb->data 4 bytes alignment. */
- alloc_sz += 14;
- }
-
- pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
- if (pkt_copy) {
- pkt_copy->dev = adapt->pnetdev;
- precvframe->pkt = pkt_copy;
- skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
- skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
- skb_put_data(pkt_copy, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
- } else {
- rtw_free_recvframe(precvframe, pfree_recv_queue);
- goto _exit_recvbuf2recvframe;
- }
-
- switch (haldata->UsbRxAggMode) {
- case USB_RX_AGG_DMA:
- case USB_RX_AGG_MIX:
- pkt_offset = (u16)round_up(pkt_offset, 128);
- break;
- case USB_RX_AGG_USB:
- pkt_offset = (u16)round_up(pkt_offset, 4);
- break;
- case USB_RX_AGG_DISABLE:
- default:
- break;
- }
- if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
- if (pattrib->physt)
- update_recvframe_phyinfo_88e(precvframe, pphy_status);
- rtw_recv_entry(precvframe);
- } else if (pattrib->pkt_rpt_type == TX_REPORT1) {
- /* CCX-TXRPT ack for xmit mgmt frames. */
- handle_txrpt_ccx_88e(adapt, precvframe->pkt->data);
- rtw_free_recvframe(precvframe, pfree_recv_queue);
- } else if (pattrib->pkt_rpt_type == TX_REPORT2) {
- ODM_RA_TxRPT2Handle_8188E(&haldata->odmpriv,
- precvframe->pkt->data,
- pattrib->pkt_len,
- pattrib->MacIDValidEntry[0],
- pattrib->MacIDValidEntry[1]);
- rtw_free_recvframe(precvframe, pfree_recv_queue);
- } else if (pattrib->pkt_rpt_type == HIS_REPORT) {
- interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->pkt->data);
- rtw_free_recvframe(precvframe, pfree_recv_queue);
- }
- pkt_cnt--;
- transfer_len -= pkt_offset;
- pbuf += pkt_offset;
- precvframe = NULL;
- pkt_copy = NULL;
-
- if (transfer_len > 0 && pkt_cnt == 0)
- pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
-
- } while ((transfer_len > 0) && (pkt_cnt > 0));
-
-_exit_recvbuf2recvframe:
-
- return _SUCCESS;
-}
-
-static unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
-{
- unsigned int pipe = 0, ep_num = 0;
- struct usb_device *pusbd = pdvobj->pusbdev;
-
- if (addr == RECV_BULK_IN_ADDR) {
- pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
- } else if (addr == RECV_INT_IN_ADDR) {
- pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
- } else if (addr < HW_QUEUE_ENTRY) {
- ep_num = pdvobj->Queue2Pipe[addr];
- pipe = usb_sndbulkpipe(pusbd, ep_num);
- }
-
- return pipe;
-}
-
-static int
-usbctrl_vendorreq(struct adapter *adapt, u16 value, void *pdata, u16 len, u8 reqtype)
-{
- struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt);
- struct usb_device *udev = dvobjpriv->pusbdev;
- unsigned int pipe;
- int status = 0;
- u8 *pIo_buf;
- int vendorreq_times = 0;
-
- if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) {
- status = -EPERM;
- goto exit;
- }
-
- if (len > MAX_VENDOR_REQ_CMD_SIZE) {
- status = -EINVAL;
- goto exit;
- }
-
- if (mutex_lock_interruptible(&dvobjpriv->usb_vendor_req_mutex)) {
- status = -ERESTARTSYS;
- goto exit;
- }
-
- /* Acquire IO memory for vendorreq */
- pIo_buf = kmalloc(MAX_USB_IO_CTL_SIZE, GFP_ATOMIC);
-
- if (!pIo_buf) {
- status = -ENOMEM;
- goto release_mutex;
- }
-
- if (reqtype == REALTEK_USB_VENQT_READ) {
- pipe = usb_rcvctrlpipe(udev, 0);
- } else if (reqtype == REALTEK_USB_VENQT_WRITE) {
- pipe = usb_sndctrlpipe(udev, 0);
- } else {
- status = -EINVAL;
- goto free_buf;
- }
-
- while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
- if (reqtype == REALTEK_USB_VENQT_READ)
- memset(pIo_buf, 0, len);
- else
- memcpy(pIo_buf, pdata, len);
-
- status = usb_control_msg(udev, pipe, REALTEK_USB_VENQT_CMD_REQ,
- reqtype, value, REALTEK_USB_VENQT_CMD_IDX,
- pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
-
- if (status == len) { /* Success this control transfer. */
- if (reqtype == REALTEK_USB_VENQT_READ)
- memcpy(pdata, pIo_buf, len);
- } else { /* error cases */
- if (status < 0) {
- if (status == -ESHUTDOWN || status == -ENODEV)
- adapt->bSurpriseRemoved = true;
- else
- adapt->HalData->srestpriv.wifi_error_status = USB_VEN_REQ_CMD_FAIL;
- } else { /* status != len && status >= 0 */
- if (status > 0) {
- if (reqtype == REALTEK_USB_VENQT_READ) {
- /* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
- memcpy(pdata, pIo_buf, len);
- }
- }
- }
- }
-
- /* firmware download is checksummed, don't retry */
- if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len)
- break;
- }
-
-free_buf:
- kfree(pIo_buf);
-release_mutex:
- mutex_unlock(&dvobjpriv->usb_vendor_req_mutex);
-exit:
- return status;
-}
-
-u8 usb_read8(struct adapter *adapter, u32 addr)
-{
- u16 wvalue = (u16)(addr & 0xffff);
- u8 data;
-
- usbctrl_vendorreq(adapter, wvalue, &data, 1, REALTEK_USB_VENQT_READ);
-
- return data;
-}
-
-u16 usb_read16(struct adapter *adapter, u32 addr)
-{
- u16 wvalue = (u16)(addr & 0xffff);
- __le32 data;
-
- usbctrl_vendorreq(adapter, wvalue, &data, 2, REALTEK_USB_VENQT_READ);
-
- return (u16)(le32_to_cpu(data) & 0xffff);
-}
-
-u32 usb_read32(struct adapter *adapter, u32 addr)
-{
- u16 wvalue = (u16)(addr & 0xffff);
- __le32 data;
-
- usbctrl_vendorreq(adapter, wvalue, &data, 4, REALTEK_USB_VENQT_READ);
-
- return le32_to_cpu(data);
-}
-
-static void usb_read_port_complete(struct urb *purb)
-{
- struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
- struct adapter *adapt = (struct adapter *)precvbuf->adapter;
- struct recv_priv *precvpriv = &adapt->recvpriv;
-
- if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) {
- precvbuf->reuse = true;
- return;
- }
-
- if (purb->status == 0) { /* SUCCESS */
- if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
- precvbuf->reuse = true;
- usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
- } else {
- skb_put(precvbuf->pskb, purb->actual_length);
- skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
-
- if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
- tasklet_schedule(&precvpriv->recv_tasklet);
-
- precvbuf->pskb = NULL;
- precvbuf->reuse = false;
- usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
- }
- } else {
- skb_put(precvbuf->pskb, purb->actual_length);
- precvbuf->pskb = NULL;
-
- switch (purb->status) {
- case -EINVAL:
- case -EPIPE:
- case -ENODEV:
- case -ESHUTDOWN:
- adapt->bSurpriseRemoved = true;
- fallthrough;
- case -ENOENT:
- adapt->bDriverStopped = true;
- break;
- case -EPROTO:
- case -EOVERFLOW:
- adapt->HalData->srestpriv.wifi_error_status = USB_READ_PORT_FAIL;
- precvbuf->reuse = true;
- usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
- break;
- case -EINPROGRESS:
- break;
- default:
- break;
- }
- }
-}
-
-u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf)
-{
- struct urb *purb = NULL;
- struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
- struct recv_priv *precvpriv = &adapter->recvpriv;
- struct usb_device *pusbd = pdvobj->pusbdev;
- int err;
- unsigned int pipe;
-
- if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
- adapter->pwrctrlpriv.pnp_bstop_trx) {
- return _FAIL;
- }
-
- if (!precvbuf)
- return _FAIL;
-
- if (!precvbuf->reuse || !precvbuf->pskb) {
- precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
- if (precvbuf->pskb)
- precvbuf->reuse = true;
- }
-
- /* re-assign for linux based on skb */
- if (!precvbuf->reuse || !precvbuf->pskb) {
- precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ);
- if (!precvbuf->pskb)
- return _FAIL;
- } else { /* reuse skb */
- precvbuf->reuse = false;
- }
-
- purb = precvbuf->purb;
-
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
-
- usb_fill_bulk_urb(purb, pusbd, pipe,
- precvbuf->pskb->data,
- MAX_RECVBUF_SZ,
- usb_read_port_complete,
- precvbuf);/* context is precvbuf */
-
- err = usb_submit_urb(purb, GFP_ATOMIC);
- if (err)
- return _FAIL;
-
- return _SUCCESS;
-}
-
-void rtw_hal_inirp_deinit(struct adapter *padapter)
-{
- int i;
- struct recv_buf *precvbuf;
-
- precvbuf = padapter->recvpriv.precv_buf;
-
- padapter->bReadPortCancel = true;
-
- for (i = 0; i < NR_RECVBUFF; i++) {
- precvbuf->reuse = true;
- if (precvbuf->purb)
- usb_kill_urb(precvbuf->purb);
- precvbuf++;
- }
-}
-
-int usb_write8(struct adapter *adapter, u32 addr, u8 val)
-{
- u16 wvalue = (u16)(addr & 0xffff);
- u8 data = val;
-
- return usbctrl_vendorreq(adapter, wvalue, &data, 1, REALTEK_USB_VENQT_WRITE);
-}
-
-int usb_write16(struct adapter *adapter, u32 addr, u16 val)
-{
- u16 wvalue = (u16)(addr & 0xffff);
- __le32 data = cpu_to_le32(val & 0xffff);
-
- return usbctrl_vendorreq(adapter, wvalue, &data, 2, REALTEK_USB_VENQT_WRITE);
-}
-
-int usb_write32(struct adapter *adapter, u32 addr, u32 val)
-{
- u16 wvalue = (u16)(addr & 0xffff);
- __le32 data = cpu_to_le32(val);
-
- return usbctrl_vendorreq(adapter, wvalue, &data, 4, REALTEK_USB_VENQT_WRITE);
-}
-
-static void usb_write_port_complete(struct urb *purb)
-{
- struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
- struct adapter *padapter = pxmitbuf->padapter;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- switch (pxmitbuf->flags) {
- case VO_QUEUE_INX:
- pxmitpriv->voq_cnt--;
- break;
- case VI_QUEUE_INX:
- pxmitpriv->viq_cnt--;
- break;
- case BE_QUEUE_INX:
- pxmitpriv->beq_cnt--;
- break;
- case BK_QUEUE_INX:
- pxmitpriv->bkq_cnt--;
- break;
- case HIGH_QUEUE_INX:
-#ifdef CONFIG_88EU_AP_MODE
- rtw_chk_hi_queue_cmd(padapter);
-#endif
- break;
- default:
- break;
- }
-
- if (padapter->bSurpriseRemoved || padapter->bDriverStopped || padapter->bWritePortCancel)
- goto check_completion;
-
- if (purb->status) {
- if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
- sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
- } else if (purb->status == -EINPROGRESS) {
- goto check_completion;
- } else if (purb->status == -ENOENT) {
- goto check_completion;
- } else if (purb->status == -ECONNRESET) {
- goto check_completion;
- } else if (purb->status == -ESHUTDOWN) {
- padapter->bDriverStopped = true;
- goto check_completion;
- } else {
- padapter->bSurpriseRemoved = true;
- goto check_completion;
- }
- }
-
-check_completion:
- rtw_sctx_done_err(&pxmitbuf->sctx,
- purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
- RTW_SCTX_DONE_SUCCESS);
-
- rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
-
- tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
-}
-
-u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, struct xmit_buf *xmitbuf)
-{
- unsigned long irqL;
- unsigned int pipe;
- int status;
- u32 ret = _FAIL;
- struct urb *purb = NULL;
- struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct xmit_frame *pxmitframe = (struct xmit_frame *)xmitbuf->priv_data;
- struct usb_device *pusbd = pdvobj->pusbdev;
-
- if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
- (padapter->pwrctrlpriv.pnp_bstop_trx)) {
- rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
- goto exit;
- }
-
- spin_lock_irqsave(&pxmitpriv->lock, irqL);
-
- switch (addr) {
- case VO_QUEUE_INX:
- pxmitpriv->voq_cnt++;
- xmitbuf->flags = VO_QUEUE_INX;
- break;
- case VI_QUEUE_INX:
- pxmitpriv->viq_cnt++;
- xmitbuf->flags = VI_QUEUE_INX;
- break;
- case BE_QUEUE_INX:
- pxmitpriv->beq_cnt++;
- xmitbuf->flags = BE_QUEUE_INX;
- break;
- case BK_QUEUE_INX:
- pxmitpriv->bkq_cnt++;
- xmitbuf->flags = BK_QUEUE_INX;
- break;
- case HIGH_QUEUE_INX:
- xmitbuf->flags = HIGH_QUEUE_INX;
- break;
- default:
- xmitbuf->flags = MGT_QUEUE_INX;
- break;
- }
-
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
-
- purb = xmitbuf->pxmit_urb[0];
-
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
-
- usb_fill_bulk_urb(purb, pusbd, pipe,
- pxmitframe->buf_addr, /* xmitbuf->pbuf */
- cnt,
- usb_write_port_complete,
- xmitbuf);/* context is xmitbuf */
-
- status = usb_submit_urb(purb, GFP_ATOMIC);
- if (status) {
- rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
- if (status == -ENODEV)
- padapter->bDriverStopped = true;
-
- goto exit;
- }
-
- ret = _SUCCESS;
-
-exit:
- if (ret != _SUCCESS)
- rtw_free_xmitbuf(pxmitpriv, xmitbuf);
- return ret;
-}
-
-void usb_write_port_cancel(struct adapter *padapter)
-{
- int i, j;
- struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
-
- padapter->bWritePortCancel = true;
-
- for (i = 0; i < NR_XMITBUFF; i++) {
- for (j = 0; j < 8; j++) {
- if (pxmitbuf->pxmit_urb[j])
- usb_kill_urb(pxmitbuf->pxmit_urb[j]);
- }
- pxmitbuf++;
- }
-
- pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
- for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
- for (j = 0; j < 8; j++) {
- if (pxmitbuf->pxmit_urb[j])
- usb_kill_urb(pxmitbuf->pxmit_urb[j]);
- }
- pxmitbuf++;
- }
-}
-
-void rtl8188eu_recv_tasklet(struct tasklet_struct *t)
-{
- struct sk_buff *pskb;
- struct adapter *adapt = from_tasklet(adapt, t, recvpriv.recv_tasklet);
- struct recv_priv *precvpriv = &adapt->recvpriv;
-
- while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
- if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) {
- dev_kfree_skb_any(pskb);
- break;
- }
- recvbuf2recvframe(adapt, pskb);
- skb_reset_tail_pointer(pskb);
- pskb->len = 0;
- skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
- }
-}
-
-void rtl8188eu_xmit_tasklet(struct tasklet_struct *t)
-{
- struct adapter *adapt = from_tasklet(adapt, t, xmitpriv.xmit_tasklet);
- struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
-
- if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY))
- return;
-
- while (1) {
- if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved) || (adapt->bWritePortCancel))
- break;
-
- if (!rtl8188eu_xmitframe_complete(adapt, pxmitpriv))
- break;
- }
-}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index b626ac45db80..358b629d2cc6 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -2167,7 +2167,7 @@ rtl92e_init_variables(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
- strcpy(priv->nick, "rtl8192E");
+ strscpy(priv->nick, "rtl8192E", sizeof(priv->nick));
priv->rtllib->softmac_features = IEEE_SOFTMAC_SCAN |
IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index e85d9c2cdc96..a7dd1578b2c6 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -23,7 +23,6 @@
#include "rtl_pm.h"
int hwwep = 1;
-static int channels = 0x3fff;
static char *ifname = "wlan%d";
@@ -2557,8 +2556,6 @@ static void _rtl92e_pci_disconnect(struct pci_dev *pdev)
release_mem_region(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
}
- } else {
- priv = rtllib_priv(dev);
}
pci_disable_device(pdev);
@@ -2642,8 +2639,6 @@ MODULE_FIRMWARE(RTL8192E_DATA_IMG_FW);
module_param(ifname, charp, 0644);
module_param(hwwep, int, 0644);
-module_param(channels, int, 0644);
MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support(default use hw. set 0 to use software security)");
-MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
index b60e2a109ce4..ed968c01c7ff 100644
--- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
+++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
@@ -133,7 +133,9 @@ static int ccmp_init_iv_and_aad(struct rtllib_hdr_4addr *hdr,
pos = (u8 *) hdr;
aad[0] = pos[0] & 0x8f;
aad[1] = pos[1] & 0xc7;
- memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN);
+ memcpy(&aad[2], &hdr->addr1, ETH_ALEN);
+ memcpy(&aad[8], &hdr->addr2, ETH_ALEN);
+ memcpy(&aad[14], &hdr->addr3, ETH_ALEN);
pos = (u8 *) &hdr->seq_ctl;
aad[20] = pos[0] & 0x0f;
aad[21] = 0; /* all bits masked */
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index c2209c033838..e3d0a361d370 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -1556,6 +1556,8 @@ static int rtllib_verify_qos_info(struct rtllib_qos_information_element
*info_element, int sub_type)
{
+ if (info_element->elementID != QOS_ELEMENT_ID)
+ return -1;
if (info_element->qui_subtype != sub_type)
return -1;
if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
@@ -1570,57 +1572,32 @@ static int rtllib_verify_qos_info(struct rtllib_qos_information_element
/* Parse a QoS parameter element */
-static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info
- *element_param,
- struct rtllib_info_element
- *info_element)
+static int rtllib_read_qos_param_element(
+ struct rtllib_qos_parameter_info *element_param,
+ struct rtllib_info_element *info_element)
{
- int ret = 0;
- u16 size = sizeof(struct rtllib_qos_parameter_info) - 2;
+ size_t size = sizeof(*element_param);
- if ((info_element == NULL) || (element_param == NULL))
+ if (!element_param || !info_element || info_element->len != size - 2)
return -1;
- if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
- memcpy(element_param->info_element.qui, info_element->data,
- info_element->len);
- element_param->info_element.elementID = info_element->id;
- element_param->info_element.length = info_element->len;
- } else
- ret = -1;
- if (ret == 0)
- ret = rtllib_verify_qos_info(&element_param->info_element,
- QOS_OUI_PARAM_SUB_TYPE);
- return ret;
+ memcpy(element_param, info_element, size);
+ return rtllib_verify_qos_info(&element_param->info_element,
+ QOS_OUI_PARAM_SUB_TYPE);
}
/* Parse a QoS information element */
-static int rtllib_read_qos_info_element(struct rtllib_qos_information_element
- *element_info,
- struct rtllib_info_element
- *info_element)
+static int rtllib_read_qos_info_element(
+ struct rtllib_qos_information_element *element_info,
+ struct rtllib_info_element *info_element)
{
- int ret = 0;
- u16 size = sizeof(struct rtllib_qos_information_element) - 2;
+ size_t size = sizeof(*element_info);
- if (element_info == NULL)
+ if (!element_info || !info_element || info_element->len != size - 2)
return -1;
- if (info_element == NULL)
- return -1;
-
- if ((info_element->id == QOS_ELEMENT_ID) &&
- (info_element->len == size)) {
- memcpy(element_info->qui, info_element->data,
- info_element->len);
- element_info->elementID = info_element->id;
- element_info->length = info_element->len;
- } else
- ret = -1;
- if (ret == 0)
- ret = rtllib_verify_qos_info(element_info,
- QOS_OUI_INFO_SUB_TYPE);
- return ret;
+ memcpy(element_info, info_element, size);
+ return rtllib_verify_qos_info(element_info, QOS_OUI_INFO_SUB_TYPE);
}
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index 25b3d3950a3c..d2726d01c757 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -2582,7 +2582,8 @@ static void rtllib_start_ibss_wq(void *data)
mutex_lock(&ieee->wx_mutex);
if (ieee->current_network.ssid_len == 0) {
- strcpy(ieee->current_network.ssid, RTLLIB_DEFAULT_TX_ESSID);
+ strscpy(ieee->current_network.ssid, RTLLIB_DEFAULT_TX_ESSID,
+ sizeof(ieee->current_network.ssid));
ieee->current_network.ssid_len = strlen(RTLLIB_DEFAULT_TX_ESSID);
ieee->ssid_set = 1;
}
diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
index f89799d43b1b..57a6d1130b6a 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
@@ -539,18 +539,14 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
}
EXPORT_SYMBOL(rtllib_wx_set_rawtx);
-int rtllib_wx_get_name(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
+int rtllib_wx_get_name(struct rtllib_device *ieee, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
{
- strcpy(wrqu->name, "802.11");
-
- if (ieee->modulation & RTLLIB_CCK_MODULATION)
- strcat(wrqu->name, "b");
- if (ieee->modulation & RTLLIB_OFDM_MODULATION)
- strcat(wrqu->name, "g");
- if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
- strcat(wrqu->name, "n");
+ const char *b = ieee->modulation & RTLLIB_CCK_MODULATION ? "b" : "";
+ const char *g = ieee->modulation & RTLLIB_OFDM_MODULATION ? "g" : "";
+ const char *n = ieee->mode & (IEEE_N_24G | IEEE_N_5G) ? "n" : "";
+
+ scnprintf(wrqu->name, sizeof(wrqu->name), "802.11%s%s%s", b, g, n);
return 0;
}
EXPORT_SYMBOL(rtllib_wx_get_name);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 7903c777a417..15207dc1f5c5 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -303,7 +303,7 @@ struct ieee_param {
struct {
u32 len;
u8 reserved[32];
- u8 data[0];
+ u8 data[];
} wpa_ie;
struct{
int command;
@@ -316,7 +316,7 @@ struct ieee_param {
u8 idx;
u8 seq[8]; /* sequence counter (set: RX, get: TX) */
u16 key_len;
- u8 key[0];
+ u8 key[];
} crypt;
} u;
};
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
index c241cf484023..ccff385cf1f8 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
@@ -141,7 +141,9 @@ static int ccmp_init_iv_and_aad(struct rtl_80211_hdr_4addr *hdr,
pos = (u8 *)hdr;
aad[0] = pos[0] & 0x8f;
aad[1] = pos[1] & 0xc7;
- memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN);
+ memcpy(&aad[2], &hdr->addr1, ETH_ALEN);
+ memcpy(&aad[8], &hdr->addr2, ETH_ALEN);
+ memcpy(&aad[14], &hdr->addr3, ETH_ALEN);
pos = (u8 *)&hdr->seq_ctl;
aad[20] = pos[0] & 0x0f;
aad[21] = 0; /* all bits masked */
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index b0e01ee65f7f..b58e75932ecd 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -1310,7 +1310,8 @@ static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
*info_element, int sub_type)
{
-
+ if (info_element->elementID != QOS_ELEMENT_ID)
+ return -1;
if (info_element->qui_subtype != sub_type)
return -1;
if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
@@ -1327,27 +1328,18 @@ static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
/*
* Parse a QoS parameter element
*/
-static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
- *element_param, struct ieee80211_info_element
- *info_element)
+static int ieee80211_read_qos_param_element(
+ struct ieee80211_qos_parameter_info *element_param,
+ struct ieee80211_info_element *info_element)
{
- int ret = 0;
- u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
+ size_t size = sizeof(*element_param);
- if (!info_element || !element_param)
+ if (!element_param || !info_element || info_element->len != size - 2)
return -1;
- if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
- memcpy(element_param->info_element.qui, info_element->data,
- info_element->len);
- element_param->info_element.elementID = info_element->id;
- element_param->info_element.length = info_element->len;
- } else
- ret = -1;
- if (ret == 0)
- ret = ieee80211_verify_qos_info(&element_param->info_element,
- QOS_OUI_PARAM_SUB_TYPE);
- return ret;
+ memcpy(element_param, info_element, size);
+ return ieee80211_verify_qos_info(&element_param->info_element,
+ QOS_OUI_PARAM_SUB_TYPE);
}
/*
@@ -1357,26 +1349,13 @@ static int ieee80211_read_qos_info_element(
struct ieee80211_qos_information_element *element_info,
struct ieee80211_info_element *info_element)
{
- int ret = 0;
- u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
+ size_t size = sizeof(*element_info);
- if (!element_info)
+ if (!element_info || !info_element || info_element->len != size - 2)
return -1;
- if (!info_element)
- return -1;
-
- if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
- memcpy(element_info->qui, info_element->data,
- info_element->len);
- element_info->elementID = info_element->id;
- element_info->length = info_element->len;
- } else
- ret = -1;
- if (ret == 0)
- ret = ieee80211_verify_qos_info(element_info,
- QOS_OUI_INFO_SUB_TYPE);
- return ret;
+ memcpy(element_info, info_element, size);
+ return ieee80211_verify_qos_info(element_info, QOS_OUI_INFO_SUB_TYPE);
}
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index ab885353f668..1a193f900779 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -2226,7 +2226,8 @@ static void ieee80211_start_ibss_wq(struct work_struct *work)
mutex_lock(&ieee->wx_mutex);
if (ieee->current_network.ssid_len == 0) {
- strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
+ strscpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID,
+ sizeof(ieee->current_network.ssid));
ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
ieee->ssid_set = 1;
}
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index db26edeccea6..b6698656fc01 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -4265,7 +4265,7 @@ static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
bpacket_match_bssid = (type != IEEE80211_FTYPE_CTL) &&
(ether_addr_equal(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
&& (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV);
- bpacket_toself = bpacket_match_bssid &
+ bpacket_toself = bpacket_match_bssid &&
(ether_addr_equal(praddr, priv->ieee80211->dev->dev_addr));
if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c
index 37b82553412e..97f4d89500ae 100644
--- a/drivers/staging/rtl8192u/r819xU_phy.c
+++ b/drivers/staging/rtl8192u/r819xU_phy.c
@@ -1185,30 +1185,30 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
u8 *stage, u8 *step, u32 *delay)
{
struct r8192_priv *priv = ieee80211_priv(dev);
- struct sw_chnl_cmd *PreCommonCmd;
- u32 PreCommonCmdCnt;
- struct sw_chnl_cmd *PostCommonCmd;
- u32 PostCommonCmdCnt;
- struct sw_chnl_cmd *RfDependCmd;
- u32 RfDependCmdCnt;
- struct sw_chnl_cmd *CurrentCmd = NULL;
- u8 e_rfpath;
- bool ret;
-
- PreCommonCmd = kzalloc(sizeof(*PreCommonCmd) * MAX_PRECMD_CNT, GFP_KERNEL);
- if (!PreCommonCmd)
+ struct sw_chnl_cmd *pre_cmd;
+ u32 pre_cmd_cnt = 0;
+ struct sw_chnl_cmd *post_cmd;
+ u32 post_cmd_cnt = 0;
+ struct sw_chnl_cmd *rf_cmd;
+ u32 rf_cmd_cnt = 0;
+ struct sw_chnl_cmd *current_cmd = NULL;
+ u8 e_rfpath;
+ bool ret;
+
+ pre_cmd = kcalloc(MAX_PRECMD_CNT, sizeof(*pre_cmd), GFP_KERNEL);
+ if (!pre_cmd)
return false;
- PostCommonCmd = kzalloc(sizeof(*PostCommonCmd) * MAX_POSTCMD_CNT, GFP_KERNEL);
- if (!PostCommonCmd) {
- kfree(PreCommonCmd);
+ post_cmd = kcalloc(MAX_POSTCMD_CNT, sizeof(*post_cmd), GFP_KERNEL);
+ if (!post_cmd) {
+ kfree(pre_cmd);
return false;
}
- RfDependCmd = kzalloc(sizeof(*RfDependCmd) * MAX_RFDEPENDCMD_CNT, GFP_KERNEL);
- if (!RfDependCmd) {
- kfree(PreCommonCmd);
- kfree(PostCommonCmd);
+ rf_cmd = kcalloc(MAX_RFDEPENDCMD_CNT, sizeof(*rf_cmd), GFP_KERNEL);
+ if (!rf_cmd) {
+ kfree(pre_cmd);
+ kfree(post_cmd);
return false;
}
@@ -1225,21 +1225,17 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
/* FIXME: need to check whether channel is legal or not here */
/* <1> Fill up pre common command. */
- PreCommonCmdCnt = 0;
- rtl8192_phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++,
+ rtl8192_phy_SetSwChnlCmdArray(pre_cmd, pre_cmd_cnt++,
MAX_PRECMD_CNT, CMD_ID_SET_TX_PWR_LEVEL,
0, 0, 0);
- rtl8192_phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++,
+ rtl8192_phy_SetSwChnlCmdArray(pre_cmd, pre_cmd_cnt++,
MAX_PRECMD_CNT, CMD_ID_END, 0, 0, 0);
/* <2> Fill up post common command. */
- PostCommonCmdCnt = 0;
-
- rtl8192_phy_SetSwChnlCmdArray(PostCommonCmd, PostCommonCmdCnt++,
+ rtl8192_phy_SetSwChnlCmdArray(post_cmd, post_cmd_cnt++,
MAX_POSTCMD_CNT, CMD_ID_END, 0, 0, 0);
/* <3> Fill up RF dependent command. */
- RfDependCmdCnt = 0;
switch (priv->rf_chip) {
case RF_8225:
if (!(channel >= 1 && channel <= 14)) {
@@ -1249,13 +1245,13 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
ret = true;
goto out;
}
- rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++,
+ rtl8192_phy_SetSwChnlCmdArray(rf_cmd, rf_cmd_cnt++,
MAX_RFDEPENDCMD_CNT,
CMD_ID_RF_WRITE_REG,
rZebra1_Channel,
RF_CHANNEL_TABLE_ZEBRA[channel],
10);
- rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++,
+ rtl8192_phy_SetSwChnlCmdArray(rf_cmd, rf_cmd_cnt++,
MAX_RFDEPENDCMD_CNT,
CMD_ID_END, 0, 0, 0);
break;
@@ -1269,11 +1265,11 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
ret = true;
goto out;
}
- rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++,
+ rtl8192_phy_SetSwChnlCmdArray(rf_cmd, rf_cmd_cnt++,
MAX_RFDEPENDCMD_CNT,
CMD_ID_RF_WRITE_REG,
rZebra1_Channel, channel, 10);
- rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++,
+ rtl8192_phy_SetSwChnlCmdArray(rf_cmd, rf_cmd_cnt++,
MAX_RFDEPENDCMD_CNT,
CMD_ID_END, 0, 0, 0);
break;
@@ -1290,19 +1286,19 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
do {
switch (*stage) {
case 0:
- CurrentCmd = &PreCommonCmd[*step];
+ current_cmd = &pre_cmd[*step];
break;
case 1:
- CurrentCmd = &RfDependCmd[*step];
+ current_cmd = &rf_cmd[*step];
break;
case 2:
- CurrentCmd = &PostCommonCmd[*step];
+ current_cmd = &post_cmd[*step];
break;
}
- if (CurrentCmd->cmd_id == CMD_ID_END) {
+ if (current_cmd->cmd_id == CMD_ID_END) {
if ((*stage) == 2) {
- (*delay) = CurrentCmd->ms_delay;
+ *delay = current_cmd->ms_delay;
ret = true;
goto out;
}
@@ -1311,31 +1307,31 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
continue;
}
- switch (CurrentCmd->cmd_id) {
+ switch (current_cmd->cmd_id) {
case CMD_ID_SET_TX_PWR_LEVEL:
if (priv->card_8192_version == VERSION_819XU_A)
/* consider it later! */
rtl8192_SetTxPowerLevel(dev, channel);
break;
case CMD_ID_WRITE_PORT_ULONG:
- write_nic_dword(dev, CurrentCmd->para_1,
- CurrentCmd->para_2);
+ write_nic_dword(dev, current_cmd->para_1,
+ current_cmd->para_2);
break;
case CMD_ID_WRITE_PORT_USHORT:
- write_nic_word(dev, CurrentCmd->para_1,
- (u16)CurrentCmd->para_2);
+ write_nic_word(dev, current_cmd->para_1,
+ (u16)current_cmd->para_2);
break;
case CMD_ID_WRITE_PORT_UCHAR:
- write_nic_byte(dev, CurrentCmd->para_1,
- (u8)CurrentCmd->para_2);
+ write_nic_byte(dev, current_cmd->para_1,
+ (u8)current_cmd->para_2);
break;
case CMD_ID_RF_WRITE_REG:
for (e_rfpath = 0; e_rfpath < RF90_PATH_MAX; e_rfpath++) {
rtl8192_phy_SetRFReg(dev,
(enum rf90_radio_path_e)e_rfpath,
- CurrentCmd->para_1,
+ current_cmd->para_1,
bZebra1_ChannelNum,
- CurrentCmd->para_2);
+ current_cmd->para_2);
}
break;
default:
@@ -1345,14 +1341,14 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
break;
} while (true);
- (*delay) = CurrentCmd->ms_delay;
+ *delay = current_cmd->ms_delay;
(*step)++;
ret = false;
out:
- kfree(PreCommonCmd);
- kfree(PostCommonCmd);
- kfree(RfDependCmd);
+ kfree(pre_cmd);
+ kfree(post_cmd);
+ kfree(rf_cmd);
return ret;
}
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
index 4eff3fdecdb8..1148075f0cd6 100644
--- a/drivers/staging/rtl8712/hal_init.c
+++ b/drivers/staging/rtl8712/hal_init.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
- * hal_init.c
*
* Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
* Linux device driver for RTL8192SU
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
index 2214aca09730..9502f6aa5306 100644
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -203,7 +203,7 @@ struct net_device *r8712_init_netdev(void)
if (!pnetdev)
return NULL;
if (dev_alloc_name(pnetdev, ifname) < 0) {
- strcpy(ifname, "wlan%d");
+ strscpy(ifname, "wlan%d", sizeof(ifname));
dev_alloc_name(pnetdev, ifname);
}
padapter = netdev_priv(pnetdev);
diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h
index e939c4a954b3..d33ddffb7ad9 100644
--- a/drivers/staging/rtl8712/osdep_service.h
+++ b/drivers/staging/rtl8712/osdep_service.h
@@ -46,7 +46,7 @@ struct __queue {
} while (0)
static inline u32 end_of_queue_search(struct list_head *head,
- struct list_head *plist)
+ struct list_head *plist)
{
return (head == plist);
}
diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h
index 577a95c62d6c..b8acb9c7395d 100644
--- a/drivers/staging/rtl8712/wifi.h
+++ b/drivers/staging/rtl8712/wifi.h
@@ -20,26 +20,10 @@
#define WLAN_HDR_A3_LEN 24
#define WLAN_HDR_A3_QOS_LEN 26
-#define P80211CAPTURE_VERSION 0x80211001
-
enum WIFI_FRAME_TYPE {
WIFI_QOS_DATA_TYPE = (BIT(7) | BIT(3)), /*!< QoS Data */
};
-enum WIFI_REG_DOMAIN {
- DOMAIN_FCC = 1,
- DOMAIN_IC = 2,
- DOMAIN_ETSI = 3,
- DOMAIN_SPAIN = 4,
- DOMAIN_FRANCE = 5,
- DOMAIN_MKK = 6,
- DOMAIN_ISRAEL = 7,
- DOMAIN_MKK1 = 8,
- DOMAIN_MKK2 = 9,
- DOMAIN_MKK3 = 10,
- DOMAIN_MAX
-};
-
#define SetToDs(pbuf) ({ \
*(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS); \
})
@@ -194,46 +178,14 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe)
return sa;
}
-/*-----------------------------------------------------------------------------
- * Below is for the security related definition
- *-----------------------------------------------------------------------------
- */
-#define _ASOCREQ_IE_OFFSET_ 4 /* excluding wlan_hdr */
-#define _ASOCRSP_IE_OFFSET_ 6
-#define _REASOCREQ_IE_OFFSET_ 10
-#define _REASOCRSP_IE_OFFSET_ 6
-#define _PROBEREQ_IE_OFFSET_ 0
-#define _PROBERSP_IE_OFFSET_ 12
-#define _AUTH_IE_OFFSET_ 6
-#define _DEAUTH_IE_OFFSET_ 0
-#define _BEACON_IE_OFFSET_ 12
-
-#define _FIXED_IE_LENGTH_ _BEACON_IE_OFFSET_
-
/* ---------------------------------------------------------------------------
* Below is the fixed elements...
* ---------------------------------------------------------------------------
*/
-#define _AUTH_ALGM_NUM_ 2
-#define _AUTH_SEQ_NUM_ 2
#define _BEACON_ITERVAL_ 2
#define _CAPABILITY_ 2
-#define _CURRENT_APADDR_ 6
-#define _LISTEN_INTERVAL_ 2
-#define _RSON_CODE_ 2
-#define _ASOC_ID_ 2
-#define _STATUS_CODE_ 2
#define _TIMESTAMP_ 8
-#define AUTH_ODD_TO 0
-#define AUTH_EVEN_TO 1
-
-/*-----------------------------------------------------------------------------
- * Below is the definition for 802.11i / 802.1x
- *------------------------------------------------------------------------------
- */
-#define _IEEE8021X_MGT_ 1 /*WPA */
-#define _IEEE8021X_PSK_ 2 /* WPA with pre-shared key */
/*-----------------------------------------------------------------------------
* Below is the definition for WMM
diff --git a/drivers/staging/rtl8723bs/Kconfig b/drivers/staging/rtl8723bs/Kconfig
index 7eae820eae3b..f40b3021fe8a 100644
--- a/drivers/staging/rtl8723bs/Kconfig
+++ b/drivers/staging/rtl8723bs/Kconfig
@@ -3,8 +3,7 @@ config RTL8723BS
tristate "Realtek RTL8723BS SDIO Wireless LAN NIC driver"
depends on WLAN && MMC && CFG80211
depends on m
- select WIRELESS_EXT
- select WEXT_PRIV
+ select CFG80211_WEXT
select CRYPTO_LIB_ARC4
help
This option enables support for RTL8723BS SDIO drivers, such as
diff --git a/drivers/staging/rtl8723bs/Makefile b/drivers/staging/rtl8723bs/Makefile
index fe45200ff53c..159ca1b9016b 100644
--- a/drivers/staging/rtl8723bs/Makefile
+++ b/drivers/staging/rtl8723bs/Makefile
@@ -35,7 +35,6 @@ r8723bs-y = \
hal/odm_HWConfig.o \
hal/odm_NoiseMonitor.o \
hal/odm_RegConfig8723B.o \
- hal/odm_RTL8723B.o \
hal/rtl8723b_cmd.o \
hal/rtl8723b_dm.o \
hal/rtl8723b_hal_init.o \
diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c
index a6fcb5e9d637..6064dd6a76b4 100644
--- a/drivers/staging/rtl8723bs/core/rtw_ap.c
+++ b/drivers/staging/rtl8723bs/core/rtw_ap.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTW_AP_C_
#include <drv_types.h>
#include <rtw_debug.h>
@@ -56,7 +55,7 @@ static void update_BCNTIM(struct adapter *padapter)
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
- unsigned char *pie = pnetwork_mlmeext->IEs;
+ unsigned char *pie = pnetwork_mlmeext->ies;
/* update TIM IE */
u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
@@ -68,7 +67,7 @@ static void update_BCNTIM(struct adapter *padapter)
p = rtw_get_ie(pie + _FIXED_IE_LENGTH_,
WLAN_EID_TIM,
&tim_ielen,
- pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_
+ pnetwork_mlmeext->ie_length - _FIXED_IE_LENGTH_
);
if (p && tim_ielen > 0) {
tim_ielen += 2;
@@ -77,7 +76,7 @@ static void update_BCNTIM(struct adapter *padapter)
tim_ie_offset = (signed int)(p - pie);
- remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
+ remainder_ielen = pnetwork_mlmeext->ie_length - tim_ie_offset - tim_ielen;
/* append TIM IE from dst_ie offset */
dst_ie = p;
@@ -91,7 +90,7 @@ static void update_BCNTIM(struct adapter *padapter)
p = rtw_get_ie(pie + _BEACON_IE_OFFSET_,
WLAN_EID_SSID,
&tmp_len,
- (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)
+ (pnetwork_mlmeext->ie_length - _BEACON_IE_OFFSET_)
);
if (p)
offset += tmp_len + 2;
@@ -99,7 +98,7 @@ static void update_BCNTIM(struct adapter *padapter)
/* get supported rates len */
p = rtw_get_ie(pie + _BEACON_IE_OFFSET_,
WLAN_EID_SUPP_RATES, &tmp_len,
- (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)
+ (pnetwork_mlmeext->ie_length - _BEACON_IE_OFFSET_)
);
if (p)
offset += tmp_len + 2;
@@ -109,7 +108,7 @@ static void update_BCNTIM(struct adapter *padapter)
premainder_ie = pie + offset;
- remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
+ remainder_ielen = pnetwork_mlmeext->ie_length - offset - tim_ielen;
/* append TIM IE from offset */
dst_ie = pie + offset;
@@ -161,7 +160,7 @@ static void update_BCNTIM(struct adapter *padapter)
}
offset = (uint)(dst_ie - pie);
- pnetwork_mlmeext->IELength = offset + remainder_ielen;
+ pnetwork_mlmeext->ie_length = offset + remainder_ielen;
}
static u8 chk_sta_is_alive(struct sta_info *psta)
@@ -340,7 +339,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
shortGIrate = query_ra_short_GI(psta);
- if (pcur_network->Configuration.DSConfig > 14) {
+ if (pcur_network->configuration.ds_config > 14) {
sta_band |= WIRELESS_INVALID;
} else {
if (tx_ra_bitmap & 0xffff000)
@@ -397,16 +396,16 @@ void update_bmc_sta(struct adapter *padapter)
/* psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this. */
/* prepare for add_RATid */
- supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
- network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates,
+ supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->supported_rates);
+ network_type = rtw_check_network_type((u8 *)&pcur_network->supported_rates,
supportRateNum,
- pcur_network->Configuration.DSConfig
+ pcur_network->configuration.ds_config
);
- if (IsSupportedTxCCK(network_type)) {
+ if (is_supported_tx_cck(network_type)) {
network_type = WIRELESS_11B;
} else if (network_type == WIRELESS_INVALID) { /* error handling */
- if (pcur_network->Configuration.DSConfig > 14)
+ if (pcur_network->configuration.ds_config > 14)
network_type = WIRELESS_INVALID;
else
network_type = WIRELESS_11B;
@@ -572,8 +571,8 @@ static void update_ap_info(struct adapter *padapter, struct sta_info *psta)
psta->wireless_mode = pmlmeext->cur_wireless_mode;
- psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);
- memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);
+ psta->bssratelen = rtw_get_rateset_len(pnetwork->supported_rates);
+ memcpy(psta->bssrateset, pnetwork->supported_rates, psta->bssratelen);
/* HT related cap */
if (phtpriv_ap->ht_option) {
@@ -656,16 +655,16 @@ void start_bss_network(struct adapter *padapter)
struct HT_info_element *pht_info = NULL;
u8 cbw40_enable = 0;
- bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
- cur_channel = pnetwork->Configuration.DSConfig;
+ bcn_interval = (u16)pnetwork->configuration.beacon_period;
+ cur_channel = pnetwork->configuration.ds_config;
cur_bwmode = CHANNEL_WIDTH_20;
cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
/* check if there is wps ie, */
/* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
/* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
- if (!rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_,
- pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL))
+ if (!rtw_get_wps_ie(pnetwork->ies + _FIXED_IE_LENGTH_,
+ pnetwork->ie_length - _FIXED_IE_LENGTH_, NULL, NULL))
pmlmeext->bstart_bss = true;
/* todo: update wmm, ht cap */
@@ -694,7 +693,7 @@ void start_bss_network(struct adapter *padapter)
Set_MSR(padapter, _HW_STATE_AP_);
/* Set BSSID REG */
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->mac_address);
/* Set EDCA param reg */
acparm = 0x002F3217; /* VO */
@@ -734,10 +733,10 @@ void start_bss_network(struct adapter *padapter)
}
/* set channel, bwmode */
- p = rtw_get_ie((pnetwork->IEs + sizeof(struct ndis_802_11_fix_ie)),
+ p = rtw_get_ie((pnetwork->ies + sizeof(struct ndis_802_11_fix_ie)),
WLAN_EID_HT_OPERATION,
&ie_len,
- (pnetwork->IELength - sizeof(struct ndis_802_11_fix_ie))
+ (pnetwork->ie_length - sizeof(struct ndis_802_11_fix_ie))
);
if (p && ie_len) {
pht_info = (struct HT_info_element *)(p + 2);
@@ -780,14 +779,14 @@ void start_bss_network(struct adapter *padapter)
pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
/* let pnetwork_mlmeext == pnetwork_mlme. */
- memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
+ memcpy(pnetwork_mlmeext, pnetwork, pnetwork->length);
/* update cur_wireless_mode */
update_wireless_mode(padapter);
/* update RRSR after set channel and bandwidth */
- UpdateBrateTbl(padapter, pnetwork->SupportedRates);
- rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
+ UpdateBrateTbl(padapter, pnetwork->supported_rates);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->supported_rates);
/* update capability after cur_wireless_mode updated */
update_capinfo(
@@ -827,7 +826,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct wlan_bssid_ex
*pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
- u8 *ie = pbss_network->IEs;
+ u8 *ie = pbss_network->ies;
if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
return _FAIL;
@@ -835,23 +834,23 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
if (len < 0 || len > MAX_IE_SZ)
return _FAIL;
- pbss_network->IELength = len;
+ pbss_network->ie_length = len;
memset(ie, 0, MAX_IE_SZ);
- memcpy(ie, pbuf, pbss_network->IELength);
+ memcpy(ie, pbuf, pbss_network->ie_length);
- if (pbss_network->InfrastructureMode != Ndis802_11APMode)
+ if (pbss_network->infrastructure_mode != Ndis802_11APMode)
return _FAIL;
- pbss_network->Rssi = 0;
+ pbss_network->rssi = 0;
- memcpy(pbss_network->MacAddress, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ memcpy(pbss_network->mac_address, myid(&(padapter->eeprompriv)), ETH_ALEN);
/* beacon interval */
p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; 8: TimeStamp, 2: Beacon Interval 2:Capability */
- /* pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p); */
- pbss_network->Configuration.BeaconPeriod = get_unaligned_le16(p);
+ /* pbss_network->configuration.beacon_period = le16_to_cpu(*(unsigned short*)p); */
+ pbss_network->configuration.beacon_period = get_unaligned_le16(p);
/* capability */
/* cap = *(unsigned short *)rtw_get_capability_from_ie(ie); */
@@ -863,26 +862,26 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
ie + _BEACON_IE_OFFSET_,
WLAN_EID_SSID,
&ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_)
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_)
);
if (p && ie_len > 0) {
- memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
- memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
- pbss_network->Ssid.SsidLength = ie_len;
+ memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid));
+ memcpy(pbss_network->ssid.ssid, (p + 2), ie_len);
+ pbss_network->ssid.ssid_length = ie_len;
}
/* channel */
channel = 0;
- pbss_network->Configuration.Length = 0;
+ pbss_network->configuration.length = 0;
p = rtw_get_ie(
ie + _BEACON_IE_OFFSET_,
WLAN_EID_DS_PARAMS, &ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_)
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_)
);
if (p && ie_len > 0)
channel = *(p + 2);
- pbss_network->Configuration.DSConfig = channel;
+ pbss_network->configuration.ds_config = channel;
memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
/* get supported rates */
@@ -890,7 +889,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
ie + _BEACON_IE_OFFSET_,
WLAN_EID_SUPP_RATES,
&ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_)
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_)
);
if (p != NULL) {
memcpy(supportRate, p + 2, ie_len);
@@ -902,7 +901,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
ie + _BEACON_IE_OFFSET_,
WLAN_EID_EXT_SUPP_RATES,
&ie_len,
- pbss_network->IELength - _BEACON_IE_OFFSET_
+ pbss_network->ie_length - _BEACON_IE_OFFSET_
);
if (p != NULL) {
memcpy(supportRate + supportRateNum, p + 2, ie_len);
@@ -911,23 +910,23 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
- rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
+ rtw_set_supported_rate(pbss_network->supported_rates, network_type);
/* parsing ERP_IE */
p = rtw_get_ie(
ie + _BEACON_IE_OFFSET_,
WLAN_EID_ERP_INFO,
&ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_)
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_)
);
if (p && ie_len > 0)
ERP_IE_handler(padapter, (struct ndis_80211_var_ie *)p);
/* update privacy/security */
if (cap & BIT(4))
- pbss_network->Privacy = 1;
+ pbss_network->privacy = 1;
else
- pbss_network->Privacy = 0;
+ pbss_network->privacy = 0;
psecuritypriv->wpa_psk = 0;
@@ -939,7 +938,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
ie + _BEACON_IE_OFFSET_,
WLAN_EID_RSN,
&ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_)
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_)
);
if (p && ie_len > 0) {
if (rtw_parse_wpa2_ie(
@@ -969,7 +968,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
p,
WLAN_EID_VENDOR_SPECIFIC,
&ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2))
);
if ((p) && (!memcmp(p + 2, OUI1, 4))) {
if (rtw_parse_wpa_ie(
@@ -1005,7 +1004,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
p,
WLAN_EID_VENDOR_SPECIFIC,
&ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2))
);
if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) {
pmlmepriv->qospriv.qos_option = 1;
@@ -1032,10 +1031,9 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
ie + _BEACON_IE_OFFSET_,
WLAN_EID_HT_CAPABILITY,
&ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_)
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_)
);
if (p && ie_len > 0) {
- u8 rf_type = 0;
u8 max_rx_ampdu_factor = 0;
struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2);
@@ -1081,11 +1079,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor
); /* set Max Rx AMPDU size to 64K */
- rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
- if (rf_type == RF_1T1R) {
- pht_cap->mcs.rx_mask[0] = 0xff;
- pht_cap->mcs.rx_mask[1] = 0x0;
- }
+ pht_cap->mcs.rx_mask[0] = 0xff;
+ pht_cap->mcs.rx_mask[1] = 0x0;
memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len);
}
@@ -1095,23 +1090,23 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
ie + _BEACON_IE_OFFSET_,
WLAN_EID_HT_OPERATION,
&ie_len,
- (pbss_network->IELength - _BEACON_IE_OFFSET_)
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_)
);
if (p && ie_len > 0)
pHT_info_ie = p;
switch (network_type) {
case WIRELESS_11B:
- pbss_network->NetworkTypeInUse = Ndis802_11DS;
+ pbss_network->network_type_in_use = Ndis802_11DS;
break;
case WIRELESS_11G:
case WIRELESS_11BG:
case WIRELESS_11G_24N:
case WIRELESS_11BG_24N:
- pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ pbss_network->network_type_in_use = Ndis802_11OFDM24;
break;
default:
- pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ pbss_network->network_type_in_use = Ndis802_11OFDM24;
break;
}
@@ -1138,7 +1133,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
HT_info_handler(padapter, (struct ndis_80211_var_ie *)pHT_info_ie);
}
- pbss_network->Length = get_wlan_bssid_ex_sz(
+ pbss_network->length = get_wlan_bssid_ex_sz(
(struct wlan_bssid_ex *)pbss_network
);
@@ -1147,9 +1142,9 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);
/* alloc sta_info for ap itself */
- psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
+ psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->mac_address);
if (!psta) {
- psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
+ psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->mac_address);
if (psta == NULL)
return _FAIL;
}
@@ -1405,7 +1400,7 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter)
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
- unsigned char *p, *ie = pnetwork->IEs;
+ unsigned char *p, *ie = pnetwork->ies;
u32 len = 0;
if (!pmlmeinfo->ERP_enable)
@@ -1416,7 +1411,7 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter)
ie + _BEACON_IE_OFFSET_,
WLAN_EID_ERP_INFO,
&len,
- (pnetwork->IELength - _BEACON_IE_OFFSET_)
+ (pnetwork->ie_length - _BEACON_IE_OFFSET_)
);
if (p && len > 0) {
struct ndis_80211_var_ie *pIE = (struct ndis_80211_var_ie *)p;
@@ -1469,8 +1464,8 @@ static void update_bcn_wps_ie(struct adapter *padapter)
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
- unsigned char *ie = pnetwork->IEs;
- u32 ielen = pnetwork->IELength;
+ unsigned char *ie = pnetwork->ies;
+ u32 ielen = pnetwork->ie_length;
pwps_ie = rtw_get_wps_ie(
ie + _FIXED_IE_LENGTH_,
@@ -1506,8 +1501,8 @@ static void update_bcn_wps_ie(struct adapter *padapter)
if (pbackup_remainder_ie)
memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
- /* update IELength */
- pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen;
+ /* update ie_length */
+ pnetwork->ie_length = wps_offset + (wps_ielen + 2) + remainder_ielen;
}
kfree(pbackup_remainder_ie);
diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c
index 04956ccf485c..d494c06dab96 100644
--- a/drivers/staging/rtl8723bs/core/rtw_cmd.c
+++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c
@@ -567,7 +567,7 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid,
int i;
for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (ssid[i].SsidLength) {
+ if (ssid[i].ssid_length) {
memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
psurveyPara->ssid_num++;
}
@@ -656,7 +656,7 @@ u8 rtw_createbss_cmd(struct adapter *padapter)
pcmd->rsp = NULL;
pcmd->rspsz = 0;
- pdev_network->Length = pcmd->cmdsz;
+ pdev_network->length = pcmd->cmdsz;
res = rtw_enqueue_cmd(pcmdpriv, pcmd);
@@ -722,7 +722,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- enum ndis_802_11_network_infrastructure ndis_network_mode = pnetwork->network.InfrastructureMode;
+ enum ndis_802_11_network_infrastructure ndis_network_mode = pnetwork->network.infrastructure_mode;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
u32 tmp_len;
@@ -733,7 +733,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
res = _FAIL;
goto exit;
}
- /* for IEs is fix buf size */
+ /* for ies is fix buf size */
t_len = sizeof(struct wlan_bssid_ex);
@@ -762,32 +762,32 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
- psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
+ psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->ie_length;
- if ((psecnetwork->IELength-12) < (256-1))
- memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12);
+ if ((psecnetwork->ie_length-12) < (256-1))
+ memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], psecnetwork->ie_length-12);
else
- memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1));
+ memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], (256-1));
- psecnetwork->IELength = 0;
+ psecnetwork->ie_length = 0;
/* Added by Albert 2009/02/18 */
/* If the driver wants to use the bssid to create the connection. */
/* If not, we have to copy the connecting AP's MAC address to it so that */
/* the driver just has the bssid information for PMKIDList searching. */
if (pmlmepriv->assoc_by_bssid == false)
- memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
+ memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.mac_address[0], ETH_ALEN);
- psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
+ psecnetwork->ie_length = rtw_restruct_sec_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], pnetwork->network.ie_length);
pqospriv->qos_option = 0;
if (pregistrypriv->wmm_enable) {
- tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
+ tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], pnetwork->network.ie_length, psecnetwork->ie_length);
- if (psecnetwork->IELength != tmp_len) {
- psecnetwork->IELength = tmp_len;
+ if (psecnetwork->ie_length != tmp_len) {
+ psecnetwork->ie_length = tmp_len;
pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
} else {
pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
@@ -795,7 +795,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
}
phtpriv->ht_option = false;
- ptmp = rtw_get_ie(&pnetwork->network.IEs[12], WLAN_EID_HT_CAPABILITY, &tmp_len, pnetwork->network.IELength-12);
+ ptmp = rtw_get_ie(&pnetwork->network.ies[12], WLAN_EID_HT_CAPABILITY, &tmp_len, pnetwork->network.ie_length-12);
if (pregistrypriv->ht_enable && ptmp && tmp_len > 0) {
/* Added by Albert 2010/06/23 */
/* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
@@ -805,18 +805,18 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
(padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
rtw_ht_use_default_setting(padapter);
- rtw_build_wmm_ie_ht(padapter, &psecnetwork->IEs[12], &psecnetwork->IELength);
+ rtw_build_wmm_ie_ht(padapter, &psecnetwork->ies[12], &psecnetwork->ie_length);
/* rtw_restructure_ht_ie */
- rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],
- pnetwork->network.IELength-12, &psecnetwork->IELength,
- pnetwork->network.Configuration.DSConfig);
+ rtw_restructure_ht_ie(padapter, &pnetwork->network.ies[12], &psecnetwork->ies[0],
+ pnetwork->network.ie_length-12, &psecnetwork->ie_length,
+ pnetwork->network.configuration.ds_config);
}
}
- rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
+ rtw_append_exented_cap(padapter, &psecnetwork->ies[0], &psecnetwork->ie_length);
- pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
+ pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.ies, pnetwork->network.ie_length);
pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
@@ -1973,9 +1973,9 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
+ psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->mac_address);
if (!psta) {
- psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
+ psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->mac_address);
if (!psta)
goto createbss_cmd_fail;
}
@@ -1995,8 +1995,8 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
}
- pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
- memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
+ pnetwork->length = get_wlan_bssid_ex_sz(pnetwork);
+ memcpy(&(pwlan->network), pnetwork, pnetwork->length);
/* pwlan->fixed = true; */
/* list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); */
@@ -2004,8 +2004,8 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
/* copy pdev_network information to pmlmepriv->cur_network */
memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
- /* reset DSConfig */
- /* tgt_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pnetwork->Configuration.DSConfig); */
+ /* reset ds_config */
+ /* tgt_network->network.configuration.ds_config = (u32)rtw_ch2freq(pnetwork->configuration.ds_config); */
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
diff --git a/drivers/staging/rtl8723bs/core/rtw_debug.c b/drivers/staging/rtl8723bs/core/rtw_debug.c
index 576b039f741c..5354fdd11c9b 100644
--- a/drivers/staging/rtl8723bs/core/rtw_debug.c
+++ b/drivers/staging/rtl8723bs/core/rtw_debug.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTW_DEBUG_C_
#include <drv_types.h>
#include <rtw_debug.h>
@@ -59,21 +58,11 @@ static void dump_4_rf_regs(struct adapter *adapter, int path, int offset)
void rf_reg_dump(struct adapter *adapter)
{
- int i, path;
- u8 rf_type = 0;
- u8 path_nums = 0;
-
- rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
- if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
- path_nums = 1;
- else
- path_nums = 2;
+ int i, path = 0;
netdev_dbg(adapter->pnetdev, "======= RF REG =======\n");
- for (path = 0; path < path_nums; path++) {
- netdev_dbg(adapter->pnetdev, "RF_Path(%x)\n", path);
- for (i = 0; i < 0x100; i++)
- dump_4_rf_regs(adapter, path, i);
- }
+ netdev_dbg(adapter->pnetdev, "RF_Path(%x)\n", path);
+ for (i = 0; i < 0x100; i++)
+ dump_4_rf_regs(adapter, path, i);
}
diff --git a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c
index 0f0fcd9dc652..b449be537376 100644
--- a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _IEEE80211_C
#include <drv_types.h>
#include <rtw_debug.h>
@@ -253,25 +252,25 @@ exit:
return ret;
}
-void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
+void rtw_set_supported_rate(u8 *supported_rates, uint mode)
{
- memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+ memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
switch (mode) {
case WIRELESS_11B:
- memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+ memcpy(supported_rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
break;
case WIRELESS_11G:
- memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
+ memcpy(supported_rates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
break;
case WIRELESS_11BG:
case WIRELESS_11G_24N:
case WIRELESS_11_24N:
case WIRELESS_11BG_24N:
- memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
- memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
+ memcpy(supported_rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+ memcpy(supported_rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
break;
}
}
@@ -291,14 +290,14 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv)
u8 wireless_mode;
int sz = 0, rateLen;
struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
- u8 *ie = pdev_network->IEs;
+ u8 *ie = pdev_network->ies;
/* timestamp will be inserted by hardware */
sz += 8;
ie += sz;
/* beacon interval : 2bytes */
- *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */
+ *(__le16 *)ie = cpu_to_le16((u16)pdev_network->configuration.beacon_period);/* BCN_INTERVAL; */
sz += 2;
ie += 2;
@@ -310,38 +309,38 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv)
if (pregistrypriv->preamble == PREAMBLE_SHORT)
*(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
- if (pdev_network->Privacy)
+ if (pdev_network->privacy)
*(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
sz += 2;
ie += 2;
/* SSID */
- ie = rtw_set_ie(ie, WLAN_EID_SSID, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz);
+ ie = rtw_set_ie(ie, WLAN_EID_SSID, pdev_network->ssid.ssid_length, pdev_network->ssid.ssid, &sz);
/* supported rates */
wireless_mode = pregistrypriv->wireless_mode;
- rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode);
+ rtw_set_supported_rate(pdev_network->supported_rates, wireless_mode);
- rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
+ rateLen = rtw_get_rateset_len(pdev_network->supported_rates);
if (rateLen > 8) {
- ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, 8, pdev_network->SupportedRates, &sz);
- /* ie = rtw_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
+ ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, 8, pdev_network->supported_rates, &sz);
+ /* ie = rtw_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), (pdev_network->supported_rates + 8), &sz); */
} else {
- ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, rateLen, pdev_network->SupportedRates, &sz);
+ ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, rateLen, pdev_network->supported_rates, &sz);
}
/* DS parameter set */
- ie = rtw_set_ie(ie, WLAN_EID_DS_PARAMS, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
+ ie = rtw_set_ie(ie, WLAN_EID_DS_PARAMS, 1, (u8 *)&(pdev_network->configuration.ds_config), &sz);
/* IBSS Parameter Set */
- ie = rtw_set_ie(ie, WLAN_EID_IBSS_PARAMS, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
+ ie = rtw_set_ie(ie, WLAN_EID_IBSS_PARAMS, 2, (u8 *)&(pdev_network->configuration.atim_window), &sz);
if (rateLen > 8) {
- ie = rtw_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
+ ie = rtw_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), (pdev_network->supported_rates + 8), &sz);
}
/* HT Cap. */
@@ -350,7 +349,7 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv)
/* todo: */
}
- /* pdev_network->IELength = sz; update IELength */
+ /* pdev_network->ie_length = sz; update ie_length */
/* return _SUCCESS; */
@@ -1030,23 +1029,23 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork)
int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
int ret = _FAIL;
- pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
+ pbuf = rtw_get_wpa_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length-12);
if (pbuf && (wpa_ielen > 0)) {
if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
- pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
- pnetwork->BcnInfo.group_cipher = group_cipher;
- pnetwork->BcnInfo.is_8021x = is8021x;
+ pnetwork->bcn_info.pairwise_cipher = pairwise_cipher;
+ pnetwork->bcn_info.group_cipher = group_cipher;
+ pnetwork->bcn_info.is_8021x = is8021x;
ret = _SUCCESS;
}
} else {
- pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
+ pbuf = rtw_get_wpa2_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length-12);
if (pbuf && (wpa_ielen > 0)) {
if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
- pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
- pnetwork->BcnInfo.group_cipher = group_cipher;
- pnetwork->BcnInfo.is_8021x = is8021x;
+ pnetwork->bcn_info.pairwise_cipher = pairwise_cipher;
+ pnetwork->bcn_info.group_cipher = group_cipher;
+ pnetwork->bcn_info.is_8021x = is8021x;
ret = _SUCCESS;
}
}
@@ -1067,104 +1066,67 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork)
unsigned char *p;
__le16 le_cap;
- memcpy((u8 *)&le_cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
+ memcpy((u8 *)&le_cap, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
cap = le16_to_cpu(le_cap);
if (cap & WLAN_CAPABILITY_PRIVACY) {
bencrypt = 1;
- pnetwork->network.Privacy = 1;
+ pnetwork->network.privacy = 1;
} else {
- pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
+ pnetwork->bcn_info.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
}
- rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &rsn_len, NULL, &wpa_len);
+ rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &rsn_len, NULL, &wpa_len);
if (rsn_len > 0) {
- pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
+ pnetwork->bcn_info.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
} else if (wpa_len > 0) {
- pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
+ pnetwork->bcn_info.encryp_protocol = ENCRYP_PROTOCOL_WPA;
} else {
if (bencrypt)
- pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
+ pnetwork->bcn_info.encryp_protocol = ENCRYP_PROTOCOL_WEP;
}
rtw_get_cipher_info(pnetwork);
/* get bwmode and ch_offset */
/* parsing HT_CAP_IE */
- p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
if (p && len > 0) {
pht_cap = (struct ieee80211_ht_cap *)(p + 2);
- pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(pht_cap->cap_info);
+ pnetwork->bcn_info.ht_cap_info = le16_to_cpu(pht_cap->cap_info);
} else {
- pnetwork->BcnInfo.ht_cap_info = 0;
+ pnetwork->bcn_info.ht_cap_info = 0;
}
/* parsing HT_INFO_IE */
- p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
if (p && len > 0) {
pht_info = (struct HT_info_element *)(p + 2);
- pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
+ pnetwork->bcn_info.ht_info_infos_0 = pht_info->infos[0];
} else {
- pnetwork->BcnInfo.ht_info_infos_0 = 0;
+ pnetwork->bcn_info.ht_info_infos_0 = 0;
}
}
/* show MCS rate, unit: 100Kbps */
-u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate)
+u16 rtw_mcs_rate(u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate)
{
u16 max_rate = 0;
- if (rf_type == RF_1T1R) {
- if (MCS_rate[0] & BIT(7))
- max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650);
- else if (MCS_rate[0] & BIT(6))
- max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
- else if (MCS_rate[0] & BIT(5))
- max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
- else if (MCS_rate[0] & BIT(4))
- max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
- else if (MCS_rate[0] & BIT(3))
- max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
- else if (MCS_rate[0] & BIT(2))
- max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
- else if (MCS_rate[0] & BIT(1))
- max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
- else if (MCS_rate[0] & BIT(0))
- max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
- } else {
- if (MCS_rate[1]) {
- if (MCS_rate[1] & BIT(7))
- max_rate = (bw_40MHz) ? ((short_GI)?3000:2700):((short_GI)?1444:1300);
- else if (MCS_rate[1] & BIT(6))
- max_rate = (bw_40MHz) ? ((short_GI)?2700:2430):((short_GI)?1300:1170);
- else if (MCS_rate[1] & BIT(5))
- max_rate = (bw_40MHz) ? ((short_GI)?2400:2160):((short_GI)?1156:1040);
- else if (MCS_rate[1] & BIT(4))
- max_rate = (bw_40MHz) ? ((short_GI)?1800:1620):((short_GI)?867:780);
- else if (MCS_rate[1] & BIT(3))
- max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
- else if (MCS_rate[1] & BIT(2))
- max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
- else if (MCS_rate[1] & BIT(1))
- max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
- else if (MCS_rate[1] & BIT(0))
- max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
- } else {
- if (MCS_rate[0] & BIT(7))
- max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650);
- else if (MCS_rate[0] & BIT(6))
- max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
- else if (MCS_rate[0] & BIT(5))
- max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
- else if (MCS_rate[0] & BIT(4))
- max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
- else if (MCS_rate[0] & BIT(3))
- max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
- else if (MCS_rate[0] & BIT(2))
- max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
- else if (MCS_rate[0] & BIT(1))
- max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
- else if (MCS_rate[0] & BIT(0))
- max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
- }
- }
+ if (MCS_rate[0] & BIT(7))
+ max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650);
+ else if (MCS_rate[0] & BIT(6))
+ max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
+ else if (MCS_rate[0] & BIT(5))
+ max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
+ else if (MCS_rate[0] & BIT(4))
+ max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
+ else if (MCS_rate[0] & BIT(3))
+ max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
+ else if (MCS_rate[0] & BIT(2))
+ max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
+ else if (MCS_rate[0] & BIT(1))
+ max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
+ else if (MCS_rate[0] & BIT(0))
+ max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
+
return max_rate;
}
diff --git a/drivers/staging/rtl8723bs/core/rtw_io.c b/drivers/staging/rtl8723bs/core/rtw_io.c
index 856e23398c03..4d3c30ec93b5 100644
--- a/drivers/staging/rtl8723bs/core/rtw_io.c
+++ b/drivers/staging/rtl8723bs/core/rtw_io.c
@@ -28,11 +28,6 @@ jackson@realtek.com.tw
#include <drv_types.h>
#include <rtw_debug.h>
-#define rtw_le16_to_cpu(val) val
-#define rtw_le32_to_cpu(val) val
-#define rtw_cpu_to_le16(val) val
-#define rtw_cpu_to_le32(val) val
-
u8 rtw_read8(struct adapter *adapter, u32 addr)
{
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
@@ -47,7 +42,6 @@ u8 rtw_read8(struct adapter *adapter, u32 addr)
u16 rtw_read16(struct adapter *adapter, u32 addr)
{
- u16 r_val;
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
@@ -55,13 +49,11 @@ u16 rtw_read16(struct adapter *adapter, u32 addr)
_read16 = pintfhdl->io_ops._read16;
- r_val = _read16(pintfhdl, addr);
- return rtw_le16_to_cpu(r_val);
+ return _read16(pintfhdl, addr);
}
u32 rtw_read32(struct adapter *adapter, u32 addr)
{
- u32 r_val;
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
@@ -69,8 +61,7 @@ u32 rtw_read32(struct adapter *adapter, u32 addr)
_read32 = pintfhdl->io_ops._read32;
- r_val = _read32(pintfhdl, addr);
- return rtw_le32_to_cpu(r_val);
+ return _read32(pintfhdl, addr);
}
diff --git a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c
index bd5056507f53..5cfde7176617 100644
--- a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c
+++ b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTW_IOCTL_SET_C_
#include <drv_types.h>
#include <rtw_debug.h>
@@ -27,7 +26,7 @@ u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
{
u8 ret = true;
- if (ssid->SsidLength > 32) {
+ if (ssid->ssid_length > 32) {
ret = false;
goto exit;
}
@@ -93,9 +92,9 @@ u8 rtw_do_join(struct adapter *padapter)
pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
- pibss = padapter->registrypriv.dev_network.MacAddress;
+ pibss = padapter->registrypriv.dev_network.mac_address;
- memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
rtw_update_registrypriv_dev_network(padapter);
@@ -135,70 +134,6 @@ exit:
return ret;
}
-u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
-{
- u8 status = _SUCCESS;
-
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- netdev_dbg(padapter->pnetdev, "set bssid:%pM\n", bssid);
-
- if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 && bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
- (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF && bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
- status = _FAIL;
- goto exit;
- }
-
- spin_lock_bh(&pmlmepriv->lock);
-
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
- goto handle_tkip_countermeasure;
- else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
- goto release_mlme_lock;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
- if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)
- goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
- } else {
- rtw_disassoc_cmd(padapter, 0, true);
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
- rtw_indicate_disconnect(padapter);
-
- rtw_free_assoc_resources(padapter, 1);
-
- if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
- _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- }
- }
- }
-
-handle_tkip_countermeasure:
- if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
- status = _FAIL;
- goto release_mlme_lock;
- }
-
- memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
- memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
- pmlmepriv->assoc_by_bssid = true;
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
- pmlmepriv->to_join = true;
- else
- status = rtw_do_join(padapter);
-
-release_mlme_lock:
- spin_unlock_bh(&pmlmepriv->lock);
-
-exit:
-
- return status;
-}
-
u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
{
u8 status = _SUCCESS;
@@ -207,7 +142,7 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
struct wlan_network *pnetwork = &pmlmepriv->cur_network;
netdev_dbg(padapter->pnetdev, "set ssid [%s] fw_state = 0x%08x\n",
- ssid->Ssid, get_fwstate(pmlmepriv));
+ ssid->ssid, get_fwstate(pmlmepriv));
if (padapter->hw_init_completed == false) {
status = _FAIL;
@@ -222,8 +157,8 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
goto release_mlme_lock;
if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
- if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
- (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
+ if ((pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length) &&
+ (!memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length))) {
if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)) {
if (rtw_is_same_ibss(padapter, pnetwork) == false) {
/* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
@@ -354,7 +289,7 @@ u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_network *cur_network = &pmlmepriv->cur_network;
- enum ndis_802_11_network_infrastructure *pold_state = &(cur_network->network.InfrastructureMode);
+ enum ndis_802_11_network_infrastructure *pold_state = &(cur_network->network.infrastructure_mode);
if (*pold_state != networktype) {
if (*pold_state == Ndis802_11APMode) {
@@ -450,10 +385,8 @@ u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_s
res = true;
} else {
- if (rtw_is_scan_deny(padapter)) {
- indicate_wx_scan_complete_event(padapter);
+ if (rtw_is_scan_deny(padapter))
return _SUCCESS;
- }
spin_lock_bh(&pmlmepriv->lock);
@@ -494,14 +427,14 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
struct security_priv *psecuritypriv = &(padapter->securitypriv);
u8 ret = _SUCCESS;
- keyid = wep->KeyIndex & 0x3fffffff;
+ keyid = wep->key_index & 0x3fffffff;
if (keyid >= 4) {
ret = false;
goto exit;
}
- switch (wep->KeyLength) {
+ switch (wep->key_length) {
case 5:
psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
break;
@@ -513,9 +446,9 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
break;
}
- memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength);
+ memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->key_material), wep->key_length);
- psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
+ psecuritypriv->dot11DefKeylen[keyid] = wep->key_length;
psecuritypriv->dot11PrivacyKeyIndex = keyid;
@@ -542,7 +475,6 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter)
struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
struct sta_info *psta = NULL;
u8 short_GI = 0;
- u8 rf_type = 0;
if ((check_fwstate(pmlmepriv, _FW_LINKED) != true)
&& (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true))
@@ -554,16 +486,13 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter)
short_GI = query_ra_short_GI(psta);
- if (IsSupportedHT(psta->wireless_mode)) {
- rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-
- max_rate = rtw_mcs_rate(rf_type,
- ((psta->bw_mode == CHANNEL_WIDTH_40)?1:0),
+ if (is_supported_ht(psta->wireless_mode)) {
+ max_rate = rtw_mcs_rate(psta->bw_mode == CHANNEL_WIDTH_40 ? 1 : 0,
short_GI,
psta->htpriv.ht_cap.mcs.rx_mask);
} else {
- while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
- rate = pcur_bss->SupportedRates[i]&0x7F;
+ while ((pcur_bss->supported_rates[i] != 0) && (pcur_bss->supported_rates[i] != 0xFF)) {
+ rate = pcur_bss->supported_rates[i]&0x7F;
if (rate > max_rate)
max_rate = rate;
i++;
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
index 2dd75e007239..ab6a24d70cc9 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
@@ -23,7 +23,7 @@ int rtw_init_mlme_priv(struct adapter *padapter)
pmlmepriv->pscanned = NULL;
pmlmepriv->fw_state = WIFI_STATION_STATE; /* Must sync with rtw_wdev_alloc() */
/* wdev->iftype = NL80211_IFTYPE_STATION */
- pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
+ pmlmepriv->cur_network.network.infrastructure_mode = Ndis802_11AutoUnknown;
pmlmepriv->scan_mode = SCAN_ACTIVE;/* 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
spin_lock_init(&pmlmepriv->lock);
@@ -245,7 +245,7 @@ struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr)
list_for_each(plist, phead) {
pnetwork = list_entry(plist, struct wlan_network, list);
- if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
+ if (!memcmp(addr, pnetwork->network.mac_address, ETH_ALEN))
break;
}
@@ -313,7 +313,7 @@ u16 rtw_get_capability(struct wlan_bssid_ex *bss)
{
__le16 val;
- memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->IEs), 2);
+ memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->ies), 2);
return le16_to_cpu(val);
}
@@ -363,10 +363,10 @@ int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
struct security_priv *psecuritypriv = &adapter->securitypriv;
if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
- (pnetwork->network.Privacy == 0))
+ (pnetwork->network.privacy == 0))
ret = false;
else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
- (pnetwork->network.Privacy == 1))
+ (pnetwork->network.privacy == 1))
ret = false;
else
ret = true;
@@ -377,8 +377,8 @@ int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
{
- return (a->Ssid.SsidLength == b->Ssid.SsidLength)
- && !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength);
+ return (a->ssid.ssid_length == b->ssid.ssid_length)
+ && !memcmp(a->ssid.ssid, b->ssid.ssid, a->ssid.ssid_length);
}
int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst, u8 feature)
@@ -389,16 +389,16 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst, u8 fea
if (rtw_bug_check(dst, src, &s_cap, &d_cap) == false)
return false;
- memcpy((u8 *)&tmps, rtw_get_capability_from_ie(src->IEs), 2);
- memcpy((u8 *)&tmpd, rtw_get_capability_from_ie(dst->IEs), 2);
+ memcpy((u8 *)&tmps, rtw_get_capability_from_ie(src->ies), 2);
+ memcpy((u8 *)&tmpd, rtw_get_capability_from_ie(dst->ies), 2);
s_cap = le16_to_cpu(tmps);
d_cap = le16_to_cpu(tmpd);
- return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
- /* (src->Configuration.DSConfig == dst->Configuration.DSConfig) && */
- ((!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN))) &&
- ((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength))) &&
+ return (src->ssid.ssid_length == dst->ssid.ssid_length) &&
+ /* (src->configuration.ds_config == dst->configuration.ds_config) && */
+ ((!memcmp(src->mac_address, dst->mac_address, ETH_ALEN))) &&
+ ((!memcmp(src->ssid.ssid, dst->ssid.ssid, src->ssid.ssid_length))) &&
((s_cap & WLAN_CAPABILITY_IBSS) ==
(d_cap & WLAN_CAPABILITY_IBSS)) &&
((s_cap & WLAN_CAPABILITY_ESS) ==
@@ -450,9 +450,9 @@ struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
struct adapter *padapter, bool update_ie)
{
- long rssi_ori = dst->Rssi;
+ long rssi_ori = dst->rssi;
- u8 sq_smp = src->PhyInfo.SignalQuality;
+ u8 sq_smp = src->phy_info.signal_quality;
u8 ss_final;
u8 sq_final;
@@ -465,32 +465,32 @@ void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
sq_final = padapter->recvpriv.signal_qual;
/* the rssi value here is undecorated, and will be used for antenna diversity */
if (sq_smp != 101) /* from the right channel */
- rssi_final = (src->Rssi+dst->Rssi*4)/5;
+ rssi_final = (src->rssi+dst->rssi*4)/5;
else
rssi_final = rssi_ori;
} else {
if (sq_smp != 101) { /* from the right channel */
- ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
- sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
- rssi_final = (src->Rssi+dst->Rssi*4)/5;
+ ss_final = ((u32)(src->phy_info.signal_strength)+(u32)(dst->phy_info.signal_strength)*4)/5;
+ sq_final = ((u32)(src->phy_info.signal_quality)+(u32)(dst->phy_info.signal_quality)*4)/5;
+ rssi_final = (src->rssi+dst->rssi*4)/5;
} else {
/* bss info not receiving from the right channel, use the original RX signal infos */
- ss_final = dst->PhyInfo.SignalStrength;
- sq_final = dst->PhyInfo.SignalQuality;
- rssi_final = dst->Rssi;
+ ss_final = dst->phy_info.signal_strength;
+ sq_final = dst->phy_info.signal_quality;
+ rssi_final = dst->rssi;
}
}
if (update_ie) {
- dst->Reserved[0] = src->Reserved[0];
- dst->Reserved[1] = src->Reserved[1];
+ dst->reserved[0] = src->reserved[0];
+ dst->reserved[1] = src->reserved[1];
memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
}
- dst->PhyInfo.SignalStrength = ss_final;
- dst->PhyInfo.SignalQuality = sq_final;
- dst->Rssi = rssi_final;
+ dst->phy_info.signal_strength = ss_final;
+ dst->phy_info.signal_quality = sq_final;
+ dst->rssi = rssi_final;
}
static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
@@ -503,11 +503,11 @@ static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex
&(pmlmepriv->cur_network.network));
if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) && (is_same_network(&(pmlmepriv->cur_network.network), pnetwork, 0))) {
- /* if (pmlmepriv->cur_network.network.IELength<= pnetwork->IELength) */
+ /* if (pmlmepriv->cur_network.network.ie_length<= pnetwork->ie_length) */
{
update_network(&(pmlmepriv->cur_network.network), pnetwork, adapter, true);
- rtw_update_protection(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof(struct ndis_802_11_fix_ie),
- pmlmepriv->cur_network.network.IELength);
+ rtw_update_protection(adapter, (pmlmepriv->cur_network.network.ies) + sizeof(struct ndis_802_11_fix_ie),
+ pmlmepriv->cur_network.network.ie_length);
}
}
}
@@ -568,8 +568,8 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
pnetwork->join_res = 0;
/* bss info not receiving from the right channel */
- if (pnetwork->network.PhyInfo.SignalQuality == 101)
- pnetwork->network.PhyInfo.SignalQuality = 0;
+ if (pnetwork->network.phy_info.signal_quality == 101)
+ pnetwork->network.phy_info.signal_quality = 0;
} else {
/* Otherwise just pull from the free list */
@@ -579,14 +579,14 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
goto exit;
bssid_ex_sz = get_wlan_bssid_ex_sz(target);
- target->Length = bssid_ex_sz;
+ target->length = bssid_ex_sz;
memcpy(&(pnetwork->network), target, bssid_ex_sz);
pnetwork->last_scanned = jiffies;
/* bss info not receiving from the right channel */
- if (pnetwork->network.PhyInfo.SignalQuality == 101)
- pnetwork->network.PhyInfo.SignalQuality = 0;
+ if (pnetwork->network.phy_info.signal_quality == 101)
+ pnetwork->network.phy_info.signal_quality = 0;
list_add_tail(&(pnetwork->list), &(queue->queue));
@@ -600,14 +600,13 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
pnetwork->last_scanned = jiffies;
- /* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
- if ((pnetwork->network.IELength > target->IELength) && (target->Reserved[0] == 1))
+ /* target.reserved[0]== 1, means that scanned network is a bcn frame. */
+ if (pnetwork->network.ie_length > target->ie_length && target->reserved[0] == 1)
update_ie = false;
/* probe resp(3) > beacon(1) > probe req(2) */
- if ((target->Reserved[0] != 2) &&
- (target->Reserved[0] >= pnetwork->network.Reserved[0])
- ) {
+ if (target->reserved[0] != 2 &&
+ target->reserved[0] >= pnetwork->network.reserved[0]) {
update_ie = true;
} else {
update_ie = false;
@@ -654,10 +653,10 @@ int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwor
int bselected = true;
desired_encmode = psecuritypriv->ndisencryptstatus;
- privacy = pnetwork->network.Privacy;
+ privacy = pnetwork->network.privacy;
if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
- if (rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen))
+ if (rtw_get_wps_ie(pnetwork->network.ies+_FIXED_IE_LENGTH_, pnetwork->network.ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen))
return true;
else
return false;
@@ -671,7 +670,7 @@ int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwor
bselected = false;
if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
- p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_));
+ p = rtw_get_ie(pnetwork->network.ies + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len, (pnetwork->network.ie_length - _BEACON_IE_OFFSET_));
if (p && ie_len > 0)
bselected = true;
else
@@ -683,7 +682,7 @@ int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwor
bselected = false;
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
- if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
+ if (pnetwork->network.infrastructure_mode != pmlmepriv->cur_network.network.infrastructure_mode)
bselected = false;
}
@@ -711,14 +710,14 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
/* update IBSS_network 's timestamp */
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) {
- if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress), pnetwork->MacAddress, ETH_ALEN)) {
+ if (!memcmp(&(pmlmepriv->cur_network.network.mac_address), pnetwork->mac_address, ETH_ALEN)) {
struct wlan_network *ibss_wlan = NULL;
- memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
+ memcpy(pmlmepriv->cur_network.network.ies, pnetwork->ies, 8);
spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
- ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->MacAddress);
+ ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->mac_address);
if (ibss_wlan) {
- memcpy(ibss_wlan->network.IEs, pnetwork->IEs, 8);
+ memcpy(ibss_wlan->network.ies, pnetwork->ies, 8);
spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
goto exit;
}
@@ -728,8 +727,8 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
/* lock pmlmepriv->lock when you accessing network_q */
if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false) {
- if (pnetwork->Ssid.Ssid[0] == 0)
- pnetwork->Ssid.SsidLength = 0;
+ if (pnetwork->ssid.ssid[0] == 0)
+ pnetwork->ssid.ssid_length = 0;
rtw_add_network(adapter, pnetwork);
}
@@ -766,12 +765,12 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
} else {
u8 ret = _SUCCESS;
struct wlan_bssid_ex *pdev_network = &(adapter->registrypriv.dev_network);
- u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
+ u8 *pibss = adapter->registrypriv.dev_network.mac_address;
/* pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;because don't set assoc_timer */
_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
- memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
rtw_update_registrypriv_dev_network(adapter);
rtw_generate_random_ibss(pibss);
@@ -818,7 +817,7 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
&& check_fwstate(pmlmepriv, _FW_LINKED)) {
if (rtw_select_roaming_candidate(pmlmepriv) == _SUCCESS) {
- receive_disconnect(adapter, pmlmepriv->cur_network.network.MacAddress
+ receive_disconnect(adapter, pmlmepriv->cur_network.network.mac_address
, WLAN_REASON_ACTIVE_ROAM);
}
}
@@ -882,7 +881,7 @@ static void find_network(struct adapter *adapter)
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
struct wlan_network *tgt_network = &pmlmepriv->cur_network;
- pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.mac_address);
if (pwlan)
pwlan->fixed = false;
@@ -905,7 +904,7 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
struct sta_info *psta;
- psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress);
+ psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.mac_address);
spin_lock_bh(&(pstapriv->sta_hash_lock));
rtw_free_stainfo(adapter, psta);
@@ -1025,9 +1024,9 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
struct sta_priv *pstapriv = &padapter->stapriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress);
+ psta = rtw_get_stainfo(pstapriv, pnetwork->network.mac_address);
if (!psta)
- psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
+ psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.mac_address);
if (psta) { /* update ptarget_sta */
@@ -1036,8 +1035,8 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
update_sta_info(padapter, psta);
/* update station supportRate */
- psta->bssratelen = rtw_get_rateset_len(pnetwork->network.SupportedRates);
- memcpy(psta->bssrateset, pnetwork->network.SupportedRates, psta->bssratelen);
+ psta->bssratelen = rtw_get_rateset_len(pnetwork->network.supported_rates);
+ memcpy(psta->bssrateset, pnetwork->network.supported_rates, psta->bssratelen);
rtw_hal_update_sta_rate_mask(padapter, psta);
psta->wireless_mode = pmlmeext->cur_wireless_mode;
@@ -1111,24 +1110,24 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
struct wlan_network *cur_network = &(pmlmepriv->cur_network);
/* why not use ptarget_wlan?? */
- memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
- /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
- cur_network->network.IELength = ptarget_wlan->network.IELength;
- memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
+ memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.length);
+ /* some ies in pnetwork is wrong, so we should use ptarget_wlan ies */
+ cur_network->network.ie_length = ptarget_wlan->network.ie_length;
+ memcpy(&cur_network->network.ies[0], &ptarget_wlan->network.ies[0], MAX_IE_SZ);
cur_network->aid = pnetwork->join_res;
rtw_set_signal_stat_timer(&padapter->recvpriv);
- padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
- padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
- /* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
- padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
+ padapter->recvpriv.signal_strength = ptarget_wlan->network.phy_info.signal_strength;
+ padapter->recvpriv.signal_qual = ptarget_wlan->network.phy_info.signal_quality;
+ /* the ptarget_wlan->network.rssi is raw data, we use ptarget_wlan->network.phy_info.signal_strength instead (has scaled) */
+ padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.phy_info.signal_strength);
rtw_set_signal_stat_timer(&padapter->recvpriv);
/* update fw_state will clr _FW_UNDER_LINKING here indirectly */
- switch (pnetwork->network.InfrastructureMode) {
+ switch (pnetwork->network.infrastructure_mode) {
case Ndis802_11Infrastructure:
if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
@@ -1145,10 +1144,10 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
break;
}
- rtw_update_protection(padapter, (cur_network->network.IEs) + sizeof(struct ndis_802_11_fix_ie),
- (cur_network->network.IELength));
+ rtw_update_protection(padapter, (cur_network->network.ies) + sizeof(struct ndis_802_11_fix_ie),
+ (cur_network->network.ie_length));
- rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength, (u8) cur_network->network.Configuration.DSConfig);
+ rtw_update_ht_cap(padapter, cur_network->network.ies, cur_network->network.ie_length, (u8) cur_network->network.configuration.ds_config);
}
/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
@@ -1172,10 +1171,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
rtw_get_encrypt_decrypt_from_registrypriv(adapter);
- the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
+ the_same_macaddr = !memcmp(pnetwork->network.mac_address, cur_network->network.mac_address, ETH_ALEN);
- pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
- if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
+ pnetwork->network.length = get_wlan_bssid_ex_sz(&pnetwork->network);
+ if (pnetwork->network.length > sizeof(struct wlan_bssid_ex))
return;
spin_lock_bh(&pmlmepriv->lock);
@@ -1190,17 +1189,17 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
/* s1. find ptarget_wlan */
if (check_fwstate(pmlmepriv, _FW_LINKED)) {
if (the_same_macaddr) {
- ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.mac_address);
} else {
- pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+ pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.mac_address);
if (pcur_wlan)
pcur_wlan->fixed = false;
- pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
+ pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.mac_address);
if (pcur_sta)
rtw_free_stainfo(adapter, pcur_sta);
- ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.mac_address);
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
if (ptarget_wlan)
ptarget_wlan->fixed = true;
@@ -1390,7 +1389,7 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
if (adapter->stapriv.asoc_sta_count == 2) {
spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
- ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.mac_address);
pmlmepriv->cur_network_scanned = ptarget_wlan;
if (ptarget_wlan)
ptarget_wlan->fixed = true;
@@ -1470,7 +1469,7 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
/* remove the network entry in scanned_queue */
- pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.mac_address);
if (pwlan) {
pwlan->fixed = false;
rtw_free_network_nolock(adapter, pwlan);
@@ -1491,7 +1490,7 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
/* free old ibss network */
/* pwlan = rtw_find_network(&pmlmepriv->scanned_queue, pstadel->macaddr); */
- pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.mac_address);
if (pwlan) {
pwlan->fixed = false;
rtw_free_network_nolock(adapter, pwlan);
@@ -1499,11 +1498,11 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
/* re-create ibss */
pdev_network = &(adapter->registrypriv.dev_network);
- pibss = adapter->registrypriv.dev_network.MacAddress;
+ pibss = adapter->registrypriv.dev_network.mac_address;
memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
- memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
rtw_update_registrypriv_dev_network(adapter);
@@ -1722,7 +1721,7 @@ static int rtw_check_roaming_candidate(struct mlme_priv *mlme
/* got specific addr to roam */
if (!is_zero_mac_addr(mlme->roam_tgt_addr)) {
- if (!memcmp(mlme->roam_tgt_addr, competitor->network.MacAddress, ETH_ALEN))
+ if (!memcmp(mlme->roam_tgt_addr, competitor->network.mac_address, ETH_ALEN))
goto update;
else
goto exit;
@@ -1730,10 +1729,10 @@ static int rtw_check_roaming_candidate(struct mlme_priv *mlme
if (jiffies_to_msecs(jiffies - competitor->last_scanned) >= mlme->roam_scanr_exp_ms)
goto exit;
- if (competitor->network.Rssi - mlme->cur_network_scanned->network.Rssi < mlme->roam_rssi_diff_th)
+ if (competitor->network.rssi - mlme->cur_network_scanned->network.rssi < mlme->roam_rssi_diff_th)
goto exit;
- if (*candidate && (*candidate)->network.Rssi >= competitor->network.Rssi)
+ if (*candidate && (*candidate)->network.rssi >= competitor->network.rssi)
goto exit;
update:
@@ -1775,7 +1774,7 @@ int rtw_select_roaming_candidate(struct mlme_priv *mlme)
} else {
mlme->roam_network = candidate;
- if (!memcmp(candidate->network.MacAddress, mlme->roam_tgt_addr, ETH_ALEN))
+ if (!memcmp(candidate->network.mac_address, mlme->roam_tgt_addr, ETH_ALEN))
eth_zero_addr(mlme->roam_tgt_addr);
}
@@ -1799,14 +1798,14 @@ static int rtw_check_join_candidate(struct mlme_priv *mlme
/* check bssid, if needed */
if (mlme->assoc_by_bssid) {
- if (memcmp(competitor->network.MacAddress, mlme->assoc_bssid, ETH_ALEN))
+ if (memcmp(competitor->network.mac_address, mlme->assoc_bssid, ETH_ALEN))
goto exit;
}
/* check ssid, if needed */
- if (mlme->assoc_ssid.Ssid[0] && mlme->assoc_ssid.SsidLength) {
- if (competitor->network.Ssid.SsidLength != mlme->assoc_ssid.SsidLength
- || memcmp(competitor->network.Ssid.Ssid, mlme->assoc_ssid.Ssid, mlme->assoc_ssid.SsidLength)
+ if (mlme->assoc_ssid.ssid[0] && mlme->assoc_ssid.ssid_length) {
+ if (competitor->network.ssid.ssid_length != mlme->assoc_ssid.ssid_length
+ || memcmp(competitor->network.ssid.ssid, mlme->assoc_ssid.ssid, mlme->assoc_ssid.ssid_length)
)
goto exit;
}
@@ -1821,7 +1820,7 @@ static int rtw_check_join_candidate(struct mlme_priv *mlme
goto exit;
}
- if (*candidate == NULL || (*candidate)->network.Rssi < competitor->network.Rssi) {
+ if (*candidate == NULL || (*candidate)->network.rssi < competitor->network.rssi) {
*candidate = competitor;
updated = true;
}
@@ -2001,7 +2000,7 @@ exit:
return res;
}
-/* adjust IEs for rtw_joinbss_cmd in WMM */
+/* adjust ies for rtw_joinbss_cmd in WMM */
int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
{
unsigned int ielength = 0;
@@ -2148,16 +2147,12 @@ void rtw_init_registrypriv_dev_network(struct adapter *adapter)
struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
u8 *myhwaddr = myid(peepriv);
- memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
+ memcpy(pdev_network->mac_address, myhwaddr, ETH_ALEN);
- memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pdev_network->ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
- pdev_network->Configuration.Length = sizeof(struct ndis_802_11_conf);
- pdev_network->Configuration.BeaconPeriod = 100;
- pdev_network->Configuration.FHConfig.Length = 0;
- pdev_network->Configuration.FHConfig.HopPattern = 0;
- pdev_network->Configuration.FHConfig.HopSet = 0;
- pdev_network->Configuration.FHConfig.DwellTime = 0;
+ pdev_network->configuration.length = sizeof(struct ndis_802_11_conf);
+ pdev_network->configuration.beacon_period = 100;
}
void rtw_update_registrypriv_dev_network(struct adapter *adapter)
@@ -2169,45 +2164,45 @@ void rtw_update_registrypriv_dev_network(struct adapter *adapter)
struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
/* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
- pdev_network->Privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0) ; /* adhoc no 802.1x */
+ pdev_network->privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0) ; /* adhoc no 802.1x */
- pdev_network->Rssi = 0;
+ pdev_network->rssi = 0;
switch (pregistrypriv->wireless_mode) {
case WIRELESS_11B:
- pdev_network->NetworkTypeInUse = (Ndis802_11DS);
+ pdev_network->network_type_in_use = (Ndis802_11DS);
break;
case WIRELESS_11G:
case WIRELESS_11BG:
case WIRELESS_11_24N:
case WIRELESS_11G_24N:
case WIRELESS_11BG_24N:
- pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
+ pdev_network->network_type_in_use = (Ndis802_11OFDM24);
break;
default:
/* TODO */
break;
}
- pdev_network->Configuration.DSConfig = (pregistrypriv->channel);
+ pdev_network->configuration.ds_config = (pregistrypriv->channel);
- if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
- pdev_network->Configuration.ATIMWindow = (0);
+ if (cur_network->network.infrastructure_mode == Ndis802_11IBSS)
+ pdev_network->configuration.atim_window = (0);
- pdev_network->InfrastructureMode = (cur_network->network.InfrastructureMode);
+ pdev_network->infrastructure_mode = (cur_network->network.infrastructure_mode);
/* 1. Supported rates */
/* 2. IE */
- /* rtw_set_supported_rate(pdev_network->SupportedRates, pregistrypriv->wireless_mode) ; will be called in rtw_generate_ie */
+ /* rtw_set_supported_rate(pdev_network->supported_rates, pregistrypriv->wireless_mode) ; will be called in rtw_generate_ie */
sz = rtw_generate_ie(pregistrypriv);
- pdev_network->IELength = sz;
+ pdev_network->ie_length = sz;
- pdev_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
+ pdev_network->length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
- /* notes: translate IELength & Length after assign the Length to cmdsz in createbss_cmd(); */
- /* pdev_network->IELength = cpu_to_le32(sz); */
+ /* notes: translate ie_length & length after assign the length to cmdsz in createbss_cmd(); */
+ /* pdev_network->ie_length = cpu_to_le32(sz); */
}
void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
@@ -2318,7 +2313,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor;
unsigned char *p;
struct ieee80211_ht_cap ht_capie;
- u8 cbw40_enable = 0, stbc_rx_enable = 0, rf_type = 0, operation_bw = 0;
+ u8 cbw40_enable = 0, stbc_rx_enable = 0, operation_bw = 0;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct ht_priv *phtpriv = &pmlmepriv->htpriv;
@@ -2394,28 +2389,13 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
}
/* fill default supported_mcs_set */
- memcpy(ht_capie.mcs.rx_mask, pmlmeext->default_supported_mcs_set, 16);
+ memcpy(&ht_capie.mcs, pmlmeext->default_supported_mcs_set, 16);
/* update default supported_mcs_set */
- rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ if (stbc_rx_enable)
+ ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_RX_STBC_1R);/* RX STBC One spatial stream */
- switch (rf_type) {
- case RF_1T1R:
- if (stbc_rx_enable)
- ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_RX_STBC_1R);/* RX STBC One spatial stream */
-
- set_mcs_rate_by_mask(ht_capie.mcs.rx_mask, MCS_RATE_1R);
- break;
-
- case RF_2T2R:
- case RF_1T2R:
- default:
- if (stbc_rx_enable)
- ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_RX_STBC_2R);/* RX STBC two spatial stream */
-
- set_mcs_rate_by_mask(ht_capie.mcs.rx_mask, MCS_RATE_2R);
- break;
- }
+ set_mcs_rate_by_mask(ht_capie.mcs.rx_mask, MCS_RATE_1R);
{
u32 rx_packet_offset, max_recvbuf_sz;
@@ -2515,24 +2495,13 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channe
(le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) &
BIT(1)) && (pmlmeinfo->HT_info.infos[0] & BIT(2))) {
int i;
- u8 rf_type;
-
- rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
/* update the MCS set */
for (i = 0; i < 16; i++)
pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
/* update the MCS rates */
- switch (rf_type) {
- case RF_1T1R:
- case RF_1T2R:
- set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
- break;
- case RF_2T2R:
- default:
- set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
- }
+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
/* switch to the 40M Hz mode according to the AP */
/* pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; */
@@ -2648,7 +2617,7 @@ void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
int do_join_r;
if (0 < rtw_to_roam(padapter)) {
- memcpy(&pmlmepriv->assoc_ssid, &cur_network->network.Ssid, sizeof(struct ndis_802_11_ssid));
+ memcpy(&pmlmepriv->assoc_ssid, &cur_network->network.ssid, sizeof(struct ndis_802_11_ssid));
pmlmepriv->assoc_by_bssid = false;
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
index c128d462c6c7..375d2a742dd2 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
@@ -343,7 +343,7 @@ static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_c
if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
return chanset_size;
- if (IsSupported24G(padapter->registrypriv.wireless_mode)) {
+ if (is_supported_24g(padapter->registrypriv.wireless_mode)) {
b2_4GBand = true;
if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
@@ -538,7 +538,7 @@ unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
if (is_valid_p2p_probereq)
goto _issue_probersp;
- if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))
+ if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->ssid.ssid, cur->ssid.ssid_length))
|| (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
)
return _SUCCESS;
@@ -634,7 +634,7 @@ unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
netdev_dbg(padapter->pnetdev,
"ap has changed, disconnect now\n ");
receive_disconnect(padapter,
- pmlmeinfo->network.MacAddress, 0);
+ pmlmeinfo->network.mac_address, 0);
return _SUCCESS;
}
/* update WMM, ERP in the beacon */
@@ -1022,10 +1022,10 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
goto OnAssocReqFail;
} else {
/* check if ssid match */
- if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
+ if (memcmp((void *)(p+2), cur->ssid.ssid, cur->ssid.ssid_length))
status = WLAN_STATUS_CHALLENGE_FAIL;
- if (ie_len != cur->Ssid.SsidLength)
+ if (ie_len != cur->ssid.ssid_length)
status = WLAN_STATUS_CHALLENGE_FAIL;
}
@@ -1428,7 +1428,7 @@ unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
pIE = (struct ndis_80211_var_ie *)(pframe + i);
- switch (pIE->ElementID) {
+ switch (pIE->element_id) {
case WLAN_EID_VENDOR_SPECIFIC:
if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
WMM_param_handler(padapter, pIE);
@@ -1450,14 +1450,14 @@ unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
break;
}
- i += (pIE->Length + 2);
+ i += (pIE->length + 2);
}
pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
/* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
- UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
+ UpdateBrateTbl(padapter, pmlmeinfo->network.supported_rates);
report_assoc_result:
if (res > 0) {
@@ -2181,12 +2181,12 @@ void issue_beacon(struct adapter *padapter, int timeout_ms)
{
int len_diff;
- memcpy(pframe, cur_network->IEs, cur_network->IELength);
+ memcpy(pframe, cur_network->ies, cur_network->ie_length);
len_diff = update_hidden_ssid(pframe+_BEACON_IE_OFFSET_,
- cur_network->IELength-_BEACON_IE_OFFSET_,
+ cur_network->ie_length-_BEACON_IE_OFFSET_,
pmlmeinfo->hidden_ssid_mode);
- pframe += (cur_network->IELength+len_diff);
- pattrib->pktlen += (cur_network->IELength+len_diff);
+ pframe += (cur_network->ie_length+len_diff);
+ pattrib->pktlen += (cur_network->ie_length+len_diff);
}
{
@@ -2217,34 +2217,34 @@ void issue_beacon(struct adapter *padapter, int timeout_ms)
/* beacon interval: 2 bytes */
- memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
pframe += 2;
pattrib->pktlen += 2;
/* capability info: 2 bytes */
- memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
pframe += 2;
pattrib->pktlen += 2;
/* SSID */
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
/* supported rates... */
- rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
+ rate_len = rtw_get_rateset_len(cur_network->supported_rates);
+ pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pattrib->pktlen);
/* DS parameter set */
- pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &pattrib->pktlen);
/* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
{
u8 erpinfo = 0;
u32 ATIMWindow;
/* IBSS Parameter Set... */
- /* ATIMWindow = cur->Configuration.ATIMWindow; */
+ /* ATIMWindow = cur->configuration.ATIMWindow; */
ATIMWindow = 0;
pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
@@ -2255,7 +2255,7 @@ void issue_beacon(struct adapter *padapter, int timeout_ms)
/* EXTERNDED SUPPORTED RATE */
if (rate_len > 8) {
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->supported_rates + 8), &pattrib->pktlen);
}
@@ -2314,7 +2314,7 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
pwlanhdr = (struct ieee80211_hdr *)pframe;
mac = myid(&(padapter->eeprompriv));
- bssid = cur_network->MacAddress;
+ bssid = cur_network->mac_address;
fctrl = &(pwlanhdr->frame_control);
*(fctrl) = 0;
@@ -2331,24 +2331,24 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
pframe += pattrib->hdrlen;
- if (cur_network->IELength > MAX_IE_SZ)
+ if (cur_network->ie_length > MAX_IE_SZ)
return;
if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
- pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
+ pwps_ie = rtw_get_wps_ie(cur_network->ies+_FIXED_IE_LENGTH_, cur_network->ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
/* inerset & update wps_probe_resp_ie */
if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
uint wps_offset, remainder_ielen;
u8 *premainder_ie;
- wps_offset = (uint)(pwps_ie - cur_network->IEs);
+ wps_offset = (uint)(pwps_ie - cur_network->ies);
premainder_ie = pwps_ie + wps_ielen;
- remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
+ remainder_ielen = cur_network->ie_length - wps_offset - wps_ielen;
- memcpy(pframe, cur_network->IEs, wps_offset);
+ memcpy(pframe, cur_network->ies, wps_offset);
pframe += wps_offset;
pattrib->pktlen += wps_offset;
@@ -2365,12 +2365,12 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
pattrib->pktlen += remainder_ielen;
}
} else {
- memcpy(pframe, cur_network->IEs, cur_network->IELength);
- pframe += cur_network->IELength;
- pattrib->pktlen += cur_network->IELength;
+ memcpy(pframe, cur_network->ies, cur_network->ie_length);
+ pframe += cur_network->ie_length;
+ pattrib->pktlen += cur_network->ie_length;
}
- /* retrieve SSID IE from cur_network->Ssid */
+ /* retrieve SSID IE from cur_network->ssid */
{
u8 *ssid_ie;
signed int ssid_ielen;
@@ -2385,9 +2385,9 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, WLAN_EID_SSID, &ssid_ielen,
(pframe-ies)-_FIXED_IE_LENGTH_);
- ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
+ ssid_ielen_diff = cur_network->ssid.ssid_length - ssid_ielen;
- if (ssid_ie && cur_network->Ssid.SsidLength) {
+ if (ssid_ie && cur_network->ssid.ssid_length) {
uint remainder_ielen;
u8 *remainder_ie;
@@ -2403,8 +2403,8 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
memcpy(buf, remainder_ie, remainder_ielen);
memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
- *(ssid_ie+1) = cur_network->Ssid.SsidLength;
- memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
+ *(ssid_ie+1) = cur_network->ssid.ssid_length;
+ memcpy(ssid_ie+2, cur_network->ssid.ssid, cur_network->ssid.ssid_length);
pframe += ssid_ielen_diff;
pattrib->pktlen += ssid_ielen_diff;
@@ -2418,14 +2418,14 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
/* beacon interval: 2 bytes */
- memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
pframe += 2;
pattrib->pktlen += 2;
/* capability info: 2 bytes */
- memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
pframe += 2;
pattrib->pktlen += 2;
@@ -2433,20 +2433,20 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
/* below for ad-hoc mode */
/* SSID */
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
/* supported rates... */
- rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
+ rate_len = rtw_get_rateset_len(cur_network->supported_rates);
+ pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pattrib->pktlen);
/* DS parameter set */
- pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &pattrib->pktlen);
if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
u8 erpinfo = 0;
u32 ATIMWindow;
/* IBSS Parameter Set... */
- /* ATIMWindow = cur->Configuration.ATIMWindow; */
+ /* ATIMWindow = cur->configuration.ATIMWindow; */
ATIMWindow = 0;
pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
@@ -2457,7 +2457,7 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
/* EXTERNDED SUPPORTED RATE */
if (rate_len > 8) {
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->supported_rates + 8), &pattrib->pktlen);
}
@@ -2530,7 +2530,7 @@ static int _issue_probereq(struct adapter *padapter,
pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
if (pssid)
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
+ pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->ssid_length, pssid->ssid, &(pattrib->pktlen));
else
pframe = rtw_set_ie(pframe, WLAN_EID_SSID, 0, NULL, &(pattrib->pktlen));
@@ -2748,7 +2748,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
- u8 *ie = pnetwork->IEs;
+ u8 *ie = pnetwork->ies;
__le16 lestatus, le_tmp;
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
@@ -2807,7 +2807,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i
/* FILL HT CAP INFO IE */
/* p = hostapd_eid_ht_capabilities_info(hapd, p); */
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
if (pbuf && ie_len > 0) {
memcpy(pframe, pbuf, ie_len+2);
pframe += (ie_len+2);
@@ -2816,7 +2816,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i
/* FILL HT ADD INFO IE */
/* p = hostapd_eid_ht_operation(hapd, p); */
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
if (pbuf && ie_len > 0) {
memcpy(pframe, pbuf, ie_len+2);
pframe += (ie_len+2);
@@ -2831,7 +2831,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i
unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
- pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
+ pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
memcpy(pframe, pbuf, ie_len+2);
pframe += (ie_len+2);
@@ -2910,7 +2910,7 @@ void issue_assocreq(struct adapter *padapter)
pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
/* caps */
- memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
+ memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.ies), 2);
pframe += 2;
pattrib->pktlen += 2;
@@ -2923,7 +2923,7 @@ void issue_assocreq(struct adapter *padapter)
pattrib->pktlen += 2;
/* SSID */
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
+ pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pmlmeinfo->network.ssid.ssid_length, pmlmeinfo->network.ssid.ssid, &(pattrib->pktlen));
/* supported rate & extended supported rate */
@@ -2938,27 +2938,27 @@ void issue_assocreq(struct adapter *padapter)
/* */
for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
- if (pmlmeinfo->network.SupportedRates[i] == 0)
+ if (pmlmeinfo->network.supported_rates[i] == 0)
break;
}
for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
- if (pmlmeinfo->network.SupportedRates[i] == 0)
+ if (pmlmeinfo->network.supported_rates[i] == 0)
break;
/* Check if the AP's supported rates are also supported by STA. */
for (j = 0; j < sta_bssrate_len; j++) {
/* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
- if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)
+ if ((pmlmeinfo->network.supported_rates[i] | IEEE80211_BASIC_RATE_MASK)
== (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
break;
}
if (j != sta_bssrate_len)
/* the rate is supported by STA */
- bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
+ bssrate[index++] = pmlmeinfo->network.supported_rates[i];
}
bssrate_len = index;
@@ -2977,15 +2977,15 @@ void issue_assocreq(struct adapter *padapter)
pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen));
/* vendor specific IE, such as WPA, WMM, WPS */
- for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) {
- pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i);
+ for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) {
+ pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i);
- switch (pIE->ElementID) {
+ switch (pIE->element_id) {
case WLAN_EID_VENDOR_SPECIFIC:
if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
(!memcmp(pIE->data, WMM_OUI, 4)) ||
(!memcmp(pIE->data, WPS_OUI, 4))) {
- vs_ie_length = pIE->Length;
+ vs_ie_length = pIE->length;
if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) {
/* Commented by Kurt 20110629
* In some older APs, WPS handshake
@@ -3001,26 +3001,26 @@ void issue_assocreq(struct adapter *padapter)
break;
case WLAN_EID_RSN:
- pframe = rtw_set_ie(pframe, WLAN_EID_RSN, pIE->Length, pIE->data, &(pattrib->pktlen));
+ pframe = rtw_set_ie(pframe, WLAN_EID_RSN, pIE->length, pIE->data, &(pattrib->pktlen));
break;
case WLAN_EID_HT_CAPABILITY:
if (padapter->mlmepriv.htpriv.ht_option) {
if (!(is_ap_in_tkip(padapter))) {
memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
- pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
+ pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, pIE->length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
}
}
break;
case WLAN_EID_EXT_CAPABILITY:
if (padapter->mlmepriv.htpriv.ht_option)
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_CAPABILITY, pIE->Length, pIE->data, &(pattrib->pktlen));
+ pframe = rtw_set_ie(pframe, WLAN_EID_EXT_CAPABILITY, pIE->length, pIE->data, &(pattrib->pktlen));
break;
default:
break;
}
- i += (pIE->Length + 2);
+ i += (pIE->length + 2);
}
if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
@@ -3540,7 +3540,7 @@ void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned ch
le_tmp = cpu_to_le16(BA_timeout_value);
pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
- /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */
+ /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.mac_address)) != NULL) */
psta = rtw_get_stainfo(pstapriv, raddr);
if (psta) {
start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
@@ -3705,13 +3705,13 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter)
pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
- p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(pbss_network->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->ie_length - _FIXED_IE_LENGTH_);
if ((p == NULL) || (len == 0)) {/* non-HT */
- if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
+ if (pbss_network->configuration.ds_config <= 0)
continue;
- ICS[0][pbss_network->Configuration.DSConfig] = 1;
+ ICS[0][pbss_network->configuration.ds_config] = 1;
if (ICS[0][0] == 0)
ICS[0][0] = 1;
@@ -3876,7 +3876,7 @@ void site_survey(struct adapter *padapter)
int i;
for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
+ if (pmlmeext->sitesurvey_res.ssid[i].ssid_length) {
/* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
if (padapter->registrypriv.wifi_spec)
issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
@@ -3971,35 +3971,35 @@ u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, str
subtype = GetFrameSubType(pframe);
if (subtype == WIFI_BEACON) {
- bssid->Reserved[0] = 1;
+ bssid->reserved[0] = 1;
ie_offset = _BEACON_IE_OFFSET_;
} else {
/* FIXME : more type */
if (subtype == WIFI_PROBERSP) {
ie_offset = _PROBERSP_IE_OFFSET_;
- bssid->Reserved[0] = 3;
+ bssid->reserved[0] = 3;
} else if (subtype == WIFI_PROBEREQ) {
ie_offset = _PROBEREQ_IE_OFFSET_;
- bssid->Reserved[0] = 2;
+ bssid->reserved[0] = 2;
} else {
- bssid->Reserved[0] = 0;
+ bssid->reserved[0] = 0;
ie_offset = _FIXED_IE_LENGTH_;
}
}
- bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
+ bssid->length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
/* below is to copy the information element */
- bssid->IELength = len;
- memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
+ bssid->ie_length = len;
+ memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
/* get the signal strength */
- bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /* in dBM.raw data */
- bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
- bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
+ bssid->rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /* in dBM.raw data */
+ bssid->phy_info.signal_quality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
+ bssid->phy_info.signal_strength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
/* checking SSID */
- p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_SSID, &len, bssid->IELength - ie_offset);
+ p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SSID, &len, bssid->ie_length - ie_offset);
if (!p)
return _FAIL;
@@ -4007,83 +4007,83 @@ u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, str
if (len > NDIS_802_11_LENGTH_SSID)
return _FAIL;
- memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
- bssid->Ssid.SsidLength = *(p + 1);
+ memcpy(bssid->ssid.ssid, (p + 2), *(p + 1));
+ bssid->ssid.ssid_length = *(p + 1);
} else
- bssid->Ssid.SsidLength = 0;
+ bssid->ssid.ssid_length = 0;
- memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+ memset(bssid->supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
/* checking rate info... */
i = 0;
- p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->IELength - ie_offset);
+ p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->ie_length - ie_offset);
if (p) {
if (len > NDIS_802_11_LENGTH_RATES_EX)
return _FAIL;
- memcpy(bssid->SupportedRates, (p + 2), len);
+ memcpy(bssid->supported_rates, (p + 2), len);
i = len;
}
- p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->IELength - ie_offset);
+ p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->ie_length - ie_offset);
if (p) {
if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
return _FAIL;
- memcpy(bssid->SupportedRates + i, (p + 2), len);
+ memcpy(bssid->supported_rates + i, (p + 2), len);
}
- bssid->NetworkTypeInUse = Ndis802_11OFDM24;
+ bssid->network_type_in_use = Ndis802_11OFDM24;
- if (bssid->IELength < 12)
+ if (bssid->ie_length < 12)
return _FAIL;
- /* Checking for DSConfig */
- p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->IELength - ie_offset);
+ /* Checking for ds_config */
+ p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->ie_length - ie_offset);
- bssid->Configuration.DSConfig = 0;
- bssid->Configuration.Length = 0;
+ bssid->configuration.ds_config = 0;
+ bssid->configuration.length = 0;
if (p) {
- bssid->Configuration.DSConfig = *(p + 2);
+ bssid->configuration.ds_config = *(p + 2);
} else {
/* In 5G, some ap do not have DSSET IE */
/* checking HT info for channel */
- p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->IELength - ie_offset);
+ p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - ie_offset);
if (p) {
struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
- bssid->Configuration.DSConfig = HT_info->primary_channel;
+ bssid->configuration.ds_config = HT_info->primary_channel;
} else { /* use current channel */
- bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
+ bssid->configuration.ds_config = rtw_get_oper_ch(padapter);
}
}
- memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
- bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
+ memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->ies), 2);
+ bssid->configuration.beacon_period = le32_to_cpu(le32_tmp);
val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
if (val16 & BIT(0)) {
- bssid->InfrastructureMode = Ndis802_11Infrastructure;
- memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
+ bssid->infrastructure_mode = Ndis802_11Infrastructure;
+ memcpy(bssid->mac_address, GetAddr2Ptr(pframe), ETH_ALEN);
} else {
- bssid->InfrastructureMode = Ndis802_11IBSS;
- memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
+ bssid->infrastructure_mode = Ndis802_11IBSS;
+ memcpy(bssid->mac_address, GetAddr3Ptr(pframe), ETH_ALEN);
}
if (val16 & BIT(4))
- bssid->Privacy = 1;
+ bssid->privacy = 1;
else
- bssid->Privacy = 0;
+ bssid->privacy = 0;
- bssid->Configuration.ATIMWindow = 0;
+ bssid->configuration.atim_window = 0;
/* 20/40 BSS Coexistence check */
if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) {
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->IELength - ie_offset);
+ p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->ie_length - ie_offset);
if (p && len > 0) {
struct HT_caps_element *pHT_caps;
@@ -4095,9 +4095,9 @@ u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, str
pmlmepriv->num_sta_no_ht++;
}
- /* mark bss info receiving from nearby channel as SignalQuality 101 */
- if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
- bssid->PhyInfo.SignalQuality = 101;
+ /* mark bss info receiving from nearby channel as signal_quality 101 */
+ if (bssid->configuration.ds_config != rtw_get_oper_ch(padapter))
+ bssid->phy_info.signal_quality = 101;
return _SUCCESS;
}
@@ -4111,7 +4111,7 @@ void start_create_ibss(struct adapter *padapter)
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
- pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
+ pmlmeext->cur_channel = (u8)pnetwork->configuration.ds_config;
pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
/* update wireless mode */
@@ -4141,7 +4141,7 @@ void start_create_ibss(struct adapter *padapter)
report_join_res(padapter, -1);
pmlmeinfo->state = WIFI_FW_NULL_STATE;
} else {
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.mac_address);
join_type = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
@@ -4187,7 +4187,7 @@ void start_clnt_join(struct adapter *padapter)
/* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
{
/* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
+ issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
}
/* here wait for receiving the beacon to start auth */
@@ -4302,7 +4302,7 @@ static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid
u8 noc; /* number of channel */
u8 j, k;
- ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ ie = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
if (!ie)
return;
if (len < 6)
@@ -4409,7 +4409,7 @@ static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid
}
/* If channel is used by AP, set channel scan type to active */
- channel = bssid->Configuration.DSConfig;
+ channel = bssid->configuration.ds_config;
chplan_new = pmlmeext->channel_set;
i = 0;
while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
@@ -4866,7 +4866,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
/* update IOT-related issue */
update_IOT_info(padapter);
- rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->supported_rates);
/* BCN interval */
rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
@@ -4883,7 +4883,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
/* Set cur_channel&cur_bwmode&cur_ch_offset */
set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
- psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
+ psta = rtw_get_stainfo(pstapriv, cur_network->mac_address);
if (psta) { /* only for infra. mode */
pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
@@ -5047,7 +5047,7 @@ void linked_status_chk(struct adapter *padapter)
/* Marked by Kurt 20130715 */
/* For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, so we could not check rx limit that strictly. */
/* todo: To check why we under miracast session, rx_chk would be false */
- psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
+ psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.mac_address);
if (psta) {
if (chk_ap_is_alive(padapter, psta) == false)
rx_chk = _FAIL;
@@ -5058,9 +5058,9 @@ void linked_status_chk(struct adapter *padapter)
{
if (rx_chk != _SUCCESS) {
if (pmlmeext->retry == 0) {
- issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
- issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
- issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
+ issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
+ issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
+ issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
}
}
@@ -5075,7 +5075,7 @@ void linked_status_chk(struct adapter *padapter)
netdev_dbg(padapter->pnetdev,
FUNC_ADPT_FMT " disconnect or roaming\n",
FUNC_ADPT_ARG(padapter));
- receive_disconnect(padapter, pmlmeinfo->network.MacAddress
+ receive_disconnect(padapter, pmlmeinfo->network.mac_address
, WLAN_REASON_EXPIRATION_CHK);
return;
}
@@ -5090,7 +5090,7 @@ void linked_status_chk(struct adapter *padapter)
pmlmeinfo->link_count = 0;
}
- } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
+ } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.mac_address)) != NULL) */
} else if (is_client_associated_to_ibss(padapter)) {
/* linked IBSS mode */
/* for each assoc list entry to check the rx pkt counter */
@@ -5301,7 +5301,7 @@ u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
}
/* below is for ad-hoc master */
- if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
+ if (pparm->network.infrastructure_mode == Ndis802_11IBSS) {
rtw_joinbss_reset(padapter);
pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
@@ -5328,13 +5328,13 @@ u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
/* clear CAM */
flush_all_cam_entry(padapter);
- memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
- pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
+ memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, ie_length));
+ pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
- if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
+ if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
return H2C_PARAMETERS_ERROR;
- memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
+ memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
start_create_ibss(padapter);
@@ -5361,7 +5361,7 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
/* check already connecting to AP or not */
if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
if (pmlmeinfo->state & WIFI_FW_STATION_STATE) {
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
+ issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
}
pmlmeinfo->state = WIFI_FW_NULL_STATE;
@@ -5393,25 +5393,25 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
/* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
pmlmeinfo->VHT_enable = 0;
- memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
- pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
+ memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, ie_length));
+ pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
- if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
+ if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
return H2C_PARAMETERS_ERROR;
- memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
+ memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
- pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
+ pmlmeext->cur_channel = (u8)pnetwork->configuration.ds_config;
pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
/* Check AP vendor to move rtw_joinbss_cmd() */
- /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */
+ /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->ies, pnetwork->ie_length); */
/* sizeof(struct ndis_802_11_fix_ie) */
- for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) {
- pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i);
+ for (i = _FIXED_IE_LENGTH_; i < pnetwork->ie_length;) {
+ pIE = (struct ndis_80211_var_ie *)(pnetwork->ies + i);
- switch (pIE->ElementID) {
+ switch (pIE->element_id) {
case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
if (!memcmp(pIE->data, WMM_OUI, 4))
WMM_param_handler(padapter, pIE);
@@ -5428,10 +5428,7 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
{
struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
- if (pnetwork->Configuration.DSConfig > 14) {
- if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20)
- cbw40_enable = 1;
- } else {
+ if (pnetwork->configuration.ds_config <= 14) {
if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
cbw40_enable = 1;
}
@@ -5460,7 +5457,7 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
break;
}
- i += (pIE->Length + 2);
+ i += (pIE->length + 2);
}
/* check channel, bandwidth, offset and switch */
@@ -5476,7 +5473,7 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
/* initialgain = 0x1E; */
/* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.mac_address);
join_type = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
@@ -5501,7 +5498,7 @@ u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
u8 val8;
if (is_client_associated_to_ap(padapter)) {
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
+ issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
}
if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
@@ -5592,11 +5589,11 @@ u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
pmlmeext->sitesurvey_res.channel_idx = 0;
for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (pparm->ssid[i].SsidLength) {
- memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
- pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
+ if (pparm->ssid[i].ssid_length) {
+ memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
+ pmlmeext->sitesurvey_res.ssid[i].ssid_length = pparm->ssid[i].ssid_length;
} else {
- pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
+ pmlmeext->sitesurvey_res.ssid[i].ssid_length = 0;
}
}
@@ -5822,10 +5819,10 @@ u8 set_tx_beacon_cmd(struct adapter *padapter)
memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
- len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_,
- ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_,
+ len_diff = update_hidden_ssid(ptxBeacon_parm->network.ies+_BEACON_IE_OFFSET_,
+ ptxBeacon_parm->network.ie_length-_BEACON_IE_OFFSET_,
pmlmeinfo->hidden_ssid_mode);
- ptxBeacon_parm->network.IELength += len_diff;
+ ptxBeacon_parm->network.ie_length += len_diff;
init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c
index d4c1725718d9..5b0a596eefb7 100644
--- a/drivers/staging/rtl8723bs/core/rtw_recv.c
+++ b/drivers/staging/rtl8723bs/core/rtw_recv.c
@@ -480,7 +480,7 @@ static union recv_frame *portctrl(struct adapter *adapter, union recv_frame *pre
prtnframe = precv_frame;
/* get ether_type */
- ptr = ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE;
+ ptr = ptr + pfhdr->attrib.hdrlen + pfhdr->attrib.iv_len + LLC_HEADER_LENGTH;
memcpy(&be_tmp, ptr, 2);
ether_type = ntohs(be_tmp);
@@ -1485,7 +1485,7 @@ static signed int validate_recv_frame(struct adapter *adapter, union recv_frame
/* dump eapol */
rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
/* get ether_type */
- memcpy(&eth_type, ptr + pattrib->hdrlen + pattrib->iv_len + LLC_HEADER_SIZE, 2);
+ memcpy(&eth_type, ptr + pattrib->hdrlen + pattrib->iv_len + LLC_HEADER_LENGTH, 2);
eth_type = ntohs((unsigned short) eth_type);
#endif
}
@@ -1588,7 +1588,7 @@ static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
/* Offset 12 denote 2 mac address */
nSubframe_Length = get_unaligned_be16(pdata + 12);
- if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length))
+ if (a_len < ETH_HLEN + nSubframe_Length)
break;
sub_pkt = rtw_os_alloc_msdu_pkt(prframe, nSubframe_Length, pdata);
diff --git a/drivers/staging/rtl8723bs/core/rtw_rf.c b/drivers/staging/rtl8723bs/core/rtw_rf.c
index a5095a4ef690..96eb8ca38003 100644
--- a/drivers/staging/rtl8723bs/core/rtw_rf.c
+++ b/drivers/staging/rtl8723bs/core/rtw_rf.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTW_RF_C_
#include <drv_types.h>
#include <linux/kernel.h>
diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c
index a99f439328f1..b050bf62e3b9 100644
--- a/drivers/staging/rtl8723bs/core/rtw_security.c
+++ b/drivers/staging/rtl8723bs/core/rtw_security.c
@@ -35,8 +35,10 @@ const char *security_type_str(u8 value)
*/
void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
{ /* exclude ICV */
-
- unsigned char crc[4];
+ union {
+ __le32 f0;
+ unsigned char f1[4];
+ } crc;
signed int curfragnum, length;
u32 keylength;
@@ -69,18 +71,18 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
- *((__le32 *)crc) = ~crc32_le(~0, payload, length);
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
arc4_setkey(ctx, wepkey, 3 + keylength);
arc4_crypt(ctx, payload, payload, length);
- arc4_crypt(ctx, payload + length, crc, 4);
+ arc4_crypt(ctx, payload + length, crc.f1, 4);
} else {
length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
- *((__le32 *)crc) = ~crc32_le(~0, payload, length);
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
arc4_setkey(ctx, wepkey, 3 + keylength);
arc4_crypt(ctx, payload, payload, length);
- arc4_crypt(ctx, payload + length, crc, 4);
+ arc4_crypt(ctx, payload + length, crc.f1, 4);
pframe += pxmitpriv->frag_len;
pframe = (u8 *)round_up((SIZE_PTR)(pframe), 4);
@@ -121,7 +123,7 @@ void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe)
arc4_crypt(ctx, payload, payload, length);
/* calculate icv and compare the icv */
- *((u32 *)crc) = le32_to_cpu(~crc32_le(~0, payload, length - 4));
+ *((u32 *)crc) = ~crc32_le(~0, payload, length - 4);
}
}
@@ -266,11 +268,6 @@ void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_cod
/* fixed algorithm "parameters" */
#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
-#define TA_SIZE 6 /* 48-bit transmitter address */
-#define TK_SIZE 16 /* 128-bit temporal key */
-#define P1K_SIZE 10 /* 80-bit Phase1 key */
-#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
-
/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in ROM) */
@@ -464,7 +461,10 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
u32 pnh;
u8 rc4key[16];
u8 ttkey[16];
- u8 crc[4];
+ union {
+ __le32 f0;
+ u8 f1[4];
+ } crc;
u8 hw_hdr_offset = 0;
signed int curfragnum, length;
@@ -506,19 +506,19 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */
length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
- *((__le32 *)crc) = ~crc32_le(~0, payload, length);
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
arc4_setkey(ctx, rc4key, 16);
arc4_crypt(ctx, payload, payload, length);
- arc4_crypt(ctx, payload + length, crc, 4);
+ arc4_crypt(ctx, payload + length, crc.f1, 4);
} else {
length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
- *((__le32 *)crc) = ~crc32_le(~0, payload, length);
+ crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
arc4_setkey(ctx, rc4key, 16);
arc4_crypt(ctx, payload, payload, length);
- arc4_crypt(ctx, payload + length, crc, 4);
+ arc4_crypt(ctx, payload + length, crc.f1, 4);
pframe += pxmitpriv->frag_len;
pframe = (u8 *)round_up((SIZE_PTR)(pframe), 4);
@@ -618,7 +618,7 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
arc4_setkey(ctx, rc4key, 16);
arc4_crypt(ctx, payload, payload, length);
- *((u32 *)crc) = le32_to_cpu(~crc32_le(~0, payload, length - 4));
+ *((u32 *)crc) = ~crc32_le(~0, payload, length - 4);
if (crc[3] != payload[length - 1] || crc[2] != payload[length - 2] ||
crc[1] != payload[length - 3] || crc[0] != payload[length - 4])
diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
index c06b74f6569a..18ba846c0b7b 100644
--- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTW_WLAN_UTIL_C_
#include <drv_types.h>
#include <rtw_debug.h>
@@ -25,8 +24,6 @@ static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
static unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
static unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
-#define R2T_PHY_DELAY (0)
-
/* define WAIT_FOR_BCN_TO_MIN (3000) */
#define WAIT_FOR_BCN_TO_MIN (6000)
#define WAIT_FOR_BCN_TO_MAX (20000)
@@ -49,16 +46,7 @@ static u8 rtw_basic_rate_ofdm[3] = {
u8 networktype_to_raid_ex(struct adapter *adapter, struct sta_info *psta)
{
- u8 raid, cur_rf_type, rf_type = RF_1T1R;
-
- rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&cur_rf_type));
-
- if (cur_rf_type == RF_1T1R) {
- rf_type = RF_1T1R;
- } else if (IsSupportedHT(psta->wireless_mode)) {
- if (psta->ra_mask & 0xfff00000)
- rf_type = RF_2T2R;
- }
+ u8 raid;
switch (psta->wireless_mode) {
case WIRELESS_11B:
@@ -72,23 +60,14 @@ u8 networktype_to_raid_ex(struct adapter *adapter, struct sta_info *psta)
break;
case WIRELESS_11_24N:
case WIRELESS_11G_24N:
- if (rf_type == RF_2T2R)
- raid = RATEID_IDX_GN_N2SS;
- else
- raid = RATEID_IDX_GN_N1SS;
+ raid = RATEID_IDX_GN_N1SS;
break;
case WIRELESS_11B_24N:
case WIRELESS_11BG_24N:
if (psta->bw_mode == CHANNEL_WIDTH_20) {
- if (rf_type == RF_2T2R)
- raid = RATEID_IDX_BGN_20M_2SS_BN;
- else
- raid = RATEID_IDX_BGN_20M_1SS_BN;
+ raid = RATEID_IDX_BGN_20M_1SS_BN;
} else {
- if (rf_type == RF_2T2R)
- raid = RATEID_IDX_BGN_40M_2SS;
- else
- raid = RATEID_IDX_BGN_40M_1SS;
+ raid = RATEID_IDX_BGN_40M_1SS;
}
break;
default:
@@ -390,14 +369,14 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigne
inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork)
{
- return pnetwork->MacAddress;
+ return pnetwork->mac_address;
}
u16 get_beacon_interval(struct wlan_bssid_ex *bss)
{
__le16 val;
- memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->IEs), 2);
+ memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->ies), 2);
return le16_to_cpu(val);
}
@@ -909,7 +888,7 @@ static void bwmode_update_check(struct adapter *padapter, struct ndis_80211_var_
if (phtpriv->ht_option == false)
return;
- if (pIE->Length > sizeof(struct HT_info_element))
+ if (pIE->length > sizeof(struct HT_info_element))
return;
pHT_info = (struct HT_info_element *)pIE->data;
@@ -964,7 +943,7 @@ static void bwmode_update_check(struct adapter *padapter, struct ndis_80211_var_
/* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
/* update ap's stainfo */
- psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
+ psta = rtw_get_stainfo(pstapriv, cur_network->mac_address);
if (psta) {
struct ht_priv *phtpriv_sta = &psta->htpriv;
@@ -985,7 +964,6 @@ static void bwmode_update_check(struct adapter *padapter, struct ndis_80211_var_
void HT_caps_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
{
unsigned int i;
- u8 rf_type;
u8 max_AMPDU_len, min_MPDU_spacing;
u8 cur_ldpc_cap = 0, cur_stbc_cap = 0;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
@@ -1001,7 +979,7 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
pmlmeinfo->HT_caps_enable = 1;
- for (i = 0; i < (pIE->Length); i++) {
+ for (i = 0; i < (pIE->length); i++) {
if (i != 2) {
/* Commented by Albert 2010/07/12 */
/* Got the endian issue here. */
@@ -1021,22 +999,13 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
}
}
- rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
/* update the MCS set */
for (i = 0; i < 16; i++)
pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
/* update the MCS rates */
- switch (rf_type) {
- case RF_1T1R:
- case RF_1T2R:
- set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
- break;
- case RF_2T2R:
- default:
- set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
- }
+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
/* Config STBC setting */
@@ -1075,11 +1044,11 @@ void HT_info_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
if (phtpriv->ht_option == false)
return;
- if (pIE->Length > sizeof(struct HT_info_element))
+ if (pIE->length > sizeof(struct HT_info_element))
return;
pmlmeinfo->HT_info_enable = 1;
- memcpy(&(pmlmeinfo->HT_info), pIE->data, pIE->Length);
+ memcpy(&(pmlmeinfo->HT_info), pIE->data, pIE->length);
}
void HTOnAssocRsp(struct adapter *padapter)
@@ -1117,11 +1086,11 @@ void ERP_IE_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (pIE->Length > 1)
+ if (pIE->length > 1)
return;
pmlmeinfo->ERP_enable = 1;
- memcpy(&(pmlmeinfo->ERP_IE), pIE->data, pIE->Length);
+ memcpy(&(pmlmeinfo->ERP_IE), pIE->data, pIE->length);
}
void VCS_update(struct adapter *padapter, struct sta_info *psta)
@@ -1208,7 +1177,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
if (len > MAX_IE_SZ)
return _FAIL;
- if (memcmp(cur_network->network.MacAddress, pbssid, 6))
+ if (memcmp(cur_network->network.mac_address, pbssid, 6))
return true;
bssid = rtw_zmalloc(sizeof(struct wlan_bssid_ex));
@@ -1223,17 +1192,17 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
subtype = GetFrameSubType(pframe) >> 4;
if (subtype == WIFI_BEACON)
- bssid->Reserved[0] = 1;
+ bssid->reserved[0] = 1;
- bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
+ bssid->length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
/* below is to copy the information element */
- bssid->IELength = len;
- memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
+ bssid->ie_length = len;
+ memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
/* check bw and channel offset */
/* parsing HT_CAP_IE */
- p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
if (p && len > 0) {
pht_cap = (struct ieee80211_ht_cap *)(p + 2);
ht_cap_info = le16_to_cpu(pht_cap->cap_info);
@@ -1241,31 +1210,31 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
ht_cap_info = 0;
}
/* parsing HT_INFO_IE */
- p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
if (p && len > 0) {
pht_info = (struct HT_info_element *)(p + 2);
ht_info_infos_0 = pht_info->infos[0];
} else {
ht_info_infos_0 = 0;
}
- if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
- ((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) {
+ if (ht_cap_info != cur_network->bcn_info.ht_cap_info ||
+ ((ht_info_infos_0&0x03) != (cur_network->bcn_info.ht_info_infos_0&0x03))) {
{
/* bcn_info_update */
- cur_network->BcnInfo.ht_cap_info = ht_cap_info;
- cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
+ cur_network->bcn_info.ht_cap_info = ht_cap_info;
+ cur_network->bcn_info.ht_info_infos_0 = ht_info_infos_0;
/* to do : need to check that whether modify related register of BB or not */
}
/* goto _mismatch; */
}
/* Checking for channel */
- p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_DS_PARAMS, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_DS_PARAMS, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
if (p) {
bcn_channel = *(p + 2);
} else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
- rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION,
- &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION,
+ &len, bssid->ie_length - _FIXED_IE_LENGTH_);
if (pht_info)
bcn_channel = pht_info->primary_channel;
else /* we don't find channel IE, so don't check it */
@@ -1277,63 +1246,63 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
/* checking SSID */
ssid_len = 0;
- p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_SSID, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_SSID, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
if (p) {
ssid_len = *(p + 1);
if (ssid_len > NDIS_802_11_LENGTH_SSID)
ssid_len = 0;
}
- memcpy(bssid->Ssid.Ssid, (p + 2), ssid_len);
- bssid->Ssid.SsidLength = ssid_len;
+ memcpy(bssid->ssid.ssid, (p + 2), ssid_len);
+ bssid->ssid.ssid_length = ssid_len;
- if (memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) ||
- bssid->Ssid.SsidLength != cur_network->network.Ssid.SsidLength)
- if (bssid->Ssid.Ssid[0] != '\0' &&
- bssid->Ssid.SsidLength != 0) /* not hidden ssid */
+ if (memcmp(bssid->ssid.ssid, cur_network->network.ssid.ssid, 32) ||
+ bssid->ssid.ssid_length != cur_network->network.ssid.ssid_length)
+ if (bssid->ssid.ssid[0] != '\0' &&
+ bssid->ssid.ssid_length != 0) /* not hidden ssid */
goto _mismatch;
/* check encryption info */
val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
if (val16 & BIT(4))
- bssid->Privacy = 1;
+ bssid->privacy = 1;
else
- bssid->Privacy = 0;
+ bssid->privacy = 0;
- if (cur_network->network.Privacy != bssid->Privacy)
+ if (cur_network->network.privacy != bssid->privacy)
goto _mismatch;
- rtw_get_sec_ie(bssid->IEs, bssid->IELength, NULL, &rsn_len, NULL, &wpa_len);
+ rtw_get_sec_ie(bssid->ies, bssid->ie_length, NULL, &rsn_len, NULL, &wpa_len);
if (rsn_len > 0)
encryp_protocol = ENCRYP_PROTOCOL_WPA2;
else if (wpa_len > 0)
encryp_protocol = ENCRYP_PROTOCOL_WPA;
else
- if (bssid->Privacy)
+ if (bssid->privacy)
encryp_protocol = ENCRYP_PROTOCOL_WEP;
- if (cur_network->BcnInfo.encryp_protocol != encryp_protocol)
+ if (cur_network->bcn_info.encryp_protocol != encryp_protocol)
goto _mismatch;
if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
- pbuf = rtw_get_wpa_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
+ pbuf = rtw_get_wpa_ie(&bssid->ies[12], &wpa_ielen, bssid->ie_length-12);
if (pbuf && (wpa_ielen > 0)) {
rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher,
&pairwise_cipher, &is_8021x);
} else {
- pbuf = rtw_get_wpa2_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
+ pbuf = rtw_get_wpa2_ie(&bssid->ies[12], &wpa_ielen, bssid->ie_length-12);
if (pbuf && (wpa_ielen > 0))
rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher,
&pairwise_cipher, &is_8021x);
}
- if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher ||
- group_cipher != cur_network->BcnInfo.group_cipher)
+ if (pairwise_cipher != cur_network->bcn_info.pairwise_cipher ||
+ group_cipher != cur_network->bcn_info.group_cipher)
goto _mismatch;
- if (is_8021x != cur_network->BcnInfo.is_8021x)
+ if (is_8021x != cur_network->bcn_info.is_8021x)
goto _mismatch;
}
@@ -1369,10 +1338,10 @@ void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, stru
for (i = 0; i < len;) {
pIE = (struct ndis_80211_var_ie *)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
- switch (pIE->ElementID) {
+ switch (pIE->element_id) {
case WLAN_EID_VENDOR_SPECIFIC:
/* to update WMM parameter set while receiving beacon */
- if (!memcmp(pIE->data, WMM_PARA_OUI, 6) && pIE->Length == WLAN_WMM_LEN) /* WMM */
+ if (!memcmp(pIE->data, WMM_PARA_OUI, 6) && pIE->length == WLAN_WMM_LEN) /* WMM */
if (WMM_param_handler(padapter, pIE))
report_wmm_edca_update(padapter);
@@ -1392,7 +1361,7 @@ void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, stru
break;
}
- i += (pIE->Length + 2);
+ i += (pIE->length + 2);
}
}
@@ -1405,10 +1374,10 @@ unsigned int is_ap_in_tkip(struct adapter *padapter)
struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
- for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) {
- pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i);
+ for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) {
+ pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i);
- switch (pIE->ElementID) {
+ switch (pIE->element_id) {
case WLAN_EID_VENDOR_SPECIFIC:
if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
return true;
@@ -1424,7 +1393,7 @@ unsigned int is_ap_in_tkip(struct adapter *padapter)
break;
}
- i += (pIE->Length + 2);
+ i += (pIE->length + 2);
}
return false;
@@ -1480,7 +1449,7 @@ static u32 get_realtek_assoc_AP_vender(struct ndis_80211_var_ie *pIE)
{
u32 Vender = HT_IOT_PEER_REALTEK;
- if (pIE->Length >= 5) {
+ if (pIE->length >= 5) {
if (pIE->data[4] == 1)
/* if (pIE->data[5] & RT_HT_CAP_USE_LONG_PREAMBLE) */
/* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_LONG_PREAMBLE; */
@@ -1511,7 +1480,7 @@ unsigned char check_assoc_AP(u8 *pframe, uint len)
for (i = sizeof(struct ndis_802_11_fix_ie); i < len;) {
pIE = (struct ndis_80211_var_ie *)(pframe + i);
- switch (pIE->ElementID) {
+ switch (pIE->element_id) {
case WLAN_EID_VENDOR_SPECIFIC:
if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) || (!memcmp(pIE->data, ARTHEROS_OUI2, 3)))
return HT_IOT_PEER_ATHEROS;
@@ -1536,7 +1505,7 @@ unsigned char check_assoc_AP(u8 *pframe, uint len)
break;
}
- i += (pIE->Length + 2);
+ i += (pIE->length + 2);
}
return HT_IOT_PEER_UNKNOWN;
@@ -1629,7 +1598,7 @@ void update_wireless_mode(struct adapter *padapter)
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
- unsigned char *rate = cur_network->SupportedRates;
+ unsigned char *rate = cur_network->supported_rates;
if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
pmlmeinfo->HT_enable = 1;
@@ -1661,7 +1630,7 @@ void update_wireless_mode(struct adapter *padapter)
void update_sta_basic_rate(struct sta_info *psta, u8 wireless_mode)
{
- if (IsSupportedTxCCK(wireless_mode)) {
+ if (is_supported_tx_cck(wireless_mode)) {
/* Only B, B/G, and B/G/N AP could use CCK rate */
memcpy(psta->bssrateset, rtw_basic_rate_cck, 4);
psta->bssratelen = 4;
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c
index dc58bb87f1b0..b3d7f50fac4c 100644
--- a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c
@@ -13,15 +13,6 @@ static struct coex_dm_8723b_1ant *pCoexDm = &GLCoexDm8723b1Ant;
static struct coex_sta_8723b_1ant GLCoexSta8723b1Ant;
static struct coex_sta_8723b_1ant *pCoexSta = &GLCoexSta8723b1Ant;
-static const char *const GLBtInfoSrc8723b1Ant[] = {
- "BT Info[wifi fw]",
- "BT Info[bt rsp]",
- "BT Info[bt auto report]",
-};
-
-static u32 GLCoexVerDate8723b1Ant = 20140507;
-static u32 GLCoexVer8723b1Ant = 0x4e;
-
/* local function proto type if needed */
/* local function start with halbtc8723b1ant_ */
static u8 halbtc8723b1ant_BtRssiState(
@@ -2210,461 +2201,6 @@ void EXhalbtc8723b1ant_InitCoexDm(struct btc_coexist *pBtCoexist)
halbtc8723b1ant_QueryBtInfo(pBtCoexist);
}
-void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist)
-{
- struct btc_board_info *pBoardInfo = &pBtCoexist->boardInfo;
- struct btc_stack_info *pStackInfo = &pBtCoexist->stackInfo;
- struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
- u8 *cliBuf = pBtCoexist->cliBuf;
- u8 u1Tmp[4], i, btInfoExt, psTdmaCase = 0;
- u16 u2Tmp[4];
- u32 u4Tmp[4];
- bool bRoam = false;
- bool bScan = false;
- bool bLink = false;
- bool bWifiUnderBMode = false;
- bool bBtHsOn = false;
- bool bWifiBusy = false;
- s32 wifiRssi = 0, btHsRssi = 0;
- u32 wifiBw, wifiTrafficDir, faOfdm, faCck, wifiLinkStatus;
- u8 wifiDot11Chnl, wifiHsChnl;
- u32 fwVer = 0, btPatchVer = 0;
- static u8 PopReportIn10s;
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n ============[BT Coexist info]============"
- );
- CL_PRINTF(cliBuf);
-
- if (pBtCoexist->bManualControl) {
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n ============[Under Manual Control]============"
- );
- CL_PRINTF(cliBuf);
- CL_SPRINTF(cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n =========================================="
- );
- CL_PRINTF(cliBuf);
- }
- if (pBtCoexist->bStopCoexDm) {
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n ============[Coex is STOPPED]============"
- );
- CL_PRINTF(cliBuf);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n =========================================="
- );
- CL_PRINTF(cliBuf);
- }
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d", "Ant PG Num/ Ant Mech/ Ant Pos:",
- pBoardInfo->pgAntNum,
- pBoardInfo->btdmAntNum,
- pBoardInfo->btdmAntPos
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s / %d", "BT stack/ hci ext ver",
- ((pStackInfo->bProfileNotified) ? "Yes" : "No"),
- pStackInfo->hciVersion
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", "CoexVer/ FwVer/ PatchVer",
- GLCoexVerDate8723b1Ant,
- GLCoexVer8723b1Ant,
- fwVer,
- btPatchVer,
- btPatchVer
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_DOT11_CHNL, &wifiDot11Chnl);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifiHsChnl);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d / %d(%d)", "Dot11 channel / HsChnl(HsMode)",
- wifiDot11Chnl,
- wifiHsChnl,
- bBtHsOn
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %02x %02x %02x ", "H2C Wifi inform bt chnl Info",
- pCoexDm->wifiChnlInfo[0],
- pCoexDm->wifiChnlInfo[1],
- pCoexDm->wifiChnlInfo[2]
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_HS_RSSI, &btHsRssi);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d", "Wifi rssi/ HS rssi",
- wifiRssi - 100, btHsRssi - 100
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d/ %s", "Wifi bLink/ bRoam/ bScan/ bHi-Pri",
- bLink, bRoam, bScan, ((pCoexSta->bWiFiIsHighPriTask) ? "1" : "0")
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
- pBtCoexist->fBtcGet(
- pBtCoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, &wifiTrafficDir
- );
- pBtCoexist->fBtcGet(
- pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode
- );
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s / %s/ %s/ AP =%d/ %s ", "Wifi status",
- ("2.4G"),
- ((bWifiUnderBMode) ? "11b" : ((wifiBw == BTC_WIFI_BW_LEGACY) ? "11bg" : (((wifiBw == BTC_WIFI_BW_HT40) ? "HT40" : "HT20")))),
- ((!bWifiBusy) ? "idle" : ((wifiTrafficDir == BTC_WIFI_TRAFFIC_TX) ? "uplink" : "downlink")),
- pCoexSta->nScanAPNum,
- (pCoexSta->bCCKLock) ? "Lock" : "noLock"
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(
- pBtCoexist, BTC_GET_U4_WIFI_LINK_STATUS, &wifiLinkStatus
- );
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d/ %d/ %d", "sta/vwifi/hs/p2pGo/p2pGc",
- ((wifiLinkStatus & WIFI_STA_CONNECTED) ? 1 : 0),
- ((wifiLinkStatus & WIFI_AP_CONNECTED) ? 1 : 0),
- ((wifiLinkStatus & WIFI_HS_CONNECTED) ? 1 : 0),
- ((wifiLinkStatus & WIFI_P2P_GO_CONNECTED) ? 1 : 0),
- ((wifiLinkStatus & WIFI_P2P_GC_CONNECTED) ? 1 : 0)
- );
- CL_PRINTF(cliBuf);
-
-
- PopReportIn10s++;
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = [%s/ %d/ %d/ %d] ", "BT [status/ rssi/ retryCnt/ popCnt]",
- ((pBtCoexist->btInfo.bBtDisabled) ? ("disabled") : ((pCoexSta->bC2hBtInquiryPage) ? ("inquiry/page scan") : ((pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE) ? "non-connected idle" :
- ((pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE) ? "connected-idle" : "busy")))),
- pCoexSta->btRssi, pCoexSta->btRetryCnt, pCoexSta->popEventCnt
- );
- CL_PRINTF(cliBuf);
-
- if (PopReportIn10s >= 5) {
- pCoexSta->popEventCnt = 0;
- PopReportIn10s = 0;
- }
-
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP",
- pBtLinkInfo->bScoExist,
- pBtLinkInfo->bHidExist,
- pBtLinkInfo->bPanExist,
- pBtLinkInfo->bA2dpExist
- );
- CL_PRINTF(cliBuf);
-
- if (pStackInfo->bProfileNotified) {
- pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_BT_LINK_INFO);
- } else {
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "BT Role",
- (pBtLinkInfo->bSlaveRole) ? "Slave" : "Master");
- CL_PRINTF(cliBuf);
- }
-
-
- btInfoExt = pCoexSta->btInfoExt;
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s", "BT Info A2DP rate",
- (btInfoExt & BIT0) ? "Basic rate" : "EDR rate"
- );
- CL_PRINTF(cliBuf);
-
- for (i = 0; i < BT_INFO_SRC_8723B_1ANT_MAX; i++) {
- if (pCoexSta->btInfoC2hCnt[i]) {
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", GLBtInfoSrc8723b1Ant[i],
- pCoexSta->btInfoC2h[i][0], pCoexSta->btInfoC2h[i][1],
- pCoexSta->btInfoC2h[i][2], pCoexSta->btInfoC2h[i][3],
- pCoexSta->btInfoC2h[i][4], pCoexSta->btInfoC2h[i][5],
- pCoexSta->btInfoC2h[i][6], pCoexSta->btInfoC2hCnt[i]
- );
- CL_PRINTF(cliBuf);
- }
- }
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s/%s, (0x%x/0x%x)", "PS state, IPS/LPS, (lps/rpwm)",
- (pCoexSta->bUnderIps ? "IPS ON" : "IPS OFF"),
- (pCoexSta->bUnderLps ? "LPS ON" : "LPS OFF"),
- pBtCoexist->btInfo.lpsVal,
- pBtCoexist->btInfo.rpwmVal
- );
- CL_PRINTF(cliBuf);
- pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD);
-
- if (!pBtCoexist->bManualControl) {
- /* Sw mechanism */
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s", "============[Sw mechanism]============"
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d", "SM[LowPenaltyRA]",
- pCoexDm->bCurLowPenaltyRa
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s/ %s/ %d ", "DelBA/ BtCtrlAgg/ AggSize",
- (pBtCoexist->btInfo.bRejectAggPkt ? "Yes" : "No"),
- (pBtCoexist->btInfo.bBtCtrlAggBufSize ? "Yes" : "No"),
- pBtCoexist->btInfo.aggBufSize
- );
- CL_PRINTF(cliBuf);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x ", "Rate Mask",
- pBtCoexist->btInfo.raMask
- );
- CL_PRINTF(cliBuf);
-
- /* Fw mechanism */
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Fw mechanism]============");
- CL_PRINTF(cliBuf);
-
- psTdmaCase = pCoexDm->curPsTdma;
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", "PS TDMA",
- pCoexDm->psTdmaPara[0], pCoexDm->psTdmaPara[1],
- pCoexDm->psTdmaPara[2], pCoexDm->psTdmaPara[3],
- pCoexDm->psTdmaPara[4], psTdmaCase, pCoexDm->bAutoTdmaAdjust);
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d", "Coex Table Type",
- pCoexSta->nCoexTableType);
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d", "IgnWlanAct",
- pCoexDm->bCurIgnoreWlanAct);
- CL_PRINTF(cliBuf);
- }
-
- /* Hw setting */
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw setting]============");
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", "backup ARFR1/ARFR2/RL/AMaxTime",
- pCoexDm->backupArfrCnt1, pCoexDm->backupArfrCnt2, pCoexDm->backupRetryLimit, pCoexDm->backupAmpduMaxTime);
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x430);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x434);
- u2Tmp[0] = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x42a);
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x456);
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", "0x430/0x434/0x42a/0x456",
- u4Tmp[0], u4Tmp[1], u2Tmp[0], u1Tmp[0]);
- CL_PRINTF(cliBuf);
-
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x778);
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6cc);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x880);
- CL_SPRINTF(
- cliBuf, BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x778/0x6cc/0x880[29:25]",
- u1Tmp[0], u4Tmp[0], (u4Tmp[1] & 0x3e000000) >> 25
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x764);
- u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x76e);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x948/ 0x67[5] / 0x764 / 0x76e",
- u4Tmp[0], ((u1Tmp[0] & 0x20) >> 5), (u4Tmp[1] & 0xffff), u1Tmp[1]
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x92c);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x930);
- u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x944);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]",
- u4Tmp[0] & 0x3, u4Tmp[1] & 0xff, u4Tmp[2] & 0x3
- );
- CL_PRINTF(cliBuf);
-
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x39);
- u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x40);
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
- u1Tmp[2] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x64);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x38[11]/0x40/0x4c[24:23]/0x64[0]",
- ((u1Tmp[0] & 0x8) >> 3),
- u1Tmp[1],
- ((u4Tmp[0] & 0x01800000) >> 23),
- u1Tmp[2] & 0x1
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x550);
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x522);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x", "0x550(bcn ctrl)/0x522",
- u4Tmp[0], u1Tmp[0]
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xc50);
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x49c);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x", "0xc50(dig)/0x49c(null-drop)",
- u4Tmp[0] & 0xff, u1Tmp[0]
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda0);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda4);
- u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda8);
- u4Tmp[3] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xcf0);
-
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0xa5b);
- u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0xa5c);
-
- faOfdm =
- ((u4Tmp[0] & 0xffff0000) >> 16) +
- ((u4Tmp[1] & 0xffff0000) >> 16) +
- (u4Tmp[1] & 0xffff) + (u4Tmp[2] & 0xffff) +
- ((u4Tmp[3] & 0xffff0000) >> 16) + (u4Tmp[3] & 0xffff);
- faCck = (u1Tmp[0] << 8) + u1Tmp[1];
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "OFDM-CCA/OFDM-FA/CCK-FA",
- u4Tmp[0] & 0xffff, faOfdm, faCck
- );
- CL_PRINTF(cliBuf);
-
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d/ %d", "CRC_OK CCK/11g/11n/11n-Agg",
- pCoexSta->nCRCOK_CCK,
- pCoexSta->nCRCOK_11g,
- pCoexSta->nCRCOK_11n,
- pCoexSta->nCRCOK_11nAgg
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d/ %d", "CRC_Err CCK/11g/11n/11n-Agg",
- pCoexSta->nCRCErr_CCK,
- pCoexSta->nCRCErr_11g,
- pCoexSta->nCRCErr_11n,
- pCoexSta->nCRCErr_11nAgg
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c0);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c4);
- u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c8);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8(coexTable)",
- u4Tmp[0], u4Tmp[1], u4Tmp[2]);
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d", "0x770(high-pri rx/tx)",
- pCoexSta->highPriorityRx, pCoexSta->highPriorityTx
- );
- CL_PRINTF(cliBuf);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)",
- pCoexSta->lowPriorityRx, pCoexSta->lowPriorityTx
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_COEX_STATISTICS);
-}
-
-
void EXhalbtc8723b1ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type)
{
if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm)
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h
index 719e19420a3b..de471e27a185 100644
--- a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.h
@@ -182,4 +182,3 @@ void EXhalbtc8723b1ant_BtInfoNotify(
void EXhalbtc8723b1ant_HaltNotify(struct btc_coexist *pBtCoexist);
void EXhalbtc8723b1ant_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState);
void EXhalbtc8723b1ant_Periodical(struct btc_coexist *pBtCoexist);
-void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist);
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c
index 84241619fb3a..c1c7b5cc17a7 100644
--- a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c
@@ -20,15 +20,6 @@ static struct coex_dm_8723b_2ant *pCoexDm = &GLCoexDm8723b2Ant;
static struct coex_sta_8723b_2ant GLCoexSta8723b2Ant;
static struct coex_sta_8723b_2ant *pCoexSta = &GLCoexSta8723b2Ant;
-static const char *const GLBtInfoSrc8723b2Ant[] = {
- "BT Info[wifi fw]",
- "BT Info[bt rsp]",
- "BT Info[bt auto report]",
-};
-
-static u32 GLCoexVerDate8723b2Ant = 20131211;
-static u32 GLCoexVer8723b2Ant = 0x40;
-
/* local function start with halbtc8723b2ant_ */
static u8 halbtc8723b2ant_BtRssiState(
u8 levelNum, u8 rssiThresh, u8 rssiThresh1
@@ -188,31 +179,6 @@ static void halbtc8723b2ant_LimitedRx(
pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
}
-static void halbtc8723b2ant_MonitorBtCtr(struct btc_coexist *pBtCoexist)
-{
- u32 regHPTxRx, regLPTxRx, u4Tmp;
- u32 regHPTx = 0, regHPRx = 0, regLPTx = 0, regLPRx = 0;
-
- regHPTxRx = 0x770;
- regLPTxRx = 0x774;
-
- u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, regHPTxRx);
- regHPTx = u4Tmp & bMaskLWord;
- regHPRx = (u4Tmp & bMaskHWord) >> 16;
-
- u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, regLPTxRx);
- regLPTx = u4Tmp & bMaskLWord;
- regLPRx = (u4Tmp & bMaskHWord) >> 16;
-
- pCoexSta->highPriorityTx = regHPTx;
- pCoexSta->highPriorityRx = regHPRx;
- pCoexSta->lowPriorityTx = regLPTx;
- pCoexSta->lowPriorityRx = regLPRx;
-
- /* reset counter */
- pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc);
-}
-
static void halbtc8723b2ant_QueryBtInfo(struct btc_coexist *pBtCoexist)
{
u8 H2C_Parameter[1] = {0};
@@ -2423,386 +2389,6 @@ void EXhalbtc8723b2ant_InitCoexDm(struct btc_coexist *pBtCoexist)
halbtc8723b2ant_InitCoexDm(pBtCoexist);
}
-void EXhalbtc8723b2ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist)
-{
- struct btc_board_info *pBoardInfo = &pBtCoexist->boardInfo;
- struct btc_stack_info *pStackInfo = &pBtCoexist->stackInfo;
- struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo;
- u8 *cliBuf = pBtCoexist->cliBuf;
- u8 u1Tmp[4], i, btInfoExt, psTdmaCase = 0;
- u32 u4Tmp[4];
- bool bRoam = false, bScan = false, bLink = false;
- bool bBtHsOn = false, bWifiBusy = false;
- s32 wifiRssi = 0, btHsRssi = 0;
- u32 wifiBw, wifiTrafficDir, faOfdm, faCck;
- u8 wifiDot11Chnl, wifiHsChnl;
- u32 fwVer = 0, btPatchVer = 0;
- u8 apNum = 0;
-
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n ============[BT Coexist info]============");
- CL_PRINTF(cliBuf);
-
- if (pBtCoexist->bManualControl) {
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n ============[Under Manual Control]============");
- CL_PRINTF(cliBuf);
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n ==========================================");
- CL_PRINTF(cliBuf);
- }
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d ", "Ant PG number/ Ant mechanism:", \
- pBoardInfo->pgAntNum,
- pBoardInfo->btdmAntNum
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", \
- (pStackInfo->bProfileNotified ? "Yes" : "No"),
- pStackInfo->hciVersion
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", "CoexVer/ FwVer/ PatchVer", \
- GLCoexVerDate8723b2Ant, GLCoexVer8723b2Ant, fwVer, btPatchVer, btPatchVer);
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_DOT11_CHNL, &wifiDot11Chnl);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifiHsChnl);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d / %d(%d)", "Dot11 channel / HsChnl(HsMode)", \
- wifiDot11Chnl,
- wifiHsChnl,
- bBtHsOn
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %02x %02x %02x ", "H2C Wifi inform bt chnl Info", \
- pCoexDm->wifiChnlInfo[0],
- pCoexDm->wifiChnlInfo[1],
- pCoexDm->wifiChnlInfo[2]
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_HS_RSSI, &btHsRssi);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_AP_NUM, &apNum);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d", "Wifi rssi/ HS rssi/ AP#", \
- wifiRssi,
- btHsRssi,
- apNum
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d ", "Wifi bLink/ bRoam/ bScan", \
- bLink,
- bRoam,
- bScan
- );
- CL_PRINTF(cliBuf);
-
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
- pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, &wifiTrafficDir);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s / %s/ %s ", "Wifi status", \
- ("2.4G"),
- ((BTC_WIFI_BW_LEGACY == wifiBw) ? "Legacy" : (((BTC_WIFI_BW_HT40 == wifiBw) ? "HT40" : "HT20"))),
- ((!bWifiBusy) ? "idle" : ((BTC_WIFI_TRAFFIC_TX == wifiTrafficDir) ? "uplink" : "downlink"))
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = [%s/ %d/ %d] ", "BT [status/ rssi/ retryCnt]", \
- ((pBtCoexist->btInfo.bBtDisabled) ? ("disabled") : ((pCoexSta->bC2hBtInquiryPage) ? ("inquiry/page scan") : ((BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus) ? "non-connected idle" :
- ((BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus) ? "connected-idle" : "busy")))),
- pCoexSta->btRssi,
- pCoexSta->btRetryCnt
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", \
- pBtLinkInfo->bScoExist,
- pBtLinkInfo->bHidExist,
- pBtLinkInfo->bPanExist,
- pBtLinkInfo->bA2dpExist
- );
- CL_PRINTF(cliBuf);
- pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_BT_LINK_INFO);
-
- btInfoExt = pCoexSta->btInfoExt;
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s", "BT Info A2DP rate", \
- (btInfoExt & BIT0) ? "Basic rate" : "EDR rate"
- );
- CL_PRINTF(cliBuf);
-
- for (i = 0; i < BT_INFO_SRC_8723B_2ANT_MAX; i++) {
- if (pCoexSta->btInfoC2hCnt[i]) {
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", GLBtInfoSrc8723b2Ant[i], \
- pCoexSta->btInfoC2h[i][0],
- pCoexSta->btInfoC2h[i][1],
- pCoexSta->btInfoC2h[i][2],
- pCoexSta->btInfoC2h[i][3],
- pCoexSta->btInfoC2h[i][4],
- pCoexSta->btInfoC2h[i][5],
- pCoexSta->btInfoC2h[i][6],
- pCoexSta->btInfoC2hCnt[i]
- );
- CL_PRINTF(cliBuf);
- }
- }
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %s/%s", "PS state, IPS/LPS", \
- ((pCoexSta->bUnderIps ? "IPS ON" : "IPS OFF")),
- ((pCoexSta->bUnderLps ? "LPS ON" : "LPS OFF"))
- );
- CL_PRINTF(cliBuf);
- pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD);
-
- /* Sw mechanism */
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s", "============[Sw mechanism]============"
- );
- CL_PRINTF(cliBuf);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d ", "SM1[ShRf/ LpRA/ LimDig]", \
- pCoexDm->bCurRfRxLpfShrink,
- pCoexDm->bCurLowPenaltyRa,
- pCoexDm->bLimitedDig
- );
- CL_PRINTF(cliBuf);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d/ %d(0x%x) ",
- "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]", \
- pCoexDm->bCurAgcTableEn,
- pCoexDm->bCurAdcBackOff,
- pCoexDm->bCurDacSwingOn,
- pCoexDm->curDacSwingLvl
- );
- CL_PRINTF(cliBuf);
-
- /* Fw mechanism */
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Fw mechanism]============");
- CL_PRINTF(cliBuf);
-
- psTdmaCase = pCoexDm->curPsTdma;
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", "PS TDMA", \
- pCoexDm->psTdmaPara[0],
- pCoexDm->psTdmaPara[1],
- pCoexDm->psTdmaPara[2],
- pCoexDm->psTdmaPara[3],
- pCoexDm->psTdmaPara[4],
- psTdmaCase, pCoexDm->bAutoTdmaAdjust
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d ", "DecBtPwr/ IgnWlanAct", \
- pCoexDm->curBtDecPwrLvl,
- pCoexDm->bCurIgnoreWlanAct
- );
- CL_PRINTF(cliBuf);
-
- /* Hw setting */
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw setting]============");
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x", "RF-A, 0x1e initVal", \
- pCoexDm->btRf0x1eBackup
- );
- CL_PRINTF(cliBuf);
-
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x778);
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x880);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x", "0x778/0x880[29:25]", \
- u1Tmp[0],
- (u4Tmp[0] & 0x3e000000) >> 25
- );
- CL_PRINTF(cliBuf);
-
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67);
- u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x948/ 0x67[5] / 0x765", \
- u4Tmp[0],
- ((u1Tmp[0] & 0x20) >> 5),
- u1Tmp[1]
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x92c);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x930);
- u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x944);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", \
- u4Tmp[0] & 0x3,
- u4Tmp[1] & 0xff,
- u4Tmp[2] & 0x3
- );
- CL_PRINTF(cliBuf);
-
-
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x39);
- u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x40);
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
- u1Tmp[2] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x64);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x38[11]/0x40/0x4c[24:23]/0x64[0]", \
- ((u1Tmp[0] & 0x8) >> 3),
- u1Tmp[1],
- ((u4Tmp[0] & 0x01800000) >> 23),
- u1Tmp[2] & 0x1
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x550);
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x522);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x", "0x550(bcn ctrl)/0x522", \
- u4Tmp[0],
- u1Tmp[0]
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xc50);
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x49c);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x", "0xc50(dig)/0x49c(null-drop)", \
- u4Tmp[0] & 0xff,
- u1Tmp[0]
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda0);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda4);
- u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda8);
- u4Tmp[3] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xcf0);
-
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0xa5b);
- u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0xa5c);
-
- faOfdm =
- ((u4Tmp[0] & 0xffff0000) >> 16) +
- ((u4Tmp[1] & 0xffff0000) >> 16) +
- (u4Tmp[1] & 0xffff) + (u4Tmp[2] & 0xffff) + \
- ((u4Tmp[3] & 0xffff0000) >> 16) +
- (u4Tmp[3] & 0xffff);
-
- faCck = (u1Tmp[0] << 8) + u1Tmp[1];
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "OFDM-CCA/OFDM-FA/CCK-FA", \
- u4Tmp[0] & 0xffff,
- faOfdm,
- faCck
- );
- CL_PRINTF(cliBuf);
-
- u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c0);
- u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c4);
- u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c8);
- u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x6cc);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", \
- u4Tmp[0],
- u4Tmp[1],
- u4Tmp[2],
- u1Tmp[0]
- );
- CL_PRINTF(cliBuf);
-
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d", "0x770(high-pri rx/tx)", \
- pCoexSta->highPriorityRx,
- pCoexSta->highPriorityTx
- );
- CL_PRINTF(cliBuf);
- CL_SPRINTF(
- cliBuf,
- BT_TMP_BUF_SIZE,
- "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)", \
- pCoexSta->lowPriorityRx,
- pCoexSta->lowPriorityTx
- );
- CL_PRINTF(cliBuf);
-
- halbtc8723b2ant_MonitorBtCtr(pBtCoexist);
- pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_COEX_STATISTICS);
-}
-
-
void EXhalbtc8723b2ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type)
{
if (BTC_IPS_ENTER == type) {
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h
index 80db3ba34a3f..1896ac54614c 100644
--- a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.h
@@ -144,4 +144,3 @@ void EXhalbtc8723b2ant_BtInfoNotify(
void EXhalbtc8723b2ant_HaltNotify(struct btc_coexist *pBtCoexist);
void EXhalbtc8723b2ant_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState);
void EXhalbtc8723b2ant_Periodical(struct btc_coexist *pBtCoexist);
-void EXhalbtc8723b2ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist);
diff --git a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h
index deb57fa15eaf..af50674b2a65 100644
--- a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h
+++ b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h
@@ -85,10 +85,6 @@ enum {
#define WIFI_P2P_GO_CONNECTED BIT3
#define WIFI_P2P_GC_CONNECTED BIT4
-/* following is for command line utility */
-#define CL_SPRINTF snprintf
-#define CL_PRINTF DCMD_Printf
-
struct btc_board_info {
/* The following is some board information */
u8 btChipType;
@@ -384,7 +380,6 @@ struct btc_coexist {
bool bInitilized;
bool bStopCoexDm;
bool bManualControl;
- u8 *cliBuf;
struct btc_statistics statistics;
u8 pwrModeVal[10];
@@ -408,8 +403,6 @@ struct btc_coexist {
/* fill h2c related */
BFP_BTC_FILL_H2C fBtcFillH2c;
- /* other */
- BFP_BTC_DISP_DBG_MSG fBtcDispDbgMsg;
/* normal get/set related */
BFP_BTC_GET fBtcGet;
BFP_BTC_SET fBtcSet;
@@ -440,6 +433,5 @@ void EXhalbtcoutsrc_Periodical(struct btc_coexist *pBtCoexist);
void EXhalbtcoutsrc_SetChipType(u8 chipType);
void EXhalbtcoutsrc_SetAntNum(u8 type, u8 antNum);
void EXhalbtcoutsrc_SetSingleAntPath(u8 singleAntPath);
-void EXhalbtcoutsrc_DisplayBtCoexInfo(struct btc_coexist *pBtCoexist);
#endif
diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c
index 3de8dcb5ed7c..dd0f74b0cf0d 100644
--- a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c
+++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c
@@ -543,12 +543,12 @@ void ODM_ReadAndConfig_MP_8723B_PHY_REG(struct dm_odm_t *pDM_Odm)
******************************************************************************/
static u32 Array_MP_8723B_PHY_REG_PG[] = {
- 0, 0, 0x00000e08, 0x0000ff00, 0x00003800,
- 0, 0, 0x0000086c, 0xffffff00, 0x32343600,
- 0, 0, 0x00000e00, 0xffffffff, 0x40424444,
- 0, 0, 0x00000e04, 0xffffffff, 0x28323638,
- 0, 0, 0x00000e10, 0xffffffff, 0x38404244,
- 0, 0, 0x00000e14, 0xffffffff, 0x26303436
+ 0, 0x00000e08, 0x0000ff00, 0x00003800,
+ 0, 0x0000086c, 0xffffff00, 0x32343600,
+ 0, 0x00000e00, 0xffffffff, 0x40424444,
+ 0, 0x00000e04, 0xffffffff, 0x28323638,
+ 0, 0x00000e10, 0xffffffff, 0x38404244,
+ 0, 0x00000e14, 0xffffffff, 0x26303436
};
void ODM_ReadAndConfig_MP_8723B_PHY_REG_PG(struct dm_odm_t *pDM_Odm)
@@ -559,13 +559,12 @@ void ODM_ReadAndConfig_MP_8723B_PHY_REG_PG(struct dm_odm_t *pDM_Odm)
pDM_Odm->PhyRegPgVersion = 1;
pDM_Odm->PhyRegPgValueType = PHY_REG_PG_EXACT_VALUE;
- for (i = 0; i < ARRAY_SIZE(Array_MP_8723B_PHY_REG_PG); i += 5) {
+ for (i = 0; i < ARRAY_SIZE(Array_MP_8723B_PHY_REG_PG); i += 4) {
u32 v1 = Array[i];
u32 v2 = Array[i+1];
u32 v3 = Array[i+2];
u32 v4 = Array[i+3];
- u32 v5 = Array[i+4];
- odm_ConfigBB_PHY_REG_PG_8723B(pDM_Odm, v1, v2, v3, v4, v5);
+ odm_ConfigBB_PHY_REG_PG_8723B(pDM_Odm, v1, v2, v3, v4);
}
}
diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c
index 00d429977ea9..efc68c17b126 100644
--- a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c
+++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c
@@ -494,48 +494,6 @@ static u8 *Array_MP_8723B_TXPWR_LMT[] = {
"FCC", "20M", "HT", "1T", "14", "63",
"ETSI", "20M", "HT", "1T", "14", "63",
"MKK", "20M", "HT", "1T", "14", "63",
- "FCC", "20M", "HT", "2T", "01", "30",
- "ETSI", "20M", "HT", "2T", "01", "32",
- "MKK", "20M", "HT", "2T", "01", "32",
- "FCC", "20M", "HT", "2T", "02", "32",
- "ETSI", "20M", "HT", "2T", "02", "32",
- "MKK", "20M", "HT", "2T", "02", "32",
- "FCC", "20M", "HT", "2T", "03", "32",
- "ETSI", "20M", "HT", "2T", "03", "32",
- "MKK", "20M", "HT", "2T", "03", "32",
- "FCC", "20M", "HT", "2T", "04", "32",
- "ETSI", "20M", "HT", "2T", "04", "32",
- "MKK", "20M", "HT", "2T", "04", "32",
- "FCC", "20M", "HT", "2T", "05", "32",
- "ETSI", "20M", "HT", "2T", "05", "32",
- "MKK", "20M", "HT", "2T", "05", "32",
- "FCC", "20M", "HT", "2T", "06", "32",
- "ETSI", "20M", "HT", "2T", "06", "32",
- "MKK", "20M", "HT", "2T", "06", "32",
- "FCC", "20M", "HT", "2T", "07", "32",
- "ETSI", "20M", "HT", "2T", "07", "32",
- "MKK", "20M", "HT", "2T", "07", "32",
- "FCC", "20M", "HT", "2T", "08", "32",
- "ETSI", "20M", "HT", "2T", "08", "32",
- "MKK", "20M", "HT", "2T", "08", "32",
- "FCC", "20M", "HT", "2T", "09", "32",
- "ETSI", "20M", "HT", "2T", "09", "32",
- "MKK", "20M", "HT", "2T", "09", "32",
- "FCC", "20M", "HT", "2T", "10", "32",
- "ETSI", "20M", "HT", "2T", "10", "32",
- "MKK", "20M", "HT", "2T", "10", "32",
- "FCC", "20M", "HT", "2T", "11", "30",
- "ETSI", "20M", "HT", "2T", "11", "32",
- "MKK", "20M", "HT", "2T", "11", "32",
- "FCC", "20M", "HT", "2T", "12", "63",
- "ETSI", "20M", "HT", "2T", "12", "32",
- "MKK", "20M", "HT", "2T", "12", "32",
- "FCC", "20M", "HT", "2T", "13", "63",
- "ETSI", "20M", "HT", "2T", "13", "32",
- "MKK", "20M", "HT", "2T", "13", "32",
- "FCC", "20M", "HT", "2T", "14", "63",
- "ETSI", "20M", "HT", "2T", "14", "63",
- "MKK", "20M", "HT", "2T", "14", "63",
"FCC", "40M", "HT", "1T", "01", "63",
"ETSI", "40M", "HT", "1T", "01", "63",
"MKK", "40M", "HT", "1T", "01", "63",
@@ -577,49 +535,7 @@ static u8 *Array_MP_8723B_TXPWR_LMT[] = {
"MKK", "40M", "HT", "1T", "13", "32",
"FCC", "40M", "HT", "1T", "14", "63",
"ETSI", "40M", "HT", "1T", "14", "63",
- "MKK", "40M", "HT", "1T", "14", "63",
- "FCC", "40M", "HT", "2T", "01", "63",
- "ETSI", "40M", "HT", "2T", "01", "63",
- "MKK", "40M", "HT", "2T", "01", "63",
- "FCC", "40M", "HT", "2T", "02", "63",
- "ETSI", "40M", "HT", "2T", "02", "63",
- "MKK", "40M", "HT", "2T", "02", "63",
- "FCC", "40M", "HT", "2T", "03", "30",
- "ETSI", "40M", "HT", "2T", "03", "30",
- "MKK", "40M", "HT", "2T", "03", "30",
- "FCC", "40M", "HT", "2T", "04", "32",
- "ETSI", "40M", "HT", "2T", "04", "30",
- "MKK", "40M", "HT", "2T", "04", "30",
- "FCC", "40M", "HT", "2T", "05", "32",
- "ETSI", "40M", "HT", "2T", "05", "30",
- "MKK", "40M", "HT", "2T", "05", "30",
- "FCC", "40M", "HT", "2T", "06", "32",
- "ETSI", "40M", "HT", "2T", "06", "30",
- "MKK", "40M", "HT", "2T", "06", "30",
- "FCC", "40M", "HT", "2T", "07", "32",
- "ETSI", "40M", "HT", "2T", "07", "30",
- "MKK", "40M", "HT", "2T", "07", "30",
- "FCC", "40M", "HT", "2T", "08", "32",
- "ETSI", "40M", "HT", "2T", "08", "30",
- "MKK", "40M", "HT", "2T", "08", "30",
- "FCC", "40M", "HT", "2T", "09", "32",
- "ETSI", "40M", "HT", "2T", "09", "30",
- "MKK", "40M", "HT", "2T", "09", "30",
- "FCC", "40M", "HT", "2T", "10", "32",
- "ETSI", "40M", "HT", "2T", "10", "30",
- "MKK", "40M", "HT", "2T", "10", "30",
- "FCC", "40M", "HT", "2T", "11", "30",
- "ETSI", "40M", "HT", "2T", "11", "30",
- "MKK", "40M", "HT", "2T", "11", "30",
- "FCC", "40M", "HT", "2T", "12", "63",
- "ETSI", "40M", "HT", "2T", "12", "32",
- "MKK", "40M", "HT", "2T", "12", "32",
- "FCC", "40M", "HT", "2T", "13", "63",
- "ETSI", "40M", "HT", "2T", "13", "32",
- "MKK", "40M", "HT", "2T", "13", "32",
- "FCC", "40M", "HT", "2T", "14", "63",
- "ETSI", "40M", "HT", "2T", "14", "63",
- "MKK", "40M", "HT", "2T", "14", "63"
+ "MKK", "40M", "HT", "1T", "14", "63"
};
void ODM_ReadAndConfig_MP_8723B_TXPWR_LMT(struct dm_odm_t *pDM_Odm)
diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf.c b/drivers/staging/rtl8723bs/hal/HalPhyRf.c
index 365e1195b5e5..7bef05a9a063 100644
--- a/drivers/staging/rtl8723bs/hal/HalPhyRf.c
+++ b/drivers/staging/rtl8723bs/hal/HalPhyRf.c
@@ -8,21 +8,6 @@
/* include "Mp_Precomp.h" */
#include "odm_precomp.h"
-
-#define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, _deltaThermal) \
- do {\
- for (_offset = 0; _offset < _size; _offset++) {\
- if (_deltaThermal < thermalThreshold[_direction][_offset]) {\
- if (_offset != 0)\
- _offset--;\
- break;\
- } \
- } \
- if (_offset >= _size)\
- _offset = _size-1;\
- } while (0)
-
-
void ConfigureTxpowerTrack(struct dm_odm_t *pDM_Odm, struct txpwrtrack_cfg *pConfig)
{
ConfigureTxpowerTrack_8723B(pConfig);
@@ -45,7 +30,7 @@ void ODM_ClearTxPowerTrackingState(struct dm_odm_t *pDM_Odm)
pDM_Odm->BbSwingIdxCck = pDM_Odm->DefaultCckIndex;
pDM_Odm->RFCalibrateInfo.CCK_index = 0;
- for (p = ODM_RF_PATH_A; p < MAX_RF_PATH; ++p) {
+ for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->DefaultOfdmIndex;
pDM_Odm->BbSwingIdxOfdm[p] = pDM_Odm->DefaultOfdmIndex;
pDM_Odm->RFCalibrateInfo.OFDM_index[p] = pDM_Odm->DefaultOfdmIndex;
@@ -108,7 +93,7 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter)
pDM_Odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
- ThermalValue = (u8)PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, c.ThermalRegAddr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
+ ThermalValue = (u8)PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, c.ThermalRegAddr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
if (
!pDM_Odm->RFCalibrateInfo.TxPowerTrackControl ||
pHalData->EEPROMThermalMeter == 0 ||
@@ -169,49 +154,49 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter)
/* 4 7.1 The Final Power Index = BaseIndex + PowerIndexOffset */
if (ThermalValue > pHalData->EEPROMThermalMeter) {
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_A] =
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A];
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_A] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A];
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A] =
deltaSwingTableIdx_TUP_A[delta];
/* Record delta swing for mix mode power tracking */
- pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] =
+ pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_A] =
deltaSwingTableIdx_TUP_A[delta];
if (c.RfPathCount > 1) {
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_B] =
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B];
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_B] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B];
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B] =
deltaSwingTableIdx_TUP_B[delta];
/* Record delta swing for mix mode power tracking */
- pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] =
+ pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_B] =
deltaSwingTableIdx_TUP_B[delta];
}
} else {
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_A] =
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A];
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_A] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A];
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_A] =
-1 * deltaSwingTableIdx_TDOWN_A[delta];
/* Record delta swing for mix mode power tracking */
- pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] =
+ pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_A] =
-1 * deltaSwingTableIdx_TDOWN_A[delta];
if (c.RfPathCount > 1) {
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_B] =
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B];
- pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[RF_PATH_B] =
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B];
+ pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[RF_PATH_B] =
-1 * deltaSwingTableIdx_TDOWN_B[delta];
/* Record delta swing for mix mode power tracking */
- pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] =
+ pDM_Odm->Absolute_OFDMSwingIdx[RF_PATH_B] =
-1 * deltaSwingTableIdx_TDOWN_B[delta];
}
}
- for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) {
+ for (p = RF_PATH_A; p < c.RfPathCount; p++) {
if (
pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] ==
pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p]
@@ -245,17 +230,17 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter)
/* else if (pDM_Odm->RFCalibrateInfo.CCK_index < 0) */
/* pDM_Odm->RFCalibrateInfo.CCK_index = 0; */
} else {
- for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++)
+ for (p = RF_PATH_A; p < c.RfPathCount; p++)
pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0;
}
/* Print Swing base & current */
- for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) {
+ for (p = RF_PATH_A; p < c.RfPathCount; p++) {
}
if (
- (pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_A] != 0 ||
- pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_B] != 0) &&
+ (pDM_Odm->RFCalibrateInfo.PowerIndexOffset[RF_PATH_A] != 0 ||
+ pDM_Odm->RFCalibrateInfo.PowerIndexOffset[RF_PATH_B] != 0) &&
pDM_Odm->RFCalibrateInfo.TxPowerTrackControl
) {
/* 4 7.2 Configure the Swing Table to adjust Tx Power. */
@@ -268,16 +253,16 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter)
/* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
if (ThermalValue > pHalData->EEPROMThermalMeter) {
- for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++)
+ for (p = RF_PATH_A; p < c.RfPathCount; p++)
(*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, 0);
} else {
- for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++)
+ for (p = RF_PATH_A; p < c.RfPathCount; p++)
(*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, Indexforchannel);
}
/* Record last time Power Tracking result as base. */
pDM_Odm->BbSwingIdxCckBase = pDM_Odm->BbSwingIdxCck;
- for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++)
+ for (p = RF_PATH_A; p < c.RfPathCount; p++)
pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->BbSwingIdxOfdm[p];
/* Record last Power Tracking Thermal Value */
diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
index 8121b8eb45b6..a52748f7b56e 100644
--- a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
+++ b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c
@@ -9,17 +9,10 @@
#include <rtw_debug.h>
#include "odm_precomp.h"
-
-
-/*---------------------------Define Local Constant---------------------------*/
-/* 2010/04/25 MH Define the max tx power tracking tx agc power. */
-#define ODM_TXPWRTRACK_MAX_IDX8723B 6
-
/* MACRO definition for pRFCalibrateInfo->TxIQC_8723B[0] */
#define PATH_S0 1 /* RF_PATH_B */
#define IDX_0xC94 0
#define IDX_0xC80 1
-#define IDX_0xC4C 2
#define IDX_0xC14 0
#define IDX_0xCA0 1
#define KEY 0
@@ -27,12 +20,7 @@
/* MACRO definition for pRFCalibrateInfo->TxIQC_8723B[1] */
#define PATH_S1 0 /* RF_PATH_A */
-#define IDX_0xC9C 0
-#define IDX_0xC88 1
#define IDX_0xC4C 2
-#define IDX_0xC1C 0
-#define IDX_0xC78 1
-
/*---------------------------Define Local Constant---------------------------*/
@@ -79,9 +67,9 @@ static void setIqkMatrix_8723B(
IqkResult_Y = IqkResult_Y | 0xFFFFFC00;
ele_C = ((IqkResult_Y * ele_D)>>8)&0x000003FF;
- /* if (RFPath == ODM_RF_PATH_A) */
+ /* if (RFPath == RF_PATH_A) */
switch (RFPath) {
- case ODM_RF_PATH_A:
+ case RF_PATH_A:
/* write new elements A, C, D to regC80 and regC94,
* element B is always 0
*/
@@ -94,7 +82,7 @@ static void setIqkMatrix_8723B(
value32 = ((IqkResult_X * ele_D)>>7)&0x01;
PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT24, value32);
break;
- case ODM_RF_PATH_B:
+ case RF_PATH_B:
/* write new elements A, C, D to regC88 and regC9C,
* element B is always 0
*/
@@ -113,13 +101,13 @@ static void setIqkMatrix_8723B(
}
} else {
switch (RFPath) {
- case ODM_RF_PATH_A:
+ case RF_PATH_A:
PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable_New[OFDM_index]);
PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00);
PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT24, 0x00);
break;
- case ODM_RF_PATH_B:
+ case RF_PATH_B:
PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable_New[OFDM_index]);
PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT28, 0x00);
@@ -373,7 +361,6 @@ void ConfigureTxpowerTrack_8723B(struct txpwrtrack_cfg *pConfig)
/* 1 7. IQK */
#define MAX_TOLERANCE 5
-#define IQK_DELAY_TIME 1 /* ms */
/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
static u8 phy_PathA_IQK_8723B(
@@ -393,13 +380,13 @@ static u8 phy_PathA_IQK_8723B(
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
/* enable path A PA in TXIQK mode */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87);
/* disable path B PA in TXIQK mode */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, bRFRegOffsetMask, 0x00020); */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x40ec1); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, bRFRegOffsetMask, 0x00020); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x40ec1); */
/* 1 Tx IQK */
/* IQK setting */
@@ -493,12 +480,12 @@ static u8 phy_PathA_RxIQK8723B(
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
/* 1 Get TXIMR setting */
/* modify RXIQK mode table */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
/* LNA2 off, PA on for Dcut */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
/* IQK setting */
@@ -577,16 +564,16 @@ static u8 phy_PathA_RxIQK8723B(
/* modify RXIQK mode table */
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
/* LAN2 on, PA off for Dcut */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77);
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
/* PA, PAD setting */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x55, bRFRegOffsetMask, 0x4021f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x55, bRFRegOffsetMask, 0x4021f);
/* IQK setting */
@@ -644,7 +631,7 @@ static u8 phy_PathA_RxIQK8723B(
/* PA/PAD controlled by 0x0 */
/* leave IQK mode */
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x780);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x780);
/* Allen 20131125 */
tmp = (regEAC & 0x03FF0000)>>16;
@@ -679,13 +666,13 @@ static u8 phy_PathB_IQK_8723B(struct adapter *padapter)
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
/* in TXIQK mode */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1); */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x20000); */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f); */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x20000); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87); */
/* enable path B PA in TXIQK mode */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fc1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fc1);
@@ -713,7 +700,7 @@ static u8 phy_PathB_IQK_8723B(struct adapter *padapter)
/* switch to path B */
PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
/* GNT_BT = 0 */
PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
@@ -773,13 +760,13 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB)
/* switch to path B */
PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
/* modify RXIQK mode table */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
/* open PA S1 & SMIXER */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fcd);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fcd);
/* IQK setting */
@@ -807,7 +794,7 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB)
/* switch to path B */
PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
/* GNT_BT = 0 */
PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
@@ -857,19 +844,19 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB)
/* modify RXIQK mode table */
/* 20121009, Kordan> RF Mode = 3 */
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77);
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77);
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); */
/* open PA S1 & close SMIXER */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30ebd);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30ebd);
/* PA, PAD setting */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80); */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000); */
/* IQK setting */
PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
@@ -894,7 +881,7 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB)
/* switch to path B */
PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0); */
/* GNT_BT = 0 */
PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
@@ -922,7 +909,7 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB)
/* PA/PAD controlled by 0x0 */
/* leave IQK mode */
/* PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, 0xffffff00, 0x00000000); */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, 0xdf, bRFRegOffsetMask, 0x180); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_B, 0xdf, bRFRegOffsetMask, 0x180); */
@@ -1397,7 +1384,7 @@ static void phy_IQCalibrate_8723B(
/* save RF path for 8723B */
/* Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord); */
-/* Path_SEL_RF = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, 0xfffff); */
+/* Path_SEL_RF = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, 0xfffff); */
/* MAC settings */
_PHY_MACSettingCalibration8723B(padapter, IQK_MAC_REG, pDM_Odm->RFCalibrateInfo.IQK_MAC_backup);
@@ -1419,12 +1406,12 @@ static void phy_IQCalibrate_8723B(
/* RX IQ calibration setting for 8723B D cut large current issue when leaving IPS */
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x60fbd);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x60fbd);
/* path A TX IQK */
for (i = 0 ; i < retryCount ; i++) {
@@ -1433,7 +1420,7 @@ static void phy_IQCalibrate_8723B(
if (PathAOK == 0x01) {
/* Path A Tx IQK Success */
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
- pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A] = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x8, bRFRegOffsetMask);
+ pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_A] = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x8, bRFRegOffsetMask);
result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
@@ -1465,7 +1452,7 @@ static void phy_IQCalibrate_8723B(
if (PathBOK == 0x01) {
/* Path B Tx IQK Success */
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
- pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_B] = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, 0x8, bRFRegOffsetMask);
+ pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_B] = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_B, 0x8, bRFRegOffsetMask);
result[t][4] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
result[t][5] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
@@ -1502,7 +1489,7 @@ static void phy_IQCalibrate_8723B(
/* Reload RF path */
/* PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB); */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF); */
/* Allen initial gain 0xc50 */
/* Restore RX initial gain */
@@ -1539,64 +1526,50 @@ static void phy_LCCalibrate_8723B(struct dm_odm_t *pDM_Odm, bool is2T)
if ((tmpReg&0x70) != 0) {
/* 1. Read original RF mode */
/* Path-A */
- RF_Amode = PHY_QueryRFReg(padapter, ODM_RF_PATH_A, RF_AC, bMask12Bits);
+ RF_Amode = PHY_QueryRFReg(padapter, RF_PATH_A, RF_AC, bMask12Bits);
/* Path-B */
if (is2T)
- RF_Bmode = PHY_QueryRFReg(padapter, ODM_RF_PATH_B, RF_AC, bMask12Bits);
+ RF_Bmode = PHY_QueryRFReg(padapter, RF_PATH_B, RF_AC, bMask12Bits);
/* 2. Set RF mode = standby mode */
/* Path-A */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000);
/* Path-B */
if (is2T)
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000);
}
/* 3. Read RF reg18 */
- LC_Cal = PHY_QueryRFReg(padapter, ODM_RF_PATH_A, RF_CHNLBW, bMask12Bits);
+ LC_Cal = PHY_QueryRFReg(padapter, RF_PATH_A, RF_CHNLBW, bMask12Bits);
/* 4. Set LC calibration begin bit15 */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFBE0); /* LDO ON */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFBE0); /* LDO ON */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000);
mdelay(100);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFFE0); /* LDO OFF */
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFFE0); /* LDO OFF */
/* Channel 10 LC calibration issue for 8723bs with 26M xtal */
if (pDM_Odm->SupportInterface == ODM_ITRF_SDIO && pDM_Odm->PackageType >= 0x2) {
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal);
}
/* Restore original situation */
if ((tmpReg&0x70) != 0) { /* Deal with contisuous TX case */
/* Path-A */
rtw_write8(pDM_Odm->Adapter, 0xd03, tmpReg);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
/* Path-B */
if (is2T)
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
} else /* Deal with Packet TX case */
rtw_write8(pDM_Odm->Adapter, REG_TXPAUSE, 0x00);
}
-/* Analog Pre-distortion calibration */
-#define APK_BB_REG_NUM 8
-#define APK_CURVE_REG_NUM 4
-#define PATH_NUM 2
-
-#define DP_BB_REG_NUM 7
-#define DP_RF_REG_NUM 1
-#define DP_RETRY_LIMIT 10
-#define DP_PATH_NUM 2
-#define DP_DPK_NUM 3
-#define DP_DPK_VALUE_NUM 2
-
-
-
/* IQK version:V2.5 20140123 */
/* IQK is controlled by Is2ant, RF path */
void PHY_IQCalibrate_8723B(
@@ -1652,7 +1625,7 @@ void PHY_IQCalibrate_8723B(
u8 path, bResult = SUCCESS;
struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo;
- path = (PHY_QueryBBReg(pDM_Odm->Adapter, rS0S1_PathSwitch, bMaskByte0) == 0x00) ? ODM_RF_PATH_A : ODM_RF_PATH_B;
+ path = (PHY_QueryBBReg(pDM_Odm->Adapter, rS0S1_PathSwitch, bMaskByte0) == 0x00) ? RF_PATH_A : RF_PATH_B;
/* Restore TX IQK */
for (i = 0; i < 3; ++i) {
@@ -1676,11 +1649,11 @@ void PHY_IQCalibrate_8723B(
PHY_SetBBReg(pDM_Odm->Adapter, offset, bMaskDWord, data);
}
- if (pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A] == 0) {
+ if (pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_A] == 0) {
bResult = FAIL;
} else {
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A]);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_B]);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_A]);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_B, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[RF_PATH_B]);
}
if (bResult == SUCCESS)
@@ -1696,7 +1669,7 @@ void PHY_IQCalibrate_8723B(
GNT_BT_default = PHY_QueryBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord);
/* Save RF Path */
/* Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord); */
-/* Path_SEL_RF = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, 0xfffff); */
+/* Path_SEL_RF = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, 0xfffff); */
/* set GNT_BT = 0, pause BT traffic */
/* PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT12, 0x0); */
@@ -1797,15 +1770,15 @@ void PHY_IQCalibrate_8723B(
PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, GNT_BT_default);
/* Restore RF Path */
/* PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB); */
-/* PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF); */
+/* PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF); */
/* Resotr RX mode table parameter */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xe6177);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x300bd);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xe6177);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0xed, 0x20, 0x1);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, 0x43, bRFRegOffsetMask, 0x300bd);
/* set GNT_BT = HW control */
/* PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT12, 0x0); */
diff --git a/drivers/staging/rtl8723bs/hal/Mp_Precomp.h b/drivers/staging/rtl8723bs/hal/Mp_Precomp.h
index 3ed1142a9896..f08823a8dd7b 100644
--- a/drivers/staging/rtl8723bs/hal/Mp_Precomp.h
+++ b/drivers/staging/rtl8723bs/hal/Mp_Precomp.h
@@ -12,8 +12,6 @@
#define BT_TMP_BUF_SIZE 100
-#define DCMD_Printf DBG_BT_INFO
-
#ifdef bEnable
#undef bEnable
#endif
diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c
index 3b0573885dce..f4b3e8b28712 100644
--- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c
+++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c
@@ -4,7 +4,6 @@
* Copyright(c) 2013 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define __HAL_BTCOEX_C__
#include <hal_data.h>
#include <rtw_debug.h>
@@ -17,52 +16,6 @@ struct btc_coexist GLBtCoexist;
static u8 GLBtcWiFiInScanState;
static u8 GLBtcWiFiInIQKState;
-static u8 GLBtcDbgBuf[BT_TMP_BUF_SIZE];
-
-struct btcdbginfo { /* _btcoexdbginfo */
- u8 *info;
- u32 size; /* buffer total size */
- u32 len; /* now used length */
-};
-
-static struct btcdbginfo GLBtcDbgInfo;
-
-#define BT_Operation(Adapter) false
-
-static void DBG_BT_INFO_INIT(struct btcdbginfo *pinfo, u8 *pbuf, u32 size)
-{
- if (!pinfo)
- return;
-
- memset(pinfo, 0, sizeof(struct btcdbginfo));
-
- if (pbuf && size) {
- pinfo->info = pbuf;
- pinfo->size = size;
- }
-}
-
-void DBG_BT_INFO(u8 *dbgmsg)
-{
- struct btcdbginfo *pinfo;
- u32 msglen;
- u8 *pbuf;
-
-
- pinfo = &GLBtcDbgInfo;
-
- if (!pinfo->info)
- return;
-
- msglen = strlen(dbgmsg);
- if (pinfo->len + msglen > pinfo->size)
- return;
-
- pbuf = pinfo->info + pinfo->len;
- memcpy(pbuf, dbgmsg, msglen);
- pinfo->len += msglen;
-}
-
/* */
/* Debug related function */
/* */
@@ -401,7 +354,7 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf)
break;
case BTC_GET_U4_WIFI_BW:
- if (IsLegacyOnly(mlmeext->cur_wireless_mode))
+ if (is_legacy_only(mlmeext->cur_wireless_mode))
*pU4Tmp = BTC_WIFI_BW_LEGACY;
else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_20)
*pU4Tmp = BTC_WIFI_BW_HT20;
@@ -580,7 +533,7 @@ static u8 halbtcoutsrc_Set(void *pBtcContext, u8 setType, void *pInBuf)
struct wlan_bssid_ex *cur_network;
cur_network = &padapter->mlmeextpriv.mlmext_info.network;
- psta = rtw_get_stainfo(&padapter->stapriv, cur_network->MacAddress);
+ psta = rtw_get_stainfo(&padapter->stapriv, cur_network->mac_address);
rtw_hal_update_ra_mask(psta, 0);
}
break;
@@ -608,17 +561,6 @@ static u8 halbtcoutsrc_Set(void *pBtcContext, u8 setType, void *pInBuf)
return ret;
}
-static void halbtcoutsrc_DisplayFwPwrModeCmd(struct btc_coexist *pBtCoexist)
-{
- u8 *cliBuf = pBtCoexist->cliBuf;
-
- CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x %02x ", "Power mode cmd ", \
- pBtCoexist->pwrModeVal[0], pBtCoexist->pwrModeVal[1],
- pBtCoexist->pwrModeVal[2], pBtCoexist->pwrModeVal[3],
- pBtCoexist->pwrModeVal[4], pBtCoexist->pwrModeVal[5]);
- CL_PRINTF(cliBuf);
-}
-
/* */
/* IO related function */
/* */
@@ -830,25 +772,6 @@ static void halbtcoutsrc_FillH2cCmd(void *pBtcContext, u8 elementId, u32 cmdLen,
rtw_hal_fill_h2c_cmd(padapter, elementId, cmdLen, pCmdBuffer);
}
-static void halbtcoutsrc_DisplayDbgMsg(void *pBtcContext, u8 dispType)
-{
- struct btc_coexist *pBtCoexist;
-
-
- pBtCoexist = (struct btc_coexist *)pBtcContext;
- switch (dispType) {
- case BTC_DBG_DISP_COEX_STATISTICS:
- break;
- case BTC_DBG_DISP_BT_LINK_INFO:
- break;
- case BTC_DBG_DISP_FW_PWR_MODE_CMD:
- halbtcoutsrc_DisplayFwPwrModeCmd(pBtCoexist);
- break;
- default:
- break;
- }
-}
-
/* */
/* Extern functions called by other module */
/* */
@@ -908,15 +831,12 @@ void hal_btcoex_Initialize(void *padapter)
pBtCoexist->fBtcGetRfReg = halbtcoutsrc_GetRfReg;
pBtCoexist->fBtcFillH2c = halbtcoutsrc_FillH2cCmd;
- pBtCoexist->fBtcDispDbgMsg = halbtcoutsrc_DisplayDbgMsg;
pBtCoexist->fBtcGet = halbtcoutsrc_Get;
pBtCoexist->fBtcSet = halbtcoutsrc_Set;
pBtCoexist->fBtcGetBtReg = halbtcoutsrc_GetBtReg;
pBtCoexist->fBtcSetBtReg = halbtcoutsrc_SetBtReg;
- pBtCoexist->cliBuf = &GLBtcDbgBuf[0];
-
pBtCoexist->boardInfo.singleAntPath = 0;
GLBtcWiFiInScanState = false;
@@ -1220,21 +1140,6 @@ void EXhalbtcoutsrc_SetSingleAntPath(u8 singleAntPath)
GLBtCoexist.boardInfo.singleAntPath = singleAntPath;
}
-void EXhalbtcoutsrc_DisplayBtCoexInfo(struct btc_coexist *pBtCoexist)
-{
- if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
- return;
-
- halbtcoutsrc_LeaveLowPower(pBtCoexist);
-
- if (pBtCoexist->boardInfo.btdmAntNum == 2)
- EXhalbtc8723b2ant_DisplayCoexInfo(pBtCoexist);
- else if (pBtCoexist->boardInfo.btdmAntNum == 1)
- EXhalbtc8723b1ant_DisplayCoexInfo(pBtCoexist);
-
- halbtcoutsrc_NormalLowPower(pBtCoexist);
-}
-
/*
* Description:
*Run BT-Coexist mechanism or not
@@ -1447,15 +1352,3 @@ void hal_btcoex_RecordPwrMode(struct adapter *padapter, u8 *pCmdBuf, u8 cmdLen)
{
memcpy(GLBtCoexist.pwrModeVal, pCmdBuf, cmdLen);
}
-
-void hal_btcoex_DisplayBtCoexInfo(struct adapter *padapter, u8 *pbuf, u32 bufsize)
-{
- struct btcdbginfo *pinfo;
-
-
- pinfo = &GLBtcDbgInfo;
- DBG_BT_INFO_INIT(pinfo, pbuf, bufsize);
- EXhalbtcoutsrc_DisplayBtCoexInfo(&GLBtCoexist);
- DBG_BT_INFO_INIT(pinfo, NULL, 0);
-}
-
diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c
index eebd48438733..909b37bcc897 100644
--- a/drivers/staging/rtl8723bs/hal/hal_com.c
+++ b/drivers/staging/rtl8723bs/hal/hal_com.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _HAL_COM_C_
#include <linux/kernel.h>
#include <drv_types.h>
@@ -71,15 +70,7 @@ void dump_chip_info(struct hal_version ChipVersion)
cnt += scnprintf(buf + cnt, sizeof(buf) - cnt,
"UNKNOWN_CUT(%d)_", ChipVersion.CUTVersion);
- if (IS_1T1R(ChipVersion))
- cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "1T1R_");
- else if (IS_1T2R(ChipVersion))
- cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "1T2R_");
- else if (IS_2T2R(ChipVersion))
- cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "2T2R_");
- else
- cnt += scnprintf(buf + cnt, sizeof(buf) - cnt,
- "UNKNOWN_RFTYPE(%d)_", ChipVersion.RFType);
+ cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "1T1R_");
cnt += scnprintf(buf + cnt, sizeof(buf) - cnt, "RomVer(%d)\n", ChipVersion.ROMVer);
}
@@ -144,12 +135,12 @@ u8 hal_com_config_channel_plan(
return chnlPlan;
}
-bool HAL_IsLegalChannel(struct adapter *Adapter, u32 Channel)
+bool HAL_IsLegalChannel(struct adapter *adapter, u32 Channel)
{
bool bLegalChannel = true;
if ((Channel <= 14) && (Channel >= 1)) {
- if (IsSupported24G(Adapter->registrypriv.wireless_mode) == false)
+ if (is_supported_24g(adapter->registrypriv.wireless_mode) == false)
bLegalChannel = false;
} else {
bLegalChannel = false;
@@ -223,78 +214,6 @@ u8 MRateToHwRate(u8 rate)
case MGN_MCS7:
ret = DESC_RATEMCS7;
break;
- case MGN_MCS8:
- ret = DESC_RATEMCS8;
- break;
- case MGN_MCS9:
- ret = DESC_RATEMCS9;
- break;
- case MGN_MCS10:
- ret = DESC_RATEMCS10;
- break;
- case MGN_MCS11:
- ret = DESC_RATEMCS11;
- break;
- case MGN_MCS12:
- ret = DESC_RATEMCS12;
- break;
- case MGN_MCS13:
- ret = DESC_RATEMCS13;
- break;
- case MGN_MCS14:
- ret = DESC_RATEMCS14;
- break;
- case MGN_MCS15:
- ret = DESC_RATEMCS15;
- break;
- case MGN_MCS16:
- ret = DESC_RATEMCS16;
- break;
- case MGN_MCS17:
- ret = DESC_RATEMCS17;
- break;
- case MGN_MCS18:
- ret = DESC_RATEMCS18;
- break;
- case MGN_MCS19:
- ret = DESC_RATEMCS19;
- break;
- case MGN_MCS20:
- ret = DESC_RATEMCS20;
- break;
- case MGN_MCS21:
- ret = DESC_RATEMCS21;
- break;
- case MGN_MCS22:
- ret = DESC_RATEMCS22;
- break;
- case MGN_MCS23:
- ret = DESC_RATEMCS23;
- break;
- case MGN_MCS24:
- ret = DESC_RATEMCS24;
- break;
- case MGN_MCS25:
- ret = DESC_RATEMCS25;
- break;
- case MGN_MCS26:
- ret = DESC_RATEMCS26;
- break;
- case MGN_MCS27:
- ret = DESC_RATEMCS27;
- break;
- case MGN_MCS28:
- ret = DESC_RATEMCS28;
- break;
- case MGN_MCS29:
- ret = DESC_RATEMCS29;
- break;
- case MGN_MCS30:
- ret = DESC_RATEMCS30;
- break;
- case MGN_MCS31:
- ret = DESC_RATEMCS31;
- break;
default:
break;
}
@@ -367,78 +286,6 @@ u8 HwRateToMRate(u8 rate)
case DESC_RATEMCS7:
ret_rate = MGN_MCS7;
break;
- case DESC_RATEMCS8:
- ret_rate = MGN_MCS8;
- break;
- case DESC_RATEMCS9:
- ret_rate = MGN_MCS9;
- break;
- case DESC_RATEMCS10:
- ret_rate = MGN_MCS10;
- break;
- case DESC_RATEMCS11:
- ret_rate = MGN_MCS11;
- break;
- case DESC_RATEMCS12:
- ret_rate = MGN_MCS12;
- break;
- case DESC_RATEMCS13:
- ret_rate = MGN_MCS13;
- break;
- case DESC_RATEMCS14:
- ret_rate = MGN_MCS14;
- break;
- case DESC_RATEMCS15:
- ret_rate = MGN_MCS15;
- break;
- case DESC_RATEMCS16:
- ret_rate = MGN_MCS16;
- break;
- case DESC_RATEMCS17:
- ret_rate = MGN_MCS17;
- break;
- case DESC_RATEMCS18:
- ret_rate = MGN_MCS18;
- break;
- case DESC_RATEMCS19:
- ret_rate = MGN_MCS19;
- break;
- case DESC_RATEMCS20:
- ret_rate = MGN_MCS20;
- break;
- case DESC_RATEMCS21:
- ret_rate = MGN_MCS21;
- break;
- case DESC_RATEMCS22:
- ret_rate = MGN_MCS22;
- break;
- case DESC_RATEMCS23:
- ret_rate = MGN_MCS23;
- break;
- case DESC_RATEMCS24:
- ret_rate = MGN_MCS24;
- break;
- case DESC_RATEMCS25:
- ret_rate = MGN_MCS25;
- break;
- case DESC_RATEMCS26:
- ret_rate = MGN_MCS26;
- break;
- case DESC_RATEMCS27:
- ret_rate = MGN_MCS27;
- break;
- case DESC_RATEMCS28:
- ret_rate = MGN_MCS28;
- break;
- case DESC_RATEMCS29:
- ret_rate = MGN_MCS29;
- break;
- case DESC_RATEMCS30:
- ret_rate = MGN_MCS30;
- break;
- case DESC_RATEMCS31:
- ret_rate = MGN_MCS31;
- break;
default:
break;
}
@@ -698,7 +545,7 @@ u8 rtw_get_mgntframe_raid(struct adapter *adapter, unsigned char network_type)
void rtw_hal_update_sta_rate_mask(struct adapter *padapter, struct sta_info *psta)
{
- u8 i, rf_type, limit;
+ u8 i, limit;
u32 tx_ra_bitmap;
if (!psta)
@@ -714,11 +561,7 @@ void rtw_hal_update_sta_rate_mask(struct adapter *padapter, struct sta_info *pst
/* n mode ra_bitmap */
if (psta->htpriv.ht_option) {
- rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
- if (rf_type == RF_2T2R)
- limit = 16; /* 2R */
- else
- limit = 8; /* 1R */
+ limit = 8; /* 1R */
for (i = 0; i < limit; i++) {
if (psta->htpriv.ht_cap.mcs.rx_mask[i/8] & BIT(i%8))
@@ -823,9 +666,6 @@ void GetHwReg(struct adapter *adapter, u8 variable, u8 *val)
case HW_VAR_DM_FLAG:
*((u32 *)val) = odm->SupportAbility;
break;
- case HW_VAR_RF_TYPE:
- *((u8 *)val) = hal_data->rf_type;
- break;
default:
netdev_dbg(adapter->pnetdev,
FUNC_ADPT_FMT " variable(%d) not defined!\n",
@@ -923,7 +763,7 @@ u8 GetHalDefVar(
pmlmepriv = &adapter->mlmepriv;
pstapriv = &adapter->stapriv;
- psta = rtw_get_stainfo(pstapriv, pmlmepriv->cur_network.network.MacAddress);
+ psta = rtw_get_stainfo(pstapriv, pmlmepriv->cur_network.network.mac_address);
if (psta)
*((int *)value) = psta->rssi_stat.UndecoratedSmoothedPWDB;
}
diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
index bb7941aee0c4..3e814a15e893 100644
--- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
+++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _HAL_COM_PHYCFG_C_
#include <drv_types.h>
#include <rtw_debug.h>
@@ -12,32 +11,23 @@
#include <linux/kernel.h>
u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath,
- u8 TxNum, enum rate_section RateSection)
+ enum rate_section RateSection)
{
struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
u8 value = 0;
- if (RfPath > ODM_RF_PATH_D)
+ if (RfPath >= RF_PATH_MAX)
return 0;
switch (RateSection) {
case CCK:
- value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][0];
+ value = pHalData->TxPwrByRateBase2_4G[RfPath][0];
break;
case OFDM:
- value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][1];
+ value = pHalData->TxPwrByRateBase2_4G[RfPath][1];
break;
case HT_MCS0_MCS7:
- value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][2];
- break;
- case HT_MCS8_MCS15:
- value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][3];
- break;
- case HT_MCS16_MCS23:
- value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][4];
- break;
- case HT_MCS24_MCS31:
- value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][5];
+ value = pHalData->TxPwrByRateBase2_4G[RfPath][2];
break;
default:
break;
@@ -47,37 +37,23 @@ u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath,
}
static void
-phy_SetTxPowerByRateBase(
- struct adapter *Adapter,
- u8 RfPath,
- enum rate_section RateSection,
- u8 TxNum,
- u8 Value
-)
+phy_SetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath,
+ enum rate_section RateSection, u8 Value)
{
struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
- if (RfPath > ODM_RF_PATH_D)
+ if (RfPath >= RF_PATH_MAX)
return;
switch (RateSection) {
case CCK:
- pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][0] = Value;
+ pHalData->TxPwrByRateBase2_4G[RfPath][0] = Value;
break;
case OFDM:
- pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][1] = Value;
+ pHalData->TxPwrByRateBase2_4G[RfPath][1] = Value;
break;
case HT_MCS0_MCS7:
- pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][2] = Value;
- break;
- case HT_MCS8_MCS15:
- pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][3] = Value;
- break;
- case HT_MCS16_MCS23:
- pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][4] = Value;
- break;
- case HT_MCS24_MCS31:
- pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][5] = Value;
+ pHalData->TxPwrByRateBase2_4G[RfPath][2] = Value;
break;
default:
break;
@@ -91,22 +67,15 @@ struct adapter *padapter
{
u8 path, base;
- for (path = ODM_RF_PATH_A; path <= ODM_RF_PATH_B; ++path) {
- base = PHY_GetTxPowerByRate(padapter, path, RF_1TX, MGN_11M);
- phy_SetTxPowerByRateBase(padapter, path, CCK, RF_1TX, base);
+ for (path = RF_PATH_A; path <= RF_PATH_B; ++path) {
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_11M);
+ phy_SetTxPowerByRateBase(padapter, path, CCK, base);
- base = PHY_GetTxPowerByRate(padapter, path, RF_1TX, MGN_54M);
- phy_SetTxPowerByRateBase(padapter, path, OFDM, RF_1TX, base);
-
- base = PHY_GetTxPowerByRate(padapter, path, RF_1TX, MGN_MCS7);
- phy_SetTxPowerByRateBase(padapter, path, HT_MCS0_MCS7, RF_1TX, base);
-
- base = PHY_GetTxPowerByRate(padapter, path, RF_2TX, MGN_MCS15);
- phy_SetTxPowerByRateBase(padapter, path, HT_MCS8_MCS15, RF_2TX, base);
-
- base = PHY_GetTxPowerByRate(padapter, path, RF_3TX, MGN_MCS23);
- phy_SetTxPowerByRateBase(padapter, path, HT_MCS16_MCS23, RF_3TX, base);
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_54M);
+ phy_SetTxPowerByRateBase(padapter, path, OFDM, base);
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_MCS7);
+ phy_SetTxPowerByRateBase(padapter, path, HT_MCS0_MCS7, base);
}
}
@@ -142,12 +111,6 @@ u8 PHY_GetRateSectionIndexOfTxPowerByRate(
case rTxAGC_A_Mcs07_Mcs04:
index = 3;
break;
- case rTxAGC_A_Mcs11_Mcs08:
- index = 4;
- break;
- case rTxAGC_A_Mcs15_Mcs12:
- index = 5;
- break;
case rTxAGC_B_Rate18_06:
index = 8;
break;
@@ -163,12 +126,6 @@ u8 PHY_GetRateSectionIndexOfTxPowerByRate(
case rTxAGC_B_Mcs07_Mcs04:
index = 11;
break;
- case rTxAGC_B_Mcs11_Mcs08:
- index = 12;
- break;
- case rTxAGC_B_Mcs15_Mcs12:
- index = 13;
- break;
default:
break;
}
@@ -267,33 +224,6 @@ PHY_GetRateValuesOfTxPowerByRate(
*RateNum = 4;
break;
- case rTxAGC_A_Mcs11_Mcs08:
- case rTxAGC_B_Mcs11_Mcs08:
- RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS8);
- RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS9);
- RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS10);
- RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS11);
- for (i = 0; i < 4; ++i) {
- PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
- ((Value >> (i * 8)) & 0xF));
- }
- *RateNum = 4;
- break;
-
- case rTxAGC_A_Mcs15_Mcs12:
- case rTxAGC_B_Mcs15_Mcs12:
- RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS12);
- RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS13);
- RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS14);
- RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS15);
- for (i = 0; i < 4; ++i) {
- PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
- ((Value >> (i * 8)) & 0xF));
- }
- *RateNum = 4;
-
- break;
-
case rTxAGC_B_CCK1_55_Mcs32:
RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_1M);
RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_2M);
@@ -380,79 +310,13 @@ PHY_GetRateValuesOfTxPowerByRate(
*RateNum = 4;
break;
- case 0xC34:
- case 0xE34:
- case 0x1834:
- case 0x1a34:
- RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS8);
- RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS9);
- RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS10);
- RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS11);
- for (i = 0; i < 4; ++i) {
- PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
- ((Value >> (i * 8)) & 0xF));
- }
- *RateNum = 4;
- break;
-
- case 0xC38:
- case 0xE38:
- case 0x1838:
- case 0x1a38:
- RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS12);
- RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS13);
- RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS14);
- RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS15);
- for (i = 0; i < 4; ++i) {
- PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
- ((Value >> (i * 8)) & 0xF));
- }
- *RateNum = 4;
- break;
-
- case 0xCD8:
- case 0xED8:
- case 0x18D8:
- case 0x1aD8:
- RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS16);
- RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS17);
- RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS18);
- RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS19);
- for (i = 0; i < 4; ++i) {
- PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
- ((Value >> (i * 8)) & 0xF));
- }
- *RateNum = 4;
- break;
-
- case 0xCDC:
- case 0xEDC:
- case 0x18DC:
- case 0x1aDC:
- RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS20);
- RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS21);
- RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS22);
- RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_MCS23);
- for (i = 0; i < 4; ++i) {
- PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 +
- ((Value >> (i * 8)) & 0xF));
- }
- *RateNum = 4;
- break;
-
default:
break;
}
}
-static void PHY_StoreTxPowerByRateNew(
- struct adapter *padapter,
- u32 RfPath,
- u32 TxNum,
- u32 RegAddr,
- u32 BitMask,
- u32 Data
-)
+static void PHY_StoreTxPowerByRateNew(struct adapter *padapter, u32 RfPath,
+ u32 RegAddr, u32 BitMask, u32 Data)
{
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
u8 i = 0, rateIndex[4] = {0}, rateNum = 0;
@@ -460,14 +324,11 @@ static void PHY_StoreTxPowerByRateNew(
PHY_GetRateValuesOfTxPowerByRate(padapter, RegAddr, BitMask, Data, rateIndex, PwrByRateVal, &rateNum);
- if (RfPath > ODM_RF_PATH_D)
- return;
-
- if (TxNum > ODM_RF_PATH_D)
+ if (RfPath >= RF_PATH_MAX)
return;
for (i = 0; i < rateNum; ++i) {
- pHalData->TxPwrByRateOffset[RfPath][TxNum][rateIndex[i]] = PwrByRateVal[i];
+ pHalData->TxPwrByRateOffset[RfPath][rateIndex[i]] = PwrByRateVal[i];
}
}
@@ -484,18 +345,16 @@ static void PHY_StoreTxPowerByRateOld(
void PHY_InitTxPowerByRate(struct adapter *padapter)
{
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
- u8 rfPath, TxNum, rate;
+ u8 rfPath, rate;
- for (rfPath = 0; rfPath < TX_PWR_BY_RATE_NUM_RF; ++rfPath)
- for (TxNum = 0; TxNum < TX_PWR_BY_RATE_NUM_RF; ++TxNum)
- for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE; ++rate)
- pHalData->TxPwrByRateOffset[rfPath][TxNum][rate] = 0;
+ for (rfPath = RF_PATH_A; rfPath < MAX_RF_PATH_NUM; ++rfPath)
+ for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE; ++rate)
+ pHalData->TxPwrByRateOffset[rfPath][rate] = 0;
}
void PHY_StoreTxPowerByRate(
struct adapter *padapter,
u32 RfPath,
- u32 TxNum,
u32 RegAddr,
u32 BitMask,
u32 Data
@@ -505,14 +364,9 @@ void PHY_StoreTxPowerByRate(
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
if (pDM_Odm->PhyRegPgVersion > 0)
- PHY_StoreTxPowerByRateNew(padapter, RfPath, TxNum, RegAddr, BitMask, Data);
+ PHY_StoreTxPowerByRateNew(padapter, RfPath, RegAddr, BitMask, Data);
else if (pDM_Odm->PhyRegPgVersion == 0) {
PHY_StoreTxPowerByRateOld(padapter, RegAddr, BitMask, Data);
-
- if (RegAddr == rTxAGC_A_Mcs15_Mcs12 && pHalData->rf_type == RF_1T1R)
- pHalData->pwrGroupCnt++;
- else if (RegAddr == rTxAGC_B_Mcs15_Mcs12 && pHalData->rf_type != RF_1T1R)
- pHalData->pwrGroupCnt++;
}
}
@@ -521,7 +375,7 @@ phy_ConvertTxPowerByRateInDbmToRelativeValues(
struct adapter *padapter
)
{
- u8 base = 0, i = 0, value = 0, path = 0, txNum = 0;
+ u8 base = 0, i = 0, value = 0, path = 0;
u8 cckRates[4] = {
MGN_1M, MGN_2M, MGN_5_5M, MGN_11M
};
@@ -531,49 +385,26 @@ struct adapter *padapter
u8 mcs0_7Rates[8] = {
MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7
};
- u8 mcs8_15Rates[8] = {
- MGN_MCS8, MGN_MCS9, MGN_MCS10, MGN_MCS11, MGN_MCS12, MGN_MCS13, MGN_MCS14, MGN_MCS15
- };
- u8 mcs16_23Rates[8] = {
- MGN_MCS16, MGN_MCS17, MGN_MCS18, MGN_MCS19, MGN_MCS20, MGN_MCS21, MGN_MCS22, MGN_MCS23
- };
-
- for (path = ODM_RF_PATH_A; path <= ODM_RF_PATH_D; ++path) {
- for (txNum = RF_1TX; txNum < RF_MAX_TX_NUM; ++txNum) {
- /* CCK */
- base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_11M);
- for (i = 0; i < ARRAY_SIZE(cckRates); ++i) {
- value = PHY_GetTxPowerByRate(padapter, path, txNum, cckRates[i]);
- PHY_SetTxPowerByRate(padapter, path, txNum, cckRates[i], value - base);
- }
-
- /* OFDM */
- base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_54M);
- for (i = 0; i < sizeof(ofdmRates); ++i) {
- value = PHY_GetTxPowerByRate(padapter, path, txNum, ofdmRates[i]);
- PHY_SetTxPowerByRate(padapter, path, txNum, ofdmRates[i], value - base);
- }
-
- /* HT MCS0~7 */
- base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_MCS7);
- for (i = 0; i < sizeof(mcs0_7Rates); ++i) {
- value = PHY_GetTxPowerByRate(padapter, path, txNum, mcs0_7Rates[i]);
- PHY_SetTxPowerByRate(padapter, path, txNum, mcs0_7Rates[i], value - base);
- }
+ for (path = RF_PATH_A; path < RF_PATH_MAX; ++path) {
+ /* CCK */
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_11M);
+ for (i = 0; i < ARRAY_SIZE(cckRates); ++i) {
+ value = PHY_GetTxPowerByRate(padapter, path, cckRates[i]);
+ PHY_SetTxPowerByRate(padapter, path, cckRates[i], value - base);
+ }
- /* HT MCS8~15 */
- base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_MCS15);
- for (i = 0; i < sizeof(mcs8_15Rates); ++i) {
- value = PHY_GetTxPowerByRate(padapter, path, txNum, mcs8_15Rates[i]);
- PHY_SetTxPowerByRate(padapter, path, txNum, mcs8_15Rates[i], value - base);
- }
+ /* OFDM */
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_54M);
+ for (i = 0; i < sizeof(ofdmRates); ++i) {
+ value = PHY_GetTxPowerByRate(padapter, path, ofdmRates[i]);
+ PHY_SetTxPowerByRate(padapter, path, ofdmRates[i], value - base);
+ }
- /* HT MCS16~23 */
- base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_MCS23);
- for (i = 0; i < sizeof(mcs16_23Rates); ++i) {
- value = PHY_GetTxPowerByRate(padapter, path, txNum, mcs16_23Rates[i]);
- PHY_SetTxPowerByRate(padapter, path, txNum, mcs16_23Rates[i], value - base);
- }
+ /* HT MCS0~7 */
+ base = PHY_GetTxPowerByRate(padapter, path, MGN_MCS7);
+ for (i = 0; i < sizeof(mcs0_7Rates); ++i) {
+ value = PHY_GetTxPowerByRate(padapter, path, mcs0_7Rates[i]);
+ PHY_SetTxPowerByRate(padapter, path, mcs0_7Rates[i], value - base);
}
}
}
@@ -615,27 +446,6 @@ void PHY_SetTxPowerIndexByRateSection(
Channel, htRates1T,
ARRAY_SIZE(htRates1T));
- } else if (RateSection == HT_MCS8_MCS15) {
- u8 htRates2T[] = {MGN_MCS8, MGN_MCS9, MGN_MCS10, MGN_MCS11, MGN_MCS12, MGN_MCS13, MGN_MCS14, MGN_MCS15};
- PHY_SetTxPowerIndexByRateArray(padapter, RFPath,
- pHalData->CurrentChannelBW,
- Channel, htRates2T,
- ARRAY_SIZE(htRates2T));
-
- } else if (RateSection == HT_MCS16_MCS23) {
- u8 htRates3T[] = {MGN_MCS16, MGN_MCS17, MGN_MCS18, MGN_MCS19, MGN_MCS20, MGN_MCS21, MGN_MCS22, MGN_MCS23};
- PHY_SetTxPowerIndexByRateArray(padapter, RFPath,
- pHalData->CurrentChannelBW,
- Channel, htRates3T,
- ARRAY_SIZE(htRates3T));
-
- } else if (RateSection == HT_MCS24_MCS31) {
- u8 htRates4T[] = {MGN_MCS24, MGN_MCS25, MGN_MCS26, MGN_MCS27, MGN_MCS28, MGN_MCS29, MGN_MCS30, MGN_MCS31};
- PHY_SetTxPowerIndexByRateArray(padapter, RFPath,
- pHalData->CurrentChannelBW,
- Channel, htRates4T,
- ARRAY_SIZE(htRates4T));
-
}
}
@@ -664,25 +474,11 @@ u8 PHY_GetTxPowerIndexBase(
txPower += pHalData->OFDM_24G_Diff[RFPath][TX_1S];
if (BandWidth == CHANNEL_WIDTH_20) { /* BW20-1S, BW20-2S */
- if (MGN_MCS0 <= Rate && Rate <= MGN_MCS31)
+ if (MGN_MCS0 <= Rate && Rate <= MGN_MCS7)
txPower += pHalData->BW20_24G_Diff[RFPath][TX_1S];
- if (MGN_MCS8 <= Rate && Rate <= MGN_MCS31)
- txPower += pHalData->BW20_24G_Diff[RFPath][TX_2S];
- if (MGN_MCS16 <= Rate && Rate <= MGN_MCS31)
- txPower += pHalData->BW20_24G_Diff[RFPath][TX_3S];
- if (MGN_MCS24 <= Rate && Rate <= MGN_MCS31)
- txPower += pHalData->BW20_24G_Diff[RFPath][TX_4S];
-
} else if (BandWidth == CHANNEL_WIDTH_40) { /* BW40-1S, BW40-2S */
- if (MGN_MCS0 <= Rate && Rate <= MGN_MCS31)
+ if (MGN_MCS0 <= Rate && Rate <= MGN_MCS7)
txPower += pHalData->BW40_24G_Diff[RFPath][TX_1S];
- if (MGN_MCS8 <= Rate && Rate <= MGN_MCS31)
- txPower += pHalData->BW40_24G_Diff[RFPath][TX_2S];
- if (MGN_MCS16 <= Rate && Rate <= MGN_MCS31)
- txPower += pHalData->BW40_24G_Diff[RFPath][TX_3S];
- if (MGN_MCS24 <= Rate && Rate <= MGN_MCS31)
- txPower += pHalData->BW40_24G_Diff[RFPath][TX_4S];
-
}
return txPower;
@@ -769,87 +565,13 @@ u8 PHY_GetRateIndexOfTxPowerByRate(u8 Rate)
case MGN_MCS7:
index = 19;
break;
- case MGN_MCS8:
- index = 20;
- break;
- case MGN_MCS9:
- index = 21;
- break;
- case MGN_MCS10:
- index = 22;
- break;
- case MGN_MCS11:
- index = 23;
- break;
- case MGN_MCS12:
- index = 24;
- break;
- case MGN_MCS13:
- index = 25;
- break;
- case MGN_MCS14:
- index = 26;
- break;
- case MGN_MCS15:
- index = 27;
- break;
- case MGN_MCS16:
- index = 28;
- break;
- case MGN_MCS17:
- index = 29;
- break;
- case MGN_MCS18:
- index = 30;
- break;
- case MGN_MCS19:
- index = 31;
- break;
- case MGN_MCS20:
- index = 32;
- break;
- case MGN_MCS21:
- index = 33;
- break;
- case MGN_MCS22:
- index = 34;
- break;
- case MGN_MCS23:
- index = 35;
- break;
- case MGN_MCS24:
- index = 36;
- break;
- case MGN_MCS25:
- index = 37;
- break;
- case MGN_MCS26:
- index = 38;
- break;
- case MGN_MCS27:
- index = 39;
- break;
- case MGN_MCS28:
- index = 40;
- break;
- case MGN_MCS29:
- index = 41;
- break;
- case MGN_MCS30:
- index = 42;
- break;
- case MGN_MCS31:
- index = 43;
- break;
default:
break;
}
return index;
}
-s8 PHY_GetTxPowerByRate(
- struct adapter *padapter, u8 RFPath, u8 TxNum, u8 Rate
-)
+s8 PHY_GetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 Rate)
{
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
s8 value = 0;
@@ -859,23 +581,19 @@ s8 PHY_GetTxPowerByRate(
padapter->registrypriv.RegEnableTxPowerByRate == 0)
return 0;
- if (RFPath > ODM_RF_PATH_D)
- return value;
-
- if (TxNum >= RF_MAX_TX_NUM)
+ if (RFPath >= RF_PATH_MAX)
return value;
if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE)
return value;
- return pHalData->TxPwrByRateOffset[RFPath][TxNum][rateIndex];
+ return pHalData->TxPwrByRateOffset[RFPath][rateIndex];
}
void PHY_SetTxPowerByRate(
struct adapter *padapter,
u8 RFPath,
- u8 TxNum,
u8 Rate,
s8 Value
)
@@ -883,33 +601,21 @@ void PHY_SetTxPowerByRate(
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate);
- if (RFPath > ODM_RF_PATH_D)
- return;
-
- if (TxNum >= RF_MAX_TX_NUM)
+ if (RFPath >= RF_PATH_MAX)
return;
if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE)
return;
- pHalData->TxPwrByRateOffset[RFPath][TxNum][rateIndex] = Value;
+ pHalData->TxPwrByRateOffset[RFPath][rateIndex] = Value;
}
void PHY_SetTxPowerLevelByPath(struct adapter *Adapter, u8 channel, u8 path)
{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
-
- /* if (pMgntInfo->RegNByteAccess == 0) */
- {
- PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, CCK);
+ PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, CCK);
- PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, OFDM);
- PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, HT_MCS0_MCS7);
-
- if (pHalData->NumTotalRFPath >= 2)
- PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, HT_MCS8_MCS15);
-
- }
+ PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, OFDM);
+ PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, HT_MCS0_MCS7);
}
void PHY_SetTxPowerIndexByRateArray(
@@ -971,15 +677,6 @@ static s16 get_rate_sctn_idx(const u8 rate)
case MGN_MCS0: case MGN_MCS1: case MGN_MCS2: case MGN_MCS3:
case MGN_MCS4: case MGN_MCS5: case MGN_MCS6: case MGN_MCS7:
return 2;
- case MGN_MCS8: case MGN_MCS9: case MGN_MCS10: case MGN_MCS11:
- case MGN_MCS12: case MGN_MCS13: case MGN_MCS14: case MGN_MCS15:
- return 3;
- case MGN_MCS16: case MGN_MCS17: case MGN_MCS18: case MGN_MCS19:
- case MGN_MCS20: case MGN_MCS21: case MGN_MCS22: case MGN_MCS23:
- return 4;
- case MGN_MCS24: case MGN_MCS25: case MGN_MCS26: case MGN_MCS27:
- case MGN_MCS28: case MGN_MCS29: case MGN_MCS30: case MGN_MCS31:
- return 5;
default:
return -1;
}
@@ -1067,22 +764,16 @@ void PHY_ConvertTxPowerLimitToPowerIndex(struct adapter *Adapter)
for (bw = 0; bw < MAX_2_4G_BANDWIDTH_NUM; ++bw) {
for (channel = 0; channel < CHANNEL_MAX_NUMBER_2G; ++channel) {
for (rateSection = 0; rateSection < MAX_RATE_SECTION_NUM; ++rateSection) {
- tempPwrLmt = pHalData->TxPwrLimit_2_4G[regulation][bw][rateSection][channel][ODM_RF_PATH_A];
+ tempPwrLmt = pHalData->TxPwrLimit_2_4G[regulation][bw][rateSection][channel][RF_PATH_A];
- for (rfPath = ODM_RF_PATH_A; rfPath < MAX_RF_PATH_NUM; ++rfPath) {
+ for (rfPath = RF_PATH_A; rfPath < MAX_RF_PATH_NUM; ++rfPath) {
if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE) {
- if (rateSection == 5) /* HT 4T */
- BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_4TX, HT_MCS24_MCS31);
- else if (rateSection == 4) /* HT 3T */
- BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_3TX, HT_MCS16_MCS23);
- else if (rateSection == 3) /* HT 2T */
- BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_2TX, HT_MCS8_MCS15);
- else if (rateSection == 2) /* HT 1T */
- BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_1TX, HT_MCS0_MCS7);
+ if (rateSection == 2) /* HT 1T */
+ BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, HT_MCS0_MCS7);
else if (rateSection == 1) /* OFDM */
- BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_1TX, OFDM);
+ BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, OFDM);
else if (rateSection == 0) /* CCK */
- BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_1TX, CCK);
+ BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, CCK);
} else
BW40PwrBasedBm2_4G = Adapter->registrypriv.RegPowerBase * 2;
@@ -1145,12 +836,6 @@ void PHY_SetTxPowerLimit(
rateSection = 1;
else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("1T"), 2))
rateSection = 2;
- else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("2T"), 2))
- rateSection = 3;
- else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("3T"), 2))
- rateSection = 4;
- else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("4T"), 2))
- rateSection = 5;
else
return;
@@ -1158,20 +843,16 @@ void PHY_SetTxPowerLimit(
bandwidth = 0;
else if (eqNByte(Bandwidth, (u8 *)("40M"), 3))
bandwidth = 1;
- else if (eqNByte(Bandwidth, (u8 *)("80M"), 3))
- bandwidth = 2;
- else if (eqNByte(Bandwidth, (u8 *)("160M"), 4))
- bandwidth = 3;
channelIndex = phy_GetChannelIndexOfTxPowerLimit(channel);
if (channelIndex == -1)
return;
- prevPowerLimit = pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A];
+ prevPowerLimit = pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A];
if (powerLimit < prevPowerLimit)
- pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A] = powerLimit;
+ pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A] = powerLimit;
}
void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan)
diff --git a/drivers/staging/rtl8723bs/hal/hal_sdio.c b/drivers/staging/rtl8723bs/hal/hal_sdio.c
index 2d61b09ebce6..9de62a0f5d35 100644
--- a/drivers/staging/rtl8723bs/hal/hal_sdio.c
+++ b/drivers/staging/rtl8723bs/hal/hal_sdio.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _HAL_SDIO_C_
#include <drv_types.h>
#include <rtw_debug.h>
diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c
index 68dfb77772b2..31f65d817899 100644
--- a/drivers/staging/rtl8723bs/hal/odm.c
+++ b/drivers/staging/rtl8723bs/hal/odm.c
@@ -281,10 +281,6 @@ u32 TxScalingTable_Jaguar[TXSCALE_TABLE_SIZE] = {
/* Remove Edca by Yu Chen */
-
-#define RxDefaultAnt1 0x65a9
-#define RxDefaultAnt2 0x569a
-
static void odm_CommonInfoSelfInit(struct dm_odm_t *pDM_Odm)
{
pDM_Odm->bCckHighPower = (bool) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(CCK_RPT_FORMAT, pDM_Odm), ODM_BIT(CCK_RPT_FORMAT, pDM_Odm));
@@ -395,36 +391,20 @@ u32 ODM_Get_Rate_Bitmap(
case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
case (ODM_WM_B|ODM_WM_N24G):
case (ODM_WM_G|ODM_WM_N24G):
- if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) {
- if (rssi_level == DM_RATR_STA_HIGH)
- rate_bitmap = 0x000f0000;
- else if (rssi_level == DM_RATR_STA_MIDDLE)
- rate_bitmap = 0x000ff000;
- else {
- if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
- rate_bitmap = 0x000ff015;
- else
- rate_bitmap = 0x000ff005;
- }
- } else {
- if (rssi_level == DM_RATR_STA_HIGH)
- rate_bitmap = 0x0f8f0000;
- else if (rssi_level == DM_RATR_STA_MIDDLE)
- rate_bitmap = 0x0f8ff000;
- else {
- if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
- rate_bitmap = 0x0f8ff015;
- else
- rate_bitmap = 0x0f8ff005;
- }
+ if (rssi_level == DM_RATR_STA_HIGH)
+ rate_bitmap = 0x000f0000;
+ else if (rssi_level == DM_RATR_STA_MIDDLE)
+ rate_bitmap = 0x000ff000;
+ else {
+ if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
+ rate_bitmap = 0x000ff015;
+ else
+ rate_bitmap = 0x000ff005;
}
break;
default:
- if (pDM_Odm->RFType == RF_1T2R)
- rate_bitmap = 0x000fffff;
- else
- rate_bitmap = 0x0fffffff;
+ rate_bitmap = 0x0fffffff;
break;
}
@@ -722,7 +702,7 @@ void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm)
pDM_Odm->BbSwingIdxCckBase = pDM_Odm->DefaultCckIndex;
pDM_Odm->RFCalibrateInfo.CCK_index = pDM_Odm->DefaultCckIndex;
- for (p = ODM_RF_PATH_A; p < MAX_RF_PATH; ++p) {
+ for (p = RF_PATH_A; p < MAX_RF_PATH; ++p) {
pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->DefaultOfdmIndex;
pDM_Odm->RFCalibrateInfo.OFDM_index[p] = pDM_Odm->DefaultOfdmIndex;
pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] = 0;
@@ -740,7 +720,7 @@ void ODM_TXPowerTrackingCheck(struct dm_odm_t *pDM_Odm)
return;
if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) { /* at least delay 1 sec */
- PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_T_METER_NEW, (BIT17 | BIT16), 0x03);
+ PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH_A, RF_T_METER_NEW, (BIT17 | BIT16), 0x03);
pDM_Odm->RFCalibrateInfo.TM_Trigger = 1;
return;
@@ -848,10 +828,6 @@ void ODM_CmnInfoInit(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, u32 V
pDM_Odm->SupportAbility = (u32)Value;
break;
- case ODM_CMNINFO_RF_TYPE:
- pDM_Odm->RFType = (u8)Value;
- break;
-
case ODM_CMNINFO_PLATFORM:
pDM_Odm->SupportPlatform = (u8)Value;
break;
@@ -860,10 +836,6 @@ void ODM_CmnInfoInit(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, u32 V
pDM_Odm->SupportInterface = (u8)Value;
break;
- case ODM_CMNINFO_MP_TEST_CHIP:
- pDM_Odm->bIsMPChip = (u8)Value;
- break;
-
case ODM_CMNINFO_IC_TYPE:
pDM_Odm->SupportICType = Value;
break;
@@ -1102,10 +1074,6 @@ void ODM_CmnInfoUpdate(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value)
pDM_Odm->SupportAbility = (u32)Value;
break;
- case ODM_CMNINFO_RF_TYPE:
- pDM_Odm->RFType = (u8)Value;
- break;
-
case ODM_CMNINFO_WIFI_DIRECT:
pDM_Odm->bWIFI_Direct = (bool)Value;
break;
diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h
index abf6547518fb..19cfc2915458 100644
--- a/drivers/staging/rtl8723bs/hal/odm.h
+++ b/drivers/staging/rtl8723bs/hal/odm.h
@@ -282,11 +282,9 @@ enum odm_cmninfo_e {
ODM_CMNINFO_PLATFORM = 0,
ODM_CMNINFO_ABILITY, /* ODM_ABILITY_E */
ODM_CMNINFO_INTERFACE, /* ODM_INTERFACE_E */
- ODM_CMNINFO_MP_TEST_CHIP,
ODM_CMNINFO_IC_TYPE, /* ODM_IC_TYPE_E */
ODM_CMNINFO_CUT_VER, /* ODM_CUT_VERSION_E */
ODM_CMNINFO_FAB_VER, /* ODM_FAB_E */
- ODM_CMNINFO_RF_TYPE, /* ODM_RF_PATH_E or ODM_RF_TYPE_E? */
ODM_CMNINFO_RFE_TYPE,
ODM_CMNINFO_PACKAGE_TYPE,
ODM_CMNINFO_EXT_LNA, /* true */
@@ -423,7 +421,6 @@ enum { /* tag_ODM_Fab_Version_Definition */
ODM_UMC = 1,
};
-/* ODM_CMNINFO_RF_TYPE */
/* */
/* For example 1T2R (A+AB = BIT0|BIT4|BIT5) */
/* */
@@ -720,7 +717,6 @@ struct dm_odm_t { /* DM_Out_Source_Dynamic_Mechanism_Structure */
/* Fab Version TSMC/UMC = 0/1 */
u8 FabVersion;
/* RF Type 4T4R/3T3R/2T2R/1T2R/1T1R/... */
- u8 RFType;
u8 RFEType;
/* Board Type Normal/HighPower/MiniCard/SLIM/Combo/... = 0/1/2/3/4/... */
u8 BoardType;
@@ -802,7 +798,6 @@ struct dm_odm_t { /* DM_Out_Source_Dynamic_Mechanism_Structure */
bool bsta_state;
u8 RSSI_Min;
u8 InterfaceIndex; /* Add for 92D dual MAC: 0--Mac0 1--Mac1 */
- bool bIsMPChip;
bool bOneEntryOnly;
/* Common info for BTDM */
bool bBtEnabled; /* BT is disabled */
@@ -998,26 +993,6 @@ struct dm_odm_t { /* DM_Out_Source_Dynamic_Mechanism_Structure */
#endif
};
-#define ODM_RF_PATH_MAX 2
-
-enum odm_rf_radio_path_e {
- ODM_RF_PATH_A = 0, /* Radio Path A */
- ODM_RF_PATH_B = 1, /* Radio Path B */
- ODM_RF_PATH_C = 2, /* Radio Path C */
- ODM_RF_PATH_D = 3, /* Radio Path D */
- ODM_RF_PATH_AB,
- ODM_RF_PATH_AC,
- ODM_RF_PATH_AD,
- ODM_RF_PATH_BC,
- ODM_RF_PATH_BD,
- ODM_RF_PATH_CD,
- ODM_RF_PATH_ABC,
- ODM_RF_PATH_ACD,
- ODM_RF_PATH_BCD,
- ODM_RF_PATH_ABCD,
- /* ODM_RF_PATH_MAX, Max RF number 90 support */
-};
-
enum odm_rf_content {
odm_radioa_txt = 0x1000,
odm_radiob_txt = 0x1001,
diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
index 0f6b9d661e39..928c58be6c9b 100644
--- a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
+++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c
@@ -94,7 +94,7 @@ void ODM_CfoTracking(void *pDM_VOID)
{
struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
struct cfo_tracking *pCfoTrack = &pDM_Odm->DM_CfoTrack;
- int CFO_kHz_A, CFO_kHz_B, CFO_ave = 0;
+ int CFO_kHz_A, CFO_ave = 0;
int CFO_ave_diff;
int CrystalCap = (int)pCfoTrack->CrystalCap;
u8 Adjust_Xtal = 1;
@@ -117,12 +117,8 @@ void ODM_CfoTracking(void *pDM_VOID)
/* 4 1.2 Calculate CFO */
CFO_kHz_A = (int)(pCfoTrack->CFO_tail[0] * 3125) / 1280;
- CFO_kHz_B = (int)(pCfoTrack->CFO_tail[1] * 3125) / 1280;
- if (pDM_Odm->RFType < ODM_2T2R)
- CFO_ave = CFO_kHz_A;
- else
- CFO_ave = (int)(CFO_kHz_A + CFO_kHz_B) >> 1;
+ CFO_ave = CFO_kHz_A;
/* 4 1.3 Avoid abnormal large CFO */
CFO_ave_diff =
@@ -188,26 +184,28 @@ void ODM_CfoTracking(void *pDM_VOID)
}
}
-void ODM_ParsingCFO(void *pDM_VOID, void *pPktinfo_VOID, s8 *pcfotail)
+void odm_parsing_cfo(void *dm_void, void *pkt_info_void, s8 *cfotail)
{
- struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
- struct odm_packet_info *pPktinfo = pPktinfo_VOID;
- struct cfo_tracking *pCfoTrack = &pDM_Odm->DM_CfoTrack;
+ struct dm_odm_t *dm_odm = (struct dm_odm_t *)dm_void;
+ struct odm_packet_info *pkt_info = pkt_info_void;
+ struct cfo_tracking *cfo_track = &dm_odm->DM_CfoTrack;
u8 i;
- if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING))
+ if (!(dm_odm->SupportAbility & ODM_BB_CFO_TRACKING))
return;
- if (pPktinfo->station_id != 0) {
- /* 3 Update CFO report for path-A & path-B */
- /* Only paht-A and path-B have CFO tail and short CFO */
- for (i = ODM_RF_PATH_A; i <= ODM_RF_PATH_B; i++)
- pCfoTrack->CFO_tail[i] = (int)pcfotail[i];
+ if (pkt_info->station_id != 0) {
+ /*
+ * 3 Update CFO report for path-A & path-B
+ * Only paht-A and path-B have CFO tail and short CFO
+ */
+ for (i = RF_PATH_A; i <= RF_PATH_B; i++)
+ cfo_track->CFO_tail[i] = (int)cfotail[i];
/* 3 Update packet counter */
- if (pCfoTrack->packetCount == 0xffffffff)
- pCfoTrack->packetCount = 0;
+ if (cfo_track->packetCount == 0xffffffff)
+ cfo_track->packetCount = 0;
else
- pCfoTrack->packetCount++;
+ cfo_track->packetCount++;
}
}
diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.h b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.h
index bb00d8c893bd..8fa6d9ec5880 100644
--- a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.h
+++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.h
@@ -34,6 +34,6 @@ void ODM_CfoTrackingInit(void *pDM_VOID);
void ODM_CfoTracking(void *pDM_VOID);
-void ODM_ParsingCFO(void *pDM_VOID, void *pPktinfo_VOID, s8 *pcfotail);
+void odm_parsing_cfo(void *pDM_VOID, void *pPktinfo_VOID, s8 *pcfotail);
#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_DIG.c b/drivers/staging/rtl8723bs/hal/odm_DIG.c
index ef5b48bb01b2..beda7b8a7c6a 100644
--- a/drivers/staging/rtl8723bs/hal/odm_DIG.c
+++ b/drivers/staging/rtl8723bs/hal/odm_DIG.c
@@ -7,8 +7,6 @@
#include "odm_precomp.h"
-#define ADAPTIVITY_VERSION "5.0"
-
void odm_NHMCounterStatisticsInit(void *pDM_VOID)
{
struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
@@ -304,8 +302,7 @@ void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI)
/* 1 Set IGI value */
PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
- if (pDM_Odm->RFType > ODM_1T1R)
- PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
+ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
pDM_DigTable->CurIGValue = CurrentIGI;
}
diff --git a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c
index 32f7eb952ca8..994b8c578e7a 100644
--- a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c
+++ b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c
@@ -9,54 +9,52 @@
#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig_MP_##ic##txt(pDM_Odm))
#define READ_AND_CONFIG READ_AND_CONFIG_MP
-#define GET_VERSION_MP(ic, txt) (ODM_GetVersion_MP_##ic##txt())
-#define GET_VERSION(ic, txt) (pDM_Odm->bIsMPChip?GET_VERSION_MP(ic, txt):GET_VERSION_TC(ic, txt))
-static u8 odm_QueryRxPwrPercentage(s8 AntPower)
+static u8 odm_query_rx_pwr_percentage(s8 ant_power)
{
- if ((AntPower <= -100) || (AntPower >= 20))
+ if ((ant_power <= -100) || (ant_power >= 20))
return 0;
- else if (AntPower >= 0)
+ else if (ant_power >= 0)
return 100;
else
- return 100 + AntPower;
+ return 100 + ant_power;
}
-s32 odm_SignalScaleMapping(struct dm_odm_t *pDM_Odm, s32 CurrSig)
+s32 odm_signal_scale_mapping(struct dm_odm_t *dm_odm, s32 curr_sig)
{
- s32 RetSig = 0;
-
- if (pDM_Odm->SupportInterface == ODM_ITRF_SDIO) {
- if (CurrSig >= 51 && CurrSig <= 100)
- RetSig = 100;
- else if (CurrSig >= 41 && CurrSig <= 50)
- RetSig = 80 + ((CurrSig - 40)*2);
- else if (CurrSig >= 31 && CurrSig <= 40)
- RetSig = 66 + (CurrSig - 30);
- else if (CurrSig >= 21 && CurrSig <= 30)
- RetSig = 54 + (CurrSig - 20);
- else if (CurrSig >= 10 && CurrSig <= 20)
- RetSig = 42 + (((CurrSig - 10) * 2) / 3);
- else if (CurrSig >= 5 && CurrSig <= 9)
- RetSig = 22 + (((CurrSig - 5) * 3) / 2);
- else if (CurrSig >= 1 && CurrSig <= 4)
- RetSig = 6 + (((CurrSig - 1) * 3) / 2);
+ s32 ret_sig = 0;
+
+ if (dm_odm->SupportInterface == ODM_ITRF_SDIO) {
+ if (curr_sig >= 51 && curr_sig <= 100)
+ ret_sig = 100;
+ else if (curr_sig >= 41 && curr_sig <= 50)
+ ret_sig = 80 + ((curr_sig - 40)*2);
+ else if (curr_sig >= 31 && curr_sig <= 40)
+ ret_sig = 66 + (curr_sig - 30);
+ else if (curr_sig >= 21 && curr_sig <= 30)
+ ret_sig = 54 + (curr_sig - 20);
+ else if (curr_sig >= 10 && curr_sig <= 20)
+ ret_sig = 42 + (((curr_sig - 10) * 2) / 3);
+ else if (curr_sig >= 5 && curr_sig <= 9)
+ ret_sig = 22 + (((curr_sig - 5) * 3) / 2);
+ else if (curr_sig >= 1 && curr_sig <= 4)
+ ret_sig = 6 + (((curr_sig - 1) * 3) / 2);
else
- RetSig = CurrSig;
+ ret_sig = curr_sig;
}
- return RetSig;
+ return ret_sig;
}
-static u8 odm_EVMdbToPercentage(s8 Value)
+static u8 odm_evm_db_to_percentage(s8 value)
{
/* */
/* -33dB~0dB to 0%~99% */
/* */
s8 ret_val;
- ret_val = Value;
+ ret_val = value;
ret_val /= 2;
if (ret_val >= 0)
@@ -73,153 +71,177 @@ static u8 odm_EVMdbToPercentage(s8 Value)
return ret_val;
}
-static void odm_RxPhyStatus92CSeries_Parsing(
- struct dm_odm_t *pDM_Odm,
- struct odm_phy_info *pPhyInfo,
- u8 *pPhyStatus,
- struct odm_packet_info *pPktinfo
-)
+static s8 odm_cck_rssi(u8 lna_idx, u8 vga_idx)
{
- u8 i, Max_spatial_stream;
+ s8 rx_pwr_all = 0x00;
+
+ switch (lna_idx) {
+ /* 46 53 73 95 201301231630 */
+ /* 46 53 77 99 201301241630 */
+
+ case 6:
+ rx_pwr_all = -34 - (2 * vga_idx);
+ break;
+ case 4:
+ rx_pwr_all = -14 - (2 * vga_idx);
+ break;
+ case 1:
+ rx_pwr_all = 6 - (2 * vga_idx);
+ break;
+ case 0:
+ rx_pwr_all = 16 - (2 * vga_idx);
+ break;
+ default:
+ /* rx_pwr_all = -53+(2*(31-VGA_idx)); */
+ break;
+ }
+ return rx_pwr_all;
+}
+
+static void odm_rx_phy_status_parsing(struct dm_odm_t *dm_odm,
+ struct odm_phy_info *phy_info,
+ u8 *phy_status,
+ struct odm_packet_info *pkt_info)
+{
+ u8 i;
s8 rx_pwr[4], rx_pwr_all = 0;
- u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT;
- u8 RSSI, total_rssi = 0;
- bool isCCKrate = false;
+ u8 evm, pwdb_all = 0, pwdb_all_bt;
+ u8 rssi, total_rssi = 0;
+ bool is_cck_rate = false;
u8 rf_rx_num = 0;
- u8 LNA_idx, VGA_idx;
- struct phy_status_rpt_8192cd_t *pPhyStaRpt = (struct phy_status_rpt_8192cd_t *)pPhyStatus;
+ u8 lna_idx, vga_idx;
+ struct phy_status_rpt_8192cd_t *phy_sta_rpt = (struct phy_status_rpt_8192cd_t *)phy_status;
- isCCKrate = pPktinfo->data_rate <= DESC_RATE11M;
- pPhyInfo->rx_mimo_signal_quality[ODM_RF_PATH_A] = -1;
- pPhyInfo->rx_mimo_signal_quality[ODM_RF_PATH_B] = -1;
+ is_cck_rate = pkt_info->data_rate <= DESC_RATE11M;
+ phy_info->rx_mimo_signal_quality[RF_PATH_A] = -1;
+ phy_info->rx_mimo_signal_quality[RF_PATH_B] = -1;
- if (isCCKrate) {
+ if (is_cck_rate) {
u8 cck_agc_rpt;
- pDM_Odm->PhyDbgInfo.NumQryPhyStatusCCK++;
- /* */
- /* (1)Hardware does not provide RSSI for CCK */
- /* (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */
- /* */
-
- cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a;
-
- /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */
- /* The RSSI formula should be modified according to the gain table */
- LNA_idx = ((cck_agc_rpt & 0xE0)>>5);
- VGA_idx = (cck_agc_rpt & 0x1F);
- rx_pwr_all = odm_CCKRSSI_8723B(LNA_idx, VGA_idx);
- PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
- if (PWDB_ALL > 100)
- PWDB_ALL = 100;
-
- pPhyInfo->rx_pwd_ba11 = PWDB_ALL;
- pPhyInfo->bt_rx_rssi_percentage = PWDB_ALL;
- pPhyInfo->recv_signal_power = rx_pwr_all;
- /* */
+ dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++;
+
+ /*
+ * (1)Hardware does not provide RSSI for CCK/
+ * (2)PWDB, Average PWDB calculated by
+ * hardware (for rate adaptive)
+ */
+
+ cck_agc_rpt = phy_sta_rpt->cck_agc_rpt_ofdm_cfosho_a;
+
+ /*
+ * 2011.11.28 LukeLee: 88E use different LNA & VGA gain table
+ * The RSSI formula should be modified according to the gain table
+ */
+ lna_idx = ((cck_agc_rpt & 0xE0)>>5);
+ vga_idx = (cck_agc_rpt & 0x1F);
+ rx_pwr_all = odm_cck_rssi(lna_idx, vga_idx);
+ pwdb_all = odm_query_rx_pwr_percentage(rx_pwr_all);
+ if (pwdb_all > 100)
+ pwdb_all = 100;
+
+ phy_info->rx_pwd_ba11 = pwdb_all;
+ phy_info->bt_rx_rssi_percentage = pwdb_all;
+ phy_info->recv_signal_power = rx_pwr_all;
+
/* (3) Get Signal Quality (EVM) */
- /* */
+
/* if (pPktinfo->bPacketMatchBSSID) */
{
- u8 SQ, SQ_rpt;
+ u8 sq, sq_rpt;
- if (pPhyInfo->rx_pwd_ba11 > 40 && !pDM_Odm->bInHctTest)
- SQ = 100;
+ if (phy_info->rx_pwd_ba11 > 40 && !dm_odm->bInHctTest)
+ sq = 100;
else {
- SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all;
+ sq_rpt = phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all;
- if (SQ_rpt > 64)
- SQ = 0;
- else if (SQ_rpt < 20)
- SQ = 100;
+ if (sq_rpt > 64)
+ sq = 0;
+ else if (sq_rpt < 20)
+ sq = 100;
else
- SQ = ((64-SQ_rpt) * 100) / 44;
+ sq = ((64-sq_rpt) * 100) / 44;
}
- pPhyInfo->signal_quality = SQ;
- pPhyInfo->rx_mimo_signal_quality[ODM_RF_PATH_A] = SQ;
- pPhyInfo->rx_mimo_signal_quality[ODM_RF_PATH_B] = -1;
+ phy_info->signal_quality = sq;
+ phy_info->rx_mimo_signal_quality[RF_PATH_A] = sq;
+ phy_info->rx_mimo_signal_quality[RF_PATH_B] = -1;
}
} else { /* is OFDM rate */
- pDM_Odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
+ dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
- /* */
- /* (1)Get RSSI for HT rate */
- /* */
+ /*
+ * (1)Get RSSI for HT rate
+ */
- for (i = ODM_RF_PATH_A; i < ODM_RF_PATH_MAX; i++) {
+ for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
/* 2008/01/30 MH we will judge RF RX path now. */
- if (pDM_Odm->RFPathRxEnable & BIT(i))
+ if (dm_odm->RFPathRxEnable & BIT(i))
rf_rx_num++;
/* else */
/* continue; */
- rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain&0x3F)*2) - 110;
-
+ rx_pwr[i] = ((phy_sta_rpt->path_agc[i].gain & 0x3F) * 2) - 110;
- pPhyInfo->rx_pwr[i] = rx_pwr[i];
+ phy_info->rx_pwr[i] = rx_pwr[i];
/* Translate DBM to percentage. */
- RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]);
- total_rssi += RSSI;
+ rssi = odm_query_rx_pwr_percentage(rx_pwr[i]);
+ total_rssi += rssi;
- pPhyInfo->rx_mimo_signal_strength[i] = (u8) RSSI;
+ phy_info->rx_mimo_signal_strength[i] = (u8)rssi;
/* Get Rx snr value in DB */
- pPhyInfo->rx_snr[i] = pDM_Odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2);
- }
-
-
- /* */
- /* (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */
- /* */
- rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1)&0x7f)-110;
-
- PWDB_ALL_BT = PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
-
- pPhyInfo->rx_pwd_ba11 = PWDB_ALL;
- pPhyInfo->bt_rx_rssi_percentage = PWDB_ALL_BT;
- pPhyInfo->rx_power = rx_pwr_all;
- pPhyInfo->recv_signal_power = rx_pwr_all;
-
- {/* pMgntInfo->CustomerID != RT_CID_819x_Lenovo */
- /* */
- /* (3)EVM of HT rate */
- /* */
- if (pPktinfo->data_rate >= DESC_RATEMCS8 && pPktinfo->data_rate <= DESC_RATEMCS15)
- Max_spatial_stream = 2; /* both spatial stream make sense */
- else
- Max_spatial_stream = 1; /* only spatial stream 1 makes sense */
-
- for (i = 0; i < Max_spatial_stream; i++) {
- /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */
- /* fill most significant bit to "zero" when doing shifting operation which may change a negative */
- /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */
- EVM = odm_EVMdbToPercentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */
-
- /* if (pPktinfo->bPacketMatchBSSID) */
- {
- if (i == ODM_RF_PATH_A) /* Fill value in RFD, Get the first spatial stream only */
- pPhyInfo->signal_quality = (u8)(EVM & 0xff);
-
- pPhyInfo->rx_mimo_signal_quality[i] = (u8)(EVM & 0xff);
- }
- }
+ phy_info->rx_snr[i] = dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(phy_sta_rpt->path_rxsnr[i]/2);
}
- ODM_ParsingCFO(pDM_Odm, pPktinfo, pPhyStaRpt->path_cfotail);
-
+ /*
+ * (2)PWDB, Average PWDB calculated by hardware (for rate adaptive)
+ */
+ rx_pwr_all = ((phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all >> 1) & 0x7f) - 110;
+
+ pwdb_all_bt = pwdb_all = odm_query_rx_pwr_percentage(rx_pwr_all);
+
+ phy_info->rx_pwd_ba11 = pwdb_all;
+ phy_info->bt_rx_rssi_percentage = pwdb_all_bt;
+ phy_info->rx_power = rx_pwr_all;
+ phy_info->recv_signal_power = rx_pwr_all;
+
+ /*
+ * (3)EVM of HT rate
+ *
+ * Only spatial stream 1 makes sense
+ *
+ * Do not use shift operation like "rx_evmX >>= 1"
+ * because the compiler of free build environment
+ * fill most significant bit to "zero" when doing
+ * shifting operation which may change a negative
+ * value to positive one, then the dbm value (which
+ * is supposed to be negative) is not correct
+ * anymore.
+ */
+ evm = odm_evm_db_to_percentage(phy_sta_rpt->stream_rxevm[0]); /* dbm */
+
+ /* Fill value in RFD, Get the first spatial stream only */
+ phy_info->signal_quality = (u8)(evm & 0xff);
+
+ phy_info->rx_mimo_signal_quality[RF_PATH_A] = (u8)(evm & 0xff);
+
+ odm_parsing_cfo(dm_odm, pkt_info, phy_sta_rpt->path_cfotail);
}
- /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */
- /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */
- if (isCCKrate) {
- pPhyInfo->signal_strength = (u8)(odm_SignalScaleMapping(pDM_Odm, PWDB_ALL));/* PWDB_ALL; */
+ /*
+ * UI BSS List signal strength(in percentage), make it good
+ * looking, from 0~100.
+ * It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
+ */
+ if (is_cck_rate) {
+ phy_info->signal_strength = (u8)(odm_signal_scale_mapping(dm_odm, pwdb_all));
} else {
if (rf_rx_num != 0) {
- pPhyInfo->signal_strength = (u8)(odm_SignalScaleMapping(pDM_Odm, total_rssi /= rf_rx_num));
+ phy_info->signal_strength = (u8)(odm_signal_scale_mapping(dm_odm, total_rssi /= rf_rx_num));
}
}
}
@@ -268,23 +290,23 @@ static void odm_Process_RSSIForDM(
if (pPktinfo->to_self || pPktinfo->is_beacon) {
if (!isCCKrate) { /* ofdm rate */
- if (pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_B] == 0) {
- RSSI_Ave = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_A];
- pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_A];
+ if (pPhyInfo->rx_mimo_signal_strength[RF_PATH_B] == 0) {
+ RSSI_Ave = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
+ pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
pDM_Odm->RSSI_B = 0;
} else {
- pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_A];
- pDM_Odm->RSSI_B = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_B];
+ pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
+ pDM_Odm->RSSI_B = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B];
if (
- pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_A] >
- pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_B]
+ pPhyInfo->rx_mimo_signal_strength[RF_PATH_A] >
+ pPhyInfo->rx_mimo_signal_strength[RF_PATH_B]
) {
- RSSI_max = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_A];
- RSSI_min = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_B];
+ RSSI_max = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
+ RSSI_min = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B];
} else {
- RSSI_max = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_B];
- RSSI_min = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_A];
+ RSSI_max = pPhyInfo->rx_mimo_signal_strength[RF_PATH_B];
+ RSSI_min = pPhyInfo->rx_mimo_signal_strength[RF_PATH_A];
}
if ((RSSI_max-RSSI_min) < 3)
@@ -371,29 +393,14 @@ static void odm_Process_RSSIForDM(
/* */
/* Endianness before calling this API */
/* */
-static void ODM_PhyStatusQuery_92CSeries(
- struct dm_odm_t *pDM_Odm,
- struct odm_phy_info *pPhyInfo,
- u8 *pPhyStatus,
- struct odm_packet_info *pPktinfo
-)
+void odm_phy_status_query(struct dm_odm_t *dm_odm, struct odm_phy_info *phy_info,
+ u8 *phy_status, struct odm_packet_info *pkt_info)
{
- odm_RxPhyStatus92CSeries_Parsing(pDM_Odm, pPhyInfo, pPhyStatus, pPktinfo);
-
- if (!pDM_Odm->RSSI_test)
- odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo);
-}
-
-void ODM_PhyStatusQuery(
- struct dm_odm_t *pDM_Odm,
- struct odm_phy_info *pPhyInfo,
- u8 *pPhyStatus,
- struct odm_packet_info *pPktinfo
-)
-{
+ odm_rx_phy_status_parsing(dm_odm, phy_info, phy_status, pkt_info);
- ODM_PhyStatusQuery_92CSeries(pDM_Odm, pPhyInfo, pPhyStatus, pPktinfo);
+ if (!dm_odm->RSSI_test)
+ odm_Process_RSSIForDM(dm_odm, phy_info, pkt_info);
}
/* */
@@ -404,7 +411,7 @@ void ODM_PhyStatusQuery(
enum hal_status ODM_ConfigRFWithHeaderFile(
struct dm_odm_t *pDM_Odm,
enum ODM_RF_Config_Type ConfigType,
- enum odm_rf_radio_path_e eRFPath
+ enum rf_path eRFPath
)
{
if (ConfigType == CONFIG_RF_RADIO)
diff --git a/drivers/staging/rtl8723bs/hal/odm_HWConfig.h b/drivers/staging/rtl8723bs/hal/odm_HWConfig.h
index 574f9cfe8190..0c3697c38e64 100644
--- a/drivers/staging/rtl8723bs/hal/odm_HWConfig.h
+++ b/drivers/staging/rtl8723bs/hal/odm_HWConfig.h
@@ -9,23 +9,6 @@
#ifndef __HALHWOUTSRC_H__
#define __HALHWOUTSRC_H__
-
-/*--------------------------Define -------------------------------------------*/
-/* define READ_NEXT_PAIR(v1, v2, i) do { i += 2; v1 = Array[i]; v2 = Array[i+1]; } while (0) */
-#define AGC_DIFF_CONFIG_MP(ic, band) (ODM_ReadAndConfig_MP_##ic##_AGC_TAB_DIFF(pDM_Odm, Array_MP_##ic##_AGC_TAB_DIFF_##band, \
- sizeof(Array_MP_##ic##_AGC_TAB_DIFF_##band)/sizeof(u32)))
-#define AGC_DIFF_CONFIG_TC(ic, band) (ODM_ReadAndConfig_TC_##ic##_AGC_TAB_DIFF(pDM_Odm, Array_TC_##ic##_AGC_TAB_DIFF_##band, \
- sizeof(Array_TC_##ic##_AGC_TAB_DIFF_##band)/sizeof(u32)))
-
-#define AGC_DIFF_CONFIG(ic, band)\
- do {\
- if (pDM_Odm->bIsMPChip)\
- AGC_DIFF_CONFIG_MP(ic, band);\
- else\
- AGC_DIFF_CONFIG_TC(ic, band);\
- } while (0)
-
-
/* */
/* structure and define */
/* */
@@ -76,19 +59,15 @@ struct phy_status_rpt_8192cd_t {
#endif
};
-void ODM_PhyStatusQuery(
- struct dm_odm_t *pDM_Odm,
- struct odm_phy_info *pPhyInfo,
- u8 *pPhyStatus,
- struct odm_packet_info *pPktinfo
-);
+void odm_phy_status_query(struct dm_odm_t *dm_odm, struct odm_phy_info *phy_info,
+ u8 *phy_status, struct odm_packet_info *pkt_info);
enum hal_status ODM_ConfigRFWithTxPwrTrackHeaderFile(struct dm_odm_t *pDM_Odm);
enum hal_status ODM_ConfigRFWithHeaderFile(
struct dm_odm_t *pDM_Odm,
enum ODM_RF_Config_Type ConfigType,
- enum odm_rf_radio_path_e eRFPath
+ enum rf_path eRFPath
);
enum hal_status ODM_ConfigBBWithHeaderFile(
@@ -102,6 +81,6 @@ enum hal_status ODM_ConfigFWWithHeaderFile(
u32 *pSize
);
-s32 odm_SignalScaleMapping(struct dm_odm_t *pDM_Odm, s32 CurrSig);
+s32 odm_signal_scale_mapping(struct dm_odm_t *pDM_Odm, s32 CurrSig);
#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c b/drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c
index ad169704f3e9..392cc8a398f5 100644
--- a/drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c
+++ b/drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c
@@ -33,10 +33,7 @@ static s16 odm_InbandNoise_Monitor_NSeries(
pDM_Odm->noise_level.noise_all = 0;
- if ((pDM_Odm->RFType == ODM_1T2R) || (pDM_Odm->RFType == ODM_2T2R))
- max_rf_path = 2;
- else
- max_rf_path = 1;
+ max_rf_path = 1;
memset(&noise_data, 0, sizeof(struct noise_level));
@@ -70,17 +67,17 @@ static s16 odm_InbandNoise_Monitor_NSeries(
/* update idle time pwer report per 5us */
PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_TxGainStage, BIT25, 0);
- noise_data.value[ODM_RF_PATH_A] = (u8)(tmp4b&0xff);
- noise_data.value[ODM_RF_PATH_B] = (u8)((tmp4b&0xff00)>>8);
+ noise_data.value[RF_PATH_A] = (u8)(tmp4b&0xff);
+ noise_data.value[RF_PATH_B] = (u8)((tmp4b&0xff00)>>8);
- for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) {
+ for (rf_path = RF_PATH_A; rf_path < max_rf_path; rf_path++) {
noise_data.sval[rf_path] = (s8)noise_data.value[rf_path];
noise_data.sval[rf_path] /= 2;
}
/* mdelay(10); */
/* msleep(10); */
- for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) {
+ for (rf_path = RF_PATH_A; rf_path < max_rf_path; rf_path++) {
if ((noise_data.valid_cnt[rf_path] < ValidCnt) && (noise_data.sval[rf_path] < Valid_Max && noise_data.sval[rf_path] >= Valid_Min)) {
noise_data.valid_cnt[rf_path]++;
noise_data.sum[rf_path] += noise_data.sval[rf_path];
@@ -94,7 +91,7 @@ static s16 odm_InbandNoise_Monitor_NSeries(
/* printk("####### valid_done:%d #############\n", valid_done); */
if ((valid_done == max_rf_path) || (jiffies_to_msecs(jiffies - start) > max_time)) {
- for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) {
+ for (rf_path = RF_PATH_A; rf_path < max_rf_path; rf_path++) {
/* printk("%s PATH_%d - sum = %d, valid_cnt = %d\n", __func__, rf_path, noise_data.sum[rf_path], noise_data.valid_cnt[rf_path]); */
if (noise_data.valid_cnt[rf_path])
noise_data.sum[rf_path] /= noise_data.valid_cnt[rf_path];
@@ -106,14 +103,14 @@ static s16 odm_InbandNoise_Monitor_NSeries(
}
reg_c50 = (s32)PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XAAGCCore1, bMaskByte0);
reg_c50 &= ~BIT7;
- pDM_Odm->noise_level.noise[ODM_RF_PATH_A] = -110 + reg_c50 + noise_data.sum[ODM_RF_PATH_A];
- pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[ODM_RF_PATH_A];
+ pDM_Odm->noise_level.noise[RF_PATH_A] = -110 + reg_c50 + noise_data.sum[RF_PATH_A];
+ pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[RF_PATH_A];
if (max_rf_path == 2) {
reg_c58 = (s32)PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBAGCCore1, bMaskByte0);
reg_c58 &= ~BIT7;
- pDM_Odm->noise_level.noise[ODM_RF_PATH_B] = -110 + reg_c58 + noise_data.sum[ODM_RF_PATH_B];
- pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[ODM_RF_PATH_B];
+ pDM_Odm->noise_level.noise[RF_PATH_B] = -110 + reg_c58 + noise_data.sum[RF_PATH_B];
+ pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[RF_PATH_B];
}
pDM_Odm->noise_level.noise_all /= max_rf_path;
diff --git a/drivers/staging/rtl8723bs/hal/odm_RTL8723B.c b/drivers/staging/rtl8723bs/hal/odm_RTL8723B.c
deleted file mode 100644
index 54518ea1be6b..000000000000
--- a/drivers/staging/rtl8723bs/hal/odm_RTL8723B.c
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#include "odm_precomp.h"
-
-s8 odm_CCKRSSI_8723B(u8 LNA_idx, u8 VGA_idx)
-{
- s8 rx_pwr_all = 0x00;
-
- switch (LNA_idx) {
- /* 46 53 73 95 201301231630 */
- /* 46 53 77 99 201301241630 */
-
- case 6:
- rx_pwr_all = -34 - (2 * VGA_idx);
- break;
- case 4:
- rx_pwr_all = -14 - (2 * VGA_idx);
- break;
- case 1:
- rx_pwr_all = 6 - (2 * VGA_idx);
- break;
- case 0:
- rx_pwr_all = 16 - (2 * VGA_idx);
- break;
- default:
- /* rx_pwr_all = -53+(2*(31-VGA_idx)); */
- break;
-
- }
- return rx_pwr_all;
-}
diff --git a/drivers/staging/rtl8723bs/hal/odm_RTL8723B.h b/drivers/staging/rtl8723bs/hal/odm_RTL8723B.h
deleted file mode 100644
index 96ef1cc41a96..000000000000
--- a/drivers/staging/rtl8723bs/hal/odm_RTL8723B.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __ODM_RTL8723B_H__
-#define __ODM_RTL8723B_H__
-
-#define DM_DIG_MIN_NIC_8723 0x1C
-
-s8 odm_CCKRSSI_8723B(u8 LNA_idx, u8 VGA_idx);
-
-#endif
diff --git a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c
index a29bd9375023..1df42069bd5c 100644
--- a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c
+++ b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c
@@ -11,7 +11,7 @@ void odm_ConfigRFReg_8723B(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data,
- enum odm_rf_radio_path_e RF_PATH,
+ enum rf_path RF_PATH,
u32 RegAddr
)
{
@@ -93,7 +93,7 @@ void odm_ConfigRF_RadioA_8723B(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data)
pDM_Odm,
Addr,
Data,
- ODM_RF_PATH_A,
+ RF_PATH_A,
Addr|maskforPhySet
);
}
@@ -118,7 +118,6 @@ void odm_ConfigBB_AGC_8723B(
void odm_ConfigBB_PHY_REG_PG_8723B(
struct dm_odm_t *pDM_Odm,
u32 RfPath,
- u32 TxNum,
u32 Addr,
u32 Bitmask,
u32 Data
@@ -127,7 +126,7 @@ void odm_ConfigBB_PHY_REG_PG_8723B(
if (Addr == 0xfe || Addr == 0xffe)
msleep(50);
else {
- PHY_StoreTxPowerByRate(pDM_Odm->Adapter, RfPath, TxNum, Addr, Bitmask, Data);
+ PHY_StoreTxPowerByRate(pDM_Odm->Adapter, RfPath, Addr, Bitmask, Data);
}
}
diff --git a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h
index bdd6fde49fc6..fba7053ee3e1 100644
--- a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h
+++ b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h
@@ -10,7 +10,7 @@
void odm_ConfigRFReg_8723B(struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data,
- enum odm_rf_radio_path_e RF_PATH,
+ enum rf_path RF_PATH,
u32 RegAddr
);
@@ -24,13 +24,8 @@ void odm_ConfigBB_AGC_8723B(struct dm_odm_t *pDM_Odm,
u32 Data
);
-void odm_ConfigBB_PHY_REG_PG_8723B(struct dm_odm_t *pDM_Odm,
- u32 RfPath,
- u32 TxNum,
- u32 Addr,
- u32 Bitmask,
- u32 Data
-);
+void odm_ConfigBB_PHY_REG_PG_8723B(struct dm_odm_t *pDM_Odm, u32 RfPath, u32 Addr,
+ u32 Bitmask, u32 Data);
void odm_ConfigBB_PHY_8723B(struct dm_odm_t *pDM_Odm,
u32 Addr,
diff --git a/drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h b/drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h
index 1c6c08000e27..3c71938899e0 100644
--- a/drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h
+++ b/drivers/staging/rtl8723bs/hal/odm_RegDefine11N.h
@@ -111,8 +111,6 @@
#define ODM_REG_TXAGC_A_1_MCS32_11N 0xE08
#define ODM_REG_TXAGC_A_MCS0_3_11N 0xE10
#define ODM_REG_TXAGC_A_MCS4_7_11N 0xE14
-#define ODM_REG_TXAGC_A_MCS8_11_11N 0xE18
-#define ODM_REG_TXAGC_A_MCS12_15_11N 0xE1C
#define ODM_REG_FPGA0_IQK_11N 0xE28
#define ODM_REG_TXIQK_TONE_A_11N 0xE30
#define ODM_REG_RXIQK_TONE_A_11N 0xE34
diff --git a/drivers/staging/rtl8723bs/hal/odm_precomp.h b/drivers/staging/rtl8723bs/hal/odm_precomp.h
index 5041c9535e9a..edce506022a5 100644
--- a/drivers/staging/rtl8723bs/hal/odm_precomp.h
+++ b/drivers/staging/rtl8723bs/hal/odm_precomp.h
@@ -43,7 +43,6 @@
#include "HalHWImg8723B_RF.h"
#include "HalHWImg8723B_BB.h"
#include "Hal8723BReg.h"
-#include "odm_RTL8723B.h"
#include "odm_RegConfig8723B.h"
#endif /* __ODM_PRECOMP_H__ */
diff --git a/drivers/staging/rtl8723bs/hal/odm_reg.h b/drivers/staging/rtl8723bs/hal/odm_reg.h
index 1ec6ffd69dbe..a3b1f673774c 100644
--- a/drivers/staging/rtl8723bs/hal/odm_reg.h
+++ b/drivers/staging/rtl8723bs/hal/odm_reg.h
@@ -32,10 +32,8 @@
#define ODM_TXAGC_B_MCS32_5 0x838
#define ODM_TXAGC_B_MCS0_MCS3 0x83c
#define ODM_TXAGC_B_MCS4_MCS7 0x848
-#define ODM_TXAGC_B_MCS8_MCS11 0x84c
#define ODM_ANALOG_REGISTER 0x85c
#define ODM_RF_INTERFACE_OUTPUT 0x860
-#define ODM_TXAGC_B_MCS12_MCS15 0x868
#define ODM_TXAGC_B_11_A_2_11 0x86c
#define ODM_AD_DA_LSB_MASK 0x874
#define ODM_ENABLE_3_WIRE 0x88c
@@ -71,8 +69,6 @@
#define ODM_TXAGC_A_1_MCS32 0xe08
#define ODM_TXAGC_A_MCS0_MCS3 0xe10
#define ODM_TXAGC_A_MCS4_MCS7 0xe14
-#define ODM_TXAGC_A_MCS8_MCS11 0xe18
-#define ODM_TXAGC_A_MCS12_MCS15 0xe1c
/* RF REG */
#define ODM_GAIN_SETTING 0x00
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c
index 2b7077bb52df..a59ae622f05e 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTL8723B_CMD_C_
#include <drv_types.h>
#include <rtw_debug.h>
@@ -136,20 +135,20 @@ static void ConstructBeacon(struct adapter *padapter, u8 *pframe, u32 *pLength)
pktlen += 8;
/* beacon interval: 2 bytes */
- memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
pframe += 2;
pktlen += 2;
/* capability info: 2 bytes */
- memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
pframe += 2;
pktlen += 2;
if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
- pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fix_ie);
- memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fix_ie), pktlen);
+ pktlen += cur_network->ie_length - sizeof(struct ndis_802_11_fix_ie);
+ memcpy(pframe, cur_network->ies+sizeof(struct ndis_802_11_fix_ie), pktlen);
goto _ConstructBeacon;
}
@@ -157,19 +156,19 @@ static void ConstructBeacon(struct adapter *padapter, u8 *pframe, u32 *pLength)
/* below for ad-hoc mode */
/* SSID */
- pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pktlen);
/* supported rates... */
- rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen);
+ rate_len = rtw_get_rateset_len(cur_network->supported_rates);
+ pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pktlen);
/* DS parameter set */
- pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &pktlen);
if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
u32 ATIMWindow;
/* IBSS Parameter Set... */
- /* ATIMWindow = cur->Configuration.ATIMWindow; */
+ /* ATIMWindow = cur->configuration.ATIMWindow; */
ATIMWindow = 0;
pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pktlen);
}
@@ -180,7 +179,7 @@ static void ConstructBeacon(struct adapter *padapter, u8 *pframe, u32 *pLength)
/* EXTERNDED SUPPORTED RATE */
if (rate_len > 8)
- pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
+ pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->supported_rates + 8), &pktlen);
/* todo:HT for adhoc */
@@ -247,7 +246,7 @@ static void ConstructNullFunctionData(
if (bForcePowerSave)
SetPwrMgt(fctrl);
- switch (cur_network->network.InfrastructureMode) {
+ switch (cur_network->network.infrastructure_mode) {
case Ndis802_11Infrastructure:
SetToDs(fctrl);
memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c b/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c
index 5840a5241fde..2028791988e7 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c
@@ -7,8 +7,6 @@
/* Description: */
/* This file is for 92CE/92CU dynamic mechanism only */
-#define _RTL8723B_DM_C_
-
#include <drv_types.h>
#include <rtw_debug.h>
#include <rtl8723b_hal.h>
@@ -46,21 +44,11 @@ static void Init_ODM_ComInfo_8723b(struct adapter *Adapter)
ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver);
ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver);
- ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(pHalData->VersionID));
ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_PATCH_ID, pHalData->CustomerID);
/* ODM_CMNINFO_BINHCT_TEST only for MP Team */
ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
-
- if (pHalData->rf_type == RF_1T1R) {
- ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
- } else if (pHalData->rf_type == RF_2T2R) {
- ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
- } else if (pHalData->rf_type == RF_1T2R) {
- ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
- }
-
pdmpriv->InitODMFlag = ODM_RF_CALIBRATION|ODM_RF_TX_PWR_TRACK;
ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
index 059d3050acc6..cce3e7e80953 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _HAL_INIT_C_
#include <linux/firmware.h>
#include <linux/slab.h>
@@ -598,14 +597,12 @@ static void Hal_GetEfuseDefinition(
}
#define VOLTAGE_V25 0x03
-#define LDOE25_SHIFT 28
/* */
/* The following is for compile ok */
/* That should be merged with the original in the future */
/* */
#define EFUSE_ACCESS_ON_8723 0x69 /* For RTL8723 only. */
-#define EFUSE_ACCESS_OFF_8723 0x00 /* For RTL8723 only. */
#define REG_EFUSE_ACCESS_8723 0x00CF /* Efuse access protection for RTL8723 */
/* */
@@ -1643,7 +1640,6 @@ static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
value32 = rtw_read32(padapter, REG_SYS_CFG);
ChipVersion.ICType = CHIP_8723B;
ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
- ChipVersion.RFType = RF_TYPE_1T1R;
ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
@@ -1664,12 +1660,6 @@ static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
dump_chip_info(ChipVersion);
#endif
pHalData->VersionID = ChipVersion;
- if (IS_1T2R(ChipVersion))
- pHalData->rf_type = RF_1T2R;
- else if (IS_2T2R(ChipVersion))
- pHalData->rf_type = RF_2T2R;
- else
- pHalData->rf_type = RF_1T1R;
return ChipVersion;
}
@@ -2061,56 +2051,18 @@ s32 rtl8723b_InitLLTTable(struct adapter *padapter)
return ret;
}
-static bool Hal_GetChnlGroup8723B(u8 Channel, u8 *pGroup)
+static void hal_get_chnl_group_8723b(u8 channel, u8 *group)
{
- bool bIn24G = true;
-
- if (Channel <= 14) {
- bIn24G = true;
-
- if (1 <= Channel && Channel <= 2)
- *pGroup = 0;
- else if (3 <= Channel && Channel <= 5)
- *pGroup = 1;
- else if (6 <= Channel && Channel <= 8)
- *pGroup = 2;
- else if (9 <= Channel && Channel <= 11)
- *pGroup = 3;
- else if (12 <= Channel && Channel <= 14)
- *pGroup = 4;
- } else {
- bIn24G = false;
-
- if (36 <= Channel && Channel <= 42)
- *pGroup = 0;
- else if (44 <= Channel && Channel <= 48)
- *pGroup = 1;
- else if (50 <= Channel && Channel <= 58)
- *pGroup = 2;
- else if (60 <= Channel && Channel <= 64)
- *pGroup = 3;
- else if (100 <= Channel && Channel <= 106)
- *pGroup = 4;
- else if (108 <= Channel && Channel <= 114)
- *pGroup = 5;
- else if (116 <= Channel && Channel <= 122)
- *pGroup = 6;
- else if (124 <= Channel && Channel <= 130)
- *pGroup = 7;
- else if (132 <= Channel && Channel <= 138)
- *pGroup = 8;
- else if (140 <= Channel && Channel <= 144)
- *pGroup = 9;
- else if (149 <= Channel && Channel <= 155)
- *pGroup = 10;
- else if (157 <= Channel && Channel <= 161)
- *pGroup = 11;
- else if (165 <= Channel && Channel <= 171)
- *pGroup = 12;
- else if (173 <= Channel && Channel <= 177)
- *pGroup = 13;
- }
- return bIn24G;
+ if (1 <= channel && channel <= 2)
+ *group = 0;
+ else if (3 <= channel && channel <= 5)
+ *group = 1;
+ else if (6 <= channel && channel <= 8)
+ *group = 2;
+ else if (9 <= channel && channel <= 11)
+ *group = 3;
+ else if (12 <= channel && channel <= 14)
+ *group = 4;
}
void Hal_InitPGData(struct adapter *padapter, u8 *PROMContent)
@@ -2273,7 +2225,7 @@ void Hal_EfuseParseTxPowerInfo_8723B(
for (ch = 0 ; ch < CHANNEL_MAX_NUMBER; ch++) {
u8 group = 0;
- Hal_GetChnlGroup8723B(ch+1, &group);
+ hal_get_chnl_group_8723b(ch + 1, &group);
if (ch == 14-1) {
pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][5];
@@ -2321,21 +2273,21 @@ void Hal_EfuseParseBTCoexistInfo_8723B(
tempval = hwinfo[EEPROM_RF_BT_SETTING_8723B];
if (tempval != 0xFF) {
pHalData->EEPROMBluetoothAntNum = tempval & BIT(0);
- /* EFUSE_0xC3[6] == 0, S1(Main)-ODM_RF_PATH_A; */
- /* EFUSE_0xC3[6] == 1, S0(Aux)-ODM_RF_PATH_B */
- pHalData->ant_path = (tempval & BIT(6))?ODM_RF_PATH_B:ODM_RF_PATH_A;
+ /* EFUSE_0xC3[6] == 0, S1(Main)-RF_PATH_A; */
+ /* EFUSE_0xC3[6] == 1, S0(Aux)-RF_PATH_B */
+ pHalData->ant_path = (tempval & BIT(6))? RF_PATH_B : RF_PATH_A;
} else {
pHalData->EEPROMBluetoothAntNum = Ant_x1;
if (pHalData->PackageType == PACKAGE_QFN68)
- pHalData->ant_path = ODM_RF_PATH_B;
+ pHalData->ant_path = RF_PATH_B;
else
- pHalData->ant_path = ODM_RF_PATH_A;
+ pHalData->ant_path = RF_PATH_A;
}
} else {
pHalData->EEPROMBluetoothCoexist = false;
pHalData->EEPROMBluetoothType = BT_RTL8723B;
pHalData->EEPROMBluetoothAntNum = Ant_x1;
- pHalData->ant_path = ODM_RF_PATH_A;
+ pHalData->ant_path = RF_PATH_A;
}
if (padapter->registrypriv.ant_num > 0) {
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
index 6e524034f388..a3bff27af523 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
@@ -4,21 +4,11 @@
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTL8723B_PHYCFG_C_
#include <drv_types.h>
#include <rtw_debug.h>
#include <rtl8723b_hal.h>
-
-/*---------------------------Define Local Constant---------------------------*/
-/* Channel switch:The size of command tables for switch channel*/
-#define MAX_PRECMD_CNT 16
-#define MAX_RFDEPENDCMD_CNT 16
-#define MAX_POSTCMD_CNT 16
-
-#define MAX_DOZE_WAITING_TIMES_9x 64
-
/**
* phy_CalculateBitShift - Get shifted position of the BitMask.
* @BitMask: Bitmask.
@@ -318,28 +308,28 @@ static void phy_InitBBRFRegisterDefinition(struct adapter *Adapter)
struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
/* RF Interface Sowrtware Control */
- pHalData->PHYRegDef[ODM_RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 LSBs if read 32-bit from 0x870 */
- pHalData->PHYRegDef[ODM_RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 LSBs if read 32-bit from 0x870 */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
/* RF Interface Output (and Enable) */
- pHalData->PHYRegDef[ODM_RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x860 */
- pHalData->PHYRegDef[ODM_RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x864 */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x860 */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x864 */
/* RF Interface (Output and) Enable */
- pHalData->PHYRegDef[ODM_RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
- pHalData->PHYRegDef[ODM_RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
+ pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
+ pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
- pHalData->PHYRegDef[ODM_RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; /* LSSI Parameter */
- pHalData->PHYRegDef[ODM_RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
+ pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; /* LSSI Parameter */
+ pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
- pHalData->PHYRegDef[ODM_RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; /* wire control parameter2 */
- pHalData->PHYRegDef[ODM_RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; /* wire control parameter2 */
+ pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; /* wire control parameter2 */
+ pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; /* wire control parameter2 */
/* Tranceiver Readback LSSI/HSPI mode */
- pHalData->PHYRegDef[ODM_RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
- pHalData->PHYRegDef[ODM_RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
- pHalData->PHYRegDef[ODM_RF_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
- pHalData->PHYRegDef[ODM_RF_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
+ pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
+ pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
+ pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
+ pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
}
@@ -409,7 +399,7 @@ int PHY_BBConfig8723B(struct adapter *Adapter)
msleep(1);
- PHY_SetRFReg(Adapter, ODM_RF_PATH_A, 0x1, 0xfffff, 0x780);
+ PHY_SetRFReg(Adapter, RF_PATH_A, 0x1, 0xfffff, 0x780);
rtw_write8(Adapter, REG_SYS_FUNC_EN, FEN_PPLL|FEN_PCIEA|FEN_DIO_PCIE|FEN_BB_GLB_RSTn|FEN_BBRSTB);
@@ -463,7 +453,7 @@ void PHY_SetTxPowerIndex(
u8 Rate
)
{
- if (RFPath == ODM_RF_PATH_A || RFPath == ODM_RF_PATH_B) {
+ if (RFPath == RF_PATH_A || RFPath == RF_PATH_B) {
switch (Rate) {
case MGN_1M:
PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, PowerIndex);
@@ -548,7 +538,7 @@ u8 PHY_GetTxPowerIndex(
s8 txPower = 0, powerDiffByRate = 0, limit = 0;
txPower = (s8) PHY_GetTxPowerIndexBase(padapter, RFPath, Rate, BandWidth, Channel);
- powerDiffByRate = PHY_GetTxPowerByRate(padapter, ODM_RF_PATH_A, RF_1TX, Rate);
+ powerDiffByRate = PHY_GetTxPowerByRate(padapter, RF_PATH_A, Rate);
limit = phy_get_tx_pwr_lmt(
padapter,
@@ -575,10 +565,10 @@ void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 Channel)
struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
struct fat_t *pDM_FatTable = &pDM_Odm->DM_FatTable;
- u8 RFPath = ODM_RF_PATH_A;
+ u8 RFPath = RF_PATH_A;
if (pHalData->AntDivCfg) {/* antenna diversity Enable */
- RFPath = ((pDM_FatTable->RxIdleAnt == MAIN_ANT) ? ODM_RF_PATH_A : ODM_RF_PATH_B);
+ RFPath = ((pDM_FatTable->RxIdleAnt == MAIN_ANT) ? RF_PATH_A : RF_PATH_B);
} else { /* antenna diversity disable */
RFPath = pHalData->ant_path;
}
@@ -682,8 +672,8 @@ static void phy_SwChnl8723B(struct adapter *padapter)
if (pHalData->rf_chip == RF_PSEUDO_11N)
return;
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff00) | channelToSW);
- PHY_SetRFReg(padapter, ODM_RF_PATH_A, RF_CHNLBW, 0x3FF, pHalData->RfRegChnlVal[0]);
- PHY_SetRFReg(padapter, ODM_RF_PATH_B, RF_CHNLBW, 0x3FF, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(padapter, RF_PATH_A, RF_CHNLBW, 0x3FF, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(padapter, RF_PATH_B, RF_CHNLBW, 0x3FF, pHalData->RfRegChnlVal[0]);
}
static void phy_SwChnlAndSetBwMode8723B(struct adapter *Adapter)
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c b/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
index 38228b46b1ee..ffb35e1ace62 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
@@ -63,14 +63,14 @@ void PHY_RF6052SetBandwidth8723B(
switch (Bandwidth) {
case CHANNEL_WIDTH_20:
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT10 | BIT11);
- PHY_SetRFReg(Adapter, ODM_RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
- PHY_SetRFReg(Adapter, ODM_RF_PATH_B, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(Adapter, RF_PATH_B, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
break;
case CHANNEL_WIDTH_40:
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT10);
- PHY_SetRFReg(Adapter, ODM_RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
- PHY_SetRFReg(Adapter, ODM_RF_PATH_B, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
+ PHY_SetRFReg(Adapter, RF_PATH_B, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
break;
default:
@@ -97,11 +97,9 @@ static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
/*----Store original RFENV control type----*/
switch (eRFPath) {
case RF_PATH_A:
- case RF_PATH_C:
u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
break;
case RF_PATH_B:
- case RF_PATH_D:
u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16);
break;
}
@@ -128,19 +126,14 @@ static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv,
CONFIG_RF_RADIO, eRFPath);
break;
- case RF_PATH_C:
- case RF_PATH_D:
- break;
}
/*----Restore RFENV control type----*/
switch (eRFPath) {
case RF_PATH_A:
- case RF_PATH_C:
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
break;
case RF_PATH_B:
- case RF_PATH_D:
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue);
break;
}
@@ -163,11 +156,7 @@ int PHY_RF6052_Config8723B(struct adapter *Adapter)
/* */
/* Initialize general global value */
/* */
- /* TODO: Extend RF_PATH_C and RF_PATH_D in the future */
- if (pHalData->rf_type == RF_1T1R)
- pHalData->NumTotalRFPath = 1;
- else
- pHalData->NumTotalRFPath = 2;
+ pHalData->NumTotalRFPath = 1;
/* */
/* Config BB and RF */
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c b/drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c
index f2f02a69f0af..717faebf8aca 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_rxdesc.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTL8723B_REDESC_C_
#include <rtl8723b_hal.h>
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
index ad803ffc0696..418016930728 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTL8723BS_RECV_C_
#include <drv_types.h>
#include <rtw_debug.h>
@@ -130,7 +129,7 @@ static void update_recvframe_phyinfo(union recv_frame *precvframe,
/* rtl8723b_query_rx_phy_status(precvframe, pphy_status); */
/* spin_lock_bh(&p_hal_data->odm_stainfo_lock); */
- ODM_PhyStatusQuery(&p_hal_data->odmpriv, p_phy_info,
+ odm_phy_status_query(&p_hal_data->odmpriv, p_phy_info,
(u8 *)pphy_status, &(pkt_info));
if (psta)
psta->rssi = pattrib->phy_info.RecvSignalPower;
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
index a05d43b716ee..156d6aba18ca 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _RTL8723BS_XMIT_C_
#include <drv_types.h>
#include <rtw_debug.h>
diff --git a/drivers/staging/rtl8723bs/hal/sdio_halinit.c b/drivers/staging/rtl8723bs/hal/sdio_halinit.c
index a07a6dacec42..c9cd6578f7f8 100644
--- a/drivers/staging/rtl8723bs/hal/sdio_halinit.c
+++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c
@@ -556,8 +556,6 @@ static void _InitRFType(struct adapter *padapter)
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
pHalData->rf_chip = RF_6052;
-
- pHalData->rf_type = RF_1T1R;
}
static void _RfPowerSave(struct adapter *padapter)
diff --git a/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h b/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h
index aad962548278..586a3dabc5ca 100644
--- a/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h
+++ b/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h
@@ -109,7 +109,6 @@
#define rTxAGC_B_Mcs03_Mcs00 0x83c
#define rTxAGC_B_Mcs07_Mcs04 0x848
-#define rTxAGC_B_Mcs11_Mcs08 0x84c
#define rFPGA0_XA_LSSIParameter 0x840
#define rFPGA0_XB_LSSIParameter 0x844
@@ -123,7 +122,6 @@
#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */
#define rFPGA0_XB_RFInterfaceOE 0x864
-#define rTxAGC_B_Mcs15_Mcs12 0x868
#define rTxAGC_B_CCK11_A_CCK2_11 0x86c
#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Control */
@@ -303,8 +301,6 @@
#define rTxAGC_A_CCK1_Mcs32 0xe08
#define rTxAGC_A_Mcs03_Mcs00 0xe10
#define rTxAGC_A_Mcs07_Mcs04 0xe14
-#define rTxAGC_A_Mcs11_Mcs08 0xe18
-#define rTxAGC_A_Mcs15_Mcs12 0xe1c
#define rFPGA0_IQK 0xe28
#define rTx_IQK_Tone_A 0xe30
diff --git a/drivers/staging/rtl8723bs/include/HalVerDef.h b/drivers/staging/rtl8723bs/include/HalVerDef.h
index bab226f77b24..8f654a49fb9d 100644
--- a/drivers/staging/rtl8723bs/include/HalVerDef.h
+++ b/drivers/staging/rtl8723bs/include/HalVerDef.h
@@ -50,23 +50,11 @@ enum hal_vendor_e { /* tag_HAL_Manufacturer_Version_Definition */
CHIP_VENDOR_SMIC = 2,
};
-enum hal_rf_type_e { /* tag_HAL_RF_Type_Definition */
- RF_TYPE_1T1R = 0,
- RF_TYPE_1T2R = 1,
- RF_TYPE_2T2R = 2,
- RF_TYPE_2T3R = 3,
- RF_TYPE_2T4R = 4,
- RF_TYPE_3T3R = 5,
- RF_TYPE_3T4R = 6,
- RF_TYPE_4T4R = 7,
-};
-
struct hal_version { /* tag_HAL_VERSION */
enum hal_ic_type_e ICType;
enum hal_chip_type_e ChipType;
enum hal_cut_version_e CUTVersion;
enum hal_vendor_e VendorType;
- enum hal_rf_type_e RFType;
u8 ROMVer;
};
@@ -76,7 +64,6 @@ struct hal_version { /* tag_HAL_VERSION */
/* Get element */
#define GET_CVID_IC_TYPE(version) ((enum hal_ic_type_e)((version).ICType))
#define GET_CVID_CHIP_TYPE(version) ((enum hal_chip_type_e)((version).ChipType))
-#define GET_CVID_RF_TYPE(version) ((enum hal_rf_type_e)((version).RFType))
#define GET_CVID_MANUFACTUER(version) ((enum hal_vendor_e)((version).VendorType))
#define GET_CVID_CUT_VERSION(version) ((enum hal_cut_version_e)((version).CUTVersion))
#define GET_CVID_ROM_VERSION(version) (((version).ROMVer) & ROM_VERSION_MASK)
@@ -105,9 +92,4 @@ struct hal_version { /* tag_HAL_VERSION */
#define IS_CHIP_VENDOR_UMC(version) ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false)
#define IS_CHIP_VENDOR_SMIC(version) ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_SMIC) ? true : false)
-/* hal_rf_type_e */
-#define IS_1T1R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T1R) ? true : false)
-#define IS_1T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false)
-#define IS_2T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false)
-
#endif
diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h
index 895c41526164..0ce08c2a0755 100644
--- a/drivers/staging/rtl8723bs/include/drv_types.h
+++ b/drivers/staging/rtl8723bs/include/drv_types.h
@@ -57,7 +57,6 @@
#include <linux/ip.h>
#include <linux/if_ether.h>
-#include <ethernet.h>
#define SPEC_DEV_ID_NONE BIT(0)
#define SPEC_DEV_ID_DISABLE_HT BIT(1)
@@ -132,17 +131,12 @@ struct registry_priv {
u8 lowrate_two_xmit;
- u8 rf_config;
u8 low_power;
u8 wifi_spec;/* !turbo_mode */
u8 channel_plan;
- u8 btcoex;
- u8 bt_iso;
- u8 bt_sco;
- u8 bt_ampdu;
s8 ant_num;
/* false:Reject AP's Add BA req, true:accept AP's Add BA req */
@@ -500,9 +494,6 @@ static inline u8 *myid(struct eeprom_priv *peepriv)
#include <rtw_btcoex.h>
-void rtw_indicate_wx_disassoc_event(struct adapter *padapter);
-void rtw_indicate_wx_assoc_event(struct adapter *padapter);
-void indicate_wx_scan_complete_event(struct adapter *padapter);
int rtw_change_ifname(struct adapter *padapter, const char *ifname);
extern char *rtw_initmac;
diff --git a/drivers/staging/rtl8723bs/include/ethernet.h b/drivers/staging/rtl8723bs/include/ethernet.h
deleted file mode 100644
index 59899ab52aab..000000000000
--- a/drivers/staging/rtl8723bs/include/ethernet.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-/*! \file */
-#ifndef __INC_ETHERNET_H
-#define __INC_ETHERNET_H
-
-#define ETHERNET_HEADER_SIZE 14 /* Ethernet Header Length */
-#define LLC_HEADER_SIZE 6 /* LLC Header Length */
-
-#endif /* #ifndef __INC_ETHERNET_H */
diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h
index 849fb90b43b7..78599d3521bf 100644
--- a/drivers/staging/rtl8723bs/include/hal_btcoex.h
+++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h
@@ -20,8 +20,6 @@ struct bt_coexist {
u8 bInitlized;
};
-void DBG_BT_INFO(u8 *dbgmsg);
-
void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist);
bool hal_btcoex_IsBtExist(struct adapter *padapter);
bool hal_btcoex_IsBtDisabled(struct adapter *);
@@ -54,6 +52,5 @@ u8 hal_btcoex_RpwmVal(struct adapter *);
u8 hal_btcoex_LpsVal(struct adapter *);
u32 hal_btcoex_GetRaMask(struct adapter *);
void hal_btcoex_RecordPwrMode(struct adapter *padapter, u8 *pCmdBuf, u8 cmdLen);
-void hal_btcoex_DisplayBtCoexInfo(struct adapter *, u8 *pbuf, u32 bufsize);
#endif /* !__HAL_BTCOEX_H__ */
diff --git a/drivers/staging/rtl8723bs/include/hal_com.h b/drivers/staging/rtl8723bs/include/hal_com.h
index 1bc332261b2a..7be0ea20bca4 100644
--- a/drivers/staging/rtl8723bs/include/hal_com.h
+++ b/drivers/staging/rtl8723bs/include/hal_com.h
@@ -45,30 +45,6 @@
#define DESC_RATEMCS5 0x11
#define DESC_RATEMCS6 0x12
#define DESC_RATEMCS7 0x13
-#define DESC_RATEMCS8 0x14
-#define DESC_RATEMCS9 0x15
-#define DESC_RATEMCS10 0x16
-#define DESC_RATEMCS11 0x17
-#define DESC_RATEMCS12 0x18
-#define DESC_RATEMCS13 0x19
-#define DESC_RATEMCS14 0x1a
-#define DESC_RATEMCS15 0x1b
-#define DESC_RATEMCS16 0x1C
-#define DESC_RATEMCS17 0x1D
-#define DESC_RATEMCS18 0x1E
-#define DESC_RATEMCS19 0x1F
-#define DESC_RATEMCS20 0x20
-#define DESC_RATEMCS21 0x21
-#define DESC_RATEMCS22 0x22
-#define DESC_RATEMCS23 0x23
-#define DESC_RATEMCS24 0x24
-#define DESC_RATEMCS25 0x25
-#define DESC_RATEMCS26 0x26
-#define DESC_RATEMCS27 0x27
-#define DESC_RATEMCS28 0x28
-#define DESC_RATEMCS29 0x29
-#define DESC_RATEMCS30 0x2A
-#define DESC_RATEMCS31 0x2B
#define HDATA_RATE(rate)\
(rate == DESC_RATE1M) ? "CCK_1M" : \
@@ -90,16 +66,7 @@
(rate == DESC_RATEMCS4) ? "MCS4" : \
(rate == DESC_RATEMCS5) ? "MCS5" : \
(rate == DESC_RATEMCS6) ? "MCS6" : \
-(rate == DESC_RATEMCS7) ? "MCS7" : \
-(rate == DESC_RATEMCS8) ? "MCS8" : \
-(rate == DESC_RATEMCS9) ? "MCS9" : \
-(rate == DESC_RATEMCS10) ? "MCS10" : \
-(rate == DESC_RATEMCS11) ? "MCS11" : \
-(rate == DESC_RATEMCS12) ? "MCS12" : \
-(rate == DESC_RATEMCS13) ? "MCS13" : \
-(rate == DESC_RATEMCS14) ? "MCS14" : \
-(rate == DESC_RATEMCS15) ? "MCS15" : "UNKNOWN"
-
+(rate == DESC_RATEMCS7) ? "MCS7" : "UNKNOWN"
enum{
UP_LINK,
diff --git a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h
index c966d0e3e5ae..cb7c7ed74146 100644
--- a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h
+++ b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h
@@ -16,18 +16,6 @@ enum rate_section {
CCK = 0,
OFDM,
HT_MCS0_MCS7,
- HT_MCS8_MCS15,
- HT_MCS16_MCS23,
- HT_MCS24_MCS31,
-};
-
-enum {
- RF_1TX = 0,
- RF_2TX,
- RF_3TX,
- RF_4TX,
- RF_MAX_TX_NUM,
- RF_TX_NUM_NONIMPLEMENT,
};
#define MAX_POWER_INDEX 0x3F
@@ -66,7 +54,7 @@ struct bb_register_def {
};
-u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath, u8 TxNum,
+u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath,
enum rate_section RateSection);
u8 PHY_GetRateSectionIndexOfTxPowerByRate(struct adapter *padapter, u32 RegAddr,
@@ -81,9 +69,9 @@ u8 PHY_GetRateIndexOfTxPowerByRate(u8 Rate);
void PHY_SetTxPowerIndexByRateSection(struct adapter *padapter, u8 RFPath, u8 Channel,
u8 RateSection);
-s8 PHY_GetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 TxNum, u8 RateIndex);
+s8 PHY_GetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 RateIndex);
-void PHY_SetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 TxNum, u8 Rate,
+void PHY_SetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 Rate,
s8 Value);
void PHY_SetTxPowerLevelByPath(struct adapter *Adapter, u8 channel, u8 path);
@@ -94,7 +82,7 @@ void PHY_SetTxPowerIndexByRateArray(struct adapter *padapter, u8 RFPath,
void PHY_InitTxPowerByRate(struct adapter *padapter);
-void PHY_StoreTxPowerByRate(struct adapter *padapter, u32 RfPath, u32 TxNum,
+void PHY_StoreTxPowerByRate(struct adapter *padapter, u32 RfPath,
u32 RegAddr, u32 BitMask, u32 Data);
void PHY_TxPowerByRateConfiguration(struct adapter *padapter);
diff --git a/drivers/staging/rtl8723bs/include/hal_com_reg.h b/drivers/staging/rtl8723bs/include/hal_com_reg.h
index b2f179b48019..8213dcf48b34 100644
--- a/drivers/staging/rtl8723bs/include/hal_com_reg.h
+++ b/drivers/staging/rtl8723bs/include/hal_com_reg.h
@@ -662,15 +662,6 @@ Default: 00b.
#define RATR_MCS5 0x00020000
#define RATR_MCS6 0x00040000
#define RATR_MCS7 0x00080000
-/* MCS 2 Spatial Stream */
-#define RATR_MCS8 0x00100000
-#define RATR_MCS9 0x00200000
-#define RATR_MCS10 0x00400000
-#define RATR_MCS11 0x00800000
-#define RATR_MCS12 0x01000000
-#define RATR_MCS13 0x02000000
-#define RATR_MCS14 0x04000000
-#define RATR_MCS15 0x08000000
/* CCK */
#define RATE_1M BIT(0)
@@ -695,16 +686,6 @@ Default: 00b.
#define RATE_MCS5 BIT(17)
#define RATE_MCS6 BIT(18)
#define RATE_MCS7 BIT(19)
-/* MCS 2 Spatial Stream */
-#define RATE_MCS8 BIT(20)
-#define RATE_MCS9 BIT(21)
-#define RATE_MCS10 BIT(22)
-#define RATE_MCS11 BIT(23)
-#define RATE_MCS12 BIT(24)
-#define RATE_MCS13 BIT(25)
-#define RATE_MCS14 BIT(26)
-#define RATE_MCS15 BIT(27)
-
/* ALL CCK Rate */
#define RATE_BITMAP_ALL 0xFFFFF
diff --git a/drivers/staging/rtl8723bs/include/hal_data.h b/drivers/staging/rtl8723bs/include/hal_data.h
index 3298fa8eb682..b87c90f693ec 100644
--- a/drivers/staging/rtl8723bs/include/hal_data.h
+++ b/drivers/staging/rtl8723bs/include/hal_data.h
@@ -52,10 +52,8 @@ enum rt_ampdu_burst {
/* Tx Power Limit Table Size */
#define MAX_REGULATION_NUM 4
-#define MAX_2_4G_BANDWIDTH_NUM 4
-#define MAX_RATE_SECTION_NUM 10
-
-#define MAX_BASE_NUM_IN_PHY_REG_PG_2_4G 10 /* CCK:1, OFDM:1, HT:4, VHT:4 */
+#define MAX_2_4G_BANDWIDTH_NUM 2
+#define MAX_RATE_SECTION_NUM 3 /* CCK:1, OFDM:1, HT:1 */
/* duplicate code, will move to ODM ######### */
/* define IQK_MAC_REG_NUM 4 */
@@ -189,7 +187,6 @@ struct hal_com_data {
/* rf_ctrl */
u8 rf_chip;
- u8 rf_type;
u8 PackageType;
u8 NumTotalRFPath;
@@ -235,16 +232,12 @@ struct hal_com_data {
u8 TxPwrInPercentage;
u8 TxPwrCalibrateRate;
- /* TX power by rate table at most 4RF path. */
- /* The register is */
- /* VHT TX power by rate off setArray = */
- /* RF: at most 4*4 = ABCD = 0/1/2/3 */
- /* CCK = 0 OFDM = 1/2 HT-MCS 0-15 =3/4/56 VHT =7/8/9/10/11 */
+ /* TX power by rate table */
+ /* RF: at most 2 = AB = 0/1 */
+ /* CCK = 0 OFDM = 1 HT-MCS 0-7 = 2 */
u8 TxPwrByRateTable;
u8 TxPwrByRateBand;
- s8 TxPwrByRateOffset[TX_PWR_BY_RATE_NUM_RF]
- [TX_PWR_BY_RATE_NUM_RF]
- [TX_PWR_BY_RATE_NUM_RATE];
+ s8 TxPwrByRateOffset[MAX_RF_PATH_NUM][TX_PWR_BY_RATE_NUM_RATE];
/* */
/* 2 Power Limit Table */
@@ -262,9 +255,7 @@ struct hal_com_data {
[MAX_RF_PATH_NUM];
/* Store the original power by rate value of the base of each rate section of rf path A & B */
- u8 TxPwrByRateBase2_4G[TX_PWR_BY_RATE_NUM_RF]
- [TX_PWR_BY_RATE_NUM_RF]
- [MAX_BASE_NUM_IN_PHY_REG_PG_2_4G];
+ u8 TxPwrByRateBase2_4G[MAX_RF_PATH_NUM][MAX_RATE_SECTION_NUM];
/* For power group */
u8 PwrGroupHT20[RF_PATH_MAX_92C_88E][CHANNEL_MAX_NUMBER];
@@ -405,6 +396,5 @@ struct hal_com_data {
#define GET_HAL_DATA(__padapter) ((struct hal_com_data *)((__padapter)->HalData))
#define GET_HAL_RFPATH_NUM(__padapter) (((struct hal_com_data *)((__padapter)->HalData))->NumTotalRFPath)
#define RT_GetInterfaceSelection(_Adapter) (GET_HAL_DATA(_Adapter)->InterfaceSel)
-#define GET_RF_TYPE(__padapter) (GET_HAL_DATA(__padapter)->rf_type)
#endif /* __HAL_DATA_H__ */
diff --git a/drivers/staging/rtl8723bs/include/hal_pg.h b/drivers/staging/rtl8723bs/include/hal_pg.h
index 2d8ccc9ddebb..7cb9c441fc01 100644
--- a/drivers/staging/rtl8723bs/include/hal_pg.h
+++ b/drivers/staging/rtl8723bs/include/hal_pg.h
@@ -14,11 +14,9 @@
*/
#define MAX_TX_COUNT 4
-/* For VHT series TX power by rate table. */
-/* VHT TX power by rate off setArray = */
-/* RF: at most 4*4 = ABCD = 0/1/2/3 */
-/* CCK = 0 OFDM = 1/2 HT-MCS 0-15 =3/4/56 VHT =7/8/9/10/11 */
-#define TX_PWR_BY_RATE_NUM_RF 4
+/* TX power by rate table. */
+/* RF: = AB = 0/1 */
+/* CCK = 0 OFDM = 1 HT-MCS 0-7 = 2 */
#define TX_PWR_BY_RATE_NUM_RATE 84
#define MAX_RF_PATH_NUM 2
#define MAX_CHNL_GROUP_24G 6
diff --git a/drivers/staging/rtl8723bs/include/hal_phy.h b/drivers/staging/rtl8723bs/include/hal_phy.h
index 861aa71cd179..3d71a4f41592 100644
--- a/drivers/staging/rtl8723bs/include/hal_phy.h
+++ b/drivers/staging/rtl8723bs/include/hal_phy.h
@@ -30,8 +30,7 @@ enum {
enum rf_path {
RF_PATH_A = 0,
RF_PATH_B,
- RF_PATH_C,
- RF_PATH_D
+ RF_PATH_MAX
};
#define TX_1S 0
diff --git a/drivers/staging/rtl8723bs/include/ieee80211.h b/drivers/staging/rtl8723bs/include/ieee80211.h
index 378c21595e05..d6236f5b069d 100644
--- a/drivers/staging/rtl8723bs/include/ieee80211.h
+++ b/drivers/staging/rtl8723bs/include/ieee80211.h
@@ -154,20 +154,12 @@ enum network_type {
#define SUPPORTED_24G_NETTYPE_MSK (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N)
-#define IsLegacyOnly(NetType) ((NetType) == ((NetType) & (WIRELESS_11BG)))
+#define is_legacy_only(net_type) ((net_type) == ((net_type) & (WIRELESS_11BG)))
-#define IsSupported24G(NetType) ((NetType) & SUPPORTED_24G_NETTYPE_MSK ? true : false)
+#define is_supported_24g(net_type) ((net_type) & SUPPORTED_24G_NETTYPE_MSK ? true : false)
-#define IsEnableHWCCK(NetType) IsSupported24G(NetType)
-#define IsEnableHWOFDM(NetType) (((NetType) & (WIRELESS_11G|WIRELESS_11_24N)) ? true : false)
-
-#define IsSupportedRxCCK(NetType) IsEnableHWCCK(NetType)
-#define IsSupportedRxOFDM(NetType) IsEnableHWOFDM(NetType)
-#define IsSupportedRxHT(NetType) IsEnableHWOFDM(NetType)
-
-#define IsSupportedTxCCK(NetType) (((NetType) & (WIRELESS_11B)) ? true : false)
-#define IsSupportedTxOFDM(NetType) (((NetType) & (WIRELESS_11G) ? true : false)
-#define IsSupportedHT(NetType) (((NetType) & (WIRELESS_11_24N)) ? true : false)
+#define is_supported_tx_cck(net_type) (((net_type) & (WIRELESS_11B)) ? true : false)
+#define is_supported_ht(net_type) (((net_type) & (WIRELESS_11_24N)) ? true : false)
struct ieee_param {
u32 cmd;
@@ -397,30 +389,6 @@ enum {
MGN_MCS5,
MGN_MCS6,
MGN_MCS7,
- MGN_MCS8,
- MGN_MCS9,
- MGN_MCS10,
- MGN_MCS11,
- MGN_MCS12,
- MGN_MCS13,
- MGN_MCS14,
- MGN_MCS15,
- MGN_MCS16,
- MGN_MCS17,
- MGN_MCS18,
- MGN_MCS19,
- MGN_MCS20,
- MGN_MCS21,
- MGN_MCS22,
- MGN_MCS23,
- MGN_MCS24,
- MGN_MCS25,
- MGN_MCS26,
- MGN_MCS27,
- MGN_MCS28,
- MGN_MCS29,
- MGN_MCS30,
- MGN_MCS31,
MGN_UNKNOWN
};
@@ -811,7 +779,7 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork);
void rtw_macaddr_cfg(struct device *dev, u8 *mac_addr);
-u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate);
+u16 rtw_mcs_rate(u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate);
int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action);
const char *action_public_str(u8 action);
diff --git a/drivers/staging/rtl8723bs/include/osdep_intf.h b/drivers/staging/rtl8723bs/include/osdep_intf.h
index 5badd441c14b..111e0179712a 100644
--- a/drivers/staging/rtl8723bs/include/osdep_intf.h
+++ b/drivers/staging/rtl8723bs/include/osdep_intf.h
@@ -48,8 +48,6 @@ void rtw_stop_drv_threads(struct adapter *padapter);
void rtw_cancel_all_timer(struct adapter *padapter);
int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-int rtw_siocdevprivate(struct net_device *dev, struct ifreq *rq,
- void __user *data, int cmd);
int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname);
struct net_device *rtw_init_netdev(struct adapter *padapter);
diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h
index b49838c7e457..bde415db4114 100644
--- a/drivers/staging/rtl8723bs/include/osdep_service.h
+++ b/drivers/staging/rtl8723bs/include/osdep_service.h
@@ -14,10 +14,6 @@
#include <osdep_service_linux.h>
-#ifndef BIT
- #define BIT(x) (1 << (x))
-#endif
-
#define BIT0 0x00000001
#define BIT1 0x00000002
#define BIT2 0x00000004
diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
index 9dd329a5208a..ad2542d0cabe 100644
--- a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
+++ b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
@@ -394,14 +394,6 @@ struct txdesc_8723b {
#define DESC8723B_RATEMCS5 0x11
#define DESC8723B_RATEMCS6 0x12
#define DESC8723B_RATEMCS7 0x13
-#define DESC8723B_RATEMCS8 0x14
-#define DESC8723B_RATEMCS9 0x15
-#define DESC8723B_RATEMCS10 0x16
-#define DESC8723B_RATEMCS11 0x17
-#define DESC8723B_RATEMCS12 0x18
-#define DESC8723B_RATEMCS13 0x19
-#define DESC8723B_RATEMCS14 0x1a
-#define DESC8723B_RATEMCS15 0x1b
#define RX_HAL_IS_CCK_RATE_8723B(pDesc)\
(GET_RX_STATUS_DESC_RX_RATE_8723B(pDesc) == DESC8723B_RATE1M ||\
diff --git a/drivers/staging/rtl8723bs/include/rtw_ioctl_set.h b/drivers/staging/rtl8723bs/include/rtw_ioctl_set.h
index 31424bf2d926..ab349de733c8 100644
--- a/drivers/staging/rtl8723bs/include/rtw_ioctl_set.h
+++ b/drivers/staging/rtl8723bs/include/rtw_ioctl_set.h
@@ -11,7 +11,6 @@
typedef u8 NDIS_802_11_PMKID_VALUE[16];
u8 rtw_set_802_11_authentication_mode(struct adapter *pdapter, enum ndis_802_11_authentication_mode authmode);
-u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid);
u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep);
u8 rtw_set_802_11_disassociate(struct adapter *padapter);
u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num);
diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme.h b/drivers/staging/rtl8723bs/include/rtw_mlme.h
index 5deb73fe3885..c94fa7d8d5a9 100644
--- a/drivers/staging/rtl8723bs/include/rtw_mlme.h
+++ b/drivers/staging/rtl8723bs/include/rtw_mlme.h
@@ -445,9 +445,9 @@ extern signed int rtw_set_key(struct adapter *adapter, struct security_priv *pse
extern signed int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv);
static inline u8 *get_bssid(struct mlme_priv *pmlmepriv)
-{ /* if sta_mode:pmlmepriv->cur_network.network.MacAddress => bssid */
- /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress => ibss mac address */
- return pmlmepriv->cur_network.network.MacAddress;
+{ /* if sta_mode:pmlmepriv->cur_network.network.mac_address => bssid */
+ /* if adhoc_mode:pmlmepriv->cur_network.network.mac_address => ibss mac address */
+ return pmlmepriv->cur_network.network.mac_address;
}
static inline signed int check_fwstate(struct mlme_priv *pmlmepriv, signed int state)
diff --git a/drivers/staging/rtl8723bs/include/rtw_recv.h b/drivers/staging/rtl8723bs/include/rtw_recv.h
index 9c3cdcc990fa..a88b7c088a86 100644
--- a/drivers/staging/rtl8723bs/include/rtw_recv.h
+++ b/drivers/staging/rtl8723bs/include/rtw_recv.h
@@ -35,6 +35,8 @@
#define MAX_SUBFRAME_COUNT 64
+#define LLC_HEADER_LENGTH 6
+
/* for Rx reordering buffer control */
struct recv_reorder_ctrl {
struct adapter *padapter;
diff --git a/drivers/staging/rtl8723bs/include/rtw_rf.h b/drivers/staging/rtl8723bs/include/rtw_rf.h
index 6c25707f4ec8..718275ee4500 100644
--- a/drivers/staging/rtl8723bs/include/rtw_rf.h
+++ b/drivers/staging/rtl8723bs/include/rtw_rf.h
@@ -97,16 +97,6 @@ enum {
HT_DATA_SC_20_LOWER_OF_40MHZ = 2,
};
-/* 2007/11/15 MH Define different RF type. */
-enum {
- RF_1T2R = 0,
- RF_2T4R = 1,
- RF_2T2R = 2,
- RF_1T1R = 3,
- RF_2T2R_GREEN = 4,
- RF_MAX_TYPE = 5,
-};
-
u32 rtw_ch2freq(u32 ch);
#endif /* _RTL8711_RF_H_ */
diff --git a/drivers/staging/rtl8723bs/include/wifi.h b/drivers/staging/rtl8723bs/include/wifi.h
index 0bd7b662b972..f03e26818d45 100644
--- a/drivers/staging/rtl8723bs/include/wifi.h
+++ b/drivers/staging/rtl8723bs/include/wifi.h
@@ -7,14 +7,6 @@
#ifndef _WIFI_H_
#define _WIFI_H_
-
-#ifdef BIT
-/* error "BIT define occurred earlier elsewhere!\n" */
-#undef BIT
-#endif
-#define BIT(x) (1 << (x))
-
-
#define WLAN_ETHHDR_LEN 14
#define WLAN_ETHADDR_LEN 6
#define WLAN_IEEE_OUI_LEN 3
diff --git a/drivers/staging/rtl8723bs/include/wlan_bssdef.h b/drivers/staging/rtl8723bs/include/wlan_bssdef.h
index a45990bed80c..eb38594c8f5c 100644
--- a/drivers/staging/rtl8723bs/include/wlan_bssdef.h
+++ b/drivers/staging/rtl8723bs/include/wlan_bssdef.h
@@ -20,8 +20,8 @@ typedef unsigned char NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; /*
typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; /* Set of 16 data rates */
struct ndis_802_11_ssid {
- u32 SsidLength;
- u8 Ssid[32];
+ u32 ssid_length;
+ u8 ssid[32];
};
enum ndis_802_11_network_type {
@@ -32,23 +32,15 @@ enum ndis_802_11_network_type {
Ndis802_11NetworkTypeMax /* not a real type, defined as an upper bound */
};
-struct ndis_802_11_conf_fh {
- u32 Length; /* Length of structure */
- u32 HopPattern; /* As defined by 802.11, MSB set */
- u32 HopSet; /* to one if non-802.11 */
- u32 DwellTime; /* units are Kusec */
-};
-
/*
FW will only save the channel number in DSConfig.
ODI Handler will convert the channel number to freq. number.
*/
struct ndis_802_11_conf {
- u32 Length; /* Length of structure */
- u32 BeaconPeriod; /* units are Kusec */
- u32 ATIMWindow; /* units are Kusec */
- u32 DSConfig; /* Frequency, units are kHz */
- struct ndis_802_11_conf_fh FHConfig;
+ u32 length; /* Length of structure */
+ u32 beacon_period; /* units are Kusec */
+ u32 atim_window; /* units are Kusec */
+ u32 ds_config; /* Frequency, units are kHz */
};
enum ndis_802_11_network_infrastructure {
@@ -60,14 +52,14 @@ enum ndis_802_11_network_infrastructure {
};
struct ndis_802_11_fix_ie {
- u8 Timestamp[8];
- u16 BeaconInterval;
- u16 Capabilities;
+ u8 time_stamp[8];
+ u16 beacon_interval;
+ u16 capabilities;
};
struct ndis_80211_var_ie {
- u8 ElementID;
- u8 Length;
+ u8 element_id;
+ u8 length;
u8 data[];
};
@@ -75,9 +67,9 @@ struct ndis_80211_var_ie {
* sizeof (NDIS_802_11_MAC_ADDRESS) + 2 +
* sizeof (struct ndis_802_11_ssid) + sizeof (u32) +
* sizeof (long) + sizeof (enum ndis_802_11_network_type) +
- * sizeof (struct ndis_802_11_conf) + sizeof (NDIS_802_11_RATES_EX) + IELength
+ * sizeof (struct ndis_802_11_conf) + sizeof (NDIS_802_11_RATES_EX) + ie_length
*
- * Except for IELength, all other fields are fixed length. Therefore, we can
+ * Except for ie_length, all other fields are fixed length. Therefore, we can
* define a macro to present the partial sum.
*/
enum ndis_802_11_authentication_mode {
@@ -115,25 +107,13 @@ enum {
#define NDIS_802_11_AI_RESFI_STATUSCODE 2
#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4
-struct ndis_802_11_ai_reqfi {
- u16 Capabilities;
- u16 ListenInterval;
- NDIS_802_11_MAC_ADDRESS CurrentAPAddress;
-};
-
-struct ndis_801_11_ai_resfi {
- u16 Capabilities;
- u16 StatusCode;
- u16 AssociationId;
-};
-
/* Key mapping keys require a BSSID */
struct ndis_802_11_wep {
- u32 Length; /* Length of this structure */
- u32 KeyIndex; /* 0 is the per-client key, 1-N are the global keys */
- u32 KeyLength; /* length of key in bytes */
- u8 KeyMaterial[16];/* variable length depending on above field */
+ u32 length; /* Length of this structure */
+ u32 key_index; /* 0 is the per-client key, 1-N are the global keys */
+ u32 key_length; /* length of key in bytes */
+ u8 key_material[16];/* variable length depending on above field */
};
/* mask for authentication/integrity fields */
@@ -151,10 +131,10 @@ struct ndis_802_11_wep {
#endif
struct wlan_phy_info {
- u8 SignalStrength;/* in percentage) */
- u8 SignalQuality;/* in percentage) */
- u8 Optimum_antenna; /* for Antenna diversity */
- u8 Reserved_0;
+ u8 signal_strength;/* in percentage) */
+ u8 signal_quality;/* in percentage) */
+ u8 optimum_antenna; /* for Antenna diversity */
+ u8 reserved_0;
};
struct wlan_bcn_info {
@@ -174,24 +154,24 @@ struct wlan_bcn_info {
* struct wlan_bssid_ex and get_wlan_bssid_ex_sz()
*/
struct wlan_bssid_ex {
- u32 Length;
- NDIS_802_11_MAC_ADDRESS MacAddress;
- u8 Reserved[2];/* 0]: IS beacon frame */
- struct ndis_802_11_ssid Ssid;
- u32 Privacy;
- long Rssi;/* in dBM, raw data , get from PHY) */
- enum ndis_802_11_network_type NetworkTypeInUse;
- struct ndis_802_11_conf Configuration;
- enum ndis_802_11_network_infrastructure InfrastructureMode;
- NDIS_802_11_RATES_EX SupportedRates;
- struct wlan_phy_info PhyInfo;
- u32 IELength;
- u8 IEs[MAX_IE_SZ]; /* timestamp, beacon interval, and capability information) */
+ u32 length;
+ NDIS_802_11_MAC_ADDRESS mac_address;
+ u8 reserved[2];/* 0]: IS beacon frame */
+ struct ndis_802_11_ssid ssid;
+ u32 privacy;
+ long rssi;/* in dBM, raw data , get from PHY) */
+ enum ndis_802_11_network_type network_type_in_use;
+ struct ndis_802_11_conf configuration;
+ enum ndis_802_11_network_infrastructure infrastructure_mode;
+ NDIS_802_11_RATES_EX supported_rates;
+ struct wlan_phy_info phy_info;
+ u32 ie_length;
+ u8 ies[MAX_IE_SZ]; /* timestamp, beacon interval, and capability information) */
} __packed;
static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
{
- return (sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->IELength);
+ return (sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->ie_length);
}
struct wlan_network {
@@ -202,7 +182,7 @@ struct wlan_network {
int aid; /* will only be valid when a BSS is joinned. */
int join_res;
struct wlan_bssid_ex network; /* must be the last item */
- struct wlan_bcn_info BcnInfo;
+ struct wlan_bcn_info bcn_info;
};
enum {
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
index fd747c8d920e..499ac3a77512 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _IOCTL_CFG80211_C_
#include <linux/etherdevice.h>
#include <drv_types.h>
@@ -71,8 +70,6 @@ static struct ieee80211_rate rtw_rates[] = {
RATETAB_ENT(540, 0x800, 0),
};
-#define rtw_a_rates (rtw_rates + 4)
-#define RTW_A_RATES_NUM 8
#define rtw_g_rates (rtw_rates + 0)
#define RTW_G_RATES_NUM 12
@@ -231,14 +228,14 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
struct wiphy *wiphy = wdev->wiphy;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- bssinf_len = pnetwork->network.IELength + sizeof(struct ieee80211_hdr_3addr);
+ bssinf_len = pnetwork->network.ie_length + sizeof(struct ieee80211_hdr_3addr);
if (bssinf_len > MAX_BSSINFO_LEN)
goto exit;
{
u16 wapi_len = 0;
- if (rtw_get_wapi_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &wapi_len) > 0)
+ if (rtw_get_wapi_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &wapi_len) > 0)
{
if (wapi_len > 0)
goto exit;
@@ -250,13 +247,13 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
if (adapter_wdev_data(padapter)->scan_request)
{
u8 *psr = NULL, sr = 0;
- struct ndis_802_11_ssid *pssid = &pnetwork->network.Ssid;
+ struct ndis_802_11_ssid *pssid = &pnetwork->network.ssid;
struct cfg80211_scan_request *request = adapter_wdev_data(padapter)->scan_request;
struct cfg80211_ssid *ssids = request->ssids;
u32 wpsielen = 0;
u8 *wpsie = NULL;
- wpsie = rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);
+ wpsie = rtw_get_wps_ie(pnetwork->network.ies+_FIXED_IE_LENGTH_, pnetwork->network.ie_length-_FIXED_IE_LENGTH_, NULL, &wpsielen);
if (wpsie && wpsielen > 0)
psr = rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
@@ -266,8 +263,8 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
if (request->n_ssids == 1 && request->n_channels == 1) /* it means under processing WPS */
{
if (ssids[0].ssid_len != 0 &&
- (pssid->SsidLength != ssids[0].ssid_len ||
- memcmp(pssid->Ssid, ssids[0].ssid, ssids[0].ssid_len)))
+ (pssid->ssid_length != ssids[0].ssid_len ||
+ memcmp(pssid->ssid, ssids[0].ssid, ssids[0].ssid_len)))
{
if (psr)
*psr = 0; /* clear sr */
@@ -278,7 +275,7 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
/* spin_unlock_bh(&pwdev_priv->scan_req_lock); */
- channel = pnetwork->network.Configuration.DSConfig;
+ channel = pnetwork->network.configuration.ds_config;
freq = rtw_ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
notify_channel = ieee80211_get_channel(wiphy, freq);
@@ -290,7 +287,7 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
notify_signal = 100*translate_percentage_to_dbm(padapter->recvpriv.signal_strength);/* dbm */
} else {
- notify_signal = 100*translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);/* dbm */
+ notify_signal = 100*translate_percentage_to_dbm(pnetwork->network.phy_info.signal_strength);/* dbm */
}
buf = kzalloc(MAX_BSSINFO_LEN, GFP_ATOMIC);
@@ -305,7 +302,7 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
/* pmlmeext->mgnt_seq++; */
- if (pnetwork->network.Reserved[0] == 1) { /* WIFI_BEACON */
+ if (pnetwork->network.reserved[0] == 1) { /* WIFI_BEACON */
eth_broadcast_addr(pwlanhdr->addr1);
SetFrameSubType(pbuf, WIFI_BEACON);
} else {
@@ -313,15 +310,15 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
SetFrameSubType(pbuf, WIFI_PROBERSP);
}
- memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);
- memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, pnetwork->network.mac_address, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, pnetwork->network.mac_address, ETH_ALEN);
pbuf += sizeof(struct ieee80211_hdr_3addr);
len = sizeof(struct ieee80211_hdr_3addr);
- memcpy(pbuf, pnetwork->network.IEs, pnetwork->network.IELength);
- len += pnetwork->network.IELength;
+ memcpy(pbuf, pnetwork->network.ies, pnetwork->network.ie_length);
+ len += pnetwork->network.ie_length;
*((__le64 *)pbuf) = cpu_to_le64(notify_timestamp);
@@ -355,12 +352,12 @@ int rtw_cfg80211_check_bss(struct adapter *padapter)
if (!(pnetwork) || !(padapter->rtw_wdev))
return false;
- freq = rtw_ieee80211_channel_to_frequency(pnetwork->Configuration.DSConfig, NL80211_BAND_2GHZ);
+ freq = rtw_ieee80211_channel_to_frequency(pnetwork->configuration.ds_config, NL80211_BAND_2GHZ);
notify_channel = ieee80211_get_channel(padapter->rtw_wdev->wiphy, freq);
bss = cfg80211_get_bss(padapter->rtw_wdev->wiphy, notify_channel,
- pnetwork->MacAddress, pnetwork->Ssid.Ssid,
- pnetwork->Ssid.SsidLength,
+ pnetwork->mac_address, pnetwork->ssid.ssid,
+ pnetwork->ssid.ssid_length,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);
@@ -374,7 +371,7 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter)
struct wlan_network *cur_network = &(pmlmepriv->cur_network);
struct wireless_dev *pwdev = padapter->rtw_wdev;
struct wiphy *wiphy = pwdev->wiphy;
- int freq = (int)cur_network->network.Configuration.DSConfig;
+ int freq = (int)cur_network->network.configuration.ds_config;
struct ieee80211_channel *chan;
if (pwdev->iftype != NL80211_IFTYPE_ADHOC)
@@ -398,8 +395,8 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter)
rtw_warn_on(1);
return;
}
- if (!memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(struct ndis_802_11_ssid))
- && !memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS))
+ if (!memcmp(&(scanned->network.ssid), &(pnetwork->ssid), sizeof(struct ndis_802_11_ssid))
+ && !memcmp(scanned->network.mac_address, pnetwork->mac_address, sizeof(NDIS_802_11_MAC_ADDRESS))
)
rtw_cfg80211_inform_bss(padapter, scanned);
else
@@ -413,7 +410,7 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter)
}
/* notify cfg80211 that device joined an IBSS */
chan = ieee80211_get_channel(wiphy, freq);
- cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, chan, GFP_ATOMIC);
+ cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.mac_address, chan, GFP_ATOMIC);
}
void rtw_cfg80211_indicate_connect(struct adapter *padapter)
@@ -440,8 +437,8 @@ void rtw_cfg80211_indicate_connect(struct adapter *padapter)
goto check_bss;
}
- if (!memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS))
- && !memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(struct ndis_802_11_ssid))
+ if (!memcmp(scanned->network.mac_address, pnetwork->mac_address, sizeof(NDIS_802_11_MAC_ADDRESS))
+ && !memcmp(&(scanned->network.ssid), &(pnetwork->ssid), sizeof(struct ndis_802_11_ssid))
)
rtw_cfg80211_inform_bss(padapter, scanned);
else
@@ -458,7 +455,7 @@ check_bss:
struct wiphy *wiphy = pwdev->wiphy;
struct ieee80211_channel *notify_channel;
u32 freq;
- u16 channel = cur_network->network.Configuration.DSConfig;
+ u16 channel = cur_network->network.configuration.ds_config;
struct cfg80211_roam_info roam_info = {};
freq = rtw_ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
@@ -466,7 +463,7 @@ check_bss:
notify_channel = ieee80211_get_channel(wiphy, freq);
roam_info.channel = notify_channel;
- roam_info.bssid = cur_network->network.MacAddress;
+ roam_info.bssid = cur_network->network.mac_address;
roam_info.req_ie =
pmlmepriv->assoc_req+sizeof(struct ieee80211_hdr_3addr)+2;
roam_info.req_ie_len =
@@ -479,7 +476,7 @@ check_bss:
}
else
{
- cfg80211_connect_result(padapter->pnetdev, cur_network->network.MacAddress
+ cfg80211_connect_result(padapter->pnetdev, cur_network->network.mac_address
, pmlmepriv->assoc_req+sizeof(struct ieee80211_hdr_3addr)+2
, pmlmepriv->assoc_req_len-sizeof(struct ieee80211_hdr_3addr)-2
, pmlmepriv->assoc_rsp+sizeof(struct ieee80211_hdr_3addr)+6
@@ -1113,7 +1110,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
{
struct wlan_network *cur_network = &(pmlmepriv->cur_network);
- if (memcmp((u8 *)mac, cur_network->network.MacAddress, ETH_ALEN)) {
+ if (memcmp((u8 *)mac, cur_network->network.mac_address, ETH_ALEN)) {
ret = -ENOENT;
goto exit;
}
@@ -1241,8 +1238,8 @@ void rtw_cfg80211_unlink_bss(struct adapter *padapter, struct wlan_network *pnet
struct wlan_bssid_ex *select_network = &pnetwork->network;
bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/,
- select_network->MacAddress, select_network->Ssid.Ssid,
- select_network->Ssid.SsidLength, 0/*WLAN_CAPABILITY_ESS*/,
+ select_network->mac_address, select_network->ssid.ssid,
+ select_network->ssid.ssid_length, 0/*WLAN_CAPABILITY_ESS*/,
0/*WLAN_CAPABILITY_ESS*/);
if (bss) {
@@ -1266,8 +1263,8 @@ void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter)
pnetwork = list_entry(plist, struct wlan_network, list);
/* report network only if the current channel set contains the channel to which this network belongs */
- if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
- && true == rtw_validate_ssid(&(pnetwork->network.Ssid))
+ if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.configuration.ds_config) >= 0
+ && true == rtw_validate_ssid(&(pnetwork->network.ssid))
)
{
/* ev =translate_scan(padapter, a, pnetwork, ev, stop); */
@@ -1398,8 +1395,8 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
/* parsing request ssids, n_ssids */
for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
- memcpy(ssid[i].Ssid, ssids[i].ssid, ssids[i].ssid_len);
- ssid[i].SsidLength = ssids[i].ssid_len;
+ memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
+ ssid[i].ssid_length = ssids[i].ssid_len;
}
/* parsing channels, n_channels */
@@ -1730,8 +1727,8 @@ static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
}
memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
- ndis_ssid.SsidLength = params->ssid_len;
- memcpy(ndis_ssid.Ssid, (u8 *)params->ssid, params->ssid_len);
+ ndis_ssid.ssid_length = params->ssid_len;
+ memcpy(ndis_ssid.ssid, (u8 *)params->ssid, params->ssid_len);
psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
@@ -1822,8 +1819,8 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
}
memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
- ndis_ssid.SsidLength = sme->ssid_len;
- memcpy(ndis_ssid.Ssid, (u8 *)sme->ssid, sme->ssid_len);
+ ndis_ssid.ssid_length = sme->ssid_len;
+ memcpy(ndis_ssid.ssid, (u8 *)sme->ssid, sme->ssid_len);
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
ret = -EBUSY;
@@ -1874,7 +1871,7 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
if (wep_key_len > 0) {
wep_key_len = wep_key_len <= 5 ? 5 : 13;
- wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
+ wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
pwep = rtw_malloc(wep_total_len);
if (pwep == NULL) {
ret = -ENOMEM;
@@ -1883,8 +1880,8 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
memset(pwep, 0, wep_total_len);
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_total_len;
+ pwep->key_length = wep_key_len;
+ pwep->length = wep_total_len;
if (wep_key_len == 13) {
padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
@@ -1895,10 +1892,10 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
goto exit;
}
- pwep->KeyIndex = wep_key_idx;
- pwep->KeyIndex |= 0x80000000;
+ pwep->key_index = wep_key_idx;
+ pwep->key_index |= 0x80000000;
- memcpy(pwep->KeyMaterial, (void *)sme->key, pwep->KeyLength);
+ memcpy(pwep->key_material, (void *)sme->key, pwep->key_length);
if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
ret = -EOPNOTSUPP;
@@ -2100,7 +2097,58 @@ void rtw_cfg80211_indicate_sta_disassoc(struct adapter *padapter, unsigned char
cfg80211_del_sta(ndev, da, GFP_ATOMIC);
}
+static u8 rtw_get_chan_type(struct adapter *adapter)
+{
+ struct mlme_ext_priv *mlme_ext = &adapter->mlmeextpriv;
+
+ switch (mlme_ext->cur_bwmode) {
+ case CHANNEL_WIDTH_20:
+ if (is_supported_ht(adapter->registrypriv.wireless_mode))
+ return NL80211_CHAN_HT20;
+ else
+ return NL80211_CHAN_NO_HT;
+ case CHANNEL_WIDTH_40:
+ if (mlme_ext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
+ return NL80211_CHAN_HT40PLUS;
+ else
+ return NL80211_CHAN_HT40MINUS;
+ default:
+ return NL80211_CHAN_HT20;
+ }
+
+ return NL80211_CHAN_HT20;
+}
+
+static int cfg80211_rtw_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct cfg80211_chan_def *chandef)
+{
+ struct adapter *adapter = wiphy_to_adapter(wiphy);
+ struct registry_priv *registrypriv = &adapter->registrypriv;
+ enum nl80211_channel_type chan_type;
+ struct ieee80211_channel *chan = NULL;
+ int channel;
+ int freq;
+
+ if (!adapter->rtw_wdev)
+ return -ENODEV;
+
+ channel = rtw_get_oper_ch(adapter);
+ if (!channel)
+ return -ENODATA;
+
+ freq = rtw_ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
+ chan = ieee80211_get_channel(adapter->rtw_wdev->wiphy, freq);
+
+ if (registrypriv->ht_enable) {
+ chan_type = rtw_get_chan_type(adapter);
+ cfg80211_chandef_create(chandef, chan, chan_type);
+ } else {
+ cfg80211_chandef_create(chandef, chan, NL80211_CHAN_NO_HT);
+ }
+
+ return 0;
+}
static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struct net_device *ndev)
{
@@ -2384,7 +2432,7 @@ static int rtw_add_beacon(struct adapter *adapter, const u8 *head, size_t head_l
/* check wps ie if inclued */
rtw_get_wps_ie(pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
- /* pbss_network->IEs will not include p2p_ie, wfd ie */
+ /* pbss_network->ies will not include p2p_ie, wfd ie */
rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, WLAN_EID_VENDOR_SPECIFIC, P2P_OUI, 4);
rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, WLAN_EID_VENDOR_SPECIFIC, WFD_OUI, 4);
@@ -2415,10 +2463,10 @@ static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct wlan_bssid_ex *pbss_network = &adapter->mlmepriv.cur_network.network;
struct wlan_bssid_ex *pbss_network_ext = &adapter->mlmeextpriv.mlmext_info.network;
- memcpy(pbss_network->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);
- pbss_network->Ssid.SsidLength = settings->ssid_len;
- memcpy(pbss_network_ext->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);
- pbss_network_ext->Ssid.SsidLength = settings->ssid_len;
+ memcpy(pbss_network->ssid.ssid, (void *)settings->ssid, settings->ssid_len);
+ pbss_network->ssid.ssid_length = settings->ssid_len;
+ memcpy(pbss_network_ext->ssid.ssid, (void *)settings->ssid, settings->ssid_len);
+ pbss_network_ext->ssid.ssid_length = settings->ssid_len;
}
return ret;
@@ -2707,7 +2755,7 @@ exit:
return ret;
}
-static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, enum nl80211_band band, u8 rf_type)
+static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, enum nl80211_band band)
{
#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
@@ -2740,34 +2788,23 @@ static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, enum
*if BW_40 rx_mask[4]= 0x01;
*highest supported RX rate
*/
- if (rf_type == RF_1T1R) {
- ht_cap->mcs.rx_mask[0] = 0xFF;
- ht_cap->mcs.rx_mask[1] = 0x00;
- ht_cap->mcs.rx_mask[4] = 0x01;
-
- ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
- } else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
- ht_cap->mcs.rx_mask[0] = 0xFF;
- ht_cap->mcs.rx_mask[1] = 0xFF;
- ht_cap->mcs.rx_mask[4] = 0x01;
+ ht_cap->mcs.rx_mask[0] = 0xFF;
+ ht_cap->mcs.rx_mask[1] = 0x00;
+ ht_cap->mcs.rx_mask[4] = 0x01;
- ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
- }
+ ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
}
void rtw_cfg80211_init_wiphy(struct adapter *padapter)
{
- u8 rf_type;
struct ieee80211_supported_band *bands;
struct wireless_dev *pwdev = padapter->rtw_wdev;
struct wiphy *wiphy = pwdev->wiphy;
- rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-
{
bands = wiphy->bands[NL80211_BAND_2GHZ];
if (bands)
- rtw_cfg80211_init_ht_capab(&bands->ht_cap, NL80211_BAND_2GHZ, rf_type);
+ rtw_cfg80211_init_ht_capab(&bands->ht_cap, NL80211_BAND_2GHZ);
}
/* copy mac_addr to wiphy */
@@ -2838,7 +2875,7 @@ static struct cfg80211_ops rtw_cfg80211_ops = {
.set_pmksa = cfg80211_rtw_set_pmksa,
.del_pmksa = cfg80211_rtw_del_pmksa,
.flush_pmksa = cfg80211_rtw_flush_pmksa,
-
+ .get_channel = cfg80211_rtw_get_channel,
.add_virtual_intf = cfg80211_rtw_add_virtual_intf,
.del_virtual_intf = cfg80211_rtw_del_virtual_intf,
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
index aa7bd76bb5f1..9d4a233a861e 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
******************************************************************************/
-#define _IOCTL_LINUX_C_
#include <linux/etherdevice.h>
#include <drv_types.h>
@@ -30,335 +29,21 @@
#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
#define WEXT_CSCAN_TYPE_SECTION 'T'
-static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
- 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
-
-void indicate_wx_scan_complete_event(struct adapter *padapter)
-{
- union iwreq_data wrqu;
-
- memset(&wrqu, 0, sizeof(union iwreq_data));
-}
-
-
-void rtw_indicate_wx_assoc_event(struct adapter *padapter)
-{
- union iwreq_data wrqu;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-
- memset(&wrqu, 0, sizeof(union iwreq_data));
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)
- memcpy(wrqu.ap_addr.sa_data, pnetwork->MacAddress, ETH_ALEN);
- else
- memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
-
- netdev_dbg(padapter->pnetdev, "assoc success\n");
-}
-
-void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
-{
- union iwreq_data wrqu;
-
- memset(&wrqu, 0, sizeof(union iwreq_data));
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- eth_zero_addr(wrqu.ap_addr.sa_data);
-}
-
-static char *translate_scan(struct adapter *padapter,
- struct iw_request_info *info, struct wlan_network *pnetwork,
- char *start, char *stop)
-{
- struct iw_event iwe;
- u16 cap;
- u32 ht_ielen = 0;
- char *custom = NULL;
- char *p;
- u16 max_rate = 0, rate, ht_cap = false, vht_cap = false;
- u32 i = 0;
- u8 bw_40MHz = 0, short_GI = 0;
- u16 mcs_rate = 0, vht_data_rate = 0;
- u8 ie_offset = (pnetwork->network.Reserved[0] == 2 ? 0 : 12);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- u8 ss, sq;
-
- /* AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-
- memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
-
- /* Add the ESSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
-
- /* parsing HT_CAP_IE */
- if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
- p = rtw_get_ie(&pnetwork->network.IEs[0], WLAN_EID_HT_CAPABILITY, &ht_ielen, pnetwork->network.IELength);
- } else {
- p = rtw_get_ie(&pnetwork->network.IEs[12], WLAN_EID_HT_CAPABILITY, &ht_ielen, pnetwork->network.IELength-12);
- }
- if (p && ht_ielen > 0) {
- struct ieee80211_ht_cap *pht_capie;
- ht_cap = true;
- pht_capie = (struct ieee80211_ht_cap *)(p+2);
- memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
- bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
- short_GI = (le16_to_cpu(pht_capie->cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
- }
-
- /* Add the protocol name */
- iwe.cmd = SIOCGIWNAME;
- if (rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates)) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
- } else if (rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates)) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
- } else {
- if (pnetwork->network.Configuration.DSConfig > 14) {
- if (vht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11AC");
- else if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
- } else {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
- }
- }
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
-
- /* Add mode */
- if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
- cap = 0;
- } else {
- __le16 le_tmp;
-
- iwe.cmd = SIOCGIWMODE;
- memcpy((u8 *)&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
- cap = le16_to_cpu(le_tmp);
- }
-
- if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_ESS)) {
- if (cap & WLAN_CAPABILITY_ESS)
- iwe.u.mode = IW_MODE_MASTER;
- else
- iwe.u.mode = IW_MODE_ADHOC;
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
- }
-
- if (pnetwork->network.Configuration.DSConfig < 1 /*|| pnetwork->network.Configuration.DSConfig > 14*/)
- pnetwork->network.Configuration.DSConfig = 1;
-
- /* Add frequency/channel */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
- iwe.u.freq.e = 1;
- iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (cap & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- else
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- iwe.u.data.length = 0;
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
-
- /*Add basic and extended rates */
- max_rate = 0;
- custom = kzalloc(MAX_CUSTOM_LEN, GFP_ATOMIC);
- if (!custom)
- return start;
- p = custom;
- p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
- while (pnetwork->network.SupportedRates[i] != 0) {
- rate = pnetwork->network.SupportedRates[i]&0x7F;
- if (rate > max_rate)
- max_rate = rate;
- p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom),
- "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
- i++;
- }
-
- if (vht_cap) {
- max_rate = vht_data_rate;
- } else if (ht_cap) {
- if (mcs_rate & 0x8000) /* MCS15 */
- max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
- else /* default MCS7 */
- max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
-
- max_rate = max_rate*2;/* Mbps/2; */
- }
-
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = max_rate * 500000;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
-
- /* parsing WPA/WPA2 IE */
- if (pnetwork->network.Reserved[0] != 2) { /* Probe Request */
- u8 *buf;
- u8 wpa_ie[255], rsn_ie[255];
- u16 wpa_len = 0, rsn_len = 0;
- u8 *p;
- rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
-
- buf = kzalloc(MAX_WPA_IE_LEN*2, GFP_ATOMIC);
- if (!buf)
- return start;
- if (wpa_len > 0) {
- p = buf;
- p += scnprintf(p, (MAX_WPA_IE_LEN * 2) - (p - buf), "wpa_ie =");
- for (i = 0; i < wpa_len; i++)
- p += scnprintf(p, (MAX_WPA_IE_LEN * 2) - (p - buf),
- "%02x", wpa_ie[i]);
-
- if (wpa_len > 100) {
- printk("-----------------Len %d----------------\n", wpa_len);
- for (i = 0; i < wpa_len; i++)
- printk("%02x ", wpa_ie[i]);
- printk("\n");
- printk("-----------------Len %d----------------\n", wpa_len);
- }
-
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop, &iwe, buf);
-
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = wpa_len;
- start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
- }
- if (rsn_len > 0) {
- p = buf;
- memset(buf, 0, MAX_WPA_IE_LEN*2);
- p += scnprintf(p, (MAX_WPA_IE_LEN * 2) - (p - buf), "rsn_ie =");
- for (i = 0; i < rsn_len; i++)
- p += scnprintf(p, (MAX_WPA_IE_LEN * 2) - (p - buf),
- "%02x", rsn_ie[i]);
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop, &iwe, buf);
-
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = rsn_len;
- start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
- }
- kfree(buf);
- }
-
- { /* parsing WPS IE */
- uint cnt = 0, total_ielen;
- u8 *wpsie_ptr = NULL;
- uint wps_ielen = 0;
-
- u8 *ie_ptr;
- total_ielen = pnetwork->network.IELength - ie_offset;
-
- if (pnetwork->network.Reserved[0] == 2) { /* Probe Request */
- ie_ptr = pnetwork->network.IEs;
- total_ielen = pnetwork->network.IELength;
- } else { /* Beacon or Probe Respones */
- ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
- total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
- }
-
- while (cnt < total_ielen) {
- if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
- wpsie_ptr = &ie_ptr[cnt];
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = (u16)wps_ielen;
- start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
- }
- cnt += ie_ptr[cnt + 1] + 2; /* goto next */
- }
- }
-
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_INVALID;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
- is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
- ss = padapter->recvpriv.signal_strength;
- sq = padapter->recvpriv.signal_qual;
- } else {
- ss = pnetwork->network.PhyInfo.SignalStrength;
- sq = pnetwork->network.PhyInfo.SignalQuality;
- }
-
-
- iwe.u.qual.level = (u8)ss;/* */
-
- iwe.u.qual.qual = (u8)sq; /* signal quality */
-
- iwe.u.qual.noise = 0; /* noise level */
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
-
- {
- u8 *buf;
- u8 *pos;
-
- buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC);
- if (!buf)
- goto exit;
-
- pos = pnetwork->network.Reserved;
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = scnprintf(buf, MAX_WPA_IE_LEN, "fm =%02X%02X", pos[1], pos[0]);
- start = iwe_stream_add_point(info, start, stop, &iwe, buf);
- kfree(buf);
- }
-exit:
- kfree(custom);
-
- return start;
-}
-
static int wpa_set_auth_algs(struct net_device *dev, u32 value)
{
struct adapter *padapter = rtw_netdev_priv(dev);
int ret = 0;
- if ((value & WLAN_AUTH_SHARED_KEY) && (value & WLAN_AUTH_OPEN)) {
+ if ((value & IW_AUTH_ALG_SHARED_KEY) && (value & IW_AUTH_ALG_OPEN_SYSTEM)) {
padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
- } else if (value & WLAN_AUTH_SHARED_KEY) {
+ } else if (value & IW_AUTH_ALG_SHARED_KEY) {
padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
- } else if (value & WLAN_AUTH_OPEN) {
+ } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
/* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
@@ -418,15 +103,15 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
if (wep_key_len > 0) {
wep_key_len = wep_key_len <= 5 ? 5 : 13;
- wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
+ wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
pwep = kzalloc(wep_total_len, GFP_KERNEL);
if (!pwep) {
ret = -ENOMEM;
goto exit;
}
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_total_len;
+ pwep->key_length = wep_key_len;
+ pwep->length = wep_total_len;
if (wep_key_len == 13) {
padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
@@ -437,10 +122,10 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
goto exit;
}
- pwep->KeyIndex = wep_key_idx;
- pwep->KeyIndex |= 0x80000000;
+ pwep->key_index = wep_key_idx;
+ pwep->key_index |= 0x80000000;
- memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
+ memcpy(pwep->key_material, param->u.crypt.key, pwep->key_length);
if (param->u.crypt.set_tx) {
if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
@@ -454,8 +139,8 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
goto exit;
}
- memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
- psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+ memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
+ psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true);
}
@@ -662,12 +347,12 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie
}
/* TKIP and AES disallow multicast packets until installing group key */
- if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
- || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
- || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
- /* WPS open need to enable multicast */
- /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */
- rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
+ if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_ ||
+ padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_ ||
+ padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
+ /* WPS open need to enable multicast */
+ /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */
+ rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
exit:
@@ -676,2084 +361,6 @@ exit:
return ret;
}
-static int rtw_wx_get_name(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- u32 ht_ielen = 0;
- char *p;
- u8 ht_cap = false, vht_cap = false;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- NDIS_802_11_RATES_EX *prates = NULL;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
- /* parsing HT_CAP_IE */
- p = rtw_get_ie(&pcur_bss->IEs[12], WLAN_EID_HT_CAPABILITY, &ht_ielen, pcur_bss->IELength-12);
- if (p && ht_ielen > 0)
- ht_cap = true;
-
- prates = &pcur_bss->SupportedRates;
-
- if (rtw_is_cckratesonly_included((u8 *)prates)) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
- } else if (rtw_is_cckrates_included((u8 *)prates)) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
- } else {
- if (pcur_bss->Configuration.DSConfig > 14) {
- if (vht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11AC");
- else if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
- } else {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
- }
- }
- } else {
- /* prates = &padapter->registrypriv.dev_network.SupportedRates; */
- /* snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); */
- snprintf(wrqu->name, IFNAMSIZ, "unassociated");
- }
- return 0;
-}
-
-static int rtw_wx_set_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- return 0;
-}
-
-static int rtw_wx_get_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
- /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
- wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = pcur_bss->Configuration.DSConfig;
-
- } else {
- wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
- }
-
- return 0;
-}
-
-static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- enum ndis_802_11_network_infrastructure networkType;
- int ret = 0;
-
- if (_FAIL == rtw_pwr_wakeup(padapter)) {
- ret = -EPERM;
- goto exit;
- }
-
- if (!padapter->hw_init_completed) {
- ret = -EPERM;
- goto exit;
- }
-
- switch (wrqu->mode) {
- case IW_MODE_AUTO:
- networkType = Ndis802_11AutoUnknown;
- break;
- case IW_MODE_ADHOC:
- networkType = Ndis802_11IBSS;
- break;
- case IW_MODE_MASTER:
- networkType = Ndis802_11APMode;
- /* rtw_setopmode_cmd(padapter, networkType, true); */
- break;
- case IW_MODE_INFRA:
- networkType = Ndis802_11Infrastructure;
- break;
- default:
- ret = -EINVAL;
- goto exit;
- }
-
-/*
- if (Ndis802_11APMode == networkType)
- {
- rtw_setopmode_cmd(padapter, networkType, true);
- }
- else
- {
- rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown, true);
- }
-*/
-
- if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
-
- ret = -EPERM;
- goto exit;
-
- }
-
- rtw_setopmode_cmd(padapter, networkType, true);
-
-exit:
- return ret;
-}
-
-static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
- wrqu->mode = IW_MODE_INFRA;
- } else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
- wrqu->mode = IW_MODE_ADHOC;
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
- wrqu->mode = IW_MODE_MASTER;
- } else {
- wrqu->mode = IW_MODE_AUTO;
- }
- return 0;
-}
-
-
-static int rtw_wx_set_pmkid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- u8 j, blInserted = false;
- int intReturn = false;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
- u8 strZeroMacAddress[ETH_ALEN] = { 0x00 };
- u8 strIssueBssid[ETH_ALEN] = { 0x00 };
-
- /*
- There are the BSSID information in the bssid.sa_data array.
- If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
- If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver.
- If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver.
- */
-
- memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
- if (pPMK->cmd == IW_PMKSA_ADD) {
- if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
- return intReturn;
- else
- intReturn = true;
-
- blInserted = false;
-
- /* overwrite PMKID */
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
-
- memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
- psecuritypriv->PMKIDList[j].bUsed = true;
- psecuritypriv->PMKIDIndex = j+1;
- blInserted = true;
- break;
- }
- }
-
- if (!blInserted) {
-
- memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
- memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
-
- psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
- psecuritypriv->PMKIDIndex++;
- if (psecuritypriv->PMKIDIndex == 16)
- psecuritypriv->PMKIDIndex = 0;
- }
- } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
- intReturn = true;
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
- eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
- psecuritypriv->PMKIDList[j].bUsed = false;
- break;
- }
- }
- } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
- memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
- psecuritypriv->PMKIDIndex = 0;
- intReturn = true;
- }
- return intReturn;
-}
-
-static int rtw_wx_get_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- {
- wrqu->sens.value = 0;
- wrqu->sens.fixed = 0; /* no auto select */
- wrqu->sens.disabled = 1;
- }
- return 0;
-}
-
-static int rtw_wx_get_range(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_range *range = (struct iw_range *)extra;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
- u16 val;
- int i;
-
- wrqu->data.length = sizeof(*range);
- memset(range, 0, sizeof(*range));
-
- /* Let's try to keep this struct in the same order as in
- * linux/include/wireless.h
- */
-
- /* TODO: See what values we can set, and remove the ones we can't
- * set, or fill them with some default data.
- */
-
- /* ~5 Mb/s real (802.11b) */
- range->throughput = 5 * 1000 * 1000;
-
- /* signal level threshold range */
-
- /* percent values between 0 and 100. */
- range->max_qual.qual = 100;
- range->max_qual.level = 100;
- range->max_qual.noise = 100;
- range->max_qual.updated = 7; /* Updated all three */
-
-
- range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
- range->avg_qual.level = 256 - 78;
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 7; /* Updated all three */
-
- range->num_bitrates = RATE_COUNT;
-
- for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
- range->bitrate[i] = rtw_rates[i];
-
- range->min_frag = MIN_FRAG_THRESHOLD;
- range->max_frag = MAX_FRAG_THRESHOLD;
-
- range->pm_capa = 0;
-
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
-
- for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
-
- /* Include only legal frequencies for some countries */
- if (pmlmeext->channel_set[i].ChannelNum != 0) {
- range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
- range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
- range->freq[val].e = 1;
- val++;
- }
-
- if (val == IW_MAX_FREQUENCIES)
- break;
- }
-
- range->num_channels = val;
- range->num_frequency = val;
-
-/* Commented by Albert 2009/10/13 */
-/* The following code will proivde the security capability to network manager. */
-/* If the driver doesn't provide this capability to network manager, */
-/* the WPA/WPA2 routers can't be chosen in the network manager. */
-
-/*
-#define IW_SCAN_CAPA_NONE 0x00
-#define IW_SCAN_CAPA_ESSID 0x01
-#define IW_SCAN_CAPA_BSSID 0x02
-#define IW_SCAN_CAPA_CHANNEL 0x04
-#define IW_SCAN_CAPA_MODE 0x08
-#define IW_SCAN_CAPA_RATE 0x10
-#define IW_SCAN_CAPA_TYPE 0x20
-#define IW_SCAN_CAPA_TIME 0x40
-*/
-
- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
-
- range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_BSSID |
- IW_SCAN_CAPA_CHANNEL | IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
-
- return 0;
-}
-
-/* set bssid flow */
-/* s1. rtw_set_802_11_infrastructure_mode() */
-/* s2. rtw_set_802_11_authentication_mode() */
-/* s3. set_802_11_encryption_mode() */
-/* s4. rtw_set_802_11_bssid() */
-static int rtw_wx_set_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra)
-{
- uint ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct sockaddr *temp = (struct sockaddr *)awrq;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct list_head *phead;
- u8 *dst_bssid, *src_bssid;
- struct __queue *queue = &(pmlmepriv->scanned_queue);
- struct wlan_network *pnetwork = NULL;
- enum ndis_802_11_authentication_mode authmode;
-
- rtw_ps_deny(padapter, PS_DENY_JOIN);
- if (_FAIL == rtw_pwr_wakeup(padapter)) {
- ret = -1;
- goto exit;
- }
-
- if (!padapter->bup) {
- ret = -1;
- goto exit;
- }
-
-
- if (temp->sa_family != ARPHRD_ETHER) {
- ret = -EINVAL;
- goto exit;
- }
-
- authmode = padapter->securitypriv.ndisauthtype;
- spin_lock_bh(&queue->lock);
- phead = get_list_head(queue);
- list_for_each(pmlmepriv->pscanned, phead) {
- pnetwork = list_entry(pmlmepriv->pscanned,
- struct wlan_network, list);
-
- dst_bssid = pnetwork->network.MacAddress;
-
- src_bssid = temp->sa_data;
-
- if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
- if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
- ret = -1;
- spin_unlock_bh(&queue->lock);
- goto exit;
- }
- break;
- }
-
- }
- spin_unlock_bh(&queue->lock);
-
- rtw_set_802_11_authentication_mode(padapter, authmode);
- /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
- if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
- ret = -1;
- goto exit;
- }
-
-exit:
-
- rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
-
- return ret;
-}
-
-static int rtw_wx_get_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- wrqu->ap_addr.sa_family = ARPHRD_ETHER;
-
- eth_zero_addr(wrqu->ap_addr.sa_data);
-
- if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
- ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
- ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true)) {
- memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
- } else {
- eth_zero_addr(wrqu->ap_addr.sa_data);
- }
-
- return 0;
-}
-
-static int rtw_wx_set_mlme(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct iw_mlme *mlme = (struct iw_mlme *)extra;
-
-
- if (mlme == NULL)
- return -1;
-
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- if (!rtw_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- case IW_MLME_DISASSOC:
- if (!rtw_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- u8 _status = false;
- int ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
-
- rtw_ps_deny(padapter, PS_DENY_SCAN);
- if (_FAIL == rtw_pwr_wakeup(padapter)) {
- ret = -1;
- goto exit;
- }
-
- if (padapter->bDriverStopped) {
- ret = -1;
- goto exit;
- }
-
- if (!padapter->bup) {
- ret = -1;
- goto exit;
- }
-
- if (!padapter->hw_init_completed) {
- ret = -1;
- goto exit;
- }
-
- /* When Busy Traffic, driver do not site survey. So driver return success. */
- /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
- /* modify by thomas 2011-02-22. */
- if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
- indicate_wx_scan_complete_event(padapter);
- goto exit;
- }
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) {
- indicate_wx_scan_complete_event(padapter);
- goto exit;
- }
-
- memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
-
- if (wrqu->data.length == sizeof(struct iw_scan_req)) {
- struct iw_scan_req *req = (struct iw_scan_req *)extra;
-
- if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
-
- memcpy(ssid[0].Ssid, req->essid, len);
- ssid[0].SsidLength = len;
-
- spin_lock_bh(&pmlmepriv->lock);
-
- _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
-
- spin_unlock_bh(&pmlmepriv->lock);
-
- }
-
- } else if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
- && !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
- int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
- char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
- char section;
- char sec_len;
- int ssid_index = 0;
-
- while (len >= 1) {
- section = *(pos++); len -= 1;
-
- switch (section) {
- case WEXT_CSCAN_SSID_SECTION:
- if (len < 1) {
- len = 0;
- break;
- }
-
- sec_len = *(pos++); len -= 1;
-
- if (sec_len > 0 && sec_len <= len) {
- ssid[ssid_index].SsidLength = sec_len;
- memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
- ssid_index++;
- }
-
- pos += sec_len; len -= sec_len;
- break;
-
-
- case WEXT_CSCAN_CHANNEL_SECTION:
- pos += 1; len -= 1;
- break;
- case WEXT_CSCAN_ACTV_DWELL_SECTION:
- pos += 2; len -= 2;
- break;
- case WEXT_CSCAN_PASV_DWELL_SECTION:
- pos += 2; len -= 2;
- break;
- case WEXT_CSCAN_HOME_DWELL_SECTION:
- pos += 2; len -= 2;
- break;
- case WEXT_CSCAN_TYPE_SECTION:
- pos += 1; len -= 1;
- break;
- default:
- len = 0; /* stop parsing */
- }
- }
-
- /* jeff: it has still some scan parameter to parse, we only do this now... */
- _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
-
- } else {
- _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
- }
-
- if (_status == false)
- ret = -1;
-
-exit:
-
- rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
-
- return ret;
-}
-
-static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct list_head *plist, *phead;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct __queue *queue = &(pmlmepriv->scanned_queue);
- struct wlan_network *pnetwork = NULL;
- char *ev = extra;
- char *stop = ev + wrqu->data.length;
- u32 ret = 0;
- signed int wait_status;
-
- if (adapter_to_pwrctl(padapter)->brfoffbyhw && padapter->bDriverStopped) {
- ret = -EINVAL;
- goto exit;
- }
-
- wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
-
- if (check_fwstate(pmlmepriv, wait_status))
- return -EAGAIN;
-
- spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
- phead = get_list_head(queue);
- list_for_each(plist, phead) {
- if ((stop - ev) < SCAN_ITEM_SIZE) {
- ret = -E2BIG;
- break;
- }
-
- pnetwork = list_entry(plist, struct wlan_network, list);
-
- /* report network only if the current channel set contains the channel to which this network belongs */
- if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
- && true == rtw_validate_ssid(&(pnetwork->network.Ssid))) {
-
- ev = translate_scan(padapter, a, pnetwork, ev, stop);
- }
-
- }
-
- spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-
- wrqu->data.length = ev-extra;
- wrqu->data.flags = 0;
-
-exit:
-
- return ret;
-
-}
-
-/* set ssid flow */
-/* s1. rtw_set_802_11_infrastructure_mode() */
-/* s2. set_802_11_authenticaion_mode() */
-/* s3. set_802_11_encryption_mode() */
-/* s4. rtw_set_802_11_ssid() */
-static int rtw_wx_set_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct list_head *phead;
- struct wlan_network *pnetwork = NULL;
- enum ndis_802_11_authentication_mode authmode;
- struct ndis_802_11_ssid ndis_ssid;
- u8 *dst_ssid, *src_ssid;
-
- uint ret = 0, len;
-
- rtw_ps_deny(padapter, PS_DENY_JOIN);
- if (_FAIL == rtw_pwr_wakeup(padapter)) {
- ret = -1;
- goto exit;
- }
-
- if (!padapter->bup) {
- ret = -1;
- goto exit;
- }
-
- if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
- ret = -E2BIG;
- goto exit;
- }
-
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- ret = -1;
- goto exit;
- }
-
- authmode = padapter->securitypriv.ndisauthtype;
- if (wrqu->essid.flags && wrqu->essid.length) {
- len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
-
- memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
- ndis_ssid.SsidLength = len;
- memcpy(ndis_ssid.Ssid, extra, len);
- src_ssid = ndis_ssid.Ssid;
-
- spin_lock_bh(&queue->lock);
- phead = get_list_head(queue);
- list_for_each(pmlmepriv->pscanned, phead) {
- pnetwork = list_entry(pmlmepriv->pscanned,
- struct wlan_network, list);
-
- dst_ssid = pnetwork->network.Ssid.Ssid;
-
- if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
- (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
- if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
- continue;
- }
-
- if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == false) {
- ret = -1;
- spin_unlock_bh(&queue->lock);
- goto exit;
- }
-
- break;
- }
- }
- spin_unlock_bh(&queue->lock);
- rtw_set_802_11_authentication_mode(padapter, authmode);
- /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
- if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
- ret = -1;
- goto exit;
- }
- }
-
-exit:
-
- rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
-
- return ret;
-}
-
-static int rtw_wx_get_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- u32 len, ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
- (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
- len = pcur_bss->Ssid.SsidLength;
-
- wrqu->essid.length = len;
-
- memcpy(extra, pcur_bss->Ssid.Ssid, len);
-
- wrqu->essid.flags = 1;
- } else {
- ret = -1;
- goto exit;
- }
-
-exit:
- return ret;
-}
-
-static int rtw_wx_set_rate(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- int i, ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- u8 datarates[NumRates];
- u32 target_rate = wrqu->bitrate.value;
- u32 fixed = wrqu->bitrate.fixed;
- u32 ratevalue = 0;
- u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
-
- if (target_rate == -1) {
- ratevalue = 11;
- goto set_rate;
- }
- target_rate = target_rate/100000;
-
- switch (target_rate) {
- case 10:
- ratevalue = 0;
- break;
- case 20:
- ratevalue = 1;
- break;
- case 55:
- ratevalue = 2;
- break;
- case 60:
- ratevalue = 3;
- break;
- case 90:
- ratevalue = 4;
- break;
- case 110:
- ratevalue = 5;
- break;
- case 120:
- ratevalue = 6;
- break;
- case 180:
- ratevalue = 7;
- break;
- case 240:
- ratevalue = 8;
- break;
- case 360:
- ratevalue = 9;
- break;
- case 480:
- ratevalue = 10;
- break;
- case 540:
- ratevalue = 11;
- break;
- default:
- ratevalue = 11;
- break;
- }
-
-set_rate:
-
- for (i = 0; i < NumRates; i++) {
- if (ratevalue == mpdatarate[i]) {
- datarates[i] = mpdatarate[i];
- if (fixed == 0)
- break;
- } else {
- datarates[i] = 0xff;
- }
- }
-
- if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS)
- ret = -1;
-
- return ret;
-}
-
-static int rtw_wx_get_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u16 max_rate = 0;
-
- max_rate = rtw_get_cur_max_rate(rtw_netdev_priv(dev));
-
- if (max_rate == 0)
- return -EPERM;
-
- wrqu->bitrate.fixed = 0; /* no auto select */
- wrqu->bitrate.value = max_rate * 100000;
-
- return 0;
-}
-
-static int rtw_wx_set_rts(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
-
- if (wrqu->rts.disabled)
- padapter->registrypriv.rts_thresh = 2347;
- else {
- if (wrqu->rts.value < 0 ||
- wrqu->rts.value > 2347)
- return -EINVAL;
-
- padapter->registrypriv.rts_thresh = wrqu->rts.value;
- }
-
- return 0;
-}
-
-static int rtw_wx_get_rts(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
-
- wrqu->rts.value = padapter->registrypriv.rts_thresh;
- wrqu->rts.fixed = 0; /* no auto select */
- /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
-
- return 0;
-}
-
-static int rtw_wx_set_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
-
- if (wrqu->frag.disabled)
- padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
- else {
- if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
- wrqu->frag.value > MAX_FRAG_THRESHOLD)
- return -EINVAL;
-
- padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
- }
-
- return 0;
-
-}
-
-static int rtw_wx_get_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
-
- wrqu->frag.value = padapter->xmitpriv.frag_len;
- wrqu->frag.fixed = 0; /* no auto select */
- /* wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); */
-
- return 0;
-}
-
-static int rtw_wx_get_retry(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- /* struct adapter *padapter = rtw_netdev_priv(dev); */
-
-
- wrqu->retry.value = 7;
- wrqu->retry.fixed = 0; /* no auto select */
- wrqu->retry.disabled = 1;
-
- return 0;
-
-}
-
-static int rtw_wx_set_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- u32 key, ret = 0;
- u32 keyindex_provided;
- struct ndis_802_11_wep wep;
- enum ndis_802_11_authentication_mode authmode;
-
- struct iw_point *erq = &(wrqu->encoding);
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-
- memset(&wep, 0, sizeof(struct ndis_802_11_wep));
-
- key = erq->flags & IW_ENCODE_INDEX;
-
- if (erq->flags & IW_ENCODE_DISABLED) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
-
- goto exit;
- }
-
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- keyindex_provided = 1;
- } else {
- keyindex_provided = 0;
- key = padapter->securitypriv.dot11PrivacyKeyIndex;
- }
-
- /* set authentication mode */
- if (erq->flags & IW_ENCODE_OPEN) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
-
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
-
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- } else if (erq->flags & IW_ENCODE_RESTRICTED) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
-
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
-
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
- authmode = Ndis802_11AuthModeShared;
- padapter->securitypriv.ndisauthtype = authmode;
- } else {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- }
-
- wep.KeyIndex = key;
- if (erq->length > 0) {
- wep.KeyLength = erq->length <= 5 ? 5 : 13;
-
- wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
- } else {
- wep.KeyLength = 0;
-
- if (keyindex_provided == 1) { /* set key_id only, no given KeyMaterial(erq->length == 0). */
- padapter->securitypriv.dot11PrivacyKeyIndex = key;
-
- switch (padapter->securitypriv.dot11DefKeylen[key]) {
- case 5:
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
- break;
- case 13:
- padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
- break;
- default:
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- break;
- }
-
- goto exit;
-
- }
-
- }
-
- wep.KeyIndex |= 0x80000000;
-
- memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
-
- if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
- if (rf_on == pwrpriv->rf_pwrstate)
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
-exit:
- return ret;
-}
-
-static int rtw_wx_get_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- uint key, ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct iw_point *erq = &(wrqu->encoding);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-
- if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
- }
-
-
- key = erq->flags & IW_ENCODE_INDEX;
-
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- } else {
- key = padapter->securitypriv.dot11PrivacyKeyIndex;
- }
-
- erq->flags = key + 1;
-
- /* if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) */
- /* */
- /* erq->flags |= IW_ENCODE_OPEN; */
- /* */
-
- switch (padapter->securitypriv.ndisencryptstatus) {
- case Ndis802_11EncryptionNotSupported:
- case Ndis802_11EncryptionDisabled:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- case Ndis802_11Encryption1Enabled:
- erq->length = padapter->securitypriv.dot11DefKeylen[key];
-
- if (erq->length) {
- memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
-
- erq->flags |= IW_ENCODE_ENABLED;
-
- if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
- erq->flags |= IW_ENCODE_OPEN;
- else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
- erq->flags |= IW_ENCODE_RESTRICTED;
- } else {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- }
- break;
- case Ndis802_11Encryption2Enabled:
- case Ndis802_11Encryption3Enabled:
- erq->length = 16;
- erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
- break;
- default:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- }
- return ret;
-}
-
-static int rtw_wx_get_power(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- /* struct adapter *padapter = rtw_netdev_priv(dev); */
-
- wrqu->power.value = 0;
- wrqu->power.fixed = 0; /* no auto select */
- wrqu->power.disabled = 1;
-
- return 0;
-}
-
-static int rtw_wx_set_gen_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
-
- return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
-}
-
-static int rtw_wx_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct iw_param *param = (struct iw_param *)&(wrqu->param);
- int ret = 0;
-
- switch (param->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- break;
- case IW_AUTH_CIPHER_GROUP:
- break;
- case IW_AUTH_KEY_MGMT:
- /*
- * ??? does not use these parameters
- */
- break;
- case IW_AUTH_TKIP_COUNTERMEASURES:
- /* wpa_supplicant is setting the tkip countermeasure. */
- if (param->value) /* enabling */
- padapter->securitypriv.btkip_countermeasure = true;
- else /* disabling */
- padapter->securitypriv.btkip_countermeasure = false;
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
-
- /*
- * This means init value, or using wep, ndisencryptstatus =
- * Ndis802_11Encryption1Enabled, then it needn't reset it;
- */
- if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
- break;
-
- if (param->value) {
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
- }
-
- break;
- case IW_AUTH_80211_AUTH_ALG:
- /*
- * It's the starting point of a link layer connection using wpa_supplicant
- */
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
- LeaveAllPowerSaveMode(padapter);
- rtw_disassoc_cmd(padapter, 500, false);
- rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter, 1);
- }
-
- ret = wpa_set_auth_algs(dev, (u32)param->value);
- break;
- case IW_AUTH_WPA_ENABLED:
- break;
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- break;
- case IW_AUTH_PRIVACY_INVOKED:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int rtw_wx_set_enc_ext(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- char *alg_name;
- u32 param_len;
- struct ieee_param *param = NULL;
- struct iw_point *pencoding = &wrqu->encoding;
- struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
- int ret = 0;
-
- param_len = sizeof(struct ieee_param) + pext->key_len;
- param = kzalloc(param_len, GFP_KERNEL);
- if (param == NULL)
- return -1;
-
- param->cmd = IEEE_CMD_SET_ENCRYPTION;
- eth_broadcast_addr(param->sta_addr);
-
-
- switch (pext->alg) {
- case IW_ENCODE_ALG_NONE:
- /* todo: remove key */
- /* remove = 1; */
- alg_name = "none";
- break;
- case IW_ENCODE_ALG_WEP:
- alg_name = "WEP";
- break;
- case IW_ENCODE_ALG_TKIP:
- alg_name = "TKIP";
- break;
- case IW_ENCODE_ALG_CCMP:
- alg_name = "CCMP";
- break;
- case IW_ENCODE_ALG_AES_CMAC:
- alg_name = "BIP";
- break;
- default:
- ret = -1;
- goto exit;
- }
-
- strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
-
- if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
- param->u.crypt.set_tx = 1;
-
- /* cliW: WEP does not have group key
- * just not checking GROUP key setting
- */
- if ((pext->alg != IW_ENCODE_ALG_WEP) &&
- ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
- || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC))) {
- param->u.crypt.set_tx = 0;
- }
-
- param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
-
- if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- memcpy(param->u.crypt.seq, pext->rx_seq, 8);
-
- if (pext->key_len) {
- param->u.crypt.key_len = pext->key_len;
- /* memcpy(param + 1, pext + 1, pext->key_len); */
- memcpy(param->u.crypt.key, pext + 1, pext->key_len);
- }
-
- if (pencoding->flags & IW_ENCODE_DISABLED) {
- /* todo: remove key */
- /* remove = 1; */
- }
-
- ret = wpa_set_encryption(dev, param, param_len);
-
-exit:
- kfree(param);
-
- return ret;
-}
-
-
-static int rtw_wx_get_nick(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- /* struct adapter *padapter = rtw_netdev_priv(dev); */
- /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
- /* struct security_priv *psecuritypriv = &padapter->securitypriv; */
-
- if (extra) {
- wrqu->data.length = 14;
- wrqu->data.flags = 1;
- memcpy(extra, "<WIFI@REALTEK>", 14);
- }
- return 0;
-}
-
-static int rtw_wx_read32(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter;
- struct iw_point *p;
- u16 len;
- u32 addr;
- u32 data32;
- u32 bytes;
- u8 *ptmp;
- int ret;
-
-
- ret = 0;
- padapter = rtw_netdev_priv(dev);
- p = &wrqu->data;
- len = p->length;
- if (0 == len)
- return -EINVAL;
-
- ptmp = rtw_malloc(len);
- if (NULL == ptmp)
- return -ENOMEM;
-
- if (copy_from_user(ptmp, p->pointer, len)) {
- ret = -EFAULT;
- goto exit;
- }
-
- bytes = 0;
- addr = 0;
- sscanf(ptmp, "%d,%x", &bytes, &addr);
-
- switch (bytes) {
- case 1:
- data32 = rtw_read8(padapter, addr);
- sprintf(extra, "0x%02X", data32);
- break;
- case 2:
- data32 = rtw_read16(padapter, addr);
- sprintf(extra, "0x%04X", data32);
- break;
- case 4:
- data32 = rtw_read32(padapter, addr);
- sprintf(extra, "0x%08X", data32);
- break;
- default:
- ret = -EINVAL;
- goto exit;
- }
-
-exit:
- kfree(ptmp);
-
- return ret;
-}
-
-static int rtw_wx_write32(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
-
- u32 addr;
- u32 data32;
- u32 bytes;
-
-
- bytes = 0;
- addr = 0;
- data32 = 0;
- sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
-
- switch (bytes) {
- case 1:
- rtw_write8(padapter, addr, (u8)data32);
- break;
- case 2:
- rtw_write16(padapter, addr, (u16)data32);
- break;
- case 4:
- rtw_write32(padapter, addr, data32);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int rtw_wx_read_rf(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- u32 path, addr, data32;
-
-
- path = *(u32 *)extra;
- addr = *((u32 *)extra + 1);
- data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
- /*
- * IMPORTANT!!
- * Only when wireless private ioctl is at odd order,
- * "extra" would be copied to user space.
- */
- sprintf(extra, "0x%05x", data32);
-
- return 0;
-}
-
-static int rtw_wx_write_rf(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- u32 path, addr, data32;
-
-
- path = *(u32 *)extra;
- addr = *((u32 *)extra + 1);
- data32 = *((u32 *)extra + 2);
- rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
-
- return 0;
-}
-
-static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- return -1;
-}
-
-static int dummy(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- /* struct adapter *padapter = rtw_netdev_priv(dev); */
- /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
-
- return -1;
-
-}
-
-static int rtw_wx_set_channel_plan(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- u8 channel_plan_req = (u8)(*((int *)wrqu));
-
- if (rtw_set_chplan_cmd(padapter, channel_plan_req, 1, 1) != _SUCCESS)
- return -EPERM;
-
- return 0;
-}
-
-static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- return 0;
-}
-
-static int rtw_wx_get_sensitivity(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *buf)
-{
- return 0;
-}
-
-static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- return 0;
-}
-
-/*
-typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-*/
-/*
- *For all data larger than 16 octets, we need to use a
- *pointer to memory allocated in user space.
- */
-static int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- return 0;
-}
-
-static int rtw_get_ap_info(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- int wpa_ielen;
- u32 cnt = 0;
- struct list_head *plist, *phead;
- unsigned char *pbuf;
- u8 bssid[ETH_ALEN];
- char data[32];
- struct wlan_network *pnetwork = NULL;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct __queue *queue = &(pmlmepriv->scanned_queue);
- struct iw_point *pdata = &wrqu->data;
-
- if ((padapter->bDriverStopped) || (pdata == NULL)) {
- ret = -EINVAL;
- goto exit;
- }
-
- while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == true) {
- msleep(30);
- cnt++;
- if (cnt > 100)
- break;
- }
-
-
- /* pdata->length = 0;? */
- pdata->flags = 0;
- if (pdata->length >= 32) {
- if (copy_from_user(data, pdata->pointer, 32)) {
- ret = -EINVAL;
- goto exit;
- }
- } else {
- ret = -EINVAL;
- goto exit;
- }
-
- spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-
- phead = get_list_head(queue);
- list_for_each(plist, phead) {
- pnetwork = list_entry(plist, struct wlan_network, list);
-
- if (!mac_pton(data, bssid)) {
- spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
- return -EINVAL;
- }
-
-
- if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) { /* BSSID match, then check if supporting wpa/wpa2 */
-
- pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
- if (pbuf && (wpa_ielen > 0)) {
- pdata->flags = 1;
- break;
- }
-
- pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
- if (pbuf && (wpa_ielen > 0)) {
- pdata->flags = 2;
- break;
- }
- }
-
- }
-
- spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-
- if (pdata->length >= 34) {
- if (copy_to_user((u8 __force __user *)pdata->pointer+32, (u8 *)&pdata->flags, 1)) {
- ret = -EINVAL;
- goto exit;
- }
- }
-
-exit:
-
- return ret;
-
-}
-
-static int rtw_set_pid(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- int *pdata = (int *)wrqu;
- int selector;
-
- if ((padapter->bDriverStopped) || (pdata == NULL)) {
- ret = -EINVAL;
- goto exit;
- }
-
- selector = *pdata;
- if (selector < 3 && selector >= 0)
- padapter->pid[selector] = *(pdata+1);
-
-exit:
-
- return ret;
-
-}
-
-static int rtw_wps_start(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- int ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- u32 u32wps_start = 0;
-
- if ((true == padapter->bDriverStopped) || (true == padapter->bSurpriseRemoved) || (NULL == pdata)) {
- ret = -EINVAL;
- goto exit;
- }
-
- if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4)) {
- ret = -EFAULT;
- goto exit;
- }
- if (u32wps_start == 0)
- u32wps_start = *extra;
-
-exit:
-
- return ret;
-
-}
-
-static int rtw_p2p_set(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- return 0;
-
-}
-
-static int rtw_p2p_get(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- return 0;
-
-}
-
-static int rtw_p2p_get2(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- return 0;
-
-}
-
-static int rtw_rereg_nd_name(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
- char new_ifname[IFNAMSIZ];
-
- if (rereg_priv->old_ifname[0] == 0) {
- char *reg_ifname;
- reg_ifname = padapter->registrypriv.ifname;
-
- strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
- rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
- }
-
- if (wrqu->data.length > IFNAMSIZ)
- return -EFAULT;
-
- if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
- return -EFAULT;
-
- if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
- return ret;
-
- ret = rtw_change_ifname(padapter, new_ifname);
- if (ret != 0)
- goto exit;
-
- strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
- rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
-
- if (!memcmp(new_ifname, "disable%d", 9)) {
- /* free network queue for Android's timming issue */
- rtw_free_network_queue(padapter, true);
-
- /* the interface is being "disabled", we can do deeper IPS */
- /* rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); */
- }
-exit:
- return ret;
-
-}
-
-static int rtw_dbg_port(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u8 major_cmd, minor_cmd;
- u16 arg;
- u32 extra_arg, *pdata, val32;
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-
- pdata = (u32 *)&wrqu->data;
-
- val32 = *pdata;
- arg = (u16)(val32&0x0000ffff);
- major_cmd = (u8)(val32>>24);
- minor_cmd = (u8)((val32>>16)&0x00ff);
-
- extra_arg = *(pdata+1);
-
- switch (major_cmd) {
- case 0x70:/* read_reg */
- switch (minor_cmd) {
- case 1:
- break;
- case 2:
- break;
- case 4:
- break;
- }
- break;
- case 0x71:/* write_reg */
- switch (minor_cmd) {
- case 1:
- rtw_write8(padapter, arg, extra_arg);
- break;
- case 2:
- rtw_write16(padapter, arg, extra_arg);
- break;
- case 4:
- rtw_write32(padapter, arg, extra_arg);
- break;
- }
- break;
- case 0x72:/* read_bb */
- break;
- case 0x73:/* write_bb */
- rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
- break;
- case 0x74:/* read_rf */
- break;
- case 0x75:/* write_rf */
- rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
- break;
-
- case 0x76:
- switch (minor_cmd) {
- case 0x00: /* normal mode, */
- padapter->recvpriv.is_signal_dbg = 0;
- break;
- case 0x01: /* dbg mode */
- padapter->recvpriv.is_signal_dbg = 1;
- extra_arg = extra_arg > 100 ? 100 : extra_arg;
- padapter->recvpriv.signal_strength_dbg = extra_arg;
- break;
- }
- break;
- case 0x78: /* IOL test */
- break;
- case 0x79:
- {
- /*
- * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
- * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
- */
- u8 value = extra_arg & 0x0f;
- u8 sign = minor_cmd;
- u16 write_value = 0;
-
- if (sign)
- value = value | 0x10;
-
- write_value = value | (value << 5);
- rtw_write16(padapter, 0x6d9, write_value);
- }
- break;
- case 0x7a:
- receive_disconnect(padapter, pmlmeinfo->network.MacAddress
- , WLAN_REASON_EXPIRATION_CHK);
- break;
- case 0x7F:
- switch (minor_cmd) {
- case 0x0:
- break;
- case 0x01:
- break;
- case 0x02:
- break;
- case 0x03:
- break;
- case 0x04:
-
- break;
- case 0x05:
- break;
- case 0x06:
- {
- u32 ODMFlag;
- rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
- ODMFlag = (u32)(0x0f&arg);
- rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
- }
- break;
- case 0x07:
- break;
- case 0x08:
- {
- }
- break;
- case 0x09:
- break;
- case 0x0a:
- {
- int max_mac_id = 0;
- max_mac_id = rtw_search_max_mac_id(padapter);
- printk("%s ==> max_mac_id = %d\n", __func__, max_mac_id);
- }
- break;
- case 0x0b: /* Enable = 1, Disable = 0 driver control vrtl_carrier_sense. */
- if (arg == 0) {
- padapter->driver_vcs_en = 0;
- } else if (arg == 1) {
- padapter->driver_vcs_en = 1;
-
- if (extra_arg > 2)
- padapter->driver_vcs_type = 1;
- else
- padapter->driver_vcs_type = extra_arg;
- }
- break;
- case 0x0c:/* dump rx/tx packet */
- {
- if (arg == 0)
- /* pHalData->bDumpRxPkt =extra_arg; */
- rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
- else if (arg == 1)
- rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
- }
- break;
- case 0x0e:
- {
- if (arg == 0) {
- padapter->driver_rx_ampdu_factor = 0xFF;
- } else if (arg == 1) {
-
- if ((extra_arg & 0x03) > 0x03)
- padapter->driver_rx_ampdu_factor = 0xFF;
- else
- padapter->driver_rx_ampdu_factor = extra_arg;
- }
- }
- break;
-
- case 0x10:/* driver version display */
- netdev_dbg(dev, "%s %s\n", "rtl8723bs", DRIVERVERSION);
- break;
- case 0x11:/* dump linked status */
- {
- linked_info_dump(padapter, extra_arg);
- }
- break;
- case 0x12: /* set rx_stbc */
- {
- struct registry_priv *pregpriv = &padapter->registrypriv;
- /* 0: disable, bit(0):enable 2.4g */
- /* default is set to enable 2.4GHZ */
- if (extra_arg == 0 || extra_arg == 1)
- pregpriv->rx_stbc = extra_arg;
- }
- break;
- case 0x13: /* set ampdu_enable */
- {
- struct registry_priv *pregpriv = &padapter->registrypriv;
- /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
- if (extra_arg < 3)
- pregpriv->ampdu_enable = extra_arg;
- }
- break;
- case 0x14:
- {
- }
- break;
- case 0x16:
- {
- if (arg == 0xff) {
- rtw_odm_dbg_comp_msg(padapter);
- } else {
- u64 dbg_comp = (u64)extra_arg;
- rtw_odm_dbg_comp_set(padapter, dbg_comp);
- }
- }
- break;
-#ifdef DBG_FIXED_CHAN
- case 0x17:
- {
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- printk("===> Fixed channel to %d\n", extra_arg);
- pmlmeext->fixed_chan = extra_arg;
-
- }
- break;
-#endif
- case 0x18:
- {
- printk("===> Switch USB Mode %d\n", extra_arg);
- rtw_hal_set_hwreg(padapter, HW_VAR_USB_MODE, (u8 *)&extra_arg);
- }
- break;
- case 0x19:
- {
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- /* extra_arg : */
- /* BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, */
- /* BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */
- if (arg == 0)
- pregistrypriv->ldpc_cap = 0x00;
- else if (arg == 1)
- pregistrypriv->ldpc_cap = (u8)(extra_arg&0x33);
- }
- break;
- case 0x1a:
- {
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- /* extra_arg : */
- /* BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, */
- /* BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */
- if (arg == 0)
- pregistrypriv->stbc_cap = 0x00;
- else if (arg == 1)
- pregistrypriv->stbc_cap = (u8)(extra_arg&0x33);
- }
- break;
- case 0x1b:
- {
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
-
- if (arg == 0) {
- init_mlme_default_rate_set(padapter);
- pregistrypriv->ht_enable = (u8)rtw_ht_enable;
- } else if (arg == 1) {
-
- int i;
- u8 max_rx_rate;
-
- max_rx_rate = (u8)extra_arg;
-
- if (max_rx_rate < 0xc) { /* max_rx_rate < MSC0 -> B or G -> disable HT */
- pregistrypriv->ht_enable = 0;
- for (i = 0; i < NumRates; i++) {
- if (pmlmeext->datarate[i] > max_rx_rate)
- pmlmeext->datarate[i] = 0xff;
- }
-
- }
- else if (max_rx_rate < 0x1c) { /* mcs0~mcs15 */
- u32 mcs_bitmap = 0x0;
-
- for (i = 0; i < ((max_rx_rate + 1) - 0xc); i++)
- mcs_bitmap |= BIT(i);
-
- set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap);
- }
- }
- }
- break;
- case 0x1c: /* enable/disable driver control AMPDU Density for peer sta's rx */
- {
- if (arg == 0) {
- padapter->driver_ampdu_spacing = 0xFF;
- } else if (arg == 1) {
-
- if (extra_arg > 0x07)
- padapter->driver_ampdu_spacing = 0xFF;
- else
- padapter->driver_ampdu_spacing = extra_arg;
- }
- }
- break;
- case 0x23:
- {
- padapter->bNotifyChannelChange = extra_arg;
- break;
- }
- case 0x24:
- {
- break;
- }
- case 0xaa:
- {
- if ((extra_arg & 0x7F) > 0x3F)
- extra_arg = 0xFF;
- padapter->fix_rate = extra_arg;
- }
- break;
- case 0xdd:/* registers dump , 0 for mac reg, 1 for bb reg, 2 for rf reg */
- {
- if (extra_arg == 0)
- mac_reg_dump(padapter);
- else if (extra_arg == 1)
- bb_reg_dump(padapter);
- else if (extra_arg == 2)
- rf_reg_dump(padapter);
- }
- break;
-
- case 0xee:/* turn on/off dynamic funcs */
- {
- u32 odm_flag;
-
- if (0xf == extra_arg) {
- rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
- } else {
- /*extra_arg = 0 - disable all dynamic func
- extra_arg = 1 - disable DIG
- extra_arg = 2 - disable tx power tracking
- extra_arg = 3 - turn on all dynamic func
- */
- rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
- rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
- }
- }
- break;
-
- case 0xfd:
- rtw_write8(padapter, 0xc50, arg);
- rtw_write8(padapter, 0xc58, arg);
- break;
- case 0xfe:
- break;
- case 0xff:
- {
- }
- break;
- }
- break;
- default:
- break;
- }
-
-
- return 0;
-
-}
-
static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
{
uint ret = 0;
@@ -2988,19 +595,19 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
if (wep_key_len > 0) {
wep_key_len = wep_key_len <= 5 ? 5 : 13;
- wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
+ wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
pwep = kzalloc(wep_total_len, GFP_KERNEL);
if (!pwep)
goto exit;
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_total_len;
+ pwep->key_length = wep_key_len;
+ pwep->length = wep_total_len;
}
- pwep->KeyIndex = wep_key_idx;
+ pwep->key_index = wep_key_idx;
- memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
+ memcpy(pwep->key_material, param->u.crypt.key, pwep->key_length);
if (param->u.crypt.set_tx) {
psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
@@ -3008,7 +615,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
- if (pwep->KeyLength == 13) {
+ if (pwep->key_length == 13) {
psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
}
@@ -3016,20 +623,20 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
- memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
+ memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
- psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+ psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
- rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 1);
+ rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 1);
} else {
/* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
/* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to cam */
- memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
+ memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->key_material, pwep->key_length);
- psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+ psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->key_length;
- rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 0);
+ rtw_ap_set_wep_key(padapter, pwep->key_material, pwep->key_length, wep_key_idx, 0);
}
goto exit;
@@ -3544,10 +1151,10 @@ static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param,
memcpy(ssid, ssid_ie+2, ssid_len);
ssid[ssid_len] = 0x0;
- memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len);
- pbss_network->Ssid.SsidLength = ssid_len;
- memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len);
- pbss_network_ext->Ssid.SsidLength = ssid_len;
+ memcpy(pbss_network->ssid.ssid, (void *)ssid, ssid_len);
+ pbss_network->ssid.ssid_length = ssid_len;
+ memcpy(pbss_network_ext->ssid.ssid, (void *)ssid, ssid_len);
+ pbss_network_ext->ssid.ssid_length = ssid_len;
}
return ret;
@@ -3728,778 +1335,8 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
return ret;
}
-static int rtw_wx_set_priv(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra)
-{
-
-#ifdef DEBUG_RTW_WX_SET_PRIV
- char *ext_dbg;
-#endif
-
- int ret = 0;
- int len = 0;
- char *ext;
-
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct iw_point *dwrq = (struct iw_point *)awrq;
-
- if (dwrq->length == 0)
- return -EFAULT;
-
- len = dwrq->length;
- ext = vmalloc(len);
- if (!ext)
- return -ENOMEM;
-
- if (copy_from_user(ext, dwrq->pointer, len)) {
- vfree(ext);
- return -EFAULT;
- }
-
- #ifdef DEBUG_RTW_WX_SET_PRIV
- ext_dbg = vmalloc(len);
- if (!ext_dbg) {
- vfree(ext, len);
- return -ENOMEM;
- }
-
- memcpy(ext_dbg, ext, len);
- #endif
-
- /* added for wps2.0 @20110524 */
- if (dwrq->flags == 0x8766 && len > 8) {
- u32 cp_sz;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- u8 *probereq_wpsie = ext;
- int probereq_wpsie_len = len;
- u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- if ((WLAN_EID_VENDOR_SPECIFIC == probereq_wpsie[0]) &&
- (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
- cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
-
- if (pmlmepriv->wps_probe_req_ie) {
- pmlmepriv->wps_probe_req_ie_len = 0;
- kfree(pmlmepriv->wps_probe_req_ie);
- pmlmepriv->wps_probe_req_ie = NULL;
- }
-
- pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
- if (pmlmepriv->wps_probe_req_ie == NULL) {
- printk("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
- ret = -EINVAL;
- goto FREE_EXT;
-
- }
-
- memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
- pmlmepriv->wps_probe_req_ie_len = cp_sz;
-
- }
-
- goto FREE_EXT;
-
- }
-
- if (len >= WEXT_CSCAN_HEADER_SIZE
- && !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
- ret = rtw_wx_set_scan(dev, info, awrq, ext);
- goto FREE_EXT;
- }
-
-FREE_EXT:
-
- vfree(ext);
- #ifdef DEBUG_RTW_WX_SET_PRIV
- vfree(ext_dbg);
- #endif
-
- return ret;
-
-}
-
-static int rtw_pm_set(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- unsigned mode = 0;
- struct adapter *padapter = rtw_netdev_priv(dev);
-
- if (!memcmp(extra, "lps =", 4)) {
- sscanf(extra+4, "%u", &mode);
- ret = rtw_pm_set_lps(padapter, mode);
- } else if (!memcmp(extra, "ips =", 4)) {
- sscanf(extra+4, "%u", &mode);
- ret = rtw_pm_set_ips(padapter, mode);
- } else {
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int rtw_test(
- struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- u32 len;
- u8 *pbuf, *pch;
- char *ptmp;
- u8 *delim = ",";
- struct adapter *padapter = rtw_netdev_priv(dev);
-
-
- len = wrqu->data.length;
-
- pbuf = rtw_zmalloc(len);
- if (!pbuf)
- return -ENOMEM;
-
- if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
- kfree(pbuf);
- return -EFAULT;
- }
-
- ptmp = (char *)pbuf;
- pch = strsep(&ptmp, delim);
- if ((pch == NULL) || (strlen(pch) == 0)) {
- kfree(pbuf);
- return -EFAULT;
- }
-
- if (strcmp(pch, "bton") == 0)
- hal_btcoex_SetManualControl(padapter, false);
-
- if (strcmp(pch, "btoff") == 0)
- hal_btcoex_SetManualControl(padapter, true);
-
- if (strcmp(pch, "h2c") == 0) {
- u8 param[8];
- u8 count = 0;
- u32 tmp;
- u8 i;
- u32 pos;
- s32 ret;
-
-
- do {
- pch = strsep(&ptmp, delim);
- if ((pch == NULL) || (strlen(pch) == 0))
- break;
-
- sscanf(pch, "%x", &tmp);
- param[count++] = (u8)tmp;
- } while (count < 8);
-
- if (count == 0) {
- kfree(pbuf);
- return -EFAULT;
- }
-
- ret = rtw_hal_fill_h2c_cmd(padapter, param[0], count-1, &param[1]);
-
- pos = sprintf(extra, "H2C ID = 0x%02x content =", param[0]);
- for (i = 1; i < count; i++)
- pos += sprintf(extra+pos, "%02x,", param[i]);
- extra[pos] = 0;
- pos--;
- pos += sprintf(extra+pos, " %s", ret == _FAIL?"FAIL":"OK");
-
- wrqu->data.length = strlen(extra) + 1;
- }
-
- kfree(pbuf);
- return 0;
-}
-
-static iw_handler rtw_handlers[] = {
- NULL, /* SIOCSIWCOMMIT */
- rtw_wx_get_name, /* SIOCGIWNAME */
- dummy, /* SIOCSIWNWID */
- dummy, /* SIOCGIWNWID */
- rtw_wx_set_freq, /* SIOCSIWFREQ */
- rtw_wx_get_freq, /* SIOCGIWFREQ */
- rtw_wx_set_mode, /* SIOCSIWMODE */
- rtw_wx_get_mode, /* SIOCGIWMODE */
- dummy, /* SIOCSIWSENS */
- rtw_wx_get_sens, /* SIOCGIWSENS */
- NULL, /* SIOCSIWRANGE */
- rtw_wx_get_range, /* SIOCGIWRANGE */
- rtw_wx_set_priv, /* SIOCSIWPRIV */
- NULL, /* SIOCGIWPRIV */
- NULL, /* SIOCSIWSTATS */
- NULL, /* SIOCGIWSTATS */
- dummy, /* SIOCSIWSPY */
- dummy, /* SIOCGIWSPY */
- NULL, /* SIOCGIWTHRSPY */
- NULL, /* SIOCWIWTHRSPY */
- rtw_wx_set_wap, /* SIOCSIWAP */
- rtw_wx_get_wap, /* SIOCGIWAP */
- rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */
- dummy, /* SIOCGIWAPLIST -- depricated */
- rtw_wx_set_scan, /* SIOCSIWSCAN */
- rtw_wx_get_scan, /* SIOCGIWSCAN */
- rtw_wx_set_essid, /* SIOCSIWESSID */
- rtw_wx_get_essid, /* SIOCGIWESSID */
- dummy, /* SIOCSIWNICKN */
- rtw_wx_get_nick, /* SIOCGIWNICKN */
- NULL, /* -- hole -- */
- NULL, /* -- hole -- */
- rtw_wx_set_rate, /* SIOCSIWRATE */
- rtw_wx_get_rate, /* SIOCGIWRATE */
- rtw_wx_set_rts, /* SIOCSIWRTS */
- rtw_wx_get_rts, /* SIOCGIWRTS */
- rtw_wx_set_frag, /* SIOCSIWFRAG */
- rtw_wx_get_frag, /* SIOCGIWFRAG */
- dummy, /* SIOCSIWTXPOW */
- dummy, /* SIOCGIWTXPOW */
- dummy, /* SIOCSIWRETRY */
- rtw_wx_get_retry, /* SIOCGIWRETRY */
- rtw_wx_set_enc, /* SIOCSIWENCODE */
- rtw_wx_get_enc, /* SIOCGIWENCODE */
- dummy, /* SIOCSIWPOWER */
- rtw_wx_get_power, /* SIOCGIWPOWER */
- NULL, /*---hole---*/
- NULL, /*---hole---*/
- rtw_wx_set_gen_ie, /* SIOCSIWGENIE */
- NULL, /* SIOCGWGENIE */
- rtw_wx_set_auth, /* SIOCSIWAUTH */
- NULL, /* SIOCGIWAUTH */
- rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
- NULL, /* SIOCGIWENCODEEXT */
- rtw_wx_set_pmkid, /* SIOCSIWPMKSA */
- NULL, /*---hole---*/
-};
-
-static const struct iw_priv_args rtw_private_args[] = {
- {
- SIOCIWFIRSTPRIV + 0x0,
- IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
- },
- {
- SIOCIWFIRSTPRIV + 0x1,
- IW_PRIV_TYPE_CHAR | 0x7FF,
- IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
- },
- {
- SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
- },
- {
- SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
- },
- {
- SIOCIWFIRSTPRIV + 0x4,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
- },
- {
- SIOCIWFIRSTPRIV + 0x5,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
- },
- {
- SIOCIWFIRSTPRIV + 0x6,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
- },
-/* for PLATFORM_MT53XX */
- {
- SIOCIWFIRSTPRIV + 0x7,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
- },
- {
- SIOCIWFIRSTPRIV + 0x8,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
- },
- {
- SIOCIWFIRSTPRIV + 0x9,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
- },
-
-/* for RTK_DMP_PLATFORM */
- {
- SIOCIWFIRSTPRIV + 0xA,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
- },
-
- {
- SIOCIWFIRSTPRIV + 0xB,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
- },
- {
- SIOCIWFIRSTPRIV + 0xC,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
- },
- {
- SIOCIWFIRSTPRIV + 0xD,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
- },
- {
- SIOCIWFIRSTPRIV + 0x10,
- IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set"
- },
- {
- SIOCIWFIRSTPRIV + 0x11,
- IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "p2p_get"
- },
- {
- SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
- },
- {
- SIOCIWFIRSTPRIV + 0x13,
- IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, "p2p_get2"
- },
- {
- SIOCIWFIRSTPRIV + 0x14,
- IW_PRIV_TYPE_CHAR | 64, 0, "tdls"
- },
- {
- SIOCIWFIRSTPRIV + 0x15,
- IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, "tdls_get"
- },
- {
- SIOCIWFIRSTPRIV + 0x16,
- IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
- },
-
- {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
- {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
- {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
- {
- SIOCIWFIRSTPRIV + 0x1D,
- IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
- },
-};
-
-static iw_handler rtw_private_handler[] = {
- rtw_wx_write32, /* 0x00 */
- rtw_wx_read32, /* 0x01 */
- rtw_drvext_hdl, /* 0x02 */
- NULL, /* 0x03 */
-
-/* for MM DTV platform */
- rtw_get_ap_info, /* 0x04 */
-
- rtw_set_pid, /* 0x05 */
- rtw_wps_start, /* 0x06 */
-
-/* for PLATFORM_MT53XX */
- rtw_wx_get_sensitivity, /* 0x07 */
- rtw_wx_set_mtk_wps_probe_ie, /* 0x08 */
- rtw_wx_set_mtk_wps_ie, /* 0x09 */
-
-/* for RTK_DMP_PLATFORM */
-/* Set Channel depend on the country code */
- rtw_wx_set_channel_plan, /* 0x0A */
-
- rtw_dbg_port, /* 0x0B */
- rtw_wx_write_rf, /* 0x0C */
- rtw_wx_read_rf, /* 0x0D */
- rtw_wx_priv_null, /* 0x0E */
- rtw_wx_priv_null, /* 0x0F */
- rtw_p2p_set, /* 0x10 */
- rtw_p2p_get, /* 0x11 */
- NULL, /* 0x12 */
- rtw_p2p_get2, /* 0x13 */
-
- NULL, /* 0x14 */
- NULL, /* 0x15 */
-
- rtw_pm_set, /* 0x16 */
- rtw_wx_priv_null, /* 0x17 */
- rtw_rereg_nd_name, /* 0x18 */
- rtw_wx_priv_null, /* 0x19 */
- NULL, /* 0x1A */
- NULL, /* 0x1B */
- NULL, /* 0x1C is reserved for hostapd */
- rtw_test, /* 0x1D */
-};
-
-static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
-{
- struct adapter *padapter = rtw_netdev_priv(dev);
- struct iw_statistics *piwstats = &padapter->iwstats;
- int tmp_level = 0;
- int tmp_qual = 0;
- int tmp_noise = 0;
-
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
- piwstats->qual.qual = 0;
- piwstats->qual.level = 0;
- piwstats->qual.noise = 0;
- } else {
- tmp_level = padapter->recvpriv.signal_strength;
- tmp_qual = padapter->recvpriv.signal_qual;
- tmp_noise = padapter->recvpriv.noise;
-
- piwstats->qual.level = tmp_level;
- piwstats->qual.qual = tmp_qual;
- piwstats->qual.noise = tmp_noise;
- }
- piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;/* IW_QUAL_DBM; */
-
- return &padapter->iwstats;
-}
-
-struct iw_handler_def rtw_handlers_def = {
- .standard = rtw_handlers,
- .num_standard = ARRAY_SIZE(rtw_handlers),
-#if defined(CONFIG_WEXT_PRIV)
- .private = rtw_private_handler,
- .private_args = (struct iw_priv_args *)rtw_private_args,
- .num_private = ARRAY_SIZE(rtw_private_handler),
- .num_private_args = ARRAY_SIZE(rtw_private_args),
-#endif
- .get_wireless_stats = rtw_get_wireless_stats,
-};
-
-/* copy from net/wireless/wext.c start */
-/* ---------------------------------------------------------------- */
-/*
- * Calculate size of private arguments
- */
-static const char iw_priv_type_size[] = {
- 0, /* IW_PRIV_TYPE_NONE */
- 1, /* IW_PRIV_TYPE_BYTE */
- 1, /* IW_PRIV_TYPE_CHAR */
- 0, /* Not defined */
- sizeof(__u32), /* IW_PRIV_TYPE_INT */
- sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */
- sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */
- 0, /* Not defined */
-};
-
-static int get_priv_size(__u16 args)
-{
- int num = args & IW_PRIV_SIZE_MASK;
- int type = (args & IW_PRIV_TYPE_MASK) >> 12;
-
- return num * iw_priv_type_size[type];
-}
/* copy from net/wireless/wext.c end */
-static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
-{
- int err = 0;
- u8 *input = NULL;
- u32 input_len = 0;
- const char delim[] = " ";
- u8 *output = NULL;
- u32 output_len = 0;
- u32 count = 0;
- u8 *buffer = NULL;
- u32 buffer_len = 0;
- char *ptr = NULL;
- u8 cmdname[17] = {0}; /* IFNAMSIZ+1 */
- u32 cmdlen;
- s32 len;
- u8 *extra = NULL;
- u32 extra_size = 0;
-
- s32 k;
- const iw_handler *priv; /* Private ioctl */
- const struct iw_priv_args *priv_args; /* Private ioctl description */
- u32 num_priv_args; /* Number of descriptions */
- iw_handler handler;
- int temp;
- int subcmd = 0; /* sub-ioctl index */
- int offset = 0; /* Space for sub-ioctl index */
-
- union iwreq_data wdata;
-
-
- memcpy(&wdata, wrq_data, sizeof(wdata));
-
- input_len = 2048;
- input = rtw_zmalloc(input_len);
- if (NULL == input)
- return -ENOMEM;
- if (copy_from_user(input, wdata.data.pointer, input_len)) {
- err = -EFAULT;
- goto exit;
- }
- ptr = input;
- len = strlen(input);
-
- sscanf(ptr, "%16s", cmdname);
- cmdlen = strlen(cmdname);
-
- /* skip command string */
- if (cmdlen > 0)
- cmdlen += 1; /* skip one space */
- ptr += cmdlen;
- len -= cmdlen;
-
- priv = rtw_private_handler;
- priv_args = rtw_private_args;
- num_priv_args = ARRAY_SIZE(rtw_private_args);
-
- if (num_priv_args == 0) {
- err = -EOPNOTSUPP;
- goto exit;
- }
-
- /* Search the correct ioctl */
- k = -1;
- while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
-
- /* If not found... */
- if (k == num_priv_args) {
- err = -EOPNOTSUPP;
- goto exit;
- }
-
- /* Watch out for sub-ioctls ! */
- if (priv_args[k].cmd < SIOCDEVPRIVATE) {
- int j = -1;
-
- /* Find the matching *real* ioctl */
- while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
- (priv_args[j].set_args != priv_args[k].set_args) ||
- (priv_args[j].get_args != priv_args[k].get_args)));
-
- /* If not found... */
- if (j == num_priv_args) {
- err = -EINVAL;
- goto exit;
- }
-
- /* Save sub-ioctl number */
- subcmd = priv_args[k].cmd;
- /* Reserve one int (simplify alignment issues) */
- offset = sizeof(__u32);
- /* Use real ioctl definition from now on */
- k = j;
- }
-
- buffer = rtw_zmalloc(4096);
- if (NULL == buffer) {
- err = -ENOMEM;
- goto exit;
- }
-
- /* If we have to set some data */
- if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
- (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
- u8 *str;
-
- switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
- case IW_PRIV_TYPE_BYTE:
- /* Fetch args */
- count = 0;
- do {
- str = strsep(&ptr, delim);
- if (NULL == str)
- break;
- sscanf(str, "%i", &temp);
- buffer[count++] = (u8)temp;
- } while (1);
- buffer_len = count;
-
- /* Number of args to fetch */
- wdata.data.length = count;
- if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
- wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
-
- break;
-
- case IW_PRIV_TYPE_INT:
- /* Fetch args */
- count = 0;
- do {
- str = strsep(&ptr, delim);
- if (NULL == str)
- break;
- sscanf(str, "%i", &temp);
- ((s32 *)buffer)[count++] = (s32)temp;
- } while (1);
- buffer_len = count * sizeof(s32);
-
- /* Number of args to fetch */
- wdata.data.length = count;
- if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
- wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
-
- break;
-
- case IW_PRIV_TYPE_CHAR:
- if (len > 0) {
- /* Size of the string to fetch */
- wdata.data.length = len;
- if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
- wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
-
- /* Fetch string */
- memcpy(buffer, ptr, wdata.data.length);
- } else {
- wdata.data.length = 1;
- buffer[0] = '\0';
- }
- buffer_len = wdata.data.length;
- break;
-
- default:
- err = -1;
- goto exit;
- }
-
- if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
- (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
- err = -EINVAL;
- goto exit;
- }
- } else { /* if args to set */
- wdata.data.length = 0L;
- }
-
- /* Those two tests are important. They define how the driver
- * will have to handle the data */
- if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
- ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
- /* First case : all SET args fit within wrq */
- if (offset)
- wdata.mode = subcmd;
- memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
- } else {
- if ((priv_args[k].set_args == 0) &&
- (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
- (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
- /* Second case : no SET args, GET args fit within wrq */
- if (offset)
- wdata.mode = subcmd;
- } else {
- /* Third case : args won't fit in wrq, or variable number of args */
- if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
- err = -EFAULT;
- goto exit;
- }
- wdata.data.flags = subcmd;
- }
- }
-
- kfree(input);
- input = NULL;
-
- extra_size = 0;
- if (IW_IS_SET(priv_args[k].cmd)) {
- /* Size of set arguments */
- extra_size = get_priv_size(priv_args[k].set_args);
-
- /* Does it fits in iwr ? */
- if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
- ((extra_size + offset) <= IFNAMSIZ))
- extra_size = 0;
- } else {
- /* Size of get arguments */
- extra_size = get_priv_size(priv_args[k].get_args);
-
- /* Does it fits in iwr ? */
- if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
- (extra_size <= IFNAMSIZ))
- extra_size = 0;
- }
-
- if (extra_size == 0) {
- extra = (u8 *)&wdata;
- kfree(buffer);
- buffer = NULL;
- } else
- extra = buffer;
-
- handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
- err = handler(dev, NULL, &wdata, extra);
-
- /* If we have to get some data */
- if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
- (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
- int j;
- int n = 0; /* number of args */
- u8 str[20] = {0};
-
- /* Check where is the returned data */
- if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
- (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
- n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
- else
- n = wdata.data.length;
-
- output = rtw_zmalloc(4096);
- if (NULL == output) {
- err = -ENOMEM;
- goto exit;
- }
-
- switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
- case IW_PRIV_TYPE_BYTE:
- /* Display args */
- for (j = 0; j < n; j++) {
- len = scnprintf(str, sizeof(str), "%d ", extra[j]);
- output_len = strlen(output);
- if ((output_len + len + 1) > 4096) {
- err = -E2BIG;
- goto exit;
- }
- memcpy(output+output_len, str, len);
- }
- break;
-
- case IW_PRIV_TYPE_INT:
- /* Display args */
- for (j = 0; j < n; j++) {
- len = scnprintf(str, sizeof(str), "%d ", ((__s32 *)extra)[j]);
- output_len = strlen(output);
- if ((output_len + len + 1) > 4096) {
- err = -E2BIG;
- goto exit;
- }
- memcpy(output+output_len, str, len);
- }
- break;
-
- case IW_PRIV_TYPE_CHAR:
- /* Display args */
- memcpy(output, extra, n);
- break;
-
- default:
- err = -1;
- goto exit;
- }
-
- output_len = strlen(output) + 1;
- wrq_data->data.length = output_len;
- if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
- err = -EFAULT;
- goto exit;
- }
- } else { /* if args to set */
- wrq_data->data.length = 0;
- }
-
-exit:
- kfree(input);
- kfree(buffer);
- kfree(output);
-
- return err;
-}
-
-int rtw_siocdevprivate(struct net_device *dev, struct ifreq *rq,
- void __user *data, int cmd)
-{
- struct iwreq *wrq = (struct iwreq *)rq;
-
- /* little hope of fixing this, better remove the whole function */
- if (in_compat_syscall())
- return -EOPNOTSUPP;
-
- if (cmd != SIOCDEVPRIVATE)
- return -EOPNOTSUPP;
-
- return rtw_ioctl_wext_private(dev, &wrq->u);
-}
-
int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct iwreq *wrq = (struct iwreq *)rq;
diff --git a/drivers/staging/rtl8723bs/os_dep/mlme_linux.c b/drivers/staging/rtl8723bs/os_dep/mlme_linux.c
index a4560ba22db1..1341801e5c21 100644
--- a/drivers/staging/rtl8723bs/os_dep/mlme_linux.c
+++ b/drivers/staging/rtl8723bs/os_dep/mlme_linux.c
@@ -48,7 +48,6 @@ void rtw_os_indicate_connect(struct adapter *adapter)
rtw_cfg80211_indicate_connect(adapter);
}
- rtw_indicate_wx_assoc_event(adapter);
netif_carrier_on(adapter->pnetdev);
if (adapter->pid[2] != 0)
@@ -58,7 +57,6 @@ void rtw_os_indicate_connect(struct adapter *adapter)
void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted)
{
rtw_cfg80211_indicate_scan_done(padapter, aborted);
- indicate_wx_scan_complete_event(padapter);
}
static struct rt_pmkid_list backupPMKIDList[NUM_PMKID_CACHE];
@@ -129,8 +127,6 @@ void rtw_os_indicate_disconnect(struct adapter *adapter)
rtw_cfg80211_indicate_disconnect(adapter);
- rtw_indicate_wx_disassoc_event(adapter);
-
/* modify for CONFIG_IEEE80211W, none 11w also can use the same command */
rtw_reset_securitypriv_cmd(adapter);
}
diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
index 9e38b53d3b4a..f78bf174de8e 100644
--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
@@ -89,18 +89,10 @@ static int rtw_beamform_cap = 0x2;
static int rtw_lowrate_two_xmit = 1;/* Use 2 path Tx to transmit MCS0~7 and legacy mode */
-/* int rf_config = RF_1T2R; 1T2R */
-static int rtw_rf_config = RF_MAX_TYPE; /* auto */
static int rtw_low_power;
static int rtw_wifi_spec;
static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX;
-static int rtw_btcoex_enable = 1;
-module_param(rtw_btcoex_enable, int, 0644);
-MODULE_PARM_DESC(rtw_btcoex_enable, "Enable BT co-existence mechanism");
-static int rtw_bt_iso = 2;/* 0:Low, 1:High, 2:From Efuse */
-static int rtw_bt_sco = 3;/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy */
-static int rtw_bt_ampdu = 1 ;/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
static int rtw_ant_num = -1; /* <0: undefined, >0: Antenna number */
module_param(rtw_ant_num, int, 0644);
MODULE_PARM_DESC(rtw_ant_num, "Antenna number setting");
@@ -109,15 +101,10 @@ static int rtw_antdiv_cfg = 1; /* 0:OFF , 1:ON, 2:decide by Efuse config */
static int rtw_antdiv_type; /* 0:decide by efuse 1: for 88EE, 1Tx and 1RxCG are diversity.(2 Ant with SPDT), 2: for 88EE, 1Tx and 2Rx are diversity.(2 Ant, Tx and RxCG are both on aux port, RxCS is on main port), 3: for 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */
-static int rtw_enusbss;/* 0:disable, 1:enable */
-
-static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */
-
-static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */
static int rtw_hw_wps_pbc;
-int rtw_mc2u_disable = 0;
+int rtw_mc2u_disable;
static int rtw_80211d;
@@ -128,7 +115,7 @@ static char *ifname = "wlan%d";
module_param(ifname, charp, 0644);
MODULE_PARM_DESC(ifname, "The default name to allocate for first interface");
-char *rtw_initmac = NULL; /* temp mac address if users want to use instead of the mac address in Efuse */
+char *rtw_initmac; /* temp mac address if users want to use instead of the mac address in Efuse */
module_param(rtw_initmac, charp, 0644);
module_param(rtw_channel_plan, int, 0644);
@@ -150,7 +137,6 @@ module_param(rtw_ampdu_amsdu, int, 0644);
module_param(rtw_lowrate_two_xmit, int, 0644);
-module_param(rtw_rf_config, int, 0644);
module_param(rtw_power_mgnt, int, 0644);
module_param(rtw_smart_ps, int, 0644);
module_param(rtw_low_power, int, 0644);
@@ -159,9 +145,6 @@ module_param(rtw_wifi_spec, int, 0644);
module_param(rtw_antdiv_cfg, int, 0644);
module_param(rtw_antdiv_type, int, 0644);
-module_param(rtw_enusbss, int, 0644);
-module_param(rtw_hwpdn_mode, int, 0644);
-module_param(rtw_hwpwrp_detect, int, 0644);
module_param(rtw_hw_wps_pbc, int, 0644);
@@ -205,8 +188,8 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev)
/* registry_par->hci = (u8)hci; */
registry_par->network_mode = (u8)rtw_network_mode;
- memcpy(registry_par->ssid.Ssid, "ANY", 3);
- registry_par->ssid.SsidLength = 3;
+ memcpy(registry_par->ssid.ssid, "ANY", 3);
+ registry_par->ssid.ssid_length = 3;
registry_par->channel = (u8)rtw_channel;
registry_par->wireless_mode = (u8)rtw_wireless_mode;
@@ -255,7 +238,6 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev)
registry_par->beamform_cap = (u8)rtw_beamform_cap;
registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit;
- registry_par->rf_config = (u8)rtw_rf_config;
registry_par->low_power = (u8)rtw_low_power;
@@ -263,10 +245,6 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev)
registry_par->channel_plan = (u8)rtw_channel_plan;
- registry_par->btcoex = (u8)rtw_btcoex_enable;
- registry_par->bt_iso = (u8)rtw_bt_iso;
- registry_par->bt_sco = (u8)rtw_bt_sco;
- registry_par->bt_ampdu = (u8)rtw_bt_ampdu;
registry_par->ant_num = (s8)rtw_ant_num;
registry_par->accept_addba_req = true;
@@ -459,7 +437,6 @@ static const struct net_device_ops rtw_netdev_ops = {
.ndo_set_mac_address = rtw_net_set_mac_address,
.ndo_get_stats = rtw_net_get_stats,
.ndo_do_ioctl = rtw_ioctl,
- .ndo_siocdevprivate = rtw_siocdevprivate,
};
int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname)
@@ -497,7 +474,6 @@ struct net_device *rtw_init_netdev(struct adapter *old_padapter)
/* pnetdev->tx_timeout = NULL; */
pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */
- pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def;
/* step 2. */
loadparam(padapter, pnetdev);
diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c b/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c
index bed930760656..0a0b04088e66 100644
--- a/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c
+++ b/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c
@@ -4,7 +4,6 @@
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
*******************************************************************************/
-#define _SDIO_OPS_LINUX_C_
#include <drv_types.h>
#include <rtw_debug.h>
diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c
index 1deb74112ad4..11d9d9155eef 100644
--- a/drivers/staging/rts5208/rtsx_scsi.c
+++ b/drivers/staging/rts5208/rtsx_scsi.c
@@ -2802,10 +2802,10 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
}
if (dev_info_id == 0x15) {
- buf_len = 0x3A;
+ buf_len = 0x3C;
data_len = 0x3A;
} else {
- buf_len = 0x6A;
+ buf_len = 0x6C;
data_len = 0x6A;
}
@@ -2855,11 +2855,7 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
}
rtsx_stor_set_xfer_buf(buf, buf_len, srb);
-
- if (dev_info_id == 0x15)
- scsi_set_resid(srb, scsi_bufflen(srb) - 0x3C);
- else
- scsi_set_resid(srb, scsi_bufflen(srb) - 0x6C);
+ scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
kfree(buf);
return STATUS_SUCCESS;
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index c237a8f8eb59..dbd1159a2ef0 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -112,8 +112,8 @@ static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
crtc = &par->crtc;
cursor = &crtc->cursor;
- if (fbcursor->image.width > cursor->maxW ||
- fbcursor->image.height > cursor->maxH ||
+ if (fbcursor->image.width > cursor->max_w ||
+ fbcursor->image.height > cursor->max_h ||
fbcursor->image.depth > 1) {
return -ENXIO;
}
@@ -175,7 +175,7 @@ static void lynxfb_ops_fillrect(struct fb_info *info,
* each time 2d function begin to work,below three variable always need
* be set, seems we can put them together in some place
*/
- base = par->crtc.oScreen;
+ base = par->crtc.o_screen;
pitch = info->fix.line_length;
Bpp = info->var.bits_per_pixel >> 3;
@@ -213,7 +213,7 @@ static void lynxfb_ops_copyarea(struct fb_info *info,
* each time 2d function begin to work,below three variable always need
* be set, seems we can put them together in some place
*/
- base = par->crtc.oScreen;
+ base = par->crtc.o_screen;
pitch = info->fix.line_length;
Bpp = info->var.bits_per_pixel >> 3;
@@ -247,7 +247,7 @@ static void lynxfb_ops_imageblit(struct fb_info *info,
* each time 2d function begin to work,below three variable always need
* be set, seems we can put them together in some place
*/
- base = par->crtc.oScreen;
+ base = par->crtc.o_screen;
pitch = info->fix.line_length;
Bpp = info->var.bits_per_pixel >> 3;
@@ -451,7 +451,7 @@ static int __maybe_unused lynxfb_resume(struct device *dev)
crtc = &par->crtc;
cursor = &crtc->cursor;
memset_io(cursor->vstart, 0x0, cursor->size);
- memset_io(crtc->vScreen, 0x0, crtc->vidmem_size);
+ memset_io(crtc->v_screen, 0x0, crtc->vidmem_size);
lynxfb_ops_set_par(info);
fb_set_suspend(info, 0);
}
@@ -463,7 +463,7 @@ static int __maybe_unused lynxfb_resume(struct device *dev)
crtc = &par->crtc;
cursor = &crtc->cursor;
memset_io(cursor->vstart, 0x0, cursor->size);
- memset_io(crtc->vScreen, 0x0, crtc->vidmem_size);
+ memset_io(crtc->v_screen, 0x0, crtc->vidmem_size);
lynxfb_ops_set_par(info);
fb_set_suspend(info, 0);
}
@@ -614,44 +614,44 @@ static int sm750fb_set_drv(struct lynxfb_par *par)
case sm750_simul_pri:
output->paths = sm750_pnc;
crtc->channel = sm750_primary;
- crtc->oScreen = 0;
- crtc->vScreen = sm750_dev->pvMem;
+ crtc->o_screen = 0;
+ crtc->v_screen = sm750_dev->pvMem;
pr_info("use simul primary mode\n");
break;
case sm750_simul_sec:
output->paths = sm750_pnc;
crtc->channel = sm750_secondary;
- crtc->oScreen = 0;
- crtc->vScreen = sm750_dev->pvMem;
+ crtc->o_screen = 0;
+ crtc->v_screen = sm750_dev->pvMem;
break;
case sm750_dual_normal:
if (par->index == 0) {
output->paths = sm750_panel;
crtc->channel = sm750_primary;
- crtc->oScreen = 0;
- crtc->vScreen = sm750_dev->pvMem;
+ crtc->o_screen = 0;
+ crtc->v_screen = sm750_dev->pvMem;
} else {
output->paths = sm750_crt;
crtc->channel = sm750_secondary;
- /* not consider of padding stuffs for oScreen,need fix */
- crtc->oScreen = sm750_dev->vidmem_size >> 1;
- crtc->vScreen = sm750_dev->pvMem + crtc->oScreen;
+ /* not consider of padding stuffs for o_screen,need fix */
+ crtc->o_screen = sm750_dev->vidmem_size >> 1;
+ crtc->v_screen = sm750_dev->pvMem + crtc->o_screen;
}
break;
case sm750_dual_swap:
if (par->index == 0) {
output->paths = sm750_panel;
crtc->channel = sm750_secondary;
- crtc->oScreen = 0;
- crtc->vScreen = sm750_dev->pvMem;
+ crtc->o_screen = 0;
+ crtc->v_screen = sm750_dev->pvMem;
} else {
output->paths = sm750_crt;
crtc->channel = sm750_primary;
- /* not consider of padding stuffs for oScreen,
+ /* not consider of padding stuffs for o_screen,
* need fix
*/
- crtc->oScreen = sm750_dev->vidmem_size >> 1;
- crtc->vScreen = sm750_dev->pvMem + crtc->oScreen;
+ crtc->o_screen = sm750_dev->vidmem_size >> 1;
+ crtc->v_screen = sm750_dev->pvMem + crtc->o_screen;
}
break;
default:
@@ -718,13 +718,13 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
* set current cursor variable and proc pointer,
* must be set after crtc member initialized
*/
- crtc->cursor.offset = crtc->oScreen + crtc->vidmem_size - 1024;
+ crtc->cursor.offset = crtc->o_screen + crtc->vidmem_size - 1024;
crtc->cursor.mmio = sm750_dev->pvReg +
0x800f0 + (int)crtc->channel * 0x140;
pr_info("crtc->cursor.mmio = %p\n", crtc->cursor.mmio);
- crtc->cursor.maxH = crtc->cursor.maxW = 64;
- crtc->cursor.size = crtc->cursor.maxH * crtc->cursor.maxW * 2 / 8;
+ crtc->cursor.max_h = crtc->cursor.max_w = 64;
+ crtc->cursor.size = crtc->cursor.max_h * crtc->cursor.max_w * 2 / 8;
crtc->cursor.vstart = sm750_dev->pvMem + crtc->cursor.offset;
memset_io(crtc->cursor.vstart, 0, crtc->cursor.size);
@@ -801,7 +801,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
crtc->line_pad);
info->pseudo_palette = &par->pseudo_palette[0];
- info->screen_base = crtc->vScreen;
+ info->screen_base = crtc->v_screen;
pr_debug("screen_base vaddr = %p\n", info->screen_base);
info->screen_size = line_length * var->yres_virtual;
info->flags = FBINFO_FLAG_DEFAULT | 0;
@@ -816,7 +816,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
strscpy(fix->id, fixId[index], sizeof(fix->id));
- fix->smem_start = crtc->oScreen + sm750_dev->vidmem_start;
+ fix->smem_start = crtc->o_screen + sm750_dev->vidmem_start;
pr_info("fix->smem_start = %lx\n", fix->smem_start);
/*
* according to mmap experiment from user space application,
diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h
index 23eefd019ec9..aff69661c8e6 100644
--- a/drivers/staging/sm750fb/sm750.h
+++ b/drivers/staging/sm750fb/sm750.h
@@ -122,8 +122,8 @@ struct lynx_cursor {
int h;
int size;
/* hardware limitation */
- int maxW;
- int maxH;
+ int max_w;
+ int max_h;
/* base virtual address and offset of cursor image */
char __iomem *vstart;
int offset;
@@ -132,10 +132,10 @@ struct lynx_cursor {
};
struct lynxfb_crtc {
- unsigned char __iomem *vCursor; /* virtual address of cursor */
- unsigned char __iomem *vScreen; /* virtual address of on_screen */
- int oCursor; /* cursor address offset in vidmem */
- int oScreen; /* onscreen address offset in vidmem */
+ unsigned char __iomem *v_cursor; /* virtual address of cursor */
+ unsigned char __iomem *v_screen; /* virtual address of on_screen */
+ int o_cursor; /* cursor address offset in vidmem */
+ int o_screen; /* onscreen address offset in vidmem */
int channel;/* which channel this crtc stands for*/
resource_size_t vidmem_size;/* this view's video memory max size */
diff --git a/drivers/staging/sm750fb/sm750_cursor.c b/drivers/staging/sm750fb/sm750_cursor.c
index bbbef27cb329..43e6f52c2551 100644
--- a/drivers/staging/sm750fb/sm750_cursor.c
+++ b/drivers/staging/sm750fb/sm750_cursor.c
@@ -97,7 +97,7 @@ void sm750_hw_cursor_setData(struct lynx_cursor *cursor, u16 rop,
count = pitch * cursor->h;
/* in byte */
- offset = cursor->maxW * 2 / 8;
+ offset = cursor->max_w * 2 / 8;
data = 0;
pstart = cursor->vstart;
@@ -147,7 +147,7 @@ void sm750_hw_cursor_setData2(struct lynx_cursor *cursor, u16 rop,
count = pitch * cursor->h;
/* in byte */
- offset = cursor->maxW * 2 / 8;
+ offset = cursor->max_w * 2 / 8;
data = 0;
pstart = cursor->vstart;
diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c
index 7136d751cff5..a7c6eb07b62e 100644
--- a/drivers/staging/sm750fb/sm750_hw.c
+++ b/drivers/staging/sm750fb/sm750_hw.c
@@ -32,7 +32,7 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
ret = 0;
- sm750_dev->vidreg_start = pci_resource_start(pdev, 1);
+ sm750_dev->vidreg_start = pci_resource_start(pdev, 1);
sm750_dev->vidreg_size = SZ_2M;
pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start);
@@ -50,8 +50,8 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
}
/* now map mmio and vidmem */
- sm750_dev->pvReg = ioremap(sm750_dev->vidreg_start,
- sm750_dev->vidreg_size);
+ sm750_dev->pvReg =
+ ioremap(sm750_dev->vidreg_start, sm750_dev->vidreg_size);
if (!sm750_dev->pvReg) {
pr_err("mmio failed\n");
ret = -EFAULT;
@@ -78,8 +78,8 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
sm750_dev->vidmem_start, sm750_dev->vidmem_size);
/* reserve the vidmem space of smi adaptor */
- sm750_dev->pvMem = ioremap_wc(sm750_dev->vidmem_start,
- sm750_dev->vidmem_size);
+ sm750_dev->pvMem =
+ ioremap_wc(sm750_dev->vidmem_start, sm750_dev->vidmem_size);
if (!sm750_dev->pvMem) {
pr_err("Map video memory failed\n");
ret = -EFAULT;
@@ -98,8 +98,8 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
parm = &sm750_dev->initParm;
if (parm->chip_clk == 0)
parm->chip_clk = (sm750_get_chip_type() == SM750LE) ?
- DEFAULT_SM750LE_CHIP_CLOCK :
- DEFAULT_SM750_CHIP_CLOCK;
+ DEFAULT_SM750LE_CHIP_CLOCK :
+ DEFAULT_SM750_CHIP_CLOCK;
if (parm->mem_clk == 0)
parm->mem_clk = parm->chip_clk;
@@ -133,8 +133,8 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
}
val = peek32(PANEL_DISPLAY_CTRL) &
- ~(PANEL_DISPLAY_CTRL_DUAL_DISPLAY |
- PANEL_DISPLAY_CTRL_DOUBLE_PIXEL);
+ ~(PANEL_DISPLAY_CTRL_DUAL_DISPLAY |
+ PANEL_DISPLAY_CTRL_DOUBLE_PIXEL);
switch (sm750_dev->pnltype) {
case sm750_24TFT:
break;
@@ -281,12 +281,12 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
/* set timing */
modparm.pixel_clock = ps_to_hz(var->pixclock);
- modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT)
- ? POS : NEG;
- modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT)
- ? POS : NEG;
- modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT)
- ? POS : NEG;
+ modparm.vertical_sync_polarity =
+ (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS : NEG;
+ modparm.horizontal_sync_polarity =
+ (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS : NEG;
+ modparm.clock_phase_polarity =
+ (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS : NEG;
modparm.horizontal_display_end = var->xres;
modparm.horizontal_sync_width = var->hsync_len;
modparm.horizontal_sync_start = var->xres + var->right_margin;
@@ -314,7 +314,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
if (crtc->channel != sm750_secondary) {
/* set pitch, offset, width, start address, etc... */
poke32(PANEL_FB_ADDRESS,
- crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK);
+ crtc->o_screen & PANEL_FB_ADDRESS_ADDRESS_MASK);
reg = var->xres * (var->bits_per_pixel >> 3);
/*
@@ -323,17 +323,17 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
*/
reg = ALIGN(reg, crtc->line_pad);
reg = (reg << PANEL_FB_WIDTH_WIDTH_SHIFT) &
- PANEL_FB_WIDTH_WIDTH_MASK;
+ PANEL_FB_WIDTH_WIDTH_MASK;
reg |= (fix->line_length & PANEL_FB_WIDTH_OFFSET_MASK);
poke32(PANEL_FB_WIDTH, reg);
reg = ((var->xres - 1) << PANEL_WINDOW_WIDTH_WIDTH_SHIFT) &
- PANEL_WINDOW_WIDTH_WIDTH_MASK;
+ PANEL_WINDOW_WIDTH_WIDTH_MASK;
reg |= (var->xoffset & PANEL_WINDOW_WIDTH_X_MASK);
poke32(PANEL_WINDOW_WIDTH, reg);
- reg = (var->yres_virtual - 1) <<
- PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT;
+ reg = (var->yres_virtual - 1)
+ << PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT;
reg &= PANEL_WINDOW_HEIGHT_HEIGHT_MASK;
reg |= (var->yoffset & PANEL_WINDOW_HEIGHT_Y_MASK);
poke32(PANEL_WINDOW_HEIGHT, reg);
@@ -341,7 +341,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
poke32(PANEL_PLANE_TL, 0);
reg = ((var->yres - 1) << PANEL_PLANE_BR_BOTTOM_SHIFT) &
- PANEL_PLANE_BR_BOTTOM_MASK;
+ PANEL_PLANE_BR_BOTTOM_MASK;
reg |= ((var->xres - 1) & PANEL_PLANE_BR_RIGHT_MASK);
poke32(PANEL_PLANE_BR, reg);
@@ -350,7 +350,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
poke32(PANEL_DISPLAY_CTRL, reg | (var->bits_per_pixel >> 4));
} else {
/* not implemented now */
- poke32(CRT_FB_ADDRESS, crtc->oScreen);
+ poke32(CRT_FB_ADDRESS, crtc->o_screen);
reg = var->xres * (var->bits_per_pixel >> 3);
/*
* crtc->channel is not equal to par->index on numeric,
@@ -372,10 +372,10 @@ exit:
return ret;
}
-int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
- ushort red, ushort green, ushort blue)
+int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index, ushort red,
+ ushort green, ushort blue)
{
- static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
+ static unsigned int add[] = { PANEL_PALETTE_RAM, CRT_PALETTE_RAM };
poke32(add[crtc->channel] + index * 4,
(red << 16) | (green << 8) | blue);
@@ -510,7 +510,7 @@ int hw_sm750le_deWait(void)
{
int i = 0x10000000;
unsigned int mask = DE_STATE2_DE_STATUS_BUSY | DE_STATE2_DE_FIFO_EMPTY |
- DE_STATE2_DE_MEM_FIFO_EMPTY;
+ DE_STATE2_DE_MEM_FIFO_EMPTY;
while (i--) {
unsigned int val = peek32(DE_STATE2);
@@ -527,8 +527,8 @@ int hw_sm750_deWait(void)
{
int i = 0x10000000;
unsigned int mask = SYSTEM_CTRL_DE_STATUS_BUSY |
- SYSTEM_CTRL_DE_FIFO_EMPTY |
- SYSTEM_CTRL_DE_MEM_FIFO_EMPTY;
+ SYSTEM_CTRL_DE_FIFO_EMPTY |
+ SYSTEM_CTRL_DE_MEM_FIFO_EMPTY;
while (i--) {
unsigned int val = peek32(SYSTEM_CTRL);
@@ -554,15 +554,15 @@ int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
total = var->yoffset * info->fix.line_length +
((var->xoffset * var->bits_per_pixel) >> 3);
- total += crtc->oScreen;
+ total += crtc->o_screen;
if (crtc->channel == sm750_primary) {
poke32(PANEL_FB_ADDRESS,
peek32(PANEL_FB_ADDRESS) |
- (total & PANEL_FB_ADDRESS_ADDRESS_MASK));
+ (total & PANEL_FB_ADDRESS_ADDRESS_MASK));
} else {
poke32(CRT_FB_ADDRESS,
peek32(CRT_FB_ADDRESS) |
- (total & CRT_FB_ADDRESS_ADDRESS_MASK));
+ (total & CRT_FB_ADDRESS_ADDRESS_MASK));
}
return 0;
}
diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig
index 4b886293f198..cb7c82403dbf 100644
--- a/drivers/staging/vc04_services/Kconfig
+++ b/drivers/staging/vc04_services/Kconfig
@@ -13,11 +13,31 @@ if BCM_VIDEOCORE
config BCM2835_VCHIQ
tristate "BCM2835 VCHIQ"
+ imply VCHIQ_CDEV
help
- Kernel to VideoCore communication interface for the
- BCM2835 family of products.
- Defaults to Y when the Broadcom Videocore services
- are included in the build, N otherwise.
+ Broadcom BCM2835 and similar SoCs have a VPU called VideoCore. This config
+ enables the VCHIQ driver, which implements a messaging interface between
+ the kernel and the firmware running on VideoCore. Other drivers use this
+ interface to communicate to the VPU. More specifically, the VCHIQ driver is
+ used by audio/video and camera drivers as well as for implementing MMAL
+ API, which is in turn used by several multimedia services on the BCM2835
+ family of SoCs.
+ Defaults to Y when the Broadcom Videocore services are included in
+ the build, N otherwise.
+
+if BCM2835_VCHIQ
+
+config VCHIQ_CDEV
+ bool "VCHIQ Character Driver"
+ help
+ Enable the creation of VCHIQ character driver. The cdev exposes ioctls used
+ by userspace libraries and testing tools to interact with VideoCore, via
+ the VCHIQ core driver (Check BCM2835_VCHIQ for more info).
+ This can be set to 'N' if the VideoCore communication is not needed by
+ userspace but only by other kernel modules (like bcm2835-audio). If not
+ sure, set this to 'Y'.
+
+endif
source "drivers/staging/vc04_services/bcm2835-audio/Kconfig"
diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile
index e21e73ae3cc6..1fd191e2e2a5 100644
--- a/drivers/staging/vc04_services/Makefile
+++ b/drivers/staging/vc04_services/Makefile
@@ -4,10 +4,13 @@ obj-$(CONFIG_BCM2835_VCHIQ) += vchiq.o
vchiq-objs := \
interface/vchiq_arm/vchiq_core.o \
interface/vchiq_arm/vchiq_arm.o \
- interface/vchiq_arm/vchiq_2835_arm.o \
interface/vchiq_arm/vchiq_debugfs.o \
interface/vchiq_arm/vchiq_connected.o \
+ifdef CONFIG_VCHIQ_CDEV
+vchiq-objs += interface/vchiq_arm/vchiq_dev.o
+endif
+
obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
index 1b36475872d6..51066ac8eea5 100644
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
@@ -22,7 +22,7 @@ enum {
/* macros for alsa2chip and chip2alsa, instead of functions */
// convert alsa to chip volume (defined as macro rather than function call)
-#define alsa2chip(vol) (uint)(-(((vol) << 8) / 100))
+#define alsa2chip(vol) ((uint)(-(((vol) << 8) / 100)))
// convert chip to alsa volume
#define chip2alsa(vol) -(((vol) * 100) >> 8)
diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
index df90c1f9d148..1b184d5c6b82 100644
--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
@@ -884,7 +884,7 @@ static int vidioc_querycap(struct file *file, void *priv,
vchiq_mmal_version(dev->instance, &major, &minor);
- strcpy((char *)cap->driver, "bm2835 mmal");
+ strscpy(cap->driver, "bm2835 mmal", sizeof(cap->driver));
snprintf((char *)cap->card, sizeof(cap->card), "mmal service %d.%d",
major, minor);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
deleted file mode 100644
index 30d6f1a404ba..000000000000
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+++ /dev/null
@@ -1,564 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/pagemap.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-#include <linux/mm.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-#include <soc/bcm2835/raspberrypi-firmware.h>
-
-#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
-
-#include "vchiq_arm.h"
-#include "vchiq_connected.h"
-#include "vchiq_pagelist.h"
-
-#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)
-
-#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0
-#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1
-
-#define BELL0 0x00
-#define BELL2 0x08
-
-#define ARM_DS_ACTIVE BIT(2)
-
-struct vchiq_2835_state {
- int inited;
- struct vchiq_arm_state arm_state;
-};
-
-struct vchiq_pagelist_info {
- struct pagelist *pagelist;
- size_t pagelist_buffer_size;
- dma_addr_t dma_addr;
- enum dma_data_direction dma_dir;
- unsigned int num_pages;
- unsigned int pages_need_release;
- struct page **pages;
- struct scatterlist *scatterlist;
- unsigned int scatterlist_mapped;
-};
-
-static void __iomem *g_regs;
-/* This value is the size of the L2 cache lines as understood by the
- * VPU firmware, which determines the required alignment of the
- * offsets/sizes in pagelists.
- *
- * Modern VPU firmware looks for a DT "cache-line-size" property in
- * the VCHIQ node and will overwrite it with the actual L2 cache size,
- * which the kernel must then respect. That property was rejected
- * upstream, so we have to use the VPU firmware's compatibility value
- * of 32.
- */
-static unsigned int g_cache_line_size = 32;
-static unsigned int g_fragments_size;
-static char *g_fragments_base;
-static char *g_free_fragments;
-static struct semaphore g_free_fragments_sema;
-static struct device *g_dev;
-
-static DEFINE_SEMAPHORE(g_free_fragments_mutex);
-
-static irqreturn_t
-vchiq_doorbell_irq(int irq, void *dev_id);
-
-static struct vchiq_pagelist_info *
-create_pagelist(char *buf, char __user *ubuf, size_t count, unsigned short type);
-
-static void
-free_pagelist(struct vchiq_pagelist_info *pagelistinfo,
- int actual);
-
-int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
-{
- struct device *dev = &pdev->dev;
- struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev);
- struct rpi_firmware *fw = drvdata->fw;
- struct vchiq_slot_zero *vchiq_slot_zero;
- void *slot_mem;
- dma_addr_t slot_phys;
- u32 channelbase;
- int slot_mem_size, frag_mem_size;
- int err, irq, i;
-
- /*
- * VCHI messages between the CPU and firmware use
- * 32-bit bus addresses.
- */
- err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-
- if (err < 0)
- return err;
-
- g_cache_line_size = drvdata->cache_line_size;
- g_fragments_size = 2 * g_cache_line_size;
-
- /* Allocate space for the channels in coherent memory */
- slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
- frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS);
-
- slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size,
- &slot_phys, GFP_KERNEL);
- if (!slot_mem) {
- dev_err(dev, "could not allocate DMA memory\n");
- return -ENOMEM;
- }
-
- WARN_ON(((unsigned long)slot_mem & (PAGE_SIZE - 1)) != 0);
-
- vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size);
- if (!vchiq_slot_zero)
- return -EINVAL;
-
- vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
- (int)slot_phys + slot_mem_size;
- vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
- MAX_FRAGMENTS;
-
- g_fragments_base = (char *)slot_mem + slot_mem_size;
-
- g_free_fragments = g_fragments_base;
- for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {
- *(char **)&g_fragments_base[i*g_fragments_size] =
- &g_fragments_base[(i + 1)*g_fragments_size];
- }
- *(char **)&g_fragments_base[i * g_fragments_size] = NULL;
- sema_init(&g_free_fragments_sema, MAX_FRAGMENTS);
-
- err = vchiq_init_state(state, vchiq_slot_zero);
- if (err)
- return err;
-
- g_regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(g_regs))
- return PTR_ERR(g_regs);
-
- irq = platform_get_irq(pdev, 0);
- if (irq <= 0)
- return irq;
-
- err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL,
- "VCHIQ doorbell", state);
- if (err) {
- dev_err(dev, "failed to register irq=%d\n", irq);
- return err;
- }
-
- /* Send the base address of the slots to VideoCore */
- channelbase = slot_phys;
- err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT,
- &channelbase, sizeof(channelbase));
- if (err || channelbase) {
- dev_err(dev, "failed to set channelbase\n");
- return err ? : -ENXIO;
- }
-
- g_dev = dev;
- vchiq_log_info(vchiq_arm_log_level,
- "vchiq_init - done (slots %pK, phys %pad)",
- vchiq_slot_zero, &slot_phys);
-
- vchiq_call_connected_callbacks();
-
- return 0;
-}
-
-int
-vchiq_platform_init_state(struct vchiq_state *state)
-{
- struct vchiq_2835_state *platform_state;
-
- state->platform_state = kzalloc(sizeof(*platform_state), GFP_KERNEL);
- if (!state->platform_state)
- return -ENOMEM;
-
- platform_state = (struct vchiq_2835_state *)state->platform_state;
-
- platform_state->inited = 1;
- vchiq_arm_init_state(state, &platform_state->arm_state);
-
- return 0;
-}
-
-struct vchiq_arm_state*
-vchiq_platform_get_arm_state(struct vchiq_state *state)
-{
- struct vchiq_2835_state *platform_state;
-
- platform_state = (struct vchiq_2835_state *)state->platform_state;
-
- WARN_ON_ONCE(!platform_state->inited);
-
- return &platform_state->arm_state;
-}
-
-void
-remote_event_signal(struct remote_event *event)
-{
- wmb();
-
- event->fired = 1;
-
- dsb(sy); /* data barrier operation */
-
- if (event->armed)
- writel(0, g_regs + BELL2); /* trigger vc interrupt */
-}
-
-int
-vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset,
- void __user *uoffset, int size, int dir)
-{
- struct vchiq_pagelist_info *pagelistinfo;
-
- pagelistinfo = create_pagelist(offset, uoffset, size,
- (dir == VCHIQ_BULK_RECEIVE)
- ? PAGELIST_READ
- : PAGELIST_WRITE);
-
- if (!pagelistinfo)
- return -ENOMEM;
-
- bulk->data = pagelistinfo->dma_addr;
-
- /*
- * Store the pagelistinfo address in remote_data,
- * which isn't used by the slave.
- */
- bulk->remote_data = pagelistinfo;
-
- return 0;
-}
-
-void
-vchiq_complete_bulk(struct vchiq_bulk *bulk)
-{
- if (bulk && bulk->remote_data && bulk->actual)
- free_pagelist((struct vchiq_pagelist_info *)bulk->remote_data,
- bulk->actual);
-}
-
-int vchiq_dump_platform_state(void *dump_context)
-{
- char buf[80];
- int len;
-
- len = snprintf(buf, sizeof(buf),
- " Platform: 2835 (VC master)");
- return vchiq_dump(dump_context, buf, len + 1);
-}
-
-/*
- * Local functions
- */
-
-static irqreturn_t
-vchiq_doorbell_irq(int irq, void *dev_id)
-{
- struct vchiq_state *state = dev_id;
- irqreturn_t ret = IRQ_NONE;
- unsigned int status;
-
- /* Read (and clear) the doorbell */
- status = readl(g_regs + BELL0);
-
- if (status & ARM_DS_ACTIVE) { /* Was the doorbell rung? */
- remote_event_pollall(state);
- ret = IRQ_HANDLED;
- }
-
- return ret;
-}
-
-static void
-cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
-{
- if (pagelistinfo->scatterlist_mapped) {
- dma_unmap_sg(g_dev, pagelistinfo->scatterlist,
- pagelistinfo->num_pages, pagelistinfo->dma_dir);
- }
-
- if (pagelistinfo->pages_need_release)
- unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages);
-
- dma_free_coherent(g_dev, pagelistinfo->pagelist_buffer_size,
- pagelistinfo->pagelist, pagelistinfo->dma_addr);
-}
-
-/* There is a potential problem with partial cache lines (pages?)
- * at the ends of the block when reading. If the CPU accessed anything in
- * the same line (page?) then it may have pulled old data into the cache,
- * obscuring the new data underneath. We can solve this by transferring the
- * partial cache lines separately, and allowing the ARM to copy into the
- * cached area.
- */
-
-static struct vchiq_pagelist_info *
-create_pagelist(char *buf, char __user *ubuf,
- size_t count, unsigned short type)
-{
- struct pagelist *pagelist;
- struct vchiq_pagelist_info *pagelistinfo;
- struct page **pages;
- u32 *addrs;
- unsigned int num_pages, offset, i, k;
- int actual_pages;
- size_t pagelist_size;
- struct scatterlist *scatterlist, *sg;
- int dma_buffers;
- dma_addr_t dma_addr;
-
- if (count >= INT_MAX - PAGE_SIZE)
- return NULL;
-
- if (buf)
- offset = (uintptr_t)buf & (PAGE_SIZE - 1);
- else
- offset = (uintptr_t)ubuf & (PAGE_SIZE - 1);
- num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE);
-
- if (num_pages > (SIZE_MAX - sizeof(struct pagelist) -
- sizeof(struct vchiq_pagelist_info)) /
- (sizeof(u32) + sizeof(pages[0]) +
- sizeof(struct scatterlist)))
- return NULL;
-
- pagelist_size = sizeof(struct pagelist) +
- (num_pages * sizeof(u32)) +
- (num_pages * sizeof(pages[0]) +
- (num_pages * sizeof(struct scatterlist))) +
- sizeof(struct vchiq_pagelist_info);
-
- /* Allocate enough storage to hold the page pointers and the page
- * list
- */
- pagelist = dma_alloc_coherent(g_dev, pagelist_size, &dma_addr,
- GFP_KERNEL);
-
- vchiq_log_trace(vchiq_arm_log_level, "%s - %pK", __func__, pagelist);
-
- if (!pagelist)
- return NULL;
-
- addrs = pagelist->addrs;
- pages = (struct page **)(addrs + num_pages);
- scatterlist = (struct scatterlist *)(pages + num_pages);
- pagelistinfo = (struct vchiq_pagelist_info *)
- (scatterlist + num_pages);
-
- pagelist->length = count;
- pagelist->type = type;
- pagelist->offset = offset;
-
- /* Populate the fields of the pagelistinfo structure */
- pagelistinfo->pagelist = pagelist;
- pagelistinfo->pagelist_buffer_size = pagelist_size;
- pagelistinfo->dma_addr = dma_addr;
- pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE;
- pagelistinfo->num_pages = num_pages;
- pagelistinfo->pages_need_release = 0;
- pagelistinfo->pages = pages;
- pagelistinfo->scatterlist = scatterlist;
- pagelistinfo->scatterlist_mapped = 0;
-
- if (buf) {
- unsigned long length = count;
- unsigned int off = offset;
-
- for (actual_pages = 0; actual_pages < num_pages;
- actual_pages++) {
- struct page *pg =
- vmalloc_to_page((buf +
- (actual_pages * PAGE_SIZE)));
- size_t bytes = PAGE_SIZE - off;
-
- if (!pg) {
- cleanup_pagelistinfo(pagelistinfo);
- return NULL;
- }
-
- if (bytes > length)
- bytes = length;
- pages[actual_pages] = pg;
- length -= bytes;
- off = 0;
- }
- /* do not try and release vmalloc pages */
- } else {
- actual_pages = pin_user_pages_fast(
- (unsigned long)ubuf & PAGE_MASK,
- num_pages,
- type == PAGELIST_READ,
- pages);
-
- if (actual_pages != num_pages) {
- vchiq_log_info(vchiq_arm_log_level,
- "%s - only %d/%d pages locked",
- __func__, actual_pages, num_pages);
-
- /* This is probably due to the process being killed */
- if (actual_pages > 0)
- unpin_user_pages(pages, actual_pages);
- cleanup_pagelistinfo(pagelistinfo);
- return NULL;
- }
- /* release user pages */
- pagelistinfo->pages_need_release = 1;
- }
-
- /*
- * Initialize the scatterlist so that the magic cookie
- * is filled if debugging is enabled
- */
- sg_init_table(scatterlist, num_pages);
- /* Now set the pages for each scatterlist */
- for (i = 0; i < num_pages; i++) {
- unsigned int len = PAGE_SIZE - offset;
-
- if (len > count)
- len = count;
- sg_set_page(scatterlist + i, pages[i], len, offset);
- offset = 0;
- count -= len;
- }
-
- dma_buffers = dma_map_sg(g_dev,
- scatterlist,
- num_pages,
- pagelistinfo->dma_dir);
-
- if (dma_buffers == 0) {
- cleanup_pagelistinfo(pagelistinfo);
- return NULL;
- }
-
- pagelistinfo->scatterlist_mapped = 1;
-
- /* Combine adjacent blocks for performance */
- k = 0;
- for_each_sg(scatterlist, sg, dma_buffers, i) {
- u32 len = sg_dma_len(sg);
- u32 addr = sg_dma_address(sg);
-
- /* Note: addrs is the address + page_count - 1
- * The firmware expects blocks after the first to be page-
- * aligned and a multiple of the page size
- */
- WARN_ON(len == 0);
- WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
- WARN_ON(i && (addr & ~PAGE_MASK));
- if (k > 0 &&
- ((addrs[k - 1] & PAGE_MASK) +
- (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
- == (addr & PAGE_MASK))
- addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
- else
- addrs[k++] = (addr & PAGE_MASK) |
- (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
- }
-
- /* Partial cache lines (fragments) require special measures */
- if ((type == PAGELIST_READ) &&
- ((pagelist->offset & (g_cache_line_size - 1)) ||
- ((pagelist->offset + pagelist->length) &
- (g_cache_line_size - 1)))) {
- char *fragments;
-
- if (down_interruptible(&g_free_fragments_sema)) {
- cleanup_pagelistinfo(pagelistinfo);
- return NULL;
- }
-
- WARN_ON(!g_free_fragments);
-
- down(&g_free_fragments_mutex);
- fragments = g_free_fragments;
- WARN_ON(!fragments);
- g_free_fragments = *(char **) g_free_fragments;
- up(&g_free_fragments_mutex);
- pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
- (fragments - g_fragments_base) / g_fragments_size;
- }
-
- return pagelistinfo;
-}
-
-static void
-free_pagelist(struct vchiq_pagelist_info *pagelistinfo,
- int actual)
-{
- struct pagelist *pagelist = pagelistinfo->pagelist;
- struct page **pages = pagelistinfo->pages;
- unsigned int num_pages = pagelistinfo->num_pages;
-
- vchiq_log_trace(vchiq_arm_log_level, "%s - %pK, %d",
- __func__, pagelistinfo->pagelist, actual);
-
- /*
- * NOTE: dma_unmap_sg must be called before the
- * cpu can touch any of the data/pages.
- */
- dma_unmap_sg(g_dev, pagelistinfo->scatterlist,
- pagelistinfo->num_pages, pagelistinfo->dma_dir);
- pagelistinfo->scatterlist_mapped = 0;
-
- /* Deal with any partial cache lines (fragments) */
- if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
- char *fragments = g_fragments_base +
- (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) *
- g_fragments_size;
- int head_bytes, tail_bytes;
-
- head_bytes = (g_cache_line_size - pagelist->offset) &
- (g_cache_line_size - 1);
- tail_bytes = (pagelist->offset + actual) &
- (g_cache_line_size - 1);
-
- if ((actual >= 0) && (head_bytes != 0)) {
- if (head_bytes > actual)
- head_bytes = actual;
-
- memcpy((char *)kmap(pages[0]) +
- pagelist->offset,
- fragments,
- head_bytes);
- kunmap(pages[0]);
- }
- if ((actual >= 0) && (head_bytes < actual) &&
- (tail_bytes != 0)) {
- memcpy((char *)kmap(pages[num_pages - 1]) +
- ((pagelist->offset + actual) &
- (PAGE_SIZE - 1) & ~(g_cache_line_size - 1)),
- fragments + g_cache_line_size,
- tail_bytes);
- kunmap(pages[num_pages - 1]);
- }
-
- down(&g_free_fragments_mutex);
- *(char **)fragments = g_free_fragments;
- g_free_fragments = fragments;
- up(&g_free_fragments_mutex);
- up(&g_free_fragments_sema);
- }
-
- /* Need to mark all the pages dirty. */
- if (pagelist->type != PAGELIST_WRITE &&
- pagelistinfo->pages_need_release) {
- unsigned int i;
-
- for (i = 0; i < num_pages; i++)
- set_page_dirty(pages[i]);
- }
-
- cleanup_pagelistinfo(pagelistinfo);
-}
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index b5aac862a298..b25369a13452 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -25,25 +25,36 @@
#include <linux/rcupdate.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
#include <soc/bcm2835/raspberrypi-firmware.h>
#include "vchiq_core.h"
#include "vchiq_ioctl.h"
#include "vchiq_arm.h"
#include "vchiq_debugfs.h"
+#include "vchiq_connected.h"
+#include "vchiq_pagelist.h"
#define DEVICE_NAME "vchiq"
+#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
+
+#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)
+
+#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0
+#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1
+
+#define BELL0 0x00
+#define BELL2 0x08
+
+#define ARM_DS_ACTIVE BIT(2)
+
/* Override the default prefix, which would be vchiq_arm (from the filename) */
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX DEVICE_NAME "."
-/* Some per-instance constants */
-#define MAX_COMPLETIONS 128
-#define MAX_SERVICES 64
-#define MAX_ELEMENTS 8
-#define MSG_QUEUE_SIZE 128
-
#define KEEPALIVE_VER 1
#define KEEPALIVE_VER_MIN KEEPALIVE_VER
@@ -51,62 +62,9 @@
int vchiq_arm_log_level = VCHIQ_LOG_DEFAULT;
int vchiq_susp_log_level = VCHIQ_LOG_ERROR;
-struct user_service {
- struct vchiq_service *service;
- void __user *userdata;
- struct vchiq_instance *instance;
- char is_vchi;
- char dequeue_pending;
- char close_pending;
- int message_available_pos;
- int msg_insert;
- int msg_remove;
- struct completion insert_event;
- struct completion remove_event;
- struct completion close_event;
- struct vchiq_header *msg_queue[MSG_QUEUE_SIZE];
-};
+DEFINE_SPINLOCK(msg_queue_spinlock);
+struct vchiq_state g_state;
-struct bulk_waiter_node {
- struct bulk_waiter bulk_waiter;
- int pid;
- struct list_head list;
-};
-
-struct vchiq_instance {
- struct vchiq_state *state;
- struct vchiq_completion_data_kernel completions[MAX_COMPLETIONS];
- int completion_insert;
- int completion_remove;
- struct completion insert_event;
- struct completion remove_event;
- struct mutex completion_mutex;
-
- int connected;
- int closing;
- int pid;
- int mark;
- int use_close_delivered;
- int trace;
-
- struct list_head bulk_waiter_list;
- struct mutex bulk_waiter_list_mutex;
-
- struct vchiq_debugfs_node debugfs_node;
-};
-
-struct dump_context {
- char __user *buf;
- size_t actual;
- size_t space;
- loff_t offset;
-};
-
-static struct cdev vchiq_cdev;
-static dev_t vchiq_devid;
-static struct vchiq_state g_state;
-static struct class *vchiq_class;
-static DEFINE_SPINLOCK(msg_queue_spinlock);
static struct platform_device *bcm2835_camera;
static struct platform_device *bcm2835_audio;
@@ -118,33 +76,528 @@ static struct vchiq_drvdata bcm2836_drvdata = {
.cache_line_size = 64,
};
-static const char *const ioctl_names[] = {
- "CONNECT",
- "SHUTDOWN",
- "CREATE_SERVICE",
- "REMOVE_SERVICE",
- "QUEUE_MESSAGE",
- "QUEUE_BULK_TRANSMIT",
- "QUEUE_BULK_RECEIVE",
- "AWAIT_COMPLETION",
- "DEQUEUE_MESSAGE",
- "GET_CLIENT_ID",
- "GET_CONFIG",
- "CLOSE_SERVICE",
- "USE_SERVICE",
- "RELEASE_SERVICE",
- "SET_SERVICE_OPTION",
- "DUMP_PHYS_MEM",
- "LIB_VERSION",
- "CLOSE_DELIVERED"
+struct vchiq_2835_state {
+ int inited;
+ struct vchiq_arm_state arm_state;
};
-static_assert(ARRAY_SIZE(ioctl_names) == (VCHIQ_IOC_MAX + 1));
+struct vchiq_pagelist_info {
+ struct pagelist *pagelist;
+ size_t pagelist_buffer_size;
+ dma_addr_t dma_addr;
+ enum dma_data_direction dma_dir;
+ unsigned int num_pages;
+ unsigned int pages_need_release;
+ struct page **pages;
+ struct scatterlist *scatterlist;
+ unsigned int scatterlist_mapped;
+};
+
+static void __iomem *g_regs;
+/* This value is the size of the L2 cache lines as understood by the
+ * VPU firmware, which determines the required alignment of the
+ * offsets/sizes in pagelists.
+ *
+ * Modern VPU firmware looks for a DT "cache-line-size" property in
+ * the VCHIQ node and will overwrite it with the actual L2 cache size,
+ * which the kernel must then respect. That property was rejected
+ * upstream, so we have to use the VPU firmware's compatibility value
+ * of 32.
+ */
+static unsigned int g_cache_line_size = 32;
+static unsigned int g_fragments_size;
+static char *g_fragments_base;
+static char *g_free_fragments;
+static struct semaphore g_free_fragments_sema;
+static struct device *g_dev;
+
+static DEFINE_SEMAPHORE(g_free_fragments_mutex);
static enum vchiq_status
vchiq_blocking_bulk_transfer(unsigned int handle, void *data,
unsigned int size, enum vchiq_bulk_dir dir);
+static irqreturn_t
+vchiq_doorbell_irq(int irq, void *dev_id)
+{
+ struct vchiq_state *state = dev_id;
+ irqreturn_t ret = IRQ_NONE;
+ unsigned int status;
+
+ /* Read (and clear) the doorbell */
+ status = readl(g_regs + BELL0);
+
+ if (status & ARM_DS_ACTIVE) { /* Was the doorbell rung? */
+ remote_event_pollall(state);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+static void
+cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
+{
+ if (pagelistinfo->scatterlist_mapped) {
+ dma_unmap_sg(g_dev, pagelistinfo->scatterlist,
+ pagelistinfo->num_pages, pagelistinfo->dma_dir);
+ }
+
+ if (pagelistinfo->pages_need_release)
+ unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages);
+
+ dma_free_coherent(g_dev, pagelistinfo->pagelist_buffer_size,
+ pagelistinfo->pagelist, pagelistinfo->dma_addr);
+}
+
+/* There is a potential problem with partial cache lines (pages?)
+ * at the ends of the block when reading. If the CPU accessed anything in
+ * the same line (page?) then it may have pulled old data into the cache,
+ * obscuring the new data underneath. We can solve this by transferring the
+ * partial cache lines separately, and allowing the ARM to copy into the
+ * cached area.
+ */
+
+static struct vchiq_pagelist_info *
+create_pagelist(char *buf, char __user *ubuf,
+ size_t count, unsigned short type)
+{
+ struct pagelist *pagelist;
+ struct vchiq_pagelist_info *pagelistinfo;
+ struct page **pages;
+ u32 *addrs;
+ unsigned int num_pages, offset, i, k;
+ int actual_pages;
+ size_t pagelist_size;
+ struct scatterlist *scatterlist, *sg;
+ int dma_buffers;
+ dma_addr_t dma_addr;
+
+ if (count >= INT_MAX - PAGE_SIZE)
+ return NULL;
+
+ if (buf)
+ offset = (uintptr_t)buf & (PAGE_SIZE - 1);
+ else
+ offset = (uintptr_t)ubuf & (PAGE_SIZE - 1);
+ num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE);
+
+ if (num_pages > (SIZE_MAX - sizeof(struct pagelist) -
+ sizeof(struct vchiq_pagelist_info)) /
+ (sizeof(u32) + sizeof(pages[0]) +
+ sizeof(struct scatterlist)))
+ return NULL;
+
+ pagelist_size = sizeof(struct pagelist) +
+ (num_pages * sizeof(u32)) +
+ (num_pages * sizeof(pages[0]) +
+ (num_pages * sizeof(struct scatterlist))) +
+ sizeof(struct vchiq_pagelist_info);
+
+ /* Allocate enough storage to hold the page pointers and the page
+ * list
+ */
+ pagelist = dma_alloc_coherent(g_dev, pagelist_size, &dma_addr,
+ GFP_KERNEL);
+
+ vchiq_log_trace(vchiq_arm_log_level, "%s - %pK", __func__, pagelist);
+
+ if (!pagelist)
+ return NULL;
+
+ addrs = pagelist->addrs;
+ pages = (struct page **)(addrs + num_pages);
+ scatterlist = (struct scatterlist *)(pages + num_pages);
+ pagelistinfo = (struct vchiq_pagelist_info *)
+ (scatterlist + num_pages);
+
+ pagelist->length = count;
+ pagelist->type = type;
+ pagelist->offset = offset;
+
+ /* Populate the fields of the pagelistinfo structure */
+ pagelistinfo->pagelist = pagelist;
+ pagelistinfo->pagelist_buffer_size = pagelist_size;
+ pagelistinfo->dma_addr = dma_addr;
+ pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ pagelistinfo->num_pages = num_pages;
+ pagelistinfo->pages_need_release = 0;
+ pagelistinfo->pages = pages;
+ pagelistinfo->scatterlist = scatterlist;
+ pagelistinfo->scatterlist_mapped = 0;
+
+ if (buf) {
+ unsigned long length = count;
+ unsigned int off = offset;
+
+ for (actual_pages = 0; actual_pages < num_pages;
+ actual_pages++) {
+ struct page *pg =
+ vmalloc_to_page((buf +
+ (actual_pages * PAGE_SIZE)));
+ size_t bytes = PAGE_SIZE - off;
+
+ if (!pg) {
+ cleanup_pagelistinfo(pagelistinfo);
+ return NULL;
+ }
+
+ if (bytes > length)
+ bytes = length;
+ pages[actual_pages] = pg;
+ length -= bytes;
+ off = 0;
+ }
+ /* do not try and release vmalloc pages */
+ } else {
+ actual_pages = pin_user_pages_fast(
+ (unsigned long)ubuf & PAGE_MASK,
+ num_pages,
+ type == PAGELIST_READ,
+ pages);
+
+ if (actual_pages != num_pages) {
+ vchiq_log_info(vchiq_arm_log_level,
+ "%s - only %d/%d pages locked",
+ __func__, actual_pages, num_pages);
+
+ /* This is probably due to the process being killed */
+ if (actual_pages > 0)
+ unpin_user_pages(pages, actual_pages);
+ cleanup_pagelistinfo(pagelistinfo);
+ return NULL;
+ }
+ /* release user pages */
+ pagelistinfo->pages_need_release = 1;
+ }
+
+ /*
+ * Initialize the scatterlist so that the magic cookie
+ * is filled if debugging is enabled
+ */
+ sg_init_table(scatterlist, num_pages);
+ /* Now set the pages for each scatterlist */
+ for (i = 0; i < num_pages; i++) {
+ unsigned int len = PAGE_SIZE - offset;
+
+ if (len > count)
+ len = count;
+ sg_set_page(scatterlist + i, pages[i], len, offset);
+ offset = 0;
+ count -= len;
+ }
+
+ dma_buffers = dma_map_sg(g_dev,
+ scatterlist,
+ num_pages,
+ pagelistinfo->dma_dir);
+
+ if (dma_buffers == 0) {
+ cleanup_pagelistinfo(pagelistinfo);
+ return NULL;
+ }
+
+ pagelistinfo->scatterlist_mapped = 1;
+
+ /* Combine adjacent blocks for performance */
+ k = 0;
+ for_each_sg(scatterlist, sg, dma_buffers, i) {
+ u32 len = sg_dma_len(sg);
+ u32 addr = sg_dma_address(sg);
+
+ /* Note: addrs is the address + page_count - 1
+ * The firmware expects blocks after the first to be page-
+ * aligned and a multiple of the page size
+ */
+ WARN_ON(len == 0);
+ WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
+ WARN_ON(i && (addr & ~PAGE_MASK));
+ if (k > 0 &&
+ ((addrs[k - 1] & PAGE_MASK) +
+ (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
+ == (addr & PAGE_MASK))
+ addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ else
+ addrs[k++] = (addr & PAGE_MASK) |
+ (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
+ }
+
+ /* Partial cache lines (fragments) require special measures */
+ if ((type == PAGELIST_READ) &&
+ ((pagelist->offset & (g_cache_line_size - 1)) ||
+ ((pagelist->offset + pagelist->length) &
+ (g_cache_line_size - 1)))) {
+ char *fragments;
+
+ if (down_interruptible(&g_free_fragments_sema)) {
+ cleanup_pagelistinfo(pagelistinfo);
+ return NULL;
+ }
+
+ WARN_ON(!g_free_fragments);
+
+ down(&g_free_fragments_mutex);
+ fragments = g_free_fragments;
+ WARN_ON(!fragments);
+ g_free_fragments = *(char **) g_free_fragments;
+ up(&g_free_fragments_mutex);
+ pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
+ (fragments - g_fragments_base) / g_fragments_size;
+ }
+
+ return pagelistinfo;
+}
+
+static void
+free_pagelist(struct vchiq_pagelist_info *pagelistinfo,
+ int actual)
+{
+ struct pagelist *pagelist = pagelistinfo->pagelist;
+ struct page **pages = pagelistinfo->pages;
+ unsigned int num_pages = pagelistinfo->num_pages;
+
+ vchiq_log_trace(vchiq_arm_log_level, "%s - %pK, %d",
+ __func__, pagelistinfo->pagelist, actual);
+
+ /*
+ * NOTE: dma_unmap_sg must be called before the
+ * cpu can touch any of the data/pages.
+ */
+ dma_unmap_sg(g_dev, pagelistinfo->scatterlist,
+ pagelistinfo->num_pages, pagelistinfo->dma_dir);
+ pagelistinfo->scatterlist_mapped = 0;
+
+ /* Deal with any partial cache lines (fragments) */
+ if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
+ char *fragments = g_fragments_base +
+ (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) *
+ g_fragments_size;
+ int head_bytes, tail_bytes;
+
+ head_bytes = (g_cache_line_size - pagelist->offset) &
+ (g_cache_line_size - 1);
+ tail_bytes = (pagelist->offset + actual) &
+ (g_cache_line_size - 1);
+
+ if ((actual >= 0) && (head_bytes != 0)) {
+ if (head_bytes > actual)
+ head_bytes = actual;
+
+ memcpy((char *)kmap(pages[0]) +
+ pagelist->offset,
+ fragments,
+ head_bytes);
+ kunmap(pages[0]);
+ }
+ if ((actual >= 0) && (head_bytes < actual) &&
+ (tail_bytes != 0)) {
+ memcpy((char *)kmap(pages[num_pages - 1]) +
+ ((pagelist->offset + actual) &
+ (PAGE_SIZE - 1) & ~(g_cache_line_size - 1)),
+ fragments + g_cache_line_size,
+ tail_bytes);
+ kunmap(pages[num_pages - 1]);
+ }
+
+ down(&g_free_fragments_mutex);
+ *(char **)fragments = g_free_fragments;
+ g_free_fragments = fragments;
+ up(&g_free_fragments_mutex);
+ up(&g_free_fragments_sema);
+ }
+
+ /* Need to mark all the pages dirty. */
+ if (pagelist->type != PAGELIST_WRITE &&
+ pagelistinfo->pages_need_release) {
+ unsigned int i;
+
+ for (i = 0; i < num_pages; i++)
+ set_page_dirty(pages[i]);
+ }
+
+ cleanup_pagelistinfo(pagelistinfo);
+}
+
+int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
+{
+ struct device *dev = &pdev->dev;
+ struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev);
+ struct rpi_firmware *fw = drvdata->fw;
+ struct vchiq_slot_zero *vchiq_slot_zero;
+ void *slot_mem;
+ dma_addr_t slot_phys;
+ u32 channelbase;
+ int slot_mem_size, frag_mem_size;
+ int err, irq, i;
+
+ /*
+ * VCHI messages between the CPU and firmware use
+ * 32-bit bus addresses.
+ */
+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+
+ if (err < 0)
+ return err;
+
+ g_cache_line_size = drvdata->cache_line_size;
+ g_fragments_size = 2 * g_cache_line_size;
+
+ /* Allocate space for the channels in coherent memory */
+ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
+ frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS);
+
+ slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size,
+ &slot_phys, GFP_KERNEL);
+ if (!slot_mem) {
+ dev_err(dev, "could not allocate DMA memory\n");
+ return -ENOMEM;
+ }
+
+ WARN_ON(((unsigned long)slot_mem & (PAGE_SIZE - 1)) != 0);
+
+ vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size);
+ if (!vchiq_slot_zero)
+ return -EINVAL;
+
+ vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
+ (int)slot_phys + slot_mem_size;
+ vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
+ MAX_FRAGMENTS;
+
+ g_fragments_base = (char *)slot_mem + slot_mem_size;
+
+ g_free_fragments = g_fragments_base;
+ for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {
+ *(char **)&g_fragments_base[i*g_fragments_size] =
+ &g_fragments_base[(i + 1)*g_fragments_size];
+ }
+ *(char **)&g_fragments_base[i * g_fragments_size] = NULL;
+ sema_init(&g_free_fragments_sema, MAX_FRAGMENTS);
+
+ err = vchiq_init_state(state, vchiq_slot_zero);
+ if (err)
+ return err;
+
+ g_regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(g_regs))
+ return PTR_ERR(g_regs);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0)
+ return irq;
+
+ err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL,
+ "VCHIQ doorbell", state);
+ if (err) {
+ dev_err(dev, "failed to register irq=%d\n", irq);
+ return err;
+ }
+
+ /* Send the base address of the slots to VideoCore */
+ channelbase = slot_phys;
+ err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT,
+ &channelbase, sizeof(channelbase));
+ if (err || channelbase) {
+ dev_err(dev, "failed to set channelbase\n");
+ return err ? : -ENXIO;
+ }
+
+ g_dev = dev;
+ vchiq_log_info(vchiq_arm_log_level,
+ "vchiq_init - done (slots %pK, phys %pad)",
+ vchiq_slot_zero, &slot_phys);
+
+ vchiq_call_connected_callbacks();
+
+ return 0;
+}
+
+int
+vchiq_platform_init_state(struct vchiq_state *state)
+{
+ struct vchiq_2835_state *platform_state;
+
+ state->platform_state = kzalloc(sizeof(*platform_state), GFP_KERNEL);
+ if (!state->platform_state)
+ return -ENOMEM;
+
+ platform_state = (struct vchiq_2835_state *)state->platform_state;
+
+ platform_state->inited = 1;
+ vchiq_arm_init_state(state, &platform_state->arm_state);
+
+ return 0;
+}
+
+struct vchiq_arm_state*
+vchiq_platform_get_arm_state(struct vchiq_state *state)
+{
+ struct vchiq_2835_state *platform_state;
+
+ platform_state = (struct vchiq_2835_state *)state->platform_state;
+
+ WARN_ON_ONCE(!platform_state->inited);
+
+ return &platform_state->arm_state;
+}
+
+void
+remote_event_signal(struct remote_event *event)
+{
+ wmb();
+
+ event->fired = 1;
+
+ dsb(sy); /* data barrier operation */
+
+ if (event->armed)
+ writel(0, g_regs + BELL2); /* trigger vc interrupt */
+}
+
+int
+vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset,
+ void __user *uoffset, int size, int dir)
+{
+ struct vchiq_pagelist_info *pagelistinfo;
+
+ pagelistinfo = create_pagelist(offset, uoffset, size,
+ (dir == VCHIQ_BULK_RECEIVE)
+ ? PAGELIST_READ
+ : PAGELIST_WRITE);
+
+ if (!pagelistinfo)
+ return -ENOMEM;
+
+ bulk->data = pagelistinfo->dma_addr;
+
+ /*
+ * Store the pagelistinfo address in remote_data,
+ * which isn't used by the slave.
+ */
+ bulk->remote_data = pagelistinfo;
+
+ return 0;
+}
+
+void
+vchiq_complete_bulk(struct vchiq_bulk *bulk)
+{
+ if (bulk && bulk->remote_data && bulk->actual)
+ free_pagelist((struct vchiq_pagelist_info *)bulk->remote_data,
+ bulk->actual);
+}
+
+int vchiq_dump_platform_state(void *dump_context)
+{
+ char buf[80];
+ int len;
+
+ len = snprintf(buf, sizeof(buf),
+ " Platform: 2835 (VC master)");
+ return vchiq_dump(dump_context, buf, len + 1);
+}
+
#define VCHIQ_INIT_RETRIES 10
int vchiq_initialise(struct vchiq_instance **instance_out)
{
@@ -199,7 +652,7 @@ failed:
}
EXPORT_SYMBOL(vchiq_initialise);
-static void free_bulk_waiter(struct vchiq_instance *instance)
+void free_bulk_waiter(struct vchiq_instance *instance)
{
struct bulk_waiter_node *waiter, *next;
@@ -561,7 +1014,7 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
return VCHIQ_SUCCESS;
}
-static enum vchiq_status
+enum vchiq_status
service_callback(enum vchiq_reason reason, struct vchiq_header *header,
unsigned int handle, void *bulk_userdata)
{
@@ -672,1294 +1125,6 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
bulk_userdata);
}
-static void
-user_service_free(void *userdata)
-{
- kfree(userdata);
-}
-
-static void close_delivered(struct user_service *user_service)
-{
- vchiq_log_info(vchiq_arm_log_level,
- "%s(handle=%x)",
- __func__, user_service->service->handle);
-
- if (user_service->close_pending) {
- /* Allow the underlying service to be culled */
- vchiq_service_put(user_service->service);
-
- /* Wake the user-thread blocked in close_ or remove_service */
- complete(&user_service->close_event);
-
- user_service->close_pending = 0;
- }
-}
-
-struct vchiq_io_copy_callback_context {
- struct vchiq_element *element;
- size_t element_offset;
- unsigned long elements_to_go;
-};
-
-static ssize_t vchiq_ioc_copy_element_data(void *context, void *dest,
- size_t offset, size_t maxsize)
-{
- struct vchiq_io_copy_callback_context *cc = context;
- size_t total_bytes_copied = 0;
- size_t bytes_this_round;
-
- while (total_bytes_copied < maxsize) {
- if (!cc->elements_to_go)
- return total_bytes_copied;
-
- if (!cc->element->size) {
- cc->elements_to_go--;
- cc->element++;
- cc->element_offset = 0;
- continue;
- }
-
- bytes_this_round = min(cc->element->size - cc->element_offset,
- maxsize - total_bytes_copied);
-
- if (copy_from_user(dest + total_bytes_copied,
- cc->element->data + cc->element_offset,
- bytes_this_round))
- return -EFAULT;
-
- cc->element_offset += bytes_this_round;
- total_bytes_copied += bytes_this_round;
-
- if (cc->element_offset == cc->element->size) {
- cc->elements_to_go--;
- cc->element++;
- cc->element_offset = 0;
- }
- }
-
- return maxsize;
-}
-
-static int
-vchiq_ioc_queue_message(unsigned int handle, struct vchiq_element *elements,
- unsigned long count)
-{
- struct vchiq_io_copy_callback_context context;
- enum vchiq_status status = VCHIQ_SUCCESS;
- unsigned long i;
- size_t total_size = 0;
-
- context.element = elements;
- context.element_offset = 0;
- context.elements_to_go = count;
-
- for (i = 0; i < count; i++) {
- if (!elements[i].data && elements[i].size != 0)
- return -EFAULT;
-
- total_size += elements[i].size;
- }
-
- status = vchiq_queue_message(handle, vchiq_ioc_copy_element_data,
- &context, total_size);
-
- if (status == VCHIQ_ERROR)
- return -EIO;
- else if (status == VCHIQ_RETRY)
- return -EINTR;
- return 0;
-}
-
-static int vchiq_ioc_create_service(struct vchiq_instance *instance,
- struct vchiq_create_service *args)
-{
- struct user_service *user_service = NULL;
- struct vchiq_service *service;
- enum vchiq_status status = VCHIQ_SUCCESS;
- struct vchiq_service_params_kernel params;
- int srvstate;
-
- user_service = kmalloc(sizeof(*user_service), GFP_KERNEL);
- if (!user_service)
- return -ENOMEM;
-
- if (args->is_open) {
- if (!instance->connected) {
- kfree(user_service);
- return -ENOTCONN;
- }
- srvstate = VCHIQ_SRVSTATE_OPENING;
- } else {
- srvstate = instance->connected ?
- VCHIQ_SRVSTATE_LISTENING : VCHIQ_SRVSTATE_HIDDEN;
- }
-
- params = (struct vchiq_service_params_kernel) {
- .fourcc = args->params.fourcc,
- .callback = service_callback,
- .userdata = user_service,
- .version = args->params.version,
- .version_min = args->params.version_min,
- };
- service = vchiq_add_service_internal(instance->state, &params,
- srvstate, instance,
- user_service_free);
- if (!service) {
- kfree(user_service);
- return -EEXIST;
- }
-
- user_service->service = service;
- user_service->userdata = args->params.userdata;
- user_service->instance = instance;
- user_service->is_vchi = (args->is_vchi != 0);
- user_service->dequeue_pending = 0;
- user_service->close_pending = 0;
- user_service->message_available_pos = instance->completion_remove - 1;
- user_service->msg_insert = 0;
- user_service->msg_remove = 0;
- init_completion(&user_service->insert_event);
- init_completion(&user_service->remove_event);
- init_completion(&user_service->close_event);
-
- if (args->is_open) {
- status = vchiq_open_service_internal(service, instance->pid);
- if (status != VCHIQ_SUCCESS) {
- vchiq_remove_service(service->handle);
- return (status == VCHIQ_RETRY) ?
- -EINTR : -EIO;
- }
- }
- args->handle = service->handle;
-
- return 0;
-}
-
-static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
- struct vchiq_dequeue_message *args)
-{
- struct user_service *user_service;
- struct vchiq_service *service;
- struct vchiq_header *header;
- int ret;
-
- DEBUG_INITIALISE(g_state.local)
- DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
- service = find_service_for_instance(instance, args->handle);
- if (!service)
- return -EINVAL;
-
- user_service = (struct user_service *)service->base.userdata;
- if (user_service->is_vchi == 0) {
- ret = -EINVAL;
- goto out;
- }
-
- spin_lock(&msg_queue_spinlock);
- if (user_service->msg_remove == user_service->msg_insert) {
- if (!args->blocking) {
- spin_unlock(&msg_queue_spinlock);
- DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
- ret = -EWOULDBLOCK;
- goto out;
- }
- user_service->dequeue_pending = 1;
- ret = 0;
- do {
- spin_unlock(&msg_queue_spinlock);
- DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
- if (wait_for_completion_interruptible(
- &user_service->insert_event)) {
- vchiq_log_info(vchiq_arm_log_level,
- "DEQUEUE_MESSAGE interrupted");
- ret = -EINTR;
- break;
- }
- spin_lock(&msg_queue_spinlock);
- } while (user_service->msg_remove == user_service->msg_insert);
-
- if (ret)
- goto out;
- }
-
- if (WARN_ON_ONCE((int)(user_service->msg_insert -
- user_service->msg_remove) < 0)) {
- spin_unlock(&msg_queue_spinlock);
- ret = -EINVAL;
- goto out;
- }
-
- header = user_service->msg_queue[user_service->msg_remove &
- (MSG_QUEUE_SIZE - 1)];
- user_service->msg_remove++;
- spin_unlock(&msg_queue_spinlock);
-
- complete(&user_service->remove_event);
- if (!header) {
- ret = -ENOTCONN;
- } else if (header->size <= args->bufsize) {
- /* Copy to user space if msgbuf is not NULL */
- if (!args->buf || (copy_to_user(args->buf,
- header->data, header->size) == 0)) {
- ret = header->size;
- vchiq_release_message(service->handle, header);
- } else {
- ret = -EFAULT;
- }
- } else {
- vchiq_log_error(vchiq_arm_log_level,
- "header %pK: bufsize %x < size %x",
- header, args->bufsize, header->size);
- WARN(1, "invalid size\n");
- ret = -EMSGSIZE;
- }
- DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
-out:
- vchiq_service_put(service);
- return ret;
-}
-
-static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
- struct vchiq_queue_bulk_transfer *args,
- enum vchiq_bulk_dir dir,
- enum vchiq_bulk_mode __user *mode)
-{
- struct vchiq_service *service;
- struct bulk_waiter_node *waiter = NULL;
- bool found = false;
- void *userdata;
- int status = 0;
- int ret;
-
- service = find_service_for_instance(instance, args->handle);
- if (!service)
- return -EINVAL;
-
- if (args->mode == VCHIQ_BULK_MODE_BLOCKING) {
- waiter = kzalloc(sizeof(*waiter), GFP_KERNEL);
- if (!waiter) {
- ret = -ENOMEM;
- goto out;
- }
-
- userdata = &waiter->bulk_waiter;
- } else if (args->mode == VCHIQ_BULK_MODE_WAITING) {
- mutex_lock(&instance->bulk_waiter_list_mutex);
- list_for_each_entry(waiter, &instance->bulk_waiter_list,
- list) {
- if (waiter->pid == current->pid) {
- list_del(&waiter->list);
- found = true;
- break;
- }
- }
- mutex_unlock(&instance->bulk_waiter_list_mutex);
- if (!found) {
- vchiq_log_error(vchiq_arm_log_level,
- "no bulk_waiter found for pid %d",
- current->pid);
- ret = -ESRCH;
- goto out;
- }
- vchiq_log_info(vchiq_arm_log_level,
- "found bulk_waiter %pK for pid %d", waiter,
- current->pid);
- userdata = &waiter->bulk_waiter;
- } else {
- userdata = args->userdata;
- }
-
- status = vchiq_bulk_transfer(args->handle, NULL, args->data, args->size,
- userdata, args->mode, dir);
-
- if (!waiter) {
- ret = 0;
- goto out;
- }
-
- if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) ||
- !waiter->bulk_waiter.bulk) {
- if (waiter->bulk_waiter.bulk) {
- /* Cancel the signal when the transfer completes. */
- spin_lock(&bulk_waiter_spinlock);
- waiter->bulk_waiter.bulk->userdata = NULL;
- spin_unlock(&bulk_waiter_spinlock);
- }
- kfree(waiter);
- ret = 0;
- } else {
- const enum vchiq_bulk_mode mode_waiting =
- VCHIQ_BULK_MODE_WAITING;
- waiter->pid = current->pid;
- mutex_lock(&instance->bulk_waiter_list_mutex);
- list_add(&waiter->list, &instance->bulk_waiter_list);
- mutex_unlock(&instance->bulk_waiter_list_mutex);
- vchiq_log_info(vchiq_arm_log_level,
- "saved bulk_waiter %pK for pid %d",
- waiter, current->pid);
-
- ret = put_user(mode_waiting, mode);
- }
-out:
- vchiq_service_put(service);
- if (ret)
- return ret;
- else if (status == VCHIQ_ERROR)
- return -EIO;
- else if (status == VCHIQ_RETRY)
- return -EINTR;
- return 0;
-}
-
-/* read a user pointer value from an array pointers in user space */
-static inline int vchiq_get_user_ptr(void __user **buf, void __user *ubuf, int index)
-{
- int ret;
-
- if (in_compat_syscall()) {
- compat_uptr_t ptr32;
- compat_uptr_t __user *uptr = ubuf;
-
- ret = get_user(ptr32, uptr + index);
- if (ret)
- return ret;
-
- *buf = compat_ptr(ptr32);
- } else {
- uintptr_t ptr, __user *uptr = ubuf;
-
- ret = get_user(ptr, uptr + index);
-
- if (ret)
- return ret;
-
- *buf = (void __user *)ptr;
- }
-
- return 0;
-}
-
-struct vchiq_completion_data32 {
- enum vchiq_reason reason;
- compat_uptr_t header;
- compat_uptr_t service_userdata;
- compat_uptr_t bulk_userdata;
-};
-
-static int vchiq_put_completion(struct vchiq_completion_data __user *buf,
- struct vchiq_completion_data *completion,
- int index)
-{
- struct vchiq_completion_data32 __user *buf32 = (void __user *)buf;
-
- if (in_compat_syscall()) {
- struct vchiq_completion_data32 tmp = {
- .reason = completion->reason,
- .header = ptr_to_compat(completion->header),
- .service_userdata = ptr_to_compat(completion->service_userdata),
- .bulk_userdata = ptr_to_compat(completion->bulk_userdata),
- };
- if (copy_to_user(&buf32[index], &tmp, sizeof(tmp)))
- return -EFAULT;
- } else {
- if (copy_to_user(&buf[index], completion, sizeof(*completion)))
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int vchiq_ioc_await_completion(struct vchiq_instance *instance,
- struct vchiq_await_completion *args,
- int __user *msgbufcountp)
-{
- int msgbufcount;
- int remove;
- int ret;
-
- DEBUG_INITIALISE(g_state.local)
-
- DEBUG_TRACE(AWAIT_COMPLETION_LINE);
- if (!instance->connected) {
- return -ENOTCONN;
- }
-
- mutex_lock(&instance->completion_mutex);
-
- DEBUG_TRACE(AWAIT_COMPLETION_LINE);
- while ((instance->completion_remove == instance->completion_insert)
- && !instance->closing) {
- int rc;
-
- DEBUG_TRACE(AWAIT_COMPLETION_LINE);
- mutex_unlock(&instance->completion_mutex);
- rc = wait_for_completion_interruptible(
- &instance->insert_event);
- mutex_lock(&instance->completion_mutex);
- if (rc) {
- DEBUG_TRACE(AWAIT_COMPLETION_LINE);
- vchiq_log_info(vchiq_arm_log_level,
- "AWAIT_COMPLETION interrupted");
- ret = -EINTR;
- goto out;
- }
- }
- DEBUG_TRACE(AWAIT_COMPLETION_LINE);
-
- msgbufcount = args->msgbufcount;
- remove = instance->completion_remove;
-
- for (ret = 0; ret < args->count; ret++) {
- struct vchiq_completion_data_kernel *completion;
- struct vchiq_completion_data user_completion;
- struct vchiq_service *service;
- struct user_service *user_service;
- struct vchiq_header *header;
-
- if (remove == instance->completion_insert)
- break;
-
- completion = &instance->completions[
- remove & (MAX_COMPLETIONS - 1)];
-
- /*
- * A read memory barrier is needed to stop
- * prefetch of a stale completion record
- */
- rmb();
-
- service = completion->service_userdata;
- user_service = service->base.userdata;
-
- memset(&user_completion, 0, sizeof(user_completion));
- user_completion = (struct vchiq_completion_data) {
- .reason = completion->reason,
- .service_userdata = user_service->userdata,
- };
-
- header = completion->header;
- if (header) {
- void __user *msgbuf;
- int msglen;
-
- msglen = header->size + sizeof(struct vchiq_header);
- /* This must be a VCHIQ-style service */
- if (args->msgbufsize < msglen) {
- vchiq_log_error(vchiq_arm_log_level,
- "header %pK: msgbufsize %x < msglen %x",
- header, args->msgbufsize, msglen);
- WARN(1, "invalid message size\n");
- if (ret == 0)
- ret = -EMSGSIZE;
- break;
- }
- if (msgbufcount <= 0)
- /* Stall here for lack of a buffer for the message. */
- break;
- /* Get the pointer from user space */
- msgbufcount--;
- if (vchiq_get_user_ptr(&msgbuf, args->msgbufs,
- msgbufcount)) {
- if (ret == 0)
- ret = -EFAULT;
- break;
- }
-
- /* Copy the message to user space */
- if (copy_to_user(msgbuf, header, msglen)) {
- if (ret == 0)
- ret = -EFAULT;
- break;
- }
-
- /* Now it has been copied, the message can be released. */
- vchiq_release_message(service->handle, header);
-
- /* The completion must point to the msgbuf. */
- user_completion.header = msgbuf;
- }
-
- if ((completion->reason == VCHIQ_SERVICE_CLOSED) &&
- !instance->use_close_delivered)
- vchiq_service_put(service);
-
- /*
- * FIXME: address space mismatch, does bulk_userdata
- * actually point to user or kernel memory?
- */
- user_completion.bulk_userdata = completion->bulk_userdata;
-
- if (vchiq_put_completion(args->buf, &user_completion, ret)) {
- if (ret == 0)
- ret = -EFAULT;
- break;
- }
-
- /*
- * Ensure that the above copy has completed
- * before advancing the remove pointer.
- */
- mb();
- remove++;
- instance->completion_remove = remove;
- }
-
- if (msgbufcount != args->msgbufcount) {
- if (put_user(msgbufcount, msgbufcountp))
- ret = -EFAULT;
- }
-out:
- if (ret)
- complete(&instance->remove_event);
- mutex_unlock(&instance->completion_mutex);
- DEBUG_TRACE(AWAIT_COMPLETION_LINE);
-
- return ret;
-}
-
-static long
-vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct vchiq_instance *instance = file->private_data;
- enum vchiq_status status = VCHIQ_SUCCESS;
- struct vchiq_service *service = NULL;
- long ret = 0;
- int i, rc;
-
- vchiq_log_trace(vchiq_arm_log_level,
- "%s - instance %pK, cmd %s, arg %lx",
- __func__, instance,
- ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) &&
- (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ?
- ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg);
-
- switch (cmd) {
- case VCHIQ_IOC_SHUTDOWN:
- if (!instance->connected)
- break;
-
- /* Remove all services */
- i = 0;
- while ((service = next_service_by_instance(instance->state,
- instance, &i))) {
- status = vchiq_remove_service(service->handle);
- vchiq_service_put(service);
- if (status != VCHIQ_SUCCESS)
- break;
- }
- service = NULL;
-
- if (status == VCHIQ_SUCCESS) {
- /* Wake the completion thread and ask it to exit */
- instance->closing = 1;
- complete(&instance->insert_event);
- }
-
- break;
-
- case VCHIQ_IOC_CONNECT:
- if (instance->connected) {
- ret = -EINVAL;
- break;
- }
- rc = mutex_lock_killable(&instance->state->mutex);
- if (rc) {
- vchiq_log_error(vchiq_arm_log_level,
- "vchiq: connect: could not lock mutex for state %d: %d",
- instance->state->id, rc);
- ret = -EINTR;
- break;
- }
- status = vchiq_connect_internal(instance->state, instance);
- mutex_unlock(&instance->state->mutex);
-
- if (status == VCHIQ_SUCCESS)
- instance->connected = 1;
- else
- vchiq_log_error(vchiq_arm_log_level,
- "vchiq: could not connect: %d", status);
- break;
-
- case VCHIQ_IOC_CREATE_SERVICE: {
- struct vchiq_create_service __user *argp;
- struct vchiq_create_service args;
-
- argp = (void __user *)arg;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
-
- ret = vchiq_ioc_create_service(instance, &args);
- if (ret < 0)
- break;
-
- if (put_user(args.handle, &argp->handle)) {
- vchiq_remove_service(args.handle);
- ret = -EFAULT;
- }
- } break;
-
- case VCHIQ_IOC_CLOSE_SERVICE:
- case VCHIQ_IOC_REMOVE_SERVICE: {
- unsigned int handle = (unsigned int)arg;
- struct user_service *user_service;
-
- service = find_service_for_instance(instance, handle);
- if (!service) {
- ret = -EINVAL;
- break;
- }
-
- user_service = service->base.userdata;
-
- /*
- * close_pending is false on first entry, and when the
- * wait in vchiq_close_service has been interrupted.
- */
- if (!user_service->close_pending) {
- status = (cmd == VCHIQ_IOC_CLOSE_SERVICE) ?
- vchiq_close_service(service->handle) :
- vchiq_remove_service(service->handle);
- if (status != VCHIQ_SUCCESS)
- break;
- }
-
- /*
- * close_pending is true once the underlying service
- * has been closed until the client library calls the
- * CLOSE_DELIVERED ioctl, signalling close_event.
- */
- if (user_service->close_pending &&
- wait_for_completion_interruptible(
- &user_service->close_event))
- status = VCHIQ_RETRY;
- break;
- }
-
- case VCHIQ_IOC_USE_SERVICE:
- case VCHIQ_IOC_RELEASE_SERVICE: {
- unsigned int handle = (unsigned int)arg;
-
- service = find_service_for_instance(instance, handle);
- if (service) {
- ret = (cmd == VCHIQ_IOC_USE_SERVICE) ?
- vchiq_use_service_internal(service) :
- vchiq_release_service_internal(service);
- if (ret) {
- vchiq_log_error(vchiq_susp_log_level,
- "%s: cmd %s returned error %ld for service %c%c%c%c:%03d",
- __func__,
- (cmd == VCHIQ_IOC_USE_SERVICE) ?
- "VCHIQ_IOC_USE_SERVICE" :
- "VCHIQ_IOC_RELEASE_SERVICE",
- ret,
- VCHIQ_FOURCC_AS_4CHARS(
- service->base.fourcc),
- service->client_id);
- }
- } else {
- ret = -EINVAL;
- }
- } break;
-
- case VCHIQ_IOC_QUEUE_MESSAGE: {
- struct vchiq_queue_message args;
-
- if (copy_from_user(&args, (const void __user *)arg,
- sizeof(args))) {
- ret = -EFAULT;
- break;
- }
-
- service = find_service_for_instance(instance, args.handle);
-
- if (service && (args.count <= MAX_ELEMENTS)) {
- /* Copy elements into kernel space */
- struct vchiq_element elements[MAX_ELEMENTS];
-
- if (copy_from_user(elements, args.elements,
- args.count * sizeof(struct vchiq_element)) == 0)
- ret = vchiq_ioc_queue_message(args.handle, elements,
- args.count);
- else
- ret = -EFAULT;
- } else {
- ret = -EINVAL;
- }
- } break;
-
- case VCHIQ_IOC_QUEUE_BULK_TRANSMIT:
- case VCHIQ_IOC_QUEUE_BULK_RECEIVE: {
- struct vchiq_queue_bulk_transfer args;
- struct vchiq_queue_bulk_transfer __user *argp;
-
- enum vchiq_bulk_dir dir =
- (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
- VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
-
- argp = (void __user *)arg;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
-
- ret = vchiq_irq_queue_bulk_tx_rx(instance, &args,
- dir, &argp->mode);
- } break;
-
- case VCHIQ_IOC_AWAIT_COMPLETION: {
- struct vchiq_await_completion args;
- struct vchiq_await_completion __user *argp;
-
- argp = (void __user *)arg;
- if (copy_from_user(&args, argp, sizeof(args))) {
- ret = -EFAULT;
- break;
- }
-
- ret = vchiq_ioc_await_completion(instance, &args,
- &argp->msgbufcount);
- } break;
-
- case VCHIQ_IOC_DEQUEUE_MESSAGE: {
- struct vchiq_dequeue_message args;
-
- if (copy_from_user(&args, (const void __user *)arg,
- sizeof(args))) {
- ret = -EFAULT;
- break;
- }
-
- ret = vchiq_ioc_dequeue_message(instance, &args);
- } break;
-
- case VCHIQ_IOC_GET_CLIENT_ID: {
- unsigned int handle = (unsigned int)arg;
-
- ret = vchiq_get_client_id(handle);
- } break;
-
- case VCHIQ_IOC_GET_CONFIG: {
- struct vchiq_get_config args;
- struct vchiq_config config;
-
- if (copy_from_user(&args, (const void __user *)arg,
- sizeof(args))) {
- ret = -EFAULT;
- break;
- }
- if (args.config_size > sizeof(config)) {
- ret = -EINVAL;
- break;
- }
-
- vchiq_get_config(&config);
- if (copy_to_user(args.pconfig, &config, args.config_size)) {
- ret = -EFAULT;
- break;
- }
- } break;
-
- case VCHIQ_IOC_SET_SERVICE_OPTION: {
- struct vchiq_set_service_option args;
-
- if (copy_from_user(&args, (const void __user *)arg,
- sizeof(args))) {
- ret = -EFAULT;
- break;
- }
-
- service = find_service_for_instance(instance, args.handle);
- if (!service) {
- ret = -EINVAL;
- break;
- }
-
- ret = vchiq_set_service_option(args.handle, args.option,
- args.value);
- } break;
-
- case VCHIQ_IOC_LIB_VERSION: {
- unsigned int lib_version = (unsigned int)arg;
-
- if (lib_version < VCHIQ_VERSION_MIN)
- ret = -EINVAL;
- else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED)
- instance->use_close_delivered = 1;
- } break;
-
- case VCHIQ_IOC_CLOSE_DELIVERED: {
- unsigned int handle = (unsigned int)arg;
-
- service = find_closed_service_for_instance(instance, handle);
- if (service) {
- struct user_service *user_service =
- (struct user_service *)service->base.userdata;
- close_delivered(user_service);
- } else {
- ret = -EINVAL;
- }
- } break;
-
- default:
- ret = -ENOTTY;
- break;
- }
-
- if (service)
- vchiq_service_put(service);
-
- if (ret == 0) {
- if (status == VCHIQ_ERROR)
- ret = -EIO;
- else if (status == VCHIQ_RETRY)
- ret = -EINTR;
- }
-
- if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) &&
- (ret != -EWOULDBLOCK))
- vchiq_log_info(vchiq_arm_log_level,
- " ioctl instance %pK, cmd %s -> status %d, %ld",
- instance,
- (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
- ioctl_names[_IOC_NR(cmd)] :
- "<invalid>",
- status, ret);
- else
- vchiq_log_trace(vchiq_arm_log_level,
- " ioctl instance %pK, cmd %s -> status %d, %ld",
- instance,
- (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
- ioctl_names[_IOC_NR(cmd)] :
- "<invalid>",
- status, ret);
-
- return ret;
-}
-
-#if defined(CONFIG_COMPAT)
-
-struct vchiq_service_params32 {
- int fourcc;
- compat_uptr_t callback;
- compat_uptr_t userdata;
- short version; /* Increment for non-trivial changes */
- short version_min; /* Update for incompatible changes */
-};
-
-struct vchiq_create_service32 {
- struct vchiq_service_params32 params;
- int is_open;
- int is_vchi;
- unsigned int handle; /* OUT */
-};
-
-#define VCHIQ_IOC_CREATE_SERVICE32 \
- _IOWR(VCHIQ_IOC_MAGIC, 2, struct vchiq_create_service32)
-
-static long
-vchiq_compat_ioctl_create_service(struct file *file, unsigned int cmd,
- struct vchiq_create_service32 __user *ptrargs32)
-{
- struct vchiq_create_service args;
- struct vchiq_create_service32 args32;
- long ret;
-
- if (copy_from_user(&args32, ptrargs32, sizeof(args32)))
- return -EFAULT;
-
- args = (struct vchiq_create_service) {
- .params = {
- .fourcc = args32.params.fourcc,
- .callback = compat_ptr(args32.params.callback),
- .userdata = compat_ptr(args32.params.userdata),
- .version = args32.params.version,
- .version_min = args32.params.version_min,
- },
- .is_open = args32.is_open,
- .is_vchi = args32.is_vchi,
- .handle = args32.handle,
- };
-
- ret = vchiq_ioc_create_service(file->private_data, &args);
- if (ret < 0)
- return ret;
-
- if (put_user(args.handle, &ptrargs32->handle)) {
- vchiq_remove_service(args.handle);
- return -EFAULT;
- }
-
- return 0;
-}
-
-struct vchiq_element32 {
- compat_uptr_t data;
- unsigned int size;
-};
-
-struct vchiq_queue_message32 {
- unsigned int handle;
- unsigned int count;
- compat_uptr_t elements;
-};
-
-#define VCHIQ_IOC_QUEUE_MESSAGE32 \
- _IOW(VCHIQ_IOC_MAGIC, 4, struct vchiq_queue_message32)
-
-static long
-vchiq_compat_ioctl_queue_message(struct file *file,
- unsigned int cmd,
- struct vchiq_queue_message32 __user *arg)
-{
- struct vchiq_queue_message args;
- struct vchiq_queue_message32 args32;
- struct vchiq_service *service;
- int ret;
-
- if (copy_from_user(&args32, arg, sizeof(args32)))
- return -EFAULT;
-
- args = (struct vchiq_queue_message) {
- .handle = args32.handle,
- .count = args32.count,
- .elements = compat_ptr(args32.elements),
- };
-
- if (args32.count > MAX_ELEMENTS)
- return -EINVAL;
-
- service = find_service_for_instance(file->private_data, args.handle);
- if (!service)
- return -EINVAL;
-
- if (args32.elements && args32.count) {
- struct vchiq_element32 element32[MAX_ELEMENTS];
- struct vchiq_element elements[MAX_ELEMENTS];
- unsigned int count;
-
- if (copy_from_user(&element32, args.elements,
- sizeof(element32))) {
- vchiq_service_put(service);
- return -EFAULT;
- }
-
- for (count = 0; count < args32.count; count++) {
- elements[count].data =
- compat_ptr(element32[count].data);
- elements[count].size = element32[count].size;
- }
- ret = vchiq_ioc_queue_message(args.handle, elements,
- args.count);
- } else {
- ret = -EINVAL;
- }
- vchiq_service_put(service);
-
- return ret;
-}
-
-struct vchiq_queue_bulk_transfer32 {
- unsigned int handle;
- compat_uptr_t data;
- unsigned int size;
- compat_uptr_t userdata;
- enum vchiq_bulk_mode mode;
-};
-
-#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 \
- _IOWR(VCHIQ_IOC_MAGIC, 5, struct vchiq_queue_bulk_transfer32)
-#define VCHIQ_IOC_QUEUE_BULK_RECEIVE32 \
- _IOWR(VCHIQ_IOC_MAGIC, 6, struct vchiq_queue_bulk_transfer32)
-
-static long
-vchiq_compat_ioctl_queue_bulk(struct file *file,
- unsigned int cmd,
- struct vchiq_queue_bulk_transfer32 __user *argp)
-{
- struct vchiq_queue_bulk_transfer32 args32;
- struct vchiq_queue_bulk_transfer args;
- enum vchiq_bulk_dir dir = (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32) ?
- VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
-
- if (copy_from_user(&args32, argp, sizeof(args32)))
- return -EFAULT;
-
- args = (struct vchiq_queue_bulk_transfer) {
- .handle = args32.handle,
- .data = compat_ptr(args32.data),
- .size = args32.size,
- .userdata = compat_ptr(args32.userdata),
- .mode = args32.mode,
- };
-
- return vchiq_irq_queue_bulk_tx_rx(file->private_data, &args,
- dir, &argp->mode);
-}
-
-struct vchiq_await_completion32 {
- unsigned int count;
- compat_uptr_t buf;
- unsigned int msgbufsize;
- unsigned int msgbufcount; /* IN/OUT */
- compat_uptr_t msgbufs;
-};
-
-#define VCHIQ_IOC_AWAIT_COMPLETION32 \
- _IOWR(VCHIQ_IOC_MAGIC, 7, struct vchiq_await_completion32)
-
-static long
-vchiq_compat_ioctl_await_completion(struct file *file,
- unsigned int cmd,
- struct vchiq_await_completion32 __user *argp)
-{
- struct vchiq_await_completion args;
- struct vchiq_await_completion32 args32;
-
- if (copy_from_user(&args32, argp, sizeof(args32)))
- return -EFAULT;
-
- args = (struct vchiq_await_completion) {
- .count = args32.count,
- .buf = compat_ptr(args32.buf),
- .msgbufsize = args32.msgbufsize,
- .msgbufcount = args32.msgbufcount,
- .msgbufs = compat_ptr(args32.msgbufs),
- };
-
- return vchiq_ioc_await_completion(file->private_data, &args,
- &argp->msgbufcount);
-}
-
-struct vchiq_dequeue_message32 {
- unsigned int handle;
- int blocking;
- unsigned int bufsize;
- compat_uptr_t buf;
-};
-
-#define VCHIQ_IOC_DEQUEUE_MESSAGE32 \
- _IOWR(VCHIQ_IOC_MAGIC, 8, struct vchiq_dequeue_message32)
-
-static long
-vchiq_compat_ioctl_dequeue_message(struct file *file,
- unsigned int cmd,
- struct vchiq_dequeue_message32 __user *arg)
-{
- struct vchiq_dequeue_message32 args32;
- struct vchiq_dequeue_message args;
-
- if (copy_from_user(&args32, arg, sizeof(args32)))
- return -EFAULT;
-
- args = (struct vchiq_dequeue_message) {
- .handle = args32.handle,
- .blocking = args32.blocking,
- .bufsize = args32.bufsize,
- .buf = compat_ptr(args32.buf),
- };
-
- return vchiq_ioc_dequeue_message(file->private_data, &args);
-}
-
-struct vchiq_get_config32 {
- unsigned int config_size;
- compat_uptr_t pconfig;
-};
-
-#define VCHIQ_IOC_GET_CONFIG32 \
- _IOWR(VCHIQ_IOC_MAGIC, 10, struct vchiq_get_config32)
-
-static long
-vchiq_compat_ioctl_get_config(struct file *file,
- unsigned int cmd,
- struct vchiq_get_config32 __user *arg)
-{
- struct vchiq_get_config32 args32;
- struct vchiq_config config;
- void __user *ptr;
-
- if (copy_from_user(&args32, arg, sizeof(args32)))
- return -EFAULT;
- if (args32.config_size > sizeof(config))
- return -EINVAL;
-
- vchiq_get_config(&config);
- ptr = compat_ptr(args32.pconfig);
- if (copy_to_user(ptr, &config, args32.config_size))
- return -EFAULT;
-
- return 0;
-}
-
-static long
-vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = compat_ptr(arg);
-
- switch (cmd) {
- case VCHIQ_IOC_CREATE_SERVICE32:
- return vchiq_compat_ioctl_create_service(file, cmd, argp);
- case VCHIQ_IOC_QUEUE_MESSAGE32:
- return vchiq_compat_ioctl_queue_message(file, cmd, argp);
- case VCHIQ_IOC_QUEUE_BULK_TRANSMIT32:
- case VCHIQ_IOC_QUEUE_BULK_RECEIVE32:
- return vchiq_compat_ioctl_queue_bulk(file, cmd, argp);
- case VCHIQ_IOC_AWAIT_COMPLETION32:
- return vchiq_compat_ioctl_await_completion(file, cmd, argp);
- case VCHIQ_IOC_DEQUEUE_MESSAGE32:
- return vchiq_compat_ioctl_dequeue_message(file, cmd, argp);
- case VCHIQ_IOC_GET_CONFIG32:
- return vchiq_compat_ioctl_get_config(file, cmd, argp);
- default:
- return vchiq_ioctl(file, cmd, (unsigned long)argp);
- }
-}
-
-#endif
-
-static int vchiq_open(struct inode *inode, struct file *file)
-{
- struct vchiq_state *state = vchiq_get_state();
- struct vchiq_instance *instance;
-
- vchiq_log_info(vchiq_arm_log_level, "vchiq_open");
-
- if (!state) {
- vchiq_log_error(vchiq_arm_log_level,
- "vchiq has no connection to VideoCore");
- return -ENOTCONN;
- }
-
- instance = kzalloc(sizeof(*instance), GFP_KERNEL);
- if (!instance)
- return -ENOMEM;
-
- instance->state = state;
- instance->pid = current->tgid;
-
- vchiq_debugfs_add_instance(instance);
-
- init_completion(&instance->insert_event);
- init_completion(&instance->remove_event);
- mutex_init(&instance->completion_mutex);
- mutex_init(&instance->bulk_waiter_list_mutex);
- INIT_LIST_HEAD(&instance->bulk_waiter_list);
-
- file->private_data = instance;
-
- return 0;
-}
-
-static int vchiq_release(struct inode *inode, struct file *file)
-{
- struct vchiq_instance *instance = file->private_data;
- struct vchiq_state *state = vchiq_get_state();
- struct vchiq_service *service;
- int ret = 0;
- int i;
-
- vchiq_log_info(vchiq_arm_log_level, "%s: instance=%lx", __func__,
- (unsigned long)instance);
-
- if (!state) {
- ret = -EPERM;
- goto out;
- }
-
- /* Ensure videocore is awake to allow termination. */
- vchiq_use_internal(instance->state, NULL, USE_TYPE_VCHIQ);
-
- mutex_lock(&instance->completion_mutex);
-
- /* Wake the completion thread and ask it to exit */
- instance->closing = 1;
- complete(&instance->insert_event);
-
- mutex_unlock(&instance->completion_mutex);
-
- /* Wake the slot handler if the completion queue is full. */
- complete(&instance->remove_event);
-
- /* Mark all services for termination... */
- i = 0;
- while ((service = next_service_by_instance(state, instance, &i))) {
- struct user_service *user_service = service->base.userdata;
-
- /* Wake the slot handler if the msg queue is full. */
- complete(&user_service->remove_event);
-
- vchiq_terminate_service_internal(service);
- vchiq_service_put(service);
- }
-
- /* ...and wait for them to die */
- i = 0;
- while ((service = next_service_by_instance(state, instance, &i))) {
- struct user_service *user_service = service->base.userdata;
-
- wait_for_completion(&service->remove_event);
-
- if (WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE)) {
- vchiq_service_put(service);
- break;
- }
-
- spin_lock(&msg_queue_spinlock);
-
- while (user_service->msg_remove != user_service->msg_insert) {
- struct vchiq_header *header;
- int m = user_service->msg_remove & (MSG_QUEUE_SIZE - 1);
-
- header = user_service->msg_queue[m];
- user_service->msg_remove++;
- spin_unlock(&msg_queue_spinlock);
-
- if (header)
- vchiq_release_message(service->handle, header);
- spin_lock(&msg_queue_spinlock);
- }
-
- spin_unlock(&msg_queue_spinlock);
-
- vchiq_service_put(service);
- }
-
- /* Release any closed services */
- while (instance->completion_remove != instance->completion_insert) {
- struct vchiq_completion_data_kernel *completion;
- struct vchiq_service *service;
-
- completion = &instance->completions[
- instance->completion_remove & (MAX_COMPLETIONS - 1)];
- service = completion->service_userdata;
- if (completion->reason == VCHIQ_SERVICE_CLOSED) {
- struct user_service *user_service =
- service->base.userdata;
-
- /* Wake any blocked user-thread */
- if (instance->use_close_delivered)
- complete(&user_service->close_event);
- vchiq_service_put(service);
- }
- instance->completion_remove++;
- }
-
- /* Release the PEER service count. */
- vchiq_release_internal(instance->state, NULL);
-
- free_bulk_waiter(instance);
-
- vchiq_debugfs_remove_instance(instance);
-
- kfree(instance);
- file->private_data = NULL;
-
-out:
- return ret;
-}
-
int vchiq_dump(void *dump_context, const char *str, int len)
{
struct dump_context *context = (struct dump_context *)dump_context;
@@ -2088,26 +1253,6 @@ int vchiq_dump_platform_service_state(void *dump_context,
return vchiq_dump(dump_context, buf, len + 1);
}
-static ssize_t
-vchiq_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
- struct dump_context context;
- int err;
-
- context.buf = buf;
- context.actual = 0;
- context.space = count;
- context.offset = *ppos;
-
- err = vchiq_dump_state(&context, &g_state);
- if (err)
- return err;
-
- *ppos += context.actual;
-
- return context.actual;
-}
-
struct vchiq_state *
vchiq_get_state(void)
{
@@ -2122,18 +1267,6 @@ vchiq_get_state(void)
(g_state.remote->initialised == 1)) ? &g_state : NULL;
}
-static const struct file_operations
-vchiq_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = vchiq_ioctl,
-#if defined(CONFIG_COMPAT)
- .compat_ioctl = vchiq_compat_ioctl,
-#endif
- .open = vchiq_open,
- .release = vchiq_release,
- .read = vchiq_read
-};
-
/*
* Autosuspend related functionality
*/
@@ -2644,7 +1777,6 @@ static int vchiq_probe(struct platform_device *pdev)
struct device_node *fw_node;
const struct of_device_id *of_id;
struct vchiq_drvdata *drvdata;
- struct device *vchiq_dev;
int err;
of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
@@ -2670,38 +1802,31 @@ static int vchiq_probe(struct platform_device *pdev)
if (err)
goto failed_platform_init;
- cdev_init(&vchiq_cdev, &vchiq_fops);
- vchiq_cdev.owner = THIS_MODULE;
- err = cdev_add(&vchiq_cdev, vchiq_devid, 1);
- if (err) {
- vchiq_log_error(vchiq_arm_log_level,
- "Unable to register device");
- goto failed_platform_init;
- }
-
- vchiq_dev = device_create(vchiq_class, &pdev->dev, vchiq_devid, NULL,
- "vchiq");
- if (IS_ERR(vchiq_dev)) {
- err = PTR_ERR(vchiq_dev);
- goto failed_device_create;
- }
-
vchiq_debugfs_init();
vchiq_log_info(vchiq_arm_log_level,
- "vchiq: initialised - version %d (min %d), device %d.%d",
- VCHIQ_VERSION, VCHIQ_VERSION_MIN,
- MAJOR(vchiq_devid), MINOR(vchiq_devid));
+ "vchiq: platform initialised - version %d (min %d)",
+ VCHIQ_VERSION, VCHIQ_VERSION_MIN);
+
+ /*
+ * Simply exit on error since the function handles cleanup in
+ * cases of failure.
+ */
+ err = vchiq_register_chrdev(&pdev->dev);
+ if (err) {
+ vchiq_log_warning(vchiq_arm_log_level,
+ "Failed to initialize vchiq cdev");
+ goto error_exit;
+ }
bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera");
bcm2835_audio = vchiq_register_child(pdev, "bcm2835_audio");
return 0;
-failed_device_create:
- cdev_del(&vchiq_cdev);
failed_platform_init:
- vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq");
+ vchiq_log_warning(vchiq_arm_log_level, "could not initialize vchiq platform");
+error_exit:
return err;
}
@@ -2710,8 +1835,7 @@ static int vchiq_remove(struct platform_device *pdev)
platform_device_unregister(bcm2835_audio);
platform_device_unregister(bcm2835_camera);
vchiq_debugfs_deinit();
- device_destroy(vchiq_class, vchiq_devid);
- cdev_del(&vchiq_cdev);
+ vchiq_deregister_chrdev();
return 0;
}
@@ -2729,31 +1853,9 @@ static int __init vchiq_driver_init(void)
{
int ret;
- vchiq_class = class_create(THIS_MODULE, DEVICE_NAME);
- if (IS_ERR(vchiq_class)) {
- pr_err("Failed to create vchiq class\n");
- return PTR_ERR(vchiq_class);
- }
-
- ret = alloc_chrdev_region(&vchiq_devid, 0, 1, DEVICE_NAME);
- if (ret) {
- pr_err("Failed to allocate vchiq's chrdev region\n");
- goto class_destroy;
- }
-
ret = platform_driver_register(&vchiq_driver);
- if (ret) {
+ if (ret)
pr_err("Failed to register vchiq driver\n");
- goto region_unregister;
- }
-
- return 0;
-
-region_unregister:
- unregister_chrdev_region(vchiq_devid, 1);
-
-class_destroy:
- class_destroy(vchiq_class);
return ret;
}
@@ -2762,8 +1864,6 @@ module_init(vchiq_driver_init);
static void __exit vchiq_driver_exit(void)
{
platform_driver_unregister(&vchiq_driver);
- unregister_chrdev_region(vchiq_devid, 1);
- class_destroy(vchiq_class);
}
module_exit(vchiq_driver_exit);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
index c7d2cf1f2e68..e8e39a154c74 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
@@ -14,6 +14,12 @@
#include "vchiq_core.h"
#include "vchiq_debugfs.h"
+/* Some per-instance constants */
+#define MAX_COMPLETIONS 128
+#define MAX_SERVICES 64
+#define MAX_ELEMENTS 8
+#define MSG_QUEUE_SIZE 128
+
enum USE_TYPE_E {
USE_TYPE_SERVICE,
USE_TYPE_VCHIQ
@@ -58,9 +64,63 @@ struct vchiq_drvdata {
struct rpi_firmware *fw;
};
+struct user_service {
+ struct vchiq_service *service;
+ void __user *userdata;
+ struct vchiq_instance *instance;
+ char is_vchi;
+ char dequeue_pending;
+ char close_pending;
+ int message_available_pos;
+ int msg_insert;
+ int msg_remove;
+ struct completion insert_event;
+ struct completion remove_event;
+ struct completion close_event;
+ struct vchiq_header *msg_queue[MSG_QUEUE_SIZE];
+};
+
+struct bulk_waiter_node {
+ struct bulk_waiter bulk_waiter;
+ int pid;
+ struct list_head list;
+};
+
+struct vchiq_instance {
+ struct vchiq_state *state;
+ struct vchiq_completion_data_kernel completions[MAX_COMPLETIONS];
+ int completion_insert;
+ int completion_remove;
+ struct completion insert_event;
+ struct completion remove_event;
+ struct mutex completion_mutex;
+
+ int connected;
+ int closing;
+ int pid;
+ int mark;
+ int use_close_delivered;
+ int trace;
+
+ struct list_head bulk_waiter_list;
+ struct mutex bulk_waiter_list_mutex;
+
+ struct vchiq_debugfs_node debugfs_node;
+};
+
+struct dump_context {
+ char __user *buf;
+ size_t actual;
+ size_t space;
+ loff_t offset;
+};
+
extern int vchiq_arm_log_level;
extern int vchiq_susp_log_level;
+extern spinlock_t msg_queue_spinlock;
+extern struct vchiq_state g_state;
+
int vchiq_platform_init(struct platform_device *pdev,
struct vchiq_state *state);
@@ -114,4 +174,26 @@ vchiq_instance_get_trace(struct vchiq_instance *instance);
extern void
vchiq_instance_set_trace(struct vchiq_instance *instance, int trace);
+#if IS_ENABLED(CONFIG_VCHIQ_CDEV)
+
+extern void
+vchiq_deregister_chrdev(void);
+
+extern int
+vchiq_register_chrdev(struct device *parent);
+
+#else
+
+static inline void vchiq_deregister_chrdev(void) { }
+static inline int vchiq_register_chrdev(struct device *parent) { return 0; }
+
+#endif /* IS_ENABLED(CONFIG_VCHIQ_CDEV) */
+
+extern enum vchiq_status
+service_callback(enum vchiq_reason reason, struct vchiq_header *header,
+ unsigned int handle, void *bulk_userdata);
+
+extern void
+free_bulk_waiter(struct vchiq_instance *instance);
+
#endif /* VCHIQ_ARM_H */
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 4f43e4213bfe..9429b8a642fb 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -3716,7 +3716,7 @@ int vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
sizeof(remoteport) - len2,
" (client %x)", service->client_id);
} else {
- strcpy(remoteport, "n/a");
+ strscpy(remoteport, "n/a", sizeof(remoteport));
}
len += scnprintf(buf + len, sizeof(buf) - len,
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
new file mode 100644
index 000000000000..bf1a88c9d1ee
--- /dev/null
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
@@ -0,0 +1,1440 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved.
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ */
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/compat.h>
+
+#include "vchiq_core.h"
+#include "vchiq_ioctl.h"
+#include "vchiq_arm.h"
+#include "vchiq_debugfs.h"
+
+#define DEVICE_NAME "vchiq"
+
+static struct cdev vchiq_cdev;
+static dev_t vchiq_devid;
+static struct class *vchiq_class;
+
+static const char *const ioctl_names[] = {
+ "CONNECT",
+ "SHUTDOWN",
+ "CREATE_SERVICE",
+ "REMOVE_SERVICE",
+ "QUEUE_MESSAGE",
+ "QUEUE_BULK_TRANSMIT",
+ "QUEUE_BULK_RECEIVE",
+ "AWAIT_COMPLETION",
+ "DEQUEUE_MESSAGE",
+ "GET_CLIENT_ID",
+ "GET_CONFIG",
+ "CLOSE_SERVICE",
+ "USE_SERVICE",
+ "RELEASE_SERVICE",
+ "SET_SERVICE_OPTION",
+ "DUMP_PHYS_MEM",
+ "LIB_VERSION",
+ "CLOSE_DELIVERED"
+};
+
+static_assert(ARRAY_SIZE(ioctl_names) == (VCHIQ_IOC_MAX + 1));
+
+static void
+user_service_free(void *userdata)
+{
+ kfree(userdata);
+}
+
+static void close_delivered(struct user_service *user_service)
+{
+ vchiq_log_info(vchiq_arm_log_level,
+ "%s(handle=%x)",
+ __func__, user_service->service->handle);
+
+ if (user_service->close_pending) {
+ /* Allow the underlying service to be culled */
+ vchiq_service_put(user_service->service);
+
+ /* Wake the user-thread blocked in close_ or remove_service */
+ complete(&user_service->close_event);
+
+ user_service->close_pending = 0;
+ }
+}
+
+struct vchiq_io_copy_callback_context {
+ struct vchiq_element *element;
+ size_t element_offset;
+ unsigned long elements_to_go;
+};
+
+static ssize_t vchiq_ioc_copy_element_data(void *context, void *dest,
+ size_t offset, size_t maxsize)
+{
+ struct vchiq_io_copy_callback_context *cc = context;
+ size_t total_bytes_copied = 0;
+ size_t bytes_this_round;
+
+ while (total_bytes_copied < maxsize) {
+ if (!cc->elements_to_go)
+ return total_bytes_copied;
+
+ if (!cc->element->size) {
+ cc->elements_to_go--;
+ cc->element++;
+ cc->element_offset = 0;
+ continue;
+ }
+
+ bytes_this_round = min(cc->element->size - cc->element_offset,
+ maxsize - total_bytes_copied);
+
+ if (copy_from_user(dest + total_bytes_copied,
+ cc->element->data + cc->element_offset,
+ bytes_this_round))
+ return -EFAULT;
+
+ cc->element_offset += bytes_this_round;
+ total_bytes_copied += bytes_this_round;
+
+ if (cc->element_offset == cc->element->size) {
+ cc->elements_to_go--;
+ cc->element++;
+ cc->element_offset = 0;
+ }
+ }
+
+ return maxsize;
+}
+
+static int
+vchiq_ioc_queue_message(unsigned int handle, struct vchiq_element *elements,
+ unsigned long count)
+{
+ struct vchiq_io_copy_callback_context context;
+ enum vchiq_status status = VCHIQ_SUCCESS;
+ unsigned long i;
+ size_t total_size = 0;
+
+ context.element = elements;
+ context.element_offset = 0;
+ context.elements_to_go = count;
+
+ for (i = 0; i < count; i++) {
+ if (!elements[i].data && elements[i].size != 0)
+ return -EFAULT;
+
+ total_size += elements[i].size;
+ }
+
+ status = vchiq_queue_message(handle, vchiq_ioc_copy_element_data,
+ &context, total_size);
+
+ if (status == VCHIQ_ERROR)
+ return -EIO;
+ else if (status == VCHIQ_RETRY)
+ return -EINTR;
+ return 0;
+}
+
+static int vchiq_ioc_create_service(struct vchiq_instance *instance,
+ struct vchiq_create_service *args)
+{
+ struct user_service *user_service = NULL;
+ struct vchiq_service *service;
+ enum vchiq_status status = VCHIQ_SUCCESS;
+ struct vchiq_service_params_kernel params;
+ int srvstate;
+
+ user_service = kmalloc(sizeof(*user_service), GFP_KERNEL);
+ if (!user_service)
+ return -ENOMEM;
+
+ if (args->is_open) {
+ if (!instance->connected) {
+ kfree(user_service);
+ return -ENOTCONN;
+ }
+ srvstate = VCHIQ_SRVSTATE_OPENING;
+ } else {
+ srvstate = instance->connected ?
+ VCHIQ_SRVSTATE_LISTENING : VCHIQ_SRVSTATE_HIDDEN;
+ }
+
+ params = (struct vchiq_service_params_kernel) {
+ .fourcc = args->params.fourcc,
+ .callback = service_callback,
+ .userdata = user_service,
+ .version = args->params.version,
+ .version_min = args->params.version_min,
+ };
+ service = vchiq_add_service_internal(instance->state, &params,
+ srvstate, instance,
+ user_service_free);
+ if (!service) {
+ kfree(user_service);
+ return -EEXIST;
+ }
+
+ user_service->service = service;
+ user_service->userdata = args->params.userdata;
+ user_service->instance = instance;
+ user_service->is_vchi = (args->is_vchi != 0);
+ user_service->dequeue_pending = 0;
+ user_service->close_pending = 0;
+ user_service->message_available_pos = instance->completion_remove - 1;
+ user_service->msg_insert = 0;
+ user_service->msg_remove = 0;
+ init_completion(&user_service->insert_event);
+ init_completion(&user_service->remove_event);
+ init_completion(&user_service->close_event);
+
+ if (args->is_open) {
+ status = vchiq_open_service_internal(service, instance->pid);
+ if (status != VCHIQ_SUCCESS) {
+ vchiq_remove_service(service->handle);
+ return (status == VCHIQ_RETRY) ?
+ -EINTR : -EIO;
+ }
+ }
+ args->handle = service->handle;
+
+ return 0;
+}
+
+static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
+ struct vchiq_dequeue_message *args)
+{
+ struct user_service *user_service;
+ struct vchiq_service *service;
+ struct vchiq_header *header;
+ int ret;
+
+ DEBUG_INITIALISE(g_state.local)
+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
+ service = find_service_for_instance(instance, args->handle);
+ if (!service)
+ return -EINVAL;
+
+ user_service = (struct user_service *)service->base.userdata;
+ if (user_service->is_vchi == 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ spin_lock(&msg_queue_spinlock);
+ if (user_service->msg_remove == user_service->msg_insert) {
+ if (!args->blocking) {
+ spin_unlock(&msg_queue_spinlock);
+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
+ ret = -EWOULDBLOCK;
+ goto out;
+ }
+ user_service->dequeue_pending = 1;
+ ret = 0;
+ do {
+ spin_unlock(&msg_queue_spinlock);
+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
+ if (wait_for_completion_interruptible(
+ &user_service->insert_event)) {
+ vchiq_log_info(vchiq_arm_log_level,
+ "DEQUEUE_MESSAGE interrupted");
+ ret = -EINTR;
+ break;
+ }
+ spin_lock(&msg_queue_spinlock);
+ } while (user_service->msg_remove == user_service->msg_insert);
+
+ if (ret)
+ goto out;
+ }
+
+ if (WARN_ON_ONCE((int)(user_service->msg_insert -
+ user_service->msg_remove) < 0)) {
+ spin_unlock(&msg_queue_spinlock);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ header = user_service->msg_queue[user_service->msg_remove &
+ (MSG_QUEUE_SIZE - 1)];
+ user_service->msg_remove++;
+ spin_unlock(&msg_queue_spinlock);
+
+ complete(&user_service->remove_event);
+ if (!header) {
+ ret = -ENOTCONN;
+ } else if (header->size <= args->bufsize) {
+ /* Copy to user space if msgbuf is not NULL */
+ if (!args->buf || (copy_to_user(args->buf,
+ header->data, header->size) == 0)) {
+ ret = header->size;
+ vchiq_release_message(service->handle, header);
+ } else {
+ ret = -EFAULT;
+ }
+ } else {
+ vchiq_log_error(vchiq_arm_log_level,
+ "header %pK: bufsize %x < size %x",
+ header, args->bufsize, header->size);
+ WARN(1, "invalid size\n");
+ ret = -EMSGSIZE;
+ }
+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
+out:
+ vchiq_service_put(service);
+ return ret;
+}
+
+static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
+ struct vchiq_queue_bulk_transfer *args,
+ enum vchiq_bulk_dir dir,
+ enum vchiq_bulk_mode __user *mode)
+{
+ struct vchiq_service *service;
+ struct bulk_waiter_node *waiter = NULL;
+ bool found = false;
+ void *userdata;
+ int status = 0;
+ int ret;
+
+ service = find_service_for_instance(instance, args->handle);
+ if (!service)
+ return -EINVAL;
+
+ if (args->mode == VCHIQ_BULK_MODE_BLOCKING) {
+ waiter = kzalloc(sizeof(*waiter), GFP_KERNEL);
+ if (!waiter) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ userdata = &waiter->bulk_waiter;
+ } else if (args->mode == VCHIQ_BULK_MODE_WAITING) {
+ mutex_lock(&instance->bulk_waiter_list_mutex);
+ list_for_each_entry(waiter, &instance->bulk_waiter_list,
+ list) {
+ if (waiter->pid == current->pid) {
+ list_del(&waiter->list);
+ found = true;
+ break;
+ }
+ }
+ mutex_unlock(&instance->bulk_waiter_list_mutex);
+ if (!found) {
+ vchiq_log_error(vchiq_arm_log_level,
+ "no bulk_waiter found for pid %d",
+ current->pid);
+ ret = -ESRCH;
+ goto out;
+ }
+ vchiq_log_info(vchiq_arm_log_level,
+ "found bulk_waiter %pK for pid %d", waiter,
+ current->pid);
+ userdata = &waiter->bulk_waiter;
+ } else {
+ userdata = args->userdata;
+ }
+
+ status = vchiq_bulk_transfer(args->handle, NULL, args->data, args->size,
+ userdata, args->mode, dir);
+
+ if (!waiter) {
+ ret = 0;
+ goto out;
+ }
+
+ if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) ||
+ !waiter->bulk_waiter.bulk) {
+ if (waiter->bulk_waiter.bulk) {
+ /* Cancel the signal when the transfer completes. */
+ spin_lock(&bulk_waiter_spinlock);
+ waiter->bulk_waiter.bulk->userdata = NULL;
+ spin_unlock(&bulk_waiter_spinlock);
+ }
+ kfree(waiter);
+ ret = 0;
+ } else {
+ const enum vchiq_bulk_mode mode_waiting =
+ VCHIQ_BULK_MODE_WAITING;
+ waiter->pid = current->pid;
+ mutex_lock(&instance->bulk_waiter_list_mutex);
+ list_add(&waiter->list, &instance->bulk_waiter_list);
+ mutex_unlock(&instance->bulk_waiter_list_mutex);
+ vchiq_log_info(vchiq_arm_log_level,
+ "saved bulk_waiter %pK for pid %d",
+ waiter, current->pid);
+
+ ret = put_user(mode_waiting, mode);
+ }
+out:
+ vchiq_service_put(service);
+ if (ret)
+ return ret;
+ else if (status == VCHIQ_ERROR)
+ return -EIO;
+ else if (status == VCHIQ_RETRY)
+ return -EINTR;
+ return 0;
+}
+
+/* read a user pointer value from an array pointers in user space */
+static inline int vchiq_get_user_ptr(void __user **buf, void __user *ubuf, int index)
+{
+ int ret;
+
+ if (in_compat_syscall()) {
+ compat_uptr_t ptr32;
+ compat_uptr_t __user *uptr = ubuf;
+
+ ret = get_user(ptr32, uptr + index);
+ if (ret)
+ return ret;
+
+ *buf = compat_ptr(ptr32);
+ } else {
+ uintptr_t ptr, __user *uptr = ubuf;
+
+ ret = get_user(ptr, uptr + index);
+
+ if (ret)
+ return ret;
+
+ *buf = (void __user *)ptr;
+ }
+
+ return 0;
+}
+
+struct vchiq_completion_data32 {
+ enum vchiq_reason reason;
+ compat_uptr_t header;
+ compat_uptr_t service_userdata;
+ compat_uptr_t bulk_userdata;
+};
+
+static int vchiq_put_completion(struct vchiq_completion_data __user *buf,
+ struct vchiq_completion_data *completion,
+ int index)
+{
+ struct vchiq_completion_data32 __user *buf32 = (void __user *)buf;
+
+ if (in_compat_syscall()) {
+ struct vchiq_completion_data32 tmp = {
+ .reason = completion->reason,
+ .header = ptr_to_compat(completion->header),
+ .service_userdata = ptr_to_compat(completion->service_userdata),
+ .bulk_userdata = ptr_to_compat(completion->bulk_userdata),
+ };
+ if (copy_to_user(&buf32[index], &tmp, sizeof(tmp)))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(&buf[index], completion, sizeof(*completion)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int vchiq_ioc_await_completion(struct vchiq_instance *instance,
+ struct vchiq_await_completion *args,
+ int __user *msgbufcountp)
+{
+ int msgbufcount;
+ int remove;
+ int ret;
+
+ DEBUG_INITIALISE(g_state.local)
+
+ DEBUG_TRACE(AWAIT_COMPLETION_LINE);
+ if (!instance->connected) {
+ return -ENOTCONN;
+ }
+
+ mutex_lock(&instance->completion_mutex);
+
+ DEBUG_TRACE(AWAIT_COMPLETION_LINE);
+ while ((instance->completion_remove == instance->completion_insert)
+ && !instance->closing) {
+ int rc;
+
+ DEBUG_TRACE(AWAIT_COMPLETION_LINE);
+ mutex_unlock(&instance->completion_mutex);
+ rc = wait_for_completion_interruptible(
+ &instance->insert_event);
+ mutex_lock(&instance->completion_mutex);
+ if (rc) {
+ DEBUG_TRACE(AWAIT_COMPLETION_LINE);
+ vchiq_log_info(vchiq_arm_log_level,
+ "AWAIT_COMPLETION interrupted");
+ ret = -EINTR;
+ goto out;
+ }
+ }
+ DEBUG_TRACE(AWAIT_COMPLETION_LINE);
+
+ msgbufcount = args->msgbufcount;
+ remove = instance->completion_remove;
+
+ for (ret = 0; ret < args->count; ret++) {
+ struct vchiq_completion_data_kernel *completion;
+ struct vchiq_completion_data user_completion;
+ struct vchiq_service *service;
+ struct user_service *user_service;
+ struct vchiq_header *header;
+
+ if (remove == instance->completion_insert)
+ break;
+
+ completion = &instance->completions[
+ remove & (MAX_COMPLETIONS - 1)];
+
+ /*
+ * A read memory barrier is needed to stop
+ * prefetch of a stale completion record
+ */
+ rmb();
+
+ service = completion->service_userdata;
+ user_service = service->base.userdata;
+
+ memset(&user_completion, 0, sizeof(user_completion));
+ user_completion = (struct vchiq_completion_data) {
+ .reason = completion->reason,
+ .service_userdata = user_service->userdata,
+ };
+
+ header = completion->header;
+ if (header) {
+ void __user *msgbuf;
+ int msglen;
+
+ msglen = header->size + sizeof(struct vchiq_header);
+ /* This must be a VCHIQ-style service */
+ if (args->msgbufsize < msglen) {
+ vchiq_log_error(vchiq_arm_log_level,
+ "header %pK: msgbufsize %x < msglen %x",
+ header, args->msgbufsize, msglen);
+ WARN(1, "invalid message size\n");
+ if (ret == 0)
+ ret = -EMSGSIZE;
+ break;
+ }
+ if (msgbufcount <= 0)
+ /* Stall here for lack of a buffer for the message. */
+ break;
+ /* Get the pointer from user space */
+ msgbufcount--;
+ if (vchiq_get_user_ptr(&msgbuf, args->msgbufs,
+ msgbufcount)) {
+ if (ret == 0)
+ ret = -EFAULT;
+ break;
+ }
+
+ /* Copy the message to user space */
+ if (copy_to_user(msgbuf, header, msglen)) {
+ if (ret == 0)
+ ret = -EFAULT;
+ break;
+ }
+
+ /* Now it has been copied, the message can be released. */
+ vchiq_release_message(service->handle, header);
+
+ /* The completion must point to the msgbuf. */
+ user_completion.header = msgbuf;
+ }
+
+ if ((completion->reason == VCHIQ_SERVICE_CLOSED) &&
+ !instance->use_close_delivered)
+ vchiq_service_put(service);
+
+ /*
+ * FIXME: address space mismatch, does bulk_userdata
+ * actually point to user or kernel memory?
+ */
+ user_completion.bulk_userdata = completion->bulk_userdata;
+
+ if (vchiq_put_completion(args->buf, &user_completion, ret)) {
+ if (ret == 0)
+ ret = -EFAULT;
+ break;
+ }
+
+ /*
+ * Ensure that the above copy has completed
+ * before advancing the remove pointer.
+ */
+ mb();
+ remove++;
+ instance->completion_remove = remove;
+ }
+
+ if (msgbufcount != args->msgbufcount) {
+ if (put_user(msgbufcount, msgbufcountp))
+ ret = -EFAULT;
+ }
+out:
+ if (ret)
+ complete(&instance->remove_event);
+ mutex_unlock(&instance->completion_mutex);
+ DEBUG_TRACE(AWAIT_COMPLETION_LINE);
+
+ return ret;
+}
+
+static long
+vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct vchiq_instance *instance = file->private_data;
+ enum vchiq_status status = VCHIQ_SUCCESS;
+ struct vchiq_service *service = NULL;
+ long ret = 0;
+ int i, rc;
+
+ vchiq_log_trace(vchiq_arm_log_level,
+ "%s - instance %pK, cmd %s, arg %lx",
+ __func__, instance,
+ ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) &&
+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ?
+ ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg);
+
+ switch (cmd) {
+ case VCHIQ_IOC_SHUTDOWN:
+ if (!instance->connected)
+ break;
+
+ /* Remove all services */
+ i = 0;
+ while ((service = next_service_by_instance(instance->state,
+ instance, &i))) {
+ status = vchiq_remove_service(service->handle);
+ vchiq_service_put(service);
+ if (status != VCHIQ_SUCCESS)
+ break;
+ }
+ service = NULL;
+
+ if (status == VCHIQ_SUCCESS) {
+ /* Wake the completion thread and ask it to exit */
+ instance->closing = 1;
+ complete(&instance->insert_event);
+ }
+
+ break;
+
+ case VCHIQ_IOC_CONNECT:
+ if (instance->connected) {
+ ret = -EINVAL;
+ break;
+ }
+ rc = mutex_lock_killable(&instance->state->mutex);
+ if (rc) {
+ vchiq_log_error(vchiq_arm_log_level,
+ "vchiq: connect: could not lock mutex for state %d: %d",
+ instance->state->id, rc);
+ ret = -EINTR;
+ break;
+ }
+ status = vchiq_connect_internal(instance->state, instance);
+ mutex_unlock(&instance->state->mutex);
+
+ if (status == VCHIQ_SUCCESS)
+ instance->connected = 1;
+ else
+ vchiq_log_error(vchiq_arm_log_level,
+ "vchiq: could not connect: %d", status);
+ break;
+
+ case VCHIQ_IOC_CREATE_SERVICE: {
+ struct vchiq_create_service __user *argp;
+ struct vchiq_create_service args;
+
+ argp = (void __user *)arg;
+ if (copy_from_user(&args, argp, sizeof(args))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ ret = vchiq_ioc_create_service(instance, &args);
+ if (ret < 0)
+ break;
+
+ if (put_user(args.handle, &argp->handle)) {
+ vchiq_remove_service(args.handle);
+ ret = -EFAULT;
+ }
+ } break;
+
+ case VCHIQ_IOC_CLOSE_SERVICE:
+ case VCHIQ_IOC_REMOVE_SERVICE: {
+ unsigned int handle = (unsigned int)arg;
+ struct user_service *user_service;
+
+ service = find_service_for_instance(instance, handle);
+ if (!service) {
+ ret = -EINVAL;
+ break;
+ }
+
+ user_service = service->base.userdata;
+
+ /*
+ * close_pending is false on first entry, and when the
+ * wait in vchiq_close_service has been interrupted.
+ */
+ if (!user_service->close_pending) {
+ status = (cmd == VCHIQ_IOC_CLOSE_SERVICE) ?
+ vchiq_close_service(service->handle) :
+ vchiq_remove_service(service->handle);
+ if (status != VCHIQ_SUCCESS)
+ break;
+ }
+
+ /*
+ * close_pending is true once the underlying service
+ * has been closed until the client library calls the
+ * CLOSE_DELIVERED ioctl, signalling close_event.
+ */
+ if (user_service->close_pending &&
+ wait_for_completion_interruptible(
+ &user_service->close_event))
+ status = VCHIQ_RETRY;
+ break;
+ }
+
+ case VCHIQ_IOC_USE_SERVICE:
+ case VCHIQ_IOC_RELEASE_SERVICE: {
+ unsigned int handle = (unsigned int)arg;
+
+ service = find_service_for_instance(instance, handle);
+ if (service) {
+ ret = (cmd == VCHIQ_IOC_USE_SERVICE) ?
+ vchiq_use_service_internal(service) :
+ vchiq_release_service_internal(service);
+ if (ret) {
+ vchiq_log_error(vchiq_susp_log_level,
+ "%s: cmd %s returned error %ld for service %c%c%c%c:%03d",
+ __func__,
+ (cmd == VCHIQ_IOC_USE_SERVICE) ?
+ "VCHIQ_IOC_USE_SERVICE" :
+ "VCHIQ_IOC_RELEASE_SERVICE",
+ ret,
+ VCHIQ_FOURCC_AS_4CHARS(
+ service->base.fourcc),
+ service->client_id);
+ }
+ } else {
+ ret = -EINVAL;
+ }
+ } break;
+
+ case VCHIQ_IOC_QUEUE_MESSAGE: {
+ struct vchiq_queue_message args;
+
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ service = find_service_for_instance(instance, args.handle);
+
+ if (service && (args.count <= MAX_ELEMENTS)) {
+ /* Copy elements into kernel space */
+ struct vchiq_element elements[MAX_ELEMENTS];
+
+ if (copy_from_user(elements, args.elements,
+ args.count * sizeof(struct vchiq_element)) == 0)
+ ret = vchiq_ioc_queue_message(args.handle, elements,
+ args.count);
+ else
+ ret = -EFAULT;
+ } else {
+ ret = -EINVAL;
+ }
+ } break;
+
+ case VCHIQ_IOC_QUEUE_BULK_TRANSMIT:
+ case VCHIQ_IOC_QUEUE_BULK_RECEIVE: {
+ struct vchiq_queue_bulk_transfer args;
+ struct vchiq_queue_bulk_transfer __user *argp;
+
+ enum vchiq_bulk_dir dir =
+ (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
+ VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
+
+ argp = (void __user *)arg;
+ if (copy_from_user(&args, argp, sizeof(args))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ ret = vchiq_irq_queue_bulk_tx_rx(instance, &args,
+ dir, &argp->mode);
+ } break;
+
+ case VCHIQ_IOC_AWAIT_COMPLETION: {
+ struct vchiq_await_completion args;
+ struct vchiq_await_completion __user *argp;
+
+ argp = (void __user *)arg;
+ if (copy_from_user(&args, argp, sizeof(args))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ ret = vchiq_ioc_await_completion(instance, &args,
+ &argp->msgbufcount);
+ } break;
+
+ case VCHIQ_IOC_DEQUEUE_MESSAGE: {
+ struct vchiq_dequeue_message args;
+
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ ret = vchiq_ioc_dequeue_message(instance, &args);
+ } break;
+
+ case VCHIQ_IOC_GET_CLIENT_ID: {
+ unsigned int handle = (unsigned int)arg;
+
+ ret = vchiq_get_client_id(handle);
+ } break;
+
+ case VCHIQ_IOC_GET_CONFIG: {
+ struct vchiq_get_config args;
+ struct vchiq_config config;
+
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
+ ret = -EFAULT;
+ break;
+ }
+ if (args.config_size > sizeof(config)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ vchiq_get_config(&config);
+ if (copy_to_user(args.pconfig, &config, args.config_size)) {
+ ret = -EFAULT;
+ break;
+ }
+ } break;
+
+ case VCHIQ_IOC_SET_SERVICE_OPTION: {
+ struct vchiq_set_service_option args;
+
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ service = find_service_for_instance(instance, args.handle);
+ if (!service) {
+ ret = -EINVAL;
+ break;
+ }
+
+ ret = vchiq_set_service_option(args.handle, args.option,
+ args.value);
+ } break;
+
+ case VCHIQ_IOC_LIB_VERSION: {
+ unsigned int lib_version = (unsigned int)arg;
+
+ if (lib_version < VCHIQ_VERSION_MIN)
+ ret = -EINVAL;
+ else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED)
+ instance->use_close_delivered = 1;
+ } break;
+
+ case VCHIQ_IOC_CLOSE_DELIVERED: {
+ unsigned int handle = (unsigned int)arg;
+
+ service = find_closed_service_for_instance(instance, handle);
+ if (service) {
+ struct user_service *user_service =
+ (struct user_service *)service->base.userdata;
+ close_delivered(user_service);
+ } else {
+ ret = -EINVAL;
+ }
+ } break;
+
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ if (service)
+ vchiq_service_put(service);
+
+ if (ret == 0) {
+ if (status == VCHIQ_ERROR)
+ ret = -EIO;
+ else if (status == VCHIQ_RETRY)
+ ret = -EINTR;
+ }
+
+ if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) &&
+ (ret != -EWOULDBLOCK))
+ vchiq_log_info(vchiq_arm_log_level,
+ " ioctl instance %pK, cmd %s -> status %d, %ld",
+ instance,
+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
+ ioctl_names[_IOC_NR(cmd)] :
+ "<invalid>",
+ status, ret);
+ else
+ vchiq_log_trace(vchiq_arm_log_level,
+ " ioctl instance %pK, cmd %s -> status %d, %ld",
+ instance,
+ (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?
+ ioctl_names[_IOC_NR(cmd)] :
+ "<invalid>",
+ status, ret);
+
+ return ret;
+}
+
+#if defined(CONFIG_COMPAT)
+
+struct vchiq_service_params32 {
+ int fourcc;
+ compat_uptr_t callback;
+ compat_uptr_t userdata;
+ short version; /* Increment for non-trivial changes */
+ short version_min; /* Update for incompatible changes */
+};
+
+struct vchiq_create_service32 {
+ struct vchiq_service_params32 params;
+ int is_open;
+ int is_vchi;
+ unsigned int handle; /* OUT */
+};
+
+#define VCHIQ_IOC_CREATE_SERVICE32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 2, struct vchiq_create_service32)
+
+static long
+vchiq_compat_ioctl_create_service(struct file *file, unsigned int cmd,
+ struct vchiq_create_service32 __user *ptrargs32)
+{
+ struct vchiq_create_service args;
+ struct vchiq_create_service32 args32;
+ long ret;
+
+ if (copy_from_user(&args32, ptrargs32, sizeof(args32)))
+ return -EFAULT;
+
+ args = (struct vchiq_create_service) {
+ .params = {
+ .fourcc = args32.params.fourcc,
+ .callback = compat_ptr(args32.params.callback),
+ .userdata = compat_ptr(args32.params.userdata),
+ .version = args32.params.version,
+ .version_min = args32.params.version_min,
+ },
+ .is_open = args32.is_open,
+ .is_vchi = args32.is_vchi,
+ .handle = args32.handle,
+ };
+
+ ret = vchiq_ioc_create_service(file->private_data, &args);
+ if (ret < 0)
+ return ret;
+
+ if (put_user(args.handle, &ptrargs32->handle)) {
+ vchiq_remove_service(args.handle);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+struct vchiq_element32 {
+ compat_uptr_t data;
+ unsigned int size;
+};
+
+struct vchiq_queue_message32 {
+ unsigned int handle;
+ unsigned int count;
+ compat_uptr_t elements;
+};
+
+#define VCHIQ_IOC_QUEUE_MESSAGE32 \
+ _IOW(VCHIQ_IOC_MAGIC, 4, struct vchiq_queue_message32)
+
+static long
+vchiq_compat_ioctl_queue_message(struct file *file,
+ unsigned int cmd,
+ struct vchiq_queue_message32 __user *arg)
+{
+ struct vchiq_queue_message args;
+ struct vchiq_queue_message32 args32;
+ struct vchiq_service *service;
+ int ret;
+
+ if (copy_from_user(&args32, arg, sizeof(args32)))
+ return -EFAULT;
+
+ args = (struct vchiq_queue_message) {
+ .handle = args32.handle,
+ .count = args32.count,
+ .elements = compat_ptr(args32.elements),
+ };
+
+ if (args32.count > MAX_ELEMENTS)
+ return -EINVAL;
+
+ service = find_service_for_instance(file->private_data, args.handle);
+ if (!service)
+ return -EINVAL;
+
+ if (args32.elements && args32.count) {
+ struct vchiq_element32 element32[MAX_ELEMENTS];
+ struct vchiq_element elements[MAX_ELEMENTS];
+ unsigned int count;
+
+ if (copy_from_user(&element32, args.elements,
+ sizeof(element32))) {
+ vchiq_service_put(service);
+ return -EFAULT;
+ }
+
+ for (count = 0; count < args32.count; count++) {
+ elements[count].data =
+ compat_ptr(element32[count].data);
+ elements[count].size = element32[count].size;
+ }
+ ret = vchiq_ioc_queue_message(args.handle, elements,
+ args.count);
+ } else {
+ ret = -EINVAL;
+ }
+ vchiq_service_put(service);
+
+ return ret;
+}
+
+struct vchiq_queue_bulk_transfer32 {
+ unsigned int handle;
+ compat_uptr_t data;
+ unsigned int size;
+ compat_uptr_t userdata;
+ enum vchiq_bulk_mode mode;
+};
+
+#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 5, struct vchiq_queue_bulk_transfer32)
+#define VCHIQ_IOC_QUEUE_BULK_RECEIVE32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 6, struct vchiq_queue_bulk_transfer32)
+
+static long
+vchiq_compat_ioctl_queue_bulk(struct file *file,
+ unsigned int cmd,
+ struct vchiq_queue_bulk_transfer32 __user *argp)
+{
+ struct vchiq_queue_bulk_transfer32 args32;
+ struct vchiq_queue_bulk_transfer args;
+ enum vchiq_bulk_dir dir = (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32) ?
+ VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
+
+ if (copy_from_user(&args32, argp, sizeof(args32)))
+ return -EFAULT;
+
+ args = (struct vchiq_queue_bulk_transfer) {
+ .handle = args32.handle,
+ .data = compat_ptr(args32.data),
+ .size = args32.size,
+ .userdata = compat_ptr(args32.userdata),
+ .mode = args32.mode,
+ };
+
+ return vchiq_irq_queue_bulk_tx_rx(file->private_data, &args,
+ dir, &argp->mode);
+}
+
+struct vchiq_await_completion32 {
+ unsigned int count;
+ compat_uptr_t buf;
+ unsigned int msgbufsize;
+ unsigned int msgbufcount; /* IN/OUT */
+ compat_uptr_t msgbufs;
+};
+
+#define VCHIQ_IOC_AWAIT_COMPLETION32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 7, struct vchiq_await_completion32)
+
+static long
+vchiq_compat_ioctl_await_completion(struct file *file,
+ unsigned int cmd,
+ struct vchiq_await_completion32 __user *argp)
+{
+ struct vchiq_await_completion args;
+ struct vchiq_await_completion32 args32;
+
+ if (copy_from_user(&args32, argp, sizeof(args32)))
+ return -EFAULT;
+
+ args = (struct vchiq_await_completion) {
+ .count = args32.count,
+ .buf = compat_ptr(args32.buf),
+ .msgbufsize = args32.msgbufsize,
+ .msgbufcount = args32.msgbufcount,
+ .msgbufs = compat_ptr(args32.msgbufs),
+ };
+
+ return vchiq_ioc_await_completion(file->private_data, &args,
+ &argp->msgbufcount);
+}
+
+struct vchiq_dequeue_message32 {
+ unsigned int handle;
+ int blocking;
+ unsigned int bufsize;
+ compat_uptr_t buf;
+};
+
+#define VCHIQ_IOC_DEQUEUE_MESSAGE32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 8, struct vchiq_dequeue_message32)
+
+static long
+vchiq_compat_ioctl_dequeue_message(struct file *file,
+ unsigned int cmd,
+ struct vchiq_dequeue_message32 __user *arg)
+{
+ struct vchiq_dequeue_message32 args32;
+ struct vchiq_dequeue_message args;
+
+ if (copy_from_user(&args32, arg, sizeof(args32)))
+ return -EFAULT;
+
+ args = (struct vchiq_dequeue_message) {
+ .handle = args32.handle,
+ .blocking = args32.blocking,
+ .bufsize = args32.bufsize,
+ .buf = compat_ptr(args32.buf),
+ };
+
+ return vchiq_ioc_dequeue_message(file->private_data, &args);
+}
+
+struct vchiq_get_config32 {
+ unsigned int config_size;
+ compat_uptr_t pconfig;
+};
+
+#define VCHIQ_IOC_GET_CONFIG32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 10, struct vchiq_get_config32)
+
+static long
+vchiq_compat_ioctl_get_config(struct file *file,
+ unsigned int cmd,
+ struct vchiq_get_config32 __user *arg)
+{
+ struct vchiq_get_config32 args32;
+ struct vchiq_config config;
+ void __user *ptr;
+
+ if (copy_from_user(&args32, arg, sizeof(args32)))
+ return -EFAULT;
+ if (args32.config_size > sizeof(config))
+ return -EINVAL;
+
+ vchiq_get_config(&config);
+ ptr = compat_ptr(args32.pconfig);
+ if (copy_to_user(ptr, &config, args32.config_size))
+ return -EFAULT;
+
+ return 0;
+}
+
+static long
+vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = compat_ptr(arg);
+
+ switch (cmd) {
+ case VCHIQ_IOC_CREATE_SERVICE32:
+ return vchiq_compat_ioctl_create_service(file, cmd, argp);
+ case VCHIQ_IOC_QUEUE_MESSAGE32:
+ return vchiq_compat_ioctl_queue_message(file, cmd, argp);
+ case VCHIQ_IOC_QUEUE_BULK_TRANSMIT32:
+ case VCHIQ_IOC_QUEUE_BULK_RECEIVE32:
+ return vchiq_compat_ioctl_queue_bulk(file, cmd, argp);
+ case VCHIQ_IOC_AWAIT_COMPLETION32:
+ return vchiq_compat_ioctl_await_completion(file, cmd, argp);
+ case VCHIQ_IOC_DEQUEUE_MESSAGE32:
+ return vchiq_compat_ioctl_dequeue_message(file, cmd, argp);
+ case VCHIQ_IOC_GET_CONFIG32:
+ return vchiq_compat_ioctl_get_config(file, cmd, argp);
+ default:
+ return vchiq_ioctl(file, cmd, (unsigned long)argp);
+ }
+}
+
+#endif
+
+static int vchiq_open(struct inode *inode, struct file *file)
+{
+ struct vchiq_state *state = vchiq_get_state();
+ struct vchiq_instance *instance;
+
+ vchiq_log_info(vchiq_arm_log_level, "vchiq_open");
+
+ if (!state) {
+ vchiq_log_error(vchiq_arm_log_level,
+ "vchiq has no connection to VideoCore");
+ return -ENOTCONN;
+ }
+
+ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+ if (!instance)
+ return -ENOMEM;
+
+ instance->state = state;
+ instance->pid = current->tgid;
+
+ vchiq_debugfs_add_instance(instance);
+
+ init_completion(&instance->insert_event);
+ init_completion(&instance->remove_event);
+ mutex_init(&instance->completion_mutex);
+ mutex_init(&instance->bulk_waiter_list_mutex);
+ INIT_LIST_HEAD(&instance->bulk_waiter_list);
+
+ file->private_data = instance;
+
+ return 0;
+}
+
+static int vchiq_release(struct inode *inode, struct file *file)
+{
+ struct vchiq_instance *instance = file->private_data;
+ struct vchiq_state *state = vchiq_get_state();
+ struct vchiq_service *service;
+ int ret = 0;
+ int i;
+
+ vchiq_log_info(vchiq_arm_log_level, "%s: instance=%lx", __func__,
+ (unsigned long)instance);
+
+ if (!state) {
+ ret = -EPERM;
+ goto out;
+ }
+
+ /* Ensure videocore is awake to allow termination. */
+ vchiq_use_internal(instance->state, NULL, USE_TYPE_VCHIQ);
+
+ mutex_lock(&instance->completion_mutex);
+
+ /* Wake the completion thread and ask it to exit */
+ instance->closing = 1;
+ complete(&instance->insert_event);
+
+ mutex_unlock(&instance->completion_mutex);
+
+ /* Wake the slot handler if the completion queue is full. */
+ complete(&instance->remove_event);
+
+ /* Mark all services for termination... */
+ i = 0;
+ while ((service = next_service_by_instance(state, instance, &i))) {
+ struct user_service *user_service = service->base.userdata;
+
+ /* Wake the slot handler if the msg queue is full. */
+ complete(&user_service->remove_event);
+
+ vchiq_terminate_service_internal(service);
+ vchiq_service_put(service);
+ }
+
+ /* ...and wait for them to die */
+ i = 0;
+ while ((service = next_service_by_instance(state, instance, &i))) {
+ struct user_service *user_service = service->base.userdata;
+
+ wait_for_completion(&service->remove_event);
+
+ if (WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE)) {
+ vchiq_service_put(service);
+ break;
+ }
+
+ spin_lock(&msg_queue_spinlock);
+
+ while (user_service->msg_remove != user_service->msg_insert) {
+ struct vchiq_header *header;
+ int m = user_service->msg_remove & (MSG_QUEUE_SIZE - 1);
+
+ header = user_service->msg_queue[m];
+ user_service->msg_remove++;
+ spin_unlock(&msg_queue_spinlock);
+
+ if (header)
+ vchiq_release_message(service->handle, header);
+ spin_lock(&msg_queue_spinlock);
+ }
+
+ spin_unlock(&msg_queue_spinlock);
+
+ vchiq_service_put(service);
+ }
+
+ /* Release any closed services */
+ while (instance->completion_remove != instance->completion_insert) {
+ struct vchiq_completion_data_kernel *completion;
+ struct vchiq_service *service;
+
+ completion = &instance->completions[
+ instance->completion_remove & (MAX_COMPLETIONS - 1)];
+ service = completion->service_userdata;
+ if (completion->reason == VCHIQ_SERVICE_CLOSED) {
+ struct user_service *user_service =
+ service->base.userdata;
+
+ /* Wake any blocked user-thread */
+ if (instance->use_close_delivered)
+ complete(&user_service->close_event);
+ vchiq_service_put(service);
+ }
+ instance->completion_remove++;
+ }
+
+ /* Release the PEER service count. */
+ vchiq_release_internal(instance->state, NULL);
+
+ free_bulk_waiter(instance);
+
+ vchiq_debugfs_remove_instance(instance);
+
+ kfree(instance);
+ file->private_data = NULL;
+
+out:
+ return ret;
+}
+
+static ssize_t
+vchiq_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ struct dump_context context;
+ int err;
+
+ context.buf = buf;
+ context.actual = 0;
+ context.space = count;
+ context.offset = *ppos;
+
+ err = vchiq_dump_state(&context, &g_state);
+ if (err)
+ return err;
+
+ *ppos += context.actual;
+
+ return context.actual;
+}
+
+static const struct file_operations
+vchiq_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = vchiq_ioctl,
+#if defined(CONFIG_COMPAT)
+ .compat_ioctl = vchiq_compat_ioctl,
+#endif
+ .open = vchiq_open,
+ .release = vchiq_release,
+ .read = vchiq_read
+};
+
+/**
+ * vchiq_register_chrdev - Register the char driver for vchiq
+ * and create the necessary class and
+ * device files in userspace.
+ * @parent The parent of the char device.
+ *
+ * Returns 0 on success else returns the error code.
+ */
+int vchiq_register_chrdev(struct device *parent)
+{
+ struct device *vchiq_dev;
+ int ret;
+
+ vchiq_class = class_create(THIS_MODULE, DEVICE_NAME);
+ if (IS_ERR(vchiq_class)) {
+ pr_err("Failed to create vchiq class\n");
+ ret = PTR_ERR(vchiq_class);
+ goto error_exit;
+ }
+
+ ret = alloc_chrdev_region(&vchiq_devid, 0, 1, DEVICE_NAME);
+ if (ret) {
+ pr_err("vchiq: Failed to allocate vchiq's chrdev region\n");
+ goto alloc_region_error;
+ }
+
+ cdev_init(&vchiq_cdev, &vchiq_fops);
+ vchiq_cdev.owner = THIS_MODULE;
+ ret = cdev_add(&vchiq_cdev, vchiq_devid, 1);
+ if (ret) {
+ vchiq_log_error(vchiq_arm_log_level,
+ "Unable to register vchiq char device");
+ goto cdev_add_error;
+ }
+
+ vchiq_dev = device_create(vchiq_class, parent, vchiq_devid, NULL,
+ DEVICE_NAME);
+ if (IS_ERR(vchiq_dev)) {
+ vchiq_log_error(vchiq_arm_log_level,
+ "Failed to create vchiq char device node");
+ ret = PTR_ERR(vchiq_dev);
+ goto device_create_error;
+ }
+
+ vchiq_log_info(vchiq_arm_log_level,
+ "vchiq char dev initialised successfully - device %d.%d",
+ MAJOR(vchiq_devid), MINOR(vchiq_devid));
+
+ return 0;
+
+device_create_error:
+ cdev_del(&vchiq_cdev);
+
+cdev_add_error:
+ unregister_chrdev_region(vchiq_devid, 1);
+
+alloc_region_error:
+ class_destroy(vchiq_class);
+
+error_exit:
+ return ret;
+}
+
+/**
+ * vchiq_deregister_chrdev - Deregister and cleanup the vchiq char
+ * driver and device files
+ */
+void vchiq_deregister_chrdev(void)
+{
+ device_destroy(vchiq_class, vchiq_devid);
+ cdev_del(&vchiq_cdev);
+ unregister_chrdev_region(vchiq_devid, 1);
+ class_destroy(vchiq_class);
+}
diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c
index d89163299172..f73f3fad3e05 100644
--- a/drivers/staging/vt6655/baseband.c
+++ b/drivers/staging/vt6655/baseband.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: baseband.c
- *
* Purpose: Implement functions to access baseband
*
* Author: Kyle Hsu
diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h
index 9354ce724446..0a30afaa7cc3 100644
--- a/drivers/staging/vt6655/baseband.h
+++ b/drivers/staging/vt6655/baseband.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: baseband.h
- *
* Purpose: Implement functions to access baseband
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index 29086189c53a..3ef3a6e0e6e1 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -3,7 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: card.c
* Purpose: Provide functions to setup NIC operation mode
* Functions:
* s_vSafeResetTx - Rest Tx
diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
index 568a2ddd6588..09e7f3f1cbed 100644
--- a/drivers/staging/vt6655/card.h
+++ b/drivers/staging/vt6655/card.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: card.h
- *
* Purpose: Provide functions to setup NIC operation mode
*
* Author: Tevin Chen
diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c
index cf46ee63681a..52b6538a201a 100644
--- a/drivers/staging/vt6655/channel.c
+++ b/drivers/staging/vt6655/channel.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: channel.c
- *
*/
#include "baseband.h"
diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h
index 0d2709607456..78b2d82317e5 100644
--- a/drivers/staging/vt6655/channel.h
+++ b/drivers/staging/vt6655/channel.h
@@ -3,7 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: channel.h
*/
#ifndef _CHANNEL_H_
diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h
index d4572847b08a..17a40c53b8ff 100644
--- a/drivers/staging/vt6655/desc.h
+++ b/drivers/staging/vt6655/desc.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: desc.h
- *
* Purpose:The header file of descriptor
*
* Revision History:
diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h
index 29f354ced563..2af769174e33 100644
--- a/drivers/staging/vt6655/device.h
+++ b/drivers/staging/vt6655/device.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: device.h
- *
* Purpose: MAC Data structure
*
* Author: Tevin Chen
diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h
index 04db6a8d3db3..2d647a3619ba 100644
--- a/drivers/staging/vt6655/device_cfg.h
+++ b/drivers/staging/vt6655/device_cfg.h
@@ -3,14 +3,13 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: device_cfg.h
- *
* Purpose: Driver configuration header
* Author: Lyndon Chen
*
* Date: Dec 17, 2002
*
*/
+
#ifndef __DEVICE_CONFIG_H
#define __DEVICE_CONFIG_H
@@ -39,9 +38,6 @@
#include <linux/fs.h>
#include <linux/fcntl.h>
-#ifndef CONFIG_PATH
-#define CONFIG_PATH "/etc/vntconfiguration.dat"
-#endif
#define PKT_BUF_SZ 2390
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 979165445d88..d40c2ac14928 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: device_main.c
- *
* Purpose: driver entry for initial, open, close, tx and rx.
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c
index 52214a30e9b6..2d06cecc0307 100644
--- a/drivers/staging/vt6655/dpc.c
+++ b/drivers/staging/vt6655/dpc.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: dpc.c
- *
* Purpose: handle dpc rx functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h
index eac67794cc49..40364c0ab7f6 100644
--- a/drivers/staging/vt6655/dpc.h
+++ b/drivers/staging/vt6655/dpc.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: dpc.h
- *
* Purpose:
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c
index 94665ddc36a5..20881cf2f394 100644
--- a/drivers/staging/vt6655/key.c
+++ b/drivers/staging/vt6655/key.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: key.c
- *
* Purpose: Implement functions for 802.11i Key management
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h
index 9347776fa3a5..d88da9dfb5c3 100644
--- a/drivers/staging/vt6655/key.h
+++ b/drivers/staging/vt6655/key.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: key.h
- *
* Purpose: Implement functions for 802.11i Key management
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c
index f5ae7f1f5689..9721c2234bf2 100644
--- a/drivers/staging/vt6655/mac.c
+++ b/drivers/staging/vt6655/mac.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: mac.c
- *
* Purpose: MAC routines
*
* Author: Tevin Chen
@@ -775,7 +773,6 @@ void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl,
if (byLocalID <= 1)
return;
- pr_debug("%s\n", __func__);
offset = MISCFIFO_KEYETRY0;
offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h
index 6e2bd16ef384..9797eddaea01 100644
--- a/drivers/staging/vt6655/mac.h
+++ b/drivers/staging/vt6655/mac.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: mac.h
- *
* Purpose: MAC routines
*
* Author: Tevin Chen
diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c
index 6b0407694e54..aac021e983d1 100644
--- a/drivers/staging/vt6655/power.c
+++ b/drivers/staging/vt6655/power.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: power.c
- *
* Purpose: Handles 802.11 power management functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h
index d1736c1cbfa8..060516f81f5b 100644
--- a/drivers/staging/vt6655/power.h
+++ b/drivers/staging/vt6655/power.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: power.h
- *
* Purpose: Handles 802.11 power management functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c
index 747d79265a7c..0dae593c6944 100644
--- a/drivers/staging/vt6655/rf.c
+++ b/drivers/staging/vt6655/rf.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: rf.c
- *
* Purpose: rf function code
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h
index affb70eba10f..d499aed45c9f 100644
--- a/drivers/staging/vt6655/rf.h
+++ b/drivers/staging/vt6655/rf.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: rf.h
- *
* Purpose:
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c
index ff452067a617..5395c3a3e35a 100644
--- a/drivers/staging/vt6655/rxtx.c
+++ b/drivers/staging/vt6655/rxtx.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: rxtx.c
- *
* Purpose: handle WMAC/802.3/802.11 rx & tx functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h
index c3c2c1566882..a67757c9bb5c 100644
--- a/drivers/staging/vt6655/rxtx.h
+++ b/drivers/staging/vt6655/rxtx.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: rxtx.h
- *
* Purpose:
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c
index df57d120ed30..5cdbc24e8c45 100644
--- a/drivers/staging/vt6655/srom.c
+++ b/drivers/staging/vt6655/srom.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: srom.c
- *
* Purpose:Implement functions to access eeprom
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h
index d8aad3ff5f46..b03073ffa18a 100644
--- a/drivers/staging/vt6655/srom.h
+++ b/drivers/staging/vt6655/srom.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: srom.h
- *
* Purpose: Implement functions to access eeprom
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6655/tmacro.h b/drivers/staging/vt6655/tmacro.h
index 8f4699f0d1f4..1582c03124c9 100644
--- a/drivers/staging/vt6655/tmacro.h
+++ b/drivers/staging/vt6655/tmacro.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: tmacro.h
- *
* Purpose: define basic common types and macros
*
* Author: Tevin Chen
diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h
index 8608693ae9c3..b374db5fca81 100644
--- a/drivers/staging/vt6655/upc.h
+++ b/drivers/staging/vt6655/upc.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: upc.h
- *
* Purpose: Macros to access device
*
* Author: Tevin Chen
diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
index 41ae779ec61f..1e1c5a7d8968 100644
--- a/drivers/staging/vt6656/baseband.c
+++ b/drivers/staging/vt6656/baseband.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: baseband.c
- *
* Purpose: Implement functions to access baseband
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h
index 12456ebc23ec..dce50a311f24 100644
--- a/drivers/staging/vt6656/baseband.h
+++ b/drivers/staging/vt6656/baseband.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: baseband.h
- *
* Purpose: Implement functions to access baseband
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
index 396736eee690..e92ecfad26d2 100644
--- a/drivers/staging/vt6656/card.c
+++ b/drivers/staging/vt6656/card.c
@@ -3,7 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: card.c
* Purpose: Provide functions to setup NIC operation mode
* Functions:
* vnt_set_rspinf - Set RSPINF
diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h
index a524fdc60ae3..be32c25c95de 100644
--- a/drivers/staging/vt6656/card.h
+++ b/drivers/staging/vt6656/card.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: card.h
- *
* Purpose: Provide functions to setup NIC operation mode
*
* Author: Tevin Chen
diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c
index 7855689af7cb..eb2d52e6420b 100644
--- a/drivers/staging/vt6656/channel.c
+++ b/drivers/staging/vt6656/channel.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: channel.c
- *
* Purpose: Channel number mapping
*
* Author: Lucas Lin
diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h
index cca330f0daf4..723660e40310 100644
--- a/drivers/staging/vt6656/channel.h
+++ b/drivers/staging/vt6656/channel.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: channel.h
- *
* Purpose: Country Regulation Rules header file
*
* Author: Lucas Lin
diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
index 703597a911f4..c13561e528db 100644
--- a/drivers/staging/vt6656/desc.h
+++ b/drivers/staging/vt6656/desc.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: desc.h
- *
* Purpose:The header file of descriptor
*
* Revision History:
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index 947530fefe94..8b6623a751f0 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: device.h
- *
* Purpose: MAC Data structure
*
* Author: Tevin Chen
@@ -77,8 +75,6 @@
#define FIRMWARE_NAME "vntwusb.fw"
#define FIRMWARE_CHUNK_SIZE 0x400
-#define CONFIG_PATH "/etc/vntconfiguration.dat"
-
#define MAX_UINTS 8
#define OPTION_DEFAULT { [0 ... MAX_UINTS - 1] = -1}
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
index 70f75c5760ce..bdc5f30c4f9d 100644
--- a/drivers/staging/vt6656/key.c
+++ b/drivers/staging/vt6656/key.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: key.c
- *
* Purpose: Implement functions for 802.11i Key management
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h
index 1f3449e66143..6f1d5b4f6da7 100644
--- a/drivers/staging/vt6656/key.h
+++ b/drivers/staging/vt6656/key.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: key.h
- *
* Purpose: Implement functions for 802.11i Key management
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c
index da7067c34643..4f1f9b03a678 100644
--- a/drivers/staging/vt6656/mac.c
+++ b/drivers/staging/vt6656/mac.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: mac.c
- *
* Purpose: MAC routines
*
* Author: Tevin Chen
diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h
index dae70b5c7634..05af9ca7d69c 100644
--- a/drivers/staging/vt6656/mac.h
+++ b/drivers/staging/vt6656/mac.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: mac.h
- *
* Purpose: MAC routines
*
* Author: Tevin Chen
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index b90d3dab28b1..ae7f5916d4d6 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: main_usb.c
- *
* Purpose: driver entry for initial, open, close, tx and rx.
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c
index 2f49c870272a..e5411f6284c7 100644
--- a/drivers/staging/vt6656/power.c
+++ b/drivers/staging/vt6656/power.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: power.c
- *
* Purpose: Handles 802.11 power management functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h
index 160872026db3..9f9c70072933 100644
--- a/drivers/staging/vt6656/power.h
+++ b/drivers/staging/vt6656/power.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: power.h
- *
* Purpose: Handles 802.11 power management functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c
index bcd4d467e03a..b9c06b312ae1 100644
--- a/drivers/staging/vt6656/rf.c
+++ b/drivers/staging/vt6656/rf.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: rf.c
- *
* Purpose: rf function code
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h
index 493faaf4e2b5..b47e149875d1 100644
--- a/drivers/staging/vt6656/rf.h
+++ b/drivers/staging/vt6656/rf.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: rf.h
- *
* Purpose:
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 5dd6b4d2bf20..a31947f2620d 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: rxtx.c
- *
* Purpose: handle WMAC/802.3/802.11 rx & tx functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index f23440799443..b9df0854b4b0 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: rxtx.h
- *
* Purpose:
*
* Author: Jerry Chen
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index 82b774be6485..7f45734390f6 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: usbpipe.c
- *
* Purpose: Handle USB control endpoint
*
* Author: Warren Hsu
diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h
index 52c2a928c9c1..922312e299bf 100644
--- a/drivers/staging/vt6656/usbpipe.h
+++ b/drivers/staging/vt6656/usbpipe.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: usbpipe.h
- *
* Purpose:
*
* Author: Warren Hsu
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
index 0ccc87da394e..e8ee2fbee76c 100644
--- a/drivers/staging/vt6656/wcmd.c
+++ b/drivers/staging/vt6656/wcmd.c
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: wcmd.c
- *
* Purpose: Handles the management command interface functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h
index a0d98cf74998..a62924671b17 100644
--- a/drivers/staging/vt6656/wcmd.h
+++ b/drivers/staging/vt6656/wcmd.h
@@ -3,8 +3,6 @@
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
- * File: wcmd.h
- *
* Purpose: Handles the management command interface functions
*
* Author: Lyndon Chen
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index 88e894dd3568..75ed8bc4bbc1 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -475,14 +475,7 @@ struct hfa384x_tx_frame {
u16 tx_control;
/*-- 802.11 Header Information --*/
-
- u16 frame_control;
- u16 duration_id;
- u8 address1[6];
- u8 address2[6];
- u8 address3[6];
- u16 sequence_control;
- u8 address4[6];
+ struct p80211_hdr hdr;
__le16 data_len; /* little endian format */
/*-- 802.3 Header Information --*/
@@ -541,13 +534,7 @@ struct hfa384x_rx_frame {
u16 reserved2;
/*-- 802.11 Header Information (802.11 byte order) --*/
- __le16 frame_control;
- u16 duration_id;
- u8 address1[6];
- u8 address2[6];
- u8 address3[6];
- u16 sequence_control;
- u8 address4[6];
+ struct p80211_hdr hdr;
__le16 data_len; /* hfa384x (little endian) format */
/*-- 802.3 Header Information --*/
@@ -1423,7 +1410,7 @@ int hfa384x_drvr_start(struct hfa384x *hw);
int hfa384x_drvr_stop(struct hfa384x *hw);
int
hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb,
- union p80211_hdr *p80211_hdr,
+ struct p80211_hdr *p80211_hdr,
struct p80211_metawep *p80211_wep);
void hfa384x_tx_timeout(struct wlandevice *wlandev);
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index f2a0e16b0318..8c8524679ba3 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -2472,7 +2472,7 @@ int hfa384x_drvr_stop(struct hfa384x *hw)
*----------------------------------------------------------------
*/
int hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb,
- union p80211_hdr *p80211_hdr,
+ struct p80211_hdr *p80211_hdr,
struct p80211_metawep *p80211_wep)
{
int usbpktlen = sizeof(struct hfa384x_tx_frame);
@@ -2516,8 +2516,7 @@ int hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb,
cpu_to_le16s(&hw->txbuff.txfrm.desc.tx_control);
/* copy the header over to the txdesc */
- memcpy(&hw->txbuff.txfrm.desc.frame_control, p80211_hdr,
- sizeof(union p80211_hdr));
+ hw->txbuff.txfrm.desc.hdr = *p80211_hdr;
/* if we're using host WEP, increase size by IV+ICV */
if (p80211_wep->data) {
@@ -3258,7 +3257,7 @@ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb)
switch (status) {
case 0:
- fc = le16_to_cpu(usbin->rxfrm.desc.frame_control);
+ fc = le16_to_cpu(usbin->rxfrm.desc.hdr.frame_control);
/* If exclude and we receive an unencrypted, drop it */
if ((wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) &&
@@ -3278,7 +3277,7 @@ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb)
* with an "overlapping" copy
*/
memmove(skb_push(skb, hdrlen),
- &usbin->rxfrm.desc.frame_control, hdrlen);
+ &usbin->rxfrm.desc.hdr, hdrlen);
skb->dev = wlandev->netdev;
@@ -3356,7 +3355,7 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev,
/* Remember the status, time, and data_len fields are in host order */
/* Figure out how big the frame is */
- fc = le16_to_cpu(rxdesc->frame_control);
+ fc = le16_to_cpu(rxdesc->hdr.frame_control);
hdrlen = p80211_headerlen(fc);
datalen = le16_to_cpu(rxdesc->data_len);
@@ -3404,7 +3403,7 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev,
/* Copy the 802.11 header to the skb
* (ctl frames may be less than a full header)
*/
- skb_put_data(skb, &rxdesc->frame_control, hdrlen);
+ skb_put_data(skb, &rxdesc->hdr.frame_control, hdrlen);
/* If any, copy the data from the card to the skb */
if (datalen > 0) {
diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c
index 0ff5fda81b05..59b25ca50d15 100644
--- a/drivers/staging/wlan-ng/p80211conv.c
+++ b/drivers/staging/wlan-ng/p80211conv.c
@@ -106,7 +106,7 @@ static const u8 oui_8021h[] = { 0x00, 0x00, 0xf8 };
*----------------------------------------------------------------
*/
int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv,
- struct sk_buff *skb, union p80211_hdr *p80211_hdr,
+ struct sk_buff *skb, struct p80211_hdr *p80211_hdr,
struct p80211_metawep *p80211_wep)
{
__le16 fc;
@@ -175,21 +175,21 @@ int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv,
switch (wlandev->macmode) {
case WLAN_MACMODE_IBSS_STA:
- memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, ETH_ALEN);
- memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, ETH_ALEN);
- memcpy(p80211_hdr->a3.a3, wlandev->bssid, ETH_ALEN);
+ memcpy(p80211_hdr->address1, &e_hdr.daddr, ETH_ALEN);
+ memcpy(p80211_hdr->address2, wlandev->netdev->dev_addr, ETH_ALEN);
+ memcpy(p80211_hdr->address3, wlandev->bssid, ETH_ALEN);
break;
case WLAN_MACMODE_ESS_STA:
fc |= cpu_to_le16(WLAN_SET_FC_TODS(1));
- memcpy(p80211_hdr->a3.a1, wlandev->bssid, ETH_ALEN);
- memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, ETH_ALEN);
- memcpy(p80211_hdr->a3.a3, &e_hdr.daddr, ETH_ALEN);
+ memcpy(p80211_hdr->address1, wlandev->bssid, ETH_ALEN);
+ memcpy(p80211_hdr->address2, wlandev->netdev->dev_addr, ETH_ALEN);
+ memcpy(p80211_hdr->address3, &e_hdr.daddr, ETH_ALEN);
break;
case WLAN_MACMODE_ESS_AP:
fc |= cpu_to_le16(WLAN_SET_FC_FROMDS(1));
- memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, ETH_ALEN);
- memcpy(p80211_hdr->a3.a2, wlandev->bssid, ETH_ALEN);
- memcpy(p80211_hdr->a3.a3, &e_hdr.saddr, ETH_ALEN);
+ memcpy(p80211_hdr->address1, &e_hdr.daddr, ETH_ALEN);
+ memcpy(p80211_hdr->address2, wlandev->bssid, ETH_ALEN);
+ memcpy(p80211_hdr->address3, &e_hdr.saddr, ETH_ALEN);
break;
default:
netdev_err(wlandev->netdev,
@@ -222,9 +222,9 @@ int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv,
/* skb->nh.raw = skb->data; */
- p80211_hdr->a3.fc = fc;
- p80211_hdr->a3.dur = 0;
- p80211_hdr->a3.seq = 0;
+ p80211_hdr->frame_control = fc;
+ p80211_hdr->duration_id = 0;
+ p80211_hdr->sequence_control = 0;
return 0;
}
@@ -281,7 +281,7 @@ int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv,
unsigned int payload_offset;
u8 daddr[ETH_ALEN];
u8 saddr[ETH_ALEN];
- union p80211_hdr *w_hdr;
+ struct p80211_hdr *w_hdr;
struct wlan_ethhdr *e_hdr;
struct wlan_llc *e_llc;
struct wlan_snap *e_snap;
@@ -291,21 +291,21 @@ int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv,
payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;
payload_offset = WLAN_HDR_A3_LEN;
- w_hdr = (union p80211_hdr *)skb->data;
+ w_hdr = (struct p80211_hdr *)skb->data;
/* setup some vars for convenience */
- fc = le16_to_cpu(w_hdr->a3.fc);
+ fc = le16_to_cpu(w_hdr->frame_control);
if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0)) {
- ether_addr_copy(daddr, w_hdr->a3.a1);
- ether_addr_copy(saddr, w_hdr->a3.a2);
+ ether_addr_copy(daddr, w_hdr->address1);
+ ether_addr_copy(saddr, w_hdr->address2);
} else if ((WLAN_GET_FC_TODS(fc) == 0) &&
(WLAN_GET_FC_FROMDS(fc) == 1)) {
- ether_addr_copy(daddr, w_hdr->a3.a1);
- ether_addr_copy(saddr, w_hdr->a3.a3);
+ ether_addr_copy(daddr, w_hdr->address1);
+ ether_addr_copy(saddr, w_hdr->address3);
} else if ((WLAN_GET_FC_TODS(fc) == 1) &&
(WLAN_GET_FC_FROMDS(fc) == 0)) {
- ether_addr_copy(daddr, w_hdr->a3.a3);
- ether_addr_copy(saddr, w_hdr->a3.a2);
+ ether_addr_copy(daddr, w_hdr->address3);
+ ether_addr_copy(saddr, w_hdr->address2);
} else {
payload_offset = WLAN_HDR_A4_LEN;
if (payload_length < WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN) {
@@ -313,8 +313,8 @@ int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv,
return 1;
}
payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
- ether_addr_copy(daddr, w_hdr->a4.a3);
- ether_addr_copy(saddr, w_hdr->a4.a4);
+ ether_addr_copy(daddr, w_hdr->address3);
+ ether_addr_copy(saddr, w_hdr->address4);
}
/* perform de-wep if necessary.. */
diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h
index 15fd635d9770..63c423507fe8 100644
--- a/drivers/staging/wlan-ng/p80211conv.h
+++ b/drivers/staging/wlan-ng/p80211conv.h
@@ -154,7 +154,7 @@ struct wlandevice;
int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv,
struct sk_buff *skb);
int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv,
- struct sk_buff *skb, union p80211_hdr *p80211_hdr,
+ struct sk_buff *skb, struct p80211_hdr *p80211_hdr,
struct p80211_metawep *p80211_wep);
int p80211_stt_findproto(u16 proto);
diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h
index 6564810fd026..5871a55e4a61 100644
--- a/drivers/staging/wlan-ng/p80211hdr.h
+++ b/drivers/staging/wlan-ng/p80211hdr.h
@@ -148,28 +148,14 @@
/* Generic 802.11 Header types */
-struct p80211_hdr_a3 {
- __le16 fc;
- u16 dur;
- u8 a1[ETH_ALEN];
- u8 a2[ETH_ALEN];
- u8 a3[ETH_ALEN];
- u16 seq;
-} __packed;
-
-struct p80211_hdr_a4 {
- u16 fc;
- u16 dur;
- u8 a1[ETH_ALEN];
- u8 a2[ETH_ALEN];
- u8 a3[ETH_ALEN];
- u16 seq;
- u8 a4[ETH_ALEN];
-} __packed;
-
-union p80211_hdr {
- struct p80211_hdr_a3 a3;
- struct p80211_hdr_a4 a4;
+struct p80211_hdr {
+ __le16 frame_control;
+ u16 duration_id;
+ u8 address1[ETH_ALEN];
+ u8 address2[ETH_ALEN];
+ u8 address3[ETH_ALEN];
+ u16 sequence_control;
+ u8 address4[ETH_ALEN];
} __packed;
/* Frame and header length macros */
diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h
index c045c08e1991..1457a6def5a2 100644
--- a/drivers/staging/wlan-ng/p80211mgmt.h
+++ b/drivers/staging/wlan-ng/p80211mgmt.h
@@ -299,7 +299,7 @@ struct wlan_fr_mgmt {
u16 type;
u16 len; /* DOES NOT include CRC !!!! */
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -311,7 +311,7 @@ struct wlan_fr_beacon {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -334,7 +334,7 @@ struct wlan_fr_ibssatim {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
@@ -350,7 +350,7 @@ struct wlan_fr_disassoc {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -365,7 +365,7 @@ struct wlan_fr_assocreq {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -382,7 +382,7 @@ struct wlan_fr_assocresp {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -399,7 +399,7 @@ struct wlan_fr_reassocreq {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -417,7 +417,7 @@ struct wlan_fr_reassocresp {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -434,7 +434,7 @@ struct wlan_fr_probereq {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -449,7 +449,7 @@ struct wlan_fr_proberesp {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -470,7 +470,7 @@ struct wlan_fr_authen {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
@@ -487,7 +487,7 @@ struct wlan_fr_deauthen {
u16 type;
u16 len;
u8 *buf;
- union p80211_hdr *hdr;
+ struct p80211_hdr *hdr;
/* used for target specific data, skb in Linux */
void *priv;
/*-- fixed fields -----------*/
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index 1c62130a5eee..2a3f9385ab3f 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -235,10 +235,10 @@ void p80211netdev_rx(struct wlandevice *wlandev, struct sk_buff *skb)
static int p80211_convert_to_ether(struct wlandevice *wlandev,
struct sk_buff *skb)
{
- struct p80211_hdr_a3 *hdr;
+ struct p80211_hdr *hdr;
- hdr = (struct p80211_hdr_a3 *)skb->data;
- if (p80211_rx_typedrop(wlandev, le16_to_cpu(hdr->fc)))
+ hdr = (struct p80211_hdr *)skb->data;
+ if (p80211_rx_typedrop(wlandev, le16_to_cpu(hdr->frame_control)))
return CONV_TO_ETHER_SKIPPED;
/* perform mcast filtering: allow my local address through but reject
@@ -246,8 +246,8 @@ static int p80211_convert_to_ether(struct wlandevice *wlandev,
*/
if (wlandev->netdev->flags & IFF_ALLMULTI) {
if (!ether_addr_equal_unaligned(wlandev->netdev->dev_addr,
- hdr->a1)) {
- if (!is_multicast_ether_addr(hdr->a1))
+ hdr->address1)) {
+ if (!is_multicast_ether_addr(hdr->address1))
return CONV_TO_ETHER_SKIPPED;
}
}
@@ -327,7 +327,7 @@ static netdev_tx_t p80211knetdev_hard_start_xmit(struct sk_buff *skb,
int result = 0;
int txresult;
struct wlandevice *wlandev = netdev->ml_priv;
- union p80211_hdr p80211_hdr;
+ struct p80211_hdr p80211_hdr;
struct p80211_metawep p80211_wep;
p80211_wep.data = NULL;
diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h
index d48466d943b4..25e5116b1590 100644
--- a/drivers/staging/wlan-ng/p80211netdev.h
+++ b/drivers/staging/wlan-ng/p80211netdev.h
@@ -180,7 +180,7 @@ struct wlandevice {
int (*close)(struct wlandevice *wlandev);
void (*reset)(struct wlandevice *wlandev);
int (*txframe)(struct wlandevice *wlandev, struct sk_buff *skb,
- union p80211_hdr *p80211_hdr,
+ struct p80211_hdr *p80211_hdr,
struct p80211_metawep *p80211_wep);
int (*mlmerequest)(struct wlandevice *wlandev, struct p80211msg *msg);
int (*set_multicast_list)(struct wlandevice *wlandev,
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index 94800c007162..02a2191d5c4d 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -296,7 +296,7 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr,
memset(&getmsg, 0, sizeof(getmsg));
getmsg.msgcode = DIDMSG_DOT11REQ_MIBGET;
getmsg.msglen = sizeof(getmsg);
- strcpy(getmsg.devname, wlandev->name);
+ strscpy(getmsg.devname, wlandev->name, sizeof(getmsg.devname));
getmsg.mibattribute.did = DIDMSG_DOT11REQ_MIBGET_MIBATTRIBUTE;
getmsg.mibattribute.status = P80211ENUM_msgitem_status_data_ok;
@@ -786,7 +786,7 @@ static int read_cardpda(struct pda *pda, struct wlandevice *wlandev)
/* set up the msg */
msg->msgcode = DIDMSG_P2REQ_READPDA;
msg->msglen = sizeof(msg);
- strcpy(msg->devname, wlandev->name);
+ strscpy(msg->devname, wlandev->name, sizeof(msg->devname));
msg->pda.did = DIDMSG_P2REQ_READPDA_PDA;
msg->pda.len = HFA384x_PDA_LEN_MAX;
msg->pda.status = P80211ENUM_msgitem_status_no_value;
@@ -1017,7 +1017,7 @@ static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk,
}
/* Initialize the messages */
- strcpy(rstmsg->devname, wlandev->name);
+ strscpy(rstmsg->devname, wlandev->name, sizeof(rstmsg->devname));
rstmsg->msgcode = DIDMSG_P2REQ_RAMDL_STATE;
rstmsg->msglen = sizeof(*rstmsg);
rstmsg->enable.did = DIDMSG_P2REQ_RAMDL_STATE_ENABLE;
@@ -1030,7 +1030,7 @@ static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk,
rstmsg->exeaddr.len = sizeof(u32);
rstmsg->resultcode.len = sizeof(u32);
- strcpy(rwrmsg->devname, wlandev->name);
+ strscpy(rwrmsg->devname, wlandev->name, sizeof(rwrmsg->devname));
rwrmsg->msgcode = DIDMSG_P2REQ_RAMDL_WRITE;
rwrmsg->msglen = sizeof(*rwrmsg);
rwrmsg->addr.did = DIDMSG_P2REQ_RAMDL_WRITE_ADDR;
diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c
index 875812a391c9..d14f032a7ed6 100644
--- a/drivers/staging/wlan-ng/prism2mib.c
+++ b/drivers/staging/wlan-ng/prism2mib.c
@@ -668,6 +668,10 @@ static int prism2mib_priv(struct mibrec *mib,
switch (mib->did) {
case DIDMIB_LNX_CONFIGTABLE_RSNAIE: {
+ /*
+ * This can never work: wpa is on the stack
+ * and has no bytes allocated in wpa.data.
+ */
struct hfa384x_wpa_data wpa;
if (isget) {
@@ -675,11 +679,17 @@ static int prism2mib_priv(struct mibrec *mib,
HFA384x_RID_CNFWPADATA,
(u8 *)&wpa,
sizeof(wpa));
+ /*
pstr->len = le16_to_cpu(wpa.datalen);
memcpy(pstr->data, wpa.data, pstr->len);
+ */
+ pstr->len = 0;
} else {
+ /*
wpa.datalen = cpu_to_le16(pstr->len);
memcpy(wpa.data, pstr->data, pstr->len);
+ */
+ wpa.datalen = 0;
hfa384x_drvr_setconfig(hw,
HFA384x_RID_CNFWPADATA,
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index e6dcb687e7a1..f67b7405156a 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -103,7 +103,7 @@ static int prism2sta_open(struct wlandevice *wlandev);
static int prism2sta_close(struct wlandevice *wlandev);
static void prism2sta_reset(struct wlandevice *wlandev);
static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb,
- union p80211_hdr *p80211_hdr,
+ struct p80211_hdr *p80211_hdr,
struct p80211_metawep *p80211_wep);
static int prism2sta_mlmerequest(struct wlandevice *wlandev,
struct p80211msg *msg);
@@ -242,7 +242,7 @@ static void prism2sta_reset(struct wlandevice *wlandev)
* process thread
*/
static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb,
- union p80211_hdr *p80211_hdr,
+ struct p80211_hdr *p80211_hdr,
struct p80211_metawep *p80211_wep)
{
struct hfa384x *hw = wlandev->priv;
@@ -250,7 +250,7 @@ static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb,
/* If necessary, set the 802.11 WEP bit */
if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) ==
HOSTWEP_PRIVACYINVOKED) {
- p80211_hdr->a3.fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
+ p80211_hdr->frame_control |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
}
return hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep);
diff --git a/drivers/target/Kconfig b/drivers/target/Kconfig
index c163b14774d7..72171ea3dd53 100644
--- a/drivers/target/Kconfig
+++ b/drivers/target/Kconfig
@@ -5,7 +5,7 @@ menuconfig TARGET_CORE
depends on BLOCK
select CONFIGFS_FS
select CRC_T10DIF
- select BLK_SCSI_REQUEST
+ select SCSI_COMMON
select SGL_ALLOC
default n
help
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_ddp.c b/drivers/target/iscsi/cxgbit/cxgbit_ddp.c
index b044999ad002..072afd070f3e 100644
--- a/drivers/target/iscsi/cxgbit/cxgbit_ddp.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_ddp.c
@@ -234,7 +234,7 @@ cxgbit_get_r2t_ttt(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
struct cxgbit_device *cdev = csk->com.cdev;
struct cxgbit_cmd *ccmd = iscsit_priv_cmd(cmd);
struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo;
- int ret = -EINVAL;
+ int ret;
if ((!ccmd->setup_ddp) ||
(!test_bit(CSK_DDP_ENABLE, &csk->com.flags)))
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 6d0b0e67e79e..52db28d868d5 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -81,7 +81,7 @@ static int tcm_loop_show_info(struct seq_file *m, struct Scsi_Host *host)
}
static int tcm_loop_driver_probe(struct device *);
-static int tcm_loop_driver_remove(struct device *);
+static void tcm_loop_driver_remove(struct device *);
static int pseudo_lld_bus_match(struct device *dev,
struct device_driver *dev_driver)
@@ -183,7 +183,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
memset(tl_cmd, 0, sizeof(*tl_cmd));
tl_cmd->sc = sc;
- tl_cmd->sc_cmd_tag = sc->request->tag;
+ tl_cmd->sc_cmd_tag = scsi_cmd_to_rq(sc)->tag;
tcm_loop_target_queue_cmd(tl_cmd);
return 0;
@@ -241,7 +241,7 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc)
{
struct tcm_loop_hba *tl_hba;
struct tcm_loop_tpg *tl_tpg;
- int ret = FAILED;
+ int ret;
/*
* Locate the tcm_loop_hba_t pointer
@@ -249,7 +249,7 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc)
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun,
- sc->request->tag, TMR_ABORT_TASK);
+ scsi_cmd_to_rq(sc)->tag, TMR_ABORT_TASK);
return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
}
@@ -261,7 +261,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
{
struct tcm_loop_hba *tl_hba;
struct tcm_loop_tpg *tl_tpg;
- int ret = FAILED;
+ int ret;
/*
* Locate the tcm_loop_hba_t pointer
@@ -363,7 +363,7 @@ static int tcm_loop_driver_probe(struct device *dev)
return 0;
}
-static int tcm_loop_driver_remove(struct device *dev)
+static void tcm_loop_driver_remove(struct device *dev)
{
struct tcm_loop_hba *tl_hba;
struct Scsi_Host *sh;
@@ -373,7 +373,6 @@ static int tcm_loop_driver_remove(struct device *dev)
scsi_remove_host(sh);
scsi_host_put(sh);
- return 0;
}
static void tcm_loop_release_adapter(struct device *dev)
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 4d3ceee23622..b9f9fb5d7e63 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -1389,8 +1389,8 @@ static void sbp_sense_mangle(struct sbp_target_request *req)
(sense[0] & 0x80) | /* valid */
((sense[2] & 0xe0) >> 1) | /* mark, eom, ili */
(sense[2] & 0x0f); /* sense_key */
- status[2] = se_cmd->scsi_asc; /* sense_code */
- status[3] = se_cmd->scsi_ascq; /* sense_qualifier */
+ status[2] = 0; /* XXX sense_code */
+ status[3] = 0; /* XXX sense_qualifier */
/* information */
status[4] = sense[3];
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 3bb921345bce..cb1de1ecaaa6 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -428,22 +428,6 @@ out:
return rc;
}
-static inline void set_ascq(struct se_cmd *cmd, u8 alua_ascq)
-{
- /*
- * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
- * The ALUA additional sense code qualifier (ASCQ) is determined
- * by the ALUA primary or secondary access state..
- */
- pr_debug("[%s]: ALUA TG Port not available, "
- "SenseKey: NOT_READY, ASC/ASCQ: "
- "0x04/0x%02x\n",
- cmd->se_tfo->fabric_name, alua_ascq);
-
- cmd->scsi_asc = 0x04;
- cmd->scsi_ascq = alua_ascq;
-}
-
static inline void core_alua_state_nonoptimized(
struct se_cmd *cmd,
unsigned char *cdb,
@@ -458,9 +442,9 @@ static inline void core_alua_state_nonoptimized(
cmd->alua_nonop_delay = nonop_delay_msecs;
}
-static inline int core_alua_state_lba_dependent(
+static inline sense_reason_t core_alua_state_lba_dependent(
struct se_cmd *cmd,
- struct t10_alua_tg_pt_gp *tg_pt_gp)
+ u16 tg_pt_gp_id)
{
struct se_device *dev = cmd->se_dev;
u64 segment_size, segment_mult, sectors, lba;
@@ -506,23 +490,19 @@ static inline int core_alua_state_lba_dependent(
}
if (!cur_map) {
spin_unlock(&dev->t10_alua.lba_map_lock);
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
- return 1;
+ return TCM_ALUA_TG_PT_UNAVAILABLE;
}
list_for_each_entry(map_mem, &cur_map->lba_map_mem_list,
lba_map_mem_list) {
- if (map_mem->lba_map_mem_alua_pg_id !=
- tg_pt_gp->tg_pt_gp_id)
+ if (map_mem->lba_map_mem_alua_pg_id != tg_pt_gp_id)
continue;
switch(map_mem->lba_map_mem_alua_state) {
case ALUA_ACCESS_STATE_STANDBY:
spin_unlock(&dev->t10_alua.lba_map_lock);
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
- return 1;
+ return TCM_ALUA_TG_PT_STANDBY;
case ALUA_ACCESS_STATE_UNAVAILABLE:
spin_unlock(&dev->t10_alua.lba_map_lock);
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
- return 1;
+ return TCM_ALUA_TG_PT_UNAVAILABLE;
default:
break;
}
@@ -532,7 +512,7 @@ static inline int core_alua_state_lba_dependent(
return 0;
}
-static inline int core_alua_state_standby(
+static inline sense_reason_t core_alua_state_standby(
struct se_cmd *cmd,
unsigned char *cdb)
{
@@ -556,24 +536,21 @@ static inline int core_alua_state_standby(
case SAI_READ_CAPACITY_16:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
- return 1;
+ return TCM_ALUA_TG_PT_STANDBY;
}
case MAINTENANCE_IN:
switch (cdb[1] & 0x1f) {
case MI_REPORT_TARGET_PGS:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
- return 1;
+ return TCM_ALUA_TG_PT_STANDBY;
}
case MAINTENANCE_OUT:
switch (cdb[1]) {
case MO_SET_TARGET_PGS:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
- return 1;
+ return TCM_ALUA_TG_PT_STANDBY;
}
case REQUEST_SENSE:
case PERSISTENT_RESERVE_IN:
@@ -582,14 +559,13 @@ static inline int core_alua_state_standby(
case WRITE_BUFFER:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY);
- return 1;
+ return TCM_ALUA_TG_PT_STANDBY;
}
return 0;
}
-static inline int core_alua_state_unavailable(
+static inline sense_reason_t core_alua_state_unavailable(
struct se_cmd *cmd,
unsigned char *cdb)
{
@@ -606,30 +582,27 @@ static inline int core_alua_state_unavailable(
case MI_REPORT_TARGET_PGS:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
- return 1;
+ return TCM_ALUA_TG_PT_UNAVAILABLE;
}
case MAINTENANCE_OUT:
switch (cdb[1]) {
case MO_SET_TARGET_PGS:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
- return 1;
+ return TCM_ALUA_TG_PT_UNAVAILABLE;
}
case REQUEST_SENSE:
case READ_BUFFER:
case WRITE_BUFFER:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE);
- return 1;
+ return TCM_ALUA_TG_PT_UNAVAILABLE;
}
return 0;
}
-static inline int core_alua_state_transition(
+static inline sense_reason_t core_alua_state_transition(
struct se_cmd *cmd,
unsigned char *cdb)
{
@@ -646,16 +619,14 @@ static inline int core_alua_state_transition(
case MI_REPORT_TARGET_PGS:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_STATE_TRANSITION);
- return 1;
+ return TCM_ALUA_STATE_TRANSITION;
}
case REQUEST_SENSE:
case READ_BUFFER:
case WRITE_BUFFER:
return 0;
default:
- set_ascq(cmd, ASCQ_04H_ALUA_STATE_TRANSITION);
- return 1;
+ return TCM_ALUA_STATE_TRANSITION;
}
return 0;
@@ -674,6 +645,8 @@ target_alua_state_check(struct se_cmd *cmd)
struct se_lun *lun = cmd->se_lun;
struct t10_alua_tg_pt_gp *tg_pt_gp;
int out_alua_state, nonop_delay_msecs;
+ u16 tg_pt_gp_id;
+ sense_reason_t rc = TCM_NO_SENSE;
if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
return 0;
@@ -687,8 +660,7 @@ target_alua_state_check(struct se_cmd *cmd)
if (atomic_read(&lun->lun_tg_pt_secondary_offline)) {
pr_debug("ALUA: Got secondary offline status for local"
" target port\n");
- set_ascq(cmd, ASCQ_04H_ALUA_OFFLINE);
- return TCM_CHECK_CONDITION_NOT_READY;
+ return TCM_ALUA_OFFLINE;
}
if (!lun->lun_tg_pt_gp)
@@ -698,8 +670,8 @@ target_alua_state_check(struct se_cmd *cmd)
tg_pt_gp = lun->lun_tg_pt_gp;
out_alua_state = tg_pt_gp->tg_pt_gp_alua_access_state;
nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs;
+ tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id;
- // XXX: keeps using tg_pt_gp witout reference after unlock
spin_unlock(&lun->lun_tg_pt_gp_lock);
/*
* Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED in a separate conditional
@@ -715,20 +687,16 @@ target_alua_state_check(struct se_cmd *cmd)
core_alua_state_nonoptimized(cmd, cdb, nonop_delay_msecs);
break;
case ALUA_ACCESS_STATE_STANDBY:
- if (core_alua_state_standby(cmd, cdb))
- return TCM_CHECK_CONDITION_NOT_READY;
+ rc = core_alua_state_standby(cmd, cdb);
break;
case ALUA_ACCESS_STATE_UNAVAILABLE:
- if (core_alua_state_unavailable(cmd, cdb))
- return TCM_CHECK_CONDITION_NOT_READY;
+ rc = core_alua_state_unavailable(cmd, cdb);
break;
case ALUA_ACCESS_STATE_TRANSITION:
- if (core_alua_state_transition(cmd, cdb))
- return TCM_CHECK_CONDITION_NOT_READY;
+ rc = core_alua_state_transition(cmd, cdb);
break;
case ALUA_ACCESS_STATE_LBA_DEPENDENT:
- if (core_alua_state_lba_dependent(cmd, tg_pt_gp))
- return TCM_CHECK_CONDITION_NOT_READY;
+ rc = core_alua_state_lba_dependent(cmd, tg_pt_gp_id);
break;
/*
* OFFLINE is a secondary ALUA target port group access state, that is
@@ -738,10 +706,16 @@ target_alua_state_check(struct se_cmd *cmd)
default:
pr_err("Unknown ALUA access state: 0x%02x\n",
out_alua_state);
- return TCM_INVALID_CDB_FIELD;
+ rc = TCM_INVALID_CDB_FIELD;
}
- return 0;
+ if (rc && rc != TCM_INVALID_CDB_FIELD) {
+ pr_debug("[%s]: ALUA TG Port not available, "
+ "SenseKey: NOT_READY, ASC/rc: 0x04/%d\n",
+ cmd->se_tfo->fabric_name, rc);
+ }
+
+ return rc;
}
/*
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 44d9d028f716..4069a1edcfa3 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -83,7 +83,7 @@ static int iblock_configure_device(struct se_device *dev)
struct blk_integrity *bi;
fmode_t mode;
unsigned int max_write_zeroes_sectors;
- int ret = -ENOMEM;
+ int ret;
if (!(ib_dev->ibd_flags & IBDF_HAS_UDEV_PATH)) {
pr_err("Missing udev_path= parameters for IBLOCK\n");
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 2629d2ef3970..75ef52f008ff 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -620,17 +620,17 @@ static void pscsi_complete_cmd(struct se_cmd *cmd, u8 scsi_status,
buf = transport_kmap_data_sg(cmd);
if (!buf) {
; /* XXX: TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE */
- }
-
- if (cdb[0] == MODE_SENSE_10) {
- if (!(buf[3] & 0x80))
- buf[3] |= 0x80;
} else {
- if (!(buf[2] & 0x80))
- buf[2] |= 0x80;
- }
+ if (cdb[0] == MODE_SENSE_10) {
+ if (!(buf[3] & 0x80))
+ buf[3] |= 0x80;
+ } else {
+ if (!(buf[2] & 0x80))
+ buf[2] |= 0x80;
+ }
- transport_kunmap_data_sg(cmd);
+ transport_kunmap_data_sg(cmd);
+ }
}
}
after_mode_sense:
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 26ceabe34de5..14c6f2bb1b01 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -736,8 +736,7 @@ static void target_complete_failure_work(struct work_struct *work)
{
struct se_cmd *cmd = container_of(work, struct se_cmd, work);
- transport_generic_request_failure(cmd,
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE);
+ transport_generic_request_failure(cmd, cmd->sense_reason);
}
/*
@@ -855,7 +854,8 @@ static bool target_cmd_interrupted(struct se_cmd *cmd)
}
/* May be called from interrupt context so must not sleep. */
-void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
+void target_complete_cmd_with_sense(struct se_cmd *cmd, u8 scsi_status,
+ sense_reason_t sense_reason)
{
struct se_wwn *wwn = cmd->se_sess->se_tpg->se_tpg_wwn;
int success, cpu;
@@ -865,6 +865,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
return;
cmd->scsi_status = scsi_status;
+ cmd->sense_reason = sense_reason;
spin_lock_irqsave(&cmd->t_state_lock, flags);
switch (cmd->scsi_status) {
@@ -893,6 +894,14 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
queue_work_on(cpu, target_completion_wq, &cmd->work);
}
+EXPORT_SYMBOL(target_complete_cmd_with_sense);
+
+void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
+{
+ target_complete_cmd_with_sense(cmd, scsi_status, scsi_status ?
+ TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE :
+ TCM_NO_SENSE);
+}
EXPORT_SYMBOL(target_complete_cmd);
void target_set_cmd_data_length(struct se_cmd *cmd, int length)
@@ -2003,7 +2012,6 @@ void transport_generic_request_failure(struct se_cmd *cmd,
case TCM_ADDRESS_OUT_OF_RANGE:
case TCM_CHECK_CONDITION_ABORT_CMD:
case TCM_CHECK_CONDITION_UNIT_ATTENTION:
- case TCM_CHECK_CONDITION_NOT_READY:
case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
@@ -2013,6 +2021,10 @@ void transport_generic_request_failure(struct se_cmd *cmd,
case TCM_TOO_MANY_SEGMENT_DESCS:
case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE:
case TCM_INVALID_FIELD_IN_COMMAND_IU:
+ case TCM_ALUA_TG_PT_STANDBY:
+ case TCM_ALUA_TG_PT_UNAVAILABLE:
+ case TCM_ALUA_STATE_TRANSITION:
+ case TCM_ALUA_OFFLINE:
break;
case TCM_OUT_OF_RESOURCES:
cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
@@ -3277,9 +3289,6 @@ static const struct sense_detail sense_detail_table[] = {
[TCM_CHECK_CONDITION_UNIT_ATTENTION] = {
.key = UNIT_ATTENTION,
},
- [TCM_CHECK_CONDITION_NOT_READY] = {
- .key = NOT_READY,
- },
[TCM_MISCOMPARE_VERIFY] = {
.key = MISCOMPARE,
.asc = 0x1d, /* MISCOMPARE DURING VERIFY OPERATION */
@@ -3340,6 +3349,26 @@ static const struct sense_detail sense_detail_table[] = {
.asc = 0x0e,
.ascq = 0x03, /* INVALID FIELD IN COMMAND INFORMATION UNIT */
},
+ [TCM_ALUA_TG_PT_STANDBY] = {
+ .key = NOT_READY,
+ .asc = 0x04,
+ .ascq = ASCQ_04H_ALUA_TG_PT_STANDBY,
+ },
+ [TCM_ALUA_TG_PT_UNAVAILABLE] = {
+ .key = NOT_READY,
+ .asc = 0x04,
+ .ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE,
+ },
+ [TCM_ALUA_STATE_TRANSITION] = {
+ .key = NOT_READY,
+ .asc = 0x04,
+ .ascq = ASCQ_04H_ALUA_STATE_TRANSITION,
+ },
+ [TCM_ALUA_OFFLINE] = {
+ .key = NOT_READY,
+ .asc = 0x04,
+ .ascq = ASCQ_04H_ALUA_OFFLINE,
+ },
};
/**
@@ -3374,11 +3403,8 @@ static void translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason)
cmd->scsi_status = SAM_STAT_BUSY;
return;
}
- } else if (sd->asc == 0) {
- WARN_ON_ONCE(cmd->scsi_asc == 0);
- asc = cmd->scsi_asc;
- ascq = cmd->scsi_ascq;
} else {
+ WARN_ON_ONCE(sd->asc == 0);
asc = sd->asc;
ascq = sd->ascq;
}
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index fbb6ffaddfbe..9f552f48084c 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -191,6 +191,7 @@ struct tcmu_cmd {
unsigned long deadline;
#define TCMU_CMD_BIT_EXPIRED 0
+#define TCMU_CMD_BIT_KEEP_BUF 1
unsigned long flags;
};
@@ -1315,11 +1316,13 @@ unlock:
mutex_unlock(&udev->cmdr_lock);
}
-static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *entry)
+static bool tcmu_handle_completion(struct tcmu_cmd *cmd,
+ struct tcmu_cmd_entry *entry, bool keep_buf)
{
struct se_cmd *se_cmd = cmd->se_cmd;
struct tcmu_dev *udev = cmd->tcmu_dev;
bool read_len_valid = false;
+ bool ret = true;
uint32_t read_len;
/*
@@ -1330,6 +1333,13 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
WARN_ON_ONCE(se_cmd);
goto out;
}
+ if (test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
+ pr_err("cmd_id %u already completed with KEEP_BUF, ring is broken\n",
+ entry->hdr.cmd_id);
+ set_bit(TCMU_DEV_BIT_BROKEN, &udev->flags);
+ ret = false;
+ goto out;
+ }
list_del_init(&cmd->queue_entry);
@@ -1379,8 +1389,22 @@ done:
target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status);
out:
- tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
- tcmu_free_cmd(cmd);
+ if (!keep_buf) {
+ tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
+ tcmu_free_cmd(cmd);
+ } else {
+ /*
+ * Keep this command after completion, since userspace still
+ * needs the data buffer. Mark it with TCMU_CMD_BIT_KEEP_BUF
+ * and reset potential TCMU_CMD_BIT_EXPIRED, so we don't accept
+ * a second completion later.
+ * Userspace can free the buffer later by writing the cmd_id
+ * to new action attribute free_kept_buf.
+ */
+ clear_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags);
+ set_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags);
+ }
+ return ret;
}
static int tcmu_run_tmr_queue(struct tcmu_dev *udev)
@@ -1432,6 +1456,7 @@ static bool tcmu_handle_completions(struct tcmu_dev *udev)
while (udev->cmdr_last_cleaned != READ_ONCE(mb->cmd_tail)) {
struct tcmu_cmd_entry *entry = udev->cmdr + udev->cmdr_last_cleaned;
+ bool keep_buf;
/*
* Flush max. up to end of cmd ring since current entry might
@@ -1453,7 +1478,11 @@ static bool tcmu_handle_completions(struct tcmu_dev *udev)
}
WARN_ON(tcmu_hdr_get_op(entry->hdr.len_op) != TCMU_OP_CMD);
- cmd = xa_erase(&udev->commands, entry->hdr.cmd_id);
+ keep_buf = !!(entry->hdr.uflags & TCMU_UFLAG_KEEP_BUF);
+ if (keep_buf)
+ cmd = xa_load(&udev->commands, entry->hdr.cmd_id);
+ else
+ cmd = xa_erase(&udev->commands, entry->hdr.cmd_id);
if (!cmd) {
pr_err("cmd_id %u not found, ring is broken\n",
entry->hdr.cmd_id);
@@ -1461,7 +1490,8 @@ static bool tcmu_handle_completions(struct tcmu_dev *udev)
return false;
}
- tcmu_handle_completion(cmd, entry);
+ if (!tcmu_handle_completion(cmd, entry, keep_buf))
+ break;
UPDATE_HEAD(udev->cmdr_last_cleaned,
tcmu_hdr_get_len(entry->hdr.len_op),
@@ -1619,7 +1649,8 @@ static void tcmu_dev_call_rcu(struct rcu_head *p)
static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd)
{
- if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+ if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags) ||
+ test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
kmem_cache_free(tcmu_cmd_cache, cmd);
return 0;
}
@@ -1903,6 +1934,38 @@ static int tcmu_open(struct uio_info *info, struct inode *inode)
static int tcmu_release(struct uio_info *info, struct inode *inode)
{
struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info);
+ struct tcmu_cmd *cmd;
+ unsigned long i;
+ bool freed = false;
+
+ mutex_lock(&udev->cmdr_lock);
+
+ xa_for_each(&udev->commands, i, cmd) {
+ /* Cmds with KEEP_BUF set are no longer on the ring, but
+ * userspace still holds the data buffer. If userspace closes
+ * we implicitly free these cmds and buffers, since after new
+ * open the (new ?) userspace cannot find the cmd in the ring
+ * and thus never will release the buffer by writing cmd_id to
+ * free_kept_buf action attribute.
+ */
+ if (!test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags))
+ continue;
+ pr_debug("removing KEEP_BUF cmd %u on dev %s from ring\n",
+ cmd->cmd_id, udev->name);
+ freed = true;
+
+ xa_erase(&udev->commands, i);
+ tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
+ tcmu_free_cmd(cmd);
+ }
+ /*
+ * We only freed data space, not ring space. Therefore we dont call
+ * run_tmr_queue, but call run_qfull_queue if tmr_list is empty.
+ */
+ if (freed && list_empty(&udev->tmr_queue))
+ run_qfull_queue(udev, false);
+
+ mutex_unlock(&udev->cmdr_lock);
clear_bit(TCMU_DEV_BIT_OPEN, &udev->flags);
@@ -2147,7 +2210,8 @@ static int tcmu_configure_device(struct se_device *dev)
mb->version = TCMU_MAILBOX_VERSION;
mb->flags = TCMU_MAILBOX_FLAG_CAP_OOOC |
TCMU_MAILBOX_FLAG_CAP_READ_LEN |
- TCMU_MAILBOX_FLAG_CAP_TMR;
+ TCMU_MAILBOX_FLAG_CAP_TMR |
+ TCMU_MAILBOX_FLAG_CAP_KEEP_BUF;
mb->cmdr_off = CMDR_OFF;
mb->cmdr_size = udev->cmdr_size;
@@ -2279,12 +2343,16 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
mutex_lock(&udev->cmdr_lock);
xa_for_each(&udev->commands, i, cmd) {
- pr_debug("removing cmd %u on dev %s from ring (is expired %d)\n",
- cmd->cmd_id, udev->name,
- test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags));
+ pr_debug("removing cmd %u on dev %s from ring %s\n",
+ cmd->cmd_id, udev->name,
+ test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags) ?
+ "(is expired)" :
+ (test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags) ?
+ "(is keep buffer)" : ""));
xa_erase(&udev->commands, i);
- if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+ if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags) &&
+ !test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
WARN_ON(!cmd->se_cmd);
list_del_init(&cmd->queue_entry);
cmd->se_cmd->priv = NULL;
@@ -2933,6 +3001,65 @@ static ssize_t tcmu_reset_ring_store(struct config_item *item, const char *page,
}
CONFIGFS_ATTR_WO(tcmu_, reset_ring);
+static ssize_t tcmu_free_kept_buf_store(struct config_item *item, const char *page,
+ size_t count)
+{
+ struct se_device *se_dev = container_of(to_config_group(item),
+ struct se_device,
+ dev_action_group);
+ struct tcmu_dev *udev = TCMU_DEV(se_dev);
+ struct tcmu_cmd *cmd;
+ u16 cmd_id;
+ int ret;
+
+ if (!target_dev_configured(&udev->se_dev)) {
+ pr_err("Device is not configured.\n");
+ return -EINVAL;
+ }
+
+ ret = kstrtou16(page, 0, &cmd_id);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&udev->cmdr_lock);
+
+ {
+ XA_STATE(xas, &udev->commands, cmd_id);
+
+ xas_lock(&xas);
+ cmd = xas_load(&xas);
+ if (!cmd) {
+ pr_err("free_kept_buf: cmd_id %d not found\n", cmd_id);
+ count = -EINVAL;
+ xas_unlock(&xas);
+ goto out_unlock;
+ }
+ if (!test_bit(TCMU_CMD_BIT_KEEP_BUF, &cmd->flags)) {
+ pr_err("free_kept_buf: cmd_id %d was not completed with KEEP_BUF\n",
+ cmd_id);
+ count = -EINVAL;
+ xas_unlock(&xas);
+ goto out_unlock;
+ }
+ xas_store(&xas, NULL);
+ xas_unlock(&xas);
+ }
+
+ tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
+ tcmu_free_cmd(cmd);
+ /*
+ * We only freed data space, not ring space. Therefore we dont call
+ * run_tmr_queue, but call run_qfull_queue if tmr_list is empty.
+ */
+ if (list_empty(&udev->tmr_queue))
+ run_qfull_queue(udev, false);
+
+out_unlock:
+ mutex_unlock(&udev->cmdr_lock);
+ return count;
+}
+CONFIGFS_ATTR_WO(tcmu_, free_kept_buf);
+
static struct configfs_attribute *tcmu_attrib_attrs[] = {
&tcmu_attr_cmd_time_out,
&tcmu_attr_qfull_time_out,
@@ -2951,6 +3078,7 @@ static struct configfs_attribute **tcmu_attrs;
static struct configfs_attribute *tcmu_action_attrs[] = {
&tcmu_attr_block_dev,
&tcmu_attr_reset_ring,
+ &tcmu_attr_free_kept_buf,
NULL,
};
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 0f1319336f3e..d4fe7cb2bd00 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -674,12 +674,16 @@ static void target_xcopy_do_work(struct work_struct *work)
unsigned int max_sectors;
int rc = 0;
unsigned short nolb, max_nolb, copied_nolb = 0;
+ sense_reason_t sense_rc;
- if (target_parse_xcopy_cmd(xop) != TCM_NO_SENSE)
+ sense_rc = target_parse_xcopy_cmd(xop);
+ if (sense_rc != TCM_NO_SENSE)
goto err_free;
- if (WARN_ON_ONCE(!xop->src_dev) || WARN_ON_ONCE(!xop->dst_dev))
+ if (WARN_ON_ONCE(!xop->src_dev) || WARN_ON_ONCE(!xop->dst_dev)) {
+ sense_rc = TCM_INVALID_PARAMETER_LIST;
goto err_free;
+ }
src_dev = xop->src_dev;
dst_dev = xop->dst_dev;
@@ -762,20 +766,20 @@ static void target_xcopy_do_work(struct work_struct *work)
return;
out:
+ /*
+ * The XCOPY command was aborted after some data was transferred.
+ * Terminate command with CHECK CONDITION status, with the sense key
+ * set to COPY ABORTED.
+ */
+ sense_rc = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
xcopy_pt_undepend_remotedev(xop);
target_free_sgl(xop->xop_data_sg, xop->xop_data_nents);
err_free:
kfree(xop);
- /*
- * Don't override an error scsi status if it has already been set
- */
- if (ec_cmd->scsi_status == SAM_STAT_GOOD) {
- pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY"
- " CHECK_CONDITION -> sending response\n", rc);
- ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
- }
- target_complete_cmd(ec_cmd, ec_cmd->scsi_status);
+ pr_warn_ratelimited("target_xcopy_do_work: rc: %d, sense: %u, XCOPY operation failed\n",
+ rc, sense_rc);
+ target_complete_cmd_with_sense(ec_cmd, SAM_STAT_CHECK_CONDITION, sense_rc);
}
/*
diff --git a/drivers/thermal/intel/Kconfig b/drivers/thermal/intel/Kconfig
index e4299ca3423c..c83ea5d04a1d 100644
--- a/drivers/thermal/intel/Kconfig
+++ b/drivers/thermal/intel/Kconfig
@@ -90,3 +90,12 @@ config INTEL_TCC_COOLING
Note that, on different platforms, the behavior might be different
on how fast the setting takes effect, and how much the CPU frequency
is reduced.
+
+config INTEL_MENLOW
+ tristate "Thermal Management driver for Intel menlow platform"
+ depends on ACPI_THERMAL
+ help
+ ACPI thermal management enhancement driver on
+ Intel Menlow platform.
+
+ If unsure, say N.
diff --git a/drivers/thermal/intel/Makefile b/drivers/thermal/intel/Makefile
index 5ff2afa388f7..960b56268b4a 100644
--- a/drivers/thermal/intel/Makefile
+++ b/drivers/thermal/intel/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
obj-$(CONFIG_INTEL_TCC_COOLING) += intel_tcc_cooling.o
obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
+obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/thermal/intel/intel_menlow.c
index 101d7e791a13..101d7e791a13 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/thermal/intel/intel_menlow.c
diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
index a062befcb3b2..7018d959f775 100644
--- a/drivers/thunderbolt/domain.c
+++ b/drivers/thunderbolt/domain.c
@@ -86,7 +86,7 @@ static int tb_service_probe(struct device *dev)
return driver->probe(svc, id);
}
-static int tb_service_remove(struct device *dev)
+static void tb_service_remove(struct device *dev)
{
struct tb_service *svc = tb_to_service(dev);
struct tb_service_driver *driver;
@@ -94,8 +94,6 @@ static int tb_service_remove(struct device *dev)
driver = container_of(dev->driver, struct tb_service_driver, driver);
if (driver->remove)
driver->remove(svc);
-
- return 0;
}
static void tb_service_shutdown(struct device *dev)
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index fa44332845a1..c73da0532be4 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -35,6 +35,8 @@
#define NHI_MAILBOX_TIMEOUT 500 /* ms */
+#define QUIRK_AUTO_CLEAR_INT BIT(0)
+
static int ring_interrupt_index(struct tb_ring *ring)
{
int bit = ring->hop;
@@ -66,14 +68,17 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
else
index = ring->hop + ring->nhi->hop_count;
- /*
- * Ask the hardware to clear interrupt status bits automatically
- * since we already know which interrupt was triggered.
- */
- misc = ioread32(ring->nhi->iobase + REG_DMA_MISC);
- if (!(misc & REG_DMA_MISC_INT_AUTO_CLEAR)) {
- misc |= REG_DMA_MISC_INT_AUTO_CLEAR;
- iowrite32(misc, ring->nhi->iobase + REG_DMA_MISC);
+ if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT) {
+ /*
+ * Ask the hardware to clear interrupt status
+ * bits automatically since we already know
+ * which interrupt was triggered.
+ */
+ misc = ioread32(ring->nhi->iobase + REG_DMA_MISC);
+ if (!(misc & REG_DMA_MISC_INT_AUTO_CLEAR)) {
+ misc |= REG_DMA_MISC_INT_AUTO_CLEAR;
+ iowrite32(misc, ring->nhi->iobase + REG_DMA_MISC);
+ }
}
ivr_base = ring->nhi->iobase + REG_INT_VEC_ALLOC_BASE;
@@ -377,11 +382,24 @@ void tb_ring_poll_complete(struct tb_ring *ring)
}
EXPORT_SYMBOL_GPL(tb_ring_poll_complete);
+static void ring_clear_msix(const struct tb_ring *ring)
+{
+ if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT)
+ return;
+
+ if (ring->is_tx)
+ ioread32(ring->nhi->iobase + REG_RING_NOTIFY_BASE);
+ else
+ ioread32(ring->nhi->iobase + REG_RING_NOTIFY_BASE +
+ 4 * (ring->nhi->hop_count / 32));
+}
+
static irqreturn_t ring_msix(int irq, void *data)
{
struct tb_ring *ring = data;
spin_lock(&ring->nhi->lock);
+ ring_clear_msix(ring);
spin_lock(&ring->lock);
__ring_interrupt(ring);
spin_unlock(&ring->lock);
@@ -1074,6 +1092,16 @@ static void nhi_shutdown(struct tb_nhi *nhi)
nhi->ops->shutdown(nhi);
}
+static void nhi_check_quirks(struct tb_nhi *nhi)
+{
+ /*
+ * Intel hardware supports auto clear of the interrupt status
+ * reqister right after interrupt is being issued.
+ */
+ if (nhi->pdev->vendor == PCI_VENDOR_ID_INTEL)
+ nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
+}
+
static int nhi_init_msi(struct tb_nhi *nhi)
{
struct pci_dev *pdev = nhi->pdev;
@@ -1190,6 +1218,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!nhi->tx_rings || !nhi->rx_rings)
return -ENOMEM;
+ nhi_check_quirks(nhi);
+
res = nhi_init_msi(nhi);
if (res) {
dev_err(&pdev->dev, "cannot enable MSI, aborting\n");
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 10d6b228cc94..3014146081c1 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -724,6 +724,12 @@ static int tb_init_port(struct tb_port *port)
int res;
int cap;
+ INIT_LIST_HEAD(&port->list);
+
+ /* Control adapter does not have configuration space */
+ if (!port->port)
+ return 0;
+
res = tb_port_read(port, &port->config, TB_CFG_PORT, 0, 8);
if (res) {
if (res == -ENODEV) {
@@ -736,7 +742,7 @@ static int tb_init_port(struct tb_port *port)
}
/* Port 0 is the switch itself and has no PHY. */
- if (port->config.type == TB_TYPE_PORT && port->port != 0) {
+ if (port->config.type == TB_TYPE_PORT) {
cap = tb_port_find_cap(port, TB_PORT_CAP_PHY);
if (cap > 0)
@@ -762,7 +768,7 @@ static int tb_init_port(struct tb_port *port)
if (!port->ctl_credits)
port->ctl_credits = 2;
- } else if (port->port != 0) {
+ } else {
cap = tb_port_find_cap(port, TB_PORT_CAP_ADAP);
if (cap > 0)
port->cap_adap = cap;
@@ -773,10 +779,7 @@ static int tb_init_port(struct tb_port *port)
ADP_CS_4_TOTAL_BUFFERS_SHIFT;
tb_dump_port(port->sw->tb, port);
-
- INIT_LIST_HEAD(&port->list);
return 0;
-
}
static int tb_port_alloc_hopid(struct tb_port *port, bool in, int min_hopid,
@@ -1498,6 +1501,7 @@ static ssize_t authorized_show(struct device *dev,
static int disapprove_switch(struct device *dev, void *not_used)
{
+ char *envp[] = { "AUTHORIZED=0", NULL };
struct tb_switch *sw;
sw = tb_to_switch(dev);
@@ -1514,7 +1518,7 @@ static int disapprove_switch(struct device *dev, void *not_used)
return ret;
sw->authorized = 0;
- kobject_uevent(&sw->dev.kobj, KOBJ_CHANGE);
+ kobject_uevent_env(&sw->dev.kobj, KOBJ_CHANGE, envp);
}
return 0;
@@ -1522,7 +1526,9 @@ static int disapprove_switch(struct device *dev, void *not_used)
static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val)
{
+ char envp_string[13];
int ret = -EINVAL;
+ char *envp[] = { envp_string, NULL };
if (!mutex_trylock(&sw->tb->lock))
return restart_syscall();
@@ -1559,8 +1565,12 @@ static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val)
if (!ret) {
sw->authorized = val;
- /* Notify status change to the userspace */
- kobject_uevent(&sw->dev.kobj, KOBJ_CHANGE);
+ /*
+ * Notify status change to the userspace, informing the new
+ * value of /sys/bus/thunderbolt/devices/.../authorized.
+ */
+ sprintf(envp_string, "AUTHORIZED=%u", sw->authorized);
+ kobject_uevent_env(&sw->dev.kobj, KOBJ_CHANGE, envp);
}
unlock:
@@ -2443,7 +2453,7 @@ static void tb_switch_default_link_ports(struct tb_switch *sw)
{
int i;
- for (i = 1; i <= sw->config.max_port_number; i += 2) {
+ for (i = 1; i <= sw->config.max_port_number; i++) {
struct tb_port *port = &sw->ports[i];
struct tb_port *subordinate;
diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c
index eca0ef311bde..1f69bab236ee 100644
--- a/drivers/thunderbolt/test.c
+++ b/drivers/thunderbolt/test.c
@@ -2206,23 +2206,13 @@ static void tb_test_credit_alloc_dma_multiple(struct kunit *test)
tb_tunnel_free(tunnel2);
}
-static void tb_test_credit_alloc_all(struct kunit *test)
+static struct tb_tunnel *TB_TEST_PCIE_TUNNEL(struct kunit *test,
+ struct tb_switch *host, struct tb_switch *dev)
{
- struct tb_port *up, *down, *in, *out, *nhi, *port;
- struct tb_tunnel *pcie_tunnel, *dp_tunnel1, *dp_tunnel2, *usb3_tunnel;
- struct tb_tunnel *dma_tunnel1, *dma_tunnel2;
- struct tb_switch *host, *dev;
+ struct tb_port *up, *down;
+ struct tb_tunnel *pcie_tunnel;
struct tb_path *path;
- /*
- * Create PCIe, 2 x DP, USB 3.x and two DMA tunnels from host to
- * device. Expectation is that all these can be established with
- * the default credit allocation found in Intel hardware.
- */
-
- host = alloc_host_usb4(test);
- dev = alloc_dev_usb4(test, host, 0x1, true);
-
down = &host->ports[8];
up = &dev->ports[9];
pcie_tunnel = tb_tunnel_alloc_pci(NULL, up, down);
@@ -2243,9 +2233,18 @@ static void tb_test_credit_alloc_all(struct kunit *test)
KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U);
KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 64U);
+ return pcie_tunnel;
+}
+
+static struct tb_tunnel *TB_TEST_DP_TUNNEL1(struct kunit *test,
+ struct tb_switch *host, struct tb_switch *dev)
+{
+ struct tb_port *in, *out;
+ struct tb_tunnel *dp_tunnel1;
+ struct tb_path *path;
+
in = &host->ports[5];
out = &dev->ports[13];
-
dp_tunnel1 = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
KUNIT_ASSERT_TRUE(test, dp_tunnel1 != NULL);
KUNIT_ASSERT_EQ(test, dp_tunnel1->npaths, (size_t)3);
@@ -2271,9 +2270,18 @@ static void tb_test_credit_alloc_all(struct kunit *test)
KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U);
KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U);
+ return dp_tunnel1;
+}
+
+static struct tb_tunnel *TB_TEST_DP_TUNNEL2(struct kunit *test,
+ struct tb_switch *host, struct tb_switch *dev)
+{
+ struct tb_port *in, *out;
+ struct tb_tunnel *dp_tunnel2;
+ struct tb_path *path;
+
in = &host->ports[6];
out = &dev->ports[14];
-
dp_tunnel2 = tb_tunnel_alloc_dp(NULL, in, out, 0, 0);
KUNIT_ASSERT_TRUE(test, dp_tunnel2 != NULL);
KUNIT_ASSERT_EQ(test, dp_tunnel2->npaths, (size_t)3);
@@ -2299,6 +2307,16 @@ static void tb_test_credit_alloc_all(struct kunit *test)
KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U);
KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U);
+ return dp_tunnel2;
+}
+
+static struct tb_tunnel *TB_TEST_USB3_TUNNEL(struct kunit *test,
+ struct tb_switch *host, struct tb_switch *dev)
+{
+ struct tb_port *up, *down;
+ struct tb_tunnel *usb3_tunnel;
+ struct tb_path *path;
+
down = &host->ports[12];
up = &dev->ports[16];
usb3_tunnel = tb_tunnel_alloc_usb3(NULL, up, down, 0, 0);
@@ -2319,9 +2337,18 @@ static void tb_test_credit_alloc_all(struct kunit *test)
KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U);
KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U);
+ return usb3_tunnel;
+}
+
+static struct tb_tunnel *TB_TEST_DMA_TUNNEL1(struct kunit *test,
+ struct tb_switch *host, struct tb_switch *dev)
+{
+ struct tb_port *nhi, *port;
+ struct tb_tunnel *dma_tunnel1;
+ struct tb_path *path;
+
nhi = &host->ports[7];
port = &dev->ports[3];
-
dma_tunnel1 = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1);
KUNIT_ASSERT_TRUE(test, dma_tunnel1 != NULL);
KUNIT_ASSERT_EQ(test, dma_tunnel1->npaths, (size_t)2);
@@ -2340,6 +2367,18 @@ static void tb_test_credit_alloc_all(struct kunit *test)
KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U);
KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U);
+ return dma_tunnel1;
+}
+
+static struct tb_tunnel *TB_TEST_DMA_TUNNEL2(struct kunit *test,
+ struct tb_switch *host, struct tb_switch *dev)
+{
+ struct tb_port *nhi, *port;
+ struct tb_tunnel *dma_tunnel2;
+ struct tb_path *path;
+
+ nhi = &host->ports[7];
+ port = &dev->ports[3];
dma_tunnel2 = tb_tunnel_alloc_dma(NULL, nhi, port, 9, 2, 9, 2);
KUNIT_ASSERT_TRUE(test, dma_tunnel2 != NULL);
KUNIT_ASSERT_EQ(test, dma_tunnel2->npaths, (size_t)2);
@@ -2358,6 +2397,31 @@ static void tb_test_credit_alloc_all(struct kunit *test)
KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U);
KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U);
+ return dma_tunnel2;
+}
+
+static void tb_test_credit_alloc_all(struct kunit *test)
+{
+ struct tb_tunnel *pcie_tunnel, *dp_tunnel1, *dp_tunnel2, *usb3_tunnel;
+ struct tb_tunnel *dma_tunnel1, *dma_tunnel2;
+ struct tb_switch *host, *dev;
+
+ /*
+ * Create PCIe, 2 x DP, USB 3.x and two DMA tunnels from host to
+ * device. Expectation is that all these can be established with
+ * the default credit allocation found in Intel hardware.
+ */
+
+ host = alloc_host_usb4(test);
+ dev = alloc_dev_usb4(test, host, 0x1, true);
+
+ pcie_tunnel = TB_TEST_PCIE_TUNNEL(test, host, dev);
+ dp_tunnel1 = TB_TEST_DP_TUNNEL1(test, host, dev);
+ dp_tunnel2 = TB_TEST_DP_TUNNEL2(test, host, dev);
+ usb3_tunnel = TB_TEST_USB3_TUNNEL(test, host, dev);
+ dma_tunnel1 = TB_TEST_DMA_TUNNEL1(test, host, dev);
+ dma_tunnel2 = TB_TEST_DMA_TUNNEL2(test, host, dev);
+
tb_tunnel_free(dma_tunnel2);
tb_tunnel_free(dma_tunnel1);
tb_tunnel_free(usb3_tunnel);
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 5ec19c48fb7a..1e60dbef676c 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -22,8 +22,6 @@
*
*/
-#include <linux/delay.h>
-
/* Set of debugging defines */
#undef SERIAL_DEBUG_INTR
@@ -31,55 +29,42 @@
#undef SERIAL_DEBUG_FLOW
#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-/* Sanity checks */
-
-#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
-#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- tty->name, (info->tport.flags), serial_driver->refcount,info->count,tty->count,s)
-#else
-#define DBG_CNT(s)
-#endif
-
/*
* End of serial driver configuration section.
*/
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-static char *serial_version = "4.30";
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
+#include <linux/bitops.h>
#include <linux/circ_buf.h>
#include <linux/console.h>
-#include <linux/major.h>
-#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
#include <linux/fcntl.h>
-#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/ptrace.h>
#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/platform_device.h>
-
-#include <asm/setup.h>
-
-
-#include <asm/irq.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/tty_flip.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
struct serial_state {
struct tty_port tport;
@@ -88,7 +73,6 @@ struct serial_state {
unsigned long port;
int baud_base;
- int xmit_fifo_size;
int custom_divisor;
int read_status_mask;
int ignore_status_mask;
@@ -99,14 +83,13 @@ struct serial_state {
int x_char; /* xon/xoff character */
};
-#define custom amiga_custom
-static char *serial_name = "Amiga-builtin serial driver";
-
static struct tty_driver *serial_driver;
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
+#define XMIT_FIFO_SIZE 1
+
static unsigned char current_ctl_bits;
static void change_speed(struct tty_struct *tty, struct serial_state *info,
@@ -114,13 +97,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-static struct serial_state rs_table[1];
-
-#define NR_PORTS ARRAY_SIZE(rs_table)
-
-#include <linux/uaccess.h>
-
-#define serial_isroot() (capable(CAP_SYS_ADMIN))
+static struct serial_state serial_state;
/* some serial hardware definitions */
#define SDR_OVRUN (1<<15)
@@ -161,9 +138,9 @@ static void rs_stop(struct tty_struct *tty)
if (info->IER & UART_IER_THRI) {
info->IER &= ~UART_IER_THRI;
/* disable Tx interrupt and remove any pending interrupts */
- custom.intena = IF_TBE;
+ amiga_custom.intena = IF_TBE;
mb();
- custom.intreq = IF_TBE;
+ amiga_custom.intreq = IF_TBE;
mb();
}
local_irq_restore(flags);
@@ -179,10 +156,10 @@ static void rs_start(struct tty_struct *tty)
&& info->xmit.buf
&& !(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
- custom.intena = IF_SETCLR | IF_TBE;
+ amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
- custom.intreq = IF_SETCLR | IF_TBE;
+ amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
}
local_irq_restore(flags);
@@ -191,21 +168,8 @@ static void rs_start(struct tty_struct *tty)
/*
* ----------------------------------------------------------------------
*
- * Here starts the interrupt handling routines. All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt(). They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off. People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible. After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
+ * Here start the interrupt handling routines.
*
- * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
* -----------------------------------------------------------------------
*/
@@ -220,9 +184,9 @@ static void receive_chars(struct serial_state *info)
icount = &info->icount;
status = UART_LSR_DR; /* We obviously have a character! */
- serdatr = custom.serdatr;
+ serdatr = amiga_custom.serdatr;
mb();
- custom.intreq = IF_RBF;
+ amiga_custom.intreq = IF_RBF;
mb();
if((serdatr & 0x1ff) == 0)
@@ -299,10 +263,10 @@ out:
static void transmit_chars(struct serial_state *info)
{
- custom.intreq = IF_TBE;
+ amiga_custom.intreq = IF_TBE;
mb();
if (info->x_char) {
- custom.serdat = info->x_char | 0x100;
+ amiga_custom.serdat = info->x_char | 0x100;
mb();
info->icount.tx++;
info->x_char = 0;
@@ -312,12 +276,12 @@ static void transmit_chars(struct serial_state *info)
|| info->tport.tty->flow.stopped
|| info->tport.tty->hw_stopped) {
info->IER &= ~UART_IER_THRI;
- custom.intena = IF_TBE;
+ amiga_custom.intena = IF_TBE;
mb();
return;
}
- custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
+ amiga_custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
mb();
info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
info->icount.tx++;
@@ -331,7 +295,7 @@ static void transmit_chars(struct serial_state *info)
printk("THRE...");
#endif
if (info->xmit.head == info->xmit.tail) {
- custom.intena = IF_TBE;
+ amiga_custom.intena = IF_TBE;
mb();
info->IER &= ~UART_IER_THRI;
}
@@ -384,10 +348,10 @@ static void check_modem_status(struct serial_state *info)
#endif
port->tty->hw_stopped = 0;
info->IER |= UART_IER_THRI;
- custom.intena = IF_SETCLR | IF_TBE;
+ amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
- custom.intreq = IF_SETCLR | IF_TBE;
+ amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
tty_wakeup(port->tty);
return;
@@ -400,9 +364,9 @@ static void check_modem_status(struct serial_state *info)
port->tty->hw_stopped = 1;
info->IER &= ~UART_IER_THRI;
/* disable Tx interrupt and remove any pending interrupts */
- custom.intena = IF_TBE;
+ amiga_custom.intena = IF_TBE;
mb();
- custom.intreq = IF_TBE;
+ amiga_custom.intreq = IF_TBE;
mb();
}
}
@@ -444,7 +408,7 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id)
{
struct serial_state *info = dev_id;
- if (custom.serdatr & SDR_TBE) {
+ if (amiga_custom.serdatr & SDR_TBE) {
#ifdef SERIAL_DEBUG_INTR
printk("ser_tx_int...");
#endif
@@ -504,20 +468,20 @@ static int startup(struct tty_struct *tty, struct serial_state *info)
/* Clear anything in the input buffer */
- custom.intreq = IF_RBF;
+ amiga_custom.intreq = IF_RBF;
mb();
retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info);
if (retval) {
- if (serial_isroot()) {
- set_bit(TTY_IO_ERROR, &tty->flags);
- retval = 0;
- }
- goto errout;
+ if (capable(CAP_SYS_ADMIN)) {
+ set_bit(TTY_IO_ERROR, &tty->flags);
+ retval = 0;
+ }
+ goto errout;
}
/* enable both Rx and Tx interrupts */
- custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
+ amiga_custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
mb();
info->IER = UART_IER_MSI;
@@ -553,13 +517,10 @@ errout:
static void shutdown(struct tty_struct *tty, struct serial_state *info)
{
unsigned long flags;
- struct serial_state *state;
if (!tty_port_initialized(&info->tport))
return;
- state = info;
-
#ifdef SERIAL_DEBUG_OPEN
printk("Shutting down serial port %d ....\n", info->line);
#endif
@@ -583,11 +544,11 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info)
}
info->IER = 0;
- custom.intena = IF_RBF | IF_TBE;
+ amiga_custom.intena = IF_RBF | IF_TBE;
mb();
/* disable break condition */
- custom.adkcon = AC_UARTBRK;
+ amiga_custom.adkcon = AC_UARTBRK;
mb();
if (C_HUPCL(tty))
@@ -671,7 +632,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
if (!quot)
quot = baud_base / 9600;
info->quot = quot;
- info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
+ info->timeout = (XMIT_FIFO_SIZE*HZ*bits*quot) / baud_base;
info->timeout += HZ/50; /* Add .02 seconds of slop */
/* CTS flow control flag and modem status interrupts */
@@ -731,7 +692,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
if(cval & UART_LCR_PARITY)
serper |= (SERPER_PARENB);
- custom.serper = serper;
+ amiga_custom.serper = serper;
mb();
}
@@ -775,10 +736,10 @@ static void rs_flush_chars(struct tty_struct *tty)
local_irq_save(flags);
info->IER |= UART_IER_THRI;
- custom.intena = IF_SETCLR | IF_TBE;
+ amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
- custom.intreq = IF_SETCLR | IF_TBE;
+ amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
local_irq_restore(flags);
}
@@ -817,10 +778,10 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
&& !(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
local_irq_disable();
- custom.intena = IF_SETCLR | IF_TBE;
+ amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
- custom.intreq = IF_SETCLR | IF_TBE;
+ amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
local_irq_restore(flags);
}
@@ -867,11 +828,11 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
/* Check this ! */
local_irq_save(flags);
- if(!(custom.intenar & IF_TBE)) {
- custom.intena = IF_SETCLR | IF_TBE;
+ if(!(amiga_custom.intenar & IF_TBE)) {
+ amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
- custom.intreq = IF_SETCLR | IF_TBE;
+ amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
}
local_irq_restore(flags);
@@ -948,7 +909,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
ss->line = tty->index;
ss->port = state->port;
ss->flags = state->tport.flags;
- ss->xmit_fifo_size = state->xmit_fifo_size;
+ ss->xmit_fifo_size = XMIT_FIFO_SIZE;
ss->baud_base = state->baud_base;
ss->close_delay = close_delay;
ss->closing_wait = closing_wait;
@@ -969,7 +930,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) ||
ss->custom_divisor != state->custom_divisor;
if (ss->irq || ss->port != state->port ||
- ss->xmit_fifo_size != state->xmit_fifo_size) {
+ ss->xmit_fifo_size != XMIT_FIFO_SIZE) {
tty_unlock(tty);
return -EINVAL;
}
@@ -979,11 +940,10 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = msecs_to_jiffies(closing_wait * 10);
- if (!serial_isroot()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((ss->baud_base != state->baud_base) ||
(close_delay != port->close_delay) ||
(closing_wait != port->closing_wait) ||
- (ss->xmit_fifo_size != state->xmit_fifo_size) ||
((ss->flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
tty_unlock(tty);
@@ -1043,7 +1003,7 @@ static int get_lsr_info(struct serial_state *info, unsigned int __user *value)
unsigned long flags;
local_irq_save(flags);
- status = custom.serdatr;
+ status = amiga_custom.serdatr;
mb();
local_irq_restore(flags);
result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0);
@@ -1105,9 +1065,9 @@ static int rs_break(struct tty_struct *tty, int break_state)
local_irq_save(flags);
if (break_state == -1)
- custom.adkcon = AC_SETCLR | AC_UARTBRK;
+ amiga_custom.adkcon = AC_SETCLR | AC_UARTBRK;
else
- custom.adkcon = AC_UARTBRK;
+ amiga_custom.adkcon = AC_UARTBRK;
mb();
local_irq_restore(flags);
return 0;
@@ -1284,10 +1244,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
state->read_status_mask &= ~UART_LSR_DR;
if (tty_port_initialized(port)) {
/* disable receive interrupts */
- custom.intena = IF_RBF;
+ amiga_custom.intena = IF_RBF;
mb();
/* clear any pending receive interrupt */
- custom.intreq = IF_RBF;
+ amiga_custom.intreq = IF_RBF;
mb();
/*
@@ -1315,9 +1275,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
unsigned long orig_jiffies, char_time;
int lsr;
- if (info->xmit_fifo_size == 0)
- return; /* Just in case.... */
-
orig_jiffies = jiffies;
/*
@@ -1328,7 +1285,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
* Note: we have to use pretty tight timings here to satisfy
* the NIST-PCTS.
*/
- char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+ char_time = (info->timeout - HZ/50) / XMIT_FIFO_SIZE;
char_time = char_time / 5;
if (char_time == 0)
char_time = 1;
@@ -1349,7 +1306,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
printk("jiff=%lu...", jiffies);
#endif
- while(!((lsr = custom.serdatr) & SDR_TSRE)) {
+ while(!((lsr = amiga_custom.serdatr) & SDR_TSRE)) {
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("serdatr = %d (jiff=%lu)...", lsr, jiffies);
#endif
@@ -1389,14 +1346,14 @@ static void rs_hangup(struct tty_struct *tty)
*/
static int rs_open(struct tty_struct *tty, struct file * filp)
{
- struct serial_state *info = rs_table + tty->index;
- struct tty_port *port = &info->tport;
+ struct tty_port *port = tty->port;
+ struct serial_state *info = container_of(port, struct serial_state,
+ tport);
int retval;
port->count++;
port->tty = tty;
tty->driver_data = info;
- tty->port = port;
retval = startup(tty, info);
if (retval) {
@@ -1461,8 +1418,8 @@ static inline void line_info(struct seq_file *m, int line,
static int rs_proc_show(struct seq_file *m, void *v)
{
- seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
- line_info(m, 0, &rs_table[0]);
+ seq_printf(m, "serinfo:1.0 driver:4.30\n");
+ line_info(m, 0, &serial_state);
return 0;
}
@@ -1474,17 +1431,6 @@ static int rs_proc_show(struct seq_file *m, void *v)
* ---------------------------------------------------------------------
*/
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static void show_serial_version(void)
-{
- printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-
static const struct tty_operations serial_ops = {
.open = rs_open,
.close = rs_close,
@@ -1543,52 +1489,43 @@ static const struct tty_port_operations amiga_port_ops = {
*/
static int __init amiga_serial_probe(struct platform_device *pdev)
{
+ struct serial_state *state = &serial_state;
+ struct tty_driver *driver;
unsigned long flags;
- struct serial_state * state;
int error;
- serial_driver = alloc_tty_driver(NR_PORTS);
- if (!serial_driver)
- return -ENOMEM;
-
- show_serial_version();
+ driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
/* Initialize the tty_driver structure */
- serial_driver->driver_name = "amiserial";
- serial_driver->name = "ttyS";
- serial_driver->major = TTY_MAJOR;
- serial_driver->minor_start = 64;
- serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver->subtype = SERIAL_TYPE_NORMAL;
- serial_driver->init_termios = tty_std_termios;
- serial_driver->init_termios.c_cflag =
+ driver->driver_name = "amiserial";
+ driver->name = "ttyS";
+ driver->major = TTY_MAJOR;
+ driver->minor_start = 64;
+ driver->type = TTY_DRIVER_TYPE_SERIAL;
+ driver->subtype = SERIAL_TYPE_NORMAL;
+ driver->init_termios = tty_std_termios;
+ driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(serial_driver, &serial_ops);
-
- state = rs_table;
- state->port = (int)&custom.serdatr; /* Just to give it a value */
- state->custom_divisor = 0;
- state->icount.cts = state->icount.dsr =
- state->icount.rng = state->icount.dcd = 0;
- state->icount.rx = state->icount.tx = 0;
- state->icount.frame = state->icount.parity = 0;
- state->icount.overrun = state->icount.brk = 0;
+ tty_set_operations(driver, &serial_ops);
+
+ memset(state, 0, sizeof(*state));
+ state->port = (int)&amiga_custom.serdatr; /* Just to give it a value */
tty_port_init(&state->tport);
state->tport.ops = &amiga_port_ops;
- tty_port_link_device(&state->tport, serial_driver, 0);
+ tty_port_link_device(&state->tport, driver, 0);
- error = tty_register_driver(serial_driver);
+ error = tty_register_driver(driver);
if (error)
- goto fail_put_tty_driver;
+ goto fail_tty_driver_kref_put;
printk(KERN_INFO "ttyS0 is the amiga builtin serial port\n");
/* Hardware set up */
state->baud_base = amiga_colorclock;
- state->xmit_fifo_size = 1;
/* set ISRs, and then disable the rx interrupts */
error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
@@ -1603,11 +1540,11 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
local_irq_save(flags);
/* turn off Rx and Tx interrupts */
- custom.intena = IF_RBF | IF_TBE;
+ amiga_custom.intena = IF_RBF | IF_TBE;
mb();
/* clear any pending interrupt */
- custom.intreq = IF_RBF | IF_TBE;
+ amiga_custom.intreq = IF_RBF | IF_TBE;
mb();
local_irq_restore(flags);
@@ -1621,15 +1558,17 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, state);
+ serial_driver = driver;
+
return 0;
fail_free_irq:
free_irq(IRQ_AMIGA_TBE, state);
fail_unregister:
- tty_unregister_driver(serial_driver);
-fail_put_tty_driver:
+ tty_unregister_driver(driver);
+fail_tty_driver_kref_put:
tty_port_destroy(&state->tport);
- put_tty_driver(serial_driver);
+ tty_driver_kref_put(driver);
return error;
}
@@ -1637,9 +1576,8 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
{
struct serial_state *state = platform_get_drvdata(pdev);
- /* printk("Unloading %s: version %s\n", serial_name, serial_version); */
tty_unregister_driver(serial_driver);
- put_tty_driver(serial_driver);
+ tty_driver_kref_put(serial_driver);
tty_port_destroy(&state->tport);
free_irq(IRQ_AMIGA_TBE, state);
@@ -1668,8 +1606,8 @@ module_platform_driver_probe(amiga_serial_driver, amiga_serial_probe);
static void amiga_serial_putc(char c)
{
- custom.serdat = (unsigned char)c | 0x100;
- while (!(custom.serdatr & 0x2000))
+ amiga_custom.serdat = (unsigned char)c | 0x100;
+ while (!(amiga_custom.serdatr & 0x2000))
barrier();
}
@@ -1682,9 +1620,9 @@ static void amiga_serial_putc(char c)
static void serial_console_write(struct console *co, const char *s,
unsigned count)
{
- unsigned short intena = custom.intenar;
+ unsigned short intena = amiga_custom.intenar;
- custom.intena = IF_TBE;
+ amiga_custom.intena = IF_TBE;
while (count--) {
if (*s == '\n')
@@ -1692,7 +1630,7 @@ static void serial_console_write(struct console *co, const char *s,
amiga_serial_putc(*s++);
}
- custom.intena = IF_SETCLR | (intena & IF_TBE);
+ amiga_custom.intena = IF_SETCLR | (intena & IF_TBE);
}
static struct tty_driver *serial_console_device(struct console *c, int *index)
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index 445e5ff9b36d..19d32cb6af84 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -751,6 +751,7 @@ static struct platform_driver ehv_bc_tty_driver = {
*/
static int __init ehv_bc_init(void)
{
+ struct tty_driver *driver;
struct device_node *np;
unsigned int count = 0; /* Number of elements in bcs[] */
int ret;
@@ -773,26 +774,28 @@ static int __init ehv_bc_init(void)
if (!bcs)
return -ENOMEM;
- ehv_bc_driver = alloc_tty_driver(count);
- if (!ehv_bc_driver) {
- ret = -ENOMEM;
+ driver = tty_alloc_driver(count, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(driver)) {
+ ret = PTR_ERR(driver);
goto err_free_bcs;
}
- ehv_bc_driver->driver_name = "ehv-bc";
- ehv_bc_driver->name = ehv_bc_console.name;
- ehv_bc_driver->type = TTY_DRIVER_TYPE_CONSOLE;
- ehv_bc_driver->subtype = SYSTEM_TYPE_CONSOLE;
- ehv_bc_driver->init_termios = tty_std_termios;
- ehv_bc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- tty_set_operations(ehv_bc_driver, &ehv_bc_ops);
+ driver->driver_name = "ehv-bc";
+ driver->name = ehv_bc_console.name;
+ driver->type = TTY_DRIVER_TYPE_CONSOLE;
+ driver->subtype = SYSTEM_TYPE_CONSOLE;
+ driver->init_termios = tty_std_termios;
+ tty_set_operations(driver, &ehv_bc_ops);
- ret = tty_register_driver(ehv_bc_driver);
+ ret = tty_register_driver(driver);
if (ret) {
pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
- goto err_put_tty_driver;
+ goto err_tty_driver_kref_put;
}
+ ehv_bc_driver = driver;
+
ret = platform_driver_register(&ehv_bc_tty_driver);
if (ret) {
pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
@@ -803,9 +806,10 @@ static int __init ehv_bc_init(void)
return 0;
err_deregister_tty_driver:
- tty_unregister_driver(ehv_bc_driver);
-err_put_tty_driver:
- put_tty_driver(ehv_bc_driver);
+ ehv_bc_driver = NULL;
+ tty_unregister_driver(driver);
+err_tty_driver_kref_put:
+ tty_driver_kref_put(driver);
err_free_bcs:
kfree(bcs);
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
index ccb683a6e6f5..d24af649a8bb 100644
--- a/drivers/tty/goldfish.c
+++ b/drivers/tty/goldfish.c
@@ -253,18 +253,18 @@ static int goldfish_tty_create_driver(void)
ret = -ENOMEM;
goto err_alloc_goldfish_ttys_failed;
}
- tty = alloc_tty_driver(goldfish_tty_line_count);
- if (tty == NULL) {
- ret = -ENOMEM;
- goto err_alloc_tty_driver_failed;
+ tty = tty_alloc_driver(goldfish_tty_line_count,
+ TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(tty)) {
+ ret = PTR_ERR(tty);
+ goto err_tty_alloc_driver_failed;
}
tty->driver_name = "goldfish";
tty->name = "ttyGF";
tty->type = TTY_DRIVER_TYPE_SERIAL;
tty->subtype = SERIAL_TYPE_NORMAL;
tty->init_termios = tty_std_termios;
- tty->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(tty, &goldfish_tty_ops);
ret = tty_register_driver(tty);
if (ret)
@@ -274,8 +274,8 @@ static int goldfish_tty_create_driver(void)
return 0;
err_tty_register_driver_failed:
- put_tty_driver(tty);
-err_alloc_tty_driver_failed:
+ tty_driver_kref_put(tty);
+err_tty_alloc_driver_failed:
kfree(goldfish_ttys);
goldfish_ttys = NULL;
err_alloc_goldfish_ttys_failed:
@@ -285,7 +285,7 @@ err_alloc_goldfish_ttys_failed:
static void goldfish_tty_delete_driver(void)
{
tty_unregister_driver(goldfish_tty_driver);
- put_tty_driver(goldfish_tty_driver);
+ tty_driver_kref_put(goldfish_tty_driver);
goldfish_tty_driver = NULL;
kfree(goldfish_ttys);
goldfish_ttys = NULL;
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 5bb8c4e44961..7b30d5a05e2f 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -1021,9 +1021,10 @@ static int hvc_init(void)
int err;
/* We need more than hvc_count adapters due to hotplug additions. */
- drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
- if (!drv) {
- err = -ENOMEM;
+ drv = tty_alloc_driver(HVC_ALLOC_TTY_ADAPTERS, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_RESET_TERMIOS);
+ if (IS_ERR(drv)) {
+ err = PTR_ERR(drv);
goto out;
}
@@ -1033,7 +1034,6 @@ static int hvc_init(void)
drv->minor_start = HVC_MINOR;
drv->type = TTY_DRIVER_TYPE_SYSTEM;
drv->init_termios = tty_std_termios;
- drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
tty_set_operations(drv, &hvc_ops);
/* Always start the kthread because there can be hotplug vty adapters
@@ -1063,7 +1063,7 @@ stop_thread:
kthread_stop(hvc_task);
hvc_task = NULL;
put_tty:
- put_tty_driver(drv);
+ tty_driver_kref_put(drv);
out:
return err;
}
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 92c9a476defc..8f143c09a169 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -86,7 +86,11 @@ static int __write_console(struct xencons_info *xencons,
cons = intf->out_cons;
prod = intf->out_prod;
mb(); /* update queue values before going on */
- BUG_ON((prod - cons) > sizeof(intf->out));
+
+ if ((prod - cons) > sizeof(intf->out)) {
+ pr_err_once("xencons: Illegal ring page indices");
+ return -EINVAL;
+ }
while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
@@ -114,7 +118,10 @@ static int domU_write_console(uint32_t vtermno, const char *data, int len)
*/
while (len) {
int sent = __write_console(cons, data, len);
-
+
+ if (sent < 0)
+ return sent;
+
data += sent;
len -= sent;
@@ -138,7 +145,11 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
cons = intf->in_cons;
prod = intf->in_prod;
mb(); /* get pointers before reading ring */
- BUG_ON((prod - cons) > sizeof(intf->in));
+
+ if ((prod - cons) > sizeof(intf->in)) {
+ pr_err_once("xencons: Illegal ring page indices");
+ return -EINVAL;
+ }
while (cons != prod && recv < len)
buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index fe5e6b4f43de..245da1dfd818 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1445,10 +1445,11 @@ static int hvcs_initialize(void)
} else
num_ttys_to_alloc = hvcs_parm_num_devs;
- hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
- if (!hvcs_tty_driver) {
+ hvcs_tty_driver = tty_alloc_driver(num_ttys_to_alloc,
+ TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(hvcs_tty_driver)) {
mutex_unlock(&hvcs_init_mutex);
- return -ENOMEM;
+ return PTR_ERR(hvcs_tty_driver);
}
if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
@@ -1473,7 +1474,6 @@ static int hvcs_initialize(void)
* throw us into a horrible recursive echo-echo-echo loop.
*/
hvcs_tty_driver->init_termios = hvcs_tty_termios;
- hvcs_tty_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(hvcs_tty_driver, &hvcs_ops);
@@ -1509,7 +1509,7 @@ buff_alloc_fail:
register_fail:
hvcs_free_index_list();
index_fail:
- put_tty_driver(hvcs_tty_driver);
+ tty_driver_kref_put(hvcs_tty_driver);
hvcs_tty_driver = NULL;
mutex_unlock(&hvcs_init_mutex);
return rc;
@@ -1562,7 +1562,7 @@ static void __exit hvcs_module_exit(void)
hvcs_free_index_list();
- put_tty_driver(hvcs_tty_driver);
+ tty_driver_kref_put(hvcs_tty_driver);
printk(KERN_INFO "HVCS: driver module removed.\n");
}
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index bfc15279d5bc..aa81f4835fef 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -1038,29 +1038,29 @@ static const struct tty_operations hvsi_ops = {
static int __init hvsi_init(void)
{
- int i;
-
- hvsi_driver = alloc_tty_driver(hvsi_count);
- if (!hvsi_driver)
- return -ENOMEM;
-
- hvsi_driver->driver_name = "hvsi";
- hvsi_driver->name = "hvsi";
- hvsi_driver->major = HVSI_MAJOR;
- hvsi_driver->minor_start = HVSI_MINOR;
- hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
- hvsi_driver->init_termios = tty_std_termios;
- hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
- hvsi_driver->init_termios.c_ispeed = 9600;
- hvsi_driver->init_termios.c_ospeed = 9600;
- hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(hvsi_driver, &hvsi_ops);
+ struct tty_driver *driver;
+ int i, ret;
+
+ driver = tty_alloc_driver(hvsi_count, TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
+
+ driver->driver_name = "hvsi";
+ driver->name = "hvsi";
+ driver->major = HVSI_MAJOR;
+ driver->minor_start = HVSI_MINOR;
+ driver->type = TTY_DRIVER_TYPE_SYSTEM;
+ driver->init_termios = tty_std_termios;
+ driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+ driver->init_termios.c_ispeed = 9600;
+ driver->init_termios.c_ospeed = 9600;
+ tty_set_operations(driver, &hvsi_ops);
for (i=0; i < hvsi_count; i++) {
struct hvsi_struct *hp = &hvsi_ports[i];
int ret = 1;
- tty_port_link_device(&hp->port, hvsi_driver, i);
+ tty_port_link_device(&hp->port, driver, i);
ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
if (ret)
@@ -1069,12 +1069,27 @@ static int __init hvsi_init(void)
}
hvsi_wait = wait_for_state; /* irqs active now */
- if (tty_register_driver(hvsi_driver))
- panic("Couldn't register hvsi console driver\n");
+ ret = tty_register_driver(driver);
+ if (ret) {
+ pr_err("Couldn't register hvsi console driver\n");
+ goto err_free_irq;
+ }
+
+ hvsi_driver = driver;
printk(KERN_DEBUG "HVSI: registered %i devices\n", hvsi_count);
return 0;
+err_free_irq:
+ hvsi_wait = poll_for_state;
+ for (i = 0; i < hvsi_count; i++) {
+ struct hvsi_struct *hp = &hvsi_ports[i];
+
+ free_irq(hp->virq, hp);
+ }
+ tty_driver_kref_put(driver);
+
+ return ret;
}
device_initcall(hvsi_init);
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
index e3a5a5ba752c..9edd5ae17580 100644
--- a/drivers/tty/ipwireless/tty.c
+++ b/drivers/tty/ipwireless/tty.c
@@ -564,9 +564,10 @@ int ipwireless_tty_init(void)
{
int result;
- ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
- if (!ipw_tty_driver)
- return -ENOMEM;
+ ipw_tty_driver = tty_alloc_driver(IPWIRELESS_PCMCIA_MINORS,
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(ipw_tty_driver))
+ return PTR_ERR(ipw_tty_driver);
ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
ipw_tty_driver->name = "ttyIPWp";
@@ -574,7 +575,6 @@ int ipwireless_tty_init(void)
ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
ipw_tty_driver->init_termios = tty_std_termios;
ipw_tty_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
@@ -585,7 +585,7 @@ int ipwireless_tty_init(void)
if (result) {
printk(KERN_ERR IPWIRELESS_PCCARD_NAME
": failed to register tty driver\n");
- put_tty_driver(ipw_tty_driver);
+ tty_driver_kref_put(ipw_tty_driver);
return result;
}
@@ -595,7 +595,7 @@ int ipwireless_tty_init(void)
void ipwireless_tty_release(void)
{
tty_unregister_driver(ipw_tty_driver);
- put_tty_driver(ipw_tty_driver);
+ tty_driver_kref_put(ipw_tty_driver);
}
int ipwireless_tty_is_modem(struct ipw_tty *tty)
diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c
index 3b5915b94fac..02c10a968de1 100644
--- a/drivers/tty/mips_ejtag_fdc.c
+++ b/drivers/tty/mips_ejtag_fdc.c
@@ -1042,7 +1042,7 @@ err_destroy_ports:
dport = &priv->ports[nport];
tty_port_destroy(&dport->port);
}
- put_tty_driver(priv->driver);
+ tty_driver_kref_put(priv->driver);
return ret;
}
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index 64b18177c790..bf17e90858b8 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -1053,7 +1053,7 @@ static int __init moxa_init(void)
if (tty_register_driver(moxaDriver)) {
printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
- put_tty_driver(moxaDriver);
+ tty_driver_kref_put(moxaDriver);
return -1;
}
@@ -1119,7 +1119,7 @@ static void __exit moxa_exit(void)
del_timer_sync(&moxaTimer);
tty_unregister_driver(moxaDriver);
- put_tty_driver(moxaDriver);
+ tty_driver_kref_put(moxaDriver);
}
module_init(moxa_init);
@@ -2034,10 +2034,10 @@ static int moxa_get_serial_info(struct tty_struct *tty,
if (!info)
return -ENODEV;
mutex_lock(&info->port.mutex);
- ss->type = info->type,
- ss->line = info->port.tty->index,
- ss->flags = info->port.flags,
- ss->baud_base = 921600,
+ ss->type = info->type;
+ ss->line = info->port.tty->index;
+ ss->flags = info->port.flags;
+ ss->baud_base = 921600;
ss->close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
mutex_unlock(&info->port.mutex);
return 0;
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 900ccb2ca166..1216f3985e18 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -1039,12 +1039,12 @@ static int mxser_get_serial_info(struct tty_struct *tty,
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = jiffies_to_msecs(closing_wait) / 10;
- ss->type = info->type,
- ss->line = tty->index,
- ss->port = info->ioaddr,
- ss->irq = info->board->irq,
- ss->flags = info->port.flags,
- ss->baud_base = MXSER_BAUD_BASE,
+ ss->type = info->type;
+ ss->line = tty->index;
+ ss->port = info->ioaddr;
+ ss->irq = info->board->irq;
+ ss->flags = info->port.flags;
+ ss->baud_base = MXSER_BAUD_BASE;
ss->close_delay = close_delay;
ss->closing_wait = closing_wait;
ss->custom_divisor = MXSER_CUSTOM_DIVISOR,
@@ -1976,9 +1976,10 @@ static int __init mxser_module_init(void)
{
int retval;
- mxvar_sdriver = alloc_tty_driver(MXSER_PORTS);
- if (!mxvar_sdriver)
- return -ENOMEM;
+ mxvar_sdriver = tty_alloc_driver(MXSER_PORTS, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(mxvar_sdriver))
+ return PTR_ERR(mxvar_sdriver);
/* Initialize the tty_driver structure */
mxvar_sdriver->name = "ttyMI";
@@ -1988,7 +1989,6 @@ static int __init mxser_module_init(void)
mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
mxvar_sdriver->init_termios = tty_std_termios;
mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
- mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(mxvar_sdriver, &mxser_ops);
retval = tty_register_driver(mxvar_sdriver);
@@ -2008,7 +2008,7 @@ static int __init mxser_module_init(void)
err_unr:
tty_unregister_driver(mxvar_sdriver);
err_put:
- put_tty_driver(mxvar_sdriver);
+ tty_driver_kref_put(mxvar_sdriver);
return retval;
}
@@ -2016,7 +2016,7 @@ static void __exit mxser_module_exit(void)
{
pci_unregister_driver(&mxser_driver);
tty_unregister_driver(mxvar_sdriver);
- put_tty_driver(mxvar_sdriver);
+ tty_driver_kref_put(mxvar_sdriver);
}
module_init(mxser_module_init);
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index e907b7a5cab5..1d92d2a84889 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -3252,10 +3252,11 @@ static int __init gsm_init(void)
return status;
}
- gsm_tty_driver = alloc_tty_driver(256);
- if (!gsm_tty_driver) {
+ gsm_tty_driver = tty_alloc_driver(256, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
+ if (IS_ERR(gsm_tty_driver)) {
pr_err("gsm_init: tty allocation failed.\n");
- status = -ENOMEM;
+ status = PTR_ERR(gsm_tty_driver);
goto err_unreg_ldisc;
}
gsm_tty_driver->driver_name = "gsmtty";
@@ -3264,8 +3265,6 @@ static int __init gsm_init(void)
gsm_tty_driver->minor_start = 0;
gsm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gsm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- gsm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV
- | TTY_DRIVER_HARDWARE_BREAK;
gsm_tty_driver->init_termios = tty_std_termios;
/* Fixme */
gsm_tty_driver->init_termios.c_lflag &= ~ECHO;
@@ -3280,7 +3279,7 @@ static int __init gsm_init(void)
gsm_tty_driver->major, gsm_tty_driver->minor_start);
return 0;
err_put_driver:
- put_tty_driver(gsm_tty_driver);
+ tty_driver_kref_put(gsm_tty_driver);
err_unreg_ldisc:
tty_unregister_ldisc(&tty_ldisc_packet);
return status;
@@ -3290,7 +3289,7 @@ static void __exit gsm_exit(void)
{
tty_unregister_ldisc(&tty_ldisc_packet);
tty_unregister_driver(gsm_tty_driver);
- put_tty_driver(gsm_tty_driver);
+ tty_driver_kref_put(gsm_tty_driver);
}
module_init(gsm_init);
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index 0c80f25c8c3d..0454c78deee6 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -1824,16 +1824,16 @@ static __init int nozomi_init(void)
{
int ret;
- ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
- if (!ntty_driver)
- return -ENOMEM;
+ ntty_driver = tty_alloc_driver(NTTY_TTY_MAXMINORS, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(ntty_driver))
+ return PTR_ERR(ntty_driver);
ntty_driver->driver_name = NOZOMI_NAME_TTY;
ntty_driver->name = "noz";
ntty_driver->major = 0;
ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
ntty_driver->subtype = SERIAL_TYPE_NORMAL;
- ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
ntty_driver->init_termios = tty_std_termios;
ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \
HUPCL | CLOCAL;
@@ -1857,7 +1857,7 @@ static __init int nozomi_init(void)
unr_tty:
tty_unregister_driver(ntty_driver);
free_tty:
- put_tty_driver(ntty_driver);
+ tty_driver_kref_put(ntty_driver);
return ret;
}
@@ -1865,7 +1865,7 @@ static __exit void nozomi_exit(void)
{
pci_unregister_driver(&nozomi_driver);
tty_unregister_driver(ntty_driver);
- put_tty_driver(ntty_driver);
+ tty_driver_kref_put(ntty_driver);
}
module_init(nozomi_init);
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 9cdfcfe07e87..f1324fe99378 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -421,15 +421,13 @@ static int serdev_drv_probe(struct device *dev)
return ret;
}
-static int serdev_drv_remove(struct device *dev)
+static void serdev_drv_remove(struct device *dev)
{
const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
if (sdrv->remove)
sdrv->remove(to_serdev_device(dev));
dev_pm_domain_detach(dev, true);
-
- return 0;
}
static struct bus_type serdev_bus_type = {
@@ -564,23 +562,45 @@ struct acpi_serdev_lookup {
int index;
};
+/**
+ * serdev_acpi_get_uart_resource - Gets UARTSerialBus resource if type matches
+ * @ares: ACPI resource
+ * @uart: Pointer to UARTSerialBus resource will be returned here
+ *
+ * Checks if the given ACPI resource is of type UARTSerialBus.
+ * In this case, returns a pointer to it to the caller.
+ *
+ * Return: True if resource type is of UARTSerialBus, otherwise false.
+ */
+bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
+ struct acpi_resource_uart_serialbus **uart)
+{
+ struct acpi_resource_uart_serialbus *sb;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
+ return false;
+
+ sb = &ares->data.uart_serial_bus;
+ if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_UART)
+ return false;
+
+ *uart = sb;
+ return true;
+}
+EXPORT_SYMBOL_GPL(serdev_acpi_get_uart_resource);
+
static int acpi_serdev_parse_resource(struct acpi_resource *ares, void *data)
{
struct acpi_serdev_lookup *lookup = data;
struct acpi_resource_uart_serialbus *sb;
acpi_status status;
- if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
- return 1;
-
- if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
+ if (!serdev_acpi_get_uart_resource(ares, &sb))
return 1;
if (lookup->index != -1 && lookup->n++ != lookup->index)
return 1;
- sb = &ares->data.uart_serial_bus;
-
status = acpi_get_handle(lookup->device_handle,
sb->resource_source.string_ptr,
&lookup->controller_handle);
@@ -588,7 +608,7 @@ static int acpi_serdev_parse_resource(struct acpi_resource *ares, void *data)
return 1;
/*
- * NOTE: Ideally, we would also want to retreive other properties here,
+ * NOTE: Ideally, we would also want to retrieve other properties here,
* once setting them before opening the device is supported by serdev.
*/
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
index 725a450058f8..7f656fac503f 100644
--- a/drivers/tty/serial/8250/8250_bcm7271.c
+++ b/drivers/tty/serial/8250/8250_bcm7271.c
@@ -941,7 +941,7 @@ static int brcmuart_probe(struct platform_device *pdev)
struct clk *baud_mux_clk;
struct uart_8250_port up;
struct resource *irq;
- void __iomem *membase = 0;
+ void __iomem *membase = NULL;
resource_size_t mapbase = 0;
u32 clk_rate = 0;
int ret;
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index 3ffeedc29c83..d502240bbcf2 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -114,6 +114,7 @@ struct exar8250;
struct exar8250_platform {
int (*rs485_config)(struct uart_port *, struct serial_rs485 *);
int (*register_gpio)(struct pci_dev *, struct uart_8250_port *);
+ void (*unregister_gpio)(struct uart_8250_port *);
};
/**
@@ -352,9 +353,8 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
}
-static void *
-__xr17v35x_register_gpio(struct pci_dev *pcidev,
- const struct software_node *node)
+static struct platform_device *__xr17v35x_register_gpio(struct pci_dev *pcidev,
+ const struct software_node *node)
{
struct platform_device *pdev;
@@ -374,6 +374,12 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev,
return pdev;
}
+static void __xr17v35x_unregister_gpio(struct platform_device *pdev)
+{
+ device_remove_software_node(&pdev->dev);
+ platform_device_unregister(pdev);
+}
+
static const struct property_entry exar_gpio_properties[] = {
PROPERTY_ENTRY_U32("exar,first-pin", 0),
PROPERTY_ENTRY_U32("ngpios", 16),
@@ -384,8 +390,7 @@ static const struct software_node exar_gpio_node = {
.properties = exar_gpio_properties,
};
-static int xr17v35x_register_gpio(struct pci_dev *pcidev,
- struct uart_8250_port *port)
+static int xr17v35x_register_gpio(struct pci_dev *pcidev, struct uart_8250_port *port)
{
if (pcidev->vendor == PCI_VENDOR_ID_EXAR)
port->port.private_data =
@@ -394,6 +399,15 @@ static int xr17v35x_register_gpio(struct pci_dev *pcidev,
return 0;
}
+static void xr17v35x_unregister_gpio(struct uart_8250_port *port)
+{
+ if (!port->port.private_data)
+ return;
+
+ __xr17v35x_unregister_gpio(port->port.private_data);
+ port->port.private_data = NULL;
+}
+
static int generic_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
@@ -419,6 +433,7 @@ static int generic_rs485_config(struct uart_port *port,
static const struct exar8250_platform exar8250_default_platform = {
.register_gpio = xr17v35x_register_gpio,
+ .unregister_gpio = xr17v35x_unregister_gpio,
.rs485_config = generic_rs485_config,
};
@@ -484,6 +499,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev,
static const struct exar8250_platform iot2040_platform = {
.rs485_config = iot2040_rs485_config,
.register_gpio = iot2040_register_gpio,
+ .unregister_gpio = xr17v35x_unregister_gpio,
};
/*
@@ -555,17 +571,11 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
static void pci_xr17v35x_exit(struct pci_dev *pcidev)
{
+ const struct exar8250_platform *platform = exar_get_platform();
struct exar8250 *priv = pci_get_drvdata(pcidev);
struct uart_8250_port *port = serial8250_get_port(priv->line[0]);
- struct platform_device *pdev;
- pdev = port->port.private_data;
- if (!pdev)
- return;
-
- device_remove_software_node(&pdev->dev);
- platform_device_unregister(pdev);
- port->port.private_data = NULL;
+ platform->unregister_gpio(port);
}
static inline void exar_misc_clear(struct exar8250 *priv)
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index 988bf6bcce42..65402d05eff9 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -209,16 +209,14 @@ static int ingenic_uart_probe(struct platform_device *pdev)
struct uart_8250_port uart = {};
struct ingenic_uart_data *data;
const struct ingenic_uart_config *cdata;
- const struct of_device_id *match;
struct resource *regs;
int irq, err, line;
- match = of_match_device(of_match, &pdev->dev);
- if (!match) {
+ cdata = of_device_get_match_data(&pdev->dev);
+ if (!cdata) {
dev_err(&pdev->dev, "Error: No device match found\n");
return -ENODEV;
}
- cdata = match->data;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index 4dee8a9e0c95..848d81e3838c 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -158,6 +158,16 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
+ struct uart_8250_dma *dma = &lpss->data.dma;
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ /*
+ * This simply makes the checks in the 8250_port to try the DMA
+ * channel request which in turn uses the magic of ACPI tables
+ * parsing (see drivers/dma/acpi-dma.c for the details) and
+ * matching with the registered General Purpose DMA controllers.
+ */
+ up->dma = dma;
return 0;
}
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 79418d4beb48..891fd8345e25 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -538,7 +538,7 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state,
static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
struct omap8250_priv *priv)
{
- const struct soc_device_attribute k3_soc_devices[] = {
+ static const struct soc_device_attribute k3_soc_devices[] = {
{ .family = "AM65X", },
{ .family = "J721E", .revision = "SR1.0" },
{ /* sentinel */ }
@@ -617,7 +617,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
struct uart_port *port = dev_id;
struct omap8250_priv *priv = port->private_data;
struct uart_8250_port *up = up_to_u8250p(port);
- unsigned int iir;
+ unsigned int iir, lsr;
int ret;
#ifdef CONFIG_SERIAL_8250_DMA
@@ -628,6 +628,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
#endif
serial8250_rpm_get(up);
+ lsr = serial_port_in(port, UART_LSR);
iir = serial_port_in(port, UART_IIR);
ret = serial8250_handle_irq(port, iir);
@@ -642,6 +643,24 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
serial_port_in(port, UART_RX);
}
+ /* Stop processing interrupts on input overrun */
+ if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) {
+ unsigned long delay;
+
+ up->ier = port->serial_in(port, UART_IER);
+ if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
+ port->ops->stop_rx(port);
+ } else {
+ /* Keep restarting the timer until
+ * the input overrun subsides.
+ */
+ cancel_delayed_work(&up->overrun_backoff);
+ }
+
+ delay = msecs_to_jiffies(up->overrun_backoff_time_ms);
+ schedule_delayed_work(&up->overrun_backoff, delay);
+ }
+
serial8250_rpm_put(up);
return IRQ_RETVAL(ret);
@@ -1353,6 +1372,10 @@ static int omap8250_probe(struct platform_device *pdev)
}
}
+ if (of_property_read_u32(np, "overrun-throttle-ms",
+ &up.overrun_backoff_time_ms) != 0)
+ up.overrun_backoff_time_ms = 0;
+
priv->wakeirq = irq_of_parse_and_map(np, 1);
pdata = of_device_get_match_data(&pdev->dev);
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index a808c283883e..726912b16a55 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -87,7 +87,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
static int
setup_port(struct serial_private *priv, struct uart_8250_port *port,
- int bar, int offset, int regshift)
+ u8 bar, unsigned int offset, int regshift)
{
struct pci_dev *dev = priv->dev;
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index de90d681b64c..98e5ee4d0d08 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -13,6 +13,7 @@
#include <linux/pnp.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/property.h>
#include <linux/serial_core.h>
#include <linux/bitops.h>
@@ -475,6 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
uart.port.flags |= UPF_SHARE_IRQ;
uart.port.uartclk = 1843200;
+ device_property_read_u32(&dev->dev, "clock-frequency", &uart.port.uartclk);
uart.port.dev = &dev->dev;
line = serial8250_register_8250_port(&uart);
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 1da29a219842..66374704747e 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -122,7 +122,8 @@ static const struct serial8250_config uart_config[] = {
.name = "16C950/954",
.fifo_size = 128,
.tx_loadsz = 128,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
+ .rxtrig_bytes = {16, 32, 112, 120},
/* UART_CAP_EFR breaks billionon CF bluetooth card. */
.flags = UART_CAP_FIFO | UART_CAP_SLEEP,
},
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index d1b3c2373fa4..71ae16de0f90 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -363,7 +363,7 @@ config SERIAL_8250_BCM2835AUX
config SERIAL_8250_FSL
bool
depends on SERIAL_8250_CONSOLE
- default PPC || ARM || ARM64
+ default PPC || ARM || ARM64 || COMPILE_TEST
config SERIAL_8250_DW
tristate "Support for Synopsys DesignWare 8250 quirks"
@@ -375,7 +375,8 @@ config SERIAL_8250_DW
config SERIAL_8250_EM
tristate "Support for Emma Mobile integrated serial port"
- depends on SERIAL_8250 && ARM && HAVE_CLK
+ depends on SERIAL_8250 && HAVE_CLK
+ depends on ARM || COMPILE_TEST
help
Selecting this option will add support for the integrated serial
port hardware found on the Emma Mobile line of processors.
@@ -383,7 +384,8 @@ config SERIAL_8250_EM
config SERIAL_8250_IOC3
tristate "SGI IOC3 8250 UART support"
- depends on SGI_MFD_IOC3 && SERIAL_8250
+ depends on SERIAL_8250
+ depends on SGI_MFD_IOC3 || COMPILE_TEST
select SERIAL_8250_EXTENDED
select SERIAL_8250_SHARE_IRQ
help
@@ -495,7 +497,7 @@ config SERIAL_8250_MID
config SERIAL_8250_PXA
tristate "PXA serial port support"
depends on SERIAL_8250
- depends on ARCH_PXA || ARCH_MMP
+ depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST
help
If you have a machine based on an Intel XScale PXA2xx CPU you can
enable its onboard serial ports by enabling this option. The option is
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 24282ad99d85..131a6a587acd 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -959,7 +959,7 @@ config SERIAL_VT8500_CONSOLE
config SERIAL_OMAP
tristate "OMAP serial port support"
- depends on ARCH_OMAP2PLUS || COMPILE_TEST
+ depends on (ARCH_OMAP2PLUS && !SERIAL_8250_OMAP) || COMPILE_TEST
select SERIAL_CORE
help
If you have a machine based on an Texas Instruments OMAP CPU you
@@ -1382,7 +1382,7 @@ config SERIAL_ST_ASC
select SERIAL_CORE
depends on ARM || COMPILE_TEST
help
- This driver is for the on-chip Asychronous Serial Controller on
+ This driver is for the on-chip Asynchronous Serial Controller on
STMicroelectronics STi SoCs.
ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
It support all industry standard baud rates.
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index e14f3378b8a0..d361cd84ff8c 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -265,6 +265,8 @@ struct uart_amba_port {
unsigned int old_cr; /* state during shutdown */
unsigned int fixed_baud; /* vendor-set fixed baud rate */
char type[12];
+ bool rs485_tx_started;
+ unsigned int rs485_tx_drain_interval; /* usecs */
#ifdef CONFIG_DMA_ENGINE
/* DMA stuff */
bool using_tx_dma;
@@ -275,6 +277,8 @@ struct uart_amba_port {
#endif
};
+static unsigned int pl011_tx_empty(struct uart_port *port);
+
static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
unsigned int reg)
{
@@ -1282,6 +1286,42 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
#define pl011_dma_flush_buffer NULL
#endif
+static void pl011_rs485_tx_stop(struct uart_amba_port *uap)
+{
+ struct uart_port *port = &uap->port;
+ int i = 0;
+ u32 cr;
+
+ /* Wait until hardware tx queue is empty */
+ while (!pl011_tx_empty(port)) {
+ if (i == port->fifosize) {
+ dev_warn(port->dev,
+ "timeout while draining hardware tx queue\n");
+ break;
+ }
+
+ udelay(uap->rs485_tx_drain_interval);
+ i++;
+ }
+
+ if (port->rs485.delay_rts_after_send)
+ mdelay(port->rs485.delay_rts_after_send);
+
+ cr = pl011_read(uap, REG_CR);
+
+ if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+ cr &= ~UART011_CR_RTS;
+ else
+ cr |= UART011_CR_RTS;
+
+ /* Disable the transmitter and reenable the transceiver */
+ cr &= ~UART011_CR_TXE;
+ cr |= UART011_CR_RXE;
+ pl011_write(cr, uap, REG_CR);
+
+ uap->rs485_tx_started = false;
+}
+
static void pl011_stop_tx(struct uart_port *port)
{
struct uart_amba_port *uap =
@@ -1290,6 +1330,9 @@ static void pl011_stop_tx(struct uart_port *port)
uap->im &= ~UART011_TXIM;
pl011_write(uap->im, uap, REG_IMSC);
pl011_dma_tx_stop(uap);
+
+ if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
+ pl011_rs485_tx_stop(uap);
}
static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
@@ -1380,6 +1423,32 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
return true;
}
+static void pl011_rs485_tx_start(struct uart_amba_port *uap)
+{
+ struct uart_port *port = &uap->port;
+ u32 cr;
+
+ /* Enable transmitter */
+ cr = pl011_read(uap, REG_CR);
+ cr |= UART011_CR_TXE;
+
+ /* Disable receiver if half-duplex */
+ if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
+ cr &= ~UART011_CR_RXE;
+
+ if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
+ cr &= ~UART011_CR_RTS;
+ else
+ cr |= UART011_CR_RTS;
+
+ pl011_write(cr, uap, REG_CR);
+
+ if (port->rs485.delay_rts_before_send)
+ mdelay(port->rs485.delay_rts_before_send);
+
+ uap->rs485_tx_started = true;
+}
+
/* Returns true if tx interrupts have to be (kept) enabled */
static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
{
@@ -1397,6 +1466,10 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
return false;
}
+ if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
+ !uap->rs485_tx_started)
+ pl011_rs485_tx_start(uap);
+
/* If we are using DMA mode, try to send some characters. */
if (pl011_dma_tx_irq(uap))
return true;
@@ -1542,6 +1615,9 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
container_of(port, struct uart_amba_port, port);
unsigned int cr;
+ if (port->rs485.flags & SER_RS485_ENABLED)
+ mctrl &= ~TIOCM_RTS;
+
cr = pl011_read(uap, REG_CR);
#define TIOCMBIT(tiocmbit, uartbit) \
@@ -1763,7 +1839,17 @@ static int pl011_startup(struct uart_port *port)
/* restore RTS and DTR */
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
- cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
+ cr |= UART01x_CR_UARTEN | UART011_CR_RXE;
+
+ if (port->rs485.flags & SER_RS485_ENABLED) {
+ if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+ cr &= ~UART011_CR_RTS;
+ else
+ cr |= UART011_CR_RTS;
+ } else {
+ cr |= UART011_CR_TXE;
+ }
+
pl011_write(cr, uap, REG_CR);
spin_unlock_irq(&uap->port.lock);
@@ -1864,6 +1950,9 @@ static void pl011_shutdown(struct uart_port *port)
pl011_dma_shutdown(uap);
+ if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
+ pl011_rs485_tx_stop(uap);
+
free_irq(uap->port.irq, uap);
pl011_disable_uart(uap);
@@ -1941,6 +2030,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned int lcr_h, old_cr;
unsigned long flags;
unsigned int baud, quot, clkdiv;
+ unsigned int bits;
if (uap->vendor->oversampling)
clkdiv = 8;
@@ -1991,6 +2081,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
if (uap->fifosize > 1)
lcr_h |= UART01x_LCRH_FEN;
+ bits = tty_get_frame_size(termios->c_cflag);
+
spin_lock_irqsave(&port->lock, flags);
/*
@@ -1998,11 +2090,21 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
*/
uart_update_timeout(port, termios->c_cflag, baud);
+ /*
+ * Calculate the approximated time it takes to transmit one character
+ * with the given baud rate. We use this as the poll interval when we
+ * wait for the tx queue to empty.
+ */
+ uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud;
+
pl011_setup_status_masks(port, termios);
if (UART_ENABLE_MS(port, termios->c_cflag))
pl011_enable_ms(port);
+ if (port->rs485.flags & SER_RS485_ENABLED)
+ termios->c_cflag &= ~CRTSCTS;
+
/* first, disable everything */
old_cr = pl011_read(uap, REG_CR);
pl011_write(0, uap, REG_CR);
@@ -2124,6 +2226,41 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
return ret;
}
+static int pl011_rs485_config(struct uart_port *port,
+ struct serial_rs485 *rs485)
+{
+ struct uart_amba_port *uap =
+ container_of(port, struct uart_amba_port, port);
+
+ /* pick sane settings if the user hasn't */
+ if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
+ !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
+ rs485->flags |= SER_RS485_RTS_ON_SEND;
+ rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
+ }
+ /* clamp the delays to [0, 100ms] */
+ rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
+ rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
+ memset(rs485->padding, 0, sizeof(rs485->padding));
+
+ if (port->rs485.flags & SER_RS485_ENABLED)
+ pl011_rs485_tx_stop(uap);
+
+ /* Set new configuration */
+ port->rs485 = *rs485;
+
+ /* Make sure auto RTS is disabled */
+ if (port->rs485.flags & SER_RS485_ENABLED) {
+ u32 cr = pl011_read(uap, REG_CR);
+
+ cr &= ~UART011_CR_RTSEN;
+ pl011_write(cr, uap, REG_CR);
+ port->status &= ~UPSTAT_AUTORTS;
+ }
+
+ return 0;
+}
+
static const struct uart_ops amba_pl011_pops = {
.tx_empty = pl011_tx_empty,
.set_mctrl = pl011_set_mctrl,
@@ -2588,10 +2725,28 @@ static int pl011_find_free_port(void)
return -EBUSY;
}
+static int pl011_get_rs485_mode(struct uart_amba_port *uap)
+{
+ struct uart_port *port = &uap->port;
+ struct serial_rs485 *rs485 = &port->rs485;
+ int ret;
+
+ ret = uart_get_rs485_mode(port);
+ if (ret)
+ return ret;
+
+ /* clamp the delays to [0, 100ms] */
+ rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
+ rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
+
+ return 0;
+}
+
static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
struct resource *mmiobase, int index)
{
void __iomem *base;
+ int ret;
base = devm_ioremap_resource(dev, mmiobase);
if (IS_ERR(base))
@@ -2608,6 +2763,10 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = index;
+ ret = pl011_get_rs485_mode(uap);
+ if (ret)
+ return ret;
+
amba_ports[index] = uap;
return 0;
@@ -2665,7 +2824,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM;
uap->port.irq = dev->irq[0];
uap->port.ops = &amba_pl011_pops;
-
+ uap->port.rs485_config = pl011_rs485_config;
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr);
diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c
index d87048073abe..283757264608 100644
--- a/drivers/tty/serial/fsl_linflexuart.c
+++ b/drivers/tty/serial/fsl_linflexuart.c
@@ -861,11 +861,7 @@ static int linflex_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sport);
- ret = uart_add_one_port(&linflex_reg, sport);
- if (ret)
- return ret;
-
- return 0;
+ return uart_add_one_port(&linflex_reg, sport);
}
static int linflex_remove(struct platform_device *pdev)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index f0e5da77ed6d..b1e7190ae483 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -7,6 +7,7 @@
#include <linux/clk.h>
#include <linux/console.h>
+#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/dmapool.h>
@@ -109,6 +110,11 @@
#define UARTSFIFO_TXOF 0x02
#define UARTSFIFO_RXUF 0x01
+/* 32-bit global registers only for i.MX7ULP/i.MX8x
+ * Used to reset all internal logic and registers, except the Global Register.
+ */
+#define UART_GLOBAL 0x8
+
/* 32-bit register definition */
#define UARTBAUD 0x00
#define UARTSTAT 0x04
@@ -219,6 +225,10 @@
#define UARTWATER_TXWATER_OFF 0
#define UARTWATER_RXWATER_OFF 16
+#define UART_GLOBAL_RST 0x2
+#define GLOBAL_RST_MIN_US 20
+#define GLOBAL_RST_MAX_US 40
+
/* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
#define DMA_RX_TIMEOUT (10)
@@ -320,6 +330,11 @@ static inline bool is_layerscape_lpuart(struct lpuart_port *sport)
sport->devtype == LS1028A_LPUART);
}
+static inline bool is_imx7ulp_lpuart(struct lpuart_port *sport)
+{
+ return sport->devtype == IMX7ULP_LPUART;
+}
+
static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
{
return sport->devtype == IMX8QXP_LPUART;
@@ -383,6 +398,33 @@ static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport)
#define lpuart_enable_clks(x) __lpuart_enable_clks(x, true)
#define lpuart_disable_clks(x) __lpuart_enable_clks(x, false)
+static int lpuart_global_reset(struct lpuart_port *sport)
+{
+ struct uart_port *port = &sport->port;
+ void __iomem *global_addr;
+ int ret;
+
+ if (uart_console(port))
+ return 0;
+
+ ret = clk_prepare_enable(sport->ipg_clk);
+ if (ret) {
+ dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret);
+ return ret;
+ }
+
+ if (is_imx7ulp_lpuart(sport) || is_imx8qxp_lpuart(sport)) {
+ global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF;
+ writel(UART_GLOBAL_RST, global_addr);
+ usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
+ writel(0, global_addr);
+ usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
+ }
+
+ clk_disable_unprepare(sport->ipg_clk);
+ return 0;
+}
+
static void lpuart_stop_tx(struct uart_port *port)
{
unsigned char temp;
@@ -479,6 +521,10 @@ static void lpuart_dma_tx_complete(void *arg)
unsigned long flags;
spin_lock_irqsave(&sport->port.lock, flags);
+ if (!sport->dma_tx_in_progress) {
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+ return;
+ }
dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents,
DMA_TO_DEVICE);
@@ -2045,11 +2091,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long flags;
- unsigned long ctrl, old_ctrl, modem;
+ unsigned long ctrl, old_ctrl, bd, modem;
unsigned int baud;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
ctrl = old_ctrl = lpuart32_read(&sport->port, UARTCTRL);
+ bd = lpuart32_read(&sport->port, UARTBAUD);
modem = lpuart32_read(&sport->port, UARTMODIR);
/*
* only support CS8 and CS7, and for CS7 must enable PE.
@@ -2093,7 +2140,9 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
}
if (termios->c_cflag & CSTOPB)
- termios->c_cflag &= ~CSTOPB;
+ bd |= UARTBAUD_SBNS;
+ else
+ bd &= ~UARTBAUD_SBNS;
/* parity must be enabled when CS7 to match 8-bits format */
if ((termios->c_cflag & CSIZE) == CS7)
@@ -2163,6 +2212,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
UARTCTRL);
+ lpuart32_write(&sport->port, bd, UARTBAUD);
lpuart32_serial_setbrg(sport, baud);
lpuart32_write(&sport->port, modem, UARTMODIR);
lpuart32_write(&sport->port, ctrl, UARTCTRL);
@@ -2611,7 +2661,7 @@ static int lpuart_probe(struct platform_device *pdev)
return PTR_ERR(sport->port.membase);
sport->port.membase += sdata->reg_off;
- sport->port.mapbase = res->start;
+ sport->port.mapbase = res->start + sdata->reg_off;
sport->port.dev = &pdev->dev;
sport->port.type = PORT_LPUART;
sport->devtype = sdata->devtype;
@@ -2691,6 +2741,10 @@ static int lpuart_probe(struct platform_device *pdev)
if (ret)
goto failed_attach_port;
+ ret = lpuart_global_reset(sport);
+ if (ret)
+ goto failed_reset;
+
ret = uart_get_rs485_mode(&sport->port);
if (ret)
goto failed_get_rs485;
@@ -2707,6 +2761,8 @@ static int lpuart_probe(struct platform_device *pdev)
return 0;
failed_get_rs485:
+failed_reset:
+ uart_remove_one_port(&lpuart_reg, &sport->port);
failed_attach_port:
failed_irq_request:
lpuart_disable_clks(sport);
diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c
index bf0e2a4cb0ce..c6f927a76c3b 100644
--- a/drivers/tty/serial/jsm/jsm_neo.c
+++ b/drivers/tty/serial/jsm/jsm_neo.c
@@ -815,7 +815,9 @@ static void neo_parse_isr(struct jsm_board *brd, u32 port)
/* Parse any modem signal changes */
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
"MOD_STAT: sending to parse_modem_sigs\n");
+ spin_lock_irqsave(&ch->uart_port.lock, lock_flags);
neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
+ spin_unlock_irqrestore(&ch->uart_port.lock, lock_flags);
}
}
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c
index 8e42a7682c63..d74cbbbf33c6 100644
--- a/drivers/tty/serial/jsm/jsm_tty.c
+++ b/drivers/tty/serial/jsm/jsm_tty.c
@@ -187,6 +187,7 @@ static void jsm_tty_break(struct uart_port *port, int break_state)
static int jsm_tty_open(struct uart_port *port)
{
+ unsigned long lock_flags;
struct jsm_board *brd;
struct jsm_channel *channel =
container_of(port, struct jsm_channel, uart_port);
@@ -240,6 +241,7 @@ static int jsm_tty_open(struct uart_port *port)
channel->ch_cached_lsr = 0;
channel->ch_stops_sent = 0;
+ spin_lock_irqsave(&port->lock, lock_flags);
termios = &port->state->port.tty->termios;
channel->ch_c_cflag = termios->c_cflag;
channel->ch_c_iflag = termios->c_iflag;
@@ -259,6 +261,7 @@ static int jsm_tty_open(struct uart_port *port)
jsm_carrier(channel);
channel->ch_open_count++;
+ spin_unlock_irqrestore(&port->lock, lock_flags);
jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n");
return 0;
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
index 3e7c6ee8e4b3..55c3c9db7462 100644
--- a/drivers/tty/serial/kgdb_nmi.c
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -330,17 +330,16 @@ int kgdb_register_nmi_console(void)
if (!arch_kgdb_ops.enable_nmi)
return 0;
- kgdb_nmi_tty_driver = alloc_tty_driver(1);
- if (!kgdb_nmi_tty_driver) {
+ kgdb_nmi_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
+ if (IS_ERR(kgdb_nmi_tty_driver)) {
pr_err("%s: cannot allocate tty\n", __func__);
- return -ENOMEM;
+ return PTR_ERR(kgdb_nmi_tty_driver);
}
kgdb_nmi_tty_driver->driver_name = "ttyNMI";
kgdb_nmi_tty_driver->name = "ttyNMI";
kgdb_nmi_tty_driver->num = 1;
kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW;
kgdb_nmi_tty_driver->init_termios = tty_std_termios;
tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios,
KGDB_NMI_BAUD, KGDB_NMI_BAUD);
@@ -356,7 +355,7 @@ int kgdb_register_nmi_console(void)
return 0;
err_drv_reg:
- put_tty_driver(kgdb_nmi_tty_driver);
+ tty_driver_kref_put(kgdb_nmi_tty_driver);
return ret;
}
EXPORT_SYMBOL_GPL(kgdb_register_nmi_console);
@@ -374,7 +373,7 @@ int kgdb_unregister_nmi_console(void)
return ret;
tty_unregister_driver(kgdb_nmi_tty_driver);
- put_tty_driver(kgdb_nmi_tty_driver);
+ tty_driver_kref_put(kgdb_nmi_tty_driver);
return 0;
}
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index ef11860cd69e..3df0788ddeb0 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1271,18 +1271,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
/* Always ask for fixed clock rate from a property. */
device_property_read_u32(dev, "clock-frequency", &uartclk);
- s->clk = devm_clk_get_optional(dev, "osc");
+ xtal = device_property_match_string(dev, "clock-names", "osc") < 0;
+ if (xtal)
+ s->clk = devm_clk_get_optional(dev, "xtal");
+ else
+ s->clk = devm_clk_get_optional(dev, "osc");
if (IS_ERR(s->clk))
return PTR_ERR(s->clk);
- if (s->clk) {
- xtal = false;
- } else {
- s->clk = devm_clk_get_optional(dev, "xtal");
- if (IS_ERR(s->clk))
- return PTR_ERR(s->clk);
-
- xtal = true;
- }
ret = clk_prepare_enable(s->clk);
if (ret)
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
index be640d9863cd..643dfbcc43f9 100644
--- a/drivers/tty/serial/mux.c
+++ b/drivers/tty/serial/mux.c
@@ -496,7 +496,7 @@ static int __init mux_probe(struct parisc_device *dev)
return 0;
}
-static int __exit mux_remove(struct parisc_device *dev)
+static void __exit mux_remove(struct parisc_device *dev)
{
int i, j;
int port_count = (long)dev_get_drvdata(&dev->dev);
@@ -518,7 +518,6 @@ static int __exit mux_remove(struct parisc_device *dev)
}
release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET);
- return 0;
}
/* Hack. This idea was taken from the 8250_gsc.c on how to properly order
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 9e81b09ba08e..0862941862c8 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -276,11 +276,8 @@ static void serial_omap_enable_ms(struct uart_port *port)
dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line);
- pm_runtime_get_sync(up->dev);
up->ier |= UART_IER_MSI;
serial_out(up, UART_IER, up->ier);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_stop_tx(struct uart_port *port)
@@ -288,8 +285,6 @@ static void serial_omap_stop_tx(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
int res;
- pm_runtime_get_sync(up->dev);
-
/* Handle RS-485 */
if (port->rs485.flags & SER_RS485_ENABLED) {
if (up->scr & OMAP_UART_SCR_TX_EMPTY) {
@@ -330,21 +325,15 @@ static void serial_omap_stop_tx(struct uart_port *port)
up->ier &= ~UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
}
-
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_stop_rx(struct uart_port *port)
{
struct uart_omap_port *up = to_uart_omap_port(port);
- pm_runtime_get_sync(up->dev);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
up->port.read_status_mask &= ~UART_LSR_DR;
serial_out(up, UART_IER, up->ier);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
@@ -399,8 +388,6 @@ static void serial_omap_start_tx(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
int res;
- pm_runtime_get_sync(up->dev);
-
/* Handle RS-485 */
if (port->rs485.flags & SER_RS485_ENABLED) {
/* Fire THR interrupts when FIFO is below trigger level */
@@ -421,8 +408,6 @@ static void serial_omap_start_tx(struct uart_port *port)
up->rs485_tx_filter_count = 0;
serial_omap_enable_ier_thri(up);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_throttle(struct uart_port *port)
@@ -430,13 +415,10 @@ static void serial_omap_throttle(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags;
- pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
serial_out(up, UART_IER, up->ier);
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_unthrottle(struct uart_port *port)
@@ -444,13 +426,10 @@ static void serial_omap_unthrottle(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags;
- pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
up->ier |= UART_IER_RLSI | UART_IER_RDI;
serial_out(up, UART_IER, up->ier);
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static unsigned int check_modem_status(struct uart_omap_port *up)
@@ -576,7 +555,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
int max_count = 256;
spin_lock(&up->port.lock);
- pm_runtime_get_sync(up->dev);
do {
iir = serial_in(up, UART_IIR);
@@ -616,8 +594,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
tty_flip_buffer_push(&up->port.state->port);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
return ret;
@@ -629,13 +605,11 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
unsigned long flags;
unsigned int ret = 0;
- pm_runtime_get_sync(up->dev);
dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line);
spin_lock_irqsave(&up->port.lock, flags);
ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
+
return ret;
}
@@ -645,10 +619,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
unsigned int status;
unsigned int ret = 0;
- pm_runtime_get_sync(up->dev);
status = check_modem_status(up);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line);
@@ -680,7 +651,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
- pm_runtime_get_sync(up->dev);
old_mcr = serial_in(up, UART_MCR);
old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 |
UART_MCR_DTR | UART_MCR_RTS);
@@ -696,9 +666,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
up->efr &= ~UART_EFR_RTS;
serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, lcr);
-
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
@@ -707,7 +674,6 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
unsigned long flags;
dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
- pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
@@ -715,8 +681,6 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
up->lcr &= ~UART_LCR_SBC;
serial_out(up, UART_LCR, up->lcr);
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static int serial_omap_startup(struct uart_port *port)
@@ -788,8 +752,6 @@ static int serial_omap_startup(struct uart_port *port)
serial_out(up, UART_OMAP_WER, up->wer);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
return 0;
}
@@ -801,7 +763,6 @@ static void serial_omap_shutdown(struct uart_port *port)
dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line);
- pm_runtime_get_sync(up->dev);
/*
* Disable interrupts from this port
*/
@@ -825,8 +786,7 @@ static void serial_omap_shutdown(struct uart_port *port)
if (serial_in(up, UART_LSR) & UART_LSR_DR)
(void) serial_in(up, UART_RX);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
+ pm_runtime_put_sync(up->dev);
free_irq(up->port.irq, up);
dev_pm_clear_wake_irq(up->dev);
}
@@ -896,7 +856,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
- pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
/*
@@ -1096,8 +1055,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_omap_set_mctrl(&up->port, up->port.mctrl);
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
}
@@ -1110,7 +1067,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line);
- pm_runtime_get_sync(up->dev);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
@@ -1120,9 +1076,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, efr);
serial_out(up, UART_LCR, 0);
-
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_release_port(struct uart_port *port)
@@ -1202,11 +1155,8 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
{
struct uart_omap_port *up = to_uart_omap_port(port);
- pm_runtime_get_sync(up->dev);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
}
static int serial_omap_poll_get_char(struct uart_port *port)
@@ -1214,7 +1164,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned int status;
- pm_runtime_get_sync(up->dev);
status = serial_in(up, UART_LSR);
if (!(status & UART_LSR_DR)) {
status = NO_POLL_CHAR;
@@ -1224,9 +1173,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
status = serial_in(up, UART_RX);
out:
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
-
return status;
}
@@ -1309,8 +1255,6 @@ serial_omap_console_write(struct console *co, const char *s,
unsigned int ier;
int locked = 1;
- pm_runtime_get_sync(up->dev);
-
local_irq_save(flags);
if (up->port.sysrq)
locked = 0;
@@ -1343,8 +1287,6 @@ serial_omap_console_write(struct console *co, const char *s,
if (up->msr_saved_flags)
check_modem_status(up);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
if (locked)
spin_unlock(&up->port.lock);
local_irq_restore(flags);
@@ -1403,8 +1345,6 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
unsigned int mode;
int val;
- pm_runtime_get_sync(up->dev);
-
/* Disable interrupts from this port */
mode = up->ier;
up->ier = 0;
@@ -1438,9 +1378,6 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
serial_out(up, UART_OMAP_SCR, up->scr);
}
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
-
return 0;
}
@@ -1737,11 +1674,7 @@ static int serial_omap_probe(struct platform_device *pdev)
omap_up_info->autosuspend_timeout = -1;
device_init_wakeup(up->dev, true);
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_autosuspend_delay(&pdev->dev,
- omap_up_info->autosuspend_timeout);
- pm_runtime_irq_safe(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
@@ -1755,12 +1688,9 @@ static int serial_omap_probe(struct platform_device *pdev)
if (ret != 0)
goto err_add_port;
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
return 0;
err_add_port:
- pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
cpu_latency_qos_remove_request(&up->pm_qos_request);
@@ -1778,7 +1708,6 @@ static int serial_omap_remove(struct platform_device *dev)
uart_remove_one_port(&serial_omap_reg, &up->port);
- pm_runtime_dont_use_autosuspend(up->dev);
pm_runtime_put_sync(up->dev);
pm_runtime_disable(up->dev);
cpu_latency_qos_remove_request(&up->pm_qos_request);
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index 9fbc61151c2e..e2f49863e9c2 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -65,6 +65,7 @@ enum s3c24xx_port_type {
struct s3c24xx_uart_info {
char *name;
enum s3c24xx_port_type type;
+ unsigned int has_usi;
unsigned int port_type;
unsigned int fifosize;
unsigned long rx_fifomask;
@@ -305,8 +306,9 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
dmaengine_pause(dma->tx_chan);
dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
dmaengine_terminate_all(dma->tx_chan);
- dma_sync_single_for_cpu(ourport->port.dev,
- dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(dma->tx_chan->device->dev,
+ dma->tx_transfer_addr, dma->tx_size,
+ DMA_TO_DEVICE);
async_tx_ack(dma->tx_desc);
count = dma->tx_bytes_requested - state.residue;
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
@@ -338,8 +340,9 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
count = dma->tx_bytes_requested - state.residue;
async_tx_ack(dma->tx_desc);
- dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr,
- dma->tx_size, DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(dma->tx_chan->device->dev,
+ dma->tx_transfer_addr, dma->tx_size,
+ DMA_TO_DEVICE);
spin_lock_irqsave(&port->lock, flags);
@@ -443,8 +446,9 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
- dma_sync_single_for_device(ourport->port.dev, dma->tx_transfer_addr,
- dma->tx_size, DMA_TO_DEVICE);
+ dma_sync_single_for_device(dma->tx_chan->device->dev,
+ dma->tx_transfer_addr, dma->tx_size,
+ DMA_TO_DEVICE);
dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan,
dma->tx_transfer_addr, dma->tx_size,
@@ -515,7 +519,7 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport,
if (!count)
return;
- dma_sync_single_for_cpu(ourport->port.dev, dma->rx_addr,
+ dma_sync_single_for_cpu(dma->rx_chan->device->dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
ourport->port.icount.rx += count;
@@ -636,8 +640,8 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
{
struct s3c24xx_uart_dma *dma = ourport->dma;
- dma_sync_single_for_device(ourport->port.dev, dma->rx_addr,
- dma->rx_size, DMA_FROM_DEVICE);
+ dma_sync_single_for_device(dma->rx_chan->device->dev, dma->rx_addr,
+ dma->rx_size, DMA_FROM_DEVICE);
dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan,
dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM,
@@ -1102,18 +1106,19 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
goto err_release_tx;
}
- dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf,
- dma->rx_size, DMA_FROM_DEVICE);
- if (dma_mapping_error(p->port.dev, dma->rx_addr)) {
+ dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
+ dma->rx_size, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dma->rx_chan->device->dev, dma->rx_addr)) {
reason = "DMA mapping error for RX buffer";
ret = -EIO;
goto err_free_rx;
}
/* TX buffer */
- dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf,
- UART_XMIT_SIZE, DMA_TO_DEVICE);
- if (dma_mapping_error(p->port.dev, dma->tx_addr)) {
+ dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
+ p->port.state->xmit.buf, UART_XMIT_SIZE,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) {
reason = "DMA mapping error for TX buffer";
ret = -EIO;
goto err_unmap_rx;
@@ -1122,8 +1127,8 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
return 0;
err_unmap_rx:
- dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size,
- DMA_FROM_DEVICE);
+ dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
+ dma->rx_size, DMA_FROM_DEVICE);
err_free_rx:
kfree(dma->rx_buf);
err_release_tx:
@@ -1142,8 +1147,8 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
if (dma->rx_chan) {
dmaengine_terminate_all(dma->rx_chan);
- dma_unmap_single(p->port.dev, dma->rx_addr,
- dma->rx_size, DMA_FROM_DEVICE);
+ dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
+ dma->rx_size, DMA_FROM_DEVICE);
kfree(dma->rx_buf);
dma_release_channel(dma->rx_chan);
dma->rx_chan = NULL;
@@ -1151,8 +1156,8 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
if (dma->tx_chan) {
dmaengine_terminate_all(dma->tx_chan);
- dma_unmap_single(p->port.dev, dma->tx_addr,
- UART_XMIT_SIZE, DMA_TO_DEVICE);
+ dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
+ UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_release_channel(dma->tx_chan);
dma->tx_chan = NULL;
}
@@ -1352,6 +1357,28 @@ static int apple_s5l_serial_startup(struct uart_port *port)
return ret;
}
+static void exynos_usi_init(struct uart_port *port)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ struct s3c24xx_uart_info *info = ourport->info;
+ unsigned int val;
+
+ if (!info->has_usi)
+ return;
+
+ /* Clear the software reset of USI block (it's set at startup) */
+ val = rd_regl(port, USI_CON);
+ val &= ~USI_CON_RESET_MASK;
+ wr_regl(port, USI_CON, val);
+ udelay(1);
+
+ /* Continuously provide the clock to USI IP w/o gating (for Rx mode) */
+ val = rd_regl(port, USI_OPTION);
+ val &= ~USI_OPTION_HWACG_MASK;
+ val |= USI_OPTION_HWACG_CLKREQ_ON;
+ wr_regl(port, USI_OPTION, val);
+}
+
/* power power management control */
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
@@ -1379,6 +1406,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
if (!IS_ERR(ourport->baudclk))
clk_prepare_enable(ourport->baudclk);
+ exynos_usi_init(port);
break;
default:
dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
@@ -2102,6 +2130,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
if (ret)
pr_warn("uart: failed to enable baudclk\n");
+ exynos_usi_init(port);
+
/* Keep all interrupts masked and cleared */
switch (ourport->info->type) {
case TYPE_S3C6400:
@@ -2750,10 +2780,11 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
#endif
#if defined(CONFIG_ARCH_EXYNOS)
-#define EXYNOS_COMMON_SERIAL_DRV_DATA \
+#define EXYNOS_COMMON_SERIAL_DRV_DATA_USI(_has_usi) \
.info = &(struct s3c24xx_uart_info) { \
.name = "Samsung Exynos UART", \
.type = TYPE_S3C6400, \
+ .has_usi = _has_usi, \
.port_type = PORT_S3C6400, \
.has_divslot = 1, \
.rx_fifomask = S5PV210_UFSTAT_RXMASK, \
@@ -2773,6 +2804,9 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.has_fracval = 1, \
} \
+#define EXYNOS_COMMON_SERIAL_DRV_DATA \
+ EXYNOS_COMMON_SERIAL_DRV_DATA_USI(0)
+
static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA,
.fifosize = { 256, 64, 16, 16 },
@@ -2783,11 +2817,19 @@ static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
.fifosize = { 64, 256, 16, 256 },
};
+static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
+ EXYNOS_COMMON_SERIAL_DRV_DATA_USI(1),
+ .fifosize = { 256, 64, 64, 64 },
+};
+
#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos5433_serial_drv_data)
+#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos850_serial_drv_data)
+
#else
-#define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
-#define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL
+#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
+#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
+#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#endif
#ifdef CONFIG_ARCH_APPLE
@@ -2843,6 +2885,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
}, {
.name = "s5l-uart",
.driver_data = S5L_SERIAL_DRV_DATA,
+ }, {
+ .name = "exynos850-uart",
+ .driver_data = EXYNOS850_SERIAL_DRV_DATA,
},
{ },
};
@@ -2866,6 +2911,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
.data = (void *)EXYNOS5433_SERIAL_DRV_DATA },
{ .compatible = "apple,s5l-uart",
.data = (void *)S5L_SERIAL_DRV_DATA },
+ { .compatible = "samsung,exynos850-uart",
+ .data = (void *)EXYNOS850_SERIAL_DRV_DATA },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index eba5b9ecba34..45e2e4109acd 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -1568,14 +1568,12 @@ static int tegra_uart_probe(struct platform_device *pdev)
struct resource *resource;
int ret;
const struct tegra_uart_chip_data *cdata;
- const struct of_device_id *match;
- match = of_match_device(tegra_uart_of_match, &pdev->dev);
- if (!match) {
+ cdata = of_device_get_match_data(&pdev->dev);
+ if (!cdata) {
dev_err(&pdev->dev, "Error: No device match found\n");
return -ENODEV;
}
- cdata = match->data;
tup = devm_kzalloc(&pdev->dev, sizeof(*tup), GFP_KERNEL);
if (!tup) {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 69092deba11f..0e2e35ab64c7 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2314,6 +2314,14 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
port->dev ? ": " : "",
port->name,
address, port->irq, port->uartclk / 16, uart_type(port));
+
+ /* The magic multiplier feature is a bit obscure, so report it too. */
+ if (port->flags & UPF_MAGIC_MULTIPLIER)
+ pr_info("%s%s%s extra baud rates supported: %d, %d",
+ port->dev ? dev_name(port->dev) : "",
+ port->dev ? ": " : "",
+ port->name,
+ port->uartclk / 8, port->uartclk / 4);
}
static void
@@ -2522,9 +2530,12 @@ int uart_register_driver(struct uart_driver *drv)
if (!drv->state)
goto out;
- normal = alloc_tty_driver(drv->nr);
- if (!normal)
+ normal = tty_alloc_driver(drv->nr, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(normal)) {
+ retval = PTR_ERR(normal);
goto out_kfree;
+ }
drv->tty_driver = normal;
@@ -2537,7 +2548,6 @@ int uart_register_driver(struct uart_driver *drv)
normal->init_termios = tty_std_termios;
normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
- normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
normal->driver_state = drv;
tty_set_operations(normal, &uart_ops);
@@ -2558,7 +2568,7 @@ int uart_register_driver(struct uart_driver *drv)
for (i = 0; i < drv->nr; i++)
tty_port_destroy(&drv->state[i].port);
- put_tty_driver(normal);
+ tty_driver_kref_put(normal);
out_kfree:
kfree(drv->state);
out:
@@ -2580,7 +2590,7 @@ void uart_unregister_driver(struct uart_driver *drv)
unsigned int i;
tty_unregister_driver(p);
- put_tty_driver(p);
+ tty_driver_kref_put(p);
for (i = 0; i < drv->nr; i++)
tty_port_destroy(&drv->state[i].port);
kfree(drv->state);
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 07eb56294371..89ee43061d3a 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1758,6 +1758,10 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
/* Handle BREAKs */
sci_handle_breaks(port);
+
+ /* drop invalid character received before break was detected */
+ serial_port_in(port, SCxRDR);
+
sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
return IRQ_HANDLED;
@@ -1837,7 +1841,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
ret = sci_er_interrupt(irq, ptr);
/* Break Interrupt */
- if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
+ if (s->irqs[SCIx_ERI_IRQ] != s->irqs[SCIx_BRI_IRQ] &&
+ (ssr_status & SCxSR_BRK(port)) && err_enabled)
ret = sci_br_interrupt(irq, ptr);
/* Overrun Interrupt */
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index ef793b3b4591..8f032e77b954 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -1034,8 +1034,8 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
int ret, irq;
irq = platform_get_irq(pdev, 0);
- if (irq <= 0)
- return irq ? : -ENODEV;
+ if (irq < 0)
+ return irq;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
@@ -1064,8 +1064,7 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
&stm32port->txftcfg);
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- port->membase = devm_ioremap_resource(&pdev->dev, res);
+ port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);
port->mapbase = res->start;
@@ -1177,7 +1176,7 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
if (uart_console(port))
return -ENODEV;
- stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L,
+ stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L,
&stm32port->rx_dma_buf,
GFP_KERNEL);
if (!stm32port->rx_buf)
@@ -1243,7 +1242,7 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port,
stm32port->tx_dma_busy = false;
- stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L,
+ stm32port->tx_buf = dma_alloc_coherent(dev, TX_BUF_L,
&stm32port->tx_dma_buf,
GFP_KERNEL);
if (!stm32port->tx_buf)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index a5f15f22d9ef..dfc1ba4e1572 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -17,11 +17,13 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#define ULITE_NAME "ttyUL"
#define ULITE_MAJOR 204
@@ -54,6 +56,7 @@
#define ULITE_CONTROL_RST_TX 0x01
#define ULITE_CONTROL_RST_RX 0x02
#define ULITE_CONTROL_IE 0x10
+#define UART_AUTOSUSPEND_TIMEOUT 3000 /* ms */
/* Static pointer to console port */
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
@@ -390,12 +393,16 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
static void ulite_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
- struct uartlite_data *pdata = port->private_data;
+ int ret;
- if (!state)
- clk_enable(pdata->clk);
- else
- clk_disable(pdata->clk);
+ if (!state) {
+ ret = pm_runtime_get_sync(port->dev);
+ if (ret < 0)
+ dev_err(port->dev, "Failed to enable clocks\n");
+ } else {
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_autosuspend(port->dev);
+ }
}
#ifdef CONFIG_CONSOLE_POLL
@@ -448,24 +455,15 @@ static const struct uart_ops ulite_ops = {
static void ulite_console_wait_tx(struct uart_port *port)
{
u8 val;
- unsigned long timeout;
/*
* Spin waiting for TX fifo to have space available.
* When using the Microblaze Debug Module this can take up to 1s
*/
- timeout = jiffies + msecs_to_jiffies(1000);
- while (1) {
- val = uart_in32(ULITE_STATUS, port);
- if ((val & ULITE_STATUS_TXFULL) == 0)
- break;
- if (time_after(jiffies, timeout)) {
- dev_warn(port->dev,
- "timeout waiting for TX buffer empty\n");
- break;
- }
- cpu_relax();
- }
+ if (read_poll_timeout_atomic(uart_in32, val, !(val & ULITE_STATUS_TXFULL),
+ 0, 1000000, false, ULITE_STATUS, port))
+ dev_warn(port->dev,
+ "timeout waiting for TX buffer empty\n");
}
static void ulite_console_putchar(struct uart_port *port, int ch)
@@ -555,16 +553,15 @@ static void early_uartlite_putc(struct uart_port *port, int c)
* This limit is pretty arbitrary, unless we are at about 10 baud
* we'll never timeout on a working UART.
*/
-
unsigned retries = 1000000;
- /* read status bit - 0x8 offset */
- while (--retries && (readl(port->membase + 8) & (1 << 3)))
+
+ while (--retries &&
+ (readl(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL))
;
/* Only attempt the iowrite if we didn't timeout */
- /* write to TX_FIFO - 0x4 offset */
if (retries)
- writel(c & 0xff, port->membase + 4);
+ writel(c & 0xff, port->membase + ULITE_TX);
}
static void early_uartlite_write(struct console *console,
@@ -719,11 +716,38 @@ static int __maybe_unused ulite_resume(struct device *dev)
return 0;
}
+static int __maybe_unused ulite_runtime_suspend(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
+
+ clk_disable(pdata->clk);
+ return 0;
+};
+
+static int __maybe_unused ulite_runtime_resume(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
+ int ret;
+
+ ret = clk_enable(pdata->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock.\n");
+ return ret;
+ }
+ return 0;
+}
+
/* ---------------------------------------------------------------------
* Platform bus binding
*/
-static SIMPLE_DEV_PM_OPS(ulite_pm_ops, ulite_suspend, ulite_resume);
+static const struct dev_pm_ops ulite_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ulite_suspend, ulite_resume)
+ SET_RUNTIME_PM_OPS(ulite_runtime_suspend,
+ ulite_runtime_resume, NULL)
+};
#if defined(CONFIG_OF)
/* Match table for of_platform binding */
@@ -779,18 +803,25 @@ static int ulite_probe(struct platform_device *pdev)
return ret;
}
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
if (!ulite_uart_driver.state) {
dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
ret = uart_register_driver(&ulite_uart_driver);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register driver\n");
+ clk_disable_unprepare(pdata->clk);
return ret;
}
}
ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
- clk_disable(pdata->clk);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
return ret;
}
@@ -799,9 +830,14 @@ static int ulite_remove(struct platform_device *pdev)
{
struct uart_port *port = dev_get_drvdata(&pdev->dev);
struct uartlite_data *pdata = port->private_data;
+ int rc;
clk_disable_unprepare(pdata->clk);
- return ulite_release(&pdev->dev);
+ rc = ulite_release(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ return rc;
}
/* work with hotplug and coldplug */
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index c5edd56ff830..e15b2bf69904 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -623,17 +623,14 @@ static int vt8500_serial_probe(struct platform_device *pdev)
struct vt8500_port *vt8500_port;
struct resource *mmres, *irqres;
struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *match;
const unsigned int *flags;
int ret;
int port;
- match = of_match_device(wmt_dt_ids, &pdev->dev);
- if (!match)
+ flags = of_device_get_match_data(&pdev->dev);
+ if (!flags)
return -EINVAL;
- flags = match->data;
-
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!mmres || !irqres)
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index 3e3b8873fa29..a9acd93e85b7 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -3647,7 +3647,7 @@ static void slgt_cleanup(void)
for (info=slgt_device_list ; info != NULL ; info=info->next_device)
tty_unregister_device(serial_driver, info->line);
tty_unregister_driver(serial_driver);
- put_tty_driver(serial_driver);
+ tty_driver_kref_put(serial_driver);
}
/* reset devices */
@@ -3686,10 +3686,11 @@ static int __init slgt_init(void)
printk(KERN_INFO "%s\n", driver_name);
- serial_driver = alloc_tty_driver(MAX_DEVICES);
- if (!serial_driver) {
+ serial_driver = tty_alloc_driver(MAX_DEVICES, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(serial_driver)) {
printk("%s can't allocate tty driver\n", driver_name);
- return -ENOMEM;
+ return PTR_ERR(serial_driver);
}
/* Initialize the tty_driver structure */
@@ -3705,11 +3706,10 @@ static int __init slgt_init(void)
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver->init_termios.c_ispeed = 9600;
serial_driver->init_termios.c_ospeed = 9600;
- serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(serial_driver, &ops);
if ((rc = tty_register_driver(serial_driver)) < 0) {
DBGERR(("%s can't register serial driver\n", driver_name));
- put_tty_driver(serial_driver);
+ tty_driver_kref_put(serial_driver);
serial_driver = NULL;
goto error;
}
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 6628792431dc..c911196ac893 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -258,7 +258,7 @@ static void sysrq_handle_showallcpus(int key)
if (!trigger_all_cpu_backtrace()) {
struct pt_regs *regs = NULL;
- if (in_irq())
+ if (in_hardirq())
regs = get_irq_regs();
if (regs) {
pr_info("CPU%d:\n", smp_processor_id());
@@ -280,7 +280,7 @@ static void sysrq_handle_showregs(int key)
{
struct pt_regs *regs = NULL;
- if (in_irq())
+ if (in_hardirq())
regs = get_irq_regs();
if (regs)
show_regs(regs);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 26debec26b4e..6616d4a0d41d 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2290,8 +2290,6 @@ static int tty_fasync(int fd, struct file *filp, int on)
* Locking:
* Called functions take tty_ldiscs_lock
* current->signal->tty check is safe without locks
- *
- * FIXME: may race normal receive processing
*/
static int tiocsti(struct tty_struct *tty, char __user *p)
@@ -2307,8 +2305,10 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
ld = tty_ldisc_ref_wait(tty);
if (!ld)
return -EIO;
+ tty_buffer_lock_exclusive(tty->port);
if (ld->ops->receive_buf)
ld->ops->receive_buf(tty, &ch, &mbz, 1);
+ tty_buffer_unlock_exclusive(tty->port);
tty_ldisc_deref(ld);
return 0;
}
@@ -3438,19 +3438,6 @@ void tty_driver_kref_put(struct tty_driver *driver)
}
EXPORT_SYMBOL(tty_driver_kref_put);
-void tty_set_operations(struct tty_driver *driver,
- const struct tty_operations *op)
-{
- driver->ops = op;
-};
-EXPORT_SYMBOL(tty_set_operations);
-
-void put_tty_driver(struct tty_driver *d)
-{
- tty_driver_kref_put(d);
-}
-EXPORT_SYMBOL(put_tty_driver);
-
/*
* Called by a tty driver to register itself.
*/
diff --git a/drivers/tty/ttynull.c b/drivers/tty/ttynull.c
index af3311a24917..1d4438472442 100644
--- a/drivers/tty/ttynull.c
+++ b/drivers/tty/ttynull.c
@@ -84,7 +84,7 @@ static int __init ttynull_init(void)
ret = tty_register_driver(driver);
if (ret < 0) {
- put_tty_driver(driver);
+ tty_driver_kref_put(driver);
tty_port_destroy(&ttynull_port);
return ret;
}
@@ -99,7 +99,7 @@ static void __exit ttynull_exit(void)
{
unregister_console(&ttynull_console);
tty_unregister_driver(ttynull_driver);
- put_tty_driver(ttynull_driver);
+ tty_driver_kref_put(ttynull_driver);
tty_port_destroy(&ttynull_port);
}
diff --git a/drivers/tty/vcc.c b/drivers/tty/vcc.c
index d06bcc3b4c07..e11383ae1e7e 100644
--- a/drivers/tty/vcc.c
+++ b/drivers/tty/vcc.c
@@ -1028,7 +1028,7 @@ static int vcc_tty_init(void)
rv = tty_register_driver(vcc_tty_driver);
if (rv) {
pr_err("VCC: TTY driver registration failed\n");
- put_tty_driver(vcc_tty_driver);
+ tty_driver_kref_put(vcc_tty_driver);
vcc_tty_driver = NULL;
return rv;
}
@@ -1041,7 +1041,7 @@ static int vcc_tty_init(void)
static void vcc_tty_exit(void)
{
tty_unregister_driver(vcc_tty_driver);
- put_tty_driver(vcc_tty_driver);
+ tty_driver_kref_put(vcc_tty_driver);
vccdbg("VCC: TTY driver unregistered\n");
vcc_tty_driver = NULL;
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 4b0d69042ceb..c7fbbcdcc346 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1171,9 +1171,9 @@ static inline unsigned char getleds(void)
*
* Check the status of a keyboard led flag and report it back
*/
-int vt_get_leds(int console, int flag)
+int vt_get_leds(unsigned int console, int flag)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
int ret;
unsigned long flags;
@@ -1193,9 +1193,9 @@ EXPORT_SYMBOL_GPL(vt_get_leds);
* Set the LEDs on a console. This is a wrapper for the VT layer
* so that we can keep kbd knowledge internal
*/
-void vt_set_led_state(int console, int leds)
+void vt_set_led_state(unsigned int console, int leds)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
setledstate(kb, leds);
}
@@ -1212,9 +1212,9 @@ void vt_set_led_state(int console, int leds)
* don't hold the lock. We probably need to split out an LED lock
* but not during an -rc release!
*/
-void vt_kbd_con_start(int console)
+void vt_kbd_con_start(unsigned int console)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&led_lock, flags);
clr_vc_kbd_led(kb, VC_SCROLLOCK);
@@ -1229,9 +1229,9 @@ void vt_kbd_con_start(int console)
* Handle console stop. This is a wrapper for the VT layer
* so that we can keep kbd knowledge internal
*/
-void vt_kbd_con_stop(int console)
+void vt_kbd_con_stop(unsigned int console)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&led_lock, flags);
set_vc_kbd_led(kb, VC_SCROLLOCK);
@@ -1377,7 +1377,7 @@ static void kbd_rawcode(unsigned char data)
{
struct vc_data *vc = vc_cons[fg_console].d;
- kbd = kbd_table + vc->vc_num;
+ kbd = &kbd_table[vc->vc_num];
if (kbd->kbdmode == VC_RAW)
put_queue(vc, data);
}
@@ -1400,7 +1400,7 @@ static void kbd_keycode(unsigned int keycode, int down, bool hw_raw)
tty->driver_data = vc;
}
- kbd = kbd_table + vc->vc_num;
+ kbd = &kbd_table[vc->vc_num];
#ifdef CONFIG_SPARC
if (keycode == KEY_STOP)
@@ -1825,9 +1825,9 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
* Update the keyboard mode bits while holding the correct locks.
* Return 0 for success or an error code.
*/
-int vt_do_kdskbmode(int console, unsigned int arg)
+int vt_do_kdskbmode(unsigned int console, unsigned int arg)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
int ret = 0;
unsigned long flags;
@@ -1865,9 +1865,9 @@ int vt_do_kdskbmode(int console, unsigned int arg)
* Update the keyboard meta bits while holding the correct locks.
* Return 0 for success or an error code.
*/
-int vt_do_kdskbmeta(int console, unsigned int arg)
+int vt_do_kdskbmeta(unsigned int console, unsigned int arg)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
int ret = 0;
unsigned long flags;
@@ -2008,9 +2008,9 @@ out:
}
int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
- int console)
+ unsigned int console)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
struct kbentry kbe;
if (copy_from_user(&kbe, user_kbe, sizeof(struct kbentry)))
@@ -2097,9 +2097,9 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
return ret;
}
-int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
+int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
unsigned char ucval;
@@ -2139,9 +2139,9 @@ int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
return -ENOIOCTLCMD;
}
-int vt_do_kdgkbmode(int console)
+int vt_do_kdgkbmode(unsigned int console)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
/* This is a spot read so needs no locking */
switch (kb->kbdmode) {
case VC_RAW:
@@ -2163,9 +2163,9 @@ int vt_do_kdgkbmode(int console)
*
* Report the meta flag status of this console
*/
-int vt_do_kdgkbmeta(int console)
+int vt_do_kdgkbmeta(unsigned int console)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
/* Again a spot read so no locking */
return vc_kbd_mode(kb, VC_META) ? K_ESCPREFIX : K_METABIT;
}
@@ -2176,7 +2176,7 @@ int vt_do_kdgkbmeta(int console)
*
* Restore the unicode console state to its default
*/
-void vt_reset_unicode(int console)
+void vt_reset_unicode(unsigned int console)
{
unsigned long flags;
@@ -2204,9 +2204,9 @@ int vt_get_shift_state(void)
* Reset the keyboard bits for a console as part of a general console
* reset event
*/
-void vt_reset_keyboard(int console)
+void vt_reset_keyboard(unsigned int console)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&kbd_event_lock, flags);
@@ -2234,9 +2234,9 @@ void vt_reset_keyboard(int console)
* caller must be sure that there are no synchronization needs
*/
-int vt_get_kbd_mode_bit(int console, int bit)
+int vt_get_kbd_mode_bit(unsigned int console, int bit)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
return vc_kbd_mode(kb, bit);
}
@@ -2249,9 +2249,9 @@ int vt_get_kbd_mode_bit(int console, int bit)
* caller must be sure that there are no synchronization needs
*/
-void vt_set_kbd_mode_bit(int console, int bit)
+void vt_set_kbd_mode_bit(unsigned int console, int bit)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&kbd_event_lock, flags);
@@ -2268,9 +2268,9 @@ void vt_set_kbd_mode_bit(int console, int bit)
* caller must be sure that there are no synchronization needs
*/
-void vt_clr_kbd_mode_bit(int console, int bit)
+void vt_clr_kbd_mode_bit(unsigned int console, int bit)
{
- struct kbd_struct *kb = kbd_table + console;
+ struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&kbd_event_lock, flags);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index cb72393f92d3..7359c3e80d63 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1219,8 +1219,25 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
new_row_size = new_cols << 1;
new_screen_size = new_row_size * new_rows;
- if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
- return 0;
+ if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) {
+ /*
+ * This function is being called here to cover the case
+ * where the userspace calls the FBIOPUT_VSCREENINFO twice,
+ * passing the same fb_var_screeninfo containing the fields
+ * yres/xres equal to a number non-multiple of vc_font.height
+ * and yres_virtual/xres_virtual equal to number lesser than the
+ * vc_font.height and yres/xres.
+ * In the second call, the struct fb_var_screeninfo isn't
+ * being modified by the underlying driver because of the
+ * if above, and this causes the fbcon_display->vrows to become
+ * negative and it eventually leads to out-of-bound
+ * access by the imageblit function.
+ * To give the correct values to the struct and to not have
+ * to deal with possible errors from the code below, we call
+ * the resize_screen here as well.
+ */
+ return resize_screen(vc, new_cols, new_rows, user);
+ }
if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
return -EINVAL;
@@ -3582,8 +3599,9 @@ int __init vty_init(const struct file_operations *console_fops)
vcs_init();
- console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
- if (!console_driver)
+ console_driver = tty_alloc_driver(MAX_NR_CONSOLES, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_RESET_TERMIOS);
+ if (IS_ERR(console_driver))
panic("Couldn't allocate console driver\n");
console_driver->name = "tty";
@@ -3594,7 +3612,6 @@ int __init vty_init(const struct file_operations *console_fops)
console_driver->init_termios = tty_std_termios;
if (default_utf8)
console_driver->init_termios.c_iflag |= IUTF8;
- console_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
tty_set_operations(console_driver, &con_ops);
if (tty_register_driver(console_driver))
panic("Couldn't register console driver\n");
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 26475b409b53..578a439e71b5 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -11,7 +11,7 @@ config USB_OHCI_BIG_ENDIAN_MMIO
config USB_OHCI_LITTLE_ENDIAN
bool
- default n if STB03xxx || PPC_MPC52xx
+ default n if PPC_MPC52xx
default y
config USB_EHCI_BIG_ENDIAN_MMIO
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 3e2cc95b7b0b..643edf5fe18c 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
obj-$(CONFIG_USB_ISP1362_HCD) += host/
obj-$(CONFIG_USB_U132_HCD) += host/
obj-$(CONFIG_USB_R8A66597_HCD) += host/
-obj-$(CONFIG_USB_HWA_HCD) += host/
obj-$(CONFIG_USB_FSL_USB2) += host/
obj-$(CONFIG_USB_FOTG210_HCD) += host/
obj-$(CONFIG_USB_MAX3421_HCD) += host/
diff --git a/drivers/usb/cdns3/cdnsp-mem.c b/drivers/usb/cdns3/cdnsp-mem.c
index a47948a1623f..ad9aee3f1e39 100644
--- a/drivers/usb/cdns3/cdnsp-mem.c
+++ b/drivers/usb/cdns3/cdnsp-mem.c
@@ -882,7 +882,7 @@ static u32 cdnsp_get_endpoint_max_burst(struct usb_gadget *g,
if (g->speed == USB_SPEED_HIGH &&
(usb_endpoint_xfer_isoc(pep->endpoint.desc) ||
usb_endpoint_xfer_int(pep->endpoint.desc)))
- return (usb_endpoint_maxp(pep->endpoint.desc) & 0x1800) >> 11;
+ return usb_endpoint_maxp_mult(pep->endpoint.desc) - 1;
return 0;
}
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index e86d13c04bdb..bdc3885c0d49 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -240,15 +240,18 @@ static int ci_ehci_hub_control(
)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ unsigned int ports = HCS_N_PORTS(ehci->hcs_params);
u32 __iomem *status_reg;
- u32 temp;
+ u32 temp, port_index;
unsigned long flags;
int retval = 0;
bool done = false;
struct device *dev = hcd->self.controller;
struct ci_hdrc *ci = dev_get_drvdata(dev);
- status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
+ port_index = wIndex & 0xff;
+ port_index -= (port_index > 0);
+ status_reg = &ehci->regs->port_status[port_index];
spin_lock_irqsave(&ehci->lock, flags);
@@ -260,6 +263,11 @@ static int ci_ehci_hub_control(
}
if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
+ if (!wIndex || wIndex > ports) {
+ retval = -EPIPE;
+ goto done;
+ }
+
temp = ehci_readl(ehci, status_reg);
if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
retval = -EPIPE;
@@ -288,7 +296,7 @@ static int ci_ehci_hub_control(
ehci_writel(ehci, temp, status_reg);
}
- set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
+ set_bit(port_index, &ehci->suspended_ports);
goto done;
}
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 4895325b16a4..8bbd8e29e60d 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -2027,16 +2027,16 @@ static const struct tty_operations acm_ops = {
static int __init acm_init(void)
{
int retval;
- acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS);
- if (!acm_tty_driver)
- return -ENOMEM;
+ acm_tty_driver = tty_alloc_driver(ACM_TTY_MINORS, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(acm_tty_driver))
+ return PTR_ERR(acm_tty_driver);
acm_tty_driver->driver_name = "acm",
acm_tty_driver->name = "ttyACM",
acm_tty_driver->major = ACM_TTY_MAJOR,
acm_tty_driver->minor_start = 0,
acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
acm_tty_driver->subtype = SERIAL_TYPE_NORMAL,
- acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
acm_tty_driver->init_termios = tty_std_termios;
acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD |
HUPCL | CLOCAL;
@@ -2044,14 +2044,14 @@ static int __init acm_init(void)
retval = tty_register_driver(acm_tty_driver);
if (retval) {
- put_tty_driver(acm_tty_driver);
+ tty_driver_kref_put(acm_tty_driver);
return retval;
}
retval = usb_register(&acm_driver);
if (retval) {
tty_unregister_driver(acm_tty_driver);
- put_tty_driver(acm_tty_driver);
+ tty_driver_kref_put(acm_tty_driver);
return retval;
}
@@ -2064,7 +2064,7 @@ static void __exit acm_exit(void)
{
usb_deregister(&acm_driver);
tty_unregister_driver(acm_tty_driver);
- put_tty_driver(acm_tty_driver);
+ tty_driver_kref_put(acm_tty_driver);
idr_destroy(&acm_minors);
}
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index 347fb3d3894a..c9bdeb4ddcb5 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -201,6 +201,26 @@ enum usb_dr_mode usb_get_dr_mode(struct device *dev)
EXPORT_SYMBOL_GPL(usb_get_dr_mode);
/**
+ * usb_get_role_switch_default_mode - Get default mode for given device
+ * @dev: Pointer to the given device
+ *
+ * The function gets string from property 'role-switch-default-mode',
+ * and returns the corresponding enum usb_dr_mode.
+ */
+enum usb_dr_mode usb_get_role_switch_default_mode(struct device *dev)
+{
+ const char *str;
+ int ret;
+
+ ret = device_property_read_string(dev, "role-switch-default-mode", &str);
+ if (ret < 0)
+ return USB_DR_MODE_UNKNOWN;
+
+ return usb_get_dr_mode_from_string(str);
+}
+EXPORT_SYMBOL_GPL(usb_get_role_switch_default_mode);
+
+/**
* usb_decode_interval - Decode bInterval into the time expressed in 1us unit
* @epd: The descriptor of the endpoint
* @speed: The speed that the endpoint works as
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index 7e13b74e60e5..4169cf40a03b 100644
--- a/drivers/usb/common/ulpi.c
+++ b/drivers/usb/common/ulpi.c
@@ -78,14 +78,12 @@ static int ulpi_probe(struct device *dev)
return drv->probe(to_ulpi_dev(dev));
}
-static int ulpi_remove(struct device *dev)
+static void ulpi_remove(struct device *dev)
{
struct ulpi_driver *drv = to_ulpi_driver(dev->driver);
if (drv->remove)
drv->remove(to_ulpi_dev(dev));
-
- return 0;
}
static struct bus_type ulpi_bus = {
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 272ae5722c86..cf0bcd0dc320 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -295,7 +295,7 @@ void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup,
if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS, GINTSTS_RESTOREDONE,
20000)) {
dev_dbg(hsotg->dev,
- "%s: Restore Done wan't generated here\n",
+ "%s: Restore Done wasn't generated here\n",
__func__);
} else {
dev_dbg(hsotg->dev, "restore done generated here\n");
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 483de2bbfaab..cb9059a8444b 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -122,6 +122,7 @@ struct dwc2_hsotg_req;
* @periodic: Set if this is a periodic ep, such as Interrupt
* @isochronous: Set if this is a isochronous ep
* @send_zlp: Set if we need to send a zero-length packet.
+ * @wedged: Set if ep is wedged.
* @desc_list_dma: The DMA address of descriptor chain currently in use.
* @desc_list: Pointer to descriptor DMA chain head currently in use.
* @desc_count: Count of entries within the DMA descriptor chain of EP.
@@ -172,6 +173,7 @@ struct dwc2_hsotg_ep {
unsigned int periodic:1;
unsigned int isochronous:1;
unsigned int send_zlp:1;
+ unsigned int wedged:1;
unsigned int target_frame;
#define TARGET_FRAME_INITIAL 0xFFFFFFFF
bool frame_overrun;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3146df6e6510..837237e4bc96 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1806,7 +1806,8 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
case USB_ENDPOINT_HALT:
halted = ep->halted;
- dwc2_hsotg_ep_sethalt(&ep->ep, set, true);
+ if (!ep->wedged)
+ dwc2_hsotg_ep_sethalt(&ep->ep, set, true);
ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
if (ret) {
@@ -4066,6 +4067,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
hs_ep->isochronous = 0;
hs_ep->periodic = 0;
hs_ep->halted = 0;
+ hs_ep->wedged = 0;
hs_ep->interval = desc->bInterval;
switch (ep_type) {
@@ -4307,6 +4309,27 @@ static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
}
/**
+ * dwc2_gadget_ep_set_wedge - set wedge on a given endpoint
+ * @ep: The endpoint to be wedged.
+ *
+ */
+static int dwc2_gadget_ep_set_wedge(struct usb_ep *ep)
+{
+ struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
+ struct dwc2_hsotg *hs = hs_ep->parent;
+
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&hs->lock, flags);
+ hs_ep->wedged = 1;
+ ret = dwc2_hsotg_ep_sethalt(ep, 1, false);
+ spin_unlock_irqrestore(&hs->lock, flags);
+
+ return ret;
+}
+
+/**
* dwc2_hsotg_ep_sethalt - set halt on a given endpoint
* @ep: The endpoint to set halt.
* @value: Set or unset the halt.
@@ -4357,6 +4380,7 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
epctl |= DXEPCTL_EPDIS;
} else {
epctl &= ~DXEPCTL_STALL;
+ hs_ep->wedged = 0;
xfertype = epctl & DXEPCTL_EPTYPE_MASK;
if (xfertype == DXEPCTL_EPTYPE_BULK ||
xfertype == DXEPCTL_EPTYPE_INTERRUPT)
@@ -4376,6 +4400,7 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
// STALL bit will be set in GOUTNAKEFF interrupt handler
} else {
epctl &= ~DXEPCTL_STALL;
+ hs_ep->wedged = 0;
xfertype = epctl & DXEPCTL_EPTYPE_MASK;
if (xfertype == DXEPCTL_EPTYPE_BULK ||
xfertype == DXEPCTL_EPTYPE_INTERRUPT)
@@ -4415,6 +4440,7 @@ static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
.queue = dwc2_hsotg_ep_queue_lock,
.dequeue = dwc2_hsotg_ep_dequeue,
.set_halt = dwc2_hsotg_ep_sethalt_lock,
+ .set_wedge = dwc2_gadget_ep_set_wedge,
/* note, don't believe we have any call for the fifo routines */
};
@@ -4683,12 +4709,35 @@ static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
return usb_phy_set_power(hsotg->uphy, mA);
}
+static void dwc2_gadget_set_speed(struct usb_gadget *g, enum usb_device_speed speed)
+{
+ struct dwc2_hsotg *hsotg = to_hsotg(g);
+ unsigned long flags;
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+ switch (speed) {
+ case USB_SPEED_HIGH:
+ hsotg->params.speed = DWC2_SPEED_PARAM_HIGH;
+ break;
+ case USB_SPEED_FULL:
+ hsotg->params.speed = DWC2_SPEED_PARAM_FULL;
+ break;
+ case USB_SPEED_LOW:
+ hsotg->params.speed = DWC2_SPEED_PARAM_LOW;
+ break;
+ default:
+ dev_err(hsotg->dev, "invalid speed (%d)\n", speed);
+ }
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = {
.get_frame = dwc2_hsotg_gadget_getframe,
.set_selfpowered = dwc2_hsotg_set_selfpowered,
.udc_start = dwc2_hsotg_udc_start,
.udc_stop = dwc2_hsotg_udc_stop,
.pullup = dwc2_hsotg_pullup,
+ .udc_set_speed = dwc2_gadget_set_speed,
.vbus_session = dwc2_hsotg_vbus_session,
.vbus_draw = dwc2_hsotg_vbus_draw,
};
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index ba74ad7f6995..01866dcb953b 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1050,6 +1050,15 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (!DWC3_VER_IS_PRIOR(DWC3, 290A))
reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
+ /*
+ * Decouple USB 2.0 L1 & L2 events which will allow for
+ * gadget driver to only receive U3/L2 suspend & wakeup
+ * events and prevent the more frequent L1 LPM transitions
+ * from interrupting the driver.
+ */
+ if (!DWC3_VER_IS_PRIOR(DWC3, 300A))
+ reg |= DWC3_GUCTL1_DEV_DECOUPLE_L1L2_EVT;
+
if (dwc->dis_tx_ipgap_linecheck_quirk)
reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
@@ -1267,6 +1276,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
u8 rx_max_burst_prd;
u8 tx_thr_num_pkt_prd;
u8 tx_max_burst_prd;
+ u8 tx_fifo_resize_max_num;
const char *usb_psy_name;
int ret;
@@ -1282,6 +1292,13 @@ static void dwc3_get_properties(struct dwc3 *dwc)
*/
hird_threshold = 12;
+ /*
+ * default to a TXFIFO size large enough to fit 6 max packets. This
+ * allows for systems with larger bus latencies to have some headroom
+ * for endpoints that have a large bMaxBurst value.
+ */
+ tx_fifo_resize_max_num = 6;
+
dwc->maximum_speed = usb_get_maximum_speed(dev);
dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev);
dwc->dr_mode = usb_get_dr_mode(dev);
@@ -1325,6 +1342,11 @@ static void dwc3_get_properties(struct dwc3 *dwc)
&tx_thr_num_pkt_prd);
device_property_read_u8(dev, "snps,tx-max-burst-prd",
&tx_max_burst_prd);
+ dwc->do_fifo_resize = device_property_read_bool(dev,
+ "tx-fifo-resize");
+ if (dwc->do_fifo_resize)
+ device_property_read_u8(dev, "tx-fifo-max-num",
+ &tx_fifo_resize_max_num);
dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk");
@@ -1390,6 +1412,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
dwc->tx_max_burst_prd = tx_max_burst_prd;
dwc->imod_interval = 0;
+
+ dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num;
}
/* check whether the core supports IMOD */
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 5991766239ba..5612bfdf37da 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -256,9 +256,10 @@
#define DWC3_GUCTL_HSTINAUTORETRY BIT(14)
/* Global User Control 1 Register */
-#define DWC3_GUCTL1_PARKMODE_DISABLE_SS BIT(17)
+#define DWC3_GUCTL1_DEV_DECOUPLE_L1L2_EVT BIT(31)
#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
-#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24)
+#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24)
+#define DWC3_GUCTL1_PARKMODE_DISABLE_SS BIT(17)
/* Global Status Register */
#define DWC3_GSTS_OTG_IP BIT(10)
@@ -1023,6 +1024,7 @@ struct dwc3_scratchpad_array {
* @rx_max_burst_prd: max periodic ESS receive burst size
* @tx_thr_num_pkt_prd: periodic ESS transmit packet count
* @tx_max_burst_prd: max periodic ESS transmit burst size
+ * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize
* @hsphy_interface: "utmi" or "ulpi"
* @connected: true when we're connected to a host, false otherwise
* @delayed_status: true when gadget driver asks for delayed status
@@ -1037,6 +1039,7 @@ struct dwc3_scratchpad_array {
* 1 - utmi_l1_suspend_n
* @is_fpga: true when we are using the FPGA board
* @pending_events: true when we have pending IRQs to be handled
+ * @do_fifo_resize: true when txfifo resizing is enabled for dwc3 endpoints
* @pullups_connected: true when Run/Stop bit is set
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
* @three_stage_setup: set if we perform a three phase setup
@@ -1079,6 +1082,11 @@ struct dwc3_scratchpad_array {
* @dis_split_quirk: set to disable split boundary.
* @imod_interval: set the interrupt moderation interval in 250ns
* increments or 0 to disable.
+ * @max_cfg_eps: current max number of IN eps used across all USB configs.
+ * @last_fifo_depth: last fifo depth used to determine next fifo ram start
+ * address.
+ * @num_ep_resized: carries the current number endpoints which have had its tx
+ * fifo resized.
*/
struct dwc3 {
struct work_struct drd_work;
@@ -1233,6 +1241,7 @@ struct dwc3 {
u8 rx_max_burst_prd;
u8 tx_thr_num_pkt_prd;
u8 tx_max_burst_prd;
+ u8 tx_fifo_resize_max_num;
const char *hsphy_interface;
@@ -1246,6 +1255,7 @@ struct dwc3 {
unsigned is_utmi_l1_suspend:1;
unsigned is_fpga:1;
unsigned pending_events:1;
+ unsigned do_fifo_resize:1;
unsigned pullups_connected:1;
unsigned setup_packet_pending:1;
unsigned three_stage_setup:1;
@@ -1282,6 +1292,10 @@ struct dwc3 {
unsigned async_callbacks:1;
u16 imod_interval;
+
+ int max_cfg_eps;
+ int last_fifo_depth;
+ int num_ep_resized;
};
#define INCRX_BURST_MODE 0
@@ -1513,6 +1527,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
struct dwc3_gadget_ep_cmd_params *params);
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
u32 param);
+void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc);
#else
static inline int dwc3_gadget_init(struct dwc3 *dwc)
{ return 0; }
@@ -1532,6 +1547,8 @@ static inline int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
int cmd, u32 param)
{ return 0; }
+static inline void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
+{ }
#endif
#if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
index 8fcbac10510c..d7f76835137f 100644
--- a/drivers/usb/dwc3/drd.c
+++ b/drivers/usb/dwc3/drd.c
@@ -541,14 +541,10 @@ static enum usb_role dwc3_usb_role_switch_get(struct usb_role_switch *sw)
static int dwc3_setup_role_switch(struct dwc3 *dwc)
{
struct usb_role_switch_desc dwc3_role_switch = {NULL};
- const char *str;
u32 mode;
- int ret;
- ret = device_property_read_string(dwc->dev, "role-switch-default-mode",
- &str);
- if (ret >= 0 && !strncmp(str, "host", strlen("host"))) {
- dwc->role_switch_default_mode = USB_DR_MODE_HOST;
+ dwc->role_switch_default_mode = usb_get_role_switch_default_mode(dwc->dev);
+ if (dwc->role_switch_default_mode == USB_DR_MODE_HOST) {
mode = DWC3_GCTL_PRTCAP_HOST;
} else {
dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL;
diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
index 756faa46d33a..d328d20abfbc 100644
--- a/drivers/usb/dwc3/dwc3-imx8mp.c
+++ b/drivers/usb/dwc3/dwc3-imx8mp.c
@@ -152,13 +152,6 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
}
dwc3_imx->irq = irq;
- err = devm_request_threaded_irq(dev, irq, NULL, dwc3_imx8mp_interrupt,
- IRQF_ONESHOT, dev_name(dev), dwc3_imx);
- if (err) {
- dev_err(dev, "failed to request IRQ #%d --> %d\n", irq, err);
- goto disable_clks;
- }
-
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
err = pm_runtime_get_sync(dev);
@@ -186,6 +179,13 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
}
of_node_put(dwc3_np);
+ err = devm_request_threaded_irq(dev, irq, NULL, dwc3_imx8mp_interrupt,
+ IRQF_ONESHOT, dev_name(dev), dwc3_imx);
+ if (err) {
+ dev_err(dev, "failed to request IRQ #%d --> %d\n", irq, err);
+ goto depopulate;
+ }
+
device_set_wakeup_capable(dev, true);
pm_runtime_put(dev);
diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
index ffe301d6ea35..d0f9b7c296b0 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -598,6 +598,8 @@ static int dwc3_meson_g12a_otg_init(struct platform_device *pdev,
USB_R5_ID_DIG_IRQ, 0);
irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
dwc3_meson_g12a_irq_thread,
IRQF_ONESHOT, pdev->name, priv);
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 2b37bdd39a74..7ff8fc8f79a9 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -44,6 +44,7 @@
#define PCI_DEVICE_ID_INTEL_ADLM 0x54ee
#define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15
+#define PCI_DEVICE_ID_AMD_MR 0x163a
#define PCI_INTEL_BXT_DSM_GUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
#define PCI_INTEL_BXT_FUNC_PMU_PWR 4
@@ -148,6 +149,14 @@ static const struct property_entry dwc3_pci_amd_properties[] = {
{}
};
+static const struct property_entry dwc3_pci_mr_properties[] = {
+ PROPERTY_ENTRY_STRING("dr_mode", "otg"),
+ PROPERTY_ENTRY_BOOL("usb-role-switch"),
+ PROPERTY_ENTRY_STRING("role-switch-default-mode", "host"),
+ PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
+ {}
+};
+
static const struct software_node dwc3_pci_intel_swnode = {
.properties = dwc3_pci_intel_properties,
};
@@ -160,6 +169,10 @@ static const struct software_node dwc3_pci_amd_swnode = {
.properties = dwc3_pci_amd_properties,
};
+static const struct software_node dwc3_pci_amd_mr_swnode = {
+ .properties = dwc3_pci_mr_properties,
+};
+
static int dwc3_pci_quirks(struct dwc3_pci *dwc)
{
struct pci_dev *pdev = dwc->pci;
@@ -401,6 +414,10 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_NL_USB),
(kernel_ulong_t) &dwc3_pci_amd_swnode, },
+
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MR),
+ (kernel_ulong_t)&dwc3_pci_amd_mr_swnode, },
+
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 49e6ca94486d..9abbd01028c5 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -115,7 +115,7 @@ static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val)
readl(base + offset);
}
-static void dwc3_qcom_vbus_overrride_enable(struct dwc3_qcom *qcom, bool enable)
+static void dwc3_qcom_vbus_override_enable(struct dwc3_qcom *qcom, bool enable)
{
if (enable) {
dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
@@ -136,7 +136,7 @@ static int dwc3_qcom_vbus_notifier(struct notifier_block *nb,
struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb);
/* enable vbus override for device mode */
- dwc3_qcom_vbus_overrride_enable(qcom, event);
+ dwc3_qcom_vbus_override_enable(qcom, event);
qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST;
return NOTIFY_DONE;
@@ -148,7 +148,7 @@ static int dwc3_qcom_host_notifier(struct notifier_block *nb,
struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb);
/* disable vbus override in host mode */
- dwc3_qcom_vbus_overrride_enable(qcom, !event);
+ dwc3_qcom_vbus_override_enable(qcom, !event);
qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL;
return NOTIFY_DONE;
@@ -614,6 +614,10 @@ static int dwc3_qcom_acpi_register_core(struct platform_device *pdev)
qcom->acpi_pdata->dwc3_core_base_size;
irq = platform_get_irq(pdev_irq, 0);
+ if (irq < 0) {
+ ret = irq;
+ goto out;
+ }
child_res[1].flags = IORESOURCE_IRQ;
child_res[1].start = child_res[1].end = irq;
@@ -645,6 +649,7 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
struct device_node *np = pdev->dev.of_node, *dwc3_np;
struct device *dev = &pdev->dev;
+ struct property *prop;
int ret;
dwc3_np = of_get_compatible_child(np, "snps,dwc3");
@@ -653,6 +658,20 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
return -ENODEV;
}
+ prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL);
+ if (!prop) {
+ ret = -ENOMEM;
+ dev_err(dev, "unable to allocate memory for property\n");
+ goto node_put;
+ }
+
+ prop->name = "tx-fifo-resize";
+ ret = of_add_property(dwc3_np, prop);
+ if (ret) {
+ dev_err(dev, "unable to add property\n");
+ goto node_put;
+ }
+
ret = of_platform_populate(np, NULL, NULL, dev);
if (ret) {
dev_err(dev, "failed to register dwc3 core - %d\n", ret);
@@ -811,7 +830,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
/* enable vbus override for device mode */
if (qcom->mode == USB_DR_MODE_PERIPHERAL)
- dwc3_qcom_vbus_overrride_enable(qcom, true);
+ dwc3_qcom_vbus_override_enable(qcom, true);
/* register extcon to override sw_vbus on Vbus change later */
ret = dwc3_qcom_register_extcon(qcom);
@@ -916,6 +935,7 @@ static const struct of_device_id dwc3_qcom_of_match[] = {
{ .compatible = "qcom,dwc3" },
{ .compatible = "qcom,msm8996-dwc3" },
{ .compatible = "qcom,msm8998-dwc3" },
+ { .compatible = "qcom,sdm660-dwc3" },
{ .compatible = "qcom,sdm845-dwc3" },
{ }
};
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2f9e45eed228..658739410992 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -621,6 +621,8 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
return -EINVAL;
case USB_STATE_ADDRESS:
+ dwc3_gadget_clear_tx_fifos(dwc);
+
ret = dwc3_ep0_delegate_req(dwc, ctrl);
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index ccb68fe6202e..804b50548163 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -632,6 +632,187 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
bool interrupt);
/**
+ * dwc3_gadget_calc_tx_fifo_size - calculates the txfifo size value
+ * @dwc: pointer to the DWC3 context
+ * @nfifos: number of fifos to calculate for
+ *
+ * Calculates the size value based on the equation below:
+ *
+ * DWC3 revision 280A and prior:
+ * fifo_size = mult * (max_packet / mdwidth) + 1;
+ *
+ * DWC3 revision 290A and onwards:
+ * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
+ *
+ * The max packet size is set to 1024, as the txfifo requirements mainly apply
+ * to super speed USB use cases. However, it is safe to overestimate the fifo
+ * allocations for other scenarios, i.e. high speed USB.
+ */
+static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
+{
+ int max_packet = 1024;
+ int fifo_size;
+ int mdwidth;
+
+ mdwidth = dwc3_mdwidth(dwc);
+
+ /* MDWIDTH is represented in bits, we need it in bytes */
+ mdwidth >>= 3;
+
+ if (DWC3_VER_IS_PRIOR(DWC3, 290A))
+ fifo_size = mult * (max_packet / mdwidth) + 1;
+ else
+ fifo_size = mult * ((max_packet + mdwidth) / mdwidth) + 1;
+ return fifo_size;
+}
+
+/**
+ * dwc3_gadget_clear_tx_fifo_size - Clears txfifo allocation
+ * @dwc: pointer to the DWC3 context
+ *
+ * Iterates through all the endpoint registers and clears the previous txfifo
+ * allocations.
+ */
+void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
+{
+ struct dwc3_ep *dep;
+ int fifo_depth;
+ int size;
+ int num;
+
+ if (!dwc->do_fifo_resize)
+ return;
+
+ /* Read ep0IN related TXFIFO size */
+ dep = dwc->eps[1];
+ size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
+ if (DWC3_IP_IS(DWC3))
+ fifo_depth = DWC3_GTXFIFOSIZ_TXFDEP(size);
+ else
+ fifo_depth = DWC31_GTXFIFOSIZ_TXFDEP(size);
+
+ dwc->last_fifo_depth = fifo_depth;
+ /* Clear existing TXFIFO for all IN eps except ep0 */
+ for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM);
+ num += 2) {
+ dep = dwc->eps[num];
+ /* Don't change TXFRAMNUM on usb31 version */
+ size = DWC3_IP_IS(DWC3) ? 0 :
+ dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) &
+ DWC31_GTXFIFOSIZ_TXFRAMNUM;
+
+ dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size);
+ }
+ dwc->num_ep_resized = 0;
+}
+
+/*
+ * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case
+ * @dwc: pointer to our context structure
+ *
+ * This function will a best effort FIFO allocation in order
+ * to improve FIFO usage and throughput, while still allowing
+ * us to enable as many endpoints as possible.
+ *
+ * Keep in mind that this operation will be highly dependent
+ * on the configured size for RAM1 - which contains TxFifo -,
+ * the amount of endpoints enabled on coreConsultant tool, and
+ * the width of the Master Bus.
+ *
+ * In general, FIFO depths are represented with the following equation:
+ *
+ * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
+ *
+ * In conjunction with dwc3_gadget_check_config(), this resizing logic will
+ * ensure that all endpoints will have enough internal memory for one max
+ * packet per endpoint.
+ */
+static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
+{
+ struct dwc3 *dwc = dep->dwc;
+ int fifo_0_start;
+ int ram1_depth;
+ int fifo_size;
+ int min_depth;
+ int num_in_ep;
+ int remaining;
+ int num_fifos = 1;
+ int fifo;
+ int tmp;
+
+ if (!dwc->do_fifo_resize)
+ return 0;
+
+ /* resize IN endpoints except ep0 */
+ if (!usb_endpoint_dir_in(dep->endpoint.desc) || dep->number <= 1)
+ return 0;
+
+ ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+
+ if ((dep->endpoint.maxburst > 1 &&
+ usb_endpoint_xfer_bulk(dep->endpoint.desc)) ||
+ usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ num_fifos = 3;
+
+ if (dep->endpoint.maxburst > 6 &&
+ usb_endpoint_xfer_bulk(dep->endpoint.desc) && DWC3_IP_IS(DWC31))
+ num_fifos = dwc->tx_fifo_resize_max_num;
+
+ /* FIFO size for a single buffer */
+ fifo = dwc3_gadget_calc_tx_fifo_size(dwc, 1);
+
+ /* Calculate the number of remaining EPs w/o any FIFO */
+ num_in_ep = dwc->max_cfg_eps;
+ num_in_ep -= dwc->num_ep_resized;
+
+ /* Reserve at least one FIFO for the number of IN EPs */
+ min_depth = num_in_ep * (fifo + 1);
+ remaining = ram1_depth - min_depth - dwc->last_fifo_depth;
+ remaining = max_t(int, 0, remaining);
+ /*
+ * We've already reserved 1 FIFO per EP, so check what we can fit in
+ * addition to it. If there is not enough remaining space, allocate
+ * all the remaining space to the EP.
+ */
+ fifo_size = (num_fifos - 1) * fifo;
+ if (remaining < fifo_size)
+ fifo_size = remaining;
+
+ fifo_size += fifo;
+ /* Last increment according to the TX FIFO size equation */
+ fifo_size++;
+
+ /* Check if TXFIFOs start at non-zero addr */
+ tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
+ fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp);
+
+ fifo_size |= (fifo_0_start + (dwc->last_fifo_depth << 16));
+ if (DWC3_IP_IS(DWC3))
+ dwc->last_fifo_depth += DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
+ else
+ dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
+
+ /* Check fifo size allocation doesn't exceed available RAM size. */
+ if (dwc->last_fifo_depth >= ram1_depth) {
+ dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n",
+ dwc->last_fifo_depth, ram1_depth,
+ dep->endpoint.name, fifo_size);
+ if (DWC3_IP_IS(DWC3))
+ fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
+ else
+ fifo_size = DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
+
+ dwc->last_fifo_depth -= fifo_size;
+ return -ENOMEM;
+ }
+
+ dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size);
+ dwc->num_ep_resized++;
+
+ return 0;
+}
+
+/**
* __dwc3_gadget_ep_enable - initializes a hw endpoint
* @dep: endpoint to be initialized
* @action: one of INIT, MODIFY or RESTORE
@@ -648,6 +829,10 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
int ret;
if (!(dep->flags & DWC3_EP_ENABLED)) {
+ ret = dwc3_gadget_resize_tx_fifos(dep);
+ if (ret)
+ return ret;
+
ret = dwc3_gadget_start_config(dep);
if (ret)
return ret;
@@ -2508,6 +2693,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
spin_lock_irqsave(&dwc->lock, flags);
dwc->gadget_driver = NULL;
+ dwc->max_cfg_eps = 0;
spin_unlock_irqrestore(&dwc->lock, flags);
free_irq(dwc->irq_gadget, dwc->ev_buf);
@@ -2595,6 +2781,51 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA)
return ret;
}
+/**
+ * dwc3_gadget_check_config - ensure dwc3 can support the USB configuration
+ * @g: pointer to the USB gadget
+ *
+ * Used to record the maximum number of endpoints being used in a USB composite
+ * device. (across all configurations) This is to be used in the calculation
+ * of the TXFIFO sizes when resizing internal memory for individual endpoints.
+ * It will help ensured that the resizing logic reserves enough space for at
+ * least one max packet.
+ */
+static int dwc3_gadget_check_config(struct usb_gadget *g)
+{
+ struct dwc3 *dwc = gadget_to_dwc(g);
+ struct usb_ep *ep;
+ int fifo_size = 0;
+ int ram1_depth;
+ int ep_num = 0;
+
+ if (!dwc->do_fifo_resize)
+ return 0;
+
+ list_for_each_entry(ep, &g->ep_list, ep_list) {
+ /* Only interested in the IN endpoints */
+ if (ep->claimed && (ep->address & USB_DIR_IN))
+ ep_num++;
+ }
+
+ if (ep_num <= dwc->max_cfg_eps)
+ return 0;
+
+ /* Update the max number of eps in the composition */
+ dwc->max_cfg_eps = ep_num;
+
+ fifo_size = dwc3_gadget_calc_tx_fifo_size(dwc, dwc->max_cfg_eps);
+ /* Based on the equation, increment by one for every ep */
+ fifo_size += dwc->max_cfg_eps;
+
+ /* Check if we can fit a single fifo per endpoint */
+ ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+ if (fifo_size > ram1_depth)
+ return -ENOMEM;
+
+ return 0;
+}
+
static void dwc3_gadget_async_callbacks(struct usb_gadget *g, bool enable)
{
struct dwc3 *dwc = gadget_to_dwc(g);
@@ -2616,6 +2847,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
.udc_set_ssp_rate = dwc3_gadget_set_ssp_rate,
.get_config_params = dwc3_gadget_config_params,
.vbus_draw = dwc3_gadget_vbus_draw,
+ .check_config = dwc3_gadget_check_config,
.udc_async_callbacks = dwc3_gadget_async_callbacks,
};
@@ -4011,7 +4243,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
}
- usb_initialize_gadget(dwc->dev, dwc->gadget, dwc_gadget_release);
+ usb_initialize_gadget(dwc->sysdev, dwc->gadget, dwc_gadget_release);
dev = &dwc->gadget->dev;
dev->platform_data = dwc;
dwc->gadget->ops = &dwc3_gadget_ops;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2d152571a7de..dd58094f0b85 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -450,6 +450,7 @@ config USB_CONFIGFS_F_UVC
depends on USB_CONFIGFS
depends on VIDEO_V4L2
depends on VIDEO_DEV
+ select VIDEOBUF2_DMA_SG
select VIDEOBUF2_VMALLOC
select USB_F_UVC
help
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 72a9797dbbae..504c1cbc255d 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -482,7 +482,7 @@ static u8 encode_bMaxPower(enum usb_device_speed speed,
{
unsigned val;
- if (c->MaxPower)
+ if (c->MaxPower || (c->bmAttributes & USB_CONFIG_ATT_SELFPOWER))
val = c->MaxPower;
else
val = CONFIG_USB_GADGET_VBUS_DRAW;
@@ -936,7 +936,11 @@ static int set_config(struct usb_composite_dev *cdev,
}
/* when we return, be sure our power usage is valid */
- power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
+ if (c->MaxPower || (c->bmAttributes & USB_CONFIG_ATT_SELFPOWER))
+ power = c->MaxPower;
+ else
+ power = CONFIG_USB_GADGET_VBUS_DRAW;
+
if (gadget->speed < USB_SPEED_SUPER)
power = min(power, 500U);
else
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 15a607ccef8a..477e72a1d11e 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -55,7 +55,7 @@ struct gadget_info {
static inline struct gadget_info *to_gadget_info(struct config_item *item)
{
- return container_of(to_config_group(item), struct gadget_info, group);
+ return container_of(to_config_group(item), struct gadget_info, group);
}
struct config_usb_cfg {
@@ -365,21 +365,21 @@ static struct configfs_attribute *gadget_root_attrs[] = {
static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
{
- return container_of(to_config_group(item), struct gadget_strings,
+ return container_of(to_config_group(item), struct gadget_strings,
group);
}
static inline struct gadget_config_name *to_gadget_config_name(
struct config_item *item)
{
- return container_of(to_config_group(item), struct gadget_config_name,
+ return container_of(to_config_group(item), struct gadget_config_name,
group);
}
static inline struct usb_function_instance *to_usb_function_instance(
struct config_item *item)
{
- return container_of(to_config_group(item),
+ return container_of(to_config_group(item),
struct usb_function_instance, group);
}
@@ -1404,6 +1404,10 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
goto err_purge_funcs;
}
}
+ ret = usb_gadget_check_config(cdev->gadget);
+ if (ret)
+ goto err_purge_funcs;
+
usb_ep_autoconfig_reset(cdev->gadget);
}
if (cdev->use_os_string) {
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 9c0c393abb39..8260f38025b7 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -2081,7 +2081,7 @@ static int __must_check ffs_do_single_desc(char *data, unsigned len,
break;
case USB_TYPE_CLASS | 0x01:
- if (*current_class == USB_INTERFACE_CLASS_HID) {
+ if (*current_class == USB_INTERFACE_CLASS_HID) {
pr_vdebug("hid descriptor\n");
if (length != sizeof(struct hid_descriptor))
goto inv_length;
@@ -3831,7 +3831,7 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len)
data = memdup_user(buf, len);
if (IS_ERR(data))
- return ERR_PTR(PTR_ERR(data));
+ return data;
pr_vdebug("Buffer from user space:\n");
ffs_dump_mem("", data, len);
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index bb476e121eae..ca0a7d9eaa34 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -45,12 +45,25 @@ struct f_hidg {
unsigned short report_desc_length;
char *report_desc;
unsigned short report_length;
+ /*
+ * use_out_ep - if true, the OUT Endpoint (interrupt out method)
+ * will be used to receive reports from the host
+ * using functions with the "intout" suffix.
+ * Otherwise, the OUT Endpoint will not be configured
+ * and the SETUP/SET_REPORT method ("ssreport" suffix)
+ * will be used to receive reports.
+ */
+ bool use_out_ep;
/* recv report */
- struct list_head completed_out_req;
spinlock_t read_spinlock;
wait_queue_head_t read_queue;
+ /* recv report - interrupt out only (use_out_ep == 1) */
+ struct list_head completed_out_req;
unsigned int qlen;
+ /* recv report - setup set_report only (use_out_ep == 0) */
+ char *set_report_buf;
+ unsigned int set_report_length;
/* send report */
spinlock_t write_spinlock;
@@ -79,7 +92,7 @@ static struct usb_interface_descriptor hidg_interface_desc = {
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
.bAlternateSetting = 0,
- .bNumEndpoints = 2,
+ /* .bNumEndpoints = DYNAMIC (depends on use_out_ep) */
.bInterfaceClass = USB_CLASS_HID,
/* .bInterfaceSubClass = DYNAMIC */
/* .bInterfaceProtocol = DYNAMIC */
@@ -140,7 +153,7 @@ static struct usb_ss_ep_comp_descriptor hidg_ss_out_comp_desc = {
/* .wBytesPerInterval = DYNAMIC */
};
-static struct usb_descriptor_header *hidg_ss_descriptors[] = {
+static struct usb_descriptor_header *hidg_ss_descriptors_intout[] = {
(struct usb_descriptor_header *)&hidg_interface_desc,
(struct usb_descriptor_header *)&hidg_desc,
(struct usb_descriptor_header *)&hidg_ss_in_ep_desc,
@@ -150,6 +163,14 @@ static struct usb_descriptor_header *hidg_ss_descriptors[] = {
NULL,
};
+static struct usb_descriptor_header *hidg_ss_descriptors_ssreport[] = {
+ (struct usb_descriptor_header *)&hidg_interface_desc,
+ (struct usb_descriptor_header *)&hidg_desc,
+ (struct usb_descriptor_header *)&hidg_ss_in_ep_desc,
+ (struct usb_descriptor_header *)&hidg_ss_in_comp_desc,
+ NULL,
+};
+
/* High-Speed Support */
static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = {
@@ -176,7 +197,7 @@ static struct usb_endpoint_descriptor hidg_hs_out_ep_desc = {
*/
};
-static struct usb_descriptor_header *hidg_hs_descriptors[] = {
+static struct usb_descriptor_header *hidg_hs_descriptors_intout[] = {
(struct usb_descriptor_header *)&hidg_interface_desc,
(struct usb_descriptor_header *)&hidg_desc,
(struct usb_descriptor_header *)&hidg_hs_in_ep_desc,
@@ -184,6 +205,13 @@ static struct usb_descriptor_header *hidg_hs_descriptors[] = {
NULL,
};
+static struct usb_descriptor_header *hidg_hs_descriptors_ssreport[] = {
+ (struct usb_descriptor_header *)&hidg_interface_desc,
+ (struct usb_descriptor_header *)&hidg_desc,
+ (struct usb_descriptor_header *)&hidg_hs_in_ep_desc,
+ NULL,
+};
+
/* Full-Speed Support */
static struct usb_endpoint_descriptor hidg_fs_in_ep_desc = {
@@ -210,7 +238,7 @@ static struct usb_endpoint_descriptor hidg_fs_out_ep_desc = {
*/
};
-static struct usb_descriptor_header *hidg_fs_descriptors[] = {
+static struct usb_descriptor_header *hidg_fs_descriptors_intout[] = {
(struct usb_descriptor_header *)&hidg_interface_desc,
(struct usb_descriptor_header *)&hidg_desc,
(struct usb_descriptor_header *)&hidg_fs_in_ep_desc,
@@ -218,6 +246,13 @@ static struct usb_descriptor_header *hidg_fs_descriptors[] = {
NULL,
};
+static struct usb_descriptor_header *hidg_fs_descriptors_ssreport[] = {
+ (struct usb_descriptor_header *)&hidg_interface_desc,
+ (struct usb_descriptor_header *)&hidg_desc,
+ (struct usb_descriptor_header *)&hidg_fs_in_ep_desc,
+ NULL,
+};
+
/*-------------------------------------------------------------------------*/
/* Strings */
@@ -241,8 +276,8 @@ static struct usb_gadget_strings *ct_func_strings[] = {
/*-------------------------------------------------------------------------*/
/* Char Device */
-static ssize_t f_hidg_read(struct file *file, char __user *buffer,
- size_t count, loff_t *ptr)
+static ssize_t f_hidg_intout_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ptr)
{
struct f_hidg *hidg = file->private_data;
struct f_hidg_req_list *list;
@@ -255,15 +290,15 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
spin_lock_irqsave(&hidg->read_spinlock, flags);
-#define READ_COND (!list_empty(&hidg->completed_out_req))
+#define READ_COND_INTOUT (!list_empty(&hidg->completed_out_req))
/* wait for at least one buffer to complete */
- while (!READ_COND) {
+ while (!READ_COND_INTOUT) {
spin_unlock_irqrestore(&hidg->read_spinlock, flags);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
- if (wait_event_interruptible(hidg->read_queue, READ_COND))
+ if (wait_event_interruptible(hidg->read_queue, READ_COND_INTOUT))
return -ERESTARTSYS;
spin_lock_irqsave(&hidg->read_spinlock, flags);
@@ -313,6 +348,60 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
return count;
}
+#define READ_COND_SSREPORT (hidg->set_report_buf != NULL)
+
+static ssize_t f_hidg_ssreport_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ptr)
+{
+ struct f_hidg *hidg = file->private_data;
+ char *tmp_buf = NULL;
+ unsigned long flags;
+
+ if (!count)
+ return 0;
+
+ spin_lock_irqsave(&hidg->read_spinlock, flags);
+
+ while (!READ_COND_SSREPORT) {
+ spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ if (wait_event_interruptible(hidg->read_queue, READ_COND_SSREPORT))
+ return -ERESTARTSYS;
+
+ spin_lock_irqsave(&hidg->read_spinlock, flags);
+ }
+
+ count = min_t(unsigned int, count, hidg->set_report_length);
+ tmp_buf = hidg->set_report_buf;
+ hidg->set_report_buf = NULL;
+
+ spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+
+ if (tmp_buf != NULL) {
+ count -= copy_to_user(buffer, tmp_buf, count);
+ kfree(tmp_buf);
+ } else {
+ count = -ENOMEM;
+ }
+
+ wake_up(&hidg->read_queue);
+
+ return count;
+}
+
+static ssize_t f_hidg_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ptr)
+{
+ struct f_hidg *hidg = file->private_data;
+
+ if (hidg->use_out_ep)
+ return f_hidg_intout_read(file, buffer, count, ptr);
+ else
+ return f_hidg_ssreport_read(file, buffer, count, ptr);
+}
+
static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_hidg *hidg = (struct f_hidg *)ep->driver_data;
@@ -433,14 +522,20 @@ static __poll_t f_hidg_poll(struct file *file, poll_table *wait)
if (WRITE_COND)
ret |= EPOLLOUT | EPOLLWRNORM;
- if (READ_COND)
- ret |= EPOLLIN | EPOLLRDNORM;
+ if (hidg->use_out_ep) {
+ if (READ_COND_INTOUT)
+ ret |= EPOLLIN | EPOLLRDNORM;
+ } else {
+ if (READ_COND_SSREPORT)
+ ret |= EPOLLIN | EPOLLRDNORM;
+ }
return ret;
}
#undef WRITE_COND
-#undef READ_COND
+#undef READ_COND_SSREPORT
+#undef READ_COND_INTOUT
static int f_hidg_release(struct inode *inode, struct file *fd)
{
@@ -467,7 +562,7 @@ static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep,
return alloc_ep_req(ep, length);
}
-static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
+static void hidg_intout_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_hidg *hidg = (struct f_hidg *) req->context;
struct usb_composite_dev *cdev = hidg->func.config->cdev;
@@ -502,6 +597,37 @@ free_req:
}
}
+static void hidg_ssreport_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_hidg *hidg = (struct f_hidg *)req->context;
+ struct usb_composite_dev *cdev = hidg->func.config->cdev;
+ char *new_buf = NULL;
+ unsigned long flags;
+
+ if (req->status != 0 || req->buf == NULL || req->actual == 0) {
+ ERROR(cdev,
+ "%s FAILED: status=%d, buf=%p, actual=%d\n",
+ __func__, req->status, req->buf, req->actual);
+ return;
+ }
+
+ spin_lock_irqsave(&hidg->read_spinlock, flags);
+
+ new_buf = krealloc(hidg->set_report_buf, req->actual, GFP_ATOMIC);
+ if (new_buf == NULL) {
+ spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+ return;
+ }
+ hidg->set_report_buf = new_buf;
+
+ hidg->set_report_length = req->actual;
+ memcpy(hidg->set_report_buf, req->buf, req->actual);
+
+ spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+
+ wake_up(&hidg->read_queue);
+}
+
static int hidg_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
@@ -549,7 +675,11 @@ static int hidg_setup(struct usb_function *f,
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_REPORT):
VDBG(cdev, "set_report | wLength=%d\n", ctrl->wLength);
- goto stall;
+ if (hidg->use_out_ep)
+ goto stall;
+ req->complete = hidg_ssreport_complete;
+ req->context = hidg;
+ goto respond;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
@@ -637,15 +767,18 @@ static void hidg_disable(struct usb_function *f)
unsigned long flags;
usb_ep_disable(hidg->in_ep);
- usb_ep_disable(hidg->out_ep);
- spin_lock_irqsave(&hidg->read_spinlock, flags);
- list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
- free_ep_req(hidg->out_ep, list->req);
- list_del(&list->list);
- kfree(list);
+ if (hidg->out_ep) {
+ usb_ep_disable(hidg->out_ep);
+
+ spin_lock_irqsave(&hidg->read_spinlock, flags);
+ list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
+ free_ep_req(hidg->out_ep, list->req);
+ list_del(&list->list);
+ kfree(list);
+ }
+ spin_unlock_irqrestore(&hidg->read_spinlock, flags);
}
- spin_unlock_irqrestore(&hidg->read_spinlock, flags);
spin_lock_irqsave(&hidg->write_spinlock, flags);
if (!hidg->write_pending) {
@@ -691,8 +824,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
}
}
-
- if (hidg->out_ep != NULL) {
+ if (hidg->use_out_ep && hidg->out_ep != NULL) {
/* restart endpoint */
usb_ep_disable(hidg->out_ep);
@@ -717,7 +849,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
hidg_alloc_ep_req(hidg->out_ep,
hidg->report_length);
if (req) {
- req->complete = hidg_set_report_complete;
+ req->complete = hidg_intout_complete;
req->context = hidg;
status = usb_ep_queue(hidg->out_ep, req,
GFP_ATOMIC);
@@ -743,7 +875,8 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
}
return 0;
disable_out_ep:
- usb_ep_disable(hidg->out_ep);
+ if (hidg->out_ep)
+ usb_ep_disable(hidg->out_ep);
free_req_in:
if (req_in)
free_ep_req(hidg->in_ep, req_in);
@@ -795,14 +928,21 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
hidg->in_ep = ep;
- ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc);
- if (!ep)
- goto fail;
- hidg->out_ep = ep;
+ hidg->out_ep = NULL;
+ if (hidg->use_out_ep) {
+ ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc);
+ if (!ep)
+ goto fail;
+ hidg->out_ep = ep;
+ }
+
+ /* used only if use_out_ep == 1 */
+ hidg->set_report_buf = NULL;
/* set descriptor dynamic values */
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
+ hidg_interface_desc.bNumEndpoints = hidg->use_out_ep ? 2 : 1;
hidg->protocol = HID_REPORT_PROTOCOL;
hidg->idle = 1;
hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
@@ -833,9 +973,19 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
hidg_ss_out_ep_desc.bEndpointAddress =
hidg_fs_out_ep_desc.bEndpointAddress;
- status = usb_assign_descriptors(f, hidg_fs_descriptors,
- hidg_hs_descriptors, hidg_ss_descriptors,
- hidg_ss_descriptors);
+ if (hidg->use_out_ep)
+ status = usb_assign_descriptors(f,
+ hidg_fs_descriptors_intout,
+ hidg_hs_descriptors_intout,
+ hidg_ss_descriptors_intout,
+ hidg_ss_descriptors_intout);
+ else
+ status = usb_assign_descriptors(f,
+ hidg_fs_descriptors_ssreport,
+ hidg_hs_descriptors_ssreport,
+ hidg_ss_descriptors_ssreport,
+ hidg_ss_descriptors_ssreport);
+
if (status)
goto fail;
@@ -950,6 +1100,7 @@ CONFIGFS_ATTR(f_hid_opts_, name)
F_HID_OPT(subclass, 8, 255);
F_HID_OPT(protocol, 8, 255);
+F_HID_OPT(no_out_endpoint, 8, 1);
F_HID_OPT(report_length, 16, 65535);
static ssize_t f_hid_opts_report_desc_show(struct config_item *item, char *page)
@@ -1009,6 +1160,7 @@ CONFIGFS_ATTR_RO(f_hid_opts_, dev);
static struct configfs_attribute *hid_attrs[] = {
&f_hid_opts_attr_subclass,
&f_hid_opts_attr_protocol,
+ &f_hid_opts_attr_no_out_endpoint,
&f_hid_opts_attr_report_length,
&f_hid_opts_attr_report_desc,
&f_hid_opts_attr_dev,
@@ -1093,6 +1245,7 @@ static void hidg_free(struct usb_function *f)
hidg = func_to_hidg(f);
opts = container_of(f->fi, struct f_hid_opts, func_inst);
kfree(hidg->report_desc);
+ kfree(hidg->set_report_buf);
kfree(hidg);
mutex_lock(&opts->lock);
--opts->refcnt;
@@ -1139,6 +1292,7 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi)
return ERR_PTR(-ENOMEM);
}
}
+ hidg->use_out_ep = !opts->no_out_endpoint;
mutex_unlock(&opts->lock);
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 4a4703634a2a..6ad669dde41c 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -6,36 +6,6 @@
* Copyright (C) 2009 Samsung Electronics
* Author: Michal Nazarewicz <mina86@mina86.com>
* All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions, and the following disclaimer,
- * without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * 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.
*/
/*
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index 855127249f24..dc8f078f918c 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -72,9 +72,7 @@ struct f_ncm {
struct sk_buff *skb_tx_data;
struct sk_buff *skb_tx_ndp;
u16 ndp_dgram_count;
- bool timer_force_tx;
struct hrtimer task_timer;
- bool timer_stopping;
};
static inline struct f_ncm *func_to_ncm(struct usb_function *f)
@@ -890,7 +888,6 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (ncm->port.in_ep->enabled) {
DBG(cdev, "reset ncm\n");
- ncm->timer_stopping = true;
ncm->netdev = NULL;
gether_disconnect(&ncm->port);
ncm_reset_values(ncm);
@@ -928,7 +925,6 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (IS_ERR(net))
return PTR_ERR(net);
ncm->netdev = net;
- ncm->timer_stopping = false;
}
spin_lock(&ncm->lock);
@@ -1017,22 +1013,20 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
{
struct f_ncm *ncm = func_to_ncm(&port->func);
struct sk_buff *skb2 = NULL;
- int ncb_len = 0;
- __le16 *ntb_data;
- __le16 *ntb_ndp;
- int dgram_pad;
-
- unsigned max_size = ncm->port.fixed_in_len;
- const struct ndp_parser_opts *opts = ncm->parser_opts;
- const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
- const int div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
- const int rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
- const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
-
- if (!skb && !ncm->skb_tx_data)
- return NULL;
if (skb) {
+ int ncb_len = 0;
+ __le16 *ntb_data;
+ __le16 *ntb_ndp;
+ int dgram_pad;
+
+ unsigned max_size = ncm->port.fixed_in_len;
+ const struct ndp_parser_opts *opts = ncm->parser_opts;
+ const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+ const int div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
+ const int rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
+ const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
+
/* Add the CRC if required up front */
if (ncm->is_crc) {
uint32_t crc;
@@ -1126,8 +1120,11 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
dev_consume_skb_any(skb);
skb = NULL;
- } else if (ncm->skb_tx_data && ncm->timer_force_tx) {
- /* If the tx was requested because of a timeout then send */
+ } else if (ncm->skb_tx_data) {
+ /* If we get here ncm_wrap_ntb() was called with NULL skb,
+ * because eth_start_xmit() was called with NULL skb by
+ * ncm_tx_timeout() - hence, this is our signal to flush/send.
+ */
skb2 = package_for_tx(ncm);
if (!skb2)
goto err;
@@ -1155,20 +1152,18 @@ err:
static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
{
struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
+ struct net_device *netdev = READ_ONCE(ncm->netdev);
- /* Only send if data is available. */
- if (!ncm->timer_stopping && ncm->skb_tx_data) {
- ncm->timer_force_tx = true;
-
+ if (netdev) {
/* XXX This allowance of a NULL skb argument to ndo_start_xmit
* XXX is not sane. The gadget layer should be redesigned so
* XXX that the dev->wrap() invocations to build SKBs is transparent
* XXX and performed in some way outside of the ndo_start_xmit
* XXX interface.
+ *
+ * This will call directly into u_ether's eth_start_xmit()
*/
- ncm->netdev->netdev_ops->ndo_start_xmit(NULL, ncm->netdev);
-
- ncm->timer_force_tx = false;
+ netdev->netdev_ops->ndo_start_xmit(NULL, netdev);
}
return HRTIMER_NORESTART;
}
@@ -1357,7 +1352,6 @@ static void ncm_disable(struct usb_function *f)
DBG(cdev, "ncm deactivated\n");
if (ncm->port.in_ep->enabled) {
- ncm->timer_stopping = true;
ncm->netdev = NULL;
gether_disconnect(&ncm->port);
}
diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
index d04707580068..5b3502df4e13 100644
--- a/drivers/usb/gadget/function/f_uac1.c
+++ b/drivers/usb/gadget/function/f_uac1.c
@@ -22,13 +22,26 @@
/* UAC1 spec: 3.7.2.3 Audio Channel Cluster Format */
#define UAC1_CHANNEL_MASK 0x0FFF
+#define USB_OUT_FU_ID (out_feature_unit_desc->bUnitID)
+#define USB_IN_FU_ID (in_feature_unit_desc->bUnitID)
+
#define EPIN_EN(_opts) ((_opts)->p_chmask != 0)
#define EPOUT_EN(_opts) ((_opts)->c_chmask != 0)
+#define FUIN_EN(_opts) ((_opts)->p_mute_present \
+ || (_opts)->p_volume_present)
+#define FUOUT_EN(_opts) ((_opts)->c_mute_present \
+ || (_opts)->c_volume_present)
struct f_uac1 {
struct g_audio g_audio;
u8 ac_intf, as_in_intf, as_out_intf;
u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */
+
+ struct usb_ctrlrequest setup_cr; /* will be used in data stage */
+
+ /* Interrupt IN endpoint of AC interface */
+ struct usb_ep *int_ep;
+ atomic_t int_count;
};
static inline struct f_uac1 *func_to_uac1(struct usb_function *f)
@@ -58,7 +71,7 @@ static inline struct f_uac1_opts *g_audio_to_uac1_opts(struct g_audio *audio)
static struct usb_interface_descriptor ac_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
- .bNumEndpoints = 0,
+ /* .bNumEndpoints = DYNAMIC */
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
};
@@ -106,6 +119,19 @@ static struct uac1_output_terminal_descriptor usb_in_ot_desc = {
/* .bSourceID = DYNAMIC */
};
+static struct uac_feature_unit_descriptor *in_feature_unit_desc;
+static struct uac_feature_unit_descriptor *out_feature_unit_desc;
+
+/* AC IN Interrupt Endpoint */
+static struct usb_endpoint_descriptor ac_int_ep_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(2),
+ .bInterval = 4,
+};
+
/* B.4.1 Standard AS Interface Descriptor */
static struct usb_interface_descriptor as_out_interface_alt_0_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
@@ -232,8 +258,13 @@ static struct usb_descriptor_header *f_audio_desc[] = {
(struct usb_descriptor_header *)&usb_out_it_desc,
(struct usb_descriptor_header *)&io_out_ot_desc,
+ (struct usb_descriptor_header *)&out_feature_unit_desc,
+
(struct usb_descriptor_header *)&io_in_it_desc,
(struct usb_descriptor_header *)&usb_in_ot_desc,
+ (struct usb_descriptor_header *)&in_feature_unit_desc,
+
+ (struct usb_descriptor_header *)&ac_int_ep_desc,
(struct usb_descriptor_header *)&as_out_interface_alt_0_desc,
(struct usb_descriptor_header *)&as_out_interface_alt_1_desc,
@@ -263,6 +294,8 @@ enum {
STR_IO_IN_IT,
STR_IO_IN_IT_CH_NAMES,
STR_USB_IN_OT,
+ STR_FU_IN,
+ STR_FU_OUT,
STR_AS_OUT_IF_ALT0,
STR_AS_OUT_IF_ALT1,
STR_AS_IN_IF_ALT0,
@@ -277,6 +310,8 @@ static struct usb_string strings_uac1[] = {
[STR_IO_IN_IT].s = "Capture Input terminal",
[STR_IO_IN_IT_CH_NAMES].s = "Capture Channels",
[STR_USB_IN_OT].s = "Capture Output terminal",
+ [STR_FU_IN].s = "Capture Volume",
+ [STR_FU_OUT].s = "Playback Volume",
[STR_AS_OUT_IF_ALT0].s = "Playback Inactive",
[STR_AS_OUT_IF_ALT1].s = "Playback Active",
[STR_AS_IN_IF_ALT0].s = "Capture Inactive",
@@ -298,6 +333,376 @@ static struct usb_gadget_strings *uac1_strings[] = {
* This function is an ALSA sound card following USB Audio Class Spec 1.0.
*/
+static void audio_notify_complete(struct usb_ep *_ep, struct usb_request *req)
+{
+ struct g_audio *audio = req->context;
+ struct f_uac1 *uac1 = func_to_uac1(&audio->func);
+
+ atomic_dec(&uac1->int_count);
+ kfree(req->buf);
+ usb_ep_free_request(_ep, req);
+}
+
+static int audio_notify(struct g_audio *audio, int unit_id, int cs)
+{
+ struct f_uac1 *uac1 = func_to_uac1(&audio->func);
+ struct usb_request *req;
+ struct uac1_status_word *msg;
+ int ret;
+
+ if (!uac1->int_ep->enabled)
+ return 0;
+
+ if (atomic_inc_return(&uac1->int_count) > UAC1_DEF_INT_REQ_NUM) {
+ atomic_dec(&uac1->int_count);
+ return 0;
+ }
+
+ req = usb_ep_alloc_request(uac1->int_ep, GFP_ATOMIC);
+ if (req == NULL) {
+ ret = -ENOMEM;
+ goto err_dec_int_count;
+ }
+
+ msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+ if (msg == NULL) {
+ ret = -ENOMEM;
+ goto err_free_request;
+ }
+
+ msg->bStatusType = UAC1_STATUS_TYPE_IRQ_PENDING
+ | UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF;
+ msg->bOriginator = unit_id;
+
+ req->length = sizeof(*msg);
+ req->buf = msg;
+ req->context = audio;
+ req->complete = audio_notify_complete;
+
+ ret = usb_ep_queue(uac1->int_ep, req, GFP_ATOMIC);
+
+ if (ret)
+ goto err_free_msg;
+
+ return 0;
+
+err_free_msg:
+ kfree(msg);
+err_free_request:
+ usb_ep_free_request(uac1->int_ep, req);
+err_dec_int_count:
+ atomic_dec(&uac1->int_count);
+
+ return ret;
+}
+
+static int
+in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+ struct usb_request *req = fn->config->cdev->req;
+ struct g_audio *audio = func_to_g_audio(fn);
+ struct f_uac1_opts *opts = g_audio_to_uac1_opts(audio);
+ u16 w_length = le16_to_cpu(cr->wLength);
+ u16 w_index = le16_to_cpu(cr->wIndex);
+ u16 w_value = le16_to_cpu(cr->wValue);
+ u8 entity_id = (w_index >> 8) & 0xff;
+ u8 control_selector = w_value >> 8;
+ int value = -EOPNOTSUPP;
+
+ if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ unsigned int is_playback = 0;
+
+ if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID))
+ is_playback = 1;
+
+ if (control_selector == UAC_FU_MUTE) {
+ unsigned int mute;
+
+ u_audio_get_mute(audio, is_playback, &mute);
+
+ *(u8 *)req->buf = mute;
+ value = min_t(unsigned int, w_length, 1);
+ } else if (control_selector == UAC_FU_VOLUME) {
+ __le16 c;
+ s16 volume;
+
+ u_audio_get_volume(audio, is_playback, &volume);
+
+ c = cpu_to_le16(volume);
+
+ value = min_t(unsigned int, w_length, sizeof(c));
+ memcpy(req->buf, &c, value);
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ }
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
+ }
+
+ return value;
+}
+
+static int
+in_rq_min(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+ struct usb_request *req = fn->config->cdev->req;
+ struct g_audio *audio = func_to_g_audio(fn);
+ struct f_uac1_opts *opts = g_audio_to_uac1_opts(audio);
+ u16 w_length = le16_to_cpu(cr->wLength);
+ u16 w_index = le16_to_cpu(cr->wIndex);
+ u16 w_value = le16_to_cpu(cr->wValue);
+ u8 entity_id = (w_index >> 8) & 0xff;
+ u8 control_selector = w_value >> 8;
+ int value = -EOPNOTSUPP;
+
+ if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ unsigned int is_playback = 0;
+
+ if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID))
+ is_playback = 1;
+
+ if (control_selector == UAC_FU_VOLUME) {
+ __le16 r;
+ s16 min_db;
+
+ if (is_playback)
+ min_db = opts->p_volume_min;
+ else
+ min_db = opts->c_volume_min;
+
+ r = cpu_to_le16(min_db);
+
+ value = min_t(unsigned int, w_length, sizeof(r));
+ memcpy(req->buf, &r, value);
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ }
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
+ }
+
+ return value;
+}
+
+static int
+in_rq_max(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+ struct usb_request *req = fn->config->cdev->req;
+ struct g_audio *audio = func_to_g_audio(fn);
+ struct f_uac1_opts *opts = g_audio_to_uac1_opts(audio);
+ u16 w_length = le16_to_cpu(cr->wLength);
+ u16 w_index = le16_to_cpu(cr->wIndex);
+ u16 w_value = le16_to_cpu(cr->wValue);
+ u8 entity_id = (w_index >> 8) & 0xff;
+ u8 control_selector = w_value >> 8;
+ int value = -EOPNOTSUPP;
+
+ if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ unsigned int is_playback = 0;
+
+ if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID))
+ is_playback = 1;
+
+ if (control_selector == UAC_FU_VOLUME) {
+ __le16 r;
+ s16 max_db;
+
+ if (is_playback)
+ max_db = opts->p_volume_max;
+ else
+ max_db = opts->c_volume_max;
+
+ r = cpu_to_le16(max_db);
+
+ value = min_t(unsigned int, w_length, sizeof(r));
+ memcpy(req->buf, &r, value);
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ }
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
+ }
+
+ return value;
+}
+
+static int
+in_rq_res(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+ struct usb_request *req = fn->config->cdev->req;
+ struct g_audio *audio = func_to_g_audio(fn);
+ struct f_uac1_opts *opts = g_audio_to_uac1_opts(audio);
+ u16 w_length = le16_to_cpu(cr->wLength);
+ u16 w_index = le16_to_cpu(cr->wIndex);
+ u16 w_value = le16_to_cpu(cr->wValue);
+ u8 entity_id = (w_index >> 8) & 0xff;
+ u8 control_selector = w_value >> 8;
+ int value = -EOPNOTSUPP;
+
+ if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ unsigned int is_playback = 0;
+
+ if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID))
+ is_playback = 1;
+
+ if (control_selector == UAC_FU_VOLUME) {
+ __le16 r;
+ s16 res_db;
+
+ if (is_playback)
+ res_db = opts->p_volume_res;
+ else
+ res_db = opts->c_volume_res;
+
+ r = cpu_to_le16(res_db);
+
+ value = min_t(unsigned int, w_length, sizeof(r));
+ memcpy(req->buf, &r, value);
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ }
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
+ }
+
+ return value;
+}
+
+static void
+out_rq_cur_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct g_audio *audio = req->context;
+ struct usb_composite_dev *cdev = audio->func.config->cdev;
+ struct f_uac1_opts *opts = g_audio_to_uac1_opts(audio);
+ struct f_uac1 *uac1 = func_to_uac1(&audio->func);
+ struct usb_ctrlrequest *cr = &uac1->setup_cr;
+ u16 w_index = le16_to_cpu(cr->wIndex);
+ u16 w_value = le16_to_cpu(cr->wValue);
+ u8 entity_id = (w_index >> 8) & 0xff;
+ u8 control_selector = w_value >> 8;
+
+ if (req->status != 0) {
+ dev_dbg(&cdev->gadget->dev, "completion err %d\n", req->status);
+ return;
+ }
+
+ if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ unsigned int is_playback = 0;
+
+ if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID))
+ is_playback = 1;
+
+ if (control_selector == UAC_FU_MUTE) {
+ u8 mute = *(u8 *)req->buf;
+
+ u_audio_set_mute(audio, is_playback, mute);
+
+ return;
+ } else if (control_selector == UAC_FU_VOLUME) {
+ __le16 *c = req->buf;
+ s16 volume;
+
+ volume = le16_to_cpu(*c);
+ u_audio_set_volume(audio, is_playback, volume);
+
+ return;
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ usb_ep_set_halt(ep);
+ }
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
+ usb_ep_set_halt(ep);
+
+ }
+}
+
+static int
+out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+ struct usb_request *req = fn->config->cdev->req;
+ struct g_audio *audio = func_to_g_audio(fn);
+ struct f_uac1_opts *opts = g_audio_to_uac1_opts(audio);
+ struct f_uac1 *uac1 = func_to_uac1(&audio->func);
+ u16 w_length = le16_to_cpu(cr->wLength);
+ u16 w_index = le16_to_cpu(cr->wIndex);
+ u16 w_value = le16_to_cpu(cr->wValue);
+ u8 entity_id = (w_index >> 8) & 0xff;
+ u8 control_selector = w_value >> 8;
+
+ if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ memcpy(&uac1->setup_cr, cr, sizeof(*cr));
+ req->context = audio;
+ req->complete = out_rq_cur_complete;
+
+ return w_length;
+ } else {
+ dev_err(&audio->gadget->dev,
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
+ }
+ return -EOPNOTSUPP;
+}
+
+static int ac_rq_in(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ int value = -EOPNOTSUPP;
+ u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n",
+ ctrl->bRequest, w_value, len, ep);
+
+ switch (ctrl->bRequest) {
+ case UAC_GET_CUR:
+ return in_rq_cur(f, ctrl);
+ case UAC_GET_MIN:
+ return in_rq_min(f, ctrl);
+ case UAC_GET_MAX:
+ return in_rq_max(f, ctrl);
+ case UAC_GET_RES:
+ return in_rq_res(f, ctrl);
+ case UAC_GET_MEM:
+ break;
+ case UAC_GET_STAT:
+ value = len;
+ break;
+ default:
+ break;
+ }
+
+ return value;
+}
+
static int audio_set_endpoint_req(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
@@ -383,7 +788,13 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
value = audio_get_endpoint_req(f, ctrl);
break;
-
+ case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
+ if (ctrl->bRequest == UAC_SET_CUR)
+ value = out_rq_cur(f, ctrl);
+ break;
+ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
+ value = ac_rq_in(f, ctrl);
+ break;
default:
ERROR(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
@@ -411,6 +822,7 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
struct usb_composite_dev *cdev = f->config->cdev;
struct usb_gadget *gadget = cdev->gadget;
struct device *dev = &gadget->dev;
+ struct g_audio *audio = func_to_g_audio(f);
struct f_uac1 *uac1 = func_to_uac1(f);
int ret = 0;
@@ -426,6 +838,14 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return -EINVAL;
}
+
+ /* restart interrupt endpoint */
+ if (uac1->int_ep) {
+ usb_ep_disable(uac1->int_ep);
+ config_ep_by_speed(gadget, &audio->func, uac1->int_ep);
+ usb_ep_enable(uac1->int_ep);
+ }
+
return 0;
}
@@ -481,10 +901,33 @@ static void f_audio_disable(struct usb_function *f)
u_audio_stop_playback(&uac1->g_audio);
u_audio_stop_capture(&uac1->g_audio);
+ if (uac1->int_ep)
+ usb_ep_disable(uac1->int_ep);
}
/*-------------------------------------------------------------------------*/
+static struct uac_feature_unit_descriptor *build_fu_desc(int chmask)
+{
+ struct uac_feature_unit_descriptor *fu_desc;
+ int channels = num_channels(chmask);
+ int fu_desc_size = UAC_DT_FEATURE_UNIT_SIZE(channels);
+
+ fu_desc = kzalloc(fu_desc_size, GFP_KERNEL);
+ if (!fu_desc)
+ return NULL;
+
+ fu_desc->bLength = fu_desc_size;
+ fu_desc->bDescriptorType = USB_DT_CS_INTERFACE;
+
+ fu_desc->bDescriptorSubtype = UAC_FEATURE_UNIT;
+ fu_desc->bControlSize = 2;
+ /* bUnitID, bSourceID and bmaControls will be defined later */
+
+ return fu_desc;
+}
+
+/* B.3.2 Class-Specific AC Interface Descriptor */
static struct
uac1_ac_header_descriptor *build_ac_header_desc(struct f_uac1_opts *opts)
{
@@ -530,9 +973,23 @@ static void setup_descriptor(struct f_uac1_opts *opts)
io_out_ot_desc.bTerminalID = i++;
if (EPIN_EN(opts))
usb_in_ot_desc.bTerminalID = i++;
-
- usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID;
- io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID;
+ if (FUOUT_EN(opts))
+ out_feature_unit_desc->bUnitID = i++;
+ if (FUIN_EN(opts))
+ in_feature_unit_desc->bUnitID = i++;
+
+ if (FUIN_EN(opts)) {
+ usb_in_ot_desc.bSourceID = in_feature_unit_desc->bUnitID;
+ in_feature_unit_desc->bSourceID = io_in_it_desc.bTerminalID;
+ } else {
+ usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID;
+ }
+ if (FUOUT_EN(opts)) {
+ io_out_ot_desc.bSourceID = out_feature_unit_desc->bUnitID;
+ out_feature_unit_desc->bSourceID = usb_out_it_desc.bTerminalID;
+ } else {
+ io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID;
+ }
as_out_header_desc.bTerminalLink = usb_out_it_desc.bTerminalID;
as_in_header_desc.bTerminalLink = usb_in_ot_desc.bTerminalID;
@@ -544,6 +1001,8 @@ static void setup_descriptor(struct f_uac1_opts *opts)
len += sizeof(usb_in_ot_desc);
len += sizeof(io_in_it_desc);
+ if (FUIN_EN(opts))
+ len += in_feature_unit_desc->bLength;
ac_header_desc->wTotalLength = cpu_to_le16(len);
}
if (EPOUT_EN(opts)) {
@@ -551,6 +1010,8 @@ static void setup_descriptor(struct f_uac1_opts *opts)
len += sizeof(usb_out_it_desc);
len += sizeof(io_out_ot_desc);
+ if (FUOUT_EN(opts))
+ len += out_feature_unit_desc->bLength;
ac_header_desc->wTotalLength = cpu_to_le16(len);
}
@@ -561,13 +1022,20 @@ static void setup_descriptor(struct f_uac1_opts *opts)
if (EPOUT_EN(opts)) {
f_audio_desc[i++] = USBDHDR(&usb_out_it_desc);
f_audio_desc[i++] = USBDHDR(&io_out_ot_desc);
+ if (FUOUT_EN(opts))
+ f_audio_desc[i++] = USBDHDR(out_feature_unit_desc);
}
if (EPIN_EN(opts)) {
f_audio_desc[i++] = USBDHDR(&io_in_it_desc);
f_audio_desc[i++] = USBDHDR(&usb_in_ot_desc);
+ if (FUIN_EN(opts))
+ f_audio_desc[i++] = USBDHDR(in_feature_unit_desc);
}
+ if (FUOUT_EN(opts) || FUIN_EN(opts))
+ f_audio_desc[i++] = USBDHDR(&ac_int_ep_desc);
+
if (EPOUT_EN(opts)) {
f_audio_desc[i++] = USBDHDR(&as_out_interface_alt_0_desc);
f_audio_desc[i++] = USBDHDR(&as_out_interface_alt_1_desc);
@@ -614,6 +1082,28 @@ static int f_audio_validate_opts(struct g_audio *audio, struct device *dev)
return -EINVAL;
}
+ if (opts->p_volume_max <= opts->p_volume_min) {
+ dev_err(dev, "Error: incorrect playback volume max/min\n");
+ return -EINVAL;
+ } else if (opts->c_volume_max <= opts->c_volume_min) {
+ dev_err(dev, "Error: incorrect capture volume max/min\n");
+ return -EINVAL;
+ } else if (opts->p_volume_res <= 0) {
+ dev_err(dev, "Error: negative/zero playback volume resolution\n");
+ return -EINVAL;
+ } else if (opts->c_volume_res <= 0) {
+ dev_err(dev, "Error: negative/zero capture volume resolution\n");
+ return -EINVAL;
+ }
+
+ if ((opts->p_volume_max - opts->p_volume_min) % opts->p_volume_res) {
+ dev_err(dev, "Error: incorrect playback volume resolution\n");
+ return -EINVAL;
+ } else if ((opts->c_volume_max - opts->c_volume_min) % opts->c_volume_res) {
+ dev_err(dev, "Error: incorrect capture volume resolution\n");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -647,6 +1137,21 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
if (!ac_header_desc)
return -ENOMEM;
+ if (FUOUT_EN(audio_opts)) {
+ out_feature_unit_desc = build_fu_desc(audio_opts->c_chmask);
+ if (!out_feature_unit_desc) {
+ status = -ENOMEM;
+ goto fail;
+ }
+ }
+ if (FUIN_EN(audio_opts)) {
+ in_feature_unit_desc = build_fu_desc(audio_opts->p_chmask);
+ if (!in_feature_unit_desc) {
+ status = -ENOMEM;
+ goto err_free_fu;
+ }
+ }
+
ac_interface_desc.iInterface = us[STR_AC_IF].id;
usb_out_it_desc.iTerminal = us[STR_USB_OUT_IT].id;
usb_out_it_desc.iChannelNames = us[STR_USB_OUT_IT_CH_NAMES].id;
@@ -659,6 +1164,21 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
as_in_interface_alt_0_desc.iInterface = us[STR_AS_IN_IF_ALT0].id;
as_in_interface_alt_1_desc.iInterface = us[STR_AS_IN_IF_ALT1].id;
+ if (FUOUT_EN(audio_opts)) {
+ u8 *i_feature;
+
+ i_feature = (u8 *)out_feature_unit_desc +
+ out_feature_unit_desc->bLength - 1;
+ *i_feature = us[STR_FU_OUT].id;
+ }
+ if (FUIN_EN(audio_opts)) {
+ u8 *i_feature;
+
+ i_feature = (u8 *)in_feature_unit_desc +
+ in_feature_unit_desc->bLength - 1;
+ *i_feature = us[STR_FU_IN].id;
+ }
+
/* Set channel numbers */
usb_out_it_desc.bNrChannels = num_channels(audio_opts->c_chmask);
usb_out_it_desc.wChannelConfig = cpu_to_le16(audio_opts->c_chmask);
@@ -671,6 +1191,27 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
as_in_type_i_desc.bSubframeSize = audio_opts->p_ssize;
as_in_type_i_desc.bBitResolution = audio_opts->p_ssize * 8;
+ if (FUOUT_EN(audio_opts)) {
+ __le16 *bma = (__le16 *)&out_feature_unit_desc->bmaControls[0];
+ u32 control = 0;
+
+ if (audio_opts->c_mute_present)
+ control |= UAC_FU_MUTE;
+ if (audio_opts->c_volume_present)
+ control |= UAC_FU_VOLUME;
+ *bma = cpu_to_le16(control);
+ }
+ if (FUIN_EN(audio_opts)) {
+ __le16 *bma = (__le16 *)&in_feature_unit_desc->bmaControls[0];
+ u32 control = 0;
+
+ if (audio_opts->p_mute_present)
+ control |= UAC_FU_MUTE;
+ if (audio_opts->p_volume_present)
+ control |= UAC_FU_VOLUME;
+ *bma = cpu_to_le16(control);
+ }
+
/* Set sample rates */
rate = audio_opts->c_srate;
sam_freq = as_out_type_i_desc.tSamFreq[0];
@@ -682,7 +1223,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
- goto fail;
+ goto err_free_fu;
ac_interface_desc.bInterfaceNumber = status;
uac1->ac_intf = status;
uac1->ac_alt = 0;
@@ -692,7 +1233,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
if (EPOUT_EN(audio_opts)) {
status = usb_interface_id(c, f);
if (status < 0)
- goto fail;
+ goto err_free_fu;
as_out_interface_alt_0_desc.bInterfaceNumber = status;
as_out_interface_alt_1_desc.bInterfaceNumber = status;
ac_header_desc->baInterfaceNr[ba_iface_id++] = status;
@@ -703,7 +1244,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
if (EPIN_EN(audio_opts)) {
status = usb_interface_id(c, f);
if (status < 0)
- goto fail;
+ goto err_free_fu;
as_in_interface_alt_0_desc.bInterfaceNumber = status;
as_in_interface_alt_1_desc.bInterfaceNumber = status;
ac_header_desc->baInterfaceNr[ba_iface_id++] = status;
@@ -715,11 +1256,24 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENODEV;
+ ac_interface_desc.bNumEndpoints = 0;
+
+ /* allocate AC interrupt endpoint */
+ if (FUOUT_EN(audio_opts) || FUIN_EN(audio_opts)) {
+ ep = usb_ep_autoconfig(cdev->gadget, &ac_int_ep_desc);
+ if (!ep)
+ goto err_free_fu;
+ uac1->int_ep = ep;
+ uac1->int_ep->desc = &ac_int_ep_desc;
+
+ ac_interface_desc.bNumEndpoints = 1;
+ }
+
/* allocate instance-specific endpoints */
if (EPOUT_EN(audio_opts)) {
ep = usb_ep_autoconfig(cdev->gadget, &as_out_ep_desc);
if (!ep)
- goto fail;
+ goto err_free_fu;
audio->out_ep = ep;
audio->out_ep->desc = &as_out_ep_desc;
}
@@ -727,7 +1281,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
if (EPIN_EN(audio_opts)) {
ep = usb_ep_autoconfig(cdev->gadget, &as_in_ep_desc);
if (!ep)
- goto fail;
+ goto err_free_fu;
audio->in_ep = ep;
audio->in_ep->desc = &as_in_ep_desc;
}
@@ -738,17 +1292,37 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL,
NULL);
if (status)
- goto fail;
+ goto err_free_fu;
audio->out_ep_maxpsize = le16_to_cpu(as_out_ep_desc.wMaxPacketSize);
audio->in_ep_maxpsize = le16_to_cpu(as_in_ep_desc.wMaxPacketSize);
audio->params.c_chmask = audio_opts->c_chmask;
audio->params.c_srate = audio_opts->c_srate;
audio->params.c_ssize = audio_opts->c_ssize;
+ if (FUIN_EN(audio_opts)) {
+ audio->params.p_fu.id = USB_IN_FU_ID;
+ audio->params.p_fu.mute_present = audio_opts->p_mute_present;
+ audio->params.p_fu.volume_present =
+ audio_opts->p_volume_present;
+ audio->params.p_fu.volume_min = audio_opts->p_volume_min;
+ audio->params.p_fu.volume_max = audio_opts->p_volume_max;
+ audio->params.p_fu.volume_res = audio_opts->p_volume_res;
+ }
audio->params.p_chmask = audio_opts->p_chmask;
audio->params.p_srate = audio_opts->p_srate;
audio->params.p_ssize = audio_opts->p_ssize;
+ if (FUOUT_EN(audio_opts)) {
+ audio->params.c_fu.id = USB_OUT_FU_ID;
+ audio->params.c_fu.mute_present = audio_opts->c_mute_present;
+ audio->params.c_fu.volume_present =
+ audio_opts->c_volume_present;
+ audio->params.c_fu.volume_min = audio_opts->c_volume_min;
+ audio->params.c_fu.volume_max = audio_opts->c_volume_max;
+ audio->params.c_fu.volume_res = audio_opts->c_volume_res;
+ }
audio->params.req_number = audio_opts->req_number;
+ if (FUOUT_EN(audio_opts) || FUIN_EN(audio_opts))
+ audio->notify = audio_notify;
status = g_audio_setup(audio, "UAC1_PCM", "UAC1_Gadget");
if (status)
@@ -758,6 +1332,11 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
err_card_register:
usb_free_all_descriptors(f);
+err_free_fu:
+ kfree(out_feature_unit_desc);
+ out_feature_unit_desc = NULL;
+ kfree(in_feature_unit_desc);
+ in_feature_unit_desc = NULL;
fail:
kfree(ac_header_desc);
ac_header_desc = NULL;
@@ -783,7 +1362,15 @@ static struct configfs_item_operations f_uac1_item_ops = {
.release = f_uac1_attr_release,
};
-#define UAC1_ATTRIBUTE(name) \
+#define uac1_kstrtou32 kstrtou32
+#define uac1_kstrtos16 kstrtos16
+#define uac1_kstrtobool(s, base, res) kstrtobool((s), (res))
+
+static const char *u32_fmt = "%u\n";
+static const char *s16_fmt = "%hd\n";
+static const char *bool_fmt = "%u\n";
+
+#define UAC1_ATTRIBUTE(type, name) \
static ssize_t f_uac1_opts_##name##_show( \
struct config_item *item, \
char *page) \
@@ -792,7 +1379,7 @@ static ssize_t f_uac1_opts_##name##_show( \
int result; \
\
mutex_lock(&opts->lock); \
- result = sprintf(page, "%u\n", opts->name); \
+ result = sprintf(page, type##_fmt, opts->name); \
mutex_unlock(&opts->lock); \
\
return result; \
@@ -804,7 +1391,7 @@ static ssize_t f_uac1_opts_##name##_store( \
{ \
struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int ret; \
- u32 num; \
+ type num; \
\
mutex_lock(&opts->lock); \
if (opts->refcnt) { \
@@ -812,7 +1399,7 @@ static ssize_t f_uac1_opts_##name##_store( \
goto end; \
} \
\
- ret = kstrtou32(page, 0, &num); \
+ ret = uac1_kstrto##type(page, 0, &num); \
if (ret) \
goto end; \
\
@@ -826,13 +1413,25 @@ end: \
\
CONFIGFS_ATTR(f_uac1_opts_, name)
-UAC1_ATTRIBUTE(c_chmask);
-UAC1_ATTRIBUTE(c_srate);
-UAC1_ATTRIBUTE(c_ssize);
-UAC1_ATTRIBUTE(p_chmask);
-UAC1_ATTRIBUTE(p_srate);
-UAC1_ATTRIBUTE(p_ssize);
-UAC1_ATTRIBUTE(req_number);
+UAC1_ATTRIBUTE(u32, c_chmask);
+UAC1_ATTRIBUTE(u32, c_srate);
+UAC1_ATTRIBUTE(u32, c_ssize);
+UAC1_ATTRIBUTE(u32, p_chmask);
+UAC1_ATTRIBUTE(u32, p_srate);
+UAC1_ATTRIBUTE(u32, p_ssize);
+UAC1_ATTRIBUTE(u32, req_number);
+
+UAC1_ATTRIBUTE(bool, p_mute_present);
+UAC1_ATTRIBUTE(bool, p_volume_present);
+UAC1_ATTRIBUTE(s16, p_volume_min);
+UAC1_ATTRIBUTE(s16, p_volume_max);
+UAC1_ATTRIBUTE(s16, p_volume_res);
+
+UAC1_ATTRIBUTE(bool, c_mute_present);
+UAC1_ATTRIBUTE(bool, c_volume_present);
+UAC1_ATTRIBUTE(s16, c_volume_min);
+UAC1_ATTRIBUTE(s16, c_volume_max);
+UAC1_ATTRIBUTE(s16, c_volume_res);
static struct configfs_attribute *f_uac1_attrs[] = {
&f_uac1_opts_attr_c_chmask,
@@ -842,6 +1441,19 @@ static struct configfs_attribute *f_uac1_attrs[] = {
&f_uac1_opts_attr_p_srate,
&f_uac1_opts_attr_p_ssize,
&f_uac1_opts_attr_req_number,
+
+ &f_uac1_opts_attr_p_mute_present,
+ &f_uac1_opts_attr_p_volume_present,
+ &f_uac1_opts_attr_p_volume_min,
+ &f_uac1_opts_attr_p_volume_max,
+ &f_uac1_opts_attr_p_volume_res,
+
+ &f_uac1_opts_attr_c_mute_present,
+ &f_uac1_opts_attr_c_volume_present,
+ &f_uac1_opts_attr_c_volume_min,
+ &f_uac1_opts_attr_c_volume_max,
+ &f_uac1_opts_attr_c_volume_res,
+
NULL,
};
@@ -879,6 +1491,19 @@ static struct usb_function_instance *f_audio_alloc_inst(void)
opts->p_chmask = UAC1_DEF_PCHMASK;
opts->p_srate = UAC1_DEF_PSRATE;
opts->p_ssize = UAC1_DEF_PSSIZE;
+
+ opts->p_mute_present = UAC1_DEF_MUTE_PRESENT;
+ opts->p_volume_present = UAC1_DEF_VOLUME_PRESENT;
+ opts->p_volume_min = UAC1_DEF_MIN_DB;
+ opts->p_volume_max = UAC1_DEF_MAX_DB;
+ opts->p_volume_res = UAC1_DEF_RES_DB;
+
+ opts->c_mute_present = UAC1_DEF_MUTE_PRESENT;
+ opts->c_volume_present = UAC1_DEF_VOLUME_PRESENT;
+ opts->c_volume_min = UAC1_DEF_MIN_DB;
+ opts->c_volume_max = UAC1_DEF_MAX_DB;
+ opts->c_volume_res = UAC1_DEF_RES_DB;
+
opts->req_number = UAC1_DEF_REQ_NUM;
return &opts->func_inst;
}
@@ -903,6 +1528,11 @@ static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
g_audio_cleanup(audio);
usb_free_all_descriptors(f);
+ kfree(out_feature_unit_desc);
+ out_feature_unit_desc = NULL;
+ kfree(in_feature_unit_desc);
+ in_feature_unit_desc = NULL;
+
kfree(ac_header_desc);
ac_header_desc = NULL;
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index ae29ff2b2b68..3c34995276e7 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -5,6 +5,9 @@
* Copyright (C) 2011
* Yadwinder Singh (yadi.brar01@gmail.com)
* Jaswinder Singh (jaswinder.singh@linaro.org)
+ *
+ * Copyright (C) 2020
+ * Ruslan Bilovol (ruslan.bilovol@gmail.com)
*/
#include <linux/usb/audio.h>
@@ -19,14 +22,16 @@
/*
* The driver implements a simple UAC_2 topology.
- * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
- * ALSA_Playback -> IT_2 -> OT_4 -> USB-IN
+ * USB-OUT -> IT_1 -> FU -> OT_3 -> ALSA_Capture
+ * ALSA_Playback -> IT_2 -> FU -> OT_4 -> USB-IN
* Capture and Playback sampling rates are independently
* controlled by two clock sources :
* CLK_5 := c_srate, and CLK_6 := p_srate
*/
#define USB_OUT_CLK_ID (out_clk_src_desc.bClockID)
#define USB_IN_CLK_ID (in_clk_src_desc.bClockID)
+#define USB_OUT_FU_ID (out_feature_unit_desc->bUnitID)
+#define USB_IN_FU_ID (in_feature_unit_desc->bUnitID)
#define CONTROL_ABSENT 0
#define CONTROL_RDONLY 1
@@ -34,6 +39,8 @@
#define CLK_FREQ_CTRL 0
#define CLK_VLD_CTRL 2
+#define FU_MUTE_CTRL 0
+#define FU_VOL_CTRL 2
#define COPY_CTRL 0
#define CONN_CTRL 2
@@ -44,12 +51,24 @@
#define EPIN_EN(_opts) ((_opts)->p_chmask != 0)
#define EPOUT_EN(_opts) ((_opts)->c_chmask != 0)
+#define FUIN_EN(_opts) (EPIN_EN(_opts) \
+ && ((_opts)->p_mute_present \
+ || (_opts)->p_volume_present))
+#define FUOUT_EN(_opts) (EPOUT_EN(_opts) \
+ && ((_opts)->c_mute_present \
+ || (_opts)->c_volume_present))
#define EPOUT_FBACK_IN_EN(_opts) ((_opts)->c_sync == USB_ENDPOINT_SYNC_ASYNC)
struct f_uac2 {
struct g_audio g_audio;
u8 ac_intf, as_in_intf, as_out_intf;
u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */
+
+ struct usb_ctrlrequest setup_cr; /* will be used in data stage */
+
+ /* Interrupt IN endpoint of AC interface */
+ struct usb_ep *int_ep;
+ atomic_t int_count;
};
static inline struct f_uac2 *func_to_uac2(struct usb_function *f)
@@ -63,6 +82,8 @@ struct f_uac2_opts *g_audio_to_uac2_opts(struct g_audio *agdev)
return container_of(agdev->func.fi, struct f_uac2_opts, func_inst);
}
+static int afunc_notify(struct g_audio *agdev, int unit_id, int cs);
+
/* --------- USB Function Interface ------------- */
enum {
@@ -74,6 +95,8 @@ enum {
STR_IO_IT,
STR_USB_OT,
STR_IO_OT,
+ STR_FU_IN,
+ STR_FU_OUT,
STR_AS_OUT_ALT0,
STR_AS_OUT_ALT1,
STR_AS_IN_ALT0,
@@ -92,6 +115,8 @@ static struct usb_string strings_fn[] = {
[STR_IO_IT].s = "USBD Out",
[STR_USB_OT].s = "USBH In",
[STR_IO_OT].s = "USBD In",
+ [STR_FU_IN].s = "Capture Volume",
+ [STR_FU_OUT].s = "Playback Volume",
[STR_AS_OUT_ALT0].s = "Playback Inactive",
[STR_AS_OUT_ALT1].s = "Playback Active",
[STR_AS_IN_ALT0].s = "Capture Inactive",
@@ -126,7 +151,7 @@ static struct usb_interface_descriptor std_ac_if_desc = {
.bDescriptorType = USB_DT_INTERFACE,
.bAlternateSetting = 0,
- .bNumEndpoints = 0,
+ /* .bNumEndpoints = DYNAMIC */
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
.bInterfaceProtocol = UAC_VERSION_2,
@@ -212,6 +237,9 @@ static struct uac2_output_terminal_descriptor io_out_ot_desc = {
.bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
};
+static struct uac2_feature_unit_descriptor *in_feature_unit_desc;
+static struct uac2_feature_unit_descriptor *out_feature_unit_desc;
+
static struct uac2_ac_header_descriptor ac_hdr_desc = {
.bLength = sizeof ac_hdr_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
@@ -223,6 +251,36 @@ static struct uac2_ac_header_descriptor ac_hdr_desc = {
.bmControls = 0,
};
+/* AC IN Interrupt Endpoint */
+static struct usb_endpoint_descriptor fs_ep_int_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(6),
+ .bInterval = 1,
+};
+
+static struct usb_endpoint_descriptor hs_ep_int_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(6),
+ .bInterval = 4,
+};
+
+static struct usb_endpoint_descriptor ss_ep_int_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(6),
+ .bInterval = 4,
+};
+
/* Audio Streaming OUT Interface - Alt0 */
static struct usb_interface_descriptor std_as_out_if0_desc = {
.bLength = sizeof std_as_out_if0_desc,
@@ -452,10 +510,14 @@ static struct usb_descriptor_header *fs_audio_desc[] = {
(struct usb_descriptor_header *)&in_clk_src_desc,
(struct usb_descriptor_header *)&out_clk_src_desc,
(struct usb_descriptor_header *)&usb_out_it_desc,
+ (struct usb_descriptor_header *)&out_feature_unit_desc,
(struct usb_descriptor_header *)&io_in_it_desc,
(struct usb_descriptor_header *)&usb_in_ot_desc,
+ (struct usb_descriptor_header *)&in_feature_unit_desc,
(struct usb_descriptor_header *)&io_out_ot_desc,
+ (struct usb_descriptor_header *)&fs_ep_int_desc,
+
(struct usb_descriptor_header *)&std_as_out_if0_desc,
(struct usb_descriptor_header *)&std_as_out_if1_desc,
@@ -483,10 +545,14 @@ static struct usb_descriptor_header *hs_audio_desc[] = {
(struct usb_descriptor_header *)&in_clk_src_desc,
(struct usb_descriptor_header *)&out_clk_src_desc,
(struct usb_descriptor_header *)&usb_out_it_desc,
+ (struct usb_descriptor_header *)&out_feature_unit_desc,
(struct usb_descriptor_header *)&io_in_it_desc,
(struct usb_descriptor_header *)&usb_in_ot_desc,
+ (struct usb_descriptor_header *)&in_feature_unit_desc,
(struct usb_descriptor_header *)&io_out_ot_desc,
+ (struct usb_descriptor_header *)&hs_ep_int_desc,
+
(struct usb_descriptor_header *)&std_as_out_if0_desc,
(struct usb_descriptor_header *)&std_as_out_if1_desc,
@@ -514,10 +580,14 @@ static struct usb_descriptor_header *ss_audio_desc[] = {
(struct usb_descriptor_header *)&in_clk_src_desc,
(struct usb_descriptor_header *)&out_clk_src_desc,
(struct usb_descriptor_header *)&usb_out_it_desc,
+ (struct usb_descriptor_header *)&out_feature_unit_desc,
(struct usb_descriptor_header *)&io_in_it_desc,
(struct usb_descriptor_header *)&usb_in_ot_desc,
+ (struct usb_descriptor_header *)&in_feature_unit_desc,
(struct usb_descriptor_header *)&io_out_ot_desc,
+ (struct usb_descriptor_header *)&ss_ep_int_desc,
+
(struct usb_descriptor_header *)&std_as_out_if0_desc,
(struct usb_descriptor_header *)&std_as_out_if1_desc,
@@ -539,6 +609,17 @@ static struct usb_descriptor_header *ss_audio_desc[] = {
NULL,
};
+struct cntrl_cur_lay2 {
+ __le16 wCUR;
+};
+
+struct cntrl_range_lay2 {
+ __le16 wNumSubRanges;
+ __le16 wMIN;
+ __le16 wMAX;
+ __le16 wRES;
+} __packed;
+
struct cntrl_cur_lay3 {
__le32 dCUR;
};
@@ -595,6 +676,26 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
return 0;
}
+static struct uac2_feature_unit_descriptor *build_fu_desc(int chmask)
+{
+ struct uac2_feature_unit_descriptor *fu_desc;
+ int channels = num_channels(chmask);
+ int fu_desc_size = UAC2_DT_FEATURE_UNIT_SIZE(channels);
+
+ fu_desc = kzalloc(fu_desc_size, GFP_KERNEL);
+ if (!fu_desc)
+ return NULL;
+
+ fu_desc->bLength = fu_desc_size;
+ fu_desc->bDescriptorType = USB_DT_CS_INTERFACE;
+
+ fu_desc->bDescriptorSubtype = UAC_FEATURE_UNIT;
+
+ /* bUnitID, bSourceID and bmaControls will be defined later */
+
+ return fu_desc;
+}
+
/* Use macro to overcome line length limitation */
#define USBDHDR(p) (struct usb_descriptor_header *)(p)
@@ -607,6 +708,7 @@ static void setup_headers(struct f_uac2_opts *opts,
struct usb_endpoint_descriptor *epout_desc;
struct usb_endpoint_descriptor *epin_desc;
struct usb_endpoint_descriptor *epin_fback_desc;
+ struct usb_endpoint_descriptor *ep_int_desc;
int i;
switch (speed) {
@@ -614,11 +716,13 @@ static void setup_headers(struct f_uac2_opts *opts,
epout_desc = &fs_epout_desc;
epin_desc = &fs_epin_desc;
epin_fback_desc = &fs_epin_fback_desc;
+ ep_int_desc = &fs_ep_int_desc;
break;
case USB_SPEED_HIGH:
epout_desc = &hs_epout_desc;
epin_desc = &hs_epin_desc;
epin_fback_desc = &hs_epin_fback_desc;
+ ep_int_desc = &hs_ep_int_desc;
break;
default:
epout_desc = &ss_epout_desc;
@@ -626,6 +730,7 @@ static void setup_headers(struct f_uac2_opts *opts,
epout_desc_comp = &ss_epout_desc_comp;
epin_desc_comp = &ss_epin_desc_comp;
epin_fback_desc = &ss_epin_fback_desc;
+ ep_int_desc = &ss_ep_int_desc;
}
i = 0;
@@ -637,13 +742,27 @@ static void setup_headers(struct f_uac2_opts *opts,
if (EPOUT_EN(opts)) {
headers[i++] = USBDHDR(&out_clk_src_desc);
headers[i++] = USBDHDR(&usb_out_it_desc);
- }
+
+ if (FUOUT_EN(opts))
+ headers[i++] = USBDHDR(out_feature_unit_desc);
+ }
+
if (EPIN_EN(opts)) {
headers[i++] = USBDHDR(&io_in_it_desc);
+
+ if (FUIN_EN(opts))
+ headers[i++] = USBDHDR(in_feature_unit_desc);
+
headers[i++] = USBDHDR(&usb_in_ot_desc);
}
- if (EPOUT_EN(opts)) {
+
+ if (EPOUT_EN(opts))
headers[i++] = USBDHDR(&io_out_ot_desc);
+
+ if (FUOUT_EN(opts) || FUIN_EN(opts))
+ headers[i++] = USBDHDR(ep_int_desc);
+
+ if (EPOUT_EN(opts)) {
headers[i++] = USBDHDR(&std_as_out_if0_desc);
headers[i++] = USBDHDR(&std_as_out_if1_desc);
headers[i++] = USBDHDR(&as_out_hdr_desc);
@@ -657,6 +776,7 @@ static void setup_headers(struct f_uac2_opts *opts,
if (EPOUT_FBACK_IN_EN(opts))
headers[i++] = USBDHDR(epin_fback_desc);
}
+
if (EPIN_EN(opts)) {
headers[i++] = USBDHDR(&std_as_in_if0_desc);
headers[i++] = USBDHDR(&std_as_in_if1_desc);
@@ -684,17 +804,35 @@ static void setup_descriptor(struct f_uac2_opts *opts)
io_out_ot_desc.bTerminalID = i++;
if (EPIN_EN(opts))
usb_in_ot_desc.bTerminalID = i++;
+ if (FUOUT_EN(opts))
+ out_feature_unit_desc->bUnitID = i++;
+ if (FUIN_EN(opts))
+ in_feature_unit_desc->bUnitID = i++;
if (EPOUT_EN(opts))
out_clk_src_desc.bClockID = i++;
if (EPIN_EN(opts))
in_clk_src_desc.bClockID = i++;
usb_out_it_desc.bCSourceID = out_clk_src_desc.bClockID;
- usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID;
+
+ if (FUIN_EN(opts)) {
+ usb_in_ot_desc.bSourceID = in_feature_unit_desc->bUnitID;
+ in_feature_unit_desc->bSourceID = io_in_it_desc.bTerminalID;
+ } else {
+ usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID;
+ }
+
usb_in_ot_desc.bCSourceID = in_clk_src_desc.bClockID;
io_in_it_desc.bCSourceID = in_clk_src_desc.bClockID;
io_out_ot_desc.bCSourceID = out_clk_src_desc.bClockID;
- io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID;
+
+ if (FUOUT_EN(opts)) {
+ io_out_ot_desc.bSourceID = out_feature_unit_desc->bUnitID;
+ out_feature_unit_desc->bSourceID = usb_out_it_desc.bTerminalID;
+ } else {
+ io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID;
+ }
+
as_out_hdr_desc.bTerminalLink = usb_out_it_desc.bTerminalID;
as_in_hdr_desc.bTerminalLink = usb_in_ot_desc.bTerminalID;
@@ -706,6 +844,10 @@ static void setup_descriptor(struct f_uac2_opts *opts)
len += sizeof(in_clk_src_desc);
len += sizeof(usb_in_ot_desc);
+
+ if (FUIN_EN(opts))
+ len += in_feature_unit_desc->bLength;
+
len += sizeof(io_in_it_desc);
ac_hdr_desc.wTotalLength = cpu_to_le16(len);
iad_desc.bInterfaceCount++;
@@ -715,6 +857,10 @@ static void setup_descriptor(struct f_uac2_opts *opts)
len += sizeof(out_clk_src_desc);
len += sizeof(usb_out_it_desc);
+
+ if (FUOUT_EN(opts))
+ len += out_feature_unit_desc->bLength;
+
len += sizeof(io_out_ot_desc);
ac_hdr_desc.wTotalLength = cpu_to_le16(len);
iad_desc.bInterfaceCount++;
@@ -752,6 +898,28 @@ static int afunc_validate_opts(struct g_audio *agdev, struct device *dev)
return -EINVAL;
}
+ if (opts->p_volume_max <= opts->p_volume_min) {
+ dev_err(dev, "Error: incorrect playback volume max/min\n");
+ return -EINVAL;
+ } else if (opts->c_volume_max <= opts->c_volume_min) {
+ dev_err(dev, "Error: incorrect capture volume max/min\n");
+ return -EINVAL;
+ } else if (opts->p_volume_res <= 0) {
+ dev_err(dev, "Error: negative/zero playback volume resolution\n");
+ return -EINVAL;
+ } else if (opts->c_volume_res <= 0) {
+ dev_err(dev, "Error: negative/zero capture volume resolution\n");
+ return -EINVAL;
+ }
+
+ if ((opts->p_volume_max - opts->p_volume_min) % opts->p_volume_res) {
+ dev_err(dev, "Error: incorrect playback volume resolution\n");
+ return -EINVAL;
+ } else if ((opts->c_volume_max - opts->c_volume_min) % opts->c_volume_res) {
+ dev_err(dev, "Error: incorrect capture volume resolution\n");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -774,6 +942,20 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
us = usb_gstrings_attach(cdev, fn_strings, ARRAY_SIZE(strings_fn));
if (IS_ERR(us))
return PTR_ERR(us);
+
+ if (FUOUT_EN(uac2_opts)) {
+ out_feature_unit_desc = build_fu_desc(uac2_opts->c_chmask);
+ if (!out_feature_unit_desc)
+ return -ENOMEM;
+ }
+ if (FUIN_EN(uac2_opts)) {
+ in_feature_unit_desc = build_fu_desc(uac2_opts->p_chmask);
+ if (!in_feature_unit_desc) {
+ ret = -ENOMEM;
+ goto err_free_fu;
+ }
+ }
+
iad_desc.iFunction = us[STR_ASSOC].id;
std_ac_if_desc.iInterface = us[STR_IF_CTRL].id;
in_clk_src_desc.iClockSource = us[STR_CLKSRC_IN].id;
@@ -787,6 +969,17 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
std_as_in_if0_desc.iInterface = us[STR_AS_IN_ALT0].id;
std_as_in_if1_desc.iInterface = us[STR_AS_IN_ALT1].id;
+ if (FUOUT_EN(uac2_opts)) {
+ u8 *i_feature = (u8 *)out_feature_unit_desc +
+ out_feature_unit_desc->bLength - 1;
+ *i_feature = us[STR_FU_OUT].id;
+ }
+ if (FUIN_EN(uac2_opts)) {
+ u8 *i_feature = (u8 *)in_feature_unit_desc +
+ in_feature_unit_desc->bLength - 1;
+ *i_feature = us[STR_FU_IN].id;
+ }
+
/* Initialize the configurable parameters */
usb_out_it_desc.bNrChannels = num_channels(uac2_opts->c_chmask);
@@ -801,6 +994,26 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
as_out_fmt1_desc.bBitResolution = uac2_opts->c_ssize * 8;
as_in_fmt1_desc.bSubslotSize = uac2_opts->p_ssize;
as_in_fmt1_desc.bBitResolution = uac2_opts->p_ssize * 8;
+ if (FUOUT_EN(uac2_opts)) {
+ __le32 *bma = (__le32 *)&out_feature_unit_desc->bmaControls[0];
+ u32 control = 0;
+
+ if (uac2_opts->c_mute_present)
+ control |= CONTROL_RDWR << FU_MUTE_CTRL;
+ if (uac2_opts->c_volume_present)
+ control |= CONTROL_RDWR << FU_VOL_CTRL;
+ *bma = cpu_to_le32(control);
+ }
+ if (FUIN_EN(uac2_opts)) {
+ __le32 *bma = (__le32 *)&in_feature_unit_desc->bmaControls[0];
+ u32 control = 0;
+
+ if (uac2_opts->p_mute_present)
+ control |= CONTROL_RDWR << FU_MUTE_CTRL;
+ if (uac2_opts->p_volume_present)
+ control |= CONTROL_RDWR << FU_VOL_CTRL;
+ *bma = cpu_to_le32(control);
+ }
snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", uac2_opts->p_srate);
snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", uac2_opts->c_srate);
@@ -808,7 +1021,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return ret;
+ goto err_free_fu;
}
iad_desc.bFirstInterface = ret;
@@ -820,7 +1033,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return ret;
+ goto err_free_fu;
}
std_as_out_if0_desc.bInterfaceNumber = ret;
std_as_out_if1_desc.bInterfaceNumber = ret;
@@ -849,7 +1062,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return ret;
+ goto err_free_fu;
}
std_as_in_if0_desc.bInterfaceNumber = ret;
std_as_in_if1_desc.bInterfaceNumber = ret;
@@ -857,6 +1070,17 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
uac2->as_in_alt = 0;
}
+ if (FUOUT_EN(uac2_opts) || FUIN_EN(uac2_opts)) {
+ uac2->int_ep = usb_ep_autoconfig(gadget, &fs_ep_int_desc);
+ if (!uac2->int_ep) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ ret = -ENODEV;
+ goto err_free_fu;
+ }
+
+ std_ac_if_desc.bNumEndpoints = 1;
+ }
+
/* Calculate wMaxPacketSize according to audio bandwidth */
ret = set_ep_max_packet_size(uac2_opts, &fs_epin_desc, USB_SPEED_FULL,
true);
@@ -904,7 +1128,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
if (!agdev->out_ep) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_free_fu;
}
if (EPOUT_FBACK_IN_EN(uac2_opts)) {
agdev->in_ep_fback = usb_ep_autoconfig(gadget,
@@ -912,7 +1137,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
if (!agdev->in_ep_fback) {
dev_err(dev, "%s:%d Error!\n",
__func__, __LINE__);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_free_fu;
}
}
}
@@ -921,7 +1147,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
if (!agdev->in_ep) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_free_fu;
}
}
@@ -937,38 +1164,137 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
agdev->out_ep_maxpsize = max_t(u16, agdev->out_ep_maxpsize,
le16_to_cpu(ss_epout_desc.wMaxPacketSize));
+ // HS and SS endpoint addresses are copied from autoconfigured FS descriptors
+ hs_ep_int_desc.bEndpointAddress = fs_ep_int_desc.bEndpointAddress;
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
hs_epin_fback_desc.bEndpointAddress = fs_epin_fback_desc.bEndpointAddress;
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
ss_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
ss_epin_fback_desc.bEndpointAddress = fs_epin_fback_desc.bEndpointAddress;
ss_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
+ ss_ep_int_desc.bEndpointAddress = fs_ep_int_desc.bEndpointAddress;
setup_descriptor(uac2_opts);
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, ss_audio_desc,
ss_audio_desc);
if (ret)
- return ret;
+ goto err_free_fu;
agdev->gadget = gadget;
agdev->params.p_chmask = uac2_opts->p_chmask;
agdev->params.p_srate = uac2_opts->p_srate;
agdev->params.p_ssize = uac2_opts->p_ssize;
+ if (FUIN_EN(uac2_opts)) {
+ agdev->params.p_fu.id = USB_IN_FU_ID;
+ agdev->params.p_fu.mute_present = uac2_opts->p_mute_present;
+ agdev->params.p_fu.volume_present = uac2_opts->p_volume_present;
+ agdev->params.p_fu.volume_min = uac2_opts->p_volume_min;
+ agdev->params.p_fu.volume_max = uac2_opts->p_volume_max;
+ agdev->params.p_fu.volume_res = uac2_opts->p_volume_res;
+ }
agdev->params.c_chmask = uac2_opts->c_chmask;
agdev->params.c_srate = uac2_opts->c_srate;
agdev->params.c_ssize = uac2_opts->c_ssize;
+ if (FUOUT_EN(uac2_opts)) {
+ agdev->params.c_fu.id = USB_OUT_FU_ID;
+ agdev->params.c_fu.mute_present = uac2_opts->c_mute_present;
+ agdev->params.c_fu.volume_present = uac2_opts->c_volume_present;
+ agdev->params.c_fu.volume_min = uac2_opts->c_volume_min;
+ agdev->params.c_fu.volume_max = uac2_opts->c_volume_max;
+ agdev->params.c_fu.volume_res = uac2_opts->c_volume_res;
+ }
agdev->params.req_number = uac2_opts->req_number;
agdev->params.fb_max = uac2_opts->fb_max;
+
+ if (FUOUT_EN(uac2_opts) || FUIN_EN(uac2_opts))
+ agdev->notify = afunc_notify;
+
ret = g_audio_setup(agdev, "UAC2 PCM", "UAC2_Gadget");
if (ret)
goto err_free_descs;
+
return 0;
err_free_descs:
usb_free_all_descriptors(fn);
agdev->gadget = NULL;
+err_free_fu:
+ kfree(out_feature_unit_desc);
+ out_feature_unit_desc = NULL;
+ kfree(in_feature_unit_desc);
+ in_feature_unit_desc = NULL;
+ return ret;
+}
+
+static void
+afunc_notify_complete(struct usb_ep *_ep, struct usb_request *req)
+{
+ struct g_audio *agdev = req->context;
+ struct f_uac2 *uac2 = func_to_uac2(&agdev->func);
+
+ atomic_dec(&uac2->int_count);
+ kfree(req->buf);
+ usb_ep_free_request(_ep, req);
+}
+
+static int
+afunc_notify(struct g_audio *agdev, int unit_id, int cs)
+{
+ struct f_uac2 *uac2 = func_to_uac2(&agdev->func);
+ struct usb_request *req;
+ struct uac2_interrupt_data_msg *msg;
+ u16 w_index, w_value;
+ int ret;
+
+ if (!uac2->int_ep->enabled)
+ return 0;
+
+ if (atomic_inc_return(&uac2->int_count) > UAC2_DEF_INT_REQ_NUM) {
+ atomic_dec(&uac2->int_count);
+ return 0;
+ }
+
+ req = usb_ep_alloc_request(uac2->int_ep, GFP_ATOMIC);
+ if (req == NULL) {
+ ret = -ENOMEM;
+ goto err_dec_int_count;
+ }
+
+ msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
+ if (msg == NULL) {
+ ret = -ENOMEM;
+ goto err_free_request;
+ }
+
+ w_index = unit_id << 8 | uac2->ac_intf;
+ w_value = cs << 8;
+
+ msg->bInfo = 0; /* Non-vendor, interface interrupt */
+ msg->bAttribute = UAC2_CS_CUR;
+ msg->wIndex = cpu_to_le16(w_index);
+ msg->wValue = cpu_to_le16(w_value);
+
+ req->length = sizeof(*msg);
+ req->buf = msg;
+ req->context = agdev;
+ req->complete = afunc_notify_complete;
+
+ ret = usb_ep_queue(uac2->int_ep, req, GFP_ATOMIC);
+
+ if (ret)
+ goto err_free_msg;
+
+ return 0;
+
+err_free_msg:
+ kfree(msg);
+err_free_request:
+ usb_ep_free_request(uac2->int_ep, req);
+err_dec_int_count:
+ atomic_dec(&uac2->int_count);
+
return ret;
}
@@ -977,6 +1303,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = fn->config->cdev;
struct f_uac2 *uac2 = func_to_uac2(fn);
+ struct g_audio *agdev = func_to_g_audio(fn);
struct usb_gadget *gadget = cdev->gadget;
struct device *dev = &gadget->dev;
int ret = 0;
@@ -993,6 +1320,14 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return -EINVAL;
}
+
+ /* restart interrupt endpoint */
+ if (uac2->int_ep) {
+ usb_ep_disable(uac2->int_ep);
+ config_ep_by_speed(gadget, &agdev->func, uac2->int_ep);
+ usb_ep_enable(uac2->int_ep);
+ }
+
return 0;
}
@@ -1047,6 +1382,8 @@ afunc_disable(struct usb_function *fn)
uac2->as_out_alt = 0;
u_audio_stop_capture(&uac2->g_audio);
u_audio_stop_playback(&uac2->g_audio);
+ if (uac2->int_ep)
+ usb_ep_disable(uac2->int_ep);
}
static int
@@ -1054,7 +1391,7 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
struct usb_request *req = fn->config->cdev->req;
struct g_audio *agdev = func_to_g_audio(fn);
- struct f_uac2_opts *opts;
+ struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev);
u16 w_length = le16_to_cpu(cr->wLength);
u16 w_index = le16_to_cpu(cr->wIndex);
u16 w_value = le16_to_cpu(cr->wValue);
@@ -1063,28 +1400,64 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
int value = -EOPNOTSUPP;
int p_srate, c_srate;
- opts = g_audio_to_uac2_opts(agdev);
p_srate = opts->p_srate;
c_srate = opts->c_srate;
- if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
- struct cntrl_cur_lay3 c;
- memset(&c, 0, sizeof(struct cntrl_cur_lay3));
+ if ((entity_id == USB_IN_CLK_ID) || (entity_id == USB_OUT_CLK_ID)) {
+ if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
+ struct cntrl_cur_lay3 c;
+
+ memset(&c, 0, sizeof(struct cntrl_cur_lay3));
+
+ if (entity_id == USB_IN_CLK_ID)
+ c.dCUR = cpu_to_le32(p_srate);
+ else if (entity_id == USB_OUT_CLK_ID)
+ c.dCUR = cpu_to_le32(c_srate);
+
+ value = min_t(unsigned int, w_length, sizeof(c));
+ memcpy(req->buf, &c, value);
+ } else if (control_selector == UAC2_CS_CONTROL_CLOCK_VALID) {
+ *(u8 *)req->buf = 1;
+ value = min_t(unsigned int, w_length, 1);
+ } else {
+ dev_err(&agdev->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ }
+ } else if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ unsigned int is_playback = 0;
+
+ if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID))
+ is_playback = 1;
- if (entity_id == USB_IN_CLK_ID)
- c.dCUR = cpu_to_le32(p_srate);
- else if (entity_id == USB_OUT_CLK_ID)
- c.dCUR = cpu_to_le32(c_srate);
+ if (control_selector == UAC_FU_MUTE) {
+ unsigned int mute;
- value = min_t(unsigned, w_length, sizeof c);
- memcpy(req->buf, &c, value);
- } else if (control_selector == UAC2_CS_CONTROL_CLOCK_VALID) {
- *(u8 *)req->buf = 1;
- value = min_t(unsigned, w_length, 1);
+ u_audio_get_mute(agdev, is_playback, &mute);
+
+ *(u8 *)req->buf = mute;
+ value = min_t(unsigned int, w_length, 1);
+ } else if (control_selector == UAC_FU_VOLUME) {
+ struct cntrl_cur_lay2 c;
+ s16 volume;
+
+ memset(&c, 0, sizeof(struct cntrl_cur_lay2));
+
+ u_audio_get_volume(agdev, is_playback, &volume);
+ c.wCUR = cpu_to_le16(volume);
+
+ value = min_t(unsigned int, w_length, sizeof(c));
+ memcpy(req->buf, &c, value);
+ } else {
+ dev_err(&agdev->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ }
} else {
dev_err(&agdev->gadget->dev,
- "%s:%d control_selector=%d TODO!\n",
- __func__, __LINE__, control_selector);
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
}
return value;
@@ -1095,38 +1468,77 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
struct usb_request *req = fn->config->cdev->req;
struct g_audio *agdev = func_to_g_audio(fn);
- struct f_uac2_opts *opts;
+ struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev);
u16 w_length = le16_to_cpu(cr->wLength);
u16 w_index = le16_to_cpu(cr->wIndex);
u16 w_value = le16_to_cpu(cr->wValue);
u8 entity_id = (w_index >> 8) & 0xff;
u8 control_selector = w_value >> 8;
- struct cntrl_range_lay3 r;
int value = -EOPNOTSUPP;
int p_srate, c_srate;
- opts = g_audio_to_uac2_opts(agdev);
p_srate = opts->p_srate;
c_srate = opts->c_srate;
- if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
- if (entity_id == USB_IN_CLK_ID)
- r.dMIN = cpu_to_le32(p_srate);
- else if (entity_id == USB_OUT_CLK_ID)
- r.dMIN = cpu_to_le32(c_srate);
- else
- return -EOPNOTSUPP;
+ if ((entity_id == USB_IN_CLK_ID) || (entity_id == USB_OUT_CLK_ID)) {
+ if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
+ struct cntrl_range_lay3 r;
+
+ if (entity_id == USB_IN_CLK_ID)
+ r.dMIN = cpu_to_le32(p_srate);
+ else if (entity_id == USB_OUT_CLK_ID)
+ r.dMIN = cpu_to_le32(c_srate);
+ else
+ return -EOPNOTSUPP;
- r.dMAX = r.dMIN;
- r.dRES = 0;
- r.wNumSubRanges = cpu_to_le16(1);
+ r.dMAX = r.dMIN;
+ r.dRES = 0;
+ r.wNumSubRanges = cpu_to_le16(1);
- value = min_t(unsigned, w_length, sizeof r);
- memcpy(req->buf, &r, value);
+ value = min_t(unsigned int, w_length, sizeof(r));
+ memcpy(req->buf, &r, value);
+ } else {
+ dev_err(&agdev->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ }
+ } else if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ unsigned int is_playback = 0;
+
+ if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID))
+ is_playback = 1;
+
+ if (control_selector == UAC_FU_VOLUME) {
+ struct cntrl_range_lay2 r;
+ s16 max_db, min_db, res_db;
+
+ if (is_playback) {
+ max_db = opts->p_volume_max;
+ min_db = opts->p_volume_min;
+ res_db = opts->p_volume_res;
+ } else {
+ max_db = opts->c_volume_max;
+ min_db = opts->c_volume_min;
+ res_db = opts->c_volume_res;
+ }
+
+ r.wMAX = cpu_to_le16(max_db);
+ r.wMIN = cpu_to_le16(min_db);
+ r.wRES = cpu_to_le16(res_db);
+ r.wNumSubRanges = cpu_to_le16(1);
+
+ value = min_t(unsigned int, w_length, sizeof(r));
+ memcpy(req->buf, &r, value);
+ } else {
+ dev_err(&agdev->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ }
} else {
dev_err(&agdev->gadget->dev,
- "%s:%d control_selector=%d TODO!\n",
- __func__, __LINE__, control_selector);
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
}
return value;
@@ -1143,16 +1555,82 @@ ac_rq_in(struct usb_function *fn, const struct usb_ctrlrequest *cr)
return -EOPNOTSUPP;
}
+static void
+out_rq_cur_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct g_audio *agdev = req->context;
+ struct usb_composite_dev *cdev = agdev->func.config->cdev;
+ struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev);
+ struct f_uac2 *uac2 = func_to_uac2(&agdev->func);
+ struct usb_ctrlrequest *cr = &uac2->setup_cr;
+ u16 w_index = le16_to_cpu(cr->wIndex);
+ u16 w_value = le16_to_cpu(cr->wValue);
+ u8 entity_id = (w_index >> 8) & 0xff;
+ u8 control_selector = w_value >> 8;
+
+ if (req->status != 0) {
+ dev_dbg(&cdev->gadget->dev, "completion err %d\n", req->status);
+ return;
+ }
+
+ if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ unsigned int is_playback = 0;
+
+ if (FUIN_EN(opts) && (entity_id == USB_IN_FU_ID))
+ is_playback = 1;
+
+ if (control_selector == UAC_FU_MUTE) {
+ u8 mute = *(u8 *)req->buf;
+
+ u_audio_set_mute(agdev, is_playback, mute);
+
+ return;
+ } else if (control_selector == UAC_FU_VOLUME) {
+ struct cntrl_cur_lay2 *c = req->buf;
+ s16 volume;
+
+ volume = le16_to_cpu(c->wCUR);
+ u_audio_set_volume(agdev, is_playback, volume);
+
+ return;
+ } else {
+ dev_err(&agdev->gadget->dev,
+ "%s:%d control_selector=%d TODO!\n",
+ __func__, __LINE__, control_selector);
+ usb_ep_set_halt(ep);
+ }
+ }
+}
+
static int
out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
+ struct usb_request *req = fn->config->cdev->req;
+ struct g_audio *agdev = func_to_g_audio(fn);
+ struct f_uac2_opts *opts = g_audio_to_uac2_opts(agdev);
+ struct f_uac2 *uac2 = func_to_uac2(fn);
u16 w_length = le16_to_cpu(cr->wLength);
+ u16 w_index = le16_to_cpu(cr->wIndex);
u16 w_value = le16_to_cpu(cr->wValue);
+ u8 entity_id = (w_index >> 8) & 0xff;
u8 control_selector = w_value >> 8;
- if (control_selector == UAC2_CS_CONTROL_SAM_FREQ)
- return w_length;
+ if ((entity_id == USB_IN_CLK_ID) || (entity_id == USB_OUT_CLK_ID)) {
+ if (control_selector == UAC2_CS_CONTROL_SAM_FREQ)
+ return w_length;
+ } else if ((FUIN_EN(opts) && (entity_id == USB_IN_FU_ID)) ||
+ (FUOUT_EN(opts) && (entity_id == USB_OUT_FU_ID))) {
+ memcpy(&uac2->setup_cr, cr, sizeof(*cr));
+ req->context = agdev;
+ req->complete = out_rq_cur_complete;
+ return w_length;
+ } else {
+ dev_err(&agdev->gadget->dev,
+ "%s:%d entity_id=%d control_selector=%d TODO!\n",
+ __func__, __LINE__, entity_id, control_selector);
+ }
return -EOPNOTSUPP;
}
@@ -1228,7 +1706,15 @@ static struct configfs_item_operations f_uac2_item_ops = {
.release = f_uac2_attr_release,
};
-#define UAC2_ATTRIBUTE(name) \
+#define uac2_kstrtou32 kstrtou32
+#define uac2_kstrtos16 kstrtos16
+#define uac2_kstrtobool(s, base, res) kstrtobool((s), (res))
+
+static const char *u32_fmt = "%u\n";
+static const char *s16_fmt = "%hd\n";
+static const char *bool_fmt = "%u\n";
+
+#define UAC2_ATTRIBUTE(type, name) \
static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
@@ -1236,7 +1722,7 @@ static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \
int result; \
\
mutex_lock(&opts->lock); \
- result = sprintf(page, "%u\n", opts->name); \
+ result = sprintf(page, type##_fmt, opts->name); \
mutex_unlock(&opts->lock); \
\
return result; \
@@ -1247,7 +1733,7 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
{ \
struct f_uac2_opts *opts = to_f_uac2_opts(item); \
int ret; \
- u32 num; \
+ type num; \
\
mutex_lock(&opts->lock); \
if (opts->refcnt) { \
@@ -1255,7 +1741,7 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
goto end; \
} \
\
- ret = kstrtou32(page, 0, &num); \
+ ret = uac2_kstrto##type(page, 0, &num); \
if (ret) \
goto end; \
\
@@ -1325,15 +1811,27 @@ end: \
\
CONFIGFS_ATTR(f_uac2_opts_, name)
-UAC2_ATTRIBUTE(p_chmask);
-UAC2_ATTRIBUTE(p_srate);
-UAC2_ATTRIBUTE(p_ssize);
-UAC2_ATTRIBUTE(c_chmask);
-UAC2_ATTRIBUTE(c_srate);
+UAC2_ATTRIBUTE(u32, p_chmask);
+UAC2_ATTRIBUTE(u32, p_srate);
+UAC2_ATTRIBUTE(u32, p_ssize);
+UAC2_ATTRIBUTE(u32, c_chmask);
+UAC2_ATTRIBUTE(u32, c_srate);
UAC2_ATTRIBUTE_SYNC(c_sync);
-UAC2_ATTRIBUTE(c_ssize);
-UAC2_ATTRIBUTE(req_number);
-UAC2_ATTRIBUTE(fb_max);
+UAC2_ATTRIBUTE(u32, c_ssize);
+UAC2_ATTRIBUTE(u32, req_number);
+
+UAC2_ATTRIBUTE(bool, p_mute_present);
+UAC2_ATTRIBUTE(bool, p_volume_present);
+UAC2_ATTRIBUTE(s16, p_volume_min);
+UAC2_ATTRIBUTE(s16, p_volume_max);
+UAC2_ATTRIBUTE(s16, p_volume_res);
+
+UAC2_ATTRIBUTE(bool, c_mute_present);
+UAC2_ATTRIBUTE(bool, c_volume_present);
+UAC2_ATTRIBUTE(s16, c_volume_min);
+UAC2_ATTRIBUTE(s16, c_volume_max);
+UAC2_ATTRIBUTE(s16, c_volume_res);
+UAC2_ATTRIBUTE(u32, fb_max);
static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_p_chmask,
@@ -1345,6 +1843,19 @@ static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_c_sync,
&f_uac2_opts_attr_req_number,
&f_uac2_opts_attr_fb_max,
+
+ &f_uac2_opts_attr_p_mute_present,
+ &f_uac2_opts_attr_p_volume_present,
+ &f_uac2_opts_attr_p_volume_min,
+ &f_uac2_opts_attr_p_volume_max,
+ &f_uac2_opts_attr_p_volume_res,
+
+ &f_uac2_opts_attr_c_mute_present,
+ &f_uac2_opts_attr_c_volume_present,
+ &f_uac2_opts_attr_c_volume_min,
+ &f_uac2_opts_attr_c_volume_max,
+ &f_uac2_opts_attr_c_volume_res,
+
NULL,
};
@@ -1383,6 +1894,19 @@ static struct usb_function_instance *afunc_alloc_inst(void)
opts->c_srate = UAC2_DEF_CSRATE;
opts->c_ssize = UAC2_DEF_CSSIZE;
opts->c_sync = UAC2_DEF_CSYNC;
+
+ opts->p_mute_present = UAC2_DEF_MUTE_PRESENT;
+ opts->p_volume_present = UAC2_DEF_VOLUME_PRESENT;
+ opts->p_volume_min = UAC2_DEF_MIN_DB;
+ opts->p_volume_max = UAC2_DEF_MAX_DB;
+ opts->p_volume_res = UAC2_DEF_RES_DB;
+
+ opts->c_mute_present = UAC2_DEF_MUTE_PRESENT;
+ opts->c_volume_present = UAC2_DEF_VOLUME_PRESENT;
+ opts->c_volume_min = UAC2_DEF_MIN_DB;
+ opts->c_volume_max = UAC2_DEF_MAX_DB;
+ opts->c_volume_res = UAC2_DEF_RES_DB;
+
opts->req_number = UAC2_DEF_REQ_NUM;
opts->fb_max = UAC2_DEF_FB_MAX;
return &opts->func_inst;
@@ -1409,6 +1933,11 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
usb_free_all_descriptors(f);
agdev->gadget = NULL;
+
+ kfree(out_feature_unit_desc);
+ out_feature_unit_desc = NULL;
+ kfree(in_feature_unit_desc);
+ in_feature_unit_desc = NULL;
}
static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
@@ -1441,3 +1970,4 @@ DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yadwinder Singh");
MODULE_AUTHOR("Jaswinder Singh");
+MODULE_AUTHOR("Ruslan Bilovol");
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index f48a00e49794..9d87c0fb8f92 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -418,6 +418,7 @@ uvc_register_video(struct uvc_device *uvc)
/* TODO reference counting. */
uvc->vdev.v4l2_dev = &uvc->v4l2_dev;
+ uvc->vdev.v4l2_dev->dev = &cdev->gadget->dev;
uvc->vdev.fops = &uvc_v4l2_fops;
uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops;
uvc->vdev.release = video_device_release_empty;
diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
index 9e5c950612d0..32ef22857083 100644
--- a/drivers/usb/gadget/function/u_audio.c
+++ b/drivers/usb/gadget/function/u_audio.c
@@ -12,11 +12,14 @@
* Jaswinder Singh (jaswinder.singh@linaro.org)
*/
+#include <linux/kernel.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/control.h>
+#include <sound/tlv.h>
+#include <linux/usb/audio.h>
#include "u_audio.h"
@@ -24,6 +27,12 @@
#define PRD_SIZE_MAX PAGE_SIZE
#define MIN_PERIODS 4
+enum {
+ UAC_FBACK_CTRL,
+ UAC_MUTE_CTRL,
+ UAC_VOLUME_CTRL,
+};
+
/* Runtime data params for one stream */
struct uac_rtd_params {
struct snd_uac_chip *uac; /* parent chip */
@@ -43,6 +52,17 @@ struct uac_rtd_params {
struct usb_request *req_fback; /* Feedback endpoint request */
bool fb_ep_enabled; /* if the ep is enabled */
+
+ /* Volume/Mute controls and their state */
+ int fu_id; /* Feature Unit ID */
+ struct snd_kcontrol *snd_kctl_volume;
+ struct snd_kcontrol *snd_kctl_mute;
+ s16 volume_min, volume_max, volume_res;
+ s16 volume;
+ int mute;
+
+ spinlock_t lock; /* lock for control transfers */
+
};
struct snd_uac_chip {
@@ -604,6 +624,103 @@ void u_audio_stop_playback(struct g_audio *audio_dev)
}
EXPORT_SYMBOL_GPL(u_audio_stop_playback);
+int u_audio_get_volume(struct g_audio *audio_dev, int playback, s16 *val)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+ struct uac_rtd_params *prm;
+ unsigned long flags;
+
+ if (playback)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ spin_lock_irqsave(&prm->lock, flags);
+ *val = prm->volume;
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(u_audio_get_volume);
+
+int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+ struct uac_rtd_params *prm;
+ unsigned long flags;
+ int change = 0;
+
+ if (playback)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ spin_lock_irqsave(&prm->lock, flags);
+ val = clamp(val, prm->volume_min, prm->volume_max);
+ if (prm->volume != val) {
+ prm->volume = val;
+ change = 1;
+ }
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ if (change)
+ snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &prm->snd_kctl_volume->id);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(u_audio_set_volume);
+
+int u_audio_get_mute(struct g_audio *audio_dev, int playback, int *val)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+ struct uac_rtd_params *prm;
+ unsigned long flags;
+
+ if (playback)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ spin_lock_irqsave(&prm->lock, flags);
+ *val = prm->mute;
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(u_audio_get_mute);
+
+int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+ struct uac_rtd_params *prm;
+ unsigned long flags;
+ int change = 0;
+ int mute;
+
+ if (playback)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ mute = val ? 1 : 0;
+
+ spin_lock_irqsave(&prm->lock, flags);
+ if (prm->mute != mute) {
+ prm->mute = mute;
+ change = 1;
+ }
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ if (change)
+ snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &prm->snd_kctl_mute->id);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(u_audio_set_mute);
+
+
static int u_audio_pitch_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -663,14 +780,158 @@ static int u_audio_pitch_put(struct snd_kcontrol *kcontrol,
return change;
}
-static const struct snd_kcontrol_new u_audio_controls[] = {
+static int u_audio_mute_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "Capture Pitch 1000000",
- .info = u_audio_pitch_info,
- .get = u_audio_pitch_get,
- .put = u_audio_pitch_put,
-},
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ uinfo->value.integer.step = 1;
+
+ return 0;
+}
+
+static int u_audio_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+
+ spin_lock_irqsave(&prm->lock, flags);
+ ucontrol->value.integer.value[0] = !prm->mute;
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ return 0;
+}
+
+static int u_audio_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
+ struct snd_uac_chip *uac = prm->uac;
+ struct g_audio *audio_dev = uac->audio_dev;
+ unsigned int val;
+ unsigned long flags;
+ int change = 0;
+
+ val = !ucontrol->value.integer.value[0];
+
+ spin_lock_irqsave(&prm->lock, flags);
+ if (val != prm->mute) {
+ prm->mute = val;
+ change = 1;
+ }
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ if (change && audio_dev->notify)
+ audio_dev->notify(audio_dev, prm->fu_id, UAC_FU_MUTE);
+
+ return change;
+}
+
+/*
+ * TLV callback for mixer volume controls
+ */
+static int u_audio_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *_tlv)
+{
+ struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
+ DECLARE_TLV_DB_MINMAX(scale, 0, 0);
+
+ if (size < sizeof(scale))
+ return -ENOMEM;
+
+ /* UAC volume resolution is 1/256 dB, TLV is 1/100 dB */
+ scale[2] = (prm->volume_min * 100) / 256;
+ scale[3] = (prm->volume_max * 100) / 256;
+ if (copy_to_user(_tlv, scale, sizeof(scale)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int u_audio_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max =
+ (prm->volume_max - prm->volume_min + prm->volume_res - 1)
+ / prm->volume_res;
+ uinfo->value.integer.step = 1;
+
+ return 0;
+}
+
+static int u_audio_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+
+ spin_lock_irqsave(&prm->lock, flags);
+ ucontrol->value.integer.value[0] =
+ (prm->volume - prm->volume_min) / prm->volume_res;
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ return 0;
+}
+
+static int u_audio_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol);
+ struct snd_uac_chip *uac = prm->uac;
+ struct g_audio *audio_dev = uac->audio_dev;
+ unsigned int val;
+ s16 volume;
+ unsigned long flags;
+ int change = 0;
+
+ val = ucontrol->value.integer.value[0];
+
+ spin_lock_irqsave(&prm->lock, flags);
+ volume = (val * prm->volume_res) + prm->volume_min;
+ volume = clamp(volume, prm->volume_min, prm->volume_max);
+ if (volume != prm->volume) {
+ prm->volume = volume;
+ change = 1;
+ }
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ if (change && audio_dev->notify)
+ audio_dev->notify(audio_dev, prm->fu_id, UAC_FU_VOLUME);
+
+ return change;
+}
+
+
+static struct snd_kcontrol_new u_audio_controls[] = {
+ [UAC_FBACK_CTRL] {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "Capture Pitch 1000000",
+ .info = u_audio_pitch_info,
+ .get = u_audio_pitch_get,
+ .put = u_audio_pitch_put,
+ },
+ [UAC_MUTE_CTRL] {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "", /* will be filled later */
+ .info = u_audio_mute_info,
+ .get = u_audio_mute_get,
+ .put = u_audio_mute_put,
+ },
+ [UAC_VOLUME_CTRL] {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "", /* will be filled later */
+ .info = u_audio_volume_info,
+ .get = u_audio_volume_get,
+ .put = u_audio_volume_put,
+ },
};
int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
@@ -682,7 +943,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
struct snd_kcontrol *kctl;
struct uac_params *params;
int p_chmask, c_chmask;
- int err;
+ int i, err;
if (!g_audio)
return -EINVAL;
@@ -700,7 +961,8 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
if (c_chmask) {
struct uac_rtd_params *prm = &uac->c_prm;
- uac->c_prm.uac = uac;
+ spin_lock_init(&prm->lock);
+ uac->c_prm.uac = uac;
prm->max_psize = g_audio->out_ep_maxpsize;
prm->reqs = kcalloc(params->req_number,
@@ -723,6 +985,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
if (p_chmask) {
struct uac_rtd_params *prm = &uac->p_prm;
+ spin_lock_init(&prm->lock);
uac->p_prm.uac = uac;
prm->max_psize = g_audio->in_ep_maxpsize;
@@ -767,10 +1030,18 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops);
- if (c_chmask && g_audio->in_ep_fback) {
+ /*
+ * Create mixer and controls
+ * Create only if it's required on USB side
+ */
+ if ((c_chmask && g_audio->in_ep_fback)
+ || (p_chmask && params->p_fu.id)
+ || (c_chmask && params->c_fu.id))
strscpy(card->mixername, card_name, sizeof(card->driver));
- kctl = snd_ctl_new1(&u_audio_controls[0], &uac->c_prm);
+ if (c_chmask && g_audio->in_ep_fback) {
+ kctl = snd_ctl_new1(&u_audio_controls[UAC_FBACK_CTRL],
+ &uac->c_prm);
if (!kctl) {
err = -ENOMEM;
goto snd_fail;
@@ -784,6 +1055,82 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
goto snd_fail;
}
+ for (i = 0; i <= SNDRV_PCM_STREAM_LAST; i++) {
+ struct uac_rtd_params *prm;
+ struct uac_fu_params *fu;
+ char ctrl_name[24];
+ char *direction;
+
+ if (!pcm->streams[i].substream_count)
+ continue;
+
+ if (i == SNDRV_PCM_STREAM_PLAYBACK) {
+ prm = &uac->p_prm;
+ fu = &params->p_fu;
+ direction = "Playback";
+ } else {
+ prm = &uac->c_prm;
+ fu = &params->c_fu;
+ direction = "Capture";
+ }
+
+ prm->fu_id = fu->id;
+
+ if (fu->mute_present) {
+ snprintf(ctrl_name, sizeof(ctrl_name),
+ "PCM %s Switch", direction);
+
+ u_audio_controls[UAC_MUTE_CTRL].name = ctrl_name;
+
+ kctl = snd_ctl_new1(&u_audio_controls[UAC_MUTE_CTRL],
+ prm);
+ if (!kctl) {
+ err = -ENOMEM;
+ goto snd_fail;
+ }
+
+ kctl->id.device = pcm->device;
+ kctl->id.subdevice = i;
+
+ err = snd_ctl_add(card, kctl);
+ if (err < 0)
+ goto snd_fail;
+ prm->snd_kctl_mute = kctl;
+ prm->mute = 0;
+ }
+
+ if (fu->volume_present) {
+ snprintf(ctrl_name, sizeof(ctrl_name),
+ "PCM %s Volume", direction);
+
+ u_audio_controls[UAC_VOLUME_CTRL].name = ctrl_name;
+
+ kctl = snd_ctl_new1(&u_audio_controls[UAC_VOLUME_CTRL],
+ prm);
+ if (!kctl) {
+ err = -ENOMEM;
+ goto snd_fail;
+ }
+
+ kctl->id.device = pcm->device;
+ kctl->id.subdevice = i;
+
+
+ kctl->tlv.c = u_audio_volume_tlv;
+ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+
+ err = snd_ctl_add(card, kctl);
+ if (err < 0)
+ goto snd_fail;
+ prm->snd_kctl_volume = kctl;
+ prm->volume = fu->volume_max;
+ prm->volume_max = fu->volume_max;
+ prm->volume_min = fu->volume_min;
+ prm->volume_res = fu->volume_res;
+ }
+ }
+
strscpy(card->driver, card_name, sizeof(card->driver));
strscpy(card->shortname, card_name, sizeof(card->shortname));
sprintf(card->longname, "%s %i", card_name, card->dev->id);
diff --git a/drivers/usb/gadget/function/u_audio.h b/drivers/usb/gadget/function/u_audio.h
index a218cdf771fe..001a79a46022 100644
--- a/drivers/usb/gadget/function/u_audio.h
+++ b/drivers/usb/gadget/function/u_audio.h
@@ -19,16 +19,30 @@
*/
#define FBACK_SLOW_MAX 250
+/* Feature Unit parameters */
+struct uac_fu_params {
+ int id; /* Feature Unit ID */
+
+ bool mute_present; /* mute control enable */
+
+ bool volume_present; /* volume control enable */
+ s16 volume_min; /* min volume in 1/256 dB */
+ s16 volume_max; /* max volume in 1/256 dB */
+ s16 volume_res; /* volume resolution in 1/256 dB */
+};
+
struct uac_params {
/* playback */
int p_chmask; /* channel mask */
int p_srate; /* rate in Hz */
int p_ssize; /* sample size */
+ struct uac_fu_params p_fu; /* Feature Unit parameters */
/* capture */
int c_chmask; /* channel mask */
int c_srate; /* rate in Hz */
int c_ssize; /* sample size */
+ struct uac_fu_params c_fu; /* Feature Unit parameters */
int req_number; /* number of preallocated requests */
int fb_max; /* upper frequency drift feedback limit per-mil */
@@ -49,6 +63,9 @@ struct g_audio {
/* Max packet size for all out_ep possible speeds */
unsigned int out_ep_maxpsize;
+ /* Notify UAC driver about control change */
+ int (*notify)(struct g_audio *g_audio, int unit_id, int cs);
+
/* The ALSA Sound Card it represents on the USB-Client side */
struct snd_uac_chip *uac;
@@ -94,4 +111,9 @@ void u_audio_stop_capture(struct g_audio *g_audio);
int u_audio_start_playback(struct g_audio *g_audio);
void u_audio_stop_playback(struct g_audio *g_audio);
+int u_audio_get_volume(struct g_audio *g_audio, int playback, s16 *val);
+int u_audio_set_volume(struct g_audio *g_audio, int playback, s16 val);
+int u_audio_get_mute(struct g_audio *g_audio, int playback, int *val);
+int u_audio_set_mute(struct g_audio *g_audio, int playback, int val);
+
#endif /* __U_AUDIO_H */
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index d1d044d9f859..85a3f6d4b5af 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -492,8 +492,9 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
}
spin_unlock_irqrestore(&dev->lock, flags);
- if (skb && !in) {
- dev_kfree_skb_any(skb);
+ if (!in) {
+ if (skb)
+ dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
diff --git a/drivers/usb/gadget/function/u_hid.h b/drivers/usb/gadget/function/u_hid.h
index 98d6af558c03..84bb70292855 100644
--- a/drivers/usb/gadget/function/u_hid.h
+++ b/drivers/usb/gadget/function/u_hid.h
@@ -20,6 +20,7 @@ struct f_hid_opts {
int minor;
unsigned char subclass;
unsigned char protocol;
+ unsigned char no_out_endpoint;
unsigned short report_length;
unsigned short report_desc_length;
unsigned char *report_desc;
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index 281ca766698a..6f68cbeeee7c 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -1445,51 +1445,53 @@ EXPORT_SYMBOL_GPL(gserial_resume);
static int userial_init(void)
{
+ struct tty_driver *driver;
unsigned i;
int status;
- gs_tty_driver = alloc_tty_driver(MAX_U_SERIAL_PORTS);
- if (!gs_tty_driver)
- return -ENOMEM;
+ driver = tty_alloc_driver(MAX_U_SERIAL_PORTS, TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(driver))
+ return PTR_ERR(driver);
- gs_tty_driver->driver_name = "g_serial";
- gs_tty_driver->name = "ttyGS";
+ driver->driver_name = "g_serial";
+ driver->name = "ttyGS";
/* uses dynamically assigned dev_t values */
- gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
- gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- gs_tty_driver->init_termios = tty_std_termios;
+ driver->type = TTY_DRIVER_TYPE_SERIAL;
+ driver->subtype = SERIAL_TYPE_NORMAL;
+ driver->init_termios = tty_std_termios;
/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
* MS-Windows. Otherwise, most of these flags shouldn't affect
* anything unless we were to actually hook up to a serial line.
*/
- gs_tty_driver->init_termios.c_cflag =
+ driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- gs_tty_driver->init_termios.c_ispeed = 9600;
- gs_tty_driver->init_termios.c_ospeed = 9600;
+ driver->init_termios.c_ispeed = 9600;
+ driver->init_termios.c_ospeed = 9600;
- tty_set_operations(gs_tty_driver, &gs_tty_ops);
+ tty_set_operations(driver, &gs_tty_ops);
for (i = 0; i < MAX_U_SERIAL_PORTS; i++)
mutex_init(&ports[i].lock);
/* export the driver ... */
- status = tty_register_driver(gs_tty_driver);
+ status = tty_register_driver(driver);
if (status) {
pr_err("%s: cannot register, err %d\n",
__func__, status);
goto fail;
}
+ gs_tty_driver = driver;
+
pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
MAX_U_SERIAL_PORTS,
(MAX_U_SERIAL_PORTS == 1) ? "" : "s");
return status;
fail:
- put_tty_driver(gs_tty_driver);
- gs_tty_driver = NULL;
+ tty_driver_kref_put(driver);
return status;
}
module_init(userial_init);
@@ -1497,7 +1499,7 @@ module_init(userial_init);
static void userial_cleanup(void)
{
tty_unregister_driver(gs_tty_driver);
- put_tty_driver(gs_tty_driver);
+ tty_driver_kref_put(gs_tty_driver);
gs_tty_driver = NULL;
}
module_exit(userial_cleanup);
diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h
index 39c0e29e1b46..589fae861141 100644
--- a/drivers/usb/gadget/function/u_uac1.h
+++ b/drivers/usb/gadget/function/u_uac1.h
@@ -18,6 +18,13 @@
#define UAC1_DEF_PSRATE 48000
#define UAC1_DEF_PSSIZE 2
#define UAC1_DEF_REQ_NUM 2
+#define UAC1_DEF_INT_REQ_NUM 10
+
+#define UAC1_DEF_MUTE_PRESENT 1
+#define UAC1_DEF_VOLUME_PRESENT 1
+#define UAC1_DEF_MIN_DB (-100*256) /* -100 dB */
+#define UAC1_DEF_MAX_DB 0 /* 0 dB */
+#define UAC1_DEF_RES_DB (1*256) /* 1 dB */
struct f_uac1_opts {
@@ -28,6 +35,19 @@ struct f_uac1_opts {
int p_chmask;
int p_srate;
int p_ssize;
+
+ bool p_mute_present;
+ bool p_volume_present;
+ s16 p_volume_min;
+ s16 p_volume_max;
+ s16 p_volume_res;
+
+ bool c_mute_present;
+ bool c_volume_present;
+ s16 c_volume_min;
+ s16 c_volume_max;
+ s16 c_volume_res;
+
int req_number;
unsigned bound:1;
diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h
index 179d3ef6a195..a73b35774c44 100644
--- a/drivers/usb/gadget/function/u_uac2.h
+++ b/drivers/usb/gadget/function/u_uac2.h
@@ -22,8 +22,16 @@
#define UAC2_DEF_CSRATE 64000
#define UAC2_DEF_CSSIZE 2
#define UAC2_DEF_CSYNC USB_ENDPOINT_SYNC_ASYNC
+
+#define UAC2_DEF_MUTE_PRESENT 1
+#define UAC2_DEF_VOLUME_PRESENT 1
+#define UAC2_DEF_MIN_DB (-100*256) /* -100 dB */
+#define UAC2_DEF_MAX_DB 0 /* 0 dB */
+#define UAC2_DEF_RES_DB (1*256) /* 1 dB */
+
#define UAC2_DEF_REQ_NUM 2
#define UAC2_DEF_FB_MAX 5
+#define UAC2_DEF_INT_REQ_NUM 10
struct f_uac2_opts {
struct usb_function_instance func_inst;
@@ -34,9 +42,22 @@ struct f_uac2_opts {
int c_srate;
int c_ssize;
int c_sync;
+
+ bool p_mute_present;
+ bool p_volume_present;
+ s16 p_volume_min;
+ s16 p_volume_max;
+ s16 p_volume_res;
+
+ bool c_mute_present;
+ bool c_volume_present;
+ s16 c_volume_min;
+ s16 c_volume_max;
+ s16 c_volume_res;
+
int req_number;
int fb_max;
- bool bound;
+ bool bound;
struct mutex lock;
int refcnt;
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index 23ee25383c1f..255a61bd6a6a 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -65,13 +65,19 @@ extern unsigned int uvc_gadget_trace_param;
* Driver specific constants
*/
-#define UVC_NUM_REQUESTS 4
#define UVC_MAX_REQUEST_SIZE 64
#define UVC_MAX_EVENTS 4
/* ------------------------------------------------------------------------
* Structures
*/
+struct uvc_request {
+ struct usb_request *req;
+ u8 *req_buffer;
+ struct uvc_video *video;
+ struct sg_table sgt;
+ u8 header[2];
+};
struct uvc_video {
struct uvc_device *uvc;
@@ -87,13 +93,16 @@ struct uvc_video {
unsigned int imagesize;
struct mutex mutex; /* protects frame parameters */
+ unsigned int uvc_num_requests;
+
/* Requests */
unsigned int req_size;
- struct usb_request *req[UVC_NUM_REQUESTS];
- __u8 *req_buffer[UVC_NUM_REQUESTS];
+ struct uvc_request *ureq;
struct list_head req_free;
spinlock_t req_lock;
+ unsigned int req_int_count;
+
void (*encode) (struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf);
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index 61e2c94cc0b0..7d00ad7c154c 100644
--- a/drivers/usb/gadget/function/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -17,6 +17,7 @@
#include <linux/wait.h>
#include <media/v4l2-common.h>
+#include <media/videobuf2-dma-sg.h>
#include <media/videobuf2-vmalloc.h>
#include "uvc.h"
@@ -43,6 +44,7 @@ static int uvc_queue_setup(struct vb2_queue *vq,
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
struct uvc_video *video = container_of(queue, struct uvc_video, queue);
+ struct usb_composite_dev *cdev = video->uvc->func.config->cdev;
if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
*nbuffers = UVC_MAX_VIDEO_BUFFERS;
@@ -51,6 +53,11 @@ static int uvc_queue_setup(struct vb2_queue *vq,
sizes[0] = video->imagesize;
+ if (cdev->gadget->speed < USB_SPEED_SUPER)
+ video->uvc_num_requests = 4;
+ else
+ video->uvc_num_requests = 64;
+
return 0;
}
@@ -70,7 +77,12 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
return -ENODEV;
buf->state = UVC_BUF_STATE_QUEUED;
- buf->mem = vb2_plane_vaddr(vb, 0);
+ if (queue->use_sg) {
+ buf->sgt = vb2_dma_sg_plane_desc(vb, 0);
+ buf->sg = buf->sgt->sgl;
+ } else {
+ buf->mem = vb2_plane_vaddr(vb, 0);
+ }
buf->length = vb2_plane_size(vb, 0);
if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->bytesused = 0;
@@ -110,9 +122,11 @@ static const struct vb2_ops uvc_queue_qops = {
.wait_finish = vb2_ops_wait_finish,
};
-int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+int uvcg_queue_init(struct uvc_video_queue *queue, struct device *dev, enum v4l2_buf_type type,
struct mutex *lock)
{
+ struct uvc_video *video = container_of(queue, struct uvc_video, queue);
+ struct usb_composite_dev *cdev = video->uvc->func.config->cdev;
int ret;
queue->queue.type = type;
@@ -121,9 +135,17 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
queue->queue.ops = &uvc_queue_qops;
queue->queue.lock = lock;
- queue->queue.mem_ops = &vb2_vmalloc_memops;
+ if (cdev->gadget->sg_supported) {
+ queue->queue.mem_ops = &vb2_dma_sg_memops;
+ queue->use_sg = 1;
+ } else {
+ queue->queue.mem_ops = &vb2_vmalloc_memops;
+ }
+
queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
| V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
+ queue->queue.dev = dev;
+
ret = vb2_queue_init(&queue->queue);
if (ret)
return ret;
diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
index 2f0fff769843..05360a0767f6 100644
--- a/drivers/usb/gadget/function/uvc_queue.h
+++ b/drivers/usb/gadget/function/uvc_queue.h
@@ -34,6 +34,9 @@ struct uvc_buffer {
enum uvc_buffer_state state;
void *mem;
+ struct sg_table *sgt;
+ struct scatterlist *sg;
+ unsigned int offset;
unsigned int length;
unsigned int bytesused;
};
@@ -50,6 +53,8 @@ struct uvc_video_queue {
unsigned int buf_used;
+ bool use_sg;
+
spinlock_t irqlock; /* Protects flags and irqqueue */
struct list_head irqqueue;
};
@@ -59,7 +64,7 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
return vb2_is_streaming(&queue->queue);
}
-int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+int uvcg_queue_init(struct uvc_video_queue *queue, struct device *dev, enum v4l2_buf_type type,
struct mutex *lock);
void uvcg_free_buffers(struct uvc_video_queue *queue);
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index 633e23d58d86..b4a763e5f70e 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -27,10 +27,10 @@ static int
uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
u8 *data, int len)
{
- data[0] = 2;
+ data[0] = UVCG_REQUEST_HEADER_LEN;
data[1] = UVC_STREAM_EOH | video->fid;
- if (buf->bytesused - video->queue.buf_used <= len - 2)
+ if (buf->bytesused - video->queue.buf_used <= len - UVCG_REQUEST_HEADER_LEN)
data[1] |= UVC_STREAM_EOF;
return 2;
@@ -95,6 +95,71 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
}
static void
+uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
+ struct uvc_buffer *buf)
+{
+ unsigned int pending = buf->bytesused - video->queue.buf_used;
+ struct uvc_request *ureq = req->context;
+ struct scatterlist *sg, *iter;
+ unsigned int len = video->req_size;
+ unsigned int sg_left, part = 0;
+ unsigned int i;
+ int ret;
+
+ sg = ureq->sgt.sgl;
+ sg_init_table(sg, ureq->sgt.nents);
+
+ /* Init the header. */
+ ret = uvc_video_encode_header(video, buf, ureq->header,
+ video->req_size);
+ sg_set_buf(sg, ureq->header, UVCG_REQUEST_HEADER_LEN);
+ len -= ret;
+
+ if (pending <= len)
+ len = pending;
+
+ req->length = (len == pending) ?
+ len + UVCG_REQUEST_HEADER_LEN : video->req_size;
+
+ /* Init the pending sgs with payload */
+ sg = sg_next(sg);
+
+ for_each_sg(sg, iter, ureq->sgt.nents - 1, i) {
+ if (!len || !buf->sg)
+ break;
+
+ sg_left = sg_dma_len(buf->sg) - buf->offset;
+ part = min_t(unsigned int, len, sg_left);
+
+ sg_set_page(iter, sg_page(buf->sg), part, buf->offset);
+
+ if (part == sg_left) {
+ buf->offset = 0;
+ buf->sg = sg_next(buf->sg);
+ } else {
+ buf->offset += part;
+ }
+ len -= part;
+ }
+
+ /* Assign the video data with header. */
+ req->buf = NULL;
+ req->sg = ureq->sgt.sgl;
+ req->num_sgs = i + 1;
+
+ req->length -= len;
+ video->queue.buf_used += req->length - UVCG_REQUEST_HEADER_LEN;
+
+ if (buf->bytesused == video->queue.buf_used || !buf->sg) {
+ video->queue.buf_used = 0;
+ buf->state = UVC_BUF_STATE_DONE;
+ buf->offset = 0;
+ uvcg_queue_next_buffer(&video->queue, buf);
+ video->fid ^= UVC_STREAM_FID;
+ }
+}
+
+static void
uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf)
{
@@ -145,7 +210,8 @@ static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req)
static void
uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
{
- struct uvc_video *video = req->context;
+ struct uvc_request *ureq = req->context;
+ struct uvc_video *video = ureq->video;
struct uvc_video_queue *queue = &video->queue;
unsigned long flags;
@@ -177,16 +243,23 @@ uvc_video_free_requests(struct uvc_video *video)
{
unsigned int i;
- for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
- if (video->req[i]) {
- usb_ep_free_request(video->ep, video->req[i]);
- video->req[i] = NULL;
- }
+ if (video->ureq) {
+ for (i = 0; i < video->uvc_num_requests; ++i) {
+ sg_free_table(&video->ureq[i].sgt);
+
+ if (video->ureq[i].req) {
+ usb_ep_free_request(video->ep, video->ureq[i].req);
+ video->ureq[i].req = NULL;
+ }
- if (video->req_buffer[i]) {
- kfree(video->req_buffer[i]);
- video->req_buffer[i] = NULL;
+ if (video->ureq[i].req_buffer) {
+ kfree(video->ureq[i].req_buffer);
+ video->ureq[i].req_buffer = NULL;
+ }
}
+
+ kfree(video->ureq);
+ video->ureq = NULL;
}
INIT_LIST_HEAD(&video->req_free);
@@ -207,21 +280,30 @@ uvc_video_alloc_requests(struct uvc_video *video)
* max_t(unsigned int, video->ep->maxburst, 1)
* (video->ep->mult);
- for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
- video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
- if (video->req_buffer[i] == NULL)
- goto error;
+ video->ureq = kcalloc(video->uvc_num_requests, sizeof(struct uvc_request), GFP_KERNEL);
+ if (video->ureq == NULL)
+ return -ENOMEM;
- video->req[i] = usb_ep_alloc_request(video->ep, GFP_KERNEL);
- if (video->req[i] == NULL)
+ for (i = 0; i < video->uvc_num_requests; ++i) {
+ video->ureq[i].req_buffer = kmalloc(req_size, GFP_KERNEL);
+ if (video->ureq[i].req_buffer == NULL)
goto error;
- video->req[i]->buf = video->req_buffer[i];
- video->req[i]->length = 0;
- video->req[i]->complete = uvc_video_complete;
- video->req[i]->context = video;
+ video->ureq[i].req = usb_ep_alloc_request(video->ep, GFP_KERNEL);
+ if (video->ureq[i].req == NULL)
+ goto error;
- list_add_tail(&video->req[i]->list, &video->req_free);
+ video->ureq[i].req->buf = video->ureq[i].req_buffer;
+ video->ureq[i].req->length = 0;
+ video->ureq[i].req->complete = uvc_video_complete;
+ video->ureq[i].req->context = &video->ureq[i];
+ video->ureq[i].video = video;
+
+ list_add_tail(&video->ureq[i].req->list, &video->req_free);
+ /* req_size/PAGE_SIZE + 1 for overruns and + 1 for header */
+ sg_alloc_table(&video->ureq[i].sgt,
+ DIV_ROUND_UP(req_size - 2, PAGE_SIZE) + 2,
+ GFP_KERNEL);
}
video->req_size = req_size;
@@ -278,6 +360,19 @@ static void uvcg_video_pump(struct work_struct *work)
video->encode(req, video, buf);
+ /* With usb3 we have more requests. This will decrease the
+ * interrupt load to a quarter but also catches the corner
+ * cases, which needs to be handled */
+ if (list_empty(&video->req_free) ||
+ buf->state == UVC_BUF_STATE_DONE ||
+ !(video->req_int_count %
+ DIV_ROUND_UP(video->uvc_num_requests, 4))) {
+ video->req_int_count = 0;
+ req->no_interrupt = 0;
+ } else {
+ req->no_interrupt = 1;
+ }
+
/* Queue the USB request */
ret = uvcg_video_ep_queue(video, req);
spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -286,6 +381,7 @@ static void uvcg_video_pump(struct work_struct *work)
uvcg_queue_cancel(queue, 0);
break;
}
+ video->req_int_count++;
}
spin_lock_irqsave(&video->req_lock, flags);
@@ -312,9 +408,9 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
cancel_work_sync(&video->pump);
uvcg_queue_cancel(&video->queue, 0);
- for (i = 0; i < UVC_NUM_REQUESTS; ++i)
- if (video->req[i])
- usb_ep_dequeue(video->ep, video->req[i]);
+ for (i = 0; i < video->uvc_num_requests; ++i)
+ if (video->ureq && video->ureq[i].req)
+ usb_ep_dequeue(video->ep, video->ureq[i].req);
uvc_video_free_requests(video);
uvcg_queue_enable(&video->queue, 0);
@@ -331,7 +427,10 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
video->encode = uvc_video_encode_bulk;
video->payload_size = 0;
} else
- video->encode = uvc_video_encode_isoc;
+ video->encode = video->queue.use_sg ?
+ uvc_video_encode_isoc_sg : uvc_video_encode_isoc;
+
+ video->req_int_count = 0;
schedule_work(&video->pump);
@@ -355,8 +454,8 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
video->imagesize = 320 * 240 * 2;
/* Initialize the video buffers queue. */
- uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT,
- &video->mutex);
+ uvcg_queue_init(&video->queue, uvc->v4l2_dev.dev->parent,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT, &video->mutex);
return 0;
}
diff --git a/drivers/usb/gadget/function/uvc_video.h b/drivers/usb/gadget/function/uvc_video.h
index 03adeefa343b..9bf19475f6f9 100644
--- a/drivers/usb/gadget/function/uvc_video.h
+++ b/drivers/usb/gadget/function/uvc_video.h
@@ -12,6 +12,8 @@
#ifndef __UVC_VIDEO_H__
#define __UVC_VIDEO_H__
+#define UVCG_REQUEST_HEADER_LEN 2
+
struct uvc_video;
int uvcg_video_enable(struct uvc_video *video, int enable);
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
index 11dd6e8adc8a..de6668e58481 100644
--- a/drivers/usb/gadget/legacy/Kconfig
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -502,6 +502,7 @@ config USB_G_WEBCAM
tristate "USB Webcam Gadget"
depends on VIDEO_V4L2
select USB_LIBCOMPOSITE
+ select VIDEOBUF2_DMA_SG
select VIDEOBUF2_VMALLOC
select USB_F_UVC
help
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index cd8e2737947b..539220d7f5b6 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -1214,8 +1214,8 @@ dev_release (struct inode *inode, struct file *fd)
static __poll_t
ep0_poll (struct file *fd, poll_table *wait)
{
- struct dev_data *dev = fd->private_data;
- __poll_t mask = 0;
+ struct dev_data *dev = fd->private_data;
+ __poll_t mask = 0;
if (dev->state <= STATE_DEV_OPENED)
return DEFAULT_POLLMASK;
diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c
index 2cd389575084..ed762ba9b629 100644
--- a/drivers/usb/gadget/legacy/printer.c
+++ b/drivers/usb/gadget/legacy/printer.c
@@ -50,6 +50,7 @@ MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;");
/* Number of requests to allocate per endpoint, not used for ep0. */
static unsigned qlen = 10;
module_param(qlen, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(qlen, "The number of 8k buffers to use per endpoint");
#define QLEN qlen
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c
index d11d3d14313f..7a635c499777 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/core.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c
@@ -5,11 +5,6 @@
* core.c - Top level support
*
* Copyright 2017 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/kernel.h>
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
index d268306a7bfe..d918e8b2af3c 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
@@ -5,11 +5,6 @@
* dev.c - Individual device/gadget management (ie, a port = a gadget)
*
* Copyright 2017 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/kernel.h>
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
index 022b777b85f8..74ea36c19b1e 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
@@ -5,11 +5,6 @@
* ep0.c - Endpoint 0 handling
*
* Copyright 2017 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/kernel.h>
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c
index cb164c615e6f..917892ca8753 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c
@@ -5,11 +5,6 @@
* epn.c - Generic endpoints management
*
* Copyright 2017 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/kernel.h>
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c
index 5c7dea5e0ff1..b9960fdd8a51 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c
@@ -5,11 +5,6 @@
* hub.c - virtual hub handling
*
* Copyright 2017 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/kernel.h>
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
index eede5cedacb4..d9ad9adf7348 100644
--- a/drivers/usb/gadget/udc/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
@@ -1876,7 +1876,9 @@ static int at91udc_probe(struct platform_device *pdev)
clk_disable(udc->iclk);
/* request UDC and maybe VBUS irqs */
- udc->udp_irq = platform_get_irq(pdev, 0);
+ udc->udp_irq = retval = platform_get_irq(pdev, 0);
+ if (retval < 0)
+ goto err_unprepare_iclk;
retval = devm_request_irq(dev, udc->udp_irq, at91_udc_irq, 0,
driver_name, udc);
if (retval) {
diff --git a/drivers/usb/gadget/udc/bdc/bdc_cmd.c b/drivers/usb/gadget/udc/bdc/bdc_cmd.c
index 995f79c79f96..67887316a1a6 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_cmd.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_cmd.c
@@ -153,7 +153,6 @@ int bdc_config_ep(struct bdc *bdc, struct bdc_ep *ep)
si = clamp_val(si, 1, 16) - 1;
mps = usb_endpoint_maxp(desc);
- mps &= 0x7ff;
param2 |= mps << MP_SHIFT;
param2 |= usb_endpoint_type(desc) << EPT_SHIFT;
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c
index 0bef6b3f049b..fa1a3908ec3b 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -488,27 +488,14 @@ static int bdc_probe(struct platform_device *pdev)
int irq;
u32 temp;
struct device *dev = &pdev->dev;
- struct clk *clk;
int phy_num;
dev_dbg(dev, "%s()\n", __func__);
- clk = devm_clk_get_optional(dev, "sw_usbd");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- dev_err(dev, "could not enable clock\n");
- return ret;
- }
-
bdc = devm_kzalloc(dev, sizeof(*bdc), GFP_KERNEL);
if (!bdc)
return -ENOMEM;
- bdc->clk = clk;
-
bdc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bdc->regs))
return PTR_ERR(bdc->regs);
@@ -545,10 +532,20 @@ static int bdc_probe(struct platform_device *pdev)
}
}
+ bdc->clk = devm_clk_get_optional(dev, "sw_usbd");
+ if (IS_ERR(bdc->clk))
+ return PTR_ERR(bdc->clk);
+
+ ret = clk_prepare_enable(bdc->clk);
+ if (ret) {
+ dev_err(dev, "could not enable clock\n");
+ return ret;
+ }
+
ret = bdc_phy_init(bdc);
if (ret) {
dev_err(bdc->dev, "BDC phy init failure:%d\n", ret);
- return ret;
+ goto disable_clk;
}
temp = bdc_readl(bdc->regs, BDC_BDCCAP1);
@@ -560,7 +557,8 @@ static int bdc_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev,
"No suitable DMA config available, abort\n");
- return -ENOTSUPP;
+ ret = -ENOTSUPP;
+ goto phycleanup;
}
dev_dbg(dev, "Using 32-bit address\n");
}
@@ -580,6 +578,8 @@ cleanup:
bdc_hw_exit(bdc);
phycleanup:
bdc_phy_exit(bdc);
+disable_clk:
+ clk_disable_unprepare(bdc->clk);
return ret;
}
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index b7f0b1ebaaa8..14fdf918ecfe 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -1003,6 +1003,25 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
}
EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
+/**
+ * usb_gadget_check_config - checks if the UDC can support the binded
+ * configuration
+ * @gadget: controller to check the USB configuration
+ *
+ * Ensure that a UDC is able to support the requested resources by a
+ * configuration, and that there are no resource limitations, such as
+ * internal memory allocated to all requested endpoints.
+ *
+ * Returns zero on success, else a negative errno.
+ */
+int usb_gadget_check_config(struct usb_gadget *gadget)
+{
+ if (gadget->ops->check_config)
+ return gadget->ops->check_config(gadget);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_check_config);
+
/* ------------------------------------------------------------------------- */
static void usb_gadget_state_work(struct work_struct *work)
diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c
index ce3d7a3eb7e3..a1057ddfbda3 100644
--- a/drivers/usb/gadget/udc/mv_u3d_core.c
+++ b/drivers/usb/gadget/udc/mv_u3d_core.c
@@ -1921,14 +1921,6 @@ static int mv_u3d_probe(struct platform_device *dev)
goto err_get_irq;
}
u3d->irq = r->start;
- if (request_irq(u3d->irq, mv_u3d_irq,
- IRQF_SHARED, driver_name, u3d)) {
- u3d->irq = 0;
- dev_err(&dev->dev, "Request irq %d for u3d failed\n",
- u3d->irq);
- retval = -ENODEV;
- goto err_request_irq;
- }
/* initialize gadget structure */
u3d->gadget.ops = &mv_u3d_ops; /* usb_gadget_ops */
@@ -1941,6 +1933,15 @@ static int mv_u3d_probe(struct platform_device *dev)
mv_u3d_eps_init(u3d);
+ if (request_irq(u3d->irq, mv_u3d_irq,
+ IRQF_SHARED, driver_name, u3d)) {
+ u3d->irq = 0;
+ dev_err(&dev->dev, "Request irq %d for u3d failed\n",
+ u3d->irq);
+ retval = -ENODEV;
+ goto err_request_irq;
+ }
+
/* external vbus detection */
if (u3d->vbus) {
u3d->clock_gating = 1;
@@ -1964,8 +1965,8 @@ static int mv_u3d_probe(struct platform_device *dev)
err_unregister:
free_irq(u3d->irq, u3d);
-err_request_irq:
err_get_irq:
+err_request_irq:
kfree(u3d->status_req);
err_alloc_status_req:
kfree(u3d->eps);
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
index 69ef1e669d0c..a09ec1d826b2 100644
--- a/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -1093,7 +1093,7 @@ static void pxa25x_ep_fifo_flush(struct usb_ep *_ep)
}
-static struct usb_ep_ops pxa25x_ep_ops = {
+static const struct usb_ep_ops pxa25x_ep_ops = {
.enable = pxa25x_ep_enable,
.disable = pxa25x_ep_disable,
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index f1b35a39d1ba..57d417a7c3e0 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -2707,10 +2707,15 @@ static const struct renesas_usb3_priv renesas_usb3_priv_r8a77990 = {
static const struct of_device_id usb3_of_match[] = {
{
+ .compatible = "renesas,r8a774c0-usb3-peri",
+ .data = &renesas_usb3_priv_r8a77990,
+ }, {
.compatible = "renesas,r8a7795-usb3-peri",
.data = &renesas_usb3_priv_gen3,
- },
- {
+ }, {
+ .compatible = "renesas,r8a77990-usb3-peri",
+ .data = &renesas_usb3_priv_r8a77990,
+ }, {
.compatible = "renesas,rcar-gen3-usb3-peri",
.data = &renesas_usb3_priv_gen3,
},
@@ -2720,17 +2725,9 @@ MODULE_DEVICE_TABLE(of, usb3_of_match);
static const struct soc_device_attribute renesas_usb3_quirks_match[] = {
{
- .soc_id = "r8a774c0",
- .data = &renesas_usb3_priv_r8a77990,
- },
- {
.soc_id = "r8a7795", .revision = "ES1.*",
.data = &renesas_usb3_priv_r8a7795_es1,
},
- {
- .soc_id = "r8a77990",
- .data = &renesas_usb3_priv_r8a77990,
- },
{ /* sentinel */ },
};
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c
index 179777cb699f..e3931da24277 100644
--- a/drivers/usb/gadget/udc/s3c2410_udc.c
+++ b/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -1784,6 +1784,10 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
s3c2410_udc_reinit(udc);
irq_usbd = platform_get_irq(pdev, 0);
+ if (irq_usbd < 0) {
+ retval = irq_usbd;
+ goto err_udc_clk;
+ }
/* irq setup after old hardware state is cleaned up */
retval = request_irq(irq_usbd, s3c2410_udc_irq,
diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index c0ca7144e512..43f1b0d461c1 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -1610,7 +1610,7 @@ static void tegra_xudc_ep_context_setup(struct tegra_xudc_ep *ep)
u16 maxpacket, maxburst = 0, esit = 0;
u32 val;
- maxpacket = usb_endpoint_maxp(desc) & 0x7ff;
+ maxpacket = usb_endpoint_maxp(desc);
if (xudc->gadget.speed == USB_SPEED_SUPER) {
if (!usb_endpoint_xfer_control(desc))
maxburst = comp_desc->bMaxBurst;
@@ -1621,7 +1621,7 @@ static void tegra_xudc_ep_context_setup(struct tegra_xudc_ep *ep)
(usb_endpoint_xfer_int(desc) ||
usb_endpoint_xfer_isoc(desc))) {
if (xudc->gadget.speed == USB_SPEED_HIGH) {
- maxburst = (usb_endpoint_maxp(desc) >> 11) & 0x3;
+ maxburst = usb_endpoint_maxp_mult(desc) - 1;
if (maxburst == 0x3) {
dev_warn(xudc->dev,
"invalid endpoint maxburst\n");
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index df9428f1dc5e..c4736d1d020c 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -187,15 +187,6 @@ config USB_EHCI_PCI
depends on USB_PCI
default y
-config USB_EHCI_HCD_PMC_MSP
- tristate "EHCI support for on-chip PMC MSP71xx USB controller"
- depends on MSP_HAS_USB
- select USB_EHCI_BIG_ENDIAN_DESC
- select USB_EHCI_BIG_ENDIAN_MMIO
- help
- Enables support for the onchip USB controller on the PMC_MSP7100 Family SoC's.
- If unsure, say N.
-
config XPS_USB_HCD_XILINX
bool "Use Xilinx usb host EHCI controller core"
depends on (PPC32 || MICROBLAZE)
diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c
index 3e0ebe8cc649..d3626bfa966b 100644
--- a/drivers/usb/host/ehci-brcm.c
+++ b/drivers/usb/host/ehci-brcm.c
@@ -108,10 +108,9 @@ static int ehci_brcm_reset(struct usb_hcd *hcd)
/*
* SWLINUX-1705: Avoid OUT packet underflows during high memory
* bus usage
- * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00 @ 0x90
*/
- ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]);
- ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]);
+ ehci_writel(ehci, 0x00800040, &ehci->regs->brcm_insnreg[1]);
+ ehci_writel(ehci, 0x00000001, &ehci->regs->brcm_insnreg[3]);
return ehci_setup(hcd);
}
@@ -223,11 +222,9 @@ static int __maybe_unused ehci_brcm_resume(struct device *dev)
/*
* SWLINUX-1705: Avoid OUT packet underflows during high memory
* bus usage
- * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00
- * @ 0x90
*/
- ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]);
- ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]);
+ ehci_writel(ehci, 0x00800040, &ehci->regs->brcm_insnreg[1]);
+ ehci_writel(ehci, 0x00000001, &ehci->regs->brcm_insnreg[3]);
ehci_resume(hcd, false);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 10b0365f3439..6bdc6d6bf74d 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1296,11 +1296,6 @@ MODULE_LICENSE ("GPL");
#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
#endif
-#ifdef CONFIG_USB_EHCI_HCD_PMC_MSP
-#include "ehci-pmcmsp.c"
-#define PLATFORM_DRIVER ehci_hcd_msp_driver
-#endif
-
#ifdef CONFIG_SPARC_LEON
#include "ehci-grlib.c"
#define PLATFORM_DRIVER ehci_grlib_driver
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index cffdc8d01b2a..8fd27249ad25 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -42,26 +42,25 @@ struct ehci_hcd_mv {
int (*set_vbus)(unsigned int vbus);
};
-static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
+static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
{
- clk_prepare_enable(ehci_mv->clk);
-}
+ int retval;
-static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
-{
- clk_disable_unprepare(ehci_mv->clk);
-}
+ retval = clk_prepare_enable(ehci_mv->clk);
+ if (retval)
+ return retval;
-static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
-{
- ehci_clock_enable(ehci_mv);
- return phy_init(ehci_mv->phy);
+ retval = phy_init(ehci_mv->phy);
+ if (retval)
+ clk_disable_unprepare(ehci_mv->clk);
+
+ return retval;
}
static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv)
{
phy_exit(ehci_mv->phy);
- ehci_clock_disable(ehci_mv);
+ clk_disable_unprepare(ehci_mv->clk);
}
static int mv_ehci_reset(struct usb_hcd *hcd)
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index a319b1df3011..3626758b3e2a 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -264,8 +264,11 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
* the clock does not exists.
*/
priv->clk = devm_clk_get(&pdev->dev, NULL);
- if (!IS_ERR(priv->clk))
- clk_prepare_enable(priv->clk);
+ if (!IS_ERR(priv->clk)) {
+ err = clk_prepare_enable(priv->clk);
+ if (err)
+ goto err_put_hcd;
+ }
priv->phy = devm_phy_optional_get(&pdev->dev, "usb");
if (IS_ERR(priv->phy)) {
@@ -311,6 +314,7 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
err_dis_clk:
if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
+err_put_hcd:
usb_put_hcd(hcd);
err:
dev_err(&pdev->dev, "init %s fail, %d\n",
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
deleted file mode 100644
index 5fb92b956cc7..000000000000
--- a/drivers/usb/host/ehci-pmcmsp.c
+++ /dev/null
@@ -1,328 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * PMC MSP EHCI (Host Controller Driver) for USB.
- *
- * (C) Copyright 2006-2010 PMC-Sierra Inc
- */
-
-/* includes */
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/usb.h>
-#include <msp_usb.h>
-
-/* stream disable*/
-#define USB_CTRL_MODE_STREAM_DISABLE 0x10
-
-/* threshold */
-#define USB_CTRL_FIFO_THRESH 0x00300000
-
-/* register offset for usb_mode */
-#define USB_EHCI_REG_USB_MODE 0x68
-
-/* register offset for usb fifo */
-#define USB_EHCI_REG_USB_FIFO 0x24
-
-/* register offset for usb status */
-#define USB_EHCI_REG_USB_STATUS 0x44
-
-/* serial/parallel transceiver */
-#define USB_EHCI_REG_BIT_STAT_STS (1<<29)
-
-/* TWI USB0 host device pin */
-#define MSP_PIN_USB0_HOST_DEV 49
-
-/* TWI USB1 host device pin */
-#define MSP_PIN_USB1_HOST_DEV 50
-
-
-static void usb_hcd_tdi_set_mode(struct ehci_hcd *ehci)
-{
- u8 *base;
- u8 *statreg;
- u8 *fiforeg;
- u32 val;
- struct ehci_regs *reg_base = ehci->regs;
-
- /* get register base */
- base = (u8 *)reg_base + USB_EHCI_REG_USB_MODE;
- statreg = (u8 *)reg_base + USB_EHCI_REG_USB_STATUS;
- fiforeg = (u8 *)reg_base + USB_EHCI_REG_USB_FIFO;
-
- /* Disable controller mode stream */
- val = ehci_readl(ehci, (u32 *)base);
- ehci_writel(ehci, (val | USB_CTRL_MODE_STREAM_DISABLE),
- (u32 *)base);
-
- /* clear STS to select parallel transceiver interface */
- val = ehci_readl(ehci, (u32 *)statreg);
- val = val & ~USB_EHCI_REG_BIT_STAT_STS;
- ehci_writel(ehci, val, (u32 *)statreg);
-
- /* write to set the proper fifo threshold */
- ehci_writel(ehci, USB_CTRL_FIFO_THRESH, (u32 *)fiforeg);
-
- /* set TWI GPIO USB_HOST_DEV pin high */
- gpio_direction_output(MSP_PIN_USB0_HOST_DEV, 1);
-}
-
-/* called during probe() after chip reset completes */
-static int ehci_msp_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
-
- ehci->big_endian_mmio = 1;
- ehci->big_endian_desc = 1;
-
- ehci->caps = hcd->regs;
- hcd->has_tt = 1;
-
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- usb_hcd_tdi_set_mode(ehci);
-
- return retval;
-}
-
-
-/* configure so an HC device and id are always provided
- * always called with process context; sleeping is OK
- */
-
-static int usb_hcd_msp_map_regs(struct mspusb_device *dev)
-{
- struct resource *res;
- struct platform_device *pdev = &dev->dev;
- u32 res_len;
- int retval;
-
- /* MAB register space */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res == NULL)
- return -ENOMEM;
- res_len = resource_size(res);
- if (!request_mem_region(res->start, res_len, "mab regs"))
- return -EBUSY;
-
- dev->mab_regs = ioremap(res->start, res_len);
- if (dev->mab_regs == NULL) {
- retval = -ENOMEM;
- goto err1;
- }
-
- /* MSP USB register space */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- if (res == NULL) {
- retval = -ENOMEM;
- goto err2;
- }
- res_len = resource_size(res);
- if (!request_mem_region(res->start, res_len, "usbid regs")) {
- retval = -EBUSY;
- goto err2;
- }
- dev->usbid_regs = ioremap(res->start, res_len);
- if (dev->usbid_regs == NULL) {
- retval = -ENOMEM;
- goto err3;
- }
-
- return 0;
-err3:
- res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- res_len = resource_size(res);
- release_mem_region(res->start, res_len);
-err2:
- iounmap(dev->mab_regs);
-err1:
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- res_len = resource_size(res);
- release_mem_region(res->start, res_len);
- dev_err(&pdev->dev, "Failed to map non-EHCI regs.\n");
- return retval;
-}
-
-/**
- * usb_hcd_msp_probe - initialize PMC MSP-based HCDs
- * @driver: Pointer to hc driver instance
- * @dev: USB controller to probe
- *
- * Context: task context, might sleep
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- */
-int usb_hcd_msp_probe(const struct hc_driver *driver,
- struct platform_device *dev)
-{
- int retval;
- struct usb_hcd *hcd;
- struct resource *res;
- struct ehci_hcd *ehci ;
-
- hcd = usb_create_hcd(driver, &dev->dev, "pmcmsp");
- if (!hcd)
- return -ENOMEM;
-
- res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- pr_debug("No IOMEM resource info for %s.\n", dev->name);
- retval = -ENOMEM;
- goto err1;
- }
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, dev->name)) {
- retval = -EBUSY;
- goto err1;
- }
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- pr_debug("ioremap failed");
- retval = -ENOMEM;
- goto err2;
- }
-
- res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
- if (res == NULL) {
- dev_err(&dev->dev, "No IRQ resource info for %s.\n", dev->name);
- retval = -ENOMEM;
- goto err3;
- }
-
- /* Map non-EHCI register spaces */
- retval = usb_hcd_msp_map_regs(to_mspusb_device(dev));
- if (retval != 0)
- goto err3;
-
- ehci = hcd_to_ehci(hcd);
- ehci->big_endian_mmio = 1;
- ehci->big_endian_desc = 1;
-
-
- retval = usb_add_hcd(hcd, res->start, IRQF_SHARED);
- if (retval == 0) {
- device_wakeup_enable(hcd->self.controller);
- return 0;
- }
-
- usb_remove_hcd(hcd);
-err3:
- iounmap(hcd->regs);
-err2:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
- usb_put_hcd(hcd);
-
- return retval;
-}
-
-
-
-/**
- * usb_hcd_msp_remove - shutdown processing for PMC MSP-based HCDs
- * @hcd: USB Host Controller being removed
- *
- * Context: task context, might sleep
- *
- * Reverses the effect of usb_hcd_msp_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- * may be called without controller electrically present
- * may be called with controller, bus, and devices active
- */
-static void usb_hcd_msp_remove(struct usb_hcd *hcd)
-{
- usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
-}
-
-static const struct hc_driver ehci_msp_hc_driver = {
- .description = hcd_name,
- .product_desc = "PMC MSP EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_msp_setup,
- .shutdown = ehci_shutdown,
- .start = ehci_run,
- .stop = ehci_stop,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_hcd_msp_drv_probe(struct platform_device *pdev)
-{
- int ret;
-
- pr_debug("In ehci_hcd_msp_drv_probe");
-
- if (usb_disabled())
- return -ENODEV;
-
- gpio_request(MSP_PIN_USB0_HOST_DEV, "USB0_HOST_DEV_GPIO");
-
- ret = usb_hcd_msp_probe(&ehci_msp_hc_driver, pdev);
-
- return ret;
-}
-
-static int ehci_hcd_msp_drv_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_hcd_msp_remove(hcd);
-
- /* free TWI GPIO USB_HOST_DEV pin */
- gpio_free(MSP_PIN_USB0_HOST_DEV);
-
- return 0;
-}
-
-MODULE_ALIAS("pmcmsp-ehci");
-
-static struct platform_driver ehci_hcd_msp_driver = {
- .probe = ehci_hcd_msp_drv_probe,
- .remove = ehci_hcd_msp_drv_remove,
- .driver = {
- .name = "pmcmsp-ehci",
- },
-};
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index 05fb8d97cf02..4b02ace09f3d 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -1858,9 +1858,11 @@ static struct fotg210_qh *fotg210_qh_alloc(struct fotg210_hcd *fotg210,
qh = kzalloc(sizeof(*qh), GFP_ATOMIC);
if (!qh)
goto done;
- qh->hw = dma_pool_zalloc(fotg210->qh_pool, flags, &dma);
+ qh->hw = (struct fotg210_qh_hw *)
+ dma_pool_alloc(fotg210->qh_pool, flags, &dma);
if (!qh->hw)
goto fail;
+ memset(qh->hw, 0, sizeof(*qh->hw));
qh->qh_dma = dma;
INIT_LIST_HEAD(&qh->qtd_list);
@@ -2510,11 +2512,6 @@ retry_xacterr:
return count;
}
-/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
-#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
-/* ... and packet size, for any kind of endpoint descriptor */
-#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
-
/* reverse of qh_urb_transaction: free a list of TDs.
* used for cleanup after errors, before HC sees an URB's TDs.
*/
@@ -2600,7 +2597,7 @@ static struct list_head *qh_urb_transaction(struct fotg210_hcd *fotg210,
token |= (1 /* "in" */ << 8);
/* else it's already initted to "out" pid (0 << 8) */
- maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input));
+ maxpacket = usb_maxpacket(urb->dev, urb->pipe, !is_input);
/*
* buffer gets wrapped in one or more qtds;
@@ -2714,9 +2711,11 @@ static struct fotg210_qh *qh_make(struct fotg210_hcd *fotg210, struct urb *urb,
gfp_t flags)
{
struct fotg210_qh *qh = fotg210_qh_alloc(fotg210, flags);
+ struct usb_host_endpoint *ep;
u32 info1 = 0, info2 = 0;
int is_input, type;
int maxp = 0;
+ int mult;
struct usb_tt *tt = urb->dev->tt;
struct fotg210_qh_hw *hw;
@@ -2731,14 +2730,15 @@ static struct fotg210_qh *qh_make(struct fotg210_hcd *fotg210, struct urb *urb,
is_input = usb_pipein(urb->pipe);
type = usb_pipetype(urb->pipe);
- maxp = usb_maxpacket(urb->dev, urb->pipe, !is_input);
+ ep = usb_pipe_endpoint(urb->dev, urb->pipe);
+ maxp = usb_endpoint_maxp(&ep->desc);
+ mult = usb_endpoint_maxp_mult(&ep->desc);
/* 1024 byte maxpacket is a hardware ceiling. High bandwidth
* acts like up to 3KB, but is built from smaller packets.
*/
- if (max_packet(maxp) > 1024) {
- fotg210_dbg(fotg210, "bogus qh maxpacket %d\n",
- max_packet(maxp));
+ if (maxp > 1024) {
+ fotg210_dbg(fotg210, "bogus qh maxpacket %d\n", maxp);
goto done;
}
@@ -2752,8 +2752,7 @@ static struct fotg210_qh *qh_make(struct fotg210_hcd *fotg210, struct urb *urb,
*/
if (type == PIPE_INTERRUPT) {
qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
- is_input, 0,
- hb_mult(maxp) * max_packet(maxp)));
+ is_input, 0, mult * maxp));
qh->start = NO_FRAME;
if (urb->dev->speed == USB_SPEED_HIGH) {
@@ -2790,7 +2789,7 @@ static struct fotg210_qh *qh_make(struct fotg210_hcd *fotg210, struct urb *urb,
think_time = tt ? tt->think_time : 0;
qh->tt_usecs = NS_TO_US(think_time +
usb_calc_bus_time(urb->dev->speed,
- is_input, 0, max_packet(maxp)));
+ is_input, 0, maxp));
qh->period = urb->interval;
if (qh->period > fotg210->periodic_size) {
qh->period = fotg210->periodic_size;
@@ -2853,11 +2852,11 @@ static struct fotg210_qh *qh_make(struct fotg210_hcd *fotg210, struct urb *urb,
* to help them do so. So now people expect to use
* such nonconformant devices with Linux too; sigh.
*/
- info1 |= max_packet(maxp) << 16;
+ info1 |= maxp << 16;
info2 |= (FOTG210_TUNE_MULT_HS << 30);
} else { /* PIPE_INTERRUPT */
- info1 |= max_packet(maxp) << 16;
- info2 |= hb_mult(maxp) << 30;
+ info1 |= maxp << 16;
+ info2 |= mult << 30;
}
break;
default:
@@ -3927,6 +3926,7 @@ static void iso_stream_init(struct fotg210_hcd *fotg210,
int is_input;
long bandwidth;
unsigned multi;
+ struct usb_host_endpoint *ep;
/*
* this might be a "high bandwidth" highspeed endpoint,
@@ -3934,14 +3934,14 @@ static void iso_stream_init(struct fotg210_hcd *fotg210,
*/
epnum = usb_pipeendpoint(pipe);
is_input = usb_pipein(pipe) ? USB_DIR_IN : 0;
- maxp = usb_maxpacket(dev, pipe, !is_input);
+ ep = usb_pipe_endpoint(dev, pipe);
+ maxp = usb_endpoint_maxp(&ep->desc);
if (is_input)
buf1 = (1 << 11);
else
buf1 = 0;
- maxp = max_packet(maxp);
- multi = hb_mult(maxp);
+ multi = usb_endpoint_maxp_mult(&ep->desc);
buf1 |= maxp;
maxp *= multi;
@@ -4112,7 +4112,7 @@ static int itd_urb_transaction(struct fotg210_iso_stream *stream,
} else {
alloc_itd:
spin_unlock_irqrestore(&fotg210->lock, flags);
- itd = dma_pool_zalloc(fotg210->itd_pool, mem_flags,
+ itd = dma_pool_alloc(fotg210->itd_pool, mem_flags,
&itd_dma);
spin_lock_irqsave(&fotg210->lock, flags);
if (!itd) {
@@ -4122,6 +4122,7 @@ alloc_itd:
}
}
+ memset(itd, 0, sizeof(*itd));
itd->itd_dma = itd_dma;
list_add(&itd->itd_list, &sched->td_list);
}
@@ -4462,13 +4463,12 @@ static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
/* HC need not update length with this error */
if (!(t & FOTG210_ISOC_BABBLE)) {
- desc->actual_length =
- fotg210_itdlen(urb, desc, t);
+ desc->actual_length = FOTG210_ITD_LENGTH(t);
urb->actual_length += desc->actual_length;
}
} else if (likely((t & FOTG210_ISOC_ACTIVE) == 0)) {
desc->status = 0;
- desc->actual_length = fotg210_itdlen(urb, desc, t);
+ desc->actual_length = FOTG210_ITD_LENGTH(t);
urb->actual_length += desc->actual_length;
} else {
/* URB was too late */
diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h
index 0a91061a0551..0781442b7a24 100644
--- a/drivers/usb/host/fotg210.h
+++ b/drivers/usb/host/fotg210.h
@@ -683,11 +683,6 @@ static inline unsigned fotg210_read_frame_index(struct fotg210_hcd *fotg210)
return fotg210_readl(fotg210, &fotg210->regs->frame_index);
}
-#define fotg210_itdlen(urb, desc, t) ({ \
- usb_pipein((urb)->pipe) ? \
- (desc)->length - FOTG210_ITD_LENGTH(t) : \
- FOTG210_ITD_LENGTH(t); \
-})
/*-------------------------------------------------------------------------*/
#endif /* __LINUX_FOTG210_H */
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 5cc05449281c..b4cd9e6c72fd 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -84,7 +84,7 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
clk_prepare_enable(sohci_p->clk);
- retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0);
+ retval = usb_add_hcd(hcd, irq, 0);
if (retval == 0) {
device_wakeup_enable(hcd->self.controller);
return retval;
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index 7f857bad9e95..08ec2ab0d95a 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -202,6 +202,9 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
if (!cell)
return -EINVAL;
+ if (irq < 0)
+ return irq;
+
hcd = usb_create_hcd(&ohci_tmio_hc_driver, &dev->dev, dev_name(&dev->dev));
if (!hcd) {
ret = -ENOMEM;
diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
index bef104511352..6e784f2fc26d 100644
--- a/drivers/usb/host/xhci-dbgtty.c
+++ b/drivers/usb/host/xhci-dbgtty.c
@@ -541,7 +541,7 @@ static int dbc_tty_init(void)
ret = tty_register_driver(dbc_tty_driver);
if (ret) {
pr_err("Can't register dbc tty driver\n");
- put_tty_driver(dbc_tty_driver);
+ tty_driver_kref_put(dbc_tty_driver);
}
return ret;
}
@@ -550,7 +550,7 @@ static void dbc_tty_exit(void)
{
if (dbc_tty_driver) {
tty_unregister_driver(dbc_tty_driver);
- put_tty_driver(dbc_tty_driver);
+ tty_driver_kref_put(dbc_tty_driver);
dbc_tty_driver = NULL;
}
}
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c
index 2c0fda57869e..dc832ddf7033 100644
--- a/drivers/usb/host/xhci-debugfs.c
+++ b/drivers/usb/host/xhci-debugfs.c
@@ -198,12 +198,13 @@ static void xhci_ring_dump_segment(struct seq_file *s,
int i;
dma_addr_t dma;
union xhci_trb *trb;
+ char str[XHCI_MSG_MAX];
for (i = 0; i < TRBS_PER_SEGMENT; i++) {
trb = &seg->trbs[i];
dma = seg->dma + i * sizeof(*trb);
seq_printf(s, "%pad: %s\n", &dma,
- xhci_decode_trb(le32_to_cpu(trb->generic.field[0]),
+ xhci_decode_trb(str, XHCI_MSG_MAX, le32_to_cpu(trb->generic.field[0]),
le32_to_cpu(trb->generic.field[1]),
le32_to_cpu(trb->generic.field[2]),
le32_to_cpu(trb->generic.field[3])));
@@ -260,11 +261,13 @@ static int xhci_slot_context_show(struct seq_file *s, void *unused)
struct xhci_slot_ctx *slot_ctx;
struct xhci_slot_priv *priv = s->private;
struct xhci_virt_device *dev = priv->dev;
+ char str[XHCI_MSG_MAX];
xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma,
- xhci_decode_slot_context(le32_to_cpu(slot_ctx->dev_info),
+ xhci_decode_slot_context(str,
+ le32_to_cpu(slot_ctx->dev_info),
le32_to_cpu(slot_ctx->dev_info2),
le32_to_cpu(slot_ctx->tt_info),
le32_to_cpu(slot_ctx->dev_state)));
@@ -280,6 +283,7 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_priv *priv = s->private;
struct xhci_virt_device *dev = priv->dev;
+ char str[XHCI_MSG_MAX];
xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
@@ -287,7 +291,8 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
dma = dev->out_ctx->dma + (ep_index + 1) * CTX_SIZE(xhci->hcc_params);
seq_printf(s, "%pad: %s\n", &dma,
- xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info),
+ xhci_decode_ep_context(str,
+ le32_to_cpu(ep_ctx->ep_info),
le32_to_cpu(ep_ctx->ep_info2),
le64_to_cpu(ep_ctx->deq),
le32_to_cpu(ep_ctx->tx_info)));
@@ -341,9 +346,10 @@ static int xhci_portsc_show(struct seq_file *s, void *unused)
{
struct xhci_port *port = s->private;
u32 portsc;
+ char str[XHCI_MSG_MAX];
portsc = readl(port->addr);
- seq_printf(s, "%s\n", xhci_decode_portsc(portsc));
+ seq_printf(s, "%s\n", xhci_decode_portsc(str, portsc));
return 0;
}
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 151e93c4bd57..a3f875eea751 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1667,7 +1667,8 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
status = 1;
}
if (!status && !reset_change) {
- xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
+ xhci_dbg(xhci, "%s: stopping usb%d port polling\n",
+ __func__, hcd->self.busnum);
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
}
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -1699,7 +1700,8 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
if (bus_state->resuming_ports || /* USB2 */
bus_state->port_remote_wakeup) { /* USB3 */
spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "suspend failed because a port is resuming\n");
+ xhci_dbg(xhci, "usb%d bus suspend to fail because a port is resuming\n",
+ hcd->self.busnum);
return -EBUSY;
}
}
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index cffcaf4dfa9f..134f4789bd89 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -80,7 +80,7 @@ decode_ep(struct usb_host_endpoint *ep, enum usb_device_speed speed)
interval /= 1000;
}
- snprintf(buf, DBG_BUF_EN, "%s ep%d%s %s, mpkt:%d, interval:%d/%d%s\n",
+ snprintf(buf, DBG_BUF_EN, "%s ep%d%s %s, mpkt:%d, interval:%d/%d%s",
usb_speed_string(speed), usb_endpoint_num(epd),
usb_endpoint_dir_in(epd) ? "in" : "out",
usb_ep_type_string(usb_endpoint_type(epd)),
@@ -129,6 +129,10 @@ get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
int bw_index;
virt_dev = xhci->devs[udev->slot_id];
+ if (!virt_dev->real_port) {
+ WARN_ONCE(1, "%s invalid real_port\n", dev_name(&udev->dev));
+ return NULL;
+ }
if (udev->speed >= USB_SPEED_SUPER) {
if (usb_endpoint_dir_out(&ep->desc))
@@ -236,14 +240,20 @@ static void drop_tt(struct usb_device *udev)
}
}
-static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
- struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
+static struct mu3h_sch_ep_info *
+create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
+ struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
{
struct mu3h_sch_ep_info *sch_ep;
+ struct mu3h_sch_bw_info *bw_info;
struct mu3h_sch_tt *tt = NULL;
u32 len_bw_budget_table;
size_t mem_size;
+ bw_info = get_bw_info(mtk, udev, ep);
+ if (!bw_info)
+ return ERR_PTR(-ENODEV);
+
if (is_fs_or_ls(udev->speed))
len_bw_budget_table = TT_MICROFRAMES_MAX;
else if ((udev->speed >= USB_SPEED_SUPER)
@@ -266,11 +276,13 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
}
}
+ sch_ep->bw_info = bw_info;
sch_ep->sch_tt = tt;
sch_ep->ep = ep;
sch_ep->speed = udev->speed;
INIT_LIST_HEAD(&sch_ep->endpoint);
INIT_LIST_HEAD(&sch_ep->tt_endpoint);
+ INIT_HLIST_NODE(&sch_ep->hentry);
return sch_ep;
}
@@ -297,6 +309,7 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
sch_ep->esit = get_esit(ep_ctx);
+ sch_ep->num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
sch_ep->ep_type = ep_type;
sch_ep->maxpkt = maxpkt;
sch_ep->offset = 0;
@@ -401,19 +414,16 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
struct mu3h_sch_ep_info *sch_ep, u32 offset)
{
- u32 num_esit;
u32 max_bw = 0;
u32 bw;
- int i;
- int j;
+ int i, j, k;
- num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
- for (i = 0; i < num_esit; i++) {
+ for (i = 0; i < sch_ep->num_esit; i++) {
u32 base = offset + i * sch_ep->esit;
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
- bw = sch_bw->bus_bw[base + j] +
- sch_ep->bw_budget_table[j];
+ k = XHCI_MTK_BW_INDEX(base + j);
+ bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j];
if (bw > max_bw)
max_bw = bw;
}
@@ -424,21 +434,17 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
struct mu3h_sch_ep_info *sch_ep, bool used)
{
- u32 num_esit;
u32 base;
- int i;
- int j;
+ int i, j, k;
- num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
- for (i = 0; i < num_esit; i++) {
+ for (i = 0; i < sch_ep->num_esit; i++) {
base = sch_ep->offset + i * sch_ep->esit;
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
+ k = XHCI_MTK_BW_INDEX(base + j);
if (used)
- sch_bw->bus_bw[base + j] +=
- sch_ep->bw_budget_table[j];
+ sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j];
else
- sch_bw->bus_bw[base + j] -=
- sch_ep->bw_budget_table[j];
+ sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j];
}
}
}
@@ -446,20 +452,20 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
{
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
- u32 num_esit, tmp;
+ u32 tmp;
int base;
- int i, j;
+ int i, j, k;
- num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
- for (i = 0; i < num_esit; i++) {
+ for (i = 0; i < sch_ep->num_esit; i++) {
base = offset + i * sch_ep->esit;
/*
* Compared with hs bus, no matter what ep type,
* the hub will always delay one uframe to send data
*/
- for (j = 0; j < sch_ep->cs_count; j++) {
- tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_cost_per_microframe;
+ for (j = 0; j < sch_ep->num_budget_microframes; j++) {
+ k = XHCI_MTK_BW_INDEX(base + j);
+ tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j];
if (tmp > FS_PAYLOAD_MAX)
return -ESCH_BW_OVERFLOW;
}
@@ -533,22 +539,19 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
{
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
- u32 base, num_esit;
- int bw_updated;
- int i, j;
-
- num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
-
- if (used)
- bw_updated = sch_ep->bw_cost_per_microframe;
- else
- bw_updated = -sch_ep->bw_cost_per_microframe;
+ u32 base;
+ int i, j, k;
- for (i = 0; i < num_esit; i++) {
+ for (i = 0; i < sch_ep->num_esit; i++) {
base = sch_ep->offset + i * sch_ep->esit;
- for (j = 0; j < sch_ep->cs_count; j++)
- tt->fs_bus_bw[base + j] += bw_updated;
+ for (j = 0; j < sch_ep->num_budget_microframes; j++) {
+ k = XHCI_MTK_BW_INDEX(base + j);
+ if (used)
+ tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j];
+ else
+ tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j];
+ }
}
if (used)
@@ -570,25 +573,9 @@ static int load_ep_bw(struct mu3h_sch_bw_info *sch_bw,
return 0;
}
-static u32 get_esit_boundary(struct mu3h_sch_ep_info *sch_ep)
-{
- u32 boundary = sch_ep->esit;
-
- if (sch_ep->sch_tt) { /* LS/FS with TT */
- /* tune for CS */
- if (sch_ep->ep_type != ISOC_OUT_EP)
- boundary++;
- else if (boundary > 1) /* normally esit >= 8 for FS/LS */
- boundary--;
- }
-
- return boundary;
-}
-
-static int check_sch_bw(struct mu3h_sch_bw_info *sch_bw,
- struct mu3h_sch_ep_info *sch_ep)
+static int check_sch_bw(struct mu3h_sch_ep_info *sch_ep)
{
- const u32 esit_boundary = get_esit_boundary(sch_ep);
+ struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info;
const u32 bw_boundary = get_bw_boundary(sch_ep->speed);
u32 offset;
u32 worst_bw;
@@ -605,9 +592,6 @@ static int check_sch_bw(struct mu3h_sch_bw_info *sch_bw,
if (ret)
continue;
- if ((offset + sch_ep->num_budget_microframes) > esit_boundary)
- break;
-
worst_bw = get_max_bw(sch_bw, sch_ep, offset);
if (worst_bw > bw_boundary)
continue;
@@ -633,23 +617,26 @@ static int check_sch_bw(struct mu3h_sch_bw_info *sch_bw,
return load_ep_bw(sch_bw, sch_ep, true);
}
-static void destroy_sch_ep(struct usb_device *udev,
- struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
+static void destroy_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
+ struct mu3h_sch_ep_info *sch_ep)
{
/* only release ep bw check passed by check_sch_bw() */
if (sch_ep->allocated)
- load_ep_bw(sch_bw, sch_ep, false);
+ load_ep_bw(sch_ep->bw_info, sch_ep, false);
if (sch_ep->sch_tt)
drop_tt(udev);
list_del(&sch_ep->endpoint);
+ hlist_del(&sch_ep->hentry);
kfree(sch_ep);
}
-static bool need_bw_sch(struct usb_host_endpoint *ep,
- enum usb_device_speed speed, int has_tt)
+static bool need_bw_sch(struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
+ bool has_tt = udev->tt && udev->tt->hub->parent;
+
/* only for periodic endpoints */
if (usb_endpoint_xfer_control(&ep->desc)
|| usb_endpoint_xfer_bulk(&ep->desc))
@@ -660,7 +647,7 @@ static bool need_bw_sch(struct usb_host_endpoint *ep,
* a TT are also ignored, root-hub will schedule them directly,
* but need set @bpkts field of endpoint context to 1.
*/
- if (is_fs_or_ls(speed) && !has_tt)
+ if (is_fs_or_ls(udev->speed) && !has_tt)
return false;
/* skip endpoint with zero maxpkt */
@@ -675,7 +662,6 @@ int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk)
struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
struct mu3h_sch_bw_info *sch_array;
int num_usb_bus;
- int i;
/* ss IN and OUT are separated */
num_usb_bus = xhci->usb3_rhub.num_ports * 2 + xhci->usb2_rhub.num_ports;
@@ -684,12 +670,10 @@ int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk)
if (sch_array == NULL)
return -ENOMEM;
- for (i = 0; i < num_usb_bus; i++)
- INIT_LIST_HEAD(&sch_array[i].bw_ep_list);
-
mtk->sch_array = sch_array;
INIT_LIST_HEAD(&mtk->bw_ep_chk_list);
+ hash_init(mtk->sch_ep_hash);
return 0;
}
@@ -713,9 +697,7 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
ep_index = xhci_get_endpoint_index(&ep->desc);
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
- xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
-
- if (!need_bw_sch(ep, udev->speed, !!virt_dev->tt_info)) {
+ if (!need_bw_sch(udev, ep)) {
/*
* set @bpkts to 1 if it is LS or FS periodic endpoint, and its
* device does not connected through an external HS hub
@@ -727,13 +709,16 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
return 0;
}
- sch_ep = create_sch_ep(udev, ep, ep_ctx);
+ xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
+
+ sch_ep = create_sch_ep(mtk, udev, ep, ep_ctx);
if (IS_ERR_OR_NULL(sch_ep))
return -ENOMEM;
setup_sch_info(ep_ctx, sch_ep);
list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list);
+ hash_add(mtk->sch_ep_hash, &sch_ep->hentry, (unsigned long)ep);
return 0;
}
@@ -743,22 +728,18 @@ static void drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
{
struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- struct xhci_virt_device *virt_dev;
- struct mu3h_sch_bw_info *sch_bw;
- struct mu3h_sch_ep_info *sch_ep, *tmp;
-
- virt_dev = xhci->devs[udev->slot_id];
-
- xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
+ struct mu3h_sch_ep_info *sch_ep;
+ struct hlist_node *hn;
- if (!need_bw_sch(ep, udev->speed, !!virt_dev->tt_info))
+ if (!need_bw_sch(udev, ep))
return;
- sch_bw = get_bw_info(mtk, udev, ep);
+ xhci_err(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
- list_for_each_entry_safe(sch_ep, tmp, &sch_bw->bw_ep_list, endpoint) {
+ hash_for_each_possible_safe(mtk->sch_ep_hash, sch_ep,
+ hn, hentry, (unsigned long)ep) {
if (sch_ep->ep == ep) {
- destroy_sch_ep(udev, sch_bw, sch_ep);
+ destroy_sch_ep(mtk, udev, sch_ep);
break;
}
}
@@ -769,30 +750,22 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
- struct mu3h_sch_bw_info *sch_bw;
- struct mu3h_sch_ep_info *sch_ep, *tmp;
+ struct mu3h_sch_ep_info *sch_ep;
int ret;
xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));
list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) {
- sch_bw = get_bw_info(mtk, udev, sch_ep->ep);
+ struct xhci_ep_ctx *ep_ctx;
+ struct usb_host_endpoint *ep = sch_ep->ep;
+ unsigned int ep_index = xhci_get_endpoint_index(&ep->desc);
- ret = check_sch_bw(sch_bw, sch_ep);
+ ret = check_sch_bw(sch_ep);
if (ret) {
xhci_err(xhci, "Not enough bandwidth! (%s)\n",
sch_error_string(-ret));
return -ENOSPC;
}
- }
-
- list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) {
- struct xhci_ep_ctx *ep_ctx;
- struct usb_host_endpoint *ep = sch_ep->ep;
- unsigned int ep_index = xhci_get_endpoint_index(&ep->desc);
-
- sch_bw = get_bw_info(mtk, udev, ep);
- list_move_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(sch_ep->pkts)
@@ -806,22 +779,23 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
sch_ep->offset, sch_ep->repeat);
}
- return xhci_check_bandwidth(hcd, udev);
+ ret = xhci_check_bandwidth(hcd, udev);
+ if (!ret)
+ INIT_LIST_HEAD(&mtk->bw_ep_chk_list);
+
+ return ret;
}
void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- struct mu3h_sch_bw_info *sch_bw;
struct mu3h_sch_ep_info *sch_ep, *tmp;
xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));
- list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) {
- sch_bw = get_bw_info(mtk, udev, sch_ep->ep);
- destroy_sch_ep(udev, sch_bw, sch_ep);
- }
+ list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint)
+ destroy_sch_ep(mtk, udev, sch_ep);
xhci_reset_bandwidth(hcd, udev);
}
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 2548976bcf05..c53f6f276d5c 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -56,6 +56,27 @@
/* u2_phy_pll register */
#define CTRL_U2_FORCE_PLL_STB BIT(28)
+/* xHCI CSR */
+#define LS_EOF_CFG 0x930
+#define LSEOF_OFFSET 0x89
+
+#define FS_EOF_CFG 0x934
+#define FSEOF_OFFSET 0x2e
+
+#define SS_GEN1_EOF_CFG 0x93c
+#define SSG1EOF_OFFSET 0x78
+
+#define HFCNTR_CFG 0x944
+#define ITP_DELTA_CLK (0xa << 1)
+#define ITP_DELTA_CLK_MASK GENMASK(5, 1)
+#define FRMCNT_LEV1_RANG (0x12b << 8)
+#define FRMCNT_LEV1_RANG_MASK GENMASK(19, 8)
+
+#define SS_GEN2_EOF_CFG 0x990
+#define SSG2EOF_OFFSET 0x3c
+
+#define XSEOF_OFFSET_MASK GENMASK(11, 0)
+
/* usb remote wakeup registers in syscon */
/* mt8173 etc */
@@ -86,6 +107,46 @@ enum ssusb_uwk_vers {
SSUSB_UWK_V1_2, /* specific revision 1.2 */
};
+/*
+ * MT8195 has 4 controllers, the controller1~3's default SOF/ITP interval
+ * is calculated from the frame counter clock 24M, but in fact, the clock
+ * is 48M, add workaround for it.
+ */
+static void xhci_mtk_set_frame_interval(struct xhci_hcd_mtk *mtk)
+{
+ struct device *dev = mtk->dev;
+ struct usb_hcd *hcd = mtk->hcd;
+ u32 value;
+
+ if (!of_device_is_compatible(dev->of_node, "mediatek,mt8195-xhci"))
+ return;
+
+ value = readl(hcd->regs + HFCNTR_CFG);
+ value &= ~(ITP_DELTA_CLK_MASK | FRMCNT_LEV1_RANG_MASK);
+ value |= (ITP_DELTA_CLK | FRMCNT_LEV1_RANG);
+ writel(value, hcd->regs + HFCNTR_CFG);
+
+ value = readl(hcd->regs + LS_EOF_CFG);
+ value &= ~XSEOF_OFFSET_MASK;
+ value |= LSEOF_OFFSET;
+ writel(value, hcd->regs + LS_EOF_CFG);
+
+ value = readl(hcd->regs + FS_EOF_CFG);
+ value &= ~XSEOF_OFFSET_MASK;
+ value |= FSEOF_OFFSET;
+ writel(value, hcd->regs + FS_EOF_CFG);
+
+ value = readl(hcd->regs + SS_GEN1_EOF_CFG);
+ value &= ~XSEOF_OFFSET_MASK;
+ value |= SSG1EOF_OFFSET;
+ writel(value, hcd->regs + SS_GEN1_EOF_CFG);
+
+ value = readl(hcd->regs + SS_GEN2_EOF_CFG);
+ value &= ~XSEOF_OFFSET_MASK;
+ value |= SSG2EOF_OFFSET;
+ writel(value, hcd->regs + SS_GEN2_EOF_CFG);
+}
+
static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
{
struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
@@ -115,8 +176,11 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
writel(value, &ippc->u3_ctrl_p[i]);
}
- /* power on and enable all u2 ports */
+ /* power on and enable all u2 ports except skipped ones */
for (i = 0; i < mtk->num_u2_ports; i++) {
+ if (BIT(i) & mtk->u2p_dis_msk)
+ continue;
+
value = readl(&ippc->u2_ctrl_p[i]);
value &= ~(CTRL_U2_PORT_PDN | CTRL_U2_PORT_DIS);
value |= CTRL_U2_PORT_HOST_SEL;
@@ -163,8 +227,11 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk)
writel(value, &ippc->u3_ctrl_p[i]);
}
- /* power down all u2 ports */
+ /* power down all u2 ports except skipped ones */
for (i = 0; i < mtk->num_u2_ports; i++) {
+ if (BIT(i) & mtk->u2p_dis_msk)
+ continue;
+
value = readl(&ippc->u2_ctrl_p[i]);
value |= CTRL_U2_PORT_PDN;
writel(value, &ippc->u2_ctrl_p[i]);
@@ -361,6 +428,9 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
ret = xhci_mtk_ssusb_config(mtk);
if (ret)
return ret;
+
+ /* workaround only for mt8195 */
+ xhci_mtk_set_frame_interval(mtk);
}
ret = xhci_gen_setup(hcd, xhci_mtk_quirks);
@@ -444,6 +514,8 @@ static int xhci_mtk_probe(struct platform_device *pdev)
/* optional property, ignore the error if it does not exist */
of_property_read_u32(node, "mediatek,u3p-dis-msk",
&mtk->u3p_dis_msk);
+ of_property_read_u32(node, "mediatek,u2p-dis-msk",
+ &mtk->u2p_dis_msk);
ret = usb_wakeup_of_property_parse(mtk, node);
if (ret) {
@@ -569,7 +641,7 @@ disable_ldos:
xhci_mtk_ldos_disable(mtk);
disable_pm:
- pm_runtime_put_sync_autosuspend(dev);
+ pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
return ret;
}
@@ -704,6 +776,7 @@ static const struct dev_pm_ops xhci_mtk_pm_ops = {
static const struct of_device_id mtk_xhci_of_match[] = {
{ .compatible = "mediatek,mt8173-xhci"},
+ { .compatible = "mediatek,mt8195-xhci"},
{ .compatible = "mediatek,mtk-xhci"},
{ },
};
diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
index ace432356c41..4b1ea89f959a 100644
--- a/drivers/usb/host/xhci-mtk.h
+++ b/drivers/usb/host/xhci-mtk.h
@@ -10,18 +10,23 @@
#define _XHCI_MTK_H_
#include <linux/clk.h>
+#include <linux/hashtable.h>
#include "xhci.h"
#define BULK_CLKS_NUM 5
+/* support at most 64 ep, use 32 size hash table */
+#define SCH_EP_HASH_BITS 5
+
/**
* To simplify scheduler algorithm, set a upper limit for ESIT,
* if a synchromous ep's ESIT is larger than @XHCI_MTK_MAX_ESIT,
* round down to the limit value, that means allocating more
* bandwidth to it.
*/
-#define XHCI_MTK_MAX_ESIT 64
+#define XHCI_MTK_MAX_ESIT (1 << 6)
+#define XHCI_MTK_BW_INDEX(x) ((x) & (XHCI_MTK_MAX_ESIT - 1))
/**
* @fs_bus_bw: array to keep track of bandwidth already used for FS
@@ -36,25 +41,26 @@ struct mu3h_sch_tt {
* struct mu3h_sch_bw_info: schedule information for bandwidth domain
*
* @bus_bw: array to keep track of bandwidth already used at each uframes
- * @bw_ep_list: eps in the bandwidth domain
*
* treat a HS root port as a bandwidth domain, but treat a SS root port as
* two bandwidth domains, one for IN eps and another for OUT eps.
*/
struct mu3h_sch_bw_info {
u32 bus_bw[XHCI_MTK_MAX_ESIT];
- struct list_head bw_ep_list;
};
/**
* struct mu3h_sch_ep_info: schedule information for endpoint
*
* @esit: unit is 125us, equal to 2 << Interval field in ep-context
+ * @num_esit: number of @esit in a period
* @num_budget_microframes: number of continuous uframes
* (@repeat==1) scheduled within the interval
* @bw_cost_per_microframe: bandwidth cost per microframe
+ * @hentry: hash table entry
* @endpoint: linked into bandwidth domain which it belongs to
* @tt_endpoint: linked into mu3h_sch_tt's list which it belongs to
+ * @bw_info: bandwidth domain which this endpoint belongs
* @sch_tt: mu3h_sch_tt linked into
* @ep_type: endpoint type
* @maxpkt: max packet size of endpoint
@@ -79,10 +85,13 @@ struct mu3h_sch_bw_info {
*/
struct mu3h_sch_ep_info {
u32 esit;
+ u32 num_esit;
u32 num_budget_microframes;
u32 bw_cost_per_microframe;
struct list_head endpoint;
+ struct hlist_node hentry;
struct list_head tt_endpoint;
+ struct mu3h_sch_bw_info *bw_info;
struct mu3h_sch_tt *sch_tt;
u32 ep_type;
u32 maxpkt;
@@ -135,9 +144,11 @@ struct xhci_hcd_mtk {
struct usb_hcd *hcd;
struct mu3h_sch_bw_info *sch_array;
struct list_head bw_ep_chk_list;
+ DECLARE_HASHTABLE(sch_ep_hash, SCH_EP_HASH_BITS);
struct mu3c_ippc_regs __iomem *ippc_regs;
int num_u2_ports;
int num_u3_ports;
+ int u2p_dis_msk;
int u3p_dis_msk;
struct regulator *vusb33;
struct regulator *vbus;
diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c
index ef5e91a5542d..52599d96634f 100644
--- a/drivers/usb/host/xhci-pci-renesas.c
+++ b/drivers/usb/host/xhci-pci-renesas.c
@@ -599,7 +599,7 @@ int renesas_xhci_check_request_fw(struct pci_dev *pdev,
err = renesas_fw_check_running(pdev);
/* Continue ahead, if the firmware is already running. */
- if (err == 0)
+ if (!err)
return 0;
/* no firmware interface available */
@@ -631,9 +631,4 @@ exit:
}
EXPORT_SYMBOL_GPL(renesas_xhci_check_request_fw);
-void renesas_xhci_pci_exit(struct pci_dev *dev)
-{
-}
-EXPORT_SYMBOL_GPL(renesas_xhci_pci_exit);
-
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 1c9a7957c45c..2c9f25ca8edd 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -449,8 +449,6 @@ static void xhci_pci_remove(struct pci_dev *dev)
struct xhci_hcd *xhci;
xhci = hcd_to_xhci(pci_get_drvdata(dev));
- if (xhci->quirks & XHCI_RENESAS_FW_QUIRK)
- renesas_xhci_pci_exit(dev);
xhci->xhc_state |= XHCI_STATE_REMOVING;
diff --git a/drivers/usb/host/xhci-pci.h b/drivers/usb/host/xhci-pci.h
index acd7cf0a1706..cb9a8f331a44 100644
--- a/drivers/usb/host/xhci-pci.h
+++ b/drivers/usb/host/xhci-pci.h
@@ -7,7 +7,6 @@
#if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS)
int renesas_xhci_check_request_fw(struct pci_dev *dev,
const struct pci_device_id *id);
-void renesas_xhci_pci_exit(struct pci_dev *dev);
#else
static int renesas_xhci_check_request_fw(struct pci_dev *dev,
@@ -16,8 +15,6 @@ static int renesas_xhci_check_request_fw(struct pci_dev *dev,
return 0;
}
-static void renesas_xhci_pci_exit(struct pci_dev *dev) { };
-
#endif
struct xhci_driver_data {
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index 1bc4fe7b8c75..9888ba7d85b6 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -134,6 +134,13 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
const struct soc_device_attribute *attr;
const char *firmware_name;
+ /*
+ * According to the datasheet, "Upon the completion of FW Download,
+ * there is no need to write or reload FW".
+ */
+ if (readl(regs + RCAR_USB3_DL_CTRL) & RCAR_USB3_DL_CTRL_FW_SUCCESS)
+ return 0;
+
attr = soc_device_match(rcar_quirks_match);
if (attr)
quirks = (uintptr_t)attr->data;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 8fea44bbc266..e676749f543b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -830,9 +830,14 @@ static void xhci_giveback_invalidated_tds(struct xhci_virt_ep *ep)
ring = xhci_urb_to_transfer_ring(ep->xhci, td->urb);
- if (td->cancel_status == TD_CLEARED)
+ if (td->cancel_status == TD_CLEARED) {
+ xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n",
+ __func__, td->urb);
xhci_td_cleanup(ep->xhci, td, ring, td->status);
-
+ } else {
+ xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n",
+ __func__, td->urb, td->cancel_status);
+ }
if (ep->xhci->xhc_state & XHCI_STATE_DYING)
return;
}
@@ -850,6 +855,10 @@ static int xhci_reset_halted_ep(struct xhci_hcd *xhci, unsigned int slot_id,
goto done;
}
+ xhci_dbg(xhci, "%s-reset ep %u, slot %u\n",
+ (reset_type == EP_HARD_RESET) ? "Hard" : "Soft",
+ ep_index, slot_id);
+
ret = xhci_queue_reset_ep(xhci, command, slot_id, ep_index, reset_type);
done:
if (ret)
@@ -883,7 +892,8 @@ static int xhci_handle_halted_endpoint(struct xhci_hcd *xhci,
}
if (ep->ep_state & EP_HALTED) {
- xhci_dbg(xhci, "Reset ep command already pending\n");
+ xhci_dbg(xhci, "Reset ep command for ep_index %d already pending\n",
+ ep->ep_index);
return 0;
}
@@ -922,9 +932,10 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
- "Removing canceled TD starting at 0x%llx (dma).",
- (unsigned long long)xhci_trb_virt_to_dma(
- td->start_seg, td->first_trb));
+ "Removing canceled TD starting at 0x%llx (dma) in stream %u URB %p",
+ (unsigned long long)xhci_trb_virt_to_dma(
+ td->start_seg, td->first_trb),
+ td->urb->stream_id, td->urb);
list_del_init(&td->td_list);
ring = xhci_urb_to_transfer_ring(xhci, td->urb);
if (!ring) {
@@ -942,17 +953,21 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
td->urb->stream_id);
hw_deq &= ~0xf;
- if (td->cancel_status == TD_HALTED) {
- cached_td = td;
- } else if (trb_in_td(xhci, td->start_seg, td->first_trb,
- td->last_trb, hw_deq, false)) {
+ if (td->cancel_status == TD_HALTED ||
+ trb_in_td(xhci, td->start_seg, td->first_trb, td->last_trb, hw_deq, false)) {
switch (td->cancel_status) {
case TD_CLEARED: /* TD is already no-op */
case TD_CLEARING_CACHE: /* set TR deq command already queued */
break;
case TD_DIRTY: /* TD is cached, clear it */
case TD_HALTED:
- /* FIXME stream case, several stopped rings */
+ td->cancel_status = TD_CLEARING_CACHE;
+ if (cached_td)
+ /* FIXME stream case, several stopped rings */
+ xhci_dbg(xhci,
+ "Move dq past stream %u URB %p instead of stream %u URB %p\n",
+ td->urb->stream_id, td->urb,
+ cached_td->urb->stream_id, cached_td->urb);
cached_td = td;
break;
}
@@ -961,18 +976,24 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
td->cancel_status = TD_CLEARED;
}
}
- if (cached_td) {
- cached_td->cancel_status = TD_CLEARING_CACHE;
- err = xhci_move_dequeue_past_td(xhci, slot_id, ep->ep_index,
- cached_td->urb->stream_id,
- cached_td);
- /* Failed to move past cached td, try just setting it noop */
- if (err) {
- td_to_noop(xhci, ring, cached_td, false);
- cached_td->cancel_status = TD_CLEARED;
+ /* If there's no need to move the dequeue pointer then we're done */
+ if (!cached_td)
+ return 0;
+
+ err = xhci_move_dequeue_past_td(xhci, slot_id, ep->ep_index,
+ cached_td->urb->stream_id,
+ cached_td);
+ if (err) {
+ /* Failed to move past cached td, just set cached TDs to no-op */
+ list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
+ if (td->cancel_status != TD_CLEARING_CACHE)
+ continue;
+ xhci_dbg(xhci, "Failed to clear cancelled cached URB %p, mark clear anyway\n",
+ td->urb);
+ td_to_noop(xhci, ring, td, false);
+ td->cancel_status = TD_CLEARED;
}
- cached_td = NULL;
}
return 0;
}
@@ -1069,6 +1090,8 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
return;
case EP_STATE_RUNNING:
/* Race, HW handled stop ep cmd before ep was running */
+ xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n");
+
command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
if (!command)
xhci_stop_watchdog_timer_in_irq(xhci, ep);
@@ -1212,6 +1235,7 @@ void xhci_stop_endpoint_command_watchdog(struct timer_list *t)
struct xhci_hcd *xhci = ep->xhci;
unsigned long flags;
u32 usbsts;
+ char str[XHCI_MSG_MAX];
spin_lock_irqsave(&xhci->lock, flags);
@@ -1225,7 +1249,7 @@ void xhci_stop_endpoint_command_watchdog(struct timer_list *t)
usbsts = readl(&xhci->op_regs->status);
xhci_warn(xhci, "xHCI host not responding to stop endpoint command.\n");
- xhci_warn(xhci, "USBSTS:%s\n", xhci_decode_usbsts(usbsts));
+ xhci_warn(xhci, "USBSTS:%s\n", xhci_decode_usbsts(str, usbsts));
ep->ep_state &= ~EP_STOP_CMD_PENDING;
@@ -1389,7 +1413,12 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
ep_ring = xhci_urb_to_transfer_ring(ep->xhci, td->urb);
if (td->cancel_status == TD_CLEARING_CACHE) {
td->cancel_status = TD_CLEARED;
+ xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n",
+ __func__, td->urb);
xhci_td_cleanup(ep->xhci, td, ep_ring, td->status);
+ } else {
+ xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n",
+ __func__, td->urb, td->cancel_status);
}
}
cleanup:
@@ -2002,7 +2031,8 @@ cleanup:
* bits are still set. When an event occurs, switch over to
* polling to avoid losing status changes.
*/
- xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+ xhci_dbg(xhci, "%s: starting usb%d port polling.\n",
+ __func__, hcd->self.busnum);
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
spin_unlock(&xhci->lock);
/* Pass this up to the core */
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 627abd236dbe..a5da02077297 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -25,8 +25,6 @@
#include "xhci.h"
#include "xhci-dbgcap.h"
-#define XHCI_MSG_MAX 500
-
DECLARE_EVENT_CLASS(xhci_log_msg,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf),
@@ -122,6 +120,7 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
__field(u32, field1)
__field(u32, field2)
__field(u32, field3)
+ __dynamic_array(char, str, XHCI_MSG_MAX)
),
TP_fast_assign(
__entry->type = ring->type;
@@ -131,7 +130,7 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
__entry->field3 = le32_to_cpu(trb->field[3]);
),
TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
- xhci_decode_trb(__entry->field0, __entry->field1,
+ xhci_decode_trb(__get_str(str), XHCI_MSG_MAX, __entry->field0, __entry->field1,
__entry->field2, __entry->field3)
)
);
@@ -323,6 +322,7 @@ DECLARE_EVENT_CLASS(xhci_log_ep_ctx,
__field(u32, info2)
__field(u64, deq)
__field(u32, tx_info)
+ __dynamic_array(char, str, XHCI_MSG_MAX)
),
TP_fast_assign(
__entry->info = le32_to_cpu(ctx->ep_info);
@@ -330,8 +330,8 @@ DECLARE_EVENT_CLASS(xhci_log_ep_ctx,
__entry->deq = le64_to_cpu(ctx->deq);
__entry->tx_info = le32_to_cpu(ctx->tx_info);
),
- TP_printk("%s", xhci_decode_ep_context(__entry->info,
- __entry->info2, __entry->deq, __entry->tx_info)
+ TP_printk("%s", xhci_decode_ep_context(__get_str(str),
+ __entry->info, __entry->info2, __entry->deq, __entry->tx_info)
)
);
@@ -368,6 +368,7 @@ DECLARE_EVENT_CLASS(xhci_log_slot_ctx,
__field(u32, info2)
__field(u32, tt_info)
__field(u32, state)
+ __dynamic_array(char, str, XHCI_MSG_MAX)
),
TP_fast_assign(
__entry->info = le32_to_cpu(ctx->dev_info);
@@ -375,9 +376,9 @@ DECLARE_EVENT_CLASS(xhci_log_slot_ctx,
__entry->tt_info = le64_to_cpu(ctx->tt_info);
__entry->state = le32_to_cpu(ctx->dev_state);
),
- TP_printk("%s", xhci_decode_slot_context(__entry->info,
- __entry->info2, __entry->tt_info,
- __entry->state)
+ TP_printk("%s", xhci_decode_slot_context(__get_str(str),
+ __entry->info, __entry->info2,
+ __entry->tt_info, __entry->state)
)
);
@@ -432,12 +433,13 @@ DECLARE_EVENT_CLASS(xhci_log_ctrl_ctx,
TP_STRUCT__entry(
__field(u32, drop)
__field(u32, add)
+ __dynamic_array(char, str, XHCI_MSG_MAX)
),
TP_fast_assign(
__entry->drop = le32_to_cpu(ctrl_ctx->drop_flags);
__entry->add = le32_to_cpu(ctrl_ctx->add_flags);
),
- TP_printk("%s", xhci_decode_ctrl_ctx(__entry->drop, __entry->add)
+ TP_printk("%s", xhci_decode_ctrl_ctx(__get_str(str), __entry->drop, __entry->add)
)
);
@@ -523,6 +525,7 @@ DECLARE_EVENT_CLASS(xhci_log_portsc,
TP_STRUCT__entry(
__field(u32, portnum)
__field(u32, portsc)
+ __dynamic_array(char, str, XHCI_MSG_MAX)
),
TP_fast_assign(
__entry->portnum = portnum;
@@ -530,7 +533,7 @@ DECLARE_EVENT_CLASS(xhci_log_portsc,
),
TP_printk("port-%d: %s",
__entry->portnum,
- xhci_decode_portsc(__entry->portsc)
+ xhci_decode_portsc(__get_str(str), __entry->portsc)
)
);
@@ -555,13 +558,14 @@ DECLARE_EVENT_CLASS(xhci_log_doorbell,
TP_STRUCT__entry(
__field(u32, slot)
__field(u32, doorbell)
+ __dynamic_array(char, str, XHCI_MSG_MAX)
),
TP_fast_assign(
__entry->slot = slot;
__entry->doorbell = doorbell;
),
TP_printk("Ring doorbell for %s",
- xhci_decode_doorbell(__entry->slot, __entry->doorbell)
+ xhci_decode_doorbell(__get_str(str), __entry->slot, __entry->doorbell)
)
);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 3618070eba78..f3dabd02382c 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -993,7 +993,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
xhci_dbc_suspend(xhci);
/* Don't poll the roothubs on bus suspend. */
- xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
+ xhci_dbg(xhci, "%s: stopping usb%d port polling.\n",
+ __func__, hcd->self.busnum);
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
del_timer_sync(&hcd->rh_timer);
clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
@@ -1257,7 +1258,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
usb_asmedia_modifyflowcontrol(to_pci_dev(hcd->self.controller));
/* Re-enable port polling. */
- xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+ xhci_dbg(xhci, "%s: starting usb%d port polling.\n",
+ __func__, hcd->self.busnum);
set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
usb_hcd_poll_rh_status(xhci->shared_hcd);
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
@@ -4705,19 +4707,19 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
{
unsigned long long timeout_ns;
- if (xhci->quirks & XHCI_INTEL_HOST)
- timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
- else
- timeout_ns = udev->u1_params.sel;
-
/* Prevent U1 if service interval is shorter than U1 exit latency */
if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
- if (xhci_service_interval_to_ns(desc) <= timeout_ns) {
+ if (xhci_service_interval_to_ns(desc) <= udev->u1_params.mel) {
dev_dbg(&udev->dev, "Disable U1, ESIT shorter than exit latency\n");
return USB3_LPM_DISABLED;
}
}
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
+ else
+ timeout_ns = udev->u1_params.sel;
+
/* The U1 timeout is encoded in 1us intervals.
* Don't return a timeout of zero, because that's USB3_LPM_DISABLED.
*/
@@ -4769,19 +4771,19 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
{
unsigned long long timeout_ns;
- if (xhci->quirks & XHCI_INTEL_HOST)
- timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
- else
- timeout_ns = udev->u2_params.sel;
-
/* Prevent U2 if service interval is shorter than U2 exit latency */
if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
- if (xhci_service_interval_to_ns(desc) <= timeout_ns) {
+ if (xhci_service_interval_to_ns(desc) <= udev->u2_params.mel) {
dev_dbg(&udev->dev, "Disable U2, ESIT shorter than exit latency\n");
return USB3_LPM_DISABLED;
}
}
+ if (xhci->quirks & XHCI_INTEL_HOST)
+ timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
+ else
+ timeout_ns = udev->u2_params.sel;
+
/* The U2 timeout is encoded in 256us intervals */
timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000);
/* If the necessary timeout value is bigger than what we can set in the
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3c7d281672ae..dca6181c33fd 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -22,6 +22,9 @@
#include "xhci-ext-caps.h"
#include "pci-quirks.h"
+/* max buffer size for trace and debug messages */
+#define XHCI_MSG_MAX 500
+
/* xHCI PCI Configuration Registers */
#define XHCI_SBRN_OFFSET (0x60)
@@ -2235,15 +2238,14 @@ static inline char *xhci_slot_state_string(u32 state)
}
}
-static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
- u32 field3)
+static inline const char *xhci_decode_trb(char *str, size_t size,
+ u32 field0, u32 field1, u32 field2, u32 field3)
{
- static char str[256];
int type = TRB_FIELD_TO_TYPE(field3);
switch (type) {
case TRB_LINK:
- sprintf(str,
+ snprintf(str, size,
"LINK %08x%08x intr %d type '%s' flags %c:%c:%c:%c",
field1, field0, GET_INTR_TARGET(field2),
xhci_trb_type_string(type),
@@ -2260,7 +2262,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_HC_EVENT:
case TRB_DEV_NOTE:
case TRB_MFINDEX_WRAP:
- sprintf(str,
+ snprintf(str, size,
"TRB %08x%08x status '%s' len %d slot %d ep %d type '%s' flags %c:%c",
field1, field0,
xhci_trb_comp_code_string(GET_COMP_CODE(field2)),
@@ -2273,7 +2275,8 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
break;
case TRB_SETUP:
- sprintf(str, "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c",
+ snprintf(str, size,
+ "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c",
field0 & 0xff,
(field0 & 0xff00) >> 8,
(field0 & 0xff000000) >> 24,
@@ -2290,7 +2293,8 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_DATA:
- sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c",
+ snprintf(str, size,
+ "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c",
field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
GET_INTR_TARGET(field2),
xhci_trb_type_string(type),
@@ -2303,7 +2307,8 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_STATUS:
- sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c",
+ snprintf(str, size,
+ "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c",
field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
GET_INTR_TARGET(field2),
xhci_trb_type_string(type),
@@ -2316,7 +2321,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_ISOC:
case TRB_EVENT_DATA:
case TRB_TR_NOOP:
- sprintf(str,
+ snprintf(str, size,
"Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c:%c",
field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
GET_INTR_TARGET(field2),
@@ -2333,21 +2338,21 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_CMD_NOOP:
case TRB_ENABLE_SLOT:
- sprintf(str,
+ snprintf(str, size,
"%s: flags %c",
xhci_trb_type_string(type),
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_DISABLE_SLOT:
case TRB_NEG_BANDWIDTH:
- sprintf(str,
+ snprintf(str, size,
"%s: slot %d flags %c",
xhci_trb_type_string(type),
TRB_TO_SLOT_ID(field3),
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_ADDR_DEV:
- sprintf(str,
+ snprintf(str, size,
"%s: ctx %08x%08x slot %d flags %c:%c",
xhci_trb_type_string(type),
field1, field0,
@@ -2356,7 +2361,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_CONFIG_EP:
- sprintf(str,
+ snprintf(str, size,
"%s: ctx %08x%08x slot %d flags %c:%c",
xhci_trb_type_string(type),
field1, field0,
@@ -2365,7 +2370,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_EVAL_CONTEXT:
- sprintf(str,
+ snprintf(str, size,
"%s: ctx %08x%08x slot %d flags %c",
xhci_trb_type_string(type),
field1, field0,
@@ -2373,7 +2378,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_RESET_EP:
- sprintf(str,
+ snprintf(str, size,
"%s: ctx %08x%08x slot %d ep %d flags %c:%c",
xhci_trb_type_string(type),
field1, field0,
@@ -2394,7 +2399,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_SET_DEQ:
- sprintf(str,
+ snprintf(str, size,
"%s: deq %08x%08x stream %d slot %d ep %d flags %c",
xhci_trb_type_string(type),
field1, field0,
@@ -2405,14 +2410,14 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_RESET_DEV:
- sprintf(str,
+ snprintf(str, size,
"%s: slot %d flags %c",
xhci_trb_type_string(type),
TRB_TO_SLOT_ID(field3),
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_FORCE_EVENT:
- sprintf(str,
+ snprintf(str, size,
"%s: event %08x%08x vf intr %d vf id %d flags %c",
xhci_trb_type_string(type),
field1, field0,
@@ -2421,14 +2426,14 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_SET_LT:
- sprintf(str,
+ snprintf(str, size,
"%s: belt %d flags %c",
xhci_trb_type_string(type),
TRB_TO_BELT(field3),
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_GET_BW:
- sprintf(str,
+ snprintf(str, size,
"%s: ctx %08x%08x slot %d speed %d flags %c",
xhci_trb_type_string(type),
field1, field0,
@@ -2437,7 +2442,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_FORCE_HEADER:
- sprintf(str,
+ snprintf(str, size,
"%s: info %08x%08x%08x pkt type %d roothub port %d flags %c",
xhci_trb_type_string(type),
field2, field1, field0 & 0xffffffe0,
@@ -2446,7 +2451,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
default:
- sprintf(str,
+ snprintf(str, size,
"type '%s' -> raw %08x %08x %08x %08x",
xhci_trb_type_string(type),
field0, field1, field2, field3);
@@ -2455,10 +2460,9 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
return str;
}
-static inline const char *xhci_decode_ctrl_ctx(unsigned long drop,
- unsigned long add)
+static inline const char *xhci_decode_ctrl_ctx(char *str,
+ unsigned long drop, unsigned long add)
{
- static char str[1024];
unsigned int bit;
int ret = 0;
@@ -2484,10 +2488,9 @@ static inline const char *xhci_decode_ctrl_ctx(unsigned long drop,
return str;
}
-static inline const char *xhci_decode_slot_context(u32 info, u32 info2,
- u32 tt_info, u32 state)
+static inline const char *xhci_decode_slot_context(char *str,
+ u32 info, u32 info2, u32 tt_info, u32 state)
{
- static char str[1024];
u32 speed;
u32 hub;
u32 mtt;
@@ -2571,9 +2574,8 @@ static inline const char *xhci_portsc_link_state_string(u32 portsc)
return "Unknown";
}
-static inline const char *xhci_decode_portsc(u32 portsc)
+static inline const char *xhci_decode_portsc(char *str, u32 portsc)
{
- static char str[256];
int ret;
ret = sprintf(str, "%s %s %s Link:%s PortSpeed:%d ",
@@ -2617,9 +2619,8 @@ static inline const char *xhci_decode_portsc(u32 portsc)
return str;
}
-static inline const char *xhci_decode_usbsts(u32 usbsts)
+static inline const char *xhci_decode_usbsts(char *str, u32 usbsts)
{
- static char str[256];
int ret = 0;
if (usbsts == ~(u32)0)
@@ -2646,9 +2647,8 @@ static inline const char *xhci_decode_usbsts(u32 usbsts)
return str;
}
-static inline const char *xhci_decode_doorbell(u32 slot, u32 doorbell)
+static inline const char *xhci_decode_doorbell(char *str, u32 slot, u32 doorbell)
{
- static char str[256];
u8 ep;
u16 stream;
int ret;
@@ -2715,10 +2715,9 @@ static inline const char *xhci_ep_type_string(u8 type)
}
}
-static inline const char *xhci_decode_ep_context(u32 info, u32 info2, u64 deq,
- u32 tx_info)
+static inline const char *xhci_decode_ep_context(char *str, u32 info,
+ u32 info2, u64 deq, u32 tx_info)
{
- static char str[1024];
int ret;
u32 esit;
diff --git a/drivers/usb/isp1760/isp1760-core.c b/drivers/usb/isp1760/isp1760-core.c
index ff07e2890692..d1d9a7d5da17 100644
--- a/drivers/usb/isp1760/isp1760-core.c
+++ b/drivers/usb/isp1760/isp1760-core.c
@@ -30,6 +30,7 @@ static int isp1760_init_core(struct isp1760_device *isp)
{
struct isp1760_hcd *hcd = &isp->hcd;
struct isp1760_udc *udc = &isp->udc;
+ u32 otg_ctrl;
/* Low-level chip reset */
if (isp->rst_gpio) {
@@ -83,16 +84,17 @@ static int isp1760_init_core(struct isp1760_device *isp)
*
* TODO: Really support OTG. For now we configure port 1 in device mode
*/
- if (((isp->devflags & ISP1760_FLAG_ISP1761) ||
- (isp->devflags & ISP1760_FLAG_ISP1763)) &&
- (isp->devflags & ISP1760_FLAG_PERIPHERAL_EN)) {
- isp1760_field_set(hcd->fields, HW_DM_PULLDOWN);
- isp1760_field_set(hcd->fields, HW_DP_PULLDOWN);
- isp1760_field_set(hcd->fields, HW_OTG_DISABLE);
- } else {
- isp1760_field_set(hcd->fields, HW_SW_SEL_HC_DC);
- isp1760_field_set(hcd->fields, HW_VBUS_DRV);
- isp1760_field_set(hcd->fields, HW_SEL_CP_EXT);
+ if (isp->devflags & ISP1760_FLAG_ISP1761) {
+ if (isp->devflags & ISP1760_FLAG_PERIPHERAL_EN) {
+ otg_ctrl = (ISP176x_HW_DM_PULLDOWN_CLEAR |
+ ISP176x_HW_DP_PULLDOWN_CLEAR |
+ ISP176x_HW_OTG_DISABLE);
+ } else {
+ otg_ctrl = (ISP176x_HW_SW_SEL_HC_DC_CLEAR |
+ ISP176x_HW_VBUS_DRV |
+ ISP176x_HW_SEL_CP_EXT);
+ }
+ isp1760_reg_write(hcd->regs, ISP176x_HC_OTG_CTRL, otg_ctrl);
}
dev_info(isp->dev, "%s bus width: %u, oc: %s\n",
@@ -235,20 +237,20 @@ static const struct reg_field isp1760_hc_reg_fields[] = {
[HC_ISO_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_AND, 0, 31),
[HC_INT_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_AND, 0, 31),
[HC_ATL_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_AND, 0, 31),
- [HW_OTG_DISABLE] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 10, 10),
- [HW_SW_SEL_HC_DC] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 7, 7),
- [HW_VBUS_DRV] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 4, 4),
- [HW_SEL_CP_EXT] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 3, 3),
- [HW_DM_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 2, 2),
- [HW_DP_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 1, 1),
- [HW_DP_PULLUP] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 0, 0),
- [HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 10, 10),
- [HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 7, 7),
- [HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 4, 4),
- [HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 3, 3),
- [HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 2, 2),
- [HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 1, 1),
- [HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 0, 0),
+ [HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL, 26, 26),
+ [HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL, 23, 23),
+ [HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL, 20, 20),
+ [HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL, 19, 19),
+ [HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL, 18, 18),
+ [HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL, 17, 17),
+ [HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL, 16, 16),
+ [HW_OTG_DISABLE] = REG_FIELD(ISP176x_HC_OTG_CTRL, 10, 10),
+ [HW_SW_SEL_HC_DC] = REG_FIELD(ISP176x_HC_OTG_CTRL, 7, 7),
+ [HW_VBUS_DRV] = REG_FIELD(ISP176x_HC_OTG_CTRL, 4, 4),
+ [HW_SEL_CP_EXT] = REG_FIELD(ISP176x_HC_OTG_CTRL, 3, 3),
+ [HW_DM_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL, 2, 2),
+ [HW_DP_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL, 1, 1),
+ [HW_DP_PULLUP] = REG_FIELD(ISP176x_HC_OTG_CTRL, 0, 0),
};
static const struct reg_field isp1763_hc_reg_fields[] = {
@@ -491,7 +493,7 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
(devflags & ISP1760_FLAG_ISP1761));
if ((!IS_ENABLED(CONFIG_USB_ISP1760_HCD) || usb_disabled()) &&
- (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || !udc_enabled))
+ (!udc_enabled || !IS_ENABLED(CONFIG_USB_ISP1761_UDC)))
return -ENODEV;
isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL);
@@ -571,7 +573,7 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
return ret;
}
- if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) && udc_enabled) {
+ if (udc_enabled && IS_ENABLED(CONFIG_USB_ISP1761_UDC)) {
ret = isp1760_udc_register(isp, irq, irqflags);
if (ret < 0) {
isp1760_hcd_unregister(hcd);
diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c
index 27168b4a4ef2..79d571f1429b 100644
--- a/drivers/usb/isp1760/isp1760-hcd.c
+++ b/drivers/usb/isp1760/isp1760-hcd.c
@@ -182,7 +182,7 @@ struct urb_listitem {
struct urb *urb;
};
-static const u32 isp1763_hc_portsc1_fields[] = {
+static const u32 isp176x_hc_portsc1_fields[] = {
[PORT_OWNER] = BIT(13),
[PORT_POWER] = BIT(12),
[PORT_LSTATUS] = BIT(10),
@@ -205,27 +205,28 @@ static u32 isp1760_hcd_read(struct usb_hcd *hcd, u32 field)
}
/*
- * We need, in isp1763, to write directly the values to the portsc1
+ * We need, in isp176x, to write directly the values to the portsc1
* register so it will make the other values to trigger.
*/
static void isp1760_hcd_portsc1_set_clear(struct isp1760_hcd *priv, u32 field,
u32 val)
{
- u32 bit = isp1763_hc_portsc1_fields[field];
- u32 port_status = readl(priv->base + ISP1763_HC_PORTSC1);
+ u32 bit = isp176x_hc_portsc1_fields[field];
+ u16 portsc1_reg = priv->is_isp1763 ? ISP1763_HC_PORTSC1 :
+ ISP176x_HC_PORTSC1;
+ u32 port_status = readl(priv->base + portsc1_reg);
if (val)
- writel(port_status | bit, priv->base + ISP1763_HC_PORTSC1);
+ writel(port_status | bit, priv->base + portsc1_reg);
else
- writel(port_status & ~bit, priv->base + ISP1763_HC_PORTSC1);
+ writel(port_status & ~bit, priv->base + portsc1_reg);
}
static void isp1760_hcd_write(struct usb_hcd *hcd, u32 field, u32 val)
{
struct isp1760_hcd *priv = hcd_to_priv(hcd);
- if (unlikely(priv->is_isp1763 &&
- (field >= PORT_OWNER && field <= PORT_CONNECT)))
+ if (unlikely((field >= PORT_OWNER && field <= PORT_CONNECT)))
return isp1760_hcd_portsc1_set_clear(priv, field, val);
isp1760_field_write(priv->fields, field, val);
@@ -250,7 +251,7 @@ static int isp1760_hcd_set_and_wait(struct usb_hcd *hcd, u32 field,
isp1760_hcd_set(hcd, field);
return regmap_field_read_poll_timeout(priv->fields[field], val,
- val, 10, timeout_us);
+ val, 0, timeout_us);
}
static int isp1760_hcd_set_and_wait_swap(struct usb_hcd *hcd, u32 field,
@@ -262,7 +263,7 @@ static int isp1760_hcd_set_and_wait_swap(struct usb_hcd *hcd, u32 field,
isp1760_hcd_set(hcd, field);
return regmap_field_read_poll_timeout(priv->fields[field], val,
- !val, 10, timeout_us);
+ !val, 0, timeout_us);
}
static int isp1760_hcd_clear_and_wait(struct usb_hcd *hcd, u32 field,
@@ -274,7 +275,7 @@ static int isp1760_hcd_clear_and_wait(struct usb_hcd *hcd, u32 field,
isp1760_hcd_clear(hcd, field);
return regmap_field_read_poll_timeout(priv->fields[field], val,
- !val, 10, timeout_us);
+ !val, 0, timeout_us);
}
static bool isp1760_hcd_is_set(struct usb_hcd *hcd, u32 field)
@@ -367,8 +368,7 @@ static void isp1760_mem_read(struct usb_hcd *hcd, u32 src_offset, void *dst,
{
struct isp1760_hcd *priv = hcd_to_priv(hcd);
- isp1760_hcd_write(hcd, MEM_BANK_SEL, ISP_BANK_0);
- isp1760_hcd_write(hcd, MEM_START_ADDR, src_offset);
+ isp1760_reg_write(priv->regs, ISP176x_HC_MEMORY, src_offset);
ndelay(100);
bank_reads8(priv->base, src_offset, ISP_BANK_0, dst, bytes);
@@ -496,8 +496,7 @@ static void isp1760_ptd_read(struct usb_hcd *hcd, u32 ptd_offset, u32 slot,
u16 src_offset = ptd_offset + slot * sizeof(*ptd);
struct isp1760_hcd *priv = hcd_to_priv(hcd);
- isp1760_hcd_write(hcd, MEM_BANK_SEL, ISP_BANK_0);
- isp1760_hcd_write(hcd, MEM_START_ADDR, src_offset);
+ isp1760_reg_write(priv->regs, ISP176x_HC_MEMORY, src_offset);
ndelay(90);
bank_reads8(priv->base, src_offset, ISP_BANK_0, (void *)ptd,
@@ -588,8 +587,8 @@ static void init_memory(struct isp1760_hcd *priv)
payload_addr = PAYLOAD_OFFSET;
- for (i = 0, curr = 0; i < ARRAY_SIZE(mem->blocks); i++) {
- for (j = 0; j < mem->blocks[i]; j++, curr++) {
+ for (i = 0, curr = 0; i < ARRAY_SIZE(mem->blocks); i++, curr += j) {
+ for (j = 0; j < mem->blocks[i]; j++) {
priv->memory_pool[curr + j].start = payload_addr;
priv->memory_pool[curr + j].size = mem->blocks_size[i];
priv->memory_pool[curr + j].free = 1;
@@ -731,12 +730,15 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
isp1760_hcd_write(hcd, HC_SCRATCH, pattern);
- /* Change bus pattern */
- scratch = isp1760_hcd_read(hcd, HC_CHIP_ID_HIGH);
- dev_err(hcd->self.controller, "Scratch test 0x%08x\n", scratch);
+ /*
+ * we do not care about the read value here we just want to
+ * change bus pattern.
+ */
+ isp1760_hcd_read(hcd, HC_CHIP_ID_HIGH);
scratch = isp1760_hcd_read(hcd, HC_SCRATCH);
if (scratch != pattern) {
- dev_err(hcd->self.controller, "Scratch test failed. 0x%08x\n", scratch);
+ dev_err(hcd->self.controller, "Scratch test failed. 0x%08x\n",
+ scratch);
return -ENODEV;
}
@@ -1826,9 +1828,11 @@ static void packetize_urb(struct usb_hcd *hcd,
goto cleanup;
if (len > mem->blocks_size[ISP176x_BLOCK_NUM - 1])
- len = mem->blocks_size[ISP176x_BLOCK_NUM - 1];
+ this_qtd_len = mem->blocks_size[ISP176x_BLOCK_NUM - 1];
+ else
+ this_qtd_len = len;
- this_qtd_len = qtd_fill(qtd, buf, len);
+ this_qtd_len = qtd_fill(qtd, buf, this_qtd_len);
list_add_tail(&qtd->qtd_list, head);
len -= this_qtd_len;
@@ -1851,7 +1855,7 @@ static void packetize_urb(struct usb_hcd *hcd,
packet_type = OUT_PID;
else
packet_type = IN_PID;
- } else if (usb_pipebulk(urb->pipe)
+ } else if (usb_pipebulk(urb->pipe) && maxpacketsize
&& (urb->transfer_flags & URB_ZERO_PACKET)
&& !(urb->transfer_buffer_length %
maxpacketsize)) {
@@ -1916,7 +1920,6 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
if (list_empty(&new_qtds))
return -ENOMEM;
- retval = 0;
spin_lock_irqsave(&priv->lock, spinflags);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
@@ -1972,16 +1975,20 @@ static void kill_transfer(struct usb_hcd *hcd, struct urb *urb,
/* We need to forcefully reclaim the slot since some transfers never
return, e.g. interrupt transfers and NAKed bulk transfers. */
if (usb_pipecontrol(urb->pipe) || usb_pipebulk(urb->pipe)) {
- skip_map = isp1760_hcd_read(hcd, HC_ATL_PTD_SKIPMAP);
- skip_map |= (1 << qh->slot);
- isp1760_hcd_write(hcd, HC_ATL_PTD_SKIPMAP, skip_map);
- ndelay(100);
+ if (qh->slot != -1) {
+ skip_map = isp1760_hcd_read(hcd, HC_ATL_PTD_SKIPMAP);
+ skip_map |= (1 << qh->slot);
+ isp1760_hcd_write(hcd, HC_ATL_PTD_SKIPMAP, skip_map);
+ ndelay(100);
+ }
priv->atl_slots[qh->slot].qh = NULL;
priv->atl_slots[qh->slot].qtd = NULL;
} else {
- skip_map = isp1760_hcd_read(hcd, HC_INT_PTD_SKIPMAP);
- skip_map |= (1 << qh->slot);
- isp1760_hcd_write(hcd, HC_INT_PTD_SKIPMAP, skip_map);
+ if (qh->slot != -1) {
+ skip_map = isp1760_hcd_read(hcd, HC_INT_PTD_SKIPMAP);
+ skip_map |= (1 << qh->slot);
+ isp1760_hcd_write(hcd, HC_INT_PTD_SKIPMAP, skip_map);
+ }
priv->int_slots[qh->slot].qh = NULL;
priv->int_slots[qh->slot].qtd = NULL;
}
@@ -2528,17 +2535,23 @@ int __init isp1760_init_kmem_once(void)
SLAB_MEM_SPREAD, NULL);
if (!qtd_cachep)
- return -ENOMEM;
+ goto destroy_urb_listitem;
qh_cachep = kmem_cache_create("isp1760_qh", sizeof(struct isp1760_qh),
0, SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL);
- if (!qh_cachep) {
- kmem_cache_destroy(qtd_cachep);
- return -ENOMEM;
- }
+ if (!qh_cachep)
+ goto destroy_qtd;
return 0;
+
+destroy_qtd:
+ kmem_cache_destroy(qtd_cachep);
+
+destroy_urb_listitem:
+ kmem_cache_destroy(urb_listitem_cachep);
+
+ return -ENOMEM;
}
void isp1760_deinit_kmem_cache(void)
diff --git a/drivers/usb/isp1760/isp1760-regs.h b/drivers/usb/isp1760/isp1760-regs.h
index 94ea60c20b2a..3a6751197e97 100644
--- a/drivers/usb/isp1760/isp1760-regs.h
+++ b/drivers/usb/isp1760/isp1760-regs.h
@@ -61,6 +61,7 @@
#define ISP176x_HC_INT_IRQ_MASK_AND 0x328
#define ISP176x_HC_ATL_IRQ_MASK_AND 0x32c
+#define ISP176x_HC_OTG_CTRL 0x374
#define ISP176x_HC_OTG_CTRL_SET 0x374
#define ISP176x_HC_OTG_CTRL_CLEAR 0x376
@@ -179,6 +180,21 @@ enum isp176x_host_controller_fields {
#define ISP176x_DC_IESUSP BIT(3)
#define ISP176x_DC_IEBRST BIT(0)
+#define ISP176x_HW_OTG_DISABLE_CLEAR BIT(26)
+#define ISP176x_HW_SW_SEL_HC_DC_CLEAR BIT(23)
+#define ISP176x_HW_VBUS_DRV_CLEAR BIT(20)
+#define ISP176x_HW_SEL_CP_EXT_CLEAR BIT(19)
+#define ISP176x_HW_DM_PULLDOWN_CLEAR BIT(18)
+#define ISP176x_HW_DP_PULLDOWN_CLEAR BIT(17)
+#define ISP176x_HW_DP_PULLUP_CLEAR BIT(16)
+#define ISP176x_HW_OTG_DISABLE BIT(10)
+#define ISP176x_HW_SW_SEL_HC_DC BIT(7)
+#define ISP176x_HW_VBUS_DRV BIT(4)
+#define ISP176x_HW_SEL_CP_EXT BIT(3)
+#define ISP176x_HW_DM_PULLDOWN BIT(2)
+#define ISP176x_HW_DP_PULLDOWN BIT(1)
+#define ISP176x_HW_DP_PULLUP BIT(0)
+
#define ISP176x_DC_ENDPTYP_ISOC 0x01
#define ISP176x_DC_ENDPTYP_BULK 0x02
#define ISP176x_DC_ENDPTYP_INTERRUPT 0x03
diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c
index a78da59d6417..5cafd23345ca 100644
--- a/drivers/usb/isp1760/isp1760-udc.c
+++ b/drivers/usb/isp1760/isp1760-udc.c
@@ -1363,7 +1363,7 @@ static irqreturn_t isp1760_udc_irq(int irq, void *dev)
status = isp1760_udc_irq_get_status(udc);
- if (status & DC_IEVBUS) {
+ if (status & ISP176x_DC_IEVBUS) {
dev_dbg(udc->isp->dev, "%s(VBUS)\n", __func__);
/* The VBUS interrupt is only triggered when VBUS appears. */
spin_lock(&udc->lock);
@@ -1371,7 +1371,7 @@ static irqreturn_t isp1760_udc_irq(int irq, void *dev)
spin_unlock(&udc->lock);
}
- if (status & DC_IEBRST) {
+ if (status & ISP176x_DC_IEBRST) {
dev_dbg(udc->isp->dev, "%s(BRST)\n", __func__);
isp1760_udc_reset(udc);
@@ -1391,18 +1391,18 @@ static irqreturn_t isp1760_udc_irq(int irq, void *dev)
}
}
- if (status & DC_IEP0SETUP) {
+ if (status & ISP176x_DC_IEP0SETUP) {
dev_dbg(udc->isp->dev, "%s(EP0SETUP)\n", __func__);
isp1760_ep0_setup(udc);
}
- if (status & DC_IERESM) {
+ if (status & ISP176x_DC_IERESM) {
dev_dbg(udc->isp->dev, "%s(RESM)\n", __func__);
isp1760_udc_resume(udc);
}
- if (status & DC_IESUSP) {
+ if (status & ISP176x_DC_IESUSP) {
dev_dbg(udc->isp->dev, "%s(SUSP)\n", __func__);
spin_lock(&udc->lock);
@@ -1413,7 +1413,7 @@ static irqreturn_t isp1760_udc_irq(int irq, void *dev)
spin_unlock(&udc->lock);
}
- if (status & DC_IEHS_STA) {
+ if (status & ISP176x_DC_IEHS_STA) {
dev_dbg(udc->isp->dev, "%s(HS_STA)\n", __func__);
udc->gadget.speed = USB_SPEED_HIGH;
}
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 6d15a097b007..ed6a19254d2f 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -394,13 +394,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
spin_lock_irqsave (&dev->buflock, flags);
if (dev->read_buffer_length) {
/* we secure access to the primary */
- char *tmp;
dev_dbg(&dev->udev->dev,
"%s : swap, read_buffer_length = %d\n",
__func__, dev->read_buffer_length);
- tmp = dev->read_buffer_secondary;
- dev->read_buffer_secondary = dev->read_buffer_primary;
- dev->read_buffer_primary = tmp;
+ swap(dev->read_buffer_primary, dev->read_buffer_secondary);
dev->secondary_head = 0;
dev->secondary_tail = dev->read_buffer_length;
dev->read_buffer_length = 0;
diff --git a/drivers/usb/misc/brcmstb-usb-pinmap.c b/drivers/usb/misc/brcmstb-usb-pinmap.c
index 336653091e3b..2b2019c19cde 100644
--- a/drivers/usb/misc/brcmstb-usb-pinmap.c
+++ b/drivers/usb/misc/brcmstb-usb-pinmap.c
@@ -293,6 +293,8 @@ static int __init brcmstb_usb_pinmap_probe(struct platform_device *pdev)
/* Enable interrupt for out pins */
irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
err = devm_request_irq(&pdev->dev, irq,
brcmstb_usb_pinmap_ovr_isr,
IRQF_TRIGGER_RISING,
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
index 5546b868b08b..022bbdc54e68 100644
--- a/drivers/usb/mtu3/mtu3.h
+++ b/drivers/usb/mtu3/mtu3.h
@@ -199,6 +199,7 @@ struct mtu3_gpd_ring {
* @id_nb : notifier for iddig(idpin) detection
* @dr_work : work for drd mode switch, used to avoid sleep in atomic context
* @desired_role : role desired to switch
+* @default_role : default mode while usb role is USB_ROLE_NONE
* @role_sw : use USB Role Switch to support dual-role switch, can't use
* extcon at the same time, and extcon is deprecated.
* @role_sw_used : true when the USB Role Switch is used.
@@ -212,6 +213,7 @@ struct otg_switch_mtk {
struct notifier_block id_nb;
struct work_struct dr_work;
enum usb_role desired_role;
+ enum usb_role default_role;
struct usb_role_switch *role_sw;
bool role_sw_used;
bool is_u3_drd;
@@ -226,6 +228,9 @@ struct otg_switch_mtk {
* host only, device only or dual-role mode
* @u2_ports: number of usb2.0 host ports
* @u3_ports: number of usb3.0 host ports
+ * @u2p_dis_msk: mask of disabling usb2 ports, e.g. bit0==1 to
+ * disable u2port0, bit1==1 to disable u2port1,... etc,
+ * but when use dual-role mode, can't disable u2port0
* @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to
* disable u3port0, bit1==1 to disable u3port1,... etc
* @dbgfs_root: only used when supports manual dual-role switch via debugfs
@@ -241,6 +246,7 @@ struct ssusb_mtk {
void __iomem *ippc_base;
struct phy **phys;
int num_phys;
+ int wakeup_irq;
/* common power & clock */
struct regulator *vusb33;
struct clk_bulk_data clks[BULK_CLKS_CNT];
@@ -250,6 +256,7 @@ struct ssusb_mtk {
bool is_host;
int u2_ports;
int u3_ports;
+ int u2p_dis_msk;
int u3p_dis_msk;
struct dentry *dbgfs_root;
/* usb wakeup for host mode */
@@ -349,6 +356,7 @@ struct mtu3 {
unsigned is_u3_ip:1;
unsigned delayed_status:1;
unsigned gen2cp:1;
+ unsigned connected:1;
u8 address;
u8 test_mode_nr;
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c
index 562f4357831e..c4a2c37abf62 100644
--- a/drivers/usb/mtu3/mtu3_core.c
+++ b/drivers/usb/mtu3/mtu3_core.c
@@ -141,6 +141,28 @@ static void mtu3_device_disable(struct mtu3 *mtu)
mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
}
+static void mtu3_dev_power_on(struct mtu3 *mtu)
+{
+ void __iomem *ibase = mtu->ippc_base;
+
+ mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
+ if (mtu->is_u3_ip)
+ mtu3_clrbits(ibase, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_PDN);
+
+ mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_PDN);
+}
+
+static void mtu3_dev_power_down(struct mtu3 *mtu)
+{
+ void __iomem *ibase = mtu->ippc_base;
+
+ if (mtu->is_u3_ip)
+ mtu3_setbits(ibase, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_PDN);
+
+ mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_PDN);
+ mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
+}
+
/* reset U3D's device module. */
static void mtu3_device_reset(struct mtu3 *mtu)
{
@@ -227,11 +249,13 @@ static void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed)
mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE);
break;
case USB_SPEED_SUPER:
+ mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE);
mtu3_clrbits(mtu->ippc_base, SSUSB_U3_CTRL(0),
SSUSB_U3_PORT_SSP_SPEED);
break;
case USB_SPEED_SUPER_PLUS:
- mtu3_setbits(mtu->ippc_base, SSUSB_U3_CTRL(0),
+ mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE);
+ mtu3_setbits(mtu->ippc_base, SSUSB_U3_CTRL(0),
SSUSB_U3_PORT_SSP_SPEED);
break;
default:
@@ -333,12 +357,7 @@ void mtu3_start(struct mtu3 *mtu)
dev_dbg(mtu->dev, "%s devctl 0x%x\n", __func__,
mtu3_readl(mbase, U3D_DEVICE_CONTROL));
- mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
- if (mtu->is_u3_ip)
- mtu3_clrbits(mtu->ippc_base, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_PDN);
-
- mtu3_clrbits(mtu->ippc_base, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_PDN);
-
+ mtu3_dev_power_on(mtu);
mtu3_csr_init(mtu);
mtu3_set_speed(mtu, mtu->speed);
@@ -360,12 +379,25 @@ void mtu3_stop(struct mtu3 *mtu)
mtu3_dev_on_off(mtu, 0);
mtu->is_active = 0;
+ mtu3_dev_power_down(mtu);
+}
- if (mtu->is_u3_ip)
- mtu3_setbits(mtu->ippc_base, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_PDN);
+static void mtu3_dev_suspend(struct mtu3 *mtu)
+{
+ if (!mtu->is_active)
+ return;
- mtu3_setbits(mtu->ippc_base, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_PDN);
- mtu3_setbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
+ mtu3_intr_disable(mtu);
+ mtu3_dev_power_down(mtu);
+}
+
+static void mtu3_dev_resume(struct mtu3 *mtu)
+{
+ if (!mtu->is_active)
+ return;
+
+ mtu3_dev_power_on(mtu);
+ mtu3_intr_enable(mtu);
}
/* for non-ep0 */
@@ -688,11 +720,15 @@ static irqreturn_t mtu3_link_isr(struct mtu3 *mtu)
mtu->g.speed = udev_speed;
mtu->g.ep0->maxpacket = maxpkt;
mtu->ep0_state = MU3D_EP0_STATE_SETUP;
+ mtu->connected = !!(udev_speed != USB_SPEED_UNKNOWN);
- if (udev_speed == USB_SPEED_UNKNOWN)
+ if (udev_speed == USB_SPEED_UNKNOWN) {
mtu3_gadget_disconnect(mtu);
- else
+ pm_runtime_put(mtu->dev);
+ } else {
+ pm_runtime_get(mtu->dev);
mtu3_ep0_setup(mtu);
+ }
return IRQ_HANDLED;
}
@@ -888,9 +924,16 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb)
if (mtu == NULL)
return -ENOMEM;
- mtu->irq = platform_get_irq(pdev, 0);
- if (mtu->irq < 0)
- return mtu->irq;
+ mtu->irq = platform_get_irq_byname_optional(pdev, "device");
+ if (mtu->irq < 0) {
+ if (mtu->irq == -EPROBE_DEFER)
+ return mtu->irq;
+
+ /* for backward compatibility */
+ mtu->irq = platform_get_irq(pdev, 0);
+ if (mtu->irq < 0)
+ return mtu->irq;
+ }
dev_info(dev, "irq %d\n", mtu->irq);
mtu->mac_base = devm_platform_ioremap_resource_byname(pdev, "mac");
@@ -965,3 +1008,47 @@ void ssusb_gadget_exit(struct ssusb_mtk *ssusb)
device_init_wakeup(ssusb->dev, false);
mtu3_hw_exit(mtu);
}
+
+bool ssusb_gadget_ip_sleep_check(struct ssusb_mtk *ssusb)
+{
+ struct mtu3 *mtu = ssusb->u3d;
+
+ /* host only, should wait for ip sleep */
+ if (!mtu)
+ return true;
+
+ /* device is started and pullup D+, ip can sleep */
+ if (mtu->is_active && mtu->softconnect)
+ return true;
+
+ /* ip can't sleep if not pullup D+ when support device mode */
+ return false;
+}
+
+int ssusb_gadget_suspend(struct ssusb_mtk *ssusb, pm_message_t msg)
+{
+ struct mtu3 *mtu = ssusb->u3d;
+
+ if (!mtu->gadget_driver)
+ return 0;
+
+ if (mtu->connected)
+ return -EBUSY;
+
+ mtu3_dev_suspend(mtu);
+ synchronize_irq(mtu->irq);
+
+ return 0;
+}
+
+int ssusb_gadget_resume(struct ssusb_mtk *ssusb, pm_message_t msg)
+{
+ struct mtu3 *mtu = ssusb->u3d;
+
+ if (!mtu->gadget_driver)
+ return 0;
+
+ mtu3_dev_resume(mtu);
+
+ return 0;
+}
diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c
index 318fbc618137..a6b04831b20b 100644
--- a/drivers/usb/mtu3/mtu3_dr.c
+++ b/drivers/usb/mtu3/mtu3_dr.c
@@ -137,14 +137,19 @@ static void ssusb_mode_sw_work(struct work_struct *work)
current_role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE;
- if (desired_role == USB_ROLE_NONE)
+ if (desired_role == USB_ROLE_NONE) {
+ /* the default mode is host as probe does */
desired_role = USB_ROLE_HOST;
+ if (otg_sx->default_role == USB_ROLE_DEVICE)
+ desired_role = USB_ROLE_DEVICE;
+ }
if (current_role == desired_role)
return;
dev_dbg(ssusb->dev, "set role : %s\n", usb_role_string(desired_role));
mtu3_dbg_trace(ssusb->dev, "set role : %s", usb_role_string(desired_role));
+ pm_runtime_get_sync(ssusb->dev);
switch (desired_role) {
case USB_ROLE_HOST:
@@ -165,6 +170,7 @@ static void ssusb_mode_sw_work(struct work_struct *work)
default:
dev_err(ssusb->dev, "invalid role\n");
}
+ pm_runtime_put(ssusb->dev);
}
static void ssusb_set_mode(struct otg_switch_mtk *otg_sx, enum usb_role role)
@@ -274,17 +280,29 @@ static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx)
{
struct usb_role_switch_desc role_sx_desc = { 0 };
struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx);
+ struct device *dev = ssusb->dev;
+ enum usb_dr_mode mode;
if (!otg_sx->role_sw_used)
return 0;
+ mode = usb_get_role_switch_default_mode(dev);
+ if (mode == USB_DR_MODE_PERIPHERAL)
+ otg_sx->default_role = USB_ROLE_DEVICE;
+ else
+ otg_sx->default_role = USB_ROLE_HOST;
+
role_sx_desc.set = ssusb_role_sw_set;
role_sx_desc.get = ssusb_role_sw_get;
- role_sx_desc.fwnode = dev_fwnode(ssusb->dev);
+ role_sx_desc.fwnode = dev_fwnode(dev);
role_sx_desc.driver_data = ssusb;
- otg_sx->role_sw = usb_role_switch_register(ssusb->dev, &role_sx_desc);
+ otg_sx->role_sw = usb_role_switch_register(dev, &role_sx_desc);
+ if (IS_ERR(otg_sx->role_sw))
+ return PTR_ERR(otg_sx->role_sw);
- return PTR_ERR_OR_ZERO(otg_sx->role_sw);
+ ssusb_set_mode(otg_sx, otg_sx->default_role);
+
+ return 0;
}
int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h
index 760fe7d69c6b..e325508bddf4 100644
--- a/drivers/usb/mtu3/mtu3_dr.h
+++ b/drivers/usb/mtu3/mtu3_dr.h
@@ -16,8 +16,8 @@ int ssusb_host_init(struct ssusb_mtk *ssusb, struct device_node *parent_dn);
void ssusb_host_exit(struct ssusb_mtk *ssusb);
int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb,
struct device_node *dn);
-int ssusb_host_enable(struct ssusb_mtk *ssusb);
-int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend);
+int ssusb_host_resume(struct ssusb_mtk *ssusb, bool p0_skipped);
+int ssusb_host_suspend(struct ssusb_mtk *ssusb);
void ssusb_wakeup_set(struct ssusb_mtk *ssusb, bool enable);
#else
@@ -38,12 +38,12 @@ static inline int ssusb_wakeup_of_property_parse(
return 0;
}
-static inline int ssusb_host_enable(struct ssusb_mtk *ssusb)
+static inline int ssusb_host_resume(struct ssusb_mtk *ssusb, bool p0_skipped)
{
return 0;
}
-static inline int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend)
+static inline int ssusb_host_suspend(struct ssusb_mtk *ssusb)
{
return 0;
}
@@ -57,6 +57,10 @@ static inline void ssusb_wakeup_set(struct ssusb_mtk *ssusb, bool enable)
#if IS_ENABLED(CONFIG_USB_MTU3_GADGET) || IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE)
int ssusb_gadget_init(struct ssusb_mtk *ssusb);
void ssusb_gadget_exit(struct ssusb_mtk *ssusb);
+int ssusb_gadget_suspend(struct ssusb_mtk *ssusb, pm_message_t msg);
+int ssusb_gadget_resume(struct ssusb_mtk *ssusb, pm_message_t msg);
+bool ssusb_gadget_ip_sleep_check(struct ssusb_mtk *ssusb);
+
#else
static inline int ssusb_gadget_init(struct ssusb_mtk *ssusb)
{
@@ -65,6 +69,24 @@ static inline int ssusb_gadget_init(struct ssusb_mtk *ssusb)
static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb)
{}
+
+static inline int
+ssusb_gadget_suspend(struct ssusb_mtk *ssusb, pm_message_t msg)
+{
+ return 0;
+}
+
+static inline int
+ssusb_gadget_resume(struct ssusb_mtk *ssusb, pm_message_t msg)
+{
+ return 0;
+}
+
+static inline bool ssusb_gadget_ip_sleep_check(struct ssusb_mtk *ssusb)
+{
+ return true;
+}
+
#endif
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c
index 5e21ba05ebf0..a9a65b4bbfed 100644
--- a/drivers/usb/mtu3/mtu3_gadget.c
+++ b/drivers/usb/mtu3/mtu3_gadget.c
@@ -64,14 +64,12 @@ static int mtu3_ep_enable(struct mtu3_ep *mep)
u32 interval = 0;
u32 mult = 0;
u32 burst = 0;
- int max_packet;
int ret;
desc = mep->desc;
comp_desc = mep->comp_desc;
mep->type = usb_endpoint_type(desc);
- max_packet = usb_endpoint_maxp(desc);
- mep->maxp = max_packet & GENMASK(10, 0);
+ mep->maxp = usb_endpoint_maxp(desc);
switch (mtu->g.speed) {
case USB_SPEED_SUPER:
@@ -92,7 +90,7 @@ static int mtu3_ep_enable(struct mtu3_ep *mep)
usb_endpoint_xfer_int(desc)) {
interval = desc->bInterval;
interval = clamp_val(interval, 1, 16) - 1;
- burst = (max_packet & GENMASK(12, 11)) >> 11;
+ mult = usb_endpoint_maxp_mult(desc) - 1;
}
break;
default:
@@ -469,6 +467,8 @@ static int mtu3_gadget_pullup(struct usb_gadget *gadget, int is_on)
dev_dbg(mtu->dev, "%s (%s) for %sactive device\n", __func__,
is_on ? "on" : "off", mtu->is_active ? "" : "in");
+ pm_runtime_get_sync(mtu->dev);
+
/* we'd rather not pullup unless the device is active. */
spin_lock_irqsave(&mtu->lock, flags);
@@ -482,6 +482,7 @@ static int mtu3_gadget_pullup(struct usb_gadget *gadget, int is_on)
}
spin_unlock_irqrestore(&mtu->lock, flags);
+ pm_runtime_put(mtu->dev);
return 0;
}
@@ -499,6 +500,7 @@ static int mtu3_gadget_start(struct usb_gadget *gadget,
}
dev_dbg(mtu->dev, "bind driver %s\n", driver->function);
+ pm_runtime_get_sync(mtu->dev);
spin_lock_irqsave(&mtu->lock, flags);
@@ -509,6 +511,7 @@ static int mtu3_gadget_start(struct usb_gadget *gadget,
mtu3_start(mtu);
spin_unlock_irqrestore(&mtu->lock, flags);
+ pm_runtime_put(mtu->dev);
return 0;
}
diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c
index 93a1a4c11e1e..f3903367a6a0 100644
--- a/drivers/usb/mtu3/mtu3_host.c
+++ b/drivers/usb/mtu3/mtu3_host.c
@@ -8,7 +8,6 @@
*/
#include <linux/clk.h>
-#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
@@ -63,7 +62,7 @@ static void ssusb_wakeup_ip_sleep_set(struct ssusb_mtk *ssusb, bool enable)
case SSUSB_UWK_V1_1:
reg = ssusb->uwk_reg_base + PERI_WK_CTRL0;
msk = WC0_IS_EN | WC0_IS_C(0xf) | WC0_IS_P;
- val = enable ? (WC0_IS_EN | WC0_IS_C(0x8)) : 0;
+ val = enable ? (WC0_IS_EN | WC0_IS_C(0x1)) : 0;
break;
case SSUSB_UWK_V1_2:
reg = ssusb->uwk_reg_base + PERI_WK_CTRL0;
@@ -126,7 +125,7 @@ static void host_ports_num_get(struct ssusb_mtk *ssusb)
}
/* only configure ports will be used later */
-int ssusb_host_enable(struct ssusb_mtk *ssusb)
+static int ssusb_host_enable(struct ssusb_mtk *ssusb)
{
void __iomem *ibase = ssusb->ippc_base;
int num_u3p = ssusb->u3_ports;
@@ -155,6 +154,9 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb)
/* power on and enable all u2 ports */
for (i = 0; i < num_u2p; i++) {
+ if ((0x1 << i) & ssusb->u2p_dis_msk)
+ continue;
+
value = mtu3_readl(ibase, SSUSB_U2_CTRL(i));
value &= ~(SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS);
value |= SSUSB_U2_PORT_HOST_SEL;
@@ -168,13 +170,12 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb)
return ssusb_check_clocks(ssusb, check_clk);
}
-int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend)
+static int ssusb_host_disable(struct ssusb_mtk *ssusb)
{
void __iomem *ibase = ssusb->ippc_base;
int num_u3p = ssusb->u3_ports;
int num_u2p = ssusb->u2_ports;
u32 value;
- int ret;
int i;
/* power down and disable u3 ports except skipped ones */
@@ -183,32 +184,101 @@ int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend)
continue;
value = mtu3_readl(ibase, SSUSB_U3_CTRL(i));
- value |= SSUSB_U3_PORT_PDN;
- value |= suspend ? 0 : SSUSB_U3_PORT_DIS;
+ value |= SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS;
mtu3_writel(ibase, SSUSB_U3_CTRL(i), value);
}
- /* power down and disable all u2 ports */
+ /* power down and disable u2 ports except skipped ones */
for (i = 0; i < num_u2p; i++) {
+ if ((0x1 << i) & ssusb->u2p_dis_msk)
+ continue;
+
value = mtu3_readl(ibase, SSUSB_U2_CTRL(i));
- value |= SSUSB_U2_PORT_PDN;
- value |= suspend ? 0 : SSUSB_U2_PORT_DIS;
+ value |= SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS;
mtu3_writel(ibase, SSUSB_U2_CTRL(i), value);
}
/* power down host ip */
mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN);
- if (!suspend)
- return 0;
+ return 0;
+}
- /* wait for host ip to sleep */
- ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS1, value,
- (value & SSUSB_IP_SLEEP_STS), 100, 100000);
- if (ret)
- dev_err(ssusb->dev, "ip sleep failed!!!\n");
+int ssusb_host_resume(struct ssusb_mtk *ssusb, bool p0_skipped)
+{
+ void __iomem *ibase = ssusb->ippc_base;
+ int u3p_skip_msk = ssusb->u3p_dis_msk;
+ int u2p_skip_msk = ssusb->u2p_dis_msk;
+ int num_u3p = ssusb->u3_ports;
+ int num_u2p = ssusb->u2_ports;
+ u32 value;
+ int i;
- return ret;
+ if (p0_skipped) {
+ u2p_skip_msk |= 0x1;
+ if (ssusb->otg_switch.is_u3_drd)
+ u3p_skip_msk |= 0x1;
+ }
+
+ /* power on host ip */
+ mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN);
+
+ /* power on u3 ports except skipped ones */
+ for (i = 0; i < num_u3p; i++) {
+ if ((0x1 << i) & u3p_skip_msk)
+ continue;
+
+ value = mtu3_readl(ibase, SSUSB_U3_CTRL(i));
+ value &= ~SSUSB_U3_PORT_PDN;
+ mtu3_writel(ibase, SSUSB_U3_CTRL(i), value);
+ }
+
+ /* power on all u2 ports except skipped ones */
+ for (i = 0; i < num_u2p; i++) {
+ if ((0x1 << i) & u2p_skip_msk)
+ continue;
+
+ value = mtu3_readl(ibase, SSUSB_U2_CTRL(i));
+ value &= ~SSUSB_U2_PORT_PDN;
+ mtu3_writel(ibase, SSUSB_U2_CTRL(i), value);
+ }
+
+ return 0;
+}
+
+/* here not skip port0 due to PDN can be set repeatedly */
+int ssusb_host_suspend(struct ssusb_mtk *ssusb)
+{
+ void __iomem *ibase = ssusb->ippc_base;
+ int num_u3p = ssusb->u3_ports;
+ int num_u2p = ssusb->u2_ports;
+ u32 value;
+ int i;
+
+ /* power down u3 ports except skipped ones */
+ for (i = 0; i < num_u3p; i++) {
+ if ((0x1 << i) & ssusb->u3p_dis_msk)
+ continue;
+
+ value = mtu3_readl(ibase, SSUSB_U3_CTRL(i));
+ value |= SSUSB_U3_PORT_PDN;
+ mtu3_writel(ibase, SSUSB_U3_CTRL(i), value);
+ }
+
+ /* power down u2 ports except skipped ones */
+ for (i = 0; i < num_u2p; i++) {
+ if ((0x1 << i) & ssusb->u2p_dis_msk)
+ continue;
+
+ value = mtu3_readl(ibase, SSUSB_U2_CTRL(i));
+ value |= SSUSB_U2_PORT_PDN;
+ mtu3_writel(ibase, SSUSB_U2_CTRL(i), value);
+ }
+
+ /* power down host ip */
+ mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN);
+
+ return 0;
}
static void ssusb_host_setup(struct ssusb_mtk *ssusb)
@@ -231,7 +301,7 @@ static void ssusb_host_cleanup(struct ssusb_mtk *ssusb)
if (ssusb->is_host)
ssusb_set_vbus(&ssusb->otg_switch, 0);
- ssusb_host_disable(ssusb, false);
+ ssusb_host_disable(ssusb);
}
/*
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index c0615f6e5cce..f13531022f4a 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -12,6 +12,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
#include "mtu3.h"
#include "mtu3_dr.h"
@@ -44,6 +45,32 @@ int ssusb_check_clocks(struct ssusb_mtk *ssusb, u32 ex_clks)
return 0;
}
+static int wait_for_ip_sleep(struct ssusb_mtk *ssusb)
+{
+ bool sleep_check = true;
+ u32 value;
+ int ret;
+
+ if (!ssusb->is_host)
+ sleep_check = ssusb_gadget_ip_sleep_check(ssusb);
+
+ if (!sleep_check)
+ return 0;
+
+ /* wait for ip enter sleep mode */
+ ret = readl_poll_timeout(ssusb->ippc_base + U3D_SSUSB_IP_PW_STS1, value,
+ (value & SSUSB_IP_SLEEP_STS), 100, 100000);
+ if (ret) {
+ dev_err(ssusb->dev, "ip sleep failed!!!\n");
+ ret = -EBUSY;
+ } else {
+ /* workaround: avoid wrong wakeup signal latch for some soc */
+ usleep_range(100, 200);
+ }
+
+ return ret;
+}
+
static int ssusb_phy_init(struct ssusb_mtk *ssusb)
{
int i;
@@ -208,6 +235,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
if (IS_ERR(ssusb->ippc_base))
return PTR_ERR(ssusb->ippc_base);
+ ssusb->wakeup_irq = platform_get_irq_byname_optional(pdev, "wakeup");
+ if (ssusb->wakeup_irq == -EPROBE_DEFER)
+ return ssusb->wakeup_irq;
+
ssusb->dr_mode = usb_get_dr_mode(dev);
if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN)
ssusb->dr_mode = USB_DR_MODE_OTG;
@@ -225,6 +256,8 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
/* optional property, ignore the error if it does not exist */
of_property_read_u32(node, "mediatek,u3p-dis-msk",
&ssusb->u3p_dis_msk);
+ of_property_read_u32(node, "mediatek,u2p-dis-msk",
+ &ssusb->u2p_dis_msk);
otg_sx->vbus = devm_regulator_get(dev, "vbus");
if (IS_ERR(otg_sx->vbus)) {
@@ -241,6 +274,9 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
of_property_read_bool(node, "enable-manual-drd");
otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch");
+ /* can't disable port0 when use dual-role mode */
+ ssusb->u2p_dis_msk &= ~0x1;
+
if (otg_sx->role_sw_used || otg_sx->manual_drd_enabled)
goto out;
@@ -253,9 +289,11 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
}
out:
- dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk: %x, drd: %s\n",
- ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk,
+ dev_info(dev, "dr_mode: %d, is_u3_dr: %d, drd: %s\n",
+ ssusb->dr_mode, otg_sx->is_u3_drd,
otg_sx->manual_drd_enabled ? "manual" : "auto");
+ dev_info(dev, "u2p_dis_msk: %x, u3p_dis_msk: %x\n",
+ ssusb->u2p_dis_msk, ssusb->u3p_dis_msk);
return 0;
}
@@ -288,14 +326,25 @@ static int mtu3_probe(struct platform_device *pdev)
ssusb_debugfs_create_root(ssusb);
/* enable power domain */
+ pm_runtime_set_active(dev);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, 4000);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
- device_enable_async_suspend(dev);
ret = ssusb_rscs_init(ssusb);
if (ret)
goto comm_init_err;
+ if (ssusb->wakeup_irq > 0) {
+ ret = dev_pm_set_dedicated_wake_irq(dev, ssusb->wakeup_irq);
+ if (ret) {
+ dev_err(dev, "failed to set wakeup irq %d\n", ssusb->wakeup_irq);
+ goto comm_exit;
+ }
+ dev_info(dev, "wakeup irq %d\n", ssusb->wakeup_irq);
+ }
+
ssusb_ip_sw_reset(ssusb);
if (IS_ENABLED(CONFIG_USB_MTU3_HOST))
@@ -346,6 +395,11 @@ static int mtu3_probe(struct platform_device *pdev)
goto comm_exit;
}
+ device_enable_async_suspend(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ pm_runtime_forbid(dev);
+
return 0;
host_exit:
@@ -355,7 +409,7 @@ gadget_exit:
comm_exit:
ssusb_rscs_exit(ssusb);
comm_init_err:
- pm_runtime_put_sync(dev);
+ pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
ssusb_debugfs_remove_root(ssusb);
@@ -366,6 +420,8 @@ static int mtu3_remove(struct platform_device *pdev)
{
struct ssusb_mtk *ssusb = platform_get_drvdata(pdev);
+ pm_runtime_get_sync(&pdev->dev);
+
switch (ssusb->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
ssusb_gadget_exit(ssusb);
@@ -383,45 +439,87 @@ static int mtu3_remove(struct platform_device *pdev)
}
ssusb_rscs_exit(ssusb);
- pm_runtime_put_sync(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
ssusb_debugfs_remove_root(ssusb);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
return 0;
}
-/*
- * when support dual-role mode, we reject suspend when
- * it works as device mode;
- */
-static int __maybe_unused mtu3_suspend(struct device *dev)
+static int resume_ip_and_ports(struct ssusb_mtk *ssusb, pm_message_t msg)
+{
+ switch (ssusb->dr_mode) {
+ case USB_DR_MODE_PERIPHERAL:
+ ssusb_gadget_resume(ssusb, msg);
+ break;
+ case USB_DR_MODE_HOST:
+ ssusb_host_resume(ssusb, false);
+ break;
+ case USB_DR_MODE_OTG:
+ ssusb_host_resume(ssusb, !ssusb->is_host);
+ if (!ssusb->is_host)
+ ssusb_gadget_resume(ssusb, msg);
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mtu3_suspend_common(struct device *dev, pm_message_t msg)
{
struct ssusb_mtk *ssusb = dev_get_drvdata(dev);
+ int ret = 0;
dev_dbg(dev, "%s\n", __func__);
- /* REVISIT: disconnect it for only device mode? */
- if (!ssusb->is_host)
- return 0;
+ switch (ssusb->dr_mode) {
+ case USB_DR_MODE_PERIPHERAL:
+ ret = ssusb_gadget_suspend(ssusb, msg);
+ if (ret)
+ goto err;
+
+ break;
+ case USB_DR_MODE_HOST:
+ ssusb_host_suspend(ssusb);
+ break;
+ case USB_DR_MODE_OTG:
+ if (!ssusb->is_host) {
+ ret = ssusb_gadget_suspend(ssusb, msg);
+ if (ret)
+ goto err;
+ }
+ ssusb_host_suspend(ssusb);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = wait_for_ip_sleep(ssusb);
+ if (ret)
+ goto sleep_err;
- ssusb_host_disable(ssusb, true);
ssusb_phy_power_off(ssusb);
clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks);
ssusb_wakeup_set(ssusb, true);
-
return 0;
+
+sleep_err:
+ resume_ip_and_ports(ssusb, msg);
+err:
+ return ret;
}
-static int __maybe_unused mtu3_resume(struct device *dev)
+static int mtu3_resume_common(struct device *dev, pm_message_t msg)
{
struct ssusb_mtk *ssusb = dev_get_drvdata(dev);
int ret;
dev_dbg(dev, "%s\n", __func__);
- if (!ssusb->is_host)
- return 0;
-
ssusb_wakeup_set(ssusb, false);
ret = clk_bulk_prepare_enable(BULK_CLKS_CNT, ssusb->clks);
if (ret)
@@ -431,9 +529,7 @@ static int __maybe_unused mtu3_resume(struct device *dev)
if (ret)
goto phy_err;
- ssusb_host_enable(ssusb);
-
- return 0;
+ return resume_ip_and_ports(ssusb, msg);
phy_err:
clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks);
@@ -441,8 +537,36 @@ clks_err:
return ret;
}
+static int __maybe_unused mtu3_suspend(struct device *dev)
+{
+ return mtu3_suspend_common(dev, PMSG_SUSPEND);
+}
+
+static int __maybe_unused mtu3_resume(struct device *dev)
+{
+ return mtu3_resume_common(dev, PMSG_SUSPEND);
+}
+
+static int __maybe_unused mtu3_runtime_suspend(struct device *dev)
+{
+ if (!device_may_wakeup(dev))
+ return 0;
+
+ return mtu3_suspend_common(dev, PMSG_AUTO_SUSPEND);
+}
+
+static int __maybe_unused mtu3_runtime_resume(struct device *dev)
+{
+ if (!device_may_wakeup(dev))
+ return 0;
+
+ return mtu3_resume_common(dev, PMSG_AUTO_SUSPEND);
+}
+
static const struct dev_pm_ops mtu3_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(mtu3_suspend, mtu3_resume)
+ SET_RUNTIME_PM_OPS(mtu3_runtime_suspend,
+ mtu3_runtime_resume, NULL)
};
#define DEV_PM_OPS (IS_ENABLED(CONFIG_PM) ? &mtu3_pm_ops : NULL)
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 5892f3ce0cdc..ce9fc46c9266 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -890,23 +890,22 @@ static int dsps_probe(struct platform_device *pdev)
if (!glue->usbss_base)
return -ENXIO;
- if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
- ret = dsps_setup_optional_vbus_irq(pdev, glue);
- if (ret)
- goto err_iounmap;
- }
-
platform_set_drvdata(pdev, glue);
pm_runtime_enable(&pdev->dev);
ret = dsps_create_musb_pdev(glue, pdev);
if (ret)
goto err;
+ if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
+ ret = dsps_setup_optional_vbus_irq(pdev, glue);
+ if (ret)
+ goto err;
+ }
+
return 0;
err:
pm_runtime_disable(&pdev->dev);
-err_iounmap:
iounmap(glue->usbss_base);
return ret;
}
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index f34c9437a182..972704262b02 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -873,6 +873,8 @@ int usb_otg_start(struct platform_device *pdev)
/* request irq */
p_otg->irq = platform_get_irq(pdev, 0);
+ if (p_otg->irq < 0)
+ return p_otg->irq;
status = request_irq(p_otg->irq, fsl_otg_isr,
IRQF_SHARED, driver_name, p_otg);
if (status) {
diff --git a/drivers/usb/phy/phy-isp1301-omap.c b/drivers/usb/phy/phy-isp1301-omap.c
index f3e9b3b6ac3e..190699b38b41 100644
--- a/drivers/usb/phy/phy-isp1301-omap.c
+++ b/drivers/usb/phy/phy-isp1301-omap.c
@@ -12,7 +12,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb.h>
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
index baebb1f5a973..a3e043e3e4aa 100644
--- a/drivers/usb/phy/phy-tahvo.c
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -393,7 +393,9 @@ static int tahvo_usb_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, tu);
- tu->irq = platform_get_irq(pdev, 0);
+ tu->irq = ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ return ret;
ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt,
IRQF_ONESHOT,
"tahvo-vbus", tu);
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 8ba6c5a91557..ab3c38a7d8ac 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -348,6 +348,11 @@ static int twl6030_usb_probe(struct platform_device *pdev)
twl->irq2 = platform_get_irq(pdev, 1);
twl->linkstat = MUSB_UNKNOWN;
+ if (twl->irq1 < 0)
+ return twl->irq1;
+ if (twl->irq2 < 0)
+ return twl->irq2;
+
twl->comparator.set_vbus = twl6030_set_vbus;
twl->comparator.start_srp = twl6030_start_srp;
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index a3c2b01ccf7b..10607e273879 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -366,7 +366,7 @@ static int usbhs_dcp_dir_switch_to_write(struct usbhs_pkt *pkt, int *is_done)
ret = usbhsf_fifo_select(pipe, fifo, 1);
if (ret < 0) {
- dev_err(dev, "%s() faile\n", __func__);
+ dev_err(dev, "%s() failed\n", __func__);
return ret;
}
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 7133818a58b9..9e38142acd38 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -74,7 +74,7 @@ err_autopm_put:
return retval;
}
-static int usb_serial_device_remove(struct device *dev)
+static void usb_serial_device_remove(struct device *dev)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct usb_serial_driver *driver;
@@ -101,8 +101,6 @@ static int usb_serial_device_remove(struct device *dev)
if (!autopm_err)
usb_autopm_put_interface(port->serial->interface);
-
- return 0;
}
static ssize_t new_id_store(struct device_driver *driver,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 3c80bfbf3bec..66a6ac50a4cd 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -400,6 +400,7 @@ struct cp210x_special_chars {
};
/* CP210X_VENDOR_SPECIFIC values */
+#define CP210X_GET_FW_VER 0x000E
#define CP210X_READ_2NCONFIG 0x000E
#define CP210X_GET_FW_VER_2N 0x0010
#define CP210X_READ_LATCH 0x00C2
@@ -638,7 +639,7 @@ static int cp210x_read_reg_block(struct usb_serial_port *port, u8 req,
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
req, REQTYPE_INTERFACE_TO_HOST, 0,
port_priv->bInterfaceNumber, dmabuf, bufsize,
- USB_CTRL_SET_TIMEOUT);
+ USB_CTRL_GET_TIMEOUT);
if (result == bufsize) {
memcpy(buf, dmabuf, bufsize);
result = 0;
@@ -1145,33 +1146,6 @@ static void cp210x_disable_event_mode(struct usb_serial_port *port)
port_priv->event_mode = false;
}
-static int cp210x_set_chars(struct usb_serial_port *port,
- struct cp210x_special_chars *chars)
-{
- struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
- struct usb_serial *serial = port->serial;
- void *dmabuf;
- int result;
-
- dmabuf = kmemdup(chars, sizeof(*chars), GFP_KERNEL);
- if (!dmabuf)
- return -ENOMEM;
-
- result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- CP210X_SET_CHARS, REQTYPE_HOST_TO_INTERFACE, 0,
- port_priv->bInterfaceNumber,
- dmabuf, sizeof(*chars), USB_CTRL_SET_TIMEOUT);
-
- kfree(dmabuf);
-
- if (result < 0) {
- dev_err(&port->dev, "failed to set special chars: %d\n", result);
- return result;
- }
-
- return 0;
-}
-
static bool cp210x_termios_change(const struct ktermios *a, const struct ktermios *b)
{
bool iflag_change, cc_change;
@@ -1192,6 +1166,7 @@ static void cp210x_set_flow_control(struct tty_struct *tty,
struct cp210x_flow_ctl flow_ctl;
u32 flow_repl;
u32 ctl_hs;
+ bool crtscts;
int ret;
/*
@@ -1218,9 +1193,12 @@ static void cp210x_set_flow_control(struct tty_struct *tty,
chars.bXonChar = START_CHAR(tty);
chars.bXoffChar = STOP_CHAR(tty);
- ret = cp210x_set_chars(port, &chars);
- if (ret)
- return;
+ ret = cp210x_write_reg_block(port, CP210X_SET_CHARS, &chars,
+ sizeof(chars));
+ if (ret) {
+ dev_err(&port->dev, "failed to set special chars: %d\n",
+ ret);
+ }
}
mutex_lock(&port_priv->mutex);
@@ -1249,14 +1227,14 @@ static void cp210x_set_flow_control(struct tty_struct *tty,
flow_repl |= CP210X_SERIAL_RTS_FLOW_CTL;
else
flow_repl |= CP210X_SERIAL_RTS_INACTIVE;
- port_priv->crtscts = true;
+ crtscts = true;
} else {
ctl_hs &= ~CP210X_SERIAL_CTS_HANDSHAKE;
if (port_priv->rts)
flow_repl |= CP210X_SERIAL_RTS_ACTIVE;
else
flow_repl |= CP210X_SERIAL_RTS_INACTIVE;
- port_priv->crtscts = false;
+ crtscts = false;
}
if (I_IXOFF(tty)) {
@@ -1279,8 +1257,12 @@ static void cp210x_set_flow_control(struct tty_struct *tty,
flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs);
flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl);
- cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl,
+ ret = cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl,
sizeof(flow_ctl));
+ if (ret)
+ goto out_unlock;
+
+ port_priv->crtscts = crtscts;
out_unlock:
mutex_unlock(&port_priv->mutex);
}
@@ -2111,12 +2093,26 @@ static int cp210x_get_fw_version(struct usb_serial *serial, u16 value)
return 0;
}
-static void cp210x_determine_quirks(struct usb_serial *serial)
+static void cp210x_determine_type(struct usb_serial *serial)
{
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
int ret;
+ ret = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST,
+ CP210X_GET_PARTNUM, &priv->partnum,
+ sizeof(priv->partnum));
+ if (ret < 0) {
+ dev_warn(&serial->interface->dev,
+ "querying part number failed\n");
+ priv->partnum = CP210X_PARTNUM_UNKNOWN;
+ return;
+ }
+
switch (priv->partnum) {
+ case CP210X_PARTNUM_CP2105:
+ case CP210X_PARTNUM_CP2108:
+ cp210x_get_fw_version(serial, CP210X_GET_FW_VER);
+ break;
case CP210X_PARTNUM_CP2102N_QFN28:
case CP210X_PARTNUM_CP2102N_QFN24:
case CP210X_PARTNUM_CP2102N_QFN20:
@@ -2140,18 +2136,9 @@ static int cp210x_attach(struct usb_serial *serial)
if (!priv)
return -ENOMEM;
- result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST,
- CP210X_GET_PARTNUM, &priv->partnum,
- sizeof(priv->partnum));
- if (result < 0) {
- dev_warn(&serial->interface->dev,
- "querying part number failed\n");
- priv->partnum = CP210X_PARTNUM_UNKNOWN;
- }
-
usb_set_serial_data(serial, priv);
- cp210x_determine_quirks(serial);
+ cp210x_determine_type(serial);
cp210x_init_max_speed(serial);
result = cp210x_gpio_init(serial);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 6b18990258c3..6924fa95f6bd 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1199,9 +1199,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(stats, bool, S_IRUGO | S_IWUSR);
+module_param(stats, bool, 0644);
MODULE_PARM_DESC(stats, "Enable statistics or not");
-module_param(interval, int, S_IRUGO | S_IWUSR);
+module_param(interval, int, 0644);
MODULE_PARM_DESC(interval, "Overrides interrupt interval");
-module_param(unstable_bauds, bool, S_IRUGO | S_IWUSR);
+module_param(unstable_bauds, bool, 0644);
MODULE_PARM_DESC(unstable_bauds, "Allow unstable baud rates");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 33bbb3470ca3..99d19828dae6 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -2938,5 +2938,5 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR);
+module_param(ndi_latency_timer, int, 0644);
MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override");
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 756d1ac7e96f..e5c75944ebb7 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1444,5 +1444,5 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(initial_mode, int, S_IRUGO);
+module_param(initial_mode, int, 0444);
MODULE_PARM_DESC(initial_mode, "Initial mode");
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index ea4edf5eed27..bdee78cc4a07 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -389,39 +389,6 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial)
release_firmware(fw);
}
-#if 0
-/************************************************************************
- *
- * Get string descriptor from device
- *
- ************************************************************************/
-static int get_string_desc(struct usb_device *dev, int Id,
- struct usb_string_descriptor **pRetDesc)
-{
- struct usb_string_descriptor StringDesc;
- struct usb_string_descriptor *pStringDesc;
-
- dev_dbg(&dev->dev, "%s - USB String ID = %d\n", __func__, Id);
-
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc,
- sizeof(StringDesc)))
- return 0;
-
- pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL);
- if (!pStringDesc)
- return -1;
-
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc,
- StringDesc.bLength)) {
- kfree(pStringDesc);
- return -1;
- }
-
- *pRetDesc = pStringDesc;
- return 0;
-}
-#endif
-
static void dump_product_info(struct edgeport_serial *edge_serial,
struct edgeport_product_info *product_info)
{
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 84b848d2794e..a7b3c15957ba 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2746,9 +2746,9 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("edgeport/down3.bin");
-module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR);
+module_param(ignore_cpu_rev, bool, 0644);
MODULE_PARM_DESC(ignore_cpu_rev,
"Ignore the cpu revision when connecting to a device");
-module_param(default_uart_mode, int, S_IRUGO | S_IWUSR);
+module_param(default_uart_mode, int, 0644);
MODULE_PARM_DESC(default_uart_mode, "Default uart_mode, 0=RS232, ...");
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index f81746c3c26c..e11441bac44f 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -599,10 +599,10 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(connect_retries, int, S_IRUGO|S_IWUSR);
+module_param(connect_retries, int, 0644);
MODULE_PARM_DESC(connect_retries,
"Maximum number of connect retries (one second each)");
-module_param(initial_wait, int, S_IRUGO|S_IWUSR);
+module_param(initial_wait, int, 0644);
MODULE_PARM_DESC(initial_wait,
"Time to wait before attempting a connection (in seconds)");
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 19753611e7b0..0be3b5e1eaf3 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -1188,20 +1188,20 @@ MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-module_param(xmas, bool, S_IRUGO | S_IWUSR);
+module_param(xmas, bool, 0644);
MODULE_PARM_DESC(xmas, "Xmas colors enabled or not");
-module_param(boost, int, S_IRUGO | S_IWUSR);
+module_param(boost, int, 0644);
MODULE_PARM_DESC(boost, "Card overclock boost (in percent 100-500)");
-module_param(clockmode, int, S_IRUGO | S_IWUSR);
+module_param(clockmode, int, 0644);
MODULE_PARM_DESC(clockmode, "Card clock mode (1=3.579 MHz, 2=3.680 MHz, "
"3=6 Mhz)");
-module_param(cdmode, int, S_IRUGO | S_IWUSR);
+module_param(cdmode, int, 0644);
MODULE_PARM_DESC(cdmode, "Card detect mode (0=none, 1=CD, 2=!CD, 3=DSR, "
"4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING)");
-module_param(vcc_default, int, S_IRUGO | S_IWUSR);
+module_param(vcc_default, int, 0644);
MODULE_PARM_DESC(vcc_default, "Set default VCC (either 3 for 3.3V or 5 "
"for 5V). Default to 5.");
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 930b3d50a330..f45ca7ddf78e 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -433,6 +433,7 @@ static int pl2303_detect_type(struct usb_serial *serial)
switch (bcdDevice) {
case 0x100:
case 0x305:
+ case 0x405:
/*
* Assume it's an HXN-type if the device doesn't
* support the old read request value.
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 4b49b7c33364..9d56138133a9 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -1056,5 +1056,5 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL v2");
-module_param(nmea, bool, S_IRUGO | S_IWUSR);
+module_param(nmea, bool, 0644);
MODULE_PARM_DESC(nmea, "NMEA streaming");
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index eeb441c77207..090a78c948f2 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1319,9 +1319,10 @@ static int __init usb_serial_init(void)
{
int result;
- usb_serial_tty_driver = alloc_tty_driver(USB_SERIAL_TTY_MINORS);
- if (!usb_serial_tty_driver)
- return -ENOMEM;
+ usb_serial_tty_driver = tty_alloc_driver(USB_SERIAL_TTY_MINORS,
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(usb_serial_tty_driver))
+ return PTR_ERR(usb_serial_tty_driver);
/* Initialize our global data */
result = bus_register(&usb_serial_bus_type);
@@ -1336,8 +1337,6 @@ static int __init usb_serial_init(void)
usb_serial_tty_driver->minor_start = 0;
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV;
usb_serial_tty_driver->init_termios = tty_std_termios;
usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
| HUPCL | CLOCAL;
@@ -1367,7 +1366,7 @@ exit_reg_driver:
exit_bus:
pr_err("%s - returning with error %d\n", __func__, result);
- put_tty_driver(usb_serial_tty_driver);
+ tty_driver_kref_put(usb_serial_tty_driver);
return result;
}
@@ -1379,7 +1378,7 @@ static void __exit usb_serial_exit(void)
usb_serial_generic_deregister();
tty_unregister_driver(usb_serial_tty_driver);
- put_tty_driver(usb_serial_tty_driver);
+ tty_driver_kref_put(usb_serial_tty_driver);
bus_unregister(&usb_serial_bus_type);
idr_destroy(&serial_minors);
}
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index f4304ce69350..4c5a0a49035f 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -551,7 +551,7 @@ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb)
/* Did this command access the last sector? */
sector = (srb->cmnd[2] << 24) | (srb->cmnd[3] << 16) |
(srb->cmnd[4] << 8) | (srb->cmnd[5]);
- disk = srb->request->rq_disk;
+ disk = scsi_cmd_to_rq(srb)->rq_disk;
if (!disk)
goto done;
sdkp = scsi_disk(disk);
diff --git a/drivers/usb/typec/bus.c b/drivers/usb/typec/bus.c
index 7f3c9a8e2bf0..78e0e78954f2 100644
--- a/drivers/usb/typec/bus.c
+++ b/drivers/usb/typec/bus.c
@@ -382,7 +382,7 @@ static int typec_probe(struct device *dev)
return ret;
}
-static int typec_remove(struct device *dev)
+static void typec_remove(struct device *dev)
{
struct typec_altmode_driver *drv = to_altmode_driver(dev->driver);
struct typec_altmode *adev = to_typec_altmode(dev);
@@ -400,8 +400,6 @@ static int typec_remove(struct device *dev)
adev->desc = NULL;
adev->ops = NULL;
-
- return 0;
}
struct bus_type typec_bus = {
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 5d05de666597..a4d37205df54 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -278,7 +278,7 @@ struct pd_mode_data {
* @req_max_curr: Requested max current of the port partner
* @req_out_volt: Requested output voltage to the port partner
* @req_op_curr: Requested operating current to the port partner
- * @supported: Parter has atleast one APDO hence supports PPS
+ * @supported: Parter has at least one APDO hence supports PPS
* @active: PPS mode is active
*/
struct pd_pps_data {
@@ -316,6 +316,7 @@ struct tcpm_port {
struct typec_partner *partner;
enum typec_cc_status cc_req;
+ enum typec_cc_status src_rp; /* work only if pd_supported == false */
enum typec_cc_status cc1;
enum typec_cc_status cc2;
@@ -323,6 +324,7 @@ struct tcpm_port {
bool attached;
bool connected;
+ bool pd_supported;
enum typec_port_type port_type;
/*
@@ -817,6 +819,9 @@ static enum typec_cc_status tcpm_rp_cc(struct tcpm_port *port)
int nr_pdo = port->nr_src_pdo;
int i;
+ if (!port->pd_supported)
+ return port->src_rp;
+
/*
* Search for first entry with matching voltage.
* It should report the maximum supported current.
@@ -2063,7 +2068,7 @@ enum pdo_err {
static const char * const pdo_err_msg[] = {
[PDO_ERR_NO_VSAFE5V] =
- " err: source/sink caps should atleast have vSafe5V",
+ " err: source/sink caps should at least have vSafe5V",
[PDO_ERR_VSAFE5V_NOT_FIRST] =
" err: vSafe5V Fixed Supply Object Shall always be the first object",
[PDO_ERR_PDO_TYPE_NOT_IN_ORDER] =
@@ -3571,9 +3576,11 @@ static int tcpm_src_attach(struct tcpm_port *port)
if (ret < 0)
return ret;
- ret = port->tcpc->set_pd_rx(port->tcpc, true);
- if (ret < 0)
- goto out_disable_mux;
+ if (port->pd_supported) {
+ ret = port->tcpc->set_pd_rx(port->tcpc, true);
+ if (ret < 0)
+ goto out_disable_mux;
+ }
/*
* USB Type-C specification, version 1.2,
@@ -3603,7 +3610,8 @@ static int tcpm_src_attach(struct tcpm_port *port)
out_disable_vconn:
tcpm_set_vconn(port, false);
out_disable_pd:
- port->tcpc->set_pd_rx(port->tcpc, false);
+ if (port->pd_supported)
+ port->tcpc->set_pd_rx(port->tcpc, false);
out_disable_mux:
tcpm_mux_set(port, TYPEC_STATE_SAFE, USB_ROLE_NONE,
TYPEC_ORIENTATION_NONE);
@@ -3807,6 +3815,20 @@ static enum typec_pwr_opmode tcpm_get_pwr_opmode(enum typec_cc_status cc)
}
}
+static enum typec_cc_status tcpm_pwr_opmode_to_rp(enum typec_pwr_opmode opmode)
+{
+ switch (opmode) {
+ case TYPEC_PWR_MODE_USB:
+ return TYPEC_CC_RP_DEF;
+ case TYPEC_PWR_MODE_1_5A:
+ return TYPEC_CC_RP_1_5;
+ case TYPEC_PWR_MODE_3_0A:
+ case TYPEC_PWR_MODE_PD:
+ default:
+ return TYPEC_CC_RP_3_0;
+ }
+}
+
static void run_state_machine(struct tcpm_port *port)
{
int ret;
@@ -3917,6 +3939,10 @@ static void run_state_machine(struct tcpm_port *port)
if (port->ams == POWER_ROLE_SWAP ||
port->ams == FAST_ROLE_SWAP)
tcpm_ams_finish(port);
+ if (!port->pd_supported) {
+ tcpm_set_state(port, SRC_READY, 0);
+ break;
+ }
port->upcoming_state = SRC_SEND_CAPABILITIES;
tcpm_ams_start(port, POWER_NEGOTIATION);
break;
@@ -4164,7 +4190,10 @@ static void run_state_machine(struct tcpm_port *port)
current_lim = PD_P_SNK_STDBY_MW / 5;
tcpm_set_current_limit(port, current_lim, 5000);
tcpm_set_charge(port, true);
- tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
+ if (!port->pd_supported)
+ tcpm_set_state(port, SNK_READY, 0);
+ else
+ tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
break;
}
/*
@@ -4392,7 +4421,8 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_vbus(port, true);
if (port->ams == HARD_RESET)
tcpm_ams_finish(port);
- port->tcpc->set_pd_rx(port->tcpc, true);
+ if (port->pd_supported)
+ port->tcpc->set_pd_rx(port->tcpc, true);
tcpm_set_attached_state(port, true);
tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON);
break;
@@ -5894,6 +5924,7 @@ EXPORT_SYMBOL_GPL(tcpm_tcpc_reset);
static int tcpm_fw_get_caps(struct tcpm_port *port,
struct fwnode_handle *fwnode)
{
+ const char *opmode_str;
const char *cap_str;
int ret;
u32 mw, frs_current;
@@ -5928,22 +5959,37 @@ static int tcpm_fw_get_caps(struct tcpm_port *port,
return ret;
port->typec_caps.type = ret;
port->port_type = port->typec_caps.type;
+ port->pd_supported = !fwnode_property_read_bool(fwnode, "pd-disable");
port->slow_charger_loop = fwnode_property_read_bool(fwnode, "slow-charger-loop");
if (port->port_type == TYPEC_PORT_SNK)
goto sink;
- /* Get source pdos */
- ret = fwnode_property_count_u32(fwnode, "source-pdos");
- if (ret <= 0)
- return -EINVAL;
+ /* Get Source PDOs for the PD port or Source Rp value for the non-PD port */
+ if (port->pd_supported) {
+ ret = fwnode_property_count_u32(fwnode, "source-pdos");
+ if (ret == 0)
+ return -EINVAL;
+ else if (ret < 0)
+ return ret;
- port->nr_src_pdo = min(ret, PDO_MAX_OBJECTS);
- ret = fwnode_property_read_u32_array(fwnode, "source-pdos",
- port->src_pdo, port->nr_src_pdo);
- if ((ret < 0) || tcpm_validate_caps(port, port->src_pdo,
- port->nr_src_pdo))
- return -EINVAL;
+ port->nr_src_pdo = min(ret, PDO_MAX_OBJECTS);
+ ret = fwnode_property_read_u32_array(fwnode, "source-pdos",
+ port->src_pdo, port->nr_src_pdo);
+ if (ret)
+ return ret;
+ ret = tcpm_validate_caps(port, port->src_pdo, port->nr_src_pdo);
+ if (ret)
+ return ret;
+ } else {
+ ret = fwnode_property_read_string(fwnode, "typec-power-opmode", &opmode_str);
+ if (ret)
+ return ret;
+ ret = typec_find_pwr_opmode(opmode_str);
+ if (ret < 0)
+ return ret;
+ port->src_rp = tcpm_pwr_opmode_to_rp(ret);
+ }
if (port->port_type == TYPEC_PORT_SRC)
return 0;
@@ -5957,6 +6003,11 @@ static int tcpm_fw_get_caps(struct tcpm_port *port,
if (port->typec_caps.prefer_role < 0)
return -EINVAL;
sink:
+ port->self_powered = fwnode_property_read_bool(fwnode, "self-powered");
+
+ if (!port->pd_supported)
+ return 0;
+
/* Get sink pdos */
ret = fwnode_property_count_u32(fwnode, "sink-pdos");
if (ret <= 0)
@@ -5973,9 +6024,7 @@ sink:
return -EINVAL;
port->operating_snk_mw = mw / 1000;
- port->self_powered = fwnode_property_read_bool(fwnode, "self-powered");
-
- /* FRS can only be supported byb DRP ports */
+ /* FRS can only be supported by DRP ports */
if (port->port_type == TYPEC_PORT_DRP) {
ret = fwnode_property_read_u32(fwnode, "new-source-frs-typec-current",
&frs_current);
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 4ba6bcdaa8e9..233265550fc6 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -455,8 +455,14 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
vhci_hcd->port_status[rhport] &= ~(1 << USB_PORT_FEAT_RESET);
vhci_hcd->re_timeout = 0;
+ /*
+ * A few drivers do usb reset during probe when
+ * the device could be in VDEV_ST_USED state
+ */
if (vhci_hcd->vdev[rhport].ud.status ==
- VDEV_ST_NOTASSIGNED) {
+ VDEV_ST_NOTASSIGNED ||
+ vhci_hcd->vdev[rhport].ud.status ==
+ VDEV_ST_USED) {
usbip_dbg_vhci_rh(
" enable rhport %d (status %u)\n",
rhport,
@@ -945,7 +951,8 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
return 0;
}
-static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
+static void vhci_cleanup_unlink_list(struct vhci_device *vdev,
+ struct list_head *unlink_list)
{
struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
struct usb_hcd *hcd = vhci_hcd_to_hcd(vhci_hcd);
@@ -956,25 +963,11 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
spin_lock_irqsave(&vhci->lock, flags);
spin_lock(&vdev->priv_lock);
- list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
- pr_info("unlink cleanup tx %lu\n", unlink->unlink_seqnum);
- list_del(&unlink->list);
- kfree(unlink);
- }
-
- while (!list_empty(&vdev->unlink_rx)) {
+ list_for_each_entry_safe(unlink, tmp, unlink_list, list) {
struct urb *urb;
- unlink = list_first_entry(&vdev->unlink_rx, struct vhci_unlink,
- list);
-
- /* give back URB of unanswered unlink request */
- pr_info("unlink cleanup rx %lu\n", unlink->unlink_seqnum);
-
urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
if (!urb) {
- pr_info("the urb (seqnum %lu) was already given back\n",
- unlink->unlink_seqnum);
list_del(&unlink->list);
kfree(unlink);
continue;
@@ -1001,6 +994,15 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
spin_unlock_irqrestore(&vhci->lock, flags);
}
+static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
+{
+ /* give back URB of unsent unlink request */
+ vhci_cleanup_unlink_list(vdev, &vdev->unlink_tx);
+
+ /* give back URB of unanswered unlink request */
+ vhci_cleanup_unlink_list(vdev, &vdev->unlink_rx);
+}
+
/*
* The important thing is that only one context begins cleanup.
* This is why error handling and cleanup become simple.
diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
index bb3f1d1f0422..3fc4525fc05c 100644
--- a/drivers/vdpa/vdpa.c
+++ b/drivers/vdpa/vdpa.c
@@ -34,15 +34,13 @@ static int vdpa_dev_probe(struct device *d)
return ret;
}
-static int vdpa_dev_remove(struct device *d)
+static void vdpa_dev_remove(struct device *d)
{
struct vdpa_device *vdev = dev_to_vdpa(d);
struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver);
if (drv && drv->remove)
drv->remove(vdev);
-
- return 0;
}
static struct bus_type vdpa_bus = {
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index 67d0bf4efa16..6130d00252ed 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -1,12 +1,22 @@
# SPDX-License-Identifier: GPL-2.0-only
+menuconfig VFIO
+ tristate "VFIO Non-Privileged userspace driver framework"
+ select IOMMU_API
+ select VFIO_IOMMU_TYPE1 if MMU && (X86 || S390 || ARM || ARM64)
+ help
+ VFIO provides a framework for secure userspace device drivers.
+ See Documentation/driver-api/vfio.rst for more details.
+
+ If you don't know what to do here, say N.
+
+if VFIO
config VFIO_IOMMU_TYPE1
tristate
- depends on VFIO
default n
config VFIO_IOMMU_SPAPR_TCE
tristate
- depends on VFIO && SPAPR_TCE_IOMMU
+ depends on SPAPR_TCE_IOMMU
default VFIO
config VFIO_SPAPR_EEH
@@ -16,22 +26,11 @@ config VFIO_SPAPR_EEH
config VFIO_VIRQFD
tristate
- depends on VFIO && EVENTFD
+ select EVENTFD
default n
-menuconfig VFIO
- tristate "VFIO Non-Privileged userspace driver framework"
- select IOMMU_API
- select VFIO_IOMMU_TYPE1 if MMU && (X86 || S390 || ARM || ARM64)
- help
- VFIO provides a framework for secure userspace device drivers.
- See Documentation/driver-api/vfio.rst for more details.
-
- If you don't know what to do here, say N.
-
-menuconfig VFIO_NOIOMMU
+config VFIO_NOIOMMU
bool "VFIO No-IOMMU support"
- depends on VFIO
help
VFIO is built on the ability to isolate devices using the IOMMU.
Only with an IOMMU can userspace access to DMA capable devices be
@@ -48,4 +47,6 @@ source "drivers/vfio/pci/Kconfig"
source "drivers/vfio/platform/Kconfig"
source "drivers/vfio/mdev/Kconfig"
source "drivers/vfio/fsl-mc/Kconfig"
+endif
+
source "virt/lib/Kconfig"
diff --git a/drivers/vfio/fsl-mc/Kconfig b/drivers/vfio/fsl-mc/Kconfig
index b1a527d6b6f2..597d338c5c8a 100644
--- a/drivers/vfio/fsl-mc/Kconfig
+++ b/drivers/vfio/fsl-mc/Kconfig
@@ -1,6 +1,7 @@
config VFIO_FSL_MC
tristate "VFIO support for QorIQ DPAA2 fsl-mc bus devices"
- depends on VFIO && FSL_MC_BUS && EVENTFD
+ depends on FSL_MC_BUS
+ select EVENTFD
help
Driver to enable support for the VFIO QorIQ DPAA2 fsl-mc
(Management Complex) devices. This is required to passthrough
diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
index 90cad109583b..0ead91bfa838 100644
--- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
@@ -19,81 +19,10 @@
static struct fsl_mc_driver vfio_fsl_mc_driver;
-static DEFINE_MUTEX(reflck_lock);
-
-static void vfio_fsl_mc_reflck_get(struct vfio_fsl_mc_reflck *reflck)
-{
- kref_get(&reflck->kref);
-}
-
-static void vfio_fsl_mc_reflck_release(struct kref *kref)
-{
- struct vfio_fsl_mc_reflck *reflck = container_of(kref,
- struct vfio_fsl_mc_reflck,
- kref);
-
- mutex_destroy(&reflck->lock);
- kfree(reflck);
- mutex_unlock(&reflck_lock);
-}
-
-static void vfio_fsl_mc_reflck_put(struct vfio_fsl_mc_reflck *reflck)
-{
- kref_put_mutex(&reflck->kref, vfio_fsl_mc_reflck_release, &reflck_lock);
-}
-
-static struct vfio_fsl_mc_reflck *vfio_fsl_mc_reflck_alloc(void)
-{
- struct vfio_fsl_mc_reflck *reflck;
-
- reflck = kzalloc(sizeof(*reflck), GFP_KERNEL);
- if (!reflck)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&reflck->kref);
- mutex_init(&reflck->lock);
-
- return reflck;
-}
-
-static int vfio_fsl_mc_reflck_attach(struct vfio_fsl_mc_device *vdev)
-{
- int ret = 0;
-
- mutex_lock(&reflck_lock);
- if (is_fsl_mc_bus_dprc(vdev->mc_dev)) {
- vdev->reflck = vfio_fsl_mc_reflck_alloc();
- ret = PTR_ERR_OR_ZERO(vdev->reflck);
- } else {
- struct device *mc_cont_dev = vdev->mc_dev->dev.parent;
- struct vfio_device *device;
- struct vfio_fsl_mc_device *cont_vdev;
-
- device = vfio_device_get_from_dev(mc_cont_dev);
- if (!device) {
- ret = -ENODEV;
- goto unlock;
- }
-
- cont_vdev =
- container_of(device, struct vfio_fsl_mc_device, vdev);
- if (!cont_vdev || !cont_vdev->reflck) {
- vfio_device_put(device);
- ret = -ENODEV;
- goto unlock;
- }
- vfio_fsl_mc_reflck_get(cont_vdev->reflck);
- vdev->reflck = cont_vdev->reflck;
- vfio_device_put(device);
- }
-
-unlock:
- mutex_unlock(&reflck_lock);
- return ret;
-}
-
-static int vfio_fsl_mc_regions_init(struct vfio_fsl_mc_device *vdev)
+static int vfio_fsl_mc_open_device(struct vfio_device *core_vdev)
{
+ struct vfio_fsl_mc_device *vdev =
+ container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
struct fsl_mc_device *mc_dev = vdev->mc_dev;
int count = mc_dev->obj_desc.region_count;
int i;
@@ -136,58 +65,30 @@ static void vfio_fsl_mc_regions_cleanup(struct vfio_fsl_mc_device *vdev)
kfree(vdev->regions);
}
-static int vfio_fsl_mc_open(struct vfio_device *core_vdev)
-{
- struct vfio_fsl_mc_device *vdev =
- container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
- int ret = 0;
-
- mutex_lock(&vdev->reflck->lock);
- if (!vdev->refcnt) {
- ret = vfio_fsl_mc_regions_init(vdev);
- if (ret)
- goto out;
- }
- vdev->refcnt++;
-out:
- mutex_unlock(&vdev->reflck->lock);
-
- return ret;
-}
-static void vfio_fsl_mc_release(struct vfio_device *core_vdev)
+static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev)
{
struct vfio_fsl_mc_device *vdev =
container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
+ struct fsl_mc_device *mc_dev = vdev->mc_dev;
+ struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev);
+ struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev);
int ret;
- mutex_lock(&vdev->reflck->lock);
+ vfio_fsl_mc_regions_cleanup(vdev);
- if (!(--vdev->refcnt)) {
- struct fsl_mc_device *mc_dev = vdev->mc_dev;
- struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev);
- struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev);
+ /* reset the device before cleaning up the interrupts */
+ ret = dprc_reset_container(mc_cont->mc_io, 0, mc_cont->mc_handle,
+ mc_cont->obj_desc.id,
+ DPRC_RESET_OPTION_NON_RECURSIVE);
- vfio_fsl_mc_regions_cleanup(vdev);
+ if (WARN_ON(ret))
+ dev_warn(&mc_cont->dev,
+ "VFIO_FLS_MC: reset device has failed (%d)\n", ret);
- /* reset the device before cleaning up the interrupts */
- ret = dprc_reset_container(mc_cont->mc_io, 0,
- mc_cont->mc_handle,
- mc_cont->obj_desc.id,
- DPRC_RESET_OPTION_NON_RECURSIVE);
+ vfio_fsl_mc_irqs_cleanup(vdev);
- if (ret) {
- dev_warn(&mc_cont->dev, "VFIO_FLS_MC: reset device has failed (%d)\n",
- ret);
- WARN_ON(1);
- }
-
- vfio_fsl_mc_irqs_cleanup(vdev);
-
- fsl_mc_cleanup_irq_pool(mc_cont);
- }
-
- mutex_unlock(&vdev->reflck->lock);
+ fsl_mc_cleanup_irq_pool(mc_cont);
}
static long vfio_fsl_mc_ioctl(struct vfio_device *core_vdev,
@@ -504,8 +405,8 @@ static int vfio_fsl_mc_mmap(struct vfio_device *core_vdev,
static const struct vfio_device_ops vfio_fsl_mc_ops = {
.name = "vfio-fsl-mc",
- .open = vfio_fsl_mc_open,
- .release = vfio_fsl_mc_release,
+ .open_device = vfio_fsl_mc_open_device,
+ .close_device = vfio_fsl_mc_close_device,
.ioctl = vfio_fsl_mc_ioctl,
.read = vfio_fsl_mc_read,
.write = vfio_fsl_mc_write,
@@ -625,13 +526,16 @@ static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev)
vdev->mc_dev = mc_dev;
mutex_init(&vdev->igate);
- ret = vfio_fsl_mc_reflck_attach(vdev);
+ if (is_fsl_mc_bus_dprc(mc_dev))
+ ret = vfio_assign_device_set(&vdev->vdev, &mc_dev->dev);
+ else
+ ret = vfio_assign_device_set(&vdev->vdev, mc_dev->dev.parent);
if (ret)
- goto out_kfree;
+ goto out_uninit;
ret = vfio_fsl_mc_init_device(vdev);
if (ret)
- goto out_reflck;
+ goto out_uninit;
ret = vfio_register_group_dev(&vdev->vdev);
if (ret) {
@@ -639,12 +543,6 @@ static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev)
goto out_device;
}
- /*
- * This triggers recursion into vfio_fsl_mc_probe() on another device
- * and the vfio_fsl_mc_reflck_attach() must succeed, which relies on the
- * vfio_add_group_dev() above. It has no impact on this vdev, so it is
- * safe to be after the vfio device is made live.
- */
ret = vfio_fsl_mc_scan_container(mc_dev);
if (ret)
goto out_group_dev;
@@ -655,9 +553,8 @@ out_group_dev:
vfio_unregister_group_dev(&vdev->vdev);
out_device:
vfio_fsl_uninit_device(vdev);
-out_reflck:
- vfio_fsl_mc_reflck_put(vdev->reflck);
-out_kfree:
+out_uninit:
+ vfio_uninit_group_dev(&vdev->vdev);
kfree(vdev);
out_group_put:
vfio_iommu_group_put(group, dev);
@@ -674,8 +571,8 @@ static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev)
dprc_remove_devices(mc_dev, NULL, 0);
vfio_fsl_uninit_device(vdev);
- vfio_fsl_mc_reflck_put(vdev->reflck);
+ vfio_uninit_group_dev(&vdev->vdev);
kfree(vdev);
vfio_iommu_group_put(mc_dev->dev.iommu_group, dev);
diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c b/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c
index 0d9f3002df7f..77e584093a23 100644
--- a/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c
+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c
@@ -120,7 +120,7 @@ static int vfio_fsl_mc_set_irq_trigger(struct vfio_fsl_mc_device *vdev,
if (start != 0 || count != 1)
return -EINVAL;
- mutex_lock(&vdev->reflck->lock);
+ mutex_lock(&vdev->vdev.dev_set->lock);
ret = fsl_mc_populate_irq_pool(mc_cont,
FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
if (ret)
@@ -129,7 +129,7 @@ static int vfio_fsl_mc_set_irq_trigger(struct vfio_fsl_mc_device *vdev,
ret = vfio_fsl_mc_irqs_allocate(vdev);
if (ret)
goto unlock;
- mutex_unlock(&vdev->reflck->lock);
+ mutex_unlock(&vdev->vdev.dev_set->lock);
if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
s32 fd = *(s32 *)data;
@@ -154,7 +154,7 @@ static int vfio_fsl_mc_set_irq_trigger(struct vfio_fsl_mc_device *vdev,
return 0;
unlock:
- mutex_unlock(&vdev->reflck->lock);
+ mutex_unlock(&vdev->vdev.dev_set->lock);
return ret;
}
diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
index 89700e00e77d..4ad63ececb91 100644
--- a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h
@@ -22,11 +22,6 @@ struct vfio_fsl_mc_irq {
char *name;
};
-struct vfio_fsl_mc_reflck {
- struct kref kref;
- struct mutex lock;
-};
-
struct vfio_fsl_mc_region {
u32 flags;
u32 type;
@@ -39,9 +34,7 @@ struct vfio_fsl_mc_device {
struct vfio_device vdev;
struct fsl_mc_device *mc_dev;
struct notifier_block nb;
- int refcnt;
struct vfio_fsl_mc_region *regions;
- struct vfio_fsl_mc_reflck *reflck;
struct mutex igate;
struct vfio_fsl_mc_irq *mc_irqs;
};
diff --git a/drivers/vfio/mdev/Kconfig b/drivers/vfio/mdev/Kconfig
index 763c877a1318..646dbed44eb2 100644
--- a/drivers/vfio/mdev/Kconfig
+++ b/drivers/vfio/mdev/Kconfig
@@ -2,7 +2,6 @@
config VFIO_MDEV
tristate "Mediated device driver framework"
- depends on VFIO
default n
help
Provides a framework to virtualize devices.
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index e4581ec093a6..b314101237fe 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -138,10 +138,6 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
if (!dev)
return -EINVAL;
- /* Not mandatory, but its absence could be a problem */
- if (!ops->request)
- dev_info(dev, "Driver cannot be asked to release device\n");
-
mutex_lock(&parent_list_lock);
/* Check for duplicate */
@@ -398,7 +394,7 @@ static void __exit mdev_exit(void)
mdev_bus_unregister();
}
-module_init(mdev_init)
+subsys_initcall(mdev_init)
module_exit(mdev_exit)
MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
index c368ec824e2b..e2cb1ff56f6c 100644
--- a/drivers/vfio/mdev/mdev_driver.c
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -57,7 +57,7 @@ static int mdev_probe(struct device *dev)
return ret;
}
-static int mdev_remove(struct device *dev)
+static void mdev_remove(struct device *dev)
{
struct mdev_driver *drv =
container_of(dev->driver, struct mdev_driver, driver);
@@ -67,8 +67,6 @@ static int mdev_remove(struct device *dev)
drv->remove(mdev);
mdev_detach_iommu(mdev);
-
- return 0;
}
static int mdev_match(struct device *dev, struct device_driver *drv)
diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
index 39ef7489fe47..7a9883048216 100644
--- a/drivers/vfio/mdev/vfio_mdev.c
+++ b/drivers/vfio/mdev/vfio_mdev.c
@@ -17,24 +17,24 @@
#include "mdev_private.h"
-static int vfio_mdev_open(struct vfio_device *core_vdev)
+static int vfio_mdev_open_device(struct vfio_device *core_vdev)
{
struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
struct mdev_parent *parent = mdev->type->parent;
- if (unlikely(!parent->ops->open))
- return -EINVAL;
+ if (unlikely(!parent->ops->open_device))
+ return 0;
- return parent->ops->open(mdev);
+ return parent->ops->open_device(mdev);
}
-static void vfio_mdev_release(struct vfio_device *core_vdev)
+static void vfio_mdev_close_device(struct vfio_device *core_vdev)
{
struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
struct mdev_parent *parent = mdev->type->parent;
- if (likely(parent->ops->release))
- parent->ops->release(mdev);
+ if (likely(parent->ops->close_device))
+ parent->ops->close_device(mdev);
}
static long vfio_mdev_unlocked_ioctl(struct vfio_device *core_vdev,
@@ -44,7 +44,7 @@ static long vfio_mdev_unlocked_ioctl(struct vfio_device *core_vdev,
struct mdev_parent *parent = mdev->type->parent;
if (unlikely(!parent->ops->ioctl))
- return -EINVAL;
+ return 0;
return parent->ops->ioctl(mdev, cmd, arg);
}
@@ -100,8 +100,8 @@ static void vfio_mdev_request(struct vfio_device *core_vdev, unsigned int count)
static const struct vfio_device_ops vfio_mdev_dev_ops = {
.name = "vfio-mdev",
- .open = vfio_mdev_open,
- .release = vfio_mdev_release,
+ .open_device = vfio_mdev_open_device,
+ .close_device = vfio_mdev_close_device,
.ioctl = vfio_mdev_unlocked_ioctl,
.read = vfio_mdev_read,
.write = vfio_mdev_write,
@@ -120,12 +120,16 @@ static int vfio_mdev_probe(struct mdev_device *mdev)
vfio_init_group_dev(vdev, &mdev->dev, &vfio_mdev_dev_ops);
ret = vfio_register_group_dev(vdev);
- if (ret) {
- kfree(vdev);
- return ret;
- }
+ if (ret)
+ goto out_uninit;
+
dev_set_drvdata(&mdev->dev, vdev);
return 0;
+
+out_uninit:
+ vfio_uninit_group_dev(vdev);
+ kfree(vdev);
+ return ret;
}
static void vfio_mdev_remove(struct mdev_device *mdev)
@@ -133,6 +137,7 @@ static void vfio_mdev_remove(struct mdev_device *mdev)
struct vfio_device *vdev = dev_get_drvdata(&mdev->dev);
vfio_unregister_group_dev(vdev);
+ vfio_uninit_group_dev(vdev);
kfree(vdev);
}
diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
index 5e2e1b9a9fd3..860424ccda1b 100644
--- a/drivers/vfio/pci/Kconfig
+++ b/drivers/vfio/pci/Kconfig
@@ -1,19 +1,29 @@
# SPDX-License-Identifier: GPL-2.0-only
-config VFIO_PCI
- tristate "VFIO support for PCI devices"
- depends on VFIO && PCI && EVENTFD
- depends on MMU
+if PCI && MMU
+config VFIO_PCI_CORE
+ tristate
select VFIO_VIRQFD
select IRQ_BYPASS_MANAGER
+
+config VFIO_PCI_MMAP
+ def_bool y if !S390
+
+config VFIO_PCI_INTX
+ def_bool y if !S390
+
+config VFIO_PCI
+ tristate "Generic VFIO support for any PCI device"
+ select VFIO_PCI_CORE
help
- Support for the PCI VFIO bus driver. This is required to make
- use of PCI drivers using the VFIO framework.
+ Support for the generic PCI VFIO bus driver which can connect any
+ PCI device to the VFIO framework.
If you don't know what to do here, say N.
+if VFIO_PCI
config VFIO_PCI_VGA
- bool "VFIO PCI support for VGA devices"
- depends on VFIO_PCI && X86 && VGA_ARB
+ bool "Generic VFIO PCI support for VGA devices"
+ depends on X86 && VGA_ARB
help
Support for VGA extension to VFIO PCI. This exposes an additional
region on VGA devices for accessing legacy VGA addresses used by
@@ -21,17 +31,9 @@ config VFIO_PCI_VGA
If you don't know what to do here, say N.
-config VFIO_PCI_MMAP
- depends on VFIO_PCI
- def_bool y if !S390
-
-config VFIO_PCI_INTX
- depends on VFIO_PCI
- def_bool y if !S390
-
config VFIO_PCI_IGD
- bool "VFIO PCI extensions for Intel graphics (GVT-d)"
- depends on VFIO_PCI && X86
+ bool "Generic VFIO PCI extensions for Intel graphics (GVT-d)"
+ depends on X86
default y
help
Support for Intel IGD specific extensions to enable direct
@@ -40,3 +42,5 @@ config VFIO_PCI_IGD
and LPC bridge config space.
To enable Intel IGD assignment through vfio-pci, say Y.
+endif
+endif
diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index 3ff42093962f..349d68d242b4 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,7 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
-vfio-pci-$(CONFIG_VFIO_PCI_IGD) += vfio_pci_igd.o
-vfio-pci-$(CONFIG_S390) += vfio_pci_zdev.o
+vfio-pci-core-y := vfio_pci_core.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
+vfio-pci-core-$(CONFIG_S390) += vfio_pci_zdev.o
+obj-$(CONFIG_VFIO_PCI_CORE) += vfio-pci-core.o
+vfio-pci-y := vfio_pci.o
+vfio-pci-$(CONFIG_VFIO_PCI_IGD) += vfio_pci_igd.o
obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 318864d52837..a5ce92beb655 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
+ * Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved
+ *
* Copyright (C) 2012 Red Hat, Inc. All rights reserved.
* Author: Alex Williamson <alex.williamson@redhat.com>
*
@@ -18,19 +20,13 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/notifier.h>
-#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uaccess.h>
-#include <linux/vfio.h>
-#include <linux/vgaarb.h>
-#include <linux/nospec.h>
-#include <linux/sched/mm.h>
-#include "vfio_pci_private.h"
+#include <linux/vfio_pci_core.h>
-#define DRIVER_VERSION "0.2"
#define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>"
#define DRIVER_DESC "VFIO PCI - User Level meta-driver"
@@ -64,15 +60,6 @@ static bool disable_denylist;
module_param(disable_denylist, bool, 0444);
MODULE_PARM_DESC(disable_denylist, "Disable use of device denylist. Disabling the denylist allows binding to devices with known errata that may lead to exploitable stability or security issues when accessed by untrusted users.");
-static inline bool vfio_vga_disabled(void)
-{
-#ifdef CONFIG_VFIO_PCI_VGA
- return disable_vga;
-#else
- return true;
-#endif
-}
-
static bool vfio_pci_dev_in_denylist(struct pci_dev *pdev)
{
switch (pdev->vendor) {
@@ -111,2270 +98,103 @@ static bool vfio_pci_is_denylisted(struct pci_dev *pdev)
return true;
}
-/*
- * Our VGA arbiter participation is limited since we don't know anything
- * about the device itself. However, if the device is the only VGA device
- * downstream of a bridge and VFIO VGA support is disabled, then we can
- * safely return legacy VGA IO and memory as not decoded since the user
- * has no way to get to it and routing can be disabled externally at the
- * bridge.
- */
-static unsigned int vfio_pci_set_vga_decode(void *opaque, bool single_vga)
-{
- struct vfio_pci_device *vdev = opaque;
- struct pci_dev *tmp = NULL, *pdev = vdev->pdev;
- unsigned char max_busnr;
- unsigned int decodes;
-
- if (single_vga || !vfio_vga_disabled() || pci_is_root_bus(pdev->bus))
- return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
- VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
-
- max_busnr = pci_bus_max_busnr(pdev->bus);
- decodes = VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
-
- while ((tmp = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, tmp)) != NULL) {
- if (tmp == pdev ||
- pci_domain_nr(tmp->bus) != pci_domain_nr(pdev->bus) ||
- pci_is_root_bus(tmp->bus))
- continue;
-
- if (tmp->bus->number >= pdev->bus->number &&
- tmp->bus->number <= max_busnr) {
- pci_dev_put(tmp);
- decodes |= VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
- break;
- }
- }
-
- return decodes;
-}
-
-static inline bool vfio_pci_is_vga(struct pci_dev *pdev)
-{
- return (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
-}
-
-static void vfio_pci_probe_mmaps(struct vfio_pci_device *vdev)
-{
- struct resource *res;
- int i;
- struct vfio_pci_dummy_resource *dummy_res;
-
- for (i = 0; i < PCI_STD_NUM_BARS; i++) {
- int bar = i + PCI_STD_RESOURCES;
-
- res = &vdev->pdev->resource[bar];
-
- if (!IS_ENABLED(CONFIG_VFIO_PCI_MMAP))
- goto no_mmap;
-
- if (!(res->flags & IORESOURCE_MEM))
- goto no_mmap;
-
- /*
- * The PCI core shouldn't set up a resource with a
- * type but zero size. But there may be bugs that
- * cause us to do that.
- */
- if (!resource_size(res))
- goto no_mmap;
-
- if (resource_size(res) >= PAGE_SIZE) {
- vdev->bar_mmap_supported[bar] = true;
- continue;
- }
-
- if (!(res->start & ~PAGE_MASK)) {
- /*
- * Add a dummy resource to reserve the remainder
- * of the exclusive page in case that hot-add
- * device's bar is assigned into it.
- */
- dummy_res = kzalloc(sizeof(*dummy_res), GFP_KERNEL);
- if (dummy_res == NULL)
- goto no_mmap;
-
- dummy_res->resource.name = "vfio sub-page reserved";
- dummy_res->resource.start = res->end + 1;
- dummy_res->resource.end = res->start + PAGE_SIZE - 1;
- dummy_res->resource.flags = res->flags;
- if (request_resource(res->parent,
- &dummy_res->resource)) {
- kfree(dummy_res);
- goto no_mmap;
- }
- dummy_res->index = bar;
- list_add(&dummy_res->res_next,
- &vdev->dummy_resources_list);
- vdev->bar_mmap_supported[bar] = true;
- continue;
- }
- /*
- * Here we don't handle the case when the BAR is not page
- * aligned because we can't expect the BAR will be
- * assigned into the same location in a page in guest
- * when we passthrough the BAR. And it's hard to access
- * this BAR in userspace because we have no way to get
- * the BAR's location in a page.
- */
-no_mmap:
- vdev->bar_mmap_supported[bar] = false;
- }
-}
-
-static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev);
-static void vfio_pci_disable(struct vfio_pci_device *vdev);
-static int vfio_pci_try_zap_and_vma_lock_cb(struct pci_dev *pdev, void *data);
-
-/*
- * INTx masking requires the ability to disable INTx signaling via PCI_COMMAND
- * _and_ the ability detect when the device is asserting INTx via PCI_STATUS.
- * If a device implements the former but not the latter we would typically
- * expect broken_intx_masking be set and require an exclusive interrupt.
- * However since we do have control of the device's ability to assert INTx,
- * we can instead pretend that the device does not implement INTx, virtualizing
- * the pin register to report zero and maintaining DisINTx set on the host.
- */
-static bool vfio_pci_nointx(struct pci_dev *pdev)
-{
- switch (pdev->vendor) {
- case PCI_VENDOR_ID_INTEL:
- switch (pdev->device) {
- /* All i40e (XL710/X710/XXV710) 10/20/25/40GbE NICs */
- case 0x1572:
- case 0x1574:
- case 0x1580 ... 0x1581:
- case 0x1583 ... 0x158b:
- case 0x37d0 ... 0x37d2:
- /* X550 */
- case 0x1563:
- return true;
- default:
- return false;
- }
- }
-
- return false;
-}
-
-static void vfio_pci_probe_power_state(struct vfio_pci_device *vdev)
+static int vfio_pci_open_device(struct vfio_device *core_vdev)
{
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
struct pci_dev *pdev = vdev->pdev;
- u16 pmcsr;
-
- if (!pdev->pm_cap)
- return;
-
- pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmcsr);
-
- vdev->needs_pm_restore = !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET);
-}
-
-/*
- * pci_set_power_state() wrapper handling devices which perform a soft reset on
- * D3->D0 transition. Save state prior to D0/1/2->D3, stash it on the vdev,
- * restore when returned to D0. Saved separately from pci_saved_state for use
- * by PM capability emulation and separately from pci_dev internal saved state
- * to avoid it being overwritten and consumed around other resets.
- */
-int vfio_pci_set_power_state(struct vfio_pci_device *vdev, pci_power_t state)
-{
- struct pci_dev *pdev = vdev->pdev;
- bool needs_restore = false, needs_save = false;
int ret;
- if (vdev->needs_pm_restore) {
- if (pdev->current_state < PCI_D3hot && state >= PCI_D3hot) {
- pci_save_state(pdev);
- needs_save = true;
- }
-
- if (pdev->current_state >= PCI_D3hot && state <= PCI_D0)
- needs_restore = true;
- }
-
- ret = pci_set_power_state(pdev, state);
-
- if (!ret) {
- /* D3 might be unsupported via quirk, skip unless in D3 */
- if (needs_save && pdev->current_state >= PCI_D3hot) {
- vdev->pm_save = pci_store_saved_state(pdev);
- } else if (needs_restore) {
- pci_load_and_free_saved_state(pdev, &vdev->pm_save);
- pci_restore_state(pdev);
- }
- }
-
- return ret;
-}
-
-static int vfio_pci_enable(struct vfio_pci_device *vdev)
-{
- struct pci_dev *pdev = vdev->pdev;
- int ret;
- u16 cmd;
- u8 msix_pos;
-
- vfio_pci_set_power_state(vdev, PCI_D0);
-
- /* Don't allow our initial saved state to include busmaster */
- pci_clear_master(pdev);
-
- ret = pci_enable_device(pdev);
+ ret = vfio_pci_core_enable(vdev);
if (ret)
return ret;
- /* If reset fails because of the device lock, fail this path entirely */
- ret = pci_try_reset_function(pdev);
- if (ret == -EAGAIN) {
- pci_disable_device(pdev);
- return ret;
- }
-
- vdev->reset_works = !ret;
- pci_save_state(pdev);
- vdev->pci_saved_state = pci_store_saved_state(pdev);
- if (!vdev->pci_saved_state)
- pci_dbg(pdev, "%s: Couldn't store saved state\n", __func__);
-
- if (likely(!nointxmask)) {
- if (vfio_pci_nointx(pdev)) {
- pci_info(pdev, "Masking broken INTx support\n");
- vdev->nointx = true;
- pci_intx(pdev, 0);
- } else
- vdev->pci_2_3 = pci_intx_mask_supported(pdev);
- }
-
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- if (vdev->pci_2_3 && (cmd & PCI_COMMAND_INTX_DISABLE)) {
- cmd &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(pdev, PCI_COMMAND, cmd);
- }
-
- ret = vfio_config_init(vdev);
- if (ret) {
- kfree(vdev->pci_saved_state);
- vdev->pci_saved_state = NULL;
- pci_disable_device(pdev);
- return ret;
- }
-
- msix_pos = pdev->msix_cap;
- if (msix_pos) {
- u16 flags;
- u32 table;
-
- pci_read_config_word(pdev, msix_pos + PCI_MSIX_FLAGS, &flags);
- pci_read_config_dword(pdev, msix_pos + PCI_MSIX_TABLE, &table);
-
- vdev->msix_bar = table & PCI_MSIX_TABLE_BIR;
- vdev->msix_offset = table & PCI_MSIX_TABLE_OFFSET;
- vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16;
- } else
- vdev->msix_bar = 0xFF;
-
- if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
- vdev->has_vga = true;
-
if (vfio_pci_is_vga(pdev) &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
IS_ENABLED(CONFIG_VFIO_PCI_IGD)) {
ret = vfio_pci_igd_init(vdev);
if (ret && ret != -ENODEV) {
pci_warn(pdev, "Failed to setup Intel IGD regions\n");
- goto disable_exit;
- }
- }
-
- vfio_pci_probe_mmaps(vdev);
-
- return 0;
-
-disable_exit:
- vfio_pci_disable(vdev);
- return ret;
-}
-
-static void vfio_pci_disable(struct vfio_pci_device *vdev)
-{
- struct pci_dev *pdev = vdev->pdev;
- struct vfio_pci_dummy_resource *dummy_res, *tmp;
- struct vfio_pci_ioeventfd *ioeventfd, *ioeventfd_tmp;
- int i, bar;
-
- /* Stop the device from further DMA */
- pci_clear_master(pdev);
-
- vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE |
- VFIO_IRQ_SET_ACTION_TRIGGER,
- vdev->irq_type, 0, 0, NULL);
-
- /* Device closed, don't need mutex here */
- list_for_each_entry_safe(ioeventfd, ioeventfd_tmp,
- &vdev->ioeventfds_list, next) {
- vfio_virqfd_disable(&ioeventfd->virqfd);
- list_del(&ioeventfd->next);
- kfree(ioeventfd);
- }
- vdev->ioeventfds_nr = 0;
-
- vdev->virq_disabled = false;
-
- for (i = 0; i < vdev->num_regions; i++)
- vdev->region[i].ops->release(vdev, &vdev->region[i]);
-
- vdev->num_regions = 0;
- kfree(vdev->region);
- vdev->region = NULL; /* don't krealloc a freed pointer */
-
- vfio_config_free(vdev);
-
- for (i = 0; i < PCI_STD_NUM_BARS; i++) {
- bar = i + PCI_STD_RESOURCES;
- if (!vdev->barmap[bar])
- continue;
- pci_iounmap(pdev, vdev->barmap[bar]);
- pci_release_selected_regions(pdev, 1 << bar);
- vdev->barmap[bar] = NULL;
- }
-
- list_for_each_entry_safe(dummy_res, tmp,
- &vdev->dummy_resources_list, res_next) {
- list_del(&dummy_res->res_next);
- release_resource(&dummy_res->resource);
- kfree(dummy_res);
- }
-
- vdev->needs_reset = true;
-
- /*
- * If we have saved state, restore it. If we can reset the device,
- * even better. Resetting with current state seems better than
- * nothing, but saving and restoring current state without reset
- * is just busy work.
- */
- if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
- pci_info(pdev, "%s: Couldn't reload saved state\n", __func__);
-
- if (!vdev->reset_works)
- goto out;
-
- pci_save_state(pdev);
- }
-
- /*
- * Disable INTx and MSI, presumably to avoid spurious interrupts
- * during reset. Stolen from pci_reset_function()
- */
- pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
-
- /*
- * Try to get the locks ourselves to prevent a deadlock. The
- * success of this is dependent on being able to lock the device,
- * which is not always possible.
- * We can not use the "try" reset interface here, which will
- * overwrite the previously restored configuration information.
- */
- if (vdev->reset_works && pci_dev_trylock(pdev)) {
- if (!__pci_reset_function_locked(pdev))
- vdev->needs_reset = false;
- pci_dev_unlock(pdev);
- }
-
- pci_restore_state(pdev);
-out:
- pci_disable_device(pdev);
-
- vfio_pci_try_bus_reset(vdev);
-
- if (!disable_idle_d3)
- vfio_pci_set_power_state(vdev, PCI_D3hot);
-}
-
-static struct pci_driver vfio_pci_driver;
-
-static struct vfio_pci_device *get_pf_vdev(struct vfio_pci_device *vdev)
-{
- struct pci_dev *physfn = pci_physfn(vdev->pdev);
- struct vfio_device *pf_dev;
-
- if (!vdev->pdev->is_virtfn)
- return NULL;
-
- pf_dev = vfio_device_get_from_dev(&physfn->dev);
- if (!pf_dev)
- return NULL;
-
- if (pci_dev_driver(physfn) != &vfio_pci_driver) {
- vfio_device_put(pf_dev);
- return NULL;
- }
-
- return container_of(pf_dev, struct vfio_pci_device, vdev);
-}
-
-static void vfio_pci_vf_token_user_add(struct vfio_pci_device *vdev, int val)
-{
- struct vfio_pci_device *pf_vdev = get_pf_vdev(vdev);
-
- if (!pf_vdev)
- return;
-
- mutex_lock(&pf_vdev->vf_token->lock);
- pf_vdev->vf_token->users += val;
- WARN_ON(pf_vdev->vf_token->users < 0);
- mutex_unlock(&pf_vdev->vf_token->lock);
-
- vfio_device_put(&pf_vdev->vdev);
-}
-
-static void vfio_pci_release(struct vfio_device *core_vdev)
-{
- struct vfio_pci_device *vdev =
- container_of(core_vdev, struct vfio_pci_device, vdev);
-
- mutex_lock(&vdev->reflck->lock);
-
- if (!(--vdev->refcnt)) {
- vfio_pci_vf_token_user_add(vdev, -1);
- vfio_spapr_pci_eeh_release(vdev->pdev);
- vfio_pci_disable(vdev);
-
- mutex_lock(&vdev->igate);
- if (vdev->err_trigger) {
- eventfd_ctx_put(vdev->err_trigger);
- vdev->err_trigger = NULL;
- }
- if (vdev->req_trigger) {
- eventfd_ctx_put(vdev->req_trigger);
- vdev->req_trigger = NULL;
- }
- mutex_unlock(&vdev->igate);
- }
-
- mutex_unlock(&vdev->reflck->lock);
-}
-
-static int vfio_pci_open(struct vfio_device *core_vdev)
-{
- struct vfio_pci_device *vdev =
- container_of(core_vdev, struct vfio_pci_device, vdev);
- int ret = 0;
-
- mutex_lock(&vdev->reflck->lock);
-
- if (!vdev->refcnt) {
- ret = vfio_pci_enable(vdev);
- if (ret)
- goto error;
-
- vfio_spapr_pci_eeh_open(vdev->pdev);
- vfio_pci_vf_token_user_add(vdev, 1);
- }
- vdev->refcnt++;
-error:
- mutex_unlock(&vdev->reflck->lock);
- return ret;
-}
-
-static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
-{
- if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) {
- u8 pin;
-
- if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) ||
- vdev->nointx || vdev->pdev->is_virtfn)
- return 0;
-
- pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin);
-
- return pin ? 1 : 0;
- } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) {
- u8 pos;
- u16 flags;
-
- pos = vdev->pdev->msi_cap;
- if (pos) {
- pci_read_config_word(vdev->pdev,
- pos + PCI_MSI_FLAGS, &flags);
- return 1 << ((flags & PCI_MSI_FLAGS_QMASK) >> 1);
- }
- } else if (irq_type == VFIO_PCI_MSIX_IRQ_INDEX) {
- u8 pos;
- u16 flags;
-
- pos = vdev->pdev->msix_cap;
- if (pos) {
- pci_read_config_word(vdev->pdev,
- pos + PCI_MSIX_FLAGS, &flags);
-
- return (flags & PCI_MSIX_FLAGS_QSIZE) + 1;
- }
- } else if (irq_type == VFIO_PCI_ERR_IRQ_INDEX) {
- if (pci_is_pcie(vdev->pdev))
- return 1;
- } else if (irq_type == VFIO_PCI_REQ_IRQ_INDEX) {
- return 1;
- }
-
- return 0;
-}
-
-static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)
-{
- (*(int *)data)++;
- return 0;
-}
-
-struct vfio_pci_fill_info {
- int max;
- int cur;
- struct vfio_pci_dependent_device *devices;
-};
-
-static int vfio_pci_fill_devs(struct pci_dev *pdev, void *data)
-{
- struct vfio_pci_fill_info *fill = data;
- struct iommu_group *iommu_group;
-
- if (fill->cur == fill->max)
- return -EAGAIN; /* Something changed, try again */
-
- iommu_group = iommu_group_get(&pdev->dev);
- if (!iommu_group)
- return -EPERM; /* Cannot reset non-isolated devices */
-
- fill->devices[fill->cur].group_id = iommu_group_id(iommu_group);
- fill->devices[fill->cur].segment = pci_domain_nr(pdev->bus);
- fill->devices[fill->cur].bus = pdev->bus->number;
- fill->devices[fill->cur].devfn = pdev->devfn;
- fill->cur++;
- iommu_group_put(iommu_group);
- return 0;
-}
-
-struct vfio_pci_group_entry {
- struct vfio_group *group;
- int id;
-};
-
-struct vfio_pci_group_info {
- int count;
- struct vfio_pci_group_entry *groups;
-};
-
-static int vfio_pci_validate_devs(struct pci_dev *pdev, void *data)
-{
- struct vfio_pci_group_info *info = data;
- struct iommu_group *group;
- int id, i;
-
- group = iommu_group_get(&pdev->dev);
- if (!group)
- return -EPERM;
-
- id = iommu_group_id(group);
-
- for (i = 0; i < info->count; i++)
- if (info->groups[i].id == id)
- break;
-
- iommu_group_put(group);
-
- return (i == info->count) ? -EINVAL : 0;
-}
-
-static bool vfio_pci_dev_below_slot(struct pci_dev *pdev, struct pci_slot *slot)
-{
- for (; pdev; pdev = pdev->bus->self)
- if (pdev->bus == slot->bus)
- return (pdev->slot == slot);
- return false;
-}
-
-struct vfio_pci_walk_info {
- int (*fn)(struct pci_dev *, void *data);
- void *data;
- struct pci_dev *pdev;
- bool slot;
- int ret;
-};
-
-static int vfio_pci_walk_wrapper(struct pci_dev *pdev, void *data)
-{
- struct vfio_pci_walk_info *walk = data;
-
- if (!walk->slot || vfio_pci_dev_below_slot(pdev, walk->pdev->slot))
- walk->ret = walk->fn(pdev, walk->data);
-
- return walk->ret;
-}
-
-static int vfio_pci_for_each_slot_or_bus(struct pci_dev *pdev,
- int (*fn)(struct pci_dev *,
- void *data), void *data,
- bool slot)
-{
- struct vfio_pci_walk_info walk = {
- .fn = fn, .data = data, .pdev = pdev, .slot = slot, .ret = 0,
- };
-
- pci_walk_bus(pdev->bus, vfio_pci_walk_wrapper, &walk);
-
- return walk.ret;
-}
-
-static int msix_mmappable_cap(struct vfio_pci_device *vdev,
- struct vfio_info_cap *caps)
-{
- struct vfio_info_cap_header header = {
- .id = VFIO_REGION_INFO_CAP_MSIX_MAPPABLE,
- .version = 1
- };
-
- return vfio_info_add_capability(caps, &header, sizeof(header));
-}
-
-int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
- unsigned int type, unsigned int subtype,
- const struct vfio_pci_regops *ops,
- size_t size, u32 flags, void *data)
-{
- struct vfio_pci_region *region;
-
- region = krealloc(vdev->region,
- (vdev->num_regions + 1) * sizeof(*region),
- GFP_KERNEL);
- if (!region)
- return -ENOMEM;
-
- vdev->region = region;
- vdev->region[vdev->num_regions].type = type;
- vdev->region[vdev->num_regions].subtype = subtype;
- vdev->region[vdev->num_regions].ops = ops;
- vdev->region[vdev->num_regions].size = size;
- vdev->region[vdev->num_regions].flags = flags;
- vdev->region[vdev->num_regions].data = data;
-
- vdev->num_regions++;
-
- return 0;
-}
-
-struct vfio_devices {
- struct vfio_pci_device **devices;
- int cur_index;
- int max_index;
-};
-
-static long vfio_pci_ioctl(struct vfio_device *core_vdev,
- unsigned int cmd, unsigned long arg)
-{
- struct vfio_pci_device *vdev =
- container_of(core_vdev, struct vfio_pci_device, vdev);
- unsigned long minsz;
-
- if (cmd == VFIO_DEVICE_GET_INFO) {
- struct vfio_device_info info;
- struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
- unsigned long capsz;
- int ret;
-
- minsz = offsetofend(struct vfio_device_info, num_irqs);
-
- /* For backward compatibility, cannot require this */
- capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset);
-
- if (copy_from_user(&info, (void __user *)arg, minsz))
- return -EFAULT;
-
- if (info.argsz < minsz)
- return -EINVAL;
-
- if (info.argsz >= capsz) {
- minsz = capsz;
- info.cap_offset = 0;
- }
-
- info.flags = VFIO_DEVICE_FLAGS_PCI;
-
- if (vdev->reset_works)
- info.flags |= VFIO_DEVICE_FLAGS_RESET;
-
- info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions;
- info.num_irqs = VFIO_PCI_NUM_IRQS;
-
- ret = vfio_pci_info_zdev_add_caps(vdev, &caps);
- if (ret && ret != -ENODEV) {
- pci_warn(vdev->pdev, "Failed to setup zPCI info capabilities\n");
- return ret;
- }
-
- if (caps.size) {
- info.flags |= VFIO_DEVICE_FLAGS_CAPS;
- if (info.argsz < sizeof(info) + caps.size) {
- info.argsz = sizeof(info) + caps.size;
- } else {
- vfio_info_cap_shift(&caps, sizeof(info));
- if (copy_to_user((void __user *)arg +
- sizeof(info), caps.buf,
- caps.size)) {
- kfree(caps.buf);
- return -EFAULT;
- }
- info.cap_offset = sizeof(info);
- }
-
- kfree(caps.buf);
- }
-
- return copy_to_user((void __user *)arg, &info, minsz) ?
- -EFAULT : 0;
-
- } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
- struct pci_dev *pdev = vdev->pdev;
- struct vfio_region_info info;
- struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
- int i, ret;
-
- minsz = offsetofend(struct vfio_region_info, offset);
-
- if (copy_from_user(&info, (void __user *)arg, minsz))
- return -EFAULT;
-
- if (info.argsz < minsz)
- return -EINVAL;
-
- switch (info.index) {
- case VFIO_PCI_CONFIG_REGION_INDEX:
- info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
- info.size = pdev->cfg_size;
- info.flags = VFIO_REGION_INFO_FLAG_READ |
- VFIO_REGION_INFO_FLAG_WRITE;
- break;
- case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
- info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
- info.size = pci_resource_len(pdev, info.index);
- if (!info.size) {
- info.flags = 0;
- break;
- }
-
- info.flags = VFIO_REGION_INFO_FLAG_READ |
- VFIO_REGION_INFO_FLAG_WRITE;
- if (vdev->bar_mmap_supported[info.index]) {
- info.flags |= VFIO_REGION_INFO_FLAG_MMAP;
- if (info.index == vdev->msix_bar) {
- ret = msix_mmappable_cap(vdev, &caps);
- if (ret)
- return ret;
- }
- }
-
- break;
- case VFIO_PCI_ROM_REGION_INDEX:
- {
- void __iomem *io;
- size_t size;
- u16 cmd;
-
- info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
- info.flags = 0;
-
- /* Report the BAR size, not the ROM size */
- info.size = pci_resource_len(pdev, info.index);
- if (!info.size) {
- /* Shadow ROMs appear as PCI option ROMs */
- if (pdev->resource[PCI_ROM_RESOURCE].flags &
- IORESOURCE_ROM_SHADOW)
- info.size = 0x20000;
- else
- break;
- }
-
- /*
- * Is it really there? Enable memory decode for
- * implicit access in pci_map_rom().
- */
- cmd = vfio_pci_memory_lock_and_enable(vdev);
- io = pci_map_rom(pdev, &size);
- if (io) {
- info.flags = VFIO_REGION_INFO_FLAG_READ;
- pci_unmap_rom(pdev, io);
- } else {
- info.size = 0;
- }
- vfio_pci_memory_unlock_and_restore(vdev, cmd);
-
- break;
- }
- case VFIO_PCI_VGA_REGION_INDEX:
- if (!vdev->has_vga)
- return -EINVAL;
-
- info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
- info.size = 0xc0000;
- info.flags = VFIO_REGION_INFO_FLAG_READ |
- VFIO_REGION_INFO_FLAG_WRITE;
-
- break;
- default:
- {
- struct vfio_region_info_cap_type cap_type = {
- .header.id = VFIO_REGION_INFO_CAP_TYPE,
- .header.version = 1 };
-
- if (info.index >=
- VFIO_PCI_NUM_REGIONS + vdev->num_regions)
- return -EINVAL;
- info.index = array_index_nospec(info.index,
- VFIO_PCI_NUM_REGIONS +
- vdev->num_regions);
-
- i = info.index - VFIO_PCI_NUM_REGIONS;
-
- info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
- info.size = vdev->region[i].size;
- info.flags = vdev->region[i].flags;
-
- cap_type.type = vdev->region[i].type;
- cap_type.subtype = vdev->region[i].subtype;
-
- ret = vfio_info_add_capability(&caps, &cap_type.header,
- sizeof(cap_type));
- if (ret)
- return ret;
-
- if (vdev->region[i].ops->add_capability) {
- ret = vdev->region[i].ops->add_capability(vdev,
- &vdev->region[i], &caps);
- if (ret)
- return ret;
- }
- }
- }
-
- if (caps.size) {
- info.flags |= VFIO_REGION_INFO_FLAG_CAPS;
- if (info.argsz < sizeof(info) + caps.size) {
- info.argsz = sizeof(info) + caps.size;
- info.cap_offset = 0;
- } else {
- vfio_info_cap_shift(&caps, sizeof(info));
- if (copy_to_user((void __user *)arg +
- sizeof(info), caps.buf,
- caps.size)) {
- kfree(caps.buf);
- return -EFAULT;
- }
- info.cap_offset = sizeof(info);
- }
-
- kfree(caps.buf);
- }
-
- return copy_to_user((void __user *)arg, &info, minsz) ?
- -EFAULT : 0;
-
- } else if (cmd == 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 >= VFIO_PCI_NUM_IRQS)
- return -EINVAL;
-
- switch (info.index) {
- case VFIO_PCI_INTX_IRQ_INDEX ... VFIO_PCI_MSIX_IRQ_INDEX:
- case VFIO_PCI_REQ_IRQ_INDEX:
- break;
- case VFIO_PCI_ERR_IRQ_INDEX:
- if (pci_is_pcie(vdev->pdev))
- break;
- fallthrough;
- default:
- return -EINVAL;
- }
-
- info.flags = VFIO_IRQ_INFO_EVENTFD;
-
- info.count = vfio_pci_get_irq_count(vdev, info.index);
-
- if (info.index == VFIO_PCI_INTX_IRQ_INDEX)
- info.flags |= (VFIO_IRQ_INFO_MASKABLE |
- VFIO_IRQ_INFO_AUTOMASKED);
- else
- info.flags |= VFIO_IRQ_INFO_NORESIZE;
-
- return copy_to_user((void __user *)arg, &info, minsz) ?
- -EFAULT : 0;
-
- } else if (cmd == VFIO_DEVICE_SET_IRQS) {
- struct vfio_irq_set hdr;
- u8 *data = NULL;
- int max, ret = 0;
- size_t data_size = 0;
-
- minsz = offsetofend(struct vfio_irq_set, count);
-
- if (copy_from_user(&hdr, (void __user *)arg, minsz))
- return -EFAULT;
-
- max = vfio_pci_get_irq_count(vdev, hdr.index);
-
- ret = vfio_set_irqs_validate_and_prepare(&hdr, max,
- VFIO_PCI_NUM_IRQS, &data_size);
- if (ret)
+ vfio_pci_core_disable(vdev);
return ret;
-
- if (data_size) {
- data = memdup_user((void __user *)(arg + minsz),
- data_size);
- if (IS_ERR(data))
- return PTR_ERR(data);
}
-
- mutex_lock(&vdev->igate);
-
- ret = vfio_pci_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
- hdr.start, hdr.count, data);
-
- mutex_unlock(&vdev->igate);
- kfree(data);
-
- return ret;
-
- } else if (cmd == VFIO_DEVICE_RESET) {
- int ret;
-
- if (!vdev->reset_works)
- return -EINVAL;
-
- vfio_pci_zap_and_down_write_memory_lock(vdev);
- ret = pci_try_reset_function(vdev->pdev);
- up_write(&vdev->memory_lock);
-
- return ret;
-
- } else if (cmd == VFIO_DEVICE_GET_PCI_HOT_RESET_INFO) {
- struct vfio_pci_hot_reset_info hdr;
- struct vfio_pci_fill_info fill = { 0 };
- struct vfio_pci_dependent_device *devices = NULL;
- bool slot = false;
- int ret = 0;
-
- minsz = offsetofend(struct vfio_pci_hot_reset_info, count);
-
- if (copy_from_user(&hdr, (void __user *)arg, minsz))
- return -EFAULT;
-
- if (hdr.argsz < minsz)
- return -EINVAL;
-
- hdr.flags = 0;
-
- /* Can we do a slot or bus reset or neither? */
- if (!pci_probe_reset_slot(vdev->pdev->slot))
- slot = true;
- else if (pci_probe_reset_bus(vdev->pdev->bus))
- return -ENODEV;
-
- /* How many devices are affected? */
- ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
- vfio_pci_count_devs,
- &fill.max, slot);
- if (ret)
- return ret;
-
- WARN_ON(!fill.max); /* Should always be at least one */
-
- /*
- * If there's enough space, fill it now, otherwise return
- * -ENOSPC and the number of devices affected.
- */
- if (hdr.argsz < sizeof(hdr) + (fill.max * sizeof(*devices))) {
- ret = -ENOSPC;
- hdr.count = fill.max;
- goto reset_info_exit;
- }
-
- devices = kcalloc(fill.max, sizeof(*devices), GFP_KERNEL);
- if (!devices)
- return -ENOMEM;
-
- fill.devices = devices;
-
- ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
- vfio_pci_fill_devs,
- &fill, slot);
-
- /*
- * If a device was removed between counting and filling,
- * we may come up short of fill.max. If a device was
- * added, we'll have a return of -EAGAIN above.
- */
- if (!ret)
- hdr.count = fill.cur;
-
-reset_info_exit:
- if (copy_to_user((void __user *)arg, &hdr, minsz))
- ret = -EFAULT;
-
- if (!ret) {
- if (copy_to_user((void __user *)(arg + minsz), devices,
- hdr.count * sizeof(*devices)))
- ret = -EFAULT;
- }
-
- kfree(devices);
- return ret;
-
- } else if (cmd == VFIO_DEVICE_PCI_HOT_RESET) {
- struct vfio_pci_hot_reset hdr;
- int32_t *group_fds;
- struct vfio_pci_group_entry *groups;
- struct vfio_pci_group_info info;
- struct vfio_devices devs = { .cur_index = 0 };
- bool slot = false;
- int i, group_idx, mem_idx = 0, count = 0, ret = 0;
-
- minsz = offsetofend(struct vfio_pci_hot_reset, count);
-
- if (copy_from_user(&hdr, (void __user *)arg, minsz))
- return -EFAULT;
-
- if (hdr.argsz < minsz || hdr.flags)
- return -EINVAL;
-
- /* Can we do a slot or bus reset or neither? */
- if (!pci_probe_reset_slot(vdev->pdev->slot))
- slot = true;
- else if (pci_probe_reset_bus(vdev->pdev->bus))
- return -ENODEV;
-
- /*
- * We can't let userspace give us an arbitrarily large
- * buffer to copy, so verify how many we think there
- * could be. Note groups can have multiple devices so
- * one group per device is the max.
- */
- ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
- vfio_pci_count_devs,
- &count, slot);
- if (ret)
- return ret;
-
- /* Somewhere between 1 and count is OK */
- if (!hdr.count || hdr.count > count)
- return -EINVAL;
-
- group_fds = kcalloc(hdr.count, sizeof(*group_fds), GFP_KERNEL);
- groups = kcalloc(hdr.count, sizeof(*groups), GFP_KERNEL);
- if (!group_fds || !groups) {
- kfree(group_fds);
- kfree(groups);
- return -ENOMEM;
- }
-
- if (copy_from_user(group_fds, (void __user *)(arg + minsz),
- hdr.count * sizeof(*group_fds))) {
- kfree(group_fds);
- kfree(groups);
- return -EFAULT;
- }
-
- /*
- * For each group_fd, get the group through the vfio external
- * user interface and store the group and iommu ID. This
- * ensures the group is held across the reset.
- */
- for (group_idx = 0; group_idx < hdr.count; group_idx++) {
- struct vfio_group *group;
- struct fd f = fdget(group_fds[group_idx]);
- if (!f.file) {
- ret = -EBADF;
- break;
- }
-
- group = vfio_group_get_external_user(f.file);
- fdput(f);
- if (IS_ERR(group)) {
- ret = PTR_ERR(group);
- break;
- }
-
- groups[group_idx].group = group;
- groups[group_idx].id =
- vfio_external_user_iommu_id(group);
- }
-
- kfree(group_fds);
-
- /* release reference to groups on error */
- if (ret)
- goto hot_reset_release;
-
- info.count = hdr.count;
- info.groups = groups;
-
- /*
- * Test whether all the affected devices are contained
- * by the set of groups provided by the user.
- */
- ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
- vfio_pci_validate_devs,
- &info, slot);
- if (ret)
- goto hot_reset_release;
-
- devs.max_index = count;
- devs.devices = kcalloc(count, sizeof(struct vfio_device *),
- GFP_KERNEL);
- if (!devs.devices) {
- ret = -ENOMEM;
- goto hot_reset_release;
- }
-
- /*
- * We need to get memory_lock for each device, but devices
- * can share mmap_lock, therefore we need to zap and hold
- * the vma_lock for each device, and only then get each
- * memory_lock.
- */
- ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
- vfio_pci_try_zap_and_vma_lock_cb,
- &devs, slot);
- if (ret)
- goto hot_reset_release;
-
- for (; mem_idx < devs.cur_index; mem_idx++) {
- struct vfio_pci_device *tmp = devs.devices[mem_idx];
-
- ret = down_write_trylock(&tmp->memory_lock);
- if (!ret) {
- ret = -EBUSY;
- goto hot_reset_release;
- }
- mutex_unlock(&tmp->vma_lock);
- }
-
- /* User has access, do the reset */
- ret = pci_reset_bus(vdev->pdev);
-
-hot_reset_release:
- for (i = 0; i < devs.cur_index; i++) {
- struct vfio_pci_device *tmp = devs.devices[i];
-
- if (i < mem_idx)
- up_write(&tmp->memory_lock);
- else
- mutex_unlock(&tmp->vma_lock);
- vfio_device_put(&tmp->vdev);
- }
- kfree(devs.devices);
-
- for (group_idx--; group_idx >= 0; group_idx--)
- vfio_group_put_external_user(groups[group_idx].group);
-
- kfree(groups);
- return ret;
- } else if (cmd == VFIO_DEVICE_IOEVENTFD) {
- struct vfio_device_ioeventfd ioeventfd;
- int count;
-
- minsz = offsetofend(struct vfio_device_ioeventfd, fd);
-
- if (copy_from_user(&ioeventfd, (void __user *)arg, minsz))
- return -EFAULT;
-
- if (ioeventfd.argsz < minsz)
- return -EINVAL;
-
- if (ioeventfd.flags & ~VFIO_DEVICE_IOEVENTFD_SIZE_MASK)
- return -EINVAL;
-
- count = ioeventfd.flags & VFIO_DEVICE_IOEVENTFD_SIZE_MASK;
-
- if (hweight8(count) != 1 || ioeventfd.fd < -1)
- return -EINVAL;
-
- return vfio_pci_ioeventfd(vdev, ioeventfd.offset,
- ioeventfd.data, count, ioeventfd.fd);
- } else if (cmd == VFIO_DEVICE_FEATURE) {
- struct vfio_device_feature feature;
- uuid_t uuid;
-
- minsz = offsetofend(struct vfio_device_feature, flags);
-
- if (copy_from_user(&feature, (void __user *)arg, minsz))
- return -EFAULT;
-
- if (feature.argsz < minsz)
- return -EINVAL;
-
- /* Check unknown flags */
- if (feature.flags & ~(VFIO_DEVICE_FEATURE_MASK |
- VFIO_DEVICE_FEATURE_SET |
- VFIO_DEVICE_FEATURE_GET |
- VFIO_DEVICE_FEATURE_PROBE))
- return -EINVAL;
-
- /* GET & SET are mutually exclusive except with PROBE */
- if (!(feature.flags & VFIO_DEVICE_FEATURE_PROBE) &&
- (feature.flags & VFIO_DEVICE_FEATURE_SET) &&
- (feature.flags & VFIO_DEVICE_FEATURE_GET))
- return -EINVAL;
-
- switch (feature.flags & VFIO_DEVICE_FEATURE_MASK) {
- case VFIO_DEVICE_FEATURE_PCI_VF_TOKEN:
- if (!vdev->vf_token)
- return -ENOTTY;
-
- /*
- * We do not support GET of the VF Token UUID as this
- * could expose the token of the previous device user.
- */
- if (feature.flags & VFIO_DEVICE_FEATURE_GET)
- return -EINVAL;
-
- if (feature.flags & VFIO_DEVICE_FEATURE_PROBE)
- return 0;
-
- /* Don't SET unless told to do so */
- if (!(feature.flags & VFIO_DEVICE_FEATURE_SET))
- return -EINVAL;
-
- if (feature.argsz < minsz + sizeof(uuid))
- return -EINVAL;
-
- if (copy_from_user(&uuid, (void __user *)(arg + minsz),
- sizeof(uuid)))
- return -EFAULT;
-
- mutex_lock(&vdev->vf_token->lock);
- uuid_copy(&vdev->vf_token->uuid, &uuid);
- mutex_unlock(&vdev->vf_token->lock);
-
- return 0;
- default:
- return -ENOTTY;
- }
- }
-
- return -ENOTTY;
-}
-
-static ssize_t vfio_pci_rw(struct vfio_pci_device *vdev, char __user *buf,
- size_t count, loff_t *ppos, bool iswrite)
-{
- unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
-
- if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions)
- return -EINVAL;
-
- switch (index) {
- case VFIO_PCI_CONFIG_REGION_INDEX:
- return vfio_pci_config_rw(vdev, buf, count, ppos, iswrite);
-
- case VFIO_PCI_ROM_REGION_INDEX:
- if (iswrite)
- return -EINVAL;
- return vfio_pci_bar_rw(vdev, buf, count, ppos, false);
-
- case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
- return vfio_pci_bar_rw(vdev, buf, count, ppos, iswrite);
-
- case VFIO_PCI_VGA_REGION_INDEX:
- return vfio_pci_vga_rw(vdev, buf, count, ppos, iswrite);
- default:
- index -= VFIO_PCI_NUM_REGIONS;
- return vdev->region[index].ops->rw(vdev, buf,
- count, ppos, iswrite);
- }
-
- return -EINVAL;
-}
-
-static ssize_t vfio_pci_read(struct vfio_device *core_vdev, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct vfio_pci_device *vdev =
- container_of(core_vdev, struct vfio_pci_device, vdev);
-
- if (!count)
- return 0;
-
- return vfio_pci_rw(vdev, buf, count, ppos, false);
-}
-
-static ssize_t vfio_pci_write(struct vfio_device *core_vdev, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct vfio_pci_device *vdev =
- container_of(core_vdev, struct vfio_pci_device, vdev);
-
- if (!count)
- return 0;
-
- return vfio_pci_rw(vdev, (char __user *)buf, count, ppos, true);
-}
-
-/* Return 1 on zap and vma_lock acquired, 0 on contention (only with @try) */
-static int vfio_pci_zap_and_vma_lock(struct vfio_pci_device *vdev, bool try)
-{
- struct vfio_pci_mmap_vma *mmap_vma, *tmp;
-
- /*
- * Lock ordering:
- * vma_lock is nested under mmap_lock for vm_ops callback paths.
- * The memory_lock semaphore is used by both code paths calling
- * into this function to zap vmas and the vm_ops.fault callback
- * to protect the memory enable state of the device.
- *
- * When zapping vmas we need to maintain the mmap_lock => vma_lock
- * ordering, which requires using vma_lock to walk vma_list to
- * acquire an mm, then dropping vma_lock to get the mmap_lock and
- * reacquiring vma_lock. This logic is derived from similar
- * requirements in uverbs_user_mmap_disassociate().
- *
- * mmap_lock must always be the top-level lock when it is taken.
- * Therefore we can only hold the memory_lock write lock when
- * vma_list is empty, as we'd need to take mmap_lock to clear
- * entries. vma_list can only be guaranteed empty when holding
- * vma_lock, thus memory_lock is nested under vma_lock.
- *
- * This enables the vm_ops.fault callback to acquire vma_lock,
- * followed by memory_lock read lock, while already holding
- * mmap_lock without risk of deadlock.
- */
- while (1) {
- struct mm_struct *mm = NULL;
-
- if (try) {
- if (!mutex_trylock(&vdev->vma_lock))
- return 0;
- } else {
- mutex_lock(&vdev->vma_lock);
- }
- while (!list_empty(&vdev->vma_list)) {
- mmap_vma = list_first_entry(&vdev->vma_list,
- struct vfio_pci_mmap_vma,
- vma_next);
- mm = mmap_vma->vma->vm_mm;
- if (mmget_not_zero(mm))
- break;
-
- list_del(&mmap_vma->vma_next);
- kfree(mmap_vma);
- mm = NULL;
- }
- if (!mm)
- return 1;
- mutex_unlock(&vdev->vma_lock);
-
- if (try) {
- if (!mmap_read_trylock(mm)) {
- mmput(mm);
- return 0;
- }
- } else {
- mmap_read_lock(mm);
- }
- if (try) {
- if (!mutex_trylock(&vdev->vma_lock)) {
- mmap_read_unlock(mm);
- mmput(mm);
- return 0;
- }
- } else {
- mutex_lock(&vdev->vma_lock);
- }
- list_for_each_entry_safe(mmap_vma, tmp,
- &vdev->vma_list, vma_next) {
- struct vm_area_struct *vma = mmap_vma->vma;
-
- if (vma->vm_mm != mm)
- continue;
-
- list_del(&mmap_vma->vma_next);
- kfree(mmap_vma);
-
- zap_vma_ptes(vma, vma->vm_start,
- vma->vm_end - vma->vm_start);
- }
- mutex_unlock(&vdev->vma_lock);
- mmap_read_unlock(mm);
- mmput(mm);
- }
-}
-
-void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_device *vdev)
-{
- vfio_pci_zap_and_vma_lock(vdev, false);
- down_write(&vdev->memory_lock);
- mutex_unlock(&vdev->vma_lock);
-}
-
-u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_device *vdev)
-{
- u16 cmd;
-
- down_write(&vdev->memory_lock);
- pci_read_config_word(vdev->pdev, PCI_COMMAND, &cmd);
- if (!(cmd & PCI_COMMAND_MEMORY))
- pci_write_config_word(vdev->pdev, PCI_COMMAND,
- cmd | PCI_COMMAND_MEMORY);
-
- return cmd;
-}
-
-void vfio_pci_memory_unlock_and_restore(struct vfio_pci_device *vdev, u16 cmd)
-{
- pci_write_config_word(vdev->pdev, PCI_COMMAND, cmd);
- up_write(&vdev->memory_lock);
-}
-
-/* Caller holds vma_lock */
-static int __vfio_pci_add_vma(struct vfio_pci_device *vdev,
- struct vm_area_struct *vma)
-{
- struct vfio_pci_mmap_vma *mmap_vma;
-
- mmap_vma = kmalloc(sizeof(*mmap_vma), GFP_KERNEL);
- if (!mmap_vma)
- return -ENOMEM;
-
- mmap_vma->vma = vma;
- list_add(&mmap_vma->vma_next, &vdev->vma_list);
-
- return 0;
-}
-
-/*
- * Zap mmaps on open so that we can fault them in on access and therefore
- * our vma_list only tracks mappings accessed since last zap.
- */
-static void vfio_pci_mmap_open(struct vm_area_struct *vma)
-{
- zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
-}
-
-static void vfio_pci_mmap_close(struct vm_area_struct *vma)
-{
- struct vfio_pci_device *vdev = vma->vm_private_data;
- struct vfio_pci_mmap_vma *mmap_vma;
-
- mutex_lock(&vdev->vma_lock);
- list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) {
- if (mmap_vma->vma == vma) {
- list_del(&mmap_vma->vma_next);
- kfree(mmap_vma);
- break;
- }
- }
- mutex_unlock(&vdev->vma_lock);
-}
-
-static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf)
-{
- struct vm_area_struct *vma = vmf->vma;
- struct vfio_pci_device *vdev = vma->vm_private_data;
- struct vfio_pci_mmap_vma *mmap_vma;
- vm_fault_t ret = VM_FAULT_NOPAGE;
-
- mutex_lock(&vdev->vma_lock);
- down_read(&vdev->memory_lock);
-
- if (!__vfio_pci_memory_enabled(vdev)) {
- ret = VM_FAULT_SIGBUS;
- goto up_out;
- }
-
- /*
- * We populate the whole vma on fault, so we need to test whether
- * the vma has already been mapped, such as for concurrent faults
- * to the same vma. io_remap_pfn_range() will trigger a BUG_ON if
- * we ask it to fill the same range again.
- */
- list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) {
- if (mmap_vma->vma == vma)
- goto up_out;
- }
-
- if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot)) {
- ret = VM_FAULT_SIGBUS;
- zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
- goto up_out;
- }
-
- if (__vfio_pci_add_vma(vdev, vma)) {
- ret = VM_FAULT_OOM;
- zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
- }
-
-up_out:
- up_read(&vdev->memory_lock);
- mutex_unlock(&vdev->vma_lock);
- return ret;
-}
-
-static const struct vm_operations_struct vfio_pci_mmap_ops = {
- .open = vfio_pci_mmap_open,
- .close = vfio_pci_mmap_close,
- .fault = vfio_pci_mmap_fault,
-};
-
-static int vfio_pci_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma)
-{
- struct vfio_pci_device *vdev =
- container_of(core_vdev, struct vfio_pci_device, vdev);
- struct pci_dev *pdev = vdev->pdev;
- unsigned int index;
- u64 phys_len, req_len, pgoff, req_start;
- int ret;
-
- index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
-
- if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions)
- return -EINVAL;
- if (vma->vm_end < vma->vm_start)
- return -EINVAL;
- if ((vma->vm_flags & VM_SHARED) == 0)
- return -EINVAL;
- if (index >= VFIO_PCI_NUM_REGIONS) {
- int regnum = index - VFIO_PCI_NUM_REGIONS;
- struct vfio_pci_region *region = vdev->region + regnum;
-
- if (region->ops && region->ops->mmap &&
- (region->flags & VFIO_REGION_INFO_FLAG_MMAP))
- return region->ops->mmap(vdev, region, vma);
- return -EINVAL;
}
- if (index >= VFIO_PCI_ROM_REGION_INDEX)
- return -EINVAL;
- if (!vdev->bar_mmap_supported[index])
- return -EINVAL;
- phys_len = PAGE_ALIGN(pci_resource_len(pdev, index));
- req_len = vma->vm_end - vma->vm_start;
- pgoff = vma->vm_pgoff &
- ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
- req_start = pgoff << PAGE_SHIFT;
-
- if (req_start + req_len > phys_len)
- return -EINVAL;
-
- /*
- * Even though we don't make use of the barmap for the mmap,
- * we need to request the region and the barmap tracks that.
- */
- if (!vdev->barmap[index]) {
- ret = pci_request_selected_regions(pdev,
- 1 << index, "vfio-pci");
- if (ret)
- return ret;
-
- vdev->barmap[index] = pci_iomap(pdev, index, 0);
- if (!vdev->barmap[index]) {
- pci_release_selected_regions(pdev, 1 << index);
- return -ENOMEM;
- }
- }
-
- vma->vm_private_data = vdev;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- vma->vm_pgoff = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff;
-
- /*
- * See remap_pfn_range(), called from vfio_pci_fault() but we can't
- * change vm_flags within the fault handler. Set them now.
- */
- vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
- vma->vm_ops = &vfio_pci_mmap_ops;
+ vfio_pci_core_finish_enable(vdev);
return 0;
}
-static void vfio_pci_request(struct vfio_device *core_vdev, unsigned int count)
-{
- struct vfio_pci_device *vdev =
- container_of(core_vdev, struct vfio_pci_device, vdev);
- struct pci_dev *pdev = vdev->pdev;
-
- mutex_lock(&vdev->igate);
-
- if (vdev->req_trigger) {
- if (!(count % 10))
- pci_notice_ratelimited(pdev,
- "Relaying device request to user (#%u)\n",
- count);
- eventfd_signal(vdev->req_trigger, 1);
- } else if (count == 0) {
- pci_warn(pdev,
- "No device request channel registered, blocked until released by user\n");
- }
-
- mutex_unlock(&vdev->igate);
-}
-
-static int vfio_pci_validate_vf_token(struct vfio_pci_device *vdev,
- bool vf_token, uuid_t *uuid)
-{
- /*
- * There's always some degree of trust or collaboration between SR-IOV
- * PF and VFs, even if just that the PF hosts the SR-IOV capability and
- * can disrupt VFs with a reset, but often the PF has more explicit
- * access to deny service to the VF or access data passed through the
- * VF. We therefore require an opt-in via a shared VF token (UUID) to
- * represent this trust. This both prevents that a VF driver might
- * assume the PF driver is a trusted, in-kernel driver, and also that
- * a PF driver might be replaced with a rogue driver, unknown to in-use
- * VF drivers.
- *
- * Therefore when presented with a VF, if the PF is a vfio device and
- * it is bound to the vfio-pci driver, the user needs to provide a VF
- * token to access the device, in the form of appending a vf_token to
- * the device name, for example:
- *
- * "0000:04:10.0 vf_token=bd8d9d2b-5a5f-4f5a-a211-f591514ba1f3"
- *
- * When presented with a PF which has VFs in use, the user must also
- * provide the current VF token to prove collaboration with existing
- * VF users. If VFs are not in use, the VF token provided for the PF
- * device will act to set the VF token.
- *
- * If the VF token is provided but unused, an error is generated.
- */
- if (!vdev->pdev->is_virtfn && !vdev->vf_token && !vf_token)
- return 0; /* No VF token provided or required */
-
- if (vdev->pdev->is_virtfn) {
- struct vfio_pci_device *pf_vdev = get_pf_vdev(vdev);
- bool match;
-
- if (!pf_vdev) {
- if (!vf_token)
- return 0; /* PF is not vfio-pci, no VF token */
-
- pci_info_ratelimited(vdev->pdev,
- "VF token incorrectly provided, PF not bound to vfio-pci\n");
- return -EINVAL;
- }
-
- if (!vf_token) {
- vfio_device_put(&pf_vdev->vdev);
- pci_info_ratelimited(vdev->pdev,
- "VF token required to access device\n");
- return -EACCES;
- }
-
- mutex_lock(&pf_vdev->vf_token->lock);
- match = uuid_equal(uuid, &pf_vdev->vf_token->uuid);
- mutex_unlock(&pf_vdev->vf_token->lock);
-
- vfio_device_put(&pf_vdev->vdev);
-
- if (!match) {
- pci_info_ratelimited(vdev->pdev,
- "Incorrect VF token provided for device\n");
- return -EACCES;
- }
- } else if (vdev->vf_token) {
- mutex_lock(&vdev->vf_token->lock);
- if (vdev->vf_token->users) {
- if (!vf_token) {
- mutex_unlock(&vdev->vf_token->lock);
- pci_info_ratelimited(vdev->pdev,
- "VF token required to access device\n");
- return -EACCES;
- }
-
- if (!uuid_equal(uuid, &vdev->vf_token->uuid)) {
- mutex_unlock(&vdev->vf_token->lock);
- pci_info_ratelimited(vdev->pdev,
- "Incorrect VF token provided for device\n");
- return -EACCES;
- }
- } else if (vf_token) {
- uuid_copy(&vdev->vf_token->uuid, uuid);
- }
-
- mutex_unlock(&vdev->vf_token->lock);
- } else if (vf_token) {
- pci_info_ratelimited(vdev->pdev,
- "VF token incorrectly provided, not a PF or VF\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-#define VF_TOKEN_ARG "vf_token="
-
-static int vfio_pci_match(struct vfio_device *core_vdev, char *buf)
-{
- struct vfio_pci_device *vdev =
- container_of(core_vdev, struct vfio_pci_device, vdev);
- bool vf_token = false;
- uuid_t uuid;
- int ret;
-
- if (strncmp(pci_name(vdev->pdev), buf, strlen(pci_name(vdev->pdev))))
- return 0; /* No match */
-
- if (strlen(buf) > strlen(pci_name(vdev->pdev))) {
- buf += strlen(pci_name(vdev->pdev));
-
- if (*buf != ' ')
- return 0; /* No match: non-whitespace after name */
-
- while (*buf) {
- if (*buf == ' ') {
- buf++;
- continue;
- }
-
- if (!vf_token && !strncmp(buf, VF_TOKEN_ARG,
- strlen(VF_TOKEN_ARG))) {
- buf += strlen(VF_TOKEN_ARG);
-
- if (strlen(buf) < UUID_STRING_LEN)
- return -EINVAL;
-
- ret = uuid_parse(buf, &uuid);
- if (ret)
- return ret;
-
- vf_token = true;
- buf += UUID_STRING_LEN;
- } else {
- /* Unknown/duplicate option */
- return -EINVAL;
- }
- }
- }
-
- ret = vfio_pci_validate_vf_token(vdev, vf_token, &uuid);
- if (ret)
- return ret;
-
- return 1; /* Match */
-}
-
static const struct vfio_device_ops vfio_pci_ops = {
.name = "vfio-pci",
- .open = vfio_pci_open,
- .release = vfio_pci_release,
- .ioctl = vfio_pci_ioctl,
- .read = vfio_pci_read,
- .write = vfio_pci_write,
- .mmap = vfio_pci_mmap,
- .request = vfio_pci_request,
- .match = vfio_pci_match,
+ .open_device = vfio_pci_open_device,
+ .close_device = vfio_pci_core_close_device,
+ .ioctl = vfio_pci_core_ioctl,
+ .read = vfio_pci_core_read,
+ .write = vfio_pci_core_write,
+ .mmap = vfio_pci_core_mmap,
+ .request = vfio_pci_core_request,
+ .match = vfio_pci_core_match,
};
-static int vfio_pci_reflck_attach(struct vfio_pci_device *vdev);
-static void vfio_pci_reflck_put(struct vfio_pci_reflck *reflck);
-
-static int vfio_pci_bus_notifier(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct vfio_pci_device *vdev = container_of(nb,
- struct vfio_pci_device, nb);
- struct device *dev = data;
- struct pci_dev *pdev = to_pci_dev(dev);
- struct pci_dev *physfn = pci_physfn(pdev);
-
- if (action == BUS_NOTIFY_ADD_DEVICE &&
- pdev->is_virtfn && physfn == vdev->pdev) {
- pci_info(vdev->pdev, "Captured SR-IOV VF %s driver_override\n",
- pci_name(pdev));
- pdev->driver_override = kasprintf(GFP_KERNEL, "%s",
- vfio_pci_ops.name);
- } else if (action == BUS_NOTIFY_BOUND_DRIVER &&
- pdev->is_virtfn && physfn == vdev->pdev) {
- struct pci_driver *drv = pci_dev_driver(pdev);
-
- if (drv && drv != &vfio_pci_driver)
- pci_warn(vdev->pdev,
- "VF %s bound to driver %s while PF bound to vfio-pci\n",
- pci_name(pdev), drv->name);
- }
-
- return 0;
-}
-
-static int vfio_pci_vf_init(struct vfio_pci_device *vdev)
-{
- struct pci_dev *pdev = vdev->pdev;
- int ret;
-
- if (!pdev->is_physfn)
- return 0;
-
- vdev->vf_token = kzalloc(sizeof(*vdev->vf_token), GFP_KERNEL);
- if (!vdev->vf_token)
- return -ENOMEM;
-
- mutex_init(&vdev->vf_token->lock);
- uuid_gen(&vdev->vf_token->uuid);
-
- vdev->nb.notifier_call = vfio_pci_bus_notifier;
- ret = bus_register_notifier(&pci_bus_type, &vdev->nb);
- if (ret) {
- kfree(vdev->vf_token);
- return ret;
- }
- return 0;
-}
-
-static void vfio_pci_vf_uninit(struct vfio_pci_device *vdev)
-{
- if (!vdev->vf_token)
- return;
-
- bus_unregister_notifier(&pci_bus_type, &vdev->nb);
- WARN_ON(vdev->vf_token->users);
- mutex_destroy(&vdev->vf_token->lock);
- kfree(vdev->vf_token);
-}
-
-static int vfio_pci_vga_init(struct vfio_pci_device *vdev)
-{
- struct pci_dev *pdev = vdev->pdev;
- int ret;
-
- if (!vfio_pci_is_vga(pdev))
- return 0;
-
- ret = vga_client_register(pdev, vdev, NULL, vfio_pci_set_vga_decode);
- if (ret)
- return ret;
- vga_set_legacy_decoding(pdev, vfio_pci_set_vga_decode(vdev, false));
- return 0;
-}
-
-static void vfio_pci_vga_uninit(struct vfio_pci_device *vdev)
-{
- struct pci_dev *pdev = vdev->pdev;
-
- if (!vfio_pci_is_vga(pdev))
- return;
- vga_client_register(pdev, NULL, NULL, NULL);
- vga_set_legacy_decoding(pdev, VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
- VGA_RSRC_LEGACY_IO |
- VGA_RSRC_LEGACY_MEM);
-}
-
static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct vfio_pci_device *vdev;
- struct iommu_group *group;
+ struct vfio_pci_core_device *vdev;
int ret;
if (vfio_pci_is_denylisted(pdev))
return -EINVAL;
- if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
- return -EINVAL;
-
- /*
- * Prevent binding to PFs with VFs enabled, the VFs might be in use
- * by the host or other users. We cannot capture the VFs if they
- * already exist, nor can we track VF users. Disabling SR-IOV here
- * would initiate removing the VFs, which would unbind the driver,
- * which is prone to blocking if that VF is also in use by vfio-pci.
- * Just reject these PFs and let the user sort it out.
- */
- if (pci_num_vf(pdev)) {
- pci_warn(pdev, "Cannot bind to PF with SR-IOV enabled\n");
- return -EBUSY;
- }
-
- group = vfio_iommu_group_get(&pdev->dev);
- if (!group)
- return -EINVAL;
-
vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
- if (!vdev) {
- ret = -ENOMEM;
- goto out_group_put;
- }
-
- vfio_init_group_dev(&vdev->vdev, &pdev->dev, &vfio_pci_ops);
- vdev->pdev = pdev;
- vdev->irq_type = VFIO_PCI_NUM_IRQS;
- mutex_init(&vdev->igate);
- spin_lock_init(&vdev->irqlock);
- mutex_init(&vdev->ioeventfds_lock);
- INIT_LIST_HEAD(&vdev->dummy_resources_list);
- INIT_LIST_HEAD(&vdev->ioeventfds_list);
- mutex_init(&vdev->vma_lock);
- INIT_LIST_HEAD(&vdev->vma_list);
- init_rwsem(&vdev->memory_lock);
+ if (!vdev)
+ return -ENOMEM;
+ vfio_pci_core_init_device(vdev, pdev, &vfio_pci_ops);
- ret = vfio_pci_reflck_attach(vdev);
+ ret = vfio_pci_core_register_device(vdev);
if (ret)
goto out_free;
- ret = vfio_pci_vf_init(vdev);
- if (ret)
- goto out_reflck;
- ret = vfio_pci_vga_init(vdev);
- if (ret)
- goto out_vf;
-
- vfio_pci_probe_power_state(vdev);
-
- if (!disable_idle_d3) {
- /*
- * pci-core sets the device power state to an unknown value at
- * bootup and after being removed from a driver. The only
- * transition it allows from this unknown state is to D0, which
- * typically happens when a driver calls pci_enable_device().
- * We're not ready to enable the device yet, but we do want to
- * be able to get to D3. Therefore first do a D0 transition
- * before going to D3.
- */
- vfio_pci_set_power_state(vdev, PCI_D0);
- vfio_pci_set_power_state(vdev, PCI_D3hot);
- }
-
- ret = vfio_register_group_dev(&vdev->vdev);
- if (ret)
- goto out_power;
dev_set_drvdata(&pdev->dev, vdev);
return 0;
-out_power:
- if (!disable_idle_d3)
- vfio_pci_set_power_state(vdev, PCI_D0);
-out_vf:
- vfio_pci_vf_uninit(vdev);
-out_reflck:
- vfio_pci_reflck_put(vdev->reflck);
out_free:
- kfree(vdev->pm_save);
+ vfio_pci_core_uninit_device(vdev);
kfree(vdev);
-out_group_put:
- vfio_iommu_group_put(group, &pdev->dev);
return ret;
}
static void vfio_pci_remove(struct pci_dev *pdev)
{
- struct vfio_pci_device *vdev = dev_get_drvdata(&pdev->dev);
-
- pci_disable_sriov(pdev);
+ struct vfio_pci_core_device *vdev = dev_get_drvdata(&pdev->dev);
- vfio_unregister_group_dev(&vdev->vdev);
-
- vfio_pci_vf_uninit(vdev);
- vfio_pci_reflck_put(vdev->reflck);
- vfio_pci_vga_uninit(vdev);
-
- vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
-
- if (!disable_idle_d3)
- vfio_pci_set_power_state(vdev, PCI_D0);
-
- mutex_destroy(&vdev->ioeventfds_lock);
- kfree(vdev->region);
- kfree(vdev->pm_save);
+ vfio_pci_core_unregister_device(vdev);
+ vfio_pci_core_uninit_device(vdev);
kfree(vdev);
}
-static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
- pci_channel_state_t state)
-{
- struct vfio_pci_device *vdev;
- struct vfio_device *device;
-
- device = vfio_device_get_from_dev(&pdev->dev);
- if (device == NULL)
- return PCI_ERS_RESULT_DISCONNECT;
-
- vdev = container_of(device, struct vfio_pci_device, vdev);
-
- mutex_lock(&vdev->igate);
-
- if (vdev->err_trigger)
- eventfd_signal(vdev->err_trigger, 1);
-
- mutex_unlock(&vdev->igate);
-
- vfio_device_put(device);
-
- return PCI_ERS_RESULT_CAN_RECOVER;
-}
-
static int vfio_pci_sriov_configure(struct pci_dev *pdev, int nr_virtfn)
{
- struct vfio_device *device;
- int ret = 0;
-
- might_sleep();
-
if (!enable_sriov)
return -ENOENT;
- device = vfio_device_get_from_dev(&pdev->dev);
- if (!device)
- return -ENODEV;
-
- if (nr_virtfn == 0)
- pci_disable_sriov(pdev);
- else
- ret = pci_enable_sriov(pdev, nr_virtfn);
-
- vfio_device_put(device);
-
- return ret < 0 ? ret : nr_virtfn;
+ return vfio_pci_core_sriov_configure(pdev, nr_virtfn);
}
-static const struct pci_error_handlers vfio_err_handlers = {
- .error_detected = vfio_pci_aer_err_detected,
+static const struct pci_device_id vfio_pci_table[] = {
+ { PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_ANY_ID, PCI_ANY_ID) }, /* match all by default */
+ {}
};
+MODULE_DEVICE_TABLE(pci, vfio_pci_table);
+
static struct pci_driver vfio_pci_driver = {
.name = "vfio-pci",
- .id_table = NULL, /* only dynamic ids */
+ .id_table = vfio_pci_table,
.probe = vfio_pci_probe,
.remove = vfio_pci_remove,
.sriov_configure = vfio_pci_sriov_configure,
- .err_handler = &vfio_err_handlers,
+ .err_handler = &vfio_pci_core_err_handlers,
};
-static DEFINE_MUTEX(reflck_lock);
-
-static struct vfio_pci_reflck *vfio_pci_reflck_alloc(void)
-{
- struct vfio_pci_reflck *reflck;
-
- reflck = kzalloc(sizeof(*reflck), GFP_KERNEL);
- if (!reflck)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&reflck->kref);
- mutex_init(&reflck->lock);
-
- return reflck;
-}
-
-static void vfio_pci_reflck_get(struct vfio_pci_reflck *reflck)
-{
- kref_get(&reflck->kref);
-}
-
-static int vfio_pci_reflck_find(struct pci_dev *pdev, void *data)
-{
- struct vfio_pci_reflck **preflck = data;
- struct vfio_device *device;
- struct vfio_pci_device *vdev;
-
- device = vfio_device_get_from_dev(&pdev->dev);
- if (!device)
- return 0;
-
- if (pci_dev_driver(pdev) != &vfio_pci_driver) {
- vfio_device_put(device);
- return 0;
- }
-
- vdev = container_of(device, struct vfio_pci_device, vdev);
-
- if (vdev->reflck) {
- vfio_pci_reflck_get(vdev->reflck);
- *preflck = vdev->reflck;
- vfio_device_put(device);
- return 1;
- }
-
- vfio_device_put(device);
- return 0;
-}
-
-static int vfio_pci_reflck_attach(struct vfio_pci_device *vdev)
-{
- bool slot = !pci_probe_reset_slot(vdev->pdev->slot);
-
- mutex_lock(&reflck_lock);
-
- if (pci_is_root_bus(vdev->pdev->bus) ||
- vfio_pci_for_each_slot_or_bus(vdev->pdev, vfio_pci_reflck_find,
- &vdev->reflck, slot) <= 0)
- vdev->reflck = vfio_pci_reflck_alloc();
-
- mutex_unlock(&reflck_lock);
-
- return PTR_ERR_OR_ZERO(vdev->reflck);
-}
-
-static void vfio_pci_reflck_release(struct kref *kref)
-{
- struct vfio_pci_reflck *reflck = container_of(kref,
- struct vfio_pci_reflck,
- kref);
-
- kfree(reflck);
- mutex_unlock(&reflck_lock);
-}
-
-static void vfio_pci_reflck_put(struct vfio_pci_reflck *reflck)
-{
- kref_put_mutex(&reflck->kref, vfio_pci_reflck_release, &reflck_lock);
-}
-
-static int vfio_pci_get_unused_devs(struct pci_dev *pdev, void *data)
-{
- struct vfio_devices *devs = data;
- struct vfio_device *device;
- struct vfio_pci_device *vdev;
-
- if (devs->cur_index == devs->max_index)
- return -ENOSPC;
-
- device = vfio_device_get_from_dev(&pdev->dev);
- if (!device)
- return -EINVAL;
-
- if (pci_dev_driver(pdev) != &vfio_pci_driver) {
- vfio_device_put(device);
- return -EBUSY;
- }
-
- vdev = container_of(device, struct vfio_pci_device, vdev);
-
- /* Fault if the device is not unused */
- if (vdev->refcnt) {
- vfio_device_put(device);
- return -EBUSY;
- }
-
- devs->devices[devs->cur_index++] = vdev;
- return 0;
-}
-
-static int vfio_pci_try_zap_and_vma_lock_cb(struct pci_dev *pdev, void *data)
-{
- struct vfio_devices *devs = data;
- struct vfio_device *device;
- struct vfio_pci_device *vdev;
-
- if (devs->cur_index == devs->max_index)
- return -ENOSPC;
-
- device = vfio_device_get_from_dev(&pdev->dev);
- if (!device)
- return -EINVAL;
-
- if (pci_dev_driver(pdev) != &vfio_pci_driver) {
- vfio_device_put(device);
- return -EBUSY;
- }
-
- vdev = container_of(device, struct vfio_pci_device, vdev);
-
- /*
- * Locking multiple devices is prone to deadlock, runaway and
- * unwind if we hit contention.
- */
- if (!vfio_pci_zap_and_vma_lock(vdev, true)) {
- vfio_device_put(device);
- return -EBUSY;
- }
-
- devs->devices[devs->cur_index++] = vdev;
- return 0;
-}
-
-/*
- * If a bus or slot reset is available for the provided device and:
- * - All of the devices affected by that bus or slot reset are unused
- * (!refcnt)
- * - At least one of the affected devices is marked dirty via
- * needs_reset (such as by lack of FLR support)
- * Then attempt to perform that bus or slot reset. Callers are required
- * to hold vdev->reflck->lock, protecting the bus/slot reset group from
- * concurrent opens. A vfio_device reference is acquired for each device
- * to prevent unbinds during the reset operation.
- *
- * NB: vfio-core considers a group to be viable even if some devices are
- * bound to drivers like pci-stub or pcieport. Here we require all devices
- * to be bound to vfio_pci since that's the only way we can be sure they
- * stay put.
- */
-static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev)
-{
- struct vfio_devices devs = { .cur_index = 0 };
- int i = 0, ret = -EINVAL;
- bool slot = false;
- struct vfio_pci_device *tmp;
-
- if (!pci_probe_reset_slot(vdev->pdev->slot))
- slot = true;
- else if (pci_probe_reset_bus(vdev->pdev->bus))
- return;
-
- if (vfio_pci_for_each_slot_or_bus(vdev->pdev, vfio_pci_count_devs,
- &i, slot) || !i)
- return;
-
- devs.max_index = i;
- devs.devices = kcalloc(i, sizeof(struct vfio_device *), GFP_KERNEL);
- if (!devs.devices)
- return;
-
- if (vfio_pci_for_each_slot_or_bus(vdev->pdev,
- vfio_pci_get_unused_devs,
- &devs, slot))
- goto put_devs;
-
- /* Does at least one need a reset? */
- for (i = 0; i < devs.cur_index; i++) {
- tmp = devs.devices[i];
- if (tmp->needs_reset) {
- ret = pci_reset_bus(vdev->pdev);
- break;
- }
- }
-
-put_devs:
- for (i = 0; i < devs.cur_index; i++) {
- tmp = devs.devices[i];
-
- /*
- * If reset was successful, affected devices no longer need
- * a reset and we should return all the collateral devices
- * to low power. If not successful, we either didn't reset
- * the bus or timed out waiting for it, so let's not touch
- * the power state.
- */
- if (!ret) {
- tmp->needs_reset = false;
-
- if (tmp != vdev && !disable_idle_d3)
- vfio_pci_set_power_state(tmp, PCI_D3hot);
- }
-
- vfio_device_put(&tmp->vdev);
- }
-
- kfree(devs.devices);
-}
-
-static void __exit vfio_pci_cleanup(void)
-{
- pci_unregister_driver(&vfio_pci_driver);
- vfio_pci_uninit_perm_bits();
-}
-
static void __init vfio_pci_fill_ids(void)
{
char *p, *id;
@@ -2419,16 +239,18 @@ static void __init vfio_pci_fill_ids(void)
static int __init vfio_pci_init(void)
{
int ret;
+ bool is_disable_vga = true;
- /* Allocate shared config space permission data used by all devices */
- ret = vfio_pci_init_perm_bits();
- if (ret)
- return ret;
+#ifdef CONFIG_VFIO_PCI_VGA
+ is_disable_vga = disable_vga;
+#endif
+
+ vfio_pci_core_set_params(nointxmask, is_disable_vga, disable_idle_d3);
/* Register and scan for devices */
ret = pci_register_driver(&vfio_pci_driver);
if (ret)
- goto out_driver;
+ return ret;
vfio_pci_fill_ids();
@@ -2436,16 +258,15 @@ static int __init vfio_pci_init(void)
pr_warn("device denylist disabled.\n");
return 0;
-
-out_driver:
- vfio_pci_uninit_perm_bits();
- return ret;
}
-
module_init(vfio_pci_init);
+
+static void __exit vfio_pci_cleanup(void)
+{
+ pci_unregister_driver(&vfio_pci_driver);
+}
module_exit(vfio_pci_cleanup);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 70e28efbc51f..6e58b4bf7a60 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -26,7 +26,7 @@
#include <linux/vfio.h>
#include <linux/slab.h>
-#include "vfio_pci_private.h"
+#include <linux/vfio_pci_core.h>
/* Fake capability ID for standard config space */
#define PCI_CAP_ID_BASIC 0
@@ -108,9 +108,9 @@ static const u16 pci_ext_cap_length[PCI_EXT_CAP_ID_MAX + 1] = {
struct perm_bits {
u8 *virt; /* read/write virtual data, not hw */
u8 *write; /* writeable bits */
- int (*readfn)(struct vfio_pci_device *vdev, int pos, int count,
+ int (*readfn)(struct vfio_pci_core_device *vdev, int pos, int count,
struct perm_bits *perm, int offset, __le32 *val);
- int (*writefn)(struct vfio_pci_device *vdev, int pos, int count,
+ int (*writefn)(struct vfio_pci_core_device *vdev, int pos, int count,
struct perm_bits *perm, int offset, __le32 val);
};
@@ -171,7 +171,7 @@ static int vfio_user_config_write(struct pci_dev *pdev, int offset,
return ret;
}
-static int vfio_default_config_read(struct vfio_pci_device *vdev, int pos,
+static int vfio_default_config_read(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 *val)
{
@@ -197,7 +197,7 @@ static int vfio_default_config_read(struct vfio_pci_device *vdev, int pos,
return count;
}
-static int vfio_default_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_default_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -244,7 +244,7 @@ static int vfio_default_config_write(struct vfio_pci_device *vdev, int pos,
}
/* Allow direct read from hardware, except for capability next pointer */
-static int vfio_direct_config_read(struct vfio_pci_device *vdev, int pos,
+static int vfio_direct_config_read(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 *val)
{
@@ -269,7 +269,7 @@ static int vfio_direct_config_read(struct vfio_pci_device *vdev, int pos,
}
/* Raw access skips any kind of virtualization */
-static int vfio_raw_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_raw_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -282,7 +282,7 @@ static int vfio_raw_config_write(struct vfio_pci_device *vdev, int pos,
return count;
}
-static int vfio_raw_config_read(struct vfio_pci_device *vdev, int pos,
+static int vfio_raw_config_read(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 *val)
{
@@ -296,7 +296,7 @@ static int vfio_raw_config_read(struct vfio_pci_device *vdev, int pos,
}
/* Virt access uses only virtualization */
-static int vfio_virt_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_virt_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -304,7 +304,7 @@ static int vfio_virt_config_write(struct vfio_pci_device *vdev, int pos,
return count;
}
-static int vfio_virt_config_read(struct vfio_pci_device *vdev, int pos,
+static int vfio_virt_config_read(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 *val)
{
@@ -396,7 +396,7 @@ static inline void p_setd(struct perm_bits *p, int off, u32 virt, u32 write)
}
/* Caller should hold memory_lock semaphore */
-bool __vfio_pci_memory_enabled(struct vfio_pci_device *vdev)
+bool __vfio_pci_memory_enabled(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
u16 cmd = le16_to_cpu(*(__le16 *)&vdev->vconfig[PCI_COMMAND]);
@@ -413,7 +413,7 @@ bool __vfio_pci_memory_enabled(struct vfio_pci_device *vdev)
* Restore the *real* BARs after we detect a FLR or backdoor reset.
* (backdoor = some device specific technique that we didn't catch)
*/
-static void vfio_bar_restore(struct vfio_pci_device *vdev)
+static void vfio_bar_restore(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
u32 *rbar = vdev->rbar;
@@ -460,7 +460,7 @@ static __le32 vfio_generate_bar_flags(struct pci_dev *pdev, int bar)
* Pretend we're hardware and tweak the values of the *virtual* PCI BARs
* to reflect the hardware capabilities. This implements BAR sizing.
*/
-static void vfio_bar_fixup(struct vfio_pci_device *vdev)
+static void vfio_bar_fixup(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
int i;
@@ -514,7 +514,7 @@ static void vfio_bar_fixup(struct vfio_pci_device *vdev)
vdev->bardirty = false;
}
-static int vfio_basic_config_read(struct vfio_pci_device *vdev, int pos,
+static int vfio_basic_config_read(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 *val)
{
@@ -536,7 +536,7 @@ static int vfio_basic_config_read(struct vfio_pci_device *vdev, int pos,
}
/* Test whether BARs match the value we think they should contain */
-static bool vfio_need_bar_restore(struct vfio_pci_device *vdev)
+static bool vfio_need_bar_restore(struct vfio_pci_core_device *vdev)
{
int i = 0, pos = PCI_BASE_ADDRESS_0, ret;
u32 bar;
@@ -552,7 +552,7 @@ static bool vfio_need_bar_restore(struct vfio_pci_device *vdev)
return false;
}
-static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_basic_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -692,7 +692,7 @@ static int __init init_pci_cap_basic_perm(struct perm_bits *perm)
return 0;
}
-static int vfio_pm_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_pm_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -747,7 +747,7 @@ static int __init init_pci_cap_pm_perm(struct perm_bits *perm)
return 0;
}
-static int vfio_vpd_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_vpd_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -829,7 +829,7 @@ static int __init init_pci_cap_pcix_perm(struct perm_bits *perm)
return 0;
}
-static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_exp_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -913,7 +913,7 @@ static int __init init_pci_cap_exp_perm(struct perm_bits *perm)
return 0;
}
-static int vfio_af_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_af_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -1072,7 +1072,7 @@ int __init vfio_pci_init_perm_bits(void)
return ret;
}
-static int vfio_find_cap_start(struct vfio_pci_device *vdev, int pos)
+static int vfio_find_cap_start(struct vfio_pci_core_device *vdev, int pos)
{
u8 cap;
int base = (pos >= PCI_CFG_SPACE_SIZE) ? PCI_CFG_SPACE_SIZE :
@@ -1089,7 +1089,7 @@ static int vfio_find_cap_start(struct vfio_pci_device *vdev, int pos)
return pos;
}
-static int vfio_msi_config_read(struct vfio_pci_device *vdev, int pos,
+static int vfio_msi_config_read(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 *val)
{
@@ -1109,7 +1109,7 @@ static int vfio_msi_config_read(struct vfio_pci_device *vdev, int pos,
return vfio_default_config_read(vdev, pos, count, perm, offset, val);
}
-static int vfio_msi_config_write(struct vfio_pci_device *vdev, int pos,
+static int vfio_msi_config_write(struct vfio_pci_core_device *vdev, int pos,
int count, struct perm_bits *perm,
int offset, __le32 val)
{
@@ -1189,7 +1189,7 @@ static int init_pci_cap_msi_perm(struct perm_bits *perm, int len, u16 flags)
}
/* Determine MSI CAP field length; initialize msi_perms on 1st call per vdev */
-static int vfio_msi_cap_len(struct vfio_pci_device *vdev, u8 pos)
+static int vfio_msi_cap_len(struct vfio_pci_core_device *vdev, u8 pos)
{
struct pci_dev *pdev = vdev->pdev;
int len, ret;
@@ -1222,7 +1222,7 @@ static int vfio_msi_cap_len(struct vfio_pci_device *vdev, u8 pos)
}
/* Determine extended capability length for VC (2 & 9) and MFVC */
-static int vfio_vc_cap_len(struct vfio_pci_device *vdev, u16 pos)
+static int vfio_vc_cap_len(struct vfio_pci_core_device *vdev, u16 pos)
{
struct pci_dev *pdev = vdev->pdev;
u32 tmp;
@@ -1263,7 +1263,7 @@ static int vfio_vc_cap_len(struct vfio_pci_device *vdev, u16 pos)
return len;
}
-static int vfio_cap_len(struct vfio_pci_device *vdev, u8 cap, u8 pos)
+static int vfio_cap_len(struct vfio_pci_core_device *vdev, u8 cap, u8 pos)
{
struct pci_dev *pdev = vdev->pdev;
u32 dword;
@@ -1338,7 +1338,7 @@ static int vfio_cap_len(struct vfio_pci_device *vdev, u8 cap, u8 pos)
return 0;
}
-static int vfio_ext_cap_len(struct vfio_pci_device *vdev, u16 ecap, u16 epos)
+static int vfio_ext_cap_len(struct vfio_pci_core_device *vdev, u16 ecap, u16 epos)
{
struct pci_dev *pdev = vdev->pdev;
u8 byte;
@@ -1412,7 +1412,7 @@ static int vfio_ext_cap_len(struct vfio_pci_device *vdev, u16 ecap, u16 epos)
return 0;
}
-static int vfio_fill_vconfig_bytes(struct vfio_pci_device *vdev,
+static int vfio_fill_vconfig_bytes(struct vfio_pci_core_device *vdev,
int offset, int size)
{
struct pci_dev *pdev = vdev->pdev;
@@ -1459,7 +1459,7 @@ static int vfio_fill_vconfig_bytes(struct vfio_pci_device *vdev,
return ret;
}
-static int vfio_cap_init(struct vfio_pci_device *vdev)
+static int vfio_cap_init(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
u8 *map = vdev->pci_config_map;
@@ -1549,7 +1549,7 @@ static int vfio_cap_init(struct vfio_pci_device *vdev)
return 0;
}
-static int vfio_ecap_init(struct vfio_pci_device *vdev)
+static int vfio_ecap_init(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
u8 *map = vdev->pci_config_map;
@@ -1669,7 +1669,7 @@ static const struct pci_device_id known_bogus_vf_intx_pin[] = {
* for each area requiring emulated bits, but the array of pointers
* would be comparable in size (at least for standard config space).
*/
-int vfio_config_init(struct vfio_pci_device *vdev)
+int vfio_config_init(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
u8 *map, *vconfig;
@@ -1773,7 +1773,7 @@ out:
return pcibios_err_to_errno(ret);
}
-void vfio_config_free(struct vfio_pci_device *vdev)
+void vfio_config_free(struct vfio_pci_core_device *vdev)
{
kfree(vdev->vconfig);
vdev->vconfig = NULL;
@@ -1790,7 +1790,7 @@ void vfio_config_free(struct vfio_pci_device *vdev)
* Find the remaining number of bytes in a dword that match the given
* position. Stop at either the end of the capability or the dword boundary.
*/
-static size_t vfio_pci_cap_remaining_dword(struct vfio_pci_device *vdev,
+static size_t vfio_pci_cap_remaining_dword(struct vfio_pci_core_device *vdev,
loff_t pos)
{
u8 cap = vdev->pci_config_map[pos];
@@ -1802,7 +1802,7 @@ static size_t vfio_pci_cap_remaining_dword(struct vfio_pci_device *vdev,
return i;
}
-static ssize_t vfio_config_do_rw(struct vfio_pci_device *vdev, char __user *buf,
+static ssize_t vfio_config_do_rw(struct vfio_pci_core_device *vdev, char __user *buf,
size_t count, loff_t *ppos, bool iswrite)
{
struct pci_dev *pdev = vdev->pdev;
@@ -1885,7 +1885,7 @@ static ssize_t vfio_config_do_rw(struct vfio_pci_device *vdev, char __user *buf,
return ret;
}
-ssize_t vfio_pci_config_rw(struct vfio_pci_device *vdev, char __user *buf,
+ssize_t vfio_pci_config_rw(struct vfio_pci_core_device *vdev, char __user *buf,
size_t count, loff_t *ppos, bool iswrite)
{
size_t done = 0;
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
new file mode 100644
index 000000000000..68198e0f2a63
--- /dev/null
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -0,0 +1,2157 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+ * Author: Alex Williamson <alex.williamson@redhat.com>
+ *
+ * Derived from original vfio:
+ * Copyright 2010 Cisco Systems, Inc. All rights reserved.
+ * Author: Tom Lyon, pugs@cisco.com
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/interrupt.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/vgaarb.h>
+#include <linux/nospec.h>
+#include <linux/sched/mm.h>
+
+#include <linux/vfio_pci_core.h>
+
+#define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>"
+#define DRIVER_DESC "core driver for VFIO based PCI devices"
+
+static bool nointxmask;
+static bool disable_vga;
+static bool disable_idle_d3;
+
+static inline bool vfio_vga_disabled(void)
+{
+#ifdef CONFIG_VFIO_PCI_VGA
+ return disable_vga;
+#else
+ return true;
+#endif
+}
+
+/*
+ * Our VGA arbiter participation is limited since we don't know anything
+ * about the device itself. However, if the device is the only VGA device
+ * downstream of a bridge and VFIO VGA support is disabled, then we can
+ * safely return legacy VGA IO and memory as not decoded since the user
+ * has no way to get to it and routing can be disabled externally at the
+ * bridge.
+ */
+static unsigned int vfio_pci_set_decode(struct pci_dev *pdev, bool single_vga)
+{
+ struct pci_dev *tmp = NULL;
+ unsigned char max_busnr;
+ unsigned int decodes;
+
+ if (single_vga || !vfio_vga_disabled() || pci_is_root_bus(pdev->bus))
+ return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
+ VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
+
+ max_busnr = pci_bus_max_busnr(pdev->bus);
+ decodes = VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+
+ while ((tmp = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, tmp)) != NULL) {
+ if (tmp == pdev ||
+ pci_domain_nr(tmp->bus) != pci_domain_nr(pdev->bus) ||
+ pci_is_root_bus(tmp->bus))
+ continue;
+
+ if (tmp->bus->number >= pdev->bus->number &&
+ tmp->bus->number <= max_busnr) {
+ pci_dev_put(tmp);
+ decodes |= VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
+ break;
+ }
+ }
+
+ return decodes;
+}
+
+static void vfio_pci_probe_mmaps(struct vfio_pci_core_device *vdev)
+{
+ struct resource *res;
+ int i;
+ struct vfio_pci_dummy_resource *dummy_res;
+
+ for (i = 0; i < PCI_STD_NUM_BARS; i++) {
+ int bar = i + PCI_STD_RESOURCES;
+
+ res = &vdev->pdev->resource[bar];
+
+ if (!IS_ENABLED(CONFIG_VFIO_PCI_MMAP))
+ goto no_mmap;
+
+ if (!(res->flags & IORESOURCE_MEM))
+ goto no_mmap;
+
+ /*
+ * The PCI core shouldn't set up a resource with a
+ * type but zero size. But there may be bugs that
+ * cause us to do that.
+ */
+ if (!resource_size(res))
+ goto no_mmap;
+
+ if (resource_size(res) >= PAGE_SIZE) {
+ vdev->bar_mmap_supported[bar] = true;
+ continue;
+ }
+
+ if (!(res->start & ~PAGE_MASK)) {
+ /*
+ * Add a dummy resource to reserve the remainder
+ * of the exclusive page in case that hot-add
+ * device's bar is assigned into it.
+ */
+ dummy_res = kzalloc(sizeof(*dummy_res), GFP_KERNEL);
+ if (dummy_res == NULL)
+ goto no_mmap;
+
+ dummy_res->resource.name = "vfio sub-page reserved";
+ dummy_res->resource.start = res->end + 1;
+ dummy_res->resource.end = res->start + PAGE_SIZE - 1;
+ dummy_res->resource.flags = res->flags;
+ if (request_resource(res->parent,
+ &dummy_res->resource)) {
+ kfree(dummy_res);
+ goto no_mmap;
+ }
+ dummy_res->index = bar;
+ list_add(&dummy_res->res_next,
+ &vdev->dummy_resources_list);
+ vdev->bar_mmap_supported[bar] = true;
+ continue;
+ }
+ /*
+ * Here we don't handle the case when the BAR is not page
+ * aligned because we can't expect the BAR will be
+ * assigned into the same location in a page in guest
+ * when we passthrough the BAR. And it's hard to access
+ * this BAR in userspace because we have no way to get
+ * the BAR's location in a page.
+ */
+no_mmap:
+ vdev->bar_mmap_supported[bar] = false;
+ }
+}
+
+struct vfio_pci_group_info;
+static bool vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set);
+static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
+ struct vfio_pci_group_info *groups);
+
+/*
+ * INTx masking requires the ability to disable INTx signaling via PCI_COMMAND
+ * _and_ the ability detect when the device is asserting INTx via PCI_STATUS.
+ * If a device implements the former but not the latter we would typically
+ * expect broken_intx_masking be set and require an exclusive interrupt.
+ * However since we do have control of the device's ability to assert INTx,
+ * we can instead pretend that the device does not implement INTx, virtualizing
+ * the pin register to report zero and maintaining DisINTx set on the host.
+ */
+static bool vfio_pci_nointx(struct pci_dev *pdev)
+{
+ switch (pdev->vendor) {
+ case PCI_VENDOR_ID_INTEL:
+ switch (pdev->device) {
+ /* All i40e (XL710/X710/XXV710) 10/20/25/40GbE NICs */
+ case 0x1572:
+ case 0x1574:
+ case 0x1580 ... 0x1581:
+ case 0x1583 ... 0x158b:
+ case 0x37d0 ... 0x37d2:
+ /* X550 */
+ case 0x1563:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ return false;
+}
+
+static void vfio_pci_probe_power_state(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ u16 pmcsr;
+
+ if (!pdev->pm_cap)
+ return;
+
+ pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmcsr);
+
+ vdev->needs_pm_restore = !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET);
+}
+
+/*
+ * pci_set_power_state() wrapper handling devices which perform a soft reset on
+ * D3->D0 transition. Save state prior to D0/1/2->D3, stash it on the vdev,
+ * restore when returned to D0. Saved separately from pci_saved_state for use
+ * by PM capability emulation and separately from pci_dev internal saved state
+ * to avoid it being overwritten and consumed around other resets.
+ */
+int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t state)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ bool needs_restore = false, needs_save = false;
+ int ret;
+
+ if (vdev->needs_pm_restore) {
+ if (pdev->current_state < PCI_D3hot && state >= PCI_D3hot) {
+ pci_save_state(pdev);
+ needs_save = true;
+ }
+
+ if (pdev->current_state >= PCI_D3hot && state <= PCI_D0)
+ needs_restore = true;
+ }
+
+ ret = pci_set_power_state(pdev, state);
+
+ if (!ret) {
+ /* D3 might be unsupported via quirk, skip unless in D3 */
+ if (needs_save && pdev->current_state >= PCI_D3hot) {
+ vdev->pm_save = pci_store_saved_state(pdev);
+ } else if (needs_restore) {
+ pci_load_and_free_saved_state(pdev, &vdev->pm_save);
+ pci_restore_state(pdev);
+ }
+ }
+
+ return ret;
+}
+
+int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ int ret;
+ u16 cmd;
+ u8 msix_pos;
+
+ vfio_pci_set_power_state(vdev, PCI_D0);
+
+ /* Don't allow our initial saved state to include busmaster */
+ pci_clear_master(pdev);
+
+ ret = pci_enable_device(pdev);
+ if (ret)
+ return ret;
+
+ /* If reset fails because of the device lock, fail this path entirely */
+ ret = pci_try_reset_function(pdev);
+ if (ret == -EAGAIN) {
+ pci_disable_device(pdev);
+ return ret;
+ }
+
+ vdev->reset_works = !ret;
+ pci_save_state(pdev);
+ vdev->pci_saved_state = pci_store_saved_state(pdev);
+ if (!vdev->pci_saved_state)
+ pci_dbg(pdev, "%s: Couldn't store saved state\n", __func__);
+
+ if (likely(!nointxmask)) {
+ if (vfio_pci_nointx(pdev)) {
+ pci_info(pdev, "Masking broken INTx support\n");
+ vdev->nointx = true;
+ pci_intx(pdev, 0);
+ } else
+ vdev->pci_2_3 = pci_intx_mask_supported(pdev);
+ }
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ if (vdev->pci_2_3 && (cmd & PCI_COMMAND_INTX_DISABLE)) {
+ cmd &= ~PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+ }
+
+ ret = vfio_config_init(vdev);
+ if (ret) {
+ kfree(vdev->pci_saved_state);
+ vdev->pci_saved_state = NULL;
+ pci_disable_device(pdev);
+ return ret;
+ }
+
+ msix_pos = pdev->msix_cap;
+ if (msix_pos) {
+ u16 flags;
+ u32 table;
+
+ pci_read_config_word(pdev, msix_pos + PCI_MSIX_FLAGS, &flags);
+ pci_read_config_dword(pdev, msix_pos + PCI_MSIX_TABLE, &table);
+
+ vdev->msix_bar = table & PCI_MSIX_TABLE_BIR;
+ vdev->msix_offset = table & PCI_MSIX_TABLE_OFFSET;
+ vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16;
+ } else
+ vdev->msix_bar = 0xFF;
+
+ if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
+ vdev->has_vga = true;
+
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_enable);
+
+void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ struct vfio_pci_dummy_resource *dummy_res, *tmp;
+ struct vfio_pci_ioeventfd *ioeventfd, *ioeventfd_tmp;
+ int i, bar;
+
+ /* For needs_reset */
+ lockdep_assert_held(&vdev->vdev.dev_set->lock);
+
+ /* Stop the device from further DMA */
+ pci_clear_master(pdev);
+
+ vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE |
+ VFIO_IRQ_SET_ACTION_TRIGGER,
+ vdev->irq_type, 0, 0, NULL);
+
+ /* Device closed, don't need mutex here */
+ list_for_each_entry_safe(ioeventfd, ioeventfd_tmp,
+ &vdev->ioeventfds_list, next) {
+ vfio_virqfd_disable(&ioeventfd->virqfd);
+ list_del(&ioeventfd->next);
+ kfree(ioeventfd);
+ }
+ vdev->ioeventfds_nr = 0;
+
+ vdev->virq_disabled = false;
+
+ for (i = 0; i < vdev->num_regions; i++)
+ vdev->region[i].ops->release(vdev, &vdev->region[i]);
+
+ vdev->num_regions = 0;
+ kfree(vdev->region);
+ vdev->region = NULL; /* don't krealloc a freed pointer */
+
+ vfio_config_free(vdev);
+
+ for (i = 0; i < PCI_STD_NUM_BARS; i++) {
+ bar = i + PCI_STD_RESOURCES;
+ if (!vdev->barmap[bar])
+ continue;
+ pci_iounmap(pdev, vdev->barmap[bar]);
+ pci_release_selected_regions(pdev, 1 << bar);
+ vdev->barmap[bar] = NULL;
+ }
+
+ list_for_each_entry_safe(dummy_res, tmp,
+ &vdev->dummy_resources_list, res_next) {
+ list_del(&dummy_res->res_next);
+ release_resource(&dummy_res->resource);
+ kfree(dummy_res);
+ }
+
+ vdev->needs_reset = true;
+
+ /*
+ * If we have saved state, restore it. If we can reset the device,
+ * even better. Resetting with current state seems better than
+ * nothing, but saving and restoring current state without reset
+ * is just busy work.
+ */
+ if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
+ pci_info(pdev, "%s: Couldn't reload saved state\n", __func__);
+
+ if (!vdev->reset_works)
+ goto out;
+
+ pci_save_state(pdev);
+ }
+
+ /*
+ * Disable INTx and MSI, presumably to avoid spurious interrupts
+ * during reset. Stolen from pci_reset_function()
+ */
+ pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
+
+ /*
+ * Try to get the locks ourselves to prevent a deadlock. The
+ * success of this is dependent on being able to lock the device,
+ * which is not always possible.
+ * We can not use the "try" reset interface here, which will
+ * overwrite the previously restored configuration information.
+ */
+ if (vdev->reset_works && pci_dev_trylock(pdev)) {
+ if (!__pci_reset_function_locked(pdev))
+ vdev->needs_reset = false;
+ pci_dev_unlock(pdev);
+ }
+
+ pci_restore_state(pdev);
+out:
+ pci_disable_device(pdev);
+
+ if (!vfio_pci_dev_set_try_reset(vdev->vdev.dev_set) && !disable_idle_d3)
+ vfio_pci_set_power_state(vdev, PCI_D3hot);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_disable);
+
+static struct vfio_pci_core_device *get_pf_vdev(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *physfn = pci_physfn(vdev->pdev);
+ struct vfio_device *pf_dev;
+
+ if (!vdev->pdev->is_virtfn)
+ return NULL;
+
+ pf_dev = vfio_device_get_from_dev(&physfn->dev);
+ if (!pf_dev)
+ return NULL;
+
+ if (pci_dev_driver(physfn) != pci_dev_driver(vdev->pdev)) {
+ vfio_device_put(pf_dev);
+ return NULL;
+ }
+
+ return container_of(pf_dev, struct vfio_pci_core_device, vdev);
+}
+
+static void vfio_pci_vf_token_user_add(struct vfio_pci_core_device *vdev, int val)
+{
+ struct vfio_pci_core_device *pf_vdev = get_pf_vdev(vdev);
+
+ if (!pf_vdev)
+ return;
+
+ mutex_lock(&pf_vdev->vf_token->lock);
+ pf_vdev->vf_token->users += val;
+ WARN_ON(pf_vdev->vf_token->users < 0);
+ mutex_unlock(&pf_vdev->vf_token->lock);
+
+ vfio_device_put(&pf_vdev->vdev);
+}
+
+void vfio_pci_core_close_device(struct vfio_device *core_vdev)
+{
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
+
+ vfio_pci_vf_token_user_add(vdev, -1);
+ vfio_spapr_pci_eeh_release(vdev->pdev);
+ vfio_pci_core_disable(vdev);
+
+ mutex_lock(&vdev->igate);
+ if (vdev->err_trigger) {
+ eventfd_ctx_put(vdev->err_trigger);
+ vdev->err_trigger = NULL;
+ }
+ if (vdev->req_trigger) {
+ eventfd_ctx_put(vdev->req_trigger);
+ vdev->req_trigger = NULL;
+ }
+ mutex_unlock(&vdev->igate);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_close_device);
+
+void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev)
+{
+ vfio_pci_probe_mmaps(vdev);
+ vfio_spapr_pci_eeh_open(vdev->pdev);
+ vfio_pci_vf_token_user_add(vdev, 1);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable);
+
+static int vfio_pci_get_irq_count(struct vfio_pci_core_device *vdev, int irq_type)
+{
+ if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) {
+ u8 pin;
+
+ if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) ||
+ vdev->nointx || vdev->pdev->is_virtfn)
+ return 0;
+
+ pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin);
+
+ return pin ? 1 : 0;
+ } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) {
+ u8 pos;
+ u16 flags;
+
+ pos = vdev->pdev->msi_cap;
+ if (pos) {
+ pci_read_config_word(vdev->pdev,
+ pos + PCI_MSI_FLAGS, &flags);
+ return 1 << ((flags & PCI_MSI_FLAGS_QMASK) >> 1);
+ }
+ } else if (irq_type == VFIO_PCI_MSIX_IRQ_INDEX) {
+ u8 pos;
+ u16 flags;
+
+ pos = vdev->pdev->msix_cap;
+ if (pos) {
+ pci_read_config_word(vdev->pdev,
+ pos + PCI_MSIX_FLAGS, &flags);
+
+ return (flags & PCI_MSIX_FLAGS_QSIZE) + 1;
+ }
+ } else if (irq_type == VFIO_PCI_ERR_IRQ_INDEX) {
+ if (pci_is_pcie(vdev->pdev))
+ return 1;
+ } else if (irq_type == VFIO_PCI_REQ_IRQ_INDEX) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)
+{
+ (*(int *)data)++;
+ return 0;
+}
+
+struct vfio_pci_fill_info {
+ int max;
+ int cur;
+ struct vfio_pci_dependent_device *devices;
+};
+
+static int vfio_pci_fill_devs(struct pci_dev *pdev, void *data)
+{
+ struct vfio_pci_fill_info *fill = data;
+ struct iommu_group *iommu_group;
+
+ if (fill->cur == fill->max)
+ return -EAGAIN; /* Something changed, try again */
+
+ iommu_group = iommu_group_get(&pdev->dev);
+ if (!iommu_group)
+ return -EPERM; /* Cannot reset non-isolated devices */
+
+ fill->devices[fill->cur].group_id = iommu_group_id(iommu_group);
+ fill->devices[fill->cur].segment = pci_domain_nr(pdev->bus);
+ fill->devices[fill->cur].bus = pdev->bus->number;
+ fill->devices[fill->cur].devfn = pdev->devfn;
+ fill->cur++;
+ iommu_group_put(iommu_group);
+ return 0;
+}
+
+struct vfio_pci_group_info {
+ int count;
+ struct vfio_group **groups;
+};
+
+static bool vfio_pci_dev_below_slot(struct pci_dev *pdev, struct pci_slot *slot)
+{
+ for (; pdev; pdev = pdev->bus->self)
+ if (pdev->bus == slot->bus)
+ return (pdev->slot == slot);
+ return false;
+}
+
+struct vfio_pci_walk_info {
+ int (*fn)(struct pci_dev *, void *data);
+ void *data;
+ struct pci_dev *pdev;
+ bool slot;
+ int ret;
+};
+
+static int vfio_pci_walk_wrapper(struct pci_dev *pdev, void *data)
+{
+ struct vfio_pci_walk_info *walk = data;
+
+ if (!walk->slot || vfio_pci_dev_below_slot(pdev, walk->pdev->slot))
+ walk->ret = walk->fn(pdev, walk->data);
+
+ return walk->ret;
+}
+
+static int vfio_pci_for_each_slot_or_bus(struct pci_dev *pdev,
+ int (*fn)(struct pci_dev *,
+ void *data), void *data,
+ bool slot)
+{
+ struct vfio_pci_walk_info walk = {
+ .fn = fn, .data = data, .pdev = pdev, .slot = slot, .ret = 0,
+ };
+
+ pci_walk_bus(pdev->bus, vfio_pci_walk_wrapper, &walk);
+
+ return walk.ret;
+}
+
+static int msix_mmappable_cap(struct vfio_pci_core_device *vdev,
+ struct vfio_info_cap *caps)
+{
+ struct vfio_info_cap_header header = {
+ .id = VFIO_REGION_INFO_CAP_MSIX_MAPPABLE,
+ .version = 1
+ };
+
+ return vfio_info_add_capability(caps, &header, sizeof(header));
+}
+
+int vfio_pci_register_dev_region(struct vfio_pci_core_device *vdev,
+ unsigned int type, unsigned int subtype,
+ const struct vfio_pci_regops *ops,
+ size_t size, u32 flags, void *data)
+{
+ struct vfio_pci_region *region;
+
+ region = krealloc(vdev->region,
+ (vdev->num_regions + 1) * sizeof(*region),
+ GFP_KERNEL);
+ if (!region)
+ return -ENOMEM;
+
+ vdev->region = region;
+ vdev->region[vdev->num_regions].type = type;
+ vdev->region[vdev->num_regions].subtype = subtype;
+ vdev->region[vdev->num_regions].ops = ops;
+ vdev->region[vdev->num_regions].size = size;
+ vdev->region[vdev->num_regions].flags = flags;
+ vdev->region[vdev->num_regions].data = data;
+
+ vdev->num_regions++;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_register_dev_region);
+
+long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
+ unsigned long arg)
+{
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
+ unsigned long minsz;
+
+ if (cmd == VFIO_DEVICE_GET_INFO) {
+ struct vfio_device_info info;
+ struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
+ unsigned long capsz;
+ int ret;
+
+ minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+ /* For backward compatibility, cannot require this */
+ capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ if (info.argsz >= capsz) {
+ minsz = capsz;
+ info.cap_offset = 0;
+ }
+
+ info.flags = VFIO_DEVICE_FLAGS_PCI;
+
+ if (vdev->reset_works)
+ info.flags |= VFIO_DEVICE_FLAGS_RESET;
+
+ info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions;
+ info.num_irqs = VFIO_PCI_NUM_IRQS;
+
+ ret = vfio_pci_info_zdev_add_caps(vdev, &caps);
+ if (ret && ret != -ENODEV) {
+ pci_warn(vdev->pdev, "Failed to setup zPCI info capabilities\n");
+ return ret;
+ }
+
+ if (caps.size) {
+ info.flags |= VFIO_DEVICE_FLAGS_CAPS;
+ if (info.argsz < sizeof(info) + caps.size) {
+ info.argsz = sizeof(info) + caps.size;
+ } else {
+ vfio_info_cap_shift(&caps, sizeof(info));
+ if (copy_to_user((void __user *)arg +
+ sizeof(info), caps.buf,
+ caps.size)) {
+ kfree(caps.buf);
+ return -EFAULT;
+ }
+ info.cap_offset = sizeof(info);
+ }
+
+ kfree(caps.buf);
+ }
+
+ return copy_to_user((void __user *)arg, &info, minsz) ?
+ -EFAULT : 0;
+
+ } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+ struct pci_dev *pdev = vdev->pdev;
+ struct vfio_region_info info;
+ struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
+ int i, ret;
+
+ minsz = offsetofend(struct vfio_region_info, offset);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ switch (info.index) {
+ case VFIO_PCI_CONFIG_REGION_INDEX:
+ info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+ info.size = pdev->cfg_size;
+ info.flags = VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE;
+ break;
+ case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
+ info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+ info.size = pci_resource_len(pdev, info.index);
+ if (!info.size) {
+ info.flags = 0;
+ break;
+ }
+
+ info.flags = VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE;
+ if (vdev->bar_mmap_supported[info.index]) {
+ info.flags |= VFIO_REGION_INFO_FLAG_MMAP;
+ if (info.index == vdev->msix_bar) {
+ ret = msix_mmappable_cap(vdev, &caps);
+ if (ret)
+ return ret;
+ }
+ }
+
+ break;
+ case VFIO_PCI_ROM_REGION_INDEX:
+ {
+ void __iomem *io;
+ size_t size;
+ u16 cmd;
+
+ info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+ info.flags = 0;
+
+ /* Report the BAR size, not the ROM size */
+ info.size = pci_resource_len(pdev, info.index);
+ if (!info.size) {
+ /* Shadow ROMs appear as PCI option ROMs */
+ if (pdev->resource[PCI_ROM_RESOURCE].flags &
+ IORESOURCE_ROM_SHADOW)
+ info.size = 0x20000;
+ else
+ break;
+ }
+
+ /*
+ * Is it really there? Enable memory decode for
+ * implicit access in pci_map_rom().
+ */
+ cmd = vfio_pci_memory_lock_and_enable(vdev);
+ io = pci_map_rom(pdev, &size);
+ if (io) {
+ info.flags = VFIO_REGION_INFO_FLAG_READ;
+ pci_unmap_rom(pdev, io);
+ } else {
+ info.size = 0;
+ }
+ vfio_pci_memory_unlock_and_restore(vdev, cmd);
+
+ break;
+ }
+ case VFIO_PCI_VGA_REGION_INDEX:
+ if (!vdev->has_vga)
+ return -EINVAL;
+
+ info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+ info.size = 0xc0000;
+ info.flags = VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE;
+
+ break;
+ default:
+ {
+ struct vfio_region_info_cap_type cap_type = {
+ .header.id = VFIO_REGION_INFO_CAP_TYPE,
+ .header.version = 1 };
+
+ if (info.index >=
+ VFIO_PCI_NUM_REGIONS + vdev->num_regions)
+ return -EINVAL;
+ info.index = array_index_nospec(info.index,
+ VFIO_PCI_NUM_REGIONS +
+ vdev->num_regions);
+
+ i = info.index - VFIO_PCI_NUM_REGIONS;
+
+ info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+ info.size = vdev->region[i].size;
+ info.flags = vdev->region[i].flags;
+
+ cap_type.type = vdev->region[i].type;
+ cap_type.subtype = vdev->region[i].subtype;
+
+ ret = vfio_info_add_capability(&caps, &cap_type.header,
+ sizeof(cap_type));
+ if (ret)
+ return ret;
+
+ if (vdev->region[i].ops->add_capability) {
+ ret = vdev->region[i].ops->add_capability(vdev,
+ &vdev->region[i], &caps);
+ if (ret)
+ return ret;
+ }
+ }
+ }
+
+ if (caps.size) {
+ info.flags |= VFIO_REGION_INFO_FLAG_CAPS;
+ if (info.argsz < sizeof(info) + caps.size) {
+ info.argsz = sizeof(info) + caps.size;
+ info.cap_offset = 0;
+ } else {
+ vfio_info_cap_shift(&caps, sizeof(info));
+ if (copy_to_user((void __user *)arg +
+ sizeof(info), caps.buf,
+ caps.size)) {
+ kfree(caps.buf);
+ return -EFAULT;
+ }
+ info.cap_offset = sizeof(info);
+ }
+
+ kfree(caps.buf);
+ }
+
+ return copy_to_user((void __user *)arg, &info, minsz) ?
+ -EFAULT : 0;
+
+ } else if (cmd == 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 >= VFIO_PCI_NUM_IRQS)
+ return -EINVAL;
+
+ switch (info.index) {
+ case VFIO_PCI_INTX_IRQ_INDEX ... VFIO_PCI_MSIX_IRQ_INDEX:
+ case VFIO_PCI_REQ_IRQ_INDEX:
+ break;
+ case VFIO_PCI_ERR_IRQ_INDEX:
+ if (pci_is_pcie(vdev->pdev))
+ break;
+ fallthrough;
+ default:
+ return -EINVAL;
+ }
+
+ info.flags = VFIO_IRQ_INFO_EVENTFD;
+
+ info.count = vfio_pci_get_irq_count(vdev, info.index);
+
+ if (info.index == VFIO_PCI_INTX_IRQ_INDEX)
+ info.flags |= (VFIO_IRQ_INFO_MASKABLE |
+ VFIO_IRQ_INFO_AUTOMASKED);
+ else
+ info.flags |= VFIO_IRQ_INFO_NORESIZE;
+
+ return copy_to_user((void __user *)arg, &info, minsz) ?
+ -EFAULT : 0;
+
+ } else if (cmd == VFIO_DEVICE_SET_IRQS) {
+ struct vfio_irq_set hdr;
+ u8 *data = NULL;
+ int max, ret = 0;
+ size_t data_size = 0;
+
+ minsz = offsetofend(struct vfio_irq_set, count);
+
+ if (copy_from_user(&hdr, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ max = vfio_pci_get_irq_count(vdev, hdr.index);
+
+ ret = vfio_set_irqs_validate_and_prepare(&hdr, max,
+ VFIO_PCI_NUM_IRQS, &data_size);
+ if (ret)
+ return ret;
+
+ if (data_size) {
+ data = memdup_user((void __user *)(arg + minsz),
+ data_size);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+ }
+
+ mutex_lock(&vdev->igate);
+
+ ret = vfio_pci_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
+ hdr.start, hdr.count, data);
+
+ mutex_unlock(&vdev->igate);
+ kfree(data);
+
+ return ret;
+
+ } else if (cmd == VFIO_DEVICE_RESET) {
+ int ret;
+
+ if (!vdev->reset_works)
+ return -EINVAL;
+
+ vfio_pci_zap_and_down_write_memory_lock(vdev);
+ ret = pci_try_reset_function(vdev->pdev);
+ up_write(&vdev->memory_lock);
+
+ return ret;
+
+ } else if (cmd == VFIO_DEVICE_GET_PCI_HOT_RESET_INFO) {
+ struct vfio_pci_hot_reset_info hdr;
+ struct vfio_pci_fill_info fill = { 0 };
+ struct vfio_pci_dependent_device *devices = NULL;
+ bool slot = false;
+ int ret = 0;
+
+ minsz = offsetofend(struct vfio_pci_hot_reset_info, count);
+
+ if (copy_from_user(&hdr, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (hdr.argsz < minsz)
+ return -EINVAL;
+
+ hdr.flags = 0;
+
+ /* Can we do a slot or bus reset or neither? */
+ if (!pci_probe_reset_slot(vdev->pdev->slot))
+ slot = true;
+ else if (pci_probe_reset_bus(vdev->pdev->bus))
+ return -ENODEV;
+
+ /* How many devices are affected? */
+ ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
+ vfio_pci_count_devs,
+ &fill.max, slot);
+ if (ret)
+ return ret;
+
+ WARN_ON(!fill.max); /* Should always be at least one */
+
+ /*
+ * If there's enough space, fill it now, otherwise return
+ * -ENOSPC and the number of devices affected.
+ */
+ if (hdr.argsz < sizeof(hdr) + (fill.max * sizeof(*devices))) {
+ ret = -ENOSPC;
+ hdr.count = fill.max;
+ goto reset_info_exit;
+ }
+
+ devices = kcalloc(fill.max, sizeof(*devices), GFP_KERNEL);
+ if (!devices)
+ return -ENOMEM;
+
+ fill.devices = devices;
+
+ ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
+ vfio_pci_fill_devs,
+ &fill, slot);
+
+ /*
+ * If a device was removed between counting and filling,
+ * we may come up short of fill.max. If a device was
+ * added, we'll have a return of -EAGAIN above.
+ */
+ if (!ret)
+ hdr.count = fill.cur;
+
+reset_info_exit:
+ if (copy_to_user((void __user *)arg, &hdr, minsz))
+ ret = -EFAULT;
+
+ if (!ret) {
+ if (copy_to_user((void __user *)(arg + minsz), devices,
+ hdr.count * sizeof(*devices)))
+ ret = -EFAULT;
+ }
+
+ kfree(devices);
+ return ret;
+
+ } else if (cmd == VFIO_DEVICE_PCI_HOT_RESET) {
+ struct vfio_pci_hot_reset hdr;
+ int32_t *group_fds;
+ struct vfio_group **groups;
+ struct vfio_pci_group_info info;
+ bool slot = false;
+ int group_idx, count = 0, ret = 0;
+
+ minsz = offsetofend(struct vfio_pci_hot_reset, count);
+
+ if (copy_from_user(&hdr, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (hdr.argsz < minsz || hdr.flags)
+ return -EINVAL;
+
+ /* Can we do a slot or bus reset or neither? */
+ if (!pci_probe_reset_slot(vdev->pdev->slot))
+ slot = true;
+ else if (pci_probe_reset_bus(vdev->pdev->bus))
+ return -ENODEV;
+
+ /*
+ * We can't let userspace give us an arbitrarily large
+ * buffer to copy, so verify how many we think there
+ * could be. Note groups can have multiple devices so
+ * one group per device is the max.
+ */
+ ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
+ vfio_pci_count_devs,
+ &count, slot);
+ if (ret)
+ return ret;
+
+ /* Somewhere between 1 and count is OK */
+ if (!hdr.count || hdr.count > count)
+ return -EINVAL;
+
+ group_fds = kcalloc(hdr.count, sizeof(*group_fds), GFP_KERNEL);
+ groups = kcalloc(hdr.count, sizeof(*groups), GFP_KERNEL);
+ if (!group_fds || !groups) {
+ kfree(group_fds);
+ kfree(groups);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(group_fds, (void __user *)(arg + minsz),
+ hdr.count * sizeof(*group_fds))) {
+ kfree(group_fds);
+ kfree(groups);
+ return -EFAULT;
+ }
+
+ /*
+ * For each group_fd, get the group through the vfio external
+ * user interface and store the group and iommu ID. This
+ * ensures the group is held across the reset.
+ */
+ for (group_idx = 0; group_idx < hdr.count; group_idx++) {
+ struct vfio_group *group;
+ struct fd f = fdget(group_fds[group_idx]);
+ if (!f.file) {
+ ret = -EBADF;
+ break;
+ }
+
+ group = vfio_group_get_external_user(f.file);
+ fdput(f);
+ if (IS_ERR(group)) {
+ ret = PTR_ERR(group);
+ break;
+ }
+
+ groups[group_idx] = group;
+ }
+
+ kfree(group_fds);
+
+ /* release reference to groups on error */
+ if (ret)
+ goto hot_reset_release;
+
+ info.count = hdr.count;
+ info.groups = groups;
+
+ ret = vfio_pci_dev_set_hot_reset(vdev->vdev.dev_set, &info);
+
+hot_reset_release:
+ for (group_idx--; group_idx >= 0; group_idx--)
+ vfio_group_put_external_user(groups[group_idx]);
+
+ kfree(groups);
+ return ret;
+ } else if (cmd == VFIO_DEVICE_IOEVENTFD) {
+ struct vfio_device_ioeventfd ioeventfd;
+ int count;
+
+ minsz = offsetofend(struct vfio_device_ioeventfd, fd);
+
+ if (copy_from_user(&ioeventfd, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (ioeventfd.argsz < minsz)
+ return -EINVAL;
+
+ if (ioeventfd.flags & ~VFIO_DEVICE_IOEVENTFD_SIZE_MASK)
+ return -EINVAL;
+
+ count = ioeventfd.flags & VFIO_DEVICE_IOEVENTFD_SIZE_MASK;
+
+ if (hweight8(count) != 1 || ioeventfd.fd < -1)
+ return -EINVAL;
+
+ return vfio_pci_ioeventfd(vdev, ioeventfd.offset,
+ ioeventfd.data, count, ioeventfd.fd);
+ } else if (cmd == VFIO_DEVICE_FEATURE) {
+ struct vfio_device_feature feature;
+ uuid_t uuid;
+
+ minsz = offsetofend(struct vfio_device_feature, flags);
+
+ if (copy_from_user(&feature, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (feature.argsz < minsz)
+ return -EINVAL;
+
+ /* Check unknown flags */
+ if (feature.flags & ~(VFIO_DEVICE_FEATURE_MASK |
+ VFIO_DEVICE_FEATURE_SET |
+ VFIO_DEVICE_FEATURE_GET |
+ VFIO_DEVICE_FEATURE_PROBE))
+ return -EINVAL;
+
+ /* GET & SET are mutually exclusive except with PROBE */
+ if (!(feature.flags & VFIO_DEVICE_FEATURE_PROBE) &&
+ (feature.flags & VFIO_DEVICE_FEATURE_SET) &&
+ (feature.flags & VFIO_DEVICE_FEATURE_GET))
+ return -EINVAL;
+
+ switch (feature.flags & VFIO_DEVICE_FEATURE_MASK) {
+ case VFIO_DEVICE_FEATURE_PCI_VF_TOKEN:
+ if (!vdev->vf_token)
+ return -ENOTTY;
+
+ /*
+ * We do not support GET of the VF Token UUID as this
+ * could expose the token of the previous device user.
+ */
+ if (feature.flags & VFIO_DEVICE_FEATURE_GET)
+ return -EINVAL;
+
+ if (feature.flags & VFIO_DEVICE_FEATURE_PROBE)
+ return 0;
+
+ /* Don't SET unless told to do so */
+ if (!(feature.flags & VFIO_DEVICE_FEATURE_SET))
+ return -EINVAL;
+
+ if (feature.argsz < minsz + sizeof(uuid))
+ return -EINVAL;
+
+ if (copy_from_user(&uuid, (void __user *)(arg + minsz),
+ sizeof(uuid)))
+ return -EFAULT;
+
+ mutex_lock(&vdev->vf_token->lock);
+ uuid_copy(&vdev->vf_token->uuid, &uuid);
+ mutex_unlock(&vdev->vf_token->lock);
+
+ return 0;
+ default:
+ return -ENOTTY;
+ }
+ }
+
+ return -ENOTTY;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_ioctl);
+
+static ssize_t vfio_pci_rw(struct vfio_pci_core_device *vdev, char __user *buf,
+ size_t count, loff_t *ppos, bool iswrite)
+{
+ unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
+
+ if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions)
+ return -EINVAL;
+
+ switch (index) {
+ case VFIO_PCI_CONFIG_REGION_INDEX:
+ return vfio_pci_config_rw(vdev, buf, count, ppos, iswrite);
+
+ case VFIO_PCI_ROM_REGION_INDEX:
+ if (iswrite)
+ return -EINVAL;
+ return vfio_pci_bar_rw(vdev, buf, count, ppos, false);
+
+ case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
+ return vfio_pci_bar_rw(vdev, buf, count, ppos, iswrite);
+
+ case VFIO_PCI_VGA_REGION_INDEX:
+ return vfio_pci_vga_rw(vdev, buf, count, ppos, iswrite);
+ default:
+ index -= VFIO_PCI_NUM_REGIONS;
+ return vdev->region[index].ops->rw(vdev, buf,
+ count, ppos, iswrite);
+ }
+
+ return -EINVAL;
+}
+
+ssize_t vfio_pci_core_read(struct vfio_device *core_vdev, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
+
+ if (!count)
+ return 0;
+
+ return vfio_pci_rw(vdev, buf, count, ppos, false);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_read);
+
+ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
+
+ if (!count)
+ return 0;
+
+ return vfio_pci_rw(vdev, (char __user *)buf, count, ppos, true);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_write);
+
+/* Return 1 on zap and vma_lock acquired, 0 on contention (only with @try) */
+static int vfio_pci_zap_and_vma_lock(struct vfio_pci_core_device *vdev, bool try)
+{
+ struct vfio_pci_mmap_vma *mmap_vma, *tmp;
+
+ /*
+ * Lock ordering:
+ * vma_lock is nested under mmap_lock for vm_ops callback paths.
+ * The memory_lock semaphore is used by both code paths calling
+ * into this function to zap vmas and the vm_ops.fault callback
+ * to protect the memory enable state of the device.
+ *
+ * When zapping vmas we need to maintain the mmap_lock => vma_lock
+ * ordering, which requires using vma_lock to walk vma_list to
+ * acquire an mm, then dropping vma_lock to get the mmap_lock and
+ * reacquiring vma_lock. This logic is derived from similar
+ * requirements in uverbs_user_mmap_disassociate().
+ *
+ * mmap_lock must always be the top-level lock when it is taken.
+ * Therefore we can only hold the memory_lock write lock when
+ * vma_list is empty, as we'd need to take mmap_lock to clear
+ * entries. vma_list can only be guaranteed empty when holding
+ * vma_lock, thus memory_lock is nested under vma_lock.
+ *
+ * This enables the vm_ops.fault callback to acquire vma_lock,
+ * followed by memory_lock read lock, while already holding
+ * mmap_lock without risk of deadlock.
+ */
+ while (1) {
+ struct mm_struct *mm = NULL;
+
+ if (try) {
+ if (!mutex_trylock(&vdev->vma_lock))
+ return 0;
+ } else {
+ mutex_lock(&vdev->vma_lock);
+ }
+ while (!list_empty(&vdev->vma_list)) {
+ mmap_vma = list_first_entry(&vdev->vma_list,
+ struct vfio_pci_mmap_vma,
+ vma_next);
+ mm = mmap_vma->vma->vm_mm;
+ if (mmget_not_zero(mm))
+ break;
+
+ list_del(&mmap_vma->vma_next);
+ kfree(mmap_vma);
+ mm = NULL;
+ }
+ if (!mm)
+ return 1;
+ mutex_unlock(&vdev->vma_lock);
+
+ if (try) {
+ if (!mmap_read_trylock(mm)) {
+ mmput(mm);
+ return 0;
+ }
+ } else {
+ mmap_read_lock(mm);
+ }
+ if (try) {
+ if (!mutex_trylock(&vdev->vma_lock)) {
+ mmap_read_unlock(mm);
+ mmput(mm);
+ return 0;
+ }
+ } else {
+ mutex_lock(&vdev->vma_lock);
+ }
+ list_for_each_entry_safe(mmap_vma, tmp,
+ &vdev->vma_list, vma_next) {
+ struct vm_area_struct *vma = mmap_vma->vma;
+
+ if (vma->vm_mm != mm)
+ continue;
+
+ list_del(&mmap_vma->vma_next);
+ kfree(mmap_vma);
+
+ zap_vma_ptes(vma, vma->vm_start,
+ vma->vm_end - vma->vm_start);
+ }
+ mutex_unlock(&vdev->vma_lock);
+ mmap_read_unlock(mm);
+ mmput(mm);
+ }
+}
+
+void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device *vdev)
+{
+ vfio_pci_zap_and_vma_lock(vdev, false);
+ down_write(&vdev->memory_lock);
+ mutex_unlock(&vdev->vma_lock);
+}
+
+u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_core_device *vdev)
+{
+ u16 cmd;
+
+ down_write(&vdev->memory_lock);
+ pci_read_config_word(vdev->pdev, PCI_COMMAND, &cmd);
+ if (!(cmd & PCI_COMMAND_MEMORY))
+ pci_write_config_word(vdev->pdev, PCI_COMMAND,
+ cmd | PCI_COMMAND_MEMORY);
+
+ return cmd;
+}
+
+void vfio_pci_memory_unlock_and_restore(struct vfio_pci_core_device *vdev, u16 cmd)
+{
+ pci_write_config_word(vdev->pdev, PCI_COMMAND, cmd);
+ up_write(&vdev->memory_lock);
+}
+
+/* Caller holds vma_lock */
+static int __vfio_pci_add_vma(struct vfio_pci_core_device *vdev,
+ struct vm_area_struct *vma)
+{
+ struct vfio_pci_mmap_vma *mmap_vma;
+
+ mmap_vma = kmalloc(sizeof(*mmap_vma), GFP_KERNEL);
+ if (!mmap_vma)
+ return -ENOMEM;
+
+ mmap_vma->vma = vma;
+ list_add(&mmap_vma->vma_next, &vdev->vma_list);
+
+ return 0;
+}
+
+/*
+ * Zap mmaps on open so that we can fault them in on access and therefore
+ * our vma_list only tracks mappings accessed since last zap.
+ */
+static void vfio_pci_mmap_open(struct vm_area_struct *vma)
+{
+ zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
+}
+
+static void vfio_pci_mmap_close(struct vm_area_struct *vma)
+{
+ struct vfio_pci_core_device *vdev = vma->vm_private_data;
+ struct vfio_pci_mmap_vma *mmap_vma;
+
+ mutex_lock(&vdev->vma_lock);
+ list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) {
+ if (mmap_vma->vma == vma) {
+ list_del(&mmap_vma->vma_next);
+ kfree(mmap_vma);
+ break;
+ }
+ }
+ mutex_unlock(&vdev->vma_lock);
+}
+
+static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct vfio_pci_core_device *vdev = vma->vm_private_data;
+ struct vfio_pci_mmap_vma *mmap_vma;
+ vm_fault_t ret = VM_FAULT_NOPAGE;
+
+ mutex_lock(&vdev->vma_lock);
+ down_read(&vdev->memory_lock);
+
+ if (!__vfio_pci_memory_enabled(vdev)) {
+ ret = VM_FAULT_SIGBUS;
+ goto up_out;
+ }
+
+ /*
+ * We populate the whole vma on fault, so we need to test whether
+ * the vma has already been mapped, such as for concurrent faults
+ * to the same vma. io_remap_pfn_range() will trigger a BUG_ON if
+ * we ask it to fill the same range again.
+ */
+ list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) {
+ if (mmap_vma->vma == vma)
+ goto up_out;
+ }
+
+ if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot)) {
+ ret = VM_FAULT_SIGBUS;
+ zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
+ goto up_out;
+ }
+
+ if (__vfio_pci_add_vma(vdev, vma)) {
+ ret = VM_FAULT_OOM;
+ zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
+ }
+
+up_out:
+ up_read(&vdev->memory_lock);
+ mutex_unlock(&vdev->vma_lock);
+ return ret;
+}
+
+static const struct vm_operations_struct vfio_pci_mmap_ops = {
+ .open = vfio_pci_mmap_open,
+ .close = vfio_pci_mmap_close,
+ .fault = vfio_pci_mmap_fault,
+};
+
+int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma)
+{
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
+ struct pci_dev *pdev = vdev->pdev;
+ unsigned int index;
+ u64 phys_len, req_len, pgoff, req_start;
+ int ret;
+
+ index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
+
+ if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions)
+ return -EINVAL;
+ if (vma->vm_end < vma->vm_start)
+ return -EINVAL;
+ if ((vma->vm_flags & VM_SHARED) == 0)
+ return -EINVAL;
+ if (index >= VFIO_PCI_NUM_REGIONS) {
+ int regnum = index - VFIO_PCI_NUM_REGIONS;
+ struct vfio_pci_region *region = vdev->region + regnum;
+
+ if (region->ops && region->ops->mmap &&
+ (region->flags & VFIO_REGION_INFO_FLAG_MMAP))
+ return region->ops->mmap(vdev, region, vma);
+ return -EINVAL;
+ }
+ if (index >= VFIO_PCI_ROM_REGION_INDEX)
+ return -EINVAL;
+ if (!vdev->bar_mmap_supported[index])
+ return -EINVAL;
+
+ phys_len = PAGE_ALIGN(pci_resource_len(pdev, index));
+ req_len = vma->vm_end - vma->vm_start;
+ pgoff = vma->vm_pgoff &
+ ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+ req_start = pgoff << PAGE_SHIFT;
+
+ if (req_start + req_len > phys_len)
+ return -EINVAL;
+
+ /*
+ * Even though we don't make use of the barmap for the mmap,
+ * we need to request the region and the barmap tracks that.
+ */
+ if (!vdev->barmap[index]) {
+ ret = pci_request_selected_regions(pdev,
+ 1 << index, "vfio-pci");
+ if (ret)
+ return ret;
+
+ vdev->barmap[index] = pci_iomap(pdev, index, 0);
+ if (!vdev->barmap[index]) {
+ pci_release_selected_regions(pdev, 1 << index);
+ return -ENOMEM;
+ }
+ }
+
+ vma->vm_private_data = vdev;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_pgoff = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff;
+
+ /*
+ * See remap_pfn_range(), called from vfio_pci_fault() but we can't
+ * change vm_flags within the fault handler. Set them now.
+ */
+ vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
+ vma->vm_ops = &vfio_pci_mmap_ops;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_mmap);
+
+void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count)
+{
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
+ struct pci_dev *pdev = vdev->pdev;
+
+ mutex_lock(&vdev->igate);
+
+ if (vdev->req_trigger) {
+ if (!(count % 10))
+ pci_notice_ratelimited(pdev,
+ "Relaying device request to user (#%u)\n",
+ count);
+ eventfd_signal(vdev->req_trigger, 1);
+ } else if (count == 0) {
+ pci_warn(pdev,
+ "No device request channel registered, blocked until released by user\n");
+ }
+
+ mutex_unlock(&vdev->igate);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_request);
+
+static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
+ bool vf_token, uuid_t *uuid)
+{
+ /*
+ * There's always some degree of trust or collaboration between SR-IOV
+ * PF and VFs, even if just that the PF hosts the SR-IOV capability and
+ * can disrupt VFs with a reset, but often the PF has more explicit
+ * access to deny service to the VF or access data passed through the
+ * VF. We therefore require an opt-in via a shared VF token (UUID) to
+ * represent this trust. This both prevents that a VF driver might
+ * assume the PF driver is a trusted, in-kernel driver, and also that
+ * a PF driver might be replaced with a rogue driver, unknown to in-use
+ * VF drivers.
+ *
+ * Therefore when presented with a VF, if the PF is a vfio device and
+ * it is bound to the vfio-pci driver, the user needs to provide a VF
+ * token to access the device, in the form of appending a vf_token to
+ * the device name, for example:
+ *
+ * "0000:04:10.0 vf_token=bd8d9d2b-5a5f-4f5a-a211-f591514ba1f3"
+ *
+ * When presented with a PF which has VFs in use, the user must also
+ * provide the current VF token to prove collaboration with existing
+ * VF users. If VFs are not in use, the VF token provided for the PF
+ * device will act to set the VF token.
+ *
+ * If the VF token is provided but unused, an error is generated.
+ */
+ if (!vdev->pdev->is_virtfn && !vdev->vf_token && !vf_token)
+ return 0; /* No VF token provided or required */
+
+ if (vdev->pdev->is_virtfn) {
+ struct vfio_pci_core_device *pf_vdev = get_pf_vdev(vdev);
+ bool match;
+
+ if (!pf_vdev) {
+ if (!vf_token)
+ return 0; /* PF is not vfio-pci, no VF token */
+
+ pci_info_ratelimited(vdev->pdev,
+ "VF token incorrectly provided, PF not bound to vfio-pci\n");
+ return -EINVAL;
+ }
+
+ if (!vf_token) {
+ vfio_device_put(&pf_vdev->vdev);
+ pci_info_ratelimited(vdev->pdev,
+ "VF token required to access device\n");
+ return -EACCES;
+ }
+
+ mutex_lock(&pf_vdev->vf_token->lock);
+ match = uuid_equal(uuid, &pf_vdev->vf_token->uuid);
+ mutex_unlock(&pf_vdev->vf_token->lock);
+
+ vfio_device_put(&pf_vdev->vdev);
+
+ if (!match) {
+ pci_info_ratelimited(vdev->pdev,
+ "Incorrect VF token provided for device\n");
+ return -EACCES;
+ }
+ } else if (vdev->vf_token) {
+ mutex_lock(&vdev->vf_token->lock);
+ if (vdev->vf_token->users) {
+ if (!vf_token) {
+ mutex_unlock(&vdev->vf_token->lock);
+ pci_info_ratelimited(vdev->pdev,
+ "VF token required to access device\n");
+ return -EACCES;
+ }
+
+ if (!uuid_equal(uuid, &vdev->vf_token->uuid)) {
+ mutex_unlock(&vdev->vf_token->lock);
+ pci_info_ratelimited(vdev->pdev,
+ "Incorrect VF token provided for device\n");
+ return -EACCES;
+ }
+ } else if (vf_token) {
+ uuid_copy(&vdev->vf_token->uuid, uuid);
+ }
+
+ mutex_unlock(&vdev->vf_token->lock);
+ } else if (vf_token) {
+ pci_info_ratelimited(vdev->pdev,
+ "VF token incorrectly provided, not a PF or VF\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define VF_TOKEN_ARG "vf_token="
+
+int vfio_pci_core_match(struct vfio_device *core_vdev, char *buf)
+{
+ struct vfio_pci_core_device *vdev =
+ container_of(core_vdev, struct vfio_pci_core_device, vdev);
+ bool vf_token = false;
+ uuid_t uuid;
+ int ret;
+
+ if (strncmp(pci_name(vdev->pdev), buf, strlen(pci_name(vdev->pdev))))
+ return 0; /* No match */
+
+ if (strlen(buf) > strlen(pci_name(vdev->pdev))) {
+ buf += strlen(pci_name(vdev->pdev));
+
+ if (*buf != ' ')
+ return 0; /* No match: non-whitespace after name */
+
+ while (*buf) {
+ if (*buf == ' ') {
+ buf++;
+ continue;
+ }
+
+ if (!vf_token && !strncmp(buf, VF_TOKEN_ARG,
+ strlen(VF_TOKEN_ARG))) {
+ buf += strlen(VF_TOKEN_ARG);
+
+ if (strlen(buf) < UUID_STRING_LEN)
+ return -EINVAL;
+
+ ret = uuid_parse(buf, &uuid);
+ if (ret)
+ return ret;
+
+ vf_token = true;
+ buf += UUID_STRING_LEN;
+ } else {
+ /* Unknown/duplicate option */
+ return -EINVAL;
+ }
+ }
+ }
+
+ ret = vfio_pci_validate_vf_token(vdev, vf_token, &uuid);
+ if (ret)
+ return ret;
+
+ return 1; /* Match */
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_match);
+
+static int vfio_pci_bus_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct vfio_pci_core_device *vdev = container_of(nb,
+ struct vfio_pci_core_device, nb);
+ struct device *dev = data;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_dev *physfn = pci_physfn(pdev);
+
+ if (action == BUS_NOTIFY_ADD_DEVICE &&
+ pdev->is_virtfn && physfn == vdev->pdev) {
+ pci_info(vdev->pdev, "Captured SR-IOV VF %s driver_override\n",
+ pci_name(pdev));
+ pdev->driver_override = kasprintf(GFP_KERNEL, "%s",
+ vdev->vdev.ops->name);
+ } else if (action == BUS_NOTIFY_BOUND_DRIVER &&
+ pdev->is_virtfn && physfn == vdev->pdev) {
+ struct pci_driver *drv = pci_dev_driver(pdev);
+
+ if (drv && drv != pci_dev_driver(vdev->pdev))
+ pci_warn(vdev->pdev,
+ "VF %s bound to driver %s while PF bound to driver %s\n",
+ pci_name(pdev), drv->name,
+ pci_dev_driver(vdev->pdev)->name);
+ }
+
+ return 0;
+}
+
+static int vfio_pci_vf_init(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ int ret;
+
+ if (!pdev->is_physfn)
+ return 0;
+
+ vdev->vf_token = kzalloc(sizeof(*vdev->vf_token), GFP_KERNEL);
+ if (!vdev->vf_token)
+ return -ENOMEM;
+
+ mutex_init(&vdev->vf_token->lock);
+ uuid_gen(&vdev->vf_token->uuid);
+
+ vdev->nb.notifier_call = vfio_pci_bus_notifier;
+ ret = bus_register_notifier(&pci_bus_type, &vdev->nb);
+ if (ret) {
+ kfree(vdev->vf_token);
+ return ret;
+ }
+ return 0;
+}
+
+static void vfio_pci_vf_uninit(struct vfio_pci_core_device *vdev)
+{
+ if (!vdev->vf_token)
+ return;
+
+ bus_unregister_notifier(&pci_bus_type, &vdev->nb);
+ WARN_ON(vdev->vf_token->users);
+ mutex_destroy(&vdev->vf_token->lock);
+ kfree(vdev->vf_token);
+}
+
+static int vfio_pci_vga_init(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ int ret;
+
+ if (!vfio_pci_is_vga(pdev))
+ return 0;
+
+ ret = vga_client_register(pdev, vfio_pci_set_decode);
+ if (ret)
+ return ret;
+ vga_set_legacy_decoding(pdev, vfio_pci_set_decode(pdev, false));
+ return 0;
+}
+
+static void vfio_pci_vga_uninit(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+
+ if (!vfio_pci_is_vga(pdev))
+ return;
+ vga_client_unregister(pdev);
+ vga_set_legacy_decoding(pdev, VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
+ VGA_RSRC_LEGACY_IO |
+ VGA_RSRC_LEGACY_MEM);
+}
+
+void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
+ struct pci_dev *pdev,
+ const struct vfio_device_ops *vfio_pci_ops)
+{
+ vfio_init_group_dev(&vdev->vdev, &pdev->dev, vfio_pci_ops);
+ vdev->pdev = pdev;
+ vdev->irq_type = VFIO_PCI_NUM_IRQS;
+ mutex_init(&vdev->igate);
+ spin_lock_init(&vdev->irqlock);
+ mutex_init(&vdev->ioeventfds_lock);
+ INIT_LIST_HEAD(&vdev->dummy_resources_list);
+ INIT_LIST_HEAD(&vdev->ioeventfds_list);
+ mutex_init(&vdev->vma_lock);
+ INIT_LIST_HEAD(&vdev->vma_list);
+ init_rwsem(&vdev->memory_lock);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_init_device);
+
+void vfio_pci_core_uninit_device(struct vfio_pci_core_device *vdev)
+{
+ mutex_destroy(&vdev->igate);
+ mutex_destroy(&vdev->ioeventfds_lock);
+ mutex_destroy(&vdev->vma_lock);
+ vfio_uninit_group_dev(&vdev->vdev);
+ kfree(vdev->region);
+ kfree(vdev->pm_save);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_uninit_device);
+
+int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ struct iommu_group *group;
+ int ret;
+
+ if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
+ return -EINVAL;
+
+ /*
+ * Prevent binding to PFs with VFs enabled, the VFs might be in use
+ * by the host or other users. We cannot capture the VFs if they
+ * already exist, nor can we track VF users. Disabling SR-IOV here
+ * would initiate removing the VFs, which would unbind the driver,
+ * which is prone to blocking if that VF is also in use by vfio-pci.
+ * Just reject these PFs and let the user sort it out.
+ */
+ if (pci_num_vf(pdev)) {
+ pci_warn(pdev, "Cannot bind to PF with SR-IOV enabled\n");
+ return -EBUSY;
+ }
+
+ group = vfio_iommu_group_get(&pdev->dev);
+ if (!group)
+ return -EINVAL;
+
+ if (pci_is_root_bus(pdev->bus)) {
+ ret = vfio_assign_device_set(&vdev->vdev, vdev);
+ } else if (!pci_probe_reset_slot(pdev->slot)) {
+ ret = vfio_assign_device_set(&vdev->vdev, pdev->slot);
+ } else {
+ /*
+ * If there is no slot reset support for this device, the whole
+ * bus needs to be grouped together to support bus-wide resets.
+ */
+ ret = vfio_assign_device_set(&vdev->vdev, pdev->bus);
+ }
+
+ if (ret)
+ goto out_group_put;
+ ret = vfio_pci_vf_init(vdev);
+ if (ret)
+ goto out_group_put;
+ ret = vfio_pci_vga_init(vdev);
+ if (ret)
+ goto out_vf;
+
+ vfio_pci_probe_power_state(vdev);
+
+ if (!disable_idle_d3) {
+ /*
+ * pci-core sets the device power state to an unknown value at
+ * bootup and after being removed from a driver. The only
+ * transition it allows from this unknown state is to D0, which
+ * typically happens when a driver calls pci_enable_device().
+ * We're not ready to enable the device yet, but we do want to
+ * be able to get to D3. Therefore first do a D0 transition
+ * before going to D3.
+ */
+ vfio_pci_set_power_state(vdev, PCI_D0);
+ vfio_pci_set_power_state(vdev, PCI_D3hot);
+ }
+
+ ret = vfio_register_group_dev(&vdev->vdev);
+ if (ret)
+ goto out_power;
+ return 0;
+
+out_power:
+ if (!disable_idle_d3)
+ vfio_pci_set_power_state(vdev, PCI_D0);
+out_vf:
+ vfio_pci_vf_uninit(vdev);
+out_group_put:
+ vfio_iommu_group_put(group, &pdev->dev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_register_device);
+
+void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev)
+{
+ struct pci_dev *pdev = vdev->pdev;
+
+ pci_disable_sriov(pdev);
+
+ vfio_unregister_group_dev(&vdev->vdev);
+
+ vfio_pci_vf_uninit(vdev);
+ vfio_pci_vga_uninit(vdev);
+
+ vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
+
+ if (!disable_idle_d3)
+ vfio_pci_set_power_state(vdev, PCI_D0);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_unregister_device);
+
+static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct vfio_pci_core_device *vdev;
+ struct vfio_device *device;
+
+ device = vfio_device_get_from_dev(&pdev->dev);
+ if (device == NULL)
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ vdev = container_of(device, struct vfio_pci_core_device, vdev);
+
+ mutex_lock(&vdev->igate);
+
+ if (vdev->err_trigger)
+ eventfd_signal(vdev->err_trigger, 1);
+
+ mutex_unlock(&vdev->igate);
+
+ vfio_device_put(device);
+
+ return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
+int vfio_pci_core_sriov_configure(struct pci_dev *pdev, int nr_virtfn)
+{
+ struct vfio_device *device;
+ int ret = 0;
+
+ device = vfio_device_get_from_dev(&pdev->dev);
+ if (!device)
+ return -ENODEV;
+
+ if (nr_virtfn == 0)
+ pci_disable_sriov(pdev);
+ else
+ ret = pci_enable_sriov(pdev, nr_virtfn);
+
+ vfio_device_put(device);
+
+ return ret < 0 ? ret : nr_virtfn;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_sriov_configure);
+
+const struct pci_error_handlers vfio_pci_core_err_handlers = {
+ .error_detected = vfio_pci_aer_err_detected,
+};
+EXPORT_SYMBOL_GPL(vfio_pci_core_err_handlers);
+
+static bool vfio_dev_in_groups(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_group_info *groups)
+{
+ unsigned int i;
+
+ for (i = 0; i < groups->count; i++)
+ if (groups->groups[i] == vdev->vdev.group)
+ return true;
+ return false;
+}
+
+static int vfio_pci_is_device_in_set(struct pci_dev *pdev, void *data)
+{
+ struct vfio_device_set *dev_set = data;
+ struct vfio_device *cur;
+
+ list_for_each_entry(cur, &dev_set->device_list, dev_set_list)
+ if (cur->dev == &pdev->dev)
+ return 0;
+ return -EBUSY;
+}
+
+/*
+ * vfio-core considers a group to be viable and will create a vfio_device even
+ * if some devices are bound to drivers like pci-stub or pcieport. Here we
+ * require all PCI devices to be inside our dev_set since that ensures they stay
+ * put and that every driver controlling the device can co-ordinate with the
+ * device reset.
+ *
+ * Returns the pci_dev to pass to pci_reset_bus() if every PCI device to be
+ * reset is inside the dev_set, and pci_reset_bus() can succeed. NULL otherwise.
+ */
+static struct pci_dev *
+vfio_pci_dev_set_resettable(struct vfio_device_set *dev_set)
+{
+ struct pci_dev *pdev;
+
+ lockdep_assert_held(&dev_set->lock);
+
+ /*
+ * By definition all PCI devices in the dev_set share the same PCI
+ * reset, so any pci_dev will have the same outcomes for
+ * pci_probe_reset_*() and pci_reset_bus().
+ */
+ pdev = list_first_entry(&dev_set->device_list,
+ struct vfio_pci_core_device,
+ vdev.dev_set_list)->pdev;
+
+ /* pci_reset_bus() is supported */
+ if (pci_probe_reset_slot(pdev->slot) && pci_probe_reset_bus(pdev->bus))
+ return NULL;
+
+ if (vfio_pci_for_each_slot_or_bus(pdev, vfio_pci_is_device_in_set,
+ dev_set,
+ !pci_probe_reset_slot(pdev->slot)))
+ return NULL;
+ return pdev;
+}
+
+/*
+ * We need to get memory_lock for each device, but devices can share mmap_lock,
+ * therefore we need to zap and hold the vma_lock for each device, and only then
+ * get each memory_lock.
+ */
+static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
+ struct vfio_pci_group_info *groups)
+{
+ struct vfio_pci_core_device *cur_mem;
+ struct vfio_pci_core_device *cur_vma;
+ struct vfio_pci_core_device *cur;
+ struct pci_dev *pdev;
+ bool is_mem = true;
+ int ret;
+
+ mutex_lock(&dev_set->lock);
+ cur_mem = list_first_entry(&dev_set->device_list,
+ struct vfio_pci_core_device,
+ vdev.dev_set_list);
+
+ pdev = vfio_pci_dev_set_resettable(dev_set);
+ if (!pdev) {
+ ret = -EINVAL;
+ goto err_unlock;
+ }
+
+ list_for_each_entry(cur_vma, &dev_set->device_list, vdev.dev_set_list) {
+ /*
+ * Test whether all the affected devices are contained by the
+ * set of groups provided by the user.
+ */
+ if (!vfio_dev_in_groups(cur_vma, groups)) {
+ ret = -EINVAL;
+ goto err_undo;
+ }
+
+ /*
+ * Locking multiple devices is prone to deadlock, runaway and
+ * unwind if we hit contention.
+ */
+ if (!vfio_pci_zap_and_vma_lock(cur_vma, true)) {
+ ret = -EBUSY;
+ goto err_undo;
+ }
+ }
+ cur_vma = NULL;
+
+ list_for_each_entry(cur_mem, &dev_set->device_list, vdev.dev_set_list) {
+ if (!down_write_trylock(&cur_mem->memory_lock)) {
+ ret = -EBUSY;
+ goto err_undo;
+ }
+ mutex_unlock(&cur_mem->vma_lock);
+ }
+ cur_mem = NULL;
+
+ ret = pci_reset_bus(pdev);
+
+err_undo:
+ list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) {
+ if (cur == cur_mem)
+ is_mem = false;
+ if (cur == cur_vma)
+ break;
+ if (is_mem)
+ up_write(&cur->memory_lock);
+ else
+ mutex_unlock(&cur->vma_lock);
+ }
+err_unlock:
+ mutex_unlock(&dev_set->lock);
+ return ret;
+}
+
+static bool vfio_pci_dev_set_needs_reset(struct vfio_device_set *dev_set)
+{
+ struct vfio_pci_core_device *cur;
+ bool needs_reset = false;
+
+ list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) {
+ /* No VFIO device in the set can have an open device FD */
+ if (cur->vdev.open_count)
+ return false;
+ needs_reset |= cur->needs_reset;
+ }
+ return needs_reset;
+}
+
+/*
+ * If a bus or slot reset is available for the provided dev_set and:
+ * - All of the devices affected by that bus or slot reset are unused
+ * - At least one of the affected devices is marked dirty via
+ * needs_reset (such as by lack of FLR support)
+ * Then attempt to perform that bus or slot reset.
+ * Returns true if the dev_set was reset.
+ */
+static bool vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
+{
+ struct vfio_pci_core_device *cur;
+ struct pci_dev *pdev;
+ int ret;
+
+ if (!vfio_pci_dev_set_needs_reset(dev_set))
+ return false;
+
+ pdev = vfio_pci_dev_set_resettable(dev_set);
+ if (!pdev)
+ return false;
+
+ ret = pci_reset_bus(pdev);
+ if (ret)
+ return false;
+
+ list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) {
+ cur->needs_reset = false;
+ if (!disable_idle_d3)
+ vfio_pci_set_power_state(cur, PCI_D3hot);
+ }
+ return true;
+}
+
+void vfio_pci_core_set_params(bool is_nointxmask, bool is_disable_vga,
+ bool is_disable_idle_d3)
+{
+ nointxmask = is_nointxmask;
+ disable_vga = is_disable_vga;
+ disable_idle_d3 = is_disable_idle_d3;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_set_params);
+
+static void vfio_pci_core_cleanup(void)
+{
+ vfio_pci_uninit_perm_bits();
+}
+
+static int __init vfio_pci_core_init(void)
+{
+ /* Allocate shared config space permission data used by all devices */
+ return vfio_pci_init_perm_bits();
+}
+
+module_init(vfio_pci_core_init);
+module_exit(vfio_pci_core_cleanup);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/vfio/pci/vfio_pci_igd.c b/drivers/vfio/pci/vfio_pci_igd.c
index 228df565e9bc..7ca4109bba48 100644
--- a/drivers/vfio/pci/vfio_pci_igd.c
+++ b/drivers/vfio/pci/vfio_pci_igd.c
@@ -15,7 +15,7 @@
#include <linux/uaccess.h>
#include <linux/vfio.h>
-#include "vfio_pci_private.h"
+#include <linux/vfio_pci_core.h>
#define OPREGION_SIGNATURE "IntelGraphicsMem"
#define OPREGION_SIZE (8 * 1024)
@@ -25,8 +25,9 @@
#define OPREGION_RVDS 0x3c2
#define OPREGION_VERSION 0x16
-static size_t vfio_pci_igd_rw(struct vfio_pci_device *vdev, char __user *buf,
- size_t count, loff_t *ppos, bool iswrite)
+static ssize_t vfio_pci_igd_rw(struct vfio_pci_core_device *vdev,
+ char __user *buf, size_t count, loff_t *ppos,
+ bool iswrite)
{
unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - VFIO_PCI_NUM_REGIONS;
void *base = vdev->region[i].data;
@@ -45,7 +46,7 @@ static size_t vfio_pci_igd_rw(struct vfio_pci_device *vdev, char __user *buf,
return count;
}
-static void vfio_pci_igd_release(struct vfio_pci_device *vdev,
+static void vfio_pci_igd_release(struct vfio_pci_core_device *vdev,
struct vfio_pci_region *region)
{
memunmap(region->data);
@@ -56,7 +57,7 @@ static const struct vfio_pci_regops vfio_pci_igd_regops = {
.release = vfio_pci_igd_release,
};
-static int vfio_pci_igd_opregion_init(struct vfio_pci_device *vdev)
+static int vfio_pci_igd_opregion_init(struct vfio_pci_core_device *vdev)
{
__le32 *dwordp = (__le32 *)(vdev->vconfig + OPREGION_PCI_ADDR);
u32 addr, size;
@@ -160,9 +161,9 @@ static int vfio_pci_igd_opregion_init(struct vfio_pci_device *vdev)
return ret;
}
-static size_t vfio_pci_igd_cfg_rw(struct vfio_pci_device *vdev,
- char __user *buf, size_t count, loff_t *ppos,
- bool iswrite)
+static ssize_t vfio_pci_igd_cfg_rw(struct vfio_pci_core_device *vdev,
+ char __user *buf, size_t count, loff_t *ppos,
+ bool iswrite)
{
unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - VFIO_PCI_NUM_REGIONS;
struct pci_dev *pdev = vdev->region[i].data;
@@ -253,7 +254,7 @@ static size_t vfio_pci_igd_cfg_rw(struct vfio_pci_device *vdev,
return count;
}
-static void vfio_pci_igd_cfg_release(struct vfio_pci_device *vdev,
+static void vfio_pci_igd_cfg_release(struct vfio_pci_core_device *vdev,
struct vfio_pci_region *region)
{
struct pci_dev *pdev = region->data;
@@ -266,7 +267,7 @@ static const struct vfio_pci_regops vfio_pci_igd_cfg_regops = {
.release = vfio_pci_igd_cfg_release,
};
-static int vfio_pci_igd_cfg_init(struct vfio_pci_device *vdev)
+static int vfio_pci_igd_cfg_init(struct vfio_pci_core_device *vdev)
{
struct pci_dev *host_bridge, *lpc_bridge;
int ret;
@@ -314,7 +315,7 @@ static int vfio_pci_igd_cfg_init(struct vfio_pci_device *vdev)
return 0;
}
-int vfio_pci_igd_init(struct vfio_pci_device *vdev)
+int vfio_pci_igd_init(struct vfio_pci_core_device *vdev)
{
int ret;
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 869dce5f134d..6069a11fb51a 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -20,20 +20,20 @@
#include <linux/wait.h>
#include <linux/slab.h>
-#include "vfio_pci_private.h"
+#include <linux/vfio_pci_core.h>
/*
* INTx
*/
static void vfio_send_intx_eventfd(void *opaque, void *unused)
{
- struct vfio_pci_device *vdev = opaque;
+ struct vfio_pci_core_device *vdev = opaque;
if (likely(is_intx(vdev) && !vdev->virq_disabled))
eventfd_signal(vdev->ctx[0].trigger, 1);
}
-void vfio_pci_intx_mask(struct vfio_pci_device *vdev)
+void vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
unsigned long flags;
@@ -73,7 +73,7 @@ void vfio_pci_intx_mask(struct vfio_pci_device *vdev)
*/
static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
{
- struct vfio_pci_device *vdev = opaque;
+ struct vfio_pci_core_device *vdev = opaque;
struct pci_dev *pdev = vdev->pdev;
unsigned long flags;
int ret = 0;
@@ -107,7 +107,7 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
return ret;
}
-void vfio_pci_intx_unmask(struct vfio_pci_device *vdev)
+void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
{
if (vfio_pci_intx_unmask_handler(vdev, NULL) > 0)
vfio_send_intx_eventfd(vdev, NULL);
@@ -115,7 +115,7 @@ void vfio_pci_intx_unmask(struct vfio_pci_device *vdev)
static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
{
- struct vfio_pci_device *vdev = dev_id;
+ struct vfio_pci_core_device *vdev = dev_id;
unsigned long flags;
int ret = IRQ_NONE;
@@ -139,7 +139,7 @@ static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
return ret;
}
-static int vfio_intx_enable(struct vfio_pci_device *vdev)
+static int vfio_intx_enable(struct vfio_pci_core_device *vdev)
{
if (!is_irq_none(vdev))
return -EINVAL;
@@ -168,7 +168,7 @@ static int vfio_intx_enable(struct vfio_pci_device *vdev)
return 0;
}
-static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
+static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd)
{
struct pci_dev *pdev = vdev->pdev;
unsigned long irqflags = IRQF_SHARED;
@@ -223,7 +223,7 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
return 0;
}
-static void vfio_intx_disable(struct vfio_pci_device *vdev)
+static void vfio_intx_disable(struct vfio_pci_core_device *vdev)
{
vfio_virqfd_disable(&vdev->ctx[0].unmask);
vfio_virqfd_disable(&vdev->ctx[0].mask);
@@ -244,7 +244,7 @@ static irqreturn_t vfio_msihandler(int irq, void *arg)
return IRQ_HANDLED;
}
-static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
+static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msix)
{
struct pci_dev *pdev = vdev->pdev;
unsigned int flag = msix ? PCI_IRQ_MSIX : PCI_IRQ_MSI;
@@ -285,7 +285,7 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
return 0;
}
-static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
+static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
int vector, int fd, bool msix)
{
struct pci_dev *pdev = vdev->pdev;
@@ -364,7 +364,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
return 0;
}
-static int vfio_msi_set_block(struct vfio_pci_device *vdev, unsigned start,
+static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start,
unsigned count, int32_t *fds, bool msix)
{
int i, j, ret = 0;
@@ -385,7 +385,7 @@ static int vfio_msi_set_block(struct vfio_pci_device *vdev, unsigned start,
return ret;
}
-static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
+static void vfio_msi_disable(struct vfio_pci_core_device *vdev, bool msix)
{
struct pci_dev *pdev = vdev->pdev;
int i;
@@ -417,7 +417,7 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
/*
* IOCTL support
*/
-static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
+static int vfio_pci_set_intx_unmask(struct vfio_pci_core_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
@@ -444,7 +444,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
return 0;
}
-static int vfio_pci_set_intx_mask(struct vfio_pci_device *vdev,
+static int vfio_pci_set_intx_mask(struct vfio_pci_core_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
@@ -464,7 +464,7 @@ static int vfio_pci_set_intx_mask(struct vfio_pci_device *vdev,
return 0;
}
-static int vfio_pci_set_intx_trigger(struct vfio_pci_device *vdev,
+static int vfio_pci_set_intx_trigger(struct vfio_pci_core_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
@@ -507,7 +507,7 @@ static int vfio_pci_set_intx_trigger(struct vfio_pci_device *vdev,
return 0;
}
-static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
+static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
@@ -613,7 +613,7 @@ static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx,
return -EINVAL;
}
-static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
+static int vfio_pci_set_err_trigger(struct vfio_pci_core_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
@@ -624,7 +624,7 @@ static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
count, flags, data);
}
-static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
+static int vfio_pci_set_req_trigger(struct vfio_pci_core_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
@@ -635,11 +635,11 @@ static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
count, flags, data);
}
-int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
+int vfio_pci_set_irqs_ioctl(struct vfio_pci_core_device *vdev, uint32_t flags,
unsigned index, unsigned start, unsigned count,
void *data)
{
- int (*func)(struct vfio_pci_device *vdev, unsigned index,
+ int (*func)(struct vfio_pci_core_device *vdev, unsigned index,
unsigned start, unsigned count, uint32_t flags,
void *data) = NULL;
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
index a0b5fc8e46f4..57d3b2cbbd8e 100644
--- a/drivers/vfio/pci/vfio_pci_rdwr.c
+++ b/drivers/vfio/pci/vfio_pci_rdwr.c
@@ -17,7 +17,7 @@
#include <linux/vfio.h>
#include <linux/vgaarb.h>
-#include "vfio_pci_private.h"
+#include <linux/vfio_pci_core.h>
#ifdef __LITTLE_ENDIAN
#define vfio_ioread64 ioread64
@@ -38,7 +38,7 @@
#define vfio_iowrite8 iowrite8
#define VFIO_IOWRITE(size) \
-static int vfio_pci_iowrite##size(struct vfio_pci_device *vdev, \
+static int vfio_pci_iowrite##size(struct vfio_pci_core_device *vdev, \
bool test_mem, u##size val, void __iomem *io) \
{ \
if (test_mem) { \
@@ -65,7 +65,7 @@ VFIO_IOWRITE(64)
#endif
#define VFIO_IOREAD(size) \
-static int vfio_pci_ioread##size(struct vfio_pci_device *vdev, \
+static int vfio_pci_ioread##size(struct vfio_pci_core_device *vdev, \
bool test_mem, u##size *val, void __iomem *io) \
{ \
if (test_mem) { \
@@ -94,7 +94,7 @@ VFIO_IOREAD(32)
* reads with -1. This is intended for handling MSI-X vector tables and
* leftover space for ROM BARs.
*/
-static ssize_t do_io_rw(struct vfio_pci_device *vdev, bool test_mem,
+static ssize_t do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
void __iomem *io, char __user *buf,
loff_t off, size_t count, size_t x_start,
size_t x_end, bool iswrite)
@@ -200,7 +200,7 @@ static ssize_t do_io_rw(struct vfio_pci_device *vdev, bool test_mem,
return done;
}
-static int vfio_pci_setup_barmap(struct vfio_pci_device *vdev, int bar)
+static int vfio_pci_setup_barmap(struct vfio_pci_core_device *vdev, int bar)
{
struct pci_dev *pdev = vdev->pdev;
int ret;
@@ -224,7 +224,7 @@ static int vfio_pci_setup_barmap(struct vfio_pci_device *vdev, int bar)
return 0;
}
-ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
+ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
size_t count, loff_t *ppos, bool iswrite)
{
struct pci_dev *pdev = vdev->pdev;
@@ -288,7 +288,7 @@ out:
return done;
}
-ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
+ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
size_t count, loff_t *ppos, bool iswrite)
{
int ret;
@@ -384,7 +384,7 @@ static void vfio_pci_ioeventfd_do_write(struct vfio_pci_ioeventfd *ioeventfd,
static int vfio_pci_ioeventfd_handler(void *opaque, void *unused)
{
struct vfio_pci_ioeventfd *ioeventfd = opaque;
- struct vfio_pci_device *vdev = ioeventfd->vdev;
+ struct vfio_pci_core_device *vdev = ioeventfd->vdev;
if (ioeventfd->test_mem) {
if (!down_read_trylock(&vdev->memory_lock))
@@ -410,7 +410,7 @@ static void vfio_pci_ioeventfd_thread(void *opaque, void *unused)
vfio_pci_ioeventfd_do_write(ioeventfd, ioeventfd->test_mem);
}
-long vfio_pci_ioeventfd(struct vfio_pci_device *vdev, loff_t offset,
+long vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
uint64_t data, int count, int fd)
{
struct pci_dev *pdev = vdev->pdev;
diff --git a/drivers/vfio/pci/vfio_pci_zdev.c b/drivers/vfio/pci/vfio_pci_zdev.c
index 7b011b62c766..ea4c0d2b0663 100644
--- a/drivers/vfio/pci/vfio_pci_zdev.c
+++ b/drivers/vfio/pci/vfio_pci_zdev.c
@@ -1,15 +1,10 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
/*
* VFIO ZPCI devices support
*
* Copyright (C) IBM Corp. 2020. All rights reserved.
* Author(s): Pierre Morel <pmorel@linux.ibm.com>
* Matthew Rosato <mjrosato@linux.ibm.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>
#include <linux/pci.h>
@@ -19,7 +14,7 @@
#include <asm/pci_clp.h>
#include <asm/pci_io.h>
-#include "vfio_pci_private.h"
+#include <linux/vfio_pci_core.h>
/*
* Add the Base PCI Function information to the device info region.
@@ -114,7 +109,7 @@ static int zpci_pfip_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
/*
* Add all supported capabilities to the VFIO_DEVICE_GET_INFO capability chain.
*/
-int vfio_pci_info_zdev_add_caps(struct vfio_pci_device *vdev,
+int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
struct vfio_info_cap *caps)
{
struct zpci_dev *zdev = to_zpci(vdev->pdev);
diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
index ab341108a0be..331a5920f5ab 100644
--- a/drivers/vfio/platform/Kconfig
+++ b/drivers/vfio/platform/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config VFIO_PLATFORM
tristate "VFIO support for platform devices"
- depends on VFIO && EVENTFD && (ARM || ARM64 || COMPILE_TEST)
+ depends on ARM || ARM64 || COMPILE_TEST
select VFIO_VIRQFD
help
Support for platform devices with VFIO. This is required to make
@@ -10,9 +10,10 @@ config VFIO_PLATFORM
If you don't know what to do here, say N.
+if VFIO_PLATFORM
config VFIO_AMBA
tristate "VFIO support for AMBA devices"
- depends on VFIO_PLATFORM && (ARM_AMBA || COMPILE_TEST)
+ depends on ARM_AMBA || COMPILE_TEST
help
Support for ARM AMBA devices with VFIO. This is required to make
use of ARM AMBA devices present on the system using the VFIO
@@ -21,3 +22,4 @@ config VFIO_AMBA
If you don't know what to do here, say N.
source "drivers/vfio/platform/reset/Kconfig"
+endif
diff --git a/drivers/vfio/platform/reset/Kconfig b/drivers/vfio/platform/reset/Kconfig
index 1edbe9ee7356..12f5f3d80387 100644
--- a/drivers/vfio/platform/reset/Kconfig
+++ b/drivers/vfio/platform/reset/Kconfig
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config VFIO_PLATFORM_CALXEDAXGMAC_RESET
tristate "VFIO support for calxeda xgmac reset"
- depends on VFIO_PLATFORM
help
Enables the VFIO platform driver to handle reset for Calxeda xgmac
@@ -9,7 +8,6 @@ config VFIO_PLATFORM_CALXEDAXGMAC_RESET
config VFIO_PLATFORM_AMDXGBE_RESET
tristate "VFIO support for AMD XGBE reset"
- depends on VFIO_PLATFORM
help
Enables the VFIO platform driver to handle reset for AMD XGBE
@@ -17,7 +15,7 @@ config VFIO_PLATFORM_AMDXGBE_RESET
config VFIO_PLATFORM_BCMFLEXRM_RESET
tristate "VFIO support for Broadcom FlexRM reset"
- depends on VFIO_PLATFORM && (ARCH_BCM_IPROC || COMPILE_TEST)
+ depends on ARCH_BCM_IPROC || COMPILE_TEST
default ARCH_BCM_IPROC
help
Enables the VFIO platform driver to handle reset for Broadcom FlexRM
diff --git a/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c b/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c
index 96064ef8f629..1131ebe4837d 100644
--- a/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c
+++ b/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2017 Broadcom
- *
- * This program is free software; 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.
*/
/*
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 703164df7637..6af7ce7d619c 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -218,65 +218,52 @@ static int vfio_platform_call_reset(struct vfio_platform_device *vdev,
return -EINVAL;
}
-static void vfio_platform_release(struct vfio_device *core_vdev)
+static void vfio_platform_close_device(struct vfio_device *core_vdev)
{
struct vfio_platform_device *vdev =
container_of(core_vdev, struct vfio_platform_device, vdev);
+ const char *extra_dbg = NULL;
+ int ret;
- mutex_lock(&driver_lock);
-
- if (!(--vdev->refcnt)) {
- const char *extra_dbg = NULL;
- int ret;
-
- 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 release (%d) %s\n",
- ret, extra_dbg ? extra_dbg : "");
- WARN_ON(1);
- }
- pm_runtime_put(vdev->device);
- vfio_platform_regions_cleanup(vdev);
- vfio_platform_irq_cleanup(vdev);
+ ret = vfio_platform_call_reset(vdev, &extra_dbg);
+ if (WARN_ON(ret && vdev->reset_required)) {
+ dev_warn(
+ vdev->device,
+ "reset driver is required and reset call failed in release (%d) %s\n",
+ ret, extra_dbg ? extra_dbg : "");
}
-
- mutex_unlock(&driver_lock);
+ pm_runtime_put(vdev->device);
+ vfio_platform_regions_cleanup(vdev);
+ vfio_platform_irq_cleanup(vdev);
}
-static int vfio_platform_open(struct vfio_device *core_vdev)
+static int vfio_platform_open_device(struct vfio_device *core_vdev)
{
struct vfio_platform_device *vdev =
container_of(core_vdev, struct vfio_platform_device, vdev);
+ const char *extra_dbg = NULL;
int ret;
- mutex_lock(&driver_lock);
-
- if (!vdev->refcnt) {
- const char *extra_dbg = NULL;
-
- ret = vfio_platform_regions_init(vdev);
- if (ret)
- goto err_reg;
+ ret = vfio_platform_regions_init(vdev);
+ if (ret)
+ return ret;
- ret = vfio_platform_irq_init(vdev);
- if (ret)
- goto err_irq;
+ ret = vfio_platform_irq_init(vdev);
+ if (ret)
+ goto err_irq;
- ret = pm_runtime_get_sync(vdev->device);
- if (ret < 0)
- goto err_rst;
+ ret = pm_runtime_get_sync(vdev->device);
+ if (ret < 0)
+ goto err_rst;
- 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",
- ret, extra_dbg ? extra_dbg : "");
- goto err_rst;
- }
+ 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",
+ ret, extra_dbg ? extra_dbg : "");
+ goto err_rst;
}
-
- vdev->refcnt++;
-
- mutex_unlock(&driver_lock);
return 0;
err_rst:
@@ -284,8 +271,6 @@ err_rst:
vfio_platform_irq_cleanup(vdev);
err_irq:
vfio_platform_regions_cleanup(vdev);
-err_reg:
- mutex_unlock(&driver_lock);
return ret;
}
@@ -616,8 +601,8 @@ static int vfio_platform_mmap(struct vfio_device *core_vdev, struct vm_area_stru
static const struct vfio_device_ops vfio_platform_ops = {
.name = "vfio-platform",
- .open = vfio_platform_open,
- .release = vfio_platform_release,
+ .open_device = vfio_platform_open_device,
+ .close_device = vfio_platform_close_device,
.ioctl = vfio_platform_ioctl,
.read = vfio_platform_read,
.write = vfio_platform_write,
@@ -667,7 +652,7 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
ret = vfio_platform_of_probe(vdev, dev);
if (ret)
- return ret;
+ goto out_uninit;
vdev->device = dev;
@@ -675,7 +660,7 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
if (ret && vdev->reset_required) {
dev_err(dev, "No reset function found for device %s\n",
vdev->name);
- return ret;
+ goto out_uninit;
}
group = vfio_iommu_group_get(dev);
@@ -698,6 +683,8 @@ put_iommu:
vfio_iommu_group_put(group, dev);
put_reset:
vfio_platform_put_reset(vdev);
+out_uninit:
+ vfio_uninit_group_dev(&vdev->vdev);
return ret;
}
EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
@@ -708,6 +695,7 @@ void vfio_platform_remove_common(struct vfio_platform_device *vdev)
pm_runtime_disable(vdev->device);
vfio_platform_put_reset(vdev);
+ vfio_uninit_group_dev(&vdev->vdev);
vfio_iommu_group_put(vdev->vdev.dev->iommu_group, vdev->vdev.dev);
}
EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index dfb834c13659..520d2a8e8375 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -48,7 +48,6 @@ struct vfio_platform_device {
u32 num_regions;
struct vfio_platform_irq *irqs;
u32 num_irqs;
- int refcnt;
struct mutex igate;
const char *compat;
const char *acpihid;
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 02cc51ce6891..3c034fe14ccb 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -96,6 +96,79 @@ module_param_named(enable_unsafe_noiommu_mode,
MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel. If you do not know what this is for, step away. (default: false)");
#endif
+static DEFINE_XARRAY(vfio_device_set_xa);
+
+int vfio_assign_device_set(struct vfio_device *device, void *set_id)
+{
+ unsigned long idx = (unsigned long)set_id;
+ struct vfio_device_set *new_dev_set;
+ struct vfio_device_set *dev_set;
+
+ if (WARN_ON(!set_id))
+ return -EINVAL;
+
+ /*
+ * Atomically acquire a singleton object in the xarray for this set_id
+ */
+ xa_lock(&vfio_device_set_xa);
+ dev_set = xa_load(&vfio_device_set_xa, idx);
+ if (dev_set)
+ goto found_get_ref;
+ xa_unlock(&vfio_device_set_xa);
+
+ new_dev_set = kzalloc(sizeof(*new_dev_set), GFP_KERNEL);
+ if (!new_dev_set)
+ return -ENOMEM;
+ mutex_init(&new_dev_set->lock);
+ INIT_LIST_HEAD(&new_dev_set->device_list);
+ new_dev_set->set_id = set_id;
+
+ xa_lock(&vfio_device_set_xa);
+ dev_set = __xa_cmpxchg(&vfio_device_set_xa, idx, NULL, new_dev_set,
+ GFP_KERNEL);
+ if (!dev_set) {
+ dev_set = new_dev_set;
+ goto found_get_ref;
+ }
+
+ kfree(new_dev_set);
+ if (xa_is_err(dev_set)) {
+ xa_unlock(&vfio_device_set_xa);
+ return xa_err(dev_set);
+ }
+
+found_get_ref:
+ dev_set->device_count++;
+ xa_unlock(&vfio_device_set_xa);
+ mutex_lock(&dev_set->lock);
+ device->dev_set = dev_set;
+ list_add_tail(&device->dev_set_list, &dev_set->device_list);
+ mutex_unlock(&dev_set->lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_assign_device_set);
+
+static void vfio_release_device_set(struct vfio_device *device)
+{
+ struct vfio_device_set *dev_set = device->dev_set;
+
+ if (!dev_set)
+ return;
+
+ mutex_lock(&dev_set->lock);
+ list_del(&device->dev_set_list);
+ mutex_unlock(&dev_set->lock);
+
+ xa_lock(&vfio_device_set_xa);
+ if (!--dev_set->device_count) {
+ __xa_erase(&vfio_device_set_xa,
+ (unsigned long)dev_set->set_id);
+ mutex_destroy(&dev_set->lock);
+ kfree(dev_set);
+ }
+ xa_unlock(&vfio_device_set_xa);
+}
+
/*
* vfio_iommu_group_{get,put} are only intended for VFIO bus driver probe
* and remove functions, any use cases other than acquiring the first
@@ -749,12 +822,25 @@ void vfio_init_group_dev(struct vfio_device *device, struct device *dev,
}
EXPORT_SYMBOL_GPL(vfio_init_group_dev);
+void vfio_uninit_group_dev(struct vfio_device *device)
+{
+ vfio_release_device_set(device);
+}
+EXPORT_SYMBOL_GPL(vfio_uninit_group_dev);
+
int vfio_register_group_dev(struct vfio_device *device)
{
struct vfio_device *existing_device;
struct iommu_group *iommu_group;
struct vfio_group *group;
+ /*
+ * If the driver doesn't specify a set then the device is added to a
+ * singleton set just for itself.
+ */
+ if (!device->dev_set)
+ vfio_assign_device_set(device, device);
+
iommu_group = iommu_group_get(device->dev);
if (!iommu_group)
return -EINVAL;
@@ -1356,7 +1442,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
{
struct vfio_device *device;
struct file *filep;
- int ret;
+ int fdno;
+ int ret = 0;
if (0 == atomic_read(&group->container_users) ||
!group->container->iommu_driver || !vfio_group_viable(group))
@@ -1370,38 +1457,32 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
return PTR_ERR(device);
if (!try_module_get(device->dev->driver->owner)) {
- vfio_device_put(device);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_device_put;
}
- ret = device->ops->open(device);
- if (ret) {
- module_put(device->dev->driver->owner);
- vfio_device_put(device);
- return ret;
+ mutex_lock(&device->dev_set->lock);
+ device->open_count++;
+ if (device->open_count == 1 && device->ops->open_device) {
+ ret = device->ops->open_device(device);
+ if (ret)
+ goto err_undo_count;
}
+ mutex_unlock(&device->dev_set->lock);
/*
* We can't use anon_inode_getfd() because we need to modify
* the f_mode flags directly to allow more than just ioctls
*/
- ret = get_unused_fd_flags(O_CLOEXEC);
- if (ret < 0) {
- device->ops->release(device);
- module_put(device->dev->driver->owner);
- vfio_device_put(device);
- return ret;
- }
+ fdno = ret = get_unused_fd_flags(O_CLOEXEC);
+ if (ret < 0)
+ goto err_close_device;
filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops,
device, O_RDWR);
if (IS_ERR(filep)) {
- put_unused_fd(ret);
ret = PTR_ERR(filep);
- device->ops->release(device);
- module_put(device->dev->driver->owner);
- vfio_device_put(device);
- return ret;
+ goto err_fd;
}
/*
@@ -1413,12 +1494,25 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
atomic_inc(&group->container_users);
- fd_install(ret, filep);
+ fd_install(fdno, filep);
if (group->noiommu)
dev_warn(device->dev, "vfio-noiommu device opened by user "
"(%s:%d)\n", current->comm, task_pid_nr(current));
-
+ return fdno;
+
+err_fd:
+ put_unused_fd(fdno);
+err_close_device:
+ mutex_lock(&device->dev_set->lock);
+ if (device->open_count == 1 && device->ops->close_device)
+ device->ops->close_device(device);
+err_undo_count:
+ device->open_count--;
+ mutex_unlock(&device->dev_set->lock);
+ module_put(device->dev->driver->owner);
+err_device_put:
+ vfio_device_put(device);
return ret;
}
@@ -1556,7 +1650,10 @@ static int vfio_device_fops_release(struct inode *inode, struct file *filep)
{
struct vfio_device *device = filep->private_data;
- device->ops->release(device);
+ mutex_lock(&device->dev_set->lock);
+ if (!--device->open_count && device->ops->close_device)
+ device->ops->close_device(device);
+ mutex_unlock(&device->dev_set->lock);
module_put(device->dev->driver->owner);
@@ -2359,6 +2456,7 @@ static void __exit vfio_cleanup(void)
class_destroy(vfio.class);
vfio.class = NULL;
misc_deregister(&vfio_dev);
+ xa_destroy(&vfio_device_set_xa);
}
module_init(vfio_init);
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 0b4f7c174c7a..0e9217687f5c 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -612,17 +612,17 @@ static int vfio_wait(struct vfio_iommu *iommu)
static int vfio_find_dma_valid(struct vfio_iommu *iommu, dma_addr_t start,
size_t size, struct vfio_dma **dma_p)
{
- int ret;
+ int ret = 0;
do {
*dma_p = vfio_find_dma(iommu, start, size);
if (!*dma_p)
- ret = -EINVAL;
+ return -EINVAL;
else if (!(*dma_p)->vaddr_invalid)
- ret = 0;
+ return ret;
else
ret = vfio_wait(iommu);
- } while (ret > 0);
+ } while (ret == WAITED);
return ret;
}
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 3a249ee7e144..28ef323882fb 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -467,7 +467,7 @@ static void vhost_tx_batch(struct vhost_net *net,
.num = nvq->batched_xdp,
.ptr = nvq->xdp,
};
- int err;
+ int i, err;
if (nvq->batched_xdp == 0)
goto signal_used;
@@ -476,6 +476,15 @@ static void vhost_tx_batch(struct vhost_net *net,
err = sock->ops->sendmsg(sock, msghdr, 0);
if (unlikely(err < 0)) {
vq_err(&nvq->vq, "Fail to batch sending packets\n");
+
+ /* free pages owned by XDP; since this is an unlikely error path,
+ * keep it simple and avoid more complex bulk update for the
+ * used pages
+ */
+ for (i = 0; i < nvq->batched_xdp; ++i)
+ put_page(virt_to_head_page(nvq->xdp[i].data));
+ nvq->batched_xdp = 0;
+ nvq->done_idx = 0;
return;
}
diff --git a/drivers/video/backlight/ktd253-backlight.c b/drivers/video/backlight/ktd253-backlight.c
index a7df5bcca9da..37aa5a669530 100644
--- a/drivers/video/backlight/ktd253-backlight.c
+++ b/drivers/video/backlight/ktd253-backlight.c
@@ -25,6 +25,7 @@
#define KTD253_T_LOW_NS (200 + 10) /* Additional 10ns as safety factor */
#define KTD253_T_HIGH_NS (200 + 10) /* Additional 10ns as safety factor */
+#define KTD253_T_OFF_CRIT_NS 100000 /* 100 us, now it doesn't look good */
#define KTD253_T_OFF_MS 3
struct ktd253_backlight {
@@ -34,13 +35,50 @@ struct ktd253_backlight {
u16 ratio;
};
+static void ktd253_backlight_set_max_ratio(struct ktd253_backlight *ktd253)
+{
+ gpiod_set_value_cansleep(ktd253->gpiod, 1);
+ ndelay(KTD253_T_HIGH_NS);
+ /* We always fall back to this when we power on */
+}
+
+static int ktd253_backlight_stepdown(struct ktd253_backlight *ktd253)
+{
+ /*
+ * These GPIO operations absolutely can NOT sleep so no _cansleep
+ * suffixes, and no using GPIO expanders on slow buses for this!
+ *
+ * The maximum number of cycles of the loop is 32 so the time taken
+ * should nominally be:
+ * (T_LOW_NS + T_HIGH_NS + loop_time) * 32
+ *
+ * Architectures do not always support ndelay() and we will get a few us
+ * instead. If we get to a critical time limit an interrupt has likely
+ * occured in the low part of the loop and we need to restart from the
+ * top so we have the backlight in a known state.
+ */
+ u64 ns;
+
+ ns = ktime_get_ns();
+ gpiod_set_value(ktd253->gpiod, 0);
+ ndelay(KTD253_T_LOW_NS);
+ gpiod_set_value(ktd253->gpiod, 1);
+ ns = ktime_get_ns() - ns;
+ if (ns >= KTD253_T_OFF_CRIT_NS) {
+ dev_err(ktd253->dev, "PCM on backlight took too long (%llu ns)\n", ns);
+ return -EAGAIN;
+ }
+ ndelay(KTD253_T_HIGH_NS);
+ return 0;
+}
+
static int ktd253_backlight_update_status(struct backlight_device *bl)
{
struct ktd253_backlight *ktd253 = bl_get_data(bl);
int brightness = backlight_get_brightness(bl);
u16 target_ratio;
u16 current_ratio = ktd253->ratio;
- unsigned long flags;
+ int ret;
dev_dbg(ktd253->dev, "new brightness/ratio: %d/32\n", brightness);
@@ -62,37 +100,34 @@ static int ktd253_backlight_update_status(struct backlight_device *bl)
}
if (current_ratio == 0) {
- gpiod_set_value_cansleep(ktd253->gpiod, 1);
- ndelay(KTD253_T_HIGH_NS);
- /* We always fall back to this when we power on */
+ ktd253_backlight_set_max_ratio(ktd253);
current_ratio = KTD253_MAX_RATIO;
}
- /*
- * WARNING:
- * The loop to set the correct current level is performed
- * with interrupts disabled as it is timing critical.
- * The maximum number of cycles of the loop is 32
- * so the time taken will be (T_LOW_NS + T_HIGH_NS + loop_time) * 32,
- */
- local_irq_save(flags);
while (current_ratio != target_ratio) {
/*
* These GPIO operations absolutely can NOT sleep so no
* _cansleep suffixes, and no using GPIO expanders on
* slow buses for this!
*/
- gpiod_set_value(ktd253->gpiod, 0);
- ndelay(KTD253_T_LOW_NS);
- gpiod_set_value(ktd253->gpiod, 1);
- ndelay(KTD253_T_HIGH_NS);
- /* After 1/32 we loop back to 32/32 */
- if (current_ratio == KTD253_MIN_RATIO)
+ ret = ktd253_backlight_stepdown(ktd253);
+ if (ret == -EAGAIN) {
+ /*
+ * Something disturbed the backlight setting code when
+ * running so we need to bring the PWM back to a known
+ * state. This shouldn't happen too much.
+ */
+ gpiod_set_value_cansleep(ktd253->gpiod, 0);
+ msleep(KTD253_T_OFF_MS);
+ ktd253_backlight_set_max_ratio(ktd253);
+ current_ratio = KTD253_MAX_RATIO;
+ } else if (current_ratio == KTD253_MIN_RATIO) {
+ /* After 1/32 we loop back to 32/32 */
current_ratio = KTD253_MAX_RATIO;
- else
+ } else {
current_ratio--;
+ }
}
- local_irq_restore(flags);
ktd253->ratio = current_ratio;
dev_dbg(ktd253->dev, "new ratio set to %d/32\n", target_ratio);
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index e48fded3e414..8d8959a70e44 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -409,6 +409,33 @@ static bool pwm_backlight_is_linear(struct platform_pwm_backlight_data *data)
static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
{
struct device_node *node = pb->dev->of_node;
+ bool active = true;
+
+ /*
+ * If the enable GPIO is present, observable (either as input
+ * or output) and off then the backlight is not currently active.
+ * */
+ if (pb->enable_gpio && gpiod_get_value_cansleep(pb->enable_gpio) == 0)
+ active = false;
+
+ if (!regulator_is_enabled(pb->power_supply))
+ active = false;
+
+ if (!pwm_is_enabled(pb->pwm))
+ active = false;
+
+ /*
+ * Synchronize the enable_gpio with the observed state of the
+ * hardware.
+ */
+ if (pb->enable_gpio)
+ gpiod_direction_output(pb->enable_gpio, active);
+
+ /*
+ * Do not change pb->enabled here! pb->enabled essentially
+ * tells us if we own one of the regulator's use counts and
+ * right now we do not.
+ */
/* Not booted with device tree or no phandle link to the node */
if (!node || !node->phandle)
@@ -420,20 +447,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
* assume that another driver will enable the backlight at the
* appropriate time. Therefore, if it is disabled, keep it so.
*/
-
- /* if the enable GPIO is disabled, do not enable the backlight */
- if (pb->enable_gpio && gpiod_get_value_cansleep(pb->enable_gpio) == 0)
- return FB_BLANK_POWERDOWN;
-
- /* The regulator is disabled, do not enable the backlight */
- if (!regulator_is_enabled(pb->power_supply))
- return FB_BLANK_POWERDOWN;
-
- /* The PWM is disabled, keep it like this */
- if (!pwm_is_enabled(pb->pwm))
- return FB_BLANK_POWERDOWN;
-
- return FB_BLANK_UNBLANK;
+ return active ? FB_BLANK_UNBLANK: FB_BLANK_POWERDOWN;
}
static int pwm_backlight_probe(struct platform_device *pdev)
@@ -486,18 +500,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
goto err_alloc;
}
- /*
- * If the GPIO is not known to be already configured as output, that
- * 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) != 0)
- gpiod_direction_output(pb->enable_gpio, 1);
-
pb->power_supply = devm_regulator_get(&pdev->dev, "power");
if (IS_ERR(pb->power_supply)) {
ret = PTR_ERR(pb->power_supply);
diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c
index 1447324ed0b6..45e64016db32 100644
--- a/drivers/video/fbdev/arcfb.c
+++ b/drivers/video/fbdev/arcfb.c
@@ -446,7 +446,7 @@ static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
/* modded from epson 1355 */
unsigned long p;
- int err=-EINVAL;
+ int err;
unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
struct arcfb_par *par;
unsigned int xres;
diff --git a/drivers/video/fbdev/asiliantfb.c b/drivers/video/fbdev/asiliantfb.c
index 3e006da47752..84c56f525889 100644
--- a/drivers/video/fbdev/asiliantfb.c
+++ b/drivers/video/fbdev/asiliantfb.c
@@ -227,6 +227,9 @@ static int asiliantfb_check_var(struct fb_var_screeninfo *var,
{
unsigned long Ftarget, ratio, remainder;
+ if (!var->pixclock)
+ return -EINVAL;
+
ratio = 1000000 / var->pixclock;
remainder = 1000000 % var->pixclock;
Ftarget = 1000000 * ratio + (1000000 * remainder) / var->pixclock;
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 1c855145711b..71fb710f1ce3 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -67,7 +67,7 @@ static struct fb_info *get_fb_info(unsigned int idx)
mutex_lock(&registration_lock);
fb_info = registered_fb[idx];
if (fb_info)
- atomic_inc(&fb_info->count);
+ refcount_inc(&fb_info->count);
mutex_unlock(&registration_lock);
return fb_info;
@@ -75,7 +75,7 @@ static struct fb_info *get_fb_info(unsigned int idx)
static void put_fb_info(struct fb_info *fb_info)
{
- if (!atomic_dec_and_test(&fb_info->count))
+ if (!refcount_dec_and_test(&fb_info->count))
return;
if (fb_info->fbops->fb_destroy)
fb_info->fbops->fb_destroy(fb_info);
@@ -1592,7 +1592,7 @@ static int do_register_framebuffer(struct fb_info *fb_info)
if (!registered_fb[i])
break;
fb_info->node = i;
- atomic_set(&fb_info->count, 1);
+ refcount_set(&fb_info->count, 1);
mutex_init(&fb_info->lock);
mutex_init(&fb_info->mm_lock);
diff --git a/drivers/video/fbdev/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c
index ba33b4dce0df..2398b3d48fed 100644
--- a/drivers/video/fbdev/ep93xx-fb.c
+++ b/drivers/video/fbdev/ep93xx-fb.c
@@ -548,7 +548,7 @@ static int ep93xxfb_probe(struct platform_device *pdev)
}
ep93xxfb_set_par(info);
- clk_enable(fbi->clk);
+ clk_prepare_enable(fbi->clk);
err = register_framebuffer(info);
if (err)
@@ -577,7 +577,7 @@ static int ep93xxfb_remove(struct platform_device *pdev)
struct ep93xx_fbi *fbi = info->par;
unregister_framebuffer(info);
- clk_disable(fbi->clk);
+ clk_disable_unprepare(fbi->clk);
ep93xxfb_dealloc_videomem(info);
fb_dealloc_cmap(&info->cmap);
diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c
index 8fbde92ae8b9..25801e8e3f74 100644
--- a/drivers/video/fbdev/kyro/fbdev.c
+++ b/drivers/video/fbdev/kyro/fbdev.c
@@ -372,6 +372,11 @@ static int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 ulWidth, u32 ulHeight
/* probably haven't called CreateOverlay yet */
return -EINVAL;
+ if (ulWidth == 0 || ulWidth == 0xffffffff ||
+ ulHeight == 0 || ulHeight == 0xffffffff ||
+ (x < 2 && ulWidth + 2 == 0))
+ return -EINVAL;
+
/* Stop Ramdac Output */
DisableRamdacOutput(deviceInfo.pSTGReg);
@@ -394,6 +399,9 @@ static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct kyrofb_info *par = info->par;
+ if (!var->pixclock)
+ return -EINVAL;
+
if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) {
printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel);
return -EINVAL;
diff --git a/drivers/video/fbdev/neofb.c b/drivers/video/fbdev/neofb.c
index c0f4f402da3f..966df2a07360 100644
--- a/drivers/video/fbdev/neofb.c
+++ b/drivers/video/fbdev/neofb.c
@@ -585,7 +585,7 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
DBG("neofb_check_var");
- if (PICOS2KHZ(var->pixclock) > par->maxClock)
+ if (var->pixclock && PICOS2KHZ(var->pixclock) > par->maxClock)
return -EINVAL;
/* Is the mode larger than the LCD panel? */
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/apply.c b/drivers/video/fbdev/omap2/omapfb/dss/apply.c
index c71021091828..acca991c7540 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/apply.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/apply.c
@@ -108,7 +108,7 @@ static struct {
} dss_data;
/* protects dss_data */
-static spinlock_t data_lock;
+static DEFINE_SPINLOCK(data_lock);
/* lock for blocking functions */
static DEFINE_MUTEX(apply_lock);
static DECLARE_COMPLETION(extra_updated_completion);
@@ -131,8 +131,6 @@ static void apply_init_priv(void)
struct mgr_priv_data *mp;
int i;
- spin_lock_init(&data_lock);
-
for (i = 0; i < num_ovls; ++i) {
struct ovl_priv_data *op;
diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c
index 55554b0433cb..84d5e23ad7d3 100644
--- a/drivers/video/fbdev/riva/fbdev.c
+++ b/drivers/video/fbdev/riva/fbdev.c
@@ -1084,6 +1084,9 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
int mode_valid = 0;
NVTRACE_ENTER();
+ if (!var->pixclock)
+ return -EINVAL;
+
switch (var->bits_per_pixel) {
case 1 ... 8:
var->red.offset = var->green.offset = var->blue.offset = 0;
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index eda448b7a0c9..1e2f71c2f8a8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -82,6 +82,11 @@ struct ssd1307fb_par {
struct regulator *vbat_reg;
u32 vcomh;
u32 width;
+ /* Cached address ranges */
+ u8 col_start;
+ u8 col_end;
+ u8 page_start;
+ u8 page_end;
};
struct ssd1307fb_array {
@@ -152,17 +157,72 @@ static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
return ret;
}
-static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+static int ssd1307fb_set_col_range(struct ssd1307fb_par *par, u8 col_start,
+ u8 cols)
+{
+ u8 col_end = col_start + cols - 1;
+ int ret;
+
+ if (col_start == par->col_start && col_end == par->col_end)
+ return 0;
+
+ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
+ if (ret < 0)
+ return ret;
+
+ ret = ssd1307fb_write_cmd(par->client, col_start);
+ if (ret < 0)
+ return ret;
+
+ ret = ssd1307fb_write_cmd(par->client, col_end);
+ if (ret < 0)
+ return ret;
+
+ par->col_start = col_start;
+ par->col_end = col_end;
+ return 0;
+}
+
+static int ssd1307fb_set_page_range(struct ssd1307fb_par *par, u8 page_start,
+ u8 pages)
+{
+ u8 page_end = page_start + pages - 1;
+ int ret;
+
+ if (page_start == par->page_start && page_end == par->page_end)
+ return 0;
+
+ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
+ if (ret < 0)
+ return ret;
+
+ ret = ssd1307fb_write_cmd(par->client, page_start);
+ if (ret < 0)
+ return ret;
+
+ ret = ssd1307fb_write_cmd(par->client, page_end);
+ if (ret < 0)
+ return ret;
+
+ par->page_start = page_start;
+ par->page_end = page_end;
+ return 0;
+}
+
+static int ssd1307fb_update_rect(struct ssd1307fb_par *par, unsigned int x,
+ unsigned int y, unsigned int width,
+ unsigned int height)
{
struct ssd1307fb_array *array;
u8 *vmem = par->info->screen_buffer;
unsigned int line_length = par->info->fix.line_length;
- unsigned int pages = DIV_ROUND_UP(par->height, 8);
- int i, j, k;
+ unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8);
+ u32 array_idx = 0;
+ int ret, i, j, k;
- array = ssd1307fb_alloc_array(par->width * pages, SSD1307FB_DATA);
+ array = ssd1307fb_alloc_array(width * pages, SSD1307FB_DATA);
if (!array)
- return;
+ return -ENOMEM;
/*
* The screen is divided in pages, each having a height of 8
@@ -193,27 +253,44 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
* (5) A4 B4 C4 D4 E4 F4 G4 H4
*/
- for (i = 0; i < pages; i++) {
- for (j = 0; j < par->width; j++) {
- int m = 8;
- u32 array_idx = i * par->width + j;
- array->data[array_idx] = 0;
- /* Last page may be partial */
- if (i + 1 == pages && par->height % 8)
- m = par->height % 8;
+ ret = ssd1307fb_set_col_range(par, par->col_offset + x, width);
+ if (ret < 0)
+ goto out_free;
+
+ ret = ssd1307fb_set_page_range(par, par->page_offset + y / 8, pages);
+ if (ret < 0)
+ goto out_free;
+
+ for (i = y / 8; i < y / 8 + pages; i++) {
+ int m = 8;
+
+ /* Last page may be partial */
+ if (8 * (i + 1) > par->height)
+ m = par->height % 8;
+ for (j = x; j < x + width; j++) {
+ u8 data = 0;
+
for (k = 0; k < m; k++) {
u8 byte = vmem[(8 * i + k) * line_length +
j / 8];
u8 bit = (byte >> (j % 8)) & 1;
- array->data[array_idx] |= bit << k;
+ data |= bit << k;
}
+ array->data[array_idx++] = data;
}
}
- ssd1307fb_write_array(par->client, array, par->width * pages);
+ ret = ssd1307fb_write_array(par->client, array, width * pages);
+
+out_free:
kfree(array);
+ return ret;
}
+static int ssd1307fb_update_display(struct ssd1307fb_par *par)
+{
+ return ssd1307fb_update_rect(par, 0, 0, par->width, par->height);
+}
static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos)
@@ -222,6 +299,7 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
unsigned long total_size;
unsigned long p = *ppos;
void *dst;
+ int ret;
total_size = info->fix.smem_len;
@@ -239,7 +317,9 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
if (copy_from_user(dst, buf, count))
return -EFAULT;
- ssd1307fb_update_display(par);
+ ret = ssd1307fb_update_display(par);
+ if (ret < 0)
+ return ret;
*ppos += count;
@@ -260,21 +340,24 @@ static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *r
{
struct ssd1307fb_par *par = info->par;
sys_fillrect(info, rect);
- ssd1307fb_update_display(par);
+ ssd1307fb_update_rect(par, rect->dx, rect->dy, rect->width,
+ rect->height);
}
static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
struct ssd1307fb_par *par = info->par;
sys_copyarea(info, area);
- ssd1307fb_update_display(par);
+ ssd1307fb_update_rect(par, area->dx, area->dy, area->width,
+ area->height);
}
static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct ssd1307fb_par *par = info->par;
sys_imageblit(info, image);
- ssd1307fb_update_display(par);
+ ssd1307fb_update_rect(par, image->dx, image->dy, image->width,
+ image->height);
}
static const struct fb_ops ssd1307fb_ops = {
@@ -454,37 +537,11 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
if (ret < 0)
return ret;
- /* Set column range */
- ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
- if (ret < 0)
- return ret;
-
- ret = ssd1307fb_write_cmd(par->client, par->col_offset);
- if (ret < 0)
- return ret;
-
- ret = ssd1307fb_write_cmd(par->client, par->col_offset + par->width - 1);
- if (ret < 0)
- return ret;
-
- /* Set page range */
- ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
- if (ret < 0)
- return ret;
-
- ret = ssd1307fb_write_cmd(par->client, par->page_offset);
- if (ret < 0)
- return ret;
-
- ret = ssd1307fb_write_cmd(par->client,
- par->page_offset +
- DIV_ROUND_UP(par->height, 8) - 1);
+ /* Clear the screen */
+ ret = ssd1307fb_update_display(par);
if (ret < 0)
return ret;
- /* Clear the screen */
- ssd1307fb_update_display(par);
-
/* Turn on the display */
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
if (ret < 0)
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 49984d2cba24..1ea0c1f6a1fd 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -278,7 +278,7 @@ err:
}
-static int virtio_dev_remove(struct device *_d)
+static void virtio_dev_remove(struct device *_d)
{
struct virtio_device *dev = dev_to_virtio(_d);
struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
@@ -292,7 +292,6 @@ static int virtio_dev_remove(struct device *_d)
/* Acknowledge the device's existence again. */
virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
- return 0;
}
static struct bus_type virtio_bus = {
diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c
index e966981c0215..4af6615808cc 100644
--- a/drivers/vlynq/vlynq.c
+++ b/drivers/vlynq/vlynq.c
@@ -342,14 +342,12 @@ static int vlynq_device_probe(struct device *dev)
return result;
}
-static int vlynq_device_remove(struct device *dev)
+static void vlynq_device_remove(struct device *dev)
{
struct vlynq_driver *drv = to_vlynq_driver(dev->driver);
if (drv->remove)
drv->remove(to_vlynq_device(dev));
-
- return 0;
}
int __vlynq_register_driver(struct vlynq_driver *driver, struct module *owner)
diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c
index 1b15afea28ee..8dba20186be3 100644
--- a/drivers/vme/vme.c
+++ b/drivers/vme/vme.c
@@ -1990,7 +1990,7 @@ static int vme_bus_probe(struct device *dev)
return -ENODEV;
}
-static int vme_bus_remove(struct device *dev)
+static void vme_bus_remove(struct device *dev)
{
struct vme_driver *driver;
struct vme_dev *vdev = dev_to_vme_dev(dev);
@@ -1998,8 +1998,6 @@ static int vme_bus_remove(struct device *dev)
driver = dev->platform_data;
if (driver->remove)
driver->remove(vdev);
-
- return 0;
}
struct bus_type vme_bus_type = {
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 546dfc1e2349..b81fe4f7d434 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -168,18 +168,6 @@ config SOFT_WATCHDOG_PRETIMEOUT
watchdog. Be aware that governors might affect the watchdog because it
is purely software, e.g. the panic governor will stall it!
-config BD70528_WATCHDOG
- tristate "ROHM BD70528 PMIC Watchdog"
- depends on MFD_ROHM_BD70528
- select WATCHDOG_CORE
- help
- Support for the watchdog in the ROHM BD70528 PMIC. Watchdog trigger
- cause system reset.
-
- Say Y here to include support for the ROHM BD70528 watchdog.
- Alternatively say M to compile the driver as a module,
- which will be called bd70528_wdt.
-
config BD957XMUF_WATCHDOG
tristate "ROHM BD9576MUF and BD9573MUF PMIC Watchdog"
depends on MFD_ROHM_BD957XMUF
@@ -487,6 +475,7 @@ config FTWDT010_WATCHDOG
config IXP4XX_WATCHDOG
tristate "IXP4xx Watchdog"
depends on ARCH_IXP4XX
+ select WATCHDOG_CORE
help
Say Y here if to include support for the watchdog timer
in the Intel IXP4xx network processors. This driver can
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index abaf2ebd814e..1bd2d6f37c53 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -204,7 +204,6 @@ obj-$(CONFIG_WATCHDOG_SUN4V) += sun4v_wdt.o
obj-$(CONFIG_XEN_WDT) += xen_wdt.o
# Architecture Independent
-obj-$(CONFIG_BD70528_WATCHDOG) += bd70528_wdt.o
obj-$(CONFIG_BD957XMUF_WATCHDOG) += bd9576_wdt.o
obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o
obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
index dec6ca019bea..94907176a0e4 100644
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -205,9 +205,13 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
if (err)
return err;
- if (pm_power_off == NULL) {
- pm_power_off = bcm2835_power_off;
- bcm2835_power_off_wdt = wdt;
+ if (of_device_is_system_power_controller(pdev->dev.parent->of_node)) {
+ if (!pm_power_off) {
+ pm_power_off = bcm2835_power_off;
+ bcm2835_power_off_wdt = wdt;
+ } else {
+ dev_info(dev, "Poweroff handler already present!\n");
+ }
}
dev_info(dev, "Broadcom BCM2835 watchdog timer");
diff --git a/drivers/watchdog/bd70528_wdt.c b/drivers/watchdog/bd70528_wdt.c
deleted file mode 100644
index 0170b37e6674..000000000000
--- a/drivers/watchdog/bd70528_wdt.c
+++ /dev/null
@@ -1,291 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-// Copyright (C) 2018 ROHM Semiconductors
-// ROHM BD70528MWV watchdog driver
-
-#include <linux/bcd.h>
-#include <linux/kernel.h>
-#include <linux/mfd/rohm-bd70528.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/watchdog.h>
-
-/*
- * Max time we can set is 1 hour, 59 minutes and 59 seconds
- * and Minimum time is 1 second
- */
-#define WDT_MAX_MS ((2 * 60 * 60 - 1) * 1000)
-#define WDT_MIN_MS 1000
-#define DEFAULT_TIMEOUT 60
-
-#define WD_CTRL_MAGIC1 0x55
-#define WD_CTRL_MAGIC2 0xAA
-
-struct wdtbd70528 {
- struct device *dev;
- struct regmap *regmap;
- struct rohm_regmap_dev *mfd;
- struct watchdog_device wdt;
-};
-
-/**
- * bd70528_wdt_set - arm or disarm watchdog timer
- *
- * @data: device data for the PMIC instance we want to operate on
- * @enable: new state of WDT. zero to disable, non zero to enable
- * @old_state: previous state of WDT will be filled here
- *
- * Arm or disarm WDT on BD70528 PMIC. Expected to be called only by
- * BD70528 RTC and BD70528 WDT drivers. The rtc_timer_lock must be taken
- * by calling bd70528_wdt_lock before calling bd70528_wdt_set.
- */
-int bd70528_wdt_set(struct rohm_regmap_dev *data, int enable, int *old_state)
-{
- int ret, i;
- unsigned int tmp;
- struct bd70528_data *bd70528 = container_of(data, struct bd70528_data,
- chip);
- u8 wd_ctrl_arr[3] = { WD_CTRL_MAGIC1, WD_CTRL_MAGIC2, 0 };
- u8 *wd_ctrl = &wd_ctrl_arr[2];
-
- ret = regmap_read(bd70528->chip.regmap, BD70528_REG_WDT_CTRL, &tmp);
- if (ret)
- return ret;
-
- *wd_ctrl = (u8)tmp;
-
- if (old_state) {
- if (*wd_ctrl & BD70528_MASK_WDT_EN)
- *old_state |= BD70528_WDT_STATE_BIT;
- else
- *old_state &= ~BD70528_WDT_STATE_BIT;
- if ((!enable) == (!(*old_state & BD70528_WDT_STATE_BIT)))
- return 0;
- }
-
- if (enable) {
- if (*wd_ctrl & BD70528_MASK_WDT_EN)
- return 0;
- *wd_ctrl |= BD70528_MASK_WDT_EN;
- } else {
- if (*wd_ctrl & BD70528_MASK_WDT_EN)
- *wd_ctrl &= ~BD70528_MASK_WDT_EN;
- else
- return 0;
- }
-
- for (i = 0; i < 3; i++) {
- ret = regmap_write(bd70528->chip.regmap, BD70528_REG_WDT_CTRL,
- wd_ctrl_arr[i]);
- if (ret)
- return ret;
- }
-
- ret = regmap_read(bd70528->chip.regmap, BD70528_REG_WDT_CTRL, &tmp);
- if ((tmp & BD70528_MASK_WDT_EN) != (*wd_ctrl & BD70528_MASK_WDT_EN)) {
- dev_err(bd70528->chip.dev,
- "Watchdog ctrl mismatch (hw) 0x%x (set) 0x%x\n",
- tmp, *wd_ctrl);
- ret = -EIO;
- }
-
- return ret;
-}
-EXPORT_SYMBOL(bd70528_wdt_set);
-
-/**
- * bd70528_wdt_lock - take WDT lock
- *
- * @data: device data for the PMIC instance we want to operate on
- *
- * Lock WDT for arming/disarming in order to avoid race condition caused
- * by WDT state changes initiated by WDT and RTC drivers.
- */
-void bd70528_wdt_lock(struct rohm_regmap_dev *data)
-{
- struct bd70528_data *bd70528 = container_of(data, struct bd70528_data,
- chip);
-
- mutex_lock(&bd70528->rtc_timer_lock);
-}
-EXPORT_SYMBOL(bd70528_wdt_lock);
-
-/**
- * bd70528_wdt_unlock - unlock WDT lock
- *
- * @data: device data for the PMIC instance we want to operate on
- *
- * Unlock WDT lock which has previously been taken by call to
- * bd70528_wdt_lock.
- */
-void bd70528_wdt_unlock(struct rohm_regmap_dev *data)
-{
- struct bd70528_data *bd70528 = container_of(data, struct bd70528_data,
- chip);
-
- mutex_unlock(&bd70528->rtc_timer_lock);
-}
-EXPORT_SYMBOL(bd70528_wdt_unlock);
-
-static int bd70528_wdt_set_locked(struct wdtbd70528 *w, int enable)
-{
- return bd70528_wdt_set(w->mfd, enable, NULL);
-}
-
-static int bd70528_wdt_change(struct wdtbd70528 *w, int enable)
-{
- int ret;
-
- bd70528_wdt_lock(w->mfd);
- ret = bd70528_wdt_set_locked(w, enable);
- bd70528_wdt_unlock(w->mfd);
-
- return ret;
-}
-
-static int bd70528_wdt_start(struct watchdog_device *wdt)
-{
- struct wdtbd70528 *w = watchdog_get_drvdata(wdt);
-
- dev_dbg(w->dev, "WDT ping...\n");
- return bd70528_wdt_change(w, 1);
-}
-
-static int bd70528_wdt_stop(struct watchdog_device *wdt)
-{
- struct wdtbd70528 *w = watchdog_get_drvdata(wdt);
-
- dev_dbg(w->dev, "WDT stopping...\n");
- return bd70528_wdt_change(w, 0);
-}
-
-static int bd70528_wdt_set_timeout(struct watchdog_device *wdt,
- unsigned int timeout)
-{
- unsigned int hours;
- unsigned int minutes;
- unsigned int seconds;
- int ret;
- struct wdtbd70528 *w = watchdog_get_drvdata(wdt);
-
- seconds = timeout;
- hours = timeout / (60 * 60);
- /* Maximum timeout is 1h 59m 59s => hours is 1 or 0 */
- if (hours)
- seconds -= (60 * 60);
- minutes = seconds / 60;
- seconds = seconds % 60;
-
- bd70528_wdt_lock(w->mfd);
-
- ret = bd70528_wdt_set_locked(w, 0);
- if (ret)
- goto out_unlock;
-
- ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_HOUR,
- BD70528_MASK_WDT_HOUR, hours);
- if (ret) {
- dev_err(w->dev, "Failed to set WDT hours\n");
- goto out_en_unlock;
- }
- ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_MINUTE,
- BD70528_MASK_WDT_MINUTE, bin2bcd(minutes));
- if (ret) {
- dev_err(w->dev, "Failed to set WDT minutes\n");
- goto out_en_unlock;
- }
- ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_SEC,
- BD70528_MASK_WDT_SEC, bin2bcd(seconds));
- if (ret)
- dev_err(w->dev, "Failed to set WDT seconds\n");
- else
- dev_dbg(w->dev, "WDT tmo set to %u\n", timeout);
-
-out_en_unlock:
- ret = bd70528_wdt_set_locked(w, 1);
-out_unlock:
- bd70528_wdt_unlock(w->mfd);
-
- return ret;
-}
-
-static const struct watchdog_info bd70528_wdt_info = {
- .identity = "bd70528-wdt",
- .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
-};
-
-static const struct watchdog_ops bd70528_wdt_ops = {
- .start = bd70528_wdt_start,
- .stop = bd70528_wdt_stop,
- .set_timeout = bd70528_wdt_set_timeout,
-};
-
-static int bd70528_wdt_probe(struct platform_device *pdev)
-{
- struct rohm_regmap_dev *bd70528;
- struct wdtbd70528 *w;
- int ret;
- unsigned int reg;
-
- bd70528 = dev_get_drvdata(pdev->dev.parent);
- if (!bd70528) {
- dev_err(&pdev->dev, "No MFD driver data\n");
- return -EINVAL;
- }
- w = devm_kzalloc(&pdev->dev, sizeof(*w), GFP_KERNEL);
- if (!w)
- return -ENOMEM;
-
- w->regmap = bd70528->regmap;
- w->mfd = bd70528;
- w->dev = &pdev->dev;
-
- w->wdt.info = &bd70528_wdt_info;
- w->wdt.ops = &bd70528_wdt_ops;
- w->wdt.min_hw_heartbeat_ms = WDT_MIN_MS;
- w->wdt.max_hw_heartbeat_ms = WDT_MAX_MS;
- w->wdt.parent = pdev->dev.parent;
- w->wdt.timeout = DEFAULT_TIMEOUT;
- watchdog_set_drvdata(&w->wdt, w);
- watchdog_init_timeout(&w->wdt, 0, pdev->dev.parent);
-
- ret = bd70528_wdt_set_timeout(&w->wdt, w->wdt.timeout);
- if (ret) {
- dev_err(&pdev->dev, "Failed to set the watchdog timeout\n");
- return ret;
- }
-
- bd70528_wdt_lock(w->mfd);
- ret = regmap_read(w->regmap, BD70528_REG_WDT_CTRL, &reg);
- bd70528_wdt_unlock(w->mfd);
-
- if (ret) {
- dev_err(&pdev->dev, "Failed to get the watchdog state\n");
- return ret;
- }
- if (reg & BD70528_MASK_WDT_EN) {
- dev_dbg(&pdev->dev, "watchdog was running during probe\n");
- set_bit(WDOG_HW_RUNNING, &w->wdt.status);
- }
-
- ret = devm_watchdog_register_device(&pdev->dev, &w->wdt);
- if (ret < 0)
- dev_err(&pdev->dev, "watchdog registration failed: %d\n", ret);
-
- return ret;
-}
-
-static struct platform_driver bd70528_wdt = {
- .driver = {
- .name = "bd70528-wdt"
- },
- .probe = bd70528_wdt_probe,
-};
-
-module_platform_driver(bd70528_wdt);
-
-MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
-MODULE_DESCRIPTION("BD70528 watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:bd70528-wdt");
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index b3f604669e2c..643c6c2d0b72 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -362,7 +362,7 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t)
* Otherwise, the BIOS generally reboots when the SMI triggers.
*/
if (p->smi_res &&
- (SMI_EN(p) & (TCO_EN | GBL_SMI_EN)) != (TCO_EN | GBL_SMI_EN))
+ (inl(SMI_EN(p)) & (TCO_EN | GBL_SMI_EN)) != (TCO_EN | GBL_SMI_EN))
tmrval /= 2;
/* from the specs: */
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index cc86018c5eb5..51bfb796898b 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -317,6 +317,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(wdog, nowayout);
watchdog_set_restart_priority(wdog, 128);
watchdog_init_timeout(wdog, timeout, dev);
+ watchdog_stop_ping_on_suspend(wdog);
if (imx2_wdt_is_running(wdev)) {
imx2_wdt_set_timeout(wdog, wdog->timeout);
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c
index aae29dcfaf11..2693ffb24ac7 100644
--- a/drivers/watchdog/ixp4xx_wdt.c
+++ b/drivers/watchdog/ixp4xx_wdt.c
@@ -1,220 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* drivers/char/watchdog/ixp4xx_wdt.c
*
* Watchdog driver for Intel IXP4xx network processors
*
* Author: Deepak Saxena <dsaxena@plexity.net>
+ * Author: Linus Walleij <linus.walleij@linaro.org>
*
* Copyright 2004 (c) MontaVista, Software, Inc.
* Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/of.h>
#include <linux/watchdog.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/uaccess.h>
-#include <mach/hardware.h>
+#include <linux/bits.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/soc/ixp4xx/cpu.h>
+
+struct ixp4xx_wdt {
+ struct watchdog_device wdd;
+ void __iomem *base;
+ unsigned long rate;
+};
-static bool nowayout = WATCHDOG_NOWAYOUT;
-static int heartbeat = 60; /* (secs) Default is 1 minute */
-static unsigned long wdt_status;
-static unsigned long boot_status;
-static DEFINE_SPINLOCK(wdt_lock);
+/* Fallback if we do not have a clock for this */
+#define IXP4XX_TIMER_FREQ 66666000
-#define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL)
+/* Registers after the timer registers */
+#define IXP4XX_OSWT_OFFSET 0x14 /* Watchdog Timer */
+#define IXP4XX_OSWE_OFFSET 0x18 /* Watchdog Enable */
+#define IXP4XX_OSWK_OFFSET 0x1C /* Watchdog Key */
+#define IXP4XX_OSST_OFFSET 0x20 /* Timer Status */
-#define WDT_IN_USE 0
-#define WDT_OK_TO_CLOSE 1
+#define IXP4XX_OSST_TIMER_WDOG_PEND 0x00000008
+#define IXP4XX_OSST_TIMER_WARM_RESET 0x00000010
+#define IXP4XX_WDT_KEY 0x0000482E
+#define IXP4XX_WDT_RESET_ENABLE 0x00000001
+#define IXP4XX_WDT_IRQ_ENABLE 0x00000002
+#define IXP4XX_WDT_COUNT_ENABLE 0x00000004
-static void wdt_enable(void)
+static inline
+struct ixp4xx_wdt *to_ixp4xx_wdt(struct watchdog_device *wdd)
{
- spin_lock(&wdt_lock);
- *IXP4XX_OSWK = IXP4XX_WDT_KEY;
- *IXP4XX_OSWE = 0;
- *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat;
- *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE;
- *IXP4XX_OSWK = 0;
- spin_unlock(&wdt_lock);
+ return container_of(wdd, struct ixp4xx_wdt, wdd);
}
-static void wdt_disable(void)
+static int ixp4xx_wdt_start(struct watchdog_device *wdd)
{
- spin_lock(&wdt_lock);
- *IXP4XX_OSWK = IXP4XX_WDT_KEY;
- *IXP4XX_OSWE = 0;
- *IXP4XX_OSWK = 0;
- spin_unlock(&wdt_lock);
-}
+ struct ixp4xx_wdt *iwdt = to_ixp4xx_wdt(wdd);
-static int ixp4xx_wdt_open(struct inode *inode, struct file *file)
-{
- if (test_and_set_bit(WDT_IN_USE, &wdt_status))
- return -EBUSY;
+ __raw_writel(IXP4XX_WDT_KEY, iwdt->base + IXP4XX_OSWK_OFFSET);
+ __raw_writel(0, iwdt->base + IXP4XX_OSWE_OFFSET);
+ __raw_writel(wdd->timeout * iwdt->rate,
+ iwdt->base + IXP4XX_OSWT_OFFSET);
+ __raw_writel(IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE,
+ iwdt->base + IXP4XX_OSWE_OFFSET);
+ __raw_writel(0, iwdt->base + IXP4XX_OSWK_OFFSET);
- clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
- wdt_enable();
- return stream_open(inode, file);
+ return 0;
}
-static ssize_t
-ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+static int ixp4xx_wdt_stop(struct watchdog_device *wdd)
{
- if (len) {
- if (!nowayout) {
- size_t i;
-
- clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
- for (i = 0; i != len; i++) {
- char c;
-
- if (get_user(c, data + i))
- return -EFAULT;
- if (c == 'V')
- set_bit(WDT_OK_TO_CLOSE, &wdt_status);
- }
- }
- wdt_enable();
- }
- return len;
-}
+ struct ixp4xx_wdt *iwdt = to_ixp4xx_wdt(wdd);
-static const struct watchdog_info ident = {
- .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
- WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
- .identity = "IXP4xx Watchdog",
-};
+ __raw_writel(IXP4XX_WDT_KEY, iwdt->base + IXP4XX_OSWK_OFFSET);
+ __raw_writel(0, iwdt->base + IXP4XX_OSWE_OFFSET);
+ __raw_writel(0, iwdt->base + IXP4XX_OSWK_OFFSET);
-
-static long ixp4xx_wdt_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int ret = -ENOTTY;
- int time;
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- ret = copy_to_user((struct watchdog_info *)arg, &ident,
- sizeof(ident)) ? -EFAULT : 0;
- break;
-
- case WDIOC_GETSTATUS:
- ret = put_user(0, (int *)arg);
- break;
-
- case WDIOC_GETBOOTSTATUS:
- ret = put_user(boot_status, (int *)arg);
- break;
-
- case WDIOC_KEEPALIVE:
- wdt_enable();
- ret = 0;
- break;
-
- case WDIOC_SETTIMEOUT:
- ret = get_user(time, (int *)arg);
- if (ret)
- break;
-
- if (time <= 0 || time > 60) {
- ret = -EINVAL;
- break;
- }
-
- heartbeat = time;
- wdt_enable();
- fallthrough;
-
- case WDIOC_GETTIMEOUT:
- ret = put_user(heartbeat, (int *)arg);
- break;
- }
- return ret;
+ return 0;
}
-static int ixp4xx_wdt_release(struct inode *inode, struct file *file)
+static int ixp4xx_wdt_set_timeout(struct watchdog_device *wdd,
+ unsigned int timeout)
{
- if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
- wdt_disable();
- else
- pr_crit("Device closed unexpectedly - timer will not stop\n");
- clear_bit(WDT_IN_USE, &wdt_status);
- clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ wdd->timeout = timeout;
+ if (watchdog_active(wdd))
+ ixp4xx_wdt_start(wdd);
return 0;
}
-
-static const struct file_operations ixp4xx_wdt_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = ixp4xx_wdt_write,
- .unlocked_ioctl = ixp4xx_wdt_ioctl,
- .compat_ioctl = compat_ptr_ioctl,
- .open = ixp4xx_wdt_open,
- .release = ixp4xx_wdt_release,
+static const struct watchdog_ops ixp4xx_wdt_ops = {
+ .start = ixp4xx_wdt_start,
+ .stop = ixp4xx_wdt_stop,
+ .set_timeout = ixp4xx_wdt_set_timeout,
+ .owner = THIS_MODULE,
};
-static struct miscdevice ixp4xx_wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &ixp4xx_wdt_fops,
+static const struct watchdog_info ixp4xx_wdt_info = {
+ .options = WDIOF_KEEPALIVEPING
+ | WDIOF_MAGICCLOSE
+ | WDIOF_SETTIMEOUT,
+ .identity = KBUILD_MODNAME,
};
-static int __init ixp4xx_wdt_init(void)
+/* Devres-handled clock disablement */
+static void ixp4xx_clock_action(void *d)
+{
+ clk_disable_unprepare(d);
+}
+
+static int ixp4xx_wdt_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct ixp4xx_wdt *iwdt;
+ struct clk *clk;
int ret;
- /*
- * FIXME: we bail out on device tree boot but this really needs
- * to be fixed in a nicer way: this registers the MDIO bus before
- * even matching the driver infrastructure, we should only probe
- * detected hardware.
- */
- if (of_have_populated_dt())
- return -ENODEV;
if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
- pr_err("Rev. A0 IXP42x CPU detected - watchdog disabled\n");
-
+ dev_err(dev, "Rev. A0 IXP42x CPU detected - watchdog disabled\n");
return -ENODEV;
}
- boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ?
- WDIOF_CARDRESET : 0;
- ret = misc_register(&ixp4xx_wdt_miscdev);
- if (ret == 0)
- pr_info("timer heartbeat %d sec\n", heartbeat);
- return ret;
-}
-static void __exit ixp4xx_wdt_exit(void)
-{
- misc_deregister(&ixp4xx_wdt_miscdev);
-}
+ iwdt = devm_kzalloc(dev, sizeof(*iwdt), GFP_KERNEL);
+ if (!iwdt)
+ return -ENOMEM;
+ iwdt->base = dev->platform_data;
+ /*
+ * Retrieve rate from a fixed clock from the device tree if
+ * the parent has that, else use the default clock rate.
+ */
+ clk = devm_clk_get(dev->parent, NULL);
+ if (!IS_ERR(clk)) {
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return ret;
+ ret = devm_add_action_or_reset(dev, ixp4xx_clock_action, clk);
+ if (ret)
+ return ret;
+ iwdt->rate = clk_get_rate(clk);
+ }
+ if (!iwdt->rate)
+ iwdt->rate = IXP4XX_TIMER_FREQ;
-module_init(ixp4xx_wdt_init);
-module_exit(ixp4xx_wdt_exit);
+ iwdt->wdd.info = &ixp4xx_wdt_info;
+ iwdt->wdd.ops = &ixp4xx_wdt_ops;
+ iwdt->wdd.min_timeout = 1;
+ iwdt->wdd.max_timeout = U32_MAX / iwdt->rate;
+ iwdt->wdd.parent = dev;
+ /* Default to 60 seconds */
+ iwdt->wdd.timeout = 60U;
+ watchdog_init_timeout(&iwdt->wdd, 0, dev);
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_DESCRIPTION("IXP4xx Network Processor Watchdog");
+ if (__raw_readl(iwdt->base + IXP4XX_OSST_OFFSET) &
+ IXP4XX_OSST_TIMER_WARM_RESET)
+ iwdt->wdd.bootstatus = WDIOF_CARDRESET;
+
+ ret = devm_watchdog_register_device(dev, &iwdt->wdd);
+ if (ret)
+ return ret;
+
+ dev_info(dev, "IXP4xx watchdog available\n");
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
+ return 0;
+}
-module_param(nowayout, bool, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+static struct platform_driver ixp4xx_wdt_driver = {
+ .probe = ixp4xx_wdt_probe,
+ .driver = {
+ .name = "ixp4xx-watchdog",
+ },
+};
+module_platform_driver(ixp4xx_wdt_driver);
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+MODULE_DESCRIPTION("IXP4xx Network Processor Watchdog");
MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index 3a899628a834..9e1541cfae0d 100644
--- a/drivers/watchdog/max63xx_wdt.c
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -26,6 +26,7 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/property.h>
#define DEFAULT_HEARTBEAT 60
#define MAX_HEARTBEAT 60
@@ -99,8 +100,8 @@ static const struct max63xx_timeout max6373_table[] = {
{ },
};
-static struct max63xx_timeout *
-max63xx_select_timeout(struct max63xx_timeout *table, int value)
+static const struct max63xx_timeout *
+max63xx_select_timeout(const struct max63xx_timeout *table, int value)
{
while (table->twd) {
if (value <= table->twd) {
@@ -202,14 +203,17 @@ static int max63xx_wdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct max63xx_wdt *wdt;
- struct max63xx_timeout *table;
+ const struct max63xx_timeout *table;
int err;
wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
if (!wdt)
return -ENOMEM;
- table = (struct max63xx_timeout *)pdev->id_entry->driver_data;
+ /* Attempt to use fwnode first */
+ table = device_get_match_data(dev);
+ if (!table)
+ table = (struct max63xx_timeout *)pdev->id_entry->driver_data;
if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
heartbeat = DEFAULT_HEARTBEAT;
@@ -255,11 +259,23 @@ static const struct platform_device_id max63xx_id_table[] = {
};
MODULE_DEVICE_TABLE(platform, max63xx_id_table);
+static const struct of_device_id max63xx_dt_id_table[] = {
+ { .compatible = "maxim,max6369", .data = max6369_table, },
+ { .compatible = "maxim,max6370", .data = max6369_table, },
+ { .compatible = "maxim,max6371", .data = max6371_table, },
+ { .compatible = "maxim,max6372", .data = max6371_table, },
+ { .compatible = "maxim,max6373", .data = max6373_table, },
+ { .compatible = "maxim,max6374", .data = max6373_table, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max63xx_dt_id_table);
+
static struct platform_driver max63xx_wdt_driver = {
.probe = max63xx_wdt_probe,
.id_table = max63xx_id_table,
.driver = {
.name = "max63xx_wdt",
+ .of_match_table = max63xx_dt_id_table,
},
};
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 2f7ded32e878..1c569be72ea2 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -118,7 +118,7 @@ static struct watchdog_info mpc8xxx_wdt_info = {
.identity = "MPC8xxx",
};
-static struct watchdog_ops mpc8xxx_wdt_ops = {
+static const struct watchdog_ops mpc8xxx_wdt_ops = {
.owner = THIS_MODULE,
.start = mpc8xxx_wdt_start,
.ping = mpc8xxx_wdt_ping,
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index 16b6aff324a7..796fbb048cbe 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -12,6 +12,7 @@
#include <dt-bindings/reset-controller/mt2712-resets.h>
#include <dt-bindings/reset-controller/mt8183-resets.h>
#include <dt-bindings/reset-controller/mt8192-resets.h>
+#include <dt-bindings/reset/mt8195-resets.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -82,6 +83,10 @@ static const struct mtk_wdt_data mt8192_data = {
.toprgu_sw_rst_num = MT8192_TOPRGU_SW_RST_NUM,
};
+static const struct mtk_wdt_data mt8195_data = {
+ .toprgu_sw_rst_num = MT8195_TOPRGU_SW_RST_NUM,
+};
+
static int toprgu_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
@@ -408,6 +413,7 @@ static const struct of_device_id mtk_wdt_dt_ids[] = {
{ .compatible = "mediatek,mt6589-wdt" },
{ .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
{ .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data },
+ { .compatible = "mediatek,mt8195-wdt", .data = &mt8195_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
diff --git a/drivers/watchdog/sl28cpld_wdt.c b/drivers/watchdog/sl28cpld_wdt.c
index 2de93298475f..9ce456f09f73 100644
--- a/drivers/watchdog/sl28cpld_wdt.c
+++ b/drivers/watchdog/sl28cpld_wdt.c
@@ -108,7 +108,7 @@ static const struct watchdog_info sl28cpld_wdt_info = {
.identity = "sl28cpld watchdog",
};
-static struct watchdog_ops sl28cpld_wdt_ops = {
+static const struct watchdog_ops sl28cpld_wdt_ops = {
.owner = THIS_MODULE,
.start = sl28cpld_wdt_start,
.stop = sl28cpld_wdt_stop,
diff --git a/drivers/watchdog/tqmx86_wdt.c b/drivers/watchdog/tqmx86_wdt.c
index 72d0b0adde38..83860e94ce9d 100644
--- a/drivers/watchdog/tqmx86_wdt.c
+++ b/drivers/watchdog/tqmx86_wdt.c
@@ -62,7 +62,7 @@ static const struct watchdog_info tqmx86_wdt_info = {
.identity = "TQMx86 Watchdog",
};
-static struct watchdog_ops tqmx86_wdt_ops = {
+static const struct watchdog_ops tqmx86_wdt_ops = {
.owner = THIS_MODULE,
.start = tqmx86_wdt_start,
.set_timeout = tqmx86_wdt_set_timeout,
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 5df0a22e2cb4..3fe8a7edc252 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -34,6 +34,7 @@
#include <linux/idr.h> /* For ida_* macros */
#include <linux/err.h> /* For IS_ERR macros */
#include <linux/of.h> /* For of_get_timeout_sec */
+#include <linux/suspend.h>
#include "watchdog_core.h" /* For watchdog_dev_register/... */
@@ -185,6 +186,33 @@ static int watchdog_restart_notifier(struct notifier_block *nb,
return NOTIFY_DONE;
}
+static int watchdog_pm_notifier(struct notifier_block *nb, unsigned long mode,
+ void *data)
+{
+ struct watchdog_device *wdd;
+ int ret = 0;
+
+ wdd = container_of(nb, struct watchdog_device, pm_nb);
+
+ switch (mode) {
+ case PM_HIBERNATION_PREPARE:
+ case PM_RESTORE_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ ret = watchdog_dev_suspend(wdd);
+ break;
+ case PM_POST_HIBERNATION:
+ case PM_POST_RESTORE:
+ case PM_POST_SUSPEND:
+ ret = watchdog_dev_resume(wdd);
+ break;
+ }
+
+ if (ret)
+ return NOTIFY_BAD;
+
+ return NOTIFY_DONE;
+}
+
/**
* watchdog_set_restart_priority - Change priority of restart handler
* @wdd: watchdog device
@@ -292,6 +320,15 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
wdd->id, ret);
}
+ if (test_bit(WDOG_NO_PING_ON_SUSPEND, &wdd->status)) {
+ wdd->pm_nb.notifier_call = watchdog_pm_notifier;
+
+ ret = register_pm_notifier(&wdd->pm_nb);
+ if (ret)
+ pr_warn("watchdog%d: Cannot register pm handler (%d)\n",
+ wdd->id, ret);
+ }
+
return 0;
}
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 3bab32485273..3a3d8b5c7ad5 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -401,7 +401,7 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd,
if (watchdog_pretimeout_invalid(wdd, timeout))
return -EINVAL;
- if (wdd->ops->set_pretimeout)
+ if (wdd->ops->set_pretimeout && (wdd->info->options & WDIOF_PRETIMEOUT))
err = wdd->ops->set_pretimeout(wdd, timeout);
else
wdd->pretimeout = timeout;
@@ -1096,6 +1096,8 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd)
watchdog_stop(wdd);
}
+ watchdog_hrtimer_pretimeout_stop(wdd);
+
mutex_lock(&wd_data->lock);
wd_data->wdd = NULL;
wdd->wd_data = NULL;
@@ -1103,7 +1105,6 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd)
hrtimer_cancel(&wd_data->timer);
kthread_cancel_work_sync(&wd_data->work);
- watchdog_hrtimer_pretimeout_stop(wdd);
put_device(&wd_data->dev);
}
@@ -1172,7 +1173,10 @@ int watchdog_set_last_hw_keepalive(struct watchdog_device *wdd,
wd_data->last_hw_keepalive = ktime_sub(now, ms_to_ktime(last_ping_ms));
- return __watchdog_ping(wdd);
+ if (watchdog_hw_running(wdd) && handle_boot_enabled)
+ return __watchdog_ping(wdd);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(watchdog_set_last_hw_keepalive);
@@ -1227,6 +1231,53 @@ void __exit watchdog_dev_exit(void)
kthread_destroy_worker(watchdog_kworker);
}
+int watchdog_dev_suspend(struct watchdog_device *wdd)
+{
+ struct watchdog_core_data *wd_data = wdd->wd_data;
+ int ret = 0;
+
+ if (!wdd->wd_data)
+ return -ENODEV;
+
+ /* ping for the last time before suspend */
+ mutex_lock(&wd_data->lock);
+ if (watchdog_worker_should_ping(wd_data))
+ ret = __watchdog_ping(wd_data->wdd);
+ mutex_unlock(&wd_data->lock);
+
+ if (ret)
+ return ret;
+
+ /*
+ * make sure that watchdog worker will not kick in when the wdog is
+ * suspended
+ */
+ hrtimer_cancel(&wd_data->timer);
+ kthread_cancel_work_sync(&wd_data->work);
+
+ return 0;
+}
+
+int watchdog_dev_resume(struct watchdog_device *wdd)
+{
+ struct watchdog_core_data *wd_data = wdd->wd_data;
+ int ret = 0;
+
+ if (!wdd->wd_data)
+ return -ENODEV;
+
+ /*
+ * __watchdog_ping will also retrigger hrtimer and therefore restore the
+ * ping worker if needed.
+ */
+ mutex_lock(&wd_data->lock);
+ if (watchdog_worker_should_ping(wd_data))
+ ret = __watchdog_ping(wd_data->wdd);
+ mutex_unlock(&wd_data->lock);
+
+ return ret;
+}
+
module_param(handle_boot_enabled, bool, 0444);
MODULE_PARM_DESC(handle_boot_enabled,
"Watchdog core auto-updates boot enabled watchdogs before userspace takes over (default="
diff --git a/drivers/xen/features.c b/drivers/xen/features.c
index 25c053b09605..7b591443833c 100644
--- a/drivers/xen/features.c
+++ b/drivers/xen/features.c
@@ -9,13 +9,26 @@
#include <linux/types.h>
#include <linux/cache.h>
#include <linux/export.h>
+#include <linux/printk.h>
#include <asm/xen/hypercall.h>
+#include <xen/xen.h>
#include <xen/interface/xen.h>
#include <xen/interface/version.h>
#include <xen/features.h>
+/*
+ * Linux kernel expects at least Xen 4.0.
+ *
+ * Assume some features to be available for that reason (depending on guest
+ * mode, of course).
+ */
+#define chk_required_feature(f) { \
+ if (!xen_feature(f)) \
+ panic("Xen: feature %s not available!\n", #f); \
+ }
+
u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
EXPORT_SYMBOL_GPL(xen_features);
@@ -31,4 +44,9 @@ void xen_setup_features(void)
for (j = 0; j < 32; j++)
xen_features[i * 32 + j] = !!(fi.submap & 1<<j);
}
+
+ if (xen_pv_domain()) {
+ chk_required_feature(XENFEAT_mmu_pt_update_preserve_ad);
+ chk_required_feature(XENFEAT_gnttab_map_avail_bits);
+ }
}
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index a3e7be96527d..1e7f6b1c0c97 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -266,20 +266,13 @@ static int find_grant_ptes(pte_t *pte, unsigned long addr, void *data)
{
struct gntdev_grant_map *map = data;
unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT;
- int flags = map->flags | GNTMAP_application_map | GNTMAP_contains_pte;
+ int flags = map->flags | GNTMAP_application_map | GNTMAP_contains_pte |
+ (1 << _GNTMAP_guest_avail0);
u64 pte_maddr;
BUG_ON(pgnr >= map->count);
pte_maddr = arbitrary_virt_to_machine(pte).maddr;
- /*
- * Set the PTE as special to force get_user_pages_fast() fall
- * back to the slow path. If this is not supported as part of
- * the grant map, it will be done afterwards.
- */
- if (xen_feature(XENFEAT_gnttab_map_avail_bits))
- flags |= (1 << _GNTMAP_guest_avail0);
-
gnttab_set_map_op(&map->map_ops[pgnr], pte_maddr, flags,
map->grants[pgnr].ref,
map->grants[pgnr].domid);
@@ -288,14 +281,6 @@ static int find_grant_ptes(pte_t *pte, unsigned long addr, void *data)
return 0;
}
-#ifdef CONFIG_X86
-static int set_grant_ptes_as_special(pte_t *pte, unsigned long addr, void *data)
-{
- set_pte_at(current->mm, addr, pte, pte_mkspecial(*pte));
- return 0;
-}
-#endif
-
int gntdev_map_grant_pages(struct gntdev_grant_map *map)
{
int i, err = 0;
@@ -1055,23 +1040,6 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
err = vm_map_pages_zero(vma, map->pages, map->count);
if (err)
goto out_put_map;
- } else {
-#ifdef CONFIG_X86
- /*
- * If the PTEs were not made special by the grant map
- * hypercall, do so here.
- *
- * This is racy since the mapping is already visible
- * to userspace but userspace should be well-behaved
- * enough to not touch it until the mmap() call
- * returns.
- */
- if (!xen_feature(XENFEAT_gnttab_map_avail_bits)) {
- apply_to_page_range(vma->vm_mm, vma->vm_start,
- vma->vm_end - vma->vm_start,
- set_grant_ptes_as_special, NULL);
- }
-#endif
}
return 0;
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 24d11861ac7d..643fe440c46e 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -100,7 +100,7 @@ static int is_xen_swiotlb_buffer(struct device *dev, dma_addr_t dma_addr)
* in our domain. Therefore _only_ check address within our domain.
*/
if (pfn_valid(PFN_DOWN(paddr)))
- return is_swiotlb_buffer(paddr);
+ return is_swiotlb_buffer(dev, paddr);
return 0;
}
@@ -164,7 +164,7 @@ int __ref xen_swiotlb_init(void)
int rc = -ENOMEM;
char *start;
- if (io_tlb_default_mem != NULL) {
+ if (io_tlb_default_mem.nslabs) {
pr_warn("swiotlb buffer already initialized\n");
return -EEXIST;
}
@@ -374,7 +374,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
if (dma_capable(dev, dev_addr, size, true) &&
!range_straddles_page_boundary(phys, size) &&
!xen_arch_need_swiotlb(dev, phys, dev_addr) &&
- swiotlb_force != SWIOTLB_FORCE)
+ !is_swiotlb_force_bounce(dev))
goto done;
/*
@@ -509,7 +509,7 @@ xen_swiotlb_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
out_unmap:
xen_swiotlb_unmap_sg(dev, sgl, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC);
sg_dma_len(sgl) = 0;
- return 0;
+ return -EIO;
}
static void
@@ -547,7 +547,7 @@ xen_swiotlb_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
static int
xen_swiotlb_dma_supported(struct device *hwdev, u64 mask)
{
- return xen_phys_to_dma(hwdev, io_tlb_default_mem->end - 1) <= mask;
+ return xen_phys_to_dma(hwdev, io_tlb_default_mem.end - 1) <= mask;
}
const struct dma_map_ops xen_swiotlb_dma_ops = {
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 61ce0d142eea..0c5e565aa8cf 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -33,8 +33,6 @@
#define pr_fmt(fmt) "xen-pvscsi: " fmt
-#include <stdarg.h>
-
#include <linux/module.h>
#include <linux/utsname.h>
#include <linux/interrupt.h>
diff --git a/drivers/xen/xenbus/xenbus.h b/drivers/xen/xenbus/xenbus.h
index 2a93b7c9c159..2754bdfadcb8 100644
--- a/drivers/xen/xenbus/xenbus.h
+++ b/drivers/xen/xenbus/xenbus.h
@@ -106,7 +106,7 @@ void xs_request_exit(struct xb_req_data *req);
int xenbus_match(struct device *_dev, struct device_driver *_drv);
int xenbus_dev_probe(struct device *_dev);
-int xenbus_dev_remove(struct device *_dev);
+void xenbus_dev_remove(struct device *_dev);
int xenbus_register_driver_common(struct xenbus_driver *drv,
struct xen_bus_type *bus,
struct module *owner,
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 0cd728961fce..e8bed1cb76ba 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -542,8 +542,7 @@ static int __xenbus_map_ring(struct xenbus_device *dev,
}
}
- if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, info->unmap, j))
- BUG();
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, info->unmap, j));
*leaked = false;
for (i = 0; i < j; i++) {
@@ -581,8 +580,7 @@ static int xenbus_unmap_ring(struct xenbus_device *dev, grant_handle_t *handles,
gnttab_set_unmap_op(&unmap[i], vaddrs[i],
GNTMAP_host_map, handles[i]);
- if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i))
- BUG();
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i));
err = GNTST_okay;
for (i = 0; i < nr_handles; i++) {
@@ -778,8 +776,7 @@ static int xenbus_unmap_ring_pv(struct xenbus_device *dev, void *vaddr)
unmap[i].handle = node->handles[i];
}
- if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i))
- BUG();
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i));
err = GNTST_okay;
leaked = false;
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 33d09b3f6211..bd003ca8acbe 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -325,7 +325,7 @@ fail:
}
EXPORT_SYMBOL_GPL(xenbus_dev_probe);
-int xenbus_dev_remove(struct device *_dev)
+void xenbus_dev_remove(struct device *_dev)
{
struct xenbus_device *dev = to_xenbus_device(_dev);
struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
@@ -355,8 +355,6 @@ int xenbus_dev_remove(struct device *_dev)
if (!drv->allow_rebind ||
xenbus_read_driver_state(dev->nodename) == XenbusStateClosing)
xenbus_switch_state(dev, XenbusStateClosed);
-
- return 0;
}
EXPORT_SYMBOL_GPL(xenbus_dev_remove);
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c
index 0dd7cbcec2b0..96f068830549 100644
--- a/drivers/zorro/zorro-driver.c
+++ b/drivers/zorro/zorro-driver.c
@@ -47,32 +47,26 @@ static int zorro_device_probe(struct device *dev)
struct zorro_driver *drv = to_zorro_driver(dev->driver);
struct zorro_dev *z = to_zorro_dev(dev);
- if (!z->driver && drv->probe) {
+ if (drv->probe) {
const struct zorro_device_id *id;
id = zorro_match_device(drv->id_table, z);
if (id)
error = drv->probe(z, id);
- if (error >= 0) {
- z->driver = drv;
+ if (error >= 0)
error = 0;
- }
}
return error;
}
-static int zorro_device_remove(struct device *dev)
+static void zorro_device_remove(struct device *dev)
{
struct zorro_dev *z = to_zorro_dev(dev);
struct zorro_driver *drv = to_zorro_driver(dev->driver);
- if (drv) {
- if (drv->remove)
- drv->remove(z);
- z->driver = NULL;
- }
- return 0;
+ if (drv->remove)
+ drv->remove(z);
}
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index bb1b286c49ae..c381499f5416 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -97,10 +97,13 @@ static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)
return acl;
}
-struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type)
+struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type, bool rcu)
{
struct v9fs_session_info *v9ses;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
v9ses = v9fs_inode2v9ses(inode);
if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) ||
((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) {
diff --git a/fs/9p/acl.h b/fs/9p/acl.h
index e4f7e882272b..d43c8949e807 100644
--- a/fs/9p/acl.h
+++ b/fs/9p/acl.h
@@ -16,7 +16,7 @@
#ifdef CONFIG_9P_FS_POSIX_ACL
extern int v9fs_get_acl(struct inode *, struct p9_fid *);
-extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type);
+extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type, bool rcu);
extern int v9fs_acl_chmod(struct inode *, struct p9_fid *);
extern int v9fs_set_create_acl(struct inode *, struct p9_fid *,
struct posix_acl *, struct posix_acl *);
diff --git a/fs/Kconfig b/fs/Kconfig
index b11bd4b387e1..d8207a1b8c44 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -136,6 +136,7 @@ menu "DOS/FAT/EXFAT/NT Filesystems"
source "fs/fat/Kconfig"
source "fs/exfat/Kconfig"
source "fs/ntfs/Kconfig"
+source "fs/ntfs3/Kconfig"
endmenu
endif # BLOCK
diff --git a/fs/Makefile b/fs/Makefile
index 354e2ba3ee67..2f21300851ae 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_CIFS) += cifs/
obj-$(CONFIG_SMB_SERVER) += ksmbd/
obj-$(CONFIG_HPFS_FS) += hpfs/
obj-$(CONFIG_NTFS_FS) += ntfs/
+obj-$(CONFIG_NTFS3_FS) += ntfs3/
obj-$(CONFIG_UFS_FS) += ufs/
obj-$(CONFIG_EFS_FS) += efs/
obj-$(CONFIG_JFFS2_FS) += jffs2/
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 48e16144c1f7..12b8fdcc445b 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -121,7 +121,7 @@ static const char *bad_inode_get_link(struct dentry *dentry,
return ERR_PTR(-EIO);
}
-static struct posix_acl *bad_inode_get_acl(struct inode *inode, int type)
+static struct posix_acl *bad_inode_get_acl(struct inode *inode, int type, bool rcu)
{
return ERR_PTR(-EIO);
}
diff --git a/fs/befs/debug.c b/fs/befs/debug.c
index eb7bd6c692c7..02fa66fb82c2 100644
--- a/fs/befs/debug.c
+++ b/fs/befs/debug.c
@@ -14,7 +14,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#ifdef __KERNEL__
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 145917f734fe..0dcfc691e7e2 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -221,8 +221,7 @@ static int load_aout_binary(struct linux_binprm * bprm)
}
error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
- PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
fd_offset);
if (error != N_TXTADDR(ex))
@@ -230,7 +229,7 @@ static int load_aout_binary(struct linux_binprm * bprm)
error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
fd_offset + ex.a_text);
if (error != N_DATADDR(ex))
return error;
@@ -309,7 +308,7 @@ static int load_aout_library(struct file *file)
/* Now use mmap to map the library into memory. */
error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
N_TXTOFF(ex));
retval = error;
if (error != start_addr)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 439ed81e755a..69d900a8473d 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -622,7 +622,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
eppnt = interp_elf_phdata;
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) {
- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+ int elf_type = MAP_PRIVATE;
int elf_prot = make_prot(eppnt->p_flags, arch_state,
true, true);
unsigned long vaddr = 0;
@@ -1070,7 +1070,7 @@ out_free_interp:
elf_prot = make_prot(elf_ppnt->p_flags, &arch_state,
!!interpreter, false);
- elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
+ elf_flags = MAP_PRIVATE;
vaddr = elf_ppnt->p_vaddr;
/*
@@ -1384,7 +1384,7 @@ static int load_elf_library(struct file *file)
(eppnt->p_filesz +
ELF_PAGEOFFSET(eppnt->p_vaddr)),
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED_NOREPLACE | MAP_PRIVATE,
(eppnt->p_offset -
ELF_PAGEOFFSET(eppnt->p_vaddr)));
if (error != ELF_PAGESTART(eppnt->p_vaddr))
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index cf4028487dcc..6d8fd6030cbb 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1041,7 +1041,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
if (phdr->p_flags & PF_W) prot |= PROT_WRITE;
if (phdr->p_flags & PF_X) prot |= PROT_EXEC;
- flags = MAP_PRIVATE | MAP_DENYWRITE;
+ flags = MAP_PRIVATE;
maddr = 0;
switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index c9f9789e828f..0a0d0eccee4e 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -16,13 +16,16 @@
#include "btrfs_inode.h"
#include "xattr.h"
-struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
+struct posix_acl *btrfs_get_acl(struct inode *inode, int type, bool rcu)
{
int size;
const char *name;
char *value = NULL;
struct posix_acl *acl;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch (type) {
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f07c82fafa04..dff2c8a3e059 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3706,7 +3706,7 @@ static inline int __btrfs_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag)
/* acl.c */
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
-struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
+struct posix_acl *btrfs_get_acl(struct inode *inode, int type, bool rcu);
int btrfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
int btrfs_init_acl(struct btrfs_trans_handle *trans,
diff --git a/fs/buffer.c b/fs/buffer.c
index bd6a9e9fbd64..ab7573d72dd7 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -3268,33 +3268,6 @@ out:
EXPORT_SYMBOL(try_to_free_buffers);
/*
- * There are no bdflush tunables left. But distributions are
- * still running obsolete flush daemons, so we terminate them here.
- *
- * Use of bdflush() is deprecated and will be removed in a future kernel.
- * The `flush-X' kernel threads fully replace bdflush daemons and this call.
- */
-SYSCALL_DEFINE2(bdflush, int, func, long, data)
-{
- static int msg_count;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (msg_count < 5) {
- msg_count++;
- printk(KERN_INFO
- "warning: process `%s' used the obsolete bdflush"
- " system call\n", current->comm);
- printk(KERN_INFO "Fix your initscripts?\n");
- }
-
- if (func == 1)
- do_exit(0);
- return 0;
-}
-
-/*
* Buffer-head allocation
*/
static struct kmem_cache *bh_cachep __read_mostly;
diff --git a/fs/cachefiles/Kconfig b/fs/cachefiles/Kconfig
index ff9ca55a9ae9..6827b40f7ddc 100644
--- a/fs/cachefiles/Kconfig
+++ b/fs/cachefiles/Kconfig
@@ -19,22 +19,3 @@ config CACHEFILES_DEBUG
caching on files module. If this is set, the debugging output may be
enabled by setting bits in /sys/modules/cachefiles/parameter/debug or
by including a debugging specifier in /etc/cachefilesd.conf.
-
-config CACHEFILES_HISTOGRAM
- bool "Gather latency information on CacheFiles"
- depends on CACHEFILES && PROC_FS
- help
-
- This option causes latency information to be gathered on CacheFiles
- operation and exported through file:
-
- /proc/fs/cachefiles/histogram
-
- The generation of this histogram adds a certain amount of overhead to
- execution as there are a number of points at which data is gathered,
- and on a multi-CPU system these may be on cachelines that keep
- bouncing between CPUs. On the other hand, the histogram may be
- useful for debugging purposes. Saying 'N' here is recommended.
-
- See Documentation/filesystems/caching/cachefiles.rst for more
- information.
diff --git a/fs/cachefiles/Makefile b/fs/cachefiles/Makefile
index 2227dc2d5498..02fd17731769 100644
--- a/fs/cachefiles/Makefile
+++ b/fs/cachefiles/Makefile
@@ -15,6 +15,4 @@ cachefiles-y := \
security.o \
xattr.o
-cachefiles-$(CONFIG_CACHEFILES_HISTOGRAM) += proc.o
-
obj-$(CONFIG_CACHEFILES) := cachefiles.o
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index 38bb7764b454..d463d89f5db8 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -108,8 +108,6 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
atomic_set(&fsdef->usage, 1);
fsdef->type = FSCACHE_COOKIE_TYPE_INDEX;
- _debug("- fsdef %p", fsdef);
-
/* look up the directory at the root of the cache */
ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path);
if (ret < 0)
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index da3948fdb615..da28ac1fa225 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -33,7 +33,7 @@ static struct fscache_object *cachefiles_alloc_object(
cache = container_of(_cache, struct cachefiles_cache, cache);
- _enter("{%s},%p,", cache->cache.identifier, cookie);
+ _enter("{%s},%x,", cache->cache.identifier, cookie->debug_id);
lookup_data = kmalloc(sizeof(*lookup_data), cachefiles_gfp);
if (!lookup_data)
@@ -96,7 +96,7 @@ static struct fscache_object *cachefiles_alloc_object(
lookup_data->key = key;
object->lookup_data = lookup_data;
- _leave(" = %p [%p]", &object->fscache, lookup_data);
+ _leave(" = %x [%p]", object->fscache.debug_id, lookup_data);
return &object->fscache;
nomem_key:
@@ -379,7 +379,7 @@ static void cachefiles_sync_cache(struct fscache_cache *_cache)
const struct cred *saved_cred;
int ret;
- _enter("%p", _cache);
+ _enter("%s", _cache->tag->name);
cache = container_of(_cache, struct cachefiles_cache, cache);
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 4ed83aa5253b..0a511c36dab8 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -181,31 +181,6 @@ extern int cachefiles_check_in_use(struct cachefiles_cache *cache,
struct dentry *dir, char *filename);
/*
- * proc.c
- */
-#ifdef CONFIG_CACHEFILES_HISTOGRAM
-extern atomic_t cachefiles_lookup_histogram[HZ];
-extern atomic_t cachefiles_mkdir_histogram[HZ];
-extern atomic_t cachefiles_create_histogram[HZ];
-
-extern int __init cachefiles_proc_init(void);
-extern void cachefiles_proc_cleanup(void);
-static inline
-void cachefiles_hist(atomic_t histogram[], unsigned long start_jif)
-{
- unsigned long jif = jiffies - start_jif;
- if (jif >= HZ)
- jif = HZ - 1;
- atomic_inc(&histogram[jif]);
-}
-
-#else
-#define cachefiles_proc_init() (0)
-#define cachefiles_proc_cleanup() do {} while (0)
-#define cachefiles_hist(hist, start_jif) do {} while (0)
-#endif
-
-/*
* rdwr.c
*/
extern int cachefiles_read_or_alloc_page(struct fscache_retrieval *,
diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c
index b13fb45fc3f3..fac2e8e7b533 100644
--- a/fs/cachefiles/io.c
+++ b/fs/cachefiles/io.c
@@ -70,7 +70,7 @@ static int cachefiles_read(struct netfs_cache_resources *cres,
_enter("%pD,%li,%llx,%zx/%llx",
file, file_inode(file)->i_ino, start_pos, len,
- i_size_read(file->f_inode));
+ i_size_read(file_inode(file)));
/* If the caller asked us to seek for data before doing the read, then
* we should do that now. If we find a gap, we fill it with zeros.
@@ -194,7 +194,7 @@ static int cachefiles_write(struct netfs_cache_resources *cres,
_enter("%pD,%li,%llx,%zx/%llx",
file, file_inode(file)->i_ino, start_pos, len,
- i_size_read(file->f_inode));
+ i_size_read(file_inode(file)));
ki = kzalloc(sizeof(struct cachefiles_kiocb), GFP_KERNEL);
if (!ki)
@@ -410,7 +410,7 @@ int cachefiles_begin_read_operation(struct netfs_read_request *rreq,
rreq->cache_resources.cache_priv = op;
rreq->cache_resources.cache_priv2 = file;
rreq->cache_resources.ops = &cachefiles_netfs_cache_ops;
- rreq->cookie_debug_id = object->fscache.debug_id;
+ rreq->cache_resources.debug_id = object->fscache.debug_id;
_leave("");
return 0;
diff --git a/fs/cachefiles/key.c b/fs/cachefiles/key.c
index be96f5fc5cac..7f94efc97e23 100644
--- a/fs/cachefiles/key.c
+++ b/fs/cachefiles/key.c
@@ -150,6 +150,6 @@ char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type)
key[len++] = 0;
key[len] = 0;
- _leave(" = %p %d", key, len);
+ _leave(" = %s %d", key, len);
return key;
}
diff --git a/fs/cachefiles/main.c b/fs/cachefiles/main.c
index ddf0cd58d60c..9c8d34c49b12 100644
--- a/fs/cachefiles/main.c
+++ b/fs/cachefiles/main.c
@@ -69,15 +69,9 @@ static int __init cachefiles_init(void)
goto error_object_jar;
}
- ret = cachefiles_proc_init();
- if (ret < 0)
- goto error_proc;
-
pr_info("Loaded\n");
return 0;
-error_proc:
- kmem_cache_destroy(cachefiles_object_jar);
error_object_jar:
misc_deregister(&cachefiles_dev);
error_dev:
@@ -94,7 +88,6 @@ static void __exit cachefiles_exit(void)
{
pr_info("Unloading\n");
- cachefiles_proc_cleanup();
kmem_cache_destroy(cachefiles_object_jar);
misc_deregister(&cachefiles_dev);
}
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 7bf0732ae25c..a9aca5ab5970 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -39,18 +39,18 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
pr_err("%sops=%u inp=%u exc=%u\n",
prefix, object->fscache.n_ops, object->fscache.n_in_progress,
object->fscache.n_exclusive);
- pr_err("%sparent=%p\n",
- prefix, object->fscache.parent);
+ pr_err("%sparent=%x\n",
+ prefix, object->fscache.parent ? object->fscache.parent->debug_id : 0);
spin_lock(&object->fscache.lock);
cookie = object->fscache.cookie;
if (cookie) {
- pr_err("%scookie=%p [pr=%p nd=%p fl=%lx]\n",
+ pr_err("%scookie=%x [pr=%x nd=%p fl=%lx]\n",
prefix,
- object->fscache.cookie,
- object->fscache.cookie->parent,
- object->fscache.cookie->netfs_data,
- object->fscache.cookie->flags);
+ cookie->debug_id,
+ cookie->parent ? cookie->parent->debug_id : 0,
+ cookie->netfs_data,
+ cookie->flags);
pr_err("%skey=[%u] '", prefix, cookie->key_len);
k = (cookie->key_len <= sizeof(cookie->inline_key)) ?
cookie->inline_key : cookie->key;
@@ -110,7 +110,7 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
/* found the dentry for */
found_dentry:
- kdebug("preemptive burial: OBJ%x [%s] %p",
+ kdebug("preemptive burial: OBJ%x [%s] %pd",
object->fscache.debug_id,
object->fscache.state->name,
dentry);
@@ -140,7 +140,7 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
struct rb_node **_p, *_parent = NULL;
struct dentry *dentry;
- _enter(",%p", object);
+ _enter(",%x", object->fscache.debug_id);
try_again:
write_lock(&cache->active_lock);
@@ -298,8 +298,6 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
_enter(",'%pd','%pd'", dir, rep);
- _debug("remove %p from %p", rep, dir);
-
/* non-directories can just be unlinked */
if (!d_is_dir(rep)) {
_debug("unlink stale object");
@@ -446,7 +444,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
struct dentry *dir;
int ret;
- _enter(",OBJ%x{%p}", object->fscache.debug_id, object->dentry);
+ _enter(",OBJ%x{%pd}", object->fscache.debug_id, object->dentry);
ASSERT(object->dentry);
ASSERT(d_backing_inode(object->dentry));
@@ -496,11 +494,10 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
struct dentry *dir, *next = NULL;
struct inode *inode;
struct path path;
- unsigned long start;
const char *name;
int ret, nlen;
- _enter("OBJ%x{%p},OBJ%x,%s,",
+ _enter("OBJ%x{%pd},OBJ%x,%s,",
parent->fscache.debug_id, parent->dentry,
object->fscache.debug_id, key);
@@ -535,9 +532,7 @@ lookup_again:
inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
- start = jiffies;
next = lookup_one_len(name, dir, nlen);
- cachefiles_hist(cachefiles_lookup_histogram, start);
if (IS_ERR(next)) {
trace_cachefiles_lookup(object, next, NULL);
goto lookup_error;
@@ -545,7 +540,7 @@ lookup_again:
inode = d_backing_inode(next);
trace_cachefiles_lookup(object, next, inode);
- _debug("next -> %p %s", next, inode ? "positive" : "negative");
+ _debug("next -> %pd %s", next, inode ? "positive" : "negative");
if (!key)
object->new = !inode;
@@ -568,9 +563,7 @@ lookup_again:
ret = security_path_mkdir(&path, next, 0);
if (ret < 0)
goto create_error;
- start = jiffies;
ret = vfs_mkdir(&init_user_ns, d_inode(dir), next, 0);
- cachefiles_hist(cachefiles_mkdir_histogram, start);
if (!key)
trace_cachefiles_mkdir(object, next, ret);
if (ret < 0)
@@ -583,8 +576,8 @@ lookup_again:
}
ASSERT(d_backing_inode(next));
- _debug("mkdir -> %p{%p{ino=%lu}}",
- next, d_backing_inode(next), d_backing_inode(next)->i_ino);
+ _debug("mkdir -> %pd{ino=%lu}",
+ next, d_backing_inode(next)->i_ino);
} else if (!d_can_lookup(next)) {
pr_err("inode %lu is not a directory\n",
@@ -604,18 +597,16 @@ lookup_again:
ret = security_path_mknod(&path, next, S_IFREG, 0);
if (ret < 0)
goto create_error;
- start = jiffies;
ret = vfs_create(&init_user_ns, d_inode(dir), next,
S_IFREG, true);
- cachefiles_hist(cachefiles_create_histogram, start);
trace_cachefiles_create(object, next, ret);
if (ret < 0)
goto create_error;
ASSERT(d_backing_inode(next));
- _debug("create -> %p{%p{ino=%lu}}",
- next, d_backing_inode(next), d_backing_inode(next)->i_ino);
+ _debug("create -> %pd{ino=%lu}",
+ next, d_backing_inode(next)->i_ino);
} else if (!d_can_lookup(next) &&
!d_is_reg(next)
@@ -765,7 +756,6 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
const char *dirname)
{
struct dentry *subdir;
- unsigned long start;
struct path path;
int ret;
@@ -775,16 +765,14 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
inode_lock(d_inode(dir));
retry:
- start = jiffies;
subdir = lookup_one_len(dirname, dir, strlen(dirname));
- cachefiles_hist(cachefiles_lookup_histogram, start);
if (IS_ERR(subdir)) {
if (PTR_ERR(subdir) == -ENOMEM)
goto nomem_d_alloc;
goto lookup_error;
}
- _debug("subdir -> %p %s",
+ _debug("subdir -> %pd %s",
subdir, d_backing_inode(subdir) ? "positive" : "negative");
/* we need to create the subdir if it doesn't exist yet */
@@ -810,10 +798,8 @@ retry:
}
ASSERT(d_backing_inode(subdir));
- _debug("mkdir -> %p{%p{ino=%lu}}",
- subdir,
- d_backing_inode(subdir),
- d_backing_inode(subdir)->i_ino);
+ _debug("mkdir -> %pd{ino=%lu}",
+ subdir, d_backing_inode(subdir)->i_ino);
}
inode_unlock(d_inode(dir));
@@ -876,7 +862,6 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
struct cachefiles_object *object;
struct rb_node *_n;
struct dentry *victim;
- unsigned long start;
int ret;
//_enter(",%pd/,%s",
@@ -885,13 +870,11 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
/* look up the victim */
inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
- start = jiffies;
victim = lookup_one_len(filename, dir, strlen(filename));
- cachefiles_hist(cachefiles_lookup_histogram, start);
if (IS_ERR(victim))
goto lookup_error;
- //_debug("victim -> %p %s",
+ //_debug("victim -> %pd %s",
// victim, d_backing_inode(victim) ? "positive" : "negative");
/* if the object is no longer there then we probably retired the object
@@ -922,7 +905,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
read_unlock(&cache->active_lock);
- //_leave(" = %p", victim);
+ //_leave(" = %pd", victim);
return victim;
object_in_use:
@@ -968,7 +951,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
if (IS_ERR(victim))
return PTR_ERR(victim);
- _debug("victim -> %p %s",
+ _debug("victim -> %pd %s",
victim, d_backing_inode(victim) ? "positive" : "negative");
/* okay... the victim is not being used so we can cull it
diff --git a/fs/cachefiles/proc.c b/fs/cachefiles/proc.c
deleted file mode 100644
index 6e67aea0f24e..000000000000
--- a/fs/cachefiles/proc.c
+++ /dev/null
@@ -1,114 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* CacheFiles statistics
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- */
-
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include "internal.h"
-
-atomic_t cachefiles_lookup_histogram[HZ];
-atomic_t cachefiles_mkdir_histogram[HZ];
-atomic_t cachefiles_create_histogram[HZ];
-
-/*
- * display the latency histogram
- */
-static int cachefiles_histogram_show(struct seq_file *m, void *v)
-{
- unsigned long index;
- unsigned x, y, z, t;
-
- switch ((unsigned long) v) {
- case 1:
- seq_puts(m, "JIFS SECS LOOKUPS MKDIRS CREATES\n");
- return 0;
- case 2:
- seq_puts(m, "===== ===== ========= ========= =========\n");
- return 0;
- default:
- index = (unsigned long) v - 3;
- x = atomic_read(&cachefiles_lookup_histogram[index]);
- y = atomic_read(&cachefiles_mkdir_histogram[index]);
- z = atomic_read(&cachefiles_create_histogram[index]);
- if (x == 0 && y == 0 && z == 0)
- return 0;
-
- t = (index * 1000) / HZ;
-
- seq_printf(m, "%4lu 0.%03u %9u %9u %9u\n", index, t, x, y, z);
- return 0;
- }
-}
-
-/*
- * set up the iterator to start reading from the first line
- */
-static void *cachefiles_histogram_start(struct seq_file *m, loff_t *_pos)
-{
- if ((unsigned long long)*_pos >= HZ + 2)
- return NULL;
- if (*_pos == 0)
- *_pos = 1;
- return (void *)(unsigned long) *_pos;
-}
-
-/*
- * move to the next line
- */
-static void *cachefiles_histogram_next(struct seq_file *m, void *v, loff_t *pos)
-{
- (*pos)++;
- return (unsigned long long)*pos > HZ + 2 ?
- NULL : (void *)(unsigned long) *pos;
-}
-
-/*
- * clean up after reading
- */
-static void cachefiles_histogram_stop(struct seq_file *m, void *v)
-{
-}
-
-static const struct seq_operations cachefiles_histogram_ops = {
- .start = cachefiles_histogram_start,
- .stop = cachefiles_histogram_stop,
- .next = cachefiles_histogram_next,
- .show = cachefiles_histogram_show,
-};
-
-/*
- * initialise the /proc/fs/cachefiles/ directory
- */
-int __init cachefiles_proc_init(void)
-{
- _enter("");
-
- if (!proc_mkdir("fs/cachefiles", NULL))
- goto error_dir;
-
- if (!proc_create_seq("fs/cachefiles/histogram", S_IFREG | 0444, NULL,
- &cachefiles_histogram_ops))
- goto error_histogram;
-
- _leave(" = 0");
- return 0;
-
-error_histogram:
- remove_proc_entry("fs/cachefiles", NULL);
-error_dir:
- _leave(" = -ENOMEM");
- return -ENOMEM;
-}
-
-/*
- * clean up the /proc/fs/cachefiles/ directory
- */
-void cachefiles_proc_cleanup(void)
-{
- remove_proc_entry("fs/cachefiles/histogram", NULL);
- remove_proc_entry("fs/cachefiles", NULL);
-}
diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c
index a591b5e09637..9e82de668595 100644
--- a/fs/cachefiles/xattr.c
+++ b/fs/cachefiles/xattr.c
@@ -36,7 +36,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
else
snprintf(type, 3, "%02x", object->fscache.cookie->def->type);
- _enter("%p{%s}", object, type);
+ _enter("%x{%s}", object->fscache.debug_id, type);
/* attempt to install a type label directly */
ret = vfs_setxattr(&init_user_ns, dentry, cachefiles_xattr_cache, type,
@@ -134,7 +134,7 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,
if (!dentry)
return -ESTALE;
- _enter("%p,#%d", object, auxdata->len);
+ _enter("%x,#%d", object->fscache.debug_id, auxdata->len);
/* attempt to install the cache metadata directly */
_debug("SET #%u", auxdata->len);
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 529af59d9fd3..f4fc8e0b847c 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -29,7 +29,7 @@ static inline void ceph_set_cached_acl(struct inode *inode,
spin_unlock(&ci->i_ceph_lock);
}
-struct posix_acl *ceph_get_acl(struct inode *inode, int type)
+struct posix_acl *ceph_get_acl(struct inode *inode, int type, bool rcu)
{
int size;
unsigned int retry_cnt = 0;
@@ -37,6 +37,9 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
char *value = NULL;
struct posix_acl *acl;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch (type) {
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index b1a363641beb..c30258f95e37 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1088,7 +1088,7 @@ void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx);
/* acl.c */
#ifdef CONFIG_CEPH_FS_POSIX_ACL
-struct posix_acl *ceph_get_acl(struct inode *, int);
+struct posix_acl *ceph_get_acl(struct inode *, int, bool);
int ceph_set_acl(struct user_namespace *mnt_userns,
struct inode *inode, struct posix_acl *acl, int type);
int ceph_pre_init_acls(struct inode *dir, umode_t *mode,
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index ac5e0c0e9181..1466b5d01cbb 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -45,7 +45,7 @@ static void configfs_d_iput(struct dentry * dentry,
/*
* Set sd->s_dentry to null only when this dentry is the one
* that is going to be killed. Otherwise configfs_d_iput may
- * run just after configfs_attach_attr and set sd->s_dentry to
+ * run just after configfs_lookup and set sd->s_dentry to
* NULL even it's still in use.
*/
if (sd->s_dentry == dentry)
@@ -417,44 +417,16 @@ static void configfs_remove_dir(struct config_item * item)
dput(dentry);
}
-
-/* attaches attribute's configfs_dirent to the dentry corresponding to the
- * attribute file
- */
-static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * dentry)
-{
- struct configfs_attribute * attr = sd->s_element;
- struct inode *inode;
-
- spin_lock(&configfs_dirent_lock);
- dentry->d_fsdata = configfs_get(sd);
- sd->s_dentry = dentry;
- spin_unlock(&configfs_dirent_lock);
-
- inode = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG);
- if (IS_ERR(inode)) {
- configfs_put(sd);
- return PTR_ERR(inode);
- }
- if (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) {
- inode->i_size = 0;
- inode->i_fop = &configfs_bin_file_operations;
- } else {
- inode->i_size = PAGE_SIZE;
- inode->i_fop = &configfs_file_operations;
- }
- d_add(dentry, inode);
- return 0;
-}
-
static struct dentry * configfs_lookup(struct inode *dir,
struct dentry *dentry,
unsigned int flags)
{
struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
struct configfs_dirent * sd;
- int found = 0;
- int err;
+ struct inode *inode = NULL;
+
+ if (dentry->d_name.len > NAME_MAX)
+ return ERR_PTR(-ENAMETOOLONG);
/*
* Fake invisibility if dir belongs to a group/default groups hierarchy
@@ -464,36 +436,39 @@ static struct dentry * configfs_lookup(struct inode *dir,
* not complete their initialization, since the dentries of the
* attributes won't be instantiated.
*/
- err = -ENOENT;
if (!configfs_dirent_is_ready(parent_sd))
- goto out;
+ return ERR_PTR(-ENOENT);
+ spin_lock(&configfs_dirent_lock);
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
- if (sd->s_type & CONFIGFS_NOT_PINNED) {
- const unsigned char * name = configfs_get_name(sd);
+ if ((sd->s_type & CONFIGFS_NOT_PINNED) &&
+ !strcmp(configfs_get_name(sd), dentry->d_name.name)) {
+ struct configfs_attribute *attr = sd->s_element;
+ umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
- if (strcmp(name, dentry->d_name.name))
- continue;
+ dentry->d_fsdata = configfs_get(sd);
+ sd->s_dentry = dentry;
+ spin_unlock(&configfs_dirent_lock);
- found = 1;
- err = configfs_attach_attr(sd, dentry);
- break;
+ inode = configfs_create(dentry, mode);
+ if (IS_ERR(inode)) {
+ configfs_put(sd);
+ return ERR_CAST(inode);
+ }
+ if (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) {
+ inode->i_size = 0;
+ inode->i_fop = &configfs_bin_file_operations;
+ } else {
+ inode->i_size = PAGE_SIZE;
+ inode->i_fop = &configfs_file_operations;
+ }
+ goto done;
}
}
-
- if (!found) {
- /*
- * If it doesn't exist and it isn't a NOT_PINNED item,
- * it must be negative.
- */
- if (dentry->d_name.len > NAME_MAX)
- return ERR_PTR(-ENAMETOOLONG);
- d_add(dentry, NULL);
- return NULL;
- }
-
-out:
- return ERR_PTR(err);
+ spin_unlock(&configfs_dirent_lock);
+done:
+ d_add(dentry, inode);
+ return NULL;
}
/*
diff --git a/fs/d_path.c b/fs/d_path.c
index 23a53f7b5c71..cd60c7535181 100644
--- a/fs/d_path.c
+++ b/fs/d_path.c
@@ -22,13 +22,57 @@ static char *extract_string(struct prepend_buffer *p)
return ERR_PTR(-ENAMETOOLONG);
}
-static void prepend(struct prepend_buffer *p, const char *str, int namelen)
+static bool prepend_char(struct prepend_buffer *p, unsigned char c)
{
- p->len -= namelen;
- if (likely(p->len >= 0)) {
- p->buf -= namelen;
- memcpy(p->buf, str, namelen);
+ if (likely(p->len > 0)) {
+ p->len--;
+ *--p->buf = c;
+ return true;
+ }
+ p->len = -1;
+ return false;
+}
+
+/*
+ * The source of the prepend data can be an optimistoc load
+ * of a dentry name and length. And because we don't hold any
+ * locks, the length and the pointer to the name may not be
+ * in sync if a concurrent rename happens, and the kernel
+ * copy might fault as a result.
+ *
+ * The end result will correct itself when we check the
+ * rename sequence count, but we need to be able to handle
+ * the fault gracefully.
+ */
+static bool prepend_copy(void *dst, const void *src, int len)
+{
+ if (unlikely(copy_from_kernel_nofault(dst, src, len))) {
+ memset(dst, 'x', len);
+ return false;
}
+ return true;
+}
+
+static bool prepend(struct prepend_buffer *p, const char *str, int namelen)
+{
+ // Already overflowed?
+ if (p->len < 0)
+ return false;
+
+ // Will overflow?
+ if (p->len < namelen) {
+ // Fill as much as possible from the end of the name
+ str += namelen - p->len;
+ p->buf -= p->len;
+ prepend_copy(p->buf, str, p->len);
+ p->len = -1;
+ return false;
+ }
+
+ // Fits fully
+ p->len -= namelen;
+ p->buf -= namelen;
+ return prepend_copy(p->buf, str, namelen);
}
/**
@@ -40,32 +84,21 @@ static void prepend(struct prepend_buffer *p, const char *str, int namelen)
* With RCU path tracing, it may race with d_move(). Use READ_ONCE() to
* make sure that either the old or the new name pointer and length are
* fetched. However, there may be mismatch between length and pointer.
- * The length cannot be trusted, we need to copy it byte-by-byte until
- * the length is reached or a null byte is found. It also prepends "/" at
+ * But since the length cannot be trusted, we need to copy the name very
+ * carefully when doing the prepend_copy(). It also prepends "/" at
* the beginning of the name. The sequence number check at the caller will
* retry it again when a d_move() does happen. So any garbage in the buffer
* due to mismatched pointer and length will be discarded.
*
- * Load acquire is needed to make sure that we see that terminating NUL.
+ * Load acquire is needed to make sure that we see the new name data even
+ * if we might get the length wrong.
*/
static bool prepend_name(struct prepend_buffer *p, const struct qstr *name)
{
const char *dname = smp_load_acquire(&name->name); /* ^^^ */
u32 dlen = READ_ONCE(name->len);
- char *s;
- p->len -= dlen + 1;
- if (unlikely(p->len < 0))
- return false;
- s = p->buf -= dlen + 1;
- *s++ = '/';
- while (dlen--) {
- char c = *dname++;
- if (!c)
- break;
- *s++ = c;
- }
- return true;
+ return prepend(p, dname, dlen) && prepend_char(p, '/');
}
static int __prepend_path(const struct dentry *dentry, const struct mount *mnt,
@@ -158,7 +191,7 @@ restart:
b = *p;
if (b.len == p->len)
- prepend(&b, "/", 1);
+ prepend_char(&b, '/');
*p = b;
return error;
@@ -186,7 +219,7 @@ char *__d_path(const struct path *path,
{
DECLARE_BUFFER(b, buf, buflen);
- prepend(&b, "", 1);
+ prepend_char(&b, 0);
if (unlikely(prepend_path(path, root, &b) > 0))
return NULL;
return extract_string(&b);
@@ -198,7 +231,7 @@ char *d_absolute_path(const struct path *path,
struct path root = {};
DECLARE_BUFFER(b, buf, buflen);
- prepend(&b, "", 1);
+ prepend_char(&b, 0);
if (unlikely(prepend_path(path, &root, &b) > 1))
return ERR_PTR(-EINVAL);
return extract_string(&b);
@@ -255,7 +288,7 @@ char *d_path(const struct path *path, char *buf, int buflen)
if (unlikely(d_unlinked(path->dentry)))
prepend(&b, " (deleted)", 11);
else
- prepend(&b, "", 1);
+ prepend_char(&b, 0);
prepend_path(path, &root, &b);
rcu_read_unlock();
@@ -290,7 +323,7 @@ char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
/* these dentries are never renamed, so d_lock is not needed */
prepend(&b, " (deleted)", 11);
prepend(&b, dentry->d_name.name, dentry->d_name.len);
- prepend(&b, "/", 1);
+ prepend_char(&b, '/');
return extract_string(&b);
}
@@ -324,7 +357,7 @@ restart:
}
done_seqretry(&rename_lock, seq);
if (b.len == p->len)
- prepend(&b, "/", 1);
+ prepend_char(&b, '/');
return extract_string(&b);
}
@@ -332,7 +365,7 @@ char *dentry_path_raw(const struct dentry *dentry, char *buf, int buflen)
{
DECLARE_BUFFER(b, buf, buflen);
- prepend(&b, "", 1);
+ prepend_char(&b, 0);
return __dentry_path(dentry, &b);
}
EXPORT_SYMBOL(dentry_path_raw);
@@ -344,7 +377,7 @@ char *dentry_path(const struct dentry *dentry, char *buf, int buflen)
if (unlikely(d_unlinked(dentry)))
prepend(&b, "//deleted", 10);
else
- prepend(&b, "", 1);
+ prepend_char(&b, 0);
return __dentry_path(dentry, &b);
}
@@ -397,7 +430,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
unsigned len;
DECLARE_BUFFER(b, page, PATH_MAX);
- prepend(&b, "", 1);
+ prepend_char(&b, 0);
if (unlikely(prepend_path(&pwd, &root, &b) > 0))
prepend(&b, "(unreachable)", 13);
rcu_read_unlock();
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index df00231d3ecc..7d162b0efbf0 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -179,8 +179,10 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
if (!fops_get(real_fops)) {
#ifdef CONFIG_MODULES
if (real_fops->owner &&
- real_fops->owner->state == MODULE_STATE_GOING)
+ real_fops->owner->state == MODULE_STATE_GOING) {
+ r = -ENXIO;
goto out;
+ }
#endif
/* Huh? Module did not clean up after itself at exit? */
@@ -314,8 +316,10 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
if (!fops_get(real_fops)) {
#ifdef CONFIG_MODULES
if (real_fops->owner &&
- real_fops->owner->state == MODULE_STATE_GOING)
+ real_fops->owner->state == MODULE_STATE_GOING) {
+ r = -ENXIO;
goto out;
+ }
#endif
/* Huh? Module did not cleanup after itself at exit? */
diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c
index 10c36ae1a8f9..45ebbe602bbf 100644
--- a/fs/dlm/dir.c
+++ b/fs/dlm/dir.c
@@ -85,8 +85,10 @@ int dlm_recover_directory(struct dlm_ls *ls)
for (;;) {
int left;
error = dlm_recovery_stopped(ls);
- if (error)
+ if (error) {
+ error = -EINTR;
goto out_free;
+ }
error = dlm_rcom_names(ls, memb->nodeid,
last_name, last_len);
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 91d1ca3a121a..5f57538b5d45 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -468,7 +468,7 @@ struct dlm_rcom {
struct dlm_opt_header {
uint16_t t_type;
uint16_t t_length;
- uint32_t o_pad;
+ uint32_t t_pad;
/* need to be 8 byte aligned */
char t_value[];
};
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index d71aba8c3e64..10eddfa6c3d7 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -498,7 +498,7 @@ static int new_lockspace(const char *name, const char *cluster,
ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
DLM_LSFL_NEWEXCL));
- size = dlm_config.ci_rsbtbl_size;
+ size = READ_ONCE(dlm_config.ci_rsbtbl_size);
ls->ls_rsbtbl_size = size;
ls->ls_rsbtbl = vmalloc(array_size(size, sizeof(struct dlm_rsbtable)));
@@ -793,6 +793,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
if (ls_count == 1) {
dlm_scand_stop();
+ dlm_clear_members(ls);
dlm_midcomms_shutdown();
}
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 0ea9ae35da0b..8f715c620e1f 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -84,9 +84,7 @@ struct connection {
struct list_head writequeue; /* List of outgoing writequeue_entries */
spinlock_t writequeue_lock;
atomic_t writequeue_cnt;
- void (*connect_action) (struct connection *); /* What to do to connect */
- void (*shutdown_action)(struct connection *con); /* What to do to shutdown */
- bool (*eof_condition)(struct connection *con); /* What to do to eof check */
+ struct mutex wq_alloc;
int retries;
#define MAX_CONNECT_RETRIES 3
struct hlist_node list;
@@ -145,6 +143,24 @@ struct dlm_node_addr {
struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
};
+struct dlm_proto_ops {
+ bool try_new_addr;
+ const char *name;
+ int proto;
+
+ int (*connect)(struct connection *con, struct socket *sock,
+ struct sockaddr *addr, int addr_len);
+ void (*sockopts)(struct socket *sock);
+ int (*bind)(struct socket *sock);
+ int (*listen_validate)(void);
+ void (*listen_sockopts)(struct socket *sock);
+ int (*listen_bind)(struct socket *sock);
+ /* What to do to shutdown */
+ void (*shutdown_action)(struct connection *con);
+ /* What to do to eof check */
+ bool (*eof_condition)(struct connection *con);
+};
+
static struct listen_sock_callbacks {
void (*sk_error_report)(struct sock *);
void (*sk_data_ready)(struct sock *);
@@ -168,12 +184,26 @@ static struct hlist_head connection_hash[CONN_HASH_SIZE];
static DEFINE_SPINLOCK(connections_lock);
DEFINE_STATIC_SRCU(connections_srcu);
+static const struct dlm_proto_ops *dlm_proto_ops;
+
static void process_recv_sockets(struct work_struct *work);
static void process_send_sockets(struct work_struct *work);
-static void sctp_connect_to_sock(struct connection *con);
-static void tcp_connect_to_sock(struct connection *con);
-static void dlm_tcp_shutdown(struct connection *con);
+/* need to held writequeue_lock */
+static struct writequeue_entry *con_next_wq(struct connection *con)
+{
+ struct writequeue_entry *e;
+
+ if (list_empty(&con->writequeue))
+ return NULL;
+
+ e = list_first_entry(&con->writequeue, struct writequeue_entry,
+ list);
+ if (e->len == 0)
+ return NULL;
+
+ return e;
+}
static struct connection *__find_con(int nodeid, int r)
{
@@ -208,20 +238,6 @@ static int dlm_con_init(struct connection *con, int nodeid)
INIT_WORK(&con->rwork, process_recv_sockets);
init_waitqueue_head(&con->shutdown_wait);
- switch (dlm_config.ci_protocol) {
- case DLM_PROTO_TCP:
- con->connect_action = tcp_connect_to_sock;
- con->shutdown_action = dlm_tcp_shutdown;
- con->eof_condition = tcp_eof_condition;
- break;
- case DLM_PROTO_SCTP:
- con->connect_action = sctp_connect_to_sock;
- break;
- default:
- kfree(con->rx_buf);
- return -EINVAL;
- }
-
return 0;
}
@@ -249,6 +265,8 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
return NULL;
}
+ mutex_init(&con->wq_alloc);
+
spin_lock(&connections_lock);
/* Because multiple workqueues/threads calls this function it can
* race on multiple cpu's. Instead of locking hot path __find_con()
@@ -583,8 +601,7 @@ static void lowcomms_error_report(struct sock *sk)
goto out;
orig_report = listen_sock.sk_error_report;
- if (con->sock == NULL ||
- kernel_getpeername(con->sock, (struct sockaddr *)&saddr) < 0) {
+ if (kernel_getpeername(sk->sk_socket, (struct sockaddr *)&saddr) < 0) {
printk_ratelimited(KERN_ERR "dlm: node %d: socket error "
"sending to node %d, port %d, "
"sk_err=%d/%d\n", dlm_our_nodeid(),
@@ -801,6 +818,7 @@ static void close_connection(struct connection *con, bool and_other,
con->rx_leftover = 0;
con->retries = 0;
+ clear_bit(CF_APP_LIMITED, &con->flags);
clear_bit(CF_CONNECTED, &con->flags);
clear_bit(CF_DELAY_CONNECT, &con->flags);
clear_bit(CF_RECONNECT, &con->flags);
@@ -877,7 +895,6 @@ static int con_realloc_receive_buf(struct connection *con, int newlen)
/* Data received from remote end */
static int receive_from_sock(struct connection *con)
{
- int call_again_soon = 0;
struct msghdr msg;
struct kvec iov;
int ret, buflen;
@@ -897,41 +914,40 @@ static int receive_from_sock(struct connection *con)
goto out_resched;
}
- /* calculate new buffer parameter regarding last receive and
- * possible leftover bytes
- */
- iov.iov_base = con->rx_buf + con->rx_leftover;
- iov.iov_len = con->rx_buflen - con->rx_leftover;
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
- ret = kernel_recvmsg(con->sock, &msg, &iov, 1, iov.iov_len,
- msg.msg_flags);
- if (ret <= 0)
- goto out_close;
- else if (ret == iov.iov_len)
- call_again_soon = 1;
-
- /* new buflen according readed bytes and leftover from last receive */
- buflen = ret + con->rx_leftover;
- ret = dlm_process_incoming_buffer(con->nodeid, con->rx_buf, buflen);
- if (ret < 0)
- goto out_close;
+ for (;;) {
+ /* calculate new buffer parameter regarding last receive and
+ * possible leftover bytes
+ */
+ iov.iov_base = con->rx_buf + con->rx_leftover;
+ iov.iov_len = con->rx_buflen - con->rx_leftover;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+ ret = kernel_recvmsg(con->sock, &msg, &iov, 1, iov.iov_len,
+ msg.msg_flags);
+ if (ret == -EAGAIN)
+ break;
+ else if (ret <= 0)
+ goto out_close;
- /* calculate leftover bytes from process and put it into begin of
- * the receive buffer, so next receive we have the full message
- * at the start address of the receive buffer.
- */
- con->rx_leftover = buflen - ret;
- if (con->rx_leftover) {
- memmove(con->rx_buf, con->rx_buf + ret,
- con->rx_leftover);
- call_again_soon = true;
+ /* new buflen according readed bytes and leftover from last receive */
+ buflen = ret + con->rx_leftover;
+ ret = dlm_process_incoming_buffer(con->nodeid, con->rx_buf, buflen);
+ if (ret < 0)
+ goto out_close;
+
+ /* calculate leftover bytes from process and put it into begin of
+ * the receive buffer, so next receive we have the full message
+ * at the start address of the receive buffer.
+ */
+ con->rx_leftover = buflen - ret;
+ if (con->rx_leftover) {
+ memmove(con->rx_buf, con->rx_buf + ret,
+ con->rx_leftover);
+ }
}
- if (call_again_soon)
- goto out_resched;
-
+ dlm_midcomms_receive_done(con->nodeid);
mutex_unlock(&con->sock_mutex);
return 0;
@@ -946,7 +962,8 @@ out_close:
log_print("connection %p got EOF from %d",
con, con->nodeid);
- if (con->eof_condition && con->eof_condition(con)) {
+ if (dlm_proto_ops->eof_condition &&
+ dlm_proto_ops->eof_condition(con)) {
set_bit(CF_EOF, &con->flags);
mutex_unlock(&con->sock_mutex);
} else {
@@ -1134,242 +1151,6 @@ static int sctp_bind_addrs(struct socket *sock, uint16_t port)
return result;
}
-/* Initiate an SCTP association.
- This is a special case of send_to_sock() in that we don't yet have a
- peeled-off socket for this association, so we use the listening socket
- and add the primary IP address of the remote node.
- */
-static void sctp_connect_to_sock(struct connection *con)
-{
- struct sockaddr_storage daddr;
- int result;
- int addr_len;
- struct socket *sock;
- unsigned int mark;
-
- mutex_lock(&con->sock_mutex);
-
- /* Some odd races can cause double-connects, ignore them */
- if (con->retries++ > MAX_CONNECT_RETRIES)
- goto out;
-
- if (con->sock) {
- log_print("node %d already connected.", con->nodeid);
- goto out;
- }
-
- memset(&daddr, 0, sizeof(daddr));
- result = nodeid_to_addr(con->nodeid, &daddr, NULL, true, &mark);
- if (result < 0) {
- log_print("no address for nodeid %d", con->nodeid);
- goto out;
- }
-
- /* Create a socket to communicate with */
- result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
- SOCK_STREAM, IPPROTO_SCTP, &sock);
- if (result < 0)
- goto socket_err;
-
- sock_set_mark(sock->sk, mark);
-
- add_sock(sock, con);
-
- /* Bind to all addresses. */
- if (sctp_bind_addrs(con->sock, 0))
- goto bind_err;
-
- make_sockaddr(&daddr, dlm_config.ci_tcp_port, &addr_len);
-
- log_print_ratelimited("connecting to %d", con->nodeid);
-
- /* Turn off Nagle's algorithm */
- sctp_sock_set_nodelay(sock->sk);
-
- /*
- * Make sock->ops->connect() function return in specified time,
- * since O_NONBLOCK argument in connect() function does not work here,
- * then, we should restore the default value of this attribute.
- */
- sock_set_sndtimeo(sock->sk, 5);
- result = sock->ops->connect(sock, (struct sockaddr *)&daddr, addr_len,
- 0);
- sock_set_sndtimeo(sock->sk, 0);
-
- if (result == -EINPROGRESS)
- result = 0;
- if (result == 0) {
- if (!test_and_set_bit(CF_CONNECTED, &con->flags))
- log_print("successful connected to node %d", con->nodeid);
- goto out;
- }
-
-bind_err:
- con->sock = NULL;
- sock_release(sock);
-
-socket_err:
- /*
- * Some errors are fatal and this list might need adjusting. For other
- * errors we try again until the max number of retries is reached.
- */
- if (result != -EHOSTUNREACH &&
- result != -ENETUNREACH &&
- result != -ENETDOWN &&
- result != -EINVAL &&
- result != -EPROTONOSUPPORT) {
- log_print("connect %d try %d error %d", con->nodeid,
- con->retries, result);
- mutex_unlock(&con->sock_mutex);
- msleep(1000);
- lowcomms_connect_sock(con);
- return;
- }
-
-out:
- mutex_unlock(&con->sock_mutex);
-}
-
-/* Connect a new socket to its peer */
-static void tcp_connect_to_sock(struct connection *con)
-{
- struct sockaddr_storage saddr, src_addr;
- unsigned int mark;
- int addr_len;
- struct socket *sock = NULL;
- int result;
-
- mutex_lock(&con->sock_mutex);
- if (con->retries++ > MAX_CONNECT_RETRIES)
- goto out;
-
- /* Some odd races can cause double-connects, ignore them */
- if (con->sock)
- goto out;
-
- /* Create a socket to communicate with */
- result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
- SOCK_STREAM, IPPROTO_TCP, &sock);
- if (result < 0)
- goto out_err;
-
- memset(&saddr, 0, sizeof(saddr));
- result = nodeid_to_addr(con->nodeid, &saddr, NULL, false, &mark);
- if (result < 0) {
- log_print("no address for nodeid %d", con->nodeid);
- goto out_err;
- }
-
- sock_set_mark(sock->sk, mark);
-
- add_sock(sock, con);
-
- /* Bind to our cluster-known address connecting to avoid
- routing problems */
- memcpy(&src_addr, dlm_local_addr[0], sizeof(src_addr));
- make_sockaddr(&src_addr, 0, &addr_len);
- result = sock->ops->bind(sock, (struct sockaddr *) &src_addr,
- addr_len);
- if (result < 0) {
- log_print("could not bind for connect: %d", result);
- /* This *may* not indicate a critical error */
- }
-
- make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len);
-
- log_print_ratelimited("connecting to %d", con->nodeid);
-
- /* Turn off Nagle's algorithm */
- tcp_sock_set_nodelay(sock->sk);
-
- result = sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len,
- O_NONBLOCK);
- if (result == -EINPROGRESS)
- result = 0;
- if (result == 0)
- goto out;
-
-out_err:
- if (con->sock) {
- sock_release(con->sock);
- con->sock = NULL;
- } else if (sock) {
- sock_release(sock);
- }
- /*
- * Some errors are fatal and this list might need adjusting. For other
- * errors we try again until the max number of retries is reached.
- */
- if (result != -EHOSTUNREACH &&
- result != -ENETUNREACH &&
- result != -ENETDOWN &&
- result != -EINVAL &&
- result != -EPROTONOSUPPORT) {
- log_print("connect %d try %d error %d", con->nodeid,
- con->retries, result);
- mutex_unlock(&con->sock_mutex);
- msleep(1000);
- lowcomms_connect_sock(con);
- return;
- }
-out:
- mutex_unlock(&con->sock_mutex);
- return;
-}
-
-/* On error caller must run dlm_close_sock() for the
- * listen connection socket.
- */
-static int tcp_create_listen_sock(struct listen_connection *con,
- struct sockaddr_storage *saddr)
-{
- struct socket *sock = NULL;
- int result = 0;
- int addr_len;
-
- if (dlm_local_addr[0]->ss_family == AF_INET)
- addr_len = sizeof(struct sockaddr_in);
- else
- addr_len = sizeof(struct sockaddr_in6);
-
- /* Create a socket to communicate with */
- result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
- SOCK_STREAM, IPPROTO_TCP, &sock);
- if (result < 0) {
- log_print("Can't create listening comms socket");
- goto create_out;
- }
-
- sock_set_mark(sock->sk, dlm_config.ci_mark);
-
- /* Turn off Nagle's algorithm */
- tcp_sock_set_nodelay(sock->sk);
-
- sock_set_reuseaddr(sock->sk);
-
- add_listen_sock(sock, con);
-
- /* Bind to our port */
- make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len);
- result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len);
- if (result < 0) {
- log_print("Can't bind to port %d", dlm_config.ci_tcp_port);
- goto create_out;
- }
- sock_set_keepalive(sock->sk);
-
- result = sock->ops->listen(sock, 5);
- if (result < 0) {
- log_print("Can't listen on port %d", dlm_config.ci_tcp_port);
- goto create_out;
- }
-
- return 0;
-
-create_out:
- return result;
-}
-
/* Get local addresses */
static void init_local(void)
{
@@ -1396,63 +1177,6 @@ static void deinit_local(void)
kfree(dlm_local_addr[i]);
}
-/* Initialise SCTP socket and bind to all interfaces
- * On error caller must run dlm_close_sock() for the
- * listen connection socket.
- */
-static int sctp_listen_for_all(struct listen_connection *con)
-{
- struct socket *sock = NULL;
- int result = -EINVAL;
-
- log_print("Using SCTP for communications");
-
- result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
- SOCK_STREAM, IPPROTO_SCTP, &sock);
- if (result < 0) {
- log_print("Can't create comms socket, check SCTP is loaded");
- goto out;
- }
-
- sock_set_rcvbuf(sock->sk, NEEDED_RMEM);
- sock_set_mark(sock->sk, dlm_config.ci_mark);
- sctp_sock_set_nodelay(sock->sk);
-
- add_listen_sock(sock, con);
-
- /* Bind to all addresses. */
- result = sctp_bind_addrs(con->sock, dlm_config.ci_tcp_port);
- if (result < 0)
- goto out;
-
- result = sock->ops->listen(sock, 5);
- if (result < 0) {
- log_print("Can't set socket listening");
- goto out;
- }
-
- return 0;
-
-out:
- return result;
-}
-
-static int tcp_listen_for_all(void)
-{
- /* We don't support multi-homed hosts */
- if (dlm_local_count > 1) {
- log_print("TCP protocol can't handle multi-homed hosts, "
- "try SCTP");
- return -EINVAL;
- }
-
- log_print("Using TCP for communications");
-
- return tcp_create_listen_sock(&listen_con, dlm_local_addr[0]);
-}
-
-
-
static struct writequeue_entry *new_writequeue_entry(struct connection *con,
gfp_t allocation)
{
@@ -1528,19 +1252,37 @@ static struct dlm_msg *dlm_lowcomms_new_msg_con(struct connection *con, int len,
{
struct writequeue_entry *e;
struct dlm_msg *msg;
+ bool sleepable;
msg = kzalloc(sizeof(*msg), allocation);
if (!msg)
return NULL;
+ /* this mutex is being used as a wait to avoid multiple "fast"
+ * new writequeue page list entry allocs in new_wq_entry in
+ * normal operation which is sleepable context. Without it
+ * we could end in multiple writequeue entries with one
+ * dlm message because multiple callers were waiting at
+ * the writequeue_lock in new_wq_entry().
+ */
+ sleepable = gfpflags_normal_context(allocation);
+ if (sleepable)
+ mutex_lock(&con->wq_alloc);
+
kref_init(&msg->ref);
e = new_wq_entry(con, len, allocation, ppc, cb, mh);
if (!e) {
+ if (sleepable)
+ mutex_unlock(&con->wq_alloc);
+
kfree(msg);
return NULL;
}
+ if (sleepable)
+ mutex_unlock(&con->wq_alloc);
+
msg->ppc = *ppc;
msg->len = len;
msg->entry = e;
@@ -1646,10 +1388,9 @@ int dlm_lowcomms_resend_msg(struct dlm_msg *msg)
/* Send a message */
static void send_to_sock(struct connection *con)
{
- int ret = 0;
const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
struct writequeue_entry *e;
- int len, offset;
+ int len, offset, ret;
int count = 0;
mutex_lock(&con->sock_mutex);
@@ -1658,7 +1399,8 @@ static void send_to_sock(struct connection *con)
spin_lock(&con->writequeue_lock);
for (;;) {
- if (list_empty(&con->writequeue))
+ e = con_next_wq(con);
+ if (!e)
break;
e = list_first_entry(&con->writequeue, struct writequeue_entry, list);
@@ -1667,25 +1409,22 @@ static void send_to_sock(struct connection *con)
BUG_ON(len == 0 && e->users == 0);
spin_unlock(&con->writequeue_lock);
- ret = 0;
- if (len) {
- ret = kernel_sendpage(con->sock, e->page, offset, len,
- msg_flags);
- if (ret == -EAGAIN || ret == 0) {
- if (ret == -EAGAIN &&
- test_bit(SOCKWQ_ASYNC_NOSPACE, &con->sock->flags) &&
- !test_and_set_bit(CF_APP_LIMITED, &con->flags)) {
- /* Notify TCP that we're limited by the
- * application window size.
- */
- set_bit(SOCK_NOSPACE, &con->sock->flags);
- con->sock->sk->sk_write_pending++;
- }
- cond_resched();
- goto out;
- } else if (ret < 0)
- goto out;
- }
+ ret = kernel_sendpage(con->sock, e->page, offset, len,
+ msg_flags);
+ if (ret == -EAGAIN || ret == 0) {
+ if (ret == -EAGAIN &&
+ test_bit(SOCKWQ_ASYNC_NOSPACE, &con->sock->flags) &&
+ !test_and_set_bit(CF_APP_LIMITED, &con->flags)) {
+ /* Notify TCP that we're limited by the
+ * application window size.
+ */
+ set_bit(SOCK_NOSPACE, &con->sock->flags);
+ con->sock->sk->sk_write_pending++;
+ }
+ cond_resched();
+ goto out;
+ } else if (ret < 0)
+ goto out;
/* Don't starve people filling buffers */
if (++count >= MAX_SEND_MSG_COUNT) {
@@ -1770,12 +1509,9 @@ int dlm_lowcomms_close(int nodeid)
static void process_recv_sockets(struct work_struct *work)
{
struct connection *con = container_of(work, struct connection, rwork);
- int err;
clear_bit(CF_READ_PENDING, &con->flags);
- do {
- err = receive_from_sock(con);
- } while (!err);
+ receive_from_sock(con);
}
static void process_listen_recv_socket(struct work_struct *work)
@@ -1783,6 +1519,74 @@ static void process_listen_recv_socket(struct work_struct *work)
accept_from_sock(&listen_con);
}
+static void dlm_connect(struct connection *con)
+{
+ struct sockaddr_storage addr;
+ int result, addr_len;
+ struct socket *sock;
+ unsigned int mark;
+
+ /* Some odd races can cause double-connects, ignore them */
+ if (con->retries++ > MAX_CONNECT_RETRIES)
+ return;
+
+ if (con->sock) {
+ log_print("node %d already connected.", con->nodeid);
+ return;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ result = nodeid_to_addr(con->nodeid, &addr, NULL,
+ dlm_proto_ops->try_new_addr, &mark);
+ if (result < 0) {
+ log_print("no address for nodeid %d", con->nodeid);
+ return;
+ }
+
+ /* Create a socket to communicate with */
+ result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
+ SOCK_STREAM, dlm_proto_ops->proto, &sock);
+ if (result < 0)
+ goto socket_err;
+
+ sock_set_mark(sock->sk, mark);
+ dlm_proto_ops->sockopts(sock);
+
+ add_sock(sock, con);
+
+ result = dlm_proto_ops->bind(sock);
+ if (result < 0)
+ goto add_sock_err;
+
+ log_print_ratelimited("connecting to %d", con->nodeid);
+ make_sockaddr(&addr, dlm_config.ci_tcp_port, &addr_len);
+ result = dlm_proto_ops->connect(con, sock, (struct sockaddr *)&addr,
+ addr_len);
+ if (result < 0)
+ goto add_sock_err;
+
+ return;
+
+add_sock_err:
+ dlm_close_sock(&con->sock);
+
+socket_err:
+ /*
+ * Some errors are fatal and this list might need adjusting. For other
+ * errors we try again until the max number of retries is reached.
+ */
+ if (result != -EHOSTUNREACH &&
+ result != -ENETUNREACH &&
+ result != -ENETDOWN &&
+ result != -EINVAL &&
+ result != -EPROTONOSUPPORT) {
+ log_print("connect %d try %d error %d", con->nodeid,
+ con->retries, result);
+ msleep(1000);
+ lowcomms_connect_sock(con);
+ }
+}
+
/* Send workqueue function */
static void process_send_sockets(struct work_struct *work)
{
@@ -1797,11 +1601,15 @@ static void process_send_sockets(struct work_struct *work)
dlm_midcomms_unack_msg_resend(con->nodeid);
}
- if (con->sock == NULL) { /* not mutex protected so check it inside too */
+ if (con->sock == NULL) {
if (test_and_clear_bit(CF_DELAY_CONNECT, &con->flags))
msleep(1000);
- con->connect_action(con);
+
+ mutex_lock(&con->sock_mutex);
+ dlm_connect(con);
+ mutex_unlock(&con->sock_mutex);
}
+
if (!list_empty(&con->writequeue))
send_to_sock(con);
}
@@ -1840,8 +1648,8 @@ static int work_start(void)
static void shutdown_conn(struct connection *con)
{
- if (con->shutdown_action)
- con->shutdown_action(con);
+ if (dlm_proto_ops->shutdown_action)
+ dlm_proto_ops->shutdown_action(con);
}
void dlm_lowcomms_shutdown(void)
@@ -1948,8 +1756,198 @@ void dlm_lowcomms_stop(void)
srcu_read_unlock(&connections_srcu, idx);
work_stop();
deinit_local();
+
+ dlm_proto_ops = NULL;
}
+static int dlm_listen_for_all(void)
+{
+ struct socket *sock;
+ int result;
+
+ log_print("Using %s for communications",
+ dlm_proto_ops->name);
+
+ result = dlm_proto_ops->listen_validate();
+ if (result < 0)
+ return result;
+
+ result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
+ SOCK_STREAM, dlm_proto_ops->proto, &sock);
+ if (result < 0) {
+ log_print("Can't create comms socket, check SCTP is loaded");
+ goto out;
+ }
+
+ sock_set_mark(sock->sk, dlm_config.ci_mark);
+ dlm_proto_ops->listen_sockopts(sock);
+
+ result = dlm_proto_ops->listen_bind(sock);
+ if (result < 0)
+ goto out;
+
+ save_listen_callbacks(sock);
+ add_listen_sock(sock, &listen_con);
+
+ INIT_WORK(&listen_con.rwork, process_listen_recv_socket);
+ result = sock->ops->listen(sock, 5);
+ if (result < 0) {
+ dlm_close_sock(&listen_con.sock);
+ goto out;
+ }
+
+ return 0;
+
+out:
+ sock_release(sock);
+ return result;
+}
+
+static int dlm_tcp_bind(struct socket *sock)
+{
+ struct sockaddr_storage src_addr;
+ int result, addr_len;
+
+ /* Bind to our cluster-known address connecting to avoid
+ * routing problems.
+ */
+ memcpy(&src_addr, dlm_local_addr[0], sizeof(src_addr));
+ make_sockaddr(&src_addr, 0, &addr_len);
+
+ result = sock->ops->bind(sock, (struct sockaddr *)&src_addr,
+ addr_len);
+ if (result < 0) {
+ /* This *may* not indicate a critical error */
+ log_print("could not bind for connect: %d", result);
+ }
+
+ return 0;
+}
+
+static int dlm_tcp_connect(struct connection *con, struct socket *sock,
+ struct sockaddr *addr, int addr_len)
+{
+ int ret;
+
+ ret = sock->ops->connect(sock, addr, addr_len, O_NONBLOCK);
+ switch (ret) {
+ case -EINPROGRESS:
+ fallthrough;
+ case 0:
+ return 0;
+ }
+
+ return ret;
+}
+
+static int dlm_tcp_listen_validate(void)
+{
+ /* We don't support multi-homed hosts */
+ if (dlm_local_count > 1) {
+ log_print("TCP protocol can't handle multi-homed hosts, try SCTP");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void dlm_tcp_sockopts(struct socket *sock)
+{
+ /* Turn off Nagle's algorithm */
+ tcp_sock_set_nodelay(sock->sk);
+}
+
+static void dlm_tcp_listen_sockopts(struct socket *sock)
+{
+ dlm_tcp_sockopts(sock);
+ sock_set_reuseaddr(sock->sk);
+}
+
+static int dlm_tcp_listen_bind(struct socket *sock)
+{
+ int addr_len;
+
+ /* Bind to our port */
+ make_sockaddr(dlm_local_addr[0], dlm_config.ci_tcp_port, &addr_len);
+ return sock->ops->bind(sock, (struct sockaddr *)dlm_local_addr[0],
+ addr_len);
+}
+
+static const struct dlm_proto_ops dlm_tcp_ops = {
+ .name = "TCP",
+ .proto = IPPROTO_TCP,
+ .connect = dlm_tcp_connect,
+ .sockopts = dlm_tcp_sockopts,
+ .bind = dlm_tcp_bind,
+ .listen_validate = dlm_tcp_listen_validate,
+ .listen_sockopts = dlm_tcp_listen_sockopts,
+ .listen_bind = dlm_tcp_listen_bind,
+ .shutdown_action = dlm_tcp_shutdown,
+ .eof_condition = tcp_eof_condition,
+};
+
+static int dlm_sctp_bind(struct socket *sock)
+{
+ return sctp_bind_addrs(sock, 0);
+}
+
+static int dlm_sctp_connect(struct connection *con, struct socket *sock,
+ struct sockaddr *addr, int addr_len)
+{
+ int ret;
+
+ /*
+ * Make sock->ops->connect() function return in specified time,
+ * since O_NONBLOCK argument in connect() function does not work here,
+ * then, we should restore the default value of this attribute.
+ */
+ sock_set_sndtimeo(sock->sk, 5);
+ ret = sock->ops->connect(sock, addr, addr_len, 0);
+ sock_set_sndtimeo(sock->sk, 0);
+ if (ret < 0)
+ return ret;
+
+ if (!test_and_set_bit(CF_CONNECTED, &con->flags))
+ log_print("successful connected to node %d", con->nodeid);
+
+ return 0;
+}
+
+static int dlm_sctp_listen_validate(void)
+{
+ if (!IS_ENABLED(CONFIG_IP_SCTP)) {
+ log_print("SCTP is not enabled by this kernel");
+ return -EOPNOTSUPP;
+ }
+
+ request_module("sctp");
+ return 0;
+}
+
+static int dlm_sctp_bind_listen(struct socket *sock)
+{
+ return sctp_bind_addrs(sock, dlm_config.ci_tcp_port);
+}
+
+static void dlm_sctp_sockopts(struct socket *sock)
+{
+ /* Turn off Nagle's algorithm */
+ sctp_sock_set_nodelay(sock->sk);
+ sock_set_rcvbuf(sock->sk, NEEDED_RMEM);
+}
+
+static const struct dlm_proto_ops dlm_sctp_ops = {
+ .name = "SCTP",
+ .proto = IPPROTO_SCTP,
+ .try_new_addr = true,
+ .connect = dlm_sctp_connect,
+ .sockopts = dlm_sctp_sockopts,
+ .bind = dlm_sctp_bind,
+ .listen_validate = dlm_sctp_listen_validate,
+ .listen_sockopts = dlm_sctp_sockopts,
+ .listen_bind = dlm_sctp_bind_listen,
+};
+
int dlm_lowcomms_start(void)
{
int error = -EINVAL;
@@ -1976,23 +1974,27 @@ int dlm_lowcomms_start(void)
/* Start listening */
switch (dlm_config.ci_protocol) {
case DLM_PROTO_TCP:
- error = tcp_listen_for_all();
+ dlm_proto_ops = &dlm_tcp_ops;
break;
case DLM_PROTO_SCTP:
- error = sctp_listen_for_all(&listen_con);
+ dlm_proto_ops = &dlm_sctp_ops;
break;
default:
log_print("Invalid protocol identifier %d set",
dlm_config.ci_protocol);
error = -EINVAL;
- break;
+ goto fail_proto_ops;
}
+
+ error = dlm_listen_for_all();
if (error)
- goto fail_unlisten;
+ goto fail_listen;
return 0;
-fail_unlisten:
+fail_listen:
+ dlm_proto_ops = NULL;
+fail_proto_ops:
dlm_allow_conn = 0;
dlm_close_sock(&listen_con.sock);
work_stop();
diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h
index aaae7115c00d..4ccae07cf005 100644
--- a/fs/dlm/lowcomms.h
+++ b/fs/dlm/lowcomms.h
@@ -46,6 +46,7 @@ int dlm_lowcomms_resend_msg(struct dlm_msg *msg);
int dlm_lowcomms_connect_node(int nodeid);
int dlm_lowcomms_nodes_set_mark(int nodeid, unsigned int mark);
int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len);
+void dlm_midcomms_receive_done(int nodeid);
#endif /* __LOWCOMMS_DOT_H__ */
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index d9e1e4170eb1..731d489aa323 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -443,8 +443,10 @@ static int ping_members(struct dlm_ls *ls)
list_for_each_entry(memb, &ls->ls_nodes, list) {
error = dlm_recovery_stopped(ls);
- if (error)
+ if (error) {
+ error = -EINTR;
break;
+ }
error = dlm_rcom_status(ls, memb->nodeid, 0);
if (error)
break;
diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c
index e3de268898ed..7ae39ec8d9b0 100644
--- a/fs/dlm/midcomms.c
+++ b/fs/dlm/midcomms.c
@@ -109,12 +109,6 @@
* compatibility. There exists better ways to make a better handling.
* However this should be changed in the next major version bump of dlm.
*
- * Ack handling:
- *
- * Currently we send an ack message for every dlm message. However we
- * can ack multiple dlm messages with one ack by just delaying the ack
- * message. Will reduce some traffic but makes the drop detection slower.
- *
* Tail Size checking:
*
* There exists a message tail payload in e.g. DLM_MSG however we don't
@@ -169,6 +163,7 @@ struct midcomms_node {
#define DLM_NODE_FLAG_CLOSE 1
#define DLM_NODE_FLAG_STOP_TX 2
#define DLM_NODE_FLAG_STOP_RX 3
+#define DLM_NODE_ULP_DELIVERED 4
unsigned long flags;
wait_queue_head_t shutdown_wait;
@@ -480,11 +475,12 @@ static void dlm_midcomms_receive_buffer(union dlm_packet *p,
{
if (seq == node->seq_next) {
node->seq_next++;
- /* send ack before fin */
- dlm_send_ack(node->nodeid, node->seq_next);
switch (p->header.h_cmd) {
case DLM_FIN:
+ /* send ack before fin */
+ dlm_send_ack(node->nodeid, node->seq_next);
+
spin_lock(&node->state_lock);
pr_debug("receive fin msg from node %d with state %s\n",
node->nodeid, dlm_state_str(node->state));
@@ -534,6 +530,7 @@ static void dlm_midcomms_receive_buffer(union dlm_packet *p,
default:
WARN_ON(test_bit(DLM_NODE_FLAG_STOP_RX, &node->flags));
dlm_receive_buffer(p, node->nodeid);
+ set_bit(DLM_NODE_ULP_DELIVERED, &node->flags);
break;
}
} else {
@@ -933,6 +930,49 @@ int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len)
return ret;
}
+void dlm_midcomms_receive_done(int nodeid)
+{
+ struct midcomms_node *node;
+ int idx;
+
+ idx = srcu_read_lock(&nodes_srcu);
+ node = nodeid2node(nodeid, 0);
+ if (!node) {
+ srcu_read_unlock(&nodes_srcu, idx);
+ return;
+ }
+
+ /* old protocol, we do nothing */
+ switch (node->version) {
+ case DLM_VERSION_3_2:
+ break;
+ default:
+ srcu_read_unlock(&nodes_srcu, idx);
+ return;
+ }
+
+ /* do nothing if we didn't delivered stateful to ulp */
+ if (!test_and_clear_bit(DLM_NODE_ULP_DELIVERED,
+ &node->flags)) {
+ srcu_read_unlock(&nodes_srcu, idx);
+ return;
+ }
+
+ spin_lock(&node->state_lock);
+ /* we only ack if state is ESTABLISHED */
+ switch (node->state) {
+ case DLM_ESTABLISHED:
+ spin_unlock(&node->state_lock);
+ dlm_send_ack(node->nodeid, node->seq_next);
+ break;
+ default:
+ spin_unlock(&node->state_lock);
+ /* do nothing FIN has it's own ack send */
+ break;
+ };
+ srcu_read_unlock(&nodes_srcu, idx);
+}
+
void dlm_midcomms_unack_msg_resend(int nodeid)
{
struct midcomms_node *node;
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 5651933f54a4..6cba86470278 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -89,22 +89,15 @@ static int create_rcom_stateless(struct dlm_ls *ls, int to_nodeid, int type,
return 0;
}
-static void _send_rcom(struct dlm_ls *ls, struct dlm_rcom *rc)
+static void send_rcom(struct dlm_mhandle *mh, struct dlm_rcom *rc)
{
dlm_rcom_out(rc);
-}
-
-static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh,
- struct dlm_rcom *rc)
-{
- _send_rcom(ls, rc);
dlm_midcomms_commit_mhandle(mh);
}
-static void send_rcom_stateless(struct dlm_ls *ls, struct dlm_msg *msg,
- struct dlm_rcom *rc)
+static void send_rcom_stateless(struct dlm_msg *msg, struct dlm_rcom *rc)
{
- _send_rcom(ls, rc);
+ dlm_rcom_out(rc);
dlm_lowcomms_commit_msg(msg);
dlm_lowcomms_put_msg(msg);
}
@@ -204,7 +197,7 @@ retry:
allow_sync_reply(ls, &rc->rc_id);
memset(ls->ls_recover_buf, 0, DLM_MAX_SOCKET_BUFSIZE);
- send_rcom_stateless(ls, msg, rc);
+ send_rcom_stateless(msg, rc);
error = dlm_wait_function(ls, &rcom_response);
disallow_sync_reply(ls);
@@ -287,7 +280,7 @@ static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in)
spin_unlock(&ls->ls_recover_lock);
do_send:
- send_rcom_stateless(ls, msg, rc);
+ send_rcom_stateless(msg, rc);
}
static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
@@ -327,7 +320,7 @@ retry:
allow_sync_reply(ls, &rc->rc_id);
memset(ls->ls_recover_buf, 0, DLM_MAX_SOCKET_BUFSIZE);
- send_rcom_stateless(ls, msg, rc);
+ send_rcom_stateless(msg, rc);
error = dlm_wait_function(ls, &rcom_response);
disallow_sync_reply(ls);
@@ -356,7 +349,7 @@ static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in)
dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen,
nodeid);
- send_rcom_stateless(ls, msg, rc);
+ send_rcom_stateless(msg, rc);
}
int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid)
@@ -373,7 +366,7 @@ int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid)
memcpy(rc->rc_buf, r->res_name, r->res_length);
rc->rc_id = (unsigned long) r->res_id;
- send_rcom(ls, mh, rc);
+ send_rcom(mh, rc);
out:
return error;
}
@@ -404,7 +397,7 @@ static void receive_rcom_lookup(struct dlm_ls *ls, struct dlm_rcom *rc_in)
rc->rc_id = rc_in->rc_id;
rc->rc_seq_reply = rc_in->rc_seq;
- send_rcom(ls, mh, rc);
+ send_rcom(mh, rc);
}
static void receive_rcom_lookup_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
@@ -461,7 +454,7 @@ int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
pack_rcom_lock(r, lkb, rl);
rc->rc_id = (unsigned long) r;
- send_rcom(ls, mh, rc);
+ send_rcom(mh, rc);
out:
return error;
}
@@ -487,7 +480,7 @@ static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in)
rc->rc_id = rc_in->rc_id;
rc->rc_seq_reply = rc_in->rc_seq;
- send_rcom(ls, mh, rc);
+ send_rcom(mh, rc);
}
/* If the lockspace doesn't exist then still send a status message
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 85e245392715..97d052cea5a9 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -125,8 +125,10 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
dlm_recover_waiters_pre(ls);
error = dlm_recovery_stopped(ls);
- if (error)
+ if (error) {
+ error = -EINTR;
goto fail;
+ }
if (neg || dlm_no_directory(ls)) {
/*
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index f00fcc4a4f72..e619c31b6bd9 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -3,6 +3,7 @@
* Implement the manual drop-all-pagecache function
*/
+#include <linux/pagemap.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/fs.h>
@@ -27,7 +28,7 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
* we need to reschedule to avoid softlockups.
*/
if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
- (inode->i_mapping->nrpages == 0 && !need_resched())) {
+ (mapping_empty(inode->i_mapping) && !need_resched())) {
spin_unlock(&inode->i_lock);
continue;
}
diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig
index 906af0c1998c..14b747026742 100644
--- a/fs/erofs/Kconfig
+++ b/fs/erofs/Kconfig
@@ -3,6 +3,7 @@
config EROFS_FS
tristate "EROFS filesystem support"
depends on BLOCK
+ select FS_IOMAP
select LIBCRC32C
help
EROFS (Enhanced Read-Only File System) is a lightweight
diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index 3787a5fb0a42..9db829715652 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -2,35 +2,13 @@
/*
* Copyright (C) 2017-2018 HUAWEI, Inc.
* https://www.huawei.com/
+ * Copyright (C) 2021, Alibaba Cloud
*/
#include "internal.h"
#include <linux/prefetch.h>
-
+#include <linux/dax.h>
#include <trace/events/erofs.h>
-static void erofs_readendio(struct bio *bio)
-{
- struct bio_vec *bvec;
- blk_status_t err = bio->bi_status;
- struct bvec_iter_all iter_all;
-
- bio_for_each_segment_all(bvec, bio, iter_all) {
- struct page *page = bvec->bv_page;
-
- /* page is already locked */
- DBG_BUGON(PageUptodate(page));
-
- if (err)
- SetPageError(page);
- else
- SetPageUptodate(page);
-
- unlock_page(page);
- /* page could be reclaimed now */
- }
- bio_put(bio);
-}
-
struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr)
{
struct address_space *const mapping = sb->s_bdev->bd_inode->i_mapping;
@@ -59,13 +37,6 @@ static int erofs_map_blocks_flatmode(struct inode *inode,
nblocks = DIV_ROUND_UP(inode->i_size, PAGE_SIZE);
lastblk = nblocks - tailendpacking;
- if (offset >= inode->i_size) {
- /* leave out-of-bound access unmapped */
- map->m_flags = 0;
- map->m_plen = 0;
- goto out;
- }
-
/* there is no hole in flatmode */
map->m_flags = EROFS_MAP_MAPPED;
@@ -100,217 +71,273 @@ static int erofs_map_blocks_flatmode(struct inode *inode,
goto err_out;
}
-out:
map->m_llen = map->m_plen;
-
err_out:
trace_erofs_map_blocks_flatmode_exit(inode, map, flags, 0);
return err;
}
-static inline struct bio *erofs_read_raw_page(struct bio *bio,
- struct address_space *mapping,
- struct page *page,
- erofs_off_t *last_block,
- unsigned int nblocks,
- unsigned int *eblks,
- bool ra)
+static int erofs_map_blocks(struct inode *inode,
+ struct erofs_map_blocks *map, int flags)
{
- struct inode *const inode = mapping->host;
- struct super_block *const sb = inode->i_sb;
- erofs_off_t current_block = (erofs_off_t)page->index;
- int err;
-
- DBG_BUGON(!nblocks);
-
- if (PageUptodate(page)) {
- err = 0;
- goto has_updated;
- }
+ struct super_block *sb = inode->i_sb;
+ struct erofs_inode *vi = EROFS_I(inode);
+ struct erofs_inode_chunk_index *idx;
+ struct page *page;
+ u64 chunknr;
+ unsigned int unit;
+ erofs_off_t pos;
+ int err = 0;
- /* note that for readpage case, bio also equals to NULL */
- if (bio &&
- (*last_block + 1 != current_block || !*eblks)) {
-submit_bio_retry:
- submit_bio(bio);
- bio = NULL;
+ if (map->m_la >= inode->i_size) {
+ /* leave out-of-bound access unmapped */
+ map->m_flags = 0;
+ map->m_plen = 0;
+ goto out;
}
- if (!bio) {
- struct erofs_map_blocks map = {
- .m_la = blknr_to_addr(current_block),
- };
- erofs_blk_t blknr;
- unsigned int blkoff;
-
- err = erofs_map_blocks_flatmode(inode, &map, EROFS_GET_BLOCKS_RAW);
- if (err)
- goto err_out;
-
- /* zero out the holed page */
- if (!(map.m_flags & EROFS_MAP_MAPPED)) {
- zero_user_segment(page, 0, PAGE_SIZE);
- SetPageUptodate(page);
-
- /* imply err = 0, see erofs_map_blocks */
- goto has_updated;
- }
-
- /* for RAW access mode, m_plen must be equal to m_llen */
- DBG_BUGON(map.m_plen != map.m_llen);
-
- blknr = erofs_blknr(map.m_pa);
- blkoff = erofs_blkoff(map.m_pa);
-
- /* deal with inline page */
- if (map.m_flags & EROFS_MAP_META) {
- void *vsrc, *vto;
- struct page *ipage;
+ if (vi->datalayout != EROFS_INODE_CHUNK_BASED)
+ return erofs_map_blocks_flatmode(inode, map, flags);
- DBG_BUGON(map.m_plen > PAGE_SIZE);
+ if (vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)
+ unit = sizeof(*idx); /* chunk index */
+ else
+ unit = EROFS_BLOCK_MAP_ENTRY_SIZE; /* block map */
- ipage = erofs_get_meta_page(inode->i_sb, blknr);
+ chunknr = map->m_la >> vi->chunkbits;
+ pos = ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize +
+ vi->xattr_isize, unit) + unit * chunknr;
- if (IS_ERR(ipage)) {
- err = PTR_ERR(ipage);
- goto err_out;
- }
+ page = erofs_get_meta_page(inode->i_sb, erofs_blknr(pos));
+ if (IS_ERR(page))
+ return PTR_ERR(page);
- vsrc = kmap_atomic(ipage);
- vto = kmap_atomic(page);
- memcpy(vto, vsrc + blkoff, map.m_plen);
- memset(vto + map.m_plen, 0, PAGE_SIZE - map.m_plen);
- kunmap_atomic(vto);
- kunmap_atomic(vsrc);
- flush_dcache_page(page);
+ map->m_la = chunknr << vi->chunkbits;
+ map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits,
+ roundup(inode->i_size - map->m_la, EROFS_BLKSIZ));
- SetPageUptodate(page);
- /* TODO: could we unlock the page earlier? */
- unlock_page(ipage);
- put_page(ipage);
+ /* handle block map */
+ if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) {
+ __le32 *blkaddr = page_address(page) + erofs_blkoff(pos);
- /* imply err = 0, see erofs_map_blocks */
- goto has_updated;
+ if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) {
+ map->m_flags = 0;
+ } else {
+ map->m_pa = blknr_to_addr(le32_to_cpu(*blkaddr));
+ map->m_flags = EROFS_MAP_MAPPED;
}
+ goto out_unlock;
+ }
+ /* parse chunk indexes */
+ idx = page_address(page) + erofs_blkoff(pos);
+ switch (le32_to_cpu(idx->blkaddr)) {
+ case EROFS_NULL_ADDR:
+ map->m_flags = 0;
+ break;
+ default:
+ /* only one device is supported for now */
+ if (idx->device_id) {
+ erofs_err(sb, "invalid device id %u @ %llu for nid %llu",
+ le16_to_cpu(idx->device_id),
+ chunknr, vi->nid);
+ err = -EFSCORRUPTED;
+ goto out_unlock;
+ }
+ map->m_pa = blknr_to_addr(le32_to_cpu(idx->blkaddr));
+ map->m_flags = EROFS_MAP_MAPPED;
+ break;
+ }
+out_unlock:
+ unlock_page(page);
+ put_page(page);
+out:
+ map->m_llen = map->m_plen;
+ return err;
+}
- /* pa must be block-aligned for raw reading */
- DBG_BUGON(erofs_blkoff(map.m_pa));
+static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
+ unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
+{
+ int ret;
+ struct erofs_map_blocks map;
+
+ map.m_la = offset;
+ map.m_llen = length;
+
+ ret = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW);
+ if (ret < 0)
+ return ret;
+
+ iomap->bdev = inode->i_sb->s_bdev;
+ iomap->dax_dev = EROFS_I_SB(inode)->dax_dev;
+ iomap->offset = map.m_la;
+ iomap->length = map.m_llen;
+ iomap->flags = 0;
+ iomap->private = NULL;
+
+ if (!(map.m_flags & EROFS_MAP_MAPPED)) {
+ iomap->type = IOMAP_HOLE;
+ iomap->addr = IOMAP_NULL_ADDR;
+ if (!iomap->length)
+ iomap->length = length;
+ return 0;
+ }
- /* max # of continuous pages */
- if (nblocks > DIV_ROUND_UP(map.m_plen, PAGE_SIZE))
- nblocks = DIV_ROUND_UP(map.m_plen, PAGE_SIZE);
+ if (map.m_flags & EROFS_MAP_META) {
+ struct page *ipage;
+
+ iomap->type = IOMAP_INLINE;
+ ipage = erofs_get_meta_page(inode->i_sb,
+ erofs_blknr(map.m_pa));
+ if (IS_ERR(ipage))
+ return PTR_ERR(ipage);
+ iomap->inline_data = page_address(ipage) +
+ erofs_blkoff(map.m_pa);
+ iomap->private = ipage;
+ } else {
+ iomap->type = IOMAP_MAPPED;
+ iomap->addr = map.m_pa;
+ }
+ return 0;
+}
- *eblks = bio_max_segs(nblocks);
- bio = bio_alloc(GFP_NOIO, *eblks);
+static int erofs_iomap_end(struct inode *inode, loff_t pos, loff_t length,
+ ssize_t written, unsigned int flags, struct iomap *iomap)
+{
+ struct page *ipage = iomap->private;
- bio->bi_end_io = erofs_readendio;
- bio_set_dev(bio, sb->s_bdev);
- bio->bi_iter.bi_sector = (sector_t)blknr <<
- LOG_SECTORS_PER_BLOCK;
- bio->bi_opf = REQ_OP_READ | (ra ? REQ_RAHEAD : 0);
+ if (ipage) {
+ DBG_BUGON(iomap->type != IOMAP_INLINE);
+ unlock_page(ipage);
+ put_page(ipage);
+ } else {
+ DBG_BUGON(iomap->type == IOMAP_INLINE);
}
+ return written;
+}
- err = bio_add_page(bio, page, PAGE_SIZE, 0);
- /* out of the extent or bio is full */
- if (err < PAGE_SIZE)
- goto submit_bio_retry;
- --*eblks;
- *last_block = current_block;
- return bio;
+static const struct iomap_ops erofs_iomap_ops = {
+ .iomap_begin = erofs_iomap_begin,
+ .iomap_end = erofs_iomap_end,
+};
-err_out:
- /* for sync reading, set page error immediately */
- if (!ra) {
- SetPageError(page);
- ClearPageUptodate(page);
+int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ u64 start, u64 len)
+{
+ if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) {
+#ifdef CONFIG_EROFS_FS_ZIP
+ return iomap_fiemap(inode, fieinfo, start, len,
+ &z_erofs_iomap_report_ops);
+#else
+ return -EOPNOTSUPP;
+#endif
}
-has_updated:
- unlock_page(page);
-
- /* if updated manually, continuous pages has a gap */
- if (bio)
- submit_bio(bio);
- return err ? ERR_PTR(err) : NULL;
+ return iomap_fiemap(inode, fieinfo, start, len, &erofs_iomap_ops);
}
/*
* since we dont have write or truncate flows, so no inode
* locking needs to be held at the moment.
*/
-static int erofs_raw_access_readpage(struct file *file, struct page *page)
+static int erofs_readpage(struct file *file, struct page *page)
{
- erofs_off_t last_block;
- unsigned int eblks;
- struct bio *bio;
-
- trace_erofs_readpage(page, true);
+ return iomap_readpage(page, &erofs_iomap_ops);
+}
- bio = erofs_read_raw_page(NULL, page->mapping,
- page, &last_block, 1, &eblks, false);
+static void erofs_readahead(struct readahead_control *rac)
+{
+ return iomap_readahead(rac, &erofs_iomap_ops);
+}
- if (IS_ERR(bio))
- return PTR_ERR(bio);
+static sector_t erofs_bmap(struct address_space *mapping, sector_t block)
+{
+ return iomap_bmap(mapping, block, &erofs_iomap_ops);
+}
- if (bio)
- submit_bio(bio);
+static int erofs_prepare_dio(struct kiocb *iocb, struct iov_iter *to)
+{
+ struct inode *inode = file_inode(iocb->ki_filp);
+ loff_t align = iocb->ki_pos | iov_iter_count(to) |
+ iov_iter_alignment(to);
+ struct block_device *bdev = inode->i_sb->s_bdev;
+ unsigned int blksize_mask;
+
+ if (bdev)
+ blksize_mask = (1 << ilog2(bdev_logical_block_size(bdev))) - 1;
+ else
+ blksize_mask = (1 << inode->i_blkbits) - 1;
+
+ if (align & blksize_mask)
+ return -EINVAL;
return 0;
}
-static void erofs_raw_access_readahead(struct readahead_control *rac)
+static ssize_t erofs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
- erofs_off_t last_block;
- unsigned int eblks;
- struct bio *bio = NULL;
- struct page *page;
-
- trace_erofs_readpages(rac->mapping->host, readahead_index(rac),
- readahead_count(rac), true);
-
- while ((page = readahead_page(rac))) {
- prefetchw(&page->flags);
-
- bio = erofs_read_raw_page(bio, rac->mapping, page, &last_block,
- readahead_count(rac), &eblks, true);
-
- /* all the page errors are ignored when readahead */
- if (IS_ERR(bio)) {
- pr_err("%s, readahead error at page %lu of nid %llu\n",
- __func__, page->index,
- EROFS_I(rac->mapping->host)->nid);
-
- bio = NULL;
- }
-
- put_page(page);
+ /* no need taking (shared) inode lock since it's a ro filesystem */
+ if (!iov_iter_count(to))
+ return 0;
+
+#ifdef CONFIG_FS_DAX
+ if (IS_DAX(iocb->ki_filp->f_mapping->host))
+ return dax_iomap_rw(iocb, to, &erofs_iomap_ops);
+#endif
+ if (iocb->ki_flags & IOCB_DIRECT) {
+ int err = erofs_prepare_dio(iocb, to);
+
+ if (!err)
+ return iomap_dio_rw(iocb, to, &erofs_iomap_ops,
+ NULL, 0);
+ if (err < 0)
+ return err;
}
+ return filemap_read(iocb, to, 0);
+}
+
+/* for uncompressed (aligned) files and raw access for other files */
+const struct address_space_operations erofs_raw_access_aops = {
+ .readpage = erofs_readpage,
+ .readahead = erofs_readahead,
+ .bmap = erofs_bmap,
+ .direct_IO = noop_direct_IO,
+};
- if (bio)
- submit_bio(bio);
+#ifdef CONFIG_FS_DAX
+static vm_fault_t erofs_dax_huge_fault(struct vm_fault *vmf,
+ enum page_entry_size pe_size)
+{
+ return dax_iomap_fault(vmf, pe_size, NULL, NULL, &erofs_iomap_ops);
}
-static sector_t erofs_bmap(struct address_space *mapping, sector_t block)
+static vm_fault_t erofs_dax_fault(struct vm_fault *vmf)
{
- struct inode *inode = mapping->host;
- struct erofs_map_blocks map = {
- .m_la = blknr_to_addr(block),
- };
+ return erofs_dax_huge_fault(vmf, PE_SIZE_PTE);
+}
- if (EROFS_I(inode)->datalayout == EROFS_INODE_FLAT_INLINE) {
- erofs_blk_t blks = i_size_read(inode) >> LOG_BLOCK_SIZE;
+static const struct vm_operations_struct erofs_dax_vm_ops = {
+ .fault = erofs_dax_fault,
+ .huge_fault = erofs_dax_huge_fault,
+};
- if (block >> LOG_SECTORS_PER_BLOCK >= blks)
- return 0;
- }
+static int erofs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!IS_DAX(file_inode(file)))
+ return generic_file_readonly_mmap(file, vma);
- if (!erofs_map_blocks_flatmode(inode, &map, EROFS_GET_BLOCKS_RAW))
- return erofs_blknr(map.m_pa);
+ if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
+ return -EINVAL;
+ vma->vm_ops = &erofs_dax_vm_ops;
+ vma->vm_flags |= VM_HUGEPAGE;
return 0;
}
-
-/* for uncompressed (aligned) files and raw access for other files */
-const struct address_space_operations erofs_raw_access_aops = {
- .readpage = erofs_raw_access_readpage,
- .readahead = erofs_raw_access_readahead,
- .bmap = erofs_bmap,
+#else
+#define erofs_file_mmap generic_file_readonly_mmap
+#endif
+
+const struct file_operations erofs_file_fops = {
+ .llseek = generic_file_llseek,
+ .read_iter = erofs_file_read_iter,
+ .mmap = erofs_file_mmap,
+ .splice_read = generic_file_splice_read,
};
diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h
index 0f8da74570b4..b0b23f41abc3 100644
--- a/fs/erofs/erofs_fs.h
+++ b/fs/erofs/erofs_fs.h
@@ -4,6 +4,7 @@
*
* Copyright (C) 2017-2018 HUAWEI, Inc.
* https://www.huawei.com/
+ * Copyright (C) 2021, Alibaba Cloud
*/
#ifndef __EROFS_FS_H
#define __EROFS_FS_H
@@ -19,10 +20,12 @@
#define EROFS_FEATURE_INCOMPAT_LZ4_0PADDING 0x00000001
#define EROFS_FEATURE_INCOMPAT_COMPR_CFGS 0x00000002
#define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER 0x00000002
+#define EROFS_FEATURE_INCOMPAT_CHUNKED_FILE 0x00000004
#define EROFS_ALL_FEATURE_INCOMPAT \
(EROFS_FEATURE_INCOMPAT_LZ4_0PADDING | \
EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \
- EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER)
+ EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER | \
+ EROFS_FEATURE_INCOMPAT_CHUNKED_FILE)
#define EROFS_SB_EXTSLOT_SIZE 16
@@ -64,13 +67,16 @@ struct erofs_super_block {
* inode, [xattrs], last_inline_data, ... | ... | no-holed data
* 3 - inode compression D:
* inode, [xattrs], map_header, extents ... | ...
- * 4~7 - reserved
+ * 4 - inode chunk-based E:
+ * inode, [xattrs], chunk indexes ... | ...
+ * 5~7 - reserved
*/
enum {
EROFS_INODE_FLAT_PLAIN = 0,
EROFS_INODE_FLAT_COMPRESSION_LEGACY = 1,
EROFS_INODE_FLAT_INLINE = 2,
EROFS_INODE_FLAT_COMPRESSION = 3,
+ EROFS_INODE_CHUNK_BASED = 4,
EROFS_INODE_DATALAYOUT_MAX
};
@@ -90,6 +96,19 @@ static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
#define EROFS_I_ALL \
((1 << (EROFS_I_DATALAYOUT_BIT + EROFS_I_DATALAYOUT_BITS)) - 1)
+/* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */
+#define EROFS_CHUNK_FORMAT_BLKBITS_MASK 0x001F
+/* with chunk indexes or just a 4-byte blkaddr array */
+#define EROFS_CHUNK_FORMAT_INDEXES 0x0020
+
+#define EROFS_CHUNK_FORMAT_ALL \
+ (EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES)
+
+struct erofs_inode_chunk_info {
+ __le16 format; /* chunk blkbits, etc. */
+ __le16 reserved;
+};
+
/* 32-byte reduced form of an ondisk inode */
struct erofs_inode_compact {
__le16 i_format; /* inode format hints */
@@ -107,6 +126,9 @@ struct erofs_inode_compact {
/* for device files, used to indicate old/new device # */
__le32 rdev;
+
+ /* for chunk-based files, it contains the summary info */
+ struct erofs_inode_chunk_info c;
} i_u;
__le32 i_ino; /* only used for 32-bit stat compatibility */
__le16 i_uid;
@@ -135,6 +157,9 @@ struct erofs_inode_extended {
/* for device files, used to indicate old/new device # */
__le32 rdev;
+
+ /* for chunk-based files, it contains the summary info */
+ struct erofs_inode_chunk_info c;
} i_u;
/* only used for 32-bit stat compatibility */
@@ -204,6 +229,19 @@ static inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e)
e->e_name_len + le16_to_cpu(e->e_value_size));
}
+/* represent a zeroed chunk (hole) */
+#define EROFS_NULL_ADDR -1
+
+/* 4-byte block address array */
+#define EROFS_BLOCK_MAP_ENTRY_SIZE sizeof(__le32)
+
+/* 8-byte inode chunk indexes */
+struct erofs_inode_chunk_index {
+ __le16 advise; /* always 0, don't care for now */
+ __le16 device_id; /* back-end storage id, always 0 for now */
+ __le32 blkaddr; /* start block address of this inode chunk */
+};
+
/* maximum supported size of a physical compression cluster */
#define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024)
@@ -338,9 +376,14 @@ static inline void erofs_check_ondisk_layout_definitions(void)
BUILD_BUG_ON(sizeof(struct erofs_inode_extended) != 64);
BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12);
BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4);
+ BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4);
+ BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8);
BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8);
BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8);
BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12);
+ /* keep in sync between 2 index structures for better extendibility */
+ BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) !=
+ sizeof(struct z_erofs_vle_decompressed_index));
BUILD_BUG_ON(BIT(Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) <
Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1);
diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c
index aa8a0d770ba3..31ac3a73b390 100644
--- a/fs/erofs/inode.c
+++ b/fs/erofs/inode.c
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2017-2018 HUAWEI, Inc.
* https://www.huawei.com/
+ * Copyright (C) 2021, Alibaba Cloud
*/
#include "xattr.h"
@@ -122,8 +123,11 @@ static struct page *erofs_read_inode(struct inode *inode,
/* total blocks for compressed files */
if (erofs_inode_is_data_compressed(vi->datalayout))
nblks = le32_to_cpu(die->i_u.compressed_blocks);
-
+ else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
+ /* fill chunked inode summary info */
+ vi->chunkformat = le16_to_cpu(die->i_u.c.format);
kfree(copied);
+ copied = NULL;
break;
case EROFS_INODE_LAYOUT_COMPACT:
vi->inode_isize = sizeof(struct erofs_inode_compact);
@@ -160,6 +164,8 @@ static struct page *erofs_read_inode(struct inode *inode,
inode->i_size = le32_to_cpu(dic->i_size);
if (erofs_inode_is_data_compressed(vi->datalayout))
nblks = le32_to_cpu(dic->i_u.compressed_blocks);
+ else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
+ vi->chunkformat = le16_to_cpu(dic->i_u.c.format);
break;
default:
erofs_err(inode->i_sb,
@@ -169,11 +175,26 @@ static struct page *erofs_read_inode(struct inode *inode,
goto err_out;
}
+ if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
+ if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_ALL)) {
+ erofs_err(inode->i_sb,
+ "unsupported chunk format %x of nid %llu",
+ vi->chunkformat, vi->nid);
+ err = -EOPNOTSUPP;
+ goto err_out;
+ }
+ vi->chunkbits = LOG_BLOCK_SIZE +
+ (vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK);
+ }
inode->i_mtime.tv_sec = inode->i_ctime.tv_sec;
inode->i_atime.tv_sec = inode->i_ctime.tv_sec;
inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec;
inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec;
+ inode->i_flags &= ~S_DAX;
+ if (test_opt(&sbi->ctx, DAX_ALWAYS) && S_ISREG(inode->i_mode) &&
+ vi->datalayout == EROFS_INODE_FLAT_PLAIN)
+ inode->i_flags |= S_DAX;
if (!nblks)
/* measure inode.i_blocks as generic filesystems */
inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9;
@@ -247,7 +268,10 @@ static int erofs_fill_inode(struct inode *inode, int isdir)
switch (inode->i_mode & S_IFMT) {
case S_IFREG:
inode->i_op = &erofs_generic_iops;
- inode->i_fop = &generic_ro_fops;
+ if (erofs_inode_is_data_compressed(vi->datalayout))
+ inode->i_fop = &generic_ro_fops;
+ else
+ inode->i_fop = &erofs_file_fops;
break;
case S_IFDIR:
inode->i_op = &erofs_dir_iops;
@@ -358,6 +382,7 @@ const struct inode_operations erofs_generic_iops = {
.getattr = erofs_getattr,
.listxattr = erofs_listxattr,
.get_acl = erofs_get_acl,
+ .fiemap = erofs_fiemap,
};
const struct inode_operations erofs_symlink_iops = {
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 543c2ff97d30..9524e155b38f 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2017-2018 HUAWEI, Inc.
* https://www.huawei.com/
+ * Copyright (C) 2021, Alibaba Cloud
*/
#ifndef __EROFS_INTERNAL_H
#define __EROFS_INTERNAL_H
@@ -15,6 +16,7 @@
#include <linux/magic.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/iomap.h>
#include "erofs_fs.h"
/* redefine pr_fmt "erofs: " */
@@ -83,6 +85,7 @@ struct erofs_sb_info {
struct erofs_sb_lz4_info lz4;
#endif /* CONFIG_EROFS_FS_ZIP */
+ struct dax_device *dax_dev;
u32 blocks;
u32 meta_blkaddr;
#ifdef CONFIG_EROFS_FS_XATTR
@@ -115,6 +118,8 @@ struct erofs_sb_info {
/* Mount flags set via mount options or defaults */
#define EROFS_MOUNT_XATTR_USER 0x00000010
#define EROFS_MOUNT_POSIX_ACL 0x00000020
+#define EROFS_MOUNT_DAX_ALWAYS 0x00000040
+#define EROFS_MOUNT_DAX_NEVER 0x00000080
#define clear_opt(ctx, option) ((ctx)->mount_opt &= ~EROFS_MOUNT_##option)
#define set_opt(ctx, option) ((ctx)->mount_opt |= EROFS_MOUNT_##option)
@@ -257,6 +262,10 @@ struct erofs_inode {
union {
erofs_blk_t raw_blkaddr;
+ struct {
+ unsigned short chunkformat;
+ unsigned char chunkbits;
+ };
#ifdef CONFIG_EROFS_FS_ZIP
struct {
unsigned short z_advise;
@@ -353,8 +362,15 @@ struct erofs_map_blocks {
/* Flags used by erofs_map_blocks_flatmode() */
#define EROFS_GET_BLOCKS_RAW 0x0001
+/*
+ * Used to get the exact decompressed length, e.g. fiemap (consider lookback
+ * approach instead if possible since it's more metadata lightweight.)
+ */
+#define EROFS_GET_BLOCKS_FIEMAP 0x0002
/* zmap.c */
+extern const struct iomap_ops z_erofs_iomap_report_ops;
+
#ifdef CONFIG_EROFS_FS_ZIP
int z_erofs_fill_inode(struct inode *inode);
int z_erofs_map_blocks_iter(struct inode *inode,
@@ -371,7 +387,10 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode,
#endif /* !CONFIG_EROFS_FS_ZIP */
/* data.c */
+extern const struct file_operations erofs_file_fops;
struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr);
+int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ u64 start, u64 len);
/* inode.c */
static inline unsigned long erofs_inode_hash(erofs_nid_t nid)
@@ -441,8 +460,7 @@ int __init z_erofs_init_zip_subsystem(void);
void z_erofs_exit_zip_subsystem(void);
int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi,
struct erofs_workgroup *egrp);
-int erofs_try_to_free_cached_page(struct address_space *mapping,
- struct page *page);
+int erofs_try_to_free_cached_page(struct page *page);
int z_erofs_load_lz4_config(struct super_block *sb,
struct erofs_super_block *dsb,
struct z_erofs_lz4_cfgs *lz4, int len);
diff --git a/fs/erofs/namei.c b/fs/erofs/namei.c
index a8271ce5e13f..8629e616028c 100644
--- a/fs/erofs/namei.c
+++ b/fs/erofs/namei.c
@@ -245,4 +245,5 @@ const struct inode_operations erofs_dir_iops = {
.getattr = erofs_getattr,
.listxattr = erofs_listxattr,
.get_acl = erofs_get_acl,
+ .fiemap = erofs_fiemap,
};
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 8fc6c04b54f4..a8d49e8fc83a 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -11,6 +11,7 @@
#include <linux/crc32c.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
+#include <linux/dax.h>
#include "xattr.h"
#define CREATE_TRACE_POINTS
@@ -355,6 +356,8 @@ enum {
Opt_user_xattr,
Opt_acl,
Opt_cache_strategy,
+ Opt_dax,
+ Opt_dax_enum,
Opt_err
};
@@ -365,14 +368,47 @@ static const struct constant_table erofs_param_cache_strategy[] = {
{}
};
+static const struct constant_table erofs_dax_param_enums[] = {
+ {"always", EROFS_MOUNT_DAX_ALWAYS},
+ {"never", EROFS_MOUNT_DAX_NEVER},
+ {}
+};
+
static const struct fs_parameter_spec erofs_fs_parameters[] = {
fsparam_flag_no("user_xattr", Opt_user_xattr),
fsparam_flag_no("acl", Opt_acl),
fsparam_enum("cache_strategy", Opt_cache_strategy,
erofs_param_cache_strategy),
+ fsparam_flag("dax", Opt_dax),
+ fsparam_enum("dax", Opt_dax_enum, erofs_dax_param_enums),
{}
};
+static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
+{
+#ifdef CONFIG_FS_DAX
+ struct erofs_fs_context *ctx = fc->fs_private;
+
+ switch (mode) {
+ case EROFS_MOUNT_DAX_ALWAYS:
+ warnfc(fc, "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
+ set_opt(ctx, DAX_ALWAYS);
+ clear_opt(ctx, DAX_NEVER);
+ return true;
+ case EROFS_MOUNT_DAX_NEVER:
+ set_opt(ctx, DAX_NEVER);
+ clear_opt(ctx, DAX_ALWAYS);
+ return true;
+ default:
+ DBG_BUGON(1);
+ return false;
+ }
+#else
+ errorfc(fc, "dax options not supported");
+ return false;
+#endif
+}
+
static int erofs_fc_parse_param(struct fs_context *fc,
struct fs_parameter *param)
{
@@ -412,6 +448,14 @@ static int erofs_fc_parse_param(struct fs_context *fc,
errorfc(fc, "compression not supported, cache_strategy ignored");
#endif
break;
+ case Opt_dax:
+ if (!erofs_fc_set_dax_mode(fc, EROFS_MOUNT_DAX_ALWAYS))
+ return -EINVAL;
+ break;
+ case Opt_dax_enum:
+ if (!erofs_fc_set_dax_mode(fc, result.uint_32))
+ return -EINVAL;
+ break;
default:
return -ENOPARAM;
}
@@ -430,7 +474,7 @@ static int erofs_managed_cache_releasepage(struct page *page, gfp_t gfp_mask)
DBG_BUGON(mapping->a_ops != &managed_cache_aops);
if (PagePrivate(page))
- ret = erofs_try_to_free_cached_page(mapping, page);
+ ret = erofs_try_to_free_cached_page(page);
return ret;
}
@@ -496,10 +540,16 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
return -ENOMEM;
sb->s_fs_info = sbi;
+ sbi->dax_dev = fs_dax_get_by_bdev(sb->s_bdev);
err = erofs_read_superblock(sb);
if (err)
return err;
+ if (test_opt(ctx, DAX_ALWAYS) &&
+ !bdev_dax_supported(sb->s_bdev, EROFS_BLKSIZ)) {
+ errorfc(fc, "DAX unsupported by block device. Turning off DAX.");
+ clear_opt(ctx, DAX_ALWAYS);
+ }
sb->s_flags |= SB_RDONLY | SB_NOATIME;
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_time_gran = 1;
@@ -609,6 +659,7 @@ static void erofs_kill_sb(struct super_block *sb)
sbi = EROFS_SB(sb);
if (!sbi)
return;
+ fs_put_dax(sbi->dax_dev);
kfree(sbi);
sb->s_fs_info = NULL;
}
@@ -711,8 +762,8 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf)
static int erofs_show_options(struct seq_file *seq, struct dentry *root)
{
- struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb);
- struct erofs_fs_context *ctx __maybe_unused = &sbi->ctx;
+ struct erofs_sb_info *sbi = EROFS_SB(root->d_sb);
+ struct erofs_fs_context *ctx = &sbi->ctx;
#ifdef CONFIG_EROFS_FS_XATTR
if (test_opt(ctx, XATTR_USER))
@@ -734,6 +785,10 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root)
else if (ctx->cache_strategy == EROFS_ZIP_CACHE_READAROUND)
seq_puts(seq, ",cache_strategy=readaround");
#endif
+ if (test_opt(ctx, DAX_ALWAYS))
+ seq_puts(seq, ",dax=always");
+ if (test_opt(ctx, DAX_NEVER))
+ seq_puts(seq, ",dax=never");
return 0;
}
diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c
index 8dd54b420a1d..778f2c52295d 100644
--- a/fs/erofs/xattr.c
+++ b/fs/erofs/xattr.c
@@ -673,12 +673,15 @@ ssize_t erofs_listxattr(struct dentry *dentry,
}
#ifdef CONFIG_EROFS_FS_POSIX_ACL
-struct posix_acl *erofs_get_acl(struct inode *inode, int type)
+struct posix_acl *erofs_get_acl(struct inode *inode, int type, bool rcu)
{
struct posix_acl *acl;
int prefix, rc;
char *value = NULL;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch (type) {
case ACL_TYPE_ACCESS:
prefix = EROFS_XATTR_INDEX_POSIX_ACL_ACCESS;
diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h
index 366dcb400525..94090c74b3f7 100644
--- a/fs/erofs/xattr.h
+++ b/fs/erofs/xattr.h
@@ -80,7 +80,7 @@ static inline int erofs_getxattr(struct inode *inode, int index,
#endif /* !CONFIG_EROFS_FS_XATTR */
#ifdef CONFIG_EROFS_FS_POSIX_ACL
-struct posix_acl *erofs_get_acl(struct inode *inode, int type);
+struct posix_acl *erofs_get_acl(struct inode *inode, int type, bool rcu);
#else
#define erofs_get_acl (NULL)
#endif
diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
index cb4d0889eca9..11c7a1aaebad 100644
--- a/fs/erofs/zdata.c
+++ b/fs/erofs/zdata.c
@@ -309,7 +309,6 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi,
{
struct z_erofs_pcluster *const pcl =
container_of(grp, struct z_erofs_pcluster, obj);
- struct address_space *const mapping = MNGD_MAPPING(sbi);
int i;
/*
@@ -326,7 +325,7 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi,
if (!trylock_page(page))
return -EBUSY;
- if (page->mapping != mapping)
+ if (!erofs_page_is_managed(sbi, page))
continue;
/* barrier is implied in the following 'unlock_page' */
@@ -337,8 +336,7 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi,
return 0;
}
-int erofs_try_to_free_cached_page(struct address_space *mapping,
- struct page *page)
+int erofs_try_to_free_cached_page(struct page *page)
{
struct z_erofs_pcluster *const pcl = (void *)page_private(page);
int ret = 0; /* 0 - busy */
diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c
index f68aea4baed7..9fb98d85a3ce 100644
--- a/fs/erofs/zmap.c
+++ b/fs/erofs/zmap.c
@@ -212,9 +212,34 @@ static unsigned int decode_compactedbits(unsigned int lobits,
return lo;
}
+static int get_compacted_la_distance(unsigned int lclusterbits,
+ unsigned int encodebits,
+ unsigned int vcnt, u8 *in, int i)
+{
+ const unsigned int lomask = (1 << lclusterbits) - 1;
+ unsigned int lo, d1 = 0;
+ u8 type;
+
+ DBG_BUGON(i >= vcnt);
+
+ do {
+ lo = decode_compactedbits(lclusterbits, lomask,
+ in, encodebits * i, &type);
+
+ if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
+ return d1;
+ ++d1;
+ } while (++i < vcnt);
+
+ /* vcnt - 1 (Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) item */
+ if (!(lo & Z_EROFS_VLE_DI_D0_CBLKCNT))
+ d1 += lo - 1;
+ return d1;
+}
+
static int unpack_compacted_index(struct z_erofs_maprecorder *m,
unsigned int amortizedshift,
- unsigned int eofs)
+ unsigned int eofs, bool lookahead)
{
struct erofs_inode *const vi = EROFS_I(m->inode);
const unsigned int lclusterbits = vi->z_logical_clusterbits;
@@ -243,6 +268,11 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
m->type = type;
if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
m->clusterofs = 1 << lclusterbits;
+
+ /* figure out lookahead_distance: delta[1] if needed */
+ if (lookahead)
+ m->delta[1] = get_compacted_la_distance(lclusterbits,
+ encodebits, vcnt, in, i);
if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) {
if (!big_pcluster) {
DBG_BUGON(1);
@@ -313,7 +343,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
}
static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
- unsigned long lcn)
+ unsigned long lcn, bool lookahead)
{
struct inode *const inode = m->inode;
struct erofs_inode *const vi = EROFS_I(inode);
@@ -364,11 +394,12 @@ out:
err = z_erofs_reload_indexes(m, erofs_blknr(pos));
if (err)
return err;
- return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos));
+ return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos),
+ lookahead);
}
static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
- unsigned int lcn)
+ unsigned int lcn, bool lookahead)
{
const unsigned int datamode = EROFS_I(m->inode)->datalayout;
@@ -376,7 +407,7 @@ static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
return legacy_load_cluster_from_disk(m, lcn);
if (datamode == EROFS_INODE_FLAT_COMPRESSION)
- return compacted_load_cluster_from_disk(m, lcn);
+ return compacted_load_cluster_from_disk(m, lcn, lookahead);
return -EINVAL;
}
@@ -399,7 +430,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
/* load extent head logical cluster if needed */
lcn -= lookback_distance;
- err = z_erofs_load_cluster_from_disk(m, lcn);
+ err = z_erofs_load_cluster_from_disk(m, lcn, false);
if (err)
return err;
@@ -450,7 +481,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
if (m->compressedlcs)
goto out;
- err = z_erofs_load_cluster_from_disk(m, lcn);
+ err = z_erofs_load_cluster_from_disk(m, lcn, false);
if (err)
return err;
@@ -498,6 +529,48 @@ err_bonus_cblkcnt:
return -EFSCORRUPTED;
}
+static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
+{
+ struct inode *inode = m->inode;
+ struct erofs_inode *vi = EROFS_I(inode);
+ struct erofs_map_blocks *map = m->map;
+ unsigned int lclusterbits = vi->z_logical_clusterbits;
+ u64 lcn = m->lcn, headlcn = map->m_la >> lclusterbits;
+ int err;
+
+ do {
+ /* handle the last EOF pcluster (no next HEAD lcluster) */
+ if ((lcn << lclusterbits) >= inode->i_size) {
+ map->m_llen = inode->i_size - map->m_la;
+ return 0;
+ }
+
+ err = z_erofs_load_cluster_from_disk(m, lcn, true);
+ if (err)
+ return err;
+
+ if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
+ DBG_BUGON(!m->delta[1] &&
+ m->clusterofs != 1 << lclusterbits);
+ } else if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
+ m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD) {
+ /* go on until the next HEAD lcluster */
+ if (lcn != headlcn)
+ break;
+ m->delta[1] = 1;
+ } else {
+ erofs_err(inode->i_sb, "unknown type %u @ lcn %llu of nid %llu",
+ m->type, lcn, vi->nid);
+ DBG_BUGON(1);
+ return -EOPNOTSUPP;
+ }
+ lcn += m->delta[1];
+ } while (m->delta[1]);
+
+ map->m_llen = (lcn << lclusterbits) + m->clusterofs - map->m_la;
+ return 0;
+}
+
int z_erofs_map_blocks_iter(struct inode *inode,
struct erofs_map_blocks *map,
int flags)
@@ -531,7 +604,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
initial_lcn = ofs >> lclusterbits;
endoff = ofs & ((1 << lclusterbits) - 1);
- err = z_erofs_load_cluster_from_disk(&m, initial_lcn);
+ err = z_erofs_load_cluster_from_disk(&m, initial_lcn, false);
if (err)
goto unmap_out;
@@ -581,6 +654,12 @@ int z_erofs_map_blocks_iter(struct inode *inode,
err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
if (err)
goto out;
+
+ if (flags & EROFS_GET_BLOCKS_FIEMAP) {
+ err = z_erofs_get_extent_decompressedlen(&m);
+ if (!err)
+ map->m_flags |= EROFS_MAP_FULL_MAPPED;
+ }
unmap_out:
if (m.kaddr)
kunmap_atomic(m.kaddr);
@@ -596,3 +675,41 @@ out:
DBG_BUGON(err < 0 && err != -ENOMEM);
return err;
}
+
+static int z_erofs_iomap_begin_report(struct inode *inode, loff_t offset,
+ loff_t length, unsigned int flags,
+ struct iomap *iomap, struct iomap *srcmap)
+{
+ int ret;
+ struct erofs_map_blocks map = { .m_la = offset };
+
+ ret = z_erofs_map_blocks_iter(inode, &map, EROFS_GET_BLOCKS_FIEMAP);
+ if (map.mpage)
+ put_page(map.mpage);
+ if (ret < 0)
+ return ret;
+
+ iomap->bdev = inode->i_sb->s_bdev;
+ iomap->offset = map.m_la;
+ iomap->length = map.m_llen;
+ if (map.m_flags & EROFS_MAP_MAPPED) {
+ iomap->type = IOMAP_MAPPED;
+ iomap->addr = map.m_pa;
+ } else {
+ iomap->type = IOMAP_HOLE;
+ iomap->addr = IOMAP_NULL_ADDR;
+ /*
+ * No strict rule how to describe extents for post EOF, yet
+ * we need do like below. Otherwise, iomap itself will get
+ * into an endless loop on post EOF.
+ */
+ if (iomap->offset >= inode->i_size)
+ iomap->length = length + map.m_la - offset;
+ }
+ iomap->flags = 0;
+ return 0;
+}
+
+const struct iomap_ops z_erofs_iomap_report_ops = {
+ .iomap_begin = z_erofs_iomap_begin_report,
+};
diff --git a/fs/exec.c b/fs/exec.c
index 3b78b22addfb..a098c133d8d7 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -217,8 +217,10 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
* We are doing an exec(). 'current' is the process
* doing the exec and bprm->mm is the new process's mm.
*/
+ mmap_read_lock(bprm->mm);
ret = get_user_pages_remote(bprm->mm, pos, 1, gup_flags,
&page, NULL, NULL);
+ mmap_read_unlock(bprm->mm);
if (ret <= 0)
return NULL;
@@ -574,7 +576,7 @@ static int copy_strings(int argc, struct user_arg_ptr argv,
}
if (kmapped_page) {
- flush_kernel_dcache_page(kmapped_page);
+ flush_dcache_page(kmapped_page);
kunmap(kmapped_page);
put_arg_page(kmapped_page);
}
@@ -592,7 +594,7 @@ static int copy_strings(int argc, struct user_arg_ptr argv,
ret = 0;
out:
if (kmapped_page) {
- flush_kernel_dcache_page(kmapped_page);
+ flush_dcache_page(kmapped_page);
kunmap(kmapped_page);
put_arg_page(kmapped_page);
}
@@ -634,7 +636,7 @@ int copy_string_kernel(const char *arg, struct linux_binprm *bprm)
kaddr = kmap_atomic(page);
flush_arg_page(bprm, pos & PAGE_MASK, page);
memcpy(kaddr + offset_in_page(pos), arg, bytes_to_copy);
- flush_kernel_dcache_page(page);
+ flush_dcache_page(page);
kunmap_atomic(kaddr);
put_arg_page(page);
}
@@ -1270,7 +1272,9 @@ int begin_new_exec(struct linux_binprm * bprm)
* not visibile until then. This also enables the update
* to be lockless.
*/
- set_mm_exe_file(bprm->mm, bprm->file);
+ retval = set_mm_exe_file(bprm->mm, bprm->file);
+ if (retval)
+ goto out;
/* If the binary is not readable then enforce mm->dumpable=0 */
would_dump(bprm, bprm->file);
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index b9a9db98e94b..bf298967c5b8 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -141,13 +141,16 @@ fail:
* inode->i_mutex: don't care
*/
struct posix_acl *
-ext2_get_acl(struct inode *inode, int type)
+ext2_get_acl(struct inode *inode, int type, bool rcu)
{
int name_index;
char *value = NULL;
struct posix_acl *acl;
int retval;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch (type) {
case ACL_TYPE_ACCESS:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index 917db5f6630a..925ab6287d35 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -55,7 +55,7 @@ static inline int ext2_acl_count(size_t size)
#ifdef CONFIG_EXT2_FS_POSIX_ACL
/* acl.c */
-extern struct posix_acl *ext2_get_acl(struct inode *inode, int type);
+extern struct posix_acl *ext2_get_acl(struct inode *inode, int type, bool rcu);
extern int ext2_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
extern int ext2_init_acl (struct inode *, struct inode *);
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 49e7af6cc93f..7d89142e1421 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -10,7 +10,7 @@ ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
super.o symlink.o sysfs.o xattr.o xattr_hurd.o xattr_trusted.o \
- xattr_user.o fast_commit.o
+ xattr_user.o fast_commit.o orphan.o
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index c5eaffccecc3..0613dfcbfd4a 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -142,13 +142,16 @@ fail:
* inode->i_mutex: don't care
*/
struct posix_acl *
-ext4_get_acl(struct inode *inode, int type)
+ext4_get_acl(struct inode *inode, int type, bool rcu)
{
int name_index;
char *value = NULL;
struct posix_acl *acl;
int retval;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch (type) {
case ACL_TYPE_ACCESS:
name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
index 84b8942a57f2..3219669732bf 100644
--- a/fs/ext4/acl.h
+++ b/fs/ext4/acl.h
@@ -55,7 +55,7 @@ static inline int ext4_acl_count(size_t size)
#ifdef CONFIG_EXT4_FS_POSIX_ACL
/* acl.c */
-struct posix_acl *ext4_get_acl(struct inode *inode, int type);
+struct posix_acl *ext4_get_acl(struct inode *inode, int type, bool rcu);
int ext4_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 9dc6e74b265c..a0fb0c4bdc7c 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -652,8 +652,14 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
* possible we just missed a transaction commit that did so
*/
smp_mb();
- if (sbi->s_mb_free_pending == 0)
+ if (sbi->s_mb_free_pending == 0) {
+ if (test_opt(sb, DISCARD)) {
+ atomic_inc(&sbi->s_retry_alloc_pending);
+ flush_work(&sbi->s_discard_work);
+ atomic_dec(&sbi->s_retry_alloc_pending);
+ }
return ext4_has_free_clusters(sbi, 1, 0);
+ }
/*
* it's possible we've just missed a transaction commit here,
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 7ebaf66b6e31..90ff5acaf11f 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1034,7 +1034,14 @@ struct ext4_inode_info {
*/
struct rw_semaphore xattr_sem;
- struct list_head i_orphan; /* unlinked but open inodes */
+ /*
+ * Inodes with EXT4_STATE_ORPHAN_FILE use i_orphan_idx. Otherwise
+ * i_orphan is used.
+ */
+ union {
+ struct list_head i_orphan; /* unlinked but open inodes */
+ unsigned int i_orphan_idx; /* Index in orphan file */
+ };
/* Fast commit related info */
@@ -1419,7 +1426,8 @@ struct ext4_super_block {
__u8 s_last_error_errcode;
__le16 s_encoding; /* Filename charset encoding */
__le16 s_encoding_flags; /* Filename charset encoding flags */
- __le32 s_reserved[95]; /* Padding to the end of the block */
+ __le32 s_orphan_file_inum; /* Inode for tracking orphan inodes */
+ __le32 s_reserved[94]; /* Padding to the end of the block */
__le32 s_checksum; /* crc32c(superblock) */
};
@@ -1438,6 +1446,54 @@ struct ext4_super_block {
#define EXT4_ENC_UTF8_12_1 1
+/* Types of ext4 journal triggers */
+enum ext4_journal_trigger_type {
+ EXT4_JTR_ORPHAN_FILE,
+ EXT4_JTR_NONE /* This must be the last entry for indexing to work! */
+};
+
+#define EXT4_JOURNAL_TRIGGER_COUNT EXT4_JTR_NONE
+
+struct ext4_journal_trigger {
+ struct jbd2_buffer_trigger_type tr_triggers;
+ struct super_block *sb;
+};
+
+static inline struct ext4_journal_trigger *EXT4_TRIGGER(
+ struct jbd2_buffer_trigger_type *trigger)
+{
+ return container_of(trigger, struct ext4_journal_trigger, tr_triggers);
+}
+
+#define EXT4_ORPHAN_BLOCK_MAGIC 0x0b10ca04
+
+/* Structure at the tail of orphan block */
+struct ext4_orphan_block_tail {
+ __le32 ob_magic;
+ __le32 ob_checksum;
+};
+
+static inline int ext4_inodes_per_orphan_block(struct super_block *sb)
+{
+ return (sb->s_blocksize - sizeof(struct ext4_orphan_block_tail)) /
+ sizeof(u32);
+}
+
+struct ext4_orphan_block {
+ atomic_t ob_free_entries; /* Number of free orphan entries in block */
+ struct buffer_head *ob_bh; /* Buffer for orphan block */
+};
+
+/*
+ * Info about orphan file.
+ */
+struct ext4_orphan_info {
+ int of_blocks; /* Number of orphan blocks in a file */
+ __u32 of_csum_seed; /* Checksum seed for orphan file */
+ struct ext4_orphan_block *of_binfo; /* Array with info about orphan
+ * file blocks */
+};
+
/*
* fourth extended-fs super-block data in memory
*/
@@ -1492,9 +1548,11 @@ struct ext4_sb_info {
/* Journaling */
struct journal_s *s_journal;
- struct list_head s_orphan;
- struct mutex s_orphan_lock;
unsigned long s_ext4_flags; /* Ext4 superblock flags */
+ struct mutex s_orphan_lock; /* Protects on disk list changes */
+ struct list_head s_orphan; /* List of orphaned inodes in on disk
+ list */
+ struct ext4_orphan_info s_orphan_info;
unsigned long s_commit_interval;
u32 s_max_batch_time;
u32 s_min_batch_time;
@@ -1527,6 +1585,9 @@ struct ext4_sb_info {
unsigned int s_mb_free_pending;
struct list_head s_freed_data_list; /* List of blocks to be freed
after commit completed */
+ struct list_head s_discard_list;
+ struct work_struct s_discard_work;
+ atomic_t s_retry_alloc_pending;
struct rb_root s_mb_avg_fragment_size_root;
rwlock_t s_mb_rb_lock;
struct list_head *s_mb_largest_free_orders;
@@ -1616,6 +1677,9 @@ struct ext4_sb_info {
struct mb_cache *s_ea_inode_cache;
spinlock_t s_es_lock ____cacheline_aligned_in_smp;
+ /* Journal triggers for checksum computation */
+ struct ext4_journal_trigger s_journal_triggers[EXT4_JOURNAL_TRIGGER_COUNT];
+
/* Ratelimit ext4 messages. */
struct ratelimit_state s_err_ratelimit_state;
struct ratelimit_state s_warning_ratelimit_state;
@@ -1826,6 +1890,7 @@ enum {
EXT4_STATE_LUSTRE_EA_INODE, /* Lustre-style ea_inode */
EXT4_STATE_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */
EXT4_STATE_FC_COMMITTING, /* Fast commit ongoing */
+ EXT4_STATE_ORPHAN_FILE, /* Inode orphaned in orphan file */
};
#define EXT4_INODE_BIT_FNS(name, field, offset) \
@@ -1927,6 +1992,7 @@ static inline bool ext4_verity_in_progress(struct inode *inode)
*/
#define EXT4_FEATURE_COMPAT_FAST_COMMIT 0x0400
#define EXT4_FEATURE_COMPAT_STABLE_INODES 0x0800
+#define EXT4_FEATURE_COMPAT_ORPHAN_FILE 0x1000 /* Orphan file exists */
#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
@@ -1947,6 +2013,8 @@ static inline bool ext4_verity_in_progress(struct inode *inode)
#define EXT4_FEATURE_RO_COMPAT_READONLY 0x1000
#define EXT4_FEATURE_RO_COMPAT_PROJECT 0x2000
#define EXT4_FEATURE_RO_COMPAT_VERITY 0x8000
+#define EXT4_FEATURE_RO_COMPAT_ORPHAN_PRESENT 0x10000 /* Orphan file may be
+ non-empty */
#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002
@@ -2030,6 +2098,7 @@ EXT4_FEATURE_COMPAT_FUNCS(dir_index, DIR_INDEX)
EXT4_FEATURE_COMPAT_FUNCS(sparse_super2, SPARSE_SUPER2)
EXT4_FEATURE_COMPAT_FUNCS(fast_commit, FAST_COMMIT)
EXT4_FEATURE_COMPAT_FUNCS(stable_inodes, STABLE_INODES)
+EXT4_FEATURE_COMPAT_FUNCS(orphan_file, ORPHAN_FILE)
EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super, SPARSE_SUPER)
EXT4_FEATURE_RO_COMPAT_FUNCS(large_file, LARGE_FILE)
@@ -2044,6 +2113,7 @@ EXT4_FEATURE_RO_COMPAT_FUNCS(metadata_csum, METADATA_CSUM)
EXT4_FEATURE_RO_COMPAT_FUNCS(readonly, READONLY)
EXT4_FEATURE_RO_COMPAT_FUNCS(project, PROJECT)
EXT4_FEATURE_RO_COMPAT_FUNCS(verity, VERITY)
+EXT4_FEATURE_RO_COMPAT_FUNCS(orphan_present, ORPHAN_PRESENT)
EXT4_FEATURE_INCOMPAT_FUNCS(compression, COMPRESSION)
EXT4_FEATURE_INCOMPAT_FUNCS(filetype, FILETYPE)
@@ -2077,7 +2147,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(casefold, CASEFOLD)
EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
-#define EXT4_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR
+#define EXT4_FEATURE_COMPAT_SUPP (EXT4_FEATURE_COMPAT_EXT_ATTR| \
+ EXT4_FEATURE_COMPAT_ORPHAN_FILE)
#define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \
EXT4_FEATURE_INCOMPAT_RECOVER| \
EXT4_FEATURE_INCOMPAT_META_BG| \
@@ -2102,7 +2173,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(casefold, CASEFOLD)
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
EXT4_FEATURE_RO_COMPAT_QUOTA |\
EXT4_FEATURE_RO_COMPAT_PROJECT |\
- EXT4_FEATURE_RO_COMPAT_VERITY)
+ EXT4_FEATURE_RO_COMPAT_VERITY |\
+ EXT4_FEATURE_RO_COMPAT_ORPHAN_PRESENT)
#define EXTN_FEATURE_FUNCS(ver) \
static inline bool ext4_has_unknown_ext##ver##_compat_features(struct super_block *sb) \
@@ -2138,6 +2210,8 @@ static inline bool ext4_has_incompat_features(struct super_block *sb)
return (EXT4_SB(sb)->s_es->s_feature_incompat != 0);
}
+extern int ext4_feature_set_ok(struct super_block *sb, int readonly);
+
/*
* Superblock flags
*/
@@ -2150,7 +2224,6 @@ static inline int ext4_forced_shutdown(struct ext4_sb_info *sbi)
return test_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
}
-
/*
* Default values for user and/or group using reserved blocks
*/
@@ -2911,13 +2984,14 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create);
int ext4_walk_page_buffers(handle_t *handle,
+ struct inode *inode,
struct buffer_head *head,
unsigned from,
unsigned to,
int *partial,
- int (*fn)(handle_t *handle,
+ int (*fn)(handle_t *handle, struct inode *inode,
struct buffer_head *bh));
-int do_journal_get_write_access(handle_t *handle,
+int do_journal_get_write_access(handle_t *handle, struct inode *inode,
struct buffer_head *bh);
#define FALL_BACK_TO_NONDELALLOC 1
#define CONVERT_INLINE_DATA 2
@@ -2996,8 +3070,6 @@ extern int ext4_init_new_dir(handle_t *handle, struct inode *dir,
struct inode *inode);
extern int ext4_dirblock_csum_verify(struct inode *inode,
struct buffer_head *bh);
-extern int ext4_orphan_add(handle_t *, struct inode *);
-extern int ext4_orphan_del(handle_t *, struct inode *);
extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
__u32 start_minor_hash, __u32 *next_hash);
extern int ext4_search_dir(struct buffer_head *bh,
@@ -3466,6 +3538,7 @@ static inline bool ext4_is_quota_journalled(struct super_block *sb)
return (ext4_has_feature_quota(sb) ||
sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]);
}
+int ext4_enable_quotas(struct super_block *sb);
#endif
/*
@@ -3727,6 +3800,19 @@ extern void ext4_stop_mmpd(struct ext4_sb_info *sbi);
/* verity.c */
extern const struct fsverity_operations ext4_verityops;
+/* orphan.c */
+extern int ext4_orphan_add(handle_t *, struct inode *);
+extern int ext4_orphan_del(handle_t *, struct inode *);
+extern void ext4_orphan_cleanup(struct super_block *sb,
+ struct ext4_super_block *es);
+extern void ext4_release_orphan_info(struct super_block *sb);
+extern int ext4_init_orphan_info(struct super_block *sb);
+extern int ext4_orphan_file_empty(struct super_block *sb);
+extern void ext4_orphan_file_block_trigger(
+ struct jbd2_buffer_trigger_type *triggers,
+ struct buffer_head *bh,
+ void *data, size_t size);
+
/*
* Add new method to test whether block and inode bitmaps are properly
* initialized. With uninit_bg reading the block from disk is not enough
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
index 44e59881a1f0..26435f3a3094 100644
--- a/fs/ext4/ext4_extents.h
+++ b/fs/ext4/ext4_extents.h
@@ -173,10 +173,11 @@ struct partial_cluster {
#define EXT_MAX_EXTENT(__hdr__) \
((le16_to_cpu((__hdr__)->eh_max)) ? \
((EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) \
- : 0)
+ : NULL)
#define EXT_MAX_INDEX(__hdr__) \
((le16_to_cpu((__hdr__)->eh_max)) ? \
- ((EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) : 0)
+ ((EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) \
+ : NULL)
static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
{
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index b60f0152ea57..6def7339056d 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -218,9 +218,11 @@ static void ext4_check_bdev_write_error(struct super_block *sb)
}
int __ext4_journal_get_write_access(const char *where, unsigned int line,
- handle_t *handle, struct buffer_head *bh)
+ handle_t *handle, struct super_block *sb,
+ struct buffer_head *bh,
+ enum ext4_journal_trigger_type trigger_type)
{
- int err = 0;
+ int err;
might_sleep();
@@ -229,11 +231,18 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
if (ext4_handle_valid(handle)) {
err = jbd2_journal_get_write_access(handle, bh);
- if (err)
+ if (err) {
ext4_journal_abort_handle(where, line, __func__, bh,
handle, err);
+ return err;
+ }
}
- return err;
+ if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
+ return 0;
+ BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
+ jbd2_journal_set_triggers(bh,
+ &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
+ return 0;
}
/*
@@ -301,17 +310,27 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
}
int __ext4_journal_get_create_access(const char *where, unsigned int line,
- handle_t *handle, struct buffer_head *bh)
+ handle_t *handle, struct super_block *sb,
+ struct buffer_head *bh,
+ enum ext4_journal_trigger_type trigger_type)
{
- int err = 0;
+ int err;
- if (ext4_handle_valid(handle)) {
- err = jbd2_journal_get_create_access(handle, bh);
- if (err)
- ext4_journal_abort_handle(where, line, __func__,
- bh, handle, err);
+ if (!ext4_handle_valid(handle))
+ return 0;
+
+ err = jbd2_journal_get_create_access(handle, bh);
+ if (err) {
+ ext4_journal_abort_handle(where, line, __func__, bh, handle,
+ err);
+ return err;
}
- return err;
+ if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
+ return 0;
+ BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
+ jbd2_journal_set_triggers(bh,
+ &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
+ return 0;
}
int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 0d2fa423b7ad..0e4fa644df01 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -231,26 +231,32 @@ int ext4_expand_extra_isize(struct inode *inode,
* Wrapper functions with which ext4 calls into JBD.
*/
int __ext4_journal_get_write_access(const char *where, unsigned int line,
- handle_t *handle, struct buffer_head *bh);
+ handle_t *handle, struct super_block *sb,
+ struct buffer_head *bh,
+ enum ext4_journal_trigger_type trigger_type);
int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
int is_metadata, struct inode *inode,
struct buffer_head *bh, ext4_fsblk_t blocknr);
int __ext4_journal_get_create_access(const char *where, unsigned int line,
- handle_t *handle, struct buffer_head *bh);
+ handle_t *handle, struct super_block *sb,
+ struct buffer_head *bh,
+ enum ext4_journal_trigger_type trigger_type);
int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
handle_t *handle, struct inode *inode,
struct buffer_head *bh);
-#define ext4_journal_get_write_access(handle, bh) \
- __ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
+#define ext4_journal_get_write_access(handle, sb, bh, trigger_type) \
+ __ext4_journal_get_write_access(__func__, __LINE__, (handle), (sb), \
+ (bh), (trigger_type))
#define ext4_forget(handle, is_metadata, inode, bh, block_nr) \
__ext4_forget(__func__, __LINE__, (handle), (is_metadata), (inode), \
(bh), (block_nr))
-#define ext4_journal_get_create_access(handle, bh) \
- __ext4_journal_get_create_access(__func__, __LINE__, (handle), (bh))
+#define ext4_journal_get_create_access(handle, sb, bh, trigger_type) \
+ __ext4_journal_get_create_access(__func__, __LINE__, (handle), (sb), \
+ (bh), (trigger_type))
#define ext4_handle_dirty_metadata(handle, inode, bh) \
__ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \
(bh))
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index c33e0a2cb6c3..c0de30f25185 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -139,7 +139,8 @@ static int ext4_ext_get_access(handle_t *handle, struct inode *inode,
if (path->p_bh) {
/* path points to block */
BUFFER_TRACE(path->p_bh, "get_write_access");
- return ext4_journal_get_write_access(handle, path->p_bh);
+ return ext4_journal_get_write_access(handle, inode->i_sb,
+ path->p_bh, EXT4_JTR_NONE);
}
/* path points to leaf/index in inode body */
/* we use in-core data, no need to protect them */
@@ -1082,7 +1083,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
}
lock_buffer(bh);
- err = ext4_journal_get_create_access(handle, bh);
+ err = ext4_journal_get_create_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (err)
goto cleanup;
@@ -1160,7 +1162,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
}
lock_buffer(bh);
- err = ext4_journal_get_create_access(handle, bh);
+ err = ext4_journal_get_create_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (err)
goto cleanup;
@@ -1286,7 +1289,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
return -ENOMEM;
lock_buffer(bh);
- err = ext4_journal_get_create_access(handle, bh);
+ err = ext4_journal_get_create_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (err) {
unlock_buffer(bh);
goto out;
@@ -3569,7 +3573,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
split_map.m_len - ee_block);
err = ext4_ext_zeroout(inode, &zero_ex1);
if (err)
- goto out;
+ goto fallback;
split_map.m_len = allocated;
}
if (split_map.m_lblk - ee_block + split_map.m_len <
@@ -3583,7 +3587,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
ext4_ext_pblock(ex));
err = ext4_ext_zeroout(inode, &zero_ex2);
if (err)
- goto out;
+ goto fallback;
}
split_map.m_len += split_map.m_lblk - ee_block;
@@ -3592,6 +3596,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
}
}
+fallback:
err = ext4_split_extent(handle, inode, ppath, &split_map, split_flag,
flags);
if (err > 0)
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index e8195229c252..8e610a381862 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -775,28 +775,27 @@ static bool ext4_fc_add_tlv(struct super_block *sb, u16 tag, u16 len, u8 *val,
}
/* Same as above, but adds dentry tlv. */
-static bool ext4_fc_add_dentry_tlv(struct super_block *sb, u16 tag,
- int parent_ino, int ino, int dlen,
- const unsigned char *dname,
- u32 *crc)
+static bool ext4_fc_add_dentry_tlv(struct super_block *sb, u32 *crc,
+ struct ext4_fc_dentry_update *fc_dentry)
{
struct ext4_fc_dentry_info fcd;
struct ext4_fc_tl tl;
+ int dlen = fc_dentry->fcd_name.len;
u8 *dst = ext4_fc_reserve_space(sb, sizeof(tl) + sizeof(fcd) + dlen,
crc);
if (!dst)
return false;
- fcd.fc_parent_ino = cpu_to_le32(parent_ino);
- fcd.fc_ino = cpu_to_le32(ino);
- tl.fc_tag = cpu_to_le16(tag);
+ fcd.fc_parent_ino = cpu_to_le32(fc_dentry->fcd_parent);
+ fcd.fc_ino = cpu_to_le32(fc_dentry->fcd_ino);
+ tl.fc_tag = cpu_to_le16(fc_dentry->fcd_op);
tl.fc_len = cpu_to_le16(sizeof(fcd) + dlen);
ext4_fc_memcpy(sb, dst, &tl, sizeof(tl), crc);
dst += sizeof(tl);
ext4_fc_memcpy(sb, dst, &fcd, sizeof(fcd), crc);
dst += sizeof(fcd);
- ext4_fc_memcpy(sb, dst, dname, dlen, crc);
+ ext4_fc_memcpy(sb, dst, fc_dentry->fcd_name.name, dlen, crc);
dst += dlen;
return true;
@@ -992,11 +991,7 @@ __releases(&sbi->s_fc_lock)
&sbi->s_fc_dentry_q[FC_Q_MAIN], fcd_list) {
if (fc_dentry->fcd_op != EXT4_FC_TAG_CREAT) {
spin_unlock(&sbi->s_fc_lock);
- if (!ext4_fc_add_dentry_tlv(
- sb, fc_dentry->fcd_op,
- fc_dentry->fcd_parent, fc_dentry->fcd_ino,
- fc_dentry->fcd_name.len,
- fc_dentry->fcd_name.name, crc)) {
+ if (!ext4_fc_add_dentry_tlv(sb, crc, fc_dentry)) {
ret = -ENOSPC;
goto lock_and_exit;
}
@@ -1035,11 +1030,7 @@ __releases(&sbi->s_fc_lock)
if (ret)
goto lock_and_exit;
- if (!ext4_fc_add_dentry_tlv(
- sb, fc_dentry->fcd_op,
- fc_dentry->fcd_parent, fc_dentry->fcd_ino,
- fc_dentry->fcd_name.len,
- fc_dentry->fcd_name.name, crc)) {
+ if (!ext4_fc_add_dentry_tlv(sb, crc, fc_dentry)) {
ret = -ENOSPC;
goto lock_and_exit;
}
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index d3b4ed91aa68..ac0e11bbb445 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -823,7 +823,8 @@ static int ext4_sample_last_mounted(struct super_block *sb,
if (IS_ERR(handle))
goto out;
BUFFER_TRACE(sbi->s_sbh, "get_write_access");
- err = ext4_journal_get_write_access(handle, sbi->s_sbh);
+ err = ext4_journal_get_write_access(handle, sb, sbi->s_sbh,
+ EXT4_JTR_NONE);
if (err)
goto out_journal;
lock_buffer(sbi->s_sbh);
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index e89fc0f770b0..f73e5eb43eae 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -300,7 +300,8 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
}
BUFFER_TRACE(bitmap_bh, "get_write_access");
- fatal = ext4_journal_get_write_access(handle, bitmap_bh);
+ fatal = ext4_journal_get_write_access(handle, sb, bitmap_bh,
+ EXT4_JTR_NONE);
if (fatal)
goto error_return;
@@ -308,7 +309,8 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
gdp = ext4_get_group_desc(sb, block_group, &bh2);
if (gdp) {
BUFFER_TRACE(bh2, "get_write_access");
- fatal = ext4_journal_get_write_access(handle, bh2);
+ fatal = ext4_journal_get_write_access(handle, sb, bh2,
+ EXT4_JTR_NONE);
}
ext4_lock_group(sb, block_group);
cleared = ext4_test_and_clear_bit(bit, bitmap_bh->b_data);
@@ -1085,7 +1087,8 @@ repeat_in_this_group:
}
}
BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
+ err = ext4_journal_get_write_access(handle, sb, inode_bitmap_bh,
+ EXT4_JTR_NONE);
if (err) {
ext4_std_error(sb, err);
goto out;
@@ -1127,7 +1130,8 @@ got:
}
BUFFER_TRACE(group_desc_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, group_desc_bh);
+ err = ext4_journal_get_write_access(handle, sb, group_desc_bh,
+ EXT4_JTR_NONE);
if (err) {
ext4_std_error(sb, err);
goto out;
@@ -1144,7 +1148,8 @@ got:
goto out;
}
BUFFER_TRACE(block_bitmap_bh, "get block bitmap access");
- err = ext4_journal_get_write_access(handle, block_bitmap_bh);
+ err = ext4_journal_get_write_access(handle, sb, block_bitmap_bh,
+ EXT4_JTR_NONE);
if (err) {
brelse(block_bitmap_bh);
ext4_std_error(sb, err);
@@ -1583,8 +1588,8 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
num = sbi->s_itb_per_group - used_blks;
BUFFER_TRACE(group_desc_bh, "get_write_access");
- ret = ext4_journal_get_write_access(handle,
- group_desc_bh);
+ ret = ext4_journal_get_write_access(handle, sb, group_desc_bh,
+ EXT4_JTR_NONE);
if (ret)
goto err_out;
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index a7bc6ad656a9..89efa78ed4b2 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -354,7 +354,8 @@ static int ext4_alloc_branch(handle_t *handle,
}
lock_buffer(bh);
BUFFER_TRACE(bh, "call get_create_access");
- err = ext4_journal_get_create_access(handle, bh);
+ err = ext4_journal_get_create_access(handle, ar->inode->i_sb,
+ bh, EXT4_JTR_NONE);
if (err) {
unlock_buffer(bh);
goto failed;
@@ -429,7 +430,8 @@ static int ext4_splice_branch(handle_t *handle,
*/
if (where->bh) {
BUFFER_TRACE(where->bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, where->bh);
+ err = ext4_journal_get_write_access(handle, ar->inode->i_sb,
+ where->bh, EXT4_JTR_NONE);
if (err)
goto err_out;
}
@@ -728,7 +730,8 @@ static int ext4_ind_truncate_ensure_credits(handle_t *handle,
return ret;
if (bh) {
BUFFER_TRACE(bh, "retaking write access");
- ret = ext4_journal_get_write_access(handle, bh);
+ ret = ext4_journal_get_write_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (unlikely(ret))
return ret;
}
@@ -916,7 +919,8 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
if (this_bh) { /* For indirect block */
BUFFER_TRACE(this_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, this_bh);
+ err = ext4_journal_get_write_access(handle, inode->i_sb,
+ this_bh, EXT4_JTR_NONE);
/* Important: if we can't update the indirect pointers
* to the blocks, we can't free them. */
if (err)
@@ -1079,7 +1083,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
*/
BUFFER_TRACE(parent_bh, "get_write_access");
if (!ext4_journal_get_write_access(handle,
- parent_bh)){
+ inode->i_sb, parent_bh,
+ EXT4_JTR_NONE)) {
*p = 0;
BUFFER_TRACE(parent_bh,
"call ext4_handle_dirty_metadata");
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 70cb64db33f7..82bf4ff6be28 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -264,7 +264,8 @@ static int ext4_create_inline_data(handle_t *handle,
return error;
BUFFER_TRACE(is.iloc.bh, "get_write_access");
- error = ext4_journal_get_write_access(handle, is.iloc.bh);
+ error = ext4_journal_get_write_access(handle, inode->i_sb, is.iloc.bh,
+ EXT4_JTR_NONE);
if (error)
goto out;
@@ -350,7 +351,8 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
goto out;
BUFFER_TRACE(is.iloc.bh, "get_write_access");
- error = ext4_journal_get_write_access(handle, is.iloc.bh);
+ error = ext4_journal_get_write_access(handle, inode->i_sb, is.iloc.bh,
+ EXT4_JTR_NONE);
if (error)
goto out;
@@ -427,7 +429,8 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,
goto out;
BUFFER_TRACE(is.iloc.bh, "get_write_access");
- error = ext4_journal_get_write_access(handle, is.iloc.bh);
+ error = ext4_journal_get_write_access(handle, inode->i_sb, is.iloc.bh,
+ EXT4_JTR_NONE);
if (error)
goto out;
@@ -593,7 +596,7 @@ retry:
ret = __block_write_begin(page, from, to, ext4_get_block);
if (!ret && ext4_should_journal_data(inode)) {
- ret = ext4_walk_page_buffers(handle, page_buffers(page),
+ ret = ext4_walk_page_buffers(handle, inode, page_buffers(page),
from, to, NULL,
do_journal_get_write_access);
}
@@ -682,7 +685,8 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
goto convert;
}
- ret = ext4_journal_get_write_access(handle, iloc.bh);
+ ret = ext4_journal_get_write_access(handle, inode->i_sb, iloc.bh,
+ EXT4_JTR_NONE);
if (ret)
goto out;
@@ -750,6 +754,12 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
ext4_write_lock_xattr(inode, &no_expand);
BUG_ON(!ext4_has_inline_data(inode));
+ /*
+ * ei->i_inline_off may have changed since ext4_write_begin()
+ * called ext4_try_to_write_inline_data()
+ */
+ (void) ext4_find_inline_data_nolock(inode);
+
kaddr = kmap_atomic(page);
ext4_write_inline_data(inode, &iloc, kaddr, pos, len);
kunmap_atomic(kaddr);
@@ -923,7 +933,8 @@ retry_journal:
if (ret < 0)
goto out_release_page;
}
- ret = ext4_journal_get_write_access(handle, iloc.bh);
+ ret = ext4_journal_get_write_access(handle, inode->i_sb, iloc.bh,
+ EXT4_JTR_NONE);
if (ret)
goto out_release_page;
@@ -1028,7 +1039,8 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
return err;
BUFFER_TRACE(iloc->bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, iloc->bh);
+ err = ext4_journal_get_write_access(handle, dir->i_sb, iloc->bh,
+ EXT4_JTR_NONE);
if (err)
return err;
ext4_insert_dentry(dir, inode, de, inline_size, fname);
@@ -1223,7 +1235,8 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
}
lock_buffer(data_bh);
- error = ext4_journal_get_create_access(handle, data_bh);
+ error = ext4_journal_get_create_access(handle, inode->i_sb, data_bh,
+ EXT4_JTR_NONE);
if (error) {
unlock_buffer(data_bh);
error = -EIO;
@@ -1707,7 +1720,8 @@ int ext4_delete_inline_entry(handle_t *handle,
}
BUFFER_TRACE(bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle, dir->i_sb, bh,
+ EXT4_JTR_NONE);
if (err)
goto out;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 325c038e7b23..d18852d6029c 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -139,7 +139,6 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode,
static void ext4_invalidatepage(struct page *page, unsigned int offset,
unsigned int length);
static int __ext4_journalled_writepage(struct page *page, unsigned int len);
-static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh);
static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
int pextents);
@@ -869,7 +868,8 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
*/
lock_buffer(bh);
BUFFER_TRACE(bh, "call get_create_access");
- err = ext4_journal_get_create_access(handle, bh);
+ err = ext4_journal_get_create_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (unlikely(err)) {
unlock_buffer(bh);
goto errout;
@@ -954,12 +954,12 @@ out_brelse:
return err;
}
-int ext4_walk_page_buffers(handle_t *handle,
+int ext4_walk_page_buffers(handle_t *handle, struct inode *inode,
struct buffer_head *head,
unsigned from,
unsigned to,
int *partial,
- int (*fn)(handle_t *handle,
+ int (*fn)(handle_t *handle, struct inode *inode,
struct buffer_head *bh))
{
struct buffer_head *bh;
@@ -978,7 +978,7 @@ int ext4_walk_page_buffers(handle_t *handle,
*partial = 1;
continue;
}
- err = (*fn)(handle, bh);
+ err = (*fn)(handle, inode, bh);
if (!ret)
ret = err;
}
@@ -1009,7 +1009,7 @@ int ext4_walk_page_buffers(handle_t *handle,
* is elevated. We'll still have enough credits for the tiny quotafile
* write.
*/
-int do_journal_get_write_access(handle_t *handle,
+int do_journal_get_write_access(handle_t *handle, struct inode *inode,
struct buffer_head *bh)
{
int dirty = buffer_dirty(bh);
@@ -1028,7 +1028,8 @@ int do_journal_get_write_access(handle_t *handle,
if (dirty)
clear_buffer_dirty(bh);
BUFFER_TRACE(bh, "get write access");
- ret = ext4_journal_get_write_access(handle, bh);
+ ret = ext4_journal_get_write_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (!ret && dirty)
ret = ext4_handle_dirty_metadata(handle, NULL, bh);
return ret;
@@ -1208,8 +1209,8 @@ retry_journal:
ret = __block_write_begin(page, pos, len, ext4_get_block);
#endif
if (!ret && ext4_should_journal_data(inode)) {
- ret = ext4_walk_page_buffers(handle, page_buffers(page),
- from, to, NULL,
+ ret = ext4_walk_page_buffers(handle, inode,
+ page_buffers(page), from, to, NULL,
do_journal_get_write_access);
}
@@ -1253,7 +1254,8 @@ retry_journal:
}
/* For write_end() in data=journal mode */
-static int write_end_fn(handle_t *handle, struct buffer_head *bh)
+static int write_end_fn(handle_t *handle, struct inode *inode,
+ struct buffer_head *bh)
{
int ret;
if (!buffer_mapped(bh) || buffer_freed(bh))
@@ -1352,6 +1354,7 @@ errout:
* to call ext4_handle_dirty_metadata() instead.
*/
static void ext4_journalled_zero_new_buffers(handle_t *handle,
+ struct inode *inode,
struct page *page,
unsigned from, unsigned to)
{
@@ -1370,7 +1373,7 @@ static void ext4_journalled_zero_new_buffers(handle_t *handle,
size = min(to, block_end) - start;
zero_user(page, start, size);
- write_end_fn(handle, bh);
+ write_end_fn(handle, inode, bh);
}
clear_buffer_new(bh);
}
@@ -1412,13 +1415,13 @@ static int ext4_journalled_write_end(struct file *file,
copied = ret;
} else if (unlikely(copied < len) && !PageUptodate(page)) {
copied = 0;
- ext4_journalled_zero_new_buffers(handle, page, from, to);
+ ext4_journalled_zero_new_buffers(handle, inode, page, from, to);
} else {
if (unlikely(copied < len))
- ext4_journalled_zero_new_buffers(handle, page,
+ ext4_journalled_zero_new_buffers(handle, inode, page,
from + copied, to);
- ret = ext4_walk_page_buffers(handle, page_buffers(page), from,
- from + copied, &partial,
+ ret = ext4_walk_page_buffers(handle, inode, page_buffers(page),
+ from, from + copied, &partial,
write_end_fn);
if (!partial)
SetPageUptodate(page);
@@ -1619,7 +1622,8 @@ static void ext4_print_free_blocks(struct inode *inode)
return;
}
-static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh)
+static int ext4_bh_delay_or_unwritten(handle_t *handle, struct inode *inode,
+ struct buffer_head *bh)
{
return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh);
}
@@ -1851,13 +1855,15 @@ int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
return 0;
}
-static int bget_one(handle_t *handle, struct buffer_head *bh)
+static int bget_one(handle_t *handle, struct inode *inode,
+ struct buffer_head *bh)
{
get_bh(bh);
return 0;
}
-static int bput_one(handle_t *handle, struct buffer_head *bh)
+static int bput_one(handle_t *handle, struct inode *inode,
+ struct buffer_head *bh)
{
put_bh(bh);
return 0;
@@ -1888,7 +1894,7 @@ static int __ext4_journalled_writepage(struct page *page,
BUG();
goto out;
}
- ext4_walk_page_buffers(handle, page_bufs, 0, len,
+ ext4_walk_page_buffers(handle, inode, page_bufs, 0, len,
NULL, bget_one);
}
/*
@@ -1920,11 +1926,11 @@ static int __ext4_journalled_writepage(struct page *page,
if (inline_data) {
ret = ext4_mark_inode_dirty(handle, inode);
} else {
- ret = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL,
- do_journal_get_write_access);
+ ret = ext4_walk_page_buffers(handle, inode, page_bufs, 0, len,
+ NULL, do_journal_get_write_access);
- err = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL,
- write_end_fn);
+ err = ext4_walk_page_buffers(handle, inode, page_bufs, 0, len,
+ NULL, write_end_fn);
}
if (ret == 0)
ret = err;
@@ -1941,7 +1947,7 @@ out:
unlock_page(page);
out_no_pagelock:
if (!inline_data && page_bufs)
- ext4_walk_page_buffers(NULL, page_bufs, 0, len,
+ ext4_walk_page_buffers(NULL, inode, page_bufs, 0, len,
NULL, bput_one);
brelse(inode_bh);
return ret;
@@ -2031,7 +2037,7 @@ static int ext4_writepage(struct page *page,
* for the extremely common case, this is an optimization that
* skips a useless round trip through ext4_bio_write_page().
*/
- if (ext4_walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+ if (ext4_walk_page_buffers(NULL, inode, page_bufs, 0, len, NULL,
ext4_bh_delay_or_unwritten)) {
redirty_page_for_writepage(wbc, page);
if ((current->flags & PF_MEMALLOC) ||
@@ -3794,7 +3800,8 @@ static int __ext4_block_zero_page_range(handle_t *handle,
}
if (ext4_should_journal_data(inode)) {
BUFFER_TRACE(bh, "get write access");
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (err)
goto unlock;
}
@@ -4329,101 +4336,93 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino,
bh = sb_getblk(sb, block);
if (unlikely(!bh))
return -ENOMEM;
- if (ext4_simulate_fail(sb, EXT4_SIM_INODE_EIO))
- goto simulate_eio;
- if (!buffer_uptodate(bh)) {
- lock_buffer(bh);
+ if (ext4_buffer_uptodate(bh))
+ goto has_buffer;
- if (ext4_buffer_uptodate(bh)) {
- /* someone brought it uptodate while we waited */
- unlock_buffer(bh);
- goto has_buffer;
- }
-
- /*
- * If we have all information of the inode in memory and this
- * is the only valid inode in the block, we need not read the
- * block.
- */
- if (in_mem) {
- struct buffer_head *bitmap_bh;
- int i, start;
+ lock_buffer(bh);
+ /*
+ * If we have all information of the inode in memory and this
+ * is the only valid inode in the block, we need not read the
+ * block.
+ */
+ if (in_mem) {
+ struct buffer_head *bitmap_bh;
+ int i, start;
- start = inode_offset & ~(inodes_per_block - 1);
+ start = inode_offset & ~(inodes_per_block - 1);
- /* Is the inode bitmap in cache? */
- bitmap_bh = sb_getblk(sb, ext4_inode_bitmap(sb, gdp));
- if (unlikely(!bitmap_bh))
- goto make_io;
+ /* Is the inode bitmap in cache? */
+ bitmap_bh = sb_getblk(sb, ext4_inode_bitmap(sb, gdp));
+ if (unlikely(!bitmap_bh))
+ goto make_io;
- /*
- * If the inode bitmap isn't in cache then the
- * optimisation may end up performing two reads instead
- * of one, so skip it.
- */
- if (!buffer_uptodate(bitmap_bh)) {
- brelse(bitmap_bh);
- goto make_io;
- }
- for (i = start; i < start + inodes_per_block; i++) {
- if (i == inode_offset)
- continue;
- if (ext4_test_bit(i, bitmap_bh->b_data))
- break;
- }
+ /*
+ * If the inode bitmap isn't in cache then the
+ * optimisation may end up performing two reads instead
+ * of one, so skip it.
+ */
+ if (!buffer_uptodate(bitmap_bh)) {
brelse(bitmap_bh);
- if (i == start + inodes_per_block) {
- /* all other inodes are free, so skip I/O */
- memset(bh->b_data, 0, bh->b_size);
- set_buffer_uptodate(bh);
- unlock_buffer(bh);
- goto has_buffer;
- }
+ goto make_io;
}
+ for (i = start; i < start + inodes_per_block; i++) {
+ if (i == inode_offset)
+ continue;
+ if (ext4_test_bit(i, bitmap_bh->b_data))
+ break;
+ }
+ brelse(bitmap_bh);
+ if (i == start + inodes_per_block) {
+ /* all other inodes are free, so skip I/O */
+ memset(bh->b_data, 0, bh->b_size);
+ set_buffer_uptodate(bh);
+ unlock_buffer(bh);
+ goto has_buffer;
+ }
+ }
make_io:
- /*
- * If we need to do any I/O, try to pre-readahead extra
- * blocks from the inode table.
- */
- blk_start_plug(&plug);
- if (EXT4_SB(sb)->s_inode_readahead_blks) {
- ext4_fsblk_t b, end, table;
- unsigned num;
- __u32 ra_blks = EXT4_SB(sb)->s_inode_readahead_blks;
-
- table = ext4_inode_table(sb, gdp);
- /* s_inode_readahead_blks is always a power of 2 */
- b = block & ~((ext4_fsblk_t) ra_blks - 1);
- if (table > b)
- b = table;
- end = b + ra_blks;
- num = EXT4_INODES_PER_GROUP(sb);
- if (ext4_has_group_desc_csum(sb))
- num -= ext4_itable_unused_count(sb, gdp);
- table += num / inodes_per_block;
- if (end > table)
- end = table;
- while (b <= end)
- ext4_sb_breadahead_unmovable(sb, b++);
- }
+ /*
+ * If we need to do any I/O, try to pre-readahead extra
+ * blocks from the inode table.
+ */
+ blk_start_plug(&plug);
+ if (EXT4_SB(sb)->s_inode_readahead_blks) {
+ ext4_fsblk_t b, end, table;
+ unsigned num;
+ __u32 ra_blks = EXT4_SB(sb)->s_inode_readahead_blks;
+
+ table = ext4_inode_table(sb, gdp);
+ /* s_inode_readahead_blks is always a power of 2 */
+ b = block & ~((ext4_fsblk_t) ra_blks - 1);
+ if (table > b)
+ b = table;
+ end = b + ra_blks;
+ num = EXT4_INODES_PER_GROUP(sb);
+ if (ext4_has_group_desc_csum(sb))
+ num -= ext4_itable_unused_count(sb, gdp);
+ table += num / inodes_per_block;
+ if (end > table)
+ end = table;
+ while (b <= end)
+ ext4_sb_breadahead_unmovable(sb, b++);
+ }
- /*
- * There are other valid inodes in the buffer, this inode
- * has in-inode xattrs, or we don't have this inode in memory.
- * Read the block from disk.
- */
- trace_ext4_load_inode(sb, ino);
- ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO, NULL);
- blk_finish_plug(&plug);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- simulate_eio:
- if (ret_block)
- *ret_block = block;
- brelse(bh);
- return -EIO;
- }
+ /*
+ * There are other valid inodes in the buffer, this inode
+ * has in-inode xattrs, or we don't have this inode in memory.
+ * Read the block from disk.
+ */
+ trace_ext4_load_inode(sb, ino);
+ ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO, NULL);
+ blk_finish_plug(&plug);
+ wait_on_buffer(bh);
+ ext4_simulate_fail_bh(sb, bh, EXT4_SIM_INODE_EIO);
+ if (!buffer_uptodate(bh)) {
+ if (ret_block)
+ *ret_block = block;
+ brelse(bh);
+ return -EIO;
}
has_buffer:
iloc->bh = bh;
@@ -4602,6 +4601,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
struct ext4_iloc iloc;
struct ext4_inode *raw_inode;
struct ext4_inode_info *ei;
+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;
struct inode *inode;
journal_t *journal = EXT4_SB(sb)->s_journal;
long ret;
@@ -4612,9 +4612,13 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
projid_t i_projid;
if ((!(flags & EXT4_IGET_SPECIAL) &&
- (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)) ||
+ ((ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) ||
+ ino == le32_to_cpu(es->s_usr_quota_inum) ||
+ ino == le32_to_cpu(es->s_grp_quota_inum) ||
+ ino == le32_to_cpu(es->s_prj_quota_inum) ||
+ ino == le32_to_cpu(es->s_orphan_file_inum))) ||
(ino < EXT4_ROOT_INO) ||
- (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))) {
+ (ino > le32_to_cpu(es->s_inodes_count))) {
if (flags & EXT4_IGET_HANDLE)
return ERR_PTR(-ESTALE);
__ext4_error(sb, function, line, false, EFSCORRUPTED, 0,
@@ -4927,8 +4931,14 @@ static int ext4_inode_blocks_set(handle_t *handle,
ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
return 0;
}
+
+ /*
+ * This should never happen since sb->s_maxbytes should not have
+ * allowed this, sb->s_maxbytes was set according to the huge_file
+ * feature in ext4_fill_super().
+ */
if (!ext4_has_feature_huge_file(sb))
- return -EFBIG;
+ return -EFSCORRUPTED;
if (i_blocks <= 0xffffffffffffULL) {
/*
@@ -5031,16 +5041,14 @@ static int ext4_do_update_inode(handle_t *handle,
spin_lock(&ei->i_raw_lock);
- /* For fields not tracked in the in-memory inode,
- * initialise them to zero for new inodes. */
+ /*
+ * For fields not tracked in the in-memory inode, initialise them
+ * to zero for new inodes.
+ */
if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
err = ext4_inode_blocks_set(handle, raw_inode, ei);
- if (err) {
- spin_unlock(&ei->i_raw_lock);
- goto out_brelse;
- }
raw_inode->i_mode = cpu_to_le16(inode->i_mode);
i_uid = i_uid_read(inode);
@@ -5049,10 +5057,11 @@ static int ext4_do_update_inode(handle_t *handle,
if (!(test_opt(inode->i_sb, NO_UID32))) {
raw_inode->i_uid_low = cpu_to_le16(low_16_bits(i_uid));
raw_inode->i_gid_low = cpu_to_le16(low_16_bits(i_gid));
-/*
- * Fix up interoperability with old kernels. Otherwise, old inodes get
- * re-used with the upper 16 bits of the uid/gid intact
- */
+ /*
+ * Fix up interoperability with old kernels. Otherwise,
+ * old inodes get re-used with the upper 16 bits of the
+ * uid/gid intact.
+ */
if (ei->i_dtime && list_empty(&ei->i_orphan)) {
raw_inode->i_uid_high = 0;
raw_inode->i_gid_high = 0;
@@ -5121,8 +5130,9 @@ static int ext4_do_update_inode(handle_t *handle,
}
}
- BUG_ON(!ext4_has_feature_project(inode->i_sb) &&
- i_projid != EXT4_DEF_PROJID);
+ if (i_projid != EXT4_DEF_PROJID &&
+ !ext4_has_feature_project(inode->i_sb))
+ err = err ?: -EFSCORRUPTED;
if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
EXT4_FITS_IN_INODE(raw_inode, ei, i_projid))
@@ -5130,6 +5140,11 @@ static int ext4_do_update_inode(handle_t *handle,
ext4_inode_csum_set(inode, raw_inode, ei);
spin_unlock(&ei->i_raw_lock);
+ if (err) {
+ EXT4_ERROR_INODE(inode, "corrupted inode contents");
+ goto out_brelse;
+ }
+
if (inode->i_sb->s_flags & SB_LAZYTIME)
ext4_update_other_inodes_time(inode->i_sb, inode->i_ino,
bh->b_data);
@@ -5137,13 +5152,15 @@ static int ext4_do_update_inode(handle_t *handle,
BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
err = ext4_handle_dirty_metadata(handle, NULL, bh);
if (err)
- goto out_brelse;
+ goto out_error;
ext4_clear_inode_state(inode, EXT4_STATE_NEW);
if (set_large_file) {
BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get write access");
- err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+ err = ext4_journal_get_write_access(handle, sb,
+ EXT4_SB(sb)->s_sbh,
+ EXT4_JTR_NONE);
if (err)
- goto out_brelse;
+ goto out_error;
lock_buffer(EXT4_SB(sb)->s_sbh);
ext4_set_feature_large_file(sb);
ext4_superblock_csum_set(sb);
@@ -5153,9 +5170,10 @@ static int ext4_do_update_inode(handle_t *handle,
EXT4_SB(sb)->s_sbh);
}
ext4_update_inode_fsync_trans(handle, inode, need_datasync);
+out_error:
+ ext4_std_error(inode->i_sb, err);
out_brelse:
brelse(bh);
- ext4_std_error(inode->i_sb, err);
return err;
}
@@ -5742,7 +5760,8 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
err = ext4_get_inode_loc(inode, iloc);
if (!err) {
BUFFER_TRACE(iloc->bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, iloc->bh);
+ err = ext4_journal_get_write_access(handle, inode->i_sb,
+ iloc->bh, EXT4_JTR_NONE);
if (err) {
brelse(iloc->bh);
iloc->bh = NULL;
@@ -5865,7 +5884,8 @@ int ext4_expand_extra_isize(struct inode *inode,
ext4_write_lock_xattr(inode, &no_expand);
BUFFER_TRACE(iloc->bh, "get_write_access");
- error = ext4_journal_get_write_access(handle, iloc->bh);
+ error = ext4_journal_get_write_access(handle, inode->i_sb, iloc->bh,
+ EXT4_JTR_NONE);
if (error) {
brelse(iloc->bh);
goto out_unlock;
@@ -6036,7 +6056,8 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
return err;
}
-static int ext4_bh_unmapped(handle_t *handle, struct buffer_head *bh)
+static int ext4_bh_unmapped(handle_t *handle, struct inode *inode,
+ struct buffer_head *bh)
{
return !buffer_mapped(bh);
}
@@ -6109,7 +6130,7 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
* inode to the transaction's list to writeprotect pages on commit.
*/
if (page_has_buffers(page)) {
- if (!ext4_walk_page_buffers(NULL, page_buffers(page),
+ if (!ext4_walk_page_buffers(NULL, inode, page_buffers(page),
0, len, NULL,
ext4_bh_unmapped)) {
/* Wait so that we don't change page under IO */
@@ -6155,11 +6176,13 @@ retry_alloc:
err = __block_write_begin(page, 0, len, ext4_get_block);
if (!err) {
ret = VM_FAULT_SIGBUS;
- if (ext4_walk_page_buffers(handle, page_buffers(page),
- 0, len, NULL, do_journal_get_write_access))
+ if (ext4_walk_page_buffers(handle, inode,
+ page_buffers(page), 0, len, NULL,
+ do_journal_get_write_access))
goto out_error;
- if (ext4_walk_page_buffers(handle, page_buffers(page),
- 0, len, NULL, write_end_fn))
+ if (ext4_walk_page_buffers(handle, inode,
+ page_buffers(page), 0, len, NULL,
+ write_end_fn))
goto out_error;
if (ext4_jbd2_inode_add_write(handle, inode,
page_offset(page), len))
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 4fb5fe083c2b..606dee9e08a3 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -1154,7 +1154,9 @@ resizefs_out:
err = PTR_ERR(handle);
goto pwsalt_err_exit;
}
- err = ext4_journal_get_write_access(handle, sbi->s_sbh);
+ err = ext4_journal_get_write_access(handle, sb,
+ sbi->s_sbh,
+ EXT4_JTR_NONE);
if (err)
goto pwsalt_err_journal;
lock_buffer(sbi->s_sbh);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 089c958aa2c3..72bfac2d6dce 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -408,6 +408,10 @@ static void ext4_mb_new_preallocation(struct ext4_allocation_context *ac);
static bool ext4_mb_good_group(struct ext4_allocation_context *ac,
ext4_group_t group, int cr);
+static int ext4_try_to_trim_range(struct super_block *sb,
+ struct ext4_buddy *e4b, ext4_grpblk_t start,
+ ext4_grpblk_t max, ext4_grpblk_t minblocks);
+
/*
* The algorithm using this percpu seq counter goes below:
* 1. We sample the percpu discard_pa_seq counter before trying for block
@@ -2474,6 +2478,12 @@ static bool ext4_mb_good_group(struct ext4_allocation_context *ac,
* This could return negative error code if something goes wrong
* during ext4_mb_init_group(). This should not be called with
* ext4_lock_group() held.
+ *
+ * Note: because we are conditionally operating with the group lock in
+ * the EXT4_MB_STRICT_CHECK case, we need to fake out sparse in this
+ * function using __acquire and __release. This means we need to be
+ * super careful before messing with the error path handling via "goto
+ * out"!
*/
static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
ext4_group_t group, int cr)
@@ -2487,8 +2497,10 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
if (sbi->s_mb_stats)
atomic64_inc(&sbi->s_bal_cX_groups_considered[ac->ac_criteria]);
- if (should_lock)
+ if (should_lock) {
ext4_lock_group(sb, group);
+ __release(ext4_group_lock_ptr(sb, group));
+ }
free = grp->bb_free;
if (free == 0)
goto out;
@@ -2496,8 +2508,10 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
goto out;
if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
goto out;
- if (should_lock)
+ if (should_lock) {
+ __acquire(ext4_group_lock_ptr(sb, group));
ext4_unlock_group(sb, group);
+ }
/* We only do this if the grp has never been initialized */
if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
@@ -2524,12 +2538,16 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
return ret;
}
- if (should_lock)
+ if (should_lock) {
ext4_lock_group(sb, group);
+ __release(ext4_group_lock_ptr(sb, group));
+ }
ret = ext4_mb_good_group(ac, group, cr);
out:
- if (should_lock)
+ if (should_lock) {
+ __acquire(ext4_group_lock_ptr(sb, group));
ext4_unlock_group(sb, group);
+ }
return ret;
}
@@ -2965,6 +2983,7 @@ int ext4_seq_mb_stats_show(struct seq_file *seq, void *offset)
}
static void *ext4_mb_seq_structs_summary_start(struct seq_file *seq, loff_t *pos)
+__acquires(&EXT4_SB(sb)->s_mb_rb_lock)
{
struct super_block *sb = PDE_DATA(file_inode(seq->file));
unsigned long position;
@@ -3037,6 +3056,7 @@ static int ext4_mb_seq_structs_summary_show(struct seq_file *seq, void *v)
}
static void ext4_mb_seq_structs_summary_stop(struct seq_file *seq, void *v)
+__releases(&EXT4_SB(sb)->s_mb_rb_lock)
{
struct super_block *sb = PDE_DATA(file_inode(seq->file));
@@ -3308,6 +3328,57 @@ static int ext4_groupinfo_create_slab(size_t size)
return 0;
}
+static void ext4_discard_work(struct work_struct *work)
+{
+ struct ext4_sb_info *sbi = container_of(work,
+ struct ext4_sb_info, s_discard_work);
+ struct super_block *sb = sbi->s_sb;
+ struct ext4_free_data *fd, *nfd;
+ struct ext4_buddy e4b;
+ struct list_head discard_list;
+ ext4_group_t grp, load_grp;
+ int err = 0;
+
+ INIT_LIST_HEAD(&discard_list);
+ spin_lock(&sbi->s_md_lock);
+ list_splice_init(&sbi->s_discard_list, &discard_list);
+ spin_unlock(&sbi->s_md_lock);
+
+ load_grp = UINT_MAX;
+ list_for_each_entry_safe(fd, nfd, &discard_list, efd_list) {
+ /*
+ * If filesystem is umounting or no memory or suffering
+ * from no space, give up the discard
+ */
+ if ((sb->s_flags & SB_ACTIVE) && !err &&
+ !atomic_read(&sbi->s_retry_alloc_pending)) {
+ grp = fd->efd_group;
+ if (grp != load_grp) {
+ if (load_grp != UINT_MAX)
+ ext4_mb_unload_buddy(&e4b);
+
+ err = ext4_mb_load_buddy(sb, grp, &e4b);
+ if (err) {
+ kmem_cache_free(ext4_free_data_cachep, fd);
+ load_grp = UINT_MAX;
+ continue;
+ } else {
+ load_grp = grp;
+ }
+ }
+
+ ext4_lock_group(sb, grp);
+ ext4_try_to_trim_range(sb, &e4b, fd->efd_start_cluster,
+ fd->efd_start_cluster + fd->efd_count - 1, 1);
+ ext4_unlock_group(sb, grp);
+ }
+ kmem_cache_free(ext4_free_data_cachep, fd);
+ }
+
+ if (load_grp != UINT_MAX)
+ ext4_mb_unload_buddy(&e4b);
+}
+
int ext4_mb_init(struct super_block *sb)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -3376,6 +3447,9 @@ int ext4_mb_init(struct super_block *sb)
spin_lock_init(&sbi->s_md_lock);
sbi->s_mb_free_pending = 0;
INIT_LIST_HEAD(&sbi->s_freed_data_list);
+ INIT_LIST_HEAD(&sbi->s_discard_list);
+ INIT_WORK(&sbi->s_discard_work, ext4_discard_work);
+ atomic_set(&sbi->s_retry_alloc_pending, 0);
sbi->s_mb_max_to_scan = MB_DEFAULT_MAX_TO_SCAN;
sbi->s_mb_min_to_scan = MB_DEFAULT_MIN_TO_SCAN;
@@ -3474,6 +3548,14 @@ int ext4_mb_release(struct super_block *sb)
struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
int count;
+ if (test_opt(sb, DISCARD)) {
+ /*
+ * wait the discard work to drain all of ext4_free_data
+ */
+ flush_work(&sbi->s_discard_work);
+ WARN_ON_ONCE(!list_empty(&sbi->s_discard_list));
+ }
+
if (sbi->s_group_info) {
for (i = 0; i < ngroups; i++) {
cond_resched();
@@ -3596,7 +3678,6 @@ static void ext4_free_data_in_buddy(struct super_block *sb,
put_page(e4b.bd_bitmap_page);
}
ext4_unlock_group(sb, entry->efd_group);
- kmem_cache_free(ext4_free_data_cachep, entry);
ext4_mb_unload_buddy(&e4b);
mb_debug(sb, "freed %d blocks in %d structures\n", count,
@@ -3611,10 +3692,9 @@ void ext4_process_freed_data(struct super_block *sb, tid_t commit_tid)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_free_data *entry, *tmp;
- struct bio *discard_bio = NULL;
struct list_head freed_data_list;
struct list_head *cut_pos = NULL;
- int err;
+ bool wake;
INIT_LIST_HEAD(&freed_data_list);
@@ -3629,30 +3709,20 @@ void ext4_process_freed_data(struct super_block *sb, tid_t commit_tid)
cut_pos);
spin_unlock(&sbi->s_md_lock);
- if (test_opt(sb, DISCARD)) {
- list_for_each_entry(entry, &freed_data_list, efd_list) {
- err = ext4_issue_discard(sb, entry->efd_group,
- entry->efd_start_cluster,
- entry->efd_count,
- &discard_bio);
- if (err && err != -EOPNOTSUPP) {
- ext4_msg(sb, KERN_WARNING, "discard request in"
- " group:%d block:%d count:%d failed"
- " with %d", entry->efd_group,
- entry->efd_start_cluster,
- entry->efd_count, err);
- } else if (err == -EOPNOTSUPP)
- break;
- }
+ list_for_each_entry(entry, &freed_data_list, efd_list)
+ ext4_free_data_in_buddy(sb, entry);
- if (discard_bio) {
- submit_bio_wait(discard_bio);
- bio_put(discard_bio);
- }
+ if (test_opt(sb, DISCARD)) {
+ spin_lock(&sbi->s_md_lock);
+ wake = list_empty(&sbi->s_discard_list);
+ list_splice_tail(&freed_data_list, &sbi->s_discard_list);
+ spin_unlock(&sbi->s_md_lock);
+ if (wake)
+ queue_work(system_unbound_wq, &sbi->s_discard_work);
+ } else {
+ list_for_each_entry_safe(entry, tmp, &freed_data_list, efd_list)
+ kmem_cache_free(ext4_free_data_cachep, entry);
}
-
- list_for_each_entry_safe(entry, tmp, &freed_data_list, efd_list)
- ext4_free_data_in_buddy(sb, entry);
}
int __init ext4_init_mballoc(void)
@@ -3726,7 +3796,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
}
BUFFER_TRACE(bitmap_bh, "getting write access");
- err = ext4_journal_get_write_access(handle, bitmap_bh);
+ err = ext4_journal_get_write_access(handle, sb, bitmap_bh,
+ EXT4_JTR_NONE);
if (err)
goto out_err;
@@ -3739,7 +3810,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
ext4_free_group_clusters(sb, gdp));
BUFFER_TRACE(gdp_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, gdp_bh);
+ err = ext4_journal_get_write_access(handle, sb, gdp_bh, EXT4_JTR_NONE);
if (err)
goto out_err;
@@ -5916,7 +5987,8 @@ do_more:
}
BUFFER_TRACE(bitmap_bh, "getting write access");
- err = ext4_journal_get_write_access(handle, bitmap_bh);
+ err = ext4_journal_get_write_access(handle, sb, bitmap_bh,
+ EXT4_JTR_NONE);
if (err)
goto error_return;
@@ -5926,7 +5998,7 @@ do_more:
* using it
*/
BUFFER_TRACE(gd_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, gd_bh);
+ err = ext4_journal_get_write_access(handle, sb, gd_bh, EXT4_JTR_NONE);
if (err)
goto error_return;
#ifdef AGGRESSIVE_CHECK
@@ -6107,7 +6179,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
}
BUFFER_TRACE(bitmap_bh, "getting write access");
- err = ext4_journal_get_write_access(handle, bitmap_bh);
+ err = ext4_journal_get_write_access(handle, sb, bitmap_bh,
+ EXT4_JTR_NONE);
if (err)
goto error_return;
@@ -6117,7 +6190,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
* using it
*/
BUFFER_TRACE(gd_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, gd_bh);
+ err = ext4_journal_get_write_access(handle, sb, gd_bh, EXT4_JTR_NONE);
if (err)
goto error_return;
@@ -6183,19 +6256,19 @@ error_return:
* @sb: super block for the file system
* @start: starting block of the free extent in the alloc. group
* @count: number of blocks to TRIM
- * @group: alloc. group we are working with
* @e4b: ext4 buddy for the group
*
* Trim "count" blocks starting at "start" in the "group". To assure that no
* one will allocate those blocks, mark it as used in buddy bitmap. This must
* be called with under the group lock.
*/
-static int ext4_trim_extent(struct super_block *sb, int start, int count,
- ext4_group_t group, struct ext4_buddy *e4b)
+static int ext4_trim_extent(struct super_block *sb,
+ int start, int count, struct ext4_buddy *e4b)
__releases(bitlock)
__acquires(bitlock)
{
struct ext4_free_extent ex;
+ ext4_group_t group = e4b->bd_group;
int ret = 0;
trace_ext4_trim_extent(sb, group, start, count);
@@ -6218,51 +6291,21 @@ __acquires(bitlock)
return ret;
}
-/**
- * ext4_trim_all_free -- function to trim all free space in alloc. group
- * @sb: super block for file system
- * @group: group to be trimmed
- * @start: first group block to examine
- * @max: last group block to examine
- * @minblocks: minimum extent block count
- *
- * ext4_trim_all_free walks through group's buddy bitmap searching for free
- * extents. When the free block is found, ext4_trim_extent is called to TRIM
- * the extent.
- *
- *
- * ext4_trim_all_free walks through group's block bitmap searching for free
- * extents. When the free extent is found, mark it as used in group buddy
- * bitmap. Then issue a TRIM command on this extent and free the extent in
- * the group buddy bitmap. This is done until whole group is scanned.
- */
-static ext4_grpblk_t
-ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
- ext4_grpblk_t start, ext4_grpblk_t max,
- ext4_grpblk_t minblocks)
+static int ext4_try_to_trim_range(struct super_block *sb,
+ struct ext4_buddy *e4b, ext4_grpblk_t start,
+ ext4_grpblk_t max, ext4_grpblk_t minblocks)
+__acquires(ext4_group_lock_ptr(sb, e4b->bd_group))
+__releases(ext4_group_lock_ptr(sb, e4b->bd_group))
{
+ ext4_grpblk_t next, count, free_count;
void *bitmap;
- ext4_grpblk_t next, count = 0, free_count = 0;
- struct ext4_buddy e4b;
int ret = 0;
- trace_ext4_trim_all_free(sb, group, start, max);
-
- ret = ext4_mb_load_buddy(sb, group, &e4b);
- if (ret) {
- ext4_warning(sb, "Error %d loading buddy information for %u",
- ret, group);
- return ret;
- }
- bitmap = e4b.bd_bitmap;
-
- ext4_lock_group(sb, group);
- if (EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) &&
- minblocks >= atomic_read(&EXT4_SB(sb)->s_last_trim_minblks))
- goto out;
-
- start = (e4b.bd_info->bb_first_free > start) ?
- e4b.bd_info->bb_first_free : start;
+ bitmap = e4b->bd_bitmap;
+ start = (e4b->bd_info->bb_first_free > start) ?
+ e4b->bd_info->bb_first_free : start;
+ count = 0;
+ free_count = 0;
while (start <= max) {
start = mb_find_next_zero_bit(bitmap, max + 1, start);
@@ -6271,8 +6314,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
next = mb_find_next_bit(bitmap, max + 1, start);
if ((next - start) >= minblocks) {
- ret = ext4_trim_extent(sb, start,
- next - start, group, &e4b);
+ ret = ext4_trim_extent(sb, start, next - start, e4b);
if (ret && ret != -EOPNOTSUPP)
break;
ret = 0;
@@ -6287,25 +6329,64 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
}
if (need_resched()) {
- ext4_unlock_group(sb, group);
+ ext4_unlock_group(sb, e4b->bd_group);
cond_resched();
- ext4_lock_group(sb, group);
+ ext4_lock_group(sb, e4b->bd_group);
}
- if ((e4b.bd_info->bb_free - free_count) < minblocks)
+ if ((e4b->bd_info->bb_free - free_count) < minblocks)
break;
}
- if (!ret) {
- ret = count;
- EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
+ return count;
+}
+
+/**
+ * ext4_trim_all_free -- function to trim all free space in alloc. group
+ * @sb: super block for file system
+ * @group: group to be trimmed
+ * @start: first group block to examine
+ * @max: last group block to examine
+ * @minblocks: minimum extent block count
+ *
+ * ext4_trim_all_free walks through group's block bitmap searching for free
+ * extents. When the free extent is found, mark it as used in group buddy
+ * bitmap. Then issue a TRIM command on this extent and free the extent in
+ * the group buddy bitmap.
+ */
+static ext4_grpblk_t
+ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+ ext4_grpblk_t start, ext4_grpblk_t max,
+ ext4_grpblk_t minblocks)
+{
+ struct ext4_buddy e4b;
+ int ret;
+
+ trace_ext4_trim_all_free(sb, group, start, max);
+
+ ret = ext4_mb_load_buddy(sb, group, &e4b);
+ if (ret) {
+ ext4_warning(sb, "Error %d loading buddy information for %u",
+ ret, group);
+ return ret;
+ }
+
+ ext4_lock_group(sb, group);
+
+ if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
+ minblocks < atomic_read(&EXT4_SB(sb)->s_last_trim_minblks)) {
+ ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
+ if (ret >= 0)
+ EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
+ } else {
+ ret = 0;
}
-out:
+
ext4_unlock_group(sb, group);
ext4_mb_unload_buddy(&e4b);
ext4_debug("trimmed %d blocks in the group %d\n",
- count, group);
+ ret, group);
return ret;
}
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index f3bbcd4efb56..da7698341d7d 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -70,7 +70,8 @@ static struct buffer_head *ext4_append(handle_t *handle,
inode->i_size += inode->i_sb->s_blocksize;
EXT4_I(inode)->i_disksize = inode->i_size;
BUFFER_TRACE(bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (err) {
brelse(bh);
ext4_std_error(inode->i_sb, err);
@@ -1927,12 +1928,14 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
}
BUFFER_TRACE(*bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, *bh);
+ err = ext4_journal_get_write_access(handle, dir->i_sb, *bh,
+ EXT4_JTR_NONE);
if (err)
goto journal_error;
BUFFER_TRACE(frame->bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, frame->bh);
+ err = ext4_journal_get_write_access(handle, dir->i_sb, frame->bh,
+ EXT4_JTR_NONE);
if (err)
goto journal_error;
@@ -2109,7 +2112,8 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
return err;
}
BUFFER_TRACE(bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle, dir->i_sb, bh,
+ EXT4_JTR_NONE);
if (err) {
ext4_std_error(dir->i_sb, err);
return err;
@@ -2167,7 +2171,8 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
blocksize = dir->i_sb->s_blocksize;
dxtrace(printk(KERN_DEBUG "Creating index: inode %lu\n", dir->i_ino));
BUFFER_TRACE(bh, "get_write_access");
- retval = ext4_journal_get_write_access(handle, bh);
+ retval = ext4_journal_get_write_access(handle, dir->i_sb, bh,
+ EXT4_JTR_NONE);
if (retval) {
ext4_std_error(dir->i_sb, retval);
brelse(bh);
@@ -2419,7 +2424,7 @@ again:
}
BUFFER_TRACE(bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle, sb, bh, EXT4_JTR_NONE);
if (err)
goto journal_error;
@@ -2476,7 +2481,8 @@ again:
node2->fake.rec_len = ext4_rec_len_to_disk(sb->s_blocksize,
sb->s_blocksize);
BUFFER_TRACE(frame->bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, frame->bh);
+ err = ext4_journal_get_write_access(handle, sb, frame->bh,
+ EXT4_JTR_NONE);
if (err)
goto journal_error;
if (!add_level) {
@@ -2486,8 +2492,9 @@ again:
icount1, icount2));
BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
- err = ext4_journal_get_write_access(handle,
- (frame - 1)->bh);
+ err = ext4_journal_get_write_access(handle, sb,
+ (frame - 1)->bh,
+ EXT4_JTR_NONE);
if (err)
goto journal_error;
@@ -2636,7 +2643,8 @@ static int ext4_delete_entry(handle_t *handle,
csum_size = sizeof(struct ext4_dir_entry_tail);
BUFFER_TRACE(bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle, dir->i_sb, bh,
+ EXT4_JTR_NONE);
if (unlikely(err))
goto out;
@@ -3046,186 +3054,6 @@ bool ext4_empty_dir(struct inode *inode)
return true;
}
-/*
- * ext4_orphan_add() links an unlinked or truncated inode into a list of
- * such inodes, starting at the superblock, in case we crash before the
- * file is closed/deleted, or in case the inode truncate spans multiple
- * transactions and the last transaction is not recovered after a crash.
- *
- * At filesystem recovery time, we walk this list deleting unlinked
- * inodes and truncating linked inodes in ext4_orphan_cleanup().
- *
- * Orphan list manipulation functions must be called under i_mutex unless
- * we are just creating the inode or deleting it.
- */
-int ext4_orphan_add(handle_t *handle, struct inode *inode)
-{
- struct super_block *sb = inode->i_sb;
- struct ext4_sb_info *sbi = EXT4_SB(sb);
- struct ext4_iloc iloc;
- int err = 0, rc;
- bool dirty = false;
-
- if (!sbi->s_journal || is_bad_inode(inode))
- return 0;
-
- WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
- !inode_is_locked(inode));
- /*
- * Exit early if inode already is on orphan list. This is a big speedup
- * since we don't have to contend on the global s_orphan_lock.
- */
- if (!list_empty(&EXT4_I(inode)->i_orphan))
- return 0;
-
- /*
- * Orphan handling is only valid for files with data blocks
- * being truncated, or files being unlinked. Note that we either
- * hold i_mutex, or the inode can not be referenced from outside,
- * so i_nlink should not be bumped due to race
- */
- ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
-
- BUFFER_TRACE(sbi->s_sbh, "get_write_access");
- err = ext4_journal_get_write_access(handle, sbi->s_sbh);
- if (err)
- goto out;
-
- err = ext4_reserve_inode_write(handle, inode, &iloc);
- if (err)
- goto out;
-
- mutex_lock(&sbi->s_orphan_lock);
- /*
- * Due to previous errors inode may be already a part of on-disk
- * orphan list. If so skip on-disk list modification.
- */
- if (!NEXT_ORPHAN(inode) || NEXT_ORPHAN(inode) >
- (le32_to_cpu(sbi->s_es->s_inodes_count))) {
- /* Insert this inode at the head of the on-disk orphan list */
- NEXT_ORPHAN(inode) = le32_to_cpu(sbi->s_es->s_last_orphan);
- lock_buffer(sbi->s_sbh);
- sbi->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
- ext4_superblock_csum_set(sb);
- unlock_buffer(sbi->s_sbh);
- dirty = true;
- }
- list_add(&EXT4_I(inode)->i_orphan, &sbi->s_orphan);
- mutex_unlock(&sbi->s_orphan_lock);
-
- if (dirty) {
- err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
- rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
- if (!err)
- err = rc;
- if (err) {
- /*
- * We have to remove inode from in-memory list if
- * addition to on disk orphan list failed. Stray orphan
- * list entries can cause panics at unmount time.
- */
- mutex_lock(&sbi->s_orphan_lock);
- list_del_init(&EXT4_I(inode)->i_orphan);
- mutex_unlock(&sbi->s_orphan_lock);
- }
- } else
- brelse(iloc.bh);
-
- jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
- jbd_debug(4, "orphan inode %lu will point to %d\n",
- inode->i_ino, NEXT_ORPHAN(inode));
-out:
- ext4_std_error(sb, err);
- return err;
-}
-
-/*
- * ext4_orphan_del() removes an unlinked or truncated inode from the list
- * of such inodes stored on disk, because it is finally being cleaned up.
- */
-int ext4_orphan_del(handle_t *handle, struct inode *inode)
-{
- struct list_head *prev;
- struct ext4_inode_info *ei = EXT4_I(inode);
- struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
- __u32 ino_next;
- struct ext4_iloc iloc;
- int err = 0;
-
- if (!sbi->s_journal && !(sbi->s_mount_state & EXT4_ORPHAN_FS))
- return 0;
-
- WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
- !inode_is_locked(inode));
- /* Do this quick check before taking global s_orphan_lock. */
- if (list_empty(&ei->i_orphan))
- return 0;
-
- if (handle) {
- /* Grab inode buffer early before taking global s_orphan_lock */
- err = ext4_reserve_inode_write(handle, inode, &iloc);
- }
-
- mutex_lock(&sbi->s_orphan_lock);
- jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
-
- prev = ei->i_orphan.prev;
- list_del_init(&ei->i_orphan);
-
- /* If we're on an error path, we may not have a valid
- * transaction handle with which to update the orphan list on
- * disk, but we still need to remove the inode from the linked
- * list in memory. */
- if (!handle || err) {
- mutex_unlock(&sbi->s_orphan_lock);
- goto out_err;
- }
-
- ino_next = NEXT_ORPHAN(inode);
- if (prev == &sbi->s_orphan) {
- jbd_debug(4, "superblock will point to %u\n", ino_next);
- BUFFER_TRACE(sbi->s_sbh, "get_write_access");
- err = ext4_journal_get_write_access(handle, sbi->s_sbh);
- if (err) {
- mutex_unlock(&sbi->s_orphan_lock);
- goto out_brelse;
- }
- lock_buffer(sbi->s_sbh);
- sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
- ext4_superblock_csum_set(inode->i_sb);
- unlock_buffer(sbi->s_sbh);
- mutex_unlock(&sbi->s_orphan_lock);
- err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
- } else {
- struct ext4_iloc iloc2;
- struct inode *i_prev =
- &list_entry(prev, struct ext4_inode_info, i_orphan)->vfs_inode;
-
- jbd_debug(4, "orphan inode %lu will point to %u\n",
- i_prev->i_ino, ino_next);
- err = ext4_reserve_inode_write(handle, i_prev, &iloc2);
- if (err) {
- mutex_unlock(&sbi->s_orphan_lock);
- goto out_brelse;
- }
- NEXT_ORPHAN(i_prev) = ino_next;
- err = ext4_mark_iloc_dirty(handle, i_prev, &iloc2);
- mutex_unlock(&sbi->s_orphan_lock);
- }
- if (err)
- goto out_brelse;
- NEXT_ORPHAN(inode) = 0;
- err = ext4_mark_iloc_dirty(handle, inode, &iloc);
-out_err:
- ext4_std_error(inode->i_sb, err);
- return err;
-
-out_brelse:
- brelse(iloc.bh);
- goto out_err;
-}
-
static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
{
int retval;
@@ -3675,7 +3503,8 @@ static int ext4_rename_dir_prepare(handle_t *handle, struct ext4_renament *ent)
if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino)
return -EFSCORRUPTED;
BUFFER_TRACE(ent->dir_bh, "get_write_access");
- return ext4_journal_get_write_access(handle, ent->dir_bh);
+ return ext4_journal_get_write_access(handle, ent->dir->i_sb,
+ ent->dir_bh, EXT4_JTR_NONE);
}
static int ext4_rename_dir_finish(handle_t *handle, struct ext4_renament *ent,
@@ -3710,7 +3539,8 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
int retval, retval2;
BUFFER_TRACE(ent->bh, "get write access");
- retval = ext4_journal_get_write_access(handle, ent->bh);
+ retval = ext4_journal_get_write_access(handle, ent->dir->i_sb, ent->bh,
+ EXT4_JTR_NONE);
if (retval)
return retval;
ent->de->inode = cpu_to_le32(ino);
diff --git a/fs/ext4/orphan.c b/fs/ext4/orphan.c
new file mode 100644
index 000000000000..53adc8f570a3
--- /dev/null
+++ b/fs/ext4/orphan.c
@@ -0,0 +1,652 @@
+/*
+ * Ext4 orphan inode handling
+ */
+#include <linux/fs.h>
+#include <linux/quotaops.h>
+#include <linux/buffer_head.h>
+
+#include "ext4.h"
+#include "ext4_jbd2.h"
+
+static int ext4_orphan_file_add(handle_t *handle, struct inode *inode)
+{
+ int i, j, start;
+ struct ext4_orphan_info *oi = &EXT4_SB(inode->i_sb)->s_orphan_info;
+ int ret = 0;
+ bool found = false;
+ __le32 *bdata;
+ int inodes_per_ob = ext4_inodes_per_orphan_block(inode->i_sb);
+ int looped = 0;
+
+ /*
+ * Find block with free orphan entry. Use CPU number for a naive hash
+ * for a search start in the orphan file
+ */
+ start = raw_smp_processor_id()*13 % oi->of_blocks;
+ i = start;
+ do {
+ if (atomic_dec_if_positive(&oi->of_binfo[i].ob_free_entries)
+ >= 0) {
+ found = true;
+ break;
+ }
+ if (++i >= oi->of_blocks)
+ i = 0;
+ } while (i != start);
+
+ if (!found) {
+ /*
+ * For now we don't grow or shrink orphan file. We just use
+ * whatever was allocated at mke2fs time. The additional
+ * credits we would have to reserve for each orphan inode
+ * operation just don't seem worth it.
+ */
+ return -ENOSPC;
+ }
+
+ ret = ext4_journal_get_write_access(handle, inode->i_sb,
+ oi->of_binfo[i].ob_bh, EXT4_JTR_ORPHAN_FILE);
+ if (ret) {
+ atomic_inc(&oi->of_binfo[i].ob_free_entries);
+ return ret;
+ }
+
+ bdata = (__le32 *)(oi->of_binfo[i].ob_bh->b_data);
+ /* Find empty slot in a block */
+ j = 0;
+ do {
+ if (looped) {
+ /*
+ * Did we walk through the block several times without
+ * finding free entry? It is theoretically possible
+ * if entries get constantly allocated and freed or
+ * if the block is corrupted. Avoid indefinite looping
+ * and bail. We'll use orphan list instead.
+ */
+ if (looped > 3) {
+ atomic_inc(&oi->of_binfo[i].ob_free_entries);
+ return -ENOSPC;
+ }
+ cond_resched();
+ }
+ while (bdata[j]) {
+ if (++j >= inodes_per_ob) {
+ j = 0;
+ looped++;
+ }
+ }
+ } while (cmpxchg(&bdata[j], (__le32)0, cpu_to_le32(inode->i_ino)) !=
+ (__le32)0);
+
+ EXT4_I(inode)->i_orphan_idx = i * inodes_per_ob + j;
+ ext4_set_inode_state(inode, EXT4_STATE_ORPHAN_FILE);
+
+ return ext4_handle_dirty_metadata(handle, NULL, oi->of_binfo[i].ob_bh);
+}
+
+/*
+ * ext4_orphan_add() links an unlinked or truncated inode into a list of
+ * such inodes, starting at the superblock, in case we crash before the
+ * file is closed/deleted, or in case the inode truncate spans multiple
+ * transactions and the last transaction is not recovered after a crash.
+ *
+ * At filesystem recovery time, we walk this list deleting unlinked
+ * inodes and truncating linked inodes in ext4_orphan_cleanup().
+ *
+ * Orphan list manipulation functions must be called under i_mutex unless
+ * we are just creating the inode or deleting it.
+ */
+int ext4_orphan_add(handle_t *handle, struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ struct ext4_iloc iloc;
+ int err = 0, rc;
+ bool dirty = false;
+
+ if (!sbi->s_journal || is_bad_inode(inode))
+ return 0;
+
+ WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
+ !inode_is_locked(inode));
+ /*
+ * Inode orphaned in orphan file or in orphan list?
+ */
+ if (ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE) ||
+ !list_empty(&EXT4_I(inode)->i_orphan))
+ return 0;
+
+ /*
+ * Orphan handling is only valid for files with data blocks
+ * being truncated, or files being unlinked. Note that we either
+ * hold i_mutex, or the inode can not be referenced from outside,
+ * so i_nlink should not be bumped due to race
+ */
+ ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
+
+ if (sbi->s_orphan_info.of_blocks) {
+ err = ext4_orphan_file_add(handle, inode);
+ /*
+ * Fallback to normal orphan list of orphan file is
+ * out of space
+ */
+ if (err != -ENOSPC)
+ return err;
+ }
+
+ BUFFER_TRACE(sbi->s_sbh, "get_write_access");
+ err = ext4_journal_get_write_access(handle, sb, sbi->s_sbh,
+ EXT4_JTR_NONE);
+ if (err)
+ goto out;
+
+ err = ext4_reserve_inode_write(handle, inode, &iloc);
+ if (err)
+ goto out;
+
+ mutex_lock(&sbi->s_orphan_lock);
+ /*
+ * Due to previous errors inode may be already a part of on-disk
+ * orphan list. If so skip on-disk list modification.
+ */
+ if (!NEXT_ORPHAN(inode) || NEXT_ORPHAN(inode) >
+ (le32_to_cpu(sbi->s_es->s_inodes_count))) {
+ /* Insert this inode at the head of the on-disk orphan list */
+ NEXT_ORPHAN(inode) = le32_to_cpu(sbi->s_es->s_last_orphan);
+ lock_buffer(sbi->s_sbh);
+ sbi->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
+ ext4_superblock_csum_set(sb);
+ unlock_buffer(sbi->s_sbh);
+ dirty = true;
+ }
+ list_add(&EXT4_I(inode)->i_orphan, &sbi->s_orphan);
+ mutex_unlock(&sbi->s_orphan_lock);
+
+ if (dirty) {
+ err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
+ rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
+ if (!err)
+ err = rc;
+ if (err) {
+ /*
+ * We have to remove inode from in-memory list if
+ * addition to on disk orphan list failed. Stray orphan
+ * list entries can cause panics at unmount time.
+ */
+ mutex_lock(&sbi->s_orphan_lock);
+ list_del_init(&EXT4_I(inode)->i_orphan);
+ mutex_unlock(&sbi->s_orphan_lock);
+ }
+ } else
+ brelse(iloc.bh);
+
+ jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
+ jbd_debug(4, "orphan inode %lu will point to %d\n",
+ inode->i_ino, NEXT_ORPHAN(inode));
+out:
+ ext4_std_error(sb, err);
+ return err;
+}
+
+static int ext4_orphan_file_del(handle_t *handle, struct inode *inode)
+{
+ struct ext4_orphan_info *oi = &EXT4_SB(inode->i_sb)->s_orphan_info;
+ __le32 *bdata;
+ int blk, off;
+ int inodes_per_ob = ext4_inodes_per_orphan_block(inode->i_sb);
+ int ret = 0;
+
+ if (!handle)
+ goto out;
+ blk = EXT4_I(inode)->i_orphan_idx / inodes_per_ob;
+ off = EXT4_I(inode)->i_orphan_idx % inodes_per_ob;
+ if (WARN_ON_ONCE(blk >= oi->of_blocks))
+ goto out;
+
+ ret = ext4_journal_get_write_access(handle, inode->i_sb,
+ oi->of_binfo[blk].ob_bh, EXT4_JTR_ORPHAN_FILE);
+ if (ret)
+ goto out;
+
+ bdata = (__le32 *)(oi->of_binfo[blk].ob_bh->b_data);
+ bdata[off] = 0;
+ atomic_inc(&oi->of_binfo[blk].ob_free_entries);
+ ret = ext4_handle_dirty_metadata(handle, NULL, oi->of_binfo[blk].ob_bh);
+out:
+ ext4_clear_inode_state(inode, EXT4_STATE_ORPHAN_FILE);
+ INIT_LIST_HEAD(&EXT4_I(inode)->i_orphan);
+
+ return ret;
+}
+
+/*
+ * ext4_orphan_del() removes an unlinked or truncated inode from the list
+ * of such inodes stored on disk, because it is finally being cleaned up.
+ */
+int ext4_orphan_del(handle_t *handle, struct inode *inode)
+{
+ struct list_head *prev;
+ struct ext4_inode_info *ei = EXT4_I(inode);
+ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ __u32 ino_next;
+ struct ext4_iloc iloc;
+ int err = 0;
+
+ if (!sbi->s_journal && !(sbi->s_mount_state & EXT4_ORPHAN_FS))
+ return 0;
+
+ WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
+ !inode_is_locked(inode));
+ if (ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE))
+ return ext4_orphan_file_del(handle, inode);
+
+ /* Do this quick check before taking global s_orphan_lock. */
+ if (list_empty(&ei->i_orphan))
+ return 0;
+
+ if (handle) {
+ /* Grab inode buffer early before taking global s_orphan_lock */
+ err = ext4_reserve_inode_write(handle, inode, &iloc);
+ }
+
+ mutex_lock(&sbi->s_orphan_lock);
+ jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
+
+ prev = ei->i_orphan.prev;
+ list_del_init(&ei->i_orphan);
+
+ /* If we're on an error path, we may not have a valid
+ * transaction handle with which to update the orphan list on
+ * disk, but we still need to remove the inode from the linked
+ * list in memory. */
+ if (!handle || err) {
+ mutex_unlock(&sbi->s_orphan_lock);
+ goto out_err;
+ }
+
+ ino_next = NEXT_ORPHAN(inode);
+ if (prev == &sbi->s_orphan) {
+ jbd_debug(4, "superblock will point to %u\n", ino_next);
+ BUFFER_TRACE(sbi->s_sbh, "get_write_access");
+ err = ext4_journal_get_write_access(handle, inode->i_sb,
+ sbi->s_sbh, EXT4_JTR_NONE);
+ if (err) {
+ mutex_unlock(&sbi->s_orphan_lock);
+ goto out_brelse;
+ }
+ lock_buffer(sbi->s_sbh);
+ sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
+ ext4_superblock_csum_set(inode->i_sb);
+ unlock_buffer(sbi->s_sbh);
+ mutex_unlock(&sbi->s_orphan_lock);
+ err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
+ } else {
+ struct ext4_iloc iloc2;
+ struct inode *i_prev =
+ &list_entry(prev, struct ext4_inode_info, i_orphan)->vfs_inode;
+
+ jbd_debug(4, "orphan inode %lu will point to %u\n",
+ i_prev->i_ino, ino_next);
+ err = ext4_reserve_inode_write(handle, i_prev, &iloc2);
+ if (err) {
+ mutex_unlock(&sbi->s_orphan_lock);
+ goto out_brelse;
+ }
+ NEXT_ORPHAN(i_prev) = ino_next;
+ err = ext4_mark_iloc_dirty(handle, i_prev, &iloc2);
+ mutex_unlock(&sbi->s_orphan_lock);
+ }
+ if (err)
+ goto out_brelse;
+ NEXT_ORPHAN(inode) = 0;
+ err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+out_err:
+ ext4_std_error(inode->i_sb, err);
+ return err;
+
+out_brelse:
+ brelse(iloc.bh);
+ goto out_err;
+}
+
+#ifdef CONFIG_QUOTA
+static int ext4_quota_on_mount(struct super_block *sb, int type)
+{
+ return dquot_quota_on_mount(sb,
+ rcu_dereference_protected(EXT4_SB(sb)->s_qf_names[type],
+ lockdep_is_held(&sb->s_umount)),
+ EXT4_SB(sb)->s_jquota_fmt, type);
+}
+#endif
+
+static void ext4_process_orphan(struct inode *inode,
+ int *nr_truncates, int *nr_orphans)
+{
+ struct super_block *sb = inode->i_sb;
+ int ret;
+
+ dquot_initialize(inode);
+ if (inode->i_nlink) {
+ if (test_opt(sb, DEBUG))
+ ext4_msg(sb, KERN_DEBUG,
+ "%s: truncating inode %lu to %lld bytes",
+ __func__, inode->i_ino, inode->i_size);
+ jbd_debug(2, "truncating inode %lu to %lld bytes\n",
+ inode->i_ino, inode->i_size);
+ inode_lock(inode);
+ truncate_inode_pages(inode->i_mapping, inode->i_size);
+ ret = ext4_truncate(inode);
+ if (ret) {
+ /*
+ * We need to clean up the in-core orphan list
+ * manually if ext4_truncate() failed to get a
+ * transaction handle.
+ */
+ ext4_orphan_del(NULL, inode);
+ ext4_std_error(inode->i_sb, ret);
+ }
+ inode_unlock(inode);
+ (*nr_truncates)++;
+ } else {
+ if (test_opt(sb, DEBUG))
+ ext4_msg(sb, KERN_DEBUG,
+ "%s: deleting unreferenced inode %lu",
+ __func__, inode->i_ino);
+ jbd_debug(2, "deleting unreferenced inode %lu\n",
+ inode->i_ino);
+ (*nr_orphans)++;
+ }
+ iput(inode); /* The delete magic happens here! */
+}
+
+/* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at
+ * the superblock) which were deleted from all directories, but held open by
+ * a process at the time of a crash. We walk the list and try to delete these
+ * inodes at recovery time (only with a read-write filesystem).
+ *
+ * In order to keep the orphan inode chain consistent during traversal (in
+ * case of crash during recovery), we link each inode into the superblock
+ * orphan list_head and handle it the same way as an inode deletion during
+ * normal operation (which journals the operations for us).
+ *
+ * We only do an iget() and an iput() on each inode, which is very safe if we
+ * accidentally point at an in-use or already deleted inode. The worst that
+ * can happen in this case is that we get a "bit already cleared" message from
+ * ext4_free_inode(). The only reason we would point at a wrong inode is if
+ * e2fsck was run on this filesystem, and it must have already done the orphan
+ * inode cleanup for us, so we can safely abort without any further action.
+ */
+void ext4_orphan_cleanup(struct super_block *sb, struct ext4_super_block *es)
+{
+ unsigned int s_flags = sb->s_flags;
+ int nr_orphans = 0, nr_truncates = 0;
+ struct inode *inode;
+ int i, j;
+#ifdef CONFIG_QUOTA
+ int quota_update = 0;
+#endif
+ __le32 *bdata;
+ struct ext4_orphan_info *oi = &EXT4_SB(sb)->s_orphan_info;
+ int inodes_per_ob = ext4_inodes_per_orphan_block(sb);
+
+ if (!es->s_last_orphan && !oi->of_blocks) {
+ jbd_debug(4, "no orphan inodes to clean up\n");
+ return;
+ }
+
+ if (bdev_read_only(sb->s_bdev)) {
+ ext4_msg(sb, KERN_ERR, "write access "
+ "unavailable, skipping orphan cleanup");
+ return;
+ }
+
+ /* Check if feature set would not allow a r/w mount */
+ if (!ext4_feature_set_ok(sb, 0)) {
+ ext4_msg(sb, KERN_INFO, "Skipping orphan cleanup due to "
+ "unknown ROCOMPAT features");
+ return;
+ }
+
+ if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
+ /* don't clear list on RO mount w/ errors */
+ if (es->s_last_orphan && !(s_flags & SB_RDONLY)) {
+ ext4_msg(sb, KERN_INFO, "Errors on filesystem, "
+ "clearing orphan list.\n");
+ es->s_last_orphan = 0;
+ }
+ jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
+ return;
+ }
+
+ if (s_flags & SB_RDONLY) {
+ ext4_msg(sb, KERN_INFO, "orphan cleanup on readonly fs");
+ sb->s_flags &= ~SB_RDONLY;
+ }
+#ifdef CONFIG_QUOTA
+ /*
+ * Turn on quotas which were not enabled for read-only mounts if
+ * filesystem has quota feature, so that they are updated correctly.
+ */
+ if (ext4_has_feature_quota(sb) && (s_flags & SB_RDONLY)) {
+ int ret = ext4_enable_quotas(sb);
+
+ if (!ret)
+ quota_update = 1;
+ else
+ ext4_msg(sb, KERN_ERR,
+ "Cannot turn on quotas: error %d", ret);
+ }
+
+ /* Turn on journaled quotas used for old sytle */
+ for (i = 0; i < EXT4_MAXQUOTAS; i++) {
+ if (EXT4_SB(sb)->s_qf_names[i]) {
+ int ret = ext4_quota_on_mount(sb, i);
+
+ if (!ret)
+ quota_update = 1;
+ else
+ ext4_msg(sb, KERN_ERR,
+ "Cannot turn on journaled "
+ "quota: type %d: error %d", i, ret);
+ }
+ }
+#endif
+
+ while (es->s_last_orphan) {
+ /*
+ * We may have encountered an error during cleanup; if
+ * so, skip the rest.
+ */
+ if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
+ jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
+ es->s_last_orphan = 0;
+ break;
+ }
+
+ inode = ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan));
+ if (IS_ERR(inode)) {
+ es->s_last_orphan = 0;
+ break;
+ }
+
+ list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
+ ext4_process_orphan(inode, &nr_truncates, &nr_orphans);
+ }
+
+ for (i = 0; i < oi->of_blocks; i++) {
+ bdata = (__le32 *)(oi->of_binfo[i].ob_bh->b_data);
+ for (j = 0; j < inodes_per_ob; j++) {
+ if (!bdata[j])
+ continue;
+ inode = ext4_orphan_get(sb, le32_to_cpu(bdata[j]));
+ if (IS_ERR(inode))
+ continue;
+ ext4_set_inode_state(inode, EXT4_STATE_ORPHAN_FILE);
+ EXT4_I(inode)->i_orphan_idx = i * inodes_per_ob + j;
+ ext4_process_orphan(inode, &nr_truncates, &nr_orphans);
+ }
+ }
+
+#define PLURAL(x) (x), ((x) == 1) ? "" : "s"
+
+ if (nr_orphans)
+ ext4_msg(sb, KERN_INFO, "%d orphan inode%s deleted",
+ PLURAL(nr_orphans));
+ if (nr_truncates)
+ ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
+ PLURAL(nr_truncates));
+#ifdef CONFIG_QUOTA
+ /* Turn off quotas if they were enabled for orphan cleanup */
+ if (quota_update) {
+ for (i = 0; i < EXT4_MAXQUOTAS; i++) {
+ if (sb_dqopt(sb)->files[i])
+ dquot_quota_off(sb, i);
+ }
+ }
+#endif
+ sb->s_flags = s_flags; /* Restore SB_RDONLY status */
+}
+
+void ext4_release_orphan_info(struct super_block *sb)
+{
+ int i;
+ struct ext4_orphan_info *oi = &EXT4_SB(sb)->s_orphan_info;
+
+ if (!oi->of_blocks)
+ return;
+ for (i = 0; i < oi->of_blocks; i++)
+ brelse(oi->of_binfo[i].ob_bh);
+ kfree(oi->of_binfo);
+}
+
+static struct ext4_orphan_block_tail *ext4_orphan_block_tail(
+ struct super_block *sb,
+ struct buffer_head *bh)
+{
+ return (struct ext4_orphan_block_tail *)(bh->b_data + sb->s_blocksize -
+ sizeof(struct ext4_orphan_block_tail));
+}
+
+static int ext4_orphan_file_block_csum_verify(struct super_block *sb,
+ struct buffer_head *bh)
+{
+ __u32 calculated;
+ int inodes_per_ob = ext4_inodes_per_orphan_block(sb);
+ struct ext4_orphan_info *oi = &EXT4_SB(sb)->s_orphan_info;
+ struct ext4_orphan_block_tail *ot;
+ __le64 dsk_block_nr = cpu_to_le64(bh->b_blocknr);
+
+ if (!ext4_has_metadata_csum(sb))
+ return 1;
+
+ ot = ext4_orphan_block_tail(sb, bh);
+ calculated = ext4_chksum(EXT4_SB(sb), oi->of_csum_seed,
+ (__u8 *)&dsk_block_nr, sizeof(dsk_block_nr));
+ calculated = ext4_chksum(EXT4_SB(sb), calculated, (__u8 *)bh->b_data,
+ inodes_per_ob * sizeof(__u32));
+ return le32_to_cpu(ot->ob_checksum) == calculated;
+}
+
+/* This gets called only when checksumming is enabled */
+void ext4_orphan_file_block_trigger(struct jbd2_buffer_trigger_type *triggers,
+ struct buffer_head *bh,
+ void *data, size_t size)
+{
+ struct super_block *sb = EXT4_TRIGGER(triggers)->sb;
+ __u32 csum;
+ int inodes_per_ob = ext4_inodes_per_orphan_block(sb);
+ struct ext4_orphan_info *oi = &EXT4_SB(sb)->s_orphan_info;
+ struct ext4_orphan_block_tail *ot;
+ __le64 dsk_block_nr = cpu_to_le64(bh->b_blocknr);
+
+ csum = ext4_chksum(EXT4_SB(sb), oi->of_csum_seed,
+ (__u8 *)&dsk_block_nr, sizeof(dsk_block_nr));
+ csum = ext4_chksum(EXT4_SB(sb), csum, (__u8 *)data,
+ inodes_per_ob * sizeof(__u32));
+ ot = ext4_orphan_block_tail(sb, bh);
+ ot->ob_checksum = cpu_to_le32(csum);
+}
+
+int ext4_init_orphan_info(struct super_block *sb)
+{
+ struct ext4_orphan_info *oi = &EXT4_SB(sb)->s_orphan_info;
+ struct inode *inode;
+ int i, j;
+ int ret;
+ int free;
+ __le32 *bdata;
+ int inodes_per_ob = ext4_inodes_per_orphan_block(sb);
+ struct ext4_orphan_block_tail *ot;
+ ino_t orphan_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_orphan_file_inum);
+
+ if (!ext4_has_feature_orphan_file(sb))
+ return 0;
+
+ inode = ext4_iget(sb, orphan_ino, EXT4_IGET_SPECIAL);
+ if (IS_ERR(inode)) {
+ ext4_msg(sb, KERN_ERR, "get orphan inode failed");
+ return PTR_ERR(inode);
+ }
+ oi->of_blocks = inode->i_size >> sb->s_blocksize_bits;
+ oi->of_csum_seed = EXT4_I(inode)->i_csum_seed;
+ oi->of_binfo = kmalloc(oi->of_blocks*sizeof(struct ext4_orphan_block),
+ GFP_KERNEL);
+ if (!oi->of_binfo) {
+ ret = -ENOMEM;
+ goto out_put;
+ }
+ for (i = 0; i < oi->of_blocks; i++) {
+ oi->of_binfo[i].ob_bh = ext4_bread(NULL, inode, i, 0);
+ if (IS_ERR(oi->of_binfo[i].ob_bh)) {
+ ret = PTR_ERR(oi->of_binfo[i].ob_bh);
+ goto out_free;
+ }
+ if (!oi->of_binfo[i].ob_bh) {
+ ret = -EIO;
+ goto out_free;
+ }
+ ot = ext4_orphan_block_tail(sb, oi->of_binfo[i].ob_bh);
+ if (le32_to_cpu(ot->ob_magic) != EXT4_ORPHAN_BLOCK_MAGIC) {
+ ext4_error(sb, "orphan file block %d: bad magic", i);
+ ret = -EIO;
+ goto out_free;
+ }
+ if (!ext4_orphan_file_block_csum_verify(sb,
+ oi->of_binfo[i].ob_bh)) {
+ ext4_error(sb, "orphan file block %d: bad checksum", i);
+ ret = -EIO;
+ goto out_free;
+ }
+ bdata = (__le32 *)(oi->of_binfo[i].ob_bh->b_data);
+ free = 0;
+ for (j = 0; j < inodes_per_ob; j++)
+ if (bdata[j] == 0)
+ free++;
+ atomic_set(&oi->of_binfo[i].ob_free_entries, free);
+ }
+ iput(inode);
+ return 0;
+out_free:
+ for (i--; i >= 0; i--)
+ brelse(oi->of_binfo[i].ob_bh);
+ kfree(oi->of_binfo);
+out_put:
+ iput(inode);
+ return ret;
+}
+
+int ext4_orphan_file_empty(struct super_block *sb)
+{
+ struct ext4_orphan_info *oi = &EXT4_SB(sb)->s_orphan_info;
+ int i;
+ int inodes_per_ob = ext4_inodes_per_orphan_block(sb);
+
+ if (!ext4_has_feature_orphan_file(sb))
+ return 1;
+ for (i = 0; i < oi->of_blocks; i++)
+ if (atomic_read(&oi->of_binfo[i].ob_free_entries) !=
+ inodes_per_ob)
+ return 0;
+ return 1;
+}
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 7a9f1adef679..b63cb88ccdae 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -409,7 +409,8 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
if (unlikely(!bh))
return ERR_PTR(-ENOMEM);
BUFFER_TRACE(bh, "get_write_access");
- if ((err = ext4_journal_get_write_access(handle, bh))) {
+ err = ext4_journal_get_write_access(handle, sb, bh, EXT4_JTR_NONE);
+ if (err) {
brelse(bh);
bh = ERR_PTR(err);
} else {
@@ -474,7 +475,8 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,
return -ENOMEM;
BUFFER_TRACE(bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle, sb, bh,
+ EXT4_JTR_NONE);
if (err) {
brelse(bh);
return err;
@@ -569,7 +571,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
}
BUFFER_TRACE(gdb, "get_write_access");
- err = ext4_journal_get_write_access(handle, gdb);
+ err = ext4_journal_get_write_access(handle, sb, gdb,
+ EXT4_JTR_NONE);
if (err) {
brelse(gdb);
goto out;
@@ -837,17 +840,18 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
}
BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
- err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+ err = ext4_journal_get_write_access(handle, sb, EXT4_SB(sb)->s_sbh,
+ EXT4_JTR_NONE);
if (unlikely(err))
goto errout;
BUFFER_TRACE(gdb_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, gdb_bh);
+ err = ext4_journal_get_write_access(handle, sb, gdb_bh, EXT4_JTR_NONE);
if (unlikely(err))
goto errout;
BUFFER_TRACE(dind, "get_write_access");
- err = ext4_journal_get_write_access(handle, dind);
+ err = ext4_journal_get_write_access(handle, sb, dind, EXT4_JTR_NONE);
if (unlikely(err)) {
ext4_std_error(sb, err);
goto errout;
@@ -956,7 +960,7 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
n_group_desc[gdb_num] = gdb_bh;
BUFFER_TRACE(gdb_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, gdb_bh);
+ err = ext4_journal_get_write_access(handle, sb, gdb_bh, EXT4_JTR_NONE);
if (err) {
kvfree(n_group_desc);
brelse(gdb_bh);
@@ -1042,7 +1046,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
for (i = 0; i < reserved_gdb; i++) {
BUFFER_TRACE(primary[i], "get_write_access");
- if ((err = ext4_journal_get_write_access(handle, primary[i])))
+ if ((err = ext4_journal_get_write_access(handle, sb, primary[i],
+ EXT4_JTR_NONE)))
goto exit_bh;
}
@@ -1149,10 +1154,9 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
backup_block, backup_block -
ext4_group_first_block_no(sb, group));
BUFFER_TRACE(bh, "get_write_access");
- if ((err = ext4_journal_get_write_access(handle, bh))) {
- brelse(bh);
+ if ((err = ext4_journal_get_write_access(handle, sb, bh,
+ EXT4_JTR_NONE)))
break;
- }
lock_buffer(bh);
memcpy(bh->b_data, data, size);
if (rest)
@@ -1232,7 +1236,8 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,
gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc,
gdb_num);
BUFFER_TRACE(gdb_bh, "get_write_access");
- err = ext4_journal_get_write_access(handle, gdb_bh);
+ err = ext4_journal_get_write_access(handle, sb, gdb_bh,
+ EXT4_JTR_NONE);
if (!err && reserved_gdb && ext4_bg_num_gdb(sb, group))
err = reserve_backup_gdb(handle, resize_inode, group);
@@ -1509,7 +1514,8 @@ static int ext4_flex_group_add(struct super_block *sb,
}
BUFFER_TRACE(sbi->s_sbh, "get_write_access");
- err = ext4_journal_get_write_access(handle, sbi->s_sbh);
+ err = ext4_journal_get_write_access(handle, sb, sbi->s_sbh,
+ EXT4_JTR_NONE);
if (err)
goto exit_journal;
@@ -1722,7 +1728,8 @@ static int ext4_group_extend_no_check(struct super_block *sb,
}
BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
- err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+ err = ext4_journal_get_write_access(handle, sb, EXT4_SB(sb)->s_sbh,
+ EXT4_JTR_NONE);
if (err) {
ext4_warning(sb, "error %d on journal write access", err);
goto errout;
@@ -1884,7 +1891,8 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
return PTR_ERR(handle);
BUFFER_TRACE(sbi->s_sbh, "get_write_access");
- err = ext4_journal_get_write_access(handle, sbi->s_sbh);
+ err = ext4_journal_get_write_access(handle, sb, sbi->s_sbh,
+ EXT4_JTR_NONE);
if (err)
goto errout;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index d6df62fc810c..136940af00b8 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -80,7 +80,6 @@ static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data);
static inline int ext2_feature_set_ok(struct super_block *sb);
static inline int ext3_feature_set_ok(struct super_block *sb);
-static int ext4_feature_set_ok(struct super_block *sb, int readonly);
static void ext4_destroy_lazyinit_thread(void);
static void ext4_unregister_li_request(struct super_block *sb);
static void ext4_clear_request_list(void);
@@ -1173,6 +1172,7 @@ static void ext4_put_super(struct super_block *sb)
flush_work(&sbi->s_error_work);
destroy_workqueue(sbi->rsv_conversion_wq);
+ ext4_release_orphan_info(sb);
/*
* Unregister sysfs before destroying jbd2 journal.
@@ -1198,6 +1198,7 @@ static void ext4_put_super(struct super_block *sb)
if (!sb_rdonly(sb) && !aborted) {
ext4_clear_feature_journal_needs_recovery(sb);
+ ext4_clear_feature_orphan_present(sb);
es->s_state = cpu_to_le16(sbi->s_mount_state);
}
if (!sb_rdonly(sb))
@@ -1582,14 +1583,12 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot);
static int ext4_write_info(struct super_block *sb, int type);
static int ext4_quota_on(struct super_block *sb, int type, int format_id,
const struct path *path);
-static int ext4_quota_on_mount(struct super_block *sb, int type);
static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
size_t len, loff_t off);
static ssize_t ext4_quota_write(struct super_block *sb, int type,
const char *data, size_t len, loff_t off);
static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
unsigned int flags);
-static int ext4_enable_quotas(struct super_block *sb);
static struct dquot **ext4_get_dquots(struct inode *inode)
{
@@ -2684,8 +2683,11 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
le16_add_cpu(&es->s_mnt_count, 1);
ext4_update_tstamp(es, s_mtime);
- if (sbi->s_journal)
+ if (sbi->s_journal) {
ext4_set_feature_journal_needs_recovery(sb);
+ if (ext4_has_feature_orphan_file(sb))
+ ext4_set_feature_orphan_present(sb);
+ }
err = ext4_commit_super(sb);
done:
@@ -2967,169 +2969,6 @@ static int ext4_check_descriptors(struct super_block *sb,
return 1;
}
-/* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at
- * the superblock) which were deleted from all directories, but held open by
- * a process at the time of a crash. We walk the list and try to delete these
- * inodes at recovery time (only with a read-write filesystem).
- *
- * In order to keep the orphan inode chain consistent during traversal (in
- * case of crash during recovery), we link each inode into the superblock
- * orphan list_head and handle it the same way as an inode deletion during
- * normal operation (which journals the operations for us).
- *
- * We only do an iget() and an iput() on each inode, which is very safe if we
- * accidentally point at an in-use or already deleted inode. The worst that
- * can happen in this case is that we get a "bit already cleared" message from
- * ext4_free_inode(). The only reason we would point at a wrong inode is if
- * e2fsck was run on this filesystem, and it must have already done the orphan
- * inode cleanup for us, so we can safely abort without any further action.
- */
-static void ext4_orphan_cleanup(struct super_block *sb,
- struct ext4_super_block *es)
-{
- unsigned int s_flags = sb->s_flags;
- int ret, nr_orphans = 0, nr_truncates = 0;
-#ifdef CONFIG_QUOTA
- int quota_update = 0;
- int i;
-#endif
- if (!es->s_last_orphan) {
- jbd_debug(4, "no orphan inodes to clean up\n");
- return;
- }
-
- if (bdev_read_only(sb->s_bdev)) {
- ext4_msg(sb, KERN_ERR, "write access "
- "unavailable, skipping orphan cleanup");
- return;
- }
-
- /* Check if feature set would not allow a r/w mount */
- if (!ext4_feature_set_ok(sb, 0)) {
- ext4_msg(sb, KERN_INFO, "Skipping orphan cleanup due to "
- "unknown ROCOMPAT features");
- return;
- }
-
- if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
- /* don't clear list on RO mount w/ errors */
- if (es->s_last_orphan && !(s_flags & SB_RDONLY)) {
- ext4_msg(sb, KERN_INFO, "Errors on filesystem, "
- "clearing orphan list.\n");
- es->s_last_orphan = 0;
- }
- jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
- return;
- }
-
- if (s_flags & SB_RDONLY) {
- ext4_msg(sb, KERN_INFO, "orphan cleanup on readonly fs");
- sb->s_flags &= ~SB_RDONLY;
- }
-#ifdef CONFIG_QUOTA
- /*
- * Turn on quotas which were not enabled for read-only mounts if
- * filesystem has quota feature, so that they are updated correctly.
- */
- if (ext4_has_feature_quota(sb) && (s_flags & SB_RDONLY)) {
- int ret = ext4_enable_quotas(sb);
-
- if (!ret)
- quota_update = 1;
- else
- ext4_msg(sb, KERN_ERR,
- "Cannot turn on quotas: error %d", ret);
- }
-
- /* Turn on journaled quotas used for old sytle */
- for (i = 0; i < EXT4_MAXQUOTAS; i++) {
- if (EXT4_SB(sb)->s_qf_names[i]) {
- int ret = ext4_quota_on_mount(sb, i);
-
- if (!ret)
- quota_update = 1;
- else
- ext4_msg(sb, KERN_ERR,
- "Cannot turn on journaled "
- "quota: type %d: error %d", i, ret);
- }
- }
-#endif
-
- while (es->s_last_orphan) {
- struct inode *inode;
-
- /*
- * We may have encountered an error during cleanup; if
- * so, skip the rest.
- */
- if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
- jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
- es->s_last_orphan = 0;
- break;
- }
-
- inode = ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan));
- if (IS_ERR(inode)) {
- es->s_last_orphan = 0;
- break;
- }
-
- list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
- dquot_initialize(inode);
- if (inode->i_nlink) {
- if (test_opt(sb, DEBUG))
- ext4_msg(sb, KERN_DEBUG,
- "%s: truncating inode %lu to %lld bytes",
- __func__, inode->i_ino, inode->i_size);
- jbd_debug(2, "truncating inode %lu to %lld bytes\n",
- inode->i_ino, inode->i_size);
- inode_lock(inode);
- truncate_inode_pages(inode->i_mapping, inode->i_size);
- ret = ext4_truncate(inode);
- if (ret) {
- /*
- * We need to clean up the in-core orphan list
- * manually if ext4_truncate() failed to get a
- * transaction handle.
- */
- ext4_orphan_del(NULL, inode);
- ext4_std_error(inode->i_sb, ret);
- }
- inode_unlock(inode);
- nr_truncates++;
- } else {
- if (test_opt(sb, DEBUG))
- ext4_msg(sb, KERN_DEBUG,
- "%s: deleting unreferenced inode %lu",
- __func__, inode->i_ino);
- jbd_debug(2, "deleting unreferenced inode %lu\n",
- inode->i_ino);
- nr_orphans++;
- }
- iput(inode); /* The delete magic happens here! */
- }
-
-#define PLURAL(x) (x), ((x) == 1) ? "" : "s"
-
- if (nr_orphans)
- ext4_msg(sb, KERN_INFO, "%d orphan inode%s deleted",
- PLURAL(nr_orphans));
- if (nr_truncates)
- ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
- PLURAL(nr_truncates));
-#ifdef CONFIG_QUOTA
- /* Turn off quotas if they were enabled for orphan cleanup */
- if (quota_update) {
- for (i = 0; i < EXT4_MAXQUOTAS; i++) {
- if (sb_dqopt(sb)->files[i])
- dquot_quota_off(sb, i);
- }
- }
-#endif
- sb->s_flags = s_flags; /* Restore SB_RDONLY status */
-}
-
/*
* Maximal extent format file size.
* Resulting logical blkno at s_maxbytes must fit in our on-disk
@@ -3309,7 +3148,7 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
* Returns 1 if this filesystem can be mounted as requested,
* 0 if it cannot be.
*/
-static int ext4_feature_set_ok(struct super_block *sb, int readonly)
+int ext4_feature_set_ok(struct super_block *sb, int readonly)
{
if (ext4_has_unknown_ext4_incompat_features(sb)) {
ext4_msg(sb, KERN_ERR,
@@ -4011,6 +3850,20 @@ static const char *ext4_quota_mode(struct super_block *sb)
#endif
}
+static void ext4_setup_csum_trigger(struct super_block *sb,
+ enum ext4_journal_trigger_type type,
+ void (*trigger)(
+ struct jbd2_buffer_trigger_type *type,
+ struct buffer_head *bh,
+ void *mapped_data,
+ size_t size))
+{
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+ sbi->s_journal_triggers[type].sb = sb;
+ sbi->s_journal_triggers[type].tr_triggers.t_frozen = trigger;
+}
+
static int ext4_fill_super(struct super_block *sb, void *data, int silent)
{
struct dax_device *dax_dev = fs_dax_get_by_bdev(sb->s_bdev);
@@ -4109,6 +3962,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
silent = 1;
goto cantfind_ext4;
}
+ ext4_setup_csum_trigger(sb, EXT4_JTR_ORPHAN_FILE,
+ ext4_orphan_file_block_trigger);
/* Load the checksum driver */
sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
@@ -4773,6 +4628,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sb->s_root = NULL;
needs_recovery = (es->s_last_orphan != 0 ||
+ ext4_has_feature_orphan_present(sb) ||
ext4_has_feature_journal_needs_recovery(sb));
if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb))
@@ -5029,6 +4885,14 @@ no_journal:
err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
GFP_KERNEL);
}
+ /*
+ * Update the checksum after updating free space/inode
+ * counters. Otherwise the superblock can have an incorrect
+ * checksum in the buffer cache until it is written out and
+ * e2fsprogs programs trying to open a file system immediately
+ * after it is mounted can fail.
+ */
+ ext4_superblock_csum_set(sb);
if (!err)
err = percpu_counter_init(&sbi->s_dirs_counter,
ext4_count_dirs(sb), GFP_KERNEL);
@@ -5063,12 +4927,15 @@ no_journal:
if (err)
goto failed_mount7;
+ err = ext4_init_orphan_info(sb);
+ if (err)
+ goto failed_mount8;
#ifdef CONFIG_QUOTA
/* Enable quota usage during mount. */
if (ext4_has_feature_quota(sb) && !sb_rdonly(sb)) {
err = ext4_enable_quotas(sb);
if (err)
- goto failed_mount8;
+ goto failed_mount9;
}
#endif /* CONFIG_QUOTA */
@@ -5087,7 +4954,7 @@ no_journal:
ext4_msg(sb, KERN_INFO, "recovery complete");
err = ext4_mark_recovery_complete(sb, es);
if (err)
- goto failed_mount8;
+ goto failed_mount9;
}
if (EXT4_SB(sb)->s_journal) {
if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
@@ -5133,6 +5000,8 @@ cantfind_ext4:
ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
goto failed_mount;
+failed_mount9:
+ ext4_release_orphan_info(sb);
failed_mount8:
ext4_unregister_sysfs(sb);
kobject_put(&sbi->s_kobj);
@@ -5643,8 +5512,15 @@ static int ext4_mark_recovery_complete(struct super_block *sb,
if (err < 0)
goto out;
- if (ext4_has_feature_journal_needs_recovery(sb) && sb_rdonly(sb)) {
+ if (sb_rdonly(sb) && (ext4_has_feature_journal_needs_recovery(sb) ||
+ ext4_has_feature_orphan_present(sb))) {
+ if (!ext4_orphan_file_empty(sb)) {
+ ext4_error(sb, "Orphan file not empty on read-only fs.");
+ err = -EFSCORRUPTED;
+ goto out;
+ }
ext4_clear_feature_journal_needs_recovery(sb);
+ ext4_clear_feature_orphan_present(sb);
ext4_commit_super(sb);
}
out:
@@ -5787,6 +5663,8 @@ static int ext4_freeze(struct super_block *sb)
/* Journal blocked and flushed, clear needs_recovery flag. */
ext4_clear_feature_journal_needs_recovery(sb);
+ if (ext4_orphan_file_empty(sb))
+ ext4_clear_feature_orphan_present(sb);
}
error = ext4_commit_super(sb);
@@ -5809,6 +5687,8 @@ static int ext4_unfreeze(struct super_block *sb)
if (EXT4_SB(sb)->s_journal) {
/* Reset the needs_recovery flag before the fs is unlocked. */
ext4_set_feature_journal_needs_recovery(sb);
+ if (ext4_has_feature_orphan_file(sb))
+ ext4_set_feature_orphan_present(sb);
}
ext4_commit_super(sb);
@@ -6012,7 +5892,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
* around from a previously readonly bdev mount,
* require a full umount/remount for now.
*/
- if (es->s_last_orphan) {
+ if (es->s_last_orphan || !ext4_orphan_file_empty(sb)) {
ext4_msg(sb, KERN_WARNING, "Couldn't "
"remount RDWR because of unprocessed "
"orphan inode list. Please "
@@ -6309,16 +6189,6 @@ static int ext4_write_info(struct super_block *sb, int type)
return ret;
}
-/*
- * Turn on quotas during mount time - we need to find
- * the quota file and such...
- */
-static int ext4_quota_on_mount(struct super_block *sb, int type)
-{
- return dquot_quota_on_mount(sb, get_qf_name(sb, EXT4_SB(sb), type),
- EXT4_SB(sb)->s_jquota_fmt, type);
-}
-
static void lockdep_set_quota_inode(struct inode *inode, int subclass)
{
struct ext4_inode_info *ei = EXT4_I(inode);
@@ -6448,7 +6318,7 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
}
/* Enable usage tracking for all quota types. */
-static int ext4_enable_quotas(struct super_block *sb)
+int ext4_enable_quotas(struct super_block *sb)
{
int type, err = 0;
unsigned long qf_inums[EXT4_MAXQUOTAS] = {
@@ -6606,7 +6476,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
if (!bh)
goto out;
BUFFER_TRACE(bh, "get write access");
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle, sb, bh, EXT4_JTR_NONE);
if (err) {
brelse(bh);
return err;
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 6dd5c05c444a..1e0fc1ed845b 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -791,7 +791,8 @@ static void ext4_xattr_update_super_block(handle_t *handle,
return;
BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
- if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
+ if (ext4_journal_get_write_access(handle, sb, EXT4_SB(sb)->s_sbh,
+ EXT4_JTR_NONE) == 0) {
lock_buffer(EXT4_SB(sb)->s_sbh);
ext4_set_feature_xattr(sb);
ext4_superblock_csum_set(sb);
@@ -1169,7 +1170,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
continue;
}
if (err > 0) {
- err = ext4_journal_get_write_access(handle, bh);
+ err = ext4_journal_get_write_access(handle,
+ parent->i_sb, bh, EXT4_JTR_NONE);
if (err) {
ext4_warning_inode(ea_inode,
"Re-get write access err=%d",
@@ -1230,7 +1232,8 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
int error = 0;
BUFFER_TRACE(bh, "get_write_access");
- error = ext4_journal_get_write_access(handle, bh);
+ error = ext4_journal_get_write_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (error)
goto out;
@@ -1371,7 +1374,8 @@ retry:
"ext4_getblk() return bh = NULL");
return -EFSCORRUPTED;
}
- ret = ext4_journal_get_write_access(handle, bh);
+ ret = ext4_journal_get_write_access(handle, ea_inode->i_sb, bh,
+ EXT4_JTR_NONE);
if (ret)
goto out;
@@ -1855,7 +1859,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
if (s->base) {
BUFFER_TRACE(bs->bh, "get_write_access");
- error = ext4_journal_get_write_access(handle, bs->bh);
+ error = ext4_journal_get_write_access(handle, sb, bs->bh,
+ EXT4_JTR_NONE);
if (error)
goto cleanup;
lock_buffer(bs->bh);
@@ -1987,8 +1992,9 @@ inserted:
if (error)
goto cleanup;
BUFFER_TRACE(new_bh, "get_write_access");
- error = ext4_journal_get_write_access(handle,
- new_bh);
+ error = ext4_journal_get_write_access(
+ handle, sb, new_bh,
+ EXT4_JTR_NONE);
if (error)
goto cleanup_dquot;
lock_buffer(new_bh);
@@ -2092,7 +2098,8 @@ getblk_failed:
}
lock_buffer(new_bh);
- error = ext4_journal_get_create_access(handle, new_bh);
+ error = ext4_journal_get_create_access(handle, sb,
+ new_bh, EXT4_JTR_NONE);
if (error) {
unlock_buffer(new_bh);
error = -EIO;
@@ -2848,7 +2855,8 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
goto cleanup;
}
- error = ext4_journal_get_write_access(handle, iloc.bh);
+ error = ext4_journal_get_write_access(handle, inode->i_sb,
+ iloc.bh, EXT4_JTR_NONE);
if (error) {
EXT4_ERROR_INODE(inode, "write access (error %d)",
error);
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
index 7669de7b49ce..7eea3cfd894d 100644
--- a/fs/f2fs/Kconfig
+++ b/fs/f2fs/Kconfig
@@ -105,6 +105,13 @@ config F2FS_FS_LZO
help
Support LZO compress algorithm, if unsure, say Y.
+config F2FS_FS_LZORLE
+ bool "LZO-RLE compression support"
+ depends on F2FS_FS_LZO
+ default y
+ help
+ Support LZO-RLE compress algorithm, if unsure, say Y.
+
config F2FS_FS_LZ4
bool "LZ4 compression support"
depends on F2FS_FS_COMPRESSION
@@ -114,7 +121,6 @@ config F2FS_FS_LZ4
config F2FS_FS_LZ4HC
bool "LZ4HC compression support"
- depends on F2FS_FS_COMPRESSION
depends on F2FS_FS_LZ4
default y
help
@@ -128,10 +134,11 @@ config F2FS_FS_ZSTD
help
Support ZSTD compress algorithm, if unsure, say Y.
-config F2FS_FS_LZORLE
- bool "LZO-RLE compression support"
- depends on F2FS_FS_COMPRESSION
- depends on F2FS_FS_LZO
+config F2FS_IOSTAT
+ bool "F2FS IO statistics information"
+ depends on F2FS_FS
default y
help
- Support LZO-RLE compress algorithm, if unsure, say Y.
+ Support getting IO statistics through sysfs and printing out periodic
+ IO statistics tracepoint events. You have to turn on "iostat_enable"
+ sysfs node to enable this feature.
diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile
index e5295746208b..8a7322d229e4 100644
--- a/fs/f2fs/Makefile
+++ b/fs/f2fs/Makefile
@@ -9,3 +9,4 @@ f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
f2fs-$(CONFIG_FS_VERITY) += verity.o
f2fs-$(CONFIG_F2FS_FS_COMPRESSION) += compress.o
+f2fs-$(CONFIG_F2FS_IOSTAT) += iostat.o
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 239ad9453b99..16e826e01f09 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -196,8 +196,11 @@ static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type,
return acl;
}
-struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
+struct posix_acl *f2fs_get_acl(struct inode *inode, int type, bool rcu)
{
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
return __f2fs_get_acl(inode, type, NULL);
}
diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h
index 986fd1bc780b..a26e33cab4ff 100644
--- a/fs/f2fs/acl.h
+++ b/fs/f2fs/acl.h
@@ -33,7 +33,7 @@ struct f2fs_acl_header {
#ifdef CONFIG_F2FS_FS_POSIX_ACL
-extern struct posix_acl *f2fs_get_acl(struct inode *, int);
+extern struct posix_acl *f2fs_get_acl(struct inode *, int, bool);
extern int f2fs_set_acl(struct user_namespace *, struct inode *,
struct posix_acl *, int);
extern int f2fs_init_acl(struct inode *, struct inode *, struct page *,
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 6c208108d69c..83e9bc0f91ff 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -18,6 +18,7 @@
#include "f2fs.h"
#include "node.h"
#include "segment.h"
+#include "iostat.h"
#include <trace/events/f2fs.h>
#define DEFAULT_CHECKPOINT_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3))
@@ -465,16 +466,29 @@ static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino,
unsigned int devidx, int type)
{
struct inode_management *im = &sbi->im[type];
- struct ino_entry *e, *tmp;
+ struct ino_entry *e = NULL, *new = NULL;
- tmp = f2fs_kmem_cache_alloc(ino_entry_slab, GFP_NOFS);
+ if (type == FLUSH_INO) {
+ rcu_read_lock();
+ e = radix_tree_lookup(&im->ino_root, ino);
+ rcu_read_unlock();
+ }
+
+retry:
+ if (!e)
+ new = f2fs_kmem_cache_alloc(ino_entry_slab,
+ GFP_NOFS, true, NULL);
radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
spin_lock(&im->ino_lock);
e = radix_tree_lookup(&im->ino_root, ino);
if (!e) {
- e = tmp;
+ if (!new) {
+ spin_unlock(&im->ino_lock);
+ goto retry;
+ }
+ e = new;
if (unlikely(radix_tree_insert(&im->ino_root, ino, e)))
f2fs_bug_on(sbi, 1);
@@ -492,8 +506,8 @@ static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino,
spin_unlock(&im->ino_lock);
radix_tree_preload_end();
- if (e != tmp)
- kmem_cache_free(ino_entry_slab, tmp);
+ if (new && e != new)
+ kmem_cache_free(ino_entry_slab, new);
}
static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
@@ -1289,12 +1303,20 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
unsigned long flags;
- spin_lock_irqsave(&sbi->cp_lock, flags);
+ if (cpc->reason & CP_UMOUNT) {
+ if (le32_to_cpu(ckpt->cp_pack_total_block_count) >
+ sbi->blocks_per_seg - NM_I(sbi)->nat_bits_blocks) {
+ clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
+ f2fs_notice(sbi, "Disable nat_bits due to no space");
+ } else if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG) &&
+ f2fs_nat_bitmap_enabled(sbi)) {
+ f2fs_enable_nat_bits(sbi);
+ set_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
+ f2fs_notice(sbi, "Rebuild and enable nat_bits");
+ }
+ }
- if ((cpc->reason & CP_UMOUNT) &&
- le32_to_cpu(ckpt->cp_pack_total_block_count) >
- sbi->blocks_per_seg - NM_I(sbi)->nat_bits_blocks)
- disable_nat_bits(sbi, false);
+ spin_lock_irqsave(&sbi->cp_lock, flags);
if (cpc->reason & CP_TRIMMED)
__set_ckpt_flags(ckpt, CP_TRIMMED_FLAG);
@@ -1480,7 +1502,8 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
start_blk = __start_cp_next_addr(sbi);
/* write nat bits */
- if (enabled_nat_bits(sbi, cpc)) {
+ if ((cpc->reason & CP_UMOUNT) &&
+ is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) {
__u64 cp_ver = cur_cp_version(ckpt);
block_t blk;
@@ -1639,8 +1662,11 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
/* write cached NAT/SIT entries to NAT/SIT area */
err = f2fs_flush_nat_entries(sbi, cpc);
- if (err)
+ if (err) {
+ f2fs_err(sbi, "f2fs_flush_nat_entries failed err:%d, stop checkpoint", err);
+ f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
goto stop;
+ }
f2fs_flush_sit_entries(sbi, cpc);
@@ -1648,10 +1674,13 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
f2fs_save_inmem_curseg(sbi);
err = do_checkpoint(sbi, cpc);
- if (err)
+ if (err) {
+ f2fs_err(sbi, "do_checkpoint failed err:%d, stop checkpoint", err);
+ f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
f2fs_release_discard_addrs(sbi);
- else
+ } else {
f2fs_clear_prefree_segments(sbi, cpc);
+ }
f2fs_restore_inmem_curseg(sbi);
stop:
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 455561826c7d..c1bf9ad4c220 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -28,7 +28,8 @@ static void *page_array_alloc(struct inode *inode, int nr)
unsigned int size = sizeof(struct page *) * nr;
if (likely(size <= sbi->page_array_slab_size))
- return kmem_cache_zalloc(sbi->page_array_slab, GFP_NOFS);
+ return f2fs_kmem_cache_alloc(sbi->page_array_slab,
+ GFP_F2FS_ZERO, false, F2FS_I_SB(inode));
return f2fs_kzalloc(sbi, size, GFP_NOFS);
}
@@ -898,6 +899,54 @@ static bool cluster_has_invalid_data(struct compress_ctx *cc)
return false;
}
+bool f2fs_sanity_check_cluster(struct dnode_of_data *dn)
+{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
+ unsigned int cluster_size = F2FS_I(dn->inode)->i_cluster_size;
+ bool compressed = dn->data_blkaddr == COMPRESS_ADDR;
+ int cluster_end = 0;
+ int i;
+ char *reason = "";
+
+ if (!compressed)
+ return false;
+
+ /* [..., COMPR_ADDR, ...] */
+ if (dn->ofs_in_node % cluster_size) {
+ reason = "[*|C|*|*]";
+ goto out;
+ }
+
+ for (i = 1; i < cluster_size; i++) {
+ block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
+ dn->ofs_in_node + i);
+
+ /* [COMPR_ADDR, ..., COMPR_ADDR] */
+ if (blkaddr == COMPRESS_ADDR) {
+ reason = "[C|*|C|*]";
+ goto out;
+ }
+ if (compressed) {
+ if (!__is_valid_data_blkaddr(blkaddr)) {
+ if (!cluster_end)
+ cluster_end = i;
+ continue;
+ }
+ /* [COMPR_ADDR, NULL_ADDR or NEW_ADDR, valid_blkaddr] */
+ if (cluster_end) {
+ reason = "[C|N|N|V]";
+ goto out;
+ }
+ }
+ }
+ return false;
+out:
+ f2fs_warn(sbi, "access invalid cluster, ino:%lu, nid:%u, ofs_in_node:%u, reason:%s",
+ dn->inode->i_ino, dn->nid, dn->ofs_in_node, reason);
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
+ return true;
+}
+
static int __f2fs_cluster_blocks(struct inode *inode,
unsigned int cluster_idx, bool compr)
{
@@ -915,6 +964,11 @@ static int __f2fs_cluster_blocks(struct inode *inode,
goto fail;
}
+ if (f2fs_sanity_check_cluster(&dn)) {
+ ret = -EFSCORRUPTED;
+ goto fail;
+ }
+
if (dn.data_blkaddr == COMPRESS_ADDR) {
int i;
@@ -1228,7 +1282,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
fio.version = ni.version;
- cic = kmem_cache_zalloc(cic_entry_slab, GFP_NOFS);
+ cic = f2fs_kmem_cache_alloc(cic_entry_slab, GFP_F2FS_ZERO, false, sbi);
if (!cic)
goto out_put_dnode;
@@ -1340,12 +1394,6 @@ out_destroy_crypt:
for (--i; i >= 0; i--)
fscrypt_finalize_bounce_page(&cc->cpages[i]);
- for (i = 0; i < cc->nr_cpages; i++) {
- if (!cc->cpages[i])
- continue;
- f2fs_compress_free_page(cc->cpages[i]);
- cc->cpages[i] = NULL;
- }
out_put_cic:
kmem_cache_free(cic_entry_slab, cic);
out_put_dnode:
@@ -1356,6 +1404,12 @@ out_unlock_op:
else
f2fs_unlock_op(sbi);
out_free:
+ for (i = 0; i < cc->nr_cpages; i++) {
+ if (!cc->cpages[i])
+ continue;
+ f2fs_compress_free_page(cc->cpages[i]);
+ cc->cpages[i] = NULL;
+ }
page_array_free(cc->inode, cc->cpages, cc->nr_cpages);
cc->cpages = NULL;
return -EAGAIN;
@@ -1506,7 +1560,8 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc)
pgoff_t start_idx = start_idx_of_cluster(cc);
int i;
- dic = kmem_cache_zalloc(dic_entry_slab, GFP_NOFS);
+ dic = f2fs_kmem_cache_alloc(dic_entry_slab, GFP_F2FS_ZERO,
+ false, F2FS_I_SB(cc->inode));
if (!dic)
return ERR_PTR(-ENOMEM);
@@ -1666,6 +1721,30 @@ void f2fs_put_page_dic(struct page *page)
f2fs_put_dic(dic);
}
+/*
+ * check whether cluster blocks are contiguous, and add extent cache entry
+ * only if cluster blocks are logically and physically contiguous.
+ */
+unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn)
+{
+ bool compressed = f2fs_data_blkaddr(dn) == COMPRESS_ADDR;
+ int i = compressed ? 1 : 0;
+ block_t first_blkaddr = data_blkaddr(dn->inode, dn->node_page,
+ dn->ofs_in_node + i);
+
+ for (i += 1; i < F2FS_I(dn->inode)->i_cluster_size; i++) {
+ block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
+ dn->ofs_in_node + i);
+
+ if (!__is_valid_data_blkaddr(blkaddr))
+ break;
+ if (first_blkaddr + i - (compressed ? 1 : 0) != blkaddr)
+ return 0;
+ }
+
+ return compressed ? i - 1 : i;
+}
+
const struct address_space_operations f2fs_compress_aops = {
.releasepage = f2fs_release_page,
.invalidatepage = f2fs_invalidate_page,
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index eb222b35edef..f4fd6c246c9a 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -25,6 +25,7 @@
#include "f2fs.h"
#include "node.h"
#include "segment.h"
+#include "iostat.h"
#include <trace/events/f2fs.h>
#define NUM_PREALLOC_POST_READ_CTXS 128
@@ -116,6 +117,7 @@ struct bio_post_read_ctx {
struct f2fs_sb_info *sbi;
struct work_struct work;
unsigned int enabled_steps;
+ block_t fs_blkaddr;
};
static void f2fs_finish_read_bio(struct bio *bio)
@@ -228,7 +230,7 @@ static void f2fs_handle_step_decompress(struct bio_post_read_ctx *ctx)
struct bio_vec *bv;
struct bvec_iter_all iter_all;
bool all_compressed = true;
- block_t blkaddr = SECTOR_TO_BLOCK(ctx->bio->bi_iter.bi_sector);
+ block_t blkaddr = ctx->fs_blkaddr;
bio_for_each_segment_all(bv, ctx->bio, iter_all) {
struct page *page = bv->bv_page;
@@ -269,7 +271,10 @@ static void f2fs_post_read_work(struct work_struct *work)
static void f2fs_read_end_io(struct bio *bio)
{
struct f2fs_sb_info *sbi = F2FS_P_SB(bio_first_page_all(bio));
- struct bio_post_read_ctx *ctx = bio->bi_private;
+ struct bio_post_read_ctx *ctx;
+
+ iostat_update_and_unbind_ctx(bio, 0);
+ ctx = bio->bi_private;
if (time_to_inject(sbi, FAULT_READ_IO)) {
f2fs_show_injection_info(sbi, FAULT_READ_IO);
@@ -291,10 +296,13 @@ static void f2fs_read_end_io(struct bio *bio)
static void f2fs_write_end_io(struct bio *bio)
{
- struct f2fs_sb_info *sbi = bio->bi_private;
+ struct f2fs_sb_info *sbi;
struct bio_vec *bvec;
struct bvec_iter_all iter_all;
+ iostat_update_and_unbind_ctx(bio, 1);
+ sbi = bio->bi_private;
+
if (time_to_inject(sbi, FAULT_WRITE_IO)) {
f2fs_show_injection_info(sbi, FAULT_WRITE_IO);
bio->bi_status = BLK_STS_IOERR;
@@ -398,6 +406,8 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages)
bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi,
fio->type, fio->temp);
}
+ iostat_alloc_and_bind_ctx(sbi, bio, NULL);
+
if (fio->io_wbc)
wbc_init_bio(fio->io_wbc, bio);
@@ -479,6 +489,8 @@ submit_io:
trace_f2fs_submit_read_bio(sbi->sb, type, bio);
else
trace_f2fs_submit_write_bio(sbi->sb, type, bio);
+
+ iostat_update_submit_ctx(bio, type);
submit_bio(bio);
}
@@ -723,7 +735,7 @@ static void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio,
struct f2fs_bio_info *io = sbi->write_io[DATA] + temp;
struct bio_entry *be;
- be = f2fs_kmem_cache_alloc(bio_entry_slab, GFP_NOFS);
+ be = f2fs_kmem_cache_alloc(bio_entry_slab, GFP_NOFS, true, NULL);
be->bio = bio;
bio_get(bio);
@@ -970,7 +982,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct bio *bio;
- struct bio_post_read_ctx *ctx;
+ struct bio_post_read_ctx *ctx = NULL;
unsigned int post_read_steps = 0;
bio = bio_alloc_bioset(for_write ? GFP_NOIO : GFP_KERNEL,
@@ -1003,8 +1015,10 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
ctx->bio = bio;
ctx->sbi = sbi;
ctx->enabled_steps = post_read_steps;
+ ctx->fs_blkaddr = blkaddr;
bio->bi_private = ctx;
}
+ iostat_alloc_and_bind_ctx(sbi, bio, ctx);
return bio;
}
@@ -1133,7 +1147,7 @@ int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index)
int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index)
{
- struct extent_info ei = {0, 0, 0};
+ struct extent_info ei = {0, };
struct inode *inode = dn->inode;
if (f2fs_lookup_extent_cache(inode, index, &ei)) {
@@ -1150,7 +1164,7 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
struct address_space *mapping = inode->i_mapping;
struct dnode_of_data dn;
struct page *page;
- struct extent_info ei = {0,0,0};
+ struct extent_info ei = {0, };
int err;
page = f2fs_grab_cache_page(mapping, index, for_write);
@@ -1448,7 +1462,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
int err = 0, ofs = 1;
unsigned int ofs_in_node, last_ofs_in_node;
blkcnt_t prealloc;
- struct extent_info ei = {0,0,0};
+ struct extent_info ei = {0, };
block_t blkaddr;
unsigned int start_pgofs;
@@ -1490,7 +1504,21 @@ next_dnode:
if (err) {
if (flag == F2FS_GET_BLOCK_BMAP)
map->m_pblk = 0;
+
if (err == -ENOENT) {
+ /*
+ * There is one exceptional case that read_node_page()
+ * may return -ENOENT due to filesystem has been
+ * shutdown or cp_error, so force to convert error
+ * number to EIO for such case.
+ */
+ if (map->m_may_create &&
+ (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) ||
+ f2fs_cp_error(sbi))) {
+ err = -EIO;
+ goto unlock_out;
+ }
+
err = 0;
if (map->m_next_pgofs)
*map->m_next_pgofs =
@@ -1550,6 +1578,13 @@ next_block:
map->m_flags |= F2FS_MAP_NEW;
blkaddr = dn.data_blkaddr;
} else {
+ if (f2fs_compressed_file(inode) &&
+ f2fs_sanity_check_cluster(&dn) &&
+ (flag != F2FS_GET_BLOCK_FIEMAP ||
+ IS_ENABLED(CONFIG_F2FS_CHECK_FS))) {
+ err = -EFSCORRUPTED;
+ goto sync_out;
+ }
if (flag == F2FS_GET_BLOCK_BMAP) {
map->m_pblk = 0;
goto sync_out;
@@ -1843,8 +1878,9 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 logical = 0, phys = 0, size = 0;
u32 flags = 0;
int ret = 0;
- bool compr_cluster = false;
+ bool compr_cluster = false, compr_appended;
unsigned int cluster_size = F2FS_I(inode)->i_cluster_size;
+ unsigned int count_in_cluster = 0;
loff_t maxbytes;
if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
@@ -1892,15 +1928,17 @@ next:
map.m_next_pgofs = &next_pgofs;
map.m_seg_type = NO_CHECK_TYPE;
- if (compr_cluster)
- map.m_len = cluster_size - 1;
+ if (compr_cluster) {
+ map.m_lblk += 1;
+ map.m_len = cluster_size - count_in_cluster;
+ }
ret = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_FIEMAP);
if (ret)
goto out;
/* HOLE */
- if (!(map.m_flags & F2FS_MAP_FLAGS)) {
+ if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) {
start_blk = next_pgofs;
if (blks_to_bytes(inode, start_blk) < blks_to_bytes(inode,
@@ -1910,6 +1948,14 @@ next:
flags |= FIEMAP_EXTENT_LAST;
}
+ compr_appended = false;
+ /* In a case of compressed cluster, append this to the last extent */
+ if (compr_cluster && ((map.m_flags & F2FS_MAP_UNWRITTEN) ||
+ !(map.m_flags & F2FS_MAP_FLAGS))) {
+ compr_appended = true;
+ goto skip_fill;
+ }
+
if (size) {
flags |= FIEMAP_EXTENT_MERGED;
if (IS_ENCRYPTED(inode))
@@ -1926,38 +1972,36 @@ next:
if (start_blk > last_blk)
goto out;
- if (compr_cluster) {
- compr_cluster = false;
-
-
- logical = blks_to_bytes(inode, start_blk - 1);
- phys = blks_to_bytes(inode, map.m_pblk);
- size = blks_to_bytes(inode, cluster_size);
-
- flags |= FIEMAP_EXTENT_ENCODED;
-
- start_blk += cluster_size - 1;
-
- if (start_blk > last_blk)
- goto out;
-
- goto prep_next;
- }
-
+skip_fill:
if (map.m_pblk == COMPRESS_ADDR) {
compr_cluster = true;
- start_blk++;
- goto prep_next;
- }
-
- logical = blks_to_bytes(inode, start_blk);
- phys = blks_to_bytes(inode, map.m_pblk);
- size = blks_to_bytes(inode, map.m_len);
- flags = 0;
- if (map.m_flags & F2FS_MAP_UNWRITTEN)
- flags = FIEMAP_EXTENT_UNWRITTEN;
+ count_in_cluster = 1;
+ } else if (compr_appended) {
+ unsigned int appended_blks = cluster_size -
+ count_in_cluster + 1;
+ size += blks_to_bytes(inode, appended_blks);
+ start_blk += appended_blks;
+ compr_cluster = false;
+ } else {
+ logical = blks_to_bytes(inode, start_blk);
+ phys = __is_valid_data_blkaddr(map.m_pblk) ?
+ blks_to_bytes(inode, map.m_pblk) : 0;
+ size = blks_to_bytes(inode, map.m_len);
+ flags = 0;
+
+ if (compr_cluster) {
+ flags = FIEMAP_EXTENT_ENCODED;
+ count_in_cluster += map.m_len;
+ if (count_in_cluster == cluster_size) {
+ compr_cluster = false;
+ size += blks_to_bytes(inode, 1);
+ }
+ } else if (map.m_flags & F2FS_MAP_UNWRITTEN) {
+ flags = FIEMAP_EXTENT_UNWRITTEN;
+ }
- start_blk += bytes_to_blks(inode, size);
+ start_blk += bytes_to_blks(inode, size);
+ }
prep_next:
cond_resched();
@@ -2115,6 +2159,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
sector_t last_block_in_file;
const unsigned blocksize = blks_to_bytes(inode, 1);
struct decompress_io_ctx *dic = NULL;
+ struct extent_info ei = {0, };
+ bool from_dnode = true;
int i;
int ret = 0;
@@ -2137,6 +2183,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
continue;
}
unlock_page(page);
+ if (for_write)
+ put_page(page);
cc->rpages[i] = NULL;
cc->nr_rpages--;
}
@@ -2145,6 +2193,12 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
if (f2fs_cluster_is_empty(cc))
goto out;
+ if (f2fs_lookup_extent_cache(inode, start_idx, &ei))
+ from_dnode = false;
+
+ if (!from_dnode)
+ goto skip_reading_dnode;
+
set_new_dnode(&dn, inode, NULL, NULL, 0);
ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE);
if (ret)
@@ -2152,11 +2206,13 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR);
+skip_reading_dnode:
for (i = 1; i < cc->cluster_size; i++) {
block_t blkaddr;
- blkaddr = data_blkaddr(dn.inode, dn.node_page,
- dn.ofs_in_node + i);
+ blkaddr = from_dnode ? data_blkaddr(dn.inode, dn.node_page,
+ dn.ofs_in_node + i) :
+ ei.blk + i - 1;
if (!__is_valid_data_blkaddr(blkaddr))
break;
@@ -2166,6 +2222,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
goto out_put_dnode;
}
cc->nr_cpages++;
+
+ if (!from_dnode && i >= ei.c_len)
+ break;
}
/* nothing to decompress */
@@ -2185,8 +2244,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
block_t blkaddr;
struct bio_post_read_ctx *ctx;
- blkaddr = data_blkaddr(dn.inode, dn.node_page,
- dn.ofs_in_node + i + 1);
+ blkaddr = from_dnode ? data_blkaddr(dn.inode, dn.node_page,
+ dn.ofs_in_node + i + 1) :
+ ei.blk + i;
f2fs_wait_on_block_writeback(inode, blkaddr);
@@ -2220,7 +2280,7 @@ submit_and_realloc:
if (bio_add_page(bio, page, blocksize, 0) < blocksize)
goto submit_and_realloc;
- ctx = bio->bi_private;
+ ctx = get_post_read_ctx(bio);
ctx->enabled_steps |= STEP_DECOMPRESS;
refcount_inc(&dic->refcnt);
@@ -2231,13 +2291,15 @@ submit_and_realloc:
*last_block_in_bio = blkaddr;
}
- f2fs_put_dnode(&dn);
+ if (from_dnode)
+ f2fs_put_dnode(&dn);
*bio_ret = bio;
return 0;
out_put_dnode:
- f2fs_put_dnode(&dn);
+ if (from_dnode)
+ f2fs_put_dnode(&dn);
out:
for (i = 0; i < cc->cluster_size; i++) {
if (cc->rpages[i]) {
@@ -2272,6 +2334,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
.nr_rpages = 0,
.nr_cpages = 0,
};
+ pgoff_t nc_cluster_idx = NULL_CLUSTER;
#endif
unsigned nr_pages = rac ? readahead_count(rac) : 1;
unsigned max_nr_pages = nr_pages;
@@ -2304,12 +2367,23 @@ static int f2fs_mpage_readpages(struct inode *inode,
if (ret)
goto set_error_page;
}
- ret = f2fs_is_compressed_cluster(inode, page->index);
- if (ret < 0)
- goto set_error_page;
- else if (!ret)
- goto read_single_page;
+ if (cc.cluster_idx == NULL_CLUSTER) {
+ if (nc_cluster_idx ==
+ page->index >> cc.log_cluster_size) {
+ goto read_single_page;
+ }
+ ret = f2fs_is_compressed_cluster(inode, page->index);
+ if (ret < 0)
+ goto set_error_page;
+ else if (!ret) {
+ nc_cluster_idx =
+ page->index >> cc.log_cluster_size;
+ goto read_single_page;
+ }
+
+ nc_cluster_idx = NULL_CLUSTER;
+ }
ret = f2fs_init_compress_ctx(&cc);
if (ret)
goto set_error_page;
@@ -2498,6 +2572,8 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
return true;
if (f2fs_is_atomic_file(inode))
return true;
+ if (is_sbi_flag_set(sbi, SBI_NEED_FSCK))
+ return true;
/* swap file is migrating in aligned write mode */
if (is_inode_flag_set(inode, FI_ALIGNED_WRITE))
@@ -2530,7 +2606,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
struct page *page = fio->page;
struct inode *inode = page->mapping->host;
struct dnode_of_data dn;
- struct extent_info ei = {0,0,0};
+ struct extent_info ei = {0, };
struct node_info ni;
bool ipu_force = false;
int err = 0;
@@ -3176,9 +3252,8 @@ static int f2fs_write_data_pages(struct address_space *mapping,
FS_CP_DATA_IO : FS_DATA_IO);
}
-static void f2fs_write_failed(struct address_space *mapping, loff_t to)
+static void f2fs_write_failed(struct inode *inode, loff_t to)
{
- struct inode *inode = mapping->host;
loff_t i_size = i_size_read(inode);
if (IS_NOQUOTA(inode))
@@ -3187,12 +3262,12 @@ static void f2fs_write_failed(struct address_space *mapping, loff_t to)
/* In the fs-verity case, f2fs_end_enable_verity() does the truncate */
if (to > i_size && !f2fs_verity_in_progress(inode)) {
down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
- filemap_invalidate_lock(mapping);
+ filemap_invalidate_lock(inode->i_mapping);
truncate_pagecache(inode, i_size);
f2fs_truncate_blocks(inode, i_size, true);
- filemap_invalidate_unlock(mapping);
+ filemap_invalidate_unlock(inode->i_mapping);
up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
}
}
@@ -3206,7 +3281,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
struct dnode_of_data dn;
struct page *ipage;
bool locked = false;
- struct extent_info ei = {0,0,0};
+ struct extent_info ei = {0, };
int err = 0;
int flag;
@@ -3328,6 +3403,9 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
*fsdata = NULL;
+ if (len == PAGE_SIZE)
+ goto repeat;
+
ret = f2fs_prepare_compress_overwrite(inode, pagep,
index, fsdata);
if (ret < 0) {
@@ -3410,7 +3488,7 @@ repeat:
fail:
f2fs_put_page(page, 1);
- f2fs_write_failed(mapping, pos + len);
+ f2fs_write_failed(inode, pos + len);
if (drop_atomic)
f2fs_drop_inmem_pages_all(sbi, false);
return err;
@@ -3552,7 +3630,7 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
if (f2fs_force_buffered_io(inode, iocb, iter))
return 0;
- do_opu = allow_outplace_dio(inode, iocb, iter);
+ do_opu = rw == WRITE && f2fs_lfs_mode(sbi);
trace_f2fs_direct_IO_enter(inode, offset, count, rw);
@@ -3600,7 +3678,7 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO,
count - iov_iter_count(iter));
} else if (err < 0) {
- f2fs_write_failed(mapping, offset + count);
+ f2fs_write_failed(inode, offset + count);
}
} else {
if (err > 0)
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 833325038ef3..8c50518475a9 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -323,11 +323,27 @@ get_cache:
#endif
}
+static char *s_flag[] = {
+ [SBI_IS_DIRTY] = " fs_dirty",
+ [SBI_IS_CLOSE] = " closing",
+ [SBI_NEED_FSCK] = " need_fsck",
+ [SBI_POR_DOING] = " recovering",
+ [SBI_NEED_SB_WRITE] = " sb_dirty",
+ [SBI_NEED_CP] = " need_cp",
+ [SBI_IS_SHUTDOWN] = " shutdown",
+ [SBI_IS_RECOVERED] = " recovered",
+ [SBI_CP_DISABLED] = " cp_disabled",
+ [SBI_CP_DISABLED_QUICK] = " cp_disabled_quick",
+ [SBI_QUOTA_NEED_FLUSH] = " quota_need_flush",
+ [SBI_QUOTA_SKIP_FLUSH] = " quota_skip_flush",
+ [SBI_QUOTA_NEED_REPAIR] = " quota_need_repair",
+ [SBI_IS_RESIZEFS] = " resizefs",
+};
+
static int stat_show(struct seq_file *s, void *v)
{
struct f2fs_stat_info *si;
- int i = 0;
- int j;
+ int i = 0, j = 0;
mutex_lock(&f2fs_stat_mutex);
list_for_each_entry(si, &f2fs_stat_list, stat_list) {
@@ -337,7 +353,13 @@ static int stat_show(struct seq_file *s, void *v)
si->sbi->sb->s_bdev, i++,
f2fs_readonly(si->sbi->sb) ? "RO": "RW",
is_set_ckpt_flags(si->sbi, CP_DISABLED_FLAG) ?
- "Disabled": (f2fs_cp_error(si->sbi) ? "Error": "Good"));
+ "Disabled" : (f2fs_cp_error(si->sbi) ? "Error" : "Good"));
+ if (si->sbi->s_flag) {
+ seq_puts(s, "[SBI:");
+ for_each_set_bit(j, &si->sbi->s_flag, 32)
+ seq_puts(s, s_flag[j]);
+ seq_puts(s, "]\n");
+ }
seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",
si->sit_area_segs, si->nat_area_segs);
seq_printf(s, "[SSA: %d] [MAIN: %d",
@@ -450,6 +472,15 @@ static int stat_show(struct seq_file *s, void *v)
si->data_segs, si->bg_data_segs);
seq_printf(s, " - node segments : %d (%d)\n",
si->node_segs, si->bg_node_segs);
+ seq_printf(s, " - Reclaimed segs : Normal (%d), Idle CB (%d), "
+ "Idle Greedy (%d), Idle AT (%d), "
+ "Urgent High (%d), Urgent Low (%d)\n",
+ si->sbi->gc_reclaimed_segs[GC_NORMAL],
+ si->sbi->gc_reclaimed_segs[GC_IDLE_CB],
+ si->sbi->gc_reclaimed_segs[GC_IDLE_GREEDY],
+ si->sbi->gc_reclaimed_segs[GC_IDLE_AT],
+ si->sbi->gc_reclaimed_segs[GC_URGENT_HIGH],
+ si->sbi->gc_reclaimed_segs[GC_URGENT_LOW]);
seq_printf(s, "Try to move %d blocks (BG: %d)\n", si->tot_blks,
si->bg_data_blks + si->bg_node_blks);
seq_printf(s, " - data blocks : %d (%d)\n", si->data_blks,
@@ -611,7 +642,7 @@ void __init f2fs_create_root_stats(void)
#ifdef CONFIG_DEBUG_FS
f2fs_debugfs_root = debugfs_create_dir("f2fs", NULL);
- debugfs_create_file("status", S_IRUGO, f2fs_debugfs_root, NULL,
+ debugfs_create_file("status", 0444, f2fs_debugfs_root, NULL,
&stat_fops);
#endif
}
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 456651682daf..1820e9c106f7 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -83,8 +83,8 @@ int f2fs_init_casefolded_name(const struct inode *dir,
struct super_block *sb = dir->i_sb;
if (IS_CASEFOLDED(dir)) {
- fname->cf_name.name = kmem_cache_alloc(f2fs_cf_name_slab,
- GFP_NOFS);
+ fname->cf_name.name = f2fs_kmem_cache_alloc(f2fs_cf_name_slab,
+ GFP_NOFS, false, F2FS_SB(sb));
if (!fname->cf_name.name)
return -ENOMEM;
fname->cf_name.len = utf8_casefold(sb->s_encoding,
@@ -1000,6 +1000,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
struct f2fs_sb_info *sbi = F2FS_I_SB(d->inode);
struct blk_plug plug;
bool readdir_ra = sbi->readdir_ra == 1;
+ bool found_valid_dirent = false;
int err = 0;
bit_pos = ((unsigned long)ctx->pos % d->max);
@@ -1014,13 +1015,15 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
de = &d->dentry[bit_pos];
if (de->name_len == 0) {
+ if (found_valid_dirent || !bit_pos) {
+ printk_ratelimited(
+ "%sF2FS-fs (%s): invalid namelen(0), ino:%u, run fsck to fix.",
+ KERN_WARNING, sbi->sb->s_id,
+ le32_to_cpu(de->ino));
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
+ }
bit_pos++;
ctx->pos = start_pos + bit_pos;
- printk_ratelimited(
- "%sF2FS-fs (%s): invalid namelen(0), ino:%u, run fsck to fix.",
- KERN_WARNING, sbi->sb->s_id,
- le32_to_cpu(de->ino));
- set_sbi_flag(sbi, SBI_NEED_FSCK);
continue;
}
@@ -1063,6 +1066,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
f2fs_ra_node_page(sbi, le32_to_cpu(de->ino));
ctx->pos = start_pos + bit_pos;
+ found_valid_dirent = true;
}
out:
if (readdir_ra)
diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
index 3ebf976a682d..866e72b29bd5 100644
--- a/fs/f2fs/extent_cache.c
+++ b/fs/f2fs/extent_cache.c
@@ -239,7 +239,7 @@ static struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi,
{
struct extent_node *en;
- en = kmem_cache_alloc(extent_node_slab, GFP_ATOMIC);
+ en = f2fs_kmem_cache_alloc(extent_node_slab, GFP_ATOMIC, false, sbi);
if (!en)
return NULL;
@@ -292,7 +292,8 @@ static struct extent_tree *__grab_extent_tree(struct inode *inode)
mutex_lock(&sbi->extent_tree_lock);
et = radix_tree_lookup(&sbi->extent_tree_root, ino);
if (!et) {
- et = f2fs_kmem_cache_alloc(extent_tree_slab, GFP_NOFS);
+ et = f2fs_kmem_cache_alloc(extent_tree_slab,
+ GFP_NOFS, true, NULL);
f2fs_radix_tree_insert(&sbi->extent_tree_root, ino, et);
memset(et, 0, sizeof(struct extent_tree));
et->ino = ino;
@@ -661,6 +662,47 @@ static void f2fs_update_extent_tree_range(struct inode *inode,
f2fs_mark_inode_dirty_sync(inode, true);
}
+#ifdef CONFIG_F2FS_FS_COMPRESSION
+void f2fs_update_extent_tree_range_compressed(struct inode *inode,
+ pgoff_t fofs, block_t blkaddr, unsigned int llen,
+ unsigned int c_len)
+{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+ struct extent_tree *et = F2FS_I(inode)->extent_tree;
+ struct extent_node *en = NULL;
+ struct extent_node *prev_en = NULL, *next_en = NULL;
+ struct extent_info ei;
+ struct rb_node **insert_p = NULL, *insert_parent = NULL;
+ bool leftmost = false;
+
+ trace_f2fs_update_extent_tree_range(inode, fofs, blkaddr, llen);
+
+ /* it is safe here to check FI_NO_EXTENT w/o et->lock in ro image */
+ if (is_inode_flag_set(inode, FI_NO_EXTENT))
+ return;
+
+ write_lock(&et->lock);
+
+ 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,
+ &insert_p, &insert_parent, false,
+ &leftmost);
+ if (en)
+ goto unlock_out;
+
+ set_extent_info(&ei, fofs, blkaddr, llen);
+ ei.c_len = c_len;
+
+ if (!__try_merge_extent_node(sbi, et, &ei, prev_en, next_en))
+ __insert_extent_tree(sbi, et, &ei,
+ insert_p, insert_parent, leftmost);
+unlock_out:
+ write_unlock(&et->lock);
+}
+#endif
+
unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink)
{
struct extent_tree *et, *next;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 906b2c4b50e7..b339ae89c1ad 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -43,6 +43,7 @@ enum {
FAULT_KVMALLOC,
FAULT_PAGE_ALLOC,
FAULT_PAGE_GET,
+ FAULT_ALLOC_BIO, /* it's obsolete due to bio_alloc() will never fail */
FAULT_ALLOC_NID,
FAULT_ORPHAN,
FAULT_BLOCK,
@@ -53,6 +54,7 @@ enum {
FAULT_CHECKPOINT,
FAULT_DISCARD,
FAULT_WRITE_IO,
+ FAULT_SLAB_ALLOC,
FAULT_MAX,
};
@@ -139,6 +141,11 @@ struct f2fs_mount_info {
int fsync_mode; /* fsync policy */
int fs_mode; /* fs mode: LFS or ADAPTIVE */
int bggc_mode; /* bggc mode: off, on or sync */
+ int discard_unit; /*
+ * discard command's offset/size should
+ * be aligned to this unit: block,
+ * segment or section
+ */
struct fscrypt_dummy_policy dummy_enc_policy; /* test dummy encryption */
block_t unusable_cap_perc; /* percentage for cap */
block_t unusable_cap; /* Amount of space allowed to be
@@ -542,7 +549,7 @@ enum {
*/
};
-#define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO count */
+#define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO or flush count */
/* congestion wait timeout value, default: 20ms */
#define DEFAULT_IO_TIMEOUT (msecs_to_jiffies(20))
@@ -575,6 +582,9 @@ struct extent_info {
unsigned int fofs; /* start offset in a file */
unsigned int len; /* length of the extent */
u32 blk; /* start block address of the extent */
+#ifdef CONFIG_F2FS_FS_COMPRESSION
+ unsigned int c_len; /* physical extent length of compressed blocks */
+#endif
};
struct extent_node {
@@ -793,6 +803,9 @@ static inline void set_extent_info(struct extent_info *ei, unsigned int fofs,
ei->fofs = fofs;
ei->blk = blk;
ei->len = len;
+#ifdef CONFIG_F2FS_FS_COMPRESSION
+ ei->c_len = 0;
+#endif
}
static inline bool __is_discard_mergeable(struct discard_info *back,
@@ -817,6 +830,12 @@ static inline bool __is_discard_front_mergeable(struct discard_info *cur,
static inline bool __is_extent_mergeable(struct extent_info *back,
struct extent_info *front)
{
+#ifdef CONFIG_F2FS_FS_COMPRESSION
+ if (back->c_len && back->len != back->c_len)
+ return false;
+ if (front->c_len && front->len != front->c_len)
+ return false;
+#endif
return (back->fofs + back->len == front->fofs &&
back->blk + back->len == front->blk);
}
@@ -1252,6 +1271,7 @@ enum {
GC_IDLE_AT,
GC_URGENT_HIGH,
GC_URGENT_LOW,
+ MAX_GC_MODE,
};
enum {
@@ -1297,6 +1317,12 @@ enum {
*/
};
+enum {
+ DISCARD_UNIT_BLOCK, /* basic discard unit is block */
+ DISCARD_UNIT_SEGMENT, /* basic discard unit is segment */
+ DISCARD_UNIT_SECTION, /* basic discard unit is section */
+};
+
static inline int f2fs_test_bit(unsigned int nr, char *addr);
static inline void f2fs_set_bit(unsigned int nr, char *addr);
static inline void f2fs_clear_bit(unsigned int nr, char *addr);
@@ -1686,14 +1712,6 @@ struct f2fs_sb_info {
#endif
spinlock_t stat_lock; /* lock for stat operations */
- /* For app/fs IO statistics */
- spinlock_t iostat_lock;
- unsigned long long rw_iostat[NR_IO_TYPE];
- unsigned long long prev_rw_iostat[NR_IO_TYPE];
- bool iostat_enable;
- unsigned long iostat_next_period;
- unsigned int iostat_period_ms;
-
/* to attach REQ_META|REQ_FUA flags */
unsigned int data_io_flag;
unsigned int node_io_flag;
@@ -1732,6 +1750,12 @@ struct f2fs_sb_info {
struct kmem_cache *inline_xattr_slab; /* inline xattr entry */
unsigned int inline_xattr_slab_size; /* default inline xattr slab size */
+ /* For reclaimed segs statistics per each GC mode */
+ unsigned int gc_segment_mode; /* GC state for reclaimed segments */
+ unsigned int gc_reclaimed_segs[MAX_GC_MODE]; /* Reclaimed segs for each mode */
+
+ unsigned long seq_file_ra_mul; /* multiplier for ra_pages of seq. files in fadvise */
+
#ifdef CONFIG_F2FS_FS_COMPRESSION
struct kmem_cache *page_array_slab; /* page array entry */
unsigned int page_array_slab_size; /* default page array slab size */
@@ -1747,6 +1771,20 @@ struct f2fs_sb_info {
unsigned int compress_watermark; /* cache page watermark */
atomic_t compress_page_hit; /* cache hit count */
#endif
+
+#ifdef CONFIG_F2FS_IOSTAT
+ /* For app/fs IO statistics */
+ spinlock_t iostat_lock;
+ unsigned long long rw_iostat[NR_IO_TYPE];
+ unsigned long long prev_rw_iostat[NR_IO_TYPE];
+ bool iostat_enable;
+ unsigned long iostat_next_period;
+ unsigned int iostat_period_ms;
+
+ /* For io latency related statistics info in one iostat period */
+ spinlock_t iostat_lat_lock;
+ struct iostat_lat_info *iostat_io_lat;
+#endif
};
struct f2fs_private_dio {
@@ -2034,36 +2072,6 @@ static inline void clear_ckpt_flags(struct f2fs_sb_info *sbi, unsigned int f)
spin_unlock_irqrestore(&sbi->cp_lock, flags);
}
-static inline void disable_nat_bits(struct f2fs_sb_info *sbi, bool lock)
-{
- unsigned long flags;
- unsigned char *nat_bits;
-
- /*
- * In order to re-enable nat_bits we need to call fsck.f2fs by
- * set_sbi_flag(sbi, SBI_NEED_FSCK). But it may give huge cost,
- * so let's rely on regular fsck or unclean shutdown.
- */
-
- if (lock)
- spin_lock_irqsave(&sbi->cp_lock, flags);
- __clear_ckpt_flags(F2FS_CKPT(sbi), CP_NAT_BITS_FLAG);
- nat_bits = NM_I(sbi)->nat_bits;
- NM_I(sbi)->nat_bits = NULL;
- if (lock)
- spin_unlock_irqrestore(&sbi->cp_lock, flags);
-
- kvfree(nat_bits);
-}
-
-static inline bool enabled_nat_bits(struct f2fs_sb_info *sbi,
- struct cp_control *cpc)
-{
- bool set = is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
-
- return (cpc) ? (cpc->reason & CP_UMOUNT) && set : set;
-}
-
static inline void f2fs_lock_op(struct f2fs_sb_info *sbi)
{
down_read(&sbi->cp_rwsem);
@@ -2587,7 +2595,7 @@ static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name,
return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, NULL);
}
-static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep,
+static inline void *f2fs_kmem_cache_alloc_nofail(struct kmem_cache *cachep,
gfp_t flags)
{
void *entry;
@@ -2598,6 +2606,20 @@ static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep,
return entry;
}
+static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep,
+ gfp_t flags, bool nofail, struct f2fs_sb_info *sbi)
+{
+ if (nofail)
+ return f2fs_kmem_cache_alloc_nofail(cachep, flags);
+
+ if (time_to_inject(sbi, FAULT_SLAB_ALLOC)) {
+ f2fs_show_injection_info(sbi, FAULT_SLAB_ALLOC);
+ return NULL;
+ }
+
+ return kmem_cache_alloc(cachep, flags);
+}
+
static inline bool is_inflight_io(struct f2fs_sb_info *sbi, int type)
{
if (get_pages(sbi, F2FS_RD_DATA) || get_pages(sbi, F2FS_RD_NODE) ||
@@ -3210,47 +3232,6 @@ static inline int get_inline_xattr_addrs(struct inode *inode)
sizeof((f2fs_inode)->field)) \
<= (F2FS_OLD_ATTRIBUTE_SIZE + (extra_isize))) \
-#define DEFAULT_IOSTAT_PERIOD_MS 3000
-#define MIN_IOSTAT_PERIOD_MS 100
-/* maximum period of iostat tracing is 1 day */
-#define MAX_IOSTAT_PERIOD_MS 8640000
-
-static inline void f2fs_reset_iostat(struct f2fs_sb_info *sbi)
-{
- int i;
-
- spin_lock(&sbi->iostat_lock);
- for (i = 0; i < NR_IO_TYPE; i++) {
- sbi->rw_iostat[i] = 0;
- sbi->prev_rw_iostat[i] = 0;
- }
- spin_unlock(&sbi->iostat_lock);
-}
-
-extern void f2fs_record_iostat(struct f2fs_sb_info *sbi);
-
-static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
- enum iostat_type type, unsigned long long io_bytes)
-{
- if (!sbi->iostat_enable)
- return;
- spin_lock(&sbi->iostat_lock);
- sbi->rw_iostat[type] += io_bytes;
-
- if (type == APP_WRITE_IO || type == APP_DIRECT_IO)
- sbi->rw_iostat[APP_BUFFERED_IO] =
- sbi->rw_iostat[APP_WRITE_IO] -
- sbi->rw_iostat[APP_DIRECT_IO];
-
- if (type == APP_READ_IO || type == APP_DIRECT_READ_IO)
- sbi->rw_iostat[APP_BUFFERED_READ_IO] =
- sbi->rw_iostat[APP_READ_IO] -
- sbi->rw_iostat[APP_DIRECT_READ_IO];
- spin_unlock(&sbi->iostat_lock);
-
- f2fs_record_iostat(sbi);
-}
-
#define __is_large_section(sbi) ((sbi)->segs_per_sec > 1)
#define __is_meta_io(fio) (PAGE_TYPE_OF_BIO((fio)->type) == META)
@@ -3417,6 +3398,7 @@ 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,
unsigned int seq_id);
+bool f2fs_nat_bitmap_enabled(struct f2fs_sb_info *sbi);
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);
@@ -3441,6 +3423,7 @@ int f2fs_recover_xattr_data(struct inode *inode, struct page *page);
int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page);
int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
unsigned int segno, struct f2fs_summary_block *sum);
+void f2fs_enable_nat_bits(struct f2fs_sb_info *sbi);
int 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);
@@ -3464,6 +3447,7 @@ int f2fs_flush_device_cache(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);
+int f2fs_start_discard_thread(struct f2fs_sb_info *sbi);
void f2fs_drop_discard_cmd(struct f2fs_sb_info *sbi);
void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi);
bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi);
@@ -3986,6 +3970,9 @@ void f2fs_destroy_extent_cache(void);
/*
* sysfs.c
*/
+#define MIN_RA_MUL 2
+#define MAX_RA_MUL 256
+
int __init f2fs_init_sysfs(void);
void f2fs_exit_sysfs(void);
int f2fs_register_sysfs(struct f2fs_sb_info *sbi);
@@ -4040,18 +4027,23 @@ void f2fs_end_read_compressed_page(struct page *page, bool failed,
block_t blkaddr);
bool f2fs_cluster_is_empty(struct compress_ctx *cc);
bool f2fs_cluster_can_merge_page(struct compress_ctx *cc, pgoff_t index);
+bool f2fs_sanity_check_cluster(struct dnode_of_data *dn);
void f2fs_compress_ctx_add_page(struct compress_ctx *cc, struct page *page);
int f2fs_write_multi_pages(struct compress_ctx *cc,
int *submitted,
struct writeback_control *wbc,
enum iostat_type io_type);
int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index);
+void f2fs_update_extent_tree_range_compressed(struct inode *inode,
+ pgoff_t fofs, block_t blkaddr, unsigned int llen,
+ unsigned int c_len);
int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
unsigned nr_pages, sector_t *last_block_in_bio,
bool is_readahead, bool for_write);
struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc);
void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed);
void f2fs_put_page_dic(struct page *page);
+unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn);
int f2fs_init_compress_ctx(struct compress_ctx *cc);
void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse);
void f2fs_init_compress_info(struct f2fs_sb_info *sbi);
@@ -4106,6 +4098,8 @@ static inline void f2fs_put_page_dic(struct page *page)
{
WARN_ON_ONCE(1);
}
+static inline unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn) { return 0; }
+static inline bool f2fs_sanity_check_cluster(struct dnode_of_data *dn) { return false; }
static inline int f2fs_init_compress_inode(struct f2fs_sb_info *sbi) { return 0; }
static inline void f2fs_destroy_compress_inode(struct f2fs_sb_info *sbi) { }
static inline int f2fs_init_page_array_cache(struct f2fs_sb_info *sbi) { return 0; }
@@ -4121,6 +4115,9 @@ static inline bool f2fs_load_compressed_page(struct f2fs_sb_info *sbi,
static inline void f2fs_invalidate_compress_pages(struct f2fs_sb_info *sbi,
nid_t ino) { }
#define inc_compr_inode_stat(inode) do { } while (0)
+static inline void f2fs_update_extent_tree_range_compressed(struct inode *inode,
+ pgoff_t fofs, block_t blkaddr, unsigned int llen,
+ unsigned int c_len) { }
#endif
static inline void set_compress_context(struct inode *inode)
@@ -4136,7 +4133,8 @@ static inline void set_compress_context(struct inode *inode)
1 << COMPRESS_CHKSUM : 0;
F2FS_I(inode)->i_cluster_size =
1 << F2FS_I(inode)->i_log_cluster_size;
- if (F2FS_I(inode)->i_compress_algorithm == COMPRESS_LZ4 &&
+ if ((F2FS_I(inode)->i_compress_algorithm == COMPRESS_LZ4 ||
+ F2FS_I(inode)->i_compress_algorithm == COMPRESS_ZSTD) &&
F2FS_OPTION(sbi).compress_level)
F2FS_I(inode)->i_compress_flag |=
F2FS_OPTION(sbi).compress_level <<
@@ -4304,16 +4302,6 @@ static inline int block_unaligned_IO(struct inode *inode,
return align & blocksize_mask;
}
-static inline int allow_outplace_dio(struct inode *inode,
- struct kiocb *iocb, struct iov_iter *iter)
-{
- struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
- int rw = iov_iter_rw(iter);
-
- return (f2fs_lfs_mode(sbi) && (rw == WRITE) &&
- !block_unaligned_IO(inode, iocb, iter));
-}
-
static inline bool f2fs_force_buffered_io(struct inode *inode,
struct kiocb *iocb, struct iov_iter *iter)
{
@@ -4368,6 +4356,11 @@ static inline bool is_journalled_quota(struct f2fs_sb_info *sbi)
return false;
}
+static inline bool f2fs_block_unit_discard(struct f2fs_sb_info *sbi)
+{
+ return F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_BLOCK;
+}
+
#define EFSBADCRC EBADMSG /* Bad CRC detected */
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 1ff333755721..9c8ef33bd8d3 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -23,6 +23,7 @@
#include <linux/nls.h>
#include <linux/sched/signal.h>
#include <linux/fileattr.h>
+#include <linux/fadvise.h>
#include "f2fs.h"
#include "node.h"
@@ -30,6 +31,7 @@
#include "xattr.h"
#include "acl.h"
#include "gc.h"
+#include "iostat.h"
#include <trace/events/f2fs.h>
#include <uapi/linux/f2fs.h>
@@ -258,8 +260,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
};
unsigned int seq_id = 0;
- if (unlikely(f2fs_readonly(inode->i_sb) ||
- is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
+ if (unlikely(f2fs_readonly(inode->i_sb)))
return 0;
trace_f2fs_sync_file_enter(inode);
@@ -273,7 +274,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
ret = file_write_and_wait_range(file, start, end);
clear_inode_flag(inode, FI_NEED_IPU);
- if (ret) {
+ if (ret || is_sbi_flag_set(sbi, SBI_CP_DISABLED)) {
trace_f2fs_sync_file_exit(inode, cp_reason, datasync, ret);
return ret;
}
@@ -298,6 +299,18 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
f2fs_exist_written_data(sbi, ino, UPDATE_INO))
goto flush_out;
goto out;
+ } else {
+ /*
+ * for OPU case, during fsync(), node can be persisted before
+ * data when lower device doesn't support write barrier, result
+ * in data corruption after SPO.
+ * So for strict fsync mode, force to use atomic write sematics
+ * to keep write order in between data/node and last node to
+ * avoid potential data corruption.
+ */
+ if (F2FS_OPTION(sbi).fsync_mode ==
+ FSYNC_MODE_STRICT && !atomic)
+ atomic = true;
}
go_write:
/*
@@ -737,6 +750,14 @@ int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock)
return err;
#ifdef CONFIG_F2FS_FS_COMPRESSION
+ /*
+ * For compressed file, after release compress blocks, don't allow write
+ * direct, but we should allow write direct after truncate to zero.
+ */
+ if (f2fs_compressed_file(inode) && !free_from
+ && is_inode_flag_set(inode, FI_COMPRESS_RELEASED))
+ clear_inode_flag(inode, FI_COMPRESS_RELEASED);
+
if (from != free_from) {
err = f2fs_truncate_partial_cluster(inode, from, lock);
if (err)
@@ -1082,7 +1103,6 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
}
if (pg_start < pg_end) {
- struct address_space *mapping = inode->i_mapping;
loff_t blk_start, blk_end;
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
@@ -1092,16 +1112,15 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
blk_end = (loff_t)pg_end << PAGE_SHIFT;
down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
- filemap_invalidate_lock(mapping);
+ filemap_invalidate_lock(inode->i_mapping);
- truncate_inode_pages_range(mapping, blk_start,
- blk_end - 1);
+ truncate_pagecache_range(inode, blk_start, blk_end - 1);
f2fs_lock_op(sbi);
ret = f2fs_truncate_hole(inode, pg_start, pg_end);
f2fs_unlock_op(sbi);
- filemap_invalidate_unlock(mapping);
+ filemap_invalidate_unlock(inode->i_mapping);
up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
}
}
@@ -3473,8 +3492,8 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
released_blocks += ret;
}
- up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
filemap_invalidate_unlock(inode->i_mapping);
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
out:
inode_unlock(inode);
@@ -3626,8 +3645,8 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
reserved_blocks += ret;
}
- up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
filemap_invalidate_unlock(inode->i_mapping);
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
if (ret >= 0) {
clear_inode_flag(inode, FI_COMPRESS_RELEASED);
@@ -4290,7 +4309,7 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
* back to buffered IO.
*/
if (!f2fs_force_buffered_io(inode, iocb, from) &&
- allow_outplace_dio(inode, iocb, from))
+ f2fs_lfs_mode(F2FS_I_SB(inode)))
goto write;
}
preallocated = true;
@@ -4330,6 +4349,34 @@ out:
return ret;
}
+static int f2fs_file_fadvise(struct file *filp, loff_t offset, loff_t len,
+ int advice)
+{
+ struct inode *inode;
+ struct address_space *mapping;
+ struct backing_dev_info *bdi;
+
+ if (advice == POSIX_FADV_SEQUENTIAL) {
+ inode = file_inode(filp);
+ if (S_ISFIFO(inode->i_mode))
+ return -ESPIPE;
+
+ mapping = filp->f_mapping;
+ if (!mapping || len < 0)
+ return -EINVAL;
+
+ bdi = inode_to_bdi(mapping->host);
+ filp->f_ra.ra_pages = bdi->ra_pages *
+ F2FS_I_SB(inode)->seq_file_ra_mul;
+ spin_lock(&filp->f_lock);
+ filp->f_mode &= ~FMODE_RANDOM;
+ spin_unlock(&filp->f_lock);
+ return 0;
+ }
+
+ return generic_fadvise(filp, offset, len, advice);
+}
+
#ifdef CONFIG_COMPAT
struct compat_f2fs_gc_range {
u32 sync;
@@ -4458,4 +4505,5 @@ const struct file_operations f2fs_file_operations = {
#endif
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
+ .fadvise = f2fs_file_fadvise,
};
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 0e42ee5f7770..77391e3b7d68 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -19,6 +19,7 @@
#include "node.h"
#include "segment.h"
#include "gc.h"
+#include "iostat.h"
#include <trace/events/f2fs.h>
static struct kmem_cache *victim_entry_slab;
@@ -371,7 +372,8 @@ static struct victim_entry *attach_victim_entry(struct f2fs_sb_info *sbi,
struct atgc_management *am = &sbi->am;
struct victim_entry *ve;
- ve = f2fs_kmem_cache_alloc(victim_entry_slab, GFP_NOFS);
+ ve = f2fs_kmem_cache_alloc(victim_entry_slab,
+ GFP_NOFS, true, NULL);
ve->mtime = mtime;
ve->segno = segno;
@@ -849,7 +851,8 @@ static void add_gc_inode(struct gc_inode_list *gc_list, struct inode *inode)
iput(inode);
return;
}
- new_ie = f2fs_kmem_cache_alloc(f2fs_inode_entry_slab, GFP_NOFS);
+ new_ie = f2fs_kmem_cache_alloc(f2fs_inode_entry_slab,
+ GFP_NOFS, true, NULL);
new_ie->inode = inode;
f2fs_radix_tree_insert(&gc_list->iroot, inode->i_ino, new_ie);
@@ -1497,8 +1500,10 @@ next_step:
int err;
if (S_ISREG(inode->i_mode)) {
- if (!down_write_trylock(&fi->i_gc_rwsem[READ]))
+ if (!down_write_trylock(&fi->i_gc_rwsem[READ])) {
+ sbi->skipped_gc_rwsem++;
continue;
+ }
if (!down_write_trylock(
&fi->i_gc_rwsem[WRITE])) {
sbi->skipped_gc_rwsem++;
@@ -1646,6 +1651,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
force_migrate);
stat_inc_seg_count(sbi, type, gc_type);
+ sbi->gc_reclaimed_segs[sbi->gc_mode]++;
migrated++;
freed:
@@ -1747,7 +1753,7 @@ gc_more:
round++;
}
- if (gc_type == FG_GC && seg_freed)
+ if (gc_type == FG_GC)
sbi->cur_victim_sec = NULL_SEGNO;
if (sync)
diff --git a/fs/f2fs/iostat.c b/fs/f2fs/iostat.c
new file mode 100644
index 000000000000..cdcf54ae0db8
--- /dev/null
+++ b/fs/f2fs/iostat.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * f2fs iostat support
+ *
+ * Copyright 2021 Google LLC
+ * Author: Daeho Jeong <daehojeong@google.com>
+ */
+
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/seq_file.h>
+
+#include "f2fs.h"
+#include "iostat.h"
+#include <trace/events/f2fs.h>
+
+#define NUM_PREALLOC_IOSTAT_CTXS 128
+static struct kmem_cache *bio_iostat_ctx_cache;
+static mempool_t *bio_iostat_ctx_pool;
+
+int __maybe_unused iostat_info_seq_show(struct seq_file *seq, void *offset)
+{
+ struct super_block *sb = seq->private;
+ struct f2fs_sb_info *sbi = F2FS_SB(sb);
+ time64_t now = ktime_get_real_seconds();
+
+ if (!sbi->iostat_enable)
+ return 0;
+
+ seq_printf(seq, "time: %-16llu\n", now);
+
+ /* print app write IOs */
+ seq_puts(seq, "[WRITE]\n");
+ seq_printf(seq, "app buffered: %-16llu\n",
+ sbi->rw_iostat[APP_BUFFERED_IO]);
+ seq_printf(seq, "app direct: %-16llu\n",
+ sbi->rw_iostat[APP_DIRECT_IO]);
+ seq_printf(seq, "app mapped: %-16llu\n",
+ sbi->rw_iostat[APP_MAPPED_IO]);
+
+ /* print fs write IOs */
+ seq_printf(seq, "fs data: %-16llu\n",
+ sbi->rw_iostat[FS_DATA_IO]);
+ seq_printf(seq, "fs node: %-16llu\n",
+ sbi->rw_iostat[FS_NODE_IO]);
+ seq_printf(seq, "fs meta: %-16llu\n",
+ sbi->rw_iostat[FS_META_IO]);
+ seq_printf(seq, "fs gc data: %-16llu\n",
+ sbi->rw_iostat[FS_GC_DATA_IO]);
+ seq_printf(seq, "fs gc node: %-16llu\n",
+ sbi->rw_iostat[FS_GC_NODE_IO]);
+ seq_printf(seq, "fs cp data: %-16llu\n",
+ sbi->rw_iostat[FS_CP_DATA_IO]);
+ seq_printf(seq, "fs cp node: %-16llu\n",
+ sbi->rw_iostat[FS_CP_NODE_IO]);
+ seq_printf(seq, "fs cp meta: %-16llu\n",
+ sbi->rw_iostat[FS_CP_META_IO]);
+
+ /* print app read IOs */
+ seq_puts(seq, "[READ]\n");
+ seq_printf(seq, "app buffered: %-16llu\n",
+ sbi->rw_iostat[APP_BUFFERED_READ_IO]);
+ seq_printf(seq, "app direct: %-16llu\n",
+ sbi->rw_iostat[APP_DIRECT_READ_IO]);
+ seq_printf(seq, "app mapped: %-16llu\n",
+ sbi->rw_iostat[APP_MAPPED_READ_IO]);
+
+ /* print fs read IOs */
+ seq_printf(seq, "fs data: %-16llu\n",
+ sbi->rw_iostat[FS_DATA_READ_IO]);
+ seq_printf(seq, "fs gc data: %-16llu\n",
+ sbi->rw_iostat[FS_GDATA_READ_IO]);
+ seq_printf(seq, "fs compr_data: %-16llu\n",
+ sbi->rw_iostat[FS_CDATA_READ_IO]);
+ seq_printf(seq, "fs node: %-16llu\n",
+ sbi->rw_iostat[FS_NODE_READ_IO]);
+ seq_printf(seq, "fs meta: %-16llu\n",
+ sbi->rw_iostat[FS_META_READ_IO]);
+
+ /* print other IOs */
+ seq_puts(seq, "[OTHER]\n");
+ seq_printf(seq, "fs discard: %-16llu\n",
+ sbi->rw_iostat[FS_DISCARD]);
+
+ return 0;
+}
+
+static inline void __record_iostat_latency(struct f2fs_sb_info *sbi)
+{
+ int io, idx = 0;
+ unsigned int cnt;
+ struct f2fs_iostat_latency iostat_lat[MAX_IO_TYPE][NR_PAGE_TYPE];
+ struct iostat_lat_info *io_lat = sbi->iostat_io_lat;
+
+ spin_lock_irq(&sbi->iostat_lat_lock);
+ for (idx = 0; idx < MAX_IO_TYPE; idx++) {
+ for (io = 0; io < NR_PAGE_TYPE; io++) {
+ cnt = io_lat->bio_cnt[idx][io];
+ iostat_lat[idx][io].peak_lat =
+ jiffies_to_msecs(io_lat->peak_lat[idx][io]);
+ iostat_lat[idx][io].cnt = cnt;
+ iostat_lat[idx][io].avg_lat = cnt ?
+ jiffies_to_msecs(io_lat->sum_lat[idx][io]) / cnt : 0;
+ io_lat->sum_lat[idx][io] = 0;
+ io_lat->peak_lat[idx][io] = 0;
+ io_lat->bio_cnt[idx][io] = 0;
+ }
+ }
+ spin_unlock_irq(&sbi->iostat_lat_lock);
+
+ trace_f2fs_iostat_latency(sbi, iostat_lat);
+}
+
+static inline void f2fs_record_iostat(struct f2fs_sb_info *sbi)
+{
+ unsigned long long iostat_diff[NR_IO_TYPE];
+ int i;
+
+ if (time_is_after_jiffies(sbi->iostat_next_period))
+ return;
+
+ /* Need double check under the lock */
+ spin_lock(&sbi->iostat_lock);
+ if (time_is_after_jiffies(sbi->iostat_next_period)) {
+ spin_unlock(&sbi->iostat_lock);
+ return;
+ }
+ sbi->iostat_next_period = jiffies +
+ msecs_to_jiffies(sbi->iostat_period_ms);
+
+ for (i = 0; i < NR_IO_TYPE; i++) {
+ iostat_diff[i] = sbi->rw_iostat[i] -
+ sbi->prev_rw_iostat[i];
+ sbi->prev_rw_iostat[i] = sbi->rw_iostat[i];
+ }
+ spin_unlock(&sbi->iostat_lock);
+
+ trace_f2fs_iostat(sbi, iostat_diff);
+
+ __record_iostat_latency(sbi);
+}
+
+void f2fs_reset_iostat(struct f2fs_sb_info *sbi)
+{
+ struct iostat_lat_info *io_lat = sbi->iostat_io_lat;
+ int i;
+
+ spin_lock(&sbi->iostat_lock);
+ for (i = 0; i < NR_IO_TYPE; i++) {
+ sbi->rw_iostat[i] = 0;
+ sbi->prev_rw_iostat[i] = 0;
+ }
+ spin_unlock(&sbi->iostat_lock);
+
+ spin_lock_irq(&sbi->iostat_lat_lock);
+ memset(io_lat, 0, sizeof(struct iostat_lat_info));
+ spin_unlock_irq(&sbi->iostat_lat_lock);
+}
+
+void f2fs_update_iostat(struct f2fs_sb_info *sbi,
+ enum iostat_type type, unsigned long long io_bytes)
+{
+ if (!sbi->iostat_enable)
+ return;
+
+ spin_lock(&sbi->iostat_lock);
+ sbi->rw_iostat[type] += io_bytes;
+
+ if (type == APP_WRITE_IO || type == APP_DIRECT_IO)
+ sbi->rw_iostat[APP_BUFFERED_IO] =
+ sbi->rw_iostat[APP_WRITE_IO] -
+ sbi->rw_iostat[APP_DIRECT_IO];
+
+ if (type == APP_READ_IO || type == APP_DIRECT_READ_IO)
+ sbi->rw_iostat[APP_BUFFERED_READ_IO] =
+ sbi->rw_iostat[APP_READ_IO] -
+ sbi->rw_iostat[APP_DIRECT_READ_IO];
+ spin_unlock(&sbi->iostat_lock);
+
+ f2fs_record_iostat(sbi);
+}
+
+static inline void __update_iostat_latency(struct bio_iostat_ctx *iostat_ctx,
+ int rw, bool is_sync)
+{
+ unsigned long ts_diff;
+ unsigned int iotype = iostat_ctx->type;
+ unsigned long flags;
+ struct f2fs_sb_info *sbi = iostat_ctx->sbi;
+ struct iostat_lat_info *io_lat = sbi->iostat_io_lat;
+ int idx;
+
+ if (!sbi->iostat_enable)
+ return;
+
+ ts_diff = jiffies - iostat_ctx->submit_ts;
+ if (iotype >= META_FLUSH)
+ iotype = META;
+
+ if (rw == 0) {
+ idx = READ_IO;
+ } else {
+ if (is_sync)
+ idx = WRITE_SYNC_IO;
+ else
+ idx = WRITE_ASYNC_IO;
+ }
+
+ spin_lock_irqsave(&sbi->iostat_lat_lock, flags);
+ io_lat->sum_lat[idx][iotype] += ts_diff;
+ io_lat->bio_cnt[idx][iotype]++;
+ if (ts_diff > io_lat->peak_lat[idx][iotype])
+ io_lat->peak_lat[idx][iotype] = ts_diff;
+ spin_unlock_irqrestore(&sbi->iostat_lat_lock, flags);
+}
+
+void iostat_update_and_unbind_ctx(struct bio *bio, int rw)
+{
+ struct bio_iostat_ctx *iostat_ctx = bio->bi_private;
+ bool is_sync = bio->bi_opf & REQ_SYNC;
+
+ if (rw == 0)
+ bio->bi_private = iostat_ctx->post_read_ctx;
+ else
+ bio->bi_private = iostat_ctx->sbi;
+ __update_iostat_latency(iostat_ctx, rw, is_sync);
+ mempool_free(iostat_ctx, bio_iostat_ctx_pool);
+}
+
+void iostat_alloc_and_bind_ctx(struct f2fs_sb_info *sbi,
+ struct bio *bio, struct bio_post_read_ctx *ctx)
+{
+ struct bio_iostat_ctx *iostat_ctx;
+ /* Due to the mempool, this never fails. */
+ iostat_ctx = mempool_alloc(bio_iostat_ctx_pool, GFP_NOFS);
+ iostat_ctx->sbi = sbi;
+ iostat_ctx->submit_ts = 0;
+ iostat_ctx->type = 0;
+ iostat_ctx->post_read_ctx = ctx;
+ bio->bi_private = iostat_ctx;
+}
+
+int __init f2fs_init_iostat_processing(void)
+{
+ bio_iostat_ctx_cache =
+ kmem_cache_create("f2fs_bio_iostat_ctx",
+ sizeof(struct bio_iostat_ctx), 0, 0, NULL);
+ if (!bio_iostat_ctx_cache)
+ goto fail;
+ bio_iostat_ctx_pool =
+ mempool_create_slab_pool(NUM_PREALLOC_IOSTAT_CTXS,
+ bio_iostat_ctx_cache);
+ if (!bio_iostat_ctx_pool)
+ goto fail_free_cache;
+ return 0;
+
+fail_free_cache:
+ kmem_cache_destroy(bio_iostat_ctx_cache);
+fail:
+ return -ENOMEM;
+}
+
+void f2fs_destroy_iostat_processing(void)
+{
+ mempool_destroy(bio_iostat_ctx_pool);
+ kmem_cache_destroy(bio_iostat_ctx_cache);
+}
+
+int f2fs_init_iostat(struct f2fs_sb_info *sbi)
+{
+ /* init iostat info */
+ spin_lock_init(&sbi->iostat_lock);
+ spin_lock_init(&sbi->iostat_lat_lock);
+ sbi->iostat_enable = false;
+ sbi->iostat_period_ms = DEFAULT_IOSTAT_PERIOD_MS;
+ sbi->iostat_io_lat = f2fs_kzalloc(sbi, sizeof(struct iostat_lat_info),
+ GFP_KERNEL);
+ if (!sbi->iostat_io_lat)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void f2fs_destroy_iostat(struct f2fs_sb_info *sbi)
+{
+ kfree(sbi->iostat_io_lat);
+}
diff --git a/fs/f2fs/iostat.h b/fs/f2fs/iostat.h
new file mode 100644
index 000000000000..22a2d01f57ef
--- /dev/null
+++ b/fs/f2fs/iostat.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2021 Google LLC
+ * Author: Daeho Jeong <daehojeong@google.com>
+ */
+#ifndef __F2FS_IOSTAT_H__
+#define __F2FS_IOSTAT_H__
+
+struct bio_post_read_ctx;
+
+#ifdef CONFIG_F2FS_IOSTAT
+
+#define DEFAULT_IOSTAT_PERIOD_MS 3000
+#define MIN_IOSTAT_PERIOD_MS 100
+/* maximum period of iostat tracing is 1 day */
+#define MAX_IOSTAT_PERIOD_MS 8640000
+
+enum {
+ READ_IO,
+ WRITE_SYNC_IO,
+ WRITE_ASYNC_IO,
+ MAX_IO_TYPE,
+};
+
+struct iostat_lat_info {
+ unsigned long sum_lat[MAX_IO_TYPE][NR_PAGE_TYPE]; /* sum of io latencies */
+ unsigned long peak_lat[MAX_IO_TYPE][NR_PAGE_TYPE]; /* peak io latency */
+ unsigned int bio_cnt[MAX_IO_TYPE][NR_PAGE_TYPE]; /* bio count */
+};
+
+extern int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
+ void *offset);
+extern void f2fs_reset_iostat(struct f2fs_sb_info *sbi);
+extern void f2fs_update_iostat(struct f2fs_sb_info *sbi,
+ enum iostat_type type, unsigned long long io_bytes);
+
+struct bio_iostat_ctx {
+ struct f2fs_sb_info *sbi;
+ unsigned long submit_ts;
+ enum page_type type;
+ struct bio_post_read_ctx *post_read_ctx;
+};
+
+static inline void iostat_update_submit_ctx(struct bio *bio,
+ enum page_type type)
+{
+ struct bio_iostat_ctx *iostat_ctx = bio->bi_private;
+
+ iostat_ctx->submit_ts = jiffies;
+ iostat_ctx->type = type;
+}
+
+static inline struct bio_post_read_ctx *get_post_read_ctx(struct bio *bio)
+{
+ struct bio_iostat_ctx *iostat_ctx = bio->bi_private;
+
+ return iostat_ctx->post_read_ctx;
+}
+
+extern void iostat_update_and_unbind_ctx(struct bio *bio, int rw);
+extern void iostat_alloc_and_bind_ctx(struct f2fs_sb_info *sbi,
+ struct bio *bio, struct bio_post_read_ctx *ctx);
+extern int f2fs_init_iostat_processing(void);
+extern void f2fs_destroy_iostat_processing(void);
+extern int f2fs_init_iostat(struct f2fs_sb_info *sbi);
+extern void f2fs_destroy_iostat(struct f2fs_sb_info *sbi);
+#else
+static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
+ enum iostat_type type, unsigned long long io_bytes) {}
+static inline void iostat_update_and_unbind_ctx(struct bio *bio, int rw) {}
+static inline void iostat_alloc_and_bind_ctx(struct f2fs_sb_info *sbi,
+ struct bio *bio, struct bio_post_read_ctx *ctx) {}
+static inline void iostat_update_submit_ctx(struct bio *bio,
+ enum page_type type) {}
+static inline struct bio_post_read_ctx *get_post_read_ctx(struct bio *bio)
+{
+ return bio->bi_private;
+}
+static inline int f2fs_init_iostat_processing(void) { return 0; }
+static inline void f2fs_destroy_iostat_processing(void) {}
+static inline int f2fs_init_iostat(struct f2fs_sb_info *sbi) { return 0; }
+static inline void f2fs_destroy_iostat(struct f2fs_sb_info *sbi) {}
+#endif
+#endif /* __F2FS_IOSTAT_H__ */
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 0be9e2d7120e..e863136081b4 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -17,6 +17,7 @@
#include "node.h"
#include "segment.h"
#include "xattr.h"
+#include "iostat.h"
#include <trace/events/f2fs.h>
#define on_f2fs_build_free_nids(nmi) mutex_is_locked(&(nm_i)->build_lock)
@@ -162,14 +163,13 @@ static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
return dst_page;
}
-static struct nat_entry *__alloc_nat_entry(nid_t nid, bool no_fail)
+static struct nat_entry *__alloc_nat_entry(struct f2fs_sb_info *sbi,
+ nid_t nid, bool no_fail)
{
struct nat_entry *new;
- if (no_fail)
- new = f2fs_kmem_cache_alloc(nat_entry_slab, GFP_F2FS_ZERO);
- else
- new = kmem_cache_alloc(nat_entry_slab, GFP_F2FS_ZERO);
+ new = f2fs_kmem_cache_alloc(nat_entry_slab,
+ GFP_F2FS_ZERO, no_fail, sbi);
if (new) {
nat_set_nid(new, nid);
nat_reset_flag(new);
@@ -242,7 +242,8 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
head = radix_tree_lookup(&nm_i->nat_set_root, set);
if (!head) {
- head = f2fs_kmem_cache_alloc(nat_entry_set_slab, GFP_NOFS);
+ head = f2fs_kmem_cache_alloc(nat_entry_set_slab,
+ GFP_NOFS, true, NULL);
INIT_LIST_HEAD(&head->entry_list);
INIT_LIST_HEAD(&head->set_list);
@@ -329,7 +330,8 @@ static unsigned int f2fs_add_fsync_node_entry(struct f2fs_sb_info *sbi,
unsigned long flags;
unsigned int seq_id;
- fn = f2fs_kmem_cache_alloc(fsync_node_entry_slab, GFP_NOFS);
+ fn = f2fs_kmem_cache_alloc(fsync_node_entry_slab,
+ GFP_NOFS, true, NULL);
get_page(page);
fn->page = page;
@@ -428,7 +430,7 @@ static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct nat_entry *new, *e;
- new = __alloc_nat_entry(nid, false);
+ new = __alloc_nat_entry(sbi, nid, false);
if (!new)
return;
@@ -451,7 +453,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct nat_entry *e;
- struct nat_entry *new = __alloc_nat_entry(ni->nid, true);
+ struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true);
down_write(&nm_i->nat_tree_lock);
e = __lookup_nat_cache(nm_i, ni->nid);
@@ -552,7 +554,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
int i;
ni->nid = nid;
-
+retry:
/* Check nat cache */
down_read(&nm_i->nat_tree_lock);
e = __lookup_nat_cache(nm_i, nid);
@@ -564,10 +566,19 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
return 0;
}
- memset(&ne, 0, sizeof(struct f2fs_nat_entry));
+ /*
+ * Check current segment summary by trying to grab journal_rwsem first.
+ * This sem is on the critical path on the checkpoint requiring the above
+ * nat_tree_lock. Therefore, we should retry, if we failed to grab here
+ * while not bothering checkpoint.
+ */
+ if (!rwsem_is_locked(&sbi->cp_global_sem)) {
+ down_read(&curseg->journal_rwsem);
+ } else if (!down_read_trylock(&curseg->journal_rwsem)) {
+ up_read(&nm_i->nat_tree_lock);
+ goto retry;
+ }
- /* Check current segment summary */
- down_read(&curseg->journal_rwsem);
i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
if (i >= 0) {
ne = nat_in_journal(journal, i);
@@ -832,6 +843,26 @@ int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
dn->ofs_in_node = offset[level];
dn->node_page = npage[level];
dn->data_blkaddr = f2fs_data_blkaddr(dn);
+
+ if (is_inode_flag_set(dn->inode, FI_COMPRESSED_FILE) &&
+ f2fs_sb_has_readonly(sbi)) {
+ unsigned int c_len = f2fs_cluster_blocks_are_contiguous(dn);
+ block_t blkaddr;
+
+ if (!c_len)
+ goto out;
+
+ blkaddr = f2fs_data_blkaddr(dn);
+ if (blkaddr == COMPRESS_ADDR)
+ blkaddr = data_blkaddr(dn->inode, dn->node_page,
+ dn->ofs_in_node + 1);
+
+ f2fs_update_extent_tree_range_compressed(dn->inode,
+ index, blkaddr,
+ F2FS_I(dn->inode)->i_cluster_size,
+ c_len);
+ }
+out:
return 0;
release_pages:
@@ -1321,7 +1352,8 @@ static int read_node_page(struct page *page, int op_flags)
if (err)
return err;
- if (unlikely(ni.blk_addr == NULL_ADDR) ||
+ /* NEW_ADDR can be seen, after cp_error drops some dirty node pages */
+ if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR) ||
is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) {
ClearPageUptodate(page);
return -ENOENT;
@@ -2181,6 +2213,24 @@ static void __move_free_nid(struct f2fs_sb_info *sbi, struct free_nid *i,
}
}
+bool f2fs_nat_bitmap_enabled(struct f2fs_sb_info *sbi)
+{
+ struct f2fs_nm_info *nm_i = NM_I(sbi);
+ unsigned int i;
+ bool ret = true;
+
+ down_read(&nm_i->nat_tree_lock);
+ for (i = 0; i < nm_i->nat_blocks; i++) {
+ if (!test_bit_le(i, nm_i->nat_block_bitmap)) {
+ ret = false;
+ break;
+ }
+ }
+ up_read(&nm_i->nat_tree_lock);
+
+ return ret;
+}
+
static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid,
bool set, bool build)
{
@@ -2222,7 +2272,7 @@ static bool add_free_nid(struct f2fs_sb_info *sbi,
if (unlikely(f2fs_check_nid_range(sbi, nid)))
return false;
- i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS);
+ i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS, true, NULL);
i->nid = nid;
i->state = FREE_NID;
@@ -2812,7 +2862,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
ne = __lookup_nat_cache(nm_i, nid);
if (!ne) {
- ne = __alloc_nat_entry(nid, true);
+ ne = __alloc_nat_entry(sbi, nid, true);
__init_nat_entry(nm_i, ne, &raw_ne, true);
}
@@ -2852,7 +2902,23 @@ add_out:
list_add_tail(&nes->set_list, head);
}
-static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
+static void __update_nat_bits(struct f2fs_nm_info *nm_i, unsigned int nat_ofs,
+ unsigned int valid)
+{
+ if (valid == 0) {
+ __set_bit_le(nat_ofs, nm_i->empty_nat_bits);
+ __clear_bit_le(nat_ofs, nm_i->full_nat_bits);
+ return;
+ }
+
+ __clear_bit_le(nat_ofs, nm_i->empty_nat_bits);
+ if (valid == NAT_ENTRY_PER_BLOCK)
+ __set_bit_le(nat_ofs, nm_i->full_nat_bits);
+ else
+ __clear_bit_le(nat_ofs, nm_i->full_nat_bits);
+}
+
+static void update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
struct page *page)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -2861,7 +2927,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
int valid = 0;
int i = 0;
- if (!enabled_nat_bits(sbi, NULL))
+ if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG))
return;
if (nat_index == 0) {
@@ -2872,17 +2938,36 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR)
valid++;
}
- if (valid == 0) {
- __set_bit_le(nat_index, nm_i->empty_nat_bits);
- __clear_bit_le(nat_index, nm_i->full_nat_bits);
- return;
+
+ __update_nat_bits(nm_i, nat_index, valid);
+}
+
+void f2fs_enable_nat_bits(struct f2fs_sb_info *sbi)
+{
+ struct f2fs_nm_info *nm_i = NM_I(sbi);
+ unsigned int nat_ofs;
+
+ down_read(&nm_i->nat_tree_lock);
+
+ for (nat_ofs = 0; nat_ofs < nm_i->nat_blocks; nat_ofs++) {
+ unsigned int valid = 0, nid_ofs = 0;
+
+ /* handle nid zero due to it should never be used */
+ if (unlikely(nat_ofs == 0)) {
+ valid = 1;
+ nid_ofs = 1;
+ }
+
+ for (; nid_ofs < NAT_ENTRY_PER_BLOCK; nid_ofs++) {
+ if (!test_bit_le(nid_ofs,
+ nm_i->free_nid_bitmap[nat_ofs]))
+ valid++;
+ }
+
+ __update_nat_bits(nm_i, nat_ofs, valid);
}
- __clear_bit_le(nat_index, nm_i->empty_nat_bits);
- if (valid == NAT_ENTRY_PER_BLOCK)
- __set_bit_le(nat_index, nm_i->full_nat_bits);
- else
- __clear_bit_le(nat_index, nm_i->full_nat_bits);
+ up_read(&nm_i->nat_tree_lock);
}
static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
@@ -2901,7 +2986,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
* #1, flush nat entries to journal in current hot data summary block.
* #2, flush nat entries to nat page.
*/
- if (enabled_nat_bits(sbi, cpc) ||
+ if ((cpc->reason & CP_UMOUNT) ||
!__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
to_journal = false;
@@ -2948,7 +3033,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
if (to_journal) {
up_write(&curseg->journal_rwsem);
} else {
- __update_nat_bits(sbi, start_nid, page);
+ update_nat_bits(sbi, start_nid, page);
f2fs_put_page(page, 1);
}
@@ -2979,7 +3064,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
* during unmount, let's flush nat_bits before checking
* nat_cnt[DIRTY_NAT].
*/
- if (enabled_nat_bits(sbi, cpc)) {
+ if (cpc->reason & CP_UMOUNT) {
down_write(&nm_i->nat_tree_lock);
remove_nats_in_journal(sbi);
up_write(&nm_i->nat_tree_lock);
@@ -2995,7 +3080,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
* entries, remove all entries from journal and merge them
* into nat entry set.
*/
- if (enabled_nat_bits(sbi, cpc) ||
+ if (cpc->reason & CP_UMOUNT ||
!__has_cursum_space(journal,
nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL))
remove_nats_in_journal(sbi);
@@ -3032,15 +3117,18 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
__u64 cp_ver = cur_cp_version(ckpt);
block_t nat_bits_addr;
- if (!enabled_nat_bits(sbi, NULL))
- return 0;
-
nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
nm_i->nat_bits = f2fs_kvzalloc(sbi,
nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, GFP_KERNEL);
if (!nm_i->nat_bits)
return -ENOMEM;
+ nm_i->full_nat_bits = nm_i->nat_bits + 8;
+ nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes;
+
+ if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG))
+ return 0;
+
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++) {
@@ -3057,13 +3145,12 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
cp_ver |= (cur_cp_crc(ckpt) << 32);
if (cpu_to_le64(cp_ver) != *(__le64 *)nm_i->nat_bits) {
- disable_nat_bits(sbi, true);
+ clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
+ f2fs_notice(sbi, "Disable nat_bits due to incorrect cp_ver (%llu, %llu)",
+ cp_ver, le64_to_cpu(*(__le64 *)nm_i->nat_bits));
return 0;
}
- nm_i->full_nat_bits = nm_i->nat_bits + 8;
- nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes;
-
f2fs_notice(sbi, "Found nat_bits in checkpoint");
return 0;
}
@@ -3074,7 +3161,7 @@ static inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi)
unsigned int i = 0;
nid_t nid, last_nid;
- if (!enabled_nat_bits(sbi, NULL))
+ if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG))
return;
for (i = 0; i < nm_i->nat_blocks; i++) {
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 695eacfe776c..04655511d7f5 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -91,7 +91,8 @@ static struct fsync_inode_entry *add_fsync_inode(struct f2fs_sb_info *sbi,
goto err_out;
}
- entry = f2fs_kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO);
+ entry = f2fs_kmem_cache_alloc(fsync_entry_slab,
+ GFP_F2FS_ZERO, true, NULL);
entry->inode = inode;
list_add_tail(&entry->list, head);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 15cc89eef28d..a135d2247415 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -20,6 +20,7 @@
#include "segment.h"
#include "node.h"
#include "gc.h"
+#include "iostat.h"
#include <trace/events/f2fs.h>
#define __reverse_ffz(x) __reverse_ffs(~(x))
@@ -188,7 +189,8 @@ void f2fs_register_inmem_page(struct inode *inode, struct page *page)
set_page_private_atomic(page);
- new = f2fs_kmem_cache_alloc(inmem_entry_slab, GFP_NOFS);
+ new = f2fs_kmem_cache_alloc(inmem_entry_slab,
+ GFP_NOFS, true, NULL);
/* add atomic page indices to the list */
new->page = page;
@@ -776,11 +778,22 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi)
return 0;
for (i = 1; i < sbi->s_ndevs; i++) {
+ int count = DEFAULT_RETRY_IO_COUNT;
+
if (!f2fs_test_bit(i, (char *)&sbi->dirty_device))
continue;
- ret = __submit_flush_wait(sbi, FDEV(i).bdev);
- if (ret)
+
+ do {
+ ret = __submit_flush_wait(sbi, FDEV(i).bdev);
+ if (ret)
+ congestion_wait(BLK_RW_ASYNC,
+ DEFAULT_IO_TIMEOUT);
+ } while (ret && --count);
+
+ if (ret) {
+ f2fs_stop_checkpoint(sbi, false);
break;
+ }
spin_lock(&sbi->dev_lock);
f2fs_clear_bit(i, (char *)&sbi->dirty_device);
@@ -990,7 +1003,7 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
pend_list = &dcc->pend_list[plist_idx(len)];
- dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS);
+ dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS, true, NULL);
INIT_LIST_HEAD(&dc->list);
dc->bdev = bdev;
dc->lstart = lstart;
@@ -1893,7 +1906,8 @@ static int f2fs_issue_discard(struct f2fs_sb_info *sbi,
se = get_seg_entry(sbi, GET_SEGNO(sbi, i));
offset = GET_BLKOFF_FROM_SEG0(sbi, i);
- if (!f2fs_test_and_set_bit(offset, se->discard_map))
+ if (f2fs_block_unit_discard(sbi) &&
+ !f2fs_test_and_set_bit(offset, se->discard_map))
sbi->discard_blks--;
}
@@ -1918,7 +1932,8 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
struct list_head *head = &SM_I(sbi)->dcc_info->entry_list;
int i;
- if (se->valid_blocks == max_blocks || !f2fs_hw_support_discard(sbi))
+ if (se->valid_blocks == max_blocks || !f2fs_hw_support_discard(sbi) ||
+ !f2fs_block_unit_discard(sbi))
return false;
if (!force) {
@@ -1949,7 +1964,7 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
if (!de) {
de = f2fs_kmem_cache_alloc(discard_entry_slab,
- GFP_F2FS_ZERO);
+ GFP_F2FS_ZERO, true, NULL);
de->start_blkaddr = START_BLOCK(sbi, cpc->trim_start);
list_add_tail(&de->list, head);
}
@@ -2003,14 +2018,18 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
unsigned int start = 0, end = -1;
unsigned int secno, start_segno;
bool force = (cpc->reason & CP_DISCARD);
- bool need_align = f2fs_lfs_mode(sbi) && __is_large_section(sbi);
+ bool section_alignment = F2FS_OPTION(sbi).discard_unit ==
+ DISCARD_UNIT_SECTION;
+
+ if (f2fs_lfs_mode(sbi) && __is_large_section(sbi))
+ section_alignment = true;
mutex_lock(&dirty_i->seglist_lock);
while (1) {
int i;
- if (need_align && end != -1)
+ if (section_alignment && end != -1)
end--;
start = find_next_bit(prefree_map, MAIN_SEGS(sbi), end + 1);
if (start >= MAIN_SEGS(sbi))
@@ -2018,7 +2037,7 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
end = find_next_zero_bit(prefree_map, MAIN_SEGS(sbi),
start + 1);
- if (need_align) {
+ if (section_alignment) {
start = rounddown(start, sbi->segs_per_sec);
end = roundup(end, sbi->segs_per_sec);
}
@@ -2056,6 +2075,9 @@ next:
}
mutex_unlock(&dirty_i->seglist_lock);
+ if (!f2fs_block_unit_discard(sbi))
+ goto wakeup;
+
/* send small discards */
list_for_each_entry_safe(entry, this, head, list) {
unsigned int cur_pos = 0, next_pos, len, total_len = 0;
@@ -2089,12 +2111,29 @@ skip:
dcc->nr_discards -= total_len;
}
+wakeup:
wake_up_discard_thread(sbi, false);
}
-static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
+int f2fs_start_discard_thread(struct f2fs_sb_info *sbi)
{
dev_t dev = sbi->sb->s_bdev->bd_dev;
+ struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+ int err = 0;
+
+ if (!f2fs_realtime_discard_enable(sbi))
+ return 0;
+
+ dcc->f2fs_issue_discard = kthread_run(issue_discard_thread, sbi,
+ "f2fs_discard-%u:%u", MAJOR(dev), MINOR(dev));
+ if (IS_ERR(dcc->f2fs_issue_discard))
+ err = PTR_ERR(dcc->f2fs_issue_discard);
+
+ return err;
+}
+
+static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
+{
struct discard_cmd_control *dcc;
int err = 0, i;
@@ -2108,6 +2147,11 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
return -ENOMEM;
dcc->discard_granularity = DEFAULT_DISCARD_GRANULARITY;
+ if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SEGMENT)
+ dcc->discard_granularity = sbi->blocks_per_seg;
+ else if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SECTION)
+ dcc->discard_granularity = BLKS_PER_SEC(sbi);
+
INIT_LIST_HEAD(&dcc->entry_list);
for (i = 0; i < MAX_PLIST_NUM; i++)
INIT_LIST_HEAD(&dcc->pend_list[i]);
@@ -2127,13 +2171,10 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
init_waitqueue_head(&dcc->discard_wait_queue);
SM_I(sbi)->dcc_info = dcc;
init_thread:
- dcc->f2fs_issue_discard = kthread_run(issue_discard_thread, sbi,
- "f2fs_discard-%u:%u", MAJOR(dev), MINOR(dev));
- if (IS_ERR(dcc->f2fs_issue_discard)) {
- err = PTR_ERR(dcc->f2fs_issue_discard);
+ err = f2fs_start_discard_thread(sbi);
+ if (err) {
kfree(dcc);
SM_I(sbi)->dcc_info = NULL;
- return err;
}
return err;
@@ -2255,7 +2296,8 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
del = 0;
}
- if (!f2fs_test_and_set_bit(offset, se->discard_map))
+ if (f2fs_block_unit_discard(sbi) &&
+ !f2fs_test_and_set_bit(offset, se->discard_map))
sbi->discard_blks--;
/*
@@ -2297,7 +2339,8 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
}
}
- if (f2fs_test_and_clear_bit(offset, se->discard_map))
+ if (f2fs_block_unit_discard(sbi) &&
+ f2fs_test_and_clear_bit(offset, se->discard_map))
sbi->discard_blks++;
}
if (!f2fs_test_bit(offset, se->ckpt_valid_map))
@@ -3563,7 +3606,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
goto drop_bio;
}
- if (is_sbi_flag_set(sbi, SBI_NEED_FSCK) || f2fs_cp_error(sbi)) {
+ if (f2fs_cp_error(sbi)) {
err = -EIO;
goto drop_bio;
}
@@ -4071,7 +4114,8 @@ static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
static struct sit_entry_set *grab_sit_entry_set(void)
{
struct sit_entry_set *ses =
- f2fs_kmem_cache_alloc(sit_entry_set_slab, GFP_NOFS);
+ f2fs_kmem_cache_alloc(sit_entry_set_slab,
+ GFP_NOFS, true, NULL);
ses->entry_cnt = 0;
INIT_LIST_HEAD(&ses->set_list);
@@ -4282,6 +4326,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
unsigned int sit_segs, start;
char *src_bitmap, *bitmap;
unsigned int bitmap_size, main_bitmap_size, sit_bitmap_size;
+ unsigned int discard_map = f2fs_block_unit_discard(sbi) ? 1 : 0;
/* allocate memory for SIT information */
sit_i = f2fs_kzalloc(sbi, sizeof(struct sit_info), GFP_KERNEL);
@@ -4304,9 +4349,9 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
return -ENOMEM;
#ifdef CONFIG_F2FS_CHECK_FS
- bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * 4;
+ bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * (3 + discard_map);
#else
- bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * 3;
+ bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * (2 + discard_map);
#endif
sit_i->bitmap = f2fs_kvzalloc(sbi, bitmap_size, GFP_KERNEL);
if (!sit_i->bitmap)
@@ -4326,8 +4371,10 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
bitmap += SIT_VBLOCK_MAP_SIZE;
#endif
- sit_i->sentries[start].discard_map = bitmap;
- bitmap += SIT_VBLOCK_MAP_SIZE;
+ if (discard_map) {
+ sit_i->sentries[start].discard_map = bitmap;
+ bitmap += SIT_VBLOCK_MAP_SIZE;
+ }
}
sit_i->tmp_map = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
@@ -4489,17 +4536,19 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
if (IS_NODESEG(se->type))
total_node_blocks += se->valid_blocks;
- /* build discard map only one time */
- if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
- memset(se->discard_map, 0xff,
- SIT_VBLOCK_MAP_SIZE);
- } else {
- memcpy(se->discard_map,
- se->cur_valid_map,
- SIT_VBLOCK_MAP_SIZE);
- sbi->discard_blks +=
- sbi->blocks_per_seg -
- se->valid_blocks;
+ if (f2fs_block_unit_discard(sbi)) {
+ /* build discard map only one time */
+ if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
+ memset(se->discard_map, 0xff,
+ SIT_VBLOCK_MAP_SIZE);
+ } else {
+ memcpy(se->discard_map,
+ se->cur_valid_map,
+ SIT_VBLOCK_MAP_SIZE);
+ sbi->discard_blks +=
+ sbi->blocks_per_seg -
+ se->valid_blocks;
+ }
}
if (__is_large_section(sbi))
@@ -4535,13 +4584,15 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
if (IS_NODESEG(se->type))
total_node_blocks += se->valid_blocks;
- if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
- memset(se->discard_map, 0xff, SIT_VBLOCK_MAP_SIZE);
- } else {
- memcpy(se->discard_map, se->cur_valid_map,
- SIT_VBLOCK_MAP_SIZE);
- sbi->discard_blks += old_valid_blocks;
- sbi->discard_blks -= se->valid_blocks;
+ if (f2fs_block_unit_discard(sbi)) {
+ if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
+ memset(se->discard_map, 0xff, SIT_VBLOCK_MAP_SIZE);
+ } else {
+ memcpy(se->discard_map, se->cur_valid_map,
+ SIT_VBLOCK_MAP_SIZE);
+ sbi->discard_blks += old_valid_blocks;
+ sbi->discard_blks -= se->valid_blocks;
+ }
}
if (__is_large_section(sbi)) {
@@ -5159,7 +5210,7 @@ int f2fs_build_segment_manager(struct f2fs_sb_info *sbi)
sm_info->ipu_policy = 1 << F2FS_IPU_FSYNC;
sm_info->min_ipu_util = DEF_MIN_IPU_UTIL;
sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS;
- sm_info->min_seq_blocks = sbi->blocks_per_seg * sbi->segs_per_sec;
+ sm_info->min_seq_blocks = sbi->blocks_per_seg;
sm_info->min_hot_blocks = DEF_MIN_HOT_BLOCKS;
sm_info->min_ssr_sections = reserved_sections(sbi);
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 050230c70a53..89fff258727d 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -142,7 +142,7 @@ enum {
};
/*
- * In the victim_sel_policy->alloc_mode, there are two block allocation modes.
+ * In the victim_sel_policy->alloc_mode, there are three block allocation modes.
* LFS writes data sequentially with cleaning operations.
* SSR (Slack Space Recycle) reuses obsolete space without cleaning operations.
* AT_SSR (Age Threshold based Slack Space Recycle) merges fragments into
@@ -155,7 +155,7 @@ enum {
};
/*
- * In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes.
+ * In the victim_sel_policy->gc_mode, there are three gc, aka cleaning, modes.
* GC_CB is based on cost-benefit algorithm.
* GC_GREEDY is based on greedy algorithm.
* GC_AT is based on age-threshold algorithm.
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index ce2ab1b85c11..78ebc306ee2b 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -33,6 +33,7 @@
#include "segment.h"
#include "xattr.h"
#include "gc.h"
+#include "iostat.h"
#define CREATE_TRACE_POINTS
#include <trace/events/f2fs.h>
@@ -56,6 +57,7 @@ const char *f2fs_fault_name[FAULT_MAX] = {
[FAULT_CHECKPOINT] = "checkpoint error",
[FAULT_DISCARD] = "discard error",
[FAULT_WRITE_IO] = "write IO error",
+ [FAULT_SLAB_ALLOC] = "slab alloc",
};
void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
@@ -155,6 +157,7 @@ enum {
Opt_atgc,
Opt_gc_merge,
Opt_nogc_merge,
+ Opt_discard_unit,
Opt_err,
};
@@ -231,6 +234,7 @@ static match_table_t f2fs_tokens = {
{Opt_atgc, "atgc"},
{Opt_gc_merge, "gc_merge"},
{Opt_nogc_merge, "nogc_merge"},
+ {Opt_discard_unit, "discard_unit=%s"},
{Opt_err, NULL},
};
@@ -657,10 +661,14 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
return -EINVAL;
break;
case Opt_discard:
+ if (!f2fs_hw_support_discard(sbi)) {
+ f2fs_warn(sbi, "device does not support discard");
+ break;
+ }
set_opt(sbi, DISCARD);
break;
case Opt_nodiscard:
- if (f2fs_sb_has_blkzoned(sbi)) {
+ if (f2fs_hw_should_discard(sbi)) {
f2fs_warn(sbi, "discard is required for zoned block devices");
return -EINVAL;
}
@@ -1173,6 +1181,25 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
case Opt_nogc_merge:
clear_opt(sbi, GC_MERGE);
break;
+ case Opt_discard_unit:
+ name = match_strdup(&args[0]);
+ if (!name)
+ return -ENOMEM;
+ if (!strcmp(name, "block")) {
+ F2FS_OPTION(sbi).discard_unit =
+ DISCARD_UNIT_BLOCK;
+ } else if (!strcmp(name, "segment")) {
+ F2FS_OPTION(sbi).discard_unit =
+ DISCARD_UNIT_SEGMENT;
+ } else if (!strcmp(name, "section")) {
+ F2FS_OPTION(sbi).discard_unit =
+ DISCARD_UNIT_SECTION;
+ } else {
+ kfree(name);
+ return -EINVAL;
+ }
+ kfree(name);
+ break;
default:
f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value",
p);
@@ -1211,6 +1238,14 @@ default_check:
return -EINVAL;
}
#endif
+ if (f2fs_sb_has_blkzoned(sbi)) {
+ if (F2FS_OPTION(sbi).discard_unit !=
+ DISCARD_UNIT_SECTION) {
+ f2fs_info(sbi, "Zoned block device doesn't need small discard, set discard_unit=section by default");
+ F2FS_OPTION(sbi).discard_unit =
+ DISCARD_UNIT_SECTION;
+ }
+ }
#ifdef CONFIG_F2FS_FS_COMPRESSION
if (f2fs_test_compress_extension(sbi)) {
@@ -1271,7 +1306,8 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
{
struct f2fs_inode_info *fi;
- fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_F2FS_ZERO);
+ fi = f2fs_kmem_cache_alloc(f2fs_inode_cachep,
+ GFP_F2FS_ZERO, false, F2FS_SB(sb));
if (!fi)
return NULL;
@@ -1541,6 +1577,7 @@ static void f2fs_put_super(struct super_block *sb)
#endif
fscrypt_free_dummy_policy(&F2FS_OPTION(sbi).dummy_enc_policy);
destroy_percpu_info(sbi);
+ f2fs_destroy_iostat(sbi);
for (i = 0; i < NR_PAGE_TYPE; i++)
kvfree(sbi->write_io[i]);
#ifdef CONFIG_UNICODE
@@ -1924,6 +1961,14 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
if (test_opt(sbi, ATGC))
seq_puts(seq, ",atgc");
+
+ if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_BLOCK)
+ seq_printf(seq, ",discard_unit=%s", "block");
+ else if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SEGMENT)
+ seq_printf(seq, ",discard_unit=%s", "segment");
+ else if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SECTION)
+ seq_printf(seq, ",discard_unit=%s", "section");
+
return 0;
}
@@ -1959,11 +2004,15 @@ static void default_options(struct f2fs_sb_info *sbi)
F2FS_OPTION(sbi).unusable_cap = 0;
sbi->sb->s_flags |= SB_LAZYTIME;
set_opt(sbi, FLUSH_MERGE);
- set_opt(sbi, DISCARD);
- if (f2fs_sb_has_blkzoned(sbi))
+ if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi))
+ set_opt(sbi, DISCARD);
+ if (f2fs_sb_has_blkzoned(sbi)) {
F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS;
- else
+ F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_SECTION;
+ } else {
F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE;
+ F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_BLOCK;
+ }
#ifdef CONFIG_F2FS_FS_XATTR
set_opt(sbi, XATTR_USER);
@@ -2038,8 +2087,17 @@ restore_flag:
static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
{
+ int retry = DEFAULT_RETRY_IO_COUNT;
+
/* we should flush all the data to keep data consistency */
- sync_inodes_sb(sbi->sb);
+ do {
+ sync_inodes_sb(sbi->sb);
+ cond_resched();
+ congestion_wait(BLK_RW_ASYNC, DEFAULT_IO_TIMEOUT);
+ } while (get_pages(sbi, F2FS_DIRTY_DATA) && retry--);
+
+ if (unlikely(retry < 0))
+ f2fs_warn(sbi, "checkpoint=enable has some unwritten data.");
down_write(&sbi->gc_lock);
f2fs_dirty_to_prefree(sbi);
@@ -2060,12 +2118,15 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
bool need_restart_gc = false, need_stop_gc = false;
bool need_restart_ckpt = false, need_stop_ckpt = false;
bool need_restart_flush = false, need_stop_flush = false;
+ bool need_restart_discard = false, need_stop_discard = false;
bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE);
- bool disable_checkpoint = test_opt(sbi, DISABLE_CHECKPOINT);
+ bool enable_checkpoint = !test_opt(sbi, DISABLE_CHECKPOINT);
bool no_io_align = !F2FS_IO_ALIGNED(sbi);
bool no_atgc = !test_opt(sbi, ATGC);
+ bool no_discard = !test_opt(sbi, DISCARD);
bool no_compress_cache = !test_opt(sbi, COMPRESS_CACHE);
- bool checkpoint_changed;
+ bool block_unit_discard = f2fs_block_unit_discard(sbi);
+ struct discard_cmd_control *dcc;
#ifdef CONFIG_QUOTA
int i, j;
#endif
@@ -2110,8 +2171,6 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
err = parse_options(sb, data, true);
if (err)
goto restore_opts;
- checkpoint_changed =
- disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
/*
* Previous and new state of filesystem is RO,
@@ -2168,6 +2227,12 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
goto restore_opts;
}
+ if (block_unit_discard != f2fs_block_unit_discard(sbi)) {
+ err = -EINVAL;
+ f2fs_warn(sbi, "switch discard_unit option is not allowed");
+ goto restore_opts;
+ }
+
if ((*flags & SB_RDONLY) && test_opt(sbi, DISABLE_CHECKPOINT)) {
err = -EINVAL;
f2fs_warn(sbi, "disabling checkpoint not compatible with read-only");
@@ -2233,11 +2298,26 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
need_stop_flush = true;
}
- if (checkpoint_changed) {
+ if (no_discard == !!test_opt(sbi, DISCARD)) {
+ if (test_opt(sbi, DISCARD)) {
+ err = f2fs_start_discard_thread(sbi);
+ if (err)
+ goto restore_flush;
+ need_stop_discard = true;
+ } else {
+ dcc = SM_I(sbi)->dcc_info;
+ f2fs_stop_discard_thread(sbi);
+ if (atomic_read(&dcc->discard_cmd_cnt))
+ f2fs_issue_discard_timeout(sbi);
+ need_restart_discard = true;
+ }
+ }
+
+ if (enable_checkpoint == !!test_opt(sbi, DISABLE_CHECKPOINT)) {
if (test_opt(sbi, DISABLE_CHECKPOINT)) {
err = f2fs_disable_checkpoint(sbi);
if (err)
- goto restore_flush;
+ goto restore_discard;
} else {
f2fs_enable_checkpoint(sbi);
}
@@ -2257,6 +2337,13 @@ skip:
adjust_unusable_cap_perc(sbi);
*flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
return 0;
+restore_discard:
+ if (need_restart_discard) {
+ if (f2fs_start_discard_thread(sbi))
+ f2fs_warn(sbi, "discard has been stopped");
+ } else if (need_stop_discard) {
+ f2fs_stop_discard_thread(sbi);
+ }
restore_flush:
if (need_restart_flush) {
if (f2fs_create_flush_cmd_control(sbi))
@@ -2517,6 +2604,33 @@ static int f2fs_enable_quotas(struct super_block *sb)
return 0;
}
+static int f2fs_quota_sync_file(struct f2fs_sb_info *sbi, int type)
+{
+ struct quota_info *dqopt = sb_dqopt(sbi->sb);
+ struct address_space *mapping = dqopt->files[type]->i_mapping;
+ int ret = 0;
+
+ ret = dquot_writeback_dquots(sbi->sb, type);
+ if (ret)
+ goto out;
+
+ ret = filemap_fdatawrite(mapping);
+ if (ret)
+ goto out;
+
+ /* if we are using journalled quota */
+ if (is_journalled_quota(sbi))
+ goto out;
+
+ ret = filemap_fdatawait(mapping);
+
+ truncate_inode_pages(&dqopt->files[type]->i_data, 0);
+out:
+ if (ret)
+ set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
+ return ret;
+}
+
int f2fs_quota_sync(struct super_block *sb, int type)
{
struct f2fs_sb_info *sbi = F2FS_SB(sb);
@@ -2525,56 +2639,41 @@ int f2fs_quota_sync(struct super_block *sb, int type)
int ret;
/*
- * do_quotactl
- * f2fs_quota_sync
- * down_read(quota_sem)
- * dquot_writeback_dquots()
- * f2fs_dquot_commit
- * block_operation
- * down_read(quota_sem)
- */
- f2fs_lock_op(sbi);
-
- down_read(&sbi->quota_sem);
- ret = dquot_writeback_dquots(sb, type);
- if (ret)
- goto out;
-
- /*
* Now when everything is written we can discard the pagecache so
* that userspace sees the changes.
*/
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- struct address_space *mapping;
if (type != -1 && cnt != type)
continue;
- if (!sb_has_quota_active(sb, cnt))
- continue;
- mapping = dqopt->files[cnt]->i_mapping;
+ if (!sb_has_quota_active(sb, type))
+ return 0;
- ret = filemap_fdatawrite(mapping);
- if (ret)
- goto out;
+ inode_lock(dqopt->files[cnt]);
- /* if we are using journalled quota */
- if (is_journalled_quota(sbi))
- continue;
+ /*
+ * do_quotactl
+ * f2fs_quota_sync
+ * down_read(quota_sem)
+ * dquot_writeback_dquots()
+ * f2fs_dquot_commit
+ * block_operation
+ * down_read(quota_sem)
+ */
+ f2fs_lock_op(sbi);
+ down_read(&sbi->quota_sem);
- ret = filemap_fdatawait(mapping);
- if (ret)
- set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR);
+ ret = f2fs_quota_sync_file(sbi, cnt);
+
+ up_read(&sbi->quota_sem);
+ f2fs_unlock_op(sbi);
- inode_lock(dqopt->files[cnt]);
- truncate_inode_pages(&dqopt->files[cnt]->i_data, 0);
inode_unlock(dqopt->files[cnt]);
+
+ if (ret)
+ break;
}
-out:
- if (ret)
- set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR);
- up_read(&sbi->quota_sem);
- f2fs_unlock_op(sbi);
return ret;
}
@@ -3207,11 +3306,13 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
return -EFSCORRUPTED;
}
- if (le32_to_cpu(raw_super->cp_payload) >
- (blocks_per_seg - F2FS_CP_PACKS)) {
- f2fs_info(sbi, "Insane cp_payload (%u > %u)",
+ if (le32_to_cpu(raw_super->cp_payload) >=
+ (blocks_per_seg - F2FS_CP_PACKS -
+ NR_CURSEG_PERSIST_TYPE)) {
+ f2fs_info(sbi, "Insane cp_payload (%u >= %u)",
le32_to_cpu(raw_super->cp_payload),
- blocks_per_seg - F2FS_CP_PACKS);
+ blocks_per_seg - F2FS_CP_PACKS -
+ NR_CURSEG_PERSIST_TYPE);
return -EFSCORRUPTED;
}
@@ -3247,6 +3348,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
unsigned int cp_pack_start_sum, cp_payload;
block_t user_block_count, valid_user_blocks;
block_t avail_node_count, valid_node_count;
+ unsigned int nat_blocks, nat_bits_bytes, nat_bits_blocks;
int i, j;
total = le32_to_cpu(raw_super->segment_count);
@@ -3377,6 +3479,17 @@ skip_cross:
return 1;
}
+ nat_blocks = nat_segs << log_blocks_per_seg;
+ nat_bits_bytes = nat_blocks / BITS_PER_BYTE;
+ nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
+ if (__is_set_ckpt_flags(ckpt, CP_NAT_BITS_FLAG) &&
+ (cp_payload + F2FS_CP_PACKS +
+ NR_CURSEG_PERSIST_TYPE + nat_bits_blocks >= blocks_per_seg)) {
+ f2fs_warn(sbi, "Insane cp_payload: %u, nat_bits_blocks: %u)",
+ cp_payload, nat_bits_blocks);
+ return -EFSCORRUPTED;
+ }
+
if (unlikely(f2fs_cp_error(sbi))) {
f2fs_err(sbi, "A bug case: need to run fsck");
return 1;
@@ -3409,6 +3522,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sbi->next_victim_seg[FG_GC] = NULL_SEGNO;
sbi->max_victim_search = DEF_MAX_VICTIM_SEARCH;
sbi->migration_granularity = sbi->segs_per_sec;
+ sbi->seq_file_ra_mul = MIN_RA_MUL;
sbi->dir_level = DEF_DIR_LEVEL;
sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
@@ -3768,7 +3882,8 @@ static void f2fs_tuning_parameters(struct f2fs_sb_info *sbi)
/* adjust parameters according to the volume size */
if (sm_i->main_segments <= SMALL_VOLUME_SEGMENTS) {
F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE;
- sm_i->dcc_info->discard_granularity = 1;
+ if (f2fs_block_unit_discard(sbi))
+ sm_i->dcc_info->discard_granularity = 1;
sm_i->ipu_policy = 1 << F2FS_IPU_FORCE;
}
@@ -3889,11 +4004,6 @@ try_onemore:
set_sbi_flag(sbi, SBI_POR_DOING);
spin_lock_init(&sbi->stat_lock);
- /* init iostat info */
- spin_lock_init(&sbi->iostat_lock);
- sbi->iostat_enable = false;
- sbi->iostat_period_ms = DEFAULT_IOSTAT_PERIOD_MS;
-
for (i = 0; i < NR_PAGE_TYPE; i++) {
int n = (i == META) ? 1 : NR_TEMP_TYPE;
int j;
@@ -3924,10 +4034,14 @@ try_onemore:
init_waitqueue_head(&sbi->cp_wait);
init_sb_info(sbi);
- err = init_percpu_info(sbi);
+ err = f2fs_init_iostat(sbi);
if (err)
goto free_bio_info;
+ err = init_percpu_info(sbi);
+ if (err)
+ goto free_iostat;
+
if (F2FS_IO_ALIGNED(sbi)) {
sbi->write_io_dummy =
mempool_create_page_pool(2 * (F2FS_IO_SIZE(sbi) - 1), 0);
@@ -4259,6 +4373,8 @@ free_io_dummy:
mempool_destroy(sbi->write_io_dummy);
free_percpu:
destroy_percpu_info(sbi);
+free_iostat:
+ f2fs_destroy_iostat(sbi);
free_bio_info:
for (i = 0; i < NR_PAGE_TYPE; i++)
kvfree(sbi->write_io[i]);
@@ -4401,9 +4517,12 @@ static int __init init_f2fs_fs(void)
err = f2fs_init_post_read_processing();
if (err)
goto free_root_stats;
- err = f2fs_init_bio_entry_cache();
+ err = f2fs_init_iostat_processing();
if (err)
goto free_post_read;
+ err = f2fs_init_bio_entry_cache();
+ if (err)
+ goto free_iostat;
err = f2fs_init_bioset();
if (err)
goto free_bio_enrty_cache;
@@ -4425,6 +4544,8 @@ free_bioset:
f2fs_destroy_bioset();
free_bio_enrty_cache:
f2fs_destroy_bio_entry_cache();
+free_iostat:
+ f2fs_destroy_iostat_processing();
free_post_read:
f2fs_destroy_post_read_processing();
free_root_stats:
@@ -4459,6 +4580,7 @@ static void __exit exit_f2fs_fs(void)
f2fs_destroy_compress_mempool();
f2fs_destroy_bioset();
f2fs_destroy_bio_entry_cache();
+ f2fs_destroy_iostat_processing();
f2fs_destroy_post_read_processing();
f2fs_destroy_root_stats();
unregister_filesystem(&f2fs_fs_type);
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index daad532a4e2b..a32fe31c33b8 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -17,6 +17,7 @@
#include "f2fs.h"
#include "segment.h"
#include "gc.h"
+#include "iostat.h"
#include <trace/events/f2fs.h>
static struct proc_dir_entry *f2fs_proc_root;
@@ -307,6 +308,14 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
return sysfs_emit(buf, "%u\n", sbi->compr_new_inode);
#endif
+ if (!strcmp(a->attr.name, "gc_segment_mode"))
+ return sysfs_emit(buf, "%u\n", sbi->gc_segment_mode);
+
+ if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {
+ return sysfs_emit(buf, "%u\n",
+ sbi->gc_reclaimed_segs[sbi->gc_segment_mode]);
+ }
+
ui = (unsigned int *)(ptr + a->offset);
return sprintf(buf, "%u\n", *ui);
@@ -343,7 +352,7 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
set = false;
}
- if (strlen(name) >= F2FS_EXTENSION_LEN)
+ if (!strlen(name) || strlen(name) >= F2FS_EXTENSION_LEN)
return -EINVAL;
down_write(&sbi->sb_lock);
@@ -420,6 +429,8 @@ out:
if (!strcmp(a->attr.name, "discard_granularity")) {
if (t == 0 || t > MAX_PLIST_NUM)
return -EINVAL;
+ if (!f2fs_block_unit_discard(sbi))
+ return -EINVAL;
if (t == *ui)
return count;
*ui = t;
@@ -467,6 +478,7 @@ out:
return count;
}
+#ifdef CONFIG_F2FS_IOSTAT
if (!strcmp(a->attr.name, "iostat_enable")) {
sbi->iostat_enable = !!t;
if (!sbi->iostat_enable)
@@ -482,6 +494,7 @@ out:
spin_unlock(&sbi->iostat_lock);
return count;
}
+#endif
#ifdef CONFIG_F2FS_FS_COMPRESSION
if (!strcmp(a->attr.name, "compr_written_block") ||
@@ -515,6 +528,29 @@ out:
return count;
}
+ if (!strcmp(a->attr.name, "gc_segment_mode")) {
+ if (t < MAX_GC_MODE)
+ sbi->gc_segment_mode = t;
+ else
+ return -EINVAL;
+ return count;
+ }
+
+ if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {
+ if (t != 0)
+ return -EINVAL;
+ sbi->gc_reclaimed_segs[sbi->gc_segment_mode] = 0;
+ return count;
+ }
+
+ if (!strcmp(a->attr.name, "seq_file_ra_mul")) {
+ if (t >= MIN_RA_MUL && t <= MAX_RA_MUL)
+ sbi->seq_file_ra_mul = t;
+ else
+ return -EINVAL;
+ return count;
+ }
+
*ui = (unsigned int)t;
return count;
@@ -667,8 +703,10 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval,
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info,
umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]);
+#ifdef CONFIG_F2FS_IOSTAT
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_period_ms, iostat_period_ms);
+#endif
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_io_bytes, max_io_bytes);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold);
@@ -740,6 +778,10 @@ F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_count, max_candidate_cou
F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_weight, age_weight);
F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_threshold, age_threshold);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, seq_file_ra_mul, seq_file_ra_mul);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_segment_mode, gc_segment_mode);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_reclaimed_segments, gc_reclaimed_segs);
+
#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
static struct attribute *f2fs_attrs[] = {
ATTR_LIST(gc_urgent_sleep_time),
@@ -770,8 +812,10 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(discard_idle_interval),
ATTR_LIST(gc_idle_interval),
ATTR_LIST(umount_discard_timeout),
+#ifdef CONFIG_F2FS_IOSTAT
ATTR_LIST(iostat_enable),
ATTR_LIST(iostat_period_ms),
+#endif
ATTR_LIST(readdir_ra),
ATTR_LIST(max_io_bytes),
ATTR_LIST(gc_pin_file_thresh),
@@ -812,6 +856,9 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(atgc_candidate_count),
ATTR_LIST(atgc_age_weight),
ATTR_LIST(atgc_age_threshold),
+ ATTR_LIST(seq_file_ra_mul),
+ ATTR_LIST(gc_segment_mode),
+ ATTR_LIST(gc_reclaimed_segments),
NULL,
};
ATTRIBUTE_GROUPS(f2fs);
@@ -1036,101 +1083,6 @@ static int __maybe_unused segment_bits_seq_show(struct seq_file *seq,
return 0;
}
-void f2fs_record_iostat(struct f2fs_sb_info *sbi)
-{
- unsigned long long iostat_diff[NR_IO_TYPE];
- int i;
-
- if (time_is_after_jiffies(sbi->iostat_next_period))
- return;
-
- /* Need double check under the lock */
- spin_lock(&sbi->iostat_lock);
- if (time_is_after_jiffies(sbi->iostat_next_period)) {
- spin_unlock(&sbi->iostat_lock);
- return;
- }
- sbi->iostat_next_period = jiffies +
- msecs_to_jiffies(sbi->iostat_period_ms);
-
- for (i = 0; i < NR_IO_TYPE; i++) {
- iostat_diff[i] = sbi->rw_iostat[i] -
- sbi->prev_rw_iostat[i];
- sbi->prev_rw_iostat[i] = sbi->rw_iostat[i];
- }
- spin_unlock(&sbi->iostat_lock);
-
- trace_f2fs_iostat(sbi, iostat_diff);
-}
-
-static int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
- void *offset)
-{
- struct super_block *sb = seq->private;
- struct f2fs_sb_info *sbi = F2FS_SB(sb);
- time64_t now = ktime_get_real_seconds();
-
- if (!sbi->iostat_enable)
- return 0;
-
- seq_printf(seq, "time: %-16llu\n", now);
-
- /* print app write IOs */
- seq_puts(seq, "[WRITE]\n");
- seq_printf(seq, "app buffered: %-16llu\n",
- sbi->rw_iostat[APP_BUFFERED_IO]);
- seq_printf(seq, "app direct: %-16llu\n",
- sbi->rw_iostat[APP_DIRECT_IO]);
- seq_printf(seq, "app mapped: %-16llu\n",
- sbi->rw_iostat[APP_MAPPED_IO]);
-
- /* print fs write IOs */
- seq_printf(seq, "fs data: %-16llu\n",
- sbi->rw_iostat[FS_DATA_IO]);
- seq_printf(seq, "fs node: %-16llu\n",
- sbi->rw_iostat[FS_NODE_IO]);
- seq_printf(seq, "fs meta: %-16llu\n",
- sbi->rw_iostat[FS_META_IO]);
- seq_printf(seq, "fs gc data: %-16llu\n",
- sbi->rw_iostat[FS_GC_DATA_IO]);
- seq_printf(seq, "fs gc node: %-16llu\n",
- sbi->rw_iostat[FS_GC_NODE_IO]);
- seq_printf(seq, "fs cp data: %-16llu\n",
- sbi->rw_iostat[FS_CP_DATA_IO]);
- seq_printf(seq, "fs cp node: %-16llu\n",
- sbi->rw_iostat[FS_CP_NODE_IO]);
- seq_printf(seq, "fs cp meta: %-16llu\n",
- sbi->rw_iostat[FS_CP_META_IO]);
-
- /* print app read IOs */
- seq_puts(seq, "[READ]\n");
- seq_printf(seq, "app buffered: %-16llu\n",
- sbi->rw_iostat[APP_BUFFERED_READ_IO]);
- seq_printf(seq, "app direct: %-16llu\n",
- sbi->rw_iostat[APP_DIRECT_READ_IO]);
- seq_printf(seq, "app mapped: %-16llu\n",
- sbi->rw_iostat[APP_MAPPED_READ_IO]);
-
- /* print fs read IOs */
- seq_printf(seq, "fs data: %-16llu\n",
- sbi->rw_iostat[FS_DATA_READ_IO]);
- seq_printf(seq, "fs gc data: %-16llu\n",
- sbi->rw_iostat[FS_GDATA_READ_IO]);
- seq_printf(seq, "fs compr_data: %-16llu\n",
- sbi->rw_iostat[FS_CDATA_READ_IO]);
- seq_printf(seq, "fs node: %-16llu\n",
- sbi->rw_iostat[FS_NODE_READ_IO]);
- seq_printf(seq, "fs meta: %-16llu\n",
- sbi->rw_iostat[FS_META_READ_IO]);
-
- /* print other IOs */
- seq_puts(seq, "[OTHER]\n");
- seq_printf(seq, "fs discard: %-16llu\n",
- sbi->rw_iostat[FS_DISCARD]);
-
- return 0;
-}
-
static int __maybe_unused victim_bits_seq_show(struct seq_file *seq,
void *offset)
{
@@ -1213,13 +1165,15 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi)
sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
if (sbi->s_proc) {
- proc_create_single_data("segment_info", S_IRUGO, sbi->s_proc,
+ proc_create_single_data("segment_info", 0444, sbi->s_proc,
segment_info_seq_show, sb);
- proc_create_single_data("segment_bits", S_IRUGO, sbi->s_proc,
+ proc_create_single_data("segment_bits", 0444, sbi->s_proc,
segment_bits_seq_show, sb);
- proc_create_single_data("iostat_info", S_IRUGO, sbi->s_proc,
+#ifdef CONFIG_F2FS_IOSTAT
+ proc_create_single_data("iostat_info", 0444, sbi->s_proc,
iostat_info_seq_show, sb);
- proc_create_single_data("victim_bits", S_IRUGO, sbi->s_proc,
+#endif
+ proc_create_single_data("victim_bits", 0444, sbi->s_proc,
victim_bits_seq_show, sb);
}
return 0;
@@ -1238,7 +1192,9 @@ put_sb_kobj:
void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi)
{
if (sbi->s_proc) {
+#ifdef CONFIG_F2FS_IOSTAT
remove_proc_entry("iostat_info", sbi->s_proc);
+#endif
remove_proc_entry("segment_info", sbi->s_proc);
remove_proc_entry("segment_bits", sbi->s_proc);
remove_proc_entry("victim_bits", sbi->s_proc);
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index c8f34decbf8e..1d2d29dcd41c 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -27,7 +27,8 @@ static void *xattr_alloc(struct f2fs_sb_info *sbi, int size, bool *is_inline)
{
if (likely(size == sbi->inline_xattr_slab_size)) {
*is_inline = true;
- return kmem_cache_zalloc(sbi->inline_xattr_slab, GFP_NOFS);
+ return f2fs_kmem_cache_alloc(sbi->inline_xattr_slab,
+ GFP_F2FS_ZERO, false, sbi);
}
*is_inline = false;
return f2fs_kzalloc(sbi, size, GFP_NOFS);
diff --git a/fs/fat/.kunitconfig b/fs/fat/.kunitconfig
new file mode 100644
index 000000000000..0a6971dbeccb
--- /dev/null
+++ b/fs/fat/.kunitconfig
@@ -0,0 +1,5 @@
+CONFIG_KUNIT=y
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_KUNIT_TEST=y
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig
index 66532a71e8fd..238cc55f84c4 100644
--- a/fs/fat/Kconfig
+++ b/fs/fat/Kconfig
@@ -77,7 +77,7 @@ config VFAT_FS
config FAT_DEFAULT_CODEPAGE
int "Default codepage for FAT"
- depends on MSDOS_FS || VFAT_FS
+ depends on FAT_FS
default 437
help
This option should be set to the codepage of your FAT filesystems.
@@ -115,3 +115,15 @@ config FAT_DEFAULT_UTF8
Say Y if you use UTF-8 encoding for file names, N otherwise.
See <file:Documentation/filesystems/vfat.rst> for more information.
+
+config FAT_KUNIT_TEST
+ tristate "Unit Tests for FAT filesystems" if !KUNIT_ALL_TESTS
+ depends on KUNIT && FAT_FS
+ default KUNIT_ALL_TESTS
+ help
+ This builds the FAT KUnit tests
+
+ For more information on KUnit and unit tests in general, please refer
+ to the KUnit documentation in Documentation/dev-tools/kunit
+
+ If unsure, say N
diff --git a/fs/fat/Makefile b/fs/fat/Makefile
index 70645ce2f7fc..2b034112690d 100644
--- a/fs/fat/Makefile
+++ b/fs/fat/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_MSDOS_FS) += msdos.o
fat-y := cache.o dir.o fatent.o file.o inode.o misc.o nfs.o
vfat-y := namei_vfat.o
msdos-y := namei_msdos.o
+
+obj-$(CONFIG_FAT_KUNIT_TEST) += fat_test.o
diff --git a/fs/fat/fat_test.c b/fs/fat/fat_test.c
new file mode 100644
index 000000000000..2dab4ca1d0d8
--- /dev/null
+++ b/fs/fat/fat_test.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit tests for FAT filesystems.
+ *
+ * Copyright (C) 2020 Google LLC.
+ * Author: David Gow <davidgow@google.com>
+ */
+
+#include <kunit/test.h>
+
+#include "fat.h"
+
+static void fat_checksum_test(struct kunit *test)
+{
+ /* With no extension. */
+ KUNIT_EXPECT_EQ(test, fat_checksum("VMLINUX "), (u8)44);
+ /* With 3-letter extension. */
+ KUNIT_EXPECT_EQ(test, fat_checksum("README TXT"), (u8)115);
+ /* With short (1-letter) extension. */
+ KUNIT_EXPECT_EQ(test, fat_checksum("ABCDEFGHA "), (u8)98);
+}
+
+struct fat_timestamp_testcase {
+ const char *name;
+ struct timespec64 ts;
+ __le16 time;
+ __le16 date;
+ u8 cs;
+ int time_offset;
+};
+
+static struct fat_timestamp_testcase time_test_cases[] = {
+ {
+ .name = "Earliest possible UTC (1980-01-01 00:00:00)",
+ .ts = {.tv_sec = 315532800LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(0),
+ .date = cpu_to_le16(33),
+ .cs = 0,
+ .time_offset = 0,
+ },
+ {
+ .name = "Latest possible UTC (2107-12-31 23:59:58)",
+ .ts = {.tv_sec = 4354819198LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(49021),
+ .date = cpu_to_le16(65439),
+ .cs = 0,
+ .time_offset = 0,
+ },
+ {
+ .name = "Earliest possible (UTC-11) (== 1979-12-31 13:00:00 UTC)",
+ .ts = {.tv_sec = 315493200LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(0),
+ .date = cpu_to_le16(33),
+ .cs = 0,
+ .time_offset = 11 * 60,
+ },
+ {
+ .name = "Latest possible (UTC+11) (== 2108-01-01 10:59:58 UTC)",
+ .ts = {.tv_sec = 4354858798LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(49021),
+ .date = cpu_to_le16(65439),
+ .cs = 0,
+ .time_offset = -11 * 60,
+ },
+ {
+ .name = "Leap Day / Year (1996-02-29 00:00:00)",
+ .ts = {.tv_sec = 825552000LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(0),
+ .date = cpu_to_le16(8285),
+ .cs = 0,
+ .time_offset = 0,
+ },
+ {
+ .name = "Year 2000 is leap year (2000-02-29 00:00:00)",
+ .ts = {.tv_sec = 951782400LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(0),
+ .date = cpu_to_le16(10333),
+ .cs = 0,
+ .time_offset = 0,
+ },
+ {
+ .name = "Year 2100 not leap year (2100-03-01 00:00:00)",
+ .ts = {.tv_sec = 4107542400LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(0),
+ .date = cpu_to_le16(61537),
+ .cs = 0,
+ .time_offset = 0,
+ },
+ {
+ .name = "Leap year + timezone UTC+1 (== 2004-02-29 00:30:00 UTC)",
+ .ts = {.tv_sec = 1078014600LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(48064),
+ .date = cpu_to_le16(12380),
+ .cs = 0,
+ .time_offset = -60,
+ },
+ {
+ .name = "Leap year + timezone UTC-1 (== 2004-02-29 23:30:00 UTC)",
+ .ts = {.tv_sec = 1078097400LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(960),
+ .date = cpu_to_le16(12385),
+ .cs = 0,
+ .time_offset = 60,
+ },
+ {
+ .name = "VFAT odd-second resolution (1999-12-31 23:59:59)",
+ .ts = {.tv_sec = 946684799LL, .tv_nsec = 0L},
+ .time = cpu_to_le16(49021),
+ .date = cpu_to_le16(10143),
+ .cs = 100,
+ .time_offset = 0,
+ },
+ {
+ .name = "VFAT 10ms resolution (1980-01-01 00:00:00:0010)",
+ .ts = {.tv_sec = 315532800LL, .tv_nsec = 10000000L},
+ .time = cpu_to_le16(0),
+ .date = cpu_to_le16(33),
+ .cs = 1,
+ .time_offset = 0,
+ },
+};
+
+static void time_testcase_desc(struct fat_timestamp_testcase *t,
+ char *desc)
+{
+ strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
+}
+
+KUNIT_ARRAY_PARAM(fat_time, time_test_cases, time_testcase_desc);
+
+static void fat_time_fat2unix_test(struct kunit *test)
+{
+ static struct msdos_sb_info fake_sb;
+ struct timespec64 ts;
+ struct fat_timestamp_testcase *testcase =
+ (struct fat_timestamp_testcase *)test->param_value;
+
+ fake_sb.options.tz_set = 1;
+ fake_sb.options.time_offset = testcase->time_offset;
+
+ fat_time_fat2unix(&fake_sb, &ts,
+ testcase->time,
+ testcase->date,
+ testcase->cs);
+ KUNIT_EXPECT_EQ_MSG(test,
+ testcase->ts.tv_sec,
+ ts.tv_sec,
+ "Timestamp mismatch (seconds)\n");
+ KUNIT_EXPECT_EQ_MSG(test,
+ testcase->ts.tv_nsec,
+ ts.tv_nsec,
+ "Timestamp mismatch (nanoseconds)\n");
+}
+
+static void fat_time_unix2fat_test(struct kunit *test)
+{
+ static struct msdos_sb_info fake_sb;
+ __le16 date, time;
+ u8 cs;
+ struct fat_timestamp_testcase *testcase =
+ (struct fat_timestamp_testcase *)test->param_value;
+
+ fake_sb.options.tz_set = 1;
+ fake_sb.options.time_offset = testcase->time_offset;
+
+ fat_time_unix2fat(&fake_sb, &testcase->ts,
+ &time, &date, &cs);
+ KUNIT_EXPECT_EQ_MSG(test,
+ le16_to_cpu(testcase->time),
+ le16_to_cpu(time),
+ "Time mismatch\n");
+ KUNIT_EXPECT_EQ_MSG(test,
+ le16_to_cpu(testcase->date),
+ le16_to_cpu(date),
+ "Date mismatch\n");
+ KUNIT_EXPECT_EQ_MSG(test,
+ testcase->cs,
+ cs,
+ "Centisecond mismatch\n");
+}
+
+static struct kunit_case fat_test_cases[] = {
+ KUNIT_CASE(fat_checksum_test),
+ KUNIT_CASE_PARAM(fat_time_fat2unix_test, fat_time_gen_params),
+ KUNIT_CASE_PARAM(fat_time_unix2fat_test, fat_time_gen_params),
+ {},
+};
+
+static struct kunit_suite fat_test_suite = {
+ .name = "fat_test",
+ .test_cases = fat_test_cases,
+};
+
+kunit_test_suites(&fat_test_suite);
+
+MODULE_LICENSE("GPL v2");
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 18a50a46b57f..91ca3c304211 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -230,6 +230,9 @@ void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec64 *ts,
}
}
+/* Export fat_time_fat2unix() for the fat_test KUnit tests. */
+EXPORT_SYMBOL_GPL(fat_time_fat2unix);
+
/* Convert linear UNIX date to a FAT time/date pair. */
void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec64 *ts,
__le16 *time, __le16 *date, u8 *time_cs)
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 68added37c15..9c6c6a3e2de5 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -1051,7 +1051,8 @@ static int __init fcntl_init(void)
__FMODE_EXEC | __FMODE_NONOTIFY));
fasync_cache = kmem_cache_create("fasync_cache",
- sizeof(struct fasync_struct), 0, SLAB_PANIC, NULL);
+ sizeof(struct fasync_struct), 0,
+ SLAB_PANIC | SLAB_ACCOUNT, NULL);
return 0;
}
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index eb57dade6076..81ec192ce067 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -406,6 +406,11 @@ static bool inode_do_switch_wbs(struct inode *inode,
inc_wb_stat(new_wb, WB_WRITEBACK);
}
+ if (mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK)) {
+ atomic_dec(&old_wb->writeback_inodes);
+ atomic_inc(&new_wb->writeback_inodes);
+ }
+
wb_get(new_wb);
/*
@@ -1034,20 +1039,20 @@ restart:
* cgroup_writeback_by_id - initiate cgroup writeback from bdi and memcg IDs
* @bdi_id: target bdi id
* @memcg_id: target memcg css id
- * @nr: number of pages to write, 0 for best-effort dirty flushing
* @reason: reason why some writeback work initiated
* @done: target wb_completion
*
* Initiate flush of the bdi_writeback identified by @bdi_id and @memcg_id
* with the specified parameters.
*/
-int cgroup_writeback_by_id(u64 bdi_id, int memcg_id, unsigned long nr,
+int cgroup_writeback_by_id(u64 bdi_id, int memcg_id,
enum wb_reason reason, struct wb_completion *done)
{
struct backing_dev_info *bdi;
struct cgroup_subsys_state *memcg_css;
struct bdi_writeback *wb;
struct wb_writeback_work *work;
+ unsigned long dirty;
int ret;
/* lookup bdi and memcg */
@@ -1076,24 +1081,22 @@ int cgroup_writeback_by_id(u64 bdi_id, int memcg_id, unsigned long nr,
}
/*
- * If @nr is zero, the caller is attempting to write out most of
+ * The caller is attempting to write out most of
* the currently dirty pages. Let's take the current dirty page
* count and inflate it by 25% which should be large enough to
* flush out most dirty pages while avoiding getting livelocked by
* concurrent dirtiers.
+ *
+ * BTW the memcg stats are flushed periodically and this is best-effort
+ * estimation, so some potential error is ok.
*/
- if (!nr) {
- unsigned long filepages, headroom, dirty, writeback;
-
- mem_cgroup_wb_stats(wb, &filepages, &headroom, &dirty,
- &writeback);
- nr = dirty * 10 / 8;
- }
+ dirty = memcg_page_state(mem_cgroup_from_css(memcg_css), NR_FILE_DIRTY);
+ dirty = dirty * 10 / 8;
/* issue the writeback work */
work = kzalloc(sizeof(*work), GFP_NOWAIT | __GFP_NOWARN);
if (work) {
- work->nr_pages = nr;
+ work->nr_pages = dirty;
work->sync_mode = WB_SYNC_NONE;
work->range_cyclic = 1;
work->reason = reason;
@@ -1999,7 +2002,6 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
static long wb_writeback(struct bdi_writeback *wb,
struct wb_writeback_work *work)
{
- unsigned long wb_start = jiffies;
long nr_pages = work->nr_pages;
unsigned long dirtied_before = jiffies;
struct inode *inode;
@@ -2053,8 +2055,6 @@ static long wb_writeback(struct bdi_writeback *wb,
progress = __writeback_inodes_wb(wb, work);
trace_writeback_written(wb, work);
- wb_update_bandwidth(wb, wb_start);
-
/*
* Did we write something? Try for more
*
diff --git a/fs/fs_context.c b/fs/fs_context.c
index de1985eae535..b7e43a780a62 100644
--- a/fs/fs_context.c
+++ b/fs/fs_context.c
@@ -254,7 +254,7 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
struct fs_context *fc;
int ret = -ENOMEM;
- fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL);
+ fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL_ACCOUNT);
if (!fc)
return ERR_PTR(-ENOMEM);
@@ -649,7 +649,7 @@ const struct fs_context_operations legacy_fs_context_ops = {
*/
static int legacy_init_fs_context(struct fs_context *fc)
{
- fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL);
+ fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL_ACCOUNT);
if (!fc->fs_private)
return -ENOMEM;
fc->ops = &legacy_fs_context_ops;
diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig
index 427efa73b9bd..b313a978ae0a 100644
--- a/fs/fscache/Kconfig
+++ b/fs/fscache/Kconfig
@@ -14,6 +14,7 @@ config FSCACHE
config FSCACHE_STATS
bool "Gather statistical information on local caching"
depends on FSCACHE && PROC_FS
+ select NETFS_STATS
help
This option causes statistical information to be gathered on local
caching and exported through file:
@@ -28,23 +29,6 @@ config FSCACHE_STATS
See Documentation/filesystems/caching/fscache.rst for more information.
-config FSCACHE_HISTOGRAM
- bool "Gather latency information on local caching"
- depends on FSCACHE && PROC_FS
- help
- This option causes latency information to be gathered on local
- caching and exported through file:
-
- /proc/fs/fscache/histogram
-
- The generation of this histogram adds a certain amount of overhead to
- execution as there are a number of points at which data is gathered,
- and on a multi-CPU system these may be on cachelines that keep
- bouncing between CPUs. On the other hand, the histogram may be
- useful for debugging purposes. Saying 'N' here is recommended.
-
- See Documentation/filesystems/caching/fscache.rst for more information.
-
config FSCACHE_DEBUG
bool "Debug FS-Cache"
depends on FSCACHE
@@ -54,10 +38,3 @@ config FSCACHE_DEBUG
enabled by setting bits in /sys/modules/fscache/parameter/debug.
See Documentation/filesystems/caching/fscache.rst for more information.
-
-config FSCACHE_OBJECT_LIST
- bool "Maintain global object list for debugging purposes"
- depends on FSCACHE && PROC_FS
- help
- Maintain a global list of active fscache objects that can be
- retrieved through /proc/fs/fscache/objects for debugging purposes
diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile
index 3b2ffa93ac18..03a871d689bb 100644
--- a/fs/fscache/Makefile
+++ b/fs/fscache/Makefile
@@ -16,7 +16,5 @@ fscache-y := \
fscache-$(CONFIG_PROC_FS) += proc.o
fscache-$(CONFIG_FSCACHE_STATS) += stats.o
-fscache-$(CONFIG_FSCACHE_HISTOGRAM) += histogram.o
-fscache-$(CONFIG_FSCACHE_OBJECT_LIST) += object-list.o
obj-$(CONFIG_FSCACHE) := fscache.o
diff --git a/fs/fscache/cache.c b/fs/fscache/cache.c
index fcc136361415..bd4f44c1cce0 100644
--- a/fs/fscache/cache.c
+++ b/fs/fscache/cache.c
@@ -116,7 +116,7 @@ struct fscache_cache *fscache_select_cache_for_object(
cache = NULL;
spin_unlock(&cookie->lock);
- _leave(" = %p [parent]", cache);
+ _leave(" = %s [parent]", cache ? cache->tag->name : "NULL");
return cache;
}
@@ -152,14 +152,14 @@ struct fscache_cache *fscache_select_cache_for_object(
if (test_bit(FSCACHE_IOERROR, &tag->cache->flags))
return NULL;
- _leave(" = %p [specific]", tag->cache);
+ _leave(" = %s [specific]", tag->name);
return tag->cache;
no_preference:
/* netfs has no preference - just select first cache */
cache = list_entry(fscache_cache_list.next,
struct fscache_cache, link);
- _leave(" = %p [first]", cache);
+ _leave(" = %s [first]", cache->tag->name);
return cache;
}
@@ -261,7 +261,6 @@ int fscache_add_cache(struct fscache_cache *cache,
spin_lock(&cache->object_list_lock);
list_add_tail(&ifsdef->cache_link, &cache->object_list);
spin_unlock(&cache->object_list_lock);
- fscache_objlist_add(ifsdef);
/* add the cache's netfs definition index object to the top level index
* cookie as a known backing object */
@@ -270,7 +269,7 @@ int fscache_add_cache(struct fscache_cache *cache,
hlist_add_head(&ifsdef->cookie_link,
&fscache_fsdef_index.backing_objects);
- atomic_inc(&fscache_fsdef_index.usage);
+ refcount_inc(&fscache_fsdef_index.ref);
/* done */
spin_unlock(&fscache_fsdef_index.lock);
@@ -335,7 +334,7 @@ static void fscache_withdraw_all_objects(struct fscache_cache *cache,
struct fscache_object, cache_link);
list_move_tail(&object->cache_link, dying_objects);
- _debug("withdraw %p", object->cookie);
+ _debug("withdraw %x", object->cookie->debug_id);
/* This must be done under object_list_lock to prevent
* a race with fscache_drop_object().
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index 751bc5b1cddf..cd42be646ed3 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -19,6 +19,8 @@ static atomic_t fscache_object_debug_id = ATOMIC_INIT(0);
#define fscache_cookie_hash_shift 15
static struct hlist_bl_head fscache_cookie_hash[1 << fscache_cookie_hash_shift];
+static LIST_HEAD(fscache_cookies);
+static DEFINE_RWLOCK(fscache_cookies_lock);
static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie,
loff_t object_size);
@@ -29,21 +31,29 @@ static int fscache_attach_object(struct fscache_cookie *cookie,
static void fscache_print_cookie(struct fscache_cookie *cookie, char prefix)
{
- struct hlist_node *object;
+ struct fscache_object *object;
+ struct hlist_node *o;
const u8 *k;
unsigned loop;
- pr_err("%c-cookie c=%p [p=%p fl=%lx nc=%u na=%u]\n",
- prefix, cookie, cookie->parent, cookie->flags,
+ pr_err("%c-cookie c=%08x [p=%08x fl=%lx nc=%u na=%u]\n",
+ prefix,
+ cookie->debug_id,
+ cookie->parent ? cookie->parent->debug_id : 0,
+ cookie->flags,
atomic_read(&cookie->n_children),
atomic_read(&cookie->n_active));
- pr_err("%c-cookie d=%p n=%p\n",
- prefix, cookie->def, cookie->netfs_data);
-
- object = READ_ONCE(cookie->backing_objects.first);
- if (object)
- pr_err("%c-cookie o=%p\n",
- prefix, hlist_entry(object, struct fscache_object, cookie_link));
+ pr_err("%c-cookie d=%p{%s} n=%p\n",
+ prefix,
+ cookie->def,
+ cookie->def ? cookie->def->name : "?",
+ cookie->netfs_data);
+
+ o = READ_ONCE(cookie->backing_objects.first);
+ if (o) {
+ object = hlist_entry(o, struct fscache_object, cookie_link);
+ pr_err("%c-cookie o=%u\n", prefix, object->debug_id);
+ }
pr_err("%c-key=[%u] '", prefix, cookie->key_len);
k = (cookie->key_len <= sizeof(cookie->inline_key)) ?
@@ -57,6 +67,9 @@ void fscache_free_cookie(struct fscache_cookie *cookie)
{
if (cookie) {
BUG_ON(!hlist_empty(&cookie->backing_objects));
+ write_lock(&fscache_cookies_lock);
+ list_del(&cookie->proc_link);
+ write_unlock(&fscache_cookies_lock);
if (cookie->aux_len > sizeof(cookie->inline_aux))
kfree(cookie->aux);
if (cookie->key_len > sizeof(cookie->inline_key))
@@ -74,10 +87,8 @@ void fscache_free_cookie(struct fscache_cookie *cookie)
static int fscache_set_key(struct fscache_cookie *cookie,
const void *index_key, size_t index_key_len)
{
- unsigned long long h;
u32 *buf;
int bufs;
- int i;
bufs = DIV_ROUND_UP(index_key_len, sizeof(*buf));
@@ -91,17 +102,7 @@ static int fscache_set_key(struct fscache_cookie *cookie,
}
memcpy(buf, index_key, index_key_len);
-
- /* Calculate a hash and combine this with the length in the first word
- * or first half word
- */
- h = (unsigned long)cookie->parent;
- h += index_key_len + cookie->type;
-
- for (i = 0; i < bufs; i++)
- h += buf[i];
-
- cookie->key_hash = h ^ (h >> 32);
+ cookie->key_hash = fscache_hash(0, buf, bufs);
return 0;
}
@@ -129,6 +130,8 @@ static long fscache_compare_cookie(const struct fscache_cookie *a,
return memcmp(ka, kb, a->key_len);
}
+static atomic_t fscache_cookie_debug_id = ATOMIC_INIT(1);
+
/*
* Allocate a cookie.
*/
@@ -161,8 +164,9 @@ struct fscache_cookie *fscache_alloc_cookie(
goto nomem;
}
- atomic_set(&cookie->usage, 1);
+ refcount_set(&cookie->ref, 1);
atomic_set(&cookie->n_children, 0);
+ cookie->debug_id = atomic_inc_return(&fscache_cookie_debug_id);
/* We keep the active count elevated until relinquishment to prevent an
* attempt to wake up every time the object operations queue quiesces.
@@ -181,6 +185,10 @@ struct fscache_cookie *fscache_alloc_cookie(
/* radix tree insertion won't use the preallocation pool unless it's
* told it may not wait */
INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
+
+ write_lock(&fscache_cookies_lock);
+ list_add_tail(&cookie->proc_link, &fscache_cookies);
+ write_unlock(&fscache_cookies_lock);
return cookie;
nomem:
@@ -217,8 +225,8 @@ struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *candidate)
collision:
if (test_and_set_bit(FSCACHE_COOKIE_ACQUIRED, &cursor->flags)) {
- trace_fscache_cookie(cursor, fscache_cookie_collision,
- atomic_read(&cursor->usage));
+ trace_fscache_cookie(cursor->debug_id, refcount_read(&cursor->ref),
+ fscache_cookie_collision);
pr_err("Duplicate cookie detected\n");
fscache_print_cookie(cursor, 'O');
fscache_print_cookie(candidate, 'N');
@@ -297,7 +305,8 @@ struct fscache_cookie *__fscache_acquire_cookie(
cookie = fscache_hash_cookie(candidate);
if (!cookie) {
- trace_fscache_cookie(candidate, fscache_cookie_discard, 1);
+ trace_fscache_cookie(candidate->debug_id, 1,
+ fscache_cookie_discard);
goto out;
}
@@ -355,7 +364,7 @@ void __fscache_enable_cookie(struct fscache_cookie *cookie,
bool (*can_enable)(void *data),
void *data)
{
- _enter("%p", cookie);
+ _enter("%x", cookie->debug_id);
trace_fscache_enable(cookie);
@@ -452,10 +461,8 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie,
/* we may be required to wait for lookup to complete at this point */
if (!fscache_defer_lookup) {
- _debug("non-deferred lookup %p", &cookie->flags);
wait_on_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP,
TASK_UNINTERRUPTIBLE);
- _debug("complete");
if (test_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags))
goto unavailable;
}
@@ -480,7 +487,7 @@ static int fscache_alloc_object(struct fscache_cache *cache,
struct fscache_object *object;
int ret;
- _enter("%p,%p{%s}", cache, cookie, cookie->def->name);
+ _enter("%s,%x{%s}", cache->tag->name, cookie->debug_id, cookie->def->name);
spin_lock(&cookie->lock);
hlist_for_each_entry(object, &cookie->backing_objects,
@@ -600,8 +607,6 @@ static int fscache_attach_object(struct fscache_cookie *cookie,
/* Attach to the cookie. The object already has a ref on it. */
hlist_add_head(&object->cookie_link, &cookie->backing_objects);
-
- fscache_objlist_add(object);
ret = 0;
cant_attach_object:
@@ -658,7 +663,7 @@ EXPORT_SYMBOL(__fscache_invalidate);
*/
void __fscache_wait_on_invalidate(struct fscache_cookie *cookie)
{
- _enter("%p", cookie);
+ _enter("%x", cookie->debug_id);
wait_on_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING,
TASK_UNINTERRUPTIBLE);
@@ -713,7 +718,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie,
struct fscache_object *object;
bool awaken = false;
- _enter("%p,%u", cookie, invalidate);
+ _enter("%x,%u", cookie->debug_id, invalidate);
trace_fscache_disable(cookie);
@@ -803,8 +808,8 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie,
return;
}
- _enter("%p{%s,%p,%d},%d",
- cookie, cookie->def->name, cookie->netfs_data,
+ _enter("%x{%s,%d},%d",
+ cookie->debug_id, cookie->def->name,
atomic_read(&cookie->n_active), retire);
trace_fscache_relinquish(cookie, retire);
@@ -821,13 +826,12 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie,
BUG_ON(!radix_tree_empty(&cookie->stores));
if (cookie->parent) {
- ASSERTCMP(atomic_read(&cookie->parent->usage), >, 0);
+ ASSERTCMP(refcount_read(&cookie->parent->ref), >, 0);
ASSERTCMP(atomic_read(&cookie->parent->n_children), >, 0);
atomic_dec(&cookie->parent->n_children);
}
/* Dispose of the netfs's link to the cookie */
- ASSERTCMP(atomic_read(&cookie->usage), >, 0);
fscache_cookie_put(cookie, fscache_cookie_put_relinquish);
_leave("");
@@ -857,17 +861,17 @@ void fscache_cookie_put(struct fscache_cookie *cookie,
enum fscache_cookie_trace where)
{
struct fscache_cookie *parent;
- int usage;
+ int ref;
- _enter("%p", cookie);
+ _enter("%x", cookie->debug_id);
do {
- usage = atomic_dec_return(&cookie->usage);
- trace_fscache_cookie(cookie, where, usage);
+ unsigned int cookie_debug_id = cookie->debug_id;
+ bool zero = __refcount_dec_and_test(&cookie->ref, &ref);
- if (usage > 0)
+ trace_fscache_cookie(cookie_debug_id, ref - 1, where);
+ if (!zero)
return;
- BUG_ON(usage < 0);
parent = cookie->parent;
fscache_unhash_cookie(cookie);
@@ -881,6 +885,19 @@ void fscache_cookie_put(struct fscache_cookie *cookie,
}
/*
+ * Get a reference to a cookie.
+ */
+struct fscache_cookie *fscache_cookie_get(struct fscache_cookie *cookie,
+ enum fscache_cookie_trace where)
+{
+ int ref;
+
+ __refcount_inc(&cookie->ref, &ref);
+ trace_fscache_cookie(cookie->debug_id, ref + 1, where);
+ return cookie;
+}
+
+/*
* check the consistency between the netfs inode and the backing cache
*
* NOTE: it only serves no-index type
@@ -958,3 +975,97 @@ inconsistent:
return -ESTALE;
}
EXPORT_SYMBOL(__fscache_check_consistency);
+
+/*
+ * Generate a list of extant cookies in /proc/fs/fscache/cookies
+ */
+static int fscache_cookies_seq_show(struct seq_file *m, void *v)
+{
+ struct fscache_cookie *cookie;
+ unsigned int keylen = 0, auxlen = 0;
+ char _type[3], *type;
+ u8 *p;
+
+ if (v == &fscache_cookies) {
+ seq_puts(m,
+ "COOKIE PARENT USAGE CHILD ACT TY FL DEF NETFS_DATA\n"
+ "======== ======== ===== ===== === == === ================ ==========\n"
+ );
+ return 0;
+ }
+
+ cookie = list_entry(v, struct fscache_cookie, proc_link);
+
+ switch (cookie->type) {
+ case 0:
+ type = "IX";
+ break;
+ case 1:
+ type = "DT";
+ break;
+ default:
+ snprintf(_type, sizeof(_type), "%02u",
+ cookie->type);
+ type = _type;
+ break;
+ }
+
+ seq_printf(m,
+ "%08x %08x %5u %5u %3u %s %03lx %-16s %px",
+ cookie->debug_id,
+ cookie->parent ? cookie->parent->debug_id : 0,
+ refcount_read(&cookie->ref),
+ atomic_read(&cookie->n_children),
+ atomic_read(&cookie->n_active),
+ type,
+ cookie->flags,
+ cookie->def->name,
+ cookie->netfs_data);
+
+ keylen = cookie->key_len;
+ auxlen = cookie->aux_len;
+
+ if (keylen > 0 || auxlen > 0) {
+ seq_puts(m, " ");
+ p = keylen <= sizeof(cookie->inline_key) ?
+ cookie->inline_key : cookie->key;
+ for (; keylen > 0; keylen--)
+ seq_printf(m, "%02x", *p++);
+ if (auxlen > 0) {
+ seq_puts(m, ", ");
+ p = auxlen <= sizeof(cookie->inline_aux) ?
+ cookie->inline_aux : cookie->aux;
+ for (; auxlen > 0; auxlen--)
+ seq_printf(m, "%02x", *p++);
+ }
+ }
+
+ seq_puts(m, "\n");
+ return 0;
+}
+
+static void *fscache_cookies_seq_start(struct seq_file *m, loff_t *_pos)
+ __acquires(fscache_cookies_lock)
+{
+ read_lock(&fscache_cookies_lock);
+ return seq_list_start_head(&fscache_cookies, *_pos);
+}
+
+static void *fscache_cookies_seq_next(struct seq_file *m, void *v, loff_t *_pos)
+{
+ return seq_list_next(v, &fscache_cookies, _pos);
+}
+
+static void fscache_cookies_seq_stop(struct seq_file *m, void *v)
+ __releases(rcu)
+{
+ read_unlock(&fscache_cookies_lock);
+}
+
+
+const struct seq_operations fscache_cookies_seq_ops = {
+ .start = fscache_cookies_seq_start,
+ .next = fscache_cookies_seq_next,
+ .stop = fscache_cookies_seq_stop,
+ .show = fscache_cookies_seq_show,
+};
diff --git a/fs/fscache/fsdef.c b/fs/fscache/fsdef.c
index 09ed8795ad86..0402673c680e 100644
--- a/fs/fscache/fsdef.c
+++ b/fs/fscache/fsdef.c
@@ -45,7 +45,8 @@ static struct fscache_cookie_def fscache_fsdef_index_def = {
};
struct fscache_cookie fscache_fsdef_index = {
- .usage = ATOMIC_INIT(1),
+ .debug_id = 1,
+ .ref = REFCOUNT_INIT(1),
.n_active = ATOMIC_INIT(1),
.lock = __SPIN_LOCK_UNLOCKED(fscache_fsdef_index.lock),
.backing_objects = HLIST_HEAD_INIT,
diff --git a/fs/fscache/histogram.c b/fs/fscache/histogram.c
deleted file mode 100644
index 4e5beeaaf454..000000000000
--- a/fs/fscache/histogram.c
+++ /dev/null
@@ -1,87 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* FS-Cache latency histogram
- *
- * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- */
-
-#define FSCACHE_DEBUG_LEVEL THREAD
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include "internal.h"
-
-atomic_t fscache_obj_instantiate_histogram[HZ];
-atomic_t fscache_objs_histogram[HZ];
-atomic_t fscache_ops_histogram[HZ];
-atomic_t fscache_retrieval_delay_histogram[HZ];
-atomic_t fscache_retrieval_histogram[HZ];
-
-/*
- * display the time-taken histogram
- */
-static int fscache_histogram_show(struct seq_file *m, void *v)
-{
- unsigned long index;
- unsigned n[5], t;
-
- switch ((unsigned long) v) {
- case 1:
- seq_puts(m, "JIFS SECS OBJ INST OP RUNS OBJ RUNS RETRV DLY RETRIEVLS\n");
- return 0;
- case 2:
- seq_puts(m, "===== ===== ========= ========= ========= ========= =========\n");
- return 0;
- default:
- index = (unsigned long) v - 3;
- n[0] = atomic_read(&fscache_obj_instantiate_histogram[index]);
- n[1] = atomic_read(&fscache_ops_histogram[index]);
- n[2] = atomic_read(&fscache_objs_histogram[index]);
- n[3] = atomic_read(&fscache_retrieval_delay_histogram[index]);
- n[4] = atomic_read(&fscache_retrieval_histogram[index]);
- if (!(n[0] | n[1] | n[2] | n[3] | n[4]))
- return 0;
-
- t = (index * 1000) / HZ;
-
- seq_printf(m, "%4lu 0.%03u %9u %9u %9u %9u %9u\n",
- index, t, n[0], n[1], n[2], n[3], n[4]);
- return 0;
- }
-}
-
-/*
- * set up the iterator to start reading from the first line
- */
-static void *fscache_histogram_start(struct seq_file *m, loff_t *_pos)
-{
- if ((unsigned long long)*_pos >= HZ + 2)
- return NULL;
- if (*_pos == 0)
- *_pos = 1;
- return (void *)(unsigned long) *_pos;
-}
-
-/*
- * move to the next line
- */
-static void *fscache_histogram_next(struct seq_file *m, void *v, loff_t *pos)
-{
- (*pos)++;
- return (unsigned long long)*pos > HZ + 2 ?
- NULL : (void *)(unsigned long) *pos;
-}
-
-/*
- * clean up after reading
- */
-static void fscache_histogram_stop(struct seq_file *m, void *v)
-{
-}
-
-const struct seq_operations fscache_histogram_ops = {
- .start = fscache_histogram_start,
- .stop = fscache_histogram_stop,
- .next = fscache_histogram_next,
- .show = fscache_histogram_show,
-};
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index c483863b740a..c3e4804b8fcb 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -45,6 +45,7 @@ extern struct fscache_cache *fscache_select_cache_for_object(
* cookie.c
*/
extern struct kmem_cache *fscache_cookie_jar;
+extern const struct seq_operations fscache_cookies_seq_ops;
extern void fscache_free_cookie(struct fscache_cookie *);
extern struct fscache_cookie *fscache_alloc_cookie(struct fscache_cookie *,
@@ -53,9 +54,18 @@ extern struct fscache_cookie *fscache_alloc_cookie(struct fscache_cookie *,
const void *, size_t,
void *, loff_t);
extern struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *);
+extern struct fscache_cookie *fscache_cookie_get(struct fscache_cookie *,
+ enum fscache_cookie_trace);
extern void fscache_cookie_put(struct fscache_cookie *,
enum fscache_cookie_trace);
+static inline void fscache_cookie_see(struct fscache_cookie *cookie,
+ enum fscache_cookie_trace where)
+{
+ trace_fscache_cookie(cookie->debug_id, refcount_read(&cookie->ref),
+ where);
+}
+
/*
* fsdef.c
*/
@@ -63,30 +73,6 @@ extern struct fscache_cookie fscache_fsdef_index;
extern struct fscache_cookie_def fscache_fsdef_netfs_def;
/*
- * histogram.c
- */
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-extern atomic_t fscache_obj_instantiate_histogram[HZ];
-extern atomic_t fscache_objs_histogram[HZ];
-extern atomic_t fscache_ops_histogram[HZ];
-extern atomic_t fscache_retrieval_delay_histogram[HZ];
-extern atomic_t fscache_retrieval_histogram[HZ];
-
-static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif)
-{
- unsigned long jif = jiffies - start_jif;
- if (jif >= HZ)
- jif = HZ - 1;
- atomic_inc(&histogram[jif]);
-}
-
-extern const struct seq_operations fscache_histogram_ops;
-
-#else
-#define fscache_hist(hist, start_jif) do {} while (0)
-#endif
-
-/*
* main.c
*/
extern unsigned fscache_defer_lookup;
@@ -97,6 +83,8 @@ extern struct workqueue_struct *fscache_object_wq;
extern struct workqueue_struct *fscache_op_wq;
DECLARE_PER_CPU(wait_queue_head_t, fscache_object_cong_wait);
+extern unsigned int fscache_hash(unsigned int salt, unsigned int *data, unsigned int n);
+
static inline bool fscache_object_congested(void)
{
return workqueue_congested(WORK_CPU_UNBOUND, fscache_object_wq);
@@ -108,19 +96,6 @@ static inline bool fscache_object_congested(void)
extern void fscache_enqueue_object(struct fscache_object *);
/*
- * object-list.c
- */
-#ifdef CONFIG_FSCACHE_OBJECT_LIST
-extern const struct proc_ops fscache_objlist_proc_ops;
-
-extern void fscache_objlist_add(struct fscache_object *);
-extern void fscache_objlist_remove(struct fscache_object *);
-#else
-#define fscache_objlist_add(object) do {} while(0)
-#define fscache_objlist_remove(object) do {} while(0)
-#endif
-
-/*
* operation.c
*/
extern int fscache_submit_exclusive_op(struct fscache_object *,
@@ -320,14 +295,6 @@ static inline void fscache_raise_event(struct fscache_object *object,
fscache_enqueue_object(object);
}
-static inline void fscache_cookie_get(struct fscache_cookie *cookie,
- enum fscache_cookie_trace where)
-{
- int usage = atomic_inc_return(&cookie->usage);
-
- trace_fscache_cookie(cookie, where, usage);
-}
-
/*
* get an extra reference to a netfs retrieval context
*/
diff --git a/fs/fscache/main.c b/fs/fscache/main.c
index c1e6cc9091aa..4207f98e405f 100644
--- a/fs/fscache/main.c
+++ b/fs/fscache/main.c
@@ -94,6 +94,45 @@ static struct ctl_table fscache_sysctls_root[] = {
#endif
/*
+ * Mixing scores (in bits) for (7,20):
+ * Input delta: 1-bit 2-bit
+ * 1 round: 330.3 9201.6
+ * 2 rounds: 1246.4 25475.4
+ * 3 rounds: 1907.1 31295.1
+ * 4 rounds: 2042.3 31718.6
+ * Perfect: 2048 31744
+ * (32*64) (32*31/2 * 64)
+ */
+#define HASH_MIX(x, y, a) \
+ ( x ^= (a), \
+ y ^= x, x = rol32(x, 7),\
+ x += y, y = rol32(y,20),\
+ y *= 9 )
+
+static inline unsigned int fold_hash(unsigned long x, unsigned long y)
+{
+ /* Use arch-optimized multiply if one exists */
+ return __hash_32(y ^ __hash_32(x));
+}
+
+/*
+ * Generate a hash. This is derived from full_name_hash(), but we want to be
+ * sure it is arch independent and that it doesn't change as bits of the
+ * computed hash value might appear on disk. The caller also guarantees that
+ * the hashed data will be a series of aligned 32-bit words.
+ */
+unsigned int fscache_hash(unsigned int salt, unsigned int *data, unsigned int n)
+{
+ unsigned int a, x = 0, y = salt;
+
+ for (; n; n--) {
+ a = *data++;
+ HASH_MIX(x, y, a);
+ }
+ return fold_hash(x, y);
+}
+
+/*
* initialise the fs caching module
*/
static int __init fscache_init(void)
diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c
index cce92216fa28..d6bdb7b5e723 100644
--- a/fs/fscache/netfs.c
+++ b/fs/fscache/netfs.c
@@ -37,7 +37,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
if (!cookie)
goto already_registered;
if (cookie != candidate) {
- trace_fscache_cookie(candidate, fscache_cookie_discard, 1);
+ trace_fscache_cookie(candidate->debug_id, 1, fscache_cookie_discard);
fscache_free_cookie(candidate);
}
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c
deleted file mode 100644
index e106a1a1600d..000000000000
--- a/fs/fscache/object-list.c
+++ /dev/null
@@ -1,414 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* Global fscache object list maintainer and viewer
- *
- * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- */
-
-#define FSCACHE_DEBUG_LEVEL COOKIE
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/key.h>
-#include <keys/user-type.h>
-#include "internal.h"
-
-static struct rb_root fscache_object_list;
-static DEFINE_RWLOCK(fscache_object_list_lock);
-
-struct fscache_objlist_data {
- unsigned long config; /* display configuration */
-#define FSCACHE_OBJLIST_CONFIG_KEY 0x00000001 /* show object keys */
-#define FSCACHE_OBJLIST_CONFIG_AUX 0x00000002 /* show object auxdata */
-#define FSCACHE_OBJLIST_CONFIG_COOKIE 0x00000004 /* show objects with cookies */
-#define FSCACHE_OBJLIST_CONFIG_NOCOOKIE 0x00000008 /* show objects without cookies */
-#define FSCACHE_OBJLIST_CONFIG_BUSY 0x00000010 /* show busy objects */
-#define FSCACHE_OBJLIST_CONFIG_IDLE 0x00000020 /* show idle objects */
-#define FSCACHE_OBJLIST_CONFIG_PENDWR 0x00000040 /* show objects with pending writes */
-#define FSCACHE_OBJLIST_CONFIG_NOPENDWR 0x00000080 /* show objects without pending writes */
-#define FSCACHE_OBJLIST_CONFIG_READS 0x00000100 /* show objects with active reads */
-#define FSCACHE_OBJLIST_CONFIG_NOREADS 0x00000200 /* show objects without active reads */
-#define FSCACHE_OBJLIST_CONFIG_EVENTS 0x00000400 /* show objects with events */
-#define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */
-#define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with work */
-#define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without work */
-};
-
-/*
- * Add an object to the object list
- * - we use the address of the fscache_object structure as the key into the
- * tree
- */
-void fscache_objlist_add(struct fscache_object *obj)
-{
- struct fscache_object *xobj;
- struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL;
-
- ASSERT(RB_EMPTY_NODE(&obj->objlist_link));
-
- write_lock(&fscache_object_list_lock);
-
- while (*p) {
- parent = *p;
- xobj = rb_entry(parent, struct fscache_object, objlist_link);
-
- if (obj < xobj)
- p = &(*p)->rb_left;
- else if (obj > xobj)
- p = &(*p)->rb_right;
- else
- BUG();
- }
-
- rb_link_node(&obj->objlist_link, parent, p);
- rb_insert_color(&obj->objlist_link, &fscache_object_list);
-
- write_unlock(&fscache_object_list_lock);
-}
-
-/*
- * Remove an object from the object list.
- */
-void fscache_objlist_remove(struct fscache_object *obj)
-{
- if (RB_EMPTY_NODE(&obj->objlist_link))
- return;
-
- write_lock(&fscache_object_list_lock);
-
- BUG_ON(RB_EMPTY_ROOT(&fscache_object_list));
- rb_erase(&obj->objlist_link, &fscache_object_list);
-
- write_unlock(&fscache_object_list_lock);
-}
-
-/*
- * find the object in the tree on or after the specified index
- */
-static struct fscache_object *fscache_objlist_lookup(loff_t *_pos)
-{
- struct fscache_object *pobj, *obj = NULL, *minobj = NULL;
- struct rb_node *p;
- unsigned long pos;
-
- if (*_pos >= (unsigned long) ERR_PTR(-ENOENT))
- return NULL;
- pos = *_pos;
-
- /* banners (can't represent line 0 by pos 0 as that would involve
- * returning a NULL pointer) */
- if (pos == 0)
- return (struct fscache_object *)(long)++(*_pos);
- if (pos < 3)
- return (struct fscache_object *)pos;
-
- pobj = (struct fscache_object *)pos;
- p = fscache_object_list.rb_node;
- while (p) {
- obj = rb_entry(p, struct fscache_object, objlist_link);
- if (pobj < obj) {
- if (!minobj || minobj > obj)
- minobj = obj;
- p = p->rb_left;
- } else if (pobj > obj) {
- p = p->rb_right;
- } else {
- minobj = obj;
- break;
- }
- obj = NULL;
- }
-
- if (!minobj)
- *_pos = (unsigned long) ERR_PTR(-ENOENT);
- else if (minobj != obj)
- *_pos = (unsigned long) minobj;
- return minobj;
-}
-
-/*
- * set up the iterator to start reading from the first line
- */
-static void *fscache_objlist_start(struct seq_file *m, loff_t *_pos)
- __acquires(&fscache_object_list_lock)
-{
- read_lock(&fscache_object_list_lock);
- return fscache_objlist_lookup(_pos);
-}
-
-/*
- * move to the next line
- */
-static void *fscache_objlist_next(struct seq_file *m, void *v, loff_t *_pos)
-{
- (*_pos)++;
- return fscache_objlist_lookup(_pos);
-}
-
-/*
- * clean up after reading
- */
-static void fscache_objlist_stop(struct seq_file *m, void *v)
- __releases(&fscache_object_list_lock)
-{
- read_unlock(&fscache_object_list_lock);
-}
-
-/*
- * display an object
- */
-static int fscache_objlist_show(struct seq_file *m, void *v)
-{
- struct fscache_objlist_data *data = m->private;
- struct fscache_object *obj = v;
- struct fscache_cookie *cookie;
- unsigned long config = data->config;
- char _type[3], *type;
- u8 *p;
-
- if ((unsigned long) v == 1) {
- seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS"
- " EM EV FL S"
- " | NETFS_COOKIE_DEF TY FL NETFS_DATA");
- if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
- FSCACHE_OBJLIST_CONFIG_AUX))
- seq_puts(m, " ");
- if (config & FSCACHE_OBJLIST_CONFIG_KEY)
- seq_puts(m, "OBJECT_KEY");
- if ((config & (FSCACHE_OBJLIST_CONFIG_KEY |
- FSCACHE_OBJLIST_CONFIG_AUX)) ==
- (FSCACHE_OBJLIST_CONFIG_KEY | FSCACHE_OBJLIST_CONFIG_AUX))
- seq_puts(m, ", ");
- if (config & FSCACHE_OBJLIST_CONFIG_AUX)
- seq_puts(m, "AUX_DATA");
- seq_puts(m, "\n");
- return 0;
- }
-
- if ((unsigned long) v == 2) {
- seq_puts(m, "======== ======== ==== ===== === === === == ====="
- " == == == ="
- " | ================ == == ================");
- if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
- FSCACHE_OBJLIST_CONFIG_AUX))
- seq_puts(m, " ================");
- seq_puts(m, "\n");
- return 0;
- }
-
- /* filter out any unwanted objects */
-#define FILTER(criterion, _yes, _no) \
- do { \
- unsigned long yes = FSCACHE_OBJLIST_CONFIG_##_yes; \
- unsigned long no = FSCACHE_OBJLIST_CONFIG_##_no; \
- if (criterion) { \
- if (!(config & yes)) \
- return 0; \
- } else { \
- if (!(config & no)) \
- return 0; \
- } \
- } while(0)
-
- cookie = obj->cookie;
- if (~config) {
- FILTER(cookie->def,
- COOKIE, NOCOOKIE);
- FILTER(fscache_object_is_active(obj) ||
- obj->n_ops != 0 ||
- obj->n_obj_ops != 0 ||
- obj->flags ||
- !list_empty(&obj->dependents),
- BUSY, IDLE);
- FILTER(test_bit(FSCACHE_OBJECT_PENDING_WRITE, &obj->flags),
- PENDWR, NOPENDWR);
- FILTER(atomic_read(&obj->n_reads),
- READS, NOREADS);
- FILTER(obj->events & obj->event_mask,
- EVENTS, NOEVENTS);
- FILTER(work_busy(&obj->work), WORK, NOWORK);
- }
-
- seq_printf(m,
- "%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %2lx %1x | ",
- obj->debug_id,
- obj->parent ? obj->parent->debug_id : -1,
- obj->state->short_name,
- obj->n_children,
- obj->n_ops,
- obj->n_obj_ops,
- obj->n_in_progress,
- obj->n_exclusive,
- atomic_read(&obj->n_reads),
- obj->event_mask,
- obj->events,
- obj->flags,
- work_busy(&obj->work));
-
- if (fscache_use_cookie(obj)) {
- uint16_t keylen = 0, auxlen = 0;
-
- switch (cookie->type) {
- case 0:
- type = "IX";
- break;
- case 1:
- type = "DT";
- break;
- default:
- snprintf(_type, sizeof(_type), "%02u",
- cookie->type);
- type = _type;
- break;
- }
-
- seq_printf(m, "%-16s %s %2lx %16p",
- cookie->def->name,
- type,
- cookie->flags,
- cookie->netfs_data);
-
- if (config & FSCACHE_OBJLIST_CONFIG_KEY)
- keylen = cookie->key_len;
-
- if (config & FSCACHE_OBJLIST_CONFIG_AUX)
- auxlen = cookie->aux_len;
-
- if (keylen > 0 || auxlen > 0) {
- seq_puts(m, " ");
- p = keylen <= sizeof(cookie->inline_key) ?
- cookie->inline_key : cookie->key;
- for (; keylen > 0; keylen--)
- seq_printf(m, "%02x", *p++);
- if (auxlen > 0) {
- if (config & FSCACHE_OBJLIST_CONFIG_KEY)
- seq_puts(m, ", ");
- p = auxlen <= sizeof(cookie->inline_aux) ?
- cookie->inline_aux : cookie->aux;
- for (; auxlen > 0; auxlen--)
- seq_printf(m, "%02x", *p++);
- }
- }
-
- seq_puts(m, "\n");
- fscache_unuse_cookie(obj);
- } else {
- seq_puts(m, "<no_netfs>\n");
- }
- return 0;
-}
-
-static const struct seq_operations fscache_objlist_ops = {
- .start = fscache_objlist_start,
- .stop = fscache_objlist_stop,
- .next = fscache_objlist_next,
- .show = fscache_objlist_show,
-};
-
-/*
- * get the configuration for filtering the list
- */
-static void fscache_objlist_config(struct fscache_objlist_data *data)
-{
-#ifdef CONFIG_KEYS
- const struct user_key_payload *confkey;
- unsigned long config;
- struct key *key;
- const char *buf;
- int len;
-
- key = request_key(&key_type_user, "fscache:objlist", NULL);
- if (IS_ERR(key))
- goto no_config;
-
- config = 0;
- rcu_read_lock();
-
- confkey = user_key_payload_rcu(key);
- if (!confkey) {
- /* key was revoked */
- rcu_read_unlock();
- key_put(key);
- goto no_config;
- }
-
- buf = confkey->data;
-
- for (len = confkey->datalen - 1; len >= 0; len--) {
- switch (buf[len]) {
- case 'K': config |= FSCACHE_OBJLIST_CONFIG_KEY; break;
- case 'A': config |= FSCACHE_OBJLIST_CONFIG_AUX; break;
- case 'C': config |= FSCACHE_OBJLIST_CONFIG_COOKIE; break;
- case 'c': config |= FSCACHE_OBJLIST_CONFIG_NOCOOKIE; break;
- case 'B': config |= FSCACHE_OBJLIST_CONFIG_BUSY; break;
- case 'b': config |= FSCACHE_OBJLIST_CONFIG_IDLE; break;
- case 'W': config |= FSCACHE_OBJLIST_CONFIG_PENDWR; break;
- case 'w': config |= FSCACHE_OBJLIST_CONFIG_NOPENDWR; break;
- case 'R': config |= FSCACHE_OBJLIST_CONFIG_READS; break;
- case 'r': config |= FSCACHE_OBJLIST_CONFIG_NOREADS; break;
- case 'S': config |= FSCACHE_OBJLIST_CONFIG_WORK; break;
- case 's': config |= FSCACHE_OBJLIST_CONFIG_NOWORK; break;
- }
- }
-
- rcu_read_unlock();
- key_put(key);
-
- if (!(config & (FSCACHE_OBJLIST_CONFIG_COOKIE | FSCACHE_OBJLIST_CONFIG_NOCOOKIE)))
- config |= FSCACHE_OBJLIST_CONFIG_COOKIE | FSCACHE_OBJLIST_CONFIG_NOCOOKIE;
- if (!(config & (FSCACHE_OBJLIST_CONFIG_BUSY | FSCACHE_OBJLIST_CONFIG_IDLE)))
- config |= FSCACHE_OBJLIST_CONFIG_BUSY | FSCACHE_OBJLIST_CONFIG_IDLE;
- if (!(config & (FSCACHE_OBJLIST_CONFIG_PENDWR | FSCACHE_OBJLIST_CONFIG_NOPENDWR)))
- config |= FSCACHE_OBJLIST_CONFIG_PENDWR | FSCACHE_OBJLIST_CONFIG_NOPENDWR;
- if (!(config & (FSCACHE_OBJLIST_CONFIG_READS | FSCACHE_OBJLIST_CONFIG_NOREADS)))
- config |= FSCACHE_OBJLIST_CONFIG_READS | FSCACHE_OBJLIST_CONFIG_NOREADS;
- if (!(config & (FSCACHE_OBJLIST_CONFIG_EVENTS | FSCACHE_OBJLIST_CONFIG_NOEVENTS)))
- config |= FSCACHE_OBJLIST_CONFIG_EVENTS | FSCACHE_OBJLIST_CONFIG_NOEVENTS;
- if (!(config & (FSCACHE_OBJLIST_CONFIG_WORK | FSCACHE_OBJLIST_CONFIG_NOWORK)))
- config |= FSCACHE_OBJLIST_CONFIG_WORK | FSCACHE_OBJLIST_CONFIG_NOWORK;
-
- data->config = config;
- return;
-
-no_config:
-#endif
- data->config = ULONG_MAX;
-}
-
-/*
- * open "/proc/fs/fscache/objects" to provide a list of active objects
- * - can be configured by a user-defined key added to the caller's keyrings
- */
-static int fscache_objlist_open(struct inode *inode, struct file *file)
-{
- struct fscache_objlist_data *data;
-
- data = __seq_open_private(file, &fscache_objlist_ops, sizeof(*data));
- if (!data)
- return -ENOMEM;
-
- /* get the configuration key */
- fscache_objlist_config(data);
-
- return 0;
-}
-
-/*
- * clean up on close
- */
-static int fscache_objlist_release(struct inode *inode, struct file *file)
-{
- struct seq_file *m = file->private_data;
-
- kfree(m->private);
- m->private = NULL;
- return seq_release(inode, file);
-}
-
-const struct proc_ops fscache_objlist_proc_ops = {
- .proc_open = fscache_objlist_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = fscache_objlist_release,
-};
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index cb2146e02cd5..f346a78f4bd6 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -277,13 +277,10 @@ static void fscache_object_work_func(struct work_struct *work)
{
struct fscache_object *object =
container_of(work, struct fscache_object, work);
- unsigned long start;
_enter("{OBJ%x}", object->debug_id);
- start = jiffies;
fscache_object_sm_dispatcher(object);
- fscache_hist(fscache_objs_histogram, start);
fscache_put_object(object, fscache_obj_put_work);
}
@@ -436,7 +433,6 @@ static const struct fscache_state *fscache_parent_ready(struct fscache_object *o
spin_lock(&parent->lock);
parent->n_ops++;
parent->n_obj_ops++;
- object->lookup_jif = jiffies;
spin_unlock(&parent->lock);
_leave("");
@@ -522,7 +518,6 @@ void fscache_object_lookup_negative(struct fscache_object *object)
set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
- _debug("wake up lookup %p", &cookie->flags);
clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
}
@@ -596,7 +591,6 @@ static const struct fscache_state *fscache_object_available(struct fscache_objec
object->cache->ops->lookup_complete(object);
fscache_stat_d(&fscache_n_cop_lookup_complete);
- fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif);
fscache_stat(&fscache_n_object_avail);
_leave("");
@@ -799,8 +793,6 @@ static void fscache_put_object(struct fscache_object *object,
*/
void fscache_object_destroy(struct fscache_object *object)
{
- fscache_objlist_remove(object);
-
/* We can get rid of the cookie now */
fscache_cookie_put(object->cookie, fscache_cookie_put_object);
object->cookie = NULL;
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 4a5651d4904e..433877107700 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -616,7 +616,6 @@ void fscache_op_work_func(struct work_struct *work)
{
struct fscache_operation *op =
container_of(work, struct fscache_operation, work);
- unsigned long start;
_enter("{OBJ%x OP%x,%d}",
op->object->debug_id, op->debug_id, atomic_read(&op->usage));
@@ -624,9 +623,7 @@ void fscache_op_work_func(struct work_struct *work)
trace_fscache_op(op->object->cookie, op, fscache_op_work);
ASSERT(op->processor != NULL);
- start = jiffies;
op->processor(op);
- fscache_hist(fscache_ops_histogram, start);
fscache_put_operation(op);
_leave("");
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 991b0a871744..27df94ef0e0b 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -289,7 +289,6 @@ static void fscache_release_retrieval_op(struct fscache_operation *_op)
ASSERTIFCMP(op->op.state != FSCACHE_OP_ST_INITIALISED,
atomic_read(&op->n_pages), ==, 0);
- fscache_hist(fscache_retrieval_histogram, op->start_time);
if (op->context)
fscache_put_context(op->cookie, op->context);
@@ -324,7 +323,6 @@ struct fscache_retrieval *fscache_alloc_retrieval(
op->mapping = mapping;
op->end_io_func = end_io_func;
op->context = context;
- op->start_time = jiffies;
INIT_LIST_HEAD(&op->to_do);
/* Pin the netfs read context in case we need to do the actual netfs
@@ -340,8 +338,6 @@ struct fscache_retrieval *fscache_alloc_retrieval(
*/
int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie)
{
- unsigned long jif;
-
_enter("");
if (!test_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags)) {
@@ -351,7 +347,6 @@ int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie)
fscache_stat(&fscache_n_retrievals_wait);
- jif = jiffies;
if (wait_on_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP,
TASK_INTERRUPTIBLE) != 0) {
fscache_stat(&fscache_n_retrievals_intr);
@@ -362,7 +357,6 @@ int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie)
ASSERT(!test_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags));
smp_rmb();
- fscache_hist(fscache_retrieval_delay_histogram, jif);
_leave(" = 0 [dly]");
return 0;
}
diff --git a/fs/fscache/proc.c b/fs/fscache/proc.c
index 90a7bc22f7e1..061df8f61ffc 100644
--- a/fs/fscache/proc.c
+++ b/fs/fscache/proc.c
@@ -21,18 +21,16 @@ int __init fscache_proc_init(void)
if (!proc_mkdir("fs/fscache", NULL))
goto error_dir;
+ if (!proc_create_seq("fs/fscache/cookies", S_IFREG | 0444, NULL,
+ &fscache_cookies_seq_ops))
+ goto error_cookies;
+
#ifdef CONFIG_FSCACHE_STATS
if (!proc_create_single("fs/fscache/stats", S_IFREG | 0444, NULL,
fscache_stats_show))
goto error_stats;
#endif
-#ifdef CONFIG_FSCACHE_HISTOGRAM
- if (!proc_create_seq("fs/fscache/histogram", S_IFREG | 0444, NULL,
- &fscache_histogram_ops))
- goto error_histogram;
-#endif
-
#ifdef CONFIG_FSCACHE_OBJECT_LIST
if (!proc_create("fs/fscache/objects", S_IFREG | 0444, NULL,
&fscache_objlist_proc_ops))
@@ -45,14 +43,12 @@ int __init fscache_proc_init(void)
#ifdef CONFIG_FSCACHE_OBJECT_LIST
error_objects:
#endif
-#ifdef CONFIG_FSCACHE_HISTOGRAM
- remove_proc_entry("fs/fscache/histogram", NULL);
-error_histogram:
-#endif
#ifdef CONFIG_FSCACHE_STATS
remove_proc_entry("fs/fscache/stats", NULL);
error_stats:
#endif
+ remove_proc_entry("fs/fscache/cookies", NULL);
+error_cookies:
remove_proc_entry("fs/fscache", NULL);
error_dir:
_leave(" = -ENOMEM");
@@ -67,11 +63,9 @@ void fscache_proc_cleanup(void)
#ifdef CONFIG_FSCACHE_OBJECT_LIST
remove_proc_entry("fs/fscache/objects", NULL);
#endif
-#ifdef CONFIG_FSCACHE_HISTOGRAM
- remove_proc_entry("fs/fscache/histogram", NULL);
-#endif
#ifdef CONFIG_FSCACHE_STATS
remove_proc_entry("fs/fscache/stats", NULL);
#endif
+ remove_proc_entry("fs/fscache/cookies", NULL);
remove_proc_entry("fs/fscache", NULL);
}
diff --git a/fs/fuse/acl.c b/fs/fuse/acl.c
index 52b165319be1..337cb29a8dd5 100644
--- a/fs/fuse/acl.c
+++ b/fs/fuse/acl.c
@@ -11,7 +11,7 @@
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h>
-struct posix_acl *fuse_get_acl(struct inode *inode, int type)
+struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu)
{
struct fuse_conn *fc = get_fuse_conn(inode);
int size;
@@ -19,6 +19,9 @@ struct posix_acl *fuse_get_acl(struct inode *inode, int type)
void *value = NULL;
struct posix_acl *acl;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
if (fuse_is_bad(inode))
return ERR_PTR(-EIO);
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index cc7e94d73c6c..000d2e5627e9 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -328,7 +328,7 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
drop_nlink(d_inode(fuse_control_sb->s_root));
}
-static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fctx)
+static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fsc)
{
static const struct tree_descr empty_descr = {""};
struct fuse_conn *fc;
@@ -354,18 +354,18 @@ static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fctx)
return 0;
}
-static int fuse_ctl_get_tree(struct fs_context *fc)
+static int fuse_ctl_get_tree(struct fs_context *fsc)
{
- return get_tree_single(fc, fuse_ctl_fill_super);
+ return get_tree_single(fsc, fuse_ctl_fill_super);
}
static const struct fs_context_operations fuse_ctl_context_ops = {
.get_tree = fuse_ctl_get_tree,
};
-static int fuse_ctl_init_fs_context(struct fs_context *fc)
+static int fuse_ctl_init_fs_context(struct fs_context *fsc)
{
- fc->ops = &fuse_ctl_context_ops;
+ fsc->ops = &fuse_ctl_context_ops;
return 0;
}
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 1c8f79b3dd06..dde341a6388a 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -288,10 +288,10 @@ void fuse_request_end(struct fuse_req *req)
/*
* test_and_set_bit() implies smp_mb() between bit
- * changing and below intr_entry check. Pairs with
+ * changing and below FR_INTERRUPTED check. Pairs with
* smp_mb() from queue_interrupt().
*/
- if (!list_empty(&req->intr_entry)) {
+ if (test_bit(FR_INTERRUPTED, &req->flags)) {
spin_lock(&fiq->lock);
list_del_init(&req->intr_entry);
spin_unlock(&fiq->lock);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 621a662c19fb..11404f8c21c7 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -198,12 +198,11 @@ void fuse_finish_open(struct inode *inode, struct file *file)
struct fuse_file *ff = file->private_data;
struct fuse_conn *fc = get_fuse_conn(inode);
- if (!(ff->open_flags & FOPEN_KEEP_CACHE))
- invalidate_inode_pages2(inode->i_mapping);
if (ff->open_flags & FOPEN_STREAM)
stream_open(inode, file);
else if (ff->open_flags & FOPEN_NONSEEKABLE)
nonseekable_open(inode, file);
+
if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
struct fuse_inode *fi = get_fuse_inode(inode);
@@ -211,10 +210,14 @@ void fuse_finish_open(struct inode *inode, struct file *file)
fi->attr_version = atomic64_inc_return(&fc->attr_version);
i_size_write(inode, 0);
spin_unlock(&fi->lock);
+ truncate_pagecache(inode, 0);
fuse_invalidate_attr(inode);
if (fc->writeback_cache)
file_update_time(file);
+ } else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) {
+ invalidate_inode_pages2(inode->i_mapping);
}
+
if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
fuse_link_write_file(file);
}
@@ -389,6 +392,7 @@ struct fuse_writepage_args {
struct list_head queue_entry;
struct fuse_writepage_args *next;
struct inode *inode;
+ struct fuse_sync_bucket *bucket;
};
static struct fuse_writepage_args *fuse_find_writeback(struct fuse_inode *fi,
@@ -1608,6 +1612,9 @@ static void fuse_writepage_free(struct fuse_writepage_args *wpa)
struct fuse_args_pages *ap = &wpa->ia.ap;
int i;
+ if (wpa->bucket)
+ fuse_sync_bucket_dec(wpa->bucket);
+
for (i = 0; i < ap->num_pages; i++)
__free_page(ap->pages[i]);
@@ -1813,8 +1820,7 @@ static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args,
fuse_writepage_free(wpa);
}
-static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
- struct fuse_inode *fi)
+static struct fuse_file *__fuse_write_file_get(struct fuse_inode *fi)
{
struct fuse_file *ff = NULL;
@@ -1829,22 +1835,20 @@ static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
return ff;
}
-static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
- struct fuse_inode *fi)
+static struct fuse_file *fuse_write_file_get(struct fuse_inode *fi)
{
- struct fuse_file *ff = __fuse_write_file_get(fc, fi);
+ struct fuse_file *ff = __fuse_write_file_get(fi);
WARN_ON(!ff);
return ff;
}
int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
{
- struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_file *ff;
int err;
- ff = __fuse_write_file_get(fc, fi);
+ ff = __fuse_write_file_get(fi);
err = fuse_flush_times(inode, ff);
if (ff)
fuse_file_put(ff, false, false);
@@ -1871,6 +1875,20 @@ static struct fuse_writepage_args *fuse_writepage_args_alloc(void)
}
+static void fuse_writepage_add_to_bucket(struct fuse_conn *fc,
+ struct fuse_writepage_args *wpa)
+{
+ if (!fc->sync_fs)
+ return;
+
+ rcu_read_lock();
+ /* Prevent resurrection of dead bucket in unlikely race with syncfs */
+ do {
+ wpa->bucket = rcu_dereference(fc->curr_bucket);
+ } while (unlikely(!atomic_inc_not_zero(&wpa->bucket->count)));
+ rcu_read_unlock();
+}
+
static int fuse_writepage_locked(struct page *page)
{
struct address_space *mapping = page->mapping;
@@ -1894,10 +1912,11 @@ static int fuse_writepage_locked(struct page *page)
goto err_free;
error = -EIO;
- wpa->ia.ff = fuse_write_file_get(fc, fi);
+ wpa->ia.ff = fuse_write_file_get(fi);
if (!wpa->ia.ff)
goto err_nofile;
+ fuse_writepage_add_to_bucket(fc, wpa);
fuse_write_args_fill(&wpa->ia, wpa->ia.ff, page_offset(page), 0);
copy_highpage(tmp_page, page);
@@ -2113,7 +2132,7 @@ static int fuse_writepages_fill(struct page *page,
if (!data->ff) {
err = -EIO;
- data->ff = fuse_write_file_get(fc, fi);
+ data->ff = fuse_write_file_get(fi);
if (!data->ff)
goto out_unlock;
}
@@ -2148,6 +2167,8 @@ static int fuse_writepages_fill(struct page *page,
__free_page(tmp_page);
goto out_unlock;
}
+ fuse_writepage_add_to_bucket(fc, wpa);
+
data->max_pages = 1;
ap = &wpa->ia.ap;
@@ -2881,7 +2902,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
static int fuse_writeback_range(struct inode *inode, loff_t start, loff_t end)
{
- int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+ int err = filemap_write_and_wait_range(inode->i_mapping, start, -1);
if (!err)
fuse_sync_writes(inode);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 6fb639b97ea8..319596df5dc6 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -482,6 +482,7 @@ struct fuse_dev {
struct fuse_fs_context {
int fd;
+ struct file *file;
unsigned int rootmode;
kuid_t user_id;
kgid_t group_id;
@@ -508,6 +509,13 @@ struct fuse_fs_context {
void **fudptr;
};
+struct fuse_sync_bucket {
+ /* count is a possible scalability bottleneck */
+ atomic_t count;
+ wait_queue_head_t waitq;
+ struct rcu_head rcu;
+};
+
/**
* A Fuse connection.
*
@@ -800,6 +808,9 @@ struct fuse_conn {
/** List of filesystems using this connection */
struct list_head mounts;
+
+ /* New writepages go into this bucket */
+ struct fuse_sync_bucket __rcu *curr_bucket;
};
/*
@@ -903,6 +914,15 @@ static inline void fuse_page_descs_length_init(struct fuse_page_desc *descs,
descs[i].length = PAGE_SIZE - descs[i].offset;
}
+static inline void fuse_sync_bucket_dec(struct fuse_sync_bucket *bucket)
+{
+ /* Need RCU protection to prevent use after free after the decrement */
+ rcu_read_lock();
+ if (atomic_dec_and_test(&bucket->count))
+ wake_up(&bucket->waitq);
+ rcu_read_unlock();
+}
+
/** Device operations */
extern const struct file_operations fuse_dev_operations;
@@ -1209,7 +1229,7 @@ extern const struct xattr_handler *fuse_acl_xattr_handlers[];
extern const struct xattr_handler *fuse_no_acl_xattr_handlers[];
struct posix_acl;
-struct posix_acl *fuse_get_acl(struct inode *inode, int type);
+struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu);
int fuse_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e07e429f32e1..36cd03114b6d 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -137,12 +137,12 @@ static void fuse_evict_inode(struct inode *inode)
}
}
-static int fuse_reconfigure(struct fs_context *fc)
+static int fuse_reconfigure(struct fs_context *fsc)
{
- struct super_block *sb = fc->root->d_sb;
+ struct super_block *sb = fsc->root->d_sb;
sync_filesystem(sb);
- if (fc->sb_flags & SB_MANDLOCK)
+ if (fsc->sb_flags & SB_MANDLOCK)
return -EINVAL;
return 0;
@@ -505,6 +505,57 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
return err;
}
+static struct fuse_sync_bucket *fuse_sync_bucket_alloc(void)
+{
+ struct fuse_sync_bucket *bucket;
+
+ bucket = kzalloc(sizeof(*bucket), GFP_KERNEL | __GFP_NOFAIL);
+ if (bucket) {
+ init_waitqueue_head(&bucket->waitq);
+ /* Initial active count */
+ atomic_set(&bucket->count, 1);
+ }
+ return bucket;
+}
+
+static void fuse_sync_fs_writes(struct fuse_conn *fc)
+{
+ struct fuse_sync_bucket *bucket, *new_bucket;
+ int count;
+
+ new_bucket = fuse_sync_bucket_alloc();
+ spin_lock(&fc->lock);
+ bucket = rcu_dereference_protected(fc->curr_bucket, 1);
+ count = atomic_read(&bucket->count);
+ WARN_ON(count < 1);
+ /* No outstanding writes? */
+ if (count == 1) {
+ spin_unlock(&fc->lock);
+ kfree(new_bucket);
+ return;
+ }
+
+ /*
+ * Completion of new bucket depends on completion of this bucket, so add
+ * one more count.
+ */
+ atomic_inc(&new_bucket->count);
+ rcu_assign_pointer(fc->curr_bucket, new_bucket);
+ spin_unlock(&fc->lock);
+ /*
+ * Drop initial active count. At this point if all writes in this and
+ * ancestor buckets complete, the count will go to zero and this task
+ * will be woken up.
+ */
+ atomic_dec(&bucket->count);
+
+ wait_event(bucket->waitq, atomic_read(&bucket->count) == 0);
+
+ /* Drop temp count on descendant bucket */
+ fuse_sync_bucket_dec(new_bucket);
+ kfree_rcu(bucket, rcu);
+}
+
static int fuse_sync_fs(struct super_block *sb, int wait)
{
struct fuse_mount *fm = get_fuse_mount_super(sb);
@@ -527,6 +578,8 @@ static int fuse_sync_fs(struct super_block *sb, int wait)
if (!fc->sync_fs)
return 0;
+ fuse_sync_fs_writes(fc);
+
memset(&inarg, 0, sizeof(inarg));
args.in_numargs = 1;
args.in_args[0].size = sizeof(inarg);
@@ -572,38 +625,38 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
{}
};
-static int fuse_parse_param(struct fs_context *fc, struct fs_parameter *param)
+static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
{
struct fs_parse_result result;
- struct fuse_fs_context *ctx = fc->fs_private;
+ struct fuse_fs_context *ctx = fsc->fs_private;
int opt;
- if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
+ if (fsc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
/*
* Ignore options coming from mount(MS_REMOUNT) for backward
* compatibility.
*/
- if (fc->oldapi)
+ if (fsc->oldapi)
return 0;
- return invalfc(fc, "No changes allowed in reconfigure");
+ return invalfc(fsc, "No changes allowed in reconfigure");
}
- opt = fs_parse(fc, fuse_fs_parameters, param, &result);
+ opt = fs_parse(fsc, fuse_fs_parameters, param, &result);
if (opt < 0)
return opt;
switch (opt) {
case OPT_SOURCE:
- if (fc->source)
- return invalfc(fc, "Multiple sources specified");
- fc->source = param->string;
+ if (fsc->source)
+ return invalfc(fsc, "Multiple sources specified");
+ fsc->source = param->string;
param->string = NULL;
break;
case OPT_SUBTYPE:
if (ctx->subtype)
- return invalfc(fc, "Multiple subtypes specified");
+ return invalfc(fsc, "Multiple subtypes specified");
ctx->subtype = param->string;
param->string = NULL;
return 0;
@@ -615,22 +668,22 @@ static int fuse_parse_param(struct fs_context *fc, struct fs_parameter *param)
case OPT_ROOTMODE:
if (!fuse_valid_type(result.uint_32))
- return invalfc(fc, "Invalid rootmode");
+ return invalfc(fsc, "Invalid rootmode");
ctx->rootmode = result.uint_32;
ctx->rootmode_present = true;
break;
case OPT_USER_ID:
- ctx->user_id = make_kuid(fc->user_ns, result.uint_32);
+ ctx->user_id = make_kuid(fsc->user_ns, result.uint_32);
if (!uid_valid(ctx->user_id))
- return invalfc(fc, "Invalid user_id");
+ return invalfc(fsc, "Invalid user_id");
ctx->user_id_present = true;
break;
case OPT_GROUP_ID:
- ctx->group_id = make_kgid(fc->user_ns, result.uint_32);
+ ctx->group_id = make_kgid(fsc->user_ns, result.uint_32);
if (!gid_valid(ctx->group_id))
- return invalfc(fc, "Invalid group_id");
+ return invalfc(fsc, "Invalid group_id");
ctx->group_id_present = true;
break;
@@ -648,7 +701,7 @@ static int fuse_parse_param(struct fs_context *fc, struct fs_parameter *param)
case OPT_BLKSIZE:
if (!ctx->is_bdev)
- return invalfc(fc, "blksize only supported for fuseblk");
+ return invalfc(fsc, "blksize only supported for fuseblk");
ctx->blksize = result.uint_32;
break;
@@ -659,9 +712,9 @@ static int fuse_parse_param(struct fs_context *fc, struct fs_parameter *param)
return 0;
}
-static void fuse_free_fc(struct fs_context *fc)
+static void fuse_free_fsc(struct fs_context *fsc)
{
- struct fuse_fs_context *ctx = fc->fs_private;
+ struct fuse_fs_context *ctx = fsc->fs_private;
if (ctx) {
kfree(ctx->subtype);
@@ -762,6 +815,7 @@ void fuse_conn_put(struct fuse_conn *fc)
{
if (refcount_dec_and_test(&fc->count)) {
struct fuse_iqueue *fiq = &fc->iq;
+ struct fuse_sync_bucket *bucket;
if (IS_ENABLED(CONFIG_FUSE_DAX))
fuse_dax_conn_free(fc);
@@ -769,6 +823,11 @@ void fuse_conn_put(struct fuse_conn *fc)
fiq->ops->release(fiq);
put_pid_ns(fc->pid_ns);
put_user_ns(fc->user_ns);
+ bucket = rcu_dereference_protected(fc->curr_bucket, 1);
+ if (bucket) {
+ WARN_ON(atomic_read(&bucket->count) != 1);
+ kfree(bucket);
+ }
fc->release(fc);
}
}
@@ -1417,6 +1476,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
if (sb->s_flags & SB_MANDLOCK)
goto err;
+ rcu_assign_pointer(fc->curr_bucket, fuse_sync_bucket_alloc());
fuse_sb_defaults(sb);
if (ctx->is_bdev) {
@@ -1508,34 +1568,33 @@ EXPORT_SYMBOL_GPL(fuse_fill_super_common);
static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
{
struct fuse_fs_context *ctx = fsc->fs_private;
- struct file *file;
int err;
struct fuse_conn *fc;
struct fuse_mount *fm;
- err = -EINVAL;
- file = fget(ctx->fd);
- if (!file)
- goto err;
+ if (!ctx->file || !ctx->rootmode_present ||
+ !ctx->user_id_present || !ctx->group_id_present)
+ return -EINVAL;
/*
* Require mount to happen from the same user namespace which
* opened /dev/fuse to prevent potential attacks.
*/
- if ((file->f_op != &fuse_dev_operations) ||
- (file->f_cred->user_ns != sb->s_user_ns))
- goto err_fput;
- ctx->fudptr = &file->private_data;
+ err = -EINVAL;
+ if ((ctx->file->f_op != &fuse_dev_operations) ||
+ (ctx->file->f_cred->user_ns != sb->s_user_ns))
+ goto err;
+ ctx->fudptr = &ctx->file->private_data;
fc = kmalloc(sizeof(*fc), GFP_KERNEL);
err = -ENOMEM;
if (!fc)
- goto err_fput;
+ goto err;
fm = kzalloc(sizeof(*fm), GFP_KERNEL);
if (!fm) {
kfree(fc);
- goto err_fput;
+ goto err;
}
fuse_conn_init(fc, fm, sb->s_user_ns, &fuse_dev_fiq_ops, NULL);
@@ -1546,12 +1605,8 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
err = fuse_fill_super_common(sb, ctx);
if (err)
goto err_put_conn;
- /*
- * atomic_dec_and_test() in fput() provides the necessary
- * memory barrier for file->private_data to be visible on all
- * CPUs after this
- */
- fput(file);
+ /* file->private_data shall be visible on all CPUs after this */
+ smp_mb();
fuse_send_init(get_fuse_mount_super(sb));
return 0;
@@ -1559,30 +1614,68 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
fuse_conn_put(fc);
kfree(fm);
sb->s_fs_info = NULL;
- err_fput:
- fput(file);
err:
return err;
}
-static int fuse_get_tree(struct fs_context *fc)
+/*
+ * This is the path where user supplied an already initialized fuse dev. In
+ * this case never create a new super if the old one is gone.
+ */
+static int fuse_set_no_super(struct super_block *sb, struct fs_context *fsc)
{
- struct fuse_fs_context *ctx = fc->fs_private;
+ return -ENOTCONN;
+}
- if (!ctx->fd_present || !ctx->rootmode_present ||
- !ctx->user_id_present || !ctx->group_id_present)
- return -EINVAL;
+static int fuse_test_super(struct super_block *sb, struct fs_context *fsc)
+{
-#ifdef CONFIG_BLOCK
- if (ctx->is_bdev)
- return get_tree_bdev(fc, fuse_fill_super);
-#endif
+ return fsc->sget_key == get_fuse_conn_super(sb);
+}
+
+static int fuse_get_tree(struct fs_context *fsc)
+{
+ struct fuse_fs_context *ctx = fsc->fs_private;
+ struct fuse_dev *fud;
+ struct super_block *sb;
+ int err;
- return get_tree_nodev(fc, fuse_fill_super);
+ if (ctx->fd_present)
+ ctx->file = fget(ctx->fd);
+
+ if (IS_ENABLED(CONFIG_BLOCK) && ctx->is_bdev) {
+ err = get_tree_bdev(fsc, fuse_fill_super);
+ goto out_fput;
+ }
+ /*
+ * While block dev mount can be initialized with a dummy device fd
+ * (found by device name), normal fuse mounts can't
+ */
+ if (!ctx->file)
+ return -EINVAL;
+
+ /*
+ * Allow creating a fuse mount with an already initialized fuse
+ * connection
+ */
+ fud = READ_ONCE(ctx->file->private_data);
+ if (ctx->file->f_op == &fuse_dev_operations && fud) {
+ fsc->sget_key = fud->fc;
+ sb = sget_fc(fsc, fuse_test_super, fuse_set_no_super);
+ err = PTR_ERR_OR_ZERO(sb);
+ if (!IS_ERR(sb))
+ fsc->root = dget(sb->s_root);
+ } else {
+ err = get_tree_nodev(fsc, fuse_fill_super);
+ }
+out_fput:
+ if (ctx->file)
+ fput(ctx->file);
+ return err;
}
static const struct fs_context_operations fuse_context_ops = {
- .free = fuse_free_fc,
+ .free = fuse_free_fsc,
.parse_param = fuse_parse_param,
.reconfigure = fuse_reconfigure,
.get_tree = fuse_get_tree,
@@ -1591,7 +1684,7 @@ static const struct fs_context_operations fuse_context_ops = {
/*
* Set up the filesystem mount context.
*/
-static int fuse_init_fs_context(struct fs_context *fc)
+static int fuse_init_fs_context(struct fs_context *fsc)
{
struct fuse_fs_context *ctx;
@@ -1604,14 +1697,14 @@ static int fuse_init_fs_context(struct fs_context *fc)
ctx->legacy_opts_show = true;
#ifdef CONFIG_BLOCK
- if (fc->fs_type == &fuseblk_fs_type) {
+ if (fsc->fs_type == &fuseblk_fs_type) {
ctx->is_bdev = true;
ctx->destroy = true;
}
#endif
- fc->fs_private = ctx;
- fc->ops = &fuse_context_ops;
+ fsc->fs_private = ctx;
+ fsc->ops = &fuse_context_ops;
return 0;
}
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 8f52cdaa8445..0ad89c6629d7 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -97,14 +97,14 @@ static const struct fs_parameter_spec virtio_fs_parameters[] = {
{}
};
-static int virtio_fs_parse_param(struct fs_context *fc,
+static int virtio_fs_parse_param(struct fs_context *fsc,
struct fs_parameter *param)
{
struct fs_parse_result result;
- struct fuse_fs_context *ctx = fc->fs_private;
+ struct fuse_fs_context *ctx = fsc->fs_private;
int opt;
- opt = fs_parse(fc, virtio_fs_parameters, param, &result);
+ opt = fs_parse(fsc, virtio_fs_parameters, param, &result);
if (opt < 0)
return opt;
@@ -119,9 +119,9 @@ static int virtio_fs_parse_param(struct fs_context *fc,
return 0;
}
-static void virtio_fs_free_fc(struct fs_context *fc)
+static void virtio_fs_free_fsc(struct fs_context *fsc)
{
- struct fuse_fs_context *ctx = fc->fs_private;
+ struct fuse_fs_context *ctx = fsc->fs_private;
kfree(ctx);
}
@@ -1488,7 +1488,7 @@ out_err:
}
static const struct fs_context_operations virtio_fs_context_ops = {
- .free = virtio_fs_free_fc,
+ .free = virtio_fs_free_fsc,
.parse_param = virtio_fs_parse_param,
.get_tree = virtio_fs_get_tree,
};
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 9165d70ead07..734d1f05d823 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -57,13 +57,16 @@ static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type)
return acl;
}
-struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
+struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder gh;
bool need_unlock = false;
struct posix_acl *acl;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
LM_FLAG_ANY, &gh);
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h
index eccc6a43326c..cd180ca7c959 100644
--- a/fs/gfs2/acl.h
+++ b/fs/gfs2/acl.h
@@ -11,7 +11,7 @@
#define GFS2_ACL_MAX_ENTRIES(sdp) ((300 << (sdp)->sd_sb.sb_bsize_shift) >> 12)
-extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type);
+extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu);
extern int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
extern int gfs2_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
diff --git a/fs/inode.c b/fs/inode.c
index 84c528cd1955..37710ca863b5 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -770,7 +770,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
return LRU_ROTATE;
}
- if (inode_has_buffers(inode) || inode->i_data.nrpages) {
+ if (inode_has_buffers(inode) || !mapping_empty(&inode->i_data)) {
__iget(inode);
spin_unlock(&inode->i_lock);
spin_unlock(lru_lock);
diff --git a/fs/io-wq.c b/fs/io-wq.c
index cd9bd095fb1b..d80e4a735677 100644
--- a/fs/io-wq.c
+++ b/fs/io-wq.c
@@ -23,8 +23,7 @@ enum {
IO_WORKER_F_UP = 1, /* up and active */
IO_WORKER_F_RUNNING = 2, /* account as running */
IO_WORKER_F_FREE = 4, /* worker on free list */
- IO_WORKER_F_FIXED = 8, /* static idle worker */
- IO_WORKER_F_BOUND = 16, /* is doing bounded work */
+ IO_WORKER_F_BOUND = 8, /* is doing bounded work */
};
enum {
@@ -32,7 +31,7 @@ enum {
};
enum {
- IO_WQE_FLAG_STALLED = 1, /* stalled on hash */
+ IO_ACCT_STALLED_BIT = 0, /* stalled on hash */
};
/*
@@ -55,7 +54,10 @@ struct io_worker {
struct callback_head create_work;
int create_index;
- struct rcu_head rcu;
+ union {
+ struct rcu_head rcu;
+ struct work_struct work;
+ };
};
#if BITS_PER_LONG == 64
@@ -71,25 +73,24 @@ struct io_wqe_acct {
unsigned max_workers;
int index;
atomic_t nr_running;
+ struct io_wq_work_list work_list;
+ unsigned long flags;
};
enum {
IO_WQ_ACCT_BOUND,
IO_WQ_ACCT_UNBOUND,
+ IO_WQ_ACCT_NR,
};
/*
* Per-node worker thread pool
*/
struct io_wqe {
- struct {
- raw_spinlock_t lock;
- struct io_wq_work_list work_list;
- unsigned flags;
- } ____cacheline_aligned_in_smp;
+ raw_spinlock_t lock;
+ struct io_wqe_acct acct[2];
int node;
- struct io_wqe_acct acct[2];
struct hlist_nulls_head free_list;
struct list_head all_list;
@@ -133,8 +134,11 @@ struct io_cb_cancel_data {
bool cancel_all;
};
-static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index, bool first);
+static bool create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index);
static void io_wqe_dec_running(struct io_worker *worker);
+static bool io_acct_cancel_pending_work(struct io_wqe *wqe,
+ struct io_wqe_acct *acct,
+ struct io_cb_cancel_data *match);
static bool io_worker_get(struct io_worker *worker)
{
@@ -195,11 +199,10 @@ static void io_worker_exit(struct io_worker *worker)
do_exit(0);
}
-static inline bool io_wqe_run_queue(struct io_wqe *wqe)
- __must_hold(wqe->lock)
+static inline bool io_acct_run_queue(struct io_wqe_acct *acct)
{
- if (!wq_list_empty(&wqe->work_list) &&
- !(wqe->flags & IO_WQE_FLAG_STALLED))
+ if (!wq_list_empty(&acct->work_list) &&
+ !test_bit(IO_ACCT_STALLED_BIT, &acct->flags))
return true;
return false;
}
@@ -208,7 +211,8 @@ static inline bool io_wqe_run_queue(struct io_wqe *wqe)
* Check head of free list for an available worker. If one isn't available,
* caller must create one.
*/
-static bool io_wqe_activate_free_worker(struct io_wqe *wqe)
+static bool io_wqe_activate_free_worker(struct io_wqe *wqe,
+ struct io_wqe_acct *acct)
__must_hold(RCU)
{
struct hlist_nulls_node *n;
@@ -222,6 +226,10 @@ static bool io_wqe_activate_free_worker(struct io_wqe *wqe)
hlist_nulls_for_each_entry_rcu(worker, n, &wqe->free_list, nulls_node) {
if (!io_worker_get(worker))
continue;
+ if (io_wqe_get_acct(worker) != acct) {
+ io_worker_release(worker);
+ continue;
+ }
if (wake_up_process(worker->task)) {
io_worker_release(worker);
return true;
@@ -236,9 +244,9 @@ static bool io_wqe_activate_free_worker(struct io_wqe *wqe)
* We need a worker. If we find a free one, we're good. If not, and we're
* below the max number of workers, create one.
*/
-static void io_wqe_wake_worker(struct io_wqe *wqe, struct io_wqe_acct *acct)
+static bool io_wqe_create_worker(struct io_wqe *wqe, struct io_wqe_acct *acct)
{
- bool ret;
+ bool do_create = false;
/*
* Most likely an attempt to queue unbounded work on an io_wq that
@@ -247,27 +255,19 @@ static void io_wqe_wake_worker(struct io_wqe *wqe, struct io_wqe_acct *acct)
if (unlikely(!acct->max_workers))
pr_warn_once("io-wq is not configured for unbound workers");
- rcu_read_lock();
- ret = io_wqe_activate_free_worker(wqe);
- rcu_read_unlock();
-
- if (!ret) {
- bool do_create = false, first = false;
-
- raw_spin_lock(&wqe->lock);
- if (acct->nr_workers < acct->max_workers) {
- if (!acct->nr_workers)
- first = true;
- acct->nr_workers++;
- do_create = true;
- }
- raw_spin_unlock(&wqe->lock);
- if (do_create) {
- atomic_inc(&acct->nr_running);
- atomic_inc(&wqe->wq->worker_refs);
- create_io_worker(wqe->wq, wqe, acct->index, first);
- }
+ raw_spin_lock(&wqe->lock);
+ if (acct->nr_workers < acct->max_workers) {
+ acct->nr_workers++;
+ do_create = true;
}
+ raw_spin_unlock(&wqe->lock);
+ if (do_create) {
+ atomic_inc(&acct->nr_running);
+ atomic_inc(&wqe->wq->worker_refs);
+ return create_io_worker(wqe->wq, wqe, acct->index);
+ }
+
+ return true;
}
static void io_wqe_inc_running(struct io_worker *worker)
@@ -283,7 +283,7 @@ static void create_worker_cb(struct callback_head *cb)
struct io_wq *wq;
struct io_wqe *wqe;
struct io_wqe_acct *acct;
- bool do_create = false, first = false;
+ bool do_create = false;
worker = container_of(cb, struct io_worker, create_work);
wqe = worker->wqe;
@@ -291,14 +291,12 @@ static void create_worker_cb(struct callback_head *cb)
acct = &wqe->acct[worker->create_index];
raw_spin_lock(&wqe->lock);
if (acct->nr_workers < acct->max_workers) {
- if (!acct->nr_workers)
- first = true;
acct->nr_workers++;
do_create = true;
}
raw_spin_unlock(&wqe->lock);
if (do_create) {
- create_io_worker(wq, wqe, worker->create_index, first);
+ create_io_worker(wq, wqe, worker->create_index);
} else {
atomic_dec(&acct->nr_running);
io_worker_ref_put(wq);
@@ -307,9 +305,11 @@ static void create_worker_cb(struct callback_head *cb)
io_worker_release(worker);
}
-static void io_queue_worker_create(struct io_wqe *wqe, struct io_worker *worker,
- struct io_wqe_acct *acct)
+static bool io_queue_worker_create(struct io_worker *worker,
+ struct io_wqe_acct *acct,
+ task_work_func_t func)
{
+ struct io_wqe *wqe = worker->wqe;
struct io_wq *wq = wqe->wq;
/* raced with exit, just ignore create call */
@@ -327,16 +327,17 @@ static void io_queue_worker_create(struct io_wqe *wqe, struct io_worker *worker,
test_and_set_bit_lock(0, &worker->create_state))
goto fail_release;
- init_task_work(&worker->create_work, create_worker_cb);
+ init_task_work(&worker->create_work, func);
worker->create_index = acct->index;
if (!task_work_add(wq->task, &worker->create_work, TWA_SIGNAL))
- return;
+ return true;
clear_bit_unlock(0, &worker->create_state);
fail_release:
io_worker_release(worker);
fail:
atomic_dec(&acct->nr_running);
io_worker_ref_put(wq);
+ return false;
}
static void io_wqe_dec_running(struct io_worker *worker)
@@ -348,10 +349,10 @@ static void io_wqe_dec_running(struct io_worker *worker)
if (!(worker->flags & IO_WORKER_F_UP))
return;
- if (atomic_dec_and_test(&acct->nr_running) && io_wqe_run_queue(wqe)) {
+ if (atomic_dec_and_test(&acct->nr_running) && io_acct_run_queue(acct)) {
atomic_inc(&acct->nr_running);
atomic_inc(&wqe->wq->worker_refs);
- io_queue_worker_create(wqe, worker, acct);
+ io_queue_worker_create(worker, acct, create_worker_cb);
}
}
@@ -363,29 +364,10 @@ static void __io_worker_busy(struct io_wqe *wqe, struct io_worker *worker,
struct io_wq_work *work)
__must_hold(wqe->lock)
{
- bool worker_bound, work_bound;
-
- BUILD_BUG_ON((IO_WQ_ACCT_UNBOUND ^ IO_WQ_ACCT_BOUND) != 1);
-
if (worker->flags & IO_WORKER_F_FREE) {
worker->flags &= ~IO_WORKER_F_FREE;
hlist_nulls_del_init_rcu(&worker->nulls_node);
}
-
- /*
- * If worker is moving from bound to unbound (or vice versa), then
- * ensure we update the running accounting.
- */
- worker_bound = (worker->flags & IO_WORKER_F_BOUND) != 0;
- work_bound = (work->flags & IO_WQ_WORK_UNBOUND) == 0;
- if (worker_bound != work_bound) {
- int index = work_bound ? IO_WQ_ACCT_UNBOUND : IO_WQ_ACCT_BOUND;
- io_wqe_dec_running(worker);
- worker->flags ^= IO_WORKER_F_BOUND;
- wqe->acct[index].nr_workers--;
- wqe->acct[index ^ 1].nr_workers++;
- io_wqe_inc_running(worker);
- }
}
/*
@@ -413,7 +395,7 @@ static void io_wait_on_hash(struct io_wqe *wqe, unsigned int hash)
{
struct io_wq *wq = wqe->wq;
- spin_lock(&wq->hash->wait.lock);
+ spin_lock_irq(&wq->hash->wait.lock);
if (list_empty(&wqe->wait.entry)) {
__add_wait_queue(&wq->hash->wait, &wqe->wait);
if (!test_bit(hash, &wq->hash->map)) {
@@ -421,48 +403,26 @@ static void io_wait_on_hash(struct io_wqe *wqe, unsigned int hash)
list_del_init(&wqe->wait.entry);
}
}
- spin_unlock(&wq->hash->wait.lock);
-}
-
-/*
- * We can always run the work if the worker is currently the same type as
- * the work (eg both are bound, or both are unbound). If they are not the
- * same, only allow it if incrementing the worker count would be allowed.
- */
-static bool io_worker_can_run_work(struct io_worker *worker,
- struct io_wq_work *work)
-{
- struct io_wqe_acct *acct;
-
- if (!(worker->flags & IO_WORKER_F_BOUND) !=
- !(work->flags & IO_WQ_WORK_UNBOUND))
- return true;
-
- /* not the same type, check if we'd go over the limit */
- acct = io_work_get_acct(worker->wqe, work);
- return acct->nr_workers < acct->max_workers;
+ spin_unlock_irq(&wq->hash->wait.lock);
}
-static struct io_wq_work *io_get_next_work(struct io_wqe *wqe,
- struct io_worker *worker,
- bool *stalled)
+static struct io_wq_work *io_get_next_work(struct io_wqe_acct *acct,
+ struct io_worker *worker)
__must_hold(wqe->lock)
{
struct io_wq_work_node *node, *prev;
struct io_wq_work *work, *tail;
unsigned int stall_hash = -1U;
+ struct io_wqe *wqe = worker->wqe;
- wq_list_for_each(node, prev, &wqe->work_list) {
+ wq_list_for_each(node, prev, &acct->work_list) {
unsigned int hash;
work = container_of(node, struct io_wq_work, list);
- if (!io_worker_can_run_work(worker, work))
- break;
-
/* not hashed, can run anytime */
if (!io_wq_is_hashed(work)) {
- wq_list_del(&wqe->work_list, node, prev);
+ wq_list_del(&acct->work_list, node, prev);
return work;
}
@@ -473,7 +433,7 @@ static struct io_wq_work *io_get_next_work(struct io_wqe *wqe,
/* hashed, can run if not already running */
if (!test_and_set_bit(hash, &wqe->wq->hash->map)) {
wqe->hash_tail[hash] = NULL;
- wq_list_cut(&wqe->work_list, &tail->list, prev);
+ wq_list_cut(&acct->work_list, &tail->list, prev);
return work;
}
if (stall_hash == -1U)
@@ -483,10 +443,14 @@ static struct io_wq_work *io_get_next_work(struct io_wqe *wqe,
}
if (stall_hash != -1U) {
+ /*
+ * Set this before dropping the lock to avoid racing with new
+ * work being added and clearing the stalled bit.
+ */
+ set_bit(IO_ACCT_STALLED_BIT, &acct->flags);
raw_spin_unlock(&wqe->lock);
io_wait_on_hash(wqe, stall_hash);
raw_spin_lock(&wqe->lock);
- *stalled = true;
}
return NULL;
@@ -520,13 +484,13 @@ static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work);
static void io_worker_handle_work(struct io_worker *worker)
__releases(wqe->lock)
{
+ struct io_wqe_acct *acct = io_wqe_get_acct(worker);
struct io_wqe *wqe = worker->wqe;
struct io_wq *wq = wqe->wq;
bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state);
do {
struct io_wq_work *work;
- bool stalled;
get_next:
/*
* If we got some work, mark us as busy. If we didn't, but
@@ -535,12 +499,9 @@ get_next:
* can't make progress, any work completion or insertion will
* clear the stalled flag.
*/
- stalled = false;
- work = io_get_next_work(wqe, worker, &stalled);
+ work = io_get_next_work(acct, worker);
if (work)
__io_worker_busy(wqe, worker, work);
- else if (stalled)
- wqe->flags |= IO_WQE_FLAG_STALLED;
raw_spin_unlock(&wqe->lock);
if (!work)
@@ -572,10 +533,10 @@ get_next:
if (hash != -1U && !next_hashed) {
clear_bit(hash, &wq->hash->map);
+ clear_bit(IO_ACCT_STALLED_BIT, &acct->flags);
if (wq_has_sleeper(&wq->hash->wait))
wake_up(&wq->hash->wait);
raw_spin_lock(&wqe->lock);
- wqe->flags &= ~IO_WQE_FLAG_STALLED;
/* skip unnecessary unlock-lock wqe->lock */
if (!work)
goto get_next;
@@ -590,8 +551,10 @@ get_next:
static int io_wqe_worker(void *data)
{
struct io_worker *worker = data;
+ struct io_wqe_acct *acct = io_wqe_get_acct(worker);
struct io_wqe *wqe = worker->wqe;
struct io_wq *wq = wqe->wq;
+ bool last_timeout = false;
char buf[TASK_COMM_LEN];
worker->flags |= (IO_WORKER_F_UP | IO_WORKER_F_RUNNING);
@@ -605,10 +568,17 @@ static int io_wqe_worker(void *data)
set_current_state(TASK_INTERRUPTIBLE);
loop:
raw_spin_lock(&wqe->lock);
- if (io_wqe_run_queue(wqe)) {
+ if (io_acct_run_queue(acct)) {
io_worker_handle_work(worker);
goto loop;
}
+ /* timed out, exit unless we're the last worker */
+ if (last_timeout && acct->nr_workers > 1) {
+ raw_spin_unlock(&wqe->lock);
+ __set_current_state(TASK_RUNNING);
+ break;
+ }
+ last_timeout = false;
__io_worker_idle(wqe, worker);
raw_spin_unlock(&wqe->lock);
if (io_flush_signals())
@@ -619,13 +589,11 @@ loop:
if (!get_signal(&ksig))
continue;
- break;
- }
- if (ret)
+ if (fatal_signal_pending(current))
+ break;
continue;
- /* timed out, exit unless we're the fixed worker */
- if (!(worker->flags & IO_WORKER_F_FIXED))
- break;
+ }
+ last_timeout = !ret;
}
if (test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
@@ -676,7 +644,91 @@ void io_wq_worker_sleeping(struct task_struct *tsk)
raw_spin_unlock(&worker->wqe->lock);
}
-static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index, bool first)
+static void io_init_new_worker(struct io_wqe *wqe, struct io_worker *worker,
+ struct task_struct *tsk)
+{
+ tsk->pf_io_worker = worker;
+ worker->task = tsk;
+ set_cpus_allowed_ptr(tsk, wqe->cpu_mask);
+ tsk->flags |= PF_NO_SETAFFINITY;
+
+ raw_spin_lock(&wqe->lock);
+ hlist_nulls_add_head_rcu(&worker->nulls_node, &wqe->free_list);
+ list_add_tail_rcu(&worker->all_list, &wqe->all_list);
+ worker->flags |= IO_WORKER_F_FREE;
+ raw_spin_unlock(&wqe->lock);
+ wake_up_new_task(tsk);
+}
+
+static bool io_wq_work_match_all(struct io_wq_work *work, void *data)
+{
+ return true;
+}
+
+static inline bool io_should_retry_thread(long err)
+{
+ switch (err) {
+ case -EAGAIN:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ case -ERESTARTNOHAND:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void create_worker_cont(struct callback_head *cb)
+{
+ struct io_worker *worker;
+ struct task_struct *tsk;
+ struct io_wqe *wqe;
+
+ worker = container_of(cb, struct io_worker, create_work);
+ clear_bit_unlock(0, &worker->create_state);
+ wqe = worker->wqe;
+ tsk = create_io_thread(io_wqe_worker, worker, wqe->node);
+ if (!IS_ERR(tsk)) {
+ io_init_new_worker(wqe, worker, tsk);
+ io_worker_release(worker);
+ return;
+ } else if (!io_should_retry_thread(PTR_ERR(tsk))) {
+ struct io_wqe_acct *acct = io_wqe_get_acct(worker);
+
+ atomic_dec(&acct->nr_running);
+ raw_spin_lock(&wqe->lock);
+ acct->nr_workers--;
+ if (!acct->nr_workers) {
+ struct io_cb_cancel_data match = {
+ .fn = io_wq_work_match_all,
+ .cancel_all = true,
+ };
+
+ while (io_acct_cancel_pending_work(wqe, acct, &match))
+ raw_spin_lock(&wqe->lock);
+ }
+ raw_spin_unlock(&wqe->lock);
+ io_worker_ref_put(wqe->wq);
+ return;
+ }
+
+ /* re-create attempts grab a new worker ref, drop the existing one */
+ io_worker_release(worker);
+ schedule_work(&worker->work);
+}
+
+static void io_workqueue_create(struct work_struct *work)
+{
+ struct io_worker *worker = container_of(work, struct io_worker, work);
+ struct io_wqe_acct *acct = io_wqe_get_acct(worker);
+
+ if (!io_queue_worker_create(worker, acct, create_worker_cont)) {
+ clear_bit_unlock(0, &worker->create_state);
+ io_worker_release(worker);
+ }
+}
+
+static bool create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index)
{
struct io_wqe_acct *acct = &wqe->acct[index];
struct io_worker *worker;
@@ -685,42 +737,35 @@ static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index, bo
__set_current_state(TASK_RUNNING);
worker = kzalloc_node(sizeof(*worker), GFP_KERNEL, wqe->node);
- if (!worker)
- goto fail;
-
- refcount_set(&worker->ref, 1);
- worker->nulls_node.pprev = NULL;
- worker->wqe = wqe;
- spin_lock_init(&worker->lock);
- init_completion(&worker->ref_done);
-
- tsk = create_io_thread(io_wqe_worker, worker, wqe->node);
- if (IS_ERR(tsk)) {
- kfree(worker);
+ if (!worker) {
fail:
atomic_dec(&acct->nr_running);
raw_spin_lock(&wqe->lock);
acct->nr_workers--;
raw_spin_unlock(&wqe->lock);
io_worker_ref_put(wq);
- return;
+ return false;
}
- tsk->pf_io_worker = worker;
- worker->task = tsk;
- set_cpus_allowed_ptr(tsk, wqe->cpu_mask);
- tsk->flags |= PF_NO_SETAFFINITY;
+ refcount_set(&worker->ref, 1);
+ worker->wqe = wqe;
+ spin_lock_init(&worker->lock);
+ init_completion(&worker->ref_done);
- raw_spin_lock(&wqe->lock);
- hlist_nulls_add_head_rcu(&worker->nulls_node, &wqe->free_list);
- list_add_tail_rcu(&worker->all_list, &wqe->all_list);
- worker->flags |= IO_WORKER_F_FREE;
if (index == IO_WQ_ACCT_BOUND)
worker->flags |= IO_WORKER_F_BOUND;
- if (first && (worker->flags & IO_WORKER_F_BOUND))
- worker->flags |= IO_WORKER_F_FIXED;
- raw_spin_unlock(&wqe->lock);
- wake_up_new_task(tsk);
+
+ tsk = create_io_thread(io_wqe_worker, worker, wqe->node);
+ if (!IS_ERR(tsk)) {
+ io_init_new_worker(wqe, worker, tsk);
+ } else if (!io_should_retry_thread(PTR_ERR(tsk))) {
+ goto fail;
+ } else {
+ INIT_WORK(&worker->work, io_workqueue_create);
+ schedule_work(&worker->work);
+ }
+
+ return true;
}
/*
@@ -755,11 +800,6 @@ static bool io_wq_worker_wake(struct io_worker *worker, void *data)
return false;
}
-static bool io_wq_work_match_all(struct io_wq_work *work, void *data)
-{
- return true;
-}
-
static void io_run_cancel(struct io_wq_work *work, struct io_wqe *wqe)
{
struct io_wq *wq = wqe->wq;
@@ -773,12 +813,13 @@ static void io_run_cancel(struct io_wq_work *work, struct io_wqe *wqe)
static void io_wqe_insert_work(struct io_wqe *wqe, struct io_wq_work *work)
{
+ struct io_wqe_acct *acct = io_work_get_acct(wqe, work);
unsigned int hash;
struct io_wq_work *tail;
if (!io_wq_is_hashed(work)) {
append:
- wq_list_add_tail(&work->list, &wqe->work_list);
+ wq_list_add_tail(&work->list, &acct->work_list);
return;
}
@@ -788,13 +829,14 @@ append:
if (!tail)
goto append;
- wq_list_add_after(&work->list, &tail->list, &wqe->work_list);
+ wq_list_add_after(&work->list, &tail->list, &acct->work_list);
}
static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work)
{
struct io_wqe_acct *acct = io_work_get_acct(wqe, work);
- bool do_wake;
+ unsigned work_flags = work->flags;
+ bool do_create;
/*
* If io-wq is exiting for this task, or if the request has explicitly
@@ -802,19 +844,36 @@ static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work)
*/
if (test_bit(IO_WQ_BIT_EXIT, &wqe->wq->state) ||
(work->flags & IO_WQ_WORK_CANCEL)) {
+run_cancel:
io_run_cancel(work, wqe);
return;
}
raw_spin_lock(&wqe->lock);
io_wqe_insert_work(wqe, work);
- wqe->flags &= ~IO_WQE_FLAG_STALLED;
- do_wake = (work->flags & IO_WQ_WORK_CONCURRENT) ||
- !atomic_read(&acct->nr_running);
+ clear_bit(IO_ACCT_STALLED_BIT, &acct->flags);
+
+ rcu_read_lock();
+ do_create = !io_wqe_activate_free_worker(wqe, acct);
+ rcu_read_unlock();
+
raw_spin_unlock(&wqe->lock);
- if (do_wake)
- io_wqe_wake_worker(wqe, acct);
+ if (do_create && ((work_flags & IO_WQ_WORK_CONCURRENT) ||
+ !atomic_read(&acct->nr_running))) {
+ bool did_create;
+
+ did_create = io_wqe_create_worker(wqe, acct);
+ if (unlikely(!did_create)) {
+ raw_spin_lock(&wqe->lock);
+ /* fatal condition, failed to create the first worker */
+ if (!acct->nr_workers) {
+ raw_spin_unlock(&wqe->lock);
+ goto run_cancel;
+ }
+ raw_spin_unlock(&wqe->lock);
+ }
+ }
}
void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work)
@@ -859,6 +918,7 @@ static inline void io_wqe_remove_pending(struct io_wqe *wqe,
struct io_wq_work *work,
struct io_wq_work_node *prev)
{
+ struct io_wqe_acct *acct = io_work_get_acct(wqe, work);
unsigned int hash = io_get_work_hash(work);
struct io_wq_work *prev_work = NULL;
@@ -870,18 +930,18 @@ static inline void io_wqe_remove_pending(struct io_wqe *wqe,
else
wqe->hash_tail[hash] = NULL;
}
- wq_list_del(&wqe->work_list, &work->list, prev);
+ wq_list_del(&acct->work_list, &work->list, prev);
}
-static void io_wqe_cancel_pending_work(struct io_wqe *wqe,
- struct io_cb_cancel_data *match)
+static bool io_acct_cancel_pending_work(struct io_wqe *wqe,
+ struct io_wqe_acct *acct,
+ struct io_cb_cancel_data *match)
+ __releases(wqe->lock)
{
struct io_wq_work_node *node, *prev;
struct io_wq_work *work;
-retry:
- raw_spin_lock(&wqe->lock);
- wq_list_for_each(node, prev, &wqe->work_list) {
+ wq_list_for_each(node, prev, &acct->work_list) {
work = container_of(node, struct io_wq_work, list);
if (!match->fn(work, match->data))
continue;
@@ -889,11 +949,27 @@ retry:
raw_spin_unlock(&wqe->lock);
io_run_cancel(work, wqe);
match->nr_pending++;
- if (!match->cancel_all)
- return;
-
/* not safe to continue after unlock */
- goto retry;
+ return true;
+ }
+
+ return false;
+}
+
+static void io_wqe_cancel_pending_work(struct io_wqe *wqe,
+ struct io_cb_cancel_data *match)
+{
+ int i;
+retry:
+ raw_spin_lock(&wqe->lock);
+ for (i = 0; i < IO_WQ_ACCT_NR; i++) {
+ struct io_wqe_acct *acct = io_get_acct(wqe, i == 0);
+
+ if (io_acct_cancel_pending_work(wqe, acct, match)) {
+ if (match->cancel_all)
+ goto retry;
+ return;
+ }
}
raw_spin_unlock(&wqe->lock);
}
@@ -954,18 +1030,24 @@ static int io_wqe_hash_wake(struct wait_queue_entry *wait, unsigned mode,
int sync, void *key)
{
struct io_wqe *wqe = container_of(wait, struct io_wqe, wait);
+ int i;
list_del_init(&wait->entry);
rcu_read_lock();
- io_wqe_activate_free_worker(wqe);
+ for (i = 0; i < IO_WQ_ACCT_NR; i++) {
+ struct io_wqe_acct *acct = &wqe->acct[i];
+
+ if (test_and_clear_bit(IO_ACCT_STALLED_BIT, &acct->flags))
+ io_wqe_activate_free_worker(wqe, acct);
+ }
rcu_read_unlock();
return 1;
}
struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
{
- int ret, node;
+ int ret, node, i;
struct io_wq *wq;
if (WARN_ON_ONCE(!data->free_work || !data->do_work))
@@ -1000,18 +1082,20 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
cpumask_copy(wqe->cpu_mask, cpumask_of_node(node));
wq->wqes[node] = wqe;
wqe->node = alloc_node;
- wqe->acct[IO_WQ_ACCT_BOUND].index = IO_WQ_ACCT_BOUND;
- wqe->acct[IO_WQ_ACCT_UNBOUND].index = IO_WQ_ACCT_UNBOUND;
wqe->acct[IO_WQ_ACCT_BOUND].max_workers = bounded;
- atomic_set(&wqe->acct[IO_WQ_ACCT_BOUND].nr_running, 0);
wqe->acct[IO_WQ_ACCT_UNBOUND].max_workers =
task_rlimit(current, RLIMIT_NPROC);
- atomic_set(&wqe->acct[IO_WQ_ACCT_UNBOUND].nr_running, 0);
- wqe->wait.func = io_wqe_hash_wake;
INIT_LIST_HEAD(&wqe->wait.entry);
+ wqe->wait.func = io_wqe_hash_wake;
+ for (i = 0; i < IO_WQ_ACCT_NR; i++) {
+ struct io_wqe_acct *acct = &wqe->acct[i];
+
+ acct->index = i;
+ atomic_set(&acct->nr_running, 0);
+ INIT_WQ_LIST(&acct->work_list);
+ }
wqe->wq = wq;
raw_spin_lock_init(&wqe->lock);
- INIT_WQ_LIST(&wqe->work_list);
INIT_HLIST_NULLS_HEAD(&wqe->free_list, 0);
INIT_LIST_HEAD(&wqe->all_list);
}
@@ -1038,7 +1122,7 @@ static bool io_task_work_match(struct callback_head *cb, void *data)
{
struct io_worker *worker;
- if (cb->func != create_worker_cb)
+ if (cb->func != create_worker_cb || cb->func != create_worker_cont)
return false;
worker = container_of(cb, struct io_worker, create_work);
return worker->wqe->wq == data;
@@ -1193,7 +1277,7 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count)
for_each_node(node) {
struct io_wqe_acct *acct;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < IO_WQ_ACCT_NR; i++) {
acct = &wq->wqes[node]->acct[i];
prev = max_t(int, acct->max_workers, prev);
if (new_count[i])
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 6f35b1285865..d816c09c88a5 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1021,6 +1021,7 @@ static const struct io_op_def io_op_defs[] = {
},
[IORING_OP_WRITE] = {
.needs_file = 1,
+ .hash_reg_file = 1,
.unbound_nonreg_file = 1,
.pollout = 1,
.plug = 1,
@@ -1851,6 +1852,17 @@ static void io_req_complete_failed(struct io_kiocb *req, long res)
io_req_complete_post(req, res, 0);
}
+static void io_req_complete_fail_submit(struct io_kiocb *req)
+{
+ /*
+ * We don't submit, fail them all, for that replace hardlinks with
+ * normal links. Extra REQ_F_LINK is tolerated.
+ */
+ req->flags &= ~REQ_F_HARDLINK;
+ req->flags |= REQ_F_LINK;
+ io_req_complete_failed(req, req->result);
+}
+
/*
* Don't initialise the fields below on every allocation, but do that in
* advance and keep them valid across allocations.
@@ -2119,6 +2131,9 @@ static void tctx_task_work(struct callback_head *cb)
while (1) {
struct io_wq_work_node *node;
+ if (!tctx->task_list.first && locked && ctx->submit_state.compl_nr)
+ io_submit_flush_completions(ctx);
+
spin_lock_irq(&tctx->task_lock);
node = tctx->task_list.first;
INIT_WQ_LIST(&tctx->task_list);
@@ -2673,7 +2688,7 @@ static void __io_complete_rw(struct io_kiocb *req, long res, long res2,
{
if (__io_complete_rw_common(req, res))
return;
- __io_req_complete(req, 0, req->result, io_put_rw_kbuf(req));
+ __io_req_complete(req, issue_flags, req->result, io_put_rw_kbuf(req));
}
static void io_complete_rw(struct kiocb *kiocb, long res, long res2)
@@ -3410,6 +3425,12 @@ static inline int io_iter_do_read(struct io_kiocb *req, struct iov_iter *iter)
return -EINVAL;
}
+static bool need_read_all(struct io_kiocb *req)
+{
+ return req->flags & REQ_F_ISREG ||
+ S_ISBLK(file_inode(req->file)->i_mode);
+}
+
static int io_read(struct io_kiocb *req, unsigned int issue_flags)
{
struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
@@ -3464,7 +3485,7 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags)
} else if (ret == -EIOCBQUEUED) {
goto out_free;
} else if (ret <= 0 || ret == io_size || !force_nonblock ||
- (req->flags & REQ_F_NOWAIT) || !(req->flags & REQ_F_ISREG)) {
+ (req->flags & REQ_F_NOWAIT) || !need_read_all(req)) {
/* read all, failed, already did sync or don't want to retry */
goto done;
}
@@ -5249,7 +5270,7 @@ static void io_poll_remove_double(struct io_kiocb *req)
}
}
-static bool io_poll_complete(struct io_kiocb *req, __poll_t mask)
+static bool __io_poll_complete(struct io_kiocb *req, __poll_t mask)
__must_hold(&req->ctx->completion_lock)
{
struct io_ring_ctx *ctx = req->ctx;
@@ -5271,10 +5292,19 @@ static bool io_poll_complete(struct io_kiocb *req, __poll_t mask)
if (flags & IORING_CQE_F_MORE)
ctx->cq_extra++;
- io_commit_cqring(ctx);
return !(flags & IORING_CQE_F_MORE);
}
+static inline bool io_poll_complete(struct io_kiocb *req, __poll_t mask)
+ __must_hold(&req->ctx->completion_lock)
+{
+ bool done;
+
+ done = __io_poll_complete(req, mask);
+ io_commit_cqring(req->ctx);
+ return done;
+}
+
static void io_poll_task_func(struct io_kiocb *req, bool *locked)
{
struct io_ring_ctx *ctx = req->ctx;
@@ -5285,7 +5315,7 @@ static void io_poll_task_func(struct io_kiocb *req, bool *locked)
} else {
bool done;
- done = io_poll_complete(req, req->result);
+ done = __io_poll_complete(req, req->result);
if (done) {
io_poll_remove_double(req);
hash_del(&req->hash_node);
@@ -5293,6 +5323,7 @@ static void io_poll_task_func(struct io_kiocb *req, bool *locked)
req->result = 0;
add_wait_queue(req->poll.head, &req->poll.wait);
}
+ io_commit_cqring(ctx);
spin_unlock(&ctx->completion_lock);
io_cqring_ev_posted(ctx);
@@ -6398,6 +6429,11 @@ static bool io_drain_req(struct io_kiocb *req)
int ret;
u32 seq;
+ if (req->flags & REQ_F_FAIL) {
+ io_req_complete_fail_submit(req);
+ return true;
+ }
+
/*
* If we need to drain a request in the middle of a link, drain the
* head request and the next request/link after the current link.
@@ -6914,7 +6950,7 @@ static inline void io_queue_sqe(struct io_kiocb *req)
if (likely(!(req->flags & (REQ_F_FORCE_ASYNC | REQ_F_FAIL)))) {
__io_queue_sqe(req);
} else if (req->flags & REQ_F_FAIL) {
- io_req_complete_failed(req, req->result);
+ io_req_complete_fail_submit(req);
} else {
int ret = io_req_prep_async(req);
@@ -10498,26 +10534,46 @@ static int io_unregister_iowq_aff(struct io_ring_ctx *ctx)
static int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
void __user *arg)
{
- struct io_uring_task *tctx = current->io_uring;
+ struct io_uring_task *tctx = NULL;
+ struct io_sq_data *sqd = NULL;
__u32 new_count[2];
int i, ret;
- if (!tctx || !tctx->io_wq)
- return -EINVAL;
if (copy_from_user(new_count, arg, sizeof(new_count)))
return -EFAULT;
for (i = 0; i < ARRAY_SIZE(new_count); i++)
if (new_count[i] > INT_MAX)
return -EINVAL;
+ if (ctx->flags & IORING_SETUP_SQPOLL) {
+ sqd = ctx->sq_data;
+ if (sqd) {
+ mutex_lock(&sqd->lock);
+ tctx = sqd->thread->io_uring;
+ }
+ } else {
+ tctx = current->io_uring;
+ }
+
+ ret = -EINVAL;
+ if (!tctx || !tctx->io_wq)
+ goto err;
+
ret = io_wq_max_workers(tctx->io_wq, new_count);
if (ret)
- return ret;
+ goto err;
+
+ if (sqd)
+ mutex_unlock(&sqd->lock);
if (copy_to_user(arg, new_count, sizeof(new_count)))
return -EFAULT;
return 0;
+err:
+ if (sqd)
+ mutex_unlock(&sqd->lock);
+ return ret;
}
static bool io_register_op_must_quiesce(int op)
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index d47a0d96bf30..8ca3527189f8 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -179,8 +179,8 @@ static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf)
if (!jbd2_journal_has_csum_v2or3(j))
return 1;
- tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize -
- sizeof(struct jbd2_journal_block_tail));
+ tail = (struct jbd2_journal_block_tail *)((char *)buf +
+ j->j_blocksize - sizeof(struct jbd2_journal_block_tail));
provided = tail->t_checksum;
tail->t_checksum = 0;
calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
@@ -196,7 +196,7 @@ static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf)
static int count_tags(journal_t *journal, struct buffer_head *bh)
{
char * tagp;
- journal_block_tag_t * tag;
+ journal_block_tag_t tag;
int nr = 0, size = journal->j_blocksize;
int tag_bytes = journal_tag_bytes(journal);
@@ -206,14 +206,14 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
tagp = &bh->b_data[sizeof(journal_header_t)];
while ((tagp - bh->b_data + tag_bytes) <= size) {
- tag = (journal_block_tag_t *) tagp;
+ memcpy(&tag, tagp, sizeof(tag));
nr++;
tagp += tag_bytes;
- if (!(tag->t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID)))
+ if (!(tag.t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID)))
tagp += 16;
- if (tag->t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG))
+ if (tag.t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG))
break;
}
@@ -433,9 +433,9 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
}
static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
+ journal_block_tag3_t *tag3,
void *buf, __u32 sequence)
{
- journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
__u32 csum32;
__be32 seq;
@@ -496,7 +496,7 @@ static int do_one_pass(journal_t *journal,
while (1) {
int flags;
char * tagp;
- journal_block_tag_t * tag;
+ journal_block_tag_t tag;
struct buffer_head * obh;
struct buffer_head * nbh;
@@ -613,8 +613,8 @@ static int do_one_pass(journal_t *journal,
<= journal->j_blocksize - descr_csum_size) {
unsigned long io_block;
- tag = (journal_block_tag_t *) tagp;
- flags = be16_to_cpu(tag->t_flags);
+ memcpy(&tag, tagp, sizeof(tag));
+ flags = be16_to_cpu(tag.t_flags);
io_block = next_log_block++;
wrap(journal, next_log_block);
@@ -632,7 +632,7 @@ static int do_one_pass(journal_t *journal,
J_ASSERT(obh != NULL);
blocknr = read_tag_block(journal,
- tag);
+ &tag);
/* If the block has been
* revoked, then we're all done
@@ -647,8 +647,8 @@ static int do_one_pass(journal_t *journal,
/* Look for block corruption */
if (!jbd2_block_tag_csum_verify(
- journal, tag, obh->b_data,
- be32_to_cpu(tmp->h_sequence))) {
+ journal, &tag, (journal_block_tag3_t *)tagp,
+ obh->b_data, be32_to_cpu(tmp->h_sequence))) {
brelse(obh);
success = -EFSBADCRC;
printk(KERN_ERR "JBD2: Invalid "
@@ -760,7 +760,6 @@ static int do_one_pass(journal_t *journal,
*/
jbd_debug(1, "JBD2: Invalid checksum ignored in transaction %u, likely stale data\n",
next_commit_ID);
- err = 0;
brelse(bh);
goto done;
}
@@ -897,7 +896,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
{
jbd2_journal_revoke_header_t *header;
int offset, max;
- int csum_size = 0;
+ unsigned csum_size = 0;
__u32 rcount;
int record_len = 4;
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 8804e126805f..6a3caedd2285 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -223,9 +223,15 @@ static void sub_reserved_credits(journal_t *journal, int blocks)
* with j_state_lock held for reading. Returns 0 if handle joined the running
* transaction. Returns 1 if we had to wait, j_state_lock is dropped, and
* caller must retry.
+ *
+ * Note: because j_state_lock may be dropped depending on the return
+ * value, we need to fake out sparse so ti doesn't complain about a
+ * locking imbalance. Callers of add_transaction_credits will need to
+ * make a similar accomodation.
*/
static int add_transaction_credits(journal_t *journal, int blocks,
int rsv_blocks)
+__must_hold(&journal->j_state_lock)
{
transaction_t *t = journal->j_running_transaction;
int needed;
@@ -238,6 +244,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
if (t->t_state != T_RUNNING) {
WARN_ON_ONCE(t->t_state >= T_FLUSH);
wait_transaction_locked(journal);
+ __acquire(&journal->j_state_lock); /* fake out sparse */
return 1;
}
@@ -266,10 +273,12 @@ static int add_transaction_credits(journal_t *journal, int blocks,
wait_event(journal->j_wait_reserved,
atomic_read(&journal->j_reserved_credits) + total <=
journal->j_max_transaction_buffers);
+ __acquire(&journal->j_state_lock); /* fake out sparse */
return 1;
}
wait_transaction_locked(journal);
+ __acquire(&journal->j_state_lock); /* fake out sparse */
return 1;
}
@@ -293,6 +302,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
journal->j_max_transaction_buffers)
__jbd2_log_wait_for_space(journal);
write_unlock(&journal->j_state_lock);
+ __acquire(&journal->j_state_lock); /* fake out sparse */
return 1;
}
@@ -310,6 +320,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
wait_event(journal->j_wait_reserved,
atomic_read(&journal->j_reserved_credits) + rsv_blocks
<= journal->j_max_transaction_buffers / 2);
+ __acquire(&journal->j_state_lock); /* fake out sparse */
return 1;
}
return 0;
@@ -413,8 +424,14 @@ repeat:
if (!handle->h_reserved) {
/* We may have dropped j_state_lock - restart in that case */
- if (add_transaction_credits(journal, blocks, rsv_blocks))
+ if (add_transaction_credits(journal, blocks, rsv_blocks)) {
+ /*
+ * add_transaction_credits releases
+ * j_state_lock on a non-zero return
+ */
+ __release(&journal->j_state_lock);
goto repeat;
+ }
} else {
/*
* We have handle reserved so we are allowed to join T_LOCKED
@@ -1404,7 +1421,7 @@ void jbd2_journal_set_triggers(struct buffer_head *bh,
{
struct journal_head *jh = jbd2_journal_grab_journal_head(bh);
- if (WARN_ON(!jh))
+ if (WARN_ON_ONCE(!jh))
return;
jh->b_triggers = type;
jbd2_journal_put_journal_head(jh);
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 55a79df70d24..e945e3484788 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -173,12 +173,15 @@ static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
return ERR_PTR(-EINVAL);
}
-struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
+struct posix_acl *jffs2_get_acl(struct inode *inode, int type, bool rcu)
{
struct posix_acl *acl;
char *value = NULL;
int rc, xprefix;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch (type) {
case ACL_TYPE_ACCESS:
xprefix = JFFS2_XPREFIX_ACL_ACCESS;
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 62c50da9d493..9d9fb7cf093e 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -27,7 +27,7 @@ struct jffs2_acl_header {
#ifdef CONFIG_JFFS2_FS_POSIX_ACL
-struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
+struct posix_acl *jffs2_get_acl(struct inode *inode, int type, bool rcu);
int jffs2_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
extern int jffs2_init_acl_pre(struct inode *, struct inode *, umode_t *);
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 43c285c3d2a7..a653f34c6e26 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -14,13 +14,16 @@
#include "jfs_xattr.h"
#include "jfs_acl.h"
-struct posix_acl *jfs_get_acl(struct inode *inode, int type)
+struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu)
{
struct posix_acl *acl;
char *ea_name;
int size;
char *value = NULL;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch(type) {
case ACL_TYPE_ACCESS:
ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index 7ae389a7a366..3de40286d31f 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -7,7 +7,7 @@
#ifdef CONFIG_JFS_POSIX_ACL
-struct posix_acl *jfs_get_acl(struct inode *inode, int type);
+struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu);
int jfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
int jfs_init_acl(tid_t, struct inode *, struct inode *);
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 33166ec90a11..ba581429bf7b 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -17,7 +17,7 @@
#include "kernfs-internal.h"
-DEFINE_MUTEX(kernfs_mutex);
+DECLARE_RWSEM(kernfs_rwsem);
static DEFINE_SPINLOCK(kernfs_rename_lock); /* kn->parent and ->name */
static char kernfs_pr_cont_buf[PATH_MAX]; /* protected by rename_lock */
static DEFINE_SPINLOCK(kernfs_idr_lock); /* root->ino_idr */
@@ -26,7 +26,7 @@ static DEFINE_SPINLOCK(kernfs_idr_lock); /* root->ino_idr */
static bool kernfs_active(struct kernfs_node *kn)
{
- lockdep_assert_held(&kernfs_mutex);
+ lockdep_assert_held(&kernfs_rwsem);
return atomic_read(&kn->active) >= 0;
}
@@ -340,7 +340,7 @@ static int kernfs_sd_compare(const struct kernfs_node *left,
* @kn->parent->dir.children.
*
* Locking:
- * mutex_lock(kernfs_mutex)
+ * kernfs_rwsem held exclusive
*
* RETURNS:
* 0 on susccess -EEXIST on failure.
@@ -372,6 +372,7 @@ static int kernfs_link_sibling(struct kernfs_node *kn)
/* successfully added, account subdir number */
if (kernfs_type(kn) == KERNFS_DIR)
kn->parent->dir.subdirs++;
+ kernfs_inc_rev(kn->parent);
return 0;
}
@@ -385,7 +386,7 @@ static int kernfs_link_sibling(struct kernfs_node *kn)
* removed, %false if @kn wasn't on the rbtree.
*
* Locking:
- * mutex_lock(kernfs_mutex)
+ * kernfs_rwsem held exclusive
*/
static bool kernfs_unlink_sibling(struct kernfs_node *kn)
{
@@ -394,6 +395,7 @@ static bool kernfs_unlink_sibling(struct kernfs_node *kn)
if (kernfs_type(kn) == KERNFS_DIR)
kn->parent->dir.subdirs--;
+ kernfs_inc_rev(kn->parent);
rb_erase(&kn->rb, &kn->parent->dir.children);
RB_CLEAR_NODE(&kn->rb);
@@ -455,14 +457,14 @@ void kernfs_put_active(struct kernfs_node *kn)
* return after draining is complete.
*/
static void kernfs_drain(struct kernfs_node *kn)
- __releases(&kernfs_mutex) __acquires(&kernfs_mutex)
+ __releases(&kernfs_rwsem) __acquires(&kernfs_rwsem)
{
struct kernfs_root *root = kernfs_root(kn);
- lockdep_assert_held(&kernfs_mutex);
+ lockdep_assert_held_write(&kernfs_rwsem);
WARN_ON_ONCE(kernfs_active(kn));
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
if (kernfs_lockdep(kn)) {
rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_);
@@ -481,7 +483,7 @@ static void kernfs_drain(struct kernfs_node *kn)
kernfs_drain_open_files(kn);
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
}
/**
@@ -720,7 +722,7 @@ int kernfs_add_one(struct kernfs_node *kn)
bool has_ns;
int ret;
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
ret = -EINVAL;
has_ns = kernfs_ns_enabled(parent);
@@ -751,7 +753,7 @@ int kernfs_add_one(struct kernfs_node *kn)
ps_iattr->ia_mtime = ps_iattr->ia_ctime;
}
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
/*
* Activate the new node unless CREATE_DEACTIVATED is requested.
@@ -765,7 +767,7 @@ int kernfs_add_one(struct kernfs_node *kn)
return 0;
out_unlock:
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
return ret;
}
@@ -786,7 +788,7 @@ static struct kernfs_node *kernfs_find_ns(struct kernfs_node *parent,
bool has_ns = kernfs_ns_enabled(parent);
unsigned int hash;
- lockdep_assert_held(&kernfs_mutex);
+ lockdep_assert_held(&kernfs_rwsem);
if (has_ns != (bool)ns) {
WARN(1, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n",
@@ -818,7 +820,7 @@ static struct kernfs_node *kernfs_walk_ns(struct kernfs_node *parent,
size_t len;
char *p, *name;
- lockdep_assert_held(&kernfs_mutex);
+ lockdep_assert_held_read(&kernfs_rwsem);
/* grab kernfs_rename_lock to piggy back on kernfs_pr_cont_buf */
spin_lock_irq(&kernfs_rename_lock);
@@ -858,10 +860,10 @@ struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent,
{
struct kernfs_node *kn;
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
kn = kernfs_find_ns(parent, name, ns);
kernfs_get(kn);
- mutex_unlock(&kernfs_mutex);
+ up_read(&kernfs_rwsem);
return kn;
}
@@ -882,10 +884,10 @@ struct kernfs_node *kernfs_walk_and_get_ns(struct kernfs_node *parent,
{
struct kernfs_node *kn;
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
kn = kernfs_walk_ns(parent, path, ns);
kernfs_get(kn);
- mutex_unlock(&kernfs_mutex);
+ up_read(&kernfs_rwsem);
return kn;
}
@@ -1037,12 +1039,34 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
- /* Always perform fresh lookup for negatives */
- if (d_really_is_negative(dentry))
- goto out_bad_unlocked;
+ /* Negative hashed dentry? */
+ if (d_really_is_negative(dentry)) {
+ struct kernfs_node *parent;
+
+ /* If the kernfs parent node has changed discard and
+ * proceed to ->lookup.
+ */
+ down_read(&kernfs_rwsem);
+ spin_lock(&dentry->d_lock);
+ parent = kernfs_dentry_node(dentry->d_parent);
+ if (parent) {
+ if (kernfs_dir_changed(parent, dentry)) {
+ spin_unlock(&dentry->d_lock);
+ up_read(&kernfs_rwsem);
+ return 0;
+ }
+ }
+ spin_unlock(&dentry->d_lock);
+ up_read(&kernfs_rwsem);
+
+ /* The kernfs parent node hasn't changed, leave the
+ * dentry negative and return success.
+ */
+ return 1;
+ }
kn = kernfs_dentry_node(dentry);
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
/* The kernfs node has been deactivated */
if (!kernfs_active(kn))
@@ -1061,11 +1085,10 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
kernfs_info(dentry->d_sb)->ns != kn->ns)
goto out_bad;
- mutex_unlock(&kernfs_mutex);
+ up_read(&kernfs_rwsem);
return 1;
out_bad:
- mutex_unlock(&kernfs_mutex);
-out_bad_unlocked:
+ up_read(&kernfs_rwsem);
return 0;
}
@@ -1077,37 +1100,29 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
struct dentry *dentry,
unsigned int flags)
{
- struct dentry *ret;
struct kernfs_node *parent = dir->i_private;
struct kernfs_node *kn;
- struct inode *inode;
+ struct inode *inode = NULL;
const void *ns = NULL;
- mutex_lock(&kernfs_mutex);
-
+ down_read(&kernfs_rwsem);
if (kernfs_ns_enabled(parent))
ns = kernfs_info(dir->i_sb)->ns;
kn = kernfs_find_ns(parent, dentry->d_name.name, ns);
-
- /* no such entry */
- if (!kn || !kernfs_active(kn)) {
- ret = NULL;
- goto out_unlock;
- }
-
/* attach dentry and inode */
- inode = kernfs_get_inode(dir->i_sb, kn);
- if (!inode) {
- ret = ERR_PTR(-ENOMEM);
- goto out_unlock;
+ if (kn && kernfs_active(kn)) {
+ inode = kernfs_get_inode(dir->i_sb, kn);
+ if (!inode)
+ inode = ERR_PTR(-ENOMEM);
}
+ /* Needed only for negative dentry validation */
+ if (!inode)
+ kernfs_set_rev(parent, dentry);
+ up_read(&kernfs_rwsem);
- /* instantiate and hash dentry */
- ret = d_splice_alias(inode, dentry);
- out_unlock:
- mutex_unlock(&kernfs_mutex);
- return ret;
+ /* instantiate and hash (possibly negative) dentry */
+ return d_splice_alias(inode, dentry);
}
static int kernfs_iop_mkdir(struct user_namespace *mnt_userns,
@@ -1227,7 +1242,7 @@ static struct kernfs_node *kernfs_next_descendant_post(struct kernfs_node *pos,
{
struct rb_node *rbn;
- lockdep_assert_held(&kernfs_mutex);
+ lockdep_assert_held_write(&kernfs_rwsem);
/* if first iteration, visit leftmost descendant which may be root */
if (!pos)
@@ -1263,7 +1278,7 @@ void kernfs_activate(struct kernfs_node *kn)
{
struct kernfs_node *pos;
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
pos = NULL;
while ((pos = kernfs_next_descendant_post(pos, kn))) {
@@ -1277,14 +1292,14 @@ void kernfs_activate(struct kernfs_node *kn)
pos->flags |= KERNFS_ACTIVATED;
}
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
}
static void __kernfs_remove(struct kernfs_node *kn)
{
struct kernfs_node *pos;
- lockdep_assert_held(&kernfs_mutex);
+ lockdep_assert_held_write(&kernfs_rwsem);
/*
* Short-circuit if non-root @kn has already finished removal.
@@ -1307,7 +1322,7 @@ static void __kernfs_remove(struct kernfs_node *kn)
pos = kernfs_leftmost_descendant(kn);
/*
- * kernfs_drain() drops kernfs_mutex temporarily and @pos's
+ * kernfs_drain() drops kernfs_rwsem temporarily and @pos's
* base ref could have been put by someone else by the time
* the function returns. Make sure it doesn't go away
* underneath us.
@@ -1354,9 +1369,9 @@ static void __kernfs_remove(struct kernfs_node *kn)
*/
void kernfs_remove(struct kernfs_node *kn)
{
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
__kernfs_remove(kn);
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
}
/**
@@ -1443,17 +1458,17 @@ bool kernfs_remove_self(struct kernfs_node *kn)
{
bool ret;
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
kernfs_break_active_protection(kn);
/*
* SUICIDAL is used to arbitrate among competing invocations. Only
* the first one will actually perform removal. When the removal
* is complete, SUICIDED is set and the active ref is restored
- * while holding kernfs_mutex. The ones which lost arbitration
- * waits for SUICDED && drained which can happen only after the
- * enclosing kernfs operation which executed the winning instance
- * of kernfs_remove_self() finished.
+ * while kernfs_rwsem for held exclusive. The ones which lost
+ * arbitration waits for SUICIDED && drained which can happen only
+ * after the enclosing kernfs operation which executed the winning
+ * instance of kernfs_remove_self() finished.
*/
if (!(kn->flags & KERNFS_SUICIDAL)) {
kn->flags |= KERNFS_SUICIDAL;
@@ -1471,9 +1486,9 @@ bool kernfs_remove_self(struct kernfs_node *kn)
atomic_read(&kn->active) == KN_DEACTIVATED_BIAS)
break;
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
schedule();
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
}
finish_wait(waitq, &wait);
WARN_ON_ONCE(!RB_EMPTY_NODE(&kn->rb));
@@ -1481,12 +1496,12 @@ bool kernfs_remove_self(struct kernfs_node *kn)
}
/*
- * This must be done while holding kernfs_mutex; otherwise, waiting
- * for SUICIDED && deactivated could finish prematurely.
+ * This must be done while kernfs_rwsem held exclusive; otherwise,
+ * waiting for SUICIDED && deactivated could finish prematurely.
*/
kernfs_unbreak_active_protection(kn);
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
return ret;
}
@@ -1510,13 +1525,13 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
return -ENOENT;
}
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
kn = kernfs_find_ns(parent, name, ns);
if (kn)
__kernfs_remove(kn);
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
if (kn)
return 0;
@@ -1542,7 +1557,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
if (!kn->parent)
return -EINVAL;
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
error = -ENOENT;
if (!kernfs_active(kn) || !kernfs_active(new_parent) ||
@@ -1596,7 +1611,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
error = 0;
out:
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
return error;
}
@@ -1671,7 +1686,7 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
if (!dir_emit_dots(file, ctx))
return 0;
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
if (kernfs_ns_enabled(parent))
ns = kernfs_info(dentry->d_sb)->ns;
@@ -1688,12 +1703,12 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
file->private_data = pos;
kernfs_get(pos);
- mutex_unlock(&kernfs_mutex);
+ up_read(&kernfs_rwsem);
if (!dir_emit(ctx, name, len, ino, type))
return 0;
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
}
- mutex_unlock(&kernfs_mutex);
+ up_read(&kernfs_rwsem);
file->private_data = NULL;
ctx->pos = INT_MAX;
return 0;
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index c75719312147..60e2a86c535e 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -860,7 +860,7 @@ repeat:
spin_unlock_irq(&kernfs_notify_lock);
/* kick fsnotify */
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
list_for_each_entry(info, &kernfs_root(kn)->supers, node) {
struct kernfs_node *parent;
@@ -898,7 +898,7 @@ repeat:
iput(inode);
}
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
kernfs_put(kn);
goto repeat;
}
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 26f2aa3586f9..c0eae1725435 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -100,9 +100,9 @@ int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
{
int ret;
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
ret = __kernfs_setattr(kn, iattr);
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
return ret;
}
@@ -116,7 +116,7 @@ int kernfs_iop_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
if (!kn)
return -EINVAL;
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
error = setattr_prepare(&init_user_ns, dentry, iattr);
if (error)
goto out;
@@ -129,7 +129,7 @@ int kernfs_iop_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
setattr_copy(&init_user_ns, inode, iattr);
out:
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
return error;
}
@@ -185,11 +185,13 @@ int kernfs_iop_getattr(struct user_namespace *mnt_userns,
struct inode *inode = d_inode(path->dentry);
struct kernfs_node *kn = inode->i_private;
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
+ spin_lock(&inode->i_lock);
kernfs_refresh_inode(kn, inode);
- mutex_unlock(&kernfs_mutex);
-
generic_fillattr(&init_user_ns, inode, stat);
+ spin_unlock(&inode->i_lock);
+ up_read(&kernfs_rwsem);
+
return 0;
}
@@ -272,17 +274,21 @@ int kernfs_iop_permission(struct user_namespace *mnt_userns,
struct inode *inode, int mask)
{
struct kernfs_node *kn;
+ int ret;
if (mask & MAY_NOT_BLOCK)
return -ECHILD;
kn = inode->i_private;
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
+ spin_lock(&inode->i_lock);
kernfs_refresh_inode(kn, inode);
- mutex_unlock(&kernfs_mutex);
+ ret = generic_permission(&init_user_ns, inode, mask);
+ spin_unlock(&inode->i_lock);
+ up_read(&kernfs_rwsem);
- return generic_permission(&init_user_ns, inode, mask);
+ return ret;
}
int kernfs_xattr_get(struct kernfs_node *kn, const char *name,
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index ccc3b44f6306..f9cc912c31e1 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -13,6 +13,7 @@
#include <linux/lockdep.h>
#include <linux/fs.h>
#include <linux/mutex.h>
+#include <linux/rwsem.h>
#include <linux/xattr.h>
#include <linux/kernfs.h>
@@ -69,7 +70,7 @@ struct kernfs_super_info {
*/
const void *ns;
- /* anchored at kernfs_root->supers, protected by kernfs_mutex */
+ /* anchored at kernfs_root->supers, protected by kernfs_rwsem */
struct list_head node;
};
#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
@@ -81,6 +82,25 @@ static inline struct kernfs_node *kernfs_dentry_node(struct dentry *dentry)
return d_inode(dentry)->i_private;
}
+static inline void kernfs_set_rev(struct kernfs_node *parent,
+ struct dentry *dentry)
+{
+ dentry->d_time = parent->dir.rev;
+}
+
+static inline void kernfs_inc_rev(struct kernfs_node *parent)
+{
+ parent->dir.rev++;
+}
+
+static inline bool kernfs_dir_changed(struct kernfs_node *parent,
+ struct dentry *dentry)
+{
+ if (parent->dir.rev != dentry->d_time)
+ return true;
+ return false;
+}
+
extern const struct super_operations kernfs_sops;
extern struct kmem_cache *kernfs_node_cache, *kernfs_iattrs_cache;
@@ -102,7 +122,7 @@ int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr);
/*
* dir.c
*/
-extern struct mutex kernfs_mutex;
+extern struct rw_semaphore kernfs_rwsem;
extern const struct dentry_operations kernfs_dops;
extern const struct file_operations kernfs_dir_fops;
extern const struct inode_operations kernfs_dir_iops;
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 9dc7e7a64e10..f2f909d09f52 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -255,9 +255,9 @@ static int kernfs_fill_super(struct super_block *sb, struct kernfs_fs_context *k
sb->s_shrink.seeks = 0;
/* get root inode, initialize and unlock it */
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
inode = kernfs_get_inode(sb, info->root->kn);
- mutex_unlock(&kernfs_mutex);
+ up_read(&kernfs_rwsem);
if (!inode) {
pr_debug("kernfs: could not get root inode\n");
return -ENOMEM;
@@ -344,9 +344,9 @@ int kernfs_get_tree(struct fs_context *fc)
}
sb->s_flags |= SB_ACTIVE;
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
list_add(&info->node, &info->root->supers);
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
}
fc->root = dget(sb->s_root);
@@ -372,9 +372,9 @@ void kernfs_kill_sb(struct super_block *sb)
{
struct kernfs_super_info *info = kernfs_info(sb);
- mutex_lock(&kernfs_mutex);
+ down_write(&kernfs_rwsem);
list_del(&info->node);
- mutex_unlock(&kernfs_mutex);
+ up_write(&kernfs_rwsem);
/*
* Remove the superblock from fs_supers/s_instances
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
index 5432883d819f..c8f8e41b8411 100644
--- a/fs/kernfs/symlink.c
+++ b/fs/kernfs/symlink.c
@@ -116,9 +116,9 @@ static int kernfs_getlink(struct inode *inode, char *path)
struct kernfs_node *target = kn->symlink.target_kn;
int error;
- mutex_lock(&kernfs_mutex);
+ down_read(&kernfs_rwsem);
error = kernfs_get_target_path(parent, target, path);
- mutex_unlock(&kernfs_mutex);
+ up_read(&kernfs_rwsem);
return error;
}
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 0ab9756ed235..b632be3ad57b 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -649,6 +649,7 @@ static int lockd_authenticate(struct svc_rqst *rqstp)
switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
case RPC_AUTH_UNIX:
+ rqstp->rq_auth_stat = rpc_auth_ok;
if (rqstp->rq_proc == 0)
return SVC_OK;
if (is_callback(rqstp->rq_proc)) {
@@ -659,6 +660,7 @@ static int lockd_authenticate(struct svc_rqst *rqstp)
}
return svc_set_client(rqstp);
}
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
return SVC_DENIED;
}
diff --git a/fs/namei.c b/fs/namei.c
index d049d3972695..95a881e0552b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4089,7 +4089,9 @@ int vfs_unlink(struct user_namespace *mnt_userns, struct inode *dir,
return -EPERM;
inode_lock(target);
- if (is_local_mountpoint(dentry))
+ if (IS_SWAPFILE(target))
+ error = -EPERM;
+ else if (is_local_mountpoint(dentry))
error = -EBUSY;
else {
error = security_inode_unlink(dir, dentry);
@@ -4597,6 +4599,10 @@ int vfs_rename(struct renamedata *rd)
else if (target)
inode_lock(target);
+ error = -EPERM;
+ if (IS_SWAPFILE(source) || (target && IS_SWAPFILE(target)))
+ goto out;
+
error = -EBUSY;
if (is_local_mountpoint(old_dentry) || is_local_mountpoint(new_dentry))
goto out;
diff --git a/fs/namespace.c b/fs/namespace.c
index 12852363d90e..659a8f39c61a 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -203,7 +203,8 @@ static struct mount *alloc_vfsmnt(const char *name)
goto out_free_cache;
if (name) {
- mnt->mnt_devname = kstrdup_const(name, GFP_KERNEL);
+ mnt->mnt_devname = kstrdup_const(name,
+ GFP_KERNEL_ACCOUNT);
if (!mnt->mnt_devname)
goto out_free_id;
}
@@ -3370,7 +3371,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool a
if (!ucounts)
return ERR_PTR(-ENOSPC);
- new_ns = kzalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
+ new_ns = kzalloc(sizeof(struct mnt_namespace), GFP_KERNEL_ACCOUNT);
if (!new_ns) {
dec_mnt_namespaces(ucounts);
return ERR_PTR(-ENOMEM);
@@ -4306,7 +4307,7 @@ void __init mnt_init(void)
int err;
mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
- 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL);
mount_hashtable = alloc_large_system_hash("Mount-cache",
sizeof(struct hlist_head),
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 7817ad94a6ba..86d856de1389 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -429,6 +429,8 @@ check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
*/
static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
+
switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
if (rqstp->rq_proc != CB_NULL)
@@ -439,6 +441,8 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
if (svc_is_backchannel(rqstp))
return SVC_DENIED;
}
+
+ rqstp->rq_auth_stat = rpc_auth_ok;
return SVC_OK;
}
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index c5348ba81129..4c48d85f6517 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -63,11 +63,10 @@ static __be32 nfs4_callback_null(struct svc_rqst *rqstp)
return htonl(NFS4_OK);
}
-static int nfs4_decode_void(struct svc_rqst *rqstp, __be32 *p)
-{
- return xdr_argsize_check(rqstp, p);
-}
-
+/*
+ * svc_process_common() looks for an XDR encoder to know when
+ * not to drop a Reply.
+ */
static int nfs4_encode_void(struct svc_rqst *rqstp, __be32 *p)
{
return xdr_ressize_check(rqstp, p);
@@ -864,17 +863,16 @@ preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op)
}
static __be32 process_op(int nop, struct svc_rqst *rqstp,
- struct xdr_stream *xdr_in, void *argp,
- struct xdr_stream *xdr_out, void *resp,
- struct cb_process_state *cps)
+ struct cb_process_state *cps)
{
+ struct xdr_stream *xdr_out = &rqstp->rq_res_stream;
struct callback_op *op = &callback_ops[0];
unsigned int op_nr;
__be32 status;
long maxlen;
__be32 res;
- status = decode_op_hdr(xdr_in, &op_nr);
+ status = decode_op_hdr(&rqstp->rq_arg_stream, &op_nr);
if (unlikely(status))
return status;
@@ -904,9 +902,11 @@ static __be32 process_op(int nop, struct svc_rqst *rqstp,
maxlen = xdr_out->end - xdr_out->p;
if (maxlen > 0 && maxlen < PAGE_SIZE) {
- status = op->decode_args(rqstp, xdr_in, argp);
+ status = op->decode_args(rqstp, &rqstp->rq_arg_stream,
+ rqstp->rq_argp);
if (likely(status == 0))
- status = op->process_op(argp, resp, cps);
+ status = op->process_op(rqstp->rq_argp, rqstp->rq_resp,
+ cps);
} else
status = htonl(NFS4ERR_RESOURCE);
@@ -915,7 +915,7 @@ encode_hdr:
if (unlikely(res))
return res;
if (op->encode_res != NULL && status == 0)
- status = op->encode_res(rqstp, xdr_out, resp);
+ status = op->encode_res(rqstp, xdr_out, rqstp->rq_resp);
return status;
}
@@ -926,22 +926,15 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
{
struct cb_compound_hdr_arg hdr_arg = { 0 };
struct cb_compound_hdr_res hdr_res = { NULL };
- struct xdr_stream xdr_in, xdr_out;
- __be32 *p, status;
struct cb_process_state cps = {
.drc_status = 0,
.clp = NULL,
.net = SVC_NET(rqstp),
};
unsigned int nops = 0;
+ __be32 status;
- xdr_init_decode(&xdr_in, &rqstp->rq_arg,
- rqstp->rq_arg.head[0].iov_base, NULL);
-
- p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
- xdr_init_encode(&xdr_out, &rqstp->rq_res, p, NULL);
-
- status = decode_compound_hdr_arg(&xdr_in, &hdr_arg);
+ status = decode_compound_hdr_arg(&rqstp->rq_arg_stream, &hdr_arg);
if (status == htonl(NFS4ERR_RESOURCE))
return rpc_garbage_args;
@@ -961,15 +954,13 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
cps.minorversion = hdr_arg.minorversion;
hdr_res.taglen = hdr_arg.taglen;
hdr_res.tag = hdr_arg.tag;
- if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) {
+ if (encode_compound_hdr_res(&rqstp->rq_res_stream, &hdr_res) != 0) {
if (cps.clp)
nfs_put_client(cps.clp);
return rpc_system_err;
}
while (status == 0 && nops != hdr_arg.nops) {
- status = process_op(nops, rqstp, &xdr_in,
- rqstp->rq_argp, &xdr_out, rqstp->rq_resp,
- &cps);
+ status = process_op(nops, rqstp, &cps);
nops++;
}
@@ -988,7 +979,20 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
out_invalidcred:
pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n");
- return svc_return_autherr(rqstp, rpc_autherr_badcred);
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
+ return rpc_success;
+}
+
+static int
+nfs_callback_dispatch(struct svc_rqst *rqstp, __be32 *statp)
+{
+ const struct svc_procedure *procp = rqstp->rq_procinfo;
+
+ svcxdr_init_decode(rqstp);
+ svcxdr_init_encode(rqstp);
+
+ *statp = procp->pc_func(rqstp);
+ return 1;
}
/*
@@ -1057,7 +1061,6 @@ static struct callback_op callback_ops[] = {
static const struct svc_procedure nfs4_callback_procedures1[] = {
[CB_NULL] = {
.pc_func = nfs4_callback_null,
- .pc_decode = nfs4_decode_void,
.pc_encode = nfs4_encode_void,
.pc_xdrressize = 1,
.pc_name = "NULL",
@@ -1079,7 +1082,7 @@ const struct svc_version nfs4_callback_version1 = {
.vs_proc = nfs4_callback_procedures1,
.vs_count = nfs4_callback_count1,
.vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
- .vs_dispatch = NULL,
+ .vs_dispatch = nfs_callback_dispatch,
.vs_hidden = true,
.vs_need_cong_ctrl = true,
};
@@ -1091,7 +1094,7 @@ const struct svc_version nfs4_callback_version4 = {
.vs_proc = nfs4_callback_procedures1,
.vs_count = nfs4_callback_count4,
.vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
- .vs_dispatch = NULL,
+ .vs_dispatch = nfs_callback_dispatch,
.vs_hidden = true,
.vs_need_cong_ctrl = true,
};
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 330f65727c45..23e165d5ec9c 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -179,6 +179,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
clp->cl_proto = cl_init->proto;
clp->cl_nconnect = cl_init->nconnect;
+ clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
clp->cl_net = get_net(cl_init->net);
clp->cl_principal = "*";
@@ -540,6 +541,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
clnt->cl_principal = clp->cl_principal;
clp->cl_rpcclient = clnt;
+ clnt->cl_max_connect = clp->cl_max_connect;
return 0;
}
EXPORT_SYMBOL_GPL(nfs_create_rpc_client);
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index d95c9a39bc70..0d444a90f513 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -60,6 +60,7 @@ enum nfs_param {
Opt_mountvers,
Opt_namelen,
Opt_nconnect,
+ Opt_max_connect,
Opt_port,
Opt_posix,
Opt_proto,
@@ -158,6 +159,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = {
fsparam_u32 ("mountvers", Opt_mountvers),
fsparam_u32 ("namlen", Opt_namelen),
fsparam_u32 ("nconnect", Opt_nconnect),
+ fsparam_u32 ("max_connect", Opt_max_connect),
fsparam_string("nfsvers", Opt_vers),
fsparam_u32 ("port", Opt_port),
fsparam_flag_no("posix", Opt_posix),
@@ -770,6 +772,11 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
goto out_of_bounds;
ctx->nfs_server.nconnect = result.uint_32;
break;
+ case Opt_max_connect:
+ if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_TRANSPORTS)
+ goto out_of_bounds;
+ ctx->nfs_server.max_connect = result.uint_32;
+ break;
case Opt_lookupcache:
switch (result.uint_32) {
case Opt_lookupcache_all:
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index a36af04188c2..66fc936834f2 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -67,6 +67,7 @@ struct nfs_client_initdata {
int proto;
u32 minorversion;
unsigned int nconnect;
+ unsigned int max_connect;
struct net *net;
const struct rpc_timeout *timeparms;
const struct cred *cred;
@@ -121,6 +122,7 @@ struct nfs_fs_context {
int port;
unsigned short protocol;
unsigned short nconnect;
+ unsigned short max_connect;
unsigned short export_path_len;
} nfs_server;
diff --git a/fs/nfs/nfs3_fs.h b/fs/nfs/nfs3_fs.h
index c8a192802dda..03a4e679fd99 100644
--- a/fs/nfs/nfs3_fs.h
+++ b/fs/nfs/nfs3_fs.h
@@ -11,7 +11,7 @@
* nfs3acl.c
*/
#ifdef CONFIG_NFS_V3_ACL
-extern struct posix_acl *nfs3_get_acl(struct inode *inode, int type);
+extern struct posix_acl *nfs3_get_acl(struct inode *inode, int type, bool rcu);
extern int nfs3_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
extern int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 9ec560aa4a50..93de0b58647a 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -44,7 +44,7 @@ static void nfs3_abort_get_acl(struct posix_acl **p)
cmpxchg(p, sentinel, ACL_NOT_CACHED);
}
-struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
+struct posix_acl *nfs3_get_acl(struct inode *inode, int type, bool rcu)
{
struct nfs_server *server = NFS_SERVER(inode);
struct page *pages[NFSACL_MAXPAGES] = { };
@@ -62,6 +62,9 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
};
int status, count;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
if (!nfs_server_capable(inode, NFS_CAP_ACLS))
return ERR_PTR(-EOPNOTSUPP);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 2299446b3b89..f7524310ddf4 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -49,8 +49,7 @@ nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
{
if (task->tk_status != -EJUKEBOX)
return 0;
- if (task->tk_status == -EJUKEBOX)
- nfs_inc_stats(inode, NFSIOS_DELAY);
+ nfs_inc_stats(inode, NFSIOS_DELAY);
task->tk_status = 0;
rpc_restart_call(task);
rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 28431acd1230..af57332503be 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -402,6 +402,33 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp)
return nfs4_init_callback(clp);
}
+static void nfs4_add_trunk(struct nfs_client *clp, struct nfs_client *old)
+{
+ struct sockaddr_storage clp_addr, old_addr;
+ struct sockaddr *clp_sap = (struct sockaddr *)&clp_addr;
+ struct sockaddr *old_sap = (struct sockaddr *)&old_addr;
+ size_t clp_salen;
+ struct xprt_create xprt_args = {
+ .ident = old->cl_proto,
+ .net = old->cl_net,
+ .servername = old->cl_hostname,
+ };
+
+ if (clp->cl_proto != old->cl_proto)
+ return;
+ clp_salen = rpc_peeraddr(clp->cl_rpcclient, clp_sap, sizeof(clp_addr));
+ rpc_peeraddr(old->cl_rpcclient, old_sap, sizeof(old_addr));
+
+ if (clp_addr.ss_family != old_addr.ss_family)
+ return;
+
+ xprt_args.dstaddr = clp_sap;
+ xprt_args.addrlen = clp_salen;
+
+ rpc_clnt_add_xprt(old->cl_rpcclient, &xprt_args,
+ rpc_clnt_test_and_add_xprt, NULL);
+}
+
/**
* nfs4_init_client - Initialise an NFS4 client record
*
@@ -436,6 +463,8 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
* won't try to use it.
*/
nfs_mark_client_ready(clp, -EPERM);
+ if (old->cl_mvops->session_trunk)
+ nfs4_add_trunk(clp, old);
}
clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags);
nfs_put_client(clp);
@@ -865,6 +894,7 @@ static int nfs4_set_client(struct nfs_server *server,
const char *ip_addr,
int proto, const struct rpc_timeout *timeparms,
u32 minorversion, unsigned int nconnect,
+ unsigned int max_connect,
struct net *net)
{
struct nfs_client_initdata cl_init = {
@@ -883,6 +913,8 @@ static int nfs4_set_client(struct nfs_server *server,
if (minorversion == 0)
__set_bit(NFS_CS_REUSEPORT, &cl_init.init_flags);
+ else
+ cl_init.max_connect = max_connect;
if (proto == XPRT_TRANSPORT_TCP)
cl_init.nconnect = nconnect;
@@ -952,8 +984,10 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
return ERR_PTR(-EINVAL);
cl_init.hostname = buf;
- if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP)
+ if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP) {
cl_init.nconnect = mds_clp->cl_nconnect;
+ cl_init.max_connect = NFS_MAX_TRANSPORTS;
+ }
if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
@@ -1122,6 +1156,7 @@ static int nfs4_init_server(struct nfs_server *server, struct fs_context *fc)
&timeparms,
ctx->minorversion,
ctx->nfs_server.nconnect,
+ ctx->nfs_server.max_connect,
fc->net_ns);
if (error < 0)
return error;
@@ -1211,6 +1246,7 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
parent_server->client->cl_timeout,
parent_client->cl_mvops->minor_version,
parent_client->cl_nconnect,
+ parent_client->cl_max_connect,
parent_client->cl_net);
if (!error)
goto init_server;
@@ -1226,6 +1262,7 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
parent_server->client->cl_timeout,
parent_client->cl_mvops->minor_version,
parent_client->cl_nconnect,
+ parent_client->cl_max_connect,
parent_client->cl_net);
if (error < 0)
goto error;
@@ -1323,7 +1360,7 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
error = nfs4_set_client(server, hostname, sap, salen, buf,
clp->cl_proto, clnt->cl_timeout,
clp->cl_minorversion,
- clp->cl_nconnect, net);
+ clp->cl_nconnect, clp->cl_max_connect, net);
clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
if (error != 0) {
nfs_server_insert_lists(server);
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index c820de58a661..c91565227ea2 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -158,13 +158,11 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
sync = true;
retry:
if (!nfs42_files_from_same_server(file_in, file_out)) {
- /* for inter copy, if copy size if smaller than 12 RPC
- * payloads, fallback to traditional copy. There are
- * 14 RPCs during an NFSv4.x mount between source/dest
- * servers.
+ /*
+ * for inter copy, if copy size is too small
+ * then fallback to generic copy.
*/
- if (sync ||
- count <= 14 * NFS_SERVER(file_inode(file_in))->rsize)
+ if (sync)
return -EOPNOTSUPP;
cn_resp = kzalloc(sizeof(struct nfs42_copy_notify_res),
GFP_NOFS);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ef14ea0b6ab8..7c9090a28e5c 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -335,7 +335,7 @@ static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
static void pnfs_barrier_update(struct pnfs_layout_hdr *lo, u32 newseq)
{
- if (pnfs_seqid_is_newer(newseq, lo->plh_barrier))
+ if (pnfs_seqid_is_newer(newseq, lo->plh_barrier) || !lo->plh_barrier)
lo->plh_barrier = newseq;
}
@@ -347,11 +347,15 @@ pnfs_set_plh_return_info(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode,
iomode = IOMODE_ANY;
lo->plh_return_iomode = iomode;
set_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags);
- if (seq != 0) {
- WARN_ON_ONCE(lo->plh_return_seq != 0 && lo->plh_return_seq != seq);
+ /*
+ * We must set lo->plh_return_seq to avoid livelocks with
+ * pnfs_layout_need_return()
+ */
+ if (seq == 0)
+ seq = be32_to_cpu(lo->plh_stateid.seqid);
+ if (!lo->plh_return_seq || pnfs_seqid_is_newer(seq, lo->plh_return_seq))
lo->plh_return_seq = seq;
- pnfs_barrier_update(lo, seq);
- }
+ pnfs_barrier_update(lo, seq);
}
static void
@@ -592,10 +596,6 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
inode = lo->plh_inode;
if (refcount_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
- if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) {
- spin_unlock(&inode->i_lock);
- return;
- }
pnfs_get_layout_hdr(lo);
pnfs_layout_remove_lseg(lo, lseg);
if (pnfs_cache_lseg_for_layoutreturn(lo, lseg))
@@ -1000,7 +1000,7 @@ pnfs_layout_stateid_blocked(const struct pnfs_layout_hdr *lo,
{
u32 seqid = be32_to_cpu(stateid->seqid);
- return !pnfs_seqid_is_newer(seqid, lo->plh_barrier) && lo->plh_barrier;
+ return lo->plh_barrier && pnfs_seqid_is_newer(lo->plh_barrier, seqid);
}
/* lget is set to 1 if called from inside send_layoutget call chain */
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 9f39e0a1a38b..08d6cc57cbc3 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -293,15 +293,19 @@ static int
readpage_async_filler(void *data, struct page *page)
{
struct nfs_readdesc *desc = data;
+ struct inode *inode = page_file_mapping(page)->host;
+ unsigned int rsize = NFS_SERVER(inode)->rsize;
struct nfs_page *new;
- unsigned int len;
+ unsigned int len, aligned_len;
int error;
len = nfs_page_length(page);
if (len == 0)
return nfs_return_empty_page(page);
- new = nfs_create_request(desc->ctx, page, 0, len);
+ aligned_len = min_t(unsigned int, ALIGN(len, rsize), PAGE_SIZE);
+
+ new = nfs_create_request(desc->ctx, page, 0, aligned_len);
if (IS_ERR(new))
goto out_error;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index fe58525cfed4..e65c83494c05 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -480,6 +480,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
if (clp->cl_nconnect > 0)
seq_printf(m, ",nconnect=%u", clp->cl_nconnect);
if (version == 4) {
+ if (clp->cl_max_connect > 1)
+ seq_printf(m, ",max_connect=%u", clp->cl_max_connect);
if (nfss->port != NFS_PORT)
seq_printf(m, ",port=%u", nfss->port);
} else
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index f229172652be..6e9ea4ee0f73 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -109,7 +109,7 @@ config NFSD_SCSILAYOUT
depends on NFSD_V4 && BLOCK
select NFSD_PNFS
select EXPORTFS_BLOCK_OPS
- select BLK_SCSI_REQUEST
+ select SCSI_COMMON
help
This option enables support for the exporting pNFS SCSI layouts
in the kernel's NFS server. The pNFS SCSI layout enables NFS
diff --git a/fs/ntfs3/Kconfig b/fs/ntfs3/Kconfig
new file mode 100644
index 000000000000..6e4cbc48ab8e
--- /dev/null
+++ b/fs/ntfs3/Kconfig
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config NTFS3_FS
+ tristate "NTFS Read-Write file system support"
+ select NLS
+ help
+ Windows OS native file system (NTFS) support up to NTFS version 3.1.
+
+ Y or M enables the NTFS3 driver with full features enabled (read,
+ write, journal replaying, sparse/compressed files support).
+ File system type to use on mount is "ntfs3". Module name (M option)
+ is also "ntfs3".
+
+ Documentation: <file:Documentation/filesystems/ntfs3.rst>
+
+config NTFS3_64BIT_CLUSTER
+ bool "64 bits per NTFS clusters"
+ depends on NTFS3_FS && 64BIT
+ help
+ Windows implementation of ntfs.sys uses 32 bits per clusters.
+ If activated 64 bits per clusters you will be able to use 4k cluster
+ for 16T+ volumes. Windows will not be able to mount such volumes.
+
+ It is recommended to say N here.
+
+config NTFS3_LZX_XPRESS
+ bool "activate support of external compressions lzx/xpress"
+ depends on NTFS3_FS
+ help
+ In Windows 10 one can use command "compact" to compress any files.
+ 4 possible variants of compression are: xpress4k, xpress8k, xpress16k and lzx.
+ If activated you will be able to read such files correctly.
+
+ It is recommended to say Y here.
+
+config NTFS3_FS_POSIX_ACL
+ bool "NTFS POSIX Access Control Lists"
+ depends on NTFS3_FS
+ select FS_POSIX_ACL
+ help
+ POSIX Access Control Lists (ACLs) support additional access rights
+ for users and groups beyond the standard owner/group/world scheme,
+ and this option selects support for ACLs specifically for ntfs
+ filesystems.
+ NOTE: this is linux only feature. Windows will ignore these ACLs.
+
+ If you don't know what Access Control Lists are, say N.
diff --git a/fs/ntfs3/Makefile b/fs/ntfs3/Makefile
new file mode 100644
index 000000000000..279701b62bbe
--- /dev/null
+++ b/fs/ntfs3/Makefile
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the ntfs3 filesystem support.
+#
+
+# to check robot warnings
+ccflags-y += -Wint-to-pointer-cast \
+ $(call cc-option,-Wunused-but-set-variable,-Wunused-const-variable) \
+ $(call cc-option,-Wold-style-declaration,-Wout-of-line-declaration)
+
+obj-$(CONFIG_NTFS3_FS) += ntfs3.o
+
+ntfs3-y := attrib.o \
+ attrlist.o \
+ bitfunc.o \
+ bitmap.o \
+ dir.o \
+ fsntfs.o \
+ frecord.o \
+ file.o \
+ fslog.o \
+ inode.o \
+ index.o \
+ lznt.o \
+ namei.o \
+ record.o \
+ run.o \
+ super.o \
+ upcase.o \
+ xattr.o
+
+ntfs3-$(CONFIG_NTFS3_LZX_XPRESS) += $(addprefix lib/,\
+ decompress_common.o \
+ lzx_decompress.o \
+ xpress_decompress.o \
+ ) \ No newline at end of file
diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c
new file mode 100644
index 000000000000..34c4cbf7e29b
--- /dev/null
+++ b/fs/ntfs3/attrib.c
@@ -0,0 +1,2093 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ * TODO: Merge attr_set_size/attr_data_get_block/attr_allocate_frame?
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/hash.h>
+#include <linux/nls.h>
+#include <linux/ratelimit.h>
+#include <linux/slab.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+/*
+ * You can set external NTFS_MIN_LOG2_OF_CLUMP/NTFS_MAX_LOG2_OF_CLUMP to manage
+ * preallocate algorithm.
+ */
+#ifndef NTFS_MIN_LOG2_OF_CLUMP
+#define NTFS_MIN_LOG2_OF_CLUMP 16
+#endif
+
+#ifndef NTFS_MAX_LOG2_OF_CLUMP
+#define NTFS_MAX_LOG2_OF_CLUMP 26
+#endif
+
+// 16M
+#define NTFS_CLUMP_MIN (1 << (NTFS_MIN_LOG2_OF_CLUMP + 8))
+// 16G
+#define NTFS_CLUMP_MAX (1ull << (NTFS_MAX_LOG2_OF_CLUMP + 8))
+
+static inline u64 get_pre_allocated(u64 size)
+{
+ u32 clump;
+ u8 align_shift;
+ u64 ret;
+
+ if (size <= NTFS_CLUMP_MIN) {
+ clump = 1 << NTFS_MIN_LOG2_OF_CLUMP;
+ align_shift = NTFS_MIN_LOG2_OF_CLUMP;
+ } else if (size >= NTFS_CLUMP_MAX) {
+ clump = 1 << NTFS_MAX_LOG2_OF_CLUMP;
+ align_shift = NTFS_MAX_LOG2_OF_CLUMP;
+ } else {
+ align_shift = NTFS_MIN_LOG2_OF_CLUMP - 1 +
+ __ffs(size >> (8 + NTFS_MIN_LOG2_OF_CLUMP));
+ clump = 1u << align_shift;
+ }
+
+ ret = (((size + clump - 1) >> align_shift)) << align_shift;
+
+ return ret;
+}
+
+/*
+ * attr_must_be_resident
+ *
+ * Return: True if attribute must be resident.
+ */
+static inline bool attr_must_be_resident(struct ntfs_sb_info *sbi,
+ enum ATTR_TYPE type)
+{
+ const struct ATTR_DEF_ENTRY *de;
+
+ switch (type) {
+ case ATTR_STD:
+ case ATTR_NAME:
+ case ATTR_ID:
+ case ATTR_LABEL:
+ case ATTR_VOL_INFO:
+ case ATTR_ROOT:
+ case ATTR_EA_INFO:
+ return true;
+ default:
+ de = ntfs_query_def(sbi, type);
+ if (de && (de->flags & NTFS_ATTR_MUST_BE_RESIDENT))
+ return true;
+ return false;
+ }
+}
+
+/*
+ * attr_load_runs - Load all runs stored in @attr.
+ */
+int attr_load_runs(struct ATTRIB *attr, struct ntfs_inode *ni,
+ struct runs_tree *run, const CLST *vcn)
+{
+ int err;
+ CLST svcn = le64_to_cpu(attr->nres.svcn);
+ CLST evcn = le64_to_cpu(attr->nres.evcn);
+ u32 asize;
+ u16 run_off;
+
+ if (svcn >= evcn + 1 || run_is_mapped_full(run, svcn, evcn))
+ return 0;
+
+ if (vcn && (evcn < *vcn || *vcn < svcn))
+ return -EINVAL;
+
+ asize = le32_to_cpu(attr->size);
+ run_off = le16_to_cpu(attr->nres.run_off);
+ err = run_unpack_ex(run, ni->mi.sbi, ni->mi.rno, svcn, evcn,
+ vcn ? *vcn : svcn, Add2Ptr(attr, run_off),
+ asize - run_off);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+/*
+ * run_deallocate_ex - Deallocate clusters.
+ */
+static int run_deallocate_ex(struct ntfs_sb_info *sbi, struct runs_tree *run,
+ CLST vcn, CLST len, CLST *done, bool trim)
+{
+ int err = 0;
+ CLST vcn_next, vcn0 = vcn, lcn, clen, dn = 0;
+ size_t idx;
+
+ if (!len)
+ goto out;
+
+ if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
+failed:
+ run_truncate(run, vcn0);
+ err = -EINVAL;
+ goto out;
+ }
+
+ for (;;) {
+ if (clen > len)
+ clen = len;
+
+ if (!clen) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (lcn != SPARSE_LCN) {
+ mark_as_free_ex(sbi, lcn, clen, trim);
+ dn += clen;
+ }
+
+ len -= clen;
+ if (!len)
+ break;
+
+ vcn_next = vcn + clen;
+ if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
+ vcn != vcn_next) {
+ /* Save memory - don't load entire run. */
+ goto failed;
+ }
+ }
+
+out:
+ if (done)
+ *done += dn;
+
+ return err;
+}
+
+/*
+ * attr_allocate_clusters - Find free space, mark it as used and store in @run.
+ */
+int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run,
+ CLST vcn, CLST lcn, CLST len, CLST *pre_alloc,
+ enum ALLOCATE_OPT opt, CLST *alen, const size_t fr,
+ CLST *new_lcn)
+{
+ int err;
+ CLST flen, vcn0 = vcn, pre = pre_alloc ? *pre_alloc : 0;
+ struct wnd_bitmap *wnd = &sbi->used.bitmap;
+ size_t cnt = run->count;
+
+ for (;;) {
+ err = ntfs_look_for_free_space(sbi, lcn, len + pre, &lcn, &flen,
+ opt);
+
+ if (err == -ENOSPC && pre) {
+ pre = 0;
+ if (*pre_alloc)
+ *pre_alloc = 0;
+ continue;
+ }
+
+ if (err)
+ goto out;
+
+ if (new_lcn && vcn == vcn0)
+ *new_lcn = lcn;
+
+ /* Add new fragment into run storage. */
+ if (!run_add_entry(run, vcn, lcn, flen, opt == ALLOCATE_MFT)) {
+ /* Undo last 'ntfs_look_for_free_space' */
+ down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
+ wnd_set_free(wnd, lcn, flen);
+ up_write(&wnd->rw_lock);
+ err = -ENOMEM;
+ goto out;
+ }
+
+ vcn += flen;
+
+ if (flen >= len || opt == ALLOCATE_MFT ||
+ (fr && run->count - cnt >= fr)) {
+ *alen = vcn - vcn0;
+ return 0;
+ }
+
+ len -= flen;
+ }
+
+out:
+ /* Undo 'ntfs_look_for_free_space' */
+ if (vcn - vcn0) {
+ run_deallocate_ex(sbi, run, vcn0, vcn - vcn0, NULL, false);
+ run_truncate(run, vcn0);
+ }
+
+ return err;
+}
+
+/*
+ * attr_make_nonresident
+ *
+ * If page is not NULL - it is already contains resident data
+ * and locked (called from ni_write_frame()).
+ */
+int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct ATTR_LIST_ENTRY *le, struct mft_inode *mi,
+ u64 new_size, struct runs_tree *run,
+ struct ATTRIB **ins_attr, struct page *page)
+{
+ struct ntfs_sb_info *sbi;
+ struct ATTRIB *attr_s;
+ struct MFT_REC *rec;
+ u32 used, asize, rsize, aoff, align;
+ bool is_data;
+ CLST len, alen;
+ char *next;
+ int err;
+
+ if (attr->non_res) {
+ *ins_attr = attr;
+ return 0;
+ }
+
+ sbi = mi->sbi;
+ rec = mi->mrec;
+ attr_s = NULL;
+ used = le32_to_cpu(rec->used);
+ asize = le32_to_cpu(attr->size);
+ next = Add2Ptr(attr, asize);
+ aoff = PtrOffset(rec, attr);
+ rsize = le32_to_cpu(attr->res.data_size);
+ is_data = attr->type == ATTR_DATA && !attr->name_len;
+
+ align = sbi->cluster_size;
+ if (is_attr_compressed(attr))
+ align <<= COMPRESSION_UNIT;
+ len = (rsize + align - 1) >> sbi->cluster_bits;
+
+ run_init(run);
+
+ /* Make a copy of original attribute. */
+ attr_s = kmemdup(attr, asize, GFP_NOFS);
+ if (!attr_s) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ if (!len) {
+ /* Empty resident -> Empty nonresident. */
+ alen = 0;
+ } else {
+ const char *data = resident_data(attr);
+
+ err = attr_allocate_clusters(sbi, run, 0, 0, len, NULL,
+ ALLOCATE_DEF, &alen, 0, NULL);
+ if (err)
+ goto out1;
+
+ if (!rsize) {
+ /* Empty resident -> Non empty nonresident. */
+ } else if (!is_data) {
+ err = ntfs_sb_write_run(sbi, run, 0, data, rsize);
+ if (err)
+ goto out2;
+ } else if (!page) {
+ char *kaddr;
+
+ page = grab_cache_page(ni->vfs_inode.i_mapping, 0);
+ if (!page) {
+ err = -ENOMEM;
+ goto out2;
+ }
+ kaddr = kmap_atomic(page);
+ memcpy(kaddr, data, rsize);
+ memset(kaddr + rsize, 0, PAGE_SIZE - rsize);
+ kunmap_atomic(kaddr);
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ set_page_dirty(page);
+ unlock_page(page);
+ put_page(page);
+ }
+ }
+
+ /* Remove original attribute. */
+ used -= asize;
+ memmove(attr, Add2Ptr(attr, asize), used - aoff);
+ rec->used = cpu_to_le32(used);
+ mi->dirty = true;
+ if (le)
+ al_remove_le(ni, le);
+
+ err = ni_insert_nonresident(ni, attr_s->type, attr_name(attr_s),
+ attr_s->name_len, run, 0, alen,
+ attr_s->flags, &attr, NULL);
+ if (err)
+ goto out3;
+
+ kfree(attr_s);
+ attr->nres.data_size = cpu_to_le64(rsize);
+ attr->nres.valid_size = attr->nres.data_size;
+
+ *ins_attr = attr;
+
+ if (is_data)
+ ni->ni_flags &= ~NI_FLAG_RESIDENT;
+
+ /* Resident attribute becomes non resident. */
+ return 0;
+
+out3:
+ attr = Add2Ptr(rec, aoff);
+ memmove(next, attr, used - aoff);
+ memcpy(attr, attr_s, asize);
+ rec->used = cpu_to_le32(used + asize);
+ mi->dirty = true;
+out2:
+ /* Undo: do not trim new allocated clusters. */
+ run_deallocate(sbi, run, false);
+ run_close(run);
+out1:
+ kfree(attr_s);
+out:
+ return err;
+}
+
+/*
+ * attr_set_size_res - Helper for attr_set_size().
+ */
+static int attr_set_size_res(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct ATTR_LIST_ENTRY *le, struct mft_inode *mi,
+ u64 new_size, struct runs_tree *run,
+ struct ATTRIB **ins_attr)
+{
+ struct ntfs_sb_info *sbi = mi->sbi;
+ struct MFT_REC *rec = mi->mrec;
+ u32 used = le32_to_cpu(rec->used);
+ u32 asize = le32_to_cpu(attr->size);
+ u32 aoff = PtrOffset(rec, attr);
+ u32 rsize = le32_to_cpu(attr->res.data_size);
+ u32 tail = used - aoff - asize;
+ char *next = Add2Ptr(attr, asize);
+ s64 dsize = ALIGN(new_size, 8) - ALIGN(rsize, 8);
+
+ if (dsize < 0) {
+ memmove(next + dsize, next, tail);
+ } else if (dsize > 0) {
+ if (used + dsize > sbi->max_bytes_per_attr)
+ return attr_make_nonresident(ni, attr, le, mi, new_size,
+ run, ins_attr, NULL);
+
+ memmove(next + dsize, next, tail);
+ memset(next, 0, dsize);
+ }
+
+ if (new_size > rsize)
+ memset(Add2Ptr(resident_data(attr), rsize), 0,
+ new_size - rsize);
+
+ rec->used = cpu_to_le32(used + dsize);
+ attr->size = cpu_to_le32(asize + dsize);
+ attr->res.data_size = cpu_to_le32(new_size);
+ mi->dirty = true;
+ *ins_attr = attr;
+
+ return 0;
+}
+
+/*
+ * attr_set_size - Change the size of attribute.
+ *
+ * Extend:
+ * - Sparse/compressed: No allocated clusters.
+ * - Normal: Append allocated and preallocated new clusters.
+ * Shrink:
+ * - No deallocate if @keep_prealloc is set.
+ */
+int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, struct runs_tree *run,
+ u64 new_size, const u64 *new_valid, bool keep_prealloc,
+ struct ATTRIB **ret)
+{
+ int err = 0;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ u8 cluster_bits = sbi->cluster_bits;
+ bool is_mft =
+ ni->mi.rno == MFT_REC_MFT && type == ATTR_DATA && !name_len;
+ u64 old_valid, old_size, old_alloc, new_alloc, new_alloc_tmp;
+ struct ATTRIB *attr = NULL, *attr_b;
+ struct ATTR_LIST_ENTRY *le, *le_b;
+ struct mft_inode *mi, *mi_b;
+ CLST alen, vcn, lcn, new_alen, old_alen, svcn, evcn;
+ CLST next_svcn, pre_alloc = -1, done = 0;
+ bool is_ext;
+ u32 align;
+ struct MFT_REC *rec;
+
+again:
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, type, name, name_len, NULL,
+ &mi_b);
+ if (!attr_b) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (!attr_b->non_res) {
+ err = attr_set_size_res(ni, attr_b, le_b, mi_b, new_size, run,
+ &attr_b);
+ if (err || !attr_b->non_res)
+ goto out;
+
+ /* Layout of records may be changed, so do a full search. */
+ goto again;
+ }
+
+ is_ext = is_attr_ext(attr_b);
+
+again_1:
+ align = sbi->cluster_size;
+
+ if (is_ext) {
+ align <<= attr_b->nres.c_unit;
+ if (is_attr_sparsed(attr_b))
+ keep_prealloc = false;
+ }
+
+ old_valid = le64_to_cpu(attr_b->nres.valid_size);
+ old_size = le64_to_cpu(attr_b->nres.data_size);
+ old_alloc = le64_to_cpu(attr_b->nres.alloc_size);
+ old_alen = old_alloc >> cluster_bits;
+
+ new_alloc = (new_size + align - 1) & ~(u64)(align - 1);
+ new_alen = new_alloc >> cluster_bits;
+
+ if (keep_prealloc && is_ext)
+ keep_prealloc = false;
+
+ if (keep_prealloc && new_size < old_size) {
+ attr_b->nres.data_size = cpu_to_le64(new_size);
+ mi_b->dirty = true;
+ goto ok;
+ }
+
+ vcn = old_alen - 1;
+
+ svcn = le64_to_cpu(attr_b->nres.svcn);
+ evcn = le64_to_cpu(attr_b->nres.evcn);
+
+ if (svcn <= vcn && vcn <= evcn) {
+ attr = attr_b;
+ le = le_b;
+ mi = mi_b;
+ } else if (!le_b) {
+ err = -EINVAL;
+ goto out;
+ } else {
+ le = le_b;
+ attr = ni_find_attr(ni, attr_b, &le, type, name, name_len, &vcn,
+ &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+next_le_1:
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn = le64_to_cpu(attr->nres.evcn);
+ }
+
+next_le:
+ rec = mi->mrec;
+
+ err = attr_load_runs(attr, ni, run, NULL);
+ if (err)
+ goto out;
+
+ if (new_size > old_size) {
+ CLST to_allocate;
+ size_t free;
+
+ if (new_alloc <= old_alloc) {
+ attr_b->nres.data_size = cpu_to_le64(new_size);
+ mi_b->dirty = true;
+ goto ok;
+ }
+
+ to_allocate = new_alen - old_alen;
+add_alloc_in_same_attr_seg:
+ lcn = 0;
+ if (is_mft) {
+ /* MFT allocates clusters from MFT zone. */
+ pre_alloc = 0;
+ } else if (is_ext) {
+ /* No preallocate for sparse/compress. */
+ pre_alloc = 0;
+ } else if (pre_alloc == -1) {
+ pre_alloc = 0;
+ if (type == ATTR_DATA && !name_len &&
+ sbi->options.prealloc) {
+ CLST new_alen2 = bytes_to_cluster(
+ sbi, get_pre_allocated(new_size));
+ pre_alloc = new_alen2 - new_alen;
+ }
+
+ /* Get the last LCN to allocate from. */
+ if (old_alen &&
+ !run_lookup_entry(run, vcn, &lcn, NULL, NULL)) {
+ lcn = SPARSE_LCN;
+ }
+
+ if (lcn == SPARSE_LCN)
+ lcn = 0;
+ else if (lcn)
+ lcn += 1;
+
+ free = wnd_zeroes(&sbi->used.bitmap);
+ if (to_allocate > free) {
+ err = -ENOSPC;
+ goto out;
+ }
+
+ if (pre_alloc && to_allocate + pre_alloc > free)
+ pre_alloc = 0;
+ }
+
+ vcn = old_alen;
+
+ if (is_ext) {
+ if (!run_add_entry(run, vcn, SPARSE_LCN, to_allocate,
+ false)) {
+ err = -ENOMEM;
+ goto out;
+ }
+ alen = to_allocate;
+ } else {
+ /* ~3 bytes per fragment. */
+ err = attr_allocate_clusters(
+ sbi, run, vcn, lcn, to_allocate, &pre_alloc,
+ is_mft ? ALLOCATE_MFT : 0, &alen,
+ is_mft ? 0
+ : (sbi->record_size -
+ le32_to_cpu(rec->used) + 8) /
+ 3 +
+ 1,
+ NULL);
+ if (err)
+ goto out;
+ }
+
+ done += alen;
+ vcn += alen;
+ if (to_allocate > alen)
+ to_allocate -= alen;
+ else
+ to_allocate = 0;
+
+pack_runs:
+ err = mi_pack_runs(mi, attr, run, vcn - svcn);
+ if (err)
+ goto out;
+
+ next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
+ new_alloc_tmp = (u64)next_svcn << cluster_bits;
+ attr_b->nres.alloc_size = cpu_to_le64(new_alloc_tmp);
+ mi_b->dirty = true;
+
+ if (next_svcn >= vcn && !to_allocate) {
+ /* Normal way. Update attribute and exit. */
+ attr_b->nres.data_size = cpu_to_le64(new_size);
+ goto ok;
+ }
+
+ /* At least two MFT to avoid recursive loop. */
+ if (is_mft && next_svcn == vcn &&
+ ((u64)done << sbi->cluster_bits) >= 2 * sbi->record_size) {
+ new_size = new_alloc_tmp;
+ attr_b->nres.data_size = attr_b->nres.alloc_size;
+ goto ok;
+ }
+
+ if (le32_to_cpu(rec->used) < sbi->record_size) {
+ old_alen = next_svcn;
+ evcn = old_alen - 1;
+ goto add_alloc_in_same_attr_seg;
+ }
+
+ attr_b->nres.data_size = attr_b->nres.alloc_size;
+ if (new_alloc_tmp < old_valid)
+ attr_b->nres.valid_size = attr_b->nres.data_size;
+
+ if (type == ATTR_LIST) {
+ err = ni_expand_list(ni);
+ if (err)
+ goto out;
+ if (next_svcn < vcn)
+ goto pack_runs;
+
+ /* Layout of records is changed. */
+ goto again;
+ }
+
+ if (!ni->attr_list.size) {
+ err = ni_create_attr_list(ni);
+ if (err)
+ goto out;
+ /* Layout of records is changed. */
+ }
+
+ if (next_svcn >= vcn) {
+ /* This is MFT data, repeat. */
+ goto again;
+ }
+
+ /* Insert new attribute segment. */
+ err = ni_insert_nonresident(ni, type, name, name_len, run,
+ next_svcn, vcn - next_svcn,
+ attr_b->flags, &attr, &mi);
+ if (err)
+ goto out;
+
+ if (!is_mft)
+ run_truncate_head(run, evcn + 1);
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn = le64_to_cpu(attr->nres.evcn);
+
+ le_b = NULL;
+ /*
+ * Layout of records maybe changed.
+ * Find base attribute to update.
+ */
+ attr_b = ni_find_attr(ni, NULL, &le_b, type, name, name_len,
+ NULL, &mi_b);
+ if (!attr_b) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ attr_b->nres.alloc_size = cpu_to_le64((u64)vcn << cluster_bits);
+ attr_b->nres.data_size = attr_b->nres.alloc_size;
+ attr_b->nres.valid_size = attr_b->nres.alloc_size;
+ mi_b->dirty = true;
+ goto again_1;
+ }
+
+ if (new_size != old_size ||
+ (new_alloc != old_alloc && !keep_prealloc)) {
+ vcn = max(svcn, new_alen);
+ new_alloc_tmp = (u64)vcn << cluster_bits;
+
+ alen = 0;
+ err = run_deallocate_ex(sbi, run, vcn, evcn - vcn + 1, &alen,
+ true);
+ if (err)
+ goto out;
+
+ run_truncate(run, vcn);
+
+ if (vcn > svcn) {
+ err = mi_pack_runs(mi, attr, run, vcn - svcn);
+ if (err)
+ goto out;
+ } else if (le && le->vcn) {
+ u16 le_sz = le16_to_cpu(le->size);
+
+ /*
+ * NOTE: List entries for one attribute are always
+ * the same size. We deal with last entry (vcn==0)
+ * and it is not first in entries array
+ * (list entry for std attribute always first).
+ * So it is safe to step back.
+ */
+ mi_remove_attr(NULL, mi, attr);
+
+ if (!al_remove_le(ni, le)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ le = (struct ATTR_LIST_ENTRY *)((u8 *)le - le_sz);
+ } else {
+ attr->nres.evcn = cpu_to_le64((u64)vcn - 1);
+ mi->dirty = true;
+ }
+
+ attr_b->nres.alloc_size = cpu_to_le64(new_alloc_tmp);
+
+ if (vcn == new_alen) {
+ attr_b->nres.data_size = cpu_to_le64(new_size);
+ if (new_size < old_valid)
+ attr_b->nres.valid_size =
+ attr_b->nres.data_size;
+ } else {
+ if (new_alloc_tmp <=
+ le64_to_cpu(attr_b->nres.data_size))
+ attr_b->nres.data_size =
+ attr_b->nres.alloc_size;
+ if (new_alloc_tmp <
+ le64_to_cpu(attr_b->nres.valid_size))
+ attr_b->nres.valid_size =
+ attr_b->nres.alloc_size;
+ }
+
+ if (is_ext)
+ le64_sub_cpu(&attr_b->nres.total_size,
+ ((u64)alen << cluster_bits));
+
+ mi_b->dirty = true;
+
+ if (new_alloc_tmp <= new_alloc)
+ goto ok;
+
+ old_size = new_alloc_tmp;
+ vcn = svcn - 1;
+
+ if (le == le_b) {
+ attr = attr_b;
+ mi = mi_b;
+ evcn = svcn - 1;
+ svcn = 0;
+ goto next_le;
+ }
+
+ if (le->type != type || le->name_len != name_len ||
+ memcmp(le_name(le), name, name_len * sizeof(short))) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = ni_load_mi(ni, le, &mi);
+ if (err)
+ goto out;
+
+ attr = mi_find_attr(mi, NULL, type, name, name_len, &le->id);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+ goto next_le_1;
+ }
+
+ok:
+ if (new_valid) {
+ __le64 valid = cpu_to_le64(min(*new_valid, new_size));
+
+ if (attr_b->nres.valid_size != valid) {
+ attr_b->nres.valid_size = valid;
+ mi_b->dirty = true;
+ }
+ }
+
+out:
+ if (!err && attr_b && ret)
+ *ret = attr_b;
+
+ /* Update inode_set_bytes. */
+ if (!err && ((type == ATTR_DATA && !name_len) ||
+ (type == ATTR_ALLOC && name == I30_NAME))) {
+ bool dirty = false;
+
+ if (ni->vfs_inode.i_size != new_size) {
+ ni->vfs_inode.i_size = new_size;
+ dirty = true;
+ }
+
+ if (attr_b && attr_b->non_res) {
+ new_alloc = le64_to_cpu(attr_b->nres.alloc_size);
+ if (inode_get_bytes(&ni->vfs_inode) != new_alloc) {
+ inode_set_bytes(&ni->vfs_inode, new_alloc);
+ dirty = true;
+ }
+ }
+
+ if (dirty) {
+ ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
+ mark_inode_dirty(&ni->vfs_inode);
+ }
+ }
+
+ return err;
+}
+
+int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
+ CLST *len, bool *new)
+{
+ int err = 0;
+ struct runs_tree *run = &ni->file.run;
+ struct ntfs_sb_info *sbi;
+ u8 cluster_bits;
+ struct ATTRIB *attr = NULL, *attr_b;
+ struct ATTR_LIST_ENTRY *le, *le_b;
+ struct mft_inode *mi, *mi_b;
+ CLST hint, svcn, to_alloc, evcn1, next_svcn, asize, end;
+ u64 total_size;
+ u32 clst_per_frame;
+ bool ok;
+
+ if (new)
+ *new = false;
+
+ down_read(&ni->file.run_lock);
+ ok = run_lookup_entry(run, vcn, lcn, len, NULL);
+ up_read(&ni->file.run_lock);
+
+ if (ok && (*lcn != SPARSE_LCN || !new)) {
+ /* Normal way. */
+ return 0;
+ }
+
+ if (!clen)
+ clen = 1;
+
+ if (ok && clen > *len)
+ clen = *len;
+
+ sbi = ni->mi.sbi;
+ cluster_bits = sbi->cluster_bits;
+
+ ni_lock(ni);
+ down_write(&ni->file.run_lock);
+
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b);
+ if (!attr_b) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (!attr_b->non_res) {
+ *lcn = RESIDENT_LCN;
+ *len = 1;
+ goto out;
+ }
+
+ asize = le64_to_cpu(attr_b->nres.alloc_size) >> sbi->cluster_bits;
+ if (vcn >= asize) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ clst_per_frame = 1u << attr_b->nres.c_unit;
+ to_alloc = (clen + clst_per_frame - 1) & ~(clst_per_frame - 1);
+
+ if (vcn + to_alloc > asize)
+ to_alloc = asize - vcn;
+
+ svcn = le64_to_cpu(attr_b->nres.svcn);
+ evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1;
+
+ attr = attr_b;
+ le = le_b;
+ mi = mi_b;
+
+ if (le_b && (vcn < svcn || evcn1 <= vcn)) {
+ attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn,
+ &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+
+ err = attr_load_runs(attr, ni, run, NULL);
+ if (err)
+ goto out;
+
+ if (!ok) {
+ ok = run_lookup_entry(run, vcn, lcn, len, NULL);
+ if (ok && (*lcn != SPARSE_LCN || !new)) {
+ /* Normal way. */
+ err = 0;
+ goto ok;
+ }
+
+ if (!ok && !new) {
+ *len = 0;
+ err = 0;
+ goto ok;
+ }
+
+ if (ok && clen > *len) {
+ clen = *len;
+ to_alloc = (clen + clst_per_frame - 1) &
+ ~(clst_per_frame - 1);
+ }
+ }
+
+ if (!is_attr_ext(attr_b)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Get the last LCN to allocate from. */
+ hint = 0;
+
+ if (vcn > evcn1) {
+ if (!run_add_entry(run, evcn1, SPARSE_LCN, vcn - evcn1,
+ false)) {
+ err = -ENOMEM;
+ goto out;
+ }
+ } else if (vcn && !run_lookup_entry(run, vcn - 1, &hint, NULL, NULL)) {
+ hint = -1;
+ }
+
+ err = attr_allocate_clusters(
+ sbi, run, vcn, hint + 1, to_alloc, NULL, 0, len,
+ (sbi->record_size - le32_to_cpu(mi->mrec->used) + 8) / 3 + 1,
+ lcn);
+ if (err)
+ goto out;
+ *new = true;
+
+ end = vcn + *len;
+
+ total_size = le64_to_cpu(attr_b->nres.total_size) +
+ ((u64)*len << cluster_bits);
+
+repack:
+ err = mi_pack_runs(mi, attr, run, max(end, evcn1) - svcn);
+ if (err)
+ goto out;
+
+ attr_b->nres.total_size = cpu_to_le64(total_size);
+ inode_set_bytes(&ni->vfs_inode, total_size);
+ ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
+
+ mi_b->dirty = true;
+ mark_inode_dirty(&ni->vfs_inode);
+
+ /* Stored [vcn : next_svcn) from [vcn : end). */
+ next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
+
+ if (end <= evcn1) {
+ if (next_svcn == evcn1) {
+ /* Normal way. Update attribute and exit. */
+ goto ok;
+ }
+ /* Add new segment [next_svcn : evcn1 - next_svcn). */
+ if (!ni->attr_list.size) {
+ err = ni_create_attr_list(ni);
+ if (err)
+ goto out;
+ /* Layout of records is changed. */
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL,
+ 0, NULL, &mi_b);
+ if (!attr_b) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ attr = attr_b;
+ le = le_b;
+ mi = mi_b;
+ goto repack;
+ }
+ }
+
+ svcn = evcn1;
+
+ /* Estimate next attribute. */
+ attr = ni_find_attr(ni, attr, &le, ATTR_DATA, NULL, 0, &svcn, &mi);
+
+ if (attr) {
+ CLST alloc = bytes_to_cluster(
+ sbi, le64_to_cpu(attr_b->nres.alloc_size));
+ CLST evcn = le64_to_cpu(attr->nres.evcn);
+
+ if (end < next_svcn)
+ end = next_svcn;
+ while (end > evcn) {
+ /* Remove segment [svcn : evcn). */
+ mi_remove_attr(NULL, mi, attr);
+
+ if (!al_remove_le(ni, le)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (evcn + 1 >= alloc) {
+ /* Last attribute segment. */
+ evcn1 = evcn + 1;
+ goto ins_ext;
+ }
+
+ if (ni_load_mi(ni, le, &mi)) {
+ attr = NULL;
+ goto out;
+ }
+
+ attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0,
+ &le->id);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn = le64_to_cpu(attr->nres.evcn);
+ }
+
+ if (end < svcn)
+ end = svcn;
+
+ err = attr_load_runs(attr, ni, run, &end);
+ if (err)
+ goto out;
+
+ evcn1 = evcn + 1;
+ attr->nres.svcn = cpu_to_le64(next_svcn);
+ err = mi_pack_runs(mi, attr, run, evcn1 - next_svcn);
+ if (err)
+ goto out;
+
+ le->vcn = cpu_to_le64(next_svcn);
+ ni->attr_list.dirty = true;
+ mi->dirty = true;
+
+ next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+ins_ext:
+ if (evcn1 > next_svcn) {
+ err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run,
+ next_svcn, evcn1 - next_svcn,
+ attr_b->flags, &attr, &mi);
+ if (err)
+ goto out;
+ }
+ok:
+ run_truncate_around(run, vcn);
+out:
+ up_write(&ni->file.run_lock);
+ ni_unlock(ni);
+
+ return err;
+}
+
+int attr_data_read_resident(struct ntfs_inode *ni, struct page *page)
+{
+ u64 vbo;
+ struct ATTRIB *attr;
+ u32 data_size;
+
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, NULL);
+ if (!attr)
+ return -EINVAL;
+
+ if (attr->non_res)
+ return E_NTFS_NONRESIDENT;
+
+ vbo = page->index << PAGE_SHIFT;
+ data_size = le32_to_cpu(attr->res.data_size);
+ if (vbo < data_size) {
+ const char *data = resident_data(attr);
+ char *kaddr = kmap_atomic(page);
+ u32 use = data_size - vbo;
+
+ if (use > PAGE_SIZE)
+ use = PAGE_SIZE;
+
+ memcpy(kaddr, data + vbo, use);
+ memset(kaddr + use, 0, PAGE_SIZE - use);
+ kunmap_atomic(kaddr);
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ } else if (!PageUptodate(page)) {
+ zero_user_segment(page, 0, PAGE_SIZE);
+ SetPageUptodate(page);
+ }
+
+ return 0;
+}
+
+int attr_data_write_resident(struct ntfs_inode *ni, struct page *page)
+{
+ u64 vbo;
+ struct mft_inode *mi;
+ struct ATTRIB *attr;
+ u32 data_size;
+
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, &mi);
+ if (!attr)
+ return -EINVAL;
+
+ if (attr->non_res) {
+ /* Return special error code to check this case. */
+ return E_NTFS_NONRESIDENT;
+ }
+
+ vbo = page->index << PAGE_SHIFT;
+ data_size = le32_to_cpu(attr->res.data_size);
+ if (vbo < data_size) {
+ char *data = resident_data(attr);
+ char *kaddr = kmap_atomic(page);
+ u32 use = data_size - vbo;
+
+ if (use > PAGE_SIZE)
+ use = PAGE_SIZE;
+ memcpy(data + vbo, kaddr, use);
+ kunmap_atomic(kaddr);
+ mi->dirty = true;
+ }
+ ni->i_valid = data_size;
+
+ return 0;
+}
+
+/*
+ * attr_load_runs_vcn - Load runs with VCN.
+ */
+int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, struct runs_tree *run,
+ CLST vcn)
+{
+ struct ATTRIB *attr;
+ int err;
+ CLST svcn, evcn;
+ u16 ro;
+
+ attr = ni_find_attr(ni, NULL, NULL, type, name, name_len, &vcn, NULL);
+ if (!attr) {
+ /* Is record corrupted? */
+ return -ENOENT;
+ }
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn = le64_to_cpu(attr->nres.evcn);
+
+ if (evcn < vcn || vcn < svcn) {
+ /* Is record corrupted? */
+ return -EINVAL;
+ }
+
+ ro = le16_to_cpu(attr->nres.run_off);
+ err = run_unpack_ex(run, ni->mi.sbi, ni->mi.rno, svcn, evcn, svcn,
+ Add2Ptr(attr, ro), le32_to_cpu(attr->size) - ro);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+/*
+ * attr_load_runs_range - Load runs for given range [from to).
+ */
+int attr_load_runs_range(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, struct runs_tree *run,
+ u64 from, u64 to)
+{
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ u8 cluster_bits = sbi->cluster_bits;
+ CLST vcn = from >> cluster_bits;
+ CLST vcn_last = (to - 1) >> cluster_bits;
+ CLST lcn, clen;
+ int err;
+
+ for (vcn = from >> cluster_bits; vcn <= vcn_last; vcn += clen) {
+ if (!run_lookup_entry(run, vcn, &lcn, &clen, NULL)) {
+ err = attr_load_runs_vcn(ni, type, name, name_len, run,
+ vcn);
+ if (err)
+ return err;
+ clen = 0; /* Next run_lookup_entry(vcn) must be success. */
+ }
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+/*
+ * attr_wof_frame_info
+ *
+ * Read header of Xpress/LZX file to get info about frame.
+ */
+int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct runs_tree *run, u64 frame, u64 frames,
+ u8 frame_bits, u32 *ondisk_size, u64 *vbo_data)
+{
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ u64 vbo[2], off[2], wof_size;
+ u32 voff;
+ u8 bytes_per_off;
+ char *addr;
+ struct page *page;
+ int i, err;
+ __le32 *off32;
+ __le64 *off64;
+
+ if (ni->vfs_inode.i_size < 0x100000000ull) {
+ /* File starts with array of 32 bit offsets. */
+ bytes_per_off = sizeof(__le32);
+ vbo[1] = frame << 2;
+ *vbo_data = frames << 2;
+ } else {
+ /* File starts with array of 64 bit offsets. */
+ bytes_per_off = sizeof(__le64);
+ vbo[1] = frame << 3;
+ *vbo_data = frames << 3;
+ }
+
+ /*
+ * Read 4/8 bytes at [vbo - 4(8)] == offset where compressed frame starts.
+ * Read 4/8 bytes at [vbo] == offset where compressed frame ends.
+ */
+ if (!attr->non_res) {
+ if (vbo[1] + bytes_per_off > le32_to_cpu(attr->res.data_size)) {
+ ntfs_inode_err(&ni->vfs_inode, "is corrupted");
+ return -EINVAL;
+ }
+ addr = resident_data(attr);
+
+ if (bytes_per_off == sizeof(__le32)) {
+ off32 = Add2Ptr(addr, vbo[1]);
+ off[0] = vbo[1] ? le32_to_cpu(off32[-1]) : 0;
+ off[1] = le32_to_cpu(off32[0]);
+ } else {
+ off64 = Add2Ptr(addr, vbo[1]);
+ off[0] = vbo[1] ? le64_to_cpu(off64[-1]) : 0;
+ off[1] = le64_to_cpu(off64[0]);
+ }
+
+ *vbo_data += off[0];
+ *ondisk_size = off[1] - off[0];
+ return 0;
+ }
+
+ wof_size = le64_to_cpu(attr->nres.data_size);
+ down_write(&ni->file.run_lock);
+ page = ni->file.offs_page;
+ if (!page) {
+ page = alloc_page(GFP_KERNEL);
+ if (!page) {
+ err = -ENOMEM;
+ goto out;
+ }
+ page->index = -1;
+ ni->file.offs_page = page;
+ }
+ lock_page(page);
+ addr = page_address(page);
+
+ if (vbo[1]) {
+ voff = vbo[1] & (PAGE_SIZE - 1);
+ vbo[0] = vbo[1] - bytes_per_off;
+ i = 0;
+ } else {
+ voff = 0;
+ vbo[0] = 0;
+ off[0] = 0;
+ i = 1;
+ }
+
+ do {
+ pgoff_t index = vbo[i] >> PAGE_SHIFT;
+
+ if (index != page->index) {
+ u64 from = vbo[i] & ~(u64)(PAGE_SIZE - 1);
+ u64 to = min(from + PAGE_SIZE, wof_size);
+
+ err = attr_load_runs_range(ni, ATTR_DATA, WOF_NAME,
+ ARRAY_SIZE(WOF_NAME), run,
+ from, to);
+ if (err)
+ goto out1;
+
+ err = ntfs_bio_pages(sbi, run, &page, 1, from,
+ to - from, REQ_OP_READ);
+ if (err) {
+ page->index = -1;
+ goto out1;
+ }
+ page->index = index;
+ }
+
+ if (i) {
+ if (bytes_per_off == sizeof(__le32)) {
+ off32 = Add2Ptr(addr, voff);
+ off[1] = le32_to_cpu(*off32);
+ } else {
+ off64 = Add2Ptr(addr, voff);
+ off[1] = le64_to_cpu(*off64);
+ }
+ } else if (!voff) {
+ if (bytes_per_off == sizeof(__le32)) {
+ off32 = Add2Ptr(addr, PAGE_SIZE - sizeof(u32));
+ off[0] = le32_to_cpu(*off32);
+ } else {
+ off64 = Add2Ptr(addr, PAGE_SIZE - sizeof(u64));
+ off[0] = le64_to_cpu(*off64);
+ }
+ } else {
+ /* Two values in one page. */
+ if (bytes_per_off == sizeof(__le32)) {
+ off32 = Add2Ptr(addr, voff);
+ off[0] = le32_to_cpu(off32[-1]);
+ off[1] = le32_to_cpu(off32[0]);
+ } else {
+ off64 = Add2Ptr(addr, voff);
+ off[0] = le64_to_cpu(off64[-1]);
+ off[1] = le64_to_cpu(off64[0]);
+ }
+ break;
+ }
+ } while (++i < 2);
+
+ *vbo_data += off[0];
+ *ondisk_size = off[1] - off[0];
+
+out1:
+ unlock_page(page);
+out:
+ up_write(&ni->file.run_lock);
+ return err;
+}
+#endif
+
+/*
+ * attr_is_frame_compressed - Used to detect compressed frame.
+ */
+int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
+ CLST frame, CLST *clst_data)
+{
+ int err;
+ u32 clst_frame;
+ CLST clen, lcn, vcn, alen, slen, vcn_next;
+ size_t idx;
+ struct runs_tree *run;
+
+ *clst_data = 0;
+
+ if (!is_attr_compressed(attr))
+ return 0;
+
+ if (!attr->non_res)
+ return 0;
+
+ clst_frame = 1u << attr->nres.c_unit;
+ vcn = frame * clst_frame;
+ run = &ni->file.run;
+
+ if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
+ err = attr_load_runs_vcn(ni, attr->type, attr_name(attr),
+ attr->name_len, run, vcn);
+ if (err)
+ return err;
+
+ if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx))
+ return -EINVAL;
+ }
+
+ if (lcn == SPARSE_LCN) {
+ /* Sparsed frame. */
+ return 0;
+ }
+
+ if (clen >= clst_frame) {
+ /*
+ * The frame is not compressed 'cause
+ * it does not contain any sparse clusters.
+ */
+ *clst_data = clst_frame;
+ return 0;
+ }
+
+ alen = bytes_to_cluster(ni->mi.sbi, le64_to_cpu(attr->nres.alloc_size));
+ slen = 0;
+ *clst_data = clen;
+
+ /*
+ * The frame is compressed if *clst_data + slen >= clst_frame.
+ * Check next fragments.
+ */
+ while ((vcn += clen) < alen) {
+ vcn_next = vcn;
+
+ if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
+ vcn_next != vcn) {
+ err = attr_load_runs_vcn(ni, attr->type,
+ attr_name(attr),
+ attr->name_len, run, vcn_next);
+ if (err)
+ return err;
+ vcn = vcn_next;
+
+ if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx))
+ return -EINVAL;
+ }
+
+ if (lcn == SPARSE_LCN) {
+ slen += clen;
+ } else {
+ if (slen) {
+ /*
+ * Data_clusters + sparse_clusters =
+ * not enough for frame.
+ */
+ return -EINVAL;
+ }
+ *clst_data += clen;
+ }
+
+ if (*clst_data + slen >= clst_frame) {
+ if (!slen) {
+ /*
+ * There is no sparsed clusters in this frame
+ * so it is not compressed.
+ */
+ *clst_data = clst_frame;
+ } else {
+ /* Frame is compressed. */
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * attr_allocate_frame - Allocate/free clusters for @frame.
+ *
+ * Assumed: down_write(&ni->file.run_lock);
+ */
+int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
+ u64 new_valid)
+{
+ int err = 0;
+ struct runs_tree *run = &ni->file.run;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct ATTRIB *attr = NULL, *attr_b;
+ struct ATTR_LIST_ENTRY *le, *le_b;
+ struct mft_inode *mi, *mi_b;
+ CLST svcn, evcn1, next_svcn, lcn, len;
+ CLST vcn, end, clst_data;
+ u64 total_size, valid_size, data_size;
+
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b);
+ if (!attr_b)
+ return -ENOENT;
+
+ if (!is_attr_ext(attr_b))
+ return -EINVAL;
+
+ vcn = frame << NTFS_LZNT_CUNIT;
+ total_size = le64_to_cpu(attr_b->nres.total_size);
+
+ svcn = le64_to_cpu(attr_b->nres.svcn);
+ evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1;
+ data_size = le64_to_cpu(attr_b->nres.data_size);
+
+ if (svcn <= vcn && vcn < evcn1) {
+ attr = attr_b;
+ le = le_b;
+ mi = mi_b;
+ } else if (!le_b) {
+ err = -EINVAL;
+ goto out;
+ } else {
+ le = le_b;
+ attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn,
+ &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+
+ err = attr_load_runs(attr, ni, run, NULL);
+ if (err)
+ goto out;
+
+ err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data);
+ if (err)
+ goto out;
+
+ total_size -= (u64)clst_data << sbi->cluster_bits;
+
+ len = bytes_to_cluster(sbi, compr_size);
+
+ if (len == clst_data)
+ goto out;
+
+ if (len < clst_data) {
+ err = run_deallocate_ex(sbi, run, vcn + len, clst_data - len,
+ NULL, true);
+ if (err)
+ goto out;
+
+ if (!run_add_entry(run, vcn + len, SPARSE_LCN, clst_data - len,
+ false)) {
+ err = -ENOMEM;
+ goto out;
+ }
+ end = vcn + clst_data;
+ /* Run contains updated range [vcn + len : end). */
+ } else {
+ CLST alen, hint = 0;
+ /* Get the last LCN to allocate from. */
+ if (vcn + clst_data &&
+ !run_lookup_entry(run, vcn + clst_data - 1, &hint, NULL,
+ NULL)) {
+ hint = -1;
+ }
+
+ err = attr_allocate_clusters(sbi, run, vcn + clst_data,
+ hint + 1, len - clst_data, NULL, 0,
+ &alen, 0, &lcn);
+ if (err)
+ goto out;
+
+ end = vcn + len;
+ /* Run contains updated range [vcn + clst_data : end). */
+ }
+
+ total_size += (u64)len << sbi->cluster_bits;
+
+repack:
+ err = mi_pack_runs(mi, attr, run, max(end, evcn1) - svcn);
+ if (err)
+ goto out;
+
+ attr_b->nres.total_size = cpu_to_le64(total_size);
+ inode_set_bytes(&ni->vfs_inode, total_size);
+
+ mi_b->dirty = true;
+ mark_inode_dirty(&ni->vfs_inode);
+
+ /* Stored [vcn : next_svcn) from [vcn : end). */
+ next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
+
+ if (end <= evcn1) {
+ if (next_svcn == evcn1) {
+ /* Normal way. Update attribute and exit. */
+ goto ok;
+ }
+ /* Add new segment [next_svcn : evcn1 - next_svcn). */
+ if (!ni->attr_list.size) {
+ err = ni_create_attr_list(ni);
+ if (err)
+ goto out;
+ /* Layout of records is changed. */
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL,
+ 0, NULL, &mi_b);
+ if (!attr_b) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ attr = attr_b;
+ le = le_b;
+ mi = mi_b;
+ goto repack;
+ }
+ }
+
+ svcn = evcn1;
+
+ /* Estimate next attribute. */
+ attr = ni_find_attr(ni, attr, &le, ATTR_DATA, NULL, 0, &svcn, &mi);
+
+ if (attr) {
+ CLST alloc = bytes_to_cluster(
+ sbi, le64_to_cpu(attr_b->nres.alloc_size));
+ CLST evcn = le64_to_cpu(attr->nres.evcn);
+
+ if (end < next_svcn)
+ end = next_svcn;
+ while (end > evcn) {
+ /* Remove segment [svcn : evcn). */
+ mi_remove_attr(NULL, mi, attr);
+
+ if (!al_remove_le(ni, le)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (evcn + 1 >= alloc) {
+ /* Last attribute segment. */
+ evcn1 = evcn + 1;
+ goto ins_ext;
+ }
+
+ if (ni_load_mi(ni, le, &mi)) {
+ attr = NULL;
+ goto out;
+ }
+
+ attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0,
+ &le->id);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn = le64_to_cpu(attr->nres.evcn);
+ }
+
+ if (end < svcn)
+ end = svcn;
+
+ err = attr_load_runs(attr, ni, run, &end);
+ if (err)
+ goto out;
+
+ evcn1 = evcn + 1;
+ attr->nres.svcn = cpu_to_le64(next_svcn);
+ err = mi_pack_runs(mi, attr, run, evcn1 - next_svcn);
+ if (err)
+ goto out;
+
+ le->vcn = cpu_to_le64(next_svcn);
+ ni->attr_list.dirty = true;
+ mi->dirty = true;
+
+ next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+ins_ext:
+ if (evcn1 > next_svcn) {
+ err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run,
+ next_svcn, evcn1 - next_svcn,
+ attr_b->flags, &attr, &mi);
+ if (err)
+ goto out;
+ }
+ok:
+ run_truncate_around(run, vcn);
+out:
+ if (new_valid > data_size)
+ new_valid = data_size;
+
+ valid_size = le64_to_cpu(attr_b->nres.valid_size);
+ if (new_valid != valid_size) {
+ attr_b->nres.valid_size = cpu_to_le64(valid_size);
+ mi_b->dirty = true;
+ }
+
+ return err;
+}
+
+/*
+ * attr_collapse_range - Collapse range in file.
+ */
+int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
+{
+ int err = 0;
+ struct runs_tree *run = &ni->file.run;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct ATTRIB *attr = NULL, *attr_b;
+ struct ATTR_LIST_ENTRY *le, *le_b;
+ struct mft_inode *mi, *mi_b;
+ CLST svcn, evcn1, len, dealloc, alen;
+ CLST vcn, end;
+ u64 valid_size, data_size, alloc_size, total_size;
+ u32 mask;
+ __le16 a_flags;
+
+ if (!bytes)
+ return 0;
+
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b);
+ if (!attr_b)
+ return -ENOENT;
+
+ if (!attr_b->non_res) {
+ /* Attribute is resident. Nothing to do? */
+ return 0;
+ }
+
+ data_size = le64_to_cpu(attr_b->nres.data_size);
+ alloc_size = le64_to_cpu(attr_b->nres.alloc_size);
+ a_flags = attr_b->flags;
+
+ if (is_attr_ext(attr_b)) {
+ total_size = le64_to_cpu(attr_b->nres.total_size);
+ mask = (sbi->cluster_size << attr_b->nres.c_unit) - 1;
+ } else {
+ total_size = alloc_size;
+ mask = sbi->cluster_mask;
+ }
+
+ if ((vbo & mask) || (bytes & mask)) {
+ /* Allow to collapse only cluster aligned ranges. */
+ return -EINVAL;
+ }
+
+ if (vbo > data_size)
+ return -EINVAL;
+
+ down_write(&ni->file.run_lock);
+
+ if (vbo + bytes >= data_size) {
+ u64 new_valid = min(ni->i_valid, vbo);
+
+ /* Simple truncate file at 'vbo'. */
+ truncate_setsize(&ni->vfs_inode, vbo);
+ err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, vbo,
+ &new_valid, true, NULL);
+
+ if (!err && new_valid < ni->i_valid)
+ ni->i_valid = new_valid;
+
+ goto out;
+ }
+
+ /*
+ * Enumerate all attribute segments and collapse.
+ */
+ alen = alloc_size >> sbi->cluster_bits;
+ vcn = vbo >> sbi->cluster_bits;
+ len = bytes >> sbi->cluster_bits;
+ end = vcn + len;
+ dealloc = 0;
+
+ svcn = le64_to_cpu(attr_b->nres.svcn);
+ evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1;
+
+ if (svcn <= vcn && vcn < evcn1) {
+ attr = attr_b;
+ le = le_b;
+ mi = mi_b;
+ } else if (!le_b) {
+ err = -EINVAL;
+ goto out;
+ } else {
+ le = le_b;
+ attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn,
+ &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+
+ for (;;) {
+ if (svcn >= end) {
+ /* Shift VCN- */
+ attr->nres.svcn = cpu_to_le64(svcn - len);
+ attr->nres.evcn = cpu_to_le64(evcn1 - 1 - len);
+ if (le) {
+ le->vcn = attr->nres.svcn;
+ ni->attr_list.dirty = true;
+ }
+ mi->dirty = true;
+ } else if (svcn < vcn || end < evcn1) {
+ CLST vcn1, eat, next_svcn;
+
+ /* Collapse a part of this attribute segment. */
+ err = attr_load_runs(attr, ni, run, &svcn);
+ if (err)
+ goto out;
+ vcn1 = max(vcn, svcn);
+ eat = min(end, evcn1) - vcn1;
+
+ err = run_deallocate_ex(sbi, run, vcn1, eat, &dealloc,
+ true);
+ if (err)
+ goto out;
+
+ if (!run_collapse_range(run, vcn1, eat)) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ if (svcn >= vcn) {
+ /* Shift VCN */
+ attr->nres.svcn = cpu_to_le64(vcn);
+ if (le) {
+ le->vcn = attr->nres.svcn;
+ ni->attr_list.dirty = true;
+ }
+ }
+
+ err = mi_pack_runs(mi, attr, run, evcn1 - svcn - eat);
+ if (err)
+ goto out;
+
+ next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
+ if (next_svcn + eat < evcn1) {
+ err = ni_insert_nonresident(
+ ni, ATTR_DATA, NULL, 0, run, next_svcn,
+ evcn1 - eat - next_svcn, a_flags, &attr,
+ &mi);
+ if (err)
+ goto out;
+
+ /* Layout of records maybe changed. */
+ attr_b = NULL;
+ le = al_find_ex(ni, NULL, ATTR_DATA, NULL, 0,
+ &next_svcn);
+ if (!le) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* Free all allocated memory. */
+ run_truncate(run, 0);
+ } else {
+ u16 le_sz;
+ u16 roff = le16_to_cpu(attr->nres.run_off);
+
+ run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn,
+ evcn1 - 1, svcn, Add2Ptr(attr, roff),
+ le32_to_cpu(attr->size) - roff);
+
+ /* Delete this attribute segment. */
+ mi_remove_attr(NULL, mi, attr);
+ if (!le)
+ break;
+
+ le_sz = le16_to_cpu(le->size);
+ if (!al_remove_le(ni, le)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (evcn1 >= alen)
+ break;
+
+ if (!svcn) {
+ /* Load next record that contains this attribute. */
+ if (ni_load_mi(ni, le, &mi)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Look for required attribute. */
+ attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL,
+ 0, &le->id);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+ goto next_attr;
+ }
+ le = (struct ATTR_LIST_ENTRY *)((u8 *)le - le_sz);
+ }
+
+ if (evcn1 >= alen)
+ break;
+
+ attr = ni_enum_attr_ex(ni, attr, &le, &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+next_attr:
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+
+ if (!attr_b) {
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL,
+ &mi_b);
+ if (!attr_b) {
+ err = -ENOENT;
+ goto out;
+ }
+ }
+
+ data_size -= bytes;
+ valid_size = ni->i_valid;
+ if (vbo + bytes <= valid_size)
+ valid_size -= bytes;
+ else if (vbo < valid_size)
+ valid_size = vbo;
+
+ attr_b->nres.alloc_size = cpu_to_le64(alloc_size - bytes);
+ attr_b->nres.data_size = cpu_to_le64(data_size);
+ attr_b->nres.valid_size = cpu_to_le64(min(valid_size, data_size));
+ total_size -= (u64)dealloc << sbi->cluster_bits;
+ if (is_attr_ext(attr_b))
+ attr_b->nres.total_size = cpu_to_le64(total_size);
+ mi_b->dirty = true;
+
+ /* Update inode size. */
+ ni->i_valid = valid_size;
+ ni->vfs_inode.i_size = data_size;
+ inode_set_bytes(&ni->vfs_inode, total_size);
+ ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
+ mark_inode_dirty(&ni->vfs_inode);
+
+out:
+ up_write(&ni->file.run_lock);
+ if (err)
+ make_bad_inode(&ni->vfs_inode);
+
+ return err;
+}
+
+/*
+ * attr_punch_hole
+ *
+ * Not for normal files.
+ */
+int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size)
+{
+ int err = 0;
+ struct runs_tree *run = &ni->file.run;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct ATTRIB *attr = NULL, *attr_b;
+ struct ATTR_LIST_ENTRY *le, *le_b;
+ struct mft_inode *mi, *mi_b;
+ CLST svcn, evcn1, vcn, len, end, alen, dealloc;
+ u64 total_size, alloc_size;
+ u32 mask;
+
+ if (!bytes)
+ return 0;
+
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b);
+ if (!attr_b)
+ return -ENOENT;
+
+ if (!attr_b->non_res) {
+ u32 data_size = le32_to_cpu(attr->res.data_size);
+ u32 from, to;
+
+ if (vbo > data_size)
+ return 0;
+
+ from = vbo;
+ to = (vbo + bytes) < data_size ? (vbo + bytes) : data_size;
+ memset(Add2Ptr(resident_data(attr_b), from), 0, to - from);
+ return 0;
+ }
+
+ if (!is_attr_ext(attr_b))
+ return -EOPNOTSUPP;
+
+ alloc_size = le64_to_cpu(attr_b->nres.alloc_size);
+ total_size = le64_to_cpu(attr_b->nres.total_size);
+
+ if (vbo >= alloc_size) {
+ /* NOTE: It is allowed. */
+ return 0;
+ }
+
+ mask = (sbi->cluster_size << attr_b->nres.c_unit) - 1;
+
+ bytes += vbo;
+ if (bytes > alloc_size)
+ bytes = alloc_size;
+ bytes -= vbo;
+
+ if ((vbo & mask) || (bytes & mask)) {
+ /* We have to zero a range(s). */
+ if (frame_size == NULL) {
+ /* Caller insists range is aligned. */
+ return -EINVAL;
+ }
+ *frame_size = mask + 1;
+ return E_NTFS_NOTALIGNED;
+ }
+
+ down_write(&ni->file.run_lock);
+ /*
+ * Enumerate all attribute segments and punch hole where necessary.
+ */
+ alen = alloc_size >> sbi->cluster_bits;
+ vcn = vbo >> sbi->cluster_bits;
+ len = bytes >> sbi->cluster_bits;
+ end = vcn + len;
+ dealloc = 0;
+
+ svcn = le64_to_cpu(attr_b->nres.svcn);
+ evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1;
+
+ if (svcn <= vcn && vcn < evcn1) {
+ attr = attr_b;
+ le = le_b;
+ mi = mi_b;
+ } else if (!le_b) {
+ err = -EINVAL;
+ goto out;
+ } else {
+ le = le_b;
+ attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn,
+ &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+
+ while (svcn < end) {
+ CLST vcn1, zero, dealloc2;
+
+ err = attr_load_runs(attr, ni, run, &svcn);
+ if (err)
+ goto out;
+ vcn1 = max(vcn, svcn);
+ zero = min(end, evcn1) - vcn1;
+
+ dealloc2 = dealloc;
+ err = run_deallocate_ex(sbi, run, vcn1, zero, &dealloc, true);
+ if (err)
+ goto out;
+
+ if (dealloc2 == dealloc) {
+ /* Looks like the required range is already sparsed. */
+ } else {
+ if (!run_add_entry(run, vcn1, SPARSE_LCN, zero,
+ false)) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = mi_pack_runs(mi, attr, run, evcn1 - svcn);
+ if (err)
+ goto out;
+ }
+ /* Free all allocated memory. */
+ run_truncate(run, 0);
+
+ if (evcn1 >= alen)
+ break;
+
+ attr = ni_enum_attr_ex(ni, attr, &le, &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+
+ total_size -= (u64)dealloc << sbi->cluster_bits;
+ attr_b->nres.total_size = cpu_to_le64(total_size);
+ mi_b->dirty = true;
+
+ /* Update inode size. */
+ inode_set_bytes(&ni->vfs_inode, total_size);
+ ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
+ mark_inode_dirty(&ni->vfs_inode);
+
+out:
+ up_write(&ni->file.run_lock);
+ if (err)
+ make_bad_inode(&ni->vfs_inode);
+
+ return err;
+}
diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c
new file mode 100644
index 000000000000..fa32399eb517
--- /dev/null
+++ b/fs/ntfs3/attrlist.c
@@ -0,0 +1,460 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+/*
+ * al_is_valid_le
+ *
+ * Return: True if @le is valid.
+ */
+static inline bool al_is_valid_le(const struct ntfs_inode *ni,
+ struct ATTR_LIST_ENTRY *le)
+{
+ if (!le || !ni->attr_list.le || !ni->attr_list.size)
+ return false;
+
+ return PtrOffset(ni->attr_list.le, le) + le16_to_cpu(le->size) <=
+ ni->attr_list.size;
+}
+
+void al_destroy(struct ntfs_inode *ni)
+{
+ run_close(&ni->attr_list.run);
+ kfree(ni->attr_list.le);
+ ni->attr_list.le = NULL;
+ ni->attr_list.size = 0;
+ ni->attr_list.dirty = false;
+}
+
+/*
+ * ntfs_load_attr_list
+ *
+ * This method makes sure that the ATTRIB list, if present,
+ * has been properly set up.
+ */
+int ntfs_load_attr_list(struct ntfs_inode *ni, struct ATTRIB *attr)
+{
+ int err;
+ size_t lsize;
+ void *le = NULL;
+
+ if (ni->attr_list.size)
+ return 0;
+
+ if (!attr->non_res) {
+ lsize = le32_to_cpu(attr->res.data_size);
+ le = kmalloc(al_aligned(lsize), GFP_NOFS);
+ if (!le) {
+ err = -ENOMEM;
+ goto out;
+ }
+ memcpy(le, resident_data(attr), lsize);
+ } else if (attr->nres.svcn) {
+ err = -EINVAL;
+ goto out;
+ } else {
+ u16 run_off = le16_to_cpu(attr->nres.run_off);
+
+ lsize = le64_to_cpu(attr->nres.data_size);
+
+ run_init(&ni->attr_list.run);
+
+ err = run_unpack_ex(&ni->attr_list.run, ni->mi.sbi, ni->mi.rno,
+ 0, le64_to_cpu(attr->nres.evcn), 0,
+ Add2Ptr(attr, run_off),
+ le32_to_cpu(attr->size) - run_off);
+ if (err < 0)
+ goto out;
+
+ le = kmalloc(al_aligned(lsize), GFP_NOFS);
+ if (!le) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = ntfs_read_run_nb(ni->mi.sbi, &ni->attr_list.run, 0, le,
+ lsize, NULL);
+ if (err)
+ goto out;
+ }
+
+ ni->attr_list.size = lsize;
+ ni->attr_list.le = le;
+
+ return 0;
+
+out:
+ ni->attr_list.le = le;
+ al_destroy(ni);
+
+ return err;
+}
+
+/*
+ * al_enumerate
+ *
+ * Return:
+ * * The next list le.
+ * * If @le is NULL then return the first le.
+ */
+struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni,
+ struct ATTR_LIST_ENTRY *le)
+{
+ size_t off;
+ u16 sz;
+
+ if (!le) {
+ le = ni->attr_list.le;
+ } else {
+ sz = le16_to_cpu(le->size);
+ if (sz < sizeof(struct ATTR_LIST_ENTRY)) {
+ /* Impossible 'cause we should not return such le. */
+ return NULL;
+ }
+ le = Add2Ptr(le, sz);
+ }
+
+ /* Check boundary. */
+ off = PtrOffset(ni->attr_list.le, le);
+ if (off + sizeof(struct ATTR_LIST_ENTRY) > ni->attr_list.size) {
+ /* The regular end of list. */
+ return NULL;
+ }
+
+ sz = le16_to_cpu(le->size);
+
+ /* Check le for errors. */
+ if (sz < sizeof(struct ATTR_LIST_ENTRY) ||
+ off + sz > ni->attr_list.size ||
+ sz < le->name_off + le->name_len * sizeof(short)) {
+ return NULL;
+ }
+
+ return le;
+}
+
+/*
+ * al_find_le
+ *
+ * Find the first le in the list which matches type, name and VCN.
+ *
+ * Return: NULL if not found.
+ */
+struct ATTR_LIST_ENTRY *al_find_le(struct ntfs_inode *ni,
+ struct ATTR_LIST_ENTRY *le,
+ const struct ATTRIB *attr)
+{
+ CLST svcn = attr_svcn(attr);
+
+ return al_find_ex(ni, le, attr->type, attr_name(attr), attr->name_len,
+ &svcn);
+}
+
+/*
+ * al_find_ex
+ *
+ * Find the first le in the list which matches type, name and VCN.
+ *
+ * Return: NULL if not found.
+ */
+struct ATTR_LIST_ENTRY *al_find_ex(struct ntfs_inode *ni,
+ struct ATTR_LIST_ENTRY *le,
+ enum ATTR_TYPE type, const __le16 *name,
+ u8 name_len, const CLST *vcn)
+{
+ struct ATTR_LIST_ENTRY *ret = NULL;
+ u32 type_in = le32_to_cpu(type);
+
+ while ((le = al_enumerate(ni, le))) {
+ u64 le_vcn;
+ int diff = le32_to_cpu(le->type) - type_in;
+
+ /* List entries are sorted by type, name and VCN. */
+ if (diff < 0)
+ continue;
+
+ if (diff > 0)
+ return ret;
+
+ if (le->name_len != name_len)
+ continue;
+
+ le_vcn = le64_to_cpu(le->vcn);
+ if (!le_vcn) {
+ /*
+ * Compare entry names only for entry with vcn == 0.
+ */
+ diff = ntfs_cmp_names(le_name(le), name_len, name,
+ name_len, ni->mi.sbi->upcase,
+ true);
+ if (diff < 0)
+ continue;
+
+ if (diff > 0)
+ return ret;
+ }
+
+ if (!vcn)
+ return le;
+
+ if (*vcn == le_vcn)
+ return le;
+
+ if (*vcn < le_vcn)
+ return ret;
+
+ ret = le;
+ }
+
+ return ret;
+}
+
+/*
+ * al_find_le_to_insert
+ *
+ * Find the first list entry which matches type, name and VCN.
+ */
+static struct ATTR_LIST_ENTRY *al_find_le_to_insert(struct ntfs_inode *ni,
+ enum ATTR_TYPE type,
+ const __le16 *name,
+ u8 name_len, CLST vcn)
+{
+ struct ATTR_LIST_ENTRY *le = NULL, *prev;
+ u32 type_in = le32_to_cpu(type);
+
+ /* List entries are sorted by type, name and VCN. */
+ while ((le = al_enumerate(ni, prev = le))) {
+ int diff = le32_to_cpu(le->type) - type_in;
+
+ if (diff < 0)
+ continue;
+
+ if (diff > 0)
+ return le;
+
+ if (!le->vcn) {
+ /*
+ * Compare entry names only for entry with vcn == 0.
+ */
+ diff = ntfs_cmp_names(le_name(le), le->name_len, name,
+ name_len, ni->mi.sbi->upcase,
+ true);
+ if (diff < 0)
+ continue;
+
+ if (diff > 0)
+ return le;
+ }
+
+ if (le64_to_cpu(le->vcn) >= vcn)
+ return le;
+ }
+
+ return prev ? Add2Ptr(prev, le16_to_cpu(prev->size)) : ni->attr_list.le;
+}
+
+/*
+ * al_add_le
+ *
+ * Add an "attribute list entry" to the list.
+ */
+int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
+ u8 name_len, CLST svcn, __le16 id, const struct MFT_REF *ref,
+ struct ATTR_LIST_ENTRY **new_le)
+{
+ int err;
+ struct ATTRIB *attr;
+ struct ATTR_LIST_ENTRY *le;
+ size_t off;
+ u16 sz;
+ size_t asize, new_asize, old_size;
+ u64 new_size;
+ typeof(ni->attr_list) *al = &ni->attr_list;
+
+ /*
+ * Compute the size of the new 'le'
+ */
+ sz = le_size(name_len);
+ old_size = al->size;
+ new_size = old_size + sz;
+ asize = al_aligned(old_size);
+ new_asize = al_aligned(new_size);
+
+ /* Scan forward to the point at which the new 'le' should be inserted. */
+ le = al_find_le_to_insert(ni, type, name, name_len, svcn);
+ off = PtrOffset(al->le, le);
+
+ if (new_size > asize) {
+ void *ptr = kmalloc(new_asize, GFP_NOFS);
+
+ if (!ptr)
+ return -ENOMEM;
+
+ memcpy(ptr, al->le, off);
+ memcpy(Add2Ptr(ptr, off + sz), le, old_size - off);
+ le = Add2Ptr(ptr, off);
+ kfree(al->le);
+ al->le = ptr;
+ } else {
+ memmove(Add2Ptr(le, sz), le, old_size - off);
+ }
+ *new_le = le;
+
+ al->size = new_size;
+
+ le->type = type;
+ le->size = cpu_to_le16(sz);
+ le->name_len = name_len;
+ le->name_off = offsetof(struct ATTR_LIST_ENTRY, name);
+ le->vcn = cpu_to_le64(svcn);
+ le->ref = *ref;
+ le->id = id;
+ memcpy(le->name, name, sizeof(short) * name_len);
+
+ err = attr_set_size(ni, ATTR_LIST, NULL, 0, &al->run, new_size,
+ &new_size, true, &attr);
+ if (err) {
+ /* Undo memmove above. */
+ memmove(le, Add2Ptr(le, sz), old_size - off);
+ al->size = old_size;
+ return err;
+ }
+
+ al->dirty = true;
+
+ if (attr && attr->non_res) {
+ err = ntfs_sb_write_run(ni->mi.sbi, &al->run, 0, al->le,
+ al->size);
+ if (err)
+ return err;
+ al->dirty = false;
+ }
+
+ return 0;
+}
+
+/*
+ * al_remove_le - Remove @le from attribute list.
+ */
+bool al_remove_le(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le)
+{
+ u16 size;
+ size_t off;
+ typeof(ni->attr_list) *al = &ni->attr_list;
+
+ if (!al_is_valid_le(ni, le))
+ return false;
+
+ /* Save on stack the size of 'le' */
+ size = le16_to_cpu(le->size);
+ off = PtrOffset(al->le, le);
+
+ memmove(le, Add2Ptr(le, size), al->size - (off + size));
+
+ al->size -= size;
+ al->dirty = true;
+
+ return true;
+}
+
+/*
+ * al_delete_le - Delete first le from the list which matches its parameters.
+ */
+bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn,
+ const __le16 *name, size_t name_len,
+ const struct MFT_REF *ref)
+{
+ u16 size;
+ struct ATTR_LIST_ENTRY *le;
+ size_t off;
+ typeof(ni->attr_list) *al = &ni->attr_list;
+
+ /* Scan forward to the first le that matches the input. */
+ le = al_find_ex(ni, NULL, type, name, name_len, &vcn);
+ if (!le)
+ return false;
+
+ off = PtrOffset(al->le, le);
+
+next:
+ if (off >= al->size)
+ return false;
+ if (le->type != type)
+ return false;
+ if (le->name_len != name_len)
+ return false;
+ if (name_len && ntfs_cmp_names(le_name(le), name_len, name, name_len,
+ ni->mi.sbi->upcase, true))
+ return false;
+ if (le64_to_cpu(le->vcn) != vcn)
+ return false;
+
+ /*
+ * The caller specified a segment reference, so we have to
+ * scan through the matching entries until we find that segment
+ * reference or we run of matching entries.
+ */
+ if (ref && memcmp(ref, &le->ref, sizeof(*ref))) {
+ off += le16_to_cpu(le->size);
+ le = Add2Ptr(al->le, off);
+ goto next;
+ }
+
+ /* Save on stack the size of 'le'. */
+ size = le16_to_cpu(le->size);
+ /* Delete the le. */
+ memmove(le, Add2Ptr(le, size), al->size - (off + size));
+
+ al->size -= size;
+ al->dirty = true;
+
+ return true;
+}
+
+int al_update(struct ntfs_inode *ni)
+{
+ int err;
+ struct ATTRIB *attr;
+ typeof(ni->attr_list) *al = &ni->attr_list;
+
+ if (!al->dirty || !al->size)
+ return 0;
+
+ /*
+ * Attribute list increased on demand in al_add_le.
+ * Attribute list decreased here.
+ */
+ err = attr_set_size(ni, ATTR_LIST, NULL, 0, &al->run, al->size, NULL,
+ false, &attr);
+ if (err)
+ goto out;
+
+ if (!attr->non_res) {
+ memcpy(resident_data(attr), al->le, al->size);
+ } else {
+ err = ntfs_sb_write_run(ni->mi.sbi, &al->run, 0, al->le,
+ al->size);
+ if (err)
+ goto out;
+
+ attr->nres.valid_size = attr->nres.data_size;
+ }
+
+ ni->mi.dirty = true;
+ al->dirty = false;
+
+out:
+ return err;
+}
diff --git a/fs/ntfs3/bitfunc.c b/fs/ntfs3/bitfunc.c
new file mode 100644
index 000000000000..ce304d40b5e1
--- /dev/null
+++ b/fs/ntfs3/bitfunc.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+#define BITS_IN_SIZE_T (sizeof(size_t) * 8)
+
+/*
+ * fill_mask[i] - first i bits are '1' , i = 0,1,2,3,4,5,6,7,8
+ * fill_mask[i] = 0xFF >> (8-i)
+ */
+static const u8 fill_mask[] = { 0x00, 0x01, 0x03, 0x07, 0x0F,
+ 0x1F, 0x3F, 0x7F, 0xFF };
+
+/*
+ * zero_mask[i] - first i bits are '0' , i = 0,1,2,3,4,5,6,7,8
+ * zero_mask[i] = 0xFF << i
+ */
+static const u8 zero_mask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
+ 0xE0, 0xC0, 0x80, 0x00 };
+
+/*
+ * are_bits_clear
+ *
+ * Return: True if all bits [bit, bit+nbits) are zeros "0".
+ */
+bool are_bits_clear(const ulong *lmap, size_t bit, size_t nbits)
+{
+ size_t pos = bit & 7;
+ const u8 *map = (u8 *)lmap + (bit >> 3);
+
+ if (pos) {
+ if (8 - pos >= nbits)
+ return !nbits || !(*map & fill_mask[pos + nbits] &
+ zero_mask[pos]);
+
+ if (*map++ & zero_mask[pos])
+ return false;
+ nbits -= 8 - pos;
+ }
+
+ pos = ((size_t)map) & (sizeof(size_t) - 1);
+ if (pos) {
+ pos = sizeof(size_t) - pos;
+ if (nbits >= pos * 8) {
+ for (nbits -= pos * 8; pos; pos--, map++) {
+ if (*map)
+ return false;
+ }
+ }
+ }
+
+ for (pos = nbits / BITS_IN_SIZE_T; pos; pos--, map += sizeof(size_t)) {
+ if (*((size_t *)map))
+ return false;
+ }
+
+ for (pos = (nbits % BITS_IN_SIZE_T) >> 3; pos; pos--, map++) {
+ if (*map)
+ return false;
+ }
+
+ pos = nbits & 7;
+ if (pos && (*map & fill_mask[pos]))
+ return false;
+
+ return true;
+}
+
+/*
+ * are_bits_set
+ *
+ * Return: True if all bits [bit, bit+nbits) are ones "1".
+ */
+bool are_bits_set(const ulong *lmap, size_t bit, size_t nbits)
+{
+ u8 mask;
+ size_t pos = bit & 7;
+ const u8 *map = (u8 *)lmap + (bit >> 3);
+
+ if (pos) {
+ if (8 - pos >= nbits) {
+ mask = fill_mask[pos + nbits] & zero_mask[pos];
+ return !nbits || (*map & mask) == mask;
+ }
+
+ mask = zero_mask[pos];
+ if ((*map++ & mask) != mask)
+ return false;
+ nbits -= 8 - pos;
+ }
+
+ pos = ((size_t)map) & (sizeof(size_t) - 1);
+ if (pos) {
+ pos = sizeof(size_t) - pos;
+ if (nbits >= pos * 8) {
+ for (nbits -= pos * 8; pos; pos--, map++) {
+ if (*map != 0xFF)
+ return false;
+ }
+ }
+ }
+
+ for (pos = nbits / BITS_IN_SIZE_T; pos; pos--, map += sizeof(size_t)) {
+ if (*((size_t *)map) != MINUS_ONE_T)
+ return false;
+ }
+
+ for (pos = (nbits % BITS_IN_SIZE_T) >> 3; pos; pos--, map++) {
+ if (*map != 0xFF)
+ return false;
+ }
+
+ pos = nbits & 7;
+ if (pos) {
+ u8 mask = fill_mask[pos];
+
+ if ((*map & mask) != mask)
+ return false;
+ }
+
+ return true;
+}
diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c
new file mode 100644
index 000000000000..831501555009
--- /dev/null
+++ b/fs/ntfs3/bitmap.c
@@ -0,0 +1,1493 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ * This code builds two trees of free clusters extents.
+ * Trees are sorted by start of extent and by length of extent.
+ * NTFS_MAX_WND_EXTENTS defines the maximum number of elements in trees.
+ * In extreme case code reads on-disk bitmap to find free clusters.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+/*
+ * Maximum number of extents in tree.
+ */
+#define NTFS_MAX_WND_EXTENTS (32u * 1024u)
+
+struct rb_node_key {
+ struct rb_node node;
+ size_t key;
+};
+
+struct e_node {
+ struct rb_node_key start; /* Tree sorted by start. */
+ struct rb_node_key count; /* Tree sorted by len. */
+};
+
+static int wnd_rescan(struct wnd_bitmap *wnd);
+static struct buffer_head *wnd_map(struct wnd_bitmap *wnd, size_t iw);
+static bool wnd_is_free_hlp(struct wnd_bitmap *wnd, size_t bit, size_t bits);
+
+static struct kmem_cache *ntfs_enode_cachep;
+
+int __init ntfs3_init_bitmap(void)
+{
+ ntfs_enode_cachep =
+ kmem_cache_create("ntfs3_enode_cache", sizeof(struct e_node), 0,
+ SLAB_RECLAIM_ACCOUNT, NULL);
+ return ntfs_enode_cachep ? 0 : -ENOMEM;
+}
+
+void ntfs3_exit_bitmap(void)
+{
+ kmem_cache_destroy(ntfs_enode_cachep);
+}
+
+static inline u32 wnd_bits(const struct wnd_bitmap *wnd, size_t i)
+{
+ return i + 1 == wnd->nwnd ? wnd->bits_last : wnd->sb->s_blocksize * 8;
+}
+
+/*
+ * wnd_scan
+ *
+ * b_pos + b_len - biggest fragment.
+ * Scan range [wpos wbits) window @buf.
+ *
+ * Return: -1 if not found.
+ */
+static size_t wnd_scan(const ulong *buf, size_t wbit, u32 wpos, u32 wend,
+ size_t to_alloc, size_t *prev_tail, size_t *b_pos,
+ size_t *b_len)
+{
+ while (wpos < wend) {
+ size_t free_len;
+ u32 free_bits, end;
+ u32 used = find_next_zero_bit(buf, wend, wpos);
+
+ if (used >= wend) {
+ if (*b_len < *prev_tail) {
+ *b_pos = wbit - *prev_tail;
+ *b_len = *prev_tail;
+ }
+
+ *prev_tail = 0;
+ return -1;
+ }
+
+ if (used > wpos) {
+ wpos = used;
+ if (*b_len < *prev_tail) {
+ *b_pos = wbit - *prev_tail;
+ *b_len = *prev_tail;
+ }
+
+ *prev_tail = 0;
+ }
+
+ /*
+ * Now we have a fragment [wpos, wend) staring with 0.
+ */
+ end = wpos + to_alloc - *prev_tail;
+ free_bits = find_next_bit(buf, min(end, wend), wpos);
+
+ free_len = *prev_tail + free_bits - wpos;
+
+ if (*b_len < free_len) {
+ *b_pos = wbit + wpos - *prev_tail;
+ *b_len = free_len;
+ }
+
+ if (free_len >= to_alloc)
+ return wbit + wpos - *prev_tail;
+
+ if (free_bits >= wend) {
+ *prev_tail += free_bits - wpos;
+ return -1;
+ }
+
+ wpos = free_bits + 1;
+
+ *prev_tail = 0;
+ }
+
+ return -1;
+}
+
+/*
+ * wnd_close - Frees all resources.
+ */
+void wnd_close(struct wnd_bitmap *wnd)
+{
+ struct rb_node *node, *next;
+
+ kfree(wnd->free_bits);
+ run_close(&wnd->run);
+
+ node = rb_first(&wnd->start_tree);
+
+ while (node) {
+ next = rb_next(node);
+ rb_erase(node, &wnd->start_tree);
+ kmem_cache_free(ntfs_enode_cachep,
+ rb_entry(node, struct e_node, start.node));
+ node = next;
+ }
+}
+
+static struct rb_node *rb_lookup(struct rb_root *root, size_t v)
+{
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *r = NULL;
+
+ while (*p) {
+ struct rb_node_key *k;
+
+ k = rb_entry(*p, struct rb_node_key, node);
+ if (v < k->key) {
+ p = &(*p)->rb_left;
+ } else if (v > k->key) {
+ r = &k->node;
+ p = &(*p)->rb_right;
+ } else {
+ return &k->node;
+ }
+ }
+
+ return r;
+}
+
+/*
+ * rb_insert_count - Helper function to insert special kind of 'count' tree.
+ */
+static inline bool rb_insert_count(struct rb_root *root, struct e_node *e)
+{
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ size_t e_ckey = e->count.key;
+ size_t e_skey = e->start.key;
+
+ while (*p) {
+ struct e_node *k =
+ rb_entry(parent = *p, struct e_node, count.node);
+
+ if (e_ckey > k->count.key) {
+ p = &(*p)->rb_left;
+ } else if (e_ckey < k->count.key) {
+ p = &(*p)->rb_right;
+ } else if (e_skey < k->start.key) {
+ p = &(*p)->rb_left;
+ } else if (e_skey > k->start.key) {
+ p = &(*p)->rb_right;
+ } else {
+ WARN_ON(1);
+ return false;
+ }
+ }
+
+ rb_link_node(&e->count.node, parent, p);
+ rb_insert_color(&e->count.node, root);
+ return true;
+}
+
+/*
+ * rb_insert_start - Helper function to insert special kind of 'count' tree.
+ */
+static inline bool rb_insert_start(struct rb_root *root, struct e_node *e)
+{
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ size_t e_skey = e->start.key;
+
+ while (*p) {
+ struct e_node *k;
+
+ parent = *p;
+
+ k = rb_entry(parent, struct e_node, start.node);
+ if (e_skey < k->start.key) {
+ p = &(*p)->rb_left;
+ } else if (e_skey > k->start.key) {
+ p = &(*p)->rb_right;
+ } else {
+ WARN_ON(1);
+ return false;
+ }
+ }
+
+ rb_link_node(&e->start.node, parent, p);
+ rb_insert_color(&e->start.node, root);
+ return true;
+}
+
+/*
+ * wnd_add_free_ext - Adds a new extent of free space.
+ * @build: 1 when building tree.
+ */
+static void wnd_add_free_ext(struct wnd_bitmap *wnd, size_t bit, size_t len,
+ bool build)
+{
+ struct e_node *e, *e0 = NULL;
+ size_t ib, end_in = bit + len;
+ struct rb_node *n;
+
+ if (build) {
+ /* Use extent_min to filter too short extents. */
+ if (wnd->count >= NTFS_MAX_WND_EXTENTS &&
+ len <= wnd->extent_min) {
+ wnd->uptodated = -1;
+ return;
+ }
+ } else {
+ /* Try to find extent before 'bit'. */
+ n = rb_lookup(&wnd->start_tree, bit);
+
+ if (!n) {
+ n = rb_first(&wnd->start_tree);
+ } else {
+ e = rb_entry(n, struct e_node, start.node);
+ n = rb_next(n);
+ if (e->start.key + e->count.key == bit) {
+ /* Remove left. */
+ bit = e->start.key;
+ len += e->count.key;
+ rb_erase(&e->start.node, &wnd->start_tree);
+ rb_erase(&e->count.node, &wnd->count_tree);
+ wnd->count -= 1;
+ e0 = e;
+ }
+ }
+
+ while (n) {
+ size_t next_end;
+
+ e = rb_entry(n, struct e_node, start.node);
+ next_end = e->start.key + e->count.key;
+ if (e->start.key > end_in)
+ break;
+
+ /* Remove right. */
+ n = rb_next(n);
+ len += next_end - end_in;
+ end_in = next_end;
+ rb_erase(&e->start.node, &wnd->start_tree);
+ rb_erase(&e->count.node, &wnd->count_tree);
+ wnd->count -= 1;
+
+ if (!e0)
+ e0 = e;
+ else
+ kmem_cache_free(ntfs_enode_cachep, e);
+ }
+
+ if (wnd->uptodated != 1) {
+ /* Check bits before 'bit'. */
+ ib = wnd->zone_bit == wnd->zone_end ||
+ bit < wnd->zone_end
+ ? 0
+ : wnd->zone_end;
+
+ while (bit > ib && wnd_is_free_hlp(wnd, bit - 1, 1)) {
+ bit -= 1;
+ len += 1;
+ }
+
+ /* Check bits after 'end_in'. */
+ ib = wnd->zone_bit == wnd->zone_end ||
+ end_in > wnd->zone_bit
+ ? wnd->nbits
+ : wnd->zone_bit;
+
+ while (end_in < ib && wnd_is_free_hlp(wnd, end_in, 1)) {
+ end_in += 1;
+ len += 1;
+ }
+ }
+ }
+ /* Insert new fragment. */
+ if (wnd->count >= NTFS_MAX_WND_EXTENTS) {
+ if (e0)
+ kmem_cache_free(ntfs_enode_cachep, e0);
+
+ wnd->uptodated = -1;
+
+ /* Compare with smallest fragment. */
+ n = rb_last(&wnd->count_tree);
+ e = rb_entry(n, struct e_node, count.node);
+ if (len <= e->count.key)
+ goto out; /* Do not insert small fragments. */
+
+ if (build) {
+ struct e_node *e2;
+
+ n = rb_prev(n);
+ e2 = rb_entry(n, struct e_node, count.node);
+ /* Smallest fragment will be 'e2->count.key'. */
+ wnd->extent_min = e2->count.key;
+ }
+
+ /* Replace smallest fragment by new one. */
+ rb_erase(&e->start.node, &wnd->start_tree);
+ rb_erase(&e->count.node, &wnd->count_tree);
+ wnd->count -= 1;
+ } else {
+ e = e0 ? e0 : kmem_cache_alloc(ntfs_enode_cachep, GFP_ATOMIC);
+ if (!e) {
+ wnd->uptodated = -1;
+ goto out;
+ }
+
+ if (build && len <= wnd->extent_min)
+ wnd->extent_min = len;
+ }
+ e->start.key = bit;
+ e->count.key = len;
+ if (len > wnd->extent_max)
+ wnd->extent_max = len;
+
+ rb_insert_start(&wnd->start_tree, e);
+ rb_insert_count(&wnd->count_tree, e);
+ wnd->count += 1;
+
+out:;
+}
+
+/*
+ * wnd_remove_free_ext - Remove a run from the cached free space.
+ */
+static void wnd_remove_free_ext(struct wnd_bitmap *wnd, size_t bit, size_t len)
+{
+ struct rb_node *n, *n3;
+ struct e_node *e, *e3;
+ size_t end_in = bit + len;
+ size_t end3, end, new_key, new_len, max_new_len;
+
+ /* Try to find extent before 'bit'. */
+ n = rb_lookup(&wnd->start_tree, bit);
+
+ if (!n)
+ return;
+
+ e = rb_entry(n, struct e_node, start.node);
+ end = e->start.key + e->count.key;
+
+ new_key = new_len = 0;
+ len = e->count.key;
+
+ /* Range [bit,end_in) must be inside 'e' or outside 'e' and 'n'. */
+ if (e->start.key > bit)
+ ;
+ else if (end_in <= end) {
+ /* Range [bit,end_in) inside 'e'. */
+ new_key = end_in;
+ new_len = end - end_in;
+ len = bit - e->start.key;
+ } else if (bit > end) {
+ bool bmax = false;
+
+ n3 = rb_next(n);
+
+ while (n3) {
+ e3 = rb_entry(n3, struct e_node, start.node);
+ if (e3->start.key >= end_in)
+ break;
+
+ if (e3->count.key == wnd->extent_max)
+ bmax = true;
+
+ end3 = e3->start.key + e3->count.key;
+ if (end3 > end_in) {
+ e3->start.key = end_in;
+ rb_erase(&e3->count.node, &wnd->count_tree);
+ e3->count.key = end3 - end_in;
+ rb_insert_count(&wnd->count_tree, e3);
+ break;
+ }
+
+ n3 = rb_next(n3);
+ rb_erase(&e3->start.node, &wnd->start_tree);
+ rb_erase(&e3->count.node, &wnd->count_tree);
+ wnd->count -= 1;
+ kmem_cache_free(ntfs_enode_cachep, e3);
+ }
+ if (!bmax)
+ return;
+ n3 = rb_first(&wnd->count_tree);
+ wnd->extent_max =
+ n3 ? rb_entry(n3, struct e_node, count.node)->count.key
+ : 0;
+ return;
+ }
+
+ if (e->count.key != wnd->extent_max) {
+ ;
+ } else if (rb_prev(&e->count.node)) {
+ ;
+ } else {
+ n3 = rb_next(&e->count.node);
+ max_new_len = len > new_len ? len : new_len;
+ if (!n3) {
+ wnd->extent_max = max_new_len;
+ } else {
+ e3 = rb_entry(n3, struct e_node, count.node);
+ wnd->extent_max = max(e3->count.key, max_new_len);
+ }
+ }
+
+ if (!len) {
+ if (new_len) {
+ e->start.key = new_key;
+ rb_erase(&e->count.node, &wnd->count_tree);
+ e->count.key = new_len;
+ rb_insert_count(&wnd->count_tree, e);
+ } else {
+ rb_erase(&e->start.node, &wnd->start_tree);
+ rb_erase(&e->count.node, &wnd->count_tree);
+ wnd->count -= 1;
+ kmem_cache_free(ntfs_enode_cachep, e);
+ }
+ goto out;
+ }
+ rb_erase(&e->count.node, &wnd->count_tree);
+ e->count.key = len;
+ rb_insert_count(&wnd->count_tree, e);
+
+ if (!new_len)
+ goto out;
+
+ if (wnd->count >= NTFS_MAX_WND_EXTENTS) {
+ wnd->uptodated = -1;
+
+ /* Get minimal extent. */
+ e = rb_entry(rb_last(&wnd->count_tree), struct e_node,
+ count.node);
+ if (e->count.key > new_len)
+ goto out;
+
+ /* Replace minimum. */
+ rb_erase(&e->start.node, &wnd->start_tree);
+ rb_erase(&e->count.node, &wnd->count_tree);
+ wnd->count -= 1;
+ } else {
+ e = kmem_cache_alloc(ntfs_enode_cachep, GFP_ATOMIC);
+ if (!e)
+ wnd->uptodated = -1;
+ }
+
+ if (e) {
+ e->start.key = new_key;
+ e->count.key = new_len;
+ rb_insert_start(&wnd->start_tree, e);
+ rb_insert_count(&wnd->count_tree, e);
+ wnd->count += 1;
+ }
+
+out:
+ if (!wnd->count && 1 != wnd->uptodated)
+ wnd_rescan(wnd);
+}
+
+/*
+ * wnd_rescan - Scan all bitmap. Used while initialization.
+ */
+static int wnd_rescan(struct wnd_bitmap *wnd)
+{
+ int err = 0;
+ size_t prev_tail = 0;
+ struct super_block *sb = wnd->sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ u64 lbo, len = 0;
+ u32 blocksize = sb->s_blocksize;
+ u8 cluster_bits = sbi->cluster_bits;
+ u32 wbits = 8 * sb->s_blocksize;
+ u32 used, frb;
+ const ulong *buf;
+ size_t wpos, wbit, iw, vbo;
+ struct buffer_head *bh = NULL;
+ CLST lcn, clen;
+
+ wnd->uptodated = 0;
+ wnd->extent_max = 0;
+ wnd->extent_min = MINUS_ONE_T;
+ wnd->total_zeroes = 0;
+
+ vbo = 0;
+
+ for (iw = 0; iw < wnd->nwnd; iw++) {
+ if (iw + 1 == wnd->nwnd)
+ wbits = wnd->bits_last;
+
+ if (wnd->inited) {
+ if (!wnd->free_bits[iw]) {
+ /* All ones. */
+ if (prev_tail) {
+ wnd_add_free_ext(wnd,
+ vbo * 8 - prev_tail,
+ prev_tail, true);
+ prev_tail = 0;
+ }
+ goto next_wnd;
+ }
+ if (wbits == wnd->free_bits[iw]) {
+ /* All zeroes. */
+ prev_tail += wbits;
+ wnd->total_zeroes += wbits;
+ goto next_wnd;
+ }
+ }
+
+ if (!len) {
+ u32 off = vbo & sbi->cluster_mask;
+
+ if (!run_lookup_entry(&wnd->run, vbo >> cluster_bits,
+ &lcn, &clen, NULL)) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ lbo = ((u64)lcn << cluster_bits) + off;
+ len = ((u64)clen << cluster_bits) - off;
+ }
+
+ bh = ntfs_bread(sb, lbo >> sb->s_blocksize_bits);
+ if (!bh) {
+ err = -EIO;
+ goto out;
+ }
+
+ buf = (ulong *)bh->b_data;
+
+ used = __bitmap_weight(buf, wbits);
+ if (used < wbits) {
+ frb = wbits - used;
+ wnd->free_bits[iw] = frb;
+ wnd->total_zeroes += frb;
+ }
+
+ wpos = 0;
+ wbit = vbo * 8;
+
+ if (wbit + wbits > wnd->nbits)
+ wbits = wnd->nbits - wbit;
+
+ do {
+ used = find_next_zero_bit(buf, wbits, wpos);
+
+ if (used > wpos && prev_tail) {
+ wnd_add_free_ext(wnd, wbit + wpos - prev_tail,
+ prev_tail, true);
+ prev_tail = 0;
+ }
+
+ wpos = used;
+
+ if (wpos >= wbits) {
+ /* No free blocks. */
+ prev_tail = 0;
+ break;
+ }
+
+ frb = find_next_bit(buf, wbits, wpos);
+ if (frb >= wbits) {
+ /* Keep last free block. */
+ prev_tail += frb - wpos;
+ break;
+ }
+
+ wnd_add_free_ext(wnd, wbit + wpos - prev_tail,
+ frb + prev_tail - wpos, true);
+
+ /* Skip free block and first '1'. */
+ wpos = frb + 1;
+ /* Reset previous tail. */
+ prev_tail = 0;
+ } while (wpos < wbits);
+
+next_wnd:
+
+ if (bh)
+ put_bh(bh);
+ bh = NULL;
+
+ vbo += blocksize;
+ if (len) {
+ len -= blocksize;
+ lbo += blocksize;
+ }
+ }
+
+ /* Add last block. */
+ if (prev_tail)
+ wnd_add_free_ext(wnd, wnd->nbits - prev_tail, prev_tail, true);
+
+ /*
+ * Before init cycle wnd->uptodated was 0.
+ * If any errors or limits occurs while initialization then
+ * wnd->uptodated will be -1.
+ * If 'uptodated' is still 0 then Tree is really updated.
+ */
+ if (!wnd->uptodated)
+ wnd->uptodated = 1;
+
+ if (wnd->zone_bit != wnd->zone_end) {
+ size_t zlen = wnd->zone_end - wnd->zone_bit;
+
+ wnd->zone_end = wnd->zone_bit;
+ wnd_zone_set(wnd, wnd->zone_bit, zlen);
+ }
+
+out:
+ return err;
+}
+
+int wnd_init(struct wnd_bitmap *wnd, struct super_block *sb, size_t nbits)
+{
+ int err;
+ u32 blocksize = sb->s_blocksize;
+ u32 wbits = blocksize * 8;
+
+ init_rwsem(&wnd->rw_lock);
+
+ wnd->sb = sb;
+ wnd->nbits = nbits;
+ wnd->total_zeroes = nbits;
+ wnd->extent_max = MINUS_ONE_T;
+ wnd->zone_bit = wnd->zone_end = 0;
+ wnd->nwnd = bytes_to_block(sb, bitmap_size(nbits));
+ wnd->bits_last = nbits & (wbits - 1);
+ if (!wnd->bits_last)
+ wnd->bits_last = wbits;
+
+ wnd->free_bits = kcalloc(wnd->nwnd, sizeof(u16), GFP_NOFS);
+ if (!wnd->free_bits)
+ return -ENOMEM;
+
+ err = wnd_rescan(wnd);
+ if (err)
+ return err;
+
+ wnd->inited = true;
+
+ return 0;
+}
+
+/*
+ * wnd_map - Call sb_bread for requested window.
+ */
+static struct buffer_head *wnd_map(struct wnd_bitmap *wnd, size_t iw)
+{
+ size_t vbo;
+ CLST lcn, clen;
+ struct super_block *sb = wnd->sb;
+ struct ntfs_sb_info *sbi;
+ struct buffer_head *bh;
+ u64 lbo;
+
+ sbi = sb->s_fs_info;
+ vbo = (u64)iw << sb->s_blocksize_bits;
+
+ if (!run_lookup_entry(&wnd->run, vbo >> sbi->cluster_bits, &lcn, &clen,
+ NULL)) {
+ return ERR_PTR(-ENOENT);
+ }
+
+ lbo = ((u64)lcn << sbi->cluster_bits) + (vbo & sbi->cluster_mask);
+
+ bh = ntfs_bread(wnd->sb, lbo >> sb->s_blocksize_bits);
+ if (!bh)
+ return ERR_PTR(-EIO);
+
+ return bh;
+}
+
+/*
+ * wnd_set_free - Mark the bits range from bit to bit + bits as free.
+ */
+int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits)
+{
+ int err = 0;
+ struct super_block *sb = wnd->sb;
+ size_t bits0 = bits;
+ u32 wbits = 8 * sb->s_blocksize;
+ size_t iw = bit >> (sb->s_blocksize_bits + 3);
+ u32 wbit = bit & (wbits - 1);
+ struct buffer_head *bh;
+
+ while (iw < wnd->nwnd && bits) {
+ u32 tail, op;
+ ulong *buf;
+
+ if (iw + 1 == wnd->nwnd)
+ wbits = wnd->bits_last;
+
+ tail = wbits - wbit;
+ op = tail < bits ? tail : bits;
+
+ bh = wnd_map(wnd, iw);
+ if (IS_ERR(bh)) {
+ err = PTR_ERR(bh);
+ break;
+ }
+
+ buf = (ulong *)bh->b_data;
+
+ lock_buffer(bh);
+
+ __bitmap_clear(buf, wbit, op);
+
+ wnd->free_bits[iw] += op;
+
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ put_bh(bh);
+
+ wnd->total_zeroes += op;
+ bits -= op;
+ wbit = 0;
+ iw += 1;
+ }
+
+ wnd_add_free_ext(wnd, bit, bits0, false);
+
+ return err;
+}
+
+/*
+ * wnd_set_used - Mark the bits range from bit to bit + bits as used.
+ */
+int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)
+{
+ int err = 0;
+ struct super_block *sb = wnd->sb;
+ size_t bits0 = bits;
+ size_t iw = bit >> (sb->s_blocksize_bits + 3);
+ u32 wbits = 8 * sb->s_blocksize;
+ u32 wbit = bit & (wbits - 1);
+ struct buffer_head *bh;
+
+ while (iw < wnd->nwnd && bits) {
+ u32 tail, op;
+ ulong *buf;
+
+ if (unlikely(iw + 1 == wnd->nwnd))
+ wbits = wnd->bits_last;
+
+ tail = wbits - wbit;
+ op = tail < bits ? tail : bits;
+
+ bh = wnd_map(wnd, iw);
+ if (IS_ERR(bh)) {
+ err = PTR_ERR(bh);
+ break;
+ }
+ buf = (ulong *)bh->b_data;
+
+ lock_buffer(bh);
+
+ __bitmap_set(buf, wbit, op);
+ wnd->free_bits[iw] -= op;
+
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ put_bh(bh);
+
+ wnd->total_zeroes -= op;
+ bits -= op;
+ wbit = 0;
+ iw += 1;
+ }
+
+ if (!RB_EMPTY_ROOT(&wnd->start_tree))
+ wnd_remove_free_ext(wnd, bit, bits0);
+
+ return err;
+}
+
+/*
+ * wnd_is_free_hlp
+ *
+ * Return: True if all clusters [bit, bit+bits) are free (bitmap only).
+ */
+static bool wnd_is_free_hlp(struct wnd_bitmap *wnd, size_t bit, size_t bits)
+{
+ struct super_block *sb = wnd->sb;
+ size_t iw = bit >> (sb->s_blocksize_bits + 3);
+ u32 wbits = 8 * sb->s_blocksize;
+ u32 wbit = bit & (wbits - 1);
+
+ while (iw < wnd->nwnd && bits) {
+ u32 tail, op;
+
+ if (unlikely(iw + 1 == wnd->nwnd))
+ wbits = wnd->bits_last;
+
+ tail = wbits - wbit;
+ op = tail < bits ? tail : bits;
+
+ if (wbits != wnd->free_bits[iw]) {
+ bool ret;
+ struct buffer_head *bh = wnd_map(wnd, iw);
+
+ if (IS_ERR(bh))
+ return false;
+
+ ret = are_bits_clear((ulong *)bh->b_data, wbit, op);
+
+ put_bh(bh);
+ if (!ret)
+ return false;
+ }
+
+ bits -= op;
+ wbit = 0;
+ iw += 1;
+ }
+
+ return true;
+}
+
+/*
+ * wnd_is_free
+ *
+ * Return: True if all clusters [bit, bit+bits) are free.
+ */
+bool wnd_is_free(struct wnd_bitmap *wnd, size_t bit, size_t bits)
+{
+ bool ret;
+ struct rb_node *n;
+ size_t end;
+ struct e_node *e;
+
+ if (RB_EMPTY_ROOT(&wnd->start_tree))
+ goto use_wnd;
+
+ n = rb_lookup(&wnd->start_tree, bit);
+ if (!n)
+ goto use_wnd;
+
+ e = rb_entry(n, struct e_node, start.node);
+
+ end = e->start.key + e->count.key;
+
+ if (bit < end && bit + bits <= end)
+ return true;
+
+use_wnd:
+ ret = wnd_is_free_hlp(wnd, bit, bits);
+
+ return ret;
+}
+
+/*
+ * wnd_is_used
+ *
+ * Return: True if all clusters [bit, bit+bits) are used.
+ */
+bool wnd_is_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)
+{
+ bool ret = false;
+ struct super_block *sb = wnd->sb;
+ size_t iw = bit >> (sb->s_blocksize_bits + 3);
+ u32 wbits = 8 * sb->s_blocksize;
+ u32 wbit = bit & (wbits - 1);
+ size_t end;
+ struct rb_node *n;
+ struct e_node *e;
+
+ if (RB_EMPTY_ROOT(&wnd->start_tree))
+ goto use_wnd;
+
+ end = bit + bits;
+ n = rb_lookup(&wnd->start_tree, end - 1);
+ if (!n)
+ goto use_wnd;
+
+ e = rb_entry(n, struct e_node, start.node);
+ if (e->start.key + e->count.key > bit)
+ return false;
+
+use_wnd:
+ while (iw < wnd->nwnd && bits) {
+ u32 tail, op;
+
+ if (unlikely(iw + 1 == wnd->nwnd))
+ wbits = wnd->bits_last;
+
+ tail = wbits - wbit;
+ op = tail < bits ? tail : bits;
+
+ if (wnd->free_bits[iw]) {
+ bool ret;
+ struct buffer_head *bh = wnd_map(wnd, iw);
+
+ if (IS_ERR(bh))
+ goto out;
+
+ ret = are_bits_set((ulong *)bh->b_data, wbit, op);
+ put_bh(bh);
+ if (!ret)
+ goto out;
+ }
+
+ bits -= op;
+ wbit = 0;
+ iw += 1;
+ }
+ ret = true;
+
+out:
+ return ret;
+}
+
+/*
+ * wnd_find - Look for free space.
+ *
+ * - flags - BITMAP_FIND_XXX flags
+ *
+ * Return: 0 if not found.
+ */
+size_t wnd_find(struct wnd_bitmap *wnd, size_t to_alloc, size_t hint,
+ size_t flags, size_t *allocated)
+{
+ struct super_block *sb;
+ u32 wbits, wpos, wzbit, wzend;
+ size_t fnd, max_alloc, b_len, b_pos;
+ size_t iw, prev_tail, nwnd, wbit, ebit, zbit, zend;
+ size_t to_alloc0 = to_alloc;
+ const ulong *buf;
+ const struct e_node *e;
+ const struct rb_node *pr, *cr;
+ u8 log2_bits;
+ bool fbits_valid;
+ struct buffer_head *bh;
+
+ /* Fast checking for available free space. */
+ if (flags & BITMAP_FIND_FULL) {
+ size_t zeroes = wnd_zeroes(wnd);
+
+ zeroes -= wnd->zone_end - wnd->zone_bit;
+ if (zeroes < to_alloc0)
+ goto no_space;
+
+ if (to_alloc0 > wnd->extent_max)
+ goto no_space;
+ } else {
+ if (to_alloc > wnd->extent_max)
+ to_alloc = wnd->extent_max;
+ }
+
+ if (wnd->zone_bit <= hint && hint < wnd->zone_end)
+ hint = wnd->zone_end;
+
+ max_alloc = wnd->nbits;
+ b_len = b_pos = 0;
+
+ if (hint >= max_alloc)
+ hint = 0;
+
+ if (RB_EMPTY_ROOT(&wnd->start_tree)) {
+ if (wnd->uptodated == 1) {
+ /* Extents tree is updated -> No free space. */
+ goto no_space;
+ }
+ goto scan_bitmap;
+ }
+
+ e = NULL;
+ if (!hint)
+ goto allocate_biggest;
+
+ /* Use hint: Enumerate extents by start >= hint. */
+ pr = NULL;
+ cr = wnd->start_tree.rb_node;
+
+ for (;;) {
+ e = rb_entry(cr, struct e_node, start.node);
+
+ if (e->start.key == hint)
+ break;
+
+ if (e->start.key < hint) {
+ pr = cr;
+ cr = cr->rb_right;
+ if (!cr)
+ break;
+ continue;
+ }
+
+ cr = cr->rb_left;
+ if (!cr) {
+ e = pr ? rb_entry(pr, struct e_node, start.node) : NULL;
+ break;
+ }
+ }
+
+ if (!e)
+ goto allocate_biggest;
+
+ if (e->start.key + e->count.key > hint) {
+ /* We have found extension with 'hint' inside. */
+ size_t len = e->start.key + e->count.key - hint;
+
+ if (len >= to_alloc && hint + to_alloc <= max_alloc) {
+ fnd = hint;
+ goto found;
+ }
+
+ if (!(flags & BITMAP_FIND_FULL)) {
+ if (len > to_alloc)
+ len = to_alloc;
+
+ if (hint + len <= max_alloc) {
+ fnd = hint;
+ to_alloc = len;
+ goto found;
+ }
+ }
+ }
+
+allocate_biggest:
+ /* Allocate from biggest free extent. */
+ e = rb_entry(rb_first(&wnd->count_tree), struct e_node, count.node);
+ if (e->count.key != wnd->extent_max)
+ wnd->extent_max = e->count.key;
+
+ if (e->count.key < max_alloc) {
+ if (e->count.key >= to_alloc) {
+ ;
+ } else if (flags & BITMAP_FIND_FULL) {
+ if (e->count.key < to_alloc0) {
+ /* Biggest free block is less then requested. */
+ goto no_space;
+ }
+ to_alloc = e->count.key;
+ } else if (-1 != wnd->uptodated) {
+ to_alloc = e->count.key;
+ } else {
+ /* Check if we can use more bits. */
+ size_t op, max_check;
+ struct rb_root start_tree;
+
+ memcpy(&start_tree, &wnd->start_tree,
+ sizeof(struct rb_root));
+ memset(&wnd->start_tree, 0, sizeof(struct rb_root));
+
+ max_check = e->start.key + to_alloc;
+ if (max_check > max_alloc)
+ max_check = max_alloc;
+ for (op = e->start.key + e->count.key; op < max_check;
+ op++) {
+ if (!wnd_is_free(wnd, op, 1))
+ break;
+ }
+ memcpy(&wnd->start_tree, &start_tree,
+ sizeof(struct rb_root));
+ to_alloc = op - e->start.key;
+ }
+
+ /* Prepare to return. */
+ fnd = e->start.key;
+ if (e->start.key + to_alloc > max_alloc)
+ to_alloc = max_alloc - e->start.key;
+ goto found;
+ }
+
+ if (wnd->uptodated == 1) {
+ /* Extents tree is updated -> no free space. */
+ goto no_space;
+ }
+
+ b_len = e->count.key;
+ b_pos = e->start.key;
+
+scan_bitmap:
+ sb = wnd->sb;
+ log2_bits = sb->s_blocksize_bits + 3;
+
+ /* At most two ranges [hint, max_alloc) + [0, hint). */
+Again:
+
+ /* TODO: Optimize request for case nbits > wbits. */
+ iw = hint >> log2_bits;
+ wbits = sb->s_blocksize * 8;
+ wpos = hint & (wbits - 1);
+ prev_tail = 0;
+ fbits_valid = true;
+
+ if (max_alloc == wnd->nbits) {
+ nwnd = wnd->nwnd;
+ } else {
+ size_t t = max_alloc + wbits - 1;
+
+ nwnd = likely(t > max_alloc) ? (t >> log2_bits) : wnd->nwnd;
+ }
+
+ /* Enumerate all windows. */
+ for (; iw < nwnd; iw++) {
+ wbit = iw << log2_bits;
+
+ if (!wnd->free_bits[iw]) {
+ if (prev_tail > b_len) {
+ b_pos = wbit - prev_tail;
+ b_len = prev_tail;
+ }
+
+ /* Skip full used window. */
+ prev_tail = 0;
+ wpos = 0;
+ continue;
+ }
+
+ if (unlikely(iw + 1 == nwnd)) {
+ if (max_alloc == wnd->nbits) {
+ wbits = wnd->bits_last;
+ } else {
+ size_t t = max_alloc & (wbits - 1);
+
+ if (t) {
+ wbits = t;
+ fbits_valid = false;
+ }
+ }
+ }
+
+ if (wnd->zone_end > wnd->zone_bit) {
+ ebit = wbit + wbits;
+ zbit = max(wnd->zone_bit, wbit);
+ zend = min(wnd->zone_end, ebit);
+
+ /* Here we have a window [wbit, ebit) and zone [zbit, zend). */
+ if (zend <= zbit) {
+ /* Zone does not overlap window. */
+ } else {
+ wzbit = zbit - wbit;
+ wzend = zend - wbit;
+
+ /* Zone overlaps window. */
+ if (wnd->free_bits[iw] == wzend - wzbit) {
+ prev_tail = 0;
+ wpos = 0;
+ continue;
+ }
+
+ /* Scan two ranges window: [wbit, zbit) and [zend, ebit). */
+ bh = wnd_map(wnd, iw);
+
+ if (IS_ERR(bh)) {
+ /* TODO: Error */
+ prev_tail = 0;
+ wpos = 0;
+ continue;
+ }
+
+ buf = (ulong *)bh->b_data;
+
+ /* Scan range [wbit, zbit). */
+ if (wpos < wzbit) {
+ /* Scan range [wpos, zbit). */
+ fnd = wnd_scan(buf, wbit, wpos, wzbit,
+ to_alloc, &prev_tail,
+ &b_pos, &b_len);
+ if (fnd != MINUS_ONE_T) {
+ put_bh(bh);
+ goto found;
+ }
+ }
+
+ prev_tail = 0;
+
+ /* Scan range [zend, ebit). */
+ if (wzend < wbits) {
+ fnd = wnd_scan(buf, wbit,
+ max(wzend, wpos), wbits,
+ to_alloc, &prev_tail,
+ &b_pos, &b_len);
+ if (fnd != MINUS_ONE_T) {
+ put_bh(bh);
+ goto found;
+ }
+ }
+
+ wpos = 0;
+ put_bh(bh);
+ continue;
+ }
+ }
+
+ /* Current window does not overlap zone. */
+ if (!wpos && fbits_valid && wnd->free_bits[iw] == wbits) {
+ /* Window is empty. */
+ if (prev_tail + wbits >= to_alloc) {
+ fnd = wbit + wpos - prev_tail;
+ goto found;
+ }
+
+ /* Increase 'prev_tail' and process next window. */
+ prev_tail += wbits;
+ wpos = 0;
+ continue;
+ }
+
+ /* Read window. */
+ bh = wnd_map(wnd, iw);
+ if (IS_ERR(bh)) {
+ // TODO: Error.
+ prev_tail = 0;
+ wpos = 0;
+ continue;
+ }
+
+ buf = (ulong *)bh->b_data;
+
+ /* Scan range [wpos, eBits). */
+ fnd = wnd_scan(buf, wbit, wpos, wbits, to_alloc, &prev_tail,
+ &b_pos, &b_len);
+ put_bh(bh);
+ if (fnd != MINUS_ONE_T)
+ goto found;
+ }
+
+ if (b_len < prev_tail) {
+ /* The last fragment. */
+ b_len = prev_tail;
+ b_pos = max_alloc - prev_tail;
+ }
+
+ if (hint) {
+ /*
+ * We have scanned range [hint max_alloc).
+ * Prepare to scan range [0 hint + to_alloc).
+ */
+ size_t nextmax = hint + to_alloc;
+
+ if (likely(nextmax >= hint) && nextmax < max_alloc)
+ max_alloc = nextmax;
+ hint = 0;
+ goto Again;
+ }
+
+ if (!b_len)
+ goto no_space;
+
+ wnd->extent_max = b_len;
+
+ if (flags & BITMAP_FIND_FULL)
+ goto no_space;
+
+ fnd = b_pos;
+ to_alloc = b_len;
+
+found:
+ if (flags & BITMAP_FIND_MARK_AS_USED) {
+ /* TODO: Optimize remove extent (pass 'e'?). */
+ if (wnd_set_used(wnd, fnd, to_alloc))
+ goto no_space;
+ } else if (wnd->extent_max != MINUS_ONE_T &&
+ to_alloc > wnd->extent_max) {
+ wnd->extent_max = to_alloc;
+ }
+
+ *allocated = fnd;
+ return to_alloc;
+
+no_space:
+ return 0;
+}
+
+/*
+ * wnd_extend - Extend bitmap ($MFT bitmap).
+ */
+int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)
+{
+ int err;
+ struct super_block *sb = wnd->sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ u32 blocksize = sb->s_blocksize;
+ u32 wbits = blocksize * 8;
+ u32 b0, new_last;
+ size_t bits, iw, new_wnd;
+ size_t old_bits = wnd->nbits;
+ u16 *new_free;
+
+ if (new_bits <= old_bits)
+ return -EINVAL;
+
+ /* Align to 8 byte boundary. */
+ new_wnd = bytes_to_block(sb, bitmap_size(new_bits));
+ new_last = new_bits & (wbits - 1);
+ if (!new_last)
+ new_last = wbits;
+
+ if (new_wnd != wnd->nwnd) {
+ new_free = kmalloc(new_wnd * sizeof(u16), GFP_NOFS);
+ if (!new_free)
+ return -ENOMEM;
+
+ if (new_free != wnd->free_bits)
+ memcpy(new_free, wnd->free_bits,
+ wnd->nwnd * sizeof(short));
+ memset(new_free + wnd->nwnd, 0,
+ (new_wnd - wnd->nwnd) * sizeof(short));
+ kfree(wnd->free_bits);
+ wnd->free_bits = new_free;
+ }
+
+ /* Zero bits [old_bits,new_bits). */
+ bits = new_bits - old_bits;
+ b0 = old_bits & (wbits - 1);
+
+ for (iw = old_bits >> (sb->s_blocksize_bits + 3); bits; iw += 1) {
+ u32 op;
+ size_t frb;
+ u64 vbo, lbo, bytes;
+ struct buffer_head *bh;
+ ulong *buf;
+
+ if (iw + 1 == new_wnd)
+ wbits = new_last;
+
+ op = b0 + bits > wbits ? wbits - b0 : bits;
+ vbo = (u64)iw * blocksize;
+
+ err = ntfs_vbo_to_lbo(sbi, &wnd->run, vbo, &lbo, &bytes);
+ if (err)
+ break;
+
+ bh = ntfs_bread(sb, lbo >> sb->s_blocksize_bits);
+ if (!bh)
+ return -EIO;
+
+ lock_buffer(bh);
+ buf = (ulong *)bh->b_data;
+
+ __bitmap_clear(buf, b0, blocksize * 8 - b0);
+ frb = wbits - __bitmap_weight(buf, wbits);
+ wnd->total_zeroes += frb - wnd->free_bits[iw];
+ wnd->free_bits[iw] = frb;
+
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ /* err = sync_dirty_buffer(bh); */
+
+ b0 = 0;
+ bits -= op;
+ }
+
+ wnd->nbits = new_bits;
+ wnd->nwnd = new_wnd;
+ wnd->bits_last = new_last;
+
+ wnd_add_free_ext(wnd, old_bits, new_bits - old_bits, false);
+
+ return 0;
+}
+
+void wnd_zone_set(struct wnd_bitmap *wnd, size_t lcn, size_t len)
+{
+ size_t zlen;
+
+ zlen = wnd->zone_end - wnd->zone_bit;
+ if (zlen)
+ wnd_add_free_ext(wnd, wnd->zone_bit, zlen, false);
+
+ if (!RB_EMPTY_ROOT(&wnd->start_tree) && len)
+ wnd_remove_free_ext(wnd, lcn, len);
+
+ wnd->zone_bit = lcn;
+ wnd->zone_end = lcn + len;
+}
+
+int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range)
+{
+ int err = 0;
+ struct super_block *sb = sbi->sb;
+ struct wnd_bitmap *wnd = &sbi->used.bitmap;
+ u32 wbits = 8 * sb->s_blocksize;
+ CLST len = 0, lcn = 0, done = 0;
+ CLST minlen = bytes_to_cluster(sbi, range->minlen);
+ CLST lcn_from = bytes_to_cluster(sbi, range->start);
+ size_t iw = lcn_from >> (sb->s_blocksize_bits + 3);
+ u32 wbit = lcn_from & (wbits - 1);
+ const ulong *buf;
+ CLST lcn_to;
+
+ if (!minlen)
+ minlen = 1;
+
+ if (range->len == (u64)-1)
+ lcn_to = wnd->nbits;
+ else
+ lcn_to = bytes_to_cluster(sbi, range->start + range->len);
+
+ down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
+
+ for (; iw < wnd->nbits; iw++, wbit = 0) {
+ CLST lcn_wnd = iw * wbits;
+ struct buffer_head *bh;
+
+ if (lcn_wnd > lcn_to)
+ break;
+
+ if (!wnd->free_bits[iw])
+ continue;
+
+ if (iw + 1 == wnd->nwnd)
+ wbits = wnd->bits_last;
+
+ if (lcn_wnd + wbits > lcn_to)
+ wbits = lcn_to - lcn_wnd;
+
+ bh = wnd_map(wnd, iw);
+ if (IS_ERR(bh)) {
+ err = PTR_ERR(bh);
+ break;
+ }
+
+ buf = (ulong *)bh->b_data;
+
+ for (; wbit < wbits; wbit++) {
+ if (!test_bit(wbit, buf)) {
+ if (!len)
+ lcn = lcn_wnd + wbit;
+ len += 1;
+ continue;
+ }
+ if (len >= minlen) {
+ err = ntfs_discard(sbi, lcn, len);
+ if (err)
+ goto out;
+ done += len;
+ }
+ len = 0;
+ }
+ put_bh(bh);
+ }
+
+ /* Process the last fragment. */
+ if (len >= minlen) {
+ err = ntfs_discard(sbi, lcn, len);
+ if (err)
+ goto out;
+ done += len;
+ }
+
+out:
+ range->len = (u64)done << sbi->cluster_bits;
+
+ up_read(&wnd->rw_lock);
+
+ return err;
+}
diff --git a/fs/ntfs3/debug.h b/fs/ntfs3/debug.h
new file mode 100644
index 000000000000..31120569a87b
--- /dev/null
+++ b/fs/ntfs3/debug.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ * Useful functions for debugging.
+ *
+ */
+
+// clang-format off
+#ifndef _LINUX_NTFS3_DEBUG_H
+#define _LINUX_NTFS3_DEBUG_H
+
+#ifndef Add2Ptr
+#define Add2Ptr(P, I) ((void *)((u8 *)(P) + (I)))
+#define PtrOffset(B, O) ((size_t)((size_t)(O) - (size_t)(B)))
+#endif
+
+#ifdef CONFIG_PRINTK
+__printf(2, 3)
+void ntfs_printk(const struct super_block *sb, const char *fmt, ...);
+__printf(2, 3)
+void ntfs_inode_printk(struct inode *inode, const char *fmt, ...);
+#else
+static inline __printf(2, 3)
+void ntfs_printk(const struct super_block *sb, const char *fmt, ...)
+{
+}
+
+static inline __printf(2, 3)
+void ntfs_inode_printk(struct inode *inode, const char *fmt, ...)
+{
+}
+#endif
+
+/*
+ * Logging macros. Thanks Joe Perches <joe@perches.com> for implementation.
+ */
+
+#define ntfs_err(sb, fmt, ...) ntfs_printk(sb, KERN_ERR fmt, ##__VA_ARGS__)
+#define ntfs_warn(sb, fmt, ...) ntfs_printk(sb, KERN_WARNING fmt, ##__VA_ARGS__)
+#define ntfs_info(sb, fmt, ...) ntfs_printk(sb, KERN_INFO fmt, ##__VA_ARGS__)
+#define ntfs_notice(sb, fmt, ...) \
+ ntfs_printk(sb, KERN_NOTICE fmt, ##__VA_ARGS__)
+
+#define ntfs_inode_err(inode, fmt, ...) \
+ ntfs_inode_printk(inode, KERN_ERR fmt, ##__VA_ARGS__)
+#define ntfs_inode_warn(inode, fmt, ...) \
+ ntfs_inode_printk(inode, KERN_WARNING fmt, ##__VA_ARGS__)
+
+#endif /* _LINUX_NTFS3_DEBUG_H */
+// clang-format on
diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c
new file mode 100644
index 000000000000..93f6d485564e
--- /dev/null
+++ b/fs/ntfs3/dir.c
@@ -0,0 +1,599 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ * Directory handling functions for NTFS-based filesystems.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/iversion.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+/* Convert little endian UTF-16 to NLS string. */
+int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni,
+ u8 *buf, int buf_len)
+{
+ int ret, uni_len, warn;
+ const __le16 *ip;
+ u8 *op;
+ struct nls_table *nls = sbi->options.nls;
+
+ static_assert(sizeof(wchar_t) == sizeof(__le16));
+
+ if (!nls) {
+ /* UTF-16 -> UTF-8 */
+ ret = utf16s_to_utf8s((wchar_t *)uni->name, uni->len,
+ UTF16_LITTLE_ENDIAN, buf, buf_len);
+ buf[ret] = '\0';
+ return ret;
+ }
+
+ ip = uni->name;
+ op = buf;
+ uni_len = uni->len;
+ warn = 0;
+
+ while (uni_len--) {
+ u16 ec;
+ int charlen;
+ char dump[5];
+
+ if (buf_len < NLS_MAX_CHARSET_SIZE) {
+ ntfs_warn(sbi->sb,
+ "filename was truncated while converting.");
+ break;
+ }
+
+ ec = le16_to_cpu(*ip++);
+ charlen = nls->uni2char(ec, op, buf_len);
+
+ if (charlen > 0) {
+ op += charlen;
+ buf_len -= charlen;
+ continue;
+ }
+
+ *op++ = '_';
+ buf_len -= 1;
+ if (warn)
+ continue;
+
+ warn = 1;
+ hex_byte_pack(&dump[0], ec >> 8);
+ hex_byte_pack(&dump[2], ec);
+ dump[4] = 0;
+
+ ntfs_err(sbi->sb, "failed to convert \"%s\" to %s", dump,
+ nls->charset);
+ }
+
+ *op = '\0';
+ return op - buf;
+}
+
+// clang-format off
+#define PLANE_SIZE 0x00010000
+
+#define SURROGATE_PAIR 0x0000d800
+#define SURROGATE_LOW 0x00000400
+#define SURROGATE_BITS 0x000003ff
+// clang-format on
+
+/*
+ * put_utf16 - Modified version of put_utf16 from fs/nls/nls_base.c
+ *
+ * Function is sparse warnings free.
+ */
+static inline void put_utf16(wchar_t *s, unsigned int c,
+ enum utf16_endian endian)
+{
+ static_assert(sizeof(wchar_t) == sizeof(__le16));
+ static_assert(sizeof(wchar_t) == sizeof(__be16));
+
+ switch (endian) {
+ default:
+ *s = (wchar_t)c;
+ break;
+ case UTF16_LITTLE_ENDIAN:
+ *(__le16 *)s = __cpu_to_le16(c);
+ break;
+ case UTF16_BIG_ENDIAN:
+ *(__be16 *)s = __cpu_to_be16(c);
+ break;
+ }
+}
+
+/*
+ * _utf8s_to_utf16s
+ *
+ * Modified version of 'utf8s_to_utf16s' allows to
+ * detect -ENAMETOOLONG without writing out of expected maximum.
+ */
+static int _utf8s_to_utf16s(const u8 *s, int inlen, enum utf16_endian endian,
+ wchar_t *pwcs, int maxout)
+{
+ u16 *op;
+ int size;
+ unicode_t u;
+
+ op = pwcs;
+ while (inlen > 0 && *s) {
+ if (*s & 0x80) {
+ size = utf8_to_utf32(s, inlen, &u);
+ if (size < 0)
+ return -EINVAL;
+ s += size;
+ inlen -= size;
+
+ if (u >= PLANE_SIZE) {
+ if (maxout < 2)
+ return -ENAMETOOLONG;
+
+ u -= PLANE_SIZE;
+ put_utf16(op++,
+ SURROGATE_PAIR |
+ ((u >> 10) & SURROGATE_BITS),
+ endian);
+ put_utf16(op++,
+ SURROGATE_PAIR | SURROGATE_LOW |
+ (u & SURROGATE_BITS),
+ endian);
+ maxout -= 2;
+ } else {
+ if (maxout < 1)
+ return -ENAMETOOLONG;
+
+ put_utf16(op++, u, endian);
+ maxout--;
+ }
+ } else {
+ if (maxout < 1)
+ return -ENAMETOOLONG;
+
+ put_utf16(op++, *s++, endian);
+ inlen--;
+ maxout--;
+ }
+ }
+ return op - pwcs;
+}
+
+/*
+ * ntfs_nls_to_utf16 - Convert input string to UTF-16.
+ * @name: Input name.
+ * @name_len: Input name length.
+ * @uni: Destination memory.
+ * @max_ulen: Destination memory.
+ * @endian: Endian of target UTF-16 string.
+ *
+ * This function is called:
+ * - to create NTFS name
+ * - to create symlink
+ *
+ * Return: UTF-16 string length or error (if negative).
+ */
+int ntfs_nls_to_utf16(struct ntfs_sb_info *sbi, const u8 *name, u32 name_len,
+ struct cpu_str *uni, u32 max_ulen,
+ enum utf16_endian endian)
+{
+ int ret, slen;
+ const u8 *end;
+ struct nls_table *nls = sbi->options.nls;
+ u16 *uname = uni->name;
+
+ static_assert(sizeof(wchar_t) == sizeof(u16));
+
+ if (!nls) {
+ /* utf8 -> utf16 */
+ ret = _utf8s_to_utf16s(name, name_len, endian, uname, max_ulen);
+ uni->len = ret;
+ return ret;
+ }
+
+ for (ret = 0, end = name + name_len; name < end; ret++, name += slen) {
+ if (ret >= max_ulen)
+ return -ENAMETOOLONG;
+
+ slen = nls->char2uni(name, end - name, uname + ret);
+ if (!slen)
+ return -EINVAL;
+ if (slen < 0)
+ return slen;
+ }
+
+#ifdef __BIG_ENDIAN
+ if (endian == UTF16_LITTLE_ENDIAN) {
+ int i = ret;
+
+ while (i--) {
+ __cpu_to_le16s(uname);
+ uname++;
+ }
+ }
+#else
+ if (endian == UTF16_BIG_ENDIAN) {
+ int i = ret;
+
+ while (i--) {
+ __cpu_to_be16s(uname);
+ uname++;
+ }
+ }
+#endif
+
+ uni->len = ret;
+ return ret;
+}
+
+/*
+ * dir_search_u - Helper function.
+ */
+struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
+ struct ntfs_fnd *fnd)
+{
+ int err = 0;
+ struct super_block *sb = dir->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct ntfs_inode *ni = ntfs_i(dir);
+ struct NTFS_DE *e;
+ int diff;
+ struct inode *inode = NULL;
+ struct ntfs_fnd *fnd_a = NULL;
+
+ if (!fnd) {
+ fnd_a = fnd_get();
+ if (!fnd_a) {
+ err = -ENOMEM;
+ goto out;
+ }
+ fnd = fnd_a;
+ }
+
+ err = indx_find(&ni->dir, ni, NULL, uni, 0, sbi, &diff, &e, fnd);
+
+ if (err)
+ goto out;
+
+ if (diff) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ inode = ntfs_iget5(sb, &e->ref, uni);
+ if (!IS_ERR(inode) && is_bad_inode(inode)) {
+ iput(inode);
+ err = -EINVAL;
+ }
+out:
+ fnd_put(fnd_a);
+
+ return err == -ENOENT ? NULL : err ? ERR_PTR(err) : inode;
+}
+
+static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,
+ const struct NTFS_DE *e, u8 *name,
+ struct dir_context *ctx)
+{
+ const struct ATTR_FILE_NAME *fname;
+ unsigned long ino;
+ int name_len;
+ u32 dt_type;
+
+ fname = Add2Ptr(e, sizeof(struct NTFS_DE));
+
+ if (fname->type == FILE_NAME_DOS)
+ return 0;
+
+ if (!mi_is_ref(&ni->mi, &fname->home))
+ return 0;
+
+ ino = ino_get(&e->ref);
+
+ if (ino == MFT_REC_ROOT)
+ return 0;
+
+ /* Skip meta files. Unless option to show metafiles is set. */
+ if (!sbi->options.showmeta && ntfs_is_meta_file(sbi, ino))
+ return 0;
+
+ if (sbi->options.nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN))
+ return 0;
+
+ name_len = ntfs_utf16_to_nls(sbi, (struct le_str *)&fname->name_len,
+ name, PATH_MAX);
+ if (name_len <= 0) {
+ ntfs_warn(sbi->sb, "failed to convert name for inode %lx.",
+ ino);
+ return 0;
+ }
+
+ dt_type = (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG;
+
+ return !dir_emit(ctx, (s8 *)name, name_len, ino, dt_type);
+}
+
+/*
+ * ntfs_read_hdr - Helper function for ntfs_readdir().
+ */
+static int ntfs_read_hdr(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,
+ const struct INDEX_HDR *hdr, u64 vbo, u64 pos,
+ u8 *name, struct dir_context *ctx)
+{
+ int err;
+ const struct NTFS_DE *e;
+ u32 e_size;
+ u32 end = le32_to_cpu(hdr->used);
+ u32 off = le32_to_cpu(hdr->de_off);
+
+ for (;; off += e_size) {
+ if (off + sizeof(struct NTFS_DE) > end)
+ return -1;
+
+ e = Add2Ptr(hdr, off);
+ e_size = le16_to_cpu(e->size);
+ if (e_size < sizeof(struct NTFS_DE) || off + e_size > end)
+ return -1;
+
+ if (de_is_last(e))
+ return 0;
+
+ /* Skip already enumerated. */
+ if (vbo + off < pos)
+ continue;
+
+ if (le16_to_cpu(e->key_size) < SIZEOF_ATTRIBUTE_FILENAME)
+ return -1;
+
+ ctx->pos = vbo + off;
+
+ /* Submit the name to the filldir callback. */
+ err = ntfs_filldir(sbi, ni, e, name, ctx);
+ if (err)
+ return err;
+ }
+}
+
+/*
+ * ntfs_readdir - file_operations::iterate_shared
+ *
+ * Use non sorted enumeration.
+ * We have an example of broken volume where sorted enumeration
+ * counts each name twice.
+ */
+static int ntfs_readdir(struct file *file, struct dir_context *ctx)
+{
+ const struct INDEX_ROOT *root;
+ u64 vbo;
+ size_t bit;
+ loff_t eod;
+ int err = 0;
+ struct inode *dir = file_inode(file);
+ struct ntfs_inode *ni = ntfs_i(dir);
+ struct super_block *sb = dir->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ loff_t i_size = i_size_read(dir);
+ u32 pos = ctx->pos;
+ u8 *name = NULL;
+ struct indx_node *node = NULL;
+ u8 index_bits = ni->dir.index_bits;
+
+ /* Name is a buffer of PATH_MAX length. */
+ static_assert(NTFS_NAME_LEN * 4 < PATH_MAX);
+
+ eod = i_size + sbi->record_size;
+
+ if (pos >= eod)
+ return 0;
+
+ if (!dir_emit_dots(file, ctx))
+ return 0;
+
+ /* Allocate PATH_MAX bytes. */
+ name = __getname();
+ if (!name)
+ return -ENOMEM;
+
+ if (!ni->mi_loaded && ni->attr_list.size) {
+ /*
+ * Directory inode is locked for read.
+ * Load all subrecords to avoid 'write' access to 'ni' during
+ * directory reading.
+ */
+ ni_lock(ni);
+ if (!ni->mi_loaded && ni->attr_list.size) {
+ err = ni_load_all_mi(ni);
+ if (!err)
+ ni->mi_loaded = true;
+ }
+ ni_unlock(ni);
+ if (err)
+ goto out;
+ }
+
+ root = indx_get_root(&ni->dir, ni, NULL, NULL);
+ if (!root) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (pos >= sbi->record_size) {
+ bit = (pos - sbi->record_size) >> index_bits;
+ } else {
+ err = ntfs_read_hdr(sbi, ni, &root->ihdr, 0, pos, name, ctx);
+ if (err)
+ goto out;
+ bit = 0;
+ }
+
+ if (!i_size) {
+ ctx->pos = eod;
+ goto out;
+ }
+
+ for (;;) {
+ vbo = (u64)bit << index_bits;
+ if (vbo >= i_size) {
+ ctx->pos = eod;
+ goto out;
+ }
+
+ err = indx_used_bit(&ni->dir, ni, &bit);
+ if (err)
+ goto out;
+
+ if (bit == MINUS_ONE_T) {
+ ctx->pos = eod;
+ goto out;
+ }
+
+ vbo = (u64)bit << index_bits;
+ if (vbo >= i_size) {
+ ntfs_inode_err(dir, "Looks like your dir is corrupt");
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
+ &node);
+ if (err)
+ goto out;
+
+ err = ntfs_read_hdr(sbi, ni, &node->index->ihdr,
+ vbo + sbi->record_size, pos, name, ctx);
+ if (err)
+ goto out;
+
+ bit += 1;
+ }
+
+out:
+
+ __putname(name);
+ put_indx_node(node);
+
+ if (err == -ENOENT) {
+ err = 0;
+ ctx->pos = pos;
+ }
+
+ return err;
+}
+
+static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs,
+ size_t *files)
+{
+ int err = 0;
+ struct ntfs_inode *ni = ntfs_i(dir);
+ struct NTFS_DE *e = NULL;
+ struct INDEX_ROOT *root;
+ struct INDEX_HDR *hdr;
+ const struct ATTR_FILE_NAME *fname;
+ u32 e_size, off, end;
+ u64 vbo = 0;
+ size_t drs = 0, fles = 0, bit = 0;
+ loff_t i_size = ni->vfs_inode.i_size;
+ struct indx_node *node = NULL;
+ u8 index_bits = ni->dir.index_bits;
+
+ if (is_empty)
+ *is_empty = true;
+
+ root = indx_get_root(&ni->dir, ni, NULL, NULL);
+ if (!root)
+ return -EINVAL;
+
+ hdr = &root->ihdr;
+
+ for (;;) {
+ end = le32_to_cpu(hdr->used);
+ off = le32_to_cpu(hdr->de_off);
+
+ for (; off + sizeof(struct NTFS_DE) <= end; off += e_size) {
+ e = Add2Ptr(hdr, off);
+ e_size = le16_to_cpu(e->size);
+ if (e_size < sizeof(struct NTFS_DE) ||
+ off + e_size > end)
+ break;
+
+ if (de_is_last(e))
+ break;
+
+ fname = de_get_fname(e);
+ if (!fname)
+ continue;
+
+ if (fname->type == FILE_NAME_DOS)
+ continue;
+
+ if (is_empty) {
+ *is_empty = false;
+ if (!dirs && !files)
+ goto out;
+ }
+
+ if (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY)
+ drs += 1;
+ else
+ fles += 1;
+ }
+
+ if (vbo >= i_size)
+ goto out;
+
+ err = indx_used_bit(&ni->dir, ni, &bit);
+ if (err)
+ goto out;
+
+ if (bit == MINUS_ONE_T)
+ goto out;
+
+ vbo = (u64)bit << index_bits;
+ if (vbo >= i_size)
+ goto out;
+
+ err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
+ &node);
+ if (err)
+ goto out;
+
+ hdr = &node->index->ihdr;
+ bit += 1;
+ vbo = (u64)bit << ni->dir.idx2vbn_bits;
+ }
+
+out:
+ put_indx_node(node);
+ if (dirs)
+ *dirs = drs;
+ if (files)
+ *files = fles;
+
+ return err;
+}
+
+bool dir_is_empty(struct inode *dir)
+{
+ bool is_empty = false;
+
+ ntfs_dir_count(dir, &is_empty, NULL, NULL);
+
+ return is_empty;
+}
+
+// clang-format off
+const struct file_operations ntfs_dir_operations = {
+ .llseek = generic_file_llseek,
+ .read = generic_read_dir,
+ .iterate_shared = ntfs_readdir,
+ .fsync = generic_file_fsync,
+ .open = ntfs_file_open,
+};
+// clang-format on
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
new file mode 100644
index 000000000000..424450e77ad5
--- /dev/null
+++ b/fs/ntfs3/file.c
@@ -0,0 +1,1251 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ * Regular file handling primitives for NTFS-based filesystems.
+ *
+ */
+
+#include <linux/backing-dev.h>
+#include <linux/buffer_head.h>
+#include <linux/compat.h>
+#include <linux/falloc.h>
+#include <linux/fiemap.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+static int ntfs_ioctl_fitrim(struct ntfs_sb_info *sbi, unsigned long arg)
+{
+ struct fstrim_range __user *user_range;
+ struct fstrim_range range;
+ struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev);
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (!blk_queue_discard(q))
+ return -EOPNOTSUPP;
+
+ user_range = (struct fstrim_range __user *)arg;
+ if (copy_from_user(&range, user_range, sizeof(range)))
+ return -EFAULT;
+
+ range.minlen = max_t(u32, range.minlen, q->limits.discard_granularity);
+
+ err = ntfs_trim_fs(sbi, &range);
+ if (err < 0)
+ return err;
+
+ if (copy_to_user(user_range, &range, sizeof(range)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg)
+{
+ struct inode *inode = file_inode(filp);
+ struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
+
+ switch (cmd) {
+ case FITRIM:
+ return ntfs_ioctl_fitrim(sbi, arg);
+ }
+ return -ENOTTY; /* Inappropriate ioctl for device. */
+}
+
+#ifdef CONFIG_COMPAT
+static long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg)
+
+{
+ return ntfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+/*
+ * ntfs_getattr - inode_operations::getattr
+ */
+int ntfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
+ struct kstat *stat, u32 request_mask, u32 flags)
+{
+ struct inode *inode = d_inode(path->dentry);
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ if (is_compressed(ni))
+ stat->attributes |= STATX_ATTR_COMPRESSED;
+
+ if (is_encrypted(ni))
+ stat->attributes |= STATX_ATTR_ENCRYPTED;
+
+ stat->attributes_mask |= STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED;
+
+ generic_fillattr(mnt_userns, inode, stat);
+
+ stat->result_mask |= STATX_BTIME;
+ stat->btime = ni->i_crtime;
+ stat->blksize = ni->mi.sbi->cluster_size; /* 512, 1K, ..., 2M */
+
+ return 0;
+}
+
+static int ntfs_extend_initialized_size(struct file *file,
+ struct ntfs_inode *ni,
+ const loff_t valid,
+ const loff_t new_valid)
+{
+ struct inode *inode = &ni->vfs_inode;
+ struct address_space *mapping = inode->i_mapping;
+ struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
+ loff_t pos = valid;
+ int err;
+
+ if (is_resident(ni)) {
+ ni->i_valid = new_valid;
+ return 0;
+ }
+
+ WARN_ON(is_compressed(ni));
+ WARN_ON(valid >= new_valid);
+
+ for (;;) {
+ u32 zerofrom, len;
+ struct page *page;
+ void *fsdata;
+ u8 bits;
+ CLST vcn, lcn, clen;
+
+ if (is_sparsed(ni)) {
+ bits = sbi->cluster_bits;
+ vcn = pos >> bits;
+
+ err = attr_data_get_block(ni, vcn, 0, &lcn, &clen,
+ NULL);
+ if (err)
+ goto out;
+
+ if (lcn == SPARSE_LCN) {
+ loff_t vbo = (loff_t)vcn << bits;
+ loff_t to = vbo + ((loff_t)clen << bits);
+
+ if (to <= new_valid) {
+ ni->i_valid = to;
+ pos = to;
+ goto next;
+ }
+
+ if (vbo < pos) {
+ pos = vbo;
+ } else {
+ to = (new_valid >> bits) << bits;
+ if (pos < to) {
+ ni->i_valid = to;
+ pos = to;
+ goto next;
+ }
+ }
+ }
+ }
+
+ zerofrom = pos & (PAGE_SIZE - 1);
+ len = PAGE_SIZE - zerofrom;
+
+ if (pos + len > new_valid)
+ len = new_valid - pos;
+
+ err = pagecache_write_begin(file, mapping, pos, len, 0, &page,
+ &fsdata);
+ if (err)
+ goto out;
+
+ zero_user_segment(page, zerofrom, PAGE_SIZE);
+
+ /* This function in any case puts page. */
+ err = pagecache_write_end(file, mapping, pos, len, len, page,
+ fsdata);
+ if (err < 0)
+ goto out;
+ pos += len;
+
+next:
+ if (pos >= new_valid)
+ break;
+
+ balance_dirty_pages_ratelimited(mapping);
+ cond_resched();
+ }
+
+ return 0;
+
+out:
+ ni->i_valid = valid;
+ ntfs_inode_warn(inode, "failed to extend initialized size to %llx.",
+ new_valid);
+ return err;
+}
+
+/*
+ * ntfs_zero_range - Helper function for punch_hole.
+ *
+ * It zeroes a range [vbo, vbo_to).
+ */
+static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
+{
+ int err = 0;
+ struct address_space *mapping = inode->i_mapping;
+ u32 blocksize = 1 << inode->i_blkbits;
+ pgoff_t idx = vbo >> PAGE_SHIFT;
+ u32 z_start = vbo & (PAGE_SIZE - 1);
+ pgoff_t idx_end = (vbo_to + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ loff_t page_off;
+ struct buffer_head *head, *bh;
+ u32 bh_next, bh_off, z_end;
+ sector_t iblock;
+ struct page *page;
+
+ for (; idx < idx_end; idx += 1, z_start = 0) {
+ page_off = (loff_t)idx << PAGE_SHIFT;
+ z_end = (page_off + PAGE_SIZE) > vbo_to ? (vbo_to - page_off)
+ : PAGE_SIZE;
+ iblock = page_off >> inode->i_blkbits;
+
+ page = find_or_create_page(mapping, idx,
+ mapping_gfp_constraint(mapping,
+ ~__GFP_FS));
+ if (!page)
+ return -ENOMEM;
+
+ if (!page_has_buffers(page))
+ create_empty_buffers(page, blocksize, 0);
+
+ bh = head = page_buffers(page);
+ bh_off = 0;
+ do {
+ bh_next = bh_off + blocksize;
+
+ if (bh_next <= z_start || bh_off >= z_end)
+ continue;
+
+ if (!buffer_mapped(bh)) {
+ ntfs_get_block(inode, iblock, bh, 0);
+ /* Unmapped? It's a hole - nothing to do. */
+ if (!buffer_mapped(bh))
+ continue;
+ }
+
+ /* Ok, it's mapped. Make sure it's up-to-date. */
+ if (PageUptodate(page))
+ set_buffer_uptodate(bh);
+
+ if (!buffer_uptodate(bh)) {
+ lock_buffer(bh);
+ bh->b_end_io = end_buffer_read_sync;
+ get_bh(bh);
+ submit_bh(REQ_OP_READ, 0, bh);
+
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ unlock_page(page);
+ put_page(page);
+ err = -EIO;
+ goto out;
+ }
+ }
+
+ mark_buffer_dirty(bh);
+
+ } while (bh_off = bh_next, iblock += 1,
+ head != (bh = bh->b_this_page));
+
+ zero_user_segment(page, z_start, z_end);
+
+ unlock_page(page);
+ put_page(page);
+ cond_resched();
+ }
+out:
+ mark_inode_dirty(inode);
+ return err;
+}
+
+/*
+ * ntfs_sparse_cluster - Helper function to zero a new allocated clusters.
+ *
+ * NOTE: 512 <= cluster size <= 2M
+ */
+void ntfs_sparse_cluster(struct inode *inode, struct page *page0, CLST vcn,
+ CLST len)
+{
+ struct address_space *mapping = inode->i_mapping;
+ struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
+ u64 vbo = (u64)vcn << sbi->cluster_bits;
+ u64 bytes = (u64)len << sbi->cluster_bits;
+ u32 blocksize = 1 << inode->i_blkbits;
+ pgoff_t idx0 = page0 ? page0->index : -1;
+ loff_t vbo_clst = vbo & sbi->cluster_mask_inv;
+ loff_t end = ntfs_up_cluster(sbi, vbo + bytes);
+ pgoff_t idx = vbo_clst >> PAGE_SHIFT;
+ u32 from = vbo_clst & (PAGE_SIZE - 1);
+ pgoff_t idx_end = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ loff_t page_off;
+ u32 to;
+ bool partial;
+ struct page *page;
+
+ for (; idx < idx_end; idx += 1, from = 0) {
+ page = idx == idx0 ? page0 : grab_cache_page(mapping, idx);
+
+ if (!page)
+ continue;
+
+ page_off = (loff_t)idx << PAGE_SHIFT;
+ to = (page_off + PAGE_SIZE) > end ? (end - page_off)
+ : PAGE_SIZE;
+ partial = false;
+
+ if ((from || PAGE_SIZE != to) &&
+ likely(!page_has_buffers(page))) {
+ create_empty_buffers(page, blocksize, 0);
+ }
+
+ if (page_has_buffers(page)) {
+ struct buffer_head *head, *bh;
+ u32 bh_off = 0;
+
+ bh = head = page_buffers(page);
+ do {
+ u32 bh_next = bh_off + blocksize;
+
+ if (from <= bh_off && bh_next <= to) {
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ } else if (!buffer_uptodate(bh)) {
+ partial = true;
+ }
+ bh_off = bh_next;
+ } while (head != (bh = bh->b_this_page));
+ }
+
+ zero_user_segment(page, from, to);
+
+ if (!partial) {
+ if (!PageUptodate(page))
+ SetPageUptodate(page);
+ set_page_dirty(page);
+ }
+
+ if (idx != idx0) {
+ unlock_page(page);
+ put_page(page);
+ }
+ cond_resched();
+ }
+ mark_inode_dirty(inode);
+}
+
+/*
+ * ntfs_file_mmap - file_operations::mmap
+ */
+static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ u64 from = ((u64)vma->vm_pgoff << PAGE_SHIFT);
+ bool rw = vma->vm_flags & VM_WRITE;
+ int err;
+
+ if (is_encrypted(ni)) {
+ ntfs_inode_warn(inode, "mmap encrypted not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (is_dedup(ni)) {
+ ntfs_inode_warn(inode, "mmap deduplicated not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (is_compressed(ni) && rw) {
+ ntfs_inode_warn(inode, "mmap(write) compressed not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (rw) {
+ u64 to = min_t(loff_t, i_size_read(inode),
+ from + vma->vm_end - vma->vm_start);
+
+ if (is_sparsed(ni)) {
+ /* Allocate clusters for rw map. */
+ struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
+ CLST lcn, len;
+ CLST vcn = from >> sbi->cluster_bits;
+ CLST end = bytes_to_cluster(sbi, to);
+ bool new;
+
+ for (; vcn < end; vcn += len) {
+ err = attr_data_get_block(ni, vcn, 1, &lcn,
+ &len, &new);
+ if (err)
+ goto out;
+
+ if (!new)
+ continue;
+ ntfs_sparse_cluster(inode, NULL, vcn, 1);
+ }
+ }
+
+ if (ni->i_valid < to) {
+ if (!inode_trylock(inode)) {
+ err = -EAGAIN;
+ goto out;
+ }
+ err = ntfs_extend_initialized_size(file, ni,
+ ni->i_valid, to);
+ inode_unlock(inode);
+ if (err)
+ goto out;
+ }
+ }
+
+ err = generic_file_mmap(file, vma);
+out:
+ return err;
+}
+
+static int ntfs_extend(struct inode *inode, loff_t pos, size_t count,
+ struct file *file)
+{
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct address_space *mapping = inode->i_mapping;
+ loff_t end = pos + count;
+ bool extend_init = file && pos > ni->i_valid;
+ int err;
+
+ if (end <= inode->i_size && !extend_init)
+ return 0;
+
+ /* Mark rw ntfs as dirty. It will be cleared at umount. */
+ ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_DIRTY);
+
+ if (end > inode->i_size) {
+ err = ntfs_set_size(inode, end);
+ if (err)
+ goto out;
+ inode->i_size = end;
+ }
+
+ if (extend_init && !is_compressed(ni)) {
+ err = ntfs_extend_initialized_size(file, ni, ni->i_valid, pos);
+ if (err)
+ goto out;
+ } else {
+ err = 0;
+ }
+
+ inode->i_ctime = inode->i_mtime = current_time(inode);
+ mark_inode_dirty(inode);
+
+ if (IS_SYNC(inode)) {
+ int err2;
+
+ err = filemap_fdatawrite_range(mapping, pos, end - 1);
+ err2 = sync_mapping_buffers(mapping);
+ if (!err)
+ err = err2;
+ err2 = write_inode_now(inode, 1);
+ if (!err)
+ err = err2;
+ if (!err)
+ err = filemap_fdatawait_range(mapping, pos, end - 1);
+ }
+
+out:
+ return err;
+}
+
+static int ntfs_truncate(struct inode *inode, loff_t new_size)
+{
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ int err, dirty = 0;
+ u64 new_valid;
+
+ if (!S_ISREG(inode->i_mode))
+ return 0;
+
+ if (is_compressed(ni)) {
+ if (ni->i_valid > new_size)
+ ni->i_valid = new_size;
+ } else {
+ err = block_truncate_page(inode->i_mapping, new_size,
+ ntfs_get_block);
+ if (err)
+ return err;
+ }
+
+ new_valid = ntfs_up_block(sb, min_t(u64, ni->i_valid, new_size));
+
+ ni_lock(ni);
+
+ truncate_setsize(inode, new_size);
+
+ down_write(&ni->file.run_lock);
+ err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size,
+ &new_valid, true, NULL);
+ up_write(&ni->file.run_lock);
+
+ if (new_valid < ni->i_valid)
+ ni->i_valid = new_valid;
+
+ ni_unlock(ni);
+
+ ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE;
+ inode->i_ctime = inode->i_mtime = current_time(inode);
+ if (!IS_DIRSYNC(inode)) {
+ dirty = 1;
+ } else {
+ err = ntfs_sync_inode(inode);
+ if (err)
+ return err;
+ }
+
+ if (dirty)
+ mark_inode_dirty(inode);
+
+ /*ntfs_flush_inodes(inode->i_sb, inode, NULL);*/
+
+ return 0;
+}
+
+/*
+ * ntfs_fallocate
+ *
+ * Preallocate space for a file. This implements ntfs's fallocate file
+ * operation, which gets called from sys_fallocate system call. User
+ * space requests 'len' bytes at 'vbo'. If FALLOC_FL_KEEP_SIZE is set
+ * we just allocate clusters without zeroing them out. Otherwise we
+ * allocate and zero out clusters via an expanding truncate.
+ */
+static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
+{
+ struct inode *inode = file->f_mapping->host;
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ loff_t end = vbo + len;
+ loff_t vbo_down = round_down(vbo, PAGE_SIZE);
+ loff_t i_size;
+ int err;
+
+ /* No support for dir. */
+ if (!S_ISREG(inode->i_mode))
+ return -EOPNOTSUPP;
+
+ /* Return error if mode is not supported. */
+ if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_COLLAPSE_RANGE)) {
+ ntfs_inode_warn(inode, "fallocate(0x%x) is not supported",
+ mode);
+ return -EOPNOTSUPP;
+ }
+
+ ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
+
+ inode_lock(inode);
+ i_size = inode->i_size;
+
+ if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) {
+ /* Should never be here, see ntfs_file_open. */
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (mode & FALLOC_FL_PUNCH_HOLE) {
+ u32 frame_size;
+ loff_t mask, vbo_a, end_a, tmp;
+
+ if (!(mode & FALLOC_FL_KEEP_SIZE)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = filemap_write_and_wait_range(inode->i_mapping, vbo,
+ end - 1);
+ if (err)
+ goto out;
+
+ err = filemap_write_and_wait_range(inode->i_mapping, end,
+ LLONG_MAX);
+ if (err)
+ goto out;
+
+ inode_dio_wait(inode);
+
+ truncate_pagecache(inode, vbo_down);
+
+ if (!is_sparsed(ni) && !is_compressed(ni)) {
+ /* Normal file. */
+ err = ntfs_zero_range(inode, vbo, end);
+ goto out;
+ }
+
+ ni_lock(ni);
+ err = attr_punch_hole(ni, vbo, len, &frame_size);
+ ni_unlock(ni);
+ if (err != E_NTFS_NOTALIGNED)
+ goto out;
+
+ /* Process not aligned punch. */
+ mask = frame_size - 1;
+ vbo_a = (vbo + mask) & ~mask;
+ end_a = end & ~mask;
+
+ tmp = min(vbo_a, end);
+ if (tmp > vbo) {
+ err = ntfs_zero_range(inode, vbo, tmp);
+ if (err)
+ goto out;
+ }
+
+ if (vbo < end_a && end_a < end) {
+ err = ntfs_zero_range(inode, end_a, end);
+ if (err)
+ goto out;
+ }
+
+ /* Aligned punch_hole */
+ if (end_a > vbo_a) {
+ ni_lock(ni);
+ err = attr_punch_hole(ni, vbo_a, end_a - vbo_a, NULL);
+ ni_unlock(ni);
+ }
+ } else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
+ if (mode & ~FALLOC_FL_COLLAPSE_RANGE) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Write tail of the last page before removed range since
+ * it will get removed from the page cache below.
+ */
+ err = filemap_write_and_wait_range(inode->i_mapping, vbo_down,
+ vbo);
+ if (err)
+ goto out;
+
+ /*
+ * Write data that will be shifted to preserve them
+ * when discarding page cache below.
+ */
+ err = filemap_write_and_wait_range(inode->i_mapping, end,
+ LLONG_MAX);
+ if (err)
+ goto out;
+
+ /* Wait for existing dio to complete. */
+ inode_dio_wait(inode);
+
+ truncate_pagecache(inode, vbo_down);
+
+ ni_lock(ni);
+ err = attr_collapse_range(ni, vbo, len);
+ ni_unlock(ni);
+ } else {
+ /*
+ * Normal file: Allocate clusters, do not change 'valid' size.
+ */
+ err = ntfs_set_size(inode, max(end, i_size));
+ if (err)
+ goto out;
+
+ if (is_sparsed(ni) || is_compressed(ni)) {
+ CLST vcn_v = ni->i_valid >> sbi->cluster_bits;
+ CLST vcn = vbo >> sbi->cluster_bits;
+ CLST cend = bytes_to_cluster(sbi, end);
+ CLST lcn, clen;
+ bool new;
+
+ /*
+ * Allocate but do not zero new clusters. (see below comments)
+ * This breaks security: One can read unused on-disk areas.
+ * Zeroing these clusters may be too long.
+ * Maybe we should check here for root rights?
+ */
+ for (; vcn < cend; vcn += clen) {
+ err = attr_data_get_block(ni, vcn, cend - vcn,
+ &lcn, &clen, &new);
+ if (err)
+ goto out;
+ if (!new || vcn >= vcn_v)
+ continue;
+
+ /*
+ * Unwritten area.
+ * NTFS is not able to store several unwritten areas.
+ * Activate 'ntfs_sparse_cluster' to zero new allocated clusters.
+ *
+ * Dangerous in case:
+ * 1G of sparsed clusters + 1 cluster of data =>
+ * valid_size == 1G + 1 cluster
+ * fallocate(1G) will zero 1G and this can be very long
+ * xfstest 016/086 will fail without 'ntfs_sparse_cluster'.
+ */
+ ntfs_sparse_cluster(inode, NULL, vcn,
+ min(vcn_v - vcn, clen));
+ }
+ }
+
+ if (mode & FALLOC_FL_KEEP_SIZE) {
+ ni_lock(ni);
+ /* True - Keep preallocated. */
+ err = attr_set_size(ni, ATTR_DATA, NULL, 0,
+ &ni->file.run, i_size, &ni->i_valid,
+ true, NULL);
+ ni_unlock(ni);
+ }
+ }
+
+out:
+ if (err == -EFBIG)
+ err = -ENOSPC;
+
+ if (!err) {
+ inode->i_ctime = inode->i_mtime = current_time(inode);
+ mark_inode_dirty(inode);
+ }
+
+ inode_unlock(inode);
+ return err;
+}
+
+/*
+ * ntfs3_setattr - inode_operations::setattr
+ */
+int ntfs3_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
+ struct iattr *attr)
+{
+ struct super_block *sb = dentry->d_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct inode *inode = d_inode(dentry);
+ struct ntfs_inode *ni = ntfs_i(inode);
+ u32 ia_valid = attr->ia_valid;
+ umode_t mode = inode->i_mode;
+ int err;
+
+ if (sbi->options.no_acs_rules) {
+ /* "No access rules" - Force any changes of time etc. */
+ attr->ia_valid |= ATTR_FORCE;
+ /* and disable for editing some attributes. */
+ attr->ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE);
+ ia_valid = attr->ia_valid;
+ }
+
+ err = setattr_prepare(mnt_userns, dentry, attr);
+ if (err)
+ goto out;
+
+ if (ia_valid & ATTR_SIZE) {
+ loff_t oldsize = inode->i_size;
+
+ if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) {
+ /* Should never be here, see ntfs_file_open(). */
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+ inode_dio_wait(inode);
+
+ if (attr->ia_size < oldsize)
+ err = ntfs_truncate(inode, attr->ia_size);
+ else if (attr->ia_size > oldsize)
+ err = ntfs_extend(inode, attr->ia_size, 0, NULL);
+
+ if (err)
+ goto out;
+
+ ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
+ }
+
+ setattr_copy(mnt_userns, inode, attr);
+
+ if (mode != inode->i_mode) {
+ err = ntfs_acl_chmod(mnt_userns, inode);
+ if (err)
+ goto out;
+
+ /* Linux 'w' -> Windows 'ro'. */
+ if (0222 & inode->i_mode)
+ ni->std_fa &= ~FILE_ATTRIBUTE_READONLY;
+ else
+ ni->std_fa |= FILE_ATTRIBUTE_READONLY;
+ }
+
+ if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE))
+ ntfs_save_wsl_perm(inode);
+ mark_inode_dirty(inode);
+out:
+ return err;
+}
+
+static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ if (is_encrypted(ni)) {
+ ntfs_inode_warn(inode, "encrypted i/o not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) {
+ ntfs_inode_warn(inode, "direct i/o + compressed not supported");
+ return -EOPNOTSUPP;
+ }
+
+#ifndef CONFIG_NTFS3_LZX_XPRESS
+ if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) {
+ ntfs_inode_warn(
+ inode,
+ "activate CONFIG_NTFS3_LZX_XPRESS to read external compressed files");
+ return -EOPNOTSUPP;
+ }
+#endif
+
+ if (is_dedup(ni)) {
+ ntfs_inode_warn(inode, "read deduplicated not supported");
+ return -EOPNOTSUPP;
+ }
+
+ return generic_file_read_iter(iocb, iter);
+}
+
+/*
+ * ntfs_get_frame_pages
+ *
+ * Return: Array of locked pages.
+ */
+static int ntfs_get_frame_pages(struct address_space *mapping, pgoff_t index,
+ struct page **pages, u32 pages_per_frame,
+ bool *frame_uptodate)
+{
+ gfp_t gfp_mask = mapping_gfp_mask(mapping);
+ u32 npages;
+
+ *frame_uptodate = true;
+
+ for (npages = 0; npages < pages_per_frame; npages++, index++) {
+ struct page *page;
+
+ page = find_or_create_page(mapping, index, gfp_mask);
+ if (!page) {
+ while (npages--) {
+ page = pages[npages];
+ unlock_page(page);
+ put_page(page);
+ }
+
+ return -ENOMEM;
+ }
+
+ if (!PageUptodate(page))
+ *frame_uptodate = false;
+
+ pages[npages] = page;
+ }
+
+ return 0;
+}
+
+/*
+ * ntfs_compress_write - Helper for ntfs_file_write_iter() (compressed files).
+ */
+static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
+{
+ int err;
+ struct file *file = iocb->ki_filp;
+ size_t count = iov_iter_count(from);
+ loff_t pos = iocb->ki_pos;
+ struct inode *inode = file_inode(file);
+ loff_t i_size = inode->i_size;
+ struct address_space *mapping = inode->i_mapping;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ u64 valid = ni->i_valid;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct page *page, **pages = NULL;
+ size_t written = 0;
+ u8 frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits;
+ u32 frame_size = 1u << frame_bits;
+ u32 pages_per_frame = frame_size >> PAGE_SHIFT;
+ u32 ip, off;
+ CLST frame;
+ u64 frame_vbo;
+ pgoff_t index;
+ bool frame_uptodate;
+
+ if (frame_size < PAGE_SIZE) {
+ /*
+ * frame_size == 8K if cluster 512
+ * frame_size == 64K if cluster 4096
+ */
+ ntfs_inode_warn(inode, "page size is bigger than frame size");
+ return -EOPNOTSUPP;
+ }
+
+ pages = kmalloc_array(pages_per_frame, sizeof(struct page *), GFP_NOFS);
+ if (!pages)
+ return -ENOMEM;
+
+ current->backing_dev_info = inode_to_bdi(inode);
+ err = file_remove_privs(file);
+ if (err)
+ goto out;
+
+ err = file_update_time(file);
+ if (err)
+ goto out;
+
+ /* Zero range [valid : pos). */
+ while (valid < pos) {
+ CLST lcn, clen;
+
+ frame = valid >> frame_bits;
+ frame_vbo = valid & ~(frame_size - 1);
+ off = valid & (frame_size - 1);
+
+ err = attr_data_get_block(ni, frame << NTFS_LZNT_CUNIT, 0, &lcn,
+ &clen, NULL);
+ if (err)
+ goto out;
+
+ if (lcn == SPARSE_LCN) {
+ ni->i_valid = valid =
+ frame_vbo + ((u64)clen << sbi->cluster_bits);
+ continue;
+ }
+
+ /* Load full frame. */
+ err = ntfs_get_frame_pages(mapping, frame_vbo >> PAGE_SHIFT,
+ pages, pages_per_frame,
+ &frame_uptodate);
+ if (err)
+ goto out;
+
+ if (!frame_uptodate && off) {
+ err = ni_read_frame(ni, frame_vbo, pages,
+ pages_per_frame);
+ if (err) {
+ for (ip = 0; ip < pages_per_frame; ip++) {
+ page = pages[ip];
+ unlock_page(page);
+ put_page(page);
+ }
+ goto out;
+ }
+ }
+
+ ip = off >> PAGE_SHIFT;
+ off = offset_in_page(valid);
+ for (; ip < pages_per_frame; ip++, off = 0) {
+ page = pages[ip];
+ zero_user_segment(page, off, PAGE_SIZE);
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ }
+
+ ni_lock(ni);
+ err = ni_write_frame(ni, pages, pages_per_frame);
+ ni_unlock(ni);
+
+ for (ip = 0; ip < pages_per_frame; ip++) {
+ page = pages[ip];
+ SetPageUptodate(page);
+ unlock_page(page);
+ put_page(page);
+ }
+
+ if (err)
+ goto out;
+
+ ni->i_valid = valid = frame_vbo + frame_size;
+ }
+
+ /* Copy user data [pos : pos + count). */
+ while (count) {
+ size_t copied, bytes;
+
+ off = pos & (frame_size - 1);
+ bytes = frame_size - off;
+ if (bytes > count)
+ bytes = count;
+
+ frame = pos >> frame_bits;
+ frame_vbo = pos & ~(frame_size - 1);
+ index = frame_vbo >> PAGE_SHIFT;
+
+ if (unlikely(iov_iter_fault_in_readable(from, bytes))) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ /* Load full frame. */
+ err = ntfs_get_frame_pages(mapping, index, pages,
+ pages_per_frame, &frame_uptodate);
+ if (err)
+ goto out;
+
+ if (!frame_uptodate) {
+ loff_t to = pos + bytes;
+
+ if (off || (to < i_size && (to & (frame_size - 1)))) {
+ err = ni_read_frame(ni, frame_vbo, pages,
+ pages_per_frame);
+ if (err) {
+ for (ip = 0; ip < pages_per_frame;
+ ip++) {
+ page = pages[ip];
+ unlock_page(page);
+ put_page(page);
+ }
+ goto out;
+ }
+ }
+ }
+
+ WARN_ON(!bytes);
+ copied = 0;
+ ip = off >> PAGE_SHIFT;
+ off = offset_in_page(pos);
+
+ /* Copy user data to pages. */
+ for (;;) {
+ size_t cp, tail = PAGE_SIZE - off;
+
+ page = pages[ip];
+ cp = copy_page_from_iter_atomic(page, off,
+ min(tail, bytes), from);
+ flush_dcache_page(page);
+
+ copied += cp;
+ bytes -= cp;
+ if (!bytes || !cp)
+ break;
+
+ if (cp < tail) {
+ off += cp;
+ } else {
+ ip++;
+ off = 0;
+ }
+ }
+
+ ni_lock(ni);
+ err = ni_write_frame(ni, pages, pages_per_frame);
+ ni_unlock(ni);
+
+ for (ip = 0; ip < pages_per_frame; ip++) {
+ page = pages[ip];
+ ClearPageDirty(page);
+ SetPageUptodate(page);
+ unlock_page(page);
+ put_page(page);
+ }
+
+ if (err)
+ goto out;
+
+ /*
+ * We can loop for a long time in here. Be nice and allow
+ * us to schedule out to avoid softlocking if preempt
+ * is disabled.
+ */
+ cond_resched();
+
+ pos += copied;
+ written += copied;
+
+ count = iov_iter_count(from);
+ }
+
+out:
+ kfree(pages);
+
+ current->backing_dev_info = NULL;
+
+ if (err < 0)
+ return err;
+
+ iocb->ki_pos += written;
+ if (iocb->ki_pos > ni->i_valid)
+ ni->i_valid = iocb->ki_pos;
+
+ return written;
+}
+
+/*
+ * ntfs_file_write_iter - file_operations::write_iter
+ */
+static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ ssize_t ret;
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ if (is_encrypted(ni)) {
+ ntfs_inode_warn(inode, "encrypted i/o not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) {
+ ntfs_inode_warn(inode, "direct i/o + compressed not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (is_dedup(ni)) {
+ ntfs_inode_warn(inode, "write into deduplicated not supported");
+ return -EOPNOTSUPP;
+ }
+
+ if (!inode_trylock(inode)) {
+ if (iocb->ki_flags & IOCB_NOWAIT)
+ return -EAGAIN;
+ inode_lock(inode);
+ }
+
+ ret = generic_write_checks(iocb, from);
+ if (ret <= 0)
+ goto out;
+
+ if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) {
+ /* Should never be here, see ntfs_file_open(). */
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ ret = ntfs_extend(inode, iocb->ki_pos, ret, file);
+ if (ret)
+ goto out;
+
+ ret = is_compressed(ni) ? ntfs_compress_write(iocb, from)
+ : __generic_file_write_iter(iocb, from);
+
+out:
+ inode_unlock(inode);
+
+ if (ret > 0)
+ ret = generic_write_sync(iocb, ret);
+
+ return ret;
+}
+
+/*
+ * ntfs_file_open - file_operations::open
+ */
+int ntfs_file_open(struct inode *inode, struct file *file)
+{
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ if (unlikely((is_compressed(ni) || is_encrypted(ni)) &&
+ (file->f_flags & O_DIRECT))) {
+ return -EOPNOTSUPP;
+ }
+
+ /* Decompress "external compressed" file if opened for rw. */
+ if ((ni->ni_flags & NI_FLAG_COMPRESSED_MASK) &&
+ (file->f_flags & (O_WRONLY | O_RDWR | O_TRUNC))) {
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+ int err = ni_decompress_file(ni);
+
+ if (err)
+ return err;
+#else
+ ntfs_inode_warn(
+ inode,
+ "activate CONFIG_NTFS3_LZX_XPRESS to write external compressed files");
+ return -EOPNOTSUPP;
+#endif
+ }
+
+ return generic_file_open(inode, file);
+}
+
+/*
+ * ntfs_file_release - file_operations::release
+ */
+static int ntfs_file_release(struct inode *inode, struct file *file)
+{
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ int err = 0;
+
+ /* If we are last writer on the inode, drop the block reservation. */
+ if (sbi->options.prealloc && ((file->f_mode & FMODE_WRITE) &&
+ atomic_read(&inode->i_writecount) == 1)) {
+ ni_lock(ni);
+ down_write(&ni->file.run_lock);
+
+ err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run,
+ inode->i_size, &ni->i_valid, false, NULL);
+
+ up_write(&ni->file.run_lock);
+ ni_unlock(ni);
+ }
+ return err;
+}
+
+/*
+ * ntfs_fiemap - file_operations::fiemap
+ */
+int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ __u64 start, __u64 len)
+{
+ int err;
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ err = fiemap_prep(inode, fieinfo, start, &len, ~FIEMAP_FLAG_XATTR);
+ if (err)
+ return err;
+
+ ni_lock(ni);
+
+ err = ni_fiemap(ni, fieinfo, start, len);
+
+ ni_unlock(ni);
+
+ return err;
+}
+
+// clang-format off
+const struct inode_operations ntfs_file_inode_operations = {
+ .getattr = ntfs_getattr,
+ .setattr = ntfs3_setattr,
+ .listxattr = ntfs_listxattr,
+ .permission = ntfs_permission,
+ .get_acl = ntfs_get_acl,
+ .set_acl = ntfs_set_acl,
+ .fiemap = ntfs_fiemap,
+};
+
+const struct file_operations ntfs_file_operations = {
+ .llseek = generic_file_llseek,
+ .read_iter = ntfs_file_read_iter,
+ .write_iter = ntfs_file_write_iter,
+ .unlocked_ioctl = ntfs_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ntfs_compat_ioctl,
+#endif
+ .splice_read = generic_file_splice_read,
+ .mmap = ntfs_file_mmap,
+ .open = ntfs_file_open,
+ .fsync = generic_file_fsync,
+ .splice_write = iter_file_splice_write,
+ .fallocate = ntfs_fallocate,
+ .release = ntfs_file_release,
+};
+// clang-format on
diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
new file mode 100644
index 000000000000..938b12d56ca6
--- /dev/null
+++ b/fs/ntfs3/frecord.c
@@ -0,0 +1,3257 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fiemap.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+#include <linux/vmalloc.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+#include "lib/lib.h"
+#endif
+
+static struct mft_inode *ni_ins_mi(struct ntfs_inode *ni, struct rb_root *tree,
+ CLST ino, struct rb_node *ins)
+{
+ struct rb_node **p = &tree->rb_node;
+ struct rb_node *pr = NULL;
+
+ while (*p) {
+ struct mft_inode *mi;
+
+ pr = *p;
+ mi = rb_entry(pr, struct mft_inode, node);
+ if (mi->rno > ino)
+ p = &pr->rb_left;
+ else if (mi->rno < ino)
+ p = &pr->rb_right;
+ else
+ return mi;
+ }
+
+ if (!ins)
+ return NULL;
+
+ rb_link_node(ins, pr, p);
+ rb_insert_color(ins, tree);
+ return rb_entry(ins, struct mft_inode, node);
+}
+
+/*
+ * ni_find_mi - Find mft_inode by record number.
+ */
+static struct mft_inode *ni_find_mi(struct ntfs_inode *ni, CLST rno)
+{
+ return ni_ins_mi(ni, &ni->mi_tree, rno, NULL);
+}
+
+/*
+ * ni_add_mi - Add new mft_inode into ntfs_inode.
+ */
+static void ni_add_mi(struct ntfs_inode *ni, struct mft_inode *mi)
+{
+ ni_ins_mi(ni, &ni->mi_tree, mi->rno, &mi->node);
+}
+
+/*
+ * ni_remove_mi - Remove mft_inode from ntfs_inode.
+ */
+void ni_remove_mi(struct ntfs_inode *ni, struct mft_inode *mi)
+{
+ rb_erase(&mi->node, &ni->mi_tree);
+}
+
+/*
+ * ni_std - Return: Pointer into std_info from primary record.
+ */
+struct ATTR_STD_INFO *ni_std(struct ntfs_inode *ni)
+{
+ const struct ATTRIB *attr;
+
+ attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
+ return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO))
+ : NULL;
+}
+
+/*
+ * ni_std5
+ *
+ * Return: Pointer into std_info from primary record.
+ */
+struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni)
+{
+ const struct ATTRIB *attr;
+
+ attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
+
+ return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO5))
+ : NULL;
+}
+
+/*
+ * ni_clear - Clear resources allocated by ntfs_inode.
+ */
+void ni_clear(struct ntfs_inode *ni)
+{
+ struct rb_node *node;
+
+ if (!ni->vfs_inode.i_nlink && is_rec_inuse(ni->mi.mrec))
+ ni_delete_all(ni);
+
+ al_destroy(ni);
+
+ for (node = rb_first(&ni->mi_tree); node;) {
+ struct rb_node *next = rb_next(node);
+ struct mft_inode *mi = rb_entry(node, struct mft_inode, node);
+
+ rb_erase(node, &ni->mi_tree);
+ mi_put(mi);
+ node = next;
+ }
+
+ /* Bad inode always has mode == S_IFREG. */
+ if (ni->ni_flags & NI_FLAG_DIR)
+ indx_clear(&ni->dir);
+ else {
+ run_close(&ni->file.run);
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+ if (ni->file.offs_page) {
+ /* On-demand allocated page for offsets. */
+ put_page(ni->file.offs_page);
+ ni->file.offs_page = NULL;
+ }
+#endif
+ }
+
+ mi_clear(&ni->mi);
+}
+
+/*
+ * ni_load_mi_ex - Find mft_inode by record number.
+ */
+int ni_load_mi_ex(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi)
+{
+ int err;
+ struct mft_inode *r;
+
+ r = ni_find_mi(ni, rno);
+ if (r)
+ goto out;
+
+ err = mi_get(ni->mi.sbi, rno, &r);
+ if (err)
+ return err;
+
+ ni_add_mi(ni, r);
+
+out:
+ if (mi)
+ *mi = r;
+ return 0;
+}
+
+/*
+ * ni_load_mi - Load mft_inode corresponded list_entry.
+ */
+int ni_load_mi(struct ntfs_inode *ni, const struct ATTR_LIST_ENTRY *le,
+ struct mft_inode **mi)
+{
+ CLST rno;
+
+ if (!le) {
+ *mi = &ni->mi;
+ return 0;
+ }
+
+ rno = ino_get(&le->ref);
+ if (rno == ni->mi.rno) {
+ *mi = &ni->mi;
+ return 0;
+ }
+ return ni_load_mi_ex(ni, rno, mi);
+}
+
+/*
+ * ni_find_attr
+ *
+ * Return: Attribute and record this attribute belongs to.
+ */
+struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct ATTR_LIST_ENTRY **le_o, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, const CLST *vcn,
+ struct mft_inode **mi)
+{
+ struct ATTR_LIST_ENTRY *le;
+ struct mft_inode *m;
+
+ if (!ni->attr_list.size ||
+ (!name_len && (type == ATTR_LIST || type == ATTR_STD))) {
+ if (le_o)
+ *le_o = NULL;
+ if (mi)
+ *mi = &ni->mi;
+
+ /* Look for required attribute in primary record. */
+ return mi_find_attr(&ni->mi, attr, type, name, name_len, NULL);
+ }
+
+ /* First look for list entry of required type. */
+ le = al_find_ex(ni, le_o ? *le_o : NULL, type, name, name_len, vcn);
+ if (!le)
+ return NULL;
+
+ if (le_o)
+ *le_o = le;
+
+ /* Load record that contains this attribute. */
+ if (ni_load_mi(ni, le, &m))
+ return NULL;
+
+ /* Look for required attribute. */
+ attr = mi_find_attr(m, NULL, type, name, name_len, &le->id);
+
+ if (!attr)
+ goto out;
+
+ if (!attr->non_res) {
+ if (vcn && *vcn)
+ goto out;
+ } else if (!vcn) {
+ if (attr->nres.svcn)
+ goto out;
+ } else if (le64_to_cpu(attr->nres.svcn) > *vcn ||
+ *vcn > le64_to_cpu(attr->nres.evcn)) {
+ goto out;
+ }
+
+ if (mi)
+ *mi = m;
+ return attr;
+
+out:
+ ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR);
+ return NULL;
+}
+
+/*
+ * ni_enum_attr_ex - Enumerates attributes in ntfs_inode.
+ */
+struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct ATTR_LIST_ENTRY **le,
+ struct mft_inode **mi)
+{
+ struct mft_inode *mi2;
+ struct ATTR_LIST_ENTRY *le2;
+
+ /* Do we have an attribute list? */
+ if (!ni->attr_list.size) {
+ *le = NULL;
+ if (mi)
+ *mi = &ni->mi;
+ /* Enum attributes in primary record. */
+ return mi_enum_attr(&ni->mi, attr);
+ }
+
+ /* Get next list entry. */
+ le2 = *le = al_enumerate(ni, attr ? *le : NULL);
+ if (!le2)
+ return NULL;
+
+ /* Load record that contains the required attribute. */
+ if (ni_load_mi(ni, le2, &mi2))
+ return NULL;
+
+ if (mi)
+ *mi = mi2;
+
+ /* Find attribute in loaded record. */
+ return rec_find_attr_le(mi2, le2);
+}
+
+/*
+ * ni_load_attr - Load attribute that contains given VCN.
+ */
+struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, CLST vcn,
+ struct mft_inode **pmi)
+{
+ struct ATTR_LIST_ENTRY *le;
+ struct ATTRIB *attr;
+ struct mft_inode *mi;
+ struct ATTR_LIST_ENTRY *next;
+
+ if (!ni->attr_list.size) {
+ if (pmi)
+ *pmi = &ni->mi;
+ return mi_find_attr(&ni->mi, NULL, type, name, name_len, NULL);
+ }
+
+ le = al_find_ex(ni, NULL, type, name, name_len, NULL);
+ if (!le)
+ return NULL;
+
+ /*
+ * Unfortunately ATTR_LIST_ENTRY contains only start VCN.
+ * So to find the ATTRIB segment that contains 'vcn' we should
+ * enumerate some entries.
+ */
+ if (vcn) {
+ for (;; le = next) {
+ next = al_find_ex(ni, le, type, name, name_len, NULL);
+ if (!next || le64_to_cpu(next->vcn) > vcn)
+ break;
+ }
+ }
+
+ if (ni_load_mi(ni, le, &mi))
+ return NULL;
+
+ if (pmi)
+ *pmi = mi;
+
+ attr = mi_find_attr(mi, NULL, type, name, name_len, &le->id);
+ if (!attr)
+ return NULL;
+
+ if (!attr->non_res)
+ return attr;
+
+ if (le64_to_cpu(attr->nres.svcn) <= vcn &&
+ vcn <= le64_to_cpu(attr->nres.evcn))
+ return attr;
+
+ return NULL;
+}
+
+/*
+ * ni_load_all_mi - Load all subrecords.
+ */
+int ni_load_all_mi(struct ntfs_inode *ni)
+{
+ int err;
+ struct ATTR_LIST_ENTRY *le;
+
+ if (!ni->attr_list.size)
+ return 0;
+
+ le = NULL;
+
+ while ((le = al_enumerate(ni, le))) {
+ CLST rno = ino_get(&le->ref);
+
+ if (rno == ni->mi.rno)
+ continue;
+
+ err = ni_load_mi_ex(ni, rno, NULL);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * ni_add_subrecord - Allocate + format + attach a new subrecord.
+ */
+bool ni_add_subrecord(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi)
+{
+ struct mft_inode *m;
+
+ m = kzalloc(sizeof(struct mft_inode), GFP_NOFS);
+ if (!m)
+ return false;
+
+ if (mi_format_new(m, ni->mi.sbi, rno, 0, ni->mi.rno == MFT_REC_MFT)) {
+ mi_put(m);
+ return false;
+ }
+
+ mi_get_ref(&ni->mi, &m->mrec->parent_ref);
+
+ ni_add_mi(ni, m);
+ *mi = m;
+ return true;
+}
+
+/*
+ * ni_remove_attr - Remove all attributes for the given type/name/id.
+ */
+int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, size_t name_len, bool base_only,
+ const __le16 *id)
+{
+ int err;
+ struct ATTRIB *attr;
+ struct ATTR_LIST_ENTRY *le;
+ struct mft_inode *mi;
+ u32 type_in;
+ int diff;
+
+ if (base_only || type == ATTR_LIST || !ni->attr_list.size) {
+ attr = mi_find_attr(&ni->mi, NULL, type, name, name_len, id);
+ if (!attr)
+ return -ENOENT;
+
+ mi_remove_attr(ni, &ni->mi, attr);
+ return 0;
+ }
+
+ type_in = le32_to_cpu(type);
+ le = NULL;
+
+ for (;;) {
+ le = al_enumerate(ni, le);
+ if (!le)
+ return 0;
+
+next_le2:
+ diff = le32_to_cpu(le->type) - type_in;
+ if (diff < 0)
+ continue;
+
+ if (diff > 0)
+ return 0;
+
+ if (le->name_len != name_len)
+ continue;
+
+ if (name_len &&
+ memcmp(le_name(le), name, name_len * sizeof(short)))
+ continue;
+
+ if (id && le->id != *id)
+ continue;
+ err = ni_load_mi(ni, le, &mi);
+ if (err)
+ return err;
+
+ al_remove_le(ni, le);
+
+ attr = mi_find_attr(mi, NULL, type, name, name_len, id);
+ if (!attr)
+ return -ENOENT;
+
+ mi_remove_attr(ni, mi, attr);
+
+ if (PtrOffset(ni->attr_list.le, le) >= ni->attr_list.size)
+ return 0;
+ goto next_le2;
+ }
+}
+
+/*
+ * ni_ins_new_attr - Insert the attribute into record.
+ *
+ * Return: Not full constructed attribute or NULL if not possible to create.
+ */
+static struct ATTRIB *
+ni_ins_new_attr(struct ntfs_inode *ni, struct mft_inode *mi,
+ struct ATTR_LIST_ENTRY *le, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, u32 asize, u16 name_off,
+ CLST svcn, struct ATTR_LIST_ENTRY **ins_le)
+{
+ int err;
+ struct ATTRIB *attr;
+ bool le_added = false;
+ struct MFT_REF ref;
+
+ mi_get_ref(mi, &ref);
+
+ if (type != ATTR_LIST && !le && ni->attr_list.size) {
+ err = al_add_le(ni, type, name, name_len, svcn, cpu_to_le16(-1),
+ &ref, &le);
+ if (err) {
+ /* No memory or no space. */
+ return NULL;
+ }
+ le_added = true;
+
+ /*
+ * al_add_le -> attr_set_size (list) -> ni_expand_list
+ * which moves some attributes out of primary record
+ * this means that name may point into moved memory
+ * reinit 'name' from le.
+ */
+ name = le->name;
+ }
+
+ attr = mi_insert_attr(mi, type, name, name_len, asize, name_off);
+ if (!attr) {
+ if (le_added)
+ al_remove_le(ni, le);
+ return NULL;
+ }
+
+ if (type == ATTR_LIST) {
+ /* Attr list is not in list entry array. */
+ goto out;
+ }
+
+ if (!le)
+ goto out;
+
+ /* Update ATTRIB Id and record reference. */
+ le->id = attr->id;
+ ni->attr_list.dirty = true;
+ le->ref = ref;
+
+out:
+ if (ins_le)
+ *ins_le = le;
+ return attr;
+}
+
+/*
+ * ni_repack
+ *
+ * Random write access to sparsed or compressed file may result to
+ * not optimized packed runs.
+ * Here is the place to optimize it.
+ */
+static int ni_repack(struct ntfs_inode *ni)
+{
+ int err = 0;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct mft_inode *mi, *mi_p = NULL;
+ struct ATTRIB *attr = NULL, *attr_p;
+ struct ATTR_LIST_ENTRY *le = NULL, *le_p;
+ CLST alloc = 0;
+ u8 cluster_bits = sbi->cluster_bits;
+ CLST svcn, evcn = 0, svcn_p, evcn_p, next_svcn;
+ u32 roff, rs = sbi->record_size;
+ struct runs_tree run;
+
+ run_init(&run);
+
+ while ((attr = ni_enum_attr_ex(ni, attr, &le, &mi))) {
+ if (!attr->non_res)
+ continue;
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ if (svcn != le64_to_cpu(le->vcn)) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (!svcn) {
+ alloc = le64_to_cpu(attr->nres.alloc_size) >>
+ cluster_bits;
+ mi_p = NULL;
+ } else if (svcn != evcn + 1) {
+ err = -EINVAL;
+ break;
+ }
+
+ evcn = le64_to_cpu(attr->nres.evcn);
+
+ if (svcn > evcn + 1) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (!mi_p) {
+ /* Do not try if not enogh free space. */
+ if (le32_to_cpu(mi->mrec->used) + 8 >= rs)
+ continue;
+
+ /* Do not try if last attribute segment. */
+ if (evcn + 1 == alloc)
+ continue;
+ run_close(&run);
+ }
+
+ roff = le16_to_cpu(attr->nres.run_off);
+ err = run_unpack(&run, sbi, ni->mi.rno, svcn, evcn, svcn,
+ Add2Ptr(attr, roff),
+ le32_to_cpu(attr->size) - roff);
+ if (err < 0)
+ break;
+
+ if (!mi_p) {
+ mi_p = mi;
+ attr_p = attr;
+ svcn_p = svcn;
+ evcn_p = evcn;
+ le_p = le;
+ err = 0;
+ continue;
+ }
+
+ /*
+ * Run contains data from two records: mi_p and mi
+ * Try to pack in one.
+ */
+ err = mi_pack_runs(mi_p, attr_p, &run, evcn + 1 - svcn_p);
+ if (err)
+ break;
+
+ next_svcn = le64_to_cpu(attr_p->nres.evcn) + 1;
+
+ if (next_svcn >= evcn + 1) {
+ /* We can remove this attribute segment. */
+ al_remove_le(ni, le);
+ mi_remove_attr(NULL, mi, attr);
+ le = le_p;
+ continue;
+ }
+
+ attr->nres.svcn = le->vcn = cpu_to_le64(next_svcn);
+ mi->dirty = true;
+ ni->attr_list.dirty = true;
+
+ if (evcn + 1 == alloc) {
+ err = mi_pack_runs(mi, attr, &run,
+ evcn + 1 - next_svcn);
+ if (err)
+ break;
+ mi_p = NULL;
+ } else {
+ mi_p = mi;
+ attr_p = attr;
+ svcn_p = next_svcn;
+ evcn_p = evcn;
+ le_p = le;
+ run_truncate_head(&run, next_svcn);
+ }
+ }
+
+ if (err) {
+ ntfs_inode_warn(&ni->vfs_inode, "repack problem");
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+
+ /* Pack loaded but not packed runs. */
+ if (mi_p)
+ mi_pack_runs(mi_p, attr_p, &run, evcn_p + 1 - svcn_p);
+ }
+
+ run_close(&run);
+ return err;
+}
+
+/*
+ * ni_try_remove_attr_list
+ *
+ * Can we remove attribute list?
+ * Check the case when primary record contains enough space for all attributes.
+ */
+static int ni_try_remove_attr_list(struct ntfs_inode *ni)
+{
+ int err = 0;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct ATTRIB *attr, *attr_list, *attr_ins;
+ struct ATTR_LIST_ENTRY *le;
+ struct mft_inode *mi;
+ u32 asize, free;
+ struct MFT_REF ref;
+ __le16 id;
+
+ if (!ni->attr_list.dirty)
+ return 0;
+
+ err = ni_repack(ni);
+ if (err)
+ return err;
+
+ attr_list = mi_find_attr(&ni->mi, NULL, ATTR_LIST, NULL, 0, NULL);
+ if (!attr_list)
+ return 0;
+
+ asize = le32_to_cpu(attr_list->size);
+
+ /* Free space in primary record without attribute list. */
+ free = sbi->record_size - le32_to_cpu(ni->mi.mrec->used) + asize;
+ mi_get_ref(&ni->mi, &ref);
+
+ le = NULL;
+ while ((le = al_enumerate(ni, le))) {
+ if (!memcmp(&le->ref, &ref, sizeof(ref)))
+ continue;
+
+ if (le->vcn)
+ return 0;
+
+ mi = ni_find_mi(ni, ino_get(&le->ref));
+ if (!mi)
+ return 0;
+
+ attr = mi_find_attr(mi, NULL, le->type, le_name(le),
+ le->name_len, &le->id);
+ if (!attr)
+ return 0;
+
+ asize = le32_to_cpu(attr->size);
+ if (asize > free)
+ return 0;
+
+ free -= asize;
+ }
+
+ /* It seems that attribute list can be removed from primary record. */
+ mi_remove_attr(NULL, &ni->mi, attr_list);
+
+ /*
+ * Repeat the cycle above and move all attributes to primary record.
+ * It should be success!
+ */
+ le = NULL;
+ while ((le = al_enumerate(ni, le))) {
+ if (!memcmp(&le->ref, &ref, sizeof(ref)))
+ continue;
+
+ mi = ni_find_mi(ni, ino_get(&le->ref));
+
+ attr = mi_find_attr(mi, NULL, le->type, le_name(le),
+ le->name_len, &le->id);
+ asize = le32_to_cpu(attr->size);
+
+ /* Insert into primary record. */
+ attr_ins = mi_insert_attr(&ni->mi, le->type, le_name(le),
+ le->name_len, asize,
+ le16_to_cpu(attr->name_off));
+ id = attr_ins->id;
+
+ /* Copy all except id. */
+ memcpy(attr_ins, attr, asize);
+ attr_ins->id = id;
+
+ /* Remove from original record. */
+ mi_remove_attr(NULL, mi, attr);
+ }
+
+ run_deallocate(sbi, &ni->attr_list.run, true);
+ run_close(&ni->attr_list.run);
+ ni->attr_list.size = 0;
+ kfree(ni->attr_list.le);
+ ni->attr_list.le = NULL;
+ ni->attr_list.dirty = false;
+
+ return 0;
+}
+
+/*
+ * ni_create_attr_list - Generates an attribute list for this primary record.
+ */
+int ni_create_attr_list(struct ntfs_inode *ni)
+{
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ int err;
+ u32 lsize;
+ struct ATTRIB *attr;
+ struct ATTRIB *arr_move[7];
+ struct ATTR_LIST_ENTRY *le, *le_b[7];
+ struct MFT_REC *rec;
+ bool is_mft;
+ CLST rno = 0;
+ struct mft_inode *mi;
+ u32 free_b, nb, to_free, rs;
+ u16 sz;
+
+ is_mft = ni->mi.rno == MFT_REC_MFT;
+ rec = ni->mi.mrec;
+ rs = sbi->record_size;
+
+ /*
+ * Skip estimating exact memory requirement.
+ * Looks like one record_size is always enough.
+ */
+ le = kmalloc(al_aligned(rs), GFP_NOFS);
+ if (!le) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ mi_get_ref(&ni->mi, &le->ref);
+ ni->attr_list.le = le;
+
+ attr = NULL;
+ nb = 0;
+ free_b = 0;
+ attr = NULL;
+
+ for (; (attr = mi_enum_attr(&ni->mi, attr)); le = Add2Ptr(le, sz)) {
+ sz = le_size(attr->name_len);
+ le->type = attr->type;
+ le->size = cpu_to_le16(sz);
+ le->name_len = attr->name_len;
+ le->name_off = offsetof(struct ATTR_LIST_ENTRY, name);
+ le->vcn = 0;
+ if (le != ni->attr_list.le)
+ le->ref = ni->attr_list.le->ref;
+ le->id = attr->id;
+
+ if (attr->name_len)
+ memcpy(le->name, attr_name(attr),
+ sizeof(short) * attr->name_len);
+ else if (attr->type == ATTR_STD)
+ continue;
+ else if (attr->type == ATTR_LIST)
+ continue;
+ else if (is_mft && attr->type == ATTR_DATA)
+ continue;
+
+ if (!nb || nb < ARRAY_SIZE(arr_move)) {
+ le_b[nb] = le;
+ arr_move[nb++] = attr;
+ free_b += le32_to_cpu(attr->size);
+ }
+ }
+
+ lsize = PtrOffset(ni->attr_list.le, le);
+ ni->attr_list.size = lsize;
+
+ to_free = le32_to_cpu(rec->used) + lsize + SIZEOF_RESIDENT;
+ if (to_free <= rs) {
+ to_free = 0;
+ } else {
+ to_free -= rs;
+
+ if (to_free > free_b) {
+ err = -EINVAL;
+ goto out1;
+ }
+ }
+
+ /* Allocate child MFT. */
+ err = ntfs_look_free_mft(sbi, &rno, is_mft, ni, &mi);
+ if (err)
+ goto out1;
+
+ /* Call mi_remove_attr() in reverse order to keep pointers 'arr_move' valid. */
+ while (to_free > 0) {
+ struct ATTRIB *b = arr_move[--nb];
+ u32 asize = le32_to_cpu(b->size);
+ u16 name_off = le16_to_cpu(b->name_off);
+
+ attr = mi_insert_attr(mi, b->type, Add2Ptr(b, name_off),
+ b->name_len, asize, name_off);
+ WARN_ON(!attr);
+
+ mi_get_ref(mi, &le_b[nb]->ref);
+ le_b[nb]->id = attr->id;
+
+ /* Copy all except id. */
+ memcpy(attr, b, asize);
+ attr->id = le_b[nb]->id;
+
+ /* Remove from primary record. */
+ WARN_ON(!mi_remove_attr(NULL, &ni->mi, b));
+
+ if (to_free <= asize)
+ break;
+ to_free -= asize;
+ WARN_ON(!nb);
+ }
+
+ attr = mi_insert_attr(&ni->mi, ATTR_LIST, NULL, 0,
+ lsize + SIZEOF_RESIDENT, SIZEOF_RESIDENT);
+ WARN_ON(!attr);
+
+ attr->non_res = 0;
+ attr->flags = 0;
+ attr->res.data_size = cpu_to_le32(lsize);
+ attr->res.data_off = SIZEOF_RESIDENT_LE;
+ attr->res.flags = 0;
+ attr->res.res = 0;
+
+ memcpy(resident_data_ex(attr, lsize), ni->attr_list.le, lsize);
+
+ ni->attr_list.dirty = false;
+
+ mark_inode_dirty(&ni->vfs_inode);
+ goto out;
+
+out1:
+ kfree(ni->attr_list.le);
+ ni->attr_list.le = NULL;
+ ni->attr_list.size = 0;
+
+out:
+ return err;
+}
+
+/*
+ * ni_ins_attr_ext - Add an external attribute to the ntfs_inode.
+ */
+static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
+ enum ATTR_TYPE type, const __le16 *name, u8 name_len,
+ u32 asize, CLST svcn, u16 name_off, bool force_ext,
+ struct ATTRIB **ins_attr, struct mft_inode **ins_mi,
+ struct ATTR_LIST_ENTRY **ins_le)
+{
+ struct ATTRIB *attr;
+ struct mft_inode *mi;
+ CLST rno;
+ u64 vbo;
+ struct rb_node *node;
+ int err;
+ bool is_mft, is_mft_data;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+
+ is_mft = ni->mi.rno == MFT_REC_MFT;
+ is_mft_data = is_mft && type == ATTR_DATA && !name_len;
+
+ if (asize > sbi->max_bytes_per_attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Standard information and attr_list cannot be made external.
+ * The Log File cannot have any external attributes.
+ */
+ if (type == ATTR_STD || type == ATTR_LIST ||
+ ni->mi.rno == MFT_REC_LOG) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Create attribute list if it is not already existed. */
+ if (!ni->attr_list.size) {
+ err = ni_create_attr_list(ni);
+ if (err)
+ goto out;
+ }
+
+ vbo = is_mft_data ? ((u64)svcn << sbi->cluster_bits) : 0;
+
+ if (force_ext)
+ goto insert_ext;
+
+ /* Load all subrecords into memory. */
+ err = ni_load_all_mi(ni);
+ if (err)
+ goto out;
+
+ /* Check each of loaded subrecord. */
+ for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
+ mi = rb_entry(node, struct mft_inode, node);
+
+ if (is_mft_data &&
+ (mi_enum_attr(mi, NULL) ||
+ vbo <= ((u64)mi->rno << sbi->record_bits))) {
+ /* We can't accept this record 'cause MFT's bootstrapping. */
+ continue;
+ }
+ if (is_mft &&
+ mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0, NULL)) {
+ /*
+ * This child record already has a ATTR_DATA.
+ * So it can't accept any other records.
+ */
+ continue;
+ }
+
+ if ((type != ATTR_NAME || name_len) &&
+ mi_find_attr(mi, NULL, type, name, name_len, NULL)) {
+ /* Only indexed attributes can share same record. */
+ continue;
+ }
+
+ /* Try to insert attribute into this subrecord. */
+ attr = ni_ins_new_attr(ni, mi, le, type, name, name_len, asize,
+ name_off, svcn, ins_le);
+ if (!attr)
+ continue;
+
+ if (ins_attr)
+ *ins_attr = attr;
+ if (ins_mi)
+ *ins_mi = mi;
+ return 0;
+ }
+
+insert_ext:
+ /* We have to allocate a new child subrecord. */
+ err = ntfs_look_free_mft(sbi, &rno, is_mft_data, ni, &mi);
+ if (err)
+ goto out;
+
+ if (is_mft_data && vbo <= ((u64)rno << sbi->record_bits)) {
+ err = -EINVAL;
+ goto out1;
+ }
+
+ attr = ni_ins_new_attr(ni, mi, le, type, name, name_len, asize,
+ name_off, svcn, ins_le);
+ if (!attr)
+ goto out2;
+
+ if (ins_attr)
+ *ins_attr = attr;
+ if (ins_mi)
+ *ins_mi = mi;
+
+ return 0;
+
+out2:
+ ni_remove_mi(ni, mi);
+ mi_put(mi);
+ err = -EINVAL;
+
+out1:
+ ntfs_mark_rec_free(sbi, rno);
+
+out:
+ return err;
+}
+
+/*
+ * ni_insert_attr - Insert an attribute into the file.
+ *
+ * If the primary record has room, it will just insert the attribute.
+ * If not, it may make the attribute external.
+ * For $MFT::Data it may make room for the attribute by
+ * making other attributes external.
+ *
+ * NOTE:
+ * The ATTR_LIST and ATTR_STD cannot be made external.
+ * This function does not fill new attribute full.
+ * It only fills 'size'/'type'/'id'/'name_len' fields.
+ */
+static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, u32 asize,
+ u16 name_off, CLST svcn, struct ATTRIB **ins_attr,
+ struct mft_inode **ins_mi,
+ struct ATTR_LIST_ENTRY **ins_le)
+{
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ int err;
+ struct ATTRIB *attr, *eattr;
+ struct MFT_REC *rec;
+ bool is_mft;
+ struct ATTR_LIST_ENTRY *le;
+ u32 list_reserve, max_free, free, used, t32;
+ __le16 id;
+ u16 t16;
+
+ is_mft = ni->mi.rno == MFT_REC_MFT;
+ rec = ni->mi.mrec;
+
+ list_reserve = SIZEOF_NONRESIDENT + 3 * (1 + 2 * sizeof(u32));
+ used = le32_to_cpu(rec->used);
+ free = sbi->record_size - used;
+
+ if (is_mft && type != ATTR_LIST) {
+ /* Reserve space for the ATTRIB list. */
+ if (free < list_reserve)
+ free = 0;
+ else
+ free -= list_reserve;
+ }
+
+ if (asize <= free) {
+ attr = ni_ins_new_attr(ni, &ni->mi, NULL, type, name, name_len,
+ asize, name_off, svcn, ins_le);
+ if (attr) {
+ if (ins_attr)
+ *ins_attr = attr;
+ if (ins_mi)
+ *ins_mi = &ni->mi;
+ err = 0;
+ goto out;
+ }
+ }
+
+ if (!is_mft || type != ATTR_DATA || svcn) {
+ /* This ATTRIB will be external. */
+ err = ni_ins_attr_ext(ni, NULL, type, name, name_len, asize,
+ svcn, name_off, false, ins_attr, ins_mi,
+ ins_le);
+ goto out;
+ }
+
+ /*
+ * Here we have: "is_mft && type == ATTR_DATA && !svcn"
+ *
+ * The first chunk of the $MFT::Data ATTRIB must be the base record.
+ * Evict as many other attributes as possible.
+ */
+ max_free = free;
+
+ /* Estimate the result of moving all possible attributes away. */
+ attr = NULL;
+
+ while ((attr = mi_enum_attr(&ni->mi, attr))) {
+ if (attr->type == ATTR_STD)
+ continue;
+ if (attr->type == ATTR_LIST)
+ continue;
+ max_free += le32_to_cpu(attr->size);
+ }
+
+ if (max_free < asize + list_reserve) {
+ /* Impossible to insert this attribute into primary record. */
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Start real attribute moving. */
+ attr = NULL;
+
+ for (;;) {
+ attr = mi_enum_attr(&ni->mi, attr);
+ if (!attr) {
+ /* We should never be here 'cause we have already check this case. */
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Skip attributes that MUST be primary record. */
+ if (attr->type == ATTR_STD || attr->type == ATTR_LIST)
+ continue;
+
+ le = NULL;
+ if (ni->attr_list.size) {
+ le = al_find_le(ni, NULL, attr);
+ if (!le) {
+ /* Really this is a serious bug. */
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ t32 = le32_to_cpu(attr->size);
+ t16 = le16_to_cpu(attr->name_off);
+ err = ni_ins_attr_ext(ni, le, attr->type, Add2Ptr(attr, t16),
+ attr->name_len, t32, attr_svcn(attr), t16,
+ false, &eattr, NULL, NULL);
+ if (err)
+ return err;
+
+ id = eattr->id;
+ memcpy(eattr, attr, t32);
+ eattr->id = id;
+
+ /* Remove from primary record. */
+ mi_remove_attr(NULL, &ni->mi, attr);
+
+ /* attr now points to next attribute. */
+ if (attr->type == ATTR_END)
+ goto out;
+ }
+ while (asize + list_reserve > sbi->record_size - le32_to_cpu(rec->used))
+ ;
+
+ attr = ni_ins_new_attr(ni, &ni->mi, NULL, type, name, name_len, asize,
+ name_off, svcn, ins_le);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (ins_attr)
+ *ins_attr = attr;
+ if (ins_mi)
+ *ins_mi = &ni->mi;
+
+out:
+ return err;
+}
+
+/* ni_expand_mft_list - Split ATTR_DATA of $MFT. */
+static int ni_expand_mft_list(struct ntfs_inode *ni)
+{
+ int err = 0;
+ struct runs_tree *run = &ni->file.run;
+ u32 asize, run_size, done = 0;
+ struct ATTRIB *attr;
+ struct rb_node *node;
+ CLST mft_min, mft_new, svcn, evcn, plen;
+ struct mft_inode *mi, *mi_min, *mi_new;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+
+ /* Find the nearest MFT. */
+ mft_min = 0;
+ mft_new = 0;
+ mi_min = NULL;
+
+ for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
+ mi = rb_entry(node, struct mft_inode, node);
+
+ attr = mi_enum_attr(mi, NULL);
+
+ if (!attr) {
+ mft_min = mi->rno;
+ mi_min = mi;
+ break;
+ }
+ }
+
+ if (ntfs_look_free_mft(sbi, &mft_new, true, ni, &mi_new)) {
+ mft_new = 0;
+ /* Really this is not critical. */
+ } else if (mft_min > mft_new) {
+ mft_min = mft_new;
+ mi_min = mi_new;
+ } else {
+ ntfs_mark_rec_free(sbi, mft_new);
+ mft_new = 0;
+ ni_remove_mi(ni, mi_new);
+ }
+
+ attr = mi_find_attr(&ni->mi, NULL, ATTR_DATA, NULL, 0, NULL);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ asize = le32_to_cpu(attr->size);
+
+ evcn = le64_to_cpu(attr->nres.evcn);
+ svcn = bytes_to_cluster(sbi, (u64)(mft_min + 1) << sbi->record_bits);
+ if (evcn + 1 >= svcn) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Split primary attribute [0 evcn] in two parts [0 svcn) + [svcn evcn].
+ *
+ * Update first part of ATTR_DATA in 'primary MFT.
+ */
+ err = run_pack(run, 0, svcn, Add2Ptr(attr, SIZEOF_NONRESIDENT),
+ asize - SIZEOF_NONRESIDENT, &plen);
+ if (err < 0)
+ goto out;
+
+ run_size = ALIGN(err, 8);
+ err = 0;
+
+ if (plen < svcn) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ attr->nres.evcn = cpu_to_le64(svcn - 1);
+ attr->size = cpu_to_le32(run_size + SIZEOF_NONRESIDENT);
+ /* 'done' - How many bytes of primary MFT becomes free. */
+ done = asize - run_size - SIZEOF_NONRESIDENT;
+ le32_sub_cpu(&ni->mi.mrec->used, done);
+
+ /* Estimate the size of second part: run_buf=NULL. */
+ err = run_pack(run, svcn, evcn + 1 - svcn, NULL, sbi->record_size,
+ &plen);
+ if (err < 0)
+ goto out;
+
+ run_size = ALIGN(err, 8);
+ err = 0;
+
+ if (plen < evcn + 1 - svcn) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * This function may implicitly call expand attr_list.
+ * Insert second part of ATTR_DATA in 'mi_min'.
+ */
+ attr = ni_ins_new_attr(ni, mi_min, NULL, ATTR_DATA, NULL, 0,
+ SIZEOF_NONRESIDENT + run_size,
+ SIZEOF_NONRESIDENT, svcn, NULL);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ attr->non_res = 1;
+ attr->name_off = SIZEOF_NONRESIDENT_LE;
+ attr->flags = 0;
+
+ run_pack(run, svcn, evcn + 1 - svcn, Add2Ptr(attr, SIZEOF_NONRESIDENT),
+ run_size, &plen);
+
+ attr->nres.svcn = cpu_to_le64(svcn);
+ attr->nres.evcn = cpu_to_le64(evcn);
+ attr->nres.run_off = cpu_to_le16(SIZEOF_NONRESIDENT);
+
+out:
+ if (mft_new) {
+ ntfs_mark_rec_free(sbi, mft_new);
+ ni_remove_mi(ni, mi_new);
+ }
+
+ return !err && !done ? -EOPNOTSUPP : err;
+}
+
+/*
+ * ni_expand_list - Move all possible attributes out of primary record.
+ */
+int ni_expand_list(struct ntfs_inode *ni)
+{
+ int err = 0;
+ u32 asize, done = 0;
+ struct ATTRIB *attr, *ins_attr;
+ struct ATTR_LIST_ENTRY *le;
+ bool is_mft = ni->mi.rno == MFT_REC_MFT;
+ struct MFT_REF ref;
+
+ mi_get_ref(&ni->mi, &ref);
+ le = NULL;
+
+ while ((le = al_enumerate(ni, le))) {
+ if (le->type == ATTR_STD)
+ continue;
+
+ if (memcmp(&ref, &le->ref, sizeof(struct MFT_REF)))
+ continue;
+
+ if (is_mft && le->type == ATTR_DATA)
+ continue;
+
+ /* Find attribute in primary record. */
+ attr = rec_find_attr_le(&ni->mi, le);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ asize = le32_to_cpu(attr->size);
+
+ /* Always insert into new record to avoid collisions (deep recursive). */
+ err = ni_ins_attr_ext(ni, le, attr->type, attr_name(attr),
+ attr->name_len, asize, attr_svcn(attr),
+ le16_to_cpu(attr->name_off), true,
+ &ins_attr, NULL, NULL);
+
+ if (err)
+ goto out;
+
+ memcpy(ins_attr, attr, asize);
+ ins_attr->id = le->id;
+ /* Remove from primary record. */
+ mi_remove_attr(NULL, &ni->mi, attr);
+
+ done += asize;
+ goto out;
+ }
+
+ if (!is_mft) {
+ err = -EFBIG; /* Attr list is too big(?) */
+ goto out;
+ }
+
+ /* Split MFT data as much as possible. */
+ err = ni_expand_mft_list(ni);
+ if (err)
+ goto out;
+
+out:
+ return !err && !done ? -EOPNOTSUPP : err;
+}
+
+/*
+ * ni_insert_nonresident - Insert new nonresident attribute.
+ */
+int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len,
+ const struct runs_tree *run, CLST svcn, CLST len,
+ __le16 flags, struct ATTRIB **new_attr,
+ struct mft_inode **mi)
+{
+ int err;
+ CLST plen;
+ struct ATTRIB *attr;
+ bool is_ext =
+ (flags & (ATTR_FLAG_SPARSED | ATTR_FLAG_COMPRESSED)) && !svcn;
+ u32 name_size = ALIGN(name_len * sizeof(short), 8);
+ u32 name_off = is_ext ? SIZEOF_NONRESIDENT_EX : SIZEOF_NONRESIDENT;
+ u32 run_off = name_off + name_size;
+ u32 run_size, asize;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+
+ err = run_pack(run, svcn, len, NULL, sbi->max_bytes_per_attr - run_off,
+ &plen);
+ if (err < 0)
+ goto out;
+
+ run_size = ALIGN(err, 8);
+
+ if (plen < len) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ asize = run_off + run_size;
+
+ if (asize > sbi->max_bytes_per_attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = ni_insert_attr(ni, type, name, name_len, asize, name_off, svcn,
+ &attr, mi, NULL);
+
+ if (err)
+ goto out;
+
+ attr->non_res = 1;
+ attr->name_off = cpu_to_le16(name_off);
+ attr->flags = flags;
+
+ run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size, &plen);
+
+ attr->nres.svcn = cpu_to_le64(svcn);
+ attr->nres.evcn = cpu_to_le64((u64)svcn + len - 1);
+
+ err = 0;
+ if (new_attr)
+ *new_attr = attr;
+
+ *(__le64 *)&attr->nres.run_off = cpu_to_le64(run_off);
+
+ attr->nres.alloc_size =
+ svcn ? 0 : cpu_to_le64((u64)len << ni->mi.sbi->cluster_bits);
+ attr->nres.data_size = attr->nres.alloc_size;
+ attr->nres.valid_size = attr->nres.alloc_size;
+
+ if (is_ext) {
+ if (flags & ATTR_FLAG_COMPRESSED)
+ attr->nres.c_unit = COMPRESSION_UNIT;
+ attr->nres.total_size = attr->nres.alloc_size;
+ }
+
+out:
+ return err;
+}
+
+/*
+ * ni_insert_resident - Inserts new resident attribute.
+ */
+int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
+ enum ATTR_TYPE type, const __le16 *name, u8 name_len,
+ struct ATTRIB **new_attr, struct mft_inode **mi,
+ struct ATTR_LIST_ENTRY **le)
+{
+ int err;
+ u32 name_size = ALIGN(name_len * sizeof(short), 8);
+ u32 asize = SIZEOF_RESIDENT + name_size + ALIGN(data_size, 8);
+ struct ATTRIB *attr;
+
+ err = ni_insert_attr(ni, type, name, name_len, asize, SIZEOF_RESIDENT,
+ 0, &attr, mi, le);
+ if (err)
+ return err;
+
+ attr->non_res = 0;
+ attr->flags = 0;
+
+ attr->res.data_size = cpu_to_le32(data_size);
+ attr->res.data_off = cpu_to_le16(SIZEOF_RESIDENT + name_size);
+ if (type == ATTR_NAME) {
+ attr->res.flags = RESIDENT_FLAG_INDEXED;
+
+ /* is_attr_indexed(attr)) == true */
+ le16_add_cpu(&ni->mi.mrec->hard_links, +1);
+ ni->mi.dirty = true;
+ }
+ attr->res.res = 0;
+
+ if (new_attr)
+ *new_attr = attr;
+
+ return 0;
+}
+
+/*
+ * ni_remove_attr_le - Remove attribute from record.
+ */
+void ni_remove_attr_le(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct mft_inode *mi, struct ATTR_LIST_ENTRY *le)
+{
+ mi_remove_attr(ni, mi, attr);
+
+ if (le)
+ al_remove_le(ni, le);
+}
+
+/*
+ * ni_delete_all - Remove all attributes and frees allocates space.
+ *
+ * ntfs_evict_inode->ntfs_clear_inode->ni_delete_all (if no links).
+ */
+int ni_delete_all(struct ntfs_inode *ni)
+{
+ int err;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ struct ATTRIB *attr = NULL;
+ struct rb_node *node;
+ u16 roff;
+ u32 asize;
+ CLST svcn, evcn;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ bool nt3 = is_ntfs3(sbi);
+ struct MFT_REF ref;
+
+ while ((attr = ni_enum_attr_ex(ni, attr, &le, NULL))) {
+ if (!nt3 || attr->name_len) {
+ ;
+ } else if (attr->type == ATTR_REPARSE) {
+ mi_get_ref(&ni->mi, &ref);
+ ntfs_remove_reparse(sbi, 0, &ref);
+ } else if (attr->type == ATTR_ID && !attr->non_res &&
+ le32_to_cpu(attr->res.data_size) >=
+ sizeof(struct GUID)) {
+ ntfs_objid_remove(sbi, resident_data(attr));
+ }
+
+ if (!attr->non_res)
+ continue;
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn = le64_to_cpu(attr->nres.evcn);
+
+ if (evcn + 1 <= svcn)
+ continue;
+
+ asize = le32_to_cpu(attr->size);
+ roff = le16_to_cpu(attr->nres.run_off);
+
+ /* run==1 means unpack and deallocate. */
+ run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn,
+ Add2Ptr(attr, roff), asize - roff);
+ }
+
+ if (ni->attr_list.size) {
+ run_deallocate(ni->mi.sbi, &ni->attr_list.run, true);
+ al_destroy(ni);
+ }
+
+ /* Free all subrecords. */
+ for (node = rb_first(&ni->mi_tree); node;) {
+ struct rb_node *next = rb_next(node);
+ struct mft_inode *mi = rb_entry(node, struct mft_inode, node);
+
+ clear_rec_inuse(mi->mrec);
+ mi->dirty = true;
+ mi_write(mi, 0);
+
+ ntfs_mark_rec_free(sbi, mi->rno);
+ ni_remove_mi(ni, mi);
+ mi_put(mi);
+ node = next;
+ }
+
+ /* Free base record. */
+ clear_rec_inuse(ni->mi.mrec);
+ ni->mi.dirty = true;
+ err = mi_write(&ni->mi, 0);
+
+ ntfs_mark_rec_free(sbi, ni->mi.rno);
+
+ return err;
+}
+
+/* ni_fname_name
+ *
+ * Return: File name attribute by its value.
+ */
+struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
+ const struct cpu_str *uni,
+ const struct MFT_REF *home_dir,
+ struct mft_inode **mi,
+ struct ATTR_LIST_ENTRY **le)
+{
+ struct ATTRIB *attr = NULL;
+ struct ATTR_FILE_NAME *fname;
+
+ *le = NULL;
+
+ /* Enumerate all names. */
+next:
+ attr = ni_find_attr(ni, attr, le, ATTR_NAME, NULL, 0, NULL, mi);
+ if (!attr)
+ return NULL;
+
+ fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
+ if (!fname)
+ goto next;
+
+ if (home_dir && memcmp(home_dir, &fname->home, sizeof(*home_dir)))
+ goto next;
+
+ if (!uni)
+ goto next;
+
+ if (uni->len != fname->name_len)
+ goto next;
+
+ if (ntfs_cmp_names_cpu(uni, (struct le_str *)&fname->name_len, NULL,
+ false))
+ goto next;
+
+ return fname;
+}
+
+/*
+ * ni_fname_type
+ *
+ * Return: File name attribute with given type.
+ */
+struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type,
+ struct mft_inode **mi,
+ struct ATTR_LIST_ENTRY **le)
+{
+ struct ATTRIB *attr = NULL;
+ struct ATTR_FILE_NAME *fname;
+
+ *le = NULL;
+
+ if (FILE_NAME_POSIX == name_type)
+ return NULL;
+
+ /* Enumerate all names. */
+ for (;;) {
+ attr = ni_find_attr(ni, attr, le, ATTR_NAME, NULL, 0, NULL, mi);
+ if (!attr)
+ return NULL;
+
+ fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
+ if (fname && name_type == fname->type)
+ return fname;
+ }
+}
+
+/*
+ * ni_new_attr_flags
+ *
+ * Process compressed/sparsed in special way.
+ * NOTE: You need to set ni->std_fa = new_fa
+ * after this function to keep internal structures in consistency.
+ */
+int ni_new_attr_flags(struct ntfs_inode *ni, enum FILE_ATTRIBUTE new_fa)
+{
+ struct ATTRIB *attr;
+ struct mft_inode *mi;
+ __le16 new_aflags;
+ u32 new_asize;
+
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, &mi);
+ if (!attr)
+ return -EINVAL;
+
+ new_aflags = attr->flags;
+
+ if (new_fa & FILE_ATTRIBUTE_SPARSE_FILE)
+ new_aflags |= ATTR_FLAG_SPARSED;
+ else
+ new_aflags &= ~ATTR_FLAG_SPARSED;
+
+ if (new_fa & FILE_ATTRIBUTE_COMPRESSED)
+ new_aflags |= ATTR_FLAG_COMPRESSED;
+ else
+ new_aflags &= ~ATTR_FLAG_COMPRESSED;
+
+ if (new_aflags == attr->flags)
+ return 0;
+
+ if ((new_aflags & (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) ==
+ (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) {
+ ntfs_inode_warn(&ni->vfs_inode,
+ "file can't be sparsed and compressed");
+ return -EOPNOTSUPP;
+ }
+
+ if (!attr->non_res)
+ goto out;
+
+ if (attr->nres.data_size) {
+ ntfs_inode_warn(
+ &ni->vfs_inode,
+ "one can change sparsed/compressed only for empty files");
+ return -EOPNOTSUPP;
+ }
+
+ /* Resize nonresident empty attribute in-place only. */
+ new_asize = (new_aflags & (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED))
+ ? (SIZEOF_NONRESIDENT_EX + 8)
+ : (SIZEOF_NONRESIDENT + 8);
+
+ if (!mi_resize_attr(mi, attr, new_asize - le32_to_cpu(attr->size)))
+ return -EOPNOTSUPP;
+
+ if (new_aflags & ATTR_FLAG_SPARSED) {
+ attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
+ /* Windows uses 16 clusters per frame but supports one cluster per frame too. */
+ attr->nres.c_unit = 0;
+ ni->vfs_inode.i_mapping->a_ops = &ntfs_aops;
+ } else if (new_aflags & ATTR_FLAG_COMPRESSED) {
+ attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
+ /* The only allowed: 16 clusters per frame. */
+ attr->nres.c_unit = NTFS_LZNT_CUNIT;
+ ni->vfs_inode.i_mapping->a_ops = &ntfs_aops_cmpr;
+ } else {
+ attr->name_off = SIZEOF_NONRESIDENT_LE;
+ /* Normal files. */
+ attr->nres.c_unit = 0;
+ ni->vfs_inode.i_mapping->a_ops = &ntfs_aops;
+ }
+ attr->nres.run_off = attr->name_off;
+out:
+ attr->flags = new_aflags;
+ mi->dirty = true;
+
+ return 0;
+}
+
+/*
+ * ni_parse_reparse
+ *
+ * Buffer is at least 24 bytes.
+ */
+enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr,
+ void *buffer)
+{
+ const struct REPARSE_DATA_BUFFER *rp = NULL;
+ u8 bits;
+ u16 len;
+ typeof(rp->CompressReparseBuffer) *cmpr;
+
+ static_assert(sizeof(struct REPARSE_DATA_BUFFER) <= 24);
+
+ /* Try to estimate reparse point. */
+ if (!attr->non_res) {
+ rp = resident_data_ex(attr, sizeof(struct REPARSE_DATA_BUFFER));
+ } else if (le64_to_cpu(attr->nres.data_size) >=
+ sizeof(struct REPARSE_DATA_BUFFER)) {
+ struct runs_tree run;
+
+ run_init(&run);
+
+ if (!attr_load_runs_vcn(ni, ATTR_REPARSE, NULL, 0, &run, 0) &&
+ !ntfs_read_run_nb(ni->mi.sbi, &run, 0, buffer,
+ sizeof(struct REPARSE_DATA_BUFFER),
+ NULL)) {
+ rp = buffer;
+ }
+
+ run_close(&run);
+ }
+
+ if (!rp)
+ return REPARSE_NONE;
+
+ len = le16_to_cpu(rp->ReparseDataLength);
+ switch (rp->ReparseTag) {
+ case (IO_REPARSE_TAG_MICROSOFT | IO_REPARSE_TAG_SYMBOLIC_LINK):
+ break; /* Symbolic link. */
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ break; /* Mount points and junctions. */
+ case IO_REPARSE_TAG_SYMLINK:
+ break;
+ case IO_REPARSE_TAG_COMPRESS:
+ /*
+ * WOF - Windows Overlay Filter - Used to compress files with
+ * LZX/Xpress.
+ *
+ * Unlike native NTFS file compression, the Windows
+ * Overlay Filter supports only read operations. This means
+ * that it doesn't need to sector-align each compressed chunk,
+ * so the compressed data can be packed more tightly together.
+ * If you open the file for writing, the WOF just decompresses
+ * the entire file, turning it back into a plain file.
+ *
+ * Ntfs3 driver decompresses the entire file only on write or
+ * change size requests.
+ */
+
+ cmpr = &rp->CompressReparseBuffer;
+ if (len < sizeof(*cmpr) ||
+ cmpr->WofVersion != WOF_CURRENT_VERSION ||
+ cmpr->WofProvider != WOF_PROVIDER_SYSTEM ||
+ cmpr->ProviderVer != WOF_PROVIDER_CURRENT_VERSION) {
+ return REPARSE_NONE;
+ }
+
+ switch (cmpr->CompressionFormat) {
+ case WOF_COMPRESSION_XPRESS4K:
+ bits = 0xc; // 4k
+ break;
+ case WOF_COMPRESSION_XPRESS8K:
+ bits = 0xd; // 8k
+ break;
+ case WOF_COMPRESSION_XPRESS16K:
+ bits = 0xe; // 16k
+ break;
+ case WOF_COMPRESSION_LZX32K:
+ bits = 0xf; // 32k
+ break;
+ default:
+ bits = 0x10; // 64k
+ break;
+ }
+ ni_set_ext_compress_bits(ni, bits);
+ return REPARSE_COMPRESSED;
+
+ case IO_REPARSE_TAG_DEDUP:
+ ni->ni_flags |= NI_FLAG_DEDUPLICATED;
+ return REPARSE_DEDUPLICATED;
+
+ default:
+ if (rp->ReparseTag & IO_REPARSE_TAG_NAME_SURROGATE)
+ break;
+
+ return REPARSE_NONE;
+ }
+
+ /* Looks like normal symlink. */
+ return REPARSE_LINK;
+}
+
+/*
+ * ni_fiemap - Helper for file_fiemap().
+ *
+ * Assumed ni_lock.
+ * TODO: Less aggressive locks.
+ */
+int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
+ __u64 vbo, __u64 len)
+{
+ int err = 0;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ u8 cluster_bits = sbi->cluster_bits;
+ struct runs_tree *run;
+ struct rw_semaphore *run_lock;
+ struct ATTRIB *attr;
+ CLST vcn = vbo >> cluster_bits;
+ CLST lcn, clen;
+ u64 valid = ni->i_valid;
+ u64 lbo, bytes;
+ u64 end, alloc_size;
+ size_t idx = -1;
+ u32 flags;
+ bool ok;
+
+ if (S_ISDIR(ni->vfs_inode.i_mode)) {
+ run = &ni->dir.alloc_run;
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_ALLOC, I30_NAME,
+ ARRAY_SIZE(I30_NAME), NULL, NULL);
+ run_lock = &ni->dir.run_lock;
+ } else {
+ run = &ni->file.run;
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL,
+ NULL);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+ if (is_attr_compressed(attr)) {
+ /* Unfortunately cp -r incorrectly treats compressed clusters. */
+ err = -EOPNOTSUPP;
+ ntfs_inode_warn(
+ &ni->vfs_inode,
+ "fiemap is not supported for compressed file (cp -r)");
+ goto out;
+ }
+ run_lock = &ni->file.run_lock;
+ }
+
+ if (!attr || !attr->non_res) {
+ err = fiemap_fill_next_extent(
+ fieinfo, 0, 0,
+ attr ? le32_to_cpu(attr->res.data_size) : 0,
+ FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_LAST |
+ FIEMAP_EXTENT_MERGED);
+ goto out;
+ }
+
+ end = vbo + len;
+ alloc_size = le64_to_cpu(attr->nres.alloc_size);
+ if (end > alloc_size)
+ end = alloc_size;
+
+ down_read(run_lock);
+
+ while (vbo < end) {
+ if (idx == -1) {
+ ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx);
+ } else {
+ CLST vcn_next = vcn;
+
+ ok = run_get_entry(run, ++idx, &vcn, &lcn, &clen) &&
+ vcn == vcn_next;
+ if (!ok)
+ vcn = vcn_next;
+ }
+
+ if (!ok) {
+ up_read(run_lock);
+ down_write(run_lock);
+
+ err = attr_load_runs_vcn(ni, attr->type,
+ attr_name(attr),
+ attr->name_len, run, vcn);
+
+ up_write(run_lock);
+ down_read(run_lock);
+
+ if (err)
+ break;
+
+ ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx);
+
+ if (!ok) {
+ err = -EINVAL;
+ break;
+ }
+ }
+
+ if (!clen) {
+ err = -EINVAL; // ?
+ break;
+ }
+
+ if (lcn == SPARSE_LCN) {
+ vcn += clen;
+ vbo = (u64)vcn << cluster_bits;
+ continue;
+ }
+
+ flags = FIEMAP_EXTENT_MERGED;
+ if (S_ISDIR(ni->vfs_inode.i_mode)) {
+ ;
+ } else if (is_attr_compressed(attr)) {
+ CLST clst_data;
+
+ err = attr_is_frame_compressed(
+ ni, attr, vcn >> attr->nres.c_unit, &clst_data);
+ if (err)
+ break;
+ if (clst_data < NTFS_LZNT_CLUSTERS)
+ flags |= FIEMAP_EXTENT_ENCODED;
+ } else if (is_attr_encrypted(attr)) {
+ flags |= FIEMAP_EXTENT_DATA_ENCRYPTED;
+ }
+
+ vbo = (u64)vcn << cluster_bits;
+ bytes = (u64)clen << cluster_bits;
+ lbo = (u64)lcn << cluster_bits;
+
+ vcn += clen;
+
+ if (vbo + bytes >= end) {
+ bytes = end - vbo;
+ flags |= FIEMAP_EXTENT_LAST;
+ }
+
+ if (vbo + bytes <= valid) {
+ ;
+ } else if (vbo >= valid) {
+ flags |= FIEMAP_EXTENT_UNWRITTEN;
+ } else {
+ /* vbo < valid && valid < vbo + bytes */
+ u64 dlen = valid - vbo;
+
+ err = fiemap_fill_next_extent(fieinfo, vbo, lbo, dlen,
+ flags);
+ if (err < 0)
+ break;
+ if (err == 1) {
+ err = 0;
+ break;
+ }
+
+ vbo = valid;
+ bytes -= dlen;
+ if (!bytes)
+ continue;
+
+ lbo += dlen;
+ flags |= FIEMAP_EXTENT_UNWRITTEN;
+ }
+
+ err = fiemap_fill_next_extent(fieinfo, vbo, lbo, bytes, flags);
+ if (err < 0)
+ break;
+ if (err == 1) {
+ err = 0;
+ break;
+ }
+
+ vbo += bytes;
+ }
+
+ up_read(run_lock);
+
+out:
+ return err;
+}
+
+/*
+ * ni_readpage_cmpr
+ *
+ * When decompressing, we typically obtain more than one page per reference.
+ * We inject the additional pages into the page cache.
+ */
+int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page)
+{
+ int err;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct address_space *mapping = page->mapping;
+ pgoff_t index = page->index;
+ u64 frame_vbo, vbo = (u64)index << PAGE_SHIFT;
+ struct page **pages = NULL; /* Array of at most 16 pages. stack? */
+ u8 frame_bits;
+ CLST frame;
+ u32 i, idx, frame_size, pages_per_frame;
+ gfp_t gfp_mask;
+ struct page *pg;
+
+ if (vbo >= ni->vfs_inode.i_size) {
+ SetPageUptodate(page);
+ err = 0;
+ goto out;
+ }
+
+ if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) {
+ /* Xpress or LZX. */
+ frame_bits = ni_ext_compress_bits(ni);
+ } else {
+ /* LZNT compression. */
+ frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits;
+ }
+ frame_size = 1u << frame_bits;
+ frame = vbo >> frame_bits;
+ frame_vbo = (u64)frame << frame_bits;
+ idx = (vbo - frame_vbo) >> PAGE_SHIFT;
+
+ pages_per_frame = frame_size >> PAGE_SHIFT;
+ pages = kcalloc(pages_per_frame, sizeof(struct page *), GFP_NOFS);
+ if (!pages) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ pages[idx] = page;
+ index = frame_vbo >> PAGE_SHIFT;
+ gfp_mask = mapping_gfp_mask(mapping);
+
+ for (i = 0; i < pages_per_frame; i++, index++) {
+ if (i == idx)
+ continue;
+
+ pg = find_or_create_page(mapping, index, gfp_mask);
+ if (!pg) {
+ err = -ENOMEM;
+ goto out1;
+ }
+ pages[i] = pg;
+ }
+
+ err = ni_read_frame(ni, frame_vbo, pages, pages_per_frame);
+
+out1:
+ if (err)
+ SetPageError(page);
+
+ for (i = 0; i < pages_per_frame; i++) {
+ pg = pages[i];
+ if (i == idx)
+ continue;
+ unlock_page(pg);
+ put_page(pg);
+ }
+
+out:
+ /* At this point, err contains 0 or -EIO depending on the "critical" page. */
+ kfree(pages);
+ unlock_page(page);
+
+ return err;
+}
+
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+/*
+ * ni_decompress_file - Decompress LZX/Xpress compressed file.
+ *
+ * Remove ATTR_DATA::WofCompressedData.
+ * Remove ATTR_REPARSE.
+ */
+int ni_decompress_file(struct ntfs_inode *ni)
+{
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct inode *inode = &ni->vfs_inode;
+ loff_t i_size = inode->i_size;
+ struct address_space *mapping = inode->i_mapping;
+ gfp_t gfp_mask = mapping_gfp_mask(mapping);
+ struct page **pages = NULL;
+ struct ATTR_LIST_ENTRY *le;
+ struct ATTRIB *attr;
+ CLST vcn, cend, lcn, clen, end;
+ pgoff_t index;
+ u64 vbo;
+ u8 frame_bits;
+ u32 i, frame_size, pages_per_frame, bytes;
+ struct mft_inode *mi;
+ int err;
+
+ /* Clusters for decompressed data. */
+ cend = bytes_to_cluster(sbi, i_size);
+
+ if (!i_size)
+ goto remove_wof;
+
+ /* Check in advance. */
+ if (cend > wnd_zeroes(&sbi->used.bitmap)) {
+ err = -ENOSPC;
+ goto out;
+ }
+
+ frame_bits = ni_ext_compress_bits(ni);
+ frame_size = 1u << frame_bits;
+ pages_per_frame = frame_size >> PAGE_SHIFT;
+ pages = kcalloc(pages_per_frame, sizeof(struct page *), GFP_NOFS);
+ if (!pages) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Step 1: Decompress data and copy to new allocated clusters.
+ */
+ index = 0;
+ for (vbo = 0; vbo < i_size; vbo += bytes) {
+ u32 nr_pages;
+ bool new;
+
+ if (vbo + frame_size > i_size) {
+ bytes = i_size - vbo;
+ nr_pages = (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ } else {
+ nr_pages = pages_per_frame;
+ bytes = frame_size;
+ }
+
+ end = bytes_to_cluster(sbi, vbo + bytes);
+
+ for (vcn = vbo >> sbi->cluster_bits; vcn < end; vcn += clen) {
+ err = attr_data_get_block(ni, vcn, cend - vcn, &lcn,
+ &clen, &new);
+ if (err)
+ goto out;
+ }
+
+ for (i = 0; i < pages_per_frame; i++, index++) {
+ struct page *pg;
+
+ pg = find_or_create_page(mapping, index, gfp_mask);
+ if (!pg) {
+ while (i--) {
+ unlock_page(pages[i]);
+ put_page(pages[i]);
+ }
+ err = -ENOMEM;
+ goto out;
+ }
+ pages[i] = pg;
+ }
+
+ err = ni_read_frame(ni, vbo, pages, pages_per_frame);
+
+ if (!err) {
+ down_read(&ni->file.run_lock);
+ err = ntfs_bio_pages(sbi, &ni->file.run, pages,
+ nr_pages, vbo, bytes,
+ REQ_OP_WRITE);
+ up_read(&ni->file.run_lock);
+ }
+
+ for (i = 0; i < pages_per_frame; i++) {
+ unlock_page(pages[i]);
+ put_page(pages[i]);
+ }
+
+ if (err)
+ goto out;
+
+ cond_resched();
+ }
+
+remove_wof:
+ /*
+ * Step 2: Deallocate attributes ATTR_DATA::WofCompressedData
+ * and ATTR_REPARSE.
+ */
+ attr = NULL;
+ le = NULL;
+ while ((attr = ni_enum_attr_ex(ni, attr, &le, NULL))) {
+ CLST svcn, evcn;
+ u32 asize, roff;
+
+ if (attr->type == ATTR_REPARSE) {
+ struct MFT_REF ref;
+
+ mi_get_ref(&ni->mi, &ref);
+ ntfs_remove_reparse(sbi, 0, &ref);
+ }
+
+ if (!attr->non_res)
+ continue;
+
+ if (attr->type != ATTR_REPARSE &&
+ (attr->type != ATTR_DATA ||
+ attr->name_len != ARRAY_SIZE(WOF_NAME) ||
+ memcmp(attr_name(attr), WOF_NAME, sizeof(WOF_NAME))))
+ continue;
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn = le64_to_cpu(attr->nres.evcn);
+
+ if (evcn + 1 <= svcn)
+ continue;
+
+ asize = le32_to_cpu(attr->size);
+ roff = le16_to_cpu(attr->nres.run_off);
+
+ /*run==1 Means unpack and deallocate. */
+ run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn,
+ Add2Ptr(attr, roff), asize - roff);
+ }
+
+ /*
+ * Step 3: Remove attribute ATTR_DATA::WofCompressedData.
+ */
+ err = ni_remove_attr(ni, ATTR_DATA, WOF_NAME, ARRAY_SIZE(WOF_NAME),
+ false, NULL);
+ if (err)
+ goto out;
+
+ /*
+ * Step 4: Remove ATTR_REPARSE.
+ */
+ err = ni_remove_attr(ni, ATTR_REPARSE, NULL, 0, false, NULL);
+ if (err)
+ goto out;
+
+ /*
+ * Step 5: Remove sparse flag from data attribute.
+ */
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (attr->non_res && is_attr_sparsed(attr)) {
+ /* Sparsed attribute header is 8 bytes bigger than normal. */
+ struct MFT_REC *rec = mi->mrec;
+ u32 used = le32_to_cpu(rec->used);
+ u32 asize = le32_to_cpu(attr->size);
+ u16 roff = le16_to_cpu(attr->nres.run_off);
+ char *rbuf = Add2Ptr(attr, roff);
+
+ memmove(rbuf - 8, rbuf, used - PtrOffset(rec, rbuf));
+ attr->size = cpu_to_le32(asize - 8);
+ attr->flags &= ~ATTR_FLAG_SPARSED;
+ attr->nres.run_off = cpu_to_le16(roff - 8);
+ attr->nres.c_unit = 0;
+ rec->used = cpu_to_le32(used - 8);
+ mi->dirty = true;
+ ni->std_fa &= ~(FILE_ATTRIBUTE_SPARSE_FILE |
+ FILE_ATTRIBUTE_REPARSE_POINT);
+
+ mark_inode_dirty(inode);
+ }
+
+ /* Clear cached flag. */
+ ni->ni_flags &= ~NI_FLAG_COMPRESSED_MASK;
+ if (ni->file.offs_page) {
+ put_page(ni->file.offs_page);
+ ni->file.offs_page = NULL;
+ }
+ mapping->a_ops = &ntfs_aops;
+
+out:
+ kfree(pages);
+ if (err) {
+ make_bad_inode(inode);
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+ }
+
+ return err;
+}
+
+/*
+ * decompress_lzx_xpress - External compression LZX/Xpress.
+ */
+static int decompress_lzx_xpress(struct ntfs_sb_info *sbi, const char *cmpr,
+ size_t cmpr_size, void *unc, size_t unc_size,
+ u32 frame_size)
+{
+ int err;
+ void *ctx;
+
+ if (cmpr_size == unc_size) {
+ /* Frame not compressed. */
+ memcpy(unc, cmpr, unc_size);
+ return 0;
+ }
+
+ err = 0;
+ if (frame_size == 0x8000) {
+ mutex_lock(&sbi->compress.mtx_lzx);
+ /* LZX: Frame compressed. */
+ ctx = sbi->compress.lzx;
+ if (!ctx) {
+ /* Lazy initialize LZX decompress context. */
+ ctx = lzx_allocate_decompressor();
+ if (!ctx) {
+ err = -ENOMEM;
+ goto out1;
+ }
+
+ sbi->compress.lzx = ctx;
+ }
+
+ if (lzx_decompress(ctx, cmpr, cmpr_size, unc, unc_size)) {
+ /* Treat all errors as "invalid argument". */
+ err = -EINVAL;
+ }
+out1:
+ mutex_unlock(&sbi->compress.mtx_lzx);
+ } else {
+ /* XPRESS: Frame compressed. */
+ mutex_lock(&sbi->compress.mtx_xpress);
+ ctx = sbi->compress.xpress;
+ if (!ctx) {
+ /* Lazy initialize Xpress decompress context. */
+ ctx = xpress_allocate_decompressor();
+ if (!ctx) {
+ err = -ENOMEM;
+ goto out2;
+ }
+
+ sbi->compress.xpress = ctx;
+ }
+
+ if (xpress_decompress(ctx, cmpr, cmpr_size, unc, unc_size)) {
+ /* Treat all errors as "invalid argument". */
+ err = -EINVAL;
+ }
+out2:
+ mutex_unlock(&sbi->compress.mtx_xpress);
+ }
+ return err;
+}
+#endif
+
+/*
+ * ni_read_frame
+ *
+ * Pages - Array of locked pages.
+ */
+int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
+ u32 pages_per_frame)
+{
+ int err;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ u8 cluster_bits = sbi->cluster_bits;
+ char *frame_ondisk = NULL;
+ char *frame_mem = NULL;
+ struct page **pages_disk = NULL;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ struct runs_tree *run = &ni->file.run;
+ u64 valid_size = ni->i_valid;
+ u64 vbo_disk;
+ size_t unc_size;
+ u32 frame_size, i, npages_disk, ondisk_size;
+ struct page *pg;
+ struct ATTRIB *attr;
+ CLST frame, clst_data;
+
+ /*
+ * To simplify decompress algorithm do vmap for source
+ * and target pages.
+ */
+ for (i = 0; i < pages_per_frame; i++)
+ kmap(pages[i]);
+
+ frame_size = pages_per_frame << PAGE_SHIFT;
+ frame_mem = vmap(pages, pages_per_frame, VM_MAP, PAGE_KERNEL);
+ if (!frame_mem) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, NULL);
+ if (!attr) {
+ err = -ENOENT;
+ goto out1;
+ }
+
+ if (!attr->non_res) {
+ u32 data_size = le32_to_cpu(attr->res.data_size);
+
+ memset(frame_mem, 0, frame_size);
+ if (frame_vbo < data_size) {
+ ondisk_size = data_size - frame_vbo;
+ memcpy(frame_mem, resident_data(attr) + frame_vbo,
+ min(ondisk_size, frame_size));
+ }
+ err = 0;
+ goto out1;
+ }
+
+ if (frame_vbo >= valid_size) {
+ memset(frame_mem, 0, frame_size);
+ err = 0;
+ goto out1;
+ }
+
+ if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) {
+#ifndef CONFIG_NTFS3_LZX_XPRESS
+ err = -EOPNOTSUPP;
+ goto out1;
+#else
+ u32 frame_bits = ni_ext_compress_bits(ni);
+ u64 frame64 = frame_vbo >> frame_bits;
+ u64 frames, vbo_data;
+
+ if (frame_size != (1u << frame_bits)) {
+ err = -EINVAL;
+ goto out1;
+ }
+ switch (frame_size) {
+ case 0x1000:
+ case 0x2000:
+ case 0x4000:
+ case 0x8000:
+ break;
+ default:
+ /* Unknown compression. */
+ err = -EOPNOTSUPP;
+ goto out1;
+ }
+
+ attr = ni_find_attr(ni, attr, &le, ATTR_DATA, WOF_NAME,
+ ARRAY_SIZE(WOF_NAME), NULL, NULL);
+ if (!attr) {
+ ntfs_inode_err(
+ &ni->vfs_inode,
+ "external compressed file should contains data attribute \"WofCompressedData\"");
+ err = -EINVAL;
+ goto out1;
+ }
+
+ if (!attr->non_res) {
+ run = NULL;
+ } else {
+ run = run_alloc();
+ if (!run) {
+ err = -ENOMEM;
+ goto out1;
+ }
+ }
+
+ frames = (ni->vfs_inode.i_size - 1) >> frame_bits;
+
+ err = attr_wof_frame_info(ni, attr, run, frame64, frames,
+ frame_bits, &ondisk_size, &vbo_data);
+ if (err)
+ goto out2;
+
+ if (frame64 == frames) {
+ unc_size = 1 + ((ni->vfs_inode.i_size - 1) &
+ (frame_size - 1));
+ ondisk_size = attr_size(attr) - vbo_data;
+ } else {
+ unc_size = frame_size;
+ }
+
+ if (ondisk_size > frame_size) {
+ err = -EINVAL;
+ goto out2;
+ }
+
+ if (!attr->non_res) {
+ if (vbo_data + ondisk_size >
+ le32_to_cpu(attr->res.data_size)) {
+ err = -EINVAL;
+ goto out1;
+ }
+
+ err = decompress_lzx_xpress(
+ sbi, Add2Ptr(resident_data(attr), vbo_data),
+ ondisk_size, frame_mem, unc_size, frame_size);
+ goto out1;
+ }
+ vbo_disk = vbo_data;
+ /* Load all runs to read [vbo_disk-vbo_to). */
+ err = attr_load_runs_range(ni, ATTR_DATA, WOF_NAME,
+ ARRAY_SIZE(WOF_NAME), run, vbo_disk,
+ vbo_data + ondisk_size);
+ if (err)
+ goto out2;
+ npages_disk = (ondisk_size + (vbo_disk & (PAGE_SIZE - 1)) +
+ PAGE_SIZE - 1) >>
+ PAGE_SHIFT;
+#endif
+ } else if (is_attr_compressed(attr)) {
+ /* LZNT compression. */
+ if (sbi->cluster_size > NTFS_LZNT_MAX_CLUSTER) {
+ err = -EOPNOTSUPP;
+ goto out1;
+ }
+
+ if (attr->nres.c_unit != NTFS_LZNT_CUNIT) {
+ err = -EOPNOTSUPP;
+ goto out1;
+ }
+
+ down_write(&ni->file.run_lock);
+ run_truncate_around(run, le64_to_cpu(attr->nres.svcn));
+ frame = frame_vbo >> (cluster_bits + NTFS_LZNT_CUNIT);
+ err = attr_is_frame_compressed(ni, attr, frame, &clst_data);
+ up_write(&ni->file.run_lock);
+ if (err)
+ goto out1;
+
+ if (!clst_data) {
+ memset(frame_mem, 0, frame_size);
+ goto out1;
+ }
+
+ frame_size = sbi->cluster_size << NTFS_LZNT_CUNIT;
+ ondisk_size = clst_data << cluster_bits;
+
+ if (clst_data >= NTFS_LZNT_CLUSTERS) {
+ /* Frame is not compressed. */
+ down_read(&ni->file.run_lock);
+ err = ntfs_bio_pages(sbi, run, pages, pages_per_frame,
+ frame_vbo, ondisk_size,
+ REQ_OP_READ);
+ up_read(&ni->file.run_lock);
+ goto out1;
+ }
+ vbo_disk = frame_vbo;
+ npages_disk = (ondisk_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ } else {
+ __builtin_unreachable();
+ err = -EINVAL;
+ goto out1;
+ }
+
+ pages_disk = kzalloc(npages_disk * sizeof(struct page *), GFP_NOFS);
+ if (!pages_disk) {
+ err = -ENOMEM;
+ goto out2;
+ }
+
+ for (i = 0; i < npages_disk; i++) {
+ pg = alloc_page(GFP_KERNEL);
+ if (!pg) {
+ err = -ENOMEM;
+ goto out3;
+ }
+ pages_disk[i] = pg;
+ lock_page(pg);
+ kmap(pg);
+ }
+
+ /* Read 'ondisk_size' bytes from disk. */
+ down_read(&ni->file.run_lock);
+ err = ntfs_bio_pages(sbi, run, pages_disk, npages_disk, vbo_disk,
+ ondisk_size, REQ_OP_READ);
+ up_read(&ni->file.run_lock);
+ if (err)
+ goto out3;
+
+ /*
+ * To simplify decompress algorithm do vmap for source and target pages.
+ */
+ frame_ondisk = vmap(pages_disk, npages_disk, VM_MAP, PAGE_KERNEL_RO);
+ if (!frame_ondisk) {
+ err = -ENOMEM;
+ goto out3;
+ }
+
+ /* Decompress: Frame_ondisk -> frame_mem. */
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+ if (run != &ni->file.run) {
+ /* LZX or XPRESS */
+ err = decompress_lzx_xpress(
+ sbi, frame_ondisk + (vbo_disk & (PAGE_SIZE - 1)),
+ ondisk_size, frame_mem, unc_size, frame_size);
+ } else
+#endif
+ {
+ /* LZNT - Native NTFS compression. */
+ unc_size = decompress_lznt(frame_ondisk, ondisk_size, frame_mem,
+ frame_size);
+ if ((ssize_t)unc_size < 0)
+ err = unc_size;
+ else if (!unc_size || unc_size > frame_size)
+ err = -EINVAL;
+ }
+ if (!err && valid_size < frame_vbo + frame_size) {
+ size_t ok = valid_size - frame_vbo;
+
+ memset(frame_mem + ok, 0, frame_size - ok);
+ }
+
+ vunmap(frame_ondisk);
+
+out3:
+ for (i = 0; i < npages_disk; i++) {
+ pg = pages_disk[i];
+ if (pg) {
+ kunmap(pg);
+ unlock_page(pg);
+ put_page(pg);
+ }
+ }
+ kfree(pages_disk);
+
+out2:
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+ if (run != &ni->file.run)
+ run_free(run);
+#endif
+out1:
+ vunmap(frame_mem);
+out:
+ for (i = 0; i < pages_per_frame; i++) {
+ pg = pages[i];
+ kunmap(pg);
+ ClearPageError(pg);
+ SetPageUptodate(pg);
+ }
+
+ return err;
+}
+
+/*
+ * ni_write_frame
+ *
+ * Pages - Array of locked pages.
+ */
+int ni_write_frame(struct ntfs_inode *ni, struct page **pages,
+ u32 pages_per_frame)
+{
+ int err;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ u8 frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits;
+ u32 frame_size = sbi->cluster_size << NTFS_LZNT_CUNIT;
+ u64 frame_vbo = (u64)pages[0]->index << PAGE_SHIFT;
+ CLST frame = frame_vbo >> frame_bits;
+ char *frame_ondisk = NULL;
+ struct page **pages_disk = NULL;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ char *frame_mem;
+ struct ATTRIB *attr;
+ struct mft_inode *mi;
+ u32 i;
+ struct page *pg;
+ size_t compr_size, ondisk_size;
+ struct lznt *lznt;
+
+ attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, &mi);
+ if (!attr) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (WARN_ON(!is_attr_compressed(attr))) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (sbi->cluster_size > NTFS_LZNT_MAX_CLUSTER) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!attr->non_res) {
+ down_write(&ni->file.run_lock);
+ err = attr_make_nonresident(ni, attr, le, mi,
+ le32_to_cpu(attr->res.data_size),
+ &ni->file.run, &attr, pages[0]);
+ up_write(&ni->file.run_lock);
+ if (err)
+ goto out;
+ }
+
+ if (attr->nres.c_unit != NTFS_LZNT_CUNIT) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ pages_disk = kcalloc(pages_per_frame, sizeof(struct page *), GFP_NOFS);
+ if (!pages_disk) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < pages_per_frame; i++) {
+ pg = alloc_page(GFP_KERNEL);
+ if (!pg) {
+ err = -ENOMEM;
+ goto out1;
+ }
+ pages_disk[i] = pg;
+ lock_page(pg);
+ kmap(pg);
+ }
+
+ /* To simplify compress algorithm do vmap for source and target pages. */
+ frame_ondisk = vmap(pages_disk, pages_per_frame, VM_MAP, PAGE_KERNEL);
+ if (!frame_ondisk) {
+ err = -ENOMEM;
+ goto out1;
+ }
+
+ for (i = 0; i < pages_per_frame; i++)
+ kmap(pages[i]);
+
+ /* Map in-memory frame for read-only. */
+ frame_mem = vmap(pages, pages_per_frame, VM_MAP, PAGE_KERNEL_RO);
+ if (!frame_mem) {
+ err = -ENOMEM;
+ goto out2;
+ }
+
+ mutex_lock(&sbi->compress.mtx_lznt);
+ lznt = NULL;
+ if (!sbi->compress.lznt) {
+ /*
+ * LZNT implements two levels of compression:
+ * 0 - Standard compression
+ * 1 - Best compression, requires a lot of cpu
+ * use mount option?
+ */
+ lznt = get_lznt_ctx(0);
+ if (!lznt) {
+ mutex_unlock(&sbi->compress.mtx_lznt);
+ err = -ENOMEM;
+ goto out3;
+ }
+
+ sbi->compress.lznt = lznt;
+ lznt = NULL;
+ }
+
+ /* Compress: frame_mem -> frame_ondisk */
+ compr_size = compress_lznt(frame_mem, frame_size, frame_ondisk,
+ frame_size, sbi->compress.lznt);
+ mutex_unlock(&sbi->compress.mtx_lznt);
+ kfree(lznt);
+
+ if (compr_size + sbi->cluster_size > frame_size) {
+ /* Frame is not compressed. */
+ compr_size = frame_size;
+ ondisk_size = frame_size;
+ } else if (compr_size) {
+ /* Frame is compressed. */
+ ondisk_size = ntfs_up_cluster(sbi, compr_size);
+ memset(frame_ondisk + compr_size, 0, ondisk_size - compr_size);
+ } else {
+ /* Frame is sparsed. */
+ ondisk_size = 0;
+ }
+
+ down_write(&ni->file.run_lock);
+ run_truncate_around(&ni->file.run, le64_to_cpu(attr->nres.svcn));
+ err = attr_allocate_frame(ni, frame, compr_size, ni->i_valid);
+ up_write(&ni->file.run_lock);
+ if (err)
+ goto out2;
+
+ if (!ondisk_size)
+ goto out2;
+
+ down_read(&ni->file.run_lock);
+ err = ntfs_bio_pages(sbi, &ni->file.run,
+ ondisk_size < frame_size ? pages_disk : pages,
+ pages_per_frame, frame_vbo, ondisk_size,
+ REQ_OP_WRITE);
+ up_read(&ni->file.run_lock);
+
+out3:
+ vunmap(frame_mem);
+
+out2:
+ for (i = 0; i < pages_per_frame; i++)
+ kunmap(pages[i]);
+
+ vunmap(frame_ondisk);
+out1:
+ for (i = 0; i < pages_per_frame; i++) {
+ pg = pages_disk[i];
+ if (pg) {
+ kunmap(pg);
+ unlock_page(pg);
+ put_page(pg);
+ }
+ }
+ kfree(pages_disk);
+out:
+ return err;
+}
+
+/*
+ * ni_remove_name - Removes name 'de' from MFT and from directory.
+ * 'de2' and 'undo_step' are used to restore MFT/dir, if error occurs.
+ */
+int ni_remove_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
+ struct NTFS_DE *de, struct NTFS_DE **de2, int *undo_step)
+{
+ int err;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct ATTR_FILE_NAME *de_name = (struct ATTR_FILE_NAME *)(de + 1);
+ struct ATTR_FILE_NAME *fname;
+ struct ATTR_LIST_ENTRY *le;
+ struct mft_inode *mi;
+ u16 de_key_size = le16_to_cpu(de->key_size);
+ u8 name_type;
+
+ *undo_step = 0;
+
+ /* Find name in record. */
+ mi_get_ref(&dir_ni->mi, &de_name->home);
+
+ fname = ni_fname_name(ni, (struct cpu_str *)&de_name->name_len,
+ &de_name->home, &mi, &le);
+ if (!fname)
+ return -ENOENT;
+
+ memcpy(&de_name->dup, &fname->dup, sizeof(struct NTFS_DUP_INFO));
+ name_type = paired_name(fname->type);
+
+ /* Mark ntfs as dirty. It will be cleared at umount. */
+ ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
+
+ /* Step 1: Remove name from directory. */
+ err = indx_delete_entry(&dir_ni->dir, dir_ni, fname, de_key_size, sbi);
+ if (err)
+ return err;
+
+ /* Step 2: Remove name from MFT. */
+ ni_remove_attr_le(ni, attr_from_name(fname), mi, le);
+
+ *undo_step = 2;
+
+ /* Get paired name. */
+ fname = ni_fname_type(ni, name_type, &mi, &le);
+ if (fname) {
+ u16 de2_key_size = fname_full_size(fname);
+
+ *de2 = Add2Ptr(de, 1024);
+ (*de2)->key_size = cpu_to_le16(de2_key_size);
+
+ memcpy(*de2 + 1, fname, de2_key_size);
+
+ /* Step 3: Remove paired name from directory. */
+ err = indx_delete_entry(&dir_ni->dir, dir_ni, fname,
+ de2_key_size, sbi);
+ if (err)
+ return err;
+
+ /* Step 4: Remove paired name from MFT. */
+ ni_remove_attr_le(ni, attr_from_name(fname), mi, le);
+
+ *undo_step = 4;
+ }
+ return 0;
+}
+
+/*
+ * ni_remove_name_undo - Paired function for ni_remove_name.
+ *
+ * Return: True if ok
+ */
+bool ni_remove_name_undo(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
+ struct NTFS_DE *de, struct NTFS_DE *de2, int undo_step)
+{
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct ATTRIB *attr;
+ u16 de_key_size = de2 ? le16_to_cpu(de2->key_size) : 0;
+
+ switch (undo_step) {
+ case 4:
+ if (ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0,
+ &attr, NULL, NULL)) {
+ return false;
+ }
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de2 + 1, de_key_size);
+
+ mi_get_ref(&ni->mi, &de2->ref);
+ de2->size = cpu_to_le16(ALIGN(de_key_size, 8) +
+ sizeof(struct NTFS_DE));
+ de2->flags = 0;
+ de2->res = 0;
+
+ if (indx_insert_entry(&dir_ni->dir, dir_ni, de2, sbi, NULL,
+ 1)) {
+ return false;
+ }
+ fallthrough;
+
+ case 2:
+ de_key_size = le16_to_cpu(de->key_size);
+
+ if (ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0,
+ &attr, NULL, NULL)) {
+ return false;
+ }
+
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de + 1, de_key_size);
+ mi_get_ref(&ni->mi, &de->ref);
+
+ if (indx_insert_entry(&dir_ni->dir, dir_ni, de, sbi, NULL, 1)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * ni_add_name - Add new name in MFT and in directory.
+ */
+int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
+ struct NTFS_DE *de)
+{
+ int err;
+ struct ATTRIB *attr;
+ struct ATTR_LIST_ENTRY *le;
+ struct mft_inode *mi;
+ struct ATTR_FILE_NAME *de_name = (struct ATTR_FILE_NAME *)(de + 1);
+ u16 de_key_size = le16_to_cpu(de->key_size);
+
+ mi_get_ref(&ni->mi, &de->ref);
+ mi_get_ref(&dir_ni->mi, &de_name->home);
+
+ /* Insert new name in MFT. */
+ err = ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0, &attr,
+ &mi, &le);
+ if (err)
+ return err;
+
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de_name, de_key_size);
+
+ /* Insert new name in directory. */
+ err = indx_insert_entry(&dir_ni->dir, dir_ni, de, ni->mi.sbi, NULL, 0);
+ if (err)
+ ni_remove_attr_le(ni, attr, mi, le);
+
+ return err;
+}
+
+/*
+ * ni_rename - Remove one name and insert new name.
+ */
+int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
+ struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de,
+ bool *is_bad)
+{
+ int err;
+ struct NTFS_DE *de2 = NULL;
+ int undo = 0;
+
+ /*
+ * There are two possible ways to rename:
+ * 1) Add new name and remove old name.
+ * 2) Remove old name and add new name.
+ *
+ * In most cases (not all!) adding new name in MFT and in directory can
+ * allocate additional cluster(s).
+ * Second way may result to bad inode if we can't add new name
+ * and then can't restore (add) old name.
+ */
+
+ /*
+ * Way 1 - Add new + remove old.
+ */
+ err = ni_add_name(new_dir_ni, ni, new_de);
+ if (!err) {
+ err = ni_remove_name(dir_ni, ni, de, &de2, &undo);
+ if (err && ni_remove_name(new_dir_ni, ni, new_de, &de2, &undo))
+ *is_bad = true;
+ }
+
+ /*
+ * Way 2 - Remove old + add new.
+ */
+ /*
+ * err = ni_remove_name(dir_ni, ni, de, &de2, &undo);
+ * if (!err) {
+ * err = ni_add_name(new_dir_ni, ni, new_de);
+ * if (err && !ni_remove_name_undo(dir_ni, ni, de, de2, undo))
+ * *is_bad = true;
+ * }
+ */
+
+ return err;
+}
+
+/*
+ * ni_is_dirty - Return: True if 'ni' requires ni_write_inode.
+ */
+bool ni_is_dirty(struct inode *inode)
+{
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct rb_node *node;
+
+ if (ni->mi.dirty || ni->attr_list.dirty ||
+ (ni->ni_flags & NI_FLAG_UPDATE_PARENT))
+ return true;
+
+ for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
+ if (rb_entry(node, struct mft_inode, node)->dirty)
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * ni_update_parent
+ *
+ * Update duplicate info of ATTR_FILE_NAME in MFT and in parent directories.
+ */
+static bool ni_update_parent(struct ntfs_inode *ni, struct NTFS_DUP_INFO *dup,
+ int sync)
+{
+ struct ATTRIB *attr;
+ struct mft_inode *mi;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct super_block *sb = sbi->sb;
+ bool re_dirty = false;
+
+ if (ni->mi.mrec->flags & RECORD_FLAG_DIR) {
+ dup->fa |= FILE_ATTRIBUTE_DIRECTORY;
+ attr = NULL;
+ dup->alloc_size = 0;
+ dup->data_size = 0;
+ } else {
+ dup->fa &= ~FILE_ATTRIBUTE_DIRECTORY;
+
+ attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL,
+ &mi);
+ if (!attr) {
+ dup->alloc_size = dup->data_size = 0;
+ } else if (!attr->non_res) {
+ u32 data_size = le32_to_cpu(attr->res.data_size);
+
+ dup->alloc_size = cpu_to_le64(ALIGN(data_size, 8));
+ dup->data_size = cpu_to_le64(data_size);
+ } else {
+ u64 new_valid = ni->i_valid;
+ u64 data_size = le64_to_cpu(attr->nres.data_size);
+ __le64 valid_le;
+
+ dup->alloc_size = is_attr_ext(attr)
+ ? attr->nres.total_size
+ : attr->nres.alloc_size;
+ dup->data_size = attr->nres.data_size;
+
+ if (new_valid > data_size)
+ new_valid = data_size;
+
+ valid_le = cpu_to_le64(new_valid);
+ if (valid_le != attr->nres.valid_size) {
+ attr->nres.valid_size = valid_le;
+ mi->dirty = true;
+ }
+ }
+ }
+
+ /* TODO: Fill reparse info. */
+ dup->reparse = 0;
+ dup->ea_size = 0;
+
+ if (ni->ni_flags & NI_FLAG_EA) {
+ attr = ni_find_attr(ni, attr, &le, ATTR_EA_INFO, NULL, 0, NULL,
+ NULL);
+ if (attr) {
+ const struct EA_INFO *info;
+
+ info = resident_data_ex(attr, sizeof(struct EA_INFO));
+ dup->ea_size = info->size_pack;
+ }
+ }
+
+ attr = NULL;
+ le = NULL;
+
+ while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
+ &mi))) {
+ struct inode *dir;
+ struct ATTR_FILE_NAME *fname;
+
+ fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
+ if (!fname || !memcmp(&fname->dup, dup, sizeof(fname->dup)))
+ continue;
+
+ /* ntfs_iget5 may sleep. */
+ dir = ntfs_iget5(sb, &fname->home, NULL);
+ if (IS_ERR(dir)) {
+ ntfs_inode_warn(
+ &ni->vfs_inode,
+ "failed to open parent directory r=%lx to update",
+ (long)ino_get(&fname->home));
+ continue;
+ }
+
+ if (!is_bad_inode(dir)) {
+ struct ntfs_inode *dir_ni = ntfs_i(dir);
+
+ if (!ni_trylock(dir_ni)) {
+ re_dirty = true;
+ } else {
+ indx_update_dup(dir_ni, sbi, fname, dup, sync);
+ ni_unlock(dir_ni);
+ memcpy(&fname->dup, dup, sizeof(fname->dup));
+ mi->dirty = true;
+ }
+ }
+ iput(dir);
+ }
+
+ return re_dirty;
+}
+
+/*
+ * ni_write_inode - Write MFT base record and all subrecords to disk.
+ */
+int ni_write_inode(struct inode *inode, int sync, const char *hint)
+{
+ int err = 0, err2;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ bool re_dirty = false;
+ struct ATTR_STD_INFO *std;
+ struct rb_node *node, *next;
+ struct NTFS_DUP_INFO dup;
+
+ if (is_bad_inode(inode) || sb_rdonly(sb))
+ return 0;
+
+ if (!ni_trylock(ni)) {
+ /* 'ni' is under modification, skip for now. */
+ mark_inode_dirty_sync(inode);
+ return 0;
+ }
+
+ if (is_rec_inuse(ni->mi.mrec) &&
+ !(sbi->flags & NTFS_FLAGS_LOG_REPLAYING) && inode->i_nlink) {
+ bool modified = false;
+
+ /* Update times in standard attribute. */
+ std = ni_std(ni);
+ if (!std) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Update the access times if they have changed. */
+ dup.m_time = kernel2nt(&inode->i_mtime);
+ if (std->m_time != dup.m_time) {
+ std->m_time = dup.m_time;
+ modified = true;
+ }
+
+ dup.c_time = kernel2nt(&inode->i_ctime);
+ if (std->c_time != dup.c_time) {
+ std->c_time = dup.c_time;
+ modified = true;
+ }
+
+ dup.a_time = kernel2nt(&inode->i_atime);
+ if (std->a_time != dup.a_time) {
+ std->a_time = dup.a_time;
+ modified = true;
+ }
+
+ dup.fa = ni->std_fa;
+ if (std->fa != dup.fa) {
+ std->fa = dup.fa;
+ modified = true;
+ }
+
+ if (modified)
+ ni->mi.dirty = true;
+
+ if (!ntfs_is_meta_file(sbi, inode->i_ino) &&
+ (modified || (ni->ni_flags & NI_FLAG_UPDATE_PARENT))
+ /* Avoid __wait_on_freeing_inode(inode). */
+ && (sb->s_flags & SB_ACTIVE)) {
+ dup.cr_time = std->cr_time;
+ /* Not critical if this function fail. */
+ re_dirty = ni_update_parent(ni, &dup, sync);
+
+ if (re_dirty)
+ ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
+ else
+ ni->ni_flags &= ~NI_FLAG_UPDATE_PARENT;
+ }
+
+ /* Update attribute list. */
+ if (ni->attr_list.size && ni->attr_list.dirty) {
+ if (inode->i_ino != MFT_REC_MFT || sync) {
+ err = ni_try_remove_attr_list(ni);
+ if (err)
+ goto out;
+ }
+
+ err = al_update(ni);
+ if (err)
+ goto out;
+ }
+ }
+
+ for (node = rb_first(&ni->mi_tree); node; node = next) {
+ struct mft_inode *mi = rb_entry(node, struct mft_inode, node);
+ bool is_empty;
+
+ next = rb_next(node);
+
+ if (!mi->dirty)
+ continue;
+
+ is_empty = !mi_enum_attr(mi, NULL);
+
+ if (is_empty)
+ clear_rec_inuse(mi->mrec);
+
+ err2 = mi_write(mi, sync);
+ if (!err && err2)
+ err = err2;
+
+ if (is_empty) {
+ ntfs_mark_rec_free(sbi, mi->rno);
+ rb_erase(node, &ni->mi_tree);
+ mi_put(mi);
+ }
+ }
+
+ if (ni->mi.dirty) {
+ err2 = mi_write(&ni->mi, sync);
+ if (!err && err2)
+ err = err2;
+ }
+out:
+ ni_unlock(ni);
+
+ if (err) {
+ ntfs_err(sb, "%s r=%lx failed, %d.", hint, inode->i_ino, err);
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+ return err;
+ }
+
+ if (re_dirty)
+ mark_inode_dirty_sync(inode);
+
+ return 0;
+}
diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c
new file mode 100644
index 000000000000..b5853aed0e25
--- /dev/null
+++ b/fs/ntfs3/fslog.c
@@ -0,0 +1,5217 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/hash.h>
+#include <linux/nls.h>
+#include <linux/random.h>
+#include <linux/ratelimit.h>
+#include <linux/slab.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+/*
+ * LOG FILE structs
+ */
+
+// clang-format off
+
+#define MaxLogFileSize 0x100000000ull
+#define DefaultLogPageSize 4096
+#define MinLogRecordPages 0x30
+
+struct RESTART_HDR {
+ struct NTFS_RECORD_HEADER rhdr; // 'RSTR'
+ __le32 sys_page_size; // 0x10: Page size of the system which initialized the log.
+ __le32 page_size; // 0x14: Log page size used for this log file.
+ __le16 ra_off; // 0x18:
+ __le16 minor_ver; // 0x1A:
+ __le16 major_ver; // 0x1C:
+ __le16 fixups[];
+};
+
+#define LFS_NO_CLIENT 0xffff
+#define LFS_NO_CLIENT_LE cpu_to_le16(0xffff)
+
+struct CLIENT_REC {
+ __le64 oldest_lsn;
+ __le64 restart_lsn; // 0x08:
+ __le16 prev_client; // 0x10:
+ __le16 next_client; // 0x12:
+ __le16 seq_num; // 0x14:
+ u8 align[6]; // 0x16:
+ __le32 name_bytes; // 0x1C: In bytes.
+ __le16 name[32]; // 0x20: Name of client.
+};
+
+static_assert(sizeof(struct CLIENT_REC) == 0x60);
+
+/* Two copies of these will exist at the beginning of the log file */
+struct RESTART_AREA {
+ __le64 current_lsn; // 0x00: Current logical end of log file.
+ __le16 log_clients; // 0x08: Maximum number of clients.
+ __le16 client_idx[2]; // 0x0A: Free/use index into the client record arrays.
+ __le16 flags; // 0x0E: See RESTART_SINGLE_PAGE_IO.
+ __le32 seq_num_bits; // 0x10: The number of bits in sequence number.
+ __le16 ra_len; // 0x14:
+ __le16 client_off; // 0x16:
+ __le64 l_size; // 0x18: Usable log file size.
+ __le32 last_lsn_data_len; // 0x20:
+ __le16 rec_hdr_len; // 0x24: Log page data offset.
+ __le16 data_off; // 0x26: Log page data length.
+ __le32 open_log_count; // 0x28:
+ __le32 align[5]; // 0x2C:
+ struct CLIENT_REC clients[]; // 0x40:
+};
+
+struct LOG_REC_HDR {
+ __le16 redo_op; // 0x00: NTFS_LOG_OPERATION
+ __le16 undo_op; // 0x02: NTFS_LOG_OPERATION
+ __le16 redo_off; // 0x04: Offset to Redo record.
+ __le16 redo_len; // 0x06: Redo length.
+ __le16 undo_off; // 0x08: Offset to Undo record.
+ __le16 undo_len; // 0x0A: Undo length.
+ __le16 target_attr; // 0x0C:
+ __le16 lcns_follow; // 0x0E:
+ __le16 record_off; // 0x10:
+ __le16 attr_off; // 0x12:
+ __le16 cluster_off; // 0x14:
+ __le16 reserved; // 0x16:
+ __le64 target_vcn; // 0x18:
+ __le64 page_lcns[]; // 0x20:
+};
+
+static_assert(sizeof(struct LOG_REC_HDR) == 0x20);
+
+#define RESTART_ENTRY_ALLOCATED 0xFFFFFFFF
+#define RESTART_ENTRY_ALLOCATED_LE cpu_to_le32(0xFFFFFFFF)
+
+struct RESTART_TABLE {
+ __le16 size; // 0x00: In bytes
+ __le16 used; // 0x02: Entries
+ __le16 total; // 0x04: Entries
+ __le16 res[3]; // 0x06:
+ __le32 free_goal; // 0x0C:
+ __le32 first_free; // 0x10:
+ __le32 last_free; // 0x14:
+
+};
+
+static_assert(sizeof(struct RESTART_TABLE) == 0x18);
+
+struct ATTR_NAME_ENTRY {
+ __le16 off; // Offset in the Open attribute Table.
+ __le16 name_bytes;
+ __le16 name[];
+};
+
+struct OPEN_ATTR_ENRTY {
+ __le32 next; // 0x00: RESTART_ENTRY_ALLOCATED if allocated
+ __le32 bytes_per_index; // 0x04:
+ enum ATTR_TYPE type; // 0x08:
+ u8 is_dirty_pages; // 0x0C:
+ u8 is_attr_name; // 0x0B: Faked field to manage 'ptr'
+ u8 name_len; // 0x0C: Faked field to manage 'ptr'
+ u8 res;
+ struct MFT_REF ref; // 0x10: File Reference of file containing attribute
+ __le64 open_record_lsn; // 0x18:
+ void *ptr; // 0x20:
+};
+
+/* 32 bit version of 'struct OPEN_ATTR_ENRTY' */
+struct OPEN_ATTR_ENRTY_32 {
+ __le32 next; // 0x00: RESTART_ENTRY_ALLOCATED if allocated
+ __le32 ptr; // 0x04:
+ struct MFT_REF ref; // 0x08:
+ __le64 open_record_lsn; // 0x10:
+ u8 is_dirty_pages; // 0x18:
+ u8 is_attr_name; // 0x19:
+ u8 res1[2];
+ enum ATTR_TYPE type; // 0x1C:
+ u8 name_len; // 0x20: In wchar
+ u8 res2[3];
+ __le32 AttributeName; // 0x24:
+ __le32 bytes_per_index; // 0x28:
+};
+
+#define SIZEOF_OPENATTRIBUTEENTRY0 0x2c
+// static_assert( 0x2C == sizeof(struct OPEN_ATTR_ENRTY_32) );
+static_assert(sizeof(struct OPEN_ATTR_ENRTY) < SIZEOF_OPENATTRIBUTEENTRY0);
+
+/*
+ * One entry exists in the Dirty Pages Table for each page which is dirty at
+ * the time the Restart Area is written.
+ */
+struct DIR_PAGE_ENTRY {
+ __le32 next; // 0x00: RESTART_ENTRY_ALLOCATED if allocated
+ __le32 target_attr; // 0x04: Index into the Open attribute Table
+ __le32 transfer_len; // 0x08:
+ __le32 lcns_follow; // 0x0C:
+ __le64 vcn; // 0x10: Vcn of dirty page
+ __le64 oldest_lsn; // 0x18:
+ __le64 page_lcns[]; // 0x20:
+};
+
+static_assert(sizeof(struct DIR_PAGE_ENTRY) == 0x20);
+
+/* 32 bit version of 'struct DIR_PAGE_ENTRY' */
+struct DIR_PAGE_ENTRY_32 {
+ __le32 next; // 0x00: RESTART_ENTRY_ALLOCATED if allocated
+ __le32 target_attr; // 0x04: Index into the Open attribute Table
+ __le32 transfer_len; // 0x08:
+ __le32 lcns_follow; // 0x0C:
+ __le32 reserved; // 0x10:
+ __le32 vcn_low; // 0x14: Vcn of dirty page
+ __le32 vcn_hi; // 0x18: Vcn of dirty page
+ __le32 oldest_lsn_low; // 0x1C:
+ __le32 oldest_lsn_hi; // 0x1C:
+ __le32 page_lcns_low; // 0x24:
+ __le32 page_lcns_hi; // 0x24:
+};
+
+static_assert(offsetof(struct DIR_PAGE_ENTRY_32, vcn_low) == 0x14);
+static_assert(sizeof(struct DIR_PAGE_ENTRY_32) == 0x2c);
+
+enum transact_state {
+ TransactionUninitialized = 0,
+ TransactionActive,
+ TransactionPrepared,
+ TransactionCommitted
+};
+
+struct TRANSACTION_ENTRY {
+ __le32 next; // 0x00: RESTART_ENTRY_ALLOCATED if allocated
+ u8 transact_state; // 0x04:
+ u8 reserved[3]; // 0x05:
+ __le64 first_lsn; // 0x08:
+ __le64 prev_lsn; // 0x10:
+ __le64 undo_next_lsn; // 0x18:
+ __le32 undo_records; // 0x20: Number of undo log records pending abort
+ __le32 undo_len; // 0x24: Total undo size
+};
+
+static_assert(sizeof(struct TRANSACTION_ENTRY) == 0x28);
+
+struct NTFS_RESTART {
+ __le32 major_ver; // 0x00:
+ __le32 minor_ver; // 0x04:
+ __le64 check_point_start; // 0x08:
+ __le64 open_attr_table_lsn; // 0x10:
+ __le64 attr_names_lsn; // 0x18:
+ __le64 dirty_pages_table_lsn; // 0x20:
+ __le64 transact_table_lsn; // 0x28:
+ __le32 open_attr_len; // 0x30: In bytes
+ __le32 attr_names_len; // 0x34: In bytes
+ __le32 dirty_pages_len; // 0x38: In bytes
+ __le32 transact_table_len; // 0x3C: In bytes
+};
+
+static_assert(sizeof(struct NTFS_RESTART) == 0x40);
+
+struct NEW_ATTRIBUTE_SIZES {
+ __le64 alloc_size;
+ __le64 valid_size;
+ __le64 data_size;
+ __le64 total_size;
+};
+
+struct BITMAP_RANGE {
+ __le32 bitmap_off;
+ __le32 bits;
+};
+
+struct LCN_RANGE {
+ __le64 lcn;
+ __le64 len;
+};
+
+/* The following type defines the different log record types. */
+#define LfsClientRecord cpu_to_le32(1)
+#define LfsClientRestart cpu_to_le32(2)
+
+/* This is used to uniquely identify a client for a particular log file. */
+struct CLIENT_ID {
+ __le16 seq_num;
+ __le16 client_idx;
+};
+
+/* This is the header that begins every Log Record in the log file. */
+struct LFS_RECORD_HDR {
+ __le64 this_lsn; // 0x00:
+ __le64 client_prev_lsn; // 0x08:
+ __le64 client_undo_next_lsn; // 0x10:
+ __le32 client_data_len; // 0x18:
+ struct CLIENT_ID client; // 0x1C: Owner of this log record.
+ __le32 record_type; // 0x20: LfsClientRecord or LfsClientRestart.
+ __le32 transact_id; // 0x24:
+ __le16 flags; // 0x28: LOG_RECORD_MULTI_PAGE
+ u8 align[6]; // 0x2A:
+};
+
+#define LOG_RECORD_MULTI_PAGE cpu_to_le16(1)
+
+static_assert(sizeof(struct LFS_RECORD_HDR) == 0x30);
+
+struct LFS_RECORD {
+ __le16 next_record_off; // 0x00: Offset of the free space in the page,
+ u8 align[6]; // 0x02:
+ __le64 last_end_lsn; // 0x08: lsn for the last log record which ends on the page,
+};
+
+static_assert(sizeof(struct LFS_RECORD) == 0x10);
+
+struct RECORD_PAGE_HDR {
+ struct NTFS_RECORD_HEADER rhdr; // 'RCRD'
+ __le32 rflags; // 0x10: See LOG_PAGE_LOG_RECORD_END
+ __le16 page_count; // 0x14:
+ __le16 page_pos; // 0x16:
+ struct LFS_RECORD record_hdr; // 0x18:
+ __le16 fixups[10]; // 0x28:
+ __le32 file_off; // 0x3c: Used when major version >= 2
+};
+
+// clang-format on
+
+// Page contains the end of a log record.
+#define LOG_PAGE_LOG_RECORD_END cpu_to_le32(0x00000001)
+
+static inline bool is_log_record_end(const struct RECORD_PAGE_HDR *hdr)
+{
+ return hdr->rflags & LOG_PAGE_LOG_RECORD_END;
+}
+
+static_assert(offsetof(struct RECORD_PAGE_HDR, file_off) == 0x3c);
+
+/*
+ * END of NTFS LOG structures
+ */
+
+/* Define some tuning parameters to keep the restart tables a reasonable size. */
+#define INITIAL_NUMBER_TRANSACTIONS 5
+
+enum NTFS_LOG_OPERATION {
+
+ Noop = 0x00,
+ CompensationLogRecord = 0x01,
+ InitializeFileRecordSegment = 0x02,
+ DeallocateFileRecordSegment = 0x03,
+ WriteEndOfFileRecordSegment = 0x04,
+ CreateAttribute = 0x05,
+ DeleteAttribute = 0x06,
+ UpdateResidentValue = 0x07,
+ UpdateNonresidentValue = 0x08,
+ UpdateMappingPairs = 0x09,
+ DeleteDirtyClusters = 0x0A,
+ SetNewAttributeSizes = 0x0B,
+ AddIndexEntryRoot = 0x0C,
+ DeleteIndexEntryRoot = 0x0D,
+ AddIndexEntryAllocation = 0x0E,
+ DeleteIndexEntryAllocation = 0x0F,
+ WriteEndOfIndexBuffer = 0x10,
+ SetIndexEntryVcnRoot = 0x11,
+ SetIndexEntryVcnAllocation = 0x12,
+ UpdateFileNameRoot = 0x13,
+ UpdateFileNameAllocation = 0x14,
+ SetBitsInNonresidentBitMap = 0x15,
+ ClearBitsInNonresidentBitMap = 0x16,
+ HotFix = 0x17,
+ EndTopLevelAction = 0x18,
+ PrepareTransaction = 0x19,
+ CommitTransaction = 0x1A,
+ ForgetTransaction = 0x1B,
+ OpenNonresidentAttribute = 0x1C,
+ OpenAttributeTableDump = 0x1D,
+ AttributeNamesDump = 0x1E,
+ DirtyPageTableDump = 0x1F,
+ TransactionTableDump = 0x20,
+ UpdateRecordDataRoot = 0x21,
+ UpdateRecordDataAllocation = 0x22,
+
+ UpdateRelativeDataInIndex =
+ 0x23, // NtOfsRestartUpdateRelativeDataInIndex
+ UpdateRelativeDataInIndex2 = 0x24,
+ ZeroEndOfFileRecord = 0x25,
+};
+
+/*
+ * Array for log records which require a target attribute.
+ * A true indicates that the corresponding restart operation
+ * requires a target attribute.
+ */
+static const u8 AttributeRequired[] = {
+ 0xFC, 0xFB, 0xFF, 0x10, 0x06,
+};
+
+static inline bool is_target_required(u16 op)
+{
+ bool ret = op <= UpdateRecordDataAllocation &&
+ (AttributeRequired[op >> 3] >> (op & 7) & 1);
+ return ret;
+}
+
+static inline bool can_skip_action(enum NTFS_LOG_OPERATION op)
+{
+ switch (op) {
+ case Noop:
+ case DeleteDirtyClusters:
+ case HotFix:
+ case EndTopLevelAction:
+ case PrepareTransaction:
+ case CommitTransaction:
+ case ForgetTransaction:
+ case CompensationLogRecord:
+ case OpenNonresidentAttribute:
+ case OpenAttributeTableDump:
+ case AttributeNamesDump:
+ case DirtyPageTableDump:
+ case TransactionTableDump:
+ return true;
+ default:
+ return false;
+ }
+}
+
+enum { lcb_ctx_undo_next, lcb_ctx_prev, lcb_ctx_next };
+
+/* Bytes per restart table. */
+static inline u32 bytes_per_rt(const struct RESTART_TABLE *rt)
+{
+ return le16_to_cpu(rt->used) * le16_to_cpu(rt->size) +
+ sizeof(struct RESTART_TABLE);
+}
+
+/* Log record length. */
+static inline u32 lrh_length(const struct LOG_REC_HDR *lr)
+{
+ u16 t16 = le16_to_cpu(lr->lcns_follow);
+
+ return struct_size(lr, page_lcns, max_t(u16, 1, t16));
+}
+
+struct lcb {
+ struct LFS_RECORD_HDR *lrh; // Log record header of the current lsn.
+ struct LOG_REC_HDR *log_rec;
+ u32 ctx_mode; // lcb_ctx_undo_next/lcb_ctx_prev/lcb_ctx_next
+ struct CLIENT_ID client;
+ bool alloc; // If true the we should deallocate 'log_rec'.
+};
+
+static void lcb_put(struct lcb *lcb)
+{
+ if (lcb->alloc)
+ kfree(lcb->log_rec);
+ kfree(lcb->lrh);
+ kfree(lcb);
+}
+
+/* Find the oldest lsn from active clients. */
+static inline void oldest_client_lsn(const struct CLIENT_REC *ca,
+ __le16 next_client, u64 *oldest_lsn)
+{
+ while (next_client != LFS_NO_CLIENT_LE) {
+ const struct CLIENT_REC *cr = ca + le16_to_cpu(next_client);
+ u64 lsn = le64_to_cpu(cr->oldest_lsn);
+
+ /* Ignore this block if it's oldest lsn is 0. */
+ if (lsn && lsn < *oldest_lsn)
+ *oldest_lsn = lsn;
+
+ next_client = cr->next_client;
+ }
+}
+
+static inline bool is_rst_page_hdr_valid(u32 file_off,
+ const struct RESTART_HDR *rhdr)
+{
+ u32 sys_page = le32_to_cpu(rhdr->sys_page_size);
+ u32 page_size = le32_to_cpu(rhdr->page_size);
+ u32 end_usa;
+ u16 ro;
+
+ if (sys_page < SECTOR_SIZE || page_size < SECTOR_SIZE ||
+ sys_page & (sys_page - 1) || page_size & (page_size - 1)) {
+ return false;
+ }
+
+ /* Check that if the file offset isn't 0, it is the system page size. */
+ if (file_off && file_off != sys_page)
+ return false;
+
+ /* Check support version 1.1+. */
+ if (le16_to_cpu(rhdr->major_ver) <= 1 && !rhdr->minor_ver)
+ return false;
+
+ if (le16_to_cpu(rhdr->major_ver) > 2)
+ return false;
+
+ ro = le16_to_cpu(rhdr->ra_off);
+ if (!IS_ALIGNED(ro, 8) || ro > sys_page)
+ return false;
+
+ end_usa = ((sys_page >> SECTOR_SHIFT) + 1) * sizeof(short);
+ end_usa += le16_to_cpu(rhdr->rhdr.fix_off);
+
+ if (ro < end_usa)
+ return false;
+
+ return true;
+}
+
+static inline bool is_rst_area_valid(const struct RESTART_HDR *rhdr)
+{
+ const struct RESTART_AREA *ra;
+ u16 cl, fl, ul;
+ u32 off, l_size, file_dat_bits, file_size_round;
+ u16 ro = le16_to_cpu(rhdr->ra_off);
+ u32 sys_page = le32_to_cpu(rhdr->sys_page_size);
+
+ if (ro + offsetof(struct RESTART_AREA, l_size) >
+ SECTOR_SIZE - sizeof(short))
+ return false;
+
+ ra = Add2Ptr(rhdr, ro);
+ cl = le16_to_cpu(ra->log_clients);
+
+ if (cl > 1)
+ return false;
+
+ off = le16_to_cpu(ra->client_off);
+
+ if (!IS_ALIGNED(off, 8) || ro + off > SECTOR_SIZE - sizeof(short))
+ return false;
+
+ off += cl * sizeof(struct CLIENT_REC);
+
+ if (off > sys_page)
+ return false;
+
+ /*
+ * Check the restart length field and whether the entire
+ * restart area is contained that length.
+ */
+ if (le16_to_cpu(rhdr->ra_off) + le16_to_cpu(ra->ra_len) > sys_page ||
+ off > le16_to_cpu(ra->ra_len)) {
+ return false;
+ }
+
+ /*
+ * As a final check make sure that the use list and the free list
+ * are either empty or point to a valid client.
+ */
+ fl = le16_to_cpu(ra->client_idx[0]);
+ ul = le16_to_cpu(ra->client_idx[1]);
+ if ((fl != LFS_NO_CLIENT && fl >= cl) ||
+ (ul != LFS_NO_CLIENT && ul >= cl))
+ return false;
+
+ /* Make sure the sequence number bits match the log file size. */
+ l_size = le64_to_cpu(ra->l_size);
+
+ file_dat_bits = sizeof(u64) * 8 - le32_to_cpu(ra->seq_num_bits);
+ file_size_round = 1u << (file_dat_bits + 3);
+ if (file_size_round != l_size &&
+ (file_size_round < l_size || (file_size_round / 2) > l_size)) {
+ return false;
+ }
+
+ /* The log page data offset and record header length must be quad-aligned. */
+ if (!IS_ALIGNED(le16_to_cpu(ra->data_off), 8) ||
+ !IS_ALIGNED(le16_to_cpu(ra->rec_hdr_len), 8))
+ return false;
+
+ return true;
+}
+
+static inline bool is_client_area_valid(const struct RESTART_HDR *rhdr,
+ bool usa_error)
+{
+ u16 ro = le16_to_cpu(rhdr->ra_off);
+ const struct RESTART_AREA *ra = Add2Ptr(rhdr, ro);
+ u16 ra_len = le16_to_cpu(ra->ra_len);
+ const struct CLIENT_REC *ca;
+ u32 i;
+
+ if (usa_error && ra_len + ro > SECTOR_SIZE - sizeof(short))
+ return false;
+
+ /* Find the start of the client array. */
+ ca = Add2Ptr(ra, le16_to_cpu(ra->client_off));
+
+ /*
+ * Start with the free list.
+ * Check that all the clients are valid and that there isn't a cycle.
+ * Do the in-use list on the second pass.
+ */
+ for (i = 0; i < 2; i++) {
+ u16 client_idx = le16_to_cpu(ra->client_idx[i]);
+ bool first_client = true;
+ u16 clients = le16_to_cpu(ra->log_clients);
+
+ while (client_idx != LFS_NO_CLIENT) {
+ const struct CLIENT_REC *cr;
+
+ if (!clients ||
+ client_idx >= le16_to_cpu(ra->log_clients))
+ return false;
+
+ clients -= 1;
+ cr = ca + client_idx;
+
+ client_idx = le16_to_cpu(cr->next_client);
+
+ if (first_client) {
+ first_client = false;
+ if (cr->prev_client != LFS_NO_CLIENT_LE)
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/*
+ * remove_client
+ *
+ * Remove a client record from a client record list an restart area.
+ */
+static inline void remove_client(struct CLIENT_REC *ca,
+ const struct CLIENT_REC *cr, __le16 *head)
+{
+ if (cr->prev_client == LFS_NO_CLIENT_LE)
+ *head = cr->next_client;
+ else
+ ca[le16_to_cpu(cr->prev_client)].next_client = cr->next_client;
+
+ if (cr->next_client != LFS_NO_CLIENT_LE)
+ ca[le16_to_cpu(cr->next_client)].prev_client = cr->prev_client;
+}
+
+/*
+ * add_client - Add a client record to the start of a list.
+ */
+static inline void add_client(struct CLIENT_REC *ca, u16 index, __le16 *head)
+{
+ struct CLIENT_REC *cr = ca + index;
+
+ cr->prev_client = LFS_NO_CLIENT_LE;
+ cr->next_client = *head;
+
+ if (*head != LFS_NO_CLIENT_LE)
+ ca[le16_to_cpu(*head)].prev_client = cpu_to_le16(index);
+
+ *head = cpu_to_le16(index);
+}
+
+static inline void *enum_rstbl(struct RESTART_TABLE *t, void *c)
+{
+ __le32 *e;
+ u32 bprt;
+ u16 rsize = t ? le16_to_cpu(t->size) : 0;
+
+ if (!c) {
+ if (!t || !t->total)
+ return NULL;
+ e = Add2Ptr(t, sizeof(struct RESTART_TABLE));
+ } else {
+ e = Add2Ptr(c, rsize);
+ }
+
+ /* Loop until we hit the first one allocated, or the end of the list. */
+ for (bprt = bytes_per_rt(t); PtrOffset(t, e) < bprt;
+ e = Add2Ptr(e, rsize)) {
+ if (*e == RESTART_ENTRY_ALLOCATED_LE)
+ return e;
+ }
+ return NULL;
+}
+
+/*
+ * find_dp - Search for a @vcn in Dirty Page Table.
+ */
+static inline struct DIR_PAGE_ENTRY *find_dp(struct RESTART_TABLE *dptbl,
+ u32 target_attr, u64 vcn)
+{
+ __le32 ta = cpu_to_le32(target_attr);
+ struct DIR_PAGE_ENTRY *dp = NULL;
+
+ while ((dp = enum_rstbl(dptbl, dp))) {
+ u64 dp_vcn = le64_to_cpu(dp->vcn);
+
+ if (dp->target_attr == ta && vcn >= dp_vcn &&
+ vcn < dp_vcn + le32_to_cpu(dp->lcns_follow)) {
+ return dp;
+ }
+ }
+ return NULL;
+}
+
+static inline u32 norm_file_page(u32 page_size, u32 *l_size, bool use_default)
+{
+ if (use_default)
+ page_size = DefaultLogPageSize;
+
+ /* Round the file size down to a system page boundary. */
+ *l_size &= ~(page_size - 1);
+
+ /* File should contain at least 2 restart pages and MinLogRecordPages pages. */
+ if (*l_size < (MinLogRecordPages + 2) * page_size)
+ return 0;
+
+ return page_size;
+}
+
+static bool check_log_rec(const struct LOG_REC_HDR *lr, u32 bytes, u32 tr,
+ u32 bytes_per_attr_entry)
+{
+ u16 t16;
+
+ if (bytes < sizeof(struct LOG_REC_HDR))
+ return false;
+ if (!tr)
+ return false;
+
+ if ((tr - sizeof(struct RESTART_TABLE)) %
+ sizeof(struct TRANSACTION_ENTRY))
+ return false;
+
+ if (le16_to_cpu(lr->redo_off) & 7)
+ return false;
+
+ if (le16_to_cpu(lr->undo_off) & 7)
+ return false;
+
+ if (lr->target_attr)
+ goto check_lcns;
+
+ if (is_target_required(le16_to_cpu(lr->redo_op)))
+ return false;
+
+ if (is_target_required(le16_to_cpu(lr->undo_op)))
+ return false;
+
+check_lcns:
+ if (!lr->lcns_follow)
+ goto check_length;
+
+ t16 = le16_to_cpu(lr->target_attr);
+ if ((t16 - sizeof(struct RESTART_TABLE)) % bytes_per_attr_entry)
+ return false;
+
+check_length:
+ if (bytes < lrh_length(lr))
+ return false;
+
+ return true;
+}
+
+static bool check_rstbl(const struct RESTART_TABLE *rt, size_t bytes)
+{
+ u32 ts;
+ u32 i, off;
+ u16 rsize = le16_to_cpu(rt->size);
+ u16 ne = le16_to_cpu(rt->used);
+ u32 ff = le32_to_cpu(rt->first_free);
+ u32 lf = le32_to_cpu(rt->last_free);
+
+ ts = rsize * ne + sizeof(struct RESTART_TABLE);
+
+ if (!rsize || rsize > bytes ||
+ rsize + sizeof(struct RESTART_TABLE) > bytes || bytes < ts ||
+ le16_to_cpu(rt->total) > ne || ff > ts || lf > ts ||
+ (ff && ff < sizeof(struct RESTART_TABLE)) ||
+ (lf && lf < sizeof(struct RESTART_TABLE))) {
+ return false;
+ }
+
+ /*
+ * Verify each entry is either allocated or points
+ * to a valid offset the table.
+ */
+ for (i = 0; i < ne; i++) {
+ off = le32_to_cpu(*(__le32 *)Add2Ptr(
+ rt, i * rsize + sizeof(struct RESTART_TABLE)));
+
+ if (off != RESTART_ENTRY_ALLOCATED && off &&
+ (off < sizeof(struct RESTART_TABLE) ||
+ ((off - sizeof(struct RESTART_TABLE)) % rsize))) {
+ return false;
+ }
+ }
+
+ /*
+ * Walk through the list headed by the first entry to make
+ * sure none of the entries are currently being used.
+ */
+ for (off = ff; off;) {
+ if (off == RESTART_ENTRY_ALLOCATED)
+ return false;
+
+ off = le32_to_cpu(*(__le32 *)Add2Ptr(rt, off));
+ }
+
+ return true;
+}
+
+/*
+ * free_rsttbl_idx - Free a previously allocated index a Restart Table.
+ */
+static inline void free_rsttbl_idx(struct RESTART_TABLE *rt, u32 off)
+{
+ __le32 *e;
+ u32 lf = le32_to_cpu(rt->last_free);
+ __le32 off_le = cpu_to_le32(off);
+
+ e = Add2Ptr(rt, off);
+
+ if (off < le32_to_cpu(rt->free_goal)) {
+ *e = rt->first_free;
+ rt->first_free = off_le;
+ if (!lf)
+ rt->last_free = off_le;
+ } else {
+ if (lf)
+ *(__le32 *)Add2Ptr(rt, lf) = off_le;
+ else
+ rt->first_free = off_le;
+
+ rt->last_free = off_le;
+ *e = 0;
+ }
+
+ le16_sub_cpu(&rt->total, 1);
+}
+
+static inline struct RESTART_TABLE *init_rsttbl(u16 esize, u16 used)
+{
+ __le32 *e, *last_free;
+ u32 off;
+ u32 bytes = esize * used + sizeof(struct RESTART_TABLE);
+ u32 lf = sizeof(struct RESTART_TABLE) + (used - 1) * esize;
+ struct RESTART_TABLE *t = kzalloc(bytes, GFP_NOFS);
+
+ if (!t)
+ return NULL;
+
+ t->size = cpu_to_le16(esize);
+ t->used = cpu_to_le16(used);
+ t->free_goal = cpu_to_le32(~0u);
+ t->first_free = cpu_to_le32(sizeof(struct RESTART_TABLE));
+ t->last_free = cpu_to_le32(lf);
+
+ e = (__le32 *)(t + 1);
+ last_free = Add2Ptr(t, lf);
+
+ for (off = sizeof(struct RESTART_TABLE) + esize; e < last_free;
+ e = Add2Ptr(e, esize), off += esize) {
+ *e = cpu_to_le32(off);
+ }
+ return t;
+}
+
+static inline struct RESTART_TABLE *extend_rsttbl(struct RESTART_TABLE *tbl,
+ u32 add, u32 free_goal)
+{
+ u16 esize = le16_to_cpu(tbl->size);
+ __le32 osize = cpu_to_le32(bytes_per_rt(tbl));
+ u32 used = le16_to_cpu(tbl->used);
+ struct RESTART_TABLE *rt;
+
+ rt = init_rsttbl(esize, used + add);
+ if (!rt)
+ return NULL;
+
+ memcpy(rt + 1, tbl + 1, esize * used);
+
+ rt->free_goal = free_goal == ~0u
+ ? cpu_to_le32(~0u)
+ : cpu_to_le32(sizeof(struct RESTART_TABLE) +
+ free_goal * esize);
+
+ if (tbl->first_free) {
+ rt->first_free = tbl->first_free;
+ *(__le32 *)Add2Ptr(rt, le32_to_cpu(tbl->last_free)) = osize;
+ } else {
+ rt->first_free = osize;
+ }
+
+ rt->total = tbl->total;
+
+ kfree(tbl);
+ return rt;
+}
+
+/*
+ * alloc_rsttbl_idx
+ *
+ * Allocate an index from within a previously initialized Restart Table.
+ */
+static inline void *alloc_rsttbl_idx(struct RESTART_TABLE **tbl)
+{
+ u32 off;
+ __le32 *e;
+ struct RESTART_TABLE *t = *tbl;
+
+ if (!t->first_free) {
+ *tbl = t = extend_rsttbl(t, 16, ~0u);
+ if (!t)
+ return NULL;
+ }
+
+ off = le32_to_cpu(t->first_free);
+
+ /* Dequeue this entry and zero it. */
+ e = Add2Ptr(t, off);
+
+ t->first_free = *e;
+
+ memset(e, 0, le16_to_cpu(t->size));
+
+ *e = RESTART_ENTRY_ALLOCATED_LE;
+
+ /* If list is going empty, then we fix the last_free as well. */
+ if (!t->first_free)
+ t->last_free = 0;
+
+ le16_add_cpu(&t->total, 1);
+
+ return Add2Ptr(t, off);
+}
+
+/*
+ * alloc_rsttbl_from_idx
+ *
+ * Allocate a specific index from within a previously initialized Restart Table.
+ */
+static inline void *alloc_rsttbl_from_idx(struct RESTART_TABLE **tbl, u32 vbo)
+{
+ u32 off;
+ __le32 *e;
+ struct RESTART_TABLE *rt = *tbl;
+ u32 bytes = bytes_per_rt(rt);
+ u16 esize = le16_to_cpu(rt->size);
+
+ /* If the entry is not the table, we will have to extend the table. */
+ if (vbo >= bytes) {
+ /*
+ * Extend the size by computing the number of entries between
+ * the existing size and the desired index and adding 1 to that.
+ */
+ u32 bytes2idx = vbo - bytes;
+
+ /*
+ * There should always be an integral number of entries
+ * being added. Now extend the table.
+ */
+ *tbl = rt = extend_rsttbl(rt, bytes2idx / esize + 1, bytes);
+ if (!rt)
+ return NULL;
+ }
+
+ /* See if the entry is already allocated, and just return if it is. */
+ e = Add2Ptr(rt, vbo);
+
+ if (*e == RESTART_ENTRY_ALLOCATED_LE)
+ return e;
+
+ /*
+ * Walk through the table, looking for the entry we're
+ * interested and the previous entry.
+ */
+ off = le32_to_cpu(rt->first_free);
+ e = Add2Ptr(rt, off);
+
+ if (off == vbo) {
+ /* this is a match */
+ rt->first_free = *e;
+ goto skip_looking;
+ }
+
+ /*
+ * Need to walk through the list looking for the predecessor
+ * of our entry.
+ */
+ for (;;) {
+ /* Remember the entry just found */
+ u32 last_off = off;
+ __le32 *last_e = e;
+
+ /* Should never run of entries. */
+
+ /* Lookup up the next entry the list. */
+ off = le32_to_cpu(*last_e);
+ e = Add2Ptr(rt, off);
+
+ /* If this is our match we are done. */
+ if (off == vbo) {
+ *last_e = *e;
+
+ /*
+ * If this was the last entry, we update that
+ * table as well.
+ */
+ if (le32_to_cpu(rt->last_free) == off)
+ rt->last_free = cpu_to_le32(last_off);
+ break;
+ }
+ }
+
+skip_looking:
+ /* If the list is now empty, we fix the last_free as well. */
+ if (!rt->first_free)
+ rt->last_free = 0;
+
+ /* Zero this entry. */
+ memset(e, 0, esize);
+ *e = RESTART_ENTRY_ALLOCATED_LE;
+
+ le16_add_cpu(&rt->total, 1);
+
+ return e;
+}
+
+#define RESTART_SINGLE_PAGE_IO cpu_to_le16(0x0001)
+
+#define NTFSLOG_WRAPPED 0x00000001
+#define NTFSLOG_MULTIPLE_PAGE_IO 0x00000002
+#define NTFSLOG_NO_LAST_LSN 0x00000004
+#define NTFSLOG_REUSE_TAIL 0x00000010
+#define NTFSLOG_NO_OLDEST_LSN 0x00000020
+
+/* Helper struct to work with NTFS $LogFile. */
+struct ntfs_log {
+ struct ntfs_inode *ni;
+
+ u32 l_size;
+ u32 sys_page_size;
+ u32 sys_page_mask;
+ u32 page_size;
+ u32 page_mask; // page_size - 1
+ u8 page_bits;
+ struct RECORD_PAGE_HDR *one_page_buf;
+
+ struct RESTART_TABLE *open_attr_tbl;
+ u32 transaction_id;
+ u32 clst_per_page;
+
+ u32 first_page;
+ u32 next_page;
+ u32 ra_off;
+ u32 data_off;
+ u32 restart_size;
+ u32 data_size;
+ u16 record_header_len;
+ u64 seq_num;
+ u32 seq_num_bits;
+ u32 file_data_bits;
+ u32 seq_num_mask; /* (1 << file_data_bits) - 1 */
+
+ struct RESTART_AREA *ra; /* In-memory image of the next restart area. */
+ u32 ra_size; /* The usable size of the restart area. */
+
+ /*
+ * If true, then the in-memory restart area is to be written
+ * to the first position on the disk.
+ */
+ bool init_ra;
+ bool set_dirty; /* True if we need to set dirty flag. */
+
+ u64 oldest_lsn;
+
+ u32 oldest_lsn_off;
+ u64 last_lsn;
+
+ u32 total_avail;
+ u32 total_avail_pages;
+ u32 total_undo_commit;
+ u32 max_current_avail;
+ u32 current_avail;
+ u32 reserved;
+
+ short major_ver;
+ short minor_ver;
+
+ u32 l_flags; /* See NTFSLOG_XXX */
+ u32 current_openlog_count; /* On-disk value for open_log_count. */
+
+ struct CLIENT_ID client_id;
+ u32 client_undo_commit;
+};
+
+static inline u32 lsn_to_vbo(struct ntfs_log *log, const u64 lsn)
+{
+ u32 vbo = (lsn << log->seq_num_bits) >> (log->seq_num_bits - 3);
+
+ return vbo;
+}
+
+/* Compute the offset in the log file of the next log page. */
+static inline u32 next_page_off(struct ntfs_log *log, u32 off)
+{
+ off = (off & ~log->sys_page_mask) + log->page_size;
+ return off >= log->l_size ? log->first_page : off;
+}
+
+static inline u32 lsn_to_page_off(struct ntfs_log *log, u64 lsn)
+{
+ return (((u32)lsn) << 3) & log->page_mask;
+}
+
+static inline u64 vbo_to_lsn(struct ntfs_log *log, u32 off, u64 Seq)
+{
+ return (off >> 3) + (Seq << log->file_data_bits);
+}
+
+static inline bool is_lsn_in_file(struct ntfs_log *log, u64 lsn)
+{
+ return lsn >= log->oldest_lsn &&
+ lsn <= le64_to_cpu(log->ra->current_lsn);
+}
+
+static inline u32 hdr_file_off(struct ntfs_log *log,
+ struct RECORD_PAGE_HDR *hdr)
+{
+ if (log->major_ver < 2)
+ return le64_to_cpu(hdr->rhdr.lsn);
+
+ return le32_to_cpu(hdr->file_off);
+}
+
+static inline u64 base_lsn(struct ntfs_log *log,
+ const struct RECORD_PAGE_HDR *hdr, u64 lsn)
+{
+ u64 h_lsn = le64_to_cpu(hdr->rhdr.lsn);
+ u64 ret = (((h_lsn >> log->file_data_bits) +
+ (lsn < (lsn_to_vbo(log, h_lsn) & ~log->page_mask) ? 1 : 0))
+ << log->file_data_bits) +
+ ((((is_log_record_end(hdr) &&
+ h_lsn <= le64_to_cpu(hdr->record_hdr.last_end_lsn))
+ ? le16_to_cpu(hdr->record_hdr.next_record_off)
+ : log->page_size) +
+ lsn) >>
+ 3);
+
+ return ret;
+}
+
+static inline bool verify_client_lsn(struct ntfs_log *log,
+ const struct CLIENT_REC *client, u64 lsn)
+{
+ return lsn >= le64_to_cpu(client->oldest_lsn) &&
+ lsn <= le64_to_cpu(log->ra->current_lsn) && lsn;
+}
+
+struct restart_info {
+ u64 last_lsn;
+ struct RESTART_HDR *r_page;
+ u32 vbo;
+ bool chkdsk_was_run;
+ bool valid_page;
+ bool initialized;
+ bool restart;
+};
+
+static int read_log_page(struct ntfs_log *log, u32 vbo,
+ struct RECORD_PAGE_HDR **buffer, bool *usa_error)
+{
+ int err = 0;
+ u32 page_idx = vbo >> log->page_bits;
+ u32 page_off = vbo & log->page_mask;
+ u32 bytes = log->page_size - page_off;
+ void *to_free = NULL;
+ u32 page_vbo = page_idx << log->page_bits;
+ struct RECORD_PAGE_HDR *page_buf;
+ struct ntfs_inode *ni = log->ni;
+ bool bBAAD;
+
+ if (vbo >= log->l_size)
+ return -EINVAL;
+
+ if (!*buffer) {
+ to_free = kmalloc(bytes, GFP_NOFS);
+ if (!to_free)
+ return -ENOMEM;
+ *buffer = to_free;
+ }
+
+ page_buf = page_off ? log->one_page_buf : *buffer;
+
+ err = ntfs_read_run_nb(ni->mi.sbi, &ni->file.run, page_vbo, page_buf,
+ log->page_size, NULL);
+ if (err)
+ goto out;
+
+ if (page_buf->rhdr.sign != NTFS_FFFF_SIGNATURE)
+ ntfs_fix_post_read(&page_buf->rhdr, PAGE_SIZE, false);
+
+ if (page_buf != *buffer)
+ memcpy(*buffer, Add2Ptr(page_buf, page_off), bytes);
+
+ bBAAD = page_buf->rhdr.sign == NTFS_BAAD_SIGNATURE;
+
+ if (usa_error)
+ *usa_error = bBAAD;
+ /* Check that the update sequence array for this page is valid */
+ /* If we don't allow errors, raise an error status */
+ else if (bBAAD)
+ err = -EINVAL;
+
+out:
+ if (err && to_free) {
+ kfree(to_free);
+ *buffer = NULL;
+ }
+
+ return err;
+}
+
+/*
+ * log_read_rst
+ *
+ * It walks through 512 blocks of the file looking for a valid
+ * restart page header. It will stop the first time we find a
+ * valid page header.
+ */
+static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
+ struct restart_info *info)
+{
+ u32 skip, vbo;
+ struct RESTART_HDR *r_page = kmalloc(DefaultLogPageSize, GFP_NOFS);
+
+ if (!r_page)
+ return -ENOMEM;
+
+ memset(info, 0, sizeof(struct restart_info));
+
+ /* Determine which restart area we are looking for. */
+ if (first) {
+ vbo = 0;
+ skip = 512;
+ } else {
+ vbo = 512;
+ skip = 0;
+ }
+
+ /* Loop continuously until we succeed. */
+ for (; vbo < l_size; vbo = 2 * vbo + skip, skip = 0) {
+ bool usa_error;
+ u32 sys_page_size;
+ bool brst, bchk;
+ struct RESTART_AREA *ra;
+
+ /* Read a page header at the current offset. */
+ if (read_log_page(log, vbo, (struct RECORD_PAGE_HDR **)&r_page,
+ &usa_error)) {
+ /* Ignore any errors. */
+ continue;
+ }
+
+ /* Exit if the signature is a log record page. */
+ if (r_page->rhdr.sign == NTFS_RCRD_SIGNATURE) {
+ info->initialized = true;
+ break;
+ }
+
+ brst = r_page->rhdr.sign == NTFS_RSTR_SIGNATURE;
+ bchk = r_page->rhdr.sign == NTFS_CHKD_SIGNATURE;
+
+ if (!bchk && !brst) {
+ if (r_page->rhdr.sign != NTFS_FFFF_SIGNATURE) {
+ /*
+ * Remember if the signature does not
+ * indicate uninitialized file.
+ */
+ info->initialized = true;
+ }
+ continue;
+ }
+
+ ra = NULL;
+ info->valid_page = false;
+ info->initialized = true;
+ info->vbo = vbo;
+
+ /* Let's check the restart area if this is a valid page. */
+ if (!is_rst_page_hdr_valid(vbo, r_page))
+ goto check_result;
+ ra = Add2Ptr(r_page, le16_to_cpu(r_page->ra_off));
+
+ if (!is_rst_area_valid(r_page))
+ goto check_result;
+
+ /*
+ * We have a valid restart page header and restart area.
+ * If chkdsk was run or we have no clients then we have
+ * no more checking to do.
+ */
+ if (bchk || ra->client_idx[1] == LFS_NO_CLIENT_LE) {
+ info->valid_page = true;
+ goto check_result;
+ }
+
+ /* Read the entire restart area. */
+ sys_page_size = le32_to_cpu(r_page->sys_page_size);
+ if (DefaultLogPageSize != sys_page_size) {
+ kfree(r_page);
+ r_page = kzalloc(sys_page_size, GFP_NOFS);
+ if (!r_page)
+ return -ENOMEM;
+
+ if (read_log_page(log, vbo,
+ (struct RECORD_PAGE_HDR **)&r_page,
+ &usa_error)) {
+ /* Ignore any errors. */
+ kfree(r_page);
+ r_page = NULL;
+ continue;
+ }
+ }
+
+ if (is_client_area_valid(r_page, usa_error)) {
+ info->valid_page = true;
+ ra = Add2Ptr(r_page, le16_to_cpu(r_page->ra_off));
+ }
+
+check_result:
+ /*
+ * If chkdsk was run then update the caller's
+ * values and return.
+ */
+ if (r_page->rhdr.sign == NTFS_CHKD_SIGNATURE) {
+ info->chkdsk_was_run = true;
+ info->last_lsn = le64_to_cpu(r_page->rhdr.lsn);
+ info->restart = true;
+ info->r_page = r_page;
+ return 0;
+ }
+
+ /*
+ * If we have a valid page then copy the values
+ * we need from it.
+ */
+ if (info->valid_page) {
+ info->last_lsn = le64_to_cpu(ra->current_lsn);
+ info->restart = true;
+ info->r_page = r_page;
+ return 0;
+ }
+ }
+
+ kfree(r_page);
+
+ return 0;
+}
+
+/*
+ * Ilog_init_pg_hdr - Init @log from restart page header.
+ */
+static void log_init_pg_hdr(struct ntfs_log *log, u32 sys_page_size,
+ u32 page_size, u16 major_ver, u16 minor_ver)
+{
+ log->sys_page_size = sys_page_size;
+ log->sys_page_mask = sys_page_size - 1;
+ log->page_size = page_size;
+ log->page_mask = page_size - 1;
+ log->page_bits = blksize_bits(page_size);
+
+ log->clst_per_page = log->page_size >> log->ni->mi.sbi->cluster_bits;
+ if (!log->clst_per_page)
+ log->clst_per_page = 1;
+
+ log->first_page = major_ver >= 2
+ ? 0x22 * page_size
+ : ((sys_page_size << 1) + (page_size << 1));
+ log->major_ver = major_ver;
+ log->minor_ver = minor_ver;
+}
+
+/*
+ * log_create - Init @log in cases when we don't have a restart area to use.
+ */
+static void log_create(struct ntfs_log *log, u32 l_size, const u64 last_lsn,
+ u32 open_log_count, bool wrapped, bool use_multi_page)
+{
+ log->l_size = l_size;
+ /* All file offsets must be quadword aligned. */
+ log->file_data_bits = blksize_bits(l_size) - 3;
+ log->seq_num_mask = (8 << log->file_data_bits) - 1;
+ log->seq_num_bits = sizeof(u64) * 8 - log->file_data_bits;
+ log->seq_num = (last_lsn >> log->file_data_bits) + 2;
+ log->next_page = log->first_page;
+ log->oldest_lsn = log->seq_num << log->file_data_bits;
+ log->oldest_lsn_off = 0;
+ log->last_lsn = log->oldest_lsn;
+
+ log->l_flags |= NTFSLOG_NO_LAST_LSN | NTFSLOG_NO_OLDEST_LSN;
+
+ /* Set the correct flags for the I/O and indicate if we have wrapped. */
+ if (wrapped)
+ log->l_flags |= NTFSLOG_WRAPPED;
+
+ if (use_multi_page)
+ log->l_flags |= NTFSLOG_MULTIPLE_PAGE_IO;
+
+ /* Compute the log page values. */
+ log->data_off = ALIGN(
+ offsetof(struct RECORD_PAGE_HDR, fixups) +
+ sizeof(short) * ((log->page_size >> SECTOR_SHIFT) + 1),
+ 8);
+ log->data_size = log->page_size - log->data_off;
+ log->record_header_len = sizeof(struct LFS_RECORD_HDR);
+
+ /* Remember the different page sizes for reservation. */
+ log->reserved = log->data_size - log->record_header_len;
+
+ /* Compute the restart page values. */
+ log->ra_off = ALIGN(
+ offsetof(struct RESTART_HDR, fixups) +
+ sizeof(short) *
+ ((log->sys_page_size >> SECTOR_SHIFT) + 1),
+ 8);
+ log->restart_size = log->sys_page_size - log->ra_off;
+ log->ra_size = struct_size(log->ra, clients, 1);
+ log->current_openlog_count = open_log_count;
+
+ /*
+ * The total available log file space is the number of
+ * log file pages times the space available on each page.
+ */
+ log->total_avail_pages = log->l_size - log->first_page;
+ log->total_avail = log->total_avail_pages >> log->page_bits;
+
+ /*
+ * We assume that we can't use the end of the page less than
+ * the file record size.
+ * Then we won't need to reserve more than the caller asks for.
+ */
+ log->max_current_avail = log->total_avail * log->reserved;
+ log->total_avail = log->total_avail * log->data_size;
+ log->current_avail = log->max_current_avail;
+}
+
+/*
+ * log_create_ra - Fill a restart area from the values stored in @log.
+ */
+static struct RESTART_AREA *log_create_ra(struct ntfs_log *log)
+{
+ struct CLIENT_REC *cr;
+ struct RESTART_AREA *ra = kzalloc(log->restart_size, GFP_NOFS);
+
+ if (!ra)
+ return NULL;
+
+ ra->current_lsn = cpu_to_le64(log->last_lsn);
+ ra->log_clients = cpu_to_le16(1);
+ ra->client_idx[1] = LFS_NO_CLIENT_LE;
+ if (log->l_flags & NTFSLOG_MULTIPLE_PAGE_IO)
+ ra->flags = RESTART_SINGLE_PAGE_IO;
+ ra->seq_num_bits = cpu_to_le32(log->seq_num_bits);
+ ra->ra_len = cpu_to_le16(log->ra_size);
+ ra->client_off = cpu_to_le16(offsetof(struct RESTART_AREA, clients));
+ ra->l_size = cpu_to_le64(log->l_size);
+ ra->rec_hdr_len = cpu_to_le16(log->record_header_len);
+ ra->data_off = cpu_to_le16(log->data_off);
+ ra->open_log_count = cpu_to_le32(log->current_openlog_count + 1);
+
+ cr = ra->clients;
+
+ cr->prev_client = LFS_NO_CLIENT_LE;
+ cr->next_client = LFS_NO_CLIENT_LE;
+
+ return ra;
+}
+
+static u32 final_log_off(struct ntfs_log *log, u64 lsn, u32 data_len)
+{
+ u32 base_vbo = lsn << 3;
+ u32 final_log_off = (base_vbo & log->seq_num_mask) & ~log->page_mask;
+ u32 page_off = base_vbo & log->page_mask;
+ u32 tail = log->page_size - page_off;
+
+ page_off -= 1;
+
+ /* Add the length of the header. */
+ data_len += log->record_header_len;
+
+ /*
+ * If this lsn is contained this log page we are done.
+ * Otherwise we need to walk through several log pages.
+ */
+ if (data_len > tail) {
+ data_len -= tail;
+ tail = log->data_size;
+ page_off = log->data_off - 1;
+
+ for (;;) {
+ final_log_off = next_page_off(log, final_log_off);
+
+ /*
+ * We are done if the remaining bytes
+ * fit on this page.
+ */
+ if (data_len <= tail)
+ break;
+ data_len -= tail;
+ }
+ }
+
+ /*
+ * We add the remaining bytes to our starting position on this page
+ * and then add that value to the file offset of this log page.
+ */
+ return final_log_off + data_len + page_off;
+}
+
+static int next_log_lsn(struct ntfs_log *log, const struct LFS_RECORD_HDR *rh,
+ u64 *lsn)
+{
+ int err;
+ u64 this_lsn = le64_to_cpu(rh->this_lsn);
+ u32 vbo = lsn_to_vbo(log, this_lsn);
+ u32 end =
+ final_log_off(log, this_lsn, le32_to_cpu(rh->client_data_len));
+ u32 hdr_off = end & ~log->sys_page_mask;
+ u64 seq = this_lsn >> log->file_data_bits;
+ struct RECORD_PAGE_HDR *page = NULL;
+
+ /* Remember if we wrapped. */
+ if (end <= vbo)
+ seq += 1;
+
+ /* Log page header for this page. */
+ err = read_log_page(log, hdr_off, &page, NULL);
+ if (err)
+ return err;
+
+ /*
+ * If the lsn we were given was not the last lsn on this page,
+ * then the starting offset for the next lsn is on a quad word
+ * boundary following the last file offset for the current lsn.
+ * Otherwise the file offset is the start of the data on the next page.
+ */
+ if (this_lsn == le64_to_cpu(page->rhdr.lsn)) {
+ /* If we wrapped, we need to increment the sequence number. */
+ hdr_off = next_page_off(log, hdr_off);
+ if (hdr_off == log->first_page)
+ seq += 1;
+
+ vbo = hdr_off + log->data_off;
+ } else {
+ vbo = ALIGN(end, 8);
+ }
+
+ /* Compute the lsn based on the file offset and the sequence count. */
+ *lsn = vbo_to_lsn(log, vbo, seq);
+
+ /*
+ * If this lsn is within the legal range for the file, we return true.
+ * Otherwise false indicates that there are no more lsn's.
+ */
+ if (!is_lsn_in_file(log, *lsn))
+ *lsn = 0;
+
+ kfree(page);
+
+ return 0;
+}
+
+/*
+ * current_log_avail - Calculate the number of bytes available for log records.
+ */
+static u32 current_log_avail(struct ntfs_log *log)
+{
+ u32 oldest_off, next_free_off, free_bytes;
+
+ if (log->l_flags & NTFSLOG_NO_LAST_LSN) {
+ /* The entire file is available. */
+ return log->max_current_avail;
+ }
+
+ /*
+ * If there is a last lsn the restart area then we know that we will
+ * have to compute the free range.
+ * If there is no oldest lsn then start at the first page of the file.
+ */
+ oldest_off = (log->l_flags & NTFSLOG_NO_OLDEST_LSN)
+ ? log->first_page
+ : (log->oldest_lsn_off & ~log->sys_page_mask);
+
+ /*
+ * We will use the next log page offset to compute the next free page.
+ * If we are going to reuse this page go to the next page.
+ * If we are at the first page then use the end of the file.
+ */
+ next_free_off = (log->l_flags & NTFSLOG_REUSE_TAIL)
+ ? log->next_page + log->page_size
+ : log->next_page == log->first_page
+ ? log->l_size
+ : log->next_page;
+
+ /* If the two offsets are the same then there is no available space. */
+ if (oldest_off == next_free_off)
+ return 0;
+ /*
+ * If the free offset follows the oldest offset then subtract
+ * this range from the total available pages.
+ */
+ free_bytes =
+ oldest_off < next_free_off
+ ? log->total_avail_pages - (next_free_off - oldest_off)
+ : oldest_off - next_free_off;
+
+ free_bytes >>= log->page_bits;
+ return free_bytes * log->reserved;
+}
+
+static bool check_subseq_log_page(struct ntfs_log *log,
+ const struct RECORD_PAGE_HDR *rp, u32 vbo,
+ u64 seq)
+{
+ u64 lsn_seq;
+ const struct NTFS_RECORD_HEADER *rhdr = &rp->rhdr;
+ u64 lsn = le64_to_cpu(rhdr->lsn);
+
+ if (rhdr->sign == NTFS_FFFF_SIGNATURE || !rhdr->sign)
+ return false;
+
+ /*
+ * If the last lsn on the page occurs was written after the page
+ * that caused the original error then we have a fatal error.
+ */
+ lsn_seq = lsn >> log->file_data_bits;
+
+ /*
+ * If the sequence number for the lsn the page is equal or greater
+ * than lsn we expect, then this is a subsequent write.
+ */
+ return lsn_seq >= seq ||
+ (lsn_seq == seq - 1 && log->first_page == vbo &&
+ vbo != (lsn_to_vbo(log, lsn) & ~log->page_mask));
+}
+
+/*
+ * last_log_lsn
+ *
+ * Walks through the log pages for a file, searching for the
+ * last log page written to the file.
+ */
+static int last_log_lsn(struct ntfs_log *log)
+{
+ int err;
+ bool usa_error = false;
+ bool replace_page = false;
+ bool reuse_page = log->l_flags & NTFSLOG_REUSE_TAIL;
+ bool wrapped_file, wrapped;
+
+ u32 page_cnt = 1, page_pos = 1;
+ u32 page_off = 0, page_off1 = 0, saved_off = 0;
+ u32 final_off, second_off, final_off_prev = 0, second_off_prev = 0;
+ u32 first_file_off = 0, second_file_off = 0;
+ u32 part_io_count = 0;
+ u32 tails = 0;
+ u32 this_off, curpage_off, nextpage_off, remain_pages;
+
+ u64 expected_seq, seq_base = 0, lsn_base = 0;
+ u64 best_lsn, best_lsn1, best_lsn2;
+ u64 lsn_cur, lsn1, lsn2;
+ u64 last_ok_lsn = reuse_page ? log->last_lsn : 0;
+
+ u16 cur_pos, best_page_pos;
+
+ struct RECORD_PAGE_HDR *page = NULL;
+ struct RECORD_PAGE_HDR *tst_page = NULL;
+ struct RECORD_PAGE_HDR *first_tail = NULL;
+ struct RECORD_PAGE_HDR *second_tail = NULL;
+ struct RECORD_PAGE_HDR *tail_page = NULL;
+ struct RECORD_PAGE_HDR *second_tail_prev = NULL;
+ struct RECORD_PAGE_HDR *first_tail_prev = NULL;
+ struct RECORD_PAGE_HDR *page_bufs = NULL;
+ struct RECORD_PAGE_HDR *best_page;
+
+ if (log->major_ver >= 2) {
+ final_off = 0x02 * log->page_size;
+ second_off = 0x12 * log->page_size;
+
+ // 0x10 == 0x12 - 0x2
+ page_bufs = kmalloc(log->page_size * 0x10, GFP_NOFS);
+ if (!page_bufs)
+ return -ENOMEM;
+ } else {
+ second_off = log->first_page - log->page_size;
+ final_off = second_off - log->page_size;
+ }
+
+next_tail:
+ /* Read second tail page (at pos 3/0x12000). */
+ if (read_log_page(log, second_off, &second_tail, &usa_error) ||
+ usa_error || second_tail->rhdr.sign != NTFS_RCRD_SIGNATURE) {
+ kfree(second_tail);
+ second_tail = NULL;
+ second_file_off = 0;
+ lsn2 = 0;
+ } else {
+ second_file_off = hdr_file_off(log, second_tail);
+ lsn2 = le64_to_cpu(second_tail->record_hdr.last_end_lsn);
+ }
+
+ /* Read first tail page (at pos 2/0x2000). */
+ if (read_log_page(log, final_off, &first_tail, &usa_error) ||
+ usa_error || first_tail->rhdr.sign != NTFS_RCRD_SIGNATURE) {
+ kfree(first_tail);
+ first_tail = NULL;
+ first_file_off = 0;
+ lsn1 = 0;
+ } else {
+ first_file_off = hdr_file_off(log, first_tail);
+ lsn1 = le64_to_cpu(first_tail->record_hdr.last_end_lsn);
+ }
+
+ if (log->major_ver < 2) {
+ int best_page;
+
+ first_tail_prev = first_tail;
+ final_off_prev = first_file_off;
+ second_tail_prev = second_tail;
+ second_off_prev = second_file_off;
+ tails = 1;
+
+ if (!first_tail && !second_tail)
+ goto tail_read;
+
+ if (first_tail && second_tail)
+ best_page = lsn1 < lsn2 ? 1 : 0;
+ else if (first_tail)
+ best_page = 0;
+ else
+ best_page = 1;
+
+ page_off = best_page ? second_file_off : first_file_off;
+ seq_base = (best_page ? lsn2 : lsn1) >> log->file_data_bits;
+ goto tail_read;
+ }
+
+ best_lsn1 = first_tail ? base_lsn(log, first_tail, first_file_off) : 0;
+ best_lsn2 =
+ second_tail ? base_lsn(log, second_tail, second_file_off) : 0;
+
+ if (first_tail && second_tail) {
+ if (best_lsn1 > best_lsn2) {
+ best_lsn = best_lsn1;
+ best_page = first_tail;
+ this_off = first_file_off;
+ } else {
+ best_lsn = best_lsn2;
+ best_page = second_tail;
+ this_off = second_file_off;
+ }
+ } else if (first_tail) {
+ best_lsn = best_lsn1;
+ best_page = first_tail;
+ this_off = first_file_off;
+ } else if (second_tail) {
+ best_lsn = best_lsn2;
+ best_page = second_tail;
+ this_off = second_file_off;
+ } else {
+ goto tail_read;
+ }
+
+ best_page_pos = le16_to_cpu(best_page->page_pos);
+
+ if (!tails) {
+ if (best_page_pos == page_pos) {
+ seq_base = best_lsn >> log->file_data_bits;
+ saved_off = page_off = le32_to_cpu(best_page->file_off);
+ lsn_base = best_lsn;
+
+ memmove(page_bufs, best_page, log->page_size);
+
+ page_cnt = le16_to_cpu(best_page->page_count);
+ if (page_cnt > 1)
+ page_pos += 1;
+
+ tails = 1;
+ }
+ } else if (seq_base == (best_lsn >> log->file_data_bits) &&
+ saved_off + log->page_size == this_off &&
+ lsn_base < best_lsn &&
+ (page_pos != page_cnt || best_page_pos == page_pos ||
+ best_page_pos == 1) &&
+ (page_pos >= page_cnt || best_page_pos == page_pos)) {
+ u16 bppc = le16_to_cpu(best_page->page_count);
+
+ saved_off += log->page_size;
+ lsn_base = best_lsn;
+
+ memmove(Add2Ptr(page_bufs, tails * log->page_size), best_page,
+ log->page_size);
+
+ tails += 1;
+
+ if (best_page_pos != bppc) {
+ page_cnt = bppc;
+ page_pos = best_page_pos;
+
+ if (page_cnt > 1)
+ page_pos += 1;
+ } else {
+ page_pos = page_cnt = 1;
+ }
+ } else {
+ kfree(first_tail);
+ kfree(second_tail);
+ goto tail_read;
+ }
+
+ kfree(first_tail_prev);
+ first_tail_prev = first_tail;
+ final_off_prev = first_file_off;
+ first_tail = NULL;
+
+ kfree(second_tail_prev);
+ second_tail_prev = second_tail;
+ second_off_prev = second_file_off;
+ second_tail = NULL;
+
+ final_off += log->page_size;
+ second_off += log->page_size;
+
+ if (tails < 0x10)
+ goto next_tail;
+tail_read:
+ first_tail = first_tail_prev;
+ final_off = final_off_prev;
+
+ second_tail = second_tail_prev;
+ second_off = second_off_prev;
+
+ page_cnt = page_pos = 1;
+
+ curpage_off = seq_base == log->seq_num ? min(log->next_page, page_off)
+ : log->next_page;
+
+ wrapped_file =
+ curpage_off == log->first_page &&
+ !(log->l_flags & (NTFSLOG_NO_LAST_LSN | NTFSLOG_REUSE_TAIL));
+
+ expected_seq = wrapped_file ? (log->seq_num + 1) : log->seq_num;
+
+ nextpage_off = curpage_off;
+
+next_page:
+ tail_page = NULL;
+ /* Read the next log page. */
+ err = read_log_page(log, curpage_off, &page, &usa_error);
+
+ /* Compute the next log page offset the file. */
+ nextpage_off = next_page_off(log, curpage_off);
+ wrapped = nextpage_off == log->first_page;
+
+ if (tails > 1) {
+ struct RECORD_PAGE_HDR *cur_page =
+ Add2Ptr(page_bufs, curpage_off - page_off);
+
+ if (curpage_off == saved_off) {
+ tail_page = cur_page;
+ goto use_tail_page;
+ }
+
+ if (page_off > curpage_off || curpage_off >= saved_off)
+ goto use_tail_page;
+
+ if (page_off1)
+ goto use_cur_page;
+
+ if (!err && !usa_error &&
+ page->rhdr.sign == NTFS_RCRD_SIGNATURE &&
+ cur_page->rhdr.lsn == page->rhdr.lsn &&
+ cur_page->record_hdr.next_record_off ==
+ page->record_hdr.next_record_off &&
+ ((page_pos == page_cnt &&
+ le16_to_cpu(page->page_pos) == 1) ||
+ (page_pos != page_cnt &&
+ le16_to_cpu(page->page_pos) == page_pos + 1 &&
+ le16_to_cpu(page->page_count) == page_cnt))) {
+ cur_page = NULL;
+ goto use_tail_page;
+ }
+
+ page_off1 = page_off;
+
+use_cur_page:
+
+ lsn_cur = le64_to_cpu(cur_page->rhdr.lsn);
+
+ if (last_ok_lsn !=
+ le64_to_cpu(cur_page->record_hdr.last_end_lsn) &&
+ ((lsn_cur >> log->file_data_bits) +
+ ((curpage_off <
+ (lsn_to_vbo(log, lsn_cur) & ~log->page_mask))
+ ? 1
+ : 0)) != expected_seq) {
+ goto check_tail;
+ }
+
+ if (!is_log_record_end(cur_page)) {
+ tail_page = NULL;
+ last_ok_lsn = lsn_cur;
+ goto next_page_1;
+ }
+
+ log->seq_num = expected_seq;
+ log->l_flags &= ~NTFSLOG_NO_LAST_LSN;
+ log->last_lsn = le64_to_cpu(cur_page->record_hdr.last_end_lsn);
+ log->ra->current_lsn = cur_page->record_hdr.last_end_lsn;
+
+ if (log->record_header_len <=
+ log->page_size -
+ le16_to_cpu(cur_page->record_hdr.next_record_off)) {
+ log->l_flags |= NTFSLOG_REUSE_TAIL;
+ log->next_page = curpage_off;
+ } else {
+ log->l_flags &= ~NTFSLOG_REUSE_TAIL;
+ log->next_page = nextpage_off;
+ }
+
+ if (wrapped_file)
+ log->l_flags |= NTFSLOG_WRAPPED;
+
+ last_ok_lsn = le64_to_cpu(cur_page->record_hdr.last_end_lsn);
+ goto next_page_1;
+ }
+
+ /*
+ * If we are at the expected first page of a transfer check to see
+ * if either tail copy is at this offset.
+ * If this page is the last page of a transfer, check if we wrote
+ * a subsequent tail copy.
+ */
+ if (page_cnt == page_pos || page_cnt == page_pos + 1) {
+ /*
+ * Check if the offset matches either the first or second
+ * tail copy. It is possible it will match both.
+ */
+ if (curpage_off == final_off)
+ tail_page = first_tail;
+
+ /*
+ * If we already matched on the first page then
+ * check the ending lsn's.
+ */
+ if (curpage_off == second_off) {
+ if (!tail_page ||
+ (second_tail &&
+ le64_to_cpu(second_tail->record_hdr.last_end_lsn) >
+ le64_to_cpu(first_tail->record_hdr
+ .last_end_lsn))) {
+ tail_page = second_tail;
+ }
+ }
+ }
+
+use_tail_page:
+ if (tail_page) {
+ /* We have a candidate for a tail copy. */
+ lsn_cur = le64_to_cpu(tail_page->record_hdr.last_end_lsn);
+
+ if (last_ok_lsn < lsn_cur) {
+ /*
+ * If the sequence number is not expected,
+ * then don't use the tail copy.
+ */
+ if (expected_seq != (lsn_cur >> log->file_data_bits))
+ tail_page = NULL;
+ } else if (last_ok_lsn > lsn_cur) {
+ /*
+ * If the last lsn is greater than the one on
+ * this page then forget this tail.
+ */
+ tail_page = NULL;
+ }
+ }
+
+ /*
+ *If we have an error on the current page,
+ * we will break of this loop.
+ */
+ if (err || usa_error)
+ goto check_tail;
+
+ /*
+ * Done if the last lsn on this page doesn't match the previous known
+ * last lsn or the sequence number is not expected.
+ */
+ lsn_cur = le64_to_cpu(page->rhdr.lsn);
+ if (last_ok_lsn != lsn_cur &&
+ expected_seq != (lsn_cur >> log->file_data_bits)) {
+ goto check_tail;
+ }
+
+ /*
+ * Check that the page position and page count values are correct.
+ * If this is the first page of a transfer the position must be 1
+ * and the count will be unknown.
+ */
+ if (page_cnt == page_pos) {
+ if (page->page_pos != cpu_to_le16(1) &&
+ (!reuse_page || page->page_pos != page->page_count)) {
+ /*
+ * If the current page is the first page we are
+ * looking at and we are reusing this page then
+ * it can be either the first or last page of a
+ * transfer. Otherwise it can only be the first.
+ */
+ goto check_tail;
+ }
+ } else if (le16_to_cpu(page->page_count) != page_cnt ||
+ le16_to_cpu(page->page_pos) != page_pos + 1) {
+ /*
+ * The page position better be 1 more than the last page
+ * position and the page count better match.
+ */
+ goto check_tail;
+ }
+
+ /*
+ * We have a valid page the file and may have a valid page
+ * the tail copy area.
+ * If the tail page was written after the page the file then
+ * break of the loop.
+ */
+ if (tail_page &&
+ le64_to_cpu(tail_page->record_hdr.last_end_lsn) > lsn_cur) {
+ /* Remember if we will replace the page. */
+ replace_page = true;
+ goto check_tail;
+ }
+
+ tail_page = NULL;
+
+ if (is_log_record_end(page)) {
+ /*
+ * Since we have read this page we know the sequence number
+ * is the same as our expected value.
+ */
+ log->seq_num = expected_seq;
+ log->last_lsn = le64_to_cpu(page->record_hdr.last_end_lsn);
+ log->ra->current_lsn = page->record_hdr.last_end_lsn;
+ log->l_flags &= ~NTFSLOG_NO_LAST_LSN;
+
+ /*
+ * If there is room on this page for another header then
+ * remember we want to reuse the page.
+ */
+ if (log->record_header_len <=
+ log->page_size -
+ le16_to_cpu(page->record_hdr.next_record_off)) {
+ log->l_flags |= NTFSLOG_REUSE_TAIL;
+ log->next_page = curpage_off;
+ } else {
+ log->l_flags &= ~NTFSLOG_REUSE_TAIL;
+ log->next_page = nextpage_off;
+ }
+
+ /* Remember if we wrapped the log file. */
+ if (wrapped_file)
+ log->l_flags |= NTFSLOG_WRAPPED;
+ }
+
+ /*
+ * Remember the last page count and position.
+ * Also remember the last known lsn.
+ */
+ page_cnt = le16_to_cpu(page->page_count);
+ page_pos = le16_to_cpu(page->page_pos);
+ last_ok_lsn = le64_to_cpu(page->rhdr.lsn);
+
+next_page_1:
+
+ if (wrapped) {
+ expected_seq += 1;
+ wrapped_file = 1;
+ }
+
+ curpage_off = nextpage_off;
+ kfree(page);
+ page = NULL;
+ reuse_page = 0;
+ goto next_page;
+
+check_tail:
+ if (tail_page) {
+ log->seq_num = expected_seq;
+ log->last_lsn = le64_to_cpu(tail_page->record_hdr.last_end_lsn);
+ log->ra->current_lsn = tail_page->record_hdr.last_end_lsn;
+ log->l_flags &= ~NTFSLOG_NO_LAST_LSN;
+
+ if (log->page_size -
+ le16_to_cpu(
+ tail_page->record_hdr.next_record_off) >=
+ log->record_header_len) {
+ log->l_flags |= NTFSLOG_REUSE_TAIL;
+ log->next_page = curpage_off;
+ } else {
+ log->l_flags &= ~NTFSLOG_REUSE_TAIL;
+ log->next_page = nextpage_off;
+ }
+
+ if (wrapped)
+ log->l_flags |= NTFSLOG_WRAPPED;
+ }
+
+ /* Remember that the partial IO will start at the next page. */
+ second_off = nextpage_off;
+
+ /*
+ * If the next page is the first page of the file then update
+ * the sequence number for log records which begon the next page.
+ */
+ if (wrapped)
+ expected_seq += 1;
+
+ /*
+ * If we have a tail copy or are performing single page I/O we can
+ * immediately look at the next page.
+ */
+ if (replace_page || (log->ra->flags & RESTART_SINGLE_PAGE_IO)) {
+ page_cnt = 2;
+ page_pos = 1;
+ goto check_valid;
+ }
+
+ if (page_pos != page_cnt)
+ goto check_valid;
+ /*
+ * If the next page causes us to wrap to the beginning of the log
+ * file then we know which page to check next.
+ */
+ if (wrapped) {
+ page_cnt = 2;
+ page_pos = 1;
+ goto check_valid;
+ }
+
+ cur_pos = 2;
+
+next_test_page:
+ kfree(tst_page);
+ tst_page = NULL;
+
+ /* Walk through the file, reading log pages. */
+ err = read_log_page(log, nextpage_off, &tst_page, &usa_error);
+
+ /*
+ * If we get a USA error then assume that we correctly found
+ * the end of the original transfer.
+ */
+ if (usa_error)
+ goto file_is_valid;
+
+ /*
+ * If we were able to read the page, we examine it to see if it
+ * is the same or different Io block.
+ */
+ if (err)
+ goto next_test_page_1;
+
+ if (le16_to_cpu(tst_page->page_pos) == cur_pos &&
+ check_subseq_log_page(log, tst_page, nextpage_off, expected_seq)) {
+ page_cnt = le16_to_cpu(tst_page->page_count) + 1;
+ page_pos = le16_to_cpu(tst_page->page_pos);
+ goto check_valid;
+ } else {
+ goto file_is_valid;
+ }
+
+next_test_page_1:
+
+ nextpage_off = next_page_off(log, curpage_off);
+ wrapped = nextpage_off == log->first_page;
+
+ if (wrapped) {
+ expected_seq += 1;
+ page_cnt = 2;
+ page_pos = 1;
+ }
+
+ cur_pos += 1;
+ part_io_count += 1;
+ if (!wrapped)
+ goto next_test_page;
+
+check_valid:
+ /* Skip over the remaining pages this transfer. */
+ remain_pages = page_cnt - page_pos - 1;
+ part_io_count += remain_pages;
+
+ while (remain_pages--) {
+ nextpage_off = next_page_off(log, curpage_off);
+ wrapped = nextpage_off == log->first_page;
+
+ if (wrapped)
+ expected_seq += 1;
+ }
+
+ /* Call our routine to check this log page. */
+ kfree(tst_page);
+ tst_page = NULL;
+
+ err = read_log_page(log, nextpage_off, &tst_page, &usa_error);
+ if (!err && !usa_error &&
+ check_subseq_log_page(log, tst_page, nextpage_off, expected_seq)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+file_is_valid:
+
+ /* We have a valid file. */
+ if (page_off1 || tail_page) {
+ struct RECORD_PAGE_HDR *tmp_page;
+
+ if (sb_rdonly(log->ni->mi.sbi->sb)) {
+ err = -EROFS;
+ goto out;
+ }
+
+ if (page_off1) {
+ tmp_page = Add2Ptr(page_bufs, page_off1 - page_off);
+ tails -= (page_off1 - page_off) / log->page_size;
+ if (!tail_page)
+ tails -= 1;
+ } else {
+ tmp_page = tail_page;
+ tails = 1;
+ }
+
+ while (tails--) {
+ u64 off = hdr_file_off(log, tmp_page);
+
+ if (!page) {
+ page = kmalloc(log->page_size, GFP_NOFS);
+ if (!page)
+ return -ENOMEM;
+ }
+
+ /*
+ * Correct page and copy the data from this page
+ * into it and flush it to disk.
+ */
+ memcpy(page, tmp_page, log->page_size);
+
+ /* Fill last flushed lsn value flush the page. */
+ if (log->major_ver < 2)
+ page->rhdr.lsn = page->record_hdr.last_end_lsn;
+ else
+ page->file_off = 0;
+
+ page->page_pos = page->page_count = cpu_to_le16(1);
+
+ ntfs_fix_pre_write(&page->rhdr, log->page_size);
+
+ err = ntfs_sb_write_run(log->ni->mi.sbi,
+ &log->ni->file.run, off, page,
+ log->page_size);
+
+ if (err)
+ goto out;
+
+ if (part_io_count && second_off == off) {
+ second_off += log->page_size;
+ part_io_count -= 1;
+ }
+
+ tmp_page = Add2Ptr(tmp_page, log->page_size);
+ }
+ }
+
+ if (part_io_count) {
+ if (sb_rdonly(log->ni->mi.sbi->sb)) {
+ err = -EROFS;
+ goto out;
+ }
+ }
+
+out:
+ kfree(second_tail);
+ kfree(first_tail);
+ kfree(page);
+ kfree(tst_page);
+ kfree(page_bufs);
+
+ return err;
+}
+
+/*
+ * read_log_rec_buf - Copy a log record from the file to a buffer.
+ *
+ * The log record may span several log pages and may even wrap the file.
+ */
+static int read_log_rec_buf(struct ntfs_log *log,
+ const struct LFS_RECORD_HDR *rh, void *buffer)
+{
+ int err;
+ struct RECORD_PAGE_HDR *ph = NULL;
+ u64 lsn = le64_to_cpu(rh->this_lsn);
+ u32 vbo = lsn_to_vbo(log, lsn) & ~log->page_mask;
+ u32 off = lsn_to_page_off(log, lsn) + log->record_header_len;
+ u32 data_len = le32_to_cpu(rh->client_data_len);
+
+ /*
+ * While there are more bytes to transfer,
+ * we continue to attempt to perform the read.
+ */
+ for (;;) {
+ bool usa_error;
+ u32 tail = log->page_size - off;
+
+ if (tail >= data_len)
+ tail = data_len;
+
+ data_len -= tail;
+
+ err = read_log_page(log, vbo, &ph, &usa_error);
+ if (err)
+ goto out;
+
+ /*
+ * The last lsn on this page better be greater or equal
+ * to the lsn we are copying.
+ */
+ if (lsn > le64_to_cpu(ph->rhdr.lsn)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ memcpy(buffer, Add2Ptr(ph, off), tail);
+
+ /* If there are no more bytes to transfer, we exit the loop. */
+ if (!data_len) {
+ if (!is_log_record_end(ph) ||
+ lsn > le64_to_cpu(ph->record_hdr.last_end_lsn)) {
+ err = -EINVAL;
+ goto out;
+ }
+ break;
+ }
+
+ if (ph->rhdr.lsn == ph->record_hdr.last_end_lsn ||
+ lsn > le64_to_cpu(ph->rhdr.lsn)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ vbo = next_page_off(log, vbo);
+ off = log->data_off;
+
+ /*
+ * Adjust our pointer the user's buffer to transfer
+ * the next block to.
+ */
+ buffer = Add2Ptr(buffer, tail);
+ }
+
+out:
+ kfree(ph);
+ return err;
+}
+
+static int read_rst_area(struct ntfs_log *log, struct NTFS_RESTART **rst_,
+ u64 *lsn)
+{
+ int err;
+ struct LFS_RECORD_HDR *rh = NULL;
+ const struct CLIENT_REC *cr =
+ Add2Ptr(log->ra, le16_to_cpu(log->ra->client_off));
+ u64 lsnr, lsnc = le64_to_cpu(cr->restart_lsn);
+ u32 len;
+ struct NTFS_RESTART *rst;
+
+ *lsn = 0;
+ *rst_ = NULL;
+
+ /* If the client doesn't have a restart area, go ahead and exit now. */
+ if (!lsnc)
+ return 0;
+
+ err = read_log_page(log, lsn_to_vbo(log, lsnc),
+ (struct RECORD_PAGE_HDR **)&rh, NULL);
+ if (err)
+ return err;
+
+ rst = NULL;
+ lsnr = le64_to_cpu(rh->this_lsn);
+
+ if (lsnc != lsnr) {
+ /* If the lsn values don't match, then the disk is corrupt. */
+ err = -EINVAL;
+ goto out;
+ }
+
+ *lsn = lsnr;
+ len = le32_to_cpu(rh->client_data_len);
+
+ if (!len) {
+ err = 0;
+ goto out;
+ }
+
+ if (len < sizeof(struct NTFS_RESTART)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ rst = kmalloc(len, GFP_NOFS);
+ if (!rst) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* Copy the data into the 'rst' buffer. */
+ err = read_log_rec_buf(log, rh, rst);
+ if (err)
+ goto out;
+
+ *rst_ = rst;
+ rst = NULL;
+
+out:
+ kfree(rh);
+ kfree(rst);
+
+ return err;
+}
+
+static int find_log_rec(struct ntfs_log *log, u64 lsn, struct lcb *lcb)
+{
+ int err;
+ struct LFS_RECORD_HDR *rh = lcb->lrh;
+ u32 rec_len, len;
+
+ /* Read the record header for this lsn. */
+ if (!rh) {
+ err = read_log_page(log, lsn_to_vbo(log, lsn),
+ (struct RECORD_PAGE_HDR **)&rh, NULL);
+
+ lcb->lrh = rh;
+ if (err)
+ return err;
+ }
+
+ /*
+ * If the lsn the log record doesn't match the desired
+ * lsn then the disk is corrupt.
+ */
+ if (lsn != le64_to_cpu(rh->this_lsn))
+ return -EINVAL;
+
+ len = le32_to_cpu(rh->client_data_len);
+
+ /*
+ * Check that the length field isn't greater than the total
+ * available space the log file.
+ */
+ rec_len = len + log->record_header_len;
+ if (rec_len >= log->total_avail)
+ return -EINVAL;
+
+ /*
+ * If the entire log record is on this log page,
+ * put a pointer to the log record the context block.
+ */
+ if (rh->flags & LOG_RECORD_MULTI_PAGE) {
+ void *lr = kmalloc(len, GFP_NOFS);
+
+ if (!lr)
+ return -ENOMEM;
+
+ lcb->log_rec = lr;
+ lcb->alloc = true;
+
+ /* Copy the data into the buffer returned. */
+ err = read_log_rec_buf(log, rh, lr);
+ if (err)
+ return err;
+ } else {
+ /* If beyond the end of the current page -> an error. */
+ u32 page_off = lsn_to_page_off(log, lsn);
+
+ if (page_off + len + log->record_header_len > log->page_size)
+ return -EINVAL;
+
+ lcb->log_rec = Add2Ptr(rh, sizeof(struct LFS_RECORD_HDR));
+ lcb->alloc = false;
+ }
+
+ return 0;
+}
+
+/*
+ * read_log_rec_lcb - Init the query operation.
+ */
+static int read_log_rec_lcb(struct ntfs_log *log, u64 lsn, u32 ctx_mode,
+ struct lcb **lcb_)
+{
+ int err;
+ const struct CLIENT_REC *cr;
+ struct lcb *lcb;
+
+ switch (ctx_mode) {
+ case lcb_ctx_undo_next:
+ case lcb_ctx_prev:
+ case lcb_ctx_next:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Check that the given lsn is the legal range for this client. */
+ cr = Add2Ptr(log->ra, le16_to_cpu(log->ra->client_off));
+
+ if (!verify_client_lsn(log, cr, lsn))
+ return -EINVAL;
+
+ lcb = kzalloc(sizeof(struct lcb), GFP_NOFS);
+ if (!lcb)
+ return -ENOMEM;
+ lcb->client = log->client_id;
+ lcb->ctx_mode = ctx_mode;
+
+ /* Find the log record indicated by the given lsn. */
+ err = find_log_rec(log, lsn, lcb);
+ if (err)
+ goto out;
+
+ *lcb_ = lcb;
+ return 0;
+
+out:
+ lcb_put(lcb);
+ *lcb_ = NULL;
+ return err;
+}
+
+/*
+ * find_client_next_lsn
+ *
+ * Attempt to find the next lsn to return to a client based on the context mode.
+ */
+static int find_client_next_lsn(struct ntfs_log *log, struct lcb *lcb, u64 *lsn)
+{
+ int err;
+ u64 next_lsn;
+ struct LFS_RECORD_HDR *hdr;
+
+ hdr = lcb->lrh;
+ *lsn = 0;
+
+ if (lcb_ctx_next != lcb->ctx_mode)
+ goto check_undo_next;
+
+ /* Loop as long as another lsn can be found. */
+ for (;;) {
+ u64 current_lsn;
+
+ err = next_log_lsn(log, hdr, &current_lsn);
+ if (err)
+ goto out;
+
+ if (!current_lsn)
+ break;
+
+ if (hdr != lcb->lrh)
+ kfree(hdr);
+
+ hdr = NULL;
+ err = read_log_page(log, lsn_to_vbo(log, current_lsn),
+ (struct RECORD_PAGE_HDR **)&hdr, NULL);
+ if (err)
+ goto out;
+
+ if (memcmp(&hdr->client, &lcb->client,
+ sizeof(struct CLIENT_ID))) {
+ /*err = -EINVAL; */
+ } else if (LfsClientRecord == hdr->record_type) {
+ kfree(lcb->lrh);
+ lcb->lrh = hdr;
+ *lsn = current_lsn;
+ return 0;
+ }
+ }
+
+out:
+ if (hdr != lcb->lrh)
+ kfree(hdr);
+ return err;
+
+check_undo_next:
+ if (lcb_ctx_undo_next == lcb->ctx_mode)
+ next_lsn = le64_to_cpu(hdr->client_undo_next_lsn);
+ else if (lcb_ctx_prev == lcb->ctx_mode)
+ next_lsn = le64_to_cpu(hdr->client_prev_lsn);
+ else
+ return 0;
+
+ if (!next_lsn)
+ return 0;
+
+ if (!verify_client_lsn(
+ log, Add2Ptr(log->ra, le16_to_cpu(log->ra->client_off)),
+ next_lsn))
+ return 0;
+
+ hdr = NULL;
+ err = read_log_page(log, lsn_to_vbo(log, next_lsn),
+ (struct RECORD_PAGE_HDR **)&hdr, NULL);
+ if (err)
+ return err;
+ kfree(lcb->lrh);
+ lcb->lrh = hdr;
+
+ *lsn = next_lsn;
+
+ return 0;
+}
+
+static int read_next_log_rec(struct ntfs_log *log, struct lcb *lcb, u64 *lsn)
+{
+ int err;
+
+ err = find_client_next_lsn(log, lcb, lsn);
+ if (err)
+ return err;
+
+ if (!*lsn)
+ return 0;
+
+ if (lcb->alloc)
+ kfree(lcb->log_rec);
+
+ lcb->log_rec = NULL;
+ lcb->alloc = false;
+ kfree(lcb->lrh);
+ lcb->lrh = NULL;
+
+ return find_log_rec(log, *lsn, lcb);
+}
+
+static inline bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes)
+{
+ __le16 mask;
+ u32 min_de, de_off, used, total;
+ const struct NTFS_DE *e;
+
+ if (hdr_has_subnode(hdr)) {
+ min_de = sizeof(struct NTFS_DE) + sizeof(u64);
+ mask = NTFS_IE_HAS_SUBNODES;
+ } else {
+ min_de = sizeof(struct NTFS_DE);
+ mask = 0;
+ }
+
+ de_off = le32_to_cpu(hdr->de_off);
+ used = le32_to_cpu(hdr->used);
+ total = le32_to_cpu(hdr->total);
+
+ if (de_off > bytes - min_de || used > bytes || total > bytes ||
+ de_off + min_de > used || used > total) {
+ return false;
+ }
+
+ e = Add2Ptr(hdr, de_off);
+ for (;;) {
+ u16 esize = le16_to_cpu(e->size);
+ struct NTFS_DE *next = Add2Ptr(e, esize);
+
+ if (esize < min_de || PtrOffset(hdr, next) > used ||
+ (e->flags & NTFS_IE_HAS_SUBNODES) != mask) {
+ return false;
+ }
+
+ if (de_is_last(e))
+ break;
+
+ e = next;
+ }
+
+ return true;
+}
+
+static inline bool check_index_buffer(const struct INDEX_BUFFER *ib, u32 bytes)
+{
+ u16 fo;
+ const struct NTFS_RECORD_HEADER *r = &ib->rhdr;
+
+ if (r->sign != NTFS_INDX_SIGNATURE)
+ return false;
+
+ fo = (SECTOR_SIZE - ((bytes >> SECTOR_SHIFT) + 1) * sizeof(short));
+
+ if (le16_to_cpu(r->fix_off) > fo)
+ return false;
+
+ if ((le16_to_cpu(r->fix_num) - 1) * SECTOR_SIZE != bytes)
+ return false;
+
+ return check_index_header(&ib->ihdr,
+ bytes - offsetof(struct INDEX_BUFFER, ihdr));
+}
+
+static inline bool check_index_root(const struct ATTRIB *attr,
+ struct ntfs_sb_info *sbi)
+{
+ bool ret;
+ const struct INDEX_ROOT *root = resident_data(attr);
+ u8 index_bits = le32_to_cpu(root->index_block_size) >= sbi->cluster_size
+ ? sbi->cluster_bits
+ : SECTOR_SHIFT;
+ u8 block_clst = root->index_block_clst;
+
+ if (le32_to_cpu(attr->res.data_size) < sizeof(struct INDEX_ROOT) ||
+ (root->type != ATTR_NAME && root->type != ATTR_ZERO) ||
+ (root->type == ATTR_NAME &&
+ root->rule != NTFS_COLLATION_TYPE_FILENAME) ||
+ (le32_to_cpu(root->index_block_size) !=
+ (block_clst << index_bits)) ||
+ (block_clst != 1 && block_clst != 2 && block_clst != 4 &&
+ block_clst != 8 && block_clst != 0x10 && block_clst != 0x20 &&
+ block_clst != 0x40 && block_clst != 0x80)) {
+ return false;
+ }
+
+ ret = check_index_header(&root->ihdr,
+ le32_to_cpu(attr->res.data_size) -
+ offsetof(struct INDEX_ROOT, ihdr));
+ return ret;
+}
+
+static inline bool check_attr(const struct MFT_REC *rec,
+ const struct ATTRIB *attr,
+ struct ntfs_sb_info *sbi)
+{
+ u32 asize = le32_to_cpu(attr->size);
+ u32 rsize = 0;
+ u64 dsize, svcn, evcn;
+ u16 run_off;
+
+ /* Check the fixed part of the attribute record header. */
+ if (asize >= sbi->record_size ||
+ asize + PtrOffset(rec, attr) >= sbi->record_size ||
+ (attr->name_len &&
+ le16_to_cpu(attr->name_off) + attr->name_len * sizeof(short) >
+ asize)) {
+ return false;
+ }
+
+ /* Check the attribute fields. */
+ switch (attr->non_res) {
+ case 0:
+ rsize = le32_to_cpu(attr->res.data_size);
+ if (rsize >= asize ||
+ le16_to_cpu(attr->res.data_off) + rsize > asize) {
+ return false;
+ }
+ break;
+
+ case 1:
+ dsize = le64_to_cpu(attr->nres.data_size);
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn = le64_to_cpu(attr->nres.evcn);
+ run_off = le16_to_cpu(attr->nres.run_off);
+
+ if (svcn > evcn + 1 || run_off >= asize ||
+ le64_to_cpu(attr->nres.valid_size) > dsize ||
+ dsize > le64_to_cpu(attr->nres.alloc_size)) {
+ return false;
+ }
+
+ if (run_unpack(NULL, sbi, 0, svcn, evcn, svcn,
+ Add2Ptr(attr, run_off), asize - run_off) < 0) {
+ return false;
+ }
+
+ return true;
+
+ default:
+ return false;
+ }
+
+ switch (attr->type) {
+ case ATTR_NAME:
+ if (fname_full_size(Add2Ptr(
+ attr, le16_to_cpu(attr->res.data_off))) > asize) {
+ return false;
+ }
+ break;
+
+ case ATTR_ROOT:
+ return check_index_root(attr, sbi);
+
+ case ATTR_STD:
+ if (rsize < sizeof(struct ATTR_STD_INFO5) &&
+ rsize != sizeof(struct ATTR_STD_INFO)) {
+ return false;
+ }
+ break;
+
+ case ATTR_LIST:
+ case ATTR_ID:
+ case ATTR_SECURE:
+ case ATTR_LABEL:
+ case ATTR_VOL_INFO:
+ case ATTR_DATA:
+ case ATTR_ALLOC:
+ case ATTR_BITMAP:
+ case ATTR_REPARSE:
+ case ATTR_EA_INFO:
+ case ATTR_EA:
+ case ATTR_PROPERTYSET:
+ case ATTR_LOGGED_UTILITY_STREAM:
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+static inline bool check_file_record(const struct MFT_REC *rec,
+ const struct MFT_REC *rec2,
+ struct ntfs_sb_info *sbi)
+{
+ const struct ATTRIB *attr;
+ u16 fo = le16_to_cpu(rec->rhdr.fix_off);
+ u16 fn = le16_to_cpu(rec->rhdr.fix_num);
+ u16 ao = le16_to_cpu(rec->attr_off);
+ u32 rs = sbi->record_size;
+
+ /* Check the file record header for consistency. */
+ if (rec->rhdr.sign != NTFS_FILE_SIGNATURE ||
+ fo > (SECTOR_SIZE - ((rs >> SECTOR_SHIFT) + 1) * sizeof(short)) ||
+ (fn - 1) * SECTOR_SIZE != rs || ao < MFTRECORD_FIXUP_OFFSET_1 ||
+ ao > sbi->record_size - SIZEOF_RESIDENT || !is_rec_inuse(rec) ||
+ le32_to_cpu(rec->total) != rs) {
+ return false;
+ }
+
+ /* Loop to check all of the attributes. */
+ for (attr = Add2Ptr(rec, ao); attr->type != ATTR_END;
+ attr = Add2Ptr(attr, le32_to_cpu(attr->size))) {
+ if (check_attr(rec, attr, sbi))
+ continue;
+ return false;
+ }
+
+ return true;
+}
+
+static inline int check_lsn(const struct NTFS_RECORD_HEADER *hdr,
+ const u64 *rlsn)
+{
+ u64 lsn;
+
+ if (!rlsn)
+ return true;
+
+ lsn = le64_to_cpu(hdr->lsn);
+
+ if (hdr->sign == NTFS_HOLE_SIGNATURE)
+ return false;
+
+ if (*rlsn > lsn)
+ return true;
+
+ return false;
+}
+
+static inline bool check_if_attr(const struct MFT_REC *rec,
+ const struct LOG_REC_HDR *lrh)
+{
+ u16 ro = le16_to_cpu(lrh->record_off);
+ u16 o = le16_to_cpu(rec->attr_off);
+ const struct ATTRIB *attr = Add2Ptr(rec, o);
+
+ while (o < ro) {
+ u32 asize;
+
+ if (attr->type == ATTR_END)
+ break;
+
+ asize = le32_to_cpu(attr->size);
+ if (!asize)
+ break;
+
+ o += asize;
+ attr = Add2Ptr(attr, asize);
+ }
+
+ return o == ro;
+}
+
+static inline bool check_if_index_root(const struct MFT_REC *rec,
+ const struct LOG_REC_HDR *lrh)
+{
+ u16 ro = le16_to_cpu(lrh->record_off);
+ u16 o = le16_to_cpu(rec->attr_off);
+ const struct ATTRIB *attr = Add2Ptr(rec, o);
+
+ while (o < ro) {
+ u32 asize;
+
+ if (attr->type == ATTR_END)
+ break;
+
+ asize = le32_to_cpu(attr->size);
+ if (!asize)
+ break;
+
+ o += asize;
+ attr = Add2Ptr(attr, asize);
+ }
+
+ return o == ro && attr->type == ATTR_ROOT;
+}
+
+static inline bool check_if_root_index(const struct ATTRIB *attr,
+ const struct INDEX_HDR *hdr,
+ const struct LOG_REC_HDR *lrh)
+{
+ u16 ao = le16_to_cpu(lrh->attr_off);
+ u32 de_off = le32_to_cpu(hdr->de_off);
+ u32 o = PtrOffset(attr, hdr) + de_off;
+ const struct NTFS_DE *e = Add2Ptr(hdr, de_off);
+ u32 asize = le32_to_cpu(attr->size);
+
+ while (o < ao) {
+ u16 esize;
+
+ if (o >= asize)
+ break;
+
+ esize = le16_to_cpu(e->size);
+ if (!esize)
+ break;
+
+ o += esize;
+ e = Add2Ptr(e, esize);
+ }
+
+ return o == ao;
+}
+
+static inline bool check_if_alloc_index(const struct INDEX_HDR *hdr,
+ u32 attr_off)
+{
+ u32 de_off = le32_to_cpu(hdr->de_off);
+ u32 o = offsetof(struct INDEX_BUFFER, ihdr) + de_off;
+ const struct NTFS_DE *e = Add2Ptr(hdr, de_off);
+ u32 used = le32_to_cpu(hdr->used);
+
+ while (o < attr_off) {
+ u16 esize;
+
+ if (de_off >= used)
+ break;
+
+ esize = le16_to_cpu(e->size);
+ if (!esize)
+ break;
+
+ o += esize;
+ de_off += esize;
+ e = Add2Ptr(e, esize);
+ }
+
+ return o == attr_off;
+}
+
+static inline void change_attr_size(struct MFT_REC *rec, struct ATTRIB *attr,
+ u32 nsize)
+{
+ u32 asize = le32_to_cpu(attr->size);
+ int dsize = nsize - asize;
+ u8 *next = Add2Ptr(attr, asize);
+ u32 used = le32_to_cpu(rec->used);
+
+ memmove(Add2Ptr(attr, nsize), next, used - PtrOffset(rec, next));
+
+ rec->used = cpu_to_le32(used + dsize);
+ attr->size = cpu_to_le32(nsize);
+}
+
+struct OpenAttr {
+ struct ATTRIB *attr;
+ struct runs_tree *run1;
+ struct runs_tree run0;
+ struct ntfs_inode *ni;
+ // CLST rno;
+};
+
+/*
+ * cmp_type_and_name
+ *
+ * Return: 0 if 'attr' has the same type and name.
+ */
+static inline int cmp_type_and_name(const struct ATTRIB *a1,
+ const struct ATTRIB *a2)
+{
+ return a1->type != a2->type || a1->name_len != a2->name_len ||
+ (a1->name_len && memcmp(attr_name(a1), attr_name(a2),
+ a1->name_len * sizeof(short)));
+}
+
+static struct OpenAttr *find_loaded_attr(struct ntfs_log *log,
+ const struct ATTRIB *attr, CLST rno)
+{
+ struct OPEN_ATTR_ENRTY *oe = NULL;
+
+ while ((oe = enum_rstbl(log->open_attr_tbl, oe))) {
+ struct OpenAttr *op_attr;
+
+ if (ino_get(&oe->ref) != rno)
+ continue;
+
+ op_attr = (struct OpenAttr *)oe->ptr;
+ if (!cmp_type_and_name(op_attr->attr, attr))
+ return op_attr;
+ }
+ return NULL;
+}
+
+static struct ATTRIB *attr_create_nonres_log(struct ntfs_sb_info *sbi,
+ enum ATTR_TYPE type, u64 size,
+ const u16 *name, size_t name_len,
+ __le16 flags)
+{
+ struct ATTRIB *attr;
+ u32 name_size = ALIGN(name_len * sizeof(short), 8);
+ bool is_ext = flags & (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED);
+ u32 asize = name_size +
+ (is_ext ? SIZEOF_NONRESIDENT_EX : SIZEOF_NONRESIDENT);
+
+ attr = kzalloc(asize, GFP_NOFS);
+ if (!attr)
+ return NULL;
+
+ attr->type = type;
+ attr->size = cpu_to_le32(asize);
+ attr->flags = flags;
+ attr->non_res = 1;
+ attr->name_len = name_len;
+
+ attr->nres.evcn = cpu_to_le64((u64)bytes_to_cluster(sbi, size) - 1);
+ attr->nres.alloc_size = cpu_to_le64(ntfs_up_cluster(sbi, size));
+ attr->nres.data_size = cpu_to_le64(size);
+ attr->nres.valid_size = attr->nres.data_size;
+ if (is_ext) {
+ attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
+ if (is_attr_compressed(attr))
+ attr->nres.c_unit = COMPRESSION_UNIT;
+
+ attr->nres.run_off =
+ cpu_to_le16(SIZEOF_NONRESIDENT_EX + name_size);
+ memcpy(Add2Ptr(attr, SIZEOF_NONRESIDENT_EX), name,
+ name_len * sizeof(short));
+ } else {
+ attr->name_off = SIZEOF_NONRESIDENT_LE;
+ attr->nres.run_off =
+ cpu_to_le16(SIZEOF_NONRESIDENT + name_size);
+ memcpy(Add2Ptr(attr, SIZEOF_NONRESIDENT), name,
+ name_len * sizeof(short));
+ }
+
+ return attr;
+}
+
+/*
+ * do_action - Common routine for the Redo and Undo Passes.
+ * @rlsn: If it is NULL then undo.
+ */
+static int do_action(struct ntfs_log *log, struct OPEN_ATTR_ENRTY *oe,
+ const struct LOG_REC_HDR *lrh, u32 op, void *data,
+ u32 dlen, u32 rec_len, const u64 *rlsn)
+{
+ int err = 0;
+ struct ntfs_sb_info *sbi = log->ni->mi.sbi;
+ struct inode *inode = NULL, *inode_parent;
+ struct mft_inode *mi = NULL, *mi2_child = NULL;
+ CLST rno = 0, rno_base = 0;
+ struct INDEX_BUFFER *ib = NULL;
+ struct MFT_REC *rec = NULL;
+ struct ATTRIB *attr = NULL, *attr2;
+ struct INDEX_HDR *hdr;
+ struct INDEX_ROOT *root;
+ struct NTFS_DE *e, *e1, *e2;
+ struct NEW_ATTRIBUTE_SIZES *new_sz;
+ struct ATTR_FILE_NAME *fname;
+ struct OpenAttr *oa, *oa2;
+ u32 nsize, t32, asize, used, esize, bmp_off, bmp_bits;
+ u16 id, id2;
+ u32 record_size = sbi->record_size;
+ u64 t64;
+ u16 roff = le16_to_cpu(lrh->record_off);
+ u16 aoff = le16_to_cpu(lrh->attr_off);
+ u64 lco = 0;
+ u64 cbo = (u64)le16_to_cpu(lrh->cluster_off) << SECTOR_SHIFT;
+ u64 tvo = le64_to_cpu(lrh->target_vcn) << sbi->cluster_bits;
+ u64 vbo = cbo + tvo;
+ void *buffer_le = NULL;
+ u32 bytes = 0;
+ bool a_dirty = false;
+ u16 data_off;
+
+ oa = oe->ptr;
+
+ /* Big switch to prepare. */
+ switch (op) {
+ /* ============================================================
+ * Process MFT records, as described by the current log record.
+ * ============================================================
+ */
+ case InitializeFileRecordSegment:
+ case DeallocateFileRecordSegment:
+ case WriteEndOfFileRecordSegment:
+ case CreateAttribute:
+ case DeleteAttribute:
+ case UpdateResidentValue:
+ case UpdateMappingPairs:
+ case SetNewAttributeSizes:
+ case AddIndexEntryRoot:
+ case DeleteIndexEntryRoot:
+ case SetIndexEntryVcnRoot:
+ case UpdateFileNameRoot:
+ case UpdateRecordDataRoot:
+ case ZeroEndOfFileRecord:
+ rno = vbo >> sbi->record_bits;
+ inode = ilookup(sbi->sb, rno);
+ if (inode) {
+ mi = &ntfs_i(inode)->mi;
+ } else if (op == InitializeFileRecordSegment) {
+ mi = kzalloc(sizeof(struct mft_inode), GFP_NOFS);
+ if (!mi)
+ return -ENOMEM;
+ err = mi_format_new(mi, sbi, rno, 0, false);
+ if (err)
+ goto out;
+ } else {
+ /* Read from disk. */
+ err = mi_get(sbi, rno, &mi);
+ if (err)
+ return err;
+ }
+ rec = mi->mrec;
+
+ if (op == DeallocateFileRecordSegment)
+ goto skip_load_parent;
+
+ if (InitializeFileRecordSegment != op) {
+ if (rec->rhdr.sign == NTFS_BAAD_SIGNATURE)
+ goto dirty_vol;
+ if (!check_lsn(&rec->rhdr, rlsn))
+ goto out;
+ if (!check_file_record(rec, NULL, sbi))
+ goto dirty_vol;
+ attr = Add2Ptr(rec, roff);
+ }
+
+ if (is_rec_base(rec) || InitializeFileRecordSegment == op) {
+ rno_base = rno;
+ goto skip_load_parent;
+ }
+
+ rno_base = ino_get(&rec->parent_ref);
+ inode_parent = ntfs_iget5(sbi->sb, &rec->parent_ref, NULL);
+ if (IS_ERR(inode_parent))
+ goto skip_load_parent;
+
+ if (is_bad_inode(inode_parent)) {
+ iput(inode_parent);
+ goto skip_load_parent;
+ }
+
+ if (ni_load_mi_ex(ntfs_i(inode_parent), rno, &mi2_child)) {
+ iput(inode_parent);
+ } else {
+ if (mi2_child->mrec != mi->mrec)
+ memcpy(mi2_child->mrec, mi->mrec,
+ sbi->record_size);
+
+ if (inode)
+ iput(inode);
+ else if (mi)
+ mi_put(mi);
+
+ inode = inode_parent;
+ mi = mi2_child;
+ rec = mi2_child->mrec;
+ attr = Add2Ptr(rec, roff);
+ }
+
+skip_load_parent:
+ inode_parent = NULL;
+ break;
+
+ /*
+ * Process attributes, as described by the current log record.
+ */
+ case UpdateNonresidentValue:
+ case AddIndexEntryAllocation:
+ case DeleteIndexEntryAllocation:
+ case WriteEndOfIndexBuffer:
+ case SetIndexEntryVcnAllocation:
+ case UpdateFileNameAllocation:
+ case SetBitsInNonresidentBitMap:
+ case ClearBitsInNonresidentBitMap:
+ case UpdateRecordDataAllocation:
+ attr = oa->attr;
+ bytes = UpdateNonresidentValue == op ? dlen : 0;
+ lco = (u64)le16_to_cpu(lrh->lcns_follow) << sbi->cluster_bits;
+
+ if (attr->type == ATTR_ALLOC) {
+ t32 = le32_to_cpu(oe->bytes_per_index);
+ if (bytes < t32)
+ bytes = t32;
+ }
+
+ if (!bytes)
+ bytes = lco - cbo;
+
+ bytes += roff;
+ if (attr->type == ATTR_ALLOC)
+ bytes = (bytes + 511) & ~511; // align
+
+ buffer_le = kmalloc(bytes, GFP_NOFS);
+ if (!buffer_le)
+ return -ENOMEM;
+
+ err = ntfs_read_run_nb(sbi, oa->run1, vbo, buffer_le, bytes,
+ NULL);
+ if (err)
+ goto out;
+
+ if (attr->type == ATTR_ALLOC && *(int *)buffer_le)
+ ntfs_fix_post_read(buffer_le, bytes, false);
+ break;
+
+ default:
+ WARN_ON(1);
+ }
+
+ /* Big switch to do operation. */
+ switch (op) {
+ case InitializeFileRecordSegment:
+ if (roff + dlen > record_size)
+ goto dirty_vol;
+
+ memcpy(Add2Ptr(rec, roff), data, dlen);
+ mi->dirty = true;
+ break;
+
+ case DeallocateFileRecordSegment:
+ clear_rec_inuse(rec);
+ le16_add_cpu(&rec->seq, 1);
+ mi->dirty = true;
+ break;
+
+ case WriteEndOfFileRecordSegment:
+ attr2 = (struct ATTRIB *)data;
+ if (!check_if_attr(rec, lrh) || roff + dlen > record_size)
+ goto dirty_vol;
+
+ memmove(attr, attr2, dlen);
+ rec->used = cpu_to_le32(ALIGN(roff + dlen, 8));
+
+ mi->dirty = true;
+ break;
+
+ case CreateAttribute:
+ attr2 = (struct ATTRIB *)data;
+ asize = le32_to_cpu(attr2->size);
+ used = le32_to_cpu(rec->used);
+
+ if (!check_if_attr(rec, lrh) || dlen < SIZEOF_RESIDENT ||
+ !IS_ALIGNED(asize, 8) ||
+ Add2Ptr(attr2, asize) > Add2Ptr(lrh, rec_len) ||
+ dlen > record_size - used) {
+ goto dirty_vol;
+ }
+
+ memmove(Add2Ptr(attr, asize), attr, used - roff);
+ memcpy(attr, attr2, asize);
+
+ rec->used = cpu_to_le32(used + asize);
+ id = le16_to_cpu(rec->next_attr_id);
+ id2 = le16_to_cpu(attr2->id);
+ if (id <= id2)
+ rec->next_attr_id = cpu_to_le16(id2 + 1);
+ if (is_attr_indexed(attr))
+ le16_add_cpu(&rec->hard_links, 1);
+
+ oa2 = find_loaded_attr(log, attr, rno_base);
+ if (oa2) {
+ void *p2 = kmemdup(attr, le32_to_cpu(attr->size),
+ GFP_NOFS);
+ if (p2) {
+ // run_close(oa2->run1);
+ kfree(oa2->attr);
+ oa2->attr = p2;
+ }
+ }
+
+ mi->dirty = true;
+ break;
+
+ case DeleteAttribute:
+ asize = le32_to_cpu(attr->size);
+ used = le32_to_cpu(rec->used);
+
+ if (!check_if_attr(rec, lrh))
+ goto dirty_vol;
+
+ rec->used = cpu_to_le32(used - asize);
+ if (is_attr_indexed(attr))
+ le16_add_cpu(&rec->hard_links, -1);
+
+ memmove(attr, Add2Ptr(attr, asize), used - asize - roff);
+
+ mi->dirty = true;
+ break;
+
+ case UpdateResidentValue:
+ nsize = aoff + dlen;
+
+ if (!check_if_attr(rec, lrh))
+ goto dirty_vol;
+
+ asize = le32_to_cpu(attr->size);
+ used = le32_to_cpu(rec->used);
+
+ if (lrh->redo_len == lrh->undo_len) {
+ if (nsize > asize)
+ goto dirty_vol;
+ goto move_data;
+ }
+
+ if (nsize > asize && nsize - asize > record_size - used)
+ goto dirty_vol;
+
+ nsize = ALIGN(nsize, 8);
+ data_off = le16_to_cpu(attr->res.data_off);
+
+ if (nsize < asize) {
+ memmove(Add2Ptr(attr, aoff), data, dlen);
+ data = NULL; // To skip below memmove().
+ }
+
+ memmove(Add2Ptr(attr, nsize), Add2Ptr(attr, asize),
+ used - le16_to_cpu(lrh->record_off) - asize);
+
+ rec->used = cpu_to_le32(used + nsize - asize);
+ attr->size = cpu_to_le32(nsize);
+ attr->res.data_size = cpu_to_le32(aoff + dlen - data_off);
+
+move_data:
+ if (data)
+ memmove(Add2Ptr(attr, aoff), data, dlen);
+
+ oa2 = find_loaded_attr(log, attr, rno_base);
+ if (oa2) {
+ void *p2 = kmemdup(attr, le32_to_cpu(attr->size),
+ GFP_NOFS);
+ if (p2) {
+ // run_close(&oa2->run0);
+ oa2->run1 = &oa2->run0;
+ kfree(oa2->attr);
+ oa2->attr = p2;
+ }
+ }
+
+ mi->dirty = true;
+ break;
+
+ case UpdateMappingPairs:
+ nsize = aoff + dlen;
+ asize = le32_to_cpu(attr->size);
+ used = le32_to_cpu(rec->used);
+
+ if (!check_if_attr(rec, lrh) || !attr->non_res ||
+ aoff < le16_to_cpu(attr->nres.run_off) || aoff > asize ||
+ (nsize > asize && nsize - asize > record_size - used)) {
+ goto dirty_vol;
+ }
+
+ nsize = ALIGN(nsize, 8);
+
+ memmove(Add2Ptr(attr, nsize), Add2Ptr(attr, asize),
+ used - le16_to_cpu(lrh->record_off) - asize);
+ rec->used = cpu_to_le32(used + nsize - asize);
+ attr->size = cpu_to_le32(nsize);
+ memmove(Add2Ptr(attr, aoff), data, dlen);
+
+ if (run_get_highest_vcn(le64_to_cpu(attr->nres.svcn),
+ attr_run(attr), &t64)) {
+ goto dirty_vol;
+ }
+
+ attr->nres.evcn = cpu_to_le64(t64);
+ oa2 = find_loaded_attr(log, attr, rno_base);
+ if (oa2 && oa2->attr->non_res)
+ oa2->attr->nres.evcn = attr->nres.evcn;
+
+ mi->dirty = true;
+ break;
+
+ case SetNewAttributeSizes:
+ new_sz = data;
+ if (!check_if_attr(rec, lrh) || !attr->non_res)
+ goto dirty_vol;
+
+ attr->nres.alloc_size = new_sz->alloc_size;
+ attr->nres.data_size = new_sz->data_size;
+ attr->nres.valid_size = new_sz->valid_size;
+
+ if (dlen >= sizeof(struct NEW_ATTRIBUTE_SIZES))
+ attr->nres.total_size = new_sz->total_size;
+
+ oa2 = find_loaded_attr(log, attr, rno_base);
+ if (oa2) {
+ void *p2 = kmemdup(attr, le32_to_cpu(attr->size),
+ GFP_NOFS);
+ if (p2) {
+ kfree(oa2->attr);
+ oa2->attr = p2;
+ }
+ }
+ mi->dirty = true;
+ break;
+
+ case AddIndexEntryRoot:
+ e = (struct NTFS_DE *)data;
+ esize = le16_to_cpu(e->size);
+ root = resident_data(attr);
+ hdr = &root->ihdr;
+ used = le32_to_cpu(hdr->used);
+
+ if (!check_if_index_root(rec, lrh) ||
+ !check_if_root_index(attr, hdr, lrh) ||
+ Add2Ptr(data, esize) > Add2Ptr(lrh, rec_len) ||
+ esize > le32_to_cpu(rec->total) - le32_to_cpu(rec->used)) {
+ goto dirty_vol;
+ }
+
+ e1 = Add2Ptr(attr, le16_to_cpu(lrh->attr_off));
+
+ change_attr_size(rec, attr, le32_to_cpu(attr->size) + esize);
+
+ memmove(Add2Ptr(e1, esize), e1,
+ PtrOffset(e1, Add2Ptr(hdr, used)));
+ memmove(e1, e, esize);
+
+ le32_add_cpu(&attr->res.data_size, esize);
+ hdr->used = cpu_to_le32(used + esize);
+ le32_add_cpu(&hdr->total, esize);
+
+ mi->dirty = true;
+ break;
+
+ case DeleteIndexEntryRoot:
+ root = resident_data(attr);
+ hdr = &root->ihdr;
+ used = le32_to_cpu(hdr->used);
+
+ if (!check_if_index_root(rec, lrh) ||
+ !check_if_root_index(attr, hdr, lrh)) {
+ goto dirty_vol;
+ }
+
+ e1 = Add2Ptr(attr, le16_to_cpu(lrh->attr_off));
+ esize = le16_to_cpu(e1->size);
+ e2 = Add2Ptr(e1, esize);
+
+ memmove(e1, e2, PtrOffset(e2, Add2Ptr(hdr, used)));
+
+ le32_sub_cpu(&attr->res.data_size, esize);
+ hdr->used = cpu_to_le32(used - esize);
+ le32_sub_cpu(&hdr->total, esize);
+
+ change_attr_size(rec, attr, le32_to_cpu(attr->size) - esize);
+
+ mi->dirty = true;
+ break;
+
+ case SetIndexEntryVcnRoot:
+ root = resident_data(attr);
+ hdr = &root->ihdr;
+
+ if (!check_if_index_root(rec, lrh) ||
+ !check_if_root_index(attr, hdr, lrh)) {
+ goto dirty_vol;
+ }
+
+ e = Add2Ptr(attr, le16_to_cpu(lrh->attr_off));
+
+ de_set_vbn_le(e, *(__le64 *)data);
+ mi->dirty = true;
+ break;
+
+ case UpdateFileNameRoot:
+ root = resident_data(attr);
+ hdr = &root->ihdr;
+
+ if (!check_if_index_root(rec, lrh) ||
+ !check_if_root_index(attr, hdr, lrh)) {
+ goto dirty_vol;
+ }
+
+ e = Add2Ptr(attr, le16_to_cpu(lrh->attr_off));
+ fname = (struct ATTR_FILE_NAME *)(e + 1);
+ memmove(&fname->dup, data, sizeof(fname->dup)); //
+ mi->dirty = true;
+ break;
+
+ case UpdateRecordDataRoot:
+ root = resident_data(attr);
+ hdr = &root->ihdr;
+
+ if (!check_if_index_root(rec, lrh) ||
+ !check_if_root_index(attr, hdr, lrh)) {
+ goto dirty_vol;
+ }
+
+ e = Add2Ptr(attr, le16_to_cpu(lrh->attr_off));
+
+ memmove(Add2Ptr(e, le16_to_cpu(e->view.data_off)), data, dlen);
+
+ mi->dirty = true;
+ break;
+
+ case ZeroEndOfFileRecord:
+ if (roff + dlen > record_size)
+ goto dirty_vol;
+
+ memset(attr, 0, dlen);
+ mi->dirty = true;
+ break;
+
+ case UpdateNonresidentValue:
+ if (lco < cbo + roff + dlen)
+ goto dirty_vol;
+
+ memcpy(Add2Ptr(buffer_le, roff), data, dlen);
+
+ a_dirty = true;
+ if (attr->type == ATTR_ALLOC)
+ ntfs_fix_pre_write(buffer_le, bytes);
+ break;
+
+ case AddIndexEntryAllocation:
+ ib = Add2Ptr(buffer_le, roff);
+ hdr = &ib->ihdr;
+ e = data;
+ esize = le16_to_cpu(e->size);
+ e1 = Add2Ptr(ib, aoff);
+
+ if (is_baad(&ib->rhdr))
+ goto dirty_vol;
+ if (!check_lsn(&ib->rhdr, rlsn))
+ goto out;
+
+ used = le32_to_cpu(hdr->used);
+
+ if (!check_index_buffer(ib, bytes) ||
+ !check_if_alloc_index(hdr, aoff) ||
+ Add2Ptr(e, esize) > Add2Ptr(lrh, rec_len) ||
+ used + esize > le32_to_cpu(hdr->total)) {
+ goto dirty_vol;
+ }
+
+ memmove(Add2Ptr(e1, esize), e1,
+ PtrOffset(e1, Add2Ptr(hdr, used)));
+ memcpy(e1, e, esize);
+
+ hdr->used = cpu_to_le32(used + esize);
+
+ a_dirty = true;
+
+ ntfs_fix_pre_write(&ib->rhdr, bytes);
+ break;
+
+ case DeleteIndexEntryAllocation:
+ ib = Add2Ptr(buffer_le, roff);
+ hdr = &ib->ihdr;
+ e = Add2Ptr(ib, aoff);
+ esize = le16_to_cpu(e->size);
+
+ if (is_baad(&ib->rhdr))
+ goto dirty_vol;
+ if (!check_lsn(&ib->rhdr, rlsn))
+ goto out;
+
+ if (!check_index_buffer(ib, bytes) ||
+ !check_if_alloc_index(hdr, aoff)) {
+ goto dirty_vol;
+ }
+
+ e1 = Add2Ptr(e, esize);
+ nsize = esize;
+ used = le32_to_cpu(hdr->used);
+
+ memmove(e, e1, PtrOffset(e1, Add2Ptr(hdr, used)));
+
+ hdr->used = cpu_to_le32(used - nsize);
+
+ a_dirty = true;
+
+ ntfs_fix_pre_write(&ib->rhdr, bytes);
+ break;
+
+ case WriteEndOfIndexBuffer:
+ ib = Add2Ptr(buffer_le, roff);
+ hdr = &ib->ihdr;
+ e = Add2Ptr(ib, aoff);
+
+ if (is_baad(&ib->rhdr))
+ goto dirty_vol;
+ if (!check_lsn(&ib->rhdr, rlsn))
+ goto out;
+ if (!check_index_buffer(ib, bytes) ||
+ !check_if_alloc_index(hdr, aoff) ||
+ aoff + dlen > offsetof(struct INDEX_BUFFER, ihdr) +
+ le32_to_cpu(hdr->total)) {
+ goto dirty_vol;
+ }
+
+ hdr->used = cpu_to_le32(dlen + PtrOffset(hdr, e));
+ memmove(e, data, dlen);
+
+ a_dirty = true;
+ ntfs_fix_pre_write(&ib->rhdr, bytes);
+ break;
+
+ case SetIndexEntryVcnAllocation:
+ ib = Add2Ptr(buffer_le, roff);
+ hdr = &ib->ihdr;
+ e = Add2Ptr(ib, aoff);
+
+ if (is_baad(&ib->rhdr))
+ goto dirty_vol;
+
+ if (!check_lsn(&ib->rhdr, rlsn))
+ goto out;
+ if (!check_index_buffer(ib, bytes) ||
+ !check_if_alloc_index(hdr, aoff)) {
+ goto dirty_vol;
+ }
+
+ de_set_vbn_le(e, *(__le64 *)data);
+
+ a_dirty = true;
+ ntfs_fix_pre_write(&ib->rhdr, bytes);
+ break;
+
+ case UpdateFileNameAllocation:
+ ib = Add2Ptr(buffer_le, roff);
+ hdr = &ib->ihdr;
+ e = Add2Ptr(ib, aoff);
+
+ if (is_baad(&ib->rhdr))
+ goto dirty_vol;
+
+ if (!check_lsn(&ib->rhdr, rlsn))
+ goto out;
+ if (!check_index_buffer(ib, bytes) ||
+ !check_if_alloc_index(hdr, aoff)) {
+ goto dirty_vol;
+ }
+
+ fname = (struct ATTR_FILE_NAME *)(e + 1);
+ memmove(&fname->dup, data, sizeof(fname->dup));
+
+ a_dirty = true;
+ ntfs_fix_pre_write(&ib->rhdr, bytes);
+ break;
+
+ case SetBitsInNonresidentBitMap:
+ bmp_off =
+ le32_to_cpu(((struct BITMAP_RANGE *)data)->bitmap_off);
+ bmp_bits = le32_to_cpu(((struct BITMAP_RANGE *)data)->bits);
+
+ if (cbo + (bmp_off + 7) / 8 > lco ||
+ cbo + ((bmp_off + bmp_bits + 7) / 8) > lco) {
+ goto dirty_vol;
+ }
+
+ __bitmap_set(Add2Ptr(buffer_le, roff), bmp_off, bmp_bits);
+ a_dirty = true;
+ break;
+
+ case ClearBitsInNonresidentBitMap:
+ bmp_off =
+ le32_to_cpu(((struct BITMAP_RANGE *)data)->bitmap_off);
+ bmp_bits = le32_to_cpu(((struct BITMAP_RANGE *)data)->bits);
+
+ if (cbo + (bmp_off + 7) / 8 > lco ||
+ cbo + ((bmp_off + bmp_bits + 7) / 8) > lco) {
+ goto dirty_vol;
+ }
+
+ __bitmap_clear(Add2Ptr(buffer_le, roff), bmp_off, bmp_bits);
+ a_dirty = true;
+ break;
+
+ case UpdateRecordDataAllocation:
+ ib = Add2Ptr(buffer_le, roff);
+ hdr = &ib->ihdr;
+ e = Add2Ptr(ib, aoff);
+
+ if (is_baad(&ib->rhdr))
+ goto dirty_vol;
+
+ if (!check_lsn(&ib->rhdr, rlsn))
+ goto out;
+ if (!check_index_buffer(ib, bytes) ||
+ !check_if_alloc_index(hdr, aoff)) {
+ goto dirty_vol;
+ }
+
+ memmove(Add2Ptr(e, le16_to_cpu(e->view.data_off)), data, dlen);
+
+ a_dirty = true;
+ ntfs_fix_pre_write(&ib->rhdr, bytes);
+ break;
+
+ default:
+ WARN_ON(1);
+ }
+
+ if (rlsn) {
+ __le64 t64 = cpu_to_le64(*rlsn);
+
+ if (rec)
+ rec->rhdr.lsn = t64;
+ if (ib)
+ ib->rhdr.lsn = t64;
+ }
+
+ if (mi && mi->dirty) {
+ err = mi_write(mi, 0);
+ if (err)
+ goto out;
+ }
+
+ if (a_dirty) {
+ attr = oa->attr;
+ err = ntfs_sb_write_run(sbi, oa->run1, vbo, buffer_le, bytes);
+ if (err)
+ goto out;
+ }
+
+out:
+
+ if (inode)
+ iput(inode);
+ else if (mi != mi2_child)
+ mi_put(mi);
+
+ kfree(buffer_le);
+
+ return err;
+
+dirty_vol:
+ log->set_dirty = true;
+ goto out;
+}
+
+/*
+ * log_replay - Replays log and empties it.
+ *
+ * This function is called during mount operation.
+ * It replays log and empties it.
+ * Initialized is set false if logfile contains '-1'.
+ */
+int log_replay(struct ntfs_inode *ni, bool *initialized)
+{
+ int err;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct ntfs_log *log;
+
+ struct restart_info rst_info, rst_info2;
+ u64 rec_lsn, ra_lsn, checkpt_lsn = 0, rlsn = 0;
+ struct ATTR_NAME_ENTRY *attr_names = NULL;
+ struct ATTR_NAME_ENTRY *ane;
+ struct RESTART_TABLE *dptbl = NULL;
+ struct RESTART_TABLE *trtbl = NULL;
+ const struct RESTART_TABLE *rt;
+ struct RESTART_TABLE *oatbl = NULL;
+ struct inode *inode;
+ struct OpenAttr *oa;
+ struct ntfs_inode *ni_oe;
+ struct ATTRIB *attr = NULL;
+ u64 size, vcn, undo_next_lsn;
+ CLST rno, lcn, lcn0, len0, clen;
+ void *data;
+ struct NTFS_RESTART *rst = NULL;
+ struct lcb *lcb = NULL;
+ struct OPEN_ATTR_ENRTY *oe;
+ struct TRANSACTION_ENTRY *tr;
+ struct DIR_PAGE_ENTRY *dp;
+ u32 i, bytes_per_attr_entry;
+ u32 l_size = ni->vfs_inode.i_size;
+ u32 orig_file_size = l_size;
+ u32 page_size, vbo, tail, off, dlen;
+ u32 saved_len, rec_len, transact_id;
+ bool use_second_page;
+ struct RESTART_AREA *ra2, *ra = NULL;
+ struct CLIENT_REC *ca, *cr;
+ __le16 client;
+ struct RESTART_HDR *rh;
+ const struct LFS_RECORD_HDR *frh;
+ const struct LOG_REC_HDR *lrh;
+ bool is_mapped;
+ bool is_ro = sb_rdonly(sbi->sb);
+ u64 t64;
+ u16 t16;
+ u32 t32;
+
+ /* Get the size of page. NOTE: To replay we can use default page. */
+#if PAGE_SIZE >= DefaultLogPageSize && PAGE_SIZE <= DefaultLogPageSize * 2
+ page_size = norm_file_page(PAGE_SIZE, &l_size, true);
+#else
+ page_size = norm_file_page(PAGE_SIZE, &l_size, false);
+#endif
+ if (!page_size)
+ return -EINVAL;
+
+ log = kzalloc(sizeof(struct ntfs_log), GFP_NOFS);
+ if (!log)
+ return -ENOMEM;
+
+ log->ni = ni;
+ log->l_size = l_size;
+ log->one_page_buf = kmalloc(page_size, GFP_NOFS);
+
+ if (!log->one_page_buf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ log->page_size = page_size;
+ log->page_mask = page_size - 1;
+ log->page_bits = blksize_bits(page_size);
+
+ /* Look for a restart area on the disk. */
+ err = log_read_rst(log, l_size, true, &rst_info);
+ if (err)
+ goto out;
+
+ /* remember 'initialized' */
+ *initialized = rst_info.initialized;
+
+ if (!rst_info.restart) {
+ if (rst_info.initialized) {
+ /* No restart area but the file is not initialized. */
+ err = -EINVAL;
+ goto out;
+ }
+
+ log_init_pg_hdr(log, page_size, page_size, 1, 1);
+ log_create(log, l_size, 0, get_random_int(), false, false);
+
+ log->ra = ra;
+
+ ra = log_create_ra(log);
+ if (!ra) {
+ err = -ENOMEM;
+ goto out;
+ }
+ log->ra = ra;
+ log->init_ra = true;
+
+ goto process_log;
+ }
+
+ /*
+ * If the restart offset above wasn't zero then we won't
+ * look for a second restart.
+ */
+ if (rst_info.vbo)
+ goto check_restart_area;
+
+ err = log_read_rst(log, l_size, false, &rst_info2);
+
+ /* Determine which restart area to use. */
+ if (!rst_info2.restart || rst_info2.last_lsn <= rst_info.last_lsn)
+ goto use_first_page;
+
+ use_second_page = true;
+
+ if (rst_info.chkdsk_was_run && page_size != rst_info.vbo) {
+ struct RECORD_PAGE_HDR *sp = NULL;
+ bool usa_error;
+
+ if (!read_log_page(log, page_size, &sp, &usa_error) &&
+ sp->rhdr.sign == NTFS_CHKD_SIGNATURE) {
+ use_second_page = false;
+ }
+ kfree(sp);
+ }
+
+ if (use_second_page) {
+ kfree(rst_info.r_page);
+ memcpy(&rst_info, &rst_info2, sizeof(struct restart_info));
+ rst_info2.r_page = NULL;
+ }
+
+use_first_page:
+ kfree(rst_info2.r_page);
+
+check_restart_area:
+ /*
+ * If the restart area is at offset 0, we want
+ * to write the second restart area first.
+ */
+ log->init_ra = !!rst_info.vbo;
+
+ /* If we have a valid page then grab a pointer to the restart area. */
+ ra2 = rst_info.valid_page
+ ? Add2Ptr(rst_info.r_page,
+ le16_to_cpu(rst_info.r_page->ra_off))
+ : NULL;
+
+ if (rst_info.chkdsk_was_run ||
+ (ra2 && ra2->client_idx[1] == LFS_NO_CLIENT_LE)) {
+ bool wrapped = false;
+ bool use_multi_page = false;
+ u32 open_log_count;
+
+ /* Do some checks based on whether we have a valid log page. */
+ if (!rst_info.valid_page) {
+ open_log_count = get_random_int();
+ goto init_log_instance;
+ }
+ open_log_count = le32_to_cpu(ra2->open_log_count);
+
+ /*
+ * If the restart page size isn't changing then we want to
+ * check how much work we need to do.
+ */
+ if (page_size != le32_to_cpu(rst_info.r_page->sys_page_size))
+ goto init_log_instance;
+
+init_log_instance:
+ log_init_pg_hdr(log, page_size, page_size, 1, 1);
+
+ log_create(log, l_size, rst_info.last_lsn, open_log_count,
+ wrapped, use_multi_page);
+
+ ra = log_create_ra(log);
+ if (!ra) {
+ err = -ENOMEM;
+ goto out;
+ }
+ log->ra = ra;
+
+ /* Put the restart areas and initialize
+ * the log file as required.
+ */
+ goto process_log;
+ }
+
+ if (!ra2) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * If the log page or the system page sizes have changed, we can't
+ * use the log file. We must use the system page size instead of the
+ * default size if there is not a clean shutdown.
+ */
+ t32 = le32_to_cpu(rst_info.r_page->sys_page_size);
+ if (page_size != t32) {
+ l_size = orig_file_size;
+ page_size =
+ norm_file_page(t32, &l_size, t32 == DefaultLogPageSize);
+ }
+
+ if (page_size != t32 ||
+ page_size != le32_to_cpu(rst_info.r_page->page_size)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* If the file size has shrunk then we won't mount it. */
+ if (l_size < le64_to_cpu(ra2->l_size)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ log_init_pg_hdr(log, page_size, page_size,
+ le16_to_cpu(rst_info.r_page->major_ver),
+ le16_to_cpu(rst_info.r_page->minor_ver));
+
+ log->l_size = le64_to_cpu(ra2->l_size);
+ log->seq_num_bits = le32_to_cpu(ra2->seq_num_bits);
+ log->file_data_bits = sizeof(u64) * 8 - log->seq_num_bits;
+ log->seq_num_mask = (8 << log->file_data_bits) - 1;
+ log->last_lsn = le64_to_cpu(ra2->current_lsn);
+ log->seq_num = log->last_lsn >> log->file_data_bits;
+ log->ra_off = le16_to_cpu(rst_info.r_page->ra_off);
+ log->restart_size = log->sys_page_size - log->ra_off;
+ log->record_header_len = le16_to_cpu(ra2->rec_hdr_len);
+ log->ra_size = le16_to_cpu(ra2->ra_len);
+ log->data_off = le16_to_cpu(ra2->data_off);
+ log->data_size = log->page_size - log->data_off;
+ log->reserved = log->data_size - log->record_header_len;
+
+ vbo = lsn_to_vbo(log, log->last_lsn);
+
+ if (vbo < log->first_page) {
+ /* This is a pseudo lsn. */
+ log->l_flags |= NTFSLOG_NO_LAST_LSN;
+ log->next_page = log->first_page;
+ goto find_oldest;
+ }
+
+ /* Find the end of this log record. */
+ off = final_log_off(log, log->last_lsn,
+ le32_to_cpu(ra2->last_lsn_data_len));
+
+ /* If we wrapped the file then increment the sequence number. */
+ if (off <= vbo) {
+ log->seq_num += 1;
+ log->l_flags |= NTFSLOG_WRAPPED;
+ }
+
+ /* Now compute the next log page to use. */
+ vbo &= ~log->sys_page_mask;
+ tail = log->page_size - (off & log->page_mask) - 1;
+
+ /*
+ *If we can fit another log record on the page,
+ * move back a page the log file.
+ */
+ if (tail >= log->record_header_len) {
+ log->l_flags |= NTFSLOG_REUSE_TAIL;
+ log->next_page = vbo;
+ } else {
+ log->next_page = next_page_off(log, vbo);
+ }
+
+find_oldest:
+ /*
+ * Find the oldest client lsn. Use the last
+ * flushed lsn as a starting point.
+ */
+ log->oldest_lsn = log->last_lsn;
+ oldest_client_lsn(Add2Ptr(ra2, le16_to_cpu(ra2->client_off)),
+ ra2->client_idx[1], &log->oldest_lsn);
+ log->oldest_lsn_off = lsn_to_vbo(log, log->oldest_lsn);
+
+ if (log->oldest_lsn_off < log->first_page)
+ log->l_flags |= NTFSLOG_NO_OLDEST_LSN;
+
+ if (!(ra2->flags & RESTART_SINGLE_PAGE_IO))
+ log->l_flags |= NTFSLOG_WRAPPED | NTFSLOG_MULTIPLE_PAGE_IO;
+
+ log->current_openlog_count = le32_to_cpu(ra2->open_log_count);
+ log->total_avail_pages = log->l_size - log->first_page;
+ log->total_avail = log->total_avail_pages >> log->page_bits;
+ log->max_current_avail = log->total_avail * log->reserved;
+ log->total_avail = log->total_avail * log->data_size;
+
+ log->current_avail = current_log_avail(log);
+
+ ra = kzalloc(log->restart_size, GFP_NOFS);
+ if (!ra) {
+ err = -ENOMEM;
+ goto out;
+ }
+ log->ra = ra;
+
+ t16 = le16_to_cpu(ra2->client_off);
+ if (t16 == offsetof(struct RESTART_AREA, clients)) {
+ memcpy(ra, ra2, log->ra_size);
+ } else {
+ memcpy(ra, ra2, offsetof(struct RESTART_AREA, clients));
+ memcpy(ra->clients, Add2Ptr(ra2, t16),
+ le16_to_cpu(ra2->ra_len) - t16);
+
+ log->current_openlog_count = get_random_int();
+ ra->open_log_count = cpu_to_le32(log->current_openlog_count);
+ log->ra_size = offsetof(struct RESTART_AREA, clients) +
+ sizeof(struct CLIENT_REC);
+ ra->client_off =
+ cpu_to_le16(offsetof(struct RESTART_AREA, clients));
+ ra->ra_len = cpu_to_le16(log->ra_size);
+ }
+
+ le32_add_cpu(&ra->open_log_count, 1);
+
+ /* Now we need to walk through looking for the last lsn. */
+ err = last_log_lsn(log);
+ if (err)
+ goto out;
+
+ log->current_avail = current_log_avail(log);
+
+ /* Remember which restart area to write first. */
+ log->init_ra = rst_info.vbo;
+
+process_log:
+ /* 1.0, 1.1, 2.0 log->major_ver/minor_ver - short values. */
+ switch ((log->major_ver << 16) + log->minor_ver) {
+ case 0x10000:
+ case 0x10001:
+ case 0x20000:
+ break;
+ default:
+ ntfs_warn(sbi->sb, "\x24LogFile version %d.%d is not supported",
+ log->major_ver, log->minor_ver);
+ err = -EOPNOTSUPP;
+ log->set_dirty = true;
+ goto out;
+ }
+
+ /* One client "NTFS" per logfile. */
+ ca = Add2Ptr(ra, le16_to_cpu(ra->client_off));
+
+ for (client = ra->client_idx[1];; client = cr->next_client) {
+ if (client == LFS_NO_CLIENT_LE) {
+ /* Insert "NTFS" client LogFile. */
+ client = ra->client_idx[0];
+ if (client == LFS_NO_CLIENT_LE)
+ return -EINVAL;
+
+ t16 = le16_to_cpu(client);
+ cr = ca + t16;
+
+ remove_client(ca, cr, &ra->client_idx[0]);
+
+ cr->restart_lsn = 0;
+ cr->oldest_lsn = cpu_to_le64(log->oldest_lsn);
+ cr->name_bytes = cpu_to_le32(8);
+ cr->name[0] = cpu_to_le16('N');
+ cr->name[1] = cpu_to_le16('T');
+ cr->name[2] = cpu_to_le16('F');
+ cr->name[3] = cpu_to_le16('S');
+
+ add_client(ca, t16, &ra->client_idx[1]);
+ break;
+ }
+
+ cr = ca + le16_to_cpu(client);
+
+ if (cpu_to_le32(8) == cr->name_bytes &&
+ cpu_to_le16('N') == cr->name[0] &&
+ cpu_to_le16('T') == cr->name[1] &&
+ cpu_to_le16('F') == cr->name[2] &&
+ cpu_to_le16('S') == cr->name[3])
+ break;
+ }
+
+ /* Update the client handle with the client block information. */
+ log->client_id.seq_num = cr->seq_num;
+ log->client_id.client_idx = client;
+
+ err = read_rst_area(log, &rst, &ra_lsn);
+ if (err)
+ goto out;
+
+ if (!rst)
+ goto out;
+
+ bytes_per_attr_entry = !rst->major_ver ? 0x2C : 0x28;
+
+ checkpt_lsn = le64_to_cpu(rst->check_point_start);
+ if (!checkpt_lsn)
+ checkpt_lsn = ra_lsn;
+
+ /* Allocate and Read the Transaction Table. */
+ if (!rst->transact_table_len)
+ goto check_dirty_page_table;
+
+ t64 = le64_to_cpu(rst->transact_table_lsn);
+ err = read_log_rec_lcb(log, t64, lcb_ctx_prev, &lcb);
+ if (err)
+ goto out;
+
+ lrh = lcb->log_rec;
+ frh = lcb->lrh;
+ rec_len = le32_to_cpu(frh->client_data_len);
+
+ if (!check_log_rec(lrh, rec_len, le32_to_cpu(frh->transact_id),
+ bytes_per_attr_entry)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ t16 = le16_to_cpu(lrh->redo_off);
+
+ rt = Add2Ptr(lrh, t16);
+ t32 = rec_len - t16;
+
+ /* Now check that this is a valid restart table. */
+ if (!check_rstbl(rt, t32)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ trtbl = kmemdup(rt, t32, GFP_NOFS);
+ if (!trtbl) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ lcb_put(lcb);
+ lcb = NULL;
+
+check_dirty_page_table:
+ /* The next record back should be the Dirty Pages Table. */
+ if (!rst->dirty_pages_len)
+ goto check_attribute_names;
+
+ t64 = le64_to_cpu(rst->dirty_pages_table_lsn);
+ err = read_log_rec_lcb(log, t64, lcb_ctx_prev, &lcb);
+ if (err)
+ goto out;
+
+ lrh = lcb->log_rec;
+ frh = lcb->lrh;
+ rec_len = le32_to_cpu(frh->client_data_len);
+
+ if (!check_log_rec(lrh, rec_len, le32_to_cpu(frh->transact_id),
+ bytes_per_attr_entry)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ t16 = le16_to_cpu(lrh->redo_off);
+
+ rt = Add2Ptr(lrh, t16);
+ t32 = rec_len - t16;
+
+ /* Now check that this is a valid restart table. */
+ if (!check_rstbl(rt, t32)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ dptbl = kmemdup(rt, t32, GFP_NOFS);
+ if (!dptbl) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* Convert Ra version '0' into version '1'. */
+ if (rst->major_ver)
+ goto end_conv_1;
+
+ dp = NULL;
+ while ((dp = enum_rstbl(dptbl, dp))) {
+ struct DIR_PAGE_ENTRY_32 *dp0 = (struct DIR_PAGE_ENTRY_32 *)dp;
+ // NOTE: Danger. Check for of boundary.
+ memmove(&dp->vcn, &dp0->vcn_low,
+ 2 * sizeof(u64) +
+ le32_to_cpu(dp->lcns_follow) * sizeof(u64));
+ }
+
+end_conv_1:
+ lcb_put(lcb);
+ lcb = NULL;
+
+ /*
+ * Go through the table and remove the duplicates,
+ * remembering the oldest lsn values.
+ */
+ if (sbi->cluster_size <= log->page_size)
+ goto trace_dp_table;
+
+ dp = NULL;
+ while ((dp = enum_rstbl(dptbl, dp))) {
+ struct DIR_PAGE_ENTRY *next = dp;
+
+ while ((next = enum_rstbl(dptbl, next))) {
+ if (next->target_attr == dp->target_attr &&
+ next->vcn == dp->vcn) {
+ if (le64_to_cpu(next->oldest_lsn) <
+ le64_to_cpu(dp->oldest_lsn)) {
+ dp->oldest_lsn = next->oldest_lsn;
+ }
+
+ free_rsttbl_idx(dptbl, PtrOffset(dptbl, next));
+ }
+ }
+ }
+trace_dp_table:
+check_attribute_names:
+ /* The next record should be the Attribute Names. */
+ if (!rst->attr_names_len)
+ goto check_attr_table;
+
+ t64 = le64_to_cpu(rst->attr_names_lsn);
+ err = read_log_rec_lcb(log, t64, lcb_ctx_prev, &lcb);
+ if (err)
+ goto out;
+
+ lrh = lcb->log_rec;
+ frh = lcb->lrh;
+ rec_len = le32_to_cpu(frh->client_data_len);
+
+ if (!check_log_rec(lrh, rec_len, le32_to_cpu(frh->transact_id),
+ bytes_per_attr_entry)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ t32 = lrh_length(lrh);
+ rec_len -= t32;
+
+ attr_names = kmemdup(Add2Ptr(lrh, t32), rec_len, GFP_NOFS);
+
+ lcb_put(lcb);
+ lcb = NULL;
+
+check_attr_table:
+ /* The next record should be the attribute Table. */
+ if (!rst->open_attr_len)
+ goto check_attribute_names2;
+
+ t64 = le64_to_cpu(rst->open_attr_table_lsn);
+ err = read_log_rec_lcb(log, t64, lcb_ctx_prev, &lcb);
+ if (err)
+ goto out;
+
+ lrh = lcb->log_rec;
+ frh = lcb->lrh;
+ rec_len = le32_to_cpu(frh->client_data_len);
+
+ if (!check_log_rec(lrh, rec_len, le32_to_cpu(frh->transact_id),
+ bytes_per_attr_entry)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ t16 = le16_to_cpu(lrh->redo_off);
+
+ rt = Add2Ptr(lrh, t16);
+ t32 = rec_len - t16;
+
+ if (!check_rstbl(rt, t32)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ oatbl = kmemdup(rt, t32, GFP_NOFS);
+ if (!oatbl) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ log->open_attr_tbl = oatbl;
+
+ /* Clear all of the Attr pointers. */
+ oe = NULL;
+ while ((oe = enum_rstbl(oatbl, oe))) {
+ if (!rst->major_ver) {
+ struct OPEN_ATTR_ENRTY_32 oe0;
+
+ /* Really 'oe' points to OPEN_ATTR_ENRTY_32. */
+ memcpy(&oe0, oe, SIZEOF_OPENATTRIBUTEENTRY0);
+
+ oe->bytes_per_index = oe0.bytes_per_index;
+ oe->type = oe0.type;
+ oe->is_dirty_pages = oe0.is_dirty_pages;
+ oe->name_len = 0;
+ oe->ref = oe0.ref;
+ oe->open_record_lsn = oe0.open_record_lsn;
+ }
+
+ oe->is_attr_name = 0;
+ oe->ptr = NULL;
+ }
+
+ lcb_put(lcb);
+ lcb = NULL;
+
+check_attribute_names2:
+ if (!rst->attr_names_len)
+ goto trace_attribute_table;
+
+ ane = attr_names;
+ if (!oatbl)
+ goto trace_attribute_table;
+ while (ane->off) {
+ /* TODO: Clear table on exit! */
+ oe = Add2Ptr(oatbl, le16_to_cpu(ane->off));
+ t16 = le16_to_cpu(ane->name_bytes);
+ oe->name_len = t16 / sizeof(short);
+ oe->ptr = ane->name;
+ oe->is_attr_name = 2;
+ ane = Add2Ptr(ane, sizeof(struct ATTR_NAME_ENTRY) + t16);
+ }
+
+trace_attribute_table:
+ /*
+ * If the checkpt_lsn is zero, then this is a freshly
+ * formatted disk and we have no work to do.
+ */
+ if (!checkpt_lsn) {
+ err = 0;
+ goto out;
+ }
+
+ if (!oatbl) {
+ oatbl = init_rsttbl(bytes_per_attr_entry, 8);
+ if (!oatbl) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
+
+ log->open_attr_tbl = oatbl;
+
+ /* Start the analysis pass from the Checkpoint lsn. */
+ rec_lsn = checkpt_lsn;
+
+ /* Read the first lsn. */
+ err = read_log_rec_lcb(log, checkpt_lsn, lcb_ctx_next, &lcb);
+ if (err)
+ goto out;
+
+ /* Loop to read all subsequent records to the end of the log file. */
+next_log_record_analyze:
+ err = read_next_log_rec(log, lcb, &rec_lsn);
+ if (err)
+ goto out;
+
+ if (!rec_lsn)
+ goto end_log_records_enumerate;
+
+ frh = lcb->lrh;
+ transact_id = le32_to_cpu(frh->transact_id);
+ rec_len = le32_to_cpu(frh->client_data_len);
+ lrh = lcb->log_rec;
+
+ if (!check_log_rec(lrh, rec_len, transact_id, bytes_per_attr_entry)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * The first lsn after the previous lsn remembered
+ * the checkpoint is the first candidate for the rlsn.
+ */
+ if (!rlsn)
+ rlsn = rec_lsn;
+
+ if (LfsClientRecord != frh->record_type)
+ goto next_log_record_analyze;
+
+ /*
+ * Now update the Transaction Table for this transaction. If there
+ * is no entry present or it is unallocated we allocate the entry.
+ */
+ if (!trtbl) {
+ trtbl = init_rsttbl(sizeof(struct TRANSACTION_ENTRY),
+ INITIAL_NUMBER_TRANSACTIONS);
+ if (!trtbl) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
+
+ tr = Add2Ptr(trtbl, transact_id);
+
+ if (transact_id >= bytes_per_rt(trtbl) ||
+ tr->next != RESTART_ENTRY_ALLOCATED_LE) {
+ tr = alloc_rsttbl_from_idx(&trtbl, transact_id);
+ if (!tr) {
+ err = -ENOMEM;
+ goto out;
+ }
+ tr->transact_state = TransactionActive;
+ tr->first_lsn = cpu_to_le64(rec_lsn);
+ }
+
+ tr->prev_lsn = tr->undo_next_lsn = cpu_to_le64(rec_lsn);
+
+ /*
+ * If this is a compensation log record, then change
+ * the undo_next_lsn to be the undo_next_lsn of this record.
+ */
+ if (lrh->undo_op == cpu_to_le16(CompensationLogRecord))
+ tr->undo_next_lsn = frh->client_undo_next_lsn;
+
+ /* Dispatch to handle log record depending on type. */
+ switch (le16_to_cpu(lrh->redo_op)) {
+ case InitializeFileRecordSegment:
+ case DeallocateFileRecordSegment:
+ case WriteEndOfFileRecordSegment:
+ case CreateAttribute:
+ case DeleteAttribute:
+ case UpdateResidentValue:
+ case UpdateNonresidentValue:
+ case UpdateMappingPairs:
+ case SetNewAttributeSizes:
+ case AddIndexEntryRoot:
+ case DeleteIndexEntryRoot:
+ case AddIndexEntryAllocation:
+ case DeleteIndexEntryAllocation:
+ case WriteEndOfIndexBuffer:
+ case SetIndexEntryVcnRoot:
+ case SetIndexEntryVcnAllocation:
+ case UpdateFileNameRoot:
+ case UpdateFileNameAllocation:
+ case SetBitsInNonresidentBitMap:
+ case ClearBitsInNonresidentBitMap:
+ case UpdateRecordDataRoot:
+ case UpdateRecordDataAllocation:
+ case ZeroEndOfFileRecord:
+ t16 = le16_to_cpu(lrh->target_attr);
+ t64 = le64_to_cpu(lrh->target_vcn);
+ dp = find_dp(dptbl, t16, t64);
+
+ if (dp)
+ goto copy_lcns;
+
+ /*
+ * Calculate the number of clusters per page the system
+ * which wrote the checkpoint, possibly creating the table.
+ */
+ if (dptbl) {
+ t32 = (le16_to_cpu(dptbl->size) -
+ sizeof(struct DIR_PAGE_ENTRY)) /
+ sizeof(u64);
+ } else {
+ t32 = log->clst_per_page;
+ kfree(dptbl);
+ dptbl = init_rsttbl(struct_size(dp, page_lcns, t32),
+ 32);
+ if (!dptbl) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
+
+ dp = alloc_rsttbl_idx(&dptbl);
+ if (!dp) {
+ err = -ENOMEM;
+ goto out;
+ }
+ dp->target_attr = cpu_to_le32(t16);
+ dp->transfer_len = cpu_to_le32(t32 << sbi->cluster_bits);
+ dp->lcns_follow = cpu_to_le32(t32);
+ dp->vcn = cpu_to_le64(t64 & ~((u64)t32 - 1));
+ dp->oldest_lsn = cpu_to_le64(rec_lsn);
+
+copy_lcns:
+ /*
+ * Copy the Lcns from the log record into the Dirty Page Entry.
+ * TODO: For different page size support, must somehow make
+ * whole routine a loop, case Lcns do not fit below.
+ */
+ t16 = le16_to_cpu(lrh->lcns_follow);
+ for (i = 0; i < t16; i++) {
+ size_t j = (size_t)(le64_to_cpu(lrh->target_vcn) -
+ le64_to_cpu(dp->vcn));
+ dp->page_lcns[j + i] = lrh->page_lcns[i];
+ }
+
+ goto next_log_record_analyze;
+
+ case DeleteDirtyClusters: {
+ u32 range_count =
+ le16_to_cpu(lrh->redo_len) / sizeof(struct LCN_RANGE);
+ const struct LCN_RANGE *r =
+ Add2Ptr(lrh, le16_to_cpu(lrh->redo_off));
+
+ /* Loop through all of the Lcn ranges this log record. */
+ for (i = 0; i < range_count; i++, r++) {
+ u64 lcn0 = le64_to_cpu(r->lcn);
+ u64 lcn_e = lcn0 + le64_to_cpu(r->len) - 1;
+
+ dp = NULL;
+ while ((dp = enum_rstbl(dptbl, dp))) {
+ u32 j;
+
+ t32 = le32_to_cpu(dp->lcns_follow);
+ for (j = 0; j < t32; j++) {
+ t64 = le64_to_cpu(dp->page_lcns[j]);
+ if (t64 >= lcn0 && t64 <= lcn_e)
+ dp->page_lcns[j] = 0;
+ }
+ }
+ }
+ goto next_log_record_analyze;
+ ;
+ }
+
+ case OpenNonresidentAttribute:
+ t16 = le16_to_cpu(lrh->target_attr);
+ if (t16 >= bytes_per_rt(oatbl)) {
+ /*
+ * Compute how big the table needs to be.
+ * Add 10 extra entries for some cushion.
+ */
+ u32 new_e = t16 / le16_to_cpu(oatbl->size);
+
+ new_e += 10 - le16_to_cpu(oatbl->used);
+
+ oatbl = extend_rsttbl(oatbl, new_e, ~0u);
+ log->open_attr_tbl = oatbl;
+ if (!oatbl) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
+
+ /* Point to the entry being opened. */
+ oe = alloc_rsttbl_from_idx(&oatbl, t16);
+ log->open_attr_tbl = oatbl;
+ if (!oe) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* Initialize this entry from the log record. */
+ t16 = le16_to_cpu(lrh->redo_off);
+ if (!rst->major_ver) {
+ /* Convert version '0' into version '1'. */
+ struct OPEN_ATTR_ENRTY_32 *oe0 = Add2Ptr(lrh, t16);
+
+ oe->bytes_per_index = oe0->bytes_per_index;
+ oe->type = oe0->type;
+ oe->is_dirty_pages = oe0->is_dirty_pages;
+ oe->name_len = 0; //oe0.name_len;
+ oe->ref = oe0->ref;
+ oe->open_record_lsn = oe0->open_record_lsn;
+ } else {
+ memcpy(oe, Add2Ptr(lrh, t16), bytes_per_attr_entry);
+ }
+
+ t16 = le16_to_cpu(lrh->undo_len);
+ if (t16) {
+ oe->ptr = kmalloc(t16, GFP_NOFS);
+ if (!oe->ptr) {
+ err = -ENOMEM;
+ goto out;
+ }
+ oe->name_len = t16 / sizeof(short);
+ memcpy(oe->ptr,
+ Add2Ptr(lrh, le16_to_cpu(lrh->undo_off)), t16);
+ oe->is_attr_name = 1;
+ } else {
+ oe->ptr = NULL;
+ oe->is_attr_name = 0;
+ }
+
+ goto next_log_record_analyze;
+
+ case HotFix:
+ t16 = le16_to_cpu(lrh->target_attr);
+ t64 = le64_to_cpu(lrh->target_vcn);
+ dp = find_dp(dptbl, t16, t64);
+ if (dp) {
+ size_t j = le64_to_cpu(lrh->target_vcn) -
+ le64_to_cpu(dp->vcn);
+ if (dp->page_lcns[j])
+ dp->page_lcns[j] = lrh->page_lcns[0];
+ }
+ goto next_log_record_analyze;
+
+ case EndTopLevelAction:
+ tr = Add2Ptr(trtbl, transact_id);
+ tr->prev_lsn = cpu_to_le64(rec_lsn);
+ tr->undo_next_lsn = frh->client_undo_next_lsn;
+ goto next_log_record_analyze;
+
+ case PrepareTransaction:
+ tr = Add2Ptr(trtbl, transact_id);
+ tr->transact_state = TransactionPrepared;
+ goto next_log_record_analyze;
+
+ case CommitTransaction:
+ tr = Add2Ptr(trtbl, transact_id);
+ tr->transact_state = TransactionCommitted;
+ goto next_log_record_analyze;
+
+ case ForgetTransaction:
+ free_rsttbl_idx(trtbl, transact_id);
+ goto next_log_record_analyze;
+
+ case Noop:
+ case OpenAttributeTableDump:
+ case AttributeNamesDump:
+ case DirtyPageTableDump:
+ case TransactionTableDump:
+ /* The following cases require no action the Analysis Pass. */
+ goto next_log_record_analyze;
+
+ default:
+ /*
+ * All codes will be explicitly handled.
+ * If we see a code we do not expect, then we are trouble.
+ */
+ goto next_log_record_analyze;
+ }
+
+end_log_records_enumerate:
+ lcb_put(lcb);
+ lcb = NULL;
+
+ /*
+ * Scan the Dirty Page Table and Transaction Table for
+ * the lowest lsn, and return it as the Redo lsn.
+ */
+ dp = NULL;
+ while ((dp = enum_rstbl(dptbl, dp))) {
+ t64 = le64_to_cpu(dp->oldest_lsn);
+ if (t64 && t64 < rlsn)
+ rlsn = t64;
+ }
+
+ tr = NULL;
+ while ((tr = enum_rstbl(trtbl, tr))) {
+ t64 = le64_to_cpu(tr->first_lsn);
+ if (t64 && t64 < rlsn)
+ rlsn = t64;
+ }
+
+ /*
+ * Only proceed if the Dirty Page Table or Transaction
+ * table are not empty.
+ */
+ if ((!dptbl || !dptbl->total) && (!trtbl || !trtbl->total))
+ goto end_reply;
+
+ sbi->flags |= NTFS_FLAGS_NEED_REPLAY;
+ if (is_ro)
+ goto out;
+
+ /* Reopen all of the attributes with dirty pages. */
+ oe = NULL;
+next_open_attribute:
+
+ oe = enum_rstbl(oatbl, oe);
+ if (!oe) {
+ err = 0;
+ dp = NULL;
+ goto next_dirty_page;
+ }
+
+ oa = kzalloc(sizeof(struct OpenAttr), GFP_NOFS);
+ if (!oa) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ inode = ntfs_iget5(sbi->sb, &oe->ref, NULL);
+ if (IS_ERR(inode))
+ goto fake_attr;
+
+ if (is_bad_inode(inode)) {
+ iput(inode);
+fake_attr:
+ if (oa->ni) {
+ iput(&oa->ni->vfs_inode);
+ oa->ni = NULL;
+ }
+
+ attr = attr_create_nonres_log(sbi, oe->type, 0, oe->ptr,
+ oe->name_len, 0);
+ if (!attr) {
+ kfree(oa);
+ err = -ENOMEM;
+ goto out;
+ }
+ oa->attr = attr;
+ oa->run1 = &oa->run0;
+ goto final_oe;
+ }
+
+ ni_oe = ntfs_i(inode);
+ oa->ni = ni_oe;
+
+ attr = ni_find_attr(ni_oe, NULL, NULL, oe->type, oe->ptr, oe->name_len,
+ NULL, NULL);
+
+ if (!attr)
+ goto fake_attr;
+
+ t32 = le32_to_cpu(attr->size);
+ oa->attr = kmemdup(attr, t32, GFP_NOFS);
+ if (!oa->attr)
+ goto fake_attr;
+
+ if (!S_ISDIR(inode->i_mode)) {
+ if (attr->type == ATTR_DATA && !attr->name_len) {
+ oa->run1 = &ni_oe->file.run;
+ goto final_oe;
+ }
+ } else {
+ if (attr->type == ATTR_ALLOC &&
+ attr->name_len == ARRAY_SIZE(I30_NAME) &&
+ !memcmp(attr_name(attr), I30_NAME, sizeof(I30_NAME))) {
+ oa->run1 = &ni_oe->dir.alloc_run;
+ goto final_oe;
+ }
+ }
+
+ if (attr->non_res) {
+ u16 roff = le16_to_cpu(attr->nres.run_off);
+ CLST svcn = le64_to_cpu(attr->nres.svcn);
+
+ err = run_unpack(&oa->run0, sbi, inode->i_ino, svcn,
+ le64_to_cpu(attr->nres.evcn), svcn,
+ Add2Ptr(attr, roff), t32 - roff);
+ if (err < 0) {
+ kfree(oa->attr);
+ oa->attr = NULL;
+ goto fake_attr;
+ }
+ err = 0;
+ }
+ oa->run1 = &oa->run0;
+ attr = oa->attr;
+
+final_oe:
+ if (oe->is_attr_name == 1)
+ kfree(oe->ptr);
+ oe->is_attr_name = 0;
+ oe->ptr = oa;
+ oe->name_len = attr->name_len;
+
+ goto next_open_attribute;
+
+ /*
+ * Now loop through the dirty page table to extract all of the Vcn/Lcn.
+ * Mapping that we have, and insert it into the appropriate run.
+ */
+next_dirty_page:
+ dp = enum_rstbl(dptbl, dp);
+ if (!dp)
+ goto do_redo_1;
+
+ oe = Add2Ptr(oatbl, le32_to_cpu(dp->target_attr));
+
+ if (oe->next != RESTART_ENTRY_ALLOCATED_LE)
+ goto next_dirty_page;
+
+ oa = oe->ptr;
+ if (!oa)
+ goto next_dirty_page;
+
+ i = -1;
+next_dirty_page_vcn:
+ i += 1;
+ if (i >= le32_to_cpu(dp->lcns_follow))
+ goto next_dirty_page;
+
+ vcn = le64_to_cpu(dp->vcn) + i;
+ size = (vcn + 1) << sbi->cluster_bits;
+
+ if (!dp->page_lcns[i])
+ goto next_dirty_page_vcn;
+
+ rno = ino_get(&oe->ref);
+ if (rno <= MFT_REC_MIRR &&
+ size < (MFT_REC_VOL + 1) * sbi->record_size &&
+ oe->type == ATTR_DATA) {
+ goto next_dirty_page_vcn;
+ }
+
+ lcn = le64_to_cpu(dp->page_lcns[i]);
+
+ if ((!run_lookup_entry(oa->run1, vcn, &lcn0, &len0, NULL) ||
+ lcn0 != lcn) &&
+ !run_add_entry(oa->run1, vcn, lcn, 1, false)) {
+ err = -ENOMEM;
+ goto out;
+ }
+ attr = oa->attr;
+ t64 = le64_to_cpu(attr->nres.alloc_size);
+ if (size > t64) {
+ attr->nres.valid_size = attr->nres.data_size =
+ attr->nres.alloc_size = cpu_to_le64(size);
+ }
+ goto next_dirty_page_vcn;
+
+do_redo_1:
+ /*
+ * Perform the Redo Pass, to restore all of the dirty pages to the same
+ * contents that they had immediately before the crash. If the dirty
+ * page table is empty, then we can skip the entire Redo Pass.
+ */
+ if (!dptbl || !dptbl->total)
+ goto do_undo_action;
+
+ rec_lsn = rlsn;
+
+ /*
+ * Read the record at the Redo lsn, before falling
+ * into common code to handle each record.
+ */
+ err = read_log_rec_lcb(log, rlsn, lcb_ctx_next, &lcb);
+ if (err)
+ goto out;
+
+ /*
+ * Now loop to read all of our log records forwards, until
+ * we hit the end of the file, cleaning up at the end.
+ */
+do_action_next:
+ frh = lcb->lrh;
+
+ if (LfsClientRecord != frh->record_type)
+ goto read_next_log_do_action;
+
+ transact_id = le32_to_cpu(frh->transact_id);
+ rec_len = le32_to_cpu(frh->client_data_len);
+ lrh = lcb->log_rec;
+
+ if (!check_log_rec(lrh, rec_len, transact_id, bytes_per_attr_entry)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Ignore log records that do not update pages. */
+ if (lrh->lcns_follow)
+ goto find_dirty_page;
+
+ goto read_next_log_do_action;
+
+find_dirty_page:
+ t16 = le16_to_cpu(lrh->target_attr);
+ t64 = le64_to_cpu(lrh->target_vcn);
+ dp = find_dp(dptbl, t16, t64);
+
+ if (!dp)
+ goto read_next_log_do_action;
+
+ if (rec_lsn < le64_to_cpu(dp->oldest_lsn))
+ goto read_next_log_do_action;
+
+ t16 = le16_to_cpu(lrh->target_attr);
+ if (t16 >= bytes_per_rt(oatbl)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ oe = Add2Ptr(oatbl, t16);
+
+ if (oe->next != RESTART_ENTRY_ALLOCATED_LE) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ oa = oe->ptr;
+
+ if (!oa) {
+ err = -EINVAL;
+ goto out;
+ }
+ attr = oa->attr;
+
+ vcn = le64_to_cpu(lrh->target_vcn);
+
+ if (!run_lookup_entry(oa->run1, vcn, &lcn, NULL, NULL) ||
+ lcn == SPARSE_LCN) {
+ goto read_next_log_do_action;
+ }
+
+ /* Point to the Redo data and get its length. */
+ data = Add2Ptr(lrh, le16_to_cpu(lrh->redo_off));
+ dlen = le16_to_cpu(lrh->redo_len);
+
+ /* Shorten length by any Lcns which were deleted. */
+ saved_len = dlen;
+
+ for (i = le16_to_cpu(lrh->lcns_follow); i; i--) {
+ size_t j;
+ u32 alen, voff;
+
+ voff = le16_to_cpu(lrh->record_off) +
+ le16_to_cpu(lrh->attr_off);
+ voff += le16_to_cpu(lrh->cluster_off) << SECTOR_SHIFT;
+
+ /* If the Vcn question is allocated, we can just get out. */
+ j = le64_to_cpu(lrh->target_vcn) - le64_to_cpu(dp->vcn);
+ if (dp->page_lcns[j + i - 1])
+ break;
+
+ if (!saved_len)
+ saved_len = 1;
+
+ /*
+ * Calculate the allocated space left relative to the
+ * log record Vcn, after removing this unallocated Vcn.
+ */
+ alen = (i - 1) << sbi->cluster_bits;
+
+ /*
+ * If the update described this log record goes beyond
+ * the allocated space, then we will have to reduce the length.
+ */
+ if (voff >= alen)
+ dlen = 0;
+ else if (voff + dlen > alen)
+ dlen = alen - voff;
+ }
+
+ /*
+ * If the resulting dlen from above is now zero,
+ * we can skip this log record.
+ */
+ if (!dlen && saved_len)
+ goto read_next_log_do_action;
+
+ t16 = le16_to_cpu(lrh->redo_op);
+ if (can_skip_action(t16))
+ goto read_next_log_do_action;
+
+ /* Apply the Redo operation a common routine. */
+ err = do_action(log, oe, lrh, t16, data, dlen, rec_len, &rec_lsn);
+ if (err)
+ goto out;
+
+ /* Keep reading and looping back until end of file. */
+read_next_log_do_action:
+ err = read_next_log_rec(log, lcb, &rec_lsn);
+ if (!err && rec_lsn)
+ goto do_action_next;
+
+ lcb_put(lcb);
+ lcb = NULL;
+
+do_undo_action:
+ /* Scan Transaction Table. */
+ tr = NULL;
+transaction_table_next:
+ tr = enum_rstbl(trtbl, tr);
+ if (!tr)
+ goto undo_action_done;
+
+ if (TransactionActive != tr->transact_state || !tr->undo_next_lsn) {
+ free_rsttbl_idx(trtbl, PtrOffset(trtbl, tr));
+ goto transaction_table_next;
+ }
+
+ log->transaction_id = PtrOffset(trtbl, tr);
+ undo_next_lsn = le64_to_cpu(tr->undo_next_lsn);
+
+ /*
+ * We only have to do anything if the transaction has
+ * something its undo_next_lsn field.
+ */
+ if (!undo_next_lsn)
+ goto commit_undo;
+
+ /* Read the first record to be undone by this transaction. */
+ err = read_log_rec_lcb(log, undo_next_lsn, lcb_ctx_undo_next, &lcb);
+ if (err)
+ goto out;
+
+ /*
+ * Now loop to read all of our log records forwards,
+ * until we hit the end of the file, cleaning up at the end.
+ */
+undo_action_next:
+
+ lrh = lcb->log_rec;
+ frh = lcb->lrh;
+ transact_id = le32_to_cpu(frh->transact_id);
+ rec_len = le32_to_cpu(frh->client_data_len);
+
+ if (!check_log_rec(lrh, rec_len, transact_id, bytes_per_attr_entry)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (lrh->undo_op == cpu_to_le16(Noop))
+ goto read_next_log_undo_action;
+
+ oe = Add2Ptr(oatbl, le16_to_cpu(lrh->target_attr));
+ oa = oe->ptr;
+
+ t16 = le16_to_cpu(lrh->lcns_follow);
+ if (!t16)
+ goto add_allocated_vcns;
+
+ is_mapped = run_lookup_entry(oa->run1, le64_to_cpu(lrh->target_vcn),
+ &lcn, &clen, NULL);
+
+ /*
+ * If the mapping isn't already the table or the mapping
+ * corresponds to a hole the mapping, we need to make sure
+ * there is no partial page already memory.
+ */
+ if (is_mapped && lcn != SPARSE_LCN && clen >= t16)
+ goto add_allocated_vcns;
+
+ vcn = le64_to_cpu(lrh->target_vcn);
+ vcn &= ~(log->clst_per_page - 1);
+
+add_allocated_vcns:
+ for (i = 0, vcn = le64_to_cpu(lrh->target_vcn),
+ size = (vcn + 1) << sbi->cluster_bits;
+ i < t16; i++, vcn += 1, size += sbi->cluster_size) {
+ attr = oa->attr;
+ if (!attr->non_res) {
+ if (size > le32_to_cpu(attr->res.data_size))
+ attr->res.data_size = cpu_to_le32(size);
+ } else {
+ if (size > le64_to_cpu(attr->nres.data_size))
+ attr->nres.valid_size = attr->nres.data_size =
+ attr->nres.alloc_size =
+ cpu_to_le64(size);
+ }
+ }
+
+ t16 = le16_to_cpu(lrh->undo_op);
+ if (can_skip_action(t16))
+ goto read_next_log_undo_action;
+
+ /* Point to the Redo data and get its length. */
+ data = Add2Ptr(lrh, le16_to_cpu(lrh->undo_off));
+ dlen = le16_to_cpu(lrh->undo_len);
+
+ /* It is time to apply the undo action. */
+ err = do_action(log, oe, lrh, t16, data, dlen, rec_len, NULL);
+
+read_next_log_undo_action:
+ /*
+ * Keep reading and looping back until we have read the
+ * last record for this transaction.
+ */
+ err = read_next_log_rec(log, lcb, &rec_lsn);
+ if (err)
+ goto out;
+
+ if (rec_lsn)
+ goto undo_action_next;
+
+ lcb_put(lcb);
+ lcb = NULL;
+
+commit_undo:
+ free_rsttbl_idx(trtbl, log->transaction_id);
+
+ log->transaction_id = 0;
+
+ goto transaction_table_next;
+
+undo_action_done:
+
+ ntfs_update_mftmirr(sbi, 0);
+
+ sbi->flags &= ~NTFS_FLAGS_NEED_REPLAY;
+
+end_reply:
+
+ err = 0;
+ if (is_ro)
+ goto out;
+
+ rh = kzalloc(log->page_size, GFP_NOFS);
+ if (!rh) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ rh->rhdr.sign = NTFS_RSTR_SIGNATURE;
+ rh->rhdr.fix_off = cpu_to_le16(offsetof(struct RESTART_HDR, fixups));
+ t16 = (log->page_size >> SECTOR_SHIFT) + 1;
+ rh->rhdr.fix_num = cpu_to_le16(t16);
+ rh->sys_page_size = cpu_to_le32(log->page_size);
+ rh->page_size = cpu_to_le32(log->page_size);
+
+ t16 = ALIGN(offsetof(struct RESTART_HDR, fixups) + sizeof(short) * t16,
+ 8);
+ rh->ra_off = cpu_to_le16(t16);
+ rh->minor_ver = cpu_to_le16(1); // 0x1A:
+ rh->major_ver = cpu_to_le16(1); // 0x1C:
+
+ ra2 = Add2Ptr(rh, t16);
+ memcpy(ra2, ra, sizeof(struct RESTART_AREA));
+
+ ra2->client_idx[0] = 0;
+ ra2->client_idx[1] = LFS_NO_CLIENT_LE;
+ ra2->flags = cpu_to_le16(2);
+
+ le32_add_cpu(&ra2->open_log_count, 1);
+
+ ntfs_fix_pre_write(&rh->rhdr, log->page_size);
+
+ err = ntfs_sb_write_run(sbi, &ni->file.run, 0, rh, log->page_size);
+ if (!err)
+ err = ntfs_sb_write_run(sbi, &log->ni->file.run, log->page_size,
+ rh, log->page_size);
+
+ kfree(rh);
+ if (err)
+ goto out;
+
+out:
+ kfree(rst);
+ if (lcb)
+ lcb_put(lcb);
+
+ /*
+ * Scan the Open Attribute Table to close all of
+ * the open attributes.
+ */
+ oe = NULL;
+ while ((oe = enum_rstbl(oatbl, oe))) {
+ rno = ino_get(&oe->ref);
+
+ if (oe->is_attr_name == 1) {
+ kfree(oe->ptr);
+ oe->ptr = NULL;
+ continue;
+ }
+
+ if (oe->is_attr_name)
+ continue;
+
+ oa = oe->ptr;
+ if (!oa)
+ continue;
+
+ run_close(&oa->run0);
+ kfree(oa->attr);
+ if (oa->ni)
+ iput(&oa->ni->vfs_inode);
+ kfree(oa);
+ }
+
+ kfree(trtbl);
+ kfree(oatbl);
+ kfree(dptbl);
+ kfree(attr_names);
+ kfree(rst_info.r_page);
+
+ kfree(ra);
+ kfree(log->one_page_buf);
+
+ if (err)
+ sbi->flags |= NTFS_FLAGS_NEED_REPLAY;
+
+ if (err == -EROFS)
+ err = 0;
+ else if (log->set_dirty)
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+
+ kfree(log);
+
+ return err;
+}
diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c
new file mode 100644
index 000000000000..91e3743e1442
--- /dev/null
+++ b/fs/ntfs3/fsntfs.c
@@ -0,0 +1,2509 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+// clang-format off
+const struct cpu_str NAME_MFT = {
+ 4, 0, { '$', 'M', 'F', 'T' },
+};
+const struct cpu_str NAME_MIRROR = {
+ 8, 0, { '$', 'M', 'F', 'T', 'M', 'i', 'r', 'r' },
+};
+const struct cpu_str NAME_LOGFILE = {
+ 8, 0, { '$', 'L', 'o', 'g', 'F', 'i', 'l', 'e' },
+};
+const struct cpu_str NAME_VOLUME = {
+ 7, 0, { '$', 'V', 'o', 'l', 'u', 'm', 'e' },
+};
+const struct cpu_str NAME_ATTRDEF = {
+ 8, 0, { '$', 'A', 't', 't', 'r', 'D', 'e', 'f' },
+};
+const struct cpu_str NAME_ROOT = {
+ 1, 0, { '.' },
+};
+const struct cpu_str NAME_BITMAP = {
+ 7, 0, { '$', 'B', 'i', 't', 'm', 'a', 'p' },
+};
+const struct cpu_str NAME_BOOT = {
+ 5, 0, { '$', 'B', 'o', 'o', 't' },
+};
+const struct cpu_str NAME_BADCLUS = {
+ 8, 0, { '$', 'B', 'a', 'd', 'C', 'l', 'u', 's' },
+};
+const struct cpu_str NAME_QUOTA = {
+ 6, 0, { '$', 'Q', 'u', 'o', 't', 'a' },
+};
+const struct cpu_str NAME_SECURE = {
+ 7, 0, { '$', 'S', 'e', 'c', 'u', 'r', 'e' },
+};
+const struct cpu_str NAME_UPCASE = {
+ 7, 0, { '$', 'U', 'p', 'C', 'a', 's', 'e' },
+};
+const struct cpu_str NAME_EXTEND = {
+ 7, 0, { '$', 'E', 'x', 't', 'e', 'n', 'd' },
+};
+const struct cpu_str NAME_OBJID = {
+ 6, 0, { '$', 'O', 'b', 'j', 'I', 'd' },
+};
+const struct cpu_str NAME_REPARSE = {
+ 8, 0, { '$', 'R', 'e', 'p', 'a', 'r', 's', 'e' },
+};
+const struct cpu_str NAME_USNJRNL = {
+ 8, 0, { '$', 'U', 's', 'n', 'J', 'r', 'n', 'l' },
+};
+const __le16 BAD_NAME[4] = {
+ cpu_to_le16('$'), cpu_to_le16('B'), cpu_to_le16('a'), cpu_to_le16('d'),
+};
+const __le16 I30_NAME[4] = {
+ cpu_to_le16('$'), cpu_to_le16('I'), cpu_to_le16('3'), cpu_to_le16('0'),
+};
+const __le16 SII_NAME[4] = {
+ cpu_to_le16('$'), cpu_to_le16('S'), cpu_to_le16('I'), cpu_to_le16('I'),
+};
+const __le16 SDH_NAME[4] = {
+ cpu_to_le16('$'), cpu_to_le16('S'), cpu_to_le16('D'), cpu_to_le16('H'),
+};
+const __le16 SDS_NAME[4] = {
+ cpu_to_le16('$'), cpu_to_le16('S'), cpu_to_le16('D'), cpu_to_le16('S'),
+};
+const __le16 SO_NAME[2] = {
+ cpu_to_le16('$'), cpu_to_le16('O'),
+};
+const __le16 SQ_NAME[2] = {
+ cpu_to_le16('$'), cpu_to_le16('Q'),
+};
+const __le16 SR_NAME[2] = {
+ cpu_to_le16('$'), cpu_to_le16('R'),
+};
+
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+const __le16 WOF_NAME[17] = {
+ cpu_to_le16('W'), cpu_to_le16('o'), cpu_to_le16('f'), cpu_to_le16('C'),
+ cpu_to_le16('o'), cpu_to_le16('m'), cpu_to_le16('p'), cpu_to_le16('r'),
+ cpu_to_le16('e'), cpu_to_le16('s'), cpu_to_le16('s'), cpu_to_le16('e'),
+ cpu_to_le16('d'), cpu_to_le16('D'), cpu_to_le16('a'), cpu_to_le16('t'),
+ cpu_to_le16('a'),
+};
+#endif
+
+// clang-format on
+
+/*
+ * ntfs_fix_pre_write - Insert fixups into @rhdr before writing to disk.
+ */
+bool ntfs_fix_pre_write(struct NTFS_RECORD_HEADER *rhdr, size_t bytes)
+{
+ u16 *fixup, *ptr;
+ u16 sample;
+ u16 fo = le16_to_cpu(rhdr->fix_off);
+ u16 fn = le16_to_cpu(rhdr->fix_num);
+
+ if ((fo & 1) || fo + fn * sizeof(short) > SECTOR_SIZE || !fn-- ||
+ fn * SECTOR_SIZE > bytes) {
+ return false;
+ }
+
+ /* Get fixup pointer. */
+ fixup = Add2Ptr(rhdr, fo);
+
+ if (*fixup >= 0x7FFF)
+ *fixup = 1;
+ else
+ *fixup += 1;
+
+ sample = *fixup;
+
+ ptr = Add2Ptr(rhdr, SECTOR_SIZE - sizeof(short));
+
+ while (fn--) {
+ *++fixup = *ptr;
+ *ptr = sample;
+ ptr += SECTOR_SIZE / sizeof(short);
+ }
+ return true;
+}
+
+/*
+ * ntfs_fix_post_read - Remove fixups after reading from disk.
+ *
+ * Return: < 0 if error, 0 if ok, 1 if need to update fixups.
+ */
+int ntfs_fix_post_read(struct NTFS_RECORD_HEADER *rhdr, size_t bytes,
+ bool simple)
+{
+ int ret;
+ u16 *fixup, *ptr;
+ u16 sample, fo, fn;
+
+ fo = le16_to_cpu(rhdr->fix_off);
+ fn = simple ? ((bytes >> SECTOR_SHIFT) + 1)
+ : le16_to_cpu(rhdr->fix_num);
+
+ /* Check errors. */
+ if ((fo & 1) || fo + fn * sizeof(short) > SECTOR_SIZE || !fn-- ||
+ fn * SECTOR_SIZE > bytes) {
+ return -EINVAL; /* Native chkntfs returns ok! */
+ }
+
+ /* Get fixup pointer. */
+ fixup = Add2Ptr(rhdr, fo);
+ sample = *fixup;
+ ptr = Add2Ptr(rhdr, SECTOR_SIZE - sizeof(short));
+ ret = 0;
+
+ while (fn--) {
+ /* Test current word. */
+ if (*ptr != sample) {
+ /* Fixup does not match! Is it serious error? */
+ ret = -E_NTFS_FIXUP;
+ }
+
+ /* Replace fixup. */
+ *ptr = *++fixup;
+ ptr += SECTOR_SIZE / sizeof(short);
+ }
+
+ return ret;
+}
+
+/*
+ * ntfs_extend_init - Load $Extend file.
+ */
+int ntfs_extend_init(struct ntfs_sb_info *sbi)
+{
+ int err;
+ struct super_block *sb = sbi->sb;
+ struct inode *inode, *inode2;
+ struct MFT_REF ref;
+
+ if (sbi->volume.major_ver < 3) {
+ ntfs_notice(sb, "Skip $Extend 'cause NTFS version");
+ return 0;
+ }
+
+ ref.low = cpu_to_le32(MFT_REC_EXTEND);
+ ref.high = 0;
+ ref.seq = cpu_to_le16(MFT_REC_EXTEND);
+ inode = ntfs_iget5(sb, &ref, &NAME_EXTEND);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load $Extend.");
+ inode = NULL;
+ goto out;
+ }
+
+ /* If ntfs_iget5() reads from disk it never returns bad inode. */
+ if (!S_ISDIR(inode->i_mode)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Try to find $ObjId */
+ inode2 = dir_search_u(inode, &NAME_OBJID, NULL);
+ if (inode2 && !IS_ERR(inode2)) {
+ if (is_bad_inode(inode2)) {
+ iput(inode2);
+ } else {
+ sbi->objid.ni = ntfs_i(inode2);
+ sbi->objid_no = inode2->i_ino;
+ }
+ }
+
+ /* Try to find $Quota */
+ inode2 = dir_search_u(inode, &NAME_QUOTA, NULL);
+ if (inode2 && !IS_ERR(inode2)) {
+ sbi->quota_no = inode2->i_ino;
+ iput(inode2);
+ }
+
+ /* Try to find $Reparse */
+ inode2 = dir_search_u(inode, &NAME_REPARSE, NULL);
+ if (inode2 && !IS_ERR(inode2)) {
+ sbi->reparse.ni = ntfs_i(inode2);
+ sbi->reparse_no = inode2->i_ino;
+ }
+
+ /* Try to find $UsnJrnl */
+ inode2 = dir_search_u(inode, &NAME_USNJRNL, NULL);
+ if (inode2 && !IS_ERR(inode2)) {
+ sbi->usn_jrnl_no = inode2->i_ino;
+ iput(inode2);
+ }
+
+ err = 0;
+out:
+ iput(inode);
+ return err;
+}
+
+int ntfs_loadlog_and_replay(struct ntfs_inode *ni, struct ntfs_sb_info *sbi)
+{
+ int err = 0;
+ struct super_block *sb = sbi->sb;
+ bool initialized = false;
+ struct MFT_REF ref;
+ struct inode *inode;
+
+ /* Check for 4GB. */
+ if (ni->vfs_inode.i_size >= 0x100000000ull) {
+ ntfs_err(sb, "\x24LogFile is too big");
+ err = -EINVAL;
+ goto out;
+ }
+
+ sbi->flags |= NTFS_FLAGS_LOG_REPLAYING;
+
+ ref.low = cpu_to_le32(MFT_REC_MFT);
+ ref.high = 0;
+ ref.seq = cpu_to_le16(1);
+
+ inode = ntfs_iget5(sb, &ref, NULL);
+
+ if (IS_ERR(inode))
+ inode = NULL;
+
+ if (!inode) {
+ /* Try to use MFT copy. */
+ u64 t64 = sbi->mft.lbo;
+
+ sbi->mft.lbo = sbi->mft.lbo2;
+ inode = ntfs_iget5(sb, &ref, NULL);
+ sbi->mft.lbo = t64;
+ if (IS_ERR(inode))
+ inode = NULL;
+ }
+
+ if (!inode) {
+ err = -EINVAL;
+ ntfs_err(sb, "Failed to load $MFT.");
+ goto out;
+ }
+
+ sbi->mft.ni = ntfs_i(inode);
+
+ /* LogFile should not contains attribute list. */
+ err = ni_load_all_mi(sbi->mft.ni);
+ if (!err)
+ err = log_replay(ni, &initialized);
+
+ iput(inode);
+ sbi->mft.ni = NULL;
+
+ sync_blockdev(sb->s_bdev);
+ invalidate_bdev(sb->s_bdev);
+
+ if (sbi->flags & NTFS_FLAGS_NEED_REPLAY) {
+ err = 0;
+ goto out;
+ }
+
+ if (sb_rdonly(sb) || !initialized)
+ goto out;
+
+ /* Fill LogFile by '-1' if it is initialized. */
+ err = ntfs_bio_fill_1(sbi, &ni->file.run);
+
+out:
+ sbi->flags &= ~NTFS_FLAGS_LOG_REPLAYING;
+
+ return err;
+}
+
+/*
+ * ntfs_query_def
+ *
+ * Return: Current ATTR_DEF_ENTRY for given attribute type.
+ */
+const struct ATTR_DEF_ENTRY *ntfs_query_def(struct ntfs_sb_info *sbi,
+ enum ATTR_TYPE type)
+{
+ int type_in = le32_to_cpu(type);
+ size_t min_idx = 0;
+ size_t max_idx = sbi->def_entries - 1;
+
+ while (min_idx <= max_idx) {
+ size_t i = min_idx + ((max_idx - min_idx) >> 1);
+ const struct ATTR_DEF_ENTRY *entry = sbi->def_table + i;
+ int diff = le32_to_cpu(entry->type) - type_in;
+
+ if (!diff)
+ return entry;
+ if (diff < 0)
+ min_idx = i + 1;
+ else if (i)
+ max_idx = i - 1;
+ else
+ return NULL;
+ }
+ return NULL;
+}
+
+/*
+ * ntfs_look_for_free_space - Look for a free space in bitmap.
+ */
+int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len,
+ CLST *new_lcn, CLST *new_len,
+ enum ALLOCATE_OPT opt)
+{
+ int err;
+ CLST alen = 0;
+ struct super_block *sb = sbi->sb;
+ size_t alcn, zlen, zeroes, zlcn, zlen2, ztrim, new_zlen;
+ struct wnd_bitmap *wnd = &sbi->used.bitmap;
+
+ down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
+ if (opt & ALLOCATE_MFT) {
+ zlen = wnd_zone_len(wnd);
+
+ if (!zlen) {
+ err = ntfs_refresh_zone(sbi);
+ if (err)
+ goto out;
+ zlen = wnd_zone_len(wnd);
+ }
+
+ if (!zlen) {
+ ntfs_err(sbi->sb, "no free space to extend mft");
+ goto out;
+ }
+
+ lcn = wnd_zone_bit(wnd);
+ alen = zlen > len ? len : zlen;
+
+ wnd_zone_set(wnd, lcn + alen, zlen - alen);
+
+ err = wnd_set_used(wnd, lcn, alen);
+ if (err) {
+ up_write(&wnd->rw_lock);
+ return err;
+ }
+ alcn = lcn;
+ goto out;
+ }
+ /*
+ * 'Cause cluster 0 is always used this value means that we should use
+ * cached value of 'next_free_lcn' to improve performance.
+ */
+ if (!lcn)
+ lcn = sbi->used.next_free_lcn;
+
+ if (lcn >= wnd->nbits)
+ lcn = 0;
+
+ alen = wnd_find(wnd, len, lcn, BITMAP_FIND_MARK_AS_USED, &alcn);
+ if (alen)
+ goto out;
+
+ /* Try to use clusters from MftZone. */
+ zlen = wnd_zone_len(wnd);
+ zeroes = wnd_zeroes(wnd);
+
+ /* Check too big request */
+ if (len > zeroes + zlen || zlen <= NTFS_MIN_MFT_ZONE)
+ goto out;
+
+ /* How many clusters to cat from zone. */
+ zlcn = wnd_zone_bit(wnd);
+ zlen2 = zlen >> 1;
+ ztrim = len > zlen ? zlen : (len > zlen2 ? len : zlen2);
+ new_zlen = zlen - ztrim;
+
+ if (new_zlen < NTFS_MIN_MFT_ZONE) {
+ new_zlen = NTFS_MIN_MFT_ZONE;
+ if (new_zlen > zlen)
+ new_zlen = zlen;
+ }
+
+ wnd_zone_set(wnd, zlcn, new_zlen);
+
+ /* Allocate continues clusters. */
+ alen = wnd_find(wnd, len, 0,
+ BITMAP_FIND_MARK_AS_USED | BITMAP_FIND_FULL, &alcn);
+
+out:
+ if (alen) {
+ err = 0;
+ *new_len = alen;
+ *new_lcn = alcn;
+
+ ntfs_unmap_meta(sb, alcn, alen);
+
+ /* Set hint for next requests. */
+ if (!(opt & ALLOCATE_MFT))
+ sbi->used.next_free_lcn = alcn + alen;
+ } else {
+ err = -ENOSPC;
+ }
+
+ up_write(&wnd->rw_lock);
+ return err;
+}
+
+/*
+ * ntfs_extend_mft - Allocate additional MFT records.
+ *
+ * sbi->mft.bitmap is locked for write.
+ *
+ * NOTE: recursive:
+ * ntfs_look_free_mft ->
+ * ntfs_extend_mft ->
+ * attr_set_size ->
+ * ni_insert_nonresident ->
+ * ni_insert_attr ->
+ * ni_ins_attr_ext ->
+ * ntfs_look_free_mft ->
+ * ntfs_extend_mft
+ *
+ * To avoid recursive always allocate space for two new MFT records
+ * see attrib.c: "at least two MFT to avoid recursive loop".
+ */
+static int ntfs_extend_mft(struct ntfs_sb_info *sbi)
+{
+ int err;
+ struct ntfs_inode *ni = sbi->mft.ni;
+ size_t new_mft_total;
+ u64 new_mft_bytes, new_bitmap_bytes;
+ struct ATTRIB *attr;
+ struct wnd_bitmap *wnd = &sbi->mft.bitmap;
+
+ new_mft_total = (wnd->nbits + MFT_INCREASE_CHUNK + 127) & (CLST)~127;
+ new_mft_bytes = (u64)new_mft_total << sbi->record_bits;
+
+ /* Step 1: Resize $MFT::DATA. */
+ down_write(&ni->file.run_lock);
+ err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run,
+ new_mft_bytes, NULL, false, &attr);
+
+ if (err) {
+ up_write(&ni->file.run_lock);
+ goto out;
+ }
+
+ attr->nres.valid_size = attr->nres.data_size;
+ new_mft_total = le64_to_cpu(attr->nres.alloc_size) >> sbi->record_bits;
+ ni->mi.dirty = true;
+
+ /* Step 2: Resize $MFT::BITMAP. */
+ new_bitmap_bytes = bitmap_size(new_mft_total);
+
+ err = attr_set_size(ni, ATTR_BITMAP, NULL, 0, &sbi->mft.bitmap.run,
+ new_bitmap_bytes, &new_bitmap_bytes, true, NULL);
+
+ /* Refresh MFT Zone if necessary. */
+ down_write_nested(&sbi->used.bitmap.rw_lock, BITMAP_MUTEX_CLUSTERS);
+
+ ntfs_refresh_zone(sbi);
+
+ up_write(&sbi->used.bitmap.rw_lock);
+ up_write(&ni->file.run_lock);
+
+ if (err)
+ goto out;
+
+ err = wnd_extend(wnd, new_mft_total);
+
+ if (err)
+ goto out;
+
+ ntfs_clear_mft_tail(sbi, sbi->mft.used, new_mft_total);
+
+ err = _ni_write_inode(&ni->vfs_inode, 0);
+out:
+ return err;
+}
+
+/*
+ * ntfs_look_free_mft - Look for a free MFT record.
+ */
+int ntfs_look_free_mft(struct ntfs_sb_info *sbi, CLST *rno, bool mft,
+ struct ntfs_inode *ni, struct mft_inode **mi)
+{
+ int err = 0;
+ size_t zbit, zlen, from, to, fr;
+ size_t mft_total;
+ struct MFT_REF ref;
+ struct super_block *sb = sbi->sb;
+ struct wnd_bitmap *wnd = &sbi->mft.bitmap;
+ u32 ir;
+
+ static_assert(sizeof(sbi->mft.reserved_bitmap) * 8 >=
+ MFT_REC_FREE - MFT_REC_RESERVED);
+
+ if (!mft)
+ down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_MFT);
+
+ zlen = wnd_zone_len(wnd);
+
+ /* Always reserve space for MFT. */
+ if (zlen) {
+ if (mft) {
+ zbit = wnd_zone_bit(wnd);
+ *rno = zbit;
+ wnd_zone_set(wnd, zbit + 1, zlen - 1);
+ }
+ goto found;
+ }
+
+ /* No MFT zone. Find the nearest to '0' free MFT. */
+ if (!wnd_find(wnd, 1, MFT_REC_FREE, 0, &zbit)) {
+ /* Resize MFT */
+ mft_total = wnd->nbits;
+
+ err = ntfs_extend_mft(sbi);
+ if (!err) {
+ zbit = mft_total;
+ goto reserve_mft;
+ }
+
+ if (!mft || MFT_REC_FREE == sbi->mft.next_reserved)
+ goto out;
+
+ err = 0;
+
+ /*
+ * Look for free record reserved area [11-16) ==
+ * [MFT_REC_RESERVED, MFT_REC_FREE ) MFT bitmap always
+ * marks it as used.
+ */
+ if (!sbi->mft.reserved_bitmap) {
+ /* Once per session create internal bitmap for 5 bits. */
+ sbi->mft.reserved_bitmap = 0xFF;
+
+ ref.high = 0;
+ for (ir = MFT_REC_RESERVED; ir < MFT_REC_FREE; ir++) {
+ struct inode *i;
+ struct ntfs_inode *ni;
+ struct MFT_REC *mrec;
+
+ ref.low = cpu_to_le32(ir);
+ ref.seq = cpu_to_le16(ir);
+
+ i = ntfs_iget5(sb, &ref, NULL);
+ if (IS_ERR(i)) {
+next:
+ ntfs_notice(
+ sb,
+ "Invalid reserved record %x",
+ ref.low);
+ continue;
+ }
+ if (is_bad_inode(i)) {
+ iput(i);
+ goto next;
+ }
+
+ ni = ntfs_i(i);
+
+ mrec = ni->mi.mrec;
+
+ if (!is_rec_base(mrec))
+ goto next;
+
+ if (mrec->hard_links)
+ goto next;
+
+ if (!ni_std(ni))
+ goto next;
+
+ if (ni_find_attr(ni, NULL, NULL, ATTR_NAME,
+ NULL, 0, NULL, NULL))
+ goto next;
+
+ __clear_bit(ir - MFT_REC_RESERVED,
+ &sbi->mft.reserved_bitmap);
+ }
+ }
+
+ /* Scan 5 bits for zero. Bit 0 == MFT_REC_RESERVED */
+ zbit = find_next_zero_bit(&sbi->mft.reserved_bitmap,
+ MFT_REC_FREE, MFT_REC_RESERVED);
+ if (zbit >= MFT_REC_FREE) {
+ sbi->mft.next_reserved = MFT_REC_FREE;
+ goto out;
+ }
+
+ zlen = 1;
+ sbi->mft.next_reserved = zbit;
+ } else {
+reserve_mft:
+ zlen = zbit == MFT_REC_FREE ? (MFT_REC_USER - MFT_REC_FREE) : 4;
+ if (zbit + zlen > wnd->nbits)
+ zlen = wnd->nbits - zbit;
+
+ while (zlen > 1 && !wnd_is_free(wnd, zbit, zlen))
+ zlen -= 1;
+
+ /* [zbit, zbit + zlen) will be used for MFT itself. */
+ from = sbi->mft.used;
+ if (from < zbit)
+ from = zbit;
+ to = zbit + zlen;
+ if (from < to) {
+ ntfs_clear_mft_tail(sbi, from, to);
+ sbi->mft.used = to;
+ }
+ }
+
+ if (mft) {
+ *rno = zbit;
+ zbit += 1;
+ zlen -= 1;
+ }
+
+ wnd_zone_set(wnd, zbit, zlen);
+
+found:
+ if (!mft) {
+ /* The request to get record for general purpose. */
+ if (sbi->mft.next_free < MFT_REC_USER)
+ sbi->mft.next_free = MFT_REC_USER;
+
+ for (;;) {
+ if (sbi->mft.next_free >= sbi->mft.bitmap.nbits) {
+ } else if (!wnd_find(wnd, 1, MFT_REC_USER, 0, &fr)) {
+ sbi->mft.next_free = sbi->mft.bitmap.nbits;
+ } else {
+ *rno = fr;
+ sbi->mft.next_free = *rno + 1;
+ break;
+ }
+
+ err = ntfs_extend_mft(sbi);
+ if (err)
+ goto out;
+ }
+ }
+
+ if (ni && !ni_add_subrecord(ni, *rno, mi)) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* We have found a record that are not reserved for next MFT. */
+ if (*rno >= MFT_REC_FREE)
+ wnd_set_used(wnd, *rno, 1);
+ else if (*rno >= MFT_REC_RESERVED && sbi->mft.reserved_bitmap_inited)
+ __set_bit(*rno - MFT_REC_RESERVED, &sbi->mft.reserved_bitmap);
+
+out:
+ if (!mft)
+ up_write(&wnd->rw_lock);
+
+ return err;
+}
+
+/*
+ * ntfs_mark_rec_free - Mark record as free.
+ */
+void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno)
+{
+ struct wnd_bitmap *wnd = &sbi->mft.bitmap;
+
+ down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_MFT);
+ if (rno >= wnd->nbits)
+ goto out;
+
+ if (rno >= MFT_REC_FREE) {
+ if (!wnd_is_used(wnd, rno, 1))
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+ else
+ wnd_set_free(wnd, rno, 1);
+ } else if (rno >= MFT_REC_RESERVED && sbi->mft.reserved_bitmap_inited) {
+ __clear_bit(rno - MFT_REC_RESERVED, &sbi->mft.reserved_bitmap);
+ }
+
+ if (rno < wnd_zone_bit(wnd))
+ wnd_zone_set(wnd, rno, 1);
+ else if (rno < sbi->mft.next_free && rno >= MFT_REC_USER)
+ sbi->mft.next_free = rno;
+
+out:
+ up_write(&wnd->rw_lock);
+}
+
+/*
+ * ntfs_clear_mft_tail - Format empty records [from, to).
+ *
+ * sbi->mft.bitmap is locked for write.
+ */
+int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to)
+{
+ int err;
+ u32 rs;
+ u64 vbo;
+ struct runs_tree *run;
+ struct ntfs_inode *ni;
+
+ if (from >= to)
+ return 0;
+
+ rs = sbi->record_size;
+ ni = sbi->mft.ni;
+ run = &ni->file.run;
+
+ down_read(&ni->file.run_lock);
+ vbo = (u64)from * rs;
+ for (; from < to; from++, vbo += rs) {
+ struct ntfs_buffers nb;
+
+ err = ntfs_get_bh(sbi, run, vbo, rs, &nb);
+ if (err)
+ goto out;
+
+ err = ntfs_write_bh(sbi, &sbi->new_rec->rhdr, &nb, 0);
+ nb_put(&nb);
+ if (err)
+ goto out;
+ }
+
+out:
+ sbi->mft.used = from;
+ up_read(&ni->file.run_lock);
+ return err;
+}
+
+/*
+ * ntfs_refresh_zone - Refresh MFT zone.
+ *
+ * sbi->used.bitmap is locked for rw.
+ * sbi->mft.bitmap is locked for write.
+ * sbi->mft.ni->file.run_lock for write.
+ */
+int ntfs_refresh_zone(struct ntfs_sb_info *sbi)
+{
+ CLST zone_limit, zone_max, lcn, vcn, len;
+ size_t lcn_s, zlen;
+ struct wnd_bitmap *wnd = &sbi->used.bitmap;
+ struct ntfs_inode *ni = sbi->mft.ni;
+
+ /* Do not change anything unless we have non empty MFT zone. */
+ if (wnd_zone_len(wnd))
+ return 0;
+
+ /*
+ * Compute the MFT zone at two steps.
+ * It would be nice if we are able to allocate 1/8 of
+ * total clusters for MFT but not more then 512 MB.
+ */
+ zone_limit = (512 * 1024 * 1024) >> sbi->cluster_bits;
+ zone_max = wnd->nbits >> 3;
+ if (zone_max > zone_limit)
+ zone_max = zone_limit;
+
+ vcn = bytes_to_cluster(sbi,
+ (u64)sbi->mft.bitmap.nbits << sbi->record_bits);
+
+ if (!run_lookup_entry(&ni->file.run, vcn - 1, &lcn, &len, NULL))
+ lcn = SPARSE_LCN;
+
+ /* We should always find Last Lcn for MFT. */
+ if (lcn == SPARSE_LCN)
+ return -EINVAL;
+
+ lcn_s = lcn + 1;
+
+ /* Try to allocate clusters after last MFT run. */
+ zlen = wnd_find(wnd, zone_max, lcn_s, 0, &lcn_s);
+ if (!zlen) {
+ ntfs_notice(sbi->sb, "MftZone: unavailable");
+ return 0;
+ }
+
+ /* Truncate too large zone. */
+ wnd_zone_set(wnd, lcn_s, zlen);
+
+ return 0;
+}
+
+/*
+ * ntfs_update_mftmirr - Update $MFTMirr data.
+ */
+int ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait)
+{
+ int err;
+ struct super_block *sb = sbi->sb;
+ u32 blocksize = sb->s_blocksize;
+ sector_t block1, block2;
+ u32 bytes;
+
+ if (!(sbi->flags & NTFS_FLAGS_MFTMIRR))
+ return 0;
+
+ err = 0;
+ bytes = sbi->mft.recs_mirr << sbi->record_bits;
+ block1 = sbi->mft.lbo >> sb->s_blocksize_bits;
+ block2 = sbi->mft.lbo2 >> sb->s_blocksize_bits;
+
+ for (; bytes >= blocksize; bytes -= blocksize) {
+ struct buffer_head *bh1, *bh2;
+
+ bh1 = sb_bread(sb, block1++);
+ if (!bh1) {
+ err = -EIO;
+ goto out;
+ }
+
+ bh2 = sb_getblk(sb, block2++);
+ if (!bh2) {
+ put_bh(bh1);
+ err = -EIO;
+ goto out;
+ }
+
+ if (buffer_locked(bh2))
+ __wait_on_buffer(bh2);
+
+ lock_buffer(bh2);
+ memcpy(bh2->b_data, bh1->b_data, blocksize);
+ set_buffer_uptodate(bh2);
+ mark_buffer_dirty(bh2);
+ unlock_buffer(bh2);
+
+ put_bh(bh1);
+ bh1 = NULL;
+
+ if (wait)
+ err = sync_dirty_buffer(bh2);
+
+ put_bh(bh2);
+ if (err)
+ goto out;
+ }
+
+ sbi->flags &= ~NTFS_FLAGS_MFTMIRR;
+
+out:
+ return err;
+}
+
+/*
+ * ntfs_set_state
+ *
+ * Mount: ntfs_set_state(NTFS_DIRTY_DIRTY)
+ * Umount: ntfs_set_state(NTFS_DIRTY_CLEAR)
+ * NTFS error: ntfs_set_state(NTFS_DIRTY_ERROR)
+ */
+int ntfs_set_state(struct ntfs_sb_info *sbi, enum NTFS_DIRTY_FLAGS dirty)
+{
+ int err;
+ struct ATTRIB *attr;
+ struct VOLUME_INFO *info;
+ struct mft_inode *mi;
+ struct ntfs_inode *ni;
+
+ /*
+ * Do not change state if fs was real_dirty.
+ * Do not change state if fs already dirty(clear).
+ * Do not change any thing if mounted read only.
+ */
+ if (sbi->volume.real_dirty || sb_rdonly(sbi->sb))
+ return 0;
+
+ /* Check cached value. */
+ if ((dirty == NTFS_DIRTY_CLEAR ? 0 : VOLUME_FLAG_DIRTY) ==
+ (sbi->volume.flags & VOLUME_FLAG_DIRTY))
+ return 0;
+
+ ni = sbi->volume.ni;
+ if (!ni)
+ return -EINVAL;
+
+ mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_DIRTY);
+
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_VOL_INFO, NULL, 0, NULL, &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ info = resident_data_ex(attr, SIZEOF_ATTRIBUTE_VOLUME_INFO);
+ if (!info) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ switch (dirty) {
+ case NTFS_DIRTY_ERROR:
+ ntfs_notice(sbi->sb, "Mark volume as dirty due to NTFS errors");
+ sbi->volume.real_dirty = true;
+ fallthrough;
+ case NTFS_DIRTY_DIRTY:
+ info->flags |= VOLUME_FLAG_DIRTY;
+ break;
+ case NTFS_DIRTY_CLEAR:
+ info->flags &= ~VOLUME_FLAG_DIRTY;
+ break;
+ }
+ /* Cache current volume flags. */
+ sbi->volume.flags = info->flags;
+ mi->dirty = true;
+ err = 0;
+
+out:
+ ni_unlock(ni);
+ if (err)
+ return err;
+
+ mark_inode_dirty(&ni->vfs_inode);
+ /* verify(!ntfs_update_mftmirr()); */
+
+ /*
+ * If we used wait=1, sync_inode_metadata waits for the io for the
+ * inode to finish. It hangs when media is removed.
+ * So wait=0 is sent down to sync_inode_metadata
+ * and filemap_fdatawrite is used for the data blocks.
+ */
+ err = sync_inode_metadata(&ni->vfs_inode, 0);
+ if (!err)
+ err = filemap_fdatawrite(ni->vfs_inode.i_mapping);
+
+ return err;
+}
+
+/*
+ * security_hash - Calculates a hash of security descriptor.
+ */
+static inline __le32 security_hash(const void *sd, size_t bytes)
+{
+ u32 hash = 0;
+ const __le32 *ptr = sd;
+
+ bytes >>= 2;
+ while (bytes--)
+ hash = ((hash >> 0x1D) | (hash << 3)) + le32_to_cpu(*ptr++);
+ return cpu_to_le32(hash);
+}
+
+int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer)
+{
+ struct block_device *bdev = sb->s_bdev;
+ u32 blocksize = sb->s_blocksize;
+ u64 block = lbo >> sb->s_blocksize_bits;
+ u32 off = lbo & (blocksize - 1);
+ u32 op = blocksize - off;
+
+ for (; bytes; block += 1, off = 0, op = blocksize) {
+ struct buffer_head *bh = __bread(bdev, block, blocksize);
+
+ if (!bh)
+ return -EIO;
+
+ if (op > bytes)
+ op = bytes;
+
+ memcpy(buffer, bh->b_data + off, op);
+
+ put_bh(bh);
+
+ bytes -= op;
+ buffer = Add2Ptr(buffer, op);
+ }
+
+ return 0;
+}
+
+int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes,
+ const void *buf, int wait)
+{
+ u32 blocksize = sb->s_blocksize;
+ struct block_device *bdev = sb->s_bdev;
+ sector_t block = lbo >> sb->s_blocksize_bits;
+ u32 off = lbo & (blocksize - 1);
+ u32 op = blocksize - off;
+ struct buffer_head *bh;
+
+ if (!wait && (sb->s_flags & SB_SYNCHRONOUS))
+ wait = 1;
+
+ for (; bytes; block += 1, off = 0, op = blocksize) {
+ if (op > bytes)
+ op = bytes;
+
+ if (op < blocksize) {
+ bh = __bread(bdev, block, blocksize);
+ if (!bh) {
+ ntfs_err(sb, "failed to read block %llx",
+ (u64)block);
+ return -EIO;
+ }
+ } else {
+ bh = __getblk(bdev, block, blocksize);
+ if (!bh)
+ return -ENOMEM;
+ }
+
+ if (buffer_locked(bh))
+ __wait_on_buffer(bh);
+
+ lock_buffer(bh);
+ if (buf) {
+ memcpy(bh->b_data + off, buf, op);
+ buf = Add2Ptr(buf, op);
+ } else {
+ memset(bh->b_data + off, -1, op);
+ }
+
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+
+ if (wait) {
+ int err = sync_dirty_buffer(bh);
+
+ if (err) {
+ ntfs_err(
+ sb,
+ "failed to sync buffer at block %llx, error %d",
+ (u64)block, err);
+ put_bh(bh);
+ return err;
+ }
+ }
+
+ put_bh(bh);
+
+ bytes -= op;
+ }
+ return 0;
+}
+
+int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+ u64 vbo, const void *buf, size_t bytes)
+{
+ struct super_block *sb = sbi->sb;
+ u8 cluster_bits = sbi->cluster_bits;
+ u32 off = vbo & sbi->cluster_mask;
+ CLST lcn, clen, vcn = vbo >> cluster_bits, vcn_next;
+ u64 lbo, len;
+ size_t idx;
+
+ if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx))
+ return -ENOENT;
+
+ if (lcn == SPARSE_LCN)
+ return -EINVAL;
+
+ lbo = ((u64)lcn << cluster_bits) + off;
+ len = ((u64)clen << cluster_bits) - off;
+
+ for (;;) {
+ u32 op = len < bytes ? len : bytes;
+ int err = ntfs_sb_write(sb, lbo, op, buf, 0);
+
+ if (err)
+ return err;
+
+ bytes -= op;
+ if (!bytes)
+ break;
+
+ vcn_next = vcn + clen;
+ if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
+ vcn != vcn_next)
+ return -ENOENT;
+
+ if (lcn == SPARSE_LCN)
+ return -EINVAL;
+
+ if (buf)
+ buf = Add2Ptr(buf, op);
+
+ lbo = ((u64)lcn << cluster_bits);
+ len = ((u64)clen << cluster_bits);
+ }
+
+ return 0;
+}
+
+struct buffer_head *ntfs_bread_run(struct ntfs_sb_info *sbi,
+ const struct runs_tree *run, u64 vbo)
+{
+ struct super_block *sb = sbi->sb;
+ u8 cluster_bits = sbi->cluster_bits;
+ CLST lcn;
+ u64 lbo;
+
+ if (!run_lookup_entry(run, vbo >> cluster_bits, &lcn, NULL, NULL))
+ return ERR_PTR(-ENOENT);
+
+ lbo = ((u64)lcn << cluster_bits) + (vbo & sbi->cluster_mask);
+
+ return ntfs_bread(sb, lbo >> sb->s_blocksize_bits);
+}
+
+int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+ u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb)
+{
+ int err;
+ struct super_block *sb = sbi->sb;
+ u32 blocksize = sb->s_blocksize;
+ u8 cluster_bits = sbi->cluster_bits;
+ u32 off = vbo & sbi->cluster_mask;
+ u32 nbh = 0;
+ CLST vcn_next, vcn = vbo >> cluster_bits;
+ CLST lcn, clen;
+ u64 lbo, len;
+ size_t idx;
+ struct buffer_head *bh;
+
+ if (!run) {
+ /* First reading of $Volume + $MFTMirr + $LogFile goes here. */
+ if (vbo > MFT_REC_VOL * sbi->record_size) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ /* Use absolute boot's 'MFTCluster' to read record. */
+ lbo = vbo + sbi->mft.lbo;
+ len = sbi->record_size;
+ } else if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
+ err = -ENOENT;
+ goto out;
+ } else {
+ if (lcn == SPARSE_LCN) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ lbo = ((u64)lcn << cluster_bits) + off;
+ len = ((u64)clen << cluster_bits) - off;
+ }
+
+ off = lbo & (blocksize - 1);
+ if (nb) {
+ nb->off = off;
+ nb->bytes = bytes;
+ }
+
+ for (;;) {
+ u32 len32 = len >= bytes ? bytes : len;
+ sector_t block = lbo >> sb->s_blocksize_bits;
+
+ do {
+ u32 op = blocksize - off;
+
+ if (op > len32)
+ op = len32;
+
+ bh = ntfs_bread(sb, block);
+ if (!bh) {
+ err = -EIO;
+ goto out;
+ }
+
+ if (buf) {
+ memcpy(buf, bh->b_data + off, op);
+ buf = Add2Ptr(buf, op);
+ }
+
+ if (!nb) {
+ put_bh(bh);
+ } else if (nbh >= ARRAY_SIZE(nb->bh)) {
+ err = -EINVAL;
+ goto out;
+ } else {
+ nb->bh[nbh++] = bh;
+ nb->nbufs = nbh;
+ }
+
+ bytes -= op;
+ if (!bytes)
+ return 0;
+ len32 -= op;
+ block += 1;
+ off = 0;
+
+ } while (len32);
+
+ vcn_next = vcn + clen;
+ if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
+ vcn != vcn_next) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (lcn == SPARSE_LCN) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ lbo = ((u64)lcn << cluster_bits);
+ len = ((u64)clen << cluster_bits);
+ }
+
+out:
+ if (!nbh)
+ return err;
+
+ while (nbh) {
+ put_bh(nb->bh[--nbh]);
+ nb->bh[nbh] = NULL;
+ }
+
+ nb->nbufs = 0;
+ return err;
+}
+
+/*
+ * ntfs_read_bh
+ *
+ * Return: < 0 if error, 0 if ok, -E_NTFS_FIXUP if need to update fixups.
+ */
+int ntfs_read_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
+ struct NTFS_RECORD_HEADER *rhdr, u32 bytes,
+ struct ntfs_buffers *nb)
+{
+ int err = ntfs_read_run_nb(sbi, run, vbo, rhdr, bytes, nb);
+
+ if (err)
+ return err;
+ return ntfs_fix_post_read(rhdr, nb->bytes, true);
+}
+
+int ntfs_get_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
+ u32 bytes, struct ntfs_buffers *nb)
+{
+ int err = 0;
+ struct super_block *sb = sbi->sb;
+ u32 blocksize = sb->s_blocksize;
+ u8 cluster_bits = sbi->cluster_bits;
+ CLST vcn_next, vcn = vbo >> cluster_bits;
+ u32 off;
+ u32 nbh = 0;
+ CLST lcn, clen;
+ u64 lbo, len;
+ size_t idx;
+
+ nb->bytes = bytes;
+
+ if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ off = vbo & sbi->cluster_mask;
+ lbo = ((u64)lcn << cluster_bits) + off;
+ len = ((u64)clen << cluster_bits) - off;
+
+ nb->off = off = lbo & (blocksize - 1);
+
+ for (;;) {
+ u32 len32 = len < bytes ? len : bytes;
+ sector_t block = lbo >> sb->s_blocksize_bits;
+
+ do {
+ u32 op;
+ struct buffer_head *bh;
+
+ if (nbh >= ARRAY_SIZE(nb->bh)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ op = blocksize - off;
+ if (op > len32)
+ op = len32;
+
+ if (op == blocksize) {
+ bh = sb_getblk(sb, block);
+ if (!bh) {
+ err = -ENOMEM;
+ goto out;
+ }
+ if (buffer_locked(bh))
+ __wait_on_buffer(bh);
+ set_buffer_uptodate(bh);
+ } else {
+ bh = ntfs_bread(sb, block);
+ if (!bh) {
+ err = -EIO;
+ goto out;
+ }
+ }
+
+ nb->bh[nbh++] = bh;
+ bytes -= op;
+ if (!bytes) {
+ nb->nbufs = nbh;
+ return 0;
+ }
+
+ block += 1;
+ len32 -= op;
+ off = 0;
+ } while (len32);
+
+ vcn_next = vcn + clen;
+ if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
+ vcn != vcn_next) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ lbo = ((u64)lcn << cluster_bits);
+ len = ((u64)clen << cluster_bits);
+ }
+
+out:
+ while (nbh) {
+ put_bh(nb->bh[--nbh]);
+ nb->bh[nbh] = NULL;
+ }
+
+ nb->nbufs = 0;
+
+ return err;
+}
+
+int ntfs_write_bh(struct ntfs_sb_info *sbi, struct NTFS_RECORD_HEADER *rhdr,
+ struct ntfs_buffers *nb, int sync)
+{
+ int err = 0;
+ struct super_block *sb = sbi->sb;
+ u32 block_size = sb->s_blocksize;
+ u32 bytes = nb->bytes;
+ u32 off = nb->off;
+ u16 fo = le16_to_cpu(rhdr->fix_off);
+ u16 fn = le16_to_cpu(rhdr->fix_num);
+ u32 idx;
+ __le16 *fixup;
+ __le16 sample;
+
+ if ((fo & 1) || fo + fn * sizeof(short) > SECTOR_SIZE || !fn-- ||
+ fn * SECTOR_SIZE > bytes) {
+ return -EINVAL;
+ }
+
+ for (idx = 0; bytes && idx < nb->nbufs; idx += 1, off = 0) {
+ u32 op = block_size - off;
+ char *bh_data;
+ struct buffer_head *bh = nb->bh[idx];
+ __le16 *ptr, *end_data;
+
+ if (op > bytes)
+ op = bytes;
+
+ if (buffer_locked(bh))
+ __wait_on_buffer(bh);
+
+ lock_buffer(nb->bh[idx]);
+
+ bh_data = bh->b_data + off;
+ end_data = Add2Ptr(bh_data, op);
+ memcpy(bh_data, rhdr, op);
+
+ if (!idx) {
+ u16 t16;
+
+ fixup = Add2Ptr(bh_data, fo);
+ sample = *fixup;
+ t16 = le16_to_cpu(sample);
+ if (t16 >= 0x7FFF) {
+ sample = *fixup = cpu_to_le16(1);
+ } else {
+ sample = cpu_to_le16(t16 + 1);
+ *fixup = sample;
+ }
+
+ *(__le16 *)Add2Ptr(rhdr, fo) = sample;
+ }
+
+ ptr = Add2Ptr(bh_data, SECTOR_SIZE - sizeof(short));
+
+ do {
+ *++fixup = *ptr;
+ *ptr = sample;
+ ptr += SECTOR_SIZE / sizeof(short);
+ } while (ptr < end_data);
+
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+
+ if (sync) {
+ int err2 = sync_dirty_buffer(bh);
+
+ if (!err && err2)
+ err = err2;
+ }
+
+ bytes -= op;
+ rhdr = Add2Ptr(rhdr, op);
+ }
+
+ return err;
+}
+
+static inline struct bio *ntfs_alloc_bio(u32 nr_vecs)
+{
+ struct bio *bio = bio_alloc(GFP_NOFS | __GFP_HIGH, nr_vecs);
+
+ if (!bio && (current->flags & PF_MEMALLOC)) {
+ while (!bio && (nr_vecs /= 2))
+ bio = bio_alloc(GFP_NOFS | __GFP_HIGH, nr_vecs);
+ }
+ return bio;
+}
+
+/*
+ * ntfs_bio_pages - Read/write pages from/to disk.
+ */
+int ntfs_bio_pages(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+ struct page **pages, u32 nr_pages, u64 vbo, u32 bytes,
+ u32 op)
+{
+ int err = 0;
+ struct bio *new, *bio = NULL;
+ struct super_block *sb = sbi->sb;
+ struct block_device *bdev = sb->s_bdev;
+ struct page *page;
+ u8 cluster_bits = sbi->cluster_bits;
+ CLST lcn, clen, vcn, vcn_next;
+ u32 add, off, page_idx;
+ u64 lbo, len;
+ size_t run_idx;
+ struct blk_plug plug;
+
+ if (!bytes)
+ return 0;
+
+ blk_start_plug(&plug);
+
+ /* Align vbo and bytes to be 512 bytes aligned. */
+ lbo = (vbo + bytes + 511) & ~511ull;
+ vbo = vbo & ~511ull;
+ bytes = lbo - vbo;
+
+ vcn = vbo >> cluster_bits;
+ if (!run_lookup_entry(run, vcn, &lcn, &clen, &run_idx)) {
+ err = -ENOENT;
+ goto out;
+ }
+ off = vbo & sbi->cluster_mask;
+ page_idx = 0;
+ page = pages[0];
+
+ for (;;) {
+ lbo = ((u64)lcn << cluster_bits) + off;
+ len = ((u64)clen << cluster_bits) - off;
+new_bio:
+ new = ntfs_alloc_bio(nr_pages - page_idx);
+ if (!new) {
+ err = -ENOMEM;
+ goto out;
+ }
+ if (bio) {
+ bio_chain(bio, new);
+ submit_bio(bio);
+ }
+ bio = new;
+ bio_set_dev(bio, bdev);
+ bio->bi_iter.bi_sector = lbo >> 9;
+ bio->bi_opf = op;
+
+ while (len) {
+ off = vbo & (PAGE_SIZE - 1);
+ add = off + len > PAGE_SIZE ? (PAGE_SIZE - off) : len;
+
+ if (bio_add_page(bio, page, add, off) < add)
+ goto new_bio;
+
+ if (bytes <= add)
+ goto out;
+ bytes -= add;
+ vbo += add;
+
+ if (add + off == PAGE_SIZE) {
+ page_idx += 1;
+ if (WARN_ON(page_idx >= nr_pages)) {
+ err = -EINVAL;
+ goto out;
+ }
+ page = pages[page_idx];
+ }
+
+ if (len <= add)
+ break;
+ len -= add;
+ lbo += add;
+ }
+
+ vcn_next = vcn + clen;
+ if (!run_get_entry(run, ++run_idx, &vcn, &lcn, &clen) ||
+ vcn != vcn_next) {
+ err = -ENOENT;
+ goto out;
+ }
+ off = 0;
+ }
+out:
+ if (bio) {
+ if (!err)
+ err = submit_bio_wait(bio);
+ bio_put(bio);
+ }
+ blk_finish_plug(&plug);
+
+ return err;
+}
+
+/*
+ * ntfs_bio_fill_1 - Helper for ntfs_loadlog_and_replay().
+ *
+ * Fill on-disk logfile range by (-1)
+ * this means empty logfile.
+ */
+int ntfs_bio_fill_1(struct ntfs_sb_info *sbi, const struct runs_tree *run)
+{
+ int err = 0;
+ struct super_block *sb = sbi->sb;
+ struct block_device *bdev = sb->s_bdev;
+ u8 cluster_bits = sbi->cluster_bits;
+ struct bio *new, *bio = NULL;
+ CLST lcn, clen;
+ u64 lbo, len;
+ size_t run_idx;
+ struct page *fill;
+ void *kaddr;
+ struct blk_plug plug;
+
+ fill = alloc_page(GFP_KERNEL);
+ if (!fill)
+ return -ENOMEM;
+
+ kaddr = kmap_atomic(fill);
+ memset(kaddr, -1, PAGE_SIZE);
+ kunmap_atomic(kaddr);
+ flush_dcache_page(fill);
+ lock_page(fill);
+
+ if (!run_lookup_entry(run, 0, &lcn, &clen, &run_idx)) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ /*
+ * TODO: Try blkdev_issue_write_same.
+ */
+ blk_start_plug(&plug);
+ do {
+ lbo = (u64)lcn << cluster_bits;
+ len = (u64)clen << cluster_bits;
+new_bio:
+ new = ntfs_alloc_bio(BIO_MAX_VECS);
+ if (!new) {
+ err = -ENOMEM;
+ break;
+ }
+ if (bio) {
+ bio_chain(bio, new);
+ submit_bio(bio);
+ }
+ bio = new;
+ bio_set_dev(bio, bdev);
+ bio->bi_opf = REQ_OP_WRITE;
+ bio->bi_iter.bi_sector = lbo >> 9;
+
+ for (;;) {
+ u32 add = len > PAGE_SIZE ? PAGE_SIZE : len;
+
+ if (bio_add_page(bio, fill, add, 0) < add)
+ goto new_bio;
+
+ lbo += add;
+ if (len <= add)
+ break;
+ len -= add;
+ }
+ } while (run_get_entry(run, ++run_idx, NULL, &lcn, &clen));
+
+ if (bio) {
+ if (!err)
+ err = submit_bio_wait(bio);
+ bio_put(bio);
+ }
+ blk_finish_plug(&plug);
+out:
+ unlock_page(fill);
+ put_page(fill);
+
+ return err;
+}
+
+int ntfs_vbo_to_lbo(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+ u64 vbo, u64 *lbo, u64 *bytes)
+{
+ u32 off;
+ CLST lcn, len;
+ u8 cluster_bits = sbi->cluster_bits;
+
+ if (!run_lookup_entry(run, vbo >> cluster_bits, &lcn, &len, NULL))
+ return -ENOENT;
+
+ off = vbo & sbi->cluster_mask;
+ *lbo = lcn == SPARSE_LCN ? -1 : (((u64)lcn << cluster_bits) + off);
+ *bytes = ((u64)len << cluster_bits) - off;
+
+ return 0;
+}
+
+struct ntfs_inode *ntfs_new_inode(struct ntfs_sb_info *sbi, CLST rno, bool dir)
+{
+ int err = 0;
+ struct super_block *sb = sbi->sb;
+ struct inode *inode = new_inode(sb);
+ struct ntfs_inode *ni;
+
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+
+ ni = ntfs_i(inode);
+
+ err = mi_format_new(&ni->mi, sbi, rno, dir ? RECORD_FLAG_DIR : 0,
+ false);
+ if (err)
+ goto out;
+
+ inode->i_ino = rno;
+ if (insert_inode_locked(inode) < 0) {
+ err = -EIO;
+ goto out;
+ }
+
+out:
+ if (err) {
+ iput(inode);
+ ni = ERR_PTR(err);
+ }
+ return ni;
+}
+
+/*
+ * O:BAG:BAD:(A;OICI;FA;;;WD)
+ * Owner S-1-5-32-544 (Administrators)
+ * Group S-1-5-32-544 (Administrators)
+ * ACE: allow S-1-1-0 (Everyone) with FILE_ALL_ACCESS
+ */
+const u8 s_default_security[] __aligned(8) = {
+ 0x01, 0x00, 0x04, 0x80, 0x30, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1C, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x14, 0x00, 0xFF, 0x01, 0x1F, 0x00,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00,
+ 0x20, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00,
+};
+
+static_assert(sizeof(s_default_security) == 0x50);
+
+static inline u32 sid_length(const struct SID *sid)
+{
+ return struct_size(sid, SubAuthority, sid->SubAuthorityCount);
+}
+
+/*
+ * is_acl_valid
+ *
+ * Thanks Mark Harmstone for idea.
+ */
+static bool is_acl_valid(const struct ACL *acl, u32 len)
+{
+ const struct ACE_HEADER *ace;
+ u32 i;
+ u16 ace_count, ace_size;
+
+ if (acl->AclRevision != ACL_REVISION &&
+ acl->AclRevision != ACL_REVISION_DS) {
+ /*
+ * This value should be ACL_REVISION, unless the ACL contains an
+ * object-specific ACE, in which case this value must be ACL_REVISION_DS.
+ * All ACEs in an ACL must be at the same revision level.
+ */
+ return false;
+ }
+
+ if (acl->Sbz1)
+ return false;
+
+ if (le16_to_cpu(acl->AclSize) > len)
+ return false;
+
+ if (acl->Sbz2)
+ return false;
+
+ len -= sizeof(struct ACL);
+ ace = (struct ACE_HEADER *)&acl[1];
+ ace_count = le16_to_cpu(acl->AceCount);
+
+ for (i = 0; i < ace_count; i++) {
+ if (len < sizeof(struct ACE_HEADER))
+ return false;
+
+ ace_size = le16_to_cpu(ace->AceSize);
+ if (len < ace_size)
+ return false;
+
+ len -= ace_size;
+ ace = Add2Ptr(ace, ace_size);
+ }
+
+ return true;
+}
+
+bool is_sd_valid(const struct SECURITY_DESCRIPTOR_RELATIVE *sd, u32 len)
+{
+ u32 sd_owner, sd_group, sd_sacl, sd_dacl;
+
+ if (len < sizeof(struct SECURITY_DESCRIPTOR_RELATIVE))
+ return false;
+
+ if (sd->Revision != 1)
+ return false;
+
+ if (sd->Sbz1)
+ return false;
+
+ if (!(sd->Control & SE_SELF_RELATIVE))
+ return false;
+
+ sd_owner = le32_to_cpu(sd->Owner);
+ if (sd_owner) {
+ const struct SID *owner = Add2Ptr(sd, sd_owner);
+
+ if (sd_owner + offsetof(struct SID, SubAuthority) > len)
+ return false;
+
+ if (owner->Revision != 1)
+ return false;
+
+ if (sd_owner + sid_length(owner) > len)
+ return false;
+ }
+
+ sd_group = le32_to_cpu(sd->Group);
+ if (sd_group) {
+ const struct SID *group = Add2Ptr(sd, sd_group);
+
+ if (sd_group + offsetof(struct SID, SubAuthority) > len)
+ return false;
+
+ if (group->Revision != 1)
+ return false;
+
+ if (sd_group + sid_length(group) > len)
+ return false;
+ }
+
+ sd_sacl = le32_to_cpu(sd->Sacl);
+ if (sd_sacl) {
+ const struct ACL *sacl = Add2Ptr(sd, sd_sacl);
+
+ if (sd_sacl + sizeof(struct ACL) > len)
+ return false;
+
+ if (!is_acl_valid(sacl, len - sd_sacl))
+ return false;
+ }
+
+ sd_dacl = le32_to_cpu(sd->Dacl);
+ if (sd_dacl) {
+ const struct ACL *dacl = Add2Ptr(sd, sd_dacl);
+
+ if (sd_dacl + sizeof(struct ACL) > len)
+ return false;
+
+ if (!is_acl_valid(dacl, len - sd_dacl))
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * ntfs_security_init - Load and parse $Secure.
+ */
+int ntfs_security_init(struct ntfs_sb_info *sbi)
+{
+ int err;
+ struct super_block *sb = sbi->sb;
+ struct inode *inode;
+ struct ntfs_inode *ni;
+ struct MFT_REF ref;
+ struct ATTRIB *attr;
+ struct ATTR_LIST_ENTRY *le;
+ u64 sds_size;
+ size_t off;
+ struct NTFS_DE *ne;
+ struct NTFS_DE_SII *sii_e;
+ struct ntfs_fnd *fnd_sii = NULL;
+ const struct INDEX_ROOT *root_sii;
+ const struct INDEX_ROOT *root_sdh;
+ struct ntfs_index *indx_sdh = &sbi->security.index_sdh;
+ struct ntfs_index *indx_sii = &sbi->security.index_sii;
+
+ ref.low = cpu_to_le32(MFT_REC_SECURE);
+ ref.high = 0;
+ ref.seq = cpu_to_le16(MFT_REC_SECURE);
+
+ inode = ntfs_iget5(sb, &ref, &NAME_SECURE);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load $Secure.");
+ inode = NULL;
+ goto out;
+ }
+
+ ni = ntfs_i(inode);
+
+ le = NULL;
+
+ attr = ni_find_attr(ni, NULL, &le, ATTR_ROOT, SDH_NAME,
+ ARRAY_SIZE(SDH_NAME), NULL, NULL);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ root_sdh = resident_data(attr);
+ if (root_sdh->type != ATTR_ZERO ||
+ root_sdh->rule != NTFS_COLLATION_TYPE_SECURITY_HASH) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = indx_init(indx_sdh, sbi, attr, INDEX_MUTEX_SDH);
+ if (err)
+ goto out;
+
+ attr = ni_find_attr(ni, attr, &le, ATTR_ROOT, SII_NAME,
+ ARRAY_SIZE(SII_NAME), NULL, NULL);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ root_sii = resident_data(attr);
+ if (root_sii->type != ATTR_ZERO ||
+ root_sii->rule != NTFS_COLLATION_TYPE_UINT) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = indx_init(indx_sii, sbi, attr, INDEX_MUTEX_SII);
+ if (err)
+ goto out;
+
+ fnd_sii = fnd_get();
+ if (!fnd_sii) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ sds_size = inode->i_size;
+
+ /* Find the last valid Id. */
+ sbi->security.next_id = SECURITY_ID_FIRST;
+ /* Always write new security at the end of bucket. */
+ sbi->security.next_off =
+ ALIGN(sds_size - SecurityDescriptorsBlockSize, 16);
+
+ off = 0;
+ ne = NULL;
+
+ for (;;) {
+ u32 next_id;
+
+ err = indx_find_raw(indx_sii, ni, root_sii, &ne, &off, fnd_sii);
+ if (err || !ne)
+ break;
+
+ sii_e = (struct NTFS_DE_SII *)ne;
+ if (le16_to_cpu(ne->view.data_size) < SIZEOF_SECURITY_HDR)
+ continue;
+
+ next_id = le32_to_cpu(sii_e->sec_id) + 1;
+ if (next_id >= sbi->security.next_id)
+ sbi->security.next_id = next_id;
+ }
+
+ sbi->security.ni = ni;
+ inode = NULL;
+out:
+ iput(inode);
+ fnd_put(fnd_sii);
+
+ return err;
+}
+
+/*
+ * ntfs_get_security_by_id - Read security descriptor by id.
+ */
+int ntfs_get_security_by_id(struct ntfs_sb_info *sbi, __le32 security_id,
+ struct SECURITY_DESCRIPTOR_RELATIVE **sd,
+ size_t *size)
+{
+ int err;
+ int diff;
+ struct ntfs_inode *ni = sbi->security.ni;
+ struct ntfs_index *indx = &sbi->security.index_sii;
+ void *p = NULL;
+ struct NTFS_DE_SII *sii_e;
+ struct ntfs_fnd *fnd_sii;
+ struct SECURITY_HDR d_security;
+ const struct INDEX_ROOT *root_sii;
+ u32 t32;
+
+ *sd = NULL;
+
+ mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_SECURITY);
+
+ fnd_sii = fnd_get();
+ if (!fnd_sii) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ root_sii = indx_get_root(indx, ni, NULL, NULL);
+ if (!root_sii) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Try to find this SECURITY descriptor in SII indexes. */
+ err = indx_find(indx, ni, root_sii, &security_id, sizeof(security_id),
+ NULL, &diff, (struct NTFS_DE **)&sii_e, fnd_sii);
+ if (err)
+ goto out;
+
+ if (diff)
+ goto out;
+
+ t32 = le32_to_cpu(sii_e->sec_hdr.size);
+ if (t32 < SIZEOF_SECURITY_HDR) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (t32 > SIZEOF_SECURITY_HDR + 0x10000) {
+ /* Looks like too big security. 0x10000 - is arbitrary big number. */
+ err = -EFBIG;
+ goto out;
+ }
+
+ *size = t32 - SIZEOF_SECURITY_HDR;
+
+ p = kmalloc(*size, GFP_NOFS);
+ if (!p) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = ntfs_read_run_nb(sbi, &ni->file.run,
+ le64_to_cpu(sii_e->sec_hdr.off), &d_security,
+ sizeof(d_security), NULL);
+ if (err)
+ goto out;
+
+ if (memcmp(&d_security, &sii_e->sec_hdr, SIZEOF_SECURITY_HDR)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = ntfs_read_run_nb(sbi, &ni->file.run,
+ le64_to_cpu(sii_e->sec_hdr.off) +
+ SIZEOF_SECURITY_HDR,
+ p, *size, NULL);
+ if (err)
+ goto out;
+
+ *sd = p;
+ p = NULL;
+
+out:
+ kfree(p);
+ fnd_put(fnd_sii);
+ ni_unlock(ni);
+
+ return err;
+}
+
+/*
+ * ntfs_insert_security - Insert security descriptor into $Secure::SDS.
+ *
+ * SECURITY Descriptor Stream data is organized into chunks of 256K bytes
+ * and it contains a mirror copy of each security descriptor. When writing
+ * to a security descriptor at location X, another copy will be written at
+ * location (X+256K).
+ * When writing a security descriptor that will cross the 256K boundary,
+ * the pointer will be advanced by 256K to skip
+ * over the mirror portion.
+ */
+int ntfs_insert_security(struct ntfs_sb_info *sbi,
+ const struct SECURITY_DESCRIPTOR_RELATIVE *sd,
+ u32 size_sd, __le32 *security_id, bool *inserted)
+{
+ int err, diff;
+ struct ntfs_inode *ni = sbi->security.ni;
+ struct ntfs_index *indx_sdh = &sbi->security.index_sdh;
+ struct ntfs_index *indx_sii = &sbi->security.index_sii;
+ struct NTFS_DE_SDH *e;
+ struct NTFS_DE_SDH sdh_e;
+ struct NTFS_DE_SII sii_e;
+ struct SECURITY_HDR *d_security;
+ u32 new_sec_size = size_sd + SIZEOF_SECURITY_HDR;
+ u32 aligned_sec_size = ALIGN(new_sec_size, 16);
+ struct SECURITY_KEY hash_key;
+ struct ntfs_fnd *fnd_sdh = NULL;
+ const struct INDEX_ROOT *root_sdh;
+ const struct INDEX_ROOT *root_sii;
+ u64 mirr_off, new_sds_size;
+ u32 next, left;
+
+ static_assert((1 << Log2OfSecurityDescriptorsBlockSize) ==
+ SecurityDescriptorsBlockSize);
+
+ hash_key.hash = security_hash(sd, size_sd);
+ hash_key.sec_id = SECURITY_ID_INVALID;
+
+ if (inserted)
+ *inserted = false;
+ *security_id = SECURITY_ID_INVALID;
+
+ /* Allocate a temporal buffer. */
+ d_security = kzalloc(aligned_sec_size, GFP_NOFS);
+ if (!d_security)
+ return -ENOMEM;
+
+ mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_SECURITY);
+
+ fnd_sdh = fnd_get();
+ if (!fnd_sdh) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ root_sdh = indx_get_root(indx_sdh, ni, NULL, NULL);
+ if (!root_sdh) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ root_sii = indx_get_root(indx_sii, ni, NULL, NULL);
+ if (!root_sii) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Check if such security already exists.
+ * Use "SDH" and hash -> to get the offset in "SDS".
+ */
+ err = indx_find(indx_sdh, ni, root_sdh, &hash_key, sizeof(hash_key),
+ &d_security->key.sec_id, &diff, (struct NTFS_DE **)&e,
+ fnd_sdh);
+ if (err)
+ goto out;
+
+ while (e) {
+ if (le32_to_cpu(e->sec_hdr.size) == new_sec_size) {
+ err = ntfs_read_run_nb(sbi, &ni->file.run,
+ le64_to_cpu(e->sec_hdr.off),
+ d_security, new_sec_size, NULL);
+ if (err)
+ goto out;
+
+ if (le32_to_cpu(d_security->size) == new_sec_size &&
+ d_security->key.hash == hash_key.hash &&
+ !memcmp(d_security + 1, sd, size_sd)) {
+ *security_id = d_security->key.sec_id;
+ /* Such security already exists. */
+ err = 0;
+ goto out;
+ }
+ }
+
+ err = indx_find_sort(indx_sdh, ni, root_sdh,
+ (struct NTFS_DE **)&e, fnd_sdh);
+ if (err)
+ goto out;
+
+ if (!e || e->key.hash != hash_key.hash)
+ break;
+ }
+
+ /* Zero unused space. */
+ next = sbi->security.next_off & (SecurityDescriptorsBlockSize - 1);
+ left = SecurityDescriptorsBlockSize - next;
+
+ /* Zero gap until SecurityDescriptorsBlockSize. */
+ if (left < new_sec_size) {
+ /* Zero "left" bytes from sbi->security.next_off. */
+ sbi->security.next_off += SecurityDescriptorsBlockSize + left;
+ }
+
+ /* Zero tail of previous security. */
+ //used = ni->vfs_inode.i_size & (SecurityDescriptorsBlockSize - 1);
+
+ /*
+ * Example:
+ * 0x40438 == ni->vfs_inode.i_size
+ * 0x00440 == sbi->security.next_off
+ * need to zero [0x438-0x440)
+ * if (next > used) {
+ * u32 tozero = next - used;
+ * zero "tozero" bytes from sbi->security.next_off - tozero
+ */
+
+ /* Format new security descriptor. */
+ d_security->key.hash = hash_key.hash;
+ d_security->key.sec_id = cpu_to_le32(sbi->security.next_id);
+ d_security->off = cpu_to_le64(sbi->security.next_off);
+ d_security->size = cpu_to_le32(new_sec_size);
+ memcpy(d_security + 1, sd, size_sd);
+
+ /* Write main SDS bucket. */
+ err = ntfs_sb_write_run(sbi, &ni->file.run, sbi->security.next_off,
+ d_security, aligned_sec_size);
+
+ if (err)
+ goto out;
+
+ mirr_off = sbi->security.next_off + SecurityDescriptorsBlockSize;
+ new_sds_size = mirr_off + aligned_sec_size;
+
+ if (new_sds_size > ni->vfs_inode.i_size) {
+ err = attr_set_size(ni, ATTR_DATA, SDS_NAME,
+ ARRAY_SIZE(SDS_NAME), &ni->file.run,
+ new_sds_size, &new_sds_size, false, NULL);
+ if (err)
+ goto out;
+ }
+
+ /* Write copy SDS bucket. */
+ err = ntfs_sb_write_run(sbi, &ni->file.run, mirr_off, d_security,
+ aligned_sec_size);
+ if (err)
+ goto out;
+
+ /* Fill SII entry. */
+ sii_e.de.view.data_off =
+ cpu_to_le16(offsetof(struct NTFS_DE_SII, sec_hdr));
+ sii_e.de.view.data_size = cpu_to_le16(SIZEOF_SECURITY_HDR);
+ sii_e.de.view.res = 0;
+ sii_e.de.size = cpu_to_le16(SIZEOF_SII_DIRENTRY);
+ sii_e.de.key_size = cpu_to_le16(sizeof(d_security->key.sec_id));
+ sii_e.de.flags = 0;
+ sii_e.de.res = 0;
+ sii_e.sec_id = d_security->key.sec_id;
+ memcpy(&sii_e.sec_hdr, d_security, SIZEOF_SECURITY_HDR);
+
+ err = indx_insert_entry(indx_sii, ni, &sii_e.de, NULL, NULL, 0);
+ if (err)
+ goto out;
+
+ /* Fill SDH entry. */
+ sdh_e.de.view.data_off =
+ cpu_to_le16(offsetof(struct NTFS_DE_SDH, sec_hdr));
+ sdh_e.de.view.data_size = cpu_to_le16(SIZEOF_SECURITY_HDR);
+ sdh_e.de.view.res = 0;
+ sdh_e.de.size = cpu_to_le16(SIZEOF_SDH_DIRENTRY);
+ sdh_e.de.key_size = cpu_to_le16(sizeof(sdh_e.key));
+ sdh_e.de.flags = 0;
+ sdh_e.de.res = 0;
+ sdh_e.key.hash = d_security->key.hash;
+ sdh_e.key.sec_id = d_security->key.sec_id;
+ memcpy(&sdh_e.sec_hdr, d_security, SIZEOF_SECURITY_HDR);
+ sdh_e.magic[0] = cpu_to_le16('I');
+ sdh_e.magic[1] = cpu_to_le16('I');
+
+ fnd_clear(fnd_sdh);
+ err = indx_insert_entry(indx_sdh, ni, &sdh_e.de, (void *)(size_t)1,
+ fnd_sdh, 0);
+ if (err)
+ goto out;
+
+ *security_id = d_security->key.sec_id;
+ if (inserted)
+ *inserted = true;
+
+ /* Update Id and offset for next descriptor. */
+ sbi->security.next_id += 1;
+ sbi->security.next_off += aligned_sec_size;
+
+out:
+ fnd_put(fnd_sdh);
+ mark_inode_dirty(&ni->vfs_inode);
+ ni_unlock(ni);
+ kfree(d_security);
+
+ return err;
+}
+
+/*
+ * ntfs_reparse_init - Load and parse $Extend/$Reparse.
+ */
+int ntfs_reparse_init(struct ntfs_sb_info *sbi)
+{
+ int err;
+ struct ntfs_inode *ni = sbi->reparse.ni;
+ struct ntfs_index *indx = &sbi->reparse.index_r;
+ struct ATTRIB *attr;
+ struct ATTR_LIST_ENTRY *le;
+ const struct INDEX_ROOT *root_r;
+
+ if (!ni)
+ return 0;
+
+ le = NULL;
+ attr = ni_find_attr(ni, NULL, &le, ATTR_ROOT, SR_NAME,
+ ARRAY_SIZE(SR_NAME), NULL, NULL);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ root_r = resident_data(attr);
+ if (root_r->type != ATTR_ZERO ||
+ root_r->rule != NTFS_COLLATION_TYPE_UINTS) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = indx_init(indx, sbi, attr, INDEX_MUTEX_SR);
+ if (err)
+ goto out;
+
+out:
+ return err;
+}
+
+/*
+ * ntfs_objid_init - Load and parse $Extend/$ObjId.
+ */
+int ntfs_objid_init(struct ntfs_sb_info *sbi)
+{
+ int err;
+ struct ntfs_inode *ni = sbi->objid.ni;
+ struct ntfs_index *indx = &sbi->objid.index_o;
+ struct ATTRIB *attr;
+ struct ATTR_LIST_ENTRY *le;
+ const struct INDEX_ROOT *root;
+
+ if (!ni)
+ return 0;
+
+ le = NULL;
+ attr = ni_find_attr(ni, NULL, &le, ATTR_ROOT, SO_NAME,
+ ARRAY_SIZE(SO_NAME), NULL, NULL);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ root = resident_data(attr);
+ if (root->type != ATTR_ZERO ||
+ root->rule != NTFS_COLLATION_TYPE_UINTS) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = indx_init(indx, sbi, attr, INDEX_MUTEX_SO);
+ if (err)
+ goto out;
+
+out:
+ return err;
+}
+
+int ntfs_objid_remove(struct ntfs_sb_info *sbi, struct GUID *guid)
+{
+ int err;
+ struct ntfs_inode *ni = sbi->objid.ni;
+ struct ntfs_index *indx = &sbi->objid.index_o;
+
+ if (!ni)
+ return -EINVAL;
+
+ mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_OBJID);
+
+ err = indx_delete_entry(indx, ni, guid, sizeof(*guid), NULL);
+
+ mark_inode_dirty(&ni->vfs_inode);
+ ni_unlock(ni);
+
+ return err;
+}
+
+int ntfs_insert_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
+ const struct MFT_REF *ref)
+{
+ int err;
+ struct ntfs_inode *ni = sbi->reparse.ni;
+ struct ntfs_index *indx = &sbi->reparse.index_r;
+ struct NTFS_DE_R re;
+
+ if (!ni)
+ return -EINVAL;
+
+ memset(&re, 0, sizeof(re));
+
+ re.de.view.data_off = cpu_to_le16(offsetof(struct NTFS_DE_R, zero));
+ re.de.size = cpu_to_le16(sizeof(struct NTFS_DE_R));
+ re.de.key_size = cpu_to_le16(sizeof(re.key));
+
+ re.key.ReparseTag = rtag;
+ memcpy(&re.key.ref, ref, sizeof(*ref));
+
+ mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_REPARSE);
+
+ err = indx_insert_entry(indx, ni, &re.de, NULL, NULL, 0);
+
+ mark_inode_dirty(&ni->vfs_inode);
+ ni_unlock(ni);
+
+ return err;
+}
+
+int ntfs_remove_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
+ const struct MFT_REF *ref)
+{
+ int err, diff;
+ struct ntfs_inode *ni = sbi->reparse.ni;
+ struct ntfs_index *indx = &sbi->reparse.index_r;
+ struct ntfs_fnd *fnd = NULL;
+ struct REPARSE_KEY rkey;
+ struct NTFS_DE_R *re;
+ struct INDEX_ROOT *root_r;
+
+ if (!ni)
+ return -EINVAL;
+
+ rkey.ReparseTag = rtag;
+ rkey.ref = *ref;
+
+ mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_REPARSE);
+
+ if (rtag) {
+ err = indx_delete_entry(indx, ni, &rkey, sizeof(rkey), NULL);
+ goto out1;
+ }
+
+ fnd = fnd_get();
+ if (!fnd) {
+ err = -ENOMEM;
+ goto out1;
+ }
+
+ root_r = indx_get_root(indx, ni, NULL, NULL);
+ if (!root_r) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* 1 - forces to ignore rkey.ReparseTag when comparing keys. */
+ err = indx_find(indx, ni, root_r, &rkey, sizeof(rkey), (void *)1, &diff,
+ (struct NTFS_DE **)&re, fnd);
+ if (err)
+ goto out;
+
+ if (memcmp(&re->key.ref, ref, sizeof(*ref))) {
+ /* Impossible. Looks like volume corrupt? */
+ goto out;
+ }
+
+ memcpy(&rkey, &re->key, sizeof(rkey));
+
+ fnd_put(fnd);
+ fnd = NULL;
+
+ err = indx_delete_entry(indx, ni, &rkey, sizeof(rkey), NULL);
+ if (err)
+ goto out;
+
+out:
+ fnd_put(fnd);
+
+out1:
+ mark_inode_dirty(&ni->vfs_inode);
+ ni_unlock(ni);
+
+ return err;
+}
+
+static inline void ntfs_unmap_and_discard(struct ntfs_sb_info *sbi, CLST lcn,
+ CLST len)
+{
+ ntfs_unmap_meta(sbi->sb, lcn, len);
+ ntfs_discard(sbi, lcn, len);
+}
+
+void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim)
+{
+ CLST end, i;
+ struct wnd_bitmap *wnd = &sbi->used.bitmap;
+
+ down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
+ if (!wnd_is_used(wnd, lcn, len)) {
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+
+ end = lcn + len;
+ len = 0;
+ for (i = lcn; i < end; i++) {
+ if (wnd_is_used(wnd, i, 1)) {
+ if (!len)
+ lcn = i;
+ len += 1;
+ continue;
+ }
+
+ if (!len)
+ continue;
+
+ if (trim)
+ ntfs_unmap_and_discard(sbi, lcn, len);
+
+ wnd_set_free(wnd, lcn, len);
+ len = 0;
+ }
+
+ if (!len)
+ goto out;
+ }
+
+ if (trim)
+ ntfs_unmap_and_discard(sbi, lcn, len);
+ wnd_set_free(wnd, lcn, len);
+
+out:
+ up_write(&wnd->rw_lock);
+}
+
+/*
+ * run_deallocate - Deallocate clusters.
+ */
+int run_deallocate(struct ntfs_sb_info *sbi, struct runs_tree *run, bool trim)
+{
+ CLST lcn, len;
+ size_t idx = 0;
+
+ while (run_get_entry(run, idx++, NULL, &lcn, &len)) {
+ if (lcn == SPARSE_LCN)
+ continue;
+
+ mark_as_free_ex(sbi, lcn, len, trim);
+ }
+
+ return 0;
+}
diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c
new file mode 100644
index 000000000000..0daca9adc54c
--- /dev/null
+++ b/fs/ntfs3/index.c
@@ -0,0 +1,2650 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+static const struct INDEX_NAMES {
+ const __le16 *name;
+ u8 name_len;
+} s_index_names[INDEX_MUTEX_TOTAL] = {
+ { I30_NAME, ARRAY_SIZE(I30_NAME) }, { SII_NAME, ARRAY_SIZE(SII_NAME) },
+ { SDH_NAME, ARRAY_SIZE(SDH_NAME) }, { SO_NAME, ARRAY_SIZE(SO_NAME) },
+ { SQ_NAME, ARRAY_SIZE(SQ_NAME) }, { SR_NAME, ARRAY_SIZE(SR_NAME) },
+};
+
+/*
+ * cmp_fnames - Compare two names in index.
+ *
+ * if l1 != 0
+ * Both names are little endian on-disk ATTR_FILE_NAME structs.
+ * else
+ * key1 - cpu_str, key2 - ATTR_FILE_NAME
+ */
+static int cmp_fnames(const void *key1, size_t l1, const void *key2, size_t l2,
+ const void *data)
+{
+ const struct ATTR_FILE_NAME *f2 = key2;
+ const struct ntfs_sb_info *sbi = data;
+ const struct ATTR_FILE_NAME *f1;
+ u16 fsize2;
+ bool both_case;
+
+ if (l2 <= offsetof(struct ATTR_FILE_NAME, name))
+ return -1;
+
+ fsize2 = fname_full_size(f2);
+ if (l2 < fsize2)
+ return -1;
+
+ both_case = f2->type != FILE_NAME_DOS /*&& !sbi->options.nocase*/;
+ if (!l1) {
+ const struct le_str *s2 = (struct le_str *)&f2->name_len;
+
+ /*
+ * If names are equal (case insensitive)
+ * try to compare it case sensitive.
+ */
+ return ntfs_cmp_names_cpu(key1, s2, sbi->upcase, both_case);
+ }
+
+ f1 = key1;
+ return ntfs_cmp_names(f1->name, f1->name_len, f2->name, f2->name_len,
+ sbi->upcase, both_case);
+}
+
+/*
+ * cmp_uint - $SII of $Secure and $Q of Quota
+ */
+static int cmp_uint(const void *key1, size_t l1, const void *key2, size_t l2,
+ const void *data)
+{
+ const u32 *k1 = key1;
+ const u32 *k2 = key2;
+
+ if (l2 < sizeof(u32))
+ return -1;
+
+ if (*k1 < *k2)
+ return -1;
+ if (*k1 > *k2)
+ return 1;
+ return 0;
+}
+
+/*
+ * cmp_sdh - $SDH of $Secure
+ */
+static int cmp_sdh(const void *key1, size_t l1, const void *key2, size_t l2,
+ const void *data)
+{
+ const struct SECURITY_KEY *k1 = key1;
+ const struct SECURITY_KEY *k2 = key2;
+ u32 t1, t2;
+
+ if (l2 < sizeof(struct SECURITY_KEY))
+ return -1;
+
+ t1 = le32_to_cpu(k1->hash);
+ t2 = le32_to_cpu(k2->hash);
+
+ /* First value is a hash value itself. */
+ if (t1 < t2)
+ return -1;
+ if (t1 > t2)
+ return 1;
+
+ /* Second value is security Id. */
+ if (data) {
+ t1 = le32_to_cpu(k1->sec_id);
+ t2 = le32_to_cpu(k2->sec_id);
+ if (t1 < t2)
+ return -1;
+ if (t1 > t2)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * cmp_uints - $O of ObjId and "$R" for Reparse.
+ */
+static int cmp_uints(const void *key1, size_t l1, const void *key2, size_t l2,
+ const void *data)
+{
+ const __le32 *k1 = key1;
+ const __le32 *k2 = key2;
+ size_t count;
+
+ if ((size_t)data == 1) {
+ /*
+ * ni_delete_all -> ntfs_remove_reparse ->
+ * delete all with this reference.
+ * k1, k2 - pointers to REPARSE_KEY
+ */
+
+ k1 += 1; // Skip REPARSE_KEY.ReparseTag
+ k2 += 1; // Skip REPARSE_KEY.ReparseTag
+ if (l2 <= sizeof(int))
+ return -1;
+ l2 -= sizeof(int);
+ if (l1 <= sizeof(int))
+ return 1;
+ l1 -= sizeof(int);
+ }
+
+ if (l2 < sizeof(int))
+ return -1;
+
+ for (count = min(l1, l2) >> 2; count > 0; --count, ++k1, ++k2) {
+ u32 t1 = le32_to_cpu(*k1);
+ u32 t2 = le32_to_cpu(*k2);
+
+ if (t1 > t2)
+ return 1;
+ if (t1 < t2)
+ return -1;
+ }
+
+ if (l1 > l2)
+ return 1;
+ if (l1 < l2)
+ return -1;
+
+ return 0;
+}
+
+static inline NTFS_CMP_FUNC get_cmp_func(const struct INDEX_ROOT *root)
+{
+ switch (root->type) {
+ case ATTR_NAME:
+ if (root->rule == NTFS_COLLATION_TYPE_FILENAME)
+ return &cmp_fnames;
+ break;
+ case ATTR_ZERO:
+ switch (root->rule) {
+ case NTFS_COLLATION_TYPE_UINT:
+ return &cmp_uint;
+ case NTFS_COLLATION_TYPE_SECURITY_HASH:
+ return &cmp_sdh;
+ case NTFS_COLLATION_TYPE_UINTS:
+ return &cmp_uints;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+struct bmp_buf {
+ struct ATTRIB *b;
+ struct mft_inode *mi;
+ struct buffer_head *bh;
+ ulong *buf;
+ size_t bit;
+ u32 nbits;
+ u64 new_valid;
+};
+
+static int bmp_buf_get(struct ntfs_index *indx, struct ntfs_inode *ni,
+ size_t bit, struct bmp_buf *bbuf)
+{
+ struct ATTRIB *b;
+ size_t data_size, valid_size, vbo, off = bit >> 3;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ CLST vcn = off >> sbi->cluster_bits;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ struct buffer_head *bh;
+ struct super_block *sb;
+ u32 blocksize;
+ const struct INDEX_NAMES *in = &s_index_names[indx->type];
+
+ bbuf->bh = NULL;
+
+ b = ni_find_attr(ni, NULL, &le, ATTR_BITMAP, in->name, in->name_len,
+ &vcn, &bbuf->mi);
+ bbuf->b = b;
+ if (!b)
+ return -EINVAL;
+
+ if (!b->non_res) {
+ data_size = le32_to_cpu(b->res.data_size);
+
+ if (off >= data_size)
+ return -EINVAL;
+
+ bbuf->buf = (ulong *)resident_data(b);
+ bbuf->bit = 0;
+ bbuf->nbits = data_size * 8;
+
+ return 0;
+ }
+
+ data_size = le64_to_cpu(b->nres.data_size);
+ if (WARN_ON(off >= data_size)) {
+ /* Looks like filesystem error. */
+ return -EINVAL;
+ }
+
+ valid_size = le64_to_cpu(b->nres.valid_size);
+
+ bh = ntfs_bread_run(sbi, &indx->bitmap_run, off);
+ if (!bh)
+ return -EIO;
+
+ if (IS_ERR(bh))
+ return PTR_ERR(bh);
+
+ bbuf->bh = bh;
+
+ if (buffer_locked(bh))
+ __wait_on_buffer(bh);
+
+ lock_buffer(bh);
+
+ sb = sbi->sb;
+ blocksize = sb->s_blocksize;
+
+ vbo = off & ~(size_t)sbi->block_mask;
+
+ bbuf->new_valid = vbo + blocksize;
+ if (bbuf->new_valid <= valid_size)
+ bbuf->new_valid = 0;
+ else if (bbuf->new_valid > data_size)
+ bbuf->new_valid = data_size;
+
+ if (vbo >= valid_size) {
+ memset(bh->b_data, 0, blocksize);
+ } else if (vbo + blocksize > valid_size) {
+ u32 voff = valid_size & sbi->block_mask;
+
+ memset(bh->b_data + voff, 0, blocksize - voff);
+ }
+
+ bbuf->buf = (ulong *)bh->b_data;
+ bbuf->bit = 8 * (off & ~(size_t)sbi->block_mask);
+ bbuf->nbits = 8 * blocksize;
+
+ return 0;
+}
+
+static void bmp_buf_put(struct bmp_buf *bbuf, bool dirty)
+{
+ struct buffer_head *bh = bbuf->bh;
+ struct ATTRIB *b = bbuf->b;
+
+ if (!bh) {
+ if (b && !b->non_res && dirty)
+ bbuf->mi->dirty = true;
+ return;
+ }
+
+ if (!dirty)
+ goto out;
+
+ if (bbuf->new_valid) {
+ b->nres.valid_size = cpu_to_le64(bbuf->new_valid);
+ bbuf->mi->dirty = true;
+ }
+
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+
+out:
+ unlock_buffer(bh);
+ put_bh(bh);
+}
+
+/*
+ * indx_mark_used - Mark the bit @bit as used.
+ */
+static int indx_mark_used(struct ntfs_index *indx, struct ntfs_inode *ni,
+ size_t bit)
+{
+ int err;
+ struct bmp_buf bbuf;
+
+ err = bmp_buf_get(indx, ni, bit, &bbuf);
+ if (err)
+ return err;
+
+ __set_bit(bit - bbuf.bit, bbuf.buf);
+
+ bmp_buf_put(&bbuf, true);
+
+ return 0;
+}
+
+/*
+ * indx_mark_free - Mark the bit @bit as free.
+ */
+static int indx_mark_free(struct ntfs_index *indx, struct ntfs_inode *ni,
+ size_t bit)
+{
+ int err;
+ struct bmp_buf bbuf;
+
+ err = bmp_buf_get(indx, ni, bit, &bbuf);
+ if (err)
+ return err;
+
+ __clear_bit(bit - bbuf.bit, bbuf.buf);
+
+ bmp_buf_put(&bbuf, true);
+
+ return 0;
+}
+
+/*
+ * scan_nres_bitmap
+ *
+ * If ntfs_readdir calls this function (indx_used_bit -> scan_nres_bitmap),
+ * inode is shared locked and no ni_lock.
+ * Use rw_semaphore for read/write access to bitmap_run.
+ */
+static int scan_nres_bitmap(struct ntfs_inode *ni, struct ATTRIB *bitmap,
+ struct ntfs_index *indx, size_t from,
+ bool (*fn)(const ulong *buf, u32 bit, u32 bits,
+ size_t *ret),
+ size_t *ret)
+{
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct super_block *sb = sbi->sb;
+ struct runs_tree *run = &indx->bitmap_run;
+ struct rw_semaphore *lock = &indx->run_lock;
+ u32 nbits = sb->s_blocksize * 8;
+ u32 blocksize = sb->s_blocksize;
+ u64 valid_size = le64_to_cpu(bitmap->nres.valid_size);
+ u64 data_size = le64_to_cpu(bitmap->nres.data_size);
+ sector_t eblock = bytes_to_block(sb, data_size);
+ size_t vbo = from >> 3;
+ sector_t blk = (vbo & sbi->cluster_mask) >> sb->s_blocksize_bits;
+ sector_t vblock = vbo >> sb->s_blocksize_bits;
+ sector_t blen, block;
+ CLST lcn, clen, vcn, vcn_next;
+ size_t idx;
+ struct buffer_head *bh;
+ bool ok;
+
+ *ret = MINUS_ONE_T;
+
+ if (vblock >= eblock)
+ return 0;
+
+ from &= nbits - 1;
+ vcn = vbo >> sbi->cluster_bits;
+
+ down_read(lock);
+ ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx);
+ up_read(lock);
+
+next_run:
+ if (!ok) {
+ int err;
+ const struct INDEX_NAMES *name = &s_index_names[indx->type];
+
+ down_write(lock);
+ err = attr_load_runs_vcn(ni, ATTR_BITMAP, name->name,
+ name->name_len, run, vcn);
+ up_write(lock);
+ if (err)
+ return err;
+ down_read(lock);
+ ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx);
+ up_read(lock);
+ if (!ok)
+ return -EINVAL;
+ }
+
+ blen = (sector_t)clen * sbi->blocks_per_cluster;
+ block = (sector_t)lcn * sbi->blocks_per_cluster;
+
+ for (; blk < blen; blk++, from = 0) {
+ bh = ntfs_bread(sb, block + blk);
+ if (!bh)
+ return -EIO;
+
+ vbo = (u64)vblock << sb->s_blocksize_bits;
+ if (vbo >= valid_size) {
+ memset(bh->b_data, 0, blocksize);
+ } else if (vbo + blocksize > valid_size) {
+ u32 voff = valid_size & sbi->block_mask;
+
+ memset(bh->b_data + voff, 0, blocksize - voff);
+ }
+
+ if (vbo + blocksize > data_size)
+ nbits = 8 * (data_size - vbo);
+
+ ok = nbits > from ? (*fn)((ulong *)bh->b_data, from, nbits, ret)
+ : false;
+ put_bh(bh);
+
+ if (ok) {
+ *ret += 8 * vbo;
+ return 0;
+ }
+
+ if (++vblock >= eblock) {
+ *ret = MINUS_ONE_T;
+ return 0;
+ }
+ }
+ blk = 0;
+ vcn_next = vcn + clen;
+ down_read(lock);
+ ok = run_get_entry(run, ++idx, &vcn, &lcn, &clen) && vcn == vcn_next;
+ if (!ok)
+ vcn = vcn_next;
+ up_read(lock);
+ goto next_run;
+}
+
+static bool scan_for_free(const ulong *buf, u32 bit, u32 bits, size_t *ret)
+{
+ size_t pos = find_next_zero_bit(buf, bits, bit);
+
+ if (pos >= bits)
+ return false;
+ *ret = pos;
+ return true;
+}
+
+/*
+ * indx_find_free - Look for free bit.
+ *
+ * Return: -1 if no free bits.
+ */
+static int indx_find_free(struct ntfs_index *indx, struct ntfs_inode *ni,
+ size_t *bit, struct ATTRIB **bitmap)
+{
+ struct ATTRIB *b;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ const struct INDEX_NAMES *in = &s_index_names[indx->type];
+ int err;
+
+ b = ni_find_attr(ni, NULL, &le, ATTR_BITMAP, in->name, in->name_len,
+ NULL, NULL);
+
+ if (!b)
+ return -ENOENT;
+
+ *bitmap = b;
+ *bit = MINUS_ONE_T;
+
+ if (!b->non_res) {
+ u32 nbits = 8 * le32_to_cpu(b->res.data_size);
+ size_t pos = find_next_zero_bit(resident_data(b), nbits, 0);
+
+ if (pos < nbits)
+ *bit = pos;
+ } else {
+ err = scan_nres_bitmap(ni, b, indx, 0, &scan_for_free, bit);
+
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static bool scan_for_used(const ulong *buf, u32 bit, u32 bits, size_t *ret)
+{
+ size_t pos = find_next_bit(buf, bits, bit);
+
+ if (pos >= bits)
+ return false;
+ *ret = pos;
+ return true;
+}
+
+/*
+ * indx_used_bit - Look for used bit.
+ *
+ * Return: MINUS_ONE_T if no used bits.
+ */
+int indx_used_bit(struct ntfs_index *indx, struct ntfs_inode *ni, size_t *bit)
+{
+ struct ATTRIB *b;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ size_t from = *bit;
+ const struct INDEX_NAMES *in = &s_index_names[indx->type];
+ int err;
+
+ b = ni_find_attr(ni, NULL, &le, ATTR_BITMAP, in->name, in->name_len,
+ NULL, NULL);
+
+ if (!b)
+ return -ENOENT;
+
+ *bit = MINUS_ONE_T;
+
+ if (!b->non_res) {
+ u32 nbits = le32_to_cpu(b->res.data_size) * 8;
+ size_t pos = find_next_bit(resident_data(b), nbits, from);
+
+ if (pos < nbits)
+ *bit = pos;
+ } else {
+ err = scan_nres_bitmap(ni, b, indx, from, &scan_for_used, bit);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * hdr_find_split
+ *
+ * Find a point at which the index allocation buffer would like to be split.
+ * NOTE: This function should never return 'END' entry NULL returns on error.
+ */
+static const struct NTFS_DE *hdr_find_split(const struct INDEX_HDR *hdr)
+{
+ size_t o;
+ const struct NTFS_DE *e = hdr_first_de(hdr);
+ u32 used_2 = le32_to_cpu(hdr->used) >> 1;
+ u16 esize;
+
+ if (!e || de_is_last(e))
+ return NULL;
+
+ esize = le16_to_cpu(e->size);
+ for (o = le32_to_cpu(hdr->de_off) + esize; o < used_2; o += esize) {
+ const struct NTFS_DE *p = e;
+
+ e = Add2Ptr(hdr, o);
+
+ /* We must not return END entry. */
+ if (de_is_last(e))
+ return p;
+
+ esize = le16_to_cpu(e->size);
+ }
+
+ return e;
+}
+
+/*
+ * hdr_insert_head - Insert some entries at the beginning of the buffer.
+ *
+ * It is used to insert entries into a newly-created buffer.
+ */
+static const struct NTFS_DE *hdr_insert_head(struct INDEX_HDR *hdr,
+ const void *ins, u32 ins_bytes)
+{
+ u32 to_move;
+ struct NTFS_DE *e = hdr_first_de(hdr);
+ u32 used = le32_to_cpu(hdr->used);
+
+ if (!e)
+ return NULL;
+
+ /* Now we just make room for the inserted entries and jam it in. */
+ to_move = used - le32_to_cpu(hdr->de_off);
+ memmove(Add2Ptr(e, ins_bytes), e, to_move);
+ memcpy(e, ins, ins_bytes);
+ hdr->used = cpu_to_le32(used + ins_bytes);
+
+ return e;
+}
+
+void fnd_clear(struct ntfs_fnd *fnd)
+{
+ int i;
+
+ for (i = 0; i < fnd->level; i++) {
+ struct indx_node *n = fnd->nodes[i];
+
+ if (!n)
+ continue;
+
+ put_indx_node(n);
+ fnd->nodes[i] = NULL;
+ }
+ fnd->level = 0;
+ fnd->root_de = NULL;
+}
+
+static int fnd_push(struct ntfs_fnd *fnd, struct indx_node *n,
+ struct NTFS_DE *e)
+{
+ int i;
+
+ i = fnd->level;
+ if (i < 0 || i >= ARRAY_SIZE(fnd->nodes))
+ return -EINVAL;
+ fnd->nodes[i] = n;
+ fnd->de[i] = e;
+ fnd->level += 1;
+ return 0;
+}
+
+static struct indx_node *fnd_pop(struct ntfs_fnd *fnd)
+{
+ struct indx_node *n;
+ int i = fnd->level;
+
+ i -= 1;
+ n = fnd->nodes[i];
+ fnd->nodes[i] = NULL;
+ fnd->level = i;
+
+ return n;
+}
+
+static bool fnd_is_empty(struct ntfs_fnd *fnd)
+{
+ if (!fnd->level)
+ return !fnd->root_de;
+
+ return !fnd->de[fnd->level - 1];
+}
+
+/*
+ * hdr_find_e - Locate an entry the index buffer.
+ *
+ * If no matching entry is found, it returns the first entry which is greater
+ * than the desired entry If the search key is greater than all the entries the
+ * buffer, it returns the 'end' entry. This function does a binary search of the
+ * current index buffer, for the first entry that is <= to the search value.
+ *
+ * Return: NULL if error.
+ */
+static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx,
+ const struct INDEX_HDR *hdr, const void *key,
+ size_t key_len, const void *ctx, int *diff)
+{
+ struct NTFS_DE *e;
+ NTFS_CMP_FUNC cmp = indx->cmp;
+ u32 e_size, e_key_len;
+ u32 end = le32_to_cpu(hdr->used);
+ u32 off = le32_to_cpu(hdr->de_off);
+
+#ifdef NTFS3_INDEX_BINARY_SEARCH
+ int max_idx = 0, fnd, min_idx;
+ int nslots = 64;
+ u16 *offs;
+
+ if (end > 0x10000)
+ goto next;
+
+ offs = kmalloc(sizeof(u16) * nslots, GFP_NOFS);
+ if (!offs)
+ goto next;
+
+ /* Use binary search algorithm. */
+next1:
+ if (off + sizeof(struct NTFS_DE) > end) {
+ e = NULL;
+ goto out1;
+ }
+ e = Add2Ptr(hdr, off);
+ e_size = le16_to_cpu(e->size);
+
+ if (e_size < sizeof(struct NTFS_DE) || off + e_size > end) {
+ e = NULL;
+ goto out1;
+ }
+
+ if (max_idx >= nslots) {
+ u16 *ptr;
+ int new_slots = ALIGN(2 * nslots, 8);
+
+ ptr = kmalloc(sizeof(u16) * new_slots, GFP_NOFS);
+ if (ptr)
+ memcpy(ptr, offs, sizeof(u16) * max_idx);
+ kfree(offs);
+ offs = ptr;
+ nslots = new_slots;
+ if (!ptr)
+ goto next;
+ }
+
+ /* Store entry table. */
+ offs[max_idx] = off;
+
+ if (!de_is_last(e)) {
+ off += e_size;
+ max_idx += 1;
+ goto next1;
+ }
+
+ /*
+ * Table of pointers is created.
+ * Use binary search to find entry that is <= to the search value.
+ */
+ fnd = -1;
+ min_idx = 0;
+
+ while (min_idx <= max_idx) {
+ int mid_idx = min_idx + ((max_idx - min_idx) >> 1);
+ int diff2;
+
+ e = Add2Ptr(hdr, offs[mid_idx]);
+
+ e_key_len = le16_to_cpu(e->key_size);
+
+ diff2 = (*cmp)(key, key_len, e + 1, e_key_len, ctx);
+
+ if (!diff2) {
+ *diff = 0;
+ goto out1;
+ }
+
+ if (diff2 < 0) {
+ max_idx = mid_idx - 1;
+ fnd = mid_idx;
+ if (!fnd)
+ break;
+ } else {
+ min_idx = mid_idx + 1;
+ }
+ }
+
+ if (fnd == -1) {
+ e = NULL;
+ goto out1;
+ }
+
+ *diff = -1;
+ e = Add2Ptr(hdr, offs[fnd]);
+
+out1:
+ kfree(offs);
+
+ return e;
+#endif
+
+next:
+ /*
+ * Entries index are sorted.
+ * Enumerate all entries until we find entry
+ * that is <= to the search value.
+ */
+ if (off + sizeof(struct NTFS_DE) > end)
+ return NULL;
+
+ e = Add2Ptr(hdr, off);
+ e_size = le16_to_cpu(e->size);
+
+ if (e_size < sizeof(struct NTFS_DE) || off + e_size > end)
+ return NULL;
+
+ off += e_size;
+
+ e_key_len = le16_to_cpu(e->key_size);
+
+ *diff = (*cmp)(key, key_len, e + 1, e_key_len, ctx);
+ if (!*diff)
+ return e;
+
+ if (*diff <= 0)
+ return e;
+
+ if (de_is_last(e)) {
+ *diff = 1;
+ return e;
+ }
+ goto next;
+}
+
+/*
+ * hdr_insert_de - Insert an index entry into the buffer.
+ *
+ * 'before' should be a pointer previously returned from hdr_find_e.
+ */
+static struct NTFS_DE *hdr_insert_de(const struct ntfs_index *indx,
+ struct INDEX_HDR *hdr,
+ const struct NTFS_DE *de,
+ struct NTFS_DE *before, const void *ctx)
+{
+ int diff;
+ size_t off = PtrOffset(hdr, before);
+ u32 used = le32_to_cpu(hdr->used);
+ u32 total = le32_to_cpu(hdr->total);
+ u16 de_size = le16_to_cpu(de->size);
+
+ /* First, check to see if there's enough room. */
+ if (used + de_size > total)
+ return NULL;
+
+ /* We know there's enough space, so we know we'll succeed. */
+ if (before) {
+ /* Check that before is inside Index. */
+ if (off >= used || off < le32_to_cpu(hdr->de_off) ||
+ off + le16_to_cpu(before->size) > total) {
+ return NULL;
+ }
+ goto ok;
+ }
+ /* No insert point is applied. Get it manually. */
+ before = hdr_find_e(indx, hdr, de + 1, le16_to_cpu(de->key_size), ctx,
+ &diff);
+ if (!before)
+ return NULL;
+ off = PtrOffset(hdr, before);
+
+ok:
+ /* Now we just make room for the entry and jam it in. */
+ memmove(Add2Ptr(before, de_size), before, used - off);
+
+ hdr->used = cpu_to_le32(used + de_size);
+ memcpy(before, de, de_size);
+
+ return before;
+}
+
+/*
+ * hdr_delete_de - Remove an entry from the index buffer.
+ */
+static inline struct NTFS_DE *hdr_delete_de(struct INDEX_HDR *hdr,
+ struct NTFS_DE *re)
+{
+ u32 used = le32_to_cpu(hdr->used);
+ u16 esize = le16_to_cpu(re->size);
+ u32 off = PtrOffset(hdr, re);
+ int bytes = used - (off + esize);
+
+ if (off >= used || esize < sizeof(struct NTFS_DE) ||
+ bytes < sizeof(struct NTFS_DE))
+ return NULL;
+
+ hdr->used = cpu_to_le32(used - esize);
+ memmove(re, Add2Ptr(re, esize), bytes);
+
+ return re;
+}
+
+void indx_clear(struct ntfs_index *indx)
+{
+ run_close(&indx->alloc_run);
+ run_close(&indx->bitmap_run);
+}
+
+int indx_init(struct ntfs_index *indx, struct ntfs_sb_info *sbi,
+ const struct ATTRIB *attr, enum index_mutex_classed type)
+{
+ u32 t32;
+ const struct INDEX_ROOT *root = resident_data(attr);
+
+ /* Check root fields. */
+ if (!root->index_block_clst)
+ return -EINVAL;
+
+ indx->type = type;
+ indx->idx2vbn_bits = __ffs(root->index_block_clst);
+
+ t32 = le32_to_cpu(root->index_block_size);
+ indx->index_bits = blksize_bits(t32);
+
+ /* Check index record size. */
+ if (t32 < sbi->cluster_size) {
+ /* Index record is smaller than a cluster, use 512 blocks. */
+ if (t32 != root->index_block_clst * SECTOR_SIZE)
+ return -EINVAL;
+
+ /* Check alignment to a cluster. */
+ if ((sbi->cluster_size >> SECTOR_SHIFT) &
+ (root->index_block_clst - 1)) {
+ return -EINVAL;
+ }
+
+ indx->vbn2vbo_bits = SECTOR_SHIFT;
+ } else {
+ /* Index record must be a multiple of cluster size. */
+ if (t32 != root->index_block_clst << sbi->cluster_bits)
+ return -EINVAL;
+
+ indx->vbn2vbo_bits = sbi->cluster_bits;
+ }
+
+ init_rwsem(&indx->run_lock);
+
+ indx->cmp = get_cmp_func(root);
+ return indx->cmp ? 0 : -EINVAL;
+}
+
+static struct indx_node *indx_new(struct ntfs_index *indx,
+ struct ntfs_inode *ni, CLST vbn,
+ const __le64 *sub_vbn)
+{
+ int err;
+ struct NTFS_DE *e;
+ struct indx_node *r;
+ struct INDEX_HDR *hdr;
+ struct INDEX_BUFFER *index;
+ u64 vbo = (u64)vbn << indx->vbn2vbo_bits;
+ u32 bytes = 1u << indx->index_bits;
+ u16 fn;
+ u32 eo;
+
+ r = kzalloc(sizeof(struct indx_node), GFP_NOFS);
+ if (!r)
+ return ERR_PTR(-ENOMEM);
+
+ index = kzalloc(bytes, GFP_NOFS);
+ if (!index) {
+ kfree(r);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ err = ntfs_get_bh(ni->mi.sbi, &indx->alloc_run, vbo, bytes, &r->nb);
+
+ if (err) {
+ kfree(index);
+ kfree(r);
+ return ERR_PTR(err);
+ }
+
+ /* Create header. */
+ index->rhdr.sign = NTFS_INDX_SIGNATURE;
+ index->rhdr.fix_off = cpu_to_le16(sizeof(struct INDEX_BUFFER)); // 0x28
+ fn = (bytes >> SECTOR_SHIFT) + 1; // 9
+ index->rhdr.fix_num = cpu_to_le16(fn);
+ index->vbn = cpu_to_le64(vbn);
+ hdr = &index->ihdr;
+ eo = ALIGN(sizeof(struct INDEX_BUFFER) + fn * sizeof(short), 8);
+ hdr->de_off = cpu_to_le32(eo);
+
+ e = Add2Ptr(hdr, eo);
+
+ if (sub_vbn) {
+ e->flags = NTFS_IE_LAST | NTFS_IE_HAS_SUBNODES;
+ e->size = cpu_to_le16(sizeof(struct NTFS_DE) + sizeof(u64));
+ hdr->used =
+ cpu_to_le32(eo + sizeof(struct NTFS_DE) + sizeof(u64));
+ de_set_vbn_le(e, *sub_vbn);
+ hdr->flags = 1;
+ } else {
+ e->size = cpu_to_le16(sizeof(struct NTFS_DE));
+ hdr->used = cpu_to_le32(eo + sizeof(struct NTFS_DE));
+ e->flags = NTFS_IE_LAST;
+ }
+
+ hdr->total = cpu_to_le32(bytes - offsetof(struct INDEX_BUFFER, ihdr));
+
+ r->index = index;
+ return r;
+}
+
+struct INDEX_ROOT *indx_get_root(struct ntfs_index *indx, struct ntfs_inode *ni,
+ struct ATTRIB **attr, struct mft_inode **mi)
+{
+ struct ATTR_LIST_ENTRY *le = NULL;
+ struct ATTRIB *a;
+ const struct INDEX_NAMES *in = &s_index_names[indx->type];
+
+ a = ni_find_attr(ni, NULL, &le, ATTR_ROOT, in->name, in->name_len, NULL,
+ mi);
+ if (!a)
+ return NULL;
+
+ if (attr)
+ *attr = a;
+
+ return resident_data_ex(a, sizeof(struct INDEX_ROOT));
+}
+
+static int indx_write(struct ntfs_index *indx, struct ntfs_inode *ni,
+ struct indx_node *node, int sync)
+{
+ struct INDEX_BUFFER *ib = node->index;
+
+ return ntfs_write_bh(ni->mi.sbi, &ib->rhdr, &node->nb, sync);
+}
+
+/*
+ * indx_read
+ *
+ * If ntfs_readdir calls this function
+ * inode is shared locked and no ni_lock.
+ * Use rw_semaphore for read/write access to alloc_run.
+ */
+int indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn,
+ struct indx_node **node)
+{
+ int err;
+ struct INDEX_BUFFER *ib;
+ struct runs_tree *run = &indx->alloc_run;
+ struct rw_semaphore *lock = &indx->run_lock;
+ u64 vbo = (u64)vbn << indx->vbn2vbo_bits;
+ u32 bytes = 1u << indx->index_bits;
+ struct indx_node *in = *node;
+ const struct INDEX_NAMES *name;
+
+ if (!in) {
+ in = kzalloc(sizeof(struct indx_node), GFP_NOFS);
+ if (!in)
+ return -ENOMEM;
+ } else {
+ nb_put(&in->nb);
+ }
+
+ ib = in->index;
+ if (!ib) {
+ ib = kmalloc(bytes, GFP_NOFS);
+ if (!ib) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
+
+ down_read(lock);
+ err = ntfs_read_bh(ni->mi.sbi, run, vbo, &ib->rhdr, bytes, &in->nb);
+ up_read(lock);
+ if (!err)
+ goto ok;
+
+ if (err == -E_NTFS_FIXUP)
+ goto ok;
+
+ if (err != -ENOENT)
+ goto out;
+
+ name = &s_index_names[indx->type];
+ down_write(lock);
+ err = attr_load_runs_range(ni, ATTR_ALLOC, name->name, name->name_len,
+ run, vbo, vbo + bytes);
+ up_write(lock);
+ if (err)
+ goto out;
+
+ down_read(lock);
+ err = ntfs_read_bh(ni->mi.sbi, run, vbo, &ib->rhdr, bytes, &in->nb);
+ up_read(lock);
+ if (err == -E_NTFS_FIXUP)
+ goto ok;
+
+ if (err)
+ goto out;
+
+ok:
+ if (err == -E_NTFS_FIXUP) {
+ ntfs_write_bh(ni->mi.sbi, &ib->rhdr, &in->nb, 0);
+ err = 0;
+ }
+
+ in->index = ib;
+ *node = in;
+
+out:
+ if (ib != in->index)
+ kfree(ib);
+
+ if (*node != in) {
+ nb_put(&in->nb);
+ kfree(in);
+ }
+
+ return err;
+}
+
+/*
+ * indx_find - Scan NTFS directory for given entry.
+ */
+int indx_find(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct INDEX_ROOT *root, const void *key, size_t key_len,
+ const void *ctx, int *diff, struct NTFS_DE **entry,
+ struct ntfs_fnd *fnd)
+{
+ int err;
+ struct NTFS_DE *e;
+ const struct INDEX_HDR *hdr;
+ struct indx_node *node;
+
+ if (!root)
+ root = indx_get_root(&ni->dir, ni, NULL, NULL);
+
+ if (!root) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ hdr = &root->ihdr;
+
+ /* Check cache. */
+ e = fnd->level ? fnd->de[fnd->level - 1] : fnd->root_de;
+ if (e && !de_is_last(e) &&
+ !(*indx->cmp)(key, key_len, e + 1, le16_to_cpu(e->key_size), ctx)) {
+ *entry = e;
+ *diff = 0;
+ return 0;
+ }
+
+ /* Soft finder reset. */
+ fnd_clear(fnd);
+
+ /* Lookup entry that is <= to the search value. */
+ e = hdr_find_e(indx, hdr, key, key_len, ctx, diff);
+ if (!e)
+ return -EINVAL;
+
+ if (fnd)
+ fnd->root_de = e;
+
+ err = 0;
+
+ for (;;) {
+ node = NULL;
+ if (*diff >= 0 || !de_has_vcn_ex(e)) {
+ *entry = e;
+ goto out;
+ }
+
+ /* Read next level. */
+ err = indx_read(indx, ni, de_get_vbn(e), &node);
+ if (err)
+ goto out;
+
+ /* Lookup entry that is <= to the search value. */
+ e = hdr_find_e(indx, &node->index->ihdr, key, key_len, ctx,
+ diff);
+ if (!e) {
+ err = -EINVAL;
+ put_indx_node(node);
+ goto out;
+ }
+
+ fnd_push(fnd, node, e);
+ }
+
+out:
+ return err;
+}
+
+int indx_find_sort(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct INDEX_ROOT *root, struct NTFS_DE **entry,
+ struct ntfs_fnd *fnd)
+{
+ int err;
+ struct indx_node *n = NULL;
+ struct NTFS_DE *e;
+ size_t iter = 0;
+ int level = fnd->level;
+
+ if (!*entry) {
+ /* Start find. */
+ e = hdr_first_de(&root->ihdr);
+ if (!e)
+ return 0;
+ fnd_clear(fnd);
+ fnd->root_de = e;
+ } else if (!level) {
+ if (de_is_last(fnd->root_de)) {
+ *entry = NULL;
+ return 0;
+ }
+
+ e = hdr_next_de(&root->ihdr, fnd->root_de);
+ if (!e)
+ return -EINVAL;
+ fnd->root_de = e;
+ } else {
+ n = fnd->nodes[level - 1];
+ e = fnd->de[level - 1];
+
+ if (de_is_last(e))
+ goto pop_level;
+
+ e = hdr_next_de(&n->index->ihdr, e);
+ if (!e)
+ return -EINVAL;
+
+ fnd->de[level - 1] = e;
+ }
+
+ /* Just to avoid tree cycle. */
+next_iter:
+ if (iter++ >= 1000)
+ return -EINVAL;
+
+ while (de_has_vcn_ex(e)) {
+ if (le16_to_cpu(e->size) <
+ sizeof(struct NTFS_DE) + sizeof(u64)) {
+ if (n) {
+ fnd_pop(fnd);
+ kfree(n);
+ }
+ return -EINVAL;
+ }
+
+ /* Read next level. */
+ err = indx_read(indx, ni, de_get_vbn(e), &n);
+ if (err)
+ return err;
+
+ /* Try next level. */
+ e = hdr_first_de(&n->index->ihdr);
+ if (!e) {
+ kfree(n);
+ return -EINVAL;
+ }
+
+ fnd_push(fnd, n, e);
+ }
+
+ if (le16_to_cpu(e->size) > sizeof(struct NTFS_DE)) {
+ *entry = e;
+ return 0;
+ }
+
+pop_level:
+ for (;;) {
+ if (!de_is_last(e))
+ goto next_iter;
+
+ /* Pop one level. */
+ if (n) {
+ fnd_pop(fnd);
+ kfree(n);
+ }
+
+ level = fnd->level;
+
+ if (level) {
+ n = fnd->nodes[level - 1];
+ e = fnd->de[level - 1];
+ } else if (fnd->root_de) {
+ n = NULL;
+ e = fnd->root_de;
+ fnd->root_de = NULL;
+ } else {
+ *entry = NULL;
+ return 0;
+ }
+
+ if (le16_to_cpu(e->size) > sizeof(struct NTFS_DE)) {
+ *entry = e;
+ if (!fnd->root_de)
+ fnd->root_de = e;
+ return 0;
+ }
+ }
+}
+
+int indx_find_raw(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct INDEX_ROOT *root, struct NTFS_DE **entry,
+ size_t *off, struct ntfs_fnd *fnd)
+{
+ int err;
+ struct indx_node *n = NULL;
+ struct NTFS_DE *e = NULL;
+ struct NTFS_DE *e2;
+ size_t bit;
+ CLST next_used_vbn;
+ CLST next_vbn;
+ u32 record_size = ni->mi.sbi->record_size;
+
+ /* Use non sorted algorithm. */
+ if (!*entry) {
+ /* This is the first call. */
+ e = hdr_first_de(&root->ihdr);
+ if (!e)
+ return 0;
+ fnd_clear(fnd);
+ fnd->root_de = e;
+
+ /* The first call with setup of initial element. */
+ if (*off >= record_size) {
+ next_vbn = (((*off - record_size) >> indx->index_bits))
+ << indx->idx2vbn_bits;
+ /* Jump inside cycle 'for'. */
+ goto next;
+ }
+
+ /* Start enumeration from root. */
+ *off = 0;
+ } else if (!fnd->root_de)
+ return -EINVAL;
+
+ for (;;) {
+ /* Check if current entry can be used. */
+ if (e && le16_to_cpu(e->size) > sizeof(struct NTFS_DE))
+ goto ok;
+
+ if (!fnd->level) {
+ /* Continue to enumerate root. */
+ if (!de_is_last(fnd->root_de)) {
+ e = hdr_next_de(&root->ihdr, fnd->root_de);
+ if (!e)
+ return -EINVAL;
+ fnd->root_de = e;
+ continue;
+ }
+
+ /* Start to enumerate indexes from 0. */
+ next_vbn = 0;
+ } else {
+ /* Continue to enumerate indexes. */
+ e2 = fnd->de[fnd->level - 1];
+
+ n = fnd->nodes[fnd->level - 1];
+
+ if (!de_is_last(e2)) {
+ e = hdr_next_de(&n->index->ihdr, e2);
+ if (!e)
+ return -EINVAL;
+ fnd->de[fnd->level - 1] = e;
+ continue;
+ }
+
+ /* Continue with next index. */
+ next_vbn = le64_to_cpu(n->index->vbn) +
+ root->index_block_clst;
+ }
+
+next:
+ /* Release current index. */
+ if (n) {
+ fnd_pop(fnd);
+ put_indx_node(n);
+ n = NULL;
+ }
+
+ /* Skip all free indexes. */
+ bit = next_vbn >> indx->idx2vbn_bits;
+ err = indx_used_bit(indx, ni, &bit);
+ if (err == -ENOENT || bit == MINUS_ONE_T) {
+ /* No used indexes. */
+ *entry = NULL;
+ return 0;
+ }
+
+ next_used_vbn = bit << indx->idx2vbn_bits;
+
+ /* Read buffer into memory. */
+ err = indx_read(indx, ni, next_used_vbn, &n);
+ if (err)
+ return err;
+
+ e = hdr_first_de(&n->index->ihdr);
+ fnd_push(fnd, n, e);
+ if (!e)
+ return -EINVAL;
+ }
+
+ok:
+ /* Return offset to restore enumerator if necessary. */
+ if (!n) {
+ /* 'e' points in root, */
+ *off = PtrOffset(&root->ihdr, e);
+ } else {
+ /* 'e' points in index, */
+ *off = (le64_to_cpu(n->index->vbn) << indx->vbn2vbo_bits) +
+ record_size + PtrOffset(&n->index->ihdr, e);
+ }
+
+ *entry = e;
+ return 0;
+}
+
+/*
+ * indx_create_allocate - Create "Allocation + Bitmap" attributes.
+ */
+static int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
+ CLST *vbn)
+{
+ int err = -ENOMEM;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct ATTRIB *bitmap;
+ struct ATTRIB *alloc;
+ u32 data_size = 1u << indx->index_bits;
+ u32 alloc_size = ntfs_up_cluster(sbi, data_size);
+ CLST len = alloc_size >> sbi->cluster_bits;
+ const struct INDEX_NAMES *in = &s_index_names[indx->type];
+ CLST alen;
+ struct runs_tree run;
+
+ run_init(&run);
+
+ err = attr_allocate_clusters(sbi, &run, 0, 0, len, NULL, 0, &alen, 0,
+ NULL);
+ if (err)
+ goto out;
+
+ err = ni_insert_nonresident(ni, ATTR_ALLOC, in->name, in->name_len,
+ &run, 0, len, 0, &alloc, NULL);
+ if (err)
+ goto out1;
+
+ alloc->nres.valid_size = alloc->nres.data_size = cpu_to_le64(data_size);
+
+ err = ni_insert_resident(ni, bitmap_size(1), ATTR_BITMAP, in->name,
+ in->name_len, &bitmap, NULL, NULL);
+ if (err)
+ goto out2;
+
+ if (in->name == I30_NAME) {
+ ni->vfs_inode.i_size = data_size;
+ inode_set_bytes(&ni->vfs_inode, alloc_size);
+ }
+
+ memcpy(&indx->alloc_run, &run, sizeof(run));
+
+ *vbn = 0;
+
+ return 0;
+
+out2:
+ mi_remove_attr(NULL, &ni->mi, alloc);
+
+out1:
+ run_deallocate(sbi, &run, false);
+
+out:
+ return err;
+}
+
+/*
+ * indx_add_allocate - Add clusters to index.
+ */
+static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
+ CLST *vbn)
+{
+ int err;
+ size_t bit;
+ u64 data_size;
+ u64 bmp_size, bmp_size_v;
+ struct ATTRIB *bmp, *alloc;
+ struct mft_inode *mi;
+ const struct INDEX_NAMES *in = &s_index_names[indx->type];
+
+ err = indx_find_free(indx, ni, &bit, &bmp);
+ if (err)
+ goto out1;
+
+ if (bit != MINUS_ONE_T) {
+ bmp = NULL;
+ } else {
+ if (bmp->non_res) {
+ bmp_size = le64_to_cpu(bmp->nres.data_size);
+ bmp_size_v = le64_to_cpu(bmp->nres.valid_size);
+ } else {
+ bmp_size = bmp_size_v = le32_to_cpu(bmp->res.data_size);
+ }
+
+ bit = bmp_size << 3;
+ }
+
+ data_size = (u64)(bit + 1) << indx->index_bits;
+
+ if (bmp) {
+ /* Increase bitmap. */
+ err = attr_set_size(ni, ATTR_BITMAP, in->name, in->name_len,
+ &indx->bitmap_run, bitmap_size(bit + 1),
+ NULL, true, NULL);
+ if (err)
+ goto out1;
+ }
+
+ alloc = ni_find_attr(ni, NULL, NULL, ATTR_ALLOC, in->name, in->name_len,
+ NULL, &mi);
+ if (!alloc) {
+ err = -EINVAL;
+ if (bmp)
+ goto out2;
+ goto out1;
+ }
+
+ /* Increase allocation. */
+ err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len,
+ &indx->alloc_run, data_size, &data_size, true,
+ NULL);
+ if (err) {
+ if (bmp)
+ goto out2;
+ goto out1;
+ }
+
+ *vbn = bit << indx->idx2vbn_bits;
+
+ return 0;
+
+out2:
+ /* Ops. No space? */
+ attr_set_size(ni, ATTR_BITMAP, in->name, in->name_len,
+ &indx->bitmap_run, bmp_size, &bmp_size_v, false, NULL);
+
+out1:
+ return err;
+}
+
+/*
+ * indx_insert_into_root - Attempt to insert an entry into the index root.
+ *
+ * @undo - True if we undoing previous remove.
+ * If necessary, it will twiddle the index b-tree.
+ */
+static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct NTFS_DE *new_de,
+ struct NTFS_DE *root_de, const void *ctx,
+ struct ntfs_fnd *fnd, bool undo)
+{
+ int err = 0;
+ struct NTFS_DE *e, *e0, *re;
+ struct mft_inode *mi;
+ struct ATTRIB *attr;
+ struct INDEX_HDR *hdr;
+ struct indx_node *n;
+ CLST new_vbn;
+ __le64 *sub_vbn, t_vbn;
+ u16 new_de_size;
+ u32 hdr_used, hdr_total, asize, to_move;
+ u32 root_size, new_root_size;
+ struct ntfs_sb_info *sbi;
+ int ds_root;
+ struct INDEX_ROOT *root, *a_root;
+
+ /* Get the record this root placed in. */
+ root = indx_get_root(indx, ni, &attr, &mi);
+ if (!root)
+ return -EINVAL;
+
+ /*
+ * Try easy case:
+ * hdr_insert_de will succeed if there's
+ * room the root for the new entry.
+ */
+ hdr = &root->ihdr;
+ sbi = ni->mi.sbi;
+ new_de_size = le16_to_cpu(new_de->size);
+ hdr_used = le32_to_cpu(hdr->used);
+ hdr_total = le32_to_cpu(hdr->total);
+ asize = le32_to_cpu(attr->size);
+ root_size = le32_to_cpu(attr->res.data_size);
+
+ ds_root = new_de_size + hdr_used - hdr_total;
+
+ /* If 'undo' is set then reduce requirements. */
+ if ((undo || asize + ds_root < sbi->max_bytes_per_attr) &&
+ mi_resize_attr(mi, attr, ds_root)) {
+ hdr->total = cpu_to_le32(hdr_total + ds_root);
+ e = hdr_insert_de(indx, hdr, new_de, root_de, ctx);
+ WARN_ON(!e);
+ fnd_clear(fnd);
+ fnd->root_de = e;
+
+ return 0;
+ }
+
+ /* Make a copy of root attribute to restore if error. */
+ a_root = kmemdup(attr, asize, GFP_NOFS);
+ if (!a_root)
+ return -ENOMEM;
+
+ /*
+ * Copy all the non-end entries from
+ * the index root to the new buffer.
+ */
+ to_move = 0;
+ e0 = hdr_first_de(hdr);
+
+ /* Calculate the size to copy. */
+ for (e = e0;; e = hdr_next_de(hdr, e)) {
+ if (!e) {
+ err = -EINVAL;
+ goto out_free_root;
+ }
+
+ if (de_is_last(e))
+ break;
+ to_move += le16_to_cpu(e->size);
+ }
+
+ if (!to_move) {
+ re = NULL;
+ } else {
+ re = kmemdup(e0, to_move, GFP_NOFS);
+ if (!re) {
+ err = -ENOMEM;
+ goto out_free_root;
+ }
+ }
+
+ sub_vbn = NULL;
+ if (de_has_vcn(e)) {
+ t_vbn = de_get_vbn_le(e);
+ sub_vbn = &t_vbn;
+ }
+
+ new_root_size = sizeof(struct INDEX_ROOT) + sizeof(struct NTFS_DE) +
+ sizeof(u64);
+ ds_root = new_root_size - root_size;
+
+ if (ds_root > 0 && asize + ds_root > sbi->max_bytes_per_attr) {
+ /* Make root external. */
+ err = -EOPNOTSUPP;
+ goto out_free_re;
+ }
+
+ if (ds_root)
+ mi_resize_attr(mi, attr, ds_root);
+
+ /* Fill first entry (vcn will be set later). */
+ e = (struct NTFS_DE *)(root + 1);
+ memset(e, 0, sizeof(struct NTFS_DE));
+ e->size = cpu_to_le16(sizeof(struct NTFS_DE) + sizeof(u64));
+ e->flags = NTFS_IE_HAS_SUBNODES | NTFS_IE_LAST;
+
+ hdr->flags = 1;
+ hdr->used = hdr->total =
+ cpu_to_le32(new_root_size - offsetof(struct INDEX_ROOT, ihdr));
+
+ fnd->root_de = hdr_first_de(hdr);
+ mi->dirty = true;
+
+ /* Create alloc and bitmap attributes (if not). */
+ err = run_is_empty(&indx->alloc_run)
+ ? indx_create_allocate(indx, ni, &new_vbn)
+ : indx_add_allocate(indx, ni, &new_vbn);
+
+ /* Layout of record may be changed, so rescan root. */
+ root = indx_get_root(indx, ni, &attr, &mi);
+ if (!root) {
+ /* Bug? */
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+ err = -EINVAL;
+ goto out_free_re;
+ }
+
+ if (err) {
+ /* Restore root. */
+ if (mi_resize_attr(mi, attr, -ds_root))
+ memcpy(attr, a_root, asize);
+ else {
+ /* Bug? */
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+ }
+ goto out_free_re;
+ }
+
+ e = (struct NTFS_DE *)(root + 1);
+ *(__le64 *)(e + 1) = cpu_to_le64(new_vbn);
+ mi->dirty = true;
+
+ /* Now we can create/format the new buffer and copy the entries into. */
+ n = indx_new(indx, ni, new_vbn, sub_vbn);
+ if (IS_ERR(n)) {
+ err = PTR_ERR(n);
+ goto out_free_re;
+ }
+
+ hdr = &n->index->ihdr;
+ hdr_used = le32_to_cpu(hdr->used);
+ hdr_total = le32_to_cpu(hdr->total);
+
+ /* Copy root entries into new buffer. */
+ hdr_insert_head(hdr, re, to_move);
+
+ /* Update bitmap attribute. */
+ indx_mark_used(indx, ni, new_vbn >> indx->idx2vbn_bits);
+
+ /* Check if we can insert new entry new index buffer. */
+ if (hdr_used + new_de_size > hdr_total) {
+ /*
+ * This occurs if MFT record is the same or bigger than index
+ * buffer. Move all root new index and have no space to add
+ * new entry classic case when MFT record is 1K and index
+ * buffer 4K the problem should not occurs.
+ */
+ kfree(re);
+ indx_write(indx, ni, n, 0);
+
+ put_indx_node(n);
+ fnd_clear(fnd);
+ err = indx_insert_entry(indx, ni, new_de, ctx, fnd, undo);
+ goto out_free_root;
+ }
+
+ /*
+ * Now root is a parent for new index buffer.
+ * Insert NewEntry a new buffer.
+ */
+ e = hdr_insert_de(indx, hdr, new_de, NULL, ctx);
+ if (!e) {
+ err = -EINVAL;
+ goto out_put_n;
+ }
+ fnd_push(fnd, n, e);
+
+ /* Just write updates index into disk. */
+ indx_write(indx, ni, n, 0);
+
+ n = NULL;
+
+out_put_n:
+ put_indx_node(n);
+out_free_re:
+ kfree(re);
+out_free_root:
+ kfree(a_root);
+ return err;
+}
+
+/*
+ * indx_insert_into_buffer
+ *
+ * Attempt to insert an entry into an Index Allocation Buffer.
+ * If necessary, it will split the buffer.
+ */
+static int
+indx_insert_into_buffer(struct ntfs_index *indx, struct ntfs_inode *ni,
+ struct INDEX_ROOT *root, const struct NTFS_DE *new_de,
+ const void *ctx, int level, struct ntfs_fnd *fnd)
+{
+ int err;
+ const struct NTFS_DE *sp;
+ struct NTFS_DE *e, *de_t, *up_e = NULL;
+ struct indx_node *n2 = NULL;
+ struct indx_node *n1 = fnd->nodes[level];
+ struct INDEX_HDR *hdr1 = &n1->index->ihdr;
+ struct INDEX_HDR *hdr2;
+ u32 to_copy, used;
+ CLST new_vbn;
+ __le64 t_vbn, *sub_vbn;
+ u16 sp_size;
+
+ /* Try the most easy case. */
+ e = fnd->level - 1 == level ? fnd->de[level] : NULL;
+ e = hdr_insert_de(indx, hdr1, new_de, e, ctx);
+ fnd->de[level] = e;
+ if (e) {
+ /* Just write updated index into disk. */
+ indx_write(indx, ni, n1, 0);
+ return 0;
+ }
+
+ /*
+ * No space to insert into buffer. Split it.
+ * To split we:
+ * - Save split point ('cause index buffers will be changed)
+ * - Allocate NewBuffer and copy all entries <= sp into new buffer
+ * - Remove all entries (sp including) from TargetBuffer
+ * - Insert NewEntry into left or right buffer (depending on sp <=>
+ * NewEntry)
+ * - Insert sp into parent buffer (or root)
+ * - Make sp a parent for new buffer
+ */
+ sp = hdr_find_split(hdr1);
+ if (!sp)
+ return -EINVAL;
+
+ sp_size = le16_to_cpu(sp->size);
+ up_e = kmalloc(sp_size + sizeof(u64), GFP_NOFS);
+ if (!up_e)
+ return -ENOMEM;
+ memcpy(up_e, sp, sp_size);
+
+ if (!hdr1->flags) {
+ up_e->flags |= NTFS_IE_HAS_SUBNODES;
+ up_e->size = cpu_to_le16(sp_size + sizeof(u64));
+ sub_vbn = NULL;
+ } else {
+ t_vbn = de_get_vbn_le(up_e);
+ sub_vbn = &t_vbn;
+ }
+
+ /* Allocate on disk a new index allocation buffer. */
+ err = indx_add_allocate(indx, ni, &new_vbn);
+ if (err)
+ goto out;
+
+ /* Allocate and format memory a new index buffer. */
+ n2 = indx_new(indx, ni, new_vbn, sub_vbn);
+ if (IS_ERR(n2)) {
+ err = PTR_ERR(n2);
+ goto out;
+ }
+
+ hdr2 = &n2->index->ihdr;
+
+ /* Make sp a parent for new buffer. */
+ de_set_vbn(up_e, new_vbn);
+
+ /* Copy all the entries <= sp into the new buffer. */
+ de_t = hdr_first_de(hdr1);
+ to_copy = PtrOffset(de_t, sp);
+ hdr_insert_head(hdr2, de_t, to_copy);
+
+ /* Remove all entries (sp including) from hdr1. */
+ used = le32_to_cpu(hdr1->used) - to_copy - sp_size;
+ memmove(de_t, Add2Ptr(sp, sp_size), used - le32_to_cpu(hdr1->de_off));
+ hdr1->used = cpu_to_le32(used);
+
+ /*
+ * Insert new entry into left or right buffer
+ * (depending on sp <=> new_de).
+ */
+ hdr_insert_de(indx,
+ (*indx->cmp)(new_de + 1, le16_to_cpu(new_de->key_size),
+ up_e + 1, le16_to_cpu(up_e->key_size),
+ ctx) < 0
+ ? hdr2
+ : hdr1,
+ new_de, NULL, ctx);
+
+ indx_mark_used(indx, ni, new_vbn >> indx->idx2vbn_bits);
+
+ indx_write(indx, ni, n1, 0);
+ indx_write(indx, ni, n2, 0);
+
+ put_indx_node(n2);
+
+ /*
+ * We've finished splitting everybody, so we are ready to
+ * insert the promoted entry into the parent.
+ */
+ if (!level) {
+ /* Insert in root. */
+ err = indx_insert_into_root(indx, ni, up_e, NULL, ctx, fnd, 0);
+ if (err)
+ goto out;
+ } else {
+ /*
+ * The target buffer's parent is another index buffer.
+ * TODO: Remove recursion.
+ */
+ err = indx_insert_into_buffer(indx, ni, root, up_e, ctx,
+ level - 1, fnd);
+ if (err)
+ goto out;
+ }
+
+out:
+ kfree(up_e);
+
+ return err;
+}
+
+/*
+ * indx_insert_entry - Insert new entry into index.
+ *
+ * @undo - True if we undoing previous remove.
+ */
+int indx_insert_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct NTFS_DE *new_de, const void *ctx,
+ struct ntfs_fnd *fnd, bool undo)
+{
+ int err;
+ int diff;
+ struct NTFS_DE *e;
+ struct ntfs_fnd *fnd_a = NULL;
+ struct INDEX_ROOT *root;
+
+ if (!fnd) {
+ fnd_a = fnd_get();
+ if (!fnd_a) {
+ err = -ENOMEM;
+ goto out1;
+ }
+ fnd = fnd_a;
+ }
+
+ root = indx_get_root(indx, ni, NULL, NULL);
+ if (!root) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (fnd_is_empty(fnd)) {
+ /*
+ * Find the spot the tree where we want to
+ * insert the new entry.
+ */
+ err = indx_find(indx, ni, root, new_de + 1,
+ le16_to_cpu(new_de->key_size), ctx, &diff, &e,
+ fnd);
+ if (err)
+ goto out;
+
+ if (!diff) {
+ err = -EEXIST;
+ goto out;
+ }
+ }
+
+ if (!fnd->level) {
+ /*
+ * The root is also a leaf, so we'll insert the
+ * new entry into it.
+ */
+ err = indx_insert_into_root(indx, ni, new_de, fnd->root_de, ctx,
+ fnd, undo);
+ if (err)
+ goto out;
+ } else {
+ /*
+ * Found a leaf buffer, so we'll insert the new entry into it.
+ */
+ err = indx_insert_into_buffer(indx, ni, root, new_de, ctx,
+ fnd->level - 1, fnd);
+ if (err)
+ goto out;
+ }
+
+out:
+ fnd_put(fnd_a);
+out1:
+ return err;
+}
+
+/*
+ * indx_find_buffer - Locate a buffer from the tree.
+ */
+static struct indx_node *indx_find_buffer(struct ntfs_index *indx,
+ struct ntfs_inode *ni,
+ const struct INDEX_ROOT *root,
+ __le64 vbn, struct indx_node *n)
+{
+ int err;
+ const struct NTFS_DE *e;
+ struct indx_node *r;
+ const struct INDEX_HDR *hdr = n ? &n->index->ihdr : &root->ihdr;
+
+ /* Step 1: Scan one level. */
+ for (e = hdr_first_de(hdr);; e = hdr_next_de(hdr, e)) {
+ if (!e)
+ return ERR_PTR(-EINVAL);
+
+ if (de_has_vcn(e) && vbn == de_get_vbn_le(e))
+ return n;
+
+ if (de_is_last(e))
+ break;
+ }
+
+ /* Step2: Do recursion. */
+ e = Add2Ptr(hdr, le32_to_cpu(hdr->de_off));
+ for (;;) {
+ if (de_has_vcn_ex(e)) {
+ err = indx_read(indx, ni, de_get_vbn(e), &n);
+ if (err)
+ return ERR_PTR(err);
+
+ r = indx_find_buffer(indx, ni, root, vbn, n);
+ if (r)
+ return r;
+ }
+
+ if (de_is_last(e))
+ break;
+
+ e = Add2Ptr(e, le16_to_cpu(e->size));
+ }
+
+ return NULL;
+}
+
+/*
+ * indx_shrink - Deallocate unused tail indexes.
+ */
+static int indx_shrink(struct ntfs_index *indx, struct ntfs_inode *ni,
+ size_t bit)
+{
+ int err = 0;
+ u64 bpb, new_data;
+ size_t nbits;
+ struct ATTRIB *b;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ const struct INDEX_NAMES *in = &s_index_names[indx->type];
+
+ b = ni_find_attr(ni, NULL, &le, ATTR_BITMAP, in->name, in->name_len,
+ NULL, NULL);
+
+ if (!b)
+ return -ENOENT;
+
+ if (!b->non_res) {
+ unsigned long pos;
+ const unsigned long *bm = resident_data(b);
+
+ nbits = (size_t)le32_to_cpu(b->res.data_size) * 8;
+
+ if (bit >= nbits)
+ return 0;
+
+ pos = find_next_bit(bm, nbits, bit);
+ if (pos < nbits)
+ return 0;
+ } else {
+ size_t used = MINUS_ONE_T;
+
+ nbits = le64_to_cpu(b->nres.data_size) * 8;
+
+ if (bit >= nbits)
+ return 0;
+
+ err = scan_nres_bitmap(ni, b, indx, bit, &scan_for_used, &used);
+ if (err)
+ return err;
+
+ if (used != MINUS_ONE_T)
+ return 0;
+ }
+
+ new_data = (u64)bit << indx->index_bits;
+
+ err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len,
+ &indx->alloc_run, new_data, &new_data, false, NULL);
+ if (err)
+ return err;
+
+ bpb = bitmap_size(bit);
+ if (bpb * 8 == nbits)
+ return 0;
+
+ err = attr_set_size(ni, ATTR_BITMAP, in->name, in->name_len,
+ &indx->bitmap_run, bpb, &bpb, false, NULL);
+
+ return err;
+}
+
+static int indx_free_children(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct NTFS_DE *e, bool trim)
+{
+ int err;
+ struct indx_node *n;
+ struct INDEX_HDR *hdr;
+ CLST vbn = de_get_vbn(e);
+ size_t i;
+
+ err = indx_read(indx, ni, vbn, &n);
+ if (err)
+ return err;
+
+ hdr = &n->index->ihdr;
+ /* First, recurse into the children, if any. */
+ if (hdr_has_subnode(hdr)) {
+ for (e = hdr_first_de(hdr); e; e = hdr_next_de(hdr, e)) {
+ indx_free_children(indx, ni, e, false);
+ if (de_is_last(e))
+ break;
+ }
+ }
+
+ put_indx_node(n);
+
+ i = vbn >> indx->idx2vbn_bits;
+ /*
+ * We've gotten rid of the children; add this buffer to the free list.
+ */
+ indx_mark_free(indx, ni, i);
+
+ if (!trim)
+ return 0;
+
+ /*
+ * If there are no used indexes after current free index
+ * then we can truncate allocation and bitmap.
+ * Use bitmap to estimate the case.
+ */
+ indx_shrink(indx, ni, i + 1);
+ return 0;
+}
+
+/*
+ * indx_get_entry_to_replace
+ *
+ * Find a replacement entry for a deleted entry.
+ * Always returns a node entry:
+ * NTFS_IE_HAS_SUBNODES is set the flags and the size includes the sub_vcn.
+ */
+static int indx_get_entry_to_replace(struct ntfs_index *indx,
+ struct ntfs_inode *ni,
+ const struct NTFS_DE *de_next,
+ struct NTFS_DE **de_to_replace,
+ struct ntfs_fnd *fnd)
+{
+ int err;
+ int level = -1;
+ CLST vbn;
+ struct NTFS_DE *e, *te, *re;
+ struct indx_node *n;
+ struct INDEX_BUFFER *ib;
+
+ *de_to_replace = NULL;
+
+ /* Find first leaf entry down from de_next. */
+ vbn = de_get_vbn(de_next);
+ for (;;) {
+ n = NULL;
+ err = indx_read(indx, ni, vbn, &n);
+ if (err)
+ goto out;
+
+ e = hdr_first_de(&n->index->ihdr);
+ fnd_push(fnd, n, e);
+
+ if (!de_is_last(e)) {
+ /*
+ * This buffer is non-empty, so its first entry
+ * could be used as the replacement entry.
+ */
+ level = fnd->level - 1;
+ }
+
+ if (!de_has_vcn(e))
+ break;
+
+ /* This buffer is a node. Continue to go down. */
+ vbn = de_get_vbn(e);
+ }
+
+ if (level == -1)
+ goto out;
+
+ n = fnd->nodes[level];
+ te = hdr_first_de(&n->index->ihdr);
+ /* Copy the candidate entry into the replacement entry buffer. */
+ re = kmalloc(le16_to_cpu(te->size) + sizeof(u64), GFP_NOFS);
+ if (!re) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ *de_to_replace = re;
+ memcpy(re, te, le16_to_cpu(te->size));
+
+ if (!de_has_vcn(re)) {
+ /*
+ * The replacement entry we found doesn't have a sub_vcn.
+ * increase its size to hold one.
+ */
+ le16_add_cpu(&re->size, sizeof(u64));
+ re->flags |= NTFS_IE_HAS_SUBNODES;
+ } else {
+ /*
+ * The replacement entry we found was a node entry, which
+ * means that all its child buffers are empty. Return them
+ * to the free pool.
+ */
+ indx_free_children(indx, ni, te, true);
+ }
+
+ /*
+ * Expunge the replacement entry from its former location,
+ * and then write that buffer.
+ */
+ ib = n->index;
+ e = hdr_delete_de(&ib->ihdr, te);
+
+ fnd->de[level] = e;
+ indx_write(indx, ni, n, 0);
+
+ /* Check to see if this action created an empty leaf. */
+ if (ib_is_leaf(ib) && ib_is_empty(ib))
+ return 0;
+
+out:
+ fnd_clear(fnd);
+ return err;
+}
+
+/*
+ * indx_delete_entry - Delete an entry from the index.
+ */
+int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const void *key, u32 key_len, const void *ctx)
+{
+ int err, diff;
+ struct INDEX_ROOT *root;
+ struct INDEX_HDR *hdr;
+ struct ntfs_fnd *fnd, *fnd2;
+ struct INDEX_BUFFER *ib;
+ struct NTFS_DE *e, *re, *next, *prev, *me;
+ struct indx_node *n, *n2d = NULL;
+ __le64 sub_vbn;
+ int level, level2;
+ struct ATTRIB *attr;
+ struct mft_inode *mi;
+ u32 e_size, root_size, new_root_size;
+ size_t trim_bit;
+ const struct INDEX_NAMES *in;
+
+ fnd = fnd_get();
+ if (!fnd) {
+ err = -ENOMEM;
+ goto out2;
+ }
+
+ fnd2 = fnd_get();
+ if (!fnd2) {
+ err = -ENOMEM;
+ goto out1;
+ }
+
+ root = indx_get_root(indx, ni, &attr, &mi);
+ if (!root) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Locate the entry to remove. */
+ err = indx_find(indx, ni, root, key, key_len, ctx, &diff, &e, fnd);
+ if (err)
+ goto out;
+
+ if (!e || diff) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ level = fnd->level;
+
+ if (level) {
+ n = fnd->nodes[level - 1];
+ e = fnd->de[level - 1];
+ ib = n->index;
+ hdr = &ib->ihdr;
+ } else {
+ hdr = &root->ihdr;
+ e = fnd->root_de;
+ n = NULL;
+ }
+
+ e_size = le16_to_cpu(e->size);
+
+ if (!de_has_vcn_ex(e)) {
+ /* The entry to delete is a leaf, so we can just rip it out. */
+ hdr_delete_de(hdr, e);
+
+ if (!level) {
+ hdr->total = hdr->used;
+
+ /* Shrink resident root attribute. */
+ mi_resize_attr(mi, attr, 0 - e_size);
+ goto out;
+ }
+
+ indx_write(indx, ni, n, 0);
+
+ /*
+ * Check to see if removing that entry made
+ * the leaf empty.
+ */
+ if (ib_is_leaf(ib) && ib_is_empty(ib)) {
+ fnd_pop(fnd);
+ fnd_push(fnd2, n, e);
+ }
+ } else {
+ /*
+ * The entry we wish to delete is a node buffer, so we
+ * have to find a replacement for it.
+ */
+ next = de_get_next(e);
+
+ err = indx_get_entry_to_replace(indx, ni, next, &re, fnd2);
+ if (err)
+ goto out;
+
+ if (re) {
+ de_set_vbn_le(re, de_get_vbn_le(e));
+ hdr_delete_de(hdr, e);
+
+ err = level ? indx_insert_into_buffer(indx, ni, root,
+ re, ctx,
+ fnd->level - 1,
+ fnd)
+ : indx_insert_into_root(indx, ni, re, e,
+ ctx, fnd, 0);
+ kfree(re);
+
+ if (err)
+ goto out;
+ } else {
+ /*
+ * There is no replacement for the current entry.
+ * This means that the subtree rooted at its node
+ * is empty, and can be deleted, which turn means
+ * that the node can just inherit the deleted
+ * entry sub_vcn.
+ */
+ indx_free_children(indx, ni, next, true);
+
+ de_set_vbn_le(next, de_get_vbn_le(e));
+ hdr_delete_de(hdr, e);
+ if (level) {
+ indx_write(indx, ni, n, 0);
+ } else {
+ hdr->total = hdr->used;
+
+ /* Shrink resident root attribute. */
+ mi_resize_attr(mi, attr, 0 - e_size);
+ }
+ }
+ }
+
+ /* Delete a branch of tree. */
+ if (!fnd2 || !fnd2->level)
+ goto out;
+
+ /* Reinit root 'cause it can be changed. */
+ root = indx_get_root(indx, ni, &attr, &mi);
+ if (!root) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ n2d = NULL;
+ sub_vbn = fnd2->nodes[0]->index->vbn;
+ level2 = 0;
+ level = fnd->level;
+
+ hdr = level ? &fnd->nodes[level - 1]->index->ihdr : &root->ihdr;
+
+ /* Scan current level. */
+ for (e = hdr_first_de(hdr);; e = hdr_next_de(hdr, e)) {
+ if (!e) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (de_has_vcn(e) && sub_vbn == de_get_vbn_le(e))
+ break;
+
+ if (de_is_last(e)) {
+ e = NULL;
+ break;
+ }
+ }
+
+ if (!e) {
+ /* Do slow search from root. */
+ struct indx_node *in;
+
+ fnd_clear(fnd);
+
+ in = indx_find_buffer(indx, ni, root, sub_vbn, NULL);
+ if (IS_ERR(in)) {
+ err = PTR_ERR(in);
+ goto out;
+ }
+
+ if (in)
+ fnd_push(fnd, in, NULL);
+ }
+
+ /* Merge fnd2 -> fnd. */
+ for (level = 0; level < fnd2->level; level++) {
+ fnd_push(fnd, fnd2->nodes[level], fnd2->de[level]);
+ fnd2->nodes[level] = NULL;
+ }
+ fnd2->level = 0;
+
+ hdr = NULL;
+ for (level = fnd->level; level; level--) {
+ struct indx_node *in = fnd->nodes[level - 1];
+
+ ib = in->index;
+ if (ib_is_empty(ib)) {
+ sub_vbn = ib->vbn;
+ } else {
+ hdr = &ib->ihdr;
+ n2d = in;
+ level2 = level;
+ break;
+ }
+ }
+
+ if (!hdr)
+ hdr = &root->ihdr;
+
+ e = hdr_first_de(hdr);
+ if (!e) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (hdr != &root->ihdr || !de_is_last(e)) {
+ prev = NULL;
+ while (!de_is_last(e)) {
+ if (de_has_vcn(e) && sub_vbn == de_get_vbn_le(e))
+ break;
+ prev = e;
+ e = hdr_next_de(hdr, e);
+ if (!e) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ if (sub_vbn != de_get_vbn_le(e)) {
+ /*
+ * Didn't find the parent entry, although this buffer
+ * is the parent trail. Something is corrupt.
+ */
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (de_is_last(e)) {
+ /*
+ * Since we can't remove the end entry, we'll remove
+ * its predecessor instead. This means we have to
+ * transfer the predecessor's sub_vcn to the end entry.
+ * Note: This index block is not empty, so the
+ * predecessor must exist.
+ */
+ if (!prev) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (de_has_vcn(prev)) {
+ de_set_vbn_le(e, de_get_vbn_le(prev));
+ } else if (de_has_vcn(e)) {
+ le16_sub_cpu(&e->size, sizeof(u64));
+ e->flags &= ~NTFS_IE_HAS_SUBNODES;
+ le32_sub_cpu(&hdr->used, sizeof(u64));
+ }
+ e = prev;
+ }
+
+ /*
+ * Copy the current entry into a temporary buffer (stripping
+ * off its down-pointer, if any) and delete it from the current
+ * buffer or root, as appropriate.
+ */
+ e_size = le16_to_cpu(e->size);
+ me = kmemdup(e, e_size, GFP_NOFS);
+ if (!me) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ if (de_has_vcn(me)) {
+ me->flags &= ~NTFS_IE_HAS_SUBNODES;
+ le16_sub_cpu(&me->size, sizeof(u64));
+ }
+
+ hdr_delete_de(hdr, e);
+
+ if (hdr == &root->ihdr) {
+ level = 0;
+ hdr->total = hdr->used;
+
+ /* Shrink resident root attribute. */
+ mi_resize_attr(mi, attr, 0 - e_size);
+ } else {
+ indx_write(indx, ni, n2d, 0);
+ level = level2;
+ }
+
+ /* Mark unused buffers as free. */
+ trim_bit = -1;
+ for (; level < fnd->level; level++) {
+ ib = fnd->nodes[level]->index;
+ if (ib_is_empty(ib)) {
+ size_t k = le64_to_cpu(ib->vbn) >>
+ indx->idx2vbn_bits;
+
+ indx_mark_free(indx, ni, k);
+ if (k < trim_bit)
+ trim_bit = k;
+ }
+ }
+
+ fnd_clear(fnd);
+ /*fnd->root_de = NULL;*/
+
+ /*
+ * Re-insert the entry into the tree.
+ * Find the spot the tree where we want to insert the new entry.
+ */
+ err = indx_insert_entry(indx, ni, me, ctx, fnd, 0);
+ kfree(me);
+ if (err)
+ goto out;
+
+ if (trim_bit != -1)
+ indx_shrink(indx, ni, trim_bit);
+ } else {
+ /*
+ * This tree needs to be collapsed down to an empty root.
+ * Recreate the index root as an empty leaf and free all
+ * the bits the index allocation bitmap.
+ */
+ fnd_clear(fnd);
+ fnd_clear(fnd2);
+
+ in = &s_index_names[indx->type];
+
+ err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len,
+ &indx->alloc_run, 0, NULL, false, NULL);
+ err = ni_remove_attr(ni, ATTR_ALLOC, in->name, in->name_len,
+ false, NULL);
+ run_close(&indx->alloc_run);
+
+ err = attr_set_size(ni, ATTR_BITMAP, in->name, in->name_len,
+ &indx->bitmap_run, 0, NULL, false, NULL);
+ err = ni_remove_attr(ni, ATTR_BITMAP, in->name, in->name_len,
+ false, NULL);
+ run_close(&indx->bitmap_run);
+
+ root = indx_get_root(indx, ni, &attr, &mi);
+ if (!root) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ root_size = le32_to_cpu(attr->res.data_size);
+ new_root_size =
+ sizeof(struct INDEX_ROOT) + sizeof(struct NTFS_DE);
+
+ if (new_root_size != root_size &&
+ !mi_resize_attr(mi, attr, new_root_size - root_size)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Fill first entry. */
+ e = (struct NTFS_DE *)(root + 1);
+ e->ref.low = 0;
+ e->ref.high = 0;
+ e->ref.seq = 0;
+ e->size = cpu_to_le16(sizeof(struct NTFS_DE));
+ e->flags = NTFS_IE_LAST; // 0x02
+ e->key_size = 0;
+ e->res = 0;
+
+ hdr = &root->ihdr;
+ hdr->flags = 0;
+ hdr->used = hdr->total = cpu_to_le32(
+ new_root_size - offsetof(struct INDEX_ROOT, ihdr));
+ mi->dirty = true;
+ }
+
+out:
+ fnd_put(fnd2);
+out1:
+ fnd_put(fnd);
+out2:
+ return err;
+}
+
+/*
+ * Update duplicated information in directory entry
+ * 'dup' - info from MFT record
+ */
+int indx_update_dup(struct ntfs_inode *ni, struct ntfs_sb_info *sbi,
+ const struct ATTR_FILE_NAME *fname,
+ const struct NTFS_DUP_INFO *dup, int sync)
+{
+ int err, diff;
+ struct NTFS_DE *e = NULL;
+ struct ATTR_FILE_NAME *e_fname;
+ struct ntfs_fnd *fnd;
+ struct INDEX_ROOT *root;
+ struct mft_inode *mi;
+ struct ntfs_index *indx = &ni->dir;
+
+ fnd = fnd_get();
+ if (!fnd)
+ return -ENOMEM;
+
+ root = indx_get_root(indx, ni, NULL, &mi);
+ if (!root) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Find entry in directory. */
+ err = indx_find(indx, ni, root, fname, fname_full_size(fname), sbi,
+ &diff, &e, fnd);
+ if (err)
+ goto out;
+
+ if (!e) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (diff) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ e_fname = (struct ATTR_FILE_NAME *)(e + 1);
+
+ if (!memcmp(&e_fname->dup, dup, sizeof(*dup))) {
+ /*
+ * Nothing to update in index! Try to avoid this call.
+ */
+ goto out;
+ }
+
+ memcpy(&e_fname->dup, dup, sizeof(*dup));
+
+ if (fnd->level) {
+ /* Directory entry in index. */
+ err = indx_write(indx, ni, fnd->nodes[fnd->level - 1], sync);
+ } else {
+ /* Directory entry in directory MFT record. */
+ mi->dirty = true;
+ if (sync)
+ err = mi_write(mi, 1);
+ else
+ mark_inode_dirty(&ni->vfs_inode);
+ }
+
+out:
+ fnd_put(fnd);
+ return err;
+}
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
new file mode 100644
index 000000000000..db2a5a4c38e4
--- /dev/null
+++ b/fs/ntfs3/inode.c
@@ -0,0 +1,1957 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/iversion.h>
+#include <linux/mpage.h>
+#include <linux/namei.h>
+#include <linux/nls.h>
+#include <linux/uio.h>
+#include <linux/writeback.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+/*
+ * ntfs_read_mft - Read record and parses MFT.
+ */
+static struct inode *ntfs_read_mft(struct inode *inode,
+ const struct cpu_str *name,
+ const struct MFT_REF *ref)
+{
+ int err = 0;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ mode_t mode = 0;
+ struct ATTR_STD_INFO5 *std5 = NULL;
+ struct ATTR_LIST_ENTRY *le;
+ struct ATTRIB *attr;
+ bool is_match = false;
+ bool is_root = false;
+ bool is_dir;
+ unsigned long ino = inode->i_ino;
+ u32 rp_fa = 0, asize, t32;
+ u16 roff, rsize, names = 0;
+ const struct ATTR_FILE_NAME *fname = NULL;
+ const struct INDEX_ROOT *root;
+ struct REPARSE_DATA_BUFFER rp; // 0x18 bytes
+ u64 t64;
+ struct MFT_REC *rec;
+ struct runs_tree *run;
+
+ inode->i_op = NULL;
+ /* Setup 'uid' and 'gid' */
+ inode->i_uid = sbi->options.fs_uid;
+ inode->i_gid = sbi->options.fs_gid;
+
+ err = mi_init(&ni->mi, sbi, ino);
+ if (err)
+ goto out;
+
+ if (!sbi->mft.ni && ino == MFT_REC_MFT && !sb->s_root) {
+ t64 = sbi->mft.lbo >> sbi->cluster_bits;
+ t32 = bytes_to_cluster(sbi, MFT_REC_VOL * sbi->record_size);
+ sbi->mft.ni = ni;
+ init_rwsem(&ni->file.run_lock);
+
+ if (!run_add_entry(&ni->file.run, 0, t64, t32, true)) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
+
+ err = mi_read(&ni->mi, ino == MFT_REC_MFT);
+
+ if (err)
+ goto out;
+
+ rec = ni->mi.mrec;
+
+ if (sbi->flags & NTFS_FLAGS_LOG_REPLAYING) {
+ ;
+ } else if (ref->seq != rec->seq) {
+ err = -EINVAL;
+ ntfs_err(sb, "MFT: r=%lx, expect seq=%x instead of %x!", ino,
+ le16_to_cpu(ref->seq), le16_to_cpu(rec->seq));
+ goto out;
+ } else if (!is_rec_inuse(rec)) {
+ err = -EINVAL;
+ ntfs_err(sb, "Inode r=%x is not in use!", (u32)ino);
+ goto out;
+ }
+
+ if (le32_to_cpu(rec->total) != sbi->record_size) {
+ /* Bad inode? */
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!is_rec_base(rec))
+ goto Ok;
+
+ /* Record should contain $I30 root. */
+ is_dir = rec->flags & RECORD_FLAG_DIR;
+
+ inode->i_generation = le16_to_cpu(rec->seq);
+
+ /* Enumerate all struct Attributes MFT. */
+ le = NULL;
+ attr = NULL;
+
+ /*
+ * To reduce tab pressure use goto instead of
+ * while( (attr = ni_enum_attr_ex(ni, attr, &le, NULL) ))
+ */
+next_attr:
+ run = NULL;
+ err = -EINVAL;
+ attr = ni_enum_attr_ex(ni, attr, &le, NULL);
+ if (!attr)
+ goto end_enum;
+
+ if (le && le->vcn) {
+ /* This is non primary attribute segment. Ignore if not MFT. */
+ if (ino != MFT_REC_MFT || attr->type != ATTR_DATA)
+ goto next_attr;
+
+ run = &ni->file.run;
+ asize = le32_to_cpu(attr->size);
+ goto attr_unpack_run;
+ }
+
+ roff = attr->non_res ? 0 : le16_to_cpu(attr->res.data_off);
+ rsize = attr->non_res ? 0 : le32_to_cpu(attr->res.data_size);
+ asize = le32_to_cpu(attr->size);
+
+ switch (attr->type) {
+ case ATTR_STD:
+ if (attr->non_res ||
+ asize < sizeof(struct ATTR_STD_INFO) + roff ||
+ rsize < sizeof(struct ATTR_STD_INFO))
+ goto out;
+
+ if (std5)
+ goto next_attr;
+
+ std5 = Add2Ptr(attr, roff);
+
+#ifdef STATX_BTIME
+ nt2kernel(std5->cr_time, &ni->i_crtime);
+#endif
+ nt2kernel(std5->a_time, &inode->i_atime);
+ nt2kernel(std5->c_time, &inode->i_ctime);
+ nt2kernel(std5->m_time, &inode->i_mtime);
+
+ ni->std_fa = std5->fa;
+
+ if (asize >= sizeof(struct ATTR_STD_INFO5) + roff &&
+ rsize >= sizeof(struct ATTR_STD_INFO5))
+ ni->std_security_id = std5->security_id;
+ goto next_attr;
+
+ case ATTR_LIST:
+ if (attr->name_len || le || ino == MFT_REC_LOG)
+ goto out;
+
+ err = ntfs_load_attr_list(ni, attr);
+ if (err)
+ goto out;
+
+ le = NULL;
+ attr = NULL;
+ goto next_attr;
+
+ case ATTR_NAME:
+ if (attr->non_res || asize < SIZEOF_ATTRIBUTE_FILENAME + roff ||
+ rsize < SIZEOF_ATTRIBUTE_FILENAME)
+ goto out;
+
+ fname = Add2Ptr(attr, roff);
+ if (fname->type == FILE_NAME_DOS)
+ goto next_attr;
+
+ names += 1;
+ if (name && name->len == fname->name_len &&
+ !ntfs_cmp_names_cpu(name, (struct le_str *)&fname->name_len,
+ NULL, false))
+ is_match = true;
+
+ goto next_attr;
+
+ case ATTR_DATA:
+ if (is_dir) {
+ /* Ignore data attribute in dir record. */
+ goto next_attr;
+ }
+
+ if (ino == MFT_REC_BADCLUST && !attr->non_res)
+ goto next_attr;
+
+ if (attr->name_len &&
+ ((ino != MFT_REC_BADCLUST || !attr->non_res ||
+ attr->name_len != ARRAY_SIZE(BAD_NAME) ||
+ memcmp(attr_name(attr), BAD_NAME, sizeof(BAD_NAME))) &&
+ (ino != MFT_REC_SECURE || !attr->non_res ||
+ attr->name_len != ARRAY_SIZE(SDS_NAME) ||
+ memcmp(attr_name(attr), SDS_NAME, sizeof(SDS_NAME))))) {
+ /* File contains stream attribute. Ignore it. */
+ goto next_attr;
+ }
+
+ if (is_attr_sparsed(attr))
+ ni->std_fa |= FILE_ATTRIBUTE_SPARSE_FILE;
+ else
+ ni->std_fa &= ~FILE_ATTRIBUTE_SPARSE_FILE;
+
+ if (is_attr_compressed(attr))
+ ni->std_fa |= FILE_ATTRIBUTE_COMPRESSED;
+ else
+ ni->std_fa &= ~FILE_ATTRIBUTE_COMPRESSED;
+
+ if (is_attr_encrypted(attr))
+ ni->std_fa |= FILE_ATTRIBUTE_ENCRYPTED;
+ else
+ ni->std_fa &= ~FILE_ATTRIBUTE_ENCRYPTED;
+
+ if (!attr->non_res) {
+ ni->i_valid = inode->i_size = rsize;
+ inode_set_bytes(inode, rsize);
+ t32 = asize;
+ } else {
+ t32 = le16_to_cpu(attr->nres.run_off);
+ }
+
+ mode = S_IFREG | (0777 & sbi->options.fs_fmask_inv);
+
+ if (!attr->non_res) {
+ ni->ni_flags |= NI_FLAG_RESIDENT;
+ goto next_attr;
+ }
+
+ inode_set_bytes(inode, attr_ondisk_size(attr));
+
+ ni->i_valid = le64_to_cpu(attr->nres.valid_size);
+ inode->i_size = le64_to_cpu(attr->nres.data_size);
+ if (!attr->nres.alloc_size)
+ goto next_attr;
+
+ run = ino == MFT_REC_BITMAP ? &sbi->used.bitmap.run
+ : &ni->file.run;
+ break;
+
+ case ATTR_ROOT:
+ if (attr->non_res)
+ goto out;
+
+ root = Add2Ptr(attr, roff);
+ is_root = true;
+
+ if (attr->name_len != ARRAY_SIZE(I30_NAME) ||
+ memcmp(attr_name(attr), I30_NAME, sizeof(I30_NAME)))
+ goto next_attr;
+
+ if (root->type != ATTR_NAME ||
+ root->rule != NTFS_COLLATION_TYPE_FILENAME)
+ goto out;
+
+ if (!is_dir)
+ goto next_attr;
+
+ ni->ni_flags |= NI_FLAG_DIR;
+
+ err = indx_init(&ni->dir, sbi, attr, INDEX_MUTEX_I30);
+ if (err)
+ goto out;
+
+ mode = sb->s_root
+ ? (S_IFDIR | (0777 & sbi->options.fs_dmask_inv))
+ : (S_IFDIR | 0777);
+ goto next_attr;
+
+ case ATTR_ALLOC:
+ if (!is_root || attr->name_len != ARRAY_SIZE(I30_NAME) ||
+ memcmp(attr_name(attr), I30_NAME, sizeof(I30_NAME)))
+ goto next_attr;
+
+ inode->i_size = le64_to_cpu(attr->nres.data_size);
+ ni->i_valid = le64_to_cpu(attr->nres.valid_size);
+ inode_set_bytes(inode, le64_to_cpu(attr->nres.alloc_size));
+
+ run = &ni->dir.alloc_run;
+ break;
+
+ case ATTR_BITMAP:
+ if (ino == MFT_REC_MFT) {
+ if (!attr->non_res)
+ goto out;
+#ifndef CONFIG_NTFS3_64BIT_CLUSTER
+ /* 0x20000000 = 2^32 / 8 */
+ if (le64_to_cpu(attr->nres.alloc_size) >= 0x20000000)
+ goto out;
+#endif
+ run = &sbi->mft.bitmap.run;
+ break;
+ } else if (is_dir && attr->name_len == ARRAY_SIZE(I30_NAME) &&
+ !memcmp(attr_name(attr), I30_NAME,
+ sizeof(I30_NAME)) &&
+ attr->non_res) {
+ run = &ni->dir.bitmap_run;
+ break;
+ }
+ goto next_attr;
+
+ case ATTR_REPARSE:
+ if (attr->name_len)
+ goto next_attr;
+
+ rp_fa = ni_parse_reparse(ni, attr, &rp);
+ switch (rp_fa) {
+ case REPARSE_LINK:
+ if (!attr->non_res) {
+ inode->i_size = rsize;
+ inode_set_bytes(inode, rsize);
+ t32 = asize;
+ } else {
+ inode->i_size =
+ le64_to_cpu(attr->nres.data_size);
+ t32 = le16_to_cpu(attr->nres.run_off);
+ }
+
+ /* Looks like normal symlink. */
+ ni->i_valid = inode->i_size;
+
+ /* Clear directory bit. */
+ if (ni->ni_flags & NI_FLAG_DIR) {
+ indx_clear(&ni->dir);
+ memset(&ni->dir, 0, sizeof(ni->dir));
+ ni->ni_flags &= ~NI_FLAG_DIR;
+ } else {
+ run_close(&ni->file.run);
+ }
+ mode = S_IFLNK | 0777;
+ is_dir = false;
+ if (attr->non_res) {
+ run = &ni->file.run;
+ goto attr_unpack_run; // Double break.
+ }
+ break;
+
+ case REPARSE_COMPRESSED:
+ break;
+
+ case REPARSE_DEDUPLICATED:
+ break;
+ }
+ goto next_attr;
+
+ case ATTR_EA_INFO:
+ if (!attr->name_len &&
+ resident_data_ex(attr, sizeof(struct EA_INFO))) {
+ ni->ni_flags |= NI_FLAG_EA;
+ /*
+ * ntfs_get_wsl_perm updates inode->i_uid, inode->i_gid, inode->i_mode
+ */
+ inode->i_mode = mode;
+ ntfs_get_wsl_perm(inode);
+ mode = inode->i_mode;
+ }
+ goto next_attr;
+
+ default:
+ goto next_attr;
+ }
+
+attr_unpack_run:
+ roff = le16_to_cpu(attr->nres.run_off);
+
+ t64 = le64_to_cpu(attr->nres.svcn);
+ err = run_unpack_ex(run, sbi, ino, t64, le64_to_cpu(attr->nres.evcn),
+ t64, Add2Ptr(attr, roff), asize - roff);
+ if (err < 0)
+ goto out;
+ err = 0;
+ goto next_attr;
+
+end_enum:
+
+ if (!std5)
+ goto out;
+
+ if (!is_match && name) {
+ /* Reuse rec as buffer for ascii name. */
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (std5->fa & FILE_ATTRIBUTE_READONLY)
+ mode &= ~0222;
+
+ if (!names) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (names != le16_to_cpu(rec->hard_links)) {
+ /* Correct minor error on the fly. Do not mark inode as dirty. */
+ rec->hard_links = cpu_to_le16(names);
+ ni->mi.dirty = true;
+ }
+
+ set_nlink(inode, names);
+
+ if (S_ISDIR(mode)) {
+ ni->std_fa |= FILE_ATTRIBUTE_DIRECTORY;
+
+ /*
+ * Dot and dot-dot should be included in count but was not
+ * included in enumeration.
+ * Usually a hard links to directories are disabled.
+ */
+ inode->i_op = &ntfs_dir_inode_operations;
+ inode->i_fop = &ntfs_dir_operations;
+ ni->i_valid = 0;
+ } else if (S_ISLNK(mode)) {
+ ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
+ inode->i_op = &ntfs_link_inode_operations;
+ inode->i_fop = NULL;
+ inode_nohighmem(inode); // ??
+ } else if (S_ISREG(mode)) {
+ ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
+ inode->i_op = &ntfs_file_inode_operations;
+ inode->i_fop = &ntfs_file_operations;
+ inode->i_mapping->a_ops =
+ is_compressed(ni) ? &ntfs_aops_cmpr : &ntfs_aops;
+ if (ino != MFT_REC_MFT)
+ init_rwsem(&ni->file.run_lock);
+ } else if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) ||
+ S_ISSOCK(mode)) {
+ inode->i_op = &ntfs_special_inode_operations;
+ init_special_inode(inode, mode, inode->i_rdev);
+ } else if (fname && fname->home.low == cpu_to_le32(MFT_REC_EXTEND) &&
+ fname->home.seq == cpu_to_le16(MFT_REC_EXTEND)) {
+ /* Records in $Extend are not a files or general directories. */
+ } else {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if ((sbi->options.sys_immutable &&
+ (std5->fa & FILE_ATTRIBUTE_SYSTEM)) &&
+ !S_ISFIFO(mode) && !S_ISSOCK(mode) && !S_ISLNK(mode)) {
+ inode->i_flags |= S_IMMUTABLE;
+ } else {
+ inode->i_flags &= ~S_IMMUTABLE;
+ }
+
+ inode->i_mode = mode;
+ if (!(ni->ni_flags & NI_FLAG_EA)) {
+ /* If no xattr then no security (stored in xattr). */
+ inode->i_flags |= S_NOSEC;
+ }
+
+Ok:
+ if (ino == MFT_REC_MFT && !sb->s_root)
+ sbi->mft.ni = NULL;
+
+ unlock_new_inode(inode);
+
+ return inode;
+
+out:
+ if (ino == MFT_REC_MFT && !sb->s_root)
+ sbi->mft.ni = NULL;
+
+ iget_failed(inode);
+ return ERR_PTR(err);
+}
+
+/*
+ * ntfs_test_inode
+ *
+ * Return: 1 if match.
+ */
+static int ntfs_test_inode(struct inode *inode, void *data)
+{
+ struct MFT_REF *ref = data;
+
+ return ino_get(ref) == inode->i_ino;
+}
+
+static int ntfs_set_inode(struct inode *inode, void *data)
+{
+ const struct MFT_REF *ref = data;
+
+ inode->i_ino = ino_get(ref);
+ return 0;
+}
+
+struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref,
+ const struct cpu_str *name)
+{
+ struct inode *inode;
+
+ inode = iget5_locked(sb, ino_get(ref), ntfs_test_inode, ntfs_set_inode,
+ (void *)ref);
+ if (unlikely(!inode))
+ return ERR_PTR(-ENOMEM);
+
+ /* If this is a freshly allocated inode, need to read it now. */
+ if (inode->i_state & I_NEW)
+ inode = ntfs_read_mft(inode, name, ref);
+ else if (ref->seq != ntfs_i(inode)->mi.mrec->seq) {
+ /* Inode overlaps? */
+ make_bad_inode(inode);
+ }
+
+ return inode;
+}
+
+enum get_block_ctx {
+ GET_BLOCK_GENERAL = 0,
+ GET_BLOCK_WRITE_BEGIN = 1,
+ GET_BLOCK_DIRECT_IO_R = 2,
+ GET_BLOCK_DIRECT_IO_W = 3,
+ GET_BLOCK_BMAP = 4,
+};
+
+static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo,
+ struct buffer_head *bh, int create,
+ enum get_block_ctx ctx)
+{
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct page *page = bh->b_page;
+ u8 cluster_bits = sbi->cluster_bits;
+ u32 block_size = sb->s_blocksize;
+ u64 bytes, lbo, valid;
+ u32 off;
+ int err;
+ CLST vcn, lcn, len;
+ bool new;
+
+ /* Clear previous state. */
+ clear_buffer_new(bh);
+ clear_buffer_uptodate(bh);
+
+ /* Direct write uses 'create=0'. */
+ if (!create && vbo >= ni->i_valid) {
+ /* Out of valid. */
+ return 0;
+ }
+
+ if (vbo >= inode->i_size) {
+ /* Out of size. */
+ return 0;
+ }
+
+ if (is_resident(ni)) {
+ ni_lock(ni);
+ err = attr_data_read_resident(ni, page);
+ ni_unlock(ni);
+
+ if (!err)
+ set_buffer_uptodate(bh);
+ bh->b_size = block_size;
+ return err;
+ }
+
+ vcn = vbo >> cluster_bits;
+ off = vbo & sbi->cluster_mask;
+ new = false;
+
+ err = attr_data_get_block(ni, vcn, 1, &lcn, &len, create ? &new : NULL);
+ if (err)
+ goto out;
+
+ if (!len)
+ return 0;
+
+ bytes = ((u64)len << cluster_bits) - off;
+
+ if (lcn == SPARSE_LCN) {
+ if (!create) {
+ if (bh->b_size > bytes)
+ bh->b_size = bytes;
+ return 0;
+ }
+ WARN_ON(1);
+ }
+
+ if (new) {
+ set_buffer_new(bh);
+ if ((len << cluster_bits) > block_size)
+ ntfs_sparse_cluster(inode, page, vcn, len);
+ }
+
+ lbo = ((u64)lcn << cluster_bits) + off;
+
+ set_buffer_mapped(bh);
+ bh->b_bdev = sb->s_bdev;
+ bh->b_blocknr = lbo >> sb->s_blocksize_bits;
+
+ valid = ni->i_valid;
+
+ if (ctx == GET_BLOCK_DIRECT_IO_W) {
+ /* ntfs_direct_IO will update ni->i_valid. */
+ if (vbo >= valid)
+ set_buffer_new(bh);
+ } else if (create) {
+ /* Normal write. */
+ if (bytes > bh->b_size)
+ bytes = bh->b_size;
+
+ if (vbo >= valid)
+ set_buffer_new(bh);
+
+ if (vbo + bytes > valid) {
+ ni->i_valid = vbo + bytes;
+ mark_inode_dirty(inode);
+ }
+ } else if (vbo >= valid) {
+ /* Read out of valid data. */
+ /* Should never be here 'cause already checked. */
+ clear_buffer_mapped(bh);
+ } else if (vbo + bytes <= valid) {
+ /* Normal read. */
+ } else if (vbo + block_size <= valid) {
+ /* Normal short read. */
+ bytes = block_size;
+ } else {
+ /*
+ * Read across valid size: vbo < valid && valid < vbo + block_size
+ */
+ bytes = block_size;
+
+ if (page) {
+ u32 voff = valid - vbo;
+
+ bh->b_size = block_size;
+ off = vbo & (PAGE_SIZE - 1);
+ set_bh_page(bh, page, off);
+ ll_rw_block(REQ_OP_READ, 0, 1, &bh);
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ err = -EIO;
+ goto out;
+ }
+ zero_user_segment(page, off + voff, off + block_size);
+ }
+ }
+
+ if (bh->b_size > bytes)
+ bh->b_size = bytes;
+
+#ifndef __LP64__
+ if (ctx == GET_BLOCK_DIRECT_IO_W || ctx == GET_BLOCK_DIRECT_IO_R) {
+ static_assert(sizeof(size_t) < sizeof(loff_t));
+ if (bytes > 0x40000000u)
+ bh->b_size = 0x40000000u;
+ }
+#endif
+
+ return 0;
+
+out:
+ return err;
+}
+
+int ntfs_get_block(struct inode *inode, sector_t vbn,
+ struct buffer_head *bh_result, int create)
+{
+ return ntfs_get_block_vbo(inode, (u64)vbn << inode->i_blkbits,
+ bh_result, create, GET_BLOCK_GENERAL);
+}
+
+static int ntfs_get_block_bmap(struct inode *inode, sector_t vsn,
+ struct buffer_head *bh_result, int create)
+{
+ return ntfs_get_block_vbo(inode,
+ (u64)vsn << inode->i_sb->s_blocksize_bits,
+ bh_result, create, GET_BLOCK_BMAP);
+}
+
+static sector_t ntfs_bmap(struct address_space *mapping, sector_t block)
+{
+ return generic_block_bmap(mapping, block, ntfs_get_block_bmap);
+}
+
+static int ntfs_readpage(struct file *file, struct page *page)
+{
+ int err;
+ struct address_space *mapping = page->mapping;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ if (is_resident(ni)) {
+ ni_lock(ni);
+ err = attr_data_read_resident(ni, page);
+ ni_unlock(ni);
+ if (err != E_NTFS_NONRESIDENT) {
+ unlock_page(page);
+ return err;
+ }
+ }
+
+ if (is_compressed(ni)) {
+ ni_lock(ni);
+ err = ni_readpage_cmpr(ni, page);
+ ni_unlock(ni);
+ return err;
+ }
+
+ /* Normal + sparse files. */
+ return mpage_readpage(page, ntfs_get_block);
+}
+
+static void ntfs_readahead(struct readahead_control *rac)
+{
+ struct address_space *mapping = rac->mapping;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ u64 valid;
+ loff_t pos;
+
+ if (is_resident(ni)) {
+ /* No readahead for resident. */
+ return;
+ }
+
+ if (is_compressed(ni)) {
+ /* No readahead for compressed. */
+ return;
+ }
+
+ valid = ni->i_valid;
+ pos = readahead_pos(rac);
+
+ if (valid < i_size_read(inode) && pos <= valid &&
+ valid < pos + readahead_length(rac)) {
+ /* Range cross 'valid'. Read it page by page. */
+ return;
+ }
+
+ mpage_readahead(rac, ntfs_get_block);
+}
+
+static int ntfs_get_block_direct_IO_R(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
+{
+ return ntfs_get_block_vbo(inode, (u64)iblock << inode->i_blkbits,
+ bh_result, create, GET_BLOCK_DIRECT_IO_R);
+}
+
+static int ntfs_get_block_direct_IO_W(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
+{
+ return ntfs_get_block_vbo(inode, (u64)iblock << inode->i_blkbits,
+ bh_result, create, GET_BLOCK_DIRECT_IO_W);
+}
+
+static ssize_t ntfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
+{
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ loff_t vbo = iocb->ki_pos;
+ loff_t end;
+ int wr = iov_iter_rw(iter) & WRITE;
+ loff_t valid;
+ ssize_t ret;
+
+ if (is_resident(ni)) {
+ /* Switch to buffered write. */
+ ret = 0;
+ goto out;
+ }
+
+ ret = blockdev_direct_IO(iocb, inode, iter,
+ wr ? ntfs_get_block_direct_IO_W
+ : ntfs_get_block_direct_IO_R);
+
+ if (ret <= 0)
+ goto out;
+
+ end = vbo + ret;
+ valid = ni->i_valid;
+ if (wr) {
+ if (end > valid && !S_ISBLK(inode->i_mode)) {
+ ni->i_valid = end;
+ mark_inode_dirty(inode);
+ }
+ } else if (vbo < valid && valid < end) {
+ /* Fix page. */
+ iov_iter_revert(iter, end - valid);
+ iov_iter_zero(end - valid, iter);
+ }
+
+out:
+ return ret;
+}
+
+int ntfs_set_size(struct inode *inode, u64 new_size)
+{
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ int err;
+
+ /* Check for maximum file size. */
+ if (is_sparsed(ni) || is_compressed(ni)) {
+ if (new_size > sbi->maxbytes_sparse) {
+ err = -EFBIG;
+ goto out;
+ }
+ } else if (new_size > sbi->maxbytes) {
+ err = -EFBIG;
+ goto out;
+ }
+
+ ni_lock(ni);
+ down_write(&ni->file.run_lock);
+
+ err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size,
+ &ni->i_valid, true, NULL);
+
+ up_write(&ni->file.run_lock);
+ ni_unlock(ni);
+
+ mark_inode_dirty(inode);
+
+out:
+ return err;
+}
+
+static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+ struct address_space *mapping = page->mapping;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ int err;
+
+ if (is_resident(ni)) {
+ ni_lock(ni);
+ err = attr_data_write_resident(ni, page);
+ ni_unlock(ni);
+ if (err != E_NTFS_NONRESIDENT) {
+ unlock_page(page);
+ return err;
+ }
+ }
+
+ return block_write_full_page(page, ntfs_get_block, wbc);
+}
+
+static int ntfs_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+{
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ /* Redirect call to 'ntfs_writepage' for resident files. */
+ get_block_t *get_block = is_resident(ni) ? NULL : &ntfs_get_block;
+
+ return mpage_writepages(mapping, wbc, get_block);
+}
+
+static int ntfs_get_block_write_begin(struct inode *inode, sector_t vbn,
+ struct buffer_head *bh_result, int create)
+{
+ return ntfs_get_block_vbo(inode, (u64)vbn << inode->i_blkbits,
+ bh_result, create, GET_BLOCK_WRITE_BEGIN);
+}
+
+static int ntfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, u32 len, u32 flags, struct page **pagep,
+ void **fsdata)
+{
+ int err;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ *pagep = NULL;
+ if (is_resident(ni)) {
+ struct page *page = grab_cache_page_write_begin(
+ mapping, pos >> PAGE_SHIFT, flags);
+
+ if (!page) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ ni_lock(ni);
+ err = attr_data_read_resident(ni, page);
+ ni_unlock(ni);
+
+ if (!err) {
+ *pagep = page;
+ goto out;
+ }
+ unlock_page(page);
+ put_page(page);
+
+ if (err != E_NTFS_NONRESIDENT)
+ goto out;
+ }
+
+ err = block_write_begin(mapping, pos, len, flags, pagep,
+ ntfs_get_block_write_begin);
+
+out:
+ return err;
+}
+
+/*
+ * ntfs_write_end - Address_space_operations::write_end.
+ */
+static int ntfs_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, u32 len, u32 copied, struct page *page,
+ void *fsdata)
+
+{
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ u64 valid = ni->i_valid;
+ bool dirty = false;
+ int err;
+
+ if (is_resident(ni)) {
+ ni_lock(ni);
+ err = attr_data_write_resident(ni, page);
+ ni_unlock(ni);
+ if (!err) {
+ dirty = true;
+ /* Clear any buffers in page. */
+ if (page_has_buffers(page)) {
+ struct buffer_head *head, *bh;
+
+ bh = head = page_buffers(page);
+ do {
+ clear_buffer_dirty(bh);
+ clear_buffer_mapped(bh);
+ set_buffer_uptodate(bh);
+ } while (head != (bh = bh->b_this_page));
+ }
+ SetPageUptodate(page);
+ err = copied;
+ }
+ unlock_page(page);
+ put_page(page);
+ } else {
+ err = generic_write_end(file, mapping, pos, len, copied, page,
+ fsdata);
+ }
+
+ if (err >= 0) {
+ if (!(ni->std_fa & FILE_ATTRIBUTE_ARCHIVE)) {
+ inode->i_ctime = inode->i_mtime = current_time(inode);
+ ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE;
+ dirty = true;
+ }
+
+ if (valid != ni->i_valid) {
+ /* ni->i_valid is changed in ntfs_get_block_vbo. */
+ dirty = true;
+ }
+
+ if (dirty)
+ mark_inode_dirty(inode);
+ }
+
+ return err;
+}
+
+int reset_log_file(struct inode *inode)
+{
+ int err;
+ loff_t pos = 0;
+ u32 log_size = inode->i_size;
+ struct address_space *mapping = inode->i_mapping;
+
+ for (;;) {
+ u32 len;
+ void *kaddr;
+ struct page *page;
+
+ len = pos + PAGE_SIZE > log_size ? (log_size - pos) : PAGE_SIZE;
+
+ err = block_write_begin(mapping, pos, len, 0, &page,
+ ntfs_get_block_write_begin);
+ if (err)
+ goto out;
+
+ kaddr = kmap_atomic(page);
+ memset(kaddr, -1, len);
+ kunmap_atomic(kaddr);
+ flush_dcache_page(page);
+
+ err = block_write_end(NULL, mapping, pos, len, len, page, NULL);
+ if (err < 0)
+ goto out;
+ pos += len;
+
+ if (pos >= log_size)
+ break;
+ balance_dirty_pages_ratelimited(mapping);
+ }
+out:
+ mark_inode_dirty_sync(inode);
+
+ return err;
+}
+
+int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+ return _ni_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+}
+
+int ntfs_sync_inode(struct inode *inode)
+{
+ return _ni_write_inode(inode, 1);
+}
+
+/*
+ * writeback_inode - Helper function for ntfs_flush_inodes().
+ *
+ * This writes both the inode and the file data blocks, waiting
+ * for in flight data blocks before the start of the call. It
+ * does not wait for any io started during the call.
+ */
+static int writeback_inode(struct inode *inode)
+{
+ int ret = sync_inode_metadata(inode, 0);
+
+ if (!ret)
+ ret = filemap_fdatawrite(inode->i_mapping);
+ return ret;
+}
+
+/*
+ * ntfs_flush_inodes
+ *
+ * Write data and metadata corresponding to i1 and i2. The io is
+ * started but we do not wait for any of it to finish.
+ *
+ * filemap_flush() is used for the block device, so if there is a dirty
+ * page for a block already in flight, we will not wait and start the
+ * io over again.
+ */
+int ntfs_flush_inodes(struct super_block *sb, struct inode *i1,
+ struct inode *i2)
+{
+ int ret = 0;
+
+ if (i1)
+ ret = writeback_inode(i1);
+ if (!ret && i2)
+ ret = writeback_inode(i2);
+ if (!ret)
+ ret = filemap_flush(sb->s_bdev->bd_inode->i_mapping);
+ return ret;
+}
+
+int inode_write_data(struct inode *inode, const void *data, size_t bytes)
+{
+ pgoff_t idx;
+
+ /* Write non resident data. */
+ for (idx = 0; bytes; idx++) {
+ size_t op = bytes > PAGE_SIZE ? PAGE_SIZE : bytes;
+ struct page *page = ntfs_map_page(inode->i_mapping, idx);
+
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+
+ lock_page(page);
+ WARN_ON(!PageUptodate(page));
+ ClearPageUptodate(page);
+
+ memcpy(page_address(page), data, op);
+
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ unlock_page(page);
+
+ ntfs_unmap_page(page);
+
+ bytes -= op;
+ data = Add2Ptr(data, PAGE_SIZE);
+ }
+ return 0;
+}
+
+/*
+ * ntfs_reparse_bytes
+ *
+ * Number of bytes for REPARSE_DATA_BUFFER(IO_REPARSE_TAG_SYMLINK)
+ * for unicode string of @uni_len length.
+ */
+static inline u32 ntfs_reparse_bytes(u32 uni_len)
+{
+ /* Header + unicode string + decorated unicode string. */
+ return sizeof(short) * (2 * uni_len + 4) +
+ offsetof(struct REPARSE_DATA_BUFFER,
+ SymbolicLinkReparseBuffer.PathBuffer);
+}
+
+static struct REPARSE_DATA_BUFFER *
+ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname,
+ u32 size, u16 *nsize)
+{
+ int i, err;
+ struct REPARSE_DATA_BUFFER *rp;
+ __le16 *rp_name;
+ typeof(rp->SymbolicLinkReparseBuffer) *rs;
+
+ rp = kzalloc(ntfs_reparse_bytes(2 * size + 2), GFP_NOFS);
+ if (!rp)
+ return ERR_PTR(-ENOMEM);
+
+ rs = &rp->SymbolicLinkReparseBuffer;
+ rp_name = rs->PathBuffer;
+
+ /* Convert link name to UTF-16. */
+ err = ntfs_nls_to_utf16(sbi, symname, size,
+ (struct cpu_str *)(rp_name - 1), 2 * size,
+ UTF16_LITTLE_ENDIAN);
+ if (err < 0)
+ goto out;
+
+ /* err = the length of unicode name of symlink. */
+ *nsize = ntfs_reparse_bytes(err);
+
+ if (*nsize > sbi->reparse.max_size) {
+ err = -EFBIG;
+ goto out;
+ }
+
+ /* Translate Linux '/' into Windows '\'. */
+ for (i = 0; i < err; i++) {
+ if (rp_name[i] == cpu_to_le16('/'))
+ rp_name[i] = cpu_to_le16('\\');
+ }
+
+ rp->ReparseTag = IO_REPARSE_TAG_SYMLINK;
+ rp->ReparseDataLength =
+ cpu_to_le16(*nsize - offsetof(struct REPARSE_DATA_BUFFER,
+ SymbolicLinkReparseBuffer));
+
+ /* PrintName + SubstituteName. */
+ rs->SubstituteNameOffset = cpu_to_le16(sizeof(short) * err);
+ rs->SubstituteNameLength = cpu_to_le16(sizeof(short) * err + 8);
+ rs->PrintNameLength = rs->SubstituteNameOffset;
+
+ /*
+ * TODO: Use relative path if possible to allow Windows to
+ * parse this path.
+ * 0-absolute path 1- relative path (SYMLINK_FLAG_RELATIVE).
+ */
+ rs->Flags = 0;
+
+ memmove(rp_name + err + 4, rp_name, sizeof(short) * err);
+
+ /* Decorate SubstituteName. */
+ rp_name += err;
+ rp_name[0] = cpu_to_le16('\\');
+ rp_name[1] = cpu_to_le16('?');
+ rp_name[2] = cpu_to_le16('?');
+ rp_name[3] = cpu_to_le16('\\');
+
+ return rp;
+out:
+ kfree(rp);
+ return ERR_PTR(err);
+}
+
+struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
+ struct inode *dir, struct dentry *dentry,
+ const struct cpu_str *uni, umode_t mode,
+ dev_t dev, const char *symname, u32 size,
+ struct ntfs_fnd *fnd)
+{
+ int err;
+ struct super_block *sb = dir->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ const struct qstr *name = &dentry->d_name;
+ CLST ino = 0;
+ struct ntfs_inode *dir_ni = ntfs_i(dir);
+ struct ntfs_inode *ni = NULL;
+ struct inode *inode = NULL;
+ struct ATTRIB *attr;
+ struct ATTR_STD_INFO5 *std5;
+ struct ATTR_FILE_NAME *fname;
+ struct MFT_REC *rec;
+ u32 asize, dsize, sd_size;
+ enum FILE_ATTRIBUTE fa;
+ __le32 security_id = SECURITY_ID_INVALID;
+ CLST vcn;
+ const void *sd;
+ u16 t16, nsize = 0, aid = 0;
+ struct INDEX_ROOT *root, *dir_root;
+ struct NTFS_DE *e, *new_de = NULL;
+ struct REPARSE_DATA_BUFFER *rp = NULL;
+ bool rp_inserted = false;
+
+ dir_root = indx_get_root(&dir_ni->dir, dir_ni, NULL, NULL);
+ if (!dir_root)
+ return ERR_PTR(-EINVAL);
+
+ if (S_ISDIR(mode)) {
+ /* Use parent's directory attributes. */
+ fa = dir_ni->std_fa | FILE_ATTRIBUTE_DIRECTORY |
+ FILE_ATTRIBUTE_ARCHIVE;
+ /*
+ * By default child directory inherits parent attributes.
+ * Root directory is hidden + system.
+ * Make an exception for children in root.
+ */
+ if (dir->i_ino == MFT_REC_ROOT)
+ fa &= ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
+ } else if (S_ISLNK(mode)) {
+ /* It is good idea that link should be the same type (file/dir) as target */
+ fa = FILE_ATTRIBUTE_REPARSE_POINT;
+
+ /*
+ * Linux: there are dir/file/symlink and so on.
+ * NTFS: symlinks are "dir + reparse" or "file + reparse"
+ * It is good idea to create:
+ * dir + reparse if 'symname' points to directory
+ * or
+ * file + reparse if 'symname' points to file
+ * Unfortunately kern_path hangs if symname contains 'dir'.
+ */
+
+ /*
+ * struct path path;
+ *
+ * if (!kern_path(symname, LOOKUP_FOLLOW, &path)){
+ * struct inode *target = d_inode(path.dentry);
+ *
+ * if (S_ISDIR(target->i_mode))
+ * fa |= FILE_ATTRIBUTE_DIRECTORY;
+ * // if ( target->i_sb == sb ){
+ * // use relative path?
+ * // }
+ * path_put(&path);
+ * }
+ */
+ } else if (S_ISREG(mode)) {
+ if (sbi->options.sparse) {
+ /* Sparsed regular file, cause option 'sparse'. */
+ fa = FILE_ATTRIBUTE_SPARSE_FILE |
+ FILE_ATTRIBUTE_ARCHIVE;
+ } else if (dir_ni->std_fa & FILE_ATTRIBUTE_COMPRESSED) {
+ /* Compressed regular file, if parent is compressed. */
+ fa = FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ARCHIVE;
+ } else {
+ /* Regular file, default attributes. */
+ fa = FILE_ATTRIBUTE_ARCHIVE;
+ }
+ } else {
+ fa = FILE_ATTRIBUTE_ARCHIVE;
+ }
+
+ if (!(mode & 0222))
+ fa |= FILE_ATTRIBUTE_READONLY;
+
+ /* Allocate PATH_MAX bytes. */
+ new_de = __getname();
+ if (!new_de) {
+ err = -ENOMEM;
+ goto out1;
+ }
+
+ /* Mark rw ntfs as dirty. it will be cleared at umount. */
+ ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
+
+ /* Step 1: allocate and fill new mft record. */
+ err = ntfs_look_free_mft(sbi, &ino, false, NULL, NULL);
+ if (err)
+ goto out2;
+
+ ni = ntfs_new_inode(sbi, ino, fa & FILE_ATTRIBUTE_DIRECTORY);
+ if (IS_ERR(ni)) {
+ err = PTR_ERR(ni);
+ ni = NULL;
+ goto out3;
+ }
+ inode = &ni->vfs_inode;
+ inode_init_owner(mnt_userns, inode, dir, mode);
+ mode = inode->i_mode;
+
+ inode->i_atime = inode->i_mtime = inode->i_ctime = ni->i_crtime =
+ current_time(inode);
+
+ rec = ni->mi.mrec;
+ rec->hard_links = cpu_to_le16(1);
+ attr = Add2Ptr(rec, le16_to_cpu(rec->attr_off));
+
+ /* Get default security id. */
+ sd = s_default_security;
+ sd_size = sizeof(s_default_security);
+
+ if (is_ntfs3(sbi)) {
+ security_id = dir_ni->std_security_id;
+ if (le32_to_cpu(security_id) < SECURITY_ID_FIRST) {
+ security_id = sbi->security.def_security_id;
+
+ if (security_id == SECURITY_ID_INVALID &&
+ !ntfs_insert_security(sbi, sd, sd_size,
+ &security_id, NULL))
+ sbi->security.def_security_id = security_id;
+ }
+ }
+
+ /* Insert standard info. */
+ std5 = Add2Ptr(attr, SIZEOF_RESIDENT);
+
+ if (security_id == SECURITY_ID_INVALID) {
+ dsize = sizeof(struct ATTR_STD_INFO);
+ } else {
+ dsize = sizeof(struct ATTR_STD_INFO5);
+ std5->security_id = security_id;
+ ni->std_security_id = security_id;
+ }
+ asize = SIZEOF_RESIDENT + dsize;
+
+ attr->type = ATTR_STD;
+ attr->size = cpu_to_le32(asize);
+ attr->id = cpu_to_le16(aid++);
+ attr->res.data_off = SIZEOF_RESIDENT_LE;
+ attr->res.data_size = cpu_to_le32(dsize);
+
+ std5->cr_time = std5->m_time = std5->c_time = std5->a_time =
+ kernel2nt(&inode->i_atime);
+
+ ni->std_fa = fa;
+ std5->fa = fa;
+
+ attr = Add2Ptr(attr, asize);
+
+ /* Insert file name. */
+ err = fill_name_de(sbi, new_de, name, uni);
+ if (err)
+ goto out4;
+
+ mi_get_ref(&ni->mi, &new_de->ref);
+
+ fname = (struct ATTR_FILE_NAME *)(new_de + 1);
+ mi_get_ref(&dir_ni->mi, &fname->home);
+ fname->dup.cr_time = fname->dup.m_time = fname->dup.c_time =
+ fname->dup.a_time = std5->cr_time;
+ fname->dup.alloc_size = fname->dup.data_size = 0;
+ fname->dup.fa = std5->fa;
+ fname->dup.ea_size = fname->dup.reparse = 0;
+
+ dsize = le16_to_cpu(new_de->key_size);
+ asize = ALIGN(SIZEOF_RESIDENT + dsize, 8);
+
+ attr->type = ATTR_NAME;
+ attr->size = cpu_to_le32(asize);
+ attr->res.data_off = SIZEOF_RESIDENT_LE;
+ attr->res.flags = RESIDENT_FLAG_INDEXED;
+ attr->id = cpu_to_le16(aid++);
+ attr->res.data_size = cpu_to_le32(dsize);
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), fname, dsize);
+
+ attr = Add2Ptr(attr, asize);
+
+ if (security_id == SECURITY_ID_INVALID) {
+ /* Insert security attribute. */
+ asize = SIZEOF_RESIDENT + ALIGN(sd_size, 8);
+
+ attr->type = ATTR_SECURE;
+ attr->size = cpu_to_le32(asize);
+ attr->id = cpu_to_le16(aid++);
+ attr->res.data_off = SIZEOF_RESIDENT_LE;
+ attr->res.data_size = cpu_to_le32(sd_size);
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), sd, sd_size);
+
+ attr = Add2Ptr(attr, asize);
+ }
+
+ attr->id = cpu_to_le16(aid++);
+ if (fa & FILE_ATTRIBUTE_DIRECTORY) {
+ /*
+ * Regular directory or symlink to directory.
+ * Create root attribute.
+ */
+ dsize = sizeof(struct INDEX_ROOT) + sizeof(struct NTFS_DE);
+ asize = sizeof(I30_NAME) + SIZEOF_RESIDENT + dsize;
+
+ attr->type = ATTR_ROOT;
+ attr->size = cpu_to_le32(asize);
+
+ attr->name_len = ARRAY_SIZE(I30_NAME);
+ attr->name_off = SIZEOF_RESIDENT_LE;
+ attr->res.data_off =
+ cpu_to_le16(sizeof(I30_NAME) + SIZEOF_RESIDENT);
+ attr->res.data_size = cpu_to_le32(dsize);
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), I30_NAME,
+ sizeof(I30_NAME));
+
+ root = Add2Ptr(attr, sizeof(I30_NAME) + SIZEOF_RESIDENT);
+ memcpy(root, dir_root, offsetof(struct INDEX_ROOT, ihdr));
+ root->ihdr.de_off =
+ cpu_to_le32(sizeof(struct INDEX_HDR)); // 0x10
+ root->ihdr.used = cpu_to_le32(sizeof(struct INDEX_HDR) +
+ sizeof(struct NTFS_DE));
+ root->ihdr.total = root->ihdr.used;
+
+ e = Add2Ptr(root, sizeof(struct INDEX_ROOT));
+ e->size = cpu_to_le16(sizeof(struct NTFS_DE));
+ e->flags = NTFS_IE_LAST;
+ } else if (S_ISLNK(mode)) {
+ /*
+ * Symlink to file.
+ * Create empty resident data attribute.
+ */
+ asize = SIZEOF_RESIDENT;
+
+ /* Insert empty ATTR_DATA */
+ attr->type = ATTR_DATA;
+ attr->size = cpu_to_le32(SIZEOF_RESIDENT);
+ attr->name_off = SIZEOF_RESIDENT_LE;
+ attr->res.data_off = SIZEOF_RESIDENT_LE;
+ } else if (S_ISREG(mode)) {
+ /*
+ * Regular file. Create empty non resident data attribute.
+ */
+ attr->type = ATTR_DATA;
+ attr->non_res = 1;
+ attr->nres.evcn = cpu_to_le64(-1ll);
+ if (fa & FILE_ATTRIBUTE_SPARSE_FILE) {
+ attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8);
+ attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
+ attr->flags = ATTR_FLAG_SPARSED;
+ asize = SIZEOF_NONRESIDENT_EX + 8;
+ } else if (fa & FILE_ATTRIBUTE_COMPRESSED) {
+ attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8);
+ attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
+ attr->flags = ATTR_FLAG_COMPRESSED;
+ attr->nres.c_unit = COMPRESSION_UNIT;
+ asize = SIZEOF_NONRESIDENT_EX + 8;
+ } else {
+ attr->size = cpu_to_le32(SIZEOF_NONRESIDENT + 8);
+ attr->name_off = SIZEOF_NONRESIDENT_LE;
+ asize = SIZEOF_NONRESIDENT + 8;
+ }
+ attr->nres.run_off = attr->name_off;
+ } else {
+ /*
+ * Node. Create empty resident data attribute.
+ */
+ attr->type = ATTR_DATA;
+ attr->size = cpu_to_le32(SIZEOF_RESIDENT);
+ attr->name_off = SIZEOF_RESIDENT_LE;
+ if (fa & FILE_ATTRIBUTE_SPARSE_FILE)
+ attr->flags = ATTR_FLAG_SPARSED;
+ else if (fa & FILE_ATTRIBUTE_COMPRESSED)
+ attr->flags = ATTR_FLAG_COMPRESSED;
+ attr->res.data_off = SIZEOF_RESIDENT_LE;
+ asize = SIZEOF_RESIDENT;
+ ni->ni_flags |= NI_FLAG_RESIDENT;
+ }
+
+ if (S_ISDIR(mode)) {
+ ni->ni_flags |= NI_FLAG_DIR;
+ err = indx_init(&ni->dir, sbi, attr, INDEX_MUTEX_I30);
+ if (err)
+ goto out4;
+ } else if (S_ISLNK(mode)) {
+ rp = ntfs_create_reparse_buffer(sbi, symname, size, &nsize);
+
+ if (IS_ERR(rp)) {
+ err = PTR_ERR(rp);
+ rp = NULL;
+ goto out4;
+ }
+
+ /*
+ * Insert ATTR_REPARSE.
+ */
+ attr = Add2Ptr(attr, asize);
+ attr->type = ATTR_REPARSE;
+ attr->id = cpu_to_le16(aid++);
+
+ /* Resident or non resident? */
+ asize = ALIGN(SIZEOF_RESIDENT + nsize, 8);
+ t16 = PtrOffset(rec, attr);
+
+ /* 0x78 - the size of EA + EAINFO to store WSL */
+ if (asize + t16 + 0x78 + 8 > sbi->record_size) {
+ CLST alen;
+ CLST clst = bytes_to_cluster(sbi, nsize);
+
+ /* Bytes per runs. */
+ t16 = sbi->record_size - t16 - SIZEOF_NONRESIDENT;
+
+ attr->non_res = 1;
+ attr->nres.evcn = cpu_to_le64(clst - 1);
+ attr->name_off = SIZEOF_NONRESIDENT_LE;
+ attr->nres.run_off = attr->name_off;
+ attr->nres.data_size = cpu_to_le64(nsize);
+ attr->nres.valid_size = attr->nres.data_size;
+ attr->nres.alloc_size =
+ cpu_to_le64(ntfs_up_cluster(sbi, nsize));
+
+ err = attr_allocate_clusters(sbi, &ni->file.run, 0, 0,
+ clst, NULL, 0, &alen, 0,
+ NULL);
+ if (err)
+ goto out5;
+
+ err = run_pack(&ni->file.run, 0, clst,
+ Add2Ptr(attr, SIZEOF_NONRESIDENT), t16,
+ &vcn);
+ if (err < 0)
+ goto out5;
+
+ if (vcn != clst) {
+ err = -EINVAL;
+ goto out5;
+ }
+
+ asize = SIZEOF_NONRESIDENT + ALIGN(err, 8);
+ inode->i_size = nsize;
+ } else {
+ attr->res.data_off = SIZEOF_RESIDENT_LE;
+ attr->res.data_size = cpu_to_le32(nsize);
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), rp, nsize);
+ inode->i_size = nsize;
+ nsize = 0;
+ }
+
+ attr->size = cpu_to_le32(asize);
+
+ err = ntfs_insert_reparse(sbi, IO_REPARSE_TAG_SYMLINK,
+ &new_de->ref);
+ if (err)
+ goto out5;
+
+ rp_inserted = true;
+ }
+
+ attr = Add2Ptr(attr, asize);
+ attr->type = ATTR_END;
+
+ rec->used = cpu_to_le32(PtrOffset(rec, attr) + 8);
+ rec->next_attr_id = cpu_to_le16(aid);
+
+ /* Step 2: Add new name in index. */
+ err = indx_insert_entry(&dir_ni->dir, dir_ni, new_de, sbi, fnd, 0);
+ if (err)
+ goto out6;
+
+ inode->i_generation = le16_to_cpu(rec->seq);
+
+ dir->i_mtime = dir->i_ctime = inode->i_atime;
+
+ if (S_ISDIR(mode)) {
+ inode->i_op = &ntfs_dir_inode_operations;
+ inode->i_fop = &ntfs_dir_operations;
+ } else if (S_ISLNK(mode)) {
+ inode->i_op = &ntfs_link_inode_operations;
+ inode->i_fop = NULL;
+ inode->i_mapping->a_ops = &ntfs_aops;
+ } else if (S_ISREG(mode)) {
+ inode->i_op = &ntfs_file_inode_operations;
+ inode->i_fop = &ntfs_file_operations;
+ inode->i_mapping->a_ops =
+ is_compressed(ni) ? &ntfs_aops_cmpr : &ntfs_aops;
+ init_rwsem(&ni->file.run_lock);
+ } else {
+ inode->i_op = &ntfs_special_inode_operations;
+ init_special_inode(inode, mode, dev);
+ }
+
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+ if (!S_ISLNK(mode) && (sb->s_flags & SB_POSIXACL)) {
+ err = ntfs_init_acl(mnt_userns, inode, dir);
+ if (err)
+ goto out6;
+ } else
+#endif
+ {
+ inode->i_flags |= S_NOSEC;
+ }
+
+ /* Write non resident data. */
+ if (nsize) {
+ err = ntfs_sb_write_run(sbi, &ni->file.run, 0, rp, nsize);
+ if (err)
+ goto out7;
+ }
+
+ /*
+ * Call 'd_instantiate' after inode->i_op is set
+ * but before finish_open.
+ */
+ d_instantiate(dentry, inode);
+
+ ntfs_save_wsl_perm(inode);
+ mark_inode_dirty(dir);
+ mark_inode_dirty(inode);
+
+ /* Normal exit. */
+ goto out2;
+
+out7:
+
+ /* Undo 'indx_insert_entry'. */
+ indx_delete_entry(&dir_ni->dir, dir_ni, new_de + 1,
+ le16_to_cpu(new_de->key_size), sbi);
+out6:
+ if (rp_inserted)
+ ntfs_remove_reparse(sbi, IO_REPARSE_TAG_SYMLINK, &new_de->ref);
+
+out5:
+ if (S_ISDIR(mode) || run_is_empty(&ni->file.run))
+ goto out4;
+
+ run_deallocate(sbi, &ni->file.run, false);
+
+out4:
+ clear_rec_inuse(rec);
+ clear_nlink(inode);
+ ni->mi.dirty = false;
+ discard_new_inode(inode);
+out3:
+ ntfs_mark_rec_free(sbi, ino);
+
+out2:
+ __putname(new_de);
+ kfree(rp);
+
+out1:
+ if (err)
+ return ERR_PTR(err);
+
+ unlock_new_inode(inode);
+
+ return inode;
+}
+
+int ntfs_link_inode(struct inode *inode, struct dentry *dentry)
+{
+ int err;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
+ struct NTFS_DE *de;
+ struct ATTR_FILE_NAME *de_name;
+
+ /* Allocate PATH_MAX bytes. */
+ de = __getname();
+ if (!de)
+ return -ENOMEM;
+
+ /* Mark rw ntfs as dirty. It will be cleared at umount. */
+ ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
+
+ /* Construct 'de'. */
+ err = fill_name_de(sbi, de, &dentry->d_name, NULL);
+ if (err)
+ goto out;
+
+ de_name = (struct ATTR_FILE_NAME *)(de + 1);
+ /* Fill duplicate info. */
+ de_name->dup.cr_time = de_name->dup.m_time = de_name->dup.c_time =
+ de_name->dup.a_time = kernel2nt(&inode->i_ctime);
+ de_name->dup.alloc_size = de_name->dup.data_size =
+ cpu_to_le64(inode->i_size);
+ de_name->dup.fa = ni->std_fa;
+ de_name->dup.ea_size = de_name->dup.reparse = 0;
+
+ err = ni_add_name(ntfs_i(d_inode(dentry->d_parent)), ni, de);
+out:
+ __putname(de);
+ return err;
+}
+
+/*
+ * ntfs_unlink_inode
+ *
+ * inode_operations::unlink
+ * inode_operations::rmdir
+ */
+int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry)
+{
+ int err;
+ struct ntfs_sb_info *sbi = dir->i_sb->s_fs_info;
+ struct inode *inode = d_inode(dentry);
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct ntfs_inode *dir_ni = ntfs_i(dir);
+ struct NTFS_DE *de, *de2 = NULL;
+ int undo_remove;
+
+ if (ntfs_is_meta_file(sbi, ni->mi.rno))
+ return -EINVAL;
+
+ /* Allocate PATH_MAX bytes. */
+ de = __getname();
+ if (!de)
+ return -ENOMEM;
+
+ ni_lock(ni);
+
+ if (S_ISDIR(inode->i_mode) && !dir_is_empty(inode)) {
+ err = -ENOTEMPTY;
+ goto out;
+ }
+
+ err = fill_name_de(sbi, de, &dentry->d_name, NULL);
+ if (err < 0)
+ goto out;
+
+ undo_remove = 0;
+ err = ni_remove_name(dir_ni, ni, de, &de2, &undo_remove);
+
+ if (!err) {
+ drop_nlink(inode);
+ dir->i_mtime = dir->i_ctime = current_time(dir);
+ mark_inode_dirty(dir);
+ inode->i_ctime = dir->i_ctime;
+ if (inode->i_nlink)
+ mark_inode_dirty(inode);
+ } else if (!ni_remove_name_undo(dir_ni, ni, de, de2, undo_remove)) {
+ make_bad_inode(inode);
+ ntfs_inode_err(inode, "failed to undo unlink");
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+ } else {
+ if (ni_is_dirty(dir))
+ mark_inode_dirty(dir);
+ if (ni_is_dirty(inode))
+ mark_inode_dirty(inode);
+ }
+
+out:
+ ni_unlock(ni);
+ __putname(de);
+ return err;
+}
+
+void ntfs_evict_inode(struct inode *inode)
+{
+ truncate_inode_pages_final(&inode->i_data);
+
+ if (inode->i_nlink)
+ _ni_write_inode(inode, inode_needs_sync(inode));
+
+ invalidate_inode_buffers(inode);
+ clear_inode(inode);
+
+ ni_clear(ntfs_i(inode));
+}
+
+static noinline int ntfs_readlink_hlp(struct inode *inode, char *buffer,
+ int buflen)
+{
+ int i, err = 0;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ u64 i_size = inode->i_size;
+ u16 nlen = 0;
+ void *to_free = NULL;
+ struct REPARSE_DATA_BUFFER *rp;
+ struct le_str *uni;
+ struct ATTRIB *attr;
+
+ /* Reparse data present. Try to parse it. */
+ static_assert(!offsetof(struct REPARSE_DATA_BUFFER, ReparseTag));
+ static_assert(sizeof(u32) == sizeof(rp->ReparseTag));
+
+ *buffer = 0;
+
+ /* Read into temporal buffer. */
+ if (i_size > sbi->reparse.max_size || i_size <= sizeof(u32)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_REPARSE, NULL, 0, NULL, NULL);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!attr->non_res) {
+ rp = resident_data_ex(attr, i_size);
+ if (!rp) {
+ err = -EINVAL;
+ goto out;
+ }
+ } else {
+ rp = kmalloc(i_size, GFP_NOFS);
+ if (!rp) {
+ err = -ENOMEM;
+ goto out;
+ }
+ to_free = rp;
+ err = ntfs_read_run_nb(sbi, &ni->file.run, 0, rp, i_size, NULL);
+ if (err)
+ goto out;
+ }
+
+ err = -EINVAL;
+
+ /* Microsoft Tag. */
+ switch (rp->ReparseTag) {
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ /* Mount points and junctions. */
+ /* Can we use 'Rp->MountPointReparseBuffer.PrintNameLength'? */
+ if (i_size <= offsetof(struct REPARSE_DATA_BUFFER,
+ MountPointReparseBuffer.PathBuffer))
+ goto out;
+ uni = Add2Ptr(rp,
+ offsetof(struct REPARSE_DATA_BUFFER,
+ MountPointReparseBuffer.PathBuffer) +
+ le16_to_cpu(rp->MountPointReparseBuffer
+ .PrintNameOffset) -
+ 2);
+ nlen = le16_to_cpu(rp->MountPointReparseBuffer.PrintNameLength);
+ break;
+
+ case IO_REPARSE_TAG_SYMLINK:
+ /* FolderSymbolicLink */
+ /* Can we use 'Rp->SymbolicLinkReparseBuffer.PrintNameLength'? */
+ if (i_size <= offsetof(struct REPARSE_DATA_BUFFER,
+ SymbolicLinkReparseBuffer.PathBuffer))
+ goto out;
+ uni = Add2Ptr(rp,
+ offsetof(struct REPARSE_DATA_BUFFER,
+ SymbolicLinkReparseBuffer.PathBuffer) +
+ le16_to_cpu(rp->SymbolicLinkReparseBuffer
+ .PrintNameOffset) -
+ 2);
+ nlen = le16_to_cpu(
+ rp->SymbolicLinkReparseBuffer.PrintNameLength);
+ break;
+
+ case IO_REPARSE_TAG_CLOUD:
+ case IO_REPARSE_TAG_CLOUD_1:
+ case IO_REPARSE_TAG_CLOUD_2:
+ case IO_REPARSE_TAG_CLOUD_3:
+ case IO_REPARSE_TAG_CLOUD_4:
+ case IO_REPARSE_TAG_CLOUD_5:
+ case IO_REPARSE_TAG_CLOUD_6:
+ case IO_REPARSE_TAG_CLOUD_7:
+ case IO_REPARSE_TAG_CLOUD_8:
+ case IO_REPARSE_TAG_CLOUD_9:
+ case IO_REPARSE_TAG_CLOUD_A:
+ case IO_REPARSE_TAG_CLOUD_B:
+ case IO_REPARSE_TAG_CLOUD_C:
+ case IO_REPARSE_TAG_CLOUD_D:
+ case IO_REPARSE_TAG_CLOUD_E:
+ case IO_REPARSE_TAG_CLOUD_F:
+ err = sizeof("OneDrive") - 1;
+ if (err > buflen)
+ err = buflen;
+ memcpy(buffer, "OneDrive", err);
+ goto out;
+
+ default:
+ if (IsReparseTagMicrosoft(rp->ReparseTag)) {
+ /* Unknown Microsoft Tag. */
+ goto out;
+ }
+ if (!IsReparseTagNameSurrogate(rp->ReparseTag) ||
+ i_size <= sizeof(struct REPARSE_POINT)) {
+ goto out;
+ }
+
+ /* Users tag. */
+ uni = Add2Ptr(rp, sizeof(struct REPARSE_POINT) - 2);
+ nlen = le16_to_cpu(rp->ReparseDataLength) -
+ sizeof(struct REPARSE_POINT);
+ }
+
+ /* Convert nlen from bytes to UNICODE chars. */
+ nlen >>= 1;
+
+ /* Check that name is available. */
+ if (!nlen || &uni->name[nlen] > (__le16 *)Add2Ptr(rp, i_size))
+ goto out;
+
+ /* If name is already zero terminated then truncate it now. */
+ if (!uni->name[nlen - 1])
+ nlen -= 1;
+ uni->len = nlen;
+
+ err = ntfs_utf16_to_nls(sbi, uni, buffer, buflen);
+
+ if (err < 0)
+ goto out;
+
+ /* Translate Windows '\' into Linux '/'. */
+ for (i = 0; i < err; i++) {
+ if (buffer[i] == '\\')
+ buffer[i] = '/';
+ }
+
+ /* Always set last zero. */
+ buffer[err] = 0;
+out:
+ kfree(to_free);
+ return err;
+}
+
+static const char *ntfs_get_link(struct dentry *de, struct inode *inode,
+ struct delayed_call *done)
+{
+ int err;
+ char *ret;
+
+ if (!de)
+ return ERR_PTR(-ECHILD);
+
+ ret = kmalloc(PAGE_SIZE, GFP_NOFS);
+ if (!ret)
+ return ERR_PTR(-ENOMEM);
+
+ err = ntfs_readlink_hlp(inode, ret, PAGE_SIZE);
+ if (err < 0) {
+ kfree(ret);
+ return ERR_PTR(err);
+ }
+
+ set_delayed_call(done, kfree_link, ret);
+
+ return ret;
+}
+
+// clang-format off
+const struct inode_operations ntfs_link_inode_operations = {
+ .get_link = ntfs_get_link,
+ .setattr = ntfs3_setattr,
+ .listxattr = ntfs_listxattr,
+ .permission = ntfs_permission,
+ .get_acl = ntfs_get_acl,
+ .set_acl = ntfs_set_acl,
+};
+
+const struct address_space_operations ntfs_aops = {
+ .readpage = ntfs_readpage,
+ .readahead = ntfs_readahead,
+ .writepage = ntfs_writepage,
+ .writepages = ntfs_writepages,
+ .write_begin = ntfs_write_begin,
+ .write_end = ntfs_write_end,
+ .direct_IO = ntfs_direct_IO,
+ .bmap = ntfs_bmap,
+ .set_page_dirty = __set_page_dirty_buffers,
+};
+
+const struct address_space_operations ntfs_aops_cmpr = {
+ .readpage = ntfs_readpage,
+ .readahead = ntfs_readahead,
+};
+// clang-format on
diff --git a/fs/ntfs3/lib/decompress_common.c b/fs/ntfs3/lib/decompress_common.c
new file mode 100644
index 000000000000..e96652240859
--- /dev/null
+++ b/fs/ntfs3/lib/decompress_common.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * decompress_common.c - Code shared by the XPRESS and LZX decompressors
+ *
+ * Copyright (C) 2015 Eric Biggers
+ */
+
+#include "decompress_common.h"
+
+/*
+ * make_huffman_decode_table() -
+ *
+ * Build a decoding table for a canonical prefix code, or "Huffman code".
+ *
+ * This is an internal function, not part of the library API!
+ *
+ * This takes as input the length of the codeword for each symbol in the
+ * alphabet and produces as output a table that can be used for fast
+ * decoding of prefix-encoded symbols using read_huffsym().
+ *
+ * Strictly speaking, a canonical prefix code might not be a Huffman
+ * code. But this algorithm will work either way; and in fact, since
+ * Huffman codes are defined in terms of symbol frequencies, there is no
+ * way for the decompressor to know whether the code is a true Huffman
+ * code or not until all symbols have been decoded.
+ *
+ * Because the prefix code is assumed to be "canonical", it can be
+ * reconstructed directly from the codeword lengths. A prefix code is
+ * canonical if and only if a longer codeword never lexicographically
+ * precedes a shorter codeword, and the lexicographic ordering of
+ * codewords of the same length is the same as the lexicographic ordering
+ * of the corresponding symbols. Consequently, we can sort the symbols
+ * primarily by codeword length and secondarily by symbol value, then
+ * reconstruct the prefix code by generating codewords lexicographically
+ * in that order.
+ *
+ * This function does not, however, generate the prefix code explicitly.
+ * Instead, it directly builds a table for decoding symbols using the
+ * code. The basic idea is this: given the next 'max_codeword_len' bits
+ * in the input, we can look up the decoded symbol by indexing a table
+ * containing 2**max_codeword_len entries. A codeword with length
+ * 'max_codeword_len' will have exactly one entry in this table, whereas
+ * a codeword shorter than 'max_codeword_len' will have multiple entries
+ * in this table. Precisely, a codeword of length n will be represented
+ * by 2**(max_codeword_len - n) entries in this table. The 0-based index
+ * of each such entry will contain the corresponding codeword as a prefix
+ * when zero-padded on the left to 'max_codeword_len' binary digits.
+ *
+ * That's the basic idea, but we implement two optimizations regarding
+ * the format of the decode table itself:
+ *
+ * - For many compression formats, the maximum codeword length is too
+ * long for it to be efficient to build the full decoding table
+ * whenever a new prefix code is used. Instead, we can build the table
+ * using only 2**table_bits entries, where 'table_bits' is some number
+ * less than or equal to 'max_codeword_len'. Then, only codewords of
+ * length 'table_bits' and shorter can be directly looked up. For
+ * longer codewords, the direct lookup instead produces the root of a
+ * binary tree. Using this tree, the decoder can do traditional
+ * bit-by-bit decoding of the remainder of the codeword. Child nodes
+ * are allocated in extra entries at the end of the table; leaf nodes
+ * contain symbols. Note that the long-codeword case is, in general,
+ * not performance critical, since in Huffman codes the most frequently
+ * used symbols are assigned the shortest codeword lengths.
+ *
+ * - When we decode a symbol using a direct lookup of the table, we still
+ * need to know its length so that the bitstream can be advanced by the
+ * appropriate number of bits. The simple solution is to simply retain
+ * the 'lens' array and use the decoded symbol as an index into it.
+ * However, this requires two separate array accesses in the fast path.
+ * The optimization is to store the length directly in the decode
+ * table. We use the bottom 11 bits for the symbol and the top 5 bits
+ * for the length. In addition, to combine this optimization with the
+ * previous one, we introduce a special case where the top 2 bits of
+ * the length are both set if the entry is actually the root of a
+ * binary tree.
+ *
+ * @decode_table:
+ * The array in which to create the decoding table. This must have
+ * a length of at least ((2**table_bits) + 2 * num_syms) entries.
+ *
+ * @num_syms:
+ * The number of symbols in the alphabet; also, the length of the
+ * 'lens' array. Must be less than or equal to 2048.
+ *
+ * @table_bits:
+ * The order of the decode table size, as explained above. Must be
+ * less than or equal to 13.
+ *
+ * @lens:
+ * An array of length @num_syms, indexable by symbol, that gives the
+ * length of the codeword, in bits, for that symbol. The length can
+ * be 0, which means that the symbol does not have a codeword
+ * assigned.
+ *
+ * @max_codeword_len:
+ * The longest codeword length allowed in the compression format.
+ * All entries in 'lens' must be less than or equal to this value.
+ * This must be less than or equal to 23.
+ *
+ * @working_space
+ * A temporary array of length '2 * (max_codeword_len + 1) +
+ * num_syms'.
+ *
+ * Returns 0 on success, or -1 if the lengths do not form a valid prefix
+ * code.
+ */
+int make_huffman_decode_table(u16 decode_table[], const u32 num_syms,
+ const u32 table_bits, const u8 lens[],
+ const u32 max_codeword_len,
+ u16 working_space[])
+{
+ const u32 table_num_entries = 1 << table_bits;
+ u16 * const len_counts = &working_space[0];
+ u16 * const offsets = &working_space[1 * (max_codeword_len + 1)];
+ u16 * const sorted_syms = &working_space[2 * (max_codeword_len + 1)];
+ int left;
+ void *decode_table_ptr;
+ u32 sym_idx;
+ u32 codeword_len;
+ u32 stores_per_loop;
+ u32 decode_table_pos;
+ u32 len;
+ u32 sym;
+
+ /* Count how many symbols have each possible codeword length.
+ * Note that a length of 0 indicates the corresponding symbol is not
+ * used in the code and therefore does not have a codeword.
+ */
+ for (len = 0; len <= max_codeword_len; len++)
+ len_counts[len] = 0;
+ for (sym = 0; sym < num_syms; sym++)
+ len_counts[lens[sym]]++;
+
+ /* We can assume all lengths are <= max_codeword_len, but we
+ * cannot assume they form a valid prefix code. A codeword of
+ * length n should require a proportion of the codespace equaling
+ * (1/2)^n. The code is valid if and only if the codespace is
+ * exactly filled by the lengths, by this measure.
+ */
+ left = 1;
+ for (len = 1; len <= max_codeword_len; len++) {
+ left <<= 1;
+ left -= len_counts[len];
+ if (left < 0) {
+ /* The lengths overflow the codespace; that is, the code
+ * is over-subscribed.
+ */
+ return -1;
+ }
+ }
+
+ if (left) {
+ /* The lengths do not fill the codespace; that is, they form an
+ * incomplete set.
+ */
+ if (left == (1 << max_codeword_len)) {
+ /* The code is completely empty. This is arguably
+ * invalid, but in fact it is valid in LZX and XPRESS,
+ * so we must allow it. By definition, no symbols can
+ * be decoded with an empty code. Consequently, we
+ * technically don't even need to fill in the decode
+ * table. However, to avoid accessing uninitialized
+ * memory if the algorithm nevertheless attempts to
+ * decode symbols using such a code, we zero out the
+ * decode table.
+ */
+ memset(decode_table, 0,
+ table_num_entries * sizeof(decode_table[0]));
+ return 0;
+ }
+ return -1;
+ }
+
+ /* Sort the symbols primarily by length and secondarily by symbol order.
+ */
+
+ /* Initialize 'offsets' so that offsets[len] for 1 <= len <=
+ * max_codeword_len is the number of codewords shorter than 'len' bits.
+ */
+ offsets[1] = 0;
+ for (len = 1; len < max_codeword_len; len++)
+ offsets[len + 1] = offsets[len] + len_counts[len];
+
+ /* Use the 'offsets' array to sort the symbols. Note that we do not
+ * include symbols that are not used in the code. Consequently, fewer
+ * than 'num_syms' entries in 'sorted_syms' may be filled.
+ */
+ for (sym = 0; sym < num_syms; sym++)
+ if (lens[sym])
+ sorted_syms[offsets[lens[sym]]++] = sym;
+
+ /* Fill entries for codewords with length <= table_bits
+ * --- that is, those short enough for a direct mapping.
+ *
+ * The table will start with entries for the shortest codeword(s), which
+ * have the most entries. From there, the number of entries per
+ * codeword will decrease.
+ */
+ decode_table_ptr = decode_table;
+ sym_idx = 0;
+ codeword_len = 1;
+ stores_per_loop = (1 << (table_bits - codeword_len));
+ for (; stores_per_loop != 0; codeword_len++, stores_per_loop >>= 1) {
+ u32 end_sym_idx = sym_idx + len_counts[codeword_len];
+
+ for (; sym_idx < end_sym_idx; sym_idx++) {
+ u16 entry;
+ u16 *p;
+ u32 n;
+
+ entry = ((u32)codeword_len << 11) | sorted_syms[sym_idx];
+ p = (u16 *)decode_table_ptr;
+ n = stores_per_loop;
+
+ do {
+ *p++ = entry;
+ } while (--n);
+
+ decode_table_ptr = p;
+ }
+ }
+
+ /* If we've filled in the entire table, we are done. Otherwise,
+ * there are codewords longer than table_bits for which we must
+ * generate binary trees.
+ */
+ decode_table_pos = (u16 *)decode_table_ptr - decode_table;
+ if (decode_table_pos != table_num_entries) {
+ u32 j;
+ u32 next_free_tree_slot;
+ u32 cur_codeword;
+
+ /* First, zero out the remaining entries. This is
+ * necessary so that these entries appear as
+ * "unallocated" in the next part. Each of these entries
+ * will eventually be filled with the representation of
+ * the root node of a binary tree.
+ */
+ j = decode_table_pos;
+ do {
+ decode_table[j] = 0;
+ } while (++j != table_num_entries);
+
+ /* We allocate child nodes starting at the end of the
+ * direct lookup table. Note that there should be
+ * 2*num_syms extra entries for this purpose, although
+ * fewer than this may actually be needed.
+ */
+ next_free_tree_slot = table_num_entries;
+
+ /* Iterate through each codeword with length greater than
+ * 'table_bits', primarily in order of codeword length
+ * and secondarily in order of symbol.
+ */
+ for (cur_codeword = decode_table_pos << 1;
+ codeword_len <= max_codeword_len;
+ codeword_len++, cur_codeword <<= 1) {
+ u32 end_sym_idx = sym_idx + len_counts[codeword_len];
+
+ for (; sym_idx < end_sym_idx; sym_idx++, cur_codeword++) {
+ /* 'sorted_sym' is the symbol represented by the
+ * codeword.
+ */
+ u32 sorted_sym = sorted_syms[sym_idx];
+ u32 extra_bits = codeword_len - table_bits;
+ u32 node_idx = cur_codeword >> extra_bits;
+
+ /* Go through each bit of the current codeword
+ * beyond the prefix of length @table_bits and
+ * walk the appropriate binary tree, allocating
+ * any slots that have not yet been allocated.
+ *
+ * Note that the 'pointer' entry to the binary
+ * tree, which is stored in the direct lookup
+ * portion of the table, is represented
+ * identically to other internal (non-leaf)
+ * nodes of the binary tree; it can be thought
+ * of as simply the root of the tree. The
+ * representation of these internal nodes is
+ * simply the index of the left child combined
+ * with the special bits 0xC000 to distinguish
+ * the entry from direct mapping and leaf node
+ * entries.
+ */
+ do {
+ /* At least one bit remains in the
+ * codeword, but the current node is an
+ * unallocated leaf. Change it to an
+ * internal node.
+ */
+ if (decode_table[node_idx] == 0) {
+ decode_table[node_idx] =
+ next_free_tree_slot | 0xC000;
+ decode_table[next_free_tree_slot++] = 0;
+ decode_table[next_free_tree_slot++] = 0;
+ }
+
+ /* Go to the left child if the next bit
+ * in the codeword is 0; otherwise go to
+ * the right child.
+ */
+ node_idx = decode_table[node_idx] & 0x3FFF;
+ --extra_bits;
+ node_idx += (cur_codeword >> extra_bits) & 1;
+ } while (extra_bits != 0);
+
+ /* We've traversed the tree using the entire
+ * codeword, and we're now at the entry where
+ * the actual symbol will be stored. This is
+ * distinguished from internal nodes by not
+ * having its high two bits set.
+ */
+ decode_table[node_idx] = sorted_sym;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/fs/ntfs3/lib/decompress_common.h b/fs/ntfs3/lib/decompress_common.h
new file mode 100644
index 000000000000..2d70ae42f1b5
--- /dev/null
+++ b/fs/ntfs3/lib/decompress_common.h
@@ -0,0 +1,338 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * decompress_common.h - Code shared by the XPRESS and LZX decompressors
+ *
+ * Copyright (C) 2015 Eric Biggers
+ */
+
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+
+
+/* "Force inline" macro (not required, but helpful for performance) */
+#define forceinline __always_inline
+
+/* Enable whole-word match copying on selected architectures */
+#if defined(__i386__) || defined(__x86_64__) || defined(__ARM_FEATURE_UNALIGNED)
+# define FAST_UNALIGNED_ACCESS
+#endif
+
+/* Size of a machine word */
+#define WORDBYTES (sizeof(size_t))
+
+static forceinline void
+copy_unaligned_word(const void *src, void *dst)
+{
+ put_unaligned(get_unaligned((const size_t *)src), (size_t *)dst);
+}
+
+
+/* Generate a "word" with platform-dependent size whose bytes all contain the
+ * value 'b'.
+ */
+static forceinline size_t repeat_byte(u8 b)
+{
+ size_t v;
+
+ v = b;
+ v |= v << 8;
+ v |= v << 16;
+ v |= v << ((WORDBYTES == 8) ? 32 : 0);
+ return v;
+}
+
+/* Structure that encapsulates a block of in-memory data being interpreted as a
+ * stream of bits, optionally with interwoven literal bytes. Bits are assumed
+ * to be stored in little endian 16-bit coding units, with the bits ordered high
+ * to low.
+ */
+struct input_bitstream {
+
+ /* Bits that have been read from the input buffer. The bits are
+ * left-justified; the next bit is always bit 31.
+ */
+ u32 bitbuf;
+
+ /* Number of bits currently held in @bitbuf. */
+ u32 bitsleft;
+
+ /* Pointer to the next byte to be retrieved from the input buffer. */
+ const u8 *next;
+
+ /* Pointer to just past the end of the input buffer. */
+ const u8 *end;
+};
+
+/* Initialize a bitstream to read from the specified input buffer. */
+static forceinline void init_input_bitstream(struct input_bitstream *is,
+ const void *buffer, u32 size)
+{
+ is->bitbuf = 0;
+ is->bitsleft = 0;
+ is->next = buffer;
+ is->end = is->next + size;
+}
+
+/* Ensure the bit buffer variable for the bitstream contains at least @num_bits
+ * bits. Following this, bitstream_peek_bits() and/or bitstream_remove_bits()
+ * may be called on the bitstream to peek or remove up to @num_bits bits. Note
+ * that @num_bits must be <= 16.
+ */
+static forceinline void bitstream_ensure_bits(struct input_bitstream *is,
+ u32 num_bits)
+{
+ if (is->bitsleft < num_bits) {
+ if (is->end - is->next >= 2) {
+ is->bitbuf |= (u32)get_unaligned_le16(is->next)
+ << (16 - is->bitsleft);
+ is->next += 2;
+ }
+ is->bitsleft += 16;
+ }
+}
+
+/* Return the next @num_bits bits from the bitstream, without removing them.
+ * There must be at least @num_bits remaining in the buffer variable, from a
+ * previous call to bitstream_ensure_bits().
+ */
+static forceinline u32
+bitstream_peek_bits(const struct input_bitstream *is, const u32 num_bits)
+{
+ return (is->bitbuf >> 1) >> (sizeof(is->bitbuf) * 8 - num_bits - 1);
+}
+
+/* Remove @num_bits from the bitstream. There must be at least @num_bits
+ * remaining in the buffer variable, from a previous call to
+ * bitstream_ensure_bits().
+ */
+static forceinline void
+bitstream_remove_bits(struct input_bitstream *is, u32 num_bits)
+{
+ is->bitbuf <<= num_bits;
+ is->bitsleft -= num_bits;
+}
+
+/* Remove and return @num_bits bits from the bitstream. There must be at least
+ * @num_bits remaining in the buffer variable, from a previous call to
+ * bitstream_ensure_bits().
+ */
+static forceinline u32
+bitstream_pop_bits(struct input_bitstream *is, u32 num_bits)
+{
+ u32 bits = bitstream_peek_bits(is, num_bits);
+
+ bitstream_remove_bits(is, num_bits);
+ return bits;
+}
+
+/* Read and return the next @num_bits bits from the bitstream. */
+static forceinline u32
+bitstream_read_bits(struct input_bitstream *is, u32 num_bits)
+{
+ bitstream_ensure_bits(is, num_bits);
+ return bitstream_pop_bits(is, num_bits);
+}
+
+/* Read and return the next literal byte embedded in the bitstream. */
+static forceinline u8
+bitstream_read_byte(struct input_bitstream *is)
+{
+ if (unlikely(is->end == is->next))
+ return 0;
+ return *is->next++;
+}
+
+/* Read and return the next 16-bit integer embedded in the bitstream. */
+static forceinline u16
+bitstream_read_u16(struct input_bitstream *is)
+{
+ u16 v;
+
+ if (unlikely(is->end - is->next < 2))
+ return 0;
+ v = get_unaligned_le16(is->next);
+ is->next += 2;
+ return v;
+}
+
+/* Read and return the next 32-bit integer embedded in the bitstream. */
+static forceinline u32
+bitstream_read_u32(struct input_bitstream *is)
+{
+ u32 v;
+
+ if (unlikely(is->end - is->next < 4))
+ return 0;
+ v = get_unaligned_le32(is->next);
+ is->next += 4;
+ return v;
+}
+
+/* Read into @dst_buffer an array of literal bytes embedded in the bitstream.
+ * Return either a pointer to the byte past the last written, or NULL if the
+ * read overflows the input buffer.
+ */
+static forceinline void *bitstream_read_bytes(struct input_bitstream *is,
+ void *dst_buffer, size_t count)
+{
+ if ((size_t)(is->end - is->next) < count)
+ return NULL;
+ memcpy(dst_buffer, is->next, count);
+ is->next += count;
+ return (u8 *)dst_buffer + count;
+}
+
+/* Align the input bitstream on a coding-unit boundary. */
+static forceinline void bitstream_align(struct input_bitstream *is)
+{
+ is->bitsleft = 0;
+ is->bitbuf = 0;
+}
+
+extern int make_huffman_decode_table(u16 decode_table[], const u32 num_syms,
+ const u32 num_bits, const u8 lens[],
+ const u32 max_codeword_len,
+ u16 working_space[]);
+
+
+/* Reads and returns the next Huffman-encoded symbol from a bitstream. If the
+ * input data is exhausted, the Huffman symbol is decoded as if the missing bits
+ * are all zeroes.
+ */
+static forceinline u32 read_huffsym(struct input_bitstream *istream,
+ const u16 decode_table[],
+ u32 table_bits,
+ u32 max_codeword_len)
+{
+ u32 entry;
+ u32 key_bits;
+
+ bitstream_ensure_bits(istream, max_codeword_len);
+
+ /* Index the decode table by the next table_bits bits of the input. */
+ key_bits = bitstream_peek_bits(istream, table_bits);
+ entry = decode_table[key_bits];
+ if (entry < 0xC000) {
+ /* Fast case: The decode table directly provided the
+ * symbol and codeword length. The low 11 bits are the
+ * symbol, and the high 5 bits are the codeword length.
+ */
+ bitstream_remove_bits(istream, entry >> 11);
+ return entry & 0x7FF;
+ }
+ /* Slow case: The codeword for the symbol is longer than
+ * table_bits, so the symbol does not have an entry
+ * directly in the first (1 << table_bits) entries of the
+ * decode table. Traverse the appropriate binary tree
+ * bit-by-bit to decode the symbol.
+ */
+ bitstream_remove_bits(istream, table_bits);
+ do {
+ key_bits = (entry & 0x3FFF) + bitstream_pop_bits(istream, 1);
+ } while ((entry = decode_table[key_bits]) >= 0xC000);
+ return entry;
+}
+
+/*
+ * Copy an LZ77 match at (dst - offset) to dst.
+ *
+ * The length and offset must be already validated --- that is, (dst - offset)
+ * can't underrun the output buffer, and (dst + length) can't overrun the output
+ * buffer. Also, the length cannot be 0.
+ *
+ * @bufend points to the byte past the end of the output buffer. This function
+ * won't write any data beyond this position.
+ *
+ * Returns dst + length.
+ */
+static forceinline u8 *lz_copy(u8 *dst, u32 length, u32 offset, const u8 *bufend,
+ u32 min_length)
+{
+ const u8 *src = dst - offset;
+
+ /*
+ * Try to copy one machine word at a time. On i386 and x86_64 this is
+ * faster than copying one byte at a time, unless the data is
+ * near-random and all the matches have very short lengths. Note that
+ * since this requires unaligned memory accesses, it won't necessarily
+ * be faster on every architecture.
+ *
+ * Also note that we might copy more than the length of the match. For
+ * example, if a word is 8 bytes and the match is of length 5, then
+ * we'll simply copy 8 bytes. This is okay as long as we don't write
+ * beyond the end of the output buffer, hence the check for (bufend -
+ * end >= WORDBYTES - 1).
+ */
+#ifdef FAST_UNALIGNED_ACCESS
+ u8 * const end = dst + length;
+
+ if (bufend - end >= (ptrdiff_t)(WORDBYTES - 1)) {
+
+ if (offset >= WORDBYTES) {
+ /* The source and destination words don't overlap. */
+
+ /* To improve branch prediction, one iteration of this
+ * loop is unrolled. Most matches are short and will
+ * fail the first check. But if that check passes, then
+ * it becomes increasing likely that the match is long
+ * and we'll need to continue copying.
+ */
+
+ copy_unaligned_word(src, dst);
+ src += WORDBYTES;
+ dst += WORDBYTES;
+
+ if (dst < end) {
+ do {
+ copy_unaligned_word(src, dst);
+ src += WORDBYTES;
+ dst += WORDBYTES;
+ } while (dst < end);
+ }
+ return end;
+ } else if (offset == 1) {
+
+ /* Offset 1 matches are equivalent to run-length
+ * encoding of the previous byte. This case is common
+ * if the data contains many repeated bytes.
+ */
+ size_t v = repeat_byte(*(dst - 1));
+
+ do {
+ put_unaligned(v, (size_t *)dst);
+ src += WORDBYTES;
+ dst += WORDBYTES;
+ } while (dst < end);
+ return end;
+ }
+ /*
+ * We don't bother with special cases for other 'offset <
+ * WORDBYTES', which are usually rarer than 'offset == 1'. Extra
+ * checks will just slow things down. Actually, it's possible
+ * to handle all the 'offset < WORDBYTES' cases using the same
+ * code, but it still becomes more complicated doesn't seem any
+ * faster overall; it definitely slows down the more common
+ * 'offset == 1' case.
+ */
+ }
+#endif /* FAST_UNALIGNED_ACCESS */
+
+ /* Fall back to a bytewise copy. */
+
+ if (min_length >= 2) {
+ *dst++ = *src++;
+ length--;
+ }
+ if (min_length >= 3) {
+ *dst++ = *src++;
+ length--;
+ }
+ do {
+ *dst++ = *src++;
+ } while (--length);
+
+ return dst;
+}
diff --git a/fs/ntfs3/lib/lib.h b/fs/ntfs3/lib/lib.h
new file mode 100644
index 000000000000..f508fbad2e71
--- /dev/null
+++ b/fs/ntfs3/lib/lib.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Adapted for linux kernel by Alexander Mamaev:
+ * - remove implementations of get_unaligned_
+ * - assume GCC is always defined
+ * - ISO C90
+ * - linux kernel code style
+ */
+
+
+/* globals from xpress_decompress.c */
+struct xpress_decompressor *xpress_allocate_decompressor(void);
+void xpress_free_decompressor(struct xpress_decompressor *d);
+int xpress_decompress(struct xpress_decompressor *__restrict d,
+ const void *__restrict compressed_data,
+ size_t compressed_size,
+ void *__restrict uncompressed_data,
+ size_t uncompressed_size);
+
+/* globals from lzx_decompress.c */
+struct lzx_decompressor *lzx_allocate_decompressor(void);
+void lzx_free_decompressor(struct lzx_decompressor *d);
+int lzx_decompress(struct lzx_decompressor *__restrict d,
+ const void *__restrict compressed_data,
+ size_t compressed_size, void *__restrict uncompressed_data,
+ size_t uncompressed_size);
diff --git a/fs/ntfs3/lib/lzx_decompress.c b/fs/ntfs3/lib/lzx_decompress.c
new file mode 100644
index 000000000000..6b16f07073c1
--- /dev/null
+++ b/fs/ntfs3/lib/lzx_decompress.c
@@ -0,0 +1,670 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * lzx_decompress.c - A decompressor for the LZX compression format, which can
+ * be used in "System Compressed" files. This is based on the code from wimlib.
+ * This code only supports a window size (dictionary size) of 32768 bytes, since
+ * this is the only size used in System Compression.
+ *
+ * Copyright (C) 2015 Eric Biggers
+ */
+
+#include "decompress_common.h"
+#include "lib.h"
+
+/* Number of literal byte values */
+#define LZX_NUM_CHARS 256
+
+/* The smallest and largest allowed match lengths */
+#define LZX_MIN_MATCH_LEN 2
+#define LZX_MAX_MATCH_LEN 257
+
+/* Number of distinct match lengths that can be represented */
+#define LZX_NUM_LENS (LZX_MAX_MATCH_LEN - LZX_MIN_MATCH_LEN + 1)
+
+/* Number of match lengths for which no length symbol is required */
+#define LZX_NUM_PRIMARY_LENS 7
+#define LZX_NUM_LEN_HEADERS (LZX_NUM_PRIMARY_LENS + 1)
+
+/* Valid values of the 3-bit block type field */
+#define LZX_BLOCKTYPE_VERBATIM 1
+#define LZX_BLOCKTYPE_ALIGNED 2
+#define LZX_BLOCKTYPE_UNCOMPRESSED 3
+
+/* Number of offset slots for a window size of 32768 */
+#define LZX_NUM_OFFSET_SLOTS 30
+
+/* Number of symbols in the main code for a window size of 32768 */
+#define LZX_MAINCODE_NUM_SYMBOLS \
+ (LZX_NUM_CHARS + (LZX_NUM_OFFSET_SLOTS * LZX_NUM_LEN_HEADERS))
+
+/* Number of symbols in the length code */
+#define LZX_LENCODE_NUM_SYMBOLS (LZX_NUM_LENS - LZX_NUM_PRIMARY_LENS)
+
+/* Number of symbols in the precode */
+#define LZX_PRECODE_NUM_SYMBOLS 20
+
+/* Number of bits in which each precode codeword length is represented */
+#define LZX_PRECODE_ELEMENT_SIZE 4
+
+/* Number of low-order bits of each match offset that are entropy-encoded in
+ * aligned offset blocks
+ */
+#define LZX_NUM_ALIGNED_OFFSET_BITS 3
+
+/* Number of symbols in the aligned offset code */
+#define LZX_ALIGNEDCODE_NUM_SYMBOLS (1 << LZX_NUM_ALIGNED_OFFSET_BITS)
+
+/* Mask for the match offset bits that are entropy-encoded in aligned offset
+ * blocks
+ */
+#define LZX_ALIGNED_OFFSET_BITMASK ((1 << LZX_NUM_ALIGNED_OFFSET_BITS) - 1)
+
+/* Number of bits in which each aligned offset codeword length is represented */
+#define LZX_ALIGNEDCODE_ELEMENT_SIZE 3
+
+/* Maximum lengths (in bits) of the codewords in each Huffman code */
+#define LZX_MAX_MAIN_CODEWORD_LEN 16
+#define LZX_MAX_LEN_CODEWORD_LEN 16
+#define LZX_MAX_PRE_CODEWORD_LEN ((1 << LZX_PRECODE_ELEMENT_SIZE) - 1)
+#define LZX_MAX_ALIGNED_CODEWORD_LEN ((1 << LZX_ALIGNEDCODE_ELEMENT_SIZE) - 1)
+
+/* The default "filesize" value used in pre/post-processing. In the LZX format
+ * used in cabinet files this value must be given to the decompressor, whereas
+ * in the LZX format used in WIM files and system-compressed files this value is
+ * fixed at 12000000.
+ */
+#define LZX_DEFAULT_FILESIZE 12000000
+
+/* Assumed block size when the encoded block size begins with a 0 bit. */
+#define LZX_DEFAULT_BLOCK_SIZE 32768
+
+/* Number of offsets in the recent (or "repeat") offsets queue. */
+#define LZX_NUM_RECENT_OFFSETS 3
+
+/* These values are chosen for fast decompression. */
+#define LZX_MAINCODE_TABLEBITS 11
+#define LZX_LENCODE_TABLEBITS 10
+#define LZX_PRECODE_TABLEBITS 6
+#define LZX_ALIGNEDCODE_TABLEBITS 7
+
+#define LZX_READ_LENS_MAX_OVERRUN 50
+
+/* Mapping: offset slot => first match offset that uses that offset slot.
+ */
+static const u32 lzx_offset_slot_base[LZX_NUM_OFFSET_SLOTS + 1] = {
+ 0, 1, 2, 3, 4, /* 0 --- 4 */
+ 6, 8, 12, 16, 24, /* 5 --- 9 */
+ 32, 48, 64, 96, 128, /* 10 --- 14 */
+ 192, 256, 384, 512, 768, /* 15 --- 19 */
+ 1024, 1536, 2048, 3072, 4096, /* 20 --- 24 */
+ 6144, 8192, 12288, 16384, 24576, /* 25 --- 29 */
+ 32768, /* extra */
+};
+
+/* Mapping: offset slot => how many extra bits must be read and added to the
+ * corresponding offset slot base to decode the match offset.
+ */
+static const u8 lzx_extra_offset_bits[LZX_NUM_OFFSET_SLOTS] = {
+ 0, 0, 0, 0, 1,
+ 1, 2, 2, 3, 3,
+ 4, 4, 5, 5, 6,
+ 6, 7, 7, 8, 8,
+ 9, 9, 10, 10, 11,
+ 11, 12, 12, 13, 13,
+};
+
+/* Reusable heap-allocated memory for LZX decompression */
+struct lzx_decompressor {
+
+ /* Huffman decoding tables, and arrays that map symbols to codeword
+ * lengths
+ */
+
+ u16 maincode_decode_table[(1 << LZX_MAINCODE_TABLEBITS) +
+ (LZX_MAINCODE_NUM_SYMBOLS * 2)];
+ u8 maincode_lens[LZX_MAINCODE_NUM_SYMBOLS + LZX_READ_LENS_MAX_OVERRUN];
+
+
+ u16 lencode_decode_table[(1 << LZX_LENCODE_TABLEBITS) +
+ (LZX_LENCODE_NUM_SYMBOLS * 2)];
+ u8 lencode_lens[LZX_LENCODE_NUM_SYMBOLS + LZX_READ_LENS_MAX_OVERRUN];
+
+
+ u16 alignedcode_decode_table[(1 << LZX_ALIGNEDCODE_TABLEBITS) +
+ (LZX_ALIGNEDCODE_NUM_SYMBOLS * 2)];
+ u8 alignedcode_lens[LZX_ALIGNEDCODE_NUM_SYMBOLS];
+
+ u16 precode_decode_table[(1 << LZX_PRECODE_TABLEBITS) +
+ (LZX_PRECODE_NUM_SYMBOLS * 2)];
+ u8 precode_lens[LZX_PRECODE_NUM_SYMBOLS];
+
+ /* Temporary space for make_huffman_decode_table() */
+ u16 working_space[2 * (1 + LZX_MAX_MAIN_CODEWORD_LEN) +
+ LZX_MAINCODE_NUM_SYMBOLS];
+};
+
+static void undo_e8_translation(void *target, s32 input_pos)
+{
+ s32 abs_offset, rel_offset;
+
+ abs_offset = get_unaligned_le32(target);
+ if (abs_offset >= 0) {
+ if (abs_offset < LZX_DEFAULT_FILESIZE) {
+ /* "good translation" */
+ rel_offset = abs_offset - input_pos;
+ put_unaligned_le32(rel_offset, target);
+ }
+ } else {
+ if (abs_offset >= -input_pos) {
+ /* "compensating translation" */
+ rel_offset = abs_offset + LZX_DEFAULT_FILESIZE;
+ put_unaligned_le32(rel_offset, target);
+ }
+ }
+}
+
+/*
+ * Undo the 'E8' preprocessing used in LZX. Before compression, the
+ * uncompressed data was preprocessed by changing the targets of suspected x86
+ * CALL instructions from relative offsets to absolute offsets. After
+ * match/literal decoding, the decompressor must undo the translation.
+ */
+static void lzx_postprocess(u8 *data, u32 size)
+{
+ /*
+ * A worthwhile optimization is to push the end-of-buffer check into the
+ * relatively rare E8 case. This is possible if we replace the last six
+ * bytes of data with E8 bytes; then we are guaranteed to hit an E8 byte
+ * before reaching end-of-buffer. In addition, this scheme guarantees
+ * that no translation can begin following an E8 byte in the last 10
+ * bytes because a 4-byte offset containing E8 as its high byte is a
+ * large negative number that is not valid for translation. That is
+ * exactly what we need.
+ */
+ u8 *tail;
+ u8 saved_bytes[6];
+ u8 *p;
+
+ if (size <= 10)
+ return;
+
+ tail = &data[size - 6];
+ memcpy(saved_bytes, tail, 6);
+ memset(tail, 0xE8, 6);
+ p = data;
+ for (;;) {
+ while (*p != 0xE8)
+ p++;
+ if (p >= tail)
+ break;
+ undo_e8_translation(p + 1, p - data);
+ p += 5;
+ }
+ memcpy(tail, saved_bytes, 6);
+}
+
+/* Read a Huffman-encoded symbol using the precode. */
+static forceinline u32 read_presym(const struct lzx_decompressor *d,
+ struct input_bitstream *is)
+{
+ return read_huffsym(is, d->precode_decode_table,
+ LZX_PRECODE_TABLEBITS, LZX_MAX_PRE_CODEWORD_LEN);
+}
+
+/* Read a Huffman-encoded symbol using the main code. */
+static forceinline u32 read_mainsym(const struct lzx_decompressor *d,
+ struct input_bitstream *is)
+{
+ return read_huffsym(is, d->maincode_decode_table,
+ LZX_MAINCODE_TABLEBITS, LZX_MAX_MAIN_CODEWORD_LEN);
+}
+
+/* Read a Huffman-encoded symbol using the length code. */
+static forceinline u32 read_lensym(const struct lzx_decompressor *d,
+ struct input_bitstream *is)
+{
+ return read_huffsym(is, d->lencode_decode_table,
+ LZX_LENCODE_TABLEBITS, LZX_MAX_LEN_CODEWORD_LEN);
+}
+
+/* Read a Huffman-encoded symbol using the aligned offset code. */
+static forceinline u32 read_alignedsym(const struct lzx_decompressor *d,
+ struct input_bitstream *is)
+{
+ return read_huffsym(is, d->alignedcode_decode_table,
+ LZX_ALIGNEDCODE_TABLEBITS,
+ LZX_MAX_ALIGNED_CODEWORD_LEN);
+}
+
+/*
+ * Read the precode from the compressed input bitstream, then use it to decode
+ * @num_lens codeword length values.
+ *
+ * @is: The input bitstream.
+ *
+ * @lens: An array that contains the length values from the previous time
+ * the codeword lengths for this Huffman code were read, or all 0's
+ * if this is the first time. This array must have at least
+ * (@num_lens + LZX_READ_LENS_MAX_OVERRUN) entries.
+ *
+ * @num_lens: Number of length values to decode.
+ *
+ * Returns 0 on success, or -1 if the data was invalid.
+ */
+static int lzx_read_codeword_lens(struct lzx_decompressor *d,
+ struct input_bitstream *is,
+ u8 *lens, u32 num_lens)
+{
+ u8 *len_ptr = lens;
+ u8 *lens_end = lens + num_lens;
+ int i;
+
+ /* Read the lengths of the precode codewords. These are given
+ * explicitly.
+ */
+ for (i = 0; i < LZX_PRECODE_NUM_SYMBOLS; i++) {
+ d->precode_lens[i] =
+ bitstream_read_bits(is, LZX_PRECODE_ELEMENT_SIZE);
+ }
+
+ /* Make the decoding table for the precode. */
+ if (make_huffman_decode_table(d->precode_decode_table,
+ LZX_PRECODE_NUM_SYMBOLS,
+ LZX_PRECODE_TABLEBITS,
+ d->precode_lens,
+ LZX_MAX_PRE_CODEWORD_LEN,
+ d->working_space))
+ return -1;
+
+ /* Decode the codeword lengths. */
+ do {
+ u32 presym;
+ u8 len;
+
+ /* Read the next precode symbol. */
+ presym = read_presym(d, is);
+ if (presym < 17) {
+ /* Difference from old length */
+ len = *len_ptr - presym;
+ if ((s8)len < 0)
+ len += 17;
+ *len_ptr++ = len;
+ } else {
+ /* Special RLE values */
+
+ u32 run_len;
+
+ if (presym == 17) {
+ /* Run of 0's */
+ run_len = 4 + bitstream_read_bits(is, 4);
+ len = 0;
+ } else if (presym == 18) {
+ /* Longer run of 0's */
+ run_len = 20 + bitstream_read_bits(is, 5);
+ len = 0;
+ } else {
+ /* Run of identical lengths */
+ run_len = 4 + bitstream_read_bits(is, 1);
+ presym = read_presym(d, is);
+ if (presym > 17)
+ return -1;
+ len = *len_ptr - presym;
+ if ((s8)len < 0)
+ len += 17;
+ }
+
+ do {
+ *len_ptr++ = len;
+ } while (--run_len);
+ /* Worst case overrun is when presym == 18,
+ * run_len == 20 + 31, and only 1 length was remaining.
+ * So LZX_READ_LENS_MAX_OVERRUN == 50.
+ *
+ * Overrun while reading the first half of maincode_lens
+ * can corrupt the previous values in the second half.
+ * This doesn't really matter because the resulting
+ * lengths will still be in range, and data that
+ * generates overruns is invalid anyway.
+ */
+ }
+ } while (len_ptr < lens_end);
+
+ return 0;
+}
+
+/*
+ * Read the header of an LZX block and save the block type and (uncompressed)
+ * size in *block_type_ret and *block_size_ret, respectively.
+ *
+ * If the block is compressed, also update the Huffman decode @tables with the
+ * new Huffman codes. If the block is uncompressed, also update the match
+ * offset @queue with the new match offsets.
+ *
+ * Return 0 on success, or -1 if the data was invalid.
+ */
+static int lzx_read_block_header(struct lzx_decompressor *d,
+ struct input_bitstream *is,
+ int *block_type_ret,
+ u32 *block_size_ret,
+ u32 recent_offsets[])
+{
+ int block_type;
+ u32 block_size;
+ int i;
+
+ bitstream_ensure_bits(is, 4);
+
+ /* The first three bits tell us what kind of block it is, and should be
+ * one of the LZX_BLOCKTYPE_* values.
+ */
+ block_type = bitstream_pop_bits(is, 3);
+
+ /* Read the block size. */
+ if (bitstream_pop_bits(is, 1)) {
+ block_size = LZX_DEFAULT_BLOCK_SIZE;
+ } else {
+ block_size = 0;
+ block_size |= bitstream_read_bits(is, 8);
+ block_size <<= 8;
+ block_size |= bitstream_read_bits(is, 8);
+ }
+
+ switch (block_type) {
+
+ case LZX_BLOCKTYPE_ALIGNED:
+
+ /* Read the aligned offset code and prepare its decode table.
+ */
+
+ for (i = 0; i < LZX_ALIGNEDCODE_NUM_SYMBOLS; i++) {
+ d->alignedcode_lens[i] =
+ bitstream_read_bits(is,
+ LZX_ALIGNEDCODE_ELEMENT_SIZE);
+ }
+
+ if (make_huffman_decode_table(d->alignedcode_decode_table,
+ LZX_ALIGNEDCODE_NUM_SYMBOLS,
+ LZX_ALIGNEDCODE_TABLEBITS,
+ d->alignedcode_lens,
+ LZX_MAX_ALIGNED_CODEWORD_LEN,
+ d->working_space))
+ return -1;
+
+ /* Fall though, since the rest of the header for aligned offset
+ * blocks is the same as that for verbatim blocks.
+ */
+ fallthrough;
+
+ case LZX_BLOCKTYPE_VERBATIM:
+
+ /* Read the main code and prepare its decode table.
+ *
+ * Note that the codeword lengths in the main code are encoded
+ * in two parts: one part for literal symbols, and one part for
+ * match symbols.
+ */
+
+ if (lzx_read_codeword_lens(d, is, d->maincode_lens,
+ LZX_NUM_CHARS))
+ return -1;
+
+ if (lzx_read_codeword_lens(d, is,
+ d->maincode_lens + LZX_NUM_CHARS,
+ LZX_MAINCODE_NUM_SYMBOLS - LZX_NUM_CHARS))
+ return -1;
+
+ if (make_huffman_decode_table(d->maincode_decode_table,
+ LZX_MAINCODE_NUM_SYMBOLS,
+ LZX_MAINCODE_TABLEBITS,
+ d->maincode_lens,
+ LZX_MAX_MAIN_CODEWORD_LEN,
+ d->working_space))
+ return -1;
+
+ /* Read the length code and prepare its decode table. */
+
+ if (lzx_read_codeword_lens(d, is, d->lencode_lens,
+ LZX_LENCODE_NUM_SYMBOLS))
+ return -1;
+
+ if (make_huffman_decode_table(d->lencode_decode_table,
+ LZX_LENCODE_NUM_SYMBOLS,
+ LZX_LENCODE_TABLEBITS,
+ d->lencode_lens,
+ LZX_MAX_LEN_CODEWORD_LEN,
+ d->working_space))
+ return -1;
+
+ break;
+
+ case LZX_BLOCKTYPE_UNCOMPRESSED:
+
+ /* Before reading the three recent offsets from the uncompressed
+ * block header, the stream must be aligned on a 16-bit
+ * boundary. But if the stream is *already* aligned, then the
+ * next 16 bits must be discarded.
+ */
+ bitstream_ensure_bits(is, 1);
+ bitstream_align(is);
+
+ recent_offsets[0] = bitstream_read_u32(is);
+ recent_offsets[1] = bitstream_read_u32(is);
+ recent_offsets[2] = bitstream_read_u32(is);
+
+ /* Offsets of 0 are invalid. */
+ if (recent_offsets[0] == 0 || recent_offsets[1] == 0 ||
+ recent_offsets[2] == 0)
+ return -1;
+ break;
+
+ default:
+ /* Unrecognized block type. */
+ return -1;
+ }
+
+ *block_type_ret = block_type;
+ *block_size_ret = block_size;
+ return 0;
+}
+
+/* Decompress a block of LZX-compressed data. */
+static int lzx_decompress_block(const struct lzx_decompressor *d,
+ struct input_bitstream *is,
+ int block_type, u32 block_size,
+ u8 * const out_begin, u8 *out_next,
+ u32 recent_offsets[])
+{
+ u8 * const block_end = out_next + block_size;
+ u32 ones_if_aligned = 0U - (block_type == LZX_BLOCKTYPE_ALIGNED);
+
+ do {
+ u32 mainsym;
+ u32 match_len;
+ u32 match_offset;
+ u32 offset_slot;
+ u32 num_extra_bits;
+
+ mainsym = read_mainsym(d, is);
+ if (mainsym < LZX_NUM_CHARS) {
+ /* Literal */
+ *out_next++ = mainsym;
+ continue;
+ }
+
+ /* Match */
+
+ /* Decode the length header and offset slot. */
+ mainsym -= LZX_NUM_CHARS;
+ match_len = mainsym % LZX_NUM_LEN_HEADERS;
+ offset_slot = mainsym / LZX_NUM_LEN_HEADERS;
+
+ /* If needed, read a length symbol to decode the full length. */
+ if (match_len == LZX_NUM_PRIMARY_LENS)
+ match_len += read_lensym(d, is);
+ match_len += LZX_MIN_MATCH_LEN;
+
+ if (offset_slot < LZX_NUM_RECENT_OFFSETS) {
+ /* Repeat offset */
+
+ /* Note: This isn't a real LRU queue, since using the R2
+ * offset doesn't bump the R1 offset down to R2. This
+ * quirk allows all 3 recent offsets to be handled by
+ * the same code. (For R0, the swap is a no-op.)
+ */
+ match_offset = recent_offsets[offset_slot];
+ recent_offsets[offset_slot] = recent_offsets[0];
+ recent_offsets[0] = match_offset;
+ } else {
+ /* Explicit offset */
+
+ /* Look up the number of extra bits that need to be read
+ * to decode offsets with this offset slot.
+ */
+ num_extra_bits = lzx_extra_offset_bits[offset_slot];
+
+ /* Start with the offset slot base value. */
+ match_offset = lzx_offset_slot_base[offset_slot];
+
+ /* In aligned offset blocks, the low-order 3 bits of
+ * each offset are encoded using the aligned offset
+ * code. Otherwise, all the extra bits are literal.
+ */
+
+ if ((num_extra_bits & ones_if_aligned) >= LZX_NUM_ALIGNED_OFFSET_BITS) {
+ match_offset +=
+ bitstream_read_bits(is, num_extra_bits -
+ LZX_NUM_ALIGNED_OFFSET_BITS)
+ << LZX_NUM_ALIGNED_OFFSET_BITS;
+ match_offset += read_alignedsym(d, is);
+ } else {
+ match_offset += bitstream_read_bits(is, num_extra_bits);
+ }
+
+ /* Adjust the offset. */
+ match_offset -= (LZX_NUM_RECENT_OFFSETS - 1);
+
+ /* Update the recent offsets. */
+ recent_offsets[2] = recent_offsets[1];
+ recent_offsets[1] = recent_offsets[0];
+ recent_offsets[0] = match_offset;
+ }
+
+ /* Validate the match, then copy it to the current position. */
+
+ if (match_len > (size_t)(block_end - out_next))
+ return -1;
+
+ if (match_offset > (size_t)(out_next - out_begin))
+ return -1;
+
+ out_next = lz_copy(out_next, match_len, match_offset,
+ block_end, LZX_MIN_MATCH_LEN);
+
+ } while (out_next != block_end);
+
+ return 0;
+}
+
+/*
+ * lzx_allocate_decompressor - Allocate an LZX decompressor
+ *
+ * Return the pointer to the decompressor on success, or return NULL and set
+ * errno on failure.
+ */
+struct lzx_decompressor *lzx_allocate_decompressor(void)
+{
+ return kmalloc(sizeof(struct lzx_decompressor), GFP_NOFS);
+}
+
+/*
+ * lzx_decompress - Decompress a buffer of LZX-compressed data
+ *
+ * @decompressor: A decompressor allocated with lzx_allocate_decompressor()
+ * @compressed_data: The buffer of data to decompress
+ * @compressed_size: Number of bytes of compressed data
+ * @uncompressed_data: The buffer in which to store the decompressed data
+ * @uncompressed_size: The number of bytes the data decompresses into
+ *
+ * Return 0 on success, or return -1 and set errno on failure.
+ */
+int lzx_decompress(struct lzx_decompressor *decompressor,
+ const void *compressed_data, size_t compressed_size,
+ void *uncompressed_data, size_t uncompressed_size)
+{
+ struct lzx_decompressor *d = decompressor;
+ u8 * const out_begin = uncompressed_data;
+ u8 *out_next = out_begin;
+ u8 * const out_end = out_begin + uncompressed_size;
+ struct input_bitstream is;
+ u32 recent_offsets[LZX_NUM_RECENT_OFFSETS] = {1, 1, 1};
+ int e8_status = 0;
+
+ init_input_bitstream(&is, compressed_data, compressed_size);
+
+ /* Codeword lengths begin as all 0's for delta encoding purposes. */
+ memset(d->maincode_lens, 0, LZX_MAINCODE_NUM_SYMBOLS);
+ memset(d->lencode_lens, 0, LZX_LENCODE_NUM_SYMBOLS);
+
+ /* Decompress blocks until we have all the uncompressed data. */
+
+ while (out_next != out_end) {
+ int block_type;
+ u32 block_size;
+
+ if (lzx_read_block_header(d, &is, &block_type, &block_size,
+ recent_offsets))
+ goto invalid;
+
+ if (block_size < 1 || block_size > (size_t)(out_end - out_next))
+ goto invalid;
+
+ if (block_type != LZX_BLOCKTYPE_UNCOMPRESSED) {
+
+ /* Compressed block */
+
+ if (lzx_decompress_block(d,
+ &is,
+ block_type,
+ block_size,
+ out_begin,
+ out_next,
+ recent_offsets))
+ goto invalid;
+
+ e8_status |= d->maincode_lens[0xe8];
+ out_next += block_size;
+ } else {
+ /* Uncompressed block */
+
+ out_next = bitstream_read_bytes(&is, out_next,
+ block_size);
+ if (!out_next)
+ goto invalid;
+
+ if (block_size & 1)
+ bitstream_read_byte(&is);
+
+ e8_status = 1;
+ }
+ }
+
+ /* Postprocess the data unless it cannot possibly contain 0xe8 bytes. */
+ if (e8_status)
+ lzx_postprocess(uncompressed_data, uncompressed_size);
+
+ return 0;
+
+invalid:
+ return -1;
+}
+
+/*
+ * lzx_free_decompressor - Free an LZX decompressor
+ *
+ * @decompressor: A decompressor that was allocated with
+ * lzx_allocate_decompressor(), or NULL.
+ */
+void lzx_free_decompressor(struct lzx_decompressor *decompressor)
+{
+ kfree(decompressor);
+}
diff --git a/fs/ntfs3/lib/xpress_decompress.c b/fs/ntfs3/lib/xpress_decompress.c
new file mode 100644
index 000000000000..769c6d3dde67
--- /dev/null
+++ b/fs/ntfs3/lib/xpress_decompress.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * xpress_decompress.c - A decompressor for the XPRESS compression format
+ * (Huffman variant), which can be used in "System Compressed" files. This is
+ * based on the code from wimlib.
+ *
+ * Copyright (C) 2015 Eric Biggers
+ */
+
+#include "decompress_common.h"
+#include "lib.h"
+
+#define XPRESS_NUM_SYMBOLS 512
+#define XPRESS_MAX_CODEWORD_LEN 15
+#define XPRESS_MIN_MATCH_LEN 3
+
+/* This value is chosen for fast decompression. */
+#define XPRESS_TABLEBITS 12
+
+/* Reusable heap-allocated memory for XPRESS decompression */
+struct xpress_decompressor {
+
+ /* The Huffman decoding table */
+ u16 decode_table[(1 << XPRESS_TABLEBITS) + 2 * XPRESS_NUM_SYMBOLS];
+
+ /* An array that maps symbols to codeword lengths */
+ u8 lens[XPRESS_NUM_SYMBOLS];
+
+ /* Temporary space for make_huffman_decode_table() */
+ u16 working_space[2 * (1 + XPRESS_MAX_CODEWORD_LEN) +
+ XPRESS_NUM_SYMBOLS];
+};
+
+/*
+ * xpress_allocate_decompressor - Allocate an XPRESS decompressor
+ *
+ * Return the pointer to the decompressor on success, or return NULL and set
+ * errno on failure.
+ */
+struct xpress_decompressor *xpress_allocate_decompressor(void)
+{
+ return kmalloc(sizeof(struct xpress_decompressor), GFP_NOFS);
+}
+
+/*
+ * xpress_decompress - Decompress a buffer of XPRESS-compressed data
+ *
+ * @decompressor: A decompressor that was allocated with
+ * xpress_allocate_decompressor()
+ * @compressed_data: The buffer of data to decompress
+ * @compressed_size: Number of bytes of compressed data
+ * @uncompressed_data: The buffer in which to store the decompressed data
+ * @uncompressed_size: The number of bytes the data decompresses into
+ *
+ * Return 0 on success, or return -1 and set errno on failure.
+ */
+int xpress_decompress(struct xpress_decompressor *decompressor,
+ const void *compressed_data, size_t compressed_size,
+ void *uncompressed_data, size_t uncompressed_size)
+{
+ struct xpress_decompressor *d = decompressor;
+ const u8 * const in_begin = compressed_data;
+ u8 * const out_begin = uncompressed_data;
+ u8 *out_next = out_begin;
+ u8 * const out_end = out_begin + uncompressed_size;
+ struct input_bitstream is;
+ u32 i;
+
+ /* Read the Huffman codeword lengths. */
+ if (compressed_size < XPRESS_NUM_SYMBOLS / 2)
+ goto invalid;
+ for (i = 0; i < XPRESS_NUM_SYMBOLS / 2; i++) {
+ d->lens[i*2 + 0] = in_begin[i] & 0xF;
+ d->lens[i*2 + 1] = in_begin[i] >> 4;
+ }
+
+ /* Build a decoding table for the Huffman code. */
+ if (make_huffman_decode_table(d->decode_table, XPRESS_NUM_SYMBOLS,
+ XPRESS_TABLEBITS, d->lens,
+ XPRESS_MAX_CODEWORD_LEN,
+ d->working_space))
+ goto invalid;
+
+ /* Decode the matches and literals. */
+
+ init_input_bitstream(&is, in_begin + XPRESS_NUM_SYMBOLS / 2,
+ compressed_size - XPRESS_NUM_SYMBOLS / 2);
+
+ while (out_next != out_end) {
+ u32 sym;
+ u32 log2_offset;
+ u32 length;
+ u32 offset;
+
+ sym = read_huffsym(&is, d->decode_table,
+ XPRESS_TABLEBITS, XPRESS_MAX_CODEWORD_LEN);
+ if (sym < 256) {
+ /* Literal */
+ *out_next++ = sym;
+ } else {
+ /* Match */
+ length = sym & 0xf;
+ log2_offset = (sym >> 4) & 0xf;
+
+ bitstream_ensure_bits(&is, 16);
+
+ offset = ((u32)1 << log2_offset) |
+ bitstream_pop_bits(&is, log2_offset);
+
+ if (length == 0xf) {
+ length += bitstream_read_byte(&is);
+ if (length == 0xf + 0xff)
+ length = bitstream_read_u16(&is);
+ }
+ length += XPRESS_MIN_MATCH_LEN;
+
+ if (offset > (size_t)(out_next - out_begin))
+ goto invalid;
+
+ if (length > (size_t)(out_end - out_next))
+ goto invalid;
+
+ out_next = lz_copy(out_next, length, offset, out_end,
+ XPRESS_MIN_MATCH_LEN);
+ }
+ }
+ return 0;
+
+invalid:
+ return -1;
+}
+
+/*
+ * xpress_free_decompressor - Free an XPRESS decompressor
+ *
+ * @decompressor: A decompressor that was allocated with
+ * xpress_allocate_decompressor(), or NULL.
+ */
+void xpress_free_decompressor(struct xpress_decompressor *decompressor)
+{
+ kfree(decompressor);
+}
diff --git a/fs/ntfs3/lznt.c b/fs/ntfs3/lznt.c
new file mode 100644
index 000000000000..f1f691a67cc4
--- /dev/null
+++ b/fs/ntfs3/lznt.c
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+// clang-format off
+/* Src buffer is zero. */
+#define LZNT_ERROR_ALL_ZEROS 1
+#define LZNT_CHUNK_SIZE 0x1000
+// clang-format on
+
+struct lznt_hash {
+ const u8 *p1;
+ const u8 *p2;
+};
+
+struct lznt {
+ const u8 *unc;
+ const u8 *unc_end;
+ const u8 *best_match;
+ size_t max_len;
+ bool std;
+
+ struct lznt_hash hash[LZNT_CHUNK_SIZE];
+};
+
+static inline size_t get_match_len(const u8 *ptr, const u8 *end, const u8 *prev,
+ size_t max_len)
+{
+ size_t len = 0;
+
+ while (ptr + len < end && ptr[len] == prev[len] && ++len < max_len)
+ ;
+ return len;
+}
+
+static size_t longest_match_std(const u8 *src, struct lznt *ctx)
+{
+ size_t hash_index;
+ size_t len1 = 0, len2 = 0;
+ const u8 **hash;
+
+ hash_index =
+ ((40543U * ((((src[0] << 4) ^ src[1]) << 4) ^ src[2])) >> 4) &
+ (LZNT_CHUNK_SIZE - 1);
+
+ hash = &(ctx->hash[hash_index].p1);
+
+ if (hash[0] >= ctx->unc && hash[0] < src && hash[0][0] == src[0] &&
+ hash[0][1] == src[1] && hash[0][2] == src[2]) {
+ len1 = 3;
+ if (ctx->max_len > 3)
+ len1 += get_match_len(src + 3, ctx->unc_end,
+ hash[0] + 3, ctx->max_len - 3);
+ }
+
+ if (hash[1] >= ctx->unc && hash[1] < src && hash[1][0] == src[0] &&
+ hash[1][1] == src[1] && hash[1][2] == src[2]) {
+ len2 = 3;
+ if (ctx->max_len > 3)
+ len2 += get_match_len(src + 3, ctx->unc_end,
+ hash[1] + 3, ctx->max_len - 3);
+ }
+
+ /* Compare two matches and select the best one. */
+ if (len1 < len2) {
+ ctx->best_match = hash[1];
+ len1 = len2;
+ } else {
+ ctx->best_match = hash[0];
+ }
+
+ hash[1] = hash[0];
+ hash[0] = src;
+ return len1;
+}
+
+static size_t longest_match_best(const u8 *src, struct lznt *ctx)
+{
+ size_t max_len;
+ const u8 *ptr;
+
+ if (ctx->unc >= src || !ctx->max_len)
+ return 0;
+
+ max_len = 0;
+ for (ptr = ctx->unc; ptr < src; ++ptr) {
+ size_t len =
+ get_match_len(src, ctx->unc_end, ptr, ctx->max_len);
+ if (len >= max_len) {
+ max_len = len;
+ ctx->best_match = ptr;
+ }
+ }
+
+ return max_len >= 3 ? max_len : 0;
+}
+
+static const size_t s_max_len[] = {
+ 0x1002, 0x802, 0x402, 0x202, 0x102, 0x82, 0x42, 0x22, 0x12,
+};
+
+static const size_t s_max_off[] = {
+ 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
+};
+
+static inline u16 make_pair(size_t offset, size_t len, size_t index)
+{
+ return ((offset - 1) << (12 - index)) |
+ ((len - 3) & (((1 << (12 - index)) - 1)));
+}
+
+static inline size_t parse_pair(u16 pair, size_t *offset, size_t index)
+{
+ *offset = 1 + (pair >> (12 - index));
+ return 3 + (pair & ((1 << (12 - index)) - 1));
+}
+
+/*
+ * compress_chunk
+ *
+ * Return:
+ * * 0 - Ok, @cmpr contains @cmpr_chunk_size bytes of compressed data.
+ * * 1 - Input buffer is full zero.
+ * * -2 - The compressed buffer is too small to hold the compressed data.
+ */
+static inline int compress_chunk(size_t (*match)(const u8 *, struct lznt *),
+ const u8 *unc, const u8 *unc_end, u8 *cmpr,
+ u8 *cmpr_end, size_t *cmpr_chunk_size,
+ struct lznt *ctx)
+{
+ size_t cnt = 0;
+ size_t idx = 0;
+ const u8 *up = unc;
+ u8 *cp = cmpr + 3;
+ u8 *cp2 = cmpr + 2;
+ u8 not_zero = 0;
+ /* Control byte of 8-bit values: ( 0 - means byte as is, 1 - short pair ). */
+ u8 ohdr = 0;
+ u8 *last;
+ u16 t16;
+
+ if (unc + LZNT_CHUNK_SIZE < unc_end)
+ unc_end = unc + LZNT_CHUNK_SIZE;
+
+ last = min(cmpr + LZNT_CHUNK_SIZE + sizeof(short), cmpr_end);
+
+ ctx->unc = unc;
+ ctx->unc_end = unc_end;
+ ctx->max_len = s_max_len[0];
+
+ while (up < unc_end) {
+ size_t max_len;
+
+ while (unc + s_max_off[idx] < up)
+ ctx->max_len = s_max_len[++idx];
+
+ /* Find match. */
+ max_len = up + 3 <= unc_end ? (*match)(up, ctx) : 0;
+
+ if (!max_len) {
+ if (cp >= last)
+ goto NotCompressed;
+ not_zero |= *cp++ = *up++;
+ } else if (cp + 1 >= last) {
+ goto NotCompressed;
+ } else {
+ t16 = make_pair(up - ctx->best_match, max_len, idx);
+ *cp++ = t16;
+ *cp++ = t16 >> 8;
+
+ ohdr |= 1 << cnt;
+ up += max_len;
+ }
+
+ cnt = (cnt + 1) & 7;
+ if (!cnt) {
+ *cp2 = ohdr;
+ ohdr = 0;
+ cp2 = cp;
+ cp += 1;
+ }
+ }
+
+ if (cp2 < last)
+ *cp2 = ohdr;
+ else
+ cp -= 1;
+
+ *cmpr_chunk_size = cp - cmpr;
+
+ t16 = (*cmpr_chunk_size - 3) | 0xB000;
+ cmpr[0] = t16;
+ cmpr[1] = t16 >> 8;
+
+ return not_zero ? 0 : LZNT_ERROR_ALL_ZEROS;
+
+NotCompressed:
+
+ if ((cmpr + LZNT_CHUNK_SIZE + sizeof(short)) > last)
+ return -2;
+
+ /*
+ * Copy non cmpr data.
+ * 0x3FFF == ((LZNT_CHUNK_SIZE + 2 - 3) | 0x3000)
+ */
+ cmpr[0] = 0xff;
+ cmpr[1] = 0x3f;
+
+ memcpy(cmpr + sizeof(short), unc, LZNT_CHUNK_SIZE);
+ *cmpr_chunk_size = LZNT_CHUNK_SIZE + sizeof(short);
+
+ return 0;
+}
+
+static inline ssize_t decompress_chunk(u8 *unc, u8 *unc_end, const u8 *cmpr,
+ const u8 *cmpr_end)
+{
+ u8 *up = unc;
+ u8 ch = *cmpr++;
+ size_t bit = 0;
+ size_t index = 0;
+ u16 pair;
+ size_t offset, length;
+
+ /* Do decompression until pointers are inside range. */
+ while (up < unc_end && cmpr < cmpr_end) {
+ /* Correct index */
+ while (unc + s_max_off[index] < up)
+ index += 1;
+
+ /* Check the current flag for zero. */
+ if (!(ch & (1 << bit))) {
+ /* Just copy byte. */
+ *up++ = *cmpr++;
+ goto next;
+ }
+
+ /* Check for boundary. */
+ if (cmpr + 1 >= cmpr_end)
+ return -EINVAL;
+
+ /* Read a short from little endian stream. */
+ pair = cmpr[1];
+ pair <<= 8;
+ pair |= cmpr[0];
+
+ cmpr += 2;
+
+ /* Translate packed information into offset and length. */
+ length = parse_pair(pair, &offset, index);
+
+ /* Check offset for boundary. */
+ if (unc + offset > up)
+ return -EINVAL;
+
+ /* Truncate the length if necessary. */
+ if (up + length >= unc_end)
+ length = unc_end - up;
+
+ /* Now we copy bytes. This is the heart of LZ algorithm. */
+ for (; length > 0; length--, up++)
+ *up = *(up - offset);
+
+next:
+ /* Advance flag bit value. */
+ bit = (bit + 1) & 7;
+
+ if (!bit) {
+ if (cmpr >= cmpr_end)
+ break;
+
+ ch = *cmpr++;
+ }
+ }
+
+ /* Return the size of uncompressed data. */
+ return up - unc;
+}
+
+/*
+ * get_lznt_ctx
+ * @level: 0 - Standard compression.
+ * !0 - Best compression, requires a lot of cpu.
+ */
+struct lznt *get_lznt_ctx(int level)
+{
+ struct lznt *r = kzalloc(level ? offsetof(struct lznt, hash)
+ : sizeof(struct lznt),
+ GFP_NOFS);
+
+ if (r)
+ r->std = !level;
+ return r;
+}
+
+/*
+ * compress_lznt - Compresses @unc into @cmpr
+ *
+ * Return:
+ * * +x - Ok, @cmpr contains 'final_compressed_size' bytes of compressed data.
+ * * 0 - Input buffer is full zero.
+ */
+size_t compress_lznt(const void *unc, size_t unc_size, void *cmpr,
+ size_t cmpr_size, struct lznt *ctx)
+{
+ int err;
+ size_t (*match)(const u8 *src, struct lznt *ctx);
+ u8 *p = cmpr;
+ u8 *end = p + cmpr_size;
+ const u8 *unc_chunk = unc;
+ const u8 *unc_end = unc_chunk + unc_size;
+ bool is_zero = true;
+
+ if (ctx->std) {
+ match = &longest_match_std;
+ memset(ctx->hash, 0, sizeof(ctx->hash));
+ } else {
+ match = &longest_match_best;
+ }
+
+ /* Compression cycle. */
+ for (; unc_chunk < unc_end; unc_chunk += LZNT_CHUNK_SIZE) {
+ cmpr_size = 0;
+ err = compress_chunk(match, unc_chunk, unc_end, p, end,
+ &cmpr_size, ctx);
+ if (err < 0)
+ return unc_size;
+
+ if (is_zero && err != LZNT_ERROR_ALL_ZEROS)
+ is_zero = false;
+
+ p += cmpr_size;
+ }
+
+ if (p <= end - 2)
+ p[0] = p[1] = 0;
+
+ return is_zero ? 0 : PtrOffset(cmpr, p);
+}
+
+/*
+ * decompress_lznt - Decompress @cmpr into @unc.
+ */
+ssize_t decompress_lznt(const void *cmpr, size_t cmpr_size, void *unc,
+ size_t unc_size)
+{
+ const u8 *cmpr_chunk = cmpr;
+ const u8 *cmpr_end = cmpr_chunk + cmpr_size;
+ u8 *unc_chunk = unc;
+ u8 *unc_end = unc_chunk + unc_size;
+ u16 chunk_hdr;
+
+ if (cmpr_size < sizeof(short))
+ return -EINVAL;
+
+ /* Read chunk header. */
+ chunk_hdr = cmpr_chunk[1];
+ chunk_hdr <<= 8;
+ chunk_hdr |= cmpr_chunk[0];
+
+ /* Loop through decompressing chunks. */
+ for (;;) {
+ size_t chunk_size_saved;
+ size_t unc_use;
+ size_t cmpr_use = 3 + (chunk_hdr & (LZNT_CHUNK_SIZE - 1));
+
+ /* Check that the chunk actually fits the supplied buffer. */
+ if (cmpr_chunk + cmpr_use > cmpr_end)
+ return -EINVAL;
+
+ /* First make sure the chunk contains compressed data. */
+ if (chunk_hdr & 0x8000) {
+ /* Decompress a chunk and return if we get an error. */
+ ssize_t err =
+ decompress_chunk(unc_chunk, unc_end,
+ cmpr_chunk + sizeof(chunk_hdr),
+ cmpr_chunk + cmpr_use);
+ if (err < 0)
+ return err;
+ unc_use = err;
+ } else {
+ /* This chunk does not contain compressed data. */
+ unc_use = unc_chunk + LZNT_CHUNK_SIZE > unc_end
+ ? unc_end - unc_chunk
+ : LZNT_CHUNK_SIZE;
+
+ if (cmpr_chunk + sizeof(chunk_hdr) + unc_use >
+ cmpr_end) {
+ return -EINVAL;
+ }
+
+ memcpy(unc_chunk, cmpr_chunk + sizeof(chunk_hdr),
+ unc_use);
+ }
+
+ /* Advance pointers. */
+ cmpr_chunk += cmpr_use;
+ unc_chunk += unc_use;
+
+ /* Check for the end of unc buffer. */
+ if (unc_chunk >= unc_end)
+ break;
+
+ /* Proceed the next chunk. */
+ if (cmpr_chunk > cmpr_end - 2)
+ break;
+
+ chunk_size_saved = LZNT_CHUNK_SIZE;
+
+ /* Read chunk header. */
+ chunk_hdr = cmpr_chunk[1];
+ chunk_hdr <<= 8;
+ chunk_hdr |= cmpr_chunk[0];
+
+ if (!chunk_hdr)
+ break;
+
+ /* Check the size of unc buffer. */
+ if (unc_use < chunk_size_saved) {
+ size_t t1 = chunk_size_saved - unc_use;
+ u8 *t2 = unc_chunk + t1;
+
+ /* 'Zero' memory. */
+ if (t2 >= unc_end)
+ break;
+
+ memset(unc_chunk, 0, t1);
+ unc_chunk = t2;
+ }
+ }
+
+ /* Check compression boundary. */
+ if (cmpr_chunk > cmpr_end)
+ return -EINVAL;
+
+ /*
+ * The unc size is just a difference between current
+ * pointer and original one.
+ */
+ return PtrOffset(unc, unc_chunk);
+}
diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c
new file mode 100644
index 000000000000..e58415d07132
--- /dev/null
+++ b/fs/ntfs3/namei.c
@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/iversion.h>
+#include <linux/namei.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+/*
+ * fill_name_de - Format NTFS_DE in @buf.
+ */
+int fill_name_de(struct ntfs_sb_info *sbi, void *buf, const struct qstr *name,
+ const struct cpu_str *uni)
+{
+ int err;
+ struct NTFS_DE *e = buf;
+ u16 data_size;
+ struct ATTR_FILE_NAME *fname = (struct ATTR_FILE_NAME *)(e + 1);
+
+#ifndef CONFIG_NTFS3_64BIT_CLUSTER
+ e->ref.high = fname->home.high = 0;
+#endif
+ if (uni) {
+#ifdef __BIG_ENDIAN
+ int ulen = uni->len;
+ __le16 *uname = fname->name;
+ const u16 *name_cpu = uni->name;
+
+ while (ulen--)
+ *uname++ = cpu_to_le16(*name_cpu++);
+#else
+ memcpy(fname->name, uni->name, uni->len * sizeof(u16));
+#endif
+ fname->name_len = uni->len;
+
+ } else {
+ /* Convert input string to unicode. */
+ err = ntfs_nls_to_utf16(sbi, name->name, name->len,
+ (struct cpu_str *)&fname->name_len,
+ NTFS_NAME_LEN, UTF16_LITTLE_ENDIAN);
+ if (err < 0)
+ return err;
+ }
+
+ fname->type = FILE_NAME_POSIX;
+ data_size = fname_full_size(fname);
+
+ e->size = cpu_to_le16(ALIGN(data_size, 8) + sizeof(struct NTFS_DE));
+ e->key_size = cpu_to_le16(data_size);
+ e->flags = 0;
+ e->res = 0;
+
+ return 0;
+}
+
+/*
+ * ntfs_lookup - inode_operations::lookup
+ */
+static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
+ u32 flags)
+{
+ struct ntfs_inode *ni = ntfs_i(dir);
+ struct cpu_str *uni = __getname();
+ struct inode *inode;
+ int err;
+
+ if (!uni)
+ inode = ERR_PTR(-ENOMEM);
+ else {
+ err = ntfs_nls_to_utf16(ni->mi.sbi, dentry->d_name.name,
+ dentry->d_name.len, uni, NTFS_NAME_LEN,
+ UTF16_HOST_ENDIAN);
+ if (err < 0)
+ inode = ERR_PTR(err);
+ else {
+ ni_lock(ni);
+ inode = dir_search_u(dir, uni, NULL);
+ ni_unlock(ni);
+ }
+ __putname(uni);
+ }
+
+ return d_splice_alias(inode, dentry);
+}
+
+/*
+ * ntfs_create - inode_operations::create
+ */
+static int ntfs_create(struct user_namespace *mnt_userns, struct inode *dir,
+ struct dentry *dentry, umode_t mode, bool excl)
+{
+ struct ntfs_inode *ni = ntfs_i(dir);
+ struct inode *inode;
+
+ ni_lock_dir(ni);
+
+ inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFREG | mode,
+ 0, NULL, 0, NULL);
+
+ ni_unlock(ni);
+
+ return IS_ERR(inode) ? PTR_ERR(inode) : 0;
+}
+
+/*
+ * ntfs_mknod
+ *
+ * inode_operations::mknod
+ */
+static int ntfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
+ struct dentry *dentry, umode_t mode, dev_t rdev)
+{
+ struct ntfs_inode *ni = ntfs_i(dir);
+ struct inode *inode;
+
+ ni_lock_dir(ni);
+
+ inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, mode, rdev,
+ NULL, 0, NULL);
+
+ ni_unlock(ni);
+
+ return IS_ERR(inode) ? PTR_ERR(inode) : 0;
+}
+
+/*
+ * ntfs_link - inode_operations::link
+ */
+static int ntfs_link(struct dentry *ode, struct inode *dir, struct dentry *de)
+{
+ int err;
+ struct inode *inode = d_inode(ode);
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ if (S_ISDIR(inode->i_mode))
+ return -EPERM;
+
+ if (inode->i_nlink >= NTFS_LINK_MAX)
+ return -EMLINK;
+
+ ni_lock_dir(ntfs_i(dir));
+ if (inode != dir)
+ ni_lock(ni);
+
+ inc_nlink(inode);
+ ihold(inode);
+
+ err = ntfs_link_inode(inode, de);
+
+ if (!err) {
+ dir->i_ctime = dir->i_mtime = inode->i_ctime =
+ current_time(dir);
+ mark_inode_dirty(inode);
+ mark_inode_dirty(dir);
+ d_instantiate(de, inode);
+ } else {
+ drop_nlink(inode);
+ iput(inode);
+ }
+
+ if (inode != dir)
+ ni_unlock(ni);
+ ni_unlock(ntfs_i(dir));
+
+ return err;
+}
+
+/*
+ * ntfs_unlink - inode_operations::unlink
+ */
+static int ntfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+ struct ntfs_inode *ni = ntfs_i(dir);
+ int err;
+
+ ni_lock_dir(ni);
+
+ err = ntfs_unlink_inode(dir, dentry);
+
+ ni_unlock(ni);
+
+ return err;
+}
+
+/*
+ * ntfs_symlink - inode_operations::symlink
+ */
+static int ntfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
+ struct dentry *dentry, const char *symname)
+{
+ u32 size = strlen(symname);
+ struct inode *inode;
+ struct ntfs_inode *ni = ntfs_i(dir);
+
+ ni_lock_dir(ni);
+
+ inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFLNK | 0777,
+ 0, symname, size, NULL);
+
+ ni_unlock(ni);
+
+ return IS_ERR(inode) ? PTR_ERR(inode) : 0;
+}
+
+/*
+ * ntfs_mkdir- inode_operations::mkdir
+ */
+static int ntfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
+ struct dentry *dentry, umode_t mode)
+{
+ struct inode *inode;
+ struct ntfs_inode *ni = ntfs_i(dir);
+
+ ni_lock_dir(ni);
+
+ inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFDIR | mode,
+ 0, NULL, 0, NULL);
+
+ ni_unlock(ni);
+
+ return IS_ERR(inode) ? PTR_ERR(inode) : 0;
+}
+
+/*
+ * ntfs_rmdir - inode_operations::rm_dir
+ */
+static int ntfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+ struct ntfs_inode *ni = ntfs_i(dir);
+ int err;
+
+ ni_lock_dir(ni);
+
+ err = ntfs_unlink_inode(dir, dentry);
+
+ ni_unlock(ni);
+
+ return err;
+}
+
+/*
+ * ntfs_rename - inode_operations::rename
+ */
+static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir,
+ struct dentry *dentry, struct inode *new_dir,
+ struct dentry *new_dentry, u32 flags)
+{
+ int err;
+ struct super_block *sb = dir->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct ntfs_inode *dir_ni = ntfs_i(dir);
+ struct ntfs_inode *new_dir_ni = ntfs_i(new_dir);
+ struct inode *inode = d_inode(dentry);
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct inode *new_inode = d_inode(new_dentry);
+ struct NTFS_DE *de, *new_de;
+ bool is_same, is_bad;
+ /*
+ * de - memory of PATH_MAX bytes:
+ * [0-1024) - original name (dentry->d_name)
+ * [1024-2048) - paired to original name, usually DOS variant of dentry->d_name
+ * [2048-3072) - new name (new_dentry->d_name)
+ */
+ static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + SIZEOF_RESIDENT < 1024);
+ static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + sizeof(struct NTFS_DE) <
+ 1024);
+ static_assert(PATH_MAX >= 4 * 1024);
+
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
+ is_same = dentry->d_name.len == new_dentry->d_name.len &&
+ !memcmp(dentry->d_name.name, new_dentry->d_name.name,
+ dentry->d_name.len);
+
+ if (is_same && dir == new_dir) {
+ /* Nothing to do. */
+ return 0;
+ }
+
+ if (ntfs_is_meta_file(sbi, inode->i_ino)) {
+ /* Should we print an error? */
+ return -EINVAL;
+ }
+
+ if (new_inode) {
+ /* Target name exists. Unlink it. */
+ dget(new_dentry);
+ ni_lock_dir(new_dir_ni);
+ err = ntfs_unlink_inode(new_dir, new_dentry);
+ ni_unlock(new_dir_ni);
+ dput(new_dentry);
+ if (err)
+ return err;
+ }
+
+ /* Allocate PATH_MAX bytes. */
+ de = __getname();
+ if (!de)
+ return -ENOMEM;
+
+ /* Translate dentry->d_name into unicode form. */
+ err = fill_name_de(sbi, de, &dentry->d_name, NULL);
+ if (err < 0)
+ goto out;
+
+ if (is_same) {
+ /* Reuse 'de'. */
+ new_de = de;
+ } else {
+ /* Translate new_dentry->d_name into unicode form. */
+ new_de = Add2Ptr(de, 2048);
+ err = fill_name_de(sbi, new_de, &new_dentry->d_name, NULL);
+ if (err < 0)
+ goto out;
+ }
+
+ ni_lock_dir(dir_ni);
+ ni_lock(ni);
+
+ is_bad = false;
+ err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de, &is_bad);
+ if (is_bad) {
+ /* Restore after failed rename failed too. */
+ make_bad_inode(inode);
+ ntfs_inode_err(inode, "failed to undo rename");
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+ } else if (!err) {
+ inode->i_ctime = dir->i_ctime = dir->i_mtime =
+ current_time(dir);
+ mark_inode_dirty(inode);
+ mark_inode_dirty(dir);
+ if (dir != new_dir) {
+ new_dir->i_mtime = new_dir->i_ctime = dir->i_ctime;
+ mark_inode_dirty(new_dir);
+ }
+
+ if (IS_DIRSYNC(dir))
+ ntfs_sync_inode(dir);
+
+ if (IS_DIRSYNC(new_dir))
+ ntfs_sync_inode(inode);
+ }
+
+ ni_unlock(ni);
+ ni_unlock(dir_ni);
+out:
+ __putname(de);
+ return err;
+}
+
+struct dentry *ntfs3_get_parent(struct dentry *child)
+{
+ struct inode *inode = d_inode(child);
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ struct ATTR_LIST_ENTRY *le = NULL;
+ struct ATTRIB *attr = NULL;
+ struct ATTR_FILE_NAME *fname;
+
+ while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
+ NULL))) {
+ fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
+ if (!fname)
+ continue;
+
+ return d_obtain_alias(
+ ntfs_iget5(inode->i_sb, &fname->home, NULL));
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+
+// clang-format off
+const struct inode_operations ntfs_dir_inode_operations = {
+ .lookup = ntfs_lookup,
+ .create = ntfs_create,
+ .link = ntfs_link,
+ .unlink = ntfs_unlink,
+ .symlink = ntfs_symlink,
+ .mkdir = ntfs_mkdir,
+ .rmdir = ntfs_rmdir,
+ .mknod = ntfs_mknod,
+ .rename = ntfs_rename,
+ .permission = ntfs_permission,
+ .get_acl = ntfs_get_acl,
+ .set_acl = ntfs_set_acl,
+ .setattr = ntfs3_setattr,
+ .getattr = ntfs_getattr,
+ .listxattr = ntfs_listxattr,
+ .fiemap = ntfs_fiemap,
+};
+
+const struct inode_operations ntfs_special_inode_operations = {
+ .setattr = ntfs3_setattr,
+ .getattr = ntfs_getattr,
+ .listxattr = ntfs_listxattr,
+ .get_acl = ntfs_get_acl,
+ .set_acl = ntfs_set_acl,
+};
+// clang-format on
diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h
new file mode 100644
index 000000000000..6bb3e595263b
--- /dev/null
+++ b/fs/ntfs3/ntfs.h
@@ -0,0 +1,1216 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ * on-disk ntfs structs
+ */
+
+// clang-format off
+#ifndef _LINUX_NTFS3_NTFS_H
+#define _LINUX_NTFS3_NTFS_H
+
+/* TODO: Check 4K MFT record and 512 bytes cluster. */
+
+/* Activate this define to use binary search in indexes. */
+#define NTFS3_INDEX_BINARY_SEARCH
+
+/* Check each run for marked clusters. */
+#define NTFS3_CHECK_FREE_CLST
+
+#define NTFS_NAME_LEN 255
+
+/* ntfs.sys used 500 maximum links on-disk struct allows up to 0xffff. */
+#define NTFS_LINK_MAX 0x400
+//#define NTFS_LINK_MAX 0xffff
+
+/*
+ * Activate to use 64 bit clusters instead of 32 bits in ntfs.sys.
+ * Logical and virtual cluster number if needed, may be
+ * redefined to use 64 bit value.
+ */
+//#define CONFIG_NTFS3_64BIT_CLUSTER
+
+#define NTFS_LZNT_MAX_CLUSTER 4096
+#define NTFS_LZNT_CUNIT 4
+#define NTFS_LZNT_CLUSTERS (1u<<NTFS_LZNT_CUNIT)
+
+struct GUID {
+ __le32 Data1;
+ __le16 Data2;
+ __le16 Data3;
+ u8 Data4[8];
+};
+
+/*
+ * This struct repeats layout of ATTR_FILE_NAME
+ * at offset 0x40.
+ * It used to store global constants NAME_MFT/NAME_MIRROR...
+ * most constant names are shorter than 10.
+ */
+struct cpu_str {
+ u8 len;
+ u8 unused;
+ u16 name[10];
+};
+
+struct le_str {
+ u8 len;
+ u8 unused;
+ __le16 name[];
+};
+
+static_assert(SECTOR_SHIFT == 9);
+
+#ifdef CONFIG_NTFS3_64BIT_CLUSTER
+typedef u64 CLST;
+static_assert(sizeof(size_t) == 8);
+#else
+typedef u32 CLST;
+#endif
+
+#define SPARSE_LCN64 ((u64)-1)
+#define SPARSE_LCN ((CLST)-1)
+#define RESIDENT_LCN ((CLST)-2)
+#define COMPRESSED_LCN ((CLST)-3)
+
+#define COMPRESSION_UNIT 4
+#define COMPRESS_MAX_CLUSTER 0x1000
+#define MFT_INCREASE_CHUNK 1024
+
+enum RECORD_NUM {
+ MFT_REC_MFT = 0,
+ MFT_REC_MIRR = 1,
+ MFT_REC_LOG = 2,
+ MFT_REC_VOL = 3,
+ MFT_REC_ATTR = 4,
+ MFT_REC_ROOT = 5,
+ MFT_REC_BITMAP = 6,
+ MFT_REC_BOOT = 7,
+ MFT_REC_BADCLUST = 8,
+ //MFT_REC_QUOTA = 9,
+ MFT_REC_SECURE = 9, // NTFS 3.0
+ MFT_REC_UPCASE = 10,
+ MFT_REC_EXTEND = 11, // NTFS 3.0
+ MFT_REC_RESERVED = 11,
+ MFT_REC_FREE = 16,
+ MFT_REC_USER = 24,
+};
+
+enum ATTR_TYPE {
+ ATTR_ZERO = cpu_to_le32(0x00),
+ ATTR_STD = cpu_to_le32(0x10),
+ ATTR_LIST = cpu_to_le32(0x20),
+ ATTR_NAME = cpu_to_le32(0x30),
+ // ATTR_VOLUME_VERSION on Nt4
+ ATTR_ID = cpu_to_le32(0x40),
+ ATTR_SECURE = cpu_to_le32(0x50),
+ ATTR_LABEL = cpu_to_le32(0x60),
+ ATTR_VOL_INFO = cpu_to_le32(0x70),
+ ATTR_DATA = cpu_to_le32(0x80),
+ ATTR_ROOT = cpu_to_le32(0x90),
+ ATTR_ALLOC = cpu_to_le32(0xA0),
+ ATTR_BITMAP = cpu_to_le32(0xB0),
+ // ATTR_SYMLINK on Nt4
+ ATTR_REPARSE = cpu_to_le32(0xC0),
+ ATTR_EA_INFO = cpu_to_le32(0xD0),
+ ATTR_EA = cpu_to_le32(0xE0),
+ ATTR_PROPERTYSET = cpu_to_le32(0xF0),
+ ATTR_LOGGED_UTILITY_STREAM = cpu_to_le32(0x100),
+ ATTR_END = cpu_to_le32(0xFFFFFFFF)
+};
+
+static_assert(sizeof(enum ATTR_TYPE) == 4);
+
+enum FILE_ATTRIBUTE {
+ FILE_ATTRIBUTE_READONLY = cpu_to_le32(0x00000001),
+ FILE_ATTRIBUTE_HIDDEN = cpu_to_le32(0x00000002),
+ FILE_ATTRIBUTE_SYSTEM = cpu_to_le32(0x00000004),
+ FILE_ATTRIBUTE_ARCHIVE = cpu_to_le32(0x00000020),
+ FILE_ATTRIBUTE_DEVICE = cpu_to_le32(0x00000040),
+ FILE_ATTRIBUTE_TEMPORARY = cpu_to_le32(0x00000100),
+ FILE_ATTRIBUTE_SPARSE_FILE = cpu_to_le32(0x00000200),
+ FILE_ATTRIBUTE_REPARSE_POINT = cpu_to_le32(0x00000400),
+ FILE_ATTRIBUTE_COMPRESSED = cpu_to_le32(0x00000800),
+ FILE_ATTRIBUTE_OFFLINE = cpu_to_le32(0x00001000),
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = cpu_to_le32(0x00002000),
+ FILE_ATTRIBUTE_ENCRYPTED = cpu_to_le32(0x00004000),
+ FILE_ATTRIBUTE_VALID_FLAGS = cpu_to_le32(0x00007fb7),
+ FILE_ATTRIBUTE_DIRECTORY = cpu_to_le32(0x10000000),
+};
+
+static_assert(sizeof(enum FILE_ATTRIBUTE) == 4);
+
+extern const struct cpu_str NAME_MFT;
+extern const struct cpu_str NAME_MIRROR;
+extern const struct cpu_str NAME_LOGFILE;
+extern const struct cpu_str NAME_VOLUME;
+extern const struct cpu_str NAME_ATTRDEF;
+extern const struct cpu_str NAME_ROOT;
+extern const struct cpu_str NAME_BITMAP;
+extern const struct cpu_str NAME_BOOT;
+extern const struct cpu_str NAME_BADCLUS;
+extern const struct cpu_str NAME_QUOTA;
+extern const struct cpu_str NAME_SECURE;
+extern const struct cpu_str NAME_UPCASE;
+extern const struct cpu_str NAME_EXTEND;
+extern const struct cpu_str NAME_OBJID;
+extern const struct cpu_str NAME_REPARSE;
+extern const struct cpu_str NAME_USNJRNL;
+
+extern const __le16 I30_NAME[4];
+extern const __le16 SII_NAME[4];
+extern const __le16 SDH_NAME[4];
+extern const __le16 SO_NAME[2];
+extern const __le16 SQ_NAME[2];
+extern const __le16 SR_NAME[2];
+
+extern const __le16 BAD_NAME[4];
+extern const __le16 SDS_NAME[4];
+extern const __le16 WOF_NAME[17]; /* WofCompressedData */
+
+/* MFT record number structure. */
+struct MFT_REF {
+ __le32 low; // The low part of the number.
+ __le16 high; // The high part of the number.
+ __le16 seq; // The sequence number of MFT record.
+};
+
+static_assert(sizeof(__le64) == sizeof(struct MFT_REF));
+
+static inline CLST ino_get(const struct MFT_REF *ref)
+{
+#ifdef CONFIG_NTFS3_64BIT_CLUSTER
+ return le32_to_cpu(ref->low) | ((u64)le16_to_cpu(ref->high) << 32);
+#else
+ return le32_to_cpu(ref->low);
+#endif
+}
+
+struct NTFS_BOOT {
+ u8 jump_code[3]; // 0x00: Jump to boot code.
+ u8 system_id[8]; // 0x03: System ID, equals "NTFS "
+
+ // NOTE: This member is not aligned(!)
+ // bytes_per_sector[0] must be 0.
+ // bytes_per_sector[1] must be multiplied by 256.
+ u8 bytes_per_sector[2]; // 0x0B: Bytes per sector.
+
+ u8 sectors_per_clusters;// 0x0D: Sectors per cluster.
+ u8 unused1[7];
+ u8 media_type; // 0x15: Media type (0xF8 - harddisk)
+ u8 unused2[2];
+ __le16 sct_per_track; // 0x18: number of sectors per track.
+ __le16 heads; // 0x1A: number of heads per cylinder.
+ __le32 hidden_sectors; // 0x1C: number of 'hidden' sectors.
+ u8 unused3[4];
+ u8 bios_drive_num; // 0x24: BIOS drive number =0x80.
+ u8 unused4;
+ u8 signature_ex; // 0x26: Extended BOOT signature =0x80.
+ u8 unused5;
+ __le64 sectors_per_volume;// 0x28: Size of volume in sectors.
+ __le64 mft_clst; // 0x30: First cluster of $MFT
+ __le64 mft2_clst; // 0x38: First cluster of $MFTMirr
+ s8 record_size; // 0x40: Size of MFT record in clusters(sectors).
+ u8 unused6[3];
+ s8 index_size; // 0x44: Size of INDX record in clusters(sectors).
+ u8 unused7[3];
+ __le64 serial_num; // 0x48: Volume serial number
+ __le32 check_sum; // 0x50: Simple additive checksum of all
+ // of the u32's which precede the 'check_sum'.
+
+ u8 boot_code[0x200 - 0x50 - 2 - 4]; // 0x54:
+ u8 boot_magic[2]; // 0x1FE: Boot signature =0x55 + 0xAA
+};
+
+static_assert(sizeof(struct NTFS_BOOT) == 0x200);
+
+enum NTFS_SIGNATURE {
+ NTFS_FILE_SIGNATURE = cpu_to_le32(0x454C4946), // 'FILE'
+ NTFS_INDX_SIGNATURE = cpu_to_le32(0x58444E49), // 'INDX'
+ NTFS_CHKD_SIGNATURE = cpu_to_le32(0x444B4843), // 'CHKD'
+ NTFS_RSTR_SIGNATURE = cpu_to_le32(0x52545352), // 'RSTR'
+ NTFS_RCRD_SIGNATURE = cpu_to_le32(0x44524352), // 'RCRD'
+ NTFS_BAAD_SIGNATURE = cpu_to_le32(0x44414142), // 'BAAD'
+ NTFS_HOLE_SIGNATURE = cpu_to_le32(0x454C4F48), // 'HOLE'
+ NTFS_FFFF_SIGNATURE = cpu_to_le32(0xffffffff),
+};
+
+static_assert(sizeof(enum NTFS_SIGNATURE) == 4);
+
+/* MFT Record header structure. */
+struct NTFS_RECORD_HEADER {
+ /* Record magic number, equals 'FILE'/'INDX'/'RSTR'/'RCRD'. */
+ enum NTFS_SIGNATURE sign; // 0x00:
+ __le16 fix_off; // 0x04:
+ __le16 fix_num; // 0x06:
+ __le64 lsn; // 0x08: Log file sequence number,
+};
+
+static_assert(sizeof(struct NTFS_RECORD_HEADER) == 0x10);
+
+static inline int is_baad(const struct NTFS_RECORD_HEADER *hdr)
+{
+ return hdr->sign == NTFS_BAAD_SIGNATURE;
+}
+
+/* Possible bits in struct MFT_REC.flags. */
+enum RECORD_FLAG {
+ RECORD_FLAG_IN_USE = cpu_to_le16(0x0001),
+ RECORD_FLAG_DIR = cpu_to_le16(0x0002),
+ RECORD_FLAG_SYSTEM = cpu_to_le16(0x0004),
+ RECORD_FLAG_UNKNOWN = cpu_to_le16(0x0008),
+};
+
+/* MFT Record structure. */
+struct MFT_REC {
+ struct NTFS_RECORD_HEADER rhdr; // 'FILE'
+
+ __le16 seq; // 0x10: Sequence number for this record.
+ __le16 hard_links; // 0x12: The number of hard links to record.
+ __le16 attr_off; // 0x14: Offset to attributes.
+ __le16 flags; // 0x16: See RECORD_FLAG.
+ __le32 used; // 0x18: The size of used part.
+ __le32 total; // 0x1C: Total record size.
+
+ struct MFT_REF parent_ref; // 0x20: Parent MFT record.
+ __le16 next_attr_id; // 0x28: The next attribute Id.
+
+ __le16 res; // 0x2A: High part of MFT record?
+ __le32 mft_record; // 0x2C: Current MFT record number.
+ __le16 fixups[]; // 0x30:
+};
+
+#define MFTRECORD_FIXUP_OFFSET_1 offsetof(struct MFT_REC, res)
+#define MFTRECORD_FIXUP_OFFSET_3 offsetof(struct MFT_REC, fixups)
+
+static_assert(MFTRECORD_FIXUP_OFFSET_1 == 0x2A);
+static_assert(MFTRECORD_FIXUP_OFFSET_3 == 0x30);
+
+static inline bool is_rec_base(const struct MFT_REC *rec)
+{
+ const struct MFT_REF *r = &rec->parent_ref;
+
+ return !r->low && !r->high && !r->seq;
+}
+
+static inline bool is_mft_rec5(const struct MFT_REC *rec)
+{
+ return le16_to_cpu(rec->rhdr.fix_off) >=
+ offsetof(struct MFT_REC, fixups);
+}
+
+static inline bool is_rec_inuse(const struct MFT_REC *rec)
+{
+ return rec->flags & RECORD_FLAG_IN_USE;
+}
+
+static inline bool clear_rec_inuse(struct MFT_REC *rec)
+{
+ return rec->flags &= ~RECORD_FLAG_IN_USE;
+}
+
+/* Possible values of ATTR_RESIDENT.flags */
+#define RESIDENT_FLAG_INDEXED 0x01
+
+struct ATTR_RESIDENT {
+ __le32 data_size; // 0x10: The size of data.
+ __le16 data_off; // 0x14: Offset to data.
+ u8 flags; // 0x16: Resident flags ( 1 - indexed ).
+ u8 res; // 0x17:
+}; // sizeof() = 0x18
+
+struct ATTR_NONRESIDENT {
+ __le64 svcn; // 0x10: Starting VCN of this segment.
+ __le64 evcn; // 0x18: End VCN of this segment.
+ __le16 run_off; // 0x20: Offset to packed runs.
+ // Unit of Compression size for this stream, expressed
+ // as a log of the cluster size.
+ //
+ // 0 means file is not compressed
+ // 1, 2, 3, and 4 are potentially legal values if the
+ // stream is compressed, however the implementation
+ // may only choose to use 4, or possibly 3. Note
+ // that 4 means cluster size time 16. If convenient
+ // the implementation may wish to accept a
+ // reasonable range of legal values here (1-5?),
+ // even if the implementation only generates
+ // a smaller set of values itself.
+ u8 c_unit; // 0x22:
+ u8 res1[5]; // 0x23:
+ __le64 alloc_size; // 0x28: The allocated size of attribute in bytes.
+ // (multiple of cluster size)
+ __le64 data_size; // 0x30: The size of attribute in bytes <= alloc_size.
+ __le64 valid_size; // 0x38: The size of valid part in bytes <= data_size.
+ __le64 total_size; // 0x40: The sum of the allocated clusters for a file.
+ // (present only for the first segment (0 == vcn)
+ // of compressed attribute)
+
+}; // sizeof()=0x40 or 0x48 (if compressed)
+
+/* Possible values of ATTRIB.flags: */
+#define ATTR_FLAG_COMPRESSED cpu_to_le16(0x0001)
+#define ATTR_FLAG_COMPRESSED_MASK cpu_to_le16(0x00FF)
+#define ATTR_FLAG_ENCRYPTED cpu_to_le16(0x4000)
+#define ATTR_FLAG_SPARSED cpu_to_le16(0x8000)
+
+struct ATTRIB {
+ enum ATTR_TYPE type; // 0x00: The type of this attribute.
+ __le32 size; // 0x04: The size of this attribute.
+ u8 non_res; // 0x08: Is this attribute non-resident?
+ u8 name_len; // 0x09: This attribute name length.
+ __le16 name_off; // 0x0A: Offset to the attribute name.
+ __le16 flags; // 0x0C: See ATTR_FLAG_XXX.
+ __le16 id; // 0x0E: Unique id (per record).
+
+ union {
+ struct ATTR_RESIDENT res; // 0x10
+ struct ATTR_NONRESIDENT nres; // 0x10
+ };
+};
+
+/* Define attribute sizes. */
+#define SIZEOF_RESIDENT 0x18
+#define SIZEOF_NONRESIDENT_EX 0x48
+#define SIZEOF_NONRESIDENT 0x40
+
+#define SIZEOF_RESIDENT_LE cpu_to_le16(0x18)
+#define SIZEOF_NONRESIDENT_EX_LE cpu_to_le16(0x48)
+#define SIZEOF_NONRESIDENT_LE cpu_to_le16(0x40)
+
+static inline u64 attr_ondisk_size(const struct ATTRIB *attr)
+{
+ return attr->non_res ? ((attr->flags &
+ (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) ?
+ le64_to_cpu(attr->nres.total_size) :
+ le64_to_cpu(attr->nres.alloc_size))
+ : ALIGN(le32_to_cpu(attr->res.data_size), 8);
+}
+
+static inline u64 attr_size(const struct ATTRIB *attr)
+{
+ return attr->non_res ? le64_to_cpu(attr->nres.data_size) :
+ le32_to_cpu(attr->res.data_size);
+}
+
+static inline bool is_attr_encrypted(const struct ATTRIB *attr)
+{
+ return attr->flags & ATTR_FLAG_ENCRYPTED;
+}
+
+static inline bool is_attr_sparsed(const struct ATTRIB *attr)
+{
+ return attr->flags & ATTR_FLAG_SPARSED;
+}
+
+static inline bool is_attr_compressed(const struct ATTRIB *attr)
+{
+ return attr->flags & ATTR_FLAG_COMPRESSED;
+}
+
+static inline bool is_attr_ext(const struct ATTRIB *attr)
+{
+ return attr->flags & (ATTR_FLAG_SPARSED | ATTR_FLAG_COMPRESSED);
+}
+
+static inline bool is_attr_indexed(const struct ATTRIB *attr)
+{
+ return !attr->non_res && (attr->res.flags & RESIDENT_FLAG_INDEXED);
+}
+
+static inline __le16 const *attr_name(const struct ATTRIB *attr)
+{
+ return Add2Ptr(attr, le16_to_cpu(attr->name_off));
+}
+
+static inline u64 attr_svcn(const struct ATTRIB *attr)
+{
+ return attr->non_res ? le64_to_cpu(attr->nres.svcn) : 0;
+}
+
+/* The size of resident attribute by its resident size. */
+#define BYTES_PER_RESIDENT(b) (0x18 + (b))
+
+static_assert(sizeof(struct ATTRIB) == 0x48);
+static_assert(sizeof(((struct ATTRIB *)NULL)->res) == 0x08);
+static_assert(sizeof(((struct ATTRIB *)NULL)->nres) == 0x38);
+
+static inline void *resident_data_ex(const struct ATTRIB *attr, u32 datasize)
+{
+ u32 asize, rsize;
+ u16 off;
+
+ if (attr->non_res)
+ return NULL;
+
+ asize = le32_to_cpu(attr->size);
+ off = le16_to_cpu(attr->res.data_off);
+
+ if (asize < datasize + off)
+ return NULL;
+
+ rsize = le32_to_cpu(attr->res.data_size);
+ if (rsize < datasize)
+ return NULL;
+
+ return Add2Ptr(attr, off);
+}
+
+static inline void *resident_data(const struct ATTRIB *attr)
+{
+ return Add2Ptr(attr, le16_to_cpu(attr->res.data_off));
+}
+
+static inline void *attr_run(const struct ATTRIB *attr)
+{
+ return Add2Ptr(attr, le16_to_cpu(attr->nres.run_off));
+}
+
+/* Standard information attribute (0x10). */
+struct ATTR_STD_INFO {
+ __le64 cr_time; // 0x00: File creation file.
+ __le64 m_time; // 0x08: File modification time.
+ __le64 c_time; // 0x10: Last time any attribute was modified.
+ __le64 a_time; // 0x18: File last access time.
+ enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more.
+ __le32 max_ver_num; // 0x24: Maximum Number of Versions.
+ __le32 ver_num; // 0x28: Version Number.
+ __le32 class_id; // 0x2C: Class Id from bidirectional Class Id index.
+};
+
+static_assert(sizeof(struct ATTR_STD_INFO) == 0x30);
+
+#define SECURITY_ID_INVALID 0x00000000
+#define SECURITY_ID_FIRST 0x00000100
+
+struct ATTR_STD_INFO5 {
+ __le64 cr_time; // 0x00: File creation file.
+ __le64 m_time; // 0x08: File modification time.
+ __le64 c_time; // 0x10: Last time any attribute was modified.
+ __le64 a_time; // 0x18: File last access time.
+ enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more.
+ __le32 max_ver_num; // 0x24: Maximum Number of Versions.
+ __le32 ver_num; // 0x28: Version Number.
+ __le32 class_id; // 0x2C: Class Id from bidirectional Class Id index.
+
+ __le32 owner_id; // 0x30: Owner Id of the user owning the file.
+ __le32 security_id; // 0x34: The Security Id is a key in the $SII Index and $SDS.
+ __le64 quota_charge; // 0x38:
+ __le64 usn; // 0x40: Last Update Sequence Number of the file. This is a direct
+ // index into the file $UsnJrnl. If zero, the USN Journal is
+ // disabled.
+};
+
+static_assert(sizeof(struct ATTR_STD_INFO5) == 0x48);
+
+/* Attribute list entry structure (0x20) */
+struct ATTR_LIST_ENTRY {
+ enum ATTR_TYPE type; // 0x00: The type of attribute.
+ __le16 size; // 0x04: The size of this record.
+ u8 name_len; // 0x06: The length of attribute name.
+ u8 name_off; // 0x07: The offset to attribute name.
+ __le64 vcn; // 0x08: Starting VCN of this attribute.
+ struct MFT_REF ref; // 0x10: MFT record number with attribute.
+ __le16 id; // 0x18: struct ATTRIB ID.
+ __le16 name[3]; // 0x1A: Just to align. To get real name can use bNameOffset.
+
+}; // sizeof(0x20)
+
+static_assert(sizeof(struct ATTR_LIST_ENTRY) == 0x20);
+
+static inline u32 le_size(u8 name_len)
+{
+ return ALIGN(offsetof(struct ATTR_LIST_ENTRY, name) +
+ name_len * sizeof(short), 8);
+}
+
+/* Returns 0 if 'attr' has the same type and name. */
+static inline int le_cmp(const struct ATTR_LIST_ENTRY *le,
+ const struct ATTRIB *attr)
+{
+ return le->type != attr->type || le->name_len != attr->name_len ||
+ (!le->name_len &&
+ memcmp(Add2Ptr(le, le->name_off),
+ Add2Ptr(attr, le16_to_cpu(attr->name_off)),
+ le->name_len * sizeof(short)));
+}
+
+static inline __le16 const *le_name(const struct ATTR_LIST_ENTRY *le)
+{
+ return Add2Ptr(le, le->name_off);
+}
+
+/* File name types (the field type in struct ATTR_FILE_NAME). */
+#define FILE_NAME_POSIX 0
+#define FILE_NAME_UNICODE 1
+#define FILE_NAME_DOS 2
+#define FILE_NAME_UNICODE_AND_DOS (FILE_NAME_DOS | FILE_NAME_UNICODE)
+
+/* Filename attribute structure (0x30). */
+struct NTFS_DUP_INFO {
+ __le64 cr_time; // 0x00: File creation file.
+ __le64 m_time; // 0x08: File modification time.
+ __le64 c_time; // 0x10: Last time any attribute was modified.
+ __le64 a_time; // 0x18: File last access time.
+ __le64 alloc_size; // 0x20: Data attribute allocated size, multiple of cluster size.
+ __le64 data_size; // 0x28: Data attribute size <= Dataalloc_size.
+ enum FILE_ATTRIBUTE fa; // 0x30: Standard DOS attributes & more.
+ __le16 ea_size; // 0x34: Packed EAs.
+ __le16 reparse; // 0x36: Used by Reparse.
+
+}; // 0x38
+
+struct ATTR_FILE_NAME {
+ struct MFT_REF home; // 0x00: MFT record for directory.
+ struct NTFS_DUP_INFO dup;// 0x08:
+ u8 name_len; // 0x40: File name length in words.
+ u8 type; // 0x41: File name type.
+ __le16 name[]; // 0x42: File name.
+};
+
+static_assert(sizeof(((struct ATTR_FILE_NAME *)NULL)->dup) == 0x38);
+static_assert(offsetof(struct ATTR_FILE_NAME, name) == 0x42);
+#define SIZEOF_ATTRIBUTE_FILENAME 0x44
+#define SIZEOF_ATTRIBUTE_FILENAME_MAX (0x42 + 255 * 2)
+
+static inline struct ATTRIB *attr_from_name(struct ATTR_FILE_NAME *fname)
+{
+ return (struct ATTRIB *)((char *)fname - SIZEOF_RESIDENT);
+}
+
+static inline u16 fname_full_size(const struct ATTR_FILE_NAME *fname)
+{
+ /* Don't return struct_size(fname, name, fname->name_len); */
+ return offsetof(struct ATTR_FILE_NAME, name) +
+ fname->name_len * sizeof(short);
+}
+
+static inline u8 paired_name(u8 type)
+{
+ if (type == FILE_NAME_UNICODE)
+ return FILE_NAME_DOS;
+ if (type == FILE_NAME_DOS)
+ return FILE_NAME_UNICODE;
+ return FILE_NAME_POSIX;
+}
+
+/* Index entry defines ( the field flags in NtfsDirEntry ). */
+#define NTFS_IE_HAS_SUBNODES cpu_to_le16(1)
+#define NTFS_IE_LAST cpu_to_le16(2)
+
+/* Directory entry structure. */
+struct NTFS_DE {
+ union {
+ struct MFT_REF ref; // 0x00: MFT record number with this file.
+ struct {
+ __le16 data_off; // 0x00:
+ __le16 data_size; // 0x02:
+ __le32 res; // 0x04: Must be 0.
+ } view;
+ };
+ __le16 size; // 0x08: The size of this entry.
+ __le16 key_size; // 0x0A: The size of File name length in bytes + 0x42.
+ __le16 flags; // 0x0C: Entry flags: NTFS_IE_XXX.
+ __le16 res; // 0x0E:
+
+ // Here any indexed attribute can be placed.
+ // One of them is:
+ // struct ATTR_FILE_NAME AttrFileName;
+ //
+
+ // The last 8 bytes of this structure contains
+ // the VBN of subnode.
+ // !!! Note !!!
+ // This field is presented only if (flags & NTFS_IE_HAS_SUBNODES)
+ // __le64 vbn;
+};
+
+static_assert(sizeof(struct NTFS_DE) == 0x10);
+
+static inline void de_set_vbn_le(struct NTFS_DE *e, __le64 vcn)
+{
+ __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64));
+
+ *v = vcn;
+}
+
+static inline void de_set_vbn(struct NTFS_DE *e, CLST vcn)
+{
+ __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64));
+
+ *v = cpu_to_le64(vcn);
+}
+
+static inline __le64 de_get_vbn_le(const struct NTFS_DE *e)
+{
+ return *(__le64 *)Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64));
+}
+
+static inline CLST de_get_vbn(const struct NTFS_DE *e)
+{
+ __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64));
+
+ return le64_to_cpu(*v);
+}
+
+static inline struct NTFS_DE *de_get_next(const struct NTFS_DE *e)
+{
+ return Add2Ptr(e, le16_to_cpu(e->size));
+}
+
+static inline struct ATTR_FILE_NAME *de_get_fname(const struct NTFS_DE *e)
+{
+ return le16_to_cpu(e->key_size) >= SIZEOF_ATTRIBUTE_FILENAME ?
+ Add2Ptr(e, sizeof(struct NTFS_DE)) :
+ NULL;
+}
+
+static inline bool de_is_last(const struct NTFS_DE *e)
+{
+ return e->flags & NTFS_IE_LAST;
+}
+
+static inline bool de_has_vcn(const struct NTFS_DE *e)
+{
+ return e->flags & NTFS_IE_HAS_SUBNODES;
+}
+
+static inline bool de_has_vcn_ex(const struct NTFS_DE *e)
+{
+ return (e->flags & NTFS_IE_HAS_SUBNODES) &&
+ (u64)(-1) != *((u64 *)Add2Ptr(e, le16_to_cpu(e->size) -
+ sizeof(__le64)));
+}
+
+#define MAX_BYTES_PER_NAME_ENTRY \
+ ALIGN(sizeof(struct NTFS_DE) + \
+ offsetof(struct ATTR_FILE_NAME, name) + \
+ NTFS_NAME_LEN * sizeof(short), 8)
+
+struct INDEX_HDR {
+ __le32 de_off; // 0x00: The offset from the start of this structure
+ // to the first NTFS_DE.
+ __le32 used; // 0x04: The size of this structure plus all
+ // entries (quad-word aligned).
+ __le32 total; // 0x08: The allocated size of for this structure plus all entries.
+ u8 flags; // 0x0C: 0x00 = Small directory, 0x01 = Large directory.
+ u8 res[3];
+
+ //
+ // de_off + used <= total
+ //
+};
+
+static_assert(sizeof(struct INDEX_HDR) == 0x10);
+
+static inline struct NTFS_DE *hdr_first_de(const struct INDEX_HDR *hdr)
+{
+ u32 de_off = le32_to_cpu(hdr->de_off);
+ u32 used = le32_to_cpu(hdr->used);
+ struct NTFS_DE *e = Add2Ptr(hdr, de_off);
+ u16 esize;
+
+ if (de_off >= used || de_off >= le32_to_cpu(hdr->total))
+ return NULL;
+
+ esize = le16_to_cpu(e->size);
+ if (esize < sizeof(struct NTFS_DE) || de_off + esize > used)
+ return NULL;
+
+ return e;
+}
+
+static inline struct NTFS_DE *hdr_next_de(const struct INDEX_HDR *hdr,
+ const struct NTFS_DE *e)
+{
+ size_t off = PtrOffset(hdr, e);
+ u32 used = le32_to_cpu(hdr->used);
+ u16 esize;
+
+ if (off >= used)
+ return NULL;
+
+ esize = le16_to_cpu(e->size);
+
+ if (esize < sizeof(struct NTFS_DE) ||
+ off + esize + sizeof(struct NTFS_DE) > used)
+ return NULL;
+
+ return Add2Ptr(e, esize);
+}
+
+static inline bool hdr_has_subnode(const struct INDEX_HDR *hdr)
+{
+ return hdr->flags & 1;
+}
+
+struct INDEX_BUFFER {
+ struct NTFS_RECORD_HEADER rhdr; // 'INDX'
+ __le64 vbn; // 0x10: vcn if index >= cluster or vsn id index < cluster
+ struct INDEX_HDR ihdr; // 0x18:
+};
+
+static_assert(sizeof(struct INDEX_BUFFER) == 0x28);
+
+static inline bool ib_is_empty(const struct INDEX_BUFFER *ib)
+{
+ const struct NTFS_DE *first = hdr_first_de(&ib->ihdr);
+
+ return !first || de_is_last(first);
+}
+
+static inline bool ib_is_leaf(const struct INDEX_BUFFER *ib)
+{
+ return !(ib->ihdr.flags & 1);
+}
+
+/* Index root structure ( 0x90 ). */
+enum COLLATION_RULE {
+ NTFS_COLLATION_TYPE_BINARY = cpu_to_le32(0),
+ // $I30
+ NTFS_COLLATION_TYPE_FILENAME = cpu_to_le32(0x01),
+ // $SII of $Secure and $Q of Quota
+ NTFS_COLLATION_TYPE_UINT = cpu_to_le32(0x10),
+ // $O of Quota
+ NTFS_COLLATION_TYPE_SID = cpu_to_le32(0x11),
+ // $SDH of $Secure
+ NTFS_COLLATION_TYPE_SECURITY_HASH = cpu_to_le32(0x12),
+ // $O of ObjId and "$R" for Reparse
+ NTFS_COLLATION_TYPE_UINTS = cpu_to_le32(0x13)
+};
+
+static_assert(sizeof(enum COLLATION_RULE) == 4);
+
+//
+struct INDEX_ROOT {
+ enum ATTR_TYPE type; // 0x00: The type of attribute to index on.
+ enum COLLATION_RULE rule; // 0x04: The rule.
+ __le32 index_block_size;// 0x08: The size of index record.
+ u8 index_block_clst; // 0x0C: The number of clusters or sectors per index.
+ u8 res[3];
+ struct INDEX_HDR ihdr; // 0x10:
+};
+
+static_assert(sizeof(struct INDEX_ROOT) == 0x20);
+static_assert(offsetof(struct INDEX_ROOT, ihdr) == 0x10);
+
+#define VOLUME_FLAG_DIRTY cpu_to_le16(0x0001)
+#define VOLUME_FLAG_RESIZE_LOG_FILE cpu_to_le16(0x0002)
+
+struct VOLUME_INFO {
+ __le64 res1; // 0x00
+ u8 major_ver; // 0x08: NTFS major version number (before .)
+ u8 minor_ver; // 0x09: NTFS minor version number (after .)
+ __le16 flags; // 0x0A: Volume flags, see VOLUME_FLAG_XXX
+
+}; // sizeof=0xC
+
+#define SIZEOF_ATTRIBUTE_VOLUME_INFO 0xc
+
+#define NTFS_LABEL_MAX_LENGTH (0x100 / sizeof(short))
+#define NTFS_ATTR_INDEXABLE cpu_to_le32(0x00000002)
+#define NTFS_ATTR_DUPALLOWED cpu_to_le32(0x00000004)
+#define NTFS_ATTR_MUST_BE_INDEXED cpu_to_le32(0x00000010)
+#define NTFS_ATTR_MUST_BE_NAMED cpu_to_le32(0x00000020)
+#define NTFS_ATTR_MUST_BE_RESIDENT cpu_to_le32(0x00000040)
+#define NTFS_ATTR_LOG_ALWAYS cpu_to_le32(0x00000080)
+
+/* $AttrDef file entry. */
+struct ATTR_DEF_ENTRY {
+ __le16 name[0x40]; // 0x00: Attr name.
+ enum ATTR_TYPE type; // 0x80: struct ATTRIB type.
+ __le32 res; // 0x84:
+ enum COLLATION_RULE rule; // 0x88:
+ __le32 flags; // 0x8C: NTFS_ATTR_XXX (see above).
+ __le64 min_sz; // 0x90: Minimum attribute data size.
+ __le64 max_sz; // 0x98: Maximum attribute data size.
+};
+
+static_assert(sizeof(struct ATTR_DEF_ENTRY) == 0xa0);
+
+/* Object ID (0x40) */
+struct OBJECT_ID {
+ struct GUID ObjId; // 0x00: Unique Id assigned to file.
+ struct GUID BirthVolumeId; // 0x10: Birth Volume Id is the Object Id of the Volume on.
+ // which the Object Id was allocated. It never changes.
+ struct GUID BirthObjectId; // 0x20: Birth Object Id is the first Object Id that was
+ // ever assigned to this MFT Record. I.e. If the Object Id
+ // is changed for some reason, this field will reflect the
+ // original value of the Object Id.
+ struct GUID DomainId; // 0x30: Domain Id is currently unused but it is intended to be
+ // used in a network environment where the local machine is
+ // part of a Windows 2000 Domain. This may be used in a Windows
+ // 2000 Advanced Server managed domain.
+};
+
+static_assert(sizeof(struct OBJECT_ID) == 0x40);
+
+/* O Directory entry structure ( rule = 0x13 ) */
+struct NTFS_DE_O {
+ struct NTFS_DE de;
+ struct GUID ObjId; // 0x10: Unique Id assigned to file.
+ struct MFT_REF ref; // 0x20: MFT record number with this file.
+ struct GUID BirthVolumeId; // 0x28: Birth Volume Id is the Object Id of the Volume on
+ // which the Object Id was allocated. It never changes.
+ struct GUID BirthObjectId; // 0x38: Birth Object Id is the first Object Id that was
+ // ever assigned to this MFT Record. I.e. If the Object Id
+ // is changed for some reason, this field will reflect the
+ // original value of the Object Id.
+ // This field is valid if data_size == 0x48.
+ struct GUID BirthDomainId; // 0x48: Domain Id is currently unused but it is intended
+ // to be used in a network environment where the local
+ // machine is part of a Windows 2000 Domain. This may be
+ // used in a Windows 2000 Advanced Server managed domain.
+};
+
+static_assert(sizeof(struct NTFS_DE_O) == 0x58);
+
+#define NTFS_OBJECT_ENTRY_DATA_SIZE1 \
+ 0x38 // struct NTFS_DE_O.BirthDomainId is not used
+#define NTFS_OBJECT_ENTRY_DATA_SIZE2 \
+ 0x48 // struct NTFS_DE_O.BirthDomainId is used
+
+/* Q Directory entry structure ( rule = 0x11 ) */
+struct NTFS_DE_Q {
+ struct NTFS_DE de;
+ __le32 owner_id; // 0x10: Unique Id assigned to file
+ __le32 Version; // 0x14: 0x02
+ __le32 flags2; // 0x18: Quota flags, see above
+ __le64 BytesUsed; // 0x1C:
+ __le64 ChangeTime; // 0x24:
+ __le64 WarningLimit; // 0x28:
+ __le64 HardLimit; // 0x34:
+ __le64 ExceededTime; // 0x3C:
+
+ // SID is placed here
+}; // sizeof() = 0x44
+
+#define SIZEOF_NTFS_DE_Q 0x44
+
+#define SecurityDescriptorsBlockSize 0x40000 // 256K
+#define SecurityDescriptorMaxSize 0x20000 // 128K
+#define Log2OfSecurityDescriptorsBlockSize 18
+
+struct SECURITY_KEY {
+ __le32 hash; // Hash value for descriptor
+ __le32 sec_id; // Security Id (guaranteed unique)
+};
+
+/* Security descriptors (the content of $Secure::SDS data stream) */
+struct SECURITY_HDR {
+ struct SECURITY_KEY key; // 0x00: Security Key.
+ __le64 off; // 0x08: Offset of this entry in the file.
+ __le32 size; // 0x10: Size of this entry, 8 byte aligned.
+ /*
+ * Security descriptor itself is placed here.
+ * Total size is 16 byte aligned.
+ */
+} __packed;
+
+#define SIZEOF_SECURITY_HDR 0x14
+
+/* SII Directory entry structure */
+struct NTFS_DE_SII {
+ struct NTFS_DE de;
+ __le32 sec_id; // 0x10: Key: sizeof(security_id) = wKeySize
+ struct SECURITY_HDR sec_hdr; // 0x14:
+} __packed;
+
+#define SIZEOF_SII_DIRENTRY 0x28
+
+/* SDH Directory entry structure */
+struct NTFS_DE_SDH {
+ struct NTFS_DE de;
+ struct SECURITY_KEY key; // 0x10: Key
+ struct SECURITY_HDR sec_hdr; // 0x18: Data
+ __le16 magic[2]; // 0x2C: 0x00490049 "I I"
+};
+
+#define SIZEOF_SDH_DIRENTRY 0x30
+
+struct REPARSE_KEY {
+ __le32 ReparseTag; // 0x00: Reparse Tag
+ struct MFT_REF ref; // 0x04: MFT record number with this file
+}; // sizeof() = 0x0C
+
+static_assert(offsetof(struct REPARSE_KEY, ref) == 0x04);
+#define SIZEOF_REPARSE_KEY 0x0C
+
+/* Reparse Directory entry structure */
+struct NTFS_DE_R {
+ struct NTFS_DE de;
+ struct REPARSE_KEY key; // 0x10: Reparse Key.
+ u32 zero; // 0x1c:
+}; // sizeof() = 0x20
+
+static_assert(sizeof(struct NTFS_DE_R) == 0x20);
+
+/* CompressReparseBuffer.WofVersion */
+#define WOF_CURRENT_VERSION cpu_to_le32(1)
+/* CompressReparseBuffer.WofProvider */
+#define WOF_PROVIDER_WIM cpu_to_le32(1)
+/* CompressReparseBuffer.WofProvider */
+#define WOF_PROVIDER_SYSTEM cpu_to_le32(2)
+/* CompressReparseBuffer.ProviderVer */
+#define WOF_PROVIDER_CURRENT_VERSION cpu_to_le32(1)
+
+#define WOF_COMPRESSION_XPRESS4K cpu_to_le32(0) // 4k
+#define WOF_COMPRESSION_LZX32K cpu_to_le32(1) // 32k
+#define WOF_COMPRESSION_XPRESS8K cpu_to_le32(2) // 8k
+#define WOF_COMPRESSION_XPRESS16K cpu_to_le32(3) // 16k
+
+/*
+ * ATTR_REPARSE (0xC0)
+ *
+ * The reparse struct GUID structure is used by all 3rd party layered drivers to
+ * store data in a reparse point. For non-Microsoft tags, The struct GUID field
+ * cannot be GUID_NULL.
+ * The constraints on reparse tags are defined below.
+ * Microsoft tags can also be used with this format of the reparse point buffer.
+ */
+struct REPARSE_POINT {
+ __le32 ReparseTag; // 0x00:
+ __le16 ReparseDataLength;// 0x04:
+ __le16 Reserved;
+
+ struct GUID Guid; // 0x08:
+
+ //
+ // Here GenericReparseBuffer is placed
+ //
+};
+
+static_assert(sizeof(struct REPARSE_POINT) == 0x18);
+
+/* Maximum allowed size of the reparse data. */
+#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
+
+/*
+ * The value of the following constant needs to satisfy the following
+ * conditions:
+ * (1) Be at least as large as the largest of the reserved tags.
+ * (2) Be strictly smaller than all the tags in use.
+ */
+#define IO_REPARSE_TAG_RESERVED_RANGE 1
+
+/*
+ * The reparse tags are a ULONG. The 32 bits are laid out as follows:
+ *
+ * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-----------------------+-------------------------------+
+ * |M|R|N|R| Reserved bits | Reparse Tag Value |
+ * +-+-+-+-+-----------------------+-------------------------------+
+ *
+ * M is the Microsoft bit. When set to 1, it denotes a tag owned by Microsoft.
+ * All ISVs must use a tag with a 0 in this position.
+ * Note: If a Microsoft tag is used by non-Microsoft software, the
+ * behavior is not defined.
+ *
+ * R is reserved. Must be zero for non-Microsoft tags.
+ *
+ * N is name surrogate. When set to 1, the file represents another named
+ * entity in the system.
+ *
+ * The M and N bits are OR-able.
+ * The following macros check for the M and N bit values:
+ */
+
+/*
+ * Macro to determine whether a reparse point tag corresponds to a tag
+ * owned by Microsoft.
+ */
+#define IsReparseTagMicrosoft(_tag) (((_tag)&IO_REPARSE_TAG_MICROSOFT))
+
+/* Macro to determine whether a reparse point tag is a name surrogate. */
+#define IsReparseTagNameSurrogate(_tag) (((_tag)&IO_REPARSE_TAG_NAME_SURROGATE))
+
+/*
+ * The following constant represents the bits that are valid to use in
+ * reparse tags.
+ */
+#define IO_REPARSE_TAG_VALID_VALUES 0xF000FFFF
+
+/*
+ * Macro to determine whether a reparse tag is a valid tag.
+ */
+#define IsReparseTagValid(_tag) \
+ (!((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) && \
+ ((_tag) > IO_REPARSE_TAG_RESERVED_RANGE))
+
+/* Microsoft tags for reparse points. */
+
+enum IO_REPARSE_TAG {
+ IO_REPARSE_TAG_SYMBOLIC_LINK = cpu_to_le32(0),
+ IO_REPARSE_TAG_NAME_SURROGATE = cpu_to_le32(0x20000000),
+ IO_REPARSE_TAG_MICROSOFT = cpu_to_le32(0x80000000),
+ IO_REPARSE_TAG_MOUNT_POINT = cpu_to_le32(0xA0000003),
+ IO_REPARSE_TAG_SYMLINK = cpu_to_le32(0xA000000C),
+ IO_REPARSE_TAG_HSM = cpu_to_le32(0xC0000004),
+ IO_REPARSE_TAG_SIS = cpu_to_le32(0x80000007),
+ IO_REPARSE_TAG_DEDUP = cpu_to_le32(0x80000013),
+ IO_REPARSE_TAG_COMPRESS = cpu_to_le32(0x80000017),
+
+ /*
+ * The reparse tag 0x80000008 is reserved for Microsoft internal use.
+ * May be published in the future.
+ */
+
+ /* Microsoft reparse tag reserved for DFS */
+ IO_REPARSE_TAG_DFS = cpu_to_le32(0x8000000A),
+
+ /* Microsoft reparse tag reserved for the file system filter manager. */
+ IO_REPARSE_TAG_FILTER_MANAGER = cpu_to_le32(0x8000000B),
+
+ /* Non-Microsoft tags for reparse points */
+
+ /* Tag allocated to CONGRUENT, May 2000. Used by IFSTEST. */
+ IO_REPARSE_TAG_IFSTEST_CONGRUENT = cpu_to_le32(0x00000009),
+
+ /* Tag allocated to ARKIVIO. */
+ IO_REPARSE_TAG_ARKIVIO = cpu_to_le32(0x0000000C),
+
+ /* Tag allocated to SOLUTIONSOFT. */
+ IO_REPARSE_TAG_SOLUTIONSOFT = cpu_to_le32(0x2000000D),
+
+ /* Tag allocated to COMMVAULT. */
+ IO_REPARSE_TAG_COMMVAULT = cpu_to_le32(0x0000000E),
+
+ /* OneDrive?? */
+ IO_REPARSE_TAG_CLOUD = cpu_to_le32(0x9000001A),
+ IO_REPARSE_TAG_CLOUD_1 = cpu_to_le32(0x9000101A),
+ IO_REPARSE_TAG_CLOUD_2 = cpu_to_le32(0x9000201A),
+ IO_REPARSE_TAG_CLOUD_3 = cpu_to_le32(0x9000301A),
+ IO_REPARSE_TAG_CLOUD_4 = cpu_to_le32(0x9000401A),
+ IO_REPARSE_TAG_CLOUD_5 = cpu_to_le32(0x9000501A),
+ IO_REPARSE_TAG_CLOUD_6 = cpu_to_le32(0x9000601A),
+ IO_REPARSE_TAG_CLOUD_7 = cpu_to_le32(0x9000701A),
+ IO_REPARSE_TAG_CLOUD_8 = cpu_to_le32(0x9000801A),
+ IO_REPARSE_TAG_CLOUD_9 = cpu_to_le32(0x9000901A),
+ IO_REPARSE_TAG_CLOUD_A = cpu_to_le32(0x9000A01A),
+ IO_REPARSE_TAG_CLOUD_B = cpu_to_le32(0x9000B01A),
+ IO_REPARSE_TAG_CLOUD_C = cpu_to_le32(0x9000C01A),
+ IO_REPARSE_TAG_CLOUD_D = cpu_to_le32(0x9000D01A),
+ IO_REPARSE_TAG_CLOUD_E = cpu_to_le32(0x9000E01A),
+ IO_REPARSE_TAG_CLOUD_F = cpu_to_le32(0x9000F01A),
+
+};
+
+#define SYMLINK_FLAG_RELATIVE 1
+
+/* Microsoft reparse buffer. (see DDK for details) */
+struct REPARSE_DATA_BUFFER {
+ __le32 ReparseTag; // 0x00:
+ __le16 ReparseDataLength; // 0x04:
+ __le16 Reserved;
+
+ union {
+ /* If ReparseTag == 0xA0000003 (IO_REPARSE_TAG_MOUNT_POINT) */
+ struct {
+ __le16 SubstituteNameOffset; // 0x08
+ __le16 SubstituteNameLength; // 0x0A
+ __le16 PrintNameOffset; // 0x0C
+ __le16 PrintNameLength; // 0x0E
+ __le16 PathBuffer[]; // 0x10
+ } MountPointReparseBuffer;
+
+ /*
+ * If ReparseTag == 0xA000000C (IO_REPARSE_TAG_SYMLINK)
+ * https://msdn.microsoft.com/en-us/library/cc232006.aspx
+ */
+ struct {
+ __le16 SubstituteNameOffset; // 0x08
+ __le16 SubstituteNameLength; // 0x0A
+ __le16 PrintNameOffset; // 0x0C
+ __le16 PrintNameLength; // 0x0E
+ // 0-absolute path 1- relative path, SYMLINK_FLAG_RELATIVE
+ __le32 Flags; // 0x10
+ __le16 PathBuffer[]; // 0x14
+ } SymbolicLinkReparseBuffer;
+
+ /* If ReparseTag == 0x80000017U */
+ struct {
+ __le32 WofVersion; // 0x08 == 1
+ /*
+ * 1 - WIM backing provider ("WIMBoot"),
+ * 2 - System compressed file provider
+ */
+ __le32 WofProvider; // 0x0C:
+ __le32 ProviderVer; // 0x10: == 1 WOF_FILE_PROVIDER_CURRENT_VERSION == 1
+ __le32 CompressionFormat; // 0x14: 0, 1, 2, 3. See WOF_COMPRESSION_XXX
+ } CompressReparseBuffer;
+
+ struct {
+ u8 DataBuffer[1]; // 0x08:
+ } GenericReparseBuffer;
+ };
+};
+
+/* ATTR_EA_INFO (0xD0) */
+
+#define FILE_NEED_EA 0x80 // See ntifs.h
+/*
+ *FILE_NEED_EA, indicates that the file to which the EA belongs cannot be
+ * interpreted without understanding the associated extended attributes.
+ */
+struct EA_INFO {
+ __le16 size_pack; // 0x00: Size of buffer to hold in packed form.
+ __le16 count; // 0x02: Count of EA's with FILE_NEED_EA bit set.
+ __le32 size; // 0x04: Size of buffer to hold in unpacked form.
+};
+
+static_assert(sizeof(struct EA_INFO) == 8);
+
+/* ATTR_EA (0xE0) */
+struct EA_FULL {
+ __le32 size; // 0x00: (not in packed)
+ u8 flags; // 0x04:
+ u8 name_len; // 0x05:
+ __le16 elength; // 0x06:
+ u8 name[]; // 0x08:
+};
+
+static_assert(offsetof(struct EA_FULL, name) == 8);
+
+#define ACL_REVISION 2
+#define ACL_REVISION_DS 4
+
+#define SE_SELF_RELATIVE cpu_to_le16(0x8000)
+
+struct SECURITY_DESCRIPTOR_RELATIVE {
+ u8 Revision;
+ u8 Sbz1;
+ __le16 Control;
+ __le32 Owner;
+ __le32 Group;
+ __le32 Sacl;
+ __le32 Dacl;
+};
+static_assert(sizeof(struct SECURITY_DESCRIPTOR_RELATIVE) == 0x14);
+
+struct ACE_HEADER {
+ u8 AceType;
+ u8 AceFlags;
+ __le16 AceSize;
+};
+static_assert(sizeof(struct ACE_HEADER) == 4);
+
+struct ACL {
+ u8 AclRevision;
+ u8 Sbz1;
+ __le16 AclSize;
+ __le16 AceCount;
+ __le16 Sbz2;
+};
+static_assert(sizeof(struct ACL) == 8);
+
+struct SID {
+ u8 Revision;
+ u8 SubAuthorityCount;
+ u8 IdentifierAuthority[6];
+ __le32 SubAuthority[];
+};
+static_assert(offsetof(struct SID, SubAuthority) == 8);
+
+#endif /* _LINUX_NTFS3_NTFS_H */
+// clang-format on
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
new file mode 100644
index 000000000000..dc71c59fd445
--- /dev/null
+++ b/fs/ntfs3/ntfs_fs.h
@@ -0,0 +1,1111 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+// clang-format off
+#ifndef _LINUX_NTFS3_NTFS_FS_H
+#define _LINUX_NTFS3_NTFS_FS_H
+
+#define MINUS_ONE_T ((size_t)(-1))
+/* Biggest MFT / smallest cluster */
+#define MAXIMUM_BYTES_PER_MFT 4096
+#define NTFS_BLOCKS_PER_MFT_RECORD (MAXIMUM_BYTES_PER_MFT / 512)
+
+#define MAXIMUM_BYTES_PER_INDEX 4096
+#define NTFS_BLOCKS_PER_INODE (MAXIMUM_BYTES_PER_INDEX / 512)
+
+/* NTFS specific error code when fixup failed. */
+#define E_NTFS_FIXUP 555
+/* NTFS specific error code about resident->nonresident. */
+#define E_NTFS_NONRESIDENT 556
+/* NTFS specific error code about punch hole. */
+#define E_NTFS_NOTALIGNED 557
+
+
+/* sbi->flags */
+#define NTFS_FLAGS_NODISCARD 0x00000001
+/* Set when LogFile is replaying. */
+#define NTFS_FLAGS_LOG_REPLAYING 0x00000008
+/* Set when we changed first MFT's which copy must be updated in $MftMirr. */
+#define NTFS_FLAGS_MFTMIRR 0x00001000
+#define NTFS_FLAGS_NEED_REPLAY 0x04000000
+
+
+/* ni->ni_flags */
+/*
+ * Data attribute is external compressed (LZX/Xpress)
+ * 1 - WOF_COMPRESSION_XPRESS4K
+ * 2 - WOF_COMPRESSION_XPRESS8K
+ * 3 - WOF_COMPRESSION_XPRESS16K
+ * 4 - WOF_COMPRESSION_LZX32K
+ */
+#define NI_FLAG_COMPRESSED_MASK 0x0000000f
+/* Data attribute is deduplicated. */
+#define NI_FLAG_DEDUPLICATED 0x00000010
+#define NI_FLAG_EA 0x00000020
+#define NI_FLAG_DIR 0x00000040
+#define NI_FLAG_RESIDENT 0x00000080
+#define NI_FLAG_UPDATE_PARENT 0x00000100
+// clang-format on
+
+struct ntfs_mount_options {
+ struct nls_table *nls;
+
+ kuid_t fs_uid;
+ kgid_t fs_gid;
+ u16 fs_fmask_inv;
+ u16 fs_dmask_inv;
+
+ unsigned uid : 1, /* uid was set. */
+ gid : 1, /* gid was set. */
+ fmask : 1, /* fmask was set. */
+ dmask : 1, /* dmask was set. */
+ sys_immutable : 1, /* Immutable system files. */
+ discard : 1, /* Issue discard requests on deletions. */
+ sparse : 1, /* Create sparse files. */
+ showmeta : 1, /* Show meta files. */
+ nohidden : 1, /* Do not show hidden files. */
+ force : 1, /* Rw mount dirty volume. */
+ no_acs_rules : 1, /*Exclude acs rules. */
+ prealloc : 1 /* Preallocate space when file is growing. */
+ ;
+};
+
+/* Special value to unpack and deallocate. */
+#define RUN_DEALLOCATE ((struct runs_tree *)(size_t)1)
+
+/* TODO: Use rb tree instead of array. */
+struct runs_tree {
+ struct ntfs_run *runs;
+ size_t count; /* Currently used size a ntfs_run storage. */
+ size_t allocated; /* Currently allocated ntfs_run storage size. */
+};
+
+struct ntfs_buffers {
+ /* Biggest MFT / smallest cluster = 4096 / 512 = 8 */
+ /* Biggest index / smallest cluster = 4096 / 512 = 8 */
+ struct buffer_head *bh[PAGE_SIZE >> SECTOR_SHIFT];
+ u32 bytes;
+ u32 nbufs;
+ u32 off;
+};
+
+enum ALLOCATE_OPT {
+ ALLOCATE_DEF = 0, // Allocate all clusters.
+ ALLOCATE_MFT = 1, // Allocate for MFT.
+};
+
+enum bitmap_mutex_classes {
+ BITMAP_MUTEX_CLUSTERS = 0,
+ BITMAP_MUTEX_MFT = 1,
+};
+
+struct wnd_bitmap {
+ struct super_block *sb;
+ struct rw_semaphore rw_lock;
+
+ struct runs_tree run;
+ size_t nbits;
+
+ size_t total_zeroes; // Total number of free bits.
+ u16 *free_bits; // Free bits in each window.
+ size_t nwnd;
+ u32 bits_last; // Bits in last window.
+
+ struct rb_root start_tree; // Extents, sorted by 'start'.
+ struct rb_root count_tree; // Extents, sorted by 'count + start'.
+ size_t count; // Extents count.
+
+ /*
+ * -1 Tree is activated but not updated (too many fragments).
+ * 0 - Tree is not activated.
+ * 1 - Tree is activated and updated.
+ */
+ int uptodated;
+ size_t extent_min; // Minimal extent used while building.
+ size_t extent_max; // Upper estimate of biggest free block.
+
+ /* Zone [bit, end) */
+ size_t zone_bit;
+ size_t zone_end;
+
+ bool set_tail; // Not necessary in driver.
+ bool inited;
+};
+
+typedef int (*NTFS_CMP_FUNC)(const void *key1, size_t len1, const void *key2,
+ size_t len2, const void *param);
+
+enum index_mutex_classed {
+ INDEX_MUTEX_I30 = 0,
+ INDEX_MUTEX_SII = 1,
+ INDEX_MUTEX_SDH = 2,
+ INDEX_MUTEX_SO = 3,
+ INDEX_MUTEX_SQ = 4,
+ INDEX_MUTEX_SR = 5,
+ INDEX_MUTEX_TOTAL
+};
+
+/* ntfs_index - Allocation unit inside directory. */
+struct ntfs_index {
+ struct runs_tree bitmap_run;
+ struct runs_tree alloc_run;
+ /* read/write access to 'bitmap_run'/'alloc_run' while ntfs_readdir */
+ struct rw_semaphore run_lock;
+
+ /*TODO: Remove 'cmp'. */
+ NTFS_CMP_FUNC cmp;
+
+ u8 index_bits; // log2(root->index_block_size)
+ u8 idx2vbn_bits; // log2(root->index_block_clst)
+ u8 vbn2vbo_bits; // index_block_size < cluster? 9 : cluster_bits
+ u8 type; // index_mutex_classed
+};
+
+/* Minimum MFT zone. */
+#define NTFS_MIN_MFT_ZONE 100
+
+/* Ntfs file system in-core superblock data. */
+struct ntfs_sb_info {
+ struct super_block *sb;
+
+ u32 discard_granularity;
+ u64 discard_granularity_mask_inv; // ~(discard_granularity_mask_inv-1)
+
+ u32 cluster_size; // bytes per cluster
+ u32 cluster_mask; // == cluster_size - 1
+ u64 cluster_mask_inv; // ~(cluster_size - 1)
+ u32 block_mask; // sb->s_blocksize - 1
+ u32 blocks_per_cluster; // cluster_size / sb->s_blocksize
+
+ u32 record_size;
+ u32 sector_size;
+ u32 index_size;
+
+ u8 sector_bits;
+ u8 cluster_bits;
+ u8 record_bits;
+
+ u64 maxbytes; // Maximum size for normal files.
+ u64 maxbytes_sparse; // Maximum size for sparse file.
+
+ u32 flags; // See NTFS_FLAGS_XXX.
+
+ CLST bad_clusters; // The count of marked bad clusters.
+
+ u16 max_bytes_per_attr; // Maximum attribute size in record.
+ u16 attr_size_tr; // Attribute size threshold (320 bytes).
+
+ /* Records in $Extend. */
+ CLST objid_no;
+ CLST quota_no;
+ CLST reparse_no;
+ CLST usn_jrnl_no;
+
+ struct ATTR_DEF_ENTRY *def_table; // Attribute definition table.
+ u32 def_entries;
+ u32 ea_max_size;
+
+ struct MFT_REC *new_rec;
+
+ u16 *upcase;
+
+ struct {
+ u64 lbo, lbo2;
+ struct ntfs_inode *ni;
+ struct wnd_bitmap bitmap; // $MFT::Bitmap
+ /*
+ * MFT records [11-24) used to expand MFT itself.
+ * They always marked as used in $MFT::Bitmap
+ * 'reserved_bitmap' contains real bitmap of these records.
+ */
+ ulong reserved_bitmap; // Bitmap of used records [11 - 24)
+ size_t next_free; // The next record to allocate from
+ size_t used; // MFT valid size in records.
+ u32 recs_mirr; // Number of records in MFTMirr
+ u8 next_reserved;
+ u8 reserved_bitmap_inited;
+ } mft;
+
+ struct {
+ struct wnd_bitmap bitmap; // $Bitmap::Data
+ CLST next_free_lcn;
+ } used;
+
+ struct {
+ u64 size; // In bytes.
+ u64 blocks; // In blocks.
+ u64 ser_num;
+ struct ntfs_inode *ni;
+ __le16 flags; // Cached current VOLUME_INFO::flags, VOLUME_FLAG_DIRTY.
+ u8 major_ver;
+ u8 minor_ver;
+ char label[65];
+ bool real_dirty; // Real fs state.
+ } volume;
+
+ struct {
+ struct ntfs_index index_sii;
+ struct ntfs_index index_sdh;
+ struct ntfs_inode *ni;
+ u32 next_id;
+ u64 next_off;
+
+ __le32 def_security_id;
+ } security;
+
+ struct {
+ struct ntfs_index index_r;
+ struct ntfs_inode *ni;
+ u64 max_size; // 16K
+ } reparse;
+
+ struct {
+ struct ntfs_index index_o;
+ struct ntfs_inode *ni;
+ } objid;
+
+ struct {
+ struct mutex mtx_lznt;
+ struct lznt *lznt;
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+ struct mutex mtx_xpress;
+ struct xpress_decompressor *xpress;
+ struct mutex mtx_lzx;
+ struct lzx_decompressor *lzx;
+#endif
+ } compress;
+
+ struct ntfs_mount_options options;
+ struct ratelimit_state msg_ratelimit;
+};
+
+/* One MFT record(usually 1024 bytes), consists of attributes. */
+struct mft_inode {
+ struct rb_node node;
+ struct ntfs_sb_info *sbi;
+
+ struct MFT_REC *mrec;
+ struct ntfs_buffers nb;
+
+ CLST rno;
+ bool dirty;
+};
+
+/* Nested class for ntfs_inode::ni_lock. */
+enum ntfs_inode_mutex_lock_class {
+ NTFS_INODE_MUTEX_DIRTY,
+ NTFS_INODE_MUTEX_SECURITY,
+ NTFS_INODE_MUTEX_OBJID,
+ NTFS_INODE_MUTEX_REPARSE,
+ NTFS_INODE_MUTEX_NORMAL,
+ NTFS_INODE_MUTEX_PARENT,
+};
+
+/*
+ * sturct ntfs_inode
+ *
+ * Ntfs inode - extends linux inode. consists of one or more MFT inodes.
+ */
+struct ntfs_inode {
+ struct mft_inode mi; // base record
+
+ /*
+ * Valid size: [0 - i_valid) - these range in file contains valid data.
+ * Range [i_valid - inode->i_size) - contains 0.
+ * Usually i_valid <= inode->i_size.
+ */
+ u64 i_valid;
+ struct timespec64 i_crtime;
+
+ struct mutex ni_lock;
+
+ /* File attributes from std. */
+ enum FILE_ATTRIBUTE std_fa;
+ __le32 std_security_id;
+
+ /*
+ * Tree of mft_inode.
+ * Not empty when primary MFT record (usually 1024 bytes) can't save all attributes
+ * e.g. file becomes too fragmented or contains a lot of names.
+ */
+ struct rb_root mi_tree;
+
+ /*
+ * This member is used in ntfs_readdir to ensure that all subrecords are loaded
+ */
+ u8 mi_loaded;
+
+ union {
+ struct ntfs_index dir;
+ struct {
+ struct rw_semaphore run_lock;
+ struct runs_tree run;
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+ struct page *offs_page;
+#endif
+ } file;
+ };
+
+ struct {
+ struct runs_tree run;
+ struct ATTR_LIST_ENTRY *le; // 1K aligned memory.
+ size_t size;
+ bool dirty;
+ } attr_list;
+
+ size_t ni_flags; // NI_FLAG_XXX
+
+ struct inode vfs_inode;
+};
+
+struct indx_node {
+ struct ntfs_buffers nb;
+ struct INDEX_BUFFER *index;
+};
+
+struct ntfs_fnd {
+ int level;
+ struct indx_node *nodes[20];
+ struct NTFS_DE *de[20];
+ struct NTFS_DE *root_de;
+};
+
+enum REPARSE_SIGN {
+ REPARSE_NONE = 0,
+ REPARSE_COMPRESSED = 1,
+ REPARSE_DEDUPLICATED = 2,
+ REPARSE_LINK = 3
+};
+
+/* Functions from attrib.c */
+int attr_load_runs(struct ATTRIB *attr, struct ntfs_inode *ni,
+ struct runs_tree *run, const CLST *vcn);
+int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run,
+ CLST vcn, CLST lcn, CLST len, CLST *pre_alloc,
+ enum ALLOCATE_OPT opt, CLST *alen, const size_t fr,
+ CLST *new_lcn);
+int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct ATTR_LIST_ENTRY *le, struct mft_inode *mi,
+ u64 new_size, struct runs_tree *run,
+ struct ATTRIB **ins_attr, struct page *page);
+int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, struct runs_tree *run,
+ u64 new_size, const u64 *new_valid, bool keep_prealloc,
+ struct ATTRIB **ret);
+int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
+ CLST *len, bool *new);
+int attr_data_read_resident(struct ntfs_inode *ni, struct page *page);
+int attr_data_write_resident(struct ntfs_inode *ni, struct page *page);
+int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, struct runs_tree *run,
+ CLST vcn);
+int attr_load_runs_range(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, struct runs_tree *run,
+ u64 from, u64 to);
+int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct runs_tree *run, u64 frame, u64 frames,
+ u8 frame_bits, u32 *ondisk_size, u64 *vbo_data);
+int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
+ CLST frame, CLST *clst_data);
+int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
+ u64 new_valid);
+int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes);
+int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size);
+
+/* Functions from attrlist.c */
+void al_destroy(struct ntfs_inode *ni);
+bool al_verify(struct ntfs_inode *ni);
+int ntfs_load_attr_list(struct ntfs_inode *ni, struct ATTRIB *attr);
+struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni,
+ struct ATTR_LIST_ENTRY *le);
+struct ATTR_LIST_ENTRY *al_find_le(struct ntfs_inode *ni,
+ struct ATTR_LIST_ENTRY *le,
+ const struct ATTRIB *attr);
+struct ATTR_LIST_ENTRY *al_find_ex(struct ntfs_inode *ni,
+ struct ATTR_LIST_ENTRY *le,
+ enum ATTR_TYPE type, const __le16 *name,
+ u8 name_len, const CLST *vcn);
+int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
+ u8 name_len, CLST svcn, __le16 id, const struct MFT_REF *ref,
+ struct ATTR_LIST_ENTRY **new_le);
+bool al_remove_le(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le);
+bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn,
+ const __le16 *name, size_t name_len,
+ const struct MFT_REF *ref);
+int al_update(struct ntfs_inode *ni);
+static inline size_t al_aligned(size_t size)
+{
+ return (size + 1023) & ~(size_t)1023;
+}
+
+/* Globals from bitfunc.c */
+bool are_bits_clear(const ulong *map, size_t bit, size_t nbits);
+bool are_bits_set(const ulong *map, size_t bit, size_t nbits);
+size_t get_set_bits_ex(const ulong *map, size_t bit, size_t nbits);
+
+/* Globals from dir.c */
+int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni,
+ u8 *buf, int buf_len);
+int ntfs_nls_to_utf16(struct ntfs_sb_info *sbi, const u8 *name, u32 name_len,
+ struct cpu_str *uni, u32 max_ulen,
+ enum utf16_endian endian);
+struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
+ struct ntfs_fnd *fnd);
+bool dir_is_empty(struct inode *dir);
+extern const struct file_operations ntfs_dir_operations;
+
+/* Globals from file.c */
+int ntfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
+ struct kstat *stat, u32 request_mask, u32 flags);
+void ntfs_sparse_cluster(struct inode *inode, struct page *page0, CLST vcn,
+ CLST len);
+int ntfs3_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
+ struct iattr *attr);
+int ntfs_file_open(struct inode *inode, struct file *file);
+int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ __u64 start, __u64 len);
+extern const struct inode_operations ntfs_special_inode_operations;
+extern const struct inode_operations ntfs_file_inode_operations;
+extern const struct file_operations ntfs_file_operations;
+
+/* Globals from frecord.c */
+void ni_remove_mi(struct ntfs_inode *ni, struct mft_inode *mi);
+struct ATTR_STD_INFO *ni_std(struct ntfs_inode *ni);
+struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni);
+void ni_clear(struct ntfs_inode *ni);
+int ni_load_mi_ex(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi);
+int ni_load_mi(struct ntfs_inode *ni, const struct ATTR_LIST_ENTRY *le,
+ struct mft_inode **mi);
+struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct ATTR_LIST_ENTRY **entry_o,
+ enum ATTR_TYPE type, const __le16 *name,
+ u8 name_len, const CLST *vcn,
+ struct mft_inode **mi);
+struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct ATTR_LIST_ENTRY **le,
+ struct mft_inode **mi);
+struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, CLST vcn,
+ struct mft_inode **pmi);
+int ni_load_all_mi(struct ntfs_inode *ni);
+bool ni_add_subrecord(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi);
+int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, size_t name_len, bool base_only,
+ const __le16 *id);
+int ni_create_attr_list(struct ntfs_inode *ni);
+int ni_expand_list(struct ntfs_inode *ni);
+int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len,
+ const struct runs_tree *run, CLST svcn, CLST len,
+ __le16 flags, struct ATTRIB **new_attr,
+ struct mft_inode **mi);
+int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
+ enum ATTR_TYPE type, const __le16 *name, u8 name_len,
+ struct ATTRIB **new_attr, struct mft_inode **mi,
+ struct ATTR_LIST_ENTRY **le);
+void ni_remove_attr_le(struct ntfs_inode *ni, struct ATTRIB *attr,
+ struct mft_inode *mi, struct ATTR_LIST_ENTRY *le);
+int ni_delete_all(struct ntfs_inode *ni);
+struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
+ const struct cpu_str *uni,
+ const struct MFT_REF *home,
+ struct mft_inode **mi,
+ struct ATTR_LIST_ENTRY **entry);
+struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type,
+ struct mft_inode **mi,
+ struct ATTR_LIST_ENTRY **entry);
+int ni_new_attr_flags(struct ntfs_inode *ni, enum FILE_ATTRIBUTE new_fa);
+enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr,
+ void *buffer);
+int ni_write_inode(struct inode *inode, int sync, const char *hint);
+#define _ni_write_inode(i, w) ni_write_inode(i, w, __func__)
+int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
+ __u64 vbo, __u64 len);
+int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page);
+int ni_decompress_file(struct ntfs_inode *ni);
+int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
+ u32 pages_per_frame);
+int ni_write_frame(struct ntfs_inode *ni, struct page **pages,
+ u32 pages_per_frame);
+int ni_remove_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
+ struct NTFS_DE *de, struct NTFS_DE **de2, int *undo_step);
+
+bool ni_remove_name_undo(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
+ struct NTFS_DE *de, struct NTFS_DE *de2,
+ int undo_step);
+
+int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
+ struct NTFS_DE *de);
+
+int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
+ struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de,
+ bool *is_bad);
+
+bool ni_is_dirty(struct inode *inode);
+
+/* Globals from fslog.c */
+int log_replay(struct ntfs_inode *ni, bool *initialized);
+
+/* Globals from fsntfs.c */
+bool ntfs_fix_pre_write(struct NTFS_RECORD_HEADER *rhdr, size_t bytes);
+int ntfs_fix_post_read(struct NTFS_RECORD_HEADER *rhdr, size_t bytes,
+ bool simple);
+int ntfs_extend_init(struct ntfs_sb_info *sbi);
+int ntfs_loadlog_and_replay(struct ntfs_inode *ni, struct ntfs_sb_info *sbi);
+const struct ATTR_DEF_ENTRY *ntfs_query_def(struct ntfs_sb_info *sbi,
+ enum ATTR_TYPE Type);
+int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len,
+ CLST *new_lcn, CLST *new_len,
+ enum ALLOCATE_OPT opt);
+int ntfs_look_free_mft(struct ntfs_sb_info *sbi, CLST *rno, bool mft,
+ struct ntfs_inode *ni, struct mft_inode **mi);
+void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno);
+int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to);
+int ntfs_refresh_zone(struct ntfs_sb_info *sbi);
+int ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait);
+enum NTFS_DIRTY_FLAGS {
+ NTFS_DIRTY_CLEAR = 0,
+ NTFS_DIRTY_DIRTY = 1,
+ NTFS_DIRTY_ERROR = 2,
+};
+int ntfs_set_state(struct ntfs_sb_info *sbi, enum NTFS_DIRTY_FLAGS dirty);
+int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer);
+int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes,
+ const void *buffer, int wait);
+int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+ u64 vbo, const void *buf, size_t bytes);
+struct buffer_head *ntfs_bread_run(struct ntfs_sb_info *sbi,
+ const struct runs_tree *run, u64 vbo);
+int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+ u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb);
+int ntfs_read_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
+ struct NTFS_RECORD_HEADER *rhdr, u32 bytes,
+ struct ntfs_buffers *nb);
+int ntfs_get_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo,
+ u32 bytes, struct ntfs_buffers *nb);
+int ntfs_write_bh(struct ntfs_sb_info *sbi, struct NTFS_RECORD_HEADER *rhdr,
+ struct ntfs_buffers *nb, int sync);
+int ntfs_bio_pages(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+ struct page **pages, u32 nr_pages, u64 vbo, u32 bytes,
+ u32 op);
+int ntfs_bio_fill_1(struct ntfs_sb_info *sbi, const struct runs_tree *run);
+int ntfs_vbo_to_lbo(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+ u64 vbo, u64 *lbo, u64 *bytes);
+struct ntfs_inode *ntfs_new_inode(struct ntfs_sb_info *sbi, CLST nRec,
+ bool dir);
+extern const u8 s_default_security[0x50];
+bool is_sd_valid(const struct SECURITY_DESCRIPTOR_RELATIVE *sd, u32 len);
+int ntfs_security_init(struct ntfs_sb_info *sbi);
+int ntfs_get_security_by_id(struct ntfs_sb_info *sbi, __le32 security_id,
+ struct SECURITY_DESCRIPTOR_RELATIVE **sd,
+ size_t *size);
+int ntfs_insert_security(struct ntfs_sb_info *sbi,
+ const struct SECURITY_DESCRIPTOR_RELATIVE *sd,
+ u32 size, __le32 *security_id, bool *inserted);
+int ntfs_reparse_init(struct ntfs_sb_info *sbi);
+int ntfs_objid_init(struct ntfs_sb_info *sbi);
+int ntfs_objid_remove(struct ntfs_sb_info *sbi, struct GUID *guid);
+int ntfs_insert_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
+ const struct MFT_REF *ref);
+int ntfs_remove_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
+ const struct MFT_REF *ref);
+void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim);
+int run_deallocate(struct ntfs_sb_info *sbi, struct runs_tree *run, bool trim);
+
+/* Globals from index.c */
+int indx_used_bit(struct ntfs_index *indx, struct ntfs_inode *ni, size_t *bit);
+void fnd_clear(struct ntfs_fnd *fnd);
+static inline struct ntfs_fnd *fnd_get(void)
+{
+ return kzalloc(sizeof(struct ntfs_fnd), GFP_NOFS);
+}
+static inline void fnd_put(struct ntfs_fnd *fnd)
+{
+ if (fnd) {
+ fnd_clear(fnd);
+ kfree(fnd);
+ }
+}
+void indx_clear(struct ntfs_index *idx);
+int indx_init(struct ntfs_index *indx, struct ntfs_sb_info *sbi,
+ const struct ATTRIB *attr, enum index_mutex_classed type);
+struct INDEX_ROOT *indx_get_root(struct ntfs_index *indx, struct ntfs_inode *ni,
+ struct ATTRIB **attr, struct mft_inode **mi);
+int indx_read(struct ntfs_index *idx, struct ntfs_inode *ni, CLST vbn,
+ struct indx_node **node);
+int indx_find(struct ntfs_index *indx, struct ntfs_inode *dir,
+ const struct INDEX_ROOT *root, const void *Key, size_t KeyLen,
+ const void *param, int *diff, struct NTFS_DE **entry,
+ struct ntfs_fnd *fnd);
+int indx_find_sort(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct INDEX_ROOT *root, struct NTFS_DE **entry,
+ struct ntfs_fnd *fnd);
+int indx_find_raw(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct INDEX_ROOT *root, struct NTFS_DE **entry,
+ size_t *off, struct ntfs_fnd *fnd);
+int indx_insert_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const struct NTFS_DE *new_de, const void *param,
+ struct ntfs_fnd *fnd, bool undo);
+int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
+ const void *key, u32 key_len, const void *param);
+int indx_update_dup(struct ntfs_inode *ni, struct ntfs_sb_info *sbi,
+ const struct ATTR_FILE_NAME *fname,
+ const struct NTFS_DUP_INFO *dup, int sync);
+
+/* Globals from inode.c */
+struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref,
+ const struct cpu_str *name);
+int ntfs_set_size(struct inode *inode, u64 new_size);
+int reset_log_file(struct inode *inode);
+int ntfs_get_block(struct inode *inode, sector_t vbn,
+ struct buffer_head *bh_result, int create);
+int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc);
+int ntfs_sync_inode(struct inode *inode);
+int ntfs_flush_inodes(struct super_block *sb, struct inode *i1,
+ struct inode *i2);
+int inode_write_data(struct inode *inode, const void *data, size_t bytes);
+struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
+ struct inode *dir, struct dentry *dentry,
+ const struct cpu_str *uni, umode_t mode,
+ dev_t dev, const char *symname, u32 size,
+ struct ntfs_fnd *fnd);
+int ntfs_link_inode(struct inode *inode, struct dentry *dentry);
+int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry);
+void ntfs_evict_inode(struct inode *inode);
+extern const struct inode_operations ntfs_link_inode_operations;
+extern const struct address_space_operations ntfs_aops;
+extern const struct address_space_operations ntfs_aops_cmpr;
+
+/* Globals from name_i.c */
+int fill_name_de(struct ntfs_sb_info *sbi, void *buf, const struct qstr *name,
+ const struct cpu_str *uni);
+struct dentry *ntfs3_get_parent(struct dentry *child);
+
+extern const struct inode_operations ntfs_dir_inode_operations;
+extern const struct inode_operations ntfs_special_inode_operations;
+
+/* Globals from record.c */
+int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi);
+void mi_put(struct mft_inode *mi);
+int mi_init(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno);
+int mi_read(struct mft_inode *mi, bool is_mft);
+struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr);
+// TODO: id?
+struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
+ enum ATTR_TYPE type, const __le16 *name,
+ size_t name_len, const __le16 *id);
+static inline struct ATTRIB *rec_find_attr_le(struct mft_inode *rec,
+ struct ATTR_LIST_ENTRY *le)
+{
+ return mi_find_attr(rec, NULL, le->type, le_name(le), le->name_len,
+ &le->id);
+}
+int mi_write(struct mft_inode *mi, int wait);
+int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
+ __le16 flags, bool is_mft);
+void mi_mark_free(struct mft_inode *mi);
+struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, u32 asize,
+ u16 name_off);
+
+bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
+ struct ATTRIB *attr);
+bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes);
+int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
+ struct runs_tree *run, CLST len);
+static inline bool mi_is_ref(const struct mft_inode *mi,
+ const struct MFT_REF *ref)
+{
+ if (le32_to_cpu(ref->low) != mi->rno)
+ return false;
+ if (ref->seq != mi->mrec->seq)
+ return false;
+
+#ifdef CONFIG_NTFS3_64BIT_CLUSTER
+ return le16_to_cpu(ref->high) == (mi->rno >> 32);
+#else
+ return !ref->high;
+#endif
+}
+
+static inline void mi_get_ref(const struct mft_inode *mi, struct MFT_REF *ref)
+{
+ ref->low = cpu_to_le32(mi->rno);
+#ifdef CONFIG_NTFS3_64BIT_CLUSTER
+ ref->high = cpu_to_le16(mi->rno >> 32);
+#else
+ ref->high = 0;
+#endif
+ ref->seq = mi->mrec->seq;
+}
+
+/* Globals from run.c */
+bool run_lookup_entry(const struct runs_tree *run, CLST vcn, CLST *lcn,
+ CLST *len, size_t *index);
+void run_truncate(struct runs_tree *run, CLST vcn);
+void run_truncate_head(struct runs_tree *run, CLST vcn);
+void run_truncate_around(struct runs_tree *run, CLST vcn);
+bool run_lookup(const struct runs_tree *run, CLST vcn, size_t *Index);
+bool run_add_entry(struct runs_tree *run, CLST vcn, CLST lcn, CLST len,
+ bool is_mft);
+bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len);
+bool run_get_entry(const struct runs_tree *run, size_t index, CLST *vcn,
+ CLST *lcn, CLST *len);
+bool run_is_mapped_full(const struct runs_tree *run, CLST svcn, CLST evcn);
+
+int run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf,
+ u32 run_buf_size, CLST *packed_vcns);
+int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
+ CLST svcn, CLST evcn, CLST vcn, const u8 *run_buf,
+ u32 run_buf_size);
+
+#ifdef NTFS3_CHECK_FREE_CLST
+int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
+ CLST svcn, CLST evcn, CLST vcn, const u8 *run_buf,
+ u32 run_buf_size);
+#else
+#define run_unpack_ex run_unpack
+#endif
+int run_get_highest_vcn(CLST vcn, const u8 *run_buf, u64 *highest_vcn);
+
+/* Globals from super.c */
+void *ntfs_set_shared(void *ptr, u32 bytes);
+void *ntfs_put_shared(void *ptr);
+void ntfs_unmap_meta(struct super_block *sb, CLST lcn, CLST len);
+int ntfs_discard(struct ntfs_sb_info *sbi, CLST Lcn, CLST Len);
+
+/* Globals from bitmap.c*/
+int __init ntfs3_init_bitmap(void);
+void ntfs3_exit_bitmap(void);
+void wnd_close(struct wnd_bitmap *wnd);
+static inline size_t wnd_zeroes(const struct wnd_bitmap *wnd)
+{
+ return wnd->total_zeroes;
+}
+int wnd_init(struct wnd_bitmap *wnd, struct super_block *sb, size_t nbits);
+int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits);
+int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits);
+bool wnd_is_free(struct wnd_bitmap *wnd, size_t bit, size_t bits);
+bool wnd_is_used(struct wnd_bitmap *wnd, size_t bit, size_t bits);
+
+/* Possible values for 'flags' 'wnd_find'. */
+#define BITMAP_FIND_MARK_AS_USED 0x01
+#define BITMAP_FIND_FULL 0x02
+size_t wnd_find(struct wnd_bitmap *wnd, size_t to_alloc, size_t hint,
+ size_t flags, size_t *allocated);
+int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits);
+void wnd_zone_set(struct wnd_bitmap *wnd, size_t Lcn, size_t Len);
+int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range);
+
+/* Globals from upcase.c */
+int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2,
+ const u16 *upcase, bool bothcase);
+int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2,
+ const u16 *upcase, bool bothcase);
+
+/* globals from xattr.c */
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+struct posix_acl *ntfs_get_acl(struct inode *inode, int type, bool rcu);
+int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
+ struct posix_acl *acl, int type);
+int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode,
+ struct inode *dir);
+#else
+#define ntfs_get_acl NULL
+#define ntfs_set_acl NULL
+#endif
+
+int ntfs_acl_chmod(struct user_namespace *mnt_userns, struct inode *inode);
+int ntfs_permission(struct user_namespace *mnt_userns, struct inode *inode,
+ int mask);
+ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
+extern const struct xattr_handler *ntfs_xattr_handlers[];
+
+int ntfs_save_wsl_perm(struct inode *inode);
+void ntfs_get_wsl_perm(struct inode *inode);
+
+/* globals from lznt.c */
+struct lznt *get_lznt_ctx(int level);
+size_t compress_lznt(const void *uncompressed, size_t uncompressed_size,
+ void *compressed, size_t compressed_size,
+ struct lznt *ctx);
+ssize_t decompress_lznt(const void *compressed, size_t compressed_size,
+ void *uncompressed, size_t uncompressed_size);
+
+static inline bool is_ntfs3(struct ntfs_sb_info *sbi)
+{
+ return sbi->volume.major_ver >= 3;
+}
+
+/* (sb->s_flags & SB_ACTIVE) */
+static inline bool is_mounted(struct ntfs_sb_info *sbi)
+{
+ return !!sbi->sb->s_root;
+}
+
+static inline bool ntfs_is_meta_file(struct ntfs_sb_info *sbi, CLST rno)
+{
+ return rno < MFT_REC_FREE || rno == sbi->objid_no ||
+ rno == sbi->quota_no || rno == sbi->reparse_no ||
+ rno == sbi->usn_jrnl_no;
+}
+
+static inline void ntfs_unmap_page(struct page *page)
+{
+ kunmap(page);
+ put_page(page);
+}
+
+static inline struct page *ntfs_map_page(struct address_space *mapping,
+ unsigned long index)
+{
+ struct page *page = read_mapping_page(mapping, index, NULL);
+
+ if (!IS_ERR(page)) {
+ kmap(page);
+ if (!PageError(page))
+ return page;
+ ntfs_unmap_page(page);
+ return ERR_PTR(-EIO);
+ }
+ return page;
+}
+
+static inline size_t wnd_zone_bit(const struct wnd_bitmap *wnd)
+{
+ return wnd->zone_bit;
+}
+
+static inline size_t wnd_zone_len(const struct wnd_bitmap *wnd)
+{
+ return wnd->zone_end - wnd->zone_bit;
+}
+
+static inline void run_init(struct runs_tree *run)
+{
+ run->runs = NULL;
+ run->count = 0;
+ run->allocated = 0;
+}
+
+static inline struct runs_tree *run_alloc(void)
+{
+ return kzalloc(sizeof(struct runs_tree), GFP_NOFS);
+}
+
+static inline void run_close(struct runs_tree *run)
+{
+ kvfree(run->runs);
+ memset(run, 0, sizeof(*run));
+}
+
+static inline void run_free(struct runs_tree *run)
+{
+ if (run) {
+ kvfree(run->runs);
+ kfree(run);
+ }
+}
+
+static inline bool run_is_empty(struct runs_tree *run)
+{
+ return !run->count;
+}
+
+/* NTFS uses quad aligned bitmaps. */
+static inline size_t bitmap_size(size_t bits)
+{
+ return ALIGN((bits + 7) >> 3, 8);
+}
+
+#define _100ns2seconds 10000000
+#define SecondsToStartOf1970 0x00000002B6109100
+
+#define NTFS_TIME_GRAN 100
+
+/*
+ * kernel2nt - Converts in-memory kernel timestamp into nt time.
+ */
+static inline __le64 kernel2nt(const struct timespec64 *ts)
+{
+ // 10^7 units of 100 nanoseconds one second
+ return cpu_to_le64(_100ns2seconds *
+ (ts->tv_sec + SecondsToStartOf1970) +
+ ts->tv_nsec / NTFS_TIME_GRAN);
+}
+
+/*
+ * nt2kernel - Converts on-disk nt time into kernel timestamp.
+ */
+static inline void nt2kernel(const __le64 tm, struct timespec64 *ts)
+{
+ u64 t = le64_to_cpu(tm) - _100ns2seconds * SecondsToStartOf1970;
+
+ // WARNING: do_div changes its first argument(!)
+ ts->tv_nsec = do_div(t, _100ns2seconds) * 100;
+ ts->tv_sec = t;
+}
+
+static inline struct ntfs_sb_info *ntfs_sb(struct super_block *sb)
+{
+ return sb->s_fs_info;
+}
+
+/*
+ * ntfs_up_cluster - Align up on cluster boundary.
+ */
+static inline u64 ntfs_up_cluster(const struct ntfs_sb_info *sbi, u64 size)
+{
+ return (size + sbi->cluster_mask) & sbi->cluster_mask_inv;
+}
+
+/*
+ * ntfs_up_block - Align up on cluster boundary.
+ */
+static inline u64 ntfs_up_block(const struct super_block *sb, u64 size)
+{
+ return (size + sb->s_blocksize - 1) & ~(u64)(sb->s_blocksize - 1);
+}
+
+static inline CLST bytes_to_cluster(const struct ntfs_sb_info *sbi, u64 size)
+{
+ return (size + sbi->cluster_mask) >> sbi->cluster_bits;
+}
+
+static inline u64 bytes_to_block(const struct super_block *sb, u64 size)
+{
+ return (size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+}
+
+static inline struct buffer_head *ntfs_bread(struct super_block *sb,
+ sector_t block)
+{
+ struct buffer_head *bh = sb_bread(sb, block);
+
+ if (bh)
+ return bh;
+
+ ntfs_err(sb, "failed to read volume at offset 0x%llx",
+ (u64)block << sb->s_blocksize_bits);
+ return NULL;
+}
+
+static inline struct ntfs_inode *ntfs_i(struct inode *inode)
+{
+ return container_of(inode, struct ntfs_inode, vfs_inode);
+}
+
+static inline bool is_compressed(const struct ntfs_inode *ni)
+{
+ return (ni->std_fa & FILE_ATTRIBUTE_COMPRESSED) ||
+ (ni->ni_flags & NI_FLAG_COMPRESSED_MASK);
+}
+
+static inline int ni_ext_compress_bits(const struct ntfs_inode *ni)
+{
+ return 0xb + (ni->ni_flags & NI_FLAG_COMPRESSED_MASK);
+}
+
+/* Bits - 0xc, 0xd, 0xe, 0xf, 0x10 */
+static inline void ni_set_ext_compress_bits(struct ntfs_inode *ni, u8 bits)
+{
+ ni->ni_flags |= (bits - 0xb) & NI_FLAG_COMPRESSED_MASK;
+}
+
+static inline bool is_dedup(const struct ntfs_inode *ni)
+{
+ return ni->ni_flags & NI_FLAG_DEDUPLICATED;
+}
+
+static inline bool is_encrypted(const struct ntfs_inode *ni)
+{
+ return ni->std_fa & FILE_ATTRIBUTE_ENCRYPTED;
+}
+
+static inline bool is_sparsed(const struct ntfs_inode *ni)
+{
+ return ni->std_fa & FILE_ATTRIBUTE_SPARSE_FILE;
+}
+
+static inline int is_resident(struct ntfs_inode *ni)
+{
+ return ni->ni_flags & NI_FLAG_RESIDENT;
+}
+
+static inline void le16_sub_cpu(__le16 *var, u16 val)
+{
+ *var = cpu_to_le16(le16_to_cpu(*var) - val);
+}
+
+static inline void le32_sub_cpu(__le32 *var, u32 val)
+{
+ *var = cpu_to_le32(le32_to_cpu(*var) - val);
+}
+
+static inline void nb_put(struct ntfs_buffers *nb)
+{
+ u32 i, nbufs = nb->nbufs;
+
+ if (!nbufs)
+ return;
+
+ for (i = 0; i < nbufs; i++)
+ put_bh(nb->bh[i]);
+ nb->nbufs = 0;
+}
+
+static inline void put_indx_node(struct indx_node *in)
+{
+ if (!in)
+ return;
+
+ kfree(in->index);
+ nb_put(&in->nb);
+ kfree(in);
+}
+
+static inline void mi_clear(struct mft_inode *mi)
+{
+ nb_put(&mi->nb);
+ kfree(mi->mrec);
+ mi->mrec = NULL;
+}
+
+static inline void ni_lock(struct ntfs_inode *ni)
+{
+ mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_NORMAL);
+}
+
+static inline void ni_lock_dir(struct ntfs_inode *ni)
+{
+ mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_PARENT);
+}
+
+static inline void ni_unlock(struct ntfs_inode *ni)
+{
+ mutex_unlock(&ni->ni_lock);
+}
+
+static inline int ni_trylock(struct ntfs_inode *ni)
+{
+ return mutex_trylock(&ni->ni_lock);
+}
+
+static inline int attr_load_runs_attr(struct ntfs_inode *ni,
+ struct ATTRIB *attr,
+ struct runs_tree *run, CLST vcn)
+{
+ return attr_load_runs_vcn(ni, attr->type, attr_name(attr),
+ attr->name_len, run, vcn);
+}
+
+static inline void le64_sub_cpu(__le64 *var, u64 val)
+{
+ *var = cpu_to_le64(le64_to_cpu(*var) - val);
+}
+
+#endif /* _LINUX_NTFS3_NTFS_FS_H */
diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c
new file mode 100644
index 000000000000..103705c86772
--- /dev/null
+++ b/fs/ntfs3/record.c
@@ -0,0 +1,605 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+static inline int compare_attr(const struct ATTRIB *left, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len,
+ const u16 *upcase)
+{
+ /* First, compare the type codes. */
+ int diff = le32_to_cpu(left->type) - le32_to_cpu(type);
+
+ if (diff)
+ return diff;
+
+ /* They have the same type code, so we have to compare the names. */
+ return ntfs_cmp_names(attr_name(left), left->name_len, name, name_len,
+ upcase, true);
+}
+
+/*
+ * mi_new_attt_id
+ *
+ * Return: Unused attribute id that is less than mrec->next_attr_id.
+ */
+static __le16 mi_new_attt_id(struct mft_inode *mi)
+{
+ u16 free_id, max_id, t16;
+ struct MFT_REC *rec = mi->mrec;
+ struct ATTRIB *attr;
+ __le16 id;
+
+ id = rec->next_attr_id;
+ free_id = le16_to_cpu(id);
+ if (free_id < 0x7FFF) {
+ rec->next_attr_id = cpu_to_le16(free_id + 1);
+ return id;
+ }
+
+ /* One record can store up to 1024/24 ~= 42 attributes. */
+ free_id = 0;
+ max_id = 0;
+
+ attr = NULL;
+
+ for (;;) {
+ attr = mi_enum_attr(mi, attr);
+ if (!attr) {
+ rec->next_attr_id = cpu_to_le16(max_id + 1);
+ mi->dirty = true;
+ return cpu_to_le16(free_id);
+ }
+
+ t16 = le16_to_cpu(attr->id);
+ if (t16 == free_id) {
+ free_id += 1;
+ attr = NULL;
+ } else if (max_id < t16)
+ max_id = t16;
+ }
+}
+
+int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi)
+{
+ int err;
+ struct mft_inode *m = kzalloc(sizeof(struct mft_inode), GFP_NOFS);
+
+ if (!m)
+ return -ENOMEM;
+
+ err = mi_init(m, sbi, rno);
+ if (err) {
+ kfree(m);
+ return err;
+ }
+
+ err = mi_read(m, false);
+ if (err) {
+ mi_put(m);
+ return err;
+ }
+
+ *mi = m;
+ return 0;
+}
+
+void mi_put(struct mft_inode *mi)
+{
+ mi_clear(mi);
+ kfree(mi);
+}
+
+int mi_init(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno)
+{
+ mi->sbi = sbi;
+ mi->rno = rno;
+ mi->mrec = kmalloc(sbi->record_size, GFP_NOFS);
+ if (!mi->mrec)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/*
+ * mi_read - Read MFT data.
+ */
+int mi_read(struct mft_inode *mi, bool is_mft)
+{
+ int err;
+ struct MFT_REC *rec = mi->mrec;
+ struct ntfs_sb_info *sbi = mi->sbi;
+ u32 bpr = sbi->record_size;
+ u64 vbo = (u64)mi->rno << sbi->record_bits;
+ struct ntfs_inode *mft_ni = sbi->mft.ni;
+ struct runs_tree *run = mft_ni ? &mft_ni->file.run : NULL;
+ struct rw_semaphore *rw_lock = NULL;
+
+ if (is_mounted(sbi)) {
+ if (!is_mft) {
+ rw_lock = &mft_ni->file.run_lock;
+ down_read(rw_lock);
+ }
+ }
+
+ err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
+ if (rw_lock)
+ up_read(rw_lock);
+ if (!err)
+ goto ok;
+
+ if (err == -E_NTFS_FIXUP) {
+ mi->dirty = true;
+ goto ok;
+ }
+
+ if (err != -ENOENT)
+ goto out;
+
+ if (rw_lock) {
+ ni_lock(mft_ni);
+ down_write(rw_lock);
+ }
+ err = attr_load_runs_vcn(mft_ni, ATTR_DATA, NULL, 0, &mft_ni->file.run,
+ vbo >> sbi->cluster_bits);
+ if (rw_lock) {
+ up_write(rw_lock);
+ ni_unlock(mft_ni);
+ }
+ if (err)
+ goto out;
+
+ if (rw_lock)
+ down_read(rw_lock);
+ err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
+ if (rw_lock)
+ up_read(rw_lock);
+
+ if (err == -E_NTFS_FIXUP) {
+ mi->dirty = true;
+ goto ok;
+ }
+ if (err)
+ goto out;
+
+ok:
+ /* Check field 'total' only here. */
+ if (le32_to_cpu(rec->total) != bpr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ return 0;
+
+out:
+ return err;
+}
+
+struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
+{
+ const struct MFT_REC *rec = mi->mrec;
+ u32 used = le32_to_cpu(rec->used);
+ u32 t32, off, asize;
+ u16 t16;
+
+ if (!attr) {
+ u32 total = le32_to_cpu(rec->total);
+
+ off = le16_to_cpu(rec->attr_off);
+
+ if (used > total)
+ return NULL;
+
+ if (off >= used || off < MFTRECORD_FIXUP_OFFSET_1 ||
+ !IS_ALIGNED(off, 4)) {
+ return NULL;
+ }
+
+ /* Skip non-resident records. */
+ if (!is_rec_inuse(rec))
+ return NULL;
+
+ attr = Add2Ptr(rec, off);
+ } else {
+ /* Check if input attr inside record. */
+ off = PtrOffset(rec, attr);
+ if (off >= used)
+ return NULL;
+
+ asize = le32_to_cpu(attr->size);
+ if (asize < SIZEOF_RESIDENT) {
+ /* Impossible 'cause we should not return such attribute. */
+ return NULL;
+ }
+
+ attr = Add2Ptr(attr, asize);
+ off += asize;
+ }
+
+ asize = le32_to_cpu(attr->size);
+
+ /* Can we use the first field (attr->type). */
+ if (off + 8 > used) {
+ static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8);
+ return NULL;
+ }
+
+ if (attr->type == ATTR_END) {
+ /* End of enumeration. */
+ return NULL;
+ }
+
+ /* 0x100 is last known attribute for now. */
+ t32 = le32_to_cpu(attr->type);
+ if ((t32 & 0xf) || (t32 > 0x100))
+ return NULL;
+
+ /* Check boundary. */
+ if (off + asize > used)
+ return NULL;
+
+ /* Check size of attribute. */
+ if (!attr->non_res) {
+ if (asize < SIZEOF_RESIDENT)
+ return NULL;
+
+ t16 = le16_to_cpu(attr->res.data_off);
+
+ if (t16 > asize)
+ return NULL;
+
+ t32 = le32_to_cpu(attr->res.data_size);
+ if (t16 + t32 > asize)
+ return NULL;
+
+ return attr;
+ }
+
+ /* Check some nonresident fields. */
+ if (attr->name_len &&
+ le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
+ le16_to_cpu(attr->nres.run_off)) {
+ return NULL;
+ }
+
+ if (attr->nres.svcn || !is_attr_ext(attr)) {
+ if (asize + 8 < SIZEOF_NONRESIDENT)
+ return NULL;
+
+ if (attr->nres.c_unit)
+ return NULL;
+ } else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
+ return NULL;
+
+ return attr;
+}
+
+/*
+ * mi_find_attr - Find the attribute by type and name and id.
+ */
+struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
+ enum ATTR_TYPE type, const __le16 *name,
+ size_t name_len, const __le16 *id)
+{
+ u32 type_in = le32_to_cpu(type);
+ u32 atype;
+
+next_attr:
+ attr = mi_enum_attr(mi, attr);
+ if (!attr)
+ return NULL;
+
+ atype = le32_to_cpu(attr->type);
+ if (atype > type_in)
+ return NULL;
+
+ if (atype < type_in)
+ goto next_attr;
+
+ if (attr->name_len != name_len)
+ goto next_attr;
+
+ if (name_len && memcmp(attr_name(attr), name, name_len * sizeof(short)))
+ goto next_attr;
+
+ if (id && *id != attr->id)
+ goto next_attr;
+
+ return attr;
+}
+
+int mi_write(struct mft_inode *mi, int wait)
+{
+ struct MFT_REC *rec;
+ int err;
+ struct ntfs_sb_info *sbi;
+
+ if (!mi->dirty)
+ return 0;
+
+ sbi = mi->sbi;
+ rec = mi->mrec;
+
+ err = ntfs_write_bh(sbi, &rec->rhdr, &mi->nb, wait);
+ if (err)
+ return err;
+
+ if (mi->rno < sbi->mft.recs_mirr)
+ sbi->flags |= NTFS_FLAGS_MFTMIRR;
+
+ mi->dirty = false;
+
+ return 0;
+}
+
+int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
+ __le16 flags, bool is_mft)
+{
+ int err;
+ u16 seq = 1;
+ struct MFT_REC *rec;
+ u64 vbo = (u64)rno << sbi->record_bits;
+
+ err = mi_init(mi, sbi, rno);
+ if (err)
+ return err;
+
+ rec = mi->mrec;
+
+ if (rno == MFT_REC_MFT) {
+ ;
+ } else if (rno < MFT_REC_FREE) {
+ seq = rno;
+ } else if (rno >= sbi->mft.used) {
+ ;
+ } else if (mi_read(mi, is_mft)) {
+ ;
+ } else if (rec->rhdr.sign == NTFS_FILE_SIGNATURE) {
+ /* Record is reused. Update its sequence number. */
+ seq = le16_to_cpu(rec->seq) + 1;
+ if (!seq)
+ seq = 1;
+ }
+
+ memcpy(rec, sbi->new_rec, sbi->record_size);
+
+ rec->seq = cpu_to_le16(seq);
+ rec->flags = RECORD_FLAG_IN_USE | flags;
+
+ mi->dirty = true;
+
+ if (!mi->nb.nbufs) {
+ struct ntfs_inode *ni = sbi->mft.ni;
+ bool lock = false;
+
+ if (is_mounted(sbi) && !is_mft) {
+ down_read(&ni->file.run_lock);
+ lock = true;
+ }
+
+ err = ntfs_get_bh(sbi, &ni->file.run, vbo, sbi->record_size,
+ &mi->nb);
+ if (lock)
+ up_read(&ni->file.run_lock);
+ }
+
+ return err;
+}
+
+/*
+ * mi_mark_free - Mark record as unused and marks it as free in bitmap.
+ */
+void mi_mark_free(struct mft_inode *mi)
+{
+ CLST rno = mi->rno;
+ struct ntfs_sb_info *sbi = mi->sbi;
+
+ if (rno >= MFT_REC_RESERVED && rno < MFT_REC_FREE) {
+ ntfs_clear_mft_tail(sbi, rno, rno + 1);
+ mi->dirty = false;
+ return;
+ }
+
+ if (mi->mrec) {
+ clear_rec_inuse(mi->mrec);
+ mi->dirty = true;
+ mi_write(mi, 0);
+ }
+ ntfs_mark_rec_free(sbi, rno);
+}
+
+/*
+ * mi_insert_attr - Reserve space for new attribute.
+ *
+ * Return: Not full constructed attribute or NULL if not possible to create.
+ */
+struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
+ const __le16 *name, u8 name_len, u32 asize,
+ u16 name_off)
+{
+ size_t tail;
+ struct ATTRIB *attr;
+ __le16 id;
+ struct MFT_REC *rec = mi->mrec;
+ struct ntfs_sb_info *sbi = mi->sbi;
+ u32 used = le32_to_cpu(rec->used);
+ const u16 *upcase = sbi->upcase;
+ int diff;
+
+ /* Can we insert mi attribute? */
+ if (used + asize > mi->sbi->record_size)
+ return NULL;
+
+ /*
+ * Scan through the list of attributes to find the point
+ * at which we should insert it.
+ */
+ attr = NULL;
+ while ((attr = mi_enum_attr(mi, attr))) {
+ diff = compare_attr(attr, type, name, name_len, upcase);
+ if (diff > 0)
+ break;
+ if (diff < 0)
+ continue;
+
+ if (!is_attr_indexed(attr))
+ return NULL;
+ break;
+ }
+
+ if (!attr) {
+ tail = 8; /* Not used, just to suppress warning. */
+ attr = Add2Ptr(rec, used - 8);
+ } else {
+ tail = used - PtrOffset(rec, attr);
+ }
+
+ id = mi_new_attt_id(mi);
+
+ memmove(Add2Ptr(attr, asize), attr, tail);
+ memset(attr, 0, asize);
+
+ attr->type = type;
+ attr->size = cpu_to_le32(asize);
+ attr->name_len = name_len;
+ attr->name_off = cpu_to_le16(name_off);
+ attr->id = id;
+
+ memmove(Add2Ptr(attr, name_off), name, name_len * sizeof(short));
+ rec->used = cpu_to_le32(used + asize);
+
+ mi->dirty = true;
+
+ return attr;
+}
+
+/*
+ * mi_remove_attr - Remove the attribute from record.
+ *
+ * NOTE: The source attr will point to next attribute.
+ */
+bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
+ struct ATTRIB *attr)
+{
+ struct MFT_REC *rec = mi->mrec;
+ u32 aoff = PtrOffset(rec, attr);
+ u32 used = le32_to_cpu(rec->used);
+ u32 asize = le32_to_cpu(attr->size);
+
+ if (aoff + asize > used)
+ return false;
+
+ if (ni && is_attr_indexed(attr)) {
+ le16_add_cpu(&ni->mi.mrec->hard_links, -1);
+ ni->mi.dirty = true;
+ }
+
+ used -= asize;
+ memmove(attr, Add2Ptr(attr, asize), used - aoff);
+ rec->used = cpu_to_le32(used);
+ mi->dirty = true;
+
+ return true;
+}
+
+/* bytes = "new attribute size" - "old attribute size" */
+bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes)
+{
+ struct MFT_REC *rec = mi->mrec;
+ u32 aoff = PtrOffset(rec, attr);
+ u32 total, used = le32_to_cpu(rec->used);
+ u32 nsize, asize = le32_to_cpu(attr->size);
+ u32 rsize = le32_to_cpu(attr->res.data_size);
+ int tail = (int)(used - aoff - asize);
+ int dsize;
+ char *next;
+
+ if (tail < 0 || aoff >= used)
+ return false;
+
+ if (!bytes)
+ return true;
+
+ total = le32_to_cpu(rec->total);
+ next = Add2Ptr(attr, asize);
+
+ if (bytes > 0) {
+ dsize = ALIGN(bytes, 8);
+ if (used + dsize > total)
+ return false;
+ nsize = asize + dsize;
+ /* Move tail */
+ memmove(next + dsize, next, tail);
+ memset(next, 0, dsize);
+ used += dsize;
+ rsize += dsize;
+ } else {
+ dsize = ALIGN(-bytes, 8);
+ if (dsize > asize)
+ return false;
+ nsize = asize - dsize;
+ memmove(next - dsize, next, tail);
+ used -= dsize;
+ rsize -= dsize;
+ }
+
+ rec->used = cpu_to_le32(used);
+ attr->size = cpu_to_le32(nsize);
+ if (!attr->non_res)
+ attr->res.data_size = cpu_to_le32(rsize);
+ mi->dirty = true;
+
+ return true;
+}
+
+int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
+ struct runs_tree *run, CLST len)
+{
+ int err = 0;
+ struct ntfs_sb_info *sbi = mi->sbi;
+ u32 new_run_size;
+ CLST plen;
+ struct MFT_REC *rec = mi->mrec;
+ CLST svcn = le64_to_cpu(attr->nres.svcn);
+ u32 used = le32_to_cpu(rec->used);
+ u32 aoff = PtrOffset(rec, attr);
+ u32 asize = le32_to_cpu(attr->size);
+ char *next = Add2Ptr(attr, asize);
+ u16 run_off = le16_to_cpu(attr->nres.run_off);
+ u32 run_size = asize - run_off;
+ u32 tail = used - aoff - asize;
+ u32 dsize = sbi->record_size - used;
+
+ /* Make a maximum gap in current record. */
+ memmove(next + dsize, next, tail);
+
+ /* Pack as much as possible. */
+ err = run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size + dsize,
+ &plen);
+ if (err < 0) {
+ memmove(next, next + dsize, tail);
+ return err;
+ }
+
+ new_run_size = ALIGN(err, 8);
+
+ memmove(next + new_run_size - run_size, next + dsize, tail);
+
+ attr->size = cpu_to_le32(asize + new_run_size - run_size);
+ attr->nres.evcn = cpu_to_le64(svcn + plen - 1);
+ rec->used = cpu_to_le32(used + new_run_size - run_size);
+ mi->dirty = true;
+
+ return 0;
+}
diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c
new file mode 100644
index 000000000000..26ed2b64345e
--- /dev/null
+++ b/fs/ntfs3/run.c
@@ -0,0 +1,1113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ * TODO: try to use extents tree (instead of array)
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/log2.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+/* runs_tree is a continues memory. Try to avoid big size. */
+#define NTFS3_RUN_MAX_BYTES 0x10000
+
+struct ntfs_run {
+ CLST vcn; /* Virtual cluster number. */
+ CLST len; /* Length in clusters. */
+ CLST lcn; /* Logical cluster number. */
+};
+
+/*
+ * run_lookup - Lookup the index of a MCB entry that is first <= vcn.
+ *
+ * Case of success it will return non-zero value and set
+ * @index parameter to index of entry been found.
+ * Case of entry missing from list 'index' will be set to
+ * point to insertion position for the entry question.
+ */
+bool run_lookup(const struct runs_tree *run, CLST vcn, size_t *index)
+{
+ size_t min_idx, max_idx, mid_idx;
+ struct ntfs_run *r;
+
+ if (!run->count) {
+ *index = 0;
+ return false;
+ }
+
+ min_idx = 0;
+ max_idx = run->count - 1;
+
+ /* Check boundary cases specially, 'cause they cover the often requests. */
+ r = run->runs;
+ if (vcn < r->vcn) {
+ *index = 0;
+ return false;
+ }
+
+ if (vcn < r->vcn + r->len) {
+ *index = 0;
+ return true;
+ }
+
+ r += max_idx;
+ if (vcn >= r->vcn + r->len) {
+ *index = run->count;
+ return false;
+ }
+
+ if (vcn >= r->vcn) {
+ *index = max_idx;
+ return true;
+ }
+
+ do {
+ mid_idx = min_idx + ((max_idx - min_idx) >> 1);
+ r = run->runs + mid_idx;
+
+ if (vcn < r->vcn) {
+ max_idx = mid_idx - 1;
+ if (!mid_idx)
+ break;
+ } else if (vcn >= r->vcn + r->len) {
+ min_idx = mid_idx + 1;
+ } else {
+ *index = mid_idx;
+ return true;
+ }
+ } while (min_idx <= max_idx);
+
+ *index = max_idx + 1;
+ return false;
+}
+
+/*
+ * run_consolidate - Consolidate runs starting from a given one.
+ */
+static void run_consolidate(struct runs_tree *run, size_t index)
+{
+ size_t i;
+ struct ntfs_run *r = run->runs + index;
+
+ while (index + 1 < run->count) {
+ /*
+ * I should merge current run with next
+ * if start of the next run lies inside one being tested.
+ */
+ struct ntfs_run *n = r + 1;
+ CLST end = r->vcn + r->len;
+ CLST dl;
+
+ /* Stop if runs are not aligned one to another. */
+ if (n->vcn > end)
+ break;
+
+ dl = end - n->vcn;
+
+ /*
+ * If range at index overlaps with next one
+ * then I will either adjust it's start position
+ * or (if completely matches) dust remove one from the list.
+ */
+ if (dl > 0) {
+ if (n->len <= dl)
+ goto remove_next_range;
+
+ n->len -= dl;
+ n->vcn += dl;
+ if (n->lcn != SPARSE_LCN)
+ n->lcn += dl;
+ dl = 0;
+ }
+
+ /*
+ * Stop if sparse mode does not match
+ * both current and next runs.
+ */
+ if ((n->lcn == SPARSE_LCN) != (r->lcn == SPARSE_LCN)) {
+ index += 1;
+ r = n;
+ continue;
+ }
+
+ /*
+ * Check if volume block
+ * of a next run lcn does not match
+ * last volume block of the current run.
+ */
+ if (n->lcn != SPARSE_LCN && n->lcn != r->lcn + r->len)
+ break;
+
+ /*
+ * Next and current are siblings.
+ * Eat/join.
+ */
+ r->len += n->len - dl;
+
+remove_next_range:
+ i = run->count - (index + 1);
+ if (i > 1)
+ memmove(n, n + 1, sizeof(*n) * (i - 1));
+
+ run->count -= 1;
+ }
+}
+
+/*
+ * run_is_mapped_full
+ *
+ * Return: True if range [svcn - evcn] is mapped.
+ */
+bool run_is_mapped_full(const struct runs_tree *run, CLST svcn, CLST evcn)
+{
+ size_t i;
+ const struct ntfs_run *r, *end;
+ CLST next_vcn;
+
+ if (!run_lookup(run, svcn, &i))
+ return false;
+
+ end = run->runs + run->count;
+ r = run->runs + i;
+
+ for (;;) {
+ next_vcn = r->vcn + r->len;
+ if (next_vcn > evcn)
+ return true;
+
+ if (++r >= end)
+ return false;
+
+ if (r->vcn != next_vcn)
+ return false;
+ }
+}
+
+bool run_lookup_entry(const struct runs_tree *run, CLST vcn, CLST *lcn,
+ CLST *len, size_t *index)
+{
+ size_t idx;
+ CLST gap;
+ struct ntfs_run *r;
+
+ /* Fail immediately if nrun was not touched yet. */
+ if (!run->runs)
+ return false;
+
+ if (!run_lookup(run, vcn, &idx))
+ return false;
+
+ r = run->runs + idx;
+
+ if (vcn >= r->vcn + r->len)
+ return false;
+
+ gap = vcn - r->vcn;
+ if (r->len <= gap)
+ return false;
+
+ *lcn = r->lcn == SPARSE_LCN ? SPARSE_LCN : (r->lcn + gap);
+
+ if (len)
+ *len = r->len - gap;
+ if (index)
+ *index = idx;
+
+ return true;
+}
+
+/*
+ * run_truncate_head - Decommit the range before vcn.
+ */
+void run_truncate_head(struct runs_tree *run, CLST vcn)
+{
+ size_t index;
+ struct ntfs_run *r;
+
+ if (run_lookup(run, vcn, &index)) {
+ r = run->runs + index;
+
+ if (vcn > r->vcn) {
+ CLST dlen = vcn - r->vcn;
+
+ r->vcn = vcn;
+ r->len -= dlen;
+ if (r->lcn != SPARSE_LCN)
+ r->lcn += dlen;
+ }
+
+ if (!index)
+ return;
+ }
+ r = run->runs;
+ memmove(r, r + index, sizeof(*r) * (run->count - index));
+
+ run->count -= index;
+
+ if (!run->count) {
+ kvfree(run->runs);
+ run->runs = NULL;
+ run->allocated = 0;
+ }
+}
+
+/*
+ * run_truncate - Decommit the range after vcn.
+ */
+void run_truncate(struct runs_tree *run, CLST vcn)
+{
+ size_t index;
+
+ /*
+ * If I hit the range then
+ * I have to truncate one.
+ * If range to be truncated is becoming empty
+ * then it will entirely be removed.
+ */
+ if (run_lookup(run, vcn, &index)) {
+ struct ntfs_run *r = run->runs + index;
+
+ r->len = vcn - r->vcn;
+
+ if (r->len > 0)
+ index += 1;
+ }
+
+ /*
+ * At this point 'index' is set to position that
+ * should be thrown away (including index itself)
+ * Simple one - just set the limit.
+ */
+ run->count = index;
+
+ /* Do not reallocate array 'runs'. Only free if possible. */
+ if (!index) {
+ kvfree(run->runs);
+ run->runs = NULL;
+ run->allocated = 0;
+ }
+}
+
+/*
+ * run_truncate_around - Trim head and tail if necessary.
+ */
+void run_truncate_around(struct runs_tree *run, CLST vcn)
+{
+ run_truncate_head(run, vcn);
+
+ if (run->count >= NTFS3_RUN_MAX_BYTES / sizeof(struct ntfs_run) / 2)
+ run_truncate(run, (run->runs + (run->count >> 1))->vcn);
+}
+
+/*
+ * run_add_entry
+ *
+ * Sets location to known state.
+ * Run to be added may overlap with existing location.
+ *
+ * Return: false if of memory.
+ */
+bool run_add_entry(struct runs_tree *run, CLST vcn, CLST lcn, CLST len,
+ bool is_mft)
+{
+ size_t used, index;
+ struct ntfs_run *r;
+ bool inrange;
+ CLST tail_vcn = 0, tail_len = 0, tail_lcn = 0;
+ bool should_add_tail = false;
+
+ /*
+ * Lookup the insertion point.
+ *
+ * Execute bsearch for the entry containing
+ * start position question.
+ */
+ inrange = run_lookup(run, vcn, &index);
+
+ /*
+ * Shortcut here would be case of
+ * range not been found but one been added
+ * continues previous run.
+ * This case I can directly make use of
+ * existing range as my start point.
+ */
+ if (!inrange && index > 0) {
+ struct ntfs_run *t = run->runs + index - 1;
+
+ if (t->vcn + t->len == vcn &&
+ (t->lcn == SPARSE_LCN) == (lcn == SPARSE_LCN) &&
+ (lcn == SPARSE_LCN || lcn == t->lcn + t->len)) {
+ inrange = true;
+ index -= 1;
+ }
+ }
+
+ /*
+ * At this point 'index' either points to the range
+ * containing start position or to the insertion position
+ * for a new range.
+ * So first let's check if range I'm probing is here already.
+ */
+ if (!inrange) {
+requires_new_range:
+ /*
+ * Range was not found.
+ * Insert at position 'index'
+ */
+ used = run->count * sizeof(struct ntfs_run);
+
+ /*
+ * Check allocated space.
+ * If one is not enough to get one more entry
+ * then it will be reallocated.
+ */
+ if (run->allocated < used + sizeof(struct ntfs_run)) {
+ size_t bytes;
+ struct ntfs_run *new_ptr;
+
+ /* Use power of 2 for 'bytes'. */
+ if (!used) {
+ bytes = 64;
+ } else if (used <= 16 * PAGE_SIZE) {
+ if (is_power_of_2(run->allocated))
+ bytes = run->allocated << 1;
+ else
+ bytes = (size_t)1
+ << (2 + blksize_bits(used));
+ } else {
+ bytes = run->allocated + (16 * PAGE_SIZE);
+ }
+
+ WARN_ON(!is_mft && bytes > NTFS3_RUN_MAX_BYTES);
+
+ new_ptr = kvmalloc(bytes, GFP_KERNEL);
+
+ if (!new_ptr)
+ return false;
+
+ r = new_ptr + index;
+ memcpy(new_ptr, run->runs,
+ index * sizeof(struct ntfs_run));
+ memcpy(r + 1, run->runs + index,
+ sizeof(struct ntfs_run) * (run->count - index));
+
+ kvfree(run->runs);
+ run->runs = new_ptr;
+ run->allocated = bytes;
+
+ } else {
+ size_t i = run->count - index;
+
+ r = run->runs + index;
+
+ /* memmove appears to be a bottle neck here... */
+ if (i > 0)
+ memmove(r + 1, r, sizeof(struct ntfs_run) * i);
+ }
+
+ r->vcn = vcn;
+ r->lcn = lcn;
+ r->len = len;
+ run->count += 1;
+ } else {
+ r = run->runs + index;
+
+ /*
+ * If one of ranges was not allocated then we
+ * have to split location we just matched and
+ * insert current one.
+ * A common case this requires tail to be reinserted
+ * a recursive call.
+ */
+ if (((lcn == SPARSE_LCN) != (r->lcn == SPARSE_LCN)) ||
+ (lcn != SPARSE_LCN && lcn != r->lcn + (vcn - r->vcn))) {
+ CLST to_eat = vcn - r->vcn;
+ CLST Tovcn = to_eat + len;
+
+ should_add_tail = Tovcn < r->len;
+
+ if (should_add_tail) {
+ tail_lcn = r->lcn == SPARSE_LCN
+ ? SPARSE_LCN
+ : (r->lcn + Tovcn);
+ tail_vcn = r->vcn + Tovcn;
+ tail_len = r->len - Tovcn;
+ }
+
+ if (to_eat > 0) {
+ r->len = to_eat;
+ inrange = false;
+ index += 1;
+ goto requires_new_range;
+ }
+
+ /* lcn should match one were going to add. */
+ r->lcn = lcn;
+ }
+
+ /*
+ * If existing range fits then were done.
+ * Otherwise extend found one and fall back to range jocode.
+ */
+ if (r->vcn + r->len < vcn + len)
+ r->len += len - ((r->vcn + r->len) - vcn);
+ }
+
+ /*
+ * And normalize it starting from insertion point.
+ * It's possible that no insertion needed case if
+ * start point lies within the range of an entry
+ * that 'index' points to.
+ */
+ if (inrange && index > 0)
+ index -= 1;
+ run_consolidate(run, index);
+ run_consolidate(run, index + 1);
+
+ /*
+ * A special case.
+ * We have to add extra range a tail.
+ */
+ if (should_add_tail &&
+ !run_add_entry(run, tail_vcn, tail_lcn, tail_len, is_mft))
+ return false;
+
+ return true;
+}
+
+/* run_collapse_range
+ *
+ * Helper for attr_collapse_range(),
+ * which is helper for fallocate(collapse_range).
+ */
+bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len)
+{
+ size_t index, eat;
+ struct ntfs_run *r, *e, *eat_start, *eat_end;
+ CLST end;
+
+ if (WARN_ON(!run_lookup(run, vcn, &index)))
+ return true; /* Should never be here. */
+
+ e = run->runs + run->count;
+ r = run->runs + index;
+ end = vcn + len;
+
+ if (vcn > r->vcn) {
+ if (r->vcn + r->len <= end) {
+ /* Collapse tail of run .*/
+ r->len = vcn - r->vcn;
+ } else if (r->lcn == SPARSE_LCN) {
+ /* Collapse a middle part of sparsed run. */
+ r->len -= len;
+ } else {
+ /* Collapse a middle part of normal run, split. */
+ if (!run_add_entry(run, vcn, SPARSE_LCN, len, false))
+ return false;
+ return run_collapse_range(run, vcn, len);
+ }
+
+ r += 1;
+ }
+
+ eat_start = r;
+ eat_end = r;
+
+ for (; r < e; r++) {
+ CLST d;
+
+ if (r->vcn >= end) {
+ r->vcn -= len;
+ continue;
+ }
+
+ if (r->vcn + r->len <= end) {
+ /* Eat this run. */
+ eat_end = r + 1;
+ continue;
+ }
+
+ d = end - r->vcn;
+ if (r->lcn != SPARSE_LCN)
+ r->lcn += d;
+ r->len -= d;
+ r->vcn -= len - d;
+ }
+
+ eat = eat_end - eat_start;
+ memmove(eat_start, eat_end, (e - eat_end) * sizeof(*r));
+ run->count -= eat;
+
+ return true;
+}
+
+/*
+ * run_get_entry - Return index-th mapped region.
+ */
+bool run_get_entry(const struct runs_tree *run, size_t index, CLST *vcn,
+ CLST *lcn, CLST *len)
+{
+ const struct ntfs_run *r;
+
+ if (index >= run->count)
+ return false;
+
+ r = run->runs + index;
+
+ if (!r->len)
+ return false;
+
+ if (vcn)
+ *vcn = r->vcn;
+ if (lcn)
+ *lcn = r->lcn;
+ if (len)
+ *len = r->len;
+ return true;
+}
+
+/*
+ * run_packed_size - Calculate the size of packed int64.
+ */
+#ifdef __BIG_ENDIAN
+static inline int run_packed_size(const s64 n)
+{
+ const u8 *p = (const u8 *)&n + sizeof(n) - 1;
+
+ if (n >= 0) {
+ if (p[-7] || p[-6] || p[-5] || p[-4])
+ p -= 4;
+ if (p[-3] || p[-2])
+ p -= 2;
+ if (p[-1])
+ p -= 1;
+ if (p[0] & 0x80)
+ p -= 1;
+ } else {
+ if (p[-7] != 0xff || p[-6] != 0xff || p[-5] != 0xff ||
+ p[-4] != 0xff)
+ p -= 4;
+ if (p[-3] != 0xff || p[-2] != 0xff)
+ p -= 2;
+ if (p[-1] != 0xff)
+ p -= 1;
+ if (!(p[0] & 0x80))
+ p -= 1;
+ }
+ return (const u8 *)&n + sizeof(n) - p;
+}
+
+/* Full trusted function. It does not check 'size' for errors. */
+static inline void run_pack_s64(u8 *run_buf, u8 size, s64 v)
+{
+ const u8 *p = (u8 *)&v;
+
+ switch (size) {
+ case 8:
+ run_buf[7] = p[0];
+ fallthrough;
+ case 7:
+ run_buf[6] = p[1];
+ fallthrough;
+ case 6:
+ run_buf[5] = p[2];
+ fallthrough;
+ case 5:
+ run_buf[4] = p[3];
+ fallthrough;
+ case 4:
+ run_buf[3] = p[4];
+ fallthrough;
+ case 3:
+ run_buf[2] = p[5];
+ fallthrough;
+ case 2:
+ run_buf[1] = p[6];
+ fallthrough;
+ case 1:
+ run_buf[0] = p[7];
+ }
+}
+
+/* Full trusted function. It does not check 'size' for errors. */
+static inline s64 run_unpack_s64(const u8 *run_buf, u8 size, s64 v)
+{
+ u8 *p = (u8 *)&v;
+
+ switch (size) {
+ case 8:
+ p[0] = run_buf[7];
+ fallthrough;
+ case 7:
+ p[1] = run_buf[6];
+ fallthrough;
+ case 6:
+ p[2] = run_buf[5];
+ fallthrough;
+ case 5:
+ p[3] = run_buf[4];
+ fallthrough;
+ case 4:
+ p[4] = run_buf[3];
+ fallthrough;
+ case 3:
+ p[5] = run_buf[2];
+ fallthrough;
+ case 2:
+ p[6] = run_buf[1];
+ fallthrough;
+ case 1:
+ p[7] = run_buf[0];
+ }
+ return v;
+}
+
+#else
+
+static inline int run_packed_size(const s64 n)
+{
+ const u8 *p = (const u8 *)&n;
+
+ if (n >= 0) {
+ if (p[7] || p[6] || p[5] || p[4])
+ p += 4;
+ if (p[3] || p[2])
+ p += 2;
+ if (p[1])
+ p += 1;
+ if (p[0] & 0x80)
+ p += 1;
+ } else {
+ if (p[7] != 0xff || p[6] != 0xff || p[5] != 0xff ||
+ p[4] != 0xff)
+ p += 4;
+ if (p[3] != 0xff || p[2] != 0xff)
+ p += 2;
+ if (p[1] != 0xff)
+ p += 1;
+ if (!(p[0] & 0x80))
+ p += 1;
+ }
+
+ return 1 + p - (const u8 *)&n;
+}
+
+/* Full trusted function. It does not check 'size' for errors. */
+static inline void run_pack_s64(u8 *run_buf, u8 size, s64 v)
+{
+ const u8 *p = (u8 *)&v;
+
+ /* memcpy( run_buf, &v, size); Is it faster? */
+ switch (size) {
+ case 8:
+ run_buf[7] = p[7];
+ fallthrough;
+ case 7:
+ run_buf[6] = p[6];
+ fallthrough;
+ case 6:
+ run_buf[5] = p[5];
+ fallthrough;
+ case 5:
+ run_buf[4] = p[4];
+ fallthrough;
+ case 4:
+ run_buf[3] = p[3];
+ fallthrough;
+ case 3:
+ run_buf[2] = p[2];
+ fallthrough;
+ case 2:
+ run_buf[1] = p[1];
+ fallthrough;
+ case 1:
+ run_buf[0] = p[0];
+ }
+}
+
+/* full trusted function. It does not check 'size' for errors */
+static inline s64 run_unpack_s64(const u8 *run_buf, u8 size, s64 v)
+{
+ u8 *p = (u8 *)&v;
+
+ /* memcpy( &v, run_buf, size); Is it faster? */
+ switch (size) {
+ case 8:
+ p[7] = run_buf[7];
+ fallthrough;
+ case 7:
+ p[6] = run_buf[6];
+ fallthrough;
+ case 6:
+ p[5] = run_buf[5];
+ fallthrough;
+ case 5:
+ p[4] = run_buf[4];
+ fallthrough;
+ case 4:
+ p[3] = run_buf[3];
+ fallthrough;
+ case 3:
+ p[2] = run_buf[2];
+ fallthrough;
+ case 2:
+ p[1] = run_buf[1];
+ fallthrough;
+ case 1:
+ p[0] = run_buf[0];
+ }
+ return v;
+}
+#endif
+
+/*
+ * run_pack - Pack runs into buffer.
+ *
+ * packed_vcns - How much runs we have packed.
+ * packed_size - How much bytes we have used run_buf.
+ */
+int run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf,
+ u32 run_buf_size, CLST *packed_vcns)
+{
+ CLST next_vcn, vcn, lcn;
+ CLST prev_lcn = 0;
+ CLST evcn1 = svcn + len;
+ int packed_size = 0;
+ size_t i;
+ bool ok;
+ s64 dlcn;
+ int offset_size, size_size, tmp;
+
+ next_vcn = vcn = svcn;
+
+ *packed_vcns = 0;
+
+ if (!len)
+ goto out;
+
+ ok = run_lookup_entry(run, vcn, &lcn, &len, &i);
+
+ if (!ok)
+ goto error;
+
+ if (next_vcn != vcn)
+ goto error;
+
+ for (;;) {
+ next_vcn = vcn + len;
+ if (next_vcn > evcn1)
+ len = evcn1 - vcn;
+
+ /* How much bytes required to pack len. */
+ size_size = run_packed_size(len);
+
+ /* offset_size - How much bytes is packed dlcn. */
+ if (lcn == SPARSE_LCN) {
+ offset_size = 0;
+ dlcn = 0;
+ } else {
+ /* NOTE: lcn can be less than prev_lcn! */
+ dlcn = (s64)lcn - prev_lcn;
+ offset_size = run_packed_size(dlcn);
+ prev_lcn = lcn;
+ }
+
+ tmp = run_buf_size - packed_size - 2 - offset_size;
+ if (tmp <= 0)
+ goto out;
+
+ /* Can we store this entire run. */
+ if (tmp < size_size)
+ goto out;
+
+ if (run_buf) {
+ /* Pack run header. */
+ run_buf[0] = ((u8)(size_size | (offset_size << 4)));
+ run_buf += 1;
+
+ /* Pack the length of run. */
+ run_pack_s64(run_buf, size_size, len);
+
+ run_buf += size_size;
+ /* Pack the offset from previous LCN. */
+ run_pack_s64(run_buf, offset_size, dlcn);
+ run_buf += offset_size;
+ }
+
+ packed_size += 1 + offset_size + size_size;
+ *packed_vcns += len;
+
+ if (packed_size + 1 >= run_buf_size || next_vcn >= evcn1)
+ goto out;
+
+ ok = run_get_entry(run, ++i, &vcn, &lcn, &len);
+ if (!ok)
+ goto error;
+
+ if (next_vcn != vcn)
+ goto error;
+ }
+
+out:
+ /* Store last zero. */
+ if (run_buf)
+ run_buf[0] = 0;
+
+ return packed_size + 1;
+
+error:
+ return -EOPNOTSUPP;
+}
+
+/*
+ * run_unpack - Unpack packed runs from @run_buf.
+ *
+ * Return: Error if negative, or real used bytes.
+ */
+int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
+ CLST svcn, CLST evcn, CLST vcn, const u8 *run_buf,
+ u32 run_buf_size)
+{
+ u64 prev_lcn, vcn64, lcn, next_vcn;
+ const u8 *run_last, *run_0;
+ bool is_mft = ino == MFT_REC_MFT;
+
+ /* Check for empty. */
+ if (evcn + 1 == svcn)
+ return 0;
+
+ if (evcn < svcn)
+ return -EINVAL;
+
+ run_0 = run_buf;
+ run_last = run_buf + run_buf_size;
+ prev_lcn = 0;
+ vcn64 = svcn;
+
+ /* Read all runs the chain. */
+ /* size_size - How much bytes is packed len. */
+ while (run_buf < run_last) {
+ /* size_size - How much bytes is packed len. */
+ u8 size_size = *run_buf & 0xF;
+ /* offset_size - How much bytes is packed dlcn. */
+ u8 offset_size = *run_buf++ >> 4;
+ u64 len;
+
+ if (!size_size)
+ break;
+
+ /*
+ * Unpack runs.
+ * NOTE: Runs are stored little endian order
+ * "len" is unsigned value, "dlcn" is signed.
+ * Large positive number requires to store 5 bytes
+ * e.g.: 05 FF 7E FF FF 00 00 00
+ */
+ if (size_size > 8)
+ return -EINVAL;
+
+ len = run_unpack_s64(run_buf, size_size, 0);
+ /* Skip size_size. */
+ run_buf += size_size;
+
+ if (!len)
+ return -EINVAL;
+
+ if (!offset_size)
+ lcn = SPARSE_LCN64;
+ else if (offset_size <= 8) {
+ s64 dlcn;
+
+ /* Initial value of dlcn is -1 or 0. */
+ dlcn = (run_buf[offset_size - 1] & 0x80) ? (s64)-1 : 0;
+ dlcn = run_unpack_s64(run_buf, offset_size, dlcn);
+ /* Skip offset_size. */
+ run_buf += offset_size;
+
+ if (!dlcn)
+ return -EINVAL;
+ lcn = prev_lcn + dlcn;
+ prev_lcn = lcn;
+ } else
+ return -EINVAL;
+
+ next_vcn = vcn64 + len;
+ /* Check boundary. */
+ if (next_vcn > evcn + 1)
+ return -EINVAL;
+
+#ifndef CONFIG_NTFS3_64BIT_CLUSTER
+ if (next_vcn > 0x100000000ull || (lcn + len) > 0x100000000ull) {
+ ntfs_err(
+ sbi->sb,
+ "This driver is compiled without CONFIG_NTFS3_64BIT_CLUSTER (like windows driver).\n"
+ "Volume contains 64 bits run: vcn %llx, lcn %llx, len %llx.\n"
+ "Activate CONFIG_NTFS3_64BIT_CLUSTER to process this case",
+ vcn64, lcn, len);
+ return -EOPNOTSUPP;
+ }
+#endif
+ if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) {
+ /* LCN range is out of volume. */
+ return -EINVAL;
+ }
+
+ if (!run)
+ ; /* Called from check_attr(fslog.c) to check run. */
+ else if (run == RUN_DEALLOCATE) {
+ /*
+ * Called from ni_delete_all to free clusters
+ * without storing in run.
+ */
+ if (lcn != SPARSE_LCN64)
+ mark_as_free_ex(sbi, lcn, len, true);
+ } else if (vcn64 >= vcn) {
+ if (!run_add_entry(run, vcn64, lcn, len, is_mft))
+ return -ENOMEM;
+ } else if (next_vcn > vcn) {
+ u64 dlen = vcn - vcn64;
+
+ if (!run_add_entry(run, vcn, lcn + dlen, len - dlen,
+ is_mft))
+ return -ENOMEM;
+ }
+
+ vcn64 = next_vcn;
+ }
+
+ if (vcn64 != evcn + 1) {
+ /* Not expected length of unpacked runs. */
+ return -EINVAL;
+ }
+
+ return run_buf - run_0;
+}
+
+#ifdef NTFS3_CHECK_FREE_CLST
+/*
+ * run_unpack_ex - Unpack packed runs from "run_buf".
+ *
+ * Checks unpacked runs to be used in bitmap.
+ *
+ * Return: Error if negative, or real used bytes.
+ */
+int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
+ CLST svcn, CLST evcn, CLST vcn, const u8 *run_buf,
+ u32 run_buf_size)
+{
+ int ret, err;
+ CLST next_vcn, lcn, len;
+ size_t index;
+ bool ok;
+ struct wnd_bitmap *wnd;
+
+ ret = run_unpack(run, sbi, ino, svcn, evcn, vcn, run_buf, run_buf_size);
+ if (ret <= 0)
+ return ret;
+
+ if (!sbi->used.bitmap.sb || !run || run == RUN_DEALLOCATE)
+ return ret;
+
+ if (ino == MFT_REC_BADCLUST)
+ return ret;
+
+ next_vcn = vcn = svcn;
+ wnd = &sbi->used.bitmap;
+
+ for (ok = run_lookup_entry(run, vcn, &lcn, &len, &index);
+ next_vcn <= evcn;
+ ok = run_get_entry(run, ++index, &vcn, &lcn, &len)) {
+ if (!ok || next_vcn != vcn)
+ return -EINVAL;
+
+ next_vcn = vcn + len;
+
+ if (lcn == SPARSE_LCN)
+ continue;
+
+ if (sbi->flags & NTFS_FLAGS_NEED_REPLAY)
+ continue;
+
+ down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
+ /* Check for free blocks. */
+ ok = wnd_is_used(wnd, lcn, len);
+ up_read(&wnd->rw_lock);
+ if (ok)
+ continue;
+
+ /* Looks like volume is corrupted. */
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+
+ if (down_write_trylock(&wnd->rw_lock)) {
+ /* Mark all zero bits as used in range [lcn, lcn+len). */
+ CLST i, lcn_f = 0, len_f = 0;
+
+ err = 0;
+ for (i = 0; i < len; i++) {
+ if (wnd_is_free(wnd, lcn + i, 1)) {
+ if (!len_f)
+ lcn_f = lcn + i;
+ len_f += 1;
+ } else if (len_f) {
+ err = wnd_set_used(wnd, lcn_f, len_f);
+ len_f = 0;
+ if (err)
+ break;
+ }
+ }
+
+ if (len_f)
+ err = wnd_set_used(wnd, lcn_f, len_f);
+
+ up_write(&wnd->rw_lock);
+ if (err)
+ return err;
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/*
+ * run_get_highest_vcn
+ *
+ * Return the highest vcn from a mapping pairs array
+ * it used while replaying log file.
+ */
+int run_get_highest_vcn(CLST vcn, const u8 *run_buf, u64 *highest_vcn)
+{
+ u64 vcn64 = vcn;
+ u8 size_size;
+
+ while ((size_size = *run_buf & 0xF)) {
+ u8 offset_size = *run_buf++ >> 4;
+ u64 len;
+
+ if (size_size > 8 || offset_size > 8)
+ return -EINVAL;
+
+ len = run_unpack_s64(run_buf, size_size, 0);
+ if (!len)
+ return -EINVAL;
+
+ run_buf += size_size + offset_size;
+ vcn64 += len;
+
+#ifndef CONFIG_NTFS3_64BIT_CLUSTER
+ if (vcn64 > 0x100000000ull)
+ return -EINVAL;
+#endif
+ }
+
+ *highest_vcn = vcn64 - 1;
+ return 0;
+}
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
new file mode 100644
index 000000000000..55bbc9200a10
--- /dev/null
+++ b/fs/ntfs3/super.c
@@ -0,0 +1,1512 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ *
+ * terminology
+ *
+ * cluster - allocation unit - 512,1K,2K,4K,...,2M
+ * vcn - virtual cluster number - Offset inside the file in clusters.
+ * vbo - virtual byte offset - Offset inside the file in bytes.
+ * lcn - logical cluster number - 0 based cluster in clusters heap.
+ * lbo - logical byte offset - Absolute position inside volume.
+ * run - maps VCN to LCN - Stored in attributes in packed form.
+ * attr - attribute segment - std/name/data etc records inside MFT.
+ * mi - MFT inode - One MFT record(usually 1024 bytes or 4K), consists of attributes.
+ * ni - NTFS inode - Extends linux inode. consists of one or more mft inodes.
+ * index - unit inside directory - 2K, 4K, <=page size, does not depend on cluster size.
+ *
+ * WSL - Windows Subsystem for Linux
+ * https://docs.microsoft.com/en-us/windows/wsl/file-permissions
+ * It stores uid/gid/mode/dev in xattr
+ *
+ */
+
+#include <linux/backing-dev.h>
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
+#include <linux/fs.h>
+#include <linux/iversion.h>
+#include <linux/log2.h>
+#include <linux/module.h>
+#include <linux/nls.h>
+#include <linux/parser.h>
+#include <linux/seq_file.h>
+#include <linux/statfs.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+#include "lib/lib.h"
+#endif
+
+#ifdef CONFIG_PRINTK
+/*
+ * ntfs_printk - Trace warnings/notices/errors.
+ *
+ * Thanks Joe Perches <joe@perches.com> for implementation
+ */
+void ntfs_printk(const struct super_block *sb, const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int level;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+
+ /* Should we use different ratelimits for warnings/notices/errors? */
+ if (!___ratelimit(&sbi->msg_ratelimit, "ntfs3"))
+ return;
+
+ va_start(args, fmt);
+
+ level = printk_get_level(fmt);
+ vaf.fmt = printk_skip_level(fmt);
+ vaf.va = &args;
+ printk("%c%cntfs3: %s: %pV\n", KERN_SOH_ASCII, level, sb->s_id, &vaf);
+
+ va_end(args);
+}
+
+static char s_name_buf[512];
+static atomic_t s_name_buf_cnt = ATOMIC_INIT(1); // 1 means 'free s_name_buf'.
+
+/*
+ * ntfs_inode_printk
+ *
+ * Print warnings/notices/errors about inode using name or inode number.
+ */
+void ntfs_inode_printk(struct inode *inode, const char *fmt, ...)
+{
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ char *name;
+ va_list args;
+ struct va_format vaf;
+ int level;
+
+ if (!___ratelimit(&sbi->msg_ratelimit, "ntfs3"))
+ return;
+
+ /* Use static allocated buffer, if possible. */
+ name = atomic_dec_and_test(&s_name_buf_cnt)
+ ? s_name_buf
+ : kmalloc(sizeof(s_name_buf), GFP_NOFS);
+
+ if (name) {
+ struct dentry *de = d_find_alias(inode);
+ const u32 name_len = ARRAY_SIZE(s_name_buf) - 1;
+
+ if (de) {
+ spin_lock(&de->d_lock);
+ snprintf(name, name_len, " \"%s\"", de->d_name.name);
+ spin_unlock(&de->d_lock);
+ name[name_len] = 0; /* To be sure. */
+ } else {
+ name[0] = 0;
+ }
+ dput(de); /* Cocci warns if placed in branch "if (de)" */
+ }
+
+ va_start(args, fmt);
+
+ level = printk_get_level(fmt);
+ vaf.fmt = printk_skip_level(fmt);
+ vaf.va = &args;
+
+ printk("%c%cntfs3: %s: ino=%lx,%s %pV\n", KERN_SOH_ASCII, level,
+ sb->s_id, inode->i_ino, name ? name : "", &vaf);
+
+ va_end(args);
+
+ atomic_inc(&s_name_buf_cnt);
+ if (name != s_name_buf)
+ kfree(name);
+}
+#endif
+
+/*
+ * Shared memory struct.
+ *
+ * On-disk ntfs's upcase table is created by ntfs formatter.
+ * 'upcase' table is 128K bytes of memory.
+ * We should read it into memory when mounting.
+ * Several ntfs volumes likely use the same 'upcase' table.
+ * It is good idea to share in-memory 'upcase' table between different volumes.
+ * Unfortunately winxp/vista/win7 use different upcase tables.
+ */
+static DEFINE_SPINLOCK(s_shared_lock);
+
+static struct {
+ void *ptr;
+ u32 len;
+ int cnt;
+} s_shared[8];
+
+/*
+ * ntfs_set_shared
+ *
+ * Return:
+ * * @ptr - If pointer was saved in shared memory.
+ * * NULL - If pointer was not shared.
+ */
+void *ntfs_set_shared(void *ptr, u32 bytes)
+{
+ void *ret = NULL;
+ int i, j = -1;
+
+ spin_lock(&s_shared_lock);
+ for (i = 0; i < ARRAY_SIZE(s_shared); i++) {
+ if (!s_shared[i].cnt) {
+ j = i;
+ } else if (bytes == s_shared[i].len &&
+ !memcmp(s_shared[i].ptr, ptr, bytes)) {
+ s_shared[i].cnt += 1;
+ ret = s_shared[i].ptr;
+ break;
+ }
+ }
+
+ if (!ret && j != -1) {
+ s_shared[j].ptr = ptr;
+ s_shared[j].len = bytes;
+ s_shared[j].cnt = 1;
+ ret = ptr;
+ }
+ spin_unlock(&s_shared_lock);
+
+ return ret;
+}
+
+/*
+ * ntfs_put_shared
+ *
+ * Return:
+ * * @ptr - If pointer is not shared anymore.
+ * * NULL - If pointer is still shared.
+ */
+void *ntfs_put_shared(void *ptr)
+{
+ void *ret = ptr;
+ int i;
+
+ spin_lock(&s_shared_lock);
+ for (i = 0; i < ARRAY_SIZE(s_shared); i++) {
+ if (s_shared[i].cnt && s_shared[i].ptr == ptr) {
+ if (--s_shared[i].cnt)
+ ret = NULL;
+ break;
+ }
+ }
+ spin_unlock(&s_shared_lock);
+
+ return ret;
+}
+
+static inline void clear_mount_options(struct ntfs_mount_options *options)
+{
+ unload_nls(options->nls);
+}
+
+enum Opt {
+ Opt_uid,
+ Opt_gid,
+ Opt_umask,
+ Opt_dmask,
+ Opt_fmask,
+ Opt_immutable,
+ Opt_discard,
+ Opt_force,
+ Opt_sparse,
+ Opt_nohidden,
+ Opt_showmeta,
+ Opt_acl,
+ Opt_noatime,
+ Opt_nls,
+ Opt_prealloc,
+ Opt_no_acs_rules,
+ Opt_err,
+};
+
+static const match_table_t ntfs_tokens = {
+ { Opt_uid, "uid=%u" },
+ { Opt_gid, "gid=%u" },
+ { Opt_umask, "umask=%o" },
+ { Opt_dmask, "dmask=%o" },
+ { Opt_fmask, "fmask=%o" },
+ { Opt_immutable, "sys_immutable" },
+ { Opt_discard, "discard" },
+ { Opt_force, "force" },
+ { Opt_sparse, "sparse" },
+ { Opt_nohidden, "nohidden" },
+ { Opt_acl, "acl" },
+ { Opt_noatime, "noatime" },
+ { Opt_showmeta, "showmeta" },
+ { Opt_nls, "nls=%s" },
+ { Opt_prealloc, "prealloc" },
+ { Opt_no_acs_rules, "no_acs_rules" },
+ { Opt_err, NULL },
+};
+
+static noinline int ntfs_parse_options(struct super_block *sb, char *options,
+ int silent,
+ struct ntfs_mount_options *opts)
+{
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int option;
+ char nls_name[30];
+ struct nls_table *nls;
+
+ opts->fs_uid = current_uid();
+ opts->fs_gid = current_gid();
+ opts->fs_fmask_inv = opts->fs_dmask_inv = ~current_umask();
+ nls_name[0] = 0;
+
+ if (!options)
+ goto out;
+
+ while ((p = strsep(&options, ","))) {
+ int token;
+
+ if (!*p)
+ continue;
+
+ token = match_token(p, ntfs_tokens, args);
+ switch (token) {
+ case Opt_immutable:
+ opts->sys_immutable = 1;
+ break;
+ case Opt_uid:
+ if (match_int(&args[0], &option))
+ return -EINVAL;
+ opts->fs_uid = make_kuid(current_user_ns(), option);
+ if (!uid_valid(opts->fs_uid))
+ return -EINVAL;
+ opts->uid = 1;
+ break;
+ case Opt_gid:
+ if (match_int(&args[0], &option))
+ return -EINVAL;
+ opts->fs_gid = make_kgid(current_user_ns(), option);
+ if (!gid_valid(opts->fs_gid))
+ return -EINVAL;
+ opts->gid = 1;
+ break;
+ case Opt_umask:
+ if (match_octal(&args[0], &option))
+ return -EINVAL;
+ opts->fs_fmask_inv = opts->fs_dmask_inv = ~option;
+ opts->fmask = opts->dmask = 1;
+ break;
+ case Opt_dmask:
+ if (match_octal(&args[0], &option))
+ return -EINVAL;
+ opts->fs_dmask_inv = ~option;
+ opts->dmask = 1;
+ break;
+ case Opt_fmask:
+ if (match_octal(&args[0], &option))
+ return -EINVAL;
+ opts->fs_fmask_inv = ~option;
+ opts->fmask = 1;
+ break;
+ case Opt_discard:
+ opts->discard = 1;
+ break;
+ case Opt_force:
+ opts->force = 1;
+ break;
+ case Opt_sparse:
+ opts->sparse = 1;
+ break;
+ case Opt_nohidden:
+ opts->nohidden = 1;
+ break;
+ case Opt_acl:
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+ sb->s_flags |= SB_POSIXACL;
+ break;
+#else
+ ntfs_err(sb, "support for ACL not compiled in!");
+ return -EINVAL;
+#endif
+ case Opt_noatime:
+ sb->s_flags |= SB_NOATIME;
+ break;
+ case Opt_showmeta:
+ opts->showmeta = 1;
+ break;
+ case Opt_nls:
+ match_strlcpy(nls_name, &args[0], sizeof(nls_name));
+ break;
+ case Opt_prealloc:
+ opts->prealloc = 1;
+ break;
+ case Opt_no_acs_rules:
+ opts->no_acs_rules = 1;
+ break;
+ default:
+ if (!silent)
+ ntfs_err(
+ sb,
+ "Unrecognized mount option \"%s\" or missing value",
+ p);
+ //return -EINVAL;
+ }
+ }
+
+out:
+ if (!strcmp(nls_name[0] ? nls_name : CONFIG_NLS_DEFAULT, "utf8")) {
+ /*
+ * For UTF-8 use utf16s_to_utf8s()/utf8s_to_utf16s()
+ * instead of NLS.
+ */
+ nls = NULL;
+ } else if (nls_name[0]) {
+ nls = load_nls(nls_name);
+ if (!nls) {
+ ntfs_err(sb, "failed to load \"%s\"", nls_name);
+ return -EINVAL;
+ }
+ } else {
+ nls = load_nls_default();
+ if (!nls) {
+ ntfs_err(sb, "failed to load default nls");
+ return -EINVAL;
+ }
+ }
+ opts->nls = nls;
+
+ return 0;
+}
+
+static int ntfs_remount(struct super_block *sb, int *flags, char *data)
+{
+ int err, ro_rw;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct ntfs_mount_options old_opts;
+ char *orig_data = kstrdup(data, GFP_KERNEL);
+
+ if (data && !orig_data)
+ return -ENOMEM;
+
+ /* Store original options. */
+ memcpy(&old_opts, &sbi->options, sizeof(old_opts));
+ clear_mount_options(&sbi->options);
+ memset(&sbi->options, 0, sizeof(sbi->options));
+
+ err = ntfs_parse_options(sb, data, 0, &sbi->options);
+ if (err)
+ goto restore_opts;
+
+ ro_rw = sb_rdonly(sb) && !(*flags & SB_RDONLY);
+ if (ro_rw && (sbi->flags & NTFS_FLAGS_NEED_REPLAY)) {
+ ntfs_warn(
+ sb,
+ "Couldn't remount rw because journal is not replayed. Please umount/remount instead\n");
+ err = -EINVAL;
+ goto restore_opts;
+ }
+
+ sync_filesystem(sb);
+
+ if (ro_rw && (sbi->volume.flags & VOLUME_FLAG_DIRTY) &&
+ !sbi->options.force) {
+ ntfs_warn(sb, "volume is dirty and \"force\" flag is not set!");
+ err = -EINVAL;
+ goto restore_opts;
+ }
+
+ clear_mount_options(&old_opts);
+
+ *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME) |
+ SB_NODIRATIME | SB_NOATIME;
+ ntfs_info(sb, "re-mounted. Opts: %s", orig_data);
+ err = 0;
+ goto out;
+
+restore_opts:
+ clear_mount_options(&sbi->options);
+ memcpy(&sbi->options, &old_opts, sizeof(old_opts));
+
+out:
+ kfree(orig_data);
+ return err;
+}
+
+static struct kmem_cache *ntfs_inode_cachep;
+
+static struct inode *ntfs_alloc_inode(struct super_block *sb)
+{
+ struct ntfs_inode *ni = kmem_cache_alloc(ntfs_inode_cachep, GFP_NOFS);
+
+ if (!ni)
+ return NULL;
+
+ memset(ni, 0, offsetof(struct ntfs_inode, vfs_inode));
+
+ mutex_init(&ni->ni_lock);
+
+ return &ni->vfs_inode;
+}
+
+static void ntfs_i_callback(struct rcu_head *head)
+{
+ struct inode *inode = container_of(head, struct inode, i_rcu);
+ struct ntfs_inode *ni = ntfs_i(inode);
+
+ mutex_destroy(&ni->ni_lock);
+
+ kmem_cache_free(ntfs_inode_cachep, ni);
+}
+
+static void ntfs_destroy_inode(struct inode *inode)
+{
+ call_rcu(&inode->i_rcu, ntfs_i_callback);
+}
+
+static void init_once(void *foo)
+{
+ struct ntfs_inode *ni = foo;
+
+ inode_init_once(&ni->vfs_inode);
+}
+
+/*
+ * put_ntfs - Noinline to reduce binary size.
+ */
+static noinline void put_ntfs(struct ntfs_sb_info *sbi)
+{
+ kfree(sbi->new_rec);
+ kvfree(ntfs_put_shared(sbi->upcase));
+ kfree(sbi->def_table);
+
+ wnd_close(&sbi->mft.bitmap);
+ wnd_close(&sbi->used.bitmap);
+
+ if (sbi->mft.ni)
+ iput(&sbi->mft.ni->vfs_inode);
+
+ if (sbi->security.ni)
+ iput(&sbi->security.ni->vfs_inode);
+
+ if (sbi->reparse.ni)
+ iput(&sbi->reparse.ni->vfs_inode);
+
+ if (sbi->objid.ni)
+ iput(&sbi->objid.ni->vfs_inode);
+
+ if (sbi->volume.ni)
+ iput(&sbi->volume.ni->vfs_inode);
+
+ ntfs_update_mftmirr(sbi, 0);
+
+ indx_clear(&sbi->security.index_sii);
+ indx_clear(&sbi->security.index_sdh);
+ indx_clear(&sbi->reparse.index_r);
+ indx_clear(&sbi->objid.index_o);
+ kfree(sbi->compress.lznt);
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+ xpress_free_decompressor(sbi->compress.xpress);
+ lzx_free_decompressor(sbi->compress.lzx);
+#endif
+ clear_mount_options(&sbi->options);
+
+ kfree(sbi);
+}
+
+static void ntfs_put_super(struct super_block *sb)
+{
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+
+ /* Mark rw ntfs as clear, if possible. */
+ ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
+
+ put_ntfs(sbi);
+
+ sync_blockdev(sb->s_bdev);
+}
+
+static int ntfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+ struct super_block *sb = dentry->d_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct wnd_bitmap *wnd = &sbi->used.bitmap;
+
+ buf->f_type = sb->s_magic;
+ buf->f_bsize = sbi->cluster_size;
+ buf->f_blocks = wnd->nbits;
+
+ buf->f_bfree = buf->f_bavail = wnd_zeroes(wnd);
+ buf->f_fsid.val[0] = sbi->volume.ser_num;
+ buf->f_fsid.val[1] = (sbi->volume.ser_num >> 32);
+ buf->f_namelen = NTFS_NAME_LEN;
+
+ return 0;
+}
+
+static int ntfs_show_options(struct seq_file *m, struct dentry *root)
+{
+ struct super_block *sb = root->d_sb;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct ntfs_mount_options *opts = &sbi->options;
+ struct user_namespace *user_ns = seq_user_ns(m);
+
+ if (opts->uid)
+ seq_printf(m, ",uid=%u",
+ from_kuid_munged(user_ns, opts->fs_uid));
+ if (opts->gid)
+ seq_printf(m, ",gid=%u",
+ from_kgid_munged(user_ns, opts->fs_gid));
+ if (opts->fmask)
+ seq_printf(m, ",fmask=%04o", ~opts->fs_fmask_inv);
+ if (opts->dmask)
+ seq_printf(m, ",dmask=%04o", ~opts->fs_dmask_inv);
+ if (opts->nls)
+ seq_printf(m, ",nls=%s", opts->nls->charset);
+ else
+ seq_puts(m, ",nls=utf8");
+ if (opts->sys_immutable)
+ seq_puts(m, ",sys_immutable");
+ if (opts->discard)
+ seq_puts(m, ",discard");
+ if (opts->sparse)
+ seq_puts(m, ",sparse");
+ if (opts->showmeta)
+ seq_puts(m, ",showmeta");
+ if (opts->nohidden)
+ seq_puts(m, ",nohidden");
+ if (opts->force)
+ seq_puts(m, ",force");
+ if (opts->no_acs_rules)
+ seq_puts(m, ",no_acs_rules");
+ if (opts->prealloc)
+ seq_puts(m, ",prealloc");
+ if (sb->s_flags & SB_POSIXACL)
+ seq_puts(m, ",acl");
+ if (sb->s_flags & SB_NOATIME)
+ seq_puts(m, ",noatime");
+
+ return 0;
+}
+
+/*
+ * ntfs_sync_fs - super_operations::sync_fs
+ */
+static int ntfs_sync_fs(struct super_block *sb, int wait)
+{
+ int err = 0, err2;
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct ntfs_inode *ni;
+ struct inode *inode;
+
+ ni = sbi->security.ni;
+ if (ni) {
+ inode = &ni->vfs_inode;
+ err2 = _ni_write_inode(inode, wait);
+ if (err2 && !err)
+ err = err2;
+ }
+
+ ni = sbi->objid.ni;
+ if (ni) {
+ inode = &ni->vfs_inode;
+ err2 = _ni_write_inode(inode, wait);
+ if (err2 && !err)
+ err = err2;
+ }
+
+ ni = sbi->reparse.ni;
+ if (ni) {
+ inode = &ni->vfs_inode;
+ err2 = _ni_write_inode(inode, wait);
+ if (err2 && !err)
+ err = err2;
+ }
+
+ if (!err)
+ ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
+
+ ntfs_update_mftmirr(sbi, wait);
+
+ return err;
+}
+
+static const struct super_operations ntfs_sops = {
+ .alloc_inode = ntfs_alloc_inode,
+ .destroy_inode = ntfs_destroy_inode,
+ .evict_inode = ntfs_evict_inode,
+ .put_super = ntfs_put_super,
+ .statfs = ntfs_statfs,
+ .show_options = ntfs_show_options,
+ .sync_fs = ntfs_sync_fs,
+ .remount_fs = ntfs_remount,
+ .write_inode = ntfs3_write_inode,
+};
+
+static struct inode *ntfs_export_get_inode(struct super_block *sb, u64 ino,
+ u32 generation)
+{
+ struct MFT_REF ref;
+ struct inode *inode;
+
+ ref.low = cpu_to_le32(ino);
+#ifdef CONFIG_NTFS3_64BIT_CLUSTER
+ ref.high = cpu_to_le16(ino >> 32);
+#else
+ ref.high = 0;
+#endif
+ ref.seq = cpu_to_le16(generation);
+
+ inode = ntfs_iget5(sb, &ref, NULL);
+ if (!IS_ERR(inode) && is_bad_inode(inode)) {
+ iput(inode);
+ inode = ERR_PTR(-ESTALE);
+ }
+
+ return inode;
+}
+
+static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ ntfs_export_get_inode);
+}
+
+static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ ntfs_export_get_inode);
+}
+
+/* TODO: == ntfs_sync_inode */
+static int ntfs_nfs_commit_metadata(struct inode *inode)
+{
+ return _ni_write_inode(inode, 1);
+}
+
+static const struct export_operations ntfs_export_ops = {
+ .fh_to_dentry = ntfs_fh_to_dentry,
+ .fh_to_parent = ntfs_fh_to_parent,
+ .get_parent = ntfs3_get_parent,
+ .commit_metadata = ntfs_nfs_commit_metadata,
+};
+
+/*
+ * format_size_gb - Return Gb,Mb to print with "%u.%02u Gb".
+ */
+static u32 format_size_gb(const u64 bytes, u32 *mb)
+{
+ /* Do simple right 30 bit shift of 64 bit value. */
+ u64 kbytes = bytes >> 10;
+ u32 kbytes32 = kbytes;
+
+ *mb = (100 * (kbytes32 & 0xfffff) + 0x7ffff) >> 20;
+ if (*mb >= 100)
+ *mb = 99;
+
+ return (kbytes32 >> 20) | (((u32)(kbytes >> 32)) << 12);
+}
+
+static u32 true_sectors_per_clst(const struct NTFS_BOOT *boot)
+{
+ return boot->sectors_per_clusters <= 0x80
+ ? boot->sectors_per_clusters
+ : (1u << (0 - boot->sectors_per_clusters));
+}
+
+/*
+ * ntfs_init_from_boot - Init internal info from on-disk boot sector.
+ */
+static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
+ u64 dev_size)
+{
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ int err;
+ u32 mb, gb, boot_sector_size, sct_per_clst, record_size;
+ u64 sectors, clusters, fs_size, mlcn, mlcn2;
+ struct NTFS_BOOT *boot;
+ struct buffer_head *bh;
+ struct MFT_REC *rec;
+ u16 fn, ao;
+
+ sbi->volume.blocks = dev_size >> PAGE_SHIFT;
+
+ bh = ntfs_bread(sb, 0);
+ if (!bh)
+ return -EIO;
+
+ err = -EINVAL;
+ boot = (struct NTFS_BOOT *)bh->b_data;
+
+ if (memcmp(boot->system_id, "NTFS ", sizeof("NTFS ") - 1))
+ goto out;
+
+ /* 0x55AA is not mandaroty. Thanks Maxim Suhanov*/
+ /*if (0x55 != boot->boot_magic[0] || 0xAA != boot->boot_magic[1])
+ * goto out;
+ */
+
+ boot_sector_size = (u32)boot->bytes_per_sector[1] << 8;
+ if (boot->bytes_per_sector[0] || boot_sector_size < SECTOR_SIZE ||
+ !is_power_of_2(boot_sector_size)) {
+ goto out;
+ }
+
+ /* cluster size: 512, 1K, 2K, 4K, ... 2M */
+ sct_per_clst = true_sectors_per_clst(boot);
+ if (!is_power_of_2(sct_per_clst))
+ goto out;
+
+ mlcn = le64_to_cpu(boot->mft_clst);
+ mlcn2 = le64_to_cpu(boot->mft2_clst);
+ sectors = le64_to_cpu(boot->sectors_per_volume);
+
+ if (mlcn * sct_per_clst >= sectors)
+ goto out;
+
+ if (mlcn2 * sct_per_clst >= sectors)
+ goto out;
+
+ /* Check MFT record size. */
+ if ((boot->record_size < 0 &&
+ SECTOR_SIZE > (2U << (-boot->record_size))) ||
+ (boot->record_size >= 0 && !is_power_of_2(boot->record_size))) {
+ goto out;
+ }
+
+ /* Check index record size. */
+ if ((boot->index_size < 0 &&
+ SECTOR_SIZE > (2U << (-boot->index_size))) ||
+ (boot->index_size >= 0 && !is_power_of_2(boot->index_size))) {
+ goto out;
+ }
+
+ sbi->sector_size = boot_sector_size;
+ sbi->sector_bits = blksize_bits(boot_sector_size);
+ fs_size = (sectors + 1) << sbi->sector_bits;
+
+ gb = format_size_gb(fs_size, &mb);
+
+ /*
+ * - Volume formatted and mounted with the same sector size.
+ * - Volume formatted 4K and mounted as 512.
+ * - Volume formatted 512 and mounted as 4K.
+ */
+ if (sbi->sector_size != sector_size) {
+ ntfs_warn(sb,
+ "Different NTFS' sector size and media sector size");
+ dev_size += sector_size - 1;
+ }
+
+ sbi->cluster_size = boot_sector_size * sct_per_clst;
+ sbi->cluster_bits = blksize_bits(sbi->cluster_size);
+
+ sbi->mft.lbo = mlcn << sbi->cluster_bits;
+ sbi->mft.lbo2 = mlcn2 << sbi->cluster_bits;
+
+ if (sbi->cluster_size < sbi->sector_size)
+ goto out;
+
+ sbi->cluster_mask = sbi->cluster_size - 1;
+ sbi->cluster_mask_inv = ~(u64)sbi->cluster_mask;
+ sbi->record_size = record_size = boot->record_size < 0
+ ? 1 << (-boot->record_size)
+ : (u32)boot->record_size
+ << sbi->cluster_bits;
+
+ if (record_size > MAXIMUM_BYTES_PER_MFT)
+ goto out;
+
+ sbi->record_bits = blksize_bits(record_size);
+ sbi->attr_size_tr = (5 * record_size >> 4); // ~320 bytes
+
+ sbi->max_bytes_per_attr =
+ record_size - ALIGN(MFTRECORD_FIXUP_OFFSET_1, 8) -
+ ALIGN(((record_size >> SECTOR_SHIFT) * sizeof(short)), 8) -
+ ALIGN(sizeof(enum ATTR_TYPE), 8);
+
+ sbi->index_size = boot->index_size < 0
+ ? 1u << (-boot->index_size)
+ : (u32)boot->index_size << sbi->cluster_bits;
+
+ sbi->volume.ser_num = le64_to_cpu(boot->serial_num);
+ sbi->volume.size = sectors << sbi->sector_bits;
+
+ /* Warning if RAW volume. */
+ if (dev_size < fs_size) {
+ u32 mb0, gb0;
+
+ gb0 = format_size_gb(dev_size, &mb0);
+ ntfs_warn(
+ sb,
+ "RAW NTFS volume: Filesystem size %u.%02u Gb > volume size %u.%02u Gb. Mount in read-only",
+ gb, mb, gb0, mb0);
+ sb->s_flags |= SB_RDONLY;
+ }
+
+ clusters = sbi->volume.size >> sbi->cluster_bits;
+#ifndef CONFIG_NTFS3_64BIT_CLUSTER
+ /* 32 bits per cluster. */
+ if (clusters >> 32) {
+ ntfs_notice(
+ sb,
+ "NTFS %u.%02u Gb is too big to use 32 bits per cluster",
+ gb, mb);
+ goto out;
+ }
+#elif BITS_PER_LONG < 64
+#error "CONFIG_NTFS3_64BIT_CLUSTER incompatible in 32 bit OS"
+#endif
+
+ sbi->used.bitmap.nbits = clusters;
+
+ rec = kzalloc(record_size, GFP_NOFS);
+ if (!rec) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ sbi->new_rec = rec;
+ rec->rhdr.sign = NTFS_FILE_SIGNATURE;
+ rec->rhdr.fix_off = cpu_to_le16(MFTRECORD_FIXUP_OFFSET_1);
+ fn = (sbi->record_size >> SECTOR_SHIFT) + 1;
+ rec->rhdr.fix_num = cpu_to_le16(fn);
+ ao = ALIGN(MFTRECORD_FIXUP_OFFSET_1 + sizeof(short) * fn, 8);
+ rec->attr_off = cpu_to_le16(ao);
+ rec->used = cpu_to_le32(ao + ALIGN(sizeof(enum ATTR_TYPE), 8));
+ rec->total = cpu_to_le32(sbi->record_size);
+ ((struct ATTRIB *)Add2Ptr(rec, ao))->type = ATTR_END;
+
+ if (sbi->cluster_size < PAGE_SIZE)
+ sb_set_blocksize(sb, sbi->cluster_size);
+
+ sbi->block_mask = sb->s_blocksize - 1;
+ sbi->blocks_per_cluster = sbi->cluster_size >> sb->s_blocksize_bits;
+ sbi->volume.blocks = sbi->volume.size >> sb->s_blocksize_bits;
+
+ /* Maximum size for normal files. */
+ sbi->maxbytes = (clusters << sbi->cluster_bits) - 1;
+
+#ifdef CONFIG_NTFS3_64BIT_CLUSTER
+ if (clusters >= (1ull << (64 - sbi->cluster_bits)))
+ sbi->maxbytes = -1;
+ sbi->maxbytes_sparse = -1;
+#else
+ /* Maximum size for sparse file. */
+ sbi->maxbytes_sparse = (1ull << (sbi->cluster_bits + 32)) - 1;
+#endif
+
+ err = 0;
+
+out:
+ brelse(bh);
+
+ return err;
+}
+
+/*
+ * ntfs_fill_super - Try to mount.
+ */
+static int ntfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+ int err;
+ struct ntfs_sb_info *sbi;
+ struct block_device *bdev = sb->s_bdev;
+ struct inode *bd_inode = bdev->bd_inode;
+ struct request_queue *rq = bdev_get_queue(bdev);
+ struct inode *inode = NULL;
+ struct ntfs_inode *ni;
+ size_t i, tt;
+ CLST vcn, lcn, len;
+ struct ATTRIB *attr;
+ const struct VOLUME_INFO *info;
+ u32 idx, done, bytes;
+ struct ATTR_DEF_ENTRY *t;
+ u16 *upcase = NULL;
+ u16 *shared;
+ bool is_ro;
+ struct MFT_REF ref;
+
+ ref.high = 0;
+
+ sbi = kzalloc(sizeof(struct ntfs_sb_info), GFP_NOFS);
+ if (!sbi)
+ return -ENOMEM;
+
+ sb->s_fs_info = sbi;
+ sbi->sb = sb;
+ sb->s_flags |= SB_NODIRATIME;
+ sb->s_magic = 0x7366746e; // "ntfs"
+ sb->s_op = &ntfs_sops;
+ sb->s_export_op = &ntfs_export_ops;
+ sb->s_time_gran = NTFS_TIME_GRAN; // 100 nsec
+ sb->s_xattr = ntfs_xattr_handlers;
+
+ ratelimit_state_init(&sbi->msg_ratelimit, DEFAULT_RATELIMIT_INTERVAL,
+ DEFAULT_RATELIMIT_BURST);
+
+ err = ntfs_parse_options(sb, data, silent, &sbi->options);
+ if (err)
+ goto out;
+
+ if (!rq || !blk_queue_discard(rq) || !rq->limits.discard_granularity) {
+ ;
+ } else {
+ sbi->discard_granularity = rq->limits.discard_granularity;
+ sbi->discard_granularity_mask_inv =
+ ~(u64)(sbi->discard_granularity - 1);
+ }
+
+ sb_set_blocksize(sb, PAGE_SIZE);
+
+ /* Parse boot. */
+ err = ntfs_init_from_boot(sb, rq ? queue_logical_block_size(rq) : 512,
+ bd_inode->i_size);
+ if (err)
+ goto out;
+
+#ifdef CONFIG_NTFS3_64BIT_CLUSTER
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+#else
+ sb->s_maxbytes = 0xFFFFFFFFull << sbi->cluster_bits;
+#endif
+
+ mutex_init(&sbi->compress.mtx_lznt);
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+ mutex_init(&sbi->compress.mtx_xpress);
+ mutex_init(&sbi->compress.mtx_lzx);
+#endif
+
+ /*
+ * Load $Volume. This should be done before $LogFile
+ * 'cause 'sbi->volume.ni' is used 'ntfs_set_state'.
+ */
+ ref.low = cpu_to_le32(MFT_REC_VOL);
+ ref.seq = cpu_to_le16(MFT_REC_VOL);
+ inode = ntfs_iget5(sb, &ref, &NAME_VOLUME);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load $Volume.");
+ inode = NULL;
+ goto out;
+ }
+
+ ni = ntfs_i(inode);
+
+ /* Load and save label (not necessary). */
+ attr = ni_find_attr(ni, NULL, NULL, ATTR_LABEL, NULL, 0, NULL, NULL);
+
+ if (!attr) {
+ /* It is ok if no ATTR_LABEL */
+ } else if (!attr->non_res && !is_attr_ext(attr)) {
+ /* $AttrDef allows labels to be up to 128 symbols. */
+ err = utf16s_to_utf8s(resident_data(attr),
+ le32_to_cpu(attr->res.data_size) >> 1,
+ UTF16_LITTLE_ENDIAN, sbi->volume.label,
+ sizeof(sbi->volume.label));
+ if (err < 0)
+ sbi->volume.label[0] = 0;
+ } else {
+ /* Should we break mounting here? */
+ //err = -EINVAL;
+ //goto out;
+ }
+
+ attr = ni_find_attr(ni, attr, NULL, ATTR_VOL_INFO, NULL, 0, NULL, NULL);
+ if (!attr || is_attr_ext(attr)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ info = resident_data_ex(attr, SIZEOF_ATTRIBUTE_VOLUME_INFO);
+ if (!info) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ sbi->volume.major_ver = info->major_ver;
+ sbi->volume.minor_ver = info->minor_ver;
+ sbi->volume.flags = info->flags;
+
+ sbi->volume.ni = ni;
+ inode = NULL;
+
+ /* Load $MFTMirr to estimate recs_mirr. */
+ ref.low = cpu_to_le32(MFT_REC_MIRR);
+ ref.seq = cpu_to_le16(MFT_REC_MIRR);
+ inode = ntfs_iget5(sb, &ref, &NAME_MIRROR);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load $MFTMirr.");
+ inode = NULL;
+ goto out;
+ }
+
+ sbi->mft.recs_mirr =
+ ntfs_up_cluster(sbi, inode->i_size) >> sbi->record_bits;
+
+ iput(inode);
+
+ /* Load LogFile to replay. */
+ ref.low = cpu_to_le32(MFT_REC_LOG);
+ ref.seq = cpu_to_le16(MFT_REC_LOG);
+ inode = ntfs_iget5(sb, &ref, &NAME_LOGFILE);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load \x24LogFile.");
+ inode = NULL;
+ goto out;
+ }
+
+ ni = ntfs_i(inode);
+
+ err = ntfs_loadlog_and_replay(ni, sbi);
+ if (err)
+ goto out;
+
+ iput(inode);
+ inode = NULL;
+
+ is_ro = sb_rdonly(sbi->sb);
+
+ if (sbi->flags & NTFS_FLAGS_NEED_REPLAY) {
+ if (!is_ro) {
+ ntfs_warn(sb,
+ "failed to replay log file. Can't mount rw!");
+ err = -EINVAL;
+ goto out;
+ }
+ } else if (sbi->volume.flags & VOLUME_FLAG_DIRTY) {
+ if (!is_ro && !sbi->options.force) {
+ ntfs_warn(
+ sb,
+ "volume is dirty and \"force\" flag is not set!");
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* Load $MFT. */
+ ref.low = cpu_to_le32(MFT_REC_MFT);
+ ref.seq = cpu_to_le16(1);
+
+ inode = ntfs_iget5(sb, &ref, &NAME_MFT);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load $MFT.");
+ inode = NULL;
+ goto out;
+ }
+
+ ni = ntfs_i(inode);
+
+ sbi->mft.used = ni->i_valid >> sbi->record_bits;
+ tt = inode->i_size >> sbi->record_bits;
+ sbi->mft.next_free = MFT_REC_USER;
+
+ err = wnd_init(&sbi->mft.bitmap, sb, tt);
+ if (err)
+ goto out;
+
+ err = ni_load_all_mi(ni);
+ if (err)
+ goto out;
+
+ sbi->mft.ni = ni;
+
+ /* Load $BadClus. */
+ ref.low = cpu_to_le32(MFT_REC_BADCLUST);
+ ref.seq = cpu_to_le16(MFT_REC_BADCLUST);
+ inode = ntfs_iget5(sb, &ref, &NAME_BADCLUS);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load $BadClus.");
+ inode = NULL;
+ goto out;
+ }
+
+ ni = ntfs_i(inode);
+
+ for (i = 0; run_get_entry(&ni->file.run, i, &vcn, &lcn, &len); i++) {
+ if (lcn == SPARSE_LCN)
+ continue;
+
+ if (!sbi->bad_clusters)
+ ntfs_notice(sb, "Volume contains bad blocks");
+
+ sbi->bad_clusters += len;
+ }
+
+ iput(inode);
+
+ /* Load $Bitmap. */
+ ref.low = cpu_to_le32(MFT_REC_BITMAP);
+ ref.seq = cpu_to_le16(MFT_REC_BITMAP);
+ inode = ntfs_iget5(sb, &ref, &NAME_BITMAP);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load $Bitmap.");
+ inode = NULL;
+ goto out;
+ }
+
+ ni = ntfs_i(inode);
+
+#ifndef CONFIG_NTFS3_64BIT_CLUSTER
+ if (inode->i_size >> 32) {
+ err = -EINVAL;
+ goto out;
+ }
+#endif
+
+ /* Check bitmap boundary. */
+ tt = sbi->used.bitmap.nbits;
+ if (inode->i_size < bitmap_size(tt)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Not necessary. */
+ sbi->used.bitmap.set_tail = true;
+ err = wnd_init(&sbi->used.bitmap, sbi->sb, tt);
+ if (err)
+ goto out;
+
+ iput(inode);
+
+ /* Compute the MFT zone. */
+ err = ntfs_refresh_zone(sbi);
+ if (err)
+ goto out;
+
+ /* Load $AttrDef. */
+ ref.low = cpu_to_le32(MFT_REC_ATTR);
+ ref.seq = cpu_to_le16(MFT_REC_ATTR);
+ inode = ntfs_iget5(sbi->sb, &ref, &NAME_ATTRDEF);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load $AttrDef -> %d", err);
+ inode = NULL;
+ goto out;
+ }
+
+ if (inode->i_size < sizeof(struct ATTR_DEF_ENTRY)) {
+ err = -EINVAL;
+ goto out;
+ }
+ bytes = inode->i_size;
+ sbi->def_table = t = kmalloc(bytes, GFP_NOFS);
+ if (!t) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ for (done = idx = 0; done < bytes; done += PAGE_SIZE, idx++) {
+ unsigned long tail = bytes - done;
+ struct page *page = ntfs_map_page(inode->i_mapping, idx);
+
+ if (IS_ERR(page)) {
+ err = PTR_ERR(page);
+ goto out;
+ }
+ memcpy(Add2Ptr(t, done), page_address(page),
+ min(PAGE_SIZE, tail));
+ ntfs_unmap_page(page);
+
+ if (!idx && ATTR_STD != t->type) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ t += 1;
+ sbi->def_entries = 1;
+ done = sizeof(struct ATTR_DEF_ENTRY);
+ sbi->reparse.max_size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
+ sbi->ea_max_size = 0x10000; /* default formatter value */
+
+ while (done + sizeof(struct ATTR_DEF_ENTRY) <= bytes) {
+ u32 t32 = le32_to_cpu(t->type);
+ u64 sz = le64_to_cpu(t->max_sz);
+
+ if ((t32 & 0xF) || le32_to_cpu(t[-1].type) >= t32)
+ break;
+
+ if (t->type == ATTR_REPARSE)
+ sbi->reparse.max_size = sz;
+ else if (t->type == ATTR_EA)
+ sbi->ea_max_size = sz;
+
+ done += sizeof(struct ATTR_DEF_ENTRY);
+ t += 1;
+ sbi->def_entries += 1;
+ }
+ iput(inode);
+
+ /* Load $UpCase. */
+ ref.low = cpu_to_le32(MFT_REC_UPCASE);
+ ref.seq = cpu_to_le16(MFT_REC_UPCASE);
+ inode = ntfs_iget5(sb, &ref, &NAME_UPCASE);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load \x24LogFile.");
+ inode = NULL;
+ goto out;
+ }
+
+ ni = ntfs_i(inode);
+
+ if (inode->i_size != 0x10000 * sizeof(short)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ sbi->upcase = upcase = kvmalloc(0x10000 * sizeof(short), GFP_KERNEL);
+ if (!upcase) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ for (idx = 0; idx < (0x10000 * sizeof(short) >> PAGE_SHIFT); idx++) {
+ const __le16 *src;
+ u16 *dst = Add2Ptr(upcase, idx << PAGE_SHIFT);
+ struct page *page = ntfs_map_page(inode->i_mapping, idx);
+
+ if (IS_ERR(page)) {
+ err = PTR_ERR(page);
+ goto out;
+ }
+
+ src = page_address(page);
+
+#ifdef __BIG_ENDIAN
+ for (i = 0; i < PAGE_SIZE / sizeof(u16); i++)
+ *dst++ = le16_to_cpu(*src++);
+#else
+ memcpy(dst, src, PAGE_SIZE);
+#endif
+ ntfs_unmap_page(page);
+ }
+
+ shared = ntfs_set_shared(upcase, 0x10000 * sizeof(short));
+ if (shared && upcase != shared) {
+ sbi->upcase = shared;
+ kvfree(upcase);
+ }
+
+ iput(inode);
+ inode = NULL;
+
+ if (is_ntfs3(sbi)) {
+ /* Load $Secure. */
+ err = ntfs_security_init(sbi);
+ if (err)
+ goto out;
+
+ /* Load $Extend. */
+ err = ntfs_extend_init(sbi);
+ if (err)
+ goto load_root;
+
+ /* Load $Extend\$Reparse. */
+ err = ntfs_reparse_init(sbi);
+ if (err)
+ goto load_root;
+
+ /* Load $Extend\$ObjId. */
+ err = ntfs_objid_init(sbi);
+ if (err)
+ goto load_root;
+ }
+
+load_root:
+ /* Load root. */
+ ref.low = cpu_to_le32(MFT_REC_ROOT);
+ ref.seq = cpu_to_le16(MFT_REC_ROOT);
+ inode = ntfs_iget5(sb, &ref, &NAME_ROOT);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ntfs_err(sb, "Failed to load root.");
+ inode = NULL;
+ goto out;
+ }
+
+ ni = ntfs_i(inode);
+
+ sb->s_root = d_make_root(inode);
+
+ if (!sb->s_root) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ return 0;
+
+out:
+ iput(inode);
+
+ if (sb->s_root) {
+ d_drop(sb->s_root);
+ sb->s_root = NULL;
+ }
+
+ put_ntfs(sbi);
+
+ sb->s_fs_info = NULL;
+ return err;
+}
+
+void ntfs_unmap_meta(struct super_block *sb, CLST lcn, CLST len)
+{
+ struct ntfs_sb_info *sbi = sb->s_fs_info;
+ struct block_device *bdev = sb->s_bdev;
+ sector_t devblock = (u64)lcn * sbi->blocks_per_cluster;
+ unsigned long blocks = (u64)len * sbi->blocks_per_cluster;
+ unsigned long cnt = 0;
+ unsigned long limit = global_zone_page_state(NR_FREE_PAGES)
+ << (PAGE_SHIFT - sb->s_blocksize_bits);
+
+ if (limit >= 0x2000)
+ limit -= 0x1000;
+ else if (limit < 32)
+ limit = 32;
+ else
+ limit >>= 1;
+
+ while (blocks--) {
+ clean_bdev_aliases(bdev, devblock++, 1);
+ if (cnt++ >= limit) {
+ sync_blockdev(bdev);
+ cnt = 0;
+ }
+ }
+}
+
+/*
+ * ntfs_discard - Issue a discard request (trim for SSD).
+ */
+int ntfs_discard(struct ntfs_sb_info *sbi, CLST lcn, CLST len)
+{
+ int err;
+ u64 lbo, bytes, start, end;
+ struct super_block *sb;
+
+ if (sbi->used.next_free_lcn == lcn + len)
+ sbi->used.next_free_lcn = lcn;
+
+ if (sbi->flags & NTFS_FLAGS_NODISCARD)
+ return -EOPNOTSUPP;
+
+ if (!sbi->options.discard)
+ return -EOPNOTSUPP;
+
+ lbo = (u64)lcn << sbi->cluster_bits;
+ bytes = (u64)len << sbi->cluster_bits;
+
+ /* Align up 'start' on discard_granularity. */
+ start = (lbo + sbi->discard_granularity - 1) &
+ sbi->discard_granularity_mask_inv;
+ /* Align down 'end' on discard_granularity. */
+ end = (lbo + bytes) & sbi->discard_granularity_mask_inv;
+
+ sb = sbi->sb;
+ if (start >= end)
+ return 0;
+
+ err = blkdev_issue_discard(sb->s_bdev, start >> 9, (end - start) >> 9,
+ GFP_NOFS, 0);
+
+ if (err == -EOPNOTSUPP)
+ sbi->flags |= NTFS_FLAGS_NODISCARD;
+
+ return err;
+}
+
+static struct dentry *ntfs_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data)
+{
+ return mount_bdev(fs_type, flags, dev_name, data, ntfs_fill_super);
+}
+
+// clang-format off
+static struct file_system_type ntfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "ntfs3",
+ .mount = ntfs_mount,
+ .kill_sb = kill_block_super,
+ .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
+};
+// clang-format on
+
+static int __init init_ntfs_fs(void)
+{
+ int err;
+
+ pr_info("ntfs3: Max link count %u\n", NTFS_LINK_MAX);
+
+ if (IS_ENABLED(CONFIG_NTFS3_FS_POSIX_ACL))
+ pr_info("ntfs3: Enabled Linux POSIX ACLs support\n");
+ if (IS_ENABLED(CONFIG_NTFS3_64BIT_CLUSTER))
+ pr_notice("ntfs3: Warning: Activated 64 bits per cluster. Windows does not support this\n");
+ if (IS_ENABLED(CONFIG_NTFS3_LZX_XPRESS))
+ pr_info("ntfs3: Read-only LZX/Xpress compression included\n");
+
+ err = ntfs3_init_bitmap();
+ if (err)
+ return err;
+
+ ntfs_inode_cachep = kmem_cache_create(
+ "ntfs_inode_cache", sizeof(struct ntfs_inode), 0,
+ (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD | SLAB_ACCOUNT),
+ init_once);
+ if (!ntfs_inode_cachep) {
+ err = -ENOMEM;
+ goto out1;
+ }
+
+ err = register_filesystem(&ntfs_fs_type);
+ if (err)
+ goto out;
+
+ return 0;
+out:
+ kmem_cache_destroy(ntfs_inode_cachep);
+out1:
+ ntfs3_exit_bitmap();
+ return err;
+}
+
+static void __exit exit_ntfs_fs(void)
+{
+ if (ntfs_inode_cachep) {
+ rcu_barrier();
+ kmem_cache_destroy(ntfs_inode_cachep);
+ }
+
+ unregister_filesystem(&ntfs_fs_type);
+ ntfs3_exit_bitmap();
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ntfs3 read/write filesystem");
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+MODULE_INFO(behaviour, "Enabled Linux POSIX ACLs support");
+#endif
+#ifdef CONFIG_NTFS3_64BIT_CLUSTER
+MODULE_INFO(cluster, "Warning: Activated 64 bits per cluster. Windows does not support this");
+#endif
+#ifdef CONFIG_NTFS3_LZX_XPRESS
+MODULE_INFO(compression, "Read-only lzx/xpress compression included");
+#endif
+
+MODULE_AUTHOR("Konstantin Komarov");
+MODULE_ALIAS_FS("ntfs3");
+
+module_init(init_ntfs_fs);
+module_exit(exit_ntfs_fs);
diff --git a/fs/ntfs3/upcase.c b/fs/ntfs3/upcase.c
new file mode 100644
index 000000000000..bbeba778237e
--- /dev/null
+++ b/fs/ntfs3/upcase.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/module.h>
+#include <linux/nls.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+static inline u16 upcase_unicode_char(const u16 *upcase, u16 chr)
+{
+ if (chr < 'a')
+ return chr;
+
+ if (chr <= 'z')
+ return chr - ('a' - 'A');
+
+ return upcase[chr];
+}
+
+/*
+ * ntfs_cmp_names
+ *
+ * Thanks Kari Argillander <kari.argillander@gmail.com> for idea and implementation 'bothcase'
+ *
+ * Straight way to compare names:
+ * - Case insensitive
+ * - If name equals and 'bothcases' then
+ * - Case sensitive
+ * 'Straight way' code scans input names twice in worst case.
+ * Optimized code scans input names only once.
+ */
+int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2,
+ const u16 *upcase, bool bothcase)
+{
+ int diff1 = 0;
+ int diff2;
+ size_t len = min(l1, l2);
+
+ if (!bothcase && upcase)
+ goto case_insentive;
+
+ for (; len; s1++, s2++, len--) {
+ diff1 = le16_to_cpu(*s1) - le16_to_cpu(*s2);
+ if (diff1) {
+ if (bothcase && upcase)
+ goto case_insentive;
+
+ return diff1;
+ }
+ }
+ return l1 - l2;
+
+case_insentive:
+ for (; len; s1++, s2++, len--) {
+ diff2 = upcase_unicode_char(upcase, le16_to_cpu(*s1)) -
+ upcase_unicode_char(upcase, le16_to_cpu(*s2));
+ if (diff2)
+ return diff2;
+ }
+
+ diff2 = l1 - l2;
+ return diff2 ? diff2 : diff1;
+}
+
+int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2,
+ const u16 *upcase, bool bothcase)
+{
+ const u16 *s1 = uni1->name;
+ const __le16 *s2 = uni2->name;
+ size_t l1 = uni1->len;
+ size_t l2 = uni2->len;
+ size_t len = min(l1, l2);
+ int diff1 = 0;
+ int diff2;
+
+ if (!bothcase && upcase)
+ goto case_insentive;
+
+ for (; len; s1++, s2++, len--) {
+ diff1 = *s1 - le16_to_cpu(*s2);
+ if (diff1) {
+ if (bothcase && upcase)
+ goto case_insentive;
+
+ return diff1;
+ }
+ }
+ return l1 - l2;
+
+case_insentive:
+ for (; len; s1++, s2++, len--) {
+ diff2 = upcase_unicode_char(upcase, *s1) -
+ upcase_unicode_char(upcase, le16_to_cpu(*s2));
+ if (diff2)
+ return diff2;
+ }
+
+ diff2 = l1 - l2;
+ return diff2 ? diff2 : diff1;
+}
diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c
new file mode 100644
index 000000000000..7282d85c4ece
--- /dev/null
+++ b/fs/ntfs3/xattr.c
@@ -0,0 +1,1122 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/nls.h>
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/xattr.h>
+
+#include "debug.h"
+#include "ntfs.h"
+#include "ntfs_fs.h"
+
+// clang-format off
+#define SYSTEM_DOS_ATTRIB "system.dos_attrib"
+#define SYSTEM_NTFS_ATTRIB "system.ntfs_attrib"
+#define SYSTEM_NTFS_SECURITY "system.ntfs_security"
+// clang-format on
+
+static inline size_t unpacked_ea_size(const struct EA_FULL *ea)
+{
+ return ea->size ? le32_to_cpu(ea->size)
+ : ALIGN(struct_size(ea, name,
+ 1 + ea->name_len +
+ le16_to_cpu(ea->elength)),
+ 4);
+}
+
+static inline size_t packed_ea_size(const struct EA_FULL *ea)
+{
+ return struct_size(ea, name,
+ 1 + ea->name_len + le16_to_cpu(ea->elength)) -
+ offsetof(struct EA_FULL, flags);
+}
+
+/*
+ * find_ea
+ *
+ * Assume there is at least one xattr in the list.
+ */
+static inline bool find_ea(const struct EA_FULL *ea_all, u32 bytes,
+ const char *name, u8 name_len, u32 *off)
+{
+ *off = 0;
+
+ if (!ea_all || !bytes)
+ return false;
+
+ for (;;) {
+ const struct EA_FULL *ea = Add2Ptr(ea_all, *off);
+ u32 next_off = *off + unpacked_ea_size(ea);
+
+ if (next_off > bytes)
+ return false;
+
+ if (ea->name_len == name_len &&
+ !memcmp(ea->name, name, name_len))
+ return true;
+
+ *off = next_off;
+ if (next_off >= bytes)
+ return false;
+ }
+}
+
+/*
+ * ntfs_read_ea - Read all extended attributes.
+ * @ea: New allocated memory.
+ * @info: Pointer into resident data.
+ */
+static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea,
+ size_t add_bytes, const struct EA_INFO **info)
+{
+ int err;
+ struct ATTR_LIST_ENTRY *le = NULL;
+ struct ATTRIB *attr_info, *attr_ea;
+ void *ea_p;
+ u32 size;
+
+ static_assert(le32_to_cpu(ATTR_EA_INFO) < le32_to_cpu(ATTR_EA));
+
+ *ea = NULL;
+ *info = NULL;
+
+ attr_info =
+ ni_find_attr(ni, NULL, &le, ATTR_EA_INFO, NULL, 0, NULL, NULL);
+ attr_ea =
+ ni_find_attr(ni, attr_info, &le, ATTR_EA, NULL, 0, NULL, NULL);
+
+ if (!attr_ea || !attr_info)
+ return 0;
+
+ *info = resident_data_ex(attr_info, sizeof(struct EA_INFO));
+ if (!*info)
+ return -EINVAL;
+
+ /* Check Ea limit. */
+ size = le32_to_cpu((*info)->size);
+ if (size > ni->mi.sbi->ea_max_size)
+ return -EFBIG;
+
+ if (attr_size(attr_ea) > ni->mi.sbi->ea_max_size)
+ return -EFBIG;
+
+ /* Allocate memory for packed Ea. */
+ ea_p = kmalloc(size + add_bytes, GFP_NOFS);
+ if (!ea_p)
+ return -ENOMEM;
+
+ if (attr_ea->non_res) {
+ struct runs_tree run;
+
+ run_init(&run);
+
+ err = attr_load_runs(attr_ea, ni, &run, NULL);
+ if (!err)
+ err = ntfs_read_run_nb(ni->mi.sbi, &run, 0, ea_p, size,
+ NULL);
+ run_close(&run);
+
+ if (err)
+ goto out;
+ } else {
+ void *p = resident_data_ex(attr_ea, size);
+
+ if (!p) {
+ err = -EINVAL;
+ goto out;
+ }
+ memcpy(ea_p, p, size);
+ }
+
+ memset(Add2Ptr(ea_p, size), 0, add_bytes);
+ *ea = ea_p;
+ return 0;
+
+out:
+ kfree(ea_p);
+ *ea = NULL;
+ return err;
+}
+
+/*
+ * ntfs_list_ea
+ *
+ * Copy a list of xattrs names into the buffer
+ * provided, or compute the buffer size required.
+ *
+ * Return:
+ * * Number of bytes used / required on
+ * * -ERRNO - on failure
+ */
+static ssize_t ntfs_list_ea(struct ntfs_inode *ni, char *buffer,
+ size_t bytes_per_buffer)
+{
+ const struct EA_INFO *info;
+ struct EA_FULL *ea_all = NULL;
+ const struct EA_FULL *ea;
+ u32 off, size;
+ int err;
+ size_t ret;
+
+ err = ntfs_read_ea(ni, &ea_all, 0, &info);
+ if (err)
+ return err;
+
+ if (!info || !ea_all)
+ return 0;
+
+ size = le32_to_cpu(info->size);
+
+ /* Enumerate all xattrs. */
+ for (ret = 0, off = 0; off < size; off += unpacked_ea_size(ea)) {
+ ea = Add2Ptr(ea_all, off);
+
+ if (buffer) {
+ if (ret + ea->name_len + 1 > bytes_per_buffer) {
+ err = -ERANGE;
+ goto out;
+ }
+
+ memcpy(buffer + ret, ea->name, ea->name_len);
+ buffer[ret + ea->name_len] = 0;
+ }
+
+ ret += ea->name_len + 1;
+ }
+
+out:
+ kfree(ea_all);
+ return err ? err : ret;
+}
+
+static int ntfs_get_ea(struct inode *inode, const char *name, size_t name_len,
+ void *buffer, size_t size, size_t *required)
+{
+ struct ntfs_inode *ni = ntfs_i(inode);
+ const struct EA_INFO *info;
+ struct EA_FULL *ea_all = NULL;
+ const struct EA_FULL *ea;
+ u32 off, len;
+ int err;
+
+ if (!(ni->ni_flags & NI_FLAG_EA))
+ return -ENODATA;
+
+ if (!required)
+ ni_lock(ni);
+
+ len = 0;
+
+ if (name_len > 255) {
+ err = -ENAMETOOLONG;
+ goto out;
+ }
+
+ err = ntfs_read_ea(ni, &ea_all, 0, &info);
+ if (err)
+ goto out;
+
+ if (!info)
+ goto out;
+
+ /* Enumerate all xattrs. */
+ if (!find_ea(ea_all, le32_to_cpu(info->size), name, name_len, &off)) {
+ err = -ENODATA;
+ goto out;
+ }
+ ea = Add2Ptr(ea_all, off);
+
+ len = le16_to_cpu(ea->elength);
+ if (!buffer) {
+ err = 0;
+ goto out;
+ }
+
+ if (len > size) {
+ err = -ERANGE;
+ if (required)
+ *required = len;
+ goto out;
+ }
+
+ memcpy(buffer, ea->name + ea->name_len + 1, len);
+ err = 0;
+
+out:
+ kfree(ea_all);
+ if (!required)
+ ni_unlock(ni);
+
+ return err ? err : len;
+}
+
+static noinline int ntfs_set_ea(struct inode *inode, const char *name,
+ size_t name_len, const void *value,
+ size_t val_size, int flags, int locked)
+{
+ struct ntfs_inode *ni = ntfs_i(inode);
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ int err;
+ struct EA_INFO ea_info;
+ const struct EA_INFO *info;
+ struct EA_FULL *new_ea;
+ struct EA_FULL *ea_all = NULL;
+ size_t add, new_pack;
+ u32 off, size;
+ __le16 size_pack;
+ struct ATTRIB *attr;
+ struct ATTR_LIST_ENTRY *le;
+ struct mft_inode *mi;
+ struct runs_tree ea_run;
+ u64 new_sz;
+ void *p;
+
+ if (!locked)
+ ni_lock(ni);
+
+ run_init(&ea_run);
+
+ if (name_len > 255) {
+ err = -ENAMETOOLONG;
+ goto out;
+ }
+
+ add = ALIGN(struct_size(ea_all, name, 1 + name_len + val_size), 4);
+
+ err = ntfs_read_ea(ni, &ea_all, add, &info);
+ if (err)
+ goto out;
+
+ if (!info) {
+ memset(&ea_info, 0, sizeof(ea_info));
+ size = 0;
+ size_pack = 0;
+ } else {
+ memcpy(&ea_info, info, sizeof(ea_info));
+ size = le32_to_cpu(ea_info.size);
+ size_pack = ea_info.size_pack;
+ }
+
+ if (info && find_ea(ea_all, size, name, name_len, &off)) {
+ struct EA_FULL *ea;
+ size_t ea_sz;
+
+ if (flags & XATTR_CREATE) {
+ err = -EEXIST;
+ goto out;
+ }
+
+ ea = Add2Ptr(ea_all, off);
+
+ /*
+ * Check simple case when we try to insert xattr with the same value
+ * e.g. ntfs_save_wsl_perm
+ */
+ if (val_size && le16_to_cpu(ea->elength) == val_size &&
+ !memcmp(ea->name + ea->name_len + 1, value, val_size)) {
+ /* xattr already contains the required value. */
+ goto out;
+ }
+
+ /* Remove current xattr. */
+ if (ea->flags & FILE_NEED_EA)
+ le16_add_cpu(&ea_info.count, -1);
+
+ ea_sz = unpacked_ea_size(ea);
+
+ le16_add_cpu(&ea_info.size_pack, 0 - packed_ea_size(ea));
+
+ memmove(ea, Add2Ptr(ea, ea_sz), size - off - ea_sz);
+
+ size -= ea_sz;
+ memset(Add2Ptr(ea_all, size), 0, ea_sz);
+
+ ea_info.size = cpu_to_le32(size);
+
+ if ((flags & XATTR_REPLACE) && !val_size) {
+ /* Remove xattr. */
+ goto update_ea;
+ }
+ } else {
+ if (flags & XATTR_REPLACE) {
+ err = -ENODATA;
+ goto out;
+ }
+
+ if (!ea_all) {
+ ea_all = kzalloc(add, GFP_NOFS);
+ if (!ea_all) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
+ }
+
+ /* Append new xattr. */
+ new_ea = Add2Ptr(ea_all, size);
+ new_ea->size = cpu_to_le32(add);
+ new_ea->flags = 0;
+ new_ea->name_len = name_len;
+ new_ea->elength = cpu_to_le16(val_size);
+ memcpy(new_ea->name, name, name_len);
+ new_ea->name[name_len] = 0;
+ memcpy(new_ea->name + name_len + 1, value, val_size);
+ new_pack = le16_to_cpu(ea_info.size_pack) + packed_ea_size(new_ea);
+
+ /* Should fit into 16 bits. */
+ if (new_pack > 0xffff) {
+ err = -EFBIG; // -EINVAL?
+ goto out;
+ }
+ ea_info.size_pack = cpu_to_le16(new_pack);
+
+ /* New size of ATTR_EA. */
+ size += add;
+ if (size > sbi->ea_max_size) {
+ err = -EFBIG; // -EINVAL?
+ goto out;
+ }
+ ea_info.size = cpu_to_le32(size);
+
+update_ea:
+
+ if (!info) {
+ /* Create xattr. */
+ if (!size) {
+ err = 0;
+ goto out;
+ }
+
+ err = ni_insert_resident(ni, sizeof(struct EA_INFO),
+ ATTR_EA_INFO, NULL, 0, NULL, NULL,
+ NULL);
+ if (err)
+ goto out;
+
+ err = ni_insert_resident(ni, 0, ATTR_EA, NULL, 0, NULL, NULL,
+ NULL);
+ if (err)
+ goto out;
+ }
+
+ new_sz = size;
+ err = attr_set_size(ni, ATTR_EA, NULL, 0, &ea_run, new_sz, &new_sz,
+ false, NULL);
+ if (err)
+ goto out;
+
+ le = NULL;
+ attr = ni_find_attr(ni, NULL, &le, ATTR_EA_INFO, NULL, 0, NULL, &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!size) {
+ /* Delete xattr, ATTR_EA_INFO */
+ ni_remove_attr_le(ni, attr, mi, le);
+ } else {
+ p = resident_data_ex(attr, sizeof(struct EA_INFO));
+ if (!p) {
+ err = -EINVAL;
+ goto out;
+ }
+ memcpy(p, &ea_info, sizeof(struct EA_INFO));
+ mi->dirty = true;
+ }
+
+ le = NULL;
+ attr = ni_find_attr(ni, NULL, &le, ATTR_EA, NULL, 0, NULL, &mi);
+ if (!attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!size) {
+ /* Delete xattr, ATTR_EA */
+ ni_remove_attr_le(ni, attr, mi, le);
+ } else if (attr->non_res) {
+ err = ntfs_sb_write_run(sbi, &ea_run, 0, ea_all, size);
+ if (err)
+ goto out;
+ } else {
+ p = resident_data_ex(attr, size);
+ if (!p) {
+ err = -EINVAL;
+ goto out;
+ }
+ memcpy(p, ea_all, size);
+ mi->dirty = true;
+ }
+
+ /* Check if we delete the last xattr. */
+ if (size)
+ ni->ni_flags |= NI_FLAG_EA;
+ else
+ ni->ni_flags &= ~NI_FLAG_EA;
+
+ if (ea_info.size_pack != size_pack)
+ ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
+ mark_inode_dirty(&ni->vfs_inode);
+
+out:
+ if (!locked)
+ ni_unlock(ni);
+
+ run_close(&ea_run);
+ kfree(ea_all);
+
+ return err;
+}
+
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+static inline void ntfs_posix_acl_release(struct posix_acl *acl)
+{
+ if (acl && refcount_dec_and_test(&acl->a_refcount))
+ kfree(acl);
+}
+
+static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns,
+ struct inode *inode, int type,
+ int locked)
+{
+ struct ntfs_inode *ni = ntfs_i(inode);
+ const char *name;
+ size_t name_len;
+ struct posix_acl *acl;
+ size_t req;
+ int err;
+ void *buf;
+
+ /* Allocate PATH_MAX bytes. */
+ buf = __getname();
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ /* Possible values of 'type' was already checked above. */
+ if (type == ACL_TYPE_ACCESS) {
+ name = XATTR_NAME_POSIX_ACL_ACCESS;
+ name_len = sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1;
+ } else {
+ name = XATTR_NAME_POSIX_ACL_DEFAULT;
+ name_len = sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1;
+ }
+
+ if (!locked)
+ ni_lock(ni);
+
+ err = ntfs_get_ea(inode, name, name_len, buf, PATH_MAX, &req);
+
+ if (!locked)
+ ni_unlock(ni);
+
+ /* Translate extended attribute to acl. */
+ if (err >= 0) {
+ acl = posix_acl_from_xattr(mnt_userns, buf, err);
+ if (!IS_ERR(acl))
+ set_cached_acl(inode, type, acl);
+ } else {
+ acl = err == -ENODATA ? NULL : ERR_PTR(err);
+ }
+
+ __putname(buf);
+
+ return acl;
+}
+
+/*
+ * ntfs_get_acl - inode_operations::get_acl
+ */
+struct posix_acl *ntfs_get_acl(struct inode *inode, int type, bool rcu)
+{
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
+ /* TODO: init_user_ns? */
+ return ntfs_get_acl_ex(&init_user_ns, inode, type, 0);
+}
+
+static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns,
+ struct inode *inode, struct posix_acl *acl,
+ int type, int locked)
+{
+ const char *name;
+ size_t size, name_len;
+ void *value = NULL;
+ int err = 0;
+
+ if (S_ISLNK(inode->i_mode))
+ return -EOPNOTSUPP;
+
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ if (acl) {
+ umode_t mode = inode->i_mode;
+
+ err = posix_acl_equiv_mode(acl, &mode);
+ if (err < 0)
+ return err;
+
+ if (inode->i_mode != mode) {
+ inode->i_mode = mode;
+ mark_inode_dirty(inode);
+ }
+
+ if (!err) {
+ /*
+ * ACL can be exactly represented in the
+ * traditional file mode permission bits.
+ */
+ acl = NULL;
+ }
+ }
+ name = XATTR_NAME_POSIX_ACL_ACCESS;
+ name_len = sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1;
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ if (!S_ISDIR(inode->i_mode))
+ return acl ? -EACCES : 0;
+ name = XATTR_NAME_POSIX_ACL_DEFAULT;
+ name_len = sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (!acl) {
+ size = 0;
+ value = NULL;
+ } else {
+ size = posix_acl_xattr_size(acl->a_count);
+ value = kmalloc(size, GFP_NOFS);
+ if (!value)
+ return -ENOMEM;
+
+ err = posix_acl_to_xattr(mnt_userns, acl, value, size);
+ if (err < 0)
+ goto out;
+ }
+
+ err = ntfs_set_ea(inode, name, name_len, value, size, 0, locked);
+ if (!err)
+ set_cached_acl(inode, type, acl);
+
+out:
+ kfree(value);
+
+ return err;
+}
+
+/*
+ * ntfs_set_acl - inode_operations::set_acl
+ */
+int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
+ struct posix_acl *acl, int type)
+{
+ return ntfs_set_acl_ex(mnt_userns, inode, acl, type, 0);
+}
+
+static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns,
+ struct inode *inode, int type, void *buffer,
+ size_t size)
+{
+ struct posix_acl *acl;
+ int err;
+
+ if (!(inode->i_sb->s_flags & SB_POSIXACL)) {
+ ntfs_inode_warn(inode, "add mount option \"acl\" to use acl");
+ return -EOPNOTSUPP;
+ }
+
+ acl = ntfs_get_acl(inode, type, false);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+
+ if (!acl)
+ return -ENODATA;
+
+ err = posix_acl_to_xattr(mnt_userns, acl, buffer, size);
+ ntfs_posix_acl_release(acl);
+
+ return err;
+}
+
+static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns,
+ struct inode *inode, int type, const void *value,
+ size_t size)
+{
+ struct posix_acl *acl;
+ int err;
+
+ if (!(inode->i_sb->s_flags & SB_POSIXACL)) {
+ ntfs_inode_warn(inode, "add mount option \"acl\" to use acl");
+ return -EOPNOTSUPP;
+ }
+
+ if (!inode_owner_or_capable(mnt_userns, inode))
+ return -EPERM;
+
+ if (!value) {
+ acl = NULL;
+ } else {
+ acl = posix_acl_from_xattr(mnt_userns, value, size);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+
+ if (acl) {
+ err = posix_acl_valid(mnt_userns, acl);
+ if (err)
+ goto release_and_out;
+ }
+ }
+
+ err = ntfs_set_acl(mnt_userns, inode, acl, type);
+
+release_and_out:
+ ntfs_posix_acl_release(acl);
+ return err;
+}
+
+/*
+ * ntfs_init_acl - Initialize the ACLs of a new inode.
+ *
+ * Called from ntfs_create_inode().
+ */
+int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode,
+ struct inode *dir)
+{
+ struct posix_acl *default_acl, *acl;
+ int err;
+
+ /*
+ * TODO: Refactoring lock.
+ * ni_lock(dir) ... -> posix_acl_create(dir,...) -> ntfs_get_acl -> ni_lock(dir)
+ */
+ inode->i_default_acl = NULL;
+
+ default_acl = ntfs_get_acl_ex(mnt_userns, dir, ACL_TYPE_DEFAULT, 1);
+
+ if (!default_acl || default_acl == ERR_PTR(-EOPNOTSUPP)) {
+ inode->i_mode &= ~current_umask();
+ err = 0;
+ goto out;
+ }
+
+ if (IS_ERR(default_acl)) {
+ err = PTR_ERR(default_acl);
+ goto out;
+ }
+
+ acl = default_acl;
+ err = __posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
+ if (err < 0)
+ goto out1;
+ if (!err) {
+ posix_acl_release(acl);
+ acl = NULL;
+ }
+
+ if (!S_ISDIR(inode->i_mode)) {
+ posix_acl_release(default_acl);
+ default_acl = NULL;
+ }
+
+ if (default_acl)
+ err = ntfs_set_acl_ex(mnt_userns, inode, default_acl,
+ ACL_TYPE_DEFAULT, 1);
+
+ if (!acl)
+ inode->i_acl = NULL;
+ else if (!err)
+ err = ntfs_set_acl_ex(mnt_userns, inode, acl, ACL_TYPE_ACCESS,
+ 1);
+
+ posix_acl_release(acl);
+out1:
+ posix_acl_release(default_acl);
+
+out:
+ return err;
+}
+#endif
+
+/*
+ * ntfs_acl_chmod - Helper for ntfs3_setattr().
+ */
+int ntfs_acl_chmod(struct user_namespace *mnt_userns, struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+
+ if (!(sb->s_flags & SB_POSIXACL))
+ return 0;
+
+ if (S_ISLNK(inode->i_mode))
+ return -EOPNOTSUPP;
+
+ return posix_acl_chmod(mnt_userns, inode, inode->i_mode);
+}
+
+/*
+ * ntfs_permission - inode_operations::permission
+ */
+int ntfs_permission(struct user_namespace *mnt_userns, struct inode *inode,
+ int mask)
+{
+ if (ntfs_sb(inode->i_sb)->options.no_acs_rules) {
+ /* "No access rules" mode - Allow all changes. */
+ return 0;
+ }
+
+ return generic_permission(mnt_userns, inode, mask);
+}
+
+/*
+ * ntfs_listxattr - inode_operations::listxattr
+ */
+ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+ struct inode *inode = d_inode(dentry);
+ struct ntfs_inode *ni = ntfs_i(inode);
+ ssize_t ret;
+
+ if (!(ni->ni_flags & NI_FLAG_EA)) {
+ /* no xattr in file */
+ return 0;
+ }
+
+ ni_lock(ni);
+
+ ret = ntfs_list_ea(ni, buffer, size);
+
+ ni_unlock(ni);
+
+ return ret;
+}
+
+static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de,
+ struct inode *inode, const char *name, void *buffer,
+ size_t size)
+{
+ int err;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ size_t name_len = strlen(name);
+
+ /* Dispatch request. */
+ if (name_len == sizeof(SYSTEM_DOS_ATTRIB) - 1 &&
+ !memcmp(name, SYSTEM_DOS_ATTRIB, sizeof(SYSTEM_DOS_ATTRIB))) {
+ /* system.dos_attrib */
+ if (!buffer) {
+ err = sizeof(u8);
+ } else if (size < sizeof(u8)) {
+ err = -ENODATA;
+ } else {
+ err = sizeof(u8);
+ *(u8 *)buffer = le32_to_cpu(ni->std_fa);
+ }
+ goto out;
+ }
+
+ if (name_len == sizeof(SYSTEM_NTFS_ATTRIB) - 1 &&
+ !memcmp(name, SYSTEM_NTFS_ATTRIB, sizeof(SYSTEM_NTFS_ATTRIB))) {
+ /* system.ntfs_attrib */
+ if (!buffer) {
+ err = sizeof(u32);
+ } else if (size < sizeof(u32)) {
+ err = -ENODATA;
+ } else {
+ err = sizeof(u32);
+ *(u32 *)buffer = le32_to_cpu(ni->std_fa);
+ }
+ goto out;
+ }
+
+ if (name_len == sizeof(SYSTEM_NTFS_SECURITY) - 1 &&
+ !memcmp(name, SYSTEM_NTFS_SECURITY, sizeof(SYSTEM_NTFS_SECURITY))) {
+ /* system.ntfs_security*/
+ struct SECURITY_DESCRIPTOR_RELATIVE *sd = NULL;
+ size_t sd_size = 0;
+
+ if (!is_ntfs3(ni->mi.sbi)) {
+ /* We should get nt4 security. */
+ err = -EINVAL;
+ goto out;
+ } else if (le32_to_cpu(ni->std_security_id) <
+ SECURITY_ID_FIRST) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ err = ntfs_get_security_by_id(ni->mi.sbi, ni->std_security_id,
+ &sd, &sd_size);
+ if (err)
+ goto out;
+
+ if (!is_sd_valid(sd, sd_size)) {
+ ntfs_inode_warn(
+ inode,
+ "looks like you get incorrect security descriptor id=%u",
+ ni->std_security_id);
+ }
+
+ if (!buffer) {
+ err = sd_size;
+ } else if (size < sd_size) {
+ err = -ENODATA;
+ } else {
+ err = sd_size;
+ memcpy(buffer, sd, sd_size);
+ }
+ kfree(sd);
+ goto out;
+ }
+
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+ if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 &&
+ !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS,
+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) ||
+ (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 &&
+ !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) {
+ /* TODO: init_user_ns? */
+ err = ntfs_xattr_get_acl(
+ &init_user_ns, inode,
+ name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1
+ ? ACL_TYPE_ACCESS
+ : ACL_TYPE_DEFAULT,
+ buffer, size);
+ goto out;
+ }
+#endif
+ /* Deal with NTFS extended attribute. */
+ err = ntfs_get_ea(inode, name, name_len, buffer, size, NULL);
+
+out:
+ return err;
+}
+
+/*
+ * ntfs_setxattr - inode_operations::setxattr
+ */
+static noinline int ntfs_setxattr(const struct xattr_handler *handler,
+ struct user_namespace *mnt_userns,
+ struct dentry *de, struct inode *inode,
+ const char *name, const void *value,
+ size_t size, int flags)
+{
+ int err = -EINVAL;
+ struct ntfs_inode *ni = ntfs_i(inode);
+ size_t name_len = strlen(name);
+ enum FILE_ATTRIBUTE new_fa;
+
+ /* Dispatch request. */
+ if (name_len == sizeof(SYSTEM_DOS_ATTRIB) - 1 &&
+ !memcmp(name, SYSTEM_DOS_ATTRIB, sizeof(SYSTEM_DOS_ATTRIB))) {
+ if (sizeof(u8) != size)
+ goto out;
+ new_fa = cpu_to_le32(*(u8 *)value);
+ goto set_new_fa;
+ }
+
+ if (name_len == sizeof(SYSTEM_NTFS_ATTRIB) - 1 &&
+ !memcmp(name, SYSTEM_NTFS_ATTRIB, sizeof(SYSTEM_NTFS_ATTRIB))) {
+ if (size != sizeof(u32))
+ goto out;
+ new_fa = cpu_to_le32(*(u32 *)value);
+
+ if (S_ISREG(inode->i_mode)) {
+ /* Process compressed/sparsed in special way. */
+ ni_lock(ni);
+ err = ni_new_attr_flags(ni, new_fa);
+ ni_unlock(ni);
+ if (err)
+ goto out;
+ }
+set_new_fa:
+ /*
+ * Thanks Mark Harmstone:
+ * Keep directory bit consistency.
+ */
+ if (S_ISDIR(inode->i_mode))
+ new_fa |= FILE_ATTRIBUTE_DIRECTORY;
+ else
+ new_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
+
+ if (ni->std_fa != new_fa) {
+ ni->std_fa = new_fa;
+ if (new_fa & FILE_ATTRIBUTE_READONLY)
+ inode->i_mode &= ~0222;
+ else
+ inode->i_mode |= 0222;
+ /* Std attribute always in primary record. */
+ ni->mi.dirty = true;
+ mark_inode_dirty(inode);
+ }
+ err = 0;
+
+ goto out;
+ }
+
+ if (name_len == sizeof(SYSTEM_NTFS_SECURITY) - 1 &&
+ !memcmp(name, SYSTEM_NTFS_SECURITY, sizeof(SYSTEM_NTFS_SECURITY))) {
+ /* system.ntfs_security*/
+ __le32 security_id;
+ bool inserted;
+ struct ATTR_STD_INFO5 *std;
+
+ if (!is_ntfs3(ni->mi.sbi)) {
+ /*
+ * We should replace ATTR_SECURE.
+ * Skip this way cause it is nt4 feature.
+ */
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!is_sd_valid(value, size)) {
+ err = -EINVAL;
+ ntfs_inode_warn(
+ inode,
+ "you try to set invalid security descriptor");
+ goto out;
+ }
+
+ err = ntfs_insert_security(ni->mi.sbi, value, size,
+ &security_id, &inserted);
+ if (err)
+ goto out;
+
+ ni_lock(ni);
+ std = ni_std5(ni);
+ if (!std) {
+ err = -EINVAL;
+ } else if (std->security_id != security_id) {
+ std->security_id = ni->std_security_id = security_id;
+ /* Std attribute always in primary record. */
+ ni->mi.dirty = true;
+ mark_inode_dirty(&ni->vfs_inode);
+ }
+ ni_unlock(ni);
+ goto out;
+ }
+
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+ if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 &&
+ !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS,
+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) ||
+ (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 &&
+ !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) {
+ err = ntfs_xattr_set_acl(
+ mnt_userns, inode,
+ name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1
+ ? ACL_TYPE_ACCESS
+ : ACL_TYPE_DEFAULT,
+ value, size);
+ goto out;
+ }
+#endif
+ /* Deal with NTFS extended attribute. */
+ err = ntfs_set_ea(inode, name, name_len, value, size, flags, 0);
+
+out:
+ return err;
+}
+
+/*
+ * ntfs_save_wsl_perm
+ *
+ * save uid/gid/mode in xattr
+ */
+int ntfs_save_wsl_perm(struct inode *inode)
+{
+ int err;
+ __le32 value;
+
+ value = cpu_to_le32(i_uid_read(inode));
+ err = ntfs_set_ea(inode, "$LXUID", sizeof("$LXUID") - 1, &value,
+ sizeof(value), 0, 0);
+ if (err)
+ goto out;
+
+ value = cpu_to_le32(i_gid_read(inode));
+ err = ntfs_set_ea(inode, "$LXGID", sizeof("$LXGID") - 1, &value,
+ sizeof(value), 0, 0);
+ if (err)
+ goto out;
+
+ value = cpu_to_le32(inode->i_mode);
+ err = ntfs_set_ea(inode, "$LXMOD", sizeof("$LXMOD") - 1, &value,
+ sizeof(value), 0, 0);
+ if (err)
+ goto out;
+
+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+ value = cpu_to_le32(inode->i_rdev);
+ err = ntfs_set_ea(inode, "$LXDEV", sizeof("$LXDEV") - 1, &value,
+ sizeof(value), 0, 0);
+ if (err)
+ goto out;
+ }
+
+out:
+ /* In case of error should we delete all WSL xattr? */
+ return err;
+}
+
+/*
+ * ntfs_get_wsl_perm
+ *
+ * get uid/gid/mode from xattr
+ * it is called from ntfs_iget5->ntfs_read_mft
+ */
+void ntfs_get_wsl_perm(struct inode *inode)
+{
+ size_t sz;
+ __le32 value[3];
+
+ if (ntfs_get_ea(inode, "$LXUID", sizeof("$LXUID") - 1, &value[0],
+ sizeof(value[0]), &sz) == sizeof(value[0]) &&
+ ntfs_get_ea(inode, "$LXGID", sizeof("$LXGID") - 1, &value[1],
+ sizeof(value[1]), &sz) == sizeof(value[1]) &&
+ ntfs_get_ea(inode, "$LXMOD", sizeof("$LXMOD") - 1, &value[2],
+ sizeof(value[2]), &sz) == sizeof(value[2])) {
+ i_uid_write(inode, (uid_t)le32_to_cpu(value[0]));
+ i_gid_write(inode, (gid_t)le32_to_cpu(value[1]));
+ inode->i_mode = le32_to_cpu(value[2]);
+
+ if (ntfs_get_ea(inode, "$LXDEV", sizeof("$$LXDEV") - 1,
+ &value[0], sizeof(value),
+ &sz) == sizeof(value[0])) {
+ inode->i_rdev = le32_to_cpu(value[0]);
+ }
+ }
+}
+
+static bool ntfs_xattr_user_list(struct dentry *dentry)
+{
+ return true;
+}
+
+// clang-format off
+static const struct xattr_handler ntfs_xattr_handler = {
+ .prefix = "",
+ .get = ntfs_getxattr,
+ .set = ntfs_setxattr,
+ .list = ntfs_xattr_user_list,
+};
+
+const struct xattr_handler *ntfs_xattr_handlers[] = {
+ &ntfs_xattr_handler,
+ NULL,
+};
+// clang-format on
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 5c72a7e6d6c5..23a72a423955 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -289,7 +289,7 @@ unlock:
return status;
}
-struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
+struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type, bool rcu)
{
struct ocfs2_super *osb;
struct buffer_head *di_bh = NULL;
@@ -297,6 +297,9 @@ struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
int had_lock;
struct ocfs2_lock_holder oh;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
osb = OCFS2_SB(inode->i_sb);
if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
return NULL;
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
index f59d8d0a61fa..95a57c888ab6 100644
--- a/fs/ocfs2/acl.h
+++ b/fs/ocfs2/acl.h
@@ -16,7 +16,7 @@ struct ocfs2_acl_entry {
__le32 e_id;
};
-struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type);
+struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type, bool rcu);
int ocfs2_iop_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
extern int ocfs2_acl_chmod(struct inode *, struct buffer_head *);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 48fd369c29a4..359524b7341f 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -16,6 +16,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/time.h>
+#include <linux/delay.h>
#include <linux/quotaops.h>
#include <linux/sched/signal.h>
@@ -2721,7 +2722,7 @@ int ocfs2_inode_lock_tracker(struct inode *inode,
return status;
}
}
- return tmp_oh ? 1 : 0;
+ return 1;
}
void ocfs2_inode_unlock_tracker(struct inode *inode,
@@ -3912,6 +3913,17 @@ downconvert:
spin_unlock_irqrestore(&lockres->l_lock, flags);
ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb,
gen);
+ /* The dlm lock convert is being cancelled in background,
+ * ocfs2_cancel_convert() is asynchronous in fs/dlm,
+ * requeue it, try again later.
+ */
+ if (ret == -EBUSY) {
+ ctl->requeue = 1;
+ mlog(ML_BASTS, "lockres %s, ReQ: Downconvert busy\n",
+ lockres->l_name);
+ ret = 0;
+ msleep(20);
+ }
leave:
if (ret)
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index eda83487c9ec..f033de733adb 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -357,7 +357,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
}
oinfo->dqi_gi.dqi_sb = sb;
oinfo->dqi_gi.dqi_type = type;
- ocfs2_qinfo_lock_res_init(&oinfo->dqi_gqlock, oinfo);
oinfo->dqi_gi.dqi_entry_size = sizeof(struct ocfs2_global_disk_dqblk);
oinfo->dqi_gi.dqi_ops = &ocfs2_global_ops;
oinfo->dqi_gqi_bh = NULL;
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index b1a8b046f4c2..0e4b16d4c037 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -702,6 +702,8 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
info->dqi_priv = oinfo;
oinfo->dqi_type = type;
INIT_LIST_HEAD(&oinfo->dqi_chunk);
+ oinfo->dqi_gqinode = NULL;
+ ocfs2_qinfo_lock_res_init(&oinfo->dqi_gqlock, oinfo);
oinfo->dqi_rec = NULL;
oinfo->dqi_lqi_bh = NULL;
oinfo->dqi_libh = NULL;
diff --git a/fs/orangefs/acl.c b/fs/orangefs/acl.c
index 18852b9ed82b..605e5a3506ec 100644
--- a/fs/orangefs/acl.c
+++ b/fs/orangefs/acl.c
@@ -10,12 +10,15 @@
#include "orangefs-bufmap.h"
#include <linux/posix_acl_xattr.h>
-struct posix_acl *orangefs_get_acl(struct inode *inode, int type)
+struct posix_acl *orangefs_get_acl(struct inode *inode, int type, bool rcu)
{
struct posix_acl *acl;
int ret;
char *key = NULL, *value = NULL;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch (type) {
case ACL_TYPE_ACCESS:
key = XATTR_NAME_POSIX_ACL_ACCESS;
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 16ac617df7d7..c1bb4c4b5d67 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -882,12 +882,7 @@ int orangefs_getattr(struct user_namespace *mnt_userns, const struct path *path,
if (!(request_mask & STATX_SIZE))
stat->result_mask &= ~STATX_SIZE;
- stat->attributes_mask = STATX_ATTR_IMMUTABLE |
- STATX_ATTR_APPEND;
- if (inode->i_flags & S_IMMUTABLE)
- stat->attributes |= STATX_ATTR_IMMUTABLE;
- if (inode->i_flags & S_APPEND)
- stat->attributes |= STATX_ATTR_APPEND;
+ generic_fill_statx_attr(inode, stat);
}
return ret;
}
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 0e6b97682e41..b5940ec1836a 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -106,7 +106,7 @@ enum orangefs_vfs_op_states {
extern int orangefs_init_acl(struct inode *inode, struct inode *dir);
extern const struct xattr_handler *orangefs_xattr_handlers[];
-extern struct posix_acl *orangefs_get_acl(struct inode *inode, int type);
+extern struct posix_acl *orangefs_get_acl(struct inode *inode, int type, bool rcu);
extern int orangefs_set_acl(struct user_namespace *mnt_userns,
struct inode *inode, struct posix_acl *acl,
int type);
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 2846b943e80c..4e7d5bfa2949 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -8,6 +8,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/file.h>
+#include <linux/fileattr.h>
#include <linux/splice.h>
#include <linux/xattr.h>
#include <linux/security.h>
@@ -62,7 +63,7 @@ int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
return list_size;
}
- buf = kzalloc(list_size, GFP_KERNEL);
+ buf = kvzalloc(list_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -105,11 +106,12 @@ retry:
if (size > value_size) {
void *new;
- new = krealloc(value, size, GFP_KERNEL);
+ new = kvmalloc(size, GFP_KERNEL);
if (!new) {
error = -ENOMEM;
break;
}
+ kvfree(value);
value = new;
value_size = size;
goto retry;
@@ -124,12 +126,50 @@ retry:
error = 0;
}
}
- kfree(value);
+ kvfree(value);
out:
- kfree(buf);
+ kvfree(buf);
return error;
}
+static int ovl_copy_fileattr(struct inode *inode, struct path *old,
+ struct path *new)
+{
+ struct fileattr oldfa = { .flags_valid = true };
+ struct fileattr newfa = { .flags_valid = true };
+ int err;
+
+ err = ovl_real_fileattr_get(old, &oldfa);
+ if (err)
+ return err;
+
+ err = ovl_real_fileattr_get(new, &newfa);
+ if (err)
+ return err;
+
+ /*
+ * We cannot set immutable and append-only flags on upper inode,
+ * because we would not be able to link upper inode to upper dir
+ * not set overlay private xattr on upper inode.
+ * Store these flags in overlay.protattr xattr instead.
+ */
+ if (oldfa.flags & OVL_PROT_FS_FLAGS_MASK) {
+ err = ovl_set_protattr(inode, new->dentry, &oldfa);
+ if (err)
+ return err;
+ }
+
+ BUILD_BUG_ON(OVL_COPY_FS_FLAGS_MASK & ~FS_COMMON_FL);
+ newfa.flags &= ~OVL_COPY_FS_FLAGS_MASK;
+ newfa.flags |= (oldfa.flags & OVL_COPY_FS_FLAGS_MASK);
+
+ BUILD_BUG_ON(OVL_COPY_FSX_FLAGS_MASK & ~FS_XFLAG_COMMON);
+ newfa.fsx_xflags &= ~OVL_COPY_FSX_FLAGS_MASK;
+ newfa.fsx_xflags |= (oldfa.fsx_xflags & OVL_COPY_FSX_FLAGS_MASK);
+
+ return ovl_real_fileattr_set(new, &newfa);
+}
+
static int ovl_copy_up_data(struct ovl_fs *ofs, struct path *old,
struct path *new, loff_t len)
{
@@ -331,8 +371,8 @@ out_err:
return ERR_PTR(err);
}
-int ovl_set_origin(struct ovl_fs *ofs, struct dentry *dentry,
- struct dentry *lower, struct dentry *upper)
+int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower,
+ struct dentry *upper)
{
const struct ovl_fh *fh = NULL;
int err;
@@ -351,7 +391,7 @@ int ovl_set_origin(struct ovl_fs *ofs, struct dentry *dentry,
/*
* Do not fail when upper doesn't support xattrs.
*/
- err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh->buf,
+ err = ovl_check_setxattr(ofs, upper, OVL_XATTR_ORIGIN, fh->buf,
fh ? fh->fb.len : 0, 0);
kfree(fh);
@@ -493,20 +533,21 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
{
struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb);
+ struct inode *inode = d_inode(c->dentry);
+ struct path upperpath, datapath;
int err;
+ ovl_path_upper(c->dentry, &upperpath);
+ if (WARN_ON(upperpath.dentry != NULL))
+ return -EIO;
+
+ upperpath.dentry = temp;
+
/*
* Copy up data first and then xattrs. Writing data after
* xattrs will remove security.capability xattr automatically.
*/
if (S_ISREG(c->stat.mode) && !c->metacopy) {
- struct path upperpath, datapath;
-
- ovl_path_upper(c->dentry, &upperpath);
- if (WARN_ON(upperpath.dentry != NULL))
- return -EIO;
- upperpath.dentry = temp;
-
ovl_path_lowerdata(c->dentry, &datapath);
err = ovl_copy_up_data(ofs, &datapath, &upperpath,
c->stat.size);
@@ -518,6 +559,16 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
if (err)
return err;
+ if (inode->i_flags & OVL_COPY_I_FLAGS_MASK) {
+ /*
+ * Copy the fileattr inode flags that are the source of already
+ * copied i_flags
+ */
+ err = ovl_copy_fileattr(inode, &c->lowerpath, &upperpath);
+ if (err)
+ return err;
+ }
+
/*
* Store identifier of lower inode in upper inode xattr to
* allow lookup of the copy up origin inode.
@@ -526,13 +577,13 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
* hard link.
*/
if (c->origin) {
- err = ovl_set_origin(ofs, c->dentry, c->lowerpath.dentry, temp);
+ err = ovl_set_origin(ofs, c->lowerpath.dentry, temp);
if (err)
return err;
}
if (c->metacopy) {
- err = ovl_check_setxattr(c->dentry, temp, OVL_XATTR_METACOPY,
+ err = ovl_check_setxattr(ofs, temp, OVL_XATTR_METACOPY,
NULL, 0, -EOPNOTSUPP);
if (err)
return err;
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 93efe7048a77..1fefb2b8960e 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -233,9 +233,10 @@ struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr)
static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper,
int xerr)
{
+ struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
int err;
- err = ovl_check_setxattr(dentry, upper, OVL_XATTR_OPAQUE, "y", 1, xerr);
+ err = ovl_check_setxattr(ofs, upper, OVL_XATTR_OPAQUE, "y", 1, xerr);
if (!err)
ovl_dentry_set_opaque(dentry);
@@ -320,6 +321,7 @@ static bool ovl_type_origin(struct dentry *dentry)
static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
struct ovl_cattr *attr)
{
+ struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
struct inode *udir = upperdir->d_inode;
struct dentry *newdentry;
@@ -338,7 +340,8 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
if (IS_ERR(newdentry))
goto out_unlock;
- if (ovl_type_merge(dentry->d_parent) && d_is_dir(newdentry)) {
+ if (ovl_type_merge(dentry->d_parent) && d_is_dir(newdentry) &&
+ !ovl_allow_offline_changes(ofs)) {
/* Setting opaque here is just an optimization, allow to fail */
ovl_set_opaque(dentry, newdentry);
}
@@ -542,8 +545,10 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
goto out_cleanup;
}
err = ovl_instantiate(dentry, inode, newdentry, hardlink);
- if (err)
- goto out_cleanup;
+ if (err) {
+ ovl_cleanup(udir, newdentry);
+ dput(newdentry);
+ }
out_dput:
dput(upper);
out_unlock:
@@ -1043,6 +1048,7 @@ static bool ovl_need_absolute_redirect(struct dentry *dentry, bool samedir)
static int ovl_set_redirect(struct dentry *dentry, bool samedir)
{
int err;
+ struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
const char *redirect = ovl_dentry_get_redirect(dentry);
bool absolute_redirect = ovl_need_absolute_redirect(dentry, samedir);
@@ -1053,7 +1059,7 @@ static int ovl_set_redirect(struct dentry *dentry, bool samedir)
if (IS_ERR(redirect))
return PTR_ERR(redirect);
- err = ovl_check_setxattr(dentry, ovl_dentry_upper(dentry),
+ err = ovl_check_setxattr(ofs, ovl_dentry_upper(dentry),
OVL_XATTR_REDIRECT,
redirect, strlen(redirect), -EXDEV);
if (!err) {
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 5e828a1c98a8..832b17589733 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -13,6 +13,7 @@
#include <linux/fiemap.h>
#include <linux/fileattr.h>
#include <linux/security.h>
+#include <linux/namei.h>
#include "overlayfs.h"
@@ -33,12 +34,6 @@ int ovl_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
goto out;
if (attr->ia_valid & ATTR_SIZE) {
- struct inode *realinode = d_inode(ovl_dentry_real(dentry));
-
- err = -ETXTBSY;
- if (atomic_read(&realinode->i_writecount) < 0)
- goto out_drop_write;
-
/* Truncate should trigger data copy up as well */
full_copy_up = true;
}
@@ -162,7 +157,8 @@ int ovl_getattr(struct user_namespace *mnt_userns, const struct path *path,
enum ovl_path_type type;
struct path realpath;
const struct cred *old_cred;
- bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
+ struct inode *inode = d_inode(dentry);
+ bool is_dir = S_ISDIR(inode->i_mode);
int fsid = 0;
int err;
bool metacopy_blocks = false;
@@ -175,6 +171,9 @@ int ovl_getattr(struct user_namespace *mnt_userns, const struct path *path,
if (err)
goto out;
+ /* Report the effective immutable/append-only STATX flags */
+ generic_fill_statx_attr(inode, stat);
+
/*
* For non-dir or same fs, we use st_ino of the copy up origin.
* This guaranties constant st_dev/st_ino across copy up.
@@ -448,7 +447,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
return res;
}
-struct posix_acl *ovl_get_acl(struct inode *inode, int type)
+struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu)
{
struct inode *realinode = ovl_inode_real(inode);
const struct cred *old_cred;
@@ -457,6 +456,9 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type)
if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode))
return NULL;
+ if (rcu)
+ return get_cached_acl_rcu(realinode, type);
+
old_cred = ovl_override_creds(inode->i_sb);
acl = get_acl(realinode, type);
revert_creds(old_cred);
@@ -503,16 +505,14 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
* Introducing security_inode_fileattr_get/set() hooks would solve this issue
* properly.
*/
-static int ovl_security_fileattr(struct dentry *dentry, struct fileattr *fa,
+static int ovl_security_fileattr(struct path *realpath, struct fileattr *fa,
bool set)
{
- struct path realpath;
struct file *file;
unsigned int cmd;
int err;
- ovl_path_real(dentry, &realpath);
- file = dentry_open(&realpath, O_RDONLY, current_cred());
+ file = dentry_open(realpath, O_RDONLY, current_cred());
if (IS_ERR(file))
return PTR_ERR(file);
@@ -527,12 +527,24 @@ static int ovl_security_fileattr(struct dentry *dentry, struct fileattr *fa,
return err;
}
+int ovl_real_fileattr_set(struct path *realpath, struct fileattr *fa)
+{
+ int err;
+
+ err = ovl_security_fileattr(realpath, fa, true);
+ if (err)
+ return err;
+
+ return vfs_fileattr_set(&init_user_ns, realpath->dentry, fa);
+}
+
int ovl_fileattr_set(struct user_namespace *mnt_userns,
struct dentry *dentry, struct fileattr *fa)
{
struct inode *inode = d_inode(dentry);
- struct dentry *upperdentry;
+ struct path upperpath;
const struct cred *old_cred;
+ unsigned int flags;
int err;
err = ovl_want_write(dentry);
@@ -541,31 +553,78 @@ int ovl_fileattr_set(struct user_namespace *mnt_userns,
err = ovl_copy_up(dentry);
if (!err) {
- upperdentry = ovl_dentry_upper(dentry);
+ ovl_path_real(dentry, &upperpath);
old_cred = ovl_override_creds(inode->i_sb);
- err = ovl_security_fileattr(dentry, fa, true);
+ /*
+ * Store immutable/append-only flags in xattr and clear them
+ * in upper fileattr (in case they were set by older kernel)
+ * so children of "ovl-immutable" directories lower aliases of
+ * "ovl-immutable" hardlinks could be copied up.
+ * Clear xattr when flags are cleared.
+ */
+ err = ovl_set_protattr(inode, upperpath.dentry, fa);
if (!err)
- err = vfs_fileattr_set(&init_user_ns, upperdentry, fa);
+ err = ovl_real_fileattr_set(&upperpath, fa);
revert_creds(old_cred);
- ovl_copyflags(ovl_inode_real(inode), inode);
+
+ /*
+ * Merge real inode flags with inode flags read from
+ * overlay.protattr xattr
+ */
+ flags = ovl_inode_real(inode)->i_flags & OVL_COPY_I_FLAGS_MASK;
+
+ BUILD_BUG_ON(OVL_PROT_I_FLAGS_MASK & ~OVL_COPY_I_FLAGS_MASK);
+ flags |= inode->i_flags & OVL_PROT_I_FLAGS_MASK;
+ inode_set_flags(inode, flags, OVL_COPY_I_FLAGS_MASK);
+
+ /* Update ctime */
+ ovl_copyattr(ovl_inode_real(inode), inode);
}
ovl_drop_write(dentry);
out:
return err;
}
+/* Convert inode protection flags to fileattr flags */
+static void ovl_fileattr_prot_flags(struct inode *inode, struct fileattr *fa)
+{
+ BUILD_BUG_ON(OVL_PROT_FS_FLAGS_MASK & ~FS_COMMON_FL);
+ BUILD_BUG_ON(OVL_PROT_FSX_FLAGS_MASK & ~FS_XFLAG_COMMON);
+
+ if (inode->i_flags & S_APPEND) {
+ fa->flags |= FS_APPEND_FL;
+ fa->fsx_xflags |= FS_XFLAG_APPEND;
+ }
+ if (inode->i_flags & S_IMMUTABLE) {
+ fa->flags |= FS_IMMUTABLE_FL;
+ fa->fsx_xflags |= FS_XFLAG_IMMUTABLE;
+ }
+}
+
+int ovl_real_fileattr_get(struct path *realpath, struct fileattr *fa)
+{
+ int err;
+
+ err = ovl_security_fileattr(realpath, fa, false);
+ if (err)
+ return err;
+
+ return vfs_fileattr_get(realpath->dentry, fa);
+}
+
int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa)
{
struct inode *inode = d_inode(dentry);
- struct dentry *realdentry = ovl_dentry_real(dentry);
+ struct path realpath;
const struct cred *old_cred;
int err;
+ ovl_path_real(dentry, &realpath);
+
old_cred = ovl_override_creds(inode->i_sb);
- err = ovl_security_fileattr(dentry, fa, false);
- if (!err)
- err = vfs_fileattr_get(realdentry, fa);
+ err = ovl_real_fileattr_get(&realpath, fa);
+ ovl_fileattr_prot_flags(inode, fa);
revert_creds(old_cred);
return err;
@@ -1118,6 +1177,10 @@ struct inode *ovl_get_inode(struct super_block *sb,
}
}
+ /* Check for immutable/append-only inode flags in xattr */
+ if (upperdentry)
+ ovl_check_protattr(inode, upperdentry);
+
if (inode->i_state & I_NEW)
unlock_new_inode(inode);
out:
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 210cd6f66e28..1a9b515fc45d 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -392,7 +392,7 @@ invalid:
upperdentry, d_inode(upperdentry)->i_mode & S_IFMT,
d_inode(origin)->i_mode & S_IFMT);
dput(origin);
- return -EIO;
+ return -ESTALE;
}
static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry,
@@ -811,7 +811,7 @@ static int ovl_fix_origin(struct ovl_fs *ofs, struct dentry *dentry,
if (err)
return err;
- err = ovl_set_origin(ofs, dentry, lower, upper);
+ err = ovl_set_origin(ofs, lower, upper);
if (!err)
err = ovl_set_impure(dentry->d_parent, upper->d_parent);
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 6ec73db4bf9e..3894f3347955 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -34,6 +34,7 @@ enum ovl_xattr {
OVL_XATTR_NLINK,
OVL_XATTR_UPPER,
OVL_XATTR_METACOPY,
+ OVL_XATTR_PROTATTR,
};
enum ovl_inode_flag {
@@ -262,6 +263,18 @@ static inline bool ovl_open_flags_need_copy_up(int flags)
return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
}
+static inline bool ovl_allow_offline_changes(struct ovl_fs *ofs)
+{
+ /*
+ * To avoid regressions in existing setups with overlay lower offline
+ * changes, we allow lower changes only if none of the new features
+ * are used.
+ */
+ return (!ofs->config.index && !ofs->config.metacopy &&
+ !ofs->config.redirect_dir && ofs->config.xino != OVL_XINO_ON);
+}
+
+
/* util.c */
int ovl_want_write(struct dentry *dentry);
void ovl_drop_write(struct dentry *dentry);
@@ -320,7 +333,7 @@ bool ovl_already_copied_up(struct dentry *dentry, int flags);
bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry);
bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry,
enum ovl_xattr ox);
-int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
+int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry,
enum ovl_xattr ox, const void *value, size_t size,
int xerr);
int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry);
@@ -485,7 +498,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
void *value, size_t size);
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
-struct posix_acl *ovl_get_acl(struct inode *inode, int type);
+struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu);
int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags);
bool ovl_is_private_xattr(struct super_block *sb, const char *name);
@@ -518,9 +531,28 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to)
i_size_write(to, i_size_read(from));
}
+/* vfs inode flags copied from real to ovl inode */
+#define OVL_COPY_I_FLAGS_MASK (S_SYNC | S_NOATIME | S_APPEND | S_IMMUTABLE)
+/* vfs inode flags read from overlay.protattr xattr to ovl inode */
+#define OVL_PROT_I_FLAGS_MASK (S_APPEND | S_IMMUTABLE)
+
+/*
+ * fileattr flags copied from lower to upper inode on copy up.
+ * We cannot copy up immutable/append-only flags, because that would prevent
+ * linking temp inode to upper dir, so we store them in xattr instead.
+ */
+#define OVL_COPY_FS_FLAGS_MASK (FS_SYNC_FL | FS_NOATIME_FL)
+#define OVL_COPY_FSX_FLAGS_MASK (FS_XFLAG_SYNC | FS_XFLAG_NOATIME)
+#define OVL_PROT_FS_FLAGS_MASK (FS_APPEND_FL | FS_IMMUTABLE_FL)
+#define OVL_PROT_FSX_FLAGS_MASK (FS_XFLAG_APPEND | FS_XFLAG_IMMUTABLE)
+
+void ovl_check_protattr(struct inode *inode, struct dentry *upper);
+int ovl_set_protattr(struct inode *inode, struct dentry *upper,
+ struct fileattr *fa);
+
static inline void ovl_copyflags(struct inode *from, struct inode *to)
{
- unsigned int mask = S_SYNC | S_IMMUTABLE | S_APPEND | S_NOATIME;
+ unsigned int mask = OVL_COPY_I_FLAGS_MASK;
inode_set_flags(to, from->i_flags & mask, mask);
}
@@ -548,6 +580,8 @@ struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr);
extern const struct file_operations ovl_file_operations;
int __init ovl_aio_request_cache_init(void);
void ovl_aio_request_cache_destroy(void);
+int ovl_real_fileattr_get(struct path *realpath, struct fileattr *fa);
+int ovl_real_fileattr_set(struct path *realpath, struct fileattr *fa);
int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa);
int ovl_fileattr_set(struct user_namespace *mnt_userns,
struct dentry *dentry, struct fileattr *fa);
@@ -561,8 +595,8 @@ int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
int ovl_set_attr(struct dentry *upper, struct kstat *stat);
struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
bool is_upper);
-int ovl_set_origin(struct ovl_fs *ofs, struct dentry *dentry,
- struct dentry *lower, struct dentry *upper);
+int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower,
+ struct dentry *upper);
/* export.c */
extern const struct export_operations ovl_export_operations;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index b01d4147520d..178daa5e82c9 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1599,9 +1599,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
* user opted-in to one of the new features that require following the
* lower inode of non-dir upper.
*/
- if (!ofs->config.index && !ofs->config.metacopy &&
- ofs->config.xino != OVL_XINO_ON &&
- uuid_is_null(uuid))
+ if (ovl_allow_offline_changes(ofs) && uuid_is_null(uuid))
return false;
for (i = 0; i < ofs->numfs; i++) {
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index b9d03627f364..f48284a2a896 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -10,6 +10,7 @@
#include <linux/cred.h>
#include <linux/xattr.h>
#include <linux/exportfs.h>
+#include <linux/fileattr.h>
#include <linux/uuid.h>
#include <linux/namei.h>
#include <linux/ratelimit.h>
@@ -585,6 +586,7 @@ bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry,
#define OVL_XATTR_NLINK_POSTFIX "nlink"
#define OVL_XATTR_UPPER_POSTFIX "upper"
#define OVL_XATTR_METACOPY_POSTFIX "metacopy"
+#define OVL_XATTR_PROTATTR_POSTFIX "protattr"
#define OVL_XATTR_TAB_ENTRY(x) \
[x] = { [false] = OVL_XATTR_TRUSTED_PREFIX x ## _POSTFIX, \
@@ -598,14 +600,14 @@ const char *const ovl_xattr_table[][2] = {
OVL_XATTR_TAB_ENTRY(OVL_XATTR_NLINK),
OVL_XATTR_TAB_ENTRY(OVL_XATTR_UPPER),
OVL_XATTR_TAB_ENTRY(OVL_XATTR_METACOPY),
+ OVL_XATTR_TAB_ENTRY(OVL_XATTR_PROTATTR),
};
-int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
+int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry,
enum ovl_xattr ox, const void *value, size_t size,
int xerr)
{
int err;
- struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
if (ofs->noxattr)
return xerr;
@@ -623,6 +625,7 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry)
{
+ struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
int err;
if (ovl_test_flag(OVL_IMPURE, d_inode(dentry)))
@@ -632,14 +635,95 @@ int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry)
* Do not fail when upper doesn't support xattrs.
* Upper inodes won't have origin nor redirect xattr anyway.
*/
- err = ovl_check_setxattr(dentry, upperdentry, OVL_XATTR_IMPURE,
- "y", 1, 0);
+ err = ovl_check_setxattr(ofs, upperdentry, OVL_XATTR_IMPURE, "y", 1, 0);
if (!err)
ovl_set_flag(OVL_IMPURE, d_inode(dentry));
return err;
}
+
+#define OVL_PROTATTR_MAX 32 /* Reserved for future flags */
+
+void ovl_check_protattr(struct inode *inode, struct dentry *upper)
+{
+ struct ovl_fs *ofs = OVL_FS(inode->i_sb);
+ u32 iflags = inode->i_flags & OVL_PROT_I_FLAGS_MASK;
+ char buf[OVL_PROTATTR_MAX+1];
+ int res, n;
+
+ res = ovl_do_getxattr(ofs, upper, OVL_XATTR_PROTATTR, buf,
+ OVL_PROTATTR_MAX);
+ if (res < 0)
+ return;
+
+ /*
+ * Initialize inode flags from overlay.protattr xattr and upper inode
+ * flags. If upper inode has those fileattr flags set (i.e. from old
+ * kernel), we do not clear them on ovl_get_inode(), but we will clear
+ * them on next fileattr_set().
+ */
+ for (n = 0; n < res; n++) {
+ if (buf[n] == 'a')
+ iflags |= S_APPEND;
+ else if (buf[n] == 'i')
+ iflags |= S_IMMUTABLE;
+ else
+ break;
+ }
+
+ if (!res || n < res) {
+ pr_warn_ratelimited("incompatible overlay.protattr format (%pd2, len=%d)\n",
+ upper, res);
+ } else {
+ inode_set_flags(inode, iflags, OVL_PROT_I_FLAGS_MASK);
+ }
+}
+
+int ovl_set_protattr(struct inode *inode, struct dentry *upper,
+ struct fileattr *fa)
+{
+ struct ovl_fs *ofs = OVL_FS(inode->i_sb);
+ char buf[OVL_PROTATTR_MAX];
+ int len = 0, err = 0;
+ u32 iflags = 0;
+
+ BUILD_BUG_ON(HWEIGHT32(OVL_PROT_FS_FLAGS_MASK) > OVL_PROTATTR_MAX);
+
+ if (fa->flags & FS_APPEND_FL) {
+ buf[len++] = 'a';
+ iflags |= S_APPEND;
+ }
+ if (fa->flags & FS_IMMUTABLE_FL) {
+ buf[len++] = 'i';
+ iflags |= S_IMMUTABLE;
+ }
+
+ /*
+ * Do not allow to set protection flags when upper doesn't support
+ * xattrs, because we do not set those fileattr flags on upper inode.
+ * Remove xattr if it exist and all protection flags are cleared.
+ */
+ if (len) {
+ err = ovl_check_setxattr(ofs, upper, OVL_XATTR_PROTATTR,
+ buf, len, -EPERM);
+ } else if (inode->i_flags & OVL_PROT_I_FLAGS_MASK) {
+ err = ovl_do_removexattr(ofs, upper, OVL_XATTR_PROTATTR);
+ if (err == -EOPNOTSUPP || err == -ENODATA)
+ err = 0;
+ }
+ if (err)
+ return err;
+
+ inode_set_flags(inode, iflags, OVL_PROT_I_FLAGS_MASK);
+
+ /* Mask out the fileattr flags that should not be set in upper inode */
+ fa->flags &= ~OVL_PROT_FS_FLAGS_MASK;
+ fa->fsx_xflags &= ~OVL_PROT_FSX_FLAGS_MASK;
+
+ return 0;
+}
+
/**
* Caller must hold a reference to inode to prevent it from being freed while
* it is marked inuse.
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index f3309a7edb49..f5c25f580dd9 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -22,6 +22,7 @@
#include <linux/xattr.h>
#include <linux/export.h>
#include <linux/user_namespace.h>
+#include <linux/namei.h>
static struct posix_acl **acl_by_type(struct inode *inode, int type)
{
@@ -56,7 +57,17 @@ EXPORT_SYMBOL(get_cached_acl);
struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type)
{
- return rcu_dereference(*acl_by_type(inode, type));
+ struct posix_acl *acl = rcu_dereference(*acl_by_type(inode, type));
+
+ if (acl == ACL_DONT_CACHE) {
+ struct posix_acl *ret;
+
+ ret = inode->i_op->get_acl(inode, type, LOOKUP_RCU);
+ if (!IS_ERR(ret))
+ acl = ret;
+ }
+
+ return acl;
}
EXPORT_SYMBOL(get_cached_acl_rcu);
@@ -138,7 +149,7 @@ struct posix_acl *get_acl(struct inode *inode, int type)
set_cached_acl(inode, type, NULL);
return NULL;
}
- acl = inode->i_op->get_acl(inode, type);
+ acl = inode->i_op->get_acl(inode, type, false);
if (IS_ERR(acl)) {
/*
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index eb97468dfe4c..cf25be3e0321 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -619,7 +619,6 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
[ilog2(VM_MAYSHARE)] = "ms",
[ilog2(VM_GROWSDOWN)] = "gd",
[ilog2(VM_PFNMAP)] = "pf",
- [ilog2(VM_DENYWRITE)] = "dw",
[ilog2(VM_LOCKED)] = "lo",
[ilog2(VM_IO)] = "io",
[ilog2(VM_SEQ_READ)] = "sr",
diff --git a/fs/reiserfs/acl.h b/fs/reiserfs/acl.h
index fd58618da360..d9052b8ce6dd 100644
--- a/fs/reiserfs/acl.h
+++ b/fs/reiserfs/acl.h
@@ -48,7 +48,7 @@ static inline int reiserfs_acl_count(size_t size)
}
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
-struct posix_acl *reiserfs_get_acl(struct inode *inode, int type);
+struct posix_acl *reiserfs_get_acl(struct inode *inode, int type, bool rcu);
int reiserfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
int reiserfs_acl_chmod(struct inode *inode);
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
index 500f2000eb41..30319dc33c18 100644
--- a/fs/reiserfs/prints.c
+++ b/fs/reiserfs/prints.c
@@ -8,7 +8,7 @@
#include <linux/string.h>
#include <linux/buffer_head.h>
-#include <stdarg.h>
+#include <linux/stdarg.h>
static char error_buf[1024];
static char fmt_buf[1024];
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index a9547144a099..d6fcddc46f5b 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -190,13 +190,16 @@ fail:
* inode->i_mutex: down
* BKL held [before 2.5.x]
*/
-struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
+struct posix_acl *reiserfs_get_acl(struct inode *inode, int type, bool rcu)
{
char *name, *value;
struct posix_acl *acl;
int size;
int retval;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
switch (type) {
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 167b5889db4b..040e1cf90528 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -114,10 +114,10 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
break;
case SIL_FAULT_BNDERR:
case SIL_FAULT_PKUERR:
- case SIL_PERF_EVENT:
+ case SIL_FAULT_PERF_EVENT:
/*
* Fall through to the SIL_FAULT case. SIL_FAULT_BNDERR,
- * SIL_FAULT_PKUERR, and SIL_PERF_EVENT are only
+ * SIL_FAULT_PKUERR, and SIL_FAULT_PERF_EVENT are only
* generated by faults that deliver them synchronously to
* userspace. In case someone injects one of these signals
* and signalfd catches it treat it as SIL_FAULT.
diff --git a/fs/stat.c b/fs/stat.c
index 1fa38bdec1a6..28d2020ba1f4 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -60,6 +60,24 @@ void generic_fillattr(struct user_namespace *mnt_userns, struct inode *inode,
EXPORT_SYMBOL(generic_fillattr);
/**
+ * generic_fill_statx_attr - Fill in the statx attributes from the inode flags
+ * @inode: Inode to use as the source
+ * @stat: Where to fill in the attribute flags
+ *
+ * Fill in the STATX_ATTR_* flags in the kstat structure for properties of the
+ * inode that are published on i_flags and enforced by the VFS.
+ */
+void generic_fill_statx_attr(struct inode *inode, struct kstat *stat)
+{
+ if (inode->i_flags & S_IMMUTABLE)
+ stat->attributes |= STATX_ATTR_IMMUTABLE;
+ if (inode->i_flags & S_APPEND)
+ stat->attributes |= STATX_ATTR_APPEND;
+ stat->attributes_mask |= KSTAT_ATTR_VFS_FLAGS;
+}
+EXPORT_SYMBOL(generic_fill_statx_attr);
+
+/**
* vfs_getattr_nosec - getattr without security checks
* @path: file to get attributes from
* @stat: structure to return attributes in
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 9aefa7779b29..d019d6ac6ad0 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -174,8 +174,8 @@ static int sysfs_kf_bin_open(struct kernfs_open_file *of)
{
struct bin_attribute *battr = of->kn->priv;
- if (battr->mapping)
- of->file->f_mapping = battr->mapping;
+ if (battr->f_mapping)
+ of->file->f_mapping = battr->f_mapping();
return 0;
}
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 64e6a6698935..f29d62004527 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -446,7 +446,7 @@ int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
if (!target)
return -ENOENT;
- entry = kernfs_find_and_get(target_kobj->sd, target_name);
+ entry = kernfs_find_and_get(target, target_name);
if (!entry) {
kernfs_put(target);
return -ENOENT;
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 74028b5a7b0a..00a01471ea05 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -70,7 +70,7 @@
#include <linux/module.h>
#include <linux/bitops.h>
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/uaccess.h>
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 5c2d806e6ae5..003f0d31743e 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -33,11 +33,6 @@ int sysctl_unprivileged_userfaultfd __read_mostly;
static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
-enum userfaultfd_state {
- UFFD_STATE_WAIT_API,
- UFFD_STATE_RUNNING,
-};
-
/*
* Start with fault_pending_wqh and fault_wqh so they're more likely
* to be in the same cacheline.
@@ -69,12 +64,10 @@ struct userfaultfd_ctx {
unsigned int flags;
/* features requested from the userspace */
unsigned int features;
- /* state machine */
- enum userfaultfd_state state;
/* released */
bool released;
/* memory mappings are changing because of non-cooperative event */
- bool mmap_changing;
+ atomic_t mmap_changing;
/* mm with one ore more vmas attached to this userfaultfd_ctx */
struct mm_struct *mm;
};
@@ -104,6 +97,14 @@ struct userfaultfd_wake_range {
unsigned long len;
};
+/* internal indication that UFFD_API ioctl was successfully executed */
+#define UFFD_FEATURE_INITIALIZED (1u << 31)
+
+static bool userfaultfd_is_initialized(struct userfaultfd_ctx *ctx)
+{
+ return ctx->features & UFFD_FEATURE_INITIALIZED;
+}
+
static int userfaultfd_wake_function(wait_queue_entry_t *wq, unsigned mode,
int wake_flags, void *key)
{
@@ -623,7 +624,8 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
* already released.
*/
out:
- WRITE_ONCE(ctx->mmap_changing, false);
+ atomic_dec(&ctx->mmap_changing);
+ VM_BUG_ON(atomic_read(&ctx->mmap_changing) < 0);
userfaultfd_ctx_put(ctx);
}
@@ -666,15 +668,14 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
refcount_set(&ctx->refcount, 1);
ctx->flags = octx->flags;
- ctx->state = UFFD_STATE_RUNNING;
ctx->features = octx->features;
ctx->released = false;
- ctx->mmap_changing = false;
+ atomic_set(&ctx->mmap_changing, 0);
ctx->mm = vma->vm_mm;
mmgrab(ctx->mm);
userfaultfd_ctx_get(octx);
- WRITE_ONCE(octx->mmap_changing, true);
+ atomic_inc(&octx->mmap_changing);
fctx->orig = octx;
fctx->new = ctx;
list_add_tail(&fctx->list, fcs);
@@ -721,7 +722,7 @@ void mremap_userfaultfd_prep(struct vm_area_struct *vma,
if (ctx->features & UFFD_FEATURE_EVENT_REMAP) {
vm_ctx->ctx = ctx;
userfaultfd_ctx_get(ctx);
- WRITE_ONCE(ctx->mmap_changing, true);
+ atomic_inc(&ctx->mmap_changing);
} else {
/* Drop uffd context if remap feature not enabled */
vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
@@ -766,7 +767,7 @@ bool userfaultfd_remove(struct vm_area_struct *vma,
return true;
userfaultfd_ctx_get(ctx);
- WRITE_ONCE(ctx->mmap_changing, true);
+ atomic_inc(&ctx->mmap_changing);
mmap_read_unlock(mm);
msg_init(&ewq.msg);
@@ -810,7 +811,7 @@ int userfaultfd_unmap_prep(struct vm_area_struct *vma,
return -ENOMEM;
userfaultfd_ctx_get(ctx);
- WRITE_ONCE(ctx->mmap_changing, true);
+ atomic_inc(&ctx->mmap_changing);
unmap_ctx->ctx = ctx;
unmap_ctx->start = start;
unmap_ctx->end = end;
@@ -943,38 +944,33 @@ static __poll_t userfaultfd_poll(struct file *file, poll_table *wait)
poll_wait(file, &ctx->fd_wqh, wait);
- switch (ctx->state) {
- case UFFD_STATE_WAIT_API:
+ if (!userfaultfd_is_initialized(ctx))
return EPOLLERR;
- case UFFD_STATE_RUNNING:
- /*
- * poll() never guarantees that read won't block.
- * userfaults can be waken before they're read().
- */
- if (unlikely(!(file->f_flags & O_NONBLOCK)))
- return EPOLLERR;
- /*
- * lockless access to see if there are pending faults
- * __pollwait last action is the add_wait_queue but
- * the spin_unlock would allow the waitqueue_active to
- * pass above the actual list_add inside
- * add_wait_queue critical section. So use a full
- * memory barrier to serialize the list_add write of
- * add_wait_queue() with the waitqueue_active read
- * below.
- */
- ret = 0;
- smp_mb();
- if (waitqueue_active(&ctx->fault_pending_wqh))
- ret = EPOLLIN;
- else if (waitqueue_active(&ctx->event_wqh))
- ret = EPOLLIN;
- return ret;
- default:
- WARN_ON_ONCE(1);
+ /*
+ * poll() never guarantees that read won't block.
+ * userfaults can be waken before they're read().
+ */
+ if (unlikely(!(file->f_flags & O_NONBLOCK)))
return EPOLLERR;
- }
+ /*
+ * lockless access to see if there are pending faults
+ * __pollwait last action is the add_wait_queue but
+ * the spin_unlock would allow the waitqueue_active to
+ * pass above the actual list_add inside
+ * add_wait_queue critical section. So use a full
+ * memory barrier to serialize the list_add write of
+ * add_wait_queue() with the waitqueue_active read
+ * below.
+ */
+ ret = 0;
+ smp_mb();
+ if (waitqueue_active(&ctx->fault_pending_wqh))
+ ret = EPOLLIN;
+ else if (waitqueue_active(&ctx->event_wqh))
+ ret = EPOLLIN;
+
+ return ret;
}
static const struct file_operations userfaultfd_fops;
@@ -1169,7 +1165,7 @@ static ssize_t userfaultfd_read(struct file *file, char __user *buf,
int no_wait = file->f_flags & O_NONBLOCK;
struct inode *inode = file_inode(file);
- if (ctx->state == UFFD_STATE_WAIT_API)
+ if (!userfaultfd_is_initialized(ctx))
return -EINVAL;
for (;;) {
@@ -1700,7 +1696,7 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
user_uffdio_copy = (struct uffdio_copy __user *) arg;
ret = -EAGAIN;
- if (READ_ONCE(ctx->mmap_changing))
+ if (atomic_read(&ctx->mmap_changing))
goto out;
ret = -EFAULT;
@@ -1757,7 +1753,7 @@ static int userfaultfd_zeropage(struct userfaultfd_ctx *ctx,
user_uffdio_zeropage = (struct uffdio_zeropage __user *) arg;
ret = -EAGAIN;
- if (READ_ONCE(ctx->mmap_changing))
+ if (atomic_read(&ctx->mmap_changing))
goto out;
ret = -EFAULT;
@@ -1807,7 +1803,7 @@ static int userfaultfd_writeprotect(struct userfaultfd_ctx *ctx,
struct userfaultfd_wake_range range;
bool mode_wp, mode_dontwake;
- if (READ_ONCE(ctx->mmap_changing))
+ if (atomic_read(&ctx->mmap_changing))
return -EAGAIN;
user_uffdio_wp = (struct uffdio_writeprotect __user *) arg;
@@ -1855,7 +1851,7 @@ static int userfaultfd_continue(struct userfaultfd_ctx *ctx, unsigned long arg)
user_uffdio_continue = (struct uffdio_continue __user *)arg;
ret = -EAGAIN;
- if (READ_ONCE(ctx->mmap_changing))
+ if (atomic_read(&ctx->mmap_changing))
goto out;
ret = -EFAULT;
@@ -1908,9 +1904,10 @@ out:
static inline unsigned int uffd_ctx_features(__u64 user_features)
{
/*
- * For the current set of features the bits just coincide
+ * For the current set of features the bits just coincide. Set
+ * UFFD_FEATURE_INITIALIZED to mark the features as enabled.
*/
- return (unsigned int)user_features;
+ return (unsigned int)user_features | UFFD_FEATURE_INITIALIZED;
}
/*
@@ -1923,12 +1920,10 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
{
struct uffdio_api uffdio_api;
void __user *buf = (void __user *)arg;
+ unsigned int ctx_features;
int ret;
__u64 features;
- ret = -EINVAL;
- if (ctx->state != UFFD_STATE_WAIT_API)
- goto out;
ret = -EFAULT;
if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api)))
goto out;
@@ -1952,9 +1947,13 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
ret = -EFAULT;
if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api)))
goto out;
- ctx->state = UFFD_STATE_RUNNING;
+
/* only enable the requested features for this uffd context */
- ctx->features = uffd_ctx_features(features);
+ ctx_features = uffd_ctx_features(features);
+ ret = -EINVAL;
+ if (cmpxchg(&ctx->features, 0, ctx_features) != 0)
+ goto err_out;
+
ret = 0;
out:
return ret;
@@ -1971,7 +1970,7 @@ static long userfaultfd_ioctl(struct file *file, unsigned cmd,
int ret = -EINVAL;
struct userfaultfd_ctx *ctx = file->private_data;
- if (cmd != UFFDIO_API && ctx->state == UFFD_STATE_WAIT_API)
+ if (cmd != UFFDIO_API && !userfaultfd_is_initialized(ctx))
return -EINVAL;
switch(cmd) {
@@ -2085,9 +2084,8 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)
refcount_set(&ctx->refcount, 1);
ctx->flags = flags;
ctx->features = 0;
- ctx->state = UFFD_STATE_WAIT_API;
ctx->released = false;
- ctx->mmap_changing = false;
+ atomic_set(&ctx->mmap_changing, 0);
ctx->mm = current->mm;
/* prevent the mm struct to be freed */
mmgrab(ctx->mm);
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c
index e986b95d94c9..6f49bf39183c 100644
--- a/fs/xfs/kmem.c
+++ b/fs/xfs/kmem.c
@@ -29,67 +29,3 @@ kmem_alloc(size_t size, xfs_km_flags_t flags)
congestion_wait(BLK_RW_ASYNC, HZ/50);
} while (1);
}
-
-
-/*
- * __vmalloc() will allocate data pages and auxiliary structures (e.g.
- * pagetables) with GFP_KERNEL, yet we may be under GFP_NOFS context here. Hence
- * we need to tell memory reclaim that we are in such a context via
- * PF_MEMALLOC_NOFS to prevent memory reclaim re-entering the filesystem here
- * and potentially deadlocking.
- */
-static void *
-__kmem_vmalloc(size_t size, xfs_km_flags_t flags)
-{
- unsigned nofs_flag = 0;
- void *ptr;
- gfp_t lflags = kmem_flags_convert(flags);
-
- if (flags & KM_NOFS)
- nofs_flag = memalloc_nofs_save();
-
- ptr = __vmalloc(size, lflags);
-
- if (flags & KM_NOFS)
- memalloc_nofs_restore(nofs_flag);
-
- return ptr;
-}
-
-/*
- * Same as kmem_alloc_large, except we guarantee the buffer returned is aligned
- * to the @align_mask. We only guarantee alignment up to page size, we'll clamp
- * alignment at page size if it is larger. vmalloc always returns a PAGE_SIZE
- * aligned region.
- */
-void *
-kmem_alloc_io(size_t size, int align_mask, xfs_km_flags_t flags)
-{
- void *ptr;
-
- trace_kmem_alloc_io(size, flags, _RET_IP_);
-
- if (WARN_ON_ONCE(align_mask >= PAGE_SIZE))
- align_mask = PAGE_SIZE - 1;
-
- ptr = kmem_alloc(size, flags | KM_MAYFAIL);
- if (ptr) {
- if (!((uintptr_t)ptr & align_mask))
- return ptr;
- kfree(ptr);
- }
- return __kmem_vmalloc(size, flags);
-}
-
-void *
-kmem_alloc_large(size_t size, xfs_km_flags_t flags)
-{
- void *ptr;
-
- trace_kmem_alloc_large(size, flags, _RET_IP_);
-
- ptr = kmem_alloc(size, flags | KM_MAYFAIL);
- if (ptr)
- return ptr;
- return __kmem_vmalloc(size, flags);
-}
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h
index 38007117697e..54da6d717a06 100644
--- a/fs/xfs/kmem.h
+++ b/fs/xfs/kmem.h
@@ -57,8 +57,6 @@ kmem_flags_convert(xfs_km_flags_t flags)
}
extern void *kmem_alloc(size_t, xfs_km_flags_t);
-extern void *kmem_alloc_io(size_t size, int align_mask, xfs_km_flags_t flags);
-extern void *kmem_alloc_large(size_t size, xfs_km_flags_t);
static inline void kmem_free(const void *ptr)
{
kvfree(ptr);
diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c
index ee9ec0c50bec..005abfd9fd34 100644
--- a/fs/xfs/libxfs/xfs_ag.c
+++ b/fs/xfs/libxfs/xfs_ag.c
@@ -313,7 +313,6 @@ xfs_get_aghdr_buf(
if (error)
return error;
- bp->b_bn = blkno;
bp->b_maps[0].bm_bn = blkno;
bp->b_ops = ops;
@@ -469,7 +468,7 @@ xfs_rmaproot_init(
rrec->rm_offset = 0;
/* account for refc btree root */
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ if (xfs_has_reflink(mp)) {
rrec = XFS_RMAP_REC_ADDR(block, 5);
rrec->rm_startblock = cpu_to_be32(xfs_refc_block(mp));
rrec->rm_blockcount = cpu_to_be32(1);
@@ -528,7 +527,7 @@ xfs_agfblock_init(
agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
- if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ if (xfs_has_rmapbt(mp)) {
agf->agf_roots[XFS_BTNUM_RMAPi] =
cpu_to_be32(XFS_RMAP_BLOCK(mp));
agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1);
@@ -541,9 +540,9 @@ xfs_agfblock_init(
tmpsize = id->agsize - mp->m_ag_prealloc_blocks;
agf->agf_freeblks = cpu_to_be32(tmpsize);
agf->agf_longest = cpu_to_be32(tmpsize);
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid);
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ if (xfs_has_reflink(mp)) {
agf->agf_refcount_root = cpu_to_be32(
xfs_refc_block(mp));
agf->agf_refcount_level = cpu_to_be32(1);
@@ -569,7 +568,7 @@ xfs_agflblock_init(
__be32 *agfl_bno;
int bucket;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
agfl->agfl_seqno = cpu_to_be32(id->agno);
uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid);
@@ -599,17 +598,17 @@ xfs_agiblock_init(
agi->agi_freecount = 0;
agi->agi_newino = cpu_to_be32(NULLAGINO);
agi->agi_dirino = cpu_to_be32(NULLAGINO);
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid);
- if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
+ if (xfs_has_finobt(mp)) {
agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp));
agi->agi_free_level = cpu_to_be32(1);
}
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
- if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+ if (xfs_has_inobtcounts(mp)) {
agi->agi_iblocks = cpu_to_be32(1);
- if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (xfs_has_finobt(mp))
agi->agi_fblocks = cpu_to_be32(1);
}
}
@@ -719,14 +718,14 @@ xfs_ag_init_headers(
.ops = &xfs_finobt_buf_ops,
.work = &xfs_btroot_init,
.type = XFS_BTNUM_FINO,
- .need_init = xfs_sb_version_hasfinobt(&mp->m_sb)
+ .need_init = xfs_has_finobt(mp)
},
{ /* RMAP root block */
.daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_RMAP_BLOCK(mp)),
.numblks = BTOBB(mp->m_sb.sb_blocksize),
.ops = &xfs_rmapbt_buf_ops,
.work = &xfs_rmaproot_init,
- .need_init = xfs_sb_version_hasrmapbt(&mp->m_sb)
+ .need_init = xfs_has_rmapbt(mp)
},
{ /* REFC root block */
.daddr = XFS_AGB_TO_DADDR(mp, id->agno, xfs_refc_block(mp)),
@@ -734,7 +733,7 @@ xfs_ag_init_headers(
.ops = &xfs_refcountbt_buf_ops,
.work = &xfs_btroot_init,
.type = XFS_BTNUM_REFC,
- .need_init = xfs_sb_version_hasreflink(&mp->m_sb)
+ .need_init = xfs_has_reflink(mp)
},
{ /* NULL terminating block */
.daddr = XFS_BUF_DADDR_NULL,
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 6929157d8d6e..95157f5a5a6c 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -51,7 +51,7 @@ xfs_agfl_size(
{
unsigned int size = mp->m_sb.sb_sectsize;
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
size -= sizeof(struct xfs_agfl);
return size / sizeof(xfs_agblock_t);
@@ -61,9 +61,9 @@ unsigned int
xfs_refc_block(
struct xfs_mount *mp)
{
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (xfs_has_rmapbt(mp))
return XFS_RMAP_BLOCK(mp) + 1;
- if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (xfs_has_finobt(mp))
return XFS_FIBT_BLOCK(mp) + 1;
return XFS_IBT_BLOCK(mp) + 1;
}
@@ -72,11 +72,11 @@ xfs_extlen_t
xfs_prealloc_blocks(
struct xfs_mount *mp)
{
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
return xfs_refc_block(mp) + 1;
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (xfs_has_rmapbt(mp))
return XFS_RMAP_BLOCK(mp) + 1;
- if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (xfs_has_finobt(mp))
return XFS_FIBT_BLOCK(mp) + 1;
return XFS_IBT_BLOCK(mp) + 1;
}
@@ -126,11 +126,11 @@ xfs_alloc_ag_max_usable(
blocks = XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)); /* ag headers */
blocks += XFS_ALLOC_AGFL_RESERVE;
blocks += 3; /* AGF, AGI btree root blocks */
- if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (xfs_has_finobt(mp))
blocks++; /* finobt root block */
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (xfs_has_rmapbt(mp))
blocks++; /* rmap root block */
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
blocks++; /* refcount root block */
return mp->m_sb.sb_agblocks - blocks;
@@ -598,7 +598,7 @@ xfs_agfl_verify(
* AGFL is what the AGF says is active. We can't get to the AGF, so we
* can't verify just those entries are valid.
*/
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return NULL;
if (!xfs_verify_magic(bp, agfl->agfl_magicnum))
@@ -638,7 +638,7 @@ xfs_agfl_read_verify(
* AGFL is what the AGF says is active. We can't get to the AGF, so we
* can't verify just those entries are valid.
*/
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (!xfs_buf_verify_cksum(bp, XFS_AGFL_CRC_OFF))
@@ -659,7 +659,7 @@ xfs_agfl_write_verify(
xfs_failaddr_t fa;
/* no verification of non-crc AGFLs */
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
fa = xfs_agfl_verify(bp);
@@ -2264,7 +2264,7 @@ xfs_alloc_min_freelist(
min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1,
mp->m_ag_maxlevels);
/* space needed reverse mapping used space btree */
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (xfs_has_rmapbt(mp))
min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1,
mp->m_rmap_maxlevels);
@@ -2373,7 +2373,7 @@ xfs_agfl_needs_reset(
int active;
/* no agfl header on v4 supers */
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return false;
/*
@@ -2877,7 +2877,7 @@ xfs_agf_verify(
struct xfs_mount *mp = bp->b_mount;
struct xfs_agf *agf = bp->b_addr;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (!uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
if (!xfs_log_check_lsn(mp, be64_to_cpu(agf->agf_lsn)))
@@ -2907,12 +2907,12 @@ xfs_agf_verify(
be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > mp->m_ag_maxlevels)
return __this_address;
- if (xfs_sb_version_hasrmapbt(&mp->m_sb) &&
+ if (xfs_has_rmapbt(mp) &&
(be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) < 1 ||
be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > mp->m_rmap_maxlevels))
return __this_address;
- if (xfs_sb_version_hasrmapbt(&mp->m_sb) &&
+ if (xfs_has_rmapbt(mp) &&
be32_to_cpu(agf->agf_rmap_blocks) > be32_to_cpu(agf->agf_length))
return __this_address;
@@ -2925,16 +2925,16 @@ xfs_agf_verify(
if (bp->b_pag && be32_to_cpu(agf->agf_seqno) != bp->b_pag->pag_agno)
return __this_address;
- if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
+ if (xfs_has_lazysbcount(mp) &&
be32_to_cpu(agf->agf_btreeblks) > be32_to_cpu(agf->agf_length))
return __this_address;
- if (xfs_sb_version_hasreflink(&mp->m_sb) &&
+ if (xfs_has_reflink(mp) &&
be32_to_cpu(agf->agf_refcount_blocks) >
be32_to_cpu(agf->agf_length))
return __this_address;
- if (xfs_sb_version_hasreflink(&mp->m_sb) &&
+ if (xfs_has_reflink(mp) &&
(be32_to_cpu(agf->agf_refcount_level) < 1 ||
be32_to_cpu(agf->agf_refcount_level) > mp->m_refc_maxlevels))
return __this_address;
@@ -2950,7 +2950,7 @@ xfs_agf_read_verify(
struct xfs_mount *mp = bp->b_mount;
xfs_failaddr_t fa;
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ if (xfs_has_crc(mp) &&
!xfs_buf_verify_cksum(bp, XFS_AGF_CRC_OFF))
xfs_verifier_error(bp, -EFSBADCRC, __this_address);
else {
@@ -2975,7 +2975,7 @@ xfs_agf_write_verify(
return;
}
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (bip)
@@ -3073,13 +3073,13 @@ xfs_alloc_read_agf(
* counter only tracks non-root blocks.
*/
allocbt_blks = pag->pagf_btreeblks;
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (xfs_has_rmapbt(mp))
allocbt_blks -= be32_to_cpu(agf->agf_rmap_blocks) - 1;
if (allocbt_blks > 0)
atomic64_add(allocbt_blks, &mp->m_allocbt_blks);
}
#ifdef DEBUG
- else if (!XFS_FORCED_SHUTDOWN(mp)) {
+ else if (!xfs_is_shutdown(mp)) {
ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks));
ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks));
ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount));
@@ -3166,7 +3166,7 @@ xfs_alloc_vextent(
* the first a.g. fails.
*/
if ((args->datatype & XFS_ALLOC_INITIAL_USER_DATA) &&
- (mp->m_flags & XFS_MOUNT_32BITINODES)) {
+ xfs_is_inode32(mp)) {
args->fsbno = XFS_AGB_TO_FSB(mp,
((mp->m_agfrotor / rotorstep) %
mp->m_sb.sb_agcount), 0);
@@ -3392,7 +3392,7 @@ struct xfs_alloc_query_range_info {
STATIC int
xfs_alloc_query_range_helper(
struct xfs_btree_cur *cur,
- union xfs_btree_rec *rec,
+ const union xfs_btree_rec *rec,
void *priv)
{
struct xfs_alloc_query_range_info *query = priv;
@@ -3407,8 +3407,8 @@ xfs_alloc_query_range_helper(
int
xfs_alloc_query_range(
struct xfs_btree_cur *cur,
- struct xfs_alloc_rec_incore *low_rec,
- struct xfs_alloc_rec_incore *high_rec,
+ const struct xfs_alloc_rec_incore *low_rec,
+ const struct xfs_alloc_rec_incore *high_rec,
xfs_alloc_query_range_fn fn,
void *priv)
{
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index e30900b6f8ba..df4aefaf0046 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -220,13 +220,13 @@ int xfs_free_extent_fix_freelist(struct xfs_trans *tp, struct xfs_perag *pag,
xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp);
typedef int (*xfs_alloc_query_range_fn)(
- struct xfs_btree_cur *cur,
- struct xfs_alloc_rec_incore *rec,
- void *priv);
+ struct xfs_btree_cur *cur,
+ const struct xfs_alloc_rec_incore *rec,
+ void *priv);
int xfs_alloc_query_range(struct xfs_btree_cur *cur,
- struct xfs_alloc_rec_incore *low_rec,
- struct xfs_alloc_rec_incore *high_rec,
+ const struct xfs_alloc_rec_incore *low_rec,
+ const struct xfs_alloc_rec_incore *high_rec,
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);
@@ -243,7 +243,7 @@ static inline __be32 *
xfs_buf_to_agfl_bno(
struct xfs_buf *bp)
{
- if (xfs_sb_version_hascrc(&bp->b_mount->m_sb))
+ if (xfs_has_crc(bp->b_mount))
return bp->b_addr + sizeof(struct xfs_agfl);
return bp->b_addr;
}
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c
index 6b363f78cfa2..6746fd735550 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.c
+++ b/fs/xfs/libxfs/xfs_alloc_btree.c
@@ -31,9 +31,9 @@ xfs_allocbt_dup_cursor(
STATIC void
xfs_allocbt_set_root(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr,
- int inc)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr,
+ int inc)
{
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agf *agf = agbp->b_addr;
@@ -50,10 +50,10 @@ xfs_allocbt_set_root(
STATIC int
xfs_allocbt_alloc_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start,
- union xfs_btree_ptr *new,
- int *stat)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *start,
+ union xfs_btree_ptr *new,
+ int *stat)
{
int error;
xfs_agblock_t bno;
@@ -87,7 +87,7 @@ xfs_allocbt_free_block(
xfs_agblock_t bno;
int error;
- bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp));
+ bno = xfs_daddr_to_agbno(cur->bc_mp, xfs_buf_daddr(bp));
error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1);
if (error)
return error;
@@ -103,11 +103,11 @@ xfs_allocbt_free_block(
*/
STATIC void
xfs_allocbt_update_lastrec(
- struct xfs_btree_cur *cur,
- struct xfs_btree_block *block,
- union xfs_btree_rec *rec,
- int ptr,
- int reason)
+ struct xfs_btree_cur *cur,
+ const struct xfs_btree_block *block,
+ const union xfs_btree_rec *rec,
+ int ptr,
+ int reason)
{
struct xfs_agf *agf = cur->bc_ag.agbp->b_addr;
struct xfs_perag *pag;
@@ -177,8 +177,8 @@ xfs_allocbt_get_maxrecs(
STATIC void
xfs_allocbt_init_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
key->alloc.ar_startblock = rec->alloc.ar_startblock;
key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
@@ -186,10 +186,10 @@ xfs_allocbt_init_key_from_rec(
STATIC void
xfs_bnobt_init_high_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
- __u32 x;
+ __u32 x;
x = be32_to_cpu(rec->alloc.ar_startblock);
x += be32_to_cpu(rec->alloc.ar_blockcount) - 1;
@@ -199,8 +199,8 @@ xfs_bnobt_init_high_key_from_rec(
STATIC void
xfs_cntbt_init_high_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
key->alloc.ar_startblock = 0;
@@ -229,23 +229,23 @@ xfs_allocbt_init_ptr_from_cur(
STATIC int64_t
xfs_bnobt_key_diff(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *key)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key)
{
- xfs_alloc_rec_incore_t *rec = &cur->bc_rec.a;
- xfs_alloc_key_t *kp = &key->alloc;
+ struct xfs_alloc_rec_incore *rec = &cur->bc_rec.a;
+ const struct xfs_alloc_rec *kp = &key->alloc;
return (int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
}
STATIC int64_t
xfs_cntbt_key_diff(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *key)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key)
{
- xfs_alloc_rec_incore_t *rec = &cur->bc_rec.a;
- xfs_alloc_key_t *kp = &key->alloc;
- int64_t diff;
+ struct xfs_alloc_rec_incore *rec = &cur->bc_rec.a;
+ const struct xfs_alloc_rec *kp = &key->alloc;
+ int64_t diff;
diff = (int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount;
if (diff)
@@ -256,9 +256,9 @@ xfs_cntbt_key_diff(
STATIC int64_t
xfs_bnobt_diff_two_keys(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
return (int64_t)be32_to_cpu(k1->alloc.ar_startblock) -
be32_to_cpu(k2->alloc.ar_startblock);
@@ -266,11 +266,11 @@ xfs_bnobt_diff_two_keys(
STATIC int64_t
xfs_cntbt_diff_two_keys(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
- int64_t diff;
+ int64_t diff;
diff = be32_to_cpu(k1->alloc.ar_blockcount) -
be32_to_cpu(k2->alloc.ar_blockcount);
@@ -295,7 +295,7 @@ xfs_allocbt_verify(
if (!xfs_verify_magic(bp, block->bb_magic))
return __this_address;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
fa = xfs_btree_sblock_v5hdr_verify(bp);
if (fa)
return fa;
@@ -376,9 +376,9 @@ const struct xfs_buf_ops xfs_cntbt_buf_ops = {
STATIC int
xfs_bnobt_keys_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
return be32_to_cpu(k1->alloc.ar_startblock) <
be32_to_cpu(k2->alloc.ar_startblock);
@@ -386,9 +386,9 @@ xfs_bnobt_keys_inorder(
STATIC int
xfs_bnobt_recs_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *r1,
- union xfs_btree_rec *r2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *r1,
+ const union xfs_btree_rec *r2)
{
return be32_to_cpu(r1->alloc.ar_startblock) +
be32_to_cpu(r1->alloc.ar_blockcount) <=
@@ -397,9 +397,9 @@ xfs_bnobt_recs_inorder(
STATIC int
xfs_cntbt_keys_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
return be32_to_cpu(k1->alloc.ar_blockcount) <
be32_to_cpu(k2->alloc.ar_blockcount) ||
@@ -410,9 +410,9 @@ xfs_cntbt_keys_inorder(
STATIC int
xfs_cntbt_recs_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *r1,
- union xfs_btree_rec *r2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *r1,
+ const union xfs_btree_rec *r2)
{
return be32_to_cpu(r1->alloc.ar_blockcount) <
be32_to_cpu(r2->alloc.ar_blockcount) ||
@@ -498,7 +498,7 @@ xfs_allocbt_init_common(
atomic_inc(&pag->pag_ref);
cur->bc_ag.pag = pag;
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
return cur;
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.h b/fs/xfs/libxfs/xfs_alloc_btree.h
index 9eb4c667a6b8..2f6b816aaf9f 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.h
+++ b/fs/xfs/libxfs/xfs_alloc_btree.h
@@ -20,7 +20,7 @@ struct xbtree_afakeroot;
* Btree block header size depends on a superblock flag.
*/
#define XFS_ALLOC_BLOCK_LEN(mp) \
- (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+ (xfs_has_crc(((mp))) ? \
XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN)
/*
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 191d51725988..fbc9d816882c 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -146,7 +146,7 @@ xfs_attr_get(
XFS_STATS_INC(args->dp->i_mount, xs_attr_get);
- if (XFS_FORCED_SHUTDOWN(args->dp->i_mount))
+ if (xfs_is_shutdown(args->dp->i_mount))
return -EIO;
args->geo = args->dp->i_mount->m_attr_geo;
@@ -224,7 +224,7 @@ xfs_attr_try_sf_addname(
if (!error && !(args->op_flags & XFS_DA_OP_NOTIME))
xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
- if (dp->i_mount->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(dp->i_mount))
xfs_trans_set_sync(args->trans);
return error;
@@ -335,6 +335,7 @@ xfs_attr_sf_addname(
* the attr fork to leaf format and will restart with the leaf
* add.
*/
+ trace_xfs_attr_sf_addname_return(XFS_DAS_UNINIT, args->dp);
dac->flags |= XFS_DAC_DEFER_FINISH;
return -EAGAIN;
}
@@ -394,6 +395,8 @@ xfs_attr_set_iter(
* handling code below
*/
dac->flags |= XFS_DAC_DEFER_FINISH;
+ trace_xfs_attr_set_iter_return(
+ dac->dela_state, args->dp);
return -EAGAIN;
} else if (error) {
return error;
@@ -411,6 +414,7 @@ xfs_attr_set_iter(
dac->dela_state = XFS_DAS_FOUND_NBLK;
}
+ trace_xfs_attr_set_iter_return(dac->dela_state, args->dp);
return -EAGAIN;
case XFS_DAS_FOUND_LBLK:
/*
@@ -438,6 +442,8 @@ xfs_attr_set_iter(
error = xfs_attr_rmtval_set_blk(dac);
if (error)
return error;
+ trace_xfs_attr_set_iter_return(dac->dela_state,
+ args->dp);
return -EAGAIN;
}
@@ -472,6 +478,7 @@ xfs_attr_set_iter(
* series.
*/
dac->dela_state = XFS_DAS_FLIP_LFLAG;
+ trace_xfs_attr_set_iter_return(dac->dela_state, args->dp);
return -EAGAIN;
case XFS_DAS_FLIP_LFLAG:
/*
@@ -488,11 +495,15 @@ xfs_attr_set_iter(
/* Set state in case xfs_attr_rmtval_remove returns -EAGAIN */
dac->dela_state = XFS_DAS_RM_LBLK;
if (args->rmtblkno) {
- error = __xfs_attr_rmtval_remove(dac);
+ error = xfs_attr_rmtval_remove(dac);
+ if (error == -EAGAIN)
+ trace_xfs_attr_set_iter_return(
+ dac->dela_state, args->dp);
if (error)
return error;
dac->dela_state = XFS_DAS_RD_LEAF;
+ trace_xfs_attr_set_iter_return(dac->dela_state, args->dp);
return -EAGAIN;
}
@@ -542,6 +553,8 @@ xfs_attr_set_iter(
error = xfs_attr_rmtval_set_blk(dac);
if (error)
return error;
+ trace_xfs_attr_set_iter_return(
+ dac->dela_state, args->dp);
return -EAGAIN;
}
@@ -577,6 +590,7 @@ xfs_attr_set_iter(
* series
*/
dac->dela_state = XFS_DAS_FLIP_NFLAG;
+ trace_xfs_attr_set_iter_return(dac->dela_state, args->dp);
return -EAGAIN;
case XFS_DAS_FLIP_NFLAG:
@@ -595,11 +609,16 @@ xfs_attr_set_iter(
/* Set state in case xfs_attr_rmtval_remove returns -EAGAIN */
dac->dela_state = XFS_DAS_RM_NBLK;
if (args->rmtblkno) {
- error = __xfs_attr_rmtval_remove(dac);
+ error = xfs_attr_rmtval_remove(dac);
+ if (error == -EAGAIN)
+ trace_xfs_attr_set_iter_return(
+ dac->dela_state, args->dp);
+
if (error)
return error;
dac->dela_state = XFS_DAS_CLR_FLAG;
+ trace_xfs_attr_set_iter_return(dac->dela_state, args->dp);
return -EAGAIN;
}
@@ -623,8 +642,8 @@ out:
/*
* Return EEXIST if attr is found, or ENOATTR if not
*/
-int
-xfs_has_attr(
+static int
+xfs_attr_lookup(
struct xfs_da_args *args)
{
struct xfs_inode *dp = args->dp;
@@ -691,7 +710,7 @@ xfs_attr_set(
int rmt_blks = 0;
unsigned int total;
- if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+ if (xfs_is_shutdown(dp->i_mount))
return -EIO;
error = xfs_qm_dqattach(dp);
@@ -761,8 +780,8 @@ xfs_attr_set(
goto out_trans_cancel;
}
+ error = xfs_attr_lookup(args);
if (args->value) {
- error = xfs_has_attr(args);
if (error == -EEXIST && (args->attr_flags & XATTR_CREATE))
goto out_trans_cancel;
if (error == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
@@ -777,7 +796,6 @@ xfs_attr_set(
if (!args->trans)
goto out_unlock;
} else {
- error = xfs_has_attr(args);
if (error != -EEXIST)
goto out_trans_cancel;
@@ -790,7 +808,7 @@ xfs_attr_set(
* If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(mp))
xfs_trans_set_sync(args->trans);
if (!(args->op_flags & XFS_DA_OP_NOTIME))
@@ -1176,6 +1194,8 @@ xfs_attr_node_addname(
* this point.
*/
dac->flags |= XFS_DAC_DEFER_FINISH;
+ trace_xfs_attr_node_addname_return(
+ dac->dela_state, args->dp);
return -EAGAIN;
}
@@ -1421,11 +1441,14 @@ xfs_attr_remove_iter(
* May return -EAGAIN. Roll and repeat until all remote
* blocks are removed.
*/
- error = __xfs_attr_rmtval_remove(dac);
- if (error == -EAGAIN)
+ error = xfs_attr_rmtval_remove(dac);
+ if (error == -EAGAIN) {
+ trace_xfs_attr_remove_iter_return(
+ dac->dela_state, args->dp);
return error;
- else if (error)
+ } else if (error) {
goto out;
+ }
/*
* Refill the state structure with buffers (the prior
@@ -1438,6 +1461,7 @@ xfs_attr_remove_iter(
goto out;
dac->dela_state = XFS_DAS_RM_NAME;
dac->flags |= XFS_DAC_DEFER_FINISH;
+ trace_xfs_attr_remove_iter_return(dac->dela_state, args->dp);
return -EAGAIN;
}
@@ -1466,6 +1490,8 @@ xfs_attr_remove_iter(
dac->flags |= XFS_DAC_DEFER_FINISH;
dac->dela_state = XFS_DAS_RM_SHRINK;
+ trace_xfs_attr_remove_iter_return(
+ dac->dela_state, args->dp);
return -EAGAIN;
}
@@ -1514,7 +1540,7 @@ xfs_attr_fillstate(xfs_da_state_t *state)
ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
if (blk->bp) {
- blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
+ blk->disk_blkno = xfs_buf_daddr(blk->bp);
blk->bp = NULL;
} else {
blk->disk_blkno = 0;
@@ -1529,7 +1555,7 @@ xfs_attr_fillstate(xfs_da_state_t *state)
ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
if (blk->bp) {
- blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
+ blk->disk_blkno = xfs_buf_daddr(blk->bp);
blk->bp = NULL;
} else {
blk->disk_blkno = 0;
diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
index 8de5d1d2733e..5e71f719bdd5 100644
--- a/fs/xfs/libxfs/xfs_attr.h
+++ b/fs/xfs/libxfs/xfs_attr.h
@@ -490,7 +490,6 @@ int xfs_attr_get_ilocked(struct xfs_da_args *args);
int xfs_attr_get(struct xfs_da_args *args);
int xfs_attr_set(struct xfs_da_args *args);
int xfs_attr_set_args(struct xfs_da_args *args);
-int xfs_has_attr(struct xfs_da_args *args);
int xfs_attr_remove_args(struct xfs_da_args *args);
int xfs_attr_remove_iter(struct xfs_delattr_context *dac);
bool xfs_attr_namecheck(const void *name, size_t length);
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index b910bd209949..e1d11e314228 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -384,7 +384,7 @@ xfs_attr3_leaf_write_verify(
return;
}
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (bip)
@@ -406,7 +406,7 @@ xfs_attr3_leaf_read_verify(
struct xfs_mount *mp = bp->b_mount;
xfs_failaddr_t fa;
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ if (xfs_has_crc(mp) &&
!xfs_buf_verify_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF))
xfs_verifier_error(bp, -EFSBADCRC, __this_address);
else {
@@ -489,7 +489,7 @@ xfs_attr_copy_value(
}
if (!args->value) {
- args->value = kmem_alloc_large(valuelen, KM_NOLOCKDEP);
+ args->value = kvmalloc(valuelen, GFP_KERNEL | __GFP_NOLOCKDEP);
if (!args->value)
return -ENOMEM;
}
@@ -568,7 +568,7 @@ xfs_attr_shortform_bytesfit(
* literal area, but for the old format we are done if there is no
* space in the fixed attribute fork.
*/
- if (!(mp->m_flags & XFS_MOUNT_ATTR2))
+ if (!xfs_has_attr2(mp))
return 0;
dsize = dp->i_df.if_bytes;
@@ -576,7 +576,7 @@ xfs_attr_shortform_bytesfit(
switch (dp->i_df.if_format) {
case XFS_DINODE_FMT_EXTENTS:
/*
- * If there is no attr fork and the data fork is extents,
+ * If there is no attr fork and the data fork is extents,
* determine if creating the default attr fork will result
* in the extents form migrating to btree. If so, the
* minimum offset only needs to be the space required for
@@ -621,21 +621,27 @@ xfs_attr_shortform_bytesfit(
}
/*
- * Switch on the ATTR2 superblock bit (implies also FEATURES2)
+ * Switch on the ATTR2 superblock bit (implies also FEATURES2) unless:
+ * - noattr2 mount option is set,
+ * - on-disk version bit says it is already set, or
+ * - the attr2 mount option is not set to enable automatic upgrade from attr1.
*/
STATIC void
-xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
+xfs_sbversion_add_attr2(
+ struct xfs_mount *mp,
+ struct xfs_trans *tp)
{
- if ((mp->m_flags & XFS_MOUNT_ATTR2) &&
- !(xfs_sb_version_hasattr2(&mp->m_sb))) {
- spin_lock(&mp->m_sb_lock);
- if (!xfs_sb_version_hasattr2(&mp->m_sb)) {
- xfs_sb_version_addattr2(&mp->m_sb);
- spin_unlock(&mp->m_sb_lock);
- xfs_log_sb(tp);
- } else
- spin_unlock(&mp->m_sb_lock);
- }
+ if (xfs_has_noattr2(mp))
+ return;
+ if (mp->m_sb.sb_features2 & XFS_SB_VERSION2_ATTR2BIT)
+ return;
+ if (!xfs_has_attr2(mp))
+ return;
+
+ spin_lock(&mp->m_sb_lock);
+ xfs_add_attr2(mp);
+ spin_unlock(&mp->m_sb_lock);
+ xfs_log_sb(tp);
}
/*
@@ -810,8 +816,7 @@ xfs_attr_sf_removename(
* Fix up the start offset of the attribute fork
*/
totsize -= size;
- if (totsize == sizeof(xfs_attr_sf_hdr_t) &&
- (mp->m_flags & XFS_MOUNT_ATTR2) &&
+ if (totsize == sizeof(xfs_attr_sf_hdr_t) && xfs_has_attr2(mp) &&
(dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
!(args->op_flags & XFS_DA_OP_ADDNAME)) {
xfs_attr_fork_remove(dp, args->trans);
@@ -821,7 +826,7 @@ xfs_attr_sf_removename(
ASSERT(dp->i_forkoff);
ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) ||
(args->op_flags & XFS_DA_OP_ADDNAME) ||
- !(mp->m_flags & XFS_MOUNT_ATTR2) ||
+ !xfs_has_attr2(mp) ||
dp->i_df.if_format == XFS_DINODE_FMT_BTREE);
xfs_trans_log_inode(args->trans, dp,
XFS_ILOG_CORE | XFS_ILOG_ADATA);
@@ -997,7 +1002,7 @@ xfs_attr_shortform_allfit(
bytes += xfs_attr_sf_entsize_byname(name_loc->namelen,
be16_to_cpu(name_loc->valuelen));
}
- if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
+ if (xfs_has_attr2(dp->i_mount) &&
(dp->i_df.if_format != XFS_DINODE_FMT_BTREE) &&
(bytes == sizeof(struct xfs_attr_sf_hdr)))
return -1;
@@ -1122,7 +1127,7 @@ xfs_attr3_leaf_to_shortform(
goto out;
if (forkoff == -1) {
- ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
+ ASSERT(xfs_has_attr2(dp->i_mount));
ASSERT(dp->i_df.if_format != XFS_DINODE_FMT_BTREE);
xfs_attr_fork_remove(dp, args->trans);
goto out;
@@ -1199,9 +1204,9 @@ xfs_attr3_leaf_to_node(
xfs_trans_buf_set_type(args->trans, bp2, XFS_BLFT_ATTR_LEAF_BUF);
bp2->b_ops = bp1->b_ops;
memcpy(bp2->b_addr, bp1->b_addr, args->geo->blksize);
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_da3_blkinfo *hdr3 = bp2->b_addr;
- hdr3->blkno = cpu_to_be64(bp2->b_bn);
+ hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp2));
}
xfs_trans_log_buf(args->trans, bp2, 0, args->geo->blksize - 1);
@@ -1264,12 +1269,12 @@ xfs_attr3_leaf_create(
memset(&ichdr, 0, sizeof(ichdr));
ichdr.firstused = args->geo->blksize;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_da3_blkinfo *hdr3 = bp->b_addr;
ichdr.magic = XFS_ATTR3_LEAF_MAGIC;
- hdr3->blkno = cpu_to_be64(bp->b_bn);
+ hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
hdr3->owner = cpu_to_be64(dp->i_ino);
uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index 0c8bee3abc3b..83b95be9ded8 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -51,7 +51,7 @@ xfs_attr3_rmt_blocks(
struct xfs_mount *mp,
int attrlen)
{
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
return (attrlen + buflen - 1) / buflen;
}
@@ -126,11 +126,11 @@ __xfs_attr3_rmt_read_verify(
int blksize = mp->m_attr_geo->blksize;
/* no verification of non-crc buffers */
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return 0;
ptr = bp->b_addr;
- bno = bp->b_bn;
+ bno = xfs_buf_daddr(bp);
len = BBTOB(bp->b_length);
ASSERT(len >= blksize);
@@ -191,11 +191,11 @@ xfs_attr3_rmt_write_verify(
xfs_daddr_t bno;
/* no verification of non-crc buffers */
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
ptr = bp->b_addr;
- bno = bp->b_bn;
+ bno = xfs_buf_daddr(bp);
len = BBTOB(bp->b_length);
ASSERT(len >= blksize);
@@ -246,7 +246,7 @@ xfs_attr3_rmt_hdr_set(
{
struct xfs_attr3_rmt_hdr *rmt = ptr;
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return 0;
rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC);
@@ -284,7 +284,7 @@ xfs_attr_rmtval_copyout(
uint8_t **dst)
{
char *src = bp->b_addr;
- xfs_daddr_t bno = bp->b_bn;
+ xfs_daddr_t bno = xfs_buf_daddr(bp);
int len = BBTOB(bp->b_length);
int blksize = mp->m_attr_geo->blksize;
@@ -296,7 +296,7 @@ xfs_attr_rmtval_copyout(
byte_cnt = min(*valuelen, byte_cnt);
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (xfs_attr3_rmt_hdr_ok(src, ino, *offset,
byte_cnt, bno)) {
xfs_alert(mp,
@@ -332,7 +332,7 @@ xfs_attr_rmtval_copyin(
uint8_t **src)
{
char *dst = bp->b_addr;
- xfs_daddr_t bno = bp->b_bn;
+ xfs_daddr_t bno = xfs_buf_daddr(bp);
int len = BBTOB(bp->b_length);
int blksize = mp->m_attr_geo->blksize;
@@ -672,7 +672,7 @@ xfs_attr_rmtval_invalidate(
* routine until it returns something other than -EAGAIN.
*/
int
-__xfs_attr_rmtval_remove(
+xfs_attr_rmtval_remove(
struct xfs_delattr_context *dac)
{
struct xfs_da_args *args = dac->da_args;
@@ -696,6 +696,7 @@ __xfs_attr_rmtval_remove(
*/
if (!done) {
dac->flags |= XFS_DAC_DEFER_FINISH;
+ trace_xfs_attr_rmtval_remove_return(dac->dela_state, args->dp);
return -EAGAIN;
}
diff --git a/fs/xfs/libxfs/xfs_attr_remote.h b/fs/xfs/libxfs/xfs_attr_remote.h
index 61b85b918db8..d72eff30ca18 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.h
+++ b/fs/xfs/libxfs/xfs_attr_remote.h
@@ -12,7 +12,7 @@ int xfs_attr_rmtval_get(struct xfs_da_args *args);
int xfs_attr_rmtval_stale(struct xfs_inode *ip, struct xfs_bmbt_irec *map,
xfs_buf_flags_t incore_flags);
int xfs_attr_rmtval_invalidate(struct xfs_da_args *args);
-int __xfs_attr_rmtval_remove(struct xfs_delattr_context *dac);
+int xfs_attr_rmtval_remove(struct xfs_delattr_context *dac);
int xfs_attr_rmt_find_hole(struct xfs_da_args *args);
int xfs_attr_rmtval_set_value(struct xfs_da_args *args);
int xfs_attr_rmtval_set_blk(struct xfs_delattr_context *dac);
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 948092babb6a..b48230f1a361 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -242,7 +242,7 @@ xfs_bmap_get_bp(
for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) {
if (!cur->bc_bufs[i])
break;
- if (XFS_BUF_ADDR(cur->bc_bufs[i]) == bno)
+ if (xfs_buf_daddr(cur->bc_bufs[i]) == bno)
return cur->bc_bufs[i];
}
@@ -251,7 +251,7 @@ xfs_bmap_get_bp(
struct xfs_buf_log_item *bip = (struct xfs_buf_log_item *)lip;
if (bip->bli_item.li_type == XFS_LI_BUF &&
- XFS_BUF_ADDR(bip->bli_buf) == bno)
+ xfs_buf_daddr(bip->bli_buf) == bno)
return bip->bli_buf;
}
@@ -739,7 +739,7 @@ xfs_bmap_extents_to_btree(
*/
abp->b_ops = &xfs_bmbt_buf_ops;
ablock = XFS_BUF_TO_BLOCK(abp);
- xfs_btree_init_block_int(mp, ablock, abp->b_bn,
+ xfs_btree_init_block_int(mp, ablock, xfs_buf_daddr(abp),
XFS_BTNUM_BMAP, 0, 0, ip->i_ino,
XFS_BTREE_LONG_PTRS);
@@ -1047,7 +1047,7 @@ xfs_bmap_set_attrforkoff(
ip->i_forkoff = xfs_attr_shortform_bytesfit(ip, size);
if (!ip->i_forkoff)
ip->i_forkoff = default_size;
- else if ((ip->i_mount->m_flags & XFS_MOUNT_ATTR2) && version)
+ else if (xfs_has_attr2(ip->i_mount) && version)
*version = 2;
break;
default:
@@ -1115,17 +1115,17 @@ xfs_bmap_add_attrfork(
xfs_trans_log_inode(tp, ip, logflags);
if (error)
goto trans_cancel;
- if (!xfs_sb_version_hasattr(&mp->m_sb) ||
- (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
+ if (!xfs_has_attr(mp) ||
+ (!xfs_has_attr2(mp) && version == 2)) {
bool log_sb = false;
spin_lock(&mp->m_sb_lock);
- if (!xfs_sb_version_hasattr(&mp->m_sb)) {
- xfs_sb_version_addattr(&mp->m_sb);
+ if (!xfs_has_attr(mp)) {
+ xfs_add_attr(mp);
log_sb = true;
}
- if (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2) {
- xfs_sb_version_addattr2(&mp->m_sb);
+ if (!xfs_has_attr2(mp) && version == 2) {
+ xfs_add_attr2(mp);
log_sb = true;
}
spin_unlock(&mp->m_sb_lock);
@@ -3422,7 +3422,7 @@ xfs_bmap_compute_alignments(
int stripe_align = 0;
/* stripe alignment for allocation is determined by mount parameters */
- if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+ if (mp->m_swidth && xfs_has_swalloc(mp))
stripe_align = mp->m_swidth;
else if (mp->m_dalign)
stripe_align = mp->m_dalign;
@@ -3938,7 +3938,7 @@ xfs_bmapi_read(
XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT))
return -EFSCORRUPTED;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
XFS_STATS_INC(mp, xs_blk_mapr);
@@ -4420,7 +4420,7 @@ xfs_bmapi_write(
return -EFSCORRUPTED;
}
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
XFS_STATS_INC(mp, xs_blk_mapw);
@@ -4703,7 +4703,7 @@ xfs_bmapi_remap(
return -EFSCORRUPTED;
}
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
error = xfs_iread_extents(tp, ip, whichfork);
@@ -5361,7 +5361,7 @@ __xfs_bunmapi(
ifp = XFS_IFORK_PTR(ip, whichfork);
if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)))
return -EFSCORRUPTED;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
@@ -5852,7 +5852,7 @@ xfs_bmap_collapse_extents(
return -EFSCORRUPTED;
}
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL));
@@ -5930,7 +5930,7 @@ xfs_bmap_can_insert_extents(
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ if (xfs_is_shutdown(ip->i_mount))
return -EIO;
xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -5967,7 +5967,7 @@ xfs_bmap_insert_extents(
return -EFSCORRUPTED;
}
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL));
@@ -6070,7 +6070,7 @@ xfs_bmap_split_extent(
return -EFSCORRUPTED;
}
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
/* Read in all the extents */
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 1ceba020940e..72444b8b38a6 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -58,7 +58,7 @@ xfs_bmdr_to_bmbt(
void
xfs_bmbt_disk_get_all(
- struct xfs_bmbt_rec *rec,
+ const struct xfs_bmbt_rec *rec,
struct xfs_bmbt_irec *irec)
{
uint64_t l0 = get_unaligned_be64(&rec->l0);
@@ -78,7 +78,7 @@ xfs_bmbt_disk_get_all(
*/
xfs_filblks_t
xfs_bmbt_disk_get_blockcount(
- xfs_bmbt_rec_t *r)
+ const struct xfs_bmbt_rec *r)
{
return (xfs_filblks_t)(be64_to_cpu(r->l1) & xfs_mask64lo(21));
}
@@ -88,7 +88,7 @@ xfs_bmbt_disk_get_blockcount(
*/
xfs_fileoff_t
xfs_bmbt_disk_get_startoff(
- xfs_bmbt_rec_t *r)
+ const struct xfs_bmbt_rec *r)
{
return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
@@ -136,7 +136,7 @@ xfs_bmbt_to_bmdr(
xfs_bmbt_key_t *tkp;
__be64 *tpp;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid,
&mp->m_sb.sb_meta_uuid));
@@ -193,10 +193,10 @@ xfs_bmbt_update_cursor(
STATIC int
xfs_bmbt_alloc_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start,
- union xfs_btree_ptr *new,
- int *stat)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *start,
+ union xfs_btree_ptr *new,
+ int *stat)
{
xfs_alloc_arg_t args; /* block allocation args */
int error; /* error return value */
@@ -282,7 +282,7 @@ xfs_bmbt_free_block(
struct xfs_mount *mp = cur->bc_mp;
struct xfs_inode *ip = cur->bc_ino.ip;
struct xfs_trans *tp = cur->bc_tp;
- xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
+ xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
struct xfs_owner_info oinfo;
xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
@@ -352,8 +352,8 @@ xfs_bmbt_get_dmaxrecs(
STATIC void
xfs_bmbt_init_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
key->bmbt.br_startoff =
cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
@@ -361,8 +361,8 @@ xfs_bmbt_init_key_from_rec(
STATIC void
xfs_bmbt_init_high_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
key->bmbt.br_startoff = cpu_to_be64(
xfs_bmbt_disk_get_startoff(&rec->bmbt) +
@@ -387,8 +387,8 @@ xfs_bmbt_init_ptr_from_cur(
STATIC int64_t
xfs_bmbt_key_diff(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *key)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key)
{
return (int64_t)be64_to_cpu(key->bmbt.br_startoff) -
cur->bc_rec.b.br_startoff;
@@ -396,12 +396,12 @@ xfs_bmbt_key_diff(
STATIC int64_t
xfs_bmbt_diff_two_keys(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
- uint64_t a = be64_to_cpu(k1->bmbt.br_startoff);
- uint64_t b = be64_to_cpu(k2->bmbt.br_startoff);
+ uint64_t a = be64_to_cpu(k1->bmbt.br_startoff);
+ uint64_t b = be64_to_cpu(k2->bmbt.br_startoff);
/*
* Note: This routine previously casted a and b to int64 and subtracted
@@ -428,7 +428,7 @@ xfs_bmbt_verify(
if (!xfs_verify_magic(bp, block->bb_magic))
return __this_address;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
/*
* XXX: need a better way of verifying the owner here. Right now
* just make sure there has been one set.
@@ -497,9 +497,9 @@ const struct xfs_buf_ops xfs_bmbt_buf_ops = {
STATIC int
xfs_bmbt_keys_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
return be64_to_cpu(k1->bmbt.br_startoff) <
be64_to_cpu(k2->bmbt.br_startoff);
@@ -507,9 +507,9 @@ xfs_bmbt_keys_inorder(
STATIC int
xfs_bmbt_recs_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *r1,
- union xfs_btree_rec *r2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *r1,
+ const union xfs_btree_rec *r2)
{
return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
xfs_bmbt_disk_get_blockcount(&r1->bmbt) <=
@@ -563,7 +563,7 @@ xfs_bmbt_init_cursor(
cur->bc_ops = &xfs_bmbt_ops;
cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE;
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
cur->bc_ino.forksize = XFS_IFORK_SIZE(ip, whichfork);
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
index 72bf74c79fb9..729e3bc569be 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.h
+++ b/fs/xfs/libxfs/xfs_bmap_btree.h
@@ -16,7 +16,7 @@ struct xfs_trans;
* Btree block header size depends on a superblock flag.
*/
#define XFS_BMBT_BLOCK_LEN(mp) \
- (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+ (xfs_has_crc(((mp))) ? \
XFS_BTREE_LBLOCK_CRC_LEN : XFS_BTREE_LBLOCK_LEN)
#define XFS_BMBT_REC_ADDR(mp, block, index) \
@@ -88,9 +88,10 @@ extern void xfs_bmdr_to_bmbt(struct xfs_inode *, xfs_bmdr_block_t *, int,
struct xfs_btree_block *, int);
void xfs_bmbt_disk_set_all(struct xfs_bmbt_rec *r, struct xfs_bmbt_irec *s);
-extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r);
-extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r);
-extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
+extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(const struct xfs_bmbt_rec *r);
+extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(const struct xfs_bmbt_rec *r);
+void xfs_bmbt_disk_get_all(const struct xfs_bmbt_rec *r,
+ struct xfs_bmbt_irec *s);
extern void xfs_bmbt_to_bmdr(struct xfs_mount *, struct xfs_btree_block *, int,
xfs_bmdr_block_t *, int);
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index be74a6b53689..298395481713 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -64,13 +64,13 @@ __xfs_btree_check_lblock(
{
struct xfs_mount *mp = cur->bc_mp;
xfs_btnum_t btnum = cur->bc_btnum;
- int crc = xfs_sb_version_hascrc(&mp->m_sb);
+ int crc = xfs_has_crc(mp);
if (crc) {
if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
if (block->bb_u.l.bb_blkno !=
- cpu_to_be64(bp ? bp->b_bn : XFS_BUF_DADDR_NULL))
+ cpu_to_be64(bp ? xfs_buf_daddr(bp) : XFS_BUF_DADDR_NULL))
return __this_address;
if (block->bb_u.l.bb_pad != cpu_to_be32(0))
return __this_address;
@@ -129,13 +129,13 @@ __xfs_btree_check_sblock(
{
struct xfs_mount *mp = cur->bc_mp;
xfs_btnum_t btnum = cur->bc_btnum;
- int crc = xfs_sb_version_hascrc(&mp->m_sb);
+ int crc = xfs_has_crc(mp);
if (crc) {
if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
if (block->bb_u.s.bb_blkno !=
- cpu_to_be64(bp ? bp->b_bn : XFS_BUF_DADDR_NULL))
+ cpu_to_be64(bp ? xfs_buf_daddr(bp) : XFS_BUF_DADDR_NULL))
return __this_address;
}
@@ -225,10 +225,10 @@ xfs_btree_check_sptr(
*/
static int
xfs_btree_check_ptr(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr,
- int index,
- int level)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr,
+ int index,
+ int level)
{
if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
if (xfs_btree_check_lptr(cur, be64_to_cpu((&ptr->l)[index]),
@@ -273,7 +273,7 @@ xfs_btree_lblock_calc_crc(
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
struct xfs_buf_log_item *bip = bp->b_log_item;
- if (!xfs_sb_version_hascrc(&bp->b_mount->m_sb))
+ if (!xfs_has_crc(bp->b_mount))
return;
if (bip)
block->bb_u.l.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
@@ -287,7 +287,7 @@ xfs_btree_lblock_verify_crc(
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
struct xfs_mount *mp = bp->b_mount;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.l.bb_lsn)))
return false;
return xfs_buf_verify_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF);
@@ -311,7 +311,7 @@ xfs_btree_sblock_calc_crc(
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
struct xfs_buf_log_item *bip = bp->b_log_item;
- if (!xfs_sb_version_hascrc(&bp->b_mount->m_sb))
+ if (!xfs_has_crc(bp->b_mount))
return;
if (bip)
block->bb_u.s.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
@@ -325,7 +325,7 @@ xfs_btree_sblock_verify_crc(
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
struct xfs_mount *mp = bp->b_mount;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.s.bb_lsn)))
return false;
return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
@@ -374,7 +374,7 @@ xfs_btree_del_cursor(
}
ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP || cur->bc_ino.allocated == 0 ||
- XFS_FORCED_SHUTDOWN(cur->bc_mp));
+ xfs_is_shutdown(cur->bc_mp));
if (unlikely(cur->bc_flags & XFS_BTREE_STAGING))
kmem_free(cur->bc_ops);
if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS) && cur->bc_ag.pag)
@@ -420,7 +420,7 @@ xfs_btree_dup_cursor(
bp = cur->bc_bufs[i];
if (bp) {
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
- XFS_BUF_ADDR(bp), mp->m_bsize,
+ xfs_buf_daddr(bp), mp->m_bsize,
0, &bp,
cur->bc_ops->buf_ops);
if (error) {
@@ -935,9 +935,9 @@ xfs_btree_readahead(
STATIC int
xfs_btree_ptr_to_daddr(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr,
- xfs_daddr_t *daddr)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr,
+ xfs_daddr_t *daddr)
{
xfs_fsblock_t fsbno;
xfs_agblock_t agbno;
@@ -1012,8 +1012,8 @@ xfs_btree_setbuf(
bool
xfs_btree_ptr_is_null(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr)
{
if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
return ptr->l == cpu_to_be64(NULLFSBLOCK);
@@ -1059,10 +1059,10 @@ xfs_btree_get_sibling(
void
xfs_btree_set_sibling(
- struct xfs_btree_cur *cur,
- struct xfs_btree_block *block,
- union xfs_btree_ptr *ptr,
- int lr)
+ struct xfs_btree_cur *cur,
+ struct xfs_btree_block *block,
+ const union xfs_btree_ptr *ptr,
+ int lr)
{
ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB);
@@ -1090,7 +1090,7 @@ xfs_btree_init_block_int(
__u64 owner,
unsigned int flags)
{
- int crc = xfs_sb_version_hascrc(&mp->m_sb);
+ int crc = xfs_has_crc(mp);
__u32 magic = xfs_btree_magic(crc, btnum);
buf->bb_magic = cpu_to_be32(magic);
@@ -1131,7 +1131,7 @@ xfs_btree_init_block(
__u16 numrecs,
__u64 owner)
{
- xfs_btree_init_block_int(mp, XFS_BUF_TO_BLOCK(bp), bp->b_bn,
+ xfs_btree_init_block_int(mp, XFS_BUF_TO_BLOCK(bp), xfs_buf_daddr(bp),
btnum, level, numrecs, owner, 0);
}
@@ -1155,9 +1155,9 @@ xfs_btree_init_block_cur(
else
owner = cur->bc_ag.pag->pag_agno;
- xfs_btree_init_block_int(cur->bc_mp, XFS_BUF_TO_BLOCK(bp), bp->b_bn,
- cur->bc_btnum, level, numrecs,
- owner, cur->bc_flags);
+ xfs_btree_init_block_int(cur->bc_mp, XFS_BUF_TO_BLOCK(bp),
+ xfs_buf_daddr(bp), cur->bc_btnum, level,
+ numrecs, owner, cur->bc_flags);
}
/*
@@ -1192,10 +1192,10 @@ xfs_btree_buf_to_ptr(
{
if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
ptr->l = cpu_to_be64(XFS_DADDR_TO_FSB(cur->bc_mp,
- XFS_BUF_ADDR(bp)));
+ xfs_buf_daddr(bp)));
else {
ptr->s = cpu_to_be32(xfs_daddr_to_agbno(cur->bc_mp,
- XFS_BUF_ADDR(bp)));
+ xfs_buf_daddr(bp)));
}
}
@@ -1229,10 +1229,10 @@ xfs_btree_set_refs(
int
xfs_btree_get_buf_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr,
- struct xfs_btree_block **block,
- struct xfs_buf **bpp)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr,
+ struct xfs_btree_block **block,
+ struct xfs_buf **bpp)
{
struct xfs_mount *mp = cur->bc_mp;
xfs_daddr_t d;
@@ -1257,11 +1257,11 @@ xfs_btree_get_buf_block(
*/
STATIC int
xfs_btree_read_buf_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr,
- int flags,
- struct xfs_btree_block **block,
- struct xfs_buf **bpp)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr,
+ int flags,
+ struct xfs_btree_block **block,
+ struct xfs_buf **bpp)
{
struct xfs_mount *mp = cur->bc_mp;
xfs_daddr_t d;
@@ -1289,10 +1289,10 @@ xfs_btree_read_buf_block(
*/
void
xfs_btree_copy_keys(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *dst_key,
- union xfs_btree_key *src_key,
- int numkeys)
+ struct xfs_btree_cur *cur,
+ union xfs_btree_key *dst_key,
+ const union xfs_btree_key *src_key,
+ int numkeys)
{
ASSERT(numkeys >= 0);
memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len);
@@ -1713,10 +1713,10 @@ error0:
int
xfs_btree_lookup_get_block(
- struct xfs_btree_cur *cur, /* btree cursor */
- int level, /* level in the btree */
- union xfs_btree_ptr *pp, /* ptr to btree block */
- struct xfs_btree_block **blkp) /* return btree block */
+ struct xfs_btree_cur *cur, /* btree cursor */
+ int level, /* level in the btree */
+ const union xfs_btree_ptr *pp, /* ptr to btree block */
+ struct xfs_btree_block **blkp) /* return btree block */
{
struct xfs_buf *bp; /* buffer pointer for btree block */
xfs_daddr_t daddr;
@@ -1739,7 +1739,7 @@ xfs_btree_lookup_get_block(
error = xfs_btree_ptr_to_daddr(cur, pp, &daddr);
if (error)
return error;
- if (bp && XFS_BUF_ADDR(bp) == daddr) {
+ if (bp && xfs_buf_daddr(bp) == daddr) {
*blkp = XFS_BUF_TO_BLOCK(bp);
return 0;
}
@@ -1749,7 +1749,7 @@ xfs_btree_lookup_get_block(
return error;
/* Check the inode owner since the verifiers don't. */
- if (xfs_sb_version_hascrc(&cur->bc_mp->m_sb) &&
+ if (xfs_has_crc(cur->bc_mp) &&
!(cur->bc_ino.flags & XFS_BTCUR_BMBT_INVALID_OWNER) &&
(cur->bc_flags & XFS_BTREE_LONG_PTRS) &&
be64_to_cpu((*blkp)->bb_u.l.bb_owner) !=
@@ -2923,10 +2923,11 @@ xfs_btree_new_iroot(
*/
memcpy(cblock, block, xfs_btree_block_len(cur));
if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+ __be64 bno = cpu_to_be64(xfs_buf_daddr(cbp));
if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
- cblock->bb_u.l.bb_blkno = cpu_to_be64(cbp->b_bn);
+ cblock->bb_u.l.bb_blkno = bno;
else
- cblock->bb_u.s.bb_blkno = cpu_to_be64(cbp->b_bn);
+ cblock->bb_u.s.bb_blkno = bno;
}
be16_add_cpu(&block->bb_level, 1);
@@ -3225,7 +3226,7 @@ xfs_btree_insrec(
/* Get pointers to the btree buffer and block. */
block = xfs_btree_get_block(cur, level, &bp);
- old_bn = bp ? bp->b_bn : XFS_BUF_DADDR_NULL;
+ old_bn = bp ? xfs_buf_daddr(bp) : XFS_BUF_DADDR_NULL;
numrecs = xfs_btree_get_numrecs(block);
#ifdef DEBUG
@@ -3341,7 +3342,7 @@ xfs_btree_insrec(
* some records into the new tree block), so use the regular key
* update mechanism.
*/
- if (bp && bp->b_bn != old_bn) {
+ if (bp && xfs_buf_daddr(bp) != old_bn) {
xfs_btree_get_keys(cur, block, lkey);
} else if (xfs_btree_needs_key_update(cur, optr)) {
error = xfs_btree_update_keys(cur, level);
@@ -4418,11 +4419,11 @@ xfs_btree_lblock_v5hdr_verify(
struct xfs_mount *mp = bp->b_mount;
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return __this_address;
if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
- if (block->bb_u.l.bb_blkno != cpu_to_be64(bp->b_bn))
+ if (block->bb_u.l.bb_blkno != cpu_to_be64(xfs_buf_daddr(bp)))
return __this_address;
if (owner != XFS_RMAP_OWN_UNKNOWN &&
be64_to_cpu(block->bb_u.l.bb_owner) != owner)
@@ -4468,11 +4469,11 @@ xfs_btree_sblock_v5hdr_verify(
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
struct xfs_perag *pag = bp->b_pag;
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return __this_address;
if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
- if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn))
+ if (block->bb_u.s.bb_blkno != cpu_to_be64(xfs_buf_daddr(bp)))
return __this_address;
if (pag && be32_to_cpu(block->bb_u.s.bb_owner) != pag->pag_agno)
return __this_address;
@@ -4499,7 +4500,7 @@ xfs_btree_sblock_verify(
return __this_address;
/* sibling pointer verification */
- agno = xfs_daddr_to_agno(mp, XFS_BUF_ADDR(bp));
+ agno = xfs_daddr_to_agno(mp, xfs_buf_daddr(bp));
if (block->bb_u.s.bb_leftsib != cpu_to_be32(NULLAGBLOCK) &&
!xfs_verify_agbno(mp, agno, be32_to_cpu(block->bb_u.s.bb_leftsib)))
return __this_address;
@@ -4536,8 +4537,8 @@ xfs_btree_compute_maxlevels(
STATIC int
xfs_btree_simple_query_range(
struct xfs_btree_cur *cur,
- union xfs_btree_key *low_key,
- union xfs_btree_key *high_key,
+ const union xfs_btree_key *low_key,
+ const union xfs_btree_key *high_key,
xfs_btree_query_range_fn fn,
void *priv)
{
@@ -4627,8 +4628,8 @@ out:
STATIC int
xfs_btree_overlapped_query_range(
struct xfs_btree_cur *cur,
- union xfs_btree_key *low_key,
- union xfs_btree_key *high_key,
+ const union xfs_btree_key *low_key,
+ const union xfs_btree_key *high_key,
xfs_btree_query_range_fn fn,
void *priv)
{
@@ -4769,8 +4770,8 @@ out:
int
xfs_btree_query_range(
struct xfs_btree_cur *cur,
- union xfs_btree_irec *low_rec,
- union xfs_btree_irec *high_rec,
+ const union xfs_btree_irec *low_rec,
+ const union xfs_btree_irec *high_rec,
xfs_btree_query_range_fn fn,
void *priv)
{
@@ -4877,7 +4878,7 @@ xfs_btree_diff_two_ptrs(
STATIC int
xfs_btree_has_record_helper(
struct xfs_btree_cur *cur,
- union xfs_btree_rec *rec,
+ const union xfs_btree_rec *rec,
void *priv)
{
return -ECANCELED;
@@ -4886,12 +4887,12 @@ xfs_btree_has_record_helper(
/* Is there a record covering a given range of keys? */
int
xfs_btree_has_record(
- struct xfs_btree_cur *cur,
- union xfs_btree_irec *low,
- union xfs_btree_irec *high,
- bool *exists)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_irec *low,
+ const union xfs_btree_irec *high,
+ bool *exists)
{
- int error;
+ int error;
error = xfs_btree_query_range(cur, low, high,
&xfs_btree_has_record_helper, NULL);
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 4dbdc659c396..4eaf8517f850 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -106,19 +106,19 @@ struct xfs_btree_ops {
/* update btree root pointer */
void (*set_root)(struct xfs_btree_cur *cur,
- union xfs_btree_ptr *nptr, int level_change);
+ const union xfs_btree_ptr *nptr, int level_change);
/* block allocation / freeing */
int (*alloc_block)(struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start_bno,
+ const union xfs_btree_ptr *start_bno,
union xfs_btree_ptr *new_bno,
int *stat);
int (*free_block)(struct xfs_btree_cur *cur, struct xfs_buf *bp);
/* update last record information */
void (*update_lastrec)(struct xfs_btree_cur *cur,
- struct xfs_btree_block *block,
- union xfs_btree_rec *rec,
+ const struct xfs_btree_block *block,
+ const union xfs_btree_rec *rec,
int ptr, int reason);
/* records in block/level */
@@ -130,37 +130,37 @@ struct xfs_btree_ops {
/* init values of btree structures */
void (*init_key_from_rec)(union xfs_btree_key *key,
- union xfs_btree_rec *rec);
+ const union xfs_btree_rec *rec);
void (*init_rec_from_cur)(struct xfs_btree_cur *cur,
union xfs_btree_rec *rec);
void (*init_ptr_from_cur)(struct xfs_btree_cur *cur,
union xfs_btree_ptr *ptr);
void (*init_high_key_from_rec)(union xfs_btree_key *key,
- union xfs_btree_rec *rec);
+ const union xfs_btree_rec *rec);
/* difference between key value and cursor value */
int64_t (*key_diff)(struct xfs_btree_cur *cur,
- union xfs_btree_key *key);
+ const union xfs_btree_key *key);
/*
* Difference between key2 and key1 -- positive if key1 > key2,
* negative if key1 < key2, and zero if equal.
*/
int64_t (*diff_two_keys)(struct xfs_btree_cur *cur,
- union xfs_btree_key *key1,
- union xfs_btree_key *key2);
+ const union xfs_btree_key *key1,
+ const union xfs_btree_key *key2);
const struct xfs_buf_ops *buf_ops;
/* check that k1 is lower than k2 */
int (*keys_inorder)(struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2);
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2);
/* check that r1 is lower than r2 */
int (*recs_inorder)(struct xfs_btree_cur *cur,
- union xfs_btree_rec *r1,
- union xfs_btree_rec *r2);
+ const union xfs_btree_rec *r1,
+ const union xfs_btree_rec *r2);
};
/*
@@ -423,7 +423,7 @@ void xfs_btree_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int, int);
/*
* Helpers.
*/
-static inline int xfs_btree_get_numrecs(struct xfs_btree_block *block)
+static inline int xfs_btree_get_numrecs(const struct xfs_btree_block *block)
{
return be16_to_cpu(block->bb_numrecs);
}
@@ -434,7 +434,7 @@ static inline void xfs_btree_set_numrecs(struct xfs_btree_block *block,
block->bb_numrecs = cpu_to_be16(numrecs);
}
-static inline int xfs_btree_get_level(struct xfs_btree_block *block)
+static inline int xfs_btree_get_level(const struct xfs_btree_block *block)
{
return be16_to_cpu(block->bb_level);
}
@@ -471,10 +471,11 @@ unsigned long long xfs_btree_calc_size(uint *limits, unsigned long long len);
* code on its own.
*/
typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur,
- union xfs_btree_rec *rec, void *priv);
+ const union xfs_btree_rec *rec, void *priv);
int xfs_btree_query_range(struct xfs_btree_cur *cur,
- union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec,
+ const union xfs_btree_irec *low_rec,
+ const union xfs_btree_irec *high_rec,
xfs_btree_query_range_fn fn, void *priv);
int xfs_btree_query_all(struct xfs_btree_cur *cur, xfs_btree_query_range_fn fn,
void *priv);
@@ -502,10 +503,11 @@ union xfs_btree_key *xfs_btree_high_key_addr(struct xfs_btree_cur *cur, int n,
union xfs_btree_ptr *xfs_btree_ptr_addr(struct xfs_btree_cur *cur, int n,
struct xfs_btree_block *block);
int xfs_btree_lookup_get_block(struct xfs_btree_cur *cur, int level,
- union xfs_btree_ptr *pp, struct xfs_btree_block **blkp);
+ const union xfs_btree_ptr *pp, struct xfs_btree_block **blkp);
struct xfs_btree_block *xfs_btree_get_block(struct xfs_btree_cur *cur,
int level, struct xfs_buf **bpp);
-bool xfs_btree_ptr_is_null(struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr);
+bool xfs_btree_ptr_is_null(struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr);
int64_t xfs_btree_diff_two_ptrs(struct xfs_btree_cur *cur,
const union xfs_btree_ptr *a,
const union xfs_btree_ptr *b);
@@ -516,8 +518,9 @@ void xfs_btree_get_keys(struct xfs_btree_cur *cur,
struct xfs_btree_block *block, union xfs_btree_key *key);
union xfs_btree_key *xfs_btree_high_key_from_key(struct xfs_btree_cur *cur,
union xfs_btree_key *key);
-int xfs_btree_has_record(struct xfs_btree_cur *cur, union xfs_btree_irec *low,
- union xfs_btree_irec *high, bool *exists);
+int xfs_btree_has_record(struct xfs_btree_cur *cur,
+ const union xfs_btree_irec *low,
+ const union xfs_btree_irec *high, bool *exists);
bool xfs_btree_has_more_records(struct xfs_btree_cur *cur);
struct xfs_ifork *xfs_btree_ifork_ptr(struct xfs_btree_cur *cur);
@@ -540,10 +543,11 @@ xfs_btree_islastblock(
void xfs_btree_set_ptr_null(struct xfs_btree_cur *cur,
union xfs_btree_ptr *ptr);
-int xfs_btree_get_buf_block(struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr,
- struct xfs_btree_block **block, struct xfs_buf **bpp);
+int xfs_btree_get_buf_block(struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr, struct xfs_btree_block **block,
+ struct xfs_buf **bpp);
void xfs_btree_set_sibling(struct xfs_btree_cur *cur,
- struct xfs_btree_block *block, union xfs_btree_ptr *ptr,
+ struct xfs_btree_block *block, const union xfs_btree_ptr *ptr,
int lr);
void xfs_btree_init_block_cur(struct xfs_btree_cur *cur,
struct xfs_buf *bp, int level, int numrecs);
@@ -551,7 +555,7 @@ void xfs_btree_copy_ptrs(struct xfs_btree_cur *cur,
union xfs_btree_ptr *dst_ptr,
const union xfs_btree_ptr *src_ptr, int numptrs);
void xfs_btree_copy_keys(struct xfs_btree_cur *cur,
- union xfs_btree_key *dst_key, union xfs_btree_key *src_key,
- int numkeys);
+ union xfs_btree_key *dst_key,
+ const union xfs_btree_key *src_key, int numkeys);
#endif /* __XFS_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_btree_staging.c b/fs/xfs/libxfs/xfs_btree_staging.c
index aa8dc9521c39..ac9e80152b5c 100644
--- a/fs/xfs/libxfs/xfs_btree_staging.c
+++ b/fs/xfs/libxfs/xfs_btree_staging.c
@@ -59,10 +59,10 @@ xfs_btree_fakeroot_dup_cursor(
*/
STATIC int
xfs_btree_fakeroot_alloc_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start_bno,
- union xfs_btree_ptr *new_bno,
- int *stat)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *start_bno,
+ union xfs_btree_ptr *new_bno,
+ int *stat)
{
ASSERT(0);
return -EFSCORRUPTED;
@@ -112,9 +112,9 @@ xfs_btree_fakeroot_init_ptr_from_cur(
/* Update the btree root information for a per-AG fake root. */
STATIC void
xfs_btree_afakeroot_set_root(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr,
- int inc)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr,
+ int inc)
{
struct xbtree_afakeroot *afake = cur->bc_ag.afake;
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index 747ec77912c3..c062e2c85178 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -129,7 +129,7 @@ xfs_da3_node_hdr_from_disk(
struct xfs_da3_icnode_hdr *to,
struct xfs_da_intnode *from)
{
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_da3_intnode *from3 = (struct xfs_da3_intnode *)from;
to->forw = be32_to_cpu(from3->hdr.info.hdr.forw);
@@ -156,7 +156,7 @@ xfs_da3_node_hdr_to_disk(
struct xfs_da_intnode *to,
struct xfs_da3_icnode_hdr *from)
{
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_da3_intnode *to3 = (struct xfs_da3_intnode *)to;
ASSERT(from->magic == XFS_DA3_NODE_MAGIC);
@@ -191,10 +191,10 @@ xfs_da3_blkinfo_verify(
if (!xfs_verify_magic16(bp, hdr->magic))
return __this_address;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
- if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
+ if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))
return __this_address;
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
return __this_address;
@@ -253,7 +253,7 @@ xfs_da3_node_write_verify(
return;
}
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (bip)
@@ -442,12 +442,12 @@ xfs_da3_node_create(
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DA_NODE_BUF);
node = bp->b_addr;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
memset(hdr3, 0, sizeof(struct xfs_da3_node_hdr));
ichdr.magic = XFS_DA3_NODE_MAGIC;
- hdr3->info.blkno = cpu_to_be64(bp->b_bn);
+ hdr3->info.blkno = cpu_to_be64(xfs_buf_daddr(bp));
hdr3->info.owner = cpu_to_be64(args->dp->i_ino);
uuid_copy(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid);
} else {
@@ -711,7 +711,7 @@ xfs_da3_root_split(
oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
struct xfs_da3_intnode *node3 = (struct xfs_da3_intnode *)node;
- node3->hdr.info.blkno = cpu_to_be64(bp->b_bn);
+ node3->hdr.info.blkno = cpu_to_be64(xfs_buf_daddr(bp));
}
xfs_trans_log_buf(tp, bp, 0, size - 1);
@@ -1219,7 +1219,7 @@ xfs_da3_root_join(
xfs_trans_buf_copy_type(root_blk->bp, bp);
if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) {
struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr;
- da3->blkno = cpu_to_be64(root_blk->bp->b_bn);
+ da3->blkno = cpu_to_be64(xfs_buf_daddr(root_blk->bp));
}
xfs_trans_log_buf(args->trans, root_blk->bp, 0,
args->geo->blksize - 1);
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h
index b876b44c0204..5a49caa5c9df 100644
--- a/fs/xfs/libxfs/xfs_da_format.h
+++ b/fs/xfs/libxfs/xfs_da_format.h
@@ -789,7 +789,7 @@ struct xfs_attr3_rmt_hdr {
#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc)
#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \
- ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
+ ((bufsize) - (xfs_has_crc((mp)) ? \
sizeof(struct xfs_attr3_rmt_hdr) : 0))
/* Number of bytes in a directory block. */
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index 050bdcc4fe73..50546eadaae2 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -115,7 +115,7 @@ xfs_da_mount(
dageo->fsblog = mp->m_sb.sb_blocklog;
dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr);
dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr);
dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr);
@@ -730,7 +730,7 @@ xfs_dir2_hashname(
struct xfs_mount *mp,
struct xfs_name *name)
{
- if (unlikely(xfs_sb_version_hasasciici(&mp->m_sb)))
+ if (unlikely(xfs_has_asciici(mp)))
return xfs_ascii_ci_hashname(name);
return xfs_da_hashname(name->name, name->len);
}
@@ -741,7 +741,7 @@ xfs_dir2_compname(
const unsigned char *name,
int len)
{
- if (unlikely(xfs_sb_version_hasasciici(&args->dp->i_mount->m_sb)))
+ if (unlikely(xfs_has_asciici(args->dp->i_mount)))
return xfs_ascii_ci_compname(args, name, len);
return xfs_da_compname(args, name, len);
}
diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
index 75e1421f69c4..df0869bba275 100644
--- a/fs/xfs/libxfs/xfs_dir2_block.c
+++ b/fs/xfs/libxfs/xfs_dir2_block.c
@@ -53,10 +53,10 @@ xfs_dir3_block_verify(
if (!xfs_verify_magic(bp, hdr3->magic))
return __this_address;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
- if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
+ if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))
return __this_address;
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
return __this_address;
@@ -71,7 +71,7 @@ xfs_dir3_block_read_verify(
struct xfs_mount *mp = bp->b_mount;
xfs_failaddr_t fa;
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ if (xfs_has_crc(mp) &&
!xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
xfs_verifier_error(bp, -EFSBADCRC, __this_address);
else {
@@ -96,7 +96,7 @@ xfs_dir3_block_write_verify(
return;
}
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (bip)
@@ -121,7 +121,7 @@ xfs_dir3_block_header_check(
{
struct xfs_mount *mp = dp->i_mount;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
if (be64_to_cpu(hdr3->owner) != dp->i_ino)
@@ -171,10 +171,10 @@ xfs_dir3_block_init(
bp->b_ops = &xfs_dir3_block_buf_ops;
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_BLOCK_BUF);
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
memset(hdr3, 0, sizeof(*hdr3));
hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
- hdr3->blkno = cpu_to_be64(bp->b_bn);
+ hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
hdr3->owner = cpu_to_be64(dp->i_ino);
uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
return;
diff --git a/fs/xfs/libxfs/xfs_dir2_data.c b/fs/xfs/libxfs/xfs_dir2_data.c
index e67fa086f2c1..dbcf58979a59 100644
--- a/fs/xfs/libxfs/xfs_dir2_data.c
+++ b/fs/xfs/libxfs/xfs_dir2_data.c
@@ -29,7 +29,7 @@ xfs_dir2_data_bestfree_p(
struct xfs_mount *mp,
struct xfs_dir2_data_hdr *hdr)
{
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
return ((struct xfs_dir3_data_hdr *)hdr)->best_free;
return hdr->bestfree;
}
@@ -51,7 +51,7 @@ xfs_dir2_data_get_ftype(
struct xfs_mount *mp,
struct xfs_dir2_data_entry *dep)
{
- if (xfs_sb_version_hasftype(&mp->m_sb)) {
+ if (xfs_has_ftype(mp)) {
uint8_t ftype = dep->name[dep->namelen];
if (likely(ftype < XFS_DIR3_FT_MAX))
@@ -70,7 +70,7 @@ xfs_dir2_data_put_ftype(
ASSERT(ftype < XFS_DIR3_FT_MAX);
ASSERT(dep->namelen != 0);
- if (xfs_sb_version_hasftype(&mp->m_sb))
+ if (xfs_has_ftype(mp))
dep->name[dep->namelen] = ftype;
}
@@ -297,10 +297,10 @@ xfs_dir3_data_verify(
if (!xfs_verify_magic(bp, hdr3->magic))
return __this_address;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
- if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
+ if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))
return __this_address;
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
return __this_address;
@@ -343,7 +343,7 @@ xfs_dir3_data_read_verify(
struct xfs_mount *mp = bp->b_mount;
xfs_failaddr_t fa;
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ if (xfs_has_crc(mp) &&
!xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
xfs_verifier_error(bp, -EFSBADCRC, __this_address);
else {
@@ -368,7 +368,7 @@ xfs_dir3_data_write_verify(
return;
}
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (bip)
@@ -401,7 +401,7 @@ xfs_dir3_data_header_check(
{
struct xfs_mount *mp = dp->i_mount;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_data_hdr *hdr3 = bp->b_addr;
if (be64_to_cpu(hdr3->hdr.owner) != dp->i_ino)
@@ -717,12 +717,12 @@ xfs_dir3_data_init(
* Initialize the header.
*/
hdr = bp->b_addr;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
memset(hdr3, 0, sizeof(*hdr3));
hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
- hdr3->blkno = cpu_to_be64(bp->b_bn);
+ hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
hdr3->owner = cpu_to_be64(dp->i_ino);
uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c
index 5369d8bb2593..d9b66306a9a7 100644
--- a/fs/xfs/libxfs/xfs_dir2_leaf.c
+++ b/fs/xfs/libxfs/xfs_dir2_leaf.c
@@ -37,7 +37,7 @@ xfs_dir2_leaf_hdr_from_disk(
struct xfs_dir3_icleaf_hdr *to,
struct xfs_dir2_leaf *from)
{
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_leaf *from3 = (struct xfs_dir3_leaf *)from;
to->forw = be32_to_cpu(from3->hdr.info.hdr.forw);
@@ -68,7 +68,7 @@ xfs_dir2_leaf_hdr_to_disk(
struct xfs_dir2_leaf *to,
struct xfs_dir3_icleaf_hdr *from)
{
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_leaf *to3 = (struct xfs_dir3_leaf *)to;
ASSERT(from->magic == XFS_DIR3_LEAF1_MAGIC ||
@@ -108,7 +108,7 @@ xfs_dir3_leaf1_check(
if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) {
struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
- if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn)
+ if (be64_to_cpu(leaf3->info.blkno) != xfs_buf_daddr(bp))
return __this_address;
} else if (leafhdr.magic != XFS_DIR2_LEAF1_MAGIC)
return __this_address;
@@ -209,7 +209,7 @@ xfs_dir3_leaf_read_verify(
struct xfs_mount *mp = bp->b_mount;
xfs_failaddr_t fa;
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ if (xfs_has_crc(mp) &&
!xfs_buf_verify_cksum(bp, XFS_DIR3_LEAF_CRC_OFF))
xfs_verifier_error(bp, -EFSBADCRC, __this_address);
else {
@@ -234,7 +234,7 @@ xfs_dir3_leaf_write_verify(
return;
}
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (bip)
@@ -308,7 +308,7 @@ xfs_dir3_leaf_init(
ASSERT(type == XFS_DIR2_LEAF1_MAGIC || type == XFS_DIR2_LEAFN_MAGIC);
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
memset(leaf3, 0, sizeof(*leaf3));
@@ -316,7 +316,7 @@ xfs_dir3_leaf_init(
leaf3->info.hdr.magic = (type == XFS_DIR2_LEAF1_MAGIC)
? cpu_to_be16(XFS_DIR3_LEAF1_MAGIC)
: cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
- leaf3->info.blkno = cpu_to_be64(bp->b_bn);
+ leaf3->info.blkno = cpu_to_be64(xfs_buf_daddr(bp));
leaf3->info.owner = cpu_to_be64(owner);
uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid);
} else {
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
index d0520afb913a..7a03aeb9f4c9 100644
--- a/fs/xfs/libxfs/xfs_dir2_node.c
+++ b/fs/xfs/libxfs/xfs_dir2_node.c
@@ -68,7 +68,7 @@ xfs_dir3_leafn_check(
if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) {
struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
- if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn)
+ if (be64_to_cpu(leaf3->info.blkno) != xfs_buf_daddr(bp))
return __this_address;
} else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC)
return __this_address;
@@ -105,12 +105,12 @@ xfs_dir3_free_verify(
if (!xfs_verify_magic(bp, hdr->magic))
return __this_address;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
- if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
+ if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))
return __this_address;
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
return __this_address;
@@ -128,7 +128,7 @@ xfs_dir3_free_read_verify(
struct xfs_mount *mp = bp->b_mount;
xfs_failaddr_t fa;
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ if (xfs_has_crc(mp) &&
!xfs_buf_verify_cksum(bp, XFS_DIR3_FREE_CRC_OFF))
xfs_verifier_error(bp, -EFSBADCRC, __this_address);
else {
@@ -153,7 +153,7 @@ xfs_dir3_free_write_verify(
return;
}
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (bip)
@@ -185,7 +185,7 @@ xfs_dir3_free_header_check(
firstdb = (xfs_dir2_da_to_db(mp->m_dir_geo, fbno) -
xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) *
maxbests;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
if (be32_to_cpu(hdr3->firstdb) != firstdb)
@@ -247,7 +247,7 @@ xfs_dir2_free_hdr_from_disk(
struct xfs_dir3_icfree_hdr *to,
struct xfs_dir2_free *from)
{
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_free *from3 = (struct xfs_dir3_free *)from;
to->magic = be32_to_cpu(from3->hdr.hdr.magic);
@@ -274,7 +274,7 @@ xfs_dir2_free_hdr_to_disk(
struct xfs_dir2_free *to,
struct xfs_dir3_icfree_hdr *from)
{
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_free *to3 = (struct xfs_dir3_free *)to;
ASSERT(from->magic == XFS_DIR3_FREE_MAGIC);
@@ -341,12 +341,12 @@ xfs_dir3_free_get_buf(
memset(bp->b_addr, 0, sizeof(struct xfs_dir3_free_hdr));
memset(&hdr, 0, sizeof(hdr));
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
hdr.magic = XFS_DIR3_FREE_MAGIC;
- hdr3->hdr.blkno = cpu_to_be64(bp->b_bn);
+ hdr3->hdr.blkno = cpu_to_be64(xfs_buf_daddr(bp));
hdr3->hdr.owner = cpu_to_be64(dp->i_ino);
uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid);
} else
diff --git a/fs/xfs/libxfs/xfs_dir2_priv.h b/fs/xfs/libxfs/xfs_dir2_priv.h
index 94943ce49cab..711709a2aa53 100644
--- a/fs/xfs/libxfs/xfs_dir2_priv.h
+++ b/fs/xfs/libxfs/xfs_dir2_priv.h
@@ -196,7 +196,7 @@ xfs_dir2_data_entsize(
len = offsetof(struct xfs_dir2_data_entry, name[0]) + namelen +
sizeof(xfs_dir2_data_off_t) /* tag */;
- if (xfs_sb_version_hasftype(&mp->m_sb))
+ if (xfs_has_ftype(mp))
len += sizeof(uint8_t);
return round_up(len, XFS_DIR2_DATA_ALIGN);
}
diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
index 46d18bf9d5e1..5a97a87eaa20 100644
--- a/fs/xfs/libxfs/xfs_dir2_sf.c
+++ b/fs/xfs/libxfs/xfs_dir2_sf.c
@@ -48,7 +48,7 @@ xfs_dir2_sf_entsize(
count += sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */
count += hdr->i8count ? XFS_INO64_SIZE : XFS_INO32_SIZE; /* ino # */
- if (xfs_sb_version_hasftype(&mp->m_sb))
+ if (xfs_has_ftype(mp))
count += sizeof(uint8_t);
return count;
}
@@ -76,7 +76,7 @@ xfs_dir2_sf_get_ino(
{
uint8_t *from = sfep->name + sfep->namelen;
- if (xfs_sb_version_hasftype(&mp->m_sb))
+ if (xfs_has_ftype(mp))
from++;
if (!hdr->i8count)
@@ -95,7 +95,7 @@ xfs_dir2_sf_put_ino(
ASSERT(ino <= XFS_MAXINUMBER);
- if (xfs_sb_version_hasftype(&mp->m_sb))
+ if (xfs_has_ftype(mp))
to++;
if (hdr->i8count)
@@ -135,7 +135,7 @@ xfs_dir2_sf_get_ftype(
struct xfs_mount *mp,
struct xfs_dir2_sf_entry *sfep)
{
- if (xfs_sb_version_hasftype(&mp->m_sb)) {
+ if (xfs_has_ftype(mp)) {
uint8_t ftype = sfep->name[sfep->namelen];
if (ftype < XFS_DIR3_FT_MAX)
@@ -153,7 +153,7 @@ xfs_dir2_sf_put_ftype(
{
ASSERT(ftype < XFS_DIR3_FT_MAX);
- if (xfs_sb_version_hasftype(&mp->m_sb))
+ if (xfs_has_ftype(mp))
sfep->name[sfep->namelen] = ftype;
}
@@ -192,7 +192,7 @@ xfs_dir2_block_sfsize(
* if there is a filetype field, add the extra byte to the namelen
* for each entry that we see.
*/
- has_ftype = xfs_sb_version_hasftype(&mp->m_sb) ? 1 : 0;
+ has_ftype = xfs_has_ftype(mp) ? 1 : 0;
count = i8count = namelen = 0;
btp = xfs_dir2_block_tail_p(geo, hdr);
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c
index 6766417d5ba4..deeb74becabc 100644
--- a/fs/xfs/libxfs/xfs_dquot_buf.c
+++ b/fs/xfs/libxfs/xfs_dquot_buf.c
@@ -70,7 +70,7 @@ xfs_dquot_verify(
return __this_address;
if ((ddq->d_type & XFS_DQTYPE_BIGTIME) &&
- !xfs_sb_version_hasbigtime(&mp->m_sb))
+ !xfs_has_bigtime(mp))
return __this_address;
if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && !ddq->d_id)
@@ -106,7 +106,7 @@ xfs_dqblk_verify(
struct xfs_dqblk *dqb,
xfs_dqid_t id) /* used only during quotacheck */
{
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ if (xfs_has_crc(mp) &&
!uuid_equal(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
@@ -134,7 +134,7 @@ xfs_dqblk_repair(
dqb->dd_diskdq.d_type = type;
dqb->dd_diskdq.d_id = cpu_to_be32(id);
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
uuid_copy(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid);
xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
XFS_DQUOT_CRC_OFF);
@@ -151,7 +151,7 @@ xfs_dquot_buf_verify_crc(
int ndquots;
int i;
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return true;
/*
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 76e2461b9e66..2d7057b7984b 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -9,7 +9,7 @@
/*
* XFS On Disk Format Definitions
*
- * This header file defines all the on-disk format definitions for
+ * This header file defines all the on-disk format definitions for
* general XFS objects. Directory and attribute related objects are defined in
* xfs_da_format.h, which log and log item formats are defined in
* xfs_log_format.h. Everything else goes here.
@@ -265,7 +265,6 @@ typedef struct xfs_dsb {
/* must be padded to 64 bit alignment */
} xfs_dsb_t;
-
/*
* Misc. Flags - warning - these will be cleared by xfs_repair unless
* a feature bit is set when the flag is used.
@@ -280,37 +279,9 @@ typedef struct xfs_dsb {
#define XFS_SB_VERSION_NUM(sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS)
-/*
- * The first XFS version we support is a v4 superblock with V2 directories.
- */
-static inline bool xfs_sb_good_v4_features(struct xfs_sb *sbp)
-{
- if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT))
- return false;
- if (!(sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT))
- return false;
-
- /* check for unknown features in the fs */
- if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKBITS) ||
- ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) &&
- (sbp->sb_features2 & ~XFS_SB_VERSION2_OKBITS)))
- return false;
-
- return true;
-}
-
-static inline bool xfs_sb_good_version(struct xfs_sb *sbp)
+static inline bool xfs_sb_is_v5(struct xfs_sb *sbp)
{
- if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5)
- return true;
- if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4)
- return xfs_sb_good_v4_features(sbp);
- return false;
-}
-
-static inline bool xfs_sb_version_hasrealtime(struct xfs_sb *sbp)
-{
- return sbp->sb_rblocks > 0;
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
}
/*
@@ -322,9 +293,10 @@ static inline bool xfs_sb_has_mismatched_features2(struct xfs_sb *sbp)
return sbp->sb_bad_features2 != sbp->sb_features2;
}
-static inline bool xfs_sb_version_hasattr(struct xfs_sb *sbp)
+static inline bool xfs_sb_version_hasmorebits(struct xfs_sb *sbp)
{
- return (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT);
+ return xfs_sb_is_v5(sbp) ||
+ (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT);
}
static inline void xfs_sb_version_addattr(struct xfs_sb *sbp)
@@ -332,87 +304,18 @@ static inline void xfs_sb_version_addattr(struct xfs_sb *sbp)
sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
}
-static inline bool xfs_sb_version_hasquota(struct xfs_sb *sbp)
-{
- return (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT);
-}
-
static inline void xfs_sb_version_addquota(struct xfs_sb *sbp)
{
sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT;
}
-static inline bool xfs_sb_version_hasalign(struct xfs_sb *sbp)
-{
- return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 ||
- (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT));
-}
-
-static inline bool xfs_sb_version_hasdalign(struct xfs_sb *sbp)
-{
- return (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT);
-}
-
-static inline bool xfs_sb_version_haslogv2(struct xfs_sb *sbp)
-{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 ||
- (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT);
-}
-
-static inline bool xfs_sb_version_hassector(struct xfs_sb *sbp)
-{
- return (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT);
-}
-
-static inline bool xfs_sb_version_hasasciici(struct xfs_sb *sbp)
-{
- return (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT);
-}
-
-static inline bool xfs_sb_version_hasmorebits(struct xfs_sb *sbp)
-{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 ||
- (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT);
-}
-
-/*
- * sb_features2 bit version macros.
- */
-static inline bool xfs_sb_version_haslazysbcount(struct xfs_sb *sbp)
-{
- return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
- (xfs_sb_version_hasmorebits(sbp) &&
- (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT));
-}
-
-static inline bool xfs_sb_version_hasattr2(struct xfs_sb *sbp)
-{
- return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
- (xfs_sb_version_hasmorebits(sbp) &&
- (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT));
-}
-
static inline void xfs_sb_version_addattr2(struct xfs_sb *sbp)
{
sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;
}
-static inline void xfs_sb_version_removeattr2(struct xfs_sb *sbp)
-{
- sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;
- if (!sbp->sb_features2)
- sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
-}
-
-static inline bool xfs_sb_version_hasprojid32bit(struct xfs_sb *sbp)
-{
- return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
- (xfs_sb_version_hasmorebits(sbp) &&
- (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT));
-}
-
-static inline void xfs_sb_version_addprojid32bit(struct xfs_sb *sbp)
+static inline void xfs_sb_version_addprojid32(struct xfs_sb *sbp)
{
sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT;
@@ -495,106 +398,21 @@ xfs_sb_has_incompat_log_feature(
return (sbp->sb_features_log_incompat & feature) != 0;
}
-/*
- * V5 superblock specific feature checks
- */
-static inline bool xfs_sb_version_hascrc(struct xfs_sb *sbp)
-{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
-}
-
-/*
- * v5 file systems support V3 inodes only, earlier file systems support
- * v2 and v1 inodes.
- */
-static inline bool xfs_sb_version_has_v3inode(struct xfs_sb *sbp)
-{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
-}
-
-static inline bool xfs_dinode_good_version(struct xfs_sb *sbp,
- uint8_t version)
-{
- if (xfs_sb_version_has_v3inode(sbp))
- return version == 3;
- return version == 1 || version == 2;
-}
-
-static inline bool xfs_sb_version_has_pquotino(struct xfs_sb *sbp)
-{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
-}
-
-static inline int xfs_sb_version_hasftype(struct xfs_sb *sbp)
-{
- return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
- xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_FTYPE)) ||
- (xfs_sb_version_hasmorebits(sbp) &&
- (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE));
-}
-
-static inline bool xfs_sb_version_hasfinobt(xfs_sb_t *sbp)
-{
- return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) &&
- (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT);
-}
-
-static inline bool xfs_sb_version_hassparseinodes(struct xfs_sb *sbp)
-{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
- xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_SPINODES);
-}
-
-/*
- * XFS_SB_FEAT_INCOMPAT_META_UUID indicates that the metadata UUID
- * is stored separately from the user-visible UUID; this allows the
- * user-visible UUID to be changed on V5 filesystems which have a
- * filesystem UUID stamped into every piece of metadata.
- */
-static inline bool xfs_sb_version_hasmetauuid(struct xfs_sb *sbp)
-{
- return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) &&
- (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID);
-}
-
-static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp)
-{
- return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) &&
- (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT);
-}
-
-static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp)
-{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
- (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK);
-}
-
-static inline bool xfs_sb_version_hasbigtime(struct xfs_sb *sbp)
-{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
- (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_BIGTIME);
-}
-
-/*
- * Inode btree block counter. We record the number of inobt and finobt blocks
- * in the AGI header so that we can skip the finobt walk at mount time when
- * setting up per-AG reservations.
- */
-static inline bool xfs_sb_version_hasinobtcounts(struct xfs_sb *sbp)
+static inline void
+xfs_sb_remove_incompat_log_features(
+ struct xfs_sb *sbp)
{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
- (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT);
+ sbp->sb_features_log_incompat &= ~XFS_SB_FEAT_INCOMPAT_LOG_ALL;
}
-static inline bool xfs_sb_version_needsrepair(struct xfs_sb *sbp)
+static inline void
+xfs_sb_add_incompat_log_features(
+ struct xfs_sb *sbp,
+ unsigned int features)
{
- return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
- (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR);
+ sbp->sb_features_log_incompat |= features;
}
-/*
- * end of superblock version macros
- */
static inline bool
xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
@@ -1062,12 +880,12 @@ enum xfs_dinode_fmt {
/*
* Inode size for given fs.
*/
-#define XFS_DINODE_SIZE(sbp) \
- (xfs_sb_version_has_v3inode(sbp) ? \
+#define XFS_DINODE_SIZE(mp) \
+ (xfs_has_v3inodes(mp) ? \
sizeof(struct xfs_dinode) : \
offsetof(struct xfs_dinode, di_crc))
#define XFS_LITINO(mp) \
- ((mp)->m_sb.sb_inodesize - XFS_DINODE_SIZE(&(mp)->m_sb))
+ ((mp)->m_sb.sb_inodesize - XFS_DINODE_SIZE(mp))
/*
* Inode data & attribute fork sizes, per inode.
@@ -1454,7 +1272,7 @@ struct xfs_dsymlink_hdr {
#define XFS_SYMLINK_MAPS 3
#define XFS_SYMLINK_BUF_SPACE(mp, bufsize) \
- ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
+ ((bufsize) - (xfs_has_crc((mp)) ? \
sizeof(struct xfs_dsymlink_hdr) : 0))
@@ -1686,7 +1504,7 @@ struct xfs_rmap_key {
typedef __be32 xfs_rmap_ptr_t;
#define XFS_RMAP_BLOCK(mp) \
- (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \
+ (xfs_has_finobt(((mp))) ? \
XFS_FIBT_BLOCK(mp) + 1 : \
XFS_IBT_BLOCK(mp) + 1)
@@ -1918,7 +1736,7 @@ struct xfs_acl {
* limited only by the maximum size of the xattr that stores the information.
*/
#define XFS_ACL_MAX_ENTRIES(mp) \
- (xfs_sb_version_hascrc(&mp->m_sb) \
+ (xfs_has_crc(mp) \
? (XFS_XATTR_SIZE_MAX - sizeof(struct xfs_acl)) / \
sizeof(struct xfs_acl_entry) \
: 25)
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index aaf8805a82df..994ad783d407 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -58,7 +58,7 @@ xfs_inobt_update(
union xfs_btree_rec rec;
rec.inobt.ir_startino = cpu_to_be32(irec->ir_startino);
- if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) {
+ if (xfs_has_sparseinodes(cur->bc_mp)) {
rec.inobt.ir_u.sp.ir_holemask = cpu_to_be16(irec->ir_holemask);
rec.inobt.ir_u.sp.ir_count = irec->ir_count;
rec.inobt.ir_u.sp.ir_freecount = irec->ir_freecount;
@@ -74,11 +74,11 @@ xfs_inobt_update(
void
xfs_inobt_btrec_to_irec(
struct xfs_mount *mp,
- union xfs_btree_rec *rec,
+ const union xfs_btree_rec *rec,
struct xfs_inobt_rec_incore *irec)
{
irec->ir_startino = be32_to_cpu(rec->inobt.ir_startino);
- if (xfs_sb_version_hassparseinodes(&mp->m_sb)) {
+ if (xfs_has_sparseinodes(mp)) {
irec->ir_holemask = be16_to_cpu(rec->inobt.ir_u.sp.ir_holemask);
irec->ir_count = rec->inobt.ir_u.sp.ir_count;
irec->ir_freecount = rec->inobt.ir_u.sp.ir_freecount;
@@ -241,7 +241,7 @@ xfs_check_agi_freecount(
}
} while (i == 1);
- if (!XFS_FORCED_SHUTDOWN(cur->bc_mp))
+ if (!xfs_is_shutdown(cur->bc_mp))
ASSERT(freecount == cur->bc_ag.pag->pagi_freecount);
}
return 0;
@@ -302,7 +302,7 @@ xfs_ialloc_inode_init(
* That means for v3 inode we log the entire buffer rather than just the
* inode cores.
*/
- if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (xfs_has_v3inodes(mp)) {
version = 3;
ino = XFS_AGINO_TO_INO(mp, agno, XFS_AGB_TO_AGINO(mp, agbno));
@@ -337,7 +337,6 @@ xfs_ialloc_inode_init(
xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length));
for (i = 0; i < M_IGEO(mp)->inodes_per_cluster; i++) {
int ioffset = i << mp->m_sb.sb_inodelog;
- uint isize = XFS_DINODE_SIZE(&mp->m_sb);
free = xfs_make_iptr(mp, fbuf, i);
free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
@@ -354,7 +353,7 @@ xfs_ialloc_inode_init(
} else if (tp) {
/* just log the inode core */
xfs_trans_log_buf(tp, fbuf, ioffset,
- ioffset + isize - 1);
+ ioffset + XFS_DINODE_SIZE(mp) - 1);
}
}
@@ -635,7 +634,7 @@ xfs_ialloc_ag_alloc(
#ifdef DEBUG
/* randomly do sparse inode allocations */
- if (xfs_sb_version_hassparseinodes(&tp->t_mountp->m_sb) &&
+ if (xfs_has_sparseinodes(tp->t_mountp) &&
igeo->ialloc_min_blks < igeo->ialloc_blks)
do_sparse = prandom_u32() & 1;
#endif
@@ -712,7 +711,7 @@ xfs_ialloc_ag_alloc(
*/
isaligned = 0;
if (igeo->ialloc_align) {
- ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
+ ASSERT(!xfs_has_noalign(args.mp));
args.alignment = args.mp->m_dalign;
isaligned = 1;
} else
@@ -754,7 +753,7 @@ xfs_ialloc_ag_alloc(
* Finally, try a sparse allocation if the filesystem supports it and
* the sparse allocation length is smaller than a full chunk.
*/
- if (xfs_sb_version_hassparseinodes(&args.mp->m_sb) &&
+ if (xfs_has_sparseinodes(args.mp) &&
igeo->ialloc_min_blks < igeo->ialloc_blks &&
args.fsbno == NULLFSBLOCK) {
sparse_alloc:
@@ -856,7 +855,7 @@ sparse_alloc:
* from the previous call. Set merge false to replace any
* existing record with this one.
*/
- if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) {
+ if (xfs_has_finobt(args.mp)) {
error = xfs_inobt_insert_sprec(args.mp, tp, agbp, pag,
XFS_BTNUM_FINO, &rec, false);
if (error)
@@ -869,7 +868,7 @@ sparse_alloc:
if (error)
return error;
- if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) {
+ if (xfs_has_finobt(args.mp)) {
error = xfs_inobt_insert(args.mp, tp, agbp, pag, newino,
newlen, XFS_BTNUM_FINO);
if (error)
@@ -1448,7 +1447,7 @@ xfs_dialloc_ag(
int offset;
int i;
- if (!xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (!xfs_has_finobt(mp))
return xfs_dialloc_ag_inobt(tp, agbp, pag, parent, inop);
/*
@@ -1784,7 +1783,7 @@ xfs_dialloc(
break;
}
- if (XFS_FORCED_SHUTDOWN(mp)) {
+ if (xfs_is_shutdown(mp)) {
error = -EFSCORRUPTED;
break;
}
@@ -1953,8 +1952,7 @@ xfs_difree_inobt(
* remove the chunk if the block size is large enough for multiple inode
* chunks (that might not be free).
*/
- if (!(mp->m_flags & XFS_MOUNT_IKEEP) &&
- rec.ir_free == XFS_INOBT_ALL_FREE &&
+ if (!xfs_has_ikeep(mp) && rec.ir_free == XFS_INOBT_ALL_FREE &&
mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK) {
struct xfs_perag *pag = agbp->b_pag;
@@ -1994,7 +1992,7 @@ xfs_difree_inobt(
goto error0;
}
- /*
+ /*
* Change the inode free counts and log the ag/sb changes.
*/
be32_add_cpu(&agi->agi_freecount, 1);
@@ -2098,9 +2096,8 @@ xfs_difree_finobt(
* enough for multiple chunks. Leave the finobt record to remain in sync
* with the inobt.
*/
- if (rec.ir_free == XFS_INOBT_ALL_FREE &&
- mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK &&
- !(mp->m_flags & XFS_MOUNT_IKEEP)) {
+ if (!xfs_has_ikeep(mp) && rec.ir_free == XFS_INOBT_ALL_FREE &&
+ mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK) {
error = xfs_btree_delete(cur, &i);
if (error)
goto error;
@@ -2189,7 +2186,7 @@ xfs_difree(
/*
* Fix up the free inode btree.
*/
- if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
+ if (xfs_has_finobt(mp)) {
error = xfs_difree_finobt(mp, tp, agbp, pag, agino, &rec);
if (error)
goto error0;
@@ -2478,7 +2475,7 @@ xfs_agi_verify(
struct xfs_agi *agi = bp->b_addr;
int i;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
if (!xfs_log_check_lsn(mp, be64_to_cpu(agi->agi_lsn)))
@@ -2497,7 +2494,7 @@ xfs_agi_verify(
be32_to_cpu(agi->agi_level) > M_IGEO(mp)->inobt_maxlevels)
return __this_address;
- if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
+ if (xfs_has_finobt(mp) &&
(be32_to_cpu(agi->agi_free_level) < 1 ||
be32_to_cpu(agi->agi_free_level) > M_IGEO(mp)->inobt_maxlevels))
return __this_address;
@@ -2528,7 +2525,7 @@ xfs_agi_read_verify(
struct xfs_mount *mp = bp->b_mount;
xfs_failaddr_t fa;
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ if (xfs_has_crc(mp) &&
!xfs_buf_verify_cksum(bp, XFS_AGI_CRC_OFF))
xfs_verifier_error(bp, -EFSBADCRC, __this_address);
else {
@@ -2553,7 +2550,7 @@ xfs_agi_write_verify(
return;
}
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (bip)
@@ -2626,7 +2623,7 @@ xfs_ialloc_read_agi(
* we are in the middle of a forced shutdown.
*/
ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) ||
- XFS_FORCED_SHUTDOWN(mp));
+ xfs_is_shutdown(mp));
return 0;
}
@@ -2716,7 +2713,7 @@ struct xfs_ialloc_count_inodes {
STATIC int
xfs_ialloc_count_inodes_rec(
struct xfs_btree_cur *cur,
- union xfs_btree_rec *rec,
+ const union xfs_btree_rec *rec,
void *priv)
{
struct xfs_inobt_rec_incore irec;
@@ -2773,7 +2770,7 @@ xfs_ialloc_setup_geometry(
uint inodes;
igeo->new_diflags2 = 0;
- if (xfs_sb_version_hasbigtime(&mp->m_sb))
+ if (xfs_has_bigtime(mp))
igeo->new_diflags2 |= XFS_DIFLAG2_BIGTIME;
/* Compute inode btree geometry. */
@@ -2828,7 +2825,7 @@ xfs_ialloc_setup_geometry(
* cannot change the behavior.
*/
igeo->inode_cluster_size_raw = XFS_INODE_BIG_CLUSTER_SIZE;
- if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (xfs_has_v3inodes(mp)) {
int new_size = igeo->inode_cluster_size_raw;
new_size *= mp->m_sb.sb_inodesize / XFS_DINODE_MIN_SIZE;
@@ -2846,7 +2843,7 @@ xfs_ialloc_setup_geometry(
igeo->inodes_per_cluster = XFS_FSB_TO_INO(mp, igeo->blocks_per_cluster);
/* Calculate inode cluster alignment. */
- if (xfs_sb_version_hasalign(&mp->m_sb) &&
+ if (xfs_has_align(mp) &&
mp->m_sb.sb_inoalignmt >= igeo->blocks_per_cluster)
igeo->cluster_align = mp->m_sb.sb_inoalignmt;
else
@@ -2894,15 +2891,15 @@ xfs_ialloc_calc_rootino(
first_bno += xfs_alloc_min_freelist(mp, NULL);
/* ...the free inode btree root... */
- if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (xfs_has_finobt(mp))
first_bno++;
/* ...the reverse mapping btree root... */
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (xfs_has_rmapbt(mp))
first_bno++;
/* ...the reference count btree... */
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
first_bno++;
/*
@@ -2920,9 +2917,9 @@ xfs_ialloc_calc_rootino(
* Now round first_bno up to whatever allocation alignment is given
* by the filesystem or was passed in.
*/
- if (xfs_sb_version_hasdalign(&mp->m_sb) && igeo->ialloc_align > 0)
+ if (xfs_has_dalign(mp) && igeo->ialloc_align > 0)
first_bno = roundup(first_bno, sunit);
- else if (xfs_sb_version_hasalign(&mp->m_sb) &&
+ else if (xfs_has_align(mp) &&
mp->m_sb.sb_inoalignmt > 1)
first_bno = roundup(first_bno, mp->m_sb.sb_inoalignmt);
@@ -2953,7 +2950,7 @@ xfs_ialloc_check_shrink(
int has;
int error;
- if (!xfs_sb_version_hassparseinodes(&mp->m_sb))
+ if (!xfs_has_sparseinodes(mp))
return 0;
pag = xfs_perag_get(mp, agno);
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h
index 9a2112b4ad5e..8b5c2b709022 100644
--- a/fs/xfs/libxfs/xfs_ialloc.h
+++ b/fs/xfs/libxfs/xfs_ialloc.h
@@ -106,7 +106,8 @@ int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_buf **bpp);
union xfs_btree_rec;
-void xfs_inobt_btrec_to_irec(struct xfs_mount *mp, union xfs_btree_rec *rec,
+void xfs_inobt_btrec_to_irec(struct xfs_mount *mp,
+ const union xfs_btree_rec *rec,
struct xfs_inobt_rec_incore *irec);
int xfs_ialloc_has_inodes_at_extent(struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_extlen_t len, bool *exists);
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index 823a038939f8..27190840c5d8 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -40,9 +40,9 @@ xfs_inobt_dup_cursor(
STATIC void
xfs_inobt_set_root(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *nptr,
- int inc) /* level change */
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *nptr,
+ int inc) /* level change */
{
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agi *agi = agbp->b_addr;
@@ -54,9 +54,9 @@ xfs_inobt_set_root(
STATIC void
xfs_finobt_set_root(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *nptr,
- int inc) /* level change */
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *nptr,
+ int inc) /* level change */
{
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agi *agi = agbp->b_addr;
@@ -76,7 +76,7 @@ xfs_inobt_mod_blockcount(
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agi *agi = agbp->b_addr;
- if (!xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb))
+ if (!xfs_has_inobtcounts(cur->bc_mp))
return;
if (cur->bc_btnum == XFS_BTNUM_FINO)
@@ -88,11 +88,11 @@ xfs_inobt_mod_blockcount(
STATIC int
__xfs_inobt_alloc_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start,
- union xfs_btree_ptr *new,
- int *stat,
- enum xfs_ag_resv_type resv)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *start,
+ union xfs_btree_ptr *new,
+ int *stat,
+ enum xfs_ag_resv_type resv)
{
xfs_alloc_arg_t args; /* block allocation args */
int error; /* error return value */
@@ -127,20 +127,20 @@ __xfs_inobt_alloc_block(
STATIC int
xfs_inobt_alloc_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start,
- union xfs_btree_ptr *new,
- int *stat)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *start,
+ union xfs_btree_ptr *new,
+ int *stat)
{
return __xfs_inobt_alloc_block(cur, start, new, stat, XFS_AG_RESV_NONE);
}
STATIC int
xfs_finobt_alloc_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start,
- union xfs_btree_ptr *new,
- int *stat)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *start,
+ union xfs_btree_ptr *new,
+ int *stat)
{
if (cur->bc_mp->m_finobt_nores)
return xfs_inobt_alloc_block(cur, start, new, stat);
@@ -156,7 +156,7 @@ __xfs_inobt_free_block(
{
xfs_inobt_mod_blockcount(cur, -1);
return xfs_free_extent(cur->bc_tp,
- XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1,
+ XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp)), 1,
&XFS_RMAP_OINFO_INOBT, resv);
}
@@ -188,18 +188,18 @@ xfs_inobt_get_maxrecs(
STATIC void
xfs_inobt_init_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
key->inobt.ir_startino = rec->inobt.ir_startino;
}
STATIC void
xfs_inobt_init_high_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
- __u32 x;
+ __u32 x;
x = be32_to_cpu(rec->inobt.ir_startino);
x += XFS_INODES_PER_CHUNK - 1;
@@ -212,7 +212,7 @@ xfs_inobt_init_rec_from_cur(
union xfs_btree_rec *rec)
{
rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino);
- if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) {
+ if (xfs_has_sparseinodes(cur->bc_mp)) {
rec->inobt.ir_u.sp.ir_holemask =
cpu_to_be16(cur->bc_rec.i.ir_holemask);
rec->inobt.ir_u.sp.ir_count = cur->bc_rec.i.ir_count;
@@ -253,8 +253,8 @@ xfs_finobt_init_ptr_from_cur(
STATIC int64_t
xfs_inobt_key_diff(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *key)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key)
{
return (int64_t)be32_to_cpu(key->inobt.ir_startino) -
cur->bc_rec.i.ir_startino;
@@ -262,9 +262,9 @@ xfs_inobt_key_diff(
STATIC int64_t
xfs_inobt_diff_two_keys(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
return (int64_t)be32_to_cpu(k1->inobt.ir_startino) -
be32_to_cpu(k2->inobt.ir_startino);
@@ -292,7 +292,7 @@ xfs_inobt_verify(
* but beware of the landmine (i.e. need to check pag->pagi_init) if we
* ever do.
*/
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
fa = xfs_btree_sblock_v5hdr_verify(bp);
if (fa)
return fa;
@@ -360,9 +360,9 @@ const struct xfs_buf_ops xfs_finobt_buf_ops = {
STATIC int
xfs_inobt_keys_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
return be32_to_cpu(k1->inobt.ir_startino) <
be32_to_cpu(k2->inobt.ir_startino);
@@ -370,9 +370,9 @@ xfs_inobt_keys_inorder(
STATIC int
xfs_inobt_recs_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *r1,
- union xfs_btree_rec *r2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *r1,
+ const union xfs_btree_rec *r2)
{
return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <=
be32_to_cpu(r2->inobt.ir_startino);
@@ -446,7 +446,7 @@ xfs_inobt_init_common(
cur->bc_blocklog = mp->m_sb.sb_blocklog;
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
/* take a reference for the cursor */
@@ -511,7 +511,7 @@ xfs_inobt_commit_staged_btree(
fields = XFS_AGI_ROOT | XFS_AGI_LEVEL;
agi->agi_root = cpu_to_be32(afake->af_root);
agi->agi_level = cpu_to_be32(afake->af_levels);
- if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) {
+ if (xfs_has_inobtcounts(cur->bc_mp)) {
agi->agi_iblocks = cpu_to_be32(afake->af_blocks);
fields |= XFS_AGI_IBLOCKS;
}
@@ -521,7 +521,7 @@ xfs_inobt_commit_staged_btree(
fields = XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL;
agi->agi_free_root = cpu_to_be32(afake->af_root);
agi->agi_free_level = cpu_to_be32(afake->af_levels);
- if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) {
+ if (xfs_has_inobtcounts(cur->bc_mp)) {
agi->agi_fblocks = cpu_to_be32(afake->af_blocks);
fields |= XFS_AGI_IBLOCKS;
}
@@ -737,10 +737,10 @@ xfs_finobt_calc_reserves(
xfs_extlen_t tree_len = 0;
int error;
- if (!xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (!xfs_has_finobt(mp))
return 0;
- if (xfs_sb_version_hasinobtcounts(&mp->m_sb))
+ if (xfs_has_inobtcounts(mp))
error = xfs_finobt_read_blocks(mp, tp, pag, &tree_len);
else
error = xfs_inobt_count_blocks(mp, tp, pag, XFS_BTNUM_FINO,
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.h b/fs/xfs/libxfs/xfs_ialloc_btree.h
index e530c82b2217..8a322d402e61 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.h
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.h
@@ -19,7 +19,7 @@ struct xfs_perag;
* Btree block header size depends on a superblock flag.
*/
#define XFS_INOBT_BLOCK_LEN(mp) \
- (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+ (xfs_has_crc(((mp))) ? \
XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN)
/*
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 84ea2e0af9f0..3932b4ebf903 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -48,7 +48,7 @@ xfs_inode_buf_verify(
/*
* Validate the magic number and version of every inode in the buffer
*/
- agno = xfs_daddr_to_agno(mp, XFS_BUF_ADDR(bp));
+ agno = xfs_daddr_to_agno(mp, xfs_buf_daddr(bp));
ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock;
for (i = 0; i < ni; i++) {
int di_ok;
@@ -58,7 +58,7 @@ xfs_inode_buf_verify(
dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
unlinked_ino = be32_to_cpu(dip->di_next_unlinked);
di_ok = xfs_verify_magic16(bp, dip->di_magic) &&
- xfs_dinode_good_version(&mp->m_sb, dip->di_version) &&
+ xfs_dinode_good_version(mp, dip->di_version) &&
xfs_verify_agino_or_null(mp, agno, unlinked_ino);
if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
XFS_ERRTAG_ITOBP_INOTOBP))) {
@@ -71,7 +71,7 @@ xfs_inode_buf_verify(
#ifdef DEBUG
xfs_alert(mp,
"bad inode magic/vsn daddr %lld #%d (magic=%x)",
- (unsigned long long)bp->b_bn, i,
+ (unsigned long long)xfs_buf_daddr(bp), i,
be16_to_cpu(dip->di_magic));
#endif
xfs_buf_verifier_error(bp, -EFSCORRUPTED,
@@ -192,7 +192,7 @@ xfs_inode_from_disk(
* inode. If the inode is unused, mode is zero and we shouldn't mess
* with the uninitialized part of it.
*/
- if (!xfs_sb_version_has_v3inode(&ip->i_mount->m_sb))
+ if (!xfs_has_v3inodes(ip->i_mount))
ip->i_flushiter = be16_to_cpu(from->di_flushiter);
inode->i_generation = be32_to_cpu(from->di_gen);
inode->i_mode = be16_to_cpu(from->di_mode);
@@ -235,7 +235,7 @@ xfs_inode_from_disk(
if (from->di_dmevmask || from->di_dmstate)
xfs_iflags_set(ip, XFS_IPRESERVE_DM_FIELDS);
- if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
+ if (xfs_has_v3inodes(ip->i_mount)) {
inode_set_iversion_queried(inode,
be64_to_cpu(from->di_changecount));
ip->i_crtime = xfs_inode_from_disk_ts(from, from->di_crtime);
@@ -313,7 +313,7 @@ xfs_inode_to_disk(
to->di_aformat = xfs_ifork_format(ip->i_afp);
to->di_flags = cpu_to_be16(ip->i_diflags);
- if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
+ if (xfs_has_v3inodes(ip->i_mount)) {
to->di_version = 3;
to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
to->di_crtime = xfs_inode_to_disk_ts(ip, ip->i_crtime);
@@ -413,7 +413,7 @@ xfs_dinode_verify(
/* Verify v3 integrity information first */
if (dip->di_version >= 3) {
- if (!xfs_sb_version_has_v3inode(&mp->m_sb))
+ if (!xfs_has_v3inodes(mp))
return __this_address;
if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
XFS_DINODE_CRC_OFF))
@@ -515,7 +515,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_has_reflink(mp))
return __this_address;
/* only regular files get reflink */
@@ -534,7 +534,7 @@ xfs_dinode_verify(
/* bigtime iflag can only happen on bigtime filesystems */
if (xfs_dinode_has_bigtime(dip) &&
- !xfs_sb_version_hasbigtime(&mp->m_sb))
+ !xfs_has_bigtime(mp))
return __this_address;
return NULL;
@@ -550,7 +550,7 @@ xfs_dinode_calc_crc(
if (dip->di_version < 3)
return;
- ASSERT(xfs_sb_version_hascrc(&mp->m_sb));
+ ASSERT(xfs_has_crc(mp));
crc = xfs_start_cksum_update((char *)dip, mp->m_sb.sb_inodesize,
XFS_DINODE_CRC_OFF);
dip->di_crc = xfs_end_cksum(crc);
@@ -677,7 +677,7 @@ xfs_inode_validate_cowextsize(
hint_flag = (flags2 & XFS_DIFLAG2_COWEXTSIZE);
cowextsize_bytes = XFS_FSB_TO_B(mp, cowextsize);
- if (hint_flag && !xfs_sb_version_hasreflink(&mp->m_sb))
+ if (hint_flag && !xfs_has_reflink(mp))
return __this_address;
if (hint_flag && !(S_ISDIR(mode) || S_ISREG(mode)))
diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
index 7f865bb4df84..585ed5a110af 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.h
+++ b/fs/xfs/libxfs/xfs_inode_buf.h
@@ -21,7 +21,7 @@ struct xfs_imap {
int xfs_imap_to_bp(struct xfs_mount *mp, struct xfs_trans *tp,
struct xfs_imap *imap, struct xfs_buf **bpp);
-void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *);
+void xfs_dinode_calc_crc(struct xfs_mount *mp, struct xfs_dinode *dip);
void xfs_inode_to_disk(struct xfs_inode *ip, struct xfs_dinode *to,
xfs_lsn_t lsn);
int xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from);
@@ -42,4 +42,13 @@ static inline uint64_t xfs_inode_encode_bigtime(struct timespec64 tv)
struct timespec64 xfs_inode_from_disk_ts(struct xfs_dinode *dip,
const xfs_timestamp_t ts);
+static inline bool
+xfs_dinode_good_version(struct xfs_mount *mp, uint8_t version)
+{
+ if (xfs_has_v3inodes(mp))
+ return version == 3;
+ return version == 1 || version == 2;
+}
+
+
#endif /* __XFS_INODE_BUF_H__ */
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
index 2c5bcbc19264..b322db523d65 100644
--- a/fs/xfs/libxfs/xfs_log_format.h
+++ b/fs/xfs/libxfs/xfs_log_format.h
@@ -41,10 +41,10 @@ typedef uint32_t xlog_tid_t;
#define XFS_MIN_LOG_FACTOR 3
#define XLOG_REC_SHIFT(log) \
- BTOBB(1 << (xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? \
+ BTOBB(1 << (xfs_has_logv2(log->l_mp) ? \
XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
#define XLOG_TOTAL_REC_SHIFT(log) \
- BTOBB(XLOG_MAX_ICLOGS << (xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? \
+ BTOBB(XLOG_MAX_ICLOGS << (xfs_has_logv2(log->l_mp) ? \
XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
/* get lsn fields */
@@ -434,7 +434,7 @@ struct xfs_log_dinode {
};
#define xfs_log_dinode_size(mp) \
- (xfs_sb_version_has_v3inode(&(mp)->m_sb) ? \
+ (xfs_has_v3inodes((mp)) ? \
sizeof(struct xfs_log_dinode) : \
offsetof(struct xfs_log_dinode, di_next_unlinked))
diff --git a/fs/xfs/libxfs/xfs_log_recover.h b/fs/xfs/libxfs/xfs_log_recover.h
index 3cca2bfe714c..ff69a0000817 100644
--- a/fs/xfs/libxfs/xfs_log_recover.h
+++ b/fs/xfs/libxfs/xfs_log_recover.h
@@ -122,6 +122,8 @@ void xlog_buf_readahead(struct xlog *log, xfs_daddr_t blkno, uint len,
const struct xfs_buf_ops *ops);
bool xlog_is_buffer_cancelled(struct xlog *log, xfs_daddr_t blkno, uint len);
+int xlog_recover_iget(struct xfs_mount *mp, xfs_ino_t ino,
+ struct xfs_inode **ipp);
void xlog_recover_release_intent(struct xlog *log, unsigned short intent_type,
uint64_t intent_id);
diff --git a/fs/xfs/libxfs/xfs_log_rlimit.c b/fs/xfs/libxfs/xfs_log_rlimit.c
index 7f55eb3f3653..67798ff5e14e 100644
--- a/fs/xfs/libxfs/xfs_log_rlimit.c
+++ b/fs/xfs/libxfs/xfs_log_rlimit.c
@@ -92,7 +92,7 @@ xfs_log_calc_minimum_size(
if (tres.tr_logcount > 1)
max_logres *= tres.tr_logcount;
- if (xfs_sb_version_haslogv2(&mp->m_sb) && mp->m_sb.sb_logsunit > 1)
+ if (xfs_has_logv2(mp) && mp->m_sb.sb_logsunit > 1)
lsunit = BTOBB(mp->m_sb.sb_logsunit);
/*
diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h
index 0f0af4e35032..a02c5062f9b2 100644
--- a/fs/xfs/libxfs/xfs_quota_defs.h
+++ b/fs/xfs/libxfs/xfs_quota_defs.h
@@ -60,37 +60,15 @@ typedef uint8_t xfs_dqtype_t;
#define XFS_DQUOT_LOGRES(mp) \
((sizeof(struct xfs_dq_logformat) + sizeof(struct xfs_disk_dquot)) * 6)
-#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
-#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
-#define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
-#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
+#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
+#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
+#define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
+#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
#define XFS_IS_UQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_UQUOTA_ENFD)
#define XFS_IS_GQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_GQUOTA_ENFD)
#define XFS_IS_PQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_PQUOTA_ENFD)
/*
- * Incore only flags for quotaoff - these bits get cleared when quota(s)
- * are in the process of getting turned off. These flags are in m_qflags but
- * never in sb_qflags.
- */
-#define XFS_UQUOTA_ACTIVE 0x1000 /* uquotas are being turned off */
-#define XFS_GQUOTA_ACTIVE 0x2000 /* gquotas are being turned off */
-#define XFS_PQUOTA_ACTIVE 0x4000 /* pquotas are being turned off */
-#define XFS_ALL_QUOTA_ACTIVE \
- (XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
-
-/*
- * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
- * quota will be not be switched off as long as that inode lock is held.
- */
-#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
- XFS_GQUOTA_ACTIVE | \
- XFS_PQUOTA_ACTIVE))
-#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
-#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
-#define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
-
-/*
* Flags to tell various functions what to do. Not all of these are meaningful
* to a single function. None of these XFS_QMOPT_* flags are meant to have
* persistent values (ie. their values can and will change between versions)
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index 860a0c9801ba..e5d767a7fc5d 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -91,7 +91,7 @@ xfs_refcount_lookup_eq(
/* Convert on-disk record to in-core format. */
void
xfs_refcount_btrec_to_irec(
- union xfs_btree_rec *rec,
+ const union xfs_btree_rec *rec,
struct xfs_refcount_irec *irec)
{
irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock);
@@ -1253,7 +1253,7 @@ xfs_refcount_increase_extent(
struct xfs_trans *tp,
struct xfs_bmbt_irec *PREV)
{
- if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb))
+ if (!xfs_has_reflink(tp->t_mountp))
return;
__xfs_refcount_add(tp, XFS_REFCOUNT_INCREASE, PREV->br_startblock,
@@ -1268,7 +1268,7 @@ xfs_refcount_decrease_extent(
struct xfs_trans *tp,
struct xfs_bmbt_irec *PREV)
{
- if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb))
+ if (!xfs_has_reflink(tp->t_mountp))
return;
__xfs_refcount_add(tp, XFS_REFCOUNT_DECREASE, PREV->br_startblock,
@@ -1617,7 +1617,7 @@ xfs_refcount_alloc_cow_extent(
{
struct xfs_mount *mp = tp->t_mountp;
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return;
__xfs_refcount_add(tp, XFS_REFCOUNT_ALLOC_COW, fsb, len);
@@ -1636,7 +1636,7 @@ xfs_refcount_free_cow_extent(
{
struct xfs_mount *mp = tp->t_mountp;
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return;
/* Remove rmap entry */
@@ -1654,7 +1654,7 @@ struct xfs_refcount_recovery {
STATIC int
xfs_refcount_recover_extent(
struct xfs_btree_cur *cur,
- union xfs_btree_rec *rec,
+ const union xfs_btree_rec *rec,
void *priv)
{
struct list_head *debris = priv;
diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
index 9f6e9aae4da0..02cb3aa405be 100644
--- a/fs/xfs/libxfs/xfs_refcount.h
+++ b/fs/xfs/libxfs/xfs_refcount.h
@@ -78,7 +78,7 @@ static inline xfs_fileoff_t xfs_refcount_max_unmap(int log_res)
extern int xfs_refcount_has_record(struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_extlen_t len, bool *exists);
union xfs_btree_rec;
-extern void xfs_refcount_btrec_to_irec(union xfs_btree_rec *rec,
+extern void xfs_refcount_btrec_to_irec(const union xfs_btree_rec *rec,
struct xfs_refcount_irec *irec);
extern int xfs_refcount_insert(struct xfs_btree_cur *cur,
struct xfs_refcount_irec *irec, int *stat);
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c
index 92d336c17e83..1ef9b99962ab 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.c
+++ b/fs/xfs/libxfs/xfs_refcount_btree.c
@@ -31,9 +31,9 @@ xfs_refcountbt_dup_cursor(
STATIC void
xfs_refcountbt_set_root(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr,
- int inc)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr,
+ int inc)
{
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agf *agf = agbp->b_addr;
@@ -51,10 +51,10 @@ xfs_refcountbt_set_root(
STATIC int
xfs_refcountbt_alloc_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start,
- union xfs_btree_ptr *new,
- int *stat)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *start,
+ union xfs_btree_ptr *new,
+ int *stat)
{
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agf *agf = agbp->b_addr;
@@ -102,7 +102,7 @@ xfs_refcountbt_free_block(
struct xfs_mount *mp = cur->bc_mp;
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agf *agf = agbp->b_addr;
- xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
+ xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
int error;
trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_ag.pag->pag_agno,
@@ -135,18 +135,18 @@ xfs_refcountbt_get_maxrecs(
STATIC void
xfs_refcountbt_init_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
key->refc.rc_startblock = rec->refc.rc_startblock;
}
STATIC void
xfs_refcountbt_init_high_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
- __u32 x;
+ __u32 x;
x = be32_to_cpu(rec->refc.rc_startblock);
x += be32_to_cpu(rec->refc.rc_blockcount) - 1;
@@ -177,20 +177,20 @@ xfs_refcountbt_init_ptr_from_cur(
STATIC int64_t
xfs_refcountbt_key_diff(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *key)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key)
{
struct xfs_refcount_irec *rec = &cur->bc_rec.rc;
- struct xfs_refcount_key *kp = &key->refc;
+ const struct xfs_refcount_key *kp = &key->refc;
return (int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock;
}
STATIC int64_t
xfs_refcountbt_diff_two_keys(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
return (int64_t)be32_to_cpu(k1->refc.rc_startblock) -
be32_to_cpu(k2->refc.rc_startblock);
@@ -209,7 +209,7 @@ xfs_refcountbt_verify(
if (!xfs_verify_magic(bp, block->bb_magic))
return __this_address;
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return __this_address;
fa = xfs_btree_sblock_v5hdr_verify(bp);
if (fa)
@@ -269,9 +269,9 @@ const struct xfs_buf_ops xfs_refcountbt_buf_ops = {
STATIC int
xfs_refcountbt_keys_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
return be32_to_cpu(k1->refc.rc_startblock) <
be32_to_cpu(k2->refc.rc_startblock);
@@ -279,9 +279,9 @@ xfs_refcountbt_keys_inorder(
STATIC int
xfs_refcountbt_recs_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *r1,
- union xfs_btree_rec *r2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *r1,
+ const union xfs_btree_rec *r2)
{
return be32_to_cpu(r1->refc.rc_startblock) +
be32_to_cpu(r1->refc.rc_blockcount) <=
@@ -462,7 +462,7 @@ xfs_refcountbt_calc_reserves(
xfs_extlen_t tree_len;
int error;
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return 0;
error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp);
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index d1dfad0204e3..f45929b1b94a 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -179,8 +179,8 @@ done:
/* Convert an internal btree record to an rmap record. */
int
xfs_rmap_btrec_to_irec(
- union xfs_btree_rec *rec,
- struct xfs_rmap_irec *irec)
+ const union xfs_btree_rec *rec,
+ struct xfs_rmap_irec *irec)
{
irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
@@ -255,9 +255,9 @@ struct xfs_find_left_neighbor_info {
/* For each rmap given, figure out if it matches the key we want. */
STATIC int
xfs_rmap_find_left_neighbor_helper(
- struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
- void *priv)
+ struct xfs_btree_cur *cur,
+ const struct xfs_rmap_irec *rec,
+ void *priv)
{
struct xfs_find_left_neighbor_info *info = priv;
@@ -331,9 +331,9 @@ xfs_rmap_find_left_neighbor(
/* For each rmap given, figure out if it matches the key we want. */
STATIC int
xfs_rmap_lookup_le_range_helper(
- struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
- void *priv)
+ struct xfs_btree_cur *cur,
+ const struct xfs_rmap_irec *rec,
+ void *priv)
{
struct xfs_find_left_neighbor_info *info = priv;
@@ -705,7 +705,7 @@ xfs_rmap_free(
struct xfs_btree_cur *cur;
int error;
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return 0;
cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
@@ -959,7 +959,7 @@ xfs_rmap_alloc(
struct xfs_btree_cur *cur;
int error;
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return 0;
cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
@@ -2278,9 +2278,9 @@ struct xfs_rmap_query_range_info {
/* Format btree record and pass to our callback. */
STATIC int
xfs_rmap_query_range_helper(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *rec,
- void *priv)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *rec,
+ void *priv)
{
struct xfs_rmap_query_range_info *query = priv;
struct xfs_rmap_irec irec;
@@ -2296,8 +2296,8 @@ xfs_rmap_query_range_helper(
int
xfs_rmap_query_range(
struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *low_rec,
- struct xfs_rmap_irec *high_rec,
+ const struct xfs_rmap_irec *low_rec,
+ const struct xfs_rmap_irec *high_rec,
xfs_rmap_query_range_fn fn,
void *priv)
{
@@ -2459,7 +2459,7 @@ xfs_rmap_update_is_needed(
struct xfs_mount *mp,
int whichfork)
{
- return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
+ return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
}
/*
@@ -2707,7 +2707,7 @@ struct xfs_rmap_key_state {
STATIC int
xfs_rmap_has_other_keys_helper(
struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
void *priv)
{
struct xfs_rmap_key_state *rks = priv;
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index f2423cf7f1e2..fd67904ed446 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -134,12 +134,13 @@ int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec,
int *stat);
typedef int (*xfs_rmap_query_range_fn)(
- struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
- void *priv);
+ struct xfs_btree_cur *cur,
+ const struct xfs_rmap_irec *rec,
+ void *priv);
int xfs_rmap_query_range(struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec,
+ const struct xfs_rmap_irec *low_rec,
+ const struct xfs_rmap_irec *high_rec,
xfs_rmap_query_range_fn fn, void *priv);
int xfs_rmap_query_all(struct xfs_btree_cur *cur, xfs_rmap_query_range_fn fn,
void *priv);
@@ -192,7 +193,7 @@ int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_agblock_t bno,
int xfs_rmap_compare(const struct xfs_rmap_irec *a,
const struct xfs_rmap_irec *b);
union xfs_btree_rec;
-int xfs_rmap_btrec_to_irec(union xfs_btree_rec *rec,
+int xfs_rmap_btrec_to_irec(const union xfs_btree_rec *rec,
struct xfs_rmap_irec *irec);
int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, bool *exists);
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
index f29bc71b9950..b7dbbfb3aeed 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -57,9 +57,9 @@ xfs_rmapbt_dup_cursor(
STATIC void
xfs_rmapbt_set_root(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr,
- int inc)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *ptr,
+ int inc)
{
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agf *agf = agbp->b_addr;
@@ -76,10 +76,10 @@ xfs_rmapbt_set_root(
STATIC int
xfs_rmapbt_alloc_block(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *start,
- union xfs_btree_ptr *new,
- int *stat)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_ptr *start,
+ union xfs_btree_ptr *new,
+ int *stat)
{
struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agf *agf = agbp->b_addr;
@@ -122,7 +122,7 @@ xfs_rmapbt_free_block(
xfs_agblock_t bno;
int error;
- bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp));
+ bno = xfs_daddr_to_agbno(cur->bc_mp, xfs_buf_daddr(bp));
trace_xfs_rmapbt_free_block(cur->bc_mp, pag->pag_agno,
bno, 1);
be32_add_cpu(&agf->agf_rmap_blocks, -1);
@@ -156,8 +156,8 @@ xfs_rmapbt_get_maxrecs(
STATIC void
xfs_rmapbt_init_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
key->rmap.rm_startblock = rec->rmap.rm_startblock;
key->rmap.rm_owner = rec->rmap.rm_owner;
@@ -173,11 +173,11 @@ xfs_rmapbt_init_key_from_rec(
*/
STATIC void
xfs_rmapbt_init_high_key_from_rec(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
+ union xfs_btree_key *key,
+ const union xfs_btree_rec *rec)
{
- uint64_t off;
- int adj;
+ uint64_t off;
+ int adj;
adj = be32_to_cpu(rec->rmap.rm_blockcount) - 1;
@@ -219,13 +219,13 @@ xfs_rmapbt_init_ptr_from_cur(
STATIC int64_t
xfs_rmapbt_key_diff(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *key)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key)
{
- struct xfs_rmap_irec *rec = &cur->bc_rec.r;
- struct xfs_rmap_key *kp = &key->rmap;
- __u64 x, y;
- int64_t d;
+ struct xfs_rmap_irec *rec = &cur->bc_rec.r;
+ const struct xfs_rmap_key *kp = &key->rmap;
+ __u64 x, y;
+ int64_t d;
d = (int64_t)be32_to_cpu(kp->rm_startblock) - rec->rm_startblock;
if (d)
@@ -249,14 +249,14 @@ xfs_rmapbt_key_diff(
STATIC int64_t
xfs_rmapbt_diff_two_keys(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
- struct xfs_rmap_key *kp1 = &k1->rmap;
- struct xfs_rmap_key *kp2 = &k2->rmap;
- int64_t d;
- __u64 x, y;
+ const struct xfs_rmap_key *kp1 = &k1->rmap;
+ const struct xfs_rmap_key *kp2 = &k2->rmap;
+ int64_t d;
+ __u64 x, y;
d = (int64_t)be32_to_cpu(kp1->rm_startblock) -
be32_to_cpu(kp2->rm_startblock);
@@ -304,7 +304,7 @@ xfs_rmapbt_verify(
if (!xfs_verify_magic(bp, block->bb_magic))
return __this_address;
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return __this_address;
fa = xfs_btree_sblock_v5hdr_verify(bp);
if (fa)
@@ -364,9 +364,9 @@ const struct xfs_buf_ops xfs_rmapbt_buf_ops = {
STATIC int
xfs_rmapbt_keys_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_key *k1,
- union xfs_btree_key *k2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1,
+ const union xfs_btree_key *k2)
{
uint32_t x;
uint32_t y;
@@ -394,9 +394,9 @@ xfs_rmapbt_keys_inorder(
STATIC int
xfs_rmapbt_recs_inorder(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *r1,
- union xfs_btree_rec *r2)
+ struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *r1,
+ const union xfs_btree_rec *r2)
{
uint32_t x;
uint32_t y;
@@ -558,7 +558,7 @@ xfs_rmapbt_compute_maxlevels(
* disallow reflinking when less than 10% of the per-AG metadata
* block reservation since the fallback is a regular file copy.
*/
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
mp->m_rmap_maxlevels = XFS_BTREE_MAXLEVELS;
else
mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(
@@ -606,7 +606,7 @@ xfs_rmapbt_calc_reserves(
xfs_extlen_t tree_len;
int error;
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return 0;
error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp);
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h
index 88d8d18788a2..f2eee6572af4 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rmap_btree.h
@@ -59,4 +59,4 @@ extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp,
extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, struct xfs_trans *tp,
struct xfs_perag *pag, xfs_extlen_t *ask, xfs_extlen_t *used);
-#endif /* __XFS_RMAP_BTREE_H__ */
+#endif /* __XFS_RMAP_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c
index 483375c6a735..5740ba664867 100644
--- a/fs/xfs/libxfs/xfs_rtbitmap.c
+++ b/fs/xfs/libxfs/xfs_rtbitmap.c
@@ -1009,8 +1009,8 @@ xfs_rtfree_extent(
int
xfs_rtalloc_query_range(
struct xfs_trans *tp,
- struct xfs_rtalloc_rec *low_rec,
- struct xfs_rtalloc_rec *high_rec,
+ const struct xfs_rtalloc_rec *low_rec,
+ const struct xfs_rtalloc_rec *high_rec,
xfs_rtalloc_query_range_fn fn,
void *priv)
{
@@ -1018,6 +1018,7 @@ xfs_rtalloc_query_range(
struct xfs_mount *mp = tp->t_mountp;
xfs_rtblock_t rtstart;
xfs_rtblock_t rtend;
+ xfs_rtblock_t high_key;
int is_free;
int error = 0;
@@ -1026,12 +1027,12 @@ xfs_rtalloc_query_range(
if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
low_rec->ar_startext == high_rec->ar_startext)
return 0;
- high_rec->ar_startext = min(high_rec->ar_startext,
- mp->m_sb.sb_rextents - 1);
+
+ high_key = min(high_rec->ar_startext, mp->m_sb.sb_rextents - 1);
/* Iterate the bitmap, looking for discrepancies. */
rtstart = low_rec->ar_startext;
- while (rtstart <= high_rec->ar_startext) {
+ while (rtstart <= high_key) {
/* Is the first block free? */
error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
&is_free);
@@ -1039,8 +1040,7 @@ xfs_rtalloc_query_range(
break;
/* How long does the extent go for? */
- error = xfs_rtfind_forw(mp, tp, rtstart,
- high_rec->ar_startext, &rtend);
+ error = xfs_rtfind_forw(mp, tp, rtstart, high_key, &rtend);
if (error)
break;
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 04f5386446db..e58349be78bd 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -30,13 +30,110 @@
* Physical superblock buffer manipulations. Shared with libxfs in userspace.
*/
+/*
+ * We support all XFS versions newer than a v4 superblock with V2 directories.
+ */
+bool
+xfs_sb_good_version(
+ struct xfs_sb *sbp)
+{
+ /* all v5 filesystems are supported */
+ if (xfs_sb_is_v5(sbp))
+ return true;
+
+ /* versions prior to v4 are not supported */
+ if (XFS_SB_VERSION_NUM(sbp) < XFS_SB_VERSION_4)
+ return false;
+
+ /* V4 filesystems need v2 directories and unwritten extents */
+ if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT))
+ return false;
+ if (!(sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT))
+ return false;
+
+ /* And must not have any unknown v4 feature bits set */
+ if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKBITS) ||
+ ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) &&
+ (sbp->sb_features2 & ~XFS_SB_VERSION2_OKBITS)))
+ return false;
+
+ /* It's a supported v4 filesystem */
+ return true;
+}
+
+uint64_t
+xfs_sb_version_to_features(
+ struct xfs_sb *sbp)
+{
+ uint64_t features = 0;
+
+ /* optional V4 features */
+ if (sbp->sb_rblocks > 0)
+ features |= XFS_FEAT_REALTIME;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT)
+ features |= XFS_FEAT_ATTR;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT)
+ features |= XFS_FEAT_QUOTA;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT)
+ features |= XFS_FEAT_ALIGN;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT)
+ features |= XFS_FEAT_LOGV2;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT)
+ features |= XFS_FEAT_DALIGN;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT)
+ features |= XFS_FEAT_EXTFLG;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT)
+ features |= XFS_FEAT_SECTOR;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT)
+ features |= XFS_FEAT_ASCIICI;
+ if (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) {
+ if (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT)
+ features |= XFS_FEAT_LAZYSBCOUNT;
+ if (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT)
+ features |= XFS_FEAT_ATTR2;
+ if (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT)
+ features |= XFS_FEAT_PROJID32;
+ if (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE)
+ features |= XFS_FEAT_FTYPE;
+ }
+
+ if (!xfs_sb_is_v5(sbp))
+ return features;
+
+ /* Always on V5 features */
+ features |= XFS_FEAT_ALIGN | XFS_FEAT_LOGV2 | XFS_FEAT_EXTFLG |
+ XFS_FEAT_LAZYSBCOUNT | XFS_FEAT_ATTR2 | XFS_FEAT_PROJID32 |
+ XFS_FEAT_V3INODES | XFS_FEAT_CRC | XFS_FEAT_PQUOTINO;
+
+ /* Optional V5 features */
+ if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT)
+ features |= XFS_FEAT_FINOBT;
+ if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT)
+ features |= XFS_FEAT_RMAPBT;
+ if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK)
+ features |= XFS_FEAT_REFLINK;
+ if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT)
+ features |= XFS_FEAT_INOBTCNT;
+ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_FTYPE)
+ features |= XFS_FEAT_FTYPE;
+ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES)
+ features |= XFS_FEAT_SPINODES;
+ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID)
+ features |= XFS_FEAT_META_UUID;
+ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_BIGTIME)
+ features |= XFS_FEAT_BIGTIME;
+ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR)
+ features |= XFS_FEAT_NEEDSREPAIR;
+ return features;
+}
+
/* Check all the superblock fields we care about when reading one in. */
STATIC int
xfs_validate_sb_read(
struct xfs_mount *mp,
struct xfs_sb *sbp)
{
- if (XFS_SB_VERSION_NUM(sbp) != XFS_SB_VERSION_5)
+ if (!xfs_sb_is_v5(sbp))
return 0;
/*
@@ -56,7 +153,7 @@ xfs_validate_sb_read(
"Superblock has unknown read-only compatible features (0x%x) enabled.",
(sbp->sb_features_ro_compat &
XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
- if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
+ if (!xfs_is_readonly(mp)) {
xfs_warn(mp,
"Attempted to mount read-only compatible filesystem read-write.");
xfs_warn(mp,
@@ -95,7 +192,7 @@ xfs_validate_sb_write(
* secondary superblocks, so allow this usage to continue because
* we never read counters from such superblocks.
*/
- if (XFS_BUF_ADDR(bp) == XFS_SB_DADDR && !sbp->sb_inprogress &&
+ if (xfs_buf_daddr(bp) == XFS_SB_DADDR && !sbp->sb_inprogress &&
(sbp->sb_fdblocks > sbp->sb_dblocks ||
!xfs_verify_icount(mp, sbp->sb_icount) ||
sbp->sb_ifree > sbp->sb_icount)) {
@@ -103,7 +200,7 @@ xfs_validate_sb_write(
return -EFSCORRUPTED;
}
- if (XFS_SB_VERSION_NUM(sbp) != XFS_SB_VERSION_5)
+ if (!xfs_sb_is_v5(sbp))
return 0;
/*
@@ -162,6 +259,7 @@ xfs_validate_sb_common(
struct xfs_dsb *dsb = bp->b_addr;
uint32_t agcount = 0;
uint32_t rem;
+ bool has_dalign;
if (!xfs_verify_magic(bp, dsb->sb_magicnum)) {
xfs_warn(mp, "bad magic number");
@@ -173,12 +271,41 @@ xfs_validate_sb_common(
return -EWRONGFS;
}
- if (xfs_sb_version_has_pquotino(sbp)) {
+ /*
+ * Validate feature flags and state
+ */
+ if (xfs_sb_is_v5(sbp)) {
+ if (sbp->sb_blocksize < XFS_MIN_CRC_BLOCKSIZE) {
+ xfs_notice(mp,
+"Block size (%u bytes) too small for Version 5 superblock (minimum %d bytes)",
+ sbp->sb_blocksize, XFS_MIN_CRC_BLOCKSIZE);
+ return -EFSCORRUPTED;
+ }
+
+ /* V5 has a separate project quota inode */
if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
xfs_notice(mp,
"Version 5 of Super block has XFS_OQUOTA bits.");
return -EFSCORRUPTED;
}
+
+ /*
+ * Full inode chunks must be aligned to inode chunk size when
+ * sparse inodes are enabled to support the sparse chunk
+ * allocation algorithm and prevent overlapping inode records.
+ */
+ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES) {
+ uint32_t align;
+
+ align = XFS_INODES_PER_CHUNK * sbp->sb_inodesize
+ >> sbp->sb_blocklog;
+ if (sbp->sb_inoalignmt != align) {
+ xfs_warn(mp,
+"Inode block alignment (%u) must match chunk size (%u) for sparse inodes.",
+ sbp->sb_inoalignmt, align);
+ return -EINVAL;
+ }
+ }
} else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
xfs_notice(mp,
@@ -186,24 +313,6 @@ xfs_validate_sb_common(
return -EFSCORRUPTED;
}
- /*
- * Full inode chunks must be aligned to inode chunk size when
- * sparse inodes are enabled to support the sparse chunk
- * allocation algorithm and prevent overlapping inode records.
- */
- if (xfs_sb_version_hassparseinodes(sbp)) {
- uint32_t align;
-
- align = XFS_INODES_PER_CHUNK * sbp->sb_inodesize
- >> sbp->sb_blocklog;
- if (sbp->sb_inoalignmt != align) {
- xfs_warn(mp,
-"Inode block alignment (%u) must match chunk size (%u) for sparse inodes.",
- sbp->sb_inoalignmt, align);
- return -EINVAL;
- }
- }
-
if (unlikely(
sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
xfs_warn(mp,
@@ -303,7 +412,8 @@ xfs_validate_sb_common(
* Either (sb_unit and !hasdalign) or (!sb_unit and hasdalign)
* would imply the image is corrupted.
*/
- if (!!sbp->sb_unit ^ xfs_sb_version_hasdalign(sbp)) {
+ has_dalign = sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT;
+ if (!!sbp->sb_unit ^ has_dalign) {
xfs_notice(mp, "SB stripe alignment sanity check failed");
return -EFSCORRUPTED;
}
@@ -312,12 +422,6 @@ xfs_validate_sb_common(
XFS_FSB_TO_B(mp, sbp->sb_width), 0, false))
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");
- return -EFSCORRUPTED;
- }
-
/*
* Currently only very few inode sizes are supported.
*/
@@ -361,7 +465,7 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp)
* We need to do these manipilations only if we are working
* with an older version of on-disk superblock.
*/
- if (xfs_sb_version_has_pquotino(sbp))
+ if (xfs_sb_is_v5(sbp))
return;
if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
@@ -454,7 +558,8 @@ __xfs_sb_from_disk(
* sb_meta_uuid is only on disk if it differs from sb_uuid and the
* feature flag is set; if not set we keep it only in memory.
*/
- if (xfs_sb_version_hasmetauuid(to))
+ if (xfs_sb_is_v5(to) &&
+ (to->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID))
uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid);
else
uuid_copy(&to->sb_meta_uuid, &from->sb_uuid);
@@ -479,7 +584,12 @@ xfs_sb_quota_to_disk(
uint16_t qflags = from->sb_qflags;
to->sb_uquotino = cpu_to_be64(from->sb_uquotino);
- if (xfs_sb_version_has_pquotino(from)) {
+
+ /*
+ * The in-memory superblock quota state matches the v5 on-disk format so
+ * just write them out and return
+ */
+ if (xfs_sb_is_v5(from)) {
to->sb_qflags = cpu_to_be16(from->sb_qflags);
to->sb_gquotino = cpu_to_be64(from->sb_gquotino);
to->sb_pquotino = cpu_to_be64(from->sb_pquotino);
@@ -487,9 +597,9 @@ xfs_sb_quota_to_disk(
}
/*
- * The in-core version of sb_qflags do not have XFS_OQUOTA_*
- * flags, whereas the on-disk version does. So, convert incore
- * XFS_{PG}QUOTA_* flags to on-disk XFS_OQUOTA_* flags.
+ * For older superblocks (v4), the in-core version of sb_qflags do not
+ * have XFS_OQUOTA_* flags, whereas the on-disk version does. So,
+ * convert incore XFS_{PG}QUOTA_* flags to on-disk XFS_OQUOTA_* flags.
*/
qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD |
XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD);
@@ -589,19 +699,20 @@ xfs_sb_to_disk(
to->sb_features2 = cpu_to_be32(from->sb_features2);
to->sb_bad_features2 = cpu_to_be32(from->sb_bad_features2);
- if (xfs_sb_version_hascrc(from)) {
- to->sb_features_compat = cpu_to_be32(from->sb_features_compat);
- to->sb_features_ro_compat =
- cpu_to_be32(from->sb_features_ro_compat);
- to->sb_features_incompat =
- cpu_to_be32(from->sb_features_incompat);
- to->sb_features_log_incompat =
- cpu_to_be32(from->sb_features_log_incompat);
- to->sb_spino_align = cpu_to_be32(from->sb_spino_align);
- to->sb_lsn = cpu_to_be64(from->sb_lsn);
- if (xfs_sb_version_hasmetauuid(from))
- uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid);
- }
+ if (!xfs_sb_is_v5(from))
+ return;
+
+ to->sb_features_compat = cpu_to_be32(from->sb_features_compat);
+ to->sb_features_ro_compat =
+ cpu_to_be32(from->sb_features_ro_compat);
+ to->sb_features_incompat =
+ cpu_to_be32(from->sb_features_incompat);
+ to->sb_features_log_incompat =
+ cpu_to_be32(from->sb_features_log_incompat);
+ to->sb_spino_align = cpu_to_be32(from->sb_spino_align);
+ to->sb_lsn = cpu_to_be64(from->sb_lsn);
+ if (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID)
+ uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid);
}
/*
@@ -636,8 +747,8 @@ xfs_sb_read_verify(
if (!xfs_buf_verify_cksum(bp, XFS_SB_CRC_OFF)) {
/* Only fail bad secondaries on a known V5 filesystem */
- if (bp->b_bn == XFS_SB_DADDR ||
- xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_buf_daddr(bp) == XFS_SB_DADDR ||
+ xfs_has_crc(mp)) {
error = -EFSBADCRC;
goto out_error;
}
@@ -704,7 +815,7 @@ xfs_sb_write_verify(
if (error)
goto out_error;
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_sb_is_v5(&sb))
return;
if (bip)
@@ -801,7 +912,7 @@ xfs_log_sb(
* unclean shutdown, this will be corrected by log recovery rebuilding
* the counters from the AGF block counts.
*/
- if (xfs_sb_version_haslazysbcount(&mp->m_sb)) {
+ if (xfs_has_lazysbcount(mp)) {
mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks);
@@ -950,10 +1061,12 @@ out:
void
xfs_fs_geometry(
- struct xfs_sb *sbp,
+ struct xfs_mount *mp,
struct xfs_fsop_geom *geo,
int struct_version)
{
+ struct xfs_sb *sbp = &mp->m_sb;
+
memset(geo, 0, sizeof(struct xfs_fsop_geom));
geo->blocksize = sbp->sb_blocksize;
@@ -984,51 +1097,51 @@ xfs_fs_geometry(
geo->flags = XFS_FSOP_GEOM_FLAGS_NLINK |
XFS_FSOP_GEOM_FLAGS_DIRV2 |
XFS_FSOP_GEOM_FLAGS_EXTFLG;
- if (xfs_sb_version_hasattr(sbp))
+ if (xfs_has_attr(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_ATTR;
- if (xfs_sb_version_hasquota(sbp))
+ if (xfs_has_quota(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_QUOTA;
- if (xfs_sb_version_hasalign(sbp))
+ if (xfs_has_align(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_IALIGN;
- if (xfs_sb_version_hasdalign(sbp))
+ if (xfs_has_dalign(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_DALIGN;
- if (xfs_sb_version_hassector(sbp))
- geo->flags |= XFS_FSOP_GEOM_FLAGS_SECTOR;
- if (xfs_sb_version_hasasciici(sbp))
+ if (xfs_has_asciici(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_DIRV2CI;
- if (xfs_sb_version_haslazysbcount(sbp))
+ if (xfs_has_lazysbcount(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_LAZYSB;
- if (xfs_sb_version_hasattr2(sbp))
+ if (xfs_has_attr2(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_ATTR2;
- if (xfs_sb_version_hasprojid32bit(sbp))
+ if (xfs_has_projid32(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_PROJID32;
- if (xfs_sb_version_hascrc(sbp))
+ if (xfs_has_crc(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_V5SB;
- if (xfs_sb_version_hasftype(sbp))
+ if (xfs_has_ftype(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_FTYPE;
- if (xfs_sb_version_hasfinobt(sbp))
+ if (xfs_has_finobt(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_FINOBT;
- if (xfs_sb_version_hassparseinodes(sbp))
+ if (xfs_has_sparseinodes(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_SPINODES;
- if (xfs_sb_version_hasrmapbt(sbp))
+ if (xfs_has_rmapbt(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_RMAPBT;
- if (xfs_sb_version_hasreflink(sbp))
+ if (xfs_has_reflink(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_REFLINK;
- if (xfs_sb_version_hasbigtime(sbp))
+ if (xfs_has_bigtime(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_BIGTIME;
- if (xfs_sb_version_hasinobtcounts(sbp))
+ if (xfs_has_inobtcounts(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_INOBTCNT;
- if (xfs_sb_version_hassector(sbp))
+ if (xfs_has_sector(mp)) {
+ geo->flags |= XFS_FSOP_GEOM_FLAGS_SECTOR;
geo->logsectsize = sbp->sb_logsectsize;
- else
+ } else {
geo->logsectsize = BBSIZE;
+ }
geo->rtsectsize = sbp->sb_blocksize;
geo->dirblocksize = xfs_dir2_dirblock_bytes(sbp);
if (struct_version < 4)
return;
- if (xfs_sb_version_haslogv2(sbp))
+ if (xfs_has_logv2(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_LOGV2;
geo->logsunit = sbp->sb_logsunit;
diff --git a/fs/xfs/libxfs/xfs_sb.h b/fs/xfs/libxfs/xfs_sb.h
index 0c1602d9b53d..a5e14740ec9a 100644
--- a/fs/xfs/libxfs/xfs_sb.h
+++ b/fs/xfs/libxfs/xfs_sb.h
@@ -20,11 +20,13 @@ extern void xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp);
extern void xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from);
extern void xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from);
extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp);
+extern bool xfs_sb_good_version(struct xfs_sb *sbp);
+extern uint64_t xfs_sb_version_to_features(struct xfs_sb *sbp);
extern int xfs_update_secondary_sbs(struct xfs_mount *mp);
#define XFS_FS_GEOM_MAX_STRUCT_VER (4)
-extern void xfs_fs_geometry(struct xfs_sb *sbp, struct xfs_fsop_geom *geo,
+extern void xfs_fs_geometry(struct xfs_mount *mp, struct xfs_fsop_geom *geo,
int struct_version);
extern int xfs_sb_read_secondary(struct xfs_mount *mp,
struct xfs_trans *tp, xfs_agnumber_t agno,
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
index 594bc447a7dd..f0b38f4aba80 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.c
+++ b/fs/xfs/libxfs/xfs_symlink_remote.c
@@ -42,7 +42,7 @@ xfs_symlink_hdr_set(
{
struct xfs_dsymlink_hdr *dsl = bp->b_addr;
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return 0;
memset(dsl, 0, sizeof(struct xfs_dsymlink_hdr));
@@ -51,7 +51,7 @@ xfs_symlink_hdr_set(
dsl->sl_bytes = cpu_to_be32(size);
uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid);
dsl->sl_owner = cpu_to_be64(ino);
- dsl->sl_blkno = cpu_to_be64(bp->b_bn);
+ dsl->sl_blkno = cpu_to_be64(xfs_buf_daddr(bp));
bp->b_ops = &xfs_symlink_buf_ops;
return sizeof(struct xfs_dsymlink_hdr);
@@ -89,13 +89,13 @@ xfs_symlink_verify(
struct xfs_mount *mp = bp->b_mount;
struct xfs_dsymlink_hdr *dsl = bp->b_addr;
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return __this_address;
if (!xfs_verify_magic(bp, dsl->sl_magic))
return __this_address;
if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
- if (bp->b_bn != be64_to_cpu(dsl->sl_blkno))
+ if (xfs_buf_daddr(bp) != be64_to_cpu(dsl->sl_blkno))
return __this_address;
if (be32_to_cpu(dsl->sl_offset) +
be32_to_cpu(dsl->sl_bytes) >= XFS_SYMLINK_MAXLEN)
@@ -116,7 +116,7 @@ xfs_symlink_read_verify(
xfs_failaddr_t fa;
/* no verification of non-crc buffers */
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
if (!xfs_buf_verify_cksum(bp, XFS_SYMLINK_CRC_OFF))
@@ -137,7 +137,7 @@ xfs_symlink_write_verify(
xfs_failaddr_t fa;
/* no verification of non-crc buffers */
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
fa = xfs_symlink_verify(bp);
@@ -173,7 +173,7 @@ xfs_symlink_local_to_remote(
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
- if (!xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (!xfs_has_crc(mp)) {
bp->b_ops = NULL;
memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
diff --git a/fs/xfs/libxfs/xfs_trans_inode.c b/fs/xfs/libxfs/xfs_trans_inode.c
index 16f723ebe8dd..8b5547073379 100644
--- a/fs/xfs/libxfs/xfs_trans_inode.c
+++ b/fs/xfs/libxfs/xfs_trans_inode.c
@@ -136,7 +136,7 @@ xfs_trans_log_inode(
* to upgrade this inode to bigtime format, do so now.
*/
if ((flags & (XFS_ILOG_CORE | XFS_ILOG_TIMESTAMP)) &&
- xfs_sb_version_hasbigtime(&ip->i_mount->m_sb) &&
+ xfs_has_bigtime(ip->i_mount) &&
!xfs_inode_has_bigtime(ip)) {
ip->i_diflags2 |= XFS_DIFLAG2_BIGTIME;
flags |= XFS_ILOG_CORE;
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
index d1a0848cb52e..5e300daa2559 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.c
+++ b/fs/xfs/libxfs/xfs_trans_resv.c
@@ -71,9 +71,9 @@ xfs_allocfree_log_count(
uint blocks;
blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1);
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (xfs_has_rmapbt(mp))
blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1);
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
blocks += num_ops * (2 * mp->m_refc_maxlevels - 1);
return blocks;
@@ -155,7 +155,7 @@ STATIC uint
xfs_calc_finobt_res(
struct xfs_mount *mp)
{
- if (!xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (!xfs_has_finobt(mp))
return 0;
return xfs_calc_inobt_res(mp);
@@ -187,7 +187,7 @@ xfs_calc_inode_chunk_res(
XFS_FSB_TO_B(mp, 1));
if (alloc) {
/* icreate tx uses ordered buffers */
- if (xfs_sb_version_has_v3inode(&mp->m_sb))
+ if (xfs_has_v3inodes(mp))
return res;
size = XFS_FSB_TO_B(mp, 1);
}
@@ -268,7 +268,7 @@ xfs_calc_write_reservation(
xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), blksz);
- if (xfs_sb_version_hasrealtime(&mp->m_sb)) {
+ if (xfs_has_realtime(mp)) {
t2 = xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
blksz) +
@@ -317,7 +317,7 @@ xfs_calc_itruncate_reservation(
t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), blksz);
- if (xfs_sb_version_hasrealtime(&mp->m_sb)) {
+ if (xfs_has_realtime(mp)) {
t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
xfs_calc_buf_res(xfs_rtalloc_log_count(mp, 2), blksz) +
xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), blksz);
@@ -799,29 +799,6 @@ xfs_calc_qm_dqalloc_reservation(
}
/*
- * Turning off quotas.
- * the quota off logitems: sizeof(struct xfs_qoff_logitem) * 2
- * the superblock for the quota flags: sector size
- */
-STATIC uint
-xfs_calc_qm_quotaoff_reservation(
- struct xfs_mount *mp)
-{
- return sizeof(struct xfs_qoff_logitem) * 2 +
- xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
-}
-
-/*
- * End of turning off quotas.
- * the quota off logitems: sizeof(struct xfs_qoff_logitem) * 2
- */
-STATIC uint
-xfs_calc_qm_quotaoff_end_reservation(void)
-{
- return sizeof(struct xfs_qoff_logitem) * 2;
-}
-
-/*
* Syncing the incore super block changes to disk.
* the super block to reflect the changes: sector size
*/
@@ -842,14 +819,14 @@ xfs_trans_resv_calc(
* require a permanent reservation on space.
*/
resp->tr_write.tr_logres = xfs_calc_write_reservation(mp);
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
else
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp);
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
resp->tr_itruncate.tr_logcount =
XFS_ITRUNCATE_LOG_COUNT_REFLINK;
else
@@ -910,7 +887,7 @@ xfs_trans_resv_calc(
resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp);
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
else
resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
@@ -923,13 +900,6 @@ xfs_trans_resv_calc(
resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation();
resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT;
- resp->tr_qm_quotaoff.tr_logres = xfs_calc_qm_quotaoff_reservation(mp);
- resp->tr_qm_quotaoff.tr_logcount = XFS_DEFAULT_LOG_COUNT;
-
- resp->tr_qm_equotaoff.tr_logres =
- xfs_calc_qm_quotaoff_end_reservation();
- resp->tr_qm_equotaoff.tr_logcount = XFS_DEFAULT_LOG_COUNT;
-
resp->tr_sb.tr_logres = xfs_calc_sb_reservation(mp);
resp->tr_sb.tr_logcount = XFS_DEFAULT_LOG_COUNT;
diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h
index 7241ab28cf84..fc4e9b369a3a 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.h
+++ b/fs/xfs/libxfs/xfs_trans_resv.h
@@ -46,8 +46,6 @@ struct xfs_trans_resv {
struct xfs_trans_res tr_growrtfree; /* grow realtime freeing */
struct xfs_trans_res tr_qm_setqlim; /* adjust quota limits */
struct xfs_trans_res tr_qm_dqalloc; /* allocate quota on disk */
- struct xfs_trans_res tr_qm_quotaoff; /* turn quota off */
- struct xfs_trans_res tr_qm_equotaoff;/* end of turn quota off */
struct xfs_trans_res tr_sb; /* modify superblock */
struct xfs_trans_res tr_fsyncts; /* update timestamps on fsync */
};
diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
index 7ad3659c5d2a..50332be34388 100644
--- a/fs/xfs/libxfs/xfs_trans_space.h
+++ b/fs/xfs/libxfs/xfs_trans_space.h
@@ -57,8 +57,7 @@
XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK)
#define XFS_IALLOC_SPACE_RES(mp) \
(M_IGEO(mp)->ialloc_blks + \
- ((xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1) * \
- M_IGEO(mp)->inobt_maxlevels))
+ ((xfs_has_finobt(mp) ? 2 : 1) * M_IGEO(mp)->inobt_maxlevels))
/*
* Space reservation values for various transactions.
@@ -94,8 +93,7 @@
#define XFS_SYMLINK_SPACE_RES(mp,nl,b) \
(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b))
#define XFS_IFREE_SPACE_RES(mp) \
- (xfs_sb_version_hasfinobt(&mp->m_sb) ? \
- M_IGEO(mp)->inobt_maxlevels : 0)
+ (xfs_has_finobt(mp) ? M_IGEO(mp)->inobt_maxlevels : 0)
#endif /* __XFS_TRANS_SPACE_H__ */
diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c
index e8f4abee7892..e810d23f2d97 100644
--- a/fs/xfs/libxfs/xfs_types.c
+++ b/fs/xfs/libxfs/xfs_types.c
@@ -169,7 +169,7 @@ xfs_internal_inum(
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_has_quota(mp) &&
xfs_is_quota_inode(&mp->m_sb, ino));
}
diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h
index 0870ef6f933d..b6da06b40989 100644
--- a/fs/xfs/libxfs/xfs_types.h
+++ b/fs/xfs/libxfs/xfs_types.h
@@ -87,6 +87,11 @@ typedef void * xfs_failaddr_t;
#define XFS_ATTR_FORK 1
#define XFS_COW_FORK 2
+#define XFS_WHICHFORK_STRINGS \
+ { XFS_DATA_FORK, "data" }, \
+ { XFS_ATTR_FORK, "attr" }, \
+ { XFS_COW_FORK, "cow" }
+
/*
* Min numbers of data/attr fork btree root pointers.
*/
diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
index be1a7e1e65f7..ae3c9f6e2c69 100644
--- a/fs/xfs/scrub/agheader.c
+++ b/fs/xfs/scrub/agheader.c
@@ -36,7 +36,7 @@ xchk_superblock_xref(
agbno = XFS_SB_BLOCK(mp);
- error = xchk_ag_init(sc, agno, &sc->sa);
+ error = xchk_ag_init_existing(sc, agno, &sc->sa);
if (!xchk_xref_process_error(sc, agno, agbno, &error))
return;
@@ -63,6 +63,7 @@ xchk_superblock(
struct xfs_mount *mp = sc->mp;
struct xfs_buf *bp;
struct xfs_dsb *sb;
+ struct xfs_perag *pag;
xfs_agnumber_t agno;
uint32_t v2_ok;
__be32 features_mask;
@@ -73,6 +74,15 @@ xchk_superblock(
if (agno == 0)
return 0;
+ /*
+ * Grab an active reference to the perag structure. If we can't get
+ * it, we're racing with something that's tearing down the AG, so
+ * signal that the AG no longer exists.
+ */
+ pag = xfs_perag_get(mp, agno);
+ if (!pag)
+ return -ENOENT;
+
error = xfs_sb_read_secondary(mp, sc->tp, agno, &bp);
/*
* The superblock verifier can return several different error codes
@@ -92,7 +102,7 @@ xchk_superblock(
break;
}
if (!xchk_process_error(sc, agno, XFS_SB_BLOCK(mp), &error))
- return error;
+ goto out_pag;
sb = bp->b_addr;
@@ -248,7 +258,7 @@ xchk_superblock(
xchk_block_set_corrupt(sc, bp);
} else {
v2_ok = XFS_SB_VERSION2_OKBITS;
- if (XFS_SB_VERSION_NUM(&mp->m_sb) >= XFS_SB_VERSION_5)
+ if (xfs_sb_is_v5(&mp->m_sb))
v2_ok |= XFS_SB_VERSION2_CRCBIT;
if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok)))
@@ -273,7 +283,7 @@ xchk_superblock(
(cpu_to_be32(mp->m_sb.sb_features2) & features_mask))
xchk_block_set_corrupt(sc, bp);
- if (!xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (!xfs_has_crc(mp)) {
/* all v5 fields must be zero */
if (memchr_inv(&sb->sb_features_compat, 0,
sizeof(struct xfs_dsb) -
@@ -324,7 +334,7 @@ xchk_superblock(
/* Don't care about sb_lsn */
}
- if (xfs_sb_version_hasmetauuid(&mp->m_sb)) {
+ if (xfs_has_metauuid(mp)) {
/* The metadata UUID must be the same for all supers */
if (!uuid_equal(&sb->sb_meta_uuid, &mp->m_sb.sb_meta_uuid))
xchk_block_set_corrupt(sc, bp);
@@ -336,7 +346,8 @@ xchk_superblock(
xchk_block_set_corrupt(sc, bp);
xchk_superblock_xref(sc, bp);
-
+out_pag:
+ xfs_perag_put(pag);
return error;
}
@@ -346,7 +357,7 @@ xchk_superblock(
STATIC int
xchk_agf_record_bno_lengths(
struct xfs_btree_cur *cur,
- struct xfs_alloc_rec_incore *rec,
+ const struct xfs_alloc_rec_incore *rec,
void *priv)
{
xfs_extlen_t *blocks = priv;
@@ -419,7 +430,7 @@ xchk_agf_xref_btreeblks(
int error;
/* agf_btreeblks didn't exist before lazysbcount */
- if (!xfs_sb_version_haslazysbcount(&sc->mp->m_sb))
+ if (!xfs_has_lazysbcount(sc->mp))
return;
/* Check agf_rmap_blocks; set up for agf_btreeblks check */
@@ -438,7 +449,7 @@ xchk_agf_xref_btreeblks(
* No rmap cursor; we can't xref if we have the rmapbt feature.
* We also can't do it if we're missing the free space btree cursors.
*/
- if ((xfs_sb_version_hasrmapbt(&mp->m_sb) && !sc->sa.rmap_cur) ||
+ if ((xfs_has_rmapbt(mp) && !sc->sa.rmap_cur) ||
!sc->sa.bno_cur || !sc->sa.cnt_cur)
return;
@@ -527,6 +538,7 @@ xchk_agf(
xchk_buffer_recheck(sc, sc->sa.agf_bp);
agf = sc->sa.agf_bp->b_addr;
+ pag = sc->sa.pag;
/* Check the AG length */
eoag = be32_to_cpu(agf->agf_length);
@@ -550,7 +562,7 @@ xchk_agf(
if (level <= 0 || level > XFS_BTREE_MAXLEVELS)
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
- if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ if (xfs_has_rmapbt(mp)) {
agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]);
if (!xfs_verify_agbno(mp, agno, agbno))
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
@@ -560,7 +572,7 @@ xchk_agf(
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
}
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ if (xfs_has_reflink(mp)) {
agbno = be32_to_cpu(agf->agf_refcount_root);
if (!xfs_verify_agbno(mp, agno, agbno))
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
@@ -582,15 +594,13 @@ xchk_agf(
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
/* Do the incore counters match? */
- pag = xfs_perag_get(mp, agno);
if (pag->pagf_freeblks != be32_to_cpu(agf->agf_freeblks))
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
if (pag->pagf_flcount != be32_to_cpu(agf->agf_flcount))
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
- if (xfs_sb_version_haslazysbcount(&sc->mp->m_sb) &&
+ if (xfs_has_lazysbcount(sc->mp) &&
pag->pagf_btreeblks != be32_to_cpu(agf->agf_btreeblks))
xchk_block_set_corrupt(sc, sc->sa.agf_bp);
- xfs_perag_put(pag);
xchk_agf_xref(sc);
out:
@@ -630,7 +640,7 @@ xchk_agfl_block(
{
struct xchk_agfl_info *sai = priv;
struct xfs_scrub *sc = sai->sc;
- xfs_agnumber_t agno = sc->sa.agno;
+ xfs_agnumber_t agno = sc->sa.pag->pag_agno;
if (xfs_verify_agbno(mp, agno, agbno) &&
sai->nr_entries < sai->sz_entries)
@@ -787,7 +797,7 @@ xchk_agi_xref_fiblocks(
xfs_agblock_t blocks;
int error = 0;
- if (!xfs_sb_version_hasinobtcounts(&sc->mp->m_sb))
+ if (!xfs_has_inobtcounts(sc->mp))
return;
if (sc->sa.ino_cur) {
@@ -857,6 +867,7 @@ xchk_agi(
xchk_buffer_recheck(sc, sc->sa.agi_bp);
agi = sc->sa.agi_bp->b_addr;
+ pag = sc->sa.pag;
/* Check the AG length */
eoag = be32_to_cpu(agi->agi_length);
@@ -872,7 +883,7 @@ xchk_agi(
if (level <= 0 || level > XFS_BTREE_MAXLEVELS)
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
- if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
+ if (xfs_has_finobt(mp)) {
agbno = be32_to_cpu(agi->agi_free_root);
if (!xfs_verify_agbno(mp, agno, agbno))
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
@@ -909,12 +920,10 @@ xchk_agi(
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
/* Do the incore counters match? */
- pag = xfs_perag_get(mp, agno);
if (pag->pagi_count != be32_to_cpu(agi->agi_count))
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
if (pag->pagi_freecount != be32_to_cpu(agi->agi_freecount))
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
- xfs_perag_put(pag);
xchk_agi_xref(sc);
out:
diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
index e95f8c98f0f7..0f8deee66f15 100644
--- a/fs/xfs/scrub/agheader_repair.c
+++ b/fs/xfs/scrub/agheader_repair.c
@@ -70,7 +70,7 @@ struct xrep_agf_allocbt {
STATIC int
xrep_agf_walk_allocbt(
struct xfs_btree_cur *cur,
- struct xfs_alloc_rec_incore *rec,
+ const struct xfs_alloc_rec_incore *rec,
void *priv)
{
struct xrep_agf_allocbt *raa = priv;
@@ -94,7 +94,7 @@ xrep_agf_check_agfl_block(
{
struct xfs_scrub *sc = priv;
- if (!xfs_verify_agbno(mp, sc->sa.agno, agbno))
+ if (!xfs_verify_agbno(mp, sc->sa.pag->pag_agno, agbno))
return -EFSCORRUPTED;
return 0;
}
@@ -164,7 +164,7 @@ xrep_agf_find_btrees(
return -EFSCORRUPTED;
/* We must find the refcountbt root if that feature is enabled. */
- if (xfs_sb_version_hasreflink(&sc->mp->m_sb) &&
+ if (xfs_has_reflink(sc->mp) &&
!xrep_check_btree_root(sc, &fab[XREP_AGF_REFCOUNTBT]))
return -EFSCORRUPTED;
@@ -188,12 +188,13 @@ xrep_agf_init_header(
memset(agf, 0, BBTOB(agf_bp->b_length));
agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
- agf->agf_seqno = cpu_to_be32(sc->sa.agno);
- agf->agf_length = cpu_to_be32(xfs_ag_block_count(mp, sc->sa.agno));
+ agf->agf_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
+ agf->agf_length = cpu_to_be32(xfs_ag_block_count(mp,
+ sc->sa.pag->pag_agno));
agf->agf_flfirst = old_agf->agf_flfirst;
agf->agf_fllast = old_agf->agf_fllast;
agf->agf_flcount = old_agf->agf_flcount;
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid);
/* Mark the incore AGF data stale until we're done fixing things. */
@@ -223,7 +224,7 @@ xrep_agf_set_roots(
agf->agf_levels[XFS_BTNUM_RMAPi] =
cpu_to_be32(fab[XREP_AGF_RMAPBT].height);
- if (xfs_sb_version_hasreflink(&sc->mp->m_sb)) {
+ if (xfs_has_reflink(sc->mp)) {
agf->agf_refcount_root =
cpu_to_be32(fab[XREP_AGF_REFCOUNTBT].root);
agf->agf_refcount_level =
@@ -280,7 +281,7 @@ xrep_agf_calc_from_btrees(
agf->agf_btreeblks = cpu_to_be32(btreeblks);
/* Update the AGF counters from the refcountbt. */
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ if (xfs_has_reflink(mp)) {
cur = xfs_refcountbt_init_cursor(mp, sc->tp, agf_bp,
sc->sa.pag);
error = xfs_btree_count_blocks(cur, &blocks);
@@ -363,16 +364,16 @@ xrep_agf(
int error;
/* We require the rmapbt to rebuild anything. */
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return -EOPNOTSUPP;
- xchk_perag_get(sc->mp, &sc->sa);
/*
* Make sure we have the AGF buffer, as scrub might have decided it
* was corrupt after xfs_alloc_read_agf failed with -EFSCORRUPTED.
*/
error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
- XFS_AG_DADDR(mp, sc->sa.agno, XFS_AGF_DADDR(mp)),
+ XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
+ XFS_AGF_DADDR(mp)),
XFS_FSS_TO_BB(mp, 1), 0, &agf_bp, NULL);
if (error)
return error;
@@ -388,7 +389,7 @@ xrep_agf(
* btrees rooted in the AGF. If the AGFL contents are obviously bad
* then we'll bail out.
*/
- error = xfs_alloc_read_agfl(mp, sc->tp, sc->sa.agno, &agfl_bp);
+ error = xfs_alloc_read_agfl(mp, sc->tp, sc->sa.pag->pag_agno, &agfl_bp);
if (error)
return error;
@@ -442,7 +443,7 @@ struct xrep_agfl {
STATIC int
xrep_agfl_walk_rmap(
struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
void *priv)
{
struct xrep_agfl *ra = priv;
@@ -586,7 +587,7 @@ xrep_agfl_init_header(
agfl = XFS_BUF_TO_AGFL(agfl_bp);
memset(agfl, 0xFF, BBTOB(agfl_bp->b_length));
agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
- agfl->agfl_seqno = cpu_to_be32(sc->sa.agno);
+ agfl->agfl_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid);
/*
@@ -599,7 +600,8 @@ xrep_agfl_init_header(
for_each_xbitmap_extent(br, n, agfl_extents) {
agbno = XFS_FSB_TO_AGBNO(mp, br->start);
- trace_xrep_agfl_insert(mp, sc->sa.agno, agbno, br->len);
+ trace_xrep_agfl_insert(mp, sc->sa.pag->pag_agno, agbno,
+ br->len);
while (br->len > 0 && fl_off < flcount) {
agfl_bno[fl_off] = cpu_to_be32(agbno);
@@ -638,10 +640,9 @@ xrep_agfl(
int error;
/* We require the rmapbt to rebuild anything. */
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return -EOPNOTSUPP;
- xchk_perag_get(sc->mp, &sc->sa);
xbitmap_init(&agfl_extents);
/*
@@ -649,7 +650,8 @@ xrep_agfl(
* nothing wrong with the AGF, but all the AG header repair functions
* have this chicken-and-egg problem.
*/
- error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.agno, 0, &agf_bp);
+ error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.pag->pag_agno, 0,
+ &agf_bp);
if (error)
return error;
@@ -658,7 +660,8 @@ xrep_agfl(
* was corrupt after xfs_alloc_read_agfl failed with -EFSCORRUPTED.
*/
error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
- XFS_AG_DADDR(mp, sc->sa.agno, XFS_AGFL_DADDR(mp)),
+ XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
+ XFS_AGFL_DADDR(mp)),
XFS_FSS_TO_BB(mp, 1), 0, &agfl_bp, NULL);
if (error)
return error;
@@ -723,7 +726,8 @@ xrep_agi_find_btrees(
int error;
/* Read the AGF. */
- error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.agno, 0, &agf_bp);
+ error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.pag->pag_agno, 0,
+ &agf_bp);
if (error)
return error;
@@ -737,7 +741,7 @@ xrep_agi_find_btrees(
return -EFSCORRUPTED;
/* We must find the finobt root if that feature is enabled. */
- if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
+ if (xfs_has_finobt(mp) &&
!xrep_check_btree_root(sc, &fab[XREP_AGI_FINOBT]))
return -EFSCORRUPTED;
@@ -761,11 +765,12 @@ xrep_agi_init_header(
memset(agi, 0, BBTOB(agi_bp->b_length));
agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
- agi->agi_seqno = cpu_to_be32(sc->sa.agno);
- agi->agi_length = cpu_to_be32(xfs_ag_block_count(mp, sc->sa.agno));
+ agi->agi_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
+ agi->agi_length = cpu_to_be32(xfs_ag_block_count(mp,
+ sc->sa.pag->pag_agno));
agi->agi_newino = cpu_to_be32(NULLAGINO);
agi->agi_dirino = cpu_to_be32(NULLAGINO);
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid);
/* We don't know how to fix the unlinked list yet. */
@@ -787,7 +792,7 @@ xrep_agi_set_roots(
agi->agi_root = cpu_to_be32(fab[XREP_AGI_INOBT].root);
agi->agi_level = cpu_to_be32(fab[XREP_AGI_INOBT].height);
- if (xfs_sb_version_hasfinobt(&sc->mp->m_sb)) {
+ if (xfs_has_finobt(sc->mp)) {
agi->agi_free_root = cpu_to_be32(fab[XREP_AGI_FINOBT].root);
agi->agi_free_level = cpu_to_be32(fab[XREP_AGI_FINOBT].height);
}
@@ -811,7 +816,7 @@ xrep_agi_calc_from_btrees(
error = xfs_ialloc_count_inodes(cur, &count, &freecount);
if (error)
goto err;
- if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+ if (xfs_has_inobtcounts(mp)) {
xfs_agblock_t blocks;
error = xfs_btree_count_blocks(cur, &blocks);
@@ -824,8 +829,7 @@ xrep_agi_calc_from_btrees(
agi->agi_count = cpu_to_be32(count);
agi->agi_freecount = cpu_to_be32(freecount);
- if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
- xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+ if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
xfs_agblock_t blocks;
cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp,
@@ -893,16 +897,16 @@ xrep_agi(
int error;
/* We require the rmapbt to rebuild anything. */
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return -EOPNOTSUPP;
- xchk_perag_get(sc->mp, &sc->sa);
/*
* Make sure we have the AGI buffer, as scrub might have decided it
* was corrupt after xfs_ialloc_read_agi failed with -EFSCORRUPTED.
*/
error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
- XFS_AG_DADDR(mp, sc->sa.agno, XFS_AGI_DADDR(mp)),
+ XFS_AG_DADDR(mp, sc->sa.pag->pag_agno,
+ XFS_AGI_DADDR(mp)),
XFS_FSS_TO_BB(mp, 1), 0, &agi_bp, NULL);
if (error)
return error;
diff --git a/fs/xfs/scrub/alloc.c b/fs/xfs/scrub/alloc.c
index d5741980094a..87518e1292f8 100644
--- a/fs/xfs/scrub/alloc.c
+++ b/fs/xfs/scrub/alloc.c
@@ -91,7 +91,7 @@ xchk_allocbt_xref(
STATIC int
xchk_allocbt_rec(
struct xchk_btree *bs,
- union xfs_btree_rec *rec)
+ const union xfs_btree_rec *rec)
{
struct xfs_mount *mp = bs->cur->bc_mp;
xfs_agnumber_t agno = bs->cur->bc_ag.pag->pag_agno;
diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c
index 552af0cf8482..b6f0c9f3f124 100644
--- a/fs/xfs/scrub/attr.c
+++ b/fs/xfs/scrub/attr.c
@@ -25,11 +25,11 @@
* reallocating the buffer if necessary. Buffer contents are not preserved
* across a reallocation.
*/
-int
+static int
xchk_setup_xattr_buf(
struct xfs_scrub *sc,
size_t value_size,
- xfs_km_flags_t flags)
+ gfp_t flags)
{
size_t sz;
struct xchk_xattr_buf *ab = sc->buf;
@@ -57,7 +57,7 @@ xchk_setup_xattr_buf(
* Don't zero the buffer upon allocation to avoid runtime overhead.
* All users must be careful never to read uninitialized contents.
*/
- ab = kmem_alloc_large(sizeof(*ab) + sz, flags);
+ ab = kvmalloc(sizeof(*ab) + sz, flags);
if (!ab)
return -ENOMEM;
@@ -79,7 +79,7 @@ xchk_setup_xattr(
* without the inode lock held, which means we can sleep.
*/
if (sc->flags & XCHK_TRY_HARDER) {
- error = xchk_setup_xattr_buf(sc, XATTR_SIZE_MAX, 0);
+ error = xchk_setup_xattr_buf(sc, XATTR_SIZE_MAX, GFP_KERNEL);
if (error)
return error;
}
@@ -138,7 +138,8 @@ xchk_xattr_listent(
* doesn't work, we overload the seen_enough variable to convey
* the error message back to the main scrub function.
*/
- error = xchk_setup_xattr_buf(sx->sc, valuelen, KM_MAYFAIL);
+ error = xchk_setup_xattr_buf(sx->sc, valuelen,
+ GFP_KERNEL | __GFP_RETRY_MAYFAIL);
if (error == -ENOMEM)
error = -EDEADLOCK;
if (error) {
@@ -323,7 +324,8 @@ xchk_xattr_block(
return 0;
/* Allocate memory for block usage checking. */
- error = xchk_setup_xattr_buf(ds->sc, 0, KM_MAYFAIL);
+ error = xchk_setup_xattr_buf(ds->sc, 0,
+ GFP_KERNEL | __GFP_RETRY_MAYFAIL);
if (error == -ENOMEM)
return -EDEADLOCK;
if (error)
@@ -334,7 +336,7 @@ xchk_xattr_block(
bitmap_zero(usedmap, mp->m_attr_geo->blksize);
/* Check all the padding. */
- if (xfs_sb_version_hascrc(&ds->sc->mp->m_sb)) {
+ if (xfs_has_crc(ds->sc->mp)) {
struct xfs_attr3_leafblock *leaf = bp->b_addr;
if (leaf->hdr.pad1 != 0 || leaf->hdr.pad2 != 0 ||
diff --git a/fs/xfs/scrub/attr.h b/fs/xfs/scrub/attr.h
index 13a1d2e8424d..1719e1c4da59 100644
--- a/fs/xfs/scrub/attr.h
+++ b/fs/xfs/scrub/attr.h
@@ -65,7 +65,4 @@ xchk_xattr_dstmap(
BITS_TO_LONGS(sc->mp->m_attr_geo->blksize);
}
-int xchk_setup_xattr_buf(struct xfs_scrub *sc, size_t value_size,
- xfs_km_flags_t flags);
-
#endif /* __XFS_SCRUB_ATTR_H__ */
diff --git a/fs/xfs/scrub/bitmap.c b/fs/xfs/scrub/bitmap.c
index 813b5f219113..d6d24c866bc4 100644
--- a/fs/xfs/scrub/bitmap.c
+++ b/fs/xfs/scrub/bitmap.c
@@ -260,7 +260,7 @@ xbitmap_set_btcur_path(
xfs_btree_get_block(cur, i, &bp);
if (!bp)
continue;
- fsb = XFS_DADDR_TO_FSB(cur->bc_mp, bp->b_bn);
+ fsb = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
error = xbitmap_set(bitmap, fsb, 1);
if (error)
return error;
@@ -284,7 +284,7 @@ xbitmap_collect_btblock(
if (!bp)
return 0;
- fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, bp->b_bn);
+ fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
return xbitmap_set(bitmap, fsbno, 1);
}
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 1d146c9d9de1..017da9ceaee9 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -260,10 +260,10 @@ xchk_bmap_iextent_xref(
agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
len = irec->br_blockcount;
- error = xchk_ag_init(info->sc, agno, &info->sc->sa);
+ error = xchk_ag_init_existing(info->sc, agno, &info->sc->sa);
if (!xchk_fblock_process_error(info->sc, info->whichfork,
irec->br_startoff, &error))
- return;
+ goto out_free;
xchk_xref_is_used_space(info->sc, agbno, len);
xchk_xref_is_not_inode_chunk(info->sc, agbno, len);
@@ -283,6 +283,7 @@ xchk_bmap_iextent_xref(
break;
}
+out_free:
xchk_ag_free(info->sc, &info->sc->sa);
}
@@ -383,7 +384,7 @@ xchk_bmap_iextent(
STATIC int
xchk_bmapbt_rec(
struct xchk_btree *bs,
- union xfs_btree_rec *rec)
+ const union xfs_btree_rec *rec)
{
struct xfs_bmbt_irec irec;
struct xfs_bmbt_irec iext_irec;
@@ -400,7 +401,7 @@ xchk_bmapbt_rec(
* Check the owners of the btree blocks up to the level below
* the root since the verifiers don't do that.
*/
- if (xfs_sb_version_hascrc(&bs->cur->bc_mp->m_sb) &&
+ if (xfs_has_crc(bs->cur->bc_mp) &&
bs->cur->bc_ptrs[0] == 1) {
for (i = 0; i < bs->cur->bc_nlevels - 1; i++) {
block = xfs_btree_get_block(bs->cur, i, &bp);
@@ -473,10 +474,11 @@ struct xchk_bmap_check_rmap_info {
STATIC int
xchk_bmap_check_rmap(
struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
void *priv)
{
struct xfs_bmbt_irec irec;
+ struct xfs_rmap_irec check_rec;
struct xchk_bmap_check_rmap_info *sbcri = priv;
struct xfs_ifork *ifp;
struct xfs_scrub *sc = sbcri->sc;
@@ -510,28 +512,30 @@ xchk_bmap_check_rmap(
* length, so we have to loop through the bmbt to make sure that the
* entire rmap is covered by bmbt records.
*/
+ check_rec = *rec;
while (have_map) {
- if (irec.br_startoff != rec->rm_offset)
+ if (irec.br_startoff != check_rec.rm_offset)
xchk_fblock_set_corrupt(sc, sbcri->whichfork,
- rec->rm_offset);
+ check_rec.rm_offset);
if (irec.br_startblock != XFS_AGB_TO_FSB(sc->mp,
- cur->bc_ag.pag->pag_agno, rec->rm_startblock))
+ cur->bc_ag.pag->pag_agno,
+ check_rec.rm_startblock))
xchk_fblock_set_corrupt(sc, sbcri->whichfork,
- rec->rm_offset);
- if (irec.br_blockcount > rec->rm_blockcount)
+ check_rec.rm_offset);
+ if (irec.br_blockcount > check_rec.rm_blockcount)
xchk_fblock_set_corrupt(sc, sbcri->whichfork,
- rec->rm_offset);
+ check_rec.rm_offset);
if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
break;
- rec->rm_startblock += irec.br_blockcount;
- rec->rm_offset += irec.br_blockcount;
- rec->rm_blockcount -= irec.br_blockcount;
- if (rec->rm_blockcount == 0)
+ check_rec.rm_startblock += irec.br_blockcount;
+ check_rec.rm_offset += irec.br_blockcount;
+ check_rec.rm_blockcount -= irec.br_blockcount;
+ if (check_rec.rm_blockcount == 0)
break;
have_map = xfs_iext_next_extent(ifp, &sbcri->icur, &irec);
if (!have_map)
xchk_fblock_set_corrupt(sc, sbcri->whichfork,
- rec->rm_offset);
+ check_rec.rm_offset);
}
out:
@@ -581,7 +585,7 @@ xchk_bmap_check_rmaps(
bool zero_size;
int error;
- if (!xfs_sb_version_hasrmapbt(&sc->mp->m_sb) ||
+ if (!xfs_has_rmapbt(sc->mp) ||
whichfork == XFS_COW_FORK ||
(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
return 0;
@@ -659,8 +663,7 @@ xchk_bmap(
}
break;
case XFS_ATTR_FORK:
- if (!xfs_sb_version_hasattr(&mp->m_sb) &&
- !xfs_sb_version_hasattr2(&mp->m_sb))
+ if (!xfs_has_attr(mp) && !xfs_has_attr2(mp))
xchk_ino_set_corrupt(sc, sc->ip->i_ino);
break;
default:
diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c
index bd1172358964..eccb855dc904 100644
--- a/fs/xfs/scrub/btree.c
+++ b/fs/xfs/scrub/btree.c
@@ -374,10 +374,10 @@ xchk_btree_check_block_owner(
init_sa = bs->cur->bc_flags & XFS_BTREE_LONG_PTRS;
if (init_sa) {
- error = xchk_ag_init(bs->sc, agno, &bs->sc->sa);
+ error = xchk_ag_init_existing(bs->sc, agno, &bs->sc->sa);
if (!xchk_btree_xref_process_error(bs->sc, bs->cur,
level, &error))
- return error;
+ goto out_free;
}
xchk_xref_is_used_space(bs->sc, agbno, 1);
@@ -393,6 +393,7 @@ xchk_btree_check_block_owner(
if (!bs->sc->sa.rmap_cur && btnum == XFS_BTNUM_RMAP)
bs->cur = NULL;
+out_free:
if (init_sa)
xchk_ag_free(bs->sc, &bs->sc->sa);
@@ -435,12 +436,12 @@ xchk_btree_check_owner(
if (!co)
return -ENOMEM;
co->level = level;
- co->daddr = XFS_BUF_ADDR(bp);
+ co->daddr = xfs_buf_daddr(bp);
list_add_tail(&co->list, &bs->to_check);
return 0;
}
- return xchk_btree_check_block_owner(bs, level, XFS_BUF_ADDR(bp));
+ return xchk_btree_check_block_owner(bs, level, xfs_buf_daddr(bp));
}
/* Decide if we want to check minrecs of a btree block in the inode root. */
diff --git a/fs/xfs/scrub/btree.h b/fs/xfs/scrub/btree.h
index 5572e475f8ed..b7d2fc01fbf9 100644
--- a/fs/xfs/scrub/btree.h
+++ b/fs/xfs/scrub/btree.h
@@ -26,8 +26,8 @@ void xchk_btree_xref_set_corrupt(struct xfs_scrub *sc,
struct xchk_btree;
typedef int (*xchk_btree_rec_fn)(
- struct xchk_btree *bs,
- union xfs_btree_rec *rec);
+ struct xchk_btree *bs,
+ const union xfs_btree_rec *rec);
struct xchk_btree {
/* caller-provided scrub state */
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index 8558ca05e11d..bf1f3607d0b6 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -186,7 +186,7 @@ xchk_block_set_preen(
struct xfs_buf *bp)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_PREEN;
- trace_xchk_block_preen(sc, bp->b_bn, __return_address);
+ trace_xchk_block_preen(sc, xfs_buf_daddr(bp), __return_address);
}
/*
@@ -219,7 +219,7 @@ xchk_block_set_corrupt(
struct xfs_buf *bp)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
- trace_xchk_block_error(sc, bp->b_bn, __return_address);
+ trace_xchk_block_error(sc, xfs_buf_daddr(bp), __return_address);
}
/* Record a corruption while cross-referencing. */
@@ -229,7 +229,7 @@ xchk_block_xref_set_corrupt(
struct xfs_buf *bp)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XCORRUPT;
- trace_xchk_block_error(sc, bp->b_bn, __return_address);
+ trace_xchk_block_error(sc, xfs_buf_daddr(bp), __return_address);
}
/*
@@ -324,7 +324,7 @@ struct xchk_rmap_ownedby_info {
STATIC int
xchk_count_rmap_ownedby_irec(
struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
void *priv)
{
struct xchk_rmap_ownedby_info *sroi = priv;
@@ -394,11 +394,11 @@ want_ag_read_header_failure(
}
/*
- * Grab all the headers for an AG.
+ * Grab the perag structure and all the headers for an AG.
*
- * The headers should be released by xchk_ag_free, but as a fail
- * safe we attach all the buffers we grab to the scrub transaction so
- * they'll all be freed when we cancel it.
+ * The headers should be released by xchk_ag_free, but as a fail safe we attach
+ * all the buffers we grab to the scrub transaction so they'll all be freed
+ * when we cancel it. Returns ENOENT if we can't grab the perag structure.
*/
int
xchk_ag_read_headers(
@@ -409,22 +409,24 @@ xchk_ag_read_headers(
struct xfs_mount *mp = sc->mp;
int error;
- sa->agno = agno;
+ ASSERT(!sa->pag);
+ sa->pag = xfs_perag_get(mp, agno);
+ if (!sa->pag)
+ return -ENOENT;
error = xfs_ialloc_read_agi(mp, sc->tp, agno, &sa->agi_bp);
if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGI))
- goto out;
+ return error;
error = xfs_alloc_read_agf(mp, sc->tp, agno, 0, &sa->agf_bp);
if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGF))
- goto out;
+ return error;
error = xfs_alloc_read_agfl(mp, sc->tp, agno, &sa->agfl_bp);
if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGFL))
- goto out;
- error = 0;
-out:
- return error;
+ return error;
+
+ return 0;
}
/* Release all the AG btree cursors. */
@@ -461,7 +463,6 @@ xchk_ag_btcur_init(
{
struct xfs_mount *mp = sc->mp;
- xchk_perag_get(sc->mp, sa);
if (sa->agf_bp &&
xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_BNO)) {
/* Set up a bnobt cursor for cross-referencing. */
@@ -484,21 +485,21 @@ xchk_ag_btcur_init(
}
/* Set up a finobt cursor for cross-referencing. */
- if (sa->agi_bp && xfs_sb_version_hasfinobt(&mp->m_sb) &&
+ if (sa->agi_bp && xfs_has_finobt(mp) &&
xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_FINO)) {
sa->fino_cur = xfs_inobt_init_cursor(mp, sc->tp, sa->agi_bp,
sa->pag, XFS_BTNUM_FINO);
}
/* Set up a rmapbt cursor for cross-referencing. */
- if (sa->agf_bp && xfs_sb_version_hasrmapbt(&mp->m_sb) &&
+ if (sa->agf_bp && xfs_has_rmapbt(mp) &&
xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_RMAP)) {
sa->rmap_cur = xfs_rmapbt_init_cursor(mp, sc->tp, sa->agf_bp,
sa->pag);
}
/* Set up a refcountbt cursor for cross-referencing. */
- if (sa->agf_bp && xfs_sb_version_hasreflink(&mp->m_sb) &&
+ if (sa->agf_bp && xfs_has_reflink(mp) &&
xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_REFC)) {
sa->refc_cur = xfs_refcountbt_init_cursor(mp, sc->tp,
sa->agf_bp, sa->pag);
@@ -528,15 +529,14 @@ xchk_ag_free(
xfs_perag_put(sa->pag);
sa->pag = NULL;
}
- sa->agno = NULLAGNUMBER;
}
/*
- * For scrub, grab the AGI and the AGF headers, in that order. Locking
- * order requires us to get the AGI before the AGF. We use the
- * transaction to avoid deadlocking on crosslinked metadata buffers;
- * either the caller passes one in (bmap scrub) or we have to create a
- * transaction ourselves.
+ * For scrub, grab the perag structure, the AGI, and the AGF headers, in that
+ * order. Locking order requires us to get the AGI before the AGF. We use the
+ * transaction to avoid deadlocking on crosslinked metadata buffers; either the
+ * caller passes one in (bmap scrub) or we have to create a transaction
+ * ourselves. Returns ENOENT if the perag struct cannot be grabbed.
*/
int
xchk_ag_init(
@@ -554,19 +554,6 @@ xchk_ag_init(
return 0;
}
-/*
- * Grab the per-ag structure if we haven't already gotten it. Teardown of the
- * xchk_ag will release it for us.
- */
-void
-xchk_perag_get(
- struct xfs_mount *mp,
- struct xchk_ag *sa)
-{
- if (!sa->pag)
- sa->pag = xfs_perag_get(mp, sa->agno);
-}
-
/* Per-scrubber setup functions */
/*
@@ -797,7 +784,7 @@ xchk_buffer_recheck(
if (!fa)
return;
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
- trace_xchk_block_error(sc, bp->b_bn, fa);
+ trace_xchk_block_error(sc, xfs_buf_daddr(bp), fa);
}
/*
@@ -842,7 +829,7 @@ xchk_metadata_inode_forks(
return error;
/* Look for incorrect shared blocks. */
- if (xfs_sb_version_hasreflink(&sc->mp->m_sb)) {
+ if (xfs_has_reflink(sc->mp)) {
error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip,
&shared);
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0,
@@ -884,6 +871,7 @@ xchk_stop_reaping(
{
sc->flags |= XCHK_REAPING_DISABLED;
xfs_blockgc_stop(sc->mp);
+ xfs_inodegc_stop(sc->mp);
}
/* Restart background reaping of resources. */
@@ -891,6 +879,13 @@ void
xchk_start_reaping(
struct xfs_scrub *sc)
{
- xfs_blockgc_start(sc->mp);
+ /*
+ * Readonly filesystems do not perform inactivation or speculative
+ * preallocation, so there's no need to restart the workers.
+ */
+ if (!xfs_is_readonly(sc->mp)) {
+ xfs_inodegc_start(sc->mp);
+ xfs_blockgc_start(sc->mp);
+ }
sc->flags &= ~XCHK_REAPING_DISABLED;
}
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 0410faf7d735..454145db10e7 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -107,7 +107,23 @@ int xchk_setup_fscounters(struct xfs_scrub *sc);
void xchk_ag_free(struct xfs_scrub *sc, struct xchk_ag *sa);
int xchk_ag_init(struct xfs_scrub *sc, xfs_agnumber_t agno,
struct xchk_ag *sa);
-void xchk_perag_get(struct xfs_mount *mp, struct xchk_ag *sa);
+
+/*
+ * Grab all AG resources, treating the inability to grab the perag structure as
+ * a fs corruption. This is intended for callers checking an ondisk reference
+ * to a given AG, which means that the AG must still exist.
+ */
+static inline int
+xchk_ag_init_existing(
+ struct xfs_scrub *sc,
+ xfs_agnumber_t agno,
+ struct xchk_ag *sa)
+{
+ int error = xchk_ag_init(sc, agno, sa);
+
+ return error == -ENOENT ? -EFSCORRUPTED : error;
+}
+
int xchk_ag_read_headers(struct xfs_scrub *sc, xfs_agnumber_t agno,
struct xchk_ag *sa);
void xchk_ag_btcur_free(struct xchk_ag *sa);
diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
index 9f0dbb47c82c..8a52514bc1ff 100644
--- a/fs/xfs/scrub/dabtree.c
+++ b/fs/xfs/scrub/dabtree.c
@@ -367,11 +367,11 @@ xchk_da_btree_block(
pmaxrecs = &ds->maxrecs[level];
/* We only started zeroing the header on v5 filesystems. */
- if (xfs_sb_version_hascrc(&ds->sc->mp->m_sb) && hdr3->hdr.pad)
+ if (xfs_has_crc(ds->sc->mp) && hdr3->hdr.pad)
xchk_da_set_corrupt(ds, level);
/* Check the owner. */
- if (xfs_sb_version_hascrc(&ip->i_mount->m_sb)) {
+ if (xfs_has_crc(ip->i_mount)) {
owner = be64_to_cpu(hdr3->owner);
if (owner != ip->i_ino)
xchk_da_set_corrupt(ds, level);
diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c
index 28dda391d5df..200a63f58fe7 100644
--- a/fs/xfs/scrub/dir.c
+++ b/fs/xfs/scrub/dir.c
@@ -51,7 +51,7 @@ xchk_dir_check_ftype(
int ino_dtype;
int error = 0;
- if (!xfs_sb_version_hasftype(&mp->m_sb)) {
+ if (!xfs_has_ftype(mp)) {
if (dtype != DT_UNKNOWN && dtype != DT_DIR)
xchk_fblock_set_corrupt(sdc->sc, XFS_DATA_FORK,
offset);
@@ -140,7 +140,7 @@ xchk_dir_actor(
if (!strncmp(".", name, namelen)) {
/* If this is "." then check that the inum matches the dir. */
- if (xfs_sb_version_hasftype(&mp->m_sb) && type != DT_DIR)
+ if (xfs_has_ftype(mp) && type != DT_DIR)
xchk_fblock_set_corrupt(sdc->sc, XFS_DATA_FORK,
offset);
checked_ftype = true;
@@ -152,7 +152,7 @@ xchk_dir_actor(
* If this is ".." in the root inode, check that the inum
* matches this dir.
*/
- if (xfs_sb_version_hasftype(&mp->m_sb) && type != DT_DIR)
+ if (xfs_has_ftype(mp) && type != DT_DIR)
xchk_fblock_set_corrupt(sdc->sc, XFS_DATA_FORK,
offset);
checked_ftype = true;
@@ -526,7 +526,7 @@ xchk_directory_leaf1_bestfree(
bestcount = be32_to_cpu(ltp->bestcount);
bestp = xfs_dir2_leaf_bests_p(ltp);
- if (xfs_sb_version_hascrc(&sc->mp->m_sb)) {
+ if (xfs_has_crc(sc->mp)) {
struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr;
if (hdr3->pad != cpu_to_be32(0))
@@ -623,7 +623,7 @@ xchk_directory_free_bestfree(
return error;
xchk_buffer_recheck(sc, bp);
- if (xfs_sb_version_hascrc(&sc->mp->m_sb)) {
+ if (xfs_has_crc(sc->mp)) {
struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
if (hdr3->pad != cpu_to_be32(0))
diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
index fd7941e04ae1..48a6cbdf95d0 100644
--- a/fs/xfs/scrub/fscounters.c
+++ b/fs/xfs/scrub/fscounters.c
@@ -148,9 +148,9 @@ xchk_fscount_btreeblks(
xfs_extlen_t blocks;
int error;
- error = xchk_ag_init(sc, agno, &sc->sa);
+ error = xchk_ag_init_existing(sc, agno, &sc->sa);
if (error)
- return error;
+ goto out_free;
error = xfs_btree_count_blocks(sc->sa.bno_cur, &blocks);
if (error)
@@ -207,7 +207,7 @@ retry:
/* Add up the free/freelist/bnobt/cntbt blocks */
fsc->fdblocks += pag->pagf_freeblks;
fsc->fdblocks += pag->pagf_flcount;
- if (xfs_sb_version_haslazysbcount(&sc->mp->m_sb)) {
+ if (xfs_has_lazysbcount(sc->mp)) {
fsc->fdblocks += pag->pagf_btreeblks;
} else {
error = xchk_fscount_btreeblks(sc, fsc, agno);
diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c
index 30e568596b79..00848ee542fb 100644
--- a/fs/xfs/scrub/ialloc.c
+++ b/fs/xfs/scrub/ialloc.c
@@ -418,7 +418,7 @@ xchk_iallocbt_rec_alignment(
STATIC int
xchk_iallocbt_rec(
struct xchk_btree *bs,
- union xfs_btree_rec *rec)
+ const union xfs_btree_rec *rec)
{
struct xfs_mount *mp = bs->cur->bc_mp;
struct xchk_iallocbt *iabt = bs->private;
@@ -517,7 +517,7 @@ xchk_iallocbt_xref_rmap_btreeblks(
int error;
if (!sc->sa.ino_cur || !sc->sa.rmap_cur ||
- (xfs_sb_version_hasfinobt(&sc->mp->m_sb) && !sc->sa.fino_cur) ||
+ (xfs_has_finobt(sc->mp) && !sc->sa.fino_cur) ||
xchk_skip_xref(sc->sm))
return;
diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
index 76fbc7ca4cec..2405b09d03d0 100644
--- a/fs/xfs/scrub/inode.c
+++ b/fs/xfs/scrub/inode.c
@@ -181,7 +181,7 @@ xchk_inode_flags2(
/* reflink flag requires reflink feature */
if ((flags2 & XFS_DIFLAG2_REFLINK) &&
- !xfs_sb_version_hasreflink(&mp->m_sb))
+ !xfs_has_reflink(mp))
goto bad;
/* cowextsize flag is checked w.r.t. mode separately */
@@ -199,8 +199,7 @@ xchk_inode_flags2(
goto bad;
/* no bigtime iflag without the bigtime feature */
- if (xfs_dinode_has_bigtime(dip) &&
- !xfs_sb_version_hasbigtime(&mp->m_sb))
+ if (xfs_dinode_has_bigtime(dip) && !xfs_has_bigtime(mp))
goto bad;
return;
@@ -278,7 +277,7 @@ xchk_dinode(
xchk_ino_set_corrupt(sc, ino);
if (dip->di_projid_hi != 0 &&
- !xfs_sb_version_hasprojid32bit(&mp->m_sb))
+ !xfs_has_projid32(mp))
xchk_ino_set_corrupt(sc, ino);
break;
default:
@@ -532,9 +531,9 @@ xchk_inode_xref(
agno = XFS_INO_TO_AGNO(sc->mp, ino);
agbno = XFS_INO_TO_AGBNO(sc->mp, ino);
- error = xchk_ag_init(sc, agno, &sc->sa);
+ error = xchk_ag_init_existing(sc, agno, &sc->sa);
if (!xchk_xref_process_error(sc, agno, agbno, &error))
- return;
+ goto out_free;
xchk_xref_is_used_space(sc, agbno, 1);
xchk_inode_xref_finobt(sc, ino);
@@ -542,6 +541,7 @@ xchk_inode_xref(
xchk_xref_is_not_shared(sc, agbno, 1);
xchk_inode_xref_bmap(sc, dip);
+out_free:
xchk_ag_free(sc, &sc->sa);
}
@@ -560,7 +560,7 @@ xchk_inode_check_reflink_iflag(
bool has_shared;
int error;
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return;
error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip,
diff --git a/fs/xfs/scrub/quota.c b/fs/xfs/scrub/quota.c
index acbb9839d42f..d6c1b00a4fc8 100644
--- a/fs/xfs/scrub/quota.c
+++ b/fs/xfs/scrub/quota.c
@@ -42,7 +42,7 @@ xchk_setup_quota(
xfs_dqtype_t dqtype;
int error;
- if (!XFS_IS_QUOTA_RUNNING(sc->mp) || !XFS_IS_QUOTA_ON(sc->mp))
+ if (!XFS_IS_QUOTA_ON(sc->mp))
return -ENOENT;
dqtype = xchk_quota_to_dqtype(sc);
@@ -127,7 +127,7 @@ xchk_quota_item(
* a reflink filesystem we're allowed to exceed physical space
* if there are no quota limits.
*/
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ if (xfs_has_reflink(mp)) {
if (mp->m_sb.sb_dblocks < dq->q_blk.count)
xchk_fblock_set_warning(sc, XFS_DATA_FORK,
offset);
diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c
index 7014b7408bad..2744eecdbaf0 100644
--- a/fs/xfs/scrub/refcount.c
+++ b/fs/xfs/scrub/refcount.c
@@ -91,7 +91,7 @@ struct xchk_refcnt_check {
STATIC int
xchk_refcountbt_rmap_check(
struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
void *priv)
{
struct xchk_refcnt_check *refchk = priv;
@@ -330,7 +330,7 @@ xchk_refcountbt_xref(
STATIC int
xchk_refcountbt_rec(
struct xchk_btree *bs,
- union xfs_btree_rec *rec)
+ const union xfs_btree_rec *rec)
{
struct xfs_mount *mp = bs->cur->bc_mp;
xfs_agblock_t *cow_blocks = bs->private;
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index ebb0e245aa72..8f3cba14ada3 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -248,19 +248,19 @@ xrep_calc_ag_resblks(
* bnobt/cntbt or inobt/finobt as pairs.
*/
bnobt_sz = 2 * xfs_allocbt_calc_size(mp, freelen);
- if (xfs_sb_version_hassparseinodes(&mp->m_sb))
+ if (xfs_has_sparseinodes(mp))
inobt_sz = xfs_iallocbt_calc_size(mp, icount /
XFS_INODES_PER_HOLEMASK_BIT);
else
inobt_sz = xfs_iallocbt_calc_size(mp, icount /
XFS_INODES_PER_CHUNK);
- if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ if (xfs_has_finobt(mp))
inobt_sz *= 2;
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
refcbt_sz = xfs_refcountbt_calc_size(mp, usedlen);
else
refcbt_sz = 0;
- if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ if (xfs_has_rmapbt(mp)) {
/*
* Guess how many blocks we need to rebuild the rmapbt.
* For non-reflink filesystems we can't have more records than
@@ -269,7 +269,7 @@ xrep_calc_ag_resblks(
* many rmaps there could be in the AG, so we start off with
* what we hope is an generous over-estimation.
*/
- if (xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_reflink(mp))
rmapbt_sz = xfs_rmapbt_calc_size(mp,
(unsigned long long)aglen * 2);
else
@@ -306,9 +306,9 @@ xrep_alloc_ag_block(
return -ENOSPC;
xfs_extent_busy_reuse(sc->mp, sc->sa.pag, bno,
1, false);
- *fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.agno, bno);
+ *fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.pag->pag_agno, bno);
if (resv == XFS_AG_RESV_RMAPBT)
- xfs_ag_resv_rmapbt_alloc(sc->mp, sc->sa.agno);
+ xfs_ag_resv_rmapbt_alloc(sc->mp, sc->sa.pag->pag_agno);
return 0;
default:
break;
@@ -317,7 +317,7 @@ xrep_alloc_ag_block(
args.tp = sc->tp;
args.mp = sc->mp;
args.oinfo = *oinfo;
- args.fsbno = XFS_AGB_TO_FSB(args.mp, sc->sa.agno, 0);
+ args.fsbno = XFS_AGB_TO_FSB(args.mp, sc->sa.pag->pag_agno, 0);
args.minlen = 1;
args.maxlen = 1;
args.prod = 1;
@@ -352,14 +352,14 @@ xrep_init_btblock(
trace_xrep_init_btblock(mp, XFS_FSB_TO_AGNO(mp, fsb),
XFS_FSB_TO_AGBNO(mp, fsb), btnum);
- ASSERT(XFS_FSB_TO_AGNO(mp, fsb) == sc->sa.agno);
+ ASSERT(XFS_FSB_TO_AGNO(mp, fsb) == sc->sa.pag->pag_agno);
error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
XFS_FSB_TO_DADDR(mp, fsb), XFS_FSB_TO_BB(mp, 1), 0,
&bp);
if (error)
return error;
xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
- xfs_btree_init_block(mp, bp, btnum, 0, 0, sc->sa.agno);
+ xfs_btree_init_block(mp, bp, btnum, 0, 0, sc->sa.pag->pag_agno);
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_BTREE_BUF);
xfs_trans_log_buf(tp, bp, 0, BBTOB(bp->b_length) - 1);
bp->b_ops = ops;
@@ -481,7 +481,7 @@ xrep_fix_freelist(
args.mp = sc->mp;
args.tp = sc->tp;
- args.agno = sc->sa.agno;
+ args.agno = sc->sa.pag->pag_agno;
args.alignment = 1;
args.pag = sc->sa.pag;
@@ -611,11 +611,11 @@ xrep_reap_extents(
xfs_fsblock_t fsbno;
int error = 0;
- ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb));
+ ASSERT(xfs_has_rmapbt(sc->mp));
for_each_xbitmap_block(fsbno, bmr, n, bitmap) {
ASSERT(sc->ip != NULL ||
- XFS_FSB_TO_AGNO(sc->mp, fsbno) == sc->sa.agno);
+ XFS_FSB_TO_AGNO(sc->mp, fsbno) == sc->sa.pag->pag_agno);
trace_xrep_dispose_btree_extent(sc->mp,
XFS_FSB_TO_AGNO(sc->mp, fsbno),
XFS_FSB_TO_AGBNO(sc->mp, fsbno), 1);
@@ -690,7 +690,7 @@ xrep_findroot_block(
int block_level;
int error = 0;
- daddr = XFS_AGB_TO_DADDR(mp, ri->sc->sa.agno, agbno);
+ daddr = XFS_AGB_TO_DADDR(mp, ri->sc->sa.pag->pag_agno, agbno);
/*
* Blocks in the AGFL have stale contents that might just happen to
@@ -819,7 +819,7 @@ xrep_findroot_block(
else
fab->root = NULLAGBLOCK;
- trace_xrep_findroot_block(mp, ri->sc->sa.agno, agbno,
+ trace_xrep_findroot_block(mp, ri->sc->sa.pag->pag_agno, agbno,
be32_to_cpu(btblock->bb_magic), fab->height - 1);
out:
xfs_trans_brelse(ri->sc->tp, bp);
@@ -833,7 +833,7 @@ out:
STATIC int
xrep_findroot_rmap(
struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
void *priv)
{
struct xrep_findroot *ri = priv;
diff --git a/fs/xfs/scrub/rmap.c b/fs/xfs/scrub/rmap.c
index fc306573f0ac..8dae0345c7df 100644
--- a/fs/xfs/scrub/rmap.c
+++ b/fs/xfs/scrub/rmap.c
@@ -88,7 +88,7 @@ xchk_rmapbt_xref(
STATIC int
xchk_rmapbt_rec(
struct xchk_btree *bs,
- union xfs_btree_rec *rec)
+ const union xfs_btree_rec *rec)
{
struct xfs_mount *mp = bs->cur->bc_mp;
struct xfs_rmap_irec irec;
diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c
index 37c0e2266c85..8fa012057405 100644
--- a/fs/xfs/scrub/rtbitmap.c
+++ b/fs/xfs/scrub/rtbitmap.c
@@ -41,7 +41,7 @@ xchk_setup_rt(
STATIC int
xchk_rtbitmap_rec(
struct xfs_trans *tp,
- struct xfs_rtalloc_rec *rec,
+ const struct xfs_rtalloc_rec *rec,
void *priv)
{
struct xfs_scrub *sc = priv;
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index 0e542636227c..51e4c61916d2 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -239,21 +239,21 @@ static const struct xchk_meta_ops meta_scrub_ops[] = {
.type = ST_PERAG,
.setup = xchk_setup_ag_iallocbt,
.scrub = xchk_finobt,
- .has = xfs_sb_version_hasfinobt,
+ .has = xfs_has_finobt,
.repair = xrep_notsupported,
},
[XFS_SCRUB_TYPE_RMAPBT] = { /* rmapbt */
.type = ST_PERAG,
.setup = xchk_setup_ag_rmapbt,
.scrub = xchk_rmapbt,
- .has = xfs_sb_version_hasrmapbt,
+ .has = xfs_has_rmapbt,
.repair = xrep_notsupported,
},
[XFS_SCRUB_TYPE_REFCNTBT] = { /* refcountbt */
.type = ST_PERAG,
.setup = xchk_setup_ag_refcountbt,
.scrub = xchk_refcountbt,
- .has = xfs_sb_version_hasreflink,
+ .has = xfs_has_reflink,
.repair = xrep_notsupported,
},
[XFS_SCRUB_TYPE_INODE] = { /* inode record */
@@ -308,14 +308,14 @@ static const struct xchk_meta_ops meta_scrub_ops[] = {
.type = ST_FS,
.setup = xchk_setup_rt,
.scrub = xchk_rtbitmap,
- .has = xfs_sb_version_hasrealtime,
+ .has = xfs_has_realtime,
.repair = xrep_notsupported,
},
[XFS_SCRUB_TYPE_RTSUM] = { /* realtime summary */
.type = ST_FS,
.setup = xchk_setup_rt,
.scrub = xchk_rtsummary,
- .has = xfs_sb_version_hasrealtime,
+ .has = xfs_has_realtime,
.repair = xrep_notsupported,
},
[XFS_SCRUB_TYPE_UQUOTA] = { /* user quota */
@@ -383,7 +383,7 @@ xchk_validate_inputs(
if (ops->setup == NULL || ops->scrub == NULL)
goto out;
/* Does this fs even support this type of metadata? */
- if (ops->has && !ops->has(&mp->m_sb))
+ if (ops->has && !ops->has(mp))
goto out;
error = -EINVAL;
@@ -415,11 +415,11 @@ xchk_validate_inputs(
*/
if (sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) {
error = -EOPNOTSUPP;
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
goto out;
error = -EROFS;
- if (mp->m_flags & XFS_MOUNT_RDONLY)
+ if (xfs_is_readonly(mp))
goto out;
}
@@ -464,9 +464,6 @@ xfs_scrub_metadata(
struct xfs_scrub sc = {
.file = file,
.sm = sm,
- .sa = {
- .agno = NULLAGNUMBER,
- },
};
struct xfs_mount *mp = XFS_I(file_inode(file))->i_mount;
int error = 0;
@@ -480,10 +477,10 @@ xfs_scrub_metadata(
/* Forbidden if we are shut down or mounted norecovery. */
error = -ESHUTDOWN;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
goto out;
error = -ENOTRECOVERABLE;
- if (mp->m_flags & XFS_MOUNT_NORECOVERY)
+ if (xfs_has_norecovery(mp))
goto out;
error = xchk_validate_inputs(mp, sm);
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index 08a483cb46e2..80e5026bba44 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -27,7 +27,7 @@ struct xchk_meta_ops {
int (*repair)(struct xfs_scrub *);
/* Decide if we even have this piece of metadata. */
- bool (*has)(struct xfs_sb *);
+ bool (*has)(struct xfs_mount *);
/* type describing required/allowed inputs */
enum xchk_type type;
@@ -35,7 +35,6 @@ struct xchk_meta_ops {
/* Buffer pointers and btree cursors for an entire AG. */
struct xchk_ag {
- xfs_agnumber_t agno;
struct xfs_perag *pag;
/* AG btree roots */
diff --git a/fs/xfs/scrub/trace.c b/fs/xfs/scrub/trace.c
index 03882a605a3c..c0ef53fe6611 100644
--- a/fs/xfs/scrub/trace.c
+++ b/fs/xfs/scrub/trace.c
@@ -22,11 +22,11 @@ xchk_btree_cur_fsbno(
int level)
{
if (level < cur->bc_nlevels && cur->bc_bufs[level])
- return XFS_DADDR_TO_FSB(cur->bc_mp, cur->bc_bufs[level]->b_bn);
- else if (level == cur->bc_nlevels - 1 &&
- cur->bc_flags & XFS_BTREE_LONG_PTRS)
+ return XFS_DADDR_TO_FSB(cur->bc_mp,
+ xfs_buf_daddr(cur->bc_bufs[level]));
+ if (level == cur->bc_nlevels - 1 && cur->bc_flags & XFS_BTREE_LONG_PTRS)
return XFS_INO_TO_FSB(cur->bc_mp, cur->bc_ino.ip->i_ino);
- else if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS))
+ if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS))
return XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno, 0);
return NULLFSBLOCK;
}
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
index e46f5cef90da..a7bbb84f91a7 100644
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -2,6 +2,10 @@
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
* Author: Darrick J. Wong <darrick.wong@oracle.com>
+ *
+ * NOTE: none of these tracepoints shall be considered a stable kernel ABI
+ * as they can change at any time. See xfs_trace.h for documentation of
+ * specific units found in tracepoint output.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM xfs_scrub
@@ -79,6 +83,16 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FSCOUNTERS);
{ XFS_SCRUB_TYPE_PQUOTA, "prjquota" }, \
{ XFS_SCRUB_TYPE_FSCOUNTERS, "fscounters" }
+#define XFS_SCRUB_FLAG_STRINGS \
+ { XFS_SCRUB_IFLAG_REPAIR, "repair" }, \
+ { XFS_SCRUB_OFLAG_CORRUPT, "corrupt" }, \
+ { XFS_SCRUB_OFLAG_PREEN, "preen" }, \
+ { XFS_SCRUB_OFLAG_XFAIL, "xfail" }, \
+ { XFS_SCRUB_OFLAG_XCORRUPT, "xcorrupt" }, \
+ { XFS_SCRUB_OFLAG_INCOMPLETE, "incomplete" }, \
+ { XFS_SCRUB_OFLAG_WARNING, "warning" }, \
+ { XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED, "norepair" }
+
DECLARE_EVENT_CLASS(xchk_class,
TP_PROTO(struct xfs_inode *ip, struct xfs_scrub_metadata *sm,
int error),
@@ -103,14 +117,14 @@ DECLARE_EVENT_CLASS(xchk_class,
__entry->flags = sm->sm_flags;
__entry->error = error;
),
- TP_printk("dev %d:%d ino 0x%llx type %s agno %u inum %llu gen %u flags 0x%x error %d",
+ TP_printk("dev %d:%d ino 0x%llx type %s agno 0x%x inum 0x%llx gen 0x%x flags (%s) error %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->agno,
__entry->inum,
__entry->gen,
- __entry->flags,
+ __print_flags(__entry->flags, "|", XFS_SCRUB_FLAG_STRINGS),
__entry->error)
)
#define DEFINE_SCRUB_EVENT(name) \
@@ -145,7 +159,7 @@ TRACE_EVENT(xchk_op_error,
__entry->error = error;
__entry->ret_ip = ret_ip;
),
- TP_printk("dev %d:%d type %s agno %u agbno %u error %d ret_ip %pS",
+ TP_printk("dev %d:%d type %s agno 0x%x agbno 0x%x error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->agno,
@@ -176,10 +190,10 @@ TRACE_EVENT(xchk_file_op_error,
__entry->error = error;
__entry->ret_ip = ret_ip;
),
- TP_printk("dev %d:%d ino 0x%llx fork %d type %s offset %llu error %d ret_ip %pS",
+ TP_printk("dev %d:%d ino 0x%llx fork %s type %s fileoff 0x%llx error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
- __entry->whichfork,
+ __print_symbolic(__entry->whichfork, XFS_WHICHFORK_STRINGS),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->offset,
__entry->error,
@@ -193,29 +207,21 @@ DECLARE_EVENT_CLASS(xchk_block_error_class,
__field(dev_t, dev)
__field(unsigned int, type)
__field(xfs_agnumber_t, agno)
- __field(xfs_agblock_t, bno)
+ __field(xfs_agblock_t, agbno)
__field(void *, ret_ip)
),
TP_fast_assign(
- xfs_fsblock_t fsbno;
- xfs_agnumber_t agno;
- xfs_agblock_t bno;
-
- fsbno = XFS_DADDR_TO_FSB(sc->mp, daddr);
- agno = XFS_FSB_TO_AGNO(sc->mp, fsbno);
- bno = XFS_FSB_TO_AGBNO(sc->mp, fsbno);
-
__entry->dev = sc->mp->m_super->s_dev;
__entry->type = sc->sm->sm_type;
- __entry->agno = agno;
- __entry->bno = bno;
+ __entry->agno = xfs_daddr_to_agno(sc->mp, daddr);
+ __entry->agbno = xfs_daddr_to_agbno(sc->mp, daddr);
__entry->ret_ip = ret_ip;
),
- TP_printk("dev %d:%d type %s agno %u agbno %u ret_ip %pS",
+ TP_printk("dev %d:%d type %s agno 0x%x agbno 0x%x ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->agno,
- __entry->bno,
+ __entry->agbno,
__entry->ret_ip)
)
@@ -281,10 +287,10 @@ DECLARE_EVENT_CLASS(xchk_fblock_error_class,
__entry->offset = offset;
__entry->ret_ip = ret_ip;
),
- TP_printk("dev %d:%d ino 0x%llx fork %d type %s offset %llu ret_ip %pS",
+ TP_printk("dev %d:%d ino 0x%llx fork %s type %s fileoff 0x%llx ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
- __entry->whichfork,
+ __print_symbolic(__entry->whichfork, XFS_WHICHFORK_STRINGS),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->offset,
__entry->ret_ip)
@@ -346,7 +352,7 @@ TRACE_EVENT(xchk_btree_op_error,
__entry->error = error;
__entry->ret_ip = ret_ip;
),
- TP_printk("dev %d:%d type %s btree %s level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
+ TP_printk("dev %d:%d type %s btree %s level %d ptr %d agno 0x%x agbno 0x%x error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
@@ -389,10 +395,10 @@ TRACE_EVENT(xchk_ifork_btree_op_error,
__entry->error = error;
__entry->ret_ip = ret_ip;
),
- TP_printk("dev %d:%d ino 0x%llx fork %d type %s btree %s level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
+ TP_printk("dev %d:%d ino 0x%llx fork %s type %s btree %s level %d ptr %d agno 0x%x agbno 0x%x error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
- __entry->whichfork,
+ __print_symbolic(__entry->whichfork, XFS_WHICHFORK_STRINGS),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->level,
@@ -428,7 +434,7 @@ TRACE_EVENT(xchk_btree_error,
__entry->ptr = cur->bc_ptrs[level];
__entry->ret_ip = ret_ip;
),
- TP_printk("dev %d:%d type %s btree %s level %d ptr %d agno %u agbno %u ret_ip %pS",
+ TP_printk("dev %d:%d type %s btree %s level %d ptr %d agno 0x%x agbno 0x%x ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
@@ -468,10 +474,10 @@ TRACE_EVENT(xchk_ifork_btree_error,
__entry->ptr = cur->bc_ptrs[level];
__entry->ret_ip = ret_ip;
),
- TP_printk("dev %d:%d ino 0x%llx fork %d type %s btree %s level %d ptr %d agno %u agbno %u ret_ip %pS",
+ TP_printk("dev %d:%d ino 0x%llx fork %s type %s btree %s level %d ptr %d agno 0x%x agbno 0x%x ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
- __entry->whichfork,
+ __print_symbolic(__entry->whichfork, XFS_WHICHFORK_STRINGS),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->level,
@@ -507,7 +513,7 @@ DECLARE_EVENT_CLASS(xchk_sbtree_class,
__entry->nlevels = cur->bc_nlevels;
__entry->ptr = cur->bc_ptrs[level];
),
- TP_printk("dev %d:%d type %s btree %s agno %u agbno %u level %d nlevels %d ptr %d",
+ TP_printk("dev %d:%d type %s btree %s agno 0x%x agbno 0x%x level %d nlevels %d ptr %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
@@ -580,7 +586,7 @@ TRACE_EVENT(xchk_iallocbt_check_cluster,
__entry->holemask = holemask;
__entry->cluster_ino = cluster_ino;
),
- TP_printk("dev %d:%d agno %d startino %u daddr 0x%llx len %d chunkino %u nr_inodes %u cluster_mask 0x%x holemask 0x%x cluster_ino %u",
+ TP_printk("dev %d:%d agno 0x%x startino 0x%x daddr 0x%llx bbcount 0x%x chunkino 0x%x nr_inodes %u cluster_mask 0x%x holemask 0x%x cluster_ino 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->startino,
@@ -670,7 +676,7 @@ DECLARE_EVENT_CLASS(xrep_extent_class,
__entry->agbno = agbno;
__entry->len = len;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -707,7 +713,7 @@ DECLARE_EVENT_CLASS(xrep_rmap_class,
__entry->offset = offset;
__entry->flags = flags;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%x",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x owner 0x%llx fileoff 0x%llx flags 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -745,7 +751,7 @@ TRACE_EVENT(xrep_refcount_extent_fn,
__entry->blockcount = irec->rc_blockcount;
__entry->refcount = irec->rc_refcount;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->startblock,
@@ -769,7 +775,7 @@ TRACE_EVENT(xrep_init_btblock,
__entry->agbno = agbno;
__entry->btnum = btnum;
),
- TP_printk("dev %d:%d agno %u agbno %u btree %s",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x btree %s",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -793,7 +799,7 @@ TRACE_EVENT(xrep_findroot_block,
__entry->magic = magic;
__entry->level = level;
),
- TP_printk("dev %d:%d agno %u agbno %u magic 0x%x level %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x magic 0x%x level %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -821,7 +827,7 @@ TRACE_EVENT(xrep_calc_ag_resblks,
__entry->freelen = freelen;
__entry->usedlen = usedlen;
),
- TP_printk("dev %d:%d agno %d icount %u aglen %u freelen %u usedlen %u",
+ TP_printk("dev %d:%d agno 0x%x icount %u aglen %u freelen %u usedlen %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->icount,
@@ -850,7 +856,7 @@ TRACE_EVENT(xrep_calc_ag_resblks_btsize,
__entry->rmapbt_sz = rmapbt_sz;
__entry->refcbt_sz = refcbt_sz;
),
- TP_printk("dev %d:%d agno %d bno %u ino %u rmap %u refcount %u",
+ TP_printk("dev %d:%d agno 0x%x bnobt %u inobt %u rmapbt %u refcountbt %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->bnobt_sz,
@@ -894,7 +900,7 @@ TRACE_EVENT(xrep_ialloc_insert,
__entry->freecount = freecount;
__entry->freemask = freemask;
),
- TP_printk("dev %d:%d agno %d startino %u holemask 0x%x count %u freecount %u freemask 0x%llx",
+ TP_printk("dev %d:%d agno 0x%x startino 0x%x holemask 0x%x count %u freecount %u freemask 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->startino,
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index d02bef24b32b..5c52ee869272 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -125,7 +125,7 @@ xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl)
}
struct posix_acl *
-xfs_get_acl(struct inode *inode, int type)
+xfs_get_acl(struct inode *inode, int type, bool rcu)
{
struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
@@ -137,6 +137,9 @@ xfs_get_acl(struct inode *inode, int type)
};
int error;
+ if (rcu)
+ return ERR_PTR(-ECHILD);
+
trace_xfs_get_acl(ip);
switch (type) {
@@ -232,7 +235,7 @@ xfs_acl_set_mode(
inode->i_ctime = current_time(inode);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
- if (mp->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(mp))
xfs_trans_set_sync(tp);
return xfs_trans_commit(tp);
}
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 7bdb3a4ed798..bb6abdcb265d 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -10,13 +10,13 @@ struct inode;
struct posix_acl;
#ifdef CONFIG_XFS_POSIX_ACL
-extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
+extern struct posix_acl *xfs_get_acl(struct inode *inode, int type, bool rcu);
extern int xfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
struct posix_acl *acl, int type);
extern int __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
void xfs_forget_acl(struct inode *inode, const char *name);
#else
-static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
+static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type, bool rcu)
{
return NULL;
}
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index cb4e0fcf4c76..34fc6148032a 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -97,7 +97,7 @@ xfs_end_ioend(
/*
* Just clean up the in-memory structures if the fs has been shut down.
*/
- if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+ if (xfs_is_shutdown(ip->i_mount)) {
error = -EIO;
goto done;
}
@@ -260,7 +260,7 @@ xfs_map_blocks(
int retries = 0;
int error = 0;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
/*
@@ -440,7 +440,7 @@ xfs_discard_page(
xfs_fileoff_t pageoff_fsb = XFS_B_TO_FSBT(mp, pageoff);
int error;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
goto out_invalidate;
xfs_alert_ratelimited(mp,
@@ -449,7 +449,7 @@ xfs_discard_page(
error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
i_blocks_per_page(inode, page) - pageoff_fsb);
- if (error && !XFS_FORCED_SHUTDOWN(mp))
+ if (error && !xfs_is_shutdown(mp))
xfs_alert(mp, "page discard unable to remove delalloc mapping.");
out_invalidate:
iomap_invalidatepage(page, pageoff, PAGE_SIZE - pageoff);
@@ -462,22 +462,6 @@ static const struct iomap_writeback_ops xfs_writeback_ops = {
};
STATIC int
-xfs_vm_writepage(
- struct page *page,
- struct writeback_control *wbc)
-{
- struct xfs_writepage_ctx wpc = { };
-
- if (WARN_ON_ONCE(current->journal_info)) {
- redirty_page_for_writepage(wbc, page);
- unlock_page(page);
- return 0;
- }
-
- return iomap_writepage(page, wbc, &wpc.ctx, &xfs_writeback_ops);
-}
-
-STATIC int
xfs_vm_writepages(
struct address_space *mapping,
struct writeback_control *wbc)
@@ -559,7 +543,6 @@ xfs_iomap_swapfile_activate(
const struct address_space_operations xfs_address_space_operations = {
.readpage = xfs_vm_readpage,
.readahead = xfs_vm_readahead,
- .writepage = xfs_vm_writepage,
.writepages = xfs_vm_writepages,
.set_page_dirty = __set_page_dirty_nobuffers,
.releasepage = iomap_releasepage,
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
index aaa7e66c42d7..2b5da6218977 100644
--- a/fs/xfs/xfs_attr_inactive.c
+++ b/fs/xfs/xfs_attr_inactive.c
@@ -151,7 +151,7 @@ xfs_attr3_node_inactive(
}
xfs_da3_node_hdr_from_disk(dp->i_mount, &ichdr, bp->b_addr);
- parent_blkno = bp->b_bn;
+ parent_blkno = xfs_buf_daddr(bp);
if (!ichdr.count) {
xfs_trans_brelse(*trans, bp);
return 0;
@@ -177,7 +177,7 @@ xfs_attr3_node_inactive(
return error;
/* save for re-read later */
- child_blkno = XFS_BUF_ADDR(child_bp);
+ child_blkno = xfs_buf_daddr(child_bp);
/*
* Invalidate the subtree, however we have to.
@@ -271,7 +271,7 @@ xfs_attr3_root_inactive(
error = xfs_da3_node_read(*trans, dp, 0, &bp, XFS_ATTR_FORK);
if (error)
return error;
- blkno = bp->b_bn;
+ blkno = xfs_buf_daddr(bp);
/*
* Invalidate the tree, even if the "tree" is only a single leaf block.
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index 25dcc98d50e6..2d1e5134cebe 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -529,7 +529,7 @@ xfs_attr_list(
XFS_STATS_INC(dp->i_mount, xs_attr_list);
- if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+ if (xfs_is_shutdown(dp->i_mount))
return -EIO;
lock_mode = xfs_ilock_attr_map_shared(dp);
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index e3a691937e92..03159970133f 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -24,7 +24,6 @@
#include "xfs_error.h"
#include "xfs_log_priv.h"
#include "xfs_log_recover.h"
-#include "xfs_quota.h"
kmem_zone_t *xfs_bui_zone;
kmem_zone_t *xfs_bud_zone;
@@ -487,18 +486,10 @@ xfs_bui_item_recover(
XFS_ATTR_FORK : XFS_DATA_FORK;
bui_type = bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK;
- /* Grab the inode. */
- error = xfs_iget(mp, NULL, bmap->me_owner, 0, 0, &ip);
+ error = xlog_recover_iget(mp, bmap->me_owner, &ip);
if (error)
return error;
- error = xfs_qm_dqattach(ip);
- if (error)
- goto err_rele;
-
- if (VFS_I(ip)->i_nlink == 0)
- xfs_iflags_set(ip, XFS_IRECOVERY);
-
/* Allocate transaction and do the work. */
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
@@ -522,6 +513,9 @@ xfs_bui_item_recover(
error = xfs_trans_log_finish_bmap_update(tp, budp, bui_type, ip,
whichfork, bmap->me_startoff, bmap->me_startblock,
&count, state);
+ if (error == -EFSCORRUPTED)
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bmap,
+ sizeof(*bmap));
if (error)
goto err_cancel;
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 1cd3f940fa6a..73a36b7be3bd 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -731,7 +731,7 @@ xfs_free_eofblocks(
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
if (error) {
- ASSERT(XFS_FORCED_SHUTDOWN(mp));
+ ASSERT(xfs_is_shutdown(mp));
return error;
}
@@ -789,7 +789,7 @@ xfs_alloc_file_space(
trace_xfs_alloc_file_space(ip);
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
error = xfs_qm_dqattach(ip);
@@ -1282,7 +1282,7 @@ xfs_swap_extents_check_format(
* If we have to use the (expensive) rmap swap method, we can
* handle any number of extents and any format.
*/
- if (xfs_sb_version_hasrmapbt(&ip->i_mount->m_sb))
+ if (xfs_has_rmapbt(ip->i_mount))
return 0;
/*
@@ -1516,7 +1516,7 @@ xfs_swap_extent_forks(
* event of a crash. Set the owner change log flags now and leave the
* bmbt scan as the last step.
*/
- if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
+ if (xfs_has_v3inodes(ip->i_mount)) {
if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE)
(*target_log_flags) |= XFS_ILOG_DOWNER;
if (tip->i_df.if_format == XFS_DINODE_FMT_BTREE)
@@ -1553,7 +1553,7 @@ xfs_swap_extent_forks(
(*src_log_flags) |= XFS_ILOG_DEXT;
break;
case XFS_DINODE_FMT_BTREE:
- ASSERT(!xfs_sb_version_has_v3inode(&ip->i_mount->m_sb) ||
+ ASSERT(!xfs_has_v3inodes(ip->i_mount) ||
(*src_log_flags & XFS_ILOG_DOWNER));
(*src_log_flags) |= XFS_ILOG_DBROOT;
break;
@@ -1565,7 +1565,7 @@ xfs_swap_extent_forks(
break;
case XFS_DINODE_FMT_BTREE:
(*target_log_flags) |= XFS_ILOG_DBROOT;
- ASSERT(!xfs_sb_version_has_v3inode(&ip->i_mount->m_sb) ||
+ ASSERT(!xfs_has_v3inodes(ip->i_mount) ||
(*target_log_flags & XFS_ILOG_DOWNER));
break;
}
@@ -1678,7 +1678,7 @@ xfs_swap_extents(
* a block reservation because it's really just a remap operation
* performed with log redo items!
*/
- if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ if (xfs_has_rmapbt(mp)) {
int w = XFS_DATA_FORK;
uint32_t ipnext = ip->i_df.if_nextents;
uint32_t tipnext = tip->i_df.if_nextents;
@@ -1759,7 +1759,7 @@ xfs_swap_extents(
src_log_flags = XFS_ILOG_CORE;
target_log_flags = XFS_ILOG_CORE;
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (xfs_has_rmapbt(mp))
error = xfs_swap_extent_rmap(&tp, ip, tip);
else
error = xfs_swap_extent_forks(tp, ip, tip, &src_log_flags,
@@ -1778,7 +1778,7 @@ xfs_swap_extents(
}
/* Swap the cow forks. */
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ if (xfs_has_reflink(mp)) {
ASSERT(!ip->i_cowfp ||
ip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
ASSERT(!tip->i_cowfp ||
@@ -1820,7 +1820,7 @@ xfs_swap_extents(
* If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(mp))
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 3ab73567a0f5..5fa6cd947dd4 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -251,7 +251,7 @@ _xfs_buf_alloc(
return error;
}
- bp->b_bn = map[0].bm_bn;
+ bp->b_rhash_key = map[0].bm_bn;
bp->b_length = 0;
for (i = 0; i < nmaps; i++) {
bp->b_maps[i].bm_bn = map[i].bm_bn;
@@ -315,7 +315,6 @@ xfs_buf_alloc_kmem(
struct xfs_buf *bp,
xfs_buf_flags_t flags)
{
- int align_mask = xfs_buftarg_dma_alignment(bp->b_target);
xfs_km_flags_t kmflag_mask = KM_NOFS;
size_t size = BBTOB(bp->b_length);
@@ -323,7 +322,7 @@ xfs_buf_alloc_kmem(
if (!(flags & XBF_READ))
kmflag_mask |= KM_ZERO;
- bp->b_addr = kmem_alloc_io(size, align_mask, kmflag_mask);
+ bp->b_addr = kmem_alloc(size, kmflag_mask);
if (!bp->b_addr)
return -ENOMEM;
@@ -460,7 +459,7 @@ _xfs_buf_obj_cmp(
*/
BUILD_BUG_ON(offsetof(struct xfs_buf_map, bm_bn) != 0);
- if (bp->b_bn != map->bm_bn)
+ if (bp->b_rhash_key != map->bm_bn)
return 1;
if (unlikely(bp->b_length != map->bm_len)) {
@@ -482,7 +481,7 @@ static const struct rhashtable_params xfs_buf_hash_params = {
.min_size = 32, /* empty AGs have minimal footprint */
.nelem_hint = 16,
.key_len = sizeof(xfs_daddr_t),
- .key_offset = offsetof(struct xfs_buf, b_bn),
+ .key_offset = offsetof(struct xfs_buf, b_rhash_key),
.head_offset = offsetof(struct xfs_buf, b_rhash_head),
.automatic_shrinking = true,
.obj_cmpfn = _xfs_buf_obj_cmp,
@@ -814,7 +813,7 @@ xfs_buf_read_map(
* buffer.
*/
if (error) {
- if (!XFS_FORCED_SHUTDOWN(target->bt_mount))
+ if (!xfs_is_shutdown(target->bt_mount))
xfs_buf_ioerror_alert(bp, fa);
bp->b_flags &= ~XBF_DONE;
@@ -854,7 +853,9 @@ xfs_buf_readahead_map(
/*
* Read an uncached buffer from disk. Allocates and returns a locked
- * buffer containing the disk contents or nothing.
+ * buffer containing the disk contents or nothing. Uncached buffers always have
+ * a cache index of XFS_BUF_DADDR_NULL so we can easily determine if the buffer
+ * is cached or uncached during fault diagnosis.
*/
int
xfs_buf_read_uncached(
@@ -876,7 +877,7 @@ xfs_buf_read_uncached(
/* set up the buffer for a read IO */
ASSERT(bp->b_map_count == 1);
- bp->b_bn = XFS_BUF_DADDR_NULL; /* always null for uncached buffers */
+ bp->b_rhash_key = XFS_BUF_DADDR_NULL;
bp->b_maps[0].bm_bn = daddr;
bp->b_flags |= XBF_READ;
bp->b_ops = ops;
@@ -1145,7 +1146,7 @@ xfs_buf_ioerror_permanent(
return true;
/* At unmount we may treat errors differently */
- if ((mp->m_flags & XFS_MOUNT_UNMOUNTING) && mp->m_fail_unmount)
+ if (xfs_is_unmounting(mp) && mp->m_fail_unmount)
return true;
return false;
@@ -1179,7 +1180,7 @@ xfs_buf_ioend_handle_error(
* If we've already decided to shutdown the filesystem because of I/O
* errors, there's no point in giving this a retry.
*/
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
goto out_stale;
xfs_buf_ioerror_alert_ratelimited(bp);
@@ -1336,7 +1337,7 @@ xfs_buf_ioerror_alert(
{
xfs_buf_alert_ratelimited(bp, "XFS: metadata IO error",
"metadata I/O error in \"%pS\" at daddr 0x%llx len %d error %d",
- func, (uint64_t)XFS_BUF_ADDR(bp),
+ func, (uint64_t)xfs_buf_daddr(bp),
bp->b_length, -bp->b_error);
}
@@ -1514,17 +1515,18 @@ _xfs_buf_ioapply(
SHUTDOWN_CORRUPT_INCORE);
return;
}
- } else if (bp->b_bn != XFS_BUF_DADDR_NULL) {
+ } else if (bp->b_rhash_key != XFS_BUF_DADDR_NULL) {
struct xfs_mount *mp = bp->b_mount;
/*
* non-crc filesystems don't attach verifiers during
* log recovery, so don't warn for such filesystems.
*/
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
xfs_warn(mp,
"%s: no buf ops on daddr 0x%llx len %d",
- __func__, bp->b_bn, bp->b_length);
+ __func__, xfs_buf_daddr(bp),
+ bp->b_length);
xfs_hex_dump(bp->b_addr,
XFS_CORRUPTION_DUMP_LEN);
dump_stack();
@@ -1592,7 +1594,7 @@ __xfs_buf_submit(
ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
/* on shutdown we stale and complete the buffer immediately */
- if (XFS_FORCED_SHUTDOWN(bp->b_mount)) {
+ if (xfs_is_shutdown(bp->b_mount)) {
xfs_buf_ioend_fail(bp);
return -EIO;
}
@@ -1794,7 +1796,7 @@ xfs_buftarg_drain(
xfs_buf_alert_ratelimited(bp,
"XFS: Corruption Alert",
"Corruption Alert: Buffer at daddr 0x%llx had permanent write failures!",
- (long long)bp->b_bn);
+ (long long)xfs_buf_daddr(bp));
}
xfs_buf_rele(bp);
}
@@ -1809,7 +1811,7 @@ xfs_buftarg_drain(
* down the fs.
*/
if (write_fail) {
- ASSERT(XFS_FORCED_SHUTDOWN(btp->bt_mount));
+ ASSERT(xfs_is_shutdown(btp->bt_mount));
xfs_alert(btp->bt_mount,
"Please run xfs_repair to determine the extent of the problem.");
}
@@ -2302,7 +2304,7 @@ xfs_verify_magic(
struct xfs_mount *mp = bp->b_mount;
int idx;
- idx = xfs_sb_version_hascrc(&mp->m_sb);
+ idx = xfs_has_crc(mp);
if (WARN_ON(!bp->b_ops || !bp->b_ops->magic[idx]))
return false;
return dmagic == bp->b_ops->magic[idx];
@@ -2320,7 +2322,7 @@ xfs_verify_magic16(
struct xfs_mount *mp = bp->b_mount;
int idx;
- idx = xfs_sb_version_hascrc(&mp->m_sb);
+ idx = xfs_has_crc(mp);
if (WARN_ON(!bp->b_ops || !bp->b_ops->magic16[idx]))
return false;
return dmagic == bp->b_ops->magic16[idx];
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index 464dc548fa23..6b0200b8007d 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -133,7 +133,8 @@ struct xfs_buf {
* fast-path on locking.
*/
struct rhash_head b_rhash_head; /* pag buffer hash node */
- xfs_daddr_t b_bn; /* block number of buffer */
+
+ xfs_daddr_t b_rhash_key; /* buffer cache index */
int b_length; /* size of buffer in BBs */
atomic_t b_hold; /* reference count */
atomic_t b_lru_ref; /* lru reclaim ref count */
@@ -296,18 +297,10 @@ extern int xfs_buf_delwri_pushbuf(struct xfs_buf *, struct list_head *);
extern int xfs_buf_init(void);
extern void xfs_buf_terminate(void);
-/*
- * These macros use the IO block map rather than b_bn. b_bn is now really
- * just for the buffer cache index for cached buffers. As IO does not use b_bn
- * anymore, uncached buffers do not use b_bn at all and hence must modify the IO
- * map directly. Uncached buffers are not allowed to be discontiguous, so this
- * is safe to do.
- *
- * In future, uncached buffers will pass the block number directly to the io
- * request function and hence these macros will go away at that point.
- */
-#define XFS_BUF_ADDR(bp) ((bp)->b_maps[0].bm_bn)
-#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_maps[0].bm_bn = (xfs_daddr_t)(bno))
+static inline xfs_daddr_t xfs_buf_daddr(struct xfs_buf *bp)
+{
+ return bp->b_maps[0].bm_bn;
+}
void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref);
@@ -355,12 +348,6 @@ extern int xfs_setsize_buftarg(struct xfs_buftarg *, unsigned int);
#define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev)
#define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev)
-static inline int
-xfs_buftarg_dma_alignment(struct xfs_buftarg *bt)
-{
- return queue_dma_alignment(bt->bt_bdev->bd_disk->queue);
-}
-
int xfs_buf_reverify(struct xfs_buf *bp, const struct xfs_buf_ops *ops);
bool xfs_verify_magic(struct xfs_buf *bp, __be32 dmagic);
bool xfs_verify_magic16(struct xfs_buf *bp, __be16 dmagic);
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 2828ce45b701..b1ab100c09e1 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -428,7 +428,7 @@ xfs_buf_item_format(
* occurs during recovery.
*/
if (bip->bli_flags & XFS_BLI_INODE_BUF) {
- if (xfs_sb_version_has_v3inode(&lip->li_mountp->m_sb) ||
+ if (xfs_has_v3inodes(lip->li_mountp) ||
!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) &&
xfs_log_item_in_current_chkpt(lip)))
bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF;
@@ -581,7 +581,7 @@ xfs_buf_item_push(
if (bp->b_flags & XBF_WRITE_FAIL) {
xfs_buf_alert_ratelimited(bp, "XFS: Failing async write",
"Failing async write on buffer block 0x%llx. Retrying async write.",
- (long long)bp->b_bn);
+ (long long)xfs_buf_daddr(bp));
}
if (!xfs_buf_delwri_queue(bp, buffer_list))
@@ -616,7 +616,7 @@ xfs_buf_item_put(
* that case, the bli is freed on buffer writeback completion.
*/
aborted = test_bit(XFS_LI_ABORTED, &lip->li_flags) ||
- XFS_FORCED_SHUTDOWN(lip->li_mountp);
+ xfs_is_shutdown(lip->li_mountp);
dirty = bip->bli_flags & XFS_BLI_DIRTY;
if (dirty && !aborted)
return false;
diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c
index 4775485b4062..a476c7ef5d53 100644
--- a/fs/xfs/xfs_buf_item_recover.c
+++ b/fs/xfs/xfs_buf_item_recover.c
@@ -219,7 +219,7 @@ xlog_recover_validate_buf_type(
* inconsistent state resulting in verification failures. Hence for now
* just avoid the verification stage for non-crc filesystems
*/
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
return;
magic32 = be32_to_cpu(*(__be32 *)bp->b_addr);
@@ -497,7 +497,7 @@ xlog_recover_do_reg_buffer(
if (fa) {
xfs_alert(mp,
"dquot corrupt at %pS trying to replay into block 0x%llx",
- fa, bp->b_bn);
+ fa, xfs_buf_daddr(bp));
goto next;
}
}
@@ -597,7 +597,7 @@ xlog_recover_do_inode_buffer(
* Post recovery validation only works properly on CRC enabled
* filesystems.
*/
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_has_crc(mp))
bp->b_ops = &xfs_inode_buf_ops;
inodes_per_buf = BBTOB(bp->b_length) >> mp->m_sb.sb_inodelog;
@@ -710,7 +710,7 @@ xlog_recover_get_buf_lsn(
uint16_t blft;
/* v4 filesystems always recover immediately */
- if (!xfs_sb_version_hascrc(&mp->m_sb))
+ if (!xfs_has_crc(mp))
goto recover_immediately;
/*
@@ -787,7 +787,7 @@ xlog_recover_get_buf_lsn(
* the relevant UUID in the superblock.
*/
lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
- if (xfs_sb_version_hasmetauuid(&mp->m_sb))
+ if (xfs_has_metauuid(mp))
uuid = &((struct xfs_dsb *)blk)->sb_meta_uuid;
else
uuid = &((struct xfs_dsb *)blk)->sb_uuid;
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
index da1cc683560c..8310005af00f 100644
--- a/fs/xfs/xfs_dir2_readdir.c
+++ b/fs/xfs/xfs_dir2_readdir.c
@@ -32,7 +32,7 @@ xfs_dir3_get_dtype(
struct xfs_mount *mp,
uint8_t filetype)
{
- if (!xfs_sb_version_hasftype(&mp->m_sb))
+ if (!xfs_has_ftype(mp))
return DT_UNKNOWN;
if (filetype >= XFS_DIR3_FT_MAX)
@@ -512,7 +512,7 @@ xfs_readdir(
trace_xfs_readdir(dp);
- if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+ if (xfs_is_shutdown(dp->i_mount))
return -EIO;
ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index 736df5660f1f..0191de8ce9ce 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -169,7 +169,7 @@ xfs_ioc_trim(
* We haven't recovered the log, so we cannot use our bnobt-guided
* storage zapping commands.
*/
- if (mp->m_flags & XFS_MOUNT_NORECOVERY)
+ if (xfs_has_norecovery(mp))
return -EROFS;
if (copy_from_user(&range, urange, sizeof(range)))
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index ecd5059d6928..c15d61d47a06 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -223,9 +223,9 @@ xfs_qm_init_dquot_blk(
d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
d->dd_diskdq.d_id = cpu_to_be32(curid);
d->dd_diskdq.d_type = type;
- if (curid > 0 && xfs_sb_version_hasbigtime(&mp->m_sb))
+ if (curid > 0 && xfs_has_bigtime(mp))
d->dd_diskdq.d_type |= XFS_DQTYPE_BIGTIME;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid);
xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
XFS_DQUOT_CRC_OFF);
@@ -526,7 +526,7 @@ xfs_dquot_check_type(
* expect an exact match for user dquots and for non-root group and
* project dquots.
*/
- if (xfs_sb_version_hascrc(&dqp->q_mount->m_sb) ||
+ if (xfs_has_crc(dqp->q_mount) ||
dqp_type == XFS_DQTYPE_USER || dqp->q_id != 0)
return ddqp_type == dqp_type;
@@ -847,9 +847,6 @@ xfs_qm_dqget_checks(
struct xfs_mount *mp,
xfs_dqtype_t type)
{
- if (WARN_ON_ONCE(!XFS_IS_QUOTA_RUNNING(mp)))
- return -ESRCH;
-
switch (type) {
case XFS_DQTYPE_USER:
if (!XFS_IS_UQUOTA_ON(mp))
@@ -1222,7 +1219,7 @@ xfs_qm_dqflush_check(
/* bigtime flag should never be set on root dquots */
if (dqp->q_type & XFS_DQTYPE_BIGTIME) {
- if (!xfs_sb_version_hasbigtime(&dqp->q_mount->m_sb))
+ if (!xfs_has_bigtime(dqp->q_mount))
return __this_address;
if (dqp->q_id == 0)
return __this_address;
@@ -1301,7 +1298,7 @@ xfs_qm_dqflush(
* buffer always has a valid CRC. This ensures there is no possibility
* of a dquot without an up-to-date CRC getting to disk.
*/
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
dqblk->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn);
xfs_update_cksum((char *)dqblk, sizeof(struct xfs_dqblk),
XFS_DQUOT_CRC_OFF);
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index f642884a6834..6b5e3cf40c8b 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -54,6 +54,16 @@ struct xfs_dquot_res {
xfs_qwarncnt_t warnings;
};
+static inline bool
+xfs_dquot_res_over_limits(
+ const struct xfs_dquot_res *qres)
+{
+ if ((qres->softlimit && qres->softlimit < qres->reserved) ||
+ (qres->hardlimit && qres->hardlimit < qres->reserved))
+ return true;
+ return false;
+}
+
/*
* The incore dquot structure
*/
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
index 8ed47b739b6c..6a1aae799cf1 100644
--- a/fs/xfs/xfs_dquot_item.c
+++ b/fs/xfs/xfs_dquot_item.c
@@ -218,137 +218,3 @@ xfs_qm_dquot_logitem_init(
&xfs_dquot_item_ops);
lp->qli_dquot = dqp;
}
-
-/*------------------ QUOTAOFF LOG ITEMS -------------------*/
-
-static inline struct xfs_qoff_logitem *QOFF_ITEM(struct xfs_log_item *lip)
-{
- return container_of(lip, struct xfs_qoff_logitem, qql_item);
-}
-
-
-/*
- * This returns the number of iovecs needed to log the given quotaoff item.
- * We only need 1 iovec for an quotaoff item. It just logs the
- * quotaoff_log_format structure.
- */
-STATIC void
-xfs_qm_qoff_logitem_size(
- struct xfs_log_item *lip,
- int *nvecs,
- int *nbytes)
-{
- *nvecs += 1;
- *nbytes += sizeof(struct xfs_qoff_logitem);
-}
-
-STATIC void
-xfs_qm_qoff_logitem_format(
- struct xfs_log_item *lip,
- struct xfs_log_vec *lv)
-{
- struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip);
- struct xfs_log_iovec *vecp = NULL;
- struct xfs_qoff_logformat *qlf;
-
- qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QUOTAOFF);
- qlf->qf_type = XFS_LI_QUOTAOFF;
- qlf->qf_size = 1;
- qlf->qf_flags = qflip->qql_flags;
- xlog_finish_iovec(lv, vecp, sizeof(struct xfs_qoff_logitem));
-}
-
-/*
- * There isn't much you can do to push a quotaoff item. It is simply
- * stuck waiting for the log to be flushed to disk.
- */
-STATIC uint
-xfs_qm_qoff_logitem_push(
- struct xfs_log_item *lip,
- struct list_head *buffer_list)
-{
- return XFS_ITEM_LOCKED;
-}
-
-STATIC xfs_lsn_t
-xfs_qm_qoffend_logitem_committed(
- struct xfs_log_item *lip,
- xfs_lsn_t lsn)
-{
- struct xfs_qoff_logitem *qfe = QOFF_ITEM(lip);
- struct xfs_qoff_logitem *qfs = qfe->qql_start_lip;
-
- xfs_qm_qoff_logitem_relse(qfs);
-
- kmem_free(lip->li_lv_shadow);
- kmem_free(qfe);
- return (xfs_lsn_t)-1;
-}
-
-STATIC void
-xfs_qm_qoff_logitem_release(
- struct xfs_log_item *lip)
-{
- struct xfs_qoff_logitem *qoff = QOFF_ITEM(lip);
-
- if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) {
- if (qoff->qql_start_lip)
- xfs_qm_qoff_logitem_relse(qoff->qql_start_lip);
- xfs_qm_qoff_logitem_relse(qoff);
- }
-}
-
-static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
- .iop_size = xfs_qm_qoff_logitem_size,
- .iop_format = xfs_qm_qoff_logitem_format,
- .iop_committed = xfs_qm_qoffend_logitem_committed,
- .iop_push = xfs_qm_qoff_logitem_push,
- .iop_release = xfs_qm_qoff_logitem_release,
-};
-
-static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
- .iop_size = xfs_qm_qoff_logitem_size,
- .iop_format = xfs_qm_qoff_logitem_format,
- .iop_push = xfs_qm_qoff_logitem_push,
- .iop_release = xfs_qm_qoff_logitem_release,
-};
-
-/*
- * Delete the quotaoff intent from the AIL and free it. On success,
- * this should only be called for the start item. It can be used for
- * either on shutdown or abort.
- */
-void
-xfs_qm_qoff_logitem_relse(
- struct xfs_qoff_logitem *qoff)
-{
- struct xfs_log_item *lip = &qoff->qql_item;
-
- ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags) ||
- test_bit(XFS_LI_ABORTED, &lip->li_flags) ||
- XFS_FORCED_SHUTDOWN(lip->li_mountp));
- xfs_trans_ail_delete(lip, 0);
- kmem_free(lip->li_lv_shadow);
- kmem_free(qoff);
-}
-
-/*
- * Allocate and initialize an quotaoff item of the correct quota type(s).
- */
-struct xfs_qoff_logitem *
-xfs_qm_qoff_logitem_init(
- struct xfs_mount *mp,
- struct xfs_qoff_logitem *start,
- uint flags)
-{
- struct xfs_qoff_logitem *qf;
-
- qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), 0);
-
- xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ?
- &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops);
- qf->qql_item.li_mountp = mp;
- qf->qql_start_lip = start;
- qf->qql_flags = flags;
- return qf;
-}
diff --git a/fs/xfs/xfs_dquot_item.h b/fs/xfs/xfs_dquot_item.h
index 2b86a43d7ce2..794710c24474 100644
--- a/fs/xfs/xfs_dquot_item.h
+++ b/fs/xfs/xfs_dquot_item.h
@@ -9,7 +9,6 @@
struct xfs_dquot;
struct xfs_trans;
struct xfs_mount;
-struct xfs_qoff_logitem;
struct xfs_dq_logitem {
struct xfs_log_item qli_item; /* common portion */
@@ -17,22 +16,6 @@ struct xfs_dq_logitem {
xfs_lsn_t qli_flush_lsn; /* lsn at last flush */
};
-struct xfs_qoff_logitem {
- struct xfs_log_item qql_item; /* common portion */
- struct xfs_qoff_logitem *qql_start_lip; /* qoff-start logitem, if any */
- unsigned int qql_flags;
-};
-
-
void xfs_qm_dquot_logitem_init(struct xfs_dquot *dqp);
-struct xfs_qoff_logitem *xfs_qm_qoff_logitem_init(struct xfs_mount *mp,
- struct xfs_qoff_logitem *start,
- uint flags);
-void xfs_qm_qoff_logitem_relse(struct xfs_qoff_logitem *);
-struct xfs_qoff_logitem *xfs_trans_get_qoff_item(struct xfs_trans *tp,
- struct xfs_qoff_logitem *startqoff,
- uint flags);
-void xfs_trans_log_quotaoff_item(struct xfs_trans *tp,
- struct xfs_qoff_logitem *qlp);
#endif /* __XFS_DQUOT_ITEM_H__ */
diff --git a/fs/xfs/xfs_dquot_item_recover.c b/fs/xfs/xfs_dquot_item_recover.c
index 5875c7e1bd28..8966ba842395 100644
--- a/fs/xfs/xfs_dquot_item_recover.c
+++ b/fs/xfs/xfs_dquot_item_recover.c
@@ -136,7 +136,7 @@ xlog_recover_dquot_commit_pass2(
* If the dquot has an LSN in it, recover the dquot only if it's less
* than the lsn of the transaction we are replaying.
*/
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddq;
xfs_lsn_t lsn = be64_to_cpu(dqb->dd_lsn);
@@ -146,7 +146,7 @@ xlog_recover_dquot_commit_pass2(
}
memcpy(ddq, recddq, item->ri_buf[1].i_len);
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
xfs_update_cksum((char *)ddq, sizeof(struct xfs_dqblk),
XFS_DQUOT_CRC_OFF);
}
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index ce3bc1b291a1..81c445e9489b 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -371,7 +371,7 @@ xfs_buf_corruption_error(
xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR,
"Metadata corruption detected at %pS, %s block 0x%llx",
- fa, bp->b_ops->name, bp->b_bn);
+ fa, bp->b_ops->name, xfs_buf_daddr(bp));
xfs_alert(mp, "Unmount and run xfs_repair");
@@ -402,7 +402,7 @@ xfs_buf_verifier_error(
xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR,
"Metadata %s detected at %pS, %s block 0x%llx %s",
bp->b_error == -EFSBADCRC ? "CRC error" : "corruption",
- fa, bp->b_ops->name, bp->b_bn, name);
+ fa, bp->b_ops->name, xfs_buf_daddr(bp), name);
xfs_alert(mp, "Unmount and run xfs_repair");
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 1717b7508356..5735d5ea87ee 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -75,4 +75,16 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp);
#define XFS_PTAG_FSBLOCK_ZERO 0x00000080
#define XFS_PTAG_VERIFIER_ERROR 0x00000100
+#define XFS_PTAG_STRINGS \
+ { XFS_NO_PTAG, "none" }, \
+ { XFS_PTAG_IFLUSH, "iflush" }, \
+ { XFS_PTAG_LOGRES, "logres" }, \
+ { XFS_PTAG_AILDELETE, "aildelete" }, \
+ { XFS_PTAG_ERROR_REPORT , "error_report" }, \
+ { XFS_PTAG_SHUTDOWN_CORRUPT, "corrupt" }, \
+ { XFS_PTAG_SHUTDOWN_IOERROR, "ioerror" }, \
+ { XFS_PTAG_SHUTDOWN_LOGERROR, "logerror" }, \
+ { XFS_PTAG_FSBLOCK_ZERO, "fsb_zero" }, \
+ { XFS_PTAG_VERIFIER_ERROR, "verifier" }
+
#endif /* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
index 1da59bdff245..1064c2342876 100644
--- a/fs/xfs/xfs_export.c
+++ b/fs/xfs/xfs_export.c
@@ -44,6 +44,7 @@ xfs_fs_encode_fh(
int *max_len,
struct inode *parent)
{
+ struct xfs_mount *mp = XFS_M(inode->i_sb);
struct fid *fid = (struct fid *)fh;
struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh;
int fileid_type;
@@ -63,8 +64,7 @@ xfs_fs_encode_fh(
* large enough filesystem may contain them, thus the slightly
* confusing looking conditional below.
*/
- if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS) ||
- (XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_32BITINODES))
+ if (!xfs_has_small_inums(mp) || xfs_is_inode32(mp))
fileid_type |= XFS_FILEID_TYPE_64FLAG;
/*
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 2424230ca2c3..3f8a0713573a 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -629,6 +629,9 @@ xfs_efi_item_recover(
error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
extp->ext_len,
&XFS_RMAP_OINFO_ANY_OWNER, false);
+ if (error == -EFSCORRUPTED)
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+ extp, sizeof(*extp));
if (error)
goto abort_error;
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 3dfbdcdb0d1c..7aa943edfc02 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -185,7 +185,7 @@ xfs_file_fsync(
if (error)
return error;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
xfs_iflags_clear(ip, XFS_ITRUNCATED);
@@ -318,7 +318,7 @@ xfs_file_read_iter(
XFS_STATS_INC(mp, xs_read_calls);
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
if (IS_DAX(inode))
@@ -462,7 +462,7 @@ xfs_dio_write_end_io(
trace_xfs_end_io_direct_write(ip, offset, size);
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ if (xfs_is_shutdown(ip->i_mount))
return -EIO;
if (error)
@@ -814,7 +814,7 @@ xfs_file_write_iter(
if (ocount == 0)
return 0;
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ if (xfs_is_shutdown(ip->i_mount))
return -EIO;
if (IS_DAX(inode))
@@ -1122,7 +1122,7 @@ static inline bool xfs_file_sync_writes(struct file *filp)
{
struct xfs_inode *ip = XFS_I(file_inode(filp));
- if (ip->i_mount->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(ip->i_mount))
return true;
if (filp->f_flags & (__O_SYNC | O_DSYNC))
return true;
@@ -1153,10 +1153,10 @@ xfs_file_remap_range(
if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
return -EINVAL;
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return -EOPNOTSUPP;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
/* Prepare and then clone file data. */
@@ -1205,7 +1205,7 @@ xfs_file_open(
{
if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
return -EFBIG;
- if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb)))
+ if (xfs_is_shutdown(XFS_M(inode->i_sb)))
return -EIO;
file->f_mode |= FMODE_NOWAIT | FMODE_BUF_RASYNC;
return 0;
@@ -1277,7 +1277,7 @@ xfs_file_llseek(
{
struct inode *inode = file->f_mapping->host;
- if (XFS_FORCED_SHUTDOWN(XFS_I(inode)->i_mount))
+ if (xfs_is_shutdown(XFS_I(inode)->i_mount))
return -EIO;
switch (whence) {
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index eed6ca5f8f91..6a3ce0f6dc9e 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -295,7 +295,7 @@ xfs_filestream_lookup_ag(
* Set the starting AG using the rotor for inode32, otherwise
* use the directory inode's AG.
*/
- if (mp->m_flags & XFS_MOUNT_32BITINODES) {
+ if (xfs_is_inode32(mp)) {
xfs_agnumber_t rotorstep = xfs_rotorstep;
startag = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount;
mp->m_agfrotor = (mp->m_agfrotor + 1) %
diff --git a/fs/xfs/xfs_filestream.h b/fs/xfs/xfs_filestream.h
index 3af963743e4d..403226ebb80b 100644
--- a/fs/xfs/xfs_filestream.h
+++ b/fs/xfs/xfs_filestream.h
@@ -21,7 +21,7 @@ static inline int
xfs_inode_is_filestream(
struct xfs_inode *ip)
{
- return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) ||
+ return xfs_has_filestreams(ip->i_mount) ||
(ip->i_diflags & XFS_DIFLAG_FILESTREAM);
}
diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
index 7d0b09c1366e..48287caad28b 100644
--- a/fs/xfs/xfs_fsmap.c
+++ b/fs/xfs/xfs_fsmap.c
@@ -61,7 +61,7 @@ xfs_fsmap_to_internal(
static int
xfs_fsmap_owner_to_rmap(
struct xfs_rmap_irec *dest,
- struct xfs_fsmap *src)
+ const struct xfs_fsmap *src)
{
if (!(src->fmr_flags & FMR_OF_SPECIAL_OWNER)) {
dest->rm_owner = src->fmr_owner;
@@ -111,8 +111,8 @@ xfs_fsmap_owner_to_rmap(
/* Convert an rmapbt owner into an fsmap owner. */
static int
xfs_fsmap_owner_from_rmap(
- struct xfs_fsmap *dest,
- struct xfs_rmap_irec *src)
+ struct xfs_fsmap *dest,
+ const struct xfs_rmap_irec *src)
{
dest->fmr_flags = 0;
if (!XFS_RMAP_NON_INODE_OWNER(src->rm_owner)) {
@@ -171,7 +171,7 @@ struct xfs_getfsmap_info {
struct xfs_getfsmap_dev {
u32 dev;
int (*fn)(struct xfs_trans *tp,
- struct xfs_fsmap *keys,
+ const struct xfs_fsmap *keys,
struct xfs_getfsmap_info *info);
};
@@ -192,7 +192,7 @@ STATIC int
xfs_getfsmap_is_shared(
struct xfs_trans *tp,
struct xfs_getfsmap_info *info,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
bool *stat)
{
struct xfs_mount *mp = tp->t_mountp;
@@ -202,7 +202,7 @@ xfs_getfsmap_is_shared(
int error;
*stat = false;
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return 0;
/* rt files will have no perag structure */
if (!info->pag)
@@ -245,7 +245,7 @@ STATIC int
xfs_getfsmap_helper(
struct xfs_trans *tp,
struct xfs_getfsmap_info *info,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
xfs_daddr_t rec_daddr)
{
struct xfs_fsmap fmr;
@@ -347,7 +347,7 @@ out:
STATIC int
xfs_getfsmap_datadev_helper(
struct xfs_btree_cur *cur,
- struct xfs_rmap_irec *rec,
+ const struct xfs_rmap_irec *rec,
void *priv)
{
struct xfs_mount *mp = cur->bc_mp;
@@ -365,7 +365,7 @@ xfs_getfsmap_datadev_helper(
STATIC int
xfs_getfsmap_datadev_bnobt_helper(
struct xfs_btree_cur *cur,
- struct xfs_alloc_rec_incore *rec,
+ const struct xfs_alloc_rec_incore *rec,
void *priv)
{
struct xfs_mount *mp = cur->bc_mp;
@@ -389,7 +389,7 @@ xfs_getfsmap_datadev_bnobt_helper(
static void
xfs_getfsmap_set_irec_flags(
struct xfs_rmap_irec *irec,
- struct xfs_fsmap *fmr)
+ const struct xfs_fsmap *fmr)
{
irec->rm_flags = 0;
if (fmr->fmr_flags & FMR_OF_ATTR_FORK)
@@ -404,7 +404,7 @@ xfs_getfsmap_set_irec_flags(
STATIC int
xfs_getfsmap_logdev(
struct xfs_trans *tp,
- struct xfs_fsmap *keys,
+ const struct xfs_fsmap *keys,
struct xfs_getfsmap_info *info)
{
struct xfs_mount *mp = tp->t_mountp;
@@ -451,7 +451,7 @@ xfs_getfsmap_logdev(
STATIC int
xfs_getfsmap_rtdev_rtbitmap_helper(
struct xfs_trans *tp,
- struct xfs_rtalloc_rec *rec,
+ const struct xfs_rtalloc_rec *rec,
void *priv)
{
struct xfs_mount *mp = tp->t_mountp;
@@ -473,7 +473,7 @@ xfs_getfsmap_rtdev_rtbitmap_helper(
STATIC int
__xfs_getfsmap_rtdev(
struct xfs_trans *tp,
- struct xfs_fsmap *keys,
+ const struct xfs_fsmap *keys,
int (*query_fn)(struct xfs_trans *,
struct xfs_getfsmap_info *),
struct xfs_getfsmap_info *info)
@@ -481,16 +481,14 @@ __xfs_getfsmap_rtdev(
struct xfs_mount *mp = tp->t_mountp;
xfs_fsblock_t start_fsb;
xfs_fsblock_t end_fsb;
- xfs_daddr_t eofs;
+ uint64_t eofs;
int error = 0;
eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
if (keys[0].fmr_physical >= eofs)
return 0;
- if (keys[1].fmr_physical >= eofs)
- keys[1].fmr_physical = eofs - 1;
start_fsb = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
- end_fsb = XFS_BB_TO_FSB(mp, keys[1].fmr_physical);
+ end_fsb = XFS_BB_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
/* Set up search keys */
info->low.rm_startblock = start_fsb;
@@ -523,27 +521,37 @@ xfs_getfsmap_rtdev_rtbitmap_query(
{
struct xfs_rtalloc_rec alow = { 0 };
struct xfs_rtalloc_rec ahigh = { 0 };
+ struct xfs_mount *mp = tp->t_mountp;
int error;
- xfs_ilock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
+ xfs_ilock(mp->m_rbmip, XFS_ILOCK_SHARED);
+ /*
+ * Set up query parameters to return free rtextents covering the range
+ * we want.
+ */
alow.ar_startext = info->low.rm_startblock;
ahigh.ar_startext = info->high.rm_startblock;
- do_div(alow.ar_startext, tp->t_mountp->m_sb.sb_rextsize);
- if (do_div(ahigh.ar_startext, tp->t_mountp->m_sb.sb_rextsize))
+ do_div(alow.ar_startext, mp->m_sb.sb_rextsize);
+ if (do_div(ahigh.ar_startext, mp->m_sb.sb_rextsize))
ahigh.ar_startext++;
error = xfs_rtalloc_query_range(tp, &alow, &ahigh,
xfs_getfsmap_rtdev_rtbitmap_helper, info);
if (error)
goto err;
- /* Report any gaps at the end of the rtbitmap */
+ /*
+ * Report any gaps at the end of the rtbitmap by simulating a null
+ * rmap starting at the block after the end of the query range.
+ */
info->last = true;
+ ahigh.ar_startext = min(mp->m_sb.sb_rextents, ahigh.ar_startext);
+
error = xfs_getfsmap_rtdev_rtbitmap_helper(tp, &ahigh, info);
if (error)
goto err;
err:
- xfs_iunlock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
+ xfs_iunlock(mp->m_rbmip, XFS_ILOCK_SHARED);
return error;
}
@@ -551,7 +559,7 @@ err:
STATIC int
xfs_getfsmap_rtdev_rtbitmap(
struct xfs_trans *tp,
- struct xfs_fsmap *keys,
+ const struct xfs_fsmap *keys,
struct xfs_getfsmap_info *info)
{
info->missing_owner = XFS_FMR_OWN_UNKNOWN;
@@ -564,7 +572,7 @@ xfs_getfsmap_rtdev_rtbitmap(
STATIC int
__xfs_getfsmap_datadev(
struct xfs_trans *tp,
- struct xfs_fsmap *keys,
+ const struct xfs_fsmap *keys,
struct xfs_getfsmap_info *info,
int (*query_fn)(struct xfs_trans *,
struct xfs_getfsmap_info *,
@@ -579,16 +587,14 @@ __xfs_getfsmap_datadev(
xfs_fsblock_t end_fsb;
xfs_agnumber_t start_ag;
xfs_agnumber_t end_ag;
- xfs_daddr_t eofs;
+ uint64_t eofs;
int error = 0;
eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
if (keys[0].fmr_physical >= eofs)
return 0;
- if (keys[1].fmr_physical >= eofs)
- keys[1].fmr_physical = eofs - 1;
start_fsb = XFS_DADDR_TO_FSB(mp, keys[0].fmr_physical);
- end_fsb = XFS_DADDR_TO_FSB(mp, keys[1].fmr_physical);
+ end_fsb = XFS_DADDR_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
/*
* Convert the fsmap low/high keys to AG based keys. Initialize
@@ -716,7 +722,7 @@ xfs_getfsmap_datadev_rmapbt_query(
STATIC int
xfs_getfsmap_datadev_rmapbt(
struct xfs_trans *tp,
- struct xfs_fsmap *keys,
+ const struct xfs_fsmap *keys,
struct xfs_getfsmap_info *info)
{
info->missing_owner = XFS_FMR_OWN_FREE;
@@ -751,7 +757,7 @@ xfs_getfsmap_datadev_bnobt_query(
STATIC int
xfs_getfsmap_datadev_bnobt(
struct xfs_trans *tp,
- struct xfs_fsmap *keys,
+ const struct xfs_fsmap *keys,
struct xfs_getfsmap_info *info)
{
struct xfs_alloc_rec_incore akeys[2];
@@ -859,7 +865,7 @@ xfs_getfsmap(
return -EINVAL;
use_rmap = capable(CAP_SYS_ADMIN) &&
- xfs_sb_version_hasrmapbt(&mp->m_sb);
+ xfs_has_rmapbt(mp);
head->fmh_entries = 0;
/* Set up our device handlers. */
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 6ed29b158312..33e26690a8c4 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -19,6 +19,7 @@
#include "xfs_log.h"
#include "xfs_ag.h"
#include "xfs_ag_resv.h"
+#include "xfs_trace.h"
/*
* Write new AG headers to disk. Non-transactional, but need to be
@@ -177,7 +178,7 @@ xfs_growfs_data_private(
* particularly important for shrink because the write verifier
* will fail if sb_fdblocks is ever larger than sb_dblocks.
*/
- if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ if (xfs_has_lazysbcount(mp))
xfs_log_sb(tp);
xfs_trans_set_sync(tp);
@@ -511,6 +512,11 @@ xfs_fs_goingdown(
* consistent. We don't do an unmount here; just shutdown the shop, make sure
* that absolutely nothing persistent happens to this filesystem after this
* point.
+ *
+ * The shutdown state change is atomic, resulting in the first and only the
+ * first shutdown call processing the shutdown. This means we only shutdown the
+ * log once as it requires, and we don't spam the logs when multiple concurrent
+ * shutdowns race to set the shutdown flags.
*/
void
xfs_do_force_shutdown(
@@ -519,48 +525,37 @@ xfs_do_force_shutdown(
char *fname,
int lnnum)
{
- bool logerror = flags & SHUTDOWN_LOG_IO_ERROR;
-
- /*
- * No need to duplicate efforts.
- */
- if (XFS_FORCED_SHUTDOWN(mp) && !logerror)
- return;
-
- /*
- * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't
- * queue up anybody new on the log reservations, and wakes up
- * everybody who's sleeping on log reservations to tell them
- * the bad news.
- */
- if (xfs_log_force_umount(mp, logerror))
- return;
+ int tag;
+ const char *why;
- if (flags & SHUTDOWN_FORCE_UMOUNT) {
- xfs_alert(mp,
-"User initiated shutdown (0x%x) received. Shutting down filesystem",
- flags);
+ if (test_and_set_bit(XFS_OPSTATE_SHUTDOWN, &mp->m_opstate))
return;
- }
-
- if (flags & SHUTDOWN_CORRUPT_INCORE) {
- xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT,
-"Corruption of in-memory data (0x%x) detected at %pS (%s:%d). Shutting down filesystem",
- flags, __return_address, fname, lnnum);
- if (XFS_ERRLEVEL_HIGH <= xfs_error_level)
- xfs_stack_trace();
- } else if (logerror) {
- xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR,
-"Log I/O error (0x%x) detected at %pS (%s:%d). Shutting down filesystem",
- flags, __return_address, fname, lnnum);
+ if (mp->m_sb_bp)
+ mp->m_sb_bp->b_flags |= XBF_DONE;
+
+ if (flags & SHUTDOWN_FORCE_UMOUNT)
+ xfs_alert(mp, "User initiated shutdown received.");
+
+ if (xlog_force_shutdown(mp->m_log, flags)) {
+ tag = XFS_PTAG_SHUTDOWN_LOGERROR;
+ why = "Log I/O Error";
+ } else if (flags & SHUTDOWN_CORRUPT_INCORE) {
+ tag = XFS_PTAG_SHUTDOWN_CORRUPT;
+ why = "Corruption of in-memory data";
} else {
- xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
-"I/O error (0x%x) detected at %pS (%s:%d). Shutting down filesystem",
- flags, __return_address, fname, lnnum);
+ tag = XFS_PTAG_SHUTDOWN_IOERROR;
+ why = "Metadata I/O Error";
}
+ trace_xfs_force_shutdown(mp, tag, flags, fname, lnnum);
+
+ xfs_alert_tag(mp, tag,
+"%s (0x%x) detected at %pS (%s:%d). Shutting down filesystem.",
+ why, flags, __return_address, fname, lnnum);
xfs_alert(mp,
"Please unmount the filesystem and rectify the problem(s)");
+ if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
+ xfs_stack_trace();
}
/*
diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c
index eb10eacabc8f..72a075bb2c10 100644
--- a/fs/xfs/xfs_health.c
+++ b/fs/xfs/xfs_health.c
@@ -30,7 +30,7 @@ xfs_health_unmount(
unsigned int checked = 0;
bool warn = false;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return;
/* Measure AG corruption levels. */
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 6007683482c6..f2210d927481 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -38,23 +38,11 @@
* radix tree tags when convenient. Avoid existing XFS_IWALK namespace.
*/
enum xfs_icwalk_goal {
- /* Goals that are not related to tags; these must be < 0. */
- XFS_ICWALK_DQRELE = -1,
-
/* Goals directly associated with tagged inodes. */
XFS_ICWALK_BLOCKGC = XFS_ICI_BLOCKGC_TAG,
XFS_ICWALK_RECLAIM = XFS_ICI_RECLAIM_TAG,
};
-#define XFS_ICWALK_NULL_TAG (-1U)
-
-/* Compute the inode radix tree tag for this goal. */
-static inline unsigned int
-xfs_icwalk_tag(enum xfs_icwalk_goal goal)
-{
- return goal < 0 ? XFS_ICWALK_NULL_TAG : goal;
-}
-
static int xfs_icwalk(struct xfs_mount *mp,
enum xfs_icwalk_goal goal, struct xfs_icwalk *icw);
static int xfs_icwalk_ag(struct xfs_perag *pag,
@@ -64,9 +52,6 @@ static int xfs_icwalk_ag(struct xfs_perag *pag,
* Private inode cache walk flags for struct xfs_icwalk. Must not
* coincide with XFS_ICWALK_FLAGS_VALID.
*/
-#define XFS_ICWALK_FLAG_DROP_UDQUOT (1U << 31)
-#define XFS_ICWALK_FLAG_DROP_GDQUOT (1U << 30)
-#define XFS_ICWALK_FLAG_DROP_PDQUOT (1U << 29)
/* Stop scanning after icw_scan_limit inodes. */
#define XFS_ICWALK_FLAG_SCAN_LIMIT (1U << 28)
@@ -74,10 +59,7 @@ static int xfs_icwalk_ag(struct xfs_perag *pag,
#define XFS_ICWALK_FLAG_RECLAIM_SICK (1U << 27)
#define XFS_ICWALK_FLAG_UNION (1U << 26) /* union filter algorithm */
-#define XFS_ICWALK_PRIVATE_FLAGS (XFS_ICWALK_FLAG_DROP_UDQUOT | \
- XFS_ICWALK_FLAG_DROP_GDQUOT | \
- XFS_ICWALK_FLAG_DROP_PDQUOT | \
- XFS_ICWALK_FLAG_SCAN_LIMIT | \
+#define XFS_ICWALK_PRIVATE_FLAGS (XFS_ICWALK_FLAG_SCAN_LIMIT | \
XFS_ICWALK_FLAG_RECLAIM_SICK | \
XFS_ICWALK_FLAG_UNION)
@@ -102,8 +84,9 @@ xfs_inode_alloc(
return NULL;
}
- /* VFS doesn't initialise i_mode! */
+ /* VFS doesn't initialise i_mode or i_state! */
VFS_I(ip)->i_mode = 0;
+ VFS_I(ip)->i_state = 0;
XFS_STATS_INC(mp, vn_active);
ASSERT(atomic_read(&ip->i_pincount) == 0);
@@ -220,9 +203,14 @@ static inline void
xfs_blockgc_queue(
struct xfs_perag *pag)
{
+ struct xfs_mount *mp = pag->pag_mount;
+
+ if (!xfs_is_blockgc_enabled(mp))
+ return;
+
rcu_read_lock();
if (radix_tree_tagged(&pag->pag_ici_root, XFS_ICI_BLOCKGC_TAG))
- queue_delayed_work(pag->pag_mount->m_gc_workqueue,
+ queue_delayed_work(pag->pag_mount->m_blockgc_wq,
&pag->pag_blockgc_work,
msecs_to_jiffies(xfs_blockgc_secs * 1000));
rcu_read_unlock();
@@ -301,31 +289,6 @@ xfs_perag_clear_inode_tag(
trace_xfs_perag_clear_inode_tag(mp, pag->pag_agno, tag, _RET_IP_);
}
-/*
- * We set the inode flag atomically with the radix tree tag.
- * Once we get tag lookups on the radix tree, this inode flag
- * can go away.
- */
-void
-xfs_inode_mark_reclaimable(
- struct xfs_inode *ip)
-{
- struct xfs_mount *mp = ip->i_mount;
- struct xfs_perag *pag;
-
- pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
- spin_lock(&pag->pag_ici_lock);
- spin_lock(&ip->i_flags_lock);
-
- xfs_perag_set_inode_tag(pag, XFS_INO_TO_AGINO(mp, ip->i_ino),
- XFS_ICI_RECLAIM_TAG);
- __xfs_iflags_set(ip, XFS_IRECLAIMABLE);
-
- spin_unlock(&ip->i_flags_lock);
- spin_unlock(&pag->pag_ici_lock);
- xfs_perag_put(pag);
-}
-
static inline void
xfs_inew_wait(
struct xfs_inode *ip)
@@ -484,6 +447,21 @@ xfs_iget_check_free_state(
return 0;
}
+/* Make all pending inactivation work start immediately. */
+static void
+xfs_inodegc_queue_all(
+ struct xfs_mount *mp)
+{
+ struct xfs_inodegc *gc;
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ gc = per_cpu_ptr(mp->m_inodegc, cpu);
+ if (!llist_empty(&gc->list))
+ queue_work_on(cpu, mp->m_inodegc_wq, &gc->work);
+ }
+}
+
/*
* Check the validity of the inode we just found it the cache
*/
@@ -516,13 +494,30 @@ xfs_iget_cache_hit(
* reclaimable state, wait for the initialisation to complete
* before continuing.
*
+ * If we're racing with the inactivation worker we also want to wait.
+ * If we're creating a new file, it's possible that the worker
+ * previously marked the inode as free on disk but hasn't finished
+ * updating the incore state yet. The AGI buffer will be dirty and
+ * locked to the icreate transaction, so a synchronous push of the
+ * inodegc workers would result in deadlock. For a regular iget, the
+ * worker is running already, so we might as well wait.
+ *
* XXX(hch): eventually we should do something equivalent to
* wait_on_inode to wait for these flags to be cleared
* instead of polling for it.
*/
- if (ip->i_flags & (XFS_INEW | XFS_IRECLAIM))
+ if (ip->i_flags & (XFS_INEW | XFS_IRECLAIM | XFS_INACTIVATING))
goto out_skip;
+ if (ip->i_flags & XFS_NEED_INACTIVE) {
+ /* Unlinked inodes cannot be re-grabbed. */
+ if (VFS_I(ip)->i_nlink == 0) {
+ error = -ENOENT;
+ goto out_error;
+ }
+ goto out_inodegc_flush;
+ }
+
/*
* Check the inode free state is valid. This also detects lookup
* racing with unlinks.
@@ -570,6 +565,17 @@ out_error:
spin_unlock(&ip->i_flags_lock);
rcu_read_unlock();
return error;
+
+out_inodegc_flush:
+ spin_unlock(&ip->i_flags_lock);
+ rcu_read_unlock();
+ /*
+ * Do not wait for the workers, because the caller could hold an AGI
+ * buffer lock. We're just going to sleep in a loop anyway.
+ */
+ if (xfs_is_inodegc_enabled(mp))
+ xfs_inodegc_queue_all(mp);
+ return -EAGAIN;
}
static int
@@ -597,7 +603,7 @@ xfs_iget_cache_miss(
/*
* For version 5 superblocks, if we are initialising a new inode and we
- * are not utilising the XFS_MOUNT_IKEEP inode cluster mode, we can
+ * are not utilising the XFS_FEAT_IKEEP inode cluster mode, we can
* simply build the new inode core with a random generation number.
*
* For version 4 (and older) superblocks, log recovery is dependent on
@@ -605,8 +611,8 @@ xfs_iget_cache_miss(
* value and hence we must also read the inode off disk even when
* initializing new inodes.
*/
- if (xfs_sb_version_has_v3inode(&mp->m_sb) &&
- (flags & XFS_IGET_CREATE) && !(mp->m_flags & XFS_MOUNT_IKEEP)) {
+ if (xfs_has_v3inodes(mp) &&
+ (flags & XFS_IGET_CREATE) && !xfs_has_ikeep(mp)) {
VFS_I(ip)->i_generation = prandom_u32();
} else {
struct xfs_buf *bp;
@@ -817,97 +823,6 @@ xfs_icache_inode_is_allocated(
return 0;
}
-#ifdef CONFIG_XFS_QUOTA
-/* Decide if we want to grab this inode to drop its dquots. */
-static bool
-xfs_dqrele_igrab(
- struct xfs_inode *ip)
-{
- bool ret = false;
-
- ASSERT(rcu_read_lock_held());
-
- /* Check for stale RCU freed inode */
- spin_lock(&ip->i_flags_lock);
- if (!ip->i_ino)
- goto out_unlock;
-
- /*
- * Skip inodes that are anywhere in the reclaim machinery because we
- * drop dquots before tagging an inode for reclamation.
- */
- if (ip->i_flags & (XFS_IRECLAIM | XFS_IRECLAIMABLE))
- goto out_unlock;
-
- /*
- * The inode looks alive; try to grab a VFS reference so that it won't
- * get destroyed. If we got the reference, return true to say that
- * we grabbed the inode.
- *
- * If we can't get the reference, then we know the inode had its VFS
- * state torn down and hasn't yet entered the reclaim machinery. Since
- * we also know that dquots are detached from an inode before it enters
- * reclaim, we can skip the inode.
- */
- ret = igrab(VFS_I(ip)) != NULL;
-
-out_unlock:
- spin_unlock(&ip->i_flags_lock);
- return ret;
-}
-
-/* Drop this inode's dquots. */
-static void
-xfs_dqrele_inode(
- struct xfs_inode *ip,
- struct xfs_icwalk *icw)
-{
- if (xfs_iflags_test(ip, XFS_INEW))
- xfs_inew_wait(ip);
-
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- if (icw->icw_flags & XFS_ICWALK_FLAG_DROP_UDQUOT) {
- xfs_qm_dqrele(ip->i_udquot);
- ip->i_udquot = NULL;
- }
- if (icw->icw_flags & XFS_ICWALK_FLAG_DROP_GDQUOT) {
- xfs_qm_dqrele(ip->i_gdquot);
- ip->i_gdquot = NULL;
- }
- if (icw->icw_flags & XFS_ICWALK_FLAG_DROP_PDQUOT) {
- xfs_qm_dqrele(ip->i_pdquot);
- ip->i_pdquot = NULL;
- }
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
- xfs_irele(ip);
-}
-
-/*
- * Detach all dquots from incore inodes if we can. The caller must already
- * have dropped the relevant XFS_[UGP]QUOTA_ACTIVE flags so that dquots will
- * not get reattached.
- */
-int
-xfs_dqrele_all_inodes(
- struct xfs_mount *mp,
- unsigned int qflags)
-{
- struct xfs_icwalk icw = { .icw_flags = 0 };
-
- if (qflags & XFS_UQUOTA_ACCT)
- icw.icw_flags |= XFS_ICWALK_FLAG_DROP_UDQUOT;
- if (qflags & XFS_GQUOTA_ACCT)
- icw.icw_flags |= XFS_ICWALK_FLAG_DROP_GDQUOT;
- if (qflags & XFS_PQUOTA_ACCT)
- icw.icw_flags |= XFS_ICWALK_FLAG_DROP_PDQUOT;
-
- return xfs_icwalk(mp, XFS_ICWALK_DQRELE, &icw);
-}
-#else
-# define xfs_dqrele_igrab(ip) (false)
-# define xfs_dqrele_inode(ip, priv) ((void)0)
-#endif /* CONFIG_XFS_QUOTA */
-
/*
* Grab the inode for reclaim exclusively.
*
@@ -976,7 +891,7 @@ xfs_reclaim_inode(
if (xfs_iflags_test_and_set(ip, XFS_IFLUSHING))
goto out_iunlock;
- if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+ if (xfs_is_shutdown(ip->i_mount)) {
xfs_iunpin_wait(ip);
xfs_iflush_abort(ip);
goto reclaim;
@@ -988,6 +903,7 @@ xfs_reclaim_inode(
xfs_iflags_clear(ip, XFS_IFLUSHING);
reclaim:
+ trace_xfs_inode_reclaiming(ip);
/*
* Because we use RCU freeing we need to ensure the inode always appears
@@ -1052,9 +968,8 @@ static inline bool
xfs_want_reclaim_sick(
struct xfs_mount *mp)
{
- return (mp->m_flags & XFS_MOUNT_UNMOUNTING) ||
- (mp->m_flags & XFS_MOUNT_NORECOVERY) ||
- XFS_FORCED_SHUTDOWN(mp);
+ return xfs_is_unmounting(mp) || xfs_has_norecovery(mp) ||
+ xfs_is_shutdown(mp);
}
void
@@ -1447,8 +1362,12 @@ xfs_blockgc_stop(
struct xfs_perag *pag;
xfs_agnumber_t agno;
- for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
+ if (!xfs_clear_blockgc_enabled(mp))
+ return;
+
+ for_each_perag(mp, agno, pag)
cancel_delayed_work_sync(&pag->pag_blockgc_work);
+ trace_xfs_blockgc_stop(mp, __return_address);
}
/* Enable post-EOF and CoW block auto-reclamation. */
@@ -1459,12 +1378,18 @@ xfs_blockgc_start(
struct xfs_perag *pag;
xfs_agnumber_t agno;
+ if (xfs_set_blockgc_enabled(mp))
+ return;
+
+ trace_xfs_blockgc_start(mp, __return_address);
for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
xfs_blockgc_queue(pag);
}
/* Don't try to run block gc on an inode that's in any of these states. */
#define XFS_BLOCKGC_NOGRAB_IFLAGS (XFS_INEW | \
+ XFS_NEED_INACTIVE | \
+ XFS_INACTIVATING | \
XFS_IRECLAIMABLE | \
XFS_IRECLAIM)
/*
@@ -1490,7 +1415,7 @@ xfs_blockgc_igrab(
spin_unlock(&ip->i_flags_lock);
/* nothing to sync during shutdown */
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ if (xfs_is_shutdown(ip->i_mount))
return false;
/* If we can't grab the inode, it must on it's way to reclaim. */
@@ -1536,27 +1461,62 @@ xfs_blockgc_worker(
struct xfs_mount *mp = pag->pag_mount;
int error;
- if (!sb_start_write_trylock(mp->m_super))
- return;
+ trace_xfs_blockgc_worker(mp, __return_address);
+
error = xfs_icwalk_ag(pag, XFS_ICWALK_BLOCKGC, NULL);
if (error)
xfs_info(mp, "AG %u preallocation gc worker failed, err=%d",
pag->pag_agno, error);
- sb_end_write(mp->m_super);
xfs_blockgc_queue(pag);
}
/*
- * Try to free space in the filesystem by purging eofblocks and cowblocks.
+ * Try to free space in the filesystem by purging inactive inodes, eofblocks
+ * and cowblocks.
*/
int
xfs_blockgc_free_space(
struct xfs_mount *mp,
struct xfs_icwalk *icw)
{
+ int error;
+
trace_xfs_blockgc_free_space(mp, icw, _RET_IP_);
- return xfs_icwalk(mp, XFS_ICWALK_BLOCKGC, icw);
+ error = xfs_icwalk(mp, XFS_ICWALK_BLOCKGC, icw);
+ if (error)
+ return error;
+
+ xfs_inodegc_flush(mp);
+ return 0;
+}
+
+/*
+ * Reclaim all the free space that we can by scheduling the background blockgc
+ * and inodegc workers immediately and waiting for them all to clear.
+ */
+void
+xfs_blockgc_flush_all(
+ struct xfs_mount *mp)
+{
+ struct xfs_perag *pag;
+ xfs_agnumber_t agno;
+
+ trace_xfs_blockgc_flush_all(mp, __return_address);
+
+ /*
+ * For each blockgc worker, move its queue time up to now. If it
+ * wasn't queued, it will not be requeued. Then flush whatever's
+ * left.
+ */
+ for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
+ mod_delayed_work(pag->pag_mount->m_blockgc_wq,
+ &pag->pag_blockgc_work, 0);
+
+ for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
+ flush_delayed_work(&pag->pag_blockgc_work);
+
+ xfs_inodegc_flush(mp);
}
/*
@@ -1647,8 +1607,6 @@ xfs_icwalk_igrab(
struct xfs_icwalk *icw)
{
switch (goal) {
- case XFS_ICWALK_DQRELE:
- return xfs_dqrele_igrab(ip);
case XFS_ICWALK_BLOCKGC:
return xfs_blockgc_igrab(ip);
case XFS_ICWALK_RECLAIM:
@@ -1672,9 +1630,6 @@ xfs_icwalk_process_inode(
int error = 0;
switch (goal) {
- case XFS_ICWALK_DQRELE:
- xfs_dqrele_inode(ip, icw);
- break;
case XFS_ICWALK_BLOCKGC:
error = xfs_blockgc_scan_inode(ip, icw);
break;
@@ -1712,22 +1667,14 @@ restart:
nr_found = 0;
do {
struct xfs_inode *batch[XFS_LOOKUP_BATCH];
- unsigned int tag = xfs_icwalk_tag(goal);
int error = 0;
int i;
rcu_read_lock();
- if (tag == XFS_ICWALK_NULL_TAG)
- nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
- (void **)batch, first_index,
- XFS_LOOKUP_BATCH);
- else
- nr_found = radix_tree_gang_lookup_tag(
- &pag->pag_ici_root,
- (void **) batch, first_index,
- XFS_LOOKUP_BATCH, tag);
-
+ nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root,
+ (void **) batch, first_index,
+ XFS_LOOKUP_BATCH, goal);
if (!nr_found) {
done = true;
rcu_read_unlock();
@@ -1805,20 +1752,6 @@ restart:
return last_error;
}
-/* Fetch the next (possibly tagged) per-AG structure. */
-static inline struct xfs_perag *
-xfs_icwalk_get_perag(
- struct xfs_mount *mp,
- xfs_agnumber_t agno,
- enum xfs_icwalk_goal goal)
-{
- unsigned int tag = xfs_icwalk_tag(goal);
-
- if (tag == XFS_ICWALK_NULL_TAG)
- return xfs_perag_get(mp, agno);
- return xfs_perag_get_tag(mp, agno, tag);
-}
-
/* Walk all incore inodes to achieve a given goal. */
static int
xfs_icwalk(
@@ -1829,18 +1762,465 @@ xfs_icwalk(
struct xfs_perag *pag;
int error = 0;
int last_error = 0;
- xfs_agnumber_t agno = 0;
+ xfs_agnumber_t agno;
- while ((pag = xfs_icwalk_get_perag(mp, agno, goal))) {
- agno = pag->pag_agno + 1;
+ for_each_perag_tag(mp, agno, pag, goal) {
error = xfs_icwalk_ag(pag, goal, icw);
- xfs_perag_put(pag);
if (error) {
last_error = error;
- if (error == -EFSCORRUPTED)
+ if (error == -EFSCORRUPTED) {
+ xfs_perag_put(pag);
break;
+ }
}
}
return last_error;
BUILD_BUG_ON(XFS_ICWALK_PRIVATE_FLAGS & XFS_ICWALK_FLAGS_VALID);
}
+
+#ifdef DEBUG
+static void
+xfs_check_delalloc(
+ struct xfs_inode *ip,
+ int whichfork)
+{
+ struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
+ struct xfs_bmbt_irec got;
+ struct xfs_iext_cursor icur;
+
+ if (!ifp || !xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got))
+ return;
+ do {
+ if (isnullstartblock(got.br_startblock)) {
+ xfs_warn(ip->i_mount,
+ "ino %llx %s fork has delalloc extent at [0x%llx:0x%llx]",
+ ip->i_ino,
+ whichfork == XFS_DATA_FORK ? "data" : "cow",
+ got.br_startoff, got.br_blockcount);
+ }
+ } while (xfs_iext_next_extent(ifp, &icur, &got));
+}
+#else
+#define xfs_check_delalloc(ip, whichfork) do { } while (0)
+#endif
+
+/* Schedule the inode for reclaim. */
+static void
+xfs_inodegc_set_reclaimable(
+ struct xfs_inode *ip)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ struct xfs_perag *pag;
+
+ if (!xfs_is_shutdown(mp) && ip->i_delayed_blks) {
+ xfs_check_delalloc(ip, XFS_DATA_FORK);
+ xfs_check_delalloc(ip, XFS_COW_FORK);
+ ASSERT(0);
+ }
+
+ pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
+ spin_lock(&pag->pag_ici_lock);
+ spin_lock(&ip->i_flags_lock);
+
+ trace_xfs_inode_set_reclaimable(ip);
+ ip->i_flags &= ~(XFS_NEED_INACTIVE | XFS_INACTIVATING);
+ ip->i_flags |= XFS_IRECLAIMABLE;
+ xfs_perag_set_inode_tag(pag, XFS_INO_TO_AGINO(mp, ip->i_ino),
+ XFS_ICI_RECLAIM_TAG);
+
+ spin_unlock(&ip->i_flags_lock);
+ spin_unlock(&pag->pag_ici_lock);
+ xfs_perag_put(pag);
+}
+
+/*
+ * Free all speculative preallocations and possibly even the inode itself.
+ * This is the last chance to make changes to an otherwise unreferenced file
+ * before incore reclamation happens.
+ */
+static void
+xfs_inodegc_inactivate(
+ struct xfs_inode *ip)
+{
+ trace_xfs_inode_inactivating(ip);
+ xfs_inactive(ip);
+ xfs_inodegc_set_reclaimable(ip);
+}
+
+void
+xfs_inodegc_worker(
+ struct work_struct *work)
+{
+ struct xfs_inodegc *gc = container_of(work, struct xfs_inodegc,
+ work);
+ struct llist_node *node = llist_del_all(&gc->list);
+ struct xfs_inode *ip, *n;
+
+ WRITE_ONCE(gc->items, 0);
+
+ if (!node)
+ return;
+
+ ip = llist_entry(node, struct xfs_inode, i_gclist);
+ trace_xfs_inodegc_worker(ip->i_mount, READ_ONCE(gc->shrinker_hits));
+
+ WRITE_ONCE(gc->shrinker_hits, 0);
+ llist_for_each_entry_safe(ip, n, node, i_gclist) {
+ xfs_iflags_set(ip, XFS_INACTIVATING);
+ xfs_inodegc_inactivate(ip);
+ }
+}
+
+/*
+ * Force all currently queued inode inactivation work to run immediately, and
+ * wait for the work to finish. Two pass - queue all the work first pass, wait
+ * for it in a second pass.
+ */
+void
+xfs_inodegc_flush(
+ struct xfs_mount *mp)
+{
+ struct xfs_inodegc *gc;
+ int cpu;
+
+ if (!xfs_is_inodegc_enabled(mp))
+ return;
+
+ trace_xfs_inodegc_flush(mp, __return_address);
+
+ xfs_inodegc_queue_all(mp);
+
+ for_each_online_cpu(cpu) {
+ gc = per_cpu_ptr(mp->m_inodegc, cpu);
+ flush_work(&gc->work);
+ }
+}
+
+/*
+ * Flush all the pending work and then disable the inode inactivation background
+ * workers and wait for them to stop.
+ */
+void
+xfs_inodegc_stop(
+ struct xfs_mount *mp)
+{
+ struct xfs_inodegc *gc;
+ int cpu;
+
+ if (!xfs_clear_inodegc_enabled(mp))
+ return;
+
+ xfs_inodegc_queue_all(mp);
+
+ for_each_online_cpu(cpu) {
+ gc = per_cpu_ptr(mp->m_inodegc, cpu);
+ cancel_work_sync(&gc->work);
+ }
+ trace_xfs_inodegc_stop(mp, __return_address);
+}
+
+/*
+ * Enable the inode inactivation background workers and schedule deferred inode
+ * inactivation work if there is any.
+ */
+void
+xfs_inodegc_start(
+ struct xfs_mount *mp)
+{
+ if (xfs_set_inodegc_enabled(mp))
+ return;
+
+ trace_xfs_inodegc_start(mp, __return_address);
+ xfs_inodegc_queue_all(mp);
+}
+
+#ifdef CONFIG_XFS_RT
+static inline bool
+xfs_inodegc_want_queue_rt_file(
+ struct xfs_inode *ip)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ uint64_t freertx;
+
+ if (!XFS_IS_REALTIME_INODE(ip))
+ return false;
+
+ freertx = READ_ONCE(mp->m_sb.sb_frextents);
+ return freertx < mp->m_low_rtexts[XFS_LOWSP_5_PCNT];
+}
+#else
+# define xfs_inodegc_want_queue_rt_file(ip) (false)
+#endif /* CONFIG_XFS_RT */
+
+/*
+ * Schedule the inactivation worker when:
+ *
+ * - We've accumulated more than one inode cluster buffer's worth of inodes.
+ * - There is less than 5% free space left.
+ * - Any of the quotas for this inode are near an enforcement limit.
+ */
+static inline bool
+xfs_inodegc_want_queue_work(
+ struct xfs_inode *ip,
+ unsigned int items)
+{
+ struct xfs_mount *mp = ip->i_mount;
+
+ if (items > mp->m_ino_geo.inodes_per_cluster)
+ return true;
+
+ if (__percpu_counter_compare(&mp->m_fdblocks,
+ mp->m_low_space[XFS_LOWSP_5_PCNT],
+ XFS_FDBLOCKS_BATCH) < 0)
+ return true;
+
+ if (xfs_inodegc_want_queue_rt_file(ip))
+ return true;
+
+ if (xfs_inode_near_dquot_enforcement(ip, XFS_DQTYPE_USER))
+ return true;
+
+ if (xfs_inode_near_dquot_enforcement(ip, XFS_DQTYPE_GROUP))
+ return true;
+
+ if (xfs_inode_near_dquot_enforcement(ip, XFS_DQTYPE_PROJ))
+ return true;
+
+ return false;
+}
+
+/*
+ * Upper bound on the number of inodes in each AG that can be queued for
+ * inactivation at any given time, to avoid monopolizing the workqueue.
+ */
+#define XFS_INODEGC_MAX_BACKLOG (4 * XFS_INODES_PER_CHUNK)
+
+/*
+ * Make the frontend wait for inactivations when:
+ *
+ * - Memory shrinkers queued the inactivation worker and it hasn't finished.
+ * - The queue depth exceeds the maximum allowable percpu backlog.
+ *
+ * Note: If the current thread is running a transaction, we don't ever want to
+ * wait for other transactions because that could introduce a deadlock.
+ */
+static inline bool
+xfs_inodegc_want_flush_work(
+ struct xfs_inode *ip,
+ unsigned int items,
+ unsigned int shrinker_hits)
+{
+ if (current->journal_info)
+ return false;
+
+ if (shrinker_hits > 0)
+ return true;
+
+ if (items > XFS_INODEGC_MAX_BACKLOG)
+ return true;
+
+ return false;
+}
+
+/*
+ * Queue a background inactivation worker if there are inodes that need to be
+ * inactivated and higher level xfs code hasn't disabled the background
+ * workers.
+ */
+static void
+xfs_inodegc_queue(
+ struct xfs_inode *ip)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ struct xfs_inodegc *gc;
+ int items;
+ unsigned int shrinker_hits;
+
+ trace_xfs_inode_set_need_inactive(ip);
+ spin_lock(&ip->i_flags_lock);
+ ip->i_flags |= XFS_NEED_INACTIVE;
+ spin_unlock(&ip->i_flags_lock);
+
+ gc = get_cpu_ptr(mp->m_inodegc);
+ llist_add(&ip->i_gclist, &gc->list);
+ items = READ_ONCE(gc->items);
+ WRITE_ONCE(gc->items, items + 1);
+ shrinker_hits = READ_ONCE(gc->shrinker_hits);
+ put_cpu_ptr(gc);
+
+ if (!xfs_is_inodegc_enabled(mp))
+ return;
+
+ if (xfs_inodegc_want_queue_work(ip, items)) {
+ trace_xfs_inodegc_queue(mp, __return_address);
+ queue_work(mp->m_inodegc_wq, &gc->work);
+ }
+
+ if (xfs_inodegc_want_flush_work(ip, items, shrinker_hits)) {
+ trace_xfs_inodegc_throttle(mp, __return_address);
+ flush_work(&gc->work);
+ }
+}
+
+/*
+ * Fold the dead CPU inodegc queue into the current CPUs queue.
+ */
+void
+xfs_inodegc_cpu_dead(
+ struct xfs_mount *mp,
+ unsigned int dead_cpu)
+{
+ struct xfs_inodegc *dead_gc, *gc;
+ struct llist_node *first, *last;
+ unsigned int count = 0;
+
+ dead_gc = per_cpu_ptr(mp->m_inodegc, dead_cpu);
+ cancel_work_sync(&dead_gc->work);
+
+ if (llist_empty(&dead_gc->list))
+ return;
+
+ first = dead_gc->list.first;
+ last = first;
+ while (last->next) {
+ last = last->next;
+ count++;
+ }
+ dead_gc->list.first = NULL;
+ dead_gc->items = 0;
+
+ /* Add pending work to current CPU */
+ gc = get_cpu_ptr(mp->m_inodegc);
+ llist_add_batch(first, last, &gc->list);
+ count += READ_ONCE(gc->items);
+ WRITE_ONCE(gc->items, count);
+ put_cpu_ptr(gc);
+
+ if (xfs_is_inodegc_enabled(mp)) {
+ trace_xfs_inodegc_queue(mp, __return_address);
+ queue_work(mp->m_inodegc_wq, &gc->work);
+ }
+}
+
+/*
+ * We set the inode flag atomically with the radix tree tag. Once we get tag
+ * lookups on the radix tree, this inode flag can go away.
+ *
+ * We always use background reclaim here because even if the inode is clean, it
+ * still may be under IO and hence we have wait for IO completion to occur
+ * before we can reclaim the inode. The background reclaim path handles this
+ * more efficiently than we can here, so simply let background reclaim tear down
+ * all inodes.
+ */
+void
+xfs_inode_mark_reclaimable(
+ struct xfs_inode *ip)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ bool need_inactive;
+
+ XFS_STATS_INC(mp, vn_reclaim);
+
+ /*
+ * We should never get here with any of the reclaim flags already set.
+ */
+ ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_ALL_IRECLAIM_FLAGS));
+
+ need_inactive = xfs_inode_needs_inactive(ip);
+ if (need_inactive) {
+ xfs_inodegc_queue(ip);
+ return;
+ }
+
+ /* Going straight to reclaim, so drop the dquots. */
+ xfs_qm_dqdetach(ip);
+ xfs_inodegc_set_reclaimable(ip);
+}
+
+/*
+ * Register a phony shrinker so that we can run background inodegc sooner when
+ * there's memory pressure. Inactivation does not itself free any memory but
+ * it does make inodes reclaimable, which eventually frees memory.
+ *
+ * The count function, seek value, and batch value are crafted to trigger the
+ * scan function during the second round of scanning. Hopefully this means
+ * that we reclaimed enough memory that initiating metadata transactions won't
+ * make things worse.
+ */
+#define XFS_INODEGC_SHRINKER_COUNT (1UL << DEF_PRIORITY)
+#define XFS_INODEGC_SHRINKER_BATCH ((XFS_INODEGC_SHRINKER_COUNT / 2) + 1)
+
+static unsigned long
+xfs_inodegc_shrinker_count(
+ struct shrinker *shrink,
+ struct shrink_control *sc)
+{
+ struct xfs_mount *mp = container_of(shrink, struct xfs_mount,
+ m_inodegc_shrinker);
+ struct xfs_inodegc *gc;
+ int cpu;
+
+ if (!xfs_is_inodegc_enabled(mp))
+ return 0;
+
+ for_each_online_cpu(cpu) {
+ gc = per_cpu_ptr(mp->m_inodegc, cpu);
+ if (!llist_empty(&gc->list))
+ return XFS_INODEGC_SHRINKER_COUNT;
+ }
+
+ return 0;
+}
+
+static unsigned long
+xfs_inodegc_shrinker_scan(
+ struct shrinker *shrink,
+ struct shrink_control *sc)
+{
+ struct xfs_mount *mp = container_of(shrink, struct xfs_mount,
+ m_inodegc_shrinker);
+ struct xfs_inodegc *gc;
+ int cpu;
+ bool no_items = true;
+
+ if (!xfs_is_inodegc_enabled(mp))
+ return SHRINK_STOP;
+
+ trace_xfs_inodegc_shrinker_scan(mp, sc, __return_address);
+
+ for_each_online_cpu(cpu) {
+ gc = per_cpu_ptr(mp->m_inodegc, cpu);
+ if (!llist_empty(&gc->list)) {
+ unsigned int h = READ_ONCE(gc->shrinker_hits);
+
+ WRITE_ONCE(gc->shrinker_hits, h + 1);
+ queue_work_on(cpu, mp->m_inodegc_wq, &gc->work);
+ no_items = false;
+ }
+ }
+
+ /*
+ * If there are no inodes to inactivate, we don't want the shrinker
+ * to think there's deferred work to call us back about.
+ */
+ if (no_items)
+ return LONG_MAX;
+
+ return SHRINK_STOP;
+}
+
+/* Register a shrinker so we can accelerate inodegc and throttle queuing. */
+int
+xfs_inodegc_register_shrinker(
+ struct xfs_mount *mp)
+{
+ struct shrinker *shrink = &mp->m_inodegc_shrinker;
+
+ shrink->count_objects = xfs_inodegc_shrinker_count;
+ shrink->scan_objects = xfs_inodegc_shrinker_scan;
+ shrink->seeks = 0;
+ shrink->flags = SHRINKER_NONSLAB;
+ shrink->batch = XFS_INODEGC_SHRINKER_BATCH;
+
+ return register_shrinker(shrink);
+}
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index c751cc32dc46..2e4cfddf8b8e 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -59,6 +59,7 @@ int xfs_blockgc_free_dquots(struct xfs_mount *mp, struct xfs_dquot *udqp,
unsigned int iwalk_flags);
int xfs_blockgc_free_quota(struct xfs_inode *ip, unsigned int iwalk_flags);
int xfs_blockgc_free_space(struct xfs_mount *mp, struct xfs_icwalk *icm);
+void xfs_blockgc_flush_all(struct xfs_mount *mp);
void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
@@ -68,16 +69,17 @@ void xfs_inode_clear_cowblocks_tag(struct xfs_inode *ip);
void xfs_blockgc_worker(struct work_struct *work);
-#ifdef CONFIG_XFS_QUOTA
-int xfs_dqrele_all_inodes(struct xfs_mount *mp, unsigned int qflags);
-#else
-# define xfs_dqrele_all_inodes(mp, qflags) (0)
-#endif
-
int xfs_icache_inode_is_allocated(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_ino_t ino, bool *inuse);
void xfs_blockgc_stop(struct xfs_mount *mp);
void xfs_blockgc_start(struct xfs_mount *mp);
+void xfs_inodegc_worker(struct work_struct *work);
+void xfs_inodegc_flush(struct xfs_mount *mp);
+void xfs_inodegc_stop(struct xfs_mount *mp);
+void xfs_inodegc_start(struct xfs_mount *mp);
+void xfs_inodegc_cpu_dead(struct xfs_mount *mp, unsigned int cpu);
+int xfs_inodegc_register_shrinker(struct xfs_mount *mp);
+
#endif
diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c
index 9b3994b9c716..017904a34c02 100644
--- a/fs/xfs/xfs_icreate_item.c
+++ b/fs/xfs/xfs_icreate_item.c
@@ -201,7 +201,7 @@ xlog_recover_icreate_commit_pass2(
if (length != igeo->ialloc_blks &&
length != igeo->ialloc_min_blks) {
xfs_warn(log->l_mp,
- "%s: unsupported chunk length", __FUNCTION__);
+ "%s: unsupported chunk length", __func__);
return -EINVAL;
}
@@ -209,7 +209,7 @@ xlog_recover_icreate_commit_pass2(
if ((count >> mp->m_sb.sb_inopblog) != length) {
xfs_warn(log->l_mp,
"%s: inconsistent inode count and chunk length",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index f00145e1a976..a4f6f034fb81 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -674,7 +674,7 @@ xfs_lookup(
trace_xfs_lookup(dp, name);
- if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+ if (xfs_is_shutdown(dp->i_mount))
return -EIO;
error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name);
@@ -716,7 +716,7 @@ xfs_inode_inherit_flags(
di_flags |= XFS_DIFLAG_PROJINHERIT;
} else if (S_ISREG(mode)) {
if ((pip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
- xfs_sb_version_hasrealtime(&ip->i_mount->m_sb))
+ xfs_has_realtime(ip->i_mount))
di_flags |= XFS_DIFLAG_REALTIME;
if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
di_flags |= XFS_DIFLAG_EXTSIZE;
@@ -837,8 +837,7 @@ xfs_init_new_inode(
inode->i_rdev = rdev;
ip->i_projid = prid;
- if (dir && !(dir->i_mode & S_ISGID) &&
- (mp->m_flags & XFS_MOUNT_GRPID)) {
+ if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) {
inode_fsuid_set(inode, mnt_userns);
inode->i_gid = dir->i_gid;
inode->i_mode = mode;
@@ -868,7 +867,7 @@ xfs_init_new_inode(
ip->i_extsize = 0;
ip->i_diflags = 0;
- if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (xfs_has_v3inodes(mp)) {
inode_set_iversion(inode, 1);
ip->i_cowextsize = 0;
ip->i_crtime = tv;
@@ -908,7 +907,7 @@ xfs_init_new_inode(
* this saves us from needing to run a separate transaction to set the
* fork offset in the immediate future.
*/
- if (init_xattrs && xfs_sb_version_hasattr(&mp->m_sb)) {
+ if (init_xattrs && xfs_has_attr(mp)) {
ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
ip->i_afp = xfs_ifork_alloc(XFS_DINODE_FMT_EXTENTS, 0);
}
@@ -987,7 +986,7 @@ xfs_create(
trace_xfs_create(dp, name);
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
prid = xfs_get_initial_prid(dp);
@@ -1079,7 +1078,7 @@ xfs_create(
* create transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+ if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
xfs_trans_set_sync(tp);
/*
@@ -1141,7 +1140,7 @@ xfs_create_tmpfile(
uint resblks;
xfs_ino_t ino;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
prid = xfs_get_initial_prid(dp);
@@ -1171,7 +1170,7 @@ xfs_create_tmpfile(
if (error)
goto out_trans_cancel;
- if (mp->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(mp))
xfs_trans_set_sync(tp);
/*
@@ -1231,7 +1230,7 @@ xfs_link(
ASSERT(!S_ISDIR(VFS_I(sip)->i_mode));
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
error = xfs_qm_dqattach(sip);
@@ -1305,7 +1304,7 @@ xfs_link(
* link transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+ if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
xfs_trans_set_sync(tp);
return xfs_trans_commit(tp);
@@ -1446,10 +1445,10 @@ xfs_release(
return 0;
/* If this is a read-only mount, don't do this (would generate I/O) */
- if (mp->m_flags & XFS_MOUNT_RDONLY)
+ if (xfs_is_readonly(mp))
return 0;
- if (!XFS_FORCED_SHUTDOWN(mp)) {
+ if (!xfs_is_shutdown(mp)) {
int truncated;
/*
@@ -1532,7 +1531,7 @@ xfs_inactive_truncate(
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
if (error) {
- ASSERT(XFS_FORCED_SHUTDOWN(mp));
+ ASSERT(xfs_is_shutdown(mp));
return error;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1603,7 +1602,7 @@ xfs_inactive_ifree(
"Failed to remove inode(s) from unlinked list. "
"Please free space, unmount and run xfs_repair.");
} else {
- ASSERT(XFS_FORCED_SHUTDOWN(mp));
+ ASSERT(xfs_is_shutdown(mp));
}
return error;
}
@@ -1639,7 +1638,7 @@ xfs_inactive_ifree(
* might do that, we need to make sure. Otherwise the
* inode might be lost for a long time or forever.
*/
- if (!XFS_FORCED_SHUTDOWN(mp)) {
+ if (!xfs_is_shutdown(mp)) {
xfs_notice(mp, "%s: xfs_ifree returned error %d",
__func__, error);
xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
@@ -1666,6 +1665,59 @@ xfs_inactive_ifree(
}
/*
+ * Returns true if we need to update the on-disk metadata before we can free
+ * the memory used by this inode. Updates include freeing post-eof
+ * preallocations; freeing COW staging extents; and marking the inode free in
+ * the inobt if it is on the unlinked list.
+ */
+bool
+xfs_inode_needs_inactive(
+ struct xfs_inode *ip)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ struct xfs_ifork *cow_ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
+
+ /*
+ * If the inode is already free, then there can be nothing
+ * to clean up here.
+ */
+ if (VFS_I(ip)->i_mode == 0)
+ return false;
+
+ /* If this is a read-only mount, don't do this (would generate I/O) */
+ if (xfs_is_readonly(mp))
+ return false;
+
+ /* If the log isn't running, push inodes straight to reclaim. */
+ if (xfs_is_shutdown(mp) || xfs_has_norecovery(mp))
+ return false;
+
+ /* Metadata inodes require explicit resource cleanup. */
+ if (xfs_is_metadata_inode(ip))
+ return false;
+
+ /* Want to clean out the cow blocks if there are any. */
+ if (cow_ifp && cow_ifp->if_bytes > 0)
+ return true;
+
+ /* Unlinked files must be freed. */
+ if (VFS_I(ip)->i_nlink == 0)
+ return true;
+
+ /*
+ * This file isn't being freed, so check if there are post-eof blocks
+ * to free. @force is true because we are evicting an inode from the
+ * cache. Post-eof blocks must be freed, lest we end up with broken
+ * free space accounting.
+ *
+ * Note: don't bother with iolock here since lockdep complains about
+ * acquiring it in reclaim context. We have the only reference to the
+ * inode at this point anyways.
+ */
+ return xfs_can_free_eofblocks(ip, true);
+}
+
+/*
* xfs_inactive
*
* This is called when the vnode reference count for the vnode
@@ -1694,7 +1746,7 @@ xfs_inactive(
ASSERT(!xfs_iflags_test(ip, XFS_IRECOVERY));
/* If this is a read-only mount, don't do this (would generate I/O) */
- if (mp->m_flags & XFS_MOUNT_RDONLY)
+ if (xfs_is_readonly(mp))
goto out;
/* Metadata inodes require explicit resource cleanup. */
@@ -1969,7 +2021,7 @@ xfs_iunlink_destroy(
rhashtable_free_and_destroy(&pag->pagi_unlinked_hash,
xfs_iunlink_free_item, &freed_anything);
- ASSERT(freed_anything == false || XFS_FORCED_SHUTDOWN(pag->pag_mount));
+ ASSERT(freed_anything == false || xfs_is_shutdown(pag->pag_mount));
}
/*
@@ -2714,7 +2766,7 @@ xfs_remove(
trace_xfs_remove(dp, name);
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
error = xfs_qm_dqattach(dp);
@@ -2813,7 +2865,7 @@ xfs_remove(
* remove transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+ if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
@@ -2890,7 +2942,7 @@ xfs_finish_rename(
* If this is a synchronous mount, make sure that the rename transaction
* goes to disk before returning to the user.
*/
- if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+ if (xfs_has_wsync(tp->t_mountp) || xfs_has_dirsync(tp->t_mountp))
xfs_trans_set_sync(tp);
return xfs_trans_commit(tp);
@@ -3473,7 +3525,7 @@ xfs_iflush(
* happen but we need to still do it to ensure backwards compatibility
* with old kernels that predate logging all inode changes.
*/
- if (!xfs_sb_version_has_v3inode(&mp->m_sb))
+ if (!xfs_has_v3inodes(mp))
ip->i_flushiter++;
/*
@@ -3495,7 +3547,7 @@ xfs_iflush(
xfs_inode_to_disk(ip, dip, iip->ili_item.li_lsn);
/* Wrap, we never let the log put out DI_MAX_FLUSH */
- if (!xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (!xfs_has_v3inodes(mp)) {
if (ip->i_flushiter == DI_MAX_FLUSH)
ip->i_flushiter = 0;
}
@@ -3614,7 +3666,7 @@ xfs_iflush_cluster(
* AIL, leaving a dirty/unpinned inode attached to the buffer
* that otherwise looks like it should be flushed.
*/
- if (XFS_FORCED_SHUTDOWN(mp)) {
+ if (xfs_is_shutdown(mp)) {
xfs_iunpin_wait(ip);
xfs_iflush_abort(ip);
xfs_iunlock(ip, XFS_ILOCK_SHARED);
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index e0ae905554e2..b21b177832d1 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -41,6 +41,7 @@ typedef struct xfs_inode {
struct xfs_inode_log_item *i_itemp; /* logging information */
mrlock_t i_lock; /* inode lock */
atomic_t i_pincount; /* inode pin count */
+ struct llist_node i_gclist; /* deferred inactivation list */
/*
* Bitsets of inode metadata that have been checked and/or are sick.
@@ -239,6 +240,7 @@ static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip)
#define __XFS_IPINNED_BIT 8 /* wakeup key for zero pin count */
#define XFS_IPINNED (1 << __XFS_IPINNED_BIT)
#define XFS_IEOFBLOCKS (1 << 9) /* has the preallocblocks tag set */
+#define XFS_NEED_INACTIVE (1 << 10) /* see XFS_INACTIVATING below */
/*
* If this unlinked inode is in the middle of recovery, don't let drop_inode
* truncate and free the inode. This can happen if we iget the inode during
@@ -248,13 +250,29 @@ static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip)
#define XFS_ICOWBLOCKS (1 << 12)/* has the cowblocks tag set */
/*
+ * If we need to update on-disk metadata before this IRECLAIMABLE inode can be
+ * freed, then NEED_INACTIVE will be set. Once we start the updates, the
+ * INACTIVATING bit will be set to keep iget away from this inode. After the
+ * inactivation completes, both flags will be cleared and the inode is a
+ * plain old IRECLAIMABLE inode.
+ */
+#define XFS_INACTIVATING (1 << 13)
+
+/* All inode state flags related to inode reclaim. */
+#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
+ XFS_IRECLAIM | \
+ XFS_NEED_INACTIVE | \
+ XFS_INACTIVATING)
+
+/*
* Per-lifetime flags need to be reset when re-using a reclaimable inode during
* inode lookup. This prevents unintended behaviour on the new inode from
* ocurring.
*/
#define XFS_IRECLAIM_RESET_FLAGS \
(XFS_IRECLAIMABLE | XFS_IRECLAIM | \
- XFS_IDIRTY_RELEASE | XFS_ITRUNCATED)
+ XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | XFS_NEED_INACTIVE | \
+ XFS_INACTIVATING)
/*
* Flags for inode locking.
@@ -381,8 +399,7 @@ enum layout_break_reason {
* new subdirectory gets S_ISGID bit from parent.
*/
#define XFS_INHERIT_GID(pip) \
- (((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \
- (VFS_I(pip)->i_mode & S_ISGID))
+ (xfs_has_grpid((pip)->i_mount) || (VFS_I(pip)->i_mode & S_ISGID))
int xfs_release(struct xfs_inode *ip);
void xfs_inactive(struct xfs_inode *ip);
@@ -492,6 +509,8 @@ extern struct kmem_zone *xfs_inode_zone;
/* The default CoW extent size hint. */
#define XFS_DEFAULT_COWEXTSZ_HINT 32
+bool xfs_inode_needs_inactive(struct xfs_inode *ip);
+
int xfs_iunlink_init(struct xfs_perag *pag);
void xfs_iunlink_destroy(struct xfs_perag *pag);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 35de30849fcc..0659d19c211e 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -396,7 +396,7 @@ xfs_inode_to_log_dinode(
/* log a dummy value to ensure log structure is fully initialised */
to->di_next_unlinked = NULLAGINO;
- if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
+ if (xfs_has_v3inodes(ip->i_mount)) {
to->di_version = 3;
to->di_changecount = inode_peek_iversion(inode);
to->di_crtime = xfs_inode_to_log_dinode_ts(ip, ip->i_crtime);
diff --git a/fs/xfs/xfs_inode_item_recover.c b/fs/xfs/xfs_inode_item_recover.c
index e0072a6cd2d3..239dd2e3384e 100644
--- a/fs/xfs/xfs_inode_item_recover.c
+++ b/fs/xfs/xfs_inode_item_recover.c
@@ -295,7 +295,7 @@ xlog_recover_inode_commit_pass2(
* superblock flag to determine whether we need to look at di_flushiter
* to skip replay when the on disk inode is newer than the log one
*/
- if (!xfs_sb_version_has_v3inode(&mp->m_sb) &&
+ if (!xfs_has_v3inodes(mp) &&
ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
/*
* Deal with the wrap case, DI_MAX_FLUSH is less
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 16039ea10ac9..0c795dc093ef 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -756,7 +756,7 @@ xfs_ioc_fsbulkstat(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
if (copy_from_user(&bulkreq, arg, sizeof(struct xfs_fsop_bulkreq)))
@@ -927,7 +927,7 @@ xfs_ioc_bulkstat(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
@@ -977,7 +977,7 @@ xfs_ioc_inumbers(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
@@ -1010,7 +1010,7 @@ xfs_ioc_fsgeometry(
struct xfs_fsop_geom fsgeo;
size_t len;
- xfs_fs_geometry(&mp->m_sb, &fsgeo, struct_version);
+ xfs_fs_geometry(mp, &fsgeo, struct_version);
if (struct_version <= 3)
len = sizeof(struct xfs_fsop_geom_v1);
@@ -1213,7 +1213,7 @@ xfs_ioctl_setattr_xflags(
/* diflags2 only valid for v3 inodes. */
i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
- if (i_flags2 && !xfs_sb_version_has_v3inode(&mp->m_sb))
+ if (i_flags2 && !xfs_has_v3inodes(mp))
return -EINVAL;
ip->i_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);
@@ -1237,8 +1237,7 @@ xfs_ioctl_setattr_prepare_dax(
if (S_ISDIR(inode->i_mode))
return;
- if ((mp->m_flags & XFS_MOUNT_DAX_ALWAYS) ||
- (mp->m_flags & XFS_MOUNT_DAX_NEVER))
+ if (xfs_has_dax_always(mp) || xfs_has_dax_never(mp))
return;
if (((fa->fsx_xflags & FS_XFLAG_DAX) &&
@@ -1263,10 +1262,10 @@ xfs_ioctl_setattr_get_trans(
struct xfs_trans *tp;
int error = -EROFS;
- if (mp->m_flags & XFS_MOUNT_RDONLY)
+ if (xfs_is_readonly(mp))
goto out_error;
error = -EIO;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
goto out_error;
error = xfs_trans_alloc_ichange(ip, NULL, NULL, pdqp,
@@ -1274,7 +1273,7 @@ xfs_ioctl_setattr_get_trans(
if (error)
goto out_error;
- if (mp->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(mp))
xfs_trans_set_sync(tp);
return tp;
@@ -1362,9 +1361,9 @@ xfs_ioctl_setattr_check_projid(
if (!fa->fsx_valid)
return 0;
- /* Disallow 32bit project ids if projid32bit feature is not enabled. */
+ /* Disallow 32bit project ids if 32bit IDs are not enabled. */
if (fa->fsx_projid > (uint16_t)-1 &&
- !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
+ !xfs_has_projid32(ip->i_mount))
return -EINVAL;
return 0;
}
@@ -1450,7 +1449,7 @@ xfs_fileattr_set(
/* Change the ownerships and register project quota modifications */
if (ip->i_projid != fa->fsx_projid) {
- if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
+ if (XFS_IS_PQUOTA_ON(mp)) {
olddquot = xfs_qm_vop_chown(tp, ip,
&ip->i_pdquot, pdqp);
}
@@ -1467,7 +1466,7 @@ xfs_fileattr_set(
else
ip->i_extsize = 0;
- if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (xfs_has_v3inodes(mp)) {
if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
ip->i_cowextsize = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);
else
@@ -1792,7 +1791,7 @@ xfs_ioc_swapext(
goto out_put_tmp_file;
}
- if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+ if (xfs_is_shutdown(ip->i_mount)) {
error = -EIO;
goto out_put_tmp_file;
}
@@ -2081,7 +2080,7 @@ xfs_file_ioctl(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (mp->m_flags & XFS_MOUNT_RDONLY)
+ if (xfs_is_readonly(mp))
return -EROFS;
if (copy_from_user(&inout, arg, sizeof(inout)))
@@ -2198,7 +2197,7 @@ xfs_file_ioctl(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (mp->m_flags & XFS_MOUNT_RDONLY)
+ if (xfs_is_readonly(mp))
return -EROFS;
if (copy_from_user(&eofb, arg, sizeof(eofb)))
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index e6506773ba55..8783af203cfc 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -50,7 +50,7 @@ xfs_compat_ioc_fsgeometry_v1(
{
struct xfs_fsop_geom fsgeo;
- xfs_fs_geometry(&mp->m_sb, &fsgeo, 3);
+ xfs_fs_geometry(mp, &fsgeo, 3);
/* The 32-bit variant simply has some padding at the end */
if (copy_to_user(arg32, &fsgeo, sizeof(struct compat_xfs_fsop_geom_v1)))
return -EFAULT;
@@ -254,7 +254,7 @@ xfs_compat_ioc_fsbulkstat(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
if (get_user(addr, &p32->lastip))
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index d8cd2583dedb..093758440ad5 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -132,7 +132,7 @@ xfs_eof_alignment(
* If mounted with the "-o swalloc" option the alignment is
* increased from the strip unit size to the stripe width.
*/
- if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+ if (mp->m_swidth && xfs_has_swalloc(mp))
align = mp->m_swidth;
else if (mp->m_dalign)
align = mp->m_dalign;
@@ -734,7 +734,7 @@ xfs_direct_write_iomap_begin(
ASSERT(flags & (IOMAP_WRITE | IOMAP_ZERO));
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
/*
@@ -874,7 +874,7 @@ xfs_buffered_write_iomap_begin(
int allocfork = XFS_DATA_FORK;
int error = 0;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
/* we can't use delayed allocations when using extent size hints */
@@ -994,7 +994,7 @@ xfs_buffered_write_iomap_begin(
* Determine the initial size of the preallocation.
* We clean up any extra preallocation when the file is closed.
*/
- if (mp->m_flags & XFS_MOUNT_ALLOCSIZE)
+ if (xfs_has_allocsize(mp))
prealloc_blocks = mp->m_allocsize_blocks;
else
prealloc_blocks = xfs_iomap_prealloc_size(ip, allocfork,
@@ -1064,11 +1064,11 @@ found_cow:
error = xfs_bmbt_to_iomap(ip, srcmap, &imap, 0);
if (error)
return error;
- } else {
- xfs_trim_extent(&cmap, offset_fsb,
- imap.br_startoff - offset_fsb);
+ return xfs_bmbt_to_iomap(ip, iomap, &cmap, IOMAP_F_SHARED);
}
- return xfs_bmbt_to_iomap(ip, iomap, &cmap, IOMAP_F_SHARED);
+
+ xfs_trim_extent(&cmap, offset_fsb, imap.br_startoff - offset_fsb);
+ return xfs_bmbt_to_iomap(ip, iomap, &cmap, 0);
out_unlock:
xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -1127,7 +1127,7 @@ xfs_buffered_write_iomap_end(
error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
end_fsb - start_fsb);
- if (error && !XFS_FORCED_SHUTDOWN(mp)) {
+ if (error && !xfs_is_shutdown(mp)) {
xfs_alert(mp, "%s: unable to clean up ino %lld",
__func__, ip->i_ino);
return error;
@@ -1162,7 +1162,7 @@ xfs_read_iomap_begin(
ASSERT(!(flags & (IOMAP_WRITE | IOMAP_ZERO)));
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
error = xfs_ilock_for_iomap(ip, flags, &lockmode);
@@ -1203,7 +1203,7 @@ xfs_seek_iomap_begin(
int error = 0;
unsigned lockmode;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
lockmode = xfs_ilock_data_map_shared(ip);
@@ -1285,7 +1285,7 @@ xfs_xattr_iomap_begin(
int nimaps = 1, error = 0;
unsigned lockmode;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
lockmode = xfs_ilock_attr_map_shared(ip);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 93c082db04b7..a607d6aca5c4 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -393,7 +393,7 @@ xfs_vn_unlink(
* but still hashed. This is incompatible with case-insensitive
* mode, so invalidate (unhash) the dentry in CI-mode.
*/
- if (xfs_sb_version_hasasciici(&XFS_M(dir->i_sb)->m_sb))
+ if (xfs_has_asciici(XFS_M(dir->i_sb)))
d_invalidate(dentry);
return 0;
}
@@ -558,10 +558,10 @@ xfs_stat_blksize(
* default buffered I/O size, return that, otherwise return the compat
* default.
*/
- if (mp->m_flags & XFS_MOUNT_LARGEIO) {
+ if (xfs_has_large_iosize(mp)) {
if (mp->m_swidth)
return XFS_FSB_TO_B(mp, mp->m_swidth);
- if (mp->m_flags & XFS_MOUNT_ALLOCSIZE)
+ if (xfs_has_allocsize(mp))
return 1U << mp->m_allocsize_log;
}
@@ -582,7 +582,7 @@ xfs_vn_getattr(
trace_xfs_getattr(ip);
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
stat->size = XFS_ISIZE(ip);
@@ -597,7 +597,7 @@ xfs_vn_getattr(
stat->ctime = inode->i_ctime;
stat->blocks = XFS_FSB_TO_BB(mp, ip->i_nblocks + ip->i_delayed_blks);
- if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (xfs_has_v3inodes(mp)) {
if (request_mask & STATX_BTIME) {
stat->result_mask |= STATX_BTIME;
stat->btime = ip->i_crtime;
@@ -673,10 +673,10 @@ xfs_vn_change_ok(
{
struct xfs_mount *mp = XFS_I(d_inode(dentry))->i_mount;
- if (mp->m_flags & XFS_MOUNT_RDONLY)
+ if (xfs_is_readonly(mp))
return -EROFS;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
return setattr_prepare(mnt_userns, dentry, iattr);
@@ -778,7 +778,7 @@ xfs_setattr_nonsize(
* in the transaction.
*/
if (!uid_eq(iuid, uid)) {
- if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_UQUOTA_ON(mp)) {
+ if (XFS_IS_UQUOTA_ON(mp)) {
ASSERT(mask & ATTR_UID);
ASSERT(udqp);
olddquot1 = xfs_qm_vop_chown(tp, ip,
@@ -787,8 +787,8 @@ xfs_setattr_nonsize(
inode->i_uid = uid;
}
if (!gid_eq(igid, gid)) {
- if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
- ASSERT(xfs_sb_version_has_pquotino(&mp->m_sb) ||
+ if (XFS_IS_GQUOTA_ON(mp)) {
+ ASSERT(xfs_has_pquotino(mp) ||
!XFS_IS_PQUOTA_ON(mp));
ASSERT(mask & ATTR_GID);
ASSERT(gdqp);
@@ -808,7 +808,7 @@ xfs_setattr_nonsize(
XFS_STATS_INC(mp, xs_ig_attrchg);
- if (mp->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(mp))
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
@@ -1037,7 +1037,7 @@ xfs_setattr_size(
XFS_STATS_INC(mp, xs_ig_attrchg);
- if (mp->m_flags & XFS_MOUNT_WSYNC)
+ if (xfs_has_wsync(mp))
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
@@ -1287,11 +1287,11 @@ xfs_inode_should_enable_dax(
{
if (!IS_ENABLED(CONFIG_FS_DAX))
return false;
- if (ip->i_mount->m_flags & XFS_MOUNT_DAX_NEVER)
+ if (xfs_has_dax_never(ip->i_mount))
return false;
if (!xfs_inode_supports_dax(ip))
return false;
- if (ip->i_mount->m_flags & XFS_MOUNT_DAX_ALWAYS)
+ if (xfs_has_dax_always(ip->i_mount))
return true;
if (ip->i_diflags2 & XFS_DIFLAG2_DAX)
return true;
@@ -1344,7 +1344,7 @@ xfs_setup_inode(
gfp_t gfp_mask;
inode->i_ino = ip->i_ino;
- inode->i_state = I_NEW;
+ inode->i_state |= I_NEW;
inode_sb_list_add(inode);
/* make the inode look hashed for the writeback code */
@@ -1401,7 +1401,7 @@ xfs_setup_iops(
inode->i_mapping->a_ops = &xfs_address_space_operations;
break;
case S_IFDIR:
- if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb))
+ if (xfs_has_asciici(XFS_M(inode->i_sb)))
inode->i_op = &xfs_dir_ci_inode_operations;
else
inode->i_op = &xfs_dir_inode_operations;
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index f331975a16de..c08c79d9e311 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -19,6 +19,7 @@
#include "xfs_error.h"
#include "xfs_icache.h"
#include "xfs_health.h"
+#include "xfs_trans.h"
/*
* Bulk Stat
@@ -107,7 +108,7 @@ xfs_bulkstat_one_int(
buf->bs_forkoff = XFS_IFORK_BOFF(ip);
buf->bs_version = XFS_BULKSTAT_VERSION_V5;
- if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+ if (xfs_has_v3inodes(mp)) {
buf->bs_btime = ip->i_crtime.tv_sec;
buf->bs_btime_nsec = ip->i_crtime.tv_nsec;
if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
@@ -163,6 +164,7 @@ xfs_bulkstat_one(
.formatter = formatter,
.breq = breq,
};
+ struct xfs_trans *tp;
int error;
if (breq->mnt_userns != &init_user_ns) {
@@ -178,9 +180,18 @@ xfs_bulkstat_one(
if (!bc.buf)
return -ENOMEM;
- error = xfs_bulkstat_one_int(breq->mp, breq->mnt_userns, NULL,
- breq->startino, &bc);
+ /*
+ * Grab an empty transaction so that we can use its recursive buffer
+ * locking abilities to detect cycles in the inobt without deadlocking.
+ */
+ error = xfs_trans_alloc_empty(breq->mp, &tp);
+ if (error)
+ goto out;
+ error = xfs_bulkstat_one_int(breq->mp, breq->mnt_userns, tp,
+ breq->startino, &bc);
+ xfs_trans_cancel(tp);
+out:
kmem_free(bc.buf);
/*
@@ -244,6 +255,7 @@ xfs_bulkstat(
.formatter = formatter,
.breq = breq,
};
+ struct xfs_trans *tp;
int error;
if (breq->mnt_userns != &init_user_ns) {
@@ -259,9 +271,18 @@ xfs_bulkstat(
if (!bc.buf)
return -ENOMEM;
- error = xfs_iwalk(breq->mp, NULL, breq->startino, breq->flags,
- xfs_bulkstat_iwalk, breq->icount, &bc);
+ /*
+ * Grab an empty transaction so that we can use its recursive buffer
+ * locking abilities to detect cycles in the inobt without deadlocking.
+ */
+ error = xfs_trans_alloc_empty(breq->mp, &tp);
+ if (error)
+ goto out;
+ error = xfs_iwalk(breq->mp, tp, breq->startino, breq->flags,
+ xfs_bulkstat_iwalk, breq->icount, &bc);
+ xfs_trans_cancel(tp);
+out:
kmem_free(bc.buf);
/*
@@ -374,13 +395,24 @@ xfs_inumbers(
.formatter = formatter,
.breq = breq,
};
+ struct xfs_trans *tp;
int error = 0;
if (xfs_bulkstat_already_done(breq->mp, breq->startino))
return 0;
- error = xfs_inobt_walk(breq->mp, NULL, breq->startino, breq->flags,
+ /*
+ * Grab an empty transaction so that we can use its recursive buffer
+ * locking abilities to detect cycles in the inobt without deadlocking.
+ */
+ error = xfs_trans_alloc_empty(breq->mp, &tp);
+ if (error)
+ goto out;
+
+ error = xfs_inobt_walk(breq->mp, tp, breq->startino, breq->flags,
xfs_inumbers_walk, breq->icount, &ic);
+ xfs_trans_cancel(tp);
+out:
/*
* We found some inode groups, so clear the error status and return
diff --git a/fs/xfs/xfs_iwalk.c b/fs/xfs/xfs_iwalk.c
index 917d51eefee3..7558486f4937 100644
--- a/fs/xfs/xfs_iwalk.c
+++ b/fs/xfs/xfs_iwalk.c
@@ -83,6 +83,9 @@ struct xfs_iwalk_ag {
/* Skip empty inobt records? */
unsigned int skip_empty:1;
+
+ /* Drop the (hopefully empty) transaction when calling iwalk_fn. */
+ unsigned int drop_trans:1;
};
/*
@@ -352,7 +355,6 @@ xfs_iwalk_run_callbacks(
int *has_more)
{
struct xfs_mount *mp = iwag->mp;
- struct xfs_trans *tp = iwag->tp;
struct xfs_inobt_rec_incore *irec;
xfs_agino_t next_agino;
int error;
@@ -362,10 +364,15 @@ xfs_iwalk_run_callbacks(
ASSERT(iwag->nr_recs > 0);
/* Delete cursor but remember the last record we cached... */
- xfs_iwalk_del_inobt(tp, curpp, agi_bpp, 0);
+ xfs_iwalk_del_inobt(iwag->tp, curpp, agi_bpp, 0);
irec = &iwag->recs[iwag->nr_recs - 1];
ASSERT(next_agino >= irec->ir_startino + XFS_INODES_PER_CHUNK);
+ if (iwag->drop_trans) {
+ xfs_trans_cancel(iwag->tp);
+ iwag->tp = NULL;
+ }
+
error = xfs_iwalk_ag_recs(iwag);
if (error)
return error;
@@ -376,8 +383,15 @@ xfs_iwalk_run_callbacks(
if (!has_more)
return 0;
+ if (iwag->drop_trans) {
+ error = xfs_trans_alloc_empty(mp, &iwag->tp);
+ if (error)
+ return error;
+ }
+
/* ...and recreate the cursor just past where we left off. */
- error = xfs_inobt_cur(mp, tp, iwag->pag, XFS_BTNUM_INO, curpp, agi_bpp);
+ error = xfs_inobt_cur(mp, iwag->tp, iwag->pag, XFS_BTNUM_INO, curpp,
+ agi_bpp);
if (error)
return error;
@@ -390,7 +404,6 @@ xfs_iwalk_ag(
struct xfs_iwalk_ag *iwag)
{
struct xfs_mount *mp = iwag->mp;
- struct xfs_trans *tp = iwag->tp;
struct xfs_perag *pag = iwag->pag;
struct xfs_buf *agi_bp = NULL;
struct xfs_btree_cur *cur = NULL;
@@ -469,7 +482,7 @@ xfs_iwalk_ag(
error = xfs_iwalk_run_callbacks(iwag, &cur, &agi_bp, &has_more);
out:
- xfs_iwalk_del_inobt(tp, &cur, &agi_bp, error);
+ xfs_iwalk_del_inobt(iwag->tp, &cur, &agi_bp, error);
return error;
}
@@ -599,8 +612,18 @@ xfs_iwalk_ag_work(
error = xfs_iwalk_alloc(iwag);
if (error)
goto out;
+ /*
+ * Grab an empty transaction so that we can use its recursive buffer
+ * locking abilities to detect cycles in the inobt without deadlocking.
+ */
+ error = xfs_trans_alloc_empty(mp, &iwag->tp);
+ if (error)
+ goto out;
+ iwag->drop_trans = 1;
error = xfs_iwalk_ag(iwag);
+ if (iwag->tp)
+ xfs_trans_cancel(iwag->tp);
xfs_iwalk_free(iwag);
out:
xfs_perag_put(iwag->pag);
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 60ac5fd63f1e..f6cd2d4aa770 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -41,6 +41,8 @@ xlog_dealloc_log(
/* local state machine functions */
STATIC void xlog_state_done_syncing(
struct xlog_in_core *iclog);
+STATIC void xlog_state_do_callback(
+ struct xlog *log);
STATIC int
xlog_state_get_iclog_space(
struct xlog *log,
@@ -50,11 +52,6 @@ xlog_state_get_iclog_space(
int *continued_write,
int *logoffsetp);
STATIC void
-xlog_state_switch_iclogs(
- struct xlog *log,
- struct xlog_in_core *iclog,
- int eventual_size);
-STATIC void
xlog_grant_push_ail(
struct xlog *log,
int need_bytes);
@@ -246,7 +243,7 @@ xlog_grant_head_wait(
list_add_tail(&tic->t_queue, &head->waiters);
do {
- if (XLOG_FORCED_SHUTDOWN(log))
+ if (xlog_is_shutdown(log))
goto shutdown;
xlog_grant_push_ail(log, need_bytes);
@@ -260,7 +257,7 @@ xlog_grant_head_wait(
trace_xfs_log_grant_wake(log, tic);
spin_lock(&head->lock);
- if (XLOG_FORCED_SHUTDOWN(log))
+ if (xlog_is_shutdown(log))
goto shutdown;
} while (xlog_space_left(log, &head->grant) < need_bytes);
@@ -298,7 +295,7 @@ xlog_grant_head_check(
int free_bytes;
int error = 0;
- ASSERT(!(log->l_flags & XLOG_ACTIVE_RECOVERY));
+ ASSERT(!xlog_in_recovery(log));
/*
* If there are other waiters on the queue then give them a chance at
@@ -359,13 +356,13 @@ xfs_log_writable(
* mounts allow internal writes for log recovery and unmount purposes,
* so don't restrict that case.
*/
- if (mp->m_flags & XFS_MOUNT_NORECOVERY)
+ if (xfs_has_norecovery(mp))
return false;
if (xfs_readonly_buftarg(mp->m_ddev_targp))
return false;
if (xfs_readonly_buftarg(mp->m_log->l_targ))
return false;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xlog_is_shutdown(mp->m_log))
return false;
return true;
}
@@ -382,7 +379,7 @@ xfs_log_regrant(
int need_bytes;
int error = 0;
- if (XLOG_FORCED_SHUTDOWN(log))
+ if (xlog_is_shutdown(log))
return -EIO;
XFS_STATS_INC(mp, xs_try_logspace);
@@ -450,7 +447,7 @@ xfs_log_reserve(
ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
- if (XLOG_FORCED_SHUTDOWN(log))
+ if (xlog_is_shutdown(log))
return -EIO;
XFS_STATS_INC(mp, xs_try_logspace);
@@ -487,6 +484,42 @@ out_error:
}
/*
+ * Run all the pending iclog callbacks and wake log force waiters and iclog
+ * space waiters so they can process the newly set shutdown state. We really
+ * don't care what order we process callbacks here because the log is shut down
+ * and so state cannot change on disk anymore.
+ *
+ * We avoid processing actively referenced iclogs so that we don't run callbacks
+ * while the iclog owner might still be preparing the iclog for IO submssion.
+ * These will be caught by xlog_state_iclog_release() and call this function
+ * again to process any callbacks that may have been added to that iclog.
+ */
+static void
+xlog_state_shutdown_callbacks(
+ struct xlog *log)
+{
+ struct xlog_in_core *iclog;
+ LIST_HEAD(cb_list);
+
+ spin_lock(&log->l_icloglock);
+ iclog = log->l_iclog;
+ do {
+ if (atomic_read(&iclog->ic_refcnt)) {
+ /* Reference holder will re-run iclog callbacks. */
+ continue;
+ }
+ list_splice_init(&iclog->ic_callbacks, &cb_list);
+ wake_up_all(&iclog->ic_write_wait);
+ wake_up_all(&iclog->ic_force_wait);
+ } while ((iclog = iclog->ic_next) != log->l_iclog);
+
+ wake_up_all(&log->l_flush_wait);
+ spin_unlock(&log->l_icloglock);
+
+ xlog_cil_process_committed(&cb_list);
+}
+
+/*
* Flush iclog to disk if this is the last reference to the given iclog and the
* it is in the WANT_SYNC state.
*
@@ -520,12 +553,11 @@ xlog_state_release_iclog(
xfs_lsn_t old_tail_lsn)
{
xfs_lsn_t tail_lsn;
+ bool last_ref;
+
lockdep_assert_held(&log->l_icloglock);
trace_xlog_iclog_release(iclog, _RET_IP_);
- if (iclog->ic_state == XLOG_STATE_IOERROR)
- return -EIO;
-
/*
* Grabbing the current log tail needs to be atomic w.r.t. the writing
* of the tail LSN into the iclog so we guarantee that the log tail does
@@ -543,7 +575,23 @@ xlog_state_release_iclog(
iclog->ic_header.h_tail_lsn = cpu_to_be64(tail_lsn);
}
- if (!atomic_dec_and_test(&iclog->ic_refcnt))
+ last_ref = atomic_dec_and_test(&iclog->ic_refcnt);
+
+ if (xlog_is_shutdown(log)) {
+ /*
+ * If there are no more references to this iclog, process the
+ * pending iclog callbacks that were waiting on the release of
+ * this iclog.
+ */
+ if (last_ref) {
+ spin_unlock(&log->l_icloglock);
+ xlog_state_shutdown_callbacks(log);
+ spin_lock(&log->l_icloglock);
+ }
+ return -EIO;
+ }
+
+ if (!last_ref)
return 0;
if (iclog->ic_state != XLOG_STATE_WANT_SYNC) {
@@ -580,25 +628,27 @@ xfs_log_mount(
xfs_daddr_t blk_offset,
int num_bblks)
{
- bool fatal = xfs_sb_version_hascrc(&mp->m_sb);
+ struct xlog *log;
+ bool fatal = xfs_has_crc(mp);
int error = 0;
int min_logfsbs;
- if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
+ if (!xfs_has_norecovery(mp)) {
xfs_notice(mp, "Mounting V%d Filesystem",
XFS_SB_VERSION_NUM(&mp->m_sb));
} else {
xfs_notice(mp,
"Mounting V%d filesystem in no-recovery mode. Filesystem will be inconsistent.",
XFS_SB_VERSION_NUM(&mp->m_sb));
- ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
+ ASSERT(xfs_is_readonly(mp));
}
- mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
- if (IS_ERR(mp->m_log)) {
- error = PTR_ERR(mp->m_log);
+ log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
+ if (IS_ERR(log)) {
+ error = PTR_ERR(log);
goto out;
}
+ mp->m_log = log;
/*
* Validate the given log space and drop a critical message via syslog
@@ -663,51 +713,51 @@ xfs_log_mount(
xfs_warn(mp, "AIL initialisation failed: error %d", error);
goto out_free_log;
}
- mp->m_log->l_ailp = mp->m_ail;
+ log->l_ailp = mp->m_ail;
/*
* skip log recovery on a norecovery mount. pretend it all
* just worked.
*/
- if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
- int readonly = (mp->m_flags & XFS_MOUNT_RDONLY);
-
- if (readonly)
- mp->m_flags &= ~XFS_MOUNT_RDONLY;
-
- error = xlog_recover(mp->m_log);
-
+ if (!xfs_has_norecovery(mp)) {
+ /*
+ * log recovery ignores readonly state and so we need to clear
+ * mount-based read only state so it can write to disk.
+ */
+ bool readonly = test_and_clear_bit(XFS_OPSTATE_READONLY,
+ &mp->m_opstate);
+ error = xlog_recover(log);
if (readonly)
- mp->m_flags |= XFS_MOUNT_RDONLY;
+ set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
if (error) {
xfs_warn(mp, "log mount/recovery failed: error %d",
error);
- xlog_recover_cancel(mp->m_log);
+ xlog_recover_cancel(log);
goto out_destroy_ail;
}
}
- error = xfs_sysfs_init(&mp->m_log->l_kobj, &xfs_log_ktype, &mp->m_kobj,
+ error = xfs_sysfs_init(&log->l_kobj, &xfs_log_ktype, &mp->m_kobj,
"log");
if (error)
goto out_destroy_ail;
/* Normal transactions can now occur */
- mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
+ clear_bit(XLOG_ACTIVE_RECOVERY, &log->l_opstate);
/*
* Now the log has been fully initialised and we know were our
* space grant counters are, we can initialise the permanent ticket
* needed for delayed logging to work.
*/
- xlog_cil_init_post_recovery(mp->m_log);
+ xlog_cil_init_post_recovery(log);
return 0;
out_destroy_ail:
xfs_trans_ail_destroy(mp);
out_free_log:
- xlog_dealloc_log(mp->m_log);
+ xlog_dealloc_log(log);
out:
return error;
}
@@ -726,19 +776,22 @@ int
xfs_log_mount_finish(
struct xfs_mount *mp)
{
- int error = 0;
- bool readonly = (mp->m_flags & XFS_MOUNT_RDONLY);
- bool recovered = mp->m_log->l_flags & XLOG_RECOVERY_NEEDED;
+ struct xlog *log = mp->m_log;
+ bool readonly;
+ int error = 0;
- if (mp->m_flags & XFS_MOUNT_NORECOVERY) {
- ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
+ if (xfs_has_norecovery(mp)) {
+ ASSERT(xfs_is_readonly(mp));
return 0;
- } else if (readonly) {
- /* Allow unlinked processing to proceed */
- mp->m_flags &= ~XFS_MOUNT_RDONLY;
}
/*
+ * log recovery ignores readonly state and so we need to clear
+ * mount-based read only state so it can write to disk.
+ */
+ readonly = test_and_clear_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
+
+ /*
* During the second phase of log recovery, we need iget and
* iput to behave like they do for an active filesystem.
* xfs_fs_drop_inode needs to be able to prevent the deletion
@@ -759,7 +812,8 @@ xfs_log_mount_finish(
* mount failure occurs.
*/
mp->m_super->s_flags |= SB_ACTIVE;
- error = xlog_recover_finish(mp->m_log);
+ if (xlog_recovery_needed(log))
+ error = xlog_recover_finish(log);
if (!error)
xfs_log_work_queue(mp);
mp->m_super->s_flags &= ~SB_ACTIVE;
@@ -774,17 +828,24 @@ xfs_log_mount_finish(
* Don't push in the error case because the AIL may have pending intents
* that aren't removed until recovery is cancelled.
*/
- if (!error && recovered) {
- xfs_log_force(mp, XFS_LOG_SYNC);
- xfs_ail_push_all_sync(mp->m_ail);
+ if (xlog_recovery_needed(log)) {
+ if (!error) {
+ xfs_log_force(mp, XFS_LOG_SYNC);
+ xfs_ail_push_all_sync(mp->m_ail);
+ }
+ xfs_notice(mp, "Ending recovery (logdev: %s)",
+ mp->m_logname ? mp->m_logname : "internal");
+ } else {
+ xfs_info(mp, "Ending clean mount");
}
xfs_buftarg_drain(mp->m_ddev_targp);
+ clear_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate);
if (readonly)
- mp->m_flags |= XFS_MOUNT_RDONLY;
+ set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
/* Make sure the log is dead if we're returning failure. */
- ASSERT(!error || (mp->m_log->l_flags & XLOG_IO_ERROR));
+ ASSERT(!error || xlog_is_shutdown(log));
return error;
}
@@ -830,7 +891,7 @@ xlog_wait_on_iclog(
struct xlog *log = iclog->ic_log;
trace_xlog_iclog_wait_on(iclog, _RET_IP_);
- if (!XLOG_FORCED_SHUTDOWN(log) &&
+ if (!xlog_is_shutdown(log) &&
iclog->ic_state != XLOG_STATE_ACTIVE &&
iclog->ic_state != XLOG_STATE_DIRTY) {
XFS_STATS_INC(log->l_mp, xs_log_force_sleep);
@@ -839,7 +900,7 @@ xlog_wait_on_iclog(
spin_unlock(&log->l_icloglock);
}
- if (XLOG_FORCED_SHUTDOWN(log))
+ if (xlog_is_shutdown(log))
return -EIO;
return 0;
}
@@ -870,7 +931,7 @@ xlog_write_unmount_record(
/* account for space used by record data */
ticket->t_curr_res -= sizeof(ulf);
- return xlog_write(log, &vec, ticket, NULL, NULL, XLOG_UNMOUNT_TRANS);
+ return xlog_write(log, NULL, &vec, ticket, XLOG_UNMOUNT_TRANS);
}
/*
@@ -893,7 +954,7 @@ xlog_unmount_write(
error = xlog_write_unmount_record(log, tic);
/*
* At this point, we're umounting anyway, so there's no point in
- * transitioning log state to IOERROR. Just continue...
+ * transitioning log state to shutdown. Just continue...
*/
out_err:
if (error)
@@ -940,7 +1001,7 @@ xfs_log_unmount_write(
xfs_log_force(mp, XFS_LOG_SYNC);
- if (XLOG_FORCED_SHUTDOWN(log))
+ if (xlog_is_shutdown(log))
return;
/*
@@ -972,6 +1033,20 @@ int
xfs_log_quiesce(
struct xfs_mount *mp)
{
+ /*
+ * Clear log incompat features since we're quiescing the log. Report
+ * failures, though it's not fatal to have a higher log feature
+ * protection level than the log contents actually require.
+ */
+ if (xfs_clear_incompat_log_features(mp)) {
+ int error;
+
+ error = xfs_sync_sb(mp, false);
+ if (error)
+ xfs_warn(mp,
+ "Failed to clear log incompat features on quiesce");
+ }
+
cancel_delayed_work_sync(&mp->m_log->l_work);
xfs_log_force(mp, XFS_LOG_SYNC);
@@ -1049,11 +1124,11 @@ xfs_log_space_wake(
struct xlog *log = mp->m_log;
int free_bytes;
- if (XLOG_FORCED_SHUTDOWN(log))
+ if (xlog_is_shutdown(log))
return;
if (!list_empty_careful(&log->l_write_head.waiters)) {
- ASSERT(!(log->l_flags & XLOG_ACTIVE_RECOVERY));
+ ASSERT(!xlog_in_recovery(log));
spin_lock(&log->l_write_head.lock);
free_bytes = xlog_space_left(log, &log->l_write_head.grant);
@@ -1062,7 +1137,7 @@ xfs_log_space_wake(
}
if (!list_empty_careful(&log->l_reserve_head.waiters)) {
- ASSERT(!(log->l_flags & XLOG_ACTIVE_RECOVERY));
+ ASSERT(!xlog_in_recovery(log));
spin_lock(&log->l_reserve_head.lock);
free_bytes = xlog_space_left(log, &log->l_reserve_head.grant);
@@ -1140,7 +1215,7 @@ xfs_log_cover(
ASSERT((xlog_cil_empty(mp->m_log) && xlog_iclogs_empty(mp->m_log) &&
!xfs_ail_min_lsn(mp->m_log->l_ailp)) ||
- XFS_FORCED_SHUTDOWN(mp));
+ xlog_is_shutdown(mp->m_log));
if (!xfs_log_writable(mp))
return 0;
@@ -1157,7 +1232,7 @@ xfs_log_cover(
* handles this for us.
*/
need_covered = xfs_log_need_covered(mp);
- if (!need_covered && !xfs_sb_version_haslazysbcount(&mp->m_sb))
+ if (!need_covered && !xfs_has_lazysbcount(mp))
return 0;
/*
@@ -1230,16 +1305,18 @@ xlog_assign_tail_lsn(
* wrap the tail, we should blow up. Rather than catch this case here,
* we depend on other ASSERTions in other parts of the code. XXXmiken
*
- * This code also handles the case where the reservation head is behind
- * the tail. The details of this case are described below, but the end
- * result is that we return the size of the log as the amount of space left.
+ * If reservation head is behind the tail, we have a problem. Warn about it,
+ * but then treat it as if the log is empty.
+ *
+ * If the log is shut down, the head and tail may be invalid or out of whack, so
+ * shortcut invalidity asserts in this case so that we don't trigger them
+ * falsely.
*/
STATIC int
xlog_space_left(
struct xlog *log,
atomic64_t *head)
{
- int free_bytes;
int tail_bytes;
int tail_cycle;
int head_cycle;
@@ -1249,29 +1326,30 @@ xlog_space_left(
xlog_crack_atomic_lsn(&log->l_tail_lsn, &tail_cycle, &tail_bytes);
tail_bytes = BBTOB(tail_bytes);
if (tail_cycle == head_cycle && head_bytes >= tail_bytes)
- free_bytes = log->l_logsize - (head_bytes - tail_bytes);
- else if (tail_cycle + 1 < head_cycle)
+ return log->l_logsize - (head_bytes - tail_bytes);
+ if (tail_cycle + 1 < head_cycle)
return 0;
- else if (tail_cycle < head_cycle) {
+
+ /* Ignore potential inconsistency when shutdown. */
+ if (xlog_is_shutdown(log))
+ return log->l_logsize;
+
+ if (tail_cycle < head_cycle) {
ASSERT(tail_cycle == (head_cycle - 1));
- free_bytes = tail_bytes - head_bytes;
- } else {
- /*
- * The reservation head is behind the tail.
- * In this case we just want to return the size of the
- * log as the amount of space left.
- */
- xfs_alert(log->l_mp, "xlog_space_left: head behind tail");
- xfs_alert(log->l_mp,
- " tail_cycle = %d, tail_bytes = %d",
- tail_cycle, tail_bytes);
- xfs_alert(log->l_mp,
- " GH cycle = %d, GH bytes = %d",
- head_cycle, head_bytes);
- ASSERT(0);
- free_bytes = log->l_logsize;
+ return tail_bytes - head_bytes;
}
- return free_bytes;
+
+ /*
+ * The reservation head is behind the tail. In this case we just want to
+ * return the size of the log as the amount of space left.
+ */
+ xfs_alert(log->l_mp, "xlog_space_left: head behind tail");
+ xfs_alert(log->l_mp, " tail_cycle = %d, tail_bytes = %d",
+ tail_cycle, tail_bytes);
+ xfs_alert(log->l_mp, " GH cycle = %d, GH bytes = %d",
+ head_cycle, head_bytes);
+ ASSERT(0);
+ return log->l_logsize;
}
@@ -1349,6 +1427,32 @@ xfs_log_work_queue(
}
/*
+ * Clear the log incompat flags if we have the opportunity.
+ *
+ * This only happens if we're about to log the second dummy transaction as part
+ * of covering the log and we can get the log incompat feature usage lock.
+ */
+static inline void
+xlog_clear_incompat(
+ struct xlog *log)
+{
+ struct xfs_mount *mp = log->l_mp;
+
+ if (!xfs_sb_has_incompat_log_feature(&mp->m_sb,
+ XFS_SB_FEAT_INCOMPAT_LOG_ALL))
+ return;
+
+ if (log->l_covered_state != XLOG_STATE_COVER_DONE2)
+ return;
+
+ if (!down_write_trylock(&log->l_incompat_users))
+ return;
+
+ xfs_clear_incompat_log_features(mp);
+ up_write(&log->l_incompat_users);
+}
+
+/*
* Every sync period we need to unpin all items in the AIL and push them to
* disk. If there is nothing dirty, then we might need to cover the log to
* indicate that the filesystem is idle.
@@ -1374,6 +1478,7 @@ xfs_log_worker(
* synchronously log the superblock instead to ensure the
* superblock is immediately unpinned and can be written back.
*/
+ xlog_clear_incompat(log);
xfs_sync_sb(mp, true);
} else
xfs_log_force(mp, 0);
@@ -1417,7 +1522,7 @@ xlog_alloc_log(
log->l_logBBstart = blk_offset;
log->l_logBBsize = num_bblks;
log->l_covered_state = XLOG_STATE_COVER_IDLE;
- log->l_flags |= XLOG_ACTIVE_RECOVERY;
+ set_bit(XLOG_ACTIVE_RECOVERY, &log->l_opstate);
INIT_DELAYED_WORK(&log->l_work, xfs_log_worker);
log->l_prev_block = -1;
@@ -1426,7 +1531,7 @@ xlog_alloc_log(
xlog_assign_atomic_lsn(&log->l_last_sync_lsn, 1, 0);
log->l_curr_cycle = 1; /* 0 is bad since this is initial value */
- if (xfs_sb_version_haslogv2(&mp->m_sb) && mp->m_sb.sb_logsunit > 1)
+ if (xfs_has_logv2(mp) && mp->m_sb.sb_logsunit > 1)
log->l_iclog_roundoff = mp->m_sb.sb_logsunit;
else
log->l_iclog_roundoff = BBSIZE;
@@ -1435,7 +1540,7 @@ xlog_alloc_log(
xlog_grant_head_init(&log->l_write_head);
error = -EFSCORRUPTED;
- if (xfs_sb_version_hassector(&mp->m_sb)) {
+ if (xfs_has_sector(mp)) {
log2_size = mp->m_sb.sb_logsectlog;
if (log2_size < BBSHIFT) {
xfs_warn(mp, "Log sector size too small (0x%x < 0x%x)",
@@ -1452,7 +1557,7 @@ xlog_alloc_log(
/* for larger sector sizes, must have v2 or external log */
if (log2_size && log->l_logBBstart > 0 &&
- !xfs_sb_version_haslogv2(&mp->m_sb)) {
+ !xfs_has_logv2(mp)) {
xfs_warn(mp,
"log sector size (0x%x) invalid for configuration.",
log2_size);
@@ -1461,6 +1566,8 @@ xlog_alloc_log(
}
log->l_sectBBsize = 1 << log2_size;
+ init_rwsem(&log->l_incompat_users);
+
xlog_get_iclog_buffer_size(mp, log);
spin_lock_init(&log->l_icloglock);
@@ -1476,7 +1583,6 @@ xlog_alloc_log(
*/
ASSERT(log->l_iclog_size >= 4096);
for (i = 0; i < log->l_iclog_bufs; i++) {
- int align_mask = xfs_buftarg_dma_alignment(mp->m_logdev_targp);
size_t bvec_size = howmany(log->l_iclog_size, PAGE_SIZE) *
sizeof(struct bio_vec);
@@ -1488,8 +1594,8 @@ xlog_alloc_log(
iclog->ic_prev = prev_iclog;
prev_iclog = iclog;
- iclog->ic_data = kmem_alloc_io(log->l_iclog_size, align_mask,
- KM_MAYFAIL | KM_ZERO);
+ iclog->ic_data = kvzalloc(log->l_iclog_size,
+ GFP_KERNEL | __GFP_RETRY_MAYFAIL);
if (!iclog->ic_data)
goto out_free_iclog;
#ifdef DEBUG
@@ -1499,7 +1605,7 @@ xlog_alloc_log(
memset(head, 0, sizeof(xlog_rec_header_t));
head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
head->h_version = cpu_to_be32(
- xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? 2 : 1);
+ xfs_has_logv2(log->l_mp) ? 2 : 1);
head->h_size = cpu_to_be32(log->l_iclog_size);
/* new fields */
head->h_fmt = cpu_to_be32(XLOG_FMT);
@@ -1551,37 +1657,6 @@ out:
} /* xlog_alloc_log */
/*
- * Write out the commit record of a transaction associated with the given
- * ticket to close off a running log write. Return the lsn of the commit record.
- */
-int
-xlog_commit_record(
- struct xlog *log,
- struct xlog_ticket *ticket,
- struct xlog_in_core **iclog,
- xfs_lsn_t *lsn)
-{
- struct xfs_log_iovec reg = {
- .i_addr = NULL,
- .i_len = 0,
- .i_type = XLOG_REG_TYPE_COMMIT,
- };
- struct xfs_log_vec vec = {
- .lv_niovecs = 1,
- .lv_iovecp = &reg,
- };
- int error;
-
- if (XLOG_FORCED_SHUTDOWN(log))
- return -EIO;
-
- error = xlog_write(log, &vec, ticket, lsn, iclog, XLOG_COMMIT_TRANS);
- if (error)
- xfs_force_shutdown(log->l_mp, SHUTDOWN_LOG_IO_ERROR);
- return error;
-}
-
-/*
* Compute the LSN that we'd need to push the log tail towards in order to have
* (a) enough on-disk log space to log the number of bytes specified, (b) at
* least 25% of the log space free, and (c) at least 256 blocks free. If the
@@ -1653,7 +1728,7 @@ xlog_grant_push_ail(
xfs_lsn_t threshold_lsn;
threshold_lsn = xlog_grant_push_threshold(log, need_bytes);
- if (threshold_lsn == NULLCOMMITLSN || XLOG_FORCED_SHUTDOWN(log))
+ if (threshold_lsn == NULLCOMMITLSN || xlog_is_shutdown(log))
return;
/*
@@ -1689,7 +1764,7 @@ xlog_pack_data(
dp += BBSIZE;
}
- if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+ if (xfs_has_logv2(log->l_mp)) {
xlog_in_core_2_t *xhdr = iclog->ic_data;
for ( ; i < BTOBB(size); i++) {
@@ -1726,7 +1801,7 @@ xlog_cksum(
offsetof(struct xlog_rec_header, h_crc));
/* ... then for additional cycle data for v2 logs ... */
- if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+ if (xfs_has_logv2(log->l_mp)) {
union xlog_in_core2 *xhdr = (union xlog_in_core2 *)rhead;
int i;
int xheads;
@@ -1795,7 +1870,7 @@ xlog_write_iclog(
* across the log IO to archieve that.
*/
down(&iclog->ic_sema);
- if (unlikely(iclog->ic_state == XLOG_STATE_IOERROR)) {
+ if (xlog_is_shutdown(log)) {
/*
* It would seem logical to return EIO here, but we rely on
* the log state machine to propagate I/O errors instead of
@@ -1953,7 +2028,7 @@ xlog_sync(
/* real byte length */
size = iclog->ic_offset;
- if (xfs_sb_version_haslogv2(&log->l_mp->m_sb))
+ if (xfs_has_logv2(log->l_mp))
size += roundoff;
iclog->ic_header.h_len = cpu_to_be32(size);
@@ -2303,8 +2378,7 @@ xlog_write_copy_finish(
int *data_cnt,
int *partial_copy,
int *partial_copy_len,
- int log_offset,
- struct xlog_in_core **commit_iclog)
+ int log_offset)
{
int error;
@@ -2323,27 +2397,20 @@ xlog_write_copy_finish(
*partial_copy = 0;
*partial_copy_len = 0;
- if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) {
- /* no more space in this iclog - push it. */
- spin_lock(&log->l_icloglock);
- xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt);
- *record_cnt = 0;
- *data_cnt = 0;
-
- if (iclog->ic_state == XLOG_STATE_ACTIVE)
- xlog_state_switch_iclogs(log, iclog, 0);
- else
- ASSERT(iclog->ic_state == XLOG_STATE_WANT_SYNC ||
- iclog->ic_state == XLOG_STATE_IOERROR);
- if (!commit_iclog)
- goto release_iclog;
- spin_unlock(&log->l_icloglock);
- ASSERT(flags & XLOG_COMMIT_TRANS);
- *commit_iclog = iclog;
- }
+ if (iclog->ic_size - log_offset > sizeof(xlog_op_header_t))
+ return 0;
- return 0;
+ /* no more space in this iclog - push it. */
+ spin_lock(&log->l_icloglock);
+ xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt);
+ *record_cnt = 0;
+ *data_cnt = 0;
+ if (iclog->ic_state == XLOG_STATE_ACTIVE)
+ xlog_state_switch_iclogs(log, iclog, 0);
+ else
+ ASSERT(iclog->ic_state == XLOG_STATE_WANT_SYNC ||
+ xlog_is_shutdown(log));
release_iclog:
error = xlog_state_release_iclog(log, iclog, 0);
spin_unlock(&log->l_icloglock);
@@ -2393,10 +2460,9 @@ release_iclog:
int
xlog_write(
struct xlog *log,
+ struct xfs_cil_ctx *ctx,
struct xfs_log_vec *log_vector,
struct xlog_ticket *ticket,
- xfs_lsn_t *start_lsn,
- struct xlog_in_core **commit_iclog,
uint optype)
{
struct xlog_in_core *iclog = NULL;
@@ -2426,8 +2492,6 @@ xlog_write(
}
len = xlog_write_calc_vec_length(ticket, log_vector, optype);
- if (start_lsn)
- *start_lsn = 0;
while (lv && (!lv->lv_niovecs || index < lv->lv_niovecs)) {
void *ptr;
int log_offset;
@@ -2440,9 +2504,15 @@ xlog_write(
ASSERT(log_offset <= iclog->ic_size - 1);
ptr = iclog->ic_datap + log_offset;
- /* Start_lsn is the first lsn written to. */
- if (start_lsn && !*start_lsn)
- *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn);
+ /*
+ * If we have a context pointer, pass it the first iclog we are
+ * writing to so it can record state needed for iclog write
+ * ordering.
+ */
+ if (ctx) {
+ xlog_cil_set_ctx_write_state(ctx, iclog);
+ ctx = NULL;
+ }
/*
* This loop writes out as many regions as can fit in the amount
@@ -2521,8 +2591,7 @@ xlog_write(
&record_cnt, &data_cnt,
&partial_copy,
&partial_copy_len,
- log_offset,
- commit_iclog);
+ log_offset);
if (error)
return error;
@@ -2560,12 +2629,7 @@ next_lv:
spin_lock(&log->l_icloglock);
xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
- if (commit_iclog) {
- ASSERT(optype & XLOG_COMMIT_TRANS);
- *commit_iclog = iclog;
- } else {
- error = xlog_state_release_iclog(log, iclog, 0);
- }
+ error = xlog_state_release_iclog(log, iclog, 0);
spin_unlock(&log->l_icloglock);
return error;
@@ -2751,8 +2815,7 @@ xlog_state_set_callback(
static bool
xlog_state_iodone_process_iclog(
struct xlog *log,
- struct xlog_in_core *iclog,
- bool *ioerror)
+ struct xlog_in_core *iclog)
{
xfs_lsn_t lowest_lsn;
xfs_lsn_t header_lsn;
@@ -2764,15 +2827,6 @@ xlog_state_iodone_process_iclog(
* Skip all iclogs in the ACTIVE & DIRTY states:
*/
return false;
- case XLOG_STATE_IOERROR:
- /*
- * Between marking a filesystem SHUTDOWN and stopping the log,
- * we do flush all iclogs to disk (if there wasn't a log I/O
- * error). So, we do want things to go smoothly in case of just
- * a SHUTDOWN w/o a LOG_IO_ERROR.
- */
- *ioerror = true;
- return false;
case XLOG_STATE_DONE_SYNC:
/*
* Now that we have an iclog that is in the DONE_SYNC state, do
@@ -2796,72 +2850,75 @@ xlog_state_iodone_process_iclog(
}
}
-STATIC void
-xlog_state_do_callback(
+/*
+ * Loop over all the iclogs, running attached callbacks on them. Return true if
+ * we ran any callbacks, indicating that we dropped the icloglock. We don't need
+ * to handle transient shutdown state here at all because
+ * xlog_state_shutdown_callbacks() will be run to do the necessary shutdown
+ * cleanup of the callbacks.
+ */
+static bool
+xlog_state_do_iclog_callbacks(
struct xlog *log)
+ __releases(&log->l_icloglock)
+ __acquires(&log->l_icloglock)
{
- struct xlog_in_core *iclog;
- struct xlog_in_core *first_iclog;
- bool cycled_icloglock;
- bool ioerror;
- int flushcnt = 0;
- int repeats = 0;
+ struct xlog_in_core *first_iclog = log->l_iclog;
+ struct xlog_in_core *iclog = first_iclog;
+ bool ran_callback = false;
- spin_lock(&log->l_icloglock);
do {
- /*
- * Scan all iclogs starting with the one pointed to by the
- * log. Reset this starting point each time the log is
- * unlocked (during callbacks).
- *
- * Keep looping through iclogs until one full pass is made
- * without running any callbacks.
- */
- first_iclog = log->l_iclog;
- iclog = log->l_iclog;
- cycled_icloglock = false;
- ioerror = false;
- repeats++;
+ LIST_HEAD(cb_list);
- do {
- LIST_HEAD(cb_list);
+ if (xlog_state_iodone_process_iclog(log, iclog))
+ break;
+ if (iclog->ic_state != XLOG_STATE_CALLBACK) {
+ iclog = iclog->ic_next;
+ continue;
+ }
+ list_splice_init(&iclog->ic_callbacks, &cb_list);
+ spin_unlock(&log->l_icloglock);
- if (xlog_state_iodone_process_iclog(log, iclog,
- &ioerror))
- break;
+ trace_xlog_iclog_callbacks_start(iclog, _RET_IP_);
+ xlog_cil_process_committed(&cb_list);
+ trace_xlog_iclog_callbacks_done(iclog, _RET_IP_);
+ ran_callback = true;
- if (iclog->ic_state != XLOG_STATE_CALLBACK &&
- iclog->ic_state != XLOG_STATE_IOERROR) {
- iclog = iclog->ic_next;
- continue;
- }
- list_splice_init(&iclog->ic_callbacks, &cb_list);
- spin_unlock(&log->l_icloglock);
+ spin_lock(&log->l_icloglock);
+ xlog_state_clean_iclog(log, iclog);
+ iclog = iclog->ic_next;
+ } while (iclog != first_iclog);
+
+ return ran_callback;
+}
- trace_xlog_iclog_callbacks_start(iclog, _RET_IP_);
- xlog_cil_process_committed(&cb_list);
- trace_xlog_iclog_callbacks_done(iclog, _RET_IP_);
- cycled_icloglock = true;
- spin_lock(&log->l_icloglock);
- if (XLOG_FORCED_SHUTDOWN(log))
- wake_up_all(&iclog->ic_force_wait);
- else
- xlog_state_clean_iclog(log, iclog);
- iclog = iclog->ic_next;
- } while (first_iclog != iclog);
+/*
+ * Loop running iclog completion callbacks until there are no more iclogs in a
+ * state that can run callbacks.
+ */
+STATIC void
+xlog_state_do_callback(
+ struct xlog *log)
+{
+ int flushcnt = 0;
+ int repeats = 0;
+
+ spin_lock(&log->l_icloglock);
+ while (xlog_state_do_iclog_callbacks(log)) {
+ if (xlog_is_shutdown(log))
+ break;
- if (repeats > 5000) {
+ if (++repeats > 5000) {
flushcnt += repeats;
repeats = 0;
xfs_warn(log->l_mp,
"%s: possible infinite loop (%d iterations)",
__func__, flushcnt);
}
- } while (!ioerror && cycled_icloglock);
+ }
- if (log->l_iclog->ic_state == XLOG_STATE_ACTIVE ||
- log->l_iclog->ic_state == XLOG_STATE_IOERROR)
+ if (log->l_iclog->ic_state == XLOG_STATE_ACTIVE)
wake_up_all(&log->l_flush_wait);
spin_unlock(&log->l_icloglock);
@@ -2871,13 +2928,6 @@ xlog_state_do_callback(
/*
* Finish transitioning this iclog to the dirty state.
*
- * Make sure that we completely execute this routine only when this is
- * the last call to the iclog. There is a good chance that iclog flushes,
- * when we reach the end of the physical log, get turned into 2 separate
- * calls to bwrite. Hence, one iclog flush could generate two calls to this
- * routine. By using the reference count bwritecnt, we guarantee that only
- * the second completion goes through.
- *
* Callbacks could take time, so they are done outside the scope of the
* global state machine log lock.
*/
@@ -2896,7 +2946,7 @@ xlog_state_done_syncing(
* split log writes, on the second, we shut down the file system and
* no iclogs should ever be attempted to be written to disk again.
*/
- if (!XLOG_FORCED_SHUTDOWN(log)) {
+ if (!xlog_is_shutdown(log)) {
ASSERT(iclog->ic_state == XLOG_STATE_SYNCING);
iclog->ic_state = XLOG_STATE_DONE_SYNC;
}
@@ -2944,7 +2994,7 @@ xlog_state_get_iclog_space(
restart:
spin_lock(&log->l_icloglock);
- if (XLOG_FORCED_SHUTDOWN(log)) {
+ if (xlog_is_shutdown(log)) {
spin_unlock(&log->l_icloglock);
return -EIO;
}
@@ -3122,7 +3172,7 @@ xfs_log_ticket_ungrant(
* This routine will mark the current iclog in the ring as WANT_SYNC and move
* the current iclog pointer to the next iclog in the ring.
*/
-STATIC void
+void
xlog_state_switch_iclogs(
struct xlog *log,
struct xlog_in_core *iclog,
@@ -3237,10 +3287,10 @@ xfs_log_force(
xlog_cil_force(log);
spin_lock(&log->l_icloglock);
- iclog = log->l_iclog;
- if (iclog->ic_state == XLOG_STATE_IOERROR)
+ if (xlog_is_shutdown(log))
goto out_error;
+ iclog = log->l_iclog;
trace_xlog_iclog_force(iclog, _RET_IP_);
if (iclog->ic_state == XLOG_STATE_DIRTY ||
@@ -3294,6 +3344,20 @@ out_error:
return -EIO;
}
+/*
+ * Force the log to a specific LSN.
+ *
+ * If an iclog with that lsn can be found:
+ * If it is in the DIRTY state, just return.
+ * If it is in the ACTIVE state, move the in-core log into the WANT_SYNC
+ * state and go to sleep or return.
+ * If it is in any other state, go to sleep or return.
+ *
+ * Synchronous forces are implemented with a wait queue. All callers trying
+ * to force a given lsn to disk must wait on the queue attached to the
+ * specific in-core log. When given in-core log finally completes its write
+ * to disk, that thread will wake up all threads waiting on the queue.
+ */
static int
xlog_force_lsn(
struct xlog *log,
@@ -3306,10 +3370,10 @@ xlog_force_lsn(
bool completed;
spin_lock(&log->l_icloglock);
- iclog = log->l_iclog;
- if (iclog->ic_state == XLOG_STATE_IOERROR)
+ if (xlog_is_shutdown(log))
goto out_error;
+ iclog = log->l_iclog;
while (be64_to_cpu(iclog->ic_header.h_lsn) != lsn) {
trace_xlog_iclog_force_lsn(iclog, _RET_IP_);
iclog = iclog->ic_next;
@@ -3379,18 +3443,13 @@ out_error:
}
/*
- * Force the in-core log to disk for a specific LSN.
- *
- * Find in-core log with lsn.
- * If it is in the DIRTY state, just return.
- * If it is in the ACTIVE state, move the in-core log into the WANT_SYNC
- * state and go to sleep or return.
- * If it is in any other state, go to sleep or return.
+ * Force the log to a specific checkpoint sequence.
*
- * Synchronous forces are implemented with a wait queue. All callers trying
- * to force a given lsn to disk must wait on the queue attached to the
- * specific in-core log. When given in-core log finally completes its write
- * to disk, that thread will wake up all threads waiting on the queue.
+ * First force the CIL so that all the required changes have been flushed to the
+ * iclogs. If the CIL force completed it will return a commit LSN that indicates
+ * the iclog that needs to be flushed to stable storage. If the caller needs
+ * a synchronous log force, we will wait on the iclog with the LSN returned by
+ * xlog_cil_force_seq() to be completed.
*/
int
xfs_log_force_seq(
@@ -3619,17 +3678,15 @@ xlog_verify_grant_tail(
xlog_crack_atomic_lsn(&log->l_tail_lsn, &tail_cycle, &tail_blocks);
if (tail_cycle != cycle) {
if (cycle - 1 != tail_cycle &&
- !(log->l_flags & XLOG_TAIL_WARN)) {
+ !test_and_set_bit(XLOG_TAIL_WARN, &log->l_opstate)) {
xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES,
"%s: cycle - 1 != tail_cycle", __func__);
- log->l_flags |= XLOG_TAIL_WARN;
}
if (space > BBTOB(tail_blocks) &&
- !(log->l_flags & XLOG_TAIL_WARN)) {
+ !test_and_set_bit(XLOG_TAIL_WARN, &log->l_opstate)) {
xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES,
"%s: space > BBTOB(tail_blocks)", __func__);
- log->l_flags |= XLOG_TAIL_WARN;
}
}
}
@@ -3765,105 +3822,66 @@ xlog_verify_iclog(
#endif
/*
- * Mark all iclogs IOERROR. l_icloglock is held by the caller.
- */
-STATIC int
-xlog_state_ioerror(
- struct xlog *log)
-{
- xlog_in_core_t *iclog, *ic;
-
- iclog = log->l_iclog;
- if (iclog->ic_state != XLOG_STATE_IOERROR) {
- /*
- * Mark all the incore logs IOERROR.
- * From now on, no log flushes will result.
- */
- ic = iclog;
- do {
- ic->ic_state = XLOG_STATE_IOERROR;
- ic = ic->ic_next;
- } while (ic != iclog);
- return 0;
- }
- /*
- * Return non-zero, if state transition has already happened.
- */
- return 1;
-}
-
-/*
- * This is called from xfs_force_shutdown, when we're forcibly
- * shutting down the filesystem, typically because of an IO error.
+ * Perform a forced shutdown on the log. This should be called once and once
+ * only by the high level filesystem shutdown code to shut the log subsystem
+ * down cleanly.
+ *
* Our main objectives here are to make sure that:
- * a. if !logerror, flush the logs to disk. Anything modified
- * after this is ignored.
- * b. the filesystem gets marked 'SHUTDOWN' for all interested
- * parties to find out, 'atomically'.
- * c. those who're sleeping on log reservations, pinned objects and
- * other resources get woken up, and be told the bad news.
- * d. nothing new gets queued up after (b) and (c) are done.
+ * a. if the shutdown was not due to a log IO error, flush the logs to
+ * disk. Anything modified after this is ignored.
+ * b. the log gets atomically marked 'XLOG_IO_ERROR' for all interested
+ * parties to find out. Nothing new gets queued after this is done.
+ * c. Tasks sleeping on log reservations, pinned objects and
+ * other resources get woken up.
*
- * Note: for the !logerror case we need to flush the regions held in memory out
- * to disk first. This needs to be done before the log is marked as shutdown,
- * otherwise the iclog writes will fail.
+ * Return true if the shutdown cause was a log IO error and we actually shut the
+ * log down.
*/
-int
-xfs_log_force_umount(
- struct xfs_mount *mp,
- int logerror)
+bool
+xlog_force_shutdown(
+ struct xlog *log,
+ int shutdown_flags)
{
- struct xlog *log;
- int retval;
-
- log = mp->m_log;
+ bool log_error = (shutdown_flags & SHUTDOWN_LOG_IO_ERROR);
/*
- * If this happens during log recovery, don't worry about
- * locking; the log isn't open for business yet.
+ * If this happens during log recovery then we aren't using the runtime
+ * log mechanisms yet so there's nothing to shut down.
*/
- if (!log ||
- log->l_flags & XLOG_ACTIVE_RECOVERY) {
- mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
- if (mp->m_sb_bp)
- mp->m_sb_bp->b_flags |= XBF_DONE;
- return 0;
- }
+ if (!log || xlog_in_recovery(log))
+ return false;
- /*
- * Somebody could've already done the hard work for us.
- * No need to get locks for this.
- */
- if (logerror && log->l_iclog->ic_state == XLOG_STATE_IOERROR) {
- ASSERT(XLOG_FORCED_SHUTDOWN(log));
- return 1;
- }
+ ASSERT(!xlog_is_shutdown(log));
/*
* Flush all the completed transactions to disk before marking the log
- * being shut down. We need to do it in this order to ensure that
- * completed operations are safely on disk before we shut down, and that
- * we don't have to issue any buffer IO after the shutdown flags are set
- * to guarantee this.
+ * being shut down. We need to do this first as shutting down the log
+ * before the force will prevent the log force from flushing the iclogs
+ * to disk.
+ *
+ * Re-entry due to a log IO error shutdown during the log force is
+ * prevented by the atomicity of higher level shutdown code.
*/
- if (!logerror)
- xfs_log_force(mp, XFS_LOG_SYNC);
+ if (!log_error)
+ xfs_log_force(log->l_mp, XFS_LOG_SYNC);
/*
- * mark the filesystem and the as in a shutdown state and wake
- * everybody up to tell them the bad news.
+ * Atomically set the shutdown state. If the shutdown state is already
+ * set, there someone else is performing the shutdown and so we are done
+ * here. This should never happen because we should only ever get called
+ * once by the first shutdown caller.
+ *
+ * Much of the log state machine transitions assume that shutdown state
+ * cannot change once they hold the log->l_icloglock. Hence we need to
+ * hold that lock here, even though we use the atomic test_and_set_bit()
+ * operation to set the shutdown state.
*/
spin_lock(&log->l_icloglock);
- mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
- if (mp->m_sb_bp)
- mp->m_sb_bp->b_flags |= XBF_DONE;
-
- /*
- * Mark the log and the iclogs with IO error flags to prevent any
- * further log IO from being issued or completed.
- */
- log->l_flags |= XLOG_IO_ERROR;
- retval = xlog_state_ioerror(log);
+ if (test_and_set_bit(XLOG_IO_ERROR, &log->l_opstate)) {
+ spin_unlock(&log->l_icloglock);
+ ASSERT(0);
+ return false;
+ }
spin_unlock(&log->l_icloglock);
/*
@@ -3883,12 +3901,12 @@ xfs_log_force_umount(
* avoid races.
*/
spin_lock(&log->l_cilp->xc_push_lock);
+ wake_up_all(&log->l_cilp->xc_start_wait);
wake_up_all(&log->l_cilp->xc_commit_wait);
spin_unlock(&log->l_cilp->xc_push_lock);
- xlog_state_do_callback(log);
+ xlog_state_shutdown_callbacks(log);
- /* return non-zero if log IOERROR transition had already happened */
- return retval;
+ return log_error;
}
STATIC int
@@ -3926,7 +3944,7 @@ xfs_log_check_lsn(
* resets the in-core LSN. We can't validate in this mode, but
* modifications are not allowed anyways so just return true.
*/
- if (mp->m_flags & XFS_MOUNT_NORECOVERY)
+ if (xfs_has_norecovery(mp))
return true;
/*
@@ -3952,11 +3970,22 @@ xfs_log_check_lsn(
return valid;
}
-bool
-xfs_log_in_recovery(
- struct xfs_mount *mp)
+/*
+ * Notify the log that we're about to start using a feature that is protected
+ * by a log incompat feature flag. This will prevent log covering from
+ * clearing those flags.
+ */
+void
+xlog_use_incompat_feat(
+ struct xlog *log)
{
- struct xlog *log = mp->m_log;
+ down_read(&log->l_incompat_users);
+}
- return log->l_flags & XLOG_ACTIVE_RECOVERY;
+/* Notify the log that we've finished using log incompat features. */
+void
+xlog_drop_incompat_feat(
+ struct xlog *log)
+{
+ up_read(&log->l_incompat_users);
}
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 813b972e9788..dc1b77b92fc1 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -104,6 +104,7 @@ struct xlog_ticket;
struct xfs_log_item;
struct xfs_item_ops;
struct xfs_trans;
+struct xlog;
int xfs_log_force(struct xfs_mount *mp, uint flags);
int xfs_log_force_seq(struct xfs_mount *mp, xfs_csn_t seq, uint flags,
@@ -125,7 +126,6 @@ int xfs_log_reserve(struct xfs_mount *mp,
bool permanent);
int xfs_log_regrant(struct xfs_mount *mp, struct xlog_ticket *tic);
void xfs_log_unmount(struct xfs_mount *mp);
-int xfs_log_force_umount(struct xfs_mount *mp, int logerror);
bool xfs_log_writable(struct xfs_mount *mp);
struct xlog_ticket *xfs_log_ticket_get(struct xlog_ticket *ticket);
@@ -138,8 +138,11 @@ void xfs_log_work_queue(struct xfs_mount *mp);
int xfs_log_quiesce(struct xfs_mount *mp);
void xfs_log_clean(struct xfs_mount *mp);
bool xfs_log_check_lsn(struct xfs_mount *, xfs_lsn_t);
-bool xfs_log_in_recovery(struct xfs_mount *);
xfs_lsn_t xlog_grant_push_threshold(struct xlog *log, int need_bytes);
+bool xlog_force_shutdown(struct xlog *log, int shutdown_flags);
+
+void xlog_use_incompat_feat(struct xlog *log);
+void xlog_drop_incompat_feat(struct xlog *log);
#endif /* __XFS_LOG_H__ */
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 4c44bc3786c0..6c93c8ada6f3 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -48,6 +48,34 @@ xlog_cil_ticket_alloc(
}
/*
+ * Unavoidable forward declaration - xlog_cil_push_work() calls
+ * xlog_cil_ctx_alloc() itself.
+ */
+static void xlog_cil_push_work(struct work_struct *work);
+
+static struct xfs_cil_ctx *
+xlog_cil_ctx_alloc(void)
+{
+ struct xfs_cil_ctx *ctx;
+
+ ctx = kmem_zalloc(sizeof(*ctx), KM_NOFS);
+ INIT_LIST_HEAD(&ctx->committing);
+ INIT_LIST_HEAD(&ctx->busy_extents);
+ INIT_WORK(&ctx->push_work, xlog_cil_push_work);
+ return ctx;
+}
+
+static void
+xlog_cil_ctx_switch(
+ struct xfs_cil *cil,
+ struct xfs_cil_ctx *ctx)
+{
+ ctx->sequence = ++cil->xc_current_sequence;
+ ctx->cil = cil;
+ cil->xc_ctx = ctx;
+}
+
+/*
* After the first stage of log recovery is done, we know where the head and
* tail of the log are. We need this log initialisation done before we can
* initialise the first CIL checkpoint context.
@@ -185,7 +213,15 @@ xlog_cil_alloc_shadow_bufs(
*/
kmem_free(lip->li_lv_shadow);
- lv = kmem_alloc_large(buf_size, KM_NOFS);
+ /*
+ * We are in transaction context, which means this
+ * allocation will pick up GFP_NOFS from the
+ * memalloc_nofs_save/restore context the transaction
+ * holds. This means we can use GFP_KERNEL here so the
+ * generic kvmalloc() code will run vmalloc on
+ * contiguous page allocation failure as we require.
+ */
+ lv = kvmalloc(buf_size, GFP_KERNEL);
memset(lv, 0, xlog_cil_iovec_space(niovecs));
lv->lv_item = lip;
@@ -535,7 +571,7 @@ xlog_discard_busy_extents(
struct blk_plug plug;
int error = 0;
- ASSERT(mp->m_flags & XFS_MOUNT_DISCARD);
+ ASSERT(xfs_has_discard(mp));
blk_start_plug(&plug);
list_for_each_entry(busyp, list, list) {
@@ -576,7 +612,7 @@ xlog_cil_committed(
struct xfs_cil_ctx *ctx)
{
struct xfs_mount *mp = ctx->cil->xc_log->l_mp;
- bool abort = XLOG_FORCED_SHUTDOWN(ctx->cil->xc_log);
+ bool abort = xlog_is_shutdown(ctx->cil->xc_log);
/*
* If the I/O failed, we're aborting the commit and already shutdown.
@@ -587,6 +623,7 @@ xlog_cil_committed(
*/
if (abort) {
spin_lock(&ctx->cil->xc_push_lock);
+ wake_up_all(&ctx->cil->xc_start_wait);
wake_up_all(&ctx->cil->xc_commit_wait);
spin_unlock(&ctx->cil->xc_push_lock);
}
@@ -596,7 +633,7 @@ xlog_cil_committed(
xfs_extent_busy_sort(&ctx->busy_extents);
xfs_extent_busy_clear(mp, &ctx->busy_extents,
- (mp->m_flags & XFS_MOUNT_DISCARD) && !abort);
+ xfs_has_discard(mp) && !abort);
spin_lock(&ctx->cil->xc_push_lock);
list_del(&ctx->committing);
@@ -624,6 +661,180 @@ xlog_cil_process_committed(
}
/*
+* Record the LSN of the iclog we were just granted space to start writing into.
+* If the context doesn't have a start_lsn recorded, then this iclog will
+* contain the start record for the checkpoint. Otherwise this write contains
+* the commit record for the checkpoint.
+*/
+void
+xlog_cil_set_ctx_write_state(
+ struct xfs_cil_ctx *ctx,
+ struct xlog_in_core *iclog)
+{
+ struct xfs_cil *cil = ctx->cil;
+ xfs_lsn_t lsn = be64_to_cpu(iclog->ic_header.h_lsn);
+
+ ASSERT(!ctx->commit_lsn);
+ if (!ctx->start_lsn) {
+ spin_lock(&cil->xc_push_lock);
+ /*
+ * The LSN we need to pass to the log items on transaction
+ * commit is the LSN reported by the first log vector write, not
+ * the commit lsn. If we use the commit record lsn then we can
+ * move the tail beyond the grant write head.
+ */
+ ctx->start_lsn = lsn;
+ wake_up_all(&cil->xc_start_wait);
+ spin_unlock(&cil->xc_push_lock);
+ return;
+ }
+
+ /*
+ * Take a reference to the iclog for the context so that we still hold
+ * it when xlog_write is done and has released it. This means the
+ * context controls when the iclog is released for IO.
+ */
+ atomic_inc(&iclog->ic_refcnt);
+
+ /*
+ * xlog_state_get_iclog_space() guarantees there is enough space in the
+ * iclog for an entire commit record, so we can attach the context
+ * callbacks now. This needs to be done before we make the commit_lsn
+ * visible to waiters so that checkpoints with commit records in the
+ * same iclog order their IO completion callbacks in the same order that
+ * the commit records appear in the iclog.
+ */
+ spin_lock(&cil->xc_log->l_icloglock);
+ list_add_tail(&ctx->iclog_entry, &iclog->ic_callbacks);
+ spin_unlock(&cil->xc_log->l_icloglock);
+
+ /*
+ * Now we can record the commit LSN and wake anyone waiting for this
+ * sequence to have the ordered commit record assigned to a physical
+ * location in the log.
+ */
+ spin_lock(&cil->xc_push_lock);
+ ctx->commit_iclog = iclog;
+ ctx->commit_lsn = lsn;
+ wake_up_all(&cil->xc_commit_wait);
+ spin_unlock(&cil->xc_push_lock);
+}
+
+
+/*
+ * Ensure that the order of log writes follows checkpoint sequence order. This
+ * relies on the context LSN being zero until the log write has guaranteed the
+ * LSN that the log write will start at via xlog_state_get_iclog_space().
+ */
+enum _record_type {
+ _START_RECORD,
+ _COMMIT_RECORD,
+};
+
+static int
+xlog_cil_order_write(
+ struct xfs_cil *cil,
+ xfs_csn_t sequence,
+ enum _record_type record)
+{
+ struct xfs_cil_ctx *ctx;
+
+restart:
+ spin_lock(&cil->xc_push_lock);
+ list_for_each_entry(ctx, &cil->xc_committing, committing) {
+ /*
+ * Avoid getting stuck in this loop because we were woken by the
+ * shutdown, but then went back to sleep once already in the
+ * shutdown state.
+ */
+ if (xlog_is_shutdown(cil->xc_log)) {
+ spin_unlock(&cil->xc_push_lock);
+ return -EIO;
+ }
+
+ /*
+ * Higher sequences will wait for this one so skip them.
+ * Don't wait for our own sequence, either.
+ */
+ if (ctx->sequence >= sequence)
+ continue;
+
+ /* Wait until the LSN for the record has been recorded. */
+ switch (record) {
+ case _START_RECORD:
+ if (!ctx->start_lsn) {
+ xlog_wait(&cil->xc_start_wait, &cil->xc_push_lock);
+ goto restart;
+ }
+ break;
+ case _COMMIT_RECORD:
+ if (!ctx->commit_lsn) {
+ xlog_wait(&cil->xc_commit_wait, &cil->xc_push_lock);
+ goto restart;
+ }
+ break;
+ }
+ }
+ spin_unlock(&cil->xc_push_lock);
+ return 0;
+}
+
+/*
+ * Write out the log vector change now attached to the CIL context. This will
+ * write a start record that needs to be strictly ordered in ascending CIL
+ * sequence order so that log recovery will always use in-order start LSNs when
+ * replaying checkpoints.
+ */
+static int
+xlog_cil_write_chain(
+ struct xfs_cil_ctx *ctx,
+ struct xfs_log_vec *chain)
+{
+ struct xlog *log = ctx->cil->xc_log;
+ int error;
+
+ error = xlog_cil_order_write(ctx->cil, ctx->sequence, _START_RECORD);
+ if (error)
+ return error;
+ return xlog_write(log, ctx, chain, ctx->ticket, XLOG_START_TRANS);
+}
+
+/*
+ * Write out the commit record of a checkpoint transaction to close off a
+ * running log write. These commit records are strictly ordered in ascending CIL
+ * sequence order so that log recovery will always replay the checkpoints in the
+ * correct order.
+ */
+static int
+xlog_cil_write_commit_record(
+ struct xfs_cil_ctx *ctx)
+{
+ struct xlog *log = ctx->cil->xc_log;
+ struct xfs_log_iovec reg = {
+ .i_addr = NULL,
+ .i_len = 0,
+ .i_type = XLOG_REG_TYPE_COMMIT,
+ };
+ struct xfs_log_vec vec = {
+ .lv_niovecs = 1,
+ .lv_iovecp = &reg,
+ };
+ int error;
+
+ if (xlog_is_shutdown(log))
+ return -EIO;
+
+ error = xlog_cil_order_write(ctx->cil, ctx->sequence, _COMMIT_RECORD);
+ if (error)
+ return error;
+
+ error = xlog_write(log, ctx, &vec, ctx->ticket, XLOG_COMMIT_TRANS);
+ if (error)
+ xfs_force_shutdown(log->l_mp, SHUTDOWN_LOG_IO_ERROR);
+ return error;
+}
+
+/*
* Push the Committed Item List to the log.
*
* If the current sequence is the same as xc_push_seq we need to do a flush. If
@@ -641,13 +852,12 @@ static void
xlog_cil_push_work(
struct work_struct *work)
{
- struct xfs_cil *cil =
- container_of(work, struct xfs_cil, xc_push_work);
+ struct xfs_cil_ctx *ctx =
+ container_of(work, struct xfs_cil_ctx, push_work);
+ struct xfs_cil *cil = ctx->cil;
struct xlog *log = cil->xc_log;
struct xfs_log_vec *lv;
- struct xfs_cil_ctx *ctx;
struct xfs_cil_ctx *new_ctx;
- struct xlog_in_core *commit_iclog;
struct xlog_ticket *tic;
int num_iovecs;
int error = 0;
@@ -655,20 +865,21 @@ xlog_cil_push_work(
struct xfs_log_iovec lhdr;
struct xfs_log_vec lvhdr = { NULL };
xfs_lsn_t preflush_tail_lsn;
- xfs_lsn_t commit_lsn;
xfs_csn_t push_seq;
struct bio bio;
DECLARE_COMPLETION_ONSTACK(bdev_flush);
+ bool push_commit_stable;
- new_ctx = kmem_zalloc(sizeof(*new_ctx), KM_NOFS);
+ new_ctx = xlog_cil_ctx_alloc();
new_ctx->ticket = xlog_cil_ticket_alloc(log);
down_write(&cil->xc_ctx_lock);
- ctx = cil->xc_ctx;
spin_lock(&cil->xc_push_lock);
push_seq = cil->xc_push_seq;
ASSERT(push_seq <= ctx->sequence);
+ push_commit_stable = cil->xc_push_commit_stable;
+ cil->xc_push_commit_stable = false;
/*
* As we are about to switch to a new, empty CIL context, we no longer
@@ -694,7 +905,7 @@ xlog_cil_push_work(
/* check for a previously pushed sequence */
- if (push_seq < cil->xc_ctx->sequence) {
+ if (push_seq < ctx->sequence) {
spin_unlock(&cil->xc_push_lock);
goto out_skip;
}
@@ -767,19 +978,7 @@ xlog_cil_push_work(
}
/*
- * initialise the new context and attach it to the CIL. Then attach
- * the current context to the CIL committing list so it can be found
- * during log forces to extract the commit lsn of the sequence that
- * needs to be forced.
- */
- INIT_LIST_HEAD(&new_ctx->committing);
- INIT_LIST_HEAD(&new_ctx->busy_extents);
- new_ctx->sequence = ctx->sequence + 1;
- new_ctx->cil = cil;
- cil->xc_ctx = new_ctx;
-
- /*
- * The switch is now done, so we can drop the context lock and move out
+ * Switch the contexts so we can drop the context lock and move out
* of a shared context. We can't just go straight to the commit record,
* though - we need to synchronise with previous and future commits so
* that the commit records are correctly ordered in the log to ensure
@@ -804,7 +1003,7 @@ xlog_cil_push_work(
* deferencing a freed context pointer.
*/
spin_lock(&cil->xc_push_lock);
- cil->xc_current_sequence = new_ctx->sequence;
+ xlog_cil_ctx_switch(cil, new_ctx);
spin_unlock(&cil->xc_push_lock);
up_write(&cil->xc_ctx_lock);
@@ -837,78 +1036,17 @@ xlog_cil_push_work(
*/
wait_for_completion(&bdev_flush);
- error = xlog_write(log, &lvhdr, tic, &ctx->start_lsn, NULL,
- XLOG_START_TRANS);
+ error = xlog_cil_write_chain(ctx, &lvhdr);
if (error)
goto out_abort_free_ticket;
- /*
- * now that we've written the checkpoint into the log, strictly
- * order the commit records so replay will get them in the right order.
- */
-restart:
- spin_lock(&cil->xc_push_lock);
- list_for_each_entry(new_ctx, &cil->xc_committing, committing) {
- /*
- * Avoid getting stuck in this loop because we were woken by the
- * shutdown, but then went back to sleep once already in the
- * shutdown state.
- */
- if (XLOG_FORCED_SHUTDOWN(log)) {
- spin_unlock(&cil->xc_push_lock);
- goto out_abort_free_ticket;
- }
-
- /*
- * Higher sequences will wait for this one so skip them.
- * Don't wait for our own sequence, either.
- */
- if (new_ctx->sequence >= ctx->sequence)
- continue;
- if (!new_ctx->commit_lsn) {
- /*
- * It is still being pushed! Wait for the push to
- * complete, then start again from the beginning.
- */
- xlog_wait(&cil->xc_commit_wait, &cil->xc_push_lock);
- goto restart;
- }
- }
- spin_unlock(&cil->xc_push_lock);
-
- error = xlog_commit_record(log, tic, &commit_iclog, &commit_lsn);
+ error = xlog_cil_write_commit_record(ctx);
if (error)
goto out_abort_free_ticket;
xfs_log_ticket_ungrant(log, tic);
/*
- * Once we attach the ctx to the iclog, a shutdown can process the
- * iclog, run the callbacks and free the ctx. The only thing preventing
- * this potential UAF situation here is that we are holding the
- * icloglock. Hence we cannot access the ctx once we have attached the
- * callbacks and dropped the icloglock.
- */
- spin_lock(&log->l_icloglock);
- if (commit_iclog->ic_state == XLOG_STATE_IOERROR) {
- spin_unlock(&log->l_icloglock);
- goto out_abort;
- }
- ASSERT_ALWAYS(commit_iclog->ic_state == XLOG_STATE_ACTIVE ||
- commit_iclog->ic_state == XLOG_STATE_WANT_SYNC);
- list_add_tail(&ctx->iclog_entry, &commit_iclog->ic_callbacks);
-
- /*
- * now the checkpoint commit is complete and we've attached the
- * callbacks to the iclog we can assign the commit LSN to the context
- * and wake up anyone who is waiting for the commit to complete.
- */
- spin_lock(&cil->xc_push_lock);
- ctx->commit_lsn = commit_lsn;
- wake_up_all(&cil->xc_commit_wait);
- spin_unlock(&cil->xc_push_lock);
-
- /*
* If the checkpoint spans multiple iclogs, wait for all previous iclogs
* to complete before we submit the commit_iclog. We can't use state
* checks for this - ACTIVE can be either a past completed iclog or a
@@ -919,21 +1057,19 @@ restart:
* wakeup until this commit_iclog is written to disk. Hence we use the
* iclog header lsn and compare it to the commit lsn to determine if we
* need to wait on iclogs or not.
- *
- * NOTE: It is not safe to reference the ctx after this check as we drop
- * the icloglock if we have to wait for completion of other iclogs.
*/
- if (ctx->start_lsn != commit_lsn) {
+ spin_lock(&log->l_icloglock);
+ if (ctx->start_lsn != ctx->commit_lsn) {
xfs_lsn_t plsn;
- plsn = be64_to_cpu(commit_iclog->ic_prev->ic_header.h_lsn);
- if (plsn && XFS_LSN_CMP(plsn, commit_lsn) < 0) {
+ plsn = be64_to_cpu(ctx->commit_iclog->ic_prev->ic_header.h_lsn);
+ if (plsn && XFS_LSN_CMP(plsn, ctx->commit_lsn) < 0) {
/*
* Waiting on ic_force_wait orders the completion of
* iclogs older than ic_prev. Hence we only need to wait
* on the most recent older iclog here.
*/
- xlog_wait_on_iclog(commit_iclog->ic_prev);
+ xlog_wait_on_iclog(ctx->commit_iclog->ic_prev);
spin_lock(&log->l_icloglock);
}
@@ -941,16 +1077,27 @@ restart:
* We need to issue a pre-flush so that the ordering for this
* checkpoint is correctly preserved down to stable storage.
*/
- commit_iclog->ic_flags |= XLOG_ICL_NEED_FLUSH;
+ ctx->commit_iclog->ic_flags |= XLOG_ICL_NEED_FLUSH;
}
/*
* The commit iclog must be written to stable storage to guarantee
* journal IO vs metadata writeback IO is correctly ordered on stable
* storage.
+ *
+ * If the push caller needs the commit to be immediately stable and the
+ * commit_iclog is not yet marked as XLOG_STATE_WANT_SYNC to indicate it
+ * will be written when released, switch it's state to WANT_SYNC right
+ * now.
*/
- commit_iclog->ic_flags |= XLOG_ICL_NEED_FUA;
- xlog_state_release_iclog(log, commit_iclog, preflush_tail_lsn);
+ ctx->commit_iclog->ic_flags |= XLOG_ICL_NEED_FUA;
+ if (push_commit_stable &&
+ ctx->commit_iclog->ic_state == XLOG_STATE_ACTIVE)
+ xlog_state_switch_iclogs(log, ctx->commit_iclog, 0);
+ xlog_state_release_iclog(log, ctx->commit_iclog, preflush_tail_lsn);
+
+ /* Not safe to reference ctx now! */
+
spin_unlock(&log->l_icloglock);
return;
@@ -962,9 +1109,15 @@ out_skip:
out_abort_free_ticket:
xfs_log_ticket_ungrant(log, tic);
-out_abort:
- ASSERT(XLOG_FORCED_SHUTDOWN(log));
- xlog_cil_committed(ctx);
+ ASSERT(xlog_is_shutdown(log));
+ if (!ctx->commit_iclog) {
+ xlog_cil_committed(ctx);
+ return;
+ }
+ spin_lock(&log->l_icloglock);
+ xlog_state_release_iclog(log, ctx->commit_iclog, 0);
+ /* Not safe to reference ctx now! */
+ spin_unlock(&log->l_icloglock);
}
/*
@@ -998,7 +1151,7 @@ xlog_cil_push_background(
spin_lock(&cil->xc_push_lock);
if (cil->xc_push_seq < cil->xc_current_sequence) {
cil->xc_push_seq = cil->xc_current_sequence;
- queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work);
+ queue_work(cil->xc_push_wq, &cil->xc_ctx->push_work);
}
/*
@@ -1034,13 +1187,26 @@ xlog_cil_push_background(
/*
* xlog_cil_push_now() is used to trigger an immediate CIL push to the sequence
* number that is passed. When it returns, the work will be queued for
- * @push_seq, but it won't be completed. The caller is expected to do any
- * waiting for push_seq to complete if it is required.
+ * @push_seq, but it won't be completed.
+ *
+ * If the caller is performing a synchronous force, we will flush the workqueue
+ * to get previously queued work moving to minimise the wait time they will
+ * undergo waiting for all outstanding pushes to complete. The caller is
+ * expected to do the required waiting for push_seq to complete.
+ *
+ * If the caller is performing an async push, we need to ensure that the
+ * checkpoint is fully flushed out of the iclogs when we finish the push. If we
+ * don't do this, then the commit record may remain sitting in memory in an
+ * ACTIVE iclog. This then requires another full log force to push to disk,
+ * which defeats the purpose of having an async, non-blocking CIL force
+ * mechanism. Hence in this case we need to pass a flag to the push work to
+ * indicate it needs to flush the commit record itself.
*/
static void
xlog_cil_push_now(
struct xlog *log,
- xfs_lsn_t push_seq)
+ xfs_lsn_t push_seq,
+ bool async)
{
struct xfs_cil *cil = log->l_cilp;
@@ -1050,7 +1216,8 @@ xlog_cil_push_now(
ASSERT(push_seq && push_seq <= cil->xc_current_sequence);
/* start on any pending background push to minimise wait time on it */
- flush_work(&cil->xc_push_work);
+ if (!async)
+ flush_workqueue(cil->xc_push_wq);
/*
* If the CIL is empty or we've already pushed the sequence then
@@ -1063,7 +1230,8 @@ xlog_cil_push_now(
}
cil->xc_push_seq = push_seq;
- queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work);
+ cil->xc_push_commit_stable = async;
+ queue_work(cil->xc_push_wq, &cil->xc_ctx->push_work);
spin_unlock(&cil->xc_push_lock);
}
@@ -1116,7 +1284,7 @@ xlog_cil_commit(
xlog_cil_insert_items(log, tp);
- if (regrant && !XLOG_FORCED_SHUTDOWN(log))
+ if (regrant && !xlog_is_shutdown(log))
xfs_log_ticket_regrant(log, tp->t_ticket);
else
xfs_log_ticket_ungrant(log, tp->t_ticket);
@@ -1148,11 +1316,26 @@ xlog_cil_commit(
}
/*
+ * Flush the CIL to stable storage but don't wait for it to complete. This
+ * requires the CIL push to ensure the commit record for the push hits the disk,
+ * but otherwise is no different to a push done from a log force.
+ */
+void
+xlog_cil_flush(
+ struct xlog *log)
+{
+ xfs_csn_t seq = log->l_cilp->xc_current_sequence;
+
+ trace_xfs_log_force(log->l_mp, seq, _RET_IP_);
+ xlog_cil_push_now(log, seq, true);
+}
+
+/*
* Conditionally push the CIL based on the sequence passed in.
*
- * We only need to push if we haven't already pushed the sequence
- * number given. Hence the only time we will trigger a push here is
- * if the push sequence is the same as the current context.
+ * We only need to push if we haven't already pushed the sequence number given.
+ * Hence the only time we will trigger a push here is if the push sequence is
+ * the same as the current context.
*
* We return the current commit lsn to allow the callers to determine if a
* iclog flush is necessary following this call.
@@ -1168,13 +1351,17 @@ xlog_cil_force_seq(
ASSERT(sequence <= cil->xc_current_sequence);
+ if (!sequence)
+ sequence = cil->xc_current_sequence;
+ trace_xfs_log_force(log->l_mp, sequence, _RET_IP_);
+
/*
* check to see if we need to force out the current context.
* xlog_cil_push() handles racing pushes for the same sequence,
* so no need to deal with it here.
*/
restart:
- xlog_cil_push_now(log, sequence);
+ xlog_cil_push_now(log, sequence, false);
/*
* See if we can find a previous sequence still committing.
@@ -1189,7 +1376,7 @@ restart:
* shutdown, but then went back to sleep once already in the
* shutdown state.
*/
- if (XLOG_FORCED_SHUTDOWN(log))
+ if (xlog_is_shutdown(log))
goto out_shutdown;
if (ctx->sequence > sequence)
continue;
@@ -1198,6 +1385,7 @@ restart:
* It is still being pushed! Wait for the push to
* complete, then start again from the beginning.
*/
+ XFS_STATS_INC(log->l_mp, xs_log_force_sleep);
xlog_wait(&cil->xc_commit_wait, &cil->xc_push_lock);
goto restart;
}
@@ -1282,32 +1470,35 @@ xlog_cil_init(
cil = kmem_zalloc(sizeof(*cil), KM_MAYFAIL);
if (!cil)
return -ENOMEM;
+ /*
+ * Limit the CIL pipeline depth to 4 concurrent works to bound the
+ * concurrency the log spinlocks will be exposed to.
+ */
+ cil->xc_push_wq = alloc_workqueue("xfs-cil/%s",
+ XFS_WQFLAGS(WQ_FREEZABLE | WQ_MEM_RECLAIM | WQ_UNBOUND),
+ 4, log->l_mp->m_super->s_id);
+ if (!cil->xc_push_wq)
+ goto out_destroy_cil;
- ctx = kmem_zalloc(sizeof(*ctx), KM_MAYFAIL);
- if (!ctx) {
- kmem_free(cil);
- return -ENOMEM;
- }
-
- INIT_WORK(&cil->xc_push_work, xlog_cil_push_work);
INIT_LIST_HEAD(&cil->xc_cil);
INIT_LIST_HEAD(&cil->xc_committing);
spin_lock_init(&cil->xc_cil_lock);
spin_lock_init(&cil->xc_push_lock);
init_waitqueue_head(&cil->xc_push_wait);
init_rwsem(&cil->xc_ctx_lock);
+ init_waitqueue_head(&cil->xc_start_wait);
init_waitqueue_head(&cil->xc_commit_wait);
-
- INIT_LIST_HEAD(&ctx->committing);
- INIT_LIST_HEAD(&ctx->busy_extents);
- ctx->sequence = 1;
- ctx->cil = cil;
- cil->xc_ctx = ctx;
- cil->xc_current_sequence = ctx->sequence;
-
cil->xc_log = log;
log->l_cilp = cil;
+
+ ctx = xlog_cil_ctx_alloc();
+ xlog_cil_ctx_switch(cil, ctx);
+
return 0;
+
+out_destroy_cil:
+ kmem_free(cil);
+ return -ENOMEM;
}
void
@@ -1321,6 +1512,7 @@ xlog_cil_destroy(
}
ASSERT(list_empty(&log->l_cilp->xc_cil));
+ destroy_workqueue(log->l_cilp->xc_push_wq);
kmem_free(log->l_cilp);
}
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index f3e79a45d60a..844fbeec3545 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -12,15 +12,6 @@ struct xlog_ticket;
struct xfs_mount;
/*
- * Flags for log structure
- */
-#define XLOG_ACTIVE_RECOVERY 0x2 /* in the middle of recovery */
-#define XLOG_RECOVERY_NEEDED 0x4 /* log was recovered */
-#define XLOG_IO_ERROR 0x8 /* log hit an I/O error, and being
- shutdown */
-#define XLOG_TAIL_WARN 0x10 /* log tail verify warning issued */
-
-/*
* get client id from packed copy.
*
* this hack is here because the xlog_pack code copies four bytes
@@ -47,7 +38,6 @@ enum xlog_iclog_state {
XLOG_STATE_DONE_SYNC, /* Done syncing to disk */
XLOG_STATE_CALLBACK, /* Callback functions now */
XLOG_STATE_DIRTY, /* Dirty IC log, not ready for ACTIVE status */
- XLOG_STATE_IOERROR, /* IO error happened in sync'ing log */
};
#define XLOG_STATE_STRINGS \
@@ -56,8 +46,7 @@ enum xlog_iclog_state {
{ XLOG_STATE_SYNCING, "XLOG_STATE_SYNCING" }, \
{ XLOG_STATE_DONE_SYNC, "XLOG_STATE_DONE_SYNC" }, \
{ XLOG_STATE_CALLBACK, "XLOG_STATE_CALLBACK" }, \
- { XLOG_STATE_DIRTY, "XLOG_STATE_DIRTY" }, \
- { XLOG_STATE_IOERROR, "XLOG_STATE_IOERROR" }
+ { XLOG_STATE_DIRTY, "XLOG_STATE_DIRTY" }
/*
* In core log flags
@@ -251,6 +240,7 @@ struct xfs_cil_ctx {
xfs_csn_t sequence; /* chkpt sequence # */
xfs_lsn_t start_lsn; /* first LSN of chkpt commit */
xfs_lsn_t commit_lsn; /* chkpt commit record lsn */
+ struct xlog_in_core *commit_iclog;
struct xlog_ticket *ticket; /* chkpt ticket */
int nvecs; /* number of regions */
int space_used; /* aggregate size of regions */
@@ -259,6 +249,7 @@ struct xfs_cil_ctx {
struct list_head iclog_entry;
struct list_head committing; /* ctx committing list */
struct work_struct discard_endio_work;
+ struct work_struct push_work;
};
/*
@@ -281,16 +272,18 @@ struct xfs_cil {
struct xlog *xc_log;
struct list_head xc_cil;
spinlock_t xc_cil_lock;
+ struct workqueue_struct *xc_push_wq;
struct rw_semaphore xc_ctx_lock ____cacheline_aligned_in_smp;
struct xfs_cil_ctx *xc_ctx;
spinlock_t xc_push_lock ____cacheline_aligned_in_smp;
xfs_csn_t xc_push_seq;
+ bool xc_push_commit_stable;
struct list_head xc_committing;
wait_queue_head_t xc_commit_wait;
+ wait_queue_head_t xc_start_wait;
xfs_csn_t xc_current_sequence;
- struct work_struct xc_push_work;
wait_queue_head_t xc_push_wait; /* background push throttle */
} ____cacheline_aligned_in_smp;
@@ -407,7 +400,7 @@ struct xlog {
struct xfs_buftarg *l_targ; /* buftarg of log */
struct workqueue_struct *l_ioend_workqueue; /* for I/O completions */
struct delayed_work l_work; /* background flush work */
- uint l_flags;
+ long l_opstate; /* operational state */
uint l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
struct list_head *l_buf_cancel_table;
int l_iclog_hsize; /* size of iclog header */
@@ -456,13 +449,40 @@ struct xlog {
xfs_lsn_t l_recovery_lsn;
uint32_t l_iclog_roundoff;/* padding roundoff */
+
+ /* Users of log incompat features should take a read lock. */
+ struct rw_semaphore l_incompat_users;
};
#define XLOG_BUF_CANCEL_BUCKET(log, blkno) \
((log)->l_buf_cancel_table + ((uint64_t)blkno % XLOG_BC_TABLE_SIZE))
-#define XLOG_FORCED_SHUTDOWN(log) \
- (unlikely((log)->l_flags & XLOG_IO_ERROR))
+/*
+ * Bits for operational state
+ */
+#define XLOG_ACTIVE_RECOVERY 0 /* in the middle of recovery */
+#define XLOG_RECOVERY_NEEDED 1 /* log was recovered */
+#define XLOG_IO_ERROR 2 /* log hit an I/O error, and being
+ shutdown */
+#define XLOG_TAIL_WARN 3 /* log tail verify warning issued */
+
+static inline bool
+xlog_recovery_needed(struct xlog *log)
+{
+ return test_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate);
+}
+
+static inline bool
+xlog_in_recovery(struct xlog *log)
+{
+ return test_bit(XLOG_ACTIVE_RECOVERY, &log->l_opstate);
+}
+
+static inline bool
+xlog_is_shutdown(struct xlog *log)
+{
+ return test_bit(XLOG_IO_ERROR, &log->l_opstate);
+}
/* common routines */
extern int
@@ -496,14 +516,14 @@ xlog_write_adv_cnt(void **ptr, int *len, int *off, size_t bytes)
void xlog_print_tic_res(struct xfs_mount *mp, struct xlog_ticket *ticket);
void xlog_print_trans(struct xfs_trans *);
-int xlog_write(struct xlog *log, struct xfs_log_vec *log_vector,
- struct xlog_ticket *tic, xfs_lsn_t *start_lsn,
- struct xlog_in_core **commit_iclog, uint optype);
-int xlog_commit_record(struct xlog *log, struct xlog_ticket *ticket,
- struct xlog_in_core **iclog, xfs_lsn_t *lsn);
+int xlog_write(struct xlog *log, struct xfs_cil_ctx *ctx,
+ struct xfs_log_vec *log_vector, struct xlog_ticket *tic,
+ uint optype);
void xfs_log_ticket_ungrant(struct xlog *log, struct xlog_ticket *ticket);
void xfs_log_ticket_regrant(struct xlog *log, struct xlog_ticket *ticket);
+void xlog_state_switch_iclogs(struct xlog *log, struct xlog_in_core *iclog,
+ int eventual_size);
int xlog_state_release_iclog(struct xlog *log, struct xlog_in_core *iclog,
xfs_lsn_t log_tail_lsn);
@@ -571,10 +591,14 @@ void xlog_cil_destroy(struct xlog *log);
bool xlog_cil_empty(struct xlog *log);
void xlog_cil_commit(struct xlog *log, struct xfs_trans *tp,
xfs_csn_t *commit_seq, bool regrant);
+void xlog_cil_set_ctx_write_state(struct xfs_cil_ctx *ctx,
+ struct xlog_in_core *iclog);
+
/*
* CIL force routines
*/
+void xlog_cil_flush(struct xlog *log);
xfs_lsn_t xlog_cil_force_seq(struct xlog *log, xfs_csn_t sequence);
static inline void
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 1721fce2ec94..10562ecbd9ea 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -26,6 +26,8 @@
#include "xfs_error.h"
#include "xfs_buf_item.h"
#include "xfs_ag.h"
+#include "xfs_quota.h"
+
#define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1)
@@ -79,8 +81,6 @@ xlog_alloc_buffer(
struct xlog *log,
int nbblks)
{
- int align_mask = xfs_buftarg_dma_alignment(log->l_targ);
-
/*
* Pass log block 0 since we don't have an addr yet, buffer will be
* verified on read.
@@ -108,7 +108,7 @@ xlog_alloc_buffer(
if (nbblks > 1 && log->l_sectBBsize > 1)
nbblks += log->l_sectBBsize;
nbblks = round_up(nbblks, log->l_sectBBsize);
- return kmem_alloc_io(BBTOB(nbblks), align_mask, KM_MAYFAIL | KM_ZERO);
+ return kvzalloc(BBTOB(nbblks), GFP_KERNEL | __GFP_RETRY_MAYFAIL);
}
/*
@@ -146,7 +146,7 @@ xlog_do_io(
error = xfs_rw_bdev(log->l_targ->bt_bdev, log->l_logBBstart + blk_no,
BBTOB(nbblks), data, op);
- if (error && !XFS_FORCED_SHUTDOWN(log->l_mp)) {
+ if (error && !xlog_is_shutdown(log)) {
xfs_alert(log->l_mp,
"log recovery %s I/O error at daddr 0x%llx len %d error %d",
op == REQ_OP_WRITE ? "write" : "read",
@@ -375,7 +375,7 @@ out:
static inline int
xlog_logrec_hblks(struct xlog *log, struct xlog_rec_header *rh)
{
- if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+ if (xfs_has_logv2(log->l_mp)) {
int h_size = be32_to_cpu(rh->h_size);
if ((be32_to_cpu(rh->h_version) & XLOG_VERSION_2) &&
@@ -1347,7 +1347,7 @@ xlog_find_tail(
* headers if we have a filesystem using non-persistent counters.
*/
if (clean)
- log->l_mp->m_flags |= XFS_MOUNT_WAS_CLEAN;
+ set_bit(XFS_OPSTATE_CLEAN, &log->l_mp->m_opstate);
/*
* Make sure that there are no blocks in front of the head
@@ -1504,7 +1504,7 @@ xlog_add_record(
recp->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
recp->h_cycle = cpu_to_be32(cycle);
recp->h_version = cpu_to_be32(
- xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? 2 : 1);
+ xfs_has_logv2(log->l_mp) ? 2 : 1);
recp->h_lsn = cpu_to_be64(xlog_assign_lsn(cycle, block));
recp->h_tail_lsn = cpu_to_be64(xlog_assign_lsn(tail_cycle, tail_block));
recp->h_fmt = cpu_to_be32(XLOG_FMT);
@@ -1756,6 +1756,30 @@ xlog_recover_release_intent(
spin_unlock(&ailp->ail_lock);
}
+int
+xlog_recover_iget(
+ struct xfs_mount *mp,
+ xfs_ino_t ino,
+ struct xfs_inode **ipp)
+{
+ int error;
+
+ error = xfs_iget(mp, NULL, ino, 0, 0, ipp);
+ if (error)
+ return error;
+
+ error = xfs_qm_dqattach(*ipp);
+ if (error) {
+ xfs_irele(*ipp);
+ return error;
+ }
+
+ if (VFS_I(*ipp)->i_nlink == 0)
+ xfs_iflags_set(*ipp, XFS_IRECOVERY);
+
+ return 0;
+}
+
/******************************************************************************
*
* Log recover routines
@@ -2062,7 +2086,9 @@ xlog_recover_add_to_cont_trans(
old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
old_len = item->ri_buf[item->ri_cnt-1].i_len;
- ptr = krealloc(old_ptr, len + old_len, GFP_KERNEL | __GFP_NOFAIL);
+ ptr = kvrealloc(old_ptr, old_len, len + old_len, GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
memcpy(&ptr[old_len], dp, len);
item->ri_buf[item->ri_cnt-1].i_len += len;
item->ri_buf[item->ri_cnt-1].i_addr = ptr;
@@ -2786,6 +2812,13 @@ xlog_recover_process_iunlinks(
}
xfs_buf_rele(agibp);
}
+
+ /*
+ * Flush the pending unlinked inodes to ensure that the inactivations
+ * are fully completed on disk and the incore inodes can be reclaimed
+ * before we signal that recovery is complete.
+ */
+ xfs_inodegc_flush(mp);
}
STATIC void
@@ -2802,7 +2835,7 @@ xlog_unpack_data(
dp += BBSIZE;
}
- if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+ if (xfs_has_logv2(log->l_mp)) {
xlog_in_core_2_t *xhdr = (xlog_in_core_2_t *)rhead;
for ( ; i < BTOBB(be32_to_cpu(rhead->h_len)); i++) {
j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
@@ -2850,7 +2883,7 @@ xlog_recover_process(
* the kernel from one that does not add CRCs by default.
*/
if (crc != old_crc) {
- if (old_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
+ if (old_crc || xfs_has_crc(log->l_mp)) {
xfs_alert(log->l_mp,
"log record CRC mismatch: found 0x%x, expected 0x%x.",
le32_to_cpu(old_crc),
@@ -2862,7 +2895,7 @@ xlog_recover_process(
* If the filesystem is CRC enabled, this mismatch becomes a
* fatal log corruption failure.
*/
- if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
+ if (xfs_has_crc(log->l_mp)) {
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
return -EFSCORRUPTED;
}
@@ -2948,7 +2981,7 @@ xlog_do_recovery_pass(
* Read the header of the tail block and get the iclog buffer size from
* h_size. Use this to tell how many sectors make up the log header.
*/
- if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+ if (xfs_has_logv2(log->l_mp)) {
/*
* When using variable length iclogs, read first sector of
* iclog header and extract the header size from it. Get a
@@ -3280,10 +3313,7 @@ xlog_do_recover(
if (error)
return error;
- /*
- * If IO errors happened during recovery, bail out.
- */
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xlog_is_shutdown(log))
return -EIO;
/*
@@ -3305,7 +3335,7 @@ xlog_do_recover(
xfs_buf_hold(bp);
error = _xfs_buf_read(bp, XBF_READ);
if (error) {
- if (!XFS_FORCED_SHUTDOWN(mp)) {
+ if (!xlog_is_shutdown(log)) {
xfs_buf_ioerror_alert(bp, __this_address);
ASSERT(0);
}
@@ -3318,6 +3348,7 @@ xlog_do_recover(
xfs_buf_relse(bp);
/* re-initialise in-core superblock and geometry structures */
+ mp->m_features |= xfs_sb_version_to_features(sbp);
xfs_reinit_percpu_counters(mp);
error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
if (error) {
@@ -3329,7 +3360,7 @@ xlog_do_recover(
xlog_recover_check_summary(log);
/* Normal transactions can now occur */
- log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
+ clear_bit(XLOG_ACTIVE_RECOVERY, &log->l_opstate);
return 0;
}
@@ -3355,7 +3386,7 @@ xlog_recover(
* could not be verified. Check the superblock LSN against the current
* LSN now that it's known.
*/
- if (xfs_sb_version_hascrc(&log->l_mp->m_sb) &&
+ if (xfs_has_crc(log->l_mp) &&
!xfs_log_check_lsn(log->l_mp, log->l_mp->m_sb.sb_lsn))
return -EINVAL;
@@ -3382,7 +3413,7 @@ xlog_recover(
* (e.g. unsupported transactions, then simply reject the
* attempt at recovery before touching anything.
*/
- if (XFS_SB_VERSION_NUM(&log->l_mp->m_sb) == XFS_SB_VERSION_5 &&
+ if (xfs_sb_is_v5(&log->l_mp->m_sb) &&
xfs_sb_has_incompat_log_feature(&log->l_mp->m_sb,
XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) {
xfs_warn(log->l_mp,
@@ -3413,68 +3444,64 @@ xlog_recover(
: "internal");
error = xlog_do_recover(log, head_blk, tail_blk);
- log->l_flags |= XLOG_RECOVERY_NEEDED;
+ set_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate);
}
return error;
}
/*
- * In the first part of recovery we replay inodes and buffers and build
- * up the list of extent free items which need to be processed. Here
- * we process the extent free items and clean up the on disk unlinked
- * inode lists. This is separated from the first part of recovery so
- * that the root and real-time bitmap inodes can be read in from disk in
- * between the two stages. This is necessary so that we can free space
- * in the real-time portion of the file system.
+ * In the first part of recovery we replay inodes and buffers and build up the
+ * list of intents which need to be processed. Here we process the intents and
+ * clean up the on disk unlinked inode lists. This is separated from the first
+ * part of recovery so that the root and real-time bitmap inodes can be read in
+ * from disk in between the two stages. This is necessary so that we can free
+ * space in the real-time portion of the file system.
*/
int
xlog_recover_finish(
struct xlog *log)
{
- /*
- * Now we're ready to do the transactions needed for the
- * rest of recovery. Start with completing all the extent
- * free intent records and then process the unlinked inode
- * lists. At this point, we essentially run in normal mode
- * except that we're still performing recovery actions
- * rather than accepting new requests.
- */
- if (log->l_flags & XLOG_RECOVERY_NEEDED) {
- int error;
- error = xlog_recover_process_intents(log);
- if (error) {
- /*
- * Cancel all the unprocessed intent items now so that
- * we don't leave them pinned in the AIL. This can
- * cause the AIL to livelock on the pinned item if
- * anyone tries to push the AIL (inode reclaim does
- * this) before we get around to xfs_log_mount_cancel.
- */
- xlog_recover_cancel_intents(log);
- xfs_force_shutdown(log->l_mp, SHUTDOWN_LOG_IO_ERROR);
- xfs_alert(log->l_mp, "Failed to recover intents");
- return error;
- }
+ int error;
+ error = xlog_recover_process_intents(log);
+ if (error) {
/*
- * Sync the log to get all the intents out of the AIL.
- * This isn't absolutely necessary, but it helps in
- * case the unlink transactions would have problems
- * pushing the intents out of the way.
+ * Cancel all the unprocessed intent items now so that we don't
+ * leave them pinned in the AIL. This can cause the AIL to
+ * livelock on the pinned item if anyone tries to push the AIL
+ * (inode reclaim does this) before we get around to
+ * xfs_log_mount_cancel.
*/
- xfs_log_force(log->l_mp, XFS_LOG_SYNC);
-
- xlog_recover_process_iunlinks(log);
+ xlog_recover_cancel_intents(log);
+ xfs_alert(log->l_mp, "Failed to recover intents");
+ xfs_force_shutdown(log->l_mp, SHUTDOWN_LOG_IO_ERROR);
+ return error;
+ }
- xlog_recover_check_summary(log);
+ /*
+ * Sync the log to get all the intents out of the AIL. This isn't
+ * absolutely necessary, but it helps in case the unlink transactions
+ * would have problems pushing the intents out of the way.
+ */
+ xfs_log_force(log->l_mp, XFS_LOG_SYNC);
- xfs_notice(log->l_mp, "Ending recovery (logdev: %s)",
- log->l_mp->m_logname ? log->l_mp->m_logname
- : "internal");
- log->l_flags &= ~XLOG_RECOVERY_NEEDED;
- } else {
- xfs_info(log->l_mp, "Ending clean mount");
+ /*
+ * Now that we've recovered the log and all the intents, we can clear
+ * the log incompat feature bits in the superblock because there's no
+ * longer anything to protect. We rely on the AIL push to write out the
+ * updated superblock after everything else.
+ */
+ if (xfs_clear_incompat_log_features(log->l_mp)) {
+ error = xfs_sync_sb(log->l_mp, false);
+ if (error < 0) {
+ xfs_alert(log->l_mp,
+ "Failed to clear log incompat features on recovery");
+ return error;
+ }
}
+
+ xlog_recover_process_iunlinks(log);
+ xlog_recover_check_summary(log);
return 0;
}
@@ -3482,7 +3509,7 @@ void
xlog_recover_cancel(
struct xlog *log)
{
- if (log->l_flags & XLOG_RECOVERY_NEEDED)
+ if (xlog_recovery_needed(log))
xlog_recover_cancel_intents(log);
}
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index d0755494597f..06dac09eddbd 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -62,7 +62,7 @@ xfs_uuid_mount(
/* Publish UUID in struct super_block */
uuid_copy(&mp->m_super->s_uuid, uuid);
- if (mp->m_flags & XFS_MOUNT_NOUUID)
+ if (xfs_has_nouuid(mp))
return 0;
if (uuid_is_null(uuid)) {
@@ -104,7 +104,7 @@ xfs_uuid_unmount(
uuid_t *uuid = &mp->m_sb.sb_uuid;
int i;
- if (mp->m_flags & XFS_MOUNT_NOUUID)
+ if (xfs_has_nouuid(mp))
return;
mutex_lock(&xfs_uuid_table_mutex);
@@ -225,6 +225,7 @@ reread:
goto reread;
}
+ mp->m_features |= xfs_sb_version_to_features(sbp);
xfs_reinit_percpu_counters(mp);
/* no need to be quiet anymore, so reset the buf ops */
@@ -318,7 +319,7 @@ xfs_validate_new_dalign(
}
}
- if (!xfs_sb_version_hasdalign(&mp->m_sb)) {
+ if (!xfs_has_dalign(mp)) {
xfs_warn(mp,
"cannot change alignment: superblock does not support data alignment");
return -EINVAL;
@@ -349,8 +350,7 @@ xfs_update_alignment(
sbp->sb_unit = mp->m_dalign;
sbp->sb_width = mp->m_swidth;
mp->m_update_sb = true;
- } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
- xfs_sb_version_hasdalign(&mp->m_sb)) {
+ } else if (!xfs_has_noalign(mp) && xfs_has_dalign(mp)) {
mp->m_dalign = sbp->sb_unit;
mp->m_swidth = sbp->sb_width;
}
@@ -365,13 +365,16 @@ void
xfs_set_low_space_thresholds(
struct xfs_mount *mp)
{
- int i;
+ uint64_t dblocks = mp->m_sb.sb_dblocks;
+ uint64_t rtexts = mp->m_sb.sb_rextents;
+ int i;
- for (i = 0; i < XFS_LOWSP_MAX; i++) {
- uint64_t space = mp->m_sb.sb_dblocks;
+ do_div(dblocks, 100);
+ do_div(rtexts, 100);
- do_div(space, 100);
- mp->m_low_space[i] = space * (i + 1);
+ for (i = 0; i < XFS_LOWSP_MAX; i++) {
+ mp->m_low_space[i] = dblocks * (i + 1);
+ mp->m_low_rtexts[i] = rtexts * (i + 1);
}
}
@@ -485,7 +488,7 @@ xfs_check_summary_counts(
* counters. If any of them are obviously incorrect, we can recompute
* them from the AGF headers in the next step.
*/
- if (XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
+ if (xfs_is_clean(mp) &&
(mp->m_sb.sb_fdblocks > mp->m_sb.sb_dblocks ||
!xfs_verify_icount(mp, mp->m_sb.sb_icount) ||
mp->m_sb.sb_ifree > mp->m_sb.sb_icount))
@@ -502,8 +505,7 @@ xfs_check_summary_counts(
* superblock to be correct and we don't need to do anything here.
* Otherwise, recalculate the summary counters.
*/
- if ((!xfs_sb_version_haslazysbcount(&mp->m_sb) ||
- XFS_LAST_UNMOUNT_WAS_CLEAN(mp)) &&
+ if ((!xfs_has_lazysbcount(mp) || xfs_is_clean(mp)) &&
!xfs_fs_has_sickness(mp, XFS_SICK_FS_COUNTERS))
return 0;
@@ -514,7 +516,8 @@ xfs_check_summary_counts(
* Flush and reclaim dirty inodes in preparation for unmount. Inodes and
* internal inode structures can be sitting in the CIL and AIL at this point,
* so we need to unpin them, write them back and/or reclaim them before unmount
- * can proceed.
+ * can proceed. In other words, callers are required to have inactivated all
+ * inodes.
*
* An inode cluster that has been freed can have its buffer still pinned in
* memory because the transaction is still sitting in a iclog. The stale inodes
@@ -543,9 +546,10 @@ xfs_unmount_flush_inodes(
xfs_extent_busy_wait_all(mp);
flush_workqueue(xfs_discard_wq);
- mp->m_flags |= XFS_MOUNT_UNMOUNTING;
+ set_bit(XFS_OPSTATE_UNMOUNTING, &mp->m_opstate);
xfs_ail_push_all_sync(mp->m_ail);
+ xfs_inodegc_stop(mp);
cancel_delayed_work_sync(&mp->m_reclaim_work);
xfs_reclaim_inodes(mp);
xfs_health_unmount(mp);
@@ -607,29 +611,13 @@ xfs_mountfs(
xfs_warn(mp, "correcting sb_features alignment problem");
sbp->sb_features2 |= sbp->sb_bad_features2;
mp->m_update_sb = true;
-
- /*
- * Re-check for ATTR2 in case it was found in bad_features2
- * slot.
- */
- if (xfs_sb_version_hasattr2(&mp->m_sb) &&
- !(mp->m_flags & XFS_MOUNT_NOATTR2))
- mp->m_flags |= XFS_MOUNT_ATTR2;
}
- if (xfs_sb_version_hasattr2(&mp->m_sb) &&
- (mp->m_flags & XFS_MOUNT_NOATTR2)) {
- xfs_sb_version_removeattr2(&mp->m_sb);
- mp->m_update_sb = true;
-
- /* update sb_versionnum for the clearing of the morebits */
- if (!sbp->sb_features2)
- mp->m_update_sb = true;
- }
/* always use v2 inodes by default now */
if (!(mp->m_sb.sb_versionnum & XFS_SB_VERSION_NLINKBIT)) {
mp->m_sb.sb_versionnum |= XFS_SB_VERSION_NLINKBIT;
+ mp->m_features |= XFS_FEAT_NLINK;
mp->m_update_sb = true;
}
@@ -702,7 +690,7 @@ xfs_mountfs(
* cluster size. Full inode chunk alignment must match the chunk size,
* but that is checked on sb read verification...
*/
- if (xfs_sb_version_hassparseinodes(&mp->m_sb) &&
+ if (xfs_has_sparseinodes(mp) &&
mp->m_sb.sb_spino_align !=
XFS_B_TO_FSBT(mp, igeo->inode_cluster_size_raw)) {
xfs_warn(mp,
@@ -764,6 +752,10 @@ xfs_mountfs(
goto out_free_perag;
}
+ error = xfs_inodegc_register_shrinker(mp);
+ if (error)
+ goto out_fail_wait;
+
/*
* Log's mount-time initialization. The first part of recovery can place
* some items on the AIL, to be handled when recovery is finished or
@@ -774,7 +766,7 @@ xfs_mountfs(
XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
if (error) {
xfs_warn(mp, "log mount failed");
- goto out_fail_wait;
+ goto out_inodegc_shrinker;
}
/* Make sure the summary counts are ok. */
@@ -782,6 +774,23 @@ xfs_mountfs(
if (error)
goto out_log_dealloc;
+ /* Enable background inode inactivation workers. */
+ xfs_inodegc_start(mp);
+ xfs_blockgc_start(mp);
+
+ /*
+ * Now that we've recovered any pending superblock feature bit
+ * additions, we can finish setting up the attr2 behaviour for the
+ * mount. The noattr2 option overrides the superblock flag, so only
+ * check the superblock feature flag if the mount option is not set.
+ */
+ if (xfs_has_noattr2(mp)) {
+ mp->m_features &= ~XFS_FEAT_ATTR2;
+ } else if (!xfs_has_attr2(mp) &&
+ (mp->m_sb.sb_features2 & XFS_SB_VERSION2_ATTR2BIT)) {
+ mp->m_features |= XFS_FEAT_ATTR2;
+ }
+
/*
* Get and sanity-check the root inode.
* Save the pointer to it in the mount structure.
@@ -825,7 +834,7 @@ xfs_mountfs(
* the next remount into writeable mode. Otherwise we would never
* perform the update e.g. for the root filesystem.
*/
- if (mp->m_update_sb && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
+ if (mp->m_update_sb && !xfs_is_readonly(mp)) {
error = xfs_sync_sb(mp, false);
if (error) {
xfs_warn(mp, "failed to write sb changes");
@@ -836,13 +845,11 @@ xfs_mountfs(
/*
* Initialise the XFS quota management subsystem for this mount
*/
- if (XFS_IS_QUOTA_RUNNING(mp)) {
+ if (XFS_IS_QUOTA_ON(mp)) {
error = xfs_qm_newmount(mp, &quotamount, &quotaflags);
if (error)
goto out_rtunmount;
} else {
- ASSERT(!XFS_IS_QUOTA_ON(mp));
-
/*
* If a file system had quotas running earlier, but decided to
* mount without -o uquota/pquota/gquota options, revoke the
@@ -884,10 +891,8 @@ xfs_mountfs(
* We use the same quiesce mechanism as the rw->ro remount, as they are
* semantically identical operations.
*/
- if ((mp->m_flags & (XFS_MOUNT_RDONLY|XFS_MOUNT_NORECOVERY)) ==
- XFS_MOUNT_RDONLY) {
+ if (xfs_is_readonly(mp) && !xfs_has_norecovery(mp))
xfs_log_clean(mp);
- }
/*
* Complete the quota initialisation, post-log-replay component.
@@ -910,7 +915,7 @@ xfs_mountfs(
* This may drive us straight to ENOSPC on mount, but that implies
* we were already there on the last unmount. Warn if this occurs.
*/
- if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
+ if (!xfs_is_readonly(mp)) {
resblks = xfs_default_resblks(mp);
error = xfs_reserve_blocks(mp, &resblks, NULL);
if (error)
@@ -944,6 +949,15 @@ xfs_mountfs(
xfs_irele(rip);
/* Clean out dquots that might be in memory after quotacheck. */
xfs_qm_unmount(mp);
+
+ /*
+ * Inactivate all inodes that might still be in memory after a log
+ * intent recovery failure so that reclaim can free them. Metadata
+ * inodes and the root directory shouldn't need inactivation, but the
+ * mount failed for some reason, so pull down all the state and flee.
+ */
+ xfs_inodegc_flush(mp);
+
/*
* Flush all inode reclamation work and flush the log.
* We have to do this /after/ rtunmount and qm_unmount because those
@@ -958,6 +972,8 @@ xfs_mountfs(
xfs_unmount_flush_inodes(mp);
out_log_dealloc:
xfs_log_mount_cancel(mp);
+ out_inodegc_shrinker:
+ unregister_shrinker(&mp->m_inodegc_shrinker);
out_fail_wait:
if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
xfs_buftarg_drain(mp->m_logdev_targp);
@@ -991,6 +1007,16 @@ xfs_unmountfs(
uint64_t resblks;
int error;
+ /*
+ * Perform all on-disk metadata updates required to inactivate inodes
+ * that the VFS evicted earlier in the unmount process. Freeing inodes
+ * and discarding CoW fork preallocations can cause shape changes to
+ * the free inode and refcount btrees, respectively, so we must finish
+ * this before we discard the metadata space reservations. Metadata
+ * inodes and the root directory do not require inactivation.
+ */
+ xfs_inodegc_flush(mp);
+
xfs_blockgc_stop(mp);
xfs_fs_unreserve_ag_blocks(mp);
xfs_qm_unmount_quotas(mp);
@@ -1028,6 +1054,7 @@ xfs_unmountfs(
#if defined(DEBUG)
xfs_errortag_clearall(mp);
#endif
+ unregister_shrinker(&mp->m_inodegc_shrinker);
xfs_free_perag(mp);
xfs_errortag_del(mp);
@@ -1049,20 +1076,12 @@ xfs_fs_writable(
{
ASSERT(level > SB_UNFROZEN);
if ((mp->m_super->s_writers.frozen >= level) ||
- XFS_FORCED_SHUTDOWN(mp) || (mp->m_flags & XFS_MOUNT_RDONLY))
+ xfs_is_shutdown(mp) || xfs_is_readonly(mp))
return false;
return true;
}
-/*
- * Deltas for the block count can vary from 1 to very large, but lock contention
- * only occurs on frequent small block count updates such as in the delayed
- * allocation path for buffered writes (page a time updates). Hence we set
- * a large batch count (1024) to minimise global counter updates except when
- * we get near to ENOSPC and we have to be very accurate with our updates.
- */
-#define XFS_FDBLOCKS_BATCH 1024
int
xfs_mod_fdblocks(
struct xfs_mount *mp,
@@ -1210,13 +1229,123 @@ void
xfs_force_summary_recalc(
struct xfs_mount *mp)
{
- if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
+ if (!xfs_has_lazysbcount(mp))
return;
xfs_fs_mark_sick(mp, XFS_SICK_FS_COUNTERS);
}
/*
+ * Enable a log incompat feature flag in the primary superblock. The caller
+ * cannot have any other transactions in progress.
+ */
+int
+xfs_add_incompat_log_feature(
+ struct xfs_mount *mp,
+ uint32_t feature)
+{
+ struct xfs_dsb *dsb;
+ int error;
+
+ ASSERT(hweight32(feature) == 1);
+ ASSERT(!(feature & XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN));
+
+ /*
+ * Force the log to disk and kick the background AIL thread to reduce
+ * the chances that the bwrite will stall waiting for the AIL to unpin
+ * the primary superblock buffer. This isn't a data integrity
+ * operation, so we don't need a synchronous push.
+ */
+ error = xfs_log_force(mp, XFS_LOG_SYNC);
+ if (error)
+ return error;
+ xfs_ail_push_all(mp->m_ail);
+
+ /*
+ * Lock the primary superblock buffer to serialize all callers that
+ * are trying to set feature bits.
+ */
+ xfs_buf_lock(mp->m_sb_bp);
+ xfs_buf_hold(mp->m_sb_bp);
+
+ if (xfs_is_shutdown(mp)) {
+ error = -EIO;
+ goto rele;
+ }
+
+ if (xfs_sb_has_incompat_log_feature(&mp->m_sb, feature))
+ goto rele;
+
+ /*
+ * Write the primary superblock to disk immediately, because we need
+ * the log_incompat bit to be set in the primary super now to protect
+ * the log items that we're going to commit later.
+ */
+ dsb = mp->m_sb_bp->b_addr;
+ xfs_sb_to_disk(dsb, &mp->m_sb);
+ dsb->sb_features_log_incompat |= cpu_to_be32(feature);
+ error = xfs_bwrite(mp->m_sb_bp);
+ if (error)
+ goto shutdown;
+
+ /*
+ * Add the feature bits to the incore superblock before we unlock the
+ * buffer.
+ */
+ xfs_sb_add_incompat_log_features(&mp->m_sb, feature);
+ xfs_buf_relse(mp->m_sb_bp);
+
+ /* Log the superblock to disk. */
+ return xfs_sync_sb(mp, false);
+shutdown:
+ xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
+rele:
+ xfs_buf_relse(mp->m_sb_bp);
+ return error;
+}
+
+/*
+ * Clear all the log incompat flags from the superblock.
+ *
+ * The caller cannot be in a transaction, must ensure that the log does not
+ * contain any log items protected by any log incompat bit, and must ensure
+ * that there are no other threads that depend on the state of the log incompat
+ * feature flags in the primary super.
+ *
+ * Returns true if the superblock is dirty.
+ */
+bool
+xfs_clear_incompat_log_features(
+ struct xfs_mount *mp)
+{
+ bool ret = false;
+
+ if (!xfs_has_crc(mp) ||
+ !xfs_sb_has_incompat_log_feature(&mp->m_sb,
+ XFS_SB_FEAT_INCOMPAT_LOG_ALL) ||
+ xfs_is_shutdown(mp))
+ return false;
+
+ /*
+ * Update the incore superblock. We synchronize on the primary super
+ * buffer lock to be consistent with the add function, though at least
+ * in theory this shouldn't be necessary.
+ */
+ xfs_buf_lock(mp->m_sb_bp);
+ xfs_buf_hold(mp->m_sb_bp);
+
+ if (xfs_sb_has_incompat_log_feature(&mp->m_sb,
+ XFS_SB_FEAT_INCOMPAT_LOG_ALL)) {
+ xfs_info(mp, "Clearing log incompat feature flags.");
+ xfs_sb_remove_incompat_log_features(&mp->m_sb);
+ ret = true;
+ }
+
+ xfs_buf_relse(mp->m_sb_bp);
+ return ret;
+}
+
+/*
* Update the in-core delayed block counter.
*
* We prefer to update the counter without having to take a spinlock for every
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index c78b63fe779a..e091f3b3fa15 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -57,6 +57,18 @@ struct xfs_error_cfg {
};
/*
+ * Per-cpu deferred inode inactivation GC lists.
+ */
+struct xfs_inodegc {
+ struct llist_head list;
+ struct work_struct work;
+
+ /* approximate count of inodes in the list */
+ unsigned int items;
+ unsigned int shrinker_hits;
+};
+
+/*
* The struct xfsmount layout is optimised to separate read-mostly variables
* from variables that are frequently modified. We put the read-mostly variables
* first, then place all the other variables at the end.
@@ -82,6 +94,9 @@ typedef struct xfs_mount {
xfs_buftarg_t *m_ddev_targp; /* saves taking the address */
xfs_buftarg_t *m_logdev_targp;/* ptr to log device */
xfs_buftarg_t *m_rtdev_targp; /* ptr to rt device */
+ struct list_head m_mount_list; /* global mount list */
+ void __percpu *m_inodegc; /* percpu inodegc structures */
+
/*
* Optional cache of rt summary level per bitmap block with the
* invariant that m_rsum_cache[bbno] <= the minimum i for which
@@ -92,10 +107,10 @@ typedef struct xfs_mount {
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
struct workqueue_struct *m_buf_workqueue;
struct workqueue_struct *m_unwritten_workqueue;
- struct workqueue_struct *m_cil_workqueue;
struct workqueue_struct *m_reclaim_workqueue;
- struct workqueue_struct *m_gc_workqueue;
struct workqueue_struct *m_sync_workqueue;
+ struct workqueue_struct *m_blockgc_wq;
+ struct workqueue_struct *m_inodegc_wq;
int m_bsize; /* fs logical block size */
uint8_t m_blkbit_log; /* blocklog + NBBY */
@@ -131,11 +146,13 @@ typedef struct xfs_mount {
uint m_rsumsize; /* size of rt summary, bytes */
int m_fixedfsid[2]; /* unchanged for life of FS */
uint m_qflags; /* quota status flags */
- uint64_t m_flags; /* global mount flags */
- int64_t m_low_space[XFS_LOWSP_MAX];
+ uint64_t m_features; /* active filesystem features */
+ uint64_t m_low_space[XFS_LOWSP_MAX];
+ uint64_t m_low_rtexts[XFS_LOWSP_MAX];
struct xfs_ino_geometry m_ino_geo; /* inode geometry */
struct xfs_trans_resv m_resv; /* precomputed res values */
/* low free space thresholds */
+ unsigned long m_opstate; /* dynamic state flags */
bool m_always_cow;
bool m_fail_unmount;
bool m_finobt_nores; /* no per-AG finobt resv. */
@@ -193,6 +210,8 @@ typedef struct xfs_mount {
xfs_agnumber_t m_agirotor; /* last ag dir inode alloced */
spinlock_t m_agirotor_lock;/* .. and lock protecting it */
+ /* Memory shrinker to throttle and reprioritize inodegc */
+ struct shrinker m_inodegc_shrinker;
/*
* Workqueue item so that we can coalesce multiple inode flush attempts
* into a single flush.
@@ -225,38 +244,178 @@ typedef struct xfs_mount {
#define M_IGEO(mp) (&(mp)->m_ino_geo)
/*
- * Flags for m_flags.
+ * Flags for m_features.
+ *
+ * These are all the active features in the filesystem, regardless of how
+ * they are configured.
*/
-#define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops
- must be synchronous except
- for space allocations */
-#define XFS_MOUNT_UNMOUNTING (1ULL << 1) /* filesystem is unmounting */
-#define XFS_MOUNT_WAS_CLEAN (1ULL << 3)
-#define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem
- operations, typically for
- disk errors in metadata */
-#define XFS_MOUNT_DISCARD (1ULL << 5) /* discard unused blocks */
-#define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment
- allocations */
-#define XFS_MOUNT_ATTR2 (1ULL << 8) /* allow use of attr2 format */
-#define XFS_MOUNT_GRPID (1ULL << 9) /* group-ID assigned from directory */
-#define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */
-#define XFS_MOUNT_ALLOCSIZE (1ULL << 12) /* specified allocation size */
-#define XFS_MOUNT_SMALL_INUMS (1ULL << 14) /* user wants 32bit inodes */
-#define XFS_MOUNT_32BITINODES (1ULL << 15) /* inode32 allocator active */
-#define XFS_MOUNT_NOUUID (1ULL << 16) /* ignore uuid during mount */
-#define XFS_MOUNT_IKEEP (1ULL << 18) /* keep empty inode clusters*/
-#define XFS_MOUNT_SWALLOC (1ULL << 19) /* turn on stripe width
- * allocation */
-#define XFS_MOUNT_RDONLY (1ULL << 20) /* read-only fs */
-#define XFS_MOUNT_DIRSYNC (1ULL << 21) /* synchronous directory ops */
-#define XFS_MOUNT_LARGEIO (1ULL << 22) /* report large preferred
+#define XFS_FEAT_ATTR (1ULL << 0) /* xattrs present in fs */
+#define XFS_FEAT_NLINK (1ULL << 1) /* 32 bit link counts */
+#define XFS_FEAT_QUOTA (1ULL << 2) /* quota active */
+#define XFS_FEAT_ALIGN (1ULL << 3) /* inode alignment */
+#define XFS_FEAT_DALIGN (1ULL << 4) /* data alignment */
+#define XFS_FEAT_LOGV2 (1ULL << 5) /* version 2 logs */
+#define XFS_FEAT_SECTOR (1ULL << 6) /* sector size > 512 bytes */
+#define XFS_FEAT_EXTFLG (1ULL << 7) /* unwritten extents */
+#define XFS_FEAT_ASCIICI (1ULL << 8) /* ASCII only case-insens. */
+#define XFS_FEAT_LAZYSBCOUNT (1ULL << 9) /* Superblk counters */
+#define XFS_FEAT_ATTR2 (1ULL << 10) /* dynamic attr fork */
+#define XFS_FEAT_PARENT (1ULL << 11) /* parent pointers */
+#define XFS_FEAT_PROJID32 (1ULL << 12) /* 32 bit project id */
+#define XFS_FEAT_CRC (1ULL << 13) /* metadata CRCs */
+#define XFS_FEAT_V3INODES (1ULL << 14) /* Version 3 inodes */
+#define XFS_FEAT_PQUOTINO (1ULL << 15) /* non-shared proj/grp quotas */
+#define XFS_FEAT_FTYPE (1ULL << 16) /* inode type in dir */
+#define XFS_FEAT_FINOBT (1ULL << 17) /* free inode btree */
+#define XFS_FEAT_RMAPBT (1ULL << 18) /* reverse map btree */
+#define XFS_FEAT_REFLINK (1ULL << 19) /* reflinked files */
+#define XFS_FEAT_SPINODES (1ULL << 20) /* sparse inode chunks */
+#define XFS_FEAT_META_UUID (1ULL << 21) /* metadata UUID */
+#define XFS_FEAT_REALTIME (1ULL << 22) /* realtime device present */
+#define XFS_FEAT_INOBTCNT (1ULL << 23) /* inobt block counts */
+#define XFS_FEAT_BIGTIME (1ULL << 24) /* large timestamps */
+#define XFS_FEAT_NEEDSREPAIR (1ULL << 25) /* needs xfs_repair */
+
+/* Mount features */
+#define XFS_FEAT_NOATTR2 (1ULL << 48) /* disable attr2 creation */
+#define XFS_FEAT_NOALIGN (1ULL << 49) /* ignore alignment */
+#define XFS_FEAT_ALLOCSIZE (1ULL << 50) /* user specified allocation size */
+#define XFS_FEAT_LARGE_IOSIZE (1ULL << 51) /* report large preferred
* I/O size in stat() */
-#define XFS_MOUNT_FILESTREAMS (1ULL << 24) /* enable the filestreams
- allocator */
-#define XFS_MOUNT_NOATTR2 (1ULL << 25) /* disable use of attr2 format */
-#define XFS_MOUNT_DAX_ALWAYS (1ULL << 26)
-#define XFS_MOUNT_DAX_NEVER (1ULL << 27)
+#define XFS_FEAT_WSYNC (1ULL << 52) /* synchronous metadata ops */
+#define XFS_FEAT_DIRSYNC (1ULL << 53) /* synchronous directory ops */
+#define XFS_FEAT_DISCARD (1ULL << 54) /* discard unused blocks */
+#define XFS_FEAT_GRPID (1ULL << 55) /* group-ID assigned from directory */
+#define XFS_FEAT_SMALL_INUMS (1ULL << 56) /* user wants 32bit inodes */
+#define XFS_FEAT_IKEEP (1ULL << 57) /* keep empty inode clusters*/
+#define XFS_FEAT_SWALLOC (1ULL << 58) /* stripe width allocation */
+#define XFS_FEAT_FILESTREAMS (1ULL << 59) /* use filestreams allocator */
+#define XFS_FEAT_DAX_ALWAYS (1ULL << 60) /* DAX always enabled */
+#define XFS_FEAT_DAX_NEVER (1ULL << 61) /* DAX never enabled */
+#define XFS_FEAT_NORECOVERY (1ULL << 62) /* no recovery - dirty fs */
+#define XFS_FEAT_NOUUID (1ULL << 63) /* ignore uuid during mount */
+
+#define __XFS_HAS_FEAT(name, NAME) \
+static inline bool xfs_has_ ## name (struct xfs_mount *mp) \
+{ \
+ return mp->m_features & XFS_FEAT_ ## NAME; \
+}
+
+/* Some features can be added dynamically so they need a set wrapper, too. */
+#define __XFS_ADD_FEAT(name, NAME) \
+ __XFS_HAS_FEAT(name, NAME); \
+static inline void xfs_add_ ## name (struct xfs_mount *mp) \
+{ \
+ mp->m_features |= XFS_FEAT_ ## NAME; \
+ xfs_sb_version_add ## name(&mp->m_sb); \
+}
+
+/* Superblock features */
+__XFS_ADD_FEAT(attr, ATTR)
+__XFS_HAS_FEAT(nlink, NLINK)
+__XFS_ADD_FEAT(quota, QUOTA)
+__XFS_HAS_FEAT(align, ALIGN)
+__XFS_HAS_FEAT(dalign, DALIGN)
+__XFS_HAS_FEAT(logv2, LOGV2)
+__XFS_HAS_FEAT(sector, SECTOR)
+__XFS_HAS_FEAT(extflg, EXTFLG)
+__XFS_HAS_FEAT(asciici, ASCIICI)
+__XFS_HAS_FEAT(lazysbcount, LAZYSBCOUNT)
+__XFS_ADD_FEAT(attr2, ATTR2)
+__XFS_HAS_FEAT(parent, PARENT)
+__XFS_ADD_FEAT(projid32, PROJID32)
+__XFS_HAS_FEAT(crc, CRC)
+__XFS_HAS_FEAT(v3inodes, V3INODES)
+__XFS_HAS_FEAT(pquotino, PQUOTINO)
+__XFS_HAS_FEAT(ftype, FTYPE)
+__XFS_HAS_FEAT(finobt, FINOBT)
+__XFS_HAS_FEAT(rmapbt, RMAPBT)
+__XFS_HAS_FEAT(reflink, REFLINK)
+__XFS_HAS_FEAT(sparseinodes, SPINODES)
+__XFS_HAS_FEAT(metauuid, META_UUID)
+__XFS_HAS_FEAT(realtime, REALTIME)
+__XFS_HAS_FEAT(inobtcounts, INOBTCNT)
+__XFS_HAS_FEAT(bigtime, BIGTIME)
+__XFS_HAS_FEAT(needsrepair, NEEDSREPAIR)
+
+/*
+ * Mount features
+ *
+ * These do not change dynamically - features that can come and go, such as 32
+ * bit inodes and read-only state, are kept as operational state rather than
+ * features.
+ */
+__XFS_HAS_FEAT(noattr2, NOATTR2)
+__XFS_HAS_FEAT(noalign, NOALIGN)
+__XFS_HAS_FEAT(allocsize, ALLOCSIZE)
+__XFS_HAS_FEAT(large_iosize, LARGE_IOSIZE)
+__XFS_HAS_FEAT(wsync, WSYNC)
+__XFS_HAS_FEAT(dirsync, DIRSYNC)
+__XFS_HAS_FEAT(discard, DISCARD)
+__XFS_HAS_FEAT(grpid, GRPID)
+__XFS_HAS_FEAT(small_inums, SMALL_INUMS)
+__XFS_HAS_FEAT(ikeep, IKEEP)
+__XFS_HAS_FEAT(swalloc, SWALLOC)
+__XFS_HAS_FEAT(filestreams, FILESTREAMS)
+__XFS_HAS_FEAT(dax_always, DAX_ALWAYS)
+__XFS_HAS_FEAT(dax_never, DAX_NEVER)
+__XFS_HAS_FEAT(norecovery, NORECOVERY)
+__XFS_HAS_FEAT(nouuid, NOUUID)
+
+/*
+ * Operational mount state flags
+ *
+ * Use these with atomic bit ops only!
+ */
+#define XFS_OPSTATE_UNMOUNTING 0 /* filesystem is unmounting */
+#define XFS_OPSTATE_CLEAN 1 /* mount was clean */
+#define XFS_OPSTATE_SHUTDOWN 2 /* stop all fs operations */
+#define XFS_OPSTATE_INODE32 3 /* inode32 allocator active */
+#define XFS_OPSTATE_READONLY 4 /* read-only fs */
+
+/*
+ * If set, inactivation worker threads will be scheduled to process queued
+ * inodegc work. If not, queued inodes remain in memory waiting to be
+ * processed.
+ */
+#define XFS_OPSTATE_INODEGC_ENABLED 5
+/*
+ * If set, background speculative prealloc gc worker threads will be scheduled
+ * to process queued blockgc work. If not, inodes retain their preallocations
+ * until explicitly deleted.
+ */
+#define XFS_OPSTATE_BLOCKGC_ENABLED 6
+
+#define __XFS_IS_OPSTATE(name, NAME) \
+static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
+{ \
+ return test_bit(XFS_OPSTATE_ ## NAME, &mp->m_opstate); \
+} \
+static inline bool xfs_clear_ ## name (struct xfs_mount *mp) \
+{ \
+ return test_and_clear_bit(XFS_OPSTATE_ ## NAME, &mp->m_opstate); \
+} \
+static inline bool xfs_set_ ## name (struct xfs_mount *mp) \
+{ \
+ return test_and_set_bit(XFS_OPSTATE_ ## NAME, &mp->m_opstate); \
+}
+
+__XFS_IS_OPSTATE(unmounting, UNMOUNTING)
+__XFS_IS_OPSTATE(clean, CLEAN)
+__XFS_IS_OPSTATE(shutdown, SHUTDOWN)
+__XFS_IS_OPSTATE(inode32, INODE32)
+__XFS_IS_OPSTATE(readonly, READONLY)
+__XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED)
+__XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED)
+
+#define XFS_OPSTATE_STRINGS \
+ { (1UL << XFS_OPSTATE_UNMOUNTING), "unmounting" }, \
+ { (1UL << XFS_OPSTATE_CLEAN), "clean" }, \
+ { (1UL << XFS_OPSTATE_SHUTDOWN), "shutdown" }, \
+ { (1UL << XFS_OPSTATE_INODE32), "inode32" }, \
+ { (1UL << XFS_OPSTATE_READONLY), "read_only" }, \
+ { (1UL << XFS_OPSTATE_INODEGC_ENABLED), "inodegc" }, \
+ { (1UL << XFS_OPSTATE_BLOCKGC_ENABLED), "blockgc" }
/*
* Max and min values for mount-option defined I/O
@@ -265,9 +424,7 @@ typedef struct xfs_mount {
#define XFS_MAX_IO_LOG 30 /* 1G */
#define XFS_MIN_IO_LOG PAGE_SHIFT
-#define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \
- ((mp)->m_flags & XFS_MOUNT_WAS_CLEAN)
-#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
+#define xfs_is_shutdown(mp) xfs_is_shutdown(mp)
void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
int lnnum);
#define xfs_force_shutdown(m,f) \
@@ -278,6 +435,12 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
#define SHUTDOWN_FORCE_UMOUNT 0x0004 /* shutdown from a forced unmount */
#define SHUTDOWN_CORRUPT_INCORE 0x0008 /* corrupt in-memory data structures */
+#define XFS_SHUTDOWN_STRINGS \
+ { SHUTDOWN_META_IO_ERROR, "metadata_io" }, \
+ { SHUTDOWN_LOG_IO_ERROR, "log_io" }, \
+ { SHUTDOWN_FORCE_UMOUNT, "force_umount" }, \
+ { SHUTDOWN_CORRUPT_INCORE, "corruption" }
+
/*
* Flags for xfs_mountfs
*/
@@ -306,6 +469,15 @@ extern uint64_t xfs_default_resblks(xfs_mount_t *mp);
extern int xfs_mountfs(xfs_mount_t *mp);
extern void xfs_unmountfs(xfs_mount_t *);
+/*
+ * Deltas for the block count can vary from 1 to very large, but lock contention
+ * only occurs on frequent small block count updates such as in the delayed
+ * allocation path for buffered writes (page a time updates). Hence we set
+ * a large batch count (1024) to minimise global counter updates except when
+ * we get near to ENOSPC and we have to be very accurate with our updates.
+ */
+#define XFS_FDBLOCKS_BATCH 1024
+
extern int xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
bool reserved);
extern int xfs_mod_frextents(struct xfs_mount *mp, int64_t delta);
@@ -325,6 +497,8 @@ int xfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb,
struct xfs_error_cfg * xfs_error_get_cfg(struct xfs_mount *mp,
int error_class, int error);
void xfs_force_summary_recalc(struct xfs_mount *mp);
+int xfs_add_incompat_log_feature(struct xfs_mount *mp, uint32_t feature);
+bool xfs_clear_incompat_log_features(struct xfs_mount *mp);
void xfs_mod_delalloc(struct xfs_mount *mp, int64_t delta);
#endif /* __XFS_MOUNT_H__ */
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index 956cca24e67f..5e1d29d8b2e7 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -92,7 +92,7 @@ xfs_fs_map_blocks(
uint lock_flags;
int error = 0;
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
/*
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index fe341f3fd419..5608066d6e53 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -157,7 +157,7 @@ xfs_qm_dqpurge(
}
ASSERT(atomic_read(&dqp->q_pincount) == 0);
- ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
+ ASSERT(xfs_is_shutdown(mp) ||
!test_bit(XFS_LI_IN_AIL, &dqp->q_logitem.qli_item.li_flags));
xfs_dqfunlock(dqp);
@@ -185,17 +185,13 @@ out_unlock:
/*
* Purge the dquot cache.
*/
-void
+static void
xfs_qm_dqpurge_all(
- struct xfs_mount *mp,
- uint flags)
+ struct xfs_mount *mp)
{
- if (flags & XFS_QMOPT_UQUOTA)
- xfs_qm_dquot_walk(mp, XFS_DQTYPE_USER, xfs_qm_dqpurge, NULL);
- if (flags & XFS_QMOPT_GQUOTA)
- xfs_qm_dquot_walk(mp, XFS_DQTYPE_GROUP, xfs_qm_dqpurge, NULL);
- if (flags & XFS_QMOPT_PQUOTA)
- xfs_qm_dquot_walk(mp, XFS_DQTYPE_PROJ, xfs_qm_dqpurge, NULL);
+ xfs_qm_dquot_walk(mp, XFS_DQTYPE_USER, xfs_qm_dqpurge, NULL);
+ xfs_qm_dquot_walk(mp, XFS_DQTYPE_GROUP, xfs_qm_dqpurge, NULL);
+ xfs_qm_dquot_walk(mp, XFS_DQTYPE_PROJ, xfs_qm_dqpurge, NULL);
}
/*
@@ -206,7 +202,7 @@ xfs_qm_unmount(
struct xfs_mount *mp)
{
if (mp->m_quotainfo) {
- xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL);
+ xfs_qm_dqpurge_all(mp);
xfs_qm_destroy_quotainfo(mp);
}
}
@@ -299,8 +295,6 @@ xfs_qm_need_dqattach(
{
struct xfs_mount *mp = ip->i_mount;
- if (!XFS_IS_QUOTA_RUNNING(mp))
- return false;
if (!XFS_IS_QUOTA_ON(mp))
return false;
if (!XFS_NOT_DQATTACHED(mp, ip))
@@ -635,7 +629,7 @@ xfs_qm_init_quotainfo(
struct xfs_quotainfo *qinf;
int error;
- ASSERT(XFS_IS_QUOTA_RUNNING(mp));
+ ASSERT(XFS_IS_QUOTA_ON(mp));
qinf = mp->m_quotainfo = kmem_zalloc(sizeof(struct xfs_quotainfo), 0);
@@ -662,7 +656,7 @@ xfs_qm_init_quotainfo(
/* Precalc some constants */
qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB);
qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(qinf->qi_dqchunklen);
- if (xfs_sb_version_hasbigtime(&mp->m_sb)) {
+ if (xfs_has_bigtime(mp)) {
qinf->qi_expiry_min =
xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MIN);
qinf->qi_expiry_max =
@@ -680,11 +674,11 @@ xfs_qm_init_quotainfo(
xfs_qm_init_timelimits(mp, XFS_DQTYPE_GROUP);
xfs_qm_init_timelimits(mp, XFS_DQTYPE_PROJ);
- if (XFS_IS_UQUOTA_RUNNING(mp))
+ if (XFS_IS_UQUOTA_ON(mp))
xfs_qm_set_defquota(mp, XFS_DQTYPE_USER, qinf);
- if (XFS_IS_GQUOTA_RUNNING(mp))
+ if (XFS_IS_GQUOTA_ON(mp))
xfs_qm_set_defquota(mp, XFS_DQTYPE_GROUP, qinf);
- if (XFS_IS_PQUOTA_RUNNING(mp))
+ if (XFS_IS_PQUOTA_ON(mp))
xfs_qm_set_defquota(mp, XFS_DQTYPE_PROJ, qinf);
qinf->qi_shrinker.count_objects = xfs_qm_shrink_count;
@@ -755,7 +749,7 @@ xfs_qm_qino_alloc(
* with PQUOTA, just use sb_gquotino for sb_pquotino and
* vice-versa.
*/
- if (!xfs_sb_version_has_pquotino(&mp->m_sb) &&
+ if (!xfs_has_pquotino(mp) &&
(flags & (XFS_QMOPT_PQUOTA|XFS_QMOPT_GQUOTA))) {
xfs_ino_t ino = NULLFSINO;
@@ -808,9 +802,9 @@ xfs_qm_qino_alloc(
*/
spin_lock(&mp->m_sb_lock);
if (flags & XFS_QMOPT_SBVERSION) {
- ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));
+ ASSERT(!xfs_has_quota(mp));
- xfs_sb_version_addquota(&mp->m_sb);
+ xfs_add_quota(mp);
mp->m_sb.sb_uquotino = NULLFSINO;
mp->m_sb.sb_gquotino = NULLFSINO;
mp->m_sb.sb_pquotino = NULLFSINO;
@@ -829,7 +823,7 @@ xfs_qm_qino_alloc(
error = xfs_trans_commit(tp);
if (error) {
- ASSERT(XFS_FORCED_SHUTDOWN(mp));
+ ASSERT(xfs_is_shutdown(mp));
xfs_alert(mp, "%s failed (error %d)!", __func__, error);
}
if (need_alloc)
@@ -896,11 +890,11 @@ xfs_qm_reset_dqcounts(
ddq->d_bwarns = 0;
ddq->d_iwarns = 0;
ddq->d_rtbwarns = 0;
- if (xfs_sb_version_hasbigtime(&mp->m_sb))
+ if (xfs_has_bigtime(mp))
ddq->d_type |= XFS_DQTYPE_BIGTIME;
}
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
xfs_update_cksum((char *)&dqb[j],
sizeof(struct xfs_dqblk),
XFS_DQUOT_CRC_OFF);
@@ -1147,7 +1141,7 @@ xfs_qm_dqusage_adjust(
xfs_filblks_t rtblks = 0; /* total rt blks */
int error;
- ASSERT(XFS_IS_QUOTA_RUNNING(mp));
+ ASSERT(XFS_IS_QUOTA_ON(mp));
/*
* rootino must have its resources accounted for, not so with the quota
@@ -1288,7 +1282,7 @@ xfs_qm_quotacheck(
flags = 0;
ASSERT(uip || gip || pip);
- ASSERT(XFS_IS_QUOTA_RUNNING(mp));
+ ASSERT(XFS_IS_QUOTA_ON(mp));
xfs_notice(mp, "Quotacheck needed: Please wait.");
@@ -1359,7 +1353,7 @@ xfs_qm_quotacheck(
* at this point (because we intentionally didn't in dqget_noattach).
*/
if (error) {
- xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL);
+ xfs_qm_dqpurge_all(mp);
goto error_return;
}
@@ -1418,7 +1412,7 @@ xfs_qm_mount_quotas(
goto write_changes;
}
- ASSERT(XFS_IS_QUOTA_RUNNING(mp));
+ ASSERT(XFS_IS_QUOTA_ON(mp));
/*
* Allocate the quotainfo structure inside the mount struct, and
@@ -1473,7 +1467,7 @@ xfs_qm_mount_quotas(
* the incore structures are convinced that quotas are
* off, but the on disk superblock doesn't know that !
*/
- ASSERT(!(XFS_IS_QUOTA_RUNNING(mp)));
+ ASSERT(!(XFS_IS_QUOTA_ON(mp)));
xfs_alert(mp, "%s: Superblock update failed!",
__func__);
}
@@ -1504,7 +1498,7 @@ xfs_qm_init_quotainos(
/*
* Get the uquota and gquota inodes
*/
- if (xfs_sb_version_hasquota(&mp->m_sb)) {
+ if (xfs_has_quota(mp)) {
if (XFS_IS_UQUOTA_ON(mp) &&
mp->m_sb.sb_uquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_uquotino > 0);
@@ -1645,7 +1639,7 @@ xfs_qm_vop_dqalloc(
int error;
uint lockflags;
- if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return 0;
lockflags = XFS_ILOCK_EXCL;
@@ -1776,7 +1770,7 @@ xfs_qm_vop_chown(
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
- ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
+ ASSERT(XFS_IS_QUOTA_ON(ip->i_mount));
/* old dquot */
prevdq = *IO_olddq;
@@ -1829,7 +1823,7 @@ xfs_qm_vop_rename_dqattach(
struct xfs_mount *mp = i_tab[0]->i_mount;
int i;
- if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return 0;
for (i = 0; (i < 4 && i_tab[i]); i++) {
@@ -1860,7 +1854,7 @@ xfs_qm_vop_create_dqattach(
{
struct xfs_mount *mp = tp->t_mountp;
- if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return;
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
@@ -1888,3 +1882,37 @@ xfs_qm_vop_create_dqattach(
}
}
+/* Decide if this inode's dquot is near an enforcement boundary. */
+bool
+xfs_inode_near_dquot_enforcement(
+ struct xfs_inode *ip,
+ xfs_dqtype_t type)
+{
+ struct xfs_dquot *dqp;
+ int64_t freesp;
+
+ /* We only care for quotas that are enabled and enforced. */
+ dqp = xfs_inode_dquot(ip, type);
+ if (!dqp || !xfs_dquot_is_enforced(dqp))
+ return false;
+
+ if (xfs_dquot_res_over_limits(&dqp->q_ino) ||
+ xfs_dquot_res_over_limits(&dqp->q_rtb))
+ return true;
+
+ /* For space on the data device, check the various thresholds. */
+ if (!dqp->q_prealloc_hi_wmark)
+ return false;
+
+ if (dqp->q_blk.reserved < dqp->q_prealloc_lo_wmark)
+ return false;
+
+ if (dqp->q_blk.reserved >= dqp->q_prealloc_hi_wmark)
+ return true;
+
+ freesp = dqp->q_prealloc_hi_wmark - dqp->q_blk.reserved;
+ if (freesp < dqp->q_low_space[XFS_QLOWSP_5_PCNT])
+ return true;
+
+ return false;
+}
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index ebbb484c49dc..442a0f97a9d4 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -140,9 +140,6 @@ struct xfs_dquot_acct {
extern void xfs_qm_destroy_quotainfo(struct xfs_mount *);
-/* dquot stuff */
-extern void xfs_qm_dqpurge_all(struct xfs_mount *, uint);
-
/* quota ops */
extern int xfs_qm_scall_trunc_qfiles(struct xfs_mount *, uint);
extern int xfs_qm_scall_getquota(struct xfs_mount *mp,
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index df00dfbf5c9d..b77673dd0558 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -75,7 +75,7 @@ xfs_qm_newmount(
uint quotaondisk;
uint uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
- quotaondisk = xfs_sb_version_hasquota(&mp->m_sb) &&
+ quotaondisk = xfs_has_quota(mp) &&
(mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
if (quotaondisk) {
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 13a56e1ea15c..47fe60e1a887 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -19,91 +19,11 @@
#include "xfs_qm.h"
#include "xfs_icache.h"
-STATIC int
-xfs_qm_log_quotaoff(
- struct xfs_mount *mp,
- struct xfs_qoff_logitem **qoffstartp,
- uint flags)
-{
- struct xfs_trans *tp;
- int error;
- struct xfs_qoff_logitem *qoffi;
-
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_quotaoff, 0, 0, 0, &tp);
- if (error)
- goto out;
-
- qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
- xfs_trans_log_quotaoff_item(tp, qoffi);
-
- spin_lock(&mp->m_sb_lock);
- mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
- spin_unlock(&mp->m_sb_lock);
-
- xfs_log_sb(tp);
-
- /*
- * We have to make sure that the transaction is secure on disk before we
- * return and actually stop quota accounting. So, make it synchronous.
- * We don't care about quotoff's performance.
- */
- xfs_trans_set_sync(tp);
- error = xfs_trans_commit(tp);
- if (error)
- goto out;
-
- *qoffstartp = qoffi;
-out:
- return error;
-}
-
-STATIC int
-xfs_qm_log_quotaoff_end(
- struct xfs_mount *mp,
- struct xfs_qoff_logitem **startqoff,
- uint flags)
-{
- struct xfs_trans *tp;
- int error;
- struct xfs_qoff_logitem *qoffi;
-
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_equotaoff, 0, 0, 0, &tp);
- if (error)
- return error;
-
- qoffi = xfs_trans_get_qoff_item(tp, *startqoff,
- flags & XFS_ALL_QUOTA_ACCT);
- xfs_trans_log_quotaoff_item(tp, qoffi);
- *startqoff = NULL;
-
- /*
- * We have to make sure that the transaction is secure on disk before we
- * return and actually stop quota accounting. So, make it synchronous.
- * We don't care about quotoff's performance.
- */
- xfs_trans_set_sync(tp);
- return xfs_trans_commit(tp);
-}
-
-/*
- * Turn off quota accounting and/or enforcement for all udquots and/or
- * gdquots. Called only at unmount time.
- *
- * This assumes that there are no dquots of this file system cached
- * incore, and modifies the ondisk dquot directly. Therefore, for example,
- * it is an error to call this twice, without purging the cache.
- */
int
xfs_qm_scall_quotaoff(
xfs_mount_t *mp,
uint flags)
{
- struct xfs_quotainfo *q = mp->m_quotainfo;
- uint dqtype;
- int error;
- uint inactivate_flags;
- struct xfs_qoff_logitem *qoffstart = NULL;
-
/*
* No file system can have quotas enabled on disk but not in core.
* Note that quota utilities (like quotaoff) _expect_
@@ -111,160 +31,23 @@ xfs_qm_scall_quotaoff(
*/
if ((mp->m_qflags & flags) == 0)
return -EEXIST;
- error = 0;
-
- flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
-
- /*
- * We don't want to deal with two quotaoffs messing up each other,
- * so we're going to serialize it. quotaoff isn't exactly a performance
- * critical thing.
- * If quotaoff, then we must be dealing with the root filesystem.
- */
- ASSERT(q);
- mutex_lock(&q->qi_quotaofflock);
/*
- * If we're just turning off quota enforcement, change mp and go.
+ * We do not support actually turning off quota accounting any more.
+ * Just log a warning and ignore the accounting related flags.
*/
- if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
- mp->m_qflags &= ~(flags);
+ if (flags & XFS_ALL_QUOTA_ACCT)
+ xfs_info(mp, "disabling of quota accounting not supported.");
- spin_lock(&mp->m_sb_lock);
- mp->m_sb.sb_qflags = mp->m_qflags;
- spin_unlock(&mp->m_sb_lock);
- mutex_unlock(&q->qi_quotaofflock);
-
- /* XXX what to do if error ? Revert back to old vals incore ? */
- return xfs_sync_sb(mp, false);
- }
-
- dqtype = 0;
- inactivate_flags = 0;
- /*
- * If accounting is off, we must turn enforcement off, clear the
- * quota 'CHKD' certificate to make it known that we have to
- * do a quotacheck the next time this quota is turned on.
- */
- if (flags & XFS_UQUOTA_ACCT) {
- dqtype |= XFS_QMOPT_UQUOTA;
- flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
- inactivate_flags |= XFS_UQUOTA_ACTIVE;
- }
- if (flags & XFS_GQUOTA_ACCT) {
- dqtype |= XFS_QMOPT_GQUOTA;
- flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
- inactivate_flags |= XFS_GQUOTA_ACTIVE;
- }
- if (flags & XFS_PQUOTA_ACCT) {
- dqtype |= XFS_QMOPT_PQUOTA;
- flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
- inactivate_flags |= XFS_PQUOTA_ACTIVE;
- }
-
- /*
- * Nothing to do? Don't complain. This happens when we're just
- * turning off quota enforcement.
- */
- if ((mp->m_qflags & flags) == 0)
- goto out_unlock;
-
- /*
- * Write the LI_QUOTAOFF log record, and do SB changes atomically,
- * and synchronously. If we fail to write, we should abort the
- * operation as it cannot be recovered safely if we crash.
- */
- error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
- if (error)
- goto out_unlock;
-
- /*
- * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
- * to take care of the race between dqget and quotaoff. We don't take
- * any special locks to reset these bits. All processes need to check
- * these bits *after* taking inode lock(s) to see if the particular
- * quota type is in the process of being turned off. If *ACTIVE, it is
- * guaranteed that all dquot structures and all quotainode ptrs will all
- * stay valid as long as that inode is kept locked.
- *
- * There is no turning back after this.
- */
- mp->m_qflags &= ~inactivate_flags;
-
- /*
- * Give back all the dquot reference(s) held by inodes.
- * Here we go thru every single incore inode in this file system, and
- * do a dqrele on the i_udquot/i_gdquot that it may have.
- * Essentially, as long as somebody has an inode locked, this guarantees
- * that quotas will not be turned off. This is handy because in a
- * transaction once we lock the inode(s) and check for quotaon, we can
- * depend on the quota inodes (and other things) being valid as long as
- * we keep the lock(s).
- */
- error = xfs_dqrele_all_inodes(mp, flags);
- ASSERT(!error);
-
- /*
- * Next we make the changes in the quota flag in the mount struct.
- * This isn't protected by a particular lock directly, because we
- * don't want to take a mrlock every time we depend on quotas being on.
- */
- mp->m_qflags &= ~flags;
-
- /*
- * Go through all the dquots of this file system and purge them,
- * according to what was turned off.
- */
- xfs_qm_dqpurge_all(mp, dqtype);
-
- /*
- * Transactions that had started before ACTIVE state bit was cleared
- * could have logged many dquots, so they'd have higher LSNs than
- * the first QUOTAOFF log record does. If we happen to crash when
- * the tail of the log has gone past the QUOTAOFF record, but
- * before the last dquot modification, those dquots __will__
- * recover, and that's not good.
- *
- * So, we have QUOTAOFF start and end logitems; the start
- * logitem won't get overwritten until the end logitem appears...
- */
- error = xfs_qm_log_quotaoff_end(mp, &qoffstart, flags);
- if (error) {
- /* We're screwed now. Shutdown is the only option. */
- xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
- goto out_unlock;
- }
-
- /*
- * If all quotas are completely turned off, close shop.
- */
- if (mp->m_qflags == 0) {
- mutex_unlock(&q->qi_quotaofflock);
- xfs_qm_destroy_quotainfo(mp);
- return 0;
- }
-
- /*
- * Release our quotainode references if we don't need them anymore.
- */
- if ((dqtype & XFS_QMOPT_UQUOTA) && q->qi_uquotaip) {
- xfs_irele(q->qi_uquotaip);
- q->qi_uquotaip = NULL;
- }
- if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
- xfs_irele(q->qi_gquotaip);
- q->qi_gquotaip = NULL;
- }
- if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
- xfs_irele(q->qi_pquotaip);
- q->qi_pquotaip = NULL;
- }
+ mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
+ mp->m_qflags &= ~(flags & XFS_ALL_QUOTA_ENFD);
+ spin_lock(&mp->m_sb_lock);
+ mp->m_sb.sb_qflags = mp->m_qflags;
+ spin_unlock(&mp->m_sb_lock);
+ mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
-out_unlock:
- if (error && qoffstart)
- xfs_qm_qoff_logitem_relse(qoffstart);
- mutex_unlock(&q->qi_quotaofflock);
- return error;
+ /* XXX what to do if error ? Revert back to old vals incore ? */
+ return xfs_sync_sb(mp, false);
}
STATIC int
@@ -322,7 +105,7 @@ xfs_qm_scall_trunc_qfiles(
{
int error = -EINVAL;
- if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0 ||
+ if (!xfs_has_quota(mp) || flags == 0 ||
(flags & ~XFS_QMOPT_QUOTALL)) {
xfs_debug(mp, "%s: flags=%x m_qflags=%x",
__func__, flags, mp->m_qflags);
@@ -421,7 +204,7 @@ xfs_qm_scall_quotaon(
(mp->m_qflags & XFS_GQUOTA_ACCT)))
return 0;
- if (! XFS_IS_QUOTA_RUNNING(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return -ESRCH;
/*
@@ -698,6 +481,10 @@ xfs_qm_scall_getquota(
struct xfs_dquot *dqp;
int error;
+ /* Flush inodegc work at the start of a quota reporting scan. */
+ if (id == 0)
+ xfs_inodegc_flush(mp);
+
/*
* Try to get the dquot. We don't want it allocated on disk, so don't
* set doalloc. If it doesn't exist, we'll get ENOENT back.
@@ -736,6 +523,10 @@ xfs_qm_scall_getquota_next(
struct xfs_dquot *dqp;
int error;
+ /* Flush inodegc work at the start of a quota reporting scan. */
+ if (*id == 0)
+ xfs_inodegc_flush(mp);
+
error = xfs_qm_dqget_next(mp, *id, type, &dqp);
if (error)
return error;
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index d00d01302545..dcc785fdd345 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -113,6 +113,7 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t blocks)
{
return xfs_trans_reserve_quota_nblks(NULL, ip, blocks, 0, false);
}
+bool xfs_inode_near_dquot_enforcement(struct xfs_inode *ip, xfs_dqtype_t type);
#else
static inline int
xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid,
@@ -168,6 +169,7 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
#define xfs_qm_mount_quotas(mp)
#define xfs_qm_unmount(mp)
#define xfs_qm_unmount_quotas(mp)
+#define xfs_inode_near_dquot_enforcement(ip, type) (false)
#endif /* CONFIG_XFS_QUOTA */
static inline int
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index 88d70c236a54..07989bd67728 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -60,18 +60,18 @@ xfs_fs_get_quota_state(
struct xfs_quotainfo *q = mp->m_quotainfo;
memset(state, 0, sizeof(*state));
- if (!XFS_IS_QUOTA_RUNNING(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return 0;
state->s_incoredqs = q->qi_dquots;
- if (XFS_IS_UQUOTA_RUNNING(mp))
+ if (XFS_IS_UQUOTA_ON(mp))
state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED;
if (XFS_IS_UQUOTA_ENFORCED(mp))
state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
- if (XFS_IS_GQUOTA_RUNNING(mp))
+ if (XFS_IS_GQUOTA_ON(mp))
state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED;
if (XFS_IS_GQUOTA_ENFORCED(mp))
state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
- if (XFS_IS_PQUOTA_RUNNING(mp))
+ if (XFS_IS_PQUOTA_ON(mp))
state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED;
if (XFS_IS_PQUOTA_ENFORCED(mp))
state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
@@ -114,10 +114,8 @@ xfs_fs_set_info(
if (sb_rdonly(sb))
return -EROFS;
- if (!XFS_IS_QUOTA_RUNNING(mp))
- return -ENOSYS;
if (!XFS_IS_QUOTA_ON(mp))
- return -ESRCH;
+ return -ENOSYS;
if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
return -EINVAL;
if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
@@ -164,7 +162,7 @@ xfs_quota_enable(
if (sb_rdonly(sb))
return -EROFS;
- if (!XFS_IS_QUOTA_RUNNING(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return -ENOSYS;
return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags));
@@ -179,10 +177,8 @@ xfs_quota_disable(
if (sb_rdonly(sb))
return -EROFS;
- if (!XFS_IS_QUOTA_RUNNING(mp))
- return -ENOSYS;
if (!XFS_IS_QUOTA_ON(mp))
- return -EINVAL;
+ return -ENOSYS;
return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
}
@@ -223,10 +219,8 @@ xfs_fs_get_dqblk(
struct xfs_mount *mp = XFS_M(sb);
xfs_dqid_t id;
- if (!XFS_IS_QUOTA_RUNNING(mp))
- return -ENOSYS;
if (!XFS_IS_QUOTA_ON(mp))
- return -ESRCH;
+ return -ENOSYS;
id = from_kqid(&init_user_ns, qid);
return xfs_qm_scall_getquota(mp, id, xfs_quota_type(qid.type), qdq);
@@ -243,10 +237,8 @@ xfs_fs_get_nextdqblk(
struct xfs_mount *mp = XFS_M(sb);
xfs_dqid_t id;
- if (!XFS_IS_QUOTA_RUNNING(mp))
- return -ENOSYS;
if (!XFS_IS_QUOTA_ON(mp))
- return -ESRCH;
+ return -ENOSYS;
id = from_kqid(&init_user_ns, *qid);
ret = xfs_qm_scall_getquota_next(mp, &id, xfs_quota_type(qid->type),
@@ -269,10 +261,8 @@ xfs_fs_set_dqblk(
if (sb_rdonly(sb))
return -EROFS;
- if (!XFS_IS_QUOTA_RUNNING(mp))
- return -ENOSYS;
if (!XFS_IS_QUOTA_ON(mp))
- return -ESRCH;
+ return -ENOSYS;
return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
xfs_quota_type(qid.type), qdq);
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index 746f4eda724c..46904b793bd4 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -423,7 +423,7 @@ xfs_cui_validate_phys(
struct xfs_mount *mp,
struct xfs_phys_extent *refc)
{
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return false;
if (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS)
@@ -522,6 +522,9 @@ xfs_cui_item_recover(
error = xfs_trans_log_finish_refcount_update(tp, cudp,
type, refc->pe_startblock, refc->pe_len,
&new_fsb, &new_len, &rcur);
+ if (error == -EFSCORRUPTED)
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+ refc, sizeof(*refc));
if (error)
goto abort_error;
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index c256104772cb..76355f293488 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -759,7 +759,7 @@ xfs_reflink_recover_cow(
xfs_agnumber_t agno;
int error = 0;
- if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ if (!xfs_has_reflink(mp))
return 0;
for_each_perag(mp, agno, pag) {
@@ -967,7 +967,7 @@ xfs_reflink_ag_has_free_space(
struct xfs_perag *pag;
int error = 0;
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return 0;
pag = xfs_perag_get(mp, agno);
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index 487b00434b96..bea65f2fe657 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -8,8 +8,7 @@
static inline bool xfs_is_always_cow_inode(struct xfs_inode *ip)
{
- return ip->i_mount->m_always_cow &&
- xfs_sb_version_hasreflink(&ip->i_mount->m_sb);
+ return ip->i_mount->m_always_cow && xfs_has_reflink(ip->i_mount);
}
static inline bool xfs_is_cow_inode(struct xfs_inode *ip)
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index dc4f0c9f0897..5f0695980467 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -466,7 +466,7 @@ xfs_rui_validate_map(
struct xfs_mount *mp,
struct xfs_map_extent *rmap)
{
- if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ if (!xfs_has_rmapbt(mp))
return false;
if (rmap->me_flags & ~XFS_RMAP_EXTENT_FLAGS)
@@ -578,6 +578,9 @@ xfs_rui_item_recover(
rmap->me_owner, whichfork,
rmap->me_startoff, rmap->me_startblock,
rmap->me_len, state, &rcur);
+ if (error == -EFSCORRUPTED)
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+ rmap, sizeof(*rmap));
if (error)
goto abort_error;
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 699066fb9052..b8c79ee791af 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -951,8 +951,7 @@ xfs_growfs_rt(
return -EINVAL;
/* Unsupported realtime features. */
- if (xfs_sb_version_hasrmapbt(&mp->m_sb) ||
- xfs_sb_version_hasreflink(&mp->m_sb))
+ if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp))
return -EOPNOTSUPP;
nrblocks = in->newblocks;
@@ -1131,6 +1130,9 @@ error_cancel:
error = xfs_trans_commit(tp);
if (error)
break;
+
+ /* Ensure the mount RT feature flag is now set. */
+ mp->m_features |= XFS_FEAT_REALTIME;
}
if (error)
goto out_free;
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index ed885620589c..91b00289509b 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -22,9 +22,9 @@ struct xfs_rtalloc_rec {
};
typedef int (*xfs_rtalloc_query_range_fn)(
- struct xfs_trans *tp,
- struct xfs_rtalloc_rec *rec,
- void *priv);
+ struct xfs_trans *tp,
+ const struct xfs_rtalloc_rec *rec,
+ void *priv);
#ifdef CONFIG_XFS_RT
/*
@@ -124,10 +124,9 @@ int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_extlen_t len,
struct xfs_buf **rbpp, xfs_fsblock_t *rsb);
int xfs_rtalloc_query_range(struct xfs_trans *tp,
- struct xfs_rtalloc_rec *low_rec,
- struct xfs_rtalloc_rec *high_rec,
- xfs_rtalloc_query_range_fn fn,
- void *priv);
+ const struct xfs_rtalloc_rec *low_rec,
+ const struct xfs_rtalloc_rec *high_rec,
+ xfs_rtalloc_query_range_fn fn, void *priv);
int xfs_rtalloc_query_all(struct xfs_trans *tp,
xfs_rtalloc_query_range_fn fn,
void *priv);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 102cbd606633..9a86d3ec2cb6 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -49,6 +49,28 @@ static struct kset *xfs_kset; /* top-level xfs sysfs dir */
static struct xfs_kobj xfs_dbg_kobj; /* global debug sysfs attrs */
#endif
+#ifdef CONFIG_HOTPLUG_CPU
+static LIST_HEAD(xfs_mount_list);
+static DEFINE_SPINLOCK(xfs_mount_list_lock);
+
+static inline void xfs_mount_list_add(struct xfs_mount *mp)
+{
+ spin_lock(&xfs_mount_list_lock);
+ list_add(&mp->m_mount_list, &xfs_mount_list);
+ spin_unlock(&xfs_mount_list_lock);
+}
+
+static inline void xfs_mount_list_del(struct xfs_mount *mp)
+{
+ spin_lock(&xfs_mount_list_lock);
+ list_del(&mp->m_mount_list);
+ spin_unlock(&xfs_mount_list_lock);
+}
+#else /* !CONFIG_HOTPLUG_CPU */
+static inline void xfs_mount_list_add(struct xfs_mount *mp) {}
+static inline void xfs_mount_list_del(struct xfs_mount *mp) {}
+#endif
+
enum xfs_dax_mode {
XFS_DAX_INODE = 0,
XFS_DAX_ALWAYS = 1,
@@ -62,15 +84,15 @@ xfs_mount_set_dax_mode(
{
switch (mode) {
case XFS_DAX_INODE:
- mp->m_flags &= ~(XFS_MOUNT_DAX_ALWAYS | XFS_MOUNT_DAX_NEVER);
+ mp->m_features &= ~(XFS_FEAT_DAX_ALWAYS | XFS_FEAT_DAX_NEVER);
break;
case XFS_DAX_ALWAYS:
- mp->m_flags |= XFS_MOUNT_DAX_ALWAYS;
- mp->m_flags &= ~XFS_MOUNT_DAX_NEVER;
+ mp->m_features |= XFS_FEAT_DAX_ALWAYS;
+ mp->m_features &= ~XFS_FEAT_DAX_NEVER;
break;
case XFS_DAX_NEVER:
- mp->m_flags |= XFS_MOUNT_DAX_NEVER;
- mp->m_flags &= ~XFS_MOUNT_DAX_ALWAYS;
+ mp->m_features |= XFS_FEAT_DAX_NEVER;
+ mp->m_features &= ~XFS_FEAT_DAX_ALWAYS;
break;
}
}
@@ -154,33 +176,32 @@ xfs_fs_show_options(
{
static struct proc_xfs_info xfs_info_set[] = {
/* the few simple ones we can get from the mount struct */
- { XFS_MOUNT_IKEEP, ",ikeep" },
- { XFS_MOUNT_WSYNC, ",wsync" },
- { XFS_MOUNT_NOALIGN, ",noalign" },
- { XFS_MOUNT_SWALLOC, ",swalloc" },
- { XFS_MOUNT_NOUUID, ",nouuid" },
- { XFS_MOUNT_NORECOVERY, ",norecovery" },
- { XFS_MOUNT_ATTR2, ",attr2" },
- { XFS_MOUNT_FILESTREAMS, ",filestreams" },
- { XFS_MOUNT_GRPID, ",grpid" },
- { XFS_MOUNT_DISCARD, ",discard" },
- { XFS_MOUNT_LARGEIO, ",largeio" },
- { XFS_MOUNT_DAX_ALWAYS, ",dax=always" },
- { XFS_MOUNT_DAX_NEVER, ",dax=never" },
+ { XFS_FEAT_IKEEP, ",ikeep" },
+ { XFS_FEAT_WSYNC, ",wsync" },
+ { XFS_FEAT_NOALIGN, ",noalign" },
+ { XFS_FEAT_SWALLOC, ",swalloc" },
+ { XFS_FEAT_NOUUID, ",nouuid" },
+ { XFS_FEAT_NORECOVERY, ",norecovery" },
+ { XFS_FEAT_ATTR2, ",attr2" },
+ { XFS_FEAT_FILESTREAMS, ",filestreams" },
+ { XFS_FEAT_GRPID, ",grpid" },
+ { XFS_FEAT_DISCARD, ",discard" },
+ { XFS_FEAT_LARGE_IOSIZE, ",largeio" },
+ { XFS_FEAT_DAX_ALWAYS, ",dax=always" },
+ { XFS_FEAT_DAX_NEVER, ",dax=never" },
{ 0, NULL }
};
struct xfs_mount *mp = XFS_M(root->d_sb);
struct proc_xfs_info *xfs_infop;
for (xfs_infop = xfs_info_set; xfs_infop->flag; xfs_infop++) {
- if (mp->m_flags & xfs_infop->flag)
+ if (mp->m_features & xfs_infop->flag)
seq_puts(m, xfs_infop->str);
}
- seq_printf(m, ",inode%d",
- (mp->m_flags & XFS_MOUNT_SMALL_INUMS) ? 32 : 64);
+ seq_printf(m, ",inode%d", xfs_has_small_inums(mp) ? 32 : 64);
- if (mp->m_flags & XFS_MOUNT_ALLOCSIZE)
+ if (xfs_has_allocsize(mp))
seq_printf(m, ",allocsize=%dk",
(1 << mp->m_allocsize_log) >> 10);
@@ -201,25 +222,20 @@ xfs_fs_show_options(
seq_printf(m, ",swidth=%d",
(int)XFS_FSB_TO_BB(mp, mp->m_swidth));
- if (mp->m_qflags & XFS_UQUOTA_ACCT) {
- if (mp->m_qflags & XFS_UQUOTA_ENFD)
- seq_puts(m, ",usrquota");
- else
- seq_puts(m, ",uqnoenforce");
- }
+ if (mp->m_qflags & XFS_UQUOTA_ENFD)
+ seq_puts(m, ",usrquota");
+ else if (mp->m_qflags & XFS_UQUOTA_ACCT)
+ seq_puts(m, ",uqnoenforce");
- if (mp->m_qflags & XFS_PQUOTA_ACCT) {
- if (mp->m_qflags & XFS_PQUOTA_ENFD)
- seq_puts(m, ",prjquota");
- else
- seq_puts(m, ",pqnoenforce");
- }
- if (mp->m_qflags & XFS_GQUOTA_ACCT) {
- if (mp->m_qflags & XFS_GQUOTA_ENFD)
- seq_puts(m, ",grpquota");
- else
- seq_puts(m, ",gqnoenforce");
- }
+ if (mp->m_qflags & XFS_PQUOTA_ENFD)
+ seq_puts(m, ",prjquota");
+ else if (mp->m_qflags & XFS_PQUOTA_ACCT)
+ seq_puts(m, ",pqnoenforce");
+
+ if (mp->m_qflags & XFS_GQUOTA_ENFD)
+ seq_puts(m, ",grpquota");
+ else if (mp->m_qflags & XFS_GQUOTA_ACCT)
+ seq_puts(m, ",gqnoenforce");
if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
seq_puts(m, ",noquota");
@@ -230,11 +246,11 @@ xfs_fs_show_options(
/*
* Set parameters for inode allocation heuristics, taking into account
* filesystem size and inode32/inode64 mount options; i.e. specifically
- * whether or not XFS_MOUNT_SMALL_INUMS is set.
+ * whether or not XFS_FEAT_SMALL_INUMS is set.
*
* Inode allocation patterns are altered only if inode32 is requested
- * (XFS_MOUNT_SMALL_INUMS), and the filesystem is sufficiently large.
- * If altered, XFS_MOUNT_32BITINODES is set as well.
+ * (XFS_FEAT_SMALL_INUMS), and the filesystem is sufficiently large.
+ * If altered, XFS_OPSTATE_INODE32 is set as well.
*
* An agcount independent of that in the mount structure is provided
* because in the growfs case, mp->m_sb.sb_agcount is not yet updated
@@ -276,13 +292,13 @@ xfs_set_inode_alloc(
/*
* If user asked for no more than 32-bit inodes, and the fs is
- * sufficiently large, set XFS_MOUNT_32BITINODES if we must alter
+ * sufficiently large, set XFS_OPSTATE_INODE32 if we must alter
* the allocator to accommodate the request.
*/
- if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
- mp->m_flags |= XFS_MOUNT_32BITINODES;
+ if (xfs_has_small_inums(mp) && ino > XFS_MAXINUMBER_32)
+ set_bit(XFS_OPSTATE_INODE32, &mp->m_opstate);
else
- mp->m_flags &= ~XFS_MOUNT_32BITINODES;
+ clear_bit(XFS_OPSTATE_INODE32, &mp->m_opstate);
for (index = 0; index < agcount; index++) {
struct xfs_perag *pag;
@@ -291,7 +307,7 @@ xfs_set_inode_alloc(
pag = xfs_perag_get(mp, index);
- if (mp->m_flags & XFS_MOUNT_32BITINODES) {
+ if (xfs_is_inode32(mp)) {
if (ino > XFS_MAXINUMBER_32) {
pag->pagi_inodeok = 0;
pag->pagf_metadata = 0;
@@ -311,7 +327,7 @@ xfs_set_inode_alloc(
xfs_perag_put(pag);
}
- return (mp->m_flags & XFS_MOUNT_32BITINODES) ? maxagi : agcount;
+ return xfs_is_inode32(mp) ? maxagi : agcount;
}
STATIC int
@@ -468,7 +484,7 @@ xfs_setup_devices(
if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
unsigned int log_sector_size = BBSIZE;
- if (xfs_sb_version_hassector(&mp->m_sb))
+ if (xfs_has_sector(mp))
log_sector_size = mp->m_sb.sb_logsectsize;
error = xfs_setsize_buftarg(mp->m_logdev_targp,
log_sector_size);
@@ -501,37 +517,37 @@ xfs_init_mount_workqueues(
if (!mp->m_unwritten_workqueue)
goto out_destroy_buf;
- mp->m_cil_workqueue = alloc_workqueue("xfs-cil/%s",
- XFS_WQFLAGS(WQ_FREEZABLE | WQ_MEM_RECLAIM | WQ_UNBOUND),
- 0, mp->m_super->s_id);
- if (!mp->m_cil_workqueue)
- goto out_destroy_unwritten;
-
mp->m_reclaim_workqueue = alloc_workqueue("xfs-reclaim/%s",
XFS_WQFLAGS(WQ_FREEZABLE | WQ_MEM_RECLAIM),
0, mp->m_super->s_id);
if (!mp->m_reclaim_workqueue)
- goto out_destroy_cil;
+ goto out_destroy_unwritten;
- mp->m_gc_workqueue = alloc_workqueue("xfs-gc/%s",
- WQ_SYSFS | WQ_UNBOUND | WQ_FREEZABLE | WQ_MEM_RECLAIM,
+ mp->m_blockgc_wq = alloc_workqueue("xfs-blockgc/%s",
+ XFS_WQFLAGS(WQ_UNBOUND | WQ_FREEZABLE | WQ_MEM_RECLAIM),
0, mp->m_super->s_id);
- if (!mp->m_gc_workqueue)
+ if (!mp->m_blockgc_wq)
goto out_destroy_reclaim;
+ mp->m_inodegc_wq = alloc_workqueue("xfs-inodegc/%s",
+ XFS_WQFLAGS(WQ_FREEZABLE | WQ_MEM_RECLAIM),
+ 1, mp->m_super->s_id);
+ if (!mp->m_inodegc_wq)
+ goto out_destroy_blockgc;
+
mp->m_sync_workqueue = alloc_workqueue("xfs-sync/%s",
XFS_WQFLAGS(WQ_FREEZABLE), 0, mp->m_super->s_id);
if (!mp->m_sync_workqueue)
- goto out_destroy_eofb;
+ goto out_destroy_inodegc;
return 0;
-out_destroy_eofb:
- destroy_workqueue(mp->m_gc_workqueue);
+out_destroy_inodegc:
+ destroy_workqueue(mp->m_inodegc_wq);
+out_destroy_blockgc:
+ destroy_workqueue(mp->m_blockgc_wq);
out_destroy_reclaim:
destroy_workqueue(mp->m_reclaim_workqueue);
-out_destroy_cil:
- destroy_workqueue(mp->m_cil_workqueue);
out_destroy_unwritten:
destroy_workqueue(mp->m_unwritten_workqueue);
out_destroy_buf:
@@ -545,9 +561,9 @@ xfs_destroy_mount_workqueues(
struct xfs_mount *mp)
{
destroy_workqueue(mp->m_sync_workqueue);
- destroy_workqueue(mp->m_gc_workqueue);
+ destroy_workqueue(mp->m_blockgc_wq);
+ destroy_workqueue(mp->m_inodegc_wq);
destroy_workqueue(mp->m_reclaim_workqueue);
- destroy_workqueue(mp->m_cil_workqueue);
destroy_workqueue(mp->m_unwritten_workqueue);
destroy_workqueue(mp->m_buf_workqueue);
}
@@ -596,32 +612,6 @@ xfs_fs_alloc_inode(
return NULL;
}
-#ifdef DEBUG
-static void
-xfs_check_delalloc(
- struct xfs_inode *ip,
- int whichfork)
-{
- struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
- struct xfs_bmbt_irec got;
- struct xfs_iext_cursor icur;
-
- if (!ifp || !xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got))
- return;
- do {
- if (isnullstartblock(got.br_startblock)) {
- xfs_warn(ip->i_mount,
- "ino %llx %s fork has delalloc extent at [0x%llx:0x%llx]",
- ip->i_ino,
- whichfork == XFS_DATA_FORK ? "data" : "cow",
- got.br_startoff, got.br_blockcount);
- }
- } while (xfs_iext_next_extent(ifp, &icur, &got));
-}
-#else
-#define xfs_check_delalloc(ip, whichfork) do { } while (0)
-#endif
-
/*
* Now that the generic code is guaranteed not to be accessing
* the linux inode, we can inactivate and reclaim the inode.
@@ -637,30 +627,6 @@ xfs_fs_destroy_inode(
ASSERT(!rwsem_is_locked(&inode->i_rwsem));
XFS_STATS_INC(ip->i_mount, vn_rele);
XFS_STATS_INC(ip->i_mount, vn_remove);
-
- xfs_inactive(ip);
-
- if (!XFS_FORCED_SHUTDOWN(ip->i_mount) && ip->i_delayed_blks) {
- xfs_check_delalloc(ip, XFS_DATA_FORK);
- xfs_check_delalloc(ip, XFS_COW_FORK);
- ASSERT(0);
- }
-
- XFS_STATS_INC(ip->i_mount, vn_reclaim);
-
- /*
- * We should never get here with one of the reclaim flags already set.
- */
- ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
- ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIM));
-
- /*
- * We always use background reclaim here because even if the inode is
- * clean, it still may be under IO and hence we have wait for IO
- * completion to occur before we can reclaim the inode. The background
- * reclaim path handles this more efficiently than we can here, so
- * simply let background reclaim tear down all inodes.
- */
xfs_inode_mark_reclaimable(ip);
}
@@ -732,7 +698,7 @@ xfs_fs_drop_inode(
* that. See the comment for this inode flag.
*/
if (ip->i_flags & XFS_IRECOVERY) {
- ASSERT(ip->i_mount->m_log->l_flags & XLOG_RECOVERY_NEEDED);
+ ASSERT(xlog_recovery_needed(ip->i_mount->m_log));
return 0;
}
@@ -755,6 +721,8 @@ xfs_fs_sync_fs(
{
struct xfs_mount *mp = XFS_M(sb);
+ trace_xfs_fs_sync_fs(mp, __return_address);
+
/*
* Doing anything during the async pass would be counterproductive.
*/
@@ -771,6 +739,25 @@ xfs_fs_sync_fs(
flush_delayed_work(&mp->m_log->l_work);
}
+ /*
+ * If we are called with page faults frozen out, it means we are about
+ * to freeze the transaction subsystem. Take the opportunity to shut
+ * down inodegc because once SB_FREEZE_FS is set it's too late to
+ * prevent inactivation races with freeze. The fs doesn't get called
+ * again by the freezing process until after SB_FREEZE_FS has been set,
+ * so it's now or never. Same logic applies to speculative allocation
+ * garbage collection.
+ *
+ * We don't care if this is a normal syncfs call that does this or
+ * freeze that does this - we can run this multiple times without issue
+ * and we won't race with a restart because a restart can only occur
+ * when the state is either SB_FREEZE_FS or SB_FREEZE_COMPLETE.
+ */
+ if (sb->s_writers.frozen == SB_FREEZE_PAGEFAULT) {
+ xfs_inodegc_stop(mp);
+ xfs_blockgc_stop(mp);
+ }
+
return 0;
}
@@ -789,6 +776,9 @@ xfs_fs_statfs(
xfs_extlen_t lsize;
int64_t ffree;
+ /* Wait for whatever inactivations are in progress. */
+ xfs_inodegc_flush(mp);
+
statp->f_type = XFS_SUPER_MAGIC;
statp->f_namelen = MAXNAMELEN - 1;
@@ -884,10 +874,22 @@ xfs_fs_freeze(
* set a GFP_NOFS context here to avoid recursion deadlocks.
*/
flags = memalloc_nofs_save();
- xfs_blockgc_stop(mp);
xfs_save_resvblks(mp);
ret = xfs_log_quiesce(mp);
memalloc_nofs_restore(flags);
+
+ /*
+ * For read-write filesystems, we need to restart the inodegc on error
+ * because we stopped it at SB_FREEZE_PAGEFAULT level and a thaw is not
+ * going to be run to restart it now. We are at SB_FREEZE_FS level
+ * here, so we can restart safely without racing with a stop in
+ * xfs_fs_sync_fs().
+ */
+ if (ret && !xfs_is_readonly(mp)) {
+ xfs_blockgc_start(mp);
+ xfs_inodegc_start(mp);
+ }
+
return ret;
}
@@ -899,7 +901,18 @@ xfs_fs_unfreeze(
xfs_restore_resvblks(mp);
xfs_log_work_queue(mp);
- xfs_blockgc_start(mp);
+
+ /*
+ * Don't reactivate the inodegc worker on a readonly filesystem because
+ * inodes are sent directly to reclaim. Don't reactivate the blockgc
+ * worker because there are no speculative preallocations on a readonly
+ * filesystem.
+ */
+ if (!xfs_is_readonly(mp)) {
+ xfs_blockgc_start(mp);
+ xfs_inodegc_start(mp);
+ }
+
return 0;
}
@@ -911,10 +924,8 @@ STATIC int
xfs_finish_flags(
struct xfs_mount *mp)
{
- int ronly = (mp->m_flags & XFS_MOUNT_RDONLY);
-
/* Fail a mount where the logbuf is smaller than the log stripe */
- if (xfs_sb_version_haslogv2(&mp->m_sb)) {
+ if (xfs_has_logv2(mp)) {
if (mp->m_logbsize <= 0 &&
mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE) {
mp->m_logbsize = mp->m_sb.sb_logsunit;
@@ -936,33 +947,24 @@ xfs_finish_flags(
/*
* V5 filesystems always use attr2 format for attributes.
*/
- if (xfs_sb_version_hascrc(&mp->m_sb) &&
- (mp->m_flags & XFS_MOUNT_NOATTR2)) {
+ if (xfs_has_crc(mp) && xfs_has_noattr2(mp)) {
xfs_warn(mp, "Cannot mount a V5 filesystem as noattr2. "
"attr2 is always enabled for V5 filesystems.");
return -EINVAL;
}
/*
- * mkfs'ed attr2 will turn on attr2 mount unless explicitly
- * told by noattr2 to turn it off
- */
- if (xfs_sb_version_hasattr2(&mp->m_sb) &&
- !(mp->m_flags & XFS_MOUNT_NOATTR2))
- mp->m_flags |= XFS_MOUNT_ATTR2;
-
- /*
* prohibit r/w mounts of read-only filesystems
*/
- if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
+ if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !xfs_is_readonly(mp)) {
xfs_warn(mp,
"cannot mount a read-only filesystem as read-write");
return -EROFS;
}
- if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
- (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE)) &&
- !xfs_sb_version_has_pquotino(&mp->m_sb)) {
+ if ((mp->m_qflags & XFS_GQUOTA_ACCT) &&
+ (mp->m_qflags & XFS_PQUOTA_ACCT) &&
+ !xfs_has_pquotino(mp)) {
xfs_warn(mp,
"Super block does not support project and group quota together");
return -EINVAL;
@@ -1020,11 +1022,40 @@ xfs_destroy_percpu_counters(
percpu_counter_destroy(&mp->m_icount);
percpu_counter_destroy(&mp->m_ifree);
percpu_counter_destroy(&mp->m_fdblocks);
- ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
+ ASSERT(xfs_is_shutdown(mp) ||
percpu_counter_sum(&mp->m_delalloc_blks) == 0);
percpu_counter_destroy(&mp->m_delalloc_blks);
}
+static int
+xfs_inodegc_init_percpu(
+ struct xfs_mount *mp)
+{
+ struct xfs_inodegc *gc;
+ int cpu;
+
+ mp->m_inodegc = alloc_percpu(struct xfs_inodegc);
+ if (!mp->m_inodegc)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ gc = per_cpu_ptr(mp->m_inodegc, cpu);
+ init_llist_head(&gc->list);
+ gc->items = 0;
+ INIT_WORK(&gc->work, xfs_inodegc_worker);
+ }
+ return 0;
+}
+
+static void
+xfs_inodegc_free_percpu(
+ struct xfs_mount *mp)
+{
+ if (!mp->m_inodegc)
+ return;
+ free_percpu(mp->m_inodegc);
+}
+
static void
xfs_fs_put_super(
struct super_block *sb)
@@ -1041,6 +1072,8 @@ xfs_fs_put_super(
xfs_freesb(mp);
free_percpu(mp->m_stats.xs_stats);
+ xfs_mount_list_del(mp);
+ xfs_inodegc_free_percpu(mp);
xfs_destroy_percpu_counters(mp);
xfs_destroy_mount_workqueues(mp);
xfs_close_devices(mp);
@@ -1129,7 +1162,7 @@ xfs_fs_warn_deprecated(
* already had the flag set
*/
if ((fc->purpose & FS_CONTEXT_FOR_RECONFIGURE) &&
- !!(XFS_M(fc->root->d_sb)->m_flags & flag) == value)
+ !!(XFS_M(fc->root->d_sb)->m_features & flag) == value)
return;
xfs_warn(fc->s_fs_info, "%s mount option is deprecated.", param->key);
}
@@ -1177,27 +1210,27 @@ xfs_fs_parse_param(
if (suffix_kstrtoint(param->string, 10, &size))
return -EINVAL;
parsing_mp->m_allocsize_log = ffs(size) - 1;
- parsing_mp->m_flags |= XFS_MOUNT_ALLOCSIZE;
+ parsing_mp->m_features |= XFS_FEAT_ALLOCSIZE;
return 0;
case Opt_grpid:
case Opt_bsdgroups:
- parsing_mp->m_flags |= XFS_MOUNT_GRPID;
+ parsing_mp->m_features |= XFS_FEAT_GRPID;
return 0;
case Opt_nogrpid:
case Opt_sysvgroups:
- parsing_mp->m_flags &= ~XFS_MOUNT_GRPID;
+ parsing_mp->m_features &= ~XFS_FEAT_GRPID;
return 0;
case Opt_wsync:
- parsing_mp->m_flags |= XFS_MOUNT_WSYNC;
+ parsing_mp->m_features |= XFS_FEAT_WSYNC;
return 0;
case Opt_norecovery:
- parsing_mp->m_flags |= XFS_MOUNT_NORECOVERY;
+ parsing_mp->m_features |= XFS_FEAT_NORECOVERY;
return 0;
case Opt_noalign:
- parsing_mp->m_flags |= XFS_MOUNT_NOALIGN;
+ parsing_mp->m_features |= XFS_FEAT_NOALIGN;
return 0;
case Opt_swalloc:
- parsing_mp->m_flags |= XFS_MOUNT_SWALLOC;
+ parsing_mp->m_features |= XFS_FEAT_SWALLOC;
return 0;
case Opt_sunit:
parsing_mp->m_dalign = result.uint_32;
@@ -1206,62 +1239,58 @@ xfs_fs_parse_param(
parsing_mp->m_swidth = result.uint_32;
return 0;
case Opt_inode32:
- parsing_mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
+ parsing_mp->m_features |= XFS_FEAT_SMALL_INUMS;
return 0;
case Opt_inode64:
- parsing_mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
+ parsing_mp->m_features &= ~XFS_FEAT_SMALL_INUMS;
return 0;
case Opt_nouuid:
- parsing_mp->m_flags |= XFS_MOUNT_NOUUID;
+ parsing_mp->m_features |= XFS_FEAT_NOUUID;
return 0;
case Opt_largeio:
- parsing_mp->m_flags |= XFS_MOUNT_LARGEIO;
+ parsing_mp->m_features |= XFS_FEAT_LARGE_IOSIZE;
return 0;
case Opt_nolargeio:
- parsing_mp->m_flags &= ~XFS_MOUNT_LARGEIO;
+ parsing_mp->m_features &= ~XFS_FEAT_LARGE_IOSIZE;
return 0;
case Opt_filestreams:
- parsing_mp->m_flags |= XFS_MOUNT_FILESTREAMS;
+ parsing_mp->m_features |= XFS_FEAT_FILESTREAMS;
return 0;
case Opt_noquota:
parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ACCT;
parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ENFD;
- parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ACTIVE;
return 0;
case Opt_quota:
case Opt_uquota:
case Opt_usrquota:
- parsing_mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE |
- XFS_UQUOTA_ENFD);
+ parsing_mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ENFD);
return 0;
case Opt_qnoenforce:
case Opt_uqnoenforce:
- parsing_mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
+ parsing_mp->m_qflags |= XFS_UQUOTA_ACCT;
parsing_mp->m_qflags &= ~XFS_UQUOTA_ENFD;
return 0;
case Opt_pquota:
case Opt_prjquota:
- parsing_mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE |
- XFS_PQUOTA_ENFD);
+ parsing_mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ENFD);
return 0;
case Opt_pqnoenforce:
- parsing_mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
+ parsing_mp->m_qflags |= XFS_PQUOTA_ACCT;
parsing_mp->m_qflags &= ~XFS_PQUOTA_ENFD;
return 0;
case Opt_gquota:
case Opt_grpquota:
- parsing_mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE |
- XFS_GQUOTA_ENFD);
+ parsing_mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ENFD);
return 0;
case Opt_gqnoenforce:
- parsing_mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
+ parsing_mp->m_qflags |= XFS_GQUOTA_ACCT;
parsing_mp->m_qflags &= ~XFS_GQUOTA_ENFD;
return 0;
case Opt_discard:
- parsing_mp->m_flags |= XFS_MOUNT_DISCARD;
+ parsing_mp->m_features |= XFS_FEAT_DISCARD;
return 0;
case Opt_nodiscard:
- parsing_mp->m_flags &= ~XFS_MOUNT_DISCARD;
+ parsing_mp->m_features &= ~XFS_FEAT_DISCARD;
return 0;
#ifdef CONFIG_FS_DAX
case Opt_dax:
@@ -1273,21 +1302,20 @@ xfs_fs_parse_param(
#endif
/* Following mount options will be removed in September 2025 */
case Opt_ikeep:
- xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_IKEEP, true);
- parsing_mp->m_flags |= XFS_MOUNT_IKEEP;
+ xfs_fs_warn_deprecated(fc, param, XFS_FEAT_IKEEP, true);
+ parsing_mp->m_features |= XFS_FEAT_IKEEP;
return 0;
case Opt_noikeep:
- xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_IKEEP, false);
- parsing_mp->m_flags &= ~XFS_MOUNT_IKEEP;
+ xfs_fs_warn_deprecated(fc, param, XFS_FEAT_IKEEP, false);
+ parsing_mp->m_features &= ~XFS_FEAT_IKEEP;
return 0;
case Opt_attr2:
- xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_ATTR2, true);
- parsing_mp->m_flags |= XFS_MOUNT_ATTR2;
+ xfs_fs_warn_deprecated(fc, param, XFS_FEAT_ATTR2, true);
+ parsing_mp->m_features |= XFS_FEAT_ATTR2;
return 0;
case Opt_noattr2:
- xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_NOATTR2, true);
- parsing_mp->m_flags &= ~XFS_MOUNT_ATTR2;
- parsing_mp->m_flags |= XFS_MOUNT_NOATTR2;
+ xfs_fs_warn_deprecated(fc, param, XFS_FEAT_NOATTR2, true);
+ parsing_mp->m_features |= XFS_FEAT_NOATTR2;
return 0;
default:
xfs_warn(parsing_mp, "unknown mount option [%s].", param->key);
@@ -1301,17 +1329,23 @@ static int
xfs_fs_validate_params(
struct xfs_mount *mp)
{
+ /* No recovery flag requires a read-only mount */
+ if (xfs_has_norecovery(mp) && !xfs_is_readonly(mp)) {
+ xfs_warn(mp, "no-recovery mounts must be read-only.");
+ return -EINVAL;
+ }
+
/*
- * no recovery flag requires a read-only mount
+ * We have not read the superblock at this point, so only the attr2
+ * mount option can set the attr2 feature by this stage.
*/
- if ((mp->m_flags & XFS_MOUNT_NORECOVERY) &&
- !(mp->m_flags & XFS_MOUNT_RDONLY)) {
- xfs_warn(mp, "no-recovery mounts must be read-only.");
+ if (xfs_has_attr2(mp) && xfs_has_noattr2(mp)) {
+ xfs_warn(mp, "attr2 and noattr2 cannot both be specified.");
return -EINVAL;
}
- if ((mp->m_flags & XFS_MOUNT_NOALIGN) &&
- (mp->m_dalign || mp->m_swidth)) {
+
+ if (xfs_has_noalign(mp) && (mp->m_dalign || mp->m_swidth)) {
xfs_warn(mp,
"sunit and swidth options incompatible with the noalign option");
return -EINVAL;
@@ -1355,7 +1389,7 @@ xfs_fs_validate_params(
return -EINVAL;
}
- if ((mp->m_flags & XFS_MOUNT_ALLOCSIZE) &&
+ if (xfs_has_allocsize(mp) &&
(mp->m_allocsize_log > XFS_MAX_IO_LOG ||
mp->m_allocsize_log < XFS_MIN_IO_LOG)) {
xfs_warn(mp, "invalid log iosize: %d [not %d-%d]",
@@ -1416,11 +1450,22 @@ xfs_fs_fill_super(
if (error)
goto out_destroy_workqueues;
+ error = xfs_inodegc_init_percpu(mp);
+ if (error)
+ goto out_destroy_counters;
+
+ /*
+ * All percpu data structures requiring cleanup when a cpu goes offline
+ * must be allocated before adding this @mp to the cpu-dead handler's
+ * mount list.
+ */
+ xfs_mount_list_add(mp);
+
/* Allocate stats memory before we do operations that might use it */
mp->m_stats.xs_stats = alloc_percpu(struct xfsstats);
if (!mp->m_stats.xs_stats) {
error = -ENOMEM;
- goto out_destroy_counters;
+ goto out_destroy_inodegc;
}
error = xfs_readsb(mp, flags);
@@ -1436,7 +1481,7 @@ xfs_fs_fill_super(
goto out_free_sb;
/* V4 support is undergoing deprecation. */
- if (!xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (!xfs_has_crc(mp)) {
#ifdef CONFIG_XFS_SUPPORT_V4
xfs_warn_once(mp,
"Deprecated V4 format (crc=0) will not be supported after September 2030.");
@@ -1449,7 +1494,7 @@ xfs_fs_fill_super(
}
/* Filesystem claims it needs repair, so refuse the mount. */
- if (xfs_sb_version_needsrepair(&mp->m_sb)) {
+ if (xfs_has_needsrepair(mp)) {
xfs_warn(mp, "Filesystem needs repair. Please run xfs_repair.");
error = -EFSCORRUPTED;
goto out_free_sb;
@@ -1521,7 +1566,7 @@ xfs_fs_fill_super(
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_max_links = XFS_MAXLINK;
sb->s_time_gran = 1;
- if (xfs_sb_version_hasbigtime(&mp->m_sb)) {
+ if (xfs_has_bigtime(mp)) {
sb->s_time_min = xfs_bigtime_to_unix(XFS_BIGTIME_TIME_MIN);
sb->s_time_max = xfs_bigtime_to_unix(XFS_BIGTIME_TIME_MAX);
} else {
@@ -1534,14 +1579,10 @@ xfs_fs_fill_super(
set_posix_acl_flag(sb);
/* version 5 superblocks support inode version counters. */
- if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5)
+ if (xfs_has_crc(mp))
sb->s_flags |= SB_I_VERSION;
- if (xfs_sb_version_hasbigtime(&mp->m_sb))
- xfs_warn(mp,
- "EXPERIMENTAL big timestamp feature in use. Use at your own risk!");
-
- if (mp->m_flags & XFS_MOUNT_DAX_ALWAYS) {
+ if (xfs_has_dax_always(mp)) {
bool rtdev_is_dax = false, datadev_is_dax;
xfs_warn(mp,
@@ -1557,7 +1598,7 @@ xfs_fs_fill_super(
"DAX unsupported by block device. Turning off DAX.");
xfs_mount_set_dax_mode(mp, XFS_DAX_NEVER);
}
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ if (xfs_has_reflink(mp)) {
xfs_alert(mp,
"DAX and reflink cannot be used together!");
error = -EINVAL;
@@ -1565,17 +1606,17 @@ xfs_fs_fill_super(
}
}
- if (mp->m_flags & XFS_MOUNT_DISCARD) {
+ if (xfs_has_discard(mp)) {
struct request_queue *q = bdev_get_queue(sb->s_bdev);
if (!blk_queue_discard(q)) {
xfs_warn(mp, "mounting with \"discard\" option, but "
"the device does not support discard");
- mp->m_flags &= ~XFS_MOUNT_DISCARD;
+ mp->m_features &= ~XFS_FEAT_DISCARD;
}
}
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ if (xfs_has_reflink(mp)) {
if (mp->m_sb.sb_rblocks) {
xfs_alert(mp,
"reflink not compatible with realtime device!");
@@ -1589,17 +1630,13 @@ xfs_fs_fill_super(
}
}
- if (xfs_sb_version_hasrmapbt(&mp->m_sb) && mp->m_sb.sb_rblocks) {
+ if (xfs_has_rmapbt(mp) && mp->m_sb.sb_rblocks) {
xfs_alert(mp,
"reverse mapping btree not compatible with realtime device!");
error = -EINVAL;
goto out_filestream_unmount;
}
- if (xfs_sb_version_hasinobtcounts(&mp->m_sb))
- xfs_warn(mp,
- "EXPERIMENTAL inode btree counters feature in use. Use at your own risk!");
-
error = xfs_mountfs(mp);
if (error)
goto out_filestream_unmount;
@@ -1623,6 +1660,9 @@ xfs_fs_fill_super(
xfs_freesb(mp);
out_free_stats:
free_percpu(mp->m_stats.xs_stats);
+ out_destroy_inodegc:
+ xfs_mount_list_del(mp);
+ xfs_inodegc_free_percpu(mp);
out_destroy_counters:
xfs_destroy_percpu_counters(mp);
out_destroy_workqueues:
@@ -1654,13 +1694,13 @@ xfs_remount_rw(
struct xfs_sb *sbp = &mp->m_sb;
int error;
- if (mp->m_flags & XFS_MOUNT_NORECOVERY) {
+ if (xfs_has_norecovery(mp)) {
xfs_warn(mp,
"ro->rw transition prohibited on norecovery mount");
return -EINVAL;
}
- if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
+ if (xfs_sb_is_v5(sbp) &&
xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
xfs_warn(mp,
"ro->rw transition prohibited on unknown (0x%x) ro-compat filesystem",
@@ -1669,7 +1709,7 @@ xfs_remount_rw(
return -EINVAL;
}
- mp->m_flags &= ~XFS_MOUNT_RDONLY;
+ clear_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
/*
* If this is the first remount to writeable state we might have some
@@ -1706,6 +1746,9 @@ xfs_remount_rw(
if (error && error != -ENOSPC)
return error;
+ /* Re-enable the background inode inactivation worker. */
+ xfs_inodegc_start(mp);
+
return 0;
}
@@ -1728,6 +1771,15 @@ xfs_remount_ro(
return error;
}
+ /*
+ * Stop the inodegc background worker. xfs_fs_reconfigure already
+ * flushed all pending inodegc work when it sync'd the filesystem.
+ * The VFS holds s_umount, so we know that inodes cannot enter
+ * xfs_fs_destroy_inode during a remount operation. In readonly mode
+ * we send inodes straight to reclaim, so no inodes will be queued.
+ */
+ xfs_inodegc_stop(mp);
+
/* Free the per-AG metadata reservation pool. */
error = xfs_fs_unreserve_ag_blocks(mp);
if (error) {
@@ -1745,7 +1797,7 @@ xfs_remount_ro(
xfs_save_resvblks(mp);
xfs_log_clean(mp);
- mp->m_flags |= XFS_MOUNT_RDONLY;
+ set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
return 0;
}
@@ -1768,12 +1820,11 @@ xfs_fs_reconfigure(
{
struct xfs_mount *mp = XFS_M(fc->root->d_sb);
struct xfs_mount *new_mp = fc->s_fs_info;
- xfs_sb_t *sbp = &mp->m_sb;
int flags = fc->sb_flags;
int error;
/* version 5 superblocks always support version counters. */
- if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5)
+ if (xfs_has_crc(mp))
fc->sb_flags |= SB_I_VERSION;
error = xfs_fs_validate_params(new_mp);
@@ -1783,28 +1834,26 @@ xfs_fs_reconfigure(
sync_filesystem(mp->m_super);
/* inode32 -> inode64 */
- if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) &&
- !(new_mp->m_flags & XFS_MOUNT_SMALL_INUMS)) {
- mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
- mp->m_maxagi = xfs_set_inode_alloc(mp, sbp->sb_agcount);
+ if (xfs_has_small_inums(mp) && !xfs_has_small_inums(new_mp)) {
+ mp->m_features &= ~XFS_FEAT_SMALL_INUMS;
+ mp->m_maxagi = xfs_set_inode_alloc(mp, mp->m_sb.sb_agcount);
}
/* inode64 -> inode32 */
- if (!(mp->m_flags & XFS_MOUNT_SMALL_INUMS) &&
- (new_mp->m_flags & XFS_MOUNT_SMALL_INUMS)) {
- mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
- mp->m_maxagi = xfs_set_inode_alloc(mp, sbp->sb_agcount);
+ if (!xfs_has_small_inums(mp) && xfs_has_small_inums(new_mp)) {
+ mp->m_features |= XFS_FEAT_SMALL_INUMS;
+ mp->m_maxagi = xfs_set_inode_alloc(mp, mp->m_sb.sb_agcount);
}
/* ro -> rw */
- if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(flags & SB_RDONLY)) {
+ if (xfs_is_readonly(mp) && !(flags & SB_RDONLY)) {
error = xfs_remount_rw(mp);
if (error)
return error;
}
/* rw -> ro */
- if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (flags & SB_RDONLY)) {
+ if (!xfs_is_readonly(mp) && (flags & SB_RDONLY)) {
error = xfs_remount_ro(mp);
if (error)
return error;
@@ -1871,11 +1920,11 @@ static int xfs_init_fs_context(
* Copy binary VFS mount flags we are interested in.
*/
if (fc->sb_flags & SB_RDONLY)
- mp->m_flags |= XFS_MOUNT_RDONLY;
+ set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
if (fc->sb_flags & SB_DIRSYNC)
- mp->m_flags |= XFS_MOUNT_DIRSYNC;
+ mp->m_features |= XFS_FEAT_DIRSYNC;
if (fc->sb_flags & SB_SYNCHRONOUS)
- mp->m_flags |= XFS_MOUNT_WSYNC;
+ mp->m_features |= XFS_FEAT_WSYNC;
fc->s_fs_info = mp;
fc->ops = &xfs_context_ops;
@@ -2118,6 +2167,48 @@ xfs_destroy_workqueues(void)
destroy_workqueue(xfs_alloc_wq);
}
+#ifdef CONFIG_HOTPLUG_CPU
+static int
+xfs_cpu_dead(
+ unsigned int cpu)
+{
+ struct xfs_mount *mp, *n;
+
+ spin_lock(&xfs_mount_list_lock);
+ list_for_each_entry_safe(mp, n, &xfs_mount_list, m_mount_list) {
+ spin_unlock(&xfs_mount_list_lock);
+ xfs_inodegc_cpu_dead(mp, cpu);
+ spin_lock(&xfs_mount_list_lock);
+ }
+ spin_unlock(&xfs_mount_list_lock);
+ return 0;
+}
+
+static int __init
+xfs_cpu_hotplug_init(void)
+{
+ int error;
+
+ error = cpuhp_setup_state_nocalls(CPUHP_XFS_DEAD, "xfs:dead", NULL,
+ xfs_cpu_dead);
+ if (error < 0)
+ xfs_alert(NULL,
+"Failed to initialise CPU hotplug, error %d. XFS is non-functional.",
+ error);
+ return error;
+}
+
+static void
+xfs_cpu_hotplug_destroy(void)
+{
+ cpuhp_remove_state_nocalls(CPUHP_XFS_DEAD);
+}
+
+#else /* !CONFIG_HOTPLUG_CPU */
+static inline int xfs_cpu_hotplug_init(void) { return 0; }
+static inline void xfs_cpu_hotplug_destroy(void) {}
+#endif
+
STATIC int __init
init_xfs_fs(void)
{
@@ -2130,10 +2221,14 @@ init_xfs_fs(void)
xfs_dir_startup();
- error = xfs_init_zones();
+ error = xfs_cpu_hotplug_init();
if (error)
goto out;
+ error = xfs_init_zones();
+ if (error)
+ goto out_destroy_hp;
+
error = xfs_init_workqueues();
if (error)
goto out_destroy_zones;
@@ -2213,6 +2308,8 @@ init_xfs_fs(void)
xfs_destroy_workqueues();
out_destroy_zones:
xfs_destroy_zones();
+ out_destroy_hp:
+ xfs_cpu_hotplug_destroy();
out:
return error;
}
@@ -2235,6 +2332,7 @@ exit_xfs_fs(void)
xfs_destroy_workqueues();
xfs_destroy_zones();
xfs_uuid_table_free();
+ xfs_cpu_hotplug_destroy();
}
module_init(init_xfs_fs);
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 1525636f4065..fc2c6a404647 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -63,7 +63,7 @@ xfs_readlink_bmap_ilocked(
byte_cnt = pathlen;
cur_chunk = bp->b_addr;
- if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (xfs_has_crc(mp)) {
if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
byte_cnt, bp)) {
error = -EFSCORRUPTED;
@@ -107,7 +107,7 @@ xfs_readlink(
ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_LOCAL);
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -168,7 +168,7 @@ xfs_symlink(
trace_xfs_symlink(dp, link_name);
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
/*
@@ -321,9 +321,8 @@ xfs_symlink(
* symlink transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
+ if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
xfs_trans_set_sync(tp);
- }
error = xfs_trans_commit(tp);
if (error)
@@ -445,7 +444,7 @@ xfs_inactive_symlink_rmt(
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
error = xfs_trans_commit(tp);
if (error) {
- ASSERT(XFS_FORCED_SHUTDOWN(mp));
+ ASSERT(xfs_is_shutdown(mp));
goto error_unlock;
}
@@ -478,7 +477,7 @@ xfs_inactive_symlink(
trace_xfs_inactive_symlink(ip);
- if (XFS_FORCED_SHUTDOWN(mp))
+ if (xfs_is_shutdown(mp))
return -EIO;
xfs_ilock(ip, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index f1bc88f4367c..18dc5eca6c04 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -10,6 +10,7 @@
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_sysfs.h"
+#include "xfs_log.h"
#include "xfs_log_priv.h"
#include "xfs_mount.h"
diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c
index 7e01e00550ac..d269ef57ff01 100644
--- a/fs/xfs/xfs_trace.c
+++ b/fs/xfs/xfs_trace.c
@@ -20,6 +20,7 @@
#include "xfs_bmap.h"
#include "xfs_attr.h"
#include "xfs_trans.h"
+#include "xfs_log.h"
#include "xfs_log_priv.h"
#include "xfs_buf_item.h"
#include "xfs_quota.h"
@@ -32,6 +33,7 @@
#include "xfs_icache.h"
#include "xfs_ag.h"
#include "xfs_ag_resv.h"
+#include "xfs_error.h"
/*
* We include this last to have the helpers above available for the trace
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 19260291ff8b..1033a95fbf8e 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -2,6 +2,41 @@
/*
* Copyright (c) 2009, Christoph Hellwig
* All Rights Reserved.
+ *
+ * NOTE: none of these tracepoints shall be considered a stable kernel ABI
+ * as they can change at any time.
+ *
+ * Current conventions for printing numbers measuring specific units:
+ *
+ * agno: allocation group number
+ *
+ * agino: per-AG inode number
+ * ino: filesystem inode number
+ *
+ * agbno: per-AG block number in fs blocks
+ * startblock: physical block number for file mappings. This is either a
+ * segmented fsblock for data device mappings, or a rfsblock
+ * for realtime device mappings
+ * fsbcount: number of blocks in an extent, in fs blocks
+ *
+ * daddr: physical block number in 512b blocks
+ * bbcount: number of blocks in a physical extent, in 512b blocks
+ *
+ * owner: reverse-mapping owner, usually inodes
+ *
+ * fileoff: file offset, in fs blocks
+ * pos: file offset, in bytes
+ * bytecount: number of bytes
+ *
+ * disize: ondisk file size, in bytes
+ * isize: incore file size, in bytes
+ *
+ * forkoff: inode fork offset, in bytes
+ *
+ * ireccount: number of inode records
+ *
+ * Numbers describing space allocations (blocks, extents, inodes) should be
+ * formatted in hexadecimal.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM xfs
@@ -139,7 +174,7 @@ DECLARE_EVENT_CLASS(xfs_perag_class,
__entry->refcount = refcount;
__entry->caller_ip = caller_ip;
),
- TP_printk("dev %d:%d agno %u refcount %d caller %pS",
+ TP_printk("dev %d:%d agno 0x%x refcount %d caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->refcount,
@@ -157,6 +192,84 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_put);
DEFINE_PERAG_REF_EVENT(xfs_perag_set_inode_tag);
DEFINE_PERAG_REF_EVENT(xfs_perag_clear_inode_tag);
+TRACE_EVENT(xfs_inodegc_worker,
+ TP_PROTO(struct xfs_mount *mp, unsigned int shrinker_hits),
+ TP_ARGS(mp, shrinker_hits),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(unsigned int, shrinker_hits)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->shrinker_hits = shrinker_hits;
+ ),
+ TP_printk("dev %d:%d shrinker_hits %u",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->shrinker_hits)
+);
+
+DECLARE_EVENT_CLASS(xfs_fs_class,
+ TP_PROTO(struct xfs_mount *mp, void *caller_ip),
+ TP_ARGS(mp, caller_ip),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(unsigned long long, mflags)
+ __field(unsigned long, opstate)
+ __field(unsigned long, sbflags)
+ __field(void *, caller_ip)
+ ),
+ TP_fast_assign(
+ if (mp) {
+ __entry->dev = mp->m_super->s_dev;
+ __entry->mflags = mp->m_features;
+ __entry->opstate = mp->m_opstate;
+ __entry->sbflags = mp->m_super->s_flags;
+ }
+ __entry->caller_ip = caller_ip;
+ ),
+ TP_printk("dev %d:%d m_features 0x%llx opstate (%s) s_flags 0x%lx caller %pS",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->mflags,
+ __print_flags(__entry->opstate, "|", XFS_OPSTATE_STRINGS),
+ __entry->sbflags,
+ __entry->caller_ip)
+);
+
+#define DEFINE_FS_EVENT(name) \
+DEFINE_EVENT(xfs_fs_class, name, \
+ TP_PROTO(struct xfs_mount *mp, void *caller_ip), \
+ TP_ARGS(mp, caller_ip))
+DEFINE_FS_EVENT(xfs_inodegc_flush);
+DEFINE_FS_EVENT(xfs_inodegc_start);
+DEFINE_FS_EVENT(xfs_inodegc_stop);
+DEFINE_FS_EVENT(xfs_inodegc_queue);
+DEFINE_FS_EVENT(xfs_inodegc_throttle);
+DEFINE_FS_EVENT(xfs_fs_sync_fs);
+DEFINE_FS_EVENT(xfs_blockgc_start);
+DEFINE_FS_EVENT(xfs_blockgc_stop);
+DEFINE_FS_EVENT(xfs_blockgc_worker);
+DEFINE_FS_EVENT(xfs_blockgc_flush_all);
+
+TRACE_EVENT(xfs_inodegc_shrinker_scan,
+ TP_PROTO(struct xfs_mount *mp, struct shrink_control *sc,
+ void *caller_ip),
+ TP_ARGS(mp, sc, caller_ip),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(unsigned long, nr_to_scan)
+ __field(void *, caller_ip)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->nr_to_scan = sc->nr_to_scan;
+ __entry->caller_ip = caller_ip;
+ ),
+ TP_printk("dev %d:%d nr_to_scan %lu caller %pS",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->nr_to_scan,
+ __entry->caller_ip)
+);
+
DECLARE_EVENT_CLASS(xfs_ag_class,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno),
TP_ARGS(mp, agno),
@@ -168,7 +281,7 @@ DECLARE_EVENT_CLASS(xfs_ag_class,
__entry->dev = mp->m_super->s_dev;
__entry->agno = agno;
),
- TP_printk("dev %d:%d agno %u",
+ TP_printk("dev %d:%d agno 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno)
);
@@ -268,7 +381,7 @@ DECLARE_EVENT_CLASS(xfs_bmap_class,
__entry->caller_ip = caller_ip;
),
TP_printk("dev %d:%d ino 0x%llx state %s cur %p/%d "
- "offset %lld block %lld count %lld flag %d caller %pS",
+ "fileoff 0x%llx startblock 0x%llx fsbcount 0x%llx flag %d caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS),
@@ -308,10 +421,7 @@ DECLARE_EVENT_CLASS(xfs_buf_class,
),
TP_fast_assign(
__entry->dev = bp->b_target->bt_dev;
- if (bp->b_bn == XFS_BUF_DADDR_NULL)
- __entry->bno = bp->b_maps[0].bm_bn;
- else
- __entry->bno = bp->b_bn;
+ __entry->bno = xfs_buf_daddr(bp);
__entry->nblks = bp->b_length;
__entry->hold = atomic_read(&bp->b_hold);
__entry->pincount = atomic_read(&bp->b_pin_count);
@@ -319,7 +429,7 @@ DECLARE_EVENT_CLASS(xfs_buf_class,
__entry->flags = bp->b_flags;
__entry->caller_ip = caller_ip;
),
- TP_printk("dev %d:%d bno 0x%llx nblks 0x%x hold %d pincount %d "
+ TP_printk("dev %d:%d daddr 0x%llx bbcount 0x%x hold %d pincount %d "
"lock %d flags %s caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long long)__entry->bno,
@@ -370,7 +480,7 @@ DECLARE_EVENT_CLASS(xfs_buf_flags_class,
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_daddr_t, bno)
- __field(size_t, buffer_length)
+ __field(unsigned int, length)
__field(int, hold)
__field(int, pincount)
__field(unsigned, lockval)
@@ -379,19 +489,19 @@ DECLARE_EVENT_CLASS(xfs_buf_flags_class,
),
TP_fast_assign(
__entry->dev = bp->b_target->bt_dev;
- __entry->bno = bp->b_bn;
- __entry->buffer_length = BBTOB(bp->b_length);
+ __entry->bno = xfs_buf_daddr(bp);
+ __entry->length = bp->b_length;
__entry->flags = flags;
__entry->hold = atomic_read(&bp->b_hold);
__entry->pincount = atomic_read(&bp->b_pin_count);
__entry->lockval = bp->b_sema.count;
__entry->caller_ip = caller_ip;
),
- TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
+ TP_printk("dev %d:%d daddr 0x%llx bbcount 0x%x hold %d pincount %d "
"lock %d flags %s caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long long)__entry->bno,
- __entry->buffer_length,
+ __entry->length,
__entry->hold,
__entry->pincount,
__entry->lockval,
@@ -413,7 +523,7 @@ TRACE_EVENT(xfs_buf_ioerror,
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_daddr_t, bno)
- __field(size_t, buffer_length)
+ __field(unsigned int, length)
__field(unsigned, flags)
__field(int, hold)
__field(int, pincount)
@@ -423,8 +533,8 @@ TRACE_EVENT(xfs_buf_ioerror,
),
TP_fast_assign(
__entry->dev = bp->b_target->bt_dev;
- __entry->bno = bp->b_bn;
- __entry->buffer_length = BBTOB(bp->b_length);
+ __entry->bno = xfs_buf_daddr(bp);
+ __entry->length = bp->b_length;
__entry->hold = atomic_read(&bp->b_hold);
__entry->pincount = atomic_read(&bp->b_pin_count);
__entry->lockval = bp->b_sema.count;
@@ -432,11 +542,11 @@ TRACE_EVENT(xfs_buf_ioerror,
__entry->flags = bp->b_flags;
__entry->caller_ip = caller_ip;
),
- TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
+ TP_printk("dev %d:%d daddr 0x%llx bbcount 0x%x hold %d pincount %d "
"lock %d error %d flags %s caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long long)__entry->bno,
- __entry->buffer_length,
+ __entry->length,
__entry->hold,
__entry->pincount,
__entry->lockval,
@@ -451,7 +561,7 @@ DECLARE_EVENT_CLASS(xfs_buf_item_class,
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_daddr_t, buf_bno)
- __field(size_t, buf_len)
+ __field(unsigned int, buf_len)
__field(int, buf_hold)
__field(int, buf_pincount)
__field(int, buf_lockval)
@@ -466,15 +576,15 @@ DECLARE_EVENT_CLASS(xfs_buf_item_class,
__entry->bli_flags = bip->bli_flags;
__entry->bli_recur = bip->bli_recur;
__entry->bli_refcount = atomic_read(&bip->bli_refcount);
- __entry->buf_bno = bip->bli_buf->b_bn;
- __entry->buf_len = BBTOB(bip->bli_buf->b_length);
+ __entry->buf_bno = xfs_buf_daddr(bip->bli_buf);
+ __entry->buf_len = bip->bli_buf->b_length;
__entry->buf_flags = bip->bli_buf->b_flags;
__entry->buf_hold = atomic_read(&bip->bli_buf->b_hold);
__entry->buf_pincount = atomic_read(&bip->bli_buf->b_pin_count);
__entry->buf_lockval = bip->bli_buf->b_sema.count;
__entry->li_flags = bip->bli_item.li_flags;
),
- TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
+ TP_printk("dev %d:%d daddr 0x%llx bbcount 0x%x hold %d pincount %d "
"lock %d flags %s recur %d refcount %d bliflags %s "
"liflags %s",
MAJOR(__entry->dev), MINOR(__entry->dev),
@@ -534,7 +644,7 @@ DECLARE_EVENT_CLASS(xfs_filestream_class,
__entry->agno = agno;
__entry->streams = xfs_filestream_peek_ag(mp, agno);
),
- TP_printk("dev %d:%d ino 0x%llx agno %u streams %d",
+ TP_printk("dev %d:%d ino 0x%llx agno 0x%x streams %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->agno,
@@ -568,7 +678,7 @@ TRACE_EVENT(xfs_filestream_pick,
__entry->free = free;
__entry->nscan = nscan;
),
- TP_printk("dev %d:%d ino 0x%llx agno %u streams %d free %d nscan %d",
+ TP_printk("dev %d:%d ino 0x%llx agno 0x%x streams %d free %d nscan %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->agno,
@@ -616,14 +726,17 @@ DECLARE_EVENT_CLASS(xfs_inode_class,
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_ino_t, ino)
+ __field(unsigned long, iflags)
),
TP_fast_assign(
__entry->dev = VFS_I(ip)->i_sb->s_dev;
__entry->ino = ip->i_ino;
+ __entry->iflags = ip->i_flags;
),
- TP_printk("dev %d:%d ino 0x%llx",
+ TP_printk("dev %d:%d ino 0x%llx iflags 0x%lx",
MAJOR(__entry->dev), MINOR(__entry->dev),
- __entry->ino)
+ __entry->ino,
+ __entry->iflags)
)
#define DEFINE_INODE_EVENT(name) \
@@ -667,6 +780,10 @@ DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid);
DEFINE_INODE_EVENT(xfs_inode_set_cowblocks_tag);
DEFINE_INODE_EVENT(xfs_inode_clear_cowblocks_tag);
DEFINE_INODE_EVENT(xfs_inode_free_cowblocks_invalid);
+DEFINE_INODE_EVENT(xfs_inode_set_reclaimable);
+DEFINE_INODE_EVENT(xfs_inode_reclaiming);
+DEFINE_INODE_EVENT(xfs_inode_set_need_inactive);
+DEFINE_INODE_EVENT(xfs_inode_inactivating);
/*
* ftrace's __print_symbolic requires that all enum values be wrapped in the
@@ -773,9 +890,12 @@ TRACE_EVENT(xfs_irec_merge_pre,
__entry->nagino = nagino;
__entry->nholemask = holemask;
),
- TP_printk("dev %d:%d agno %d inobt (%u:0x%x) new (%u:0x%x)",
- MAJOR(__entry->dev), MINOR(__entry->dev), __entry->agno,
- __entry->agino, __entry->holemask, __entry->nagino,
+ TP_printk("dev %d:%d agno 0x%x agino 0x%x holemask 0x%x new_agino 0x%x new_holemask 0x%x",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->agno,
+ __entry->agino,
+ __entry->holemask,
+ __entry->nagino,
__entry->nholemask)
)
@@ -795,8 +915,11 @@ TRACE_EVENT(xfs_irec_merge_post,
__entry->agino = agino;
__entry->holemask = holemask;
),
- TP_printk("dev %d:%d agno %d inobt (%u:0x%x)", MAJOR(__entry->dev),
- MINOR(__entry->dev), __entry->agno, __entry->agino,
+ TP_printk("dev %d:%d agno 0x%x agino 0x%x holemask 0x%x",
+ MAJOR(__entry->dev),
+ MINOR(__entry->dev),
+ __entry->agno,
+ __entry->agino,
__entry->holemask)
)
@@ -1301,7 +1424,7 @@ DECLARE_EVENT_CLASS(xfs_file_class,
__entry->offset = iocb->ki_pos;
__entry->count = iov_iter_count(iter);
),
- TP_printk("dev %d:%d ino 0x%llx size 0x%llx offset 0x%llx count 0x%zx",
+ TP_printk("dev %d:%d ino 0x%llx disize 0x%llx pos 0x%llx bytecount 0x%zx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->size,
@@ -1348,14 +1471,14 @@ DECLARE_EVENT_CLASS(xfs_imap_class,
__entry->startblock = irec ? irec->br_startblock : 0;
__entry->blockcount = irec ? irec->br_blockcount : 0;
),
- TP_printk("dev %d:%d ino 0x%llx size 0x%llx offset 0x%llx count %zd "
- "fork %s startoff 0x%llx startblock %lld blockcount 0x%llx",
+ TP_printk("dev %d:%d ino 0x%llx disize 0x%llx pos 0x%llx bytecount 0x%zx "
+ "fork %s startoff 0x%llx startblock 0x%llx fsbcount 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->size,
__entry->offset,
__entry->count,
- __entry->whichfork == XFS_COW_FORK ? "cow" : "data",
+ __print_symbolic(__entry->whichfork, XFS_WHICHFORK_STRINGS),
__entry->startoff,
(int64_t)__entry->startblock,
__entry->blockcount)
@@ -1391,7 +1514,7 @@ DECLARE_EVENT_CLASS(xfs_simple_io_class,
__entry->count = count;
),
TP_printk("dev %d:%d ino 0x%llx isize 0x%llx disize 0x%llx "
- "offset 0x%llx count %zd",
+ "pos 0x%llx bytecount 0x%zx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->isize,
@@ -1427,7 +1550,7 @@ DECLARE_EVENT_CLASS(xfs_itrunc_class,
__entry->size = ip->i_disk_size;
__entry->new_size = new_size;
),
- TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx",
+ TP_printk("dev %d:%d ino 0x%llx disize 0x%llx new_size 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->size,
@@ -1458,7 +1581,7 @@ TRACE_EVENT(xfs_pagecache_inval,
__entry->start = start;
__entry->finish = finish;
),
- TP_printk("dev %d:%d ino 0x%llx size 0x%llx start 0x%llx finish 0x%llx",
+ TP_printk("dev %d:%d ino 0x%llx disize 0x%llx start 0x%llx finish 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->size,
@@ -1467,14 +1590,14 @@ TRACE_EVENT(xfs_pagecache_inval,
);
TRACE_EVENT(xfs_bunmap,
- TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len,
+ TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t fileoff, xfs_filblks_t len,
int flags, unsigned long caller_ip),
- TP_ARGS(ip, bno, len, flags, caller_ip),
+ TP_ARGS(ip, fileoff, len, flags, caller_ip),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_ino_t, ino)
__field(xfs_fsize_t, size)
- __field(xfs_fileoff_t, bno)
+ __field(xfs_fileoff_t, fileoff)
__field(xfs_filblks_t, len)
__field(unsigned long, caller_ip)
__field(int, flags)
@@ -1483,17 +1606,17 @@ TRACE_EVENT(xfs_bunmap,
__entry->dev = VFS_I(ip)->i_sb->s_dev;
__entry->ino = ip->i_ino;
__entry->size = ip->i_disk_size;
- __entry->bno = bno;
+ __entry->fileoff = fileoff;
__entry->len = len;
__entry->caller_ip = caller_ip;
__entry->flags = flags;
),
- TP_printk("dev %d:%d ino 0x%llx size 0x%llx bno 0x%llx len 0x%llx"
+ TP_printk("dev %d:%d ino 0x%llx disize 0x%llx fileoff 0x%llx fsbcount 0x%llx"
"flags %s caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->size,
- __entry->bno,
+ __entry->fileoff,
__entry->len,
__print_flags(__entry->flags, "|", XFS_BMAPI_FLAGS),
(void *)__entry->caller_ip)
@@ -1516,7 +1639,7 @@ DECLARE_EVENT_CLASS(xfs_extent_busy_class,
__entry->agbno = agbno;
__entry->len = len;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -1554,7 +1677,7 @@ TRACE_EVENT(xfs_extent_busy_trim,
__entry->tbno = tbno;
__entry->tlen = tlen;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u tbno %u tlen %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x found_agbno 0x%x found_fsbcount 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -1601,7 +1724,7 @@ DECLARE_EVENT_CLASS(xfs_agf_class,
__entry->longest = be32_to_cpu(agf->agf_longest);
__entry->caller_ip = caller_ip;
),
- TP_printk("dev %d:%d agno %u flags %s length %u roots b %u c %u "
+ TP_printk("dev %d:%d agno 0x%x flags %s length %u roots b %u c %u "
"levels b %u c %u flfirst %u fllast %u flcount %u "
"freeblks %u longest %u caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
@@ -1650,7 +1773,7 @@ TRACE_EVENT(xfs_free_extent,
__entry->haveleft = haveleft;
__entry->haveright = haveright;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u resv %d %s",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x resv %d %s",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -1707,7 +1830,7 @@ DECLARE_EVENT_CLASS(xfs_alloc_class,
__entry->datatype = args->datatype;
__entry->firstblock = args->tp->t_firstblock;
),
- TP_printk("dev %d:%d agno %u agbno %u minlen %u maxlen %u mod %u "
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x minlen %u maxlen %u mod %u "
"prod %u minleft %u total %u alignment %u minalignslop %u "
"len %u type %s otype %s wasdel %d wasfromfl %d resv %d "
"datatype 0x%x firstblock 0x%llx",
@@ -1785,7 +1908,7 @@ TRACE_EVENT(xfs_alloc_cur_check,
__entry->diff = diff;
__entry->new = new;
),
- TP_printk("dev %d:%d btree %s bno 0x%x len 0x%x diff 0x%x new %d",
+ TP_printk("dev %d:%d btree %s agbno 0x%x fsbcount 0x%x diff 0x%x new %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->bno, __entry->len, __entry->diff, __entry->new)
@@ -2060,7 +2183,7 @@ DECLARE_EVENT_CLASS(xfs_swap_extent_class,
__entry->fork_off = XFS_IFORK_BOFF(ip);
),
TP_printk("dev %d:%d ino 0x%llx (%s), %s format, num_extents %d, "
- "broot size %d, fork offset %d",
+ "broot size %d, forkoff 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__print_symbolic(__entry->which, XFS_SWAPEXT_INODES),
@@ -2186,7 +2309,7 @@ DECLARE_EVENT_CLASS(xfs_log_recover_buf_item_class,
__entry->size = buf_f->blf_size;
__entry->map_size = buf_f->blf_map_size;
),
- TP_printk("dev %d:%d blkno 0x%llx, len %u, flags 0x%x, size %d, "
+ TP_printk("dev %d:%d daddr 0x%llx, bbcount 0x%x, flags 0x%x, size %d, "
"map_size %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->blkno,
@@ -2237,7 +2360,7 @@ DECLARE_EVENT_CLASS(xfs_log_recover_ino_item_class,
__entry->boffset = in_f->ilf_boffset;
),
TP_printk("dev %d:%d ino 0x%llx, size %u, fields 0x%x, asize %d, "
- "dsize %d, blkno 0x%llx, len %d, boffset %d",
+ "dsize %d, daddr 0x%llx, bbcount 0x%x, boffset %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->size,
@@ -2278,10 +2401,14 @@ DECLARE_EVENT_CLASS(xfs_log_recover_icreate_item_class,
__entry->length = be32_to_cpu(in_f->icl_length);
__entry->gen = be32_to_cpu(in_f->icl_gen);
),
- TP_printk("dev %d:%d agno %u agbno %u count %u isize %u length %u "
- "gen %u", MAJOR(__entry->dev), MINOR(__entry->dev),
- __entry->agno, __entry->agbno, __entry->count, __entry->isize,
- __entry->length, __entry->gen)
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x ireccount %u isize %u gen 0x%x",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->agno,
+ __entry->agbno,
+ __entry->length,
+ __entry->count,
+ __entry->isize,
+ __entry->gen)
)
#define DEFINE_LOG_RECOVER_ICREATE_ITEM(name) \
DEFINE_EVENT(xfs_log_recover_icreate_item_class, name, \
@@ -2307,7 +2434,7 @@ DECLARE_EVENT_CLASS(xfs_discard_class,
__entry->agbno = agbno;
__entry->len = len;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -2350,7 +2477,7 @@ DECLARE_EVENT_CLASS(xfs_btree_cur_class,
__entry->level = level;
__entry->nlevels = cur->bc_nlevels;
__entry->ptr = cur->bc_ptrs[level];
- __entry->daddr = bp ? bp->b_bn : -1;
+ __entry->daddr = bp ? xfs_buf_daddr(bp) : -1;
),
TP_printk("dev %d:%d btree %s level %d/%d ptr %d daddr 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
@@ -2466,7 +2593,7 @@ DECLARE_EVENT_CLASS(xfs_phys_extent_deferred_class,
__entry->agbno = agbno;
__entry->len = len;
),
- TP_printk("dev %d:%d op %d agno %u agbno %u len %u",
+ TP_printk("dev %d:%d op %d agno 0x%x agbno 0x%x fsbcount 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type,
__entry->agno,
@@ -2513,13 +2640,13 @@ DECLARE_EVENT_CLASS(xfs_map_extent_deferred_class,
__entry->l_state = state;
__entry->op = op;
),
- TP_printk("dev %d:%d op %d agno %u agbno %u owner %lld %s offset %llu len %llu state %d",
+ TP_printk("dev %d:%d op %d agno 0x%x agbno 0x%x owner 0x%llx %s fileoff 0x%llx fsbcount 0x%llx state %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->op,
__entry->agno,
__entry->agbno,
__entry->ino,
- __entry->whichfork == XFS_ATTR_FORK ? "attr" : "data",
+ __print_symbolic(__entry->whichfork, XFS_WHICHFORK_STRINGS),
__entry->l_loff,
__entry->l_len,
__entry->l_state)
@@ -2583,7 +2710,7 @@ DECLARE_EVENT_CLASS(xfs_rmap_class,
if (unwritten)
__entry->flags |= XFS_RMAP_UNWRITTEN;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%lx",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x owner 0x%llx fileoff 0x%llx flags 0x%lx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -2616,7 +2743,7 @@ DECLARE_EVENT_CLASS(xfs_ag_error_class,
__entry->error = error;
__entry->caller_ip = caller_ip;
),
- TP_printk("dev %d:%d agno %u error %d caller %pS",
+ TP_printk("dev %d:%d agno 0x%x error %d caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->error,
@@ -2663,7 +2790,7 @@ DECLARE_EVENT_CLASS(xfs_rmapbt_class,
__entry->offset = offset;
__entry->flags = flags;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%x",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x owner 0x%llx fileoff 0x%llx flags 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -2732,7 +2859,7 @@ DECLARE_EVENT_CLASS(xfs_ag_resv_class,
__entry->asked = r ? r->ar_asked : 0;
__entry->len = len;
),
- TP_printk("dev %d:%d agno %u resv %d freeblks %u flcount %u "
+ TP_printk("dev %d:%d agno 0x%x resv %d freeblks %u flcount %u "
"resv %u ask %u len %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
@@ -2785,7 +2912,7 @@ DECLARE_EVENT_CLASS(xfs_ag_btree_lookup_class,
__entry->agbno = agbno;
__entry->dir = dir;
),
- TP_printk("dev %d:%d agno %u agbno %u cmp %s(%d)",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x cmp %s(%d)",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
@@ -2818,7 +2945,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_extent_class,
__entry->blockcount = irec->rc_blockcount;
__entry->refcount = irec->rc_refcount;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->startblock,
@@ -2853,7 +2980,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_extent_at_class,
__entry->refcount = irec->rc_refcount;
__entry->agbno = agbno;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u @ agbno %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u @ agbno 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->startblock,
@@ -2893,8 +3020,8 @@ DECLARE_EVENT_CLASS(xfs_refcount_double_extent_class,
__entry->i2_blockcount = i2->rc_blockcount;
__entry->i2_refcount = i2->rc_refcount;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- "
- "agbno %u len %u refcount %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u -- "
+ "agbno 0x%x fsbcount 0x%x refcount %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->i1_startblock,
@@ -2939,8 +3066,8 @@ DECLARE_EVENT_CLASS(xfs_refcount_double_extent_at_class,
__entry->i2_refcount = i2->rc_refcount;
__entry->agbno = agbno;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- "
- "agbno %u len %u refcount %u @ agbno %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u -- "
+ "agbno 0x%x fsbcount 0x%x refcount %u @ agbno 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->i1_startblock,
@@ -2991,9 +3118,9 @@ DECLARE_EVENT_CLASS(xfs_refcount_triple_extent_class,
__entry->i3_blockcount = i3->rc_blockcount;
__entry->i3_refcount = i3->rc_refcount;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- "
- "agbno %u len %u refcount %u -- "
- "agbno %u len %u refcount %u",
+ TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u -- "
+ "agbno 0x%x fsbcount 0x%x refcount %u -- "
+ "agbno 0x%x fsbcount 0x%x refcount %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->i1_startblock,
@@ -3080,7 +3207,7 @@ TRACE_EVENT(xfs_refcount_finish_one_leftover,
__entry->new_agbno = new_agbno;
__entry->new_len = new_len;
),
- TP_printk("dev %d:%d type %d agno %u agbno %u len %u new_agbno %u new_len %u",
+ TP_printk("dev %d:%d type %d agno 0x%x agbno 0x%x fsbcount 0x%x new_agbno 0x%x new_fsbcount 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type,
__entry->agno,
@@ -3106,7 +3233,7 @@ DECLARE_EVENT_CLASS(xfs_inode_error_class,
__entry->error = error;
__entry->caller_ip = caller_ip;
),
- TP_printk("dev %d:%d ino %llx error %d caller %pS",
+ TP_printk("dev %d:%d ino 0x%llx error %d caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->error,
@@ -3132,7 +3259,7 @@ DECLARE_EVENT_CLASS(xfs_double_io_class,
__field(loff_t, src_isize)
__field(loff_t, src_disize)
__field(loff_t, src_offset)
- __field(size_t, len)
+ __field(long long, len)
__field(xfs_ino_t, dest_ino)
__field(loff_t, dest_isize)
__field(loff_t, dest_disize)
@@ -3150,9 +3277,9 @@ DECLARE_EVENT_CLASS(xfs_double_io_class,
__entry->dest_disize = dest->i_disk_size;
__entry->dest_offset = doffset;
),
- TP_printk("dev %d:%d count %zd "
- "ino 0x%llx isize 0x%llx disize 0x%llx offset 0x%llx -> "
- "ino 0x%llx isize 0x%llx disize 0x%llx offset 0x%llx",
+ TP_printk("dev %d:%d bytecount 0x%llx "
+ "ino 0x%llx isize 0x%llx disize 0x%llx pos 0x%llx -> "
+ "ino 0x%llx isize 0x%llx disize 0x%llx pos 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->len,
__entry->src_ino,
@@ -3191,7 +3318,7 @@ DECLARE_EVENT_CLASS(xfs_inode_irec_class,
__entry->pblk = irec->br_startblock;
__entry->state = irec->br_state;
),
- TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx len 0x%x pblk %llu st %d",
+ TP_printk("dev %d:%d ino 0x%llx fileoff 0x%llx fsbcount 0x%x startblock 0x%llx st %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->lblk,
@@ -3231,9 +3358,8 @@ TRACE_EVENT(xfs_reflink_remap_blocks,
__entry->dest_ino = dest->i_ino;
__entry->dest_lblk = doffset;
),
- TP_printk("dev %d:%d len 0x%llx "
- "ino 0x%llx offset 0x%llx blocks -> "
- "ino 0x%llx offset 0x%llx blocks",
+ TP_printk("dev %d:%d fsbcount 0x%llx "
+ "ino 0x%llx fileoff 0x%llx -> ino 0x%llx fileoff 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->len,
__entry->src_ino,
@@ -3272,9 +3398,7 @@ TRACE_EVENT(xfs_ioctl_clone,
__entry->dest_ino = dest->i_ino;
__entry->dest_isize = i_size_read(dest);
),
- TP_printk("dev %d:%d "
- "ino 0x%lx isize 0x%llx -> "
- "ino 0x%lx isize 0x%llx",
+ TP_printk("dev %d:%d ino 0x%lx isize 0x%llx -> ino 0x%lx isize 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->src_ino,
__entry->src_isize,
@@ -3310,7 +3434,7 @@ DEFINE_INODE_ERROR_EVENT(xfs_swap_extent_rmap_error);
/* fsmap traces */
DECLARE_EVENT_CLASS(xfs_fsmap_class,
TP_PROTO(struct xfs_mount *mp, u32 keydev, xfs_agnumber_t agno,
- struct xfs_rmap_irec *rmap),
+ const struct xfs_rmap_irec *rmap),
TP_ARGS(mp, keydev, agno, rmap),
TP_STRUCT__entry(
__field(dev_t, dev)
@@ -3332,7 +3456,7 @@ DECLARE_EVENT_CLASS(xfs_fsmap_class,
__entry->offset = rmap->rm_offset;
__entry->flags = rmap->rm_flags;
),
- TP_printk("dev %d:%d keydev %d:%d agno %u bno %llu len %llu owner %lld offset %llu flags 0x%x",
+ TP_printk("dev %d:%d keydev %d:%d agno 0x%x startblock 0x%llx fsbcount 0x%llx owner 0x%llx fileoff 0x%llx flags 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
MAJOR(__entry->keydev), MINOR(__entry->keydev),
__entry->agno,
@@ -3345,7 +3469,7 @@ DECLARE_EVENT_CLASS(xfs_fsmap_class,
#define DEFINE_FSMAP_EVENT(name) \
DEFINE_EVENT(xfs_fsmap_class, name, \
TP_PROTO(struct xfs_mount *mp, u32 keydev, xfs_agnumber_t agno, \
- struct xfs_rmap_irec *rmap), \
+ const struct xfs_rmap_irec *rmap), \
TP_ARGS(mp, keydev, agno, rmap))
DEFINE_FSMAP_EVENT(xfs_fsmap_low_key);
DEFINE_FSMAP_EVENT(xfs_fsmap_high_key);
@@ -3372,7 +3496,7 @@ DECLARE_EVENT_CLASS(xfs_getfsmap_class,
__entry->offset = fsmap->fmr_offset;
__entry->flags = fsmap->fmr_flags;
),
- TP_printk("dev %d:%d keydev %d:%d block %llu len %llu owner %lld offset %llu flags 0x%llx",
+ TP_printk("dev %d:%d keydev %d:%d daddr 0x%llx bbcount 0x%llx owner 0x%llx fileoff_daddr 0x%llx flags 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
MAJOR(__entry->keydev), MINOR(__entry->keydev),
__entry->block,
@@ -3471,7 +3595,7 @@ TRACE_EVENT(xfs_iunlink_update_bucket,
__entry->old_ptr = old_ptr;
__entry->new_ptr = new_ptr;
),
- TP_printk("dev %d:%d agno %u bucket %u old 0x%x new 0x%x",
+ TP_printk("dev %d:%d agno 0x%x bucket %u old 0x%x new 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->bucket,
@@ -3497,7 +3621,7 @@ TRACE_EVENT(xfs_iunlink_update_dinode,
__entry->old_ptr = old_ptr;
__entry->new_ptr = new_ptr;
),
- TP_printk("dev %d:%d agno %u agino 0x%x old 0x%x new 0x%x",
+ TP_printk("dev %d:%d agno 0x%x agino 0x%x old 0x%x new 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agino,
@@ -3518,7 +3642,7 @@ DECLARE_EVENT_CLASS(xfs_ag_inode_class,
__entry->agno = XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino);
__entry->agino = XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino);
),
- TP_printk("dev %d:%d agno %u agino %u",
+ TP_printk("dev %d:%d agno 0x%x agino 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno, __entry->agino)
)
@@ -3570,7 +3694,7 @@ DECLARE_EVENT_CLASS(xfs_ag_corrupt_class,
__entry->agno = agno;
__entry->flags = flags;
),
- TP_printk("dev %d:%d agno %u flags 0x%x",
+ TP_printk("dev %d:%d agno 0x%x flags 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno, __entry->flags)
);
@@ -3621,7 +3745,7 @@ TRACE_EVENT(xfs_iwalk_ag,
__entry->agno = agno;
__entry->startino = startino;
),
- TP_printk("dev %d:%d agno %d startino %u",
+ TP_printk("dev %d:%d agno 0x%x startino 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev), __entry->agno,
__entry->startino)
)
@@ -3642,7 +3766,7 @@ TRACE_EVENT(xfs_iwalk_ag_rec,
__entry->startino = irec->ir_startino;
__entry->freemask = irec->ir_free;
),
- TP_printk("dev %d:%d agno %d startino %u freemask 0x%llx",
+ TP_printk("dev %d:%d agno 0x%x startino 0x%x freemask 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev), __entry->agno,
__entry->startino, __entry->freemask)
)
@@ -3689,8 +3813,6 @@ DEFINE_EVENT(xfs_kmem_class, name, \
TP_PROTO(ssize_t size, int flags, unsigned long caller_ip), \
TP_ARGS(size, flags, caller_ip))
DEFINE_KMEM_EVENT(kmem_alloc);
-DEFINE_KMEM_EVENT(kmem_alloc_io);
-DEFINE_KMEM_EVENT(kmem_alloc_large);
TRACE_EVENT(xfs_check_new_dalign,
TP_PROTO(struct xfs_mount *mp, int new_dalign, xfs_ino_t calc_rootino),
@@ -3707,7 +3829,7 @@ TRACE_EVENT(xfs_check_new_dalign,
__entry->sb_rootino = mp->m_sb.sb_rootino;
__entry->calc_rootino = calc_rootino;
),
- TP_printk("dev %d:%d new_dalign %d sb_rootino %llu calc_rootino %llu",
+ TP_printk("dev %d:%d new_dalign %d sb_rootino 0x%llx calc_rootino 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->new_dalign, __entry->sb_rootino,
__entry->calc_rootino)
@@ -3732,7 +3854,7 @@ TRACE_EVENT(xfs_btree_commit_afakeroot,
__entry->levels = cur->bc_ag.afake->af_levels;
__entry->blocks = cur->bc_ag.afake->af_blocks;
),
- TP_printk("dev %d:%d btree %s ag %u levels %u blocks %u root %u",
+ TP_printk("dev %d:%d btree %s agno 0x%x levels %u blocks %u root %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->agno,
@@ -3764,12 +3886,12 @@ TRACE_EVENT(xfs_btree_commit_ifakeroot,
__entry->blocks = cur->bc_ino.ifake->if_blocks;
__entry->whichfork = cur->bc_ino.whichfork;
),
- TP_printk("dev %d:%d btree %s ag %u agino %u whichfork %s levels %u blocks %u",
+ TP_printk("dev %d:%d btree %s agno 0x%x agino 0x%x whichfork %s levels %u blocks %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->agno,
__entry->agino,
- __entry->whichfork == XFS_ATTR_FORK ? "attr" : "data",
+ __print_symbolic(__entry->whichfork, XFS_WHICHFORK_STRINGS),
__entry->levels,
__entry->blocks)
)
@@ -3847,7 +3969,7 @@ TRACE_EVENT(xfs_btree_bload_block,
}
__entry->nr_records = nr_records;
),
- TP_printk("dev %d:%d btree %s level %u block %llu/%llu fsb (%u/%u) recs %u",
+ TP_printk("dev %d:%d btree %s level %u block %llu/%llu agno 0x%x agbno 0x%x recs %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->level,
@@ -3934,7 +4056,6 @@ TRACE_DEFINE_ENUM(XLOG_STATE_SYNCING);
TRACE_DEFINE_ENUM(XLOG_STATE_DONE_SYNC);
TRACE_DEFINE_ENUM(XLOG_STATE_CALLBACK);
TRACE_DEFINE_ENUM(XLOG_STATE_DIRTY);
-TRACE_DEFINE_ENUM(XLOG_STATE_IOERROR);
DECLARE_EVENT_CLASS(xlog_iclog_class,
TP_PROTO(struct xlog_in_core *iclog, unsigned long caller_ip),
@@ -3990,6 +4111,57 @@ DEFINE_ICLOG_EVENT(xlog_iclog_want_sync);
DEFINE_ICLOG_EVENT(xlog_iclog_wait_on);
DEFINE_ICLOG_EVENT(xlog_iclog_write);
+DECLARE_EVENT_CLASS(xfs_das_state_class,
+ TP_PROTO(int das, struct xfs_inode *ip),
+ TP_ARGS(das, ip),
+ TP_STRUCT__entry(
+ __field(int, das)
+ __field(xfs_ino_t, ino)
+ ),
+ TP_fast_assign(
+ __entry->das = das;
+ __entry->ino = ip->i_ino;
+ ),
+ TP_printk("state change %d ino 0x%llx",
+ __entry->das, __entry->ino)
+)
+
+#define DEFINE_DAS_STATE_EVENT(name) \
+DEFINE_EVENT(xfs_das_state_class, name, \
+ TP_PROTO(int das, struct xfs_inode *ip), \
+ TP_ARGS(das, ip))
+DEFINE_DAS_STATE_EVENT(xfs_attr_sf_addname_return);
+DEFINE_DAS_STATE_EVENT(xfs_attr_set_iter_return);
+DEFINE_DAS_STATE_EVENT(xfs_attr_node_addname_return);
+DEFINE_DAS_STATE_EVENT(xfs_attr_remove_iter_return);
+DEFINE_DAS_STATE_EVENT(xfs_attr_rmtval_remove_return);
+
+TRACE_EVENT(xfs_force_shutdown,
+ TP_PROTO(struct xfs_mount *mp, int ptag, int flags, const char *fname,
+ int line_num),
+ TP_ARGS(mp, ptag, flags, fname, line_num),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(int, ptag)
+ __field(int, flags)
+ __string(fname, fname)
+ __field(int, line_num)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->ptag = ptag;
+ __entry->flags = flags;
+ __assign_str(fname, fname);
+ __entry->line_num = line_num;
+ ),
+ TP_printk("dev %d:%d tag %s flags %s file %s line_num %d",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __print_flags(__entry->ptag, "|", XFS_PTAG_STRINGS),
+ __print_flags(__entry->flags, "|", XFS_SHUTDOWN_STRINGS),
+ __get_str(fname),
+ __entry->line_num)
+);
+
#endif /* _TRACE_XFS_H */
#undef TRACE_INCLUDE_PATH
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 87bffd12c20c..67dec11e34c7 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -9,7 +9,6 @@
#include "xfs_shared.h"
#include "xfs_format.h"
#include "xfs_log_format.h"
-#include "xfs_log_priv.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
#include "xfs_extent_busy.h"
@@ -17,6 +16,7 @@
#include "xfs_trans.h"
#include "xfs_trans_priv.h"
#include "xfs_log.h"
+#include "xfs_log_priv.h"
#include "xfs_trace.h"
#include "xfs_error.h"
#include "xfs_defer.h"
@@ -275,7 +275,7 @@ retry:
WARN_ON(resp->tr_logres > 0 &&
mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) ||
- xfs_sb_version_haslazysbcount(&mp->m_sb));
+ xfs_has_lazysbcount(mp));
tp->t_magic = XFS_TRANS_HEADER_MAGIC;
tp->t_flags = flags;
@@ -295,10 +295,7 @@ retry:
* Do not perform a synchronous scan because callers can hold
* other locks.
*/
- error = xfs_blockgc_free_space(mp, NULL);
- if (error)
- return error;
-
+ xfs_blockgc_flush_all(mp);
want_retry = false;
goto retry;
}
@@ -367,12 +364,12 @@ xfs_trans_mod_sb(
switch (field) {
case XFS_TRANS_SB_ICOUNT:
tp->t_icount_delta += delta;
- if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ if (xfs_has_lazysbcount(mp))
flags &= ~XFS_TRANS_SB_DIRTY;
break;
case XFS_TRANS_SB_IFREE:
tp->t_ifree_delta += delta;
- if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ if (xfs_has_lazysbcount(mp))
flags &= ~XFS_TRANS_SB_DIRTY;
break;
case XFS_TRANS_SB_FDBLOCKS:
@@ -401,7 +398,7 @@ xfs_trans_mod_sb(
delta -= blkres_delta;
}
tp->t_fdblocks_delta += delta;
- if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ if (xfs_has_lazysbcount(mp))
flags &= ~XFS_TRANS_SB_DIRTY;
break;
case XFS_TRANS_SB_RES_FDBLOCKS:
@@ -411,7 +408,7 @@ xfs_trans_mod_sb(
* be applied to the on-disk superblock.
*/
tp->t_res_fdblocks_delta += delta;
- if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ if (xfs_has_lazysbcount(mp))
flags &= ~XFS_TRANS_SB_DIRTY;
break;
case XFS_TRANS_SB_FREXTENTS:
@@ -490,7 +487,7 @@ xfs_trans_apply_sb_deltas(
/*
* Only update the superblock counters if we are logging them
*/
- if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
+ if (!xfs_has_lazysbcount((tp->t_mountp))) {
if (tp->t_icount_delta)
be64_add_cpu(&sbp->sb_icount, tp->t_icount_delta);
if (tp->t_ifree_delta)
@@ -588,7 +585,7 @@ xfs_trans_unreserve_and_mod_sb(
if (tp->t_blk_res > 0)
blkdelta = tp->t_blk_res;
if ((tp->t_fdblocks_delta != 0) &&
- (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
+ (xfs_has_lazysbcount(mp) ||
(tp->t_flags & XFS_TRANS_SB_DIRTY)))
blkdelta += tp->t_fdblocks_delta;
@@ -598,7 +595,7 @@ xfs_trans_unreserve_and_mod_sb(
(tp->t_flags & XFS_TRANS_SB_DIRTY))
rtxdelta += tp->t_frextents_delta;
- if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
+ if (xfs_has_lazysbcount(mp) ||
(tp->t_flags & XFS_TRANS_SB_DIRTY)) {
idelta = tp->t_icount_delta;
ifreedelta = tp->t_ifree_delta;
@@ -778,7 +775,7 @@ xfs_trans_committed_bulk(
* object into the AIL as we are in a shutdown situation.
*/
if (aborted) {
- ASSERT(XFS_FORCED_SHUTDOWN(ailp->ail_mount));
+ ASSERT(xfs_is_shutdown(ailp->ail_mount));
if (lip->li_ops->iop_unpin)
lip->li_ops->iop_unpin(lip, 1);
continue;
@@ -867,7 +864,7 @@ __xfs_trans_commit(
if (!(tp->t_flags & XFS_TRANS_DIRTY))
goto out_unreserve;
- if (XFS_FORCED_SHUTDOWN(mp)) {
+ if (xfs_is_shutdown(mp)) {
error = -EIO;
goto out_unreserve;
}
@@ -908,7 +905,7 @@ out_unreserve:
*/
xfs_trans_unreserve_and_mod_dquots(tp);
if (tp->t_ticket) {
- if (regrant && !XLOG_FORCED_SHUTDOWN(mp->m_log))
+ if (regrant && !xlog_is_shutdown(mp->m_log))
xfs_log_ticket_regrant(mp->m_log, tp->t_ticket);
else
xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
@@ -953,12 +950,12 @@ xfs_trans_cancel(
* filesystem. This happens in paths where we detect
* corruption and decide to give up.
*/
- if (dirty && !XFS_FORCED_SHUTDOWN(mp)) {
+ if (dirty && !xfs_is_shutdown(mp)) {
XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
}
#ifdef DEBUG
- if (!dirty && !XFS_FORCED_SHUTDOWN(mp)) {
+ if (!dirty && !xfs_is_shutdown(mp)) {
struct xfs_log_item *lip;
list_for_each_entry(lip, &tp->t_items, li_trans)
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index dbb69b4bf3ed..2a8c8dc54c95 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -17,6 +17,7 @@
#include "xfs_errortag.h"
#include "xfs_error.h"
#include "xfs_log.h"
+#include "xfs_log_priv.h"
#ifdef DEBUG
/*
@@ -429,8 +430,12 @@ xfsaild_push(
/*
* If we encountered pinned items or did not finish writing out all
- * buffers the last time we ran, force the log first and wait for it
- * before pushing again.
+ * buffers the last time we ran, force a background CIL push to get the
+ * items unpinned in the near future. We do not wait on the CIL push as
+ * that could stall us for seconds if there is enough background IO
+ * load. Stalling for that long when the tail of the log is pinned and
+ * needs flushing will hard stop the transaction subsystem when log
+ * space runs out.
*/
if (ailp->ail_log_flush && ailp->ail_last_pushed_lsn == 0 &&
(!list_empty_careful(&ailp->ail_buf_list) ||
@@ -438,7 +443,7 @@ xfsaild_push(
ailp->ail_log_flush = 0;
XFS_STATS_INC(mp, xs_push_ail_flush);
- xfs_log_force(mp, XFS_LOG_SYNC);
+ xlog_cil_flush(mp->m_log);
}
spin_lock(&ailp->ail_lock);
@@ -615,7 +620,7 @@ xfsaild(
* opportunity to release such buffers from the queue.
*/
ASSERT(list_empty(&ailp->ail_buf_list) ||
- XFS_FORCED_SHUTDOWN(ailp->ail_mount));
+ xfs_is_shutdown(ailp->ail_mount));
xfs_buf_delwri_cancel(&ailp->ail_buf_list);
break;
}
@@ -678,7 +683,7 @@ xfs_ail_push(
struct xfs_log_item *lip;
lip = xfs_ail_min(ailp);
- if (!lip || XFS_FORCED_SHUTDOWN(ailp->ail_mount) ||
+ if (!lip || xfs_is_shutdown(ailp->ail_mount) ||
XFS_LSN_CMP(threshold_lsn, ailp->ail_target) <= 0)
return;
@@ -743,7 +748,7 @@ xfs_ail_update_finish(
return;
}
- if (!XFS_FORCED_SHUTDOWN(mp))
+ if (!xfs_is_shutdown(mp))
xlog_assign_tail_lsn_locked(mp);
if (list_empty(&ailp->ail_head))
@@ -863,7 +868,7 @@ xfs_trans_ail_delete(
spin_lock(&ailp->ail_lock);
if (!test_bit(XFS_LI_IN_AIL, &lip->li_flags)) {
spin_unlock(&ailp->ail_lock);
- if (shutdown_type && !XFS_FORCED_SHUTDOWN(mp)) {
+ if (shutdown_type && !xfs_is_shutdown(mp)) {
xfs_alert_tag(mp, XFS_PTAG_AILDELETE,
"%s: attempting to delete a log item that is not in the AIL",
__func__);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index d11d032da0b4..6549e50d852c 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -38,7 +38,7 @@ xfs_trans_buf_item_match(
blip = (struct xfs_buf_log_item *)lip;
if (blip->bli_item.li_type == XFS_LI_BUF &&
blip->bli_buf->b_target == target &&
- XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn &&
+ xfs_buf_daddr(blip->bli_buf) == map[0].bm_bn &&
blip->bli_buf->b_length == len) {
ASSERT(blip->bli_buf->b_map_count == nmaps);
return blip->bli_buf;
@@ -138,7 +138,7 @@ xfs_trans_get_buf_map(
bp = xfs_trans_buf_item_match(tp, target, map, nmaps);
if (bp != NULL) {
ASSERT(xfs_buf_islocked(bp));
- if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) {
+ if (xfs_is_shutdown(tp->t_mountp)) {
xfs_buf_stale(bp);
bp->b_flags |= XBF_DONE;
}
@@ -244,7 +244,7 @@ xfs_trans_read_buf_map(
* We never locked this buf ourselves, so we shouldn't
* brelse it either. Just get out.
*/
- if (XFS_FORCED_SHUTDOWN(mp)) {
+ if (xfs_is_shutdown(mp)) {
trace_xfs_trans_read_buf_shut(bp, _RET_IP_);
return -EIO;
}
@@ -300,7 +300,7 @@ xfs_trans_read_buf_map(
return error;
}
- if (XFS_FORCED_SHUTDOWN(mp)) {
+ if (xfs_is_shutdown(mp)) {
xfs_buf_relse(bp);
trace_xfs_trans_read_buf_shut(bp, _RET_IP_);
return -EIO;
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 48e09ea30ee5..3872ce671411 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -58,7 +58,7 @@ xfs_trans_log_dquot(
/* Upgrade the dquot to bigtime format if possible. */
if (dqp->q_id != 0 &&
- xfs_sb_version_hasbigtime(&tp->t_mountp->m_sb) &&
+ xfs_has_bigtime(tp->t_mountp) &&
!(dqp->q_type & XFS_DQTYPE_BIGTIME))
dqp->q_type |= XFS_DQTYPE_BIGTIME;
@@ -132,8 +132,7 @@ xfs_trans_mod_dquot_byino(
{
xfs_mount_t *mp = tp->t_mountp;
- if (!XFS_IS_QUOTA_RUNNING(mp) ||
- !XFS_IS_QUOTA_ON(mp) ||
+ if (!XFS_IS_QUOTA_ON(mp) ||
xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
return;
@@ -192,7 +191,7 @@ xfs_trans_mod_dquot(
struct xfs_dqtrx *qtrx;
ASSERT(tp);
- ASSERT(XFS_IS_QUOTA_RUNNING(tp->t_mountp));
+ ASSERT(XFS_IS_QUOTA_ON(tp->t_mountp));
qtrx = NULL;
if (!delta)
@@ -738,7 +737,7 @@ xfs_trans_reserve_quota_bydquots(
{
int error;
- if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return 0;
ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
@@ -795,7 +794,7 @@ xfs_trans_reserve_quota_nblks(
unsigned int qflags = 0;
int error;
- if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return 0;
ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
@@ -836,51 +835,13 @@ xfs_trans_reserve_quota_icreate(
{
struct xfs_mount *mp = tp->t_mountp;
- if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+ if (!XFS_IS_QUOTA_ON(mp))
return 0;
return xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp, pdqp,
dblocks, 1, XFS_QMOPT_RES_REGBLKS);
}
-/*
- * This routine is called to allocate a quotaoff log item.
- */
-struct xfs_qoff_logitem *
-xfs_trans_get_qoff_item(
- struct xfs_trans *tp,
- struct xfs_qoff_logitem *startqoff,
- uint flags)
-{
- struct xfs_qoff_logitem *q;
-
- ASSERT(tp != NULL);
-
- q = xfs_qm_qoff_logitem_init(tp->t_mountp, startqoff, flags);
- ASSERT(q != NULL);
-
- /*
- * Get a log_item_desc to point at the new item.
- */
- xfs_trans_add_item(tp, &q->qql_item);
- return q;
-}
-
-
-/*
- * This is called to mark the quotaoff logitem as needing
- * to be logged when the transaction is committed. The logitem must
- * already be associated with the given transaction.
- */
-void
-xfs_trans_log_quotaoff_item(
- struct xfs_trans *tp,
- struct xfs_qoff_logitem *qlp)
-{
- tp->t_flags |= XFS_TRANS_DIRTY;
- set_bit(XFS_LI_DIRTY, &qlp->qql_item.li_flags);
-}
-
STATIC void
xfs_trans_alloc_dqinfo(
xfs_trans_t *tp)
diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h
index f6656be81760..fb172a03a753 100644
--- a/include/acpi/platform/acgcc.h
+++ b/include/acpi/platform/acgcc.h
@@ -22,7 +22,7 @@ typedef __builtin_va_list va_list;
#define va_arg(v, l) __builtin_va_arg(v, l)
#define va_copy(d, s) __builtin_va_copy(d, s)
#else
-#include <stdarg.h>
+#include <linux/stdarg.h>
#endif
#endif
diff --git a/include/asm-generic/bitops/builtin-ffs.h b/include/asm-generic/bitops/builtin-ffs.h
index 1dacfdb4247e..7b129329046b 100644
--- a/include/asm-generic/bitops/builtin-ffs.h
+++ b/include/asm-generic/bitops/builtin-ffs.h
@@ -8,7 +8,7 @@
*
* This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
+ * differs in spirit from ffz (man ffs).
*/
#define ffs(x) __builtin_ffs(x)
diff --git a/include/asm-generic/bitops/ffs.h b/include/asm-generic/bitops/ffs.h
index e81868b2c0f0..323fd5d6ae26 100644
--- a/include/asm-generic/bitops/ffs.h
+++ b/include/asm-generic/bitops/ffs.h
@@ -8,7 +8,7 @@
*
* This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
+ * differs in spirit from ffz (man ffs).
*/
static inline int ffs(int x)
{
diff --git a/include/asm-generic/bitops/non-atomic.h b/include/asm-generic/bitops/non-atomic.h
index 365377fb104b..078cc68be2f1 100644
--- a/include/asm-generic/bitops/non-atomic.h
+++ b/include/asm-generic/bitops/non-atomic.h
@@ -14,7 +14,7 @@
* may be that only one operation succeeds.
*/
static __always_inline void
-arch___set_bit(int nr, volatile unsigned long *addr)
+arch___set_bit(unsigned int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
@@ -24,7 +24,7 @@ arch___set_bit(int nr, volatile unsigned long *addr)
#define __set_bit arch___set_bit
static __always_inline void
-arch___clear_bit(int nr, volatile unsigned long *addr)
+arch___clear_bit(unsigned int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
@@ -43,7 +43,7 @@ arch___clear_bit(int nr, volatile unsigned long *addr)
* may be that only one operation succeeds.
*/
static __always_inline
-void arch___change_bit(int nr, volatile unsigned long *addr)
+void arch___change_bit(unsigned int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
@@ -62,7 +62,7 @@ void arch___change_bit(int nr, volatile unsigned long *addr)
* but actually fail. You must protect multiple accesses with a lock.
*/
static __always_inline int
-arch___test_and_set_bit(int nr, volatile unsigned long *addr)
+arch___test_and_set_bit(unsigned int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
@@ -83,7 +83,7 @@ arch___test_and_set_bit(int nr, volatile unsigned long *addr)
* but actually fail. You must protect multiple accesses with a lock.
*/
static __always_inline int
-arch___test_and_clear_bit(int nr, volatile unsigned long *addr)
+arch___test_and_clear_bit(unsigned int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
@@ -96,7 +96,7 @@ arch___test_and_clear_bit(int nr, volatile unsigned long *addr)
/* WARNING: non atomic and it can be reordered! */
static __always_inline int
-arch___test_and_change_bit(int nr, volatile unsigned long *addr)
+arch___test_and_change_bit(unsigned int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
@@ -113,7 +113,7 @@ arch___test_and_change_bit(int nr, volatile unsigned long *addr)
* @addr: Address to start counting from
*/
static __always_inline int
-arch_test_bit(int nr, const volatile unsigned long *addr)
+arch_test_bit(unsigned int nr, const volatile unsigned long *addr)
{
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
}
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index 9a000ba2bb75..c1ab6a6e72b5 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -22,6 +22,7 @@
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/cpumask.h>
+#include <linux/nmi.h>
#include <asm/ptrace.h>
#include <asm/hyperv-tlfs.h>
@@ -38,6 +39,9 @@ struct ms_hyperv_info {
};
extern struct ms_hyperv_info ms_hyperv;
+extern void __percpu **hyperv_pcpu_input_arg;
+extern void __percpu **hyperv_pcpu_output_arg;
+
extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);
@@ -151,6 +155,8 @@ void hv_remove_crash_handler(void);
extern int vmbus_interrupt;
extern int vmbus_irq;
+extern bool hv_root_partition;
+
#if IS_ENABLED(CONFIG_HYPERV)
/*
* Hypervisor's notion of virtual processor ID is different from
@@ -161,9 +167,16 @@ extern int vmbus_irq;
extern u32 *hv_vp_index;
extern u32 hv_max_vp_index;
+extern u64 (*hv_read_reference_counter)(void);
+
/* Sentinel value for an uninitialized entry in hv_vp_index array */
#define VP_INVAL U32_MAX
+int __init hv_common_init(void);
+void __init hv_common_free(void);
+int hv_common_cpu_init(unsigned int cpu);
+int hv_common_cpu_die(unsigned int cpu);
+
void *hv_alloc_hyperv_page(void);
void *hv_alloc_hyperv_zeroed_page(void);
void hv_free_hyperv_page(unsigned long addr);
diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
index a0b2f270dddc..10ffa8b5c117 100644
--- a/include/asm-generic/uaccess.h
+++ b/include/asm-generic/uaccess.h
@@ -119,6 +119,11 @@ static inline void set_fs(mm_segment_t fs)
#ifndef uaccess_kernel
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
#endif
+
+#ifndef user_addr_max
+#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
+#endif
+
#endif /* CONFIG_SET_FS */
#define access_ok(addr, size) __access_ok((unsigned long)(addr),(size))
@@ -244,50 +249,6 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
extern int __get_user_bad(void) __attribute__((noreturn));
/*
- * Copy a null terminated string from userspace.
- */
-#ifndef __strncpy_from_user
-static inline long
-__strncpy_from_user(char *dst, const char __user *src, long count)
-{
- char *tmp;
- strncpy(dst, (const char __force *)src, count);
- for (tmp = dst; *tmp && count > 0; tmp++, count--)
- ;
- return (tmp - dst);
-}
-#endif
-
-static inline long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
- if (!access_ok(src, 1))
- return -EFAULT;
- return __strncpy_from_user(dst, src, count);
-}
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 on exception, a value greater than N if too long
- */
-#ifndef __strnlen_user
-#define __strnlen_user(s, n) (strnlen((s), (n)) + 1)
-#endif
-
-/*
- * Unlike strnlen, strnlen_user includes the nul terminator in
- * its returned count. Callers should check for a returned value
- * greater than N as an indication the string is too long.
- */
-static inline long strnlen_user(const char __user *src, long n)
-{
- if (!access_ok(src, 1))
- return 0;
- return __strnlen_user(src, n);
-}
-
-/*
* Zero Userspace
*/
#ifndef __clear_user
@@ -311,4 +272,8 @@ clear_user(void __user *to, unsigned long n)
#include <asm/extable.h>
+__must_check long strncpy_from_user(char *dst, const char __user *src,
+ long count);
+__must_check long strnlen_user(const char __user *src, long n);
+
#endif /* __ASM_GENERIC_UACCESS_H */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 62669b36a772..aa50bf2959fe 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -483,6 +483,8 @@
\
TRACEDATA \
\
+ PRINTK_INDEX \
+ \
/* Kernel symbol table: Normal symbols */ \
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
__start___ksymtab = .; \
@@ -894,6 +896,17 @@
#define TRACEDATA
#endif
+#ifdef CONFIG_PRINTK_INDEX
+#define PRINTK_INDEX \
+ .printk_index : AT(ADDR(.printk_index) - LOAD_OFFSET) { \
+ __start_printk_index = .; \
+ *(.printk_index) \
+ __stop_printk_index = .; \
+ }
+#else
+#define PRINTK_INDEX
+#endif
+
#define NOTES \
.notes : AT(ADDR(.notes) - LOAD_OFFSET) { \
__start_notes = .; \
diff --git a/include/clocksource/hyperv_timer.h b/include/clocksource/hyperv_timer.h
index b6774aa5a4b8..b3f5d73ae1d6 100644
--- a/include/clocksource/hyperv_timer.h
+++ b/include/clocksource/hyperv_timer.h
@@ -20,6 +20,8 @@
#define HV_MAX_MAX_DELTA_TICKS 0xffffffff
#define HV_MIN_DELTA_TICKS 1
+#ifdef CONFIG_HYPERV_TIMER
+
/* Routines called by the VMbus driver */
extern int hv_stimer_alloc(bool have_percpu_irqs);
extern int hv_stimer_cleanup(unsigned int cpu);
@@ -28,8 +30,6 @@ extern void hv_stimer_legacy_cleanup(unsigned int cpu);
extern void hv_stimer_global_cleanup(void);
extern void hv_stimer0_isr(void);
-#ifdef CONFIG_HYPERV_TIMER
-extern u64 (*hv_read_reference_counter)(void);
extern void hv_init_clocksource(void);
extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void);
@@ -100,6 +100,13 @@ static inline u64 hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg,
{
return U64_MAX;
}
+
+static inline int hv_stimer_cleanup(unsigned int cpu) { return 0; }
+static inline void hv_stimer_legacy_init(unsigned int cpu, int sint) {}
+static inline void hv_stimer_legacy_cleanup(unsigned int cpu) {}
+static inline void hv_stimer_global_cleanup(void) {}
+static inline void hv_stimer0_isr(void) {}
+
#endif /* CONFIG_HYPERV_TIMER */
#endif
diff --git a/include/drm/amd_asic_type.h b/include/drm/amd_asic_type.h
index 0bf0ad869eb9..0f66a0d9f06d 100644
--- a/include/drm/amd_asic_type.h
+++ b/include/drm/amd_asic_type.h
@@ -53,14 +53,15 @@ enum amd_asic_type {
CHIP_RENOIR, /* 24 */
CHIP_ALDEBARAN, /* 25 */
CHIP_NAVI10, /* 26 */
- CHIP_NAVI14, /* 27 */
- CHIP_NAVI12, /* 28 */
- CHIP_SIENNA_CICHLID, /* 29 */
- CHIP_NAVY_FLOUNDER, /* 30 */
- CHIP_VANGOGH, /* 31 */
- CHIP_DIMGREY_CAVEFISH, /* 32 */
- CHIP_BEIGE_GOBY, /* 33 */
- CHIP_YELLOW_CARP, /* 34 */
+ CHIP_CYAN_SKILLFISH, /* 27 */
+ CHIP_NAVI14, /* 28 */
+ CHIP_NAVI12, /* 29 */
+ CHIP_SIENNA_CICHLID, /* 30 */
+ CHIP_NAVY_FLOUNDER, /* 31 */
+ CHIP_VANGOGH, /* 32 */
+ CHIP_DIMGREY_CAVEFISH, /* 33 */
+ CHIP_BEIGE_GOBY, /* 34 */
+ CHIP_YELLOW_CARP, /* 35 */
CHIP_LAST,
};
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 6a5716655619..2a1f85f9a8a3 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -126,6 +126,8 @@ struct dw_hdmi_phy_ops {
struct dw_hdmi_plat_data {
struct regmap *regm;
+ unsigned int output_port;
+
unsigned long input_bus_encoding;
bool use_drm_infoframe;
bool ycbcr_420_allowed;
diff --git a/include/drm/drm_aperture.h b/include/drm/drm_aperture.h
index 6c148078780c..7096703c3949 100644
--- a/include/drm/drm_aperture.h
+++ b/include/drm/drm_aperture.h
@@ -6,20 +6,22 @@
#include <linux/types.h>
struct drm_device;
+struct drm_driver;
struct pci_dev;
int devm_aperture_acquire_from_firmware(struct drm_device *dev, resource_size_t base,
resource_size_t size);
int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
- bool primary, const char *name);
+ bool primary, const struct drm_driver *req_driver);
-int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name);
+int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
+ const struct drm_driver *req_driver);
/**
* drm_aperture_remove_framebuffers - remove all existing framebuffers
* @primary: also kick vga16fb if present
- * @name: requesting driver name
+ * @req_driver: requesting DRM driver
*
* This function removes all graphics device drivers. Use this function on systems
* that can have their framebuffer located anywhere in memory.
@@ -27,9 +29,11 @@ int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const
* Returns:
* 0 on success, or a negative errno code otherwise
*/
-static inline int drm_aperture_remove_framebuffers(bool primary, const char *name)
+static inline int
+drm_aperture_remove_framebuffers(bool primary, const struct drm_driver *req_driver)
{
- return drm_aperture_remove_conflicting_framebuffers(0, (resource_size_t)-1, primary, name);
+ return drm_aperture_remove_conflicting_framebuffers(0, (resource_size_t)-1, primary,
+ req_driver);
}
#endif
diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h
index 6bf8b2b78991..ba248ca8866f 100644
--- a/include/drm/drm_auth.h
+++ b/include/drm/drm_auth.h
@@ -58,12 +58,6 @@ struct drm_lock_data {
* @refcount: Refcount for this master object.
* @dev: Link back to the DRM device
* @driver_priv: Pointer to driver-private information.
- * @lessor: Lease holder
- * @lessee_id: id for lessees. Owners always have id 0
- * @lessee_list: other lessees of the same master
- * @lessees: drm_masters leasing from this one
- * @leases: Objects leased to this drm_master.
- * @lessee_idr: All lessees under this owner (only used where lessor == NULL)
*
* Note that master structures are only relevant for the legacy/primary device
* nodes, hence there can only be one per device, not one per drm_minor.
@@ -88,17 +82,68 @@ struct drm_master {
struct idr magic_map;
void *driver_priv;
- /* Tree of display resource leases, each of which is a drm_master struct
- * All of these get activated simultaneously, so drm_device master points
- * at the top of the tree (for which lessor is NULL). Protected by
- * &drm_device.mode_config.idr_mutex.
+ /**
+ * @lessor:
+ *
+ * Lease grantor, only set if this &struct drm_master represents a
+ * lessee holding a lease of objects from @lessor. Full owners of the
+ * device have this set to NULL.
+ *
+ * The lessor does not change once it's set in drm_lease_create(), and
+ * each lessee holds a reference to its lessor that it releases upon
+ * being destroyed in drm_lease_destroy().
+ *
+ * See also the :ref:`section on display resource leasing
+ * <drm_leasing>`.
*/
-
struct drm_master *lessor;
+
+ /**
+ * @lessee_id:
+ *
+ * ID for lessees. Owners (i.e. @lessor is NULL) always have ID 0.
+ * Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex.
+ */
int lessee_id;
+
+ /**
+ * @lessee_list:
+ *
+ * List entry of lessees of @lessor, where they are linked to @lessees.
+ * Not used for owners. Protected by &drm_device.mode_config's
+ * &drm_mode_config.idr_mutex.
+ */
struct list_head lessee_list;
+
+ /**
+ * @lessees:
+ *
+ * List of drm_masters leasing from this one. Protected by
+ * &drm_device.mode_config's &drm_mode_config.idr_mutex.
+ *
+ * This list is empty if no leases have been granted, or if all lessees
+ * have been destroyed. Since lessors are referenced by all their
+ * lessees, this master cannot be destroyed unless the list is empty.
+ */
struct list_head lessees;
+
+ /**
+ * @leases:
+ *
+ * Objects leased to this drm_master. Protected by
+ * &drm_device.mode_config's &drm_mode_config.idr_mutex.
+ *
+ * Objects are leased all together in drm_lease_create(), and are
+ * removed all together when the lease is revoked.
+ */
struct idr leases;
+
+ /**
+ * @lessee_idr:
+ *
+ * All lessees under this owner (only used where @lessor is NULL).
+ * Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex.
+ */
struct idr lessee_idr;
/* private: */
#if IS_ENABLED(CONFIG_DRM_LEGACY)
@@ -107,6 +152,7 @@ struct drm_master {
};
struct drm_master *drm_master_get(struct drm_master *master);
+struct drm_master *drm_file_get_master(struct drm_file *file_priv);
void drm_master_put(struct drm_master **master);
bool drm_is_current_master(struct drm_file *fpriv);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 2195daa289d2..46bdfa48c413 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -171,6 +171,11 @@ struct drm_bridge_funcs {
* signals) feeding it is still running when this callback is called.
*
* The @disable callback is optional.
+ *
+ * NOTE:
+ *
+ * This is deprecated, do not use!
+ * New drivers shall use &drm_bridge_funcs.atomic_disable.
*/
void (*disable)(struct drm_bridge *bridge);
@@ -190,6 +195,11 @@ struct drm_bridge_funcs {
* called.
*
* The @post_disable callback is optional.
+ *
+ * NOTE:
+ *
+ * This is deprecated, do not use!
+ * New drivers shall use &drm_bridge_funcs.atomic_post_disable.
*/
void (*post_disable)(struct drm_bridge *bridge);
@@ -215,9 +225,9 @@ struct drm_bridge_funcs {
*
* NOTE:
*
- * If a need arises to store and access modes adjusted for other
- * locations than the connection between the CRTC and the first bridge,
- * the DRM framework will have to be extended with DRM bridge states.
+ * This is deprecated, do not use!
+ * New drivers shall set their mode in the
+ * &drm_bridge_funcs.atomic_enable operation.
*/
void (*mode_set)(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
@@ -239,6 +249,11 @@ struct drm_bridge_funcs {
* there is one) when this callback is called.
*
* The @pre_enable callback is optional.
+ *
+ * NOTE:
+ *
+ * This is deprecated, do not use!
+ * New drivers shall use &drm_bridge_funcs.atomic_pre_enable.
*/
void (*pre_enable)(struct drm_bridge *bridge);
@@ -259,6 +274,11 @@ struct drm_bridge_funcs {
* chain if there is one.
*
* The @enable callback is optional.
+ *
+ * NOTE:
+ *
+ * This is deprecated, do not use!
+ * New drivers shall use &drm_bridge_funcs.atomic_enable.
*/
void (*enable)(struct drm_bridge *bridge);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 714d1a01c065..1647960c9e50 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -848,6 +848,11 @@ struct drm_connector_funcs {
* locks to avoid races with concurrent modeset changes need to use
* &drm_connector_helper_funcs.detect_ctx instead.
*
+ * Also note that this callback can be called no matter the
+ * state the connector is in. Drivers that need the underlying
+ * device to be powered to perform the detection will first need
+ * to make sure it's been properly enabled.
+ *
* RETURNS:
*
* drm_connector_status indicating the connector's status.
@@ -1735,6 +1740,11 @@ void drm_mode_put_tile_group(struct drm_device *dev,
* drm_connector_list_iter_begin(), drm_connector_list_iter_end() and
* drm_connector_list_iter_next() respectively the convenience macro
* drm_for_each_connector_iter().
+ *
+ * Note that the return value of drm_connector_list_iter_next() is only valid
+ * up to the next drm_connector_list_iter_next() or
+ * drm_connector_list_iter_end() call. If you want to use the connector later,
+ * then you need to grab your own reference first using drm_connector_get().
*/
struct drm_connector_list_iter {
/* private: */
diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h
index 40c34a5bf149..effda42cce31 100644
--- a/include/drm/drm_damage_helper.h
+++ b/include/drm/drm_damage_helper.h
@@ -64,7 +64,6 @@ struct drm_atomic_helper_damage_iter {
bool full_update;
};
-void drm_plane_enable_fb_damage_clips(struct drm_plane *plane);
void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state,
struct drm_plane_state *plane_state);
int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
@@ -82,21 +81,4 @@ bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
struct drm_plane_state *state,
struct drm_rect *rect);
-/**
- * drm_helper_get_plane_damage_clips - Returns damage clips in &drm_rect.
- * @state: Plane state.
- *
- * Returns plane damage rectangles in internal &drm_rect. Currently &drm_rect
- * can be obtained by simply typecasting &drm_mode_rect. This is because both
- * are signed 32 and during drm_atomic_check_only() it is verified that damage
- * clips are inside fb.
- *
- * Return: Clips in plane fb_damage_clips blob property.
- */
-static inline struct drm_rect *
-drm_helper_get_plane_damage_clips(const struct drm_plane_state *state)
-{
- return (struct drm_rect *)drm_plane_get_damage_clips(state);
-}
-
#endif
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index f588f967bb14..604b1d1b2d72 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -192,20 +192,6 @@ struct drm_device {
struct list_head clientlist;
/**
- * @irq_enabled:
- *
- * Indicates that interrupt handling is enabled, specifically vblank
- * handling. Drivers which don't use drm_irq_install() need to set this
- * to true manually.
- */
- bool irq_enabled;
-
- /**
- * @irq: Used by the drm_irq_install() and drm_irq_unistall() helpers.
- */
- int irq;
-
- /**
* @vblank_disable_immediate:
*
* If true, vblank interrupt will be disabled immediately when the
@@ -372,6 +358,10 @@ struct drm_device {
/* Scatter gather memory */
struct drm_sg_mem *sg;
+
+ /* IRQs */
+ bool irq_enabled;
+ int irq;
#endif
};
diff --git a/include/drm/drm_dp_aux_bus.h b/include/drm/drm_dp_aux_bus.h
new file mode 100644
index 000000000000..4f19b20b1dd6
--- /dev/null
+++ b/include/drm/drm_dp_aux_bus.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * The DP AUX bus is used for devices that are connected over a DisplayPort
+ * AUX bus. The devices on the far side of the bus are referred to as
+ * endpoints in this code.
+ */
+
+#ifndef _DP_AUX_BUS_H_
+#define _DP_AUX_BUS_H_
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+/**
+ * struct dp_aux_ep_device - Main dev structure for DP AUX endpoints
+ *
+ * This is used to instantiate devices that are connected via a DP AUX
+ * bus. Usually the device is a panel, but conceivable other devices could
+ * be hooked up there.
+ */
+struct dp_aux_ep_device {
+ /** @dev: The normal dev pointer */
+ struct device dev;
+ /** @aux: Pointer to the aux bus */
+ struct drm_dp_aux *aux;
+};
+
+struct dp_aux_ep_driver {
+ int (*probe)(struct dp_aux_ep_device *aux_ep);
+ void (*remove)(struct dp_aux_ep_device *aux_ep);
+ void (*shutdown)(struct dp_aux_ep_device *aux_ep);
+ struct device_driver driver;
+};
+
+static inline struct dp_aux_ep_device *to_dp_aux_ep_dev(struct device *dev)
+{
+ return container_of(dev, struct dp_aux_ep_device, dev);
+}
+
+static inline struct dp_aux_ep_driver *to_dp_aux_ep_drv(struct device_driver *drv)
+{
+ return container_of(drv, struct dp_aux_ep_driver, driver);
+}
+
+int of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux);
+void of_dp_aux_depopulate_ep_devices(struct drm_dp_aux *aux);
+int devm_of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux);
+
+#define dp_aux_dp_driver_register(aux_ep_drv) \
+ __dp_aux_dp_driver_register(aux_ep_drv, THIS_MODULE)
+int __dp_aux_dp_driver_register(struct dp_aux_ep_driver *aux_ep_drv,
+ struct module *owner);
+void dp_aux_dp_driver_unregister(struct dp_aux_ep_driver *aux_ep_drv);
+
+#endif /* _DP_AUX_BUS_H_ */
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 3f2715eb965f..1d5b3dbb6e56 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -30,6 +30,7 @@
struct drm_device;
struct drm_dp_aux;
+struct drm_panel;
/*
* Unless otherwise noted, all values are from the DP 1.1a spec. Note that
@@ -1818,6 +1819,24 @@ drm_dp_sink_can_do_video_without_timing_msa(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
DP_MSA_TIMING_PAR_IGNORED;
}
+/**
+ * drm_edp_backlight_supported() - Check an eDP DPCD for VESA backlight support
+ * @edp_dpcd: The DPCD to check
+ *
+ * Note that currently this function will return %false for panels which support various DPCD
+ * backlight features but which require the brightness be set through PWM, and don't support setting
+ * the brightness level via the DPCD. This is a TODO.
+ *
+ * Returns: %True if @edp_dpcd indicates that VESA backlight controls are supported, %false
+ * otherwise
+ */
+static inline bool
+drm_edp_backlight_supported(const u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE])
+{
+ return (edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP) &&
+ (edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP);
+}
+
/*
* DisplayPort AUX channel
*/
@@ -1858,35 +1877,6 @@ struct drm_dp_aux_cec {
/**
* struct drm_dp_aux - DisplayPort AUX channel
- * @name: user-visible name of this AUX channel and the I2C-over-AUX adapter
- * @ddc: I2C adapter that can be used for I2C-over-AUX communication
- * @dev: pointer to struct device that is the parent for this AUX channel
- * @drm_dev: pointer to the &drm_device that owns this AUX channel. Beware, this
- * may be %NULL before drm_dp_aux_register() has been called.
- * @crtc: backpointer to the crtc that is currently using this AUX channel
- * @hw_mutex: internal mutex used for locking transfers
- * @crc_work: worker that captures CRCs for each frame
- * @crc_count: counter of captured frame CRCs
- * @transfer: transfers a message representing a single AUX transaction
- *
- * The @dev field should be set to a pointer to the device that implements the
- * AUX channel. As well, the @drm_dev field should be set to the &drm_device
- * that will be using this AUX channel as early as possible. For many graphics
- * drivers this should happen before drm_dp_aux_init(), however it's perfectly
- * fine to set this field later so long as it's assigned before calling
- * drm_dp_aux_register().
- *
- * The @name field may be used to specify the name of the I2C adapter. If set to
- * %NULL, dev_name() of @dev will be used.
- *
- * Drivers provide a hardware-specific implementation of how transactions are
- * executed via the @transfer() function. A pointer to a &drm_dp_aux_msg
- * structure describing the transaction is passed into this function. Upon
- * success, the implementation should return the number of payload bytes that
- * were transferred, or a negative error-code on failure. Helpers propagate
- * errors from the @transfer() function, with the exception of the %-EBUSY
- * error, which causes a transaction to be retried. On a short, helpers will
- * return %-EPROTO to make it simpler to check for failure.
*
* An AUX channel can also be used to transport I2C messages to a sink. A
* typical application of that is to access an EDID that's present in the sink
@@ -1897,22 +1887,96 @@ struct drm_dp_aux_cec {
* transfers by default; if a partial response is received, the adapter will
* drop down to the size given by the partial response for this transaction
* only.
- *
- * Note that the aux helper code assumes that the @transfer() function only
- * modifies the reply field of the &drm_dp_aux_msg structure. The retry logic
- * and i2c helpers assume this is the case.
*/
struct drm_dp_aux {
+ /**
+ * @name: user-visible name of this AUX channel and the
+ * I2C-over-AUX adapter.
+ *
+ * It's also used to specify the name of the I2C adapter. If set
+ * to %NULL, dev_name() of @dev will be used.
+ */
const char *name;
+
+ /**
+ * @ddc: I2C adapter that can be used for I2C-over-AUX
+ * communication
+ */
struct i2c_adapter ddc;
+
+ /**
+ * @dev: pointer to struct device that is the parent for this
+ * AUX channel.
+ */
struct device *dev;
+
+ /**
+ * @drm_dev: pointer to the &drm_device that owns this AUX channel.
+ * Beware, this may be %NULL before drm_dp_aux_register() has been
+ * called.
+ *
+ * It should be set to the &drm_device that will be using this AUX
+ * channel as early as possible. For many graphics drivers this should
+ * happen before drm_dp_aux_init(), however it's perfectly fine to set
+ * this field later so long as it's assigned before calling
+ * drm_dp_aux_register().
+ */
struct drm_device *drm_dev;
+
+ /**
+ * @crtc: backpointer to the crtc that is currently using this
+ * AUX channel
+ */
struct drm_crtc *crtc;
+
+ /**
+ * @hw_mutex: internal mutex used for locking transfers.
+ *
+ * Note that if the underlying hardware is shared among multiple
+ * channels, the driver needs to do additional locking to
+ * prevent concurrent access.
+ */
struct mutex hw_mutex;
+
+ /**
+ * @crc_work: worker that captures CRCs for each frame
+ */
struct work_struct crc_work;
+
+ /**
+ * @crc_count: counter of captured frame CRCs
+ */
u8 crc_count;
+
+ /**
+ * @transfer: transfers a message representing a single AUX
+ * transaction.
+ *
+ * This is a hardware-specific implementation of how
+ * transactions are executed that the drivers must provide.
+ *
+ * A pointer to a &drm_dp_aux_msg structure describing the
+ * transaction is passed into this function. Upon success, the
+ * implementation should return the number of payload bytes that
+ * were transferred, or a negative error-code on failure.
+ *
+ * Helpers will propagate these errors, with the exception of
+ * the %-EBUSY error, which causes a transaction to be retried.
+ * On a short, helpers will return %-EPROTO to make it simpler
+ * to check for failure.
+ *
+ * The @transfer() function must only modify the reply field of
+ * the &drm_dp_aux_msg structure. The retry logic and i2c
+ * helpers assume this is the case.
+ *
+ * Also note that this callback can be called no matter the
+ * state @dev is in. Drivers that need that device to be powered
+ * to perform this operation will first need to make sure it's
+ * been properly enabled.
+ */
ssize_t (*transfer)(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg);
+
/**
* @i2c_nack_count: Counts I2C NACKs, used for DP validation.
*/
@@ -2124,6 +2188,51 @@ drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk)
return desc->quirks & BIT(quirk);
}
+/**
+ * struct drm_edp_backlight_info - Probed eDP backlight info struct
+ * @pwmgen_bit_count: The pwmgen bit count
+ * @pwm_freq_pre_divider: The PWM frequency pre-divider value being used for this backlight, if any
+ * @max: The maximum backlight level that may be set
+ * @lsb_reg_used: Do we also write values to the DP_EDP_BACKLIGHT_BRIGHTNESS_LSB register?
+ * @aux_enable: Does the panel support the AUX enable cap?
+ *
+ * This structure contains various data about an eDP backlight, which can be populated by using
+ * drm_edp_backlight_init().
+ */
+struct drm_edp_backlight_info {
+ u8 pwmgen_bit_count;
+ u8 pwm_freq_pre_divider;
+ u16 max;
+
+ bool lsb_reg_used : 1;
+ bool aux_enable : 1;
+};
+
+int
+drm_edp_backlight_init(struct drm_dp_aux *aux, struct drm_edp_backlight_info *bl,
+ u16 driver_pwm_freq_hz, const u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE],
+ u16 *current_level, u8 *current_mode);
+int drm_edp_backlight_set_level(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl,
+ u16 level);
+int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl,
+ u16 level);
+int drm_edp_backlight_disable(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl);
+
+#if IS_ENABLED(CONFIG_DRM_KMS_HELPER) && (IS_BUILTIN(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
+ (IS_MODULE(CONFIG_DRM_KMS_HELPER) && IS_MODULE(CONFIG_BACKLIGHT_CLASS_DEVICE)))
+
+int drm_panel_dp_aux_backlight(struct drm_panel *panel, struct drm_dp_aux *aux);
+
+#else
+
+static inline int drm_panel_dp_aux_backlight(struct drm_panel *panel,
+ struct drm_dp_aux *aux)
+{
+ return 0;
+}
+
+#endif
+
#ifdef CONFIG_DRM_DP_CEC
void drm_dp_cec_irq(struct drm_dp_aux *aux);
void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index b439ae1921b8..0cd95953cdf5 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -137,10 +137,6 @@ enum drm_driver_feature {
* @DRIVER_HAVE_IRQ:
*
* Legacy irq support. Only for legacy drivers. Do not use.
- *
- * New drivers can either use the drm_irq_install() and
- * drm_irq_uninstall() helper functions, or roll their own irq support
- * code by calling request_irq() directly.
*/
DRIVER_HAVE_IRQ = BIT(30),
/**
@@ -272,42 +268,6 @@ struct drm_driver {
void (*release) (struct drm_device *);
/**
- * @irq_handler:
- *
- * Interrupt handler called when using drm_irq_install(). Not used by
- * drivers which implement their own interrupt handling.
- */
- irqreturn_t(*irq_handler) (int irq, void *arg);
-
- /**
- * @irq_preinstall:
- *
- * Optional callback used by drm_irq_install() which is called before
- * the interrupt handler is registered. This should be used to clear out
- * any pending interrupts (from e.g. firmware based drives) and reset
- * the interrupt handling registers.
- */
- void (*irq_preinstall) (struct drm_device *dev);
-
- /**
- * @irq_postinstall:
- *
- * Optional callback used by drm_irq_install() which is called after
- * the interrupt handler is registered. This should be used to enable
- * interrupt generation in the hardware.
- */
- int (*irq_postinstall) (struct drm_device *dev);
-
- /**
- * @irq_uninstall:
- *
- * Optional callback used by drm_irq_uninstall() which is called before
- * the interrupt handler is unregistered. This should be used to disable
- * interrupt generation in the hardware.
- */
- void (*irq_uninstall) (struct drm_device *dev);
-
- /**
* @master_set:
*
* Called whenever the minor master is set. Only used by vmwgfx.
@@ -504,6 +464,10 @@ struct drm_driver {
int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
int (*dma_quiescent) (struct drm_device *);
int (*context_dtor) (struct drm_device *dev, int context);
+ irqreturn_t (*irq_handler)(int irq, void *arg);
+ void (*irq_preinstall)(struct drm_device *dev);
+ int (*irq_postinstall)(struct drm_device *dev);
+ void (*irq_uninstall)(struct drm_device *dev);
u32 (*get_vblank_counter)(struct drm_device *dev, unsigned int pipe);
int (*enable_vblank)(struct drm_device *dev, unsigned int pipe);
void (*disable_vblank)(struct drm_device *dev, unsigned int pipe);
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 759328a5eeb2..deccfd39e6db 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -336,7 +336,7 @@ struct edid {
u8 features;
/* Color characteristics */
u8 red_green_lo;
- u8 black_white_lo;
+ u8 blue_white_lo;
u8 red_x;
u8 red_y;
u8 green_x;
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index b81b3bfb08c8..a3acb7ac3550 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -226,15 +226,31 @@ struct drm_file {
/**
* @master:
*
- * Master this node is currently associated with. Only relevant if
- * drm_is_primary_client() returns true. Note that this only
- * matches &drm_device.master if the master is the currently active one.
+ * Master this node is currently associated with. Protected by struct
+ * &drm_device.master_mutex, and serialized by @master_lookup_lock.
+ *
+ * Only relevant if drm_is_primary_client() returns true. Note that
+ * this only matches &drm_device.master if the master is the currently
+ * active one.
+ *
+ * To update @master, both &drm_device.master_mutex and
+ * @master_lookup_lock need to be held, therefore holding either of
+ * them is safe and enough for the read side.
+ *
+ * When dereferencing this pointer, either hold struct
+ * &drm_device.master_mutex for the duration of the pointer's use, or
+ * use drm_file_get_master() if struct &drm_device.master_mutex is not
+ * currently held and there is no other need to hold it. This prevents
+ * @master from being freed during use.
*
* See also @authentication and @is_master and the :ref:`section on
* primary nodes and authentication <drm_primary_node>`.
*/
struct drm_master *master;
+ /** @master_lock: Serializes @master. */
+ spinlock_t master_lookup_lock;
+
/** @pid: Process that opened this file. */
struct pid *pid;
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 3b138d4ae67e..22aa64d07c79 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -25,6 +25,11 @@
#include <linux/types.h>
#include <uapi/drm/drm_fourcc.h>
+/**
+ * DRM_FORMAT_MAX_PLANES - maximum number of planes a DRM format can have
+ */
+#define DRM_FORMAT_MAX_PLANES 4u
+
/*
* DRM formats are little endian. Define host endian variants for the
* most common formats here, to reduce the #ifdefs needed in drivers.
@@ -78,7 +83,7 @@ struct drm_format_info {
* triplet @char_per_block, @block_w, @block_h for better
* describing the pixel format.
*/
- u8 cpp[4];
+ u8 cpp[DRM_FORMAT_MAX_PLANES];
/**
* @char_per_block:
@@ -104,7 +109,7 @@ struct drm_format_info {
* information from their drm_mode_config.get_format_info hook
* if they want the core to be validating the pitch.
*/
- u8 char_per_block[4];
+ u8 char_per_block[DRM_FORMAT_MAX_PLANES];
};
/**
@@ -113,7 +118,7 @@ struct drm_format_info {
* Block width in pixels, this is intended to be accessed through
* drm_format_info_block_width()
*/
- u8 block_w[4];
+ u8 block_w[DRM_FORMAT_MAX_PLANES];
/**
* @block_h:
@@ -121,7 +126,7 @@ struct drm_format_info {
* Block height in pixels, this is intended to be accessed through
* drm_format_info_block_height()
*/
- u8 block_h[4];
+ u8 block_h[DRM_FORMAT_MAX_PLANES];
/** @hsub: Horizontal chroma subsampling factor */
u8 hsub;
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index be658ebbec72..f67c5b7bcb68 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h
@@ -27,12 +27,12 @@
#include <linux/list.h>
#include <linux/sched.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_mode_object.h>
struct drm_clip_rect;
struct drm_device;
struct drm_file;
-struct drm_format_info;
struct drm_framebuffer;
struct drm_gem_object;
@@ -147,7 +147,7 @@ struct drm_framebuffer {
* @pitches: Line stride per buffer. For userspace created object this
* is copied from drm_mode_fb_cmd2.
*/
- unsigned int pitches[4];
+ unsigned int pitches[DRM_FORMAT_MAX_PLANES];
/**
* @offsets: Offset from buffer start to the actual pixel data in bytes,
* per buffer. For userspace created object this is copied from
@@ -165,7 +165,7 @@ struct drm_framebuffer {
* data (even for linear buffers). Specifying an x/y pixel offset is
* instead done through the source rectangle in &struct drm_plane_state.
*/
- unsigned int offsets[4];
+ unsigned int offsets[DRM_FORMAT_MAX_PLANES];
/**
* @modifier: Data layout modifier. This is used to describe
* tiling, or also special layouts (like compression) of auxiliary
@@ -210,7 +210,7 @@ struct drm_framebuffer {
* This is used by the GEM framebuffer helpers, see e.g.
* drm_gem_fb_create().
*/
- struct drm_gem_object *obj[4];
+ struct drm_gem_object *obj[DRM_FORMAT_MAX_PLANES];
};
#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 240049566592..35e7f44c2a75 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -384,8 +384,6 @@ drm_gem_object_put(struct drm_gem_object *obj)
__drm_gem_object_put(obj);
}
-void drm_gem_object_put_locked(struct drm_gem_object *obj);
-
int drm_gem_handle_create(struct drm_file *file_priv,
struct drm_gem_object *obj,
u32 *handlep);
diff --git a/include/drm/drm_gem_atomic_helper.h b/include/drm/drm_gem_atomic_helper.h
index cfc5adee3d13..48222a107873 100644
--- a/include/drm/drm_gem_atomic_helper.h
+++ b/include/drm/drm_gem_atomic_helper.h
@@ -5,6 +5,7 @@
#include <linux/dma-buf-map.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_plane.h>
struct drm_simple_display_pipe;
@@ -40,7 +41,15 @@ struct drm_shadow_plane_state {
* The memory mappings stored in map should be established in the plane's
* prepare_fb callback and removed in the cleanup_fb callback.
*/
- struct dma_buf_map map[4];
+ struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];
+
+ /**
+ * @data: Address of each framebuffer BO's data
+ *
+ * The address of the data stored in each mapping. This is different
+ * for framebuffers with non-zero offset fields.
+ */
+ struct dma_buf_map data[DRM_FORMAT_MAX_PLANES];
};
/**
@@ -53,6 +62,12 @@ to_drm_shadow_plane_state(struct drm_plane_state *state)
return container_of(state, struct drm_shadow_plane_state, base);
}
+void __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane,
+ struct drm_shadow_plane_state *new_shadow_plane_state);
+void __drm_gem_destroy_shadow_plane_state(struct drm_shadow_plane_state *shadow_plane_state);
+void __drm_gem_reset_shadow_plane(struct drm_plane *plane,
+ struct drm_shadow_plane_state *shadow_plane_state);
+
void drm_gem_reset_shadow_plane(struct drm_plane *plane);
struct drm_plane_state *drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane);
void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane,
diff --git a/include/drm/drm_gem_framebuffer_helper.h b/include/drm/drm_gem_framebuffer_helper.h
index 6bdffc7aa124..905727719ead 100644
--- a/include/drm/drm_gem_framebuffer_helper.h
+++ b/include/drm/drm_gem_framebuffer_helper.h
@@ -1,6 +1,11 @@
#ifndef __DRM_GEM_FB_HELPER_H__
#define __DRM_GEM_FB_HELPER_H__
+#include <linux/dma-buf.h>
+#include <linux/dma-buf-map.h>
+
+#include <drm/drm_fourcc.h>
+
struct drm_afbc_framebuffer;
struct drm_device;
struct drm_fb_helper_surface_size;
@@ -34,6 +39,14 @@ struct drm_framebuffer *
drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
const struct drm_mode_fb_cmd2 *mode_cmd);
+int drm_gem_fb_vmap(struct drm_framebuffer *fb,
+ struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES],
+ struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]);
+void drm_gem_fb_vunmap(struct drm_framebuffer *fb,
+ struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES]);
+int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);
+void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);
+
#define drm_is_afbc(modifier) \
(((modifier) & AFBC_VENDOR_AND_TYPE_MASK) == DRM_FORMAT_MOD_ARM_AFBC(0))
diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h
index 27ed7e9243b9..d3cf06c9af65 100644
--- a/include/drm/drm_gem_vram_helper.h
+++ b/include/drm/drm_gem_vram_helper.h
@@ -124,6 +124,18 @@ void
drm_gem_vram_plane_helper_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state);
+/**
+ * DRM_GEM_VRAM_PLANE_HELPER_FUNCS -
+ * Initializes struct drm_plane_helper_funcs for VRAM handling
+ *
+ * Drivers may use GEM BOs as VRAM helpers for the framebuffer memory. This
+ * macro initializes struct drm_plane_helper_funcs to use the respective helper
+ * functions.
+ */
+#define DRM_GEM_VRAM_PLANE_HELPER_FUNCS \
+ .prepare_fb = drm_gem_vram_plane_helper_prepare_fb, \
+ .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb
+
/*
* Helpers for struct drm_simple_display_pipe_funcs
*/
@@ -192,10 +204,6 @@ void drm_vram_mm_debugfs_init(struct drm_minor *minor);
* Helpers for integration with struct drm_device
*/
-struct drm_vram_mm *drm_vram_helper_alloc_mm(
- struct drm_device *dev, uint64_t vram_base, size_t vram_size);
-void drm_vram_helper_release_mm(struct drm_device *dev);
-
int drmm_vram_helper_init(struct drm_device *dev, uint64_t vram_base,
size_t vram_size);
diff --git a/include/drm/drm_legacy.h b/include/drm/drm_legacy.h
index b17e79e12bc2..58dc8d8cc907 100644
--- a/include/drm/drm_legacy.h
+++ b/include/drm/drm_legacy.h
@@ -192,6 +192,9 @@ do { \
void drm_legacy_idlelock_take(struct drm_lock_data *lock);
void drm_legacy_idlelock_release(struct drm_lock_data *lock);
+/* drm_irq.c */
+int drm_legacy_irq_uninstall(struct drm_device *dev);
+
/* drm_pci.c */
#ifdef CONFIG_PCI
diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
index f543d6e3e822..05e194958265 100644
--- a/include/drm/drm_mipi_dbi.h
+++ b/include/drm/drm_mipi_dbi.h
@@ -183,7 +183,12 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
#define mipi_dbi_command(dbi, cmd, seq...) \
({ \
const u8 d[] = { seq }; \
- mipi_dbi_command_stackbuf(dbi, cmd, d, ARRAY_SIZE(d)); \
+ struct device *dev = &(dbi)->spi->dev; \
+ int ret; \
+ ret = mipi_dbi_command_stackbuf(dbi, cmd, d, ARRAY_SIZE(d)); \
+ if (ret) \
+ dev_err_ratelimited(dev, "error %d when sending command %#02x\n", ret, cmd); \
+ ret; \
})
#ifdef CONFIG_DEBUG_FS
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 360e6377e84b..af7ba8071eb0 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -80,6 +80,11 @@ int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
* Note that typically DSI packet transmission is atomic, so the .transfer()
* function will seldomly return anything other than the number of bytes
* contained in the transmit buffer on success.
+ *
+ * Also note that those callbacks can be called no matter the state the
+ * host is in. Drivers that need the underlying device to be powered to
+ * perform these operations will first need to make sure it's been
+ * properly enabled.
*/
struct mipi_dsi_host_ops {
int (*attach)(struct mipi_dsi_host *host,
@@ -119,15 +124,15 @@ struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
/* enable hsync-end packets in vsync-pulse and v-porch area */
#define MIPI_DSI_MODE_VIDEO_HSE BIT(4)
/* disable hfront-porch area */
-#define MIPI_DSI_MODE_VIDEO_HFP BIT(5)
+#define MIPI_DSI_MODE_VIDEO_NO_HFP BIT(5)
/* disable hback-porch area */
-#define MIPI_DSI_MODE_VIDEO_HBP BIT(6)
+#define MIPI_DSI_MODE_VIDEO_NO_HBP BIT(6)
/* disable hsync-active area */
-#define MIPI_DSI_MODE_VIDEO_HSA BIT(7)
+#define MIPI_DSI_MODE_VIDEO_NO_HSA BIT(7)
/* flush display FIFO on vsync pulse */
#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8)
/* disable EoT packets in HS mode */
-#define MIPI_DSI_MODE_EOT_PACKET BIT(9)
+#define MIPI_DSI_MODE_NO_EOT_PACKET BIT(9)
/* device supports non-continuous clock behavior (DSI spec 5.6.1) */
#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10)
/* transmit data in low power */
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index f3a4b47b3986..fdfa9f37ce05 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -1178,8 +1178,11 @@ struct drm_plane_helper_funcs {
* equivalent functionality should be implemented through private
* members in the plane structure.
*
- * Drivers which always have their buffers pinned should use
- * drm_gem_plane_helper_prepare_fb() for this hook.
+ * For GEM drivers who neither have a @prepare_fb nor @cleanup_fb hook
+ * set drm_gem_plane_helper_prepare_fb() is called automatically to
+ * implement this. Other drivers which need additional plane processing
+ * can call drm_gem_plane_helper_prepare_fb() from their @prepare_fb
+ * hook.
*
* The helpers will call @cleanup_fb with matching arguments for every
* successful call to this hook.
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 33605c3f0eba..4602f833eb51 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -64,8 +64,8 @@ enum drm_panel_orientation;
* the panel. This is the job of the .unprepare() function.
*
* Backlight can be handled automatically if configured using
- * drm_panel_of_backlight(). Then the driver does not need to implement the
- * functionality to enable/disable backlight.
+ * drm_panel_of_backlight() or drm_panel_dp_aux_backlight(). Then the driver
+ * does not need to implement the functionality to enable/disable backlight.
*/
struct drm_panel_funcs {
/**
@@ -144,8 +144,8 @@ struct drm_panel {
* Backlight device, used to turn on backlight after the call
* to enable(), and to turn off backlight before the call to
* disable().
- * backlight is set by drm_panel_of_backlight() and drivers
- * shall not assign it.
+ * backlight is set by drm_panel_of_backlight() or
+ * drm_panel_dp_aux_backlight() and drivers shall not assign it.
*/
struct backlight_device *backlight;
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 1294610e84f4..fed97e35626f 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -186,6 +186,9 @@ struct drm_plane_state {
* since last plane update) as an array of &drm_mode_rect in framebuffer
* coodinates of the attached framebuffer. Note that unlike plane src,
* damage clips are not in 16.16 fixed point.
+ *
+ * See drm_plane_get_damage_clips() and
+ * drm_plane_get_damage_clips_count() for accessing these.
*/
struct drm_property_blob *fb_damage_clips;
@@ -894,38 +897,12 @@ static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
bool drm_any_plane_has_format(struct drm_device *dev,
u32 format, u64 modifier);
-/**
- * drm_plane_get_damage_clips_count - Returns damage clips count.
- * @state: Plane state.
- *
- * Simple helper to get the number of &drm_mode_rect clips set by user-space
- * during plane update.
- *
- * Return: Number of clips in plane fb_damage_clips blob property.
- */
-static inline unsigned int
-drm_plane_get_damage_clips_count(const struct drm_plane_state *state)
-{
- return (state && state->fb_damage_clips) ?
- state->fb_damage_clips->length/sizeof(struct drm_mode_rect) : 0;
-}
-/**
- * drm_plane_get_damage_clips - Returns damage clips.
- * @state: Plane state.
- *
- * Note that this function returns uapi type &drm_mode_rect. Drivers might
- * instead be interested in internal &drm_rect which can be obtained by calling
- * drm_helper_get_plane_damage_clips().
- *
- * Return: Damage clips in plane fb_damage_clips blob property.
- */
-static inline struct drm_mode_rect *
-drm_plane_get_damage_clips(const struct drm_plane_state *state)
-{
- return (struct drm_mode_rect *)((state && state->fb_damage_clips) ?
- state->fb_damage_clips->data : NULL);
-}
+void drm_plane_enable_fb_damage_clips(struct drm_plane *plane);
+unsigned int
+drm_plane_get_damage_clips_count(const struct drm_plane_state *state);
+struct drm_mode_rect *
+drm_plane_get_damage_clips(const struct drm_plane_state *state);
int drm_plane_create_scaling_filter_property(struct drm_plane *plane,
unsigned int supported_filters);
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index 9b66be54dd16..15a089a87c22 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -327,7 +327,7 @@ static inline bool drm_debug_enabled(enum drm_debug_category category)
/*
* struct device based logging
*
- * Prefer drm_device based logging over device or prink based logging.
+ * Prefer drm_device based logging over device or printk based logging.
*/
__printf(3, 4)
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
index bbf5c1fdd7b0..65bc9710a470 100644
--- a/include/drm/drm_property.h
+++ b/include/drm/drm_property.h
@@ -31,7 +31,6 @@
/**
* struct drm_property_enum - symbolic values for enumerations
- * @value: numeric property value for this enum entry
* @head: list of enum values, linked to &drm_property.enum_list
* @name: symbolic name for the enum
*
@@ -39,6 +38,14 @@
* decoding for each value. This is used for example for the rotation property.
*/
struct drm_property_enum {
+ /**
+ * @value: numeric property value for this enum entry
+ *
+ * If the property has the type &DRM_MODE_PROP_BITMASK, @value stores a
+ * bitshift, not a bitmask. In other words, the enum entry is enabled
+ * if the bit number @value is set in the property's value. This enum
+ * entry has the bitmask ``1 << value``.
+ */
uint64_t value;
struct list_head head;
char name[DRM_PROP_NAME_LEN];
diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h
index 39f2deee709c..6f6e19bd4dac 100644
--- a/include/drm/drm_rect.h
+++ b/include/drm/drm_rect.h
@@ -39,6 +39,9 @@
* @x2: horizontal ending coordinate (exclusive)
* @y1: vertical starting coordinate (inclusive)
* @y2: vertical ending coordinate (exclusive)
+ *
+ * Note that this must match the layout of struct drm_mode_rect or the damage
+ * helpers like drm_atomic_helper_damage_iter_init() break.
*/
struct drm_rect {
int x1, y1, x2, y2;
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index ef9944e9c5fc..0b3647e614dd 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -116,8 +116,11 @@ struct drm_simple_display_pipe_funcs {
* the documentation for the &drm_plane_helper_funcs.prepare_fb hook for
* more details.
*
- * Drivers which always have their buffers pinned should use
- * drm_gem_simple_display_pipe_prepare_fb() for this hook.
+ * For GEM drivers who neither have a @prepare_fb nor @cleanup_fb hook
+ * set drm_gem_simple_display_pipe_prepare_fb() is called automatically
+ * to implement this. Other drivers which need additional plane
+ * processing can call drm_gem_simple_display_pipe_prepare_fb() from
+ * their @prepare_fb hook.
*/
int (*prepare_fb)(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *plane_state);
@@ -151,6 +154,33 @@ struct drm_simple_display_pipe_funcs {
void (*disable_vblank)(struct drm_simple_display_pipe *pipe);
/**
+ * @reset_crtc:
+ *
+ * Optional, called by &drm_crtc_funcs.reset. Please read the
+ * documentation for the &drm_crtc_funcs.reset hook for more details.
+ */
+ void (*reset_crtc)(struct drm_simple_display_pipe *pipe);
+
+ /**
+ * @duplicate_crtc_state:
+ *
+ * Optional, called by &drm_crtc_funcs.atomic_duplicate_state. Please
+ * read the documentation for the &drm_crtc_funcs.atomic_duplicate_state
+ * hook for more details.
+ */
+ struct drm_crtc_state * (*duplicate_crtc_state)(struct drm_simple_display_pipe *pipe);
+
+ /**
+ * @destroy_crtc_state:
+ *
+ * Optional, called by &drm_crtc_funcs.atomic_destroy_state. Please
+ * read the documentation for the &drm_crtc_funcs.atomic_destroy_state
+ * hook for more details.
+ */
+ void (*destroy_crtc_state)(struct drm_simple_display_pipe *pipe,
+ struct drm_crtc_state *crtc_state);
+
+ /**
* @reset_plane:
*
* Optional, called by &drm_plane_funcs.reset. Please read the
diff --git a/include/drm/drm_vma_manager.h b/include/drm/drm_vma_manager.h
index 76ac5e97a559..4f8c35206f7c 100644
--- a/include/drm/drm_vma_manager.h
+++ b/include/drm/drm_vma_manager.h
@@ -53,7 +53,7 @@ struct drm_vma_offset_node {
rwlock_t vm_lock;
struct drm_mm_node vm_node;
struct rb_root vm_files;
- bool readonly:1;
+ void *driver_private;
};
struct drm_vma_offset_manager {
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index d18af49fd009..88ae7f331bb1 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -239,6 +239,38 @@ struct drm_sched_backend_ops {
* @timedout_job: Called when a job has taken too long to execute,
* to trigger GPU recovery.
*
+ * This method is called in a workqueue context.
+ *
+ * Drivers typically issue a reset to recover from GPU hangs, and this
+ * procedure usually follows the following workflow:
+ *
+ * 1. Stop the scheduler using drm_sched_stop(). This will park the
+ * scheduler thread and cancel the timeout work, guaranteeing that
+ * nothing is queued while we reset the hardware queue
+ * 2. Try to gracefully stop non-faulty jobs (optional)
+ * 3. Issue a GPU reset (driver-specific)
+ * 4. Re-submit jobs using drm_sched_resubmit_jobs()
+ * 5. Restart the scheduler using drm_sched_start(). At that point, new
+ * jobs can be queued, and the scheduler thread is unblocked
+ *
+ * Note that some GPUs have distinct hardware queues but need to reset
+ * the GPU globally, which requires extra synchronization between the
+ * timeout handler of the different &drm_gpu_scheduler. One way to
+ * achieve this synchronization is to create an ordered workqueue
+ * (using alloc_ordered_workqueue()) at the driver level, and pass this
+ * queue to drm_sched_init(), to guarantee that timeout handlers are
+ * executed sequentially. The above workflow needs to be slightly
+ * adjusted in that case:
+ *
+ * 1. Stop all schedulers impacted by the reset using drm_sched_stop()
+ * 2. Try to gracefully stop non-faulty jobs on all queues impacted by
+ * the reset (optional)
+ * 3. Issue a GPU reset on all faulty queues (driver-specific)
+ * 4. Re-submit jobs on all schedulers impacted by the reset using
+ * drm_sched_resubmit_jobs()
+ * 5. Restart all schedulers that were stopped in step #1 using
+ * drm_sched_start()
+ *
* Return DRM_GPU_SCHED_STAT_NOMINAL, when all is normal,
* and the underlying driver has started or completed recovery.
*
@@ -269,6 +301,7 @@ struct drm_sched_backend_ops {
* finished.
* @hw_rq_count: the number of jobs currently in the hardware queue.
* @job_id_count: used to assign unique id to the each job.
+ * @timeout_wq: workqueue used to queue @work_tdr
* @work_tdr: schedules a delayed call to @drm_sched_job_timedout after the
* timeout interval is over.
* @thread: the kthread on which the scheduler which run.
@@ -293,6 +326,7 @@ struct drm_gpu_scheduler {
wait_queue_head_t job_scheduled;
atomic_t hw_rq_count;
atomic64_t job_id_count;
+ struct workqueue_struct *timeout_wq;
struct delayed_work work_tdr;
struct task_struct *thread;
struct list_head pending_list;
@@ -306,7 +340,8 @@ struct drm_gpu_scheduler {
int drm_sched_init(struct drm_gpu_scheduler *sched,
const struct drm_sched_backend_ops *ops,
- uint32_t hw_submission, unsigned hang_limit, long timeout,
+ uint32_t hw_submission, unsigned hang_limit,
+ long timeout, struct workqueue_struct *timeout_wq,
atomic_t *score, const char *name);
void drm_sched_fini(struct drm_gpu_scheduler *sched);
diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h
index aa6ba4d0cf78..8995c9e4ec1b 100644
--- a/include/drm/ttm/ttm_placement.h
+++ b/include/drm/ttm/ttm_placement.h
@@ -47,8 +47,11 @@
* top of the memory area, instead of the bottom.
*/
-#define TTM_PL_FLAG_CONTIGUOUS (1 << 19)
-#define TTM_PL_FLAG_TOPDOWN (1 << 22)
+#define TTM_PL_FLAG_CONTIGUOUS (1 << 0)
+#define TTM_PL_FLAG_TOPDOWN (1 << 1)
+
+/* For multihop handling */
+#define TTM_PL_FLAG_TEMPORARY (1 << 2)
/**
* struct ttm_place
diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h
index d24b627cb2e7..01e8bab1d767 100644
--- a/include/dt-bindings/clock/imx8mn-clock.h
+++ b/include/dt-bindings/clock/imx8mn-clock.h
@@ -241,6 +241,8 @@
#define IMX8MN_CLK_CLKOUT2_DIV 219
#define IMX8MN_CLK_CLKOUT2 220
-#define IMX8MN_CLK_END 221
+#define IMX8MN_CLK_M7_CORE 221
+
+#define IMX8MN_CLK_END 222
#endif
diff --git a/include/dt-bindings/clock/mt8192-clk.h b/include/dt-bindings/clock/mt8192-clk.h
new file mode 100644
index 000000000000..5ab68f15a256
--- /dev/null
+++ b/include/dt-bindings/clock/mt8192-clk.h
@@ -0,0 +1,585 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8192_H
+#define _DT_BINDINGS_CLK_MT8192_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_AXI_SEL 0
+#define CLK_TOP_SPM_SEL 1
+#define CLK_TOP_SCP_SEL 2
+#define CLK_TOP_BUS_AXIMEM_SEL 3
+#define CLK_TOP_DISP_SEL 4
+#define CLK_TOP_MDP_SEL 5
+#define CLK_TOP_IMG1_SEL 6
+#define CLK_TOP_IMG2_SEL 7
+#define CLK_TOP_IPE_SEL 8
+#define CLK_TOP_DPE_SEL 9
+#define CLK_TOP_CAM_SEL 10
+#define CLK_TOP_CCU_SEL 11
+#define CLK_TOP_DSP7_SEL 12
+#define CLK_TOP_MFG_REF_SEL 13
+#define CLK_TOP_MFG_PLL_SEL 14
+#define CLK_TOP_CAMTG_SEL 15
+#define CLK_TOP_CAMTG2_SEL 16
+#define CLK_TOP_CAMTG3_SEL 17
+#define CLK_TOP_CAMTG4_SEL 18
+#define CLK_TOP_CAMTG5_SEL 19
+#define CLK_TOP_CAMTG6_SEL 20
+#define CLK_TOP_UART_SEL 21
+#define CLK_TOP_SPI_SEL 22
+#define CLK_TOP_MSDC50_0_H_SEL 23
+#define CLK_TOP_MSDC50_0_SEL 24
+#define CLK_TOP_MSDC30_1_SEL 25
+#define CLK_TOP_MSDC30_2_SEL 26
+#define CLK_TOP_AUDIO_SEL 27
+#define CLK_TOP_AUD_INTBUS_SEL 28
+#define CLK_TOP_PWRAP_ULPOSC_SEL 29
+#define CLK_TOP_ATB_SEL 30
+#define CLK_TOP_DPI_SEL 31
+#define CLK_TOP_SCAM_SEL 32
+#define CLK_TOP_DISP_PWM_SEL 33
+#define CLK_TOP_USB_TOP_SEL 34
+#define CLK_TOP_SSUSB_XHCI_SEL 35
+#define CLK_TOP_I2C_SEL 36
+#define CLK_TOP_SENINF_SEL 37
+#define CLK_TOP_SENINF1_SEL 38
+#define CLK_TOP_SENINF2_SEL 39
+#define CLK_TOP_SENINF3_SEL 40
+#define CLK_TOP_TL_SEL 41
+#define CLK_TOP_DXCC_SEL 42
+#define CLK_TOP_AUD_ENGEN1_SEL 43
+#define CLK_TOP_AUD_ENGEN2_SEL 44
+#define CLK_TOP_AES_UFSFDE_SEL 45
+#define CLK_TOP_UFS_SEL 46
+#define CLK_TOP_AUD_1_SEL 47
+#define CLK_TOP_AUD_2_SEL 48
+#define CLK_TOP_ADSP_SEL 49
+#define CLK_TOP_DPMAIF_MAIN_SEL 50
+#define CLK_TOP_VENC_SEL 51
+#define CLK_TOP_VDEC_SEL 52
+#define CLK_TOP_CAMTM_SEL 53
+#define CLK_TOP_PWM_SEL 54
+#define CLK_TOP_AUDIO_H_SEL 55
+#define CLK_TOP_SPMI_MST_SEL 56
+#define CLK_TOP_AES_MSDCFDE_SEL 57
+#define CLK_TOP_SFLASH_SEL 58
+#define CLK_TOP_APLL_I2S0_M_SEL 59
+#define CLK_TOP_APLL_I2S1_M_SEL 60
+#define CLK_TOP_APLL_I2S2_M_SEL 61
+#define CLK_TOP_APLL_I2S3_M_SEL 62
+#define CLK_TOP_APLL_I2S4_M_SEL 63
+#define CLK_TOP_APLL_I2S5_M_SEL 64
+#define CLK_TOP_APLL_I2S6_M_SEL 65
+#define CLK_TOP_APLL_I2S7_M_SEL 66
+#define CLK_TOP_APLL_I2S8_M_SEL 67
+#define CLK_TOP_APLL_I2S9_M_SEL 68
+#define CLK_TOP_MAINPLL_D3 69
+#define CLK_TOP_MAINPLL_D4 70
+#define CLK_TOP_MAINPLL_D4_D2 71
+#define CLK_TOP_MAINPLL_D4_D4 72
+#define CLK_TOP_MAINPLL_D4_D8 73
+#define CLK_TOP_MAINPLL_D4_D16 74
+#define CLK_TOP_MAINPLL_D5 75
+#define CLK_TOP_MAINPLL_D5_D2 76
+#define CLK_TOP_MAINPLL_D5_D4 77
+#define CLK_TOP_MAINPLL_D5_D8 78
+#define CLK_TOP_MAINPLL_D6 79
+#define CLK_TOP_MAINPLL_D6_D2 80
+#define CLK_TOP_MAINPLL_D6_D4 81
+#define CLK_TOP_MAINPLL_D7 82
+#define CLK_TOP_MAINPLL_D7_D2 83
+#define CLK_TOP_MAINPLL_D7_D4 84
+#define CLK_TOP_MAINPLL_D7_D8 85
+#define CLK_TOP_UNIVPLL_D3 86
+#define CLK_TOP_UNIVPLL_D4 87
+#define CLK_TOP_UNIVPLL_D4_D2 88
+#define CLK_TOP_UNIVPLL_D4_D4 89
+#define CLK_TOP_UNIVPLL_D4_D8 90
+#define CLK_TOP_UNIVPLL_D5 91
+#define CLK_TOP_UNIVPLL_D5_D2 92
+#define CLK_TOP_UNIVPLL_D5_D4 93
+#define CLK_TOP_UNIVPLL_D5_D8 94
+#define CLK_TOP_UNIVPLL_D6 95
+#define CLK_TOP_UNIVPLL_D6_D2 96
+#define CLK_TOP_UNIVPLL_D6_D4 97
+#define CLK_TOP_UNIVPLL_D6_D8 98
+#define CLK_TOP_UNIVPLL_D6_D16 99
+#define CLK_TOP_UNIVPLL_D7 100
+#define CLK_TOP_APLL1 101
+#define CLK_TOP_APLL1_D2 102
+#define CLK_TOP_APLL1_D4 103
+#define CLK_TOP_APLL1_D8 104
+#define CLK_TOP_APLL2 105
+#define CLK_TOP_APLL2_D2 106
+#define CLK_TOP_APLL2_D4 107
+#define CLK_TOP_APLL2_D8 108
+#define CLK_TOP_MMPLL_D4 109
+#define CLK_TOP_MMPLL_D4_D2 110
+#define CLK_TOP_MMPLL_D5 111
+#define CLK_TOP_MMPLL_D5_D2 112
+#define CLK_TOP_MMPLL_D6 113
+#define CLK_TOP_MMPLL_D6_D2 114
+#define CLK_TOP_MMPLL_D7 115
+#define CLK_TOP_MMPLL_D9 116
+#define CLK_TOP_APUPLL 117
+#define CLK_TOP_NPUPLL 118
+#define CLK_TOP_TVDPLL 119
+#define CLK_TOP_TVDPLL_D2 120
+#define CLK_TOP_TVDPLL_D4 121
+#define CLK_TOP_TVDPLL_D8 122
+#define CLK_TOP_TVDPLL_D16 123
+#define CLK_TOP_MSDCPLL 124
+#define CLK_TOP_MSDCPLL_D2 125
+#define CLK_TOP_MSDCPLL_D4 126
+#define CLK_TOP_ULPOSC 127
+#define CLK_TOP_OSC_D2 128
+#define CLK_TOP_OSC_D4 129
+#define CLK_TOP_OSC_D8 130
+#define CLK_TOP_OSC_D10 131
+#define CLK_TOP_OSC_D16 132
+#define CLK_TOP_OSC_D20 133
+#define CLK_TOP_CSW_F26M_D2 134
+#define CLK_TOP_ADSPPLL 135
+#define CLK_TOP_UNIVPLL_192M 136
+#define CLK_TOP_UNIVPLL_192M_D2 137
+#define CLK_TOP_UNIVPLL_192M_D4 138
+#define CLK_TOP_UNIVPLL_192M_D8 139
+#define CLK_TOP_UNIVPLL_192M_D16 140
+#define CLK_TOP_UNIVPLL_192M_D32 141
+#define CLK_TOP_APLL12_DIV0 142
+#define CLK_TOP_APLL12_DIV1 143
+#define CLK_TOP_APLL12_DIV2 144
+#define CLK_TOP_APLL12_DIV3 145
+#define CLK_TOP_APLL12_DIV4 146
+#define CLK_TOP_APLL12_DIVB 147
+#define CLK_TOP_APLL12_DIV5 148
+#define CLK_TOP_APLL12_DIV6 149
+#define CLK_TOP_APLL12_DIV7 150
+#define CLK_TOP_APLL12_DIV8 151
+#define CLK_TOP_APLL12_DIV9 152
+#define CLK_TOP_SSUSB_TOP_REF 153
+#define CLK_TOP_SSUSB_PHY_REF 154
+#define CLK_TOP_NR_CLK 155
+
+/* INFRACFG */
+
+#define CLK_INFRA_PMIC_TMR 0
+#define CLK_INFRA_PMIC_AP 1
+#define CLK_INFRA_PMIC_MD 2
+#define CLK_INFRA_PMIC_CONN 3
+#define CLK_INFRA_SCPSYS 4
+#define CLK_INFRA_SEJ 5
+#define CLK_INFRA_APXGPT 6
+#define CLK_INFRA_GCE 7
+#define CLK_INFRA_GCE2 8
+#define CLK_INFRA_THERM 9
+#define CLK_INFRA_I2C0 10
+#define CLK_INFRA_AP_DMA_PSEUDO 11
+#define CLK_INFRA_I2C2 12
+#define CLK_INFRA_I2C3 13
+#define CLK_INFRA_PWM_H 14
+#define CLK_INFRA_PWM1 15
+#define CLK_INFRA_PWM2 16
+#define CLK_INFRA_PWM3 17
+#define CLK_INFRA_PWM4 18
+#define CLK_INFRA_PWM 19
+#define CLK_INFRA_UART0 20
+#define CLK_INFRA_UART1 21
+#define CLK_INFRA_UART2 22
+#define CLK_INFRA_UART3 23
+#define CLK_INFRA_GCE_26M 24
+#define CLK_INFRA_CQ_DMA_FPC 25
+#define CLK_INFRA_BTIF 26
+#define CLK_INFRA_SPI0 27
+#define CLK_INFRA_MSDC0 28
+#define CLK_INFRA_MSDC1 29
+#define CLK_INFRA_MSDC2 30
+#define CLK_INFRA_MSDC0_SRC 31
+#define CLK_INFRA_GCPU 32
+#define CLK_INFRA_TRNG 33
+#define CLK_INFRA_AUXADC 34
+#define CLK_INFRA_CPUM 35
+#define CLK_INFRA_CCIF1_AP 36
+#define CLK_INFRA_CCIF1_MD 37
+#define CLK_INFRA_AUXADC_MD 38
+#define CLK_INFRA_PCIE_TL_26M 39
+#define CLK_INFRA_MSDC1_SRC 40
+#define CLK_INFRA_MSDC2_SRC 41
+#define CLK_INFRA_PCIE_TL_96M 42
+#define CLK_INFRA_PCIE_PL_P_250M 43
+#define CLK_INFRA_DEVICE_APC 44
+#define CLK_INFRA_CCIF_AP 45
+#define CLK_INFRA_DEBUGSYS 46
+#define CLK_INFRA_AUDIO 47
+#define CLK_INFRA_CCIF_MD 48
+#define CLK_INFRA_DXCC_SEC_CORE 49
+#define CLK_INFRA_DXCC_AO 50
+#define CLK_INFRA_DBG_TRACE 51
+#define CLK_INFRA_DEVMPU_B 52
+#define CLK_INFRA_DRAMC_F26M 53
+#define CLK_INFRA_IRTX 54
+#define CLK_INFRA_SSUSB 55
+#define CLK_INFRA_DISP_PWM 56
+#define CLK_INFRA_CLDMA_B 57
+#define CLK_INFRA_AUDIO_26M_B 58
+#define CLK_INFRA_MODEM_TEMP_SHARE 59
+#define CLK_INFRA_SPI1 60
+#define CLK_INFRA_I2C4 61
+#define CLK_INFRA_SPI2 62
+#define CLK_INFRA_SPI3 63
+#define CLK_INFRA_UNIPRO_SYS 64
+#define CLK_INFRA_UNIPRO_TICK 65
+#define CLK_INFRA_UFS_MP_SAP_B 66
+#define CLK_INFRA_MD32_B 67
+#define CLK_INFRA_UNIPRO_MBIST 68
+#define CLK_INFRA_I2C5 69
+#define CLK_INFRA_I2C5_ARBITER 70
+#define CLK_INFRA_I2C5_IMM 71
+#define CLK_INFRA_I2C1_ARBITER 72
+#define CLK_INFRA_I2C1_IMM 73
+#define CLK_INFRA_I2C2_ARBITER 74
+#define CLK_INFRA_I2C2_IMM 75
+#define CLK_INFRA_SPI4 76
+#define CLK_INFRA_SPI5 77
+#define CLK_INFRA_CQ_DMA 78
+#define CLK_INFRA_UFS 79
+#define CLK_INFRA_AES_UFSFDE 80
+#define CLK_INFRA_UFS_TICK 81
+#define CLK_INFRA_SSUSB_XHCI 82
+#define CLK_INFRA_MSDC0_SELF 83
+#define CLK_INFRA_MSDC1_SELF 84
+#define CLK_INFRA_MSDC2_SELF 85
+#define CLK_INFRA_UFS_AXI 86
+#define CLK_INFRA_I2C6 87
+#define CLK_INFRA_AP_MSDC0 88
+#define CLK_INFRA_MD_MSDC0 89
+#define CLK_INFRA_CCIF5_AP 90
+#define CLK_INFRA_CCIF5_MD 91
+#define CLK_INFRA_PCIE_TOP_H_133M 92
+#define CLK_INFRA_FLASHIF_TOP_H_133M 93
+#define CLK_INFRA_PCIE_PERI_26M 94
+#define CLK_INFRA_CCIF2_AP 95
+#define CLK_INFRA_CCIF2_MD 96
+#define CLK_INFRA_CCIF3_AP 97
+#define CLK_INFRA_CCIF3_MD 98
+#define CLK_INFRA_SEJ_F13M 99
+#define CLK_INFRA_AES 100
+#define CLK_INFRA_I2C7 101
+#define CLK_INFRA_I2C8 102
+#define CLK_INFRA_FBIST2FPC 103
+#define CLK_INFRA_DEVICE_APC_SYNC 104
+#define CLK_INFRA_DPMAIF_MAIN 105
+#define CLK_INFRA_PCIE_TL_32K 106
+#define CLK_INFRA_CCIF4_AP 107
+#define CLK_INFRA_CCIF4_MD 108
+#define CLK_INFRA_SPI6 109
+#define CLK_INFRA_SPI7 110
+#define CLK_INFRA_133M 111
+#define CLK_INFRA_66M 112
+#define CLK_INFRA_66M_PERI_BUS 113
+#define CLK_INFRA_FREE_DCM_133M 114
+#define CLK_INFRA_FREE_DCM_66M 115
+#define CLK_INFRA_PERI_BUS_DCM_133M 116
+#define CLK_INFRA_PERI_BUS_DCM_66M 117
+#define CLK_INFRA_FLASHIF_PERI_26M 118
+#define CLK_INFRA_FLASHIF_SFLASH 119
+#define CLK_INFRA_AP_DMA 120
+#define CLK_INFRA_NR_CLK 121
+
+/* PERICFG */
+
+#define CLK_PERI_PERIAXI 0
+#define CLK_PERI_NR_CLK 1
+
+/* APMIXEDSYS */
+
+#define CLK_APMIXED_MAINPLL 0
+#define CLK_APMIXED_UNIVPLL 1
+#define CLK_APMIXED_USBPLL 2
+#define CLK_APMIXED_MSDCPLL 3
+#define CLK_APMIXED_MMPLL 4
+#define CLK_APMIXED_ADSPPLL 5
+#define CLK_APMIXED_MFGPLL 6
+#define CLK_APMIXED_TVDPLL 7
+#define CLK_APMIXED_APLL1 8
+#define CLK_APMIXED_APLL2 9
+#define CLK_APMIXED_MIPID26M 10
+#define CLK_APMIXED_NR_CLK 11
+
+/* SCP_ADSP */
+
+#define CLK_SCP_ADSP_AUDIODSP 0
+#define CLK_SCP_ADSP_NR_CLK 1
+
+/* IMP_IIC_WRAP_C */
+
+#define CLK_IMP_IIC_WRAP_C_I2C10 0
+#define CLK_IMP_IIC_WRAP_C_I2C11 1
+#define CLK_IMP_IIC_WRAP_C_I2C12 2
+#define CLK_IMP_IIC_WRAP_C_I2C13 3
+#define CLK_IMP_IIC_WRAP_C_NR_CLK 4
+
+/* AUDSYS */
+
+#define CLK_AUD_AFE 0
+#define CLK_AUD_22M 1
+#define CLK_AUD_24M 2
+#define CLK_AUD_APLL2_TUNER 3
+#define CLK_AUD_APLL_TUNER 4
+#define CLK_AUD_TDM 5
+#define CLK_AUD_ADC 6
+#define CLK_AUD_DAC 7
+#define CLK_AUD_DAC_PREDIS 8
+#define CLK_AUD_TML 9
+#define CLK_AUD_NLE 10
+#define CLK_AUD_I2S1_B 11
+#define CLK_AUD_I2S2_B 12
+#define CLK_AUD_I2S3_B 13
+#define CLK_AUD_I2S4_B 14
+#define CLK_AUD_CONNSYS_I2S_ASRC 15
+#define CLK_AUD_GENERAL1_ASRC 16
+#define CLK_AUD_GENERAL2_ASRC 17
+#define CLK_AUD_DAC_HIRES 18
+#define CLK_AUD_ADC_HIRES 19
+#define CLK_AUD_ADC_HIRES_TML 20
+#define CLK_AUD_ADDA6_ADC 21
+#define CLK_AUD_ADDA6_ADC_HIRES 22
+#define CLK_AUD_3RD_DAC 23
+#define CLK_AUD_3RD_DAC_PREDIS 24
+#define CLK_AUD_3RD_DAC_TML 25
+#define CLK_AUD_3RD_DAC_HIRES 26
+#define CLK_AUD_I2S5_B 27
+#define CLK_AUD_I2S6_B 28
+#define CLK_AUD_I2S7_B 29
+#define CLK_AUD_I2S8_B 30
+#define CLK_AUD_I2S9_B 31
+#define CLK_AUD_NR_CLK 32
+
+/* IMP_IIC_WRAP_E */
+
+#define CLK_IMP_IIC_WRAP_E_I2C3 0
+#define CLK_IMP_IIC_WRAP_E_NR_CLK 1
+
+/* IMP_IIC_WRAP_S */
+
+#define CLK_IMP_IIC_WRAP_S_I2C7 0
+#define CLK_IMP_IIC_WRAP_S_I2C8 1
+#define CLK_IMP_IIC_WRAP_S_I2C9 2
+#define CLK_IMP_IIC_WRAP_S_NR_CLK 3
+
+/* IMP_IIC_WRAP_WS */
+
+#define CLK_IMP_IIC_WRAP_WS_I2C1 0
+#define CLK_IMP_IIC_WRAP_WS_I2C2 1
+#define CLK_IMP_IIC_WRAP_WS_I2C4 2
+#define CLK_IMP_IIC_WRAP_WS_NR_CLK 3
+
+/* IMP_IIC_WRAP_W */
+
+#define CLK_IMP_IIC_WRAP_W_I2C5 0
+#define CLK_IMP_IIC_WRAP_W_NR_CLK 1
+
+/* IMP_IIC_WRAP_N */
+
+#define CLK_IMP_IIC_WRAP_N_I2C0 0
+#define CLK_IMP_IIC_WRAP_N_I2C6 1
+#define CLK_IMP_IIC_WRAP_N_NR_CLK 2
+
+/* MSDC_TOP */
+
+#define CLK_MSDC_TOP_AES_0P 0
+#define CLK_MSDC_TOP_SRC_0P 1
+#define CLK_MSDC_TOP_SRC_1P 2
+#define CLK_MSDC_TOP_SRC_2P 3
+#define CLK_MSDC_TOP_P_MSDC0 4
+#define CLK_MSDC_TOP_P_MSDC1 5
+#define CLK_MSDC_TOP_P_MSDC2 6
+#define CLK_MSDC_TOP_P_CFG 7
+#define CLK_MSDC_TOP_AXI 8
+#define CLK_MSDC_TOP_H_MST_0P 9
+#define CLK_MSDC_TOP_H_MST_1P 10
+#define CLK_MSDC_TOP_H_MST_2P 11
+#define CLK_MSDC_TOP_MEM_OFF_DLY_26M 12
+#define CLK_MSDC_TOP_32K 13
+#define CLK_MSDC_TOP_AHB2AXI_BRG_AXI 14
+#define CLK_MSDC_TOP_NR_CLK 15
+
+/* MSDC */
+
+#define CLK_MSDC_AXI_WRAP 0
+#define CLK_MSDC_NR_CLK 1
+
+/* MFGCFG */
+
+#define CLK_MFG_BG3D 0
+#define CLK_MFG_NR_CLK 1
+
+/* MMSYS */
+
+#define CLK_MM_DISP_MUTEX0 0
+#define CLK_MM_DISP_CONFIG 1
+#define CLK_MM_DISP_OVL0 2
+#define CLK_MM_DISP_RDMA0 3
+#define CLK_MM_DISP_OVL0_2L 4
+#define CLK_MM_DISP_WDMA0 5
+#define CLK_MM_DISP_UFBC_WDMA0 6
+#define CLK_MM_DISP_RSZ0 7
+#define CLK_MM_DISP_AAL0 8
+#define CLK_MM_DISP_CCORR0 9
+#define CLK_MM_DISP_DITHER0 10
+#define CLK_MM_SMI_INFRA 11
+#define CLK_MM_DISP_GAMMA0 12
+#define CLK_MM_DISP_POSTMASK0 13
+#define CLK_MM_DISP_DSC_WRAP0 14
+#define CLK_MM_DSI0 15
+#define CLK_MM_DISP_COLOR0 16
+#define CLK_MM_SMI_COMMON 17
+#define CLK_MM_DISP_FAKE_ENG0 18
+#define CLK_MM_DISP_FAKE_ENG1 19
+#define CLK_MM_MDP_TDSHP4 20
+#define CLK_MM_MDP_RSZ4 21
+#define CLK_MM_MDP_AAL4 22
+#define CLK_MM_MDP_HDR4 23
+#define CLK_MM_MDP_RDMA4 24
+#define CLK_MM_MDP_COLOR4 25
+#define CLK_MM_DISP_Y2R0 26
+#define CLK_MM_SMI_GALS 27
+#define CLK_MM_DISP_OVL2_2L 28
+#define CLK_MM_DISP_RDMA4 29
+#define CLK_MM_DISP_DPI0 30
+#define CLK_MM_SMI_IOMMU 31
+#define CLK_MM_DSI_DSI0 32
+#define CLK_MM_DPI_DPI0 33
+#define CLK_MM_26MHZ 34
+#define CLK_MM_32KHZ 35
+#define CLK_MM_NR_CLK 36
+
+/* IMGSYS */
+
+#define CLK_IMG_LARB9 0
+#define CLK_IMG_LARB10 1
+#define CLK_IMG_DIP 2
+#define CLK_IMG_GALS 3
+#define CLK_IMG_NR_CLK 4
+
+/* IMGSYS2 */
+
+#define CLK_IMG2_LARB11 0
+#define CLK_IMG2_LARB12 1
+#define CLK_IMG2_MFB 2
+#define CLK_IMG2_WPE 3
+#define CLK_IMG2_MSS 4
+#define CLK_IMG2_GALS 5
+#define CLK_IMG2_NR_CLK 6
+
+/* VDECSYS_SOC */
+
+#define CLK_VDEC_SOC_LARB1 0
+#define CLK_VDEC_SOC_LAT 1
+#define CLK_VDEC_SOC_LAT_ACTIVE 2
+#define CLK_VDEC_SOC_VDEC 3
+#define CLK_VDEC_SOC_VDEC_ACTIVE 4
+#define CLK_VDEC_SOC_NR_CLK 5
+
+/* VDECSYS */
+
+#define CLK_VDEC_LARB1 0
+#define CLK_VDEC_LAT 1
+#define CLK_VDEC_LAT_ACTIVE 2
+#define CLK_VDEC_VDEC 3
+#define CLK_VDEC_ACTIVE 4
+#define CLK_VDEC_NR_CLK 5
+
+/* VENCSYS */
+
+#define CLK_VENC_SET0_LARB 0
+#define CLK_VENC_SET1_VENC 1
+#define CLK_VENC_SET2_JPGENC 2
+#define CLK_VENC_SET5_GALS 3
+#define CLK_VENC_NR_CLK 4
+
+/* CAMSYS */
+
+#define CLK_CAM_LARB13 0
+#define CLK_CAM_DFP_VAD 1
+#define CLK_CAM_LARB14 2
+#define CLK_CAM_CAM 3
+#define CLK_CAM_CAMTG 4
+#define CLK_CAM_SENINF 5
+#define CLK_CAM_CAMSV0 6
+#define CLK_CAM_CAMSV1 7
+#define CLK_CAM_CAMSV2 8
+#define CLK_CAM_CAMSV3 9
+#define CLK_CAM_CCU0 10
+#define CLK_CAM_CCU1 11
+#define CLK_CAM_MRAW0 12
+#define CLK_CAM_FAKE_ENG 13
+#define CLK_CAM_CCU_GALS 14
+#define CLK_CAM_CAM2MM_GALS 15
+#define CLK_CAM_NR_CLK 16
+
+/* CAMSYS_RAWA */
+
+#define CLK_CAM_RAWA_LARBX 0
+#define CLK_CAM_RAWA_CAM 1
+#define CLK_CAM_RAWA_CAMTG 2
+#define CLK_CAM_RAWA_NR_CLK 3
+
+/* CAMSYS_RAWB */
+
+#define CLK_CAM_RAWB_LARBX 0
+#define CLK_CAM_RAWB_CAM 1
+#define CLK_CAM_RAWB_CAMTG 2
+#define CLK_CAM_RAWB_NR_CLK 3
+
+/* CAMSYS_RAWC */
+
+#define CLK_CAM_RAWC_LARBX 0
+#define CLK_CAM_RAWC_CAM 1
+#define CLK_CAM_RAWC_CAMTG 2
+#define CLK_CAM_RAWC_NR_CLK 3
+
+/* IPESYS */
+
+#define CLK_IPE_LARB19 0
+#define CLK_IPE_LARB20 1
+#define CLK_IPE_SMI_SUBCOM 2
+#define CLK_IPE_FD 3
+#define CLK_IPE_FE 4
+#define CLK_IPE_RSC 5
+#define CLK_IPE_DPE 6
+#define CLK_IPE_GALS 7
+#define CLK_IPE_NR_CLK 8
+
+/* MDPSYS */
+
+#define CLK_MDP_RDMA0 0
+#define CLK_MDP_TDSHP0 1
+#define CLK_MDP_IMG_DL_ASYNC0 2
+#define CLK_MDP_IMG_DL_ASYNC1 3
+#define CLK_MDP_RDMA1 4
+#define CLK_MDP_TDSHP1 5
+#define CLK_MDP_SMI0 6
+#define CLK_MDP_APB_BUS 7
+#define CLK_MDP_WROT0 8
+#define CLK_MDP_RSZ0 9
+#define CLK_MDP_HDR0 10
+#define CLK_MDP_MUTEX0 11
+#define CLK_MDP_WROT1 12
+#define CLK_MDP_RSZ1 13
+#define CLK_MDP_HDR1 14
+#define CLK_MDP_FAKE_ENG0 15
+#define CLK_MDP_AAL0 16
+#define CLK_MDP_AAL1 17
+#define CLK_MDP_COLOR0 18
+#define CLK_MDP_COLOR1 19
+#define CLK_MDP_IMG_DL_RELAY0_ASYNC0 20
+#define CLK_MDP_IMG_DL_RELAY1_ASYNC1 21
+#define CLK_MDP_NR_CLK 22
+
+#endif /* _DT_BINDINGS_CLK_MT8192_H */
diff --git a/include/dt-bindings/clock/qcom,dispcc-sc7280.h b/include/dt-bindings/clock/qcom,dispcc-sc7280.h
new file mode 100644
index 000000000000..a4a692c20acf
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,dispcc-sc7280.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_DISP_CC_SC7280_H
+#define _DT_BINDINGS_CLK_QCOM_DISP_CC_SC7280_H
+
+/* DISP_CC clocks */
+#define DISP_CC_PLL0 0
+#define DISP_CC_MDSS_AHB_CLK 1
+#define DISP_CC_MDSS_AHB_CLK_SRC 2
+#define DISP_CC_MDSS_BYTE0_CLK 3
+#define DISP_CC_MDSS_BYTE0_CLK_SRC 4
+#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC 5
+#define DISP_CC_MDSS_BYTE0_INTF_CLK 6
+#define DISP_CC_MDSS_DP_AUX_CLK 7
+#define DISP_CC_MDSS_DP_AUX_CLK_SRC 8
+#define DISP_CC_MDSS_DP_CRYPTO_CLK 9
+#define DISP_CC_MDSS_DP_CRYPTO_CLK_SRC 10
+#define DISP_CC_MDSS_DP_LINK_CLK 11
+#define DISP_CC_MDSS_DP_LINK_CLK_SRC 12
+#define DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC 13
+#define DISP_CC_MDSS_DP_LINK_INTF_CLK 14
+#define DISP_CC_MDSS_DP_PIXEL_CLK 15
+#define DISP_CC_MDSS_DP_PIXEL_CLK_SRC 16
+#define DISP_CC_MDSS_EDP_AUX_CLK 17
+#define DISP_CC_MDSS_EDP_AUX_CLK_SRC 18
+#define DISP_CC_MDSS_EDP_LINK_CLK 19
+#define DISP_CC_MDSS_EDP_LINK_CLK_SRC 20
+#define DISP_CC_MDSS_EDP_LINK_DIV_CLK_SRC 21
+#define DISP_CC_MDSS_EDP_LINK_INTF_CLK 22
+#define DISP_CC_MDSS_EDP_PIXEL_CLK 23
+#define DISP_CC_MDSS_EDP_PIXEL_CLK_SRC 24
+#define DISP_CC_MDSS_ESC0_CLK 25
+#define DISP_CC_MDSS_ESC0_CLK_SRC 26
+#define DISP_CC_MDSS_MDP_CLK 27
+#define DISP_CC_MDSS_MDP_CLK_SRC 28
+#define DISP_CC_MDSS_MDP_LUT_CLK 29
+#define DISP_CC_MDSS_NON_GDSC_AHB_CLK 30
+#define DISP_CC_MDSS_PCLK0_CLK 31
+#define DISP_CC_MDSS_PCLK0_CLK_SRC 32
+#define DISP_CC_MDSS_ROT_CLK 33
+#define DISP_CC_MDSS_ROT_CLK_SRC 34
+#define DISP_CC_MDSS_RSCC_AHB_CLK 35
+#define DISP_CC_MDSS_RSCC_VSYNC_CLK 36
+#define DISP_CC_MDSS_VSYNC_CLK 37
+#define DISP_CC_MDSS_VSYNC_CLK_SRC 38
+#define DISP_CC_SLEEP_CLK 39
+#define DISP_CC_XO_CLK 40
+
+/* DISP_CC power domains */
+#define DISP_CC_MDSS_CORE_GDSC 0
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8953.h b/include/dt-bindings/clock/qcom,gcc-msm8953.h
new file mode 100644
index 000000000000..783162da6148
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-msm8953.h
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_8953_H
+#define _DT_BINDINGS_CLK_MSM_GCC_8953_H
+
+/* Clocks */
+#define APC0_DROOP_DETECTOR_CLK_SRC 0
+#define APC1_DROOP_DETECTOR_CLK_SRC 1
+#define APSS_AHB_CLK_SRC 2
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 3
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 4
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 5
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 6
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 7
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 8
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 9
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 10
+#define BLSP1_UART1_APPS_CLK_SRC 11
+#define BLSP1_UART2_APPS_CLK_SRC 12
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 13
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 14
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 15
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 16
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 17
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 18
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 19
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 20
+#define BLSP2_UART1_APPS_CLK_SRC 21
+#define BLSP2_UART2_APPS_CLK_SRC 22
+#define BYTE0_CLK_SRC 23
+#define BYTE1_CLK_SRC 24
+#define CAMSS_GP0_CLK_SRC 25
+#define CAMSS_GP1_CLK_SRC 26
+#define CAMSS_TOP_AHB_CLK_SRC 27
+#define CCI_CLK_SRC 28
+#define CPP_CLK_SRC 29
+#define CRYPTO_CLK_SRC 30
+#define CSI0PHYTIMER_CLK_SRC 31
+#define CSI0P_CLK_SRC 32
+#define CSI0_CLK_SRC 33
+#define CSI1PHYTIMER_CLK_SRC 34
+#define CSI1P_CLK_SRC 35
+#define CSI1_CLK_SRC 36
+#define CSI2PHYTIMER_CLK_SRC 37
+#define CSI2P_CLK_SRC 38
+#define CSI2_CLK_SRC 39
+#define ESC0_CLK_SRC 40
+#define ESC1_CLK_SRC 41
+#define GCC_APC0_DROOP_DETECTOR_GPLL0_CLK 42
+#define GCC_APC1_DROOP_DETECTOR_GPLL0_CLK 43
+#define GCC_APSS_AHB_CLK 44
+#define GCC_APSS_AXI_CLK 45
+#define GCC_APSS_TCU_ASYNC_CLK 46
+#define GCC_BIMC_GFX_CLK 47
+#define GCC_BIMC_GPU_CLK 48
+#define GCC_BLSP1_AHB_CLK 49
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 50
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 51
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 52
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 53
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 54
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 55
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 56
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 57
+#define GCC_BLSP1_UART1_APPS_CLK 58
+#define GCC_BLSP1_UART2_APPS_CLK 59
+#define GCC_BLSP2_AHB_CLK 60
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 61
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 62
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 63
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 64
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 65
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 66
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 67
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 68
+#define GCC_BLSP2_UART1_APPS_CLK 69
+#define GCC_BLSP2_UART2_APPS_CLK 70
+#define GCC_BOOT_ROM_AHB_CLK 71
+#define GCC_CAMSS_AHB_CLK 72
+#define GCC_CAMSS_CCI_AHB_CLK 73
+#define GCC_CAMSS_CCI_CLK 74
+#define GCC_CAMSS_CPP_AHB_CLK 75
+#define GCC_CAMSS_CPP_AXI_CLK 76
+#define GCC_CAMSS_CPP_CLK 77
+#define GCC_CAMSS_CSI0PHYTIMER_CLK 78
+#define GCC_CAMSS_CSI0PHY_CLK 79
+#define GCC_CAMSS_CSI0PIX_CLK 80
+#define GCC_CAMSS_CSI0RDI_CLK 81
+#define GCC_CAMSS_CSI0_AHB_CLK 82
+#define GCC_CAMSS_CSI0_CLK 83
+#define GCC_CAMSS_CSI0_CSIPHY_3P_CLK 84
+#define GCC_CAMSS_CSI1PHYTIMER_CLK 85
+#define GCC_CAMSS_CSI1PHY_CLK 86
+#define GCC_CAMSS_CSI1PIX_CLK 87
+#define GCC_CAMSS_CSI1RDI_CLK 88
+#define GCC_CAMSS_CSI1_AHB_CLK 89
+#define GCC_CAMSS_CSI1_CLK 90
+#define GCC_CAMSS_CSI1_CSIPHY_3P_CLK 91
+#define GCC_CAMSS_CSI2PHYTIMER_CLK 92
+#define GCC_CAMSS_CSI2PHY_CLK 93
+#define GCC_CAMSS_CSI2PIX_CLK 94
+#define GCC_CAMSS_CSI2RDI_CLK 95
+#define GCC_CAMSS_CSI2_AHB_CLK 96
+#define GCC_CAMSS_CSI2_CLK 97
+#define GCC_CAMSS_CSI2_CSIPHY_3P_CLK 98
+#define GCC_CAMSS_CSI_VFE0_CLK 99
+#define GCC_CAMSS_CSI_VFE1_CLK 100
+#define GCC_CAMSS_GP0_CLK 101
+#define GCC_CAMSS_GP1_CLK 102
+#define GCC_CAMSS_ISPIF_AHB_CLK 103
+#define GCC_CAMSS_JPEG0_CLK 104
+#define GCC_CAMSS_JPEG_AHB_CLK 105
+#define GCC_CAMSS_JPEG_AXI_CLK 106
+#define GCC_CAMSS_MCLK0_CLK 107
+#define GCC_CAMSS_MCLK1_CLK 108
+#define GCC_CAMSS_MCLK2_CLK 109
+#define GCC_CAMSS_MCLK3_CLK 110
+#define GCC_CAMSS_MICRO_AHB_CLK 111
+#define GCC_CAMSS_TOP_AHB_CLK 112
+#define GCC_CAMSS_VFE0_AHB_CLK 113
+#define GCC_CAMSS_VFE0_AXI_CLK 114
+#define GCC_CAMSS_VFE0_CLK 115
+#define GCC_CAMSS_VFE1_AHB_CLK 116
+#define GCC_CAMSS_VFE1_AXI_CLK 117
+#define GCC_CAMSS_VFE1_CLK 118
+#define GCC_CPP_TBU_CLK 119
+#define GCC_CRYPTO_AHB_CLK 120
+#define GCC_CRYPTO_AXI_CLK 121
+#define GCC_CRYPTO_CLK 122
+#define GCC_DCC_CLK 123
+#define GCC_GP1_CLK 124
+#define GCC_GP2_CLK 125
+#define GCC_GP3_CLK 126
+#define GCC_JPEG_TBU_CLK 127
+#define GCC_MDP_TBU_CLK 128
+#define GCC_MDSS_AHB_CLK 129
+#define GCC_MDSS_AXI_CLK 130
+#define GCC_MDSS_BYTE0_CLK 131
+#define GCC_MDSS_BYTE1_CLK 132
+#define GCC_MDSS_ESC0_CLK 133
+#define GCC_MDSS_ESC1_CLK 134
+#define GCC_MDSS_MDP_CLK 135
+#define GCC_MDSS_PCLK0_CLK 136
+#define GCC_MDSS_PCLK1_CLK 137
+#define GCC_MDSS_VSYNC_CLK 138
+#define GCC_MSS_CFG_AHB_CLK 139
+#define GCC_MSS_Q6_BIMC_AXI_CLK 140
+#define GCC_OXILI_AHB_CLK 141
+#define GCC_OXILI_AON_CLK 142
+#define GCC_OXILI_GFX3D_CLK 143
+#define GCC_OXILI_TIMER_CLK 144
+#define GCC_PCNOC_USB3_AXI_CLK 145
+#define GCC_PDM2_CLK 146
+#define GCC_PDM_AHB_CLK 147
+#define GCC_PRNG_AHB_CLK 148
+#define GCC_QDSS_DAP_CLK 149
+#define GCC_QUSB_REF_CLK 150
+#define GCC_RBCPR_GFX_CLK 151
+#define GCC_SDCC1_AHB_CLK 152
+#define GCC_SDCC1_APPS_CLK 153
+#define GCC_SDCC1_ICE_CORE_CLK 154
+#define GCC_SDCC2_AHB_CLK 155
+#define GCC_SDCC2_APPS_CLK 156
+#define GCC_SMMU_CFG_CLK 157
+#define GCC_USB30_MASTER_CLK 158
+#define GCC_USB30_MOCK_UTMI_CLK 159
+#define GCC_USB30_SLEEP_CLK 160
+#define GCC_USB3_AUX_CLK 161
+#define GCC_USB3_PIPE_CLK 162
+#define GCC_USB_PHY_CFG_AHB_CLK 163
+#define GCC_USB_SS_REF_CLK 164
+#define GCC_VENUS0_AHB_CLK 165
+#define GCC_VENUS0_AXI_CLK 166
+#define GCC_VENUS0_CORE0_VCODEC0_CLK 167
+#define GCC_VENUS0_VCODEC0_CLK 168
+#define GCC_VENUS_TBU_CLK 169
+#define GCC_VFE1_TBU_CLK 170
+#define GCC_VFE_TBU_CLK 171
+#define GFX3D_CLK_SRC 172
+#define GP1_CLK_SRC 173
+#define GP2_CLK_SRC 174
+#define GP3_CLK_SRC 175
+#define GPLL0 176
+#define GPLL0_EARLY 177
+#define GPLL2 178
+#define GPLL2_EARLY 179
+#define GPLL3 180
+#define GPLL3_EARLY 181
+#define GPLL4 182
+#define GPLL4_EARLY 183
+#define GPLL6 184
+#define GPLL6_EARLY 185
+#define JPEG0_CLK_SRC 186
+#define MCLK0_CLK_SRC 187
+#define MCLK1_CLK_SRC 188
+#define MCLK2_CLK_SRC 189
+#define MCLK3_CLK_SRC 190
+#define MDP_CLK_SRC 191
+#define PCLK0_CLK_SRC 192
+#define PCLK1_CLK_SRC 193
+#define PDM2_CLK_SRC 194
+#define RBCPR_GFX_CLK_SRC 195
+#define SDCC1_APPS_CLK_SRC 196
+#define SDCC1_ICE_CORE_CLK_SRC 197
+#define SDCC2_APPS_CLK_SRC 198
+#define USB30_MASTER_CLK_SRC 199
+#define USB30_MOCK_UTMI_CLK_SRC 200
+#define USB3_AUX_CLK_SRC 201
+#define VCODEC0_CLK_SRC 202
+#define VFE0_CLK_SRC 203
+#define VFE1_CLK_SRC 204
+#define VSYNC_CLK_SRC 205
+
+/* GCC block resets */
+#define GCC_CAMSS_MICRO_BCR 0
+#define GCC_MSS_BCR 1
+#define GCC_QUSB2_PHY_BCR 2
+#define GCC_USB3PHY_PHY_BCR 3
+#define GCC_USB3_PHY_BCR 4
+#define GCC_USB_30_BCR 5
+
+/* GDSCs */
+#define CPP_GDSC 0
+#define JPEG_GDSC 1
+#define MDSS_GDSC 2
+#define OXILI_CX_GDSC 3
+#define OXILI_GX_GDSC 4
+#define USB30_GDSC 5
+#define VENUS_CORE0_GDSC 6
+#define VENUS_GDSC 7
+#define VFE0_GDSC 8
+#define VFE1_GDSC 9
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,gcc-sc7280.h b/include/dt-bindings/clock/qcom,gcc-sc7280.h
index 4394f15111c6..3d5724b79bff 100644
--- a/include/dt-bindings/clock/qcom,gcc-sc7280.h
+++ b/include/dt-bindings/clock/qcom,gcc-sc7280.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
diff --git a/include/dt-bindings/clock/qcom,gcc-sm6115.h b/include/dt-bindings/clock/qcom,gcc-sm6115.h
new file mode 100644
index 000000000000..b91a7b460433
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-sm6115.h
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SM6115_H
+#define _DT_BINDINGS_CLK_QCOM_GCC_SM6115_H
+
+/* GCC clocks */
+#define GPLL0 0
+#define GPLL0_OUT_AUX2 1
+#define GPLL0_OUT_MAIN 2
+#define GPLL10 3
+#define GPLL10_OUT_MAIN 4
+#define GPLL11 5
+#define GPLL11_OUT_MAIN 6
+#define GPLL3 7
+#define GPLL4 8
+#define GPLL4_OUT_MAIN 9
+#define GPLL6 10
+#define GPLL6_OUT_MAIN 11
+#define GPLL7 12
+#define GPLL7_OUT_MAIN 13
+#define GPLL8 14
+#define GPLL8_OUT_MAIN 15
+#define GPLL9 16
+#define GPLL9_OUT_MAIN 17
+#define GCC_CAMSS_CSI0PHYTIMER_CLK 18
+#define GCC_CAMSS_CSI0PHYTIMER_CLK_SRC 19
+#define GCC_CAMSS_CSI1PHYTIMER_CLK 20
+#define GCC_CAMSS_CSI1PHYTIMER_CLK_SRC 21
+#define GCC_CAMSS_CSI2PHYTIMER_CLK 22
+#define GCC_CAMSS_CSI2PHYTIMER_CLK_SRC 23
+#define GCC_CAMSS_MCLK0_CLK 24
+#define GCC_CAMSS_MCLK0_CLK_SRC 25
+#define GCC_CAMSS_MCLK1_CLK 26
+#define GCC_CAMSS_MCLK1_CLK_SRC 27
+#define GCC_CAMSS_MCLK2_CLK 28
+#define GCC_CAMSS_MCLK2_CLK_SRC 29
+#define GCC_CAMSS_MCLK3_CLK 30
+#define GCC_CAMSS_MCLK3_CLK_SRC 31
+#define GCC_CAMSS_NRT_AXI_CLK 32
+#define GCC_CAMSS_OPE_AHB_CLK 33
+#define GCC_CAMSS_OPE_AHB_CLK_SRC 34
+#define GCC_CAMSS_OPE_CLK 35
+#define GCC_CAMSS_OPE_CLK_SRC 36
+#define GCC_CAMSS_RT_AXI_CLK 37
+#define GCC_CAMSS_TFE_0_CLK 38
+#define GCC_CAMSS_TFE_0_CLK_SRC 39
+#define GCC_CAMSS_TFE_0_CPHY_RX_CLK 40
+#define GCC_CAMSS_TFE_0_CSID_CLK 41
+#define GCC_CAMSS_TFE_0_CSID_CLK_SRC 42
+#define GCC_CAMSS_TFE_1_CLK 43
+#define GCC_CAMSS_TFE_1_CLK_SRC 44
+#define GCC_CAMSS_TFE_1_CPHY_RX_CLK 45
+#define GCC_CAMSS_TFE_1_CSID_CLK 46
+#define GCC_CAMSS_TFE_1_CSID_CLK_SRC 47
+#define GCC_CAMSS_TFE_2_CLK 48
+#define GCC_CAMSS_TFE_2_CLK_SRC 49
+#define GCC_CAMSS_TFE_2_CPHY_RX_CLK 50
+#define GCC_CAMSS_TFE_2_CSID_CLK 51
+#define GCC_CAMSS_TFE_2_CSID_CLK_SRC 52
+#define GCC_CAMSS_TFE_CPHY_RX_CLK_SRC 53
+#define GCC_CAMSS_TOP_AHB_CLK 54
+#define GCC_CAMSS_TOP_AHB_CLK_SRC 55
+#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 56
+#define GCC_CPUSS_AHB_CLK 57
+#define GCC_CPUSS_GNOC_CLK 60
+#define GCC_DISP_AHB_CLK 61
+#define GCC_DISP_GPLL0_DIV_CLK_SRC 62
+#define GCC_DISP_HF_AXI_CLK 63
+#define GCC_DISP_THROTTLE_CORE_CLK 64
+#define GCC_DISP_XO_CLK 65
+#define GCC_GP1_CLK 66
+#define GCC_GP1_CLK_SRC 67
+#define GCC_GP2_CLK 68
+#define GCC_GP2_CLK_SRC 69
+#define GCC_GP3_CLK 70
+#define GCC_GP3_CLK_SRC 71
+#define GCC_GPU_CFG_AHB_CLK 72
+#define GCC_GPU_GPLL0_CLK_SRC 73
+#define GCC_GPU_GPLL0_DIV_CLK_SRC 74
+#define GCC_GPU_IREF_CLK 75
+#define GCC_GPU_MEMNOC_GFX_CLK 76
+#define GCC_GPU_SNOC_DVM_GFX_CLK 77
+#define GCC_GPU_THROTTLE_CORE_CLK 78
+#define GCC_GPU_THROTTLE_XO_CLK 79
+#define GCC_PDM2_CLK 80
+#define GCC_PDM2_CLK_SRC 81
+#define GCC_PDM_AHB_CLK 82
+#define GCC_PDM_XO4_CLK 83
+#define GCC_PRNG_AHB_CLK 84
+#define GCC_QMIP_CAMERA_NRT_AHB_CLK 85
+#define GCC_QMIP_CAMERA_RT_AHB_CLK 86
+#define GCC_QMIP_DISP_AHB_CLK 87
+#define GCC_QMIP_GPU_CFG_AHB_CLK 88
+#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 89
+#define GCC_QUPV3_WRAP0_CORE_2X_CLK 90
+#define GCC_QUPV3_WRAP0_CORE_CLK 91
+#define GCC_QUPV3_WRAP0_S0_CLK 92
+#define GCC_QUPV3_WRAP0_S0_CLK_SRC 93
+#define GCC_QUPV3_WRAP0_S1_CLK 94
+#define GCC_QUPV3_WRAP0_S1_CLK_SRC 95
+#define GCC_QUPV3_WRAP0_S2_CLK 96
+#define GCC_QUPV3_WRAP0_S2_CLK_SRC 97
+#define GCC_QUPV3_WRAP0_S3_CLK 98
+#define GCC_QUPV3_WRAP0_S3_CLK_SRC 99
+#define GCC_QUPV3_WRAP0_S4_CLK 100
+#define GCC_QUPV3_WRAP0_S4_CLK_SRC 101
+#define GCC_QUPV3_WRAP0_S5_CLK 102
+#define GCC_QUPV3_WRAP0_S5_CLK_SRC 103
+#define GCC_QUPV3_WRAP_0_M_AHB_CLK 104
+#define GCC_QUPV3_WRAP_0_S_AHB_CLK 105
+#define GCC_SDCC1_AHB_CLK 106
+#define GCC_SDCC1_APPS_CLK 107
+#define GCC_SDCC1_APPS_CLK_SRC 108
+#define GCC_SDCC1_ICE_CORE_CLK 109
+#define GCC_SDCC1_ICE_CORE_CLK_SRC 110
+#define GCC_SDCC2_AHB_CLK 111
+#define GCC_SDCC2_APPS_CLK 112
+#define GCC_SDCC2_APPS_CLK_SRC 113
+#define GCC_SYS_NOC_CPUSS_AHB_CLK 114
+#define GCC_SYS_NOC_UFS_PHY_AXI_CLK 115
+#define GCC_SYS_NOC_USB3_PRIM_AXI_CLK 116
+#define GCC_UFS_PHY_AHB_CLK 117
+#define GCC_UFS_PHY_AXI_CLK 118
+#define GCC_UFS_PHY_AXI_CLK_SRC 119
+#define GCC_UFS_PHY_ICE_CORE_CLK 120
+#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 121
+#define GCC_UFS_PHY_PHY_AUX_CLK 122
+#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 123
+#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 124
+#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 125
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK 126
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 127
+#define GCC_USB30_PRIM_MASTER_CLK 128
+#define GCC_USB30_PRIM_MASTER_CLK_SRC 129
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK 130
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 131
+#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 132
+#define GCC_USB30_PRIM_SLEEP_CLK 133
+#define GCC_USB3_PRIM_CLKREF_CLK 134
+#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 135
+#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 136
+#define GCC_USB3_PRIM_PHY_PIPE_CLK 137
+#define GCC_VCODEC0_AXI_CLK 138
+#define GCC_VENUS_AHB_CLK 139
+#define GCC_VENUS_CTL_AXI_CLK 140
+#define GCC_VIDEO_AHB_CLK 141
+#define GCC_VIDEO_AXI0_CLK 142
+#define GCC_VIDEO_THROTTLE_CORE_CLK 143
+#define GCC_VIDEO_VCODEC0_SYS_CLK 144
+#define GCC_VIDEO_VENUS_CLK_SRC 145
+#define GCC_VIDEO_VENUS_CTL_CLK 146
+#define GCC_VIDEO_XO_CLK 147
+#define GCC_AHB2PHY_CSI_CLK 148
+#define GCC_AHB2PHY_USB_CLK 149
+#define GCC_BIMC_GPU_AXI_CLK 150
+#define GCC_BOOT_ROM_AHB_CLK 151
+#define GCC_CAM_THROTTLE_NRT_CLK 152
+#define GCC_CAM_THROTTLE_RT_CLK 153
+#define GCC_CAMERA_AHB_CLK 154
+#define GCC_CAMERA_XO_CLK 155
+#define GCC_CAMSS_AXI_CLK 156
+#define GCC_CAMSS_AXI_CLK_SRC 157
+#define GCC_CAMSS_CAMNOC_ATB_CLK 158
+#define GCC_CAMSS_CAMNOC_NTS_XO_CLK 159
+#define GCC_CAMSS_CCI_0_CLK 160
+#define GCC_CAMSS_CCI_CLK_SRC 161
+#define GCC_CAMSS_CPHY_0_CLK 162
+#define GCC_CAMSS_CPHY_1_CLK 163
+#define GCC_CAMSS_CPHY_2_CLK 164
+#define GCC_UFS_CLKREF_CLK 165
+#define GCC_DISP_GPLL0_CLK_SRC 166
+
+/* GCC resets */
+#define GCC_QUSB2PHY_PRIM_BCR 0
+#define GCC_QUSB2PHY_SEC_BCR 1
+#define GCC_SDCC1_BCR 2
+#define GCC_UFS_PHY_BCR 3
+#define GCC_USB30_PRIM_BCR 4
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR 5
+#define GCC_VCODEC0_BCR 6
+#define GCC_VENUS_BCR 7
+#define GCC_VIDEO_INTERFACE_BCR 8
+#define GCC_USB3PHY_PHY_PRIM_SP0_BCR 9
+#define GCC_USB3_PHY_PRIM_SP0_BCR 10
+#define GCC_SDCC2_BCR 11
+
+/* Indexes for GDSCs */
+#define GCC_CAMSS_TOP_GDSC 0
+#define GCC_UFS_PHY_GDSC 1
+#define GCC_USB30_PRIM_GDSC 2
+#define GCC_VCODEC0_GDSC 3
+#define GCC_VENUS_GDSC 4
+#define HLOS1_VOTE_TURING_MMU_TBU1_GDSC 5
+#define HLOS1_VOTE_TURING_MMU_TBU0_GDSC 6
+#define HLOS1_VOTE_MM_SNOC_MMU_TBU_RT_GDSC 7
+#define HLOS1_VOTE_MM_SNOC_MMU_TBU_NRT_GDSC 8
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,gcc-sm6350.h b/include/dt-bindings/clock/qcom,gcc-sm6350.h
new file mode 100644
index 000000000000..ba584ca33c39
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-sm6350.h
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SM6350_H
+#define _DT_BINDINGS_CLK_QCOM_GCC_SM6350_H
+
+/* GCC clocks */
+#define GPLL0 0
+#define GPLL0_OUT_EVEN 1
+#define GPLL0_OUT_ODD 2
+#define GPLL6 3
+#define GPLL6_OUT_EVEN 4
+#define GPLL7 5
+#define GCC_AGGRE_CNOC_PERIPH_CENTER_AHB_CLK 6
+#define GCC_AGGRE_NOC_CENTER_AHB_CLK 7
+#define GCC_AGGRE_NOC_PCIE_SF_AXI_CLK 8
+#define GCC_AGGRE_NOC_PCIE_TBU_CLK 9
+#define GCC_AGGRE_NOC_WLAN_AXI_CLK 10
+#define GCC_AGGRE_UFS_PHY_AXI_CLK 11
+#define GCC_AGGRE_USB3_PRIM_AXI_CLK 12
+#define GCC_BOOT_ROM_AHB_CLK 13
+#define GCC_CAMERA_AHB_CLK 14
+#define GCC_CAMERA_AXI_CLK 15
+#define GCC_CAMERA_THROTTLE_NRT_AXI_CLK 16
+#define GCC_CAMERA_THROTTLE_RT_AXI_CLK 17
+#define GCC_CAMERA_XO_CLK 18
+#define GCC_CE1_AHB_CLK 19
+#define GCC_CE1_AXI_CLK 20
+#define GCC_CE1_CLK 21
+#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 22
+#define GCC_CPUSS_AHB_CLK 23
+#define GCC_CPUSS_AHB_CLK_SRC 24
+#define GCC_CPUSS_AHB_DIV_CLK_SRC 25
+#define GCC_CPUSS_GNOC_CLK 26
+#define GCC_CPUSS_RBCPR_CLK 27
+#define GCC_DDRSS_GPU_AXI_CLK 28
+#define GCC_DISP_AHB_CLK 29
+#define GCC_DISP_AXI_CLK 30
+#define GCC_DISP_CC_SLEEP_CLK 31
+#define GCC_DISP_CC_XO_CLK 32
+#define GCC_DISP_GPLL0_CLK 33
+#define GCC_DISP_THROTTLE_AXI_CLK 34
+#define GCC_DISP_XO_CLK 35
+#define GCC_GP1_CLK 36
+#define GCC_GP1_CLK_SRC 37
+#define GCC_GP2_CLK 38
+#define GCC_GP2_CLK_SRC 39
+#define GCC_GP3_CLK 40
+#define GCC_GP3_CLK_SRC 41
+#define GCC_GPU_CFG_AHB_CLK 42
+#define GCC_GPU_GPLL0_CLK 43
+#define GCC_GPU_GPLL0_DIV_CLK 44
+#define GCC_GPU_MEMNOC_GFX_CLK 45
+#define GCC_GPU_SNOC_DVM_GFX_CLK 46
+#define GCC_NPU_AXI_CLK 47
+#define GCC_NPU_BWMON_AXI_CLK 48
+#define GCC_NPU_BWMON_DMA_CFG_AHB_CLK 49
+#define GCC_NPU_BWMON_DSP_CFG_AHB_CLK 50
+#define GCC_NPU_CFG_AHB_CLK 51
+#define GCC_NPU_DMA_CLK 52
+#define GCC_NPU_GPLL0_CLK 53
+#define GCC_NPU_GPLL0_DIV_CLK 54
+#define GCC_PCIE_0_AUX_CLK 55
+#define GCC_PCIE_0_AUX_CLK_SRC 56
+#define GCC_PCIE_0_CFG_AHB_CLK 57
+#define GCC_PCIE_0_MSTR_AXI_CLK 58
+#define GCC_PCIE_0_PIPE_CLK 59
+#define GCC_PCIE_0_SLV_AXI_CLK 60
+#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 61
+#define GCC_PCIE_PHY_RCHNG_CLK 62
+#define GCC_PCIE_PHY_RCHNG_CLK_SRC 63
+#define GCC_PDM2_CLK 64
+#define GCC_PDM2_CLK_SRC 65
+#define GCC_PDM_AHB_CLK 66
+#define GCC_PDM_XO4_CLK 67
+#define GCC_PRNG_AHB_CLK 68
+#define GCC_QUPV3_WRAP0_CORE_2X_CLK 69
+#define GCC_QUPV3_WRAP0_CORE_CLK 70
+#define GCC_QUPV3_WRAP0_S0_CLK 71
+#define GCC_QUPV3_WRAP0_S0_CLK_SRC 72
+#define GCC_QUPV3_WRAP0_S1_CLK 73
+#define GCC_QUPV3_WRAP0_S1_CLK_SRC 74
+#define GCC_QUPV3_WRAP0_S2_CLK 75
+#define GCC_QUPV3_WRAP0_S2_CLK_SRC 76
+#define GCC_QUPV3_WRAP0_S3_CLK 77
+#define GCC_QUPV3_WRAP0_S3_CLK_SRC 78
+#define GCC_QUPV3_WRAP0_S4_CLK 79
+#define GCC_QUPV3_WRAP0_S4_CLK_SRC 80
+#define GCC_QUPV3_WRAP0_S5_CLK 81
+#define GCC_QUPV3_WRAP0_S5_CLK_SRC 82
+#define GCC_QUPV3_WRAP1_CORE_2X_CLK 83
+#define GCC_QUPV3_WRAP1_CORE_CLK 84
+#define GCC_QUPV3_WRAP1_S0_CLK 85
+#define GCC_QUPV3_WRAP1_S0_CLK_SRC 86
+#define GCC_QUPV3_WRAP1_S1_CLK 87
+#define GCC_QUPV3_WRAP1_S1_CLK_SRC 88
+#define GCC_QUPV3_WRAP1_S2_CLK 89
+#define GCC_QUPV3_WRAP1_S2_CLK_SRC 90
+#define GCC_QUPV3_WRAP1_S3_CLK 91
+#define GCC_QUPV3_WRAP1_S3_CLK_SRC 92
+#define GCC_QUPV3_WRAP1_S4_CLK 93
+#define GCC_QUPV3_WRAP1_S4_CLK_SRC 94
+#define GCC_QUPV3_WRAP1_S5_CLK 95
+#define GCC_QUPV3_WRAP1_S5_CLK_SRC 96
+#define GCC_QUPV3_WRAP_0_M_AHB_CLK 97
+#define GCC_QUPV3_WRAP_0_S_AHB_CLK 98
+#define GCC_QUPV3_WRAP_1_M_AHB_CLK 99
+#define GCC_QUPV3_WRAP_1_S_AHB_CLK 100
+#define GCC_SDCC1_AHB_CLK 101
+#define GCC_SDCC1_APPS_CLK 102
+#define GCC_SDCC1_APPS_CLK_SRC 103
+#define GCC_SDCC1_ICE_CORE_CLK 104
+#define GCC_SDCC1_ICE_CORE_CLK_SRC 105
+#define GCC_SDCC2_AHB_CLK 106
+#define GCC_SDCC2_APPS_CLK 107
+#define GCC_SDCC2_APPS_CLK_SRC 108
+#define GCC_SYS_NOC_CPUSS_AHB_CLK 109
+#define GCC_UFS_MEM_CLKREF_CLK 110
+#define GCC_UFS_PHY_AHB_CLK 111
+#define GCC_UFS_PHY_AXI_CLK 112
+#define GCC_UFS_PHY_AXI_CLK_SRC 113
+#define GCC_UFS_PHY_ICE_CORE_CLK 114
+#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 115
+#define GCC_UFS_PHY_PHY_AUX_CLK 116
+#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 117
+#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 118
+#define GCC_UFS_PHY_RX_SYMBOL_1_CLK 119
+#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 120
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK 121
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 122
+#define GCC_USB30_PRIM_MASTER_CLK 123
+#define GCC_USB30_PRIM_MASTER_CLK_SRC 124
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK 125
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 126
+#define GCC_USB30_PRIM_MOCK_UTMI_DIV_CLK_SRC 127
+#define GCC_USB3_PRIM_CLKREF_CLK 128
+#define GCC_USB30_PRIM_SLEEP_CLK 129
+#define GCC_USB3_PRIM_PHY_AUX_CLK 130
+#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 131
+#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 132
+#define GCC_USB3_PRIM_PHY_PIPE_CLK 133
+#define GCC_VIDEO_AHB_CLK 134
+#define GCC_VIDEO_AXI_CLK 135
+#define GCC_VIDEO_THROTTLE_AXI_CLK 136
+#define GCC_VIDEO_XO_CLK 137
+#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK 138
+#define GCC_UFS_PHY_AXI_HW_CTL_CLK 139
+#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK 140
+#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK 141
+#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK 142
+#define GCC_RX5_PCIE_CLKREF_CLK 143
+#define GCC_GPU_GPLL0_MAIN_DIV_CLK_SRC 144
+#define GCC_NPU_PLL0_MAIN_DIV_CLK_SRC 145
+
+/* GCC resets */
+#define GCC_QUSB2PHY_PRIM_BCR 0
+#define GCC_QUSB2PHY_SEC_BCR 1
+#define GCC_SDCC1_BCR 2
+#define GCC_SDCC2_BCR 3
+#define GCC_UFS_PHY_BCR 4
+#define GCC_USB30_PRIM_BCR 5
+#define GCC_PCIE_0_BCR 6
+#define GCC_PCIE_0_PHY_BCR 7
+#define GCC_QUPV3_WRAPPER_0_BCR 8
+#define GCC_QUPV3_WRAPPER_1_BCR 9
+#define GCC_USB3_PHY_PRIM_BCR 10
+#define GCC_USB3_DP_PHY_PRIM_BCR 11
+
+/* GCC GDSCs */
+#define USB30_PRIM_GDSC 0
+#define UFS_PHY_GDSC 1
+#define HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC 2
+#define HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC 3
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,gpucc-sc7280.h b/include/dt-bindings/clock/qcom,gpucc-sc7280.h
new file mode 100644
index 000000000000..669b23b606ba
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gpucc-sc7280.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SC7280_H
+#define _DT_BINDINGS_CLK_QCOM_GPU_CC_SC7280_H
+
+/* GPU_CC clocks */
+#define GPU_CC_PLL0 0
+#define GPU_CC_PLL1 1
+#define GPU_CC_AHB_CLK 2
+#define GPU_CC_CB_CLK 3
+#define GPU_CC_CRC_AHB_CLK 4
+#define GPU_CC_CX_GMU_CLK 5
+#define GPU_CC_CX_SNOC_DVM_CLK 6
+#define GPU_CC_CXO_AON_CLK 7
+#define GPU_CC_CXO_CLK 8
+#define GPU_CC_GMU_CLK_SRC 9
+#define GPU_CC_GX_GMU_CLK 10
+#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK 11
+#define GPU_CC_HUB_AHB_DIV_CLK_SRC 12
+#define GPU_CC_HUB_AON_CLK 13
+#define GPU_CC_HUB_CLK_SRC 14
+#define GPU_CC_HUB_CX_INT_CLK 15
+#define GPU_CC_HUB_CX_INT_DIV_CLK_SRC 16
+#define GPU_CC_MND1X_0_GFX3D_CLK 17
+#define GPU_CC_MND1X_1_GFX3D_CLK 18
+#define GPU_CC_SLEEP_CLK 19
+
+/* GPU_CC power domains */
+#define GPU_CC_CX_GDSC 0
+#define GPU_CC_GX_GDSC 1
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,mmcc-msm8994.h b/include/dt-bindings/clock/qcom,mmcc-msm8994.h
new file mode 100644
index 000000000000..4b289092f5a2
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,mmcc-msm8994.h
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, Konrad Dybcio
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_MMCC_8994_H
+#define _DT_BINDINGS_CLK_MSM_MMCC_8994_H
+
+/* Clocks */
+#define MMPLL0_EARLY 0
+#define MMPLL0_PLL 1
+#define MMPLL1_EARLY 2
+#define MMPLL1_PLL 3
+#define MMPLL3_EARLY 4
+#define MMPLL3_PLL 5
+#define MMPLL4_EARLY 6
+#define MMPLL4_PLL 7
+#define MMPLL5_EARLY 8
+#define MMPLL5_PLL 9
+#define AXI_CLK_SRC 10
+#define RBBMTIMER_CLK_SRC 11
+#define PCLK0_CLK_SRC 12
+#define PCLK1_CLK_SRC 13
+#define MDP_CLK_SRC 14
+#define VSYNC_CLK_SRC 15
+#define BYTE0_CLK_SRC 16
+#define BYTE1_CLK_SRC 17
+#define ESC0_CLK_SRC 18
+#define ESC1_CLK_SRC 19
+#define MDSS_AHB_CLK 20
+#define MDSS_PCLK0_CLK 21
+#define MDSS_PCLK1_CLK 22
+#define MDSS_VSYNC_CLK 23
+#define MDSS_BYTE0_CLK 24
+#define MDSS_BYTE1_CLK 25
+#define MDSS_ESC0_CLK 26
+#define MDSS_ESC1_CLK 27
+#define CSI0_CLK_SRC 28
+#define CSI1_CLK_SRC 29
+#define CSI2_CLK_SRC 30
+#define CSI3_CLK_SRC 31
+#define VFE0_CLK_SRC 32
+#define VFE1_CLK_SRC 33
+#define CPP_CLK_SRC 34
+#define JPEG0_CLK_SRC 35
+#define JPEG1_CLK_SRC 36
+#define JPEG2_CLK_SRC 37
+#define CSI2PHYTIMER_CLK_SRC 38
+#define FD_CORE_CLK_SRC 39
+#define OCMEMNOC_CLK_SRC 40
+#define CCI_CLK_SRC 41
+#define MMSS_GP0_CLK_SRC 42
+#define MMSS_GP1_CLK_SRC 43
+#define JPEG_DMA_CLK_SRC 44
+#define MCLK0_CLK_SRC 45
+#define MCLK1_CLK_SRC 46
+#define MCLK2_CLK_SRC 47
+#define MCLK3_CLK_SRC 48
+#define CSI0PHYTIMER_CLK_SRC 49
+#define CSI1PHYTIMER_CLK_SRC 50
+#define EXTPCLK_CLK_SRC 51
+#define HDMI_CLK_SRC 52
+#define CAMSS_AHB_CLK 53
+#define CAMSS_CCI_CCI_AHB_CLK 54
+#define CAMSS_CCI_CCI_CLK 55
+#define CAMSS_VFE_CPP_AHB_CLK 56
+#define CAMSS_VFE_CPP_AXI_CLK 57
+#define CAMSS_VFE_CPP_CLK 58
+#define CAMSS_CSI0_AHB_CLK 59
+#define CAMSS_CSI0_CLK 60
+#define CAMSS_CSI0PHY_CLK 61
+#define CAMSS_CSI0PIX_CLK 62
+#define CAMSS_CSI0RDI_CLK 63
+#define CAMSS_CSI1_AHB_CLK 64
+#define CAMSS_CSI1_CLK 65
+#define CAMSS_CSI1PHY_CLK 66
+#define CAMSS_CSI1PIX_CLK 67
+#define CAMSS_CSI1RDI_CLK 68
+#define CAMSS_CSI2_AHB_CLK 69
+#define CAMSS_CSI2_CLK 70
+#define CAMSS_CSI2PHY_CLK 71
+#define CAMSS_CSI2PIX_CLK 72
+#define CAMSS_CSI2RDI_CLK 73
+#define CAMSS_CSI3_AHB_CLK 74
+#define CAMSS_CSI3_CLK 75
+#define CAMSS_CSI3PHY_CLK 76
+#define CAMSS_CSI3PIX_CLK 77
+#define CAMSS_CSI3RDI_CLK 78
+#define CAMSS_CSI_VFE0_CLK 79
+#define CAMSS_CSI_VFE1_CLK 80
+#define CAMSS_GP0_CLK 81
+#define CAMSS_GP1_CLK 82
+#define CAMSS_ISPIF_AHB_CLK 83
+#define CAMSS_JPEG_DMA_CLK 84
+#define CAMSS_JPEG_JPEG0_CLK 85
+#define CAMSS_JPEG_JPEG1_CLK 86
+#define CAMSS_JPEG_JPEG2_CLK 87
+#define CAMSS_JPEG_JPEG_AHB_CLK 88
+#define CAMSS_JPEG_JPEG_AXI_CLK 89
+#define CAMSS_MCLK0_CLK 90
+#define CAMSS_MCLK1_CLK 91
+#define CAMSS_MCLK2_CLK 92
+#define CAMSS_MCLK3_CLK 93
+#define CAMSS_MICRO_AHB_CLK 94
+#define CAMSS_PHY0_CSI0PHYTIMER_CLK 95
+#define CAMSS_PHY1_CSI1PHYTIMER_CLK 96
+#define CAMSS_PHY2_CSI2PHYTIMER_CLK 97
+#define CAMSS_TOP_AHB_CLK 98
+#define CAMSS_VFE_VFE0_CLK 99
+#define CAMSS_VFE_VFE1_CLK 100
+#define CAMSS_VFE_VFE_AHB_CLK 101
+#define CAMSS_VFE_VFE_AXI_CLK 102
+#define FD_AXI_CLK 103
+#define FD_CORE_CLK 104
+#define FD_CORE_UAR_CLK 105
+#define MDSS_AXI_CLK 106
+#define MDSS_EXTPCLK_CLK 107
+#define MDSS_HDMI_AHB_CLK 108
+#define MDSS_HDMI_CLK 109
+#define MDSS_MDP_CLK 110
+#define MMSS_MISC_AHB_CLK 111
+#define MMSS_MMSSNOC_AXI_CLK 112
+#define MMSS_S0_AXI_CLK 113
+#define OCMEMCX_OCMEMNOC_CLK 114
+#define OXILI_GFX3D_CLK 115
+#define OXILI_RBBMTIMER_CLK 116
+#define OXILICX_AHB_CLK 117
+#define VENUS0_AHB_CLK 118
+#define VENUS0_AXI_CLK 119
+#define VENUS0_OCMEMNOC_CLK 120
+#define VENUS0_VCODEC0_CLK 121
+#define VENUS0_CORE0_VCODEC_CLK 122
+#define VENUS0_CORE1_VCODEC_CLK 123
+#define VENUS0_CORE2_VCODEC_CLK 124
+#define AHB_CLK_SRC 125
+#define FD_AHB_CLK 126
+
+/* GDSCs */
+#define VENUS_GDSC 0
+#define VENUS_CORE0_GDSC 1
+#define VENUS_CORE1_GDSC 2
+#define VENUS_CORE2_GDSC 3
+#define CAMSS_TOP_GDSC 4
+#define MDSS_GDSC 5
+#define JPEG_GDSC 6
+#define VFE_GDSC 7
+#define CPP_GDSC 8
+#define OXILI_GX_GDSC 9
+#define OXILI_CX_GDSC 10
+#define FD_GDSC 11
+
+/* Resets */
+#define CAMSS_MICRO_BCR 0
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h
index 8aaba7cd9589..aa834d516234 100644
--- a/include/dt-bindings/clock/qcom,rpmcc.h
+++ b/include/dt-bindings/clock/qcom,rpmcc.h
@@ -149,5 +149,15 @@
#define RPM_SMD_CE2_A_CLK 103
#define RPM_SMD_CE3_CLK 104
#define RPM_SMD_CE3_A_CLK 105
+#define RPM_SMD_QUP_CLK 106
+#define RPM_SMD_QUP_A_CLK 107
+#define RPM_SMD_MMRT_CLK 108
+#define RPM_SMD_MMRT_A_CLK 109
+#define RPM_SMD_MMNRT_CLK 110
+#define RPM_SMD_MMNRT_A_CLK 111
+#define RPM_SMD_SNOC_PERIPH_CLK 112
+#define RPM_SMD_SNOC_PERIPH_A_CLK 113
+#define RPM_SMD_SNOC_LPASS_CLK 114
+#define RPM_SMD_SNOC_LPASS_A_CLK 115
#endif
diff --git a/include/dt-bindings/clock/qcom,rpmh.h b/include/dt-bindings/clock/qcom,rpmh.h
index 583a99161aaa..0a7d1be0d124 100644
--- a/include/dt-bindings/clock/qcom,rpmh.h
+++ b/include/dt-bindings/clock/qcom,rpmh.h
@@ -31,5 +31,7 @@
#define RPMH_RF_CLK5_A 22
#define RPMH_PKA_CLK 23
#define RPMH_HWKM_CLK 24
+#define RPMH_QLINK_CLK 25
+#define RPMH_QLINK_CLK_A 26
#endif
diff --git a/include/dt-bindings/clock/qcom,videocc-sc7280.h b/include/dt-bindings/clock/qcom,videocc-sc7280.h
new file mode 100644
index 000000000000..9e00c3a5f75e
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,videocc-sc7280.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SC7280_H
+#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SC7280_H
+
+/* VIDEO_CC clocks */
+#define VIDEO_PLL0 0
+#define VIDEO_CC_IRIS_AHB_CLK 1
+#define VIDEO_CC_IRIS_CLK_SRC 2
+#define VIDEO_CC_MVS0_AXI_CLK 3
+#define VIDEO_CC_MVS0_CORE_CLK 4
+#define VIDEO_CC_MVSC_CORE_CLK 5
+#define VIDEO_CC_MVSC_CTL_AXI_CLK 6
+#define VIDEO_CC_SLEEP_CLK 7
+#define VIDEO_CC_SLEEP_CLK_SRC 8
+#define VIDEO_CC_VENUS_AHB_CLK 9
+#define VIDEO_CC_XO_CLK 10
+#define VIDEO_CC_XO_CLK_SRC 11
+
+/* VIDEO_CC power domains */
+#define MVS0_GDSC 0
+#define MVSC_GDSC 1
+
+#endif
diff --git a/include/dt-bindings/clock/r9a07g044-cpg.h b/include/dt-bindings/clock/r9a07g044-cpg.h
index 0728ad07ff7a..0bb17ff1a01a 100644
--- a/include/dt-bindings/clock/r9a07g044-cpg.h
+++ b/include/dt-bindings/clock/r9a07g044-cpg.h
@@ -30,6 +30,7 @@
#define R9A07G044_CLK_P2 19
#define R9A07G044_CLK_AT 20
#define R9A07G044_OSCCLK 21
+#define R9A07G044_CLK_P0_DIV2 22
/* R9A07G044 Module Clocks */
#define R9A07G044_CA55_SCLK 0
diff --git a/include/dt-bindings/clock/rk3036-cru.h b/include/dt-bindings/clock/rk3036-cru.h
index 35a5a01f9697..a96a9870ad59 100644
--- a/include/dt-bindings/clock/rk3036-cru.h
+++ b/include/dt-bindings/clock/rk3036-cru.h
@@ -81,6 +81,7 @@
#define HCLK_OTG0 449
#define HCLK_OTG1 450
#define HCLK_NANDC 453
+#define HCLK_SFC 454
#define HCLK_SDMMC 456
#define HCLK_SDIO 457
#define HCLK_EMMC 459
diff --git a/include/dt-bindings/clock/zx296718-clock.h b/include/dt-bindings/clock/zx296718-clock.h
deleted file mode 100644
index bf2ff6d2ee23..000000000000
--- a/include/dt-bindings/clock/zx296718-clock.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2015 - 2016 ZTE Corporation.
- */
-#ifndef __DT_BINDINGS_CLOCK_ZX296718_H
-#define __DT_BINDINGS_CLOCK_ZX296718_H
-
-/* PLL */
-#define ZX296718_PLL_CPU 1
-#define ZX296718_PLL_MAC 2
-#define ZX296718_PLL_MM0 3
-#define ZX296718_PLL_MM1 4
-#define ZX296718_PLL_VGA 5
-#define ZX296718_PLL_DDR 6
-#define ZX296718_PLL_AUDIO 7
-#define ZX296718_PLL_HSIC 8
-#define CPU_DBG_GATE 9
-#define A72_GATE 10
-#define CPU_PERI_GATE 11
-#define A53_GATE 12
-#define DDR1_GATE 13
-#define DDR0_GATE 14
-#define SD1_WCLK 15
-#define SD1_AHB 16
-#define SD0_WCLK 17
-#define SD0_AHB 18
-#define EMMC_WCLK 19
-#define EMMC_NAND_AXI 20
-#define NAND_WCLK 21
-#define EMMC_NAND_AHB 22
-#define LSP1_148M5 23
-#define LSP1_99M 24
-#define LSP1_24M 25
-#define LSP0_74M25 26
-#define LSP0_32K 27
-#define LSP0_148M5 28
-#define LSP0_99M 29
-#define LSP0_24M 30
-#define DEMUX_AXI 31
-#define DEMUX_APB 32
-#define DEMUX_148M5 33
-#define DEMUX_108M 34
-#define AUDIO_APB 35
-#define AUDIO_99M 36
-#define AUDIO_24M 37
-#define AUDIO_16M384 38
-#define AUDIO_32K 39
-#define WDT_WCLK 40
-#define TIMER_WCLK 41
-#define VDE_ACLK 42
-#define VCE_ACLK 43
-#define HDE_ACLK 44
-#define GPU_ACLK 45
-#define SAPPU_ACLK 46
-#define SAPPU_WCLK 47
-#define VOU_ACLK 48
-#define VOU_MAIN_WCLK 49
-#define VOU_AUX_WCLK 50
-#define VOU_PPU_WCLK 51
-#define MIPI_CFG_CLK 52
-#define VGA_I2C_WCLK 53
-#define MIPI_REF_CLK 54
-#define HDMI_OSC_CEC 55
-#define HDMI_OSC_CLK 56
-#define HDMI_XCLK 57
-#define VIU_M0_ACLK 58
-#define VIU_M1_ACLK 59
-#define VIU_WCLK 60
-#define VIU_JPEG_WCLK 61
-#define VIU_CFG_CLK 62
-#define TS_SYS_WCLK 63
-#define TS_SYS_108M 64
-#define USB20_HCLK 65
-#define USB20_PHY_CLK 66
-#define USB21_HCLK 67
-#define USB21_PHY_CLK 68
-#define GMAC_RMIICLK 69
-#define GMAC_PCLK 70
-#define GMAC_ACLK 71
-#define GMAC_RFCLK 72
-#define TEMPSENSOR_GATE 73
-
-#define TOP_NR_CLKS 74
-
-
-#define LSP0_TIMER3_PCLK 1
-#define LSP0_TIMER3_WCLK 2
-#define LSP0_TIMER4_PCLK 3
-#define LSP0_TIMER4_WCLK 4
-#define LSP0_TIMER5_PCLK 5
-#define LSP0_TIMER5_WCLK 6
-#define LSP0_UART3_PCLK 7
-#define LSP0_UART3_WCLK 8
-#define LSP0_UART1_PCLK 9
-#define LSP0_UART1_WCLK 10
-#define LSP0_UART2_PCLK 11
-#define LSP0_UART2_WCLK 12
-#define LSP0_SPIFC0_PCLK 13
-#define LSP0_SPIFC0_WCLK 14
-#define LSP0_I2C4_PCLK 15
-#define LSP0_I2C4_WCLK 16
-#define LSP0_I2C5_PCLK 17
-#define LSP0_I2C5_WCLK 18
-#define LSP0_SSP0_PCLK 19
-#define LSP0_SSP0_WCLK 20
-#define LSP0_SSP1_PCLK 21
-#define LSP0_SSP1_WCLK 22
-#define LSP0_USIM_PCLK 23
-#define LSP0_USIM_WCLK 24
-#define LSP0_GPIO_PCLK 25
-#define LSP0_GPIO_WCLK 26
-#define LSP0_I2C3_PCLK 27
-#define LSP0_I2C3_WCLK 28
-
-#define LSP0_NR_CLKS 29
-
-
-#define LSP1_UART4_PCLK 1
-#define LSP1_UART4_WCLK 2
-#define LSP1_UART5_PCLK 3
-#define LSP1_UART5_WCLK 4
-#define LSP1_PWM_PCLK 5
-#define LSP1_PWM_WCLK 6
-#define LSP1_I2C2_PCLK 7
-#define LSP1_I2C2_WCLK 8
-#define LSP1_SSP2_PCLK 9
-#define LSP1_SSP2_WCLK 10
-#define LSP1_SSP3_PCLK 11
-#define LSP1_SSP3_WCLK 12
-#define LSP1_SSP4_PCLK 13
-#define LSP1_SSP4_WCLK 14
-#define LSP1_USIM1_PCLK 15
-#define LSP1_USIM1_WCLK 16
-
-#define LSP1_NR_CLKS 17
-
-
-#define AUDIO_I2S0_WCLK 1
-#define AUDIO_I2S0_PCLK 2
-#define AUDIO_I2S1_WCLK 3
-#define AUDIO_I2S1_PCLK 4
-#define AUDIO_I2S2_WCLK 5
-#define AUDIO_I2S2_PCLK 6
-#define AUDIO_I2S3_WCLK 7
-#define AUDIO_I2S3_PCLK 8
-#define AUDIO_I2C0_WCLK 9
-#define AUDIO_I2C0_PCLK 10
-#define AUDIO_SPDIF0_WCLK 11
-#define AUDIO_SPDIF0_PCLK 12
-#define AUDIO_SPDIF1_WCLK 13
-#define AUDIO_SPDIF1_PCLK 14
-#define AUDIO_TIMER_WCLK 15
-#define AUDIO_TIMER_PCLK 16
-#define AUDIO_TDM_WCLK 17
-#define AUDIO_TDM_PCLK 18
-#define AUDIO_TS_PCLK 19
-#define I2S0_WCLK_MUX 20
-#define I2S1_WCLK_MUX 21
-#define I2S2_WCLK_MUX 22
-#define I2S3_WCLK_MUX 23
-
-#define AUDIO_NR_CLKS 24
-
-#endif
diff --git a/include/dt-bindings/gce/mt8192-gce.h b/include/dt-bindings/gce/mt8192-gce.h
new file mode 100644
index 000000000000..9e5a0eb040a0
--- /dev/null
+++ b/include/dt-bindings/gce/mt8192-gce.h
@@ -0,0 +1,335 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Yongqiang Niu <yongqiang.niu@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_GCE_MT8192_H
+#define _DT_BINDINGS_GCE_MT8192_H
+
+/* assign timeout 0 also means default */
+#define CMDQ_NO_TIMEOUT 0xffffffff
+#define CMDQ_TIMEOUT_DEFAULT 1000
+
+/* GCE thread priority */
+#define CMDQ_THR_PRIO_LOWEST 0
+#define CMDQ_THR_PRIO_1 1
+#define CMDQ_THR_PRIO_2 2
+#define CMDQ_THR_PRIO_3 3
+#define CMDQ_THR_PRIO_4 4
+#define CMDQ_THR_PRIO_5 5
+#define CMDQ_THR_PRIO_6 6
+#define CMDQ_THR_PRIO_HIGHEST 7
+
+/* CPR count in 32bit register */
+#define GCE_CPR_COUNT 1312
+
+/* GCE subsys table */
+#define SUBSYS_1300XXXX 0
+#define SUBSYS_1400XXXX 1
+#define SUBSYS_1401XXXX 2
+#define SUBSYS_1402XXXX 3
+#define SUBSYS_1502XXXX 4
+#define SUBSYS_1880XXXX 5
+#define SUBSYS_1881XXXX 6
+#define SUBSYS_1882XXXX 7
+#define SUBSYS_1883XXXX 8
+#define SUBSYS_1884XXXX 9
+#define SUBSYS_1000XXXX 10
+#define SUBSYS_1001XXXX 11
+#define SUBSYS_1002XXXX 12
+#define SUBSYS_1003XXXX 13
+#define SUBSYS_1004XXXX 14
+#define SUBSYS_1005XXXX 15
+#define SUBSYS_1020XXXX 16
+#define SUBSYS_1028XXXX 17
+#define SUBSYS_1700XXXX 18
+#define SUBSYS_1701XXXX 19
+#define SUBSYS_1702XXXX 20
+#define SUBSYS_1703XXXX 21
+#define SUBSYS_1800XXXX 22
+#define SUBSYS_1801XXXX 23
+#define SUBSYS_1802XXXX 24
+#define SUBSYS_1804XXXX 25
+#define SUBSYS_1805XXXX 26
+#define SUBSYS_1808XXXX 27
+#define SUBSYS_180aXXXX 28
+#define SUBSYS_180bXXXX 29
+
+#define CMDQ_EVENT_VDEC_LAT_SOF_0 0
+#define CMDQ_EVENT_VDEC_LAT_FRAME_DONE_0 1
+#define CMDQ_EVENT_VDEC_LAT_FRAME_DONE_1 2
+#define CMDQ_EVENT_VDEC_LAT_FRAME_DONE_2 3
+#define CMDQ_EVENT_VDEC_LAT_FRAME_DONE_3 4
+#define CMDQ_EVENT_VDEC_LAT_FRAME_DONE_4 5
+#define CMDQ_EVENT_VDEC_LAT_FRAME_DONE_5 6
+#define CMDQ_EVENT_VDEC_LAT_FRAME_DONE_6 7
+#define CMDQ_EVENT_VDEC_LAT_ENG_EVENT_0 8
+#define CMDQ_EVENT_VDEC_LAT_ENG_EVENT_1 9
+#define CMDQ_EVENT_VDEC_LAT_ENG_EVENT_2 10
+#define CMDQ_EVENT_VDEC_LAT_ENG_EVENT_3 11
+#define CMDQ_EVENT_VDEC_LAT_ENG_EVENT_4 12
+#define CMDQ_EVENT_VDEC_LAT_ENG_EVENT_5 13
+#define CMDQ_EVENT_VDEC_LAT_ENG_EVENT_6 14
+#define CMDQ_EVENT_VDEC_LAT_ENG_EVENT_7 15
+
+#define CMDQ_EVENT_ISP_FRAME_DONE_A 65
+#define CMDQ_EVENT_ISP_FRAME_DONE_B 66
+#define CMDQ_EVENT_ISP_FRAME_DONE_C 67
+#define CMDQ_EVENT_CAMSV0_PASS1_DONE 68
+#define CMDQ_EVENT_CAMSV02_PASS1_DONE 69
+#define CMDQ_EVENT_CAMSV1_PASS1_DONE 70
+#define CMDQ_EVENT_CAMSV2_PASS1_DONE 71
+#define CMDQ_EVENT_CAMSV3_PASS1_DONE 72
+#define CMDQ_EVENT_MRAW_0_PASS1_DONE 73
+#define CMDQ_EVENT_MRAW_1_PASS1_DONE 74
+#define CMDQ_EVENT_SENINF_CAM0_FIFO_FULL 75
+#define CMDQ_EVENT_SENINF_CAM1_FIFO_FULL 76
+#define CMDQ_EVENT_SENINF_CAM2_FIFO_FULL 77
+#define CMDQ_EVENT_SENINF_CAM3_FIFO_FULL 78
+#define CMDQ_EVENT_SENINF_CAM4_FIFO_FULL 79
+#define CMDQ_EVENT_SENINF_CAM5_FIFO_FULL 80
+#define CMDQ_EVENT_SENINF_CAM6_FIFO_FULL 81
+#define CMDQ_EVENT_SENINF_CAM7_FIFO_FULL 82
+#define CMDQ_EVENT_SENINF_CAM8_FIFO_FULL 83
+#define CMDQ_EVENT_SENINF_CAM9_FIFO_FULL 84
+#define CMDQ_EVENT_SENINF_CAM10_FIFO_FULL 85
+#define CMDQ_EVENT_SENINF_CAM11_FIFO_FULL 86
+#define CMDQ_EVENT_SENINF_CAM12_FIFO_FULL 87
+#define CMDQ_EVENT_TG_OVRUN_A_INT 88
+#define CMDQ_EVENT_DMA_R1_ERROR_A_INT 89
+#define CMDQ_EVENT_TG_OVRUN_B_INT 90
+#define CMDQ_EVENT_DMA_R1_ERROR_B_INT 91
+#define CMDQ_EVENT_TG_OVRUN_C_INT 92
+#define CMDQ_EVENT_DMA_R1_ERROR_C_INT 93
+#define CMDQ_EVENT_TG_OVRUN_M0_INT 94
+#define CMDQ_EVENT_DMA_R1_ERROR_M0_INT 95
+#define CMDQ_EVENT_TG_GRABERR_M0_INT 96
+#define CMDQ_EVENT_TG_GRABERR_M1_INT 97
+#define CMDQ_EVENT_TG_GRABERR_A_INT 98
+#define CMDQ_EVENT_CQ_VR_SNAP_A_INT 99
+#define CMDQ_EVENT_TG_GRABERR_B_INT 100
+#define CMDQ_EVENT_CQ_VR_SNAP_B_INT 101
+#define CMDQ_EVENT_TG_GRABERR_C_INT 102
+#define CMDQ_EVENT_CQ_VR_SNAP_C_INT 103
+
+#define CMDQ_EVENT_VENC_CMDQ_FRAME_DONE 129
+#define CMDQ_EVENT_VENC_CMDQ_PAUSE_DONE 130
+#define CMDQ_EVENT_JPGENC_CMDQ_DONE 131
+#define CMDQ_EVENT_VENC_CMDQ_MB_DONE 132
+#define CMDQ_EVENT_VENC_CMDQ_128BYTE_CNT_DONE 133
+#define CMDQ_EVENT_VENC_C0_CMDQ_WP_2ND_STAGE_DONE 134
+#define CMDQ_EVENT_VENC_C0_CMDQ_WP_3RD_STAGE_DONE 135
+#define CMDQ_EVENT_VENC_CMDQ_PPS_DONE 136
+#define CMDQ_EVENT_VENC_CMDQ_SPS_DONE 137
+#define CMDQ_EVENT_VENC_CMDQ_VPS_DONE 138
+
+#define CMDQ_EVENT_VDEC_CORE0_SOF_0 160
+#define CMDQ_EVENT_VDEC_CORE0_FRAME_DONE_0 161
+#define CMDQ_EVENT_VDEC_CORE0_FRAME_DONE_1 162
+#define CMDQ_EVENT_VDEC_CORE0_FRAME_DONE_2 163
+#define CMDQ_EVENT_VDEC_CORE0_FRAME_DONE_3 164
+#define CMDQ_EVENT_VDEC_CORE0_FRAME_DONE_4 165
+#define CMDQ_EVENT_VDEC_CORE0_FRAME_DONE_5 166
+#define CMDQ_EVENT_VDEC_CORE0_FRAME_DONE_6 167
+#define CMDQ_EVENT_VDEC_CORE0_ENG_EVENT_0 168
+#define CMDQ_EVENT_VDEC_CORE0_ENG_EVENT_1 169
+#define CMDQ_EVENT_VDEC_CORE0_ENG_EVENT_2 170
+#define CMDQ_EVENT_VDEC_CORE0_ENG_EVENT_3 171
+#define CMDQ_EVENT_VDEC_CORE0_ENG_EVENT_4 172
+#define CMDQ_EVENT_VDEC_CORE0_ENG_EVENT_5 173
+#define CMDQ_EVENT_VDEC_CORE0_ENG_EVENT_6 174
+#define CMDQ_EVENT_VDEC_CORE0_ENG_EVENT_7 175
+#define CMDQ_EVENT_FDVT_DONE 177
+#define CMDQ_EVENT_FE_DONE 178
+#define CMDQ_EVENT_RSC_DONE 179
+#define CMDQ_EVENT_DVS_DONE_ASYNC_SHOT 180
+#define CMDQ_EVENT_DVP_DONE_ASYNC_SHOT 181
+
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_0 193
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_1 194
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_2 195
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_3 196
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_4 197
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_5 198
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_6 199
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_7 200
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_8 201
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_9 202
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_10 203
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_11 204
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_12 205
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_13 206
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_14 207
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_15 208
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_16 209
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_17 210
+#define CMDQ_EVENT_IMG2_DIP_FRAME_DONE_P2_18 211
+#define CMDQ_EVENT_IMG2_DIP_DMA_ERR_EVENT 212
+#define CMDQ_EVENT_IMG2_AMD_FRAME_DONE 213
+#define CMDQ_EVENT_IMG2_MFB_DONE_LINK_MISC 214
+#define CMDQ_EVENT_IMG2_WPE_A_DONE_LINK_MISC 215
+#define CMDQ_EVENT_IMG2_MSS_DONE_LINK_MISC 216
+
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_0 225
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_1 226
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_2 227
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_3 228
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_4 229
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_5 230
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_6 231
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_7 232
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_8 233
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_9 234
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_10 235
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_11 236
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_12 237
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_13 238
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_14 239
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_15 240
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_16 241
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_17 242
+#define CMDQ_EVENT_IMG1_DIP_FRAME_DONE_P2_18 243
+#define CMDQ_EVENT_IMG1_DIP_DMA_ERR_EVENT 244
+#define CMDQ_EVENT_IMG1_AMD_FRAME_DONE 245
+#define CMDQ_EVENT_IMG1_MFB_DONE_LINK_MISC 246
+#define CMDQ_EVENT_IMG1_WPE_A_DONE_LINK_MISC 247
+#define CMDQ_EVENT_IMG1_MSS_DONE_LINK_MISC 248
+
+#define CMDQ_EVENT_MDP_RDMA0_SOF 256
+#define CMDQ_EVENT_MDP_RDMA1_SOF 257
+#define CMDQ_EVENT_MDP_AAL0_SOF 258
+#define CMDQ_EVENT_MDP_AAL1_SOF 259
+#define CMDQ_EVENT_MDP_HDR0_SOF 260
+#define CMDQ_EVENT_MDP_HDR1_SOF 261
+#define CMDQ_EVENT_MDP_RSZ0_SOF 262
+#define CMDQ_EVENT_MDP_RSZ1_SOF 263
+#define CMDQ_EVENT_MDP_WROT0_SOF 264
+#define CMDQ_EVENT_MDP_WROT1_SOF 265
+#define CMDQ_EVENT_MDP_TDSHP0_SOF 266
+#define CMDQ_EVENT_MDP_TDSHP1_SOF 267
+#define CMDQ_EVENT_IMG_DL_RELAY0_SOF 268
+#define CMDQ_EVENT_IMG_DL_RELAY1_SOF 269
+#define CMDQ_EVENT_MDP_COLOR0_SOF 270
+#define CMDQ_EVENT_MDP_COLOR1_SOF 271
+#define CMDQ_EVENT_MDP_WROT1_FRAME_DONE 290
+#define CMDQ_EVENT_MDP_WROT0_FRAME_DONE 291
+#define CMDQ_EVENT_MDP_TDSHP1_FRAME_DONE 294
+#define CMDQ_EVENT_MDP_TDSHP0_FRAME_DONE 295
+#define CMDQ_EVENT_MDP_RSZ1_FRAME_DONE 302
+#define CMDQ_EVENT_MDP_RSZ0_FRAME_DONE 303
+#define CMDQ_EVENT_MDP_RDMA1_FRAME_DONE 306
+#define CMDQ_EVENT_MDP_RDMA0_FRAME_DONE 307
+#define CMDQ_EVENT_MDP_HDR1_FRAME_DONE 308
+#define CMDQ_EVENT_MDP_HDR0_FRAME_DONE 309
+#define CMDQ_EVENT_MDP_COLOR1_FRAME_DONE 312
+#define CMDQ_EVENT_MDP_COLOR0_FRAME_DONE 313
+#define CMDQ_EVENT_MDP_AAL1_FRAME_DONE 316
+#define CMDQ_EVENT_MDP_AAL0_FRAME_DONE 317
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_0 320
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_1 321
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_2 322
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_3 323
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_4 324
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_5 325
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_6 326
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_7 327
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_8 328
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_9 329
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_10 330
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_11 331
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_12 332
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_13 333
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_14 334
+#define CMDQ_EVENT_MDP_STREAM_DONE_ENG_EVENT_15 335
+#define CMDQ_EVENT_MDP_WROT1_SW_RST_DONE_ENG_EVENT 338
+#define CMDQ_EVENT_MDP_WROT0_SW_RST_DONE_ENG_EVENT 339
+#define CMDQ_EVENT_MDP_RDMA1_SW_RST_DONE_ENG_EVENT 342
+#define CMDQ_EVENT_MDP_RDMA0_SW_RST_DONE_ENG_EVENT 343
+
+#define CMDQ_EVENT_DISP_OVL0_SOF 384
+#define CMDQ_EVENT_DISP_OVL0_2L_SOF 385
+#define CMDQ_EVENT_DISP_RDMA0_SOF 386
+#define CMDQ_EVENT_DISP_RSZ0_SOF 387
+#define CMDQ_EVENT_DISP_COLOR0_SOF 388
+#define CMDQ_EVENT_DISP_CCORR0_SOF 389
+#define CMDQ_EVENT_DISP_AAL0_SOF 390
+#define CMDQ_EVENT_DISP_GAMMA0_SOF 391
+#define CMDQ_EVENT_DISP_POSTMASK0_SOF 392
+#define CMDQ_EVENT_DISP_DITHER0_SOF 393
+#define CMDQ_EVENT_DISP_DSC_WRAP0_CORE0_SOF 394
+#define CMDQ_EVENT_DISP_DSC_WRAP0_CORE1_SOF 395
+#define CMDQ_EVENT_DSI0_SOF 396
+#define CMDQ_EVENT_DISP_WDMA0_SOF 397
+#define CMDQ_EVENT_DISP_UFBC_WDMA0_SOF 398
+#define CMDQ_EVENT_DISP_PWM0_SOF 399
+#define CMDQ_EVENT_DISP_OVL2_2L_SOF 400
+#define CMDQ_EVENT_DISP_RDMA4_SOF 401
+#define CMDQ_EVENT_DISP_DPI0_SOF 402
+#define CMDQ_EVENT_MDP_RDMA4_SOF 403
+#define CMDQ_EVENT_MDP_HDR4_SOF 404
+#define CMDQ_EVENT_MDP_RSZ4_SOF 405
+#define CMDQ_EVENT_MDP_AAL4_SOF 406
+#define CMDQ_EVENT_MDP_TDSHP4_SOF 407
+#define CMDQ_EVENT_MDP_COLOR4_SOF 408
+#define CMDQ_EVENT_DISP_Y2R0_SOF 409
+#define CMDQ_EVENT_MDP_TDSHP4_FRAME_DONE 410
+#define CMDQ_EVENT_MDP_RSZ4_FRAME_DONE 411
+#define CMDQ_EVENT_MDP_RDMA4_FRAME_DONE 412
+#define CMDQ_EVENT_MDP_HDR4_FRAME_DONE 413
+#define CMDQ_EVENT_MDP_COLOR4_FRAME_DONE 414
+#define CMDQ_EVENT_MDP_AAL4_FRAME_DONE 415
+#define CMDQ_EVENT_DSI0_FRAME_DONE 416
+#define CMDQ_EVENT_DISP_WDMA0_FRAME_DONE 417
+#define CMDQ_EVENT_DISP_UFBC_WDMA0_FRAME_DONE 418
+#define CMDQ_EVENT_DISP_RSZ0_FRAME_DONE 419
+#define CMDQ_EVENT_DISP_RDMA4_FRAME_DONE 420
+#define CMDQ_EVENT_DISP_RDMA0_FRAME_DONE 421
+#define CMDQ_EVENT_DISP_POSTMASK0_FRAME_DONE 422
+#define CMDQ_EVENT_DISP_OVL2_2L_FRAME_DONE 423
+#define CMDQ_EVENT_DISP_OVL0_FRAME_DONE 424
+#define CMDQ_EVENT_DISP_OVL0_2L_FRAME_DONE 425
+#define CMDQ_EVENT_DISP_GAMMA0_FRAME_DONE 426
+#define CMDQ_EVENT_DISP_DSC_WRAP0_CORE1_FRAME_DONE 427
+#define CMDQ_EVENT_DISP_DSC_WRAP0_CORE0_FRAME_DONE 428
+#define CMDQ_EVENT_DISP_DPI0_FRAME_DONE 429
+#define CMDQ_EVENT_DISP_DITHER0_FRAME_DONE 430
+#define CMDQ_EVENT_DISP_COLOR0_FRAME_DONE 431
+#define CMDQ_EVENT_DISP_CCORR0_FRAME_DONE 432
+#define CMDQ_EVENT_DISP_AAL0_FRAME_DONE 433
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_0 434
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_1 435
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_2 436
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_3 437
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_4 438
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_5 439
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_6 440
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_7 441
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_8 442
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_9 443
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_10 444
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_11 445
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_12 446
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_13 447
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_14 448
+#define CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_15 449
+#define CMDQ_EVENT_DSI0_TE_ENG_EVENT 450
+#define CMDQ_EVENT_DSI0_IRQ_ENG_EVENT 451
+#define CMDQ_EVENT_DSI0_DONE_ENG_EVENT 452
+#define CMDQ_EVENT_DISP_WDMA0_SW_RST_DONE_ENG_EVENT 453
+#define CMDQ_EVENT_DISP_SMIASSERT_ENG_EVENT 454
+#define CMDQ_EVENT_DISP_POSTMASK0_RST_DONE_ENG_EVENT 455
+#define CMDQ_EVENT_DISP_OVL2_2L_RST_DONE_ENG_EVENT 456
+#define CMDQ_EVENT_DISP_OVL0_RST_DONE_ENG_EVENT 457
+#define CMDQ_EVENT_DISP_OVL0_2L_RST_DONE_ENG_EVENT 458
+#define CMDQ_EVENT_BUF_UNDERRUN_ENG_EVENT_0 459
+#define CMDQ_EVENT_BUF_UNDERRUN_ENG_EVENT_1 460
+#define CMDQ_EVENT_BUF_UNDERRUN_ENG_EVENT_2 461
+#define CMDQ_EVENT_BUF_UNDERRUN_ENG_EVENT_3 462
+#define CMDQ_EVENT_BUF_UNDERRUN_ENG_EVENT_4 463
+#define CMDQ_EVENT_BUF_UNDERRUN_ENG_EVENT_5 464
+#define CMDQ_EVENT_BUF_UNDERRUN_ENG_EVENT_6 465
+#define CMDQ_EVENT_BUF_UNDERRUN_ENG_EVENT_7 466
+#define CMDQ_MAX_HW_EVENT 512
+
+#endif
diff --git a/include/dt-bindings/gce/mt8195-gce.h b/include/dt-bindings/gce/mt8195-gce.h
new file mode 100644
index 000000000000..dcfb302b8a5b
--- /dev/null
+++ b/include/dt-bindings/gce/mt8195-gce.h
@@ -0,0 +1,812 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Jason-JH Lin <jason0jh.lin@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_GCE_MT8195_H
+#define _DT_BINDINGS_GCE_MT8195_H
+
+/* assign timeout 0 also means default */
+#define CMDQ_NO_TIMEOUT 0xffffffff
+#define CMDQ_TIMEOUT_DEFAULT 1000
+
+/* GCE thread priority */
+#define CMDQ_THR_PRIO_LOWEST 0
+#define CMDQ_THR_PRIO_1 1
+#define CMDQ_THR_PRIO_2 2
+#define CMDQ_THR_PRIO_3 3
+#define CMDQ_THR_PRIO_4 4
+#define CMDQ_THR_PRIO_5 5
+#define CMDQ_THR_PRIO_6 6
+#define CMDQ_THR_PRIO_HIGHEST 7
+
+/* CPR count in 32bit register */
+#define GCE_CPR_COUNT 1312
+
+/* GCE subsys table */
+#define SUBSYS_1400XXXX 0
+#define SUBSYS_1401XXXX 1
+#define SUBSYS_1402XXXX 2
+#define SUBSYS_1c00XXXX 3
+#define SUBSYS_1c01XXXX 4
+#define SUBSYS_1c02XXXX 5
+#define SUBSYS_1c10XXXX 6
+#define SUBSYS_1c11XXXX 7
+#define SUBSYS_1c12XXXX 8
+#define SUBSYS_14f0XXXX 9
+#define SUBSYS_14f1XXXX 10
+#define SUBSYS_14f2XXXX 11
+#define SUBSYS_1800XXXX 12
+#define SUBSYS_1801XXXX 13
+#define SUBSYS_1802XXXX 14
+#define SUBSYS_1803XXXX 15
+#define SUBSYS_1032XXXX 16
+#define SUBSYS_1033XXXX 17
+#define SUBSYS_1600XXXX 18
+#define SUBSYS_1601XXXX 19
+#define SUBSYS_14e0XXXX 20
+#define SUBSYS_1c20XXXX 21
+#define SUBSYS_1c30XXXX 22
+#define SUBSYS_1c40XXXX 23
+#define SUBSYS_1c50XXXX 24
+#define SUBSYS_1c60XXXX 25
+
+/* GCE General Purpose Register (GPR) support */
+#define GCE_GPR_R00 0x0
+#define GCE_GPR_R01 0x1
+#define GCE_GPR_R02 0x2
+#define GCE_GPR_R03 0x3
+#define GCE_GPR_R04 0x4
+#define GCE_GPR_R05 0x5
+#define GCE_GPR_R06 0x6
+#define GCE_GPR_R07 0x7
+#define GCE_GPR_R08 0x8
+#define GCE_GPR_R09 0x9
+#define GCE_GPR_R10 0xa
+#define GCE_GPR_R11 0xb
+#define GCE_GPR_R12 0xc
+#define GCE_GPR_R13 0xd
+#define GCE_GPR_R14 0xe
+#define GCE_GPR_R15 0xf
+
+/* GCE hw event id */
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_0 1
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_1 2
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_2 3
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_3 4
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_4 5
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_5 6
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_6 7
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_7 8
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_8 9
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_9 10
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_10 11
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_11 12
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_12 13
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_13 14
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW0_14 15
+#define CMDQ_EVENT_TRAW0_DMA_ERROR_INT 16
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_0 17
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_1 18
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_2 19
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_3 20
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_4 21
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_5 22
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_6 23
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_7 24
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_8 25
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_9 26
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_10 27
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_11 28
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_12 29
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_13 30
+#define CMDQ_EVENT_CQ_THR_DONE_TRAW1_14 31
+#define CMDQ_EVENT_TRAW1_DMA_ERROR_INT 32
+
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_0 65
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_1 66
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_2 67
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_3 68
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_4 69
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_5 70
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_6 71
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_7 72
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_8 73
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_9 74
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_10 75
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_11 76
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_12 77
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_13 78
+#define CMDQ_EVENT_DIP0_FRAME_DONE_P2_14 79
+#define CMDQ_EVENT_DIP0_DMA_ERR 80
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_0 81
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_1 82
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_2 83
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_3 84
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_4 85
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_5 86
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_6 87
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_7 88
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_8 89
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_9 90
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_10 91
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_11 92
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_12 93
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_13 94
+#define CMDQ_EVENT_PQA0_FRAME_DONE_P2_14 95
+#define CMDQ_EVENT_PQA0_DMA_ERR 96
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_0 97
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_1 98
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_2 99
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_3 100
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_4 101
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_5 102
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_6 103
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_7 104
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_8 105
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_9 106
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_10 107
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_11 108
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_12 109
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_13 110
+#define CMDQ_EVENT_PQB0_FRAME_DONE_P2_14 111
+#define CMDQ_EVENT_PQB0_DMA_ERR 112
+#define CMDQ_EVENT_DIP0_DUMMY_0 113
+#define CMDQ_EVENT_DIP0_DUMMY_1 114
+#define CMDQ_EVENT_DIP0_DUMMY_2 115
+#define CMDQ_EVENT_DIP0_DUMMY_3 116
+#define CMDQ_EVENT_WPE0_EIS_GCE_FRAME_DONE 117
+#define CMDQ_EVENT_WPE0_EIS_DONE_SYNC_OUT 118
+#define CMDQ_EVENT_WPE0_TNR_GCE_FRAME_DONE 119
+#define CMDQ_EVENT_WPE0_TNR_DONE_SYNC_OUT 120
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_0 121
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_1 122
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_2 123
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_3 124
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_4 125
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_5 126
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_6 127
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_7 128
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_8 129
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_9 130
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_10 131
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_11 132
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_12 133
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_13 134
+#define CMDQ_EVENT_WPE0_EIS_FRAME_DONE_P2_14 135
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_0 136
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_1 137
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_2 138
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_3 139
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_4 140
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_5 141
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_6 142
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_7 143
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_8 144
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_9 145
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_10 146
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_11 147
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_12 148
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_13 149
+#define CMDQ_EVENT_WPE0_TNR_FRAME_DONE_P2_14 150
+#define CMDQ_EVENT_WPE0_DUMMY_0 151
+#define CMDQ_EVENT_IMGSYS_IPE_DUMMY 152
+#define CMDQ_EVENT_IMGSYS_IPE_FDVT_DONE 153
+#define CMDQ_EVENT_IMGSYS_IPE_ME_DONE 154
+#define CMDQ_EVENT_IMGSYS_IPE_DVS_DONE 155
+#define CMDQ_EVENT_IMGSYS_IPE_DVP_DONE 156
+
+#define CMDQ_EVENT_TPR_0 194
+#define CMDQ_EVENT_TPR_1 195
+#define CMDQ_EVENT_TPR_2 196
+#define CMDQ_EVENT_TPR_3 197
+#define CMDQ_EVENT_TPR_4 198
+#define CMDQ_EVENT_TPR_5 199
+#define CMDQ_EVENT_TPR_6 200
+#define CMDQ_EVENT_TPR_7 201
+#define CMDQ_EVENT_TPR_8 202
+#define CMDQ_EVENT_TPR_9 203
+#define CMDQ_EVENT_TPR_10 204
+#define CMDQ_EVENT_TPR_11 205
+#define CMDQ_EVENT_TPR_12 206
+#define CMDQ_EVENT_TPR_13 207
+#define CMDQ_EVENT_TPR_14 208
+#define CMDQ_EVENT_TPR_15 209
+#define CMDQ_EVENT_TPR_16 210
+#define CMDQ_EVENT_TPR_17 211
+#define CMDQ_EVENT_TPR_18 212
+#define CMDQ_EVENT_TPR_19 213
+#define CMDQ_EVENT_TPR_20 214
+#define CMDQ_EVENT_TPR_21 215
+#define CMDQ_EVENT_TPR_22 216
+#define CMDQ_EVENT_TPR_23 217
+#define CMDQ_EVENT_TPR_24 218
+#define CMDQ_EVENT_TPR_25 219
+#define CMDQ_EVENT_TPR_26 220
+#define CMDQ_EVENT_TPR_27 221
+#define CMDQ_EVENT_TPR_28 222
+#define CMDQ_EVENT_TPR_29 223
+#define CMDQ_EVENT_TPR_30 224
+#define CMDQ_EVENT_TPR_31 225
+#define CMDQ_EVENT_TPR_TIMEOUT_0 226
+#define CMDQ_EVENT_TPR_TIMEOUT_1 227
+#define CMDQ_EVENT_TPR_TIMEOUT_2 228
+#define CMDQ_EVENT_TPR_TIMEOUT_3 229
+#define CMDQ_EVENT_TPR_TIMEOUT_4 230
+#define CMDQ_EVENT_TPR_TIMEOUT_5 231
+#define CMDQ_EVENT_TPR_TIMEOUT_6 232
+#define CMDQ_EVENT_TPR_TIMEOUT_7 233
+#define CMDQ_EVENT_TPR_TIMEOUT_8 234
+#define CMDQ_EVENT_TPR_TIMEOUT_9 235
+#define CMDQ_EVENT_TPR_TIMEOUT_10 236
+#define CMDQ_EVENT_TPR_TIMEOUT_11 237
+#define CMDQ_EVENT_TPR_TIMEOUT_12 238
+#define CMDQ_EVENT_TPR_TIMEOUT_13 239
+#define CMDQ_EVENT_TPR_TIMEOUT_14 240
+#define CMDQ_EVENT_TPR_TIMEOUT_15 241
+
+#define CMDQ_EVENT_VPP0_MDP_RDMA_SOF 256
+#define CMDQ_EVENT_VPP0_MDP_FG_SOF 257
+#define CMDQ_EVENT_VPP0_STITCH_SOF 258
+#define CMDQ_EVENT_VPP0_MDP_HDR_SOF 259
+#define CMDQ_EVENT_VPP0_MDP_AAL_SOF 260
+#define CMDQ_EVENT_VPP0_MDP_RSZ_IN_RSZ_SOF 261
+#define CMDQ_EVENT_VPP0_MDP_TDSHP_SOF 262
+#define CMDQ_EVENT_VPP0_DISP_COLOR_SOF 263
+#define CMDQ_EVENT_VPP0_DISP_OVL_NOAFBC_SOF 264
+#define CMDQ_EVENT_VPP0_VPP_PADDING_IN_PADDING_SOF 265
+#define CMDQ_EVENT_VPP0_MDP_TCC_IN_SOF 266
+#define CMDQ_EVENT_VPP0_MDP_WROT_SOF 267
+
+#define CMDQ_EVENT_VPP0_WARP0_MMSYS_TOP_RELAY_SOF_PRE 269
+#define CMDQ_EVENT_VPP0_WARP1_MMSYS_TOP_RELAY_SOF_PRE 270
+#define CMDQ_EVENT_VPP0_VPP1_MMSYS_TOP_RELAY_SOF 271
+#define CMDQ_EVENT_VPP0_VPP1_IN_MMSYS_TOP_RELAY_SOF_PRE 272
+
+#define CMDQ_EVENT_VPP0_MDP_RDMA_FRAME_DONE 288
+#define CMDQ_EVENT_VPP0_MDP_FG_TILE_DONE 289
+#define CMDQ_EVENT_VPP0_STITCH_FRAME_DONE 290
+#define CMDQ_EVENT_VPP0_MDP_HDR_FRAME_DONE 291
+#define CMDQ_EVENT_VPP0_MDP_AAL_FRAME_DONE 292
+#define CMDQ_EVENT_VPP0_MDP_RSZ_FRAME_DONE 293
+#define CMDQ_EVENT_VPP0_MDP_TDSHP_FRAME_DONE 294
+#define CMDQ_EVENT_VPP0_DISP_COLOR_FRAME_DONE 295
+#define CMDQ_EVENT_VPP0_DISP_OVL_NOAFBC_FRAME_DONE 296
+#define CMDQ_EVENT_VPP0_VPP_PADDING_IN_PADDING_FRAME_DONE 297
+#define CMDQ_EVENT_VPP0_MDP_TCC_TCC_FRAME_DONE 298
+#define CMDQ_EVENT_VPP0_MDP_WROT_VIDO_WDONE 299
+
+#define CMDQ_EVENT_VPP0_STREAM_DONE_0 320
+#define CMDQ_EVENT_VPP0_STREAM_DONE_1 321
+#define CMDQ_EVENT_VPP0_STREAM_DONE_2 322
+#define CMDQ_EVENT_VPP0_STREAM_DONE_3 323
+#define CMDQ_EVENT_VPP0_STREAM_DONE_4 324
+#define CMDQ_EVENT_VPP0_STREAM_DONE_5 325
+#define CMDQ_EVENT_VPP0_STREAM_DONE_6 326
+#define CMDQ_EVENT_VPP0_STREAM_DONE_7 327
+#define CMDQ_EVENT_VPP0_STREAM_DONE_8 328
+#define CMDQ_EVENT_VPP0_STREAM_DONE_9 329
+#define CMDQ_EVENT_VPP0_STREAM_DONE_10 330
+#define CMDQ_EVENT_VPP0_STREAM_DONE_11 331
+#define CMDQ_EVENT_VPP0_STREAM_DONE_12 332
+#define CMDQ_EVENT_VPP0_STREAM_DONE_13 333
+#define CMDQ_EVENT_VPP0_STREAM_DONE_14 334
+#define CMDQ_EVENT_VPP0_STREAM_DONE_15 335
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_0 336
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_1 337
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_2 338
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_3 339
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_4 340
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_5 341
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_6 342
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_7 343
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_8 344
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_9 345
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_10 346
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_11 347
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_12 348
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_13 349
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_14 350
+#define CMDQ_EVENT_VPP0_BUF_UNDERRUN_15 351
+#define CMDQ_EVENT_VPP0_MDP_RDMA_SW_RST_DONE 352
+#define CMDQ_EVENT_VPP0_MDP_RDMA_PM_VALID 353
+#define CMDQ_EVENT_VPP0_DISP_OVL_NOAFBC_FRAME_RESET_DONE_PULSE 354
+#define CMDQ_EVENT_VPP0_MDP_WROT_SW_RST_DONE 355
+
+#define CMDQ_EVENT_VPP1_HDMI_META_SOF 384
+#define CMDQ_EVENT_VPP1_DGI_SOF 385
+#define CMDQ_EVENT_VPP1_VPP_SPLIT_SOF 386
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_TCC_SOF 387
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_RDMA_SOF 388
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_RDMA_SOF 389
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_RDMA_SOF 390
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_FG_SOF 391
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_FG_SOF 392
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_FG_SOF 393
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_HDR_SOF 394
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_HDR_SOF 395
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_HDR_SOF 396
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_AAL_SOF 397
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_AAL_SOF 398
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_AAL_SOF 399
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_RSZ_SOF 400
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_RSZ_SOF 401
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_RSZ_SOF 402
+#define CMDQ_EVENT_VPP1_SVPP1_TDSHP_SOF 403
+#define CMDQ_EVENT_VPP1_SVPP2_TDSHP_SOF 404
+#define CMDQ_EVENT_VPP1_SVPP3_TDSHP_SOF 405
+#define CMDQ_EVENT_VPP1_SVPP2_VPP_MERGE_SOF 406
+#define CMDQ_EVENT_VPP1_SVPP3_VPP_MERGE_SOF 407
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_COLOR_SOF 408
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_COLOR_SOF 409
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_COLOR_SOF 410
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_OVL_SOF 411
+#define CMDQ_EVENT_VPP1_SVPP1_VPP_PAD_SOF 412
+#define CMDQ_EVENT_VPP1_SVPP2_VPP_PAD_SOF 413
+#define CMDQ_EVENT_VPP1_SVPP3_VPP_PAD_SOF 414
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_WROT_SOF 415
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_WROT_SOF 416
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_WROT_SOF 417
+#define CMDQ_EVENT_VPP1_VPP0_DL_IRLY_SOF 418
+#define CMDQ_EVENT_VPP1_VPP0_DL_ORLY_SOF 419
+#define CMDQ_EVENT_VPP1_VDO0_DL_ORLY_0_SOF 420
+#define CMDQ_EVENT_VPP1_VDO0_DL_ORLY_1_SOF 421
+#define CMDQ_EVENT_VPP1_VDO1_DL_ORLY_0_SOF 422
+#define CMDQ_EVENT_VPP1_VDO1_DL_ORLY_1_SOF 423
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_RDMA_FRAME_DONE 424
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_RDMA_FRAME_DONE 425
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_RDMA_FRAME_DONE 426
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_WROT_FRAME_DONE 427
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_WROT_FRAME_DONE 428
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_WROT_FRAME_DONE 429
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_OVL_FRAME_DONE 430
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_RSZ_FRAME_DONE 431
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_RSZ_FRAME_DONE 432
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_RSZ_FRAME_DONE 433
+#define CMDQ_EVENT_VPP1_FRAME_DONE_10 434
+#define CMDQ_EVENT_VPP1_FRAME_DONE_11 435
+#define CMDQ_EVENT_VPP1_FRAME_DONE_12 436
+#define CMDQ_EVENT_VPP1_FRAME_DONE_13 437
+#define CMDQ_EVENT_VPP1_FRAME_DONE_14 438
+#define CMDQ_EVENT_VPP1_STREAM_DONE_0 439
+#define CMDQ_EVENT_VPP1_STREAM_DONE_1 440
+#define CMDQ_EVENT_VPP1_STREAM_DONE_2 441
+#define CMDQ_EVENT_VPP1_STREAM_DONE_3 442
+#define CMDQ_EVENT_VPP1_STREAM_DONE_4 443
+#define CMDQ_EVENT_VPP1_STREAM_DONE_5 444
+#define CMDQ_EVENT_VPP1_STREAM_DONE_6 445
+#define CMDQ_EVENT_VPP1_STREAM_DONE_7 446
+#define CMDQ_EVENT_VPP1_STREAM_DONE_8 447
+#define CMDQ_EVENT_VPP1_STREAM_DONE_9 448
+#define CMDQ_EVENT_VPP1_STREAM_DONE_10 449
+#define CMDQ_EVENT_VPP1_STREAM_DONE_11 450
+#define CMDQ_EVENT_VPP1_STREAM_DONE_12 451
+#define CMDQ_EVENT_VPP1_STREAM_DONE_13 452
+#define CMDQ_EVENT_VPP1_STREAM_DONE_14 453
+#define CMDQ_EVENT_VPP1_STREAM_DONE_15 454
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_0 455
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_1 456
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_2 457
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_3 458
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_4 459
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_5 460
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_6 461
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_7 462
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_8 463
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_9 464
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_10 465
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_11 466
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_12 467
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_13 468
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_14 469
+#define CMDQ_EVENT_VPP1_MDP_BUF_UNDERRUN_15 470
+#define CMDQ_EVENT_VPP1_DGI_0 471
+#define CMDQ_EVENT_VPP1_DGI_1 472
+#define CMDQ_EVENT_VPP1_DGI_2 473
+#define CMDQ_EVENT_VPP1_DGI_3 474
+#define CMDQ_EVENT_VPP1_DGI_4 475
+#define CMDQ_EVENT_VPP1_DGI_5 476
+#define CMDQ_EVENT_VPP1_DGI_6 477
+#define CMDQ_EVENT_VPP1_DGI_7 478
+#define CMDQ_EVENT_VPP1_DGI_8 479
+#define CMDQ_EVENT_VPP1_DGI_9 480
+#define CMDQ_EVENT_VPP1_DGI_10 481
+#define CMDQ_EVENT_VPP1_DGI_11 482
+#define CMDQ_EVENT_VPP1_DGI_12 483
+#define CMDQ_EVENT_VPP1_DGI_13 484
+#define CMDQ_EVENT_VPP1_SVPP3_VPP_MERGE 485
+#define CMDQ_EVENT_VPP1_SVPP2_VPP_MERGE 486
+#define CMDQ_EVENT_VPP1_MDP_OVL_FRAME_RESET_DONE_PULSE 487
+#define CMDQ_EVENT_VPP1_VPP_SPLIT_DGI 488
+#define CMDQ_EVENT_VPP1_VPP_SPLIT_HDMI 489
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_WROT_SW_RST_DONE 490
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_WROT_SW_RST_DONE 491
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_WROT_SW_RST_DONE 492
+#define CMDQ_EVENT_VPP1_SVPP3_MDP_FG_TILE_DONE 493
+#define CMDQ_EVENT_VPP1_SVPP2_MDP_FG_TILE_DONE 494
+#define CMDQ_EVENT_VPP1_SVPP1_MDP_FG_TILE_DONE 495
+
+#define CMDQ_EVENT_VDO0_DISP_OVL0_SOF 512
+#define CMDQ_EVENT_VDO0_DISP_WDMA0_SOF 513
+#define CMDQ_EVENT_VDO0_DISP_RDMA0_SOF 514
+#define CMDQ_EVENT_VDO0_DISP_COLOR0_SOF 515
+#define CMDQ_EVENT_VDO0_DISP_CCORR0_SOF 516
+#define CMDQ_EVENT_VDO0_DISP_AAL0_SOF 517
+#define CMDQ_EVENT_VDO0_DISP_GAMMA0_SOF 518
+#define CMDQ_EVENT_VDO0_DISP_DITHER0_SOF 519
+#define CMDQ_EVENT_VDO0_DSI0_SOF 520
+#define CMDQ_EVENT_VDO0_DSC_WRAP0C0_SOF 521
+#define CMDQ_EVENT_VDO0_DISP_OVL1_SOF 522
+#define CMDQ_EVENT_VDO0_DISP_WDMA1_SOF 523
+#define CMDQ_EVENT_VDO0_DISP_RDMA1_SOF 524
+#define CMDQ_EVENT_VDO0_DISP_COLOR1_SOF 525
+#define CMDQ_EVENT_VDO0_DISP_CCORR1_SOF 526
+#define CMDQ_EVENT_VDO0_DISP_AAL1_SOF 527
+#define CMDQ_EVENT_VDO0_DISP_GAMMA1_SOF 528
+#define CMDQ_EVENT_VDO0_DISP_DITHER1_SOF 529
+#define CMDQ_EVENT_VDO0_DSI1_SOF 530
+#define CMDQ_EVENT_VDO0_DSC_WRAP0C1_SOF 531
+#define CMDQ_EVENT_VDO0_VPP_MERGE0_SOF 532
+#define CMDQ_EVENT_VDO0_DP_INTF0_SOF 533
+#define CMDQ_EVENT_VDO0_VPP1_DL_RELAY0_SOF 534
+#define CMDQ_EVENT_VDO0_VPP1_DL_RELAY1_SOF 535
+#define CMDQ_EVENT_VDO0_VDO1_DL_RELAY2_SOF 536
+#define CMDQ_EVENT_VDO0_VDO0_DL_RELAY3_SOF 537
+#define CMDQ_EVENT_VDO0_VDO0_DL_RELAY4_SOF 538
+#define CMDQ_EVENT_VDO0_DISP_PWM0_SOF 539
+#define CMDQ_EVENT_VDO0_DISP_PWM1_SOF 540
+
+#define CMDQ_EVENT_VDO0_DISP_OVL0_FRAME_DONE 544
+#define CMDQ_EVENT_VDO0_DISP_WDMA0_FRAME_DONE 545
+#define CMDQ_EVENT_VDO0_DISP_RDMA0_FRAME_DONE 546
+#define CMDQ_EVENT_VDO0_DISP_COLOR0_FRAME_DONE 547
+#define CMDQ_EVENT_VDO0_DISP_CCORR0_FRAME_DONE 548
+#define CMDQ_EVENT_VDO0_DISP_AAL0_FRAME_DONE 549
+#define CMDQ_EVENT_VDO0_DISP_GAMMA0_FRAME_DONE 550
+#define CMDQ_EVENT_VDO0_DISP_DITHER0_FRAME_DONE 551
+#define CMDQ_EVENT_VDO0_DSI0_FRAME_DONE 552
+#define CMDQ_EVENT_VDO0_DSC_WRAP0C0_FRAME_DONE 553
+#define CMDQ_EVENT_VDO0_DISP_OVL1_FRAME_DONE 554
+#define CMDQ_EVENT_VDO0_DISP_WDMA1_FRAME_DONE 555
+#define CMDQ_EVENT_VDO0_DISP_RDMA1_FRAME_DONE 556
+#define CMDQ_EVENT_VDO0_DISP_COLOR1_FRAME_DONE 557
+#define CMDQ_EVENT_VDO0_DISP_CCORR1_FRAME_DONE 558
+#define CMDQ_EVENT_VDO0_DISP_AAL1_FRAME_DONE 559
+#define CMDQ_EVENT_VDO0_DISP_GAMMA1_FRAME_DONE 560
+#define CMDQ_EVENT_VDO0_DISP_DITHER1_FRAME_DONE 561
+#define CMDQ_EVENT_VDO0_DSI1_FRAME_DONE 562
+#define CMDQ_EVENT_VDO0_DSC_WRAP0C1_FRAME_DONE 563
+
+#define CMDQ_EVENT_VDO0_DP_INTF0_FRAME_DONE 565
+
+#define CMDQ_EVENT_VDO0_DISP_SMIASSERT_ENG 576
+#define CMDQ_EVENT_VDO0_DSI0_IRQ_ENG_EVENT_MM 577
+#define CMDQ_EVENT_VDO0_DSI0_TE_ENG_EVENT_MM 578
+#define CMDQ_EVENT_VDO0_DSI0_DONE_ENG_EVENT_MM 579
+#define CMDQ_EVENT_VDO0_DSI0_SOF_ENG_EVENT_MM 580
+#define CMDQ_EVENT_VDO0_DSI0_VACTL_ENG_EVENT_MM 581
+#define CMDQ_EVENT_VDO0_DSI1_IRQ_ENG_EVENT_MM 582
+#define CMDQ_EVENT_VDO0_DSI1_TE_ENG_EVENT_MM 583
+#define CMDQ_EVENT_VDO0_DSI1_DONE_ENG_EVENT_MM 584
+#define CMDQ_EVENT_VDO0_DSI1_SOF_ENG_EVENT_MM 585
+#define CMDQ_EVENT_VDO0_DSI1_VACTL_ENG_EVENT_MM 586
+#define CMDQ_EVENT_VDO0_DISP_WDMA0_SW_RST_DONE_ENG 587
+#define CMDQ_EVENT_VDO0_DISP_WDMA1_SW_RST_DONE_ENG 588
+#define CMDQ_EVENT_VDO0_DISP_OVL0_RST_DONE_ENG 589
+#define CMDQ_EVENT_VDO0_DISP_OVL1_RST_DONE_ENG 590
+#define CMDQ_EVENT_VDO0_DP_INTF0_VSYNC_START_ENG_EVENT_MM 591
+#define CMDQ_EVENT_VDO0_DP_INTF0_VSYNC_END_ENG_EVENT_MM 592
+#define CMDQ_EVENT_VDO0_DP_INTF0_VDE_START_ENG_EVENT_MM 593
+#define CMDQ_EVENT_VDO0_DP_INTF0_VDE_END_ENG_EVENT_MM 594
+#define CMDQ_EVENT_VDO0_DP_INTF0_TARGET_LINE_ENG_EVENT_MM 595
+#define CMDQ_EVENT_VDO0_VPP_MERGE0_ENG 596
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_0 597
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_1 598
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_2 599
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_3 600
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_4 601
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_5 602
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_6 603
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_7 604
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_8 605
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_9 606
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_10 607
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_11 608
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_12 609
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_13 610
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_14 611
+#define CMDQ_EVENT_VDO0_DISP_STREAM_DONE_15 612
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_0 613
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_1 614
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_2 615
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_3 616
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_4 617
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_5 618
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_6 619
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_7 620
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_8 621
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_9 622
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_10 623
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_11 624
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_12 625
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_13 626
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_14 627
+#define CMDQ_EVENT_VDO0_DISP_BUF_UNDERRUN_15 628
+
+#define CMDQ_EVENT_VDO1_MDP_RDMA0_SOF 640
+#define CMDQ_EVENT_VDO1_MDP_RDMA1_SOF 641
+#define CMDQ_EVENT_VDO1_MDP_RDMA2_SOF 642
+#define CMDQ_EVENT_VDO1_MDP_RDMA3_SOF 643
+#define CMDQ_EVENT_VDO1_MDP_RDMA4_SOF 644
+#define CMDQ_EVENT_VDO1_MDP_RDMA5_SOF 645
+#define CMDQ_EVENT_VDO1_MDP_RDMA6_SOF 646
+#define CMDQ_EVENT_VDO1_MDP_RDMA7_SOF 647
+#define CMDQ_EVENT_VDO1_VPP_MERGE0_SOF 648
+#define CMDQ_EVENT_VDO1_VPP_MERGE1_SOF 649
+#define CMDQ_EVENT_VDO1_VPP_MERGE2_SOF 650
+#define CMDQ_EVENT_VDO1_VPP_MERGE3_SOF 651
+#define CMDQ_EVENT_VDO1_VPP_MERGE4_SOF 652
+#define CMDQ_EVENT_VDO1_VPP2_DL_RELAY_SOF 653
+#define CMDQ_EVENT_VDO1_VPP3_DL_RELAY_SOF 654
+#define CMDQ_EVENT_VDO1_VDO0_DSC_DL_ASYNC_SOF 655
+#define CMDQ_EVENT_VDO1_VDO0_MERGE_DL_ASYNC_SOF 656
+#define CMDQ_EVENT_VDO1_OUT_DL_RELAY_SOF 657
+#define CMDQ_EVENT_VDO1_DISP_MIXER_SOF 658
+#define CMDQ_EVENT_VDO1_HDR_VDO_FE0_SOF 659
+#define CMDQ_EVENT_VDO1_HDR_VDO_FE1_SOF 660
+#define CMDQ_EVENT_VDO1_HDR_GFX_FE0_SOF 661
+#define CMDQ_EVENT_VDO1_HDR_GFX_FE1_SOF 662
+#define CMDQ_EVENT_VDO1_HDR_VDO_BE0_SOF 663
+#define CMDQ_EVENT_VDO1_HDR_MLOAD_SOF 664
+
+#define CMDQ_EVENT_VDO1_MDP_RDMA0_FRAME_DONE 672
+#define CMDQ_EVENT_VDO1_MDP_RDMA1_FRAME_DONE 673
+#define CMDQ_EVENT_VDO1_MDP_RDMA2_FRAME_DONE 674
+#define CMDQ_EVENT_VDO1_MDP_RDMA3_FRAME_DONE 675
+#define CMDQ_EVENT_VDO1_MDP_RDMA4_FRAME_DONE 676
+#define CMDQ_EVENT_VDO1_MDP_RDMA5_FRAME_DONE 677
+#define CMDQ_EVENT_VDO1_MDP_RDMA6_FRAME_DONE 678
+#define CMDQ_EVENT_VDO1_MDP_RDMA7_FRAME_DONE 679
+#define CMDQ_EVENT_VDO1_VPP_MERGE0_FRAME_DONE 680
+#define CMDQ_EVENT_VDO1_VPP_MERGE1_FRAME_DONE 681
+#define CMDQ_EVENT_VDO1_VPP_MERGE2_FRAME_DONE 682
+#define CMDQ_EVENT_VDO1_VPP_MERGE3_FRAME_DONE 683
+#define CMDQ_EVENT_VDO1_VPP_MERGE4_FRAME_DONE 684
+#define CMDQ_EVENT_VDO1_DPI0_FRAME_DONE 685
+#define CMDQ_EVENT_VDO1_DPI1_FRAME_DONE 686
+#define CMDQ_EVENT_VDO1_DP_INTF0_FRAME_DONE 687
+#define CMDQ_EVENT_VDO1_DISP_MIXER_FRAME_DONE_MM 688
+
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_0 704
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_1 705
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_2 706
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_3 707
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_4 708
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_5 709
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_6 710
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_7 711
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_8 712
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_9 713
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_10 714
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_11 715
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_12 716
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_13 717
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_14 718
+#define CMDQ_EVENT_VDO1_STREAM_DONE_ENG_15 719
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_0 720
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_1 721
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_2 722
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_3 723
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_4 724
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_5 725
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_6 726
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_7 727
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_8 728
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_9 729
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_10 730
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_11 731
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_12 732
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_13 733
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_14 734
+#define CMDQ_EVENT_VDO1_BUF_UNDERRUN_ENG_15 735
+#define CMDQ_EVENT_VDO1_MDP_RDMA0_SW_RST_DONE 736
+#define CMDQ_EVENT_VDO1_MDP_RDMA1_SW_RST_DONE 737
+#define CMDQ_EVENT_VDO1_MDP_RDMA2_SW_RST_DONE 738
+#define CMDQ_EVENT_VDO1_MDP_RDMA3_SW_RST_DONE 739
+#define CMDQ_EVENT_VDO1_MDP_RDMA4_SW_RST_DONE 740
+#define CMDQ_EVENT_VDO1_MDP_RDMA5_SW_RST_DONE 741
+#define CMDQ_EVENT_VDO1_MDP_RDMA6_SW_RST_DONE 742
+#define CMDQ_EVENT_VDO1_MDP_RDMA7_SW_RST_DONE 743
+
+#define CMDQ_EVENT_VDO1_DP0_VDE_END_ENG_EVENT_MM 745
+#define CMDQ_EVENT_VDO1_DP0_VDE_START_ENG_EVENT_MM 746
+#define CMDQ_EVENT_VDO1_DP0_VSYNC_END_ENG_EVENT_MM 747
+#define CMDQ_EVENT_VDO1_DP0_VSYNC_START_ENG_EVENT_MM 748
+#define CMDQ_EVENT_VDO1_DP0_TARGET_LINE_ENG_EVENT_MM 749
+#define CMDQ_EVENT_VDO1_VPP_MERGE0 750
+#define CMDQ_EVENT_VDO1_VPP_MERGE1 751
+#define CMDQ_EVENT_VDO1_VPP_MERGE2 752
+#define CMDQ_EVENT_VDO1_VPP_MERGE3 753
+#define CMDQ_EVENT_VDO1_VPP_MERGE4 754
+#define CMDQ_EVENT_VDO1_HDMITX 755
+#define CMDQ_EVENT_VDO1_HDR_VDO_BE0_ADL_TRIG_EVENT_MM 756
+#define CMDQ_EVENT_VDO1_HDR_GFX_FE1_THDR_ADL_TRIG_EVENT_MM 757
+#define CMDQ_EVENT_VDO1_HDR_GFX_FE1_DM_ADL_TRIG_EVENT_MM 758
+#define CMDQ_EVENT_VDO1_HDR_GFX_FE0_THDR_ADL_TRIG_EVENT_MM 759
+#define CMDQ_EVENT_VDO1_HDR_GFX_FE0_DM_ADL_TRIG_EVENT_MM 760
+#define CMDQ_EVENT_VDO1_HDR_VDO_FE1_ADL_TRIG_EVENT_MM 761
+#define CMDQ_EVENT_VDO1_HDR_VDO_FE1_AD0_TRIG_EVENT_MM 762
+
+#define CMDQ_EVENT_CAM_A_PASS1_DONE 769
+#define CMDQ_EVENT_CAM_B_PASS1_DONE 770
+#define CMDQ_EVENT_GCAMSV_A_PASS1_DONE 771
+#define CMDQ_EVENT_GCAMSV_B_PASS1_DONE 772
+#define CMDQ_EVENT_MRAW_0_PASS1_DONE 773
+#define CMDQ_EVENT_MRAW_1_PASS1_DONE 774
+#define CMDQ_EVENT_MRAW_2_PASS1_DONE 775
+#define CMDQ_EVENT_MRAW_3_PASS1_DONE 776
+#define CMDQ_EVENT_SENINF_CAM0_FIFO_FULL_X 777
+#define CMDQ_EVENT_SENINF_CAM1_FIFO_FULL_X 778
+#define CMDQ_EVENT_SENINF_CAM2_FIFO_FULL 779
+#define CMDQ_EVENT_SENINF_CAM3_FIFO_FULL 780
+#define CMDQ_EVENT_SENINF_CAM4_FIFO_FULL 781
+#define CMDQ_EVENT_SENINF_CAM5_FIFO_FULL 782
+#define CMDQ_EVENT_SENINF_CAM6_FIFO_FULL 783
+#define CMDQ_EVENT_SENINF_CAM7_FIFO_FULL 784
+#define CMDQ_EVENT_SENINF_CAM8_FIFO_FULL 785
+#define CMDQ_EVENT_SENINF_CAM9_FIFO_FULL 786
+#define CMDQ_EVENT_SENINF_CAM10_FIFO_FULL_X 787
+#define CMDQ_EVENT_SENINF_CAM11_FIFO_FULL_X 788
+#define CMDQ_EVENT_SENINF_CAM12_FIFO_FULL_X 789
+#define CMDQ_EVENT_SENINF_CAM13_FIFO_FULL_X 790
+#define CMDQ_EVENT_TG_OVRUN_MRAW0_INT_X0 791
+#define CMDQ_EVENT_TG_OVRUN_MRAW1_INT_X0 792
+#define CMDQ_EVENT_TG_OVRUN_MRAW2_INT 793
+#define CMDQ_EVENT_TG_OVRUN_MRAW3_INT 794
+#define CMDQ_EVENT_DMA_R1_ERROR_MRAW0_INT 795
+#define CMDQ_EVENT_DMA_R1_ERROR_MRAW1_INT 796
+#define CMDQ_EVENT_DMA_R1_ERROR_MRAW2_INT 797
+#define CMDQ_EVENT_DMA_R1_ERROR_MRAW3_INT 798
+#define CMDQ_EVENT_U_CAMSYS_PDA_IRQO_EVENT_DONE_D1 799
+#define CMDQ_EVENT_SUBB_TG_INT4 800
+#define CMDQ_EVENT_SUBB_TG_INT3 801
+#define CMDQ_EVENT_SUBB_TG_INT2 802
+#define CMDQ_EVENT_SUBB_TG_INT1 803
+#define CMDQ_EVENT_SUBA_TG_INT4 804
+#define CMDQ_EVENT_SUBA_TG_INT3 805
+#define CMDQ_EVENT_SUBA_TG_INT2 806
+#define CMDQ_EVENT_SUBA_TG_INT1 807
+#define CMDQ_EVENT_SUBB_DRZS4NO_R1_LOW_LATENCY_LINE_CNT_INT 808
+#define CMDQ_EVENT_SUBB_YUVO_R3_LOW_LATENCY_LINE_CNT_INT 809
+#define CMDQ_EVENT_SUBB_YUVO_R1_LOW_LATENCY_LINE_CNT_INT 810
+#define CMDQ_EVENT_SUBB_IMGO_R1_LOW_LATENCY_LINE_CNT_INT 811
+#define CMDQ_EVENT_SUBA_DRZS4NO_R1_LOW_LATENCY_LINE_CNT_INT 812
+#define CMDQ_EVENT_SUBA_YUVO_R3_LOW_LATENCY_LINE_CNT_INT 813
+#define CMDQ_EVENT_SUBA_YUVO_R1_LOW_LATENCY_LINE_CNT_INT 814
+#define CMDQ_EVENT_SUBA_IMGO_R1_LOW_LATENCY_LINE_CNT_INT 815
+#define CMDQ_EVENT_GCE1_SOF_0 816
+#define CMDQ_EVENT_GCE1_SOF_1 817
+#define CMDQ_EVENT_GCE1_SOF_2 818
+#define CMDQ_EVENT_GCE1_SOF_3 819
+#define CMDQ_EVENT_GCE1_SOF_4 820
+#define CMDQ_EVENT_GCE1_SOF_5 821
+#define CMDQ_EVENT_GCE1_SOF_6 822
+#define CMDQ_EVENT_GCE1_SOF_7 823
+#define CMDQ_EVENT_GCE1_SOF_8 824
+#define CMDQ_EVENT_GCE1_SOF_9 825
+#define CMDQ_EVENT_GCE1_SOF_10 826
+#define CMDQ_EVENT_GCE1_SOF_11 827
+#define CMDQ_EVENT_GCE1_SOF_12 828
+#define CMDQ_EVENT_GCE1_SOF_13 829
+#define CMDQ_EVENT_GCE1_SOF_14 830
+#define CMDQ_EVENT_GCE1_SOF_15 831
+
+#define CMDQ_EVENT_VDEC_LAT_LINE_COUNT_THRESHOLD_INTERRUPT 832
+#define CMDQ_EVENT_VDEC_LAT_VDEC_INT 833
+#define CMDQ_EVENT_VDEC_LAT_VDEC_PAUSE 834
+#define CMDQ_EVENT_VDEC_LAT_VDEC_DEC_ERROR 835
+#define CMDQ_EVENT_VDEC_LAT_MC_BUSY_OVERFLOW_MDEC_TIMEOUT 836
+#define CMDQ_EVENT_VDEC_LAT_VDEC_FRAME_DONE 837
+#define CMDQ_EVENT_VDEC_LAT_INI_FETCH_RDY 838
+#define CMDQ_EVENT_VDEC_LAT_PROCESS_FLAG 839
+#define CMDQ_EVENT_VDEC_LAT_SEARCH_START_CODE_DONE 840
+#define CMDQ_EVENT_VDEC_LAT_REF_REORDER_DONE 841
+#define CMDQ_EVENT_VDEC_LAT_WP_TBLE_DONE 842
+#define CMDQ_EVENT_VDEC_LAT_COUNT_SRAM_CLR_DONE_AND_CTX_SRAM_CLR_DONE 843
+#define CMDQ_EVENT_VDEC_LAT_GCE_CNT_OP_THRESHOLD 847
+
+#define CMDQ_EVENT_VDEC_LAT1_LINE_COUNT_THRESHOLD_INTERRUPT 848
+#define CMDQ_EVENT_VDEC_LAT1_VDEC_INT 849
+#define CMDQ_EVENT_VDEC_LAT1_VDEC_PAUSE 850
+#define CMDQ_EVENT_VDEC_LAT1_VDEC_DEC_ERROR 851
+#define CMDQ_EVENT_VDEC_LAT1_MC_BUSY_OVERFLOW_MDEC_TIMEOUT 852
+#define CMDQ_EVENT_VDEC_LAT1_VDEC_FRAME_DONE 853
+#define CMDQ_EVENT_VDEC_LAT1_INI_FETCH_RDY 854
+#define CMDQ_EVENT_VDEC_LAT1_PROCESS_FLAG 855
+#define CMDQ_EVENT_VDEC_LAT1_SEARCH_START_CODE_DONE 856
+#define CMDQ_EVENT_VDEC_LAT1_REF_REORDER_DONE 857
+#define CMDQ_EVENT_VDEC_LAT1_WP_TBLE_DONE 858
+#define CMDQ_EVENT_VDEC_LAT1_COUNT_SRAM_CLR_DONE_AND_CTX_SRAM_CLR_DONE 859
+#define CMDQ_EVENT_VDEC_LAT1_GCE_CNT_OP_THRESHOLD 863
+
+#define CMDQ_EVENT_VDEC_SOC_GLOBAL_CON_250_0 864
+#define CMDQ_EVENT_VDEC_SOC_GLOBAL_CON_250_1 865
+
+#define CMDQ_EVENT_VDEC_SOC_GLOBAL_CON_250_8 872
+#define CMDQ_EVENT_VDEC_SOC_GLOBAL_CON_250_9 873
+
+#define CMDQ_EVENT_VDEC_CORE_LINE_COUNT_THRESHOLD_INTERRUPT 896
+#define CMDQ_EVENT_VDEC_CORE_VDEC_INT 897
+#define CMDQ_EVENT_VDEC_CORE_VDEC_PAUSE 898
+#define CMDQ_EVENT_VDEC_CORE_VDEC_DEC_ERROR 899
+#define CMDQ_EVENT_VDEC_CORE_MC_BUSY_OVERFLOW_MDEC_TIMEOUT 900
+#define CMDQ_EVENT_VDEC_CORE_VDEC_FRAME_DONE 901
+#define CMDQ_EVENT_VDEC_CORE_INI_FETCH_RDY 902
+#define CMDQ_EVENT_VDEC_CORE_PROCESS_FLAG 903
+#define CMDQ_EVENT_VDEC_CORE_SEARCH_START_CODE_DONE 904
+#define CMDQ_EVENT_VDEC_CORE_REF_REORDER_DONE 905
+#define CMDQ_EVENT_VDEC_CORE_WP_TBLE_DONE 906
+#define CMDQ_EVENT_VDEC_CORE_COUNT_SRAM_CLR_DONE_AND_CTX_SRAM_CLR_DONE 907
+#define CMDQ_EVENT_VDEC_CORE_GCE_CNT_OP_THRESHOLD 911
+
+#define CMDQ_EVENT_VDEC_CORE1_LINE_COUNT_THRESHOLD_INTERRUPT 912
+#define CMDQ_EVENT_VDEC_CORE1_VDEC_INT 913
+#define CMDQ_EVENT_VDEC_CORE1_VDEC_PAUSE 914
+#define CMDQ_EVENT_VDEC_CORE1_VDEC_DEC_ERROR 915
+#define CMDQ_EVENT_VDEC_CORE1_MC_BUSY_OVERFLOW_MDEC_TIMEOUT 916
+#define CMDQ_EVENT_VDEC_CORE1_VDEC_FRAME_DONE 917
+#define CMDQ_EVENT_VDEC_CORE1_INI_FETCH_RDY 918
+#define CMDQ_EVENT_VDEC_CORE1_PROCESS_FLAG 919
+#define CMDQ_EVENT_VDEC_CORE1_SEARCH_START_CODE_DONE 920
+#define CMDQ_EVENT_VDEC_CORE1_REF_REORDER_DONE 921
+#define CMDQ_EVENT_VDEC_CORE1_WP_TBLE_DONE 922
+#define CMDQ_EVENT_VDEC_CORE1_COUNT_SRAM_CLR_DONE_AND_CTX_SRAM_CLR_DONE 923
+#define CMDQ_EVENT_VDEC_CORE1_CNT_OP_THRESHOLD 927
+
+#define CMDQ_EVENT_VENC_TOP_FRAME_DONE 929
+#define CMDQ_EVENT_VENC_TOP_PAUSE_DONE 930
+#define CMDQ_EVENT_VENC_TOP_JPGENC_DONE 931
+#define CMDQ_EVENT_VENC_TOP_MB_DONE 932
+#define CMDQ_EVENT_VENC_TOP_128BYTE_DONE 933
+#define CMDQ_EVENT_VENC_TOP_JPGDEC_DONE 934
+#define CMDQ_EVENT_VENC_TOP_JPGDEC_C1_DONE 935
+#define CMDQ_EVENT_VENC_TOP_JPGDEC_INSUFF_DONE 936
+#define CMDQ_EVENT_VENC_TOP_JPGDEC_C1_INSUFF_DONE 937
+#define CMDQ_EVENT_VENC_TOP_WP_2ND_STAGE_DONE 938
+#define CMDQ_EVENT_VENC_TOP_WP_3RD_STAGE_DONE 939
+#define CMDQ_EVENT_VENC_TOP_PPS_HEADER_DONE 940
+#define CMDQ_EVENT_VENC_TOP_SPS_HEADER_DONE 941
+#define CMDQ_EVENT_VENC_TOP_VPS_HEADER_DONE 942
+
+#define CMDQ_EVENT_VENC_CORE1_TOP_FRAME_DONE 945
+#define CMDQ_EVENT_VENC_CORE1_TOP_PAUSE_DONE 946
+#define CMDQ_EVENT_VENC_CORE1_TOP_JPGENC_DONE 947
+#define CMDQ_EVENT_VENC_CORE1_TOP_MB_DONE 948
+#define CMDQ_EVENT_VENC_CORE1_TOP_128BYTE_DONE 949
+#define CMDQ_EVENT_VENC_CORE1_TOP_JPGDEC_DONE 950
+#define CMDQ_EVENT_VENC_CORE1_TOP_JPGDEC_C1_DONE 951
+#define CMDQ_EVENT_VENC_CORE1_TOP_JPGDEC_INSUFF_DONE 952
+#define CMDQ_EVENT_VENC_CORE1_TOP_JPGDEC_C1_INSUFF_DONE 953
+#define CMDQ_EVENT_VENC_CORE1_TOP_WP_2ND_STAGE_DONE 954
+#define CMDQ_EVENT_VENC_CORE1_TOP_WP_3RD_STAGE_DONE 955
+#define CMDQ_EVENT_VENC_CORE1_TOP_PPS_HEADER_DONE 956
+#define CMDQ_EVENT_VENC_CORE1_TOP_SPS_HEADER_DONE 957
+#define CMDQ_EVENT_VENC_CORE1_TOP_VPS_HEADER_DONE 958
+
+#define CMDQ_EVENT_WPE_VPP0_WPE_GCE_FRAME_DONE 962
+#define CMDQ_EVENT_WPE_VPP0_WPE_DONE_SYNC_OUT 963
+
+#define CMDQ_EVENT_WPE_VPP1_WPE_GCE_FRAME_DONE 969
+#define CMDQ_EVENT_WPE_VPP1_WPE_DONE_SYNC_OUT 970
+
+#define CMDQ_EVENT_DP_TX_VBLANK_FALLING 994
+#define CMDQ_EVENT_DP_TX_VSC_FINISH 995
+
+#define CMDQ_EVENT_OUTPIN_0 1018
+#define CMDQ_EVENT_OUTPIN_1 1019
+
+/* end of hw event */
+#define CMDQ_MAX_HW_EVENT 1019
+
+#endif
diff --git a/include/dt-bindings/iio/adc/ingenic,adc.h b/include/dt-bindings/iio/adc/ingenic,adc.h
index 4627a00e369e..a6ccc031635b 100644
--- a/include/dt-bindings/iio/adc/ingenic,adc.h
+++ b/include/dt-bindings/iio/adc/ingenic,adc.h
@@ -13,5 +13,6 @@
#define INGENIC_ADC_TOUCH_YN 6
#define INGENIC_ADC_TOUCH_XD 7
#define INGENIC_ADC_TOUCH_YD 8
+#define INGENIC_ADC_AUX0 9
#endif
diff --git a/include/dt-bindings/interconnect/qcom,sc8180x.h b/include/dt-bindings/interconnect/qcom,sc8180x.h
new file mode 100644
index 000000000000..235b525d2803
--- /dev/null
+++ b/include/dt-bindings/interconnect/qcom,sc8180x.h
@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Qualcomm SC8180x interconnect IDs
+ *
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_SC8180X_H
+#define __DT_BINDINGS_INTERCONNECT_QCOM_SC8180X_H
+
+#define MASTER_A1NOC_CFG 0
+#define MASTER_UFS_CARD 1
+#define MASTER_UFS_GEN4 2
+#define MASTER_UFS_MEM 3
+#define MASTER_USB3 4
+#define MASTER_USB3_1 5
+#define MASTER_USB3_2 6
+#define A1NOC_SNOC_SLV 7
+#define SLAVE_SERVICE_A1NOC 8
+
+#define MASTER_A2NOC_CFG 0
+#define MASTER_QDSS_BAM 1
+#define MASTER_QSPI_0 2
+#define MASTER_QSPI_1 3
+#define MASTER_QUP_0 4
+#define MASTER_QUP_1 5
+#define MASTER_QUP_2 6
+#define MASTER_SENSORS_AHB 7
+#define MASTER_CRYPTO_CORE_0 8
+#define MASTER_IPA 9
+#define MASTER_EMAC 10
+#define MASTER_PCIE 11
+#define MASTER_PCIE_1 12
+#define MASTER_PCIE_2 13
+#define MASTER_PCIE_3 14
+#define MASTER_QDSS_ETR 15
+#define MASTER_SDCC_2 16
+#define MASTER_SDCC_4 17
+#define A2NOC_SNOC_SLV 18
+#define SLAVE_ANOC_PCIE_GEM_NOC 19
+#define SLAVE_SERVICE_A2NOC 20
+
+#define MASTER_CAMNOC_HF0_UNCOMP 0
+#define MASTER_CAMNOC_HF1_UNCOMP 1
+#define MASTER_CAMNOC_SF_UNCOMP 2
+#define SLAVE_CAMNOC_UNCOMP 3
+
+#define MASTER_NPU 0
+#define SLAVE_CDSP_MEM_NOC 1
+
+#define SNOC_CNOC_MAS 0
+#define SLAVE_A1NOC_CFG 1
+#define SLAVE_A2NOC_CFG 2
+#define SLAVE_AHB2PHY_CENTER 3
+#define SLAVE_AHB2PHY_EAST 4
+#define SLAVE_AHB2PHY_WEST 5
+#define SLAVE_AHB2PHY_SOUTH 6
+#define SLAVE_AOP 7
+#define SLAVE_AOSS 8
+#define SLAVE_CAMERA_CFG 9
+#define SLAVE_CLK_CTL 10
+#define SLAVE_CDSP_CFG 11
+#define SLAVE_RBCPR_CX_CFG 12
+#define SLAVE_RBCPR_MMCX_CFG 13
+#define SLAVE_RBCPR_MX_CFG 14
+#define SLAVE_CRYPTO_0_CFG 15
+#define SLAVE_CNOC_DDRSS 16
+#define SLAVE_DISPLAY_CFG 17
+#define SLAVE_EMAC_CFG 18
+#define SLAVE_GLM 19
+#define SLAVE_GRAPHICS_3D_CFG 20
+#define SLAVE_IMEM_CFG 21
+#define SLAVE_IPA_CFG 22
+#define SLAVE_CNOC_MNOC_CFG 23
+#define SLAVE_NPU_CFG 24
+#define SLAVE_PCIE_0_CFG 25
+#define SLAVE_PCIE_1_CFG 26
+#define SLAVE_PCIE_2_CFG 27
+#define SLAVE_PCIE_3_CFG 28
+#define SLAVE_PDM 29
+#define SLAVE_PIMEM_CFG 30
+#define SLAVE_PRNG 31
+#define SLAVE_QDSS_CFG 32
+#define SLAVE_QSPI_0 33
+#define SLAVE_QSPI_1 34
+#define SLAVE_QUP_1 35
+#define SLAVE_QUP_2 36
+#define SLAVE_QUP_0 37
+#define SLAVE_SDCC_2 38
+#define SLAVE_SDCC_4 39
+#define SLAVE_SECURITY 40
+#define SLAVE_SNOC_CFG 41
+#define SLAVE_SPSS_CFG 42
+#define SLAVE_TCSR 43
+#define SLAVE_TLMM_EAST 44
+#define SLAVE_TLMM_SOUTH 45
+#define SLAVE_TLMM_WEST 46
+#define SLAVE_TSIF 47
+#define SLAVE_UFS_CARD_CFG 48
+#define SLAVE_UFS_MEM_0_CFG 49
+#define SLAVE_UFS_MEM_1_CFG 50
+#define SLAVE_USB3 51
+#define SLAVE_USB3_1 52
+#define SLAVE_USB3_2 53
+#define SLAVE_VENUS_CFG 54
+#define SLAVE_VSENSE_CTRL_CFG 55
+#define SLAVE_SERVICE_CNOC 56
+
+#define MASTER_CNOC_DC_NOC 0
+#define SLAVE_GEM_NOC_CFG 1
+#define SLAVE_LLCC_CFG 2
+
+#define MASTER_AMPSS_M0 0
+#define MASTER_GPU_TCU 1
+#define MASTER_SYS_TCU 2
+#define MASTER_GEM_NOC_CFG 3
+#define MASTER_COMPUTE_NOC 4
+#define MASTER_GRAPHICS_3D 5
+#define MASTER_MNOC_HF_MEM_NOC 6
+#define MASTER_MNOC_SF_MEM_NOC 7
+#define MASTER_GEM_NOC_PCIE_SNOC 8
+#define MASTER_SNOC_GC_MEM_NOC 9
+#define MASTER_SNOC_SF_MEM_NOC 10
+#define MASTER_ECC 11
+#define SLAVE_MSS_PROC_MS_MPU_CFG 12
+#define SLAVE_ECC 13
+#define SLAVE_GEM_NOC_SNOC 14
+#define SLAVE_LLCC 15
+#define SLAVE_SERVICE_GEM_NOC 16
+#define SLAVE_SERVICE_GEM_NOC_1 17
+
+#define MASTER_IPA_CORE 0
+#define SLAVE_IPA_CORE 1
+
+#define MASTER_LLCC 0
+#define SLAVE_EBI_CH0 1
+
+#define MASTER_CNOC_MNOC_CFG 0
+#define MASTER_CAMNOC_HF0 1
+#define MASTER_CAMNOC_HF1 2
+#define MASTER_CAMNOC_SF 3
+#define MASTER_MDP_PORT0 4
+#define MASTER_MDP_PORT1 5
+#define MASTER_ROTATOR 6
+#define MASTER_VIDEO_P0 7
+#define MASTER_VIDEO_P1 8
+#define MASTER_VIDEO_PROC 9
+#define SLAVE_MNOC_SF_MEM_NOC 10
+#define SLAVE_MNOC_HF_MEM_NOC 11
+#define SLAVE_SERVICE_MNOC 12
+
+#define MASTER_SNOC_CFG 0
+#define A1NOC_SNOC_MAS 1
+#define A2NOC_SNOC_MAS 2
+#define MASTER_GEM_NOC_SNOC 3
+#define MASTER_PIMEM 4
+#define MASTER_GIC 5
+#define SLAVE_APPSS 6
+#define SNOC_CNOC_SLV 7
+#define SLAVE_SNOC_GEM_NOC_GC 8
+#define SLAVE_SNOC_GEM_NOC_SF 9
+#define SLAVE_OCIMEM 10
+#define SLAVE_PIMEM 11
+#define SLAVE_SERVICE_SNOC 12
+#define SLAVE_PCIE_0 13
+#define SLAVE_PCIE_1 14
+#define SLAVE_PCIE_2 15
+#define SLAVE_PCIE_3 16
+#define SLAVE_QDSS_STM 17
+#define SLAVE_TCU 18
+
+#define MASTER_MNOC_HF_MEM_NOC_DISPLAY 0
+#define MASTER_MNOC_SF_MEM_NOC_DISPLAY 1
+#define SLAVE_LLCC_DISPLAY 2
+
+#define MASTER_LLCC_DISPLAY 0
+#define SLAVE_EBI_CH0_DISPLAY 1
+
+#define MASTER_MDP_PORT0_DISPLAY 0
+#define MASTER_MDP_PORT1_DISPLAY 1
+#define MASTER_ROTATOR_DISPLAY 2
+#define SLAVE_MNOC_SF_MEM_NOC_DISPLAY 3
+#define SLAVE_MNOC_HF_MEM_NOC_DISPLAY 4
+
+#endif
diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
index 887a31b250a8..f48c9acf251e 100644
--- a/include/dt-bindings/phy/phy.h
+++ b/include/dt-bindings/phy/phy.h
@@ -20,5 +20,7 @@
#define PHY_TYPE_XPCS 7
#define PHY_TYPE_SGMII 8
#define PHY_TYPE_QSGMII 9
+#define PHY_TYPE_DPHY 10
+#define PHY_TYPE_CPHY 11
#endif /* _DT_BINDINGS_PHY */
diff --git a/arch/arm/boot/dts/mt8135-pinfunc.h b/include/dt-bindings/pinctrl/mt8135-pinfunc.h
index ce0cb5a440eb..ce0cb5a440eb 100644
--- a/arch/arm/boot/dts/mt8135-pinfunc.h
+++ b/include/dt-bindings/pinctrl/mt8135-pinfunc.h
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-pinfunc.h b/include/dt-bindings/pinctrl/mt8183-pinfunc.h
index 6221cd712718..6221cd712718 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-pinfunc.h
+++ b/include/dt-bindings/pinctrl/mt8183-pinfunc.h
diff --git a/include/dt-bindings/pinctrl/pinctrl-zynq.h b/include/dt-bindings/pinctrl/pinctrl-zynq.h
new file mode 100644
index 000000000000..bbfc345f017d
--- /dev/null
+++ b/include/dt-bindings/pinctrl/pinctrl-zynq.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * MIO pin configuration defines for Xilinx Zynq
+ *
+ * Copyright (C) 2021 Xilinx, Inc.
+ */
+
+#ifndef _DT_BINDINGS_PINCTRL_ZYNQ_H
+#define _DT_BINDINGS_PINCTRL_ZYNQ_H
+
+/* Configuration options for different power supplies */
+#define IO_STANDARD_LVCMOS18 1
+#define IO_STANDARD_LVCMOS25 2
+#define IO_STANDARD_LVCMOS33 3
+#define IO_STANDARD_HSTL 4
+
+#endif /* _DT_BINDINGS_PINCTRL_ZYNQ_H */
diff --git a/include/dt-bindings/pinctrl/rzg2l-pinctrl.h b/include/dt-bindings/pinctrl/rzg2l-pinctrl.h
new file mode 100644
index 000000000000..b48f8c7a5556
--- /dev/null
+++ b/include/dt-bindings/pinctrl/rzg2l-pinctrl.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * This header provides constants for Renesas RZ/G2L family pinctrl bindings.
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ */
+
+#ifndef __DT_BINDINGS_RZG2L_PINCTRL_H
+#define __DT_BINDINGS_RZG2L_PINCTRL_H
+
+#define RZG2L_PINS_PER_PORT 8
+
+/*
+ * Create the pin index from its bank and position numbers and store in
+ * the upper 16 bits the alternate function identifier
+ */
+#define RZG2L_PORT_PINMUX(b, p, f) ((b) * RZG2L_PINS_PER_PORT + (p) | ((f) << 16))
+
+/* Convert a port and pin label to its global pin index */
+ #define RZG2L_GPIO(port, pin) ((port) * RZG2L_PINS_PER_PORT + (pin))
+
+#endif /* __DT_BINDINGS_RZG2L_PINCTRL_H */
diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
index 8b5708bb9671..4533dbbf9937 100644
--- a/include/dt-bindings/power/qcom-rpmpd.h
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -192,6 +192,16 @@
#define SDM660_SSCMX 8
#define SDM660_SSCMX_VFL 9
+/* SM6115 Power Domains */
+#define SM6115_VDDCX 0
+#define SM6115_VDDCX_AO 1
+#define SM6115_VDDCX_VFL 2
+#define SM6115_VDDMX 3
+#define SM6115_VDDMX_AO 4
+#define SM6115_VDDMX_VFL 5
+#define SM6115_VDD_LPI_CX 6
+#define SM6115_VDD_LPI_MX 7
+
/* RPM SMD Power Domain performance levels */
#define RPM_SMD_LEVEL_RETENTION 16
#define RPM_SMD_LEVEL_RETENTION_PLUS 32
diff --git a/include/dt-bindings/reset/mt8195-resets.h b/include/dt-bindings/reset/mt8195-resets.h
new file mode 100644
index 000000000000..a26bccc8b957
--- /dev/null
+++ b/include/dt-bindings/reset/mt8195-resets.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)*/
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Christine Zhu <christine.zhu@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8195
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8195
+
+#define MT8195_TOPRGU_CONN_MCU_SW_RST 0
+#define MT8195_TOPRGU_INFRA_GRST_SW_RST 1
+#define MT8195_TOPRGU_APU_SW_RST 2
+#define MT8195_TOPRGU_INFRA_AO_GRST_SW_RST 6
+#define MT8195_TOPRGU_MMSYS_SW_RST 7
+#define MT8195_TOPRGU_MFG_SW_RST 8
+#define MT8195_TOPRGU_VENC_SW_RST 9
+#define MT8195_TOPRGU_VDEC_SW_RST 10
+#define MT8195_TOPRGU_IMG_SW_RST 11
+#define MT8195_TOPRGU_APMIXEDSYS_SW_RST 13
+#define MT8195_TOPRGU_AUDIO_SW_RST 14
+#define MT8195_TOPRGU_CAMSYS_SW_RST 15
+#define MT8195_TOPRGU_EDPTX_SW_RST 16
+#define MT8195_TOPRGU_ADSPSYS_SW_RST 21
+#define MT8195_TOPRGU_DPTX_SW_RST 22
+#define MT8195_TOPRGU_SPMI_MST_SW_RST 23
+
+#define MT8195_TOPRGU_SW_RST_NUM 16
+
+#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8195 */
diff --git a/include/dt-bindings/reset/qcom,sdm845-pdc.h b/include/dt-bindings/reset/qcom,sdm845-pdc.h
index 53c37f9c319a..03a0c0eb8147 100644
--- a/include/dt-bindings/reset/qcom,sdm845-pdc.h
+++ b/include/dt-bindings/reset/qcom,sdm845-pdc.h
@@ -16,5 +16,7 @@
#define PDC_DISPLAY_SYNC_RESET 7
#define PDC_COMPUTE_SYNC_RESET 8
#define PDC_MODEM_SYNC_RESET 9
+#define PDC_WLAN_RF_SYNC_RESET 10
+#define PDC_WPSS_SYNC_RESET 11
#endif
diff --git a/include/dt-bindings/soc/zte,pm_domains.h b/include/dt-bindings/soc/zte,pm_domains.h
deleted file mode 100644
index df044705a5ec..000000000000
--- a/include/dt-bindings/soc/zte,pm_domains.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2017 Linaro Ltd.
- *
- * Author: Baoyou Xie <baoyou.xie@linaro.org>
- */
-
-#ifndef _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H
-#define _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H
-
-#define DM_ZX296718_SAPPU 0
-#define DM_ZX296718_VDE 1 /* g1v6 */
-#define DM_ZX296718_VCE 2 /* h1v6 */
-#define DM_ZX296718_HDE 3 /* g2v2 */
-#define DM_ZX296718_VIU 4
-#define DM_ZX296718_USB20 5
-#define DM_ZX296718_USB21 6
-#define DM_ZX296718_USB30 7
-#define DM_ZX296718_HSIC 8
-#define DM_ZX296718_GMAC 9
-#define DM_ZX296718_TS 10
-#define DM_ZX296718_VOU 11
-
-#endif /* _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H */
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index 1d7edad9914f..33207004cfde 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -116,6 +116,7 @@ struct bdi_writeback {
struct list_head b_dirty_time; /* time stamps are dirty */
spinlock_t list_lock; /* protects the b_* lists */
+ atomic_t writeback_inodes; /* number of inodes under writeback */
struct percpu_counter stat[NR_WB_STAT_ITEMS];
unsigned long congested; /* WB_[a]sync_congested flags */
@@ -142,6 +143,7 @@ struct bdi_writeback {
spinlock_t work_lock; /* protects work_list & dwork scheduling */
struct list_head work_list;
struct delayed_work dwork; /* work item used for writeback */
+ struct delayed_work bw_dwork; /* work item used for bandwidth estimate */
unsigned long dirty_sleep; /* last wait */
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 29530859d9ff..ac7f231b8825 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -288,6 +288,17 @@ static inline struct bdi_writeback *inode_to_wb(const struct inode *inode)
return inode->i_wb;
}
+static inline struct bdi_writeback *inode_to_wb_wbc(
+ struct inode *inode,
+ struct writeback_control *wbc)
+{
+ /*
+ * If wbc does not have inode attached, it means cgroup writeback was
+ * disabled when wbc started. Just use the default wb in that case.
+ */
+ return wbc->wb ? wbc->wb : &inode_to_bdi(inode)->wb;
+}
+
/**
* unlocked_inode_to_wb_begin - begin unlocked inode wb access transaction
* @inode: target inode
@@ -366,6 +377,14 @@ static inline struct bdi_writeback *inode_to_wb(struct inode *inode)
return &inode_to_bdi(inode)->wb;
}
+static inline struct bdi_writeback *inode_to_wb_wbc(
+ struct inode *inode,
+ struct writeback_control *wbc)
+{
+ return inode_to_wb(inode);
+}
+
+
static inline struct bdi_writeback *
unlocked_inode_to_wb_begin(struct inode *inode, struct wb_lock_cookie *cookie)
{
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index a36cfcec4e77..37f36dad18bd 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -227,6 +227,12 @@ unsigned int bitmap_ord_to_pos(const unsigned long *bitmap, unsigned int ord, un
int bitmap_print_to_pagebuf(bool list, char *buf,
const unsigned long *maskp, int nmaskbits);
+extern int bitmap_print_bitmask_to_buf(char *buf, const unsigned long *maskp,
+ int nmaskbits, loff_t off, size_t count);
+
+extern int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp,
+ int nmaskbits, loff_t off, size_t count);
+
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index c9cb12483e12..12b9dbcc980e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -17,7 +17,6 @@
#include <linux/bio.h>
#include <linux/stringify.h>
#include <linux/gfp.h>
-#include <linux/bsg.h>
#include <linux/smp.h>
#include <linux/rcupdate.h>
#include <linux/percpu-refcount.h>
@@ -27,14 +26,11 @@
#include <linux/sbitmap.h>
struct module;
-struct scsi_ioctl_command;
-
struct request_queue;
struct elevator_queue;
struct blk_trace;
struct request;
struct sg_io_hdr;
-struct bsg_job;
struct blkcg_gq;
struct blk_flush_queue;
struct pr_ops;
@@ -274,9 +270,6 @@ enum blk_queue_state {
#define BLK_TAG_ALLOC_FIFO 0 /* allocate starting from 0 */
#define BLK_TAG_ALLOC_RR 1 /* allocate starting from last allocated tag */
-#define BLK_SCSI_MAX_CMDS (256)
-#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
-
/*
* Zoned block device models (zoned limit).
*
@@ -505,11 +498,6 @@ struct request_queue {
unsigned int max_active_zones;
#endif /* CONFIG_BLK_DEV_ZONED */
- /*
- * sg stuff
- */
- unsigned int sg_timeout;
- unsigned int sg_reserved_size;
int node;
struct mutex debugfs_mutex;
#ifdef CONFIG_BLK_DEV_IO_TRACE
@@ -536,10 +524,6 @@ struct request_queue {
int mq_freeze_depth;
-#if defined(CONFIG_BLK_DEV_BSG)
- struct bsg_class_device bsg_dev;
-#endif
-
#ifdef CONFIG_BLK_DEV_THROTTLING
/* Throttle data */
struct throtl_data *td;
@@ -885,16 +869,6 @@ extern blk_status_t blk_insert_cloned_request(struct request_queue *q,
struct request *rq);
int blk_rq_append_bio(struct request *rq, struct bio *bio);
extern void blk_queue_split(struct bio **);
-extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int);
-extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t,
- unsigned int, void __user *);
-extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
- unsigned int, void __user *);
-extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
- struct scsi_ioctl_command __user *);
-extern int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp);
-extern int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp);
-
extern int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags);
extern void blk_queue_exit(struct request_queue *q);
extern void blk_sync_queue(struct request_queue *q);
@@ -1347,8 +1321,6 @@ static inline int sb_issue_zeroout(struct super_block *sb, sector_t block,
gfp_mask, 0);
}
-extern int blk_verify_command(unsigned char *cmd, fmode_t mode);
-
static inline bool bdev_is_partition(struct block_device *bdev)
{
return bdev->bd_partno;
@@ -1377,6 +1349,11 @@ static inline unsigned int queue_max_sectors(const struct request_queue *q)
return q->limits.max_sectors;
}
+static inline unsigned int queue_max_bytes(struct request_queue *q)
+{
+ return min_t(unsigned int, queue_max_sectors(q), INT_MAX >> 9) << 9;
+}
+
static inline unsigned int queue_max_hw_sectors(const struct request_queue *q)
{
return q->limits.max_hw_sectors;
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
index 960988d42f77..6b211323a489 100644
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -12,6 +12,7 @@
#include <linux/blkdev.h>
#include <scsi/scsi_request.h>
+struct bsg_job;
struct request;
struct device;
struct scatterlist;
diff --git a/include/linux/bsg.h b/include/linux/bsg.h
index dac37b6e00ec..1ac81c809da9 100644
--- a/include/linux/bsg.h
+++ b/include/linux/bsg.h
@@ -4,36 +4,16 @@
#include <uapi/linux/bsg.h>
-struct request;
+struct bsg_device;
+struct device;
+struct request_queue;
-#ifdef CONFIG_BLK_DEV_BSG
-struct bsg_ops {
- int (*check_proto)(struct sg_io_v4 *hdr);
- int (*fill_hdr)(struct request *rq, struct sg_io_v4 *hdr,
- fmode_t mode);
- int (*complete_rq)(struct request *rq, struct sg_io_v4 *hdr);
- void (*free_rq)(struct request *rq);
-};
+typedef int (bsg_sg_io_fn)(struct request_queue *, struct sg_io_v4 *hdr,
+ fmode_t mode, unsigned int timeout);
-struct bsg_class_device {
- struct device *class_dev;
- int minor;
- struct request_queue *queue;
- const struct bsg_ops *ops;
-};
+struct bsg_device *bsg_register_queue(struct request_queue *q,
+ struct device *parent, const char *name,
+ bsg_sg_io_fn *sg_io_fn);
+void bsg_unregister_queue(struct bsg_device *bcd);
-int bsg_register_queue(struct request_queue *q, struct device *parent,
- const char *name, const struct bsg_ops *ops);
-int bsg_scsi_register_queue(struct request_queue *q, struct device *parent);
-void bsg_unregister_queue(struct request_queue *q);
-#else
-static inline int bsg_scsi_register_queue(struct request_queue *q,
- struct device *parent)
-{
- return 0;
-}
-static inline void bsg_unregister_queue(struct request_queue *q)
-{
-}
-#endif /* CONFIG_BLK_DEV_BSG */
#endif /* _LINUX_BSG_H */
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index e7e99da31349..6486d3c19463 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -409,7 +409,7 @@ static inline void invalidate_inode_buffers(struct inode *inode) {}
static inline int remove_inode_buffers(struct inode *inode) { return 1; }
static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; }
static inline void invalidate_bh_lrus_cpu(int cpu) {}
-static inline bool has_bh_in_lru(int cpu, void *dummy) { return 0; }
+static inline bool has_bh_in_lru(int cpu, void *dummy) { return false; }
#define buffer_heads_over_limit 0
#endif /* CONFIG_BLOCK */
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index f48d0a31deae..c4fef00abdf3 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -86,11 +86,13 @@ struct cdrom_device_ops {
/* play stuff */
int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *);
-/* driver specifications */
- const int capability; /* capability flags */
/* handle uniform packets for scsi type devices (scsi,atapi) */
int (*generic_packet) (struct cdrom_device_info *,
struct packet_command *);
+ int (*read_cdda_bpc)(struct cdrom_device_info *cdi, void __user *ubuf,
+ u32 lba, u32 nframes, u8 *last_sense);
+/* driver specifications */
+ const int capability; /* capability flags */
};
int cdrom_multisession(struct cdrom_device_info *cdi,
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index d83b829305c0..f59c875271a0 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -342,7 +342,7 @@ struct clk_fixed_rate {
unsigned long flags;
};
-#define CLK_FIXED_RATE_PARENT_ACCURACY BIT(0)
+#define CLK_FIXED_RATE_PARENT_ACCURACY BIT(0)
extern const struct clk_ops clk_fixed_rate_ops;
struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
@@ -1001,6 +1001,12 @@ struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
* CLK_FRAC_DIVIDER_BIG_ENDIAN - By default little endian register accesses are
* used for the divider register. Setting this flag makes the register
* accesses big endian.
+ * CLK_FRAC_DIVIDER_POWER_OF_TWO_PS - By default the resulting fraction might
+ * be saturated and the caller will get quite far from the good enough
+ * approximation. Instead the caller may require, by setting this flag,
+ * to shift left by a few bits in case, when the asked one is quite small
+ * to satisfy the desired range of denominator. It assumes that on the
+ * caller's side the power-of-two capable prescaler exists.
*/
struct clk_fractional_divider {
struct clk_hw hw;
@@ -1022,8 +1028,8 @@ struct clk_fractional_divider {
#define CLK_FRAC_DIVIDER_ZERO_BASED BIT(0)
#define CLK_FRAC_DIVIDER_BIG_ENDIAN BIT(1)
+#define CLK_FRAC_DIVIDER_POWER_OF_TWO_PS BIT(2)
-extern const struct clk_ops clk_fractional_divider_ops;
struct clk *clk_register_fractional_divider(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
@@ -1069,9 +1075,9 @@ struct clk_multiplier {
#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw)
-#define CLK_MULTIPLIER_ZERO_BYPASS BIT(0)
+#define CLK_MULTIPLIER_ZERO_BYPASS BIT(0)
#define CLK_MULTIPLIER_ROUND_CLOSEST BIT(1)
-#define CLK_MULTIPLIER_BIG_ENDIAN BIT(2)
+#define CLK_MULTIPLIER_BIG_ENDIAN BIT(2)
extern const struct clk_ops clk_multiplier_ops;
diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h
index a4f82e836a7c..ccb3f034bfa9 100644
--- a/include/linux/clk/at91_pmc.h
+++ b/include/linux/clk/at91_pmc.h
@@ -137,6 +137,32 @@
#define AT91_PMC_PLLADIV2_ON (1 << 12)
#define AT91_PMC_H32MXDIV BIT(24)
+#define AT91_PMC_MCR_V2 0x30 /* Master Clock Register [SAMA7G5 only] */
+#define AT91_PMC_MCR_V2_ID_MSK (0xF)
+#define AT91_PMC_MCR_V2_ID(_id) ((_id) & AT91_PMC_MCR_V2_ID_MSK)
+#define AT91_PMC_MCR_V2_CMD (1 << 7)
+#define AT91_PMC_MCR_V2_DIV (7 << 8)
+#define AT91_PMC_MCR_V2_DIV1 (0 << 8)
+#define AT91_PMC_MCR_V2_DIV2 (1 << 8)
+#define AT91_PMC_MCR_V2_DIV4 (2 << 8)
+#define AT91_PMC_MCR_V2_DIV8 (3 << 8)
+#define AT91_PMC_MCR_V2_DIV16 (4 << 8)
+#define AT91_PMC_MCR_V2_DIV32 (5 << 8)
+#define AT91_PMC_MCR_V2_DIV64 (6 << 8)
+#define AT91_PMC_MCR_V2_DIV3 (7 << 8)
+#define AT91_PMC_MCR_V2_CSS (0x1F << 16)
+#define AT91_PMC_MCR_V2_CSS_MD_SLCK (0 << 16)
+#define AT91_PMC_MCR_V2_CSS_TD_SLCK (1 << 16)
+#define AT91_PMC_MCR_V2_CSS_MAINCK (2 << 16)
+#define AT91_PMC_MCR_V2_CSS_MCK0 (3 << 16)
+#define AT91_PMC_MCR_V2_CSS_SYSPLL (5 << 16)
+#define AT91_PMC_MCR_V2_CSS_DDRPLL (6 << 16)
+#define AT91_PMC_MCR_V2_CSS_IMGPLL (7 << 16)
+#define AT91_PMC_MCR_V2_CSS_BAUDPLL (8 << 16)
+#define AT91_PMC_MCR_V2_CSS_AUDIOPLL (9 << 16)
+#define AT91_PMC_MCR_V2_CSS_ETHPLL (10 << 16)
+#define AT91_PMC_MCR_V2_EN (1 << 28)
+
#define AT91_PMC_XTALF 0x34 /* Main XTAL Frequency Register [SAMA7G5 only] */
#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index c24098c7acca..34bce35c808d 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -84,6 +84,8 @@ static inline unsigned long compact_gap(unsigned int order)
extern unsigned int sysctl_compaction_proactiveness;
extern int sysctl_compaction_handler(struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos);
+extern int compaction_proactiveness_sysctl_handler(struct ctl_table *table,
+ int write, void *buffer, size_t *length, loff_t *ppos);
extern int sysctl_extfrag_threshold;
extern int sysctl_compact_unevictable_allowed;
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 85008a65e21f..93a2922b7653 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -220,6 +220,10 @@ struct coresight_sysfs_link {
* @nr_links: number of sysfs links created to other components from this
* device. These will appear in the "connections" group.
* @has_conns_grp: Have added a "connections" group for sysfs links.
+ * @feature_csdev_list: List of complex feature programming added to the device.
+ * @config_csdev_list: List of system configurations added to the device.
+ * @cscfg_csdev_lock: Protect the lists of configurations and features.
+ * @active_cscfg_ctxt: Context information for current active system configuration.
*/
struct coresight_device {
struct coresight_platform_data *pdata;
@@ -241,6 +245,11 @@ struct coresight_device {
int nr_links;
bool has_conns_grp;
bool ect_enabled; /* true only if associated ect device is enabled */
+ /* system configuration and feature lists */
+ struct list_head feature_csdev_list;
+ struct list_head config_csdev_list;
+ spinlock_t cscfg_csdev_lock;
+ void *active_cscfg_ctxt;
};
/*
diff --git a/include/linux/counter.h b/include/linux/counter.h
index 9dbd5df4cd34..d16ce2819b48 100644
--- a/include/linux/counter.h
+++ b/include/linux/counter.h
@@ -162,15 +162,15 @@ struct counter_count_ext {
void *priv;
};
-enum counter_count_function {
- COUNTER_COUNT_FUNCTION_INCREASE = 0,
- COUNTER_COUNT_FUNCTION_DECREASE,
- COUNTER_COUNT_FUNCTION_PULSE_DIRECTION,
- COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A,
- COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B,
- COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
- COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,
- COUNTER_COUNT_FUNCTION_QUADRATURE_X4
+enum counter_function {
+ COUNTER_FUNCTION_INCREASE = 0,
+ COUNTER_FUNCTION_DECREASE,
+ COUNTER_FUNCTION_PULSE_DIRECTION,
+ COUNTER_FUNCTION_QUADRATURE_X1_A,
+ COUNTER_FUNCTION_QUADRATURE_X1_B,
+ COUNTER_FUNCTION_QUADRATURE_X2_A,
+ COUNTER_FUNCTION_QUADRATURE_X2_B,
+ COUNTER_FUNCTION_QUADRATURE_X4
};
/**
@@ -192,7 +192,7 @@ struct counter_count {
const char *name;
size_t function;
- const enum counter_count_function *functions_list;
+ const enum counter_function *functions_list;
size_t num_functions;
struct counter_synapse *synapses;
@@ -290,16 +290,16 @@ struct counter_device_state {
const struct attribute_group **groups;
};
-enum counter_signal_value {
- COUNTER_SIGNAL_LOW = 0,
- COUNTER_SIGNAL_HIGH
+enum counter_signal_level {
+ COUNTER_SIGNAL_LEVEL_LOW,
+ COUNTER_SIGNAL_LEVEL_HIGH,
};
/**
* struct counter_ops - Callbacks from driver
* @signal_read: optional read callback for Signal attribute. The read
- * value of the respective Signal should be passed back via
- * the val parameter.
+ * level of the respective Signal should be passed back via
+ * the level parameter.
* @count_read: optional read callback for Count attribute. The read
* value of the respective Count should be passed back via
* the val parameter.
@@ -324,7 +324,7 @@ enum counter_signal_value {
struct counter_ops {
int (*signal_read)(struct counter_device *counter,
struct counter_signal *signal,
- enum counter_signal_value *val);
+ enum counter_signal_level *level);
int (*count_read)(struct counter_device *counter,
struct counter_count *count, unsigned long *val);
int (*count_write)(struct counter_device *counter,
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 95f88edc8f09..39cf84a30b9f 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -53,6 +53,7 @@ enum cpuhp_state {
CPUHP_FS_BUFF_DEAD,
CPUHP_PRINTK_DEAD,
CPUHP_MM_MEMCQ_DEAD,
+ CPUHP_XFS_DEAD,
CPUHP_PERCPU_CNT_DEAD,
CPUHP_RADIX_DEAD,
CPUHP_PAGE_ALLOC,
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index f3689a52bfd0..5d4d07a9e1ed 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -983,6 +983,44 @@ cpumap_print_to_pagebuf(bool list, char *buf, const struct cpumask *mask)
nr_cpu_ids);
}
+/**
+ * cpumap_print_bitmask_to_buf - copies the cpumask into the buffer as
+ * hex values of cpumask
+ *
+ * @buf: the buffer to copy into
+ * @mask: the cpumask to copy
+ * @off: in the string from which we are copying, we copy to @buf
+ * @count: the maximum number of bytes to print
+ *
+ * The function prints the cpumask into the buffer as hex values of
+ * cpumask; Typically used by bin_attribute to export cpumask bitmask
+ * ABI.
+ *
+ * Returns the length of how many bytes have been copied.
+ */
+static inline ssize_t
+cpumap_print_bitmask_to_buf(char *buf, const struct cpumask *mask,
+ loff_t off, size_t count)
+{
+ return bitmap_print_bitmask_to_buf(buf, cpumask_bits(mask),
+ nr_cpu_ids, off, count);
+}
+
+/**
+ * cpumap_print_list_to_buf - copies the cpumask into the buffer as
+ * comma-separated list of cpus
+ *
+ * Everything is same with the above cpumap_print_bitmask_to_buf()
+ * except the print format.
+ */
+static inline ssize_t
+cpumap_print_list_to_buf(char *buf, const struct cpumask *mask,
+ loff_t off, size_t count)
+{
+ return bitmap_print_list_to_buf(buf, cpumask_bits(mask),
+ nr_cpu_ids, off, count);
+}
+
#if NR_CPUS <= BITS_PER_LONG
#define CPU_MASK_ALL \
(cpumask_t) { { \
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index a5192b718dbe..2618577a4d6d 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -10,13 +10,14 @@
#include <linux/pgtable.h> /* for pgprot_t */
-#ifdef CONFIG_CRASH_DUMP
+/* For IS_ENABLED(CONFIG_CRASH_DUMP) */
#define ELFCORE_ADDR_MAX (-1ULL)
#define ELFCORE_ADDR_ERR (-2ULL)
extern unsigned long long elfcorehdr_addr;
extern unsigned long long elfcorehdr_size;
+#ifdef CONFIG_CRASH_DUMP
extern int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size);
extern void elfcorehdr_free(unsigned long long addr);
extern ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos);
diff --git a/include/linux/dev_printk.h b/include/linux/dev_printk.h
index 82d3d46005a1..8904063d4c9f 100644
--- a/include/linux/dev_printk.h
+++ b/include/linux/dev_printk.h
@@ -38,8 +38,8 @@ __printf(3, 4) __cold
int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...);
__printf(3, 4) __cold
-void dev_printk(const char *level, const struct device *dev,
- const char *fmt, ...);
+void _dev_printk(const char *level, const struct device *dev,
+ const char *fmt, ...);
__printf(2, 3) __cold
void _dev_emerg(const struct device *dev, const char *fmt, ...);
__printf(2, 3) __cold
@@ -69,7 +69,7 @@ static inline void __dev_printk(const char *level, const struct device *dev,
struct va_format *vaf)
{}
static inline __printf(3, 4)
-void dev_printk(const char *level, const struct device *dev,
+void _dev_printk(const char *level, const struct device *dev,
const char *fmt, ...)
{}
@@ -98,24 +98,56 @@ void _dev_info(const struct device *dev, const char *fmt, ...)
#endif
/*
+ * Need to take variadic arguments even though we don't use them, as dev_fmt()
+ * may only just have been expanded and may result in multiple arguments.
+ */
+#define dev_printk_index_emit(level, fmt, ...) \
+ printk_index_subsys_emit("%s %s: ", level, fmt)
+
+#define dev_printk_index_wrap(_p_func, level, dev, fmt, ...) \
+ ({ \
+ dev_printk_index_emit(level, fmt); \
+ _p_func(dev, fmt, ##__VA_ARGS__); \
+ })
+
+/*
+ * Some callsites directly call dev_printk rather than going through the
+ * dev_<level> infrastructure, so we need to emit here as well as inside those
+ * level-specific macros. Only one index entry will be produced, either way,
+ * since dev_printk's `fmt` isn't known at compile time if going through the
+ * dev_<level> macros.
+ *
+ * dev_fmt() isn't called for dev_printk when used directly, as it's used by
+ * the dev_<level> macros internally which already have dev_fmt() processed.
+ *
+ * We also can't use dev_printk_index_wrap directly, because we have a separate
+ * level to process.
+ */
+#define dev_printk(level, dev, fmt, ...) \
+ ({ \
+ dev_printk_index_emit(level, fmt); \
+ _dev_printk(level, dev, fmt, ##__VA_ARGS__); \
+ })
+
+/*
* #defines for all the dev_<level> macros to prefix with whatever
* possible use of #define dev_fmt(fmt) ...
*/
-#define dev_emerg(dev, fmt, ...) \
- _dev_emerg(dev, dev_fmt(fmt), ##__VA_ARGS__)
-#define dev_crit(dev, fmt, ...) \
- _dev_crit(dev, dev_fmt(fmt), ##__VA_ARGS__)
-#define dev_alert(dev, fmt, ...) \
- _dev_alert(dev, dev_fmt(fmt), ##__VA_ARGS__)
-#define dev_err(dev, fmt, ...) \
- _dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__)
-#define dev_warn(dev, fmt, ...) \
- _dev_warn(dev, dev_fmt(fmt), ##__VA_ARGS__)
-#define dev_notice(dev, fmt, ...) \
- _dev_notice(dev, dev_fmt(fmt), ##__VA_ARGS__)
-#define dev_info(dev, fmt, ...) \
- _dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__)
+#define dev_emerg(dev, fmt, ...) \
+ dev_printk_index_wrap(_dev_emerg, KERN_EMERG, dev, dev_fmt(fmt), ##__VA_ARGS__)
+#define dev_crit(dev, fmt, ...) \
+ dev_printk_index_wrap(_dev_crit, KERN_CRIT, dev, dev_fmt(fmt), ##__VA_ARGS__)
+#define dev_alert(dev, fmt, ...) \
+ dev_printk_index_wrap(_dev_alert, KERN_ALERT, dev, dev_fmt(fmt), ##__VA_ARGS__)
+#define dev_err(dev, fmt, ...) \
+ dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
+#define dev_warn(dev, fmt, ...) \
+ dev_printk_index_wrap(_dev_warn, KERN_WARNING, dev, dev_fmt(fmt), ##__VA_ARGS__)
+#define dev_notice(dev, fmt, ...) \
+ dev_printk_index_wrap(_dev_notice, KERN_NOTICE, dev, dev_fmt(fmt), ##__VA_ARGS__)
+#define dev_info(dev, fmt, ...) \
+ dev_printk_index_wrap(_dev_info, KERN_INFO, dev, dev_fmt(fmt), ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
diff --git a/include/linux/device.h b/include/linux/device.h
index 65d84b67b024..e270cb740b9e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -424,6 +424,7 @@ struct dev_links_info {
* @dma_pools: Dma pools (if dma'ble device).
* @dma_mem: Internal for coherent mem override.
* @cma_area: Contiguous memory area for dma allocations
+ * @dma_io_tlb_mem: Pointer to the swiotlb pool used. Not for driver use.
* @archdata: For arch-specific additions.
* @of_node: Associated device tree node.
* @fwnode: Associated device node supplied by platform firmware.
@@ -534,6 +535,9 @@ struct device {
struct cma *cma_area; /* contiguous memory area for dma
allocations */
#endif
+#ifdef CONFIG_SWIOTLB
+ struct io_tlb_mem *dma_io_tlb_mem;
+#endif
/* arch specific additions */
struct dev_archdata archdata;
diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h
index 1ea5e1d1545b..062777a45a74 100644
--- a/include/linux/device/bus.h
+++ b/include/linux/device/bus.h
@@ -91,7 +91,7 @@ struct bus_type {
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
void (*sync_state)(struct device *dev);
- int (*remove)(struct device *dev);
+ void (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*online)(struct device *dev);
diff --git a/include/linux/dfl.h b/include/linux/dfl.h
index 6cc10982351a..431636a0dc78 100644
--- a/include/linux/dfl.h
+++ b/include/linux/dfl.h
@@ -38,6 +38,7 @@ struct dfl_device {
int id;
u16 type;
u16 feature_id;
+ u8 revision;
struct resource mmio_res;
int *irqs;
unsigned int num_irqs;
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index efdc56b9d95f..8b32b4bdd590 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -54,7 +54,7 @@ struct dma_buf_ops {
* device), and otherwise need to fail the attach operation.
*
* The exporter should also in general check whether the current
- * allocation fullfills the DMA constraints of the new device. If this
+ * allocation fulfills the DMA constraints of the new device. If this
* is not the case, and the allocation cannot be moved, it should also
* fail the attach operation.
*
@@ -96,6 +96,12 @@ struct dma_buf_ops {
* This is called automatically for non-dynamic importers from
* dma_buf_attach().
*
+ * Note that similar to non-dynamic exporters in their @map_dma_buf
+ * callback the driver must guarantee that the memory is available for
+ * use and cleared of any old data by the time this function returns.
+ * Drivers which pipeline their buffer moves internally must wait for
+ * all moves and clears to complete.
+ *
* Returns:
*
* 0 on success, negative error code on failure.
@@ -144,9 +150,18 @@ struct dma_buf_ops {
* This is always called with the dmabuf->resv object locked when
* the dynamic_mapping flag is true.
*
+ * Note that for non-dynamic exporters the driver must guarantee that
+ * that the memory is available for use and cleared of any old data by
+ * the time this function returns. Drivers which pipeline their buffer
+ * moves internally must wait for all moves and clears to complete.
+ * Dynamic exporters do not need to follow this rule: For non-dynamic
+ * importers the buffer is already pinned through @pin, which has the
+ * same requirements. Dynamic importers otoh are required to obey the
+ * dma_resv fences.
+ *
* Returns:
*
- * A &sg_table scatter list of or the backing storage of the DMA buffer,
+ * A &sg_table scatter list of the backing storage of the DMA buffer,
* already mapped into the device address space of the &device attached
* with the provided &dma_buf_attachment. The addresses and lengths in
* the scatter list are PAGE_SIZE aligned.
@@ -168,7 +183,7 @@ struct dma_buf_ops {
*
* This is called by dma_buf_unmap_attachment() and should unmap and
* release the &sg_table allocated in @map_dma_buf, and it is mandatory.
- * For static dma_buf handling this might also unpins the backing
+ * For static dma_buf handling this might also unpin the backing
* storage if this is the last mapping of the DMA buffer.
*/
void (*unmap_dma_buf)(struct dma_buf_attachment *,
@@ -237,7 +252,7 @@ struct dma_buf_ops {
* This callback is used by the dma_buf_mmap() function
*
* Note that the mapping needs to be incoherent, userspace is expected
- * to braket CPU access using the DMA_BUF_IOCTL_SYNC interface.
+ * to bracket CPU access using the DMA_BUF_IOCTL_SYNC interface.
*
* Because dma-buf buffers have invariant size over their lifetime, the
* dma-buf core checks whether a vma is too large and rejects such
@@ -274,27 +289,6 @@ struct dma_buf_ops {
/**
* struct dma_buf - shared buffer object
- * @size: size of the buffer; invariant over the lifetime of the buffer.
- * @file: file pointer used for sharing buffers across, and for refcounting.
- * @attachments: list of dma_buf_attachment that denotes all devices attached,
- * protected by dma_resv lock.
- * @ops: dma_buf_ops associated with this buffer object.
- * @lock: used internally to serialize list manipulation, attach/detach and
- * vmap/unmap
- * @vmapping_counter: used internally to refcnt the vmaps
- * @vmap_ptr: the current vmap ptr if vmapping_counter > 0
- * @exp_name: name of the exporter; useful for debugging.
- * @name: userspace-provided name; useful for accounting and debugging,
- * protected by @resv.
- * @name_lock: spinlock to protect name access
- * @owner: pointer to exporter module; used for refcounting when exporter is a
- * kernel module.
- * @list_node: node for dma_buf accounting and debugging.
- * @priv: exporter specific private data for this buffer object.
- * @resv: reservation object linked to this dma-buf
- * @poll: for userspace poll support
- * @cb_excl: for userspace poll support
- * @cb_shared: for userspace poll support
*
* This represents a shared buffer, created by calling dma_buf_export(). The
* userspace representation is a normal file descriptor, which can be created by
@@ -306,30 +300,152 @@ struct dma_buf_ops {
* Device DMA access is handled by the separate &struct dma_buf_attachment.
*/
struct dma_buf {
+ /**
+ * @size:
+ *
+ * Size of the buffer; invariant over the lifetime of the buffer.
+ */
size_t size;
+
+ /**
+ * @file:
+ *
+ * File pointer used for sharing buffers across, and for refcounting.
+ * See dma_buf_get() and dma_buf_put().
+ */
struct file *file;
+
+ /**
+ * @attachments:
+ *
+ * List of dma_buf_attachment that denotes all devices attached,
+ * protected by &dma_resv lock @resv.
+ */
struct list_head attachments;
+
+ /** @ops: dma_buf_ops associated with this buffer object. */
const struct dma_buf_ops *ops;
+
+ /**
+ * @lock:
+ *
+ * Used internally to serialize list manipulation, attach/detach and
+ * vmap/unmap. Note that in many cases this is superseeded by
+ * dma_resv_lock() on @resv.
+ */
struct mutex lock;
+
+ /**
+ * @vmapping_counter:
+ *
+ * Used internally to refcnt the vmaps returned by dma_buf_vmap().
+ * Protected by @lock.
+ */
unsigned vmapping_counter;
+
+ /**
+ * @vmap_ptr:
+ * The current vmap ptr if @vmapping_counter > 0. Protected by @lock.
+ */
struct dma_buf_map vmap_ptr;
+
+ /**
+ * @exp_name:
+ *
+ * Name of the exporter; useful for debugging. See the
+ * DMA_BUF_SET_NAME IOCTL.
+ */
const char *exp_name;
+
+ /**
+ * @name:
+ *
+ * Userspace-provided name; useful for accounting and debugging,
+ * protected by dma_resv_lock() on @resv and @name_lock for read access.
+ */
const char *name;
+
+ /** @name_lock: Spinlock to protect name acces for read access. */
spinlock_t name_lock;
+
+ /**
+ * @owner:
+ *
+ * Pointer to exporter module; used for refcounting when exporter is a
+ * kernel module.
+ */
struct module *owner;
+
+ /** @list_node: node for dma_buf accounting and debugging. */
struct list_head list_node;
+
+ /** @priv: exporter specific private data for this buffer object. */
void *priv;
+
+ /**
+ * @resv:
+ *
+ * Reservation object linked to this dma-buf.
+ *
+ * IMPLICIT SYNCHRONIZATION RULES:
+ *
+ * Drivers which support implicit synchronization of buffer access as
+ * e.g. exposed in `Implicit Fence Poll Support`_ must follow the
+ * below rules.
+ *
+ * - Drivers must add a shared fence through dma_resv_add_shared_fence()
+ * for anything the userspace API considers a read access. This highly
+ * depends upon the API and window system.
+ *
+ * - Similarly drivers must set the exclusive fence through
+ * dma_resv_add_excl_fence() for anything the userspace API considers
+ * write access.
+ *
+ * - Drivers may just always set the exclusive fence, since that only
+ * causes unecessarily synchronization, but no correctness issues.
+ *
+ * - Some drivers only expose a synchronous userspace API with no
+ * pipelining across drivers. These do not set any fences for their
+ * access. An example here is v4l.
+ *
+ * DYNAMIC IMPORTER RULES:
+ *
+ * Dynamic importers, see dma_buf_attachment_is_dynamic(), have
+ * additional constraints on how they set up fences:
+ *
+ * - Dynamic importers must obey the exclusive fence and wait for it to
+ * signal before allowing access to the buffer's underlying storage
+ * through the device.
+ *
+ * - Dynamic importers should set fences for any access that they can't
+ * disable immediately from their &dma_buf_attach_ops.move_notify
+ * callback.
+ */
struct dma_resv *resv;
- /* poll support */
+ /** @poll: for userspace poll support */
wait_queue_head_t poll;
+ /** @cb_excl: for userspace poll support */
+ /** @cb_shared: for userspace poll support */
struct dma_buf_poll_cb_t {
struct dma_fence_cb cb;
wait_queue_head_t *poll;
__poll_t active;
} cb_excl, cb_shared;
+#ifdef CONFIG_DMABUF_SYSFS_STATS
+ /**
+ * @sysfs_entry:
+ *
+ * For exposing information about this buffer in sysfs. See also
+ * `DMA-BUF statistics`_ for the uapi this enables.
+ */
+ struct dma_buf_sysfs_entry {
+ struct kobject kobj;
+ struct dma_buf *dmabuf;
+ } *sysfs_entry;
+#endif
};
/**
@@ -464,7 +580,7 @@ static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
/**
* dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
- * mappinsg
+ * mappings
* @attach: the DMA-buf attachment to check
*
* Returns true if a DMA-buf importer wants to call the map/unmap functions with
diff --git a/include/linux/dma-fence-chain.h b/include/linux/dma-fence-chain.h
index 10462a029da2..54fe3443fd2c 100644
--- a/include/linux/dma-fence-chain.h
+++ b/include/linux/dma-fence-chain.h
@@ -12,25 +12,41 @@
#include <linux/dma-fence.h>
#include <linux/irq_work.h>
+#include <linux/slab.h>
/**
* struct dma_fence_chain - fence to represent an node of a fence chain
* @base: fence base class
- * @lock: spinlock for fence handling
* @prev: previous fence of the chain
* @prev_seqno: original previous seqno before garbage collection
* @fence: encapsulated fence
- * @cb: callback structure for signaling
- * @work: irq work item for signaling
+ * @lock: spinlock for fence handling
*/
struct dma_fence_chain {
struct dma_fence base;
- spinlock_t lock;
struct dma_fence __rcu *prev;
u64 prev_seqno;
struct dma_fence *fence;
- struct dma_fence_cb cb;
- struct irq_work work;
+ union {
+ /**
+ * @cb: callback for signaling
+ *
+ * This is used to add the callback for signaling the
+ * complection of the fence chain. Never used at the same time
+ * as the irq work.
+ */
+ struct dma_fence_cb cb;
+
+ /**
+ * @work: irq work item for signaling
+ *
+ * Irq work structure to allow us to add the callback without
+ * running into lock inversion. Never used at the same time as
+ * the callback.
+ */
+ struct irq_work work;
+ };
+ spinlock_t lock;
};
extern const struct dma_fence_ops dma_fence_chain_ops;
@@ -52,6 +68,30 @@ to_dma_fence_chain(struct dma_fence *fence)
}
/**
+ * dma_fence_chain_alloc
+ *
+ * Returns a new struct dma_fence_chain object or NULL on failure.
+ */
+static inline struct dma_fence_chain *dma_fence_chain_alloc(void)
+{
+ return kmalloc(sizeof(struct dma_fence_chain), GFP_KERNEL);
+};
+
+/**
+ * dma_fence_chain_free
+ * @chain: chain node to free
+ *
+ * Frees up an allocated but not used struct dma_fence_chain object. This
+ * doesn't need an RCU grace period since the fence was never initialized nor
+ * published. After dma_fence_chain_init() has been called the fence must be
+ * released by calling dma_fence_put(), and not through this function.
+ */
+static inline void dma_fence_chain_free(struct dma_fence_chain *chain)
+{
+ kfree(chain);
+};
+
+/**
* dma_fence_chain_for_each - iterate over all fences in chain
* @iter: current fence
* @head: starting point
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 758ca4694257..24607dc3c2ac 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -20,6 +20,7 @@ void iommu_put_dma_cookie(struct iommu_domain *domain);
/* Setup call for arch DMA mapping code */
void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 dma_limit);
+int iommu_dma_init_fq(struct iommu_domain *domain);
/* The DMA API isn't _quite_ the whole story, though... */
/*
@@ -54,6 +55,11 @@ static inline void iommu_setup_dma_ops(struct device *dev, u64 dma_base,
{
}
+static inline int iommu_dma_init_fq(struct iommu_domain *domain)
+{
+ return -EINVAL;
+}
+
static inline int iommu_get_dma_cookie(struct iommu_domain *domain)
{
return -ENODEV;
diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
index 0d53a96a3d64..0d5b06b3a4a6 100644
--- a/include/linux/dma-map-ops.h
+++ b/include/linux/dma-map-ops.h
@@ -41,8 +41,9 @@ struct dma_map_ops {
size_t size, enum dma_data_direction dir,
unsigned long attrs);
/*
- * map_sg returns 0 on error and a value > 0 on success.
- * It should never return a value < 0.
+ * map_sg should return a negative error code on error. See
+ * dma_map_sgtable() for a list of appropriate error codes
+ * and their meanings.
*/
int (*map_sg)(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir, unsigned long attrs);
@@ -170,13 +171,6 @@ int dma_alloc_from_dev_coherent(struct device *dev, ssize_t size,
int dma_release_from_dev_coherent(struct device *dev, int order, void *vaddr);
int dma_mmap_from_dev_coherent(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, size_t size, int *ret);
-
-void *dma_alloc_from_global_coherent(struct device *dev, ssize_t size,
- dma_addr_t *dma_handle);
-int dma_release_from_global_coherent(int order, void *vaddr);
-int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *cpu_addr,
- size_t size, int *ret);
-
#else
static inline int dma_declare_coherent_memory(struct device *dev,
phys_addr_t phys_addr, dma_addr_t device_addr, size_t size)
@@ -186,7 +180,16 @@ static inline int dma_declare_coherent_memory(struct device *dev,
#define dma_alloc_from_dev_coherent(dev, size, handle, ret) (0)
#define dma_release_from_dev_coherent(dev, order, vaddr) (0)
#define dma_mmap_from_dev_coherent(dev, vma, vaddr, order, ret) (0)
+#endif /* CONFIG_DMA_DECLARE_COHERENT */
+#ifdef CONFIG_DMA_GLOBAL_POOL
+void *dma_alloc_from_global_coherent(struct device *dev, ssize_t size,
+ dma_addr_t *dma_handle);
+int dma_release_from_global_coherent(int order, void *vaddr);
+int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *cpu_addr,
+ size_t size, int *ret);
+int dma_init_global_coherent(phys_addr_t phys_addr, size_t size);
+#else
static inline void *dma_alloc_from_global_coherent(struct device *dev,
ssize_t size, dma_addr_t *dma_handle)
{
@@ -201,7 +204,7 @@ static inline int dma_mmap_from_global_coherent(struct vm_area_struct *vma,
{
return 0;
}
-#endif /* CONFIG_DMA_DECLARE_COHERENT */
+#endif /* CONFIG_DMA_GLOBAL_POOL */
/*
* This is the actual return value from the ->alloc_noncontiguous method.
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 183e7103a66d..dca2b1355bb1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -105,11 +105,13 @@ dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page,
unsigned long attrs);
void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr, size_t size,
enum dma_data_direction dir, unsigned long attrs);
-int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, unsigned long attrs);
+unsigned int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir, unsigned long attrs);
void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
unsigned long attrs);
+int dma_map_sgtable(struct device *dev, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs);
dma_addr_t dma_map_resource(struct device *dev, phys_addr_t phys_addr,
size_t size, enum dma_data_direction dir, unsigned long attrs);
void dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
@@ -164,8 +166,9 @@ static inline void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr,
size_t size, enum dma_data_direction dir, unsigned long attrs)
{
}
-static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir, unsigned long attrs)
+static inline unsigned int dma_map_sg_attrs(struct device *dev,
+ struct scatterlist *sg, int nents, enum dma_data_direction dir,
+ unsigned long attrs)
{
return 0;
}
@@ -174,6 +177,11 @@ static inline void dma_unmap_sg_attrs(struct device *dev,
unsigned long attrs)
{
}
+static inline int dma_map_sgtable(struct device *dev, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ return -EOPNOTSUPP;
+}
static inline dma_addr_t dma_map_resource(struct device *dev,
phys_addr_t phys_addr, size_t size, enum dma_data_direction dir,
unsigned long attrs)
@@ -344,34 +352,6 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
}
/**
- * dma_map_sgtable - Map the given buffer for DMA
- * @dev: The device for which to perform the DMA operation
- * @sgt: The sg_table object describing the buffer
- * @dir: DMA direction
- * @attrs: Optional DMA attributes for the map operation
- *
- * Maps a buffer described by a scatterlist stored in the given sg_table
- * object for the @dir DMA operation by the @dev device. After success the
- * ownership for the buffer is transferred to the DMA domain. One has to
- * call dma_sync_sgtable_for_cpu() or dma_unmap_sgtable() to move the
- * ownership of the buffer back to the CPU domain before touching the
- * buffer by the CPU.
- *
- * Returns 0 on success or -EINVAL on error during mapping the buffer.
- */
-static inline int dma_map_sgtable(struct device *dev, struct sg_table *sgt,
- enum dma_data_direction dir, unsigned long attrs)
-{
- int nents;
-
- nents = dma_map_sg_attrs(dev, sgt->sgl, sgt->orig_nents, dir, attrs);
- if (nents <= 0)
- return -EINVAL;
- sgt->nents = nents;
- return 0;
-}
-
-/**
* dma_unmap_sgtable - Unmap the given buffer for DMA
* @dev: The device for which to perform the DMA operation
* @sgt: The sg_table object describing the buffer
diff --git a/include/linux/entry-kvm.h b/include/linux/entry-kvm.h
index 136b8d97d8c0..0d7865a0731c 100644
--- a/include/linux/entry-kvm.h
+++ b/include/linux/entry-kvm.h
@@ -2,7 +2,11 @@
#ifndef __LINUX_ENTRYKVM_H
#define __LINUX_ENTRYKVM_H
-#include <linux/entry-common.h>
+#include <linux/static_call_types.h>
+#include <linux/tracehook.h>
+#include <linux/syscalls.h>
+#include <linux/seccomp.h>
+#include <linux/sched.h>
#include <linux/tick.h>
/* Transfer to guest mode work */
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 330345b1be54..928c411bd509 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -300,6 +300,18 @@ static inline void ether_addr_copy(u8 *dst, const u8 *src)
}
/**
+ * eth_hw_addr_set - Assign Ethernet address to a net_device
+ * @dev: pointer to net_device structure
+ * @addr: address to assign
+ *
+ * Assign given address to the net_device, addr_assign_type is not changed.
+ */
+static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr)
+{
+ ether_addr_copy(dev->dev_addr, addr);
+}
+
+/**
* eth_hw_addr_inherit - Copy dev_addr from another net_device
* @dst: pointer to net_device to copy dev_addr to
* @src: pointer to net_device to copy dev_addr from
diff --git a/include/linux/fb.h b/include/linux/fb.h
index ecfbcc0553a5..5950f8f5dc74 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -2,6 +2,7 @@
#ifndef _LINUX_FB_H
#define _LINUX_FB_H
+#include <linux/refcount.h>
#include <linux/kgdb.h>
#include <uapi/linux/fb.h>
@@ -435,7 +436,7 @@ struct fb_tile_ops {
struct fb_info {
- atomic_t count;
+ refcount_t count;
int node;
int flags;
/*
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 7d248941ecea..4a93c12543ee 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -5,8 +5,6 @@
#ifndef __LINUX_FILTER_H__
#define __LINUX_FILTER_H__
-#include <stdarg.h>
-
#include <linux/atomic.h>
#include <linux/refcount.h>
#include <linux/compat.h>
diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h
index 9d1a5c175065..56b426fe020c 100644
--- a/include/linux/firmware/xlnx-zynqmp.h
+++ b/include/linux/firmware/xlnx-zynqmp.h
@@ -52,6 +52,10 @@
#define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U
#define ZYNQMP_PM_CAPABILITY_UNUSABLE 0x8U
+/* Loader commands */
+#define PM_LOAD_PDI 0x701
+#define PDI_SRC_DDR 0xF
+
/*
* Firmware FPGA Manager flags
* XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration
@@ -411,6 +415,7 @@ int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
u32 *value);
int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
u32 value);
+int zynqmp_pm_load_pdi(const u32 src, const u64 address);
#else
static inline int zynqmp_pm_get_api_version(u32 *version)
{
@@ -622,6 +627,11 @@ static inline int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
{
return -ENODEV;
}
+
+static inline int zynqmp_pm_load_pdi(const u32 src, const u64 address)
+{
+ return -ENODEV;
+}
#endif
#endif /* __FIRMWARE_ZYNQMP_H__ */
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index ec2cd8bfceb0..474c1f506307 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -110,7 +110,7 @@ struct fpga_image_info {
* @initial_header_size: Maximum number of bytes that should be passed into write_init
* @state: returns an enum value of the FPGA's state
* @status: returns status of the FPGA, including reconfiguration error code
- * @write_init: prepare the FPGA to receive confuration data
+ * @write_init: prepare the FPGA to receive configuration data
* @write: write count bytes of configuration data to the FPGA
* @write_sg: write the scatter list of configuration data to the FPGA
* @write_complete: set FPGA to operating state after writing is done
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1c01f9f2b574..37ad9a730a89 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -588,6 +588,11 @@ static inline void mapping_allow_writable(struct address_space *mapping)
struct posix_acl;
#define ACL_NOT_CACHED ((void *)(-1))
+/*
+ * ACL_DONT_CACHE is for stacked filesystems, that rely on underlying fs to
+ * cache the ACL. This also means that ->get_acl() can be called in RCU mode
+ * with the LOOKUP_RCU flag.
+ */
#define ACL_DONT_CACHE ((void *)(-3))
static inline struct posix_acl *
@@ -2109,7 +2114,7 @@ struct inode_operations {
struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
int (*permission) (struct user_namespace *, struct inode *, int);
- struct posix_acl * (*get_acl)(struct inode *, int);
+ struct posix_acl * (*get_acl)(struct inode *, int, bool);
int (*readlink) (struct dentry *, char __user *,int);
@@ -3018,15 +3023,20 @@ static inline void file_end_write(struct file *file)
}
/*
+ * This is used for regular files where some users -- especially the
+ * currently executed binary in a process, previously handled via
+ * VM_DENYWRITE -- cannot handle concurrent write (and maybe mmap
+ * read-write shared) accesses.
+ *
* get_write_access() gets write permission for a file.
* put_write_access() releases this write permission.
- * This is used for regular files.
- * We cannot support write (and maybe mmap read-write shared) accesses and
- * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode
- * can have the following values:
- * 0: no writers, no VM_DENYWRITE mappings
- * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
- * > 0: (i_writecount) users are writing to the file.
+ * deny_write_access() denies write access to a file.
+ * allow_write_access() re-enables write access to a file.
+ *
+ * The i_writecount field of an inode can have the following values:
+ * 0: no write access, no denied write access
+ * < 0: (-i_writecount) users that denied write access to the file.
+ * > 0: (i_writecount) users that have write access to the file.
*
* Normally we operate on that counter with atomic_{inc,dec} and it's safe
* except for the cases where we don't hold i_writecount yet. Then we need to
@@ -3314,6 +3324,7 @@ extern int page_symlink(struct inode *inode, const char *symname, int len);
extern const struct inode_operations page_symlink_inode_operations;
extern void kfree_link(void *);
void generic_fillattr(struct user_namespace *, struct inode *, struct kstat *);
+void generic_fill_statx_attr(struct inode *inode, struct kstat *stat);
extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int);
extern int vfs_getattr(const struct path *, struct kstat *, u32, unsigned int);
void __inode_add_bytes(struct inode *inode, loff_t bytes);
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 3235ddbdcc09..8d39491c5f9f 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -147,7 +147,6 @@ struct fscache_retrieval {
fscache_rw_complete_t end_io_func; /* function to call on I/O completion */
void *context; /* netfs read context (pinned) */
struct list_head to_do; /* list of things to be done by the backend */
- unsigned long start_time; /* time at which retrieval started */
atomic_t n_pages; /* number of pages to be retrieved */
};
@@ -385,9 +384,6 @@ struct fscache_object {
struct list_head dependents; /* FIFO of dependent objects */
struct list_head dep_link; /* link in parent's dependents list */
struct list_head pending_ops; /* unstarted operations on this object */
-#ifdef CONFIG_FSCACHE_OBJECT_LIST
- struct rb_node objlist_link; /* link in global object list */
-#endif
pgoff_t store_limit; /* current storage limit */
loff_t store_limit_l; /* current storage limit */
};
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index abc1c4737fb8..a4dab5998613 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -123,15 +123,17 @@ struct fscache_netfs {
* - indices are created on disk just-in-time
*/
struct fscache_cookie {
- atomic_t usage; /* number of users of this cookie */
+ refcount_t ref; /* number of users of this cookie */
atomic_t n_children; /* number of children of this cookie */
atomic_t n_active; /* number of active users of netfs ptrs */
+ unsigned int debug_id;
spinlock_t lock;
spinlock_t stores_lock; /* lock on page store tree */
struct hlist_head backing_objects; /* object(s) backing this file/index */
const struct fscache_cookie_def *def; /* definition */
struct fscache_cookie *parent; /* parent of this entry */
struct hlist_bl_node hash_link; /* Link in hash table */
+ struct list_head proc_link; /* Link in proc list */
void *netfs_data; /* back pointer to netfs */
struct radix_tree_root stores; /* pages to be stored on this cookie */
#define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 566feb56601f..97a28ad3393b 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -609,7 +609,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO)
struct device_node;
-struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
+struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label);
@@ -619,7 +619,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
struct device_node;
static inline
-struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
+struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label)
@@ -633,7 +633,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
struct device_node;
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
- struct device_node *node,
+ const struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label);
@@ -644,7 +644,7 @@ struct device_node;
static inline
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
- struct device_node *node,
+ const struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label)
@@ -680,10 +680,10 @@ struct acpi_gpio_mapping {
unsigned int quirks;
};
-#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI)
-
struct acpi_device;
+#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI)
+
int acpi_dev_add_driver_gpios(struct acpi_device *adev,
const struct acpi_gpio_mapping *gpios);
void acpi_dev_remove_driver_gpios(struct acpi_device *adev);
@@ -696,8 +696,6 @@ struct gpio_desc *acpi_get_and_request_gpiod(char *path, int pin, char *label);
#else /* CONFIG_GPIOLIB && CONFIG_ACPI */
-struct acpi_device;
-
static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
const struct acpi_gpio_mapping *gpios)
{
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 3a268781fcec..a0f9901dcae6 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -312,6 +312,9 @@ struct gpio_irq_chip {
* get rid of the static GPIO number space in the long run.
* @ngpio: the number of GPIOs handled by this controller; the last GPIO
* handled is (base + ngpio - 1).
+ * @offset: when multiple gpio chips belong to the same device this
+ * can be used as offset within the device so friendly names can
+ * be properly assigned.
* @names: if set, must be an array of strings to use as alternative
* names for the GPIOs in this chip. Any entry in the array
* may be NULL if there is no alias for the GPIO, however the
@@ -398,6 +401,7 @@ struct gpio_chip {
int base;
u16 ngpio;
+ u16 offset;
const char *const *names;
bool can_sleep;
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 69bc86ea382c..76878b357ffa 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -116,7 +116,6 @@ extern void rcu_nmi_exit(void);
do { \
lockdep_off(); \
arch_nmi_enter(); \
- printk_nmi_enter(); \
BUG_ON(in_nmi() == NMI_MASK); \
__preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \
} while (0)
@@ -135,7 +134,6 @@ extern void rcu_nmi_exit(void);
do { \
BUG_ON(!in_nmi()); \
__preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \
- printk_nmi_exit(); \
arch_nmi_exit(); \
lockdep_on(); \
} while (0)
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index d9a606a9fc64..b4c49f9cc379 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -130,10 +130,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma, struct page *page
}
#endif
-#ifndef ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-static inline void flush_kernel_dcache_page(struct page *page)
-{
-}
+#ifndef ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE
static inline void flush_kernel_vmap_range(void *vaddr, int size)
{
}
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 9b0487c88571..7bccf589aba7 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -170,6 +170,8 @@ u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base);
void host1x_syncpt_release_vblank_reservation(struct host1x_client *client,
u32 syncpt_id);
+struct dma_fence *host1x_fence_create(struct host1x_syncpt *sp, u32 threshold);
+
/*
* host1x channel
*/
@@ -216,8 +218,8 @@ struct host1x_job {
struct host1x_client *client;
/* Gathers and their memory */
- struct host1x_job_gather *gathers;
- unsigned int num_gathers;
+ struct host1x_job_cmd *cmds;
+ unsigned int num_cmds;
/* Array of handles to be pinned & unpinned */
struct host1x_reloc *relocs;
@@ -234,9 +236,15 @@ struct host1x_job {
u32 syncpt_incrs;
u32 syncpt_end;
+ /* Completion waiter ref */
+ void *waiter;
+
/* Maximum time to wait for this job */
unsigned int timeout;
+ /* Job has timed out and should be released */
+ bool cancelled;
+
/* Index and number of slots used in the push buffer */
unsigned int first_get;
unsigned int num_slots;
@@ -257,12 +265,25 @@ struct host1x_job {
/* Add a channel wait for previous ops to complete */
bool serialize;
+
+ /* Fast-forward syncpoint increments on job timeout */
+ bool syncpt_recovery;
+
+ /* Callback called when job is freed */
+ void (*release)(struct host1x_job *job);
+ void *user_data;
+
+ /* Whether host1x-side firewall should be ran for this job or not */
+ bool enable_firewall;
};
struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
- u32 num_cmdbufs, u32 num_relocs);
+ u32 num_cmdbufs, u32 num_relocs,
+ bool skip_firewall);
void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *bo,
unsigned int words, unsigned int offset);
+void host1x_job_add_wait(struct host1x_job *job, u32 id, u32 thresh,
+ bool relative, u32 next_class);
struct host1x_job *host1x_job_get(struct host1x_job *job);
void host1x_job_put(struct host1x_job *job);
int host1x_job_pin(struct host1x_job *job, struct device *dev);
diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h
index 0b8d1fdda3a1..c137396129db 100644
--- a/include/linux/hugetlb_cgroup.h
+++ b/include/linux/hugetlb_cgroup.h
@@ -121,6 +121,13 @@ static inline void hugetlb_cgroup_put_rsvd_cgroup(struct hugetlb_cgroup *h_cg)
css_put(&h_cg->css);
}
+static inline void resv_map_dup_hugetlb_cgroup_uncharge_info(
+ struct resv_map *resv_map)
+{
+ if (resv_map->css)
+ css_get(resv_map->css);
+}
+
extern int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
struct hugetlb_cgroup **ptr);
extern int hugetlb_cgroup_charge_cgroup_rsvd(int idx, unsigned long nr_pages,
@@ -199,6 +206,11 @@ static inline void hugetlb_cgroup_put_rsvd_cgroup(struct hugetlb_cgroup *h_cg)
{
}
+static inline void resv_map_dup_hugetlb_cgroup_uncharge_info(
+ struct resv_map *resv_map)
+{
+}
+
static inline int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
struct hugetlb_cgroup **ptr)
{
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 2e859d2f9609..ddc8713ce57b 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -538,12 +538,6 @@ struct vmbus_channel_rescind_offer {
u32 child_relid;
} __packed;
-static inline u32
-hv_ringbuffer_pending_size(const struct hv_ring_buffer_info *rbi)
-{
- return rbi->ring_buffer->pending_send_sz;
-}
-
/*
* Request Offer -- no parameters, SynIC message contains the partition ID
* Set Snoop -- no parameters, SynIC message contains the partition ID
@@ -1092,16 +1086,6 @@ static inline void set_channel_pending_send_size(struct vmbus_channel *c,
c->outbound.ring_buffer->pending_send_sz = size;
}
-static inline void set_low_latency_mode(struct vmbus_channel *c)
-{
- c->low_latency = true;
-}
-
-static inline void clear_low_latency_mode(struct vmbus_channel *c)
-{
- c->low_latency = false;
-}
-
void vmbus_onmessage(struct vmbus_channel_message_header *hdr);
int vmbus_request_offers(void);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 3eb60a2e9e61..2ce3efbe9198 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -1010,6 +1010,7 @@ struct acpi_resource_i2c_serialbus;
#if IS_ENABLED(CONFIG_ACPI)
bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
struct acpi_resource_i2c_serialbus **i2c);
+int i2c_acpi_client_count(struct acpi_device *adev);
u32 i2c_acpi_find_bus_speed(struct device *dev);
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
struct i2c_board_info *info);
@@ -1020,6 +1021,10 @@ static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
{
return false;
}
+static inline int i2c_acpi_client_count(struct acpi_device *adev)
+{
+ return 0;
+}
static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
{
return 0;
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 61d5723ec303..b6ab66a546ae 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -11,9 +11,11 @@
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/kexec.h>
+#include <crypto/hash_info.h>
struct linux_binprm;
#ifdef CONFIG_IMA
+extern enum hash_algo ima_get_current_hash_algo(void);
extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_file_check(struct file *file, int mask);
extern void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
@@ -33,10 +35,10 @@ extern void ima_post_path_mknod(struct user_namespace *mnt_userns,
extern int ima_file_hash(struct file *file, char *buf, size_t buf_size);
extern int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size);
extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size);
-extern void ima_measure_critical_data(const char *event_label,
- const char *event_name,
- const void *buf, size_t buf_len,
- bool hash);
+extern int ima_measure_critical_data(const char *event_label,
+ const char *event_name,
+ const void *buf, size_t buf_len,
+ bool hash, u8 *digest, size_t digest_len);
#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
extern void ima_appraise_parse_cmdline(void);
@@ -64,6 +66,11 @@ static inline const char * const *arch_get_ima_policy(void)
#endif
#else
+static inline enum hash_algo ima_get_current_hash_algo(void)
+{
+ return HASH_ALGO__LAST;
+}
+
static inline int ima_bprm_check(struct linux_binprm *bprm)
{
return 0;
@@ -137,10 +144,14 @@ static inline int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size
static inline void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) {}
-static inline void ima_measure_critical_data(const char *event_label,
+static inline int ima_measure_critical_data(const char *event_label,
const char *event_name,
const void *buf, size_t buf_len,
- bool hash) {}
+ bool hash, u8 *digest,
+ size_t digest_len)
+{
+ return -ENOENT;
+}
#endif /* CONFIG_IMA */
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index d0fa0b31994d..05a65eb155f7 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -124,9 +124,9 @@
#define DMAR_MTRR_PHYSMASK8_REG 0x208
#define DMAR_MTRR_PHYSBASE9_REG 0x210
#define DMAR_MTRR_PHYSMASK9_REG 0x218
-#define DMAR_VCCAP_REG 0xe00 /* Virtual command capability register */
-#define DMAR_VCMD_REG 0xe10 /* Virtual command register */
-#define DMAR_VCRSP_REG 0xe20 /* Virtual command response register */
+#define DMAR_VCCAP_REG 0xe30 /* Virtual command capability register */
+#define DMAR_VCMD_REG 0xe00 /* Virtual command register */
+#define DMAR_VCRSP_REG 0xe10 /* Virtual command response register */
#define DMAR_IQER_REG_IQEI(reg) FIELD_GET(GENMASK_ULL(3, 0), reg)
#define DMAR_IQER_REG_ITESID(reg) FIELD_GET(GENMASK_ULL(47, 32), reg)
diff --git a/include/linux/intel-svm.h b/include/linux/intel-svm.h
index 10fa80eef13a..57cceecbe37f 100644
--- a/include/linux/intel-svm.h
+++ b/include/linux/intel-svm.h
@@ -14,6 +14,11 @@
#define SVM_REQ_EXEC (1<<1)
#define SVM_REQ_PRIV (1<<0)
+/* Page Request Queue depth */
+#define PRQ_ORDER 2
+#define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x20)
+#define PRQ_DEPTH ((0x1000 << PRQ_ORDER) >> 5)
+
/*
* The SVM_FLAG_SUPERVISOR_MODE flag requests a PASID which can be used only
* for access to kernel addresses. No IOTLB flushes are automatically done
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
index 4d40dfa75b55..86af6f0a00a2 100644
--- a/include/linux/io-pgtable.h
+++ b/include/linux/io-pgtable.h
@@ -16,6 +16,7 @@ enum io_pgtable_fmt {
ARM_V7S,
ARM_MALI_LPAE,
AMD_IOMMU_V1,
+ APPLE_DART,
IO_PGTABLE_NUM_FMTS,
};
@@ -73,10 +74,6 @@ struct io_pgtable_cfg {
* to support up to 35 bits PA where the bit32, bit33 and bit34 are
* encoded in the bit9, bit4 and bit5 of the PTE respectively.
*
- * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
- * on unmap, for DMA domains using the flush queue mechanism for
- * delayed invalidation.
- *
* IO_PGTABLE_QUIRK_ARM_TTBR1: (ARM LPAE format) Configure the table
* for use in the upper half of a split address space.
*
@@ -86,7 +83,6 @@ struct io_pgtable_cfg {
#define IO_PGTABLE_QUIRK_ARM_NS BIT(0)
#define IO_PGTABLE_QUIRK_NO_PERMS BIT(1)
#define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3)
- #define IO_PGTABLE_QUIRK_NON_STRICT BIT(4)
#define IO_PGTABLE_QUIRK_ARM_TTBR1 BIT(5)
#define IO_PGTABLE_QUIRK_ARM_OUTER_WBWA BIT(6)
unsigned long quirks;
@@ -136,6 +132,11 @@ struct io_pgtable_cfg {
u64 transtab;
u64 memattr;
} arm_mali_lpae_cfg;
+
+ struct {
+ u64 ttbr[4];
+ u32 n_ttbrs;
+ } apple_dart_cfg;
};
};
@@ -143,7 +144,9 @@ struct io_pgtable_cfg {
* struct io_pgtable_ops - Page table manipulation API for IOMMU drivers.
*
* @map: Map a physically contiguous memory region.
+ * @map_pages: Map a physically contiguous range of pages of the same size.
* @unmap: Unmap a physically contiguous memory region.
+ * @unmap_pages: Unmap a range of virtually contiguous pages of the same size.
* @iova_to_phys: Translate iova to physical address.
*
* These functions map directly onto the iommu_ops member functions with
@@ -152,8 +155,14 @@ struct io_pgtable_cfg {
struct io_pgtable_ops {
int (*map)(struct io_pgtable_ops *ops, unsigned long iova,
phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
+ int (*map_pages)(struct io_pgtable_ops *ops, unsigned long iova,
+ phys_addr_t paddr, size_t pgsize, size_t pgcount,
+ int prot, gfp_t gfp, size_t *mapped);
size_t (*unmap)(struct io_pgtable_ops *ops, unsigned long iova,
size_t size, struct iommu_iotlb_gather *gather);
+ size_t (*unmap_pages)(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t pgsize, size_t pgcount,
+ struct iommu_iotlb_gather *gather);
phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
unsigned long iova);
};
@@ -246,5 +255,6 @@ extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns;
extern struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns;
extern struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns;
extern struct io_pgtable_init_fns io_pgtable_amd_iommu_v1_init_fns;
+extern struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns;
#endif /* __IO_PGTABLE_H */
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 32d448050bf7..d2f3435e7d17 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -40,6 +40,7 @@ struct iommu_domain;
struct notifier_block;
struct iommu_sva;
struct iommu_fault_event;
+struct iommu_dma_cookie;
/* iommu fault flags */
#define IOMMU_FAULT_READ 0x0
@@ -60,6 +61,7 @@ struct iommu_domain_geometry {
#define __IOMMU_DOMAIN_DMA_API (1U << 1) /* Domain for use in DMA-API
implementation */
#define __IOMMU_DOMAIN_PT (1U << 2) /* Domain is identity mapped */
+#define __IOMMU_DOMAIN_DMA_FQ (1U << 3) /* DMA-API uses flush queue */
/*
* This are the possible domain-types
@@ -72,12 +74,17 @@ struct iommu_domain_geometry {
* IOMMU_DOMAIN_DMA - Internally used for DMA-API implementations.
* This flag allows IOMMU drivers to implement
* certain optimizations for these domains
+ * IOMMU_DOMAIN_DMA_FQ - As above, but definitely using batched TLB
+ * invalidation.
*/
#define IOMMU_DOMAIN_BLOCKED (0U)
#define IOMMU_DOMAIN_IDENTITY (__IOMMU_DOMAIN_PT)
#define IOMMU_DOMAIN_UNMANAGED (__IOMMU_DOMAIN_PAGING)
#define IOMMU_DOMAIN_DMA (__IOMMU_DOMAIN_PAGING | \
__IOMMU_DOMAIN_DMA_API)
+#define IOMMU_DOMAIN_DMA_FQ (__IOMMU_DOMAIN_PAGING | \
+ __IOMMU_DOMAIN_DMA_API | \
+ __IOMMU_DOMAIN_DMA_FQ)
struct iommu_domain {
unsigned type;
@@ -86,9 +93,14 @@ struct iommu_domain {
iommu_fault_handler_t handler;
void *handler_token;
struct iommu_domain_geometry geometry;
- void *iova_cookie;
+ struct iommu_dma_cookie *iova_cookie;
};
+static inline bool iommu_is_dma_domain(struct iommu_domain *domain)
+{
+ return domain->type & __IOMMU_DOMAIN_DMA_API;
+}
+
enum iommu_cap {
IOMMU_CAP_CACHE_COHERENCY, /* IOMMU can enforce cache coherent DMA
transactions */
@@ -160,16 +172,22 @@ enum iommu_dev_features {
* @start: IOVA representing the start of the range to be flushed
* @end: IOVA representing the end of the range to be flushed (inclusive)
* @pgsize: The interval at which to perform the flush
+ * @freelist: Removed pages to free after sync
+ * @queued: Indicates that the flush will be queued
*
* This structure is intended to be updated by multiple calls to the
* ->unmap() function in struct iommu_ops before eventually being passed
- * into ->iotlb_sync().
+ * into ->iotlb_sync(). Drivers can add pages to @freelist to be freed after
+ * ->iotlb_sync() or ->iotlb_flush_all() have cleared all cached references to
+ * them. @queued is set to indicate when ->iotlb_flush_all() will be called
+ * later instead of ->iotlb_sync(), so drivers may optimise accordingly.
*/
struct iommu_iotlb_gather {
unsigned long start;
unsigned long end;
size_t pgsize;
struct page *freelist;
+ bool queued;
};
/**
@@ -180,7 +198,10 @@ struct iommu_iotlb_gather {
* @attach_dev: attach device to an iommu domain
* @detach_dev: detach device from an iommu domain
* @map: map a physically contiguous memory region to an iommu domain
+ * @map_pages: map a physically contiguous set of pages of the same size to
+ * an iommu domain.
* @unmap: unmap a physically contiguous memory region from an iommu domain
+ * @unmap_pages: unmap a number of pages of the same size from an iommu domain
* @flush_iotlb_all: Synchronously flush all hardware TLBs for this domain
* @iotlb_sync_map: Sync mappings created recently using @map to the hardware
* @iotlb_sync: Flush all queued ranges from the hardware TLBs and empty flush
@@ -229,8 +250,14 @@ struct iommu_ops {
void (*detach_dev)(struct iommu_domain *domain, struct device *dev);
int (*map)(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
+ int (*map_pages)(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t pgsize, size_t pgcount,
+ int prot, gfp_t gfp, size_t *mapped);
size_t (*unmap)(struct iommu_domain *domain, unsigned long iova,
size_t size, struct iommu_iotlb_gather *iotlb_gather);
+ size_t (*unmap_pages)(struct iommu_domain *domain, unsigned long iova,
+ size_t pgsize, size_t pgcount,
+ struct iommu_iotlb_gather *iotlb_gather);
void (*flush_iotlb_all)(struct iommu_domain *domain);
void (*iotlb_sync_map)(struct iommu_domain *domain, unsigned long iova,
size_t size);
@@ -414,11 +441,11 @@ extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
extern size_t iommu_unmap_fast(struct iommu_domain *domain,
unsigned long iova, size_t size,
struct iommu_iotlb_gather *iotlb_gather);
-extern size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
- struct scatterlist *sg,unsigned int nents, int prot);
-extern size_t iommu_map_sg_atomic(struct iommu_domain *domain,
- unsigned long iova, struct scatterlist *sg,
- unsigned int nents, int prot);
+extern ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+ struct scatterlist *sg, unsigned int nents, int prot);
+extern ssize_t iommu_map_sg_atomic(struct iommu_domain *domain,
+ unsigned long iova, struct scatterlist *sg,
+ unsigned int nents, int prot);
extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova);
extern void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler, void *token);
@@ -476,8 +503,7 @@ int iommu_enable_nesting(struct iommu_domain *domain);
int iommu_set_pgtable_quirks(struct iommu_domain *domain,
unsigned long quirks);
-void iommu_set_dma_strict(bool val);
-bool iommu_get_dma_strict(struct iommu_domain *domain);
+void iommu_set_dma_strict(void);
extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
unsigned long iova, int flags);
@@ -497,29 +523,80 @@ static inline void iommu_iotlb_sync(struct iommu_domain *domain,
iommu_iotlb_gather_init(iotlb_gather);
}
+/**
+ * iommu_iotlb_gather_is_disjoint - Checks whether a new range is disjoint
+ *
+ * @gather: TLB gather data
+ * @iova: start of page to invalidate
+ * @size: size of page to invalidate
+ *
+ * Helper for IOMMU drivers to check whether a new range and the gathered range
+ * are disjoint. For many IOMMUs, flushing the IOMMU in this case is better
+ * than merging the two, which might lead to unnecessary invalidations.
+ */
+static inline
+bool iommu_iotlb_gather_is_disjoint(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t size)
+{
+ unsigned long start = iova, end = start + size - 1;
+
+ return gather->end != 0 &&
+ (end + 1 < gather->start || start > gather->end + 1);
+}
+
+
+/**
+ * iommu_iotlb_gather_add_range - Gather for address-based TLB invalidation
+ * @gather: TLB gather data
+ * @iova: start of page to invalidate
+ * @size: size of page to invalidate
+ *
+ * Helper for IOMMU drivers to build arbitrarily-sized invalidation commands
+ * where only the address range matters, and simply minimising intermediate
+ * syncs is preferred.
+ */
+static inline void iommu_iotlb_gather_add_range(struct iommu_iotlb_gather *gather,
+ unsigned long iova, size_t size)
+{
+ unsigned long end = iova + size - 1;
+
+ if (gather->start > iova)
+ gather->start = iova;
+ if (gather->end < end)
+ gather->end = end;
+}
+
+/**
+ * iommu_iotlb_gather_add_page - Gather for page-based TLB invalidation
+ * @domain: IOMMU domain to be invalidated
+ * @gather: TLB gather data
+ * @iova: start of page to invalidate
+ * @size: size of page to invalidate
+ *
+ * Helper for IOMMU drivers to build invalidation commands based on individual
+ * pages, or with page size/table level hints which cannot be gathered if they
+ * differ.
+ */
static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain,
struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size)
{
- unsigned long start = iova, end = start + size - 1;
-
/*
* If the new page is disjoint from the current range or is mapped at
* a different granularity, then sync the TLB so that the gather
* structure can be rewritten.
*/
- if (gather->pgsize != size ||
- end + 1 < gather->start || start > gather->end + 1) {
- if (gather->pgsize)
- iommu_iotlb_sync(domain, gather);
- gather->pgsize = size;
- }
+ if ((gather->pgsize && gather->pgsize != size) ||
+ iommu_iotlb_gather_is_disjoint(gather, iova, size))
+ iommu_iotlb_sync(domain, gather);
- if (gather->end < end)
- gather->end = end;
+ gather->pgsize = size;
+ iommu_iotlb_gather_add_range(gather, iova, size);
+}
- if (gather->start > start)
- gather->start = start;
+static inline bool iommu_iotlb_gather_queued(struct iommu_iotlb_gather *gather)
+{
+ return gather && gather->queued;
}
/* PCI device grouping function */
@@ -679,18 +756,18 @@ static inline size_t iommu_unmap_fast(struct iommu_domain *domain,
return 0;
}
-static inline size_t iommu_map_sg(struct iommu_domain *domain,
- unsigned long iova, struct scatterlist *sg,
- unsigned int nents, int prot)
+static inline ssize_t iommu_map_sg(struct iommu_domain *domain,
+ unsigned long iova, struct scatterlist *sg,
+ unsigned int nents, int prot)
{
- return 0;
+ return -ENODEV;
}
-static inline size_t iommu_map_sg_atomic(struct iommu_domain *domain,
+static inline ssize_t iommu_map_sg_atomic(struct iommu_domain *domain,
unsigned long iova, struct scatterlist *sg,
unsigned int nents, int prot)
{
- return 0;
+ return -ENODEV;
}
static inline void iommu_flush_iotlb_all(struct iommu_domain *domain)
@@ -870,6 +947,11 @@ static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain,
{
}
+static inline bool iommu_iotlb_gather_queued(struct iommu_iotlb_gather *gather)
+{
+ return false;
+}
+
static inline void iommu_device_unregister(struct iommu_device *iommu)
{
}
diff --git a/include/linux/kasan-tags.h b/include/linux/kasan-tags.h
new file mode 100644
index 000000000000..4f85f562512c
--- /dev/null
+++ b/include/linux/kasan-tags.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KASAN_TAGS_H
+#define _LINUX_KASAN_TAGS_H
+
+#define KASAN_TAG_KERNEL 0xFF /* native kernel pointers tag */
+#define KASAN_TAG_INVALID 0xFE /* inaccessible memory tag */
+#define KASAN_TAG_MAX 0xFD /* maximum value for random tags */
+
+#ifdef CONFIG_KASAN_HW_TAGS
+#define KASAN_TAG_MIN 0xF0 /* minimum value for random tags */
+#else
+#define KASAN_TAG_MIN 0x00 /* minimum value for random tags */
+#endif
+
+#endif /* LINUX_KASAN_TAGS_H */
diff --git a/include/linux/kdb.h b/include/linux/kdb.h
index 0125a677b67f..ea0f5e580fac 100644
--- a/include/linux/kdb.h
+++ b/include/linux/kdb.h
@@ -13,6 +13,8 @@
* Copyright (C) 2009 Jason Wessel <jason.wessel@windriver.com>
*/
+#include <linux/list.h>
+
/* Shifted versions of the command enable bits are be used if the command
* has no arguments (see kdb_check_flags). This allows commands, such as
* go, to have different permissions depending upon whether it is called
@@ -64,6 +66,17 @@ typedef enum {
typedef int (*kdb_func_t)(int, const char **);
+/* The KDB shell command table */
+typedef struct _kdbtab {
+ char *name; /* Command name */
+ kdb_func_t func; /* Function to execute command */
+ char *usage; /* Usage String for this command */
+ char *help; /* Help message for this command */
+ short minlen; /* Minimum legal # cmd chars required */
+ kdb_cmdflags_t flags; /* Command behaviour flags */
+ struct list_head list_node; /* Command list */
+} kdbtab_t;
+
#ifdef CONFIG_KGDB_KDB
#include <linux/init.h>
#include <linux/sched.h>
@@ -193,19 +206,13 @@ static inline const char *kdb_walk_kallsyms(loff_t *pos)
#endif /* ! CONFIG_KALLSYMS */
/* Dynamic kdb shell command registration */
-extern int kdb_register(char *, kdb_func_t, char *, char *, short);
-extern int kdb_register_flags(char *, kdb_func_t, char *, char *,
- short, kdb_cmdflags_t);
-extern int kdb_unregister(char *);
+extern int kdb_register(kdbtab_t *cmd);
+extern void kdb_unregister(kdbtab_t *cmd);
#else /* ! CONFIG_KGDB_KDB */
static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; }
static inline void kdb_init(int level) {}
-static inline int kdb_register(char *cmd, kdb_func_t func, char *usage,
- char *help, short minlen) { return 0; }
-static inline int kdb_register_flags(char *cmd, kdb_func_t func, char *usage,
- char *help, short minlen,
- kdb_cmdflags_t flags) { return 0; }
-static inline int kdb_unregister(char *cmd) { return 0; }
+static inline int kdb_register(kdbtab_t *cmd) { return 0; }
+static inline void kdb_unregister(kdbtab_t *cmd) {}
#endif /* CONFIG_KGDB_KDB */
enum {
KDB_NOT_INITIALIZED,
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 1b2f0a7e00d6..2776423a587e 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -2,7 +2,7 @@
#ifndef _LINUX_KERNEL_H
#define _LINUX_KERNEL_H
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/align.h>
#include <linux/limits.h>
#include <linux/linkage.h>
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 9e8ca8743c26..1093abf7c28c 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -98,6 +98,11 @@ struct kernfs_elem_dir {
* better directly in kernfs_node but is here to save space.
*/
struct kernfs_root *root;
+ /*
+ * Monotonic revision counter, used to identify if a directory
+ * node has changed during negative dentry revalidation.
+ */
+ unsigned long rev;
};
struct kernfs_elem_symlink {
@@ -188,7 +193,7 @@ struct kernfs_root {
u32 id_highbits;
struct kernfs_syscall_ops *syscall_ops;
- /* list of kernfs_super_info of this root, protected by kernfs_mutex */
+ /* list of kernfs_super_info of this root, protected by kernfs_rwsem */
struct list_head supers;
wait_queue_head_t deactivate_waitq;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ae7735b490b4..041ca7f15ea4 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -150,6 +150,7 @@ static inline bool is_error_page(struct page *page)
#define KVM_REQ_MMU_RELOAD (1 | KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
#define KVM_REQ_UNBLOCK 2
#define KVM_REQ_UNHALT 3
+#define KVM_REQ_VM_BUGGED (4 | KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
#define KVM_REQUEST_ARCH_BASE 8
#define KVM_ARCH_REQ_FLAGS(nr, flags) ({ \
@@ -158,6 +159,15 @@ static inline bool is_error_page(struct page *page)
})
#define KVM_ARCH_REQ(nr) KVM_ARCH_REQ_FLAGS(nr, 0)
+bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req,
+ struct kvm_vcpu *except,
+ unsigned long *vcpu_bitmap, cpumask_var_t tmp);
+bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
+bool kvm_make_all_cpus_request_except(struct kvm *kvm, unsigned int req,
+ struct kvm_vcpu *except);
+bool kvm_make_cpus_request_mask(struct kvm *kvm, unsigned int req,
+ unsigned long *vcpu_bitmap);
+
#define KVM_USERSPACE_IRQ_SOURCE_ID 0
#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
@@ -344,6 +354,13 @@ struct kvm_vcpu {
struct kvm_vcpu_stat stat;
char stats_id[KVM_STATS_NAME_SIZE];
struct kvm_dirty_ring dirty_ring;
+
+ /*
+ * The index of the most recently used memslot by this vCPU. It's ok
+ * if this becomes stale due to memslot changes since we always check
+ * it is a valid slot.
+ */
+ int last_used_slot;
};
/* must be called with irqs disabled */
@@ -512,7 +529,7 @@ struct kvm_memslots {
u64 generation;
/* The mapping table from slot id to the index in memslots[]. */
short id_to_index[KVM_MEM_SLOTS_NUM];
- atomic_t lru_slot;
+ atomic_t last_used_slot;
int used_slots;
struct kvm_memory_slot memslots[];
};
@@ -538,6 +555,11 @@ struct kvm {
struct kvm_memslots __rcu *memslots[KVM_ADDRESS_SPACE_NUM];
struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
+ /* Used to wait for completion of MMU notifiers. */
+ spinlock_t mn_invalidate_lock;
+ unsigned long mn_active_invalidate_count;
+ struct rcuwait mn_memslots_update_rcuwait;
+
/*
* created_vcpus is protected by kvm->lock, and is incremented
* at the beginning of KVM_CREATE_VCPU. online_vcpus is only
@@ -596,6 +618,7 @@ struct kvm {
pid_t userspace_pid;
unsigned int max_halt_poll_ns;
u32 dirty_ring_size;
+ bool vm_bugged;
#ifdef CONFIG_HAVE_KVM_PM_NOTIFIER
struct notifier_block pm_notifier;
@@ -629,6 +652,30 @@ struct kvm {
#define vcpu_err(vcpu, fmt, ...) \
kvm_err("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
+static inline void kvm_vm_bugged(struct kvm *kvm)
+{
+ kvm->vm_bugged = true;
+ kvm_make_all_cpus_request(kvm, KVM_REQ_VM_BUGGED);
+}
+
+#define KVM_BUG(cond, kvm, fmt...) \
+({ \
+ int __ret = (cond); \
+ \
+ if (WARN_ONCE(__ret && !(kvm)->vm_bugged, fmt)) \
+ kvm_vm_bugged(kvm); \
+ unlikely(__ret); \
+})
+
+#define KVM_BUG_ON(cond, kvm) \
+({ \
+ int __ret = (cond); \
+ \
+ if (WARN_ON_ONCE(__ret && !(kvm)->vm_bugged)) \
+ kvm_vm_bugged(kvm); \
+ unlikely(__ret); \
+})
+
static inline bool kvm_dirty_log_manual_protect_and_init_set(struct kvm *kvm)
{
return !!(kvm->manual_dirty_log_protect & KVM_DIRTY_LOG_INITIALLY_SET);
@@ -720,6 +767,7 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
void kvm_exit(void);
void kvm_get_kvm(struct kvm *kvm);
+bool kvm_get_kvm_safe(struct kvm *kvm);
void kvm_put_kvm(struct kvm *kvm);
bool file_is_kvm(struct file *file);
void kvm_put_kvm_no_destroy(struct kvm *kvm);
@@ -824,7 +872,6 @@ void kvm_release_pfn_clean(kvm_pfn_t pfn);
void kvm_release_pfn_dirty(kvm_pfn_t pfn);
void kvm_set_pfn_dirty(kvm_pfn_t pfn);
void kvm_set_pfn_accessed(kvm_pfn_t pfn);
-void kvm_get_pfn(kvm_pfn_t pfn);
void kvm_release_pfn(kvm_pfn_t pfn, bool dirty, struct gfn_to_pfn_cache *cache);
int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
@@ -943,14 +990,10 @@ void kvm_mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc);
void *kvm_mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc);
#endif
-bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req,
- struct kvm_vcpu *except,
- unsigned long *vcpu_bitmap, cpumask_var_t tmp);
-bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
-bool kvm_make_all_cpus_request_except(struct kvm *kvm, unsigned int req,
- struct kvm_vcpu *except);
-bool kvm_make_cpus_request_mask(struct kvm *kvm, unsigned int req,
- unsigned long *vcpu_bitmap);
+void kvm_inc_notifier_count(struct kvm *kvm, unsigned long start,
+ unsigned long end);
+void kvm_dec_notifier_count(struct kvm *kvm, unsigned long start,
+ unsigned long end);
long kvm_arch_dev_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg);
@@ -1034,6 +1077,7 @@ bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu);
bool kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu);
int kvm_arch_post_init_vm(struct kvm *kvm);
void kvm_arch_pre_destroy_vm(struct kvm *kvm);
+int kvm_arch_create_vm_debugfs(struct kvm *kvm);
#ifndef __KVM_HAVE_ARCH_VM_ALLOC
/*
@@ -1157,29 +1201,49 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args);
/*
- * search_memslots() and __gfn_to_memslot() are here because they are
- * used in non-modular code in arch/powerpc/kvm/book3s_hv_rm_mmu.c.
- * gfn_to_memslot() itself isn't here as an inline because that would
- * bloat other code too much.
+ * Returns a pointer to the memslot at slot_index if it contains gfn.
+ * Otherwise returns NULL.
+ */
+static inline struct kvm_memory_slot *
+try_get_memslot(struct kvm_memslots *slots, int slot_index, gfn_t gfn)
+{
+ struct kvm_memory_slot *slot;
+
+ if (slot_index < 0 || slot_index >= slots->used_slots)
+ return NULL;
+
+ /*
+ * slot_index can come from vcpu->last_used_slot which is not kept
+ * in sync with userspace-controllable memslot deletion. So use nospec
+ * to prevent the CPU from speculating past the end of memslots[].
+ */
+ slot_index = array_index_nospec(slot_index, slots->used_slots);
+ slot = &slots->memslots[slot_index];
+
+ if (gfn >= slot->base_gfn && gfn < slot->base_gfn + slot->npages)
+ return slot;
+ else
+ return NULL;
+}
+
+/*
+ * Returns a pointer to the memslot that contains gfn and records the index of
+ * the slot in index. Otherwise returns NULL.
*
* IMPORTANT: Slots are sorted from highest GFN to lowest GFN!
*/
static inline struct kvm_memory_slot *
-search_memslots(struct kvm_memslots *slots, gfn_t gfn)
+search_memslots(struct kvm_memslots *slots, gfn_t gfn, int *index)
{
int start = 0, end = slots->used_slots;
- int slot = atomic_read(&slots->lru_slot);
struct kvm_memory_slot *memslots = slots->memslots;
+ struct kvm_memory_slot *slot;
if (unlikely(!slots->used_slots))
return NULL;
- if (gfn >= memslots[slot].base_gfn &&
- gfn < memslots[slot].base_gfn + memslots[slot].npages)
- return &memslots[slot];
-
while (start < end) {
- slot = start + (end - start) / 2;
+ int slot = start + (end - start) / 2;
if (gfn >= memslots[slot].base_gfn)
end = slot;
@@ -1187,19 +1251,37 @@ search_memslots(struct kvm_memslots *slots, gfn_t gfn)
start = slot + 1;
}
- if (start < slots->used_slots && gfn >= memslots[start].base_gfn &&
- gfn < memslots[start].base_gfn + memslots[start].npages) {
- atomic_set(&slots->lru_slot, start);
- return &memslots[start];
+ slot = try_get_memslot(slots, start, gfn);
+ if (slot) {
+ *index = start;
+ return slot;
}
return NULL;
}
+/*
+ * __gfn_to_memslot() and its descendants are here because it is called from
+ * non-modular code in arch/powerpc/kvm/book3s_64_vio{,_hv}.c. gfn_to_memslot()
+ * itself isn't here as an inline because that would bloat other code too much.
+ */
static inline struct kvm_memory_slot *
__gfn_to_memslot(struct kvm_memslots *slots, gfn_t gfn)
{
- return search_memslots(slots, gfn);
+ struct kvm_memory_slot *slot;
+ int slot_index = atomic_read(&slots->last_used_slot);
+
+ slot = try_get_memslot(slots, slot_index, gfn);
+ if (slot)
+ return slot;
+
+ slot = search_memslots(slots, gfn, &slot_index);
+ if (slot) {
+ atomic_set(&slots->last_used_slot, slot_index);
+ return slot;
+ }
+
+ return NULL;
}
static inline unsigned long
@@ -1273,56 +1355,66 @@ struct _kvm_stats_desc {
char name[KVM_STATS_NAME_SIZE];
};
-#define STATS_DESC_COMMON(type, unit, base, exp) \
+#define STATS_DESC_COMMON(type, unit, base, exp, sz, bsz) \
.flags = type | unit | base | \
BUILD_BUG_ON_ZERO(type & ~KVM_STATS_TYPE_MASK) | \
BUILD_BUG_ON_ZERO(unit & ~KVM_STATS_UNIT_MASK) | \
BUILD_BUG_ON_ZERO(base & ~KVM_STATS_BASE_MASK), \
.exponent = exp, \
- .size = 1
+ .size = sz, \
+ .bucket_size = bsz
-#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp) \
+#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
{ \
{ \
- STATS_DESC_COMMON(type, unit, base, exp), \
+ STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
.offset = offsetof(struct kvm_vm_stat, generic.stat) \
}, \
.name = #stat, \
}
-#define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp) \
+#define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
{ \
{ \
- STATS_DESC_COMMON(type, unit, base, exp), \
+ STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
.offset = offsetof(struct kvm_vcpu_stat, generic.stat) \
}, \
.name = #stat, \
}
-#define VM_STATS_DESC(stat, type, unit, base, exp) \
+#define VM_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
{ \
{ \
- STATS_DESC_COMMON(type, unit, base, exp), \
+ STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
.offset = offsetof(struct kvm_vm_stat, stat) \
}, \
.name = #stat, \
}
-#define VCPU_STATS_DESC(stat, type, unit, base, exp) \
+#define VCPU_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
{ \
{ \
- STATS_DESC_COMMON(type, unit, base, exp), \
+ STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
.offset = offsetof(struct kvm_vcpu_stat, stat) \
}, \
.name = #stat, \
}
/* SCOPE: VM, VM_GENERIC, VCPU, VCPU_GENERIC */
-#define STATS_DESC(SCOPE, stat, type, unit, base, exp) \
- SCOPE##_STATS_DESC(stat, type, unit, base, exp)
+#define STATS_DESC(SCOPE, stat, type, unit, base, exp, sz, bsz) \
+ SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, bsz)
#define STATS_DESC_CUMULATIVE(SCOPE, name, unit, base, exponent) \
- STATS_DESC(SCOPE, name, KVM_STATS_TYPE_CUMULATIVE, unit, base, exponent)
+ STATS_DESC(SCOPE, name, KVM_STATS_TYPE_CUMULATIVE, \
+ unit, base, exponent, 1, 0)
#define STATS_DESC_INSTANT(SCOPE, name, unit, base, exponent) \
- STATS_DESC(SCOPE, name, KVM_STATS_TYPE_INSTANT, unit, base, exponent)
+ STATS_DESC(SCOPE, name, KVM_STATS_TYPE_INSTANT, \
+ unit, base, exponent, 1, 0)
#define STATS_DESC_PEAK(SCOPE, name, unit, base, exponent) \
- STATS_DESC(SCOPE, name, KVM_STATS_TYPE_PEAK, unit, base, exponent)
+ STATS_DESC(SCOPE, name, KVM_STATS_TYPE_PEAK, \
+ unit, base, exponent, 1, 0)
+#define STATS_DESC_LINEAR_HIST(SCOPE, name, unit, base, exponent, sz, bsz) \
+ STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST, \
+ unit, base, exponent, sz, bsz)
+#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz) \
+ STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST, \
+ unit, base, exponent, sz, 0)
/* Cumulative counter, read/write */
#define STATS_DESC_COUNTER(SCOPE, name) \
@@ -1341,9 +1433,18 @@ struct _kvm_stats_desc {
#define STATS_DESC_TIME_NSEC(SCOPE, name) \
STATS_DESC_CUMULATIVE(SCOPE, name, KVM_STATS_UNIT_SECONDS, \
KVM_STATS_BASE_POW10, -9)
+/* Linear histogram for time in nanosecond */
+#define STATS_DESC_LINHIST_TIME_NSEC(SCOPE, name, sz, bsz) \
+ STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS, \
+ KVM_STATS_BASE_POW10, -9, sz, bsz)
+/* Logarithmic histogram for time in nanosecond */
+#define STATS_DESC_LOGHIST_TIME_NSEC(SCOPE, name, sz) \
+ STATS_DESC_LOG_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS, \
+ KVM_STATS_BASE_POW10, -9, sz)
#define KVM_GENERIC_VM_STATS() \
- STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
+ STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush), \
+ STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush_requests)
#define KVM_GENERIC_VCPU_STATS() \
STATS_DESC_COUNTER(VCPU_GENERIC, halt_successful_poll), \
@@ -1351,13 +1452,62 @@ struct _kvm_stats_desc {
STATS_DESC_COUNTER(VCPU_GENERIC, halt_poll_invalid), \
STATS_DESC_COUNTER(VCPU_GENERIC, halt_wakeup), \
STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_success_ns), \
- STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns)
+ STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns), \
+ STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_wait_ns), \
+ STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_success_hist, \
+ HALT_POLL_HIST_COUNT), \
+ STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_hist, \
+ HALT_POLL_HIST_COUNT), \
+ STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_wait_hist, \
+ HALT_POLL_HIST_COUNT)
extern struct dentry *kvm_debugfs_dir;
+
ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
const struct _kvm_stats_desc *desc,
void *stats, size_t size_stats,
char __user *user_buffer, size_t size, loff_t *offset);
+
+/**
+ * kvm_stats_linear_hist_update() - Update bucket value for linear histogram
+ * statistics data.
+ *
+ * @data: start address of the stats data
+ * @size: the number of bucket of the stats data
+ * @value: the new value used to update the linear histogram's bucket
+ * @bucket_size: the size (width) of a bucket
+ */
+static inline void kvm_stats_linear_hist_update(u64 *data, size_t size,
+ u64 value, size_t bucket_size)
+{
+ size_t index = div64_u64(value, bucket_size);
+
+ index = min(index, size - 1);
+ ++data[index];
+}
+
+/**
+ * kvm_stats_log_hist_update() - Update bucket value for logarithmic histogram
+ * statistics data.
+ *
+ * @data: start address of the stats data
+ * @size: the number of bucket of the stats data
+ * @value: the new value used to update the logarithmic histogram's bucket
+ */
+static inline void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
+{
+ size_t index = fls64(value);
+
+ index = min(index, size - 1);
+ ++data[index];
+}
+
+#define KVM_STATS_LINEAR_HIST_UPDATE(array, value, bsize) \
+ kvm_stats_linear_hist_update(array, ARRAY_SIZE(array), value, bsize)
+#define KVM_STATS_LOG_HIST_UPDATE(array, value) \
+ kvm_stats_log_hist_update(array, ARRAY_SIZE(array), value)
+
+
extern const struct kvm_stats_header kvm_vm_stats_header;
extern const struct _kvm_stats_desc kvm_vm_stats_desc[];
extern const struct kvm_stats_header kvm_vcpu_stats_header;
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index ed6a985c5680..2237abb93ccd 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -76,8 +76,11 @@ struct kvm_mmu_memory_cache {
};
#endif
+#define HALT_POLL_HIST_COUNT 32
+
struct kvm_vm_stat_generic {
u64 remote_tlb_flush;
+ u64 remote_tlb_flush_requests;
};
struct kvm_vcpu_stat_generic {
@@ -87,6 +90,10 @@ struct kvm_vcpu_stat_generic {
u64 halt_wakeup;
u64 halt_poll_success_ns;
u64 halt_poll_fail_ns;
+ u64 halt_wait_ns;
+ u64 halt_poll_success_hist[HALT_POLL_HIST_COUNT];
+ u64 halt_poll_fail_hist[HALT_POLL_HIST_COUNT];
+ u64 halt_wait_hist[HALT_POLL_HIST_COUNT];
};
#define KVM_STATS_NAME_SIZE 48
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 860e63f5667b..c0c64f03e107 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -426,6 +426,7 @@ enum {
ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */
ATA_HORKAGE_MAX_SEC_1024 = (1 << 25), /* Limit max sects to 1024 */
ATA_HORKAGE_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */
+ ATA_HORKAGE_NO_NCQ_ON_ATI = (1 << 27), /* Disable NCQ on ATI chipset */
/* DMA mask for user DMA control: User visible values; DO NOT
renumber */
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 5cf387813754..9fe165beb0f9 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -306,31 +306,29 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);
#define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0)
-#define lockdep_assert_held(l) do { \
- WARN_ON(debug_locks && \
- lockdep_is_held(l) == LOCK_STATE_NOT_HELD); \
- } while (0)
+#define lockdep_assert(cond) \
+ do { WARN_ON(debug_locks && !(cond)); } while (0)
-#define lockdep_assert_not_held(l) do { \
- WARN_ON(debug_locks && \
- lockdep_is_held(l) == LOCK_STATE_HELD); \
- } while (0)
+#define lockdep_assert_once(cond) \
+ do { WARN_ON_ONCE(debug_locks && !(cond)); } while (0)
-#define lockdep_assert_held_write(l) do { \
- WARN_ON(debug_locks && !lockdep_is_held_type(l, 0)); \
- } while (0)
+#define lockdep_assert_held(l) \
+ lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD)
-#define lockdep_assert_held_read(l) do { \
- WARN_ON(debug_locks && !lockdep_is_held_type(l, 1)); \
- } while (0)
+#define lockdep_assert_not_held(l) \
+ lockdep_assert(lockdep_is_held(l) != LOCK_STATE_HELD)
-#define lockdep_assert_held_once(l) do { \
- WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \
- } while (0)
+#define lockdep_assert_held_write(l) \
+ lockdep_assert(lockdep_is_held_type(l, 0))
-#define lockdep_assert_none_held_once() do { \
- WARN_ON_ONCE(debug_locks && current->lockdep_depth); \
- } while (0)
+#define lockdep_assert_held_read(l) \
+ lockdep_assert(lockdep_is_held_type(l, 1))
+
+#define lockdep_assert_held_once(l) \
+ lockdep_assert_once(lockdep_is_held(l) != LOCK_STATE_NOT_HELD)
+
+#define lockdep_assert_none_held_once() \
+ lockdep_assert_once(!current->lockdep_depth)
#define lockdep_recursing(tsk) ((tsk)->lockdep_recursion)
@@ -407,6 +405,9 @@ extern int lock_is_held(const void *);
extern int lockdep_is_held(const void *);
#define lockdep_is_held_type(l, r) (1)
+#define lockdep_assert(c) do { } while (0)
+#define lockdep_assert_once(c) do { } while (0)
+
#define lockdep_assert_held(l) do { (void)(l); } while (0)
#define lockdep_assert_not_held(l) do { (void)(l); } while (0)
#define lockdep_assert_held_write(l) do { (void)(l); } while (0)
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index a7330eb3ec64..7dd1f01ec4f9 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -18,7 +18,6 @@
#ifndef mISDNIF_H
#define mISDNIF_H
-#include <stdarg.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/socket.h>
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 3a38598c2605..68427e8fadeb 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -72,11 +72,6 @@ struct device *mtype_get_parent_dev(struct mdev_type *mtype);
* @mdev: mdev_device device structure which is being
* destroyed
* Returns integer: success (0) or error (< 0)
- * @open: Open mediated device.
- * @mdev: mediated device.
- * Returns integer: success (0) or error (< 0)
- * @release: release mediated device
- * @mdev: mediated device.
* @read: Read emulation callback
* @mdev: mediated device structure
* @buf: read buffer
@@ -111,8 +106,8 @@ struct mdev_parent_ops {
int (*create)(struct mdev_device *mdev);
int (*remove)(struct mdev_device *mdev);
- int (*open)(struct mdev_device *mdev);
- void (*release)(struct mdev_device *mdev);
+ int (*open_device)(struct mdev_device *mdev);
+ void (*close_device)(struct mdev_device *mdev);
ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
size_t count, loff_t *ppos);
ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index 07f5ef8fc456..c6786c12b207 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -91,12 +91,13 @@ void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv);
mei_cldev_driver_register,\
mei_cldev_driver_unregister)
-ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length);
+ssize_t mei_cldev_send(struct mei_cl_device *cldev, const u8 *buf,
+ size_t length);
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
size_t length);
-ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
- u8 vtag);
+ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, const u8 *buf,
+ size_t length, u8 vtag);
ssize_t mei_cldev_recv_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
u8 *vtag);
ssize_t mei_cldev_recv_nonblock_vtag(struct mei_cl_device *cldev, u8 *buf,
@@ -114,6 +115,6 @@ void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data);
int mei_cldev_enable(struct mei_cl_device *cldev);
int mei_cldev_disable(struct mei_cl_device *cldev);
-bool mei_cldev_enabled(struct mei_cl_device *cldev);
+bool mei_cldev_enabled(const struct mei_cl_device *cldev);
#endif /* _LINUX_MEI_CL_BUS_H */
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 4a53c3ca86bd..b066024c62e3 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -99,8 +99,6 @@ void memblock_discard(void);
static inline void memblock_discard(void) {}
#endif
-phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,
- phys_addr_t size, phys_addr_t align);
void memblock_allow_resize(void);
int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid);
int memblock_add(phys_addr_t base, phys_addr_t size);
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 20151c4f1e0e..3096c9a0ee01 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -105,14 +105,6 @@ struct mem_cgroup_reclaim_iter {
unsigned int generation;
};
-struct lruvec_stat {
- long count[NR_VM_NODE_STAT_ITEMS];
-};
-
-struct batched_lruvec_stat {
- s32 count[NR_VM_NODE_STAT_ITEMS];
-};
-
/*
* Bitmap and deferred work of shrinker::id corresponding to memcg-aware
* shrinkers, which have elements charged to this memcg.
@@ -123,24 +115,30 @@ struct shrinker_info {
unsigned long *map;
};
+struct lruvec_stats_percpu {
+ /* Local (CPU and cgroup) state */
+ long state[NR_VM_NODE_STAT_ITEMS];
+
+ /* Delta calculation for lockless upward propagation */
+ long state_prev[NR_VM_NODE_STAT_ITEMS];
+};
+
+struct lruvec_stats {
+ /* Aggregated (CPU and subtree) state */
+ long state[NR_VM_NODE_STAT_ITEMS];
+
+ /* Pending child counts during tree propagation */
+ long state_pending[NR_VM_NODE_STAT_ITEMS];
+};
+
/*
* per-node information in memory controller.
*/
struct mem_cgroup_per_node {
struct lruvec lruvec;
- /*
- * Legacy local VM stats. This should be struct lruvec_stat and
- * cannot be optimized to struct batched_lruvec_stat. Because
- * the threshold of the lruvec_stat_cpu can be as big as
- * MEMCG_CHARGE_BATCH * PAGE_SIZE. It can fit into s32. But this
- * filed has no upper limit.
- */
- struct lruvec_stat __percpu *lruvec_stat_local;
-
- /* Subtree VM stats (batched updates) */
- struct batched_lruvec_stat __percpu *lruvec_stat_cpu;
- atomic_long_t lruvec_stat[NR_VM_NODE_STAT_ITEMS];
+ struct lruvec_stats_percpu __percpu *lruvec_stats_percpu;
+ struct lruvec_stats lruvec_stats;
unsigned long lru_zone_size[MAX_NR_ZONES][NR_LRU_LISTS];
@@ -595,13 +593,6 @@ static inline struct obj_cgroup **page_objcgs_check(struct page *page)
}
#endif
-static __always_inline bool memcg_stat_item_in_bytes(int idx)
-{
- if (idx == MEMCG_PERCPU_B)
- return true;
- return vmstat_item_in_bytes(idx);
-}
-
static inline bool mem_cgroup_is_root(struct mem_cgroup *memcg)
{
return (memcg == root_mem_cgroup);
@@ -693,13 +684,35 @@ static inline bool mem_cgroup_below_min(struct mem_cgroup *memcg)
page_counter_read(&memcg->memory);
}
-int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask);
+int __mem_cgroup_charge(struct page *page, struct mm_struct *mm,
+ gfp_t gfp_mask);
+static inline int mem_cgroup_charge(struct page *page, struct mm_struct *mm,
+ gfp_t gfp_mask)
+{
+ if (mem_cgroup_disabled())
+ return 0;
+ return __mem_cgroup_charge(page, mm, gfp_mask);
+}
+
int mem_cgroup_swapin_charge_page(struct page *page, struct mm_struct *mm,
gfp_t gfp, swp_entry_t entry);
void mem_cgroup_swapin_uncharge_swap(swp_entry_t entry);
-void mem_cgroup_uncharge(struct page *page);
-void mem_cgroup_uncharge_list(struct list_head *page_list);
+void __mem_cgroup_uncharge(struct page *page);
+static inline void mem_cgroup_uncharge(struct page *page)
+{
+ if (mem_cgroup_disabled())
+ return;
+ __mem_cgroup_uncharge(page);
+}
+
+void __mem_cgroup_uncharge_list(struct list_head *page_list);
+static inline void mem_cgroup_uncharge_list(struct list_head *page_list)
+{
+ if (mem_cgroup_disabled())
+ return;
+ __mem_cgroup_uncharge_list(page_list);
+}
void mem_cgroup_migrate(struct page *oldpage, struct page *newpage);
@@ -884,11 +897,6 @@ static inline bool mem_cgroup_online(struct mem_cgroup *memcg)
return !!(memcg->css.flags & CSS_ONLINE);
}
-/*
- * For memory reclaim.
- */
-int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);
-
void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
int zid, int nr_pages);
@@ -955,22 +963,21 @@ static inline void mod_memcg_state(struct mem_cgroup *memcg,
local_irq_restore(flags);
}
+static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)
+{
+ return READ_ONCE(memcg->vmstats.state[idx]);
+}
+
static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
enum node_stat_item idx)
{
struct mem_cgroup_per_node *pn;
- long x;
if (mem_cgroup_disabled())
return node_page_state(lruvec_pgdat(lruvec), idx);
pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
- x = atomic_long_read(&pn->lruvec_stat[idx]);
-#ifdef CONFIG_SMP
- if (x < 0)
- x = 0;
-#endif
- return x;
+ return READ_ONCE(pn->lruvec_stats.state[idx]);
}
static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
@@ -985,7 +992,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
for_each_possible_cpu(cpu)
- x += per_cpu(pn->lruvec_stat_local->count[idx], cpu);
+ x += per_cpu(pn->lruvec_stats_percpu->state[idx], cpu);
#ifdef CONFIG_SMP
if (x < 0)
x = 0;
@@ -993,6 +1000,8 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
return x;
}
+void mem_cgroup_flush_stats(void);
+
void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
int val);
void __mod_lruvec_kmem_state(void *p, enum node_stat_item idx, int val);
@@ -1391,6 +1400,11 @@ static inline void mod_memcg_state(struct mem_cgroup *memcg,
{
}
+static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)
+{
+ return 0;
+}
+
static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
enum node_stat_item idx)
{
@@ -1403,6 +1417,10 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
return node_page_state(lruvec_pgdat(lruvec), idx);
}
+static inline void mem_cgroup_flush_stats(void)
+{
+}
+
static inline void __mod_memcg_lruvec_state(struct lruvec *lruvec,
enum node_stat_item idx, int val)
{
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 97e92e8b556a..d9a0b61cd432 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -90,7 +90,7 @@ int create_memory_block_devices(unsigned long start, unsigned long size,
void remove_memory_block_devices(unsigned long start, unsigned long size);
extern void memory_dev_init(void);
extern int memory_notify(unsigned long val, void *v);
-extern struct memory_block *find_memory_block(struct mem_section *);
+extern struct memory_block *find_memory_block(unsigned long section_nr);
typedef int (*walk_memory_blocks_func_t)(struct memory_block *, void *);
extern int walk_memory_blocks(unsigned long start, unsigned long size,
void *arg, walk_memory_blocks_func_t func);
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 0aaf91b496e2..4091692bed8c 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -184,6 +184,14 @@ extern bool vma_migratable(struct vm_area_struct *vma);
extern int mpol_misplaced(struct page *, struct vm_area_struct *, unsigned long);
extern void mpol_put_task_policy(struct task_struct *);
+extern bool numa_demotion_enabled;
+
+static inline bool mpol_is_preferred_many(struct mempolicy *pol)
+{
+ return (pol->mode == MPOL_PREFERRED_MANY);
+}
+
+
#else
struct mempolicy {};
@@ -292,5 +300,13 @@ static inline nodemask_t *policy_nodemask_current(gfp_t gfp)
{
return NULL;
}
+
+#define numa_demotion_enabled false
+
+static inline bool mpol_is_preferred_many(struct mempolicy *pol)
+{
+ return false;
+}
+
#endif /* CONFIG_NUMA */
#endif
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index e6ee2ec35de9..cbf9d7619493 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -186,10 +186,11 @@ enum ddr_pwrst {
#define PRCMU_FW_PROJECT_U8500_C3 8
#define PRCMU_FW_PROJECT_U8500_C4 9
#define PRCMU_FW_PROJECT_U9500_MBL 10
-#define PRCMU_FW_PROJECT_U8500_MBL 11 /* Customer specific */
+#define PRCMU_FW_PROJECT_U8500_SSG1 11 /* Samsung specific */
#define PRCMU_FW_PROJECT_U8500_MBL2 12 /* Customer specific */
#define PRCMU_FW_PROJECT_U8520 13
#define PRCMU_FW_PROJECT_U8420 14
+#define PRCMU_FW_PROJECT_U8500_SSG2 15 /* Samsung specific */
#define PRCMU_FW_PROJECT_U8420_SYSCLK 17
#define PRCMU_FW_PROJECT_A9420 20
/* [32..63] 9540 and derivatives */
diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h
index 2660226138b8..e5b8dbf828b6 100644
--- a/include/linux/mfd/hi6421-spmi-pmic.h
+++ b/include/linux/mfd/hi6421-spmi-pmic.h
@@ -19,11 +19,6 @@ struct hi6421_spmi_pmic {
struct resource *res;
struct device *dev;
void __iomem *regs;
- spinlock_t lock;
- struct irq_domain *domain;
- int irq;
- int gpio;
- unsigned int *irqs;
struct regmap *regmap;
};
diff --git a/include/linux/mfd/idt82p33_reg.h b/include/linux/mfd/idt82p33_reg.h
new file mode 100644
index 000000000000..129a6c078221
--- /dev/null
+++ b/include/linux/mfd/idt82p33_reg.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Register Map - Based on AN888_SMUforIEEE_SynchEther_82P33xxx_RevH.pdf
+ *
+ * Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
+ */
+#ifndef HAVE_IDT82P33_REG
+#define HAVE_IDT82P33_REG
+
+/* Register address */
+#define DPLL1_TOD_CNFG 0x134
+#define DPLL2_TOD_CNFG 0x1B4
+
+#define DPLL1_TOD_STS 0x10B
+#define DPLL2_TOD_STS 0x18B
+
+#define DPLL1_TOD_TRIGGER 0x115
+#define DPLL2_TOD_TRIGGER 0x195
+
+#define DPLL1_OPERATING_MODE_CNFG 0x120
+#define DPLL2_OPERATING_MODE_CNFG 0x1A0
+
+#define DPLL1_HOLDOVER_FREQ_CNFG 0x12C
+#define DPLL2_HOLDOVER_FREQ_CNFG 0x1AC
+
+#define DPLL1_PHASE_OFFSET_CNFG 0x143
+#define DPLL2_PHASE_OFFSET_CNFG 0x1C3
+
+#define DPLL1_SYNC_EDGE_CNFG 0x140
+#define DPLL2_SYNC_EDGE_CNFG 0x1C0
+
+#define DPLL1_INPUT_MODE_CNFG 0x116
+#define DPLL2_INPUT_MODE_CNFG 0x196
+
+#define DPLL1_OPERATING_STS 0x102
+#define DPLL2_OPERATING_STS 0x182
+
+#define DPLL1_CURRENT_FREQ_STS 0x103
+#define DPLL2_CURRENT_FREQ_STS 0x183
+
+#define REG_SOFT_RESET 0X381
+
+#define OUT_MUX_CNFG(outn) REG_ADDR(0x6, (0xC * (outn)))
+
+/* Register bit definitions */
+#define SYNC_TOD BIT(1)
+#define PH_OFFSET_EN BIT(7)
+#define SQUELCH_ENABLE BIT(5)
+
+/* Bit definitions for the DPLL_MODE register */
+#define PLL_MODE_SHIFT (0)
+#define PLL_MODE_MASK (0x1F)
+#define COMBO_MODE_EN BIT(5)
+#define COMBO_MODE_SHIFT (6)
+#define COMBO_MODE_MASK (0x3)
+
+/* Bit definitions for DPLL_OPERATING_STS register */
+#define OPERATING_STS_MASK (0x7)
+#define OPERATING_STS_SHIFT (0x0)
+
+/* Bit definitions for DPLL_TOD_TRIGGER register */
+#define READ_TRIGGER_MASK (0xF)
+#define READ_TRIGGER_SHIFT (0x0)
+#define WRITE_TRIGGER_MASK (0xF0)
+#define WRITE_TRIGGER_SHIFT (0x4)
+
+/* Bit definitions for REG_SOFT_RESET register */
+#define SOFT_RESET_EN BIT(7)
+
+enum pll_mode {
+ PLL_MODE_MIN = 0,
+ PLL_MODE_AUTOMATIC = PLL_MODE_MIN,
+ PLL_MODE_FORCE_FREERUN = 1,
+ PLL_MODE_FORCE_HOLDOVER = 2,
+ PLL_MODE_FORCE_LOCKED = 4,
+ PLL_MODE_FORCE_PRE_LOCKED2 = 5,
+ PLL_MODE_FORCE_PRE_LOCKED = 6,
+ PLL_MODE_FORCE_LOST_PHASE = 7,
+ PLL_MODE_DCO = 10,
+ PLL_MODE_WPH = 18,
+ PLL_MODE_MAX = PLL_MODE_WPH,
+};
+
+enum hw_tod_trig_sel {
+ HW_TOD_TRIG_SEL_MIN = 0,
+ HW_TOD_TRIG_SEL_NO_WRITE = HW_TOD_TRIG_SEL_MIN,
+ HW_TOD_TRIG_SEL_NO_READ = HW_TOD_TRIG_SEL_MIN,
+ HW_TOD_TRIG_SEL_SYNC_SEL = 1,
+ HW_TOD_TRIG_SEL_IN12 = 2,
+ HW_TOD_TRIG_SEL_IN13 = 3,
+ HW_TOD_TRIG_SEL_IN14 = 4,
+ HW_TOD_TRIG_SEL_TOD_PPS = 5,
+ HW_TOD_TRIG_SEL_TIMER_INTERVAL = 6,
+ HW_TOD_TRIG_SEL_MSB_PHASE_OFFSET_CNFG = 7,
+ HW_TOD_TRIG_SEL_MSB_HOLDOVER_FREQ_CNFG = 8,
+ HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG = 9,
+ HW_TOD_RD_TRIG_SEL_LSB_TOD_STS = HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
+ WR_TRIG_SEL_MAX = HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
+};
+
+/** @brief Enumerated type listing DPLL operational modes */
+enum dpll_state {
+ DPLL_STATE_FREERUN = 1,
+ DPLL_STATE_HOLDOVER = 2,
+ DPLL_STATE_LOCKED = 4,
+ DPLL_STATE_PRELOCKED2 = 5,
+ DPLL_STATE_PRELOCKED = 6,
+ DPLL_STATE_LOSTPHASE = 7,
+ DPLL_STATE_MAX
+};
+
+#endif
diff --git a/include/linux/mfd/idt8a340_reg.h b/include/linux/mfd/idt8a340_reg.h
new file mode 100644
index 000000000000..92d763230bdf
--- /dev/null
+++ b/include/linux/mfd/idt8a340_reg.h
@@ -0,0 +1,729 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Based on 5.2.0, Family Programming Guide (Sept 30, 2020)
+ *
+ * Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
+ */
+#ifndef HAVE_IDT8A340_REG
+#define HAVE_IDT8A340_REG
+
+#define PAGE_ADDR_BASE 0x0000
+#define PAGE_ADDR 0x00fc
+
+#define HW_REVISION 0x8180
+#define REV_ID 0x007a
+
+#define HW_DPLL_0 (0x8a00)
+#define HW_DPLL_1 (0x8b00)
+#define HW_DPLL_2 (0x8c00)
+#define HW_DPLL_3 (0x8d00)
+#define HW_DPLL_4 (0x8e00)
+#define HW_DPLL_5 (0x8f00)
+#define HW_DPLL_6 (0x9000)
+#define HW_DPLL_7 (0x9100)
+
+#define HW_DPLL_TOD_SW_TRIG_ADDR__0 (0x080)
+#define HW_DPLL_TOD_CTRL_1 (0x089)
+#define HW_DPLL_TOD_CTRL_2 (0x08A)
+#define HW_DPLL_TOD_OVR__0 (0x098)
+#define HW_DPLL_TOD_OUT_0__0 (0x0B0)
+
+#define HW_Q0_Q1_CH_SYNC_CTRL_0 (0xa740)
+#define HW_Q0_Q1_CH_SYNC_CTRL_1 (0xa741)
+#define HW_Q2_Q3_CH_SYNC_CTRL_0 (0xa742)
+#define HW_Q2_Q3_CH_SYNC_CTRL_1 (0xa743)
+#define HW_Q4_Q5_CH_SYNC_CTRL_0 (0xa744)
+#define HW_Q4_Q5_CH_SYNC_CTRL_1 (0xa745)
+#define HW_Q6_Q7_CH_SYNC_CTRL_0 (0xa746)
+#define HW_Q6_Q7_CH_SYNC_CTRL_1 (0xa747)
+#define HW_Q8_CH_SYNC_CTRL_0 (0xa748)
+#define HW_Q8_CH_SYNC_CTRL_1 (0xa749)
+#define HW_Q9_CH_SYNC_CTRL_0 (0xa74a)
+#define HW_Q9_CH_SYNC_CTRL_1 (0xa74b)
+#define HW_Q10_CH_SYNC_CTRL_0 (0xa74c)
+#define HW_Q10_CH_SYNC_CTRL_1 (0xa74d)
+#define HW_Q11_CH_SYNC_CTRL_0 (0xa74e)
+#define HW_Q11_CH_SYNC_CTRL_1 (0xa74f)
+
+#define SYNC_SOURCE_DPLL0_TOD_PPS 0x14
+#define SYNC_SOURCE_DPLL1_TOD_PPS 0x15
+#define SYNC_SOURCE_DPLL2_TOD_PPS 0x16
+#define SYNC_SOURCE_DPLL3_TOD_PPS 0x17
+
+#define SYNCTRL1_MASTER_SYNC_RST BIT(7)
+#define SYNCTRL1_MASTER_SYNC_TRIG BIT(5)
+#define SYNCTRL1_TOD_SYNC_TRIG BIT(4)
+#define SYNCTRL1_FBDIV_FRAME_SYNC_TRIG BIT(3)
+#define SYNCTRL1_FBDIV_SYNC_TRIG BIT(2)
+#define SYNCTRL1_Q1_DIV_SYNC_TRIG BIT(1)
+#define SYNCTRL1_Q0_DIV_SYNC_TRIG BIT(0)
+
+#define HW_Q8_CTRL_SPARE (0xa7d4)
+#define HW_Q11_CTRL_SPARE (0xa7ec)
+
+/**
+ * Select FOD5 as sync_trigger for Q8 divider.
+ * Transition from logic zero to one
+ * sets trigger to sync Q8 divider.
+ *
+ * Unused when FOD4 is driving Q8 divider (normal operation).
+ */
+#define Q9_TO_Q8_SYNC_TRIG BIT(1)
+
+/**
+ * Enable FOD5 as driver for clock and sync for Q8 divider.
+ * Enable fanout buffer for FOD5.
+ *
+ * Unused when FOD4 is driving Q8 divider (normal operation).
+ */
+#define Q9_TO_Q8_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK (BIT(0) | BIT(2))
+
+/**
+ * Select FOD6 as sync_trigger for Q11 divider.
+ * Transition from logic zero to one
+ * sets trigger to sync Q11 divider.
+ *
+ * Unused when FOD7 is driving Q11 divider (normal operation).
+ */
+#define Q10_TO_Q11_SYNC_TRIG BIT(1)
+
+/**
+ * Enable FOD6 as driver for clock and sync for Q11 divider.
+ * Enable fanout buffer for FOD6.
+ *
+ * Unused when FOD7 is driving Q11 divider (normal operation).
+ */
+#define Q10_TO_Q11_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK (BIT(0) | BIT(2))
+
+#define RESET_CTRL 0xc000
+#define SM_RESET 0x0012
+#define SM_RESET_V520 0x0013
+#define SM_RESET_CMD 0x5A
+
+#define GENERAL_STATUS 0xc014
+#define BOOT_STATUS 0x0000
+#define HW_REV_ID 0x000A
+#define BOND_ID 0x000B
+#define HW_CSR_ID 0x000C
+#define HW_IRQ_ID 0x000E
+#define MAJ_REL 0x0010
+#define MIN_REL 0x0011
+#define HOTFIX_REL 0x0012
+#define PIPELINE_ID 0x0014
+#define BUILD_ID 0x0018
+#define JTAG_DEVICE_ID 0x001c
+#define PRODUCT_ID 0x001e
+#define OTP_SCSR_CONFIG_SELECT 0x0022
+
+#define STATUS 0xc03c
+#define DPLL0_STATUS 0x0018
+#define DPLL1_STATUS 0x0019
+#define DPLL2_STATUS 0x001a
+#define DPLL3_STATUS 0x001b
+#define DPLL4_STATUS 0x001c
+#define DPLL5_STATUS 0x001d
+#define DPLL6_STATUS 0x001e
+#define DPLL7_STATUS 0x001f
+#define DPLL_SYS_STATUS 0x0020
+#define DPLL_SYS_APLL_STATUS 0x0021
+#define DPLL0_FILTER_STATUS 0x0044
+#define DPLL1_FILTER_STATUS 0x004c
+#define DPLL2_FILTER_STATUS 0x0054
+#define DPLL3_FILTER_STATUS 0x005c
+#define DPLL4_FILTER_STATUS 0x0064
+#define DPLL5_FILTER_STATUS 0x006c
+#define DPLL6_FILTER_STATUS 0x0074
+#define DPLL7_FILTER_STATUS 0x007c
+#define DPLLSYS_FILTER_STATUS 0x0084
+#define USER_GPIO0_TO_7_STATUS 0x008a
+#define USER_GPIO8_TO_15_STATUS 0x008b
+
+#define GPIO_USER_CONTROL 0xc160
+#define GPIO0_TO_7_OUT 0x0000
+#define GPIO8_TO_15_OUT 0x0001
+#define GPIO0_TO_7_OUT_V520 0x0002
+#define GPIO8_TO_15_OUT_V520 0x0003
+
+#define STICKY_STATUS_CLEAR 0xc164
+
+#define GPIO_TOD_NOTIFICATION_CLEAR 0xc16c
+
+#define ALERT_CFG 0xc188
+
+#define SYS_DPLL_XO 0xc194
+
+#define SYS_APLL 0xc19c
+
+#define INPUT_0 0xc1b0
+#define INPUT_1 0xc1c0
+#define INPUT_2 0xc1d0
+#define INPUT_3 0xc200
+#define INPUT_4 0xc210
+#define INPUT_5 0xc220
+#define INPUT_6 0xc230
+#define INPUT_7 0xc240
+#define INPUT_8 0xc250
+#define INPUT_9 0xc260
+#define INPUT_10 0xc280
+#define INPUT_11 0xc290
+#define INPUT_12 0xc2a0
+#define INPUT_13 0xc2b0
+#define INPUT_14 0xc2c0
+#define INPUT_15 0xc2d0
+
+#define REF_MON_0 0xc2e0
+#define REF_MON_1 0xc2ec
+#define REF_MON_2 0xc300
+#define REF_MON_3 0xc30c
+#define REF_MON_4 0xc318
+#define REF_MON_5 0xc324
+#define REF_MON_6 0xc330
+#define REF_MON_7 0xc33c
+#define REF_MON_8 0xc348
+#define REF_MON_9 0xc354
+#define REF_MON_10 0xc360
+#define REF_MON_11 0xc36c
+#define REF_MON_12 0xc380
+#define REF_MON_13 0xc38c
+#define REF_MON_14 0xc398
+#define REF_MON_15 0xc3a4
+
+#define DPLL_0 0xc3b0
+#define DPLL_CTRL_REG_0 0x0002
+#define DPLL_CTRL_REG_1 0x0003
+#define DPLL_CTRL_REG_2 0x0004
+#define DPLL_TOD_SYNC_CFG 0x0031
+#define DPLL_COMBO_SLAVE_CFG_0 0x0032
+#define DPLL_COMBO_SLAVE_CFG_1 0x0033
+#define DPLL_SLAVE_REF_CFG 0x0034
+#define DPLL_REF_MODE 0x0035
+#define DPLL_PHASE_MEASUREMENT_CFG 0x0036
+#define DPLL_MODE 0x0037
+#define DPLL_MODE_V520 0x003B
+#define DPLL_1 0xc400
+#define DPLL_2 0xc438
+#define DPLL_2_V520 0xc43c
+#define DPLL_3 0xc480
+#define DPLL_4 0xc4b8
+#define DPLL_4_V520 0xc4bc
+#define DPLL_5 0xc500
+#define DPLL_6 0xc538
+#define DPLL_6_V520 0xc53c
+#define DPLL_7 0xc580
+#define SYS_DPLL 0xc5b8
+#define SYS_DPLL_V520 0xc5bc
+
+#define DPLL_CTRL_0 0xc600
+#define DPLL_CTRL_DPLL_MANU_REF_CFG 0x0001
+#define DPLL_CTRL_DPLL_FOD_FREQ 0x001c
+#define DPLL_CTRL_COMBO_MASTER_CFG 0x003a
+#define DPLL_CTRL_1 0xc63c
+#define DPLL_CTRL_2 0xc680
+#define DPLL_CTRL_3 0xc6bc
+#define DPLL_CTRL_4 0xc700
+#define DPLL_CTRL_5 0xc73c
+#define DPLL_CTRL_6 0xc780
+#define DPLL_CTRL_7 0xc7bc
+#define SYS_DPLL_CTRL 0xc800
+
+#define DPLL_PHASE_0 0xc818
+/* Signed 42-bit FFO in units of 2^(-53) */
+#define DPLL_WR_PHASE 0x0000
+#define DPLL_PHASE_1 0xc81c
+#define DPLL_PHASE_2 0xc820
+#define DPLL_PHASE_3 0xc824
+#define DPLL_PHASE_4 0xc828
+#define DPLL_PHASE_5 0xc82c
+#define DPLL_PHASE_6 0xc830
+#define DPLL_PHASE_7 0xc834
+
+#define DPLL_FREQ_0 0xc838
+/* Signed 42-bit FFO in units of 2^(-53) */
+#define DPLL_WR_FREQ 0x0000
+#define DPLL_FREQ_1 0xc840
+#define DPLL_FREQ_2 0xc848
+#define DPLL_FREQ_3 0xc850
+#define DPLL_FREQ_4 0xc858
+#define DPLL_FREQ_5 0xc860
+#define DPLL_FREQ_6 0xc868
+#define DPLL_FREQ_7 0xc870
+
+#define DPLL_PHASE_PULL_IN_0 0xc880
+#define PULL_IN_OFFSET 0x0000 /* Signed 32 bit */
+#define PULL_IN_SLOPE_LIMIT 0x0004 /* Unsigned 24 bit */
+#define PULL_IN_CTRL 0x0007
+#define DPLL_PHASE_PULL_IN_1 0xc888
+#define DPLL_PHASE_PULL_IN_2 0xc890
+#define DPLL_PHASE_PULL_IN_3 0xc898
+#define DPLL_PHASE_PULL_IN_4 0xc8a0
+#define DPLL_PHASE_PULL_IN_5 0xc8a8
+#define DPLL_PHASE_PULL_IN_6 0xc8b0
+#define DPLL_PHASE_PULL_IN_7 0xc8b8
+
+#define GPIO_CFG 0xc8c0
+#define GPIO_CFG_GBL 0x0000
+#define GPIO_0 0xc8c2
+#define GPIO_DCO_INC_DEC 0x0000
+#define GPIO_OUT_CTRL_0 0x0001
+#define GPIO_OUT_CTRL_1 0x0002
+#define GPIO_TOD_TRIG 0x0003
+#define GPIO_DPLL_INDICATOR 0x0004
+#define GPIO_LOS_INDICATOR 0x0005
+#define GPIO_REF_INPUT_DSQ_0 0x0006
+#define GPIO_REF_INPUT_DSQ_1 0x0007
+#define GPIO_REF_INPUT_DSQ_2 0x0008
+#define GPIO_REF_INPUT_DSQ_3 0x0009
+#define GPIO_MAN_CLK_SEL_0 0x000a
+#define GPIO_MAN_CLK_SEL_1 0x000b
+#define GPIO_MAN_CLK_SEL_2 0x000c
+#define GPIO_SLAVE 0x000d
+#define GPIO_ALERT_OUT_CFG 0x000e
+#define GPIO_TOD_NOTIFICATION_CFG 0x000f
+#define GPIO_CTRL 0x0010
+#define GPIO_CTRL_V520 0x0011
+#define GPIO_1 0xc8d4
+#define GPIO_2 0xc8e6
+#define GPIO_3 0xc900
+#define GPIO_4 0xc912
+#define GPIO_5 0xc924
+#define GPIO_6 0xc936
+#define GPIO_7 0xc948
+#define GPIO_8 0xc95a
+#define GPIO_9 0xc980
+#define GPIO_10 0xc992
+#define GPIO_11 0xc9a4
+#define GPIO_12 0xc9b6
+#define GPIO_13 0xc9c8
+#define GPIO_14 0xc9da
+#define GPIO_15 0xca00
+
+#define OUT_DIV_MUX 0xca12
+#define OUTPUT_0 0xca14
+#define OUTPUT_0_V520 0xca20
+/* FOD frequency output divider value */
+#define OUT_DIV 0x0000
+#define OUT_DUTY_CYCLE_HIGH 0x0004
+#define OUT_CTRL_0 0x0008
+#define OUT_CTRL_1 0x0009
+/* Phase adjustment in FOD cycles */
+#define OUT_PHASE_ADJ 0x000c
+#define OUTPUT_1 0xca24
+#define OUTPUT_1_V520 0xca30
+#define OUTPUT_2 0xca34
+#define OUTPUT_2_V520 0xca40
+#define OUTPUT_3 0xca44
+#define OUTPUT_3_V520 0xca50
+#define OUTPUT_4 0xca54
+#define OUTPUT_4_V520 0xca60
+#define OUTPUT_5 0xca64
+#define OUTPUT_5_V520 0xca80
+#define OUTPUT_6 0xca80
+#define OUTPUT_6_V520 0xca90
+#define OUTPUT_7 0xca90
+#define OUTPUT_7_V520 0xcaa0
+#define OUTPUT_8 0xcaa0
+#define OUTPUT_8_V520 0xcab0
+#define OUTPUT_9 0xcab0
+#define OUTPUT_9_V520 0xcac0
+#define OUTPUT_10 0xcac0
+#define OUTPUT_10_V520 0xcad0
+#define OUTPUT_11 0xcad0
+#define OUTPUT_11_V520 0xcae0
+
+#define SERIAL 0xcae0
+#define SERIAL_V520 0xcaf0
+
+#define PWM_ENCODER_0 0xcb00
+#define PWM_ENCODER_1 0xcb08
+#define PWM_ENCODER_2 0xcb10
+#define PWM_ENCODER_3 0xcb18
+#define PWM_ENCODER_4 0xcb20
+#define PWM_ENCODER_5 0xcb28
+#define PWM_ENCODER_6 0xcb30
+#define PWM_ENCODER_7 0xcb38
+#define PWM_DECODER_0 0xcb40
+#define PWM_DECODER_1 0xcb48
+#define PWM_DECODER_1_V520 0xcb4a
+#define PWM_DECODER_2 0xcb50
+#define PWM_DECODER_2_V520 0xcb54
+#define PWM_DECODER_3 0xcb58
+#define PWM_DECODER_3_V520 0xcb5e
+#define PWM_DECODER_4 0xcb60
+#define PWM_DECODER_4_V520 0xcb68
+#define PWM_DECODER_5 0xcb68
+#define PWM_DECODER_5_V520 0xcb80
+#define PWM_DECODER_6 0xcb70
+#define PWM_DECODER_6_V520 0xcb8a
+#define PWM_DECODER_7 0xcb80
+#define PWM_DECODER_7_V520 0xcb94
+#define PWM_DECODER_8 0xcb88
+#define PWM_DECODER_8_V520 0xcb9e
+#define PWM_DECODER_9 0xcb90
+#define PWM_DECODER_9_V520 0xcba8
+#define PWM_DECODER_10 0xcb98
+#define PWM_DECODER_10_V520 0xcbb2
+#define PWM_DECODER_11 0xcba0
+#define PWM_DECODER_11_V520 0xcbbc
+#define PWM_DECODER_12 0xcba8
+#define PWM_DECODER_12_V520 0xcbc6
+#define PWM_DECODER_13 0xcbb0
+#define PWM_DECODER_13_V520 0xcbd0
+#define PWM_DECODER_14 0xcbb8
+#define PWM_DECODER_14_V520 0xcbda
+#define PWM_DECODER_15 0xcbc0
+#define PWM_DECODER_15_V520 0xcbe4
+#define PWM_USER_DATA 0xcbc8
+#define PWM_USER_DATA_V520 0xcbf0
+
+#define TOD_0 0xcbcc
+#define TOD_0_V520 0xcc00
+/* Enable TOD counter, output channel sync and even-PPS mode */
+#define TOD_CFG 0x0000
+#define TOD_CFG_V520 0x0001
+#define TOD_1 0xcbce
+#define TOD_1_V520 0xcc02
+#define TOD_2 0xcbd0
+#define TOD_2_V520 0xcc04
+#define TOD_3 0xcbd2
+#define TOD_3_V520 0xcc06
+
+#define TOD_WRITE_0 0xcc00
+#define TOD_WRITE_0_V520 0xcc10
+/* 8-bit subns, 32-bit ns, 48-bit seconds */
+#define TOD_WRITE 0x0000
+/* Counter increments after TOD write is completed */
+#define TOD_WRITE_COUNTER 0x000c
+/* TOD write trigger configuration */
+#define TOD_WRITE_SELECT_CFG_0 0x000d
+/* TOD write trigger selection */
+#define TOD_WRITE_CMD 0x000f
+#define TOD_WRITE_1 0xcc10
+#define TOD_WRITE_1_V520 0xcc20
+#define TOD_WRITE_2 0xcc20
+#define TOD_WRITE_2_V520 0xcc30
+#define TOD_WRITE_3 0xcc30
+#define TOD_WRITE_3_V520 0xcc40
+
+#define TOD_READ_PRIMARY_0 0xcc40
+#define TOD_READ_PRIMARY_0_V520 0xcc50
+/* 8-bit subns, 32-bit ns, 48-bit seconds */
+#define TOD_READ_PRIMARY 0x0000
+/* Counter increments after TOD write is completed */
+#define TOD_READ_PRIMARY_COUNTER 0x000b
+/* Read trigger configuration */
+#define TOD_READ_PRIMARY_SEL_CFG_0 0x000c
+/* Read trigger selection */
+#define TOD_READ_PRIMARY_CMD 0x000e
+#define TOD_READ_PRIMARY_CMD_V520 0x000f
+#define TOD_READ_PRIMARY_1 0xcc50
+#define TOD_READ_PRIMARY_1_V520 0xcc60
+#define TOD_READ_PRIMARY_2 0xcc60
+#define TOD_READ_PRIMARY_2_V520 0xcc80
+#define TOD_READ_PRIMARY_3 0xcc80
+#define TOD_READ_PRIMARY_3_V520 0xcc90
+
+#define TOD_READ_SECONDARY_0 0xcc90
+#define TOD_READ_SECONDARY_0_V520 0xcca0
+#define TOD_READ_SECONDARY_1 0xcca0
+#define TOD_READ_SECONDARY_1_V520 0xccb0
+#define TOD_READ_SECONDARY_2 0xccb0
+#define TOD_READ_SECONDARY_2_V520 0xccc0
+#define TOD_READ_SECONDARY_3 0xccc0
+#define TOD_READ_SECONDARY_3_V520 0xccd0
+
+#define OUTPUT_TDC_CFG 0xccd0
+#define OUTPUT_TDC_CFG_V520 0xcce0
+#define OUTPUT_TDC_0 0xcd00
+#define OUTPUT_TDC_1 0xcd08
+#define OUTPUT_TDC_2 0xcd10
+#define OUTPUT_TDC_3 0xcd18
+#define INPUT_TDC 0xcd20
+
+#define SCRATCH 0xcf50
+#define SCRATCH_V520 0xcf4c
+
+#define EEPROM 0xcf68
+#define EEPROM_V520 0xcf64
+
+#define OTP 0xcf70
+
+#define BYTE 0xcf80
+
+/* Bit definitions for the MAJ_REL register */
+#define MAJOR_SHIFT (1)
+#define MAJOR_MASK (0x7f)
+#define PR_BUILD BIT(0)
+
+/* Bit definitions for the USER_GPIO0_TO_7_STATUS register */
+#define GPIO0_LEVEL BIT(0)
+#define GPIO1_LEVEL BIT(1)
+#define GPIO2_LEVEL BIT(2)
+#define GPIO3_LEVEL BIT(3)
+#define GPIO4_LEVEL BIT(4)
+#define GPIO5_LEVEL BIT(5)
+#define GPIO6_LEVEL BIT(6)
+#define GPIO7_LEVEL BIT(7)
+
+/* Bit definitions for the USER_GPIO8_TO_15_STATUS register */
+#define GPIO8_LEVEL BIT(0)
+#define GPIO9_LEVEL BIT(1)
+#define GPIO10_LEVEL BIT(2)
+#define GPIO11_LEVEL BIT(3)
+#define GPIO12_LEVEL BIT(4)
+#define GPIO13_LEVEL BIT(5)
+#define GPIO14_LEVEL BIT(6)
+#define GPIO15_LEVEL BIT(7)
+
+/* Bit definitions for the GPIO0_TO_7_OUT register */
+#define GPIO0_DRIVE_LEVEL BIT(0)
+#define GPIO1_DRIVE_LEVEL BIT(1)
+#define GPIO2_DRIVE_LEVEL BIT(2)
+#define GPIO3_DRIVE_LEVEL BIT(3)
+#define GPIO4_DRIVE_LEVEL BIT(4)
+#define GPIO5_DRIVE_LEVEL BIT(5)
+#define GPIO6_DRIVE_LEVEL BIT(6)
+#define GPIO7_DRIVE_LEVEL BIT(7)
+
+/* Bit definitions for the GPIO8_TO_15_OUT register */
+#define GPIO8_DRIVE_LEVEL BIT(0)
+#define GPIO9_DRIVE_LEVEL BIT(1)
+#define GPIO10_DRIVE_LEVEL BIT(2)
+#define GPIO11_DRIVE_LEVEL BIT(3)
+#define GPIO12_DRIVE_LEVEL BIT(4)
+#define GPIO13_DRIVE_LEVEL BIT(5)
+#define GPIO14_DRIVE_LEVEL BIT(6)
+#define GPIO15_DRIVE_LEVEL BIT(7)
+
+/* Bit definitions for the DPLL_TOD_SYNC_CFG register */
+#define TOD_SYNC_SOURCE_SHIFT (1)
+#define TOD_SYNC_SOURCE_MASK (0x3)
+#define TOD_SYNC_EN BIT(0)
+
+/* Bit definitions for the DPLL_MODE register */
+#define WRITE_TIMER_MODE BIT(6)
+#define PLL_MODE_SHIFT (3)
+#define PLL_MODE_MASK (0x7)
+#define STATE_MODE_SHIFT (0)
+#define STATE_MODE_MASK (0x7)
+
+/* Bit definitions for the GPIO_CFG_GBL register */
+#define SUPPLY_MODE_SHIFT (0)
+#define SUPPLY_MODE_MASK (0x3)
+
+/* Bit definitions for the GPIO_DCO_INC_DEC register */
+#define INCDEC_DPLL_INDEX_SHIFT (0)
+#define INCDEC_DPLL_INDEX_MASK (0x7)
+
+/* Bit definitions for the GPIO_OUT_CTRL_0 register */
+#define CTRL_OUT_0 BIT(0)
+#define CTRL_OUT_1 BIT(1)
+#define CTRL_OUT_2 BIT(2)
+#define CTRL_OUT_3 BIT(3)
+#define CTRL_OUT_4 BIT(4)
+#define CTRL_OUT_5 BIT(5)
+#define CTRL_OUT_6 BIT(6)
+#define CTRL_OUT_7 BIT(7)
+
+/* Bit definitions for the GPIO_OUT_CTRL_1 register */
+#define CTRL_OUT_8 BIT(0)
+#define CTRL_OUT_9 BIT(1)
+#define CTRL_OUT_10 BIT(2)
+#define CTRL_OUT_11 BIT(3)
+#define CTRL_OUT_12 BIT(4)
+#define CTRL_OUT_13 BIT(5)
+#define CTRL_OUT_14 BIT(6)
+#define CTRL_OUT_15 BIT(7)
+
+/* Bit definitions for the GPIO_TOD_TRIG register */
+#define TOD_TRIG_0 BIT(0)
+#define TOD_TRIG_1 BIT(1)
+#define TOD_TRIG_2 BIT(2)
+#define TOD_TRIG_3 BIT(3)
+
+/* Bit definitions for the GPIO_DPLL_INDICATOR register */
+#define IND_DPLL_INDEX_SHIFT (0)
+#define IND_DPLL_INDEX_MASK (0x7)
+
+/* Bit definitions for the GPIO_LOS_INDICATOR register */
+#define REFMON_INDEX_SHIFT (0)
+#define REFMON_INDEX_MASK (0xf)
+/* Active level of LOS indicator, 0=low 1=high */
+#define ACTIVE_LEVEL BIT(4)
+
+/* Bit definitions for the GPIO_REF_INPUT_DSQ_0 register */
+#define DSQ_INP_0 BIT(0)
+#define DSQ_INP_1 BIT(1)
+#define DSQ_INP_2 BIT(2)
+#define DSQ_INP_3 BIT(3)
+#define DSQ_INP_4 BIT(4)
+#define DSQ_INP_5 BIT(5)
+#define DSQ_INP_6 BIT(6)
+#define DSQ_INP_7 BIT(7)
+
+/* Bit definitions for the GPIO_REF_INPUT_DSQ_1 register */
+#define DSQ_INP_8 BIT(0)
+#define DSQ_INP_9 BIT(1)
+#define DSQ_INP_10 BIT(2)
+#define DSQ_INP_11 BIT(3)
+#define DSQ_INP_12 BIT(4)
+#define DSQ_INP_13 BIT(5)
+#define DSQ_INP_14 BIT(6)
+#define DSQ_INP_15 BIT(7)
+
+/* Bit definitions for the GPIO_REF_INPUT_DSQ_2 register */
+#define DSQ_DPLL_0 BIT(0)
+#define DSQ_DPLL_1 BIT(1)
+#define DSQ_DPLL_2 BIT(2)
+#define DSQ_DPLL_3 BIT(3)
+#define DSQ_DPLL_4 BIT(4)
+#define DSQ_DPLL_5 BIT(5)
+#define DSQ_DPLL_6 BIT(6)
+#define DSQ_DPLL_7 BIT(7)
+
+/* Bit definitions for the GPIO_REF_INPUT_DSQ_3 register */
+#define DSQ_DPLL_SYS BIT(0)
+#define GPIO_DSQ_LEVEL BIT(1)
+
+/* Bit definitions for the GPIO_TOD_NOTIFICATION_CFG register */
+#define DPLL_TOD_SHIFT (0)
+#define DPLL_TOD_MASK (0x3)
+#define TOD_READ_SECONDARY BIT(2)
+#define GPIO_ASSERT_LEVEL BIT(3)
+
+/* Bit definitions for the GPIO_CTRL register */
+#define GPIO_FUNCTION_EN BIT(0)
+#define GPIO_CMOS_OD_MODE BIT(1)
+#define GPIO_CONTROL_DIR BIT(2)
+#define GPIO_PU_PD_MODE BIT(3)
+#define GPIO_FUNCTION_SHIFT (4)
+#define GPIO_FUNCTION_MASK (0xf)
+
+/* Bit definitions for the OUT_CTRL_1 register */
+#define OUT_SYNC_DISABLE BIT(7)
+#define SQUELCH_VALUE BIT(6)
+#define SQUELCH_DISABLE BIT(5)
+#define PAD_VDDO_SHIFT (2)
+#define PAD_VDDO_MASK (0x7)
+#define PAD_CMOSDRV_SHIFT (0)
+#define PAD_CMOSDRV_MASK (0x3)
+
+/* Bit definitions for the TOD_CFG register */
+#define TOD_EVEN_PPS_MODE BIT(2)
+#define TOD_OUT_SYNC_ENABLE BIT(1)
+#define TOD_ENABLE BIT(0)
+
+/* Bit definitions for the TOD_WRITE_SELECT_CFG_0 register */
+#define WR_PWM_DECODER_INDEX_SHIFT (4)
+#define WR_PWM_DECODER_INDEX_MASK (0xf)
+#define WR_REF_INDEX_SHIFT (0)
+#define WR_REF_INDEX_MASK (0xf)
+
+/* Bit definitions for the TOD_WRITE_CMD register */
+#define TOD_WRITE_SELECTION_SHIFT (0)
+#define TOD_WRITE_SELECTION_MASK (0xf)
+/* 4.8.7 */
+#define TOD_WRITE_TYPE_SHIFT (4)
+#define TOD_WRITE_TYPE_MASK (0x3)
+
+/* Bit definitions for the TOD_READ_PRIMARY_SEL_CFG_0 register */
+#define RD_PWM_DECODER_INDEX_SHIFT (4)
+#define RD_PWM_DECODER_INDEX_MASK (0xf)
+#define RD_REF_INDEX_SHIFT (0)
+#define RD_REF_INDEX_MASK (0xf)
+
+/* Bit definitions for the TOD_READ_PRIMARY_CMD register */
+#define TOD_READ_TRIGGER_MODE BIT(4)
+#define TOD_READ_TRIGGER_SHIFT (0)
+#define TOD_READ_TRIGGER_MASK (0xf)
+
+/* Bit definitions for the DPLL_CTRL_COMBO_MASTER_CFG register */
+#define COMBO_MASTER_HOLD BIT(0)
+
+/* Bit definitions for DPLL_SYS_STATUS register */
+#define DPLL_SYS_STATE_MASK (0xf)
+
+/* Bit definitions for SYS_APLL_STATUS register */
+#define SYS_APLL_LOSS_LOCK_LIVE_MASK BIT(0)
+#define SYS_APLL_LOSS_LOCK_LIVE_LOCKED 0
+#define SYS_APLL_LOSS_LOCK_LIVE_UNLOCKED 1
+
+/* Bit definitions for the DPLL0_STATUS register */
+#define DPLL_STATE_MASK (0xf)
+#define DPLL_STATE_SHIFT (0x0)
+
+/* Values of DPLL_N.DPLL_MODE.PLL_MODE */
+enum pll_mode {
+ PLL_MODE_MIN = 0,
+ PLL_MODE_NORMAL = PLL_MODE_MIN,
+ PLL_MODE_WRITE_PHASE = 1,
+ PLL_MODE_WRITE_FREQUENCY = 2,
+ PLL_MODE_GPIO_INC_DEC = 3,
+ PLL_MODE_SYNTHESIS = 4,
+ PLL_MODE_PHASE_MEASUREMENT = 5,
+ PLL_MODE_DISABLED = 6,
+ PLL_MODE_MAX = PLL_MODE_DISABLED,
+};
+
+enum hw_tod_write_trig_sel {
+ HW_TOD_WR_TRIG_SEL_MIN = 0,
+ HW_TOD_WR_TRIG_SEL_MSB = HW_TOD_WR_TRIG_SEL_MIN,
+ HW_TOD_WR_TRIG_SEL_RESERVED = 1,
+ HW_TOD_WR_TRIG_SEL_TOD_PPS = 2,
+ HW_TOD_WR_TRIG_SEL_IRIGB_PPS = 3,
+ HW_TOD_WR_TRIG_SEL_PWM_PPS = 4,
+ HW_TOD_WR_TRIG_SEL_GPIO = 5,
+ HW_TOD_WR_TRIG_SEL_FOD_SYNC = 6,
+ WR_TRIG_SEL_MAX = HW_TOD_WR_TRIG_SEL_FOD_SYNC,
+};
+
+enum scsr_read_trig_sel {
+ /* CANCEL CURRENT TOD READ; MODULE BECOMES IDLE - NO TRIGGER OCCURS */
+ SCSR_TOD_READ_TRIG_SEL_DISABLE = 0,
+ /* TRIGGER IMMEDIATELY */
+ SCSR_TOD_READ_TRIG_SEL_IMMEDIATE = 1,
+ /* TRIGGER ON RISING EDGE OF INTERNAL TOD PPS SIGNAL */
+ SCSR_TOD_READ_TRIG_SEL_TODPPS = 2,
+ /* TRGGER ON RISING EDGE OF SELECTED REFERENCE INPUT */
+ SCSR_TOD_READ_TRIG_SEL_REFCLK = 3,
+ /* TRIGGER ON RISING EDGE OF SELECTED PWM DECODER 1PPS OUTPUT */
+ SCSR_TOD_READ_TRIG_SEL_PWMPPS = 4,
+ SCSR_TOD_READ_TRIG_SEL_RESERVED = 5,
+ /* TRIGGER WHEN WRITE FREQUENCY EVENT OCCURS */
+ SCSR_TOD_READ_TRIG_SEL_WRITEFREQUENCYEVENT = 6,
+ /* TRIGGER ON SELECTED GPIO */
+ SCSR_TOD_READ_TRIG_SEL_GPIO = 7,
+ SCSR_TOD_READ_TRIG_SEL_MAX = SCSR_TOD_READ_TRIG_SEL_GPIO,
+};
+
+/* Values STATUS.DPLL_SYS_STATUS.DPLL_SYS_STATE */
+enum dpll_state {
+ DPLL_STATE_MIN = 0,
+ DPLL_STATE_FREERUN = DPLL_STATE_MIN,
+ DPLL_STATE_LOCKACQ = 1,
+ DPLL_STATE_LOCKREC = 2,
+ DPLL_STATE_LOCKED = 3,
+ DPLL_STATE_HOLDOVER = 4,
+ DPLL_STATE_OPEN_LOOP = 5,
+ DPLL_STATE_MAX = DPLL_STATE_OPEN_LOOP,
+};
+
+/* 4.8.7 only */
+enum scsr_tod_write_trig_sel {
+ SCSR_TOD_WR_TRIG_SEL_DISABLE = 0,
+ SCSR_TOD_WR_TRIG_SEL_IMMEDIATE = 1,
+ SCSR_TOD_WR_TRIG_SEL_REFCLK = 2,
+ SCSR_TOD_WR_TRIG_SEL_PWMPPS = 3,
+ SCSR_TOD_WR_TRIG_SEL_TODPPS = 4,
+ SCSR_TOD_WR_TRIG_SEL_SYNCFOD = 5,
+ SCSR_TOD_WR_TRIG_SEL_GPIO = 6,
+ SCSR_TOD_WR_TRIG_SEL_MAX = SCSR_TOD_WR_TRIG_SEL_GPIO,
+};
+
+/* 4.8.7 only */
+enum scsr_tod_write_type_sel {
+ SCSR_TOD_WR_TYPE_SEL_ABSOLUTE = 0,
+ SCSR_TOD_WR_TYPE_SEL_DELTA_PLUS = 1,
+ SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS = 2,
+ SCSR_TOD_WR_TYPE_SEL_MAX = SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS,
+};
+#endif
diff --git a/include/linux/mfd/rsmu.h b/include/linux/mfd/rsmu.h
new file mode 100644
index 000000000000..6870de608233
--- /dev/null
+++ b/include/linux/mfd/rsmu.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Core interface for Renesas Synchronization Management Unit (SMU) devices.
+ *
+ * Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
+ */
+
+#ifndef __LINUX_MFD_RSMU_H
+#define __LINUX_MFD_RSMU_H
+
+/* The supported devices are ClockMatrix, Sabre and SnowLotus */
+enum rsmu_type {
+ RSMU_CM = 0x34000,
+ RSMU_SABRE = 0x33810,
+ RSMU_SL = 0x19850,
+};
+
+/**
+ *
+ * struct rsmu_ddata - device data structure for sub devices.
+ *
+ * @dev: i2c/spi device.
+ * @regmap: i2c/spi bus access.
+ * @lock: mutex used by sub devices to make sure a series of
+ * bus access requests are not interrupted.
+ * @type: RSMU device type.
+ * @page: i2c/spi bus driver internal use only.
+ */
+struct rsmu_ddata {
+ struct device *dev;
+ struct regmap *regmap;
+ struct mutex lock;
+ enum rsmu_type type;
+ u16 page;
+};
+#endif /* __LINUX_MFD_RSMU_H */
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index beb918328eef..723985879035 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -303,6 +303,7 @@ struct mhi_controller_config {
* @rddm_size: RAM dump size that host should allocate for debugging purpose
* @sbl_size: SBL image size downloaded through BHIe (optional)
* @seg_len: BHIe vector size (optional)
+ * @reg_len: Length of the MHI MMIO region (required)
* @fbc_image: Points to firmware image buffer
* @rddm_image: Points to RAM dump buffer
* @mhi_chan: Points to the channel configuration table
@@ -387,6 +388,7 @@ struct mhi_controller {
size_t rddm_size;
size_t sbl_size;
size_t seg_len;
+ size_t reg_len;
struct image_info *fbc_image;
struct image_info *rddm_image;
struct mhi_chan *mhi_chan;
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index 23dadf7aeba8..326250996b4e 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -28,6 +28,7 @@ enum migrate_reason {
MR_NUMA_MISPLACED,
MR_CONTIG_RANGE,
MR_LONGTERM_PIN,
+ MR_DEMOTION,
MR_TYPES
};
@@ -41,7 +42,8 @@ extern int migrate_page(struct address_space *mapping,
struct page *newpage, struct page *page,
enum migrate_mode mode);
extern int migrate_pages(struct list_head *l, new_page_t new, free_page_t free,
- unsigned long private, enum migrate_mode mode, int reason);
+ unsigned long private, enum migrate_mode mode, int reason,
+ unsigned int *ret_succeeded);
extern struct page *alloc_migration_target(struct page *page, unsigned long private);
extern int isolate_movable_page(struct page *page, isolate_mode_t mode);
@@ -56,7 +58,7 @@ extern int migrate_page_move_mapping(struct address_space *mapping,
static inline void putback_movable_pages(struct list_head *l) {}
static inline int migrate_pages(struct list_head *l, new_page_t new,
free_page_t free, unsigned long private, enum migrate_mode mode,
- int reason)
+ int reason, unsigned int *ret_succeeded)
{ return -ENOSYS; }
static inline struct page *alloc_migration_target(struct page *page,
unsigned long private)
@@ -166,6 +168,14 @@ struct migrate_vma {
int migrate_vma_setup(struct migrate_vma *args);
void migrate_vma_pages(struct migrate_vma *migrate);
void migrate_vma_finalize(struct migrate_vma *migrate);
+int next_demotion_node(int node);
+
+#else /* CONFIG_MIGRATION disabled: */
+
+static inline int next_demotion_node(int node)
+{
+ return NUMA_NO_NODE;
+}
#endif /* CONFIG_MIGRATION */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 7ca22e6e694a..73a52aba448f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -281,7 +281,6 @@ extern unsigned int kobjsize(const void *objp);
#define VM_GROWSDOWN 0x00000100 /* general info on the segment */
#define VM_UFFD_MISSING 0x00000200 /* missing pages tracking */
#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */
-#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */
#define VM_UFFD_WP 0x00001000 /* wrprotect pages tracking */
#define VM_LOCKED 0x00002000
@@ -829,6 +828,8 @@ static inline void *kvcalloc(size_t n, size_t size, gfp_t flags)
return kvmalloc_array(n, size, flags | __GFP_ZERO);
}
+extern void *kvrealloc(const void *p, size_t oldsize, size_t newsize,
+ gfp_t flags);
extern void kvfree(const void *addr);
extern void kvfree_sensitive(const void *addr, size_t len);
@@ -1214,8 +1215,8 @@ static inline void get_page(struct page *page)
}
bool __must_check try_grab_page(struct page *page, unsigned int flags);
-__maybe_unused struct page *try_grab_compound_head(struct page *page, int refs,
- unsigned int flags);
+struct page *try_grab_compound_head(struct page *page, int refs,
+ unsigned int flags);
static inline __must_check bool try_get_page(struct page *page)
@@ -1847,7 +1848,6 @@ int __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc,
struct kvec;
int get_kernel_pages(const struct kvec *iov, int nr_pages, int write,
struct page **pages);
-int get_kernel_page(unsigned long start, int write, struct page **pages);
struct page *get_dump_page(unsigned long addr);
extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
@@ -2580,7 +2580,8 @@ static inline int check_data_rlimit(unsigned long rlim,
extern int mm_take_all_locks(struct mm_struct *mm);
extern void mm_drop_all_locks(struct mm_struct *mm);
-extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
+extern int set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
+extern int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
extern struct file *get_mm_exe_file(struct mm_struct *mm);
extern struct file *get_task_exe_file(struct task_struct *task);
@@ -3119,7 +3120,7 @@ extern void memory_failure_queue_kick(int cpu);
extern int unpoison_memory(unsigned long pfn);
extern int sysctl_memory_failure_early_kill;
extern int sysctl_memory_failure_recovery;
-extern void shake_page(struct page *p, int access);
+extern void shake_page(struct page *p);
extern atomic_long_t num_poisoned_pages __read_mostly;
extern int soft_offline_page(unsigned long pfn, int flags);
diff --git a/include/linux/mman.h b/include/linux/mman.h
index ebb09a964272..b66e91b8176c 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -32,7 +32,8 @@
* The historical set of flags that all mmap implementations implicitly
* support when a ->mmap_validate() op is not provided in file_operations.
*
- * MAP_EXECUTABLE is completely ignored throughout the kernel.
+ * MAP_EXECUTABLE and MAP_DENYWRITE are completely ignored throughout the
+ * kernel.
*/
#define LEGACY_MAP_MASK (MAP_SHARED \
| MAP_PRIVATE \
@@ -153,7 +154,6 @@ static inline unsigned long
calc_vm_flag_bits(unsigned long flags)
{
return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
- _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
_calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) |
_calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) |
arch_calc_vm_flag_bits(flags);
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index fcb535560028..1bd5f5955f9a 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -846,6 +846,7 @@ typedef struct pglist_data {
enum zone_type kcompactd_highest_zoneidx;
wait_queue_head_t kcompactd_wait;
struct task_struct *kcompactd;
+ bool proactive_compact_trigger;
#endif
/*
* This is a per-node reserve of pages that are not available
@@ -1342,7 +1343,6 @@ static inline struct mem_section *__nr_to_section(unsigned long nr)
return NULL;
return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
}
-extern unsigned long __section_nr(struct mem_section *ms);
extern size_t mem_section_usage_size(void);
/*
@@ -1365,7 +1365,7 @@ extern size_t mem_section_usage_size(void);
#define SECTION_TAINT_ZONE_DEVICE (1UL<<4)
#define SECTION_MAP_LAST_BIT (1UL<<5)
#define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1))
-#define SECTION_NID_SHIFT 3
+#define SECTION_NID_SHIFT 6
static inline struct page *__section_mem_map_addr(struct mem_section *section)
{
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 8e291cfdaf06..ae2e75d15b21 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -16,6 +16,10 @@ typedef unsigned long kernel_ulong_t;
#define PCI_ANY_ID (~0)
+enum {
+ PCI_ID_F_VFIO_DRIVER_OVERRIDE = 1,
+};
+
/**
* struct pci_device_id - PCI device ID structure
* @vendor: Vendor ID to match (or PCI_ANY_ID)
@@ -34,12 +38,14 @@ typedef unsigned long kernel_ulong_t;
* Best practice is to use driver_data as an index
* into a static list of equivalent device types,
* instead of using it as a pointer.
+ * @override_only: Match only when dev->driver_override is this driver.
*/
struct pci_device_id {
__u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
__u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
__u32 class, class_mask; /* (class,subclass,prog-if) triplet */
kernel_ulong_t driver_data; /* Data private to the driver */
+ __u32 override_only;
};
diff --git a/include/linux/module.h b/include/linux/module.h
index 8a298d820dbc..c9f1200b2312 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -511,6 +511,11 @@ struct module {
struct klp_modinfo *klp_info;
#endif
+#ifdef CONFIG_PRINTK_INDEX
+ unsigned int printk_index_size;
+ struct pi_entry **printk_index_start;
+#endif
+
#ifdef CONFIG_MODULE_UNLOAD
/* What modules depend on me? */
struct list_head source_list;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7c41593c1d6a..d79163208dfd 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4641,6 +4641,24 @@ void __hw_addr_unsync_dev(struct netdev_hw_addr_list *list,
void __hw_addr_init(struct netdev_hw_addr_list *list);
/* Functions used for device addresses handling */
+static inline void
+__dev_addr_set(struct net_device *dev, const u8 *addr, size_t len)
+{
+ memcpy(dev->dev_addr, addr, len);
+}
+
+static inline void dev_addr_set(struct net_device *dev, const u8 *addr)
+{
+ __dev_addr_set(dev, addr, dev->addr_len);
+}
+
+static inline void
+dev_addr_mod(struct net_device *dev, unsigned int offset,
+ const u8 *addr, size_t len)
+{
+ memcpy(&dev->dev_addr[offset], addr, len);
+}
+
int dev_addr_add(struct net_device *dev, const unsigned char *addr,
unsigned char addr_type);
int dev_addr_del(struct net_device *dev, const unsigned char *addr,
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 0c7d8d1e945d..700ea077ce2d 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -18,6 +18,7 @@ struct ip_conntrack_stat {
unsigned int expect_create;
unsigned int expect_delete;
unsigned int search_restart;
+ unsigned int chaintoolong;
};
#define NFCT_INFOMASK 7UL
diff --git a/include/linux/netfs.h b/include/linux/netfs.h
index 9062adfa2fb9..5d6a4158a9a6 100644
--- a/include/linux/netfs.h
+++ b/include/linux/netfs.h
@@ -102,6 +102,7 @@ struct netfs_cache_resources {
const struct netfs_cache_ops *ops;
void *cache_priv;
void *cache_priv2;
+ unsigned int debug_id; /* Cookie debug ID */
};
/*
@@ -137,7 +138,6 @@ struct netfs_read_request {
struct list_head subrequests; /* Requests to fetch I/O from disk or net */
void *netfs_priv; /* Private data for the netfs */
unsigned int debug_id;
- unsigned int cookie_debug_id;
atomic_t nr_rd_ops; /* Number of read ops in progress */
atomic_t nr_wr_ops; /* Number of write ops in progress */
size_t submitted; /* Amount submitted for I/O so far */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index ce6474594872..b9a8b925db43 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -41,6 +41,11 @@
#include <linux/mempool.h>
/*
+ * These are the default for number of transports to different server IPs
+ */
+#define NFS_MAX_TRANSPORTS 16
+
+/*
* These are the default flags for swap requests
*/
#define NFS_RPC_SWAPFLAGS (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS)
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index d71a0e90faeb..2a9acbfe00f0 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -62,6 +62,7 @@ struct nfs_client {
u32 cl_minorversion;/* NFSv4 minorversion */
unsigned int cl_nconnect; /* Number of connections */
+ unsigned int cl_max_connect; /* max number of xprts allowed */
const char * cl_principal; /* used for machine cred */
#if IS_ENABLED(CONFIG_NFS_V4)
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index eba50b057f6f..392fc6c53e96 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -86,7 +86,7 @@ extern struct list_head nubus_func_rsrcs;
struct nubus_driver {
struct device_driver driver;
int (*probe)(struct nubus_board *board);
- int (*remove)(struct nubus_board *board);
+ void (*remove)(struct nubus_board *board);
};
extern struct bus_type nubus_bus_type;
diff --git a/include/linux/of.h b/include/linux/of.h
index 9c2e71e202d1..6f1c41f109bb 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -896,7 +896,7 @@ static inline int of_parse_phandle_with_fixed_args(const struct device_node *np,
return -ENOSYS;
}
-static inline int of_count_phandle_with_args(struct device_node *np,
+static inline int of_count_phandle_with_args(const struct device_node *np,
const char *list_name,
const char *cells_name)
{
@@ -946,6 +946,11 @@ static inline int of_machine_is_compatible(const char *compat)
return 0;
}
+static inline int of_add_property(struct device_node *np, struct property *prop)
+{
+ return 0;
+}
+
static inline int of_remove_property(struct device_node *np, struct property *prop)
{
return 0;
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index acf820e88952..cf6a65b94d40 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -67,9 +67,6 @@ extern void early_init_fdt_scan_reserved_mem(void);
extern void early_init_fdt_reserve_self(void);
extern void __init early_init_dt_scan_chosen_arch(unsigned long node);
extern void early_init_dt_add_memory_arch(u64 base, u64 size);
-extern int early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size);
-extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size,
- bool no_map);
extern u64 dt_mem_next_cell(int s, const __be32 **cellp);
/* Early flat tree scan hooks */
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index f821095218b0..8bf2ea859653 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -49,7 +49,7 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
return container_of(gc, struct of_mm_gpio_chip, gc);
}
-extern int of_get_named_gpio_flags(struct device_node *np,
+extern int of_get_named_gpio_flags(const struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags);
extern int of_mm_gpiochip_add_data(struct device_node *np,
@@ -67,7 +67,7 @@ extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);
#include <linux/errno.h>
/* Drivers may not strictly depend on the GPIO support, so let them link. */
-static inline int of_get_named_gpio_flags(struct device_node *np,
+static inline int of_get_named_gpio_flags(const struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags)
{
if (flags)
@@ -98,7 +98,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
* The above example defines four GPIOs, two of which are not specified.
* This function will return '4'
*/
-static inline int of_gpio_named_count(struct device_node *np, const char* propname)
+static inline int of_gpio_named_count(const struct device_node *np,
+ const char *propname)
{
return of_count_phandle_with_args(np, propname, "#gpio-cells");
}
@@ -109,12 +110,12 @@ static inline int of_gpio_named_count(struct device_node *np, const char* propna
*
* Same as of_gpio_named_count, but hard coded to use the 'gpios' property
*/
-static inline int of_gpio_count(struct device_node *np)
+static inline int of_gpio_count(const struct device_node *np)
{
return of_gpio_named_count(np, "gpios");
}
-static inline int of_get_gpio_flags(struct device_node *np, int index,
+static inline int of_get_gpio_flags(const struct device_node *np, int index,
enum of_gpio_flags *flags)
{
return of_get_named_gpio_flags(np, "gpios", index, flags);
@@ -129,7 +130,7 @@ static inline int of_get_gpio_flags(struct device_node *np, int index,
* Returns GPIO number to use with Linux generic GPIO API, or one of the errno
* value on the error condition.
*/
-static inline int of_get_named_gpio(struct device_node *np,
+static inline int of_get_named_gpio(const struct device_node *np,
const char *propname, int index)
{
return of_get_named_gpio_flags(np, propname, index, NULL);
@@ -143,7 +144,7 @@ static inline int of_get_named_gpio(struct device_node *np,
* Returns GPIO number to use with Linux generic GPIO API, or one of the errno
* value on the error condition.
*/
-static inline int of_get_gpio(struct device_node *np, int index)
+static inline int of_get_gpio(const struct device_node *np, int index)
{
return of_get_gpio_flags(np, index, NULL);
}
diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h
index b7bf735960c2..082841908fe7 100644
--- a/include/linux/omap-gpmc.h
+++ b/include/linux/omap-gpmc.h
@@ -81,9 +81,6 @@ extern int gpmc_configure(int cmd, int wval);
extern void gpmc_read_settings_dt(struct device_node *np,
struct gpmc_settings *p);
-extern void omap3_gpmc_save_context(void);
-extern void omap3_gpmc_restore_context(void);
-
struct gpmc_timings;
struct omap_nand_platform_data;
struct omap_onenand_platform_data;
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 5922031ffab6..1ace27c4a8e0 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -633,43 +633,6 @@ static inline int PageTransCompound(struct page *page)
}
/*
- * PageTransCompoundMap is the same as PageTransCompound, but it also
- * guarantees the primary MMU has the entire compound page mapped
- * through pmd_trans_huge, which in turn guarantees the secondary MMUs
- * can also map the entire compound page. This allows the secondary
- * MMUs to call get_user_pages() only once for each compound page and
- * to immediately map the entire compound page with a single secondary
- * MMU fault. If there will be a pmd split later, the secondary MMUs
- * will get an update through the MMU notifier invalidation through
- * split_huge_pmd().
- *
- * Unlike PageTransCompound, this is safe to be called only while
- * split_huge_pmd() cannot run from under us, like if protected by the
- * MMU notifier, otherwise it may result in page->_mapcount check false
- * positives.
- *
- * We have to treat page cache THP differently since every subpage of it
- * would get _mapcount inc'ed once it is PMD mapped. But, it may be PTE
- * mapped in the current process so comparing subpage's _mapcount to
- * compound_mapcount to filter out PTE mapped case.
- */
-static inline int PageTransCompoundMap(struct page *page)
-{
- struct page *head;
-
- if (!PageTransCompound(page))
- return 0;
-
- if (PageAnon(page))
- return atomic_read(&page->_mapcount) < 0;
-
- head = compound_head(page);
- /* File THP is PMD mapped and not PTE mapped */
- return atomic_read(&page->_mapcount) ==
- atomic_read(compound_mapcount_ptr(head));
-}
-
-/*
* PageTransTail returns true for both transparent huge pages
* and hugetlbfs pages, so it should only be called when it's known
* that hugetlbfs pages aren't involved.
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index ed02aa522263..5dcf446f42e5 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -736,7 +736,7 @@ extern void add_page_wait_queue(struct page *page, wait_queue_entry_t *waiter);
/*
* Fault everything in given userspace address range in.
*/
-static inline int fault_in_pages_writeable(char __user *uaddr, int size)
+static inline int fault_in_pages_writeable(char __user *uaddr, size_t size)
{
char __user *end = uaddr + size - 1;
@@ -763,7 +763,7 @@ static inline int fault_in_pages_writeable(char __user *uaddr, int size)
return 0;
}
-static inline int fault_in_pages_readable(const char __user *uaddr, int size)
+static inline int fault_in_pages_readable(const char __user *uaddr, size_t size)
{
volatile char c;
const char __user *end = uaddr + size - 1;
diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
index 2debc27ba95e..8292420426f3 100644
--- a/include/linux/pci-epf.h
+++ b/include/linux/pci-epf.h
@@ -85,7 +85,7 @@ struct pci_epf_ops {
*/
struct pci_epf_driver {
int (*probe)(struct pci_epf *epf);
- int (*remove)(struct pci_epf *epf);
+ void (*remove)(struct pci_epf *epf);
struct device_driver driver;
struct pci_epf_ops *ops;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 947430637cac..34d7d94ddf6d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -902,6 +902,35 @@ struct pci_driver {
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
/**
+ * PCI_DEVICE_DRIVER_OVERRIDE - macro used to describe a PCI device with
+ * override_only flags.
+ * @vend: the 16 bit PCI Vendor ID
+ * @dev: the 16 bit PCI Device ID
+ * @driver_override: the 32 bit PCI Device override_only
+ *
+ * This macro is used to create a struct pci_device_id that matches only a
+ * driver_override device. The subvendor and subdevice fields will be set to
+ * PCI_ANY_ID.
+ */
+#define PCI_DEVICE_DRIVER_OVERRIDE(vend, dev, driver_override) \
+ .vendor = (vend), .device = (dev), .subvendor = PCI_ANY_ID, \
+ .subdevice = PCI_ANY_ID, .override_only = (driver_override)
+
+/**
+ * PCI_DRIVER_OVERRIDE_DEVICE_VFIO - macro used to describe a VFIO
+ * "driver_override" PCI device.
+ * @vend: the 16 bit PCI Vendor ID
+ * @dev: the 16 bit PCI Device ID
+ *
+ * This macro is used to create a struct pci_device_id that matches a
+ * specific device. The subvendor and subdevice fields will be set to
+ * PCI_ANY_ID and the driver_override will be set to
+ * PCI_ID_F_VFIO_DRIVER_OVERRIDE.
+ */
+#define PCI_DRIVER_OVERRIDE_DEVICE_VFIO(vend, dev) \
+ PCI_DEVICE_DRIVER_OVERRIDE(vend, dev, PCI_ID_F_VFIO_DRIVER_OVERRIDE)
+
+/**
* PCI_DEVICE_SUB - macro used to describe a specific PCI device with subsystem
* @vend: the 16 bit PCI Vendor ID
* @dev: the 16 bit PCI Device ID
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index afb3ded0b691..237291196ce2 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -451,6 +451,9 @@ void phylink_mac_change(struct phylink *, bool up);
void phylink_start(struct phylink *);
void phylink_stop(struct phylink *);
+void phylink_suspend(struct phylink *pl, bool mac_wol);
+void phylink_resume(struct phylink *pl);
+
void phylink_ethtool_get_wol(struct phylink *, struct ethtool_wolinfo *);
int phylink_ethtool_set_wol(struct phylink *, struct ethtool_wolinfo *);
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index 5d1fb0d78a22..76b13ef67562 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -96,6 +96,7 @@ enum {
MCASP_VERSION_2, /* DA8xx/OMAPL1x */
MCASP_VERSION_3, /* TI81xx/AM33xx */
MCASP_VERSION_4, /* DRA7xxx */
+ MCASP_VERSION_OMAP, /* OMAP4/5 */
};
enum mcbsp_clk_input_pin {
diff --git a/include/linux/platform_data/gpio-dwapb.h b/include/linux/platform_data/gpio-dwapb.h
deleted file mode 100644
index 0aa5c6720259..000000000000
--- a/include/linux/platform_data/gpio-dwapb.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright(c) 2014 Intel Corporation.
- */
-
-#ifndef GPIO_DW_APB_H
-#define GPIO_DW_APB_H
-
-#define DWAPB_MAX_GPIOS 32
-
-struct dwapb_port_property {
- struct fwnode_handle *fwnode;
- unsigned int idx;
- unsigned int ngpio;
- unsigned int gpio_base;
- int irq[DWAPB_MAX_GPIOS];
- bool irq_shared;
-};
-
-struct dwapb_platform_data {
- struct dwapb_port_property *properties;
- unsigned int nports;
-};
-
-#endif
diff --git a/include/linux/platform_data/pata_ixp4xx_cf.h b/include/linux/platform_data/pata_ixp4xx_cf.h
index 601ba97fef57..e60fa41da4a5 100644
--- a/include/linux/platform_data/pata_ixp4xx_cf.h
+++ b/include/linux/platform_data/pata_ixp4xx_cf.h
@@ -14,8 +14,8 @@ struct ixp4xx_pata_data {
volatile u32 *cs1_cfg;
unsigned long cs0_bits;
unsigned long cs1_bits;
- void __iomem *cs0;
- void __iomem *cs1;
+ void __iomem *cmd;
+ void __iomem *ctl;
};
#endif
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index 2f274cf52805..17dc5cb6f3f2 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -61,6 +61,7 @@
#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075
/* Misc */
+#define ASUS_WMI_DEVID_PANEL_OD 0x00050019
#define ASUS_WMI_DEVID_CAMERA 0x00060013
#define ASUS_WMI_DEVID_LID_FLIP 0x00060062
@@ -89,6 +90,12 @@
/* Keyboard dock */
#define ASUS_WMI_DEVID_KBD_DOCK 0x00120063
+/* dgpu on/off */
+#define ASUS_WMI_DEVID_EGPU 0x00090019
+
+/* dgpu on/off */
+#define ASUS_WMI_DEVID_DGPU 0x00090020
+
/* DSTS masks */
#define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
#define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002
diff --git a/include/linux/platform_data/x86/clk-lpss.h b/include/linux/platform_data/x86/clk-lpss.h
index 207e1a317800..41df326583f9 100644
--- a/include/linux/platform_data/x86/clk-lpss.h
+++ b/include/linux/platform_data/x86/clk-lpss.h
@@ -15,6 +15,6 @@ struct lpss_clk_data {
struct clk *clk;
};
-extern int lpt_clk_init(void);
+extern int lpss_atom_clk_init(void);
#endif /* __CLK_LPSS_H */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index ed42ea9f60ba..7c96f169d274 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -197,8 +197,6 @@ extern int platform_device_add_resources(struct platform_device *pdev,
unsigned int num);
extern int platform_device_add_data(struct platform_device *pdev,
const void *data, size_t size);
-extern int platform_device_add_properties(struct platform_device *pdev,
- const struct property_entry *properties);
extern int platform_device_add(struct platform_device *pdev);
extern void platform_device_del(struct platform_device *pdev);
extern void platform_device_put(struct platform_device *pdev);
diff --git a/include/linux/pm_clock.h b/include/linux/pm_clock.h
index 8ddc7860e131..ada3a0ab10bf 100644
--- a/include/linux/pm_clock.h
+++ b/include/linux/pm_clock.h
@@ -47,6 +47,7 @@ extern void pm_clk_remove(struct device *dev, const char *con_id);
extern void pm_clk_remove_clk(struct device *dev, struct clk *clk);
extern int pm_clk_suspend(struct device *dev);
extern int pm_clk_resume(struct device *dev);
+extern int devm_pm_clk_create(struct device *dev);
#else
static inline bool pm_clk_no_clocks(struct device *dev)
{
@@ -83,6 +84,10 @@ static inline void pm_clk_remove(struct device *dev, const char *con_id)
static inline void pm_clk_remove_clk(struct device *dev, struct clk *clk)
{
}
+static inline int devm_pm_clk_create(struct device *dev)
+{
+ return -EINVAL;
+}
#endif
#ifdef CONFIG_HAVE_CLK
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index aab8b35e9f8a..222da43b7096 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -59,6 +59,8 @@ 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_link *link);
+extern int devm_pm_runtime_enable(struct device *dev);
+
/**
* pm_runtime_get_if_in_use - Conditionally bump up runtime PM usage counter.
* @dev: Target device.
@@ -253,6 +255,8 @@ static inline void __pm_runtime_disable(struct device *dev, bool c) {}
static inline void pm_runtime_allow(struct device *dev) {}
static inline void pm_runtime_forbid(struct device *dev) {}
+static inline int devm_pm_runtime_enable(struct device *dev) { return 0; }
+
static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {}
static inline void pm_runtime_get_noresume(struct device *dev) {}
static inline void pm_runtime_put_noidle(struct device *dev) {}
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 307094ebb88c..b65c877d92b8 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -72,6 +72,8 @@ extern struct posix_acl *get_posix_acl(struct inode *, int);
extern int set_posix_acl(struct user_namespace *, struct inode *, int,
struct posix_acl *);
+struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type);
+
#ifdef CONFIG_FS_POSIX_ACL
int posix_acl_chmod(struct user_namespace *, struct inode *, umode_t);
extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **,
@@ -84,7 +86,6 @@ extern int simple_set_acl(struct user_namespace *, struct inode *,
extern int simple_acl_create(struct inode *, struct inode *);
struct posix_acl *get_cached_acl(struct inode *inode, int type);
-struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type);
void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl);
void forget_cached_acl(struct inode *inode, int type);
void forget_all_cached_acls(struct inode *inode);
diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h
index 971c9264179e..167b9b040091 100644
--- a/include/linux/power/smartreflex.h
+++ b/include/linux/power/smartreflex.h
@@ -155,6 +155,7 @@ struct omap_sr {
struct voltagedomain *voltdm;
struct dentry *dbg_dir;
unsigned int irq;
+ struct clk *fck;
int srid;
int ip_type;
int nvalue_count;
@@ -169,6 +170,7 @@ struct omap_sr {
u32 senp_mod;
u32 senn_mod;
void __iomem *base;
+ unsigned long enabled:1;
};
/**
diff --git a/include/linux/printk.h b/include/linux/printk.h
index e834d78f0478..85b656f82d75 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -2,7 +2,7 @@
#ifndef __KERNEL_PRINTK__
#define __KERNEL_PRINTK__
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/init.h>
#include <linux/kern_levels.h>
#include <linux/linkage.h>
@@ -70,16 +70,7 @@ extern int console_printk[];
#define minimum_console_loglevel (console_printk[2])
#define default_console_loglevel (console_printk[3])
-static inline void console_silent(void)
-{
- console_loglevel = CONSOLE_LOGLEVEL_SILENT;
-}
-
-static inline void console_verbose(void)
-{
- if (console_loglevel)
- console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;
-}
+extern void console_verbose(void);
/* strlen("ratelimit") + 1 */
#define DEVKMSG_STR_MAX_SIZE 10
@@ -150,18 +141,6 @@ static inline __printf(1, 2) __cold
void early_printk(const char *s, ...) { }
#endif
-#ifdef CONFIG_PRINTK_NMI
-extern void printk_nmi_enter(void);
-extern void printk_nmi_exit(void);
-extern void printk_nmi_direct_enter(void);
-extern void printk_nmi_direct_exit(void);
-#else
-static inline void printk_nmi_enter(void) { }
-static inline void printk_nmi_exit(void) { }
-static inline void printk_nmi_direct_enter(void) { }
-static inline void printk_nmi_direct_exit(void) { }
-#endif /* PRINTK_NMI */
-
struct dev_printk_info;
#ifdef CONFIG_PRINTK
@@ -174,12 +153,22 @@ asmlinkage __printf(1, 0)
int vprintk(const char *fmt, va_list args);
asmlinkage __printf(1, 2) __cold
-int printk(const char *fmt, ...);
+int _printk(const char *fmt, ...);
/*
* Special printk facility for scheduler/timekeeping use only, _DO_NOT_USE_ !
*/
-__printf(1, 2) __cold int printk_deferred(const char *fmt, ...);
+__printf(1, 2) __cold int _printk_deferred(const char *fmt, ...);
+
+extern void __printk_safe_enter(void);
+extern void __printk_safe_exit(void);
+/*
+ * The printk_deferred_enter/exit macros are available only as a hack for
+ * some code paths that need to defer all printk console printing. Interrupts
+ * must be disabled for the deferred duration.
+ */
+#define printk_deferred_enter __printk_safe_enter
+#define printk_deferred_exit __printk_safe_exit
/*
* Please don't use printk_ratelimit(), because it shares ratelimiting state
@@ -209,8 +198,6 @@ void dump_stack_print_info(const char *log_lvl);
void show_regs_print_info(const char *log_lvl);
extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold;
extern asmlinkage void dump_stack(void) __cold;
-extern void printk_safe_flush(void);
-extern void printk_safe_flush_on_panic(void);
#else
static inline __printf(1, 0)
int vprintk(const char *s, va_list args)
@@ -218,15 +205,24 @@ int vprintk(const char *s, va_list args)
return 0;
}
static inline __printf(1, 2) __cold
-int printk(const char *s, ...)
+int _printk(const char *s, ...)
{
return 0;
}
static inline __printf(1, 2) __cold
-int printk_deferred(const char *s, ...)
+int _printk_deferred(const char *s, ...)
{
return 0;
}
+
+static inline void printk_deferred_enter(void)
+{
+}
+
+static inline void printk_deferred_exit(void)
+{
+}
+
static inline int printk_ratelimit(void)
{
return 0;
@@ -278,14 +274,6 @@ static inline void dump_stack_lvl(const char *log_lvl)
static inline void dump_stack(void)
{
}
-
-static inline void printk_safe_flush(void)
-{
-}
-
-static inline void printk_safe_flush_on_panic(void)
-{
-}
#endif
#ifdef CONFIG_SMP
@@ -348,6 +336,117 @@ extern int kptr_restrict;
#define pr_fmt(fmt) fmt
#endif
+struct module;
+
+#ifdef CONFIG_PRINTK_INDEX
+struct pi_entry {
+ const char *fmt;
+ const char *func;
+ const char *file;
+ unsigned int line;
+
+ /*
+ * While printk and pr_* have the level stored in the string at compile
+ * time, some subsystems dynamically add it at runtime through the
+ * format string. For these dynamic cases, we allow the subsystem to
+ * tell us the level at compile time.
+ *
+ * NULL indicates that the level, if any, is stored in fmt.
+ */
+ const char *level;
+
+ /*
+ * The format string used by various subsystem specific printk()
+ * wrappers to prefix the message.
+ *
+ * Note that the static prefix defined by the pr_fmt() macro is stored
+ * directly in the message format (@fmt), not here.
+ */
+ const char *subsys_fmt_prefix;
+} __packed;
+
+#define __printk_index_emit(_fmt, _level, _subsys_fmt_prefix) \
+ do { \
+ if (__builtin_constant_p(_fmt) && __builtin_constant_p(_level)) { \
+ /*
+ * We check __builtin_constant_p multiple times here
+ * for the same input because GCC will produce an error
+ * if we try to assign a static variable to fmt if it
+ * is not a constant, even with the outer if statement.
+ */ \
+ static const struct pi_entry _entry \
+ __used = { \
+ .fmt = __builtin_constant_p(_fmt) ? (_fmt) : NULL, \
+ .func = __func__, \
+ .file = __FILE__, \
+ .line = __LINE__, \
+ .level = __builtin_constant_p(_level) ? (_level) : NULL, \
+ .subsys_fmt_prefix = _subsys_fmt_prefix,\
+ }; \
+ static const struct pi_entry *_entry_ptr \
+ __used __section(".printk_index") = &_entry; \
+ } \
+ } while (0)
+
+#else /* !CONFIG_PRINTK_INDEX */
+#define __printk_index_emit(...) do {} while (0)
+#endif /* CONFIG_PRINTK_INDEX */
+
+/*
+ * Some subsystems have their own custom printk that applies a va_format to a
+ * generic format, for example, to include a device number or other metadata
+ * alongside the format supplied by the caller.
+ *
+ * In order to store these in the way they would be emitted by the printk
+ * infrastructure, the subsystem provides us with the start, fixed string, and
+ * any subsequent text in the format string.
+ *
+ * We take a variable argument list as pr_fmt/dev_fmt/etc are sometimes passed
+ * as multiple arguments (eg: `"%s: ", "blah"`), and we must only take the
+ * first one.
+ *
+ * subsys_fmt_prefix must be known at compile time, or compilation will fail
+ * (since this is a mistake). If fmt or level is not known at compile time, no
+ * index entry will be made (since this can legitimately happen).
+ */
+#define printk_index_subsys_emit(subsys_fmt_prefix, level, fmt, ...) \
+ __printk_index_emit(fmt, level, subsys_fmt_prefix)
+
+#define printk_index_wrap(_p_func, _fmt, ...) \
+ ({ \
+ __printk_index_emit(_fmt, NULL, NULL); \
+ _p_func(_fmt, ##__VA_ARGS__); \
+ })
+
+
+/**
+ * printk - print a kernel message
+ * @fmt: format string
+ *
+ * This is printk(). It can be called from any context. We want it to work.
+ *
+ * If printk indexing is enabled, _printk() is called from printk_index_wrap.
+ * Otherwise, printk is simply #defined to _printk.
+ *
+ * We try to grab the console_lock. If we succeed, it's easy - we log the
+ * output and call the console drivers. If we fail to get the semaphore, we
+ * place the output into the log buffer and return. The current holder of
+ * the console_sem will notice the new output in console_unlock(); and will
+ * send it to the consoles before releasing the lock.
+ *
+ * One effect of this deferred printing is that code which calls printk() and
+ * then changes console_loglevel may break. This is because console_loglevel
+ * is inspected when the actual printing occurs.
+ *
+ * See also:
+ * printf(3)
+ *
+ * See the vsnprintf() documentation for format string extensions over C99.
+ */
+#define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
+#define printk_deferred(fmt, ...) \
+ printk_index_wrap(_printk_deferred, fmt, ##__VA_ARGS__)
+
/**
* pr_emerg - Print an emergency-level message
* @fmt: format string
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index 7c811eebcaab..f5672785c0c4 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -8,11 +8,24 @@
#include <linux/interconnect.h>
-/* Transfer mode supported by GENI Serial Engines */
+/**
+ * enum geni_se_xfer_mode: Transfer modes supported by Serial Engines
+ *
+ * @GENI_SE_INVALID: Invalid mode
+ * @GENI_SE_FIFO: FIFO mode. Data is transferred with SE FIFO
+ * by programmed IO method
+ * @GENI_SE_DMA: Serial Engine DMA mode. Data is transferred
+ * with SE by DMAengine internal to SE
+ * @GENI_GPI_DMA: GPI DMA mode. Data is transferred using a DMAengine
+ * configured by a firmware residing on a GSI engine. This DMA name is
+ * interchangeably used as GSI or GPI which seem to imply the same DMAengine
+ */
+
enum geni_se_xfer_mode {
GENI_SE_INVALID,
GENI_SE_FIFO,
GENI_SE_DMA,
+ GENI_GPI_DMA,
};
/* Protocols supported by GENI Serial Engines */
@@ -63,6 +76,7 @@ struct geni_se {
#define SE_GENI_STATUS 0x40
#define GENI_SER_M_CLK_CFG 0x48
#define GENI_SER_S_CLK_CFG 0x4c
+#define GENI_IF_DISABLE_RO 0x64
#define GENI_FW_REVISION_RO 0x68
#define SE_GENI_CLK_SEL 0x7c
#define SE_GENI_DMA_MODE_EN 0x258
@@ -105,6 +119,9 @@ struct geni_se {
#define CLK_DIV_MSK GENMASK(15, 4)
#define CLK_DIV_SHFT 4
+/* GENI_IF_DISABLE_RO fields */
+#define FIFO_IF_DISABLE (BIT(0))
+
/* GENI_FW_REVISION_RO fields */
#define FW_REV_PROTOCOL_MSK GENMASK(15, 8)
#define FW_REV_PROTOCOL_SHFT 8
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index a5b37bc10865..83c09ac36b13 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -369,9 +369,8 @@ enum rsc_handling_status {
* @da_to_va: optional platform hook to perform address translations
* @parse_fw: parse firmware to extract information (e.g. resource table)
* @handle_rsc: optional platform hook to handle vendor resources. Should return
- * RSC_HANDLED if resource was handled, RSC_IGNORED if not handled and a
- * negative value on error
- * @load_rsc_table: load resource table from firmware image
+ * RSC_HANDLED if resource was handled, RSC_IGNORED if not handled
+ * and a negative value on error
* @find_loaded_rsc_table: find the loaded resource table from firmware image
* @get_loaded_rsc_table: get resource table installed in memory
* by external entity
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index ecf87484814f..266754a55327 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -39,6 +39,12 @@ struct sg_table {
unsigned int orig_nents; /* original size of list */
};
+struct sg_append_table {
+ struct sg_table sgt; /* The scatter list table */
+ struct scatterlist *prv; /* last populated sge in the table */
+ unsigned int total_nents; /* Total entries in the table */
+};
+
/*
* Notes on SG table design.
*
@@ -280,19 +286,51 @@ typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t);
typedef void (sg_free_fn)(struct scatterlist *, unsigned int);
void __sg_free_table(struct sg_table *, unsigned int, unsigned int,
- sg_free_fn *);
+ sg_free_fn *, unsigned int);
void sg_free_table(struct sg_table *);
+void sg_free_append_table(struct sg_append_table *sgt);
int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int,
struct scatterlist *, unsigned int, gfp_t, sg_alloc_fn *);
int sg_alloc_table(struct sg_table *, unsigned int, gfp_t);
-struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
- struct page **pages, unsigned int n_pages, unsigned int offset,
- unsigned long size, unsigned int max_segment,
- struct scatterlist *prv, unsigned int left_pages,
- gfp_t gfp_mask);
-int sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages,
- unsigned int n_pages, unsigned int offset,
- unsigned long size, gfp_t gfp_mask);
+int sg_alloc_append_table_from_pages(struct sg_append_table *sgt,
+ struct page **pages, unsigned int n_pages,
+ unsigned int offset, unsigned long size,
+ unsigned int max_segment,
+ unsigned int left_pages, gfp_t gfp_mask);
+int sg_alloc_table_from_pages_segment(struct sg_table *sgt, struct page **pages,
+ unsigned int n_pages, unsigned int offset,
+ unsigned long size,
+ unsigned int max_segment, gfp_t gfp_mask);
+
+/**
+ * sg_alloc_table_from_pages - Allocate and initialize an sg table from
+ * an array of pages
+ * @sgt: The sg table header to use
+ * @pages: Pointer to an array of page pointers
+ * @n_pages: Number of pages in the pages array
+ * @offset: Offset from start of the first page to the start of a buffer
+ * @size: Number of valid bytes in the buffer (after offset)
+ * @gfp_mask: GFP allocation mask
+ *
+ * Description:
+ * Allocate and initialize an sg table from a list of pages. Contiguous
+ * ranges of the pages are squashed into a single scatterlist node. A user
+ * may provide an offset at a start and a size of valid data in a buffer
+ * specified by the page array. The returned sg table is released by
+ * sg_free_table.
+ *
+ * Returns:
+ * 0 on success, negative error on failure
+ */
+static inline int sg_alloc_table_from_pages(struct sg_table *sgt,
+ struct page **pages,
+ unsigned int n_pages,
+ unsigned int offset,
+ unsigned long size, gfp_t gfp_mask)
+{
+ return sg_alloc_table_from_pages_segment(sgt, pages, n_pages, offset,
+ size, UINT_MAX, gfp_mask);
+}
#ifdef CONFIG_SGL_ALLOC
struct scatterlist *sgl_alloc_order(unsigned long long length,
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
index e24b1fe348e3..5561486fddef 100644
--- a/include/linux/sched/mm.h
+++ b/include/linux/sched/mm.h
@@ -174,13 +174,13 @@ static inline gfp_t current_gfp_context(gfp_t flags)
}
#ifdef CONFIG_LOCKDEP
-extern void __fs_reclaim_acquire(void);
-extern void __fs_reclaim_release(void);
+extern void __fs_reclaim_acquire(unsigned long ip);
+extern void __fs_reclaim_release(unsigned long ip);
extern void fs_reclaim_acquire(gfp_t gfp_mask);
extern void fs_reclaim_release(gfp_t gfp_mask);
#else
-static inline void __fs_reclaim_acquire(void) { }
-static inline void __fs_reclaim_release(void) { }
+static inline void __fs_reclaim_acquire(unsigned long ip) { }
+static inline void __fs_reclaim_release(unsigned long ip) { }
static inline void fs_reclaim_acquire(gfp_t gfp_mask) { }
static inline void fs_reclaim_release(gfp_t gfp_mask) { }
#endif
@@ -306,7 +306,7 @@ set_active_memcg(struct mem_cgroup *memcg)
{
struct mem_cgroup *old;
- if (in_interrupt()) {
+ if (!in_task()) {
old = this_cpu_read(int_active_memcg);
this_cpu_write(int_active_memcg, memcg);
} else {
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 0310a5add9ab..e5f4ce622ee6 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -298,11 +298,6 @@ static inline void kernel_signal_stop(void)
schedule();
}
-#ifdef __ARCH_SI_TRAPNO
-# define ___ARCH_SI_TRAPNO(_a1) , _a1
-#else
-# define ___ARCH_SI_TRAPNO(_a1)
-#endif
#ifdef __ia64__
# define ___ARCH_SI_IA64(_a1, _a2, _a3) , _a1, _a2, _a3
#else
@@ -310,14 +305,11 @@ static inline void kernel_signal_stop(void)
#endif
int force_sig_fault_to_task(int sig, int code, void __user *addr
- ___ARCH_SI_TRAPNO(int trapno)
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
, struct task_struct *t);
int force_sig_fault(int sig, int code, void __user *addr
- ___ARCH_SI_TRAPNO(int trapno)
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr));
int send_sig_fault(int sig, int code, void __user *addr
- ___ARCH_SI_TRAPNO(int trapno)
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
, struct task_struct *t);
@@ -329,6 +321,10 @@ int force_sig_pkuerr(void __user *addr, u32 pkey);
int force_sig_perf(void __user *addr, u32 type, u64 sig_data);
int force_sig_ptrace_errno_trap(int errno, void __user *addr);
+int force_sig_fault_trapno(int sig, int code, void __user *addr, int trapno);
+int send_sig_fault_trapno(int sig, int code, void __user *addr, int trapno,
+ struct task_struct *t);
+int force_sig_seccomp(int syscall, int reason, bool force_coredump);
extern int send_sig_info(int, struct kernel_siginfo *, struct task_struct *);
extern void force_sigsegv(int sig);
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 9f14f9c12ec4..3368c261ab62 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -327,4 +327,18 @@ static inline int serdev_tty_port_unregister(struct tty_port *port)
}
#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
+struct acpi_resource;
+struct acpi_resource_uart_serialbus;
+
+#ifdef CONFIG_ACPI
+bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
+ struct acpi_resource_uart_serialbus **uart);
+#else
+static inline bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
+ struct acpi_resource_uart_serialbus **uart)
+{
+ return false;
+}
+#endif /* CONFIG_ACPI */
+
#endif /*_LINUX_SERDEV_H */
diff --git a/include/linux/serial_s3c.h b/include/linux/serial_s3c.h
index f6c3323fc4c5..cf0de4a86640 100644
--- a/include/linux/serial_s3c.h
+++ b/include/linux/serial_s3c.h
@@ -27,6 +27,15 @@
#define S3C2410_UERSTAT (0x14)
#define S3C2410_UFSTAT (0x18)
#define S3C2410_UMSTAT (0x1C)
+#define USI_CON (0xC4)
+#define USI_OPTION (0xC8)
+
+#define USI_CON_RESET (1<<0)
+#define USI_CON_RESET_MASK (1<<0)
+
+#define USI_OPTION_HWACG_CLKREQ_ON (1<<1)
+#define USI_OPTION_HWACG_CLKSTOP_ON (1<<2)
+#define USI_OPTION_HWACG_MASK (3<<1)
#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 8e775ce517bb..166158b6e917 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -18,6 +18,7 @@ struct shmem_inode_info {
unsigned long flags;
unsigned long alloced; /* data pages alloced to file */
unsigned long swapped; /* subtotal assigned to swap */
+ pgoff_t fallocend; /* highest fallocate endindex */
struct list_head shrinklist; /* shrinkable hpage inodes */
struct list_head swaplist; /* chain of maybes on swap */
struct shared_policy policy; /* NUMA memory alloc policy */
@@ -31,7 +32,7 @@ struct shmem_sb_info {
struct percpu_counter used_blocks; /* How many are allocated */
unsigned long max_inodes; /* How many inodes are allowed */
unsigned long free_inodes; /* How many are left for allocation */
- spinlock_t stat_lock; /* Serialize shmem_sb_info changes */
+ raw_spinlock_t stat_lock; /* Serialize shmem_sb_info changes */
umode_t mode; /* Mount mode for root directory */
unsigned char huge; /* Whether to try for hugepages */
kuid_t uid; /* Mount uid for root directory */
@@ -85,7 +86,12 @@ extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
extern int shmem_unuse(unsigned int type, bool frontswap,
unsigned long *fs_pages_to_unuse);
-extern bool shmem_huge_enabled(struct vm_area_struct *vma);
+extern bool shmem_is_huge(struct vm_area_struct *vma,
+ struct inode *inode, pgoff_t index);
+static inline bool shmem_huge_enabled(struct vm_area_struct *vma)
+{
+ return shmem_is_huge(vma, file_inode(vma->vm_file), vma->vm_pgoff);
+}
extern unsigned long shmem_swap_usage(struct vm_area_struct *vma);
extern unsigned long shmem_partial_swap_usage(struct address_space *mapping,
pgoff_t start, pgoff_t end);
@@ -93,9 +99,8 @@ extern unsigned long shmem_partial_swap_usage(struct address_space *mapping,
/* Flag allocation requirements to shmem_getpage */
enum sgp_type {
SGP_READ, /* don't exceed i_size, don't allocate page */
+ SGP_NOALLOC, /* similar, but fail on hole or use fallocated page */
SGP_CACHE, /* don't exceed i_size, may allocate page */
- SGP_NOHUGE, /* like SGP_CACHE, but no huge pages */
- SGP_HUGE, /* like SGP_CACHE, huge pages preferred */
SGP_WRITE, /* may exceed i_size, may allocate !Uptodate page */
SGP_FALLOC, /* like SGP_WRITE, but make existing page Uptodate */
};
@@ -119,6 +124,18 @@ static inline bool shmem_file(struct file *file)
return shmem_mapping(file->f_mapping);
}
+/*
+ * If fallocate(FALLOC_FL_KEEP_SIZE) has been used, there may be pages
+ * beyond i_size's notion of EOF, which fallocate has committed to reserving:
+ * which split_huge_page() must therefore not delete. This use of a single
+ * "fallocend" per inode errs on the side of not deleting a reservation when
+ * in doubt: there are plenty of cases when it preserves unreserved pages.
+ */
+static inline pgoff_t shmem_fallocend(struct inode *inode, pgoff_t eof)
+{
+ return max(eof, SHMEM_I(inode)->fallocend);
+}
+
extern bool shmem_charge(struct inode *inode, long pages);
extern void shmem_uncharge(struct inode *inode, long pages);
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 3454c7ff0778..3f96a6374e4f 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -44,7 +44,7 @@ enum siginfo_layout {
SIL_FAULT_MCEERR,
SIL_FAULT_BNDERR,
SIL_FAULT_PKUERR,
- SIL_PERF_EVENT,
+ SIL_FAULT_PERF_EVENT,
SIL_CHLD,
SIL_RT,
SIL_SYS,
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6bdb0db3e825..841e2f0f5240 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1940,7 +1940,7 @@ static inline void __skb_insert(struct sk_buff *newsk,
WRITE_ONCE(newsk->prev, prev);
WRITE_ONCE(next->prev, newsk);
WRITE_ONCE(prev->next, newsk);
- list->qlen++;
+ WRITE_ONCE(list->qlen, list->qlen + 1);
}
static inline void __skb_queue_splice(const struct sk_buff_head *list,
diff --git a/include/linux/soc/marvell/octeontx2/asm.h b/include/linux/soc/marvell/octeontx2/asm.h
index 28c04d918f0f..fa1d6af0164e 100644
--- a/include/linux/soc/marvell/octeontx2/asm.h
+++ b/include/linux/soc/marvell/octeontx2/asm.h
@@ -22,12 +22,17 @@
: [rs]"r" (ioaddr)); \
(result); \
})
+/*
+ * STEORL store to memory with release semantics.
+ * This will avoid using DMB barrier after each LMTST
+ * operation.
+ */
#define cn10k_lmt_flush(val, addr) \
({ \
__asm__ volatile(".cpu generic+lse\n" \
- "steor %x[rf],[%[rs]]" \
- : [rf]"+r"(val) \
- : [rs]"r"(addr)); \
+ "steorl %x[rf],[%[rs]]" \
+ : [rf] "+r"(val) \
+ : [rs] "r"(addr)); \
})
#else
#define otx2_lmt_flush(ioaddr) ({ 0; })
diff --git a/include/linux/soc/qcom/smd-rpm.h b/include/linux/soc/qcom/smd-rpm.h
index f2645ec52520..60e66fc9b6bf 100644
--- a/include/linux/soc/qcom/smd-rpm.h
+++ b/include/linux/soc/qcom/smd-rpm.h
@@ -29,6 +29,7 @@ struct qcom_smd_rpm;
#define QCOM_SMD_RPM_NCPB 0x6270636E
#define QCOM_SMD_RPM_OCMEM_PWR 0x706d636f
#define QCOM_SMD_RPM_QPIC_CLK 0x63697071
+#define QCOM_SMD_RPM_QUP_CLK 0x707571
#define QCOM_SMD_RPM_SMPA 0x61706d73
#define QCOM_SMD_RPM_SMPB 0x62706d73
#define QCOM_SMD_RPM_SPDM 0x63707362
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index a48ac3e77301..76ce3f3ac0f2 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -661,6 +661,8 @@ struct sdw_slave_ops {
* initialized
* @first_interrupt_done: status flag tracking if the interrupt handling
* for a Slave happens for the first time after enumeration
+ * @is_mockup_device: status flag used to squelch errors in the command/control
+ * protocol for SoundWire mockup devices
*/
struct sdw_slave {
struct sdw_slave_id id;
@@ -683,6 +685,7 @@ struct sdw_slave {
struct completion initialization_complete;
u32 unattach_request;
bool first_interrupt_done;
+ bool is_mockup_device;
};
#define dev_to_sdw_dev(_dev) container_of(_dev, struct sdw_slave, dev)
diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h
index 1ebea7764011..8a463b8fc12a 100644
--- a/include/linux/soundwire/sdw_intel.h
+++ b/include/linux/soundwire/sdw_intel.h
@@ -7,6 +7,85 @@
#include <linux/irqreturn.h>
#include <linux/soundwire/sdw.h>
+#define SDW_SHIM_BASE 0x2C000
+#define SDW_ALH_BASE 0x2C800
+#define SDW_LINK_BASE 0x30000
+#define SDW_LINK_SIZE 0x10000
+
+/* Intel SHIM Registers Definition */
+#define SDW_SHIM_LCAP 0x0
+#define SDW_SHIM_LCTL 0x4
+#define SDW_SHIM_IPPTR 0x8
+#define SDW_SHIM_SYNC 0xC
+
+#define SDW_SHIM_CTLSCAP(x) (0x010 + 0x60 * (x))
+#define SDW_SHIM_CTLS0CM(x) (0x012 + 0x60 * (x))
+#define SDW_SHIM_CTLS1CM(x) (0x014 + 0x60 * (x))
+#define SDW_SHIM_CTLS2CM(x) (0x016 + 0x60 * (x))
+#define SDW_SHIM_CTLS3CM(x) (0x018 + 0x60 * (x))
+#define SDW_SHIM_PCMSCAP(x) (0x020 + 0x60 * (x))
+
+#define SDW_SHIM_PCMSYCHM(x, y) (0x022 + (0x60 * (x)) + (0x2 * (y)))
+#define SDW_SHIM_PCMSYCHC(x, y) (0x042 + (0x60 * (x)) + (0x2 * (y)))
+#define SDW_SHIM_PDMSCAP(x) (0x062 + 0x60 * (x))
+#define SDW_SHIM_IOCTL(x) (0x06C + 0x60 * (x))
+#define SDW_SHIM_CTMCTL(x) (0x06E + 0x60 * (x))
+
+#define SDW_SHIM_WAKEEN 0x190
+#define SDW_SHIM_WAKESTS 0x192
+
+#define SDW_SHIM_LCTL_SPA BIT(0)
+#define SDW_SHIM_LCTL_SPA_MASK GENMASK(3, 0)
+#define SDW_SHIM_LCTL_CPA BIT(8)
+#define SDW_SHIM_LCTL_CPA_MASK GENMASK(11, 8)
+
+#define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
+#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
+#define SDW_SHIM_SYNC_SYNCPRD GENMASK(14, 0)
+#define SDW_SHIM_SYNC_SYNCCPU BIT(15)
+#define SDW_SHIM_SYNC_CMDSYNC_MASK GENMASK(19, 16)
+#define SDW_SHIM_SYNC_CMDSYNC BIT(16)
+#define SDW_SHIM_SYNC_SYNCGO BIT(24)
+
+#define SDW_SHIM_PCMSCAP_ISS GENMASK(3, 0)
+#define SDW_SHIM_PCMSCAP_OSS GENMASK(7, 4)
+#define SDW_SHIM_PCMSCAP_BSS GENMASK(12, 8)
+
+#define SDW_SHIM_PCMSYCM_LCHN GENMASK(3, 0)
+#define SDW_SHIM_PCMSYCM_HCHN GENMASK(7, 4)
+#define SDW_SHIM_PCMSYCM_STREAM GENMASK(13, 8)
+#define SDW_SHIM_PCMSYCM_DIR BIT(15)
+
+#define SDW_SHIM_PDMSCAP_ISS GENMASK(3, 0)
+#define SDW_SHIM_PDMSCAP_OSS GENMASK(7, 4)
+#define SDW_SHIM_PDMSCAP_BSS GENMASK(12, 8)
+#define SDW_SHIM_PDMSCAP_CPSS GENMASK(15, 13)
+
+#define SDW_SHIM_IOCTL_MIF BIT(0)
+#define SDW_SHIM_IOCTL_CO BIT(1)
+#define SDW_SHIM_IOCTL_COE BIT(2)
+#define SDW_SHIM_IOCTL_DO BIT(3)
+#define SDW_SHIM_IOCTL_DOE BIT(4)
+#define SDW_SHIM_IOCTL_BKE BIT(5)
+#define SDW_SHIM_IOCTL_WPDD BIT(6)
+#define SDW_SHIM_IOCTL_CIBD BIT(8)
+#define SDW_SHIM_IOCTL_DIBD BIT(9)
+
+#define SDW_SHIM_CTMCTL_DACTQE BIT(0)
+#define SDW_SHIM_CTMCTL_DODS BIT(1)
+#define SDW_SHIM_CTMCTL_DOAIS GENMASK(4, 3)
+
+#define SDW_SHIM_WAKEEN_ENABLE BIT(0)
+#define SDW_SHIM_WAKESTS_STATUS BIT(0)
+
+/* Intel ALH Register definitions */
+#define SDW_ALH_STRMZCFG(x) (0x000 + (0x4 * (x)))
+#define SDW_ALH_NUM_STREAMS 64
+
+#define SDW_ALH_STRMZCFG_DMAT_VAL 0x3
+#define SDW_ALH_STRMZCFG_DMAT GENMASK(7, 0)
+#define SDW_ALH_STRMZCFG_CHN GENMASK(19, 16)
+
/**
* struct sdw_intel_stream_params_data: configuration passed during
* the @params_stream callback, e.g. for interaction with DSP
@@ -116,6 +195,8 @@ struct sdw_intel_slave_id {
* @link_list: list to handle interrupts across all links
* @shim_lock: mutex to handle concurrent rmw access to shared SHIM registers.
* @shim_mask: flags to track initialization of SHIM shared registers
+ * @shim_base: sdw shim base.
+ * @alh_base: sdw alh base.
*/
struct sdw_intel_ctx {
int count;
@@ -128,6 +209,8 @@ struct sdw_intel_ctx {
struct list_head link_list;
struct mutex shim_lock; /* lock for access to shared SHIM registers */
u32 shim_mask;
+ u32 shim_base;
+ u32 alh_base;
};
/**
@@ -146,6 +229,8 @@ struct sdw_intel_ctx {
* machine-specific quirks are handled in the DSP driver.
* @clock_stop_quirks: mask array of possible behaviors requested by the
* DSP driver. The quirks are common for all links for now.
+ * @shim_base: sdw shim base.
+ * @alh_base: sdw alh base.
*/
struct sdw_intel_res {
int count;
@@ -157,6 +242,8 @@ struct sdw_intel_res {
struct device *dev;
u32 link_mask;
u32 clock_stop_quirks;
+ u32 shim_base;
+ u32 alh_base;
};
/*
diff --git a/include/linux/spi/max7301.h b/include/linux/spi/max7301.h
index 433c20e2f46e..21449067aedb 100644
--- a/include/linux/spi/max7301.h
+++ b/include/linux/spi/max7301.h
@@ -2,7 +2,7 @@
#ifndef LINUX_SPI_MAX7301_H
#define LINUX_SPI_MAX7301_H
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
/*
* Some registers must be read back to modify.
diff --git a/include/linux/stat.h b/include/linux/stat.h
index fff27e603814..7df06931f25d 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -34,6 +34,10 @@ struct kstat {
STATX_ATTR_ENCRYPTED | \
STATX_ATTR_VERITY \
)/* Attrs corresponding to FS_*_FL flags */
+#define KSTAT_ATTR_VFS_FLAGS \
+ (STATX_ATTR_IMMUTABLE | \
+ STATX_ATTR_APPEND \
+ ) /* Attrs corresponding to S_* flags that are enforced by the VFS */
u64 ino;
dev_t dev;
dev_t rdev;
diff --git a/include/linux/stdarg.h b/include/linux/stdarg.h
new file mode 100644
index 000000000000..c8dc7f4f390c
--- /dev/null
+++ b/include/linux/stdarg.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#ifndef _LINUX_STDARG_H
+#define _LINUX_STDARG_H
+
+typedef __builtin_va_list va_list;
+#define va_start(v, l) __builtin_va_start(v, l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v, T) __builtin_va_arg(v, T)
+#define va_copy(d, s) __builtin_va_copy(d, s)
+
+#endif
diff --git a/include/linux/string.h b/include/linux/string.h
index b48d2d28e0b1..5e96d656be7a 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -6,7 +6,7 @@
#include <linux/types.h> /* for size_t */
#include <linux/stddef.h> /* for NULL */
#include <linux/errno.h> /* for E2BIG */
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <uapi/linux/string.h>
extern char *strndup_user(const char __user *, long);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 8b5d5c97553e..a4661646adc9 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -14,6 +14,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/in6.h>
+#include <linux/refcount.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/sched.h>
@@ -35,7 +36,7 @@ struct rpc_sysfs_client;
* The high-level client handle
*/
struct rpc_clnt {
- atomic_t cl_count; /* Number of references */
+ refcount_t cl_count; /* Number of references */
unsigned int cl_clid; /* client id */
struct list_head cl_clients; /* Global list of clients */
struct list_head cl_tasks; /* List of tasks */
@@ -81,6 +82,7 @@ struct rpc_clnt {
struct work_struct cl_work;
};
const struct cred *cl_cred;
+ unsigned int cl_max_connect; /* max number of transports not to the same IP */
};
/*
@@ -135,6 +137,7 @@ struct rpc_create_args {
char *client_name;
struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */
const struct cred *cred;
+ unsigned int max_connect;
};
struct rpc_add_xprt_test {
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index f0f846fa396e..064c96157d1f 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -277,13 +277,13 @@ struct svc_rqst {
#define RQ_VICTIM (5) /* about to be shut down */
#define RQ_BUSY (6) /* request is busy */
#define RQ_DATA (7) /* request has data */
-#define RQ_AUTHERR (8) /* Request status is auth error */
unsigned long rq_flags; /* flags field */
ktime_t rq_qtime; /* enqueue time */
void * rq_argp; /* decoded arguments */
void * rq_resp; /* xdr'd results */
void * rq_auth_data; /* flavor-specific data */
+ __be32 rq_auth_stat; /* authentication status */
int rq_auth_slack; /* extra space xdr code
* should leave in head
* for krb5i, krb5p.
@@ -537,7 +537,6 @@ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
char *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
struct kvec *first, void *p,
size_t total);
-__be32 svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err);
__be32 svc_generic_init_request(struct svc_rqst *rqstp,
const struct svc_program *progp,
struct svc_process_info *procinfo);
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index b0003866a249..6d9cc9080aca 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -127,7 +127,7 @@ struct auth_ops {
char * name;
struct module *owner;
int flavour;
- int (*accept)(struct svc_rqst *rq, __be32 *authp);
+ int (*accept)(struct svc_rqst *rq);
int (*release)(struct svc_rqst *rq);
void (*domain_release)(struct auth_domain *);
int (*set_client)(struct svc_rqst *rq);
@@ -149,7 +149,7 @@ struct auth_ops {
struct svc_xprt;
-extern int svc_authenticate(struct svc_rqst *rqstp, __be32 *authp);
+extern int svc_authenticate(struct svc_rqst *rqstp);
extern int svc_authorise(struct svc_rqst *rqstp);
extern int svc_set_client(struct svc_rqst *rqstp);
extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index b15c1f07162d..955ea4d7af0b 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -431,6 +431,7 @@ void xprt_release_write(struct rpc_xprt *, struct rpc_task *);
#define XPRT_CONGESTED (9)
#define XPRT_CWND_WAIT (10)
#define XPRT_WRITE_SPACE (11)
+#define XPRT_SND_IS_COOKIE (12)
static inline void xprt_set_connected(struct rpc_xprt *xprt)
{
diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h
index b19addc8b715..bbb8a5fa0816 100644
--- a/include/linux/sunrpc/xprtmultipath.h
+++ b/include/linux/sunrpc/xprtmultipath.h
@@ -18,6 +18,7 @@ struct rpc_xprt_switch {
unsigned int xps_id;
unsigned int xps_nxprts;
unsigned int xps_nactive;
+ unsigned int xps_nunique_destaddr_xprts;
atomic_long_t xps_queuelen;
struct list_head xps_xprt_list;
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 6f5a43251593..ba52f3a3478e 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -408,7 +408,7 @@ static inline bool node_reclaim_enabled(void)
extern void check_move_unevictable_pages(struct pagevec *pvec);
-extern int kswapd_run(int nid);
+extern void kswapd_run(int nid);
extern void kswapd_stop(int nid);
#ifdef CONFIG_SWAP
@@ -721,7 +721,13 @@ static inline int mem_cgroup_swappiness(struct mem_cgroup *mem)
#endif
#if defined(CONFIG_SWAP) && defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP)
-extern void cgroup_throttle_swaprate(struct page *page, gfp_t gfp_mask);
+extern void __cgroup_throttle_swaprate(struct page *page, gfp_t gfp_mask);
+static inline void cgroup_throttle_swaprate(struct page *page, gfp_t gfp_mask)
+{
+ if (mem_cgroup_disabled())
+ return;
+ __cgroup_throttle_swaprate(page, gfp_mask);
+}
#else
static inline void cgroup_throttle_swaprate(struct page *page, gfp_t gfp_mask)
{
@@ -730,8 +736,22 @@ static inline void cgroup_throttle_swaprate(struct page *page, gfp_t gfp_mask)
#ifdef CONFIG_MEMCG_SWAP
extern void mem_cgroup_swapout(struct page *page, swp_entry_t entry);
-extern int mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry);
-extern void mem_cgroup_uncharge_swap(swp_entry_t entry, unsigned int nr_pages);
+extern int __mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry);
+static inline int mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry)
+{
+ if (mem_cgroup_disabled())
+ return 0;
+ return __mem_cgroup_try_charge_swap(page, entry);
+}
+
+extern void __mem_cgroup_uncharge_swap(swp_entry_t entry, unsigned int nr_pages);
+static inline void mem_cgroup_uncharge_swap(swp_entry_t entry, unsigned int nr_pages)
+{
+ if (mem_cgroup_disabled())
+ return;
+ __mem_cgroup_uncharge_swap(entry, nr_pages);
+}
+
extern long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg);
extern bool mem_cgroup_swap_full(struct page *page);
#else
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 216854a5e513..b0cb2a9973f4 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -2,6 +2,7 @@
#ifndef __LINUX_SWIOTLB_H
#define __LINUX_SWIOTLB_H
+#include <linux/device.h>
#include <linux/dma-direction.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -72,7 +73,8 @@ extern enum swiotlb_force swiotlb_force;
* range check to see if the memory was in fact allocated by this
* API.
* @nslabs: The number of IO TLB blocks (in groups of 64) between @start and
- * @end. This is command line adjustable via setup_io_tlb_npages.
+ * @end. For default swiotlb, this is command line adjustable via
+ * setup_io_tlb_npages.
* @used: The number of used IO TLB block.
* @list: The free list describing the number of free entries available
* from each index.
@@ -83,6 +85,8 @@ extern enum swiotlb_force swiotlb_force;
* unmap calls.
* @debugfs: The dentry to debugfs.
* @late_alloc: %true if allocated using the page allocator
+ * @force_bounce: %true if swiotlb bouncing is forced
+ * @for_alloc: %true if the pool is used for memory allocation
*/
struct io_tlb_mem {
phys_addr_t start;
@@ -93,29 +97,42 @@ struct io_tlb_mem {
spinlock_t lock;
struct dentry *debugfs;
bool late_alloc;
+ bool force_bounce;
+ bool for_alloc;
struct io_tlb_slot {
phys_addr_t orig_addr;
size_t alloc_size;
unsigned int list;
- } slots[];
+ } *slots;
};
-extern struct io_tlb_mem *io_tlb_default_mem;
+extern struct io_tlb_mem io_tlb_default_mem;
-static inline bool is_swiotlb_buffer(phys_addr_t paddr)
+static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
return mem && paddr >= mem->start && paddr < mem->end;
}
+static inline bool is_swiotlb_force_bounce(struct device *dev)
+{
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
+
+ return mem && mem->force_bounce;
+}
+
void __init swiotlb_exit(void);
unsigned int swiotlb_max_segment(void);
size_t swiotlb_max_mapping_size(struct device *dev);
-bool is_swiotlb_active(void);
+bool is_swiotlb_active(struct device *dev);
void __init swiotlb_adjust_size(unsigned long size);
#else
#define swiotlb_force SWIOTLB_NO_FORCE
-static inline bool is_swiotlb_buffer(phys_addr_t paddr)
+static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr)
+{
+ return false;
+}
+static inline bool is_swiotlb_force_bounce(struct device *dev)
{
return false;
}
@@ -131,7 +148,7 @@ static inline size_t swiotlb_max_mapping_size(struct device *dev)
return SIZE_MAX;
}
-static inline bool is_swiotlb_active(void)
+static inline bool is_swiotlb_active(struct device *dev)
{
return false;
}
@@ -144,4 +161,28 @@ static inline void swiotlb_adjust_size(unsigned long size)
extern void swiotlb_print_info(void);
extern void swiotlb_set_max_segment(unsigned int);
+#ifdef CONFIG_DMA_RESTRICTED_POOL
+struct page *swiotlb_alloc(struct device *dev, size_t size);
+bool swiotlb_free(struct device *dev, struct page *page, size_t size);
+
+static inline bool is_swiotlb_for_alloc(struct device *dev)
+{
+ return dev->dma_io_tlb_mem->for_alloc;
+}
+#else
+static inline struct page *swiotlb_alloc(struct device *dev, size_t size)
+{
+ return NULL;
+}
+static inline bool swiotlb_free(struct device *dev, struct page *page,
+ size_t size)
+{
+ return false;
+}
+static inline bool is_swiotlb_for_alloc(struct device *dev)
+{
+ return false;
+}
+#endif /* CONFIG_DMA_RESTRICTED_POOL */
+
#endif /* __LINUX_SWIOTLB_H */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 69c9a7010081..60a3ab0ad2cc 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -915,6 +915,7 @@ asmlinkage long sys_mincore(unsigned long start, size_t len,
asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior);
asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec,
size_t vlen, int behavior, unsigned int flags);
+asmlinkage long sys_process_mrelease(int pidfd, unsigned int flags);
asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
unsigned long prot, unsigned long pgoff,
unsigned long flags);
@@ -1158,7 +1159,6 @@ asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf);
asmlinkage long sys_vfork(void);
asmlinkage long sys_recv(int, void __user *, size_t, unsigned);
asmlinkage long sys_send(int, void __user *, size_t, unsigned);
-asmlinkage long sys_bdflush(int func, long data);
asmlinkage long sys_oldumount(char __user *name);
asmlinkage long sys_uselib(const char __user *library);
asmlinkage long sys_sysfs(int option,
diff --git a/arch/x86/include/asm/sysfb.h b/include/linux/sysfb.h
index 9834eef7f034..b0dcfa26d07b 100644
--- a/arch/x86/include/asm/sysfb.h
+++ b/include/linux/sysfb.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _ARCH_X86_KERNEL_SYSFB_H
-#define _ARCH_X86_KERNEL_SYSFB_H
+#ifndef _LINUX_SYSFB_H
+#define _LINUX_SYSFB_H
/*
* Generic System Framebuffers on x86
@@ -58,37 +58,37 @@ struct efifb_dmi_info {
#ifdef CONFIG_EFI
extern struct efifb_dmi_info efifb_dmi_list[];
-void sysfb_apply_efi_quirks(void);
+void sysfb_apply_efi_quirks(struct platform_device *pd);
#else /* CONFIG_EFI */
-static inline void sysfb_apply_efi_quirks(void)
+static inline void sysfb_apply_efi_quirks(struct platform_device *pd)
{
}
#endif /* CONFIG_EFI */
-#ifdef CONFIG_X86_SYSFB
+#ifdef CONFIG_SYSFB_SIMPLEFB
-bool parse_mode(const struct screen_info *si,
- struct simplefb_platform_data *mode);
-int create_simplefb(const struct screen_info *si,
- const struct simplefb_platform_data *mode);
+bool sysfb_parse_mode(const struct screen_info *si,
+ struct simplefb_platform_data *mode);
+int sysfb_create_simplefb(const struct screen_info *si,
+ const struct simplefb_platform_data *mode);
-#else /* CONFIG_X86_SYSFB */
+#else /* CONFIG_SYSFB_SIMPLE */
-static inline bool parse_mode(const struct screen_info *si,
- struct simplefb_platform_data *mode)
+static inline bool sysfb_parse_mode(const struct screen_info *si,
+ struct simplefb_platform_data *mode)
{
return false;
}
-static inline int create_simplefb(const struct screen_info *si,
- const struct simplefb_platform_data *mode)
+static inline int sysfb_create_simplefb(const struct screen_info *si,
+ const struct simplefb_platform_data *mode)
{
return -EINVAL;
}
-#endif /* CONFIG_X86_SYSFB */
+#endif /* CONFIG_SYSFB_SIMPLE */
-#endif /* _ARCH_X86_KERNEL_SYSFB_H */
+#endif /* _LINUX_SYSFB_H */
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index a12556a4b93a..e3f1e8ac1f85 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -176,7 +176,7 @@ struct bin_attribute {
struct attribute attr;
size_t size;
void *private;
- struct address_space *mapping;
+ struct address_space *(*f_mapping)(void);
ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h
index e7c96c37174f..124e13cb1469 100644
--- a/include/linux/thunderbolt.h
+++ b/include/linux/thunderbolt.h
@@ -468,6 +468,7 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc)
* @interrupt_work: Work scheduled to handle ring interrupt when no
* MSI-X is used.
* @hop_count: Number of rings (end point hops) supported by NHI.
+ * @quirks: NHI specific quirks if any
*/
struct tb_nhi {
spinlock_t lock;
@@ -480,6 +481,7 @@ struct tb_nhi {
bool going_away;
struct work_struct interrupt_work;
u32 hop_count;
+ unsigned long quirks;
};
/**
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 8e0631a4b046..3e475eeb5a99 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -310,8 +310,10 @@ enum {
TRACE_EVENT_FL_NO_SET_FILTER_BIT,
TRACE_EVENT_FL_IGNORE_ENABLE_BIT,
TRACE_EVENT_FL_TRACEPOINT_BIT,
+ TRACE_EVENT_FL_DYNAMIC_BIT,
TRACE_EVENT_FL_KPROBE_BIT,
TRACE_EVENT_FL_UPROBE_BIT,
+ TRACE_EVENT_FL_EPROBE_BIT,
};
/*
@@ -321,8 +323,10 @@ enum {
* NO_SET_FILTER - Set when filter has error and is to be ignored
* IGNORE_ENABLE - For trace internal events, do not enable with debugfs file
* TRACEPOINT - Event is a tracepoint
+ * DYNAMIC - Event is a dynamic event (created at run time)
* KPROBE - Event is a kprobe
* UPROBE - Event is a uprobe
+ * EPROBE - Event is an event probe
*/
enum {
TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
@@ -330,8 +334,10 @@ enum {
TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT),
TRACE_EVENT_FL_IGNORE_ENABLE = (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT),
TRACE_EVENT_FL_TRACEPOINT = (1 << TRACE_EVENT_FL_TRACEPOINT_BIT),
+ TRACE_EVENT_FL_DYNAMIC = (1 << TRACE_EVENT_FL_DYNAMIC_BIT),
TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT),
TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT),
+ TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT),
};
#define TRACE_EVENT_FL_UKPROBE (TRACE_EVENT_FL_KPROBE | TRACE_EVENT_FL_UPROBE)
@@ -347,7 +353,14 @@ struct trace_event_call {
struct trace_event event;
char *print_fmt;
struct event_filter *filter;
- void *mod;
+ /*
+ * Static events can disappear with modules,
+ * where as dynamic ones need their own ref count.
+ */
+ union {
+ void *module;
+ atomic_t refcnt;
+ };
void *data;
/* See the TRACE_EVENT_FL_* flags above */
@@ -363,6 +376,42 @@ struct trace_event_call {
#endif
};
+#ifdef CONFIG_DYNAMIC_EVENTS
+bool trace_event_dyn_try_get_ref(struct trace_event_call *call);
+void trace_event_dyn_put_ref(struct trace_event_call *call);
+bool trace_event_dyn_busy(struct trace_event_call *call);
+#else
+static inline bool trace_event_dyn_try_get_ref(struct trace_event_call *call)
+{
+ /* Without DYNAMIC_EVENTS configured, nothing should be calling this */
+ return false;
+}
+static inline void trace_event_dyn_put_ref(struct trace_event_call *call)
+{
+}
+static inline bool trace_event_dyn_busy(struct trace_event_call *call)
+{
+ /* Nothing should call this without DYNAIMIC_EVENTS configured. */
+ return true;
+}
+#endif
+
+static inline bool trace_event_try_get_ref(struct trace_event_call *call)
+{
+ if (call->flags & TRACE_EVENT_FL_DYNAMIC)
+ return trace_event_dyn_try_get_ref(call);
+ else
+ return try_module_get(call->module);
+}
+
+static inline void trace_event_put_ref(struct trace_event_call *call)
+{
+ if (call->flags & TRACE_EVENT_FL_DYNAMIC)
+ trace_event_dyn_put_ref(call);
+ else
+ module_put(call->module);
+}
+
#ifdef CONFIG_PERF_EVENTS
static inline bool bpf_prog_array_valid(struct trace_event_call *call)
{
@@ -634,6 +683,7 @@ enum event_trigger_type {
ETT_EVENT_ENABLE = (1 << 3),
ETT_EVENT_HIST = (1 << 4),
ETT_HIST_ENABLE = (1 << 5),
+ ETT_EVENT_EPROBE = (1 << 6),
};
extern int filter_match_preds(struct event_filter *filter, void *rec);
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index ab58696d0ddd..28031b15f878 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -475,7 +475,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
* *
* * The declared 'local variable' is called '__entry'
* *
- * * __field(pid_t, prev_prid) is equivalent to a standard declaration:
+ * * __field(pid_t, prev_pid) is equivalent to a standard declaration:
* *
* * pid_t prev_pid;
* *
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 19dc1097e09c..168e57e40bbb 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -6,11 +6,12 @@
#include <linux/major.h>
#include <linux/termios.h>
#include <linux/workqueue.h>
+#include <linux/tty_buffer.h>
#include <linux/tty_driver.h>
#include <linux/tty_ldisc.h>
+#include <linux/tty_port.h>
#include <linux/mutex.h>
#include <linux/tty_flags.h>
-#include <linux/seq_file.h>
#include <uapi/linux/tty.h>
#include <linux/rwsem.h>
#include <linux/llist.h>
@@ -31,54 +32,6 @@
*/
#define __DISABLED_CHAR '\0'
-struct tty_buffer {
- union {
- struct tty_buffer *next;
- struct llist_node free;
- };
- int used;
- int size;
- int commit;
- int read;
- int flags;
- /* Data points here */
- unsigned long data[];
-};
-
-/* Values for .flags field of tty_buffer */
-#define TTYB_NORMAL 1 /* buffer has no flags buffer */
-
-static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs)
-{
- return ((unsigned char *)b->data) + ofs;
-}
-
-static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs)
-{
- return (char *)char_buf_ptr(b, ofs) + b->size;
-}
-
-struct tty_bufhead {
- struct tty_buffer *head; /* Queue head */
- struct work_struct work;
- struct mutex lock;
- atomic_t priority;
- struct tty_buffer sentinel;
- struct llist_head free; /* Free queue head */
- atomic_t mem_used; /* In-use buffers excluding free list */
- int mem_limit;
- struct tty_buffer *tail; /* Active buffer */
-};
-/*
- * When a break, frame error, or parity error happens, these codes are
- * stuffed into the flags buffer.
- */
-#define TTY_NORMAL 0
-#define TTY_BREAK 1
-#define TTY_FRAME 2
-#define TTY_PARITY 3
-#define TTY_OVERRUN 4
-
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
@@ -164,85 +117,6 @@ struct tty_bufhead {
struct device;
struct signal_struct;
-
-/*
- * Port level information. Each device keeps its own port level information
- * so provide a common structure for those ports wanting to use common support
- * routines.
- *
- * The tty port has a different lifetime to the tty so must be kept apart.
- * In addition be careful as tty -> port mappings are valid for the life
- * of the tty object but in many cases port -> tty mappings are valid only
- * until a hangup so don't use the wrong path.
- */
-
-struct tty_port;
-
-struct tty_port_operations {
- /* Return 1 if the carrier is raised */
- int (*carrier_raised)(struct tty_port *port);
- /* Control the DTR line */
- void (*dtr_rts)(struct tty_port *port, int raise);
- /* Called when the last close completes or a hangup finishes
- IFF the port was initialized. Do not use to free resources. Called
- under the port mutex to serialize against activate/shutdowns */
- void (*shutdown)(struct tty_port *port);
- /* Called under the port mutex from tty_port_open, serialized using
- the port mutex */
- /* FIXME: long term getting the tty argument *out* of this would be
- good for consoles */
- int (*activate)(struct tty_port *port, struct tty_struct *tty);
- /* Called on the final put of a port */
- void (*destruct)(struct tty_port *port);
-};
-
-struct tty_port_client_operations {
- int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t);
- void (*write_wakeup)(struct tty_port *port);
-};
-
-extern const struct tty_port_client_operations tty_port_default_client_ops;
-
-struct tty_port {
- struct tty_bufhead buf; /* Locked internally */
- struct tty_struct *tty; /* Back pointer */
- struct tty_struct *itty; /* internal back ptr */
- const struct tty_port_operations *ops; /* Port operations */
- const struct tty_port_client_operations *client_ops; /* Port client operations */
- spinlock_t lock; /* Lock protecting tty field */
- int blocked_open; /* Waiting to open */
- int count; /* Usage count */
- wait_queue_head_t open_wait; /* Open waiters */
- wait_queue_head_t delta_msr_wait; /* Modem status change */
- unsigned long flags; /* User TTY flags ASYNC_ */
- unsigned long iflags; /* Internal flags TTY_PORT_ */
- unsigned char console:1; /* port is a console */
- struct mutex mutex; /* Locking */
- struct mutex buf_mutex; /* Buffer alloc lock */
- unsigned char *xmit_buf; /* Optional buffer */
- unsigned int close_delay; /* Close port delay */
- unsigned int closing_wait; /* Delay for output */
- int drain_delay; /* Set to zero if no pure time
- based drain is needed else
- set to size of fifo */
- struct kref kref; /* Ref counter */
- void *client_data;
-};
-
-/* tty_port::iflags bits -- use atomic bit ops */
-#define TTY_PORT_INITIALIZED 0 /* device is initialized */
-#define TTY_PORT_SUSPENDED 1 /* device is suspended */
-#define TTY_PORT_ACTIVE 2 /* device is open */
-
-/*
- * uart drivers: use the uart_port::status field and the UPSTAT_* defines
- * for s/w-based flow control steering and carrier detection status
- */
-#define TTY_PORT_CTS_FLOW 3 /* h/w flow control enabled */
-#define TTY_PORT_CHECK_CD 4 /* carrier detect enabled */
-#define TTY_PORT_KOPENED 5 /* device exclusively opened by
- kernel */
-
struct tty_operations;
/**
@@ -446,15 +320,6 @@ extern const char *tty_driver_name(const struct tty_struct *tty);
extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
extern void stop_tty(struct tty_struct *tty);
extern void start_tty(struct tty_struct *tty);
-extern int tty_register_driver(struct tty_driver *driver);
-extern void tty_unregister_driver(struct tty_driver *driver);
-extern struct device *tty_register_device(struct tty_driver *driver,
- unsigned index, struct device *dev);
-extern struct device *tty_register_device_attr(struct tty_driver *driver,
- unsigned index, struct device *device,
- void *drvdata,
- const struct attribute_group **attr_grp);
-extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
extern void tty_write_message(struct tty_struct *tty, char *msg);
extern int tty_send_xchar(struct tty_struct *tty, char ch);
extern int tty_put_char(struct tty_struct *tty, unsigned char c);
@@ -502,13 +367,7 @@ extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
extern int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b);
extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
-extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
-extern void tty_ldisc_deref(struct tty_ldisc *);
-extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
-extern const struct seq_operations tty_ldiscs_seq_ops;
-
extern void tty_wakeup(struct tty_struct *tty);
-extern void tty_ldisc_flush(struct tty_struct *tty);
extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
@@ -522,128 +381,6 @@ extern int tty_standard_install(struct tty_driver *driver,
extern struct mutex tty_mutex;
-extern void tty_port_init(struct tty_port *port);
-extern void tty_port_link_device(struct tty_port *port,
- struct tty_driver *driver, unsigned index);
-extern struct device *tty_port_register_device(struct tty_port *port,
- struct tty_driver *driver, unsigned index,
- struct device *device);
-extern struct device *tty_port_register_device_attr(struct tty_port *port,
- struct tty_driver *driver, unsigned index,
- struct device *device, void *drvdata,
- const struct attribute_group **attr_grp);
-extern struct device *tty_port_register_device_serdev(struct tty_port *port,
- struct tty_driver *driver, unsigned index,
- struct device *device);
-extern struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
- struct tty_driver *driver, unsigned index,
- struct device *device, void *drvdata,
- const struct attribute_group **attr_grp);
-extern void tty_port_unregister_device(struct tty_port *port,
- struct tty_driver *driver, unsigned index);
-extern int tty_port_alloc_xmit_buf(struct tty_port *port);
-extern void tty_port_free_xmit_buf(struct tty_port *port);
-extern void tty_port_destroy(struct tty_port *port);
-extern void tty_port_put(struct tty_port *port);
-
-static inline struct tty_port *tty_port_get(struct tty_port *port)
-{
- if (port && kref_get_unless_zero(&port->kref))
- return port;
- return NULL;
-}
-
-/* If the cts flow control is enabled, return true. */
-static inline bool tty_port_cts_enabled(const struct tty_port *port)
-{
- return test_bit(TTY_PORT_CTS_FLOW, &port->iflags);
-}
-
-static inline void tty_port_set_cts_flow(struct tty_port *port, bool val)
-{
- assign_bit(TTY_PORT_CTS_FLOW, &port->iflags, val);
-}
-
-static inline bool tty_port_active(const struct tty_port *port)
-{
- return test_bit(TTY_PORT_ACTIVE, &port->iflags);
-}
-
-static inline void tty_port_set_active(struct tty_port *port, bool val)
-{
- assign_bit(TTY_PORT_ACTIVE, &port->iflags, val);
-}
-
-static inline bool tty_port_check_carrier(const struct tty_port *port)
-{
- return test_bit(TTY_PORT_CHECK_CD, &port->iflags);
-}
-
-static inline void tty_port_set_check_carrier(struct tty_port *port, bool val)
-{
- assign_bit(TTY_PORT_CHECK_CD, &port->iflags, val);
-}
-
-static inline bool tty_port_suspended(const struct tty_port *port)
-{
- return test_bit(TTY_PORT_SUSPENDED, &port->iflags);
-}
-
-static inline void tty_port_set_suspended(struct tty_port *port, bool val)
-{
- assign_bit(TTY_PORT_SUSPENDED, &port->iflags, val);
-}
-
-static inline bool tty_port_initialized(const struct tty_port *port)
-{
- return test_bit(TTY_PORT_INITIALIZED, &port->iflags);
-}
-
-static inline void tty_port_set_initialized(struct tty_port *port, bool val)
-{
- assign_bit(TTY_PORT_INITIALIZED, &port->iflags, val);
-}
-
-static inline bool tty_port_kopened(const struct tty_port *port)
-{
- return test_bit(TTY_PORT_KOPENED, &port->iflags);
-}
-
-static inline void tty_port_set_kopened(struct tty_port *port, bool val)
-{
- assign_bit(TTY_PORT_KOPENED, &port->iflags, val);
-}
-
-extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
-extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
-extern int tty_port_carrier_raised(struct tty_port *port);
-extern void tty_port_raise_dtr_rts(struct tty_port *port);
-extern void tty_port_lower_dtr_rts(struct tty_port *port);
-extern void tty_port_hangup(struct tty_port *port);
-extern void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
-extern void tty_port_tty_wakeup(struct tty_port *port);
-extern int tty_port_block_til_ready(struct tty_port *port,
- struct tty_struct *tty, struct file *filp);
-extern int tty_port_close_start(struct tty_port *port,
- struct tty_struct *tty, struct file *filp);
-extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
-extern void tty_port_close(struct tty_port *port,
- struct tty_struct *tty, struct file *filp);
-extern int tty_port_install(struct tty_port *port, struct tty_driver *driver,
- struct tty_struct *tty);
-extern int tty_port_open(struct tty_port *port,
- struct tty_struct *tty, struct file *filp);
-static inline int tty_port_users(struct tty_port *port)
-{
- return port->count + port->blocked_open;
-}
-
-extern int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc);
-extern void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc);
-extern int tty_set_ldisc(struct tty_struct *tty, int disc);
-extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
- const char *f, int count);
-
/* n_tty.c */
extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
#ifdef CONFIG_TTY
@@ -691,12 +428,4 @@ extern void tty_lock_slave(struct tty_struct *tty);
extern void tty_unlock_slave(struct tty_struct *tty);
extern void tty_set_lock_subclass(struct tty_struct *tty);
-#ifdef CONFIG_PROC_FS
-extern void proc_tty_register_driver(struct tty_driver *);
-extern void proc_tty_unregister_driver(struct tty_driver *);
-#else
-static inline void proc_tty_register_driver(struct tty_driver *d) {}
-static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
-#endif
-
#endif
diff --git a/include/linux/tty_buffer.h b/include/linux/tty_buffer.h
new file mode 100644
index 000000000000..3b9d77604291
--- /dev/null
+++ b/include/linux/tty_buffer.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_TTY_BUFFER_H
+#define _LINUX_TTY_BUFFER_H
+
+#include <linux/atomic.h>
+#include <linux/llist.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+struct tty_buffer {
+ union {
+ struct tty_buffer *next;
+ struct llist_node free;
+ };
+ int used;
+ int size;
+ int commit;
+ int read;
+ int flags;
+ /* Data points here */
+ unsigned long data[];
+};
+
+/* Values for .flags field of tty_buffer */
+#define TTYB_NORMAL 1 /* buffer has no flags buffer */
+
+static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs)
+{
+ return ((unsigned char *)b->data) + ofs;
+}
+
+static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs)
+{
+ return (char *)char_buf_ptr(b, ofs) + b->size;
+}
+
+struct tty_bufhead {
+ struct tty_buffer *head; /* Queue head */
+ struct work_struct work;
+ struct mutex lock;
+ atomic_t priority;
+ struct tty_buffer sentinel;
+ struct llist_head free; /* Free queue head */
+ atomic_t mem_used; /* In-use buffers excluding free list */
+ int mem_limit;
+ struct tty_buffer *tail; /* Active buffer */
+};
+
+/*
+ * When a break, frame error, or parity error happens, these codes are
+ * stuffed into the flags buffer.
+ */
+#define TTY_NORMAL 0
+#define TTY_BREAK 1
+#define TTY_FRAME 2
+#define TTY_PARITY 3
+#define TTY_OVERRUN 4
+
+#endif
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 448f8ee6db6e..c20431d8def8 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -233,6 +233,7 @@
#include <linux/export.h>
#include <linux/fs.h>
+#include <linux/kref.h>
#include <linux/list.h>
#include <linux/cdev.h>
#include <linux/termios.h>
@@ -328,9 +329,6 @@ extern struct list_head tty_drivers;
extern struct tty_driver *__tty_alloc_driver(unsigned int lines,
struct module *owner, unsigned long flags);
-extern void put_tty_driver(struct tty_driver *driver);
-extern void tty_set_operations(struct tty_driver *driver,
- const struct tty_operations *op);
extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
extern void tty_driver_kref_put(struct tty_driver *driver);
@@ -339,24 +337,18 @@ extern void tty_driver_kref_put(struct tty_driver *driver);
#define tty_alloc_driver(lines, flags) \
__tty_alloc_driver(lines, THIS_MODULE, flags)
-/*
- * DEPRECATED Do not use this in new code, use tty_alloc_driver instead.
- * (And change the return value checks.)
- */
-static inline struct tty_driver *alloc_tty_driver(unsigned int lines)
-{
- struct tty_driver *ret = tty_alloc_driver(lines, 0);
- if (IS_ERR(ret))
- return NULL;
- return ret;
-}
-
static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
{
kref_get(&d->kref);
return d;
}
+static inline void tty_set_operations(struct tty_driver *driver,
+ const struct tty_operations *op)
+{
+ driver->ops = op;
+}
+
/* tty driver magic number */
#define TTY_DRIVER_MAGIC 0x5402
@@ -434,4 +426,21 @@ static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
/* serial subtype definitions */
#define SERIAL_TYPE_NORMAL 1
+int tty_register_driver(struct tty_driver *driver);
+void tty_unregister_driver(struct tty_driver *driver);
+struct device *tty_register_device(struct tty_driver *driver, unsigned index,
+ struct device *dev);
+struct device *tty_register_device_attr(struct tty_driver *driver,
+ unsigned index, struct device *device, void *drvdata,
+ const struct attribute_group **attr_grp);
+void tty_unregister_device(struct tty_driver *driver, unsigned index);
+
+#ifdef CONFIG_PROC_FS
+void proc_tty_register_driver(struct tty_driver *);
+void proc_tty_unregister_driver(struct tty_driver *);
+#else
+static inline void proc_tty_register_driver(struct tty_driver *d) {}
+static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
+#endif
+
#endif /* #ifdef _LINUX_TTY_DRIVER_H */
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index 67d78dc553e1..32284992b31a 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -2,7 +2,10 @@
#ifndef _LINUX_TTY_FLIP_H
#define _LINUX_TTY_FLIP_H
-#include <linux/tty.h>
+#include <linux/tty_buffer.h>
+#include <linux/tty_port.h>
+
+struct tty_ldisc;
extern int tty_buffer_set_limit(struct tty_port *port, int limit);
extern unsigned int tty_buffer_space_avail(struct tty_port *port);
@@ -39,6 +42,9 @@ static inline int tty_insert_flip_string(struct tty_port *port,
return tty_insert_flip_string_fixed_flag(port, chars, TTY_NORMAL, size);
}
+int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
+ const char *f, int count);
+
extern void tty_buffer_lock_exclusive(struct tty_port *port);
extern void tty_buffer_unlock_exclusive(struct tty_port *port);
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index fbe9de278629..b1d812e902aa 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -2,6 +2,8 @@
#ifndef _LINUX_TTY_LDISC_H
#define _LINUX_TTY_LDISC_H
+struct tty_struct;
+
/*
* This structure defines the interface between the tty line discipline
* implementation and the tty routines. The following routines can be
@@ -126,6 +128,9 @@
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/atomic.h>
+#include <linux/list.h>
+#include <linux/lockdep.h>
+#include <linux/seq_file.h>
/*
* the semaphore definition
@@ -220,4 +225,16 @@ struct tty_ldisc {
#define MODULE_ALIAS_LDISC(ldisc) \
MODULE_ALIAS("tty-ldisc-" __stringify(ldisc))
+extern const struct seq_operations tty_ldiscs_seq_ops;
+
+struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
+void tty_ldisc_deref(struct tty_ldisc *);
+struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
+
+void tty_ldisc_flush(struct tty_struct *tty);
+
+int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc);
+void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc);
+int tty_set_ldisc(struct tty_struct *tty, int disc);
+
#endif /* _LINUX_TTY_LDISC_H */
diff --git a/include/linux/tty_port.h b/include/linux/tty_port.h
new file mode 100644
index 000000000000..6e86e9e118b6
--- /dev/null
+++ b/include/linux/tty_port.h
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_TTY_PORT_H
+#define _LINUX_TTY_PORT_H
+
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/tty_buffer.h>
+#include <linux/wait.h>
+
+/*
+ * Port level information. Each device keeps its own port level information
+ * so provide a common structure for those ports wanting to use common support
+ * routines.
+ *
+ * The tty port has a different lifetime to the tty so must be kept apart.
+ * In addition be careful as tty -> port mappings are valid for the life
+ * of the tty object but in many cases port -> tty mappings are valid only
+ * until a hangup so don't use the wrong path.
+ */
+
+struct attribute_group;
+struct tty_driver;
+struct tty_port;
+struct tty_struct;
+
+struct tty_port_operations {
+ /* Return 1 if the carrier is raised */
+ int (*carrier_raised)(struct tty_port *port);
+ /* Control the DTR line */
+ void (*dtr_rts)(struct tty_port *port, int raise);
+ /* Called when the last close completes or a hangup finishes
+ IFF the port was initialized. Do not use to free resources. Called
+ under the port mutex to serialize against activate/shutdowns */
+ void (*shutdown)(struct tty_port *port);
+ /* Called under the port mutex from tty_port_open, serialized using
+ the port mutex */
+ /* FIXME: long term getting the tty argument *out* of this would be
+ good for consoles */
+ int (*activate)(struct tty_port *port, struct tty_struct *tty);
+ /* Called on the final put of a port */
+ void (*destruct)(struct tty_port *port);
+};
+
+struct tty_port_client_operations {
+ int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t);
+ void (*write_wakeup)(struct tty_port *port);
+};
+
+extern const struct tty_port_client_operations tty_port_default_client_ops;
+
+struct tty_port {
+ struct tty_bufhead buf; /* Locked internally */
+ struct tty_struct *tty; /* Back pointer */
+ struct tty_struct *itty; /* internal back ptr */
+ const struct tty_port_operations *ops; /* Port operations */
+ const struct tty_port_client_operations *client_ops; /* Port client operations */
+ spinlock_t lock; /* Lock protecting tty field */
+ int blocked_open; /* Waiting to open */
+ int count; /* Usage count */
+ wait_queue_head_t open_wait; /* Open waiters */
+ wait_queue_head_t delta_msr_wait; /* Modem status change */
+ unsigned long flags; /* User TTY flags ASYNC_ */
+ unsigned long iflags; /* Internal flags TTY_PORT_ */
+ unsigned char console:1; /* port is a console */
+ struct mutex mutex; /* Locking */
+ struct mutex buf_mutex; /* Buffer alloc lock */
+ unsigned char *xmit_buf; /* Optional buffer */
+ unsigned int close_delay; /* Close port delay */
+ unsigned int closing_wait; /* Delay for output */
+ int drain_delay; /* Set to zero if no pure time
+ based drain is needed else
+ set to size of fifo */
+ struct kref kref; /* Ref counter */
+ void *client_data;
+};
+
+/* tty_port::iflags bits -- use atomic bit ops */
+#define TTY_PORT_INITIALIZED 0 /* device is initialized */
+#define TTY_PORT_SUSPENDED 1 /* device is suspended */
+#define TTY_PORT_ACTIVE 2 /* device is open */
+
+/*
+ * uart drivers: use the uart_port::status field and the UPSTAT_* defines
+ * for s/w-based flow control steering and carrier detection status
+ */
+#define TTY_PORT_CTS_FLOW 3 /* h/w flow control enabled */
+#define TTY_PORT_CHECK_CD 4 /* carrier detect enabled */
+#define TTY_PORT_KOPENED 5 /* device exclusively opened by
+ kernel */
+
+void tty_port_init(struct tty_port *port);
+void tty_port_link_device(struct tty_port *port, struct tty_driver *driver,
+ unsigned index);
+struct device *tty_port_register_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device);
+struct device *tty_port_register_device_attr(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device, void *drvdata,
+ const struct attribute_group **attr_grp);
+struct device *tty_port_register_device_serdev(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device);
+struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device, void *drvdata,
+ const struct attribute_group **attr_grp);
+void tty_port_unregister_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index);
+int tty_port_alloc_xmit_buf(struct tty_port *port);
+void tty_port_free_xmit_buf(struct tty_port *port);
+void tty_port_destroy(struct tty_port *port);
+void tty_port_put(struct tty_port *port);
+
+static inline struct tty_port *tty_port_get(struct tty_port *port)
+{
+ if (port && kref_get_unless_zero(&port->kref))
+ return port;
+ return NULL;
+}
+
+/* If the cts flow control is enabled, return true. */
+static inline bool tty_port_cts_enabled(const struct tty_port *port)
+{
+ return test_bit(TTY_PORT_CTS_FLOW, &port->iflags);
+}
+
+static inline void tty_port_set_cts_flow(struct tty_port *port, bool val)
+{
+ assign_bit(TTY_PORT_CTS_FLOW, &port->iflags, val);
+}
+
+static inline bool tty_port_active(const struct tty_port *port)
+{
+ return test_bit(TTY_PORT_ACTIVE, &port->iflags);
+}
+
+static inline void tty_port_set_active(struct tty_port *port, bool val)
+{
+ assign_bit(TTY_PORT_ACTIVE, &port->iflags, val);
+}
+
+static inline bool tty_port_check_carrier(const struct tty_port *port)
+{
+ return test_bit(TTY_PORT_CHECK_CD, &port->iflags);
+}
+
+static inline void tty_port_set_check_carrier(struct tty_port *port, bool val)
+{
+ assign_bit(TTY_PORT_CHECK_CD, &port->iflags, val);
+}
+
+static inline bool tty_port_suspended(const struct tty_port *port)
+{
+ return test_bit(TTY_PORT_SUSPENDED, &port->iflags);
+}
+
+static inline void tty_port_set_suspended(struct tty_port *port, bool val)
+{
+ assign_bit(TTY_PORT_SUSPENDED, &port->iflags, val);
+}
+
+static inline bool tty_port_initialized(const struct tty_port *port)
+{
+ return test_bit(TTY_PORT_INITIALIZED, &port->iflags);
+}
+
+static inline void tty_port_set_initialized(struct tty_port *port, bool val)
+{
+ assign_bit(TTY_PORT_INITIALIZED, &port->iflags, val);
+}
+
+static inline bool tty_port_kopened(const struct tty_port *port)
+{
+ return test_bit(TTY_PORT_KOPENED, &port->iflags);
+}
+
+static inline void tty_port_set_kopened(struct tty_port *port, bool val)
+{
+ assign_bit(TTY_PORT_KOPENED, &port->iflags, val);
+}
+
+struct tty_struct *tty_port_tty_get(struct tty_port *port);
+void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
+int tty_port_carrier_raised(struct tty_port *port);
+void tty_port_raise_dtr_rts(struct tty_port *port);
+void tty_port_lower_dtr_rts(struct tty_port *port);
+void tty_port_hangup(struct tty_port *port);
+void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
+void tty_port_tty_wakeup(struct tty_port *port);
+int tty_port_block_til_ready(struct tty_port *port, struct tty_struct *tty,
+ struct file *filp);
+int tty_port_close_start(struct tty_port *port, struct tty_struct *tty,
+ struct file *filp);
+void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
+void tty_port_close(struct tty_port *port, struct tty_struct *tty,
+ struct file *filp);
+int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+ struct tty_struct *tty);
+int tty_port_open(struct tty_port *port, struct tty_struct *tty,
+ struct file *filp);
+
+static inline int tty_port_users(struct tty_port *port)
+{
+ return port->count + port->blocked_open;
+}
+
+#endif
diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h
index ead8c9a47c6a..8fc2abd7aecb 100644
--- a/include/linux/usb/audio-v2.h
+++ b/include/linux/usb/audio-v2.h
@@ -156,6 +156,20 @@ struct uac2_feature_unit_descriptor {
__u8 bmaControls[]; /* variable length */
} __attribute__((packed));
+#define UAC2_DT_FEATURE_UNIT_SIZE(ch) (6 + ((ch) + 1) * 4)
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_UAC2_FEATURE_UNIT_DESCRIPTOR(ch) \
+struct uac2_feature_unit_descriptor_##ch { \
+ __u8 bLength; \
+ __u8 bDescriptorType; \
+ __u8 bDescriptorSubtype; \
+ __u8 bUnitID; \
+ __u8 bSourceID; \
+ __le32 bmaControls[ch + 1]; \
+ __u8 iFeature; \
+} __packed
+
/* 4.7.2.10 Effect Unit Descriptor */
struct uac2_effect_unit_descriptor {
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
index 78e006355557..c892c5bc6638 100644
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -45,6 +45,7 @@ struct ehci_caps {
#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */
#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */
#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */
+#define HCS_N_PORTS_MAX 15 /* N_PORTS valid 0x1-0xF */
u32 hcc_params; /* HCCPARAMS - offset 0x8 */
/* EHCI 1.1 addendum */
@@ -126,8 +127,9 @@ struct ehci_regs {
u32 configured_flag;
#define FLAG_CF (1<<0) /* true: we'll support "high speed" */
- /* PORTSC: offset 0x44 */
- u32 port_status[0]; /* up to N_PORTS */
+ union {
+ /* PORTSC: offset 0x44 */
+ u32 port_status[HCS_N_PORTS_MAX]; /* up to N_PORTS */
/* EHCI 1.1 addendum */
#define PORTSC_SUSPEND_STS_ACK 0
#define PORTSC_SUSPEND_STS_NYET 1
@@ -164,28 +166,35 @@ struct ehci_regs {
#define PORT_CSC (1<<1) /* connect status change */
#define PORT_CONNECT (1<<0) /* device connected */
#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
-
- u32 reserved3[9];
-
- /* USBMODE: offset 0x68 */
- u32 usbmode; /* USB Device mode */
+ struct {
+ u32 reserved3[9];
+ /* USBMODE: offset 0x68 */
+ u32 usbmode; /* USB Device mode */
+ };
#define USBMODE_SDIS (1<<3) /* Stream disable */
#define USBMODE_BE (1<<2) /* BE/LE endianness select */
#define USBMODE_CM_HC (3<<0) /* host controller mode */
#define USBMODE_CM_IDLE (0<<0) /* idle state */
-
- u32 reserved4[6];
+ };
/* Moorestown has some non-standard registers, partially due to the fact that
* its EHCI controller has both TT and LPM support. HOSTPCx are extensions to
* PORTSCx
*/
- /* HOSTPC: offset 0x84 */
- u32 hostpc[0]; /* HOSTPC extension */
+ union {
+ struct {
+ u32 reserved4;
+ /* HOSTPC: offset 0x84 */
+ u32 hostpc[HCS_N_PORTS_MAX];
#define HOSTPC_PHCD (1<<22) /* Phy clock disable */
#define HOSTPC_PSPD (3<<25) /* Port speed detection */
+ };
+
+ /* Broadcom-proprietary USB_EHCI_INSNREG00 @ 0x80 */
+ u32 brcm_insnreg[4];
+ };
- u32 reserved5[17];
+ u32 reserved5[2];
/* USBMODE_EX: offset 0xc8 */
u32 usbmode_ex; /* USB Device mode extension */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 75c7538e350a..10fe57cf40be 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -329,6 +329,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+ int (*check_config)(struct usb_gadget *gadget);
};
/**
@@ -491,7 +492,7 @@ extern char *usb_get_gadget_udc_name(void);
*/
static inline size_t usb_ep_align(struct usb_ep *ep, size_t len)
{
- int max_packet_size = (size_t)usb_endpoint_maxp(ep->desc) & 0x7ff;
+ int max_packet_size = (size_t)usb_endpoint_maxp(ep->desc);
return round_up(len, max_packet_size);
}
@@ -608,6 +609,7 @@ int usb_gadget_connect(struct usb_gadget *gadget);
int usb_gadget_disconnect(struct usb_gadget *gadget);
int usb_gadget_deactivate(struct usb_gadget *gadget);
int usb_gadget_activate(struct usb_gadget *gadget);
+int usb_gadget_check_config(struct usb_gadget *gadget);
#else
static inline int usb_gadget_frame_number(struct usb_gadget *gadget)
{ return 0; }
@@ -631,6 +633,8 @@ static inline int usb_gadget_deactivate(struct usb_gadget *gadget)
{ return 0; }
static inline int usb_gadget_activate(struct usb_gadget *gadget)
{ return 0; }
+static inline int usb_gadget_check_config(struct usb_gadget *gadget)
+{ return 0; }
#endif /* CONFIG_USB_GADGET */
/*-------------------------------------------------------------------------*/
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 7ceeecbb9e02..6475f880be37 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -128,5 +128,6 @@ enum usb_dr_mode {
* and returns the corresponding enum usb_dr_mode
*/
extern enum usb_dr_mode usb_get_dr_mode(struct device *dev);
+extern enum usb_dr_mode usb_get_role_switch_default_mode(struct device *dev);
#endif /* __LINUX_USB_OTG_H */
diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h
index 331d2ccf0bcc..33cea484d1ad 100644
--- a/include/linux/userfaultfd_k.h
+++ b/include/linux/userfaultfd_k.h
@@ -60,16 +60,16 @@ extern int mfill_atomic_install_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd,
extern ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start,
unsigned long src_start, unsigned long len,
- bool *mmap_changing, __u64 mode);
+ atomic_t *mmap_changing, __u64 mode);
extern ssize_t mfill_zeropage(struct mm_struct *dst_mm,
unsigned long dst_start,
unsigned long len,
- bool *mmap_changing);
+ atomic_t *mmap_changing);
extern ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long dst_start,
- unsigned long len, bool *mmap_changing);
+ unsigned long len, atomic_t *mmap_changing);
extern int mwriteprotect_range(struct mm_struct *dst_mm,
unsigned long start, unsigned long len,
- bool enable_wp, bool *mmap_changing);
+ bool enable_wp, atomic_t *mmap_changing);
/* mm helpers */
static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *vma,
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index a2c5b30e1763..b53a9557884a 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -15,13 +15,28 @@
#include <linux/poll.h>
#include <uapi/linux/vfio.h>
+/*
+ * VFIO devices can be placed in a set, this allows all devices to share this
+ * structure and the VFIO core will provide a lock that is held around
+ * open_device()/close_device() for all devices in the set.
+ */
+struct vfio_device_set {
+ void *set_id;
+ struct mutex lock;
+ struct list_head device_list;
+ unsigned int device_count;
+};
+
struct vfio_device {
struct device *dev;
const struct vfio_device_ops *ops;
struct vfio_group *group;
+ struct vfio_device_set *dev_set;
+ struct list_head dev_set_list;
/* Members below here are private, not for driver use */
refcount_t refcount;
+ unsigned int open_count;
struct completion comp;
struct list_head group_next;
};
@@ -29,8 +44,8 @@ struct vfio_device {
/**
* struct vfio_device_ops - VFIO bus driver device callbacks
*
- * @open: Called when userspace creates new file descriptor for device
- * @release: Called when userspace releases file descriptor for device
+ * @open_device: Called when the first file descriptor is opened for this device
+ * @close_device: Opposite of open_device
* @read: Perform read(2) on device file descriptor
* @write: Perform write(2) on device file descriptor
* @ioctl: Perform ioctl(2) on device file descriptor, supporting VFIO_DEVICE_*
@@ -43,8 +58,8 @@ struct vfio_device {
*/
struct vfio_device_ops {
char *name;
- int (*open)(struct vfio_device *vdev);
- void (*release)(struct vfio_device *vdev);
+ int (*open_device)(struct vfio_device *vdev);
+ void (*close_device)(struct vfio_device *vdev);
ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
size_t count, loff_t *ppos);
ssize_t (*write)(struct vfio_device *vdev, const char __user *buf,
@@ -61,11 +76,14 @@ extern void vfio_iommu_group_put(struct iommu_group *group, struct device *dev);
void vfio_init_group_dev(struct vfio_device *device, struct device *dev,
const struct vfio_device_ops *ops);
+void vfio_uninit_group_dev(struct vfio_device *device);
int vfio_register_group_dev(struct vfio_device *device);
void vfio_unregister_group_dev(struct vfio_device *device);
extern struct vfio_device *vfio_device_get_from_dev(struct device *dev);
extern void vfio_device_put(struct vfio_device *device);
+int vfio_assign_device_set(struct vfio_device *device, void *set_id);
+
/* events for the backend driver notify callback */
enum vfio_iommu_notify_type {
VFIO_IOMMU_CONTAINER_CLOSE = 0,
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/include/linux/vfio_pci_core.h
index 5a36272cecbf..ef9a44b6cf5d 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/include/linux/vfio_pci_core.h
@@ -10,13 +10,14 @@
#include <linux/mutex.h>
#include <linux/pci.h>
+#include <linux/vfio.h>
#include <linux/irqbypass.h>
#include <linux/types.h>
#include <linux/uuid.h>
#include <linux/notifier.h>
-#ifndef VFIO_PCI_PRIVATE_H
-#define VFIO_PCI_PRIVATE_H
+#ifndef VFIO_PCI_CORE_H
+#define VFIO_PCI_CORE_H
#define VFIO_PCI_OFFSET_SHIFT 40
@@ -33,7 +34,7 @@
struct vfio_pci_ioeventfd {
struct list_head next;
- struct vfio_pci_device *vdev;
+ struct vfio_pci_core_device *vdev;
struct virqfd *virqfd;
void __iomem *addr;
uint64_t data;
@@ -52,18 +53,18 @@ struct vfio_pci_irq_ctx {
struct irq_bypass_producer producer;
};
-struct vfio_pci_device;
+struct vfio_pci_core_device;
struct vfio_pci_region;
struct vfio_pci_regops {
- size_t (*rw)(struct vfio_pci_device *vdev, char __user *buf,
+ ssize_t (*rw)(struct vfio_pci_core_device *vdev, char __user *buf,
size_t count, loff_t *ppos, bool iswrite);
- void (*release)(struct vfio_pci_device *vdev,
+ void (*release)(struct vfio_pci_core_device *vdev,
struct vfio_pci_region *region);
- int (*mmap)(struct vfio_pci_device *vdev,
+ int (*mmap)(struct vfio_pci_core_device *vdev,
struct vfio_pci_region *region,
struct vm_area_struct *vma);
- int (*add_capability)(struct vfio_pci_device *vdev,
+ int (*add_capability)(struct vfio_pci_core_device *vdev,
struct vfio_pci_region *region,
struct vfio_info_cap *caps);
};
@@ -83,11 +84,6 @@ struct vfio_pci_dummy_resource {
struct list_head res_next;
};
-struct vfio_pci_reflck {
- struct kref kref;
- struct mutex lock;
-};
-
struct vfio_pci_vf_token {
struct mutex lock;
uuid_t uuid;
@@ -99,7 +95,7 @@ struct vfio_pci_mmap_vma {
struct list_head vma_next;
};
-struct vfio_pci_device {
+struct vfio_pci_core_device {
struct vfio_device vdev;
struct pci_dev *pdev;
void __iomem *barmap[PCI_STD_NUM_BARS];
@@ -130,8 +126,6 @@ struct vfio_pci_device {
bool needs_pm_restore;
struct pci_saved_state *pci_saved_state;
struct pci_saved_state *pm_save;
- struct vfio_pci_reflck *reflck;
- int refcnt;
int ioeventfds_nr;
struct eventfd_ctx *err_trigger;
struct eventfd_ctx *req_trigger;
@@ -151,65 +145,95 @@ struct vfio_pci_device {
#define is_irq_none(vdev) (!(is_intx(vdev) || is_msi(vdev) || is_msix(vdev)))
#define irq_is(vdev, type) (vdev->irq_type == type)
-extern void vfio_pci_intx_mask(struct vfio_pci_device *vdev);
-extern void vfio_pci_intx_unmask(struct vfio_pci_device *vdev);
+extern void vfio_pci_intx_mask(struct vfio_pci_core_device *vdev);
+extern void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev);
-extern int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev,
+extern int vfio_pci_set_irqs_ioctl(struct vfio_pci_core_device *vdev,
uint32_t flags, unsigned index,
unsigned start, unsigned count, void *data);
-extern ssize_t vfio_pci_config_rw(struct vfio_pci_device *vdev,
+extern ssize_t vfio_pci_config_rw(struct vfio_pci_core_device *vdev,
char __user *buf, size_t count,
loff_t *ppos, bool iswrite);
-extern ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
+extern ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
size_t count, loff_t *ppos, bool iswrite);
-extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
+extern ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
size_t count, loff_t *ppos, bool iswrite);
-extern long vfio_pci_ioeventfd(struct vfio_pci_device *vdev, loff_t offset,
+extern long vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
uint64_t data, int count, int fd);
extern int vfio_pci_init_perm_bits(void);
extern void vfio_pci_uninit_perm_bits(void);
-extern int vfio_config_init(struct vfio_pci_device *vdev);
-extern void vfio_config_free(struct vfio_pci_device *vdev);
+extern int vfio_config_init(struct vfio_pci_core_device *vdev);
+extern void vfio_config_free(struct vfio_pci_core_device *vdev);
-extern int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
+extern int vfio_pci_register_dev_region(struct vfio_pci_core_device *vdev,
unsigned int type, unsigned int subtype,
const struct vfio_pci_regops *ops,
size_t size, u32 flags, void *data);
-extern int vfio_pci_set_power_state(struct vfio_pci_device *vdev,
+extern int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev,
pci_power_t state);
-extern bool __vfio_pci_memory_enabled(struct vfio_pci_device *vdev);
-extern void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_device
+extern bool __vfio_pci_memory_enabled(struct vfio_pci_core_device *vdev);
+extern void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device
*vdev);
-extern u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_device *vdev);
-extern void vfio_pci_memory_unlock_and_restore(struct vfio_pci_device *vdev,
+extern u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_core_device *vdev);
+extern void vfio_pci_memory_unlock_and_restore(struct vfio_pci_core_device *vdev,
u16 cmd);
#ifdef CONFIG_VFIO_PCI_IGD
-extern int vfio_pci_igd_init(struct vfio_pci_device *vdev);
+extern int vfio_pci_igd_init(struct vfio_pci_core_device *vdev);
#else
-static inline int vfio_pci_igd_init(struct vfio_pci_device *vdev)
+static inline int vfio_pci_igd_init(struct vfio_pci_core_device *vdev)
{
return -ENODEV;
}
#endif
#ifdef CONFIG_S390
-extern int vfio_pci_info_zdev_add_caps(struct vfio_pci_device *vdev,
+extern int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
struct vfio_info_cap *caps);
#else
-static inline int vfio_pci_info_zdev_add_caps(struct vfio_pci_device *vdev,
+static inline int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
struct vfio_info_cap *caps)
{
return -ENODEV;
}
#endif
-#endif /* VFIO_PCI_PRIVATE_H */
+/* Will be exported for vfio pci drivers usage */
+void vfio_pci_core_set_params(bool nointxmask, bool is_disable_vga,
+ bool is_disable_idle_d3);
+void vfio_pci_core_close_device(struct vfio_device *core_vdev);
+void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
+ struct pci_dev *pdev,
+ const struct vfio_device_ops *vfio_pci_ops);
+int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev);
+void vfio_pci_core_uninit_device(struct vfio_pci_core_device *vdev);
+void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev);
+int vfio_pci_core_sriov_configure(struct pci_dev *pdev, int nr_virtfn);
+extern const struct pci_error_handlers vfio_pci_core_err_handlers;
+long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
+ unsigned long arg);
+ssize_t vfio_pci_core_read(struct vfio_device *core_vdev, char __user *buf,
+ size_t count, loff_t *ppos);
+ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *buf,
+ size_t count, loff_t *ppos);
+int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma);
+void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count);
+int vfio_pci_core_match(struct vfio_device *core_vdev, char *buf);
+int vfio_pci_core_enable(struct vfio_pci_core_device *vdev);
+void vfio_pci_core_disable(struct vfio_pci_core_device *vdev);
+void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev);
+
+static inline bool vfio_pci_is_vga(struct pci_dev *pdev)
+{
+ return (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
+}
+
+#endif /* VFIO_PCI_CORE_H */
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
index dc6ddce92066..b4b9137f9792 100644
--- a/include/linux/vgaarb.h
+++ b/include/linux/vgaarb.h
@@ -33,6 +33,8 @@
#include <video/vga.h>
+struct pci_dev;
+
/* Legacy VGA regions */
#define VGA_RSRC_NONE 0x00
#define VGA_RSRC_LEGACY_IO 0x01
@@ -42,42 +44,45 @@
#define VGA_RSRC_NORMAL_IO 0x04
#define VGA_RSRC_NORMAL_MEM 0x08
-/* Passing that instead of a pci_dev to use the system "default"
- * device, that is the one used by vgacon. Archs will probably
- * have to provide their own vga_default_device();
- */
-#define VGA_DEFAULT_DEVICE (NULL)
-
-struct pci_dev;
-
-/* For use by clients */
-
-/**
- * vga_set_legacy_decoding
- *
- * @pdev: pci device of the VGA card
- * @decodes: bit mask of what legacy regions the card decodes
- *
- * Indicates to the arbiter if the card decodes legacy VGA IOs,
- * legacy VGA Memory, both, or none. All cards default to both,
- * the card driver (fbdev for example) should tell the arbiter
- * if it has disabled legacy decoding, so the card can be left
- * out of the arbitration process (and can be safe to take
- * interrupts at any time.
- */
-#if defined(CONFIG_VGA_ARB)
-extern void vga_set_legacy_decoding(struct pci_dev *pdev,
- unsigned int decodes);
-#else
+#ifdef CONFIG_VGA_ARB
+void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes);
+int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible);
+void vga_put(struct pci_dev *pdev, unsigned int rsrc);
+struct pci_dev *vga_default_device(void);
+void vga_set_default_device(struct pci_dev *pdev);
+int vga_remove_vgacon(struct pci_dev *pdev);
+int vga_client_register(struct pci_dev *pdev,
+ unsigned int (*set_decode)(struct pci_dev *pdev, bool state));
+#else /* CONFIG_VGA_ARB */
static inline void vga_set_legacy_decoding(struct pci_dev *pdev,
- unsigned int decodes) { };
-#endif
-
-#if defined(CONFIG_VGA_ARB)
-extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible);
-#else
-static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) { return 0; }
-#endif
+ unsigned int decodes)
+{
+};
+static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc,
+ int interruptible)
+{
+ return 0;
+}
+static inline void vga_put(struct pci_dev *pdev, unsigned int rsrc)
+{
+}
+static inline struct pci_dev *vga_default_device(void)
+{
+ return NULL;
+}
+static inline void vga_set_default_device(struct pci_dev *pdev)
+{
+}
+static inline int vga_remove_vgacon(struct pci_dev *pdev)
+{
+ return 0;
+}
+static inline int vga_client_register(struct pci_dev *pdev,
+ unsigned int (*set_decode)(struct pci_dev *pdev, bool state))
+{
+ return 0;
+}
+#endif /* CONFIG_VGA_ARB */
/**
* vga_get_interruptible
@@ -109,48 +114,9 @@ static inline int vga_get_uninterruptible(struct pci_dev *pdev,
return vga_get(pdev, rsrc, 0);
}
-#if defined(CONFIG_VGA_ARB)
-extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
-#else
-static inline void vga_put(struct pci_dev *pdev, unsigned int rsrc)
+static inline void vga_client_unregister(struct pci_dev *pdev)
{
+ vga_client_register(pdev, NULL);
}
-#endif
-
-
-#ifdef CONFIG_VGA_ARB
-extern struct pci_dev *vga_default_device(void);
-extern void vga_set_default_device(struct pci_dev *pdev);
-extern int vga_remove_vgacon(struct pci_dev *pdev);
-#else
-static inline struct pci_dev *vga_default_device(void) { return NULL; }
-static inline void vga_set_default_device(struct pci_dev *pdev) { }
-static inline int vga_remove_vgacon(struct pci_dev *pdev) { return 0; }
-#endif
-
-/*
- * Architectures should define this if they have several
- * independent PCI domains that can afford concurrent VGA
- * decoding
- */
-#ifndef __ARCH_HAS_VGA_CONFLICT
-static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2)
-{
- return 1;
-}
-#endif
-
-#if defined(CONFIG_VGA_ARB)
-int vga_client_register(struct pci_dev *pdev, void *cookie,
- void (*irq_set_state)(void *cookie, bool state),
- unsigned int (*set_vga_decode)(void *cookie, bool state));
-#else
-static inline int vga_client_register(struct pci_dev *pdev, void *cookie,
- void (*irq_set_state)(void *cookie, bool state),
- unsigned int (*set_vga_decode)(void *cookie, bool state))
-{
- return 0;
-}
-#endif
#endif /* LINUX_VGA_H */
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index ae0dd1948c2b..a185cc75ff52 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -33,6 +33,8 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
PGREUSE,
PGSTEAL_KSWAPD,
PGSTEAL_DIRECT,
+ PGDEMOTE_KSWAPD,
+ PGDEMOTE_DIRECT,
PGSCAN_KSWAPD,
PGSCAN_DIRECT,
PGSCAN_DIRECT_THROTTLE,
diff --git a/include/linux/vmpressure.h b/include/linux/vmpressure.h
index 6d28bc433c1c..6a2f51ebbfd3 100644
--- a/include/linux/vmpressure.h
+++ b/include/linux/vmpressure.h
@@ -37,7 +37,7 @@ extern void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio);
extern void vmpressure_init(struct vmpressure *vmpr);
extern void vmpressure_cleanup(struct vmpressure *vmpr);
extern struct vmpressure *memcg_to_vmpressure(struct mem_cgroup *memcg);
-extern struct cgroup_subsys_state *vmpressure_to_css(struct vmpressure *vmpr);
+extern struct mem_cgroup *vmpressure_to_memcg(struct vmpressure *vmpr);
extern int vmpressure_register_event(struct mem_cgroup *memcg,
struct eventfd_ctx *eventfd,
const char *args);
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 0da94a6dee15..b5ab452fca5b 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -148,26 +148,26 @@ void hide_boot_cursor(bool hide);
/* keyboard provided interfaces */
int vt_do_diacrit(unsigned int cmd, void __user *up, int eperm);
-int vt_do_kdskbmode(int console, unsigned int arg);
-int vt_do_kdskbmeta(int console, unsigned int arg);
+int vt_do_kdskbmode(unsigned int console, unsigned int arg);
+int vt_do_kdskbmeta(unsigned int console, unsigned int arg);
int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
int perm);
int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
- int console);
+ unsigned int console);
int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm);
-int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm);
-int vt_do_kdgkbmode(int console);
-int vt_do_kdgkbmeta(int console);
-void vt_reset_unicode(int console);
+int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm);
+int vt_do_kdgkbmode(unsigned int console);
+int vt_do_kdgkbmeta(unsigned int console);
+void vt_reset_unicode(unsigned int console);
int vt_get_shift_state(void);
-void vt_reset_keyboard(int console);
-int vt_get_leds(int console, int flag);
-int vt_get_kbd_mode_bit(int console, int bit);
-void vt_set_kbd_mode_bit(int console, int bit);
-void vt_clr_kbd_mode_bit(int console, int bit);
-void vt_set_led_state(int console, int leds);
-void vt_kbd_con_start(int console);
-void vt_kbd_con_stop(int console);
+void vt_reset_keyboard(unsigned int console);
+int vt_get_leds(unsigned int console, int flag);
+int vt_get_kbd_mode_bit(unsigned int console, int bit);
+void vt_set_kbd_mode_bit(unsigned int console, int bit);
+void vt_clr_kbd_mode_bit(unsigned int console, int bit);
+void vt_set_led_state(unsigned int console, int leds);
+void vt_kbd_con_start(unsigned int console);
+void vt_kbd_con_stop(unsigned int console);
void vc_scrolldelta_helper(struct vc_data *c, int lines,
unsigned int rolled_over, void *_base, unsigned int size);
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index 9b19e6bb68b5..99660197a36c 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -107,6 +107,7 @@ struct watchdog_device {
unsigned int max_hw_heartbeat_ms;
struct notifier_block reboot_nb;
struct notifier_block restart_nb;
+ struct notifier_block pm_nb;
void *driver_data;
struct watchdog_core_data *wd_data;
unsigned long status;
@@ -116,6 +117,7 @@ struct watchdog_device {
#define WDOG_STOP_ON_REBOOT 2 /* Should be stopped on reboot */
#define WDOG_HW_RUNNING 3 /* True if HW watchdog running */
#define WDOG_STOP_ON_UNREGISTER 4 /* Should be stopped on unregister */
+#define WDOG_NO_PING_ON_SUSPEND 5 /* Ping worker should be stopped on suspend */
struct list_head deferred;
};
@@ -156,6 +158,12 @@ static inline void watchdog_stop_on_unregister(struct watchdog_device *wdd)
set_bit(WDOG_STOP_ON_UNREGISTER, &wdd->status);
}
+/* Use the following function to stop the wdog ping worker when suspending */
+static inline void watchdog_stop_ping_on_suspend(struct watchdog_device *wdd)
+{
+ set_bit(WDOG_NO_PING_ON_SUSPEND, &wdd->status);
+}
+
/* Use the following function to check if a timeout value is invalid */
static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
{
@@ -209,6 +217,8 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
unsigned int timeout_parm, struct device *dev);
extern int watchdog_register_device(struct watchdog_device *);
extern void watchdog_unregister_device(struct watchdog_device *);
+int watchdog_dev_suspend(struct watchdog_device *wdd);
+int watchdog_dev_resume(struct watchdog_device *wdd);
int watchdog_set_last_hw_keepalive(struct watchdog_device *, unsigned int);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 270677dc4f36..d1f65adf6a26 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -218,7 +218,7 @@ void wbc_attach_and_unlock_inode(struct writeback_control *wbc,
void wbc_detach_inode(struct writeback_control *wbc);
void wbc_account_cgroup_owner(struct writeback_control *wbc, struct page *page,
size_t bytes);
-int cgroup_writeback_by_id(u64 bdi_id, int memcg_id, unsigned long nr_pages,
+int cgroup_writeback_by_id(u64 bdi_id, int memcg_id,
enum wb_reason reason, struct wb_completion *done);
void cgroup_writeback_umount(void);
bool cleanup_offline_cgwb(struct bdi_writeback *wb);
@@ -374,7 +374,7 @@ int dirty_writeback_centisecs_handler(struct ctl_table *table, int write,
void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty);
unsigned long wb_calc_thresh(struct bdi_writeback *wb, unsigned long thresh);
-void wb_update_bandwidth(struct bdi_writeback *wb, unsigned long start_time);
+void wb_update_bandwidth(struct bdi_writeback *wb);
void balance_dirty_pages_ratelimited(struct address_space *mapping);
bool wb_over_bg_thresh(struct bdi_writeback *wb);
diff --git a/include/linux/zorro.h b/include/linux/zorro.h
index e2e4de188d84..db7416ed6057 100644
--- a/include/linux/zorro.h
+++ b/include/linux/zorro.h
@@ -29,7 +29,6 @@
struct zorro_dev {
struct ExpansionRom rom;
zorro_id id;
- struct zorro_driver *driver; /* which driver has allocated this device */
struct device dev; /* Generic device interface */
u16 slotaddr;
u16 slotsize;
diff --git a/include/media/dvb-usb-ids.h b/include/media/dvb-usb-ids.h
index d37cb74b769c..b0a535d6893a 100644
--- a/include/media/dvb-usb-ids.h
+++ b/include/media/dvb-usb-ids.h
@@ -394,6 +394,8 @@
#define USB_PID_MYGICA_T230C 0xc689
#define USB_PID_MYGICA_T230C2 0xc68a
#define USB_PID_MYGICA_T230C_LITE 0xc699
+#define USB_PID_MYGICA_T230C2_LITE 0xc69a
+#define USB_PID_MYGICA_T230A 0x689a
#define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011
#define USB_PID_ELGATO_EYETV_DTT 0x0021
#define USB_PID_ELGATO_EYETV_DTT_2 0x003f
diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
index 53c0038c792b..781371bff2ad 100644
--- a/include/media/hevc-ctrls.h
+++ b/include/media/hevc-ctrls.h
@@ -196,10 +196,11 @@ struct v4l2_ctrl_hevc_slice_params {
__u8 pic_struct;
/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ __u32 slice_segment_addr;
__u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
__u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
- __u8 padding[5];
+ __u8 padding;
/* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
struct v4l2_hevc_pred_weight_table pred_weight_table;
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index a1019c4ab5e8..8c5b7978e1d9 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -151,7 +151,7 @@ struct lirc_fh {
* @tx_ir: transmit IR
* @s_idle: enable/disable hardware idle mode, upon which,
* device doesn't interrupt host until it sees IR pulses
- * @s_learning_mode: enable wide band receiver used for learning
+ * @s_wideband_receiver: enable wide band receiver used for learning
* @s_carrier_report: enable carrier reports
* @s_filter: set the scancode filter
* @s_wakeup_filter: set the wakeup scancode filter. If the mask is zero
@@ -218,7 +218,7 @@ struct rc_dev {
int (*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max);
int (*tx_ir)(struct rc_dev *dev, unsigned *txbuf, unsigned n);
void (*s_idle)(struct rc_dev *dev, bool enable);
- int (*s_learning_mode)(struct rc_dev *dev, int enable);
+ int (*s_wideband_receiver)(struct rc_dev *dev, int enable);
int (*s_carrier_report) (struct rc_dev *dev, int enable);
int (*s_filter)(struct rc_dev *dev,
struct rc_scancode_filter *filter);
@@ -313,6 +313,7 @@ struct ir_raw_event {
#define MS_TO_US(msec) ((msec) * 1000)
#define IR_MAX_DURATION MS_TO_US(500)
#define IR_DEFAULT_TIMEOUT MS_TO_US(125)
+#define IR_MAX_TIMEOUT LIRC_VALUE_MASK
void ir_raw_event_handle(struct rc_dev *dev);
int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev);
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 5b275a845c20..fa4901162663 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -129,11 +129,11 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
*
* This function initializes the notifier @asd_list. It must be called
* before adding a subdevice to a notifier, using one of:
- * @v4l2_async_notifier_add_fwnode_remote_subdev,
- * @v4l2_async_notifier_add_fwnode_subdev,
- * @v4l2_async_notifier_add_i2c_subdev,
- * @__v4l2_async_notifier_add_subdev or
- * @v4l2_async_notifier_parse_fwnode_endpoints.
+ * v4l2_async_notifier_add_fwnode_remote_subdev(),
+ * v4l2_async_notifier_add_fwnode_subdev(),
+ * v4l2_async_notifier_add_i2c_subdev(),
+ * __v4l2_async_notifier_add_subdev() or
+ * v4l2_async_notifier_parse_fwnode_endpoints().
*/
void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
@@ -145,9 +145,9 @@ void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
* @asd: pointer to &struct v4l2_async_subdev
*
* \warning: Drivers should avoid using this function and instead use one of:
- * @v4l2_async_notifier_add_fwnode_subdev,
- * @v4l2_async_notifier_add_fwnode_remote_subdev or
- * @v4l2_async_notifier_add_i2c_subdev.
+ * v4l2_async_notifier_add_fwnode_subdev(),
+ * v4l2_async_notifier_add_fwnode_remote_subdev() or
+ * v4l2_async_notifier_add_i2c_subdev().
*
* Call this function before registering a notifier to link the provided @asd to
* the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
@@ -200,7 +200,7 @@ __v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif
* function also gets a reference of the fwnode which is released later at
* notifier cleanup time.
*
- * This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the
+ * This is just like v4l2_async_notifier_add_fwnode_subdev(), but with the
* exception that the fwnode refers to a local endpoint, not the remote one.
*/
#define v4l2_async_notifier_add_fwnode_remote_subdev(notifier, ep, type) \
@@ -265,13 +265,13 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
* sub-devices allocated for the purposes of the notifier but not the notifier
* itself. The user is responsible for calling this function to clean up the
* notifier after calling
- * @v4l2_async_notifier_add_fwnode_remote_subdev,
- * @v4l2_async_notifier_add_fwnode_subdev,
- * @v4l2_async_notifier_add_i2c_subdev,
- * @__v4l2_async_notifier_add_subdev or
- * @v4l2_async_notifier_parse_fwnode_endpoints.
+ * v4l2_async_notifier_add_fwnode_remote_subdev(),
+ * v4l2_async_notifier_add_fwnode_subdev(),
+ * v4l2_async_notifier_add_i2c_subdev(),
+ * __v4l2_async_notifier_add_subdev() or
+ * v4l2_async_notifier_parse_fwnode_endpoints().
*
- * There is no harm from calling v4l2_async_notifier_cleanup in other
+ * There is no harm from calling v4l2_async_notifier_cleanup() in other
* cases as long as its memory has been zeroed after it has been
* allocated.
*/
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 95f8bfd63273..95ec18c2f49c 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -355,6 +355,16 @@ struct v4l2_mbus_frame_desc {
};
/**
+ * enum v4l2_subdev_pre_streamon_flags - Flags for pre_streamon subdev core op
+ *
+ * @V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP: Set the transmitter to either LP-11
+ * or LP-111 mode before call to s_stream().
+ */
+enum v4l2_subdev_pre_streamon_flags {
+ V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP = BIT(0),
+};
+
+/**
* struct v4l2_subdev_video_ops - Callbacks used when v4l device was opened
* in video mode.
*
@@ -409,6 +419,19 @@ struct v4l2_mbus_frame_desc {
* @s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev
* can adjust @size to a lower value and must not write more data to the
* buffer starting at @data than the original value of @size.
+ *
+ * @pre_streamon: May be called before streaming is actually started, to help
+ * initialising the bus. Current usage is to set a CSI-2 transmitter to
+ * LP-11 or LP-111 mode before streaming. See &enum
+ * v4l2_subdev_pre_streamon_flags.
+ *
+ * pre_streamon shall return error if it cannot perform the operation as
+ * indicated by the flags argument. In particular, -EACCES indicates lack
+ * of support for the operation. The caller shall call post_streamoff for
+ * each successful call of pre_streamon.
+ *
+ * @post_streamoff: Called after streaming is stopped, but if and only if
+ * pre_streamon was called earlier.
*/
struct v4l2_subdev_video_ops {
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
@@ -435,6 +458,8 @@ struct v4l2_subdev_video_ops {
struct v4l2_dv_timings *timings);
int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf,
unsigned int *size);
+ int (*pre_streamon)(struct v4l2_subdev *sd, u32 flags);
+ int (*post_streamoff)(struct v4l2_subdev *sd);
};
/**
@@ -871,7 +896,7 @@ struct v4l2_subdev_platform_data {
* @asd: Pointer to respective &struct v4l2_async_subdev.
* @notifier: Pointer to the managing notifier.
* @subdev_notifier: A sub-device notifier implicitly registered for the sub-
- * device using v4l2_device_register_sensor_subdev().
+ * device using v4l2_async_register_subdev_sensor().
* @pdata: common part of subdevice platform data
*
* Each instance of a subdev driver should create this struct, either
diff --git a/include/net/flow.h b/include/net/flow.h
index 6f5e70240071..58beb16a49b8 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -194,7 +194,7 @@ static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)
static inline struct flowi_common *flowi4_to_flowi_common(struct flowi4 *fl4)
{
- return &(flowi4_to_flowi(fl4)->u.__fl_common);
+ return &(fl4->__fl_common);
}
static inline struct flowi *flowi6_to_flowi(struct flowi6 *fl6)
@@ -204,7 +204,7 @@ static inline struct flowi *flowi6_to_flowi(struct flowi6 *fl6)
static inline struct flowi_common *flowi6_to_flowi_common(struct flowi6 *fl6)
{
- return &(flowi6_to_flowi(fl6)->u.__fl_common);
+ return &(fl6->__fl_common);
}
static inline struct flowi *flowidn_to_flowi(struct flowidn *fldn)
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index ba3c808a3789..3634d4cc7a56 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -366,20 +366,6 @@ struct ib_sa_mcmember_rec {
#define IB_DEFAULT_SERVICE_LEASE 0xFFFFFFFF
-struct ib_sa_service_rec {
- u64 id;
- union ib_gid gid;
- __be16 pkey;
- /* reserved */
- u32 lease;
- u8 key[16];
- u8 name[64];
- u8 data8[16];
- u16 data16[8];
- u32 data32[4];
- u64 data64[2];
-};
-
#define IB_SA_GUIDINFO_REC_LID IB_SA_COMP_MASK(0)
#define IB_SA_GUIDINFO_REC_BLOCK_NUM IB_SA_COMP_MASK(1)
#define IB_SA_GUIDINFO_REC_RES1 IB_SA_COMP_MASK(2)
@@ -430,16 +416,6 @@ int ib_sa_path_rec_get(struct ib_sa_client *client, struct ib_device *device,
void *context),
void *context, struct ib_sa_query **query);
-int ib_sa_service_rec_query(struct ib_sa_client *client,
- struct ib_device *device, u32 port_num, u8 method,
- struct ib_sa_service_rec *rec,
- ib_sa_comp_mask comp_mask, unsigned long timeout_ms,
- gfp_t gfp_mask,
- void (*callback)(int status,
- struct ib_sa_service_rec *resp,
- void *context),
- void *context, struct ib_sa_query **sa_query);
-
struct ib_sa_multicast {
struct ib_sa_mcmember_rec rec;
ib_sa_comp_mask comp_mask;
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index 676c57f5ca80..5ae9dff74dac 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -26,9 +26,7 @@ struct ib_umem {
u32 is_odp : 1;
u32 is_dmabuf : 1;
struct work_struct work;
- struct sg_table sg_head;
- int nmap;
- unsigned int sg_nents;
+ struct sg_append_table sgt_append;
};
struct ib_umem_dmabuf {
@@ -56,7 +54,7 @@ static inline int ib_umem_offset(struct ib_umem *umem)
static inline unsigned long ib_umem_dma_offset(struct ib_umem *umem,
unsigned long pgsz)
{
- return (sg_dma_address(umem->sg_head.sgl) + ib_umem_offset(umem)) &
+ return (sg_dma_address(umem->sgt_append.sgt.sgl) + ib_umem_offset(umem)) &
(pgsz - 1);
}
@@ -77,7 +75,8 @@ static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
struct ib_umem *umem,
unsigned long pgsz)
{
- __rdma_block_iter_start(biter, umem->sg_head.sgl, umem->nmap, pgsz);
+ __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
+ umem->sgt_append.sgt.nents, pgsz);
}
/**
@@ -128,7 +127,7 @@ static inline unsigned long ib_umem_find_best_pgoff(struct ib_umem *umem,
unsigned long pgsz_bitmap,
u64 pgoff_bitmask)
{
- struct scatterlist *sg = umem->sg_head.sgl;
+ struct scatterlist *sg = umem->sgt_append.sgt.sgl;
dma_addr_t dma_addr;
dma_addr = sg_dma_address(sg) + (umem->address & ~PAGE_MASK);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 371df1c80aeb..4b50d9a3018a 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2268,8 +2268,13 @@ struct iw_cm_conn_param;
!__same_type(((struct drv_struct *)NULL)->member, \
struct ib_struct)))
-#define rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, gfp) \
- ((struct ib_type *)kzalloc(ib_dev->ops.size_##ib_type, gfp))
+#define rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, gfp) \
+ ((struct ib_type *)rdma_zalloc_obj(ib_dev, ib_dev->ops.size_##ib_type, \
+ gfp, false))
+
+#define rdma_zalloc_drv_obj_numa(ib_dev, ib_type) \
+ ((struct ib_type *)rdma_zalloc_obj(ib_dev, ib_dev->ops.size_##ib_type, \
+ GFP_KERNEL, true))
#define rdma_zalloc_drv_obj(ib_dev, ib_type) \
rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, GFP_KERNEL)
@@ -2435,9 +2440,8 @@ struct ib_device_ops {
struct ib_udata *udata);
int (*query_srq)(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
int (*destroy_srq)(struct ib_srq *srq, struct ib_udata *udata);
- struct ib_qp *(*create_qp)(struct ib_pd *pd,
- struct ib_qp_init_attr *qp_init_attr,
- struct ib_udata *udata);
+ int (*create_qp)(struct ib_qp *qp, struct ib_qp_init_attr *qp_init_attr,
+ struct ib_udata *udata);
int (*modify_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_udata *udata);
int (*query_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
@@ -2635,11 +2639,18 @@ struct ib_device_ops {
int (*query_ucontext)(struct ib_ucontext *context,
struct uverbs_attr_bundle *attrs);
+ /*
+ * Provide NUMA node. This API exists for rdmavt/hfi1 only.
+ * Everyone else relies on Linux memory management model.
+ */
+ int (*get_numa_node)(struct ib_device *dev);
+
DECLARE_RDMA_OBJ_SIZE(ib_ah);
DECLARE_RDMA_OBJ_SIZE(ib_counters);
DECLARE_RDMA_OBJ_SIZE(ib_cq);
DECLARE_RDMA_OBJ_SIZE(ib_mw);
DECLARE_RDMA_OBJ_SIZE(ib_pd);
+ DECLARE_RDMA_OBJ_SIZE(ib_qp);
DECLARE_RDMA_OBJ_SIZE(ib_rwq_ind_table);
DECLARE_RDMA_OBJ_SIZE(ib_srq);
DECLARE_RDMA_OBJ_SIZE(ib_ucontext);
@@ -2746,6 +2757,15 @@ struct ib_device {
u32 lag_flags;
};
+static inline void *rdma_zalloc_obj(struct ib_device *dev, size_t size,
+ gfp_t gfp, bool is_numa_aware)
+{
+ if (is_numa_aware && dev->ops.get_numa_node)
+ return kzalloc_node(size, gfp, dev->ops.get_numa_node(dev));
+
+ return kzalloc(size, gfp);
+}
+
struct ib_client_nl_info;
struct ib_client {
const char *name;
@@ -3668,13 +3688,21 @@ static inline int ib_post_srq_recv(struct ib_srq *srq,
bad_recv_wr ? : &dummy);
}
-struct ib_qp *ib_create_named_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *qp_init_attr,
- const char *caller);
+struct ib_qp *ib_create_qp_kernel(struct ib_pd *pd,
+ struct ib_qp_init_attr *qp_init_attr,
+ const char *caller);
+/**
+ * ib_create_qp - Creates a kernel QP associated with the specific protection
+ * domain.
+ * @pd: The protection domain associated with the QP.
+ * @init_attr: A list of initial attributes required to create the
+ * QP. If QP creation succeeds, then the attributes are updated to
+ * the actual capabilities of the created QP.
+ */
static inline struct ib_qp *ib_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *init_attr)
{
- return ib_create_named_qp(pd, init_attr, KBUILD_MODNAME);
+ return ib_create_qp_kernel(pd, init_attr, KBUILD_MODNAME);
}
/**
@@ -4058,6 +4086,34 @@ static inline void ib_dma_unmap_sg_attrs(struct ib_device *dev,
}
/**
+ * ib_dma_map_sgtable_attrs - Map a scatter/gather table to DMA addresses
+ * @dev: The device for which the DMA addresses are to be created
+ * @sg: The sg_table object describing the buffer
+ * @direction: The direction of the DMA
+ * @attrs: Optional DMA attributes for the map operation
+ */
+static inline int ib_dma_map_sgtable_attrs(struct ib_device *dev,
+ struct sg_table *sgt,
+ enum dma_data_direction direction,
+ unsigned long dma_attrs)
+{
+ if (ib_uses_virt_dma(dev)) {
+ ib_dma_virt_map_sg(dev, sgt->sgl, sgt->orig_nents);
+ return 0;
+ }
+ return dma_map_sgtable(dev->dma_device, sgt, direction, dma_attrs);
+}
+
+static inline void ib_dma_unmap_sgtable_attrs(struct ib_device *dev,
+ struct sg_table *sgt,
+ enum dma_data_direction direction,
+ unsigned long dma_attrs)
+{
+ if (!ib_uses_virt_dma(dev))
+ dma_unmap_sgtable(dev->dma_device, sgt, direction, dma_attrs);
+}
+
+/**
* ib_dma_map_sg - Map a scatter/gather list to DMA addresses
* @dev: The device for which the DMA addresses are to be created
* @sg: The array of scatter/gather entries
diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h
index 8275954f5ce6..2e58d5e6ac0e 100644
--- a/include/rdma/rdmavt_qp.h
+++ b/include/rdma/rdmavt_qp.h
@@ -444,7 +444,7 @@ struct rvt_qp {
/*
* This sge list MUST be last. Do not add anything below here.
*/
- struct rvt_sge r_sg_list[] /* verified SGEs */
+ struct rvt_sge *r_sg_list /* verified SGEs */
____cacheline_aligned_in_smp;
};
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 779a59fe8676..eaf04c9a1dfc 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -111,9 +111,6 @@ struct scsi_cmnd {
reconnects. Probably == sector
size */
- struct request *request; /* The command we are
- working on */
-
unsigned char *sense_buffer;
/* obtained by REQUEST SENSE when
* CHECK CONDITION is received on original
@@ -142,10 +139,15 @@ struct scsi_cmnd {
int flags; /* Command flags */
unsigned long state; /* Command completion state */
- unsigned char tag; /* SCSI-II queued command tag */
unsigned int extra_len; /* length of alignment and padding */
};
+/* Variant of blk_mq_rq_from_pdu() that verifies the type of its argument. */
+static inline struct request *scsi_cmd_to_rq(struct scsi_cmnd *scmd)
+{
+ return blk_mq_rq_from_pdu(scmd);
+}
+
/*
* Return the driver private allocation behind the command.
* Only works if cmd_size is set in the host template.
@@ -158,7 +160,9 @@ static inline void *scsi_cmd_priv(struct scsi_cmnd *cmd)
/* make sure not to use it with passthrough commands */
static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
{
- return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
+ struct request *rq = scsi_cmd_to_rq(cmd);
+
+ return *(struct scsi_driver **)rq->rq_disk->private_data;
}
extern void scsi_finish_command(struct scsi_cmnd *cmd);
@@ -220,6 +224,25 @@ static inline int scsi_sg_copy_to_buffer(struct scsi_cmnd *cmd,
buf, buflen);
}
+static inline sector_t scsi_get_sector(struct scsi_cmnd *scmd)
+{
+ return blk_rq_pos(scsi_cmd_to_rq(scmd));
+}
+
+static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd)
+{
+ unsigned int shift = ilog2(scmd->device->sector_size) - SECTOR_SHIFT;
+
+ return blk_rq_pos(scsi_cmd_to_rq(scmd)) >> shift;
+}
+
+static inline unsigned int scsi_logical_block_count(struct scsi_cmnd *scmd)
+{
+ unsigned int shift = ilog2(scmd->device->sector_size) - SECTOR_SHIFT;
+
+ return blk_rq_bytes(scsi_cmd_to_rq(scmd)) >> shift;
+}
+
/*
* The operations below are hints that tell the controller driver how
* to handle I/Os with DIF or similar types of protection information.
@@ -282,9 +305,11 @@ static inline unsigned char scsi_get_prot_type(struct scsi_cmnd *scmd)
return scmd->prot_type;
}
-static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd)
+static inline u32 scsi_prot_ref_tag(struct scsi_cmnd *scmd)
{
- return blk_rq_pos(scmd->request);
+ struct request *rq = blk_mq_rq_from_pdu(scmd);
+
+ return t10_pi_ref_tag(rq);
}
static inline unsigned int scsi_prot_interval(struct scsi_cmnd *scmd)
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index ac6ab16abee7..09a17f6e93a7 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -10,6 +10,7 @@
#include <linux/atomic.h>
#include <linux/sbitmap.h>
+struct bsg_device;
struct device;
struct request_queue;
struct scsi_cmnd;
@@ -205,6 +206,7 @@ struct scsi_device {
unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */
unsigned rpm_autosuspend:1; /* Enable runtime autosuspend at device
* creation time */
+ unsigned ignore_media_change:1; /* Ignore MEDIA CHANGE on resume */
bool offline_already; /* Device offline message logged */
@@ -234,6 +236,10 @@ struct scsi_device {
size_t dma_drain_len;
void *dma_drain_buf;
+ unsigned int sg_timeout;
+ unsigned int sg_reserved_size;
+
+ struct bsg_device *bsg_dev;
unsigned char access_state;
struct mutex state_mutex;
enum scsi_device_state sdev_state;
@@ -265,13 +271,15 @@ sdev_prefix_printk(const char *, const struct scsi_device *, const char *,
__printf(3, 4) void
scmd_printk(const char *, const struct scsi_cmnd *, const char *, ...);
-#define scmd_dbg(scmd, fmt, a...) \
- do { \
- if ((scmd)->request->rq_disk) \
- sdev_dbg((scmd)->device, "[%s] " fmt, \
- (scmd)->request->rq_disk->disk_name, ##a);\
- else \
- sdev_dbg((scmd)->device, fmt, ##a); \
+#define scmd_dbg(scmd, fmt, a...) \
+ do { \
+ struct request *__rq = scsi_cmd_to_rq((scmd)); \
+ \
+ if (__rq->rq_disk) \
+ sdev_dbg((scmd)->device, "[%s] " fmt, \
+ __rq->rq_disk->disk_name, ##a); \
+ else \
+ sdev_dbg((scmd)->device, fmt, ##a); \
} while (0)
enum scsi_target_state {
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index 3fdb322d4c4b..5d14adae21c7 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -28,7 +28,8 @@
#define BLIST_LARGELUN ((__force blist_flags_t)(1ULL << 9))
/* override additional length field */
#define BLIST_INQUIRY_36 ((__force blist_flags_t)(1ULL << 10))
-#define __BLIST_UNUSED_11 ((__force blist_flags_t)(1ULL << 11))
+/* ignore MEDIA CHANGE unit attention after resuming from runtime suspend */
+#define BLIST_IGN_MEDIA_CHANGE ((__force blist_flags_t)(1ULL << 11))
/* do not do automatic start on add */
#define BLIST_NOSTARTONADD ((__force blist_flags_t)(1ULL << 12))
#define __BLIST_UNUSED_13 ((__force blist_flags_t)(1ULL << 13))
@@ -73,8 +74,7 @@
#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 | \
+#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_13 | \
__BLIST_UNUSED_14 | \
__BLIST_UNUSED_15 | \
__BLIST_UNUSED_16 | \
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index b465799f4d2d..d2cb9aeaf1f1 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -18,7 +18,9 @@
#ifdef __KERNEL__
+struct gendisk;
struct scsi_device;
+struct sg_io_hdr;
/*
* Structures used for scsi_ioctl et al.
@@ -43,8 +45,11 @@ typedef struct scsi_fctargaddress {
int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
int cmd, bool ndelay);
-extern int scsi_ioctl(struct scsi_device *, int, void __user *);
-extern int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg);
+int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
+ int cmd, void __user *arg);
+int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp);
+int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp);
+bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode);
#endif /* __KERNEL__ */
#endif /* _SCSI_IOCTL_H */
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
index b06f28c74908..9129b23e12bc 100644
--- a/include/scsi/scsi_request.h
+++ b/include/scsi/scsi_request.h
@@ -28,6 +28,4 @@ static inline void scsi_req_free_cmd(struct scsi_request *req)
kfree(req->cmd);
}
-void scsi_req_init(struct scsi_request *req);
-
#endif /* _SCSI_SCSI_REQUEST_H */
diff --git a/include/soc/at91/sama7-ddr.h b/include/soc/at91/sama7-ddr.h
new file mode 100644
index 000000000000..f6542584ca13
--- /dev/null
+++ b/include/soc/at91/sama7-ddr.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Microchip SAMA7 UDDR Controller and DDR3 PHY Controller registers offsets
+ * and bit definitions.
+ *
+ * Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudu Beznea <claudiu.beznea@microchip.com>
+ */
+
+#ifndef __SAMA7_DDR_H__
+#define __SAMA7_DDR_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+/* DDR3PHY */
+#define DDR3PHY_PIR (0x04) /* DDR3PHY PHY Initialization Register */
+#define DDR3PHY_PIR_DLLBYP (1 << 17) /* DLL Bypass */
+#define DDR3PHY_PIR_ITMSRST (1 << 4) /* Interface Timing Module Soft Reset */
+#define DDR3PHY_PIR_DLLLOCK (1 << 2) /* DLL Lock */
+#define DDR3PHY_PIR_DLLSRST (1 << 1) /* DLL Soft Rest */
+#define DDR3PHY_PIR_INIT (1 << 0) /* Initialization Trigger */
+
+#define DDR3PHY_PGCR (0x08) /* DDR3PHY PHY General Configuration Register */
+#define DDR3PHY_PGCR_CKDV1 (1 << 13) /* CK# Disable Value */
+#define DDR3PHY_PGCR_CKDV0 (1 << 12) /* CK Disable Value */
+
+#define DDR3PHY_PGSR (0x0C) /* DDR3PHY PHY General Status Register */
+#define DDR3PHY_PGSR_IDONE (1 << 0) /* Initialization Done */
+
+#define DDR3PHY_ACIOCR (0x24) /* DDR3PHY AC I/O Configuration Register */
+#define DDR3PHY_ACIOCR_CSPDD_CS0 (1 << 18) /* CS#[0] Power Down Driver */
+#define DDR3PHY_ACIOCR_CKPDD_CK0 (1 << 8) /* CK[0] Power Down Driver */
+#define DDR3PHY_ACIORC_ACPDD (1 << 3) /* AC Power Down Driver */
+
+#define DDR3PHY_DXCCR (0x28) /* DDR3PHY DATX8 Common Configuration Register */
+#define DDR3PHY_DXCCR_DXPDR (1 << 3) /* Data Power Down Receiver */
+
+#define DDR3PHY_DSGCR (0x2C) /* DDR3PHY DDR System General Configuration Register */
+#define DDR3PHY_DSGCR_ODTPDD_ODT0 (1 << 20) /* ODT[0] Power Down Driver */
+
+#define DDR3PHY_ZQ0SR0 (0x188) /* ZQ status register 0 */
+
+/* UDDRC */
+#define UDDRC_STAT (0x04) /* UDDRC Operating Mode Status Register */
+#define UDDRC_STAT_SELFREF_TYPE_DIS (0x0 << 4) /* SDRAM is not in Self-refresh */
+#define UDDRC_STAT_SELFREF_TYPE_PHY (0x1 << 4) /* SDRAM is in Self-refresh, which was caused by PHY Master Request */
+#define UDDRC_STAT_SELFREF_TYPE_SW (0x2 << 4) /* SDRAM is in Self-refresh, which was not caused solely under Automatic Self-refresh control */
+#define UDDRC_STAT_SELFREF_TYPE_AUTO (0x3 << 4) /* SDRAM is in Self-refresh, which was caused by Automatic Self-refresh only */
+#define UDDRC_STAT_SELFREF_TYPE_MSK (0x3 << 4) /* Self-refresh type mask */
+#define UDDRC_STAT_OPMODE_INIT (0x0 << 0) /* Init */
+#define UDDRC_STAT_OPMODE_NORMAL (0x1 << 0) /* Normal */
+#define UDDRC_STAT_OPMODE_PWRDOWN (0x2 << 0) /* Power-down */
+#define UDDRC_STAT_OPMODE_SELF_REFRESH (0x3 << 0) /* Self-refresh */
+#define UDDRC_STAT_OPMODE_MSK (0x7 << 0) /* Operating mode mask */
+
+#define UDDRC_PWRCTL (0x30) /* UDDRC Low Power Control Register */
+#define UDDRC_PWRCTRL_SELFREF_SW (1 << 5) /* Software self-refresh */
+
+#define UDDRC_DFIMISC (0x1B0) /* UDDRC DFI Miscellaneous Control Register */
+#define UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN (1 << 0) /* PHY initialization complete enable signal */
+
+#define UDDRC_SWCTRL (0x320) /* UDDRC Software Register Programming Control Enable */
+#define UDDRC_SWCTRL_SW_DONE (1 << 0) /* Enable quasi-dynamic register programming outside reset */
+
+#define UDDRC_SWSTAT (0x324) /* UDDRC Software Register Programming Control Status */
+#define UDDRC_SWSTAT_SW_DONE_ACK (1 << 0) /* Register programming done */
+
+#define UDDRC_PSTAT (0x3FC) /* UDDRC Port Status Register */
+#define UDDRC_PSTAT_ALL_PORTS (0x1F001F) /* Read + writes outstanding transactions on all ports */
+
+#define UDDRC_PCTRL_0 (0x490) /* UDDRC Port 0 Control Register */
+#define UDDRC_PCTRL_1 (0x540) /* UDDRC Port 1 Control Register */
+#define UDDRC_PCTRL_2 (0x5F0) /* UDDRC Port 2 Control Register */
+#define UDDRC_PCTRL_3 (0x6A0) /* UDDRC Port 3 Control Register */
+#define UDDRC_PCTRL_4 (0x750) /* UDDRC Port 4 Control Register */
+
+#endif /* CONFIG_SOC_SAMA7 */
+
+#endif /* __SAMA7_DDR_H__ */
diff --git a/include/soc/at91/sama7-sfrbu.h b/include/soc/at91/sama7-sfrbu.h
new file mode 100644
index 000000000000..76b740810d34
--- /dev/null
+++ b/include/soc/at91/sama7-sfrbu.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Microchip SAMA7 SFRBU registers offsets and bit definitions.
+ *
+ * Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudu Beznea <claudiu.beznea@microchip.com>
+ */
+
+#ifndef __SAMA7_SFRBU_H__
+#define __SAMA7_SFRBU_H__
+
+#ifdef CONFIG_SOC_SAMA7
+
+#define AT91_SFRBU_PSWBU (0x00) /* SFRBU Power Switch BU Control Register */
+#define AT91_SFRBU_PSWBU_PSWKEY (0x4BD20C << 8) /* Specific value mandatory to allow writing of other register bits */
+#define AT91_SFRBU_PSWBU_STATE (1 << 2) /* Power switch BU state */
+#define AT91_SFRBU_PSWBU_SOFTSWITCH (1 << 1) /* Power switch BU source selection */
+#define AT91_SFRBU_PSWBU_CTRL (1 << 0) /* Power switch BU control */
+
+#define AT91_SFRBU_25LDOCR (0x0C) /* SFRBU 2.5V LDO Control Register */
+#define AT91_SFRBU_25LDOCR_LDOANAKEY (0x3B6E18 << 8) /* Specific value mandatory to allow writing of other register bits. */
+#define AT91_SFRBU_25LDOCR_STATE (1 << 3) /* LDOANA Switch On/Off Control */
+#define AT91_SFRBU_25LDOCR_LP (1 << 2) /* LDOANA Low-Power Mode Control */
+#define AT91_SFRBU_PD_VALUE_MSK (0x3)
+#define AT91_SFRBU_25LDOCR_PD_VALUE(v) ((v) & AT91_SFRBU_PD_VALUE_MSK) /* LDOANA Pull-down value */
+
+#define AT91_FRBU_DDRPWR (0x10) /* SFRBU DDR Power Control Register */
+#define AT91_FRBU_DDRPWR_STATE (1 << 0) /* DDR Power Mode State */
+
+#endif /* CONFIG_SOC_SAMA7 */
+
+#endif /* __SAMA7_SFRBU_H__ */
+
diff --git a/include/soc/tegra/pm.h b/include/soc/tegra/pm.h
index 08477d7bfab9..433878927026 100644
--- a/include/soc/tegra/pm.h
+++ b/include/soc/tegra/pm.h
@@ -14,6 +14,7 @@ enum tegra_suspend_mode {
TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
TEGRA_MAX_SUSPEND_MODE,
+ TEGRA_SUSPEND_NOT_READY,
};
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
@@ -28,6 +29,7 @@ void tegra_pm_clear_cpu_in_lp2(void);
void tegra_pm_set_cpu_in_lp2(void);
int tegra_pm_enter_lp2(void);
int tegra_pm_park_secondary_cpu(unsigned long cpu);
+void tegra_pm_init_suspend(void);
#else
static inline enum tegra_suspend_mode
tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
@@ -61,6 +63,10 @@ static inline int tegra_pm_park_secondary_cpu(unsigned long cpu)
{
return -ENOTSUPP;
}
+
+static inline void tegra_pm_init_suspend(void)
+{
+}
#endif /* CONFIG_PM_SLEEP */
#endif /* __SOC_TEGRA_PM_H__ */
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index 277087f635f3..d91289c6f00e 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -165,8 +165,6 @@ struct snd_compr {
};
/* compress device register APIs */
-int snd_compress_register(struct snd_compr *device);
-int snd_compress_deregister(struct snd_compr *device);
int snd_compress_new(struct snd_card *card, int device,
int type, const char *id, struct snd_compr *compr);
diff --git a/include/sound/core.h b/include/sound/core.h
index c4ade121727d..b7e9b58d3c78 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -117,6 +117,8 @@ struct snd_card {
struct device card_dev; /* cardX object for sysfs */
const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
bool registered; /* card_dev is registered? */
+ bool managed; /* managed via devres */
+ bool releasing; /* during card free process */
int sync_irq; /* assigned irq, used for PCM sync */
wait_queue_head_t remove_sleep;
@@ -274,6 +276,9 @@ extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
int snd_card_new(struct device *parent, int idx, const char *xid,
struct module *module, int extra_size,
struct snd_card **card_ret);
+int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+ struct module *module, size_t extra_size,
+ struct snd_card **card_ret);
int snd_card_disconnect(struct snd_card *card);
void snd_card_disconnect_sync(struct snd_card *card);
@@ -324,6 +329,7 @@ int snd_device_get_state(struct snd_card *card, void *device_data);
void snd_dma_program(unsigned long dma, unsigned long addr, unsigned int size, unsigned short mode);
void snd_dma_disable(unsigned long dma);
unsigned int snd_dma_pointer(unsigned long dma, unsigned int size);
+int snd_devm_request_dma(struct device *dev, int dma, const char *name);
#endif
/* misc.c */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 468e38c54dd3..39787fecc8d9 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1701,7 +1701,7 @@ struct snd_emu10k1 {
struct snd_dma_buffer silent_page; /* silent page */
struct snd_dma_buffer ptb_pages; /* page table pages */
struct snd_dma_device p16v_dma_dev;
- struct snd_dma_buffer p16v_buffer;
+ struct snd_dma_buffer *p16v_buffer;
struct snd_util_memhdr *memhdr; /* page allocation list */
@@ -1796,14 +1796,12 @@ int snd_emu10k1_create(struct snd_card *card,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
- uint subsystem,
- struct snd_emu10k1 ** remu);
+ uint subsystem);
int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device);
int snd_p16v_pcm(struct snd_emu10k1 *emu, int device);
-int snd_p16v_free(struct snd_emu10k1 * emu);
int snd_p16v_mixer(struct snd_emu10k1 * emu);
int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 *emu, int device);
diff --git a/include/sound/emu8000.h b/include/sound/emu8000.h
index ad0365d6de5e..072791bbcf5c 100644
--- a/include/sound/emu8000.h
+++ b/include/sound/emu8000.h
@@ -56,9 +56,6 @@ struct snd_emu8000 {
unsigned long port1; /* Port usually base+0 */
unsigned long port2; /* Port usually at base+0x400 */
unsigned long port3; /* Port usually at base+0x800 */
- struct resource *res_port1;
- struct resource *res_port2;
- struct resource *res_port3;
unsigned short last_reg;/* Last register command */
spinlock_t reg_lock;
diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h
index 2e8d51937acd..01570dbda503 100644
--- a/include/sound/hda_codec.h
+++ b/include/sound/hda_codec.h
@@ -114,7 +114,6 @@ struct hda_codec_ops {
int (*resume)(struct hda_codec *codec);
int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
#endif
- void (*reboot_notify)(struct hda_codec *codec);
void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on);
};
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
index a125e3814b58..375581634143 100644
--- a/include/sound/hdaudio_ext.h
+++ b/include/sound/hdaudio_ext.h
@@ -51,7 +51,7 @@ enum hdac_ext_stream_type {
* @decoupled: stream host and link is decoupled
* @link_locked: link is locked
* @link_prepared: link is prepared
- * link_substream: link substream
+ * @link_substream: link substream
*/
struct hdac_ext_stream {
struct hdac_stream hstream;
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index 44d87775b352..b197e3f431c1 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -31,13 +31,13 @@ struct snd_dma_device {
#define SNDRV_DMA_TYPE_UNKNOWN 0 /* not defined */
#define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */
#define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */
-#define SNDRV_DMA_TYPE_DEV_UC 5 /* continuous non-cahced */
+#define SNDRV_DMA_TYPE_DEV_WC 5 /* continuous write-combined */
#ifdef CONFIG_SND_DMA_SGBUF
#define SNDRV_DMA_TYPE_DEV_SG 3 /* generic device SG-buffer */
-#define SNDRV_DMA_TYPE_DEV_UC_SG 6 /* SG non-cached */
+#define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */
#else
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
-#define SNDRV_DMA_TYPE_DEV_UC_SG SNDRV_DMA_TYPE_DEV_UC
+#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
#endif
#ifdef CONFIG_GENERIC_ALLOCATOR
#define SNDRV_DMA_TYPE_DEV_IRAM 4 /* generic device iram-buffer */
@@ -79,5 +79,9 @@ struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset);
unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size);
+/* device-managed memory allocator */
+struct snd_dma_buffer *snd_devm_alloc_pages(struct device *dev, int type,
+ size_t size);
+
#endif /* __SOUND_MEMALLOC_H */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 938f36050a5e..33451f8ff755 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1204,11 +1204,48 @@ void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
-void snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
- struct device *data, size_t size, size_t max);
-void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
- struct device *data,
- size_t size, size_t max);
+int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
+ struct device *data, size_t size, size_t max);
+int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
+ struct device *data,
+ size_t size, size_t max);
+
+/**
+ * snd_pcm_set_fixed_buffer - Preallocate and set up the fixed size PCM buffer
+ * @substream: the pcm substream instance
+ * @type: DMA type (SNDRV_DMA_TYPE_*)
+ * @data: DMA type dependent data
+ * @size: the requested pre-allocation size in bytes
+ *
+ * This is a variant of snd_pcm_set_managed_buffer(), but this pre-allocates
+ * only the given sized buffer and doesn't allow re-allocation nor dynamic
+ * allocation of a larger buffer unlike the standard one.
+ * The function may return -ENOMEM error, hence the caller must check it.
+ */
+static inline int __must_check
+snd_pcm_set_fixed_buffer(struct snd_pcm_substream *substream, int type,
+ struct device *data, size_t size)
+{
+ return snd_pcm_set_managed_buffer(substream, type, data, size, 0);
+}
+
+/**
+ * snd_pcm_set_fixed_buffer_all - Preallocate and set up the fixed size PCM buffer
+ * @pcm: the pcm instance
+ * @type: DMA type (SNDRV_DMA_TYPE_*)
+ * @data: DMA type dependent data
+ * @size: the requested pre-allocation size in bytes
+ *
+ * Apply the set up of the fixed buffer via snd_pcm_set_fixed_buffer() for
+ * all substream. If any of allocation fails, it returns -ENOMEM, hence the
+ * caller must check the return value.
+ */
+static inline int __must_check
+snd_pcm_set_fixed_buffer_all(struct snd_pcm *pcm, int type,
+ struct device *data, size_t size)
+{
+ return snd_pcm_set_managed_buffer_all(pcm, type, data, size, 0);
+}
int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
size_t size, gfp_t gfp_flags);
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 0feaf16e6ac0..95100cff25d1 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -14,18 +14,12 @@ struct snd_soc_component;
extern int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
-extern int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_open(struct snd_pcm_substream *substream);
extern int pxa2xx_pcm_close(struct snd_pcm_substream *substream);
-extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma);
-extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream);
-extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm);
-extern void pxa2xx_soc_pcm_free(struct snd_soc_component *component,
- struct snd_pcm *pcm);
+extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm);
extern int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd);
extern int pxa2xx_soc_pcm_open(struct snd_soc_component *component,
@@ -35,8 +29,6 @@ extern int pxa2xx_soc_pcm_close(struct snd_soc_component *component,
extern int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
-extern int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream);
extern int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
@@ -44,9 +36,6 @@ extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
extern snd_pcm_uframes_t
pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
-extern int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma);
/* AC97 */
diff --git a/include/sound/sof.h b/include/sound/sof.h
index 502ed9b8d6a1..6a1cd8e783d8 100644
--- a/include/sound/sof.h
+++ b/include/sound/sof.h
@@ -101,5 +101,6 @@ struct sof_dev_desc {
};
int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd);
+int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd);
#endif
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index 1f78b09bba55..675f3a1fe613 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -75,6 +75,7 @@ void target_backend_unregister(const struct target_backend_ops *);
void target_complete_cmd(struct se_cmd *, u8);
void target_set_cmd_data_length(struct se_cmd *, int);
+void target_complete_cmd_with_sense(struct se_cmd *, u8, sense_reason_t);
void target_complete_cmd_with_length(struct se_cmd *, u8, int);
void transport_copy_sense_to_cmd(struct se_cmd *, unsigned char *);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 85c16c266eac..fb11c7693b25 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -171,7 +171,7 @@ enum tcm_sense_reason_table {
TCM_WRITE_PROTECTED = R(0x0c),
TCM_CHECK_CONDITION_ABORT_CMD = R(0x0d),
TCM_CHECK_CONDITION_UNIT_ATTENTION = R(0x0e),
- TCM_CHECK_CONDITION_NOT_READY = R(0x0f),
+
TCM_RESERVATION_CONFLICT = R(0x10),
TCM_ADDRESS_OUT_OF_RANGE = R(0x11),
TCM_OUT_OF_RESOURCES = R(0x12),
@@ -188,6 +188,10 @@ enum tcm_sense_reason_table {
TCM_INSUFFICIENT_REGISTRATION_RESOURCES = R(0x1d),
TCM_LUN_BUSY = R(0x1e),
TCM_INVALID_FIELD_IN_COMMAND_IU = R(0x1f),
+ TCM_ALUA_TG_PT_STANDBY = R(0x20),
+ TCM_ALUA_TG_PT_UNAVAILABLE = R(0x21),
+ TCM_ALUA_STATE_TRANSITION = R(0x22),
+ TCM_ALUA_OFFLINE = R(0x23),
#undef R
};
@@ -453,10 +457,10 @@ enum target_core_dif_check {
#define TCM_ACA_TAG 0x24
struct se_cmd {
+ /* Used for fail with specific sense codes */
+ sense_reason_t sense_reason;
/* SAM response code being sent to initiator */
u8 scsi_status;
- u8 scsi_asc;
- u8 scsi_ascq;
u16 scsi_sense_length;
unsigned unknown_data_length:1;
bool state_active:1;
diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h
index 5d9de24cb9c0..9a448fe9355d 100644
--- a/include/trace/events/cachefiles.h
+++ b/include/trace/events/cachefiles.h
@@ -78,20 +78,20 @@ TRACE_EVENT(cachefiles_ref,
/* Note that obj may be NULL */
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
- __field(struct fscache_cookie *, cookie )
+ __field(unsigned int, obj )
+ __field(unsigned int, cookie )
__field(enum cachefiles_obj_ref_trace, why )
__field(int, usage )
),
TP_fast_assign(
- __entry->obj = obj;
- __entry->cookie = cookie;
+ __entry->obj = obj->fscache.debug_id;
+ __entry->cookie = cookie->debug_id;
__entry->usage = usage;
__entry->why = why;
),
- TP_printk("c=%p o=%p u=%d %s",
+ TP_printk("c=%08x o=%08x u=%d %s",
__entry->cookie, __entry->obj, __entry->usage,
__print_symbolic(__entry->why, cachefiles_obj_ref_traces))
);
@@ -104,18 +104,18 @@ TRACE_EVENT(cachefiles_lookup,
TP_ARGS(obj, de, inode),
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
__field(struct dentry *, de )
__field(struct inode *, inode )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
__entry->inode = inode;
),
- TP_printk("o=%p d=%p i=%p",
+ TP_printk("o=%08x d=%p i=%p",
__entry->obj, __entry->de, __entry->inode)
);
@@ -126,18 +126,18 @@ TRACE_EVENT(cachefiles_mkdir,
TP_ARGS(obj, de, ret),
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
__field(struct dentry *, de )
__field(int, ret )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
__entry->ret = ret;
),
- TP_printk("o=%p d=%p r=%u",
+ TP_printk("o=%08x d=%p r=%u",
__entry->obj, __entry->de, __entry->ret)
);
@@ -148,18 +148,18 @@ TRACE_EVENT(cachefiles_create,
TP_ARGS(obj, de, ret),
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
__field(struct dentry *, de )
__field(int, ret )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
__entry->ret = ret;
),
- TP_printk("o=%p d=%p r=%u",
+ TP_printk("o=%08x d=%p r=%u",
__entry->obj, __entry->de, __entry->ret)
);
@@ -172,18 +172,18 @@ TRACE_EVENT(cachefiles_unlink,
/* Note that obj may be NULL */
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
__field(struct dentry *, de )
__field(enum fscache_why_object_killed, why )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
__entry->why = why;
),
- TP_printk("o=%p d=%p w=%s",
+ TP_printk("o=%08x d=%p w=%s",
__entry->obj, __entry->de,
__print_symbolic(__entry->why, cachefiles_obj_kill_traces))
);
@@ -198,20 +198,20 @@ TRACE_EVENT(cachefiles_rename,
/* Note that obj may be NULL */
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
__field(struct dentry *, de )
__field(struct dentry *, to )
__field(enum fscache_why_object_killed, why )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
__entry->to = to;
__entry->why = why;
),
- TP_printk("o=%p d=%p t=%p w=%s",
+ TP_printk("o=%08x d=%p t=%p w=%s",
__entry->obj, __entry->de, __entry->to,
__print_symbolic(__entry->why, cachefiles_obj_kill_traces))
);
@@ -224,16 +224,16 @@ TRACE_EVENT(cachefiles_mark_active,
/* Note that obj may be NULL */
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
__field(struct dentry *, de )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
),
- TP_printk("o=%p d=%p",
+ TP_printk("o=%08x d=%p",
__entry->obj, __entry->de)
);
@@ -246,22 +246,22 @@ TRACE_EVENT(cachefiles_wait_active,
/* Note that obj may be NULL */
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
+ __field(unsigned int, xobj )
__field(struct dentry *, de )
- __field(struct cachefiles_object *, xobj )
__field(u16, flags )
__field(u16, fsc_flags )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
- __entry->xobj = xobj;
+ __entry->xobj = xobj->fscache.debug_id;
__entry->flags = xobj->flags;
__entry->fsc_flags = xobj->fscache.flags;
),
- TP_printk("o=%p d=%p wo=%p wf=%x wff=%x",
+ TP_printk("o=%08x d=%p wo=%08x wf=%x wff=%x",
__entry->obj, __entry->de, __entry->xobj,
__entry->flags, __entry->fsc_flags)
);
@@ -275,18 +275,18 @@ TRACE_EVENT(cachefiles_mark_inactive,
/* Note that obj may be NULL */
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
__field(struct dentry *, de )
__field(struct inode *, inode )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
__entry->inode = inode;
),
- TP_printk("o=%p d=%p i=%p",
+ TP_printk("o=%08x d=%p i=%p",
__entry->obj, __entry->de, __entry->inode)
);
@@ -299,18 +299,18 @@ TRACE_EVENT(cachefiles_mark_buried,
/* Note that obj may be NULL */
TP_STRUCT__entry(
- __field(struct cachefiles_object *, obj )
+ __field(unsigned int, obj )
__field(struct dentry *, de )
__field(enum fscache_why_object_killed, why )
),
TP_fast_assign(
- __entry->obj = obj;
+ __entry->obj = obj->fscache.debug_id;
__entry->de = de;
__entry->why = why;
),
- TP_printk("o=%p d=%p w=%s",
+ TP_printk("o=%08x d=%p w=%s",
__entry->obj, __entry->de,
__print_symbolic(__entry->why, cachefiles_obj_kill_traces))
);
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 56b113e3cd6a..4e881d91c874 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -1818,6 +1818,7 @@ DEFINE_EVENT(f2fs_zip_end, f2fs_decompress_pages_end,
TP_ARGS(inode, cluster_idx, compressed_size, ret)
);
+#ifdef CONFIG_F2FS_IOSTAT
TRACE_EVENT(f2fs_iostat,
TP_PROTO(struct f2fs_sb_info *sbi, unsigned long long *iostat),
@@ -1894,6 +1895,102 @@ TRACE_EVENT(f2fs_iostat,
__entry->fs_cdrio, __entry->fs_nrio, __entry->fs_mrio)
);
+#ifndef __F2FS_IOSTAT_LATENCY_TYPE
+#define __F2FS_IOSTAT_LATENCY_TYPE
+struct f2fs_iostat_latency {
+ unsigned int peak_lat;
+ unsigned int avg_lat;
+ unsigned int cnt;
+};
+#endif /* __F2FS_IOSTAT_LATENCY_TYPE */
+
+TRACE_EVENT(f2fs_iostat_latency,
+
+ TP_PROTO(struct f2fs_sb_info *sbi, struct f2fs_iostat_latency (*iostat_lat)[NR_PAGE_TYPE]),
+
+ TP_ARGS(sbi, iostat_lat),
+
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(unsigned int, d_rd_peak)
+ __field(unsigned int, d_rd_avg)
+ __field(unsigned int, d_rd_cnt)
+ __field(unsigned int, n_rd_peak)
+ __field(unsigned int, n_rd_avg)
+ __field(unsigned int, n_rd_cnt)
+ __field(unsigned int, m_rd_peak)
+ __field(unsigned int, m_rd_avg)
+ __field(unsigned int, m_rd_cnt)
+ __field(unsigned int, d_wr_s_peak)
+ __field(unsigned int, d_wr_s_avg)
+ __field(unsigned int, d_wr_s_cnt)
+ __field(unsigned int, n_wr_s_peak)
+ __field(unsigned int, n_wr_s_avg)
+ __field(unsigned int, n_wr_s_cnt)
+ __field(unsigned int, m_wr_s_peak)
+ __field(unsigned int, m_wr_s_avg)
+ __field(unsigned int, m_wr_s_cnt)
+ __field(unsigned int, d_wr_as_peak)
+ __field(unsigned int, d_wr_as_avg)
+ __field(unsigned int, d_wr_as_cnt)
+ __field(unsigned int, n_wr_as_peak)
+ __field(unsigned int, n_wr_as_avg)
+ __field(unsigned int, n_wr_as_cnt)
+ __field(unsigned int, m_wr_as_peak)
+ __field(unsigned int, m_wr_as_avg)
+ __field(unsigned int, m_wr_as_cnt)
+ ),
+
+ TP_fast_assign(
+ __entry->dev = sbi->sb->s_dev;
+ __entry->d_rd_peak = iostat_lat[0][DATA].peak_lat;
+ __entry->d_rd_avg = iostat_lat[0][DATA].avg_lat;
+ __entry->d_rd_cnt = iostat_lat[0][DATA].cnt;
+ __entry->n_rd_peak = iostat_lat[0][NODE].peak_lat;
+ __entry->n_rd_avg = iostat_lat[0][NODE].avg_lat;
+ __entry->n_rd_cnt = iostat_lat[0][NODE].cnt;
+ __entry->m_rd_peak = iostat_lat[0][META].peak_lat;
+ __entry->m_rd_avg = iostat_lat[0][META].avg_lat;
+ __entry->m_rd_cnt = iostat_lat[0][META].cnt;
+ __entry->d_wr_s_peak = iostat_lat[1][DATA].peak_lat;
+ __entry->d_wr_s_avg = iostat_lat[1][DATA].avg_lat;
+ __entry->d_wr_s_cnt = iostat_lat[1][DATA].cnt;
+ __entry->n_wr_s_peak = iostat_lat[1][NODE].peak_lat;
+ __entry->n_wr_s_avg = iostat_lat[1][NODE].avg_lat;
+ __entry->n_wr_s_cnt = iostat_lat[1][NODE].cnt;
+ __entry->m_wr_s_peak = iostat_lat[1][META].peak_lat;
+ __entry->m_wr_s_avg = iostat_lat[1][META].avg_lat;
+ __entry->m_wr_s_cnt = iostat_lat[1][META].cnt;
+ __entry->d_wr_as_peak = iostat_lat[2][DATA].peak_lat;
+ __entry->d_wr_as_avg = iostat_lat[2][DATA].avg_lat;
+ __entry->d_wr_as_cnt = iostat_lat[2][DATA].cnt;
+ __entry->n_wr_as_peak = iostat_lat[2][NODE].peak_lat;
+ __entry->n_wr_as_avg = iostat_lat[2][NODE].avg_lat;
+ __entry->n_wr_as_cnt = iostat_lat[2][NODE].cnt;
+ __entry->m_wr_as_peak = iostat_lat[2][META].peak_lat;
+ __entry->m_wr_as_avg = iostat_lat[2][META].avg_lat;
+ __entry->m_wr_as_cnt = iostat_lat[2][META].cnt;
+ ),
+
+ TP_printk("dev = (%d,%d), "
+ "iotype [peak lat.(ms)/avg lat.(ms)/count], "
+ "rd_data [%u/%u/%u], rd_node [%u/%u/%u], rd_meta [%u/%u/%u], "
+ "wr_sync_data [%u/%u/%u], wr_sync_node [%u/%u/%u], "
+ "wr_sync_meta [%u/%u/%u], wr_async_data [%u/%u/%u], "
+ "wr_async_node [%u/%u/%u], wr_async_meta [%u/%u/%u]",
+ show_dev(__entry->dev),
+ __entry->d_rd_peak, __entry->d_rd_avg, __entry->d_rd_cnt,
+ __entry->n_rd_peak, __entry->n_rd_avg, __entry->n_rd_cnt,
+ __entry->m_rd_peak, __entry->m_rd_avg, __entry->m_rd_cnt,
+ __entry->d_wr_s_peak, __entry->d_wr_s_avg, __entry->d_wr_s_cnt,
+ __entry->n_wr_s_peak, __entry->n_wr_s_avg, __entry->n_wr_s_cnt,
+ __entry->m_wr_s_peak, __entry->m_wr_s_avg, __entry->m_wr_s_cnt,
+ __entry->d_wr_as_peak, __entry->d_wr_as_avg, __entry->d_wr_as_cnt,
+ __entry->n_wr_as_peak, __entry->n_wr_as_avg, __entry->n_wr_as_cnt,
+ __entry->m_wr_as_peak, __entry->m_wr_as_avg, __entry->m_wr_as_cnt)
+);
+#endif
+
TRACE_EVENT(f2fs_bmap,
TP_PROTO(struct inode *inode, sector_t lblock, sector_t pblock),
diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h
index d16fe6ed78a2..446392f5ba83 100644
--- a/include/trace/events/fscache.h
+++ b/include/trace/events/fscache.h
@@ -160,37 +160,27 @@ fscache_cookie_traces;
TRACE_EVENT(fscache_cookie,
- TP_PROTO(struct fscache_cookie *cookie,
- enum fscache_cookie_trace where,
- int usage),
+ TP_PROTO(unsigned int cookie_debug_id,
+ int ref,
+ enum fscache_cookie_trace where),
- TP_ARGS(cookie, where, usage),
+ TP_ARGS(cookie_debug_id, ref, where),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
- __field(struct fscache_cookie *, parent )
+ __field(unsigned int, cookie )
__field(enum fscache_cookie_trace, where )
- __field(int, usage )
- __field(int, n_children )
- __field(int, n_active )
- __field(u8, flags )
+ __field(int, ref )
),
TP_fast_assign(
- __entry->cookie = cookie;
- __entry->parent = cookie->parent;
+ __entry->cookie = cookie_debug_id;
__entry->where = where;
- __entry->usage = usage;
- __entry->n_children = atomic_read(&cookie->n_children);
- __entry->n_active = atomic_read(&cookie->n_active);
- __entry->flags = cookie->flags;
+ __entry->ref = ref;
),
- TP_printk("%s c=%p u=%d p=%p Nc=%d Na=%d f=%02x",
+ TP_printk("%s c=%08x r=%d",
__print_symbolic(__entry->where, fscache_cookie_traces),
- __entry->cookie, __entry->usage,
- __entry->parent, __entry->n_children, __entry->n_active,
- __entry->flags)
+ __entry->cookie, __entry->ref)
);
TRACE_EVENT(fscache_netfs,
@@ -199,17 +189,17 @@ TRACE_EVENT(fscache_netfs,
TP_ARGS(netfs),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
+ __field(unsigned int, cookie )
__array(char, name, 8 )
),
TP_fast_assign(
- __entry->cookie = netfs->primary_index;
+ __entry->cookie = netfs->primary_index->debug_id;
strncpy(__entry->name, netfs->name, 8);
__entry->name[7] = 0;
),
- TP_printk("c=%p n=%s",
+ TP_printk("c=%08x n=%s",
__entry->cookie, __entry->name)
);
@@ -219,26 +209,26 @@ TRACE_EVENT(fscache_acquire,
TP_ARGS(cookie),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
- __field(struct fscache_cookie *, parent )
+ __field(unsigned int, cookie )
+ __field(unsigned int, parent )
__array(char, name, 8 )
- __field(int, p_usage )
+ __field(int, p_ref )
__field(int, p_n_children )
__field(u8, p_flags )
),
TP_fast_assign(
- __entry->cookie = cookie;
- __entry->parent = cookie->parent;
- __entry->p_usage = atomic_read(&cookie->parent->usage);
+ __entry->cookie = cookie->debug_id;
+ __entry->parent = cookie->parent->debug_id;
+ __entry->p_ref = refcount_read(&cookie->parent->ref);
__entry->p_n_children = atomic_read(&cookie->parent->n_children);
__entry->p_flags = cookie->parent->flags;
memcpy(__entry->name, cookie->def->name, 8);
__entry->name[7] = 0;
),
- TP_printk("c=%p p=%p pu=%d pc=%d pf=%02x n=%s",
- __entry->cookie, __entry->parent, __entry->p_usage,
+ TP_printk("c=%08x p=%08x pr=%d pc=%d pf=%02x n=%s",
+ __entry->cookie, __entry->parent, __entry->p_ref,
__entry->p_n_children, __entry->p_flags, __entry->name)
);
@@ -248,9 +238,9 @@ TRACE_EVENT(fscache_relinquish,
TP_ARGS(cookie, retire),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
- __field(struct fscache_cookie *, parent )
- __field(int, usage )
+ __field(unsigned int, cookie )
+ __field(unsigned int, parent )
+ __field(int, ref )
__field(int, n_children )
__field(int, n_active )
__field(u8, flags )
@@ -258,17 +248,17 @@ TRACE_EVENT(fscache_relinquish,
),
TP_fast_assign(
- __entry->cookie = cookie;
- __entry->parent = cookie->parent;
- __entry->usage = atomic_read(&cookie->usage);
+ __entry->cookie = cookie->debug_id;
+ __entry->parent = cookie->parent->debug_id;
+ __entry->ref = refcount_read(&cookie->ref);
__entry->n_children = atomic_read(&cookie->n_children);
__entry->n_active = atomic_read(&cookie->n_active);
__entry->flags = cookie->flags;
__entry->retire = retire;
),
- TP_printk("c=%p u=%d p=%p Nc=%d Na=%d f=%02x r=%u",
- __entry->cookie, __entry->usage,
+ TP_printk("c=%08x r=%d p=%08x Nc=%d Na=%d f=%02x r=%u",
+ __entry->cookie, __entry->ref,
__entry->parent, __entry->n_children, __entry->n_active,
__entry->flags, __entry->retire)
);
@@ -279,23 +269,23 @@ TRACE_EVENT(fscache_enable,
TP_ARGS(cookie),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
- __field(int, usage )
+ __field(unsigned int, cookie )
+ __field(int, ref )
__field(int, n_children )
__field(int, n_active )
__field(u8, flags )
),
TP_fast_assign(
- __entry->cookie = cookie;
- __entry->usage = atomic_read(&cookie->usage);
+ __entry->cookie = cookie->debug_id;
+ __entry->ref = refcount_read(&cookie->ref);
__entry->n_children = atomic_read(&cookie->n_children);
__entry->n_active = atomic_read(&cookie->n_active);
__entry->flags = cookie->flags;
),
- TP_printk("c=%p u=%d Nc=%d Na=%d f=%02x",
- __entry->cookie, __entry->usage,
+ TP_printk("c=%08x r=%d Nc=%d Na=%d f=%02x",
+ __entry->cookie, __entry->ref,
__entry->n_children, __entry->n_active, __entry->flags)
);
@@ -305,23 +295,23 @@ TRACE_EVENT(fscache_disable,
TP_ARGS(cookie),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
- __field(int, usage )
+ __field(unsigned int, cookie )
+ __field(int, ref )
__field(int, n_children )
__field(int, n_active )
__field(u8, flags )
),
TP_fast_assign(
- __entry->cookie = cookie;
- __entry->usage = atomic_read(&cookie->usage);
+ __entry->cookie = cookie->debug_id;
+ __entry->ref = refcount_read(&cookie->ref);
__entry->n_children = atomic_read(&cookie->n_children);
__entry->n_active = atomic_read(&cookie->n_active);
__entry->flags = cookie->flags;
),
- TP_printk("c=%p u=%d Nc=%d Na=%d f=%02x",
- __entry->cookie, __entry->usage,
+ TP_printk("c=%08x r=%d Nc=%d Na=%d f=%02x",
+ __entry->cookie, __entry->ref,
__entry->n_children, __entry->n_active, __entry->flags)
);
@@ -333,8 +323,8 @@ TRACE_EVENT(fscache_osm,
TP_ARGS(object, state, wait, oob, event_num),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
- __field(struct fscache_object *, object )
+ __field(unsigned int, cookie )
+ __field(unsigned int, object )
__array(char, state, 8 )
__field(bool, wait )
__field(bool, oob )
@@ -342,15 +332,15 @@ TRACE_EVENT(fscache_osm,
),
TP_fast_assign(
- __entry->cookie = object->cookie;
- __entry->object = object;
+ __entry->cookie = object->cookie->debug_id;
+ __entry->object = object->debug_id;
__entry->wait = wait;
__entry->oob = oob;
__entry->event_num = event_num;
memcpy(__entry->state, state->short_name, 8);
),
- TP_printk("c=%p o=%p %s %s%sev=%d",
+ TP_printk("c=%08x o=%08d %s %s%sev=%d",
__entry->cookie,
__entry->object,
__entry->state,
@@ -370,18 +360,18 @@ TRACE_EVENT(fscache_page,
TP_ARGS(cookie, page, why),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
+ __field(unsigned int, cookie )
__field(pgoff_t, page )
__field(enum fscache_page_trace, why )
),
TP_fast_assign(
- __entry->cookie = cookie;
+ __entry->cookie = cookie->debug_id;
__entry->page = page->index;
__entry->why = why;
),
- TP_printk("c=%p %s pg=%lx",
+ TP_printk("c=%08x %s pg=%lx",
__entry->cookie,
__print_symbolic(__entry->why, fscache_page_traces),
__entry->page)
@@ -394,20 +384,20 @@ TRACE_EVENT(fscache_check_page,
TP_ARGS(cookie, page, val, n),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
+ __field(unsigned int, cookie )
__field(void *, page )
__field(void *, val )
__field(int, n )
),
TP_fast_assign(
- __entry->cookie = cookie;
+ __entry->cookie = cookie->debug_id;
__entry->page = page;
__entry->val = val;
__entry->n = n;
),
- TP_printk("c=%p pg=%p val=%p n=%d",
+ TP_printk("c=%08x pg=%p val=%p n=%d",
__entry->cookie, __entry->page, __entry->val, __entry->n)
);
@@ -417,14 +407,14 @@ TRACE_EVENT(fscache_wake_cookie,
TP_ARGS(cookie),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
+ __field(unsigned int, cookie )
),
TP_fast_assign(
- __entry->cookie = cookie;
+ __entry->cookie = cookie->debug_id;
),
- TP_printk("c=%p", __entry->cookie)
+ TP_printk("c=%08x", __entry->cookie)
);
TRACE_EVENT(fscache_op,
@@ -434,18 +424,18 @@ TRACE_EVENT(fscache_op,
TP_ARGS(cookie, op, why),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
- __field(struct fscache_operation *, op )
+ __field(unsigned int, cookie )
+ __field(unsigned int, op )
__field(enum fscache_op_trace, why )
),
TP_fast_assign(
- __entry->cookie = cookie;
- __entry->op = op;
+ __entry->cookie = cookie ? cookie->debug_id : 0;
+ __entry->op = op->debug_id;
__entry->why = why;
),
- TP_printk("c=%p op=%p %s",
+ TP_printk("c=%08x op=%08x %s",
__entry->cookie, __entry->op,
__print_symbolic(__entry->why, fscache_op_traces))
);
@@ -457,20 +447,20 @@ TRACE_EVENT(fscache_page_op,
TP_ARGS(cookie, page, op, what),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
+ __field(unsigned int, cookie )
+ __field(unsigned int, op )
__field(pgoff_t, page )
- __field(struct fscache_operation *, op )
__field(enum fscache_page_op_trace, what )
),
TP_fast_assign(
- __entry->cookie = cookie;
+ __entry->cookie = cookie->debug_id;
__entry->page = page ? page->index : 0;
- __entry->op = op;
+ __entry->op = op->debug_id;
__entry->what = what;
),
- TP_printk("c=%p %s pg=%lx op=%p",
+ TP_printk("c=%08x %s pg=%lx op=%08x",
__entry->cookie,
__print_symbolic(__entry->what, fscache_page_op_traces),
__entry->page, __entry->op)
@@ -483,20 +473,20 @@ TRACE_EVENT(fscache_wrote_page,
TP_ARGS(cookie, page, op, ret),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
+ __field(unsigned int, cookie )
+ __field(unsigned int, op )
__field(pgoff_t, page )
- __field(struct fscache_operation *, op )
__field(int, ret )
),
TP_fast_assign(
- __entry->cookie = cookie;
+ __entry->cookie = cookie->debug_id;
__entry->page = page->index;
- __entry->op = op;
+ __entry->op = op->debug_id;
__entry->ret = ret;
),
- TP_printk("c=%p pg=%lx op=%p ret=%d",
+ TP_printk("c=%08x pg=%lx op=%08x ret=%d",
__entry->cookie, __entry->page, __entry->op, __entry->ret)
);
@@ -507,22 +497,22 @@ TRACE_EVENT(fscache_gang_lookup,
TP_ARGS(cookie, op, results, n, store_limit),
TP_STRUCT__entry(
- __field(struct fscache_cookie *, cookie )
- __field(struct fscache_operation *, op )
+ __field(unsigned int, cookie )
+ __field(unsigned int, op )
__field(pgoff_t, results0 )
__field(int, n )
__field(pgoff_t, store_limit )
),
TP_fast_assign(
- __entry->cookie = cookie;
- __entry->op = op;
+ __entry->cookie = cookie->debug_id;
+ __entry->op = op->debug_id;
__entry->results0 = results[0] ? ((struct page *)results[0])->index : (pgoff_t)-1;
__entry->n = n;
__entry->store_limit = store_limit;
),
- TP_printk("c=%p op=%p r0=%lx n=%d sl=%lx",
+ TP_printk("c=%08x op=%08x r0=%lx n=%d sl=%lx",
__entry->cookie, __entry->op, __entry->results0, __entry->n,
__entry->store_limit)
);
diff --git a/include/trace/events/io_uring.h b/include/trace/events/io_uring.h
index e4e44a2b4aa9..0dd30de00e5b 100644
--- a/include/trace/events/io_uring.h
+++ b/include/trace/events/io_uring.h
@@ -295,14 +295,14 @@ TRACE_EVENT(io_uring_fail_link,
*/
TRACE_EVENT(io_uring_complete,
- TP_PROTO(void *ctx, u64 user_data, long res, unsigned cflags),
+ TP_PROTO(void *ctx, u64 user_data, int res, unsigned cflags),
TP_ARGS(ctx, user_data, res, cflags),
TP_STRUCT__entry (
__field( void *, ctx )
__field( u64, user_data )
- __field( long, res )
+ __field( int, res )
__field( unsigned, cflags )
),
@@ -313,7 +313,7 @@ TRACE_EVENT(io_uring_complete,
__entry->cflags = cflags;
),
- TP_printk("ring %p, user_data 0x%llx, result %ld, cflags %x",
+ TP_printk("ring %p, user_data 0x%llx, result %d, cflags %x",
__entry->ctx, (unsigned long long)__entry->user_data,
__entry->res, __entry->cflags)
);
diff --git a/include/trace/events/migrate.h b/include/trace/events/migrate.h
index 9fb2a3bbcdfb..779f3fad9ecd 100644
--- a/include/trace/events/migrate.h
+++ b/include/trace/events/migrate.h
@@ -21,7 +21,8 @@
EM( MR_MEMPOLICY_MBIND, "mempolicy_mbind") \
EM( MR_NUMA_MISPLACED, "numa_misplaced") \
EM( MR_CONTIG_RANGE, "contig_range") \
- EMe(MR_LONGTERM_PIN, "longterm_pin")
+ EM( MR_LONGTERM_PIN, "longterm_pin") \
+ EMe(MR_DEMOTION, "demotion")
/*
* First define the enums in the above macros to be exported to userspace
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
index f160484afc5c..0b53e855c4ac 100644
--- a/include/trace/events/mmflags.h
+++ b/include/trace/events/mmflags.h
@@ -165,7 +165,6 @@ IF_HAVE_PG_SKIP_KASAN_POISON(PG_skip_kasan_poison, "skip_kasan_poison")
{VM_UFFD_MISSING, "uffd_missing" }, \
IF_HAVE_UFFD_MINOR(VM_UFFD_MINOR, "uffd_minor" ) \
{VM_PFNMAP, "pfnmap" }, \
- {VM_DENYWRITE, "denywrite" }, \
{VM_UFFD_WP, "uffd_wp" }, \
{VM_LOCKED, "locked" }, \
{VM_IO, "io" }, \
diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h
index de1c64635e42..4d470bffd9f1 100644
--- a/include/trace/events/netfs.h
+++ b/include/trace/events/netfs.h
@@ -139,7 +139,7 @@ TRACE_EVENT(netfs_read,
TP_fast_assign(
__entry->rreq = rreq->debug_id;
- __entry->cookie = rreq->cookie_debug_id;
+ __entry->cookie = rreq->cache_resources.debug_id;
__entry->start = start;
__entry->len = len;
__entry->what = what;
diff --git a/include/trace/events/rpcrdma.h b/include/trace/events/rpcrdma.h
index bd55908c1bef..de4195499592 100644
--- a/include/trace/events/rpcrdma.h
+++ b/include/trace/events/rpcrdma.h
@@ -793,6 +793,39 @@ TRACE_EVENT(xprtrdma_post_send,
)
);
+TRACE_EVENT(xprtrdma_post_send_err,
+ TP_PROTO(
+ const struct rpcrdma_xprt *r_xprt,
+ const struct rpcrdma_req *req,
+ int rc
+ ),
+
+ TP_ARGS(r_xprt, req, rc),
+
+ TP_STRUCT__entry(
+ __field(u32, cq_id)
+ __field(unsigned int, task_id)
+ __field(unsigned int, client_id)
+ __field(int, rc)
+ ),
+
+ TP_fast_assign(
+ const struct rpc_rqst *rqst = &req->rl_slot;
+ const struct rpcrdma_ep *ep = r_xprt->rx_ep;
+
+ __entry->cq_id = ep ? ep->re_attr.recv_cq->res.id : 0;
+ __entry->task_id = rqst->rq_task->tk_pid;
+ __entry->client_id = rqst->rq_task->tk_client ?
+ rqst->rq_task->tk_client->cl_clid : -1;
+ __entry->rc = rc;
+ ),
+
+ TP_printk("task:%u@%u cq.id=%u rc=%d",
+ __entry->task_id, __entry->client_id,
+ __entry->cq_id, __entry->rc
+ )
+);
+
TRACE_EVENT(xprtrdma_post_recv,
TP_PROTO(
const struct rpcrdma_rep *rep
@@ -818,16 +851,14 @@ TRACE_EVENT(xprtrdma_post_recv,
TRACE_EVENT(xprtrdma_post_recvs,
TP_PROTO(
const struct rpcrdma_xprt *r_xprt,
- unsigned int count,
- int status
+ unsigned int count
),
- TP_ARGS(r_xprt, count, status),
+ TP_ARGS(r_xprt, count),
TP_STRUCT__entry(
__field(u32, cq_id)
__field(unsigned int, count)
- __field(int, status)
__field(int, posted)
__string(addr, rpcrdma_addrstr(r_xprt))
__string(port, rpcrdma_portstr(r_xprt))
@@ -838,15 +869,44 @@ TRACE_EVENT(xprtrdma_post_recvs,
__entry->cq_id = ep->re_attr.recv_cq->res.id;
__entry->count = count;
- __entry->status = status;
__entry->posted = ep->re_receive_count;
__assign_str(addr, rpcrdma_addrstr(r_xprt));
__assign_str(port, rpcrdma_portstr(r_xprt));
),
- TP_printk("peer=[%s]:%s cq.id=%d %u new recvs, %d active (rc %d)",
+ TP_printk("peer=[%s]:%s cq.id=%d %u new recvs, %d active",
+ __get_str(addr), __get_str(port), __entry->cq_id,
+ __entry->count, __entry->posted
+ )
+);
+
+TRACE_EVENT(xprtrdma_post_recvs_err,
+ TP_PROTO(
+ const struct rpcrdma_xprt *r_xprt,
+ int status
+ ),
+
+ TP_ARGS(r_xprt, status),
+
+ TP_STRUCT__entry(
+ __field(u32, cq_id)
+ __field(int, status)
+ __string(addr, rpcrdma_addrstr(r_xprt))
+ __string(port, rpcrdma_portstr(r_xprt))
+ ),
+
+ TP_fast_assign(
+ const struct rpcrdma_ep *ep = r_xprt->rx_ep;
+
+ __entry->cq_id = ep->re_attr.recv_cq->res.id;
+ __entry->status = status;
+ __assign_str(addr, rpcrdma_addrstr(r_xprt));
+ __assign_str(port, rpcrdma_portstr(r_xprt));
+ ),
+
+ TP_printk("peer=[%s]:%s cq.id=%d rc=%d",
__get_str(addr), __get_str(port), __entry->cq_id,
- __entry->count, __entry->posted, __entry->status
+ __entry->status
)
);
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
index d323f5a049c8..2d04eb96d418 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -295,25 +295,11 @@ TRACE_EVENT(rpc_request,
)
);
-TRACE_DEFINE_ENUM(RPC_TASK_ASYNC);
-TRACE_DEFINE_ENUM(RPC_TASK_SWAPPER);
-TRACE_DEFINE_ENUM(RPC_TASK_NULLCREDS);
-TRACE_DEFINE_ENUM(RPC_CALL_MAJORSEEN);
-TRACE_DEFINE_ENUM(RPC_TASK_ROOTCREDS);
-TRACE_DEFINE_ENUM(RPC_TASK_DYNAMIC);
-TRACE_DEFINE_ENUM(RPC_TASK_NO_ROUND_ROBIN);
-TRACE_DEFINE_ENUM(RPC_TASK_SOFT);
-TRACE_DEFINE_ENUM(RPC_TASK_SOFTCONN);
-TRACE_DEFINE_ENUM(RPC_TASK_SENT);
-TRACE_DEFINE_ENUM(RPC_TASK_TIMEOUT);
-TRACE_DEFINE_ENUM(RPC_TASK_NOCONNECT);
-TRACE_DEFINE_ENUM(RPC_TASK_NO_RETRANS_TIMEOUT);
-TRACE_DEFINE_ENUM(RPC_TASK_CRED_NOREF);
-
#define rpc_show_task_flags(flags) \
__print_flags(flags, "|", \
{ RPC_TASK_ASYNC, "ASYNC" }, \
{ RPC_TASK_SWAPPER, "SWAPPER" }, \
+ { RPC_TASK_MOVEABLE, "MOVEABLE" }, \
{ RPC_TASK_NULLCREDS, "NULLCREDS" }, \
{ RPC_CALL_MAJORSEEN, "MAJORSEEN" }, \
{ RPC_TASK_ROOTCREDS, "ROOTCREDS" }, \
@@ -327,14 +313,6 @@ TRACE_DEFINE_ENUM(RPC_TASK_CRED_NOREF);
{ RPC_TASK_NO_RETRANS_TIMEOUT, "NORTO" }, \
{ RPC_TASK_CRED_NOREF, "CRED_NOREF" })
-TRACE_DEFINE_ENUM(RPC_TASK_RUNNING);
-TRACE_DEFINE_ENUM(RPC_TASK_QUEUED);
-TRACE_DEFINE_ENUM(RPC_TASK_ACTIVE);
-TRACE_DEFINE_ENUM(RPC_TASK_NEED_XMIT);
-TRACE_DEFINE_ENUM(RPC_TASK_NEED_RECV);
-TRACE_DEFINE_ENUM(RPC_TASK_MSG_PIN_WAIT);
-TRACE_DEFINE_ENUM(RPC_TASK_SIGNALLED);
-
#define rpc_show_runstate(flags) \
__print_flags(flags, "|", \
{ (1UL << RPC_TASK_RUNNING), "RUNNING" }, \
@@ -945,17 +923,6 @@ TRACE_EVENT(rpc_socket_nospace,
)
);
-TRACE_DEFINE_ENUM(XPRT_LOCKED);
-TRACE_DEFINE_ENUM(XPRT_CONNECTED);
-TRACE_DEFINE_ENUM(XPRT_CONNECTING);
-TRACE_DEFINE_ENUM(XPRT_CLOSE_WAIT);
-TRACE_DEFINE_ENUM(XPRT_BOUND);
-TRACE_DEFINE_ENUM(XPRT_BINDING);
-TRACE_DEFINE_ENUM(XPRT_CLOSING);
-TRACE_DEFINE_ENUM(XPRT_CONGESTED);
-TRACE_DEFINE_ENUM(XPRT_CWND_WAIT);
-TRACE_DEFINE_ENUM(XPRT_WRITE_SPACE);
-
#define rpc_show_xprt_state(x) \
__print_flags(x, "|", \
{ (1UL << XPRT_LOCKED), "LOCKED"}, \
@@ -965,6 +932,8 @@ TRACE_DEFINE_ENUM(XPRT_WRITE_SPACE);
{ (1UL << XPRT_BOUND), "BOUND"}, \
{ (1UL << XPRT_BINDING), "BINDING"}, \
{ (1UL << XPRT_CLOSING), "CLOSING"}, \
+ { (1UL << XPRT_OFFLINE), "OFFLINE"}, \
+ { (1UL << XPRT_REMOVE), "REMOVE"}, \
{ (1UL << XPRT_CONGESTED), "CONGESTED"}, \
{ (1UL << XPRT_CWND_WAIT), "CWND_WAIT"}, \
{ (1UL << XPRT_WRITE_SPACE), "WRITE_SPACE"})
@@ -1092,10 +1061,10 @@ TRACE_EVENT(xprt_retransmit,
__field(u32, xid)
__field(int, ntrans)
__field(int, version)
+ __field(unsigned long, timeout)
__string(progname,
rqst->rq_task->tk_client->cl_program->name)
- __string(procedure,
- rqst->rq_task->tk_msg.rpc_proc->p_name)
+ __string(procname, rpc_proc_name(rqst->rq_task))
),
TP_fast_assign(
@@ -1106,17 +1075,19 @@ TRACE_EVENT(xprt_retransmit,
task->tk_client->cl_clid : -1;
__entry->xid = be32_to_cpu(rqst->rq_xid);
__entry->ntrans = rqst->rq_ntrans;
+ __entry->timeout = task->tk_timeout;
__assign_str(progname,
task->tk_client->cl_program->name);
__entry->version = task->tk_client->cl_vers;
- __assign_str(procedure, task->tk_msg.rpc_proc->p_name);
+ __assign_str(procname, rpc_proc_name(task));
),
TP_printk(
- "task:%u@%u xid=0x%08x %sv%d %s ntrans=%d",
+ "task:%u@%u xid=0x%08x %sv%d %s ntrans=%d timeout=%lu",
__entry->task_id, __entry->client_id, __entry->xid,
- __get_str(progname), __entry->version, __get_str(procedure),
- __entry->ntrans)
+ __get_str(progname), __entry->version, __get_str(procname),
+ __entry->ntrans, __entry->timeout
+ )
);
TRACE_EVENT(xprt_ping,
@@ -1568,8 +1539,7 @@ DEFINE_SVCXDRBUF_EVENT(sendto);
svc_rqst_flag(SPLICE_OK) \
svc_rqst_flag(VICTIM) \
svc_rqst_flag(BUSY) \
- svc_rqst_flag(DATA) \
- svc_rqst_flag_end(AUTHERR)
+ svc_rqst_flag_end(DATA)
#undef svc_rqst_flag
#undef svc_rqst_flag_end
@@ -1611,9 +1581,9 @@ TRACE_DEFINE_ENUM(SVC_COMPLETE);
{ SVC_COMPLETE, "SVC_COMPLETE" })
TRACE_EVENT(svc_authenticate,
- TP_PROTO(const struct svc_rqst *rqst, int auth_res, __be32 auth_stat),
+ TP_PROTO(const struct svc_rqst *rqst, int auth_res),
- TP_ARGS(rqst, auth_res, auth_stat),
+ TP_ARGS(rqst, auth_res),
TP_STRUCT__entry(
__field(u32, xid)
@@ -1624,7 +1594,7 @@ TRACE_EVENT(svc_authenticate,
TP_fast_assign(
__entry->xid = be32_to_cpu(rqst->rq_xid);
__entry->svc_status = auth_res;
- __entry->auth_stat = be32_to_cpu(auth_stat);
+ __entry->auth_stat = be32_to_cpu(rqst->rq_auth_stat);
),
TP_printk("xid=0x%08x auth_res=%s auth_stat=%s",
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 5a3c221f4c9d..3ba180f550d7 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -29,6 +29,11 @@ typedef union sigval {
#define __ARCH_SI_ATTRIBUTES
#endif
+/*
+ * Be careful when extending this union. On 32bit siginfo_t is 32bit
+ * aligned. Which means that a 64bit field or any other field that
+ * would increase the alignment of siginfo_t will break the ABI.
+ */
union __sifields {
/* kill() */
struct {
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index a9d6fcd95f42..14c8fe863c6d 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -877,9 +877,11 @@ __SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self)
#define __NR_memfd_secret 447
__SYSCALL(__NR_memfd_secret, sys_memfd_secret)
#endif
+#define __NR_process_mrelease 448
+__SYSCALL(__NR_process_mrelease, sys_process_mrelease)
#undef __NR_syscalls
-#define __NR_syscalls 448
+#define __NR_syscalls 449
/*
* 32 bit systems traditionally used different
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index d043752a74cf..3b810b53ba8b 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -635,8 +635,8 @@ struct drm_gem_open {
/**
* DRM_CAP_VBLANK_HIGH_CRTC
*
- * If set to 1, the kernel supports specifying a CRTC index in the high bits of
- * &drm_wait_vblank_request.type.
+ * If set to 1, the kernel supports specifying a :ref:`CRTC index<crtc_index>`
+ * in the high bits of &drm_wait_vblank_request.type.
*
* Starting kernel version 2.6.39, this capability is always set to 1.
*/
@@ -1050,6 +1050,16 @@ extern "C" {
#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob)
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
+/**
+ * DRM_IOCTL_MODE_RMFB - Remove a framebuffer.
+ *
+ * This removes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL
+ * argument is a framebuffer object ID.
+ *
+ * Warning: removing a framebuffer currently in-use on an enabled plane will
+ * disable that plane. The CRTC the plane is linked to may also be disabled
+ * (depending on driver capabilities).
+ */
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index f7156322aba5..9f4bb4a6f358 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -900,9 +900,9 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
/*
* The top 4 bits (out of the 56 bits alloted for specifying vendor specific
- * modifiers) denote the category for modifiers. Currently we have only two
- * categories of modifiers ie AFBC and MISC. We can have a maximum of sixteen
- * different categories.
+ * modifiers) denote the category for modifiers. Currently we have three
+ * categories of modifiers ie AFBC, MISC and AFRC. We can have a maximum of
+ * sixteen different categories.
*/
#define DRM_FORMAT_MOD_ARM_CODE(__type, __val) \
fourcc_mod_code(ARM, ((__u64)(__type) << 52) | ((__val) & 0x000fffffffffffffULL))
@@ -1018,6 +1018,109 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
#define AFBC_FORMAT_MOD_USM (1ULL << 12)
/*
+ * Arm Fixed-Rate Compression (AFRC) modifiers
+ *
+ * AFRC is a proprietary fixed rate image compression protocol and format,
+ * designed to provide guaranteed bandwidth and memory footprint
+ * reductions in graphics and media use-cases.
+ *
+ * AFRC buffers consist of one or more planes, with the same components
+ * and meaning as an uncompressed buffer using the same pixel format.
+ *
+ * Within each plane, the pixel/luma/chroma values are grouped into
+ * "coding unit" blocks which are individually compressed to a
+ * fixed size (in bytes). All coding units within a given plane of a buffer
+ * store the same number of values, and have the same compressed size.
+ *
+ * The coding unit size is configurable, allowing different rates of compression.
+ *
+ * The start of each AFRC buffer plane must be aligned to an alignment granule which
+ * depends on the coding unit size.
+ *
+ * Coding Unit Size Plane Alignment
+ * ---------------- ---------------
+ * 16 bytes 1024 bytes
+ * 24 bytes 512 bytes
+ * 32 bytes 2048 bytes
+ *
+ * Coding units are grouped into paging tiles. AFRC buffer dimensions must be aligned
+ * to a multiple of the paging tile dimensions.
+ * The dimensions of each paging tile depend on whether the buffer is optimised for
+ * scanline (SCAN layout) or rotated (ROT layout) access.
+ *
+ * Layout Paging Tile Width Paging Tile Height
+ * ------ ----------------- ------------------
+ * SCAN 16 coding units 4 coding units
+ * ROT 8 coding units 8 coding units
+ *
+ * The dimensions of each coding unit depend on the number of components
+ * in the compressed plane and whether the buffer is optimised for
+ * scanline (SCAN layout) or rotated (ROT layout) access.
+ *
+ * Number of Components in Plane Layout Coding Unit Width Coding Unit Height
+ * ----------------------------- --------- ----------------- ------------------
+ * 1 SCAN 16 samples 4 samples
+ * Example: 16x4 luma samples in a 'Y' plane
+ * 16x4 chroma 'V' values, in the 'V' plane of a fully-planar YUV buffer
+ * ----------------------------- --------- ----------------- ------------------
+ * 1 ROT 8 samples 8 samples
+ * Example: 8x8 luma samples in a 'Y' plane
+ * 8x8 chroma 'V' values, in the 'V' plane of a fully-planar YUV buffer
+ * ----------------------------- --------- ----------------- ------------------
+ * 2 DONT CARE 8 samples 4 samples
+ * Example: 8x4 chroma pairs in the 'UV' plane of a semi-planar YUV buffer
+ * ----------------------------- --------- ----------------- ------------------
+ * 3 DONT CARE 4 samples 4 samples
+ * Example: 4x4 pixels in an RGB buffer without alpha
+ * ----------------------------- --------- ----------------- ------------------
+ * 4 DONT CARE 4 samples 4 samples
+ * Example: 4x4 pixels in an RGB buffer with alpha
+ */
+
+#define DRM_FORMAT_MOD_ARM_TYPE_AFRC 0x02
+
+#define DRM_FORMAT_MOD_ARM_AFRC(__afrc_mode) \
+ DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_AFRC, __afrc_mode)
+
+/*
+ * AFRC coding unit size modifier.
+ *
+ * Indicates the number of bytes used to store each compressed coding unit for
+ * one or more planes in an AFRC encoded buffer. The coding unit size for chrominance
+ * is the same for both Cb and Cr, which may be stored in separate planes.
+ *
+ * AFRC_FORMAT_MOD_CU_SIZE_P0 indicates the number of bytes used to store
+ * each compressed coding unit in the first plane of the buffer. For RGBA buffers
+ * this is the only plane, while for semi-planar and fully-planar YUV buffers,
+ * this corresponds to the luma plane.
+ *
+ * AFRC_FORMAT_MOD_CU_SIZE_P12 indicates the number of bytes used to store
+ * each compressed coding unit in the second and third planes in the buffer.
+ * For semi-planar and fully-planar YUV buffers, this corresponds to the chroma plane(s).
+ *
+ * For single-plane buffers, AFRC_FORMAT_MOD_CU_SIZE_P0 must be specified
+ * and AFRC_FORMAT_MOD_CU_SIZE_P12 must be zero.
+ * For semi-planar and fully-planar buffers, both AFRC_FORMAT_MOD_CU_SIZE_P0 and
+ * AFRC_FORMAT_MOD_CU_SIZE_P12 must be specified.
+ */
+#define AFRC_FORMAT_MOD_CU_SIZE_MASK 0xf
+#define AFRC_FORMAT_MOD_CU_SIZE_16 (1ULL)
+#define AFRC_FORMAT_MOD_CU_SIZE_24 (2ULL)
+#define AFRC_FORMAT_MOD_CU_SIZE_32 (3ULL)
+
+#define AFRC_FORMAT_MOD_CU_SIZE_P0(__afrc_cu_size) (__afrc_cu_size)
+#define AFRC_FORMAT_MOD_CU_SIZE_P12(__afrc_cu_size) ((__afrc_cu_size) << 4)
+
+/*
+ * AFRC scanline memory layout.
+ *
+ * Indicates if the buffer uses the scanline-optimised layout
+ * for an AFRC encoded buffer, otherwise, it uses the rotation-optimised layout.
+ * The memory layout is the same for all planes.
+ */
+#define AFRC_FORMAT_MOD_LAYOUT_SCAN (1ULL << 8)
+
+/*
* Arm 16x16 Block U-Interleaved modifier
*
* This is used by Arm Mali Utgard and Midgard GPUs. It divides the image
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 9b6722d45f36..90c55383f1ee 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -312,16 +312,48 @@ struct drm_mode_set_plane {
__u32 src_w;
};
+/**
+ * struct drm_mode_get_plane - Get plane metadata.
+ *
+ * Userspace can perform a GETPLANE ioctl to retrieve information about a
+ * plane.
+ *
+ * To retrieve the number of formats supported, set @count_format_types to zero
+ * and call the ioctl. @count_format_types will be updated with the value.
+ *
+ * To retrieve these formats, allocate an array with the memory needed to store
+ * @count_format_types formats. Point @format_type_ptr to this array and call
+ * the ioctl again (with @count_format_types still set to the value returned in
+ * the first ioctl call).
+ */
struct drm_mode_get_plane {
+ /**
+ * @plane_id: Object ID of the plane whose information should be
+ * retrieved. Set by caller.
+ */
__u32 plane_id;
+ /** @crtc_id: Object ID of the current CRTC. */
__u32 crtc_id;
+ /** @fb_id: Object ID of the current fb. */
__u32 fb_id;
+ /**
+ * @possible_crtcs: Bitmask of CRTC's compatible with the plane. CRTC's
+ * are created and they receive an index, which corresponds to their
+ * position in the bitmask. Bit N corresponds to
+ * :ref:`CRTC index<crtc_index>` N.
+ */
__u32 possible_crtcs;
+ /** @gamma_size: Never used. */
__u32 gamma_size;
+ /** @count_format_types: Number of formats. */
__u32 count_format_types;
+ /**
+ * @format_type_ptr: Pointer to ``__u32`` array of formats that are
+ * supported by the plane. These formats do not require modifiers.
+ */
__u64 format_type_ptr;
};
@@ -509,22 +541,74 @@ struct drm_mode_get_connector {
*/
#define DRM_MODE_PROP_ATOMIC 0x80000000
+/**
+ * struct drm_mode_property_enum - Description for an enum/bitfield entry.
+ * @value: numeric value for this enum entry.
+ * @name: symbolic name for this enum entry.
+ *
+ * See struct drm_property_enum for details.
+ */
struct drm_mode_property_enum {
__u64 value;
char name[DRM_PROP_NAME_LEN];
};
+/**
+ * struct drm_mode_get_property - Get property metadata.
+ *
+ * User-space can perform a GETPROPERTY ioctl to retrieve information about a
+ * property. The same property may be attached to multiple objects, see
+ * "Modeset Base Object Abstraction".
+ *
+ * The meaning of the @values_ptr field changes depending on the property type.
+ * See &drm_property.flags for more details.
+ *
+ * The @enum_blob_ptr and @count_enum_blobs fields are only meaningful when the
+ * property has the type &DRM_MODE_PROP_ENUM or &DRM_MODE_PROP_BITMASK. For
+ * backwards compatibility, the kernel will always set @count_enum_blobs to
+ * zero when the property has the type &DRM_MODE_PROP_BLOB. User-space must
+ * ignore these two fields if the property has a different type.
+ *
+ * User-space is expected to retrieve values and enums by performing this ioctl
+ * at least twice: the first time to retrieve the number of elements, the
+ * second time to retrieve the elements themselves.
+ *
+ * To retrieve the number of elements, set @count_values and @count_enum_blobs
+ * to zero, then call the ioctl. @count_values will be updated with the number
+ * of elements. If the property has the type &DRM_MODE_PROP_ENUM or
+ * &DRM_MODE_PROP_BITMASK, @count_enum_blobs will be updated as well.
+ *
+ * To retrieve the elements themselves, allocate an array for @values_ptr and
+ * set @count_values to its capacity. If the property has the type
+ * &DRM_MODE_PROP_ENUM or &DRM_MODE_PROP_BITMASK, allocate an array for
+ * @enum_blob_ptr and set @count_enum_blobs to its capacity. Calling the ioctl
+ * again will fill the arrays.
+ */
struct drm_mode_get_property {
- __u64 values_ptr; /* values and blob lengths */
- __u64 enum_blob_ptr; /* enum and blob id ptrs */
+ /** @values_ptr: Pointer to a ``__u64`` array. */
+ __u64 values_ptr;
+ /** @enum_blob_ptr: Pointer to a struct drm_mode_property_enum array. */
+ __u64 enum_blob_ptr;
+ /**
+ * @prop_id: Object ID of the property which should be retrieved. Set
+ * by the caller.
+ */
__u32 prop_id;
+ /**
+ * @flags: ``DRM_MODE_PROP_*`` bitfield. See &drm_property.flags for
+ * a definition of the flags.
+ */
__u32 flags;
+ /**
+ * @name: Symbolic property name. User-space should use this field to
+ * recognize properties.
+ */
char name[DRM_PROP_NAME_LEN];
+ /** @count_values: Number of elements in @values_ptr. */
__u32 count_values;
- /* This is only used to count enum values, not blobs. The _blobs is
- * simply because of a historical reason, i.e. backwards compat. */
+ /** @count_enum_blobs: Number of elements in @enum_blob_ptr. */
__u32 count_enum_blobs;
};
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index c2c7759b7d2e..bde5860b3686 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -572,6 +572,15 @@ typedef struct drm_i915_irq_wait {
#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2)
#define I915_SCHEDULER_CAP_SEMAPHORES (1ul << 3)
#define I915_SCHEDULER_CAP_ENGINE_BUSY_STATS (1ul << 4)
+/*
+ * Indicates the 2k user priority levels are statically mapped into 3 buckets as
+ * follows:
+ *
+ * -1k to -1 Low priority
+ * 0 Normal priority
+ * 1 to 1k Highest priority
+ */
+#define I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP (1ul << 5)
#define I915_PARAM_HUC_STATUS 42
@@ -674,6 +683,9 @@ typedef struct drm_i915_irq_wait {
*/
#define I915_PARAM_HAS_EXEC_TIMELINE_FENCES 55
+/* Query if the kernel supports the I915_USERPTR_PROBE flag. */
+#define I915_PARAM_HAS_USERPTR_PROBE 56
+
/* Must be kept compact -- no holes and well documented */
typedef struct drm_i915_getparam {
@@ -849,45 +861,113 @@ struct drm_i915_gem_mmap_gtt {
__u64 offset;
};
+/**
+ * struct drm_i915_gem_mmap_offset - Retrieve an offset so we can mmap this buffer object.
+ *
+ * This struct is passed as argument to the `DRM_IOCTL_I915_GEM_MMAP_OFFSET` ioctl,
+ * and is used to retrieve the fake offset to mmap an object specified by &handle.
+ *
+ * The legacy way of using `DRM_IOCTL_I915_GEM_MMAP` is removed on gen12+.
+ * `DRM_IOCTL_I915_GEM_MMAP_GTT` is an older supported alias to this struct, but will behave
+ * as setting the &extensions to 0, and &flags to `I915_MMAP_OFFSET_GTT`.
+ */
struct drm_i915_gem_mmap_offset {
- /** Handle for the object being mapped. */
+ /** @handle: Handle for the object being mapped. */
__u32 handle;
+ /** @pad: Must be zero */
__u32 pad;
/**
- * Fake offset to use for subsequent mmap call
+ * @offset: The fake offset to use for subsequent mmap call
*
* This is a fixed-size type for 32/64 compatibility.
*/
__u64 offset;
/**
- * Flags for extended behaviour.
+ * @flags: Flags for extended behaviour.
+ *
+ * It is mandatory that one of the `MMAP_OFFSET` types
+ * should be included:
*
- * It is mandatory that one of the MMAP_OFFSET types
- * (GTT, WC, WB, UC, etc) should be included.
+ * - `I915_MMAP_OFFSET_GTT`: Use mmap with the object bound to GTT. (Write-Combined)
+ * - `I915_MMAP_OFFSET_WC`: Use Write-Combined caching.
+ * - `I915_MMAP_OFFSET_WB`: Use Write-Back caching.
+ * - `I915_MMAP_OFFSET_FIXED`: Use object placement to determine caching.
+ *
+ * On devices with local memory `I915_MMAP_OFFSET_FIXED` is the only valid
+ * type. On devices without local memory, this caching mode is invalid.
+ *
+ * As caching mode when specifying `I915_MMAP_OFFSET_FIXED`, WC or WB will
+ * be used, depending on the object placement on creation. WB will be used
+ * when the object can only exist in system memory, WC otherwise.
*/
__u64 flags;
-#define I915_MMAP_OFFSET_GTT 0
-#define I915_MMAP_OFFSET_WC 1
-#define I915_MMAP_OFFSET_WB 2
-#define I915_MMAP_OFFSET_UC 3
- /*
- * Zero-terminated chain of extensions.
+#define I915_MMAP_OFFSET_GTT 0
+#define I915_MMAP_OFFSET_WC 1
+#define I915_MMAP_OFFSET_WB 2
+#define I915_MMAP_OFFSET_UC 3
+#define I915_MMAP_OFFSET_FIXED 4
+
+ /**
+ * @extensions: Zero-terminated chain of extensions.
*
* No current extensions defined; mbz.
*/
__u64 extensions;
};
+/**
+ * struct drm_i915_gem_set_domain - Adjust the objects write or read domain, in
+ * preparation for accessing the pages via some CPU domain.
+ *
+ * Specifying a new write or read domain will flush the object out of the
+ * previous domain(if required), before then updating the objects domain
+ * tracking with the new domain.
+ *
+ * Note this might involve waiting for the object first if it is still active on
+ * the GPU.
+ *
+ * Supported values for @read_domains and @write_domain:
+ *
+ * - I915_GEM_DOMAIN_WC: Uncached write-combined domain
+ * - I915_GEM_DOMAIN_CPU: CPU cache domain
+ * - I915_GEM_DOMAIN_GTT: Mappable aperture domain
+ *
+ * All other domains are rejected.
+ *
+ * Note that for discrete, starting from DG1, this is no longer supported, and
+ * is instead rejected. On such platforms the CPU domain is effectively static,
+ * where we also only support a single &drm_i915_gem_mmap_offset cache mode,
+ * which can't be set explicitly and instead depends on the object placements,
+ * as per the below.
+ *
+ * Implicit caching rules, starting from DG1:
+ *
+ * - If any of the object placements (see &drm_i915_gem_create_ext_memory_regions)
+ * contain I915_MEMORY_CLASS_DEVICE then the object will be allocated and
+ * mapped as write-combined only.
+ *
+ * - Everything else is always allocated and mapped as write-back, with the
+ * guarantee that everything is also coherent with the GPU.
+ *
+ * Note that this is likely to change in the future again, where we might need
+ * more flexibility on future devices, so making this all explicit as part of a
+ * new &drm_i915_gem_create_ext extension is probable.
+ */
struct drm_i915_gem_set_domain {
- /** Handle for the object */
+ /** @handle: Handle for the object. */
__u32 handle;
- /** New read domains */
+ /** @read_domains: New read domains. */
__u32 read_domains;
- /** New write domain */
+ /**
+ * @write_domain: New write domain.
+ *
+ * Note that having something in the write domain implies it's in the
+ * read domain, and only that read domain.
+ */
__u32 write_domain;
};
@@ -1348,12 +1428,11 @@ struct drm_i915_gem_busy {
* reading from the object simultaneously.
*
* The value of each engine class is the same as specified in the
- * I915_CONTEXT_SET_ENGINES parameter and via perf, i.e.
+ * I915_CONTEXT_PARAM_ENGINES context parameter and via perf, i.e.
* I915_ENGINE_CLASS_RENDER, I915_ENGINE_CLASS_COPY, etc.
- * reported as active itself. Some hardware may have parallel
- * execution engines, e.g. multiple media engines, which are
- * mapped to the same class identifier and so are not separately
- * reported for busyness.
+ * Some hardware may have parallel execution engines, e.g. multiple
+ * media engines, which are mapped to the same class identifier and so
+ * are not separately reported for busyness.
*
* Caveat emptor:
* Only the boolean result of this query is reliable; that is whether
@@ -1364,43 +1443,79 @@ struct drm_i915_gem_busy {
};
/**
- * I915_CACHING_NONE
- *
- * GPU access is not coherent with cpu caches. Default for machines without an
- * LLC.
- */
-#define I915_CACHING_NONE 0
-/**
- * I915_CACHING_CACHED
- *
- * GPU access is coherent with cpu caches and furthermore the data is cached in
- * last-level caches shared between cpu cores and the gpu GT. Default on
- * machines with HAS_LLC.
+ * struct drm_i915_gem_caching - Set or get the caching for given object
+ * handle.
+ *
+ * Allow userspace to control the GTT caching bits for a given object when the
+ * object is later mapped through the ppGTT(or GGTT on older platforms lacking
+ * ppGTT support, or if the object is used for scanout). Note that this might
+ * require unbinding the object from the GTT first, if its current caching value
+ * doesn't match.
+ *
+ * Note that this all changes on discrete platforms, starting from DG1, the
+ * set/get caching is no longer supported, and is now rejected. Instead the CPU
+ * caching attributes(WB vs WC) will become an immutable creation time property
+ * for the object, along with the GTT caching level. For now we don't expose any
+ * new uAPI for this, instead on DG1 this is all implicit, although this largely
+ * shouldn't matter since DG1 is coherent by default(without any way of
+ * controlling it).
+ *
+ * Implicit caching rules, starting from DG1:
+ *
+ * - If any of the object placements (see &drm_i915_gem_create_ext_memory_regions)
+ * contain I915_MEMORY_CLASS_DEVICE then the object will be allocated and
+ * mapped as write-combined only.
+ *
+ * - Everything else is always allocated and mapped as write-back, with the
+ * guarantee that everything is also coherent with the GPU.
+ *
+ * Note that this is likely to change in the future again, where we might need
+ * more flexibility on future devices, so making this all explicit as part of a
+ * new &drm_i915_gem_create_ext extension is probable.
+ *
+ * Side note: Part of the reason for this is that changing the at-allocation-time CPU
+ * caching attributes for the pages might be required(and is expensive) if we
+ * need to then CPU map the pages later with different caching attributes. This
+ * inconsistent caching behaviour, while supported on x86, is not universally
+ * supported on other architectures. So for simplicity we opt for setting
+ * everything at creation time, whilst also making it immutable, on discrete
+ * platforms.
*/
-#define I915_CACHING_CACHED 1
-/**
- * I915_CACHING_DISPLAY
- *
- * Special GPU caching mode which is coherent with the scanout engines.
- * Transparently falls back to I915_CACHING_NONE on platforms where no special
- * cache mode (like write-through or gfdt flushing) is available. The kernel
- * automatically sets this mode when using a buffer as a scanout target.
- * Userspace can manually set this mode to avoid a costly stall and clflush in
- * the hotpath of drawing the first frame.
- */
-#define I915_CACHING_DISPLAY 2
-
struct drm_i915_gem_caching {
/**
- * Handle of the buffer to set/get the caching level of. */
+ * @handle: Handle of the buffer to set/get the caching level.
+ */
__u32 handle;
/**
- * Cacheing level to apply or return value
+ * @caching: The GTT caching level to apply or possible return value.
+ *
+ * The supported @caching values:
*
- * bits0-15 are for generic caching control (i.e. the above defined
- * values). bits16-31 are reserved for platform-specific variations
- * (e.g. l3$ caching on gen7). */
+ * I915_CACHING_NONE:
+ *
+ * GPU access is not coherent with CPU caches. Default for machines
+ * without an LLC. This means manual flushing might be needed, if we
+ * want GPU access to be coherent.
+ *
+ * I915_CACHING_CACHED:
+ *
+ * GPU access is coherent with CPU caches and furthermore the data is
+ * cached in last-level caches shared between CPU cores and the GPU GT.
+ *
+ * I915_CACHING_DISPLAY:
+ *
+ * Special GPU caching mode which is coherent with the scanout engines.
+ * Transparently falls back to I915_CACHING_NONE on platforms where no
+ * special cache mode (like write-through or gfdt flushing) is
+ * available. The kernel automatically sets this mode when using a
+ * buffer as a scanout target. Userspace can manually set this mode to
+ * avoid a costly stall and clflush in the hotpath of drawing the first
+ * frame.
+ */
+#define I915_CACHING_NONE 0
+#define I915_CACHING_CACHED 1
+#define I915_CACHING_DISPLAY 2
__u32 caching;
};
@@ -1639,6 +1754,10 @@ struct drm_i915_gem_context_param {
__u32 size;
__u64 param;
#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
+/* I915_CONTEXT_PARAM_NO_ZEROMAP has been removed. On the off chance
+ * someone somewhere has attempted to use it, never re-use this context
+ * param number.
+ */
#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4
@@ -1723,24 +1842,8 @@ struct drm_i915_gem_context_param {
*/
#define I915_CONTEXT_PARAM_PERSISTENCE 0xb
-/*
- * I915_CONTEXT_PARAM_RINGSIZE:
- *
- * Sets the size of the CS ringbuffer to use for logical ring contexts. This
- * applies a limit of how many batches can be queued to HW before the caller
- * is blocked due to lack of space for more commands.
- *
- * Only reliably possible to be set prior to first use, i.e. during
- * construction. At any later point, the current execution must be flushed as
- * the ring can only be changed while the context is idle. Note, the ringsize
- * can be specified as a constructor property, see
- * I915_CONTEXT_CREATE_EXT_SETPARAM, but can also be set later if required.
- *
- * Only applies to the current set of engine and lost when those engines
- * are replaced by a new mapping (see I915_CONTEXT_PARAM_ENGINES).
- *
- * Must be between 4 - 512 KiB, in intervals of page size [4 KiB].
- * Default is 16 KiB.
+/* This API has been removed. On the off chance someone somewhere has
+ * attempted to use it, never re-use this context param number.
*/
#define I915_CONTEXT_PARAM_RINGSIZE 0xc
/* Must be kept compact -- no holes and well documented */
@@ -1807,6 +1910,69 @@ struct drm_i915_gem_context_param_sseu {
__u32 rsvd;
};
+/**
+ * DOC: Virtual Engine uAPI
+ *
+ * Virtual engine is a concept where userspace is able to configure a set of
+ * physical engines, submit a batch buffer, and let the driver execute it on any
+ * engine from the set as it sees fit.
+ *
+ * This is primarily useful on parts which have multiple instances of a same
+ * class engine, like for example GT3+ Skylake parts with their two VCS engines.
+ *
+ * For instance userspace can enumerate all engines of a certain class using the
+ * previously described `Engine Discovery uAPI`_. After that userspace can
+ * create a GEM context with a placeholder slot for the virtual engine (using
+ * `I915_ENGINE_CLASS_INVALID` and `I915_ENGINE_CLASS_INVALID_NONE` for class
+ * and instance respectively) and finally using the
+ * `I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE` extension place a virtual engine in
+ * the same reserved slot.
+ *
+ * Example of creating a virtual engine and submitting a batch buffer to it:
+ *
+ * .. code-block:: C
+ *
+ * I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(virtual, 2) = {
+ * .base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE,
+ * .engine_index = 0, // Place this virtual engine into engine map slot 0
+ * .num_siblings = 2,
+ * .engines = { { I915_ENGINE_CLASS_VIDEO, 0 },
+ * { I915_ENGINE_CLASS_VIDEO, 1 }, },
+ * };
+ * I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 1) = {
+ * .engines = { { I915_ENGINE_CLASS_INVALID,
+ * I915_ENGINE_CLASS_INVALID_NONE } },
+ * .extensions = to_user_pointer(&virtual), // Chains after load_balance extension
+ * };
+ * struct drm_i915_gem_context_create_ext_setparam p_engines = {
+ * .base = {
+ * .name = I915_CONTEXT_CREATE_EXT_SETPARAM,
+ * },
+ * .param = {
+ * .param = I915_CONTEXT_PARAM_ENGINES,
+ * .value = to_user_pointer(&engines),
+ * .size = sizeof(engines),
+ * },
+ * };
+ * struct drm_i915_gem_context_create_ext create = {
+ * .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
+ * .extensions = to_user_pointer(&p_engines);
+ * };
+ *
+ * ctx_id = gem_context_create_ext(drm_fd, &create);
+ *
+ * // Now we have created a GEM context with its engine map containing a
+ * // single virtual engine. Submissions to this slot can go either to
+ * // vcs0 or vcs1, depending on the load balancing algorithm used inside
+ * // the driver. The load balancing is dynamic from one batch buffer to
+ * // another and transparent to userspace.
+ *
+ * ...
+ * execbuf.rsvd1 = ctx_id;
+ * execbuf.flags = 0; // Submits to index 0 which is the virtual engine
+ * gem_execbuf(drm_fd, &execbuf);
+ */
+
/*
* i915_context_engines_load_balance:
*
@@ -1883,6 +2049,61 @@ struct i915_context_engines_bond {
struct i915_engine_class_instance engines[N__]; \
} __attribute__((packed)) name__
+/**
+ * DOC: Context Engine Map uAPI
+ *
+ * Context engine map is a new way of addressing engines when submitting batch-
+ * buffers, replacing the existing way of using identifiers like `I915_EXEC_BLT`
+ * inside the flags field of `struct drm_i915_gem_execbuffer2`.
+ *
+ * To use it created GEM contexts need to be configured with a list of engines
+ * the user is intending to submit to. This is accomplished using the
+ * `I915_CONTEXT_PARAM_ENGINES` parameter and `struct
+ * i915_context_param_engines`.
+ *
+ * For such contexts the `I915_EXEC_RING_MASK` field becomes an index into the
+ * configured map.
+ *
+ * Example of creating such context and submitting against it:
+ *
+ * .. code-block:: C
+ *
+ * I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 2) = {
+ * .engines = { { I915_ENGINE_CLASS_RENDER, 0 },
+ * { I915_ENGINE_CLASS_COPY, 0 } }
+ * };
+ * struct drm_i915_gem_context_create_ext_setparam p_engines = {
+ * .base = {
+ * .name = I915_CONTEXT_CREATE_EXT_SETPARAM,
+ * },
+ * .param = {
+ * .param = I915_CONTEXT_PARAM_ENGINES,
+ * .value = to_user_pointer(&engines),
+ * .size = sizeof(engines),
+ * },
+ * };
+ * struct drm_i915_gem_context_create_ext create = {
+ * .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
+ * .extensions = to_user_pointer(&p_engines);
+ * };
+ *
+ * ctx_id = gem_context_create_ext(drm_fd, &create);
+ *
+ * // We have now created a GEM context with two engines in the map:
+ * // Index 0 points to rcs0 while index 1 points to bcs0. Other engines
+ * // will not be accessible from this context.
+ *
+ * ...
+ * execbuf.rsvd1 = ctx_id;
+ * execbuf.flags = 0; // Submits to index 0, which is rcs0 for this context
+ * gem_execbuf(drm_fd, &execbuf);
+ *
+ * ...
+ * execbuf.rsvd1 = ctx_id;
+ * execbuf.flags = 1; // Submits to index 0, which is bcs0 for this context
+ * gem_execbuf(drm_fd, &execbuf);
+ */
+
struct i915_context_param_engines {
__u64 extensions; /* linked chain of extension blocks, 0 terminates */
#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0 /* see i915_context_engines_load_balance */
@@ -1901,20 +2122,10 @@ struct drm_i915_gem_context_create_ext_setparam {
struct drm_i915_gem_context_param param;
};
-struct drm_i915_gem_context_create_ext_clone {
+/* This API has been removed. On the off chance someone somewhere has
+ * attempted to use it, never re-use this extension number.
+ */
#define I915_CONTEXT_CREATE_EXT_CLONE 1
- struct i915_user_extension base;
- __u32 clone_id;
- __u32 flags;
-#define I915_CONTEXT_CLONE_ENGINES (1u << 0)
-#define I915_CONTEXT_CLONE_FLAGS (1u << 1)
-#define I915_CONTEXT_CLONE_SCHEDATTR (1u << 2)
-#define I915_CONTEXT_CLONE_SSEU (1u << 3)
-#define I915_CONTEXT_CLONE_TIMELINE (1u << 4)
-#define I915_CONTEXT_CLONE_VM (1u << 5)
-#define I915_CONTEXT_CLONE_UNKNOWN -(I915_CONTEXT_CLONE_VM << 1)
- __u64 rsvd;
-};
struct drm_i915_gem_context_destroy {
__u32 ctx_id;
@@ -1986,14 +2197,69 @@ struct drm_i915_reset_stats {
__u32 pad;
};
+/**
+ * struct drm_i915_gem_userptr - Create GEM object from user allocated memory.
+ *
+ * Userptr objects have several restrictions on what ioctls can be used with the
+ * object handle.
+ */
struct drm_i915_gem_userptr {
+ /**
+ * @user_ptr: The pointer to the allocated memory.
+ *
+ * Needs to be aligned to PAGE_SIZE.
+ */
__u64 user_ptr;
+
+ /**
+ * @user_size:
+ *
+ * The size in bytes for the allocated memory. This will also become the
+ * object size.
+ *
+ * Needs to be aligned to PAGE_SIZE, and should be at least PAGE_SIZE,
+ * or larger.
+ */
__u64 user_size;
+
+ /**
+ * @flags:
+ *
+ * Supported flags:
+ *
+ * I915_USERPTR_READ_ONLY:
+ *
+ * Mark the object as readonly, this also means GPU access can only be
+ * readonly. This is only supported on HW which supports readonly access
+ * through the GTT. If the HW can't support readonly access, an error is
+ * returned.
+ *
+ * I915_USERPTR_PROBE:
+ *
+ * Probe the provided @user_ptr range and validate that the @user_ptr is
+ * indeed pointing to normal memory and that the range is also valid.
+ * For example if some garbage address is given to the kernel, then this
+ * should complain.
+ *
+ * Returns -EFAULT if the probe failed.
+ *
+ * Note that this doesn't populate the backing pages, and also doesn't
+ * guarantee that the object will remain valid when the object is
+ * eventually used.
+ *
+ * The kernel supports this feature if I915_PARAM_HAS_USERPTR_PROBE
+ * returns a non-zero value.
+ *
+ * I915_USERPTR_UNSYNCHRONIZED:
+ *
+ * NOT USED. Setting this flag will result in an error.
+ */
__u32 flags;
#define I915_USERPTR_READ_ONLY 0x1
+#define I915_USERPTR_PROBE 0x2
#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
/**
- * Returned handle for the object.
+ * @handle: Returned handle for the object.
*
* Object handles are nonzero.
*/
@@ -2377,6 +2643,76 @@ struct drm_i915_query_topology_info {
};
/**
+ * DOC: Engine Discovery uAPI
+ *
+ * Engine discovery uAPI is a way of enumerating physical engines present in a
+ * GPU associated with an open i915 DRM file descriptor. This supersedes the old
+ * way of using `DRM_IOCTL_I915_GETPARAM` and engine identifiers like
+ * `I915_PARAM_HAS_BLT`.
+ *
+ * The need for this interface came starting with Icelake and newer GPUs, which
+ * started to establish a pattern of having multiple engines of a same class,
+ * where not all instances were always completely functionally equivalent.
+ *
+ * Entry point for this uapi is `DRM_IOCTL_I915_QUERY` with the
+ * `DRM_I915_QUERY_ENGINE_INFO` as the queried item id.
+ *
+ * Example for getting the list of engines:
+ *
+ * .. code-block:: C
+ *
+ * struct drm_i915_query_engine_info *info;
+ * struct drm_i915_query_item item = {
+ * .query_id = DRM_I915_QUERY_ENGINE_INFO;
+ * };
+ * struct drm_i915_query query = {
+ * .num_items = 1,
+ * .items_ptr = (uintptr_t)&item,
+ * };
+ * int err, i;
+ *
+ * // First query the size of the blob we need, this needs to be large
+ * // enough to hold our array of engines. The kernel will fill out the
+ * // item.length for us, which is the number of bytes we need.
+ * //
+ * // Alternatively a large buffer can be allocated straight away enabling
+ * // querying in one pass, in which case item.length should contain the
+ * // length of the provided buffer.
+ * err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
+ * if (err) ...
+ *
+ * info = calloc(1, item.length);
+ * // Now that we allocated the required number of bytes, we call the ioctl
+ * // again, this time with the data_ptr pointing to our newly allocated
+ * // blob, which the kernel can then populate with info on all engines.
+ * item.data_ptr = (uintptr_t)&info,
+ *
+ * err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
+ * if (err) ...
+ *
+ * // We can now access each engine in the array
+ * for (i = 0; i < info->num_engines; i++) {
+ * struct drm_i915_engine_info einfo = info->engines[i];
+ * u16 class = einfo.engine.class;
+ * u16 instance = einfo.engine.instance;
+ * ....
+ * }
+ *
+ * free(info);
+ *
+ * Each of the enumerated engines, apart from being defined by its class and
+ * instance (see `struct i915_engine_class_instance`), also can have flags and
+ * capabilities defined as documented in i915_drm.h.
+ *
+ * For instance video engines which support HEVC encoding will have the
+ * `I915_VIDEO_CLASS_CAPABILITY_HEVC` capability bit set.
+ *
+ * Engine discovery only fully comes to its own when combined with the new way
+ * of addressing engines when submitting batch buffers using contexts with
+ * engine maps configured.
+ */
+
+/**
* struct drm_i915_engine_info
*
* Describes one engine and it's capabilities as known to the driver.
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index f075851021c3..6b8fffc28a50 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -73,11 +73,19 @@ struct drm_msm_timespec {
#define MSM_PARAM_MAX_FREQ 0x04
#define MSM_PARAM_TIMESTAMP 0x05
#define MSM_PARAM_GMEM_BASE 0x06
-#define MSM_PARAM_NR_RINGS 0x07
+#define MSM_PARAM_PRIORITIES 0x07 /* The # of priority levels */
#define MSM_PARAM_PP_PGTABLE 0x08 /* => 1 for per-process pagetables, else 0 */
#define MSM_PARAM_FAULTS 0x09
#define MSM_PARAM_SUSPENDS 0x0a
+/* For backwards compat. The original support for preemption was based on
+ * a single ring per priority level so # of priority levels equals the #
+ * of rings. With drm/scheduler providing additional levels of priority,
+ * the number of priorities is greater than the # of rings. The param is
+ * renamed to better reflect this.
+ */
+#define MSM_PARAM_NR_RINGS MSM_PARAM_PRIORITIES
+
struct drm_msm_param {
__u32 pipe; /* in, MSM_PIPE_x */
__u32 param; /* in, MSM_PARAM_x */
@@ -304,6 +312,10 @@ struct drm_msm_gem_madvise {
#define MSM_SUBMITQUEUE_FLAGS (0)
+/*
+ * The submitqueue priority should be between 0 and MSM_PARAM_PRIORITIES-1,
+ * a lower numeric value is higher priority.
+ */
struct drm_msm_submitqueue {
__u32 flags; /* in, MSM_SUBMITQUEUE_x */
__u32 prio; /* in, Priority level */
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
index c4df3c3668b3..94cfc306d50a 100644
--- a/include/uapi/drm/tegra_drm.h
+++ b/include/uapi/drm/tegra_drm.h
@@ -1,24 +1,5 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
+/* SPDX-License-Identifier: MIT */
+/* Copyright (c) 2012-2020 NVIDIA Corporation */
#ifndef _UAPI_TEGRA_DRM_H_
#define _UAPI_TEGRA_DRM_H_
@@ -29,6 +10,8 @@
extern "C" {
#endif
+/* Tegra DRM legacy UAPI. Only enabled with STAGING */
+
#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0)
#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
@@ -649,8 +632,8 @@ struct drm_tegra_gem_get_flags {
#define DRM_TEGRA_SYNCPT_READ 0x02
#define DRM_TEGRA_SYNCPT_INCR 0x03
#define DRM_TEGRA_SYNCPT_WAIT 0x04
-#define DRM_TEGRA_OPEN_CHANNEL 0x05
-#define DRM_TEGRA_CLOSE_CHANNEL 0x06
+#define DRM_TEGRA_OPEN_CHANNEL 0x05
+#define DRM_TEGRA_CLOSE_CHANNEL 0x06
#define DRM_TEGRA_GET_SYNCPT 0x07
#define DRM_TEGRA_SUBMIT 0x08
#define DRM_TEGRA_GET_SYNCPT_BASE 0x09
@@ -674,6 +657,402 @@ struct drm_tegra_gem_get_flags {
#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags)
#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags)
+/* New Tegra DRM UAPI */
+
+/*
+ * Reported by the driver in the `capabilities` field.
+ *
+ * DRM_TEGRA_CHANNEL_CAP_CACHE_COHERENT: If set, the engine is cache coherent
+ * with regard to the system memory.
+ */
+#define DRM_TEGRA_CHANNEL_CAP_CACHE_COHERENT (1 << 0)
+
+struct drm_tegra_channel_open {
+ /**
+ * @host1x_class: [in]
+ *
+ * Host1x class of the engine that will be programmed using this
+ * channel.
+ */
+ __u32 host1x_class;
+
+ /**
+ * @flags: [in]
+ *
+ * Flags.
+ */
+ __u32 flags;
+
+ /**
+ * @context: [out]
+ *
+ * Opaque identifier corresponding to the opened channel.
+ */
+ __u32 context;
+
+ /**
+ * @version: [out]
+ *
+ * Version of the engine hardware. This can be used by userspace
+ * to determine how the engine needs to be programmed.
+ */
+ __u32 version;
+
+ /**
+ * @capabilities: [out]
+ *
+ * Flags describing the hardware capabilities.
+ */
+ __u32 capabilities;
+ __u32 padding;
+};
+
+struct drm_tegra_channel_close {
+ /**
+ * @context: [in]
+ *
+ * Identifier of the channel to close.
+ */
+ __u32 context;
+ __u32 padding;
+};
+
+/*
+ * Mapping flags that can be used to influence how the mapping is created.
+ *
+ * DRM_TEGRA_CHANNEL_MAP_READ: create mapping that allows HW read access
+ * DRM_TEGRA_CHANNEL_MAP_WRITE: create mapping that allows HW write access
+ */
+#define DRM_TEGRA_CHANNEL_MAP_READ (1 << 0)
+#define DRM_TEGRA_CHANNEL_MAP_WRITE (1 << 1)
+#define DRM_TEGRA_CHANNEL_MAP_READ_WRITE (DRM_TEGRA_CHANNEL_MAP_READ | \
+ DRM_TEGRA_CHANNEL_MAP_WRITE)
+
+struct drm_tegra_channel_map {
+ /**
+ * @context: [in]
+ *
+ * Identifier of the channel to which make memory available for.
+ */
+ __u32 context;
+
+ /**
+ * @handle: [in]
+ *
+ * GEM handle of the memory to map.
+ */
+ __u32 handle;
+
+ /**
+ * @flags: [in]
+ *
+ * Flags.
+ */
+ __u32 flags;
+
+ /**
+ * @mapping: [out]
+ *
+ * Identifier corresponding to the mapping, to be used for
+ * relocations or unmapping later.
+ */
+ __u32 mapping;
+};
+
+struct drm_tegra_channel_unmap {
+ /**
+ * @context: [in]
+ *
+ * Channel identifier of the channel to unmap memory from.
+ */
+ __u32 context;
+
+ /**
+ * @mapping: [in]
+ *
+ * Mapping identifier of the memory mapping to unmap.
+ */
+ __u32 mapping;
+};
+
+/* Submission */
+
+/**
+ * Specify that bit 39 of the patched-in address should be set to switch
+ * swizzling between Tegra and non-Tegra sector layout on systems that store
+ * surfaces in system memory in non-Tegra sector layout.
+ */
+#define DRM_TEGRA_SUBMIT_RELOC_SECTOR_LAYOUT (1 << 0)
+
+struct drm_tegra_submit_buf {
+ /**
+ * @mapping: [in]
+ *
+ * Identifier of the mapping to use in the submission.
+ */
+ __u32 mapping;
+
+ /**
+ * @flags: [in]
+ *
+ * Flags.
+ */
+ __u32 flags;
+
+ /**
+ * Information for relocation patching.
+ */
+ struct {
+ /**
+ * @target_offset: [in]
+ *
+ * Offset from the start of the mapping of the data whose
+ * address is to be patched into the gather.
+ */
+ __u64 target_offset;
+
+ /**
+ * @gather_offset_words: [in]
+ *
+ * Offset in words from the start of the gather data to
+ * where the address should be patched into.
+ */
+ __u32 gather_offset_words;
+
+ /**
+ * @shift: [in]
+ *
+ * Number of bits the address should be shifted right before
+ * patching in.
+ */
+ __u32 shift;
+ } reloc;
+};
+
+/**
+ * Execute `words` words of Host1x opcodes specified in the `gather_data_ptr`
+ * buffer. Each GATHER_UPTR command uses successive words from the buffer.
+ */
+#define DRM_TEGRA_SUBMIT_CMD_GATHER_UPTR 0
+/**
+ * Wait for a syncpoint to reach a value before continuing with further
+ * commands.
+ */
+#define DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT 1
+/**
+ * Wait for a syncpoint to reach a value before continuing with further
+ * commands. The threshold is calculated relative to the start of the job.
+ */
+#define DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT_RELATIVE 2
+
+struct drm_tegra_submit_cmd_gather_uptr {
+ __u32 words;
+ __u32 reserved[3];
+};
+
+struct drm_tegra_submit_cmd_wait_syncpt {
+ __u32 id;
+ __u32 value;
+ __u32 reserved[2];
+};
+
+struct drm_tegra_submit_cmd {
+ /**
+ * @type: [in]
+ *
+ * Command type to execute. One of the DRM_TEGRA_SUBMIT_CMD*
+ * defines.
+ */
+ __u32 type;
+
+ /**
+ * @flags: [in]
+ *
+ * Flags.
+ */
+ __u32 flags;
+
+ union {
+ struct drm_tegra_submit_cmd_gather_uptr gather_uptr;
+ struct drm_tegra_submit_cmd_wait_syncpt wait_syncpt;
+ __u32 reserved[4];
+ };
+};
+
+struct drm_tegra_submit_syncpt {
+ /**
+ * @id: [in]
+ *
+ * ID of the syncpoint that the job will increment.
+ */
+ __u32 id;
+
+ /**
+ * @flags: [in]
+ *
+ * Flags.
+ */
+ __u32 flags;
+
+ /**
+ * @increments: [in]
+ *
+ * Number of times the job will increment this syncpoint.
+ */
+ __u32 increments;
+
+ /**
+ * @value: [out]
+ *
+ * Value the syncpoint will have once the job has completed all
+ * its specified syncpoint increments.
+ *
+ * Note that the kernel may increment the syncpoint before or after
+ * the job. These increments are not reflected in this field.
+ *
+ * If the job hangs or times out, not all of the increments may
+ * get executed.
+ */
+ __u32 value;
+};
+
+struct drm_tegra_channel_submit {
+ /**
+ * @context: [in]
+ *
+ * Identifier of the channel to submit this job to.
+ */
+ __u32 context;
+
+ /**
+ * @num_bufs: [in]
+ *
+ * Number of elements in the `bufs_ptr` array.
+ */
+ __u32 num_bufs;
+
+ /**
+ * @num_cmds: [in]
+ *
+ * Number of elements in the `cmds_ptr` array.
+ */
+ __u32 num_cmds;
+
+ /**
+ * @gather_data_words: [in]
+ *
+ * Number of 32-bit words in the `gather_data_ptr` array.
+ */
+ __u32 gather_data_words;
+
+ /**
+ * @bufs_ptr: [in]
+ *
+ * Pointer to an array of drm_tegra_submit_buf structures.
+ */
+ __u64 bufs_ptr;
+
+ /**
+ * @cmds_ptr: [in]
+ *
+ * Pointer to an array of drm_tegra_submit_cmd structures.
+ */
+ __u64 cmds_ptr;
+
+ /**
+ * @gather_data_ptr: [in]
+ *
+ * Pointer to an array of Host1x opcodes to be used by GATHER_UPTR
+ * commands.
+ */
+ __u64 gather_data_ptr;
+
+ /**
+ * @syncobj_in: [in]
+ *
+ * Handle for DRM syncobj that will be waited before submission.
+ * Ignored if zero.
+ */
+ __u32 syncobj_in;
+
+ /**
+ * @syncobj_out: [in]
+ *
+ * Handle for DRM syncobj that will have its fence replaced with
+ * the job's completion fence. Ignored if zero.
+ */
+ __u32 syncobj_out;
+
+ /**
+ * @syncpt_incr: [in,out]
+ *
+ * Information about the syncpoint the job will increment.
+ */
+ struct drm_tegra_submit_syncpt syncpt;
+};
+
+struct drm_tegra_syncpoint_allocate {
+ /**
+ * @id: [out]
+ *
+ * ID of allocated syncpoint.
+ */
+ __u32 id;
+ __u32 padding;
+};
+
+struct drm_tegra_syncpoint_free {
+ /**
+ * @id: [in]
+ *
+ * ID of syncpoint to free.
+ */
+ __u32 id;
+ __u32 padding;
+};
+
+struct drm_tegra_syncpoint_wait {
+ /**
+ * @timeout: [in]
+ *
+ * Absolute timestamp at which the wait will time out.
+ */
+ __s64 timeout_ns;
+
+ /**
+ * @id: [in]
+ *
+ * ID of syncpoint to wait on.
+ */
+ __u32 id;
+
+ /**
+ * @threshold: [in]
+ *
+ * Threshold to wait for.
+ */
+ __u32 threshold;
+
+ /**
+ * @value: [out]
+ *
+ * Value of the syncpoint upon wait completion.
+ */
+ __u32 value;
+
+ __u32 padding;
+};
+
+#define DRM_IOCTL_TEGRA_CHANNEL_OPEN DRM_IOWR(DRM_COMMAND_BASE + 0x10, struct drm_tegra_channel_open)
+#define DRM_IOCTL_TEGRA_CHANNEL_CLOSE DRM_IOWR(DRM_COMMAND_BASE + 0x11, struct drm_tegra_channel_close)
+#define DRM_IOCTL_TEGRA_CHANNEL_MAP DRM_IOWR(DRM_COMMAND_BASE + 0x12, struct drm_tegra_channel_map)
+#define DRM_IOCTL_TEGRA_CHANNEL_UNMAP DRM_IOWR(DRM_COMMAND_BASE + 0x13, struct drm_tegra_channel_unmap)
+#define DRM_IOCTL_TEGRA_CHANNEL_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + 0x14, struct drm_tegra_channel_submit)
+
+#define DRM_IOCTL_TEGRA_SYNCPOINT_ALLOCATE DRM_IOWR(DRM_COMMAND_BASE + 0x20, struct drm_tegra_syncpoint_allocate)
+#define DRM_IOCTL_TEGRA_SYNCPOINT_FREE DRM_IOWR(DRM_COMMAND_BASE + 0x21, struct drm_tegra_syncpoint_free)
+#define DRM_IOCTL_TEGRA_SYNCPOINT_WAIT DRM_IOWR(DRM_COMMAND_BASE + 0x22, struct drm_tegra_syncpoint_wait)
+
#if defined(__cplusplus)
}
#endif
diff --git a/include/uapi/drm/v3d_drm.h b/include/uapi/drm/v3d_drm.h
index 1ce746e228d9..4104f22fb3d3 100644
--- a/include/uapi/drm/v3d_drm.h
+++ b/include/uapi/drm/v3d_drm.h
@@ -38,6 +38,9 @@ extern "C" {
#define DRM_V3D_GET_BO_OFFSET 0x05
#define DRM_V3D_SUBMIT_TFU 0x06
#define DRM_V3D_SUBMIT_CSD 0x07
+#define DRM_V3D_PERFMON_CREATE 0x08
+#define DRM_V3D_PERFMON_DESTROY 0x09
+#define DRM_V3D_PERFMON_GET_VALUES 0x0a
#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
@@ -47,6 +50,12 @@ extern "C" {
#define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
#define DRM_IOCTL_V3D_SUBMIT_CSD DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
+#define DRM_IOCTL_V3D_PERFMON_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_CREATE, \
+ struct drm_v3d_perfmon_create)
+#define DRM_IOCTL_V3D_PERFMON_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_DESTROY, \
+ struct drm_v3d_perfmon_destroy)
+#define DRM_IOCTL_V3D_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_VALUES, \
+ struct drm_v3d_perfmon_get_values)
#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
@@ -127,6 +136,11 @@ struct drm_v3d_submit_cl {
__u32 bo_handle_count;
__u32 flags;
+
+ /* ID of the perfmon to attach to this job. 0 means no perfmon. */
+ __u32 perfmon_id;
+
+ __u32 pad;
};
/**
@@ -195,6 +209,7 @@ enum drm_v3d_param {
DRM_V3D_PARAM_SUPPORTS_TFU,
DRM_V3D_PARAM_SUPPORTS_CSD,
DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
+ DRM_V3D_PARAM_SUPPORTS_PERFMON,
};
struct drm_v3d_get_param {
@@ -258,6 +273,127 @@ struct drm_v3d_submit_csd {
__u32 in_sync;
/* Sync object to signal when the CSD job is done. */
__u32 out_sync;
+
+ /* ID of the perfmon to attach to this job. 0 means no perfmon. */
+ __u32 perfmon_id;
+};
+
+enum {
+ V3D_PERFCNT_FEP_VALID_PRIMTS_NO_PIXELS,
+ V3D_PERFCNT_FEP_VALID_PRIMS,
+ V3D_PERFCNT_FEP_EZ_NFCLIP_QUADS,
+ V3D_PERFCNT_FEP_VALID_QUADS,
+ V3D_PERFCNT_TLB_QUADS_STENCIL_FAIL,
+ V3D_PERFCNT_TLB_QUADS_STENCILZ_FAIL,
+ V3D_PERFCNT_TLB_QUADS_STENCILZ_PASS,
+ V3D_PERFCNT_TLB_QUADS_ZERO_COV,
+ V3D_PERFCNT_TLB_QUADS_NONZERO_COV,
+ V3D_PERFCNT_TLB_QUADS_WRITTEN,
+ V3D_PERFCNT_PTB_PRIM_VIEWPOINT_DISCARD,
+ V3D_PERFCNT_PTB_PRIM_CLIP,
+ V3D_PERFCNT_PTB_PRIM_REV,
+ V3D_PERFCNT_QPU_IDLE_CYCLES,
+ V3D_PERFCNT_QPU_ACTIVE_CYCLES_VERTEX_COORD_USER,
+ V3D_PERFCNT_QPU_ACTIVE_CYCLES_FRAG,
+ V3D_PERFCNT_QPU_CYCLES_VALID_INSTR,
+ V3D_PERFCNT_QPU_CYCLES_TMU_STALL,
+ V3D_PERFCNT_QPU_CYCLES_SCOREBOARD_STALL,
+ V3D_PERFCNT_QPU_CYCLES_VARYINGS_STALL,
+ V3D_PERFCNT_QPU_IC_HIT,
+ V3D_PERFCNT_QPU_IC_MISS,
+ V3D_PERFCNT_QPU_UC_HIT,
+ V3D_PERFCNT_QPU_UC_MISS,
+ V3D_PERFCNT_TMU_TCACHE_ACCESS,
+ V3D_PERFCNT_TMU_TCACHE_MISS,
+ V3D_PERFCNT_VPM_VDW_STALL,
+ V3D_PERFCNT_VPM_VCD_STALL,
+ V3D_PERFCNT_BIN_ACTIVE,
+ V3D_PERFCNT_RDR_ACTIVE,
+ V3D_PERFCNT_L2T_HITS,
+ V3D_PERFCNT_L2T_MISSES,
+ V3D_PERFCNT_CYCLE_COUNT,
+ V3D_PERFCNT_QPU_CYCLES_STALLED_VERTEX_COORD_USER,
+ V3D_PERFCNT_QPU_CYCLES_STALLED_FRAGMENT,
+ V3D_PERFCNT_PTB_PRIMS_BINNED,
+ V3D_PERFCNT_AXI_WRITES_WATCH_0,
+ V3D_PERFCNT_AXI_READS_WATCH_0,
+ V3D_PERFCNT_AXI_WRITE_STALLS_WATCH_0,
+ V3D_PERFCNT_AXI_READ_STALLS_WATCH_0,
+ V3D_PERFCNT_AXI_WRITE_BYTES_WATCH_0,
+ V3D_PERFCNT_AXI_READ_BYTES_WATCH_0,
+ V3D_PERFCNT_AXI_WRITES_WATCH_1,
+ V3D_PERFCNT_AXI_READS_WATCH_1,
+ V3D_PERFCNT_AXI_WRITE_STALLS_WATCH_1,
+ V3D_PERFCNT_AXI_READ_STALLS_WATCH_1,
+ V3D_PERFCNT_AXI_WRITE_BYTES_WATCH_1,
+ V3D_PERFCNT_AXI_READ_BYTES_WATCH_1,
+ V3D_PERFCNT_TLB_PARTIAL_QUADS,
+ V3D_PERFCNT_TMU_CONFIG_ACCESSES,
+ V3D_PERFCNT_L2T_NO_ID_STALL,
+ V3D_PERFCNT_L2T_COM_QUE_STALL,
+ V3D_PERFCNT_L2T_TMU_WRITES,
+ V3D_PERFCNT_TMU_ACTIVE_CYCLES,
+ V3D_PERFCNT_TMU_STALLED_CYCLES,
+ V3D_PERFCNT_CLE_ACTIVE,
+ V3D_PERFCNT_L2T_TMU_READS,
+ V3D_PERFCNT_L2T_CLE_READS,
+ V3D_PERFCNT_L2T_VCD_READS,
+ V3D_PERFCNT_L2T_TMUCFG_READS,
+ V3D_PERFCNT_L2T_SLC0_READS,
+ V3D_PERFCNT_L2T_SLC1_READS,
+ V3D_PERFCNT_L2T_SLC2_READS,
+ V3D_PERFCNT_L2T_TMU_W_MISSES,
+ V3D_PERFCNT_L2T_TMU_R_MISSES,
+ V3D_PERFCNT_L2T_CLE_MISSES,
+ V3D_PERFCNT_L2T_VCD_MISSES,
+ V3D_PERFCNT_L2T_TMUCFG_MISSES,
+ V3D_PERFCNT_L2T_SLC0_MISSES,
+ V3D_PERFCNT_L2T_SLC1_MISSES,
+ V3D_PERFCNT_L2T_SLC2_MISSES,
+ V3D_PERFCNT_CORE_MEM_WRITES,
+ V3D_PERFCNT_L2T_MEM_WRITES,
+ V3D_PERFCNT_PTB_MEM_WRITES,
+ V3D_PERFCNT_TLB_MEM_WRITES,
+ V3D_PERFCNT_CORE_MEM_READS,
+ V3D_PERFCNT_L2T_MEM_READS,
+ V3D_PERFCNT_PTB_MEM_READS,
+ V3D_PERFCNT_PSE_MEM_READS,
+ V3D_PERFCNT_TLB_MEM_READS,
+ V3D_PERFCNT_GMP_MEM_READS,
+ V3D_PERFCNT_PTB_W_MEM_WORDS,
+ V3D_PERFCNT_TLB_W_MEM_WORDS,
+ V3D_PERFCNT_PSE_R_MEM_WORDS,
+ V3D_PERFCNT_TLB_R_MEM_WORDS,
+ V3D_PERFCNT_TMU_MRU_HITS,
+ V3D_PERFCNT_COMPUTE_ACTIVE,
+ V3D_PERFCNT_NUM,
+};
+
+#define DRM_V3D_MAX_PERF_COUNTERS 32
+
+struct drm_v3d_perfmon_create {
+ __u32 id;
+ __u32 ncounters;
+ __u8 counters[DRM_V3D_MAX_PERF_COUNTERS];
+};
+
+struct drm_v3d_perfmon_destroy {
+ __u32 id;
+};
+
+/*
+ * Returns the values of the performance counters tracked by this
+ * perfmon (as an array of ncounters u64 values).
+ *
+ * No implicit synchronization is performed, so the user has to
+ * guarantee that any jobs using this perfmon have already been
+ * completed (probably by blocking on the seqno returned by the
+ * last exec that used the perfmon).
+ */
+struct drm_v3d_perfmon_get_values {
+ __u32 id;
+ __u32 pad;
+ __u64 values_ptr;
};
#if defined(__cplusplus)
diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h
index 02e917507479..9078775feb51 100644
--- a/include/uapi/drm/vmwgfx_drm.h
+++ b/include/uapi/drm/vmwgfx_drm.h
@@ -72,6 +72,9 @@ extern "C" {
#define DRM_VMW_GB_SURFACE_CREATE_EXT 27
#define DRM_VMW_GB_SURFACE_REF_EXT 28
#define DRM_VMW_MSG 29
+#define DRM_VMW_MKSSTAT_RESET 30
+#define DRM_VMW_MKSSTAT_ADD 31
+#define DRM_VMW_MKSSTAT_REMOVE 32
/*************************************************************************/
/**
@@ -1236,6 +1239,44 @@ struct drm_vmw_msg_arg {
__u32 receive_len;
};
+/**
+ * struct drm_vmw_mksstat_add_arg
+ *
+ * @stat: Pointer to user-space stat-counters array, page-aligned.
+ * @info: Pointer to user-space counter-infos array, page-aligned.
+ * @strs: Pointer to user-space stat strings, page-aligned.
+ * @stat_len: Length in bytes of stat-counters array.
+ * @info_len: Length in bytes of counter-infos array.
+ * @strs_len: Length in bytes of the stat strings, terminators included.
+ * @description: Pointer to instance descriptor string; will be truncated
+ * to MKS_GUEST_STAT_INSTANCE_DESC_LENGTH chars.
+ * @id: Output identifier of the produced record; -1 if error.
+ *
+ * Argument to the DRM_VMW_MKSSTAT_ADD ioctl.
+ */
+struct drm_vmw_mksstat_add_arg {
+ __u64 stat;
+ __u64 info;
+ __u64 strs;
+ __u64 stat_len;
+ __u64 info_len;
+ __u64 strs_len;
+ __u64 description;
+ __u64 id;
+};
+
+/**
+ * struct drm_vmw_mksstat_remove_arg
+ *
+ * @id: Identifier of the record being disposed, originally obtained through
+ * DRM_VMW_MKSSTAT_ADD ioctl.
+ *
+ * Argument to the DRM_VMW_MKSSTAT_REMOVE ioctl.
+ */
+struct drm_vmw_mksstat_remove_arg {
+ __u64 id;
+};
+
#if defined(__cplusplus)
}
#endif
diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h
index 2ddb4226cd23..463d1ba2232a 100644
--- a/include/uapi/linux/capability.h
+++ b/include/uapi/linux/capability.h
@@ -243,7 +243,6 @@ struct vfs_ns_cap_data {
/* Allow examination and configuration of disk quotas */
/* Allow setting the domainname */
/* Allow setting the hostname */
-/* Allow calling bdflush() */
/* Allow mount() and umount(), setting up new smb connection */
/* Allow some autofs root ioctls */
/* Allow nfsservctl */
diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h
index dc8879d179fd..de936f5e446d 100644
--- a/include/uapi/linux/cec.h
+++ b/include/uapi/linux/cec.h
@@ -642,7 +642,7 @@ struct cec_event {
#define CEC_OP_REC_SEQ_WEDNESDAY 0x08
#define CEC_OP_REC_SEQ_THURSDAY 0x10
#define CEC_OP_REC_SEQ_FRIDAY 0x20
-#define CEC_OP_REC_SEQ_SATERDAY 0x40
+#define CEC_OP_REC_SEQ_SATURDAY 0x40
#define CEC_OP_REC_SEQ_ONCE_ONLY 0x00
#define CEC_MSG_CLEAR_DIGITAL_TIMER 0x99
diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
index 7f30393b92c3..8e4a2ca0bcbf 100644
--- a/include/uapi/linux/dma-buf.h
+++ b/include/uapi/linux/dma-buf.h
@@ -22,8 +22,56 @@
#include <linux/types.h>
-/* begin/end dma-buf functions used for userspace mmap. */
+/**
+ * struct dma_buf_sync - Synchronize with CPU access.
+ *
+ * When a DMA buffer is accessed from the CPU via mmap, it is not always
+ * possible to guarantee coherency between the CPU-visible map and underlying
+ * memory. To manage coherency, DMA_BUF_IOCTL_SYNC must be used to bracket
+ * any CPU access to give the kernel the chance to shuffle memory around if
+ * needed.
+ *
+ * Prior to accessing the map, the client must call DMA_BUF_IOCTL_SYNC
+ * with DMA_BUF_SYNC_START and the appropriate read/write flags. Once the
+ * access is complete, the client should call DMA_BUF_IOCTL_SYNC with
+ * DMA_BUF_SYNC_END and the same read/write flags.
+ *
+ * The synchronization provided via DMA_BUF_IOCTL_SYNC only provides cache
+ * coherency. It does not prevent other processes or devices from
+ * accessing the memory at the same time. If synchronization with a GPU or
+ * other device driver is required, it is the client's responsibility to
+ * wait for buffer to be ready for reading or writing before calling this
+ * ioctl with DMA_BUF_SYNC_START. Likewise, the client must ensure that
+ * follow-up work is not submitted to GPU or other device driver until
+ * after this ioctl has been called with DMA_BUF_SYNC_END?
+ *
+ * If the driver or API with which the client is interacting uses implicit
+ * synchronization, waiting for prior work to complete can be done via
+ * poll() on the DMA buffer file descriptor. If the driver or API requires
+ * explicit synchronization, the client may have to wait on a sync_file or
+ * other synchronization primitive outside the scope of the DMA buffer API.
+ */
struct dma_buf_sync {
+ /**
+ * @flags: Set of access flags
+ *
+ * DMA_BUF_SYNC_START:
+ * Indicates the start of a map access session.
+ *
+ * DMA_BUF_SYNC_END:
+ * Indicates the end of a map access session.
+ *
+ * DMA_BUF_SYNC_READ:
+ * Indicates that the mapped DMA buffer will be read by the
+ * client via the CPU map.
+ *
+ * DMA_BUF_SYNC_WRITE:
+ * Indicates that the mapped DMA buffer will be written by the
+ * client via the CPU map.
+ *
+ * DMA_BUF_SYNC_RW:
+ * An alias for DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE.
+ */
__u64 flags;
};
diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h
index 3cb5b5dd9f77..af96af174dc4 100644
--- a/include/uapi/linux/kfd_ioctl.h
+++ b/include/uapi/linux/kfd_ioctl.h
@@ -31,9 +31,10 @@
* - 1.3 - Add SMI events support
* - 1.4 - Indicate new SRAM EDC bit in device properties
* - 1.5 - Add SVM API
+ * - 1.6 - Query clear flags in SVM get_attr API
*/
#define KFD_IOCTL_MAJOR_VERSION 1
-#define KFD_IOCTL_MINOR_VERSION 5
+#define KFD_IOCTL_MINOR_VERSION 6
struct kfd_ioctl_get_version_args {
__u32 major_version; /* from KFD */
@@ -575,18 +576,19 @@ struct kfd_ioctl_svm_attribute {
* @KFD_IOCTL_SVM_ATTR_PREFERRED_LOC or
* @KFD_IOCTL_SVM_ATTR_PREFETCH_LOC resepctively. For
* @KFD_IOCTL_SVM_ATTR_SET_FLAGS, flags of all pages will be
- * aggregated by bitwise AND. The minimum migration granularity
- * throughout the range will be returned for
- * @KFD_IOCTL_SVM_ATTR_GRANULARITY.
+ * aggregated by bitwise AND. That means, a flag will be set in the
+ * output, if that flag is set for all pages in the range. For
+ * @KFD_IOCTL_SVM_ATTR_CLR_FLAGS, flags of all pages will be
+ * aggregated by bitwise NOR. That means, a flag will be set in the
+ * output, if that flag is clear for all pages in the range.
+ * The minimum migration granularity throughout the range will be
+ * returned for @KFD_IOCTL_SVM_ATTR_GRANULARITY.
*
* Querying of accessibility attributes works by initializing the
* attribute type to @KFD_IOCTL_SVM_ATTR_ACCESS and the value to the
* GPUID being queried. Multiple attributes can be given to allow
* querying multiple GPUIDs. The ioctl function overwrites the
* attribute type to indicate the access for the specified GPU.
- *
- * @KFD_IOCTL_SVM_ATTR_CLR_FLAGS is invalid for
- * @KFD_IOCTL_SVM_OP_GET_ATTR.
*/
struct kfd_ioctl_svm_args {
__u64 start_addr;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index d9e4aabcb31a..a067410ebea5 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1965,7 +1965,9 @@ struct kvm_stats_header {
#define KVM_STATS_TYPE_CUMULATIVE (0x0 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_INSTANT (0x1 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_PEAK (0x2 << KVM_STATS_TYPE_SHIFT)
-#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_PEAK
+#define KVM_STATS_TYPE_LINEAR_HIST (0x3 << KVM_STATS_TYPE_SHIFT)
+#define KVM_STATS_TYPE_LOG_HIST (0x4 << KVM_STATS_TYPE_SHIFT)
+#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_LOG_HIST
#define KVM_STATS_UNIT_SHIFT 4
#define KVM_STATS_UNIT_MASK (0xF << KVM_STATS_UNIT_SHIFT)
@@ -1988,8 +1990,9 @@ struct kvm_stats_header {
* @size: The number of data items for this stats.
* Every data item is of type __u64.
* @offset: The offset of the stats to the start of stat structure in
- * struture kvm or kvm_vcpu.
- * @unused: Unused field for future usage. Always 0 for now.
+ * structure kvm or kvm_vcpu.
+ * @bucket_size: A parameter value used for histogram stats. It is only used
+ * for linear histogram stats, specifying the size of the bucket;
* @name: The name string for the stats. Its size is indicated by the
* &kvm_stats_header->name_size.
*/
@@ -1998,7 +2001,7 @@ struct kvm_stats_desc {
__s16 exponent;
__u16 size;
__u32 offset;
- __u32 unused;
+ __u32 bucket_size;
char name[];
};
diff --git a/include/uapi/linux/mempolicy.h b/include/uapi/linux/mempolicy.h
index 19a00bc7fe86..046d0ccba4cd 100644
--- a/include/uapi/linux/mempolicy.h
+++ b/include/uapi/linux/mempolicy.h
@@ -22,6 +22,7 @@ enum {
MPOL_BIND,
MPOL_INTERLEAVE,
MPOL_LOCAL,
+ MPOL_PREFERRED_MANY,
MPOL_MAX, /* always last member of enum */
};
diff --git a/include/uapi/linux/netfilter/nfnetlink_conntrack.h b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
index c6e6d7d7d538..c2ac7269acf7 100644
--- a/include/uapi/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -258,6 +258,7 @@ enum ctattr_stats_cpu {
CTA_STATS_ERROR,
CTA_STATS_SEARCH_RESTART,
CTA_STATS_CLASH_RESOLVE,
+ CTA_STATS_CHAIN_TOOLONG,
__CTA_STATS_MAX,
};
#define CTA_STATS_MAX (__CTA_STATS_MAX - 1)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 79a699f106b1..ec88590b3198 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -827,6 +827,8 @@ struct tc_codel_xstats {
/* FQ_CODEL */
+#define FQ_CODEL_QUANTUM_MAX (1 << 20)
+
enum {
TCA_FQ_CODEL_UNSPEC,
TCA_FQ_CODEL_TARGET,
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 964c41ed303e..43bd7f713c39 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -235,14 +235,15 @@ struct prctl_mm_map {
#define PR_GET_TAGGED_ADDR_CTRL 56
# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
/* MTE tag check fault modes */
-# define PR_MTE_TCF_SHIFT 1
-# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
-# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
-# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
-# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_NONE 0
+# define PR_MTE_TCF_SYNC (1UL << 1)
+# define PR_MTE_TCF_ASYNC (1UL << 2)
+# define PR_MTE_TCF_MASK (PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC)
/* MTE tag inclusion mask */
# define PR_MTE_TAG_SHIFT 3
# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
+/* Unused; kept only for source compatibility */
+# define PR_MTE_TCF_SHIFT 1
/* Control reclaim behavior when allocating memory */
#define PR_SET_IO_FLUSHER 57
diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
index be07b5470f4b..f51bc8f36813 100644
--- a/include/uapi/linux/serial_reg.h
+++ b/include/uapi/linux/serial_reg.h
@@ -62,6 +62,7 @@
* ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
* TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
* TI16C752: 8 16 56 60 8 16 32 56
+ * OX16C950: 16 32 112 120 16 32 64 112 PORT_16C950
* Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
*/
#define UART_FCR_R_TRIG_00 0x00
diff --git a/include/uapi/linux/target_core_user.h b/include/uapi/linux/target_core_user.h
index 95b1597f16ae..27ace512babd 100644
--- a/include/uapi/linux/target_core_user.h
+++ b/include/uapi/linux/target_core_user.h
@@ -46,6 +46,7 @@
#define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0) /* Out-of-order completions */
#define TCMU_MAILBOX_FLAG_CAP_READ_LEN (1 << 1) /* Read data length */
#define TCMU_MAILBOX_FLAG_CAP_TMR (1 << 2) /* TMR notifications */
+#define TCMU_MAILBOX_FLAG_CAP_KEEP_BUF (1<<3) /* Keep buf after cmd completion */
struct tcmu_mailbox {
__u16 version;
@@ -75,6 +76,7 @@ struct tcmu_cmd_entry_hdr {
__u8 kflags;
#define TCMU_UFLAG_UNKNOWN_OP 0x1
#define TCMU_UFLAG_READ_LEN 0x2
+#define TCMU_UFLAG_KEEP_BUF 0x4
__u8 uflags;
} __packed;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index fdf97a6d7d18..5532b5f68493 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -435,6 +435,7 @@ enum v4l2_mpeg_video_multi_slice_mode {
#define V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX (V4L2_CID_CODEC_BASE+233)
#define V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES (V4L2_CID_CODEC_BASE+234)
#define V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR (V4L2_CID_CODEC_BASE+235)
+#define V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD (V4L2_CID_CODEC_BASE+236)
/* CIDs for the MPEG-2 Part 2 (H.262) codec */
#define V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL (V4L2_CID_CODEC_BASE+270)
diff --git a/include/uapi/linux/virtio_gpio.h b/include/uapi/linux/virtio_gpio.h
new file mode 100644
index 000000000000..0445f905d8cc
--- /dev/null
+++ b/include/uapi/linux/virtio_gpio.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef _LINUX_VIRTIO_GPIO_H
+#define _LINUX_VIRTIO_GPIO_H
+
+#include <linux/types.h>
+
+/* Virtio GPIO request types */
+#define VIRTIO_GPIO_MSG_GET_NAMES 0x0001
+#define VIRTIO_GPIO_MSG_GET_DIRECTION 0x0002
+#define VIRTIO_GPIO_MSG_SET_DIRECTION 0x0003
+#define VIRTIO_GPIO_MSG_GET_VALUE 0x0004
+#define VIRTIO_GPIO_MSG_SET_VALUE 0x0005
+
+/* Possible values of the status field */
+#define VIRTIO_GPIO_STATUS_OK 0x0
+#define VIRTIO_GPIO_STATUS_ERR 0x1
+
+/* Direction types */
+#define VIRTIO_GPIO_DIRECTION_NONE 0x00
+#define VIRTIO_GPIO_DIRECTION_OUT 0x01
+#define VIRTIO_GPIO_DIRECTION_IN 0x02
+
+struct virtio_gpio_config {
+ __le16 ngpio;
+ __u8 padding[2];
+ __le32 gpio_names_size;
+} __packed;
+
+/* Virtio GPIO Request / Response */
+struct virtio_gpio_request {
+ __le16 type;
+ __le16 gpio;
+ __le32 value;
+};
+
+struct virtio_gpio_response {
+ __u8 status;
+ __u8 value;
+};
+
+struct virtio_gpio_response_get_names {
+ __u8 status;
+ __u8 value[];
+};
+
+#endif /* _LINUX_VIRTIO_GPIO_H */
diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
index 99aa27b100bc..50d352f5e86f 100644
--- a/include/uapi/linux/virtio_ids.h
+++ b/include/uapi/linux/virtio_ids.h
@@ -55,8 +55,10 @@
#define VIRTIO_ID_FS 26 /* virtio filesystem */
#define VIRTIO_ID_PMEM 27 /* virtio pmem */
#define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */
+#define VIRTIO_ID_SCMI 32 /* virtio SCMI */
#define VIRTIO_ID_I2C_ADAPTER 34 /* virtio i2c adapter */
#define VIRTIO_ID_BT 40 /* virtio bluetooth */
+#define VIRTIO_ID_GPIO 41 /* virtio gpio */
/*
* Virtio Transitional IDs
diff --git a/include/uapi/linux/virtio_scmi.h b/include/uapi/linux/virtio_scmi.h
new file mode 100644
index 000000000000..f8ddd04a3ace
--- /dev/null
+++ b/include/uapi/linux/virtio_scmi.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/*
+ * Copyright (C) 2020-2021 OpenSynergy GmbH
+ * Copyright (C) 2021 ARM Ltd.
+ */
+
+#ifndef _UAPI_LINUX_VIRTIO_SCMI_H
+#define _UAPI_LINUX_VIRTIO_SCMI_H
+
+#include <linux/virtio_types.h>
+
+/* Device implements some SCMI notifications, or delayed responses. */
+#define VIRTIO_SCMI_F_P2A_CHANNELS 0
+
+/* Device implements any SCMI statistics shared memory region */
+#define VIRTIO_SCMI_F_SHARED_MEMORY 1
+
+/* Virtqueues */
+
+#define VIRTIO_SCMI_VQ_TX 0 /* cmdq */
+#define VIRTIO_SCMI_VQ_RX 1 /* eventq */
+#define VIRTIO_SCMI_VQ_MAX_CNT 2
+
+#endif /* _UAPI_LINUX_VIRTIO_SCMI_H */
diff --git a/include/uapi/rdma/mlx5-abi.h b/include/uapi/rdma/mlx5-abi.h
index 8597e6f22a1c..86be4a92b67b 100644
--- a/include/uapi/rdma/mlx5-abi.h
+++ b/include/uapi/rdma/mlx5-abi.h
@@ -50,6 +50,7 @@ enum {
MLX5_QP_FLAG_ALLOW_SCATTER_CQE = 1 << 8,
MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE = 1 << 9,
MLX5_QP_FLAG_UAR_PAGE_INDEX = 1 << 10,
+ MLX5_QP_FLAG_DCI_STREAM = 1 << 11,
};
enum {
@@ -238,6 +239,11 @@ struct mlx5_ib_striding_rq_caps {
__u32 reserved;
};
+struct mlx5_ib_dci_streams_caps {
+ __u8 max_log_num_concurent;
+ __u8 max_log_num_errored;
+};
+
enum mlx5_ib_query_dev_resp_flags {
/* Support 128B CQE compression */
MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_COMP = 1 << 0,
@@ -266,7 +272,8 @@ struct mlx5_ib_query_device_resp {
struct mlx5_ib_sw_parsing_caps sw_parsing_caps;
struct mlx5_ib_striding_rq_caps striding_rq_caps;
__u32 tunnel_offloads_caps; /* enum mlx5_ib_tunnel_offloads */
- __u32 reserved;
+ struct mlx5_ib_dci_streams_caps dci_streams_caps;
+ __u16 reserved;
};
enum mlx5_ib_create_cq_flags {
@@ -313,6 +320,11 @@ struct mlx5_ib_create_srq_resp {
__u32 reserved;
};
+struct mlx5_ib_create_qp_dci_streams {
+ __u8 log_num_concurent;
+ __u8 log_num_errored;
+};
+
struct mlx5_ib_create_qp {
__aligned_u64 buf_addr;
__aligned_u64 db_addr;
@@ -327,7 +339,8 @@ struct mlx5_ib_create_qp {
__aligned_u64 access_key;
};
__u32 ece_options;
- __u32 reserved;
+ struct mlx5_ib_create_qp_dci_streams dci_streams;
+ __u16 reserved;
};
/* RX Hash function flags */
diff --git a/include/uapi/scsi/fc/fc_els.h b/include/uapi/scsi/fc/fc_els.h
index 91d4be987220..c9812c5c2fc4 100644
--- a/include/uapi/scsi/fc/fc_els.h
+++ b/include/uapi/scsi/fc/fc_els.h
@@ -41,6 +41,7 @@ enum fc_els_cmd {
ELS_REC = 0x13, /* read exchange concise */
ELS_SRR = 0x14, /* sequence retransmission request */
ELS_FPIN = 0x16, /* Fabric Performance Impact Notification */
+ ELS_EDC = 0x17, /* Exchange Diagnostic Capabilities */
ELS_RDP = 0x18, /* Read Diagnostic Parameters */
ELS_RDF = 0x19, /* Register Diagnostic Functions */
ELS_PRLI = 0x20, /* process login */
@@ -111,6 +112,7 @@ enum fc_els_cmd {
[ELS_REC] = "REC", \
[ELS_SRR] = "SRR", \
[ELS_FPIN] = "FPIN", \
+ [ELS_EDC] = "EDC", \
[ELS_RDP] = "RDP", \
[ELS_RDF] = "RDF", \
[ELS_PRLI] = "PRLI", \
@@ -218,6 +220,10 @@ enum fc_els_rjt_explan {
enum fc_ls_tlv_dtag {
ELS_DTAG_LS_REQ_INFO = 0x00000001,
/* Link Service Request Information Descriptor */
+ ELS_DTAG_LNK_FAULT_CAP = 0x0001000D,
+ /* Link Fault Capability Descriptor */
+ ELS_DTAG_CG_SIGNAL_CAP = 0x0001000F,
+ /* Congestion Signaling Capability Descriptor */
ELS_DTAG_LNK_INTEGRITY = 0x00020001,
/* Link Integrity Notification Descriptor */
ELS_DTAG_DELIVERY = 0x00020002,
@@ -236,6 +242,8 @@ enum fc_ls_tlv_dtag {
*/
#define FC_LS_TLV_DTAG_INIT { \
{ ELS_DTAG_LS_REQ_INFO, "Link Service Request Information" }, \
+ { ELS_DTAG_LNK_FAULT_CAP, "Link Fault Capability" }, \
+ { ELS_DTAG_CG_SIGNAL_CAP, "Congestion Signaling Capability" }, \
{ ELS_DTAG_LNK_INTEGRITY, "Link Integrity Notification" }, \
{ ELS_DTAG_DELIVERY, "Delivery Notification Present" }, \
{ ELS_DTAG_PEER_CONGEST, "Peer Congestion Notification" }, \
@@ -1144,4 +1152,102 @@ struct fc_els_rdf_resp {
};
+/*
+ * Diagnostic Capability Descriptors for EDC ELS
+ */
+
+/*
+ * Diagnostic: Link Fault Capability Descriptor
+ */
+struct fc_diag_lnkflt_desc {
+ __be32 desc_tag; /* Descriptor Tag (0x0001000D) */
+ __be32 desc_len; /* Length of Descriptor (in bytes).
+ * Size of descriptor excluding
+ * desc_tag and desc_len fields.
+ * 12 bytes
+ */
+ __be32 degrade_activate_threshold;
+ __be32 degrade_deactivate_threshold;
+ __be32 fec_degrade_interval;
+};
+
+enum fc_edc_cg_signal_cap_types {
+ /* Note: Capability: bits 31:4 Rsvd; bits 3:0 are capabilities */
+ EDC_CG_SIG_NOTSUPPORTED = 0x00, /* neither supported */
+ EDC_CG_SIG_WARN_ONLY = 0x01,
+ EDC_CG_SIG_WARN_ALARM = 0x02, /* both supported */
+};
+
+/*
+ * Initializer useful for decoding table.
+ * Please keep this in sync with the above definitions.
+ */
+#define FC_EDC_CG_SIGNAL_CAP_TYPES_INIT { \
+ { EDC_CG_SIG_NOTSUPPORTED, "Signaling Not Supported" }, \
+ { EDC_CG_SIG_WARN_ONLY, "Warning Signal" }, \
+ { EDC_CG_SIG_WARN_ALARM, "Warning and Alarm Signals" }, \
+}
+
+enum fc_diag_cg_sig_freq_types {
+ EDC_CG_SIGFREQ_CNT_MIN = 1, /* Min Frequency Count */
+ EDC_CG_SIGFREQ_CNT_MAX = 999, /* Max Frequency Count */
+
+ EDC_CG_SIGFREQ_SEC = 0x1, /* Units: seconds */
+ EDC_CG_SIGFREQ_MSEC = 0x2, /* Units: milliseconds */
+};
+
+struct fc_diag_cg_sig_freq {
+ __be16 count; /* Time between signals
+ * note: upper 6 bits rsvd
+ */
+ __be16 units; /* Time unit for count
+ * note: upper 12 bits rsvd
+ */
+};
+
+/*
+ * Diagnostic: Congestion Signaling Capability Descriptor
+ */
+struct fc_diag_cg_sig_desc {
+ __be32 desc_tag; /* Descriptor Tag (0x0001000F) */
+ __be32 desc_len; /* Length of Descriptor (in bytes).
+ * Size of descriptor excluding
+ * desc_tag and desc_len fields.
+ * 16 bytes
+ */
+ __be32 xmt_signal_capability;
+ struct fc_diag_cg_sig_freq xmt_signal_frequency;
+ __be32 rcv_signal_capability;
+ struct fc_diag_cg_sig_freq rcv_signal_frequency;
+};
+
+/*
+ * ELS_EDC - Exchange Diagnostic Capabilities
+ */
+struct fc_els_edc {
+ __u8 edc_cmd; /* command (0x17) */
+ __u8 edc_zero[3]; /* specified as zero - part of cmd */
+ __be32 desc_len; /* Length of Descriptor List (in bytes).
+ * Size of ELS excluding edc_cmd,
+ * edc_zero and desc_len fields.
+ */
+ struct fc_tlv_desc desc[0];
+ /* Diagnostic Descriptor list */
+};
+
+/*
+ * ELS EDC LS_ACC Response.
+ */
+struct fc_els_edc_resp {
+ struct fc_els_ls_acc acc_hdr;
+ __be32 desc_list_len; /* Length of response (in
+ * bytes). Excludes acc_hdr
+ * and desc_list_len fields.
+ */
+ struct fc_els_lsri_desc lsri;
+ struct fc_tlv_desc desc[0];
+ /* Supported Diagnostic Descriptor list */
+};
+
+
#endif /* _FC_ELS_H_ */
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index d17c061950df..1d84ec9db93b 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -299,6 +299,7 @@ typedef int __bitwise snd_pcm_subformat_t;
#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */
#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */
#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */
+#define SNDRV_PCM_INFO_EXPLICIT_SYNC 0x10000000 /* needs explicit sync of pointers and data */
#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
diff --git a/include/uapi/sound/snd_sst_tokens.h b/include/uapi/sound/snd_sst_tokens.h
index 8ba0112e5336..ff3748e9308a 100644
--- a/include/uapi/sound/snd_sst_tokens.h
+++ b/include/uapi/sound/snd_sst_tokens.h
@@ -233,6 +233,8 @@
*
* %SKL_TKN_U32_ASTATE_CLK_SRC: Clock source for A-State entry
*
+ * %SKL_TKN_U32_FMT_CFG_IDX: Format config index
+ *
* module_id and loadable flags dont have tokens as these values will be
* read from the DSP FW manifest
*
@@ -324,7 +326,9 @@ enum SKL_TKNS {
SKL_TKN_U32_ASTATE_COUNT,
SKL_TKN_U32_ASTATE_KCPS,
SKL_TKN_U32_ASTATE_CLK_SRC,
- SKL_TKN_MAX = SKL_TKN_U32_ASTATE_CLK_SRC,
+
+ SKL_TKN_U32_FMT_CFG_IDX = 96,
+ SKL_TKN_MAX = SKL_TKN_U32_FMT_CFG_IDX,
};
#endif
diff --git a/init/Kconfig b/init/Kconfig
index 55f9f7738ebb..8cb97f141b70 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -137,6 +137,20 @@ config COMPILE_TEST
here. If you are a user/distributor, say N here to exclude useless
drivers to be distributed.
+config WERROR
+ bool "Compile the kernel with warnings as errors"
+ default y
+ help
+ A kernel build should not cause any compiler warnings, and this
+ enables the '-Werror' flag to enforce that rule by default.
+
+ However, if you have a new (or very old) compiler with odd and
+ unusual warnings, or you have some architecture with problems,
+ you may need to disable this config option in order to
+ successfully build the kernel.
+
+ If in doubt, say Y.
+
config UAPI_HEADER_TEST
bool "Compile test UAPI headers"
depends on HEADERS_INSTALL && CC_CAN_LINK
@@ -775,6 +789,20 @@ config PRINTK_SAFE_LOG_BUF_SHIFT
13 => 8 KB for each CPU
12 => 4 KB for each CPU
+config PRINTK_INDEX
+ bool "Printk indexing debugfs interface"
+ depends on PRINTK && DEBUG_FS
+ help
+ Add support for indexing of all printk formats known at compile time
+ at <debugfs>/printk/index/<module>.
+
+ This can be used as part of maintaining daemons which monitor
+ /dev/kmsg, as it permits auditing the printk formats present in a
+ kernel, allowing detection of cases where monitored printks are
+ changed or no longer present.
+
+ There is no additional runtime cost to printk with this enabled.
+
#
# Architectures with an unreliable sched_clock() should select this:
#
@@ -1509,11 +1537,6 @@ config PRINTK
very difficult to diagnose system problems, saying N here is
strongly discouraged.
-config PRINTK_NMI
- def_bool y
- depends on PRINTK
- depends on HAVE_NMI
-
config BUG
bool "BUG() support" if EXPERT
default y
diff --git a/ipc/msg.c b/ipc/msg.c
index 6810276d6bb9..a0d05775af2c 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -147,7 +147,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
key_t key = params->key;
int msgflg = params->flg;
- msq = kmalloc(sizeof(*msq), GFP_KERNEL);
+ msq = kmalloc(sizeof(*msq), GFP_KERNEL_ACCOUNT);
if (unlikely(!msq))
return -ENOMEM;
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 7bd0766ddc3b..ae83f0f2651b 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -42,7 +42,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
goto fail;
err = -ENOMEM;
- ns = kzalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
+ ns = kzalloc(sizeof(struct ipc_namespace), GFP_KERNEL_ACCOUNT);
if (ns == NULL)
goto fail_dec;
diff --git a/ipc/sem.c b/ipc/sem.c
index 971e75d28364..1a8b9f0ac047 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -514,7 +514,7 @@ static struct sem_array *sem_alloc(size_t nsems)
if (nsems > (INT_MAX - sizeof(*sma)) / sizeof(sma->sems[0]))
return NULL;
- sma = kvzalloc(struct_size(sma, sems, nsems), GFP_KERNEL);
+ sma = kvzalloc(struct_size(sma, sems, nsems), GFP_KERNEL_ACCOUNT);
if (unlikely(!sma))
return NULL;
@@ -1855,7 +1855,7 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
undo_list = current->sysvsem.undo_list;
if (!undo_list) {
- undo_list = kzalloc(sizeof(*undo_list), GFP_KERNEL);
+ undo_list = kzalloc(sizeof(*undo_list), GFP_KERNEL_ACCOUNT);
if (undo_list == NULL)
return -ENOMEM;
spin_lock_init(&undo_list->lock);
@@ -1941,7 +1941,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
/* step 2: allocate new undo structure */
new = kvzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems,
- GFP_KERNEL);
+ GFP_KERNEL_ACCOUNT);
if (!new) {
ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
return ERR_PTR(-ENOMEM);
@@ -2005,7 +2005,8 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
if (nsops > ns->sc_semopm)
return -E2BIG;
if (nsops > SEMOPM_FAST) {
- sops = kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL);
+ sops = kvmalloc_array(nsops, sizeof(*sops),
+ GFP_KERNEL_ACCOUNT);
if (sops == NULL)
return -ENOMEM;
}
diff --git a/ipc/shm.c b/ipc/shm.c
index 748933e376ca..ab749be6d8b7 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -619,7 +619,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
ns->shm_tot + numpages > ns->shm_ctlall)
return -ENOSPC;
- shp = kmalloc(sizeof(*shp), GFP_KERNEL);
+ shp = kmalloc(sizeof(*shp), GFP_KERNEL_ACCOUNT);
if (unlikely(!shp))
return -ENOMEM;
diff --git a/kernel/cgroup/namespace.c b/kernel/cgroup/namespace.c
index f5e8828c109c..0d5c29879a50 100644
--- a/kernel/cgroup/namespace.c
+++ b/kernel/cgroup/namespace.c
@@ -24,7 +24,7 @@ static struct cgroup_namespace *alloc_cgroup_ns(void)
struct cgroup_namespace *new_ns;
int ret;
- new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL);
+ new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL_ACCOUNT);
if (!new_ns)
return ERR_PTR(-ENOMEM);
ret = ns_alloc_inum(&new_ns->ns);
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index b4aa6bb6b2bd..da06a5553835 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Kernel Debug Core
*
@@ -22,10 +23,6 @@
*
* Original KGDB stub: David Grothe <dave@gcom.com>,
* Tigran Aivazian <tigran@sco.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
*/
#define pr_fmt(fmt) "KGDB: " fmt
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index b6f28fad4307..9d34d2364b5a 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Kernel Debug Core
*
@@ -22,10 +23,6 @@
*
* Original KGDB stub: David Grothe <dave@gcom.com>,
* Tigran Aivazian <tigran@sco.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
*/
#include <linux/kernel.h>
diff --git a/kernel/debug/kdb/kdb_bp.c b/kernel/debug/kdb/kdb_bp.c
index 2168f8dacb99..372025cf1ca3 100644
--- a/kernel/debug/kdb/kdb_bp.c
+++ b/kernel/debug/kdb/kdb_bp.c
@@ -523,51 +523,51 @@ static int kdb_ss(int argc, const char **argv)
}
static kdbtab_t bptab[] = {
- { .cmd_name = "bp",
- .cmd_func = kdb_bp,
- .cmd_usage = "[<vaddr>]",
- .cmd_help = "Set/Display breakpoints",
- .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
+ { .name = "bp",
+ .func = kdb_bp,
+ .usage = "[<vaddr>]",
+ .help = "Set/Display breakpoints",
+ .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
},
- { .cmd_name = "bl",
- .cmd_func = kdb_bp,
- .cmd_usage = "[<vaddr>]",
- .cmd_help = "Display breakpoints",
- .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
+ { .name = "bl",
+ .func = kdb_bp,
+ .usage = "[<vaddr>]",
+ .help = "Display breakpoints",
+ .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
},
- { .cmd_name = "bc",
- .cmd_func = kdb_bc,
- .cmd_usage = "<bpnum>",
- .cmd_help = "Clear Breakpoint",
- .cmd_flags = KDB_ENABLE_FLOW_CTRL,
+ { .name = "bc",
+ .func = kdb_bc,
+ .usage = "<bpnum>",
+ .help = "Clear Breakpoint",
+ .flags = KDB_ENABLE_FLOW_CTRL,
},
- { .cmd_name = "be",
- .cmd_func = kdb_bc,
- .cmd_usage = "<bpnum>",
- .cmd_help = "Enable Breakpoint",
- .cmd_flags = KDB_ENABLE_FLOW_CTRL,
+ { .name = "be",
+ .func = kdb_bc,
+ .usage = "<bpnum>",
+ .help = "Enable Breakpoint",
+ .flags = KDB_ENABLE_FLOW_CTRL,
},
- { .cmd_name = "bd",
- .cmd_func = kdb_bc,
- .cmd_usage = "<bpnum>",
- .cmd_help = "Disable Breakpoint",
- .cmd_flags = KDB_ENABLE_FLOW_CTRL,
+ { .name = "bd",
+ .func = kdb_bc,
+ .usage = "<bpnum>",
+ .help = "Disable Breakpoint",
+ .flags = KDB_ENABLE_FLOW_CTRL,
},
- { .cmd_name = "ss",
- .cmd_func = kdb_ss,
- .cmd_usage = "",
- .cmd_help = "Single Step",
- .cmd_minlen = 1,
- .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
+ { .name = "ss",
+ .func = kdb_ss,
+ .usage = "",
+ .help = "Single Step",
+ .minlen = 1,
+ .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
},
};
static kdbtab_t bphcmd = {
- .cmd_name = "bph",
- .cmd_func = kdb_bp,
- .cmd_usage = "[<vaddr>]",
- .cmd_help = "[datar [length]|dataw [length]] Set hw brk",
- .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
+ .name = "bph",
+ .func = kdb_bp,
+ .usage = "[<vaddr>]",
+ .help = "[datar [length]|dataw [length]] Set hw brk",
+ .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
};
/* Initialize the breakpoint table and register breakpoint commands. */
diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c
index 0220afda3200..e91fc3e4edd5 100644
--- a/kernel/debug/kdb/kdb_debugger.c
+++ b/kernel/debug/kdb/kdb_debugger.c
@@ -140,7 +140,6 @@ int kdb_stub(struct kgdb_state *ks)
*/
kdb_common_deinit_state();
KDB_STATE_CLEAR(PAGER);
- kdbnearsym_cleanup();
if (error == KDB_CMD_KGDB) {
if (KDB_STATE(DOING_KGDB))
KDB_STATE_CLEAR(DOING_KGDB);
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index d8ee5647b732..fa6deda894a1 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -33,7 +33,6 @@
#include <linux/kallsyms.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
-#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -654,16 +653,17 @@ static void kdb_cmderror(int diag)
* Returns:
* zero for success, a kdb diagnostic if error
*/
-struct defcmd_set {
- int count;
- bool usable;
- char *name;
- char *usage;
- char *help;
- char **command;
+struct kdb_macro {
+ kdbtab_t cmd; /* Macro command */
+ struct list_head statements; /* Associated statement list */
};
-static struct defcmd_set *defcmd_set;
-static int defcmd_set_count;
+
+struct kdb_macro_statement {
+ char *statement; /* Statement text */
+ struct list_head list_node; /* Statement list node */
+};
+
+static struct kdb_macro *kdb_macro;
static bool defcmd_in_progress;
/* Forward references */
@@ -671,53 +671,55 @@ static int kdb_exec_defcmd(int argc, const char **argv);
static int kdb_defcmd2(const char *cmdstr, const char *argv0)
{
- struct defcmd_set *s = defcmd_set + defcmd_set_count - 1;
- char **save_command = s->command;
+ struct kdb_macro_statement *kms;
+
+ if (!kdb_macro)
+ return KDB_NOTIMP;
+
if (strcmp(argv0, "endefcmd") == 0) {
defcmd_in_progress = false;
- if (!s->count)
- s->usable = false;
- if (s->usable)
- /* macros are always safe because when executed each
- * internal command re-enters kdb_parse() and is
- * safety checked individually.
- */
- kdb_register_flags(s->name, kdb_exec_defcmd, s->usage,
- s->help, 0,
- KDB_ENABLE_ALWAYS_SAFE);
+ if (!list_empty(&kdb_macro->statements))
+ kdb_register(&kdb_macro->cmd);
return 0;
}
- if (!s->usable)
- return KDB_NOTIMP;
- 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",
+
+ kms = kmalloc(sizeof(*kms), GFP_KDB);
+ if (!kms) {
+ kdb_printf("Could not allocate new kdb macro command: %s\n",
cmdstr);
- s->usable = false;
return KDB_NOTIMP;
}
- memcpy(s->command, save_command, s->count * sizeof(*(s->command)));
- s->command[s->count++] = kdb_strdup(cmdstr, GFP_KDB);
- kfree(save_command);
+
+ kms->statement = kdb_strdup(cmdstr, GFP_KDB);
+ list_add_tail(&kms->list_node, &kdb_macro->statements);
+
return 0;
}
static int kdb_defcmd(int argc, const char **argv)
{
- struct defcmd_set *save_defcmd_set = defcmd_set, *s;
+ kdbtab_t *mp;
+
if (defcmd_in_progress) {
kdb_printf("kdb: nested defcmd detected, assuming missing "
"endefcmd\n");
kdb_defcmd2("endefcmd", "endefcmd");
}
if (argc == 0) {
- int i;
- for (s = defcmd_set; s < defcmd_set + defcmd_set_count; ++s) {
- kdb_printf("defcmd %s \"%s\" \"%s\"\n", s->name,
- s->usage, s->help);
- for (i = 0; i < s->count; ++i)
- kdb_printf("%s", s->command[i]);
- kdb_printf("endefcmd\n");
+ kdbtab_t *kp;
+ struct kdb_macro *kmp;
+ struct kdb_macro_statement *kms;
+
+ list_for_each_entry(kp, &kdb_cmds_head, list_node) {
+ if (kp->func == kdb_exec_defcmd) {
+ kdb_printf("defcmd %s \"%s\" \"%s\"\n",
+ kp->name, kp->usage, kp->help);
+ kmp = container_of(kp, struct kdb_macro, cmd);
+ list_for_each_entry(kms, &kmp->statements,
+ list_node)
+ kdb_printf("%s", kms->statement);
+ kdb_printf("endefcmd\n");
+ }
}
return 0;
}
@@ -727,45 +729,43 @@ static int kdb_defcmd(int argc, const char **argv)
kdb_printf("Command only available during kdb_init()\n");
return KDB_NOTIMP;
}
- defcmd_set = kmalloc_array(defcmd_set_count + 1, sizeof(*defcmd_set),
- GFP_KDB);
- if (!defcmd_set)
+ kdb_macro = kzalloc(sizeof(*kdb_macro), GFP_KDB);
+ if (!kdb_macro)
goto fail_defcmd;
- memcpy(defcmd_set, save_defcmd_set,
- defcmd_set_count * sizeof(*defcmd_set));
- s = defcmd_set + defcmd_set_count;
- memset(s, 0, sizeof(*s));
- s->usable = true;
- s->name = kdb_strdup(argv[1], GFP_KDB);
- if (!s->name)
+
+ mp = &kdb_macro->cmd;
+ mp->func = kdb_exec_defcmd;
+ mp->minlen = 0;
+ mp->flags = KDB_ENABLE_ALWAYS_SAFE;
+ mp->name = kdb_strdup(argv[1], GFP_KDB);
+ if (!mp->name)
goto fail_name;
- s->usage = kdb_strdup(argv[2], GFP_KDB);
- if (!s->usage)
+ mp->usage = kdb_strdup(argv[2], GFP_KDB);
+ if (!mp->usage)
goto fail_usage;
- s->help = kdb_strdup(argv[3], GFP_KDB);
- if (!s->help)
+ mp->help = kdb_strdup(argv[3], GFP_KDB);
+ if (!mp->help)
goto fail_help;
- if (s->usage[0] == '"') {
- strcpy(s->usage, argv[2]+1);
- s->usage[strlen(s->usage)-1] = '\0';
+ if (mp->usage[0] == '"') {
+ strcpy(mp->usage, argv[2]+1);
+ mp->usage[strlen(mp->usage)-1] = '\0';
}
- if (s->help[0] == '"') {
- strcpy(s->help, argv[3]+1);
- s->help[strlen(s->help)-1] = '\0';
+ if (mp->help[0] == '"') {
+ strcpy(mp->help, argv[3]+1);
+ mp->help[strlen(mp->help)-1] = '\0';
}
- ++defcmd_set_count;
+
+ INIT_LIST_HEAD(&kdb_macro->statements);
defcmd_in_progress = true;
- kfree(save_defcmd_set);
return 0;
fail_help:
- kfree(s->usage);
+ kfree(mp->usage);
fail_usage:
- kfree(s->name);
+ kfree(mp->name);
fail_name:
- kfree(defcmd_set);
+ kfree(kdb_macro);
fail_defcmd:
- kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]);
- defcmd_set = save_defcmd_set;
+ kdb_printf("Could not allocate new kdb_macro entry for %s\n", argv[1]);
return KDB_NOTIMP;
}
@@ -780,25 +780,31 @@ fail_defcmd:
*/
static int kdb_exec_defcmd(int argc, const char **argv)
{
- int i, ret;
- struct defcmd_set *s;
+ int ret;
+ kdbtab_t *kp;
+ struct kdb_macro *kmp;
+ struct kdb_macro_statement *kms;
+
if (argc != 0)
return KDB_ARGCOUNT;
- for (s = defcmd_set, i = 0; i < defcmd_set_count; ++i, ++s) {
- if (strcmp(s->name, argv[0]) == 0)
+
+ list_for_each_entry(kp, &kdb_cmds_head, list_node) {
+ if (strcmp(kp->name, argv[0]) == 0)
break;
}
- if (i == defcmd_set_count) {
+ if (list_entry_is_head(kp, &kdb_cmds_head, list_node)) {
kdb_printf("kdb_exec_defcmd: could not find commands for %s\n",
argv[0]);
return KDB_NOTIMP;
}
- for (i = 0; i < s->count; ++i) {
- /* Recursive use of kdb_parse, do not use argv after
- * this point */
+ kmp = container_of(kp, struct kdb_macro, cmd);
+ list_for_each_entry(kms, &kmp->statements, list_node) {
+ /*
+ * Recursive use of kdb_parse, do not use argv after this point.
+ */
argv = NULL;
- kdb_printf("[%s]kdb> %s\n", s->name, s->command[i]);
- ret = kdb_parse(s->command[i]);
+ kdb_printf("[%s]kdb> %s\n", kmp->cmd.name, kms->statement);
+ ret = kdb_parse(kms->statement);
if (ret)
return ret;
}
@@ -1009,11 +1015,11 @@ int kdb_parse(const char *cmdstr)
* If this command is allowed to be abbreviated,
* check to see if this is it.
*/
- if (tp->cmd_minlen && (strlen(argv[0]) <= tp->cmd_minlen) &&
- (strncmp(argv[0], tp->cmd_name, tp->cmd_minlen) == 0))
+ if (tp->minlen && (strlen(argv[0]) <= tp->minlen) &&
+ (strncmp(argv[0], tp->name, tp->minlen) == 0))
break;
- if (strcmp(argv[0], tp->cmd_name) == 0)
+ if (strcmp(argv[0], tp->name) == 0)
break;
}
@@ -1024,8 +1030,7 @@ int kdb_parse(const char *cmdstr)
*/
if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
list_for_each_entry(tp, &kdb_cmds_head, list_node) {
- if (strncmp(argv[0], tp->cmd_name,
- strlen(tp->cmd_name)) == 0)
+ if (strncmp(argv[0], tp->name, strlen(tp->name)) == 0)
break;
}
}
@@ -1033,19 +1038,19 @@ int kdb_parse(const char *cmdstr)
if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
int result;
- if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))
+ if (!kdb_check_flags(tp->flags, kdb_cmd_enabled, argc <= 1))
return KDB_NOPERM;
KDB_STATE_SET(CMD);
- result = (*tp->cmd_func)(argc-1, (const char **)argv);
+ result = (*tp->func)(argc-1, (const char **)argv);
if (result && ignore_errors && result > KDB_CMD_GO)
result = 0;
KDB_STATE_CLEAR(CMD);
- if (tp->cmd_flags & KDB_REPEAT_WITH_ARGS)
+ if (tp->flags & KDB_REPEAT_WITH_ARGS)
return result;
- argc = tp->cmd_flags & KDB_REPEAT_NO_ARGS ? 1 : 0;
+ argc = tp->flags & KDB_REPEAT_NO_ARGS ? 1 : 0;
if (argv[argc])
*(argv[argc]) = '\0';
return result;
@@ -2412,12 +2417,12 @@ static int kdb_help(int argc, const char **argv)
char *space = "";
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
- if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true))
+ if (!kdb_check_flags(kt->flags, kdb_cmd_enabled, true))
continue;
- if (strlen(kt->cmd_usage) > 20)
+ if (strlen(kt->usage) > 20)
space = "\n ";
- kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name,
- kt->cmd_usage, space, kt->cmd_help);
+ kdb_printf("%-15.15s %-20s%s%s\n", kt->name,
+ kt->usage, space, kt->help);
}
return 0;
}
@@ -2613,56 +2618,32 @@ static int kdb_grep_help(int argc, const char **argv)
return 0;
}
-/*
- * kdb_register_flags - This function is used to register a kernel
- * debugger command.
- * Inputs:
- * cmd Command name
- * func Function to execute the command
- * usage A simple usage string showing arguments
- * help A simple help string describing command
- * repeat Does the command auto repeat on enter?
- * Returns:
- * zero for success, one if a duplicate command.
+/**
+ * kdb_register() - This function is used to register a kernel debugger
+ * command.
+ * @cmd: pointer to kdb command
+ *
+ * Note that it's the job of the caller to keep the memory for the cmd
+ * allocated until unregister is called.
*/
-int kdb_register_flags(char *cmd,
- kdb_func_t func,
- char *usage,
- char *help,
- short minlen,
- kdb_cmdflags_t flags)
+int kdb_register(kdbtab_t *cmd)
{
kdbtab_t *kp;
list_for_each_entry(kp, &kdb_cmds_head, list_node) {
- if (strcmp(kp->cmd_name, cmd) == 0) {
- kdb_printf("Duplicate kdb command registered: "
- "%s, func %px help %s\n", cmd, func, help);
+ if (strcmp(kp->name, cmd->name) == 0) {
+ kdb_printf("Duplicate kdb cmd: %s, func %p help %s\n",
+ cmd->name, cmd->func, cmd->help);
return 1;
}
}
- kp = kmalloc(sizeof(*kp), GFP_KDB);
- if (!kp) {
- kdb_printf("Could not allocate new kdb_command table\n");
- return 1;
- }
-
- kp->cmd_name = cmd;
- kp->cmd_func = func;
- kp->cmd_usage = usage;
- kp->cmd_help = help;
- kp->cmd_minlen = minlen;
- kp->cmd_flags = flags;
- kp->is_dynamic = true;
-
- list_add_tail(&kp->list_node, &kdb_cmds_head);
-
+ list_add_tail(&cmd->list_node, &kdb_cmds_head);
return 0;
}
-EXPORT_SYMBOL_GPL(kdb_register_flags);
+EXPORT_SYMBOL_GPL(kdb_register);
-/*
+/**
* kdb_register_table() - This function is used to register a kdb command
* table.
* @kp: pointer to kdb command table
@@ -2676,266 +2657,231 @@ void kdb_register_table(kdbtab_t *kp, size_t len)
}
}
-/*
- * kdb_register - Compatibility register function for commands that do
- * not need to specify a repeat state. Equivalent to
- * kdb_register_flags with flags set to 0.
- * Inputs:
- * cmd Command name
- * func Function to execute the command
- * usage A simple usage string showing arguments
- * help A simple help string describing command
- * Returns:
- * zero for success, one if a duplicate command.
+/**
+ * kdb_unregister() - This function is used to unregister a kernel debugger
+ * command. It is generally called when a module which
+ * implements kdb command is unloaded.
+ * @cmd: pointer to kdb command
*/
-int kdb_register(char *cmd,
- kdb_func_t func,
- char *usage,
- char *help,
- short minlen)
+void kdb_unregister(kdbtab_t *cmd)
{
- return kdb_register_flags(cmd, func, usage, help, minlen, 0);
-}
-EXPORT_SYMBOL_GPL(kdb_register);
-
-/*
- * kdb_unregister - This function is used to unregister a kernel
- * debugger command. It is generally called when a module which
- * implements kdb commands is unloaded.
- * Inputs:
- * cmd Command name
- * Returns:
- * zero for success, one command not registered.
- */
-int kdb_unregister(char *cmd)
-{
- kdbtab_t *kp;
-
- /*
- * find the command.
- */
- list_for_each_entry(kp, &kdb_cmds_head, list_node) {
- if (strcmp(kp->cmd_name, cmd) == 0) {
- list_del(&kp->list_node);
- if (kp->is_dynamic)
- kfree(kp);
- return 0;
- }
- }
-
- /* Couldn't find it. */
- return 1;
+ list_del(&cmd->list_node);
}
EXPORT_SYMBOL_GPL(kdb_unregister);
static kdbtab_t maintab[] = {
- { .cmd_name = "md",
- .cmd_func = kdb_md,
- .cmd_usage = "<vaddr>",
- .cmd_help = "Display Memory Contents, also mdWcN, e.g. md8c1",
- .cmd_minlen = 1,
- .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
+ { .name = "md",
+ .func = kdb_md,
+ .usage = "<vaddr>",
+ .help = "Display Memory Contents, also mdWcN, e.g. md8c1",
+ .minlen = 1,
+ .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
},
- { .cmd_name = "mdr",
- .cmd_func = kdb_md,
- .cmd_usage = "<vaddr> <bytes>",
- .cmd_help = "Display Raw Memory",
- .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
+ { .name = "mdr",
+ .func = kdb_md,
+ .usage = "<vaddr> <bytes>",
+ .help = "Display Raw Memory",
+ .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
},
- { .cmd_name = "mdp",
- .cmd_func = kdb_md,
- .cmd_usage = "<paddr> <bytes>",
- .cmd_help = "Display Physical Memory",
- .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
+ { .name = "mdp",
+ .func = kdb_md,
+ .usage = "<paddr> <bytes>",
+ .help = "Display Physical Memory",
+ .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
},
- { .cmd_name = "mds",
- .cmd_func = kdb_md,
- .cmd_usage = "<vaddr>",
- .cmd_help = "Display Memory Symbolically",
- .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
+ { .name = "mds",
+ .func = kdb_md,
+ .usage = "<vaddr>",
+ .help = "Display Memory Symbolically",
+ .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
},
- { .cmd_name = "mm",
- .cmd_func = kdb_mm,
- .cmd_usage = "<vaddr> <contents>",
- .cmd_help = "Modify Memory Contents",
- .cmd_flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS,
+ { .name = "mm",
+ .func = kdb_mm,
+ .usage = "<vaddr> <contents>",
+ .help = "Modify Memory Contents",
+ .flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS,
},
- { .cmd_name = "go",
- .cmd_func = kdb_go,
- .cmd_usage = "[<vaddr>]",
- .cmd_help = "Continue Execution",
- .cmd_minlen = 1,
- .cmd_flags = KDB_ENABLE_REG_WRITE |
+ { .name = "go",
+ .func = kdb_go,
+ .usage = "[<vaddr>]",
+ .help = "Continue Execution",
+ .minlen = 1,
+ .flags = KDB_ENABLE_REG_WRITE |
KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
},
- { .cmd_name = "rd",
- .cmd_func = kdb_rd,
- .cmd_usage = "",
- .cmd_help = "Display Registers",
- .cmd_flags = KDB_ENABLE_REG_READ,
+ { .name = "rd",
+ .func = kdb_rd,
+ .usage = "",
+ .help = "Display Registers",
+ .flags = KDB_ENABLE_REG_READ,
},
- { .cmd_name = "rm",
- .cmd_func = kdb_rm,
- .cmd_usage = "<reg> <contents>",
- .cmd_help = "Modify Registers",
- .cmd_flags = KDB_ENABLE_REG_WRITE,
+ { .name = "rm",
+ .func = kdb_rm,
+ .usage = "<reg> <contents>",
+ .help = "Modify Registers",
+ .flags = KDB_ENABLE_REG_WRITE,
},
- { .cmd_name = "ef",
- .cmd_func = kdb_ef,
- .cmd_usage = "<vaddr>",
- .cmd_help = "Display exception frame",
- .cmd_flags = KDB_ENABLE_MEM_READ,
+ { .name = "ef",
+ .func = kdb_ef,
+ .usage = "<vaddr>",
+ .help = "Display exception frame",
+ .flags = KDB_ENABLE_MEM_READ,
},
- { .cmd_name = "bt",
- .cmd_func = kdb_bt,
- .cmd_usage = "[<vaddr>]",
- .cmd_help = "Stack traceback",
- .cmd_minlen = 1,
- .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
+ { .name = "bt",
+ .func = kdb_bt,
+ .usage = "[<vaddr>]",
+ .help = "Stack traceback",
+ .minlen = 1,
+ .flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
},
- { .cmd_name = "btp",
- .cmd_func = kdb_bt,
- .cmd_usage = "<pid>",
- .cmd_help = "Display stack for process <pid>",
- .cmd_flags = KDB_ENABLE_INSPECT,
+ { .name = "btp",
+ .func = kdb_bt,
+ .usage = "<pid>",
+ .help = "Display stack for process <pid>",
+ .flags = KDB_ENABLE_INSPECT,
},
- { .cmd_name = "bta",
- .cmd_func = kdb_bt,
- .cmd_usage = "[D|R|S|T|C|Z|E|U|I|M|A]",
- .cmd_help = "Backtrace all processes matching state flag",
- .cmd_flags = KDB_ENABLE_INSPECT,
+ { .name = "bta",
+ .func = kdb_bt,
+ .usage = "[D|R|S|T|C|Z|E|U|I|M|A]",
+ .help = "Backtrace all processes matching state flag",
+ .flags = KDB_ENABLE_INSPECT,
},
- { .cmd_name = "btc",
- .cmd_func = kdb_bt,
- .cmd_usage = "",
- .cmd_help = "Backtrace current process on each cpu",
- .cmd_flags = KDB_ENABLE_INSPECT,
+ { .name = "btc",
+ .func = kdb_bt,
+ .usage = "",
+ .help = "Backtrace current process on each cpu",
+ .flags = KDB_ENABLE_INSPECT,
},
- { .cmd_name = "btt",
- .cmd_func = kdb_bt,
- .cmd_usage = "<vaddr>",
- .cmd_help = "Backtrace process given its struct task address",
- .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
+ { .name = "btt",
+ .func = kdb_bt,
+ .usage = "<vaddr>",
+ .help = "Backtrace process given its struct task address",
+ .flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
},
- { .cmd_name = "env",
- .cmd_func = kdb_env,
- .cmd_usage = "",
- .cmd_help = "Show environment variables",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "env",
+ .func = kdb_env,
+ .usage = "",
+ .help = "Show environment variables",
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
- { .cmd_name = "set",
- .cmd_func = kdb_set,
- .cmd_usage = "",
- .cmd_help = "Set environment variables",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "set",
+ .func = kdb_set,
+ .usage = "",
+ .help = "Set environment variables",
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
- { .cmd_name = "help",
- .cmd_func = kdb_help,
- .cmd_usage = "",
- .cmd_help = "Display Help Message",
- .cmd_minlen = 1,
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "help",
+ .func = kdb_help,
+ .usage = "",
+ .help = "Display Help Message",
+ .minlen = 1,
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
- { .cmd_name = "?",
- .cmd_func = kdb_help,
- .cmd_usage = "",
- .cmd_help = "Display Help Message",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "?",
+ .func = kdb_help,
+ .usage = "",
+ .help = "Display Help Message",
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
- { .cmd_name = "cpu",
- .cmd_func = kdb_cpu,
- .cmd_usage = "<cpunum>",
- .cmd_help = "Switch to new cpu",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
+ { .name = "cpu",
+ .func = kdb_cpu,
+ .usage = "<cpunum>",
+ .help = "Switch to new cpu",
+ .flags = KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
},
- { .cmd_name = "kgdb",
- .cmd_func = kdb_kgdb,
- .cmd_usage = "",
- .cmd_help = "Enter kgdb mode",
- .cmd_flags = 0,
+ { .name = "kgdb",
+ .func = kdb_kgdb,
+ .usage = "",
+ .help = "Enter kgdb mode",
+ .flags = 0,
},
- { .cmd_name = "ps",
- .cmd_func = kdb_ps,
- .cmd_usage = "[<flags>|A]",
- .cmd_help = "Display active task list",
- .cmd_flags = KDB_ENABLE_INSPECT,
+ { .name = "ps",
+ .func = kdb_ps,
+ .usage = "[<flags>|A]",
+ .help = "Display active task list",
+ .flags = KDB_ENABLE_INSPECT,
},
- { .cmd_name = "pid",
- .cmd_func = kdb_pid,
- .cmd_usage = "<pidnum>",
- .cmd_help = "Switch to another task",
- .cmd_flags = KDB_ENABLE_INSPECT,
+ { .name = "pid",
+ .func = kdb_pid,
+ .usage = "<pidnum>",
+ .help = "Switch to another task",
+ .flags = KDB_ENABLE_INSPECT,
},
- { .cmd_name = "reboot",
- .cmd_func = kdb_reboot,
- .cmd_usage = "",
- .cmd_help = "Reboot the machine immediately",
- .cmd_flags = KDB_ENABLE_REBOOT,
+ { .name = "reboot",
+ .func = kdb_reboot,
+ .usage = "",
+ .help = "Reboot the machine immediately",
+ .flags = KDB_ENABLE_REBOOT,
},
#if defined(CONFIG_MODULES)
- { .cmd_name = "lsmod",
- .cmd_func = kdb_lsmod,
- .cmd_usage = "",
- .cmd_help = "List loaded kernel modules",
- .cmd_flags = KDB_ENABLE_INSPECT,
+ { .name = "lsmod",
+ .func = kdb_lsmod,
+ .usage = "",
+ .help = "List loaded kernel modules",
+ .flags = KDB_ENABLE_INSPECT,
},
#endif
#if defined(CONFIG_MAGIC_SYSRQ)
- { .cmd_name = "sr",
- .cmd_func = kdb_sr,
- .cmd_usage = "<key>",
- .cmd_help = "Magic SysRq key",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "sr",
+ .func = kdb_sr,
+ .usage = "<key>",
+ .help = "Magic SysRq key",
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
#endif
#if defined(CONFIG_PRINTK)
- { .cmd_name = "dmesg",
- .cmd_func = kdb_dmesg,
- .cmd_usage = "[lines]",
- .cmd_help = "Display syslog buffer",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "dmesg",
+ .func = kdb_dmesg,
+ .usage = "[lines]",
+ .help = "Display syslog buffer",
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
#endif
- { .cmd_name = "defcmd",
- .cmd_func = kdb_defcmd,
- .cmd_usage = "name \"usage\" \"help\"",
- .cmd_help = "Define a set of commands, down to endefcmd",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "defcmd",
+ .func = kdb_defcmd,
+ .usage = "name \"usage\" \"help\"",
+ .help = "Define a set of commands, down to endefcmd",
+ /*
+ * Macros are always safe because when executed each
+ * internal command re-enters kdb_parse() and is safety
+ * checked individually.
+ */
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
- { .cmd_name = "kill",
- .cmd_func = kdb_kill,
- .cmd_usage = "<-signal> <pid>",
- .cmd_help = "Send a signal to a process",
- .cmd_flags = KDB_ENABLE_SIGNAL,
+ { .name = "kill",
+ .func = kdb_kill,
+ .usage = "<-signal> <pid>",
+ .help = "Send a signal to a process",
+ .flags = KDB_ENABLE_SIGNAL,
},
- { .cmd_name = "summary",
- .cmd_func = kdb_summary,
- .cmd_usage = "",
- .cmd_help = "Summarize the system",
- .cmd_minlen = 4,
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "summary",
+ .func = kdb_summary,
+ .usage = "",
+ .help = "Summarize the system",
+ .minlen = 4,
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
- { .cmd_name = "per_cpu",
- .cmd_func = kdb_per_cpu,
- .cmd_usage = "<sym> [<bytes>] [<cpu>]",
- .cmd_help = "Display per_cpu variables",
- .cmd_minlen = 3,
- .cmd_flags = KDB_ENABLE_MEM_READ,
+ { .name = "per_cpu",
+ .func = kdb_per_cpu,
+ .usage = "<sym> [<bytes>] [<cpu>]",
+ .help = "Display per_cpu variables",
+ .minlen = 3,
+ .flags = KDB_ENABLE_MEM_READ,
},
- { .cmd_name = "grephelp",
- .cmd_func = kdb_grep_help,
- .cmd_usage = "",
- .cmd_help = "Display help on | grep",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ { .name = "grephelp",
+ .func = kdb_grep_help,
+ .usage = "",
+ .help = "Display help on | grep",
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
},
};
static kdbtab_t nmicmd = {
- .cmd_name = "disable_nmi",
- .cmd_func = kdb_disable_nmi,
- .cmd_usage = "",
- .cmd_help = "Disable NMI entry to KDB",
- .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+ .name = "disable_nmi",
+ .func = kdb_disable_nmi,
+ .usage = "",
+ .help = "Disable NMI entry to KDB",
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
};
/* Initialize the kdb command table. */
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h
index 170c69aedebb..629590084a0d 100644
--- a/kernel/debug/kdb/kdb_private.h
+++ b/kernel/debug/kdb/kdb_private.h
@@ -109,7 +109,6 @@ extern int kdbgetaddrarg(int, const char **, int*, unsigned long *,
long *, char **);
extern int kdbgetsymval(const char *, kdb_symtab_t *);
extern int kdbnearsym(unsigned long, kdb_symtab_t *);
-extern void kdbnearsym_cleanup(void);
extern char *kdb_strdup(const char *str, gfp_t type);
extern void kdb_symbol_print(unsigned long, const kdb_symtab_t *, unsigned int);
@@ -165,19 +164,6 @@ typedef struct _kdb_bp {
#ifdef CONFIG_KGDB_KDB
extern kdb_bp_t kdb_breakpoints[/* KDB_MAXBPT */];
-/* The KDB shell command table */
-typedef struct _kdbtab {
- char *cmd_name; /* Command name */
- kdb_func_t cmd_func; /* Function to execute command */
- char *cmd_usage; /* Usage String for this command */
- char *cmd_help; /* Help message for this command */
- short cmd_minlen; /* Minimum legal # command
- * chars required */
- kdb_cmdflags_t cmd_flags; /* Command behaviour flags */
- struct list_head list_node; /* Command list */
- bool is_dynamic; /* Command table allocation type */
-} kdbtab_t;
-
extern void kdb_register_table(kdbtab_t *kp, size_t len);
extern int kdb_bt(int, const char **); /* KDB display back trace */
@@ -233,10 +219,6 @@ extern struct task_struct *kdb_curr_task(int);
#define GFP_KDB (in_dbg_master() ? GFP_ATOMIC : GFP_KERNEL)
-extern void *debug_kmalloc(size_t size, gfp_t flags);
-extern void debug_kfree(void *);
-extern void debug_kusage(void);
-
extern struct task_struct *kdb_current_task;
extern struct pt_regs *kdb_current_regs;
diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c
index 9f50d22d68e6..7507d9a8dc6a 100644
--- a/kernel/debug/kdb/kdb_support.c
+++ b/kernel/debug/kdb/kdb_support.c
@@ -10,7 +10,6 @@
* 03/02/13 added new 2.5 kallsyms <xavier.bru@bull.net>
*/
-#include <stdarg.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -52,48 +51,48 @@ int kdbgetsymval(const char *symname, kdb_symtab_t *symtab)
}
EXPORT_SYMBOL(kdbgetsymval);
-static char *kdb_name_table[100]; /* arbitrary size */
-
-/*
- * kdbnearsym - Return the name of the symbol with the nearest address
- * less than 'addr'.
+/**
+ * kdbnearsym() - Return the name of the symbol with the nearest address
+ * less than @addr.
+ * @addr: Address to check for near symbol
+ * @symtab: Structure to receive results
*
- * Parameters:
- * addr Address to check for symbol near
- * symtab Structure to receive results
- * Returns:
- * 0 No sections contain this address, symtab zero filled
- * 1 Address mapped to module/symbol/section, data in symtab
- * Remarks:
- * 2.6 kallsyms has a "feature" where it unpacks the name into a
- * string. If that string is reused before the caller expects it
- * then the caller sees its string change without warning. To
- * avoid cluttering up the main kdb code with lots of kdb_strdup,
- * tests and kfree calls, kdbnearsym maintains an LRU list of the
- * last few unique strings. The list is sized large enough to
- * hold active strings, no kdb caller of kdbnearsym makes more
- * than ~20 later calls before using a saved value.
+ * WARNING: This function may return a pointer to a single statically
+ * allocated buffer (namebuf). kdb's unusual calling context (single
+ * threaded, all other CPUs halted) provides us sufficient locking for
+ * this to be safe. The only constraint imposed by the static buffer is
+ * that the caller must consume any previous reply prior to another call
+ * to lookup a new symbol.
+ *
+ * Note that, strictly speaking, some architectures may re-enter the kdb
+ * trap if the system turns out to be very badly damaged and this breaks
+ * the single-threaded assumption above. In these circumstances successful
+ * continuation and exit from the inner trap is unlikely to work and any
+ * user attempting this receives a prominent warning before being allowed
+ * to progress. In these circumstances we remain memory safe because
+ * namebuf[KSYM_NAME_LEN-1] will never change from '\0' although we do
+ * tolerate the possibility of garbled symbol display from the outer kdb
+ * trap.
+ *
+ * Return:
+ * * 0 - No sections contain this address, symtab zero filled
+ * * 1 - Address mapped to module/symbol/section, data in symtab
*/
int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
{
int ret = 0;
unsigned long symbolsize = 0;
unsigned long offset = 0;
-#define knt1_size 128 /* must be >= kallsyms table size */
- char *knt1 = NULL;
+ static char namebuf[KSYM_NAME_LEN];
kdb_dbg_printf(AR, "addr=0x%lx, symtab=%px\n", addr, symtab);
memset(symtab, 0, sizeof(*symtab));
if (addr < 4096)
goto out;
- knt1 = debug_kmalloc(knt1_size, GFP_ATOMIC);
- if (!knt1) {
- kdb_func_printf("addr=0x%lx cannot kmalloc knt1\n", addr);
- goto out;
- }
+
symtab->sym_name = kallsyms_lookup(addr, &symbolsize , &offset,
- (char **)(&symtab->mod_name), knt1);
+ (char **)(&symtab->mod_name), namebuf);
if (offset > 8*1024*1024) {
symtab->sym_name = NULL;
addr = offset = symbolsize = 0;
@@ -102,63 +101,14 @@ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
symtab->sym_end = symtab->sym_start + symbolsize;
ret = symtab->sym_name != NULL && *(symtab->sym_name) != '\0';
- if (ret) {
- int i;
- /* Another 2.6 kallsyms "feature". Sometimes the sym_name is
- * set but the buffer passed into kallsyms_lookup is not used,
- * so it contains garbage. The caller has to work out which
- * buffer needs to be saved.
- *
- * What was Rusty smoking when he wrote that code?
- */
- if (symtab->sym_name != knt1) {
- strncpy(knt1, symtab->sym_name, knt1_size);
- knt1[knt1_size-1] = '\0';
- }
- for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) {
- if (kdb_name_table[i] &&
- strcmp(kdb_name_table[i], knt1) == 0)
- break;
- }
- if (i >= ARRAY_SIZE(kdb_name_table)) {
- debug_kfree(kdb_name_table[0]);
- memmove(kdb_name_table, kdb_name_table+1,
- sizeof(kdb_name_table[0]) *
- (ARRAY_SIZE(kdb_name_table)-1));
- } else {
- debug_kfree(knt1);
- knt1 = kdb_name_table[i];
- memmove(kdb_name_table+i, kdb_name_table+i+1,
- sizeof(kdb_name_table[0]) *
- (ARRAY_SIZE(kdb_name_table)-i-1));
- }
- i = ARRAY_SIZE(kdb_name_table) - 1;
- kdb_name_table[i] = knt1;
- symtab->sym_name = kdb_name_table[i];
- knt1 = NULL;
- }
-
if (symtab->mod_name == NULL)
symtab->mod_name = "kernel";
kdb_dbg_printf(AR, "returns %d symtab->sym_start=0x%lx, symtab->mod_name=%px, symtab->sym_name=%px (%s)\n",
ret, symtab->sym_start, symtab->mod_name, symtab->sym_name, symtab->sym_name);
-
out:
- debug_kfree(knt1);
return ret;
}
-void kdbnearsym_cleanup(void)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) {
- if (kdb_name_table[i]) {
- debug_kfree(kdb_name_table[i]);
- kdb_name_table[i] = NULL;
- }
- }
-}
-
static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1];
/*
@@ -656,230 +606,6 @@ unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask)
return (mask & kdb_task_state_string(state)) != 0;
}
-/* Last ditch allocator for debugging, so we can still debug even when
- * the GFP_ATOMIC pool has been exhausted. The algorithms are tuned
- * for space usage, not for speed. One smallish memory pool, the free
- * chain is always in ascending address order to allow coalescing,
- * allocations are done in brute force best fit.
- */
-
-struct debug_alloc_header {
- u32 next; /* offset of next header from start of pool */
- u32 size;
- void *caller;
-};
-
-/* The memory returned by this allocator must be aligned, which means
- * so must the header size. Do not assume that sizeof(struct
- * debug_alloc_header) is a multiple of the alignment, explicitly
- * calculate the overhead of this header, including the alignment.
- * The rest of this code must not use sizeof() on any header or
- * pointer to a header.
- */
-#define dah_align 8
-#define dah_overhead ALIGN(sizeof(struct debug_alloc_header), dah_align)
-
-static u64 debug_alloc_pool_aligned[256*1024/dah_align]; /* 256K pool */
-static char *debug_alloc_pool = (char *)debug_alloc_pool_aligned;
-static u32 dah_first, dah_first_call = 1, dah_used, dah_used_max;
-
-/* Locking is awkward. The debug code is called from all contexts,
- * including non maskable interrupts. A normal spinlock is not safe
- * in NMI context. Try to get the debug allocator lock, if it cannot
- * be obtained after a second then give up. If the lock could not be
- * previously obtained on this cpu then only try once.
- *
- * sparse has no annotation for "this function _sometimes_ acquires a
- * lock", so fudge the acquire/release notation.
- */
-static DEFINE_SPINLOCK(dap_lock);
-static int get_dap_lock(void)
- __acquires(dap_lock)
-{
- static int dap_locked = -1;
- int count;
- if (dap_locked == smp_processor_id())
- count = 1;
- else
- count = 1000;
- while (1) {
- if (spin_trylock(&dap_lock)) {
- dap_locked = -1;
- return 1;
- }
- if (!count--)
- break;
- udelay(1000);
- }
- dap_locked = smp_processor_id();
- __acquire(dap_lock);
- return 0;
-}
-
-void *debug_kmalloc(size_t size, gfp_t flags)
-{
- unsigned int rem, h_offset;
- struct debug_alloc_header *best, *bestprev, *prev, *h;
- void *p = NULL;
- if (!get_dap_lock()) {
- __release(dap_lock); /* we never actually got it */
- return NULL;
- }
- h = (struct debug_alloc_header *)(debug_alloc_pool + dah_first);
- if (dah_first_call) {
- h->size = sizeof(debug_alloc_pool_aligned) - dah_overhead;
- dah_first_call = 0;
- }
- size = ALIGN(size, dah_align);
- prev = best = bestprev = NULL;
- while (1) {
- if (h->size >= size && (!best || h->size < best->size)) {
- best = h;
- bestprev = prev;
- if (h->size == size)
- break;
- }
- if (!h->next)
- break;
- prev = h;
- h = (struct debug_alloc_header *)(debug_alloc_pool + h->next);
- }
- if (!best)
- goto out;
- rem = best->size - size;
- /* The pool must always contain at least one header */
- if (best->next == 0 && bestprev == NULL && rem < dah_overhead)
- goto out;
- if (rem >= dah_overhead) {
- best->size = size;
- h_offset = ((char *)best - debug_alloc_pool) +
- dah_overhead + best->size;
- h = (struct debug_alloc_header *)(debug_alloc_pool + h_offset);
- h->size = rem - dah_overhead;
- h->next = best->next;
- } else
- h_offset = best->next;
- best->caller = __builtin_return_address(0);
- dah_used += best->size;
- dah_used_max = max(dah_used, dah_used_max);
- if (bestprev)
- bestprev->next = h_offset;
- else
- dah_first = h_offset;
- p = (char *)best + dah_overhead;
- memset(p, POISON_INUSE, best->size - 1);
- *((char *)p + best->size - 1) = POISON_END;
-out:
- spin_unlock(&dap_lock);
- return p;
-}
-
-void debug_kfree(void *p)
-{
- struct debug_alloc_header *h;
- unsigned int h_offset;
- if (!p)
- return;
- if ((char *)p < debug_alloc_pool ||
- (char *)p >= debug_alloc_pool + sizeof(debug_alloc_pool_aligned)) {
- kfree(p);
- return;
- }
- if (!get_dap_lock()) {
- __release(dap_lock); /* we never actually got it */
- return; /* memory leak, cannot be helped */
- }
- h = (struct debug_alloc_header *)((char *)p - dah_overhead);
- memset(p, POISON_FREE, h->size - 1);
- *((char *)p + h->size - 1) = POISON_END;
- h->caller = NULL;
- dah_used -= h->size;
- h_offset = (char *)h - debug_alloc_pool;
- if (h_offset < dah_first) {
- h->next = dah_first;
- dah_first = h_offset;
- } else {
- struct debug_alloc_header *prev;
- unsigned int prev_offset;
- prev = (struct debug_alloc_header *)(debug_alloc_pool +
- dah_first);
- while (1) {
- if (!prev->next || prev->next > h_offset)
- break;
- prev = (struct debug_alloc_header *)
- (debug_alloc_pool + prev->next);
- }
- prev_offset = (char *)prev - debug_alloc_pool;
- if (prev_offset + dah_overhead + prev->size == h_offset) {
- prev->size += dah_overhead + h->size;
- memset(h, POISON_FREE, dah_overhead - 1);
- *((char *)h + dah_overhead - 1) = POISON_END;
- h = prev;
- h_offset = prev_offset;
- } else {
- h->next = prev->next;
- prev->next = h_offset;
- }
- }
- if (h_offset + dah_overhead + h->size == h->next) {
- struct debug_alloc_header *next;
- next = (struct debug_alloc_header *)
- (debug_alloc_pool + h->next);
- h->size += dah_overhead + next->size;
- h->next = next->next;
- memset(next, POISON_FREE, dah_overhead - 1);
- *((char *)next + dah_overhead - 1) = POISON_END;
- }
- spin_unlock(&dap_lock);
-}
-
-void debug_kusage(void)
-{
- struct debug_alloc_header *h_free, *h_used;
-#ifdef CONFIG_IA64
- /* FIXME: using dah for ia64 unwind always results in a memory leak.
- * Fix that memory leak first, then set debug_kusage_one_time = 1 for
- * all architectures.
- */
- static int debug_kusage_one_time;
-#else
- static int debug_kusage_one_time = 1;
-#endif
- if (!get_dap_lock()) {
- __release(dap_lock); /* we never actually got it */
- return;
- }
- h_free = (struct debug_alloc_header *)(debug_alloc_pool + dah_first);
- if (dah_first == 0 &&
- (h_free->size == sizeof(debug_alloc_pool_aligned) - dah_overhead ||
- dah_first_call))
- goto out;
- if (!debug_kusage_one_time)
- goto out;
- debug_kusage_one_time = 0;
- kdb_func_printf("debug_kmalloc memory leak dah_first %d\n", dah_first);
- if (dah_first) {
- h_used = (struct debug_alloc_header *)debug_alloc_pool;
- kdb_func_printf("h_used %px size %d\n", h_used, h_used->size);
- }
- do {
- h_used = (struct debug_alloc_header *)
- ((char *)h_free + dah_overhead + h_free->size);
- kdb_func_printf("h_used %px size %d caller %px\n",
- h_used, h_used->size, h_used->caller);
- h_free = (struct debug_alloc_header *)
- (debug_alloc_pool + h_free->next);
- } while (h_free->next);
- h_used = (struct debug_alloc_header *)
- ((char *)h_free + dah_overhead + h_free->size);
- if ((char *)h_used - debug_alloc_pool !=
- sizeof(debug_alloc_pool_aligned))
- kdb_func_printf("h_used %px size %d caller %px\n",
- h_used, h_used->size, h_used->caller);
-out:
- spin_unlock(&dap_lock);
-}
-
/* Maintain a small stack of kdb_flags to allow recursion without disturbing
* the global kdb state.
*/
diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig
index 77b405508743..1b02179758cb 100644
--- a/kernel/dma/Kconfig
+++ b/kernel/dma/Kconfig
@@ -80,6 +80,19 @@ config SWIOTLB
bool
select NEED_DMA_MAP_STATE
+config DMA_RESTRICTED_POOL
+ bool "DMA Restricted Pool"
+ depends on OF && OF_RESERVED_MEM && SWIOTLB
+ help
+ This enables support for restricted DMA pools which provide a level of
+ DMA memory protection on systems with limited hardware protection
+ capabilities, such as those lacking an IOMMU.
+
+ For more information see
+ <Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt>
+ and <kernel/dma/swiotlb.c>.
+ If unsure, say "n".
+
#
# Should be selected if we can mmap non-coherent mappings to userspace.
# The only thing that is really required is a way to set an uncached bit
@@ -93,6 +106,10 @@ config DMA_COHERENT_POOL
select GENERIC_ALLOCATOR
bool
+config DMA_GLOBAL_POOL
+ select DMA_DECLARE_COHERENT
+ bool
+
config DMA_REMAP
bool
depends on MMU
diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c
index 794e76b03b34..25fc85a7aebe 100644
--- a/kernel/dma/coherent.c
+++ b/kernel/dma/coherent.c
@@ -20,8 +20,6 @@ struct dma_coherent_mem {
bool use_dev_dma_pfn_offset;
};
-static struct dma_coherent_mem *dma_coherent_default_memory __ro_after_init;
-
static inline struct dma_coherent_mem *dev_get_coherent_memory(struct device *dev)
{
if (dev && dev->dma_mem)
@@ -37,51 +35,44 @@ static inline dma_addr_t dma_get_device_base(struct device *dev,
return mem->device_base;
}
-static int dma_init_coherent_memory(phys_addr_t phys_addr,
- dma_addr_t device_addr, size_t size,
- struct dma_coherent_mem **mem)
+static struct dma_coherent_mem *dma_init_coherent_memory(phys_addr_t phys_addr,
+ dma_addr_t device_addr, size_t size, bool use_dma_pfn_offset)
{
- struct dma_coherent_mem *dma_mem = NULL;
- void *mem_base = NULL;
+ struct dma_coherent_mem *dma_mem;
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
- int ret;
+ void *mem_base;
- if (!size) {
- ret = -EINVAL;
- goto out;
- }
+ if (!size)
+ return ERR_PTR(-EINVAL);
mem_base = memremap(phys_addr, size, MEMREMAP_WC);
- if (!mem_base) {
- ret = -EINVAL;
- goto out;
- }
+ if (!mem_base)
+ return ERR_PTR(-EINVAL);
+
dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
- if (!dma_mem) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!dma_mem)
+ goto out_unmap_membase;
dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- if (!dma_mem->bitmap) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!dma_mem->bitmap)
+ goto out_free_dma_mem;
dma_mem->virt_base = mem_base;
dma_mem->device_base = device_addr;
dma_mem->pfn_base = PFN_DOWN(phys_addr);
dma_mem->size = pages;
+ dma_mem->use_dev_dma_pfn_offset = use_dma_pfn_offset;
spin_lock_init(&dma_mem->spinlock);
- *mem = dma_mem;
- return 0;
+ return dma_mem;
-out:
+out_free_dma_mem:
kfree(dma_mem);
- if (mem_base)
- memunmap(mem_base);
- return ret;
+out_unmap_membase:
+ memunmap(mem_base);
+ pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %zd MiB\n",
+ &phys_addr, size / SZ_1M);
+ return ERR_PTR(-ENOMEM);
}
static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
@@ -130,9 +121,9 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
struct dma_coherent_mem *mem;
int ret;
- ret = dma_init_coherent_memory(phys_addr, device_addr, size, &mem);
- if (ret)
- return ret;
+ mem = dma_init_coherent_memory(phys_addr, device_addr, size, false);
+ if (IS_ERR(mem))
+ return PTR_ERR(mem);
ret = dma_assign_coherent_memory(dev, mem);
if (ret)
@@ -198,16 +189,6 @@ int dma_alloc_from_dev_coherent(struct device *dev, ssize_t size,
return 1;
}
-void *dma_alloc_from_global_coherent(struct device *dev, ssize_t size,
- dma_addr_t *dma_handle)
-{
- if (!dma_coherent_default_memory)
- return NULL;
-
- return __dma_alloc_from_coherent(dev, dma_coherent_default_memory, size,
- dma_handle);
-}
-
static int __dma_release_from_coherent(struct dma_coherent_mem *mem,
int order, void *vaddr)
{
@@ -243,15 +224,6 @@ int dma_release_from_dev_coherent(struct device *dev, int order, void *vaddr)
return __dma_release_from_coherent(mem, order, vaddr);
}
-int dma_release_from_global_coherent(int order, void *vaddr)
-{
- if (!dma_coherent_default_memory)
- return 0;
-
- return __dma_release_from_coherent(dma_coherent_default_memory, order,
- vaddr);
-}
-
static int __dma_mmap_from_coherent(struct dma_coherent_mem *mem,
struct vm_area_struct *vma, void *vaddr, size_t size, int *ret)
{
@@ -297,6 +269,28 @@ int dma_mmap_from_dev_coherent(struct device *dev, struct vm_area_struct *vma,
return __dma_mmap_from_coherent(mem, vma, vaddr, size, ret);
}
+#ifdef CONFIG_DMA_GLOBAL_POOL
+static struct dma_coherent_mem *dma_coherent_default_memory __ro_after_init;
+
+void *dma_alloc_from_global_coherent(struct device *dev, ssize_t size,
+ dma_addr_t *dma_handle)
+{
+ if (!dma_coherent_default_memory)
+ return NULL;
+
+ return __dma_alloc_from_coherent(dev, dma_coherent_default_memory, size,
+ dma_handle);
+}
+
+int dma_release_from_global_coherent(int order, void *vaddr)
+{
+ if (!dma_coherent_default_memory)
+ return 0;
+
+ return __dma_release_from_coherent(dma_coherent_default_memory, order,
+ vaddr);
+}
+
int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *vaddr,
size_t size, int *ret)
{
@@ -307,6 +301,19 @@ int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *vaddr,
vaddr, size, ret);
}
+int dma_init_global_coherent(phys_addr_t phys_addr, size_t size)
+{
+ struct dma_coherent_mem *mem;
+
+ mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true);
+ if (IS_ERR(mem))
+ return PTR_ERR(mem);
+ dma_coherent_default_memory = mem;
+ pr_info("DMA: default coherent area is set\n");
+ return 0;
+}
+#endif /* CONFIG_DMA_GLOBAL_POOL */
+
/*
* Support for reserved memory regions defined in device tree
*/
@@ -315,25 +322,22 @@ int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *vaddr,
#include <linux/of_fdt.h>
#include <linux/of_reserved_mem.h>
+#ifdef CONFIG_DMA_GLOBAL_POOL
static struct reserved_mem *dma_reserved_default_memory __initdata;
+#endif
static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
{
- struct dma_coherent_mem *mem = rmem->priv;
- int ret;
-
- if (!mem) {
- ret = dma_init_coherent_memory(rmem->base, rmem->base,
- rmem->size, &mem);
- if (ret) {
- pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
- &rmem->base, (unsigned long)rmem->size / SZ_1M);
- return ret;
- }
+ if (!rmem->priv) {
+ struct dma_coherent_mem *mem;
+
+ mem = dma_init_coherent_memory(rmem->base, rmem->base,
+ rmem->size, true);
+ if (IS_ERR(mem))
+ return PTR_ERR(mem);
+ rmem->priv = mem;
}
- mem->use_dev_dma_pfn_offset = true;
- rmem->priv = mem;
- dma_assign_coherent_memory(dev, mem);
+ dma_assign_coherent_memory(dev, rmem->priv);
return 0;
}
@@ -361,7 +365,9 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
pr_err("Reserved memory: regions without no-map are not yet supported\n");
return -EINVAL;
}
+#endif
+#ifdef CONFIG_DMA_GLOBAL_POOL
if (of_get_flat_dt_prop(node, "linux,dma-default", NULL)) {
WARN(dma_reserved_default_memory,
"Reserved memory: region for default DMA coherent area is redefined\n");
@@ -375,31 +381,16 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
return 0;
}
+#ifdef CONFIG_DMA_GLOBAL_POOL
static int __init dma_init_reserved_memory(void)
{
- const struct reserved_mem_ops *ops;
- int ret;
-
if (!dma_reserved_default_memory)
return -ENOMEM;
-
- ops = dma_reserved_default_memory->ops;
-
- /*
- * We rely on rmem_dma_device_init() does not propagate error of
- * dma_assign_coherent_memory() for "NULL" device.
- */
- ret = ops->device_init(dma_reserved_default_memory, NULL);
-
- if (!ret) {
- dma_coherent_default_memory = dma_reserved_default_memory->priv;
- pr_info("DMA: default coherent area is set\n");
- }
-
- return ret;
+ return dma_init_global_coherent(dma_reserved_default_memory->base,
+ dma_reserved_default_memory->size);
}
-
core_initcall(dma_init_reserved_memory);
+#endif /* CONFIG_DMA_GLOBAL_POOL */
RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup);
#endif
diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index dadae6255d05..6c90c69e5311 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -792,7 +792,7 @@ static int dump_show(struct seq_file *seq, void *v)
}
DEFINE_SHOW_ATTRIBUTE(dump);
-static void dma_debug_fs_init(void)
+static int __init dma_debug_fs_init(void)
{
struct dentry *dentry = debugfs_create_dir("dma-api", NULL);
@@ -805,7 +805,10 @@ static void dma_debug_fs_init(void)
debugfs_create_u32("nr_total_entries", 0444, dentry, &nr_total_entries);
debugfs_create_file("driver_filter", 0644, dentry, NULL, &filter_fops);
debugfs_create_file("dump", 0444, dentry, NULL, &dump_fops);
+
+ return 0;
}
+core_initcall_sync(dma_debug_fs_init);
static int device_dma_allocations(struct device *dev, struct dma_debug_entry **out_entry)
{
@@ -890,8 +893,6 @@ static int dma_debug_init(void)
spin_lock_init(&dma_entry_hash[i].lock);
}
- dma_debug_fs_init();
-
nr_pages = DIV_ROUND_UP(nr_prealloc_entries, DMA_DEBUG_DYNAMIC_ENTRIES);
for (i = 0; i < nr_pages; ++i)
dma_debug_create_entries(GFP_KERNEL);
@@ -1064,20 +1065,10 @@ static void check_for_stack(struct device *dev,
}
}
-static inline bool overlap(void *addr, unsigned long len, void *start, void *end)
-{
- unsigned long a1 = (unsigned long)addr;
- unsigned long b1 = a1 + len;
- unsigned long a2 = (unsigned long)start;
- unsigned long b2 = (unsigned long)end;
-
- return !(b1 <= a2 || a1 >= b2);
-}
-
static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len)
{
- if (overlap(addr, len, _stext, _etext) ||
- overlap(addr, len, __start_rodata, __end_rodata))
+ if (memory_intersects(_stext, _etext, addr, len) ||
+ memory_intersects(__start_rodata, __end_rodata, addr, len))
err_printk(dev, NULL, "device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len);
}
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index f737e3347059..4c6c5e0635e3 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -75,6 +75,15 @@ static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit);
}
+static void __dma_direct_free_pages(struct device *dev, struct page *page,
+ size_t size)
+{
+ if (IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL) &&
+ swiotlb_free(dev, page, size))
+ return;
+ dma_free_contiguous(dev, page, size);
+}
+
static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
gfp_t gfp)
{
@@ -86,6 +95,16 @@ static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
gfp |= dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
&phys_limit);
+ if (IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL) &&
+ is_swiotlb_for_alloc(dev)) {
+ page = swiotlb_alloc(dev, size);
+ if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
+ __dma_direct_free_pages(dev, page, size);
+ return NULL;
+ }
+ return page;
+ }
+
page = dma_alloc_contiguous(dev, size, gfp);
if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
dma_free_contiguous(dev, page, size);
@@ -142,7 +161,7 @@ void *dma_direct_alloc(struct device *dev, size_t size,
gfp |= __GFP_NOWARN;
if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
- !force_dma_unencrypted(dev)) {
+ !force_dma_unencrypted(dev) && !is_swiotlb_for_alloc(dev)) {
page = __dma_direct_alloc_pages(dev, size, gfp & ~__GFP_ZERO);
if (!page)
return NULL;
@@ -156,17 +175,28 @@ void *dma_direct_alloc(struct device *dev, size_t size,
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED) &&
!IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
- !dev_is_dma_coherent(dev))
+ !IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
+ !dev_is_dma_coherent(dev) &&
+ !is_swiotlb_for_alloc(dev))
return arch_dma_alloc(dev, size, dma_handle, gfp, attrs);
+ if (IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
+ !dev_is_dma_coherent(dev))
+ return dma_alloc_from_global_coherent(dev, size, dma_handle);
+
/*
* Remapping or decrypting memory may block. If either is required and
* we can't block, allocate the memory from the atomic pools.
+ * If restricted DMA (i.e., is_swiotlb_for_alloc) is required, one must
+ * set up another device coherent pool by shared-dma-pool and use
+ * dma_alloc_from_dev_coherent instead.
*/
if (IS_ENABLED(CONFIG_DMA_COHERENT_POOL) &&
!gfpflags_allow_blocking(gfp) &&
(force_dma_unencrypted(dev) ||
- (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !dev_is_dma_coherent(dev))))
+ (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
+ !dev_is_dma_coherent(dev))) &&
+ !is_swiotlb_for_alloc(dev))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
/* we always manually zero the memory once we are done */
@@ -237,7 +267,7 @@ out_encrypt_pages:
return NULL;
}
out_free_pages:
- dma_free_contiguous(dev, page, size);
+ __dma_direct_free_pages(dev, page, size);
return NULL;
}
@@ -247,7 +277,7 @@ void dma_direct_free(struct device *dev, size_t size,
unsigned int page_order = get_order(size);
if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
- !force_dma_unencrypted(dev)) {
+ !force_dma_unencrypted(dev) && !is_swiotlb_for_alloc(dev)) {
/* cpu_addr is a struct page cookie, not a kernel address */
dma_free_contiguous(dev, cpu_addr, size);
return;
@@ -255,11 +285,20 @@ void dma_direct_free(struct device *dev, size_t size,
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED) &&
!IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
- !dev_is_dma_coherent(dev)) {
+ !IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
+ !dev_is_dma_coherent(dev) &&
+ !is_swiotlb_for_alloc(dev)) {
arch_dma_free(dev, size, cpu_addr, dma_addr, attrs);
return;
}
+ if (IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
+ !dev_is_dma_coherent(dev)) {
+ if (!dma_release_from_global_coherent(page_order, cpu_addr))
+ WARN_ON_ONCE(1);
+ return;
+ }
+
/* If cpu_addr is not from an atomic pool, dma_free_from_pool() fails */
if (IS_ENABLED(CONFIG_DMA_COHERENT_POOL) &&
dma_free_from_pool(dev, cpu_addr, PAGE_ALIGN(size)))
@@ -273,7 +312,7 @@ void dma_direct_free(struct device *dev, size_t size,
else if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_CLEAR_UNCACHED))
arch_dma_clear_uncached(cpu_addr, size);
- dma_free_contiguous(dev, dma_direct_to_page(dev, dma_addr), size);
+ __dma_direct_free_pages(dev, dma_direct_to_page(dev, dma_addr), size);
}
struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
@@ -283,7 +322,8 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
void *ret;
if (IS_ENABLED(CONFIG_DMA_COHERENT_POOL) &&
- force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp))
+ force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp) &&
+ !is_swiotlb_for_alloc(dev))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
page = __dma_direct_alloc_pages(dev, size, gfp);
@@ -310,7 +350,7 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
*dma_handle = phys_to_dma_direct(dev, page_to_phys(page));
return page;
out_free_pages:
- dma_free_contiguous(dev, page, size);
+ __dma_direct_free_pages(dev, page, size);
return NULL;
}
@@ -329,7 +369,7 @@ void dma_direct_free_pages(struct device *dev, size_t size,
if (force_dma_unencrypted(dev))
set_memory_encrypted((unsigned long)vaddr, 1 << page_order);
- dma_free_contiguous(dev, page, size);
+ __dma_direct_free_pages(dev, page, size);
}
#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
@@ -343,7 +383,7 @@ void dma_direct_sync_sg_for_device(struct device *dev,
for_each_sg(sgl, sg, nents, i) {
phys_addr_t paddr = dma_to_phys(dev, sg_dma_address(sg));
- if (unlikely(is_swiotlb_buffer(paddr)))
+ if (unlikely(is_swiotlb_buffer(dev, paddr)))
swiotlb_sync_single_for_device(dev, paddr, sg->length,
dir);
@@ -369,7 +409,7 @@ void dma_direct_sync_sg_for_cpu(struct device *dev,
if (!dev_is_dma_coherent(dev))
arch_sync_dma_for_cpu(paddr, sg->length, dir);
- if (unlikely(is_swiotlb_buffer(paddr)))
+ if (unlikely(is_swiotlb_buffer(dev, paddr)))
swiotlb_sync_single_for_cpu(dev, paddr, sg->length,
dir);
@@ -411,7 +451,7 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
out_unmap:
dma_direct_unmap_sg(dev, sgl, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC);
- return 0;
+ return -EIO;
}
dma_addr_t dma_direct_map_resource(struct device *dev, phys_addr_t paddr,
@@ -462,6 +502,8 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
return ret;
+ if (dma_mmap_from_global_coherent(vma, cpu_addr, size, &ret))
+ return ret;
if (vma->vm_pgoff >= count || user_count > count - vma->vm_pgoff)
return -ENXIO;
@@ -495,8 +537,8 @@ int dma_direct_supported(struct device *dev, u64 mask)
size_t dma_direct_max_mapping_size(struct device *dev)
{
/* If SWIOTLB is active, use its maximum mapping size */
- if (is_swiotlb_active() &&
- (dma_addressing_limited(dev) || swiotlb_force == SWIOTLB_FORCE))
+ if (is_swiotlb_active(dev) &&
+ (dma_addressing_limited(dev) || is_swiotlb_force_bounce(dev)))
return swiotlb_max_mapping_size(dev);
return SIZE_MAX;
}
@@ -504,7 +546,7 @@ size_t dma_direct_max_mapping_size(struct device *dev)
bool dma_direct_need_sync(struct device *dev, dma_addr_t dma_addr)
{
return !dev_is_dma_coherent(dev) ||
- is_swiotlb_buffer(dma_to_phys(dev, dma_addr));
+ is_swiotlb_buffer(dev, dma_to_phys(dev, dma_addr));
}
/**
diff --git a/kernel/dma/direct.h b/kernel/dma/direct.h
index 50afc05b6f1d..4632b0f4f72e 100644
--- a/kernel/dma/direct.h
+++ b/kernel/dma/direct.h
@@ -56,7 +56,7 @@ static inline void dma_direct_sync_single_for_device(struct device *dev,
{
phys_addr_t paddr = dma_to_phys(dev, addr);
- if (unlikely(is_swiotlb_buffer(paddr)))
+ if (unlikely(is_swiotlb_buffer(dev, paddr)))
swiotlb_sync_single_for_device(dev, paddr, size, dir);
if (!dev_is_dma_coherent(dev))
@@ -73,7 +73,7 @@ static inline void dma_direct_sync_single_for_cpu(struct device *dev,
arch_sync_dma_for_cpu_all();
}
- if (unlikely(is_swiotlb_buffer(paddr)))
+ if (unlikely(is_swiotlb_buffer(dev, paddr)))
swiotlb_sync_single_for_cpu(dev, paddr, size, dir);
if (dir == DMA_FROM_DEVICE)
@@ -87,7 +87,7 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev,
phys_addr_t phys = page_to_phys(page) + offset;
dma_addr_t dma_addr = phys_to_dma(dev, phys);
- if (unlikely(swiotlb_force == SWIOTLB_FORCE))
+ if (is_swiotlb_force_bounce(dev))
return swiotlb_map(dev, phys, size, dir, attrs);
if (unlikely(!dma_capable(dev, dma_addr, size, true))) {
@@ -113,7 +113,7 @@ static inline void dma_direct_unmap_page(struct device *dev, dma_addr_t addr,
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
dma_direct_sync_single_for_cpu(dev, addr, size, dir);
- if (unlikely(is_swiotlb_buffer(phys)))
+ if (unlikely(is_swiotlb_buffer(dev, phys)))
swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs);
}
#endif /* _KERNEL_DMA_DIRECT_H */
diff --git a/kernel/dma/dummy.c b/kernel/dma/dummy.c
index eacd4c5b10bf..b492d59ac77e 100644
--- a/kernel/dma/dummy.c
+++ b/kernel/dma/dummy.c
@@ -22,7 +22,7 @@ static int dma_dummy_map_sg(struct device *dev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
unsigned long attrs)
{
- return 0;
+ return -EINVAL;
}
static int dma_dummy_supported(struct device *hwdev, u64 mask)
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 2b06a809d0b9..7ee5284bff58 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -177,12 +177,8 @@ void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr, size_t size,
}
EXPORT_SYMBOL(dma_unmap_page_attrs);
-/*
- * dma_maps_sg_attrs returns 0 on error and > 0 on success.
- * It should never return a value < 0.
- */
-int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, unsigned long attrs)
+static int __dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir, unsigned long attrs)
{
const struct dma_map_ops *ops = get_dma_ops(dev);
int ents;
@@ -197,13 +193,81 @@ int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents,
ents = dma_direct_map_sg(dev, sg, nents, dir, attrs);
else
ents = ops->map_sg(dev, sg, nents, dir, attrs);
- BUG_ON(ents < 0);
- debug_dma_map_sg(dev, sg, nents, ents, dir);
+
+ if (ents > 0)
+ debug_dma_map_sg(dev, sg, nents, ents, dir);
+ else if (WARN_ON_ONCE(ents != -EINVAL && ents != -ENOMEM &&
+ ents != -EIO))
+ return -EIO;
return ents;
}
+
+/**
+ * dma_map_sg_attrs - Map the given buffer for DMA
+ * @dev: The device for which to perform the DMA operation
+ * @sg: The sg_table object describing the buffer
+ * @dir: DMA direction
+ * @attrs: Optional DMA attributes for the map operation
+ *
+ * Maps a buffer described by a scatterlist passed in the sg argument with
+ * nents segments for the @dir DMA operation by the @dev device.
+ *
+ * Returns the number of mapped entries (which can be less than nents)
+ * on success. Zero is returned for any error.
+ *
+ * dma_unmap_sg_attrs() should be used to unmap the buffer with the
+ * original sg and original nents (not the value returned by this funciton).
+ */
+unsigned int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir, unsigned long attrs)
+{
+ int ret;
+
+ ret = __dma_map_sg_attrs(dev, sg, nents, dir, attrs);
+ if (ret < 0)
+ return 0;
+ return ret;
+}
EXPORT_SYMBOL(dma_map_sg_attrs);
+/**
+ * dma_map_sgtable - Map the given buffer for DMA
+ * @dev: The device for which to perform the DMA operation
+ * @sgt: The sg_table object describing the buffer
+ * @dir: DMA direction
+ * @attrs: Optional DMA attributes for the map operation
+ *
+ * Maps a buffer described by a scatterlist stored in the given sg_table
+ * object for the @dir DMA operation by the @dev device. After success, the
+ * ownership for the buffer is transferred to the DMA domain. One has to
+ * call dma_sync_sgtable_for_cpu() or dma_unmap_sgtable() to move the
+ * ownership of the buffer back to the CPU domain before touching the
+ * buffer by the CPU.
+ *
+ * Returns 0 on success or a negative error code on error. The following
+ * error codes are supported with the given meaning:
+ *
+ * -EINVAL - An invalid argument, unaligned access or other error
+ * in usage. Will not succeed if retried.
+ * -ENOMEM - Insufficient resources (like memory or IOVA space) to
+ * complete the mapping. Should succeed if retried later.
+ * -EIO - Legacy error code with an unknown meaning. eg. this is
+ * returned if a lower level call returned DMA_MAPPING_ERROR.
+ */
+int dma_map_sgtable(struct device *dev, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ int nents;
+
+ nents = __dma_map_sg_attrs(dev, sgt->sgl, sgt->orig_nents, dir, attrs);
+ if (nents < 0)
+ return nents;
+ sgt->nents = nents;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dma_map_sgtable);
+
void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
unsigned long attrs)
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index e50df8d8f87e..87c40517e822 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -39,6 +39,13 @@
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#endif
+#ifdef CONFIG_DMA_RESTRICTED_POOL
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/slab.h>
+#endif
#include <asm/io.h>
#include <asm/dma.h>
@@ -63,7 +70,7 @@
enum swiotlb_force swiotlb_force;
-struct io_tlb_mem *io_tlb_default_mem;
+struct io_tlb_mem io_tlb_default_mem;
/*
* Max segment that we can provide which (if pages are contingous) will
@@ -94,7 +101,7 @@ early_param("swiotlb", setup_io_tlb_npages);
unsigned int swiotlb_max_segment(void)
{
- return io_tlb_default_mem ? max_segment : 0;
+ return io_tlb_default_mem.nslabs ? max_segment : 0;
}
EXPORT_SYMBOL_GPL(swiotlb_max_segment);
@@ -127,9 +134,9 @@ void __init swiotlb_adjust_size(unsigned long size)
void swiotlb_print_info(void)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
+ struct io_tlb_mem *mem = &io_tlb_default_mem;
- if (!mem) {
+ if (!mem->nslabs) {
pr_warn("No low mem\n");
return;
}
@@ -156,11 +163,11 @@ static inline unsigned long nr_slots(u64 val)
*/
void __init swiotlb_update_mem_attributes(void)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
+ struct io_tlb_mem *mem = &io_tlb_default_mem;
void *vaddr;
unsigned long bytes;
- if (!mem || mem->late_alloc)
+ if (!mem->nslabs || mem->late_alloc)
return;
vaddr = phys_to_virt(mem->start);
bytes = PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT);
@@ -168,36 +175,50 @@ void __init swiotlb_update_mem_attributes(void)
memset(vaddr, 0, bytes);
}
-int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
+static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,
+ unsigned long nslabs, bool late_alloc)
{
+ void *vaddr = phys_to_virt(start);
unsigned long bytes = nslabs << IO_TLB_SHIFT, i;
- struct io_tlb_mem *mem;
- size_t alloc_size;
-
- if (swiotlb_force == SWIOTLB_NO_FORCE)
- return 0;
-
- /* protect against double initialization */
- if (WARN_ON_ONCE(io_tlb_default_mem))
- return -ENOMEM;
- alloc_size = PAGE_ALIGN(struct_size(mem, slots, nslabs));
- mem = memblock_alloc(alloc_size, PAGE_SIZE);
- if (!mem)
- panic("%s: Failed to allocate %zu bytes align=0x%lx\n",
- __func__, alloc_size, PAGE_SIZE);
mem->nslabs = nslabs;
- mem->start = __pa(tlb);
+ mem->start = start;
mem->end = mem->start + bytes;
mem->index = 0;
+ mem->late_alloc = late_alloc;
+
+ if (swiotlb_force == SWIOTLB_FORCE)
+ mem->force_bounce = true;
+
spin_lock_init(&mem->lock);
for (i = 0; i < mem->nslabs; i++) {
mem->slots[i].list = IO_TLB_SEGSIZE - io_tlb_offset(i);
mem->slots[i].orig_addr = INVALID_PHYS_ADDR;
mem->slots[i].alloc_size = 0;
}
+ memset(vaddr, 0, bytes);
+}
+
+int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
+{
+ struct io_tlb_mem *mem = &io_tlb_default_mem;
+ size_t alloc_size;
+
+ if (swiotlb_force == SWIOTLB_NO_FORCE)
+ return 0;
+
+ /* protect against double initialization */
+ if (WARN_ON_ONCE(mem->nslabs))
+ return -ENOMEM;
+
+ alloc_size = PAGE_ALIGN(array_size(sizeof(*mem->slots), nslabs));
+ mem->slots = memblock_alloc(alloc_size, PAGE_SIZE);
+ if (!mem->slots)
+ panic("%s: Failed to allocate %zu bytes align=0x%lx\n",
+ __func__, alloc_size, PAGE_SIZE);
+
+ swiotlb_init_io_tlb_mem(mem, __pa(tlb), nslabs, false);
- io_tlb_default_mem = mem;
if (verbose)
swiotlb_print_info();
swiotlb_set_max_segment(mem->nslabs << IO_TLB_SHIFT);
@@ -282,37 +303,24 @@ swiotlb_late_init_with_default_size(size_t default_size)
int
swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
{
- unsigned long bytes = nslabs << IO_TLB_SHIFT, i;
- struct io_tlb_mem *mem;
+ struct io_tlb_mem *mem = &io_tlb_default_mem;
+ unsigned long bytes = nslabs << IO_TLB_SHIFT;
if (swiotlb_force == SWIOTLB_NO_FORCE)
return 0;
/* protect against double initialization */
- if (WARN_ON_ONCE(io_tlb_default_mem))
+ if (WARN_ON_ONCE(mem->nslabs))
return -ENOMEM;
- mem = (void *)__get_free_pages(GFP_KERNEL,
- get_order(struct_size(mem, slots, nslabs)));
- if (!mem)
+ mem->slots = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(array_size(sizeof(*mem->slots), nslabs)));
+ if (!mem->slots)
return -ENOMEM;
- mem->nslabs = nslabs;
- mem->start = virt_to_phys(tlb);
- mem->end = mem->start + bytes;
- mem->index = 0;
- mem->late_alloc = 1;
- spin_lock_init(&mem->lock);
- for (i = 0; i < mem->nslabs; i++) {
- mem->slots[i].list = IO_TLB_SEGSIZE - io_tlb_offset(i);
- mem->slots[i].orig_addr = INVALID_PHYS_ADDR;
- mem->slots[i].alloc_size = 0;
- }
-
set_memory_decrypted((unsigned long)tlb, bytes >> PAGE_SHIFT);
- memset(tlb, 0, bytes);
+ swiotlb_init_io_tlb_mem(mem, virt_to_phys(tlb), nslabs, true);
- io_tlb_default_mem = mem;
swiotlb_print_info();
swiotlb_set_max_segment(mem->nslabs << IO_TLB_SHIFT);
return 0;
@@ -320,18 +328,28 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
void __init swiotlb_exit(void)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
- size_t size;
+ struct io_tlb_mem *mem = &io_tlb_default_mem;
+ unsigned long tbl_vaddr;
+ size_t tbl_size, slots_size;
- if (!mem)
+ if (!mem->nslabs)
return;
- size = struct_size(mem, slots, mem->nslabs);
- if (mem->late_alloc)
- free_pages((unsigned long)mem, get_order(size));
- else
- memblock_free_late(__pa(mem), PAGE_ALIGN(size));
- io_tlb_default_mem = NULL;
+ pr_info("tearing down default memory pool\n");
+ tbl_vaddr = (unsigned long)phys_to_virt(mem->start);
+ tbl_size = PAGE_ALIGN(mem->end - mem->start);
+ slots_size = PAGE_ALIGN(array_size(sizeof(*mem->slots), mem->nslabs));
+
+ set_memory_encrypted(tbl_vaddr, tbl_size >> PAGE_SHIFT);
+ if (mem->late_alloc) {
+ free_pages(tbl_vaddr, get_order(tbl_size));
+ free_pages((unsigned long)mem->slots, get_order(slots_size));
+ } else {
+ memblock_free_late(mem->start, tbl_size);
+ memblock_free_late(__pa(mem->slots), slots_size);
+ }
+
+ memset(mem, 0, sizeof(*mem));
}
/*
@@ -348,19 +366,33 @@ static unsigned int swiotlb_align_offset(struct device *dev, u64 addr)
static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size,
enum dma_data_direction dir)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
int index = (tlb_addr - mem->start) >> IO_TLB_SHIFT;
phys_addr_t orig_addr = mem->slots[index].orig_addr;
size_t alloc_size = mem->slots[index].alloc_size;
unsigned long pfn = PFN_DOWN(orig_addr);
unsigned char *vaddr = phys_to_virt(tlb_addr);
- unsigned int tlb_offset;
+ unsigned int tlb_offset, orig_addr_offset;
if (orig_addr == INVALID_PHYS_ADDR)
return;
- tlb_offset = (tlb_addr & (IO_TLB_SIZE - 1)) -
- swiotlb_align_offset(dev, orig_addr);
+ tlb_offset = tlb_addr & (IO_TLB_SIZE - 1);
+ orig_addr_offset = swiotlb_align_offset(dev, orig_addr);
+ if (tlb_offset < orig_addr_offset) {
+ dev_WARN_ONCE(dev, 1,
+ "Access before mapping start detected. orig offset %u, requested offset %u.\n",
+ orig_addr_offset, tlb_offset);
+ return;
+ }
+
+ tlb_offset -= orig_addr_offset;
+ if (tlb_offset > alloc_size) {
+ dev_WARN_ONCE(dev, 1,
+ "Buffer overflow detected. Allocation size: %zu. Mapping size: %zu+%u.\n",
+ alloc_size, size, tlb_offset);
+ return;
+ }
orig_addr += tlb_offset;
alloc_size -= tlb_offset;
@@ -426,10 +458,10 @@ static unsigned int wrap_index(struct io_tlb_mem *mem, unsigned int index)
* Find a suitable number of IO TLB entries size that will fit this request and
* allocate a buffer from that IO TLB pool.
*/
-static int find_slots(struct device *dev, phys_addr_t orig_addr,
- size_t alloc_size)
+static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr,
+ size_t alloc_size)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
unsigned long boundary_mask = dma_get_seg_boundary(dev);
dma_addr_t tbl_dma_addr =
phys_to_dma_unencrypted(dev, mem->start) & boundary_mask;
@@ -438,6 +470,7 @@ static int find_slots(struct device *dev, phys_addr_t orig_addr,
dma_get_min_align_mask(dev) & ~(IO_TLB_SIZE - 1);
unsigned int nslots = nr_slots(alloc_size), stride;
unsigned int index, wrap, count = 0, i;
+ unsigned int offset = swiotlb_align_offset(dev, orig_addr);
unsigned long flags;
BUG_ON(!nslots);
@@ -457,8 +490,9 @@ static int find_slots(struct device *dev, phys_addr_t orig_addr,
index = wrap = wrap_index(mem, ALIGN(mem->index, stride));
do {
- if ((slot_addr(tbl_dma_addr, index) & iotlb_align_mask) !=
- (orig_addr & iotlb_align_mask)) {
+ if (orig_addr &&
+ (slot_addr(tbl_dma_addr, index) & iotlb_align_mask) !=
+ (orig_addr & iotlb_align_mask)) {
index = wrap_index(mem, index + 1);
continue;
}
@@ -482,8 +516,11 @@ not_found:
return -1;
found:
- for (i = index; i < index + nslots; i++)
+ for (i = index; i < index + nslots; i++) {
mem->slots[i].list = 0;
+ mem->slots[i].alloc_size =
+ alloc_size - (offset + ((i - index) << IO_TLB_SHIFT));
+ }
for (i = index - 1;
io_tlb_offset(i) != IO_TLB_SEGSIZE - 1 &&
mem->slots[i].list; i--)
@@ -506,7 +543,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
size_t mapping_size, size_t alloc_size,
enum dma_data_direction dir, unsigned long attrs)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
unsigned int offset = swiotlb_align_offset(dev, orig_addr);
unsigned int i;
int index;
@@ -524,7 +561,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
return (phys_addr_t)DMA_MAPPING_ERROR;
}
- index = find_slots(dev, orig_addr, alloc_size + offset);
+ index = swiotlb_find_slots(dev, orig_addr, alloc_size + offset);
if (index == -1) {
if (!(attrs & DMA_ATTR_NO_WARN))
dev_warn_ratelimited(dev,
@@ -538,11 +575,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
* This is needed when we sync the memory. Then we sync the buffer if
* needed.
*/
- for (i = 0; i < nr_slots(alloc_size + offset); i++) {
+ for (i = 0; i < nr_slots(alloc_size + offset); i++)
mem->slots[index + i].orig_addr = slot_addr(orig_addr, i);
- mem->slots[index + i].alloc_size =
- alloc_size - (i << IO_TLB_SHIFT);
- }
tlb_addr = slot_addr(mem->start, index) + offset;
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
@@ -550,28 +584,16 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
return tlb_addr;
}
-/*
- * tlb_addr is the physical address of the bounce buffer to unmap.
- */
-void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr,
- size_t mapping_size, enum dma_data_direction dir,
- unsigned long attrs)
+static void swiotlb_release_slots(struct device *dev, phys_addr_t tlb_addr)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
unsigned long flags;
- unsigned int offset = swiotlb_align_offset(hwdev, tlb_addr);
+ unsigned int offset = swiotlb_align_offset(dev, tlb_addr);
int index = (tlb_addr - offset - mem->start) >> IO_TLB_SHIFT;
int nslots = nr_slots(mem->slots[index].alloc_size + offset);
int count, i;
/*
- * First, sync the memory before unmapping the entry
- */
- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
- (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
- swiotlb_bounce(hwdev, tlb_addr, mapping_size, DMA_FROM_DEVICE);
-
- /*
* Return the buffer to the free list by setting the corresponding
* entries to indicate the number of contiguous entries available.
* While returning the entries to the free list, we merge the entries
@@ -605,6 +627,23 @@ void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr,
spin_unlock_irqrestore(&mem->lock, flags);
}
+/*
+ * tlb_addr is the physical address of the bounce buffer to unmap.
+ */
+void swiotlb_tbl_unmap_single(struct device *dev, phys_addr_t tlb_addr,
+ size_t mapping_size, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ /*
+ * First, sync the memory before unmapping the entry
+ */
+ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
+ (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
+ swiotlb_bounce(dev, tlb_addr, mapping_size, DMA_FROM_DEVICE);
+
+ swiotlb_release_slots(dev, tlb_addr);
+}
+
void swiotlb_sync_single_for_device(struct device *dev, phys_addr_t tlb_addr,
size_t size, enum dma_data_direction dir)
{
@@ -662,26 +701,155 @@ size_t swiotlb_max_mapping_size(struct device *dev)
return ((size_t)IO_TLB_SIZE) * IO_TLB_SEGSIZE;
}
-bool is_swiotlb_active(void)
+bool is_swiotlb_active(struct device *dev)
{
- return io_tlb_default_mem != NULL;
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
+
+ return mem && mem->nslabs;
}
EXPORT_SYMBOL_GPL(is_swiotlb_active);
#ifdef CONFIG_DEBUG_FS
+static struct dentry *debugfs_dir;
-static int __init swiotlb_create_debugfs(void)
+static void swiotlb_create_debugfs_files(struct io_tlb_mem *mem)
{
- struct io_tlb_mem *mem = io_tlb_default_mem;
-
- if (!mem)
- return 0;
- mem->debugfs = debugfs_create_dir("swiotlb", NULL);
debugfs_create_ulong("io_tlb_nslabs", 0400, mem->debugfs, &mem->nslabs);
debugfs_create_ulong("io_tlb_used", 0400, mem->debugfs, &mem->used);
+}
+
+static int __init swiotlb_create_default_debugfs(void)
+{
+ struct io_tlb_mem *mem = &io_tlb_default_mem;
+
+ debugfs_dir = debugfs_create_dir("swiotlb", NULL);
+ if (mem->nslabs) {
+ mem->debugfs = debugfs_dir;
+ swiotlb_create_debugfs_files(mem);
+ }
return 0;
}
-late_initcall(swiotlb_create_debugfs);
+late_initcall(swiotlb_create_default_debugfs);
+
+#endif
+#ifdef CONFIG_DMA_RESTRICTED_POOL
+
+#ifdef CONFIG_DEBUG_FS
+static void rmem_swiotlb_debugfs_init(struct reserved_mem *rmem)
+{
+ struct io_tlb_mem *mem = rmem->priv;
+
+ mem->debugfs = debugfs_create_dir(rmem->name, debugfs_dir);
+ swiotlb_create_debugfs_files(mem);
+}
+#else
+static void rmem_swiotlb_debugfs_init(struct reserved_mem *rmem)
+{
+}
#endif
+
+struct page *swiotlb_alloc(struct device *dev, size_t size)
+{
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
+ phys_addr_t tlb_addr;
+ int index;
+
+ if (!mem)
+ return NULL;
+
+ index = swiotlb_find_slots(dev, 0, size);
+ if (index == -1)
+ return NULL;
+
+ tlb_addr = slot_addr(mem->start, index);
+
+ return pfn_to_page(PFN_DOWN(tlb_addr));
+}
+
+bool swiotlb_free(struct device *dev, struct page *page, size_t size)
+{
+ phys_addr_t tlb_addr = page_to_phys(page);
+
+ if (!is_swiotlb_buffer(dev, tlb_addr))
+ return false;
+
+ swiotlb_release_slots(dev, tlb_addr);
+
+ return true;
+}
+
+static int rmem_swiotlb_device_init(struct reserved_mem *rmem,
+ struct device *dev)
+{
+ struct io_tlb_mem *mem = rmem->priv;
+ unsigned long nslabs = rmem->size >> IO_TLB_SHIFT;
+
+ /*
+ * Since multiple devices can share the same pool, the private data,
+ * io_tlb_mem struct, will be initialized by the first device attached
+ * to it.
+ */
+ if (!mem) {
+ mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+ if (!mem)
+ return -ENOMEM;
+
+ mem->slots = kzalloc(array_size(sizeof(*mem->slots), nslabs),
+ GFP_KERNEL);
+ if (!mem->slots) {
+ kfree(mem);
+ return -ENOMEM;
+ }
+
+ set_memory_decrypted((unsigned long)phys_to_virt(rmem->base),
+ rmem->size >> PAGE_SHIFT);
+ swiotlb_init_io_tlb_mem(mem, rmem->base, nslabs, false);
+ mem->force_bounce = true;
+ mem->for_alloc = true;
+
+ rmem->priv = mem;
+
+ rmem_swiotlb_debugfs_init(rmem);
+ }
+
+ dev->dma_io_tlb_mem = mem;
+
+ return 0;
+}
+
+static void rmem_swiotlb_device_release(struct reserved_mem *rmem,
+ struct device *dev)
+{
+ dev->dma_io_tlb_mem = &io_tlb_default_mem;
+}
+
+static const struct reserved_mem_ops rmem_swiotlb_ops = {
+ .device_init = rmem_swiotlb_device_init,
+ .device_release = rmem_swiotlb_device_release,
+};
+
+static int __init rmem_swiotlb_setup(struct reserved_mem *rmem)
+{
+ unsigned long node = rmem->fdt_node;
+
+ if (of_get_flat_dt_prop(node, "reusable", NULL) ||
+ of_get_flat_dt_prop(node, "linux,cma-default", NULL) ||
+ of_get_flat_dt_prop(node, "linux,dma-default", NULL) ||
+ of_get_flat_dt_prop(node, "no-map", NULL))
+ return -EINVAL;
+
+ if (PageHighMem(pfn_to_page(PHYS_PFN(rmem->base)))) {
+ pr_err("Restricted DMA pool must be accessible within the linear mapping.");
+ return -EINVAL;
+ }
+
+ rmem->ops = &rmem_swiotlb_ops;
+ pr_info("Reserved memory: created restricted DMA pool at %pa, size %ld MiB\n",
+ &rmem->base, (unsigned long)rmem->size / SZ_1M);
+ return 0;
+}
+
+RESERVEDMEM_OF_DECLARE(dma, "restricted-dma-pool", rmem_swiotlb_setup);
+#endif /* CONFIG_DMA_RESTRICTED_POOL */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 011cc5069b7b..744e8726c5b2 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -8320,8 +8320,6 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
else
flags = MAP_PRIVATE;
- if (vma->vm_flags & VM_DENYWRITE)
- flags |= MAP_DENYWRITE;
if (vma->vm_flags & VM_LOCKED)
flags |= MAP_LOCKED;
if (is_vm_hugetlb_page(vma))
diff --git a/kernel/fork.c b/kernel/fork.c
index 695d1343a254..6d2e10a3df0b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -471,6 +471,20 @@ void free_task(struct task_struct *tsk)
}
EXPORT_SYMBOL(free_task);
+static void dup_mm_exe_file(struct mm_struct *mm, struct mm_struct *oldmm)
+{
+ struct file *exe_file;
+
+ exe_file = get_mm_exe_file(oldmm);
+ RCU_INIT_POINTER(mm->exe_file, exe_file);
+ /*
+ * We depend on the oldmm having properly denied write access to the
+ * exe_file already.
+ */
+ if (exe_file && deny_write_access(exe_file))
+ pr_warn_once("deny_write_access() failed in %s\n", __func__);
+}
+
#ifdef CONFIG_MMU
static __latent_entropy int dup_mmap(struct mm_struct *mm,
struct mm_struct *oldmm)
@@ -494,7 +508,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
mmap_write_lock_nested(mm, SINGLE_DEPTH_NESTING);
/* No ordering required: file already has been exposed. */
- RCU_INIT_POINTER(mm->exe_file, get_mm_exe_file(oldmm));
+ dup_mm_exe_file(mm, oldmm);
mm->total_vm = oldmm->total_vm;
mm->data_vm = oldmm->data_vm;
@@ -557,12 +571,9 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
tmp->vm_flags &= ~(VM_LOCKED | VM_LOCKONFAULT);
file = tmp->vm_file;
if (file) {
- struct inode *inode = file_inode(file);
struct address_space *mapping = file->f_mapping;
get_file(file);
- if (tmp->vm_flags & VM_DENYWRITE)
- put_write_access(inode);
i_mmap_lock_write(mapping);
if (tmp->vm_flags & VM_SHARED)
mapping_allow_writable(mapping);
@@ -640,7 +651,7 @@ static inline void mm_free_pgd(struct mm_struct *mm)
static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
{
mmap_write_lock(oldmm);
- RCU_INIT_POINTER(mm->exe_file, get_mm_exe_file(oldmm));
+ dup_mm_exe_file(mm, oldmm);
mmap_write_unlock(oldmm);
return 0;
}
@@ -1150,11 +1161,11 @@ void mmput_async(struct mm_struct *mm)
*
* Main users are mmput() and sys_execve(). Callers prevent concurrent
* invocations: in mmput() nobody alive left, in execve task is single
- * threaded. sys_prctl(PR_SET_MM_MAP/EXE_FILE) also needs to set the
- * mm->exe_file, but does so without using set_mm_exe_file() in order
- * to avoid the need for any locks.
+ * threaded.
+ *
+ * Can only fail if new_exe_file != NULL.
*/
-void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
+int set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
{
struct file *old_exe_file;
@@ -1165,11 +1176,73 @@ void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
*/
old_exe_file = rcu_dereference_raw(mm->exe_file);
- if (new_exe_file)
+ if (new_exe_file) {
+ /*
+ * We expect the caller (i.e., sys_execve) to already denied
+ * write access, so this is unlikely to fail.
+ */
+ if (unlikely(deny_write_access(new_exe_file)))
+ return -EACCES;
get_file(new_exe_file);
+ }
rcu_assign_pointer(mm->exe_file, new_exe_file);
- if (old_exe_file)
+ if (old_exe_file) {
+ allow_write_access(old_exe_file);
fput(old_exe_file);
+ }
+ return 0;
+}
+
+/**
+ * replace_mm_exe_file - replace a reference to the mm's executable file
+ *
+ * This changes mm's executable file (shown as symlink /proc/[pid]/exe),
+ * dealing with concurrent invocation and without grabbing the mmap lock in
+ * write mode.
+ *
+ * Main user is sys_prctl(PR_SET_MM_MAP/EXE_FILE).
+ */
+int replace_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
+{
+ struct vm_area_struct *vma;
+ struct file *old_exe_file;
+ int ret = 0;
+
+ /* Forbid mm->exe_file change if old file still mapped. */
+ old_exe_file = get_mm_exe_file(mm);
+ if (old_exe_file) {
+ mmap_read_lock(mm);
+ for (vma = mm->mmap; vma && !ret; vma = vma->vm_next) {
+ if (!vma->vm_file)
+ continue;
+ if (path_equal(&vma->vm_file->f_path,
+ &old_exe_file->f_path))
+ ret = -EBUSY;
+ }
+ mmap_read_unlock(mm);
+ fput(old_exe_file);
+ if (ret)
+ return ret;
+ }
+
+ /* set the new file, lockless */
+ ret = deny_write_access(new_exe_file);
+ if (ret)
+ return -EACCES;
+ get_file(new_exe_file);
+
+ old_exe_file = xchg(&mm->exe_file, new_exe_file);
+ if (old_exe_file) {
+ /*
+ * Don't race with dup_mmap() getting the file and disallowing
+ * write access while someone might open the file writable.
+ */
+ mmap_read_lock(mm);
+ allow_write_access(old_exe_file);
+ fput(old_exe_file);
+ mmap_read_unlock(mm);
+ }
+ return 0;
}
/**
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 62be16135e7c..19e83e9b723c 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -491,6 +491,7 @@ struct irq_domain *irq_get_default_host(void)
{
return irq_default_domain;
}
+EXPORT_SYMBOL_GPL(irq_get_default_host);
static bool irq_domain_is_nomap(struct irq_domain *domain)
{
diff --git a/kernel/kcsan/atomic.h b/kernel/kcsan/atomic.h
deleted file mode 100644
index 530ae1bda8e7..000000000000
--- a/kernel/kcsan/atomic.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Rules for implicitly atomic memory accesses.
- *
- * Copyright (C) 2019, Google LLC.
- */
-
-#ifndef _KERNEL_KCSAN_ATOMIC_H
-#define _KERNEL_KCSAN_ATOMIC_H
-
-#include <linux/types.h>
-
-/*
- * Special rules for certain memory where concurrent conflicting accesses are
- * common, however, the current convention is to not mark them; returns true if
- * access to @ptr should be considered atomic. Called from slow-path.
- */
-static bool kcsan_is_atomic_special(const volatile void *ptr)
-{
- return false;
-}
-
-#endif /* _KERNEL_KCSAN_ATOMIC_H */
diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c
index 26709ea65c71..76e67d1e02d4 100644
--- a/kernel/kcsan/core.c
+++ b/kernel/kcsan/core.c
@@ -20,9 +20,9 @@
#include <linux/sched.h>
#include <linux/uaccess.h>
-#include "atomic.h"
#include "encoding.h"
#include "kcsan.h"
+#include "permissive.h"
static bool kcsan_early_enable = IS_ENABLED(CONFIG_KCSAN_EARLY_ENABLE);
unsigned int kcsan_udelay_task = CONFIG_KCSAN_UDELAY_TASK;
@@ -301,9 +301,9 @@ static inline void reset_kcsan_skip(void)
this_cpu_write(kcsan_skip, skip_count);
}
-static __always_inline bool kcsan_is_enabled(void)
+static __always_inline bool kcsan_is_enabled(struct kcsan_ctx *ctx)
{
- return READ_ONCE(kcsan_enabled) && get_ctx()->disable_count == 0;
+ return READ_ONCE(kcsan_enabled) && !ctx->disable_count;
}
/* Introduce delay depending on context and configuration. */
@@ -353,10 +353,18 @@ static noinline void kcsan_found_watchpoint(const volatile void *ptr,
atomic_long_t *watchpoint,
long encoded_watchpoint)
{
+ const bool is_assert = (type & KCSAN_ACCESS_ASSERT) != 0;
+ struct kcsan_ctx *ctx = get_ctx();
unsigned long flags;
bool consumed;
- if (!kcsan_is_enabled())
+ /*
+ * We know a watchpoint exists. Let's try to keep the race-window
+ * between here and finally consuming the watchpoint below as small as
+ * possible -- avoid unneccessarily complex code until consumed.
+ */
+
+ if (!kcsan_is_enabled(ctx))
return;
/*
@@ -364,14 +372,22 @@ static noinline void kcsan_found_watchpoint(const volatile void *ptr,
* reporting a race where e.g. the writer set up the watchpoint, but the
* reader has access_mask!=0, we have to ignore the found watchpoint.
*/
- if (get_ctx()->access_mask != 0)
+ if (ctx->access_mask)
return;
/*
- * Consume the watchpoint as soon as possible, to minimize the chances
- * of !consumed. Consuming the watchpoint must always be guarded by
- * kcsan_is_enabled() check, as otherwise we might erroneously
- * triggering reports when disabled.
+ * If the other thread does not want to ignore the access, and there was
+ * a value change as a result of this thread's operation, we will still
+ * generate a report of unknown origin.
+ *
+ * Use CONFIG_KCSAN_REPORT_RACE_UNKNOWN_ORIGIN=n to filter.
+ */
+ if (!is_assert && kcsan_ignore_address(ptr))
+ return;
+
+ /*
+ * Consuming the watchpoint must be guarded by kcsan_is_enabled() to
+ * avoid erroneously triggering reports if the context is disabled.
*/
consumed = try_consume_watchpoint(watchpoint, encoded_watchpoint);
@@ -391,7 +407,7 @@ static noinline void kcsan_found_watchpoint(const volatile void *ptr,
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_REPORT_RACES]);
}
- if ((type & KCSAN_ACCESS_ASSERT) != 0)
+ if (is_assert)
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_ASSERT_FAILURES]);
else
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_DATA_RACES]);
@@ -409,6 +425,7 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
unsigned long access_mask;
enum kcsan_value_change value_change = KCSAN_VALUE_CHANGE_MAYBE;
unsigned long ua_flags = user_access_save();
+ struct kcsan_ctx *ctx = get_ctx();
unsigned long irq_flags = 0;
/*
@@ -417,16 +434,14 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
*/
reset_kcsan_skip();
- if (!kcsan_is_enabled())
+ if (!kcsan_is_enabled(ctx))
goto out;
/*
- * Special atomic rules: unlikely to be true, so we check them here in
- * the slow-path, and not in the fast-path in is_atomic(). Call after
- * kcsan_is_enabled(), as we may access memory that is not yet
- * initialized during early boot.
+ * Check to-ignore addresses after kcsan_is_enabled(), as we may access
+ * memory that is not yet initialized during early boot.
*/
- if (!is_assert && kcsan_is_atomic_special(ptr))
+ if (!is_assert && kcsan_ignore_address(ptr))
goto out;
if (!check_encodable((unsigned long)ptr, size)) {
@@ -479,15 +494,6 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
break; /* ignore; we do not diff the values */
}
- if (IS_ENABLED(CONFIG_KCSAN_DEBUG)) {
- kcsan_disable_current();
- pr_err("watching %s, size: %zu, addr: %px [slot: %d, encoded: %lx]\n",
- is_write ? "write" : "read", size, ptr,
- watchpoint_slot((unsigned long)ptr),
- encode_watchpoint((unsigned long)ptr, size, is_write));
- kcsan_enable_current();
- }
-
/*
* Delay this thread, to increase probability of observing a racy
* conflicting access.
@@ -498,7 +504,7 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
* Re-read value, and check if it is as expected; if not, we infer a
* racy access.
*/
- access_mask = get_ctx()->access_mask;
+ access_mask = ctx->access_mask;
new = 0;
switch (size) {
case 1:
@@ -521,8 +527,14 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
if (access_mask)
diff &= access_mask;
- /* Were we able to observe a value-change? */
- if (diff != 0)
+ /*
+ * Check if we observed a value change.
+ *
+ * Also check if the data race should be ignored (the rules depend on
+ * non-zero diff); if it is to be ignored, the below rules for
+ * KCSAN_VALUE_CHANGE_MAYBE apply.
+ */
+ if (diff && !kcsan_ignore_data_race(size, type, old, new, diff))
value_change = KCSAN_VALUE_CHANGE_TRUE;
/* Check if this access raced with another. */
@@ -644,6 +656,15 @@ void __init kcsan_init(void)
pr_info("enabled early\n");
WRITE_ONCE(kcsan_enabled, true);
}
+
+ if (IS_ENABLED(CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY) ||
+ IS_ENABLED(CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC) ||
+ IS_ENABLED(CONFIG_KCSAN_PERMISSIVE) ||
+ IS_ENABLED(CONFIG_KCSAN_IGNORE_ATOMICS)) {
+ pr_warn("non-strict mode configured - use CONFIG_KCSAN_STRICT=y to see all data races\n");
+ } else {
+ pr_info("strict mode configured\n");
+ }
}
/* === Exported interface =================================================== */
diff --git a/kernel/kcsan/kcsan_test.c b/kernel/kcsan/kcsan_test.c
index 8bcffbdef3d3..dc55fd5a36fc 100644
--- a/kernel/kcsan/kcsan_test.c
+++ b/kernel/kcsan/kcsan_test.c
@@ -414,6 +414,14 @@ static noinline void test_kernel_atomic_builtins(void)
__atomic_load_n(&test_var, __ATOMIC_RELAXED);
}
+static noinline void test_kernel_xor_1bit(void)
+{
+ /* Do not report data races between the read-writes. */
+ kcsan_nestable_atomic_begin();
+ test_var ^= 0x10000;
+ kcsan_nestable_atomic_end();
+}
+
/* ===== Test cases ===== */
/* Simple test with normal data race. */
@@ -952,6 +960,29 @@ static void test_atomic_builtins(struct kunit *test)
KUNIT_EXPECT_FALSE(test, match_never);
}
+__no_kcsan
+static void test_1bit_value_change(struct kunit *test)
+{
+ const struct expect_report expect = {
+ .access = {
+ { test_kernel_read, &test_var, sizeof(test_var), 0 },
+ { test_kernel_xor_1bit, &test_var, sizeof(test_var), __KCSAN_ACCESS_RW(KCSAN_ACCESS_WRITE) },
+ },
+ };
+ bool match = false;
+
+ begin_test_checks(test_kernel_read, test_kernel_xor_1bit);
+ do {
+ match = IS_ENABLED(CONFIG_KCSAN_PERMISSIVE)
+ ? report_available()
+ : report_matches(&expect);
+ } while (!end_test_checks(match));
+ if (IS_ENABLED(CONFIG_KCSAN_PERMISSIVE))
+ KUNIT_EXPECT_FALSE(test, match);
+ else
+ KUNIT_EXPECT_TRUE(test, match);
+}
+
/*
* Generate thread counts for all test cases. Values generated are in interval
* [2, 5] followed by exponentially increasing thread counts from 8 to 32.
@@ -1024,6 +1055,7 @@ static struct kunit_case kcsan_test_cases[] = {
KCSAN_KUNIT_CASE(test_jiffies_noreport),
KCSAN_KUNIT_CASE(test_seqlock_noreport),
KCSAN_KUNIT_CASE(test_atomic_builtins),
+ KCSAN_KUNIT_CASE(test_1bit_value_change),
{},
};
diff --git a/kernel/kcsan/permissive.h b/kernel/kcsan/permissive.h
new file mode 100644
index 000000000000..2c01fe4a59ee
--- /dev/null
+++ b/kernel/kcsan/permissive.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Special rules for ignoring entire classes of data-racy memory accesses. None
+ * of the rules here imply that such data races are generally safe!
+ *
+ * All rules in this file can be configured via CONFIG_KCSAN_PERMISSIVE. Keep
+ * them separate from core code to make it easier to audit.
+ *
+ * Copyright (C) 2019, Google LLC.
+ */
+
+#ifndef _KERNEL_KCSAN_PERMISSIVE_H
+#define _KERNEL_KCSAN_PERMISSIVE_H
+
+#include <linux/bitops.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+
+/*
+ * Access ignore rules based on address.
+ */
+static __always_inline bool kcsan_ignore_address(const volatile void *ptr)
+{
+ if (!IS_ENABLED(CONFIG_KCSAN_PERMISSIVE))
+ return false;
+
+ /*
+ * Data-racy bitops on current->flags are too common, ignore completely
+ * for now.
+ */
+ return ptr == &current->flags;
+}
+
+/*
+ * Data race ignore rules based on access type and value change patterns.
+ */
+static bool
+kcsan_ignore_data_race(size_t size, int type, u64 old, u64 new, u64 diff)
+{
+ if (!IS_ENABLED(CONFIG_KCSAN_PERMISSIVE))
+ return false;
+
+ /*
+ * Rules here are only for plain read accesses, so that we still report
+ * data races between plain read-write accesses.
+ */
+ if (type || size > sizeof(long))
+ return false;
+
+ /*
+ * A common pattern is checking/setting just 1 bit in a variable; for
+ * example:
+ *
+ * if (flags & SOME_FLAG) { ... }
+ *
+ * and elsewhere flags is updated concurrently:
+ *
+ * flags |= SOME_OTHER_FLAG; // just 1 bit
+ *
+ * While it is still recommended that such accesses be marked
+ * appropriately, in many cases these types of data races are so common
+ * that marking them all is often unrealistic and left to maintainer
+ * preference.
+ *
+ * The assumption in all cases is that with all known compiler
+ * optimizations (including those that tear accesses), because no more
+ * than 1 bit changed, the plain accesses are safe despite the presence
+ * of data races.
+ *
+ * The rules here will ignore the data races if we observe no more than
+ * 1 bit changed.
+ *
+ * Of course many operations can effecively change just 1 bit, but the
+ * general assuption that data races involving 1-bit changes can be
+ * tolerated still applies.
+ *
+ * And in case a true bug is missed, the bug likely manifests as a
+ * reportable data race elsewhere.
+ */
+ if (hweight64(diff) == 1) {
+ /*
+ * Exception: Report data races where the values look like
+ * ordinary booleans (one of them was 0 and the 0th bit was
+ * changed) More often than not, they come with interesting
+ * memory ordering requirements, so let's report them.
+ */
+ if (!((!old || !new) && diff == 1))
+ return true;
+ }
+
+ return false;
+}
+
+#endif /* _KERNEL_KCSAN_PERMISSIVE_H */
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 4b34a9aa32bc..5a5d192a89ac 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -979,7 +979,6 @@ void crash_kexec(struct pt_regs *regs)
old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu);
if (old_cpu == PANIC_CPU_INVALID) {
/* This is the 1st CPU which comes here, so go ahead. */
- printk_safe_flush_on_panic();
__crash_kexec(regs);
/*
diff --git a/kernel/livepatch/transition.c b/kernel/livepatch/transition.c
index 3a4beb9395c4..291b857a6e20 100644
--- a/kernel/livepatch/transition.c
+++ b/kernel/livepatch/transition.c
@@ -411,7 +411,7 @@ void klp_try_complete_transition(void)
/*
* Ditto for the idle "swapper" tasks.
*/
- get_online_cpus();
+ cpus_read_lock();
for_each_possible_cpu(cpu) {
task = idle_task(cpu);
if (cpu_online(cpu)) {
@@ -423,7 +423,7 @@ void klp_try_complete_transition(void)
task->patch_state = klp_target_state;
}
}
- put_online_cpus();
+ cpus_read_unlock();
if (!complete) {
if (klp_signals_cnt && !(klp_signals_cnt % SIGNALS_TIMEOUT))
diff --git a/kernel/module.c b/kernel/module.c
index ed13917ea5f3..40ec9a030eec 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3355,6 +3355,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)
sizeof(unsigned long),
&mod->num_kprobe_blacklist);
#endif
+#ifdef CONFIG_PRINTK_INDEX
+ mod->printk_index_start = section_objs(info, ".printk_index",
+ sizeof(*mod->printk_index_start),
+ &mod->printk_index_size);
+#endif
#ifdef CONFIG_HAVE_STATIC_CALL_INLINE
mod->static_call_sites = section_objs(info, ".static_call_sites",
sizeof(*mod->static_call_sites),
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index abc01fcad8c7..eec72ca962e2 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -568,6 +568,6 @@ out:
int __init nsproxy_cache_init(void)
{
- nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
+ nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC|SLAB_ACCOUNT);
return 0;
}
diff --git a/kernel/panic.c b/kernel/panic.c
index edad89660a2b..cefd7d82366f 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -248,7 +248,6 @@ void panic(const char *fmt, ...)
* Bypass the panic_cpu check and call __crash_kexec directly.
*/
if (!_crash_kexec_post_notifiers) {
- printk_safe_flush_on_panic();
__crash_kexec(NULL);
/*
@@ -272,8 +271,6 @@ void panic(const char *fmt, ...)
*/
atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
- /* Call flush even twice. It tries harder with a single online CPU */
- printk_safe_flush_on_panic();
kmsg_dump(KMSG_DUMP_PANIC);
/*
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index ca43239a255a..a46a3723bc66 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -51,7 +51,8 @@ static struct kmem_cache *create_pid_cachep(unsigned int level)
mutex_lock(&pid_caches_mutex);
/* Name collision forces to do allocation under mutex. */
if (!*pkc)
- *pkc = kmem_cache_create(name, len, 0, SLAB_HWCACHE_ALIGN, 0);
+ *pkc = kmem_cache_create(name, len, 0,
+ SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT, 0);
mutex_unlock(&pid_caches_mutex);
/* current can fail, but someone else can succeed. */
return READ_ONCE(*pkc);
@@ -449,7 +450,7 @@ const struct proc_ns_operations pidns_for_children_operations = {
static __init int pid_namespaces_init(void)
{
- pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
+ pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC | SLAB_ACCOUNT);
#ifdef CONFIG_CHECKPOINT_RESTORE
register_sysctl_paths(kern_path, pid_ns_ctl_table);
diff --git a/kernel/printk/Makefile b/kernel/printk/Makefile
index eee3dc9b60a9..d118739874c0 100644
--- a/kernel/printk/Makefile
+++ b/kernel/printk/Makefile
@@ -3,3 +3,4 @@ obj-y = printk.o
obj-$(CONFIG_PRINTK) += printk_safe.o
obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o
obj-$(CONFIG_PRINTK) += printk_ringbuffer.o
+obj-$(CONFIG_PRINTK_INDEX) += index.o
diff --git a/kernel/printk/index.c b/kernel/printk/index.c
new file mode 100644
index 000000000000..d3709408debe
--- /dev/null
+++ b/kernel/printk/index.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Userspace indexing of printk formats
+ */
+
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+
+#include "internal.h"
+
+extern struct pi_entry *__start_printk_index[];
+extern struct pi_entry *__stop_printk_index[];
+
+/* The base dir for module formats, typically debugfs/printk/index/ */
+static struct dentry *dfs_index;
+
+static struct pi_entry *pi_get_entry(const struct module *mod, loff_t pos)
+{
+ struct pi_entry **entries;
+ unsigned int nr_entries;
+
+#ifdef CONFIG_MODULES
+ if (mod) {
+ entries = mod->printk_index_start;
+ nr_entries = mod->printk_index_size;
+ }
+#endif
+
+ if (!mod) {
+ /* vmlinux, comes from linker symbols */
+ entries = __start_printk_index;
+ nr_entries = __stop_printk_index - __start_printk_index;
+ }
+
+ if (pos >= nr_entries)
+ return NULL;
+
+ return entries[pos];
+}
+
+static void *pi_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ const struct module *mod = s->file->f_inode->i_private;
+ struct pi_entry *entry = pi_get_entry(mod, *pos);
+
+ (*pos)++;
+
+ return entry;
+}
+
+static void *pi_start(struct seq_file *s, loff_t *pos)
+{
+ /*
+ * Make show() print the header line. Do not update *pos because
+ * pi_next() still has to return the entry at index 0 later.
+ */
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
+ return pi_next(s, NULL, pos);
+}
+
+/*
+ * We need both ESCAPE_ANY and explicit characters from ESCAPE_SPECIAL in @only
+ * because otherwise ESCAPE_NAP will cause double quotes and backslashes to be
+ * ignored for quoting.
+ */
+#define seq_escape_printf_format(s, src) \
+ seq_escape_str(s, src, ESCAPE_ANY | ESCAPE_NAP | ESCAPE_APPEND, "\"\\")
+
+static int pi_show(struct seq_file *s, void *v)
+{
+ const struct pi_entry *entry = v;
+ int level = LOGLEVEL_DEFAULT;
+ enum printk_info_flags flags = 0;
+ u16 prefix_len = 0;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(s, "# <level/flags> filename:line function \"format\"\n");
+ return 0;
+ }
+
+ if (!entry->fmt)
+ return 0;
+
+ if (entry->level)
+ printk_parse_prefix(entry->level, &level, &flags);
+ else
+ prefix_len = printk_parse_prefix(entry->fmt, &level, &flags);
+
+
+ if (flags & LOG_CONT) {
+ /*
+ * LOGLEVEL_DEFAULT here means "use the same level as the
+ * message we're continuing from", not the default message
+ * loglevel, so don't display it as such.
+ */
+ if (level == LOGLEVEL_DEFAULT)
+ seq_puts(s, "<c>");
+ else
+ seq_printf(s, "<%d,c>", level);
+ } else
+ seq_printf(s, "<%d>", level);
+
+ seq_printf(s, " %s:%d %s \"", entry->file, entry->line, entry->func);
+ if (entry->subsys_fmt_prefix)
+ seq_escape_printf_format(s, entry->subsys_fmt_prefix);
+ seq_escape_printf_format(s, entry->fmt + prefix_len);
+ seq_puts(s, "\"\n");
+
+ return 0;
+}
+
+static void pi_stop(struct seq_file *p, void *v) { }
+
+static const struct seq_operations dfs_index_sops = {
+ .start = pi_start,
+ .next = pi_next,
+ .show = pi_show,
+ .stop = pi_stop,
+};
+
+DEFINE_SEQ_ATTRIBUTE(dfs_index);
+
+#ifdef CONFIG_MODULES
+static const char *pi_get_module_name(struct module *mod)
+{
+ return mod ? mod->name : "vmlinux";
+}
+#else
+static const char *pi_get_module_name(struct module *mod)
+{
+ return "vmlinux";
+}
+#endif
+
+static void pi_create_file(struct module *mod)
+{
+ debugfs_create_file(pi_get_module_name(mod), 0444, dfs_index,
+ mod, &dfs_index_fops);
+}
+
+#ifdef CONFIG_MODULES
+static void pi_remove_file(struct module *mod)
+{
+ debugfs_remove(debugfs_lookup(pi_get_module_name(mod), dfs_index));
+}
+
+static int pi_module_notify(struct notifier_block *nb, unsigned long op,
+ void *data)
+{
+ struct module *mod = data;
+
+ switch (op) {
+ case MODULE_STATE_COMING:
+ pi_create_file(mod);
+ break;
+ case MODULE_STATE_GOING:
+ pi_remove_file(mod);
+ break;
+ default: /* we don't care about other module states */
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block module_printk_fmts_nb = {
+ .notifier_call = pi_module_notify,
+};
+
+static void __init pi_setup_module_notifier(void)
+{
+ register_module_notifier(&module_printk_fmts_nb);
+}
+#else
+static inline void __init pi_setup_module_notifier(void) { }
+#endif
+
+static int __init pi_init(void)
+{
+ struct dentry *dfs_root = debugfs_create_dir("printk", NULL);
+
+ dfs_index = debugfs_create_dir("index", dfs_root);
+ pi_setup_module_notifier();
+ pi_create_file(NULL);
+
+ return 0;
+}
+
+/* debugfs comes up on core and must be initialised first */
+postcore_initcall(pi_init);
diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
index 51615c909b2f..9f3ed2fdb721 100644
--- a/kernel/printk/internal.h
+++ b/kernel/printk/internal.h
@@ -6,11 +6,11 @@
#ifdef CONFIG_PRINTK
-#define PRINTK_SAFE_CONTEXT_MASK 0x007ffffff
-#define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x008000000
-#define PRINTK_NMI_CONTEXT_MASK 0xff0000000
-
-#define PRINTK_NMI_CONTEXT_OFFSET 0x010000000
+/* Flags for a single printk record. */
+enum printk_info_flags {
+ LOG_NEWLINE = 2, /* text ended with a newline */
+ LOG_CONT = 8, /* text is a fragment of a continuation line */
+};
__printf(4, 0)
int vprintk_store(int facility, int level,
@@ -19,10 +19,7 @@ int vprintk_store(int facility, int level,
__printf(1, 0) int vprintk_default(const char *fmt, va_list args);
__printf(1, 0) int vprintk_deferred(const char *fmt, va_list args);
-void __printk_safe_enter(void);
-void __printk_safe_exit(void);
-void printk_safe_init(void);
bool printk_percpu_data_ready(void);
#define printk_safe_enter_irqsave(flags) \
@@ -37,20 +34,10 @@ bool printk_percpu_data_ready(void);
local_irq_restore(flags); \
} while (0)
-#define printk_safe_enter_irq() \
- do { \
- local_irq_disable(); \
- __printk_safe_enter(); \
- } while (0)
-
-#define printk_safe_exit_irq() \
- do { \
- __printk_safe_exit(); \
- local_irq_enable(); \
- } while (0)
-
void defer_console_output(void);
+u16 printk_parse_prefix(const char *text, int *level,
+ enum printk_info_flags *flags);
#else
/*
@@ -61,9 +48,5 @@ void defer_console_output(void);
#define printk_safe_enter_irqsave(flags) local_irq_save(flags)
#define printk_safe_exit_irqrestore(flags) local_irq_restore(flags)
-#define printk_safe_enter_irq() local_irq_disable()
-#define printk_safe_exit_irq() local_irq_enable()
-
-static inline void printk_safe_init(void) { }
static inline bool printk_percpu_data_ready(void) { return false; }
#endif /* CONFIG_PRINTK */
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 142a58d124d9..825277e1e742 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -350,13 +350,8 @@ static int console_msg_format = MSG_FORMAT_DEFAULT;
* non-prinatable characters are escaped in the "\xff" notation.
*/
-enum log_flags {
- LOG_NEWLINE = 2, /* text ended with a newline */
- LOG_CONT = 8, /* text is a fragment of a continuation line */
-};
-
/* syslog_lock protects syslog_* variables and write access to clear_seq. */
-static DEFINE_RAW_SPINLOCK(syslog_lock);
+static DEFINE_MUTEX(syslog_lock);
#ifdef CONFIG_PRINTK
DECLARE_WAIT_QUEUE_HEAD(log_wait);
@@ -732,27 +727,22 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
if (ret)
return ret;
- printk_safe_enter_irq();
if (!prb_read_valid(prb, atomic64_read(&user->seq), r)) {
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
- printk_safe_exit_irq();
goto out;
}
- printk_safe_exit_irq();
ret = wait_event_interruptible(log_wait,
prb_read_valid(prb, atomic64_read(&user->seq), r));
if (ret)
goto out;
- printk_safe_enter_irq();
}
if (r->info->seq != atomic64_read(&user->seq)) {
/* our last seen message is gone, return error and reset */
atomic64_set(&user->seq, r->info->seq);
ret = -EPIPE;
- printk_safe_exit_irq();
goto out;
}
@@ -762,7 +752,6 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
&r->info->dev_info);
atomic64_set(&user->seq, r->info->seq + 1);
- printk_safe_exit_irq();
if (len > count) {
ret = -EINVAL;
@@ -797,7 +786,6 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
if (offset)
return -ESPIPE;
- printk_safe_enter_irq();
switch (whence) {
case SEEK_SET:
/* the first record */
@@ -818,7 +806,6 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
default:
ret = -EINVAL;
}
- printk_safe_exit_irq();
return ret;
}
@@ -833,7 +820,6 @@ static __poll_t devkmsg_poll(struct file *file, poll_table *wait)
poll_wait(file, &log_wait, wait);
- printk_safe_enter_irq();
if (prb_read_valid_info(prb, atomic64_read(&user->seq), &info, NULL)) {
/* return error when data has vanished underneath us */
if (info.seq != atomic64_read(&user->seq))
@@ -841,7 +827,6 @@ static __poll_t devkmsg_poll(struct file *file, poll_table *wait)
else
ret = EPOLLIN|EPOLLRDNORM;
}
- printk_safe_exit_irq();
return ret;
}
@@ -874,9 +859,7 @@ static int devkmsg_open(struct inode *inode, struct file *file)
prb_rec_init_rd(&user->record, &user->info,
&user->text_buf[0], sizeof(user->text_buf));
- printk_safe_enter_irq();
atomic64_set(&user->seq, prb_first_valid_seq(prb));
- printk_safe_exit_irq();
file->private_data = user;
return 0;
@@ -1042,9 +1025,6 @@ static inline void log_buf_add_cpu(void) {}
static void __init set_percpu_data_ready(void)
{
- printk_safe_init();
- /* Make sure we set this flag only after printk_safe() init is done */
- barrier();
__printk_percpu_data_ready = true;
}
@@ -1082,6 +1062,7 @@ void __init setup_log_buf(int early)
struct prb_desc *new_descs;
struct printk_info info;
struct printk_record r;
+ unsigned int text_size;
size_t new_descs_size;
size_t new_infos_size;
unsigned long flags;
@@ -1142,24 +1123,37 @@ void __init setup_log_buf(int early)
new_descs, ilog2(new_descs_count),
new_infos);
- printk_safe_enter_irqsave(flags);
+ local_irq_save(flags);
log_buf_len = new_log_buf_len;
log_buf = new_log_buf;
new_log_buf_len = 0;
free = __LOG_BUF_LEN;
- prb_for_each_record(0, &printk_rb_static, seq, &r)
- free -= add_to_rb(&printk_rb_dynamic, &r);
+ prb_for_each_record(0, &printk_rb_static, seq, &r) {
+ text_size = add_to_rb(&printk_rb_dynamic, &r);
+ if (text_size > free)
+ free = 0;
+ else
+ free -= text_size;
+ }
- /*
- * This is early enough that everything is still running on the
- * boot CPU and interrupts are disabled. So no new messages will
- * appear during the transition to the dynamic buffer.
- */
prb = &printk_rb_dynamic;
- printk_safe_exit_irqrestore(flags);
+ local_irq_restore(flags);
+
+ /*
+ * Copy any remaining messages that might have appeared from
+ * NMI context after copying but before switching to the
+ * dynamic buffer.
+ */
+ prb_for_each_record(seq, &printk_rb_static, seq, &r) {
+ text_size = add_to_rb(&printk_rb_dynamic, &r);
+ if (text_size > free)
+ free = 0;
+ else
+ free -= text_size;
+ }
if (seq != prb_next_seq(&printk_rb_static)) {
pr_err("dropped %llu messages\n",
@@ -1481,12 +1475,14 @@ static u64 find_first_fitting_seq(u64 start_seq, u64 max_seq, size_t size,
return seq;
}
+/* The caller is responsible for making sure @size is greater than 0. */
static int syslog_print(char __user *buf, int size)
{
struct printk_info info;
struct printk_record r;
char *text;
int len = 0;
+ u64 seq;
text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL);
if (!text)
@@ -1494,17 +1490,35 @@ static int syslog_print(char __user *buf, int size)
prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX);
- while (size > 0) {
+ mutex_lock(&syslog_lock);
+
+ /*
+ * Wait for the @syslog_seq record to be available. @syslog_seq may
+ * change while waiting.
+ */
+ do {
+ seq = syslog_seq;
+
+ mutex_unlock(&syslog_lock);
+ len = wait_event_interruptible(log_wait, prb_read_valid(prb, seq, NULL));
+ mutex_lock(&syslog_lock);
+
+ if (len)
+ goto out;
+ } while (syslog_seq != seq);
+
+ /*
+ * Copy records that fit into the buffer. The above cycle makes sure
+ * that the first record is always available.
+ */
+ do {
size_t n;
size_t skip;
+ int err;
- printk_safe_enter_irq();
- raw_spin_lock(&syslog_lock);
- if (!prb_read_valid(prb, syslog_seq, &r)) {
- raw_spin_unlock(&syslog_lock);
- printk_safe_exit_irq();
+ if (!prb_read_valid(prb, syslog_seq, &r))
break;
- }
+
if (r.info->seq != syslog_seq) {
/* message is gone, move to next valid one */
syslog_seq = r.info->seq;
@@ -1531,13 +1545,15 @@ static int syslog_print(char __user *buf, int size)
syslog_partial += n;
} else
n = 0;
- raw_spin_unlock(&syslog_lock);
- printk_safe_exit_irq();
if (!n)
break;
- if (copy_to_user(buf, text + skip, n)) {
+ mutex_unlock(&syslog_lock);
+ err = copy_to_user(buf, text + skip, n);
+ mutex_lock(&syslog_lock);
+
+ if (err) {
if (!len)
len = -EFAULT;
break;
@@ -1546,8 +1562,9 @@ static int syslog_print(char __user *buf, int size)
len += n;
size -= n;
buf += n;
- }
-
+ } while (size);
+out:
+ mutex_unlock(&syslog_lock);
kfree(text);
return len;
}
@@ -1566,7 +1583,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
return -ENOMEM;
time = printk_time;
- printk_safe_enter_irq();
/*
* Find first record that fits, including all following records,
* into the user-provided buffer for this dump.
@@ -1587,23 +1603,20 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
break;
}
- printk_safe_exit_irq();
if (copy_to_user(buf + len, text, textlen))
len = -EFAULT;
else
len += textlen;
- printk_safe_enter_irq();
if (len < 0)
break;
}
if (clear) {
- raw_spin_lock(&syslog_lock);
+ mutex_lock(&syslog_lock);
latched_seq_write(&clear_seq, seq);
- raw_spin_unlock(&syslog_lock);
+ mutex_unlock(&syslog_lock);
}
- printk_safe_exit_irq();
kfree(text);
return len;
@@ -1611,23 +1624,9 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
static void syslog_clear(void)
{
- printk_safe_enter_irq();
- raw_spin_lock(&syslog_lock);
+ mutex_lock(&syslog_lock);
latched_seq_write(&clear_seq, prb_next_seq(prb));
- raw_spin_unlock(&syslog_lock);
- printk_safe_exit_irq();
-}
-
-/* Return a consistent copy of @syslog_seq. */
-static u64 read_syslog_seq_irq(void)
-{
- u64 seq;
-
- raw_spin_lock_irq(&syslog_lock);
- seq = syslog_seq;
- raw_spin_unlock_irq(&syslog_lock);
-
- return seq;
+ mutex_unlock(&syslog_lock);
}
int do_syslog(int type, char __user *buf, int len, int source)
@@ -1653,11 +1652,6 @@ int do_syslog(int type, char __user *buf, int len, int source)
return 0;
if (!access_ok(buf, len))
return -EFAULT;
-
- error = wait_event_interruptible(log_wait,
- prb_read_valid(prb, read_syslog_seq_irq(), NULL));
- if (error)
- return error;
error = syslog_print(buf, len);
break;
/* Read/clear last kernel messages */
@@ -1703,12 +1697,10 @@ int do_syslog(int type, char __user *buf, int len, int source)
break;
/* Number of chars in the log buffer */
case SYSLOG_ACTION_SIZE_UNREAD:
- printk_safe_enter_irq();
- raw_spin_lock(&syslog_lock);
+ mutex_lock(&syslog_lock);
if (!prb_read_valid_info(prb, syslog_seq, &info, NULL)) {
/* No unread messages. */
- raw_spin_unlock(&syslog_lock);
- printk_safe_exit_irq();
+ mutex_unlock(&syslog_lock);
return 0;
}
if (info.seq != syslog_seq) {
@@ -1736,8 +1728,7 @@ int do_syslog(int type, char __user *buf, int len, int source)
}
error -= syslog_partial;
}
- raw_spin_unlock(&syslog_lock);
- printk_safe_exit_irq();
+ mutex_unlock(&syslog_lock);
break;
/* Size of the log buffer */
case SYSLOG_ACTION_SIZE_BUFFER:
@@ -1940,6 +1931,76 @@ static void call_console_drivers(const char *ext_text, size_t ext_len,
}
}
+/*
+ * Recursion is tracked separately on each CPU. If NMIs are supported, an
+ * additional NMI context per CPU is also separately tracked. Until per-CPU
+ * is available, a separate "early tracking" is performed.
+ */
+static DEFINE_PER_CPU(u8, printk_count);
+static u8 printk_count_early;
+#ifdef CONFIG_HAVE_NMI
+static DEFINE_PER_CPU(u8, printk_count_nmi);
+static u8 printk_count_nmi_early;
+#endif
+
+/*
+ * Recursion is limited to keep the output sane. printk() should not require
+ * more than 1 level of recursion (allowing, for example, printk() to trigger
+ * a WARN), but a higher value is used in case some printk-internal errors
+ * exist, such as the ringbuffer validation checks failing.
+ */
+#define PRINTK_MAX_RECURSION 3
+
+/*
+ * Return a pointer to the dedicated counter for the CPU+context of the
+ * caller.
+ */
+static u8 *__printk_recursion_counter(void)
+{
+#ifdef CONFIG_HAVE_NMI
+ if (in_nmi()) {
+ if (printk_percpu_data_ready())
+ return this_cpu_ptr(&printk_count_nmi);
+ return &printk_count_nmi_early;
+ }
+#endif
+ if (printk_percpu_data_ready())
+ return this_cpu_ptr(&printk_count);
+ return &printk_count_early;
+}
+
+/*
+ * Enter recursion tracking. Interrupts are disabled to simplify tracking.
+ * The caller must check the boolean return value to see if the recursion is
+ * allowed. On failure, interrupts are not disabled.
+ *
+ * @recursion_ptr must be a variable of type (u8 *) and is the same variable
+ * that is passed to printk_exit_irqrestore().
+ */
+#define printk_enter_irqsave(recursion_ptr, flags) \
+({ \
+ bool success = true; \
+ \
+ typecheck(u8 *, recursion_ptr); \
+ local_irq_save(flags); \
+ (recursion_ptr) = __printk_recursion_counter(); \
+ if (*(recursion_ptr) > PRINTK_MAX_RECURSION) { \
+ local_irq_restore(flags); \
+ success = false; \
+ } else { \
+ (*(recursion_ptr))++; \
+ } \
+ success; \
+})
+
+/* Exit recursion tracking, restoring interrupts. */
+#define printk_exit_irqrestore(recursion_ptr, flags) \
+ do { \
+ typecheck(u8 *, recursion_ptr); \
+ (*(recursion_ptr))--; \
+ local_irq_restore(flags); \
+ } while (0)
+
int printk_delay_msec __read_mostly;
static inline void printk_delay(void)
@@ -1961,23 +2022,24 @@ static inline u32 printk_caller_id(void)
}
/**
- * parse_prefix - Parse level and control flags.
+ * printk_parse_prefix - Parse level and control flags.
*
* @text: The terminated text message.
* @level: A pointer to the current level value, will be updated.
- * @lflags: A pointer to the current log flags, will be updated.
+ * @flags: A pointer to the current printk_info flags, will be updated.
*
* @level may be NULL if the caller is not interested in the parsed value.
* Otherwise the variable pointed to by @level must be set to
* LOGLEVEL_DEFAULT in order to be updated with the parsed value.
*
- * @lflags may be NULL if the caller is not interested in the parsed value.
- * Otherwise the variable pointed to by @lflags will be OR'd with the parsed
+ * @flags may be NULL if the caller is not interested in the parsed value.
+ * Otherwise the variable pointed to by @flags will be OR'd with the parsed
* value.
*
* Return: The length of the parsed level and control flags.
*/
-static u16 parse_prefix(char *text, int *level, enum log_flags *lflags)
+u16 printk_parse_prefix(const char *text, int *level,
+ enum printk_info_flags *flags)
{
u16 prefix_len = 0;
int kern_level;
@@ -1993,8 +2055,8 @@ static u16 parse_prefix(char *text, int *level, enum log_flags *lflags)
*level = kern_level - '0';
break;
case 'c': /* KERN_CONT */
- if (lflags)
- *lflags |= LOG_CONT;
+ if (flags)
+ *flags |= LOG_CONT;
}
prefix_len += 2;
@@ -2004,8 +2066,9 @@ static u16 parse_prefix(char *text, int *level, enum log_flags *lflags)
return prefix_len;
}
-static u16 printk_sprint(char *text, u16 size, int facility, enum log_flags *lflags,
- const char *fmt, va_list args)
+static u16 printk_sprint(char *text, u16 size, int facility,
+ enum printk_info_flags *flags, const char *fmt,
+ va_list args)
{
u16 text_len;
@@ -2014,14 +2077,14 @@ static u16 printk_sprint(char *text, u16 size, int facility, enum log_flags *lfl
/* Mark and strip a trailing newline. */
if (text_len && text[text_len - 1] == '\n') {
text_len--;
- *lflags |= LOG_NEWLINE;
+ *flags |= LOG_NEWLINE;
}
/* Strip log level and control flags. */
if (facility == 0) {
u16 prefix_len;
- prefix_len = parse_prefix(text, NULL, NULL);
+ prefix_len = printk_parse_prefix(text, NULL, NULL);
if (prefix_len) {
text_len -= prefix_len;
memmove(text, text + prefix_len, text_len);
@@ -2038,13 +2101,16 @@ int vprintk_store(int facility, int level,
{
const u32 caller_id = printk_caller_id();
struct prb_reserved_entry e;
- enum log_flags lflags = 0;
+ enum printk_info_flags flags = 0;
struct printk_record r;
+ unsigned long irqflags;
u16 trunc_msg_len = 0;
char prefix_buf[8];
+ u8 *recursion_ptr;
u16 reserve_size;
va_list args2;
u16 text_len;
+ int ret = 0;
u64 ts_nsec;
/*
@@ -2055,6 +2121,9 @@ int vprintk_store(int facility, int level,
*/
ts_nsec = local_clock();
+ if (!printk_enter_irqsave(recursion_ptr, irqflags))
+ return 0;
+
/*
* The sprintf needs to come first since the syslog prefix might be
* passed in as a parameter. An extra byte must be reserved so that
@@ -2070,29 +2139,30 @@ int vprintk_store(int facility, int level,
/* Extract log level or control flags. */
if (facility == 0)
- parse_prefix(&prefix_buf[0], &level, &lflags);
+ printk_parse_prefix(&prefix_buf[0], &level, &flags);
if (level == LOGLEVEL_DEFAULT)
level = default_message_loglevel;
if (dev_info)
- lflags |= LOG_NEWLINE;
+ flags |= LOG_NEWLINE;
- if (lflags & LOG_CONT) {
+ if (flags & LOG_CONT) {
prb_rec_init_wr(&r, reserve_size);
if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) {
text_len = printk_sprint(&r.text_buf[r.info->text_len], reserve_size,
- facility, &lflags, fmt, args);
+ facility, &flags, fmt, args);
r.info->text_len += text_len;
- if (lflags & LOG_NEWLINE) {
+ if (flags & LOG_NEWLINE) {
r.info->flags |= LOG_NEWLINE;
prb_final_commit(&e);
} else {
prb_commit(&e);
}
- return text_len;
+ ret = text_len;
+ goto out;
}
}
@@ -2108,29 +2178,32 @@ int vprintk_store(int facility, int level,
prb_rec_init_wr(&r, reserve_size + trunc_msg_len);
if (!prb_reserve(&e, prb, &r))
- return 0;
+ goto out;
}
/* fill message */
- text_len = printk_sprint(&r.text_buf[0], reserve_size, facility, &lflags, fmt, args);
+ text_len = printk_sprint(&r.text_buf[0], reserve_size, facility, &flags, fmt, args);
if (trunc_msg_len)
memcpy(&r.text_buf[text_len], trunc_msg, trunc_msg_len);
r.info->text_len = text_len + trunc_msg_len;
r.info->facility = facility;
r.info->level = level & 7;
- r.info->flags = lflags & 0x1f;
+ r.info->flags = flags & 0x1f;
r.info->ts_nsec = ts_nsec;
r.info->caller_id = caller_id;
if (dev_info)
memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info));
/* A message without a trailing newline can be continued. */
- if (!(lflags & LOG_NEWLINE))
+ if (!(flags & LOG_NEWLINE))
prb_commit(&e);
else
prb_final_commit(&e);
- return (text_len + trunc_msg_len);
+ ret = text_len + trunc_msg_len;
+out:
+ printk_exit_irqrestore(recursion_ptr, irqflags);
+ return ret;
}
asmlinkage int vprintk_emit(int facility, int level,
@@ -2139,7 +2212,6 @@ asmlinkage int vprintk_emit(int facility, int level,
{
int printed_len;
bool in_sched = false;
- unsigned long flags;
/* Suppress unimportant messages after panic happens */
if (unlikely(suppress_printk))
@@ -2153,9 +2225,7 @@ asmlinkage int vprintk_emit(int facility, int level,
boot_delay_msec(level);
printk_delay();
- printk_safe_enter_irqsave(flags);
printed_len = vprintk_store(facility, level, dev_info, fmt, args);
- printk_safe_exit_irqrestore(flags);
/* If called from the scheduler, we can not call up(). */
if (!in_sched) {
@@ -2186,28 +2256,7 @@ int vprintk_default(const char *fmt, va_list args)
}
EXPORT_SYMBOL_GPL(vprintk_default);
-/**
- * printk - print a kernel message
- * @fmt: format string
- *
- * This is printk(). It can be called from any context. We want it to work.
- *
- * We try to grab the console_lock. If we succeed, it's easy - we log the
- * output and call the console drivers. If we fail to get the semaphore, we
- * place the output into the log buffer and return. The current holder of
- * the console_sem will notice the new output in console_unlock(); and will
- * send it to the consoles before releasing the lock.
- *
- * One effect of this deferred printing is that code which calls printk() and
- * then changes console_loglevel may break. This is because console_loglevel
- * is inspected when the actual printing occurs.
- *
- * See also:
- * printf(3)
- *
- * See the vsnprintf() documentation for format string extensions over C99.
- */
-asmlinkage __visible int printk(const char *fmt, ...)
+asmlinkage __visible int _printk(const char *fmt, ...)
{
va_list args;
int r;
@@ -2218,7 +2267,7 @@ asmlinkage __visible int printk(const char *fmt, ...)
return r;
}
-EXPORT_SYMBOL(printk);
+EXPORT_SYMBOL(_printk);
#else /* CONFIG_PRINTK */
@@ -2404,6 +2453,18 @@ module_param_named(console_suspend, console_suspend_enabled,
MODULE_PARM_DESC(console_suspend, "suspend console during suspend"
" and hibernate operations");
+static bool printk_console_no_auto_verbose;
+
+void console_verbose(void)
+{
+ if (console_loglevel && !printk_console_no_auto_verbose)
+ console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;
+}
+EXPORT_SYMBOL_GPL(console_verbose);
+
+module_param_named(console_no_auto_verbose, printk_console_no_auto_verbose, bool, 0644);
+MODULE_PARM_DESC(console_no_auto_verbose, "Disable console loglevel raise to highest on oops/panic/etc");
+
/**
* suspend_console - suspend the console subsystem
*
@@ -2545,6 +2606,7 @@ void console_unlock(void)
bool do_cond_resched, retry;
struct printk_info info;
struct printk_record r;
+ u64 __maybe_unused next_seq;
if (console_suspended) {
up_console_sem();
@@ -2584,9 +2646,9 @@ again:
for (;;) {
size_t ext_len = 0;
+ int handover;
size_t len;
- printk_safe_enter_irqsave(flags);
skip:
if (!prb_read_valid(prb, console_seq, &r))
break;
@@ -2636,26 +2698,31 @@ skip:
* were to occur on another CPU, it may wait for this one to
* finish. This task can not be preempted if there is a
* waiter waiting to take over.
+ *
+ * Interrupts are disabled because the hand over to a waiter
+ * must not be interrupted until the hand over is completed
+ * (@console_waiter is cleared).
*/
+ printk_safe_enter_irqsave(flags);
console_lock_spinning_enable();
stop_critical_timings(); /* don't trace print latency */
call_console_drivers(ext_text, ext_len, text, len);
start_critical_timings();
- if (console_lock_spinning_disable_and_check()) {
- printk_safe_exit_irqrestore(flags);
- return;
- }
-
+ handover = console_lock_spinning_disable_and_check();
printk_safe_exit_irqrestore(flags);
+ if (handover)
+ return;
if (do_cond_resched)
cond_resched();
}
- console_locked = 0;
+ /* Get consistent value of the next-to-be-used sequence number. */
+ next_seq = console_seq;
+ console_locked = 0;
up_console_sem();
/*
@@ -2664,9 +2731,7 @@ skip:
* there's a new owner and the console_unlock() from them will do the
* flush, no worries.
*/
- retry = prb_read_valid(prb, console_seq, NULL);
- printk_safe_exit_irqrestore(flags);
-
+ retry = prb_read_valid(prb, next_seq, NULL);
if (retry && console_trylock())
goto again;
}
@@ -2728,13 +2793,8 @@ void console_flush_on_panic(enum con_flush_mode mode)
console_trylock();
console_may_schedule = 0;
- if (mode == CONSOLE_REPLAY_ALL) {
- unsigned long flags;
-
- printk_safe_enter_irqsave(flags);
+ if (mode == CONSOLE_REPLAY_ALL)
console_seq = prb_first_valid_seq(prb);
- printk_safe_exit_irqrestore(flags);
- }
console_unlock();
}
@@ -2869,7 +2929,6 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
*/
void register_console(struct console *newcon)
{
- unsigned long flags;
struct console *bcon = NULL;
int err;
@@ -2974,9 +3033,9 @@ void register_console(struct console *newcon)
exclusive_console_stop_seq = console_seq;
/* Get a consistent copy of @syslog_seq. */
- raw_spin_lock_irqsave(&syslog_lock, flags);
+ mutex_lock(&syslog_lock);
console_seq = syslog_seq;
- raw_spin_unlock_irqrestore(&syslog_lock, flags);
+ mutex_unlock(&syslog_lock);
}
console_unlock();
console_sysfs_notify();
@@ -3203,7 +3262,7 @@ int vprintk_deferred(const char *fmt, va_list args)
return r;
}
-int printk_deferred(const char *fmt, ...)
+int _printk_deferred(const char *fmt, ...)
{
va_list args;
int r;
@@ -3386,14 +3445,12 @@ bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog,
struct printk_info info;
unsigned int line_count;
struct printk_record r;
- unsigned long flags;
size_t l = 0;
bool ret = false;
if (iter->cur_seq < min_seq)
iter->cur_seq = min_seq;
- printk_safe_enter_irqsave(flags);
prb_rec_init_rd(&r, &info, line, size);
/* Read text or count text lines? */
@@ -3414,7 +3471,6 @@ bool kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog,
iter->cur_seq = r.info->seq + 1;
ret = true;
out:
- printk_safe_exit_irqrestore(flags);
if (len)
*len = l;
return ret;
@@ -3446,7 +3502,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog,
u64 min_seq = latched_seq_read_nolock(&clear_seq);
struct printk_info info;
struct printk_record r;
- unsigned long flags;
u64 seq;
u64 next_seq;
size_t len = 0;
@@ -3459,7 +3514,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog,
if (iter->cur_seq < min_seq)
iter->cur_seq = min_seq;
- printk_safe_enter_irqsave(flags);
if (prb_read_valid_info(prb, iter->cur_seq, &info, NULL)) {
if (info.seq != iter->cur_seq) {
/* messages are gone, move to first available one */
@@ -3468,10 +3522,8 @@ bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog,
}
/* last entry */
- if (iter->cur_seq >= iter->next_seq) {
- printk_safe_exit_irqrestore(flags);
+ if (iter->cur_seq >= iter->next_seq)
goto out;
- }
/*
* Find first record that fits, including all following records,
@@ -3503,7 +3555,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog,
iter->next_seq = next_seq;
ret = true;
- printk_safe_exit_irqrestore(flags);
out:
if (len_out)
*len_out = len;
@@ -3521,12 +3572,8 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
*/
void kmsg_dump_rewind(struct kmsg_dump_iter *iter)
{
- unsigned long flags;
-
- printk_safe_enter_irqsave(flags);
iter->cur_seq = latched_seq_read_nolock(&clear_seq);
iter->next_seq = prb_next_seq(prb);
- printk_safe_exit_irqrestore(flags);
}
EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
index 94232186fccb..ef0f9a2044da 100644
--- a/kernel/printk/printk_safe.c
+++ b/kernel/printk/printk_safe.c
@@ -4,347 +4,16 @@
*/
#include <linux/preempt.h>
-#include <linux/spinlock.h>
-#include <linux/debug_locks.h>
#include <linux/kdb.h>
#include <linux/smp.h>
#include <linux/cpumask.h>
-#include <linux/irq_work.h>
#include <linux/printk.h>
#include <linux/kprobes.h>
#include "internal.h"
-/*
- * In NMI and safe mode, printk() avoids taking locks. Instead,
- * it uses an alternative implementation that temporary stores
- * the strings into a per-CPU buffer. The content of the buffer
- * is later flushed into the main ring buffer via IRQ work.
- *
- * The alternative implementation is chosen transparently
- * by examining current printk() context mask stored in @printk_context
- * per-CPU variable.
- *
- * The implementation allows to flush the strings also from another CPU.
- * There are situations when we want to make sure that all buffers
- * were handled or when IRQs are blocked.
- */
-
-#define SAFE_LOG_BUF_LEN ((1 << CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT) - \
- sizeof(atomic_t) - \
- sizeof(atomic_t) - \
- sizeof(struct irq_work))
-
-struct printk_safe_seq_buf {
- atomic_t len; /* length of written data */
- atomic_t message_lost;
- struct irq_work work; /* IRQ work that flushes the buffer */
- unsigned char buffer[SAFE_LOG_BUF_LEN];
-};
-
-static DEFINE_PER_CPU(struct printk_safe_seq_buf, safe_print_seq);
static DEFINE_PER_CPU(int, printk_context);
-static DEFINE_RAW_SPINLOCK(safe_read_lock);
-
-#ifdef CONFIG_PRINTK_NMI
-static DEFINE_PER_CPU(struct printk_safe_seq_buf, nmi_print_seq);
-#endif
-
-/* Get flushed in a more safe context. */
-static void queue_flush_work(struct printk_safe_seq_buf *s)
-{
- if (printk_percpu_data_ready())
- irq_work_queue(&s->work);
-}
-
-/*
- * Add a message to per-CPU context-dependent buffer. NMI and printk-safe
- * have dedicated buffers, because otherwise printk-safe preempted by
- * NMI-printk would have overwritten the NMI messages.
- *
- * The messages are flushed from irq work (or from panic()), possibly,
- * from other CPU, concurrently with printk_safe_log_store(). Should this
- * happen, printk_safe_log_store() will notice the buffer->len mismatch
- * and repeat the write.
- */
-static __printf(2, 0) int printk_safe_log_store(struct printk_safe_seq_buf *s,
- const char *fmt, va_list args)
-{
- int add;
- size_t len;
- va_list ap;
-
-again:
- len = atomic_read(&s->len);
-
- /* The trailing '\0' is not counted into len. */
- if (len >= sizeof(s->buffer) - 1) {
- atomic_inc(&s->message_lost);
- queue_flush_work(s);
- return 0;
- }
-
- /*
- * Make sure that all old data have been read before the buffer
- * was reset. This is not needed when we just append data.
- */
- if (!len)
- smp_rmb();
-
- va_copy(ap, args);
- add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, ap);
- va_end(ap);
- if (!add)
- return 0;
-
- /*
- * Do it once again if the buffer has been flushed in the meantime.
- * Note that atomic_cmpxchg() is an implicit memory barrier that
- * makes sure that the data were written before updating s->len.
- */
- if (atomic_cmpxchg(&s->len, len, len + add) != len)
- goto again;
-
- queue_flush_work(s);
- return add;
-}
-
-static inline void printk_safe_flush_line(const char *text, int len)
-{
- /*
- * Avoid any console drivers calls from here, because we may be
- * in NMI or printk_safe context (when in panic). The messages
- * must go only into the ring buffer at this stage. Consoles will
- * get explicitly called later when a crashdump is not generated.
- */
- printk_deferred("%.*s", len, text);
-}
-
-/* printk part of the temporary buffer line by line */
-static int printk_safe_flush_buffer(const char *start, size_t len)
-{
- const char *c, *end;
- bool header;
-
- c = start;
- end = start + len;
- header = true;
-
- /* Print line by line. */
- while (c < end) {
- if (*c == '\n') {
- printk_safe_flush_line(start, c - start + 1);
- start = ++c;
- header = true;
- continue;
- }
-
- /* Handle continuous lines or missing new line. */
- if ((c + 1 < end) && printk_get_level(c)) {
- if (header) {
- c = printk_skip_level(c);
- continue;
- }
-
- printk_safe_flush_line(start, c - start);
- start = c++;
- header = true;
- continue;
- }
-
- header = false;
- c++;
- }
-
- /* Check if there was a partial line. Ignore pure header. */
- if (start < end && !header) {
- static const char newline[] = KERN_CONT "\n";
-
- printk_safe_flush_line(start, end - start);
- printk_safe_flush_line(newline, strlen(newline));
- }
-
- return len;
-}
-
-static void report_message_lost(struct printk_safe_seq_buf *s)
-{
- int lost = atomic_xchg(&s->message_lost, 0);
-
- if (lost)
- printk_deferred("Lost %d message(s)!\n", lost);
-}
-
-/*
- * Flush data from the associated per-CPU buffer. The function
- * can be called either via IRQ work or independently.
- */
-static void __printk_safe_flush(struct irq_work *work)
-{
- struct printk_safe_seq_buf *s =
- container_of(work, struct printk_safe_seq_buf, work);
- unsigned long flags;
- size_t len;
- int i;
-
- /*
- * The lock has two functions. First, one reader has to flush all
- * available message to make the lockless synchronization with
- * writers easier. Second, we do not want to mix messages from
- * different CPUs. This is especially important when printing
- * a backtrace.
- */
- raw_spin_lock_irqsave(&safe_read_lock, flags);
-
- i = 0;
-more:
- len = atomic_read(&s->len);
-
- /*
- * This is just a paranoid check that nobody has manipulated
- * the buffer an unexpected way. If we printed something then
- * @len must only increase. Also it should never overflow the
- * buffer size.
- */
- if ((i && i >= len) || len > sizeof(s->buffer)) {
- const char *msg = "printk_safe_flush: internal error\n";
-
- printk_safe_flush_line(msg, strlen(msg));
- len = 0;
- }
-
- if (!len)
- goto out; /* Someone else has already flushed the buffer. */
-
- /* Make sure that data has been written up to the @len */
- smp_rmb();
- i += printk_safe_flush_buffer(s->buffer + i, len - i);
-
- /*
- * Check that nothing has got added in the meantime and truncate
- * the buffer. Note that atomic_cmpxchg() is an implicit memory
- * barrier that makes sure that the data were copied before
- * updating s->len.
- */
- if (atomic_cmpxchg(&s->len, len, 0) != len)
- goto more;
-
-out:
- report_message_lost(s);
- raw_spin_unlock_irqrestore(&safe_read_lock, flags);
-}
-
-/**
- * printk_safe_flush - flush all per-cpu nmi buffers.
- *
- * The buffers are flushed automatically via IRQ work. This function
- * is useful only when someone wants to be sure that all buffers have
- * been flushed at some point.
- */
-void printk_safe_flush(void)
-{
- int cpu;
-
- for_each_possible_cpu(cpu) {
-#ifdef CONFIG_PRINTK_NMI
- __printk_safe_flush(&per_cpu(nmi_print_seq, cpu).work);
-#endif
- __printk_safe_flush(&per_cpu(safe_print_seq, cpu).work);
- }
-}
-
-/**
- * printk_safe_flush_on_panic - flush all per-cpu nmi buffers when the system
- * goes down.
- *
- * Similar to printk_safe_flush() but it can be called even in NMI context when
- * the system goes down. It does the best effort to get NMI messages into
- * the main ring buffer.
- *
- * Note that it could try harder when there is only one CPU online.
- */
-void printk_safe_flush_on_panic(void)
-{
- /*
- * Make sure that we could access the safe buffers.
- * Do not risk a double release when more CPUs are up.
- */
- if (raw_spin_is_locked(&safe_read_lock)) {
- if (num_online_cpus() > 1)
- return;
-
- debug_locks_off();
- raw_spin_lock_init(&safe_read_lock);
- }
-
- printk_safe_flush();
-}
-
-#ifdef CONFIG_PRINTK_NMI
-/*
- * Safe printk() for NMI context. It uses a per-CPU buffer to
- * store the message. NMIs are not nested, so there is always only
- * one writer running. But the buffer might get flushed from another
- * CPU, so we need to be careful.
- */
-static __printf(1, 0) int vprintk_nmi(const char *fmt, va_list args)
-{
- struct printk_safe_seq_buf *s = this_cpu_ptr(&nmi_print_seq);
-
- return printk_safe_log_store(s, fmt, args);
-}
-
-void noinstr printk_nmi_enter(void)
-{
- this_cpu_add(printk_context, PRINTK_NMI_CONTEXT_OFFSET);
-}
-
-void noinstr printk_nmi_exit(void)
-{
- this_cpu_sub(printk_context, PRINTK_NMI_CONTEXT_OFFSET);
-}
-
-/*
- * Marks a code that might produce many messages in NMI context
- * and the risk of losing them is more critical than eventual
- * reordering.
- *
- * It has effect only when called in NMI context. Then printk()
- * will store the messages into the main logbuf directly.
- */
-void printk_nmi_direct_enter(void)
-{
- if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK)
- this_cpu_or(printk_context, PRINTK_NMI_DIRECT_CONTEXT_MASK);
-}
-
-void printk_nmi_direct_exit(void)
-{
- this_cpu_and(printk_context, ~PRINTK_NMI_DIRECT_CONTEXT_MASK);
-}
-
-#else
-
-static __printf(1, 0) int vprintk_nmi(const char *fmt, va_list args)
-{
- return 0;
-}
-
-#endif /* CONFIG_PRINTK_NMI */
-
-/*
- * Lock-less printk(), to avoid deadlocks should the printk() recurse
- * into itself. It uses a per-CPU buffer to store the message, just like
- * NMI.
- */
-static __printf(1, 0) int vprintk_safe(const char *fmt, va_list args)
-{
- struct printk_safe_seq_buf *s = this_cpu_ptr(&safe_print_seq);
-
- return printk_safe_log_store(s, fmt, args);
-}
-
/* Can be preempted by NMI. */
void __printk_safe_enter(void)
{
@@ -369,46 +38,15 @@ asmlinkage int vprintk(const char *fmt, va_list args)
* Use the main logbuf even in NMI. But avoid calling console
* drivers that might have their own locks.
*/
- if ((this_cpu_read(printk_context) & PRINTK_NMI_DIRECT_CONTEXT_MASK)) {
- unsigned long flags;
+ if (this_cpu_read(printk_context) || in_nmi()) {
int len;
- printk_safe_enter_irqsave(flags);
len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
- printk_safe_exit_irqrestore(flags);
defer_console_output();
return len;
}
- /* Use extra buffer in NMI. */
- if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK)
- return vprintk_nmi(fmt, args);
-
- /* Use extra buffer to prevent a recursion deadlock in safe mode. */
- if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK)
- return vprintk_safe(fmt, args);
-
/* No obstacles. */
return vprintk_default(fmt, args);
}
EXPORT_SYMBOL(vprintk);
-
-void __init printk_safe_init(void)
-{
- int cpu;
-
- for_each_possible_cpu(cpu) {
- struct printk_safe_seq_buf *s;
-
- s = &per_cpu(safe_print_seq, cpu);
- init_irq_work(&s->work, __printk_safe_flush);
-
-#ifdef CONFIG_PRINTK_NMI
- s = &per_cpu(nmi_print_seq, cpu);
- init_irq_work(&s->work, __printk_safe_flush);
-#endif
- }
-
- /* Flush pending messages that did not have scheduled IRQ works. */
- printk_safe_flush();
-}
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 6469eca8078c..4d8f44a17727 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -922,30 +922,6 @@ void get_seccomp_filter(struct task_struct *tsk)
refcount_inc(&orig->users);
}
-static void seccomp_init_siginfo(kernel_siginfo_t *info, int syscall, int reason)
-{
- clear_siginfo(info);
- info->si_signo = SIGSYS;
- info->si_code = SYS_SECCOMP;
- info->si_call_addr = (void __user *)KSTK_EIP(current);
- info->si_errno = reason;
- info->si_arch = syscall_get_arch(current);
- info->si_syscall = syscall;
-}
-
-/**
- * seccomp_send_sigsys - signals the task to allow in-process syscall emulation
- * @syscall: syscall number to send to userland
- * @reason: filter-supplied reason code to send to userland (via si_errno)
- *
- * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
- */
-static void seccomp_send_sigsys(int syscall, int reason)
-{
- struct kernel_siginfo info;
- seccomp_init_siginfo(&info, syscall, reason);
- force_sig_info(&info);
-}
#endif /* CONFIG_SECCOMP_FILTER */
/* For use with seccomp_actions_logged */
@@ -1218,7 +1194,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
/* Show the handler the original registers. */
syscall_rollback(current, current_pt_regs());
/* Let the filter pass back 16 bits of data. */
- seccomp_send_sigsys(this_syscall, data);
+ force_sig_seccomp(this_syscall, data, false);
goto skip;
case SECCOMP_RET_TRACE:
@@ -1288,19 +1264,15 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
seccomp_log(this_syscall, SIGSYS, action, true);
/* Dump core only if this is the last remaining thread. */
if (action != SECCOMP_RET_KILL_THREAD ||
- get_nr_threads(current) == 1) {
- kernel_siginfo_t info;
-
+ (atomic_read(&current->signal->live) == 1)) {
/* Show the original registers in the dump. */
syscall_rollback(current, current_pt_regs());
- /* Trigger a manual coredump since do_exit skips it. */
- seccomp_init_siginfo(&info, this_syscall, data);
- do_coredump(&info);
- }
- if (action == SECCOMP_RET_KILL_THREAD)
+ /* Trigger a coredump with SIGSYS */
+ force_sig_seccomp(this_syscall, data, true);
+ } else {
do_exit(SIGSYS);
- else
- do_group_exit(SIGSYS);
+ }
+ return -1; /* skip the syscall go directly to signal handling */
}
unreachable();
diff --git a/kernel/signal.c b/kernel/signal.c
index 52b6abec0ff8..952741f6d0f9 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -54,6 +54,7 @@
#include <asm/unistd.h>
#include <asm/siginfo.h>
#include <asm/cacheflush.h>
+#include <asm/syscall.h> /* for syscall_get_* */
/*
* SLAB caches for signal bits.
@@ -1213,7 +1214,7 @@ static inline bool has_si_pid_and_uid(struct kernel_siginfo *info)
case SIL_FAULT_MCEERR:
case SIL_FAULT_BNDERR:
case SIL_FAULT_PKUERR:
- case SIL_PERF_EVENT:
+ case SIL_FAULT_PERF_EVENT:
case SIL_SYS:
ret = false;
break;
@@ -1322,7 +1323,7 @@ int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p
* that is why we also clear SIGNAL_UNKILLABLE.
*/
static int
-force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t)
+force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool sigdfl)
{
unsigned long int flags;
int ret, blocked, ignored;
@@ -1333,7 +1334,7 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t)
action = &t->sighand->action[sig-1];
ignored = action->sa.sa_handler == SIG_IGN;
blocked = sigismember(&t->blocked, sig);
- if (blocked || ignored) {
+ if (blocked || ignored || sigdfl) {
action->sa.sa_handler = SIG_DFL;
if (blocked) {
sigdelset(&t->blocked, sig);
@@ -1354,7 +1355,7 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t)
int force_sig_info(struct kernel_siginfo *info)
{
- return force_sig_info_to_task(info, current);
+ return force_sig_info_to_task(info, current, false);
}
/*
@@ -1681,7 +1682,6 @@ void force_sigsegv(int sig)
}
int force_sig_fault_to_task(int sig, int code, void __user *addr
- ___ARCH_SI_TRAPNO(int trapno)
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
, struct task_struct *t)
{
@@ -1692,28 +1692,22 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
info.si_errno = 0;
info.si_code = code;
info.si_addr = addr;
-#ifdef __ARCH_SI_TRAPNO
- info.si_trapno = trapno;
-#endif
#ifdef __ia64__
info.si_imm = imm;
info.si_flags = flags;
info.si_isr = isr;
#endif
- return force_sig_info_to_task(&info, t);
+ return force_sig_info_to_task(&info, t, false);
}
int force_sig_fault(int sig, int code, void __user *addr
- ___ARCH_SI_TRAPNO(int trapno)
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
{
return force_sig_fault_to_task(sig, code, addr
- ___ARCH_SI_TRAPNO(trapno)
___ARCH_SI_IA64(imm, flags, isr), current);
}
int send_sig_fault(int sig, int code, void __user *addr
- ___ARCH_SI_TRAPNO(int trapno)
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
, struct task_struct *t)
{
@@ -1724,9 +1718,6 @@ int send_sig_fault(int sig, int code, void __user *addr
info.si_errno = 0;
info.si_code = code;
info.si_addr = addr;
-#ifdef __ARCH_SI_TRAPNO
- info.si_trapno = trapno;
-#endif
#ifdef __ia64__
info.si_imm = imm;
info.si_flags = flags;
@@ -1808,6 +1799,27 @@ int force_sig_perf(void __user *addr, u32 type, u64 sig_data)
return force_sig_info(&info);
}
+/**
+ * force_sig_seccomp - signals the task to allow in-process syscall emulation
+ * @syscall: syscall number to send to userland
+ * @reason: filter-supplied reason code to send to userland (via si_errno)
+ *
+ * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
+ */
+int force_sig_seccomp(int syscall, int reason, bool force_coredump)
+{
+ struct kernel_siginfo info;
+
+ clear_siginfo(&info);
+ info.si_signo = SIGSYS;
+ info.si_code = SYS_SECCOMP;
+ info.si_call_addr = (void __user *)KSTK_EIP(current);
+ info.si_errno = reason;
+ info.si_arch = syscall_get_arch(current);
+ info.si_syscall = syscall;
+ return force_sig_info_to_task(&info, current, force_coredump);
+}
+
/* For the crazy architectures that include trap information in
* the errno field, instead of an actual errno value.
*/
@@ -1823,6 +1835,39 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
return force_sig_info(&info);
}
+/* For the rare architectures that include trap information using
+ * si_trapno.
+ */
+int force_sig_fault_trapno(int sig, int code, void __user *addr, int trapno)
+{
+ struct kernel_siginfo info;
+
+ clear_siginfo(&info);
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = addr;
+ info.si_trapno = trapno;
+ return force_sig_info(&info);
+}
+
+/* For the rare architectures that include trap information using
+ * si_trapno.
+ */
+int send_sig_fault_trapno(int sig, int code, void __user *addr, int trapno,
+ struct task_struct *t)
+{
+ struct kernel_siginfo info;
+
+ clear_siginfo(&info);
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = addr;
+ info.si_trapno = trapno;
+ return send_sig_info(info.si_signo, &info, t);
+}
+
int kill_pgrp(struct pid *pid, int sig, int priv)
{
int ret;
@@ -2572,7 +2617,7 @@ static void hide_si_addr_tag_bits(struct ksignal *ksig)
case SIL_FAULT_MCEERR:
case SIL_FAULT_BNDERR:
case SIL_FAULT_PKUERR:
- case SIL_PERF_EVENT:
+ case SIL_FAULT_PERF_EVENT:
ksig->info.si_addr = arch_untagged_si_addr(
ksig->info.si_addr, ksig->sig, ksig->info.si_code);
break;
@@ -3257,11 +3302,14 @@ enum siginfo_layout siginfo_layout(unsigned sig, int si_code)
layout = SIL_FAULT_PKUERR;
#endif
else if ((sig == SIGTRAP) && (si_code == TRAP_PERF))
- layout = SIL_PERF_EVENT;
-#ifdef __ARCH_SI_TRAPNO
- else if (layout == SIL_FAULT)
+ layout = SIL_FAULT_PERF_EVENT;
+ else if (IS_ENABLED(CONFIG_SPARC) &&
+ (sig == SIGILL) && (si_code == ILL_ILLTRP))
+ layout = SIL_FAULT_TRAPNO;
+ else if (IS_ENABLED(CONFIG_ALPHA) &&
+ ((sig == SIGFPE) ||
+ ((sig == SIGTRAP) && (si_code == TRAP_UNK))))
layout = SIL_FAULT_TRAPNO;
-#endif
}
else if (si_code <= NSIGPOLL)
layout = SIL_POLL;
@@ -3383,7 +3431,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
to->si_addr = ptr_to_compat(from->si_addr);
to->si_pkey = from->si_pkey;
break;
- case SIL_PERF_EVENT:
+ case SIL_FAULT_PERF_EVENT:
to->si_addr = ptr_to_compat(from->si_addr);
to->si_perf_data = from->si_perf_data;
to->si_perf_type = from->si_perf_type;
@@ -3460,7 +3508,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
to->si_addr = compat_ptr(from->si_addr);
to->si_pkey = from->si_pkey;
break;
- case SIL_PERF_EVENT:
+ case SIL_FAULT_PERF_EVENT:
to->si_addr = compat_ptr(from->si_addr);
to->si_perf_data = from->si_perf_data;
to->si_perf_type = from->si_perf_type;
@@ -4678,7 +4726,7 @@ void __init signals_init(void)
{
siginfo_buildtime_checks();
- sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC);
+ sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC | SLAB_ACCOUNT);
}
#ifdef CONFIG_KGDB_KDB
diff --git a/kernel/sys.c b/kernel/sys.c
index 72c7639e3c98..b6aa704f861d 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1847,7 +1847,6 @@ SYSCALL_DEFINE1(umask, int, mask)
static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
{
struct fd exe;
- struct file *old_exe, *exe_file;
struct inode *inode;
int err;
@@ -1870,40 +1869,10 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
if (err)
goto exit;
- /*
- * Forbid mm->exe_file change if old file still mapped.
- */
- exe_file = get_mm_exe_file(mm);
- err = -EBUSY;
- if (exe_file) {
- struct vm_area_struct *vma;
-
- mmap_read_lock(mm);
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- if (!vma->vm_file)
- continue;
- if (path_equal(&vma->vm_file->f_path,
- &exe_file->f_path))
- goto exit_err;
- }
-
- mmap_read_unlock(mm);
- fput(exe_file);
- }
-
- err = 0;
- /* set the new file, lockless */
- get_file(exe.file);
- old_exe = xchg(&mm->exe_file, exe.file);
- if (old_exe)
- fput(old_exe);
+ err = replace_mm_exe_file(mm, exe.file);
exit:
fdput(exe);
return err;
-exit_err:
- mmap_read_unlock(mm);
- fput(exe_file);
- goto exit;
}
/*
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 30971b1dd4a9..64578adfe115 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -289,6 +289,7 @@ COND_SYSCALL(munlockall);
COND_SYSCALL(mincore);
COND_SYSCALL(madvise);
COND_SYSCALL(process_madvise);
+COND_SYSCALL(process_mrelease);
COND_SYSCALL(remap_file_pages);
COND_SYSCALL(mbind);
COND_SYSCALL_COMPAT(mbind);
@@ -416,7 +417,6 @@ COND_SYSCALL(epoll_wait);
COND_SYSCALL(recv);
COND_SYSCALL_COMPAT(recv);
COND_SYSCALL(send);
-COND_SYSCALL(bdflush);
COND_SYSCALL(uselib);
/* optional: time32 */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 25e49b4d8049..083be6af29d7 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2912,7 +2912,7 @@ static struct ctl_table vm_table[] = {
.data = &sysctl_compaction_proactiveness,
.maxlen = sizeof(sysctl_compaction_proactiveness),
.mode = 0644,
- .proc_handler = proc_dointvec_minmax,
+ .proc_handler = compaction_proactiveness_sysctl_handler,
.extra1 = SYSCTL_ZERO,
.extra2 = &one_hundred,
},
diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
index 12eab0d2ae28..aec832801c26 100644
--- a/kernel/time/namespace.c
+++ b/kernel/time/namespace.c
@@ -88,13 +88,13 @@ static struct time_namespace *clone_time_ns(struct user_namespace *user_ns,
goto fail;
err = -ENOMEM;
- ns = kmalloc(sizeof(*ns), GFP_KERNEL);
+ ns = kmalloc(sizeof(*ns), GFP_KERNEL_ACCOUNT);
if (!ns)
goto fail_dec;
refcount_set(&ns->ns.count, 1);
- ns->vvar_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ ns->vvar_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
if (!ns->vvar_page)
goto fail_free;
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 3913222e7bcf..1cd10b102c51 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -273,8 +273,8 @@ static int posix_get_hrtimer_res(clockid_t which_clock, struct timespec64 *tp)
static __init int init_posix_timers(void)
{
posix_timers_cache = kmem_cache_create("posix_timers_cache",
- sizeof (struct k_itimer), 0, SLAB_PANIC,
- NULL);
+ sizeof(struct k_itimer), 0,
+ SLAB_PANIC | SLAB_ACCOUNT, NULL);
return 0;
}
__initcall(init_posix_timers);
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 3ee23f4d437f..420ff4bc67fd 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -135,10 +135,9 @@ config TRACING_SUPPORT
depends on STACKTRACE_SUPPORT
default y
-if TRACING_SUPPORT
-
menuconfig FTRACE
bool "Tracers"
+ depends on TRACING_SUPPORT
default y if DEBUG_KERNEL
help
Enable the kernel tracing infrastructure.
@@ -1037,6 +1036,3 @@ config HIST_TRIGGERS_DEBUG
If unsure, say N.
endif # FTRACE
-
-endif # TRACING_SUPPORT
-
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index b1c47ccf4f73..6de5d4d63165 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o
endif
obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
obj-$(CONFIG_EVENT_TRACING) += trace_events_trigger.o
+obj-$(CONFIG_PROBE_EVENTS) += trace_eprobe.o
obj-$(CONFIG_TRACE_EVENT_INJECT) += trace_events_inject.o
obj-$(CONFIG_SYNTH_EVENTS) += trace_events_synth.o
obj-$(CONFIG_HIST_TRIGGERS) += trace_events_hist.o
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index e592d1df6f88..c5a3fbf19617 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2111,7 +2111,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
}
}
- get_online_cpus();
+ cpus_read_lock();
/*
* Fire off all the required work handlers
* We can't schedule on offline CPUs, but it's not necessary
@@ -2143,7 +2143,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
cpu_buffer->nr_pages_to_update = 0;
}
- put_online_cpus();
+ cpus_read_unlock();
} else {
cpu_buffer = buffer->buffers[cpu_id];
@@ -2171,7 +2171,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
goto out_err;
}
- get_online_cpus();
+ cpus_read_lock();
/* Can't run something on an offline CPU. */
if (!cpu_online(cpu_id))
@@ -2183,7 +2183,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
}
cpu_buffer->nr_pages_to_update = 0;
- put_online_cpus();
+ cpus_read_unlock();
}
out:
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index a1adb29ef5c1..2dbf797aa133 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3697,11 +3697,11 @@ static bool trace_safe_str(struct trace_iterator *iter, const char *str)
return false;
event = container_of(trace_event, struct trace_event_call, event);
- if (!event->mod)
+ if ((event->flags & TRACE_EVENT_FL_DYNAMIC) || !event->module)
return false;
/* Would rather have rodata, but this will suffice */
- if (within_module_core(addr, event->mod))
+ if (within_module_core(addr, event->module))
return true;
return false;
@@ -5543,6 +5543,7 @@ static const char readme_msg[] =
#ifdef CONFIG_HIST_TRIGGERS
"\t s:[synthetic/]<event> <field> [<field>]\n"
#endif
+ "\t e[:[<group>/]<event>] <attached-group>.<attached-event> [<args>]\n"
"\t -:[<group>/]<event>\n"
#ifdef CONFIG_KPROBE_EVENTS
"\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
@@ -5552,7 +5553,7 @@ static const char readme_msg[] =
" place (uprobe): <path>:<offset>[%return][(ref_ctr_offset)]\n"
#endif
"\t args: <name>=fetcharg[:type]\n"
- "\t fetcharg: %<register>, @<address>, @<symbol>[+|-<offset>],\n"
+ "\t fetcharg: (%<register>|$<efield>), @<address>, @<symbol>[+|-<offset>],\n"
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
"\t $stack<index>, $stack, $retval, $comm, $arg<N>,\n"
#else
@@ -5567,6 +5568,8 @@ static const char readme_msg[] =
"\t stype: u8/u16/u32/u64, s8/s16/s32/s64, pid_t,\n"
"\t [unsigned] char/int/long\n"
#endif
+ "\t efield: For event probes ('e' types), the field is on of the fields\n"
+ "\t of the <attached-group>/<attached-event>.\n"
#endif
" events/\t\t- Directory containing all trace event subsystems:\n"
" enable\t\t- Write 0/1 to enable/disable tracing of all events\n"
@@ -5654,6 +5657,7 @@ static const char readme_msg[] =
"\t .execname display a common_pid as a program name\n"
"\t .syscall display a syscall id as a syscall name\n"
"\t .log2 display log2 value rather than raw number\n"
+ "\t .buckets=size display values in groups of size rather than raw number\n"
"\t .usecs display a common_timestamp in microseconds\n\n"
"\t The 'pause' parameter can be used to pause an existing hist\n"
"\t trigger or to start a hist trigger but not log any events\n"
@@ -9815,7 +9819,6 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
tracing_off();
local_irq_save(flags);
- printk_nmi_direct_enter();
/* Simulate the iterator */
trace_init_global_iter(&iter);
@@ -9897,7 +9900,6 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
atomic_dec(&per_cpu_ptr(iter.array_buffer->data, cpu)->disabled);
}
atomic_dec(&dump_running);
- printk_nmi_direct_exit();
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(ftrace_dump);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 4a0e693000c6..b7c0f8e160fb 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -126,6 +126,11 @@ struct kprobe_trace_entry_head {
unsigned long ip;
};
+struct eprobe_trace_entry_head {
+ struct trace_entry ent;
+ unsigned int type;
+};
+
struct kretprobe_trace_entry_head {
struct trace_entry ent;
unsigned long func;
@@ -1508,9 +1513,14 @@ static inline int register_trigger_hist_enable_disable_cmds(void) { return 0; }
extern int register_trigger_cmds(void);
extern void clear_event_triggers(struct trace_array *tr);
+enum {
+ EVENT_TRIGGER_FL_PROBE = BIT(0),
+};
+
struct event_trigger_data {
unsigned long count;
int ref;
+ int flags;
struct event_trigger_ops *ops;
struct event_command *cmd_ops;
struct event_filter __rcu *filter;
@@ -1918,6 +1928,14 @@ static inline bool is_good_name(const char *name)
return true;
}
+/* Convert certain expected symbols into '_' when generating event names */
+static inline void sanitize_event_name(char *name)
+{
+ while (*name++ != '\0')
+ if (*name == ':' || *name == '.')
+ *name = '_';
+}
+
/*
* This is a generic way to read and write a u64 value from a file in tracefs.
*
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
index 94ef2d099e32..1060b0446032 100644
--- a/kernel/trace/trace_boot.c
+++ b/kernel/trace/trace_boot.c
@@ -171,6 +171,290 @@ trace_boot_add_synth_event(struct xbc_node *node, const char *event)
}
#endif
+#ifdef CONFIG_HIST_TRIGGERS
+static int __init __printf(3, 4)
+append_printf(char **bufp, char *end, const char *fmt, ...)
+{
+ va_list args;
+ int ret;
+
+ if (*bufp == end)
+ return -ENOSPC;
+
+ va_start(args, fmt);
+ ret = vsnprintf(*bufp, end - *bufp, fmt, args);
+ if (ret < end - *bufp) {
+ *bufp += ret;
+ } else {
+ *bufp = end;
+ ret = -ERANGE;
+ }
+ va_end(args);
+
+ return ret;
+}
+
+static int __init
+append_str_nospace(char **bufp, char *end, const char *str)
+{
+ char *p = *bufp;
+ int len;
+
+ while (p < end - 1 && *str != '\0') {
+ if (!isspace(*str))
+ *(p++) = *str;
+ str++;
+ }
+ *p = '\0';
+ if (p == end - 1) {
+ *bufp = end;
+ return -ENOSPC;
+ }
+ len = p - *bufp;
+ *bufp = p;
+ return (int)len;
+}
+
+static int __init
+trace_boot_hist_add_array(struct xbc_node *hnode, char **bufp,
+ char *end, const char *key)
+{
+ struct xbc_node *knode, *anode;
+ const char *p;
+ char sep;
+
+ knode = xbc_node_find_child(hnode, key);
+ if (knode) {
+ anode = xbc_node_get_child(knode);
+ if (!anode) {
+ pr_err("hist.%s requires value(s).\n", key);
+ return -EINVAL;
+ }
+
+ append_printf(bufp, end, ":%s", key);
+ sep = '=';
+ xbc_array_for_each_value(anode, p) {
+ append_printf(bufp, end, "%c%s", sep, p);
+ if (sep == '=')
+ sep = ',';
+ }
+ } else
+ return -ENOENT;
+
+ return 0;
+}
+
+static int __init
+trace_boot_hist_add_one_handler(struct xbc_node *hnode, char **bufp,
+ char *end, const char *handler,
+ const char *param)
+{
+ struct xbc_node *knode, *anode;
+ const char *p;
+ char sep;
+
+ /* Compose 'handler' parameter */
+ p = xbc_node_find_value(hnode, param, NULL);
+ if (!p) {
+ pr_err("hist.%s requires '%s' option.\n",
+ xbc_node_get_data(hnode), param);
+ return -EINVAL;
+ }
+ append_printf(bufp, end, ":%s(%s)", handler, p);
+
+ /* Compose 'action' parameter */
+ knode = xbc_node_find_child(hnode, "trace");
+ if (!knode)
+ knode = xbc_node_find_child(hnode, "save");
+
+ if (knode) {
+ anode = xbc_node_get_child(knode);
+ if (!anode || !xbc_node_is_value(anode)) {
+ pr_err("hist.%s.%s requires value(s).\n",
+ xbc_node_get_data(hnode),
+ xbc_node_get_data(knode));
+ return -EINVAL;
+ }
+
+ append_printf(bufp, end, ".%s", xbc_node_get_data(knode));
+ sep = '(';
+ xbc_array_for_each_value(anode, p) {
+ append_printf(bufp, end, "%c%s", sep, p);
+ if (sep == '(')
+ sep = ',';
+ }
+ append_printf(bufp, end, ")");
+ } else if (xbc_node_find_child(hnode, "snapshot")) {
+ append_printf(bufp, end, ".snapshot()");
+ } else {
+ pr_err("hist.%s requires an action.\n",
+ xbc_node_get_data(hnode));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init
+trace_boot_hist_add_handlers(struct xbc_node *hnode, char **bufp,
+ char *end, const char *param)
+{
+ struct xbc_node *node;
+ const char *p, *handler;
+ int ret;
+
+ handler = xbc_node_get_data(hnode);
+
+ xbc_node_for_each_subkey(hnode, node) {
+ p = xbc_node_get_data(node);
+ if (!isdigit(p[0]))
+ continue;
+ /* All digit started node should be instances. */
+ ret = trace_boot_hist_add_one_handler(node, bufp, end, handler, param);
+ if (ret < 0)
+ break;
+ }
+
+ if (xbc_node_find_child(hnode, param))
+ ret = trace_boot_hist_add_one_handler(hnode, bufp, end, handler, param);
+
+ return ret;
+}
+
+/*
+ * Histogram boottime tracing syntax.
+ *
+ * ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist[.N] {
+ * keys = <KEY>[,...]
+ * values = <VAL>[,...]
+ * sort = <SORT-KEY>[,...]
+ * size = <ENTRIES>
+ * name = <HISTNAME>
+ * var { <VAR> = <EXPR> ... }
+ * pause|continue|clear
+ * onmax|onchange[.N] { var = <VAR>; <ACTION> [= <PARAM>] }
+ * onmatch[.N] { event = <EVENT>; <ACTION> [= <PARAM>] }
+ * filter = <FILTER>
+ * }
+ *
+ * Where <ACTION> are;
+ *
+ * trace = <EVENT>, <ARG1>[, ...]
+ * save = <ARG1>[, ...]
+ * snapshot
+ */
+static int __init
+trace_boot_compose_hist_cmd(struct xbc_node *hnode, char *buf, size_t size)
+{
+ struct xbc_node *node, *knode;
+ char *end = buf + size;
+ const char *p;
+ int ret = 0;
+
+ append_printf(&buf, end, "hist");
+
+ ret = trace_boot_hist_add_array(hnode, &buf, end, "keys");
+ if (ret < 0) {
+ if (ret == -ENOENT)
+ pr_err("hist requires keys.\n");
+ return -EINVAL;
+ }
+
+ ret = trace_boot_hist_add_array(hnode, &buf, end, "values");
+ if (ret == -EINVAL)
+ return ret;
+ ret = trace_boot_hist_add_array(hnode, &buf, end, "sort");
+ if (ret == -EINVAL)
+ return ret;
+
+ p = xbc_node_find_value(hnode, "size", NULL);
+ if (p)
+ append_printf(&buf, end, ":size=%s", p);
+
+ p = xbc_node_find_value(hnode, "name", NULL);
+ if (p)
+ append_printf(&buf, end, ":name=%s", p);
+
+ node = xbc_node_find_child(hnode, "var");
+ if (node) {
+ xbc_node_for_each_key_value(node, knode, p) {
+ /* Expression must not include spaces. */
+ append_printf(&buf, end, ":%s=",
+ xbc_node_get_data(knode));
+ append_str_nospace(&buf, end, p);
+ }
+ }
+
+ /* Histogram control attributes (mutual exclusive) */
+ if (xbc_node_find_child(hnode, "pause"))
+ append_printf(&buf, end, ":pause");
+ else if (xbc_node_find_child(hnode, "continue"))
+ append_printf(&buf, end, ":continue");
+ else if (xbc_node_find_child(hnode, "clear"))
+ append_printf(&buf, end, ":clear");
+
+ /* Histogram handler and actions */
+ node = xbc_node_find_child(hnode, "onmax");
+ if (node && trace_boot_hist_add_handlers(node, &buf, end, "var") < 0)
+ return -EINVAL;
+ node = xbc_node_find_child(hnode, "onchange");
+ if (node && trace_boot_hist_add_handlers(node, &buf, end, "var") < 0)
+ return -EINVAL;
+ node = xbc_node_find_child(hnode, "onmatch");
+ if (node && trace_boot_hist_add_handlers(node, &buf, end, "event") < 0)
+ return -EINVAL;
+
+ p = xbc_node_find_value(hnode, "filter", NULL);
+ if (p)
+ append_printf(&buf, end, " if %s", p);
+
+ if (buf == end) {
+ pr_err("hist exceeds the max command length.\n");
+ return -E2BIG;
+ }
+
+ return 0;
+}
+
+static void __init
+trace_boot_init_histograms(struct trace_event_file *file,
+ struct xbc_node *hnode, char *buf, size_t size)
+{
+ struct xbc_node *node;
+ const char *p;
+ char *tmp;
+
+ xbc_node_for_each_subkey(hnode, node) {
+ p = xbc_node_get_data(node);
+ if (!isdigit(p[0]))
+ continue;
+ /* All digit started node should be instances. */
+ if (trace_boot_compose_hist_cmd(node, buf, size) == 0) {
+ tmp = kstrdup(buf, GFP_KERNEL);
+ if (trigger_process_regex(file, buf) < 0)
+ pr_err("Failed to apply hist trigger: %s\n", tmp);
+ kfree(tmp);
+ }
+ }
+
+ if (xbc_node_find_child(hnode, "keys")) {
+ if (trace_boot_compose_hist_cmd(hnode, buf, size) == 0) {
+ tmp = kstrdup(buf, GFP_KERNEL);
+ if (trigger_process_regex(file, buf) < 0)
+ pr_err("Failed to apply hist trigger: %s\n", tmp);
+ kfree(tmp);
+ }
+ }
+}
+#else
+static void __init
+trace_boot_init_histograms(struct trace_event_file *file,
+ struct xbc_node *hnode, char *buf, size_t size)
+{
+ /* do nothing */
+}
+#endif
+
static void __init
trace_boot_init_one_event(struct trace_array *tr, struct xbc_node *gnode,
struct xbc_node *enode)
@@ -205,12 +489,18 @@ trace_boot_init_one_event(struct trace_array *tr, struct xbc_node *gnode,
pr_err("Failed to apply filter: %s\n", buf);
}
- xbc_node_for_each_array_value(enode, "actions", anode, p) {
- if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf))
- pr_err("action string is too long: %s\n", p);
- else if (trigger_process_regex(file, buf) < 0)
- pr_err("Failed to apply an action: %s\n", buf);
- }
+ if (IS_ENABLED(CONFIG_HIST_TRIGGERS)) {
+ xbc_node_for_each_array_value(enode, "actions", anode, p) {
+ if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf))
+ pr_err("action string is too long: %s\n", p);
+ else if (trigger_process_regex(file, buf) < 0)
+ pr_err("Failed to apply an action: %s\n", p);
+ }
+ anode = xbc_node_find_child(enode, "hist");
+ if (anode)
+ trace_boot_init_histograms(file, anode, buf, ARRAY_SIZE(buf));
+ } else if (xbc_node_find_value(enode, "actions", NULL))
+ pr_err("Failed to apply event actions because CONFIG_HIST_TRIGGERS is not set.\n");
if (xbc_node_find_value(enode, "enable", NULL)) {
if (trace_event_enable_disable(file, 1, 0) < 0)
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index e57cc0870892..1110112e55bd 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -13,11 +13,49 @@
#include <linux/tracefs.h>
#include "trace.h"
+#include "trace_output.h" /* for trace_event_sem */
#include "trace_dynevent.h"
static DEFINE_MUTEX(dyn_event_ops_mutex);
static LIST_HEAD(dyn_event_ops_list);
+bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call)
+{
+ struct trace_event_call *call;
+ bool ret = false;
+
+ if (WARN_ON_ONCE(!(dyn_call->flags & TRACE_EVENT_FL_DYNAMIC)))
+ return false;
+
+ down_read(&trace_event_sem);
+ list_for_each_entry(call, &ftrace_events, list) {
+ if (call == dyn_call) {
+ atomic_inc(&dyn_call->refcnt);
+ ret = true;
+ }
+ }
+ up_read(&trace_event_sem);
+ return ret;
+}
+
+void trace_event_dyn_put_ref(struct trace_event_call *call)
+{
+ if (WARN_ON_ONCE(!(call->flags & TRACE_EVENT_FL_DYNAMIC)))
+ return;
+
+ if (WARN_ON_ONCE(atomic_read(&call->refcnt) <= 0)) {
+ atomic_set(&call->refcnt, 0);
+ return;
+ }
+
+ atomic_dec(&call->refcnt);
+}
+
+bool trace_event_dyn_busy(struct trace_event_call *call)
+{
+ return atomic_read(&call->refcnt) != 0;
+}
+
int dyn_event_register(struct dyn_event_operations *ops)
{
if (!ops || !ops->create || !ops->show || !ops->is_busy ||
diff --git a/kernel/trace/trace_dynevent.h b/kernel/trace/trace_dynevent.h
index 7754936b57ee..936477a111d3 100644
--- a/kernel/trace/trace_dynevent.h
+++ b/kernel/trace/trace_dynevent.h
@@ -76,13 +76,15 @@ int dyn_event_init(struct dyn_event *ev, struct dyn_event_operations *ops)
return 0;
}
-static inline int dyn_event_add(struct dyn_event *ev)
+static inline int dyn_event_add(struct dyn_event *ev,
+ struct trace_event_call *call)
{
lockdep_assert_held(&event_mutex);
if (!ev || !ev->ops)
return -EINVAL;
+ call->flags |= TRACE_EVENT_FL_DYNAMIC;
list_add_tail(&ev->list, &dyn_event_list);
return 0;
}
diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c
new file mode 100644
index 000000000000..56a96e9750cf
--- /dev/null
+++ b/kernel/trace/trace_eprobe.c
@@ -0,0 +1,903 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * event probes
+ *
+ * Part of this code was copied from kernel/trace/trace_kprobe.c written by
+ * Masami Hiramatsu <mhiramat@kernel.org>
+ *
+ * Copyright (C) 2021, VMware Inc, Steven Rostedt <rostedt@goodmis.org>
+ * Copyright (C) 2021, VMware Inc, Tzvetomir Stoyanov tz.stoyanov@gmail.com>
+ *
+ */
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/ftrace.h>
+
+#include "trace_dynevent.h"
+#include "trace_probe.h"
+#include "trace_probe_tmpl.h"
+
+#define EPROBE_EVENT_SYSTEM "eprobes"
+
+struct trace_eprobe {
+ /* tracepoint system */
+ const char *event_system;
+
+ /* tracepoint event */
+ const char *event_name;
+
+ struct trace_event_call *event;
+
+ struct dyn_event devent;
+ struct trace_probe tp;
+};
+
+struct eprobe_data {
+ struct trace_event_file *file;
+ struct trace_eprobe *ep;
+};
+
+static int __trace_eprobe_create(int argc, const char *argv[]);
+
+static void trace_event_probe_cleanup(struct trace_eprobe *ep)
+{
+ if (!ep)
+ return;
+ trace_probe_cleanup(&ep->tp);
+ kfree(ep->event_name);
+ kfree(ep->event_system);
+ if (ep->event)
+ trace_event_put_ref(ep->event);
+ kfree(ep);
+}
+
+static struct trace_eprobe *to_trace_eprobe(struct dyn_event *ev)
+{
+ return container_of(ev, struct trace_eprobe, devent);
+}
+
+static int eprobe_dyn_event_create(const char *raw_command)
+{
+ return trace_probe_create(raw_command, __trace_eprobe_create);
+}
+
+static int eprobe_dyn_event_show(struct seq_file *m, struct dyn_event *ev)
+{
+ struct trace_eprobe *ep = to_trace_eprobe(ev);
+ int i;
+
+ seq_printf(m, "e:%s/%s", trace_probe_group_name(&ep->tp),
+ trace_probe_name(&ep->tp));
+ seq_printf(m, " %s.%s", ep->event_system, ep->event_name);
+
+ for (i = 0; i < ep->tp.nr_args; i++)
+ seq_printf(m, " %s=%s", ep->tp.args[i].name, ep->tp.args[i].comm);
+ seq_putc(m, '\n');
+
+ return 0;
+}
+
+static int unregister_trace_eprobe(struct trace_eprobe *ep)
+{
+ /* If other probes are on the event, just unregister eprobe */
+ if (trace_probe_has_sibling(&ep->tp))
+ goto unreg;
+
+ /* Enabled event can not be unregistered */
+ if (trace_probe_is_enabled(&ep->tp))
+ return -EBUSY;
+
+ /* Will fail if probe is being used by ftrace or perf */
+ if (trace_probe_unregister_event_call(&ep->tp))
+ return -EBUSY;
+
+unreg:
+ dyn_event_remove(&ep->devent);
+ trace_probe_unlink(&ep->tp);
+
+ return 0;
+}
+
+static int eprobe_dyn_event_release(struct dyn_event *ev)
+{
+ struct trace_eprobe *ep = to_trace_eprobe(ev);
+ int ret = unregister_trace_eprobe(ep);
+
+ if (!ret)
+ trace_event_probe_cleanup(ep);
+ return ret;
+}
+
+static bool eprobe_dyn_event_is_busy(struct dyn_event *ev)
+{
+ struct trace_eprobe *ep = to_trace_eprobe(ev);
+
+ return trace_probe_is_enabled(&ep->tp);
+}
+
+static bool eprobe_dyn_event_match(const char *system, const char *event,
+ int argc, const char **argv, struct dyn_event *ev)
+{
+ struct trace_eprobe *ep = to_trace_eprobe(ev);
+
+ return strcmp(trace_probe_name(&ep->tp), event) == 0 &&
+ (!system || strcmp(trace_probe_group_name(&ep->tp), system) == 0) &&
+ trace_probe_match_command_args(&ep->tp, argc, argv);
+}
+
+static struct dyn_event_operations eprobe_dyn_event_ops = {
+ .create = eprobe_dyn_event_create,
+ .show = eprobe_dyn_event_show,
+ .is_busy = eprobe_dyn_event_is_busy,
+ .free = eprobe_dyn_event_release,
+ .match = eprobe_dyn_event_match,
+};
+
+static struct trace_eprobe *alloc_event_probe(const char *group,
+ const char *this_event,
+ struct trace_event_call *event,
+ int nargs)
+{
+ struct trace_eprobe *ep;
+ const char *event_name;
+ const char *sys_name;
+ int ret = -ENOMEM;
+
+ if (!event)
+ return ERR_PTR(-ENODEV);
+
+ sys_name = event->class->system;
+ event_name = trace_event_name(event);
+
+ ep = kzalloc(struct_size(ep, tp.args, nargs), GFP_KERNEL);
+ if (!ep) {
+ trace_event_put_ref(ep->event);
+ goto error;
+ }
+ ep->event = event;
+ ep->event_name = kstrdup(event_name, GFP_KERNEL);
+ if (!ep->event_name)
+ goto error;
+ ep->event_system = kstrdup(sys_name, GFP_KERNEL);
+ if (!ep->event_system)
+ goto error;
+
+ ret = trace_probe_init(&ep->tp, this_event, group, false);
+ if (ret < 0)
+ goto error;
+
+ dyn_event_init(&ep->devent, &eprobe_dyn_event_ops);
+ return ep;
+error:
+ trace_event_probe_cleanup(ep);
+ return ERR_PTR(ret);
+}
+
+static int trace_eprobe_tp_arg_update(struct trace_eprobe *ep, int i)
+{
+ struct probe_arg *parg = &ep->tp.args[i];
+ struct ftrace_event_field *field;
+ struct list_head *head;
+
+ head = trace_get_fields(ep->event);
+ list_for_each_entry(field, head, link) {
+ if (!strcmp(parg->code->data, field->name)) {
+ kfree(parg->code->data);
+ parg->code->data = field;
+ return 0;
+ }
+ }
+ kfree(parg->code->data);
+ parg->code->data = NULL;
+ return -ENOENT;
+}
+
+static int eprobe_event_define_fields(struct trace_event_call *event_call)
+{
+ int ret;
+ struct eprobe_trace_entry_head field;
+ struct trace_probe *tp;
+
+ tp = trace_probe_primary_from_call(event_call);
+ if (WARN_ON_ONCE(!tp))
+ return -ENOENT;
+
+ DEFINE_FIELD(unsigned int, type, FIELD_STRING_TYPE, 0);
+
+ return traceprobe_define_arg_fields(event_call, sizeof(field), tp);
+}
+
+static struct trace_event_fields eprobe_fields_array[] = {
+ { .type = TRACE_FUNCTION_TYPE,
+ .define_fields = eprobe_event_define_fields },
+ {}
+};
+
+/* Event entry printers */
+static enum print_line_t
+print_eprobe_event(struct trace_iterator *iter, int flags,
+ struct trace_event *event)
+{
+ struct eprobe_trace_entry_head *field;
+ struct trace_event_call *pevent;
+ struct trace_event *probed_event;
+ struct trace_seq *s = &iter->seq;
+ struct trace_probe *tp;
+
+ field = (struct eprobe_trace_entry_head *)iter->ent;
+ tp = trace_probe_primary_from_call(
+ container_of(event, struct trace_event_call, event));
+ if (WARN_ON_ONCE(!tp))
+ goto out;
+
+ trace_seq_printf(s, "%s: (", trace_probe_name(tp));
+
+ probed_event = ftrace_find_event(field->type);
+ if (probed_event) {
+ pevent = container_of(probed_event, struct trace_event_call, event);
+ trace_seq_printf(s, "%s.%s", pevent->class->system,
+ trace_event_name(pevent));
+ } else {
+ trace_seq_printf(s, "%u", field->type);
+ }
+
+ trace_seq_putc(s, ')');
+
+ if (print_probe_args(s, tp->args, tp->nr_args,
+ (u8 *)&field[1], field) < 0)
+ goto out;
+
+ trace_seq_putc(s, '\n');
+ out:
+ return trace_handle_return(s);
+}
+
+static unsigned long get_event_field(struct fetch_insn *code, void *rec)
+{
+ struct ftrace_event_field *field = code->data;
+ unsigned long val;
+ void *addr;
+
+ addr = rec + field->offset;
+
+ switch (field->size) {
+ case 1:
+ if (field->is_signed)
+ val = *(char *)addr;
+ else
+ val = *(unsigned char *)addr;
+ break;
+ case 2:
+ if (field->is_signed)
+ val = *(short *)addr;
+ else
+ val = *(unsigned short *)addr;
+ break;
+ case 4:
+ if (field->is_signed)
+ val = *(int *)addr;
+ else
+ val = *(unsigned int *)addr;
+ break;
+ default:
+ if (field->is_signed)
+ val = *(long *)addr;
+ else
+ val = *(unsigned long *)addr;
+ break;
+ }
+ return val;
+}
+
+static int get_eprobe_size(struct trace_probe *tp, void *rec)
+{
+ struct probe_arg *arg;
+ int i, len, ret = 0;
+
+ for (i = 0; i < tp->nr_args; i++) {
+ arg = tp->args + i;
+ if (unlikely(arg->dynamic)) {
+ unsigned long val;
+
+ val = get_event_field(arg->code, rec);
+ len = process_fetch_insn_bottom(arg->code + 1, val, NULL, NULL);
+ if (len > 0)
+ ret += len;
+ }
+ }
+
+ return ret;
+}
+
+/* Kprobe specific fetch functions */
+
+/* Note that we don't verify it, since the code does not come from user space */
+static int
+process_fetch_insn(struct fetch_insn *code, void *rec, void *dest,
+ void *base)
+{
+ unsigned long val;
+
+ val = get_event_field(code, rec);
+ return process_fetch_insn_bottom(code + 1, val, dest, base);
+}
+NOKPROBE_SYMBOL(process_fetch_insn)
+
+/* Return the length of string -- including null terminal byte */
+static nokprobe_inline int
+fetch_store_strlen_user(unsigned long addr)
+{
+ const void __user *uaddr = (__force const void __user *)addr;
+
+ return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
+}
+
+/* Return the length of string -- including null terminal byte */
+static nokprobe_inline int
+fetch_store_strlen(unsigned long addr)
+{
+ int ret, len = 0;
+ u8 c;
+
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+ if (addr < TASK_SIZE)
+ return fetch_store_strlen_user(addr);
+#endif
+
+ do {
+ ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
+ len++;
+ } while (c && ret == 0 && len < MAX_STRING_SIZE);
+
+ return (ret < 0) ? ret : len;
+}
+
+/*
+ * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf
+ * with max length and relative data location.
+ */
+static nokprobe_inline int
+fetch_store_string_user(unsigned long addr, void *dest, void *base)
+{
+ const void __user *uaddr = (__force const void __user *)addr;
+ int maxlen = get_loc_len(*(u32 *)dest);
+ void *__dest;
+ long ret;
+
+ if (unlikely(!maxlen))
+ return -ENOMEM;
+
+ __dest = get_loc_data(dest, base);
+
+ ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
+ if (ret >= 0)
+ *(u32 *)dest = make_data_loc(ret, __dest - base);
+
+ return ret;
+}
+
+/*
+ * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max
+ * length and relative data location.
+ */
+static nokprobe_inline int
+fetch_store_string(unsigned long addr, void *dest, void *base)
+{
+ int maxlen = get_loc_len(*(u32 *)dest);
+ void *__dest;
+ long ret;
+
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+ if ((unsigned long)addr < TASK_SIZE)
+ return fetch_store_string_user(addr, dest, base);
+#endif
+
+ if (unlikely(!maxlen))
+ return -ENOMEM;
+
+ __dest = get_loc_data(dest, base);
+
+ /*
+ * Try to get string again, since the string can be changed while
+ * probing.
+ */
+ ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
+ if (ret >= 0)
+ *(u32 *)dest = make_data_loc(ret, __dest - base);
+
+ return ret;
+}
+
+static nokprobe_inline int
+probe_mem_read_user(void *dest, void *src, size_t size)
+{
+ const void __user *uaddr = (__force const void __user *)src;
+
+ return copy_from_user_nofault(dest, uaddr, size);
+}
+
+static nokprobe_inline int
+probe_mem_read(void *dest, void *src, size_t size)
+{
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+ if ((unsigned long)src < TASK_SIZE)
+ return probe_mem_read_user(dest, src, size);
+#endif
+ return copy_from_kernel_nofault(dest, src, size);
+}
+
+/* eprobe handler */
+static inline void
+__eprobe_trace_func(struct eprobe_data *edata, void *rec)
+{
+ struct eprobe_trace_entry_head *entry;
+ struct trace_event_call *call = trace_probe_event_call(&edata->ep->tp);
+ struct trace_event_buffer fbuffer;
+ int dsize;
+
+ if (WARN_ON_ONCE(call != edata->file->event_call))
+ return;
+
+ if (trace_trigger_soft_disabled(edata->file))
+ return;
+
+ fbuffer.trace_ctx = tracing_gen_ctx();
+ fbuffer.trace_file = edata->file;
+
+ dsize = get_eprobe_size(&edata->ep->tp, rec);
+ fbuffer.regs = NULL;
+
+ fbuffer.event =
+ trace_event_buffer_lock_reserve(&fbuffer.buffer, edata->file,
+ call->event.type,
+ sizeof(*entry) + edata->ep->tp.size + dsize,
+ fbuffer.trace_ctx);
+ if (!fbuffer.event)
+ return;
+
+ entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event);
+ if (edata->ep->event)
+ entry->type = edata->ep->event->event.type;
+ else
+ entry->type = 0;
+ store_trace_args(&entry[1], &edata->ep->tp, rec, sizeof(*entry), dsize);
+
+ trace_event_buffer_commit(&fbuffer);
+}
+
+/*
+ * The event probe implementation uses event triggers to get access to
+ * the event it is attached to, but is not an actual trigger. The below
+ * functions are just stubs to fulfill what is needed to use the trigger
+ * infrastructure.
+ */
+static int eprobe_trigger_init(struct event_trigger_ops *ops,
+ struct event_trigger_data *data)
+{
+ return 0;
+}
+
+static void eprobe_trigger_free(struct event_trigger_ops *ops,
+ struct event_trigger_data *data)
+{
+
+}
+
+static int eprobe_trigger_print(struct seq_file *m,
+ struct event_trigger_ops *ops,
+ struct event_trigger_data *data)
+{
+ /* Do not print eprobe event triggers */
+ return 0;
+}
+
+static void eprobe_trigger_func(struct event_trigger_data *data,
+ struct trace_buffer *buffer, void *rec,
+ struct ring_buffer_event *rbe)
+{
+ struct eprobe_data *edata = data->private_data;
+
+ __eprobe_trace_func(edata, rec);
+}
+
+static struct event_trigger_ops eprobe_trigger_ops = {
+ .func = eprobe_trigger_func,
+ .print = eprobe_trigger_print,
+ .init = eprobe_trigger_init,
+ .free = eprobe_trigger_free,
+};
+
+static int eprobe_trigger_cmd_func(struct event_command *cmd_ops,
+ struct trace_event_file *file,
+ char *glob, char *cmd, char *param)
+{
+ return -1;
+}
+
+static int eprobe_trigger_reg_func(char *glob, struct event_trigger_ops *ops,
+ struct event_trigger_data *data,
+ struct trace_event_file *file)
+{
+ return -1;
+}
+
+static void eprobe_trigger_unreg_func(char *glob, struct event_trigger_ops *ops,
+ struct event_trigger_data *data,
+ struct trace_event_file *file)
+{
+
+}
+
+static struct event_trigger_ops *eprobe_trigger_get_ops(char *cmd,
+ char *param)
+{
+ return &eprobe_trigger_ops;
+}
+
+static struct event_command event_trigger_cmd = {
+ .name = "eprobe",
+ .trigger_type = ETT_EVENT_EPROBE,
+ .flags = EVENT_CMD_FL_NEEDS_REC,
+ .func = eprobe_trigger_cmd_func,
+ .reg = eprobe_trigger_reg_func,
+ .unreg = eprobe_trigger_unreg_func,
+ .unreg_all = NULL,
+ .get_trigger_ops = eprobe_trigger_get_ops,
+ .set_filter = NULL,
+};
+
+static struct event_trigger_data *
+new_eprobe_trigger(struct trace_eprobe *ep, struct trace_event_file *file)
+{
+ struct event_trigger_data *trigger;
+ struct eprobe_data *edata;
+
+ edata = kzalloc(sizeof(*edata), GFP_KERNEL);
+ trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
+ if (!trigger || !edata) {
+ kfree(edata);
+ kfree(trigger);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ trigger->flags = EVENT_TRIGGER_FL_PROBE;
+ trigger->count = -1;
+ trigger->ops = &eprobe_trigger_ops;
+
+ /*
+ * EVENT PROBE triggers are not registered as commands with
+ * register_event_command(), as they are not controlled by the user
+ * from the trigger file
+ */
+ trigger->cmd_ops = &event_trigger_cmd;
+
+ INIT_LIST_HEAD(&trigger->list);
+ RCU_INIT_POINTER(trigger->filter, NULL);
+
+ edata->file = file;
+ edata->ep = ep;
+ trigger->private_data = edata;
+
+ return trigger;
+}
+
+static int enable_eprobe(struct trace_eprobe *ep,
+ struct trace_event_file *eprobe_file)
+{
+ struct event_trigger_data *trigger;
+ struct trace_event_file *file;
+ struct trace_array *tr = eprobe_file->tr;
+
+ file = find_event_file(tr, ep->event_system, ep->event_name);
+ if (!file)
+ return -ENOENT;
+ trigger = new_eprobe_trigger(ep, eprobe_file);
+ if (IS_ERR(trigger))
+ return PTR_ERR(trigger);
+
+ list_add_tail_rcu(&trigger->list, &file->triggers);
+
+ trace_event_trigger_enable_disable(file, 1);
+ update_cond_flag(file);
+
+ return 0;
+}
+
+static struct trace_event_functions eprobe_funcs = {
+ .trace = print_eprobe_event
+};
+
+static int disable_eprobe(struct trace_eprobe *ep,
+ struct trace_array *tr)
+{
+ struct event_trigger_data *trigger;
+ struct trace_event_file *file;
+ struct eprobe_data *edata;
+
+ file = find_event_file(tr, ep->event_system, ep->event_name);
+ if (!file)
+ return -ENOENT;
+
+ list_for_each_entry(trigger, &file->triggers, list) {
+ if (!(trigger->flags & EVENT_TRIGGER_FL_PROBE))
+ continue;
+ edata = trigger->private_data;
+ if (edata->ep == ep)
+ break;
+ }
+ if (list_entry_is_head(trigger, &file->triggers, list))
+ return -ENODEV;
+
+ list_del_rcu(&trigger->list);
+
+ trace_event_trigger_enable_disable(file, 0);
+ update_cond_flag(file);
+ return 0;
+}
+
+static int enable_trace_eprobe(struct trace_event_call *call,
+ struct trace_event_file *file)
+{
+ struct trace_probe *pos, *tp;
+ struct trace_eprobe *ep;
+ bool enabled;
+ int ret = 0;
+
+ tp = trace_probe_primary_from_call(call);
+ if (WARN_ON_ONCE(!tp))
+ return -ENODEV;
+ enabled = trace_probe_is_enabled(tp);
+
+ /* This also changes "enabled" state */
+ if (file) {
+ ret = trace_probe_add_file(tp, file);
+ if (ret)
+ return ret;
+ } else
+ trace_probe_set_flag(tp, TP_FLAG_PROFILE);
+
+ if (enabled)
+ return 0;
+
+ list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
+ ep = container_of(pos, struct trace_eprobe, tp);
+ ret = enable_eprobe(ep, file);
+ if (ret)
+ break;
+ enabled = true;
+ }
+
+ if (ret) {
+ /* Failed to enable one of them. Roll back all */
+ if (enabled)
+ disable_eprobe(ep, file->tr);
+ if (file)
+ trace_probe_remove_file(tp, file);
+ else
+ trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
+ }
+
+ return ret;
+}
+
+static int disable_trace_eprobe(struct trace_event_call *call,
+ struct trace_event_file *file)
+{
+ struct trace_probe *pos, *tp;
+ struct trace_eprobe *ep;
+
+ tp = trace_probe_primary_from_call(call);
+ if (WARN_ON_ONCE(!tp))
+ return -ENODEV;
+
+ if (file) {
+ if (!trace_probe_get_file_link(tp, file))
+ return -ENOENT;
+ if (!trace_probe_has_single_file(tp))
+ goto out;
+ trace_probe_clear_flag(tp, TP_FLAG_TRACE);
+ } else
+ trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
+
+ if (!trace_probe_is_enabled(tp)) {
+ list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
+ ep = container_of(pos, struct trace_eprobe, tp);
+ disable_eprobe(ep, file->tr);
+ }
+ }
+
+ out:
+ if (file)
+ /*
+ * Synchronization is done in below function. For perf event,
+ * file == NULL and perf_trace_event_unreg() calls
+ * tracepoint_synchronize_unregister() to ensure synchronize
+ * event. We don't need to care about it.
+ */
+ trace_probe_remove_file(tp, file);
+
+ return 0;
+}
+
+static int eprobe_register(struct trace_event_call *event,
+ enum trace_reg type, void *data)
+{
+ struct trace_event_file *file = data;
+
+ switch (type) {
+ case TRACE_REG_REGISTER:
+ return enable_trace_eprobe(event, file);
+ case TRACE_REG_UNREGISTER:
+ return disable_trace_eprobe(event, file);
+#ifdef CONFIG_PERF_EVENTS
+ case TRACE_REG_PERF_REGISTER:
+ case TRACE_REG_PERF_UNREGISTER:
+ case TRACE_REG_PERF_OPEN:
+ case TRACE_REG_PERF_CLOSE:
+ case TRACE_REG_PERF_ADD:
+ case TRACE_REG_PERF_DEL:
+ return 0;
+#endif
+ }
+ return 0;
+}
+
+static inline void init_trace_eprobe_call(struct trace_eprobe *ep)
+{
+ struct trace_event_call *call = trace_probe_event_call(&ep->tp);
+
+ call->flags = TRACE_EVENT_FL_EPROBE;
+ call->event.funcs = &eprobe_funcs;
+ call->class->fields_array = eprobe_fields_array;
+ call->class->reg = eprobe_register;
+}
+
+static struct trace_event_call *
+find_and_get_event(const char *system, const char *event_name)
+{
+ struct trace_event_call *tp_event;
+ const char *name;
+
+ list_for_each_entry(tp_event, &ftrace_events, list) {
+ /* Skip other probes and ftrace events */
+ if (tp_event->flags &
+ (TRACE_EVENT_FL_IGNORE_ENABLE |
+ TRACE_EVENT_FL_KPROBE |
+ TRACE_EVENT_FL_UPROBE |
+ TRACE_EVENT_FL_EPROBE))
+ continue;
+ if (!tp_event->class->system ||
+ strcmp(system, tp_event->class->system))
+ continue;
+ name = trace_event_name(tp_event);
+ if (!name || strcmp(event_name, name))
+ continue;
+ if (!trace_event_try_get_ref(tp_event)) {
+ return NULL;
+ break;
+ }
+ return tp_event;
+ break;
+ }
+ return NULL;
+}
+
+static int trace_eprobe_tp_update_arg(struct trace_eprobe *ep, const char *argv[], int i)
+{
+ unsigned int flags = TPARG_FL_KERNEL | TPARG_FL_TPOINT;
+ int ret;
+
+ ret = traceprobe_parse_probe_arg(&ep->tp, i, argv[i], flags);
+ if (ret)
+ return ret;
+
+ if (ep->tp.args[i].code->op == FETCH_OP_TP_ARG)
+ ret = trace_eprobe_tp_arg_update(ep, i);
+
+ return ret;
+}
+
+static int __trace_eprobe_create(int argc, const char *argv[])
+{
+ /*
+ * Argument syntax:
+ * e[:[GRP/]ENAME] SYSTEM.EVENT [FETCHARGS]
+ * Fetch args:
+ * <name>=$<field>[:TYPE]
+ */
+ const char *event = NULL, *group = EPROBE_EVENT_SYSTEM;
+ const char *sys_event = NULL, *sys_name = NULL;
+ struct trace_event_call *event_call;
+ struct trace_eprobe *ep = NULL;
+ char buf1[MAX_EVENT_NAME_LEN];
+ char buf2[MAX_EVENT_NAME_LEN];
+ int ret = 0;
+ int i;
+
+ if (argc < 2 || argv[0][0] != 'e')
+ return -ECANCELED;
+
+ trace_probe_log_init("event_probe", argc, argv);
+
+ event = strchr(&argv[0][1], ':');
+ if (event) {
+ event++;
+ ret = traceprobe_parse_event_name(&event, &group, buf1,
+ event - argv[0]);
+ if (ret)
+ goto parse_error;
+ } else {
+ strscpy(buf1, argv[1], MAX_EVENT_NAME_LEN);
+ sanitize_event_name(buf1);
+ event = buf1;
+ }
+ if (!is_good_name(event) || !is_good_name(group))
+ goto parse_error;
+
+ sys_event = argv[1];
+ ret = traceprobe_parse_event_name(&sys_event, &sys_name, buf2,
+ sys_event - argv[1]);
+ if (ret || !sys_name)
+ goto parse_error;
+ if (!is_good_name(sys_event) || !is_good_name(sys_name))
+ goto parse_error;
+
+ mutex_lock(&event_mutex);
+ event_call = find_and_get_event(sys_name, sys_event);
+ ep = alloc_event_probe(group, event, event_call, argc - 2);
+ mutex_unlock(&event_mutex);
+
+ if (IS_ERR(ep)) {
+ ret = PTR_ERR(ep);
+ /* This must return -ENOMEM, else there is a bug */
+ WARN_ON_ONCE(ret != -ENOMEM);
+ goto error; /* We know ep is not allocated */
+ }
+
+ argc -= 2; argv += 2;
+ /* parse arguments */
+ for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
+ trace_probe_log_set_index(i + 2);
+ ret = trace_eprobe_tp_update_arg(ep, argv, i);
+ if (ret)
+ goto error;
+ }
+ ret = traceprobe_set_print_fmt(&ep->tp, PROBE_PRINT_EVENT);
+ if (ret < 0)
+ goto error;
+ init_trace_eprobe_call(ep);
+ mutex_lock(&event_mutex);
+ ret = trace_probe_register_event_call(&ep->tp);
+ if (ret) {
+ if (ret == -EEXIST) {
+ trace_probe_log_set_index(0);
+ trace_probe_log_err(0, EVENT_EXIST);
+ }
+ mutex_unlock(&event_mutex);
+ goto error;
+ }
+ ret = dyn_event_add(&ep->devent, &ep->tp.event->call);
+ mutex_unlock(&event_mutex);
+ return ret;
+parse_error:
+ ret = -EINVAL;
+error:
+ trace_event_probe_cleanup(ep);
+ return ret;
+}
+
+/*
+ * Register dynevent at core_initcall. This allows kernel to setup eprobe
+ * events in postcore_initcall without tracefs.
+ */
+static __init int trace_events_eprobe_init_early(void)
+{
+ int err = 0;
+
+ err = dyn_event_register(&eprobe_dyn_event_ops);
+ if (err)
+ pr_warn("Could not register eprobe_dyn_event_ops\n");
+
+ return err;
+}
+core_initcall(trace_events_eprobe_init_early);
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 03be4435d103..6aed10e2f7ce 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -177,7 +177,7 @@ static void perf_trace_event_unreg(struct perf_event *p_event)
}
}
out:
- module_put(tp_event->mod);
+ trace_event_put_ref(tp_event);
}
static int perf_trace_event_open(struct perf_event *p_event)
@@ -224,10 +224,10 @@ int perf_trace_init(struct perf_event *p_event)
list_for_each_entry(tp_event, &ftrace_events, list) {
if (tp_event->event.type == event_id &&
tp_event->class && tp_event->class->reg &&
- try_module_get(tp_event->mod)) {
+ trace_event_try_get_ref(tp_event)) {
ret = perf_trace_event_init(tp_event, p_event);
if (ret)
- module_put(tp_event->mod);
+ trace_event_put_ref(tp_event);
break;
}
}
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 80e96989770e..1349b6de5eeb 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2525,7 +2525,10 @@ __register_event(struct trace_event_call *call, struct module *mod)
return ret;
list_add(&call->list, &ftrace_events);
- call->mod = mod;
+ if (call->flags & TRACE_EVENT_FL_DYNAMIC)
+ atomic_set(&call->refcnt, 0);
+ else
+ call->module = mod;
return 0;
}
@@ -2839,7 +2842,9 @@ static void trace_module_remove_events(struct module *mod)
down_write(&trace_event_sem);
list_for_each_entry_safe(call, p, &ftrace_events, list) {
- if (call->mod == mod)
+ if ((call->flags & TRACE_EVENT_FL_DYNAMIC) || !call->module)
+ continue;
+ if (call->module == mod)
__trace_remove_event_call(call);
}
up_write(&trace_event_sem);
@@ -2982,7 +2987,7 @@ struct trace_event_file *trace_get_event_file(const char *instance,
}
/* Don't let event modules unload while in use */
- ret = try_module_get(file->event_call->mod);
+ ret = trace_event_try_get_ref(file->event_call);
if (!ret) {
trace_array_put(tr);
ret = -EBUSY;
@@ -3012,7 +3017,7 @@ EXPORT_SYMBOL_GPL(trace_get_event_file);
void trace_put_event_file(struct trace_event_file *file)
{
mutex_lock(&event_mutex);
- module_put(file->event_call->mod);
+ trace_event_put_ref(file->event_call);
mutex_unlock(&event_mutex);
trace_array_put(file->tr);
@@ -3147,7 +3152,7 @@ static int free_probe_data(void *data)
if (!edata->ref) {
/* Remove the SOFT_MODE flag */
__ftrace_event_enable_disable(edata->file, 0, 1);
- module_put(edata->file->event_call->mod);
+ trace_event_put_ref(edata->file->event_call);
kfree(edata);
}
return 0;
@@ -3280,7 +3285,7 @@ event_enable_func(struct trace_array *tr, struct ftrace_hash *hash,
out_reg:
/* Don't let event modules unload while probe registered */
- ret = try_module_get(file->event_call->mod);
+ ret = trace_event_try_get_ref(file->event_call);
if (!ret) {
ret = -EBUSY;
goto out_free;
@@ -3310,7 +3315,7 @@ event_enable_func(struct trace_array *tr, struct ftrace_hash *hash,
out_disable:
__ftrace_event_enable_disable(file, 0, 1);
out_put:
- module_put(file->event_call->mod);
+ trace_event_put_ref(file->event_call);
out_free:
kfree(data);
goto out;
@@ -3376,7 +3381,8 @@ void __trace_early_add_events(struct trace_array *tr)
list_for_each_entry(call, &ftrace_events, list) {
/* Early boot up should not have any modules loaded */
- if (WARN_ON_ONCE(call->mod))
+ if (!(call->flags & TRACE_EVENT_FL_DYNAMIC) &&
+ WARN_ON_ONCE(call->module))
continue;
ret = __trace_early_add_new_event(call, tr);
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index a48aa2a2875b..9d91b1c06957 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -121,6 +121,7 @@ struct hist_field {
unsigned int size;
unsigned int offset;
unsigned int is_signed;
+ unsigned long buckets;
const char *type;
struct hist_field *operands[HIST_FIELD_OPERANDS_MAX];
struct hist_trigger_data *hist_data;
@@ -219,6 +220,27 @@ static u64 hist_field_log2(struct hist_field *hist_field,
return (u64) ilog2(roundup_pow_of_two(val));
}
+static u64 hist_field_bucket(struct hist_field *hist_field,
+ struct tracing_map_elt *elt,
+ struct trace_buffer *buffer,
+ struct ring_buffer_event *rbe,
+ void *event)
+{
+ struct hist_field *operand = hist_field->operands[0];
+ unsigned long buckets = hist_field->buckets;
+
+ u64 val = operand->fn(operand, elt, buffer, rbe, event);
+
+ if (WARN_ON_ONCE(!buckets))
+ return val;
+
+ if (val >= LONG_MAX)
+ val = div64_ul(val, buckets);
+ else
+ val = (u64)((unsigned long)val / buckets);
+ return val * buckets;
+}
+
static u64 hist_field_plus(struct hist_field *hist_field,
struct tracing_map_elt *elt,
struct trace_buffer *buffer,
@@ -318,6 +340,7 @@ enum hist_field_flags {
HIST_FIELD_FL_VAR_REF = 1 << 14,
HIST_FIELD_FL_CPU = 1 << 15,
HIST_FIELD_FL_ALIAS = 1 << 16,
+ HIST_FIELD_FL_BUCKET = 1 << 17,
};
struct var_defs {
@@ -1109,7 +1132,8 @@ static const char *hist_field_name(struct hist_field *field,
if (field->field)
field_name = field->field->name;
else if (field->flags & HIST_FIELD_FL_LOG2 ||
- field->flags & HIST_FIELD_FL_ALIAS)
+ field->flags & HIST_FIELD_FL_ALIAS ||
+ field->flags & HIST_FIELD_FL_BUCKET)
field_name = hist_field_name(field->operands[0], ++level);
else if (field->flags & HIST_FIELD_FL_CPU)
field_name = "common_cpu";
@@ -1396,17 +1420,17 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
struct hist_trigger_data *hist_data = elt->map->private_data;
unsigned int size = TASK_COMM_LEN;
struct hist_elt_data *elt_data;
- struct hist_field *key_field;
+ struct hist_field *hist_field;
unsigned int i, n_str;
elt_data = kzalloc(sizeof(*elt_data), GFP_KERNEL);
if (!elt_data)
return -ENOMEM;
- for_each_hist_key_field(i, hist_data) {
- key_field = hist_data->fields[i];
+ for_each_hist_field(i, hist_data) {
+ hist_field = hist_data->fields[i];
- if (key_field->flags & HIST_FIELD_FL_EXECNAME) {
+ if (hist_field->flags & HIST_FIELD_FL_EXECNAME) {
elt_data->comm = kzalloc(size, GFP_KERNEL);
if (!elt_data->comm) {
kfree(elt_data);
@@ -1470,6 +1494,8 @@ static const char *get_hist_field_flags(struct hist_field *hist_field)
flags_str = "syscall";
else if (hist_field->flags & HIST_FIELD_FL_LOG2)
flags_str = "log2";
+ else if (hist_field->flags & HIST_FIELD_FL_BUCKET)
+ flags_str = "buckets";
else if (hist_field->flags & HIST_FIELD_FL_TIMESTAMP_USECS)
flags_str = "usecs";
@@ -1590,7 +1616,9 @@ static void __destroy_hist_field(struct hist_field *hist_field)
kfree(hist_field->var.name);
kfree(hist_field->name);
- kfree(hist_field->type);
+
+ /* Can likely be a const */
+ kfree_const(hist_field->type);
kfree(hist_field->system);
kfree(hist_field->event_name);
@@ -1647,9 +1675,7 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
if (flags & HIST_FIELD_FL_HITCOUNT) {
hist_field->fn = hist_field_counter;
hist_field->size = sizeof(u64);
- hist_field->type = kstrdup("u64", GFP_KERNEL);
- if (!hist_field->type)
- goto free;
+ hist_field->type = "u64";
goto out;
}
@@ -1658,12 +1684,13 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
goto out;
}
- if (flags & HIST_FIELD_FL_LOG2) {
- unsigned long fl = flags & ~HIST_FIELD_FL_LOG2;
- hist_field->fn = hist_field_log2;
+ if (flags & (HIST_FIELD_FL_LOG2 | HIST_FIELD_FL_BUCKET)) {
+ unsigned long fl = flags & ~(HIST_FIELD_FL_LOG2 | HIST_FIELD_FL_BUCKET);
+ hist_field->fn = flags & HIST_FIELD_FL_LOG2 ? hist_field_log2 :
+ hist_field_bucket;
hist_field->operands[0] = create_hist_field(hist_data, field, fl, NULL);
hist_field->size = hist_field->operands[0]->size;
- hist_field->type = kstrdup(hist_field->operands[0]->type, GFP_KERNEL);
+ hist_field->type = kstrdup_const(hist_field->operands[0]->type, GFP_KERNEL);
if (!hist_field->type)
goto free;
goto out;
@@ -1672,18 +1699,14 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
if (flags & HIST_FIELD_FL_TIMESTAMP) {
hist_field->fn = hist_field_timestamp;
hist_field->size = sizeof(u64);
- hist_field->type = kstrdup("u64", GFP_KERNEL);
- if (!hist_field->type)
- goto free;
+ hist_field->type = "u64";
goto out;
}
if (flags & HIST_FIELD_FL_CPU) {
hist_field->fn = hist_field_cpu;
hist_field->size = sizeof(int);
- hist_field->type = kstrdup("unsigned int", GFP_KERNEL);
- if (!hist_field->type)
- goto free;
+ hist_field->type = "unsigned int";
goto out;
}
@@ -1696,7 +1719,7 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
flags |= HIST_FIELD_FL_STRING;
hist_field->size = MAX_FILTER_STR_VAL;
- hist_field->type = kstrdup(field->type, GFP_KERNEL);
+ hist_field->type = kstrdup_const(field->type, GFP_KERNEL);
if (!hist_field->type)
goto free;
@@ -1709,7 +1732,7 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
} else {
hist_field->size = field->size;
hist_field->is_signed = field->is_signed;
- hist_field->type = kstrdup(field->type, GFP_KERNEL);
+ hist_field->type = kstrdup_const(field->type, GFP_KERNEL);
if (!hist_field->type)
goto free;
@@ -1795,7 +1818,7 @@ static int init_var_ref(struct hist_field *ref_field,
}
}
- ref_field->type = kstrdup(var_field->type, GFP_KERNEL);
+ ref_field->type = kstrdup_const(var_field->type, GFP_KERNEL);
if (!ref_field->type) {
err = -ENOMEM;
goto free;
@@ -1953,7 +1976,7 @@ static struct hist_field *parse_var_ref(struct hist_trigger_data *hist_data,
static struct ftrace_event_field *
parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
- char *field_str, unsigned long *flags)
+ char *field_str, unsigned long *flags, unsigned long *buckets)
{
struct ftrace_event_field *field = NULL;
char *field_name, *modifier, *str;
@@ -1980,7 +2003,22 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
*flags |= HIST_FIELD_FL_LOG2;
else if (strcmp(modifier, "usecs") == 0)
*flags |= HIST_FIELD_FL_TIMESTAMP_USECS;
- else {
+ else if (strncmp(modifier, "bucket", 6) == 0) {
+ int ret;
+
+ modifier += 6;
+
+ if (*modifier == 's')
+ modifier++;
+ if (*modifier != '=')
+ goto error;
+ modifier++;
+ ret = kstrtoul(modifier, 0, buckets);
+ if (ret || !(*buckets))
+ goto error;
+ *flags |= HIST_FIELD_FL_BUCKET;
+ } else {
+ error:
hist_err(tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(modifier));
field = ERR_PTR(-EINVAL);
goto out;
@@ -2049,6 +2087,7 @@ static struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
char *s, *ref_system = NULL, *ref_event = NULL, *ref_var = str;
struct ftrace_event_field *field = NULL;
struct hist_field *hist_field = NULL;
+ unsigned long buckets = 0;
int ret = 0;
s = strchr(str, '.');
@@ -2086,7 +2125,7 @@ static struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
} else
str = s;
- field = parse_field(hist_data, file, str, flags);
+ field = parse_field(hist_data, file, str, flags, &buckets);
if (IS_ERR(field)) {
ret = PTR_ERR(field);
goto out;
@@ -2097,6 +2136,7 @@ static struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
ret = -ENOMEM;
goto out;
}
+ hist_field->buckets = buckets;
return hist_field;
out:
@@ -2171,7 +2211,7 @@ static struct hist_field *parse_unary(struct hist_trigger_data *hist_data,
expr->operands[0] = operand1;
expr->operator = FIELD_OP_UNARY_MINUS;
expr->name = expr_str(expr, 0);
- expr->type = kstrdup(operand1->type, GFP_KERNEL);
+ expr->type = kstrdup_const(operand1->type, GFP_KERNEL);
if (!expr->type) {
ret = -ENOMEM;
goto free;
@@ -2311,7 +2351,7 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
expr->operator = field_op;
expr->name = expr_str(expr, 0);
- expr->type = kstrdup(operand1->type, GFP_KERNEL);
+ expr->type = kstrdup_const(operand1->type, GFP_KERNEL);
if (!expr->type) {
ret = -ENOMEM;
goto free;
@@ -2699,10 +2739,10 @@ static struct hist_field *create_var(struct hist_trigger_data *hist_data,
var->var.hist_data = var->hist_data = hist_data;
var->size = size;
var->var.name = kstrdup(name, GFP_KERNEL);
- var->type = kstrdup(type, GFP_KERNEL);
+ var->type = kstrdup_const(type, GFP_KERNEL);
if (!var->var.name || !var->type) {
+ kfree_const(var->type);
kfree(var->var.name);
- kfree(var->type);
kfree(var);
var = ERR_PTR(-ENOMEM);
}
@@ -3731,6 +3771,41 @@ static int create_val_field(struct hist_trigger_data *hist_data,
return __create_val_field(hist_data, val_idx, file, NULL, field_str, 0);
}
+static const char *no_comm = "(no comm)";
+
+static u64 hist_field_execname(struct hist_field *hist_field,
+ struct tracing_map_elt *elt,
+ struct trace_buffer *buffer,
+ struct ring_buffer_event *rbe,
+ void *event)
+{
+ struct hist_elt_data *elt_data;
+
+ if (WARN_ON_ONCE(!elt))
+ return (u64)(unsigned long)no_comm;
+
+ elt_data = elt->private_data;
+
+ if (WARN_ON_ONCE(!elt_data->comm))
+ return (u64)(unsigned long)no_comm;
+
+ return (u64)(unsigned long)(elt_data->comm);
+}
+
+/* Convert a var that points to common_pid.execname to a string */
+static void update_var_execname(struct hist_field *hist_field)
+{
+ hist_field->flags = HIST_FIELD_FL_STRING | HIST_FIELD_FL_VAR |
+ HIST_FIELD_FL_EXECNAME;
+ hist_field->size = MAX_FILTER_STR_VAL;
+ hist_field->is_signed = 0;
+
+ kfree_const(hist_field->type);
+ hist_field->type = "char[]";
+
+ hist_field->fn = hist_field_execname;
+}
+
static int create_var_field(struct hist_trigger_data *hist_data,
unsigned int val_idx,
struct trace_event_file *file,
@@ -3755,6 +3830,9 @@ static int create_var_field(struct hist_trigger_data *hist_data,
ret = __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags);
+ if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_EXECNAME)
+ update_var_execname(hist_data->fields[val_idx]);
+
if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING)
hist_data->fields[val_idx]->var_str_idx = hist_data->n_var_str++;
@@ -4698,6 +4776,11 @@ static void hist_trigger_print_key(struct seq_file *m,
} else if (key_field->flags & HIST_FIELD_FL_LOG2) {
seq_printf(m, "%s: ~ 2^%-2llu", field_name,
*(u64 *)(key + key_field->offset));
+ } else if (key_field->flags & HIST_FIELD_FL_BUCKET) {
+ unsigned long buckets = key_field->buckets;
+ uval = *(u64 *)(key + key_field->offset);
+ seq_printf(m, "%s: ~ %llu-%llu", field_name,
+ uval, uval + buckets -1);
} else if (key_field->flags & HIST_FIELD_FL_STRING) {
seq_printf(m, "%s: %-50s", field_name,
(char *)(key + key_field->offset));
@@ -5137,6 +5220,8 @@ static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)
seq_printf(m, ".%s", flags);
}
}
+ if (hist_field->buckets)
+ seq_printf(m, "=%ld", hist_field->buckets);
}
static int event_hist_trigger_print(struct seq_file *m,
diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
index 9315fc03e303..d54094b7a9d7 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -1298,7 +1298,7 @@ static int __create_synth_event(const char *name, const char *raw_fields)
}
ret = register_synth_event(event);
if (!ret)
- dyn_event_add(&event->devent);
+ dyn_event_add(&event->devent, &event->call);
else
free_synth_event(event);
out:
@@ -1369,13 +1369,15 @@ static int destroy_synth_event(struct synth_event *se)
int ret;
if (se->ref)
- ret = -EBUSY;
- else {
- ret = unregister_synth_event(se);
- if (!ret) {
- dyn_event_remove(&se->devent);
- free_synth_event(se);
- }
+ return -EBUSY;
+
+ if (trace_event_dyn_busy(&se->call))
+ return -EBUSY;
+
+ ret = unregister_synth_event(se);
+ if (!ret) {
+ dyn_event_remove(&se->devent);
+ free_synth_event(se);
}
return ret;
@@ -2102,6 +2104,9 @@ static int synth_event_release(struct dyn_event *ev)
if (event->ref)
return -EBUSY;
+ if (trace_event_dyn_busy(&event->call))
+ return -EBUSY;
+
ret = unregister_synth_event(event);
if (ret)
return ret;
diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c
index cf84d0f6583a..3d5c07239a2a 100644
--- a/kernel/trace/trace_events_trigger.c
+++ b/kernel/trace/trace_events_trigger.c
@@ -124,6 +124,18 @@ static void *trigger_next(struct seq_file *m, void *t, loff_t *pos)
return seq_list_next(t, &event_file->triggers, pos);
}
+static bool check_user_trigger(struct trace_event_file *file)
+{
+ struct event_trigger_data *data;
+
+ list_for_each_entry_rcu(data, &file->triggers, list) {
+ if (data->flags & EVENT_TRIGGER_FL_PROBE)
+ continue;
+ return true;
+ }
+ return false;
+}
+
static void *trigger_start(struct seq_file *m, loff_t *pos)
{
struct trace_event_file *event_file;
@@ -134,7 +146,7 @@ static void *trigger_start(struct seq_file *m, loff_t *pos)
if (unlikely(!event_file))
return ERR_PTR(-ENODEV);
- if (list_empty(&event_file->triggers))
+ if (list_empty(&event_file->triggers) || !check_user_trigger(event_file))
return *pos == 0 ? SHOW_AVAILABLE_TRIGGERS : NULL;
return seq_list_start(&event_file->triggers, *pos);
@@ -1334,7 +1346,7 @@ void event_enable_trigger_free(struct event_trigger_ops *ops,
if (!data->ref) {
/* Remove the SOFT_MODE flag */
trace_event_enable_disable(enable_data->file, 0, 1);
- module_put(enable_data->file->event_call->mod);
+ trace_event_put_ref(enable_data->file->event_call);
trigger_data_free(data);
kfree(enable_data);
}
@@ -1481,7 +1493,7 @@ int event_enable_trigger_func(struct event_command *cmd_ops,
out_reg:
/* Don't let event modules unload while probe registered */
- ret = try_module_get(event_enable_file->event_call->mod);
+ ret = trace_event_try_get_ref(event_enable_file->event_call);
if (!ret) {
ret = -EBUSY;
goto out_free;
@@ -1510,7 +1522,7 @@ int event_enable_trigger_func(struct event_command *cmd_ops,
out_disable:
trace_event_enable_disable(event_enable_file, 0, 1);
out_put:
- module_put(event_enable_file->event_call->mod);
+ trace_event_put_ref(event_enable_file->event_call);
out_free:
if (cmd_ops->set_filter)
cmd_ops->set_filter(NULL, trigger_data, NULL);
diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c
index 14f46aae1981..1b83d75eb103 100644
--- a/kernel/trace/trace_hwlat.c
+++ b/kernel/trace/trace_hwlat.c
@@ -325,10 +325,10 @@ static void move_to_next_cpu(void)
if (!cpumask_equal(current_mask, current->cpus_ptr))
goto change_mode;
- get_online_cpus();
+ cpus_read_lock();
cpumask_and(current_mask, cpu_online_mask, tr->tracing_cpumask);
next_cpu = cpumask_next(raw_smp_processor_id(), current_mask);
- put_online_cpus();
+ cpus_read_unlock();
if (next_cpu >= nr_cpu_ids)
next_cpu = cpumask_first(current_mask);
@@ -398,7 +398,7 @@ static void stop_single_kthread(void)
struct hwlat_kthread_data *kdata = get_cpu_data();
struct task_struct *kthread;
- get_online_cpus();
+ cpus_read_lock();
kthread = kdata->kthread;
if (!kthread)
@@ -408,7 +408,7 @@ static void stop_single_kthread(void)
kdata->kthread = NULL;
out_put_cpus:
- put_online_cpus();
+ cpus_read_unlock();
}
@@ -425,14 +425,14 @@ static int start_single_kthread(struct trace_array *tr)
struct task_struct *kthread;
int next_cpu;
- get_online_cpus();
+ cpus_read_lock();
if (kdata->kthread)
goto out_put_cpus;
kthread = kthread_create(kthread_fn, NULL, "hwlatd");
if (IS_ERR(kthread)) {
pr_err(BANNER "could not start sampling thread\n");
- put_online_cpus();
+ cpus_read_unlock();
return -ENOMEM;
}
@@ -452,7 +452,7 @@ static int start_single_kthread(struct trace_array *tr)
wake_up_process(kthread);
out_put_cpus:
- put_online_cpus();
+ cpus_read_unlock();
return 0;
}
@@ -479,10 +479,10 @@ static void stop_per_cpu_kthreads(void)
{
unsigned int cpu;
- get_online_cpus();
+ cpus_read_lock();
for_each_online_cpu(cpu)
stop_cpu_kthread(cpu);
- put_online_cpus();
+ cpus_read_unlock();
}
/*
@@ -515,7 +515,7 @@ static void hwlat_hotplug_workfn(struct work_struct *dummy)
mutex_lock(&trace_types_lock);
mutex_lock(&hwlat_data.lock);
- get_online_cpus();
+ cpus_read_lock();
if (!hwlat_busy || hwlat_data.thread_mode != MODE_PER_CPU)
goto out_unlock;
@@ -526,7 +526,7 @@ static void hwlat_hotplug_workfn(struct work_struct *dummy)
start_cpu_kthread(cpu);
out_unlock:
- put_online_cpus();
+ cpus_read_unlock();
mutex_unlock(&hwlat_data.lock);
mutex_unlock(&trace_types_lock);
}
@@ -582,7 +582,7 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
unsigned int cpu;
int retval;
- get_online_cpus();
+ cpus_read_lock();
/*
* Run only on CPUs in which hwlat is allowed to run.
*/
@@ -596,12 +596,12 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
if (retval)
goto out_error;
}
- put_online_cpus();
+ cpus_read_unlock();
return 0;
out_error:
- put_online_cpus();
+ cpus_read_unlock();
stop_per_cpu_kthreads();
return retval;
}
diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c
index 9da76104f7a2..59857a1ee44c 100644
--- a/kernel/trace/trace_kdb.c
+++ b/kernel/trace/trace_kdb.c
@@ -147,11 +147,17 @@ static int kdb_ftdump(int argc, const char **argv)
return 0;
}
+static kdbtab_t ftdump_cmd = {
+ .name = "ftdump",
+ .func = kdb_ftdump,
+ .usage = "[skip_#entries] [cpu]",
+ .help = "Dump ftrace log; -skip dumps last #entries",
+ .flags = KDB_ENABLE_ALWAYS_SAFE,
+};
+
static __init int kdb_ftrace_register(void)
{
- kdb_register_flags("ftdump", kdb_ftdump, "[skip_#entries] [cpu]",
- "Dump ftrace log; -skip dumps last #entries", 0,
- KDB_ENABLE_ALWAYS_SAFE);
+ kdb_register(&ftdump_cmd);
return 0;
}
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index ea6178cb5e33..3a64ba4bbad6 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -80,10 +80,6 @@ static struct trace_kprobe *to_trace_kprobe(struct dyn_event *ev)
for_each_dyn_event(dpos) \
if (is_trace_kprobe(dpos) && (pos = to_trace_kprobe(dpos)))
-#define SIZEOF_TRACE_KPROBE(n) \
- (offsetof(struct trace_kprobe, tp.args) + \
- (sizeof(struct probe_arg) * (n)))
-
static nokprobe_inline bool trace_kprobe_is_return(struct trace_kprobe *tk)
{
return tk->rp.handler != NULL;
@@ -265,7 +261,7 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
struct trace_kprobe *tk;
int ret = -ENOMEM;
- tk = kzalloc(SIZEOF_TRACE_KPROBE(nargs), GFP_KERNEL);
+ tk = kzalloc(struct_size(tk, tp.args, nargs), GFP_KERNEL);
if (!tk)
return ERR_PTR(ret);
@@ -543,6 +539,10 @@ static int unregister_trace_kprobe(struct trace_kprobe *tk)
if (trace_probe_is_enabled(&tk->tp))
return -EBUSY;
+ /* If there's a reference to the dynamic event */
+ if (trace_event_dyn_busy(trace_probe_event_call(&tk->tp)))
+ return -EBUSY;
+
/* Will fail if probe is being used by ftrace or perf */
if (unregister_kprobe_event(tk))
return -EBUSY;
@@ -618,7 +618,7 @@ static int append_trace_kprobe(struct trace_kprobe *tk, struct trace_kprobe *to)
if (ret)
trace_probe_unlink(&tk->tp);
else
- dyn_event_add(&tk->devent);
+ dyn_event_add(&tk->devent, trace_probe_event_call(&tk->tp));
return ret;
}
@@ -647,7 +647,11 @@ static int register_trace_kprobe(struct trace_kprobe *tk)
/* Register new event */
ret = register_kprobe_event(tk);
if (ret) {
- pr_warn("Failed to register probe event(%d)\n", ret);
+ if (ret == -EEXIST) {
+ trace_probe_log_set_index(0);
+ trace_probe_log_err(0, EVENT_EXIST);
+ } else
+ pr_warn("Failed to register probe event(%d)\n", ret);
goto end;
}
@@ -661,7 +665,7 @@ static int register_trace_kprobe(struct trace_kprobe *tk)
if (ret < 0)
unregister_kprobe_event(tk);
else
- dyn_event_add(&tk->devent);
+ dyn_event_add(&tk->devent, trace_probe_event_call(&tk->tp));
end:
mutex_unlock(&event_mutex);
@@ -703,14 +707,6 @@ static struct notifier_block trace_kprobe_module_nb = {
.priority = 1 /* Invoked after kprobe module callback */
};
-/* Convert certain expected symbols into '_' when generating event names */
-static inline void sanitize_event_name(char *name)
-{
- while (*name++ != '\0')
- if (*name == ':' || *name == '.')
- *name = '_';
-}
-
static int __trace_kprobe_create(int argc, const char *argv[])
{
/*
@@ -742,6 +738,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
bool is_return = false;
char *symbol = NULL, *tmp = NULL;
const char *event = NULL, *group = KPROBE_EVENT_SYSTEM;
+ enum probe_print_type ptype;
int maxactive = 0;
long offset = 0;
void *addr = NULL;
@@ -869,20 +866,14 @@ static int __trace_kprobe_create(int argc, const char *argv[])
/* parse arguments */
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
- tmp = kstrdup(argv[i], GFP_KERNEL);
- if (!tmp) {
- ret = -ENOMEM;
- goto error;
- }
-
trace_probe_log_set_index(i + 2);
- ret = traceprobe_parse_probe_arg(&tk->tp, i, tmp, flags);
- kfree(tmp);
+ ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], flags);
if (ret)
goto error; /* This can be -ENOMEM */
}
- ret = traceprobe_set_print_fmt(&tk->tp, is_return);
+ ptype = is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
+ ret = traceprobe_set_print_fmt(&tk->tp, ptype);
if (ret < 0)
goto error;
@@ -1330,9 +1321,10 @@ probe_mem_read(void *dest, void *src, size_t size)
/* Note that we don't verify it, since the code does not come from user space */
static int
-process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
+process_fetch_insn(struct fetch_insn *code, void *rec, void *dest,
void *base)
{
+ struct pt_regs *regs = rec;
unsigned long val;
retry:
@@ -1806,6 +1798,7 @@ struct trace_event_call *
create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
bool is_return)
{
+ enum probe_print_type ptype;
struct trace_kprobe *tk;
int ret;
char *event;
@@ -1829,7 +1822,9 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
init_trace_event_call(tk);
- if (traceprobe_set_print_fmt(&tk->tp, trace_kprobe_is_return(tk)) < 0) {
+ ptype = trace_kprobe_is_return(tk) ?
+ PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
+ if (traceprobe_set_print_fmt(&tk->tp, ptype) < 0) {
ret = -ENOMEM;
goto error;
}
diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
index b61eefe5ccf5..65b08b8e5bf8 100644
--- a/kernel/trace/trace_osnoise.c
+++ b/kernel/trace/trace_osnoise.c
@@ -1498,12 +1498,12 @@ static void stop_per_cpu_kthreads(void)
{
int cpu;
- get_online_cpus();
+ cpus_read_lock();
for_each_online_cpu(cpu)
stop_kthread(cpu);
- put_online_cpus();
+ cpus_read_unlock();
}
/*
@@ -1551,7 +1551,7 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
int retval;
int cpu;
- get_online_cpus();
+ cpus_read_lock();
/*
* Run only on CPUs in which trace and osnoise are allowed to run.
*/
@@ -1572,7 +1572,7 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
}
}
- put_online_cpus();
+ cpus_read_unlock();
return 0;
}
@@ -1590,7 +1590,7 @@ static void osnoise_hotplug_workfn(struct work_struct *dummy)
goto out_unlock_trace;
mutex_lock(&interface_lock);
- get_online_cpus();
+ cpus_read_lock();
if (!cpumask_test_cpu(cpu, &osnoise_cpumask))
goto out_unlock;
@@ -1601,7 +1601,7 @@ static void osnoise_hotplug_workfn(struct work_struct *dummy)
start_kthread(cpu);
out_unlock:
- put_online_cpus();
+ cpus_read_unlock();
mutex_unlock(&interface_lock);
out_unlock_trace:
mutex_unlock(&trace_types_lock);
@@ -1743,11 +1743,11 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,
/*
* osnoise_cpumask is read by CPU hotplug operations.
*/
- get_online_cpus();
+ cpus_read_lock();
cpumask_copy(&osnoise_cpumask, osnoise_cpumask_new);
- put_online_cpus();
+ cpus_read_unlock();
mutex_unlock(&interface_lock);
if (running)
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 15413ad7cef2..3ed2a3f37297 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -233,6 +233,9 @@ int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
int len;
slash = strchr(event, '/');
+ if (!slash)
+ slash = strchr(event, '.');
+
if (slash) {
if (slash == event) {
trace_probe_log_err(offset, NO_GROUP_NAME);
@@ -316,6 +319,13 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
code->op = FETCH_OP_ARG;
code->param = (unsigned int)param - 1;
#endif
+ } else if (flags & TPARG_FL_TPOINT) {
+ if (code->data)
+ return -EFAULT;
+ code->data = kstrdup(arg, GFP_KERNEL);
+ if (!code->data)
+ return -ENOMEM;
+ code->op = FETCH_OP_TP_ARG;
} else
goto inval_var;
@@ -540,26 +550,34 @@ static int __parse_bitfield_probe_arg(const char *bf,
}
/* String length checking wrapper */
-static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
+static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
struct probe_arg *parg, unsigned int flags, int offset)
{
struct fetch_insn *code, *scode, *tmp = NULL;
char *t, *t2, *t3;
+ char *arg;
int ret, len;
+ arg = kstrdup(argv, GFP_KERNEL);
+ if (!arg)
+ return -ENOMEM;
+
+ ret = -EINVAL;
len = strlen(arg);
if (len > MAX_ARGSTR_LEN) {
trace_probe_log_err(offset, ARG_TOO_LONG);
- return -EINVAL;
+ goto out;
} else if (len == 0) {
trace_probe_log_err(offset, NO_ARG_BODY);
- return -EINVAL;
+ goto out;
}
+ ret = -ENOMEM;
parg->comm = kstrdup(arg, GFP_KERNEL);
if (!parg->comm)
- return -ENOMEM;
+ goto out;
+ ret = -EINVAL;
t = strchr(arg, ':');
if (t) {
*t = '\0';
@@ -571,22 +589,22 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
offset += t2 + strlen(t2) - arg;
trace_probe_log_err(offset,
ARRAY_NO_CLOSE);
- return -EINVAL;
+ goto out;
} else if (t3[1] != '\0') {
trace_probe_log_err(offset + t3 + 1 - arg,
BAD_ARRAY_SUFFIX);
- return -EINVAL;
+ goto out;
}
*t3 = '\0';
if (kstrtouint(t2, 0, &parg->count) || !parg->count) {
trace_probe_log_err(offset + t2 - arg,
BAD_ARRAY_NUM);
- return -EINVAL;
+ goto out;
}
if (parg->count > MAX_ARRAY_LEN) {
trace_probe_log_err(offset + t2 - arg,
ARRAY_TOO_BIG);
- return -EINVAL;
+ goto out;
}
}
}
@@ -598,29 +616,30 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
if (strcmp(arg, "$comm") == 0 || strncmp(arg, "\\\"", 2) == 0) {
/* The type of $comm must be "string", and not an array. */
if (parg->count || (t && strcmp(t, "string")))
- return -EINVAL;
+ goto out;
parg->type = find_fetch_type("string");
} else
parg->type = find_fetch_type(t);
if (!parg->type) {
trace_probe_log_err(offset + (t ? (t - arg) : 0), BAD_TYPE);
- return -EINVAL;
+ goto out;
}
parg->offset = *size;
*size += parg->type->size * (parg->count ?: 1);
+ ret = -ENOMEM;
if (parg->count) {
len = strlen(parg->type->fmttype) + 6;
parg->fmt = kmalloc(len, GFP_KERNEL);
if (!parg->fmt)
- return -ENOMEM;
+ goto out;
snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype,
parg->count);
}
code = tmp = kcalloc(FETCH_INSN_MAX, sizeof(*code), GFP_KERNEL);
if (!code)
- return -ENOMEM;
+ goto out;
code[FETCH_INSN_MAX - 1].op = FETCH_OP_END;
ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1],
@@ -628,19 +647,20 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
if (ret)
goto fail;
+ ret = -EINVAL;
/* Store operation */
if (!strcmp(parg->type->name, "string") ||
!strcmp(parg->type->name, "ustring")) {
if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF &&
code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM &&
- code->op != FETCH_OP_DATA) {
+ code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) {
trace_probe_log_err(offset + (t ? (t - arg) : 0),
BAD_STRING);
- ret = -EINVAL;
goto fail;
}
if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM ||
- code->op == FETCH_OP_DATA) || parg->count) {
+ code->op == FETCH_OP_DATA) || code->op == FETCH_OP_TP_ARG ||
+ parg->count) {
/*
* IMM, DATA and COMM is pointing actual address, those
* must be kept, and if parg->count != 0, this is an
@@ -650,7 +670,6 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
code++;
if (code->op != FETCH_OP_NOP) {
trace_probe_log_err(offset, TOO_MANY_OPS);
- ret = -EINVAL;
goto fail;
}
}
@@ -672,7 +691,6 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
code++;
if (code->op != FETCH_OP_NOP) {
trace_probe_log_err(offset, TOO_MANY_OPS);
- ret = -EINVAL;
goto fail;
}
code->op = FETCH_OP_ST_RAW;
@@ -687,6 +705,7 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
goto fail;
}
}
+ ret = -EINVAL;
/* Loop(Array) operation */
if (parg->count) {
if (scode->op != FETCH_OP_ST_MEM &&
@@ -694,13 +713,11 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
scode->op != FETCH_OP_ST_USTRING) {
trace_probe_log_err(offset + (t ? (t - arg) : 0),
BAD_STRING);
- ret = -EINVAL;
goto fail;
}
code++;
if (code->op != FETCH_OP_NOP) {
trace_probe_log_err(offset, TOO_MANY_OPS);
- ret = -EINVAL;
goto fail;
}
code->op = FETCH_OP_LP_ARRAY;
@@ -709,6 +726,7 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
code++;
code->op = FETCH_OP_END;
+ ret = 0;
/* Shrink down the code buffer */
parg->code = kcalloc(code - tmp + 1, sizeof(*code), GFP_KERNEL);
if (!parg->code)
@@ -724,6 +742,8 @@ fail:
kfree(code->data);
}
kfree(tmp);
+out:
+ kfree(arg);
return ret;
}
@@ -745,11 +765,11 @@ static int traceprobe_conflict_field_name(const char *name,
return 0;
}
-int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, char *arg,
+int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, const char *arg,
unsigned int flags)
{
struct probe_arg *parg = &tp->args[i];
- char *body;
+ const char *body;
/* Increment count for freeing args in error case */
tp->nr_args++;
@@ -839,19 +859,29 @@ int traceprobe_update_arg(struct probe_arg *arg)
/* When len=0, we just calculate the needed length */
#define LEN_OR_ZERO (len ? len - pos : 0)
static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
- bool is_return)
+ enum probe_print_type ptype)
{
struct probe_arg *parg;
int i, j;
int pos = 0;
const char *fmt, *arg;
- if (!is_return) {
+ switch (ptype) {
+ case PROBE_PRINT_NORMAL:
fmt = "(%lx)";
arg = "REC->" FIELD_STRING_IP;
- } else {
+ break;
+ case PROBE_PRINT_RETURN:
fmt = "(%lx <- %lx)";
arg = "REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP;
+ break;
+ case PROBE_PRINT_EVENT:
+ fmt = "(%u)";
+ arg = "REC->" FIELD_STRING_TYPE;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return 0;
}
pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
@@ -900,20 +930,20 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
}
#undef LEN_OR_ZERO
-int traceprobe_set_print_fmt(struct trace_probe *tp, bool is_return)
+int traceprobe_set_print_fmt(struct trace_probe *tp, enum probe_print_type ptype)
{
struct trace_event_call *call = trace_probe_event_call(tp);
int len;
char *print_fmt;
/* First: called with 0 length to calculate the needed length */
- len = __set_print_fmt(tp, NULL, 0, is_return);
+ len = __set_print_fmt(tp, NULL, 0, ptype);
print_fmt = kmalloc(len + 1, GFP_KERNEL);
if (!print_fmt)
return -ENOMEM;
/* Second: actually write the @print_fmt */
- __set_print_fmt(tp, print_fmt, len + 1, is_return);
+ __set_print_fmt(tp, print_fmt, len + 1, ptype);
call->print_fmt = print_fmt;
return 0;
@@ -1029,11 +1059,36 @@ error:
return ret;
}
+static struct trace_event_call *
+find_trace_event_call(const char *system, const char *event_name)
+{
+ struct trace_event_call *tp_event;
+ const char *name;
+
+ list_for_each_entry(tp_event, &ftrace_events, list) {
+ if (!tp_event->class->system ||
+ strcmp(system, tp_event->class->system))
+ continue;
+ name = trace_event_name(tp_event);
+ if (!name || strcmp(event_name, name))
+ continue;
+ return tp_event;
+ }
+
+ return NULL;
+}
+
int trace_probe_register_event_call(struct trace_probe *tp)
{
struct trace_event_call *call = trace_probe_event_call(tp);
int ret;
+ lockdep_assert_held(&event_mutex);
+
+ if (find_trace_event_call(trace_probe_group_name(tp),
+ trace_probe_name(tp)))
+ return -EEXIST;
+
ret = register_trace_event(&call->event);
if (!ret)
return -ENODEV;
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 227d518e5ba5..99e7a5df025e 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -38,6 +38,7 @@
#define FIELD_STRING_IP "__probe_ip"
#define FIELD_STRING_RETIP "__probe_ret_ip"
#define FIELD_STRING_FUNC "__probe_func"
+#define FIELD_STRING_TYPE "__probe_type"
#undef DEFINE_FIELD
#define DEFINE_FIELD(type, item, name, is_signed) \
@@ -102,6 +103,7 @@ enum fetch_op {
FETCH_OP_MOD_BF, /* Bitfield: .basesize, .lshift, .rshift */
// Stage 5 (loop) op
FETCH_OP_LP_ARRAY, /* Array: .param = loop count */
+ FETCH_OP_TP_ARG, /* Trace Point argument */
FETCH_OP_END,
FETCH_NOP_SYMBOL, /* Unresolved Symbol holder */
};
@@ -351,10 +353,11 @@ int trace_probe_create(const char *raw_command, int (*createfn)(int, const char
#define TPARG_FL_RETURN BIT(0)
#define TPARG_FL_KERNEL BIT(1)
#define TPARG_FL_FENTRY BIT(2)
-#define TPARG_FL_MASK GENMASK(2, 0)
+#define TPARG_FL_TPOINT BIT(3)
+#define TPARG_FL_MASK GENMASK(3, 0)
extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i,
- char *arg, unsigned int flags);
+ const char *argv, unsigned int flags);
extern int traceprobe_update_arg(struct probe_arg *arg);
extern void traceprobe_free_probe_arg(struct probe_arg *arg);
@@ -363,7 +366,13 @@ extern int traceprobe_split_symbol_offset(char *symbol, long *offset);
int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
char *buf, int offset);
-extern int traceprobe_set_print_fmt(struct trace_probe *tp, bool is_return);
+enum probe_print_type {
+ PROBE_PRINT_NORMAL,
+ PROBE_PRINT_RETURN,
+ PROBE_PRINT_EVENT,
+};
+
+extern int traceprobe_set_print_fmt(struct trace_probe *tp, enum probe_print_type ptype);
#ifdef CONFIG_PERF_EVENTS
extern struct trace_event_call *
@@ -399,6 +408,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
C(NO_EVENT_NAME, "Event name is not specified"), \
C(EVENT_TOO_LONG, "Event name is too long"), \
C(BAD_EVENT_NAME, "Event name must follow the same rules as C identifiers"), \
+ C(EVENT_EXIST, "Given group/event name is already used by another event"), \
C(RETVAL_ON_PROBE, "$retval is not available on probe"), \
C(BAD_STACK_NUM, "Invalid stack number"), \
C(BAD_ARG_NUM, "Invalid argument number"), \
diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h
index f003c5d02a3a..b3bdb8ddb862 100644
--- a/kernel/trace/trace_probe_tmpl.h
+++ b/kernel/trace/trace_probe_tmpl.h
@@ -54,7 +54,7 @@ fetch_apply_bitfield(struct fetch_insn *code, void *buf)
* If dest is NULL, don't store result and return required dynamic data size.
*/
static int
-process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs,
+process_fetch_insn(struct fetch_insn *code, void *rec,
void *dest, void *base);
static nokprobe_inline int fetch_store_strlen(unsigned long addr);
static nokprobe_inline int
@@ -188,7 +188,7 @@ __get_data_size(struct trace_probe *tp, struct pt_regs *regs)
/* Store the value of each argument */
static nokprobe_inline void
-store_trace_args(void *data, struct trace_probe *tp, struct pt_regs *regs,
+store_trace_args(void *data, struct trace_probe *tp, void *rec,
int header_size, int maxlen)
{
struct probe_arg *arg;
@@ -203,7 +203,7 @@ store_trace_args(void *data, struct trace_probe *tp, struct pt_regs *regs,
/* Point the dynamic data area if needed */
if (unlikely(arg->dynamic))
*dl = make_data_loc(maxlen, dyndata - base);
- ret = process_fetch_insn(arg->code, regs, dl, base);
+ ret = process_fetch_insn(arg->code, rec, dl, base);
if (unlikely(ret < 0 && arg->dynamic)) {
*dl = make_data_loc(0, dyndata - base);
} else {
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 9b50869a5ddb..225ce569bf8f 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -83,10 +83,6 @@ static struct trace_uprobe *to_trace_uprobe(struct dyn_event *ev)
for_each_dyn_event(dpos) \
if (is_trace_uprobe(dpos) && (pos = to_trace_uprobe(dpos)))
-#define SIZEOF_TRACE_UPROBE(n) \
- (offsetof(struct trace_uprobe, tp.args) + \
- (sizeof(struct probe_arg) * (n)))
-
static int register_uprobe_event(struct trace_uprobe *tu);
static int unregister_uprobe_event(struct trace_uprobe *tu);
@@ -217,9 +213,10 @@ static unsigned long translate_user_vaddr(unsigned long file_offset)
/* Note that we don't verify it, since the code does not come from user space */
static int
-process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
+process_fetch_insn(struct fetch_insn *code, void *rec, void *dest,
void *base)
{
+ struct pt_regs *regs = rec;
unsigned long val;
/* 1st stage: get value from context */
@@ -340,7 +337,7 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
struct trace_uprobe *tu;
int ret;
- tu = kzalloc(SIZEOF_TRACE_UPROBE(nargs), GFP_KERNEL);
+ tu = kzalloc(struct_size(tu, tp.args, nargs), GFP_KERNEL);
if (!tu)
return ERR_PTR(-ENOMEM);
@@ -393,6 +390,10 @@ static int unregister_trace_uprobe(struct trace_uprobe *tu)
if (trace_probe_has_sibling(&tu->tp))
goto unreg;
+ /* If there's a reference to the dynamic event */
+ if (trace_event_dyn_busy(trace_probe_event_call(&tu->tp)))
+ return -EBUSY;
+
ret = unregister_uprobe_event(tu);
if (ret)
return ret;
@@ -455,7 +456,7 @@ static int append_trace_uprobe(struct trace_uprobe *tu, struct trace_uprobe *to)
/* Append to existing event */
ret = trace_probe_append(&tu->tp, &to->tp);
if (!ret)
- dyn_event_add(&tu->devent);
+ dyn_event_add(&tu->devent, trace_probe_event_call(&tu->tp));
return ret;
}
@@ -514,11 +515,15 @@ static int register_trace_uprobe(struct trace_uprobe *tu)
ret = register_uprobe_event(tu);
if (ret) {
- pr_warn("Failed to register probe event(%d)\n", ret);
+ if (ret == -EEXIST) {
+ trace_probe_log_set_index(0);
+ trace_probe_log_err(0, EVENT_EXIST);
+ } else
+ pr_warn("Failed to register probe event(%d)\n", ret);
goto end;
}
- dyn_event_add(&tu->devent);
+ dyn_event_add(&tu->devent, trace_probe_event_call(&tu->tp));
end:
mutex_unlock(&event_mutex);
@@ -536,6 +541,7 @@ static int __trace_uprobe_create(int argc, const char **argv)
const char *event = NULL, *group = UPROBE_EVENT_SYSTEM;
char *arg, *filename, *rctr, *rctr_end, *tmp;
char buf[MAX_EVENT_NAME_LEN];
+ enum probe_print_type ptype;
struct path path;
unsigned long offset, ref_ctr_offset;
bool is_return = false;
@@ -680,21 +686,15 @@ static int __trace_uprobe_create(int argc, const char **argv)
/* parse arguments */
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
- tmp = kstrdup(argv[i], GFP_KERNEL);
- if (!tmp) {
- ret = -ENOMEM;
- goto error;
- }
-
trace_probe_log_set_index(i + 2);
- ret = traceprobe_parse_probe_arg(&tu->tp, i, tmp,
+ ret = traceprobe_parse_probe_arg(&tu->tp, i, argv[i],
is_return ? TPARG_FL_RETURN : 0);
- kfree(tmp);
if (ret)
goto error;
}
- ret = traceprobe_set_print_fmt(&tu->tp, is_ret_probe(tu));
+ ptype = is_ret_probe(tu) ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
+ ret = traceprobe_set_print_fmt(&tu->tp, ptype);
if (ret < 0)
goto error;
@@ -1585,6 +1585,7 @@ struct trace_event_call *
create_local_trace_uprobe(char *name, unsigned long offs,
unsigned long ref_ctr_offset, bool is_return)
{
+ enum probe_print_type ptype;
struct trace_uprobe *tu;
struct path path;
int ret;
@@ -1619,7 +1620,8 @@ create_local_trace_uprobe(char *name, unsigned long offs,
tu->filename = kstrdup(name, GFP_KERNEL);
init_trace_event_call(tu);
- if (traceprobe_set_print_fmt(&tu->tp, is_ret_probe(tu)) < 0) {
+ ptype = is_ret_probe(tu) ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
+ if (traceprobe_set_print_fmt(&tu->tp, ptype) < 0) {
ret = -ENOMEM;
goto error;
}
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index efd14c79fab4..64ea283f2f86 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -577,7 +577,7 @@ bool trace_module_has_bad_taint(struct module *mod)
static BLOCKING_NOTIFIER_HEAD(tracepoint_notify_list);
/**
- * register_tracepoint_notifier - register tracepoint coming/going notifier
+ * register_tracepoint_module_notifier - register tracepoint coming/going notifier
* @nb: notifier block
*
* Notifiers registered with this function are called on module
@@ -603,7 +603,7 @@ end:
EXPORT_SYMBOL_GPL(register_tracepoint_module_notifier);
/**
- * unregister_tracepoint_notifier - unregister tracepoint coming/going notifier
+ * unregister_tracepoint_module_notifier - unregister tracepoint coming/going notifier
* @nb: notifier block
*
* The notifier block callback should expect a "struct tp_module" data
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index ef82d401dde8..6b2e3ca7ee99 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -1385,7 +1385,7 @@ const struct proc_ns_operations userns_operations = {
static __init int user_namespaces_init(void)
{
- user_ns_cachep = KMEM_CACHE(user_namespace, SLAB_PANIC);
+ user_ns_cachep = KMEM_CACHE(user_namespace, SLAB_PANIC | SLAB_ACCOUNT);
return 0;
}
subsys_initcall(user_namespaces_init);
diff --git a/lib/Kconfig b/lib/Kconfig
index 5c9c0687f76d..5e7165e6a346 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -50,12 +50,18 @@ config HAVE_ARCH_BITREVERSE
This option enables the use of hardware bit-reversal instructions on
architectures which support such operations.
-config GENERIC_STRNCPY_FROM_USER
+config ARCH_HAS_STRNCPY_FROM_USER
bool
-config GENERIC_STRNLEN_USER
+config ARCH_HAS_STRNLEN_USER
bool
+config GENERIC_STRNCPY_FROM_USER
+ def_bool !ARCH_HAS_STRNCPY_FROM_USER
+
+config GENERIC_STRNLEN_USER
+ def_bool !ARCH_HAS_STRNLEN_USER
+
config GENERIC_NET_UTILS
bool
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 12b805dabbc9..0f61b1ec385d 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -346,7 +346,7 @@ config FRAME_WARN
int "Warn for stack frames larger than"
range 0 8192
default 2048 if GCC_PLUGIN_LATENT_ENTROPY
- default 1280 if (!64BIT && PARISC)
+ default 1536 if (!64BIT && PARISC)
default 1024 if (!64BIT && !PARISC)
default 2048 if 64BIT
help
@@ -365,6 +365,7 @@ config STRIP_ASM_SYMS
config READABLE_ASM
bool "Generate readable assembler code"
depends on DEBUG_KERNEL
+ depends on CC_IS_GCC
help
Disable some compiler optimizations that tend to generate human unreadable
assembler output. This may make the kernel slightly slower, but it helps
@@ -383,6 +384,7 @@ config HEADERS_INSTALL
config DEBUG_SECTION_MISMATCH
bool "Enable full Section mismatch analysis"
+ depends on CC_IS_GCC
help
The section mismatch analysis checks if there are illegal
references from one section to another section.
diff --git a/lib/Kconfig.kcsan b/lib/Kconfig.kcsan
index 0440f373248e..e0a93ffdef30 100644
--- a/lib/Kconfig.kcsan
+++ b/lib/Kconfig.kcsan
@@ -40,10 +40,14 @@ menuconfig KCSAN
if KCSAN
-# Compiler capabilities that should not fail the test if they are unavailable.
config CC_HAS_TSAN_COMPOUND_READ_BEFORE_WRITE
def_bool (CC_IS_CLANG && $(cc-option,-fsanitize=thread -mllvm -tsan-compound-read-before-write=1)) || \
(CC_IS_GCC && $(cc-option,-fsanitize=thread --param tsan-compound-read-before-write=1))
+ help
+ The compiler instruments plain compound read-write operations
+ differently (++, --, +=, -=, |=, &=, etc.), which allows KCSAN to
+ distinguish them from other plain accesses. This is currently
+ supported by Clang 12 or later.
config KCSAN_VERBOSE
bool "Show verbose reports with more information about system state"
@@ -58,9 +62,6 @@ config KCSAN_VERBOSE
generated from any one of them, system stability may suffer due to
deadlocks or recursion. If in doubt, say N.
-config KCSAN_DEBUG
- bool "Debugging of KCSAN internals"
-
config KCSAN_SELFTEST
bool "Perform short selftests on boot"
default y
@@ -149,7 +150,8 @@ config KCSAN_SKIP_WATCH_RANDOMIZE
KCSAN_WATCH_SKIP.
config KCSAN_INTERRUPT_WATCHER
- bool "Interruptible watchers"
+ bool "Interruptible watchers" if !KCSAN_STRICT
+ default KCSAN_STRICT
help
If enabled, a task that set up a watchpoint may be interrupted while
delayed. This option will allow KCSAN to detect races between
@@ -169,13 +171,9 @@ config KCSAN_REPORT_ONCE_IN_MS
reporting to avoid flooding the console with reports. Setting this
to 0 disables rate limiting.
-# The main purpose of the below options is to control reported data races (e.g.
-# in fuzzer configs), and are not expected to be switched frequently by other
-# users. We could turn some of them into boot parameters, but given they should
-# not be switched normally, let's keep them here to simplify configuration.
-#
-# The defaults below are chosen to be very conservative, and may miss certain
-# bugs.
+# The main purpose of the below options is to control reported data races, and
+# are not expected to be switched frequently by non-testers or at runtime.
+# The defaults are chosen to be conservative, and can miss certain bugs.
config KCSAN_REPORT_RACE_UNKNOWN_ORIGIN
bool "Report races of unknown origin"
@@ -186,9 +184,17 @@ config KCSAN_REPORT_RACE_UNKNOWN_ORIGIN
reported if it was only possible to infer a race due to a data value
change while an access is being delayed on a watchpoint.
+config KCSAN_STRICT
+ bool "Strict data-race checking"
+ help
+ KCSAN will report data races with the strictest possible rules, which
+ closely aligns with the rules defined by the Linux-kernel memory
+ consistency model (LKMM).
+
config KCSAN_REPORT_VALUE_CHANGE_ONLY
bool "Only report races where watcher observed a data value change"
default y
+ depends on !KCSAN_STRICT
help
If enabled and a conflicting write is observed via a watchpoint, but
the data value of the memory location was observed to remain
@@ -197,6 +203,7 @@ config KCSAN_REPORT_VALUE_CHANGE_ONLY
config KCSAN_ASSUME_PLAIN_WRITES_ATOMIC
bool "Assume that plain aligned writes up to word size are atomic"
default y
+ depends on !KCSAN_STRICT
help
Assume that plain aligned writes up to word size are atomic by
default, and also not subject to other unsafe compiler optimizations
@@ -209,6 +216,7 @@ config KCSAN_ASSUME_PLAIN_WRITES_ATOMIC
config KCSAN_IGNORE_ATOMICS
bool "Do not instrument marked atomic accesses"
+ depends on !KCSAN_STRICT
help
Never instrument marked atomic accesses. This option can be used for
additional filtering. Conflicting marked atomic reads and plain
@@ -224,4 +232,14 @@ config KCSAN_IGNORE_ATOMICS
due to two conflicting plain writes will be reported (aligned and
unaligned, if CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC=n).
+config KCSAN_PERMISSIVE
+ bool "Enable all additional permissive rules"
+ depends on KCSAN_REPORT_VALUE_CHANGE_ONLY
+ help
+ Enable additional permissive rules to ignore certain classes of data
+ races (also see kernel/kcsan/permissive.h). None of the permissive
+ rules imply that such data races are generally safe, but can be used
+ to further reduce reported data races due to data-racy patterns
+ common across the kernel.
+
endif # KCSAN
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 9401d39e4722..663dd81967d4 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -487,6 +487,127 @@ int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp,
}
EXPORT_SYMBOL(bitmap_print_to_pagebuf);
+/**
+ * bitmap_print_to_buf - convert bitmap to list or hex format ASCII string
+ * @list: indicates whether the bitmap must be list
+ * true: print in decimal list format
+ * false: print in hexadecimal bitmask format
+ */
+static int bitmap_print_to_buf(bool list, char *buf, const unsigned long *maskp,
+ int nmaskbits, loff_t off, size_t count)
+{
+ const char *fmt = list ? "%*pbl\n" : "%*pb\n";
+ ssize_t size;
+ void *data;
+
+ data = kasprintf(GFP_KERNEL, fmt, nmaskbits, maskp);
+ if (!data)
+ return -ENOMEM;
+
+ size = memory_read_from_buffer(buf, count, &off, data, strlen(data) + 1);
+ kfree(data);
+
+ return size;
+}
+
+/**
+ * bitmap_print_bitmask_to_buf - convert bitmap to hex bitmask format ASCII string
+ *
+ * The bitmap_print_to_pagebuf() is used indirectly via its cpumap wrapper
+ * cpumap_print_to_pagebuf() or directly by drivers to export hexadecimal
+ * bitmask and decimal list to userspace by sysfs ABI.
+ * Drivers might be using a normal attribute for this kind of ABIs. A
+ * normal attribute typically has show entry as below:
+ * static ssize_t example_attribute_show(struct device *dev,
+ * struct device_attribute *attr, char *buf)
+ * {
+ * ...
+ * return bitmap_print_to_pagebuf(true, buf, &mask, nr_trig_max);
+ * }
+ * show entry of attribute has no offset and count parameters and this
+ * means the file is limited to one page only.
+ * bitmap_print_to_pagebuf() API works terribly well for this kind of
+ * normal attribute with buf parameter and without offset, count:
+ * bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp,
+ * int nmaskbits)
+ * {
+ * }
+ * The problem is once we have a large bitmap, we have a chance to get a
+ * bitmask or list more than one page. Especially for list, it could be
+ * as complex as 0,3,5,7,9,... We have no simple way to know it exact size.
+ * It turns out bin_attribute is a way to break this limit. bin_attribute
+ * has show entry as below:
+ * static ssize_t
+ * example_bin_attribute_show(struct file *filp, struct kobject *kobj,
+ * struct bin_attribute *attr, char *buf,
+ * loff_t offset, size_t count)
+ * {
+ * ...
+ * }
+ * With the new offset and count parameters, this makes sysfs ABI be able
+ * to support file size more than one page. For example, offset could be
+ * >= 4096.
+ * bitmap_print_bitmask_to_buf(), bitmap_print_list_to_buf() wit their
+ * cpumap wrapper cpumap_print_bitmask_to_buf(), cpumap_print_list_to_buf()
+ * make those drivers be able to support large bitmask and list after they
+ * move to use bin_attribute. In result, we have to pass the corresponding
+ * parameters such as off, count from bin_attribute show entry to this API.
+ *
+ * @buf: buffer into which string is placed
+ * @maskp: pointer to bitmap to convert
+ * @nmaskbits: size of bitmap, in bits
+ * @off: in the string from which we are copying, We copy to @buf
+ * @count: the maximum number of bytes to print
+ *
+ * The role of cpumap_print_bitmask_to_buf() and cpumap_print_list_to_buf()
+ * is similar with cpumap_print_to_pagebuf(), the difference is that
+ * bitmap_print_to_pagebuf() mainly serves sysfs attribute with the assumption
+ * the destination buffer is exactly one page and won't be more than one page.
+ * cpumap_print_bitmask_to_buf() and cpumap_print_list_to_buf(), on the other
+ * hand, mainly serves bin_attribute which doesn't work with exact one page,
+ * and it can break the size limit of converted decimal list and hexadecimal
+ * bitmask.
+ *
+ * WARNING!
+ *
+ * This function is not a replacement for sprintf() or bitmap_print_to_pagebuf().
+ * It is intended to workaround sysfs limitations discussed above and should be
+ * used carefully in general case for the following reasons:
+ * - Time complexity is O(nbits^2/count), comparing to O(nbits) for snprintf().
+ * - Memory complexity is O(nbits), comparing to O(1) for snprintf().
+ * - @off and @count are NOT offset and number of bits to print.
+ * - If printing part of bitmap as list, the resulting string is not a correct
+ * list representation of bitmap. Particularly, some bits within or out of
+ * related interval may be erroneously set or unset. The format of the string
+ * may be broken, so bitmap_parselist-like parser may fail parsing it.
+ * - If printing the whole bitmap as list by parts, user must ensure the order
+ * of calls of the function such that the offset is incremented linearly.
+ * - If printing the whole bitmap as list by parts, user must keep bitmap
+ * unchanged between the very first and very last call. Otherwise concatenated
+ * result may be incorrect, and format may be broken.
+ *
+ * Returns the number of characters actually printed to @buf
+ */
+int bitmap_print_bitmask_to_buf(char *buf, const unsigned long *maskp,
+ int nmaskbits, loff_t off, size_t count)
+{
+ return bitmap_print_to_buf(false, buf, maskp, nmaskbits, off, count);
+}
+EXPORT_SYMBOL(bitmap_print_bitmask_to_buf);
+
+/**
+ * bitmap_print_list_to_buf - convert bitmap to decimal list format ASCII string
+ *
+ * Everything is same with the above bitmap_print_bitmask_to_buf() except
+ * the print format.
+ */
+int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp,
+ int nmaskbits, loff_t off, size_t count)
+{
+ return bitmap_print_to_buf(true, buf, maskp, nmaskbits, off, count);
+}
+EXPORT_SYMBOL(bitmap_print_list_to_buf);
+
/*
* Region 9-38:4/10 describes the following bitmap structure:
* 0 9 12 18 38 N
diff --git a/lib/debug_info.c b/lib/debug_info.c
index 36daf753293c..cc4723c74af5 100644
--- a/lib/debug_info.c
+++ b/lib/debug_info.c
@@ -5,8 +5,6 @@
* CONFIG_DEBUG_INFO_REDUCED. Please do not add actual code. However,
* adding appropriate #includes is fine.
*/
-#include <stdarg.h>
-
#include <linux/cred.h>
#include <linux/crypto.h>
#include <linux/dcache.h>
@@ -22,6 +20,7 @@
#include <linux/net.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/stdarg.h>
#include <linux/types.h>
#include <net/addrconf.h>
#include <net/sock.h>
diff --git a/lib/kasprintf.c b/lib/kasprintf.c
index bacf7b83ccf0..cd2f5974ed98 100644
--- a/lib/kasprintf.c
+++ b/lib/kasprintf.c
@@ -5,7 +5,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/types.h>
diff --git a/lib/kunit/string-stream.h b/lib/kunit/string-stream.h
index 5e94b623454f..43f9508a55b4 100644
--- a/lib/kunit/string-stream.h
+++ b/lib/kunit/string-stream.h
@@ -11,7 +11,7 @@
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <stdarg.h>
+#include <linux/stdarg.h>
struct string_stream_fragment {
struct kunit *test;
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index d79ecb86ea57..f246b847024e 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -10,6 +10,7 @@
#include <kunit/test-bug.h>
#include <linux/kernel.h>
#include <linux/kref.h>
+#include <linux/moduleparam.h>
#include <linux/sched/debug.h>
#include <linux/sched.h>
@@ -52,6 +53,51 @@ EXPORT_SYMBOL_GPL(__kunit_fail_current_test);
#endif
/*
+ * KUnit statistic mode:
+ * 0 - disabled
+ * 1 - only when there is more than one subtest
+ * 2 - enabled
+ */
+static int kunit_stats_enabled = 1;
+module_param_named(stats_enabled, kunit_stats_enabled, int, 0644);
+MODULE_PARM_DESC(stats_enabled,
+ "Print test stats: never (0), only for multiple subtests (1), or always (2)");
+
+struct kunit_result_stats {
+ unsigned long passed;
+ unsigned long skipped;
+ unsigned long failed;
+ unsigned long total;
+};
+
+static bool kunit_should_print_stats(struct kunit_result_stats stats)
+{
+ if (kunit_stats_enabled == 0)
+ return false;
+
+ if (kunit_stats_enabled == 2)
+ return true;
+
+ return (stats.total > 1);
+}
+
+static void kunit_print_test_stats(struct kunit *test,
+ struct kunit_result_stats stats)
+{
+ if (!kunit_should_print_stats(stats))
+ return;
+
+ kunit_log(KERN_INFO, test,
+ KUNIT_SUBTEST_INDENT
+ "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
+ test->name,
+ stats.passed,
+ stats.failed,
+ stats.skipped,
+ stats.total);
+}
+
+/*
* Append formatted message to log, size of which is limited to
* KUNIT_LOG_SIZE bytes (including null terminating byte).
*/
@@ -393,15 +439,69 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
test_case->status = KUNIT_SUCCESS;
}
+static void kunit_print_suite_stats(struct kunit_suite *suite,
+ struct kunit_result_stats suite_stats,
+ struct kunit_result_stats param_stats)
+{
+ if (kunit_should_print_stats(suite_stats)) {
+ kunit_log(KERN_INFO, suite,
+ "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
+ suite->name,
+ suite_stats.passed,
+ suite_stats.failed,
+ suite_stats.skipped,
+ suite_stats.total);
+ }
+
+ if (kunit_should_print_stats(param_stats)) {
+ kunit_log(KERN_INFO, suite,
+ "# Totals: pass:%lu fail:%lu skip:%lu total:%lu",
+ param_stats.passed,
+ param_stats.failed,
+ param_stats.skipped,
+ param_stats.total);
+ }
+}
+
+static void kunit_update_stats(struct kunit_result_stats *stats,
+ enum kunit_status status)
+{
+ switch (status) {
+ case KUNIT_SUCCESS:
+ stats->passed++;
+ break;
+ case KUNIT_SKIPPED:
+ stats->skipped++;
+ break;
+ case KUNIT_FAILURE:
+ stats->failed++;
+ break;
+ }
+
+ stats->total++;
+}
+
+static void kunit_accumulate_stats(struct kunit_result_stats *total,
+ struct kunit_result_stats add)
+{
+ total->passed += add.passed;
+ total->skipped += add.skipped;
+ total->failed += add.failed;
+ total->total += add.total;
+}
+
int kunit_run_tests(struct kunit_suite *suite)
{
char param_desc[KUNIT_PARAM_DESC_SIZE];
struct kunit_case *test_case;
+ struct kunit_result_stats suite_stats = { 0 };
+ struct kunit_result_stats total_stats = { 0 };
kunit_print_subtest_start(suite);
kunit_suite_for_each_test_case(suite, test_case) {
struct kunit test = { .param_value = NULL, .param_index = 0 };
+ struct kunit_result_stats param_stats = { 0 };
test_case->status = KUNIT_SKIPPED;
if (test_case->generate_params) {
@@ -431,14 +531,23 @@ int kunit_run_tests(struct kunit_suite *suite)
test.param_value = test_case->generate_params(test.param_value, param_desc);
test.param_index++;
}
+
+ kunit_update_stats(&param_stats, test.status);
+
} while (test.param_value);
+ kunit_print_test_stats(&test, param_stats);
+
kunit_print_ok_not_ok(&test, true, test_case->status,
kunit_test_case_num(suite, test_case),
test_case->name,
test.status_comment);
+
+ kunit_update_stats(&suite_stats, test_case->status);
+ kunit_accumulate_stats(&total_stats, param_stats);
}
+ kunit_print_suite_stats(suite, suite_stats, total_stats);
kunit_print_subtest_end(suite);
return 0;
diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c
index 8abe1870dba4..f9e89001b52e 100644
--- a/lib/nmi_backtrace.c
+++ b/lib/nmi_backtrace.c
@@ -75,12 +75,6 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask,
touch_softlockup_watchdog();
}
- /*
- * Force flush any remote buffers that might be stuck in IRQ context
- * and therefore could not run their irq_work.
- */
- printk_safe_flush();
-
clear_bit_unlock(0, &backtrace_flag);
put_cpu();
}
@@ -92,8 +86,14 @@ module_param(backtrace_idle, bool, 0644);
bool nmi_cpu_backtrace(struct pt_regs *regs)
{
int cpu = smp_processor_id();
+ unsigned long flags;
if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
+ /*
+ * Allow nested NMI backtraces while serializing
+ * against other CPUs.
+ */
+ printk_cpu_lock_irqsave(flags);
if (!READ_ONCE(backtrace_idle) && regs && cpu_in_idle(instruction_pointer(regs))) {
pr_warn("NMI backtrace for cpu %d skipped: idling at %pS\n",
cpu, (void *)instruction_pointer(regs));
@@ -104,6 +104,7 @@ bool nmi_cpu_backtrace(struct pt_regs *regs)
else
dump_stack();
}
+ printk_cpu_unlock_irqrestore(flags);
cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
return true;
}
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 27efa6178153..abb3432ed744 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -182,6 +182,7 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents)
* @nents_first_chunk: Number of entries int the (preallocated) first
* scatterlist chunk, 0 means no such preallocated first chunk
* @free_fn: Free function
+ * @num_ents: Number of entries in the table
*
* Description:
* Free an sg table previously allocated and setup with
@@ -190,7 +191,8 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents)
*
**/
void __sg_free_table(struct sg_table *table, unsigned int max_ents,
- unsigned int nents_first_chunk, sg_free_fn *free_fn)
+ unsigned int nents_first_chunk, sg_free_fn *free_fn,
+ unsigned int num_ents)
{
struct scatterlist *sgl, *next;
unsigned curr_max_ents = nents_first_chunk ?: max_ents;
@@ -199,8 +201,8 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents,
return;
sgl = table->sgl;
- while (table->orig_nents) {
- unsigned int alloc_size = table->orig_nents;
+ while (num_ents) {
+ unsigned int alloc_size = num_ents;
unsigned int sg_size;
/*
@@ -218,7 +220,7 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents,
next = NULL;
}
- table->orig_nents -= sg_size;
+ num_ents -= sg_size;
if (nents_first_chunk)
nents_first_chunk = 0;
else
@@ -232,13 +234,27 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents,
EXPORT_SYMBOL(__sg_free_table);
/**
+ * sg_free_append_table - Free a previously allocated append sg table.
+ * @table: The mapped sg append table header
+ *
+ **/
+void sg_free_append_table(struct sg_append_table *table)
+{
+ __sg_free_table(&table->sgt, SG_MAX_SINGLE_ALLOC, false, sg_kfree,
+ table->total_nents);
+}
+EXPORT_SYMBOL(sg_free_append_table);
+
+
+/**
* sg_free_table - Free a previously allocated sg table
* @table: The mapped sg table header
*
**/
void sg_free_table(struct sg_table *table)
{
- __sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree);
+ __sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree,
+ table->orig_nents);
}
EXPORT_SYMBOL(sg_free_table);
@@ -359,13 +375,12 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC,
NULL, 0, gfp_mask, sg_kmalloc);
if (unlikely(ret))
- __sg_free_table(table, SG_MAX_SINGLE_ALLOC, 0, sg_kfree);
-
+ sg_free_table(table);
return ret;
}
EXPORT_SYMBOL(sg_alloc_table);
-static struct scatterlist *get_next_sg(struct sg_table *table,
+static struct scatterlist *get_next_sg(struct sg_append_table *table,
struct scatterlist *cur,
unsigned long needed_sges,
gfp_t gfp_mask)
@@ -386,54 +401,52 @@ static struct scatterlist *get_next_sg(struct sg_table *table,
return ERR_PTR(-ENOMEM);
sg_init_table(new_sg, alloc_size);
if (cur) {
+ table->total_nents += alloc_size - 1;
__sg_chain(next_sg, new_sg);
- table->orig_nents += alloc_size - 1;
} else {
- table->sgl = new_sg;
- table->orig_nents = alloc_size;
- table->nents = 0;
+ table->sgt.sgl = new_sg;
+ table->total_nents = alloc_size;
}
return new_sg;
}
/**
- * __sg_alloc_table_from_pages - Allocate and initialize an sg table from
- * an array of pages
- * @sgt: The sg table header to use
- * @pages: Pointer to an array of page pointers
- * @n_pages: Number of pages in the pages array
+ * sg_alloc_append_table_from_pages - Allocate and initialize an append sg
+ * table from an array of pages
+ * @sgt_append: The sg append table to use
+ * @pages: Pointer to an array of page pointers
+ * @n_pages: Number of pages in the pages array
* @offset: Offset from start of the first page to the start of a buffer
* @size: Number of valid bytes in the buffer (after offset)
* @max_segment: Maximum size of a scatterlist element in bytes
- * @prv: Last populated sge in sgt
* @left_pages: Left pages caller have to set after this call
* @gfp_mask: GFP allocation mask
*
* Description:
- * If @prv is NULL, allocate and initialize an sg table from a list of pages,
- * else reuse the scatterlist passed in at @prv.
- * Contiguous ranges of the pages are squashed into a single scatterlist
- * entry up to the maximum size specified in @max_segment. A user may
- * provide an offset at a start and a size of valid data in a buffer
- * specified by the page array.
+ * In the first call it allocate and initialize an sg table from a list of
+ * pages, else reuse the scatterlist from sgt_append. Contiguous ranges of
+ * the pages are squashed into a single scatterlist entry up to the maximum
+ * size specified in @max_segment. A user may provide an offset at a start
+ * and a size of valid data in a buffer specified by the page array. The
+ * returned sg table is released by sg_free_append_table
*
* Returns:
- * Last SGE in sgt on success, PTR_ERR on otherwise.
- * The allocation in @sgt must be released by sg_free_table.
+ * 0 on success, negative error on failure
*
* Notes:
* If this function returns non-0 (eg failure), the caller must call
- * sg_free_table() to cleanup any leftover allocations.
+ * sg_free_append_table() to cleanup any leftover allocations.
+ *
+ * In the fist call, sgt_append must by initialized.
*/
-struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
+int sg_alloc_append_table_from_pages(struct sg_append_table *sgt_append,
struct page **pages, unsigned int n_pages, unsigned int offset,
unsigned long size, unsigned int max_segment,
- struct scatterlist *prv, unsigned int left_pages,
- gfp_t gfp_mask)
+ unsigned int left_pages, gfp_t gfp_mask)
{
unsigned int chunks, cur_page, seg_len, i, prv_len = 0;
unsigned int added_nents = 0;
- struct scatterlist *s = prv;
+ struct scatterlist *s = sgt_append->prv;
/*
* The algorithm below requires max_segment to be aligned to PAGE_SIZE
@@ -441,25 +454,26 @@ struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
*/
max_segment = ALIGN_DOWN(max_segment, PAGE_SIZE);
if (WARN_ON(max_segment < PAGE_SIZE))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
- if (IS_ENABLED(CONFIG_ARCH_NO_SG_CHAIN) && prv)
- return ERR_PTR(-EOPNOTSUPP);
+ if (IS_ENABLED(CONFIG_ARCH_NO_SG_CHAIN) && sgt_append->prv)
+ return -EOPNOTSUPP;
- if (prv) {
- unsigned long paddr = (page_to_pfn(sg_page(prv)) * PAGE_SIZE +
- prv->offset + prv->length) /
- PAGE_SIZE;
+ if (sgt_append->prv) {
+ unsigned long paddr =
+ (page_to_pfn(sg_page(sgt_append->prv)) * PAGE_SIZE +
+ sgt_append->prv->offset + sgt_append->prv->length) /
+ PAGE_SIZE;
if (WARN_ON(offset))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
/* Merge contiguous pages into the last SG */
- prv_len = prv->length;
+ prv_len = sgt_append->prv->length;
while (n_pages && page_to_pfn(pages[0]) == paddr) {
- if (prv->length + PAGE_SIZE > max_segment)
+ if (sgt_append->prv->length + PAGE_SIZE > max_segment)
break;
- prv->length += PAGE_SIZE;
+ sgt_append->prv->length += PAGE_SIZE;
paddr++;
pages++;
n_pages--;
@@ -496,15 +510,16 @@ struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
}
/* Pass how many chunks might be left */
- s = get_next_sg(sgt, s, chunks - i + left_pages, gfp_mask);
+ s = get_next_sg(sgt_append, s, chunks - i + left_pages,
+ gfp_mask);
if (IS_ERR(s)) {
/*
* Adjust entry length to be as before function was
* called.
*/
- if (prv)
- prv->length = prv_len;
- return s;
+ if (sgt_append->prv)
+ sgt_append->prv->length = prv_len;
+ return PTR_ERR(s);
}
chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset;
sg_set_page(s, pages[cur_page],
@@ -514,42 +529,58 @@ struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
offset = 0;
cur_page = j;
}
- sgt->nents += added_nents;
+ sgt_append->sgt.nents += added_nents;
+ sgt_append->sgt.orig_nents = sgt_append->sgt.nents;
+ sgt_append->prv = s;
out:
if (!left_pages)
sg_mark_end(s);
- return s;
+ return 0;
}
-EXPORT_SYMBOL(__sg_alloc_table_from_pages);
+EXPORT_SYMBOL(sg_alloc_append_table_from_pages);
/**
- * sg_alloc_table_from_pages - Allocate and initialize an sg table from
- * an array of pages
+ * sg_alloc_table_from_pages_segment - Allocate and initialize an sg table from
+ * an array of pages and given maximum
+ * segment.
* @sgt: The sg table header to use
* @pages: Pointer to an array of page pointers
* @n_pages: Number of pages in the pages array
* @offset: Offset from start of the first page to the start of a buffer
* @size: Number of valid bytes in the buffer (after offset)
+ * @max_segment: Maximum size of a scatterlist element in bytes
* @gfp_mask: GFP allocation mask
*
* Description:
* Allocate and initialize an sg table from a list of pages. Contiguous
- * ranges of the pages are squashed into a single scatterlist node. A user
- * may provide an offset at a start and a size of valid data in a buffer
- * specified by the page array. The returned sg table is released by
- * sg_free_table.
+ * ranges of the pages are squashed into a single scatterlist node up to the
+ * maximum size specified in @max_segment. A user may provide an offset at a
+ * start and a size of valid data in a buffer specified by the page array.
*
- * Returns:
+ * The returned sg table is released by sg_free_table.
+ *
+ * Returns:
* 0 on success, negative error on failure
*/
-int sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages,
- unsigned int n_pages, unsigned int offset,
- unsigned long size, gfp_t gfp_mask)
+int sg_alloc_table_from_pages_segment(struct sg_table *sgt, struct page **pages,
+ unsigned int n_pages, unsigned int offset,
+ unsigned long size, unsigned int max_segment,
+ gfp_t gfp_mask)
{
- return PTR_ERR_OR_ZERO(__sg_alloc_table_from_pages(sgt, pages, n_pages,
- offset, size, UINT_MAX, NULL, 0, gfp_mask));
+ struct sg_append_table append = {};
+ int err;
+
+ err = sg_alloc_append_table_from_pages(&append, pages, n_pages, offset,
+ size, max_segment, 0, gfp_mask);
+ if (err) {
+ sg_free_append_table(&append);
+ return err;
+ }
+ memcpy(sgt, &append.sgt, sizeof(*sgt));
+ WARN_ON(append.total_nents != sgt->orig_nents);
+ return 0;
}
-EXPORT_SYMBOL(sg_alloc_table_from_pages);
+EXPORT_SYMBOL(sg_alloc_table_from_pages_segment);
#ifdef CONFIG_SGL_ALLOC
@@ -887,9 +918,8 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
miter->__offset += miter->consumed;
miter->__remaining -= miter->consumed;
- if ((miter->__flags & SG_MITER_TO_SG) &&
- !PageSlab(miter->page))
- flush_kernel_dcache_page(miter->page);
+ if (miter->__flags & SG_MITER_TO_SG)
+ flush_dcache_page(miter->page);
if (miter->__flags & SG_MITER_ATOMIC) {
WARN_ON_ONCE(preemptible());
diff --git a/lib/sg_pool.c b/lib/sg_pool.c
index db29e5c1f790..a0b1a52cd6f7 100644
--- a/lib/sg_pool.c
+++ b/lib/sg_pool.c
@@ -90,7 +90,8 @@ void sg_free_table_chained(struct sg_table *table,
if (nents_first_chunk == 1)
nents_first_chunk = 0;
- __sg_free_table(table, SG_CHUNK_SIZE, nents_first_chunk, sg_pool_free);
+ __sg_free_table(table, SG_CHUNK_SIZE, nents_first_chunk, sg_pool_free,
+ table->orig_nents);
}
EXPORT_SYMBOL_GPL(sg_free_table_chained);
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 5a35c7e16e96..3806a52ce697 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -361,6 +361,9 @@ static bool escape_special(unsigned char c, char **dst, char *end)
case '\e':
to = 'e';
break;
+ case '"':
+ to = '"';
+ break;
default:
return false;
}
@@ -474,6 +477,7 @@ static bool escape_hex(unsigned char c, char **dst, char *end)
* '\t' - horizontal tab
* '\v' - vertical tab
* %ESCAPE_SPECIAL:
+ * '\"' - double quote
* '\\' - backslash
* '\a' - alert (BEL)
* '\e' - escape
diff --git a/lib/test-string_helpers.c b/lib/test-string_helpers.c
index 2185d71704f0..437d8e6b7cb1 100644
--- a/lib/test-string_helpers.c
+++ b/lib/test-string_helpers.c
@@ -140,13 +140,13 @@ static const struct test_string_2 escape0[] __initconst = {{
},{
.in = "\\h\\\"\a\e\\",
.s1 = {{
- .out = "\\\\h\\\\\"\\a\\e\\\\",
+ .out = "\\\\h\\\\\\\"\\a\\e\\\\",
.flags = ESCAPE_SPECIAL,
},{
- .out = "\\\\\\150\\\\\\042\\a\\e\\\\",
+ .out = "\\\\\\150\\\\\\\"\\a\\e\\\\",
.flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
},{
- .out = "\\\\\\x68\\\\\\x22\\a\\e\\\\",
+ .out = "\\\\\\x68\\\\\\\"\\a\\e\\\\",
.flags = ESCAPE_SPECIAL | ESCAPE_HEX,
},{
/* terminator */
@@ -157,10 +157,10 @@ static const struct test_string_2 escape0[] __initconst = {{
.out = "\eb \\C\007\"\x90\\r]",
.flags = ESCAPE_SPACE,
},{
- .out = "\\eb \\\\C\\a\"\x90\r]",
+ .out = "\\eb \\\\C\\a\\\"\x90\r]",
.flags = ESCAPE_SPECIAL,
},{
- .out = "\\eb \\\\C\\a\"\x90\\r]",
+ .out = "\\eb \\\\C\\a\\\"\x90\\r]",
.flags = ESCAPE_SPACE | ESCAPE_SPECIAL,
},{
.out = "\\033\\142\\040\\134\\103\\007\\042\\220\\015\\135",
@@ -169,10 +169,10 @@ static const struct test_string_2 escape0[] __initconst = {{
.out = "\\033\\142\\040\\134\\103\\007\\042\\220\\r\\135",
.flags = ESCAPE_SPACE | ESCAPE_OCTAL,
},{
- .out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\015\\135",
+ .out = "\\e\\142\\040\\\\\\103\\a\\\"\\220\\015\\135",
.flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
},{
- .out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\r\\135",
+ .out = "\\e\\142\\040\\\\\\103\\a\\\"\\220\\r\\135",
.flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_OCTAL,
},{
.out = "\eb \\C\007\"\x90\r]",
diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c
index 4ea73f5aed41..d33fa5a61b95 100644
--- a/lib/test_bitmap.c
+++ b/lib/test_bitmap.c
@@ -19,6 +19,7 @@
KSTM_MODULE_GLOBALS();
static char pbl_buffer[PAGE_SIZE] __initdata;
+static char print_buf[PAGE_SIZE * 2] __initdata;
static const unsigned long exp1[] __initconst = {
BITMAP_FROM_U64(1),
@@ -156,6 +157,20 @@ static bool __init __check_eq_clump8(const char *srcfile, unsigned int line,
return true;
}
+static bool __init
+__check_eq_str(const char *srcfile, unsigned int line,
+ const char *exp_str, const char *str,
+ unsigned int len)
+{
+ bool eq;
+
+ eq = strncmp(exp_str, str, len) == 0;
+ if (!eq)
+ pr_err("[%s:%u] expected %s, got %s\n", srcfile, line, exp_str, str);
+
+ return eq;
+}
+
#define __expect_eq(suffix, ...) \
({ \
int result = 0; \
@@ -173,6 +188,7 @@ static bool __init __check_eq_clump8(const char *srcfile, unsigned int line,
#define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__)
#define expect_eq_u32_array(...) __expect_eq(u32_array, ##__VA_ARGS__)
#define expect_eq_clump8(...) __expect_eq(clump8, ##__VA_ARGS__)
+#define expect_eq_str(...) __expect_eq(str, ##__VA_ARGS__)
static void __init test_zero_clear(void)
{
@@ -660,6 +676,139 @@ static void __init test_bitmap_cut(void)
}
}
+struct test_bitmap_print {
+ const unsigned long *bitmap;
+ unsigned long nbits;
+ const char *mask;
+ const char *list;
+};
+
+static const unsigned long small_bitmap[] __initconst = {
+ BITMAP_FROM_U64(0x3333333311111111ULL),
+};
+
+static const char small_mask[] __initconst = "33333333,11111111\n";
+static const char small_list[] __initconst = "0,4,8,12,16,20,24,28,32-33,36-37,40-41,44-45,48-49,52-53,56-57,60-61\n";
+
+static const unsigned long large_bitmap[] __initconst = {
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+ BITMAP_FROM_U64(0x3333333311111111ULL), BITMAP_FROM_U64(0x3333333311111111ULL),
+};
+
+static const char large_mask[] __initconst = "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111,"
+ "33333333,11111111,33333333,11111111\n";
+
+static const char large_list[] __initconst = /* more than 4KB */
+ "0,4,8,12,16,20,24,28,32-33,36-37,40-41,44-45,48-49,52-53,56-57,60-61,64,68,72,76,80,84,88,92,96-97,100-101,104-1"
+ "05,108-109,112-113,116-117,120-121,124-125,128,132,136,140,144,148,152,156,160-161,164-165,168-169,172-173,176-1"
+ "77,180-181,184-185,188-189,192,196,200,204,208,212,216,220,224-225,228-229,232-233,236-237,240-241,244-245,248-2"
+ "49,252-253,256,260,264,268,272,276,280,284,288-289,292-293,296-297,300-301,304-305,308-309,312-313,316-317,320,3"
+ "24,328,332,336,340,344,348,352-353,356-357,360-361,364-365,368-369,372-373,376-377,380-381,384,388,392,396,400,4"
+ "04,408,412,416-417,420-421,424-425,428-429,432-433,436-437,440-441,444-445,448,452,456,460,464,468,472,476,480-4"
+ "81,484-485,488-489,492-493,496-497,500-501,504-505,508-509,512,516,520,524,528,532,536,540,544-545,548-549,552-5"
+ "53,556-557,560-561,564-565,568-569,572-573,576,580,584,588,592,596,600,604,608-609,612-613,616-617,620-621,624-6"
+ "25,628-629,632-633,636-637,640,644,648,652,656,660,664,668,672-673,676-677,680-681,684-685,688-689,692-693,696-6"
+ "97,700-701,704,708,712,716,720,724,728,732,736-737,740-741,744-745,748-749,752-753,756-757,760-761,764-765,768,7"
+ "72,776,780,784,788,792,796,800-801,804-805,808-809,812-813,816-817,820-821,824-825,828-829,832,836,840,844,848,8"
+ "52,856,860,864-865,868-869,872-873,876-877,880-881,884-885,888-889,892-893,896,900,904,908,912,916,920,924,928-9"
+ "29,932-933,936-937,940-941,944-945,948-949,952-953,956-957,960,964,968,972,976,980,984,988,992-993,996-997,1000-"
+ "1001,1004-1005,1008-1009,1012-1013,1016-1017,1020-1021,1024,1028,1032,1036,1040,1044,1048,1052,1056-1057,1060-10"
+ "61,1064-1065,1068-1069,1072-1073,1076-1077,1080-1081,1084-1085,1088,1092,1096,1100,1104,1108,1112,1116,1120-1121"
+ ",1124-1125,1128-1129,1132-1133,1136-1137,1140-1141,1144-1145,1148-1149,1152,1156,1160,1164,1168,1172,1176,1180,1"
+ "184-1185,1188-1189,1192-1193,1196-1197,1200-1201,1204-1205,1208-1209,1212-1213,1216,1220,1224,1228,1232,1236,124"
+ "0,1244,1248-1249,1252-1253,1256-1257,1260-1261,1264-1265,1268-1269,1272-1273,1276-1277,1280,1284,1288,1292,1296,"
+ "1300,1304,1308,1312-1313,1316-1317,1320-1321,1324-1325,1328-1329,1332-1333,1336-1337,1340-1341,1344,1348,1352,13"
+ "56,1360,1364,1368,1372,1376-1377,1380-1381,1384-1385,1388-1389,1392-1393,1396-1397,1400-1401,1404-1405,1408,1412"
+ ",1416,1420,1424,1428,1432,1436,1440-1441,1444-1445,1448-1449,1452-1453,1456-1457,1460-1461,1464-1465,1468-1469,1"
+ "472,1476,1480,1484,1488,1492,1496,1500,1504-1505,1508-1509,1512-1513,1516-1517,1520-1521,1524-1525,1528-1529,153"
+ "2-1533,1536,1540,1544,1548,1552,1556,1560,1564,1568-1569,1572-1573,1576-1577,1580-1581,1584-1585,1588-1589,1592-"
+ "1593,1596-1597,1600,1604,1608,1612,1616,1620,1624,1628,1632-1633,1636-1637,1640-1641,1644-1645,1648-1649,1652-16"
+ "53,1656-1657,1660-1661,1664,1668,1672,1676,1680,1684,1688,1692,1696-1697,1700-1701,1704-1705,1708-1709,1712-1713"
+ ",1716-1717,1720-1721,1724-1725,1728,1732,1736,1740,1744,1748,1752,1756,1760-1761,1764-1765,1768-1769,1772-1773,1"
+ "776-1777,1780-1781,1784-1785,1788-1789,1792,1796,1800,1804,1808,1812,1816,1820,1824-1825,1828-1829,1832-1833,183"
+ "6-1837,1840-1841,1844-1845,1848-1849,1852-1853,1856,1860,1864,1868,1872,1876,1880,1884,1888-1889,1892-1893,1896-"
+ "1897,1900-1901,1904-1905,1908-1909,1912-1913,1916-1917,1920,1924,1928,1932,1936,1940,1944,1948,1952-1953,1956-19"
+ "57,1960-1961,1964-1965,1968-1969,1972-1973,1976-1977,1980-1981,1984,1988,1992,1996,2000,2004,2008,2012,2016-2017"
+ ",2020-2021,2024-2025,2028-2029,2032-2033,2036-2037,2040-2041,2044-2045,2048,2052,2056,2060,2064,2068,2072,2076,2"
+ "080-2081,2084-2085,2088-2089,2092-2093,2096-2097,2100-2101,2104-2105,2108-2109,2112,2116,2120,2124,2128,2132,213"
+ "6,2140,2144-2145,2148-2149,2152-2153,2156-2157,2160-2161,2164-2165,2168-2169,2172-2173,2176,2180,2184,2188,2192,"
+ "2196,2200,2204,2208-2209,2212-2213,2216-2217,2220-2221,2224-2225,2228-2229,2232-2233,2236-2237,2240,2244,2248,22"
+ "52,2256,2260,2264,2268,2272-2273,2276-2277,2280-2281,2284-2285,2288-2289,2292-2293,2296-2297,2300-2301,2304,2308"
+ ",2312,2316,2320,2324,2328,2332,2336-2337,2340-2341,2344-2345,2348-2349,2352-2353,2356-2357,2360-2361,2364-2365,2"
+ "368,2372,2376,2380,2384,2388,2392,2396,2400-2401,2404-2405,2408-2409,2412-2413,2416-2417,2420-2421,2424-2425,242"
+ "8-2429,2432,2436,2440,2444,2448,2452,2456,2460,2464-2465,2468-2469,2472-2473,2476-2477,2480-2481,2484-2485,2488-"
+ "2489,2492-2493,2496,2500,2504,2508,2512,2516,2520,2524,2528-2529,2532-2533,2536-2537,2540-2541,2544-2545,2548-25"
+ "49,2552-2553,2556-2557\n";
+
+static const struct test_bitmap_print test_print[] __initconst = {
+ { small_bitmap, sizeof(small_bitmap) * BITS_PER_BYTE, small_mask, small_list },
+ { large_bitmap, sizeof(large_bitmap) * BITS_PER_BYTE, large_mask, large_list },
+};
+
+static void __init test_bitmap_print_buf(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_print); i++) {
+ const struct test_bitmap_print *t = &test_print[i];
+ int n;
+
+ n = bitmap_print_bitmask_to_buf(print_buf, t->bitmap, t->nbits,
+ 0, 2 * PAGE_SIZE);
+ expect_eq_uint(strlen(t->mask) + 1, n);
+ expect_eq_str(t->mask, print_buf, n);
+
+ n = bitmap_print_list_to_buf(print_buf, t->bitmap, t->nbits,
+ 0, 2 * PAGE_SIZE);
+ expect_eq_uint(strlen(t->list) + 1, n);
+ expect_eq_str(t->list, print_buf, n);
+
+ /* test by non-zero offset */
+ if (strlen(t->list) > PAGE_SIZE) {
+ n = bitmap_print_list_to_buf(print_buf, t->bitmap, t->nbits,
+ PAGE_SIZE, PAGE_SIZE);
+ expect_eq_uint(strlen(t->list) + 1 - PAGE_SIZE, n);
+ expect_eq_str(t->list + PAGE_SIZE, print_buf, n);
+ }
+ }
+}
+
static void __init selftest(void)
{
test_zero_clear();
@@ -672,6 +821,7 @@ static void __init selftest(void)
test_mem_optimisations();
test_for_each_set_clump8();
test_bitmap_cut();
+ test_bitmap_print_buf();
}
KSTM_MODULE_LOADERS(test_bitmap);
diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index 8f7b0b2f6e11..8835e0784578 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -53,7 +53,6 @@ static int kasan_test_init(struct kunit *test)
}
multishot = kasan_save_enable_multi_shot();
- kasan_set_tagging_report_once(false);
fail_data.report_found = false;
kunit_add_named_resource(test, NULL, NULL, &resource,
"kasan_data", &fail_data);
@@ -62,7 +61,6 @@ static int kasan_test_init(struct kunit *test)
static void kasan_test_exit(struct kunit *test)
{
- kasan_set_tagging_report_once(true);
kasan_restore_multi_shot(multishot);
KUNIT_EXPECT_FALSE(test, fail_data.report_found);
}
@@ -122,12 +120,28 @@ static void kasan_test_exit(struct kunit *test)
static void kmalloc_oob_right(struct kunit *test)
{
char *ptr;
- size_t size = 123;
+ size_t size = 128 - KASAN_GRANULE_SIZE - 5;
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, ptr[size + OOB_TAG_OFF] = 'x');
+ /*
+ * An unaligned access past the requested kmalloc size.
+ * Only generic KASAN can precisely detect these.
+ */
+ if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+ KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 'x');
+
+ /*
+ * An aligned access into the first out-of-bounds granule that falls
+ * within the aligned kmalloc object.
+ */
+ KUNIT_EXPECT_KASAN_FAIL(test, ptr[size + 5] = 'y');
+
+ /* Out-of-bounds access past the aligned kmalloc object. */
+ KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] =
+ ptr[size + KASAN_GRANULE_SIZE + 5]);
+
kfree(ptr);
}
@@ -151,7 +165,7 @@ static void kmalloc_node_oob_right(struct kunit *test)
ptr = kmalloc_node(size, GFP_KERNEL, 0);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 0);
+ KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = ptr[size]);
kfree(ptr);
}
@@ -187,7 +201,7 @@ static void kmalloc_pagealloc_uaf(struct kunit *test)
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
kfree(ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = 0);
+ KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]);
}
static void kmalloc_pagealloc_invalid_free(struct kunit *test)
@@ -221,7 +235,7 @@ static void pagealloc_oob_right(struct kunit *test)
ptr = page_address(pages);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 0);
+ KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = ptr[size]);
free_pages((unsigned long)ptr, order);
}
@@ -236,7 +250,7 @@ static void pagealloc_uaf(struct kunit *test)
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
free_pages((unsigned long)ptr, order);
- KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = 0);
+ KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]);
}
static void kmalloc_large_oob_right(struct kunit *test)
@@ -412,64 +426,70 @@ static void kmalloc_uaf_16(struct kunit *test)
kfree(ptr1);
}
+/*
+ * Note: in the memset tests below, the written range touches both valid and
+ * invalid memory. This makes sure that the instrumentation does not only check
+ * the starting address but the whole range.
+ */
+
static void kmalloc_oob_memset_2(struct kunit *test)
{
char *ptr;
- size_t size = 8;
+ size_t size = 128 - KASAN_GRANULE_SIZE;
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + 7 + OOB_TAG_OFF, 0, 2));
+ KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 1, 0, 2));
kfree(ptr);
}
static void kmalloc_oob_memset_4(struct kunit *test)
{
char *ptr;
- size_t size = 8;
+ size_t size = 128 - KASAN_GRANULE_SIZE;
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + 5 + OOB_TAG_OFF, 0, 4));
+ KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 3, 0, 4));
kfree(ptr);
}
-
static void kmalloc_oob_memset_8(struct kunit *test)
{
char *ptr;
- size_t size = 8;
+ size_t size = 128 - KASAN_GRANULE_SIZE;
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + 1 + OOB_TAG_OFF, 0, 8));
+ KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 7, 0, 8));
kfree(ptr);
}
static void kmalloc_oob_memset_16(struct kunit *test)
{
char *ptr;
- size_t size = 16;
+ size_t size = 128 - KASAN_GRANULE_SIZE;
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + 1 + OOB_TAG_OFF, 0, 16));
+ KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 15, 0, 16));
kfree(ptr);
}
static void kmalloc_oob_in_memset(struct kunit *test)
{
char *ptr;
- size_t size = 666;
+ size_t size = 128 - KASAN_GRANULE_SIZE;
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr, 0, size + 5 + OOB_TAG_OFF));
+ KUNIT_EXPECT_KASAN_FAIL(test,
+ memset(ptr, 0, size + KASAN_GRANULE_SIZE));
kfree(ptr);
}
@@ -479,11 +499,17 @@ static void kmalloc_memmove_invalid_size(struct kunit *test)
size_t size = 64;
volatile size_t invalid_size = -2;
+ /*
+ * Hardware tag-based mode doesn't check memmove for negative size.
+ * As a result, this test introduces a side-effect memory corruption,
+ * which can result in a crash.
+ */
+ KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_HW_TAGS);
+
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
memset((char *)ptr, 0, 64);
-
KUNIT_EXPECT_KASAN_FAIL(test,
memmove((char *)ptr, (char *)ptr + 4, invalid_size));
kfree(ptr);
@@ -498,7 +524,7 @@ static void kmalloc_uaf(struct kunit *test)
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
kfree(ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, *(ptr + 8) = 'x');
+ KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[8]);
}
static void kmalloc_uaf_memset(struct kunit *test)
@@ -506,6 +532,12 @@ static void kmalloc_uaf_memset(struct kunit *test)
char *ptr;
size_t size = 33;
+ /*
+ * Only generic KASAN uses quarantine, which is required to avoid a
+ * kernel memory corruption this test causes.
+ */
+ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
+
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
@@ -537,7 +569,7 @@ again:
goto again;
}
- KUNIT_EXPECT_KASAN_FAIL(test, ptr1[40] = 'x');
+ KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr1)[40]);
KUNIT_EXPECT_PTR_NE(test, ptr1, ptr2);
kfree(ptr2);
@@ -684,7 +716,7 @@ static void ksize_unpoisons_memory(struct kunit *test)
ptr[size] = 'x';
/* This one must. */
- KUNIT_EXPECT_KASAN_FAIL(test, ptr[real_size] = 'y');
+ KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[real_size]);
kfree(ptr);
}
@@ -703,8 +735,8 @@ static void ksize_uaf(struct kunit *test)
kfree(ptr);
KUNIT_EXPECT_KASAN_FAIL(test, ksize(ptr));
- KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = *ptr);
- KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = *(ptr + size));
+ KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]);
+ KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]);
}
static void kasan_stack_oob(struct kunit *test)
diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c
index f1017f345d6c..7ebf433edef3 100644
--- a/lib/test_kasan_module.c
+++ b/lib/test_kasan_module.c
@@ -15,13 +15,11 @@
#include "../mm/kasan/kasan.h"
-#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_GRANULE_SIZE)
-
static noinline void __init copy_user_test(void)
{
char *kmem;
char __user *usermem;
- size_t size = 10;
+ size_t size = 128 - KASAN_GRANULE_SIZE;
int __maybe_unused unused;
kmem = kmalloc(size, GFP_KERNEL);
@@ -38,25 +36,25 @@ static noinline void __init copy_user_test(void)
}
pr_info("out-of-bounds in copy_from_user()\n");
- unused = copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
+ unused = copy_from_user(kmem, usermem, size + 1);
pr_info("out-of-bounds in copy_to_user()\n");
- unused = copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
+ unused = copy_to_user(usermem, kmem, size + 1);
pr_info("out-of-bounds in __copy_from_user()\n");
- unused = __copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
+ unused = __copy_from_user(kmem, usermem, size + 1);
pr_info("out-of-bounds in __copy_to_user()\n");
- unused = __copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
+ unused = __copy_to_user(usermem, kmem, size + 1);
pr_info("out-of-bounds in __copy_from_user_inatomic()\n");
- unused = __copy_from_user_inatomic(kmem, usermem, size + 1 + OOB_TAG_OFF);
+ unused = __copy_from_user_inatomic(kmem, usermem, size + 1);
pr_info("out-of-bounds in __copy_to_user_inatomic()\n");
- unused = __copy_to_user_inatomic(usermem, kmem, size + 1 + OOB_TAG_OFF);
+ unused = __copy_to_user_inatomic(usermem, kmem, size + 1);
pr_info("out-of-bounds in strncpy_from_user()\n");
- unused = strncpy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
+ unused = strncpy_from_user(kmem, usermem, size + 1);
vm_munmap((unsigned long)usermem, PAGE_SIZE);
kfree(kmem);
@@ -73,7 +71,7 @@ static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
struct kasan_rcu_info, rcu);
kfree(fp);
- fp->i = 1;
+ ((volatile struct kasan_rcu_info *)fp)->i;
}
static noinline void __init kasan_rcu_uaf(void)
diff --git a/lib/test_printf.c b/lib/test_printf.c
index 8ac71aee46af..8a48b61c3763 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -675,9 +675,8 @@ flags(void)
"uptodate|dirty|lru|active|swapbacked",
cmp_buffer);
- flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC
- | VM_DENYWRITE;
- test("read|exec|mayread|maywrite|mayexec|denywrite", "%pGv", &flags);
+ flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+ test("read|exec|mayread|maywrite|mayexec", "%pGv", &flags);
gfp = GFP_TRANSHUGE;
test("GFP_TRANSHUGE", "%pGg", &gfp);
diff --git a/lib/test_scanf.c b/lib/test_scanf.c
index 84fe09eaf55e..b620cf7de503 100644
--- a/lib/test_scanf.c
+++ b/lib/test_scanf.c
@@ -271,7 +271,7 @@ static u32 __init next_test_random(u32 max_bits)
{
u32 n_bits = hweight32(prandom_u32_state(&rnd_state)) % (max_bits + 1);
- return prandom_u32_state(&rnd_state) & (UINT_MAX >> (32 - n_bits));
+ return prandom_u32_state(&rnd_state) & GENMASK(n_bits, 0);
}
static unsigned long long __init next_test_random_ull(void)
@@ -280,7 +280,7 @@ static unsigned long long __init next_test_random_ull(void)
u32 n_bits = (hweight32(rand1) * 3) % 64;
u64 val = (u64)prandom_u32_state(&rnd_state) * rand1;
- return val & (ULLONG_MAX >> (64 - n_bits));
+ return val & GENMASK_ULL(n_bits, 0);
}
#define random_for_type(T) \
@@ -398,7 +398,7 @@ do { \
test_array_8(fn, expect, test_buffer, fmt_buffer, result); \
} while (0)
-static void __init numbers_list(const char *delim)
+static void __init numbers_list_ll(const char *delim)
{
numbers_list_8(unsigned long long, "%llu", delim, "llu", check_ull);
numbers_list_8(long long, "%lld", delim, "lld", check_ll);
@@ -406,28 +406,40 @@ static void __init numbers_list(const char *delim)
numbers_list_8(unsigned long long, "%llx", delim, "llx", check_ull);
numbers_list_8(unsigned long long, "0x%llx", delim, "llx", check_ull);
numbers_list_8(long long, "0x%llx", delim, "lli", check_ll);
+}
+static void __init numbers_list_l(const char *delim)
+{
numbers_list_8(unsigned long, "%lu", delim, "lu", check_ulong);
numbers_list_8(long, "%ld", delim, "ld", check_long);
numbers_list_8(long, "%ld", delim, "li", check_long);
numbers_list_8(unsigned long, "%lx", delim, "lx", check_ulong);
numbers_list_8(unsigned long, "0x%lx", delim, "lx", check_ulong);
numbers_list_8(long, "0x%lx", delim, "li", check_long);
+}
+static void __init numbers_list_d(const char *delim)
+{
numbers_list_8(unsigned int, "%u", delim, "u", check_uint);
numbers_list_8(int, "%d", delim, "d", check_int);
numbers_list_8(int, "%d", delim, "i", check_int);
numbers_list_8(unsigned int, "%x", delim, "x", check_uint);
numbers_list_8(unsigned int, "0x%x", delim, "x", check_uint);
numbers_list_8(int, "0x%x", delim, "i", check_int);
+}
+static void __init numbers_list_h(const char *delim)
+{
numbers_list_8(unsigned short, "%hu", delim, "hu", check_ushort);
numbers_list_8(short, "%hd", delim, "hd", check_short);
numbers_list_8(short, "%hd", delim, "hi", check_short);
numbers_list_8(unsigned short, "%hx", delim, "hx", check_ushort);
numbers_list_8(unsigned short, "0x%hx", delim, "hx", check_ushort);
numbers_list_8(short, "0x%hx", delim, "hi", check_short);
+}
+static void __init numbers_list_hh(const char *delim)
+{
numbers_list_8(unsigned char, "%hhu", delim, "hhu", check_uchar);
numbers_list_8(signed char, "%hhd", delim, "hhd", check_char);
numbers_list_8(signed char, "%hhd", delim, "hhi", check_char);
@@ -436,11 +448,16 @@ static void __init numbers_list(const char *delim)
numbers_list_8(signed char, "0x%hhx", delim, "hhi", check_char);
}
-/*
- * List of numbers separated by delim. Each field width specifier is the
- * maximum possible digits for the given type and base.
- */
-static void __init numbers_list_field_width_typemax(const char *delim)
+static void __init numbers_list(const char *delim)
+{
+ numbers_list_ll(delim);
+ numbers_list_l(delim);
+ numbers_list_d(delim);
+ numbers_list_h(delim);
+ numbers_list_hh(delim);
+}
+
+static void __init numbers_list_field_width_ll(const char *delim)
{
numbers_list_fix_width(unsigned long long, "%llu", delim, 20, "llu", check_ull);
numbers_list_fix_width(long long, "%lld", delim, 20, "lld", check_ll);
@@ -448,7 +465,10 @@ static void __init numbers_list_field_width_typemax(const char *delim)
numbers_list_fix_width(unsigned long long, "%llx", delim, 16, "llx", check_ull);
numbers_list_fix_width(unsigned long long, "0x%llx", delim, 18, "llx", check_ull);
numbers_list_fix_width(long long, "0x%llx", delim, 18, "lli", check_ll);
+}
+static void __init numbers_list_field_width_l(const char *delim)
+{
#if BITS_PER_LONG == 64
numbers_list_fix_width(unsigned long, "%lu", delim, 20, "lu", check_ulong);
numbers_list_fix_width(long, "%ld", delim, 20, "ld", check_long);
@@ -464,21 +484,30 @@ static void __init numbers_list_field_width_typemax(const char *delim)
numbers_list_fix_width(unsigned long, "0x%lx", delim, 10, "lx", check_ulong);
numbers_list_fix_width(long, "0x%lx", delim, 10, "li", check_long);
#endif
+}
+static void __init numbers_list_field_width_d(const char *delim)
+{
numbers_list_fix_width(unsigned int, "%u", delim, 10, "u", check_uint);
numbers_list_fix_width(int, "%d", delim, 11, "d", check_int);
numbers_list_fix_width(int, "%d", delim, 11, "i", check_int);
numbers_list_fix_width(unsigned int, "%x", delim, 8, "x", check_uint);
numbers_list_fix_width(unsigned int, "0x%x", delim, 10, "x", check_uint);
numbers_list_fix_width(int, "0x%x", delim, 10, "i", check_int);
+}
+static void __init numbers_list_field_width_h(const char *delim)
+{
numbers_list_fix_width(unsigned short, "%hu", delim, 5, "hu", check_ushort);
numbers_list_fix_width(short, "%hd", delim, 6, "hd", check_short);
numbers_list_fix_width(short, "%hd", delim, 6, "hi", check_short);
numbers_list_fix_width(unsigned short, "%hx", delim, 4, "hx", check_ushort);
numbers_list_fix_width(unsigned short, "0x%hx", delim, 6, "hx", check_ushort);
numbers_list_fix_width(short, "0x%hx", delim, 6, "hi", check_short);
+}
+static void __init numbers_list_field_width_hh(const char *delim)
+{
numbers_list_fix_width(unsigned char, "%hhu", delim, 3, "hhu", check_uchar);
numbers_list_fix_width(signed char, "%hhd", delim, 4, "hhd", check_char);
numbers_list_fix_width(signed char, "%hhd", delim, 4, "hhi", check_char);
@@ -489,9 +518,18 @@ static void __init numbers_list_field_width_typemax(const char *delim)
/*
* List of numbers separated by delim. Each field width specifier is the
- * exact length of the corresponding value digits in the string being scanned.
+ * maximum possible digits for the given type and base.
*/
-static void __init numbers_list_field_width_val_width(const char *delim)
+static void __init numbers_list_field_width_typemax(const char *delim)
+{
+ numbers_list_field_width_ll(delim);
+ numbers_list_field_width_l(delim);
+ numbers_list_field_width_d(delim);
+ numbers_list_field_width_h(delim);
+ numbers_list_field_width_hh(delim);
+}
+
+static void __init numbers_list_field_width_val_ll(const char *delim)
{
numbers_list_val_width(unsigned long long, "%llu", delim, "llu", check_ull);
numbers_list_val_width(long long, "%lld", delim, "lld", check_ll);
@@ -499,28 +537,40 @@ static void __init numbers_list_field_width_val_width(const char *delim)
numbers_list_val_width(unsigned long long, "%llx", delim, "llx", check_ull);
numbers_list_val_width(unsigned long long, "0x%llx", delim, "llx", check_ull);
numbers_list_val_width(long long, "0x%llx", delim, "lli", check_ll);
+}
+static void __init numbers_list_field_width_val_l(const char *delim)
+{
numbers_list_val_width(unsigned long, "%lu", delim, "lu", check_ulong);
numbers_list_val_width(long, "%ld", delim, "ld", check_long);
numbers_list_val_width(long, "%ld", delim, "li", check_long);
numbers_list_val_width(unsigned long, "%lx", delim, "lx", check_ulong);
numbers_list_val_width(unsigned long, "0x%lx", delim, "lx", check_ulong);
numbers_list_val_width(long, "0x%lx", delim, "li", check_long);
+}
+static void __init numbers_list_field_width_val_d(const char *delim)
+{
numbers_list_val_width(unsigned int, "%u", delim, "u", check_uint);
numbers_list_val_width(int, "%d", delim, "d", check_int);
numbers_list_val_width(int, "%d", delim, "i", check_int);
numbers_list_val_width(unsigned int, "%x", delim, "x", check_uint);
numbers_list_val_width(unsigned int, "0x%x", delim, "x", check_uint);
numbers_list_val_width(int, "0x%x", delim, "i", check_int);
+}
+static void __init numbers_list_field_width_val_h(const char *delim)
+{
numbers_list_val_width(unsigned short, "%hu", delim, "hu", check_ushort);
numbers_list_val_width(short, "%hd", delim, "hd", check_short);
numbers_list_val_width(short, "%hd", delim, "hi", check_short);
numbers_list_val_width(unsigned short, "%hx", delim, "hx", check_ushort);
numbers_list_val_width(unsigned short, "0x%hx", delim, "hx", check_ushort);
numbers_list_val_width(short, "0x%hx", delim, "hi", check_short);
+}
+static void __init numbers_list_field_width_val_hh(const char *delim)
+{
numbers_list_val_width(unsigned char, "%hhu", delim, "hhu", check_uchar);
numbers_list_val_width(signed char, "%hhd", delim, "hhd", check_char);
numbers_list_val_width(signed char, "%hhd", delim, "hhi", check_char);
@@ -530,6 +580,19 @@ static void __init numbers_list_field_width_val_width(const char *delim)
}
/*
+ * List of numbers separated by delim. Each field width specifier is the
+ * exact length of the corresponding value digits in the string being scanned.
+ */
+static void __init numbers_list_field_width_val_width(const char *delim)
+{
+ numbers_list_field_width_val_ll(delim);
+ numbers_list_field_width_val_l(delim);
+ numbers_list_field_width_val_d(delim);
+ numbers_list_field_width_val_h(delim);
+ numbers_list_field_width_val_hh(delim);
+}
+
+/*
* Slice a continuous string of digits without field delimiters, containing
* numbers of varying length, using the field width to extract each group
* of digits. For example the hex values c0,3,bf01,303 would have a
diff --git a/lib/test_stackinit.c b/lib/test_stackinit.c
index f93b1e145ada..a3c74e6a21ff 100644
--- a/lib/test_stackinit.c
+++ b/lib/test_stackinit.c
@@ -1,8 +1,13 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Test cases for compiler-based stack variable zeroing via future
- * compiler flags or CONFIG_GCC_PLUGIN_STRUCTLEAK*.
+ * Test cases for compiler-based stack variable zeroing via
+ * -ftrivial-auto-var-init={zero,pattern} or CONFIG_GCC_PLUGIN_STRUCTLEAK*.
+ *
+ * External build example:
+ * clang -O2 -Wall -ftrivial-auto-var-init=pattern \
+ * -o test_stackinit test_stackinit.c
*/
+#ifdef __KERNEL__
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
@@ -10,6 +15,63 @@
#include <linux/module.h>
#include <linux/string.h>
+#else
+
+/* Userspace headers. */
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/types.h>
+
+/* Linux kernel-ism stubs for stand-alone userspace build. */
+#define KBUILD_MODNAME "stackinit"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define pr_err(fmt, ...) fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warn(fmt, ...) fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_info(fmt, ...) fprintf(stdout, pr_fmt(fmt), ##__VA_ARGS__)
+#define __init /**/
+#define __exit /**/
+#define __user /**/
+#define noinline __attribute__((__noinline__))
+#define __aligned(x) __attribute__((__aligned__(x)))
+#ifdef __clang__
+# define __compiletime_error(message) /**/
+#else
+# define __compiletime_error(message) __attribute__((__error__(message)))
+#endif
+#define __compiletime_assert(condition, msg, prefix, suffix) \
+ do { \
+ extern void prefix ## suffix(void) __compiletime_error(msg); \
+ if (!(condition)) \
+ prefix ## suffix(); \
+ } while (0)
+#define _compiletime_assert(condition, msg, prefix, suffix) \
+ __compiletime_assert(condition, msg, prefix, suffix)
+#define compiletime_assert(condition, msg) \
+ _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
+#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
+#define BUILD_BUG_ON(condition) \
+ BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+#define module_init(func) static int (*do_init)(void) = func
+#define module_exit(func) static void (*do_exit)(void) = func
+#define MODULE_LICENSE(str) int main(void) { \
+ int rc; \
+ /* License: str */ \
+ rc = do_init(); \
+ if (rc == 0) \
+ do_exit(); \
+ return rc; \
+ }
+
+#endif /* __KERNEL__ */
+
/* Exfiltration buffer. */
#define MAX_VAR_SIZE 128
static u8 check_buf[MAX_VAR_SIZE];
@@ -33,6 +95,10 @@ static bool range_contains(char *haystack_start, size_t haystack_size,
return false;
}
+/* Whether the test is expected to fail. */
+#define WANT_SUCCESS 0
+#define XFAIL 1
+
#define DO_NOTHING_TYPE_SCALAR(var_type) var_type
#define DO_NOTHING_TYPE_STRING(var_type) void
#define DO_NOTHING_TYPE_STRUCT(var_type) void
@@ -58,34 +124,73 @@ static bool range_contains(char *haystack_start, size_t haystack_size,
#define INIT_CLONE_STRING [FILL_SIZE_STRING]
#define INIT_CLONE_STRUCT /**/
-#define INIT_SCALAR_none /**/
-#define INIT_SCALAR_zero = 0
+#define ZERO_CLONE_SCALAR(zero) memset(&(zero), 0x00, sizeof(zero))
+#define ZERO_CLONE_STRING(zero) memset(&(zero), 0x00, sizeof(zero))
+/*
+ * For the struct, intentionally poison padding to see if it gets
+ * copied out in direct assignments.
+ * */
+#define ZERO_CLONE_STRUCT(zero) \
+ do { \
+ memset(&(zero), 0xFF, sizeof(zero)); \
+ zero.one = 0; \
+ zero.two = 0; \
+ zero.three = 0; \
+ zero.four = 0; \
+ } while (0)
+
+#define INIT_SCALAR_none(var_type) /**/
+#define INIT_SCALAR_zero(var_type) = 0
-#define INIT_STRING_none [FILL_SIZE_STRING] /**/
-#define INIT_STRING_zero [FILL_SIZE_STRING] = { }
+#define INIT_STRING_none(var_type) [FILL_SIZE_STRING] /**/
+#define INIT_STRING_zero(var_type) [FILL_SIZE_STRING] = { }
-#define INIT_STRUCT_none /**/
-#define INIT_STRUCT_zero = { }
-#define INIT_STRUCT_static_partial = { .two = 0, }
-#define INIT_STRUCT_static_all = { .one = arg->one, \
- .two = arg->two, \
- .three = arg->three, \
- .four = arg->four, \
+#define INIT_STRUCT_none(var_type) /**/
+#define INIT_STRUCT_zero(var_type) = { }
+
+
+#define __static_partial { .two = 0, }
+#define __static_all { .one = 0, \
+ .two = 0, \
+ .three = 0, \
+ .four = 0, \
}
-#define INIT_STRUCT_dynamic_partial = { .two = arg->two, }
-#define INIT_STRUCT_dynamic_all = { .one = arg->one, \
- .two = arg->two, \
- .three = arg->three, \
- .four = arg->four, \
+#define __dynamic_partial { .two = arg->two, }
+#define __dynamic_all { .one = arg->one, \
+ .two = arg->two, \
+ .three = arg->three, \
+ .four = arg->four, \
}
-#define INIT_STRUCT_runtime_partial ; \
- var.two = 0
-#define INIT_STRUCT_runtime_all ; \
- var.one = 0; \
+#define __runtime_partial var.two = 0
+#define __runtime_all var.one = 0; \
var.two = 0; \
var.three = 0; \
- memset(&var.four, 0, \
- sizeof(var.four))
+ var.four = 0
+
+#define INIT_STRUCT_static_partial(var_type) \
+ = __static_partial
+#define INIT_STRUCT_static_all(var_type) \
+ = __static_all
+#define INIT_STRUCT_dynamic_partial(var_type) \
+ = __dynamic_partial
+#define INIT_STRUCT_dynamic_all(var_type) \
+ = __dynamic_all
+#define INIT_STRUCT_runtime_partial(var_type) \
+ ; __runtime_partial
+#define INIT_STRUCT_runtime_all(var_type) \
+ ; __runtime_all
+
+#define INIT_STRUCT_assigned_static_partial(var_type) \
+ ; var = (var_type)__static_partial
+#define INIT_STRUCT_assigned_static_all(var_type) \
+ ; var = (var_type)__static_all
+#define INIT_STRUCT_assigned_dynamic_partial(var_type) \
+ ; var = (var_type)__dynamic_partial
+#define INIT_STRUCT_assigned_dynamic_all(var_type) \
+ ; var = (var_type)__dynamic_all
+
+#define INIT_STRUCT_assigned_copy(var_type) \
+ ; var = *(arg)
/*
* @name: unique string name for the test
@@ -106,7 +211,7 @@ static noinline __init int test_ ## name (void) \
BUILD_BUG_ON(sizeof(zero) > MAX_VAR_SIZE); \
\
/* Fill clone type with zero for per-field init. */ \
- memset(&zero, 0x00, sizeof(zero)); \
+ ZERO_CLONE_ ## which(zero); \
/* Clear entire check buffer for 0xFF overlap test. */ \
memset(check_buf, 0x00, sizeof(check_buf)); \
/* Fill stack with 0xFF. */ \
@@ -149,7 +254,7 @@ static noinline __init int test_ ## name (void) \
return (xfail) ? 0 : 1; \
} \
}
-#define DEFINE_TEST(name, var_type, which, init_level) \
+#define DEFINE_TEST(name, var_type, which, init_level, xfail) \
/* no-op to force compiler into ignoring "uninitialized" vars */\
static noinline __init DO_NOTHING_TYPE_ ## which(var_type) \
do_nothing_ ## name(var_type *ptr) \
@@ -165,7 +270,8 @@ static noinline __init int leaf_ ## name(unsigned long sp, \
var_type *arg) \
{ \
char buf[VAR_BUFFER]; \
- var_type var INIT_ ## which ## _ ## init_level; \
+ var_type var \
+ INIT_ ## which ## _ ## init_level(var_type); \
\
target_start = &var; \
target_size = sizeof(var); \
@@ -191,7 +297,7 @@ static noinline __init int leaf_ ## name(unsigned long sp, \
\
return (int)buf[0] | (int)buf[sizeof(buf) - 1]; \
} \
-DEFINE_TEST_DRIVER(name, var_type, which, 0)
+DEFINE_TEST_DRIVER(name, var_type, which, xfail)
/* Structure with no padding. */
struct test_packed {
@@ -210,18 +316,13 @@ struct test_small_hole {
unsigned long four;
};
-/* Try to trigger unhandled padding in a structure. */
-struct test_aligned {
- u32 internal1;
- u64 internal2;
-} __aligned(64);
-
+/* Trigger unhandled padding in a structure. */
struct test_big_hole {
u8 one;
u8 two;
u8 three;
/* 61 byte padding hole here. */
- struct test_aligned four;
+ u8 four __aligned(64);
} __aligned(64);
struct test_trailing_hole {
@@ -240,42 +341,50 @@ struct test_user {
unsigned long four;
};
-#define DEFINE_SCALAR_TEST(name, init) \
- DEFINE_TEST(name ## _ ## init, name, SCALAR, init)
+#define DEFINE_SCALAR_TEST(name, init, xfail) \
+ DEFINE_TEST(name ## _ ## init, name, SCALAR, \
+ init, xfail)
-#define DEFINE_SCALAR_TESTS(init) \
- DEFINE_SCALAR_TEST(u8, init); \
- DEFINE_SCALAR_TEST(u16, init); \
- DEFINE_SCALAR_TEST(u32, init); \
- DEFINE_SCALAR_TEST(u64, init); \
- DEFINE_TEST(char_array_ ## init, unsigned char, STRING, init)
+#define DEFINE_SCALAR_TESTS(init, xfail) \
+ DEFINE_SCALAR_TEST(u8, init, xfail); \
+ DEFINE_SCALAR_TEST(u16, init, xfail); \
+ DEFINE_SCALAR_TEST(u32, init, xfail); \
+ DEFINE_SCALAR_TEST(u64, init, xfail); \
+ DEFINE_TEST(char_array_ ## init, unsigned char, \
+ STRING, init, xfail)
-#define DEFINE_STRUCT_TEST(name, init) \
+#define DEFINE_STRUCT_TEST(name, init, xfail) \
DEFINE_TEST(name ## _ ## init, \
- struct test_ ## name, STRUCT, init)
+ struct test_ ## name, STRUCT, init, \
+ xfail)
+
+#define DEFINE_STRUCT_TESTS(init, xfail) \
+ DEFINE_STRUCT_TEST(small_hole, init, xfail); \
+ DEFINE_STRUCT_TEST(big_hole, init, xfail); \
+ DEFINE_STRUCT_TEST(trailing_hole, init, xfail); \
+ DEFINE_STRUCT_TEST(packed, init, xfail)
-#define DEFINE_STRUCT_TESTS(init) \
- DEFINE_STRUCT_TEST(small_hole, init); \
- DEFINE_STRUCT_TEST(big_hole, init); \
- DEFINE_STRUCT_TEST(trailing_hole, init); \
- DEFINE_STRUCT_TEST(packed, init)
+#define DEFINE_STRUCT_INITIALIZER_TESTS(base) \
+ DEFINE_STRUCT_TESTS(base ## _ ## partial, \
+ WANT_SUCCESS); \
+ DEFINE_STRUCT_TESTS(base ## _ ## all, \
+ WANT_SUCCESS)
/* These should be fully initialized all the time! */
-DEFINE_SCALAR_TESTS(zero);
-DEFINE_STRUCT_TESTS(zero);
-/* Static initialization: padding may be left uninitialized. */
-DEFINE_STRUCT_TESTS(static_partial);
-DEFINE_STRUCT_TESTS(static_all);
-/* Dynamic initialization: padding may be left uninitialized. */
-DEFINE_STRUCT_TESTS(dynamic_partial);
-DEFINE_STRUCT_TESTS(dynamic_all);
-/* Runtime initialization: padding may be left uninitialized. */
-DEFINE_STRUCT_TESTS(runtime_partial);
-DEFINE_STRUCT_TESTS(runtime_all);
+DEFINE_SCALAR_TESTS(zero, WANT_SUCCESS);
+DEFINE_STRUCT_TESTS(zero, WANT_SUCCESS);
+/* Struct initializers: padding may be left uninitialized. */
+DEFINE_STRUCT_INITIALIZER_TESTS(static);
+DEFINE_STRUCT_INITIALIZER_TESTS(dynamic);
+DEFINE_STRUCT_INITIALIZER_TESTS(runtime);
+DEFINE_STRUCT_INITIALIZER_TESTS(assigned_static);
+DEFINE_STRUCT_INITIALIZER_TESTS(assigned_dynamic);
+DEFINE_STRUCT_TESTS(assigned_copy, XFAIL);
/* No initialization without compiler instrumentation. */
-DEFINE_SCALAR_TESTS(none);
-DEFINE_STRUCT_TESTS(none);
-DEFINE_TEST(user, struct test_user, STRUCT, none);
+DEFINE_SCALAR_TESTS(none, WANT_SUCCESS);
+DEFINE_STRUCT_TESTS(none, WANT_SUCCESS);
+/* Initialization of members with __user attribute. */
+DEFINE_TEST(user, struct test_user, STRUCT, none, WANT_SUCCESS);
/*
* Check two uses through a variable declaration outside either path,
@@ -285,6 +394,10 @@ DEFINE_TEST(user, struct test_user, STRUCT, none);
static int noinline __leaf_switch_none(int path, bool fill)
{
switch (path) {
+ /*
+ * This is intentionally unreachable. To silence the
+ * warning, build with -Wno-switch-unreachable
+ */
uint64_t var;
case 1:
@@ -334,8 +447,8 @@ static noinline __init int leaf_switch_2_none(unsigned long sp, bool fill,
* non-code areas (i.e. in a switch statement before the first "case").
* https://bugs.llvm.org/show_bug.cgi?id=44916
*/
-DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR, 1);
-DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, 1);
+DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR, XFAIL);
+DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, XFAIL);
static int __init test_stackinit_init(void)
{
@@ -361,12 +474,18 @@ static int __init test_stackinit_init(void)
test_structs(zero);
/* Padding here appears to be accidentally always initialized? */
test_structs(dynamic_partial);
+ test_structs(assigned_dynamic_partial);
/* Padding initialization depends on compiler behaviors. */
test_structs(static_partial);
test_structs(static_all);
test_structs(dynamic_all);
test_structs(runtime_partial);
test_structs(runtime_all);
+ test_structs(assigned_static_partial);
+ test_structs(assigned_static_all);
+ test_structs(assigned_dynamic_all);
+ /* Everything fails this since it effectively performs a memcpy(). */
+ test_structs(assigned_copy);
/* STRUCTLEAK_BYREF_ALL should cover everything from here down. */
test_scalars(none);
diff --git a/lib/test_vmalloc.c b/lib/test_vmalloc.c
index 01e9543de566..e14993bc84d2 100644
--- a/lib/test_vmalloc.c
+++ b/lib/test_vmalloc.c
@@ -35,6 +35,9 @@ __param(int, test_repeat_count, 1,
__param(int, test_loop_count, 1000000,
"Set test loop counter");
+__param(int, nr_pages, 0,
+ "Set number of pages for fix_size_alloc_test(default: 1)");
+
__param(int, run_test_mask, INT_MAX,
"Set tests specified in the mask.\n\n"
"\t\tid: 1, name: fix_size_alloc_test\n"
@@ -262,7 +265,7 @@ static int fix_size_alloc_test(void)
int i;
for (i = 0; i < test_loop_count; i++) {
- ptr = vmalloc(3 * PAGE_SIZE);
+ ptr = vmalloc((nr_pages > 0 ? nr_pages:1) * PAGE_SIZE);
if (!ptr)
return -1;
diff --git a/lib/ubsan.c b/lib/ubsan.c
index 26229973049d..bdc380ff5d5c 100644
--- a/lib/ubsan.c
+++ b/lib/ubsan.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
+#include <kunit/test-bug.h>
#include "ubsan.h"
@@ -141,6 +142,8 @@ static void ubsan_prologue(struct source_location *loc, const char *reason)
"========================================\n");
pr_err("UBSAN: %s in %s:%d:%d\n", reason, loc->file_name,
loc->line & LINE_MASK, loc->column & COLUMN_MASK);
+
+ kunit_fail_current_test("%s in %s", reason, loc->file_name);
}
static void ubsan_epilogue(void)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 26c83943748a..3bcb7be03f93 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -17,7 +17,7 @@
* - scnprintf and vscnprintf
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/build_bug.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index cd06dca232c3..4a9d4e27d0d9 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -271,6 +271,14 @@ void wb_wakeup_delayed(struct bdi_writeback *wb)
spin_unlock_bh(&wb->work_lock);
}
+static void wb_update_bandwidth_workfn(struct work_struct *work)
+{
+ struct bdi_writeback *wb = container_of(to_delayed_work(work),
+ struct bdi_writeback, bw_dwork);
+
+ wb_update_bandwidth(wb);
+}
+
/*
* Initial write bandwidth: 100 MB/s
*/
@@ -293,6 +301,7 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
INIT_LIST_HEAD(&wb->b_dirty_time);
spin_lock_init(&wb->list_lock);
+ atomic_set(&wb->writeback_inodes, 0);
wb->bw_time_stamp = jiffies;
wb->balanced_dirty_ratelimit = INIT_BW;
wb->dirty_ratelimit = INIT_BW;
@@ -302,6 +311,7 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
spin_lock_init(&wb->work_lock);
INIT_LIST_HEAD(&wb->work_list);
INIT_DELAYED_WORK(&wb->dwork, wb_workfn);
+ INIT_DELAYED_WORK(&wb->bw_dwork, wb_update_bandwidth_workfn);
wb->dirty_sleep = jiffies;
err = fprop_local_init_percpu(&wb->completions, gfp);
@@ -350,6 +360,7 @@ 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));
+ flush_delayed_work(&wb->bw_dwork);
}
static void wb_exit(struct bdi_writeback *wb)
diff --git a/mm/bootmem_info.c b/mm/bootmem_info.c
index 5b152dba7344..f03f42f426f6 100644
--- a/mm/bootmem_info.c
+++ b/mm/bootmem_info.c
@@ -39,7 +39,7 @@ void put_page_bootmem(struct page *page)
}
#ifndef CONFIG_SPARSEMEM_VMEMMAP
-static void register_page_bootmem_info_section(unsigned long start_pfn)
+static void __init register_page_bootmem_info_section(unsigned long start_pfn)
{
unsigned long mapsize, section_nr, i;
struct mem_section *ms;
@@ -74,7 +74,7 @@ static void register_page_bootmem_info_section(unsigned long start_pfn)
}
#else /* CONFIG_SPARSEMEM_VMEMMAP */
-static void register_page_bootmem_info_section(unsigned long start_pfn)
+static void __init register_page_bootmem_info_section(unsigned long start_pfn)
{
unsigned long mapsize, section_nr, i;
struct mem_section *ms;
diff --git a/mm/compaction.c b/mm/compaction.c
index 621508e0ecd5..fa9b2b598eab 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -2398,7 +2398,7 @@ compact_zone(struct compact_control *cc, struct capture_control *capc)
err = migrate_pages(&cc->migratepages, compaction_alloc,
compaction_free, (unsigned long)cc, cc->mode,
- MR_COMPACTION);
+ MR_COMPACTION, NULL);
trace_mm_compaction_migratepages(cc->nr_migratepages, err,
&cc->migratepages);
@@ -2706,6 +2706,30 @@ static void compact_nodes(void)
*/
unsigned int __read_mostly sysctl_compaction_proactiveness = 20;
+int compaction_proactiveness_sysctl_handler(struct ctl_table *table, int write,
+ void *buffer, size_t *length, loff_t *ppos)
+{
+ int rc, nid;
+
+ rc = proc_dointvec_minmax(table, write, buffer, length, ppos);
+ if (rc)
+ return rc;
+
+ if (write && sysctl_compaction_proactiveness) {
+ for_each_online_node(nid) {
+ pg_data_t *pgdat = NODE_DATA(nid);
+
+ if (pgdat->proactive_compact_trigger)
+ continue;
+
+ pgdat->proactive_compact_trigger = true;
+ wake_up_interruptible(&pgdat->kcompactd_wait);
+ }
+ }
+
+ return 0;
+}
+
/*
* This is the entry point for compacting all nodes via
* /proc/sys/vm/compact_memory
@@ -2750,7 +2774,8 @@ void compaction_unregister_node(struct node *node)
static inline bool kcompactd_work_requested(pg_data_t *pgdat)
{
- return pgdat->kcompactd_max_order > 0 || kthread_should_stop();
+ return pgdat->kcompactd_max_order > 0 || kthread_should_stop() ||
+ pgdat->proactive_compact_trigger;
}
static bool kcompactd_node_suitable(pg_data_t *pgdat)
@@ -2885,7 +2910,8 @@ static int kcompactd(void *p)
{
pg_data_t *pgdat = (pg_data_t *)p;
struct task_struct *tsk = current;
- unsigned int proactive_defer = 0;
+ long default_timeout = msecs_to_jiffies(HPAGE_FRAG_CHECK_INTERVAL_MSEC);
+ long timeout = default_timeout;
const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
@@ -2900,25 +2926,39 @@ static int kcompactd(void *p)
while (!kthread_should_stop()) {
unsigned long pflags;
+ /*
+ * Avoid the unnecessary wakeup for proactive compaction
+ * when it is disabled.
+ */
+ if (!sysctl_compaction_proactiveness)
+ timeout = MAX_SCHEDULE_TIMEOUT;
trace_mm_compaction_kcompactd_sleep(pgdat->node_id);
if (wait_event_freezable_timeout(pgdat->kcompactd_wait,
- kcompactd_work_requested(pgdat),
- msecs_to_jiffies(HPAGE_FRAG_CHECK_INTERVAL_MSEC))) {
+ kcompactd_work_requested(pgdat), timeout) &&
+ !pgdat->proactive_compact_trigger) {
psi_memstall_enter(&pflags);
kcompactd_do_work(pgdat);
psi_memstall_leave(&pflags);
+ /*
+ * Reset the timeout value. The defer timeout from
+ * proactive compaction is lost here but that is fine
+ * as the condition of the zone changing substantionally
+ * then carrying on with the previous defer interval is
+ * not useful.
+ */
+ timeout = default_timeout;
continue;
}
- /* kcompactd wait timeout */
+ /*
+ * Start the proactive work with default timeout. Based
+ * on the fragmentation score, this timeout is updated.
+ */
+ timeout = default_timeout;
if (should_proactive_compact_node(pgdat)) {
unsigned int prev_score, score;
- if (proactive_defer) {
- proactive_defer--;
- continue;
- }
prev_score = fragmentation_score_node(pgdat);
proactive_compact_node(pgdat);
score = fragmentation_score_node(pgdat);
@@ -2926,9 +2966,12 @@ static int kcompactd(void *p)
* Defer proactive compaction if the fragmentation
* score did not go down i.e. no progress made.
*/
- proactive_defer = score < prev_score ?
- 0 : 1 << COMPACT_MAX_DEFER_SHIFT;
+ if (unlikely(score >= prev_score))
+ timeout =
+ default_timeout << COMPACT_MAX_DEFER_SHIFT;
}
+ if (unlikely(pgdat->proactive_compact_trigger))
+ pgdat->proactive_compact_trigger = false;
}
return 0;
diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
index 1c922691aa61..1403639302e4 100644
--- a/mm/debug_vm_pgtable.c
+++ b/mm/debug_vm_pgtable.c
@@ -29,6 +29,8 @@
#include <linux/start_kernel.h>
#include <linux/sched/mm.h>
#include <linux/io.h>
+
+#include <asm/cacheflush.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -58,10 +60,41 @@
#define RANDOM_ORVALUE (GENMASK(BITS_PER_LONG - 1, 0) & ~ARCH_SKIP_MASK)
#define RANDOM_NZVALUE GENMASK(7, 0)
-static void __init pte_basic_tests(unsigned long pfn, int idx)
+struct pgtable_debug_args {
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+
+ pgd_t *pgdp;
+ p4d_t *p4dp;
+ pud_t *pudp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ p4d_t *start_p4dp;
+ pud_t *start_pudp;
+ pmd_t *start_pmdp;
+ pgtable_t start_ptep;
+
+ unsigned long vaddr;
+ pgprot_t page_prot;
+ pgprot_t page_prot_none;
+
+ bool is_contiguous_page;
+ unsigned long pud_pfn;
+ unsigned long pmd_pfn;
+ unsigned long pte_pfn;
+
+ unsigned long fixed_pgd_pfn;
+ unsigned long fixed_p4d_pfn;
+ unsigned long fixed_pud_pfn;
+ unsigned long fixed_pmd_pfn;
+ unsigned long fixed_pte_pfn;
+};
+
+static void __init pte_basic_tests(struct pgtable_debug_args *args, int idx)
{
pgprot_t prot = protection_map[idx];
- pte_t pte = pfn_pte(pfn, prot);
+ pte_t pte = pfn_pte(args->fixed_pte_pfn, prot);
unsigned long val = idx, *ptr = &val;
pr_debug("Validating PTE basic (%pGv)\n", ptr);
@@ -86,53 +119,63 @@ static void __init pte_basic_tests(unsigned long pfn, int idx)
WARN_ON(!pte_dirty(pte_wrprotect(pte_mkdirty(pte))));
}
-static void __init pte_advanced_tests(struct mm_struct *mm,
- struct vm_area_struct *vma, pte_t *ptep,
- unsigned long pfn, unsigned long vaddr,
- pgprot_t prot)
+static void __init pte_advanced_tests(struct pgtable_debug_args *args)
{
+ struct page *page;
pte_t pte;
/*
* Architectures optimize set_pte_at by avoiding TLB flush.
* This requires set_pte_at to be not used to update an
* existing pte entry. Clear pte before we do set_pte_at
+ *
+ * flush_dcache_page() is called after set_pte_at() to clear
+ * PG_arch_1 for the page on ARM64. The page flag isn't cleared
+ * when it's released and page allocation check will fail when
+ * the page is allocated again. For architectures other than ARM64,
+ * the unexpected overhead of cache flushing is acceptable.
*/
+ page = (args->pte_pfn != ULONG_MAX) ? pfn_to_page(args->pte_pfn) : NULL;
+ if (!page)
+ return;
pr_debug("Validating PTE advanced\n");
- pte = pfn_pte(pfn, prot);
- set_pte_at(mm, vaddr, ptep, pte);
- ptep_set_wrprotect(mm, vaddr, ptep);
- pte = ptep_get(ptep);
+ pte = pfn_pte(args->pte_pfn, args->page_prot);
+ set_pte_at(args->mm, args->vaddr, args->ptep, pte);
+ flush_dcache_page(page);
+ ptep_set_wrprotect(args->mm, args->vaddr, args->ptep);
+ pte = ptep_get(args->ptep);
WARN_ON(pte_write(pte));
- ptep_get_and_clear(mm, vaddr, ptep);
- pte = ptep_get(ptep);
+ ptep_get_and_clear(args->mm, args->vaddr, args->ptep);
+ pte = ptep_get(args->ptep);
WARN_ON(!pte_none(pte));
- pte = pfn_pte(pfn, prot);
+ pte = pfn_pte(args->pte_pfn, args->page_prot);
pte = pte_wrprotect(pte);
pte = pte_mkclean(pte);
- set_pte_at(mm, vaddr, ptep, pte);
+ set_pte_at(args->mm, args->vaddr, args->ptep, pte);
+ flush_dcache_page(page);
pte = pte_mkwrite(pte);
pte = pte_mkdirty(pte);
- ptep_set_access_flags(vma, vaddr, ptep, pte, 1);
- pte = ptep_get(ptep);
+ ptep_set_access_flags(args->vma, args->vaddr, args->ptep, pte, 1);
+ pte = ptep_get(args->ptep);
WARN_ON(!(pte_write(pte) && pte_dirty(pte)));
- ptep_get_and_clear_full(mm, vaddr, ptep, 1);
- pte = ptep_get(ptep);
+ ptep_get_and_clear_full(args->mm, args->vaddr, args->ptep, 1);
+ pte = ptep_get(args->ptep);
WARN_ON(!pte_none(pte));
- pte = pfn_pte(pfn, prot);
+ pte = pfn_pte(args->pte_pfn, args->page_prot);
pte = pte_mkyoung(pte);
- set_pte_at(mm, vaddr, ptep, pte);
- ptep_test_and_clear_young(vma, vaddr, ptep);
- pte = ptep_get(ptep);
+ set_pte_at(args->mm, args->vaddr, args->ptep, pte);
+ flush_dcache_page(page);
+ ptep_test_and_clear_young(args->vma, args->vaddr, args->ptep);
+ pte = ptep_get(args->ptep);
WARN_ON(pte_young(pte));
}
-static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot)
+static void __init pte_savedwrite_tests(struct pgtable_debug_args *args)
{
- pte_t pte = pfn_pte(pfn, prot);
+ pte_t pte = pfn_pte(args->fixed_pte_pfn, args->page_prot_none);
if (!IS_ENABLED(CONFIG_NUMA_BALANCING))
return;
@@ -143,7 +186,7 @@ static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot)
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static void __init pmd_basic_tests(unsigned long pfn, int idx)
+static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx)
{
pgprot_t prot = protection_map[idx];
unsigned long val = idx, *ptr = &val;
@@ -153,7 +196,7 @@ static void __init pmd_basic_tests(unsigned long pfn, int idx)
return;
pr_debug("Validating PMD basic (%pGv)\n", ptr);
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->fixed_pmd_pfn, prot);
/*
* This test needs to be executed after the given page table entry
@@ -181,57 +224,70 @@ static void __init pmd_basic_tests(unsigned long pfn, int idx)
WARN_ON(!pmd_bad(pmd_mkhuge(pmd)));
}
-static void __init pmd_advanced_tests(struct mm_struct *mm,
- struct vm_area_struct *vma, pmd_t *pmdp,
- unsigned long pfn, unsigned long vaddr,
- pgprot_t prot, pgtable_t pgtable)
+static void __init pmd_advanced_tests(struct pgtable_debug_args *args)
{
+ struct page *page;
pmd_t pmd;
+ unsigned long vaddr = args->vaddr;
if (!has_transparent_hugepage())
return;
+ page = (args->pmd_pfn != ULONG_MAX) ? pfn_to_page(args->pmd_pfn) : NULL;
+ if (!page)
+ return;
+
+ /*
+ * flush_dcache_page() is called after set_pmd_at() to clear
+ * PG_arch_1 for the page on ARM64. The page flag isn't cleared
+ * when it's released and page allocation check will fail when
+ * the page is allocated again. For architectures other than ARM64,
+ * the unexpected overhead of cache flushing is acceptable.
+ */
pr_debug("Validating PMD advanced\n");
/* Align the address wrt HPAGE_PMD_SIZE */
vaddr &= HPAGE_PMD_MASK;
- pgtable_trans_huge_deposit(mm, pmdp, pgtable);
+ pgtable_trans_huge_deposit(args->mm, args->pmdp, args->start_ptep);
- pmd = pfn_pmd(pfn, prot);
- set_pmd_at(mm, vaddr, pmdp, pmd);
- pmdp_set_wrprotect(mm, vaddr, pmdp);
- pmd = READ_ONCE(*pmdp);
+ pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
+ set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
+ flush_dcache_page(page);
+ pmdp_set_wrprotect(args->mm, vaddr, args->pmdp);
+ pmd = READ_ONCE(*args->pmdp);
WARN_ON(pmd_write(pmd));
- pmdp_huge_get_and_clear(mm, vaddr, pmdp);
- pmd = READ_ONCE(*pmdp);
+ pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
+ pmd = READ_ONCE(*args->pmdp);
WARN_ON(!pmd_none(pmd));
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
pmd = pmd_wrprotect(pmd);
pmd = pmd_mkclean(pmd);
- set_pmd_at(mm, vaddr, pmdp, pmd);
+ set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
+ flush_dcache_page(page);
pmd = pmd_mkwrite(pmd);
pmd = pmd_mkdirty(pmd);
- pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
- pmd = READ_ONCE(*pmdp);
+ pmdp_set_access_flags(args->vma, vaddr, args->pmdp, pmd, 1);
+ pmd = READ_ONCE(*args->pmdp);
WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
- pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
- pmd = READ_ONCE(*pmdp);
+ pmdp_huge_get_and_clear_full(args->vma, vaddr, args->pmdp, 1);
+ pmd = READ_ONCE(*args->pmdp);
WARN_ON(!pmd_none(pmd));
- pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
+ pmd = pmd_mkhuge(pfn_pmd(args->pmd_pfn, args->page_prot));
pmd = pmd_mkyoung(pmd);
- set_pmd_at(mm, vaddr, pmdp, pmd);
- pmdp_test_and_clear_young(vma, vaddr, pmdp);
- pmd = READ_ONCE(*pmdp);
+ set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
+ flush_dcache_page(page);
+ pmdp_test_and_clear_young(args->vma, vaddr, args->pmdp);
+ pmd = READ_ONCE(*args->pmdp);
WARN_ON(pmd_young(pmd));
/* Clear the pte entries */
- pmdp_huge_get_and_clear(mm, vaddr, pmdp);
- pgtable = pgtable_trans_huge_withdraw(mm, pmdp);
+ pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
+ pgtable_trans_huge_withdraw(args->mm, args->pmdp);
}
-static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot)
+static void __init pmd_leaf_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
@@ -239,7 +295,7 @@ static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PMD leaf\n");
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->fixed_pmd_pfn, args->page_prot);
/*
* PMD based THP is a leaf entry.
@@ -248,7 +304,7 @@ static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot)
WARN_ON(!pmd_leaf(pmd));
}
-static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot)
+static void __init pmd_savedwrite_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
@@ -259,13 +315,13 @@ static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PMD saved write\n");
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->fixed_pmd_pfn, args->page_prot_none);
WARN_ON(!pmd_savedwrite(pmd_mk_savedwrite(pmd_clear_savedwrite(pmd))));
WARN_ON(pmd_savedwrite(pmd_clear_savedwrite(pmd_mk_savedwrite(pmd))));
}
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
-static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx)
+static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx)
{
pgprot_t prot = protection_map[idx];
unsigned long val = idx, *ptr = &val;
@@ -275,7 +331,7 @@ static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int
return;
pr_debug("Validating PUD basic (%pGv)\n", ptr);
- pud = pfn_pud(pfn, prot);
+ pud = pfn_pud(args->fixed_pud_pfn, prot);
/*
* This test needs to be executed after the given page table entry
@@ -296,7 +352,7 @@ static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int
WARN_ON(pud_dirty(pud_wrprotect(pud_mkclean(pud))));
WARN_ON(!pud_dirty(pud_wrprotect(pud_mkdirty(pud))));
- if (mm_pmd_folded(mm))
+ if (mm_pmd_folded(args->mm))
return;
/*
@@ -306,58 +362,71 @@ static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int
WARN_ON(!pud_bad(pud_mkhuge(pud)));
}
-static void __init pud_advanced_tests(struct mm_struct *mm,
- struct vm_area_struct *vma, pud_t *pudp,
- unsigned long pfn, unsigned long vaddr,
- pgprot_t prot)
+static void __init pud_advanced_tests(struct pgtable_debug_args *args)
{
+ struct page *page;
+ unsigned long vaddr = args->vaddr;
pud_t pud;
if (!has_transparent_hugepage())
return;
+ page = (args->pud_pfn != ULONG_MAX) ? pfn_to_page(args->pud_pfn) : NULL;
+ if (!page)
+ return;
+
+ /*
+ * flush_dcache_page() is called after set_pud_at() to clear
+ * PG_arch_1 for the page on ARM64. The page flag isn't cleared
+ * when it's released and page allocation check will fail when
+ * the page is allocated again. For architectures other than ARM64,
+ * the unexpected overhead of cache flushing is acceptable.
+ */
pr_debug("Validating PUD advanced\n");
/* Align the address wrt HPAGE_PUD_SIZE */
vaddr &= HPAGE_PUD_MASK;
- pud = pfn_pud(pfn, prot);
- set_pud_at(mm, vaddr, pudp, pud);
- pudp_set_wrprotect(mm, vaddr, pudp);
- pud = READ_ONCE(*pudp);
+ pud = pfn_pud(args->pud_pfn, args->page_prot);
+ set_pud_at(args->mm, vaddr, args->pudp, pud);
+ flush_dcache_page(page);
+ pudp_set_wrprotect(args->mm, vaddr, args->pudp);
+ pud = READ_ONCE(*args->pudp);
WARN_ON(pud_write(pud));
#ifndef __PAGETABLE_PMD_FOLDED
- pudp_huge_get_and_clear(mm, vaddr, pudp);
- pud = READ_ONCE(*pudp);
+ pudp_huge_get_and_clear(args->mm, vaddr, args->pudp);
+ pud = READ_ONCE(*args->pudp);
WARN_ON(!pud_none(pud));
#endif /* __PAGETABLE_PMD_FOLDED */
- pud = pfn_pud(pfn, prot);
+ pud = pfn_pud(args->pud_pfn, args->page_prot);
pud = pud_wrprotect(pud);
pud = pud_mkclean(pud);
- set_pud_at(mm, vaddr, pudp, pud);
+ set_pud_at(args->mm, vaddr, args->pudp, pud);
+ flush_dcache_page(page);
pud = pud_mkwrite(pud);
pud = pud_mkdirty(pud);
- pudp_set_access_flags(vma, vaddr, pudp, pud, 1);
- pud = READ_ONCE(*pudp);
+ pudp_set_access_flags(args->vma, vaddr, args->pudp, pud, 1);
+ pud = READ_ONCE(*args->pudp);
WARN_ON(!(pud_write(pud) && pud_dirty(pud)));
#ifndef __PAGETABLE_PMD_FOLDED
- pudp_huge_get_and_clear_full(mm, vaddr, pudp, 1);
- pud = READ_ONCE(*pudp);
+ pudp_huge_get_and_clear_full(args->mm, vaddr, args->pudp, 1);
+ pud = READ_ONCE(*args->pudp);
WARN_ON(!pud_none(pud));
#endif /* __PAGETABLE_PMD_FOLDED */
- pud = pfn_pud(pfn, prot);
+ pud = pfn_pud(args->pud_pfn, args->page_prot);
pud = pud_mkyoung(pud);
- set_pud_at(mm, vaddr, pudp, pud);
- pudp_test_and_clear_young(vma, vaddr, pudp);
- pud = READ_ONCE(*pudp);
+ set_pud_at(args->mm, vaddr, args->pudp, pud);
+ flush_dcache_page(page);
+ pudp_test_and_clear_young(args->vma, vaddr, args->pudp);
+ pud = READ_ONCE(*args->pudp);
WARN_ON(pud_young(pud));
- pudp_huge_get_and_clear(mm, vaddr, pudp);
+ pudp_huge_get_and_clear(args->mm, vaddr, args->pudp);
}
-static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot)
+static void __init pud_leaf_tests(struct pgtable_debug_args *args)
{
pud_t pud;
@@ -365,7 +434,7 @@ static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PUD leaf\n");
- pud = pfn_pud(pfn, prot);
+ pud = pfn_pud(args->fixed_pud_pfn, args->page_prot);
/*
* PUD based THP is a leaf entry.
*/
@@ -373,41 +442,26 @@ static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot)
WARN_ON(!pud_leaf(pud));
}
#else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
-static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx) { }
-static void __init pud_advanced_tests(struct mm_struct *mm,
- struct vm_area_struct *vma, pud_t *pudp,
- unsigned long pfn, unsigned long vaddr,
- pgprot_t prot)
-{
-}
-static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }
+static void __init pud_advanced_tests(struct pgtable_debug_args *args) { }
+static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
#else /* !CONFIG_TRANSPARENT_HUGEPAGE */
-static void __init pmd_basic_tests(unsigned long pfn, int idx) { }
-static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx) { }
-static void __init pmd_advanced_tests(struct mm_struct *mm,
- struct vm_area_struct *vma, pmd_t *pmdp,
- unsigned long pfn, unsigned long vaddr,
- pgprot_t prot, pgtable_t pgtable)
-{
-}
-static void __init pud_advanced_tests(struct mm_struct *mm,
- struct vm_area_struct *vma, pud_t *pudp,
- unsigned long pfn, unsigned long vaddr,
- pgprot_t prot)
-{
-}
-static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot) { }
-static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot) { }
-static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx) { }
+static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }
+static void __init pmd_advanced_tests(struct pgtable_debug_args *args) { }
+static void __init pud_advanced_tests(struct pgtable_debug_args *args) { }
+static void __init pmd_leaf_tests(struct pgtable_debug_args *args) { }
+static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }
+static void __init pmd_savedwrite_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
-static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
+static void __init pmd_huge_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
- if (!arch_vmap_pmd_supported(prot))
+ if (!arch_vmap_pmd_supported(args->page_prot))
return;
pr_debug("Validating PMD huge\n");
@@ -415,18 +469,18 @@ static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
* X86 defined pmd_set_huge() verifies that the given
* PMD is not a populated non-leaf entry.
*/
- WRITE_ONCE(*pmdp, __pmd(0));
- WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
- WARN_ON(!pmd_clear_huge(pmdp));
- pmd = READ_ONCE(*pmdp);
+ WRITE_ONCE(*args->pmdp, __pmd(0));
+ WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn), args->page_prot));
+ WARN_ON(!pmd_clear_huge(args->pmdp));
+ pmd = READ_ONCE(*args->pmdp);
WARN_ON(!pmd_none(pmd));
}
-static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
+static void __init pud_huge_tests(struct pgtable_debug_args *args)
{
pud_t pud;
- if (!arch_vmap_pud_supported(prot))
+ if (!arch_vmap_pud_supported(args->page_prot))
return;
pr_debug("Validating PUD huge\n");
@@ -434,18 +488,18 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
* X86 defined pud_set_huge() verifies that the given
* PUD is not a populated non-leaf entry.
*/
- WRITE_ONCE(*pudp, __pud(0));
- WARN_ON(!pud_set_huge(pudp, __pfn_to_phys(pfn), prot));
- WARN_ON(!pud_clear_huge(pudp));
- pud = READ_ONCE(*pudp);
+ WRITE_ONCE(*args->pudp, __pud(0));
+ WARN_ON(!pud_set_huge(args->pudp, __pfn_to_phys(args->fixed_pud_pfn), args->page_prot));
+ WARN_ON(!pud_clear_huge(args->pudp));
+ pud = READ_ONCE(*args->pudp);
WARN_ON(!pud_none(pud));
}
#else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
-static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot) { }
-static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) { }
+static void __init pmd_huge_tests(struct pgtable_debug_args *args) { }
+static void __init pud_huge_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
-static void __init p4d_basic_tests(unsigned long pfn, pgprot_t prot)
+static void __init p4d_basic_tests(struct pgtable_debug_args *args)
{
p4d_t p4d;
@@ -454,7 +508,7 @@ static void __init p4d_basic_tests(unsigned long pfn, pgprot_t prot)
WARN_ON(!p4d_same(p4d, p4d));
}
-static void __init pgd_basic_tests(unsigned long pfn, pgprot_t prot)
+static void __init pgd_basic_tests(struct pgtable_debug_args *args)
{
pgd_t pgd;
@@ -464,27 +518,26 @@ static void __init pgd_basic_tests(unsigned long pfn, pgprot_t prot)
}
#ifndef __PAGETABLE_PUD_FOLDED
-static void __init pud_clear_tests(struct mm_struct *mm, pud_t *pudp)
+static void __init pud_clear_tests(struct pgtable_debug_args *args)
{
- pud_t pud = READ_ONCE(*pudp);
+ pud_t pud = READ_ONCE(*args->pudp);
- if (mm_pmd_folded(mm))
+ if (mm_pmd_folded(args->mm))
return;
pr_debug("Validating PUD clear\n");
pud = __pud(pud_val(pud) | RANDOM_ORVALUE);
- WRITE_ONCE(*pudp, pud);
- pud_clear(pudp);
- pud = READ_ONCE(*pudp);
+ WRITE_ONCE(*args->pudp, pud);
+ pud_clear(args->pudp);
+ pud = READ_ONCE(*args->pudp);
WARN_ON(!pud_none(pud));
}
-static void __init pud_populate_tests(struct mm_struct *mm, pud_t *pudp,
- pmd_t *pmdp)
+static void __init pud_populate_tests(struct pgtable_debug_args *args)
{
pud_t pud;
- if (mm_pmd_folded(mm))
+ if (mm_pmd_folded(args->mm))
return;
pr_debug("Validating PUD populate\n");
@@ -492,40 +545,36 @@ static void __init pud_populate_tests(struct mm_struct *mm, pud_t *pudp,
* This entry points to next level page table page.
* Hence this must not qualify as pud_bad().
*/
- pud_populate(mm, pudp, pmdp);
- pud = READ_ONCE(*pudp);
+ pud_populate(args->mm, args->pudp, args->start_pmdp);
+ pud = READ_ONCE(*args->pudp);
WARN_ON(pud_bad(pud));
}
#else /* !__PAGETABLE_PUD_FOLDED */
-static void __init pud_clear_tests(struct mm_struct *mm, pud_t *pudp) { }
-static void __init pud_populate_tests(struct mm_struct *mm, pud_t *pudp,
- pmd_t *pmdp)
-{
-}
+static void __init pud_clear_tests(struct pgtable_debug_args *args) { }
+static void __init pud_populate_tests(struct pgtable_debug_args *args) { }
#endif /* PAGETABLE_PUD_FOLDED */
#ifndef __PAGETABLE_P4D_FOLDED
-static void __init p4d_clear_tests(struct mm_struct *mm, p4d_t *p4dp)
+static void __init p4d_clear_tests(struct pgtable_debug_args *args)
{
- p4d_t p4d = READ_ONCE(*p4dp);
+ p4d_t p4d = READ_ONCE(*args->p4dp);
- if (mm_pud_folded(mm))
+ if (mm_pud_folded(args->mm))
return;
pr_debug("Validating P4D clear\n");
p4d = __p4d(p4d_val(p4d) | RANDOM_ORVALUE);
- WRITE_ONCE(*p4dp, p4d);
- p4d_clear(p4dp);
- p4d = READ_ONCE(*p4dp);
+ WRITE_ONCE(*args->p4dp, p4d);
+ p4d_clear(args->p4dp);
+ p4d = READ_ONCE(*args->p4dp);
WARN_ON(!p4d_none(p4d));
}
-static void __init p4d_populate_tests(struct mm_struct *mm, p4d_t *p4dp,
- pud_t *pudp)
+static void __init p4d_populate_tests(struct pgtable_debug_args *args)
{
p4d_t p4d;
- if (mm_pud_folded(mm))
+ if (mm_pud_folded(args->mm))
return;
pr_debug("Validating P4D populate\n");
@@ -533,34 +582,33 @@ static void __init p4d_populate_tests(struct mm_struct *mm, p4d_t *p4dp,
* This entry points to next level page table page.
* Hence this must not qualify as p4d_bad().
*/
- pud_clear(pudp);
- p4d_clear(p4dp);
- p4d_populate(mm, p4dp, pudp);
- p4d = READ_ONCE(*p4dp);
+ pud_clear(args->pudp);
+ p4d_clear(args->p4dp);
+ p4d_populate(args->mm, args->p4dp, args->start_pudp);
+ p4d = READ_ONCE(*args->p4dp);
WARN_ON(p4d_bad(p4d));
}
-static void __init pgd_clear_tests(struct mm_struct *mm, pgd_t *pgdp)
+static void __init pgd_clear_tests(struct pgtable_debug_args *args)
{
- pgd_t pgd = READ_ONCE(*pgdp);
+ pgd_t pgd = READ_ONCE(*(args->pgdp));
- if (mm_p4d_folded(mm))
+ if (mm_p4d_folded(args->mm))
return;
pr_debug("Validating PGD clear\n");
pgd = __pgd(pgd_val(pgd) | RANDOM_ORVALUE);
- WRITE_ONCE(*pgdp, pgd);
- pgd_clear(pgdp);
- pgd = READ_ONCE(*pgdp);
+ WRITE_ONCE(*args->pgdp, pgd);
+ pgd_clear(args->pgdp);
+ pgd = READ_ONCE(*args->pgdp);
WARN_ON(!pgd_none(pgd));
}
-static void __init pgd_populate_tests(struct mm_struct *mm, pgd_t *pgdp,
- p4d_t *p4dp)
+static void __init pgd_populate_tests(struct pgtable_debug_args *args)
{
pgd_t pgd;
- if (mm_p4d_folded(mm))
+ if (mm_p4d_folded(args->mm))
return;
pr_debug("Validating PGD populate\n");
@@ -568,56 +616,60 @@ static void __init pgd_populate_tests(struct mm_struct *mm, pgd_t *pgdp,
* This entry points to next level page table page.
* Hence this must not qualify as pgd_bad().
*/
- p4d_clear(p4dp);
- pgd_clear(pgdp);
- pgd_populate(mm, pgdp, p4dp);
- pgd = READ_ONCE(*pgdp);
+ p4d_clear(args->p4dp);
+ pgd_clear(args->pgdp);
+ pgd_populate(args->mm, args->pgdp, args->start_p4dp);
+ pgd = READ_ONCE(*args->pgdp);
WARN_ON(pgd_bad(pgd));
}
#else /* !__PAGETABLE_P4D_FOLDED */
-static void __init p4d_clear_tests(struct mm_struct *mm, p4d_t *p4dp) { }
-static void __init pgd_clear_tests(struct mm_struct *mm, pgd_t *pgdp) { }
-static void __init p4d_populate_tests(struct mm_struct *mm, p4d_t *p4dp,
- pud_t *pudp)
-{
-}
-static void __init pgd_populate_tests(struct mm_struct *mm, pgd_t *pgdp,
- p4d_t *p4dp)
-{
-}
+static void __init p4d_clear_tests(struct pgtable_debug_args *args) { }
+static void __init pgd_clear_tests(struct pgtable_debug_args *args) { }
+static void __init p4d_populate_tests(struct pgtable_debug_args *args) { }
+static void __init pgd_populate_tests(struct pgtable_debug_args *args) { }
#endif /* PAGETABLE_P4D_FOLDED */
-static void __init pte_clear_tests(struct mm_struct *mm, pte_t *ptep,
- unsigned long pfn, unsigned long vaddr,
- pgprot_t prot)
+static void __init pte_clear_tests(struct pgtable_debug_args *args)
{
- pte_t pte = pfn_pte(pfn, prot);
+ struct page *page;
+ pte_t pte = pfn_pte(args->pte_pfn, args->page_prot);
+
+ page = (args->pte_pfn != ULONG_MAX) ? pfn_to_page(args->pte_pfn) : NULL;
+ if (!page)
+ return;
+ /*
+ * flush_dcache_page() is called after set_pte_at() to clear
+ * PG_arch_1 for the page on ARM64. The page flag isn't cleared
+ * when it's released and page allocation check will fail when
+ * the page is allocated again. For architectures other than ARM64,
+ * the unexpected overhead of cache flushing is acceptable.
+ */
pr_debug("Validating PTE clear\n");
#ifndef CONFIG_RISCV
pte = __pte(pte_val(pte) | RANDOM_ORVALUE);
#endif
- set_pte_at(mm, vaddr, ptep, pte);
+ set_pte_at(args->mm, args->vaddr, args->ptep, pte);
+ flush_dcache_page(page);
barrier();
- pte_clear(mm, vaddr, ptep);
- pte = ptep_get(ptep);
+ pte_clear(args->mm, args->vaddr, args->ptep);
+ pte = ptep_get(args->ptep);
WARN_ON(!pte_none(pte));
}
-static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp)
+static void __init pmd_clear_tests(struct pgtable_debug_args *args)
{
- pmd_t pmd = READ_ONCE(*pmdp);
+ pmd_t pmd = READ_ONCE(*args->pmdp);
pr_debug("Validating PMD clear\n");
pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE);
- WRITE_ONCE(*pmdp, pmd);
- pmd_clear(pmdp);
- pmd = READ_ONCE(*pmdp);
+ WRITE_ONCE(*args->pmdp, pmd);
+ pmd_clear(args->pmdp);
+ pmd = READ_ONCE(*args->pmdp);
WARN_ON(!pmd_none(pmd));
}
-static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
- pgtable_t pgtable)
+static void __init pmd_populate_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
@@ -626,14 +678,14 @@ static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
* This entry points to next level page table page.
* Hence this must not qualify as pmd_bad().
*/
- pmd_populate(mm, pmdp, pgtable);
- pmd = READ_ONCE(*pmdp);
+ pmd_populate(args->mm, args->pmdp, args->start_ptep);
+ pmd = READ_ONCE(*args->pmdp);
WARN_ON(pmd_bad(pmd));
}
-static void __init pte_special_tests(unsigned long pfn, pgprot_t prot)
+static void __init pte_special_tests(struct pgtable_debug_args *args)
{
- pte_t pte = pfn_pte(pfn, prot);
+ pte_t pte = pfn_pte(args->fixed_pte_pfn, args->page_prot);
if (!IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL))
return;
@@ -642,9 +694,9 @@ static void __init pte_special_tests(unsigned long pfn, pgprot_t prot)
WARN_ON(!pte_special(pte_mkspecial(pte)));
}
-static void __init pte_protnone_tests(unsigned long pfn, pgprot_t prot)
+static void __init pte_protnone_tests(struct pgtable_debug_args *args)
{
- pte_t pte = pfn_pte(pfn, prot);
+ pte_t pte = pfn_pte(args->fixed_pte_pfn, args->page_prot_none);
if (!IS_ENABLED(CONFIG_NUMA_BALANCING))
return;
@@ -655,7 +707,7 @@ static void __init pte_protnone_tests(unsigned long pfn, pgprot_t prot)
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static void __init pmd_protnone_tests(unsigned long pfn, pgprot_t prot)
+static void __init pmd_protnone_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
@@ -666,25 +718,25 @@ static void __init pmd_protnone_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PMD protnone\n");
- pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
+ pmd = pmd_mkhuge(pfn_pmd(args->fixed_pmd_pfn, args->page_prot_none));
WARN_ON(!pmd_protnone(pmd));
WARN_ON(!pmd_present(pmd));
}
#else /* !CONFIG_TRANSPARENT_HUGEPAGE */
-static void __init pmd_protnone_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pmd_protnone_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#ifdef CONFIG_ARCH_HAS_PTE_DEVMAP
-static void __init pte_devmap_tests(unsigned long pfn, pgprot_t prot)
+static void __init pte_devmap_tests(struct pgtable_debug_args *args)
{
- pte_t pte = pfn_pte(pfn, prot);
+ pte_t pte = pfn_pte(args->fixed_pte_pfn, args->page_prot);
pr_debug("Validating PTE devmap\n");
WARN_ON(!pte_devmap(pte_mkdevmap(pte)));
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot)
+static void __init pmd_devmap_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
@@ -692,12 +744,12 @@ static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PMD devmap\n");
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->fixed_pmd_pfn, args->page_prot);
WARN_ON(!pmd_devmap(pmd_mkdevmap(pmd)));
}
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
-static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot)
+static void __init pud_devmap_tests(struct pgtable_debug_args *args)
{
pud_t pud;
@@ -705,25 +757,25 @@ static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PUD devmap\n");
- pud = pfn_pud(pfn, prot);
+ pud = pfn_pud(args->fixed_pud_pfn, args->page_prot);
WARN_ON(!pud_devmap(pud_mkdevmap(pud)));
}
#else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
-static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pud_devmap_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
#else /* CONFIG_TRANSPARENT_HUGEPAGE */
-static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot) { }
-static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pmd_devmap_tests(struct pgtable_debug_args *args) { }
+static void __init pud_devmap_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#else
-static void __init pte_devmap_tests(unsigned long pfn, pgprot_t prot) { }
-static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot) { }
-static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pte_devmap_tests(struct pgtable_debug_args *args) { }
+static void __init pmd_devmap_tests(struct pgtable_debug_args *args) { }
+static void __init pud_devmap_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_ARCH_HAS_PTE_DEVMAP */
-static void __init pte_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
+static void __init pte_soft_dirty_tests(struct pgtable_debug_args *args)
{
- pte_t pte = pfn_pte(pfn, prot);
+ pte_t pte = pfn_pte(args->fixed_pte_pfn, args->page_prot);
if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY))
return;
@@ -733,9 +785,9 @@ static void __init pte_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
WARN_ON(pte_soft_dirty(pte_clear_soft_dirty(pte)));
}
-static void __init pte_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
+static void __init pte_swap_soft_dirty_tests(struct pgtable_debug_args *args)
{
- pte_t pte = pfn_pte(pfn, prot);
+ pte_t pte = pfn_pte(args->fixed_pte_pfn, args->page_prot);
if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY))
return;
@@ -746,7 +798,7 @@ static void __init pte_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static void __init pmd_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
+static void __init pmd_soft_dirty_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
@@ -757,12 +809,12 @@ static void __init pmd_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PMD soft dirty\n");
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->fixed_pmd_pfn, args->page_prot);
WARN_ON(!pmd_soft_dirty(pmd_mksoft_dirty(pmd)));
WARN_ON(pmd_soft_dirty(pmd_clear_soft_dirty(pmd)));
}
-static void __init pmd_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
+static void __init pmd_swap_soft_dirty_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
@@ -774,31 +826,29 @@ static void __init pmd_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PMD swap soft dirty\n");
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->fixed_pmd_pfn, args->page_prot);
WARN_ON(!pmd_swp_soft_dirty(pmd_swp_mksoft_dirty(pmd)));
WARN_ON(pmd_swp_soft_dirty(pmd_swp_clear_soft_dirty(pmd)));
}
#else /* !CONFIG_TRANSPARENT_HUGEPAGE */
-static void __init pmd_soft_dirty_tests(unsigned long pfn, pgprot_t prot) { }
-static void __init pmd_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
-{
-}
+static void __init pmd_soft_dirty_tests(struct pgtable_debug_args *args) { }
+static void __init pmd_swap_soft_dirty_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
-static void __init pte_swap_tests(unsigned long pfn, pgprot_t prot)
+static void __init pte_swap_tests(struct pgtable_debug_args *args)
{
swp_entry_t swp;
pte_t pte;
pr_debug("Validating PTE swap\n");
- pte = pfn_pte(pfn, prot);
+ pte = pfn_pte(args->fixed_pte_pfn, args->page_prot);
swp = __pte_to_swp_entry(pte);
pte = __swp_entry_to_pte(swp);
- WARN_ON(pfn != pte_pfn(pte));
+ WARN_ON(args->fixed_pte_pfn != pte_pfn(pte));
}
#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
-static void __init pmd_swap_tests(unsigned long pfn, pgprot_t prot)
+static void __init pmd_swap_tests(struct pgtable_debug_args *args)
{
swp_entry_t swp;
pmd_t pmd;
@@ -807,16 +857,16 @@ static void __init pmd_swap_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PMD swap\n");
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->fixed_pmd_pfn, args->page_prot);
swp = __pmd_to_swp_entry(pmd);
pmd = __swp_entry_to_pmd(swp);
- WARN_ON(pfn != pmd_pfn(pmd));
+ WARN_ON(args->fixed_pmd_pfn != pmd_pfn(pmd));
}
#else /* !CONFIG_ARCH_ENABLE_THP_MIGRATION */
-static void __init pmd_swap_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pmd_swap_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_ARCH_ENABLE_THP_MIGRATION */
-static void __init swap_migration_tests(void)
+static void __init swap_migration_tests(struct pgtable_debug_args *args)
{
struct page *page;
swp_entry_t swp;
@@ -824,19 +874,18 @@ static void __init swap_migration_tests(void)
if (!IS_ENABLED(CONFIG_MIGRATION))
return;
- pr_debug("Validating swap migration\n");
/*
* swap_migration_tests() requires a dedicated page as it needs to
* be locked before creating a migration entry from it. Locking the
* page that actually maps kernel text ('start_kernel') can be real
- * problematic. Lets allocate a dedicated page explicitly for this
- * purpose that will be freed subsequently.
+ * problematic. Lets use the allocated page explicitly for this
+ * purpose.
*/
- page = alloc_page(GFP_KERNEL);
- if (!page) {
- pr_err("page allocation failed\n");
+ page = (args->pte_pfn != ULONG_MAX) ? pfn_to_page(args->pte_pfn) : NULL;
+ if (!page)
return;
- }
+
+ pr_debug("Validating swap migration\n");
/*
* make_migration_entry() expects given page to be
@@ -855,11 +904,10 @@ static void __init swap_migration_tests(void)
WARN_ON(!is_migration_entry(swp));
WARN_ON(is_writable_migration_entry(swp));
__ClearPageLocked(page);
- __free_page(page);
}
#ifdef CONFIG_HUGETLB_PAGE
-static void __init hugetlb_basic_tests(unsigned long pfn, pgprot_t prot)
+static void __init hugetlb_basic_tests(struct pgtable_debug_args *args)
{
struct page *page;
pte_t pte;
@@ -869,25 +917,25 @@ static void __init hugetlb_basic_tests(unsigned long pfn, pgprot_t prot)
* Accessing the page associated with the pfn is safe here,
* as it was previously derived from a real kernel symbol.
*/
- page = pfn_to_page(pfn);
- pte = mk_huge_pte(page, prot);
+ page = pfn_to_page(args->fixed_pmd_pfn);
+ pte = mk_huge_pte(page, args->page_prot);
WARN_ON(!huge_pte_dirty(huge_pte_mkdirty(pte)));
WARN_ON(!huge_pte_write(huge_pte_mkwrite(huge_pte_wrprotect(pte))));
WARN_ON(huge_pte_write(huge_pte_wrprotect(huge_pte_mkwrite(pte))));
#ifdef CONFIG_ARCH_WANT_GENERAL_HUGETLB
- pte = pfn_pte(pfn, prot);
+ pte = pfn_pte(args->fixed_pmd_pfn, args->page_prot);
WARN_ON(!pte_huge(pte_mkhuge(pte)));
#endif /* CONFIG_ARCH_WANT_GENERAL_HUGETLB */
}
#else /* !CONFIG_HUGETLB_PAGE */
-static void __init hugetlb_basic_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init hugetlb_basic_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_HUGETLB_PAGE */
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static void __init pmd_thp_tests(unsigned long pfn, pgprot_t prot)
+static void __init pmd_thp_tests(struct pgtable_debug_args *args)
{
pmd_t pmd;
@@ -906,7 +954,7 @@ static void __init pmd_thp_tests(unsigned long pfn, pgprot_t prot)
* needs to return true. pmd_present() should be true whenever
* pmd_trans_huge() returns true.
*/
- pmd = pfn_pmd(pfn, prot);
+ pmd = pfn_pmd(args->fixed_pmd_pfn, args->page_prot);
WARN_ON(!pmd_trans_huge(pmd_mkhuge(pmd)));
#ifndef __HAVE_ARCH_PMDP_INVALIDATE
@@ -916,7 +964,7 @@ static void __init pmd_thp_tests(unsigned long pfn, pgprot_t prot)
}
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
-static void __init pud_thp_tests(unsigned long pfn, pgprot_t prot)
+static void __init pud_thp_tests(struct pgtable_debug_args *args)
{
pud_t pud;
@@ -924,7 +972,7 @@ static void __init pud_thp_tests(unsigned long pfn, pgprot_t prot)
return;
pr_debug("Validating PUD based THP\n");
- pud = pfn_pud(pfn, prot);
+ pud = pfn_pud(args->fixed_pud_pfn, args->page_prot);
WARN_ON(!pud_trans_huge(pud_mkhuge(pud)));
/*
@@ -936,11 +984,11 @@ static void __init pud_thp_tests(unsigned long pfn, pgprot_t prot)
*/
}
#else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
-static void __init pud_thp_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pud_thp_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
#else /* !CONFIG_TRANSPARENT_HUGEPAGE */
-static void __init pmd_thp_tests(unsigned long pfn, pgprot_t prot) { }
-static void __init pud_thp_tests(unsigned long pfn, pgprot_t prot) { }
+static void __init pmd_thp_tests(struct pgtable_debug_args *args) { }
+static void __init pud_thp_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
static unsigned long __init get_random_vaddr(void)
@@ -955,43 +1003,179 @@ static unsigned long __init get_random_vaddr(void)
return random_vaddr;
}
-static int __init debug_vm_pgtable(void)
+static void __init destroy_args(struct pgtable_debug_args *args)
{
- struct vm_area_struct *vma;
- struct mm_struct *mm;
- pgd_t *pgdp;
- p4d_t *p4dp, *saved_p4dp;
- pud_t *pudp, *saved_pudp;
- pmd_t *pmdp, *saved_pmdp, pmd;
- pte_t *ptep;
- pgtable_t saved_ptep;
- pgprot_t prot, protnone;
- phys_addr_t paddr;
- unsigned long vaddr, pte_aligned, pmd_aligned;
- unsigned long pud_aligned, p4d_aligned, pgd_aligned;
- spinlock_t *ptl = NULL;
- int idx;
+ struct page *page = NULL;
+
+ /* Free (huge) page */
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
+ IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) &&
+ has_transparent_hugepage() &&
+ args->pud_pfn != ULONG_MAX) {
+ if (args->is_contiguous_page) {
+ free_contig_range(args->pud_pfn,
+ (1 << (HPAGE_PUD_SHIFT - PAGE_SHIFT)));
+ } else {
+ page = pfn_to_page(args->pud_pfn);
+ __free_pages(page, HPAGE_PUD_SHIFT - PAGE_SHIFT);
+ }
+
+ args->pud_pfn = ULONG_MAX;
+ args->pmd_pfn = ULONG_MAX;
+ args->pte_pfn = ULONG_MAX;
+ }
- pr_info("Validating architecture page table helpers\n");
- prot = vm_get_page_prot(VMFLAGS);
- vaddr = get_random_vaddr();
- mm = mm_alloc();
- if (!mm) {
- pr_err("mm_struct allocation failed\n");
- return 1;
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
+ has_transparent_hugepage() &&
+ args->pmd_pfn != ULONG_MAX) {
+ if (args->is_contiguous_page) {
+ free_contig_range(args->pmd_pfn, (1 << HPAGE_PMD_ORDER));
+ } else {
+ page = pfn_to_page(args->pmd_pfn);
+ __free_pages(page, HPAGE_PMD_ORDER);
+ }
+
+ args->pmd_pfn = ULONG_MAX;
+ args->pte_pfn = ULONG_MAX;
}
+ if (args->pte_pfn != ULONG_MAX) {
+ page = pfn_to_page(args->pte_pfn);
+ __free_pages(page, 0);
+
+ args->pte_pfn = ULONG_MAX;
+ }
+
+ /* Free page table entries */
+ if (args->start_ptep) {
+ pte_free(args->mm, args->start_ptep);
+ mm_dec_nr_ptes(args->mm);
+ }
+
+ if (args->start_pmdp) {
+ pmd_free(args->mm, args->start_pmdp);
+ mm_dec_nr_pmds(args->mm);
+ }
+
+ if (args->start_pudp) {
+ pud_free(args->mm, args->start_pudp);
+ mm_dec_nr_puds(args->mm);
+ }
+
+ if (args->start_p4dp)
+ p4d_free(args->mm, args->start_p4dp);
+
+ /* Free vma and mm struct */
+ if (args->vma)
+ vm_area_free(args->vma);
+
+ if (args->mm)
+ mmdrop(args->mm);
+}
+
+static struct page * __init
+debug_vm_pgtable_alloc_huge_page(struct pgtable_debug_args *args, int order)
+{
+ struct page *page = NULL;
+
+#ifdef CONFIG_CONTIG_ALLOC
+ if (order >= MAX_ORDER) {
+ page = alloc_contig_pages((1 << order), GFP_KERNEL,
+ first_online_node, NULL);
+ if (page) {
+ args->is_contiguous_page = true;
+ return page;
+ }
+ }
+#endif
+
+ if (order < MAX_ORDER)
+ page = alloc_pages(GFP_KERNEL, order);
+
+ return page;
+}
+
+static int __init init_args(struct pgtable_debug_args *args)
+{
+ struct page *page = NULL;
+ phys_addr_t phys;
+ int ret = 0;
+
/*
+ * Initialize the debugging data.
+ *
* __P000 (or even __S000) will help create page table entries with
* PROT_NONE permission as required for pxx_protnone_tests().
*/
- protnone = __P000;
+ memset(args, 0, sizeof(*args));
+ args->vaddr = get_random_vaddr();
+ args->page_prot = vm_get_page_prot(VMFLAGS);
+ args->page_prot_none = __P000;
+ args->is_contiguous_page = false;
+ args->pud_pfn = ULONG_MAX;
+ args->pmd_pfn = ULONG_MAX;
+ args->pte_pfn = ULONG_MAX;
+ args->fixed_pgd_pfn = ULONG_MAX;
+ args->fixed_p4d_pfn = ULONG_MAX;
+ args->fixed_pud_pfn = ULONG_MAX;
+ args->fixed_pmd_pfn = ULONG_MAX;
+ args->fixed_pte_pfn = ULONG_MAX;
+
+ /* Allocate mm and vma */
+ args->mm = mm_alloc();
+ if (!args->mm) {
+ pr_err("Failed to allocate mm struct\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ args->vma = vm_area_alloc(args->mm);
+ if (!args->vma) {
+ pr_err("Failed to allocate vma\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ /*
+ * Allocate page table entries. They will be modified in the tests.
+ * Lets save the page table entries so that they can be released
+ * when the tests are completed.
+ */
+ args->pgdp = pgd_offset(args->mm, args->vaddr);
+ args->p4dp = p4d_alloc(args->mm, args->pgdp, args->vaddr);
+ if (!args->p4dp) {
+ pr_err("Failed to allocate p4d entries\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+ args->start_p4dp = p4d_offset(args->pgdp, 0UL);
+ WARN_ON(!args->start_p4dp);
+
+ args->pudp = pud_alloc(args->mm, args->p4dp, args->vaddr);
+ if (!args->pudp) {
+ pr_err("Failed to allocate pud entries\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+ args->start_pudp = pud_offset(args->p4dp, 0UL);
+ WARN_ON(!args->start_pudp);
+
+ args->pmdp = pmd_alloc(args->mm, args->pudp, args->vaddr);
+ if (!args->pmdp) {
+ pr_err("Failed to allocate pmd entries\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+ args->start_pmdp = pmd_offset(args->pudp, 0UL);
+ WARN_ON(!args->start_pmdp);
- vma = vm_area_alloc(mm);
- if (!vma) {
- pr_err("vma allocation failed\n");
- return 1;
+ if (pte_alloc(args->mm, args->pmdp)) {
+ pr_err("Failed to allocate pte entries\n");
+ ret = -ENOMEM;
+ goto error;
}
+ args->start_ptep = pmd_pgtable(READ_ONCE(*args->pmdp));
+ WARN_ON(!args->start_ptep);
/*
* PFN for mapping at PTE level is determined from a standard kernel
@@ -1000,40 +1184,65 @@ static int __init debug_vm_pgtable(void)
* exist on the platform but that does not really matter as pfn_pxx()
* helpers will still create appropriate entries for the test. This
* helps avoid large memory block allocations to be used for mapping
- * at higher page table levels.
+ * at higher page table levels in some of the tests.
*/
- paddr = __pa_symbol(&start_kernel);
-
- pte_aligned = (paddr & PAGE_MASK) >> PAGE_SHIFT;
- pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;
- pud_aligned = (paddr & PUD_MASK) >> PAGE_SHIFT;
- p4d_aligned = (paddr & P4D_MASK) >> PAGE_SHIFT;
- pgd_aligned = (paddr & PGDIR_MASK) >> PAGE_SHIFT;
- WARN_ON(!pfn_valid(pte_aligned));
-
- pgdp = pgd_offset(mm, vaddr);
- p4dp = p4d_alloc(mm, pgdp, vaddr);
- pudp = pud_alloc(mm, p4dp, vaddr);
- pmdp = pmd_alloc(mm, pudp, vaddr);
+ phys = __pa_symbol(&start_kernel);
+ args->fixed_pgd_pfn = __phys_to_pfn(phys & PGDIR_MASK);
+ args->fixed_p4d_pfn = __phys_to_pfn(phys & P4D_MASK);
+ args->fixed_pud_pfn = __phys_to_pfn(phys & PUD_MASK);
+ args->fixed_pmd_pfn = __phys_to_pfn(phys & PMD_MASK);
+ args->fixed_pte_pfn = __phys_to_pfn(phys & PAGE_MASK);
+ WARN_ON(!pfn_valid(args->fixed_pte_pfn));
+
/*
- * Allocate pgtable_t
+ * Allocate (huge) pages because some of the tests need to access
+ * the data in the pages. The corresponding tests will be skipped
+ * if we fail to allocate (huge) pages.
*/
- if (pte_alloc(mm, pmdp)) {
- pr_err("pgtable allocation failed\n");
- return 1;
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
+ IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) &&
+ has_transparent_hugepage()) {
+ page = debug_vm_pgtable_alloc_huge_page(args,
+ HPAGE_PUD_SHIFT - PAGE_SHIFT);
+ if (page) {
+ args->pud_pfn = page_to_pfn(page);
+ args->pmd_pfn = args->pud_pfn;
+ args->pte_pfn = args->pud_pfn;
+ return 0;
+ }
}
- /*
- * Save all the page table page addresses as the page table
- * entries will be used for testing with random or garbage
- * values. These saved addresses will be used for freeing
- * page table pages.
- */
- pmd = READ_ONCE(*pmdp);
- saved_p4dp = p4d_offset(pgdp, 0UL);
- saved_pudp = pud_offset(p4dp, 0UL);
- saved_pmdp = pmd_offset(pudp, 0UL);
- saved_ptep = pmd_pgtable(pmd);
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
+ has_transparent_hugepage()) {
+ page = debug_vm_pgtable_alloc_huge_page(args, HPAGE_PMD_ORDER);
+ if (page) {
+ args->pmd_pfn = page_to_pfn(page);
+ args->pte_pfn = args->pmd_pfn;
+ return 0;
+ }
+ }
+
+ page = alloc_pages(GFP_KERNEL, 0);
+ if (page)
+ args->pte_pfn = page_to_pfn(page);
+
+ return 0;
+
+error:
+ destroy_args(args);
+ return ret;
+}
+
+static int __init debug_vm_pgtable(void)
+{
+ struct pgtable_debug_args args;
+ spinlock_t *ptl = NULL;
+ int idx, ret;
+
+ pr_info("Validating architecture page table helpers\n");
+ ret = init_args(&args);
+ if (ret)
+ return ret;
/*
* Iterate over the protection_map[] to make sure that all
@@ -1042,9 +1251,9 @@ static int __init debug_vm_pgtable(void)
* given page table entry.
*/
for (idx = 0; idx < ARRAY_SIZE(protection_map); idx++) {
- pte_basic_tests(pte_aligned, idx);
- pmd_basic_tests(pmd_aligned, idx);
- pud_basic_tests(mm, pud_aligned, idx);
+ pte_basic_tests(&args, idx);
+ pmd_basic_tests(&args, idx);
+ pud_basic_tests(&args, idx);
}
/*
@@ -1054,79 +1263,70 @@ static int __init debug_vm_pgtable(void)
* the above iteration for now to save some test execution
* time.
*/
- p4d_basic_tests(p4d_aligned, prot);
- pgd_basic_tests(pgd_aligned, prot);
+ p4d_basic_tests(&args);
+ pgd_basic_tests(&args);
- pmd_leaf_tests(pmd_aligned, prot);
- pud_leaf_tests(pud_aligned, prot);
+ pmd_leaf_tests(&args);
+ pud_leaf_tests(&args);
- pte_savedwrite_tests(pte_aligned, protnone);
- pmd_savedwrite_tests(pmd_aligned, protnone);
+ pte_savedwrite_tests(&args);
+ pmd_savedwrite_tests(&args);
- pte_special_tests(pte_aligned, prot);
- pte_protnone_tests(pte_aligned, protnone);
- pmd_protnone_tests(pmd_aligned, protnone);
+ pte_special_tests(&args);
+ pte_protnone_tests(&args);
+ pmd_protnone_tests(&args);
- pte_devmap_tests(pte_aligned, prot);
- pmd_devmap_tests(pmd_aligned, prot);
- pud_devmap_tests(pud_aligned, prot);
+ pte_devmap_tests(&args);
+ pmd_devmap_tests(&args);
+ pud_devmap_tests(&args);
- pte_soft_dirty_tests(pte_aligned, prot);
- pmd_soft_dirty_tests(pmd_aligned, prot);
- pte_swap_soft_dirty_tests(pte_aligned, prot);
- pmd_swap_soft_dirty_tests(pmd_aligned, prot);
+ pte_soft_dirty_tests(&args);
+ pmd_soft_dirty_tests(&args);
+ pte_swap_soft_dirty_tests(&args);
+ pmd_swap_soft_dirty_tests(&args);
- pte_swap_tests(pte_aligned, prot);
- pmd_swap_tests(pmd_aligned, prot);
+ pte_swap_tests(&args);
+ pmd_swap_tests(&args);
- swap_migration_tests();
+ swap_migration_tests(&args);
- pmd_thp_tests(pmd_aligned, prot);
- pud_thp_tests(pud_aligned, prot);
+ pmd_thp_tests(&args);
+ pud_thp_tests(&args);
- hugetlb_basic_tests(pte_aligned, prot);
+ hugetlb_basic_tests(&args);
/*
* Page table modifying tests. They need to hold
* proper page table lock.
*/
- ptep = pte_offset_map_lock(mm, pmdp, vaddr, &ptl);
- pte_clear_tests(mm, ptep, pte_aligned, vaddr, prot);
- pte_advanced_tests(mm, vma, ptep, pte_aligned, vaddr, prot);
- pte_unmap_unlock(ptep, ptl);
+ args.ptep = pte_offset_map_lock(args.mm, args.pmdp, args.vaddr, &ptl);
+ pte_clear_tests(&args);
+ pte_advanced_tests(&args);
+ pte_unmap_unlock(args.ptep, ptl);
- ptl = pmd_lock(mm, pmdp);
- pmd_clear_tests(mm, pmdp);
- pmd_advanced_tests(mm, vma, pmdp, pmd_aligned, vaddr, prot, saved_ptep);
- pmd_huge_tests(pmdp, pmd_aligned, prot);
- pmd_populate_tests(mm, pmdp, saved_ptep);
+ ptl = pmd_lock(args.mm, args.pmdp);
+ pmd_clear_tests(&args);
+ pmd_advanced_tests(&args);
+ pmd_huge_tests(&args);
+ pmd_populate_tests(&args);
spin_unlock(ptl);
- ptl = pud_lock(mm, pudp);
- pud_clear_tests(mm, pudp);
- pud_advanced_tests(mm, vma, pudp, pud_aligned, vaddr, prot);
- pud_huge_tests(pudp, pud_aligned, prot);
- pud_populate_tests(mm, pudp, saved_pmdp);
+ ptl = pud_lock(args.mm, args.pudp);
+ pud_clear_tests(&args);
+ pud_advanced_tests(&args);
+ pud_huge_tests(&args);
+ pud_populate_tests(&args);
spin_unlock(ptl);
- spin_lock(&mm->page_table_lock);
- p4d_clear_tests(mm, p4dp);
- pgd_clear_tests(mm, pgdp);
- p4d_populate_tests(mm, p4dp, saved_pudp);
- pgd_populate_tests(mm, pgdp, saved_p4dp);
- spin_unlock(&mm->page_table_lock);
-
- p4d_free(mm, saved_p4dp);
- pud_free(mm, saved_pudp);
- pmd_free(mm, saved_pmdp);
- pte_free(mm, saved_ptep);
-
- vm_area_free(vma);
- mm_dec_nr_puds(mm);
- mm_dec_nr_pmds(mm);
- mm_dec_nr_ptes(mm);
- mmdrop(mm);
+ spin_lock(&(args.mm->page_table_lock));
+ p4d_clear_tests(&args);
+ pgd_clear_tests(&args);
+ p4d_populate_tests(&args);
+ pgd_populate_tests(&args);
+ spin_unlock(&(args.mm->page_table_lock));
+
+ destroy_args(&args);
return 0;
}
late_initcall(debug_vm_pgtable);
diff --git a/mm/filemap.c b/mm/filemap.c
index 920e8dc03251..dae481293b5d 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -260,12 +260,11 @@ static void page_cache_free_page(struct address_space *mapping,
void delete_from_page_cache(struct page *page)
{
struct address_space *mapping = page_mapping(page);
- unsigned long flags;
BUG_ON(!PageLocked(page));
- xa_lock_irqsave(&mapping->i_pages, flags);
+ xa_lock_irq(&mapping->i_pages);
__delete_from_page_cache(page, NULL);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
+ xa_unlock_irq(&mapping->i_pages);
page_cache_free_page(mapping, page);
}
@@ -337,19 +336,18 @@ void delete_from_page_cache_batch(struct address_space *mapping,
struct pagevec *pvec)
{
int i;
- unsigned long flags;
if (!pagevec_count(pvec))
return;
- xa_lock_irqsave(&mapping->i_pages, flags);
+ xa_lock_irq(&mapping->i_pages);
for (i = 0; i < pagevec_count(pvec); i++) {
trace_mm_filemap_delete_from_page_cache(pvec->pages[i]);
unaccount_page_cache_page(mapping, pvec->pages[i]);
}
page_cache_delete_batch(mapping, pvec);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
+ xa_unlock_irq(&mapping->i_pages);
for (i = 0; i < pagevec_count(pvec); i++)
page_cache_free_page(mapping, pvec->pages[i]);
@@ -841,7 +839,6 @@ void replace_page_cache_page(struct page *old, struct page *new)
void (*freepage)(struct page *) = mapping->a_ops->freepage;
pgoff_t offset = old->index;
XA_STATE(xas, &mapping->i_pages, offset);
- unsigned long flags;
VM_BUG_ON_PAGE(!PageLocked(old), old);
VM_BUG_ON_PAGE(!PageLocked(new), new);
@@ -853,7 +850,7 @@ void replace_page_cache_page(struct page *old, struct page *new)
mem_cgroup_migrate(old, new);
- xas_lock_irqsave(&xas, flags);
+ xas_lock_irq(&xas);
xas_store(&xas, new);
old->mapping = NULL;
@@ -866,7 +863,7 @@ void replace_page_cache_page(struct page *old, struct page *new)
__dec_lruvec_page_state(old, NR_SHMEM);
if (PageSwapBacked(new))
__inc_lruvec_page_state(new, NR_SHMEM);
- xas_unlock_irqrestore(&xas, flags);
+ xas_unlock_irq(&xas);
if (freepage)
freepage(old);
put_page(old);
diff --git a/mm/gup.c b/mm/gup.c
index b94717977d17..886d6148d3d0 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -92,10 +92,17 @@ static inline struct page *try_get_compound_head(struct page *page, int refs)
return head;
}
-/*
+/**
* try_grab_compound_head() - attempt to elevate a page's refcount, by a
* flags-dependent amount.
*
+ * Even though the name includes "compound_head", this function is still
+ * appropriate for callers that have a non-compound @page to get.
+ *
+ * @page: pointer to page to be grabbed
+ * @refs: the value to (effectively) add to the page's refcount
+ * @flags: gup flags: these are the FOLL_* flag values.
+ *
* "grab" names in this file mean, "look at flags to decide whether to use
* FOLL_PIN or FOLL_GET behavior, when incrementing the page's refcount.
*
@@ -103,22 +110,26 @@ static inline struct page *try_get_compound_head(struct page *page, int refs)
* same time. (That's true throughout the get_user_pages*() and
* pin_user_pages*() APIs.) Cases:
*
- * FOLL_GET: page's refcount will be incremented by 1.
- * FOLL_PIN: page's refcount will be incremented by GUP_PIN_COUNTING_BIAS.
+ * FOLL_GET: page's refcount will be incremented by @refs.
+ *
+ * FOLL_PIN on compound pages that are > two pages long: page's refcount will
+ * be incremented by @refs, and page[2].hpage_pinned_refcount will be
+ * incremented by @refs * GUP_PIN_COUNTING_BIAS.
+ *
+ * FOLL_PIN on normal pages, or compound pages that are two pages long:
+ * page's refcount will be incremented by @refs * GUP_PIN_COUNTING_BIAS.
*
* Return: head page (with refcount appropriately incremented) for success, or
* NULL upon failure. If neither FOLL_GET nor FOLL_PIN was set, that's
* considered failure, and furthermore, a likely bug in the caller, so a warning
* is also emitted.
*/
-__maybe_unused struct page *try_grab_compound_head(struct page *page,
- int refs, unsigned int flags)
+struct page *try_grab_compound_head(struct page *page,
+ int refs, unsigned int flags)
{
if (flags & FOLL_GET)
return try_get_compound_head(page, refs);
else if (flags & FOLL_PIN) {
- int orig_refs = refs;
-
/*
* Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a
* right zone, so fail and let the caller fall back to the slow
@@ -143,6 +154,8 @@ __maybe_unused struct page *try_grab_compound_head(struct page *page,
*
* However, be sure to *also* increment the normal page refcount
* field at least once, so that the page really is pinned.
+ * That's why the refcount from the earlier
+ * try_get_compound_head() is left intact.
*/
if (hpage_pincount_available(page))
hpage_pincount_add(page, refs);
@@ -150,7 +163,7 @@ __maybe_unused struct page *try_grab_compound_head(struct page *page,
page_ref_add(page, refs * (GUP_PIN_COUNTING_BIAS - 1));
mod_node_page_state(page_pgdat(page), NR_FOLL_PIN_ACQUIRED,
- orig_refs);
+ refs);
return page;
}
@@ -186,10 +199,8 @@ static void put_compound_head(struct page *page, int refs, unsigned int flags)
* @flags: gup flags: these are the FOLL_* flag values.
*
* Either FOLL_PIN or FOLL_GET (or neither) may be set, but not both at the same
- * time. Cases:
- *
- * FOLL_GET: page's refcount will be incremented by 1.
- * FOLL_PIN: page's refcount will be incremented by GUP_PIN_COUNTING_BIAS.
+ * time. Cases: please see the try_grab_compound_head() documentation, with
+ * "refs=1".
*
* Return: true for success, or if no action was required (if neither FOLL_PIN
* nor FOLL_GET was set, nothing is done). False for failure: FOLL_GET or
@@ -197,35 +208,10 @@ static void put_compound_head(struct page *page, int refs, unsigned int flags)
*/
bool __must_check try_grab_page(struct page *page, unsigned int flags)
{
- WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == (FOLL_GET | FOLL_PIN));
-
- if (flags & FOLL_GET)
- return try_get_page(page);
- else if (flags & FOLL_PIN) {
- int refs = 1;
-
- page = compound_head(page);
-
- if (WARN_ON_ONCE(page_ref_count(page) <= 0))
- return false;
-
- if (hpage_pincount_available(page))
- hpage_pincount_add(page, 1);
- else
- refs = GUP_PIN_COUNTING_BIAS;
-
- /*
- * Similar to try_grab_compound_head(): even if using the
- * hpage_pincount_add/_sub() routines, be sure to
- * *also* increment the normal page refcount field at least
- * once, so that the page really is pinned.
- */
- page_ref_add(page, refs);
+ if (!(flags & (FOLL_GET | FOLL_PIN)))
+ return true;
- mod_node_page_state(page_pgdat(page), NR_FOLL_PIN_ACQUIRED, 1);
- }
-
- return true;
+ return try_grab_compound_head(page, 1, flags);
}
/**
@@ -1151,7 +1137,6 @@ static long __get_user_pages(struct mm_struct *mm,
* We must stop here.
*/
BUG_ON(gup_flags & FOLL_NOWAIT);
- BUG_ON(ret != 0);
goto out;
}
continue;
@@ -1276,7 +1261,7 @@ int fixup_user_fault(struct mm_struct *mm,
bool *unlocked)
{
struct vm_area_struct *vma;
- vm_fault_t ret, major = 0;
+ vm_fault_t ret;
address = untagged_addr(address);
@@ -1296,7 +1281,6 @@ retry:
return -EINTR;
ret = handle_mm_fault(vma, address, fault_flags, NULL);
- major |= ret & VM_FAULT_MAJOR;
if (ret & VM_FAULT_ERROR) {
int err = vm_fault_to_errno(ret, 0);
@@ -1475,8 +1459,8 @@ long populate_vma_page_range(struct vm_area_struct *vma,
unsigned long nr_pages = (end - start) / PAGE_SIZE;
int gup_flags;
- VM_BUG_ON(start & ~PAGE_MASK);
- VM_BUG_ON(end & ~PAGE_MASK);
+ VM_BUG_ON(!PAGE_ALIGNED(start));
+ VM_BUG_ON(!PAGE_ALIGNED(end));
VM_BUG_ON_VMA(start < vma->vm_start, vma);
VM_BUG_ON_VMA(end > vma->vm_end, vma);
mmap_assert_locked(mm);
@@ -1775,7 +1759,7 @@ static long check_and_migrate_movable_pages(unsigned long nr_pages,
if (!list_empty(&movable_page_list)) {
ret = migrate_pages(&movable_page_list, alloc_migration_target,
NULL, (unsigned long)&mtc, MIGRATE_SYNC,
- MR_LONGTERM_PIN);
+ MR_LONGTERM_PIN, NULL);
if (ret && !list_empty(&movable_page_list))
putback_movable_pages(&movable_page_list);
}
@@ -2244,6 +2228,7 @@ static int __gup_device_huge(unsigned long pfn, unsigned long addr,
{
int nr_start = *nr;
struct dev_pagemap *pgmap = NULL;
+ int ret = 1;
do {
struct page *page = pfn_to_page(pfn);
@@ -2251,21 +2236,22 @@ static int __gup_device_huge(unsigned long pfn, unsigned long addr,
pgmap = get_dev_pagemap(pfn, pgmap);
if (unlikely(!pgmap)) {
undo_dev_pagemap(nr, nr_start, flags, pages);
- return 0;
+ ret = 0;
+ break;
}
SetPageReferenced(page);
pages[*nr] = page;
if (unlikely(!try_grab_page(page, flags))) {
undo_dev_pagemap(nr, nr_start, flags, pages);
- return 0;
+ ret = 0;
+ break;
}
(*nr)++;
pfn++;
} while (addr += PAGE_SIZE, addr != end);
- if (pgmap)
- put_dev_pagemap(pgmap);
- return 1;
+ put_dev_pagemap(pgmap);
+ return ret;
}
static int __gup_device_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr,
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index afff3ac87067..5e9ef0fc261e 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1440,32 +1440,6 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf)
goto out;
}
- /*
- * Since we took the NUMA fault, we must have observed the !accessible
- * bit. Make sure all other CPUs agree with that, to avoid them
- * modifying the page we're about to migrate.
- *
- * Must be done under PTL such that we'll observe the relevant
- * inc_tlb_flush_pending().
- *
- * We are not sure a pending tlb flush here is for a huge page
- * mapping or not. Hence use the tlb range variant
- */
- if (mm_tlb_flush_pending(vma->vm_mm)) {
- flush_tlb_range(vma, haddr, haddr + HPAGE_PMD_SIZE);
- /*
- * change_huge_pmd() released the pmd lock before
- * invalidating the secondary MMUs sharing the primary
- * MMU pagetables (with ->invalidate_range()). The
- * mmu_notifier_invalidate_range_end() (which
- * internally calls ->invalidate_range()) in
- * change_pmd_range() will run after us, so we can't
- * rely on it here and we need an explicit invalidate.
- */
- mmu_notifier_invalidate_range(vma->vm_mm, haddr,
- haddr + HPAGE_PMD_SIZE);
- }
-
pmd = pmd_modify(oldpmd, vma->vm_page_prot);
page = vm_normal_page_pmd(vma, haddr, pmd);
if (!page)
@@ -2454,11 +2428,11 @@ static void __split_huge_page(struct page *page, struct list_head *list,
for (i = nr - 1; i >= 1; i--) {
__split_huge_page_tail(head, i, lruvec, list);
- /* Some pages can be beyond i_size: drop them from page cache */
+ /* Some pages can be beyond EOF: drop them from page cache */
if (head[i].index >= end) {
ClearPageDirty(head + i);
__delete_from_page_cache(head + i, NULL);
- if (IS_ENABLED(CONFIG_SHMEM) && PageSwapBacked(head))
+ if (shmem_mapping(head->mapping))
shmem_uncharge(head->mapping->host, 1);
put_page(head + i);
} else if (!PageAnon(page)) {
@@ -2686,6 +2660,8 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
* head page lock is good enough to serialize the trimming.
*/
end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE);
+ if (shmem_mapping(mapping))
+ end = shmem_fallocend(mapping->host, end);
}
/*
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 8ea35ba6699f..95dc7b83381f 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1072,6 +1072,8 @@ static void enqueue_huge_page(struct hstate *h, struct page *page)
int nid = page_to_nid(page);
lockdep_assert_held(&hugetlb_lock);
+ VM_BUG_ON_PAGE(page_count(page), page);
+
list_move(&page->lru, &h->hugepage_freelists[nid]);
h->free_huge_pages++;
h->free_huge_pages_node[nid]++;
@@ -1143,7 +1145,7 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
unsigned long address, int avoid_reserve,
long chg)
{
- struct page *page;
+ struct page *page = NULL;
struct mempolicy *mpol;
gfp_t gfp_mask;
nodemask_t *nodemask;
@@ -1164,7 +1166,17 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
gfp_mask = htlb_alloc_mask(h);
nid = huge_node(vma, address, gfp_mask, &mpol, &nodemask);
- page = dequeue_huge_page_nodemask(h, gfp_mask, nid, nodemask);
+
+ if (mpol_is_preferred_many(mpol)) {
+ page = dequeue_huge_page_nodemask(h, gfp_mask, nid, nodemask);
+
+ /* Fallback to all nodes if page==NULL */
+ nodemask = NULL;
+ }
+
+ if (!page)
+ page = dequeue_huge_page_nodemask(h, gfp_mask, nid, nodemask);
+
if (page && !avoid_reserve && vma_has_reserves(vma, chg)) {
SetHPageRestoreReserve(page);
h->resv_huge_pages--;
@@ -1368,8 +1380,28 @@ static void remove_hugetlb_page(struct hstate *h, struct page *page,
h->surplus_huge_pages_node[nid]--;
}
+ /*
+ * Very subtle
+ *
+ * For non-gigantic pages set the destructor to the normal compound
+ * page dtor. This is needed in case someone takes an additional
+ * temporary ref to the page, and freeing is delayed until they drop
+ * their reference.
+ *
+ * For gigantic pages set the destructor to the null dtor. This
+ * destructor will never be called. Before freeing the gigantic
+ * page destroy_compound_gigantic_page will turn the compound page
+ * into a simple group of pages. After this the destructor does not
+ * apply.
+ *
+ * This handles the case where more than one ref is held when and
+ * after update_and_free_page is called.
+ */
set_page_refcounted(page);
- set_compound_page_dtor(page, NULL_COMPOUND_DTOR);
+ if (hstate_is_gigantic(h))
+ set_compound_page_dtor(page, NULL_COMPOUND_DTOR);
+ else
+ set_compound_page_dtor(page, COMPOUND_PAGE_DTOR);
h->nr_huge_pages--;
h->nr_huge_pages_node[nid]--;
@@ -1399,11 +1431,20 @@ static void add_hugetlb_page(struct hstate *h, struct page *page,
SetHPageVmemmapOptimized(page);
/*
- * This page is now managed by the hugetlb allocator and has
- * no users -- drop the last reference.
+ * This page is about to be managed by the hugetlb allocator and
+ * should have no users. Drop our reference, and check for others
+ * just in case.
*/
zeroed = put_page_testzero(page);
- VM_BUG_ON_PAGE(!zeroed, page);
+ if (!zeroed)
+ /*
+ * It is VERY unlikely soneone else has taken a ref on
+ * the page. In this case, we simply return as the
+ * hugetlb destructor (free_huge_page) will be called
+ * when this other ref is dropped.
+ */
+ return;
+
arch_clear_hugepage_flags(page);
enqueue_huge_page(h, page);
}
@@ -1657,16 +1698,14 @@ static bool prep_compound_gigantic_page(struct page *page, unsigned int order)
* cache adding could take a ref on a 'to be' tail page.
* We need to respect any increased ref count, and only set
* the ref count to zero if count is currently 1. If count
- * is not 1, we call synchronize_rcu in the hope that a rcu
- * grace period will cause ref count to drop and then retry.
- * If count is still inflated on retry we return an error and
- * must discard the pages.
+ * is not 1, we return an error. An error return indicates
+ * the set of pages can not be converted to a gigantic page.
+ * The caller who allocated the pages should then discard the
+ * pages using the appropriate free interface.
*/
if (!page_ref_freeze(p, 1)) {
- pr_info("HugeTLB unexpected inflated ref count on freshly allocated page\n");
- synchronize_rcu();
- if (!page_ref_freeze(p, 1))
- goto out_error;
+ pr_warn("HugeTLB page can not be used due to unexpected inflated ref count\n");
+ goto out_error;
}
set_page_count(p, 0);
set_compound_head(p, page);
@@ -1830,7 +1869,6 @@ retry:
retry = true;
goto retry;
}
- pr_warn("HugeTLB page can not be used due to unexpected inflated ref count\n");
return NULL;
}
}
@@ -2020,9 +2058,10 @@ int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
* Allocates a fresh surplus page from the page allocator.
*/
static struct page *alloc_surplus_huge_page(struct hstate *h, gfp_t gfp_mask,
- int nid, nodemask_t *nmask)
+ int nid, nodemask_t *nmask, bool zero_ref)
{
struct page *page = NULL;
+ bool retry = false;
if (hstate_is_gigantic(h))
return NULL;
@@ -2032,6 +2071,7 @@ static struct page *alloc_surplus_huge_page(struct hstate *h, gfp_t gfp_mask,
goto out_unlock;
spin_unlock_irq(&hugetlb_lock);
+retry:
page = alloc_fresh_huge_page(h, gfp_mask, nid, nmask, NULL);
if (!page)
return NULL;
@@ -2049,11 +2089,35 @@ static struct page *alloc_surplus_huge_page(struct hstate *h, gfp_t gfp_mask,
spin_unlock_irq(&hugetlb_lock);
put_page(page);
return NULL;
- } else {
- h->surplus_huge_pages++;
- h->surplus_huge_pages_node[page_to_nid(page)]++;
}
+ if (zero_ref) {
+ /*
+ * Caller requires a page with zero ref count.
+ * We will drop ref count here. If someone else is holding
+ * a ref, the page will be freed when they drop it. Abuse
+ * temporary page flag to accomplish this.
+ */
+ SetHPageTemporary(page);
+ if (!put_page_testzero(page)) {
+ /*
+ * Unexpected inflated ref count on freshly allocated
+ * huge. Retry once.
+ */
+ pr_info("HugeTLB unexpected inflated ref count on freshly allocated page\n");
+ spin_unlock_irq(&hugetlb_lock);
+ if (retry)
+ return NULL;
+
+ retry = true;
+ goto retry;
+ }
+ ClearHPageTemporary(page);
+ }
+
+ h->surplus_huge_pages++;
+ h->surplus_huge_pages_node[page_to_nid(page)]++;
+
out_unlock:
spin_unlock_irq(&hugetlb_lock);
@@ -2088,16 +2152,26 @@ static
struct page *alloc_buddy_huge_page_with_mpol(struct hstate *h,
struct vm_area_struct *vma, unsigned long addr)
{
- struct page *page;
+ struct page *page = NULL;
struct mempolicy *mpol;
gfp_t gfp_mask = htlb_alloc_mask(h);
int nid;
nodemask_t *nodemask;
nid = huge_node(vma, addr, gfp_mask, &mpol, &nodemask);
- page = alloc_surplus_huge_page(h, gfp_mask, nid, nodemask);
- mpol_cond_put(mpol);
+ if (mpol_is_preferred_many(mpol)) {
+ gfp_t gfp = gfp_mask | __GFP_NOWARN;
+ gfp &= ~(__GFP_DIRECT_RECLAIM | __GFP_NOFAIL);
+ page = alloc_surplus_huge_page(h, gfp, nid, nodemask, false);
+
+ /* Fallback to all nodes if page==NULL */
+ nodemask = NULL;
+ }
+
+ if (!page)
+ page = alloc_surplus_huge_page(h, gfp_mask, nid, nodemask, false);
+ mpol_cond_put(mpol);
return page;
}
@@ -2167,7 +2241,7 @@ retry:
spin_unlock_irq(&hugetlb_lock);
for (i = 0; i < needed; i++) {
page = alloc_surplus_huge_page(h, htlb_alloc_mask(h),
- NUMA_NO_NODE, NULL);
+ NUMA_NO_NODE, NULL, true);
if (!page) {
alloc_ok = false;
break;
@@ -2208,24 +2282,20 @@ retry:
/* Free the needed pages to the hugetlb pool */
list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
- int zeroed;
-
if ((--needed) < 0)
break;
- /*
- * This page is now managed by the hugetlb allocator and has
- * no users -- drop the buddy allocator's reference.
- */
- zeroed = put_page_testzero(page);
- VM_BUG_ON_PAGE(!zeroed, page);
+ /* Add the page to the hugetlb allocator */
enqueue_huge_page(h, page);
}
free:
spin_unlock_irq(&hugetlb_lock);
- /* Free unnecessary surplus pages to the buddy allocator */
+ /*
+ * Free unnecessary surplus pages to the buddy allocator.
+ * Pages have no ref count, call free_huge_page directly.
+ */
list_for_each_entry_safe(page, tmp, &surplus_list, lru)
- put_page(page);
+ free_huge_page(page);
spin_lock_irq(&hugetlb_lock);
return ret;
@@ -2534,6 +2604,7 @@ static int alloc_and_dissolve_huge_page(struct hstate *h, struct page *old_page,
{
gfp_t gfp_mask = htlb_alloc_mask(h) | __GFP_THISNODE;
int nid = page_to_nid(old_page);
+ bool alloc_retry = false;
struct page *new_page;
int ret = 0;
@@ -2544,9 +2615,30 @@ static int alloc_and_dissolve_huge_page(struct hstate *h, struct page *old_page,
* the pool. This simplifies and let us do most of the processing
* under the lock.
*/
+alloc_retry:
new_page = alloc_buddy_huge_page(h, gfp_mask, nid, NULL, NULL);
if (!new_page)
return -ENOMEM;
+ /*
+ * If all goes well, this page will be directly added to the free
+ * list in the pool. For this the ref count needs to be zero.
+ * Attempt to drop now, and retry once if needed. It is VERY
+ * unlikely there is another ref on the page.
+ *
+ * If someone else has a reference to the page, it will be freed
+ * when they drop their ref. Abuse temporary page flag to accomplish
+ * this. Retry once if there is an inflated ref count.
+ */
+ SetHPageTemporary(new_page);
+ if (!put_page_testzero(new_page)) {
+ if (alloc_retry)
+ return -EBUSY;
+
+ alloc_retry = true;
+ goto alloc_retry;
+ }
+ ClearHPageTemporary(new_page);
+
__prep_new_huge_page(h, new_page);
retry:
@@ -2586,11 +2678,10 @@ retry:
remove_hugetlb_page(h, old_page, false);
/*
- * Reference count trick is needed because allocator gives us
- * referenced page but the pool requires pages with 0 refcount.
+ * Ref count on new page is already zero as it was dropped
+ * earlier. It can be directly added to the pool free list.
*/
__prep_account_new_huge_page(h, nid);
- page_ref_dec(new_page);
enqueue_huge_page(h, new_page);
/*
@@ -2604,6 +2695,8 @@ retry:
free_new:
spin_unlock_irq(&hugetlb_lock);
+ /* Page has a zero ref count, but needs a ref to be freed */
+ set_page_refcounted(new_page);
update_and_free_page(h, new_page, false);
return ret;
@@ -2828,8 +2921,8 @@ static void __init gather_bootmem_prealloc(void)
prep_new_huge_page(h, page, page_to_nid(page));
put_page(page); /* add to the hugepage allocator */
} else {
+ /* VERY unlikely inflated ref count on a tail page */
free_gigantic_page(page, huge_page_order(h));
- pr_warn("HugeTLB page can not be used due to unexpected inflated ref count\n");
}
/*
@@ -4033,8 +4126,10 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma)
* after this open call completes. It is therefore safe to take a
* new reference here without additional locking.
*/
- if (resv && is_vma_resv_set(vma, HPAGE_RESV_OWNER))
+ if (resv && is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+ resv_map_dup_hugetlb_cgroup_uncharge_info(resv);
kref_get(&resv->refs);
+ }
}
static void hugetlb_vm_op_close(struct vm_area_struct *vma)
diff --git a/mm/hwpoison-inject.c b/mm/hwpoison-inject.c
index 1ae1ebc2b9b1..aff4d27ec235 100644
--- a/mm/hwpoison-inject.c
+++ b/mm/hwpoison-inject.c
@@ -30,7 +30,7 @@ static int hwpoison_inject(void *data, u64 val)
if (!hwpoison_filter_enable)
goto inject;
- shake_page(hpage, 0);
+ shake_page(hpage);
/*
* This implies unable to support non-LRU pages.
*/
diff --git a/mm/internal.h b/mm/internal.h
index 31ff935b2547..cf3cb933eba3 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -211,6 +211,10 @@ extern void zone_pcp_reset(struct zone *zone);
extern void zone_pcp_disable(struct zone *zone);
extern void zone_pcp_enable(struct zone *zone);
+extern void *memmap_alloc(phys_addr_t size, phys_addr_t align,
+ phys_addr_t min_addr,
+ int nid, bool exact_nid);
+
#if defined CONFIG_COMPACTION || defined CONFIG_CMA
/*
@@ -539,12 +543,17 @@ static inline void mminit_validate_memmodel_limits(unsigned long *start_pfn,
#ifdef CONFIG_NUMA
extern int node_reclaim(struct pglist_data *, gfp_t, unsigned int);
+extern int find_next_best_node(int node, nodemask_t *used_node_mask);
#else
static inline int node_reclaim(struct pglist_data *pgdat, gfp_t mask,
unsigned int order)
{
return NODE_RECLAIM_NOSCAN;
}
+static inline int find_next_best_node(int node, nodemask_t *used_node_mask)
+{
+ return NUMA_NO_NODE;
+}
#endif
extern int hwpoison_filter(struct page *p);
diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c
index 4ea8c368b5b8..05d1e9460e2e 100644
--- a/mm/kasan/hw_tags.c
+++ b/mm/kasan/hw_tags.c
@@ -37,16 +37,9 @@ enum kasan_arg_stacktrace {
KASAN_ARG_STACKTRACE_ON,
};
-enum kasan_arg_fault {
- KASAN_ARG_FAULT_DEFAULT,
- KASAN_ARG_FAULT_REPORT,
- KASAN_ARG_FAULT_PANIC,
-};
-
static enum kasan_arg kasan_arg __ro_after_init;
static enum kasan_arg_mode kasan_arg_mode __ro_after_init;
static enum kasan_arg_stacktrace kasan_arg_stacktrace __ro_after_init;
-static enum kasan_arg_fault kasan_arg_fault __ro_after_init;
/* Whether KASAN is enabled at all. */
DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled);
@@ -59,9 +52,6 @@ EXPORT_SYMBOL_GPL(kasan_flag_async);
/* Whether to collect alloc/free stack traces. */
DEFINE_STATIC_KEY_FALSE(kasan_flag_stacktrace);
-/* Whether to panic or print a report and disable tag checking on fault. */
-bool kasan_flag_panic __ro_after_init;
-
/* kasan=off/on */
static int __init early_kasan_flag(char *arg)
{
@@ -113,23 +103,6 @@ static int __init early_kasan_flag_stacktrace(char *arg)
}
early_param("kasan.stacktrace", early_kasan_flag_stacktrace);
-/* kasan.fault=report/panic */
-static int __init early_kasan_fault(char *arg)
-{
- if (!arg)
- return -EINVAL;
-
- if (!strcmp(arg, "report"))
- kasan_arg_fault = KASAN_ARG_FAULT_REPORT;
- else if (!strcmp(arg, "panic"))
- kasan_arg_fault = KASAN_ARG_FAULT_PANIC;
- else
- return -EINVAL;
-
- return 0;
-}
-early_param("kasan.fault", early_kasan_fault);
-
/* kasan_init_hw_tags_cpu() is called for each CPU. */
void kasan_init_hw_tags_cpu(void)
{
@@ -142,8 +115,6 @@ void kasan_init_hw_tags_cpu(void)
if (kasan_arg == KASAN_ARG_OFF)
return;
- hw_init_tags(KASAN_TAG_MAX);
-
/*
* Enable async mode only when explicitly requested through
* the command line.
@@ -197,22 +168,6 @@ void __init kasan_init_hw_tags(void)
break;
}
- switch (kasan_arg_fault) {
- case KASAN_ARG_FAULT_DEFAULT:
- /*
- * Default to no panic on report.
- * Do nothing, kasan_flag_panic keeps its default value.
- */
- break;
- case KASAN_ARG_FAULT_REPORT:
- /* Do nothing, kasan_flag_panic keeps its default value. */
- break;
- case KASAN_ARG_FAULT_PANIC:
- /* Enable panic on report. */
- kasan_flag_panic = true;
- break;
- }
-
pr_info("KernelAddressSanitizer initialized\n");
}
@@ -250,12 +205,6 @@ void kasan_free_pages(struct page *page, unsigned int order)
#if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST)
-void kasan_set_tagging_report_once(bool state)
-{
- hw_set_tagging_report_once(state);
-}
-EXPORT_SYMBOL_GPL(kasan_set_tagging_report_once);
-
void kasan_enable_tagging_sync(void)
{
hw_enable_tagging_sync();
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index d739cdd1621a..8bf568a80eb8 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -3,6 +3,7 @@
#define __MM_KASAN_KASAN_H
#include <linux/kasan.h>
+#include <linux/kasan-tags.h>
#include <linux/kfence.h>
#include <linux/stackdepot.h>
@@ -37,7 +38,6 @@ static inline bool kasan_async_mode_enabled(void)
#endif
-extern bool kasan_flag_panic __ro_after_init;
extern bool kasan_flag_async __ro_after_init;
#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
@@ -51,16 +51,6 @@ extern bool kasan_flag_async __ro_after_init;
#define KASAN_MEMORY_PER_SHADOW_PAGE (KASAN_GRANULE_SIZE << PAGE_SHIFT)
-#define KASAN_TAG_KERNEL 0xFF /* native kernel pointers tag */
-#define KASAN_TAG_INVALID 0xFE /* inaccessible memory tag */
-#define KASAN_TAG_MAX 0xFD /* maximum value for random tags */
-
-#ifdef CONFIG_KASAN_HW_TAGS
-#define KASAN_TAG_MIN 0xF0 /* minimum value for random tags */
-#else
-#define KASAN_TAG_MIN 0x00 /* minimum value for random tags */
-#endif
-
#ifdef CONFIG_KASAN_GENERIC
#define KASAN_FREE_PAGE 0xFF /* page was freed */
#define KASAN_PAGE_REDZONE 0xFE /* redzone for kmalloc_large allocations */
@@ -299,12 +289,6 @@ static inline const void *arch_kasan_set_tag(const void *addr, u8 tag)
#ifndef arch_enable_tagging_async
#define arch_enable_tagging_async()
#endif
-#ifndef arch_init_tags
-#define arch_init_tags(max_tag)
-#endif
-#ifndef arch_set_tagging_report_once
-#define arch_set_tagging_report_once(state)
-#endif
#ifndef arch_force_async_tag_fault
#define arch_force_async_tag_fault()
#endif
@@ -320,8 +304,6 @@ static inline const void *arch_kasan_set_tag(const void *addr, u8 tag)
#define hw_enable_tagging_sync() arch_enable_tagging_sync()
#define hw_enable_tagging_async() arch_enable_tagging_async()
-#define hw_init_tags(max_tag) arch_init_tags(max_tag)
-#define hw_set_tagging_report_once(state) arch_set_tagging_report_once(state)
#define hw_force_async_tag_fault() arch_force_async_tag_fault()
#define hw_get_random_tag() arch_get_random_tag()
#define hw_get_mem_tag(addr) arch_get_mem_tag(addr)
@@ -332,19 +314,16 @@ static inline const void *arch_kasan_set_tag(const void *addr, u8 tag)
#define hw_enable_tagging_sync()
#define hw_enable_tagging_async()
-#define hw_set_tagging_report_once(state)
#endif /* CONFIG_KASAN_HW_TAGS */
#if defined(CONFIG_KASAN_HW_TAGS) && IS_ENABLED(CONFIG_KASAN_KUNIT_TEST)
-void kasan_set_tagging_report_once(bool state);
void kasan_enable_tagging_sync(void);
void kasan_force_async_fault(void);
#else /* CONFIG_KASAN_HW_TAGS || CONFIG_KASAN_KUNIT_TEST */
-static inline void kasan_set_tagging_report_once(bool state) { }
static inline void kasan_enable_tagging_sync(void) { }
static inline void kasan_force_async_fault(void) { }
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 8fff1825b22c..884a950c7026 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -39,6 +39,31 @@ static unsigned long kasan_flags;
#define KASAN_BIT_REPORTED 0
#define KASAN_BIT_MULTI_SHOT 1
+enum kasan_arg_fault {
+ KASAN_ARG_FAULT_DEFAULT,
+ KASAN_ARG_FAULT_REPORT,
+ KASAN_ARG_FAULT_PANIC,
+};
+
+static enum kasan_arg_fault kasan_arg_fault __ro_after_init = KASAN_ARG_FAULT_DEFAULT;
+
+/* kasan.fault=report/panic */
+static int __init early_kasan_fault(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
+
+ if (!strcmp(arg, "report"))
+ kasan_arg_fault = KASAN_ARG_FAULT_REPORT;
+ else if (!strcmp(arg, "panic"))
+ kasan_arg_fault = KASAN_ARG_FAULT_PANIC;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+early_param("kasan.fault", early_kasan_fault);
+
bool kasan_save_enable_multi_shot(void)
{
return test_and_set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
@@ -102,10 +127,8 @@ static void end_report(unsigned long *flags, unsigned long addr)
panic_on_warn = 0;
panic("panic_on_warn set ...\n");
}
-#ifdef CONFIG_KASAN_HW_TAGS
- if (kasan_flag_panic)
+ if (kasan_arg_fault == KASAN_ARG_FAULT_PANIC)
panic("kasan.fault=panic set ...\n");
-#endif
kasan_enable_current();
}
diff --git a/mm/kfence/report.c b/mm/kfence/report.c
index 2a319c21c939..4b891dd75650 100644
--- a/mm/kfence/report.c
+++ b/mm/kfence/report.c
@@ -5,7 +5,7 @@
* Copyright (C) 2020, Google LLC.
*/
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include <linux/kernel.h>
#include <linux/lockdep.h>
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index b0412be08fa2..045cc579f724 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1721,7 +1721,7 @@ static void collapse_file(struct mm_struct *mm,
xas_unlock_irq(&xas);
/* swap in or instantiate fallocated page */
if (shmem_getpage(mapping->host, index, &page,
- SGP_NOHUGE)) {
+ SGP_NOALLOC)) {
result = SCAN_FAIL;
goto xa_unlocked;
}
diff --git a/mm/ksm.c b/mm/ksm.c
index 3fa9bc8a67cf..025338128cd9 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -259,7 +259,7 @@ static unsigned long ksm_stable_node_chains;
static unsigned long ksm_stable_node_dups;
/* Delay in pruning stale stable_node_dups in the stable_node_chains */
-static int ksm_stable_node_chains_prune_millisecs = 2000;
+static unsigned int ksm_stable_node_chains_prune_millisecs = 2000;
/* Maximum number of page slots sharing a stable node */
static int ksm_max_page_sharing = 256;
@@ -3105,11 +3105,11 @@ stable_node_chains_prune_millisecs_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
- unsigned long msecs;
+ unsigned int msecs;
int err;
- err = kstrtoul(buf, 10, &msecs);
- if (err || msecs > UINT_MAX)
+ err = kstrtouint(buf, 10, &msecs);
+ if (err)
return -EINVAL;
ksm_stable_node_chains_prune_millisecs = msecs;
diff --git a/mm/madvise.c b/mm/madvise.c
index 56324a3dbc4e..0734db8d53a7 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -1048,6 +1048,7 @@ process_madvise_behavior_valid(int behavior)
switch (behavior) {
case MADV_COLD:
case MADV_PAGEOUT:
+ case MADV_WILLNEED:
return true;
default:
return false;
diff --git a/mm/memblock.c b/mm/memblock.c
index de7b553baa50..0ab5a749bfa6 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -315,7 +315,7 @@ static phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
* Return:
* Found address on success, 0 on failure.
*/
-phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
+static phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
phys_addr_t end, phys_addr_t size,
phys_addr_t align)
{
@@ -665,6 +665,11 @@ repeat:
int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size,
int nid)
{
+ phys_addr_t end = base + size - 1;
+
+ memblock_dbg("%s: [%pa-%pa] nid=%d %pS\n", __func__,
+ &base, &end, nid, (void *)_RET_IP_);
+
return memblock_add_range(&memblock.memory, base, size, nid, 0);
}
@@ -1491,18 +1496,12 @@ void * __init memblock_alloc_exact_nid_raw(
phys_addr_t min_addr, phys_addr_t max_addr,
int nid)
{
- void *ptr;
-
memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pS\n",
__func__, (u64)size, (u64)align, nid, &min_addr,
&max_addr, (void *)_RET_IP_);
- ptr = memblock_alloc_internal(size, align,
- min_addr, max_addr, nid, true);
- if (ptr && size > 0)
- page_init_poison(ptr, size);
-
- return ptr;
+ return memblock_alloc_internal(size, align, min_addr, max_addr, nid,
+ true);
}
/**
@@ -1529,18 +1528,12 @@ void * __init memblock_alloc_try_nid_raw(
phys_addr_t min_addr, phys_addr_t max_addr,
int nid)
{
- void *ptr;
-
memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pS\n",
__func__, (u64)size, (u64)align, nid, &min_addr,
&max_addr, (void *)_RET_IP_);
- ptr = memblock_alloc_internal(size, align,
- min_addr, max_addr, nid, false);
- if (ptr && size > 0)
- page_init_poison(ptr, size);
-
- return ptr;
+ return memblock_alloc_internal(size, align, min_addr, max_addr, nid,
+ false);
}
/**
@@ -1680,6 +1673,11 @@ void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
if (!size)
return;
+ if (memblock.memory.cnt <= 1) {
+ pr_warn("%s: No memory registered yet\n", __func__);
+ return;
+ }
+
ret = memblock_isolate_range(&memblock.memory, base, size,
&start_rgn, &end_rgn);
if (ret)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 389b5766e74f..b762215d73eb 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -103,6 +103,14 @@ static bool do_memsw_account(void)
return !cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_noswap;
}
+/* memcg and lruvec stats flushing */
+static void flush_memcg_stats_dwork(struct work_struct *w);
+static DECLARE_DEFERRABLE_WORK(stats_flush_dwork, flush_memcg_stats_dwork);
+static void flush_memcg_stats_work(struct work_struct *w);
+static DECLARE_WORK(stats_flush_work, flush_memcg_stats_work);
+static DEFINE_PER_CPU(unsigned int, stats_flush_threshold);
+static DEFINE_SPINLOCK(stats_flush_lock);
+
#define THRESHOLDS_EVENTS_TARGET 128
#define SOFTLIMIT_EVENTS_TARGET 1024
@@ -248,9 +256,9 @@ struct vmpressure *memcg_to_vmpressure(struct mem_cgroup *memcg)
return &memcg->vmpressure;
}
-struct cgroup_subsys_state *vmpressure_to_css(struct vmpressure *vmpr)
+struct mem_cgroup *vmpressure_to_memcg(struct vmpressure *vmpr)
{
- return &container_of(vmpr, struct mem_cgroup, vmpressure)->css;
+ return container_of(vmpr, struct mem_cgroup, vmpressure);
}
#ifdef CONFIG_MEMCG_KMEM
@@ -646,17 +654,6 @@ void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val)
}
/* idx can be of type enum memcg_stat_item or node_stat_item. */
-static unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)
-{
- long x = READ_ONCE(memcg->vmstats.state[idx]);
-#ifdef CONFIG_SMP
- if (x < 0)
- x = 0;
-#endif
- return x;
-}
-
-/* idx can be of type enum memcg_stat_item or node_stat_item. */
static unsigned long memcg_page_state_local(struct mem_cgroup *memcg, int idx)
{
long x = 0;
@@ -671,23 +668,11 @@ static unsigned long memcg_page_state_local(struct mem_cgroup *memcg, int idx)
return x;
}
-static struct mem_cgroup_per_node *
-parent_nodeinfo(struct mem_cgroup_per_node *pn, int nid)
-{
- struct mem_cgroup *parent;
-
- parent = parent_mem_cgroup(pn->memcg);
- if (!parent)
- return NULL;
- return parent->nodeinfo[nid];
-}
-
void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
int val)
{
struct mem_cgroup_per_node *pn;
struct mem_cgroup *memcg;
- long x, threshold = MEMCG_CHARGE_BATCH;
pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
memcg = pn->memcg;
@@ -696,21 +681,9 @@ void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
__mod_memcg_state(memcg, idx, val);
/* Update lruvec */
- __this_cpu_add(pn->lruvec_stat_local->count[idx], val);
-
- if (vmstat_item_in_bytes(idx))
- threshold <<= PAGE_SHIFT;
-
- x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]);
- if (unlikely(abs(x) > threshold)) {
- pg_data_t *pgdat = lruvec_pgdat(lruvec);
- struct mem_cgroup_per_node *pi;
-
- for (pi = pn; pi; pi = parent_nodeinfo(pi, pgdat->node_id))
- atomic_long_add(x, &pi->lruvec_stat[idx]);
- x = 0;
- }
- __this_cpu_write(pn->lruvec_stat_cpu->count[idx], x);
+ __this_cpu_add(pn->lruvec_stats_percpu->state[idx], val);
+ if (!(__this_cpu_inc_return(stats_flush_threshold) % MEMCG_CHARGE_BATCH))
+ queue_work(system_unbound_wq, &stats_flush_work);
}
/**
@@ -905,7 +878,7 @@ EXPORT_SYMBOL(mem_cgroup_from_task);
static __always_inline struct mem_cgroup *active_memcg(void)
{
- if (in_interrupt())
+ if (!in_task())
return this_cpu_read(int_active_memcg);
else
return current->active_memcg;
@@ -2205,8 +2178,9 @@ static void drain_local_stock(struct work_struct *dummy)
unsigned long flags;
/*
- * The only protection from memory hotplug vs. drain_stock races is
- * that we always operate on local CPU stock here with IRQ disabled
+ * The only protection from cpu hotplug (memcg_hotplug_cpu_dead) vs.
+ * drain_stock races is that we always operate on local CPU stock
+ * here with IRQ disabled
*/
local_irq_save(flags);
@@ -2273,7 +2247,7 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
if (memcg && stock->nr_pages &&
mem_cgroup_is_descendant(memcg, root_memcg))
flush = true;
- if (obj_stock_flush_required(stock, root_memcg))
+ else if (obj_stock_flush_required(stock, root_memcg))
flush = true;
rcu_read_unlock();
@@ -2289,40 +2263,13 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
mutex_unlock(&percpu_charge_mutex);
}
-static void memcg_flush_lruvec_page_state(struct mem_cgroup *memcg, int cpu)
-{
- int nid;
-
- for_each_node(nid) {
- struct mem_cgroup_per_node *pn = memcg->nodeinfo[nid];
- unsigned long stat[NR_VM_NODE_STAT_ITEMS];
- struct batched_lruvec_stat *lstatc;
- int i;
-
- lstatc = per_cpu_ptr(pn->lruvec_stat_cpu, cpu);
- for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) {
- stat[i] = lstatc->count[i];
- lstatc->count[i] = 0;
- }
-
- do {
- for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
- atomic_long_add(stat[i], &pn->lruvec_stat[i]);
- } while ((pn = parent_nodeinfo(pn, nid)));
- }
-}
-
static int memcg_hotplug_cpu_dead(unsigned int cpu)
{
struct memcg_stock_pcp *stock;
- struct mem_cgroup *memcg;
stock = &per_cpu(memcg_stock, cpu);
drain_stock(stock);
- for_each_mem_cgroup(memcg)
- memcg_flush_lruvec_page_state(memcg, cpu);
-
return 0;
}
@@ -4116,7 +4063,7 @@ static int mem_cgroup_swappiness_write(struct cgroup_subsys_state *css,
{
struct mem_cgroup *memcg = mem_cgroup_from_css(css);
- if (val > 100)
+ if (val > 200)
return -EINVAL;
if (!mem_cgroup_is_root(memcg))
@@ -4668,7 +4615,7 @@ void mem_cgroup_flush_foreign(struct bdi_writeback *wb)
atomic_read(&frn->done.cnt) == 1) {
frn->at = 0;
trace_flush_foreign(wb, frn->bdi_id, frn->memcg_id);
- cgroup_writeback_by_id(frn->bdi_id, frn->memcg_id, 0,
+ cgroup_writeback_by_id(frn->bdi_id, frn->memcg_id,
WB_REASON_FOREIGN_FLUSH,
&frn->done);
}
@@ -4892,9 +4839,9 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
vfs_poll(efile.file, &event->pt);
- spin_lock(&memcg->event_list_lock);
+ spin_lock_irq(&memcg->event_list_lock);
list_add(&event->list, &memcg->event_list);
- spin_unlock(&memcg->event_list_lock);
+ spin_unlock_irq(&memcg->event_list_lock);
fdput(cfile);
fdput(efile);
@@ -5129,17 +5076,9 @@ static int alloc_mem_cgroup_per_node_info(struct mem_cgroup *memcg, int node)
if (!pn)
return 1;
- pn->lruvec_stat_local = alloc_percpu_gfp(struct lruvec_stat,
- GFP_KERNEL_ACCOUNT);
- if (!pn->lruvec_stat_local) {
- kfree(pn);
- return 1;
- }
-
- pn->lruvec_stat_cpu = alloc_percpu_gfp(struct batched_lruvec_stat,
- GFP_KERNEL_ACCOUNT);
- if (!pn->lruvec_stat_cpu) {
- free_percpu(pn->lruvec_stat_local);
+ pn->lruvec_stats_percpu = alloc_percpu_gfp(struct lruvec_stats_percpu,
+ GFP_KERNEL_ACCOUNT);
+ if (!pn->lruvec_stats_percpu) {
kfree(pn);
return 1;
}
@@ -5160,8 +5099,7 @@ static void free_mem_cgroup_per_node_info(struct mem_cgroup *memcg, int node)
if (!pn)
return;
- free_percpu(pn->lruvec_stat_cpu);
- free_percpu(pn->lruvec_stat_local);
+ free_percpu(pn->lruvec_stats_percpu);
kfree(pn);
}
@@ -5177,15 +5115,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
static void mem_cgroup_free(struct mem_cgroup *memcg)
{
- int cpu;
-
memcg_wb_domain_exit(memcg);
- /*
- * Flush percpu lruvec stats to guarantee the value
- * correctness on parent's and all ancestor levels.
- */
- for_each_online_cpu(cpu)
- memcg_flush_lruvec_page_state(memcg, cpu);
__mem_cgroup_free(memcg);
}
@@ -5321,6 +5251,10 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
/* Online state pins memcg ID, memcg ID pins CSS */
refcount_set(&memcg->id.ref, 1);
css_get(css);
+
+ if (unlikely(mem_cgroup_is_root(memcg)))
+ queue_delayed_work(system_unbound_wq, &stats_flush_dwork,
+ 2UL*HZ);
return 0;
}
@@ -5334,12 +5268,12 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
* Notify userspace about cgroup removing only after rmdir of cgroup
* directory to avoid race between userspace and kernelspace.
*/
- spin_lock(&memcg->event_list_lock);
+ spin_lock_irq(&memcg->event_list_lock);
list_for_each_entry_safe(event, tmp, &memcg->event_list, list) {
list_del_init(&event->list);
schedule_work(&event->remove);
}
- spin_unlock(&memcg->event_list_lock);
+ spin_unlock_irq(&memcg->event_list_lock);
page_counter_set_min(&memcg->memory, 0);
page_counter_set_low(&memcg->memory, 0);
@@ -5412,13 +5346,33 @@ static void mem_cgroup_css_reset(struct cgroup_subsys_state *css)
memcg_wb_domain_size_changed(memcg);
}
+void mem_cgroup_flush_stats(void)
+{
+ if (!spin_trylock(&stats_flush_lock))
+ return;
+
+ cgroup_rstat_flush_irqsafe(root_mem_cgroup->css.cgroup);
+ spin_unlock(&stats_flush_lock);
+}
+
+static void flush_memcg_stats_dwork(struct work_struct *w)
+{
+ mem_cgroup_flush_stats();
+ queue_delayed_work(system_unbound_wq, &stats_flush_dwork, 2UL*HZ);
+}
+
+static void flush_memcg_stats_work(struct work_struct *w)
+{
+ mem_cgroup_flush_stats();
+}
+
static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu)
{
struct mem_cgroup *memcg = mem_cgroup_from_css(css);
struct mem_cgroup *parent = parent_mem_cgroup(memcg);
struct memcg_vmstats_percpu *statc;
long delta, v;
- int i;
+ int i, nid;
statc = per_cpu_ptr(memcg->vmstats_percpu, cpu);
@@ -5466,6 +5420,36 @@ static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu)
if (parent)
parent->vmstats.events_pending[i] += delta;
}
+
+ for_each_node_state(nid, N_MEMORY) {
+ struct mem_cgroup_per_node *pn = memcg->nodeinfo[nid];
+ struct mem_cgroup_per_node *ppn = NULL;
+ struct lruvec_stats_percpu *lstatc;
+
+ if (parent)
+ ppn = parent->nodeinfo[nid];
+
+ lstatc = per_cpu_ptr(pn->lruvec_stats_percpu, cpu);
+
+ for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) {
+ delta = pn->lruvec_stats.state_pending[i];
+ if (delta)
+ pn->lruvec_stats.state_pending[i] = 0;
+
+ v = READ_ONCE(lstatc->state[i]);
+ if (v != lstatc->state_prev[i]) {
+ delta += v - lstatc->state_prev[i];
+ lstatc->state_prev[i] = v;
+ }
+
+ if (!delta)
+ continue;
+
+ pn->lruvec_stats.state[i] += delta;
+ if (ppn)
+ ppn->lruvec_stats.state_pending[i] += delta;
+ }
+ }
}
#ifdef CONFIG_MMU
@@ -6399,6 +6383,8 @@ static int memory_numa_stat_show(struct seq_file *m, void *v)
int i;
struct mem_cgroup *memcg = mem_cgroup_from_seq(m);
+ cgroup_rstat_flush(memcg->css.cgroup);
+
for (i = 0; i < ARRAY_SIZE(memory_stats); i++) {
int nid;
@@ -6704,8 +6690,7 @@ void mem_cgroup_calculate_protection(struct mem_cgroup *root,
atomic_long_read(&parent->memory.children_low_usage)));
}
-static int __mem_cgroup_charge(struct page *page, struct mem_cgroup *memcg,
- gfp_t gfp)
+static int charge_memcg(struct page *page, struct mem_cgroup *memcg, gfp_t gfp)
{
unsigned int nr_pages = thp_nr_pages(page);
int ret;
@@ -6726,7 +6711,7 @@ out:
}
/**
- * mem_cgroup_charge - charge a newly allocated page to a cgroup
+ * __mem_cgroup_charge - charge a newly allocated page to a cgroup
* @page: page to charge
* @mm: mm context of the victim
* @gfp_mask: reclaim mode
@@ -6739,16 +6724,14 @@ out:
*
* Returns 0 on success. Otherwise, an error code is returned.
*/
-int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
+int __mem_cgroup_charge(struct page *page, struct mm_struct *mm,
+ gfp_t gfp_mask)
{
struct mem_cgroup *memcg;
int ret;
- if (mem_cgroup_disabled())
- return 0;
-
memcg = get_mem_cgroup_from_mm(mm);
- ret = __mem_cgroup_charge(page, memcg, gfp_mask);
+ ret = charge_memcg(page, memcg, gfp_mask);
css_put(&memcg->css);
return ret;
@@ -6783,7 +6766,7 @@ int mem_cgroup_swapin_charge_page(struct page *page, struct mm_struct *mm,
memcg = get_mem_cgroup_from_mm(mm);
rcu_read_unlock();
- ret = __mem_cgroup_charge(page, memcg, gfp);
+ ret = charge_memcg(page, memcg, gfp);
css_put(&memcg->css);
return ret;
@@ -6919,18 +6902,15 @@ static void uncharge_page(struct page *page, struct uncharge_gather *ug)
}
/**
- * mem_cgroup_uncharge - uncharge a page
+ * __mem_cgroup_uncharge - uncharge a page
* @page: page to uncharge
*
- * Uncharge a page previously charged with mem_cgroup_charge().
+ * Uncharge a page previously charged with __mem_cgroup_charge().
*/
-void mem_cgroup_uncharge(struct page *page)
+void __mem_cgroup_uncharge(struct page *page)
{
struct uncharge_gather ug;
- if (mem_cgroup_disabled())
- return;
-
/* Don't touch page->lru of any random page, pre-check: */
if (!page_memcg(page))
return;
@@ -6941,20 +6921,17 @@ void mem_cgroup_uncharge(struct page *page)
}
/**
- * mem_cgroup_uncharge_list - uncharge a list of page
+ * __mem_cgroup_uncharge_list - uncharge a list of page
* @page_list: list of pages to uncharge
*
* Uncharge a list of pages previously charged with
- * mem_cgroup_charge().
+ * __mem_cgroup_charge().
*/
-void mem_cgroup_uncharge_list(struct list_head *page_list)
+void __mem_cgroup_uncharge_list(struct list_head *page_list)
{
struct uncharge_gather ug;
struct page *page;
- if (mem_cgroup_disabled())
- return;
-
uncharge_gather_clear(&ug);
list_for_each_entry(page, page_list, lru)
uncharge_page(page, &ug);
@@ -7244,7 +7221,7 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
}
/**
- * mem_cgroup_try_charge_swap - try charging swap space for a page
+ * __mem_cgroup_try_charge_swap - try charging swap space for a page
* @page: page being added to swap
* @entry: swap entry to charge
*
@@ -7252,16 +7229,13 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
*
* Returns 0 on success, -ENOMEM on failure.
*/
-int mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry)
+int __mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry)
{
unsigned int nr_pages = thp_nr_pages(page);
struct page_counter *counter;
struct mem_cgroup *memcg;
unsigned short oldid;
- if (mem_cgroup_disabled())
- return 0;
-
if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
return 0;
@@ -7297,11 +7271,11 @@ int mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry)
}
/**
- * mem_cgroup_uncharge_swap - uncharge swap space
+ * __mem_cgroup_uncharge_swap - uncharge swap space
* @entry: swap entry to uncharge
* @nr_pages: the amount of swap space to uncharge
*/
-void mem_cgroup_uncharge_swap(swp_entry_t entry, unsigned int nr_pages)
+void __mem_cgroup_uncharge_swap(swp_entry_t entry, unsigned int nr_pages)
{
struct mem_cgroup *memcg;
unsigned short id;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index e1f87cf13235..54879c339024 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -68,7 +68,7 @@ atomic_long_t num_poisoned_pages __read_mostly = ATOMIC_LONG_INIT(0);
static bool __page_handle_poison(struct page *page)
{
- bool ret;
+ int ret;
zone_pcp_disable(page_zone(page));
ret = dissolve_free_huge_page(page);
@@ -76,7 +76,7 @@ static bool __page_handle_poison(struct page *page)
ret = take_page_off_buddy(page);
zone_pcp_enable(page_zone(page));
- return ret;
+ return ret > 0;
}
static bool page_handle_poison(struct page *page, bool hugepage_or_freepage, bool release)
@@ -282,9 +282,9 @@ static int kill_proc(struct to_kill *tk, unsigned long pfn, int flags)
/*
* Unknown page type encountered. Try to check whether it can turn PageLRU by
- * lru_add_drain_all, or a free page by reclaiming slabs when possible.
+ * lru_add_drain_all.
*/
-void shake_page(struct page *p, int access)
+void shake_page(struct page *p)
{
if (PageHuge(p))
return;
@@ -296,11 +296,9 @@ void shake_page(struct page *p, int access)
}
/*
- * Only call shrink_node_slabs here (which would also shrink
- * other caches) if access is not potentially fatal.
+ * TODO: Could shrink slab caches here if a lightweight range-based
+ * shrinker will be available.
*/
- if (access)
- drop_slab_node(page_to_nid(p));
}
EXPORT_SYMBOL_GPL(shake_page);
@@ -391,8 +389,8 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
/*
* Kill the processes that have been collected earlier.
*
- * Only do anything when DOIT is set, otherwise just free the list
- * (this is used for clean pages which do not need killing)
+ * Only do anything when FORCEKILL is set, otherwise just free the
+ * list (this is used for clean pages which do not need killing)
* Also when FAIL is set do a force kill because something went
* wrong earlier.
*/
@@ -632,7 +630,7 @@ static int hwpoison_pte_range(pmd_t *pmdp, unsigned long addr,
{
struct hwp_walk *hwp = (struct hwp_walk *)walk->private;
int ret = 0;
- pte_t *ptep;
+ pte_t *ptep, *mapped_pte;
spinlock_t *ptl;
ptl = pmd_trans_huge_lock(pmdp, walk->vma);
@@ -645,14 +643,15 @@ static int hwpoison_pte_range(pmd_t *pmdp, unsigned long addr,
if (pmd_trans_unstable(pmdp))
goto out;
- ptep = pte_offset_map_lock(walk->vma->vm_mm, pmdp, addr, &ptl);
+ mapped_pte = ptep = pte_offset_map_lock(walk->vma->vm_mm, pmdp,
+ addr, &ptl);
for (; addr != end; ptep++, addr += PAGE_SIZE) {
ret = check_hwpoisoned_entry(*ptep, addr, PAGE_SHIFT,
hwp->pfn, &hwp->tk);
if (ret == 1)
break;
}
- pte_unmap_unlock(ptep - 1, ptl);
+ pte_unmap_unlock(mapped_pte, ptl);
out:
cond_resched();
return ret;
@@ -1204,7 +1203,7 @@ try_again:
* page, retry.
*/
if (pass++ < 3) {
- shake_page(p, 1);
+ shake_page(p);
goto try_again;
}
ret = -EIO;
@@ -1221,7 +1220,7 @@ try_again:
*/
if (pass++ < 3) {
put_page(p);
- shake_page(p, 1);
+ shake_page(p);
count_increased = false;
goto try_again;
}
@@ -1229,6 +1228,9 @@ try_again:
ret = -EIO;
}
out:
+ if (ret == -EIO)
+ dump_page(p, "hwpoison: unhandlable page");
+
return ret;
}
@@ -1270,14 +1272,13 @@ static int get_hwpoison_page(struct page *p, unsigned long flags)
* the pages and send SIGBUS to the processes if the data was dirty.
*/
static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
- int flags, struct page **hpagep)
+ int flags, struct page *hpage)
{
enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC;
struct address_space *mapping;
LIST_HEAD(tokill);
bool unmap_success;
int kill = 1, forcekill;
- struct page *hpage = *hpagep;
bool mlocked = PageMlocked(hpage);
/*
@@ -1369,7 +1370,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
* shake_page() again to ensure that it's flushed.
*/
if (mlocked)
- shake_page(hpage, 0);
+ shake_page(hpage);
/*
* Now that the dirty bit has been propagated to the
@@ -1502,7 +1503,7 @@ static int memory_failure_hugetlb(unsigned long pfn, int flags)
goto out;
}
- if (!hwpoison_user_mappings(p, pfn, flags, &head)) {
+ if (!hwpoison_user_mappings(p, pfn, flags, head)) {
action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);
res = -EBUSY;
goto out;
@@ -1518,7 +1519,6 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
struct dev_pagemap *pgmap)
{
struct page *page = pfn_to_page(pfn);
- const bool unmap_success = true;
unsigned long size = 0;
struct to_kill *tk;
LIST_HEAD(tokill);
@@ -1590,7 +1590,7 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
start = (page->index << PAGE_SHIFT) & ~(size - 1);
unmap_mapping_range(page->mapping, start, size, 0);
}
- kill_procs(&tokill, flags & MF_MUST_KILL, !unmap_success, pfn, flags);
+ kill_procs(&tokill, flags & MF_MUST_KILL, false, pfn, flags);
rc = 0;
unlock:
dax_unlock_page(page, cookie);
@@ -1724,7 +1724,7 @@ try_again:
* The check (unnecessarily) ignores LRU pages being isolated and
* walked by the page reclaim code, however that's not a big loss.
*/
- shake_page(p, 0);
+ shake_page(p);
lock_page(p);
@@ -1783,7 +1783,7 @@ try_again:
* Now take care of user space mappings.
* Abort on fail: __delete_from_page_cache() assumes unmapped page.
*/
- if (!hwpoison_user_mappings(p, pfn, flags, &p)) {
+ if (!hwpoison_user_mappings(p, pfn, flags, p)) {
action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);
res = -EBUSY;
goto unlock_page;
@@ -2099,7 +2099,7 @@ static int __soft_offline_page(struct page *page)
if (isolate_page(hpage, &pagelist)) {
ret = migrate_pages(&pagelist, alloc_migration_target, NULL,
- (unsigned long)&mtc, MIGRATE_SYNC, MR_MEMORY_FAILURE);
+ (unsigned long)&mtc, MIGRATE_SYNC, MR_MEMORY_FAILURE, NULL);
if (!ret) {
bool release = !huge;
@@ -2208,9 +2208,6 @@ retry:
try_again = false;
goto retry;
}
- } else if (ret == -EIO) {
- pr_info("%s: %#lx: unknown page type: %lx (%pGp)\n",
- __func__, pfn, page->flags, &page->flags);
}
return ret;
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 86c3af79e874..4c527a80b6c9 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1469,7 +1469,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
if (nodes_empty(nmask))
node_set(mtc.nid, nmask);
ret = migrate_pages(&source, alloc_migration_target, NULL,
- (unsigned long)&mtc, MIGRATE_SYNC, MR_MEMORY_HOTPLUG);
+ (unsigned long)&mtc, MIGRATE_SYNC, MR_MEMORY_HOTPLUG, NULL);
if (ret) {
list_for_each_entry(page, &source, lru) {
if (__ratelimit(&migrate_rs)) {
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index e32360e90274..5e90b3fb7794 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -31,6 +31,9 @@
* but useful to set in a VMA when you have a non default
* process policy.
*
+ * preferred many Try a set of nodes first before normal fallback. This is
+ * similar to preferred without the special case.
+ *
* default Allocate on the local node first, or when on a VMA
* use the process policy. This is what Linux always did
* in a NUMA aware kernel and still does by, ahem, default.
@@ -189,7 +192,7 @@ static void mpol_relative_nodemask(nodemask_t *ret, const nodemask_t *orig,
nodes_onto(*ret, tmp, *rel);
}
-static int mpol_new_interleave(struct mempolicy *pol, const nodemask_t *nodes)
+static int mpol_new_nodemask(struct mempolicy *pol, const nodemask_t *nodes)
{
if (nodes_empty(*nodes))
return -EINVAL;
@@ -207,14 +210,6 @@ static int mpol_new_preferred(struct mempolicy *pol, const nodemask_t *nodes)
return 0;
}
-static int mpol_new_bind(struct mempolicy *pol, const nodemask_t *nodes)
-{
- if (nodes_empty(*nodes))
- return -EINVAL;
- pol->nodes = *nodes;
- return 0;
-}
-
/*
* mpol_set_nodemask is called after mpol_new() to set up the nodemask, if
* any, for the new policy. mpol_new() has already validated the nodes
@@ -394,7 +389,7 @@ static const struct mempolicy_operations mpol_ops[MPOL_MAX] = {
.rebind = mpol_rebind_default,
},
[MPOL_INTERLEAVE] = {
- .create = mpol_new_interleave,
+ .create = mpol_new_nodemask,
.rebind = mpol_rebind_nodemask,
},
[MPOL_PREFERRED] = {
@@ -402,12 +397,16 @@ static const struct mempolicy_operations mpol_ops[MPOL_MAX] = {
.rebind = mpol_rebind_preferred,
},
[MPOL_BIND] = {
- .create = mpol_new_bind,
+ .create = mpol_new_nodemask,
.rebind = mpol_rebind_nodemask,
},
[MPOL_LOCAL] = {
.rebind = mpol_rebind_default,
},
+ [MPOL_PREFERRED_MANY] = {
+ .create = mpol_new_nodemask,
+ .rebind = mpol_rebind_preferred,
+ },
};
static int migrate_page_add(struct page *page, struct list_head *pagelist,
@@ -900,6 +899,7 @@ static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes)
case MPOL_BIND:
case MPOL_INTERLEAVE:
case MPOL_PREFERRED:
+ case MPOL_PREFERRED_MANY:
*nodes = p->nodes;
break;
case MPOL_LOCAL:
@@ -1084,7 +1084,7 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest,
if (!list_empty(&pagelist)) {
err = migrate_pages(&pagelist, alloc_migration_target, NULL,
- (unsigned long)&mtc, MIGRATE_SYNC, MR_SYSCALL);
+ (unsigned long)&mtc, MIGRATE_SYNC, MR_SYSCALL, NULL);
if (err)
putback_movable_pages(&pagelist);
}
@@ -1338,7 +1338,7 @@ static long do_mbind(unsigned long start, unsigned long len,
if (!list_empty(&pagelist)) {
WARN_ON_ONCE(flags & MPOL_MF_LAZY);
nr_failed = migrate_pages(&pagelist, new_page, NULL,
- start, MIGRATE_SYNC, MR_MEMPOLICY_MBIND);
+ start, MIGRATE_SYNC, MR_MEMPOLICY_MBIND, NULL);
if (nr_failed)
putback_movable_pages(&pagelist);
}
@@ -1446,7 +1446,8 @@ static inline int sanitize_mpol_flags(int *mode, unsigned short *flags)
{
*flags = *mode & MPOL_MODE_FLAGS;
*mode &= ~MPOL_MODE_FLAGS;
- if ((unsigned int)(*mode) >= MPOL_MAX)
+
+ if ((unsigned int)(*mode) >= MPOL_MAX)
return -EINVAL;
if ((*flags & MPOL_F_STATIC_NODES) && (*flags & MPOL_F_RELATIVE_NODES))
return -EINVAL;
@@ -1875,16 +1876,27 @@ static int apply_policy_zone(struct mempolicy *policy, enum zone_type zone)
*/
nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy)
{
+ int mode = policy->mode;
+
/* Lower zones don't get a nodemask applied for MPOL_BIND */
- if (unlikely(policy->mode == MPOL_BIND) &&
- apply_policy_zone(policy, gfp_zone(gfp)) &&
- cpuset_nodemask_valid_mems_allowed(&policy->nodes))
+ if (unlikely(mode == MPOL_BIND) &&
+ apply_policy_zone(policy, gfp_zone(gfp)) &&
+ cpuset_nodemask_valid_mems_allowed(&policy->nodes))
+ return &policy->nodes;
+
+ if (mode == MPOL_PREFERRED_MANY)
return &policy->nodes;
return NULL;
}
-/* Return the node id preferred by the given mempolicy, or the given id */
+/*
+ * Return the preferred node id for 'prefer' mempolicy, and return
+ * the given id for all other policies.
+ *
+ * policy_node() is always coupled with policy_nodemask(), which
+ * secures the nodemask limit for 'bind' and 'prefer-many' policy.
+ */
static int policy_node(gfp_t gfp, struct mempolicy *policy, int nd)
{
if (policy->mode == MPOL_PREFERRED) {
@@ -1922,7 +1934,7 @@ unsigned int mempolicy_slab_node(void)
struct mempolicy *policy;
int node = numa_mem_id();
- if (in_interrupt())
+ if (!in_task())
return node;
policy = current->mempolicy;
@@ -1936,7 +1948,9 @@ unsigned int mempolicy_slab_node(void)
case MPOL_INTERLEAVE:
return interleave_nodes(policy);
- case MPOL_BIND: {
+ case MPOL_BIND:
+ case MPOL_PREFERRED_MANY:
+ {
struct zoneref *z;
/*
@@ -2008,12 +2022,12 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
* @addr: address in @vma for shared policy lookup and interleave policy
* @gfp_flags: for requested zone
* @mpol: pointer to mempolicy pointer for reference counted mempolicy
- * @nodemask: pointer to nodemask pointer for MPOL_BIND nodemask
+ * @nodemask: pointer to nodemask pointer for 'bind' and 'prefer-many' policy
*
* Returns a nid suitable for a huge page allocation and a pointer
* to the struct mempolicy for conditional unref after allocation.
- * If the effective policy is 'BIND, returns a pointer to the mempolicy's
- * @nodemask for filtering the zonelist.
+ * If the effective policy is 'bind' or 'prefer-many', returns a pointer
+ * to the mempolicy's @nodemask for filtering the zonelist.
*
* Must be protected by read_mems_allowed_begin()
*/
@@ -2021,16 +2035,18 @@ int huge_node(struct vm_area_struct *vma, unsigned long addr, gfp_t gfp_flags,
struct mempolicy **mpol, nodemask_t **nodemask)
{
int nid;
+ int mode;
*mpol = get_vma_policy(vma, addr);
- *nodemask = NULL; /* assume !MPOL_BIND */
+ *nodemask = NULL;
+ mode = (*mpol)->mode;
- if (unlikely((*mpol)->mode == MPOL_INTERLEAVE)) {
+ if (unlikely(mode == MPOL_INTERLEAVE)) {
nid = interleave_nid(*mpol, vma, addr,
huge_page_shift(hstate_vma(vma)));
} else {
nid = policy_node(gfp_flags, *mpol, numa_node_id());
- if ((*mpol)->mode == MPOL_BIND)
+ if (mode == MPOL_BIND || mode == MPOL_PREFERRED_MANY)
*nodemask = &(*mpol)->nodes;
}
return nid;
@@ -2063,6 +2079,7 @@ bool init_nodemask_of_mempolicy(nodemask_t *mask)
mempolicy = current->mempolicy;
switch (mempolicy->mode) {
case MPOL_PREFERRED:
+ case MPOL_PREFERRED_MANY:
case MPOL_BIND:
case MPOL_INTERLEAVE:
*mask = mempolicy->nodes;
@@ -2128,6 +2145,27 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
return page;
}
+static struct page *alloc_pages_preferred_many(gfp_t gfp, unsigned int order,
+ int nid, struct mempolicy *pol)
+{
+ struct page *page;
+ gfp_t preferred_gfp;
+
+ /*
+ * This is a two pass approach. The first pass will only try the
+ * preferred nodes but skip the direct reclaim and allow the
+ * allocation to fail, while the second pass will try all the
+ * nodes in system.
+ */
+ preferred_gfp = gfp | __GFP_NOWARN;
+ preferred_gfp &= ~(__GFP_DIRECT_RECLAIM | __GFP_NOFAIL);
+ page = __alloc_pages(preferred_gfp, order, nid, &pol->nodes);
+ if (!page)
+ page = __alloc_pages(gfp, order, numa_node_id(), NULL);
+
+ return page;
+}
+
/**
* alloc_pages_vma - Allocate a page for a VMA.
* @gfp: GFP flags.
@@ -2163,6 +2201,12 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
goto out;
}
+ if (pol->mode == MPOL_PREFERRED_MANY) {
+ page = alloc_pages_preferred_many(gfp, order, node, pol);
+ mpol_cond_put(pol);
+ goto out;
+ }
+
if (unlikely(IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hugepage)) {
int hpage_node = node;
@@ -2173,7 +2217,7 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
* node and don't fall back to other nodes, as the cost of
* remote accesses would likely offset THP benefits.
*
- * If the policy is interleave, or does not allow the current
+ * If the policy is interleave or does not allow the current
* node in its nodemask, we allocate the standard way.
*/
if (pol->mode == MPOL_PREFERRED)
@@ -2240,6 +2284,9 @@ struct page *alloc_pages(gfp_t gfp, unsigned order)
*/
if (pol->mode == MPOL_INTERLEAVE)
page = alloc_page_interleave(gfp, order, interleave_nodes(pol));
+ else if (pol->mode == MPOL_PREFERRED_MANY)
+ page = alloc_pages_preferred_many(gfp, order,
+ numa_node_id(), pol);
else
page = __alloc_pages(gfp, order,
policy_node(gfp, pol, numa_node_id()),
@@ -2311,6 +2358,7 @@ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b)
case MPOL_BIND:
case MPOL_INTERLEAVE:
case MPOL_PREFERRED:
+ case MPOL_PREFERRED_MANY:
return !!nodes_equal(a->nodes, b->nodes);
case MPOL_LOCAL:
return true;
@@ -2425,8 +2473,8 @@ static void sp_free(struct sp_node *n)
* node id. Policy determination "mimics" alloc_page_vma().
* Called from fault path where we know the vma and faulting address.
*
- * Return: -1 if the page is in a node that is valid for this policy, or a
- * suitable node ID to allocate a replacement page from.
+ * Return: NUMA_NO_NODE if the page is in a node that is valid for this
+ * policy, or a suitable node ID to allocate a replacement page from.
*/
int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long addr)
{
@@ -2437,7 +2485,7 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
int thiscpu = raw_smp_processor_id();
int thisnid = cpu_to_node(thiscpu);
int polnid = NUMA_NO_NODE;
- int ret = -1;
+ int ret = NUMA_NO_NODE;
pol = get_vma_policy(vma, addr);
if (!(pol->flags & MPOL_F_MOF))
@@ -2451,6 +2499,8 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
break;
case MPOL_PREFERRED:
+ if (node_isset(curnid, pol->nodes))
+ goto out;
polnid = first_node(pol->nodes);
break;
@@ -2465,9 +2515,10 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
break;
goto out;
}
+ fallthrough;
+ case MPOL_PREFERRED_MANY:
/*
- * allows binding to multiple nodes.
* use current page if in policy nodemask,
* else select nearest allowed node, if any.
* If no allowed nodes, use current [!misplaced].
@@ -2829,6 +2880,7 @@ static const char * const policy_modes[] =
[MPOL_BIND] = "bind",
[MPOL_INTERLEAVE] = "interleave",
[MPOL_LOCAL] = "local",
+ [MPOL_PREFERRED_MANY] = "prefer (many)",
};
@@ -2907,6 +2959,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
if (!nodelist)
err = 0;
goto out;
+ case MPOL_PREFERRED_MANY:
case MPOL_BIND:
/*
* Insist on a nodelist
@@ -2993,6 +3046,7 @@ void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
case MPOL_LOCAL:
break;
case MPOL_PREFERRED:
+ case MPOL_PREFERRED_MANY:
case MPOL_BIND:
case MPOL_INTERLEAVE:
nodes = pol->nodes;
@@ -3021,3 +3075,64 @@ void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
p += scnprintf(p, buffer + maxlen - p, ":%*pbl",
nodemask_pr_args(&nodes));
}
+
+bool numa_demotion_enabled = false;
+
+#ifdef CONFIG_SYSFS
+static ssize_t numa_demotion_enabled_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%s\n",
+ numa_demotion_enabled? "true" : "false");
+}
+
+static ssize_t numa_demotion_enabled_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (!strncmp(buf, "true", 4) || !strncmp(buf, "1", 1))
+ numa_demotion_enabled = true;
+ else if (!strncmp(buf, "false", 5) || !strncmp(buf, "0", 1))
+ numa_demotion_enabled = false;
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static struct kobj_attribute numa_demotion_enabled_attr =
+ __ATTR(demotion_enabled, 0644, numa_demotion_enabled_show,
+ numa_demotion_enabled_store);
+
+static struct attribute *numa_attrs[] = {
+ &numa_demotion_enabled_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group numa_attr_group = {
+ .attrs = numa_attrs,
+};
+
+static int __init numa_init_sysfs(void)
+{
+ int err;
+ struct kobject *numa_kobj;
+
+ numa_kobj = kobject_create_and_add("numa", mm_kobj);
+ if (!numa_kobj) {
+ pr_err("failed to create numa kobject\n");
+ return -ENOMEM;
+ }
+ err = sysfs_create_group(numa_kobj, &numa_attr_group);
+ if (err) {
+ pr_err("failed to register numa group\n");
+ goto delete_obj;
+ }
+ return 0;
+
+delete_obj:
+ kobject_put(numa_kobj);
+ return err;
+}
+subsys_initcall(numa_init_sysfs);
+#endif
diff --git a/mm/migrate.c b/mm/migrate.c
index 7e240437e7d9..a0aeb3fe46a7 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -49,6 +49,7 @@
#include <linux/sched/mm.h>
#include <linux/ptrace.h>
#include <linux/oom.h>
+#include <linux/memory.h>
#include <asm/tlbflush.h>
@@ -1099,6 +1100,80 @@ out:
return rc;
}
+
+/*
+ * node_demotion[] example:
+ *
+ * Consider a system with two sockets. Each socket has
+ * three classes of memory attached: fast, medium and slow.
+ * Each memory class is placed in its own NUMA node. The
+ * CPUs are placed in the node with the "fast" memory. The
+ * 6 NUMA nodes (0-5) might be split among the sockets like
+ * this:
+ *
+ * Socket A: 0, 1, 2
+ * Socket B: 3, 4, 5
+ *
+ * When Node 0 fills up, its memory should be migrated to
+ * Node 1. When Node 1 fills up, it should be migrated to
+ * Node 2. The migration path start on the nodes with the
+ * processors (since allocations default to this node) and
+ * fast memory, progress through medium and end with the
+ * slow memory:
+ *
+ * 0 -> 1 -> 2 -> stop
+ * 3 -> 4 -> 5 -> stop
+ *
+ * This is represented in the node_demotion[] like this:
+ *
+ * { 1, // Node 0 migrates to 1
+ * 2, // Node 1 migrates to 2
+ * -1, // Node 2 does not migrate
+ * 4, // Node 3 migrates to 4
+ * 5, // Node 4 migrates to 5
+ * -1} // Node 5 does not migrate
+ */
+
+/*
+ * Writes to this array occur without locking. Cycles are
+ * not allowed: Node X demotes to Y which demotes to X...
+ *
+ * If multiple reads are performed, a single rcu_read_lock()
+ * must be held over all reads to ensure that no cycles are
+ * observed.
+ */
+static int node_demotion[MAX_NUMNODES] __read_mostly =
+ {[0 ... MAX_NUMNODES - 1] = NUMA_NO_NODE};
+
+/**
+ * next_demotion_node() - Get the next node in the demotion path
+ * @node: The starting node to lookup the next node
+ *
+ * Return: node id for next memory node in the demotion path hierarchy
+ * from @node; NUMA_NO_NODE if @node is terminal. This does not keep
+ * @node online or guarantee that it *continues* to be the next demotion
+ * target.
+ */
+int next_demotion_node(int node)
+{
+ int target;
+
+ /*
+ * node_demotion[] is updated without excluding this
+ * function from running. RCU doesn't provide any
+ * compiler barriers, so the READ_ONCE() is required
+ * to avoid compiler reordering or read merging.
+ *
+ * Make sure to use RCU over entire code blocks if
+ * node_demotion[] reads need to be consistent.
+ */
+ rcu_read_lock();
+ target = READ_ONCE(node_demotion[node]);
+ rcu_read_unlock();
+
+ return target;
+}
+
/*
* Obtain the lock on page, remove all ptes and migrate the page
* to the newly allocated page in newpage.
@@ -1354,6 +1429,8 @@ static inline int try_split_thp(struct page *page, struct page **page2,
* @mode: The migration mode that specifies the constraints for
* page migration, if any.
* @reason: The reason for page migration.
+ * @ret_succeeded: Set to the number of pages migrated successfully if
+ * the caller passes a non-NULL pointer.
*
* The function returns after 10 attempts or if no pages are movable any more
* because the list has become empty or no retryable pages exist any more.
@@ -1364,7 +1441,7 @@ static inline int try_split_thp(struct page *page, struct page **page2,
*/
int migrate_pages(struct list_head *from, new_page_t get_new_page,
free_page_t put_new_page, unsigned long private,
- enum migrate_mode mode, int reason)
+ enum migrate_mode mode, int reason, unsigned int *ret_succeeded)
{
int retry = 1;
int thp_retry = 1;
@@ -1519,6 +1596,9 @@ out:
if (!swapwrite)
current->flags &= ~PF_SWAPWRITE;
+ if (ret_succeeded)
+ *ret_succeeded = nr_succeeded;
+
return rc;
}
@@ -1588,7 +1668,7 @@ static int do_move_pages_to_node(struct mm_struct *mm,
};
err = migrate_pages(pagelist, alloc_migration_target, NULL,
- (unsigned long)&mtc, MIGRATE_SYNC, MR_SYSCALL);
+ (unsigned long)&mtc, MIGRATE_SYNC, MR_SYSCALL, NULL);
if (err)
putback_movable_pages(pagelist);
return err;
@@ -2103,7 +2183,7 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
list_add(&page->lru, &migratepages);
nr_remaining = migrate_pages(&migratepages, *new, NULL, node,
- MIGRATE_ASYNC, MR_NUMA_MISPLACED);
+ MIGRATE_ASYNC, MR_NUMA_MISPLACED, NULL);
if (nr_remaining) {
if (!list_empty(&migratepages)) {
list_del(&page->lru);
@@ -2982,3 +3062,232 @@ void migrate_vma_finalize(struct migrate_vma *migrate)
}
EXPORT_SYMBOL(migrate_vma_finalize);
#endif /* CONFIG_DEVICE_PRIVATE */
+
+#if defined(CONFIG_MEMORY_HOTPLUG)
+/* Disable reclaim-based migration. */
+static void __disable_all_migrate_targets(void)
+{
+ int node;
+
+ for_each_online_node(node)
+ node_demotion[node] = NUMA_NO_NODE;
+}
+
+static void disable_all_migrate_targets(void)
+{
+ __disable_all_migrate_targets();
+
+ /*
+ * Ensure that the "disable" is visible across the system.
+ * Readers will see either a combination of before+disable
+ * state or disable+after. They will never see before and
+ * after state together.
+ *
+ * The before+after state together might have cycles and
+ * could cause readers to do things like loop until this
+ * function finishes. This ensures they can only see a
+ * single "bad" read and would, for instance, only loop
+ * once.
+ */
+ synchronize_rcu();
+}
+
+/*
+ * Find an automatic demotion target for 'node'.
+ * Failing here is OK. It might just indicate
+ * being at the end of a chain.
+ */
+static int establish_migrate_target(int node, nodemask_t *used)
+{
+ int migration_target;
+
+ /*
+ * Can not set a migration target on a
+ * node with it already set.
+ *
+ * No need for READ_ONCE() here since this
+ * in the write path for node_demotion[].
+ * This should be the only thread writing.
+ */
+ if (node_demotion[node] != NUMA_NO_NODE)
+ return NUMA_NO_NODE;
+
+ migration_target = find_next_best_node(node, used);
+ if (migration_target == NUMA_NO_NODE)
+ return NUMA_NO_NODE;
+
+ node_demotion[node] = migration_target;
+
+ return migration_target;
+}
+
+/*
+ * When memory fills up on a node, memory contents can be
+ * automatically migrated to another node instead of
+ * discarded at reclaim.
+ *
+ * Establish a "migration path" which will start at nodes
+ * with CPUs and will follow the priorities used to build the
+ * page allocator zonelists.
+ *
+ * The difference here is that cycles must be avoided. If
+ * node0 migrates to node1, then neither node1, nor anything
+ * node1 migrates to can migrate to node0.
+ *
+ * This function can run simultaneously with readers of
+ * node_demotion[]. However, it can not run simultaneously
+ * with itself. Exclusion is provided by memory hotplug events
+ * being single-threaded.
+ */
+static void __set_migration_target_nodes(void)
+{
+ nodemask_t next_pass = NODE_MASK_NONE;
+ nodemask_t this_pass = NODE_MASK_NONE;
+ nodemask_t used_targets = NODE_MASK_NONE;
+ int node;
+
+ /*
+ * Avoid any oddities like cycles that could occur
+ * from changes in the topology. This will leave
+ * a momentary gap when migration is disabled.
+ */
+ disable_all_migrate_targets();
+
+ /*
+ * Allocations go close to CPUs, first. Assume that
+ * the migration path starts at the nodes with CPUs.
+ */
+ next_pass = node_states[N_CPU];
+again:
+ this_pass = next_pass;
+ next_pass = NODE_MASK_NONE;
+ /*
+ * To avoid cycles in the migration "graph", ensure
+ * that migration sources are not future targets by
+ * setting them in 'used_targets'. Do this only
+ * once per pass so that multiple source nodes can
+ * share a target node.
+ *
+ * 'used_targets' will become unavailable in future
+ * passes. This limits some opportunities for
+ * multiple source nodes to share a destination.
+ */
+ nodes_or(used_targets, used_targets, this_pass);
+ for_each_node_mask(node, this_pass) {
+ int target_node = establish_migrate_target(node, &used_targets);
+
+ if (target_node == NUMA_NO_NODE)
+ continue;
+
+ /*
+ * Visit targets from this pass in the next pass.
+ * Eventually, every node will have been part of
+ * a pass, and will become set in 'used_targets'.
+ */
+ node_set(target_node, next_pass);
+ }
+ /*
+ * 'next_pass' contains nodes which became migration
+ * targets in this pass. Make additional passes until
+ * no more migrations targets are available.
+ */
+ if (!nodes_empty(next_pass))
+ goto again;
+}
+
+/*
+ * For callers that do not hold get_online_mems() already.
+ */
+static void set_migration_target_nodes(void)
+{
+ get_online_mems();
+ __set_migration_target_nodes();
+ put_online_mems();
+}
+
+/*
+ * React to hotplug events that might affect the migration targets
+ * like events that online or offline NUMA nodes.
+ *
+ * The ordering is also currently dependent on which nodes have
+ * CPUs. That means we need CPU on/offline notification too.
+ */
+static int migration_online_cpu(unsigned int cpu)
+{
+ set_migration_target_nodes();
+ return 0;
+}
+
+static int migration_offline_cpu(unsigned int cpu)
+{
+ set_migration_target_nodes();
+ return 0;
+}
+
+/*
+ * This leaves migrate-on-reclaim transiently disabled between
+ * the MEM_GOING_OFFLINE and MEM_OFFLINE events. This runs
+ * whether reclaim-based migration is enabled or not, which
+ * ensures that the user can turn reclaim-based migration at
+ * any time without needing to recalculate migration targets.
+ *
+ * These callbacks already hold get_online_mems(). That is why
+ * __set_migration_target_nodes() can be used as opposed to
+ * set_migration_target_nodes().
+ */
+static int __meminit migrate_on_reclaim_callback(struct notifier_block *self,
+ unsigned long action, void *arg)
+{
+ switch (action) {
+ case MEM_GOING_OFFLINE:
+ /*
+ * Make sure there are not transient states where
+ * an offline node is a migration target. This
+ * will leave migration disabled until the offline
+ * completes and the MEM_OFFLINE case below runs.
+ */
+ disable_all_migrate_targets();
+ break;
+ case MEM_OFFLINE:
+ case MEM_ONLINE:
+ /*
+ * Recalculate the target nodes once the node
+ * reaches its final state (online or offline).
+ */
+ __set_migration_target_nodes();
+ break;
+ case MEM_CANCEL_OFFLINE:
+ /*
+ * MEM_GOING_OFFLINE disabled all the migration
+ * targets. Reenable them.
+ */
+ __set_migration_target_nodes();
+ break;
+ case MEM_GOING_ONLINE:
+ case MEM_CANCEL_ONLINE:
+ break;
+ }
+
+ return notifier_from_errno(0);
+}
+
+static int __init migrate_on_reclaim_init(void)
+{
+ int ret;
+
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "migrate on reclaim",
+ migration_online_cpu,
+ migration_offline_cpu);
+ /*
+ * In the unlikely case that this fails, the automatic
+ * migration targets may become suboptimal for nodes
+ * where N_CPU changes. With such a small impact in a
+ * rare case, do not bother trying to do anything special.
+ */
+ WARN_ON(ret < 0);
+
+ hotplug_memory_notifier(migrate_on_reclaim_callback, 100);
+ return 0;
+}
+late_initcall(migrate_on_reclaim_init);
+#endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/mm/mmap.c b/mm/mmap.c
index 181a113b545d..88dcc5c25225 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -148,8 +148,6 @@ void vma_set_page_prot(struct vm_area_struct *vma)
static void __remove_shared_vm_struct(struct vm_area_struct *vma,
struct file *file, struct address_space *mapping)
{
- if (vma->vm_flags & VM_DENYWRITE)
- allow_write_access(file);
if (vma->vm_flags & VM_SHARED)
mapping_unmap_writable(mapping);
@@ -534,6 +532,7 @@ static int find_vma_links(struct mm_struct *mm, unsigned long addr,
{
struct rb_node **__rb_link, *__rb_parent, *rb_prev;
+ mmap_assert_locked(mm);
__rb_link = &mm->mm_rb.rb_node;
rb_prev = __rb_parent = NULL;
@@ -666,8 +665,6 @@ static void __vma_link_file(struct vm_area_struct *vma)
if (file) {
struct address_space *mapping = file->f_mapping;
- if (vma->vm_flags & VM_DENYWRITE)
- put_write_access(file_inode(file));
if (vma->vm_flags & VM_SHARED)
mapping_allow_writable(mapping);
@@ -1624,8 +1621,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
return PTR_ERR(file);
}
- flags &= ~MAP_DENYWRITE;
-
retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
out_fput:
if (file)
@@ -1782,22 +1777,12 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
vma->vm_pgoff = pgoff;
if (file) {
- if (vm_flags & VM_DENYWRITE) {
- error = deny_write_access(file);
- if (error)
- goto free_vma;
- }
if (vm_flags & VM_SHARED) {
error = mapping_map_writable(file->f_mapping);
if (error)
- goto allow_write_and_free_vma;
+ goto free_vma;
}
- /* ->mmap() can change vma->vm_file, but must guarantee that
- * vma_link() below can deny write-access if VM_DENYWRITE is set
- * and map writably if VM_SHARED is set. This usually means the
- * new file must not have been exposed to user-space, yet.
- */
vma->vm_file = get_file(file);
error = call_mmap(file, vma);
if (error)
@@ -1854,13 +1839,9 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
vma_link(mm, vma, prev, rb_link, rb_parent);
/* Once vma denies write, undo our temporary denial count */
- if (file) {
unmap_writable:
- if (vm_flags & VM_SHARED)
- mapping_unmap_writable(file->f_mapping);
- if (vm_flags & VM_DENYWRITE)
- allow_write_access(file);
- }
+ if (file && vm_flags & VM_SHARED)
+ mapping_unmap_writable(file->f_mapping);
file = vma->vm_file;
out:
perf_event_mmap(vma);
@@ -1900,9 +1881,6 @@ unmap_and_free_vma:
charged = 0;
if (vm_flags & VM_SHARED)
mapping_unmap_writable(file->f_mapping);
-allow_write_and_free_vma:
- if (vm_flags & VM_DENYWRITE)
- allow_write_access(file);
free_vma:
vm_area_free(vma);
unacct_error:
@@ -2297,6 +2275,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
struct rb_node *rb_node;
struct vm_area_struct *vma;
+ mmap_assert_locked(mm);
/* Check the cache first. */
vma = vmacache_find(mm, addr);
if (likely(vma))
@@ -2986,14 +2965,11 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
if (mmap_write_lock_killable(mm))
return -EINTR;
- vma = find_vma(mm, start);
+ vma = vma_lookup(mm, start);
if (!vma || !(vma->vm_flags & VM_SHARED))
goto out;
- if (start < vma->vm_start)
- goto out;
-
if (start + size > vma->vm_end) {
struct vm_area_struct *next;
diff --git a/mm/mremap.c b/mm/mremap.c
index 5989d3990020..badfe17ade1f 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -686,7 +686,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
if (do_munmap(mm, old_addr, old_len, uf_unmap) < 0) {
/* OOM: unable to split vma, just get accounts right */
if (vm_flags & VM_ACCOUNT && !(flags & MREMAP_DONTUNMAP))
- vm_acct_memory(new_len >> PAGE_SHIFT);
+ vm_acct_memory(old_len >> PAGE_SHIFT);
excess = 0;
}
diff --git a/mm/nommu.c b/mm/nommu.c
index 9d0ad98f838c..02d2427b8f9e 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1293,8 +1293,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
goto out;
}
- flags &= ~MAP_DENYWRITE;
-
retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
if (file)
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index c729a4c4a1ac..831340e7ad8b 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -28,6 +28,7 @@
#include <linux/sched/task.h>
#include <linux/sched/debug.h>
#include <linux/swap.h>
+#include <linux/syscalls.h>
#include <linux/timex.h>
#include <linux/jiffies.h>
#include <linux/cpuset.h>
@@ -1141,3 +1142,72 @@ void pagefault_out_of_memory(void)
out_of_memory(&oc);
mutex_unlock(&oom_lock);
}
+
+SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags)
+{
+#ifdef CONFIG_MMU
+ struct mm_struct *mm = NULL;
+ struct task_struct *task;
+ struct task_struct *p;
+ unsigned int f_flags;
+ bool reap = true;
+ struct pid *pid;
+ long ret = 0;
+
+ if (flags)
+ return -EINVAL;
+
+ pid = pidfd_get_pid(pidfd, &f_flags);
+ if (IS_ERR(pid))
+ return PTR_ERR(pid);
+
+ task = get_pid_task(pid, PIDTYPE_TGID);
+ if (!task) {
+ ret = -ESRCH;
+ goto put_pid;
+ }
+
+ /*
+ * Make sure to choose a thread which still has a reference to mm
+ * during the group exit
+ */
+ p = find_lock_task_mm(task);
+ if (!p) {
+ ret = -ESRCH;
+ goto put_task;
+ }
+
+ mm = p->mm;
+ mmgrab(mm);
+
+ /* If the work has been done already, just exit with success */
+ if (test_bit(MMF_OOM_SKIP, &mm->flags))
+ reap = false;
+ else if (!task_will_free_mem(p)) {
+ reap = false;
+ ret = -EINVAL;
+ }
+ task_unlock(p);
+
+ if (!reap)
+ goto drop_mm;
+
+ if (mmap_read_lock_killable(mm)) {
+ ret = -EINTR;
+ goto drop_mm;
+ }
+ if (!__oom_reap_task_mm(mm))
+ ret = -EAGAIN;
+ mmap_read_unlock(mm);
+
+drop_mm:
+ mmdrop(mm);
+put_task:
+ put_task_struct(task);
+put_pid:
+ put_pid(pid);
+ return ret;
+#else
+ return -ENOSYS;
+#endif /* CONFIG_MMU */
+}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index c12f67cbfa19..4812a17b288c 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -183,7 +183,7 @@ static struct fprop_local_percpu *wb_memcg_completions(struct bdi_writeback *wb)
static void wb_min_max_ratio(struct bdi_writeback *wb,
unsigned long *minp, unsigned long *maxp)
{
- unsigned long this_bw = wb->avg_write_bandwidth;
+ unsigned long this_bw = READ_ONCE(wb->avg_write_bandwidth);
unsigned long tot_bw = atomic_long_read(&wb->bdi->tot_write_bandwidth);
unsigned long long min = wb->bdi->min_ratio;
unsigned long long max = wb->bdi->max_ratio;
@@ -892,7 +892,7 @@ static long long pos_ratio_polynom(unsigned long setpoint,
static void wb_position_ratio(struct dirty_throttle_control *dtc)
{
struct bdi_writeback *wb = dtc->wb;
- unsigned long write_bw = wb->avg_write_bandwidth;
+ unsigned long write_bw = READ_ONCE(wb->avg_write_bandwidth);
unsigned long freerun = dirty_freerun_ceiling(dtc->thresh, dtc->bg_thresh);
unsigned long limit = hard_dirty_limit(dtc_dom(dtc), dtc->thresh);
unsigned long wb_thresh = dtc->wb_thresh;
@@ -1115,7 +1115,7 @@ out:
&wb->bdi->tot_write_bandwidth) <= 0);
}
wb->write_bandwidth = bw;
- wb->avg_write_bandwidth = avg;
+ WRITE_ONCE(wb->avg_write_bandwidth, avg);
}
static void update_dirty_limit(struct dirty_throttle_control *dtc)
@@ -1147,8 +1147,8 @@ update:
dom->dirty_limit = limit;
}
-static void domain_update_bandwidth(struct dirty_throttle_control *dtc,
- unsigned long now)
+static void domain_update_dirty_limit(struct dirty_throttle_control *dtc,
+ unsigned long now)
{
struct wb_domain *dom = dtc_dom(dtc);
@@ -1324,7 +1324,7 @@ static void wb_update_dirty_ratelimit(struct dirty_throttle_control *dtc,
else
dirty_ratelimit -= step;
- wb->dirty_ratelimit = max(dirty_ratelimit, 1UL);
+ WRITE_ONCE(wb->dirty_ratelimit, max(dirty_ratelimit, 1UL));
wb->balanced_dirty_ratelimit = balanced_dirty_ratelimit;
trace_bdi_dirty_ratelimit(wb, dirty_rate, task_ratelimit);
@@ -1332,35 +1332,28 @@ static void wb_update_dirty_ratelimit(struct dirty_throttle_control *dtc,
static void __wb_update_bandwidth(struct dirty_throttle_control *gdtc,
struct dirty_throttle_control *mdtc,
- unsigned long start_time,
bool update_ratelimit)
{
struct bdi_writeback *wb = gdtc->wb;
unsigned long now = jiffies;
- unsigned long elapsed = now - wb->bw_time_stamp;
+ unsigned long elapsed;
unsigned long dirtied;
unsigned long written;
- lockdep_assert_held(&wb->list_lock);
+ spin_lock(&wb->list_lock);
/*
- * rate-limit, only update once every 200ms.
+ * Lockless checks for elapsed time are racy and delayed update after
+ * IO completion doesn't do it at all (to make sure written pages are
+ * accounted reasonably quickly). Make sure elapsed >= 1 to avoid
+ * division errors.
*/
- if (elapsed < BANDWIDTH_INTERVAL)
- return;
-
+ elapsed = max(now - wb->bw_time_stamp, 1UL);
dirtied = percpu_counter_read(&wb->stat[WB_DIRTIED]);
written = percpu_counter_read(&wb->stat[WB_WRITTEN]);
- /*
- * Skip quiet periods when disk bandwidth is under-utilized.
- * (at least 1s idle time between two flusher runs)
- */
- if (elapsed > HZ && time_before(wb->bw_time_stamp, start_time))
- goto snapshot;
-
if (update_ratelimit) {
- domain_update_bandwidth(gdtc, now);
+ domain_update_dirty_limit(gdtc, now);
wb_update_dirty_ratelimit(gdtc, dirtied, elapsed);
/*
@@ -1368,23 +1361,41 @@ static void __wb_update_bandwidth(struct dirty_throttle_control *gdtc,
* compiler has no way to figure that out. Help it.
*/
if (IS_ENABLED(CONFIG_CGROUP_WRITEBACK) && mdtc) {
- domain_update_bandwidth(mdtc, now);
+ domain_update_dirty_limit(mdtc, now);
wb_update_dirty_ratelimit(mdtc, dirtied, elapsed);
}
}
wb_update_write_bandwidth(wb, elapsed, written);
-snapshot:
wb->dirtied_stamp = dirtied;
wb->written_stamp = written;
- wb->bw_time_stamp = now;
+ WRITE_ONCE(wb->bw_time_stamp, now);
+ spin_unlock(&wb->list_lock);
}
-void wb_update_bandwidth(struct bdi_writeback *wb, unsigned long start_time)
+void wb_update_bandwidth(struct bdi_writeback *wb)
{
struct dirty_throttle_control gdtc = { GDTC_INIT(wb) };
- __wb_update_bandwidth(&gdtc, NULL, start_time, false);
+ __wb_update_bandwidth(&gdtc, NULL, false);
+}
+
+/* Interval after which we consider wb idle and don't estimate bandwidth */
+#define WB_BANDWIDTH_IDLE_JIF (HZ)
+
+static void wb_bandwidth_estimate_start(struct bdi_writeback *wb)
+{
+ unsigned long now = jiffies;
+ unsigned long elapsed = now - READ_ONCE(wb->bw_time_stamp);
+
+ if (elapsed > WB_BANDWIDTH_IDLE_JIF &&
+ !atomic_read(&wb->writeback_inodes)) {
+ spin_lock(&wb->list_lock);
+ wb->dirtied_stamp = wb_stat(wb, WB_DIRTIED);
+ wb->written_stamp = wb_stat(wb, WB_WRITTEN);
+ WRITE_ONCE(wb->bw_time_stamp, now);
+ spin_unlock(&wb->list_lock);
+ }
}
/*
@@ -1407,7 +1418,7 @@ static unsigned long dirty_poll_interval(unsigned long dirty,
static unsigned long wb_max_pause(struct bdi_writeback *wb,
unsigned long wb_dirty)
{
- unsigned long bw = wb->avg_write_bandwidth;
+ unsigned long bw = READ_ONCE(wb->avg_write_bandwidth);
unsigned long t;
/*
@@ -1429,8 +1440,8 @@ static long wb_min_pause(struct bdi_writeback *wb,
unsigned long dirty_ratelimit,
int *nr_dirtied_pause)
{
- long hi = ilog2(wb->avg_write_bandwidth);
- long lo = ilog2(wb->dirty_ratelimit);
+ long hi = ilog2(READ_ONCE(wb->avg_write_bandwidth));
+ long lo = ilog2(READ_ONCE(wb->dirty_ratelimit));
long t; /* target pause */
long pause; /* estimated next pause */
int pages; /* target nr_dirtied_pause */
@@ -1710,15 +1721,12 @@ free_running:
if (dirty_exceeded && !wb->dirty_exceeded)
wb->dirty_exceeded = 1;
- if (time_is_before_jiffies(wb->bw_time_stamp +
- BANDWIDTH_INTERVAL)) {
- spin_lock(&wb->list_lock);
- __wb_update_bandwidth(gdtc, mdtc, start_time, true);
- spin_unlock(&wb->list_lock);
- }
+ if (time_is_before_jiffies(READ_ONCE(wb->bw_time_stamp) +
+ BANDWIDTH_INTERVAL))
+ __wb_update_bandwidth(gdtc, mdtc, true);
/* throttle according to the chosen dtc */
- dirty_ratelimit = wb->dirty_ratelimit;
+ dirty_ratelimit = READ_ONCE(wb->dirty_ratelimit);
task_ratelimit = ((u64)dirty_ratelimit * sdtc->pos_ratio) >>
RATELIMIT_CALC_SHIFT;
max_pause = wb_max_pause(wb, sdtc->wb_dirty);
@@ -2345,9 +2353,12 @@ EXPORT_SYMBOL(generic_writepages);
int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
int ret;
+ struct bdi_writeback *wb;
if (wbc->nr_to_write <= 0)
return 0;
+ wb = inode_to_wb_wbc(mapping->host, wbc);
+ wb_bandwidth_estimate_start(wb);
while (1) {
if (mapping->a_ops->writepages)
ret = mapping->a_ops->writepages(mapping, wbc);
@@ -2358,6 +2369,14 @@ int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
cond_resched();
congestion_wait(BLK_RW_ASYNC, HZ/50);
}
+ /*
+ * Usually few pages are written by now from those we've just submitted
+ * but if there's constant writeback being submitted, this makes sure
+ * writeback bandwidth is updated once in a while.
+ */
+ if (time_is_before_jiffies(READ_ONCE(wb->bw_time_stamp) +
+ BANDWIDTH_INTERVAL))
+ wb_update_bandwidth(wb);
return ret;
}
@@ -2729,6 +2748,24 @@ int clear_page_dirty_for_io(struct page *page)
}
EXPORT_SYMBOL(clear_page_dirty_for_io);
+static void wb_inode_writeback_start(struct bdi_writeback *wb)
+{
+ atomic_inc(&wb->writeback_inodes);
+}
+
+static void wb_inode_writeback_end(struct bdi_writeback *wb)
+{
+ atomic_dec(&wb->writeback_inodes);
+ /*
+ * Make sure estimate of writeback throughput gets updated after
+ * writeback completed. We delay the update by BANDWIDTH_INTERVAL
+ * (which is the interval other bandwidth updates use for batching) so
+ * that if multiple inodes end writeback at a similar time, they get
+ * batched into one bandwidth update.
+ */
+ queue_delayed_work(bdi_wq, &wb->bw_dwork, BANDWIDTH_INTERVAL);
+}
+
int test_clear_page_writeback(struct page *page)
{
struct address_space *mapping = page_mapping(page);
@@ -2750,6 +2787,9 @@ int test_clear_page_writeback(struct page *page)
dec_wb_stat(wb, WB_WRITEBACK);
__wb_writeout_inc(wb);
+ if (!mapping_tagged(mapping,
+ PAGECACHE_TAG_WRITEBACK))
+ wb_inode_writeback_end(wb);
}
}
@@ -2792,8 +2832,13 @@ int __test_set_page_writeback(struct page *page, bool keep_write)
PAGECACHE_TAG_WRITEBACK);
xas_set_mark(&xas, PAGECACHE_TAG_WRITEBACK);
- if (bdi->capabilities & BDI_CAP_WRITEBACK_ACCT)
- inc_wb_stat(inode_to_wb(inode), WB_WRITEBACK);
+ if (bdi->capabilities & BDI_CAP_WRITEBACK_ACCT) {
+ struct bdi_writeback *wb = inode_to_wb(inode);
+
+ inc_wb_stat(wb, WB_WRITEBACK);
+ if (!on_wblist)
+ wb_inode_writeback_start(wb);
+ }
/*
* We can come through here when swapping anonymous
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index eeb3a9cb36bb..f95e1d2386a1 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4211,7 +4211,7 @@ static void warn_alloc_show_mem(gfp_t gfp_mask, nodemask_t *nodemask)
if (tsk_is_oom_victim(current) ||
(current->flags & (PF_MEMALLOC | PF_EXITING)))
filter &= ~SHOW_MEM_FILTER_NODES;
- if (in_interrupt() || !(gfp_mask & __GFP_DIRECT_RECLAIM))
+ if (!in_task() || !(gfp_mask & __GFP_DIRECT_RECLAIM))
filter &= ~SHOW_MEM_FILTER_NODES;
show_mem(filter, nodemask);
@@ -4549,14 +4549,14 @@ static bool __need_reclaim(gfp_t gfp_mask)
return true;
}
-void __fs_reclaim_acquire(void)
+void __fs_reclaim_acquire(unsigned long ip)
{
- lock_map_acquire(&__fs_reclaim_map);
+ lock_acquire_exclusive(&__fs_reclaim_map, 0, 0, NULL, ip);
}
-void __fs_reclaim_release(void)
+void __fs_reclaim_release(unsigned long ip)
{
- lock_map_release(&__fs_reclaim_map);
+ lock_release(&__fs_reclaim_map, ip);
}
void fs_reclaim_acquire(gfp_t gfp_mask)
@@ -4565,7 +4565,7 @@ void fs_reclaim_acquire(gfp_t gfp_mask)
if (__need_reclaim(gfp_mask)) {
if (gfp_mask & __GFP_FS)
- __fs_reclaim_acquire();
+ __fs_reclaim_acquire(_RET_IP_);
#ifdef CONFIG_MMU_NOTIFIER
lock_map_acquire(&__mmu_notifier_invalidate_range_start_map);
@@ -4582,7 +4582,7 @@ void fs_reclaim_release(gfp_t gfp_mask)
if (__need_reclaim(gfp_mask)) {
if (gfp_mask & __GFP_FS)
- __fs_reclaim_release();
+ __fs_reclaim_release(_RET_IP_);
}
}
EXPORT_SYMBOL_GPL(fs_reclaim_release);
@@ -4697,7 +4697,7 @@ gfp_to_alloc_flags(gfp_t gfp_mask)
* comment for __cpuset_node_allowed().
*/
alloc_flags &= ~ALLOC_CPUSET;
- } else if (unlikely(rt_task(current)) && !in_interrupt())
+ } else if (unlikely(rt_task(current)) && in_task())
alloc_flags |= ALLOC_HARDER;
alloc_flags = gfp_to_alloc_flags_cma(gfp_mask, alloc_flags);
@@ -5157,7 +5157,7 @@ static inline bool prepare_alloc_pages(gfp_t gfp_mask, unsigned int order,
* When we are in the interrupt context, it is irrelevant
* to the current task context. It means that any node ok.
*/
- if (!in_interrupt() && !ac->nodemask)
+ if (in_task() && !ac->nodemask)
ac->nodemask = &cpuset_current_mems_allowed;
else
*alloc_flags |= ALLOC_CPUSET;
@@ -5903,6 +5903,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
" unevictable:%lu dirty:%lu writeback:%lu\n"
" slab_reclaimable:%lu slab_unreclaimable:%lu\n"
" mapped:%lu shmem:%lu pagetables:%lu bounce:%lu\n"
+ " kernel_misc_reclaimable:%lu\n"
" free:%lu free_pcp:%lu free_cma:%lu\n",
global_node_page_state(NR_ACTIVE_ANON),
global_node_page_state(NR_INACTIVE_ANON),
@@ -5919,6 +5920,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
global_node_page_state(NR_SHMEM),
global_node_page_state(NR_PAGETABLE),
global_zone_page_state(NR_BOUNCE),
+ global_node_page_state(NR_KERNEL_MISC_RECLAIMABLE),
global_zone_page_state(NR_FREE_PAGES),
free_pcp,
global_zone_page_state(NR_FREE_CMA_PAGES));
@@ -6155,7 +6157,7 @@ static int node_load[MAX_NUMNODES];
*
* Return: node id of the found node or %NUMA_NO_NODE if no node is found.
*/
-static int find_next_best_node(int node, nodemask_t *used_node_mask)
+int find_next_best_node(int node, nodemask_t *used_node_mask)
{
int n, val;
int min_val = INT_MAX;
@@ -6640,7 +6642,6 @@ static void __meminit zone_init_free_lists(struct zone *zone)
}
}
-#if !defined(CONFIG_FLATMEM)
/*
* Only struct pages that correspond to ranges defined by memblock.memory
* are zeroed and initialized by going through __init_single_page() during
@@ -6685,13 +6686,6 @@ static void __init init_unavailable_range(unsigned long spfn,
pr_info("On node %d, zone %s: %lld pages in unavailable ranges",
node, zone_names[zone], pgcnt);
}
-#else
-static inline void init_unavailable_range(unsigned long spfn,
- unsigned long epfn,
- int zone, int node)
-{
-}
-#endif
static void __init memmap_init_zone_range(struct zone *zone,
unsigned long start_pfn,
@@ -6721,7 +6715,7 @@ static void __init memmap_init(void)
{
unsigned long start_pfn, end_pfn;
unsigned long hole_pfn = 0;
- int i, j, zone_id, nid;
+ int i, j, zone_id = 0, nid;
for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
struct pglist_data *node = NODE_DATA(nid);
@@ -6754,6 +6748,26 @@ static void __init memmap_init(void)
init_unavailable_range(hole_pfn, end_pfn, zone_id, nid);
}
+void __init *memmap_alloc(phys_addr_t size, phys_addr_t align,
+ phys_addr_t min_addr, int nid, bool exact_nid)
+{
+ void *ptr;
+
+ if (exact_nid)
+ ptr = memblock_alloc_exact_nid_raw(size, align, min_addr,
+ MEMBLOCK_ALLOC_ACCESSIBLE,
+ nid);
+ else
+ ptr = memblock_alloc_try_nid_raw(size, align, min_addr,
+ MEMBLOCK_ALLOC_ACCESSIBLE,
+ nid);
+
+ if (ptr && size > 0)
+ page_init_poison(ptr, size);
+
+ return ptr;
+}
+
static int zone_batchsize(struct zone *zone)
{
#ifdef CONFIG_MMU
@@ -7501,7 +7515,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat)
}
#ifdef CONFIG_FLATMEM
-static void __ref alloc_node_mem_map(struct pglist_data *pgdat)
+static void __init alloc_node_mem_map(struct pglist_data *pgdat)
{
unsigned long __maybe_unused start = 0;
unsigned long __maybe_unused offset = 0;
@@ -7525,8 +7539,8 @@ static void __ref alloc_node_mem_map(struct pglist_data *pgdat)
end = pgdat_end_pfn(pgdat);
end = ALIGN(end, MAX_ORDER_NR_PAGES);
size = (end - start) * sizeof(struct page);
- map = memblock_alloc_node(size, SMP_CACHE_BYTES,
- pgdat->node_id);
+ map = memmap_alloc(size, SMP_CACHE_BYTES, MEMBLOCK_LOW_LIMIT,
+ pgdat->node_id, false);
if (!map)
panic("Failed to allocate %ld bytes for node %d memory map\n",
size, pgdat->node_id);
@@ -7547,7 +7561,7 @@ static void __ref alloc_node_mem_map(struct pglist_data *pgdat)
#endif
}
#else
-static void __ref alloc_node_mem_map(struct pglist_data *pgdat) { }
+static inline void alloc_node_mem_map(struct pglist_data *pgdat) { }
#endif /* CONFIG_FLATMEM */
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
@@ -8976,7 +8990,7 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
cc->nr_migratepages -= nr_reclaimed;
ret = migrate_pages(&cc->migratepages, alloc_migration_target,
- NULL, (unsigned long)&mtc, cc->mode, MR_CONTIG_RANGE);
+ NULL, (unsigned long)&mtc, cc->mode, MR_CONTIG_RANGE, NULL);
/*
* On -ENOMEM, migrate_pages() bails out right away. It is pointless
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index bddf788f45bf..fff55bb830f9 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -287,6 +287,7 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
unsigned long pfn, flags;
struct page *page;
struct zone *zone;
+ int ret;
/*
* Note: pageblock_nr_pages != MAX_ORDER. Then, chunks of free pages
@@ -299,15 +300,21 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
break;
}
page = __first_valid_page(start_pfn, end_pfn - start_pfn);
- if ((pfn < end_pfn) || !page)
- return -EBUSY;
+ if ((pfn < end_pfn) || !page) {
+ ret = -EBUSY;
+ goto out;
+ }
+
/* Check all pages are free or marked as ISOLATED */
zone = page_zone(page);
spin_lock_irqsave(&zone->lock, flags);
pfn = __test_page_isolated_in_pageblock(start_pfn, end_pfn, isol_flags);
spin_unlock_irqrestore(&zone->lock, flags);
+ ret = pfn < end_pfn ? -EBUSY : 0;
+
+out:
trace_test_pages_isolated(start_pfn, end_pfn, pfn);
- return pfn < end_pfn ? -EBUSY : 0;
+ return ret;
}
diff --git a/mm/percpu.c b/mm/percpu.c
index 7f2e0151c4e2..e1c20837a42a 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1520,9 +1520,6 @@ static void pcpu_free_chunk(struct pcpu_chunk *chunk)
* Pages in [@page_start,@page_end) have been populated to @chunk. Update
* the bookkeeping information accordingly. Must be called after each
* successful population.
- *
- * If this is @for_alloc, do not increment pcpu_nr_empty_pop_pages because it
- * is to serve an allocation in that area.
*/
static void pcpu_chunk_populated(struct pcpu_chunk *chunk, int page_start,
int page_end)
diff --git a/mm/shmem.c b/mm/shmem.c
index 3107acee4f71..88742953532c 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -38,8 +38,7 @@
#include <linux/hugetlb.h>
#include <linux/frontswap.h>
#include <linux/fs_parser.h>
-
-#include <asm/tlbflush.h> /* for arch/microblaze update_mmu_cache() */
+#include <linux/swapfile.h>
static struct vfsmount *shm_mnt;
@@ -137,9 +136,6 @@ static unsigned long shmem_default_max_inodes(void)
}
#endif
-static bool shmem_should_replace_page(struct page *page, gfp_t gfp);
-static int shmem_replace_page(struct page **pagep, gfp_t gfp,
- struct shmem_inode_info *info, pgoff_t index);
static int shmem_swapin_page(struct inode *inode, pgoff_t index,
struct page **pagep, enum sgp_type sgp,
gfp_t gfp, struct vm_area_struct *vma,
@@ -278,10 +274,10 @@ static int shmem_reserve_inode(struct super_block *sb, ino_t *inop)
ino_t ino;
if (!(sb->s_flags & SB_KERNMOUNT)) {
- spin_lock(&sbinfo->stat_lock);
+ raw_spin_lock(&sbinfo->stat_lock);
if (sbinfo->max_inodes) {
if (!sbinfo->free_inodes) {
- spin_unlock(&sbinfo->stat_lock);
+ raw_spin_unlock(&sbinfo->stat_lock);
return -ENOSPC;
}
sbinfo->free_inodes--;
@@ -304,7 +300,7 @@ static int shmem_reserve_inode(struct super_block *sb, ino_t *inop)
}
*inop = ino;
}
- spin_unlock(&sbinfo->stat_lock);
+ raw_spin_unlock(&sbinfo->stat_lock);
} else if (inop) {
/*
* __shmem_file_setup, one of our callers, is lock-free: it
@@ -319,13 +315,14 @@ static int shmem_reserve_inode(struct super_block *sb, ino_t *inop)
* to worry about things like glibc compatibility.
*/
ino_t *next_ino;
+
next_ino = per_cpu_ptr(sbinfo->ino_batch, get_cpu());
ino = *next_ino;
if (unlikely(ino % SHMEM_INO_BATCH == 0)) {
- spin_lock(&sbinfo->stat_lock);
+ raw_spin_lock(&sbinfo->stat_lock);
ino = sbinfo->next_ino;
sbinfo->next_ino += SHMEM_INO_BATCH;
- spin_unlock(&sbinfo->stat_lock);
+ raw_spin_unlock(&sbinfo->stat_lock);
if (unlikely(is_zero_ino(ino)))
ino++;
}
@@ -341,9 +338,9 @@ static void shmem_free_inode(struct super_block *sb)
{
struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
if (sbinfo->max_inodes) {
- spin_lock(&sbinfo->stat_lock);
+ raw_spin_lock(&sbinfo->stat_lock);
sbinfo->free_inodes++;
- spin_unlock(&sbinfo->stat_lock);
+ raw_spin_unlock(&sbinfo->stat_lock);
}
}
@@ -474,7 +471,38 @@ static bool shmem_confirm_swap(struct address_space *mapping,
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
/* ifdef here to avoid bloating shmem.o when not necessary */
-static int shmem_huge __read_mostly;
+static int shmem_huge __read_mostly = SHMEM_HUGE_NEVER;
+
+bool shmem_is_huge(struct vm_area_struct *vma,
+ struct inode *inode, pgoff_t index)
+{
+ loff_t i_size;
+
+ if (shmem_huge == SHMEM_HUGE_DENY)
+ return false;
+ if (vma && ((vma->vm_flags & VM_NOHUGEPAGE) ||
+ test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)))
+ return false;
+ if (shmem_huge == SHMEM_HUGE_FORCE)
+ return true;
+
+ switch (SHMEM_SB(inode->i_sb)->huge) {
+ case SHMEM_HUGE_ALWAYS:
+ return true;
+ case SHMEM_HUGE_WITHIN_SIZE:
+ index = round_up(index, HPAGE_PMD_NR);
+ i_size = round_up(i_size_read(inode), PAGE_SIZE);
+ if (i_size >= HPAGE_PMD_SIZE && (i_size >> PAGE_SHIFT) >= index)
+ return true;
+ fallthrough;
+ case SHMEM_HUGE_ADVISE:
+ if (vma && (vma->vm_flags & VM_HUGEPAGE))
+ return true;
+ fallthrough;
+ default:
+ return false;
+ }
+}
#if defined(CONFIG_SYSFS)
static int shmem_parse_huge(const char *str)
@@ -645,6 +673,12 @@ static long shmem_unused_huge_count(struct super_block *sb,
#define shmem_huge SHMEM_HUGE_DENY
+bool shmem_is_huge(struct vm_area_struct *vma,
+ struct inode *inode, pgoff_t index)
+{
+ return false;
+}
+
static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
struct shrink_control *sc, unsigned long nr_to_split)
{
@@ -652,15 +686,6 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
-static inline bool is_huge_enabled(struct shmem_sb_info *sbinfo)
-{
- if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
- (shmem_huge == SHMEM_HUGE_FORCE || sbinfo->huge) &&
- shmem_huge != SHMEM_HUGE_DENY)
- return true;
- return false;
-}
-
/*
* Like add_to_page_cache_locked, but error if expected item has gone.
*/
@@ -905,6 +930,9 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
if (lend == -1)
end = -1; /* unsigned, so actually very big */
+ if (info->fallocend > start && info->fallocend <= end && !unfalloc)
+ info->fallocend = start;
+
pagevec_init(&pvec);
index = start;
while (index < end && find_lock_entries(mapping, index, end - 1,
@@ -1038,7 +1066,6 @@ static int shmem_getattr(struct user_namespace *mnt_userns,
{
struct inode *inode = path->dentry->d_inode;
struct shmem_inode_info *info = SHMEM_I(inode);
- struct shmem_sb_info *sb_info = SHMEM_SB(inode->i_sb);
if (info->alloced - info->swapped != inode->i_mapping->nrpages) {
spin_lock_irq(&info->lock);
@@ -1047,7 +1074,7 @@ static int shmem_getattr(struct user_namespace *mnt_userns,
}
generic_fillattr(&init_user_ns, inode, stat);
- if (is_huge_enabled(sb_info))
+ if (shmem_is_huge(NULL, inode, 0))
stat->blksize = HPAGE_PMD_SIZE;
return 0;
@@ -1058,7 +1085,6 @@ static int shmem_setattr(struct user_namespace *mnt_userns,
{
struct inode *inode = d_inode(dentry);
struct shmem_inode_info *info = SHMEM_I(inode);
- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
int error;
error = setattr_prepare(&init_user_ns, dentry, attr);
@@ -1094,24 +1120,6 @@ static int shmem_setattr(struct user_namespace *mnt_userns,
if (oldsize > holebegin)
unmap_mapping_range(inode->i_mapping,
holebegin, 0, 1);
-
- /*
- * Part of the huge page can be beyond i_size: subject
- * to shrink under memory pressure.
- */
- if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
- spin_lock(&sbinfo->shrinklist_lock);
- /*
- * _careful to defend against unlocked access to
- * ->shrink_list in shmem_unused_huge_shrink()
- */
- if (list_empty_careful(&info->shrinklist)) {
- list_add_tail(&info->shrinklist,
- &sbinfo->shrinklist);
- sbinfo->shrinklist_len++;
- }
- spin_unlock(&sbinfo->shrinklist_lock);
- }
}
}
@@ -1156,8 +1164,6 @@ static void shmem_evict_inode(struct inode *inode)
clear_inode(inode);
}
-extern struct swap_info_struct *swap_info[];
-
static int shmem_find_swap_entries(struct address_space *mapping,
pgoff_t start, unsigned int nr_entries,
struct page **entries, pgoff_t *indices,
@@ -1338,7 +1344,19 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
swp_entry_t swap;
pgoff_t index;
- VM_BUG_ON_PAGE(PageCompound(page), page);
+ /*
+ * If /sys/kernel/mm/transparent_hugepage/shmem_enabled is "always" or
+ * "force", drivers/gpu/drm/i915/gem/i915_gem_shmem.c gets huge pages,
+ * and its shmem_writeback() needs them to be split when swapping.
+ */
+ if (PageTransCompound(page)) {
+ /* Ensure the subpages are still dirty */
+ SetPageDirty(page);
+ if (split_huge_page(page) < 0)
+ goto redirty;
+ ClearPageDirty(page);
+ }
+
BUG_ON(!PageLocked(page));
mapping = page->mapping;
index = page->index;
@@ -1453,10 +1471,10 @@ static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
{
struct mempolicy *mpol = NULL;
if (sbinfo->mpol) {
- spin_lock(&sbinfo->stat_lock); /* prevent replace/use races */
+ raw_spin_lock(&sbinfo->stat_lock); /* prevent replace/use races */
mpol = sbinfo->mpol;
mpol_get(mpol);
- spin_unlock(&sbinfo->stat_lock);
+ raw_spin_unlock(&sbinfo->stat_lock);
}
return mpol;
}
@@ -1798,7 +1816,6 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
struct shmem_sb_info *sbinfo;
struct mm_struct *charge_mm;
struct page *page;
- enum sgp_type sgp_huge = sgp;
pgoff_t hindex = index;
gfp_t huge_gfp;
int error;
@@ -1807,8 +1824,6 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
if (index > (MAX_LFS_FILESIZE >> PAGE_SHIFT))
return -EFBIG;
- if (sgp == SGP_NOHUGE || sgp == SGP_HUGE)
- sgp = SGP_CACHE;
repeat:
if (sgp <= SGP_CACHE &&
((loff_t)index << PAGE_SHIFT) >= i_size_read(inode)) {
@@ -1840,26 +1855,31 @@ repeat:
return error;
}
- if (page)
+ if (page) {
hindex = page->index;
- if (page && sgp == SGP_WRITE)
- mark_page_accessed(page);
-
- /* fallocated page? */
- if (page && !PageUptodate(page)) {
+ if (sgp == SGP_WRITE)
+ mark_page_accessed(page);
+ if (PageUptodate(page))
+ goto out;
+ /* fallocated page */
if (sgp != SGP_READ)
goto clear;
unlock_page(page);
put_page(page);
- page = NULL;
- hindex = index;
}
- if (page || sgp == SGP_READ)
- goto out;
/*
- * Fast cache lookup did not find it:
- * bring it back from swap or allocate.
+ * SGP_READ: succeed on hole, with NULL page, letting caller zero.
+ * SGP_NOALLOC: fail on hole, with NULL page, letting caller fail.
+ */
+ *pagep = NULL;
+ if (sgp == SGP_READ)
+ return 0;
+ if (sgp == SGP_NOALLOC)
+ return -ENOENT;
+
+ /*
+ * Fast cache lookup and swap lookup did not find it: allocate.
*/
if (vma && userfaultfd_missing(vma)) {
@@ -1867,36 +1887,12 @@ repeat:
return 0;
}
- /* shmem_symlink() */
- if (!shmem_mapping(mapping))
- goto alloc_nohuge;
- if (shmem_huge == SHMEM_HUGE_DENY || sgp_huge == SGP_NOHUGE)
- goto alloc_nohuge;
- if (shmem_huge == SHMEM_HUGE_FORCE)
- goto alloc_huge;
- switch (sbinfo->huge) {
- case SHMEM_HUGE_NEVER:
+ /* Never use a huge page for shmem_symlink() */
+ if (S_ISLNK(inode->i_mode))
goto alloc_nohuge;
- case SHMEM_HUGE_WITHIN_SIZE: {
- loff_t i_size;
- pgoff_t off;
-
- off = round_up(index, HPAGE_PMD_NR);
- i_size = round_up(i_size_read(inode), PAGE_SIZE);
- if (i_size >= HPAGE_PMD_SIZE &&
- i_size >> PAGE_SHIFT >= off)
- goto alloc_huge;
-
- fallthrough;
- }
- case SHMEM_HUGE_ADVISE:
- if (sgp_huge == SGP_HUGE)
- goto alloc_huge;
- /* TODO: implement fadvise() hints */
+ if (!shmem_is_huge(vma, inode, index))
goto alloc_nohuge;
- }
-alloc_huge:
huge_gfp = vma_thp_gfp_mask(vma);
huge_gfp = limit_gfp_mask(huge_gfp, gfp);
page = shmem_alloc_and_acct_page(huge_gfp, inode, index, true);
@@ -2052,7 +2048,6 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf)
struct vm_area_struct *vma = vmf->vma;
struct inode *inode = file_inode(vma->vm_file);
gfp_t gfp = mapping_gfp_mask(inode->i_mapping);
- enum sgp_type sgp;
int err;
vm_fault_t ret = VM_FAULT_LOCKED;
@@ -2115,15 +2110,7 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf)
spin_unlock(&inode->i_lock);
}
- sgp = SGP_CACHE;
-
- if ((vma->vm_flags & VM_NOHUGEPAGE) ||
- test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags))
- sgp = SGP_NOHUGE;
- else if (vma->vm_flags & VM_HUGEPAGE)
- sgp = SGP_HUGE;
-
- err = shmem_getpage_gfp(inode, vmf->pgoff, &vmf->page, sgp,
+ err = shmem_getpage_gfp(inode, vmf->pgoff, &vmf->page, SGP_CACHE,
gfp, vma, vmf, &ret);
if (err)
return vmf_error(err);
@@ -2655,7 +2642,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
struct shmem_inode_info *info = SHMEM_I(inode);
struct shmem_falloc shmem_falloc;
- pgoff_t start, index, end;
+ pgoff_t start, index, end, undo_fallocend;
int error;
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
@@ -2724,7 +2711,16 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
inode->i_private = &shmem_falloc;
spin_unlock(&inode->i_lock);
- for (index = start; index < end; index++) {
+ /*
+ * info->fallocend is only relevant when huge pages might be
+ * involved: to prevent split_huge_page() freeing fallocated
+ * pages when FALLOC_FL_KEEP_SIZE committed beyond i_size.
+ */
+ undo_fallocend = info->fallocend;
+ if (info->fallocend < end)
+ info->fallocend = end;
+
+ for (index = start; index < end; ) {
struct page *page;
/*
@@ -2738,6 +2734,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
else
error = shmem_getpage(inode, index, &page, SGP_FALLOC);
if (error) {
+ info->fallocend = undo_fallocend;
/* Remove the !PageUptodate pages we added */
if (index > start) {
shmem_undo_range(inode,
@@ -2747,13 +2744,26 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
goto undone;
}
+ index++;
+ /*
+ * Here is a more important optimization than it appears:
+ * a second SGP_FALLOC on the same huge page will clear it,
+ * making it PageUptodate and un-undoable if we fail later.
+ */
+ if (PageTransCompound(page)) {
+ index = round_up(index, HPAGE_PMD_NR);
+ /* Beware 32-bit wraparound */
+ if (!index)
+ index--;
+ }
+
/*
* Inform shmem_writepage() how far we have reached.
* No need for lock or barrier: we have the page lock.
*/
- shmem_falloc.next++;
if (!PageUptodate(page))
- shmem_falloc.nr_falloced++;
+ shmem_falloc.nr_falloced += index - shmem_falloc.next;
+ shmem_falloc.next = index;
/*
* If !PageUptodate, leave it that way so that freeable pages
@@ -3488,9 +3498,10 @@ static int shmem_reconfigure(struct fs_context *fc)
struct shmem_options *ctx = fc->fs_private;
struct shmem_sb_info *sbinfo = SHMEM_SB(fc->root->d_sb);
unsigned long inodes;
+ struct mempolicy *mpol = NULL;
const char *err;
- spin_lock(&sbinfo->stat_lock);
+ raw_spin_lock(&sbinfo->stat_lock);
inodes = sbinfo->max_inodes - sbinfo->free_inodes;
if ((ctx->seen & SHMEM_SEEN_BLOCKS) && ctx->blocks) {
if (!sbinfo->max_blocks) {
@@ -3535,14 +3546,15 @@ static int shmem_reconfigure(struct fs_context *fc)
* Preserve previous mempolicy unless mpol remount option was specified.
*/
if (ctx->mpol) {
- mpol_put(sbinfo->mpol);
+ mpol = sbinfo->mpol;
sbinfo->mpol = ctx->mpol; /* transfers initial ref */
ctx->mpol = NULL;
}
- spin_unlock(&sbinfo->stat_lock);
+ raw_spin_unlock(&sbinfo->stat_lock);
+ mpol_put(mpol);
return 0;
out:
- spin_unlock(&sbinfo->stat_lock);
+ raw_spin_unlock(&sbinfo->stat_lock);
return invalfc(fc, "%s", err);
}
@@ -3613,7 +3625,6 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
struct shmem_options *ctx = fc->fs_private;
struct inode *inode;
struct shmem_sb_info *sbinfo;
- int err = -ENOMEM;
/* Round up to L1_CACHE_BYTES to resist false sharing */
sbinfo = kzalloc(max((int)sizeof(struct shmem_sb_info),
@@ -3659,7 +3670,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
sbinfo->mpol = ctx->mpol;
ctx->mpol = NULL;
- spin_lock_init(&sbinfo->stat_lock);
+ raw_spin_lock_init(&sbinfo->stat_lock);
if (percpu_counter_init(&sbinfo->used_blocks, 0, GFP_KERNEL))
goto failed;
spin_lock_init(&sbinfo->shrinklist_lock);
@@ -3691,7 +3702,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
failed:
shmem_put_super(sb);
- return err;
+ return -ENOMEM;
}
static int shmem_get_tree(struct fs_context *fc)
@@ -3907,7 +3918,7 @@ int __init shmem_init(void)
if (has_transparent_hugepage() && shmem_huge > SHMEM_HUGE_DENY)
SHMEM_SB(shm_mnt->mnt_sb)->huge = shmem_huge;
else
- shmem_huge = 0; /* just in case it was patched */
+ shmem_huge = SHMEM_HUGE_NEVER; /* just in case it was patched */
#endif
return 0;
@@ -3976,42 +3987,6 @@ struct kobj_attribute shmem_enabled_attr =
__ATTR(shmem_enabled, 0644, shmem_enabled_show, shmem_enabled_store);
#endif /* CONFIG_TRANSPARENT_HUGEPAGE && CONFIG_SYSFS */
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-bool shmem_huge_enabled(struct vm_area_struct *vma)
-{
- struct inode *inode = file_inode(vma->vm_file);
- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
- loff_t i_size;
- pgoff_t off;
-
- if (!transhuge_vma_enabled(vma, vma->vm_flags))
- return false;
- if (shmem_huge == SHMEM_HUGE_FORCE)
- return true;
- if (shmem_huge == SHMEM_HUGE_DENY)
- return false;
- switch (sbinfo->huge) {
- case SHMEM_HUGE_NEVER:
- return false;
- case SHMEM_HUGE_ALWAYS:
- return true;
- case SHMEM_HUGE_WITHIN_SIZE:
- off = round_up(vma->vm_pgoff, HPAGE_PMD_NR);
- i_size = round_up(i_size_read(inode), PAGE_SIZE);
- if (i_size >= HPAGE_PMD_SIZE &&
- i_size >> PAGE_SHIFT >= off)
- return true;
- fallthrough;
- case SHMEM_HUGE_ADVISE:
- /* TODO: implement fadvise() hints */
- return (vma->vm_flags & VM_HUGEPAGE);
- default:
- VM_BUG_ON(1);
- return false;
- }
-}
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
-
#else /* !CONFIG_SHMEM */
/*
diff --git a/mm/sparse.c b/mm/sparse.c
index 6326cdf36c4f..120bc8ea5293 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -109,32 +109,6 @@ static inline int sparse_index_init(unsigned long section_nr, int nid)
}
#endif
-#ifdef CONFIG_SPARSEMEM_EXTREME
-unsigned long __section_nr(struct mem_section *ms)
-{
- unsigned long root_nr;
- struct mem_section *root = NULL;
-
- for (root_nr = 0; root_nr < NR_SECTION_ROOTS; root_nr++) {
- root = __nr_to_section(root_nr * SECTIONS_PER_ROOT);
- if (!root)
- continue;
-
- if ((ms >= root) && (ms < (root + SECTIONS_PER_ROOT)))
- break;
- }
-
- VM_BUG_ON(!root);
-
- return (root_nr * SECTIONS_PER_ROOT) + (ms - root);
-}
-#else
-unsigned long __section_nr(struct mem_section *ms)
-{
- return (unsigned long)(ms - mem_section[0]);
-}
-#endif
-
/*
* During early boot, before section_mem_map is used for an actual
* mem_map, we use section_mem_map to store the section's NUMA
@@ -143,7 +117,7 @@ unsigned long __section_nr(struct mem_section *ms)
*/
static inline unsigned long sparse_encode_early_nid(int nid)
{
- return (nid << SECTION_NID_SHIFT);
+ return ((unsigned long)nid << SECTION_NID_SHIFT);
}
static inline int sparse_early_nid(struct mem_section *section)
@@ -187,10 +161,9 @@ void __meminit mminit_validate_memmodel_limits(unsigned long *start_pfn,
* those loops early.
*/
unsigned long __highest_present_section_nr;
-static void section_mark_present(struct mem_section *ms)
+static void __section_mark_present(struct mem_section *ms,
+ unsigned long section_nr)
{
- unsigned long section_nr = __section_nr(ms);
-
if (section_nr > __highest_present_section_nr)
__highest_present_section_nr = section_nr;
@@ -280,7 +253,7 @@ static void __init memory_present(int nid, unsigned long start, unsigned long en
if (!ms->section_mem_map) {
ms->section_mem_map = sparse_encode_early_nid(nid) |
SECTION_IS_ONLINE;
- section_mark_present(ms);
+ __section_mark_present(ms, section);
}
}
}
@@ -348,7 +321,8 @@ size_t mem_section_usage_size(void)
static inline phys_addr_t pgdat_to_phys(struct pglist_data *pgdat)
{
#ifndef CONFIG_NUMA
- return __pa_symbol(pgdat);
+ VM_BUG_ON(pgdat != &contig_page_data);
+ return __pa_symbol(&contig_page_data);
#else
return __pa(pgdat);
#endif
@@ -462,8 +436,7 @@ struct page __init *__populate_section_memmap(unsigned long pfn,
if (map)
return map;
- map = memblock_alloc_try_nid_raw(size, size, addr,
- MEMBLOCK_ALLOC_ACCESSIBLE, nid);
+ map = memmap_alloc(size, size, addr, nid, false);
if (!map)
panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%pa\n",
__func__, size, PAGE_SIZE, nid, &addr);
@@ -490,8 +463,7 @@ static void __init sparse_buffer_init(unsigned long size, int nid)
* and we want it to be properly aligned to the section size - this is
* especially the case for VMEMMAP which maps memmap to PMDs
*/
- sparsemap_buf = memblock_alloc_exact_nid_raw(size, section_map_size(),
- addr, MEMBLOCK_ALLOC_ACCESSIBLE, nid);
+ sparsemap_buf = memmap_alloc(size, section_map_size(), addr, nid, true);
sparsemap_buf_end = sparsemap_buf + size;
}
@@ -934,7 +906,7 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn,
ms = __nr_to_section(section_nr);
set_section_nid(section_nr, nid);
- section_mark_present(ms);
+ __section_mark_present(ms, section_nr);
/* Align memmap to section boundary in the subsection case */
if (section_nr_to_pfn(section_nr) != start_pfn)
diff --git a/mm/swap.c b/mm/swap.c
index 19600430e536..897200d27dd0 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -179,28 +179,6 @@ int get_kernel_pages(const struct kvec *kiov, int nr_segs, int write,
}
EXPORT_SYMBOL_GPL(get_kernel_pages);
-/*
- * get_kernel_page() - pin a kernel page in memory
- * @start: starting kernel address
- * @write: pinning for read/write, currently ignored
- * @pages: array that receives pointer to the page pinned.
- * Must be at least nr_segs long.
- *
- * Returns 1 if page is pinned. If the page was not pinned, returns
- * -errno. The page returned must be released with a put_page() call
- * when it is finished with.
- */
-int get_kernel_page(unsigned long start, int write, struct page **pages)
-{
- const struct kvec kiov = {
- .iov_base = (void *)start,
- .iov_len = PAGE_SIZE
- };
-
- return get_kernel_pages(&kiov, 1, write, pages);
-}
-EXPORT_SYMBOL_GPL(get_kernel_page);
-
static void pagevec_lru_move_fn(struct pagevec *pvec,
void (*move_fn)(struct page *page, struct lruvec *lruvec))
{
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 1e07d1c776f2..22d10f713848 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -3130,6 +3130,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
struct filename *name;
struct file *swap_file = NULL;
struct address_space *mapping;
+ struct dentry *dentry;
int prio;
int error;
union swap_header *swap_header;
@@ -3173,6 +3174,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
p->swap_file = swap_file;
mapping = swap_file->f_mapping;
+ dentry = swap_file->f_path.dentry;
inode = mapping->host;
error = claim_swapfile(p, inode);
@@ -3180,6 +3182,10 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
goto bad_swap;
inode_lock(inode);
+ if (d_unlinked(dentry) || cant_mount(dentry)) {
+ error = -ENOENT;
+ goto bad_swap_unlock_inode;
+ }
if (IS_SWAPFILE(inode)) {
error = -EBUSY;
goto bad_swap_unlock_inode;
@@ -3773,7 +3779,7 @@ static void free_swap_count_continuations(struct swap_info_struct *si)
}
#if defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP)
-void cgroup_throttle_swaprate(struct page *page, gfp_t gfp_mask)
+void __cgroup_throttle_swaprate(struct page *page, gfp_t gfp_mask)
{
struct swap_info_struct *si, *next;
int nid = page_to_nid(page);
diff --git a/mm/truncate.c b/mm/truncate.c
index 44ad5e515140..714eaf19821d 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -484,8 +484,9 @@ static unsigned long __invalidate_mapping_pages(struct address_space *mapping,
index = indices[i];
if (xa_is_value(page)) {
- invalidate_exceptional_entry(mapping, index,
- page);
+ count += invalidate_exceptional_entry(mapping,
+ index,
+ page);
continue;
}
index += thp_nr_pages(page) - 1;
@@ -513,19 +514,18 @@ static unsigned long __invalidate_mapping_pages(struct address_space *mapping,
}
/**
- * invalidate_mapping_pages - Invalidate all the unlocked pages of one inode
- * @mapping: the address_space which holds the pages to invalidate
+ * invalidate_mapping_pages - Invalidate all clean, unlocked cache of one inode
+ * @mapping: the address_space which holds the cache to invalidate
* @start: the offset 'from' which to invalidate
* @end: the offset 'to' which to invalidate (inclusive)
*
- * This function only removes the unlocked pages, if you want to
- * remove all the pages of one inode, you must call truncate_inode_pages.
+ * This function removes pages that are clean, unmapped and unlocked,
+ * as well as shadow entries. It will not block on IO activity.
*
- * invalidate_mapping_pages() will not block on IO activity. It will not
- * invalidate pages which are dirty, locked, under writeback or mapped into
- * pagetables.
+ * If you want to remove all the pages of one inode, regardless of
+ * their use and writeback state, use truncate_inode_pages().
*
- * Return: the number of the pages that were invalidated
+ * Return: the number of the cache entries that were invalidated
*/
unsigned long invalidate_mapping_pages(struct address_space *mapping,
pgoff_t start, pgoff_t end)
@@ -561,21 +561,19 @@ void invalidate_mapping_pagevec(struct address_space *mapping,
static int
invalidate_complete_page2(struct address_space *mapping, struct page *page)
{
- unsigned long flags;
-
if (page->mapping != mapping)
return 0;
if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL))
return 0;
- xa_lock_irqsave(&mapping->i_pages, flags);
+ xa_lock_irq(&mapping->i_pages);
if (PageDirty(page))
goto failed;
BUG_ON(page_has_private(page));
__delete_from_page_cache(page, NULL);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
+ xa_unlock_irq(&mapping->i_pages);
if (mapping->a_ops->freepage)
mapping->a_ops->freepage(page);
@@ -583,7 +581,7 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
put_page(page); /* pagecache ref */
return 1;
failed:
- xa_unlock_irqrestore(&mapping->i_pages, flags);
+ xa_unlock_irq(&mapping->i_pages);
return 0;
}
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 0e2132834bc7..7a9008415534 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -483,7 +483,7 @@ static __always_inline ssize_t __mcopy_atomic(struct mm_struct *dst_mm,
unsigned long src_start,
unsigned long len,
enum mcopy_atomic_mode mcopy_mode,
- bool *mmap_changing,
+ atomic_t *mmap_changing,
__u64 mode)
{
struct vm_area_struct *dst_vma;
@@ -517,7 +517,7 @@ retry:
* request the user to retry later
*/
err = -EAGAIN;
- if (mmap_changing && READ_ONCE(*mmap_changing))
+ if (mmap_changing && atomic_read(mmap_changing))
goto out_unlock;
/*
@@ -650,28 +650,29 @@ out:
ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start,
unsigned long src_start, unsigned long len,
- bool *mmap_changing, __u64 mode)
+ atomic_t *mmap_changing, __u64 mode)
{
return __mcopy_atomic(dst_mm, dst_start, src_start, len,
MCOPY_ATOMIC_NORMAL, mmap_changing, mode);
}
ssize_t mfill_zeropage(struct mm_struct *dst_mm, unsigned long start,
- unsigned long len, bool *mmap_changing)
+ unsigned long len, atomic_t *mmap_changing)
{
return __mcopy_atomic(dst_mm, start, 0, len, MCOPY_ATOMIC_ZEROPAGE,
mmap_changing, 0);
}
ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long start,
- unsigned long len, bool *mmap_changing)
+ unsigned long len, atomic_t *mmap_changing)
{
return __mcopy_atomic(dst_mm, start, 0, len, MCOPY_ATOMIC_CONTINUE,
mmap_changing, 0);
}
int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
- unsigned long len, bool enable_wp, bool *mmap_changing)
+ unsigned long len, bool enable_wp,
+ atomic_t *mmap_changing)
{
struct vm_area_struct *dst_vma;
pgprot_t newprot;
@@ -694,7 +695,7 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
* request the user to retry later
*/
err = -EAGAIN;
- if (mmap_changing && READ_ONCE(*mmap_changing))
+ if (mmap_changing && atomic_read(mmap_changing))
goto out_unlock;
err = -ENOENT;
diff --git a/mm/util.c b/mm/util.c
index 9043d03750a7..499b6b5767ed 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -593,6 +593,10 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node)
if (ret || size <= PAGE_SIZE)
return ret;
+ /* Don't even allow crazy sizes */
+ if (WARN_ON_ONCE(size > INT_MAX))
+ return NULL;
+
return __vmalloc_node(size, 1, flags, node,
__builtin_return_address(0));
}
@@ -635,6 +639,21 @@ void kvfree_sensitive(const void *addr, size_t len)
}
EXPORT_SYMBOL(kvfree_sensitive);
+void *kvrealloc(const void *p, size_t oldsize, size_t newsize, gfp_t flags)
+{
+ void *newp;
+
+ if (oldsize >= newsize)
+ return (void *)p;
+ newp = kvmalloc(newsize, flags);
+ if (!newp)
+ return NULL;
+ memcpy(newp, p, oldsize);
+ kvfree(p);
+ return newp;
+}
+EXPORT_SYMBOL(kvrealloc);
+
static inline void *__page_rmapping(struct page *page)
{
unsigned long mapping;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d5cd52805149..3824dc16ce1c 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -787,6 +787,28 @@ unsigned long vmalloc_nr_pages(void)
return atomic_long_read(&nr_vmalloc_pages);
}
+static struct vmap_area *find_vmap_area_exceed_addr(unsigned long addr)
+{
+ struct vmap_area *va = NULL;
+ struct rb_node *n = vmap_area_root.rb_node;
+
+ while (n) {
+ struct vmap_area *tmp;
+
+ tmp = rb_entry(n, struct vmap_area, rb_node);
+ if (tmp->va_end > addr) {
+ va = tmp;
+ if (tmp->va_start <= addr)
+ break;
+
+ n = n->rb_left;
+ } else
+ n = n->rb_right;
+ }
+
+ return va;
+}
+
static struct vmap_area *__find_vmap_area(unsigned long addr)
{
struct rb_node *n = vmap_area_root.rb_node;
@@ -1479,6 +1501,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
int node, gfp_t gfp_mask)
{
struct vmap_area *va;
+ unsigned long freed;
unsigned long addr;
int purged = 0;
int ret;
@@ -1542,13 +1565,12 @@ overflow:
goto retry;
}
- if (gfpflags_allow_blocking(gfp_mask)) {
- unsigned long freed = 0;
- blocking_notifier_call_chain(&vmap_notify_list, 0, &freed);
- if (freed > 0) {
- purged = 0;
- goto retry;
- }
+ freed = 0;
+ blocking_notifier_call_chain(&vmap_notify_list, 0, &freed);
+
+ if (freed > 0) {
+ purged = 0;
+ goto retry;
}
if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit())
@@ -2779,7 +2801,7 @@ EXPORT_SYMBOL_GPL(vmap_pfn);
static inline unsigned int
vm_area_alloc_pages(gfp_t gfp, int nid,
- unsigned int order, unsigned long nr_pages, struct page **pages)
+ unsigned int order, unsigned int nr_pages, struct page **pages)
{
unsigned int nr_allocated = 0;
@@ -2789,10 +2811,32 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
* to fails, fallback to a single page allocator that is
* more permissive.
*/
- if (!order)
- nr_allocated = alloc_pages_bulk_array_node(
- gfp, nid, nr_pages, pages);
- else
+ if (!order) {
+ while (nr_allocated < nr_pages) {
+ unsigned int nr, nr_pages_request;
+
+ /*
+ * A maximum allowed request is hard-coded and is 100
+ * pages per call. That is done in order to prevent a
+ * long preemption off scenario in the bulk-allocator
+ * so the range is [1:100].
+ */
+ nr_pages_request = min(100U, nr_pages - nr_allocated);
+
+ nr = alloc_pages_bulk_array_node(gfp, nid,
+ nr_pages_request, pages + nr_allocated);
+
+ nr_allocated += nr;
+ cond_resched();
+
+ /*
+ * If zero or pages were obtained partly,
+ * fallback to a single page allocator.
+ */
+ if (nr != nr_pages_request)
+ break;
+ }
+ } else
/*
* Compound pages required for remap_vmalloc_page if
* high-order pages.
@@ -2816,9 +2860,7 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
for (i = 0; i < (1U << order); i++)
pages[nr_allocated + i] = page + i;
- if (gfpflags_allow_blocking(gfp))
- cond_resched();
-
+ cond_resched();
nr_allocated += 1U << order;
}
@@ -3267,9 +3309,14 @@ long vread(char *buf, char *addr, unsigned long count)
count = -(unsigned long) addr;
spin_lock(&vmap_area_lock);
- va = __find_vmap_area((unsigned long)addr);
+ va = find_vmap_area_exceed_addr((unsigned long)addr);
if (!va)
goto finished;
+
+ /* no intersects with alive vmap_area */
+ if ((unsigned long)addr + count <= va->va_start)
+ goto finished;
+
list_for_each_entry_from(va, &vmap_area_list, list) {
if (!count)
break;
diff --git a/mm/vmpressure.c b/mm/vmpressure.c
index d69019fc3789..76518e4166dc 100644
--- a/mm/vmpressure.c
+++ b/mm/vmpressure.c
@@ -74,8 +74,7 @@ static struct vmpressure *work_to_vmpressure(struct work_struct *work)
static struct vmpressure *vmpressure_parent(struct vmpressure *vmpr)
{
- struct cgroup_subsys_state *css = vmpressure_to_css(vmpr);
- struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+ struct mem_cgroup *memcg = vmpressure_to_memcg(vmpr);
memcg = parent_mem_cgroup(memcg);
if (!memcg)
@@ -240,7 +239,12 @@ static void vmpressure_work_fn(struct work_struct *work)
void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree,
unsigned long scanned, unsigned long reclaimed)
{
- struct vmpressure *vmpr = memcg_to_vmpressure(memcg);
+ struct vmpressure *vmpr;
+
+ if (mem_cgroup_disabled())
+ return;
+
+ vmpr = memcg_to_vmpressure(memcg);
/*
* Here we only want to account pressure that userland is able to
diff --git a/mm/vmscan.c b/mm/vmscan.c
index eeae2f6bc532..740d03e6dae2 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -41,6 +41,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/memcontrol.h>
+#include <linux/migrate.h>
#include <linux/delayacct.h>
#include <linux/sysctl.h>
#include <linux/oom.h>
@@ -121,6 +122,9 @@ struct scan_control {
/* The file pages on the current node are dangerously low */
unsigned int file_is_tiny:1;
+ /* Always discard instead of demoting to lower tier memory */
+ unsigned int no_demotion:1;
+
/* Allocation order */
s8 order;
@@ -518,6 +522,48 @@ static long add_nr_deferred(long nr, struct shrinker *shrinker,
return atomic_long_add_return(nr, &shrinker->nr_deferred[nid]);
}
+static bool can_demote(int nid, struct scan_control *sc)
+{
+ if (!numa_demotion_enabled)
+ return false;
+ if (sc) {
+ if (sc->no_demotion)
+ return false;
+ /* It is pointless to do demotion in memcg reclaim */
+ if (cgroup_reclaim(sc))
+ return false;
+ }
+ if (next_demotion_node(nid) == NUMA_NO_NODE)
+ return false;
+
+ return true;
+}
+
+static inline bool can_reclaim_anon_pages(struct mem_cgroup *memcg,
+ int nid,
+ struct scan_control *sc)
+{
+ if (memcg == NULL) {
+ /*
+ * For non-memcg reclaim, is there
+ * space in any swap device?
+ */
+ if (get_nr_swap_pages() > 0)
+ return true;
+ } else {
+ /* Is the memcg below its swap limit? */
+ if (mem_cgroup_get_nr_swap_pages(memcg) > 0)
+ return true;
+ }
+
+ /*
+ * The page can not be swapped.
+ *
+ * Can it be reclaimed from this node via demotion?
+ */
+ return can_demote(nid, sc);
+}
+
/*
* This misses isolated pages which are not accounted for to save counters.
* As the data only determines if reclaim or compaction continues, it is
@@ -529,7 +575,7 @@ unsigned long zone_reclaimable_pages(struct zone *zone)
nr = zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_FILE) +
zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_FILE);
- if (get_nr_swap_pages() > 0)
+ if (can_reclaim_anon_pages(NULL, zone_to_nid(zone), NULL))
nr += zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_ANON) +
zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_ANON);
@@ -893,6 +939,7 @@ out:
void drop_slab_node(int nid)
{
unsigned long freed;
+ int shift = 0;
do {
struct mem_cgroup *memcg = NULL;
@@ -905,7 +952,7 @@ void drop_slab_node(int nid)
do {
freed += shrink_slab(GFP_KERNEL, nid, memcg, 0);
} while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL);
- } while (freed > 10);
+ } while ((freed >> shift++) > 1);
}
void drop_slab(void)
@@ -1052,14 +1099,13 @@ static pageout_t pageout(struct page *page, struct address_space *mapping)
static int __remove_mapping(struct address_space *mapping, struct page *page,
bool reclaimed, struct mem_cgroup *target_memcg)
{
- unsigned long flags;
int refcount;
void *shadow = NULL;
BUG_ON(!PageLocked(page));
BUG_ON(mapping != page_mapping(page));
- xa_lock_irqsave(&mapping->i_pages, flags);
+ xa_lock_irq(&mapping->i_pages);
/*
* The non racy check for a busy page.
*
@@ -1100,7 +1146,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
if (reclaimed && !mapping_exiting(mapping))
shadow = workingset_eviction(page, target_memcg);
__delete_from_swap_cache(page, swap, shadow);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
+ xa_unlock_irq(&mapping->i_pages);
put_swap_page(page, swap);
} else {
void (*freepage)(struct page *);
@@ -1126,7 +1172,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
!mapping_exiting(mapping) && !dax_mapping(mapping))
shadow = workingset_eviction(page, target_memcg);
__delete_from_page_cache(page, shadow);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
+ xa_unlock_irq(&mapping->i_pages);
if (freepage != NULL)
freepage(page);
@@ -1135,7 +1181,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
return 1;
cannot_free:
- xa_unlock_irqrestore(&mapping->i_pages, flags);
+ xa_unlock_irq(&mapping->i_pages);
return 0;
}
@@ -1264,6 +1310,54 @@ static void page_check_dirty_writeback(struct page *page,
mapping->a_ops->is_dirty_writeback(page, dirty, writeback);
}
+static struct page *alloc_demote_page(struct page *page, unsigned long node)
+{
+ struct migration_target_control mtc = {
+ /*
+ * Allocate from 'node', or fail quickly and quietly.
+ * When this happens, 'page' will likely just be discarded
+ * instead of migrated.
+ */
+ .gfp_mask = (GFP_HIGHUSER_MOVABLE & ~__GFP_RECLAIM) |
+ __GFP_THISNODE | __GFP_NOWARN |
+ __GFP_NOMEMALLOC | GFP_NOWAIT,
+ .nid = node
+ };
+
+ return alloc_migration_target(page, (unsigned long)&mtc);
+}
+
+/*
+ * Take pages on @demote_list and attempt to demote them to
+ * another node. Pages which are not demoted are left on
+ * @demote_pages.
+ */
+static unsigned int demote_page_list(struct list_head *demote_pages,
+ struct pglist_data *pgdat)
+{
+ int target_nid = next_demotion_node(pgdat->node_id);
+ unsigned int nr_succeeded;
+ int err;
+
+ if (list_empty(demote_pages))
+ return 0;
+
+ if (target_nid == NUMA_NO_NODE)
+ return 0;
+
+ /* Demotion ignores all cpuset and mempolicy settings */
+ err = migrate_pages(demote_pages, alloc_demote_page, NULL,
+ target_nid, MIGRATE_ASYNC, MR_DEMOTION,
+ &nr_succeeded);
+
+ if (current_is_kswapd())
+ __count_vm_events(PGDEMOTE_KSWAPD, nr_succeeded);
+ else
+ __count_vm_events(PGDEMOTE_DIRECT, nr_succeeded);
+
+ return nr_succeeded;
+}
+
/*
* shrink_page_list() returns the number of reclaimed pages
*/
@@ -1275,12 +1369,16 @@ static unsigned int shrink_page_list(struct list_head *page_list,
{
LIST_HEAD(ret_pages);
LIST_HEAD(free_pages);
+ LIST_HEAD(demote_pages);
unsigned int nr_reclaimed = 0;
unsigned int pgactivate = 0;
+ bool do_demote_pass;
memset(stat, 0, sizeof(*stat));
cond_resched();
+ do_demote_pass = can_demote(pgdat->node_id, sc);
+retry:
while (!list_empty(page_list)) {
struct address_space *mapping;
struct page *page;
@@ -1430,6 +1528,17 @@ static unsigned int shrink_page_list(struct list_head *page_list,
}
/*
+ * Before reclaiming the page, try to relocate
+ * its contents to another node.
+ */
+ if (do_demote_pass &&
+ (thp_migration_supported() || !PageTransHuge(page))) {
+ list_add(&page->lru, &demote_pages);
+ unlock_page(page);
+ continue;
+ }
+
+ /*
* Anonymous process memory has backing store?
* Try to allocate it some swap space here.
* Lazyfree page could be freed directly
@@ -1624,11 +1733,14 @@ static unsigned int shrink_page_list(struct list_head *page_list,
/* follow __remove_mapping for reference */
if (!page_ref_freeze(page, 1))
goto keep_locked;
- if (PageDirty(page)) {
- page_ref_unfreeze(page, 1);
- goto keep_locked;
- }
-
+ /*
+ * The page has only one reference left, which is
+ * from the isolation. After the caller puts the
+ * page back on lru and drops the reference, the
+ * page will be freed anyway. It doesn't matter
+ * which lru it goes. So we don't bother checking
+ * PageDirty here.
+ */
count_vm_event(PGLAZYFREED);
count_memcg_page_event(page, PGLAZYFREED);
} else if (!mapping || !__remove_mapping(mapping, page, true,
@@ -1680,6 +1792,17 @@ keep:
list_add(&page->lru, &ret_pages);
VM_BUG_ON_PAGE(PageLRU(page) || PageUnevictable(page), page);
}
+ /* 'page_list' is always empty here */
+
+ /* Migrate pages selected for demotion */
+ nr_reclaimed += demote_page_list(&demote_pages, pgdat);
+ /* Pages that could not be demoted are still in @demote_pages */
+ if (!list_empty(&demote_pages)) {
+ /* Pages which failed to demoted go back on @page_list for retry: */
+ list_splice_init(&demote_pages, page_list);
+ do_demote_pass = false;
+ goto retry;
+ }
pgactivate = stat->nr_activate[0] + stat->nr_activate[1];
@@ -1698,7 +1821,6 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
{
struct scan_control sc = {
.gfp_mask = GFP_KERNEL,
- .priority = DEF_PRIORITY,
.may_unmap = 1,
};
struct reclaim_stat stat;
@@ -2323,10 +2445,10 @@ unsigned long reclaim_pages(struct list_head *page_list)
unsigned int noreclaim_flag;
struct scan_control sc = {
.gfp_mask = GFP_KERNEL,
- .priority = DEF_PRIORITY,
.may_writepage = 1,
.may_unmap = 1,
.may_swap = 1,
+ .no_demotion = 1,
};
noreclaim_flag = memalloc_noreclaim_save();
@@ -2452,6 +2574,7 @@ enum scan_balance {
static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
unsigned long *nr)
{
+ struct pglist_data *pgdat = lruvec_pgdat(lruvec);
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
unsigned long anon_cost, file_cost, total_cost;
int swappiness = mem_cgroup_swappiness(memcg);
@@ -2462,7 +2585,7 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
enum lru_list lru;
/* If we have no swap space, do not bother scanning anon pages. */
- if (!sc->may_swap || mem_cgroup_get_nr_swap_pages(memcg) <= 0) {
+ if (!sc->may_swap || !can_reclaim_anon_pages(memcg, pgdat->node_id, sc)) {
scan_balance = SCAN_FILE;
goto out;
}
@@ -2645,6 +2768,21 @@ out:
}
}
+/*
+ * Anonymous LRU management is a waste if there is
+ * ultimately no way to reclaim the memory.
+ */
+static bool can_age_anon_pages(struct pglist_data *pgdat,
+ struct scan_control *sc)
+{
+ /* Aging the anon LRU is valuable if swap is present: */
+ if (total_swap_pages > 0)
+ return true;
+
+ /* Also valuable if anon pages can be demoted: */
+ return can_demote(pgdat->node_id, sc);
+}
+
static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
{
unsigned long nr[NR_LRU_LISTS];
@@ -2754,7 +2892,8 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
* Even if we did not try to evict anon pages at all, we want to
* rebalance the anon lru active/inactive ratio.
*/
- if (total_swap_pages && inactive_is_low(lruvec, LRU_INACTIVE_ANON))
+ if (can_age_anon_pages(lruvec_pgdat(lruvec), sc) &&
+ inactive_is_low(lruvec, LRU_INACTIVE_ANON))
shrink_active_list(SWAP_CLUSTER_MAX, lruvec,
sc, LRU_ACTIVE_ANON);
}
@@ -2824,7 +2963,7 @@ static inline bool should_continue_reclaim(struct pglist_data *pgdat,
*/
pages_for_compaction = compact_gap(sc->order);
inactive_lru_pages = node_page_state(pgdat, NR_INACTIVE_FILE);
- if (get_nr_swap_pages() > 0)
+ if (can_reclaim_anon_pages(NULL, pgdat->node_id, sc))
inactive_lru_pages += node_page_state(pgdat, NR_INACTIVE_ANON);
return inactive_lru_pages > pages_for_compaction;
@@ -2898,6 +3037,12 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
target_lruvec = mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat);
again:
+ /*
+ * Flush the memory cgroup stats, so that we read accurate per-memcg
+ * lruvec stats for heuristics.
+ */
+ mem_cgroup_flush_stats();
+
memset(&sc->nr, 0, sizeof(sc->nr));
nr_reclaimed = sc->nr_reclaimed;
@@ -3434,18 +3579,14 @@ static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
* blocked waiting on the same lock. Instead, throttle for up to a
* second before continuing.
*/
- if (!(gfp_mask & __GFP_FS)) {
+ if (!(gfp_mask & __GFP_FS))
wait_event_interruptible_timeout(pgdat->pfmemalloc_wait,
allow_direct_reclaim(pgdat), HZ);
+ else
+ /* Throttle until kswapd wakes the process */
+ wait_event_killable(zone->zone_pgdat->pfmemalloc_wait,
+ allow_direct_reclaim(pgdat));
- goto check_pending;
- }
-
- /* Throttle until kswapd wakes the process */
- wait_event_killable(zone->zone_pgdat->pfmemalloc_wait,
- allow_direct_reclaim(pgdat));
-
-check_pending:
if (fatal_signal_pending(current))
return true;
@@ -3583,7 +3724,7 @@ static void age_active_anon(struct pglist_data *pgdat,
struct mem_cgroup *memcg;
struct lruvec *lruvec;
- if (!total_swap_pages)
+ if (!can_age_anon_pages(pgdat, sc))
return;
lruvec = mem_cgroup_lruvec(NULL, pgdat);
@@ -3812,7 +3953,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int highest_zoneidx)
set_task_reclaim_state(current, &sc.reclaim_state);
psi_memstall_enter(&pflags);
- __fs_reclaim_acquire();
+ __fs_reclaim_acquire(_THIS_IP_);
count_vm_event(PAGEOUTRUN);
@@ -3938,9 +4079,9 @@ restart:
wake_up_all(&pgdat->pfmemalloc_wait);
/* Check if kswapd should be suspending */
- __fs_reclaim_release();
+ __fs_reclaim_release(_THIS_IP_);
ret = try_to_freeze();
- __fs_reclaim_acquire();
+ __fs_reclaim_acquire(_THIS_IP_);
if (ret || kthread_should_stop())
break;
@@ -3992,7 +4133,7 @@ out:
}
snapshot_refaults(NULL, pgdat);
- __fs_reclaim_release();
+ __fs_reclaim_release(_THIS_IP_);
psi_memstall_leave(&pflags);
set_task_reclaim_state(current, NULL);
@@ -4290,23 +4431,20 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim)
* This kswapd start function will be called by init and node-hot-add.
* On node-hot-add, kswapd will moved to proper cpus if cpus are hot-added.
*/
-int kswapd_run(int nid)
+void kswapd_run(int nid)
{
pg_data_t *pgdat = NODE_DATA(nid);
- int ret = 0;
if (pgdat->kswapd)
- return 0;
+ return;
pgdat->kswapd = kthread_run(kswapd, pgdat, "kswapd%d", nid);
if (IS_ERR(pgdat->kswapd)) {
/* failure at boot is fatal */
BUG_ON(system_state < SYSTEM_RUNNING);
pr_err("Failed to start kswapd on node %d\n", nid);
- ret = PTR_ERR(pgdat->kswapd);
pgdat->kswapd = NULL;
}
- return ret;
}
/*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index a7ed56ac4c0b..0885a34197b7 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -204,7 +204,7 @@ int calculate_normal_threshold(struct zone *zone)
*
* Some sample thresholds:
*
- * Threshold Processors (fls) Zonesize fls(mem+1)
+ * Threshold Processors (fls) Zonesize fls(mem)+1
* ------------------------------------------------------------------
* 8 1 1 0.9-1 GB 4
* 16 2 2 0.9-1 GB 4
@@ -1217,6 +1217,8 @@ const char * const vmstat_text[] = {
"pgreuse",
"pgsteal_kswapd",
"pgsteal_direct",
+ "pgdemote_kswapd",
+ "pgdemote_direct",
"pgscan_kswapd",
"pgscan_direct",
"pgscan_direct_throttle",
@@ -1452,7 +1454,7 @@ static void pagetypeinfo_showfree_print(struct seq_file *m,
}
/* Print out the free pages at each order for each migatetype */
-static int pagetypeinfo_showfree(struct seq_file *m, void *arg)
+static void pagetypeinfo_showfree(struct seq_file *m, void *arg)
{
int order;
pg_data_t *pgdat = (pg_data_t *)arg;
@@ -1464,8 +1466,6 @@ static int pagetypeinfo_showfree(struct seq_file *m, void *arg)
seq_putc(m, '\n');
walk_zones_in_node(m, pgdat, true, false, pagetypeinfo_showfree_print);
-
- return 0;
}
static void pagetypeinfo_showblockcount_print(struct seq_file *m,
@@ -1501,7 +1501,7 @@ static void pagetypeinfo_showblockcount_print(struct seq_file *m,
}
/* Print out the number of pageblocks for each migratetype */
-static int pagetypeinfo_showblockcount(struct seq_file *m, void *arg)
+static void pagetypeinfo_showblockcount(struct seq_file *m, void *arg)
{
int mtype;
pg_data_t *pgdat = (pg_data_t *)arg;
@@ -1512,8 +1512,6 @@ static int pagetypeinfo_showblockcount(struct seq_file *m, void *arg)
seq_putc(m, '\n');
walk_zones_in_node(m, pgdat, true, false,
pagetypeinfo_showblockcount_print);
-
- return 0;
}
/*
@@ -1874,11 +1872,6 @@ static void vmstat_update(struct work_struct *w)
}
/*
- * Switch off vmstat processing and then fold all the remaining differentials
- * until the diffs stay at zero. The function is used by NOHZ and can only be
- * invoked when tick processing is not active.
- */
-/*
* Check if the diffs for a certain cpu indicate that
* an update is needed.
*/
@@ -1894,17 +1887,15 @@ static bool need_update(int cpu)
/*
* The fast way of checking if there are any vmstat diffs.
*/
- if (memchr_inv(pzstats->vm_stat_diff, 0, NR_VM_ZONE_STAT_ITEMS *
- sizeof(pzstats->vm_stat_diff[0])))
+ if (memchr_inv(pzstats->vm_stat_diff, 0, sizeof(pzstats->vm_stat_diff)))
return true;
if (last_pgdat == zone->zone_pgdat)
continue;
last_pgdat = zone->zone_pgdat;
n = per_cpu_ptr(zone->zone_pgdat->per_cpu_nodestats, cpu);
- if (memchr_inv(n->vm_node_stat_diff, 0, NR_VM_NODE_STAT_ITEMS *
- sizeof(n->vm_node_stat_diff[0])))
- return true;
+ if (memchr_inv(n->vm_node_stat_diff, 0, sizeof(n->vm_node_stat_diff)))
+ return true;
}
return false;
}
diff --git a/net/batman-adv/log.c b/net/batman-adv/log.c
index f0e5d1429662..7a93a1e94c40 100644
--- a/net/batman-adv/log.c
+++ b/net/batman-adv/log.c
@@ -7,7 +7,7 @@
#include "log.h"
#include "main.h"
-#include <stdarg.h>
+#include <linux/stdarg.h>
#include "trace.h"
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 4e095746e002..ebd78fdbd6e8 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -1127,9 +1127,10 @@ int __init rfcomm_init_ttys(void)
{
int error;
- rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
- if (!rfcomm_tty_driver)
- return -ENOMEM;
+ rfcomm_tty_driver = tty_alloc_driver(RFCOMM_TTY_PORTS,
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+ if (IS_ERR(rfcomm_tty_driver))
+ return PTR_ERR(rfcomm_tty_driver);
rfcomm_tty_driver->driver_name = "rfcomm";
rfcomm_tty_driver->name = "rfcomm";
@@ -1137,7 +1138,6 @@ int __init rfcomm_init_ttys(void)
rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR;
rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
rfcomm_tty_driver->init_termios = tty_std_termios;
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
@@ -1146,7 +1146,7 @@ int __init rfcomm_init_ttys(void)
error = tty_register_driver(rfcomm_tty_driver);
if (error) {
BT_ERR("Can't register RFCOMM TTY driver");
- put_tty_driver(rfcomm_tty_driver);
+ tty_driver_kref_put(rfcomm_tty_driver);
return error;
}
@@ -1158,5 +1158,5 @@ int __init rfcomm_init_ttys(void)
void rfcomm_cleanup_ttys(void)
{
tty_unregister_driver(rfcomm_tty_driver);
- put_tty_driver(rfcomm_tty_driver);
+ tty_driver_kref_put(rfcomm_tty_driver);
}
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 9231617a16e4..3523c8c7068f 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -4255,7 +4255,7 @@ int br_multicast_set_port_router(struct net_bridge_mcast_port *pmctx,
bool del = false;
brmctx = br_multicast_port_ctx_get_global(pmctx);
- spin_lock(&brmctx->br->multicast_lock);
+ spin_lock_bh(&brmctx->br->multicast_lock);
if (pmctx->multicast_router == val) {
/* Refresh the temp router port timer */
if (pmctx->multicast_router == MDB_RTR_TYPE_TEMP) {
@@ -4305,7 +4305,7 @@ int br_multicast_set_port_router(struct net_bridge_mcast_port *pmctx,
}
err = 0;
unlock:
- spin_unlock(&brmctx->br->multicast_lock);
+ spin_unlock_bh(&brmctx->br->multicast_lock);
return err;
}
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index 37b67194c0df..414dc5671c45 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -53,20 +53,6 @@ struct chnl_net {
enum caif_states state;
};
-static void robust_list_del(struct list_head *delete_node)
-{
- struct list_head *list_node;
- struct list_head *n;
- ASSERT_RTNL();
- list_for_each_safe(list_node, n, &chnl_net_list) {
- if (list_node == delete_node) {
- list_del(list_node);
- return;
- }
- }
- WARN_ON(1);
-}
-
static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
{
struct sk_buff *skb;
@@ -364,6 +350,7 @@ static int chnl_net_init(struct net_device *dev)
ASSERT_RTNL();
priv = netdev_priv(dev);
strncpy(priv->name, dev->name, sizeof(priv->name));
+ INIT_LIST_HEAD(&priv->list_field);
return 0;
}
@@ -372,7 +359,7 @@ static void chnl_net_uninit(struct net_device *dev)
struct chnl_net *priv;
ASSERT_RTNL();
priv = netdev_priv(dev);
- robust_list_del(&priv->list_field);
+ list_del_init(&priv->list_field);
}
static const struct net_device_ops netdev_ops = {
@@ -537,7 +524,7 @@ static void __exit chnl_exit_module(void)
rtnl_lock();
list_for_each_safe(list_node, _tmp, &chnl_net_list) {
dev = list_entry(list_node, struct chnl_net, list_field);
- list_del(list_node);
+ list_del_init(list_node);
delete_device(dev);
}
rtnl_unlock();
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 9e5a3249373c..a3d74e2704c4 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3602,7 +3602,6 @@ out:
static int pktgen_thread_worker(void *arg)
{
- DEFINE_WAIT(wait);
struct pktgen_thread *t = arg;
struct pktgen_dev *pkt_dev = NULL;
int cpu = t->cpu;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f9311762cc47..2170bea2c7de 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3884,7 +3884,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
skb_push(nskb, -skb_network_offset(nskb) + offset);
skb_release_head_state(nskb);
- __copy_skb_header(nskb, skb);
+ __copy_skb_header(nskb, skb);
skb_headers_offset_update(nskb, skb_headroom(nskb) - skb_headroom(skb));
skb_copy_from_linear_data_offset(skb, -tnl_hlen,
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index c5c74a34d139..91e7a2202697 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -94,6 +94,8 @@ struct sock *dccp_create_openreq_child(const struct sock *sk,
newdp->dccps_role = DCCP_ROLE_SERVER;
newdp->dccps_hc_rx_ackvec = NULL;
newdp->dccps_service_list = NULL;
+ newdp->dccps_hc_rx_ccid = NULL;
+ newdp->dccps_hc_tx_ccid = NULL;
newdp->dccps_service = dreq->dreq_service;
newdp->dccps_timestamp_echo = dreq->dreq_timestamp_echo;
newdp->dccps_timestamp_time = dreq->dreq_timestamp_time;
diff --git a/net/dsa/tag_rtl4_a.c b/net/dsa/tag_rtl4_a.c
index 40811bab4d09..f920487ae145 100644
--- a/net/dsa/tag_rtl4_a.c
+++ b/net/dsa/tag_rtl4_a.c
@@ -54,9 +54,10 @@ static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
p = (__be16 *)tag;
*p = htons(RTL4_A_ETHERTYPE);
- out = (RTL4_A_PROTOCOL_RTL8366RB << 12) | (2 << 8);
- /* The lower bits is the port number */
- out |= (u8)dp->index;
+ out = (RTL4_A_PROTOCOL_RTL8366RB << RTL4_A_PROTOCOL_SHIFT) | (2 << 8);
+ /* The lower bits indicate the port number */
+ out |= BIT(dp->index);
+
p = (__be16 *)(tag + 2);
*p = htons(out);
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 7fbd0b532f52..099259fc826a 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -465,16 +465,14 @@ void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
if (!doi_def)
return;
- if (doi_def->map.std) {
- switch (doi_def->type) {
- case CIPSO_V4_MAP_TRANS:
- kfree(doi_def->map.std->lvl.cipso);
- kfree(doi_def->map.std->lvl.local);
- kfree(doi_def->map.std->cat.cipso);
- kfree(doi_def->map.std->cat.local);
- kfree(doi_def->map.std);
- break;
- }
+ switch (doi_def->type) {
+ case CIPSO_V4_MAP_TRANS:
+ kfree(doi_def->map.std->lvl.cipso);
+ kfree(doi_def->map.std->lvl.local);
+ kfree(doi_def->map.std->cat.cipso);
+ kfree(doi_def->map.std->cat.local);
+ kfree(doi_def->map.std);
+ break;
}
kfree(doi_def);
}
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 177d26d8fb9c..0fe6c936dc54 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -473,8 +473,6 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
static int gre_handle_offloads(struct sk_buff *skb, bool csum)
{
- if (csum && skb_checksum_start(skb) < skb->data)
- return -EINVAL;
return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
}
@@ -632,15 +630,20 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
}
if (dev->header_ops) {
+ const int pull_len = tunnel->hlen + sizeof(struct iphdr);
+
if (skb_cow_head(skb, 0))
goto free_skb;
tnl_params = (const struct iphdr *)skb->data;
+ if (pull_len > skb_transport_offset(skb))
+ goto free_skb;
+
/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
* to gre header.
*/
- skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
+ skb_pull(skb, pull_len);
skb_reset_mac_header(skb);
} else {
if (skb_cow_head(skb, dev->needed_headroom))
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index b297bb28556e..7cef9987ab4a 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -279,7 +279,7 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
case IP_RETOPTS:
err = cmsg->cmsg_len - sizeof(struct cmsghdr);
- /* Our caller is responsible for freeing ipc->opt */
+ /* Our caller is responsible for freeing ipc->opt when err = 0 */
err = ip_options_get(net, &ipc->opt,
KERNEL_SOCKPTR(CMSG_DATA(cmsg)),
err < 40 ? err : 40);
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index 4075230b14c6..75ca4b6e484f 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -2490,6 +2490,7 @@ static int nh_create_ipv4(struct net *net, struct nexthop *nh,
.fc_gw4 = cfg->gw.ipv4,
.fc_gw_family = cfg->gw.ipv4 ? AF_INET : 0,
.fc_flags = cfg->nh_flags,
+ .fc_nlinfo = cfg->nlinfo,
.fc_encap = cfg->nh_encap,
.fc_encap_type = cfg->nh_encap_type,
};
@@ -2528,6 +2529,7 @@ static int nh_create_ipv6(struct net *net, struct nexthop *nh,
.fc_ifindex = cfg->nh_ifindex,
.fc_gateway = cfg->gw.ipv6,
.fc_flags = cfg->nh_flags,
+ .fc_nlinfo = cfg->nlinfo,
.fc_encap = cfg->nh_encap,
.fc_encap_type = cfg->nh_encap_type,
.fc_is_fdb = cfg->nh_fdb,
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 1e44a43acfe2..c588f9f2f46c 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -727,10 +727,9 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (msg->msg_controllen) {
err = ip_cmsg_send(sk, msg, &ipc, false);
- if (unlikely(err)) {
- kfree(ipc.opt);
+ if (unlikely(err))
return err;
- }
+
if (ipc.opt)
free = 1;
}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index bb446e60cf58..1c98063a3ae8 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -562,10 +562,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (msg->msg_controllen) {
err = ip_cmsg_send(sk, msg, &ipc, false);
- if (unlikely(err)) {
- kfree(ipc.opt);
+ if (unlikely(err))
goto out;
- }
+
if (ipc.opt)
free = 1;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 8851c9463b4b..d5f5981d7a43 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1122,10 +1122,9 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (err > 0)
err = ip_cmsg_send(sk, msg, &ipc,
sk->sk_family == AF_INET6);
- if (unlikely(err < 0)) {
- kfree(ipc.opt);
+ if (unlikely(err < 0))
return err;
- }
+
if (ipc.opt)
free = 1;
connected = 0;
diff --git a/net/ipv4/udp_tunnel_nic.c b/net/ipv4/udp_tunnel_nic.c
index 0d122edc368d..b91003538d87 100644
--- a/net/ipv4/udp_tunnel_nic.c
+++ b/net/ipv4/udp_tunnel_nic.c
@@ -935,7 +935,7 @@ static int __init udp_tunnel_nic_init_module(void)
{
int err;
- udp_tunnel_nic_workqueue = alloc_workqueue("udp_tunnel_nic", 0, 0);
+ udp_tunnel_nic_workqueue = alloc_ordered_workqueue("udp_tunnel_nic", 0);
if (!udp_tunnel_nic_workqueue)
return -ENOMEM;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 17756f3ed33b..c6a90b7bbb70 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3092,19 +3092,22 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
}
}
-#if IS_ENABLED(CONFIG_IPV6_SIT)
-static void sit_add_v4_addrs(struct inet6_dev *idev)
+#if IS_ENABLED(CONFIG_IPV6_SIT) || IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
+static void add_v4_addrs(struct inet6_dev *idev)
{
struct in6_addr addr;
struct net_device *dev;
struct net *net = dev_net(idev->dev);
- int scope, plen;
+ int scope, plen, offset = 0;
u32 pflags = 0;
ASSERT_RTNL();
memset(&addr, 0, sizeof(struct in6_addr));
- memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
+ /* in case of IP6GRE the dev_addr is an IPv6 and therefore we use only the last 4 bytes */
+ if (idev->dev->addr_len == sizeof(struct in6_addr))
+ offset = sizeof(struct in6_addr) - 4;
+ memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
if (idev->dev->flags&IFF_POINTOPOINT) {
addr.s6_addr32[0] = htonl(0xfe800000);
@@ -3342,8 +3345,6 @@ static void addrconf_dev_config(struct net_device *dev)
(dev->type != ARPHRD_IEEE1394) &&
(dev->type != ARPHRD_TUNNEL6) &&
(dev->type != ARPHRD_6LOWPAN) &&
- (dev->type != ARPHRD_IP6GRE) &&
- (dev->type != ARPHRD_IPGRE) &&
(dev->type != ARPHRD_TUNNEL) &&
(dev->type != ARPHRD_NONE) &&
(dev->type != ARPHRD_RAWIP)) {
@@ -3391,14 +3392,14 @@ static void addrconf_sit_config(struct net_device *dev)
return;
}
- sit_add_v4_addrs(idev);
+ add_v4_addrs(idev);
if (dev->flags&IFF_POINTOPOINT)
addrconf_add_mroute(dev);
}
#endif
-#if IS_ENABLED(CONFIG_NET_IPGRE)
+#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
static void addrconf_gre_config(struct net_device *dev)
{
struct inet6_dev *idev;
@@ -3411,7 +3412,13 @@ static void addrconf_gre_config(struct net_device *dev)
return;
}
- addrconf_addr_gen(idev, true);
+ if (dev->type == ARPHRD_ETHER) {
+ addrconf_addr_gen(idev, true);
+ return;
+ }
+
+ add_v4_addrs(idev);
+
if (dev->flags & IFF_POINTOPOINT)
addrconf_add_mroute(dev);
}
@@ -3587,7 +3594,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
addrconf_sit_config(dev);
break;
#endif
-#if IS_ENABLED(CONFIG_NET_IPGRE)
+#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
+ case ARPHRD_IP6GRE:
case ARPHRD_IPGRE:
addrconf_gre_config(dev);
break;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 1bec5b22f80d..0371d2c14145 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1378,7 +1378,6 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
int err = -ENOMEM;
int allow_create = 1;
int replace_required = 0;
- int sernum = fib6_new_sernum(info->nl_net);
if (info->nlh) {
if (!(info->nlh->nlmsg_flags & NLM_F_CREATE))
@@ -1478,7 +1477,7 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
if (!err) {
if (rt->nh)
list_add(&rt->nh_list, &rt->nh->f6i_list);
- __fib6_update_sernum_upto_root(rt, sernum);
+ __fib6_update_sernum_upto_root(rt, fib6_new_sernum(info->nl_net));
fib6_start_gc(info->nl_net, rt);
}
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 7baf41d160f5..3ad201d372d8 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -629,8 +629,6 @@ drop:
static int gre_handle_offloads(struct sk_buff *skb, bool csum)
{
- if (csum && skb_checksum_start(skb) < skb->data)
- return -EINVAL;
return iptunnel_handle_offloads(skb,
csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index cd951faa2fac..bed8155508c8 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1356,8 +1356,8 @@ static int mld_process_v1(struct inet6_dev *idev, struct mld_msg *mld,
return 0;
}
-static int mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld,
- unsigned long *max_delay)
+static void mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld,
+ unsigned long *max_delay)
{
*max_delay = max(msecs_to_jiffies(mldv2_mrc(mld)), 1UL);
@@ -1367,7 +1367,7 @@ static int mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld,
idev->mc_maxdelay = *max_delay;
- return 0;
+ return;
}
/* called with rcu_read_lock() */
@@ -1454,9 +1454,7 @@ static void __mld_query_work(struct sk_buff *skb)
mlh2 = (struct mld2_query *)skb_transport_header(skb);
- err = mld_process_v2(idev, mlh2, &max_delay);
- if (err < 0)
- goto out;
+ mld_process_v2(idev, mlh2, &max_delay);
if (group_type == IPV6_ADDR_ANY) { /* general query */
if (mlh2->mld2q_nsrcs)
diff --git a/net/ipv6/netfilter/nf_socket_ipv6.c b/net/ipv6/netfilter/nf_socket_ipv6.c
index 6fd54744cbc3..aa5bb8789ba0 100644
--- a/net/ipv6/netfilter/nf_socket_ipv6.c
+++ b/net/ipv6/netfilter/nf_socket_ipv6.c
@@ -99,7 +99,7 @@ struct sock *nf_sk_lookup_slow_v6(struct net *net, const struct sk_buff *skb,
{
__be16 dport, sport;
const struct in6_addr *daddr = NULL, *saddr = NULL;
- struct ipv6hdr *iph = ipv6_hdr(skb);
+ struct ipv6hdr *iph = ipv6_hdr(skb), ipv6_var;
struct sk_buff *data_skb = NULL;
int doff = 0;
int thoff = 0, tproto;
@@ -129,8 +129,6 @@ struct sock *nf_sk_lookup_slow_v6(struct net *net, const struct sk_buff *skb,
thoff + sizeof(*hp);
} else if (tproto == IPPROTO_ICMPV6) {
- struct ipv6hdr ipv6_var;
-
if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
&sport, &dport, &ipv6_var))
return NULL;
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index 1bf5f5ae75ac..3adc5d9211ad 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -385,7 +385,7 @@ static int seg6_output_core(struct net *net, struct sock *sk,
struct dst_entry *orig_dst = skb_dst(skb);
struct dst_entry *dst = NULL;
struct seg6_lwt *slwt;
- int err = -EINVAL;
+ int err;
err = seg6_do_srh(skb);
if (unlikely(err))
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 53486b162f01..93271a2632b8 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -869,8 +869,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
}
if (tunnel->version == L2TP_HDR_VER_3 &&
- l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+ l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) {
+ l2tp_session_dec_refcount(session);
goto invalid;
+ }
l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
l2tp_session_dec_refcount(session);
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index 1cf5ac09edcb..323d3d2d986f 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -617,7 +617,7 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name,
{
struct net_device *ndev = NULL;
struct ieee802154_sub_if_data *sdata = NULL;
- int ret = -ENOMEM;
+ int ret;
ASSERT_RTNL();
diff --git a/net/mctp/route.c b/net/mctp/route.c
index 5265525011ad..5ca186d53cb0 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
@@ -1083,8 +1083,10 @@ static void __net_exit mctp_routes_net_exit(struct net *net)
{
struct mctp_route *rt;
+ rcu_read_lock();
list_for_each_entry_rcu(rt, &net->mctp.routes, list)
mctp_route_release(rt);
+ rcu_read_unlock();
}
static struct pernet_operations mctp_net_ops = {
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 1e4289c507ff..c4f9a5ce3815 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -644,15 +644,12 @@ void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
subflow = list_first_entry_or_null(&msk->conn_list, typeof(*subflow), node);
if (subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
- bool slow;
spin_unlock_bh(&msk->pm.lock);
pr_debug("send ack for %s",
mptcp_pm_should_add_signal(msk) ? "add_addr" : "rm_addr");
- slow = lock_sock_fast(ssk);
- tcp_send_ack(ssk);
- unlock_sock_fast(ssk, slow);
+ mptcp_subflow_send_ack(ssk);
spin_lock_bh(&msk->pm.lock);
}
}
@@ -669,7 +666,6 @@ int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
struct sock *sk = (struct sock *)msk;
struct mptcp_addr_info local;
- bool slow;
local_address((struct sock_common *)ssk, &local);
if (!addresses_equal(&local, addr, addr->port))
@@ -682,9 +678,7 @@ int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
spin_unlock_bh(&msk->pm.lock);
pr_debug("send ack for mp_prio");
- slow = lock_sock_fast(ssk);
- tcp_send_ack(ssk);
- unlock_sock_fast(ssk, slow);
+ mptcp_subflow_send_ack(ssk);
spin_lock_bh(&msk->pm.lock);
return 0;
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index ade648c3512b..2602f1386160 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -440,19 +440,22 @@ static bool tcp_can_send_ack(const struct sock *ssk)
(TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_TIME_WAIT | TCPF_CLOSE | TCPF_LISTEN));
}
+void mptcp_subflow_send_ack(struct sock *ssk)
+{
+ bool slow;
+
+ slow = lock_sock_fast(ssk);
+ if (tcp_can_send_ack(ssk))
+ tcp_send_ack(ssk);
+ unlock_sock_fast(ssk, slow);
+}
+
static void mptcp_send_ack(struct mptcp_sock *msk)
{
struct mptcp_subflow_context *subflow;
- mptcp_for_each_subflow(msk, subflow) {
- struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
- bool slow;
-
- slow = lock_sock_fast(ssk);
- if (tcp_can_send_ack(ssk))
- tcp_send_ack(ssk);
- unlock_sock_fast(ssk, slow);
- }
+ mptcp_for_each_subflow(msk, subflow)
+ mptcp_subflow_send_ack(mptcp_subflow_tcp_sock(subflow));
}
static void mptcp_subflow_cleanup_rbuf(struct sock *ssk)
@@ -1003,6 +1006,13 @@ static void mptcp_wmem_uncharge(struct sock *sk, int size)
msk->wmem_reserved += size;
}
+static void __mptcp_mem_reclaim_partial(struct sock *sk)
+{
+ lockdep_assert_held_once(&sk->sk_lock.slock);
+ __mptcp_update_wmem(sk);
+ sk_mem_reclaim_partial(sk);
+}
+
static void mptcp_mem_reclaim_partial(struct sock *sk)
{
struct mptcp_sock *msk = mptcp_sk(sk);
@@ -1094,12 +1104,8 @@ static void __mptcp_clean_una(struct sock *sk)
msk->recovery = false;
out:
- if (cleaned) {
- if (tcp_under_memory_pressure(sk)) {
- __mptcp_update_wmem(sk);
- sk_mem_reclaim_partial(sk);
- }
- }
+ if (cleaned && tcp_under_memory_pressure(sk))
+ __mptcp_mem_reclaim_partial(sk);
if (snd_una == READ_ONCE(msk->snd_nxt) && !msk->recovery) {
if (mptcp_timer_pending(sk) && !mptcp_data_fin_enabled(msk))
@@ -1179,6 +1185,7 @@ struct mptcp_sendmsg_info {
u16 limit;
u16 sent;
unsigned int flags;
+ bool data_lock_held;
};
static int mptcp_check_allowed_size(struct mptcp_sock *msk, u64 data_seq,
@@ -1250,17 +1257,17 @@ static bool __mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, gfp_t gfp)
return false;
}
-static bool mptcp_must_reclaim_memory(struct sock *sk, struct sock *ssk)
+static bool mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, bool data_lock_held)
{
- return !ssk->sk_tx_skb_cache &&
- tcp_under_memory_pressure(sk);
-}
+ gfp_t gfp = data_lock_held ? GFP_ATOMIC : sk->sk_allocation;
-static bool mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk)
-{
- if (unlikely(mptcp_must_reclaim_memory(sk, ssk)))
- mptcp_mem_reclaim_partial(sk);
- return __mptcp_alloc_tx_skb(sk, ssk, sk->sk_allocation);
+ if (unlikely(tcp_under_memory_pressure(sk))) {
+ if (data_lock_held)
+ __mptcp_mem_reclaim_partial(sk);
+ else
+ mptcp_mem_reclaim_partial(sk);
+ }
+ return __mptcp_alloc_tx_skb(sk, ssk, gfp);
}
/* note: this always recompute the csum on the whole skb, even
@@ -1284,7 +1291,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
bool zero_window_probe = false;
struct mptcp_ext *mpext = NULL;
struct sk_buff *skb, *tail;
- bool can_collapse = false;
+ bool must_collapse = false;
int size_bias = 0;
int avail_size;
size_t ret = 0;
@@ -1304,16 +1311,24 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
* SSN association set here
*/
mpext = skb_ext_find(skb, SKB_EXT_MPTCP);
- can_collapse = (info->size_goal - skb->len > 0) &&
- mptcp_skb_can_collapse_to(data_seq, skb, mpext);
- if (!can_collapse) {
+ if (!mptcp_skb_can_collapse_to(data_seq, skb, mpext)) {
TCP_SKB_CB(skb)->eor = 1;
- } else {
+ goto alloc_skb;
+ }
+
+ must_collapse = (info->size_goal - skb->len > 0) &&
+ (skb_shinfo(skb)->nr_frags < sysctl_max_skb_frags);
+ if (must_collapse) {
size_bias = skb->len;
avail_size = info->size_goal - skb->len;
}
}
+alloc_skb:
+ if (!must_collapse && !ssk->sk_tx_skb_cache &&
+ !mptcp_alloc_tx_skb(sk, ssk, info->data_lock_held))
+ return 0;
+
/* Zero window and all data acked? Probe. */
avail_size = mptcp_check_allowed_size(msk, data_seq, avail_size);
if (avail_size == 0) {
@@ -1343,7 +1358,6 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
if (skb == tail) {
TCP_SKB_CB(tail)->tcp_flags &= ~TCPHDR_PSH;
mpext->data_len += ret;
- WARN_ON_ONCE(!can_collapse);
WARN_ON_ONCE(zero_window_probe);
goto out;
}
@@ -1530,15 +1544,6 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
if (ssk != prev_ssk)
lock_sock(ssk);
- /* keep it simple and always provide a new skb for the
- * subflow, even if we will not use it when collapsing
- * on the pending one
- */
- if (!mptcp_alloc_tx_skb(sk, ssk)) {
- mptcp_push_release(sk, ssk, &info);
- goto out;
- }
-
ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
if (ret <= 0) {
mptcp_push_release(sk, ssk, &info);
@@ -1571,7 +1576,9 @@ out:
static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
{
struct mptcp_sock *msk = mptcp_sk(sk);
- struct mptcp_sendmsg_info info;
+ struct mptcp_sendmsg_info info = {
+ .data_lock_held = true,
+ };
struct mptcp_data_frag *dfrag;
struct sock *xmit_ssk;
int len, copied = 0;
@@ -1597,13 +1604,6 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
goto out;
}
- if (unlikely(mptcp_must_reclaim_memory(sk, ssk))) {
- __mptcp_update_wmem(sk);
- sk_mem_reclaim_partial(sk);
- }
- if (!__mptcp_alloc_tx_skb(sk, ssk, GFP_ATOMIC))
- goto out;
-
ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
if (ret <= 0)
goto out;
@@ -2409,9 +2409,6 @@ static void __mptcp_retrans(struct sock *sk)
info.sent = 0;
info.limit = READ_ONCE(msk->csum_enabled) ? dfrag->data_len : dfrag->already_sent;
while (info.sent < info.limit) {
- if (!mptcp_alloc_tx_skb(sk, ssk))
- break;
-
ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
if (ret <= 0)
break;
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index d7aba1c4dc48..d3e6fd1615f1 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -34,7 +34,7 @@
#define OPTIONS_MPTCP_MPC (OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | \
OPTION_MPTCP_MPC_ACK)
#define OPTIONS_MPTCP_MPJ (OPTION_MPTCP_MPJ_SYN | OPTION_MPTCP_MPJ_SYNACK | \
- OPTION_MPTCP_MPJ_SYNACK)
+ OPTION_MPTCP_MPJ_ACK)
/* MPTCP option subtypes */
#define MPTCPOPT_MP_CAPABLE 0
@@ -573,6 +573,7 @@ void __init mptcp_subflow_init(void);
void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how);
void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
struct mptcp_subflow_context *subflow);
+void mptcp_subflow_send_ack(struct sock *ssk);
void mptcp_subflow_reset(struct sock *ssk);
void mptcp_sock_graft(struct sock *sk, struct socket *parent);
struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index 0b6cfd3b31e0..03757e76bb6b 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -80,6 +80,7 @@ enum {
#define NCSI_OEM_MFR_BCM_ID 0x113d
#define NCSI_OEM_MFR_INTEL_ID 0x157
/* Intel specific OEM command */
+#define NCSI_OEM_INTEL_CMD_GMA 0x06 /* CMD ID for Get MAC */
#define NCSI_OEM_INTEL_CMD_KEEP_PHY 0x20 /* CMD ID for Keep PHY up */
/* Broadcom specific OEM Command */
#define NCSI_OEM_BCM_CMD_GMA 0x01 /* CMD ID for Get MAC */
@@ -89,6 +90,7 @@ enum {
#define NCSI_OEM_MLX_CMD_SMAF 0x01 /* CMD ID for Set MC Affinity */
#define NCSI_OEM_MLX_CMD_SMAF_PARAM 0x07 /* Parameter for SMAF */
/* OEM Command payload lengths*/
+#define NCSI_OEM_INTEL_CMD_GMA_LEN 5
#define NCSI_OEM_INTEL_CMD_KEEP_PHY_LEN 7
#define NCSI_OEM_BCM_CMD_GMA_LEN 12
#define NCSI_OEM_MLX_CMD_GMA_LEN 8
@@ -99,6 +101,7 @@ enum {
/* Mac address offset in OEM response */
#define BCM_MAC_ADDR_OFFSET 28
#define MLX_MAC_ADDR_OFFSET 8
+#define INTEL_MAC_ADDR_OFFSET 1
struct ncsi_channel_version {
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 89c7742cd72e..7121ce2a47c0 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -795,13 +795,36 @@ static int ncsi_oem_smaf_mlx(struct ncsi_cmd_arg *nca)
return ret;
}
+static int ncsi_oem_gma_handler_intel(struct ncsi_cmd_arg *nca)
+{
+ unsigned char data[NCSI_OEM_INTEL_CMD_GMA_LEN];
+ int ret = 0;
+
+ nca->payload = NCSI_OEM_INTEL_CMD_GMA_LEN;
+
+ memset(data, 0, NCSI_OEM_INTEL_CMD_GMA_LEN);
+ *(unsigned int *)data = ntohl((__force __be32)NCSI_OEM_MFR_INTEL_ID);
+ data[4] = NCSI_OEM_INTEL_CMD_GMA;
+
+ nca->data = data;
+
+ ret = ncsi_xmit_cmd(nca);
+ if (ret)
+ netdev_err(nca->ndp->ndev.dev,
+ "NCSI: Failed to transmit cmd 0x%x during configure\n",
+ nca->type);
+
+ return ret;
+}
+
/* OEM Command handlers initialization */
static struct ncsi_oem_gma_handler {
unsigned int mfr_id;
int (*handler)(struct ncsi_cmd_arg *nca);
} ncsi_oem_gma_handlers[] = {
{ NCSI_OEM_MFR_BCM_ID, ncsi_oem_gma_handler_bcm },
- { NCSI_OEM_MFR_MLX_ID, ncsi_oem_gma_handler_mlx }
+ { NCSI_OEM_MFR_MLX_ID, ncsi_oem_gma_handler_mlx },
+ { NCSI_OEM_MFR_INTEL_ID, ncsi_oem_gma_handler_intel }
};
static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id)
diff --git a/net/ncsi/ncsi-pkt.h b/net/ncsi/ncsi-pkt.h
index 80938b338fee..ba66c7dc3a21 100644
--- a/net/ncsi/ncsi-pkt.h
+++ b/net/ncsi/ncsi-pkt.h
@@ -178,6 +178,12 @@ struct ncsi_rsp_oem_bcm_pkt {
unsigned char data[]; /* Cmd specific Data */
};
+/* Intel Response Data */
+struct ncsi_rsp_oem_intel_pkt {
+ unsigned char cmd; /* OEM Command ID */
+ unsigned char data[]; /* Cmd specific Data */
+};
+
/* Get Link Status */
struct ncsi_rsp_gls_pkt {
struct ncsi_rsp_pkt_hdr rsp; /* Response header */
diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
index d48374894817..6447a09932f5 100644
--- a/net/ncsi/ncsi-rsp.c
+++ b/net/ncsi/ncsi-rsp.c
@@ -699,9 +699,51 @@ static int ncsi_rsp_handler_oem_bcm(struct ncsi_request *nr)
return 0;
}
+/* Response handler for Intel command Get Mac Address */
+static int ncsi_rsp_handler_oem_intel_gma(struct ncsi_request *nr)
+{
+ struct ncsi_dev_priv *ndp = nr->ndp;
+ struct net_device *ndev = ndp->ndev.dev;
+ const struct net_device_ops *ops = ndev->netdev_ops;
+ struct ncsi_rsp_oem_pkt *rsp;
+ struct sockaddr saddr;
+ int ret = 0;
+
+ /* Get the response header */
+ rsp = (struct ncsi_rsp_oem_pkt *)skb_network_header(nr->rsp);
+
+ saddr.sa_family = ndev->type;
+ ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+ memcpy(saddr.sa_data, &rsp->data[INTEL_MAC_ADDR_OFFSET], ETH_ALEN);
+ /* Increase mac address by 1 for BMC's address */
+ eth_addr_inc((u8 *)saddr.sa_data);
+ if (!is_valid_ether_addr((const u8 *)saddr.sa_data))
+ return -ENXIO;
+
+ /* Set the flag for GMA command which should only be called once */
+ ndp->gma_flag = 1;
+
+ ret = ops->ndo_set_mac_address(ndev, &saddr);
+ if (ret < 0)
+ netdev_warn(ndev,
+ "NCSI: 'Writing mac address to device failed\n");
+
+ return ret;
+}
+
/* Response handler for Intel card */
static int ncsi_rsp_handler_oem_intel(struct ncsi_request *nr)
{
+ struct ncsi_rsp_oem_intel_pkt *intel;
+ struct ncsi_rsp_oem_pkt *rsp;
+
+ /* Get the response header */
+ rsp = (struct ncsi_rsp_oem_pkt *)skb_network_header(nr->rsp);
+ intel = (struct ncsi_rsp_oem_intel_pkt *)(rsp->data);
+
+ if (intel->cmd == NCSI_OEM_INTEL_CMD_GMA)
+ return ncsi_rsp_handler_oem_intel_gma(nr);
+
return 0;
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index d31dbccbe7bd..94e18fb9690d 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -21,7 +21,6 @@
#include <linux/stddef.h>
#include <linux/slab.h>
#include <linux/random.h>
-#include <linux/jhash.h>
#include <linux/siphash.h>
#include <linux/err.h>
#include <linux/percpu.h>
@@ -78,6 +77,8 @@ static __read_mostly bool nf_conntrack_locks_all;
#define GC_SCAN_INTERVAL (120u * HZ)
#define GC_SCAN_MAX_DURATION msecs_to_jiffies(10)
+#define MAX_CHAINLEN 64u
+
static struct conntrack_gc_work conntrack_gc_work;
void nf_conntrack_lock(spinlock_t *lock) __acquires(lock)
@@ -184,25 +185,31 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
unsigned int nf_conntrack_max __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_max);
seqcount_spinlock_t nf_conntrack_generation __read_mostly;
-static unsigned int nf_conntrack_hash_rnd __read_mostly;
+static siphash_key_t nf_conntrack_hash_rnd __read_mostly;
static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple,
const struct net *net)
{
- unsigned int n;
- u32 seed;
+ struct {
+ struct nf_conntrack_man src;
+ union nf_inet_addr dst_addr;
+ u32 net_mix;
+ u16 dport;
+ u16 proto;
+ } __aligned(SIPHASH_ALIGNMENT) combined;
get_random_once(&nf_conntrack_hash_rnd, sizeof(nf_conntrack_hash_rnd));
- /* The direction must be ignored, so we hash everything up to the
- * destination ports (which is a multiple of 4) and treat the last
- * three bytes manually.
- */
- seed = nf_conntrack_hash_rnd ^ net_hash_mix(net);
- n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32);
- return jhash2((u32 *)tuple, n, seed ^
- (((__force __u16)tuple->dst.u.all << 16) |
- tuple->dst.protonum));
+ memset(&combined, 0, sizeof(combined));
+
+ /* The direction must be ignored, so handle usable members manually. */
+ combined.src = tuple->src;
+ combined.dst_addr = tuple->dst.u3;
+ combined.net_mix = net_hash_mix(net);
+ combined.dport = (__force __u16)tuple->dst.u.all;
+ combined.proto = tuple->dst.protonum;
+
+ return (u32)siphash(&combined, sizeof(combined), &nf_conntrack_hash_rnd);
}
static u32 scale_hash(u32 hash)
@@ -835,7 +842,9 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
unsigned int hash, reply_hash;
struct nf_conntrack_tuple_hash *h;
struct hlist_nulls_node *n;
+ unsigned int chainlen = 0;
unsigned int sequence;
+ int err = -EEXIST;
zone = nf_ct_zone(ct);
@@ -849,15 +858,24 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
} while (nf_conntrack_double_lock(net, hash, reply_hash, sequence));
/* See if there's one in the list already, including reverse */
- hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[hash], hnnode)
+ hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[hash], hnnode) {
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
zone, net))
goto out;
- hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[reply_hash], hnnode)
+ if (chainlen++ > MAX_CHAINLEN)
+ goto chaintoolong;
+ }
+
+ chainlen = 0;
+
+ hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[reply_hash], hnnode) {
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
zone, net))
goto out;
+ if (chainlen++ > MAX_CHAINLEN)
+ goto chaintoolong;
+ }
smp_wmb();
/* The caller holds a reference to this object */
@@ -867,11 +885,13 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
NF_CT_STAT_INC(net, insert);
local_bh_enable();
return 0;
-
+chaintoolong:
+ NF_CT_STAT_INC(net, chaintoolong);
+ err = -ENOSPC;
out:
nf_conntrack_double_unlock(hash, reply_hash);
local_bh_enable();
- return -EEXIST;
+ return err;
}
EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert);
@@ -1084,6 +1104,7 @@ int
__nf_conntrack_confirm(struct sk_buff *skb)
{
const struct nf_conntrack_zone *zone;
+ unsigned int chainlen = 0, sequence;
unsigned int hash, reply_hash;
struct nf_conntrack_tuple_hash *h;
struct nf_conn *ct;
@@ -1091,7 +1112,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
struct hlist_nulls_node *n;
enum ip_conntrack_info ctinfo;
struct net *net;
- unsigned int sequence;
int ret = NF_DROP;
ct = nf_ct_get(skb, &ctinfo);
@@ -1151,15 +1171,28 @@ __nf_conntrack_confirm(struct sk_buff *skb)
/* See if there's one in the list already, including reverse:
NAT could have grabbed it without realizing, since we're
not in the hash. If there is, we lost race. */
- hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[hash], hnnode)
+ hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[hash], hnnode) {
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
zone, net))
goto out;
+ if (chainlen++ > MAX_CHAINLEN)
+ goto chaintoolong;
+ }
- hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[reply_hash], hnnode)
+ chainlen = 0;
+ hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[reply_hash], hnnode) {
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
zone, net))
goto out;
+ if (chainlen++ > MAX_CHAINLEN) {
+chaintoolong:
+ nf_ct_add_to_dying_list(ct);
+ NF_CT_STAT_INC(net, chaintoolong);
+ NF_CT_STAT_INC(net, insert_failed);
+ ret = NF_DROP;
+ goto dying;
+ }
+ }
/* Timer relative to confirmation time, not original
setting time, otherwise we'd get timer wrap in
@@ -2594,26 +2627,24 @@ int nf_conntrack_init_start(void)
spin_lock_init(&nf_conntrack_locks[i]);
if (!nf_conntrack_htable_size) {
- /* Idea from tcp.c: use 1/16384 of memory.
- * On i386: 32MB machine has 512 buckets.
- * >= 1GB machines have 16384 buckets.
- * >= 4GB machines have 65536 buckets.
- */
nf_conntrack_htable_size
= (((nr_pages << PAGE_SHIFT) / 16384)
/ sizeof(struct hlist_head));
- if (nr_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE)))
- nf_conntrack_htable_size = 65536;
+ if (BITS_PER_LONG >= 64 &&
+ nr_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE)))
+ nf_conntrack_htable_size = 262144;
else if (nr_pages > (1024 * 1024 * 1024 / PAGE_SIZE))
- nf_conntrack_htable_size = 16384;
- if (nf_conntrack_htable_size < 32)
- nf_conntrack_htable_size = 32;
-
- /* Use a max. factor of four by default to get the same max as
- * with the old struct list_heads. When a table size is given
- * we use the old value of 8 to avoid reducing the max.
- * entries. */
- max_factor = 4;
+ nf_conntrack_htable_size = 65536;
+
+ if (nf_conntrack_htable_size < 1024)
+ nf_conntrack_htable_size = 1024;
+ /* Use a max. factor of one by default to keep the average
+ * hash chain length at 2 entries. Each entry has to be added
+ * twice (once for original direction, once for reply).
+ * When a table size is given we use the old value of 8 to
+ * avoid implicit reduction of the max entries setting.
+ */
+ max_factor = 1;
}
nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, 1);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 1e851bc2e61a..f562eeef4234 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -17,7 +17,7 @@
#include <linux/err.h>
#include <linux/percpu.h>
#include <linux/kernel.h>
-#include <linux/jhash.h>
+#include <linux/siphash.h>
#include <linux/moduleparam.h>
#include <linux/export.h>
#include <net/net_namespace.h>
@@ -41,7 +41,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
unsigned int nf_ct_expect_max __read_mostly;
static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
-static unsigned int nf_ct_expect_hashrnd __read_mostly;
+static siphash_key_t nf_ct_expect_hashrnd __read_mostly;
/* nf_conntrack_expect helper functions */
void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
@@ -81,15 +81,26 @@ static void nf_ct_expectation_timed_out(struct timer_list *t)
static unsigned int nf_ct_expect_dst_hash(const struct net *n, const struct nf_conntrack_tuple *tuple)
{
- unsigned int hash, seed;
+ struct {
+ union nf_inet_addr dst_addr;
+ u32 net_mix;
+ u16 dport;
+ u8 l3num;
+ u8 protonum;
+ } __aligned(SIPHASH_ALIGNMENT) combined;
+ u32 hash;
get_random_once(&nf_ct_expect_hashrnd, sizeof(nf_ct_expect_hashrnd));
- seed = nf_ct_expect_hashrnd ^ net_hash_mix(n);
+ memset(&combined, 0, sizeof(combined));
- hash = jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all),
- (((tuple->dst.protonum ^ tuple->src.l3num) << 16) |
- (__force __u16)tuple->dst.u.all) ^ seed);
+ combined.dst_addr = tuple->dst.u3;
+ combined.net_mix = net_hash_mix(n);
+ combined.dport = (__force __u16)tuple->dst.u.all;
+ combined.l3num = tuple->src.l3num;
+ combined.protonum = tuple->dst.protonum;
+
+ hash = siphash(&combined, sizeof(combined), &nf_ct_expect_hashrnd);
return reciprocal_scale(hash, nf_ct_expect_hsize);
}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 5f9fc6b94855..f1e5443fe7c7 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2528,7 +2528,9 @@ ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
nla_put_be32(skb, CTA_STATS_SEARCH_RESTART,
htonl(st->search_restart)) ||
nla_put_be32(skb, CTA_STATS_CLASH_RESOLVE,
- htonl(st->clash_resolve)))
+ htonl(st->clash_resolve)) ||
+ nla_put_be32(skb, CTA_STATS_CHAIN_TOOLONG,
+ htonl(st->chaintoolong)))
goto nla_put_failure;
nlmsg_end(skb, nlh);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 7e0d956da51d..80f675d884b2 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -432,7 +432,7 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v)
unsigned int nr_conntracks;
if (v == SEQ_START_TOKEN) {
- seq_puts(seq, "entries clashres found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete search_restart\n");
+ seq_puts(seq, "entries clashres found new invalid ignore delete chainlength insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete search_restart\n");
return 0;
}
@@ -447,7 +447,7 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v)
st->invalid,
0,
0,
- 0,
+ st->chaintoolong,
st->insert,
st->insert_failed,
st->drop,
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 7de595ead06a..7008961f5cb0 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -13,7 +13,7 @@
#include <linux/skbuff.h>
#include <linux/gfp.h>
#include <net/xfrm.h>
-#include <linux/jhash.h>
+#include <linux/siphash.h>
#include <linux/rtnetlink.h>
#include <net/netfilter/nf_conntrack.h>
@@ -34,7 +34,7 @@ static unsigned int nat_net_id __read_mostly;
static struct hlist_head *nf_nat_bysource __read_mostly;
static unsigned int nf_nat_htable_size __read_mostly;
-static unsigned int nf_nat_hash_rnd __read_mostly;
+static siphash_key_t nf_nat_hash_rnd __read_mostly;
struct nf_nat_lookup_hook_priv {
struct nf_hook_entries __rcu *entries;
@@ -153,12 +153,22 @@ static unsigned int
hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple)
{
unsigned int hash;
+ struct {
+ struct nf_conntrack_man src;
+ u32 net_mix;
+ u32 protonum;
+ } __aligned(SIPHASH_ALIGNMENT) combined;
get_random_once(&nf_nat_hash_rnd, sizeof(nf_nat_hash_rnd));
+ memset(&combined, 0, sizeof(combined));
+
/* Original src, to ensure we map it consistently if poss. */
- hash = jhash2((u32 *)&tuple->src, sizeof(tuple->src) / sizeof(u32),
- tuple->dst.protonum ^ nf_nat_hash_rnd ^ net_hash_mix(n));
+ combined.src = tuple->src;
+ combined.net_mix = net_hash_mix(n);
+ combined.protonum = tuple->dst.protonum;
+
+ hash = siphash(&combined, sizeof(combined), &nf_nat_hash_rnd);
return reciprocal_scale(hash, nf_nat_htable_size);
}
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 337e22d8b40b..99b1de14ff7e 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -41,6 +41,7 @@ struct nft_ct_helper_obj {
#ifdef CONFIG_NF_CONNTRACK_ZONES
static DEFINE_PER_CPU(struct nf_conn *, nft_ct_pcpu_template);
static unsigned int nft_ct_pcpu_template_refcnt __read_mostly;
+static DEFINE_MUTEX(nft_ct_pcpu_mutex);
#endif
static u64 nft_ct_get_eval_counter(const struct nf_conn_counter *c,
@@ -525,8 +526,10 @@ static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
#endif
#ifdef CONFIG_NF_CONNTRACK_ZONES
case NFT_CT_ZONE:
+ mutex_lock(&nft_ct_pcpu_mutex);
if (--nft_ct_pcpu_template_refcnt == 0)
nft_ct_tmpl_put_pcpu();
+ mutex_unlock(&nft_ct_pcpu_mutex);
break;
#endif
default:
@@ -564,9 +567,13 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
#endif
#ifdef CONFIG_NF_CONNTRACK_ZONES
case NFT_CT_ZONE:
- if (!nft_ct_tmpl_alloc_pcpu())
+ mutex_lock(&nft_ct_pcpu_mutex);
+ if (!nft_ct_tmpl_alloc_pcpu()) {
+ mutex_unlock(&nft_ct_pcpu_mutex);
return -ENOMEM;
+ }
nft_ct_pcpu_template_refcnt++;
+ mutex_unlock(&nft_ct_pcpu_mutex);
len = sizeof(u16);
break;
#endif
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 543365f58e97..2a2bc64f75cf 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -46,6 +46,8 @@
* Copyright (C) 2011, <lokec@ccs.neu.edu>
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/ethtool.h>
#include <linux/types.h>
#include <linux/mm.h>
diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index 525e3ea063b1..ec2322529727 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -493,7 +493,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
goto err;
}
- if (!size || size & 3 || len != size + hdrlen)
+ if (!size || len != ALIGN(size, 4) + hdrlen)
goto err;
if (cb->dst_port != QRTR_PORT_CTRL && cb->type != QRTR_TYPE_DATA &&
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index c4afdd026f51..bb0cd6d3d2c2 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -369,6 +369,7 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
{
struct fq_codel_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_FQ_CODEL_MAX + 1];
+ u32 quantum = 0;
int err;
if (!opt)
@@ -386,6 +387,13 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
q->flows_cnt > 65536)
return -EINVAL;
}
+ if (tb[TCA_FQ_CODEL_QUANTUM]) {
+ quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
+ if (quantum > FQ_CODEL_QUANTUM_MAX) {
+ NL_SET_ERR_MSG(extack, "Invalid quantum");
+ return -EINVAL;
+ }
+ }
sch_tree_lock(sch);
if (tb[TCA_FQ_CODEL_TARGET]) {
@@ -412,8 +420,8 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
if (tb[TCA_FQ_CODEL_ECN])
q->cparams.ecn = !!nla_get_u32(tb[TCA_FQ_CODEL_ECN]);
- if (tb[TCA_FQ_CODEL_QUANTUM])
- q->quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
+ if (quantum)
+ q->quantum = quantum;
if (tb[TCA_FQ_CODEL_DROP_BATCH_SIZE])
q->drop_batch_size = max(1U, nla_get_u32(tb[TCA_FQ_CODEL_DROP_BATCH_SIZE]));
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
index d1c003a25b0f..61c276bddaf2 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
@@ -160,7 +160,7 @@ static struct rpc_clnt *get_gssp_clnt(struct sunrpc_net *sn)
mutex_lock(&sn->gssp_lock);
clnt = sn->gssp_clnt;
if (clnt)
- atomic_inc(&clnt->cl_count);
+ refcount_inc(&clnt->cl_count);
mutex_unlock(&sn->gssp_lock);
return clnt;
}
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 3d685fe328fa..9de41e7f2d07 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -707,11 +707,11 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
/*
* Verify the checksum on the header and return SVC_OK on success.
* Otherwise, return SVC_DROP (in the case of a bad sequence number)
- * or return SVC_DENIED and indicate error in authp.
+ * or return SVC_DENIED and indicate error in rqstp->rq_auth_stat.
*/
static int
gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
- __be32 *rpcstart, struct rpc_gss_wire_cred *gc, __be32 *authp)
+ __be32 *rpcstart, struct rpc_gss_wire_cred *gc)
{
struct gss_ctx *ctx_id = rsci->mechctx;
struct xdr_buf rpchdr;
@@ -725,7 +725,7 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
iov.iov_len = (u8 *)argv->iov_base - (u8 *)rpcstart;
xdr_buf_from_iov(&iov, &rpchdr);
- *authp = rpc_autherr_badverf;
+ rqstp->rq_auth_stat = rpc_autherr_badverf;
if (argv->iov_len < 4)
return SVC_DENIED;
flavor = svc_getnl(argv);
@@ -737,13 +737,13 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
if (rqstp->rq_deferred) /* skip verification of revisited request */
return SVC_OK;
if (gss_verify_mic(ctx_id, &rpchdr, &checksum) != GSS_S_COMPLETE) {
- *authp = rpcsec_gsserr_credproblem;
+ rqstp->rq_auth_stat = rpcsec_gsserr_credproblem;
return SVC_DENIED;
}
if (gc->gc_seq > MAXSEQ) {
trace_rpcgss_svc_seqno_large(rqstp, gc->gc_seq);
- *authp = rpcsec_gsserr_ctxproblem;
+ rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem;
return SVC_DENIED;
}
if (!gss_check_seq_num(rqstp, rsci, gc->gc_seq))
@@ -1038,6 +1038,8 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
struct rpc_gss_wire_cred *gc = &svcdata->clcred;
int stat;
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
+
/*
* A gss export can be specified either by:
* export *(sec=krb5,rw)
@@ -1053,6 +1055,8 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
stat = svcauth_unix_set_client(rqstp);
if (stat == SVC_DROP || stat == SVC_CLOSE)
return stat;
+
+ rqstp->rq_auth_stat = rpc_auth_ok;
return SVC_OK;
}
@@ -1142,7 +1146,7 @@ static void gss_free_in_token_pages(struct gssp_in_token *in_token)
}
static int gss_read_proxy_verf(struct svc_rqst *rqstp,
- struct rpc_gss_wire_cred *gc, __be32 *authp,
+ struct rpc_gss_wire_cred *gc,
struct xdr_netobj *in_handle,
struct gssp_in_token *in_token)
{
@@ -1151,7 +1155,7 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp,
int pages, i, res, pgto, pgfrom;
size_t inlen, to_offs, from_offs;
- res = gss_read_common_verf(gc, argv, authp, in_handle);
+ res = gss_read_common_verf(gc, argv, &rqstp->rq_auth_stat, in_handle);
if (res)
return res;
@@ -1227,7 +1231,7 @@ gss_write_resv(struct kvec *resv, size_t size_limit,
* Otherwise, drop the request pending an answer to the upcall.
*/
static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
- struct rpc_gss_wire_cred *gc, __be32 *authp)
+ struct rpc_gss_wire_cred *gc)
{
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
@@ -1236,7 +1240,7 @@ static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
memset(&rsikey, 0, sizeof(rsikey));
- ret = gss_read_verf(gc, argv, authp,
+ ret = gss_read_verf(gc, argv, &rqstp->rq_auth_stat,
&rsikey.in_handle, &rsikey.in_token);
if (ret)
return ret;
@@ -1339,7 +1343,7 @@ out:
}
static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
- struct rpc_gss_wire_cred *gc, __be32 *authp)
+ struct rpc_gss_wire_cred *gc)
{
struct kvec *resv = &rqstp->rq_res.head[0];
struct xdr_netobj cli_handle;
@@ -1351,8 +1355,7 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
memset(&ud, 0, sizeof(ud));
- ret = gss_read_proxy_verf(rqstp, gc, authp,
- &ud.in_handle, &ud.in_token);
+ ret = gss_read_proxy_verf(rqstp, gc, &ud.in_handle, &ud.in_token);
if (ret)
return ret;
@@ -1525,7 +1528,7 @@ static void destroy_use_gss_proxy_proc_entry(struct net *net) {}
* response here and return SVC_COMPLETE.
*/
static int
-svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+svcauth_gss_accept(struct svc_rqst *rqstp)
{
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
@@ -1538,7 +1541,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
int ret;
struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
- *authp = rpc_autherr_badcred;
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
if (!svcdata)
svcdata = kmalloc(sizeof(*svcdata), GFP_KERNEL);
if (!svcdata)
@@ -1575,22 +1578,22 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0))
goto auth_err;
- *authp = rpc_autherr_badverf;
+ rqstp->rq_auth_stat = rpc_autherr_badverf;
switch (gc->gc_proc) {
case RPC_GSS_PROC_INIT:
case RPC_GSS_PROC_CONTINUE_INIT:
if (use_gss_proxy(SVC_NET(rqstp)))
- return svcauth_gss_proxy_init(rqstp, gc, authp);
+ return svcauth_gss_proxy_init(rqstp, gc);
else
- return svcauth_gss_legacy_init(rqstp, gc, authp);
+ return svcauth_gss_legacy_init(rqstp, gc);
case RPC_GSS_PROC_DATA:
case RPC_GSS_PROC_DESTROY:
/* Look up the context, and check the verifier: */
- *authp = rpcsec_gsserr_credproblem;
+ rqstp->rq_auth_stat = rpcsec_gsserr_credproblem;
rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx);
if (!rsci)
goto auth_err;
- switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) {
+ switch (gss_verify_header(rqstp, rsci, rpcstart, gc)) {
case SVC_OK:
break;
case SVC_DENIED:
@@ -1600,7 +1603,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
}
break;
default:
- *authp = rpc_autherr_rejectedcred;
+ rqstp->rq_auth_stat = rpc_autherr_rejectedcred;
goto auth_err;
}
@@ -1616,13 +1619,13 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
svc_putnl(resv, RPC_SUCCESS);
goto complete;
case RPC_GSS_PROC_DATA:
- *authp = rpcsec_gsserr_ctxproblem;
+ rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem;
svcdata->verf_start = resv->iov_base + resv->iov_len;
if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
goto auth_err;
rqstp->rq_cred = rsci->cred;
get_group_info(rsci->cred.cr_group_info);
- *authp = rpc_autherr_badcred;
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
switch (gc->gc_svc) {
case RPC_GSS_SVC_NONE:
break;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 8b4de70e8ead..f056ff931444 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -167,7 +167,7 @@ static int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
case RPC_PIPEFS_MOUNT:
if (clnt->cl_pipedir_objects.pdh_dentry != NULL)
return 1;
- if (atomic_read(&clnt->cl_count) == 0)
+ if (refcount_read(&clnt->cl_count) == 0)
return 1;
break;
case RPC_PIPEFS_UMOUNT:
@@ -419,7 +419,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
clnt->cl_rtt = &clnt->cl_rtt_default;
rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval);
- atomic_set(&clnt->cl_count, 1);
+ refcount_set(&clnt->cl_count, 1);
if (nodename == NULL)
nodename = utsname()->nodename;
@@ -431,7 +431,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
if (err)
goto out_no_path;
if (parent)
- atomic_inc(&parent->cl_count);
+ refcount_inc(&parent->cl_count);
trace_rpc_clnt_new(clnt, xprt, program->name, args->servername);
return clnt;
@@ -918,18 +918,16 @@ rpc_free_client(struct rpc_clnt *clnt)
static struct rpc_clnt *
rpc_free_auth(struct rpc_clnt *clnt)
{
- if (clnt->cl_auth == NULL)
- return rpc_free_client(clnt);
-
/*
* Note: RPCSEC_GSS may need to send NULL RPC calls in order to
* release remaining GSS contexts. This mechanism ensures
* that it can do so safely.
*/
- atomic_inc(&clnt->cl_count);
- rpcauth_release(clnt->cl_auth);
- clnt->cl_auth = NULL;
- if (atomic_dec_and_test(&clnt->cl_count))
+ if (clnt->cl_auth != NULL) {
+ rpcauth_release(clnt->cl_auth);
+ clnt->cl_auth = NULL;
+ }
+ if (refcount_dec_and_test(&clnt->cl_count))
return rpc_free_client(clnt);
return NULL;
}
@@ -943,7 +941,7 @@ rpc_release_client(struct rpc_clnt *clnt)
do {
if (list_empty(&clnt->cl_tasks))
wake_up(&destroy_wait);
- if (!atomic_dec_and_test(&clnt->cl_count))
+ if (refcount_dec_not_one(&clnt->cl_count))
break;
clnt = rpc_free_auth(clnt);
} while (clnt != NULL);
@@ -1082,7 +1080,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
if (clnt != NULL) {
rpc_task_set_transport(task, clnt);
task->tk_client = clnt;
- atomic_inc(&clnt->cl_count);
+ refcount_inc(&clnt->cl_count);
if (clnt->cl_softrtry)
task->tk_flags |= RPC_TASK_SOFT;
if (clnt->cl_softerr)
@@ -2694,17 +2692,18 @@ static const struct rpc_procinfo rpcproc_null = {
.p_decode = rpcproc_decode_null,
};
-static int rpc_ping(struct rpc_clnt *clnt)
+static void
+rpc_null_call_prepare(struct rpc_task *task, void *data)
{
- struct rpc_message msg = {
- .rpc_proc = &rpcproc_null,
- };
- int err;
- err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN |
- RPC_TASK_NULLCREDS);
- return err;
+ task->tk_flags &= ~RPC_TASK_NO_RETRANS_TIMEOUT;
+ rpc_call_start(task);
}
+static const struct rpc_call_ops rpc_null_ops = {
+ .rpc_call_prepare = rpc_null_call_prepare,
+ .rpc_call_done = rpc_default_callback,
+};
+
static
struct rpc_task *rpc_call_null_helper(struct rpc_clnt *clnt,
struct rpc_xprt *xprt, struct rpc_cred *cred, int flags,
@@ -2718,7 +2717,7 @@ struct rpc_task *rpc_call_null_helper(struct rpc_clnt *clnt,
.rpc_xprt = xprt,
.rpc_message = &msg,
.rpc_op_cred = cred,
- .callback_ops = (ops != NULL) ? ops : &rpc_default_ops,
+ .callback_ops = ops ?: &rpc_null_ops,
.callback_data = data,
.flags = flags | RPC_TASK_SOFT | RPC_TASK_SOFTCONN |
RPC_TASK_NULLCREDS,
@@ -2733,6 +2732,19 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int
}
EXPORT_SYMBOL_GPL(rpc_call_null);
+static int rpc_ping(struct rpc_clnt *clnt)
+{
+ struct rpc_task *task;
+ int status;
+
+ task = rpc_call_null_helper(clnt, NULL, NULL, 0, NULL, NULL);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+ status = task->tk_status;
+ rpc_put_task(task);
+ return status;
+}
+
struct rpc_cb_add_xprt_calldata {
struct rpc_xprt_switch *xps;
struct rpc_xprt *xprt;
@@ -2756,6 +2768,7 @@ static void rpc_cb_add_xprt_release(void *calldata)
}
static const struct rpc_call_ops rpc_cb_add_xprt_call_ops = {
+ .rpc_call_prepare = rpc_null_call_prepare,
.rpc_call_done = rpc_cb_add_xprt_done,
.rpc_release = rpc_cb_add_xprt_release,
};
@@ -2774,6 +2787,15 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
struct rpc_cb_add_xprt_calldata *data;
struct rpc_task *task;
+ if (xps->xps_nunique_destaddr_xprts + 1 > clnt->cl_max_connect) {
+ rcu_read_lock();
+ pr_warn("SUNRPC: reached max allowed number (%d) did not add "
+ "transport to server: %s\n", clnt->cl_max_connect,
+ rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+
data = kmalloc(sizeof(*data), GFP_NOFS);
if (!data)
return -ENOMEM;
@@ -2786,7 +2808,7 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
task = rpc_call_null_helper(clnt, xprt, NULL, RPC_TASK_ASYNC,
&rpc_cb_add_xprt_call_ops, data);
-
+ data->xps->xps_nunique_destaddr_xprts++;
rpc_put_task(task);
success:
return 1;
diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
index 827bf3a28178..7dc9cc929bfd 100644
--- a/net/sunrpc/debugfs.c
+++ b/net/sunrpc/debugfs.c
@@ -90,7 +90,7 @@ static int tasks_open(struct inode *inode, struct file *filp)
struct seq_file *seq = filp->private_data;
struct rpc_clnt *clnt = seq->private = inode->i_private;
- if (!atomic_inc_not_zero(&clnt->cl_count)) {
+ if (!refcount_inc_not_zero(&clnt->cl_count)) {
seq_release(inode, filp);
ret = -EINVAL;
}
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 09c000d490a1..ee5336d73fdd 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -423,7 +423,7 @@ rpc_info_open(struct inode *inode, struct file *file)
spin_lock(&file->f_path.dentry->d_lock);
if (!d_unhashed(file->f_path.dentry))
clnt = RPC_I(inode)->private;
- if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) {
+ if (clnt != NULL && refcount_inc_not_zero(&clnt->cl_count)) {
spin_unlock(&file->f_path.dentry->d_lock);
m->private = clnt;
} else {
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index bfcbaf7b3822..a3bbe5ce4570 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1186,22 +1186,6 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {}
#endif
-__be32
-svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err)
-{
- set_bit(RQ_AUTHERR, &rqstp->rq_flags);
- return auth_err;
-}
-EXPORT_SYMBOL_GPL(svc_return_autherr);
-
-static __be32
-svc_get_autherr(struct svc_rqst *rqstp, __be32 *statp)
-{
- if (test_and_clear_bit(RQ_AUTHERR, &rqstp->rq_flags))
- return *statp;
- return rpc_auth_ok;
-}
-
static int
svc_generic_dispatch(struct svc_rqst *rqstp, __be32 *statp)
{
@@ -1225,7 +1209,7 @@ svc_generic_dispatch(struct svc_rqst *rqstp, __be32 *statp)
test_bit(RQ_DROPME, &rqstp->rq_flags))
return 0;
- if (test_bit(RQ_AUTHERR, &rqstp->rq_flags))
+ if (rqstp->rq_auth_stat != rpc_auth_ok)
return 1;
if (*statp != rpc_success)
@@ -1306,7 +1290,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
struct svc_process_info process;
__be32 *statp;
u32 prog, vers;
- __be32 auth_stat, rpc_stat;
+ __be32 rpc_stat;
int auth_res;
__be32 *reply_statp;
@@ -1349,14 +1333,12 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
* We do this before anything else in order to get a decent
* auth verifier.
*/
- auth_res = svc_authenticate(rqstp, &auth_stat);
+ auth_res = svc_authenticate(rqstp);
/* Also give the program a chance to reject this call: */
- if (auth_res == SVC_OK && progp) {
- auth_stat = rpc_autherr_badcred;
+ if (auth_res == SVC_OK && progp)
auth_res = progp->pg_authenticate(rqstp);
- }
if (auth_res != SVC_OK)
- trace_svc_authenticate(rqstp, auth_res, auth_stat);
+ trace_svc_authenticate(rqstp, auth_res);
switch (auth_res) {
case SVC_OK:
break;
@@ -1415,15 +1397,15 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
goto release_dropit;
if (*statp == rpc_garbage_args)
goto err_garbage;
- auth_stat = svc_get_autherr(rqstp, statp);
- if (auth_stat != rpc_auth_ok)
- goto err_release_bad_auth;
} else {
dprintk("svc: calling dispatcher\n");
if (!process.dispatch(rqstp, statp))
goto release_dropit; /* Release reply info */
}
+ if (rqstp->rq_auth_stat != rpc_auth_ok)
+ goto err_release_bad_auth;
+
/* Check RPC status result */
if (*statp != rpc_success)
resv->iov_len = ((void*)statp) - resv->iov_base + 4;
@@ -1473,13 +1455,14 @@ err_release_bad_auth:
if (procp->pc_release)
procp->pc_release(rqstp);
err_bad_auth:
- dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
+ dprintk("svc: authentication failed (%d)\n",
+ be32_to_cpu(rqstp->rq_auth_stat));
serv->sv_stats->rpcbadauth++;
/* Restore write pointer to location of accept status: */
xdr_ressize_check(rqstp, reply_statp);
svc_putnl(resv, 1); /* REJECT */
svc_putnl(resv, 1); /* AUTH_ERROR */
- svc_putnl(resv, ntohl(auth_stat)); /* status */
+ svc_putu32(resv, rqstp->rq_auth_stat); /* status */
goto sendit;
err_bad_prog:
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index 998b196b6176..5a8b8e03fdd4 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -59,12 +59,12 @@ svc_put_auth_ops(struct auth_ops *aops)
}
int
-svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
+svc_authenticate(struct svc_rqst *rqstp)
{
rpc_authflavor_t flavor;
struct auth_ops *aops;
- *authp = rpc_auth_ok;
+ rqstp->rq_auth_stat = rpc_auth_ok;
flavor = svc_getnl(&rqstp->rq_arg.head[0]);
@@ -72,7 +72,7 @@ svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
aops = svc_get_auth_ops(flavor);
if (aops == NULL) {
- *authp = rpc_autherr_badcred;
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
return SVC_DENIED;
}
@@ -80,7 +80,7 @@ svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
init_svc_cred(&rqstp->rq_cred);
rqstp->rq_authop = aops;
- return aops->accept(rqstp, authp);
+ return aops->accept(rqstp);
}
EXPORT_SYMBOL_GPL(svc_authenticate);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 35b7966ac3b3..d7ed7d49115a 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -681,8 +681,9 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
rqstp->rq_client = NULL;
if (rqstp->rq_proc == 0)
- return SVC_OK;
+ goto out;
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
ipm = ip_map_cached_get(xprt);
if (ipm == NULL)
ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
@@ -719,13 +720,16 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
put_group_info(cred->cr_group_info);
cred->cr_group_info = gi;
}
+
+out:
+ rqstp->rq_auth_stat = rpc_auth_ok;
return SVC_OK;
}
EXPORT_SYMBOL_GPL(svcauth_unix_set_client);
static int
-svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
+svcauth_null_accept(struct svc_rqst *rqstp)
{
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
@@ -736,12 +740,12 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
if (svc_getu32(argv) != 0) {
dprintk("svc: bad null cred\n");
- *authp = rpc_autherr_badcred;
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
return SVC_DENIED;
}
if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
dprintk("svc: bad null verf\n");
- *authp = rpc_autherr_badverf;
+ rqstp->rq_auth_stat = rpc_autherr_badverf;
return SVC_DENIED;
}
@@ -785,7 +789,7 @@ struct auth_ops svcauth_null = {
static int
-svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
+svcauth_unix_accept(struct svc_rqst *rqstp)
{
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
@@ -827,7 +831,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
}
groups_sort(cred->cr_group_info);
if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
- *authp = rpc_autherr_badverf;
+ rqstp->rq_auth_stat = rpc_autherr_badverf;
return SVC_DENIED;
}
@@ -839,7 +843,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
return SVC_OK;
badcred:
- *authp = rpc_autherr_badcred;
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
return SVC_DENIED;
}
diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c
index 64da3bfd28e6..9a6f17e18f73 100644
--- a/net/sunrpc/sysfs.c
+++ b/net/sunrpc/sysfs.c
@@ -100,6 +100,28 @@ static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj,
return ret + 1;
}
+static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
+ struct sockaddr_storage saddr;
+ struct sock_xprt *sock;
+ ssize_t ret = -1;
+
+ if (!xprt)
+ return 0;
+
+ sock = container_of(xprt, struct sock_xprt, xprt);
+ if (kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0)
+ goto out;
+
+ ret = sprintf(buf, "%pISc\n", &saddr);
+out:
+ xprt_put(xprt);
+ return ret + 1;
+}
+
static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
@@ -114,14 +136,16 @@ static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
"max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n"
"binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n"
"backlog_q_len=%u\nmain_xprt=%d\nsrc_port=%u\n"
- "tasks_queuelen=%ld\n",
+ "tasks_queuelen=%ld\ndst_port=%s\n",
xprt->last_used, xprt->cong, xprt->cwnd, xprt->max_reqs,
xprt->min_reqs, xprt->num_reqs, xprt->binding.qlen,
xprt->sending.qlen, xprt->pending.qlen,
xprt->backlog.qlen, xprt->main,
(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP) ?
get_srcport(xprt) : 0,
- atomic_long_read(&xprt->queuelen));
+ atomic_long_read(&xprt->queuelen),
+ (xprt->xprt_class->ident == XPRT_TRANSPORT_TCP) ?
+ xprt->address_strings[RPC_DISPLAY_PORT] : "0");
xprt_put(xprt);
return ret + 1;
}
@@ -183,8 +207,10 @@ static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj,
if (!xprt_switch)
return 0;
- ret = sprintf(buf, "num_xprts=%u\nnum_active=%u\nqueue_len=%ld\n",
+ ret = sprintf(buf, "num_xprts=%u\nnum_active=%u\n"
+ "num_unique_destaddr=%u\nqueue_len=%ld\n",
xprt_switch->xps_nxprts, xprt_switch->xps_nactive,
+ xprt_switch->xps_nunique_destaddr_xprts,
atomic_long_read(&xprt_switch->xps_queuelen));
xprt_switch_put(xprt_switch);
return ret + 1;
@@ -376,6 +402,9 @@ static const void *rpc_sysfs_xprt_namespace(struct kobject *kobj)
static struct kobj_attribute rpc_sysfs_xprt_dstaddr = __ATTR(dstaddr,
0644, rpc_sysfs_xprt_dstaddr_show, rpc_sysfs_xprt_dstaddr_store);
+static struct kobj_attribute rpc_sysfs_xprt_srcaddr = __ATTR(srcaddr,
+ 0644, rpc_sysfs_xprt_srcaddr_show, NULL);
+
static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info,
0444, rpc_sysfs_xprt_info_show, NULL);
@@ -384,6 +413,7 @@ static struct kobj_attribute rpc_sysfs_xprt_change_state = __ATTR(xprt_state,
static struct attribute *rpc_sysfs_xprt_attrs[] = {
&rpc_sysfs_xprt_dstaddr.attr,
+ &rpc_sysfs_xprt_srcaddr.attr,
&rpc_sysfs_xprt_info.attr,
&rpc_sysfs_xprt_change_state.attr,
NULL,
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 05abe344a269..cfd681700d1a 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -762,6 +762,20 @@ void xprt_disconnect_done(struct rpc_xprt *xprt)
EXPORT_SYMBOL_GPL(xprt_disconnect_done);
/**
+ * xprt_schedule_autoclose_locked - Try to schedule an autoclose RPC call
+ * @xprt: transport to disconnect
+ */
+static void xprt_schedule_autoclose_locked(struct rpc_xprt *xprt)
+{
+ set_bit(XPRT_CLOSE_WAIT, &xprt->state);
+ if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+ queue_work(xprtiod_workqueue, &xprt->task_cleanup);
+ else if (xprt->snd_task && !test_bit(XPRT_SND_IS_COOKIE, &xprt->state))
+ rpc_wake_up_queued_task_set_status(&xprt->pending,
+ xprt->snd_task, -ENOTCONN);
+}
+
+/**
* xprt_force_disconnect - force a transport to disconnect
* @xprt: transport to disconnect
*
@@ -772,13 +786,7 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
/* Don't race with the test_bit() in xprt_clear_locked() */
spin_lock(&xprt->transport_lock);
- set_bit(XPRT_CLOSE_WAIT, &xprt->state);
- /* Try to schedule an autoclose RPC call */
- if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
- queue_work(xprtiod_workqueue, &xprt->task_cleanup);
- else if (xprt->snd_task)
- rpc_wake_up_queued_task_set_status(&xprt->pending,
- xprt->snd_task, -ENOTCONN);
+ xprt_schedule_autoclose_locked(xprt);
spin_unlock(&xprt->transport_lock);
}
EXPORT_SYMBOL_GPL(xprt_force_disconnect);
@@ -818,11 +826,7 @@ void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie)
goto out;
if (test_bit(XPRT_CLOSING, &xprt->state))
goto out;
- set_bit(XPRT_CLOSE_WAIT, &xprt->state);
- /* Try to schedule an autoclose RPC call */
- if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
- queue_work(xprtiod_workqueue, &xprt->task_cleanup);
- xprt_wake_pending_tasks(xprt, -EAGAIN);
+ xprt_schedule_autoclose_locked(xprt);
out:
spin_unlock(&xprt->transport_lock);
}
@@ -880,12 +884,14 @@ bool xprt_lock_connect(struct rpc_xprt *xprt,
goto out;
if (xprt->snd_task != task)
goto out;
+ set_bit(XPRT_SND_IS_COOKIE, &xprt->state);
xprt->snd_task = cookie;
ret = true;
out:
spin_unlock(&xprt->transport_lock);
return ret;
}
+EXPORT_SYMBOL_GPL(xprt_lock_connect);
void xprt_unlock_connect(struct rpc_xprt *xprt, void *cookie)
{
@@ -895,12 +901,14 @@ void xprt_unlock_connect(struct rpc_xprt *xprt, void *cookie)
if (!test_bit(XPRT_LOCKED, &xprt->state))
goto out;
xprt->snd_task =NULL;
+ clear_bit(XPRT_SND_IS_COOKIE, &xprt->state);
xprt->ops->release_xprt(xprt, NULL);
xprt_schedule_autodisconnect(xprt);
out:
spin_unlock(&xprt->transport_lock);
wake_up_bit(&xprt->state, XPRT_LOCKED);
}
+EXPORT_SYMBOL_GPL(xprt_unlock_connect);
/**
* xprt_connect - schedule a transport connect operation
diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c
index c60820e45082..1693f81aae37 100644
--- a/net/sunrpc/xprtmultipath.c
+++ b/net/sunrpc/xprtmultipath.c
@@ -139,6 +139,7 @@ struct rpc_xprt_switch *xprt_switch_alloc(struct rpc_xprt *xprt,
xps->xps_iter_ops = &rpc_xprt_iter_singular;
rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags);
xprt_switch_add_xprt_locked(xps, xprt);
+ xps->xps_nunique_destaddr_xprts = 1;
rpc_sysfs_xprt_setup(xps, xprt, gfp_flags);
}
diff --git a/net/sunrpc/xprtrdma/backchannel.c b/net/sunrpc/xprtrdma/backchannel.c
index 1151efd09b27..17f174d6ea3b 100644
--- a/net/sunrpc/xprtrdma/backchannel.c
+++ b/net/sunrpc/xprtrdma/backchannel.c
@@ -115,7 +115,7 @@ int xprt_rdma_bc_send_reply(struct rpc_rqst *rqst)
if (rc < 0)
goto failed_marshal;
- if (rpcrdma_post_sends(r_xprt, req))
+ if (frwr_send(r_xprt, req))
goto drop_connection;
return 0;
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c
index 229fcc9a9064..f700b34a5bfd 100644
--- a/net/sunrpc/xprtrdma/frwr_ops.c
+++ b/net/sunrpc/xprtrdma/frwr_ops.c
@@ -394,6 +394,7 @@ int frwr_send(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
struct rpcrdma_ep *ep = r_xprt->rx_ep;
struct rpcrdma_mr *mr;
unsigned int num_wrs;
+ int ret;
num_wrs = 1;
post_wr = send_wr;
@@ -420,7 +421,10 @@ int frwr_send(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
}
trace_xprtrdma_post_send(req);
- return ib_post_send(ep->re_id->qp, post_wr, NULL);
+ ret = ib_post_send(ep->re_id->qp, post_wr, NULL);
+ if (ret)
+ trace_xprtrdma_post_send_err(r_xprt, req, ret);
+ return ret;
}
/**
@@ -557,6 +561,10 @@ void frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
/* On error, the MRs get destroyed once the QP has drained. */
trace_xprtrdma_post_linv_err(req, rc);
+
+ /* Force a connection loss to ensure complete recovery.
+ */
+ rpcrdma_force_disconnect(ep);
}
/**
@@ -653,4 +661,8 @@ void frwr_unmap_async(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
* retransmission.
*/
rpcrdma_unpin_rqst(req->rl_reply);
+
+ /* Force a connection loss to ensure complete recovery.
+ */
+ rpcrdma_force_disconnect(ep);
}
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index 9c2ffc67c0fd..16e5696314a4 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -250,12 +250,9 @@ xprt_rdma_connect_worker(struct work_struct *work)
xprt->stat.connect_start;
xprt_set_connected(xprt);
rc = -EAGAIN;
- } else {
- /* Force a call to xprt_rdma_close to clean up */
- spin_lock(&xprt->transport_lock);
- set_bit(XPRT_CLOSE_WAIT, &xprt->state);
- spin_unlock(&xprt->transport_lock);
- }
+ } else
+ rpcrdma_xprt_disconnect(r_xprt);
+ xprt_unlock_connect(xprt, r_xprt);
xprt_wake_pending_tasks(xprt, rc);
}
@@ -489,6 +486,8 @@ xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task)
struct rpcrdma_ep *ep = r_xprt->rx_ep;
unsigned long delay;
+ WARN_ON_ONCE(!xprt_lock_connect(xprt, task, r_xprt));
+
delay = 0;
if (ep && ep->re_connect_status != 0) {
delay = xprt_reconnect_delay(xprt);
@@ -661,7 +660,7 @@ xprt_rdma_send_request(struct rpc_rqst *rqst)
goto drop_connection;
rqst->rq_xtime = ktime_get();
- if (rpcrdma_post_sends(r_xprt, req))
+ if (frwr_send(r_xprt, req))
goto drop_connection;
rqst->rq_xmit_bytes_sent += rqst->rq_snd_buf.len;
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 649c23518ec0..aaec3c9be8db 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -124,7 +124,7 @@ static void rpcrdma_xprt_drain(struct rpcrdma_xprt *r_xprt)
* connection is closed or lost. (The important thing is it needs
* to be invoked "at least" once).
*/
-static void rpcrdma_force_disconnect(struct rpcrdma_ep *ep)
+void rpcrdma_force_disconnect(struct rpcrdma_ep *ep)
{
if (atomic_add_unless(&ep->re_force_disconnect, 1, 1))
xprt_force_disconnect(ep->re_xprt);
@@ -1350,21 +1350,6 @@ static void rpcrdma_regbuf_free(struct rpcrdma_regbuf *rb)
}
/**
- * rpcrdma_post_sends - Post WRs to a transport's Send Queue
- * @r_xprt: controlling transport instance
- * @req: rpcrdma_req containing the Send WR to post
- *
- * Returns 0 if the post was successful, otherwise -ENOTCONN
- * is returned.
- */
-int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
-{
- if (frwr_send(r_xprt, req))
- return -ENOTCONN;
- return 0;
-}
-
-/**
* rpcrdma_post_recvs - Refill the Receive Queue
* @r_xprt: controlling transport instance
* @needed: current credit grant
@@ -1416,12 +1401,8 @@ void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp)
rc = ib_post_recv(ep->re_id->qp, wr,
(const struct ib_recv_wr **)&bad_wr);
- if (atomic_dec_return(&ep->re_receiving) > 0)
- complete(&ep->re_done);
-
-out:
- trace_xprtrdma_post_recvs(r_xprt, count, rc);
if (rc) {
+ trace_xprtrdma_post_recvs_err(r_xprt, rc);
for (wr = bad_wr; wr;) {
struct rpcrdma_rep *rep;
@@ -1431,6 +1412,11 @@ out:
--count;
}
}
+ if (atomic_dec_return(&ep->re_receiving) > 0)
+ complete(&ep->re_done);
+
+out:
+ trace_xprtrdma_post_recvs(r_xprt, count);
ep->re_receive_count += count;
return;
}
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index 5d231d94e944..d91f54eae00b 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -454,11 +454,11 @@ extern unsigned int xprt_rdma_memreg_strategy;
/*
* Endpoint calls - xprtrdma/verbs.c
*/
+void rpcrdma_force_disconnect(struct rpcrdma_ep *ep);
void rpcrdma_flush_disconnect(struct rpcrdma_xprt *r_xprt, struct ib_wc *wc);
int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt);
void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt);
-int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req);
void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp);
/*
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index b7dbdcbdeb6c..04f1b78bcbca 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1656,7 +1656,7 @@ static int xs_get_srcport(struct sock_xprt *transport)
unsigned short get_srcport(struct rpc_xprt *xprt)
{
struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt);
- return sock->srcport;
+ return xs_sock_getport(sock->sock);
}
EXPORT_SYMBOL(get_srcport);
@@ -2099,13 +2099,20 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt)
if (sock == NULL)
return;
+ if (!xprt->reuseport) {
+ xs_close(xprt);
+ return;
+ }
switch (skst) {
- default:
+ case TCP_FIN_WAIT1:
+ case TCP_FIN_WAIT2:
+ break;
+ case TCP_ESTABLISHED:
+ case TCP_CLOSE_WAIT:
kernel_sock_shutdown(sock, SHUT_RDWR);
trace_rpc_socket_shutdown(xprt, sock);
break;
- case TCP_CLOSE:
- case TCP_TIME_WAIT:
+ default:
xs_reset_transport(transport);
}
}
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index e3105ba407c7..ad570c2450be 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1426,7 +1426,7 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
if (ua) {
if (!tipc_uaddr_valid(ua, m->msg_namelen))
return -EINVAL;
- atype = ua->addrtype;
+ atype = ua->addrtype;
}
/* If socket belongs to a communication group follow other paths */
@@ -2423,7 +2423,7 @@ static int tipc_sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
u32 dport, struct sk_buff_head *xmitq)
{
- unsigned long time_limit = jiffies + 2;
+ unsigned long time_limit = jiffies + usecs_to_jiffies(20000);
struct sk_buff *skb;
unsigned int lim;
atomic_t *dcnt;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index eb47b9de2380..92345c9bb60c 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -3073,7 +3073,7 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
other = unix_peer(sk);
if (other && unix_peer(other) != sk &&
- unix_recvq_full(other) &&
+ unix_recvq_full_lockless(other) &&
unix_dgram_peer_wake_me(sk, other))
writable = 0;
diff --git a/samples/kdb/kdb_hello.c b/samples/kdb/kdb_hello.c
index c1c2fa0f62c2..82736e5a5e32 100644
--- a/samples/kdb/kdb_hello.c
+++ b/samples/kdb/kdb_hello.c
@@ -28,28 +28,26 @@ static int kdb_hello_cmd(int argc, const char **argv)
return 0;
}
+static kdbtab_t hello_cmd = {
+ .name = "hello",
+ .func = kdb_hello_cmd,
+ .usage = "[string]",
+ .help = "Say Hello World or Hello [string]",
+};
static int __init kdb_hello_cmd_init(void)
{
/*
* Registration of a dynamically added kdb command is done with
- * kdb_register() with the arguments being:
- * 1: The name of the shell command
- * 2: The function that processes the command
- * 3: Description of the usage of any arguments
- * 4: Descriptive text when you run help
- * 5: Number of characters to complete the command
- * 0 == type the whole command
- * 1 == match both "g" and "go" for example
+ * kdb_register().
*/
- kdb_register("hello", kdb_hello_cmd, "[string]",
- "Say Hello World or Hello [string]", 0);
+ kdb_register(&hello_cmd);
return 0;
}
static void __exit kdb_hello_cmd_exit(void)
{
- kdb_unregister("hello");
+ kdb_unregister(&hello_cmd);
}
module_init(kdb_hello_cmd_init);
diff --git a/samples/mei/mei-amt-version.c b/samples/mei/mei-amt-version.c
index ad3e56042f96..867debd3b912 100644
--- a/samples/mei/mei-amt-version.c
+++ b/samples/mei/mei-amt-version.c
@@ -154,31 +154,52 @@ err:
static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer,
ssize_t len, unsigned long timeout)
{
+ struct timeval tv;
+ fd_set set;
ssize_t rc;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000000;
+
mei_msg(me, "call read length = %zd\n", len);
+ FD_ZERO(&set);
+ FD_SET(me->fd, &set);
+ rc = select(me->fd + 1, &set, NULL, NULL, &tv);
+ if (rc > 0 && FD_ISSET(me->fd, &set)) {
+ mei_msg(me, "have reply\n");
+ } else if (rc == 0) {
+ rc = -1;
+ mei_err(me, "read failed on timeout\n");
+ goto out;
+ } else { /* rc < 0 */
+ rc = errno;
+ mei_err(me, "read failed on select with status %zd %s\n",
+ rc, strerror(errno));
+ goto out;
+ }
+
rc = read(me->fd, buffer, len);
if (rc < 0) {
mei_err(me, "read failed with status %zd %s\n",
rc, strerror(errno));
- mei_deinit(me);
- } else {
- mei_msg(me, "read succeeded with result %zd\n", rc);
+ goto out;
}
+
+ mei_msg(me, "read succeeded with result %zd\n", rc);
+
+out:
+ if (rc < 0)
+ mei_deinit(me);
+
return rc;
}
static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer,
ssize_t len, unsigned long timeout)
{
- struct timeval tv;
ssize_t written;
ssize_t rc;
- fd_set set;
-
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000000;
mei_msg(me, "call write length = %zd\n", len);
@@ -189,19 +210,7 @@ static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer,
written, strerror(errno));
goto out;
}
-
- FD_ZERO(&set);
- FD_SET(me->fd, &set);
- rc = select(me->fd + 1 , &set, NULL, NULL, &tv);
- if (rc > 0 && FD_ISSET(me->fd, &set)) {
- mei_msg(me, "write success\n");
- } else if (rc == 0) {
- mei_err(me, "write failed on timeout with status\n");
- goto out;
- } else { /* rc < 0 */
- mei_err(me, "write failed on select with status %zd\n", rc);
- goto out;
- }
+ mei_msg(me, "write success\n");
rc = written;
out:
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 6c0f229db36a..c313ab4d1f4e 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -129,7 +129,7 @@ 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;
+static atomic_t mbochs_avail_mbytes;
static const struct vfio_device_ops mbochs_dev_ops;
struct vfio_region_info_ext {
@@ -507,18 +507,22 @@ static int mbochs_reset(struct mdev_state *mdev_state)
static int mbochs_probe(struct mdev_device *mdev)
{
+ int avail_mbytes = atomic_read(&mbochs_avail_mbytes);
const struct mbochs_type *type =
&mbochs_types[mdev_get_type_group_id(mdev)];
struct device *dev = mdev_dev(mdev);
struct mdev_state *mdev_state;
int ret = -ENOMEM;
- if (type->mbytes + mbochs_used_mbytes > max_mbytes)
- return -ENOMEM;
+ do {
+ if (avail_mbytes < type->mbytes)
+ return -ENOSPC;
+ } while (!atomic_try_cmpxchg(&mbochs_avail_mbytes, &avail_mbytes,
+ avail_mbytes - type->mbytes));
mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
if (mdev_state == NULL)
- return -ENOMEM;
+ goto err_avail;
vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mbochs_dev_ops);
mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
@@ -549,17 +553,18 @@ static int mbochs_probe(struct mdev_device *mdev)
mbochs_create_config_space(mdev_state);
mbochs_reset(mdev_state);
- mbochs_used_mbytes += type->mbytes;
-
ret = vfio_register_group_dev(&mdev_state->vdev);
if (ret)
goto err_mem;
dev_set_drvdata(&mdev->dev, mdev_state);
return 0;
-
err_mem:
+ vfio_uninit_group_dev(&mdev_state->vdev);
+ kfree(mdev_state->pages);
kfree(mdev_state->vconfig);
kfree(mdev_state);
+err_avail:
+ atomic_add(type->mbytes, &mbochs_avail_mbytes);
return ret;
}
@@ -567,8 +572,9 @@ static void mbochs_remove(struct mdev_device *mdev)
{
struct mdev_state *mdev_state = dev_get_drvdata(&mdev->dev);
- mbochs_used_mbytes -= mdev_state->type->mbytes;
vfio_unregister_group_dev(&mdev_state->vdev);
+ vfio_uninit_group_dev(&mdev_state->vdev);
+ atomic_add(mdev_state->type->mbytes, &mbochs_avail_mbytes);
kfree(mdev_state->pages);
kfree(mdev_state->vconfig);
kfree(mdev_state);
@@ -1272,15 +1278,7 @@ static long mbochs_ioctl(struct vfio_device *vdev, unsigned int cmd,
return -ENOTTY;
}
-static int mbochs_open(struct vfio_device *vdev)
-{
- if (!try_module_get(THIS_MODULE))
- return -ENODEV;
-
- return 0;
-}
-
-static void mbochs_close(struct vfio_device *vdev)
+static void mbochs_close_device(struct vfio_device *vdev)
{
struct mdev_state *mdev_state =
container_of(vdev, struct mdev_state, vdev);
@@ -1300,7 +1298,6 @@ static void mbochs_close(struct vfio_device *vdev)
mbochs_put_pages(mdev_state);
mutex_unlock(&mdev_state->ops_lock);
- module_put(THIS_MODULE);
}
static ssize_t
@@ -1355,7 +1352,7 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
{
const struct mbochs_type *type =
&mbochs_types[mtype_get_type_group_id(mtype)];
- int count = (max_mbytes - mbochs_used_mbytes) / type->mbytes;
+ int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;
return sprintf(buf, "%d\n", count);
}
@@ -1399,8 +1396,7 @@ static struct attribute_group *mdev_type_groups[] = {
};
static const struct vfio_device_ops mbochs_dev_ops = {
- .open = mbochs_open,
- .release = mbochs_close,
+ .close_device = mbochs_close_device,
.read = mbochs_read,
.write = mbochs_write,
.ioctl = mbochs_ioctl,
@@ -1437,6 +1433,8 @@ static int __init mbochs_dev_init(void)
{
int ret = 0;
+ atomic_set(&mbochs_avail_mbytes, max_mbytes);
+
ret = alloc_chrdev_region(&mbochs_devt, 0, MINORMASK + 1, MBOCHS_NAME);
if (ret < 0) {
pr_err("Error: failed to register mbochs_dev, err: %d\n", ret);
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index 393c9df6f6a0..8d1a80a0722a 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -235,17 +235,16 @@ static int mdpy_probe(struct mdev_device *mdev)
mdev_state->vconfig = kzalloc(MDPY_CONFIG_SPACE_SIZE, GFP_KERNEL);
if (mdev_state->vconfig == NULL) {
- kfree(mdev_state);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_state;
}
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;
+ ret = -ENOMEM;
+ goto err_vconfig;
}
dev_info(dev, "%s: %s (%dx%d)\n", __func__, type->name, type->width,
type->height);
@@ -260,13 +259,18 @@ static int mdpy_probe(struct mdev_device *mdev)
mdpy_count++;
ret = vfio_register_group_dev(&mdev_state->vdev);
- if (ret) {
- kfree(mdev_state->vconfig);
- kfree(mdev_state);
- return ret;
- }
+ if (ret)
+ goto err_mem;
dev_set_drvdata(&mdev->dev, mdev_state);
return 0;
+err_mem:
+ vfree(mdev_state->memblk);
+err_vconfig:
+ kfree(mdev_state->vconfig);
+err_state:
+ vfio_uninit_group_dev(&mdev_state->vdev);
+ kfree(mdev_state);
+ return ret;
}
static void mdpy_remove(struct mdev_device *mdev)
@@ -278,6 +282,7 @@ static void mdpy_remove(struct mdev_device *mdev)
vfio_unregister_group_dev(&mdev_state->vdev);
vfree(mdev_state->memblk);
kfree(mdev_state->vconfig);
+ vfio_uninit_group_dev(&mdev_state->vdev);
kfree(mdev_state);
mdpy_count--;
@@ -609,19 +614,6 @@ static long mdpy_ioctl(struct vfio_device *vdev, unsigned int cmd,
return -ENOTTY;
}
-static int mdpy_open(struct vfio_device *vdev)
-{
- if (!try_module_get(THIS_MODULE))
- return -ENODEV;
-
- return 0;
-}
-
-static void mdpy_close(struct vfio_device *vdev)
-{
- module_put(THIS_MODULE);
-}
-
static ssize_t
resolution_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -716,8 +708,6 @@ static struct attribute_group *mdev_type_groups[] = {
};
static const struct vfio_device_ops mdpy_dev_ops = {
- .open = mdpy_open,
- .release = mdpy_close,
.read = mdpy_read,
.write = mdpy_write,
.ioctl = mdpy_ioctl,
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index 8b26fecc4afe..5983cdb16e3d 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -718,8 +718,8 @@ static int mtty_probe(struct mdev_device *mdev)
mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
if (mdev_state == NULL) {
- atomic_add(nr_ports, &mdev_avail_ports);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_nr_ports;
}
vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mtty_dev_ops);
@@ -732,9 +732,8 @@ static int mtty_probe(struct mdev_device *mdev)
mdev_state->vconfig = kzalloc(MTTY_CONFIG_SPACE_SIZE, GFP_KERNEL);
if (mdev_state->vconfig == NULL) {
- kfree(mdev_state);
- atomic_add(nr_ports, &mdev_avail_ports);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_state;
}
mutex_init(&mdev_state->ops_lock);
@@ -743,14 +742,19 @@ static int mtty_probe(struct mdev_device *mdev)
mtty_create_config_space(mdev_state);
ret = vfio_register_group_dev(&mdev_state->vdev);
- if (ret) {
- kfree(mdev_state);
- atomic_add(nr_ports, &mdev_avail_ports);
- return ret;
- }
-
+ if (ret)
+ goto err_vconfig;
dev_set_drvdata(&mdev->dev, mdev_state);
return 0;
+
+err_vconfig:
+ kfree(mdev_state->vconfig);
+err_state:
+ vfio_uninit_group_dev(&mdev_state->vdev);
+ kfree(mdev_state);
+err_nr_ports:
+ atomic_add(nr_ports, &mdev_avail_ports);
+ return ret;
}
static void mtty_remove(struct mdev_device *mdev)
@@ -761,6 +765,7 @@ static void mtty_remove(struct mdev_device *mdev)
vfio_unregister_group_dev(&mdev_state->vdev);
kfree(mdev_state->vconfig);
+ vfio_uninit_group_dev(&mdev_state->vdev);
kfree(mdev_state);
atomic_add(nr_ports, &mdev_avail_ports);
}
@@ -1202,17 +1207,6 @@ static long mtty_ioctl(struct vfio_device *vdev, unsigned int cmd,
return -ENOTTY;
}
-static int mtty_open(struct vfio_device *vdev)
-{
- pr_info("%s\n", __func__);
- return 0;
-}
-
-static void mtty_close(struct vfio_device *mdev)
-{
- pr_info("%s\n", __func__);
-}
-
static ssize_t
sample_mtty_dev_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1320,8 +1314,6 @@ static struct attribute_group *mdev_type_groups[] = {
static const struct vfio_device_ops mtty_dev_ops = {
.name = "vfio-mtty",
- .open = mtty_open,
- .release = mtty_close,
.read = mtty_read,
.write = mtty_write,
.ioctl = mtty_ioctl,
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index f247e691562d..cdec22088423 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -57,6 +57,7 @@ kecho := $($(quiet)kecho)
# - If the content differ the new file is used
# - If they are equal no change, and no timestamp update
define filechk
+ $(check-FORCE)
$(Q)set -e; \
mkdir -p $(dir $@); \
trap "rm -f $(dot-target).tmp" EXIT; \
@@ -130,13 +131,19 @@ make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1))))
# PHONY targets skipped in both cases.
newer-prereqs = $(filter-out $(PHONY),$?)
+# It is a typical mistake to forget the FORCE prerequisite. Check it here so
+# no more breakage will slip in.
+check-FORCE = $(if $(filter FORCE, $^),,$(warning FORCE prerequisite is missing))
+
+if-changed-cond = $(newer-prereqs)$(cmd-check)$(check-FORCE)
+
# Execute command if command has changed or prerequisite(s) are updated.
-if_changed = $(if $(newer-prereqs)$(cmd-check), \
+if_changed = $(if $(if-changed-cond), \
$(cmd); \
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
# Execute the command and also postprocess generated .d dependencies file.
-if_changed_dep = $(if $(newer-prereqs)$(cmd-check),$(cmd_and_fixdep),@:)
+if_changed_dep = $(if $(if-changed-cond),$(cmd_and_fixdep),@:)
cmd_and_fixdep = \
$(cmd); \
@@ -146,7 +153,7 @@ cmd_and_fixdep = \
# Usage: $(call if_changed_rule,foo)
# Will check if $(cmd_foo) or any of the prerequisites changed,
# and if so will execute $(rule_foo).
-if_changed_rule = $(if $(newer-prereqs)$(cmd-check),$(rule_$(1)),@:)
+if_changed_rule = $(if $(if-changed-cond),$(rule_$(1)),@:)
###
# why - tell why a target got built
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 02197cb8e3a7..3efc984d4c69 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -88,6 +88,10 @@ endif
targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m)))
+ifdef CONFIG_LTO_CLANG
+targets-for-modules += $(patsubst %.o, %.lto.o, $(filter %.o, $(obj-m)))
+endif
+
ifdef need-modorder
targets-for-modules += $(obj)/modules.order
endif
@@ -173,6 +177,8 @@ cmd_modversions_c = \
if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $@.symversions; \
+ else \
+ rm -f $@.symversions; \
fi;
else
cmd_modversions_c = \
@@ -271,12 +277,33 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) $$(objtool_dep) FORCE
$(call if_changed_rule,cc_o_c)
$(call cmd,force_checksrc)
+ifdef CONFIG_LTO_CLANG
+# Module .o files may contain LLVM bitcode, compile them into native code
+# before ELF processing
+quiet_cmd_cc_lto_link_modules = LTO [M] $@
+cmd_cc_lto_link_modules = \
+ $(LD) $(ld_flags) -r -o $@ \
+ $(shell [ -s $(@:.lto.o=.o.symversions) ] && \
+ echo -T $(@:.lto.o=.o.symversions)) \
+ --whole-archive $(filter-out FORCE,$^)
+
+ifdef CONFIG_STACK_VALIDATION
+# objtool was skipped for LLVM bitcode, run it now that we have compiled
+# modules into native code
+cmd_cc_lto_link_modules += ; \
+ $(objtree)/tools/objtool/objtool $(objtool_args) --module $@
+endif
+
+$(obj)/%.lto.o: $(obj)/%.o FORCE
+ $(call if_changed,cc_lto_link_modules)
+endif
+
cmd_mod = { \
echo $(if $($*-objs)$($*-y)$($*-m), $(addprefix $(obj)/, $($*-objs) $($*-y) $($*-m)), $(@:.mod=.o)); \
$(undefined_syms) echo; \
} > $@
-$(obj)/%.mod: $(obj)/%.o FORCE
+$(obj)/%.mod: $(obj)/%$(mod-prelink-ext).o FORCE
$(call if_changed,mod)
quiet_cmd_cc_lst_c = MKLST $@
@@ -381,7 +408,6 @@ $(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
# combine symversions for later processing
-quiet_cmd_update_lto_symversions = SYMVER $@
ifeq ($(CONFIG_LTO_CLANG) $(CONFIG_MODVERSIONS),y y)
cmd_update_lto_symversions = \
rm -f $@.symversions \
diff --git a/scripts/Makefile.clang b/scripts/Makefile.clang
new file mode 100644
index 000000000000..4cce8fd0779c
--- /dev/null
+++ b/scripts/Makefile.clang
@@ -0,0 +1,35 @@
+# Individual arch/{arch}/Makefiles should use -EL/-EB to set intended
+# endianness and -m32/-m64 to set word size based on Kconfigs instead of
+# relying on the target triple.
+CLANG_TARGET_FLAGS_arm := arm-linux-gnueabi
+CLANG_TARGET_FLAGS_arm64 := aarch64-linux-gnu
+CLANG_TARGET_FLAGS_hexagon := hexagon-linux-musl
+CLANG_TARGET_FLAGS_m68k := m68k-linux-gnu
+CLANG_TARGET_FLAGS_mips := mipsel-linux-gnu
+CLANG_TARGET_FLAGS_powerpc := powerpc64le-linux-gnu
+CLANG_TARGET_FLAGS_riscv := riscv64-linux-gnu
+CLANG_TARGET_FLAGS_s390 := s390x-linux-gnu
+CLANG_TARGET_FLAGS_x86 := x86_64-linux-gnu
+CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(SRCARCH))
+
+ifeq ($(CROSS_COMPILE),)
+ifeq ($(CLANG_TARGET_FLAGS),)
+$(error Specify CROSS_COMPILE or add '--target=' option to scripts/Makefile.clang)
+else
+CLANG_FLAGS += --target=$(CLANG_TARGET_FLAGS)
+endif # CLANG_TARGET_FLAGS
+else
+CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))
+endif # CROSS_COMPILE
+
+ifeq ($(LLVM_IAS),0)
+CLANG_FLAGS += -fno-integrated-as
+GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
+CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
+else
+CLANG_FLAGS += -fintegrated-as
+endif
+CLANG_FLAGS += -Werror=unknown-warning-option
+KBUILD_CFLAGS += $(CLANG_FLAGS)
+KBUILD_AFLAGS += $(CLANG_FLAGS)
+export CLANG_FLAGS
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 10950559b223..54582673fc1a 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -225,17 +225,23 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \
$(addprefix -I,$(DTC_INCLUDE)) \
-undef -D__DTS__
+ifeq ($(CONFIG_LTO_CLANG),y)
+# With CONFIG_LTO_CLANG, .o files in modules might be LLVM bitcode, so we
+# need to run LTO to compile them into native code (.lto.o) before further
+# processing.
+mod-prelink-ext := .lto
+endif
+
# Objtool arguments are also needed for modfinal with LTO, so we define
# then here to avoid duplication.
objtool_args = \
$(if $(CONFIG_UNWINDER_ORC),orc generate,check) \
- $(if $(part-of-module), --module,) \
+ $(if $(part-of-module), --module) \
$(if $(CONFIG_FRAME_POINTER),, --no-fp) \
- $(if $(or $(CONFIG_GCOV_KERNEL),$(CONFIG_LTO_CLANG)), \
- --no-unreachable,) \
- $(if $(CONFIG_RETPOLINE), --retpoline,) \
- $(if $(CONFIG_X86_SMAP), --uaccess,) \
- $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount,)
+ $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\
+ $(if $(CONFIG_RETPOLINE), --retpoline) \
+ $(if $(CONFIG_X86_SMAP), --uaccess) \
+ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)
# Useful for describing the dependency of composite objects
# Usage:
@@ -309,8 +315,7 @@ DTC_FLAGS += -Wno-unit_address_vs_reg \
-Wno-alias_paths \
-Wno-graph_child_address \
-Wno-simple_bus_reg \
- -Wno-unique_unit_address \
- -Wno-pci_device_reg
+ -Wno-unique_unit_address
endif
ifneq ($(findstring 2,$(KBUILD_EXTRA_WARN)),)
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index 5e9b8057fb24..ff805777431c 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -9,7 +9,7 @@ __modfinal:
include include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
-# for c_flags and objtool_args
+# for c_flags and mod-prelink-ext
include $(srctree)/scripts/Makefile.lib
# find all modules listed in modules.order
@@ -30,23 +30,6 @@ quiet_cmd_cc_o_c = CC [M] $@
ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
-ifdef CONFIG_LTO_CLANG
-# With CONFIG_LTO_CLANG, reuse the object file we compiled for modpost to
-# avoid a second slow LTO link
-prelink-ext := .lto
-
-# ELF processing was skipped earlier because we didn't have native code,
-# so let's now process the prelinked binary before we link the module.
-
-ifdef CONFIG_STACK_VALIDATION
-cmd_ld_ko_o += \
- $(objtree)/tools/objtool/objtool $(objtool_args) \
- $(@:.ko=$(prelink-ext).o);
-
-endif # CONFIG_STACK_VALIDATION
-
-endif # CONFIG_LTO_CLANG
-
quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o += \
$(LD) -r $(KBUILD_LDFLAGS) \
@@ -72,7 +55,7 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
# Re-generate module BTFs if either module's .ko or vmlinux changed
-$(modules): %.ko: %$(prelink-ext).o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
+$(modules): %.ko: %$(mod-prelink-ext).o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
+$(call if_changed_except,ld_ko_o,vmlinux)
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+$(if $(newer-prereqs),$(call cmd,btf_ko))
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index c383ba33d837..eef56d629799 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -41,7 +41,7 @@ __modpost:
include include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
-# for ld_flags
+# for mod-prelink-ext
include $(srctree)/scripts/Makefile.lib
MODPOST = scripts/mod/modpost \
@@ -118,22 +118,6 @@ $(input-symdump):
@echo >&2 ' Modules may not have dependencies or modversions.'
@echo >&2 ' You may get many unresolved symbol warnings.'
-ifdef CONFIG_LTO_CLANG
-# With CONFIG_LTO_CLANG, .o files might be LLVM bitcode, so we need to run
-# LTO to compile them into native code before running modpost
-prelink-ext := .lto
-
-quiet_cmd_cc_lto_link_modules = LTO [M] $@
-cmd_cc_lto_link_modules = \
- $(LD) $(ld_flags) -r -o $@ \
- $(shell [ -s $(@:.lto.o=.o.symversions) ] && \
- echo -T $(@:.lto.o=.o.symversions)) \
- --whole-archive $^
-
-%.lto.o: %.o
- $(call if_changed,cc_lto_link_modules)
-endif
-
modules := $(sort $(shell cat $(MODORDER)))
# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined symbols
@@ -144,9 +128,9 @@ endif
# Read out modules.order to pass in modpost.
# Otherwise, allmodconfig would fail with "Argument list too long".
quiet_cmd_modpost = MODPOST $@
- cmd_modpost = sed 's/\.ko$$/$(prelink-ext)\.o/' $< | $(MODPOST) -T -
+ cmd_modpost = sed 's/\.ko$$/$(mod-prelink-ext)\.o/' $< | $(MODPOST) -T -
-$(output-symdump): $(MODORDER) $(input-symdump) $(modules:.ko=$(prelink-ext).o) FORCE
+$(output-symdump): $(MODORDER) $(input-symdump) $(modules:.ko=$(mod-prelink-ext).o) FORCE
$(call if_changed,modpost)
targets += $(output-symdump)
diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh
index d8f6f9c63043..59fdb875e818 100755
--- a/scripts/adjust_autoksyms.sh
+++ b/scripts/adjust_autoksyms.sh
@@ -42,10 +42,10 @@ $CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh "$new_ksyms_file"
changed=$(
count=0
sort "$cur_ksyms_file" "$new_ksyms_file" | uniq -u |
-sed -n 's/^#define __KSYM_\(.*\) 1/\1/p' | tr "A-Z_" "a-z/" |
+sed -n 's/^#define __KSYM_\(.*\) 1/\1/p' |
while read sympath; do
if [ -z "$sympath" ]; then continue; fi
- depfile="include/ksym/${sympath}.h"
+ depfile="include/ksym/${sympath}"
mkdir -p "$(dirname "$depfile")"
touch "$depfile"
# Filesystems with coarse time precision may create timestamps
diff --git a/scripts/as-version.sh b/scripts/as-version.sh
index 8b9410e329df..1a21495e9ff0 100755
--- a/scripts/as-version.sh
+++ b/scripts/as-version.sh
@@ -21,14 +21,14 @@ get_canonical_version()
echo $((10000 * $1 + 100 * ${2:-0} + ${3:-0}))
}
-# Clang fails to handle -Wa,--version unless -no-integrated-as is given.
-# We check -(f)integrated-as, expecting it is explicitly passed in for the
+# Clang fails to handle -Wa,--version unless -fno-integrated-as is given.
+# We check -fintegrated-as, expecting it is explicitly passed in for the
# integrated assembler case.
check_integrated_as()
{
while [ $# -gt 0 ]; do
- if [ "$1" = -integrated-as -o "$1" = -fintegrated-as ]; then
- # For the intergrated assembler, we do not check the
+ if [ "$1" = -fintegrated-as ]; then
+ # For the integrated assembler, we do not check the
# version here. It is the same as the clang version, and
# it has been already checked by scripts/cc-version.sh.
echo LLVM 0
diff --git a/scripts/checkdeclares.pl b/scripts/checkdeclares.pl
index f6d551c84fc6..f6d551c84fc6 100644..100755
--- a/scripts/checkdeclares.pl
+++ b/scripts/checkdeclares.pl
diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py
index 1548f9ce4682..b9b0f15e5880 100755
--- a/scripts/checkkconfigsymbols.py
+++ b/scripts/checkkconfigsymbols.py
@@ -329,7 +329,7 @@ def check_symbols_helper(pool, ignore):
if REGEX_FILE_KCONFIG.match(gitfile):
kconfig_files.append(gitfile)
else:
- if ignore and not re.match(ignore, gitfile):
+ if ignore and re.match(ignore, gitfile):
continue
# add source files that do not match the ignore pattern
source_files.append(gitfile)
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index b7609958ee36..fd9777f63f14 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -266,4 +266,4 @@ syscall_list() {
}
(ignore_list && syscall_list $(dirname $0)/../arch/x86/entry/syscalls/syscall_32.tbl) | \
-$* -E -x c - > /dev/null
+$* -Wno-error -E -x c - > /dev/null
diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py
index b7e9ecf16e56..0033eedce003 100755
--- a/scripts/clang-tools/gen_compile_commands.py
+++ b/scripts/clang-tools/gen_compile_commands.py
@@ -18,7 +18,7 @@ _DEFAULT_OUTPUT = 'compile_commands.json'
_DEFAULT_LOG_LEVEL = 'WARNING'
_FILENAME_PATTERN = r'^\..*\.cmd$'
-_LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$'
+_LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c) *(;|$)'
_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
# The tools/ directory adopts a different build system, and produces .cmd
# files in a different format. Do not support it.
diff --git a/scripts/gcc-plugins/gen-random-seed.sh b/scripts/gcc-plugins/gen-random-seed.sh
index 68af5cc20a64..68af5cc20a64 100644..100755
--- a/scripts/gcc-plugins/gen-random-seed.sh
+++ b/scripts/gcc-plugins/gen-random-seed.sh
diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh
index da320151e7c3..6ed0d225c8b1 100755
--- a/scripts/gen_autoksyms.sh
+++ b/scripts/gen_autoksyms.sh
@@ -26,18 +26,6 @@ if [ -n "$CONFIG_MODVERSIONS" ]; then
needed_symbols="$needed_symbols module_layout"
fi
-# With CONFIG_LTO_CLANG, LLVM bitcode has not yet been compiled into a binary
-# when the .mod files are generated, which means they don't yet contain
-# references to certain symbols that will be present in the final binaries.
-if [ -n "$CONFIG_LTO_CLANG" ]; then
- # intrinsic functions
- needed_symbols="$needed_symbols memcpy memmove memset"
- # ftrace
- needed_symbols="$needed_symbols _mcount"
- # stack protector symbols
- needed_symbols="$needed_symbols __stack_chk_fail __stack_chk_guard"
-fi
-
ksym_wl=
if [ -n "$CONFIG_UNUSED_KSYMS_WHITELIST" ]; then
# Use 'eval' to expand the whitelist path and check if it is relative
diff --git a/scripts/gen_ksymdeps.sh b/scripts/gen_ksymdeps.sh
index 1324986e1362..8ee533f33659 100755
--- a/scripts/gen_ksymdeps.sh
+++ b/scripts/gen_ksymdeps.sh
@@ -4,7 +4,13 @@
set -e
# List of exported symbols
-ksyms=$($NM $1 | sed -n 's/.*__ksym_marker_\(.*\)/\1/p' | tr A-Z a-z)
+#
+# If the object has no symbol, $NM warns 'no symbols'.
+# Suppress the stderr.
+# TODO:
+# Use -q instead of 2>/dev/null when we upgrade the minimum version of
+# binutils to 2.37, llvm to 13.0.0.
+ksyms=$($NM $1 2>/dev/null | sed -n 's/.*__ksym_marker_\(.*\)/\1/p')
if [ -z "$ksyms" ]; then
exit 0
@@ -15,8 +21,7 @@ echo "ksymdeps_$1 := \\"
for s in $ksyms
do
- echo $s | sed -e 's:^_*: $(wildcard include/ksym/:' \
- -e 's:__*:/:g' -e 's/$/.h) \\/'
+ printf ' $(wildcard include/ksym/%s) \\\n' "$s"
done
echo
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
index 63c8565206a4..e5b46980c22a 100755
--- a/scripts/kconfig/merge_config.sh
+++ b/scripts/kconfig/merge_config.sh
@@ -28,6 +28,7 @@ usage() {
echo " -r list redundant entries when merging fragments"
echo " -y make builtin have precedence over modules"
echo " -O dir to put generated output files. Consider setting \$KCONFIG_CONFIG instead."
+ echo " -s strict mode. Fail if the fragment redefines any value."
echo
echo "Used prefix: '$CONFIG_PREFIX'. You can redefine it with \$CONFIG_ environment variable."
}
@@ -37,6 +38,7 @@ ALLTARGET=alldefconfig
WARNREDUN=false
BUILTIN=false
OUTPUT=.
+STRICT=false
CONFIG_PREFIX=${CONFIG_-CONFIG_}
while true; do
@@ -75,6 +77,11 @@ while true; do
shift 2
continue
;;
+ "-s")
+ STRICT=true
+ shift
+ continue
+ ;;
*)
break
;;
@@ -141,6 +148,9 @@ for ORIG_MERGE_FILE in $MERGE_LIST ; do
echo Previous value: $PREV_VAL
echo New value: $NEW_VAL
echo
+ if [ "$STRICT" = "true" ]; then
+ STRICT_MODE_VIOLATED=true
+ fi
elif [ "$WARNREDUN" = "true" ]; then
echo Value of $CFG is redundant by fragment $ORIG_MERGE_FILE:
fi
@@ -153,6 +163,11 @@ for ORIG_MERGE_FILE in $MERGE_LIST ; do
cat $MERGE_FILE >> $TMP_FILE
done
+if [ "$STRICT_MODE_VIOLATED" = "true" ]; then
+ echo "The fragment redefined a value and strict mode had been passed."
+ exit 1
+fi
+
if [ "$RUNMAKE" = "false" ]; then
cp -T -- "$TMP_FILE" "$KCONFIG_CONFIG"
echo "#"
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 7c4a6a507ac4..cfcb60737957 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -329,10 +329,6 @@ if (defined($ENV{'KBUILD_VERBOSE'})) {
$verbose = "$ENV{'KBUILD_VERBOSE'}";
}
-if (defined($ENV{'KDOC_WERROR'})) {
- $Werror = "$ENV{'KDOC_WERROR'}";
-}
-
if (defined($ENV{'KCFLAGS'})) {
my $kcflags = "$ENV{'KCFLAGS'}";
@@ -341,6 +337,10 @@ if (defined($ENV{'KCFLAGS'})) {
}
}
+if (defined($ENV{'KDOC_WERROR'})) {
+ $Werror = "$ENV{'KDOC_WERROR'}";
+}
+
# Generated docbook code is inserted in a template at a point where
# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
# https://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 36ef7b37fc5d..d74cee5c4326 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -149,67 +149,54 @@ objtool_link()
# ${2}, ${3}, ... - optional extra .o files
vmlinux_link()
{
- local lds="${objtree}/${KBUILD_LDS}"
local output=${1}
- local objects
- local strip_debug
- local map_option
+ local objs
+ local libs
+ local ld
+ local ldflags
+ local ldlibs
info LD ${output}
# skip output file argument
shift
+ if [ -n "${CONFIG_LTO_CLANG}" ]; then
+ # Use vmlinux.o instead of performing the slow LTO link again.
+ objs=vmlinux.o
+ libs=
+ else
+ objs="${KBUILD_VMLINUX_OBJS}"
+ libs="${KBUILD_VMLINUX_LIBS}"
+ fi
+
+ if [ "${SRCARCH}" = "um" ]; then
+ wl=-Wl,
+ ld="${CC}"
+ ldflags="${CFLAGS_vmlinux}"
+ ldlibs="-lutil -lrt -lpthread"
+ else
+ wl=
+ ld="${LD}"
+ ldflags="${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux}"
+ ldlibs=
+ fi
+
+ ldflags="${ldflags} ${wl}--script=${objtree}/${KBUILD_LDS}"
+
# The kallsyms linking does not need debug symbols included.
if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then
- strip_debug=-Wl,--strip-debug
+ ldflags="${ldflags} ${wl}--strip-debug"
fi
if [ -n "${CONFIG_VMLINUX_MAP}" ]; then
- map_option="-Map=${output}.map"
+ ldflags="${ldflags} ${wl}-Map=${output}.map"
fi
- if [ "${SRCARCH}" != "um" ]; then
- if [ -n "${CONFIG_LTO_CLANG}" ]; then
- # Use vmlinux.o instead of performing the slow LTO
- # link again.
- objects="--whole-archive \
- vmlinux.o \
- --no-whole-archive \
- ${@}"
- else
- objects="--whole-archive \
- ${KBUILD_VMLINUX_OBJS} \
- --no-whole-archive \
- --start-group \
- ${KBUILD_VMLINUX_LIBS} \
- --end-group \
- ${@}"
- fi
-
- ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
- ${strip_debug#-Wl,} \
- -o ${output} \
- ${map_option} \
- -T ${lds} ${objects}
- else
- objects="-Wl,--whole-archive \
- ${KBUILD_VMLINUX_OBJS} \
- -Wl,--no-whole-archive \
- -Wl,--start-group \
- ${KBUILD_VMLINUX_LIBS} \
- -Wl,--end-group \
- ${@}"
-
- ${CC} ${CFLAGS_vmlinux} \
- ${strip_debug} \
- -o ${output} \
- ${map_option:+-Wl,${map_option}} \
- -Wl,-T,${lds} \
- ${objects} \
- -lutil -lrt -lpthread
- rm -f linux
- fi
+ ${ld} ${ldflags} -o ${output} \
+ ${wl}--whole-archive ${objs} ${wl}--no-whole-archive \
+ ${wl}--start-group ${libs} ${wl}--end-group \
+ $@ ${ldlibs}
}
# generate .BTF typeinfo from DWARF debuginfo
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index 9bb6c7edccc4..cc3625617a0e 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -42,6 +42,7 @@ int main(void)
DEVID_FIELD(pci_device_id, subdevice);
DEVID_FIELD(pci_device_id, class);
DEVID_FIELD(pci_device_id, class_mask);
+ DEVID_FIELD(pci_device_id, override_only);
DEVID(ccw_device_id);
DEVID_FIELD(ccw_device_id, match_flags);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 7c97fa8e36bc..49aba862073e 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -426,7 +426,7 @@ static int do_ieee1394_entry(const char *filename,
return 1;
}
-/* Looks like: pci:vNdNsvNsdNbcNscNiN. */
+/* Looks like: pci:vNdNsvNsdNbcNscNiN or <prefix>_pci:vNdNsvNsdNbcNscNiN. */
static int do_pci_entry(const char *filename,
void *symval, char *alias)
{
@@ -440,8 +440,21 @@ static int do_pci_entry(const char *filename,
DEF_FIELD(symval, pci_device_id, subdevice);
DEF_FIELD(symval, pci_device_id, class);
DEF_FIELD(symval, pci_device_id, class_mask);
+ DEF_FIELD(symval, pci_device_id, override_only);
+
+ switch (override_only) {
+ case 0:
+ strcpy(alias, "pci:");
+ break;
+ case PCI_ID_F_VFIO_DRIVER_OVERRIDE:
+ strcpy(alias, "vfio_pci:");
+ break;
+ default:
+ warn("Unknown PCI driver_override alias %08X\n",
+ override_only);
+ return 0;
+ }
- strcpy(alias, "pci:");
ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
ADD(alias, "d", device != PCI_ANY_ID, device);
ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 270a7df898e2..cb8ab7d91d30 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -17,6 +17,7 @@
#include <ctype.h>
#include <string.h>
#include <limits.h>
+#include <stdbool.h>
#include <errno.h>
#include "modpost.h"
#include "../../include/linux/license.h"
@@ -89,6 +90,14 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
error_occurred = true;
}
+static inline bool strends(const char *str, const char *postfix)
+{
+ if (strlen(str) < strlen(postfix))
+ return false;
+
+ return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+}
+
void *do_nofail(void *ptr, const char *expr)
{
if (!ptr)
@@ -931,7 +940,7 @@ static void check_section(const char *modname, struct elf_info *elf,
".kprobes.text", ".cpuidle.text", ".noinstr.text"
#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
".fixup", ".entry.text", ".exception.text", ".text.*", \
- ".coldtext"
+ ".coldtext", ".softirqentry.text"
#define INIT_SECTIONS ".init.*"
#define MEM_INIT_SECTIONS ".meminit.*"
@@ -2060,7 +2069,7 @@ static void read_symbols(const char *modname)
if (!mod->is_vmlinux) {
version = get_modinfo(&info, "version");
if (version || all_versions)
- get_src_version(modname, mod->srcversion,
+ get_src_version(mod->name, mod->srcversion,
sizeof(mod->srcversion) - 1);
}
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index c1a895c0d682..0c47ff95c0e2 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -2,7 +2,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
-#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -178,14 +177,6 @@ static inline unsigned int get_secindex(const struct elf_info *info,
return info->symtab_shndx_start[sym - info->symtab_start];
}
-static inline bool strends(const char *str, const char *postfix)
-{
- if (strlen(str) < strlen(postfix))
- return false;
-
- return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
-}
-
/* file2alias.c */
extern unsigned int cross_build;
void handle_moddevtable(struct module *mod, struct elf_info *info,
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 760e6baa7eda..905c0ec291e1 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -391,14 +391,9 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
struct md4_ctx md;
char *fname;
char filelist[PATH_MAX + 1];
- int postfix_len = 1;
-
- if (strends(modname, ".lto.o"))
- postfix_len = 5;
/* objects for a module are listed in the first line of *.mod file. */
- snprintf(filelist, sizeof(filelist), "%.*smod",
- (int)strlen(modname) - postfix_len, modname);
+ snprintf(filelist, sizeof(filelist), "%s.mod", modname);
buf = read_text_file(filelist);
diff --git a/scripts/spdxcheck-test.sh b/scripts/spdxcheck-test.sh
index cfea6a0d1cc0..cb76324756bd 100644
--- a/scripts/spdxcheck-test.sh
+++ b/scripts/spdxcheck-test.sh
@@ -1,12 +1,10 @@
#!/bin/sh
-for PYTHON in python2 python3; do
- # run check on a text and a binary file
- for FILE in Makefile Documentation/logo.gif; do
- $PYTHON scripts/spdxcheck.py $FILE
- $PYTHON scripts/spdxcheck.py - < $FILE
- done
-
- # run check on complete tree to catch any other issues
- $PYTHON scripts/spdxcheck.py > /dev/null
+# run check on a text and a binary file
+for FILE in Makefile Documentation/logo.gif; do
+ python3 scripts/spdxcheck.py $FILE
+ python3 scripts/spdxcheck.py - < $FILE
done
+
+# run check on complete tree to catch any other issues
+python3 scripts/spdxcheck.py > /dev/null
diff --git a/scripts/subarch.include b/scripts/subarch.include
index 650682821126..776849a3c500 100644
--- a/scripts/subarch.include
+++ b/scripts/subarch.include
@@ -7,7 +7,7 @@
SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
-e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
- -e s/s390x/s390/ -e s/parisc64/parisc/ \
+ -e s/s390x/s390/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
-e s/riscv.*/riscv/)
diff --git a/scripts/syscallnr.sh b/scripts/syscallnr.sh
index 3aa29e0dcc52..3aa29e0dcc52 100644..100755
--- a/scripts/syscallnr.sh
+++ b/scripts/syscallnr.sh
diff --git a/scripts/xen-hypercalls.sh b/scripts/xen-hypercalls.sh
index f18b00843df3..f18b00843df3 100644..100755
--- a/scripts/xen-hypercalls.sh
+++ b/scripts/xen-hypercalls.sh
diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
index a56c36470cb1..90cbaff86e13 100644
--- a/security/Kconfig.hardening
+++ b/security/Kconfig.hardening
@@ -29,6 +29,7 @@ choice
prompt "Initialize kernel stack variables at function entry"
default GCC_PLUGIN_STRUCTLEAK_BYREF_ALL if COMPILE_TEST && GCC_PLUGINS
default INIT_STACK_ALL_PATTERN if COMPILE_TEST && CC_HAS_AUTO_VAR_INIT_PATTERN
+ default INIT_STACK_ALL_ZERO if CC_HAS_AUTO_VAR_INIT_PATTERN
default INIT_STACK_NONE
help
This option enables initialization of stack variables at
@@ -39,11 +40,11 @@ choice
syscalls.
This chooses the level of coverage over classes of potentially
- uninitialized variables. The selected class will be
+ uninitialized variables. The selected class of variable will be
initialized before use in a function.
config INIT_STACK_NONE
- bool "no automatic initialization (weakest)"
+ bool "no automatic stack variable initialization (weakest)"
help
Disable automatic stack variable initialization.
This leaves the kernel vulnerable to the standard
@@ -80,7 +81,7 @@ choice
and is disallowed.
config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
- bool "zero-init anything passed by reference (very strong)"
+ bool "zero-init everything passed by reference (very strong)"
depends on GCC_PLUGINS
depends on !(KASAN && KASAN_STACK)
select GCC_PLUGIN_STRUCTLEAK
@@ -91,33 +92,44 @@ choice
of uninitialized stack variable exploits and information
exposures.
+ As a side-effect, this keeps a lot of variables on the
+ stack that can otherwise be optimized out, so combining
+ this with CONFIG_KASAN_STACK can lead to a stack overflow
+ and is disallowed.
+
config INIT_STACK_ALL_PATTERN
- bool "0xAA-init everything on the stack (strongest)"
+ bool "pattern-init everything (strongest)"
depends on CC_HAS_AUTO_VAR_INIT_PATTERN
help
- Initializes everything on the stack with a 0xAA
- pattern. This is intended to eliminate all classes
- of uninitialized stack variable exploits and information
- exposures, even variables that were warned to have been
- left uninitialized.
+ Initializes everything on the stack (including padding)
+ with a specific debug value. This is intended to eliminate
+ all classes of uninitialized stack variable exploits and
+ information exposures, even variables that were warned about
+ having been left uninitialized.
Pattern initialization is known to provoke many existing bugs
related to uninitialized locals, e.g. pointers receive
- non-NULL values, buffer sizes and indices are very big.
+ non-NULL values, buffer sizes and indices are very big. The
+ pattern is situation-specific; Clang on 64-bit uses 0xAA
+ repeating for all types and padding except float and double
+ which use 0xFF repeating (-NaN). Clang on 32-bit uses 0xFF
+ repeating for all types and padding.
config INIT_STACK_ALL_ZERO
- bool "zero-init everything on the stack (strongest and safest)"
+ bool "zero-init everything (strongest and safest)"
depends on CC_HAS_AUTO_VAR_INIT_ZERO
help
- Initializes everything on the stack with a zero
- value. This is intended to eliminate all classes
- of uninitialized stack variable exploits and information
- exposures, even variables that were warned to have been
- left uninitialized.
-
- Zero initialization provides safe defaults for strings,
- pointers, indices and sizes, and is therefore
- more suitable as a security mitigation measure.
+ Initializes everything on the stack (including padding)
+ with a zero value. This is intended to eliminate all
+ classes of uninitialized stack variable exploits and
+ information exposures, even variables that were warned
+ about having been left uninitialized.
+
+ Zero initialization provides safe defaults for strings
+ (immediately NUL-terminated), pointers (NULL), indices
+ (index 0), and sizes (0 length), so it is therefore more
+ suitable as a production security mitigation than pattern
+ initialization.
endchoice
@@ -217,6 +229,25 @@ config INIT_ON_FREE_DEFAULT_ON
touching "cold" memory areas. Most cases see 3-5% impact. Some
synthetic workloads have measured as high as 8%.
+config CC_HAS_ZERO_CALL_USED_REGS
+ def_bool $(cc-option,-fzero-call-used-regs=used-gpr)
+
+config ZERO_CALL_USED_REGS
+ bool "Enable register zeroing on function exit"
+ depends on CC_HAS_ZERO_CALL_USED_REGS
+ help
+ At the end of functions, always zero any caller-used register
+ contents. This helps ensure that temporary values are not
+ leaked beyond the function boundary. This means that register
+ contents are less likely to be available for side channels
+ and information exposures. Additionally, this helps reduce the
+ number of useful ROP gadgets by about 20% (and removes compiler
+ generated "write-what-where" gadgets) in the resulting kernel
+ image. This has a less than 1% performance impact on most
+ workloads. Image size growth depends on architecture, and should
+ be evaluated for suitability. For example, x86_64 grows by less
+ than 1%, and arm64 grows by about 5%.
+
endmenu
endmenu
diff --git a/security/Makefile b/security/Makefile
index 47e432900e24..18121f8f85cd 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -4,16 +4,6 @@
#
obj-$(CONFIG_KEYS) += keys/
-subdir-$(CONFIG_SECURITY_SELINUX) += selinux
-subdir-$(CONFIG_SECURITY_SMACK) += smack
-subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
-subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
-subdir-$(CONFIG_SECURITY_YAMA) += yama
-subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin
-subdir-$(CONFIG_SECURITY_SAFESETID) += safesetid
-subdir-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown
-subdir-$(CONFIG_BPF_LSM) += bpf
-subdir-$(CONFIG_SECURITY_LANDLOCK) += landlock
# always enable default capabilities
obj-y += commoncap.o
@@ -36,5 +26,4 @@ obj-$(CONFIG_BPF_LSM) += bpf/
obj-$(CONFIG_SECURITY_LANDLOCK) += landlock/
# Object integrity file lists
-subdir-$(CONFIG_INTEGRITY) += integrity
obj-$(CONFIG_INTEGRITY) += integrity/
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index d0ceada99243..f3a9cc201c8c 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -6,7 +6,6 @@ config IMA
select SECURITYFS
select CRYPTO
select CRYPTO_HMAC
- select CRYPTO_MD5
select CRYPTO_SHA1
select CRYPTO_HASH_INFO
select TCG_TPM if HAS_IOMEM && !UML
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index f0e448ed1f9f..be965a8715e4 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -46,8 +46,11 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
/* current content of the policy */
extern int ima_policy_flag;
+/* bitset of digests algorithms allowed in the setxattr hook */
+extern atomic_t ima_setxattr_allowed_hash_algorithms;
+
/* set during initialization */
-extern int ima_hash_algo;
+extern int ima_hash_algo __ro_after_init;
extern int ima_sha1_idx __ro_after_init;
extern int ima_hash_algo_idx __ro_after_init;
extern int ima_extra_slots __ro_after_init;
@@ -198,6 +201,7 @@ static inline unsigned int ima_hash_key(u8 *digest)
hook(KEXEC_CMDLINE, kexec_cmdline) \
hook(KEY_CHECK, key) \
hook(CRITICAL_DATA, critical_data) \
+ hook(SETXATTR_CHECK, setxattr_check) \
hook(MAX_CHECK, none)
#define __ima_hook_enumify(ENUM, str) ENUM,
@@ -254,7 +258,7 @@ int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
const struct cred *cred, u32 secid, int mask,
enum ima_hooks func, int *pcr,
struct ima_template_desc **template_desc,
- const char *func_data);
+ const char *func_data, unsigned int *allowed_algos);
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
int ima_collect_measurement(struct integrity_iint_cache *iint,
struct file *file, void *buf, loff_t size,
@@ -264,11 +268,11 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
struct evm_ima_xattr_data *xattr_value,
int xattr_len, const struct modsig *modsig, int pcr,
struct ima_template_desc *template_desc);
-void process_buffer_measurement(struct user_namespace *mnt_userns,
- struct inode *inode, const void *buf, int size,
- const char *eventname, enum ima_hooks func,
- int pcr, const char *func_data,
- bool buf_hash);
+int process_buffer_measurement(struct user_namespace *mnt_userns,
+ struct inode *inode, const void *buf, int size,
+ const char *eventname, enum ima_hooks func,
+ int pcr, const char *func_data,
+ bool buf_hash, u8 *digest, size_t digest_len);
void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename);
int ima_alloc_init_template(struct ima_event_data *event_data,
@@ -285,10 +289,10 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
const struct cred *cred, u32 secid, enum ima_hooks func,
int mask, int flags, int *pcr,
struct ima_template_desc **template_desc,
- const char *func_data);
+ const char *func_data, unsigned int *allowed_algos);
void ima_init_policy(void);
void ima_update_policy(void);
-void ima_update_policy_flag(void);
+void ima_update_policy_flags(void);
ssize_t ima_parse_add_rule(char *);
void ima_delete_rules(void);
int ima_check_policy(void);
@@ -319,7 +323,7 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
enum ima_hooks func);
-enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
int xattr_len);
int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index d8e321cc6936..2c6c3a5228b5 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -172,6 +172,7 @@ err_out:
* @pcr: pointer filled in if matched measure policy sets pcr=
* @template_desc: pointer filled in if matched measure policy sets template=
* @func_data: func specific data, may be NULL
+ * @allowed_algos: allowlist of hash algorithms for the IMA xattr
*
* The policy is defined in terms of keypairs:
* subj=, obj=, type=, func=, mask=, fsmagic=
@@ -188,14 +189,15 @@ int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
const struct cred *cred, u32 secid, int mask,
enum ima_hooks func, int *pcr,
struct ima_template_desc **template_desc,
- const char *func_data)
+ const char *func_data, unsigned int *allowed_algos)
{
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
flags &= ima_policy_flag;
return ima_match_policy(mnt_userns, inode, cred, secid, func, mask,
- flags, pcr, template_desc, func_data);
+ flags, pcr, template_desc, func_data,
+ allowed_algos);
}
/*
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index ef9dcfce45d4..dbba51583e7c 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -77,8 +77,9 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
return 0;
security_task_getsecid_subj(current, &secid);
- return ima_match_policy(mnt_userns, inode, current_cred(), secid, func,
- mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
+ return ima_match_policy(mnt_userns, inode, current_cred(), secid,
+ func, mask, IMA_APPRAISE | IMA_HASH, NULL,
+ NULL, NULL, NULL);
}
static int ima_fix_xattr(struct dentry *dentry,
@@ -171,7 +172,7 @@ static void ima_cache_flags(struct integrity_iint_cache *iint,
}
}
-enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
int xattr_len)
{
struct signature_v2_hdr *sig;
@@ -184,7 +185,8 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
switch (xattr_value->type) {
case EVM_IMA_XATTR_DIGSIG:
sig = (typeof(sig))xattr_value;
- if (sig->version != 2 || xattr_len <= sizeof(*sig))
+ if (sig->version != 2 || xattr_len <= sizeof(*sig)
+ || sig->hash_algo >= HASH_ALGO__LAST)
return ima_hash_algo;
return sig->hash_algo;
break;
@@ -357,7 +359,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
process_buffer_measurement(&init_user_ns, NULL, digest, digestsize,
"blacklisted-hash", NONE,
- pcr, NULL, false);
+ pcr, NULL, false, NULL, 0);
}
return rc;
@@ -575,6 +577,66 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig)
clear_bit(IMA_DIGSIG, &iint->atomic_flags);
}
+/**
+ * validate_hash_algo() - Block setxattr with unsupported hash algorithms
+ * @dentry: object of the setxattr()
+ * @xattr_value: userland supplied xattr value
+ * @xattr_value_len: length of xattr_value
+ *
+ * The xattr value is mapped to its hash algorithm, and this algorithm
+ * must be built in the kernel for the setxattr to be allowed.
+ *
+ * Emit an audit message when the algorithm is invalid.
+ *
+ * Return: 0 on success, else an error.
+ */
+static int validate_hash_algo(struct dentry *dentry,
+ const struct evm_ima_xattr_data *xattr_value,
+ size_t xattr_value_len)
+{
+ char *path = NULL, *pathbuf = NULL;
+ enum hash_algo xattr_hash_algo;
+ const char *errmsg = "unavailable-hash-algorithm";
+ unsigned int allowed_hashes;
+
+ xattr_hash_algo = ima_get_hash_algo(xattr_value, xattr_value_len);
+
+ allowed_hashes = atomic_read(&ima_setxattr_allowed_hash_algorithms);
+
+ if (allowed_hashes) {
+ /* success if the algorithm is allowed in the ima policy */
+ if (allowed_hashes & (1U << xattr_hash_algo))
+ return 0;
+
+ /*
+ * We use a different audit message when the hash algorithm
+ * is denied by a policy rule, instead of not being built
+ * in the kernel image
+ */
+ errmsg = "denied-hash-algorithm";
+ } else {
+ if (likely(xattr_hash_algo == ima_hash_algo))
+ return 0;
+
+ /* allow any xattr using an algorithm built in the kernel */
+ if (crypto_has_alg(hash_algo_name[xattr_hash_algo], 0, 0))
+ return 0;
+ }
+
+ pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!pathbuf)
+ return -EACCES;
+
+ path = dentry_path(dentry, pathbuf, PATH_MAX);
+
+ integrity_audit_msg(AUDIT_INTEGRITY_DATA, d_inode(dentry), path,
+ "set_data", errmsg, -EACCES, 0);
+
+ kfree(pathbuf);
+
+ return -EACCES;
+}
+
int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
const void *xattr_value, size_t xattr_value_len)
{
@@ -592,9 +654,11 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG);
}
if (result == 1 || evm_revalidate_status(xattr_name)) {
+ result = validate_hash_algo(dentry, xvalue, xattr_value_len);
+ if (result)
+ return result;
+
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
- if (result == 1)
- result = 0;
}
return result;
}
diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c
index c985418698a4..f6aa0b47a772 100644
--- a/security/integrity/ima/ima_asymmetric_keys.c
+++ b/security/integrity/ima/ima_asymmetric_keys.c
@@ -62,5 +62,5 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
*/
process_buffer_measurement(&init_user_ns, NULL, payload, payload_len,
keyring->description, KEY_CHECK, 0,
- keyring->description, false);
+ keyring->description, false, NULL, 0);
}
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 5076a7d9d23e..b26fa67476b4 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -154,7 +154,8 @@ int __init ima_init(void)
ima_init_key_queue();
ima_measure_critical_data("kernel_info", "kernel_version",
- UTS_RELEASE, strlen(UTS_RELEASE), false);
+ UTS_RELEASE, strlen(UTS_RELEASE), false,
+ NULL, 0);
return rc;
}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 673833f94069..465865412100 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -35,7 +35,7 @@ int ima_appraise = IMA_APPRAISE_ENFORCE;
int ima_appraise;
#endif
-int ima_hash_algo = HASH_ALGO_SHA1;
+int __ro_after_init ima_hash_algo = HASH_ALGO_SHA1;
static int hash_setup_done;
static struct notifier_block ima_lsm_policy_notifier = {
@@ -76,6 +76,11 @@ out:
}
__setup("ima_hash=", hash_setup);
+enum hash_algo ima_get_current_hash_algo(void)
+{
+ return ima_hash_algo;
+}
+
/* Prevent mmap'ing a file execute that is already mmap'ed write */
static int mmap_violation_check(enum ima_hooks func, struct file *file,
char **pathbuf, const char **pathname,
@@ -210,6 +215,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
int xattr_len = 0;
bool violation_check;
enum hash_algo hash_algo;
+ unsigned int allowed_algos = 0;
if (!ima_policy_flag || !S_ISREG(inode->i_mode))
return 0;
@@ -219,7 +225,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
* Included is the appraise submask.
*/
action = ima_get_action(file_mnt_user_ns(file), inode, cred, secid,
- mask, func, &pcr, &template_desc, NULL);
+ mask, func, &pcr, &template_desc, NULL,
+ &allowed_algos);
violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
(ima_policy_flag & IMA_MEASURE));
if (!action && !violation_check)
@@ -356,6 +363,16 @@ static int process_measurement(struct file *file, const struct cred *cred,
if ((file->f_flags & O_DIRECT) && (iint->flags & IMA_PERMIT_DIRECTIO))
rc = 0;
+
+ /* Ensure the digest was generated using an allowed algorithm */
+ if (rc == 0 && must_appraise && allowed_algos != 0 &&
+ (allowed_algos & (1U << hash_algo)) == 0) {
+ rc = -EACCES;
+
+ integrity_audit_msg(AUDIT_INTEGRITY_DATA, file_inode(file),
+ pathname, "collect_data",
+ "denied-hash-algorithm", rc, 0);
+ }
out_locked:
if ((mask & MAY_WRITE) && test_bit(IMA_DIGSIG, &iint->atomic_flags) &&
!(iint->flags & IMA_NEW_FILE))
@@ -433,7 +450,7 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
inode = file_inode(vma->vm_file);
action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
current_cred(), secid, MAY_EXEC, MMAP_CHECK,
- &pcr, &template, NULL);
+ &pcr, &template, NULL, NULL);
/* Is the mmap'ed file in policy? */
if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
@@ -822,7 +839,7 @@ int ima_post_load_data(char *buf, loff_t size,
return 0;
}
-/*
+/**
* process_buffer_measurement - Measure the buffer or the buffer data hash
* @mnt_userns: user namespace of the mount the inode was found from
* @inode: inode associated with the object being measured (NULL for KEY_CHECK)
@@ -833,14 +850,20 @@ int ima_post_load_data(char *buf, loff_t size,
* @pcr: pcr to extend the measurement
* @func_data: func specific data, may be NULL
* @buf_hash: measure buffer data hash
+ * @digest: buffer digest will be written to
+ * @digest_len: buffer length
*
* Based on policy, either the buffer data or buffer data hash is measured
+ *
+ * Return: 0 if the buffer has been successfully measured, 1 if the digest
+ * has been written to the passed location but not added to a measurement entry,
+ * a negative value otherwise.
*/
-void process_buffer_measurement(struct user_namespace *mnt_userns,
- struct inode *inode, const void *buf, int size,
- const char *eventname, enum ima_hooks func,
- int pcr, const char *func_data,
- bool buf_hash)
+int process_buffer_measurement(struct user_namespace *mnt_userns,
+ struct inode *inode, const void *buf, int size,
+ const char *eventname, enum ima_hooks func,
+ int pcr, const char *func_data,
+ bool buf_hash, u8 *digest, size_t digest_len)
{
int ret = 0;
const char *audit_cause = "ENOMEM";
@@ -861,8 +884,11 @@ void process_buffer_measurement(struct user_namespace *mnt_userns,
int action = 0;
u32 secid;
- if (!ima_policy_flag)
- return;
+ if (digest && digest_len < digest_hash_len)
+ return -EINVAL;
+
+ if (!ima_policy_flag && !digest)
+ return -ENOENT;
template = ima_template_desc_buf();
if (!template) {
@@ -882,9 +908,9 @@ void process_buffer_measurement(struct user_namespace *mnt_userns,
security_task_getsecid_subj(current, &secid);
action = ima_get_action(mnt_userns, inode, current_cred(),
secid, 0, func, &pcr, &template,
- func_data);
- if (!(action & IMA_MEASURE))
- return;
+ func_data, NULL);
+ if (!(action & IMA_MEASURE) && !digest)
+ return -ENOENT;
}
if (!pcr)
@@ -914,6 +940,12 @@ void process_buffer_measurement(struct user_namespace *mnt_userns,
event_data.buf_len = digest_hash_len;
}
+ if (digest)
+ memcpy(digest, iint.ima_hash->digest, digest_hash_len);
+
+ if (!ima_policy_flag || (func && !(action & IMA_MEASURE)))
+ return 1;
+
ret = ima_alloc_init_template(&event_data, &entry, template);
if (ret < 0) {
audit_cause = "alloc_entry";
@@ -932,7 +964,7 @@ out:
func_measure_str(func),
audit_cause, ret, 0, ret);
- return;
+ return ret;
}
/**
@@ -956,7 +988,7 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
process_buffer_measurement(file_mnt_user_ns(f.file), file_inode(f.file),
buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
- NULL, false);
+ NULL, false, NULL, 0);
fdput(f);
}
@@ -967,23 +999,30 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
* @buf: pointer to buffer data
* @buf_len: length of buffer data (in bytes)
* @hash: measure buffer data hash
+ * @digest: buffer digest will be written to
+ * @digest_len: buffer length
*
* Measure data critical to the integrity of the kernel into the IMA log
* and extend the pcr. Examples of critical data could be various data
* structures, policies, and states stored in kernel memory that can
* impact the integrity of the system.
+ *
+ * Return: 0 if the buffer has been successfully measured, 1 if the digest
+ * has been written to the passed location but not added to a measurement entry,
+ * a negative value otherwise.
*/
-void ima_measure_critical_data(const char *event_label,
- const char *event_name,
- const void *buf, size_t buf_len,
- bool hash)
+int ima_measure_critical_data(const char *event_label,
+ const char *event_name,
+ const void *buf, size_t buf_len,
+ bool hash, u8 *digest, size_t digest_len)
{
if (!event_name || !event_label || !buf || !buf_len)
- return;
+ return -ENOPARAM;
- process_buffer_measurement(&init_user_ns, NULL, buf, buf_len, event_name,
- CRITICAL_DATA, 0, event_label,
- hash);
+ return process_buffer_measurement(&init_user_ns, NULL, buf, buf_len,
+ event_name, CRITICAL_DATA, 0,
+ event_label, hash, digest,
+ digest_len);
}
EXPORT_SYMBOL_GPL(ima_measure_critical_data);
@@ -1013,7 +1052,7 @@ static int __init init_ima(void)
pr_warn("Couldn't register LSM notifier, error %d\n", error);
if (!error)
- ima_update_policy_flag();
+ ima_update_policy_flags();
return error;
}
diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c
index 1e5c01916173..95cc31525c57 100644
--- a/security/integrity/ima/ima_mok.c
+++ b/security/integrity/ima/ima_mok.c
@@ -21,7 +21,7 @@ struct key *ima_blacklist_keyring;
/*
* Allocate the IMA blacklist keyring
*/
-__init int ima_mok_init(void)
+static __init int ima_mok_init(void)
{
struct key_restriction *restriction;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index fd5d46e511f1..87b9b71cb820 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -35,6 +35,7 @@
#define IMA_FSNAME 0x0200
#define IMA_KEYRINGS 0x0400
#define IMA_LABEL 0x0800
+#define IMA_VALIDATE_ALGOS 0x1000
#define UNKNOWN 0
#define MEASURE 0x0001 /* same as IMA_MEASURE */
@@ -52,6 +53,8 @@ int ima_policy_flag;
static int temp_ima_appraise;
static int build_ima_appraise __ro_after_init;
+atomic_t ima_setxattr_allowed_hash_algorithms;
+
#define MAX_LSM_RULES 6
enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
@@ -79,6 +82,7 @@ struct ima_rule_entry {
bool (*uid_op)(kuid_t, kuid_t); /* Handlers for operators */
bool (*fowner_op)(kuid_t, kuid_t); /* uid_eq(), uid_gt(), uid_lt() */
int pcr;
+ unsigned int allowed_algos; /* bitfield of allowed hash algorithms */
struct {
void *rule; /* LSM file metadata specific */
char *args_p; /* audit value */
@@ -91,6 +95,14 @@ struct ima_rule_entry {
};
/*
+ * sanity check in case the kernels gains more hash algorithms that can
+ * fit in an unsigned int
+ */
+static_assert(
+ 8 * sizeof(unsigned int) >= HASH_ALGO__LAST,
+ "The bitfield allowed_algos in ima_rule_entry is too small to contain all the supported hash algorithms, consider using a bigger type");
+
+/*
* Without LSM specific knowledge, the default policy can only be
* written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
*/
@@ -646,6 +658,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
* @pcr: set the pcr to extend
* @template_desc: the template that should be used for this rule
* @func_data: func specific data, may be NULL
+ * @allowed_algos: allowlist of hash algorithms for the IMA xattr
*
* Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
* conditions.
@@ -658,7 +671,7 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
const struct cred *cred, u32 secid, enum ima_hooks func,
int mask, int flags, int *pcr,
struct ima_template_desc **template_desc,
- const char *func_data)
+ const char *func_data, unsigned int *allowed_algos)
{
struct ima_rule_entry *entry;
int action = 0, actmask = flags | (flags << 1);
@@ -684,8 +697,11 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
action &= ~IMA_HASH;
if (ima_fail_unverifiable_sigs)
action |= IMA_FAIL_UNVERIFIABLE_SIGS;
- }
+ if (allowed_algos &&
+ entry->flags & IMA_VALIDATE_ALGOS)
+ *allowed_algos = entry->allowed_algos;
+ }
if (entry->action & IMA_DO_MASK)
actmask &= ~(entry->action | entry->action << 1);
@@ -706,24 +722,57 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
return action;
}
-/*
- * Initialize the ima_policy_flag variable based on the currently
- * loaded policy. Based on this flag, the decision to short circuit
- * out of a function or not call the function in the first place
- * can be made earlier.
+/**
+ * ima_update_policy_flags() - Update global IMA variables
+ *
+ * Update ima_policy_flag and ima_setxattr_allowed_hash_algorithms
+ * based on the currently loaded policy.
+ *
+ * With ima_policy_flag, the decision to short circuit out of a function
+ * or not call the function in the first place can be made earlier.
+ *
+ * With ima_setxattr_allowed_hash_algorithms, the policy can restrict the
+ * set of hash algorithms accepted when updating the security.ima xattr of
+ * a file.
+ *
+ * Context: called after a policy update and at system initialization.
*/
-void ima_update_policy_flag(void)
+void ima_update_policy_flags(void)
{
struct ima_rule_entry *entry;
+ int new_policy_flag = 0;
+ rcu_read_lock();
list_for_each_entry(entry, ima_rules, list) {
+ /*
+ * SETXATTR_CHECK rules do not implement a full policy check
+ * because rule checking would probably have an important
+ * performance impact on setxattr(). As a consequence, only one
+ * SETXATTR_CHECK can be active at a given time.
+ * Because we want to preserve that property, we set out to use
+ * atomic_cmpxchg. Either:
+ * - the atomic was non-zero: a setxattr hash policy is
+ * already enforced, we do nothing
+ * - the atomic was zero: no setxattr policy was set, enable
+ * the setxattr hash policy
+ */
+ if (entry->func == SETXATTR_CHECK) {
+ atomic_cmpxchg(&ima_setxattr_allowed_hash_algorithms,
+ 0, entry->allowed_algos);
+ /* SETXATTR_CHECK doesn't impact ima_policy_flag */
+ continue;
+ }
+
if (entry->action & IMA_DO_MASK)
- ima_policy_flag |= entry->action;
+ new_policy_flag |= entry->action;
}
+ rcu_read_unlock();
ima_appraise |= (build_ima_appraise | temp_ima_appraise);
if (!ima_appraise)
- ima_policy_flag &= ~IMA_APPRAISE;
+ new_policy_flag &= ~IMA_APPRAISE;
+
+ ima_policy_flag = new_policy_flag;
}
static int ima_appraise_flag(enum ima_hooks func)
@@ -889,7 +938,9 @@ void __init ima_init_policy(void)
ARRAY_SIZE(critical_data_rules),
IMA_DEFAULT_POLICY);
- ima_update_policy_flag();
+ atomic_set(&ima_setxattr_allowed_hash_algorithms, 0);
+
+ ima_update_policy_flags();
}
/* Make sure we have a valid policy, at least containing some rules. */
@@ -929,7 +980,7 @@ void ima_update_policy(void)
*/
kfree(arch_policy_entry);
}
- ima_update_policy_flag();
+ ima_update_policy_flags();
/* Custom IMA policy has been loaded */
ima_process_queued_keys();
@@ -946,7 +997,7 @@ enum {
Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq,
Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt,
Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
- Opt_appraise_type, Opt_appraise_flag,
+ Opt_appraise_type, Opt_appraise_flag, Opt_appraise_algos,
Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings,
Opt_label, Opt_err
};
@@ -981,6 +1032,7 @@ static const match_table_t policy_tokens = {
{Opt_fowner_lt, "fowner<%s"},
{Opt_appraise_type, "appraise_type=%s"},
{Opt_appraise_flag, "appraise_flag=%s"},
+ {Opt_appraise_algos, "appraise_algos=%s"},
{Opt_permit_directio, "permit_directio"},
{Opt_pcr, "pcr=%s"},
{Opt_template, "template=%s"},
@@ -1081,7 +1133,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
return false;
if (entry->action != APPRAISE &&
- entry->flags & (IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED | IMA_CHECK_BLACKLIST))
+ entry->flags & (IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED |
+ IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS))
return false;
/*
@@ -1111,7 +1164,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
IMA_UID | IMA_FOWNER | IMA_FSUUID |
IMA_INMASK | IMA_EUID | IMA_PCR |
IMA_FSNAME | IMA_DIGSIG_REQUIRED |
- IMA_PERMIT_DIRECTIO))
+ IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS))
return false;
break;
@@ -1123,7 +1176,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
IMA_INMASK | IMA_EUID | IMA_PCR |
IMA_FSNAME | IMA_DIGSIG_REQUIRED |
IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED |
- IMA_CHECK_BLACKLIST))
+ IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS))
return false;
break;
@@ -1161,6 +1214,23 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
return false;
break;
+ case SETXATTR_CHECK:
+ /* any action other than APPRAISE is unsupported */
+ if (entry->action != APPRAISE)
+ return false;
+
+ /* SETXATTR_CHECK requires an appraise_algos parameter */
+ if (!(entry->flags & IMA_VALIDATE_ALGOS))
+ return false;
+
+ /*
+ * full policies are not supported, they would have too
+ * much of a performance impact
+ */
+ if (entry->flags & ~(IMA_FUNC | IMA_VALIDATE_ALGOS))
+ return false;
+
+ break;
default:
return false;
}
@@ -1173,6 +1243,34 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
return true;
}
+static unsigned int ima_parse_appraise_algos(char *arg)
+{
+ unsigned int res = 0;
+ int idx;
+ char *token;
+
+ while ((token = strsep(&arg, ",")) != NULL) {
+ idx = match_string(hash_algo_name, HASH_ALGO__LAST, token);
+
+ if (idx < 0) {
+ pr_err("unknown hash algorithm \"%s\"",
+ token);
+ return 0;
+ }
+
+ if (!crypto_has_alg(hash_algo_name[idx], 0, 0)) {
+ pr_err("unavailable hash algorithm \"%s\", check your kernel configuration",
+ token);
+ return 0;
+ }
+
+ /* Add the hash algorithm to the 'allowed' bitfield */
+ res |= (1U << idx);
+ }
+
+ return res;
+}
+
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
{
struct audit_buffer *ab;
@@ -1294,6 +1392,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
entry->func = KEY_CHECK;
else if (strcmp(args[0].from, "CRITICAL_DATA") == 0)
entry->func = CRITICAL_DATA;
+ else if (strcmp(args[0].from, "SETXATTR_CHECK") == 0)
+ entry->func = SETXATTR_CHECK;
else
result = -EINVAL;
if (!result)
@@ -1508,6 +1608,25 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
else
result = -EINVAL;
break;
+ case Opt_appraise_algos:
+ ima_log_string(ab, "appraise_algos", args[0].from);
+
+ if (entry->allowed_algos) {
+ result = -EINVAL;
+ break;
+ }
+
+ entry->allowed_algos =
+ ima_parse_appraise_algos(args[0].from);
+ /* invalid or empty list of algorithms */
+ if (!entry->allowed_algos) {
+ result = -EINVAL;
+ break;
+ }
+
+ entry->flags |= IMA_VALIDATE_ALGOS;
+
+ break;
case Opt_permit_directio:
entry->flags |= IMA_PERMIT_DIRECTIO;
break;
@@ -1700,6 +1819,23 @@ static void ima_show_rule_opt_list(struct seq_file *m,
seq_printf(m, "%s%s", i ? "|" : "", opt_list->items[i]);
}
+static void ima_policy_show_appraise_algos(struct seq_file *m,
+ unsigned int allowed_hashes)
+{
+ int idx, list_size = 0;
+
+ for (idx = 0; idx < HASH_ALGO__LAST; idx++) {
+ if (!(allowed_hashes & (1U << idx)))
+ continue;
+
+ /* only add commas if the list contains multiple entries */
+ if (list_size++)
+ seq_puts(m, ",");
+
+ seq_puts(m, hash_algo_name[idx]);
+ }
+}
+
int ima_policy_show(struct seq_file *m, void *v)
{
struct ima_rule_entry *entry = v;
@@ -1811,6 +1947,12 @@ int ima_policy_show(struct seq_file *m, void *v)
seq_puts(m, " ");
}
+ if (entry->flags & IMA_VALIDATE_ALGOS) {
+ seq_puts(m, "appraise_algos=");
+ ima_policy_show_appraise_algos(m, entry->allowed_algos);
+ seq_puts(m, " ");
+ }
+
for (i = 0; i < MAX_LSM_RULES; i++) {
if (entry->lsm[i].rule) {
switch (i) {
diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c
index 979ef6c71f3d..93056c03bf5a 100644
--- a/security/integrity/ima/ima_queue_keys.c
+++ b/security/integrity/ima/ima_queue_keys.c
@@ -165,7 +165,7 @@ void ima_process_queued_keys(void)
entry->keyring_name,
KEY_CHECK, 0,
entry->keyring_name,
- false);
+ false, NULL, 0);
list_del(&entry->list);
ima_free_key_entry(entry);
}
diff --git a/security/selinux/ima.c b/security/selinux/ima.c
index 34d421861bfc..727c4e43219d 100644
--- a/security/selinux/ima.c
+++ b/security/selinux/ima.c
@@ -86,7 +86,8 @@ void selinux_ima_measure_state_locked(struct selinux_state *state)
}
ima_measure_critical_data("selinux", "selinux-state",
- state_str, strlen(state_str), false);
+ state_str, strlen(state_str), false,
+ NULL, 0);
kfree(state_str);
@@ -103,7 +104,8 @@ void selinux_ima_measure_state_locked(struct selinux_state *state)
}
ima_measure_critical_data("selinux", "selinux-policy-hash",
- policy, policy_len, true);
+ policy, policy_len, true,
+ NULL, 0);
vfree(policy);
}
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 98d985895ec8..31af29f669d2 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -897,6 +897,9 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
struct tomoyo_page_dump *dump)
{
struct page *page;
+#ifdef CONFIG_MMU
+ int ret;
+#endif
/* dump->data is released by tomoyo_find_next_domain(). */
if (!dump->data) {
@@ -909,11 +912,13 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
/*
* This is called at execve() time in order to dig around
* in the argv/environment of the new proceess
- * (represented by bprm). 'current' is the process doing
- * the execve().
+ * (represented by bprm).
*/
- if (get_user_pages_remote(bprm->mm, pos, 1,
- FOLL_FORCE, &page, NULL, NULL) <= 0)
+ mmap_read_lock(bprm->mm);
+ ret = get_user_pages_remote(bprm->mm, pos, 1,
+ FOLL_FORCE, &page, NULL, NULL);
+ mmap_read_unlock(bprm->mm);
+ if (ret <= 0)
return false;
#else
page = bprm->page[pos / PAGE_SIZE];
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index 6ddf646cda65..0d31a6d71468 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -514,7 +514,7 @@ static int ac97_bus_probe(struct device *dev)
return ret;
}
-static int ac97_bus_remove(struct device *dev)
+static void ac97_bus_remove(struct device *dev)
{
struct ac97_codec_device *adev = to_ac97_device(dev);
struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
@@ -522,7 +522,7 @@ static int ac97_bus_remove(struct device *dev)
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
- return ret;
+ return;
ret = adrv->remove(adev);
pm_runtime_put_noidle(dev);
@@ -530,8 +530,6 @@ static int ac97_bus_remove(struct device *dev)
ac97_put_disable_clk(adev);
pm_runtime_disable(dev);
-
- return ret;
}
static struct bus_type ac97_bus_type = {
diff --git a/sound/aoa/codecs/onyx.h b/sound/aoa/codecs/onyx.h
index 8a32c3c3d716..6c31b7373b78 100644
--- a/sound/aoa/codecs/onyx.h
+++ b/sound/aoa/codecs/onyx.h
@@ -6,7 +6,6 @@
*/
#ifndef __SND_AOA_CODEC_ONYX_H
#define __SND_AOA_CODEC_ONYX_H
-#include <stddef.h>
#include <linux/i2c.h>
#include <asm/pmac_low_i2c.h>
#include <asm/prom.h>
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index ac246dd3ab49..ab19a37e2a68 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -58,7 +58,6 @@
* and up to the hardware designer to not wire
* them up in some weird unusable way.
*/
-#include <stddef.h>
#include <linux/i2c.h>
#include <asm/pmac_low_i2c.h>
#include <asm/prom.h>
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c
index 002fb5bf220b..c9579d97fbab 100644
--- a/sound/aoa/soundbus/core.c
+++ b/sound/aoa/soundbus/core.c
@@ -104,7 +104,7 @@ static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env)
return retval;
}
-static int soundbus_device_remove(struct device *dev)
+static void soundbus_device_remove(struct device *dev)
{
struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
@@ -112,8 +112,6 @@ static int soundbus_device_remove(struct device *dev)
if (dev->driver && drv->remove)
drv->remove(soundbus_dev);
soundbus_dev_put(soundbus_dev);
-
- return 0;
}
static void soundbus_device_shutdown(struct device *dev)
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index a67e6685b00c..c17a19fe59ed 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -172,38 +172,28 @@ static const struct snd_pcm_ops pxa2xx_ac97_pcm_ops = {
.open = pxa2xx_ac97_pcm_open,
.close = pxa2xx_ac97_pcm_close,
.hw_params = pxa2xx_pcm_hw_params,
- .hw_free = pxa2xx_pcm_hw_free,
.prepare = pxa2xx_ac97_pcm_prepare,
.trigger = pxa2xx_pcm_trigger,
.pointer = pxa2xx_pcm_pointer,
- .mmap = pxa2xx_pcm_mmap,
};
static int pxa2xx_ac97_pcm_new(struct snd_card *card)
{
struct snd_pcm *pcm;
- int stream, ret;
+ int ret;
ret = snd_pcm_new(card, "PXA2xx-PCM", 0, 1, 1, &pcm);
if (ret)
goto out;
- pcm->private_free = pxa2xx_pcm_free_dma_buffers;
-
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
goto out;
- stream = SNDRV_PCM_STREAM_PLAYBACK;
- snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
- ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
- if (ret)
- goto out;
-
- stream = SNDRV_PCM_STREAM_CAPTURE;
- snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
- ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pxa2xx_ac97_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pxa2xx_ac97_pcm_ops);
+ ret = pxa2xx_pcm_preallocate_dma_buffer(pcm);
if (ret)
goto out;
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index e81083e1bc68..0a48805e513a 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -54,19 +54,10 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
if (ret)
return ret;
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
return 0;
}
EXPORT_SYMBOL(pxa2xx_pcm_hw_params);
-int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- snd_pcm_set_runtime_buffer(substream, NULL);
- return 0;
-}
-EXPORT_SYMBOL(pxa2xx_pcm_hw_free);
-
int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
return snd_dmaengine_pcm_trigger(substream, cmd);
@@ -131,56 +122,14 @@ int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
}
EXPORT_SYMBOL(pxa2xx_pcm_close);
-int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
- runtime->dma_addr, runtime->dma_bytes);
-}
-EXPORT_SYMBOL(pxa2xx_pcm_mmap);
-
-int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm)
{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
- buf->bytes = size;
- return 0;
-}
-EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
-void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
- dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers);
-
-void pxa2xx_soc_pcm_free(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- pxa2xx_pcm_free_dma_buffers(pcm);
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+ pcm->card->dev, size);
}
-EXPORT_SYMBOL(pxa2xx_soc_pcm_free);
+EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
@@ -193,21 +142,7 @@ int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
if (ret)
return ret;
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
- out:
- return ret;
+ return pxa2xx_pcm_preallocate_dma_buffer(pcm);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_new);
@@ -233,13 +168,6 @@ int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_params);
-int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- return pxa2xx_pcm_hw_free(substream);
-}
-EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_free);
-
int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -262,14 +190,6 @@ pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_pointer);
-int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return pxa2xx_pcm_mmap(substream, vma);
-}
-EXPORT_SYMBOL(pxa2xx_soc_pcm_mmap);
-
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx sound library");
MODULE_LICENSE("GPL");
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 21ce4c056a92..de514ec8c83d 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -47,8 +47,6 @@
* driver should be able to register multiple nodes
*/
-static DEFINE_MUTEX(device_mutex);
-
struct snd_compr_file {
unsigned long caps;
struct snd_compr_stream stream;
@@ -1179,6 +1177,7 @@ int snd_compress_new(struct snd_card *card, int device,
compr->card = card;
compr->device = device;
compr->direction = dirn;
+ mutex_init(&compr->lock);
snd_compress_set_id(compr, id);
@@ -1193,72 +1192,6 @@ int snd_compress_new(struct snd_card *card, int device,
}
EXPORT_SYMBOL_GPL(snd_compress_new);
-static int snd_compress_add_device(struct snd_compr *device)
-{
- int ret;
-
- if (!device->card)
- return -EINVAL;
-
- /* register the card */
- ret = snd_card_register(device->card);
- if (ret)
- goto out;
- return 0;
-
-out:
- pr_err("failed with %d\n", ret);
- return ret;
-
-}
-
-static int snd_compress_remove_device(struct snd_compr *device)
-{
- return snd_card_free(device->card);
-}
-
-/**
- * snd_compress_register - register compressed device
- *
- * @device: compressed device to register
- */
-int snd_compress_register(struct snd_compr *device)
-{
- int retval;
-
- if (device->name == NULL || device->ops == NULL)
- return -EINVAL;
-
- pr_debug("Registering compressed device %s\n", device->name);
- if (snd_BUG_ON(!device->ops->open))
- return -EINVAL;
- if (snd_BUG_ON(!device->ops->free))
- return -EINVAL;
- if (snd_BUG_ON(!device->ops->set_params))
- return -EINVAL;
- if (snd_BUG_ON(!device->ops->trigger))
- return -EINVAL;
-
- mutex_init(&device->lock);
-
- /* register a compressed card */
- mutex_lock(&device_mutex);
- retval = snd_compress_add_device(device);
- mutex_unlock(&device_mutex);
- return retval;
-}
-EXPORT_SYMBOL_GPL(snd_compress_register);
-
-int snd_compress_deregister(struct snd_compr *device)
-{
- pr_debug("Removing compressed device %s\n", device->name);
- mutex_lock(&device_mutex);
- snd_compress_remove_device(device);
- mutex_unlock(&device_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_compress_deregister);
-
MODULE_DESCRIPTION("ALSA Compressed offload framework");
MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/core/control_led.c b/sound/core/control_led.c
index 764058cc345d..a95332b2b90b 100644
--- a/sound/core/control_led.c
+++ b/sound/core/control_led.c
@@ -564,7 +564,7 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si
else {
for (; *s >= ' '; s++);
*s = '\0';
- strlcpy(id.name, buf2, sizeof(id.name));
+ strscpy(id.name, buf2, sizeof(id.name));
}
break;
}
diff --git a/sound/core/info.c b/sound/core/info.c
index 9fec3070f8ba..a451b24199c3 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -16,7 +16,6 @@
#include <linux/utsname.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
-#include <stdarg.h>
int snd_info_check_reserved_words(const char *str)
{
diff --git a/sound/core/init.c b/sound/core/init.c
index 1490568efdb0..ac335f5906c6 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -134,6 +134,9 @@ void snd_device_initialize(struct device *dev, struct snd_card *card)
}
EXPORT_SYMBOL_GPL(snd_device_initialize);
+static int snd_card_init(struct snd_card *card, struct device *parent,
+ int idx, const char *xid, struct module *module,
+ size_t extra_size);
static int snd_card_do_free(struct snd_card *card);
static const struct attribute_group card_dev_attr_group;
@@ -163,9 +166,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
{
struct snd_card *card;
int err;
-#ifdef CONFIG_SND_DEBUG
- char name[8];
-#endif
if (snd_BUG_ON(!card_ret))
return -EINVAL;
@@ -176,6 +176,74 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
if (!card)
return -ENOMEM;
+
+ err = snd_card_init(card, parent, idx, xid, module, extra_size);
+ if (err < 0) {
+ kfree(card);
+ return err;
+ }
+
+ *card_ret = card;
+ return 0;
+}
+EXPORT_SYMBOL(snd_card_new);
+
+static void __snd_card_release(struct device *dev, void *data)
+{
+ snd_card_free(data);
+}
+
+/**
+ * snd_devm_card_new - managed snd_card object creation
+ * @parent: the parent device object
+ * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
+ * @xid: card identification (ASCII string)
+ * @module: top level module for locking
+ * @extra_size: allocate this extra size after the main soundcard structure
+ * @card_ret: the pointer to store the created card instance
+ *
+ * This function works like snd_card_new() but manages the allocated resource
+ * via devres, i.e. you don't need to free explicitly.
+ *
+ * When a snd_card object is created with this function and registered via
+ * snd_card_register(), the very first devres action to call snd_card_free()
+ * is added automatically. In that way, the resource disconnection is assured
+ * at first, then released in the expected order.
+ */
+int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+ struct module *module, size_t extra_size,
+ struct snd_card **card_ret)
+{
+ struct snd_card *card;
+ int err;
+
+ *card_ret = NULL;
+ card = devres_alloc(__snd_card_release, sizeof(*card) + extra_size,
+ GFP_KERNEL);
+ if (!card)
+ return -ENOMEM;
+ card->managed = true;
+ err = snd_card_init(card, parent, idx, xid, module, extra_size);
+ if (err < 0) {
+ devres_free(card);
+ return err;
+ }
+
+ devres_add(parent, card);
+ *card_ret = card;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_devm_card_new);
+
+static int snd_card_init(struct snd_card *card, struct device *parent,
+ int idx, const char *xid, struct module *module,
+ size_t extra_size)
+{
+ int err;
+#ifdef CONFIG_SND_DEBUG
+ char name[8];
+#endif
+
if (extra_size > 0)
card->private_data = (char *)card + sizeof(struct snd_card);
if (xid)
@@ -197,7 +265,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
mutex_unlock(&snd_card_mutex);
dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
idx, snd_ecards_limit - 1, err);
- kfree(card);
return err;
}
set_bit(idx, snd_cards_lock); /* lock it */
@@ -256,8 +323,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
sprintf(name, "card%d", idx);
card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
#endif
-
- *card_ret = card;
return 0;
__error_ctl:
@@ -266,7 +331,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
put_device(&card->card_dev);
return err;
}
-EXPORT_SYMBOL(snd_card_new);
/**
* snd_card_ref - Get the card object from the index
@@ -481,6 +545,7 @@ EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
static int snd_card_do_free(struct snd_card *card)
{
+ card->releasing = true;
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
@@ -498,7 +563,8 @@ static int snd_card_do_free(struct snd_card *card)
#endif
if (card->release_completion)
complete(card->release_completion);
- kfree(card);
+ if (!card->managed)
+ kfree(card);
return 0;
}
@@ -539,6 +605,15 @@ int snd_card_free(struct snd_card *card)
DECLARE_COMPLETION_ONSTACK(released);
int ret;
+ /* The call of snd_card_free() is allowed from various code paths;
+ * a manual call from the driver and the call via devres_free, and
+ * we need to avoid double-free. Moreover, the release via devres
+ * may call snd_card_free() twice due to its nature, we need to have
+ * the check here at the beginning.
+ */
+ if (card->releasing)
+ return 0;
+
card->release_completion = &released;
ret = snd_card_free_when_closed(card);
if (ret)
@@ -745,6 +820,11 @@ int snd_card_add_dev_attr(struct snd_card *card,
}
EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
+static void trigger_card_free(void *data)
+{
+ snd_card_free(data);
+}
+
/**
* snd_card_register - register the soundcard
* @card: soundcard structure
@@ -768,6 +848,15 @@ int snd_card_register(struct snd_card *card)
if (err < 0)
return err;
card->registered = true;
+ } else {
+ if (card->managed)
+ devm_remove_action(card->dev, trigger_card_free, card);
+ }
+
+ if (card->managed) {
+ err = devm_add_action(card->dev, trigger_card_free, card);
+ if (err < 0)
+ return err;
}
err = snd_device_register_all(card);
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index c3d789ef6975..1f45ede023b4 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -97,3 +97,41 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
return size - result;
}
EXPORT_SYMBOL(snd_dma_pointer);
+
+struct snd_dma_data {
+ int dma;
+};
+
+static void __snd_release_dma(struct device *dev, void *data)
+{
+ struct snd_dma_data *p = data;
+
+ snd_dma_disable(p->dma);
+ free_dma(p->dma);
+}
+
+/**
+ * snd_devm_request_dma - the managed version of request_dma()
+ * @dev: the device pointer
+ * @dma: the dma number
+ * @name: the name string of the requester
+ *
+ * Returns zero on success, or a negative error code.
+ * The requested DMA will be automatically released at unbinding via devres.
+ */
+int snd_devm_request_dma(struct device *dev, int dma, const char *name)
+{
+ struct snd_dma_data *p;
+
+ if (request_dma(dma, name))
+ return -EBUSY;
+ p = devres_alloc(__snd_release_dma, sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ free_dma(dma);
+ return -ENOMEM;
+ }
+ p->dma = dma;
+ devres_add(dev, p);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_devm_request_dma);
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 439a358ecfe9..c7c943c661e6 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -29,12 +29,12 @@ static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
return (__force gfp_t)(unsigned long)dmab->dev.dev;
}
-static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
+static void *__snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
{
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
if (WARN_ON_ONCE(!ops || !ops->alloc))
- return -EINVAL;
+ return NULL;
return ops->alloc(dmab, size);
}
@@ -54,8 +54,6 @@ static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
int snd_dma_alloc_pages(int type, struct device *device, size_t size,
struct snd_dma_buffer *dmab)
{
- int err;
-
if (WARN_ON(!size))
return -ENXIO;
if (WARN_ON(!dmab))
@@ -65,12 +63,9 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
dmab->dev.type = type;
dmab->dev.dev = device;
dmab->bytes = 0;
- dmab->area = NULL;
dmab->addr = 0;
dmab->private_data = NULL;
- err = __snd_dma_alloc_pages(dmab, size);
- if (err < 0)
- return err;
+ dmab->area = __snd_dma_alloc_pages(dmab, size);
if (!dmab->area)
return -ENOMEM;
dmab->bytes = size;
@@ -127,6 +122,52 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
}
EXPORT_SYMBOL(snd_dma_free_pages);
+/* called by devres */
+static void __snd_release_pages(struct device *dev, void *res)
+{
+ snd_dma_free_pages(res);
+}
+
+/**
+ * snd_devm_alloc_pages - allocate the buffer and manage with devres
+ * @dev: the device pointer
+ * @type: the DMA buffer type
+ * @size: the buffer size to allocate
+ *
+ * Allocate buffer pages depending on the given type and manage using devres.
+ * The pages will be released automatically at the device removal.
+ *
+ * Unlike snd_dma_alloc_pages(), this function requires the real device pointer,
+ * hence it can't work with SNDRV_DMA_TYPE_CONTINUOUS or
+ * SNDRV_DMA_TYPE_VMALLOC type.
+ *
+ * The function returns the snd_dma_buffer object at success, or NULL if failed.
+ */
+struct snd_dma_buffer *
+snd_devm_alloc_pages(struct device *dev, int type, size_t size)
+{
+ struct snd_dma_buffer *dmab;
+ int err;
+
+ if (WARN_ON(type == SNDRV_DMA_TYPE_CONTINUOUS ||
+ type == SNDRV_DMA_TYPE_VMALLOC))
+ return NULL;
+
+ dmab = devres_alloc(__snd_release_pages, sizeof(*dmab), GFP_KERNEL);
+ if (!dmab)
+ return NULL;
+
+ err = snd_dma_alloc_pages(type, dev, size, dmab);
+ if (err < 0) {
+ devres_free(dmab);
+ return NULL;
+ }
+
+ devres_add(dev, dmab);
+ return dmab;
+}
+EXPORT_SYMBOL_GPL(snd_devm_alloc_pages);
+
/**
* snd_dma_buffer_mmap - perform mmap of the given DMA buffer
* @dmab: buffer allocation information
@@ -198,12 +239,14 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
/*
* Continuous pages allocator
*/
-static int snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
{
gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL);
+ void *p = alloc_pages_exact(size, gfp);
- dmab->area = alloc_pages_exact(size, gfp);
- return 0;
+ if (p)
+ dmab->addr = page_to_phys(virt_to_page(p));
+ return p;
}
static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
@@ -215,7 +258,7 @@ static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
return remap_pfn_range(area, area->vm_start,
- page_to_pfn(virt_to_page(dmab->area)),
+ dmab->addr >> PAGE_SHIFT,
area->vm_end - area->vm_start,
area->vm_page_prot);
}
@@ -229,12 +272,11 @@ static const struct snd_malloc_ops snd_dma_continuous_ops = {
/*
* VMALLOC allocator
*/
-static int snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size)
{
gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL | __GFP_HIGHMEM);
- dmab->area = __vmalloc(size, gfp);
- return 0;
+ return __vmalloc(size, gfp);
}
static void snd_dma_vmalloc_free(struct snd_dma_buffer *dmab)
@@ -248,11 +290,13 @@ static int snd_dma_vmalloc_mmap(struct snd_dma_buffer *dmab,
return remap_vmalloc_range(area, dmab->area, 0);
}
+#define get_vmalloc_page_addr(dmab, offset) \
+ page_to_phys(vmalloc_to_page((dmab)->area + (offset)))
+
static dma_addr_t snd_dma_vmalloc_get_addr(struct snd_dma_buffer *dmab,
size_t offset)
{
- return page_to_phys(vmalloc_to_page(dmab->area + offset)) +
- offset % PAGE_SIZE;
+ return get_vmalloc_page_addr(dmab, offset) + offset % PAGE_SIZE;
}
static struct page *snd_dma_vmalloc_get_page(struct snd_dma_buffer *dmab,
@@ -265,11 +309,23 @@ static unsigned int
snd_dma_vmalloc_get_chunk_size(struct snd_dma_buffer *dmab,
unsigned int ofs, unsigned int size)
{
- ofs %= PAGE_SIZE;
- size += ofs;
- if (size > PAGE_SIZE)
- size = PAGE_SIZE;
- return size - ofs;
+ unsigned int start, end;
+ unsigned long addr;
+
+ start = ALIGN_DOWN(ofs, PAGE_SIZE);
+ end = ofs + size - 1; /* the last byte address */
+ /* check page continuity */
+ addr = get_vmalloc_page_addr(dmab, start);
+ for (;;) {
+ start += PAGE_SIZE;
+ if (start > end)
+ break;
+ addr += PAGE_SIZE;
+ if (get_vmalloc_page_addr(dmab, start) != addr)
+ return start - ofs;
+ }
+ /* ok, all on continuous pages */
+ return size;
}
static const struct snd_malloc_ops snd_dma_vmalloc_ops = {
@@ -286,20 +342,20 @@ static const struct snd_malloc_ops snd_dma_vmalloc_ops = {
* IRAM allocator
*/
#ifdef CONFIG_GENERIC_ALLOCATOR
-static int snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size)
{
struct device *dev = dmab->dev.dev;
struct gen_pool *pool;
+ void *p;
if (dev->of_node) {
pool = of_gen_pool_get(dev->of_node, "iram", 0);
/* Assign the pool into private_data field */
dmab->private_data = pool;
- dmab->area = gen_pool_dma_alloc_align(pool, size, &dmab->addr,
- PAGE_SIZE);
- if (dmab->area)
- return 0;
+ p = gen_pool_dma_alloc_align(pool, size, &dmab->addr, PAGE_SIZE);
+ if (p)
+ return p;
}
/* Internal memory might have limited size and no enough space,
@@ -334,31 +390,31 @@ static const struct snd_malloc_ops snd_dma_iram_ops = {
};
#endif /* CONFIG_GENERIC_ALLOCATOR */
+#define DEFAULT_GFP \
+ (GFP_KERNEL | \
+ __GFP_COMP | /* compound page lets parts be mapped */ \
+ __GFP_NORETRY | /* don't trigger OOM-killer */ \
+ __GFP_NOWARN) /* no stack trace print - this call is non-critical */
+
/*
* Coherent device pages allocator
*/
-static int snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
{
- gfp_t gfp_flags;
-
- gfp_flags = GFP_KERNEL
- | __GFP_COMP /* compound page lets parts be mapped */
- | __GFP_NORETRY /* don't trigger OOM-killer */
- | __GFP_NOWARN; /* no stack trace print - this call is non-critical */
- dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr,
- gfp_flags);
+ void *p;
+
+ p = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
#ifdef CONFIG_X86
- if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
- set_memory_wc((unsigned long)dmab->area,
- PAGE_ALIGN(size) >> PAGE_SHIFT);
+ if (p && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
+ set_memory_wc((unsigned long)p, PAGE_ALIGN(size) >> PAGE_SHIFT);
#endif
- return 0;
+ return p;
}
static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
{
#ifdef CONFIG_X86
- if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC)
+ if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
set_memory_wb((unsigned long)dmab->area,
PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
#endif
@@ -368,6 +424,10 @@ static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
static int snd_dma_dev_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
+#ifdef CONFIG_X86
+ if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
+ area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+#endif
return dma_mmap_coherent(dmab->dev.dev, area,
dmab->area, dmab->addr, dmab->bytes);
}
@@ -377,6 +437,37 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
.free = snd_dma_dev_free,
.mmap = snd_dma_dev_mmap,
};
+
+/*
+ * Write-combined pages
+ */
+#ifdef CONFIG_X86
+/* On x86, share the same ops as the standard dev ops */
+#define snd_dma_wc_ops snd_dma_dev_ops
+#else /* CONFIG_X86 */
+static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+ return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
+}
+
+static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
+{
+ dma_free_wc(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
+}
+
+static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
+ struct vm_area_struct *area)
+{
+ return dma_mmap_wc(dmab->dev.dev, area,
+ dmab->area, dmab->addr, dmab->bytes);
+}
+
+static const struct snd_malloc_ops snd_dma_wc_ops = {
+ .alloc = snd_dma_wc_alloc,
+ .free = snd_dma_wc_free,
+ .mmap = snd_dma_wc_mmap,
+};
+#endif /* CONFIG_X86 */
#endif /* CONFIG_HAS_DMA */
/*
@@ -387,14 +478,14 @@ static const struct snd_malloc_ops *dma_ops[] = {
[SNDRV_DMA_TYPE_VMALLOC] = &snd_dma_vmalloc_ops,
#ifdef CONFIG_HAS_DMA
[SNDRV_DMA_TYPE_DEV] = &snd_dma_dev_ops,
- [SNDRV_DMA_TYPE_DEV_UC] = &snd_dma_dev_ops,
+ [SNDRV_DMA_TYPE_DEV_WC] = &snd_dma_wc_ops,
#ifdef CONFIG_GENERIC_ALLOCATOR
[SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
#endif /* CONFIG_GENERIC_ALLOCATOR */
#endif /* CONFIG_HAS_DMA */
#ifdef CONFIG_SND_DMA_SGBUF
[SNDRV_DMA_TYPE_DEV_SG] = &snd_dma_sg_ops,
- [SNDRV_DMA_TYPE_DEV_UC_SG] = &snd_dma_sg_ops,
+ [SNDRV_DMA_TYPE_DEV_WC_SG] = &snd_dma_sg_ops,
#endif
};
diff --git a/sound/core/memalloc_local.h b/sound/core/memalloc_local.h
index dbea7f2aed07..9f2e0a608b49 100644
--- a/sound/core/memalloc_local.h
+++ b/sound/core/memalloc_local.h
@@ -3,7 +3,7 @@
#define __MEMALLOC_LOCAL_H
struct snd_malloc_ops {
- int (*alloc)(struct snd_dma_buffer *dmab, size_t size);
+ void *(*alloc)(struct snd_dma_buffer *dmab, size_t size);
void (*free)(struct snd_dma_buffer *dmab);
dma_addr_t (*get_addr)(struct snd_dma_buffer *dmab, size_t offset);
struct page *(*get_page)(struct snd_dma_buffer *dmab, size_t offset);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 7d5883432085..a144a3f68e9e 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1746,7 +1746,7 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream,
channels = params_channels(params);
frame_size = snd_pcm_format_size(format, channels);
if (frame_size > 0)
- params->fifo_size /= (unsigned)frame_size;
+ params->fifo_size /= frame_size;
}
return 0;
}
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index d7621ed105bd..7fbd1ccbb5b0 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -67,7 +67,8 @@ static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)
*
* the minimum size is snd_minimum_buffer. it should be power of 2.
*/
-static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
+static int preallocate_pcm_pages(struct snd_pcm_substream *substream,
+ size_t size, bool no_fallback)
{
struct snd_dma_buffer *dmab = &substream->dma_buffer;
struct snd_card *card = substream->pcm->card;
@@ -79,6 +80,8 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
size, dmab);
if (err != -ENOMEM)
return err;
+ if (no_fallback)
+ break;
size >>= 1;
} while (size >= snd_minimum_buffer);
dmab->bytes = 0; /* tell error */
@@ -86,7 +89,7 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
substream->pcm->card->number, substream->pcm->device,
substream->stream ? 'c' : 'p', substream->number,
substream->pcm->name, orig_size);
- return 0;
+ return -ENOMEM;
}
/**
@@ -222,18 +225,31 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
/*
* pre-allocate the buffer and create a proc file for the substream
*/
-static void preallocate_pages(struct snd_pcm_substream *substream,
+static int preallocate_pages(struct snd_pcm_substream *substream,
int type, struct device *data,
size_t size, size_t max, bool managed)
{
+ int err;
+
if (snd_BUG_ON(substream->dma_buffer.dev.type))
- return;
+ return -EINVAL;
substream->dma_buffer.dev.type = type;
substream->dma_buffer.dev.dev = data;
- if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
- preallocate_pcm_pages(substream, size);
+ if (size > 0) {
+ if (!max) {
+ /* no fallback, only also inform -ENOMEM */
+ err = preallocate_pcm_pages(substream, size, true);
+ if (err < 0)
+ return err;
+ } else if (preallocate_dma &&
+ substream->number < maximum_substreams) {
+ err = preallocate_pcm_pages(substream, size, false);
+ if (err < 0 && err != -ENOMEM)
+ return err;
+ }
+ }
if (substream->dma_buffer.bytes > 0)
substream->buffer_bytes_max = substream->dma_buffer.bytes;
@@ -242,17 +258,22 @@ static void preallocate_pages(struct snd_pcm_substream *substream,
preallocate_info_init(substream);
if (managed)
substream->managed_buffer_alloc = 1;
+ return 0;
}
-static void preallocate_pages_for_all(struct snd_pcm *pcm, int type,
+static int preallocate_pages_for_all(struct snd_pcm *pcm, int type,
void *data, size_t size, size_t max,
bool managed)
{
struct snd_pcm_substream *substream;
- int stream;
+ int stream, err;
- for_each_pcm_substream(pcm, stream, substream)
- preallocate_pages(substream, type, data, size, max, managed);
+ for_each_pcm_substream(pcm, stream, substream) {
+ err = preallocate_pages(substream, type, data, size, max, managed);
+ if (err < 0)
+ return err;
+ }
+ return 0;
}
/**
@@ -309,11 +330,22 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
* When a buffer is actually allocated before the PCM hw_params call, it
* turns on the runtime buffer_changed flag for drivers changing their h/w
* parameters accordingly.
+ *
+ * When @size is non-zero and @max is zero, this tries to allocate for only
+ * the exact buffer size without fallback, and may return -ENOMEM.
+ * Otherwise, the function tries to allocate smaller chunks if the allocation
+ * fails. This is the behavior of snd_pcm_set_fixed_buffer().
+ *
+ * When both @size and @max are zero, the function only sets up the buffer
+ * for later dynamic allocations. It's used typically for buffers with
+ * SNDRV_DMA_TYPE_VMALLOC type.
+ *
+ * Upon successful buffer allocation and setup, the function returns 0.
*/
-void snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
+int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type,
struct device *data, size_t size, size_t max)
{
- preallocate_pages(substream, type, data, size, max, true);
+ return preallocate_pages(substream, type, data, size, max, true);
}
EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
@@ -329,11 +361,11 @@ EXPORT_SYMBOL(snd_pcm_set_managed_buffer);
* Do pre-allocation to all substreams of the given pcm for the specified DMA
* type and size, and set the managed_buffer_alloc flag to each substream.
*/
-void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
- struct device *data,
- size_t size, size_t max)
+int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type,
+ struct device *data,
+ size_t size, size_t max)
{
- preallocate_pages_for_all(pcm, type, data, size, max, true);
+ return preallocate_pages_for_all(pcm, type, data, size, max, true);
}
EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all);
@@ -376,6 +408,9 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
substream->dma_buffer.bytes >= size) {
dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
} else {
+ /* dma_max=0 means the fixed size preallocation */
+ if (substream->dma_buffer.area && !substream->dma_max)
+ return -ENOMEM;
dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
if (! dmab)
return -ENOMEM;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 71323d807dbf..d233cb3b41d8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -243,13 +243,18 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
static bool hw_support_mmap(struct snd_pcm_substream *substream)
{
+ struct snd_dma_buffer *dmabuf;
+
if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
return false;
if (substream->ops->mmap || substream->ops->page)
return true;
- switch (substream->dma_buffer.dev.type) {
+ dmabuf = snd_pcm_get_dma_buf(substream);
+ if (!dmabuf)
+ dmabuf = &substream->dma_buffer;
+ switch (dmabuf->dev.type) {
case SNDRV_DMA_TYPE_UNKNOWN:
/* we can't know the device, so just assume that the driver does
* everything right
@@ -259,7 +264,7 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
case SNDRV_DMA_TYPE_VMALLOC:
return true;
default:
- return dma_can_mmap(substream->dma_buffer.dev.dev);
+ return dma_can_mmap(dmabuf->dev.dev);
}
}
@@ -3616,6 +3621,12 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
{
+ /* If drivers require the explicit sync (typically for non-coherent
+ * pages), we have to disable the mmap of status and control data
+ * to enforce the control via SYNC_PTR ioctl.
+ */
+ if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_EXPLICIT_SYNC)
+ return false;
/* See pcm_control_mmap_allowed() below.
* Since older alsa-lib requires both status and control mmaps to be
* coupled, we have to disable the status mmap for old alsa-lib, too.
@@ -3630,6 +3641,9 @@ static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
{
if (pcm_file->no_compat_mmap)
return false;
+ /* see above */
+ if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_EXPLICIT_SYNC)
+ return false;
/* Disallow the control mmap when SYNC_APPLPTR flag is set;
* it enforces the user-space to fall back to snd_pcm_sync_ptr(),
* thus it effectively assures the manual update of appl_ptr.
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index ac760b1e3d12..8c18d8c4177e 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -20,15 +20,15 @@
are redirected to output port immediately.
The routing can be done via aconnect program in alsa-utils.
- Each client has a static client number 62 (= SNDRV_SEQ_CLIENT_DUMMY).
+ Each client has a static client number 14 (= SNDRV_SEQ_CLIENT_DUMMY).
If you want to auto-load this module, you may add the following alias
in your /etc/conf.modules file.
- alias snd-seq-client-62 snd-seq-dummy
+ alias snd-seq-client-14 snd-seq-dummy
- The module is loaded on demand for client 62, or /proc/asound/seq/
+ The module is loaded on demand for client 14, or /proc/asound/seq/
is accessed. If you don't need this module to be loaded, alias
- snd-seq-client-62 as "off". This will help modprobe.
+ snd-seq-client-14 as "off". This will help modprobe.
The number of ports to be created can be specified via the module
parameter "ports". For example, to create four ports, add the
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index 232cf3f1bcb3..8352a5cdb19f 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -43,8 +43,8 @@ static void snd_dma_sg_free(struct snd_dma_buffer *dmab)
dmab->area = NULL;
tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
- if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG)
- tmpb.dev.type = SNDRV_DMA_TYPE_DEV_UC;
+ if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
+ tmpb.dev.type = SNDRV_DMA_TYPE_DEV_WC;
tmpb.dev.dev = sgbuf->dev;
for (i = 0; i < sgbuf->pages; i++) {
if (!(sgbuf->table[i].addr & ~PAGE_MASK))
@@ -63,7 +63,7 @@ static void snd_dma_sg_free(struct snd_dma_buffer *dmab)
#define MAX_ALLOC_PAGES 32
-static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
{
struct snd_sg_buf *sgbuf;
unsigned int i, pages, chunk, maxpages;
@@ -72,12 +72,13 @@ static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
struct page **pgtable;
int type = SNDRV_DMA_TYPE_DEV;
pgprot_t prot = PAGE_KERNEL;
+ void *area;
dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
if (!sgbuf)
- return -ENOMEM;
- if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) {
- type = SNDRV_DMA_TYPE_DEV_UC;
+ return NULL;
+ if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG) {
+ type = SNDRV_DMA_TYPE_DEV_WC;
#ifdef pgprot_noncached
prot = pgprot_noncached(PAGE_KERNEL);
#endif
@@ -127,14 +128,14 @@ static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size)
}
sgbuf->size = size;
- dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot);
- if (! dmab->area)
+ area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot);
+ if (!area)
goto _failed;
- return 0;
+ return area;
_failed:
snd_dma_sg_free(dmab); /* free the table */
- return -ENOMEM;
+ return NULL;
}
static dma_addr_t snd_dma_sg_get_addr(struct snd_dma_buffer *dmab,
@@ -182,10 +183,19 @@ static unsigned int snd_dma_sg_get_chunk_size(struct snd_dma_buffer *dmab,
return size;
}
+static int snd_dma_sg_mmap(struct snd_dma_buffer *dmab,
+ struct vm_area_struct *area)
+{
+ if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
+ area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+ return -ENOENT; /* continue with the default mmap handler */
+}
+
const struct snd_malloc_ops snd_dma_sg_ops = {
.alloc = snd_dma_sg_alloc,
.free = snd_dma_sg_free,
.get_addr = snd_dma_sg_get_addr,
.get_page = snd_dma_sg_get_page,
.get_chunk_size = snd_dma_sg_get_chunk_size,
+ .mmap = snd_dma_sg_mmap,
};
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 7141f73cddd3..ca4cdf666f82 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -102,7 +102,7 @@ config SND_ALOOP
configured number of substreams (see the pcm_substreams module
parameter).
- The loopback device allows time sychronization with an external
+ The loopback device allows time synchronization with an external
timing source using the time shift universal control (+-20%
of system time).
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 80b814b9922a..9b4a7cdb103a 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -1712,8 +1712,8 @@ static int loopback_probe(struct platform_device *devptr)
int dev = devptr->id;
int err;
- err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct loopback), &card);
+ err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct loopback), &card);
if (err < 0)
return err;
loopback = card->private_data;
@@ -1730,13 +1730,13 @@ static int loopback_probe(struct platform_device *devptr)
err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]);
if (err < 0)
- goto __nodev;
+ return err;
err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]);
if (err < 0)
- goto __nodev;
+ return err;
err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0);
if (err < 0)
- goto __nodev;
+ return err;
loopback_cable_proc_new(loopback, 0);
loopback_cable_proc_new(loopback, 1);
loopback_timer_source_proc_new(loopback);
@@ -1744,18 +1744,9 @@ static int loopback_probe(struct platform_device *devptr)
strcpy(card->shortname, "Loopback");
sprintf(card->longname, "Loopback %i", dev + 1);
err = snd_card_register(card);
- if (!err) {
- platform_set_drvdata(devptr, card);
- return 0;
- }
- __nodev:
- snd_card_free(card);
- return err;
-}
-
-static int loopback_remove(struct platform_device *devptr)
-{
- snd_card_free(platform_get_drvdata(devptr));
+ if (err < 0)
+ return err;
+ platform_set_drvdata(devptr, card);
return 0;
}
@@ -1786,7 +1777,6 @@ static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume);
static struct platform_driver loopback_driver = {
.probe = loopback_probe,
- .remove = loopback_remove,
.driver = {
.name = SND_LOOPBACK_DRIVER,
.pm = LOOPBACK_PM_OPS,
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 01a3eab50d7b..2a7fc49c1a7c 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -1025,8 +1025,8 @@ static int snd_dummy_probe(struct platform_device *devptr)
int idx, err;
int dev = devptr->id;
- err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_dummy), &card);
+ err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_dummy), &card);
if (err < 0)
return err;
dummy = card->private_data;
@@ -1047,7 +1047,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]);
if (err < 0)
- goto __nodev;
+ return err;
}
dummy->pcm_hw = dummy_pcm_hardware;
@@ -1078,7 +1078,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
err = snd_card_dummy_new_mixer(dummy);
if (err < 0)
- goto __nodev;
+ return err;
strcpy(card->driver, "Dummy");
strcpy(card->shortname, "Dummy");
sprintf(card->longname, "Dummy %i", dev + 1);
@@ -1086,18 +1086,9 @@ static int snd_dummy_probe(struct platform_device *devptr)
dummy_proc_init(dummy);
err = snd_card_register(card);
- if (err == 0) {
- platform_set_drvdata(devptr, card);
- return 0;
- }
- __nodev:
- snd_card_free(card);
- return err;
-}
-
-static int snd_dummy_remove(struct platform_device *devptr)
-{
- snd_card_free(platform_get_drvdata(devptr));
+ if (err < 0)
+ return err;
+ platform_set_drvdata(devptr, card);
return 0;
}
@@ -1128,7 +1119,6 @@ static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume);
static struct platform_driver snd_dummy_driver = {
.probe = snd_dummy_probe,
- .remove = snd_dummy_remove,
.driver = {
.name = SND_DUMMY_DRIVER,
.pm = SND_DUMMY_PM_OPS,
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index d0b55dbb411a..3398aee33baa 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -59,8 +59,8 @@ static int snd_mpu401_create(struct device *devptr, int dev,
snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
*rcard = NULL;
- err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+ 0, &card);
if (err < 0)
return err;
strcpy(card->driver, "MPU-401 UART");
@@ -76,15 +76,11 @@ static int snd_mpu401_create(struct device *devptr, int dev,
irq[dev], NULL);
if (err < 0) {
printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
- goto _err;
+ return err;
}
*rcard = card;
return 0;
-
- _err:
- snd_card_free(card);
- return err;
}
static int snd_mpu401_probe(struct platform_device *devptr)
@@ -105,25 +101,16 @@ static int snd_mpu401_probe(struct platform_device *devptr)
if (err < 0)
return err;
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
platform_set_drvdata(devptr, card);
return 0;
}
-static int snd_mpu401_remove(struct platform_device *devptr)
-{
- snd_card_free(platform_get_drvdata(devptr));
- return 0;
-}
-
#define SND_MPU401_DRIVER "snd_mpu401"
static struct platform_driver snd_mpu401_driver = {
.probe = snd_mpu401_probe,
- .remove = snd_mpu401_remove,
.driver = {
.name = SND_MPU401_DRIVER,
},
@@ -184,10 +171,8 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
if (err < 0)
return err;
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pnp_set_drvdata(pnp_dev, card);
snd_mpu401_devices++;
++dev;
@@ -196,19 +181,10 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
return -ENODEV;
}
-static void snd_mpu401_pnp_remove(struct pnp_dev *dev)
-{
- struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev);
-
- snd_card_disconnect(card);
- snd_card_free_when_closed(card);
-}
-
static struct pnp_driver snd_mpu401_pnp_driver = {
.name = "mpu401",
.id_table = snd_mpu401_pnpids,
.probe = snd_mpu401_pnp_probe,
- .remove = snd_mpu401_pnp_remove,
};
#else
static struct pnp_driver snd_mpu401_pnp_driver;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 0e95b08d34d6..11235baaf6fa 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -566,13 +566,15 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
*/
static int snd_mtpav_get_ISA(struct mtpav *mcard)
{
- mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI");
+ mcard->res_port = devm_request_region(mcard->card->dev, port, 3,
+ "MotuMTPAV MIDI");
if (!mcard->res_port) {
snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
return -EBUSY;
}
mcard->port = port;
- if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) {
+ if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0,
+ "MOTU MTPAV", mcard)) {
snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
return -EBUSY;
}
@@ -667,9 +669,6 @@ static void snd_mtpav_free(struct snd_card *card)
if (crd->istimer > 0)
snd_mtpav_remove_output_timer(crd);
spin_unlock_irqrestore(&crd->spinlock, flags);
- if (crd->irq >= 0)
- free_irq(crd->irq, (void *)crd);
- release_and_free_resource(crd->res_port);
}
/*
@@ -680,8 +679,8 @@ static int snd_mtpav_probe(struct platform_device *dev)
int err;
struct mtpav *mtp_card;
- err = snd_card_new(&dev->dev, index, id, THIS_MODULE,
- sizeof(*mtp_card), &card);
+ err = snd_devm_card_new(&dev->dev, index, id, THIS_MODULE,
+ sizeof(*mtp_card), &card);
if (err < 0)
return err;
@@ -698,13 +697,13 @@ static int snd_mtpav_probe(struct platform_device *dev)
err = snd_mtpav_get_RAWMIDI(mtp_card);
if (err < 0)
- goto __error;
+ return err;
mtp_card->inmidiport = mtp_card->num_ports + MTPAV_PIDX_BROADCAST;
err = snd_mtpav_get_ISA(mtp_card);
if (err < 0)
- goto __error;
+ return err;
strcpy(card->driver, "MTPAV");
strcpy(card->shortname, "MTPAV on parallel port");
@@ -715,28 +714,17 @@ static int snd_mtpav_probe(struct platform_device *dev)
err = snd_card_register(mtp_card->card);
if (err < 0)
- goto __error;
+ return err;
platform_set_drvdata(dev, card);
printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
return 0;
-
- __error:
- snd_card_free(card);
- return err;
-}
-
-static int snd_mtpav_remove(struct platform_device *devptr)
-{
- snd_card_free(platform_get_drvdata(devptr));
- return 0;
}
#define SND_MTPAV_DRIVER "snd_mtpav"
static struct platform_driver snd_mtpav_driver = {
.probe = snd_mtpav_probe,
- .remove = snd_mtpav_remove,
.driver = {
.name = SND_MTPAV_DRIVER,
},
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 7689fa2f9531..c7be1c395bcb 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -42,9 +42,8 @@ struct snd_pcsp pcsp_chip;
static int snd_pcsp_create(struct snd_card *card)
{
- static const struct snd_device_ops ops = { };
unsigned int resolution = hrtimer_resolution;
- int err, div, min_div, order;
+ int div, min_div, order;
if (!nopcm) {
if (resolution > PCSP_MAX_PERIOD_NS) {
@@ -83,15 +82,18 @@ static int snd_pcsp_create(struct snd_card *card)
pcsp_chip.port = 0x61;
pcsp_chip.irq = -1;
pcsp_chip.dma = -1;
-
- /* Register device */
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops);
- if (err < 0)
- return err;
+ card->private_data = &pcsp_chip;
return 0;
}
+static void pcsp_stop_beep(struct snd_pcsp *chip);
+
+static void alsa_card_pcsp_free(struct snd_card *card)
+{
+ pcsp_stop_beep(card->private_data);
+}
+
static int snd_card_pcsp_probe(int devnum, struct device *dev)
{
struct snd_card *card;
@@ -103,22 +105,22 @@ static int snd_card_pcsp_probe(int devnum, struct device *dev)
hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
pcsp_chip.timer.function = pcsp_do_timer;
- err = snd_card_new(dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(dev, index, id, THIS_MODULE, 0, &card);
if (err < 0)
return err;
err = snd_pcsp_create(card);
if (err < 0)
- goto free_card;
+ return err;
if (!nopcm) {
err = snd_pcsp_new_pcm(&pcsp_chip);
if (err < 0)
- goto free_card;
+ return err;
}
err = snd_pcsp_new_mixer(&pcsp_chip, nopcm);
if (err < 0)
- goto free_card;
+ return err;
strcpy(card->driver, "PC-Speaker");
strcpy(card->shortname, "pcsp");
@@ -127,13 +129,10 @@ static int snd_card_pcsp_probe(int devnum, struct device *dev)
err = snd_card_register(card);
if (err < 0)
- goto free_card;
+ return err;
+ card->private_free = alsa_card_pcsp_free;
return 0;
-
-free_card:
- snd_card_free(card);
- return err;
}
static int alsa_card_pcsp_init(struct device *dev)
@@ -155,11 +154,6 @@ static int alsa_card_pcsp_init(struct device *dev)
return 0;
}
-static void alsa_card_pcsp_exit(struct snd_pcsp *chip)
-{
- snd_card_free(chip->card);
-}
-
static int pcsp_probe(struct platform_device *dev)
{
int err;
@@ -169,23 +163,13 @@ static int pcsp_probe(struct platform_device *dev)
return err;
err = alsa_card_pcsp_init(&dev->dev);
- if (err < 0) {
- pcspkr_input_remove(pcsp_chip.input_dev);
+ if (err < 0)
return err;
- }
platform_set_drvdata(dev, &pcsp_chip);
return 0;
}
-static int pcsp_remove(struct platform_device *dev)
-{
- struct snd_pcsp *chip = platform_get_drvdata(dev);
- pcspkr_input_remove(chip->input_dev);
- alsa_card_pcsp_exit(chip);
- return 0;
-}
-
static void pcsp_stop_beep(struct snd_pcsp *chip)
{
pcsp_sync_stop(chip);
@@ -218,7 +202,6 @@ static struct platform_driver pcsp_platform_driver = {
.pm = PCSP_PM_OPS,
},
.probe = pcsp_probe,
- .remove = pcsp_remove,
.shutdown = pcsp_shutdown,
};
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
index e79603fe743d..5a799f7f00a2 100644
--- a/sound/drivers/pcsp/pcsp_input.c
+++ b/sound/drivers/pcsp/pcsp_input.c
@@ -78,7 +78,7 @@ int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
{
int err;
- struct input_dev *input_dev = input_allocate_device();
+ struct input_dev *input_dev = devm_input_allocate_device(dev);
if (!input_dev)
return -ENOMEM;
@@ -95,19 +95,9 @@ int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
input_dev->event = pcspkr_input_event;
err = input_register_device(input_dev);
- if (err) {
- input_free_device(input_dev);
+ if (err)
return err;
- }
*rdev = input_dev;
return 0;
}
-
-int pcspkr_input_remove(struct input_dev *dev)
-{
- pcspkr_stop_sound();
- input_unregister_device(dev); /* this also does kfree() */
-
- return 0;
-}
diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
index e80079b38a56..42bfc9eab6eb 100644
--- a/sound/drivers/pcsp/pcsp_input.h
+++ b/sound/drivers/pcsp/pcsp_input.h
@@ -9,7 +9,6 @@
#define __PCSP_INPUT_H__
int pcspkr_input_init(struct input_dev **rdev, struct device *dev);
-int pcspkr_input_remove(struct input_dev *dev);
void pcspkr_stop_sound(void);
#endif
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index da9983cba01c..3cbc7a4adcb4 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -115,7 +115,6 @@ struct snd_uart16550 {
int irq;
unsigned long base;
- struct resource *res_base;
unsigned int speed;
unsigned int speed_base;
@@ -323,8 +322,7 @@ static int snd_uart16550_detect(struct snd_uart16550 *uart)
return -ENODEV; /* Not configured */
}
- uart->res_base = request_region(io_base, 8, "Serial MIDI");
- if (uart->res_base == NULL) {
+ if (!devm_request_region(uart->card->dev, io_base, 8, "Serial MIDI")) {
snd_printk(KERN_ERR "u16550: can't grab port 0x%lx\n", io_base);
return -EBUSY;
}
@@ -752,21 +750,6 @@ static const struct snd_rawmidi_ops snd_uart16550_input =
.trigger = snd_uart16550_input_trigger,
};
-static int snd_uart16550_free(struct snd_uart16550 *uart)
-{
- if (uart->irq >= 0)
- free_irq(uart->irq, uart);
- release_and_free_resource(uart->res_base);
- kfree(uart);
- return 0;
-};
-
-static int snd_uart16550_dev_free(struct snd_device *device)
-{
- struct snd_uart16550 *uart = device->device_data;
- return snd_uart16550_free(uart);
-}
-
static int snd_uart16550_create(struct snd_card *card,
unsigned long iobase,
int irq,
@@ -776,14 +759,11 @@ static int snd_uart16550_create(struct snd_card *card,
int droponfull,
struct snd_uart16550 **ruart)
{
- static const struct snd_device_ops ops = {
- .dev_free = snd_uart16550_dev_free,
- };
struct snd_uart16550 *uart;
int err;
- uart = kzalloc(sizeof(*uart), GFP_KERNEL);
+ uart = devm_kzalloc(card->dev, sizeof(*uart), GFP_KERNEL);
if (!uart)
return -ENOMEM;
uart->adaptor = adaptor;
@@ -796,13 +776,12 @@ static int snd_uart16550_create(struct snd_card *card,
err = snd_uart16550_detect(uart);
if (err <= 0) {
printk(KERN_ERR "no UART detected at 0x%lx\n", iobase);
- snd_uart16550_free(uart);
return -ENODEV;
}
if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
- if (request_irq(irq, snd_uart16550_interrupt,
- 0, "Serial MIDI", uart)) {
+ if (devm_request_irq(card->dev, irq, snd_uart16550_interrupt,
+ 0, "Serial MIDI", uart)) {
snd_printk(KERN_WARNING
"irq %d busy. Using Polling.\n", irq);
} else {
@@ -819,13 +798,6 @@ static int snd_uart16550_create(struct snd_card *card,
timer_setup(&uart->buffer_timer, snd_uart16550_buffer_timer, 0);
uart->timer_running = 0;
- /* Register device */
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops);
- if (err < 0) {
- snd_uart16550_free(uart);
- return err;
- }
-
switch (uart->adaptor) {
case SNDRV_SERIAL_MS124W_SA:
case SNDRV_SERIAL_MS124W_MB:
@@ -927,8 +899,8 @@ static int snd_serial_probe(struct platform_device *devptr)
return -ENODEV;
}
- err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+ 0, &card);
if (err < 0)
return err;
@@ -939,11 +911,11 @@ static int snd_serial_probe(struct platform_device *devptr)
base[dev], adaptor[dev], droponfull[dev],
&uart);
if (err < 0)
- goto _err;
+ return err;
err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi);
if (err < 0)
- goto _err;
+ return err;
sprintf(card->longname, "%s [%s] at %#lx, irq %d",
card->shortname,
@@ -953,27 +925,16 @@ static int snd_serial_probe(struct platform_device *devptr)
err = snd_card_register(card);
if (err < 0)
- goto _err;
+ return err;
platform_set_drvdata(devptr, card);
return 0;
-
- _err:
- snd_card_free(card);
- return err;
-}
-
-static int snd_serial_remove(struct platform_device *devptr)
-{
- snd_card_free(platform_get_drvdata(devptr));
- return 0;
}
#define SND_SERIAL_DRIVER "snd_serial_u16550"
static struct platform_driver snd_serial_driver = {
.probe = snd_serial_probe,
- .remove = snd_serial_remove,
.driver = {
.name = SND_SERIAL_DRIVER,
},
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 4206d93ab47e..7f7eed6faaae 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -75,8 +75,8 @@ static int snd_virmidi_probe(struct platform_device *devptr)
int idx, err;
int dev = devptr->id;
- err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_card_virmidi), &card);
+ err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_card_virmidi), &card);
if (err < 0)
return err;
vmidi = card->private_data;
@@ -94,7 +94,7 @@ static int snd_virmidi_probe(struct platform_device *devptr)
err = snd_virmidi_new(card, idx, &rmidi);
if (err < 0)
- goto __nodev;
+ return err;
rdev = rmidi->private_data;
vmidi->midi[idx] = rmidi;
strcpy(rmidi->name, "Virtual Raw MIDI");
@@ -106,18 +106,10 @@ static int snd_virmidi_probe(struct platform_device *devptr)
sprintf(card->longname, "Virtual MIDI Card %i", dev + 1);
err = snd_card_register(card);
- if (!err) {
- platform_set_drvdata(devptr, card);
- return 0;
- }
-__nodev:
- snd_card_free(card);
- return err;
-}
+ if (err)
+ return err;
-static int snd_virmidi_remove(struct platform_device *devptr)
-{
- snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, card);
return 0;
}
@@ -125,7 +117,6 @@ static int snd_virmidi_remove(struct platform_device *devptr)
static struct platform_driver snd_virmidi_driver = {
.probe = snd_virmidi_probe,
- .remove = snd_virmidi_remove,
.driver = {
.name = SND_VIRMIDI_DRIVER,
},
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index a10449af5a76..18901e5bcfcf 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -774,6 +774,11 @@ int snd_vx_resume(struct vx_core *chip)
EXPORT_SYMBOL(snd_vx_resume);
#endif
+static void snd_vx_release(struct device *dev, void *data)
+{
+ snd_vx_free_firmware(data);
+}
+
/**
* snd_vx_create - constructor for struct vx_core
* @card: card instance
@@ -784,6 +789,8 @@ EXPORT_SYMBOL(snd_vx_resume);
* this function allocates the instance and prepare for the hardware
* initialization.
*
+ * The object is managed via devres, and will be automatically released.
+ *
* return the instance pointer if successful, NULL in error.
*/
struct vx_core *snd_vx_create(struct snd_card *card,
@@ -796,8 +803,9 @@ struct vx_core *snd_vx_create(struct snd_card *card,
if (snd_BUG_ON(!card || !hw || !ops))
return NULL;
- chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL);
- if (! chip)
+ chip = devres_alloc(snd_vx_release, sizeof(*chip) + extra_size,
+ GFP_KERNEL);
+ if (!chip)
return NULL;
mutex_init(&chip->lock);
chip->irq = -1;
diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c
index 93d5df1ae550..2bd4485e4bc7 100644
--- a/sound/firewire/motu/motu-protocol-v2.c
+++ b/sound/firewire/motu/motu-protocol-v2.c
@@ -12,11 +12,11 @@
#define V2_CLOCK_RATE_SHIFT 3
#define V2_CLOCK_SRC_MASK 0x00000007
#define V2_CLOCK_SRC_SHIFT 0
-#define V2_CLOCK_SRC_AESEBU_ON_XLR 0x07
+#define V2_CLOCK_SRC_AESEBU_ON_XLR 0x07 // In Traveler.
#define V2_CLOCK_SRC_ADAT_ON_DSUB 0x05
#define V2_CLOCK_SRC_WORD_ON_BNC 0x04
#define V2_CLOCK_SRC_SPH 0x03
-#define V2_CLOCK_SRC_SPDIF 0x02 // on either coaxial or optical
+#define V2_CLOCK_SRC_SPDIF 0x02 // on either coaxial or optical. AES/EBU in 896HD.
#define V2_CLOCK_SRC_ADAT_ON_OPT 0x01
#define V2_CLOCK_SRC_INTERNAL 0x00
#define V2_CLOCK_FETCH_ENABLE 0x02000000
@@ -100,7 +100,9 @@ static int get_clock_source(struct snd_motu *motu, u32 data,
bool support_iec60958_on_opt = (motu->spec == &snd_motu_spec_828mk2 ||
motu->spec == &snd_motu_spec_traveler);
- if (!support_iec60958_on_opt) {
+ if (motu->spec == &snd_motu_spec_896hd) {
+ *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;
+ } else if (!support_iec60958_on_opt) {
*src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX;
} else {
__be32 reg;
@@ -129,6 +131,7 @@ static int get_clock_source(struct snd_motu *motu, u32 data,
*src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB;
break;
case V2_CLOCK_SRC_AESEBU_ON_XLR:
+ // For Traveler.
*src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR;
break;
default:
@@ -153,7 +156,7 @@ int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
return get_clock_source(motu, be32_to_cpu(reg), src);
}
-// Expected for Traveler and 896HD, which implements Altera Cyclone EP1C3.
+// Expected for Traveler, which implements Altera Cyclone EP1C3.
static int switch_fetching_mode_cyclone(struct snd_motu *motu, u32 *data,
bool enable)
{
@@ -190,6 +193,9 @@ int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
if (motu->spec == &snd_motu_spec_828mk2) {
// 828mkII implements Altera ACEX 1K EP1K30. Nothing to do.
return 0;
+ } else if (motu->spec == &snd_motu_spec_896hd) {
+ // 896HD implements Altera Cyclone EP1C3 but nothing to do.
+ return 0;
} else {
__be32 reg;
u32 data;
@@ -274,6 +280,14 @@ const struct snd_motu_spec snd_motu_spec_828mk2 = {
.rx_fixed_pcm_chunks = {14, 14, 0},
};
+const struct snd_motu_spec snd_motu_spec_896hd = {
+ .name = "896HD",
+ .protocol_version = SND_MOTU_PROTOCOL_V2,
+ // No support for MIDI.
+ .tx_fixed_pcm_chunks = {14, 14, 8},
+ .rx_fixed_pcm_chunks = {14, 14, 8},
+};
+
const struct snd_motu_spec snd_motu_spec_traveler = {
.name = "Traveler",
.protocol_version = SND_MOTU_PROTOCOL_V2,
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c
index 543136578c70..f65426238d4c 100644
--- a/sound/firewire/motu/motu.c
+++ b/sound/firewire/motu/motu.c
@@ -153,6 +153,7 @@ static const struct ieee1394_device_id motu_id_table[] = {
SND_MOTU_DEV_ENTRY(0x000001, &snd_motu_spec_828),
SND_MOTU_DEV_ENTRY(0x000002, &snd_motu_spec_896),
SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2),
+ SND_MOTU_DEV_ENTRY(0x000005, &snd_motu_spec_896hd),
SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler),
SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite),
SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre),
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h
index 73f36d1be515..f1a830b358d4 100644
--- a/sound/firewire/motu/motu.h
+++ b/sound/firewire/motu/motu.h
@@ -126,6 +126,7 @@ extern const struct snd_motu_spec snd_motu_spec_828;
extern const struct snd_motu_spec snd_motu_spec_896;
extern const struct snd_motu_spec snd_motu_spec_828mk2;
+extern const struct snd_motu_spec snd_motu_spec_896hd;
extern const struct snd_motu_spec snd_motu_spec_traveler;
extern const struct snd_motu_spec snd_motu_spec_ultralite;
extern const struct snd_motu_spec snd_motu_spec_8pre;
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index fa5bed0d5a6f..9ac873773129 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -124,28 +124,24 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
struct snd_ad1816a *chip;
struct snd_opl3 *opl3;
- error = snd_card_new(&pcard->card->dev,
- index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_ad1816a), &card);
+ error = snd_devm_card_new(&pcard->card->dev,
+ index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_ad1816a), &card);
if (error < 0)
return error;
chip = card->private_data;
error = snd_card_ad1816a_pnp(dev, pcard, pid);
- if (error) {
- snd_card_free(card);
+ if (error)
return error;
- }
error = snd_ad1816a_create(card, port[dev],
irq[dev],
dma1[dev],
dma2[dev],
chip);
- if (error) {
- snd_card_free(card);
+ if (error)
return error;
- }
if (clockfreq[dev] >= 5000 && clockfreq[dev] <= 100000)
chip->clock_freq = clockfreq[dev];
@@ -155,22 +151,16 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
error = snd_ad1816a_pcm(chip, 0);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_ad1816a_mixer(chip);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_ad1816a_timer(chip, 0);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
if (mpu_port[dev] > 0) {
if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
@@ -186,18 +176,14 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2);
} else {
error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
}
}
error = snd_card_register(card);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
pnp_set_card_drvdata(pcard, card);
return 0;
}
@@ -223,12 +209,6 @@ static int snd_ad1816a_pnp_detect(struct pnp_card_link *card,
return -ENODEV;
}
-static void snd_ad1816a_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
#ifdef CONFIG_PM
static int snd_ad1816a_pnp_suspend(struct pnp_card_link *pcard,
pm_message_t state)
@@ -255,7 +235,6 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
.name = "ad1816a",
.id_table = snd_ad1816a_pnpids,
.probe = snd_ad1816a_pnp_detect,
- .remove = snd_ad1816a_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_ad1816a_pnp_suspend,
.resume = snd_ad1816a_pnp_resume,
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 6d4999b30461..132a095dca2c 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -541,28 +541,6 @@ static int snd_ad1816a_probe(struct snd_ad1816a *chip)
return 0;
}
-static int snd_ad1816a_free(struct snd_ad1816a *chip)
-{
- release_and_free_resource(chip->res_port);
- if (chip->irq >= 0)
- free_irq(chip->irq, (void *) chip);
- if (chip->dma1 >= 0) {
- snd_dma_disable(chip->dma1);
- free_dma(chip->dma1);
- }
- if (chip->dma2 >= 0) {
- snd_dma_disable(chip->dma2);
- free_dma(chip->dma2);
- }
- return 0;
-}
-
-static int snd_ad1816a_dev_free(struct snd_device *device)
-{
- struct snd_ad1816a *chip = device->device_data;
- return snd_ad1816a_free(chip);
-}
-
static const char *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
{
switch (chip->hardware) {
@@ -580,37 +558,31 @@ int snd_ad1816a_create(struct snd_card *card,
unsigned long port, int irq, int dma1, int dma2,
struct snd_ad1816a *chip)
{
- static const struct snd_device_ops ops = {
- .dev_free = snd_ad1816a_dev_free,
- };
int error;
chip->irq = -1;
chip->dma1 = -1;
chip->dma2 = -1;
- chip->res_port = request_region(port, 16, "AD1816A");
+ chip->res_port = devm_request_region(card->dev, port, 16, "AD1816A");
if (!chip->res_port) {
snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port);
- snd_ad1816a_free(chip);
return -EBUSY;
}
- if (request_irq(irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) {
+ if (devm_request_irq(card->dev, irq, snd_ad1816a_interrupt, 0,
+ "AD1816A", (void *) chip)) {
snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq);
- snd_ad1816a_free(chip);
return -EBUSY;
}
chip->irq = irq;
card->sync_irq = chip->irq;
- if (request_dma(dma1, "AD1816A - 1")) {
+ if (snd_devm_request_dma(card->dev, dma1, "AD1816A - 1")) {
snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1);
- snd_ad1816a_free(chip);
return -EBUSY;
}
chip->dma1 = dma1;
- if (request_dma(dma2, "AD1816A - 2")) {
+ if (snd_devm_request_dma(card->dev, dma2, "AD1816A - 2")) {
snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2);
- snd_ad1816a_free(chip);
return -EBUSY;
}
chip->dma2 = dma2;
@@ -620,20 +592,11 @@ int snd_ad1816a_create(struct snd_card *card,
spin_lock_init(&chip->lock);
error = snd_ad1816a_probe(chip);
- if (error) {
- snd_ad1816a_free(chip);
+ if (error)
return error;
- }
snd_ad1816a_init(chip);
- /* Register device */
- error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (error < 0) {
- snd_ad1816a_free(chip);
- return error;
- }
-
return 0;
}
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index edafb49797e7..c471ac2aa450 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -72,7 +72,7 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
struct snd_wss *chip;
int error;
- error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+ error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
if (error < 0)
return error;
@@ -80,17 +80,17 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT,
0, &chip);
if (error < 0)
- goto out;
+ return error;
card->private_data = chip;
error = snd_wss_pcm(chip, 0);
if (error < 0)
- goto out;
+ return error;
error = snd_wss_mixer(chip);
if (error < 0)
- goto out;
+ return error;
strscpy(card->driver, "AD1848", sizeof(card->driver));
strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
@@ -106,18 +106,10 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
error = snd_card_register(card);
if (error < 0)
- goto out;
+ return error;
dev_set_drvdata(dev, card);
return 0;
-
-out: snd_card_free(card);
- return error;
-}
-
-static void snd_ad1848_remove(struct device *dev, unsigned int n)
-{
- snd_card_free(dev_get_drvdata(dev));
}
#ifdef CONFIG_PM
@@ -145,7 +137,6 @@ static int snd_ad1848_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_ad1848_driver = {
.match = snd_ad1848_match,
.probe = snd_ad1848_probe,
- .remove = snd_ad1848_remove,
#ifdef CONFIG_PM
.suspend = snd_ad1848_suspend,
.resume = snd_ad1848_resume,
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
index e6cd7c4da38e..f079ba4ef1a0 100644
--- a/sound/isa/adlib.c
+++ b/sound/isa/adlib.c
@@ -43,30 +43,23 @@ static int snd_adlib_match(struct device *dev, unsigned int n)
return 1;
}
-static void snd_adlib_free(struct snd_card *card)
-{
- release_and_free_resource(card->private_data);
-}
-
static int snd_adlib_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
struct snd_opl3 *opl3;
int error;
- error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+ error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
if (error < 0) {
dev_err(dev, "could not create card\n");
return error;
}
- card->private_data = request_region(port[n], 4, CRD_NAME);
+ card->private_data = devm_request_region(dev, port[n], 4, CRD_NAME);
if (!card->private_data) {
dev_err(dev, "could not grab ports\n");
- error = -EBUSY;
- goto out;
+ return -EBUSY;
}
- card->private_free = snd_adlib_free;
strcpy(card->driver, DEV_NAME);
strcpy(card->shortname, CRD_NAME);
@@ -75,37 +68,28 @@ static int snd_adlib_probe(struct device *dev, unsigned int n)
error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3);
if (error < 0) {
dev_err(dev, "could not create OPL\n");
- goto out;
+ return error;
}
error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
if (error < 0) {
dev_err(dev, "could not create FM\n");
- goto out;
+ return error;
}
error = snd_card_register(card);
if (error < 0) {
dev_err(dev, "could not register card\n");
- goto out;
+ return error;
}
dev_set_drvdata(dev, card);
return 0;
-
-out: snd_card_free(card);
- return error;
-}
-
-static void snd_adlib_remove(struct device *dev, unsigned int n)
-{
- snd_card_free(dev_get_drvdata(dev));
}
static struct isa_driver snd_adlib_driver = {
.match = snd_adlib_match,
.probe = snd_adlib_probe,
- .remove = snd_adlib_remove,
.driver = {
.name = DEV_NAME
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index d4597fdfe091..d582eff64082 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -170,18 +170,16 @@ static int snd_card_als100_probe(int dev,
struct snd_card_als100 *acard;
struct snd_opl3 *opl3;
- error = snd_card_new(&pcard->card->dev,
- index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_card_als100), &card);
+ error = snd_devm_card_new(&pcard->card->dev,
+ index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_card_als100), &card);
if (error < 0)
return error;
acard = card->private_data;
error = snd_card_als100_pnp(dev, acard, pcard, pid);
- if (error) {
- snd_card_free(card);
+ if (error)
return error;
- }
if (pid->driver_data == SB_HW_DT019X)
dma16[dev] = -1;
@@ -191,10 +189,8 @@ static int snd_card_als100_probe(int dev,
dma8[dev], dma16[dev],
pid->driver_data,
&chip);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
acard->chip = chip;
if (pid->driver_data == SB_HW_DT019X) {
@@ -213,16 +209,12 @@ static int snd_card_als100_probe(int dev,
}
error = snd_sb16dsp_pcm(chip, 0);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_sbmixer_new(chip);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
int mpu_type = MPU401_HW_ALS100;
@@ -249,23 +241,17 @@ static int snd_card_als100_probe(int dev,
fm_port[dev], fm_port[dev] + 2);
} else {
error = snd_opl3_timer_new(opl3, 0, 1);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
}
}
error = snd_card_register(card);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
pnp_set_card_drvdata(pcard, card);
return 0;
}
@@ -291,12 +277,6 @@ static int snd_als100_pnp_detect(struct pnp_card_link *card,
return -ENODEV;
}
-static void snd_als100_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
#ifdef CONFIG_PM
static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -327,7 +307,6 @@ static struct pnp_card_driver als100_pnpc_driver = {
.name = "als100",
.id_table = snd_als100_pnpids,
.probe = snd_als100_pnp_detect,
- .remove = snd_als100_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_als100_pnp_suspend,
.resume = snd_als100_pnp_resume,
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index dd5c059b3744..761cd198df2b 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -169,33 +169,27 @@ static int snd_card_azt2320_probe(int dev,
struct snd_wss *chip;
struct snd_opl3 *opl3;
- error = snd_card_new(&pcard->card->dev,
- index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_card_azt2320), &card);
+ error = snd_devm_card_new(&pcard->card->dev,
+ index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_card_azt2320), &card);
if (error < 0)
return error;
acard = card->private_data;
error = snd_card_azt2320_pnp(dev, acard, pcard, pid);
- if (error) {
- snd_card_free(card);
+ if (error)
return error;
- }
error = snd_card_azt2320_enable_wss(port[dev]);
- if (error) {
- snd_card_free(card);
+ if (error)
return error;
- }
error = snd_wss_create(card, wss_port[dev], -1,
irq[dev],
dma1[dev], dma2[dev],
WSS_HW_DETECT, 0, &chip);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
strcpy(card->driver, "AZT2320");
strcpy(card->shortname, "Aztech AZT2320");
@@ -203,20 +197,14 @@ static int snd_card_azt2320_probe(int dev,
card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
error = snd_wss_pcm(chip, 0);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_wss_mixer(chip);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_wss_timer(chip, 0);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
@@ -233,23 +221,17 @@ static int snd_card_azt2320_probe(int dev,
fm_port[dev], fm_port[dev] + 2);
} else {
error = snd_opl3_timer_new(opl3, 1, 2);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
}
}
error = snd_card_register(card);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
pnp_set_card_drvdata(pcard, card);
return 0;
}
@@ -275,12 +257,6 @@ static int snd_azt2320_pnp_detect(struct pnp_card_link *card,
return -ENODEV;
}
-static void snd_azt2320_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
#ifdef CONFIG_PM
static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -310,7 +286,6 @@ static struct pnp_card_driver azt2320_pnpc_driver = {
.name = "azt2320",
.id_table = snd_azt2320_pnpids,
.probe = snd_azt2320_pnp_detect,
- .remove = snd_azt2320_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_azt2320_pnp_suspend,
.resume = snd_azt2320_pnp_resume,
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index 3b9fbb02864b..8902cfb830f7 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -294,8 +294,8 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
}
outb(val, port);
- err = snd_card_new(pdev, index[ndev], id[ndev], THIS_MODULE,
- sizeof(struct snd_cmi8328), &card);
+ err = snd_devm_card_new(pdev, index[ndev], id[ndev], THIS_MODULE,
+ sizeof(struct snd_cmi8328), &card);
if (err < 0)
return err;
cmi = card->private_data;
@@ -306,18 +306,18 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
err = snd_wss_create(card, port + 4, -1, irq[ndev], dma1[ndev],
dma2[ndev], WSS_HW_DETECT, 0, &cmi->wss);
if (err < 0)
- goto error;
+ return err;
err = snd_wss_pcm(cmi->wss, 0);
if (err < 0)
- goto error;
+ return err;
err = snd_wss_mixer(cmi->wss);
if (err < 0)
- goto error;
+ return err;
err = snd_cmi8328_mixer(cmi->wss);
if (err < 0)
- goto error;
+ return err;
if (snd_wss_timer(cmi->wss, 0) < 0)
snd_printk(KERN_WARNING "error initializing WSS timer\n");
@@ -371,24 +371,21 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
dev_set_drvdata(pdev, card);
err = snd_card_register(card);
if (err < 0)
- goto error;
+ return err;
#ifdef SUPPORT_JOYSTICK
if (!gameport[ndev])
return 0;
/* gameport is hardwired to 0x200 */
- res = request_region(0x200, 8, "CMI8328 gameport");
+ res = devm_request_region(pdev, 0x200, 8, "CMI8328 gameport");
if (!res)
snd_printk(KERN_WARNING "unable to allocate gameport I/O port\n");
else {
struct gameport *gp = cmi->gameport = gameport_allocate_port();
- if (!cmi->gameport)
- release_and_free_resource(res);
- else {
+ if (cmi->gameport) {
gameport_set_name(gp, "CMI8328 Gameport");
gameport_set_phys(gp, "%s/gameport0", dev_name(pdev));
gameport_set_dev_parent(gp, pdev);
gp->io = 0x200;
- gameport_set_port_data(gp, res);
/* Enable gameport */
snd_cmi8328_cfg_write(port, CFG1,
CFG1_SB_DISABLE | CFG1_GAMEPORT);
@@ -397,10 +394,6 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
}
#endif
return 0;
-error:
- snd_card_free(card);
-
- return err;
}
static void snd_cmi8328_remove(struct device *pdev, unsigned int dev)
@@ -409,17 +402,13 @@ static void snd_cmi8328_remove(struct device *pdev, unsigned int dev)
struct snd_cmi8328 *cmi = card->private_data;
#ifdef SUPPORT_JOYSTICK
- if (cmi->gameport) {
- struct resource *res = gameport_get_port_data(cmi->gameport);
+ if (cmi->gameport)
gameport_unregister_port(cmi->gameport);
- release_and_free_resource(res);
- }
#endif
/* disable everything */
snd_cmi8328_cfg_write(cmi->port, CFG1, CFG1_SB_DISABLE);
snd_cmi8328_cfg_write(cmi->port, CFG2, 0);
snd_cmi8328_cfg_write(cmi->port, CFG3, 0);
- snd_card_free(card);
}
#ifdef CONFIG_PM
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index ef6d0a20efd8..f209b16c5229 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -507,8 +507,8 @@ static int snd_cmi8330_card_new(struct device *pdev, int dev,
struct snd_cmi8330 *acard;
int err;
- err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_cmi8330), &card);
+ err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_cmi8330), &card);
if (err < 0) {
snd_printk(KERN_ERR PFX "could not get a new card\n");
return err;
@@ -629,20 +629,12 @@ static int snd_cmi8330_isa_probe(struct device *pdev,
if (err < 0)
return err;
err = snd_cmi8330_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
dev_set_drvdata(pdev, card);
return 0;
}
-static void snd_cmi8330_isa_remove(struct device *devptr,
- unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
-}
-
#ifdef CONFIG_PM
static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
@@ -661,7 +653,6 @@ static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_cmi8330_driver = {
.match = snd_cmi8330_isa_match,
.probe = snd_cmi8330_isa_probe,
- .remove = snd_cmi8330_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_cmi8330_isa_suspend,
.resume = snd_cmi8330_isa_resume,
@@ -693,25 +684,16 @@ static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid);
if (res < 0) {
snd_printk(KERN_ERR PFX "PnP detection failed\n");
- snd_card_free(card);
return res;
}
res = snd_cmi8330_probe(card, dev);
- if (res < 0) {
- snd_card_free(card);
+ if (res < 0)
return res;
- }
pnp_set_card_drvdata(pcard, card);
dev++;
return 0;
}
-static void snd_cmi8330_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
#ifdef CONFIG_PM
static int snd_cmi8330_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -729,7 +711,6 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
.name = "cmi8330",
.id_table = snd_cmi8330_pnpids,
.probe = snd_cmi8330_pnp_detect,
- .remove = snd_cmi8330_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_cmi8330_pnp_suspend,
.resume = snd_cmi8330_pnp_resume,
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index ec054b929214..1e8923385366 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -79,20 +79,20 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
struct snd_wss *chip;
int error;
- error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+ error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
if (error < 0)
return error;
error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
WSS_HW_DETECT, 0, &chip);
if (error < 0)
- goto out;
+ return error;
card->private_data = chip;
error = snd_wss_pcm(chip, 0);
if (error < 0)
- goto out;
+ return error;
strscpy(card->driver, "CS4231", sizeof(card->driver));
strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
@@ -108,11 +108,11 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
error = snd_wss_mixer(chip);
if (error < 0)
- goto out;
+ return error;
error = snd_wss_timer(chip, 0);
if (error < 0)
- goto out;
+ return error;
if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) {
if (mpu_irq[n] == SNDRV_AUTO_IRQ)
@@ -125,18 +125,10 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
error = snd_card_register(card);
if (error < 0)
- goto out;
+ return error;
dev_set_drvdata(dev, card);
return 0;
-
-out: snd_card_free(card);
- return error;
-}
-
-static void snd_cs4231_remove(struct device *dev, unsigned int n)
-{
- snd_card_free(dev_get_drvdata(dev));
}
#ifdef CONFIG_PM
@@ -164,7 +156,6 @@ static int snd_cs4231_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_cs4231_driver = {
.match = snd_cs4231_match,
.probe = snd_cs4231_probe,
- .remove = snd_cs4231_remove,
#ifdef CONFIG_PM
.suspend = snd_cs4231_suspend,
.resume = snd_cs4231_resume,
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 0b7fd17f8ecc..b6bdebd9ef27 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -76,7 +76,6 @@ static int pnp_registered;
struct snd_card_cs4236 {
struct snd_wss *chip;
- struct resource *res_sb_port;
#ifdef CONFIG_PNP
struct pnp_dev *wss;
struct pnp_dev *ctrl;
@@ -309,24 +308,16 @@ static int snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
#define is_isapnp_selected(dev) 0
#endif
-static void snd_card_cs4236_free(struct snd_card *card)
-{
- struct snd_card_cs4236 *acard = card->private_data;
-
- release_and_free_resource(acard->res_sb_port);
-}
-
static int snd_cs423x_card_new(struct device *pdev, int dev,
struct snd_card **cardp)
{
struct snd_card *card;
int err;
- err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_card_cs4236), &card);
+ err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_card_cs4236), &card);
if (err < 0)
return err;
- card->private_free = snd_card_cs4236_free;
*cardp = card;
return 0;
}
@@ -340,8 +331,8 @@ static int snd_cs423x_probe(struct snd_card *card, int dev)
acard = card->private_data;
if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT) {
- acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB");
- if (!acard->res_sb_port) {
+ if (!devm_request_region(card->dev, sb_port[dev], 16,
+ IDENT " SB")) {
printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]);
return -EBUSY;
}
@@ -448,21 +439,12 @@ static int snd_cs423x_isa_probe(struct device *pdev,
if (err < 0)
return err;
err = snd_cs423x_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
-
dev_set_drvdata(pdev, card);
return 0;
}
-static void snd_cs423x_isa_remove(struct device *pdev,
- unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(pdev));
-}
-
#ifdef CONFIG_PM
static int snd_cs423x_suspend(struct snd_card *card)
{
@@ -495,7 +477,6 @@ static int snd_cs423x_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver cs423x_isa_driver = {
.match = snd_cs423x_isa_match,
.probe = snd_cs423x_isa_probe,
- .remove = snd_cs423x_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_cs423x_isa_suspend,
.resume = snd_cs423x_isa_resume,
@@ -539,24 +520,16 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev);
if (err < 0) {
printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n");
- snd_card_free(card);
return err;
}
err = snd_cs423x_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pnp_set_drvdata(pdev, card);
dev++;
return 0;
}
-static void snd_cs423x_pnp_remove(struct pnp_dev *pdev)
-{
- snd_card_free(pnp_get_drvdata(pdev));
-}
-
#ifdef CONFIG_PM
static int snd_cs423x_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
{
@@ -573,7 +546,6 @@ static struct pnp_driver cs423x_pnp_driver = {
.name = "cs423x-pnpbios",
.id_table = snd_cs423x_pnpbiosids,
.probe = snd_cs423x_pnpbios_detect,
- .remove = snd_cs423x_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_cs423x_pnp_suspend,
.resume = snd_cs423x_pnp_resume,
@@ -601,25 +573,16 @@ static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
if (res < 0) {
printk(KERN_ERR "isapnp detection failed and probing for " IDENT
" is not supported\n");
- snd_card_free(card);
return res;
}
res = snd_cs423x_probe(card, dev);
- if (res < 0) {
- snd_card_free(card);
+ if (res < 0)
return res;
- }
pnp_set_card_drvdata(pcard, card);
dev++;
return 0;
}
-static void snd_cs423x_pnpc_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
#ifdef CONFIG_PM
static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -637,7 +600,6 @@ static struct pnp_card_driver cs423x_pnpc_driver = {
.name = CS423X_ISAPNP_DRIVER,
.id_table = snd_cs423x_pnpids,
.probe = snd_cs423x_pnpc_detect,
- .remove = snd_cs423x_pnpc_remove,
#ifdef CONFIG_PM
.suspend = snd_cs423x_pnpc_suspend,
.resume = snd_cs423x_pnpc_resume,
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 63957aea456b..35f25911adcf 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -298,7 +298,6 @@ int snd_cs4236_create(struct snd_card *card,
if (cport < 0x100 || cport == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR "please, specify control port "
"for CS4236+ chips\n");
- snd_device_free(card, chip);
return -ENODEV;
}
ver1 = snd_cs4236_ctrl_in(chip, 1);
@@ -308,7 +307,6 @@ int snd_cs4236_create(struct snd_card *card,
if (ver1 != ver2) {
snd_printk(KERN_ERR "CS4236+ chip detected, but "
"control port 0x%lx is not valid\n", cport);
- snd_device_free(card, chip);
return -ENODEV;
}
snd_cs4236_ctrl_out(chip, 0, 0x00);
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 750d4995634f..f935b56eeec7 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -166,36 +166,27 @@ static int snd_es1688_isa_probe(struct device *dev, unsigned int n)
struct snd_card *card;
int error;
- error = snd_card_new(dev, index[n], id[n], THIS_MODULE,
- sizeof(struct snd_es1688), &card);
+ error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+ sizeof(struct snd_es1688), &card);
if (error < 0)
return error;
error = snd_es1688_legacy_create(card, dev, n);
if (error < 0)
- goto out;
+ return error;
error = snd_es1688_probe(card, n);
if (error < 0)
- goto out;
+ return error;
dev_set_drvdata(dev, card);
return 0;
-out:
- snd_card_free(card);
- return error;
-}
-
-static void snd_es1688_isa_remove(struct device *dev, unsigned int n)
-{
- snd_card_free(dev_get_drvdata(dev));
}
static struct isa_driver snd_es1688_driver = {
.match = snd_es1688_match,
.probe = snd_es1688_isa_probe,
- .remove = snd_es1688_isa_remove,
#if 0 /* FIXME */
.suspend = snd_es1688_suspend,
.resume = snd_es1688_resume,
@@ -249,22 +240,18 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
if (dev == SNDRV_CARDS)
return -ENODEV;
- error = snd_card_new(&pcard->card->dev,
- index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_es1688), &card);
+ error = snd_devm_card_new(&pcard->card->dev,
+ index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_es1688), &card);
if (error < 0)
return error;
error = snd_card_es968_pnp(card, dev, pcard, pid);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_es1688_probe(card, dev);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
pnp_set_card_drvdata(pcard, card);
snd_es968_pnp_is_probed = 1;
return 0;
@@ -272,8 +259,6 @@ static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
static void snd_es968_pnp_remove(struct pnp_card_link *pcard)
{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
snd_es968_pnp_is_probed = 0;
}
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 68b9c59e1127..3fcd168480b6 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -87,9 +87,6 @@
struct snd_es18xx {
unsigned long port; /* port of ESS chip */
unsigned long ctrl_port; /* Control port of ESS chip */
- struct resource *res_port;
- struct resource *res_mpu_port;
- struct resource *res_ctrl_port;
int irq; /* IRQ number of ESS chip */
int dma1; /* DMA1 */
int dma2; /* DMA2 */
@@ -1531,7 +1528,7 @@ static int snd_es18xx_initialize(struct snd_es18xx *chip,
return 0;
}
-static int snd_es18xx_identify(struct snd_es18xx *chip)
+static int snd_es18xx_identify(struct snd_card *card, struct snd_es18xx *chip)
{
int hi,lo;
@@ -1573,8 +1570,8 @@ static int snd_es18xx_identify(struct snd_es18xx *chip)
udelay(10);
chip->ctrl_port += inb(chip->port + 0x05);
- chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL");
- if (!chip->res_ctrl_port) {
+ if (!devm_request_region(card->dev, chip->ctrl_port, 8,
+ "ES18xx - CTRL")) {
snd_printk(KERN_ERR PFX "unable go grab port 0x%lx\n", chip->ctrl_port);
return -EBUSY;
}
@@ -1601,11 +1598,12 @@ static int snd_es18xx_identify(struct snd_es18xx *chip)
return 0;
}
-static int snd_es18xx_probe(struct snd_es18xx *chip,
+static int snd_es18xx_probe(struct snd_card *card,
+ struct snd_es18xx *chip,
unsigned long mpu_port,
unsigned long fm_port)
{
- if (snd_es18xx_identify(chip) < 0) {
+ if (snd_es18xx_identify(card, chip) < 0) {
snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
return -ENODEV;
}
@@ -1722,31 +1720,6 @@ static int snd_es18xx_resume(struct snd_card *card)
}
#endif /* CONFIG_PM */
-static int snd_es18xx_free(struct snd_card *card)
-{
- struct snd_es18xx *chip = card->private_data;
-
- release_and_free_resource(chip->res_port);
- release_and_free_resource(chip->res_ctrl_port);
- release_and_free_resource(chip->res_mpu_port);
- if (chip->irq >= 0)
- free_irq(chip->irq, (void *) card);
- if (chip->dma1 >= 0) {
- disable_dma(chip->dma1);
- free_dma(chip->dma1);
- }
- if (chip->dma2 >= 0 && chip->dma1 != chip->dma2) {
- disable_dma(chip->dma2);
- free_dma(chip->dma2);
- }
- return 0;
-}
-
-static int snd_es18xx_dev_free(struct snd_device *device)
-{
- return snd_es18xx_free(device->card);
-}
-
static int snd_es18xx_new_device(struct snd_card *card,
unsigned long port,
unsigned long mpu_port,
@@ -1754,10 +1727,6 @@ static int snd_es18xx_new_device(struct snd_card *card,
int irq, int dma1, int dma2)
{
struct snd_es18xx *chip = card->private_data;
- static const struct snd_device_ops ops = {
- .dev_free = snd_es18xx_dev_free,
- };
- int err;
spin_lock_init(&chip->reg_lock);
spin_lock_init(&chip->mixer_lock);
@@ -1768,45 +1737,34 @@ static int snd_es18xx_new_device(struct snd_card *card,
chip->audio2_vol = 0x00;
chip->active = 0;
- chip->res_port = request_region(port, 16, "ES18xx");
- if (chip->res_port == NULL) {
- snd_es18xx_free(card);
+ if (!devm_request_region(card->dev, port, 16, "ES18xx")) {
snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
return -EBUSY;
}
- if (request_irq(irq, snd_es18xx_interrupt, 0, "ES18xx",
- (void *) card)) {
- snd_es18xx_free(card);
+ if (devm_request_irq(card->dev, irq, snd_es18xx_interrupt, 0, "ES18xx",
+ (void *) card)) {
snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
return -EBUSY;
}
chip->irq = irq;
card->sync_irq = chip->irq;
- if (request_dma(dma1, "ES18xx DMA 1")) {
- snd_es18xx_free(card);
+ if (snd_devm_request_dma(card->dev, dma1, "ES18xx DMA 1")) {
snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
return -EBUSY;
}
chip->dma1 = dma1;
- if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) {
- snd_es18xx_free(card);
+ if (dma2 != dma1 &&
+ snd_devm_request_dma(card->dev, dma2, "ES18xx DMA 2")) {
snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
return -EBUSY;
}
chip->dma2 = dma2;
- if (snd_es18xx_probe(chip, mpu_port, fm_port) < 0) {
- snd_es18xx_free(card);
+ if (snd_es18xx_probe(card, chip, mpu_port, fm_port) < 0)
return -ENODEV;
- }
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_es18xx_free(card);
- return err;
- }
return 0;
}
@@ -2088,8 +2046,8 @@ static int snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
static int snd_es18xx_card_new(struct device *pdev, int dev,
struct snd_card **cardp)
{
- return snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_es18xx), cardp);
+ return snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_es18xx), cardp);
}
static int snd_audiodrive_probe(struct snd_card *card, int dev)
@@ -2164,10 +2122,8 @@ static int snd_es18xx_isa_probe1(int dev, struct device *devptr)
if (err < 0)
return err;
err = snd_audiodrive_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
dev_set_drvdata(devptr, card);
return 0;
}
@@ -2215,12 +2171,6 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
}
}
-static void snd_es18xx_isa_remove(struct device *devptr,
- unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
-}
-
#ifdef CONFIG_PM
static int snd_es18xx_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
@@ -2239,7 +2189,6 @@ static int snd_es18xx_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_es18xx_isa_driver = {
.match = snd_es18xx_isa_match,
.probe = snd_es18xx_isa_probe,
- .remove = snd_es18xx_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_es18xx_isa_suspend,
.resume = snd_es18xx_isa_resume,
@@ -2271,25 +2220,16 @@ static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
if (err < 0)
return err;
err = snd_audiodrive_pnp(dev, card->private_data, pdev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_audiodrive_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pnp_set_drvdata(pdev, card);
dev++;
return 0;
}
-static void snd_audiodrive_pnp_remove(struct pnp_dev *pdev)
-{
- snd_card_free(pnp_get_drvdata(pdev));
-}
-
#ifdef CONFIG_PM
static int snd_audiodrive_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
{
@@ -2305,7 +2245,6 @@ static struct pnp_driver es18xx_pnp_driver = {
.name = "es18xx-pnpbios",
.id_table = snd_audiodrive_pnpbiosids,
.probe = snd_audiodrive_pnp_detect,
- .remove = snd_audiodrive_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_audiodrive_pnp_suspend,
.resume = snd_audiodrive_pnp_resume,
@@ -2331,27 +2270,17 @@ static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
return res;
res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid);
- if (res < 0) {
- snd_card_free(card);
+ if (res < 0)
return res;
- }
res = snd_audiodrive_probe(card, dev);
- if (res < 0) {
- snd_card_free(card);
+ if (res < 0)
return res;
- }
pnp_set_card_drvdata(pcard, card);
dev++;
return 0;
}
-static void snd_audiodrive_pnpc_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
#ifdef CONFIG_PM
static int snd_audiodrive_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -2370,7 +2299,6 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
.name = "es18xx",
.id_table = snd_audiodrive_pnpids,
.probe = snd_audiodrive_pnpc_detect,
- .remove = snd_audiodrive_pnpc_remove,
#ifdef CONFIG_PM
.suspend = snd_audiodrive_pnpc_suspend,
.resume = snd_audiodrive_pnpc_resume,
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
index d33d69f29924..ea001c80149d 100644
--- a/sound/isa/galaxy/galaxy.c
+++ b/sound/isa/galaxy/galaxy.c
@@ -472,20 +472,10 @@ static void snd_galaxy_free(struct snd_card *card)
{
struct snd_galaxy *galaxy = card->private_data;
- if (galaxy->wss_port) {
+ if (galaxy->wss_port)
wss_set_config(galaxy->wss_port, 0);
- ioport_unmap(galaxy->wss_port);
- release_and_free_resource(galaxy->res_wss_port);
- }
- if (galaxy->config_port) {
+ if (galaxy->config_port)
galaxy_set_config(galaxy, galaxy->config);
- ioport_unmap(galaxy->config_port);
- release_and_free_resource(galaxy->res_config_port);
- }
- if (galaxy->port) {
- ioport_unmap(galaxy->port);
- release_and_free_resource(galaxy->res_port);
- }
}
static int snd_galaxy_probe(struct device *dev, unsigned int n)
@@ -496,56 +486,60 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
u8 type;
int err;
- err = snd_card_new(dev, index[n], id[n], THIS_MODULE,
- sizeof(*galaxy), &card);
+ err = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+ sizeof(*galaxy), &card);
if (err < 0)
return err;
card->private_free = snd_galaxy_free;
galaxy = card->private_data;
- galaxy->res_port = request_region(port[n], 16, DRV_NAME);
+ galaxy->res_port = devm_request_region(dev, port[n], 16, DRV_NAME);
if (!galaxy->res_port) {
dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n],
port[n] + 15);
- err = -EBUSY;
- goto error;
+ return -EBUSY;
}
- galaxy->port = ioport_map(port[n], 16);
+ galaxy->port = devm_ioport_map(dev, port[n], 16);
+ if (!galaxy->port)
+ return -ENOMEM;
err = galaxy_init(galaxy, &type);
if (err < 0) {
dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]);
- goto error;
+ return err;
}
dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]);
- galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG,
- 16, DRV_NAME);
+ galaxy->res_config_port =
+ devm_request_region(dev, port[n] + GALAXY_PORT_CONFIG, 16,
+ DRV_NAME);
if (!galaxy->res_config_port) {
dev_err(dev, "could not grab ports %#lx-%#lx\n",
port[n] + GALAXY_PORT_CONFIG,
port[n] + GALAXY_PORT_CONFIG + 15);
- err = -EBUSY;
- goto error;
+ return -EBUSY;
}
- galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16);
-
+ galaxy->config_port =
+ devm_ioport_map(dev, port[n] + GALAXY_PORT_CONFIG, 16);
+ if (!galaxy->config_port)
+ return -ENOMEM;
galaxy_config(galaxy, config[n]);
- galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME);
+ galaxy->res_wss_port = devm_request_region(dev, wss_port[n], 4, DRV_NAME);
if (!galaxy->res_wss_port) {
dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n],
wss_port[n] + 3);
- err = -EBUSY;
- goto error;
+ return -EBUSY;
}
- galaxy->wss_port = ioport_map(wss_port[n], 4);
+ galaxy->wss_port = devm_ioport_map(dev, wss_port[n], 4);
+ if (!galaxy->wss_port)
+ return -ENOMEM;
err = galaxy_wss_config(galaxy, wss_config[n]);
if (err < 0) {
dev_err(dev, "could not configure WSS\n");
- goto error;
+ return err;
}
strcpy(card->driver, DRV_NAME);
@@ -557,25 +551,25 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n],
dma2[n], WSS_HW_DETECT, 0, &chip);
if (err < 0)
- goto error;
+ return err;
err = snd_wss_pcm(chip, 0);
if (err < 0)
- goto error;
+ return err;
err = snd_wss_mixer(chip);
if (err < 0)
- goto error;
+ return err;
err = snd_wss_timer(chip, 0);
if (err < 0)
- goto error;
+ return err;
if (mpu_port[n] >= 0) {
err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
mpu_port[n], 0, mpu_irq[n], NULL);
if (err < 0)
- goto error;
+ return err;
}
if (fm_port[n] >= 0) {
@@ -585,38 +579,28 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n)
OPL3_HW_AUTO, 0, &opl3);
if (err < 0) {
dev_err(dev, "no OPL device at %#lx\n", fm_port[n]);
- goto error;
+ return err;
}
err = snd_opl3_timer_new(opl3, 1, 2);
if (err < 0)
- goto error;
+ return err;
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
- goto error;
+ return err;
}
err = snd_card_register(card);
if (err < 0)
- goto error;
+ return err;
dev_set_drvdata(dev, card);
return 0;
-
-error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_galaxy_remove(struct device *dev, unsigned int n)
-{
- snd_card_free(dev_get_drvdata(dev));
}
static struct isa_driver snd_galaxy_driver = {
.match = snd_galaxy_match,
.probe = snd_galaxy_probe,
- .remove = snd_galaxy_remove,
.driver = {
.name = DEV_NAME
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 3b46490271fe..ae1e2542ee4a 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -87,24 +87,10 @@ static void snd_gus_init_control(struct snd_gus_card *gus)
static int snd_gus_free(struct snd_gus_card *gus)
{
- if (gus->gf1.res_port2 == NULL)
- goto __hw_end;
- snd_gf1_stop(gus);
- snd_gus_init_dma_irq(gus, 0);
- __hw_end:
- release_and_free_resource(gus->gf1.res_port1);
- release_and_free_resource(gus->gf1.res_port2);
- if (gus->gf1.irq >= 0)
- free_irq(gus->gf1.irq, (void *) gus);
- if (gus->gf1.dma1 >= 0) {
- disable_dma(gus->gf1.dma1);
- free_dma(gus->gf1.dma1);
+ if (gus->gf1.res_port2) {
+ snd_gf1_stop(gus);
+ snd_gus_init_dma_irq(gus, 0);
}
- if (!gus->equal_dma && gus->gf1.dma2 >= 0) {
- disable_dma(gus->gf1.dma2);
- free_dma(gus->gf1.dma2);
- }
- kfree(gus);
return 0;
}
@@ -130,7 +116,7 @@ int snd_gus_create(struct snd_card *card,
};
*rgus = NULL;
- gus = kzalloc(sizeof(*gus), GFP_KERNEL);
+ gus = devm_kzalloc(card->dev, sizeof(*gus), GFP_KERNEL);
if (gus == NULL)
return -ENOMEM;
spin_lock_init(&gus->reg_lock);
@@ -156,35 +142,33 @@ int snd_gus_create(struct snd_card *card,
gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL);
gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA);
/* allocate resources */
- gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)");
+ gus->gf1.res_port1 = devm_request_region(card->dev, port, 16,
+ "GUS GF1 (Adlib/SB)");
if (!gus->gf1.res_port1) {
snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port);
- snd_gus_free(gus);
return -EBUSY;
}
- gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)");
+ gus->gf1.res_port2 = devm_request_region(card->dev, port + 0x100, 12,
+ "GUS GF1 (Synth)");
if (!gus->gf1.res_port2) {
snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100);
- snd_gus_free(gus);
return -EBUSY;
}
- if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) {
+ if (irq >= 0 && devm_request_irq(card->dev, irq, snd_gus_interrupt, 0,
+ "GUS GF1", (void *) gus)) {
snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq);
- snd_gus_free(gus);
return -EBUSY;
}
gus->gf1.irq = irq;
card->sync_irq = irq;
- if (request_dma(dma1, "GUS - 1")) {
+ if (snd_devm_request_dma(card->dev, dma1, "GUS - 1")) {
snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1);
- snd_gus_free(gus);
return -EBUSY;
}
gus->gf1.dma1 = dma1;
if (dma2 >= 0 && dma1 != dma2) {
- if (request_dma(dma2, "GUS - 2")) {
+ if (snd_devm_request_dma(card->dev, dma2, "GUS - 2")) {
snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2);
- snd_gus_free(gus);
return -EBUSY;
}
gus->gf1.dma2 = dma2;
@@ -209,10 +193,8 @@ int snd_gus_create(struct snd_card *card,
gus->gf1.volume_ramp = 25;
gus->gf1.smooth_pan = 1;
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops);
- if (err < 0) {
- snd_gus_free(gus);
+ if (err < 0)
return err;
- }
*rgus = gus;
return 0;
}
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index bca1caa4968c..09cc53ceea2a 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -135,7 +135,7 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
struct snd_gus_card *gus;
int error;
- error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
+ error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
if (error < 0)
return error;
@@ -144,37 +144,37 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
error = snd_gusclassic_create(card, dev, n, &gus);
if (error < 0)
- goto out;
+ return error;
error = snd_gusclassic_detect(gus);
if (error < 0)
- goto out;
+ return error;
gus->joystick_dac = joystick_dac[n];
error = snd_gus_initialize(gus);
if (error < 0)
- goto out;
+ return error;
error = -ENODEV;
if (gus->max_flag || gus->ess_flag) {
dev_err(dev, "GUS Classic or ACE soundcard was "
"not detected at 0x%lx\n", gus->gf1.port);
- goto out;
+ return error;
}
error = snd_gf1_new_mixer(gus);
if (error < 0)
- goto out;
+ return error;
error = snd_gf1_pcm_new(gus, 0, 0);
if (error < 0)
- goto out;
+ return error;
if (!gus->ace_flag) {
error = snd_gf1_rawmidi_new(gus, 0);
if (error < 0)
- goto out;
+ return error;
}
sprintf(card->longname + strlen(card->longname),
@@ -187,27 +187,17 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n)
error = snd_card_register(card);
if (error < 0)
- goto out;
+ return error;
dev_set_drvdata(dev, card);
return 0;
-
-out: snd_card_free(card);
- return error;
-}
-
-static void snd_gusclassic_remove(struct device *dev, unsigned int n)
-{
- snd_card_free(dev_get_drvdata(dev));
}
static struct isa_driver snd_gusclassic_driver = {
.match = snd_gusclassic_match,
.probe = snd_gusclassic_probe,
- .remove = snd_gusclassic_remove,
#if 0 /* FIXME */
.suspend = snd_gusclassic_suspend,
- .remove = snd_gusclassic_remove,
#endif
.driver = {
.name = DEV_NAME
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index a409a4a29afc..63d9f2d75df0 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -228,8 +228,8 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
struct snd_opl3 *opl3;
int error;
- error = snd_card_new(dev, index[n], id[n], THIS_MODULE,
- sizeof(struct snd_es1688), &card);
+ error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
+ sizeof(struct snd_es1688), &card);
if (error < 0)
return error;
@@ -243,56 +243,56 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
error = snd_gusextreme_es1688_create(card, es1688, dev, n);
if (error < 0)
- goto out;
+ return error;
if (gf1_port[n] < 0)
gf1_port[n] = es1688->port + 0x20;
error = snd_gusextreme_gus_card_create(card, dev, n, &gus);
if (error < 0)
- goto out;
+ return error;
error = snd_gusextreme_detect(gus, es1688);
if (error < 0)
- goto out;
+ return error;
gus->joystick_dac = joystick_dac[n];
error = snd_gus_initialize(gus);
if (error < 0)
- goto out;
+ return error;
error = -ENODEV;
if (!gus->ess_flag) {
dev_err(dev, "GUS Extreme soundcard was not "
"detected at 0x%lx\n", gus->gf1.port);
- goto out;
+ return error;
}
gus->codec_flag = 1;
error = snd_es1688_pcm(card, es1688, 0);
if (error < 0)
- goto out;
+ return error;
error = snd_es1688_mixer(card, es1688);
if (error < 0)
- goto out;
+ return error;
snd_component_add(card, "ES1688");
if (pcm_channels[n] > 0) {
error = snd_gf1_pcm_new(gus, 1, 1);
if (error < 0)
- goto out;
+ return error;
}
error = snd_gf1_new_mixer(gus);
if (error < 0)
- goto out;
+ return error;
error = snd_gusextreme_mixer(card);
if (error < 0)
- goto out;
+ return error;
if (snd_opl3_create(card, es1688->port, es1688->port + 2,
OPL3_HW_OPL3, 0, &opl3) < 0)
@@ -300,14 +300,14 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
else {
error = snd_opl3_hwdep_new(opl3, 0, 2, NULL);
if (error < 0)
- goto out;
+ return error;
}
if (es1688->mpu_port >= 0x300) {
error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
es1688->mpu_port, 0, mpu_irq[n], NULL);
if (error < 0)
- goto out;
+ return error;
}
sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, "
@@ -316,24 +316,15 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n)
error = snd_card_register(card);
if (error < 0)
- goto out;
+ return error;
dev_set_drvdata(dev, card);
return 0;
-
-out: snd_card_free(card);
- return error;
-}
-
-static void snd_gusextreme_remove(struct device *dev, unsigned int n)
-{
- snd_card_free(dev_get_drvdata(dev));
}
static struct isa_driver snd_gusextreme_driver = {
.match = snd_gusextreme_match,
.probe = snd_gusextreme_probe,
- .remove = snd_gusextreme_remove,
#if 0 /* FIXME */
.suspend = snd_gusextreme_suspend,
.resume = snd_gusextreme_resume,
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index ad118d462142..6834c0560064 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -179,16 +179,6 @@ static int snd_gusmax_mixer(struct snd_wss *chip)
return 0;
}
-static void snd_gusmax_free(struct snd_card *card)
-{
- struct snd_gusmax *maxcard = card->private_data;
-
- if (maxcard == NULL)
- return;
- if (maxcard->irq >= 0)
- free_irq(maxcard->irq, (void *)maxcard);
-}
-
static int snd_gusmax_match(struct device *pdev, unsigned int dev)
{
return enable[dev];
@@ -204,11 +194,10 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
struct snd_wss *wss;
struct snd_gusmax *maxcard;
- err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_gusmax), &card);
+ err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_gusmax), &card);
if (err < 0)
return err;
- card->private_free = snd_gusmax_free;
maxcard = card->private_data;
maxcard->card = card;
maxcard->irq = -1;
@@ -218,8 +207,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
xirq = snd_legacy_find_free_irq(possible_irqs);
if (xirq < 0) {
snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
- err = -EBUSY;
- goto _err;
+ return -EBUSY;
}
}
xdma1 = dma1[dev];
@@ -227,8 +215,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
xdma1 = snd_legacy_find_free_dma(possible_dmas);
if (xdma1 < 0) {
snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
- err = -EBUSY;
- goto _err;
+ return -EBUSY;
}
}
xdma2 = dma2[dev];
@@ -236,8 +223,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
xdma2 = snd_legacy_find_free_dma(possible_dmas);
if (xdma2 < 0) {
snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
- err = -EBUSY;
- goto _err;
+ return -EBUSY;
}
}
@@ -267,29 +253,28 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
}
}
if (err < 0)
- goto _err;
+ return err;
err = snd_gusmax_detect(gus);
if (err < 0)
- goto _err;
+ return err;
maxcard->gus_status_reg = gus->gf1.reg_irqstat;
maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
snd_gusmax_init(dev, card, gus);
err = snd_gus_initialize(gus);
if (err < 0)
- goto _err;
+ return err;
if (!gus->max_flag) {
snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
- err = -ENODEV;
- goto _err;
+ return -ENODEV;
}
- if (request_irq(xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) {
+ if (devm_request_irq(card->dev, xirq, snd_gusmax_interrupt, 0,
+ "GUS MAX", (void *)maxcard)) {
snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
- err = -EBUSY;
- goto _err;
+ return -EBUSY;
}
maxcard->irq = xirq;
card->sync_irq = maxcard->irq;
@@ -303,32 +288,32 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
WSS_HWSHARE_DMA2,
&wss);
if (err < 0)
- goto _err;
+ return err;
err = snd_wss_pcm(wss, 0);
if (err < 0)
- goto _err;
+ return err;
err = snd_wss_mixer(wss);
if (err < 0)
- goto _err;
+ return err;
err = snd_wss_timer(wss, 2);
if (err < 0)
- goto _err;
+ return err;
if (pcm_channels[dev] > 0) {
err = snd_gf1_pcm_new(gus, 1, 1);
if (err < 0)
- goto _err;
+ return err;
}
err = snd_gusmax_mixer(wss);
if (err < 0)
- goto _err;
+ return err;
err = snd_gf1_rawmidi_new(gus, 0);
if (err < 0)
- goto _err;
+ return err;
sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
if (xdma2 >= 0)
@@ -336,22 +321,13 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
err = snd_card_register(card);
if (err < 0)
- goto _err;
+ return err;
maxcard->gus = gus;
maxcard->wss = wss;
dev_set_drvdata(pdev, card);
return 0;
-
- _err:
- snd_card_free(card);
- return err;
-}
-
-static void snd_gusmax_remove(struct device *devptr, unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
}
#define DEV_NAME "gusmax"
@@ -359,7 +335,6 @@ static void snd_gusmax_remove(struct device *devptr, unsigned int dev)
static struct isa_driver snd_gusmax_driver = {
.match = snd_gusmax_match,
.probe = snd_gusmax_probe,
- .remove = snd_gusmax_remove,
/* FIXME: suspend/resume */
.driver = {
.name = DEV_NAME
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 755de47d0bb6..20f490e9d563 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -204,13 +204,15 @@ static int snd_interwave_detect_stb(struct snd_interwave *iwcard,
port = 0x360;
}
while (port <= 0x380) {
- iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)");
+ iwcard->i2c_res = devm_request_region(card->dev, port, 1,
+ "InterWave (I2C bus)");
if (iwcard->i2c_res)
break;
port += 0x10;
}
} else {
- iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)");
+ iwcard->i2c_res = devm_request_region(card->dev, port, 1,
+ "InterWave (I2C bus)");
}
if (iwcard->i2c_res == NULL) {
snd_printk(KERN_ERR "interwave: can't grab i2c bus port\n");
@@ -598,19 +600,6 @@ static int snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
}
#endif /* CONFIG_PNP */
-static void snd_interwave_free(struct snd_card *card)
-{
- struct snd_interwave *iwcard = card->private_data;
-
- if (iwcard == NULL)
- return;
-#ifdef SNDRV_STB
- release_and_free_resource(iwcard->i2c_res);
-#endif
- if (iwcard->irq >= 0)
- free_irq(iwcard->irq, (void *)iwcard);
-}
-
static int snd_interwave_card_new(struct device *pdev, int dev,
struct snd_card **cardp)
{
@@ -618,14 +607,13 @@ static int snd_interwave_card_new(struct device *pdev, int dev,
struct snd_interwave *iwcard;
int err;
- err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_interwave), &card);
+ err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_interwave), &card);
if (err < 0)
return err;
iwcard = card->private_data;
iwcard->card = card;
iwcard->irq = -1;
- card->private_free = snd_interwave_free;
*cardp = card;
return 0;
}
@@ -671,8 +659,8 @@ static int snd_interwave_probe(struct snd_card *card, int dev)
if (err < 0)
return err;
- if (request_irq(xirq, snd_interwave_interrupt, 0,
- "InterWave", iwcard)) {
+ if (devm_request_irq(card->dev, xirq, snd_interwave_interrupt, 0,
+ "InterWave", iwcard)) {
snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
return -EBUSY;
}
@@ -779,10 +767,8 @@ static int snd_interwave_isa_probe1(int dev, struct device *devptr)
return err;
err = snd_interwave_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
dev_set_drvdata(devptr, card);
return 0;
}
@@ -843,15 +829,9 @@ static int snd_interwave_isa_probe(struct device *pdev,
}
}
-static void snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
-}
-
static struct isa_driver snd_interwave_driver = {
.match = snd_interwave_isa_match,
.probe = snd_interwave_isa_probe,
- .remove = snd_interwave_isa_remove,
/* FIXME: suspend,resume */
.driver = {
.name = INTERWAVE_DRIVER
@@ -878,32 +858,21 @@ static int snd_interwave_pnp_detect(struct pnp_card_link *pcard,
return res;
res = snd_interwave_pnp(dev, card->private_data, pcard, pid);
- if (res < 0) {
- snd_card_free(card);
+ if (res < 0)
return res;
- }
res = snd_interwave_probe(card, dev);
- if (res < 0) {
- snd_card_free(card);
+ if (res < 0)
return res;
- }
pnp_set_card_drvdata(pcard, card);
dev++;
return 0;
}
-static void snd_interwave_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
static struct pnp_card_driver interwave_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = INTERWAVE_PNP_DRIVER,
.id_table = snd_interwave_pnpids,
.probe = snd_interwave_pnp_detect,
- .remove = snd_interwave_pnp_remove,
/* FIXME: suspend,resume */
};
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c
index 4fbc22a5bc5a..c3fd1eb301bb 100644
--- a/sound/isa/msnd/msnd.c
+++ b/sound/isa/msnd/msnd.c
@@ -425,7 +425,7 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
}
static const struct snd_pcm_hardware snd_msnd_playback = {
- .info = SNDRV_PCM_INFO_MMAP |
+ .info = SNDRV_PCM_INFO_MMAP_IOMEM |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_BATCH,
@@ -444,7 +444,7 @@ static const struct snd_pcm_hardware snd_msnd_playback = {
};
static const struct snd_pcm_hardware snd_msnd_capture = {
- .info = SNDRV_PCM_INFO_MMAP |
+ .info = SNDRV_PCM_INFO_MMAP_IOMEM |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_BATCH,
@@ -473,6 +473,7 @@ static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
snd_msnd_enable_irq(chip);
runtime->dma_area = (__force void *)chip->mappedbase;
+ runtime->dma_addr = chip->base;
runtime->dma_bytes = 0x3000;
chip->playback_substream = substream;
@@ -566,6 +567,7 @@ static const struct snd_pcm_ops snd_msnd_playback_ops = {
.prepare = snd_msnd_playback_prepare,
.trigger = snd_msnd_playback_trigger,
.pointer = snd_msnd_playback_pointer,
+ .mmap = snd_pcm_lib_mmap_iomem,
};
static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
@@ -576,6 +578,7 @@ static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
set_bit(F_AUDIO_READ_INUSE, &chip->flags);
snd_msnd_enable_irq(chip);
runtime->dma_area = (__force void *)chip->mappedbase + 0x3000;
+ runtime->dma_addr = chip->base + 0x3000;
runtime->dma_bytes = 0x3000;
memset(runtime->dma_area, 0, runtime->dma_bytes);
chip->capture_substream = substream;
@@ -662,6 +665,7 @@ static const struct snd_pcm_ops snd_msnd_capture_ops = {
.prepare = snd_msnd_capture_prepare,
.trigger = snd_msnd_capture_trigger,
.pointer = snd_msnd_capture_pointer,
+ .mmap = snd_pcm_lib_mmap_iomem,
};
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 69647b41300d..4433a92f08e7 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -472,11 +472,6 @@ static int snd_msnd_dsp_full_reset(struct snd_card *card)
return rv;
}
-static int snd_msnd_dev_free(struct snd_device *device)
-{
- snd_printdd("snd_msnd_chip_free()\n");
- return 0;
-}
static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
{
@@ -528,58 +523,47 @@ static int snd_msnd_attach(struct snd_card *card)
{
struct snd_msnd *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_msnd_dev_free,
- };
- err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname,
- chip);
+ err = devm_request_irq(card->dev, chip->irq, snd_msnd_interrupt, 0,
+ card->shortname, chip);
if (err < 0) {
printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
return err;
}
card->sync_irq = chip->irq;
- if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) {
- free_irq(chip->irq, chip);
+ if (!devm_request_region(card->dev, chip->io, DSP_NUMIO,
+ card->shortname))
return -EBUSY;
- }
- if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
+ if (!devm_request_mem_region(card->dev, chip->base, BUFFSIZE,
+ card->shortname)) {
printk(KERN_ERR LOGNAME
": unable to grab memory region 0x%lx-0x%lx\n",
chip->base, chip->base + BUFFSIZE - 1);
- release_region(chip->io, DSP_NUMIO);
- free_irq(chip->irq, chip);
return -EBUSY;
}
- chip->mappedbase = ioremap(chip->base, 0x8000);
+ chip->mappedbase = devm_ioremap(card->dev, chip->base, 0x8000);
if (!chip->mappedbase) {
printk(KERN_ERR LOGNAME
": unable to map memory region 0x%lx-0x%lx\n",
chip->base, chip->base + BUFFSIZE - 1);
- err = -EIO;
- goto err_release_region;
+ return -EIO;
}
err = snd_msnd_dsp_full_reset(card);
if (err < 0)
- goto err_release_region;
-
- /* Register device */
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0)
- goto err_release_region;
+ return err;
err = snd_msnd_pcm(card, 0);
if (err < 0) {
printk(KERN_ERR LOGNAME ": error creating new PCM device\n");
- goto err_release_region;
+ return err;
}
err = snd_msndmix_new(card);
if (err < 0) {
printk(KERN_ERR LOGNAME ": error creating new Mixer device\n");
- goto err_release_region;
+ return err;
}
@@ -595,7 +579,7 @@ static int snd_msnd_attach(struct snd_card *card)
if (err < 0) {
printk(KERN_ERR LOGNAME
": error creating new Midi device\n");
- goto err_release_region;
+ return err;
}
mpu = chip->rmidi->private_data;
@@ -610,30 +594,12 @@ static int snd_msnd_attach(struct snd_card *card)
err = snd_card_register(card);
if (err < 0)
- goto err_release_region;
+ return err;
return 0;
-
-err_release_region:
- iounmap(chip->mappedbase);
- release_mem_region(chip->base, BUFFSIZE);
- release_region(chip->io, DSP_NUMIO);
- free_irq(chip->irq, chip);
- return err;
}
-static void snd_msnd_unload(struct snd_card *card)
-{
- struct snd_msnd *chip = card->private_data;
-
- iounmap(chip->mappedbase);
- release_mem_region(chip->base, BUFFSIZE);
- release_region(chip->io, DSP_NUMIO);
- free_irq(chip->irq, chip);
- snd_card_free(card);
-}
-
#ifndef MSND_CLASSIC
/* Pinnacle/Fiji Logical Device Configuration */
@@ -892,8 +858,8 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
return -ENODEV;
}
- err = snd_card_new(pdev, index[idx], id[idx], THIS_MODULE,
- sizeof(struct snd_msnd), &card);
+ err = snd_devm_card_new(pdev, index[idx], id[idx], THIS_MODULE,
+ sizeof(struct snd_msnd), &card);
if (err < 0)
return err;
@@ -934,17 +900,15 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n",
cfg[idx]);
- if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) {
+ if (!devm_request_region(card->dev, cfg[idx], 2,
+ "Pinnacle/Fiji Config")) {
printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n",
cfg[idx]);
- snd_card_free(card);
return -EIO;
}
if (reset[idx])
- if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) {
- err = -EIO;
- goto cfg_error;
- }
+ if (snd_msnd_pinnacle_cfg_reset(cfg[idx]))
+ return -EIO;
/* DSP */
err = snd_msnd_write_cfg_logical(cfg[idx], 0,
@@ -952,7 +916,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
irq[idx], mem[idx]);
if (err)
- goto cfg_error;
+ return err;
/* The following are Pinnacle specific */
@@ -967,7 +931,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
mpu_irq[idx], 0);
if (err)
- goto cfg_error;
+ return err;
}
/* IDE */
@@ -982,7 +946,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
ide_irq[idx], 0);
if (err)
- goto cfg_error;
+ return err;
}
/* Joystick */
@@ -995,9 +959,8 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
0, 0);
if (err)
- goto cfg_error;
+ return err;
}
- release_region(cfg[idx], 2);
#endif /* MSND_CLASSIC */
@@ -1027,37 +990,22 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
err = snd_msnd_probe(card);
if (err < 0) {
printk(KERN_ERR LOGNAME ": Probe failed\n");
- snd_card_free(card);
return err;
}
err = snd_msnd_attach(card);
if (err < 0) {
printk(KERN_ERR LOGNAME ": Attach failed\n");
- snd_card_free(card);
return err;
}
dev_set_drvdata(pdev, card);
return 0;
-
-#ifndef MSND_CLASSIC
-cfg_error:
- release_region(cfg[idx], 2);
- snd_card_free(card);
- return err;
-#endif
-}
-
-static void snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
-{
- snd_msnd_unload(dev_get_drvdata(pdev));
}
static struct isa_driver snd_msnd_driver = {
.match = snd_msnd_isa_match,
.probe = snd_msnd_isa_probe,
- .remove = snd_msnd_isa_remove,
/* FIXME: suspend, resume */
.driver = {
.name = DEV_NAME
@@ -1107,9 +1055,9 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
* Create a new ALSA sound card entry, in anticipation
* of detecting our hardware ...
*/
- ret = snd_card_new(&pcard->card->dev,
- index[idx], id[idx], THIS_MODULE,
- sizeof(struct snd_msnd), &card);
+ ret = snd_devm_card_new(&pcard->card->dev,
+ index[idx], id[idx], THIS_MODULE,
+ sizeof(struct snd_msnd), &card);
if (ret < 0)
return ret;
@@ -1151,28 +1099,18 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
ret = snd_msnd_probe(card);
if (ret < 0) {
printk(KERN_ERR LOGNAME ": Probe failed\n");
- goto _release_card;
+ return ret;
}
ret = snd_msnd_attach(card);
if (ret < 0) {
printk(KERN_ERR LOGNAME ": Attach failed\n");
- goto _release_card;
+ return ret;
}
pnp_set_card_drvdata(pcard, card);
++idx;
return 0;
-
-_release_card:
- snd_card_free(card);
- return ret;
-}
-
-static void snd_msnd_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_msnd_unload(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
}
static int isa_registered;
@@ -1191,7 +1129,6 @@ static struct pnp_card_driver msnd_pnpc_driver = {
.name = "msnd_pinnacle",
.id_table = msnd_pnpids,
.probe = snd_msnd_pnp_detect,
- .remove = snd_msnd_pnp_remove,
};
#endif /* CONFIG_PNP */
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 6f42f869928c..bad1490a66a0 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -208,7 +208,8 @@ static int snd_opl3sa2_detect(struct snd_card *card)
char str[2];
port = chip->port;
- chip->res_port = request_region(port, 2, "OPL3-SA control");
+ chip->res_port = devm_request_region(card->dev, port, 2,
+ "OPL3-SA control");
if (!chip->res_port) {
snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
return -EBUSY;
@@ -609,14 +610,6 @@ static int snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
}
#endif /* CONFIG_PNP */
-static void snd_opl3sa2_free(struct snd_card *card)
-{
- struct snd_opl3sa2 *chip = card->private_data;
- if (chip->irq >= 0)
- free_irq(chip->irq, card);
- release_and_free_resource(chip->res_port);
-}
-
static int snd_opl3sa2_card_new(struct device *pdev, int dev,
struct snd_card **cardp)
{
@@ -624,8 +617,8 @@ static int snd_opl3sa2_card_new(struct device *pdev, int dev,
struct snd_opl3sa2 *chip;
int err;
- err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_opl3sa2), &card);
+ err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_opl3sa2), &card);
if (err < 0)
return err;
strcpy(card->driver, "OPL3SA2");
@@ -633,7 +626,6 @@ static int snd_opl3sa2_card_new(struct device *pdev, int dev,
chip = card->private_data;
spin_lock_init(&chip->reg_lock);
chip->irq = -1;
- card->private_free = snd_opl3sa2_free;
*cardp = card;
return 0;
}
@@ -658,8 +650,8 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev)
err = snd_opl3sa2_detect(card);
if (err < 0)
return err;
- err = request_irq(xirq, snd_opl3sa2_interrupt, 0,
- "OPL3-SA2", card);
+ err = devm_request_irq(card->dev, xirq, snd_opl3sa2_interrupt, 0,
+ "OPL3-SA2", card);
if (err) {
snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
return -ENODEV;
@@ -737,25 +729,16 @@ static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
if (err < 0)
return err;
err = snd_opl3sa2_pnp(dev, card->private_data, pdev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_opl3sa2_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pnp_set_drvdata(pdev, card);
dev++;
return 0;
}
-static void snd_opl3sa2_pnp_remove(struct pnp_dev *pdev)
-{
- snd_card_free(pnp_get_drvdata(pdev));
-}
-
#ifdef CONFIG_PM
static int snd_opl3sa2_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
{
@@ -771,7 +754,6 @@ static struct pnp_driver opl3sa2_pnp_driver = {
.name = "snd-opl3sa2-pnpbios",
.id_table = snd_opl3sa2_pnpbiosids,
.probe = snd_opl3sa2_pnp_detect,
- .remove = snd_opl3sa2_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_opl3sa2_pnp_suspend,
.resume = snd_opl3sa2_pnp_resume,
@@ -803,26 +785,16 @@ static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
if (err < 0)
return err;
err = snd_opl3sa2_pnp(dev, card->private_data, pdev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_opl3sa2_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pnp_set_card_drvdata(pcard, card);
dev++;
return 0;
}
-static void snd_opl3sa2_pnp_cremove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
#ifdef CONFIG_PM
static int snd_opl3sa2_pnp_csuspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -839,7 +811,6 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
.name = "snd-opl3sa2-cpnp",
.id_table = snd_opl3sa2_pnpids,
.probe = snd_opl3sa2_pnp_cdetect,
- .remove = snd_opl3sa2_pnp_cremove,
#ifdef CONFIG_PM
.suspend = snd_opl3sa2_pnp_csuspend,
.resume = snd_opl3sa2_pnp_cresume,
@@ -885,20 +856,12 @@ static int snd_opl3sa2_isa_probe(struct device *pdev,
if (err < 0)
return err;
err = snd_opl3sa2_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
dev_set_drvdata(pdev, card);
return 0;
}
-static void snd_opl3sa2_isa_remove(struct device *devptr,
- unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
-}
-
#ifdef CONFIG_PM
static int snd_opl3sa2_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
@@ -917,7 +880,6 @@ static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_opl3sa2_isa_driver = {
.match = snd_opl3sa2_isa_match,
.probe = snd_opl3sa2_isa_probe,
- .remove = snd_opl3sa2_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_opl3sa2_isa_suspend,
.resume = snd_opl3sa2_isa_resume,
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index e1fb7567fdcc..59242baed576 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -1159,12 +1159,13 @@ __skip_mpu:
return 0;
}
-static int snd_miro_opti_check(struct snd_miro *chip)
+static int snd_miro_opti_check(struct snd_card *card, struct snd_miro *chip)
{
unsigned char value;
- chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
- "OPTi9xx MC");
+ chip->res_mc_base =
+ devm_request_region(card->dev, chip->mc_base,
+ chip->mc_base_size, "OPTi9xx MC");
if (chip->res_mc_base == NULL)
return -ENOMEM;
@@ -1173,7 +1174,7 @@ static int snd_miro_opti_check(struct snd_miro *chip)
if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
return 0;
- release_and_free_resource(chip->res_mc_base);
+ devm_release_resource(card->dev, chip->res_mc_base);
chip->res_mc_base = NULL;
return -ENODEV;
@@ -1190,7 +1191,7 @@ static int snd_card_miro_detect(struct snd_card *card,
if (err < 0)
return err;
- err = snd_miro_opti_check(chip);
+ err = snd_miro_opti_check(card, chip);
if (err == 0)
return 1;
}
@@ -1214,7 +1215,8 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
regval=inb(miro->mc_base + 4);
aci->aci_port = (regval & 0x10) ? 0x344 : 0x354;
- miro->res_aci_port = request_region(aci->aci_port, 3, "miro aci");
+ miro->res_aci_port =
+ devm_request_region(card->dev, aci->aci_port, 3, "miro aci");
if (miro->res_aci_port == NULL) {
snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n",
aci->aci_port, aci->aci_port+2);
@@ -1253,16 +1255,6 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
return 0;
}
-static void snd_card_miro_free(struct snd_card *card)
-{
- struct snd_miro *miro = card->private_data;
-
- release_and_free_resource(miro->res_aci_port);
- if (miro->aci)
- miro->aci->aci_port = 0;
- release_and_free_resource(miro->res_mc_base);
-}
-
static int snd_miro_probe(struct snd_card *card)
{
int error;
@@ -1271,9 +1263,10 @@ static int snd_miro_probe(struct snd_card *card)
struct snd_rawmidi *rmidi;
if (!miro->res_mc_base) {
- miro->res_mc_base = request_region(miro->mc_base,
- miro->mc_base_size,
- "miro (OPTi9xx MC)");
+ miro->res_mc_base = devm_request_region(card->dev,
+ miro->mc_base,
+ miro->mc_base_size,
+ "miro (OPTi9xx MC)");
if (miro->res_mc_base == NULL) {
snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
return -ENOMEM;
@@ -1408,17 +1401,15 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
struct snd_miro *miro;
struct snd_card *card;
- error = snd_card_new(devptr, index, id, THIS_MODULE,
- sizeof(struct snd_miro), &card);
+ error = snd_devm_card_new(devptr, index, id, THIS_MODULE,
+ sizeof(struct snd_miro), &card);
if (error < 0)
return error;
- card->private_free = snd_card_miro_free;
miro = card->private_data;
error = snd_card_miro_detect(card, miro);
if (error < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
return -ENODEV;
}
@@ -1426,7 +1417,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
if (port == SNDRV_AUTO_PORT) {
port = snd_legacy_find_free_ioport(possible_ports, 4);
if (port < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR "unable to find a free WSS port\n");
return -EBUSY;
}
@@ -1435,7 +1425,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
if (mpu_port == SNDRV_AUTO_PORT) {
mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2);
if (mpu_port < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR
"unable to find a free MPU401 port\n");
return -EBUSY;
@@ -1445,7 +1434,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
if (irq == SNDRV_AUTO_IRQ) {
irq = snd_legacy_find_free_irq(possible_irqs);
if (irq < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR "unable to find a free IRQ\n");
return -EBUSY;
}
@@ -1453,7 +1441,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
if (mpu_irq == SNDRV_AUTO_IRQ) {
mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs);
if (mpu_irq < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR
"unable to find a free MPU401 IRQ\n");
return -EBUSY;
@@ -1462,7 +1449,6 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
if (dma1 == SNDRV_AUTO_DMA) {
dma1 = snd_legacy_find_free_dma(possible_dma1s);
if (dma1 < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR "unable to find a free DMA1\n");
return -EBUSY;
}
@@ -1470,34 +1456,24 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
if (dma2 == SNDRV_AUTO_DMA) {
dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]);
if (dma2 < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR "unable to find a free DMA2\n");
return -EBUSY;
}
}
error = snd_miro_probe(card);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
dev_set_drvdata(devptr, card);
return 0;
}
-static void snd_miro_isa_remove(struct device *devptr,
- unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
-}
-
#define DEV_NAME "miro"
static struct isa_driver snd_miro_driver = {
.match = snd_miro_isa_match,
.probe = snd_miro_isa_probe,
- .remove = snd_miro_isa_remove,
/* FIXME: suspend/resume */
.driver = {
.name = DEV_NAME
@@ -1578,39 +1554,31 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
return -EBUSY;
if (!isapnp)
return -ENODEV;
- err = snd_card_new(&pcard->card->dev, index, id, THIS_MODULE,
- sizeof(struct snd_miro), &card);
+ err = snd_devm_card_new(&pcard->card->dev, index, id, THIS_MODULE,
+ sizeof(struct snd_miro), &card);
if (err < 0)
return err;
- card->private_free = snd_card_miro_free;
miro = card->private_data;
err = snd_card_miro_pnp(miro, pcard, pid);
- if (err) {
- snd_card_free(card);
+ if (err)
return err;
- }
/* only miroSOUND PCM20 and PCM12 == OPTi924 */
err = snd_miro_init(miro, OPTi9XX_HW_82C924);
- if (err) {
- snd_card_free(card);
+ if (err)
return err;
- }
- err = snd_miro_opti_check(miro);
+ err = snd_miro_opti_check(card, miro);
if (err) {
snd_printk(KERN_ERR "OPTI chip not found\n");
- snd_card_free(card);
return err;
}
err = snd_miro_probe(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pnp_set_card_drvdata(pcard, card);
snd_miro_pnp_is_probed = 1;
return 0;
@@ -1618,8 +1586,6 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
static void snd_miro_pnp_remove(struct pnp_card_link *pcard)
{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
snd_miro_pnp_is_probed = 0;
}
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 4bd1dc6707fc..4beeb32fe2a7 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -654,16 +654,18 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
#endif /* OPTi93X */
-static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
+static int snd_opti9xx_read_check(struct snd_card *card,
+ struct snd_opti9xx *chip)
{
unsigned char value;
#ifdef OPTi93X
unsigned long flags;
#endif
- chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
- "OPTi9xx MC");
- if (chip->res_mc_base == NULL)
+ chip->res_mc_base =
+ devm_request_region(card->dev, chip->mc_base,
+ chip->mc_base_size, "OPTi9xx MC");
+ if (!chip->res_mc_base)
return -EBUSY;
#ifndef OPTi93X
value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
@@ -671,9 +673,10 @@ static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
return 0;
#else /* OPTi93X */
- chip->res_mc_indir = request_region(chip->mc_indir_index, 2,
- "OPTi93x MC");
- if (chip->res_mc_indir == NULL)
+ chip->res_mc_indir =
+ devm_request_region(card->dev, chip->mc_indir_index, 2,
+ "OPTi93x MC");
+ if (!chip->res_mc_indir)
return -EBUSY;
spin_lock_irqsave(&chip->lock, flags);
@@ -686,10 +689,10 @@ static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
return 0;
- release_and_free_resource(chip->res_mc_indir);
+ devm_release_resource(card->dev, chip->res_mc_indir);
chip->res_mc_indir = NULL;
#endif /* OPTi93X */
- release_and_free_resource(chip->res_mc_base);
+ devm_release_resource(card->dev, chip->res_mc_base);
chip->res_mc_base = NULL;
return -ENODEV;
@@ -709,7 +712,7 @@ static int snd_card_opti9xx_detect(struct snd_card *card,
if (err < 0)
return err;
- err = snd_opti9xx_read_check(chip);
+ err = snd_opti9xx_read_check(card, chip);
if (err == 0)
return 1;
#ifdef OPTi93X
@@ -789,22 +792,6 @@ static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
}
#endif /* CONFIG_PNP */
-static void snd_card_opti9xx_free(struct snd_card *card)
-{
- struct snd_opti9xx *chip = card->private_data;
-
- if (chip) {
-#ifdef OPTi93X
- if (chip->irq > 0) {
- disable_irq(chip->irq);
- free_irq(chip->irq, chip);
- }
- release_and_free_resource(chip->res_mc_indir);
-#endif
- release_and_free_resource(chip->res_mc_base);
- }
-}
-
static int snd_opti9xx_probe(struct snd_card *card)
{
static const long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
@@ -860,8 +847,8 @@ static int snd_opti9xx_probe(struct snd_card *card)
return error;
#endif
#ifdef OPTi93X
- error = request_irq(irq, snd_opti93x_interrupt,
- 0, DEV_NAME" - WSS", chip);
+ error = devm_request_irq(card->dev, irq, snd_opti93x_interrupt,
+ 0, DEV_NAME" - WSS", chip);
if (error < 0) {
snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq);
return error;
@@ -931,11 +918,10 @@ static int snd_opti9xx_card_new(struct device *pdev, struct snd_card **cardp)
struct snd_card *card;
int err;
- err = snd_card_new(pdev, index, id, THIS_MODULE,
- sizeof(struct snd_opti9xx), &card);
+ err = snd_devm_card_new(pdev, index, id, THIS_MODULE,
+ sizeof(struct snd_opti9xx), &card);
if (err < 0)
return err;
- card->private_free = snd_card_opti9xx_free;
*cardp = card;
return 0;
}
@@ -1012,25 +998,15 @@ static int snd_opti9xx_isa_probe(struct device *devptr,
return error;
error = snd_card_opti9xx_detect(card, card->private_data);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
error = snd_opti9xx_probe(card);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
dev_set_drvdata(devptr, card);
return 0;
}
-static void snd_opti9xx_isa_remove(struct device *devptr,
- unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
-}
-
#ifdef CONFIG_PM
static int snd_opti9xx_suspend(struct snd_card *card)
{
@@ -1075,7 +1051,6 @@ static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_opti9xx_driver = {
.match = snd_opti9xx_isa_match,
.probe = snd_opti9xx_isa_probe,
- .remove = snd_opti9xx_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_opti9xx_isa_suspend,
.resume = snd_opti9xx_isa_resume,
@@ -1114,26 +1089,20 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
hw = OPTi9XX_HW_82C931;
break;
default:
- snd_card_free(card);
return -ENODEV;
}
error = snd_opti9xx_init(chip, hw);
- if (error) {
- snd_card_free(card);
+ if (error)
return error;
- }
- error = snd_opti9xx_read_check(chip);
+ error = snd_opti9xx_read_check(card, chip);
if (error) {
snd_printk(KERN_ERR "OPTI chip not found\n");
- snd_card_free(card);
return error;
}
error = snd_opti9xx_probe(card);
- if (error < 0) {
- snd_card_free(card);
+ if (error < 0)
return error;
- }
pnp_set_card_drvdata(pcard, card);
snd_opti9xx_pnp_is_probed = 1;
return 0;
@@ -1141,8 +1110,6 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
snd_opti9xx_pnp_is_probed = 0;
}
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 5e4187940265..e02029677743 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1048,27 +1048,6 @@ __error:
return err;
}
-
-/*
- * free resources
- */
-static int snd_emu8000_free(struct snd_emu8000 *hw)
-{
- release_and_free_resource(hw->res_port1);
- release_and_free_resource(hw->res_port2);
- release_and_free_resource(hw->res_port3);
- kfree(hw);
- return 0;
-}
-
-/*
- */
-static int snd_emu8000_dev_free(struct snd_device *device)
-{
- struct snd_emu8000 *hw = device->device_data;
- return snd_emu8000_free(hw);
-}
-
/*
* initialize and register emu8000 synth device.
*/
@@ -1079,9 +1058,6 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
struct snd_seq_device *awe;
struct snd_emu8000 *hw;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_emu8000_dev_free,
- };
if (awe_ret)
*awe_ret = NULL;
@@ -1089,7 +1065,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
if (seq_ports <= 0)
return 0;
- hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+ hw = devm_kzalloc(card->dev, sizeof(*hw), GFP_KERNEL);
if (hw == NULL)
return -ENOMEM;
spin_lock_init(&hw->reg_lock);
@@ -1097,12 +1073,10 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
hw->port1 = port;
hw->port2 = port + 0x400;
hw->port3 = port + 0x800;
- hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1");
- hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2");
- hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3");
- if (!hw->res_port1 || !hw->res_port2 || !hw->res_port3) {
+ if (!devm_request_region(card->dev, hw->port1, 4, "Emu8000-1") ||
+ !devm_request_region(card->dev, hw->port2, 4, "Emu8000-2") ||
+ !devm_request_region(card->dev, hw->port3, 4, "Emu8000-3")) {
snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
- snd_emu8000_free(hw);
return -EBUSY;
}
hw->mem_size = 0;
@@ -1115,23 +1089,13 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
hw->fm_chorus_depth = 0;
hw->fm_reverb_depth = 0;
- if (snd_emu8000_detect(hw) < 0) {
- snd_emu8000_free(hw);
+ if (snd_emu8000_detect(hw) < 0)
return -ENODEV;
- }
snd_emu8000_init_hw(hw);
err = snd_emu8000_create_mixer(card, hw);
- if (err < 0) {
- snd_emu8000_free(hw);
+ if (err < 0)
return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops);
- if (err < 0) {
- snd_emu8000_free(hw);
- return err;
- }
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
sizeof(struct snd_emu8000*), &awe) >= 0) {
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 7ba5dd1ec810..64936c917170 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -226,8 +226,8 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
static const int possible_dmas16[] = {5, 7, -1};
int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq;
- err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_card_jazz16), &card);
+ err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_card_jazz16), &card);
if (err < 0)
return err;
@@ -238,8 +238,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
xirq = snd_legacy_find_free_irq(possible_irqs);
if (xirq < 0) {
snd_printk(KERN_ERR "unable to find a free IRQ\n");
- err = -EBUSY;
- goto err_free;
+ return -EBUSY;
}
}
xdma8 = dma8[dev];
@@ -247,8 +246,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
xdma8 = snd_legacy_find_free_dma(possible_dmas8);
if (xdma8 < 0) {
snd_printk(KERN_ERR "unable to find a free DMA8\n");
- err = -EBUSY;
- goto err_free;
+ return -EBUSY;
}
}
xdma16 = dma16[dev];
@@ -256,8 +254,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
xdma16 = snd_legacy_find_free_dma(possible_dmas16);
if (xdma16 < 0) {
snd_printk(KERN_ERR "unable to find a free DMA16\n");
- err = -EBUSY;
- goto err_free;
+ return -EBUSY;
}
}
@@ -267,7 +264,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
err = jazz16_detect_board(port[dev], xmpu_port);
if (err < 0) {
printk(KERN_ERR "Media Vision Jazz16 board not detected\n");
- goto err_free;
+ return err;
}
err = snd_sbdsp_create(card, port[dev], irq[dev],
jazz16_interrupt,
@@ -275,7 +272,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
SB_HW_JAZZ16,
&chip);
if (err < 0)
- goto err_free;
+ return err;
xmpu_irq = mpu_irq[dev];
if (xmpu_irq == SNDRV_AUTO_IRQ || mpu_port[dev] == SNDRV_AUTO_PORT)
@@ -283,7 +280,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
err = jazz16_configure_board(chip, xmpu_irq);
if (err < 0) {
printk(KERN_ERR "Media Vision Jazz16 configuration failed\n");
- goto err_free;
+ return err;
}
jazz16->chip = chip;
@@ -296,10 +293,10 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
err = snd_sb8dsp_pcm(chip, 0);
if (err < 0)
- goto err_free;
+ return err;
err = snd_sbmixer_new(chip);
if (err < 0)
- goto err_free;
+ return err;
err = snd_opl3_create(card, chip->port, chip->port + 2,
OPL3_HW_AUTO, 1, &opl3);
@@ -309,7 +306,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
else {
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
- goto err_free;
+ return err;
}
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
@@ -326,21 +323,10 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
err = snd_card_register(card);
if (err < 0)
- goto err_free;
+ return err;
dev_set_drvdata(devptr, card);
return 0;
-
-err_free:
- snd_card_free(card);
- return err;
-}
-
-static void snd_jazz16_remove(struct device *devptr, unsigned int dev)
-{
- struct snd_card *card = dev_get_drvdata(devptr);
-
- snd_card_free(card);
}
#ifdef CONFIG_PM
@@ -372,7 +358,6 @@ static int snd_jazz16_resume(struct device *pdev, unsigned int n)
static struct isa_driver snd_jazz16_driver = {
.match = snd_jazz16_match,
.probe = snd_jazz16_probe,
- .remove = snd_jazz16_remove,
#ifdef CONFIG_PM
.suspend = snd_jazz16_suspend,
.resume = snd_jazz16_resume,
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index d0f797c02841..e89b095aa282 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -285,15 +285,6 @@ __wt_error:
#endif /* CONFIG_PNP */
-static void snd_sb16_free(struct snd_card *card)
-{
- struct snd_card_sb16 *acard = card->private_data;
-
- if (acard == NULL)
- return;
- release_and_free_resource(acard->fm_res);
-}
-
#ifdef CONFIG_PNP
#define is_isapnp_selected(dev) isapnp[dev]
#else
@@ -306,11 +297,10 @@ static int snd_sb16_card_new(struct device *devptr, int dev,
struct snd_card *card;
int err;
- err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_card_sb16), &card);
+ err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_card_sb16), &card);
if (err < 0)
return err;
- card->private_free = snd_sb16_free;
*cardp = card;
return 0;
}
@@ -482,17 +472,16 @@ static int snd_sb16_isa_probe1(int dev, struct device *pdev)
/* non-PnP FM port address is hardwired with base port address */
fm_port[dev] = port[dev];
/* block the 0x388 port to avoid PnP conflicts */
- acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+ acard->fm_res = devm_request_region(card->dev, 0x388, 4,
+ "SoundBlaster FM");
#ifdef SNDRV_SBAWE_EMU8000
/* non-PnP AWE port address is hardwired with base port address */
awe_port[dev] = port[dev] + 0x400;
#endif
err = snd_sb16_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
dev_set_drvdata(pdev, card);
return 0;
}
@@ -547,11 +536,6 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
}
}
-static void snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(pdev));
-}
-
#ifdef CONFIG_PM
static int snd_sb16_isa_suspend(struct device *dev, unsigned int n,
pm_message_t state)
@@ -574,7 +558,6 @@ static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_sb16_isa_driver = {
.match = snd_sb16_isa_match,
.probe = snd_sb16_isa_probe,
- .remove = snd_sb16_isa_remove,
#ifdef CONFIG_PM
.suspend = snd_sb16_isa_suspend,
.resume = snd_sb16_isa_resume,
@@ -600,15 +583,11 @@ static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
if (res < 0)
return res;
res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid);
- if (res < 0) {
- snd_card_free(card);
+ if (res < 0)
return res;
- }
res = snd_sb16_probe(card, dev);
- if (res < 0) {
- snd_card_free(card);
+ if (res < 0)
return res;
- }
pnp_set_card_drvdata(pcard, card);
dev++;
return 0;
@@ -617,12 +596,6 @@ static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
return -ENODEV;
}
-static void snd_sb16_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
#ifdef CONFIG_PM
static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -643,7 +616,6 @@ static struct pnp_card_driver sb16_pnpc_driver = {
#endif
.id_table = snd_sb16_pnpids,
.probe = snd_sb16_pnp_detect,
- .remove = snd_sb16_pnp_remove,
#ifdef CONFIG_PM
.suspend = snd_sb16_pnp_suspend,
.resume = snd_sb16_pnp_resume,
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index b08e6e7690c9..e5ef1777161f 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -54,15 +54,6 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id)
}
}
-static void snd_sb8_free(struct snd_card *card)
-{
- struct snd_sb8 *acard = card->private_data;
-
- if (acard == NULL)
- return;
- release_and_free_resource(acard->fm_res);
-}
-
static int snd_sb8_match(struct device *pdev, unsigned int dev)
{
if (!enable[dev])
@@ -86,26 +77,26 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
struct snd_opl3 *opl3;
int err;
- err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_sb8), &card);
+ err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_sb8), &card);
if (err < 0)
return err;
acard = card->private_data;
- card->private_free = snd_sb8_free;
/*
* Block the 0x388 port to avoid PnP conflicts.
* No need to check this value after request_region,
* as we never do anything with it.
*/
- acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+ acard->fm_res = devm_request_region(card->dev, 0x388, 4,
+ "SoundBlaster FM");
if (port[dev] != SNDRV_AUTO_PORT) {
err = snd_sbdsp_create(card, port[dev], irq[dev],
snd_sb8_interrupt, dma8[dev],
-1, SB_HW_AUTO, &chip);
if (err < 0)
- goto _err;
+ return err;
} else {
/* auto-probe legacy ports */
static const unsigned long possible_ports[] = {
@@ -125,10 +116,8 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
break;
}
}
- if (i >= ARRAY_SIZE(possible_ports)) {
- err = -EINVAL;
- goto _err;
- }
+ if (i >= ARRAY_SIZE(possible_ports))
+ return -EINVAL;
}
acard->chip = chip;
@@ -139,17 +128,16 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
else
snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
port[dev]);
- err = -ENODEV;
- goto _err;
+ return -ENODEV;
}
err = snd_sb8dsp_pcm(chip, 0);
if (err < 0)
- goto _err;
+ return err;
err = snd_sbmixer_new(chip);
if (err < 0)
- goto _err;
+ return err;
if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) {
err = snd_opl3_create(card, chip->port + 8, 0,
@@ -167,12 +155,12 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
if (err >= 0) {
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
- goto _err;
+ return err;
}
err = snd_sb8dsp_midi(chip, 0);
if (err < 0)
- goto _err;
+ return err;
strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
strcpy(card->shortname, chip->name);
@@ -183,19 +171,10 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
err = snd_card_register(card);
if (err < 0)
- goto _err;
+ return err;
dev_set_drvdata(pdev, card);
return 0;
-
- _err:
- snd_card_free(card);
- return err;
-}
-
-static void snd_sb8_remove(struct device *pdev, unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(pdev));
}
#ifdef CONFIG_PM
@@ -229,7 +208,6 @@ static int snd_sb8_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_sb8_driver = {
.match = snd_sb8_match,
.probe = snd_sb8_probe,
- .remove = snd_sb8_remove,
#ifdef CONFIG_PM
.suspend = snd_sb8_suspend,
.resume = snd_sb8_resume,
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index 57121218ed24..c0e319d14210 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -168,31 +168,6 @@ static int snd_sbdsp_probe(struct snd_sb * chip)
return 0;
}
-static int snd_sbdsp_free(struct snd_sb *chip)
-{
- release_and_free_resource(chip->res_port);
- if (chip->irq >= 0)
- free_irq(chip->irq, (void *) chip);
-#ifdef CONFIG_ISA
- if (chip->dma8 >= 0) {
- disable_dma(chip->dma8);
- free_dma(chip->dma8);
- }
- if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) {
- disable_dma(chip->dma16);
- free_dma(chip->dma16);
- }
-#endif
- kfree(chip);
- return 0;
-}
-
-static int snd_sbdsp_dev_free(struct snd_device *device)
-{
- struct snd_sb *chip = device->device_data;
- return snd_sbdsp_free(chip);
-}
-
int snd_sbdsp_create(struct snd_card *card,
unsigned long port,
int irq,
@@ -204,15 +179,12 @@ int snd_sbdsp_create(struct snd_card *card,
{
struct snd_sb *chip;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_sbdsp_dev_free,
- };
if (snd_BUG_ON(!r_chip))
return -EINVAL;
*r_chip = NULL;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
+ chip = devm_kzalloc(card->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
spin_lock_init(&chip->open_lock);
@@ -223,13 +195,12 @@ int snd_sbdsp_create(struct snd_card *card,
chip->dma16 = -1;
chip->port = port;
- if (request_irq(irq, irq_handler,
- (hardware == SB_HW_ALS4000 ||
- hardware == SB_HW_CS5530) ?
- IRQF_SHARED : 0,
- "SoundBlaster", (void *) chip)) {
+ if (devm_request_irq(card->dev, irq, irq_handler,
+ (hardware == SB_HW_ALS4000 ||
+ hardware == SB_HW_CS5530) ?
+ IRQF_SHARED : 0,
+ "SoundBlaster", (void *) chip)) {
snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
- snd_sbdsp_free(chip);
return -EBUSY;
}
chip->irq = irq;
@@ -238,17 +209,17 @@ int snd_sbdsp_create(struct snd_card *card,
if (hardware == SB_HW_ALS4000)
goto __skip_allocation;
- chip->res_port = request_region(port, 16, "SoundBlaster");
+ chip->res_port = devm_request_region(card->dev, port, 16,
+ "SoundBlaster");
if (!chip->res_port) {
snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port);
- snd_sbdsp_free(chip);
return -EBUSY;
}
#ifdef CONFIG_ISA
- if (dma8 >= 0 && request_dma(dma8, "SoundBlaster - 8bit")) {
+ if (dma8 >= 0 && snd_devm_request_dma(card->dev, dma8,
+ "SoundBlaster - 8bit")) {
snd_printk(KERN_ERR "sb: can't grab DMA8 %d\n", dma8);
- snd_sbdsp_free(chip);
return -EBUSY;
}
chip->dma8 = dma8;
@@ -256,9 +227,9 @@ int snd_sbdsp_create(struct snd_card *card,
if (hardware != SB_HW_ALS100 && (dma16 < 5 || dma16 > 7)) {
/* no duplex */
dma16 = -1;
- } else if (request_dma(dma16, "SoundBlaster - 16bit")) {
+ } else if (snd_devm_request_dma(card->dev, dma16,
+ "SoundBlaster - 16bit")) {
snd_printk(KERN_ERR "sb: can't grab DMA16 %d\n", dma16);
- snd_sbdsp_free(chip);
return -EBUSY;
}
}
@@ -269,15 +240,8 @@ int snd_sbdsp_create(struct snd_card *card,
chip->card = card;
chip->hardware = hardware;
err = snd_sbdsp_probe(chip);
- if (err < 0) {
- snd_sbdsp_free(chip);
+ if (err < 0)
return err;
- }
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_sbdsp_free(chip);
- return err;
- }
*r_chip = chip;
return 0;
}
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index 3462663050bb..26ab7ff80768 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -529,6 +529,14 @@ static int snd_sc6000_match(struct device *devptr, unsigned int dev)
return 1;
}
+static void snd_sc6000_free(struct snd_card *card)
+{
+ char __iomem *vport = (char __force __iomem *)card->private_data;
+
+ if (vport)
+ sc6000_setup_board(vport, 0);
+}
+
static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
{
static const int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
@@ -539,22 +547,19 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
struct snd_card *card;
struct snd_wss *chip;
struct snd_opl3 *opl3;
- char __iomem **vport;
+ char __iomem *vport;
char __iomem *vmss_port;
-
- err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
- sizeof(vport), &card);
+ err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
+ 0, &card);
if (err < 0)
return err;
- vport = card->private_data;
if (xirq == SNDRV_AUTO_IRQ) {
xirq = snd_legacy_find_free_irq(possible_irqs);
if (xirq < 0) {
snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
- err = -EBUSY;
- goto err_exit;
+ return -EBUSY;
}
}
@@ -562,68 +567,65 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
xdma = snd_legacy_find_free_dma(possible_dmas);
if (xdma < 0) {
snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
- err = -EBUSY;
- goto err_exit;
+ return -EBUSY;
}
}
- if (!request_region(port[dev], 0x10, DRV_NAME)) {
+ if (!devm_request_region(devptr, port[dev], 0x10, DRV_NAME)) {
snd_printk(KERN_ERR PFX
"I/O port region is already in use.\n");
- err = -EBUSY;
- goto err_exit;
+ return -EBUSY;
}
- *vport = devm_ioport_map(devptr, port[dev], 0x10);
- if (*vport == NULL) {
+ vport = devm_ioport_map(devptr, port[dev], 0x10);
+ if (!vport) {
snd_printk(KERN_ERR PFX
"I/O port cannot be iomapped.\n");
- err = -EBUSY;
- goto err_unmap1;
+ return -EBUSY;
}
+ card->private_data = (void __force *)vport;
/* to make it marked as used */
- if (!request_region(mss_port[dev], 4, DRV_NAME)) {
+ if (!devm_request_region(devptr, mss_port[dev], 4, DRV_NAME)) {
snd_printk(KERN_ERR PFX
"SC-6000 port I/O port region is already in use.\n");
- err = -EBUSY;
- goto err_unmap1;
+ return -EBUSY;
}
vmss_port = devm_ioport_map(devptr, mss_port[dev], 4);
if (!vmss_port) {
snd_printk(KERN_ERR PFX
"MSS port I/O cannot be iomapped.\n");
- err = -EBUSY;
- goto err_unmap2;
+ return -EBUSY;
}
snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n",
port[dev], xirq, xdma,
mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]);
- err = sc6000_init_board(*vport, vmss_port, dev);
+ err = sc6000_init_board(vport, vmss_port, dev);
if (err < 0)
- goto err_unmap2;
+ return err;
+ card->private_free = snd_sc6000_free;
err = snd_wss_create(card, mss_port[dev] + 4, -1, xirq, xdma, -1,
WSS_HW_DETECT, 0, &chip);
if (err < 0)
- goto err_unmap2;
+ return err;
err = snd_wss_pcm(chip, 0);
if (err < 0) {
snd_printk(KERN_ERR PFX
"error creating new WSS PCM device\n");
- goto err_unmap2;
+ return err;
}
err = snd_wss_mixer(chip);
if (err < 0) {
snd_printk(KERN_ERR PFX "error creating new WSS mixer\n");
- goto err_unmap2;
+ return err;
}
err = snd_sc6000_mixer(chip);
if (err < 0) {
snd_printk(KERN_ERR PFX "the mixer rewrite failed\n");
- goto err_unmap2;
+ return err;
}
if (snd_opl3_create(card,
0x388, 0x388 + 2,
@@ -633,7 +635,7 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
} else {
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
- goto err_unmap2;
+ return err;
}
if (mpu_port[dev] != SNDRV_AUTO_PORT) {
@@ -654,39 +656,15 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
err = snd_card_register(card);
if (err < 0)
- goto err_unmap2;
+ return err;
dev_set_drvdata(devptr, card);
return 0;
-
-err_unmap2:
- sc6000_setup_board(*vport, 0);
- release_region(mss_port[dev], 4);
-err_unmap1:
- release_region(port[dev], 0x10);
-err_exit:
- snd_card_free(card);
- return err;
-}
-
-static void snd_sc6000_remove(struct device *devptr, unsigned int dev)
-{
- struct snd_card *card = dev_get_drvdata(devptr);
- char __iomem **vport = card->private_data;
-
- if (sc6000_setup_board(*vport, 0) < 0)
- snd_printk(KERN_WARNING "sc6000_setup_board failed on exit!\n");
-
- release_region(port[dev], 0x10);
- release_region(mss_port[dev], 4);
-
- snd_card_free(card);
}
static struct isa_driver snd_sc6000_driver = {
.match = snd_sc6000_match,
.probe = snd_sc6000_probe,
- .remove = snd_sc6000_remove,
/* FIXME: suspend/resume */
.driver = {
.name = DRV_NAME,
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index e70ef9aee545..0bc0025f7c19 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -328,17 +328,6 @@ static void activate_ad1845_unsafe(unsigned io_base)
}
/*
- * Do the necessary ALSA-level cleanup to deallocate our driver ...
- */
-static void soundscape_free(struct snd_card *c)
-{
- struct soundscape *sscape = get_card_soundscape(c);
- release_and_free_resource(sscape->io_res);
- release_and_free_resource(sscape->wss_res);
- free_dma(sscape->chip->dma1);
-}
-
-/*
* Tell the SoundScape to begin a DMA transfer using the given channel.
* All locking issues are left to the caller.
*/
@@ -941,7 +930,7 @@ static int create_sscape(int dev, struct snd_card *card)
* Grab IO ports that we will need to probe so that we
* can detect and control this hardware ...
*/
- io_res = request_region(port[dev], 8, "SoundScape");
+ io_res = devm_request_region(card->dev, port[dev], 8, "SoundScape");
if (!io_res) {
snd_printk(KERN_ERR
"sscape: can't grab port 0x%lx\n", port[dev]);
@@ -949,22 +938,22 @@ static int create_sscape(int dev, struct snd_card *card)
}
wss_res = NULL;
if (sscape->type == SSCAPE_VIVO) {
- wss_res = request_region(wss_port[dev], 4, "SoundScape");
+ wss_res = devm_request_region(card->dev, wss_port[dev], 4,
+ "SoundScape");
if (!wss_res) {
snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n",
wss_port[dev]);
- err = -EBUSY;
- goto _release_region;
+ return -EBUSY;
}
}
/*
* Grab one DMA channel ...
*/
- err = request_dma(dma[dev], "SoundScape");
+ err = snd_devm_request_dma(card->dev, dma[dev], "SoundScape");
if (err < 0) {
snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]);
- goto _release_region;
+ return err;
}
spin_lock_init(&sscape->lock);
@@ -975,8 +964,7 @@ static int create_sscape(int dev, struct snd_card *card)
if (!detect_sscape(sscape, wss_port[dev])) {
printk(KERN_ERR "sscape: hardware not detected at 0x%x\n",
sscape->io_base);
- err = -ENODEV;
- goto _release_dma;
+ return -ENODEV;
}
switch (sscape->type) {
@@ -1006,15 +994,13 @@ static int create_sscape(int dev, struct snd_card *card)
irq_cfg = get_irq_config(sscape->type, irq[dev]);
if (irq_cfg == INVALID_IRQ) {
snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
- err = -ENXIO;
- goto _release_dma;
+ return -ENXIO;
}
mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]);
if (mpu_irq_cfg == INVALID_IRQ) {
snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
- err = -ENXIO;
- goto _release_dma;
+ return -ENXIO;
}
/*
@@ -1060,7 +1046,7 @@ static int create_sscape(int dev, struct snd_card *card)
snd_printk(KERN_ERR
"sscape: No AD1845 device at 0x%lx, IRQ %d\n",
wss_port[dev], irq[dev]);
- goto _release_dma;
+ return err;
}
strcpy(card->driver, "SoundScape");
strcpy(card->shortname, name);
@@ -1082,7 +1068,7 @@ static int create_sscape(int dev, struct snd_card *card)
snd_printk(KERN_ERR "sscape: Failed to create "
"MPU-401 device at 0x%lx\n",
port[dev]);
- goto _release_dma;
+ return err;
}
/*
@@ -1109,24 +1095,7 @@ static int create_sscape(int dev, struct snd_card *card)
}
}
- /*
- * Now that we have successfully created this sound card,
- * it is safe to store the pointer.
- * NOTE: we only register the sound card's "destructor"
- * function now that our "constructor" has completed.
- */
- card->private_free = soundscape_free;
-
return 0;
-
-_release_dma:
- free_dma(dma[dev]);
-
-_release_region:
- release_and_free_resource(wss_res);
- release_and_free_resource(io_res);
-
- return err;
}
@@ -1156,8 +1125,8 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev)
struct soundscape *sscape;
int ret;
- ret = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct soundscape), &card);
+ ret = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct soundscape), &card);
if (ret < 0)
return ret;
@@ -1168,24 +1137,15 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev)
ret = create_sscape(dev, card);
if (ret < 0)
- goto _release_card;
+ return ret;
ret = snd_card_register(card);
if (ret < 0) {
snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
- goto _release_card;
+ return ret;
}
dev_set_drvdata(pdev, card);
return 0;
-
-_release_card:
- snd_card_free(card);
- return ret;
-}
-
-static void snd_sscape_remove(struct device *devptr, unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
}
#define DEV_NAME "sscape"
@@ -1193,7 +1153,6 @@ static void snd_sscape_remove(struct device *devptr, unsigned int dev)
static struct isa_driver snd_sscape_driver = {
.match = snd_sscape_match,
.probe = snd_sscape_probe,
- .remove = snd_sscape_remove,
/* FIXME: suspend/resume */
.driver = {
.name = DEV_NAME
@@ -1244,9 +1203,9 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard,
* Create a new ALSA sound card entry, in anticipation
* of detecting our hardware ...
*/
- ret = snd_card_new(&pcard->card->dev,
- index[idx], id[idx], THIS_MODULE,
- sizeof(struct soundscape), &card);
+ ret = snd_devm_card_new(&pcard->card->dev,
+ index[idx], id[idx], THIS_MODULE,
+ sizeof(struct soundscape), &card);
if (ret < 0)
return ret;
@@ -1277,27 +1236,17 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard,
ret = create_sscape(idx, card);
if (ret < 0)
- goto _release_card;
+ return ret;
ret = snd_card_register(card);
if (ret < 0) {
snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
- goto _release_card;
+ return ret;
}
pnp_set_card_drvdata(pcard, card);
++idx;
return 0;
-
-_release_card:
- snd_card_free(card);
- return ret;
-}
-
-static void sscape_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
}
static struct pnp_card_driver sscape_pnpc_driver = {
@@ -1305,7 +1254,6 @@ static struct pnp_card_driver sscape_pnpc_driver = {
.name = "sscape",
.id_table = sscape_pnpids,
.probe = sscape_pnp_detect,
- .remove = sscape_pnp_remove,
};
#endif /* CONFIG_PNP */
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index dfdeaf7b6bf4..e6e46a0266b0 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -308,18 +308,6 @@ static struct snd_rawmidi *snd_wavefront_new_midi(struct snd_card *card,
return rmidi;
}
-static void
-snd_wavefront_free(struct snd_card *card)
-{
- snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data;
-
- if (acard) {
- release_and_free_resource(acard->wavefront.res_base);
- if (acard->wavefront.irq > 0)
- free_irq(acard->wavefront.irq, (void *)acard);
- }
-}
-
static int snd_wavefront_card_new(struct device *pdev, int dev,
struct snd_card **cardp)
{
@@ -327,8 +315,8 @@ static int snd_wavefront_card_new(struct device *pdev, int dev,
snd_wavefront_card_t *acard;
int err;
- err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
- sizeof(snd_wavefront_card_t), &card);
+ err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
+ sizeof(snd_wavefront_card_t), &card);
if (err < 0)
return err;
@@ -339,7 +327,6 @@ static int snd_wavefront_card_new(struct device *pdev, int dev,
spin_lock_init(&acard->wavefront.midi.open);
spin_lock_init(&acard->wavefront.midi.virtual);
acard->wavefront.card = card;
- card->private_free = snd_wavefront_free;
*cardp = card;
return 0;
@@ -394,15 +381,17 @@ snd_wavefront_probe (struct snd_card *card, int dev)
/* ------- ICS2115 Wavetable synth ------- */
- acard->wavefront.res_base = request_region(ics2115_port[dev], 16,
- "ICS2115");
+ acard->wavefront.res_base =
+ devm_request_region(card->dev, ics2115_port[dev], 16,
+ "ICS2115");
if (acard->wavefront.res_base == NULL) {
snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
ics2115_port[dev], ics2115_port[dev] + 16 - 1);
return -EBUSY;
}
- if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt,
- 0, "ICS2115", acard)) {
+ if (devm_request_irq(card->dev, ics2115_irq[dev],
+ snd_wavefront_ics2115_interrupt,
+ 0, "ICS2115", acard)) {
snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
return -EBUSY;
}
@@ -556,27 +545,18 @@ static int snd_wavefront_isa_probe(struct device *pdev,
if (err < 0)
return err;
err = snd_wavefront_probe(card, dev);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
dev_set_drvdata(pdev, card);
return 0;
}
-static void snd_wavefront_isa_remove(struct device *devptr,
- unsigned int dev)
-{
- snd_card_free(dev_get_drvdata(devptr));
-}
-
#define DEV_NAME "wavefront"
static struct isa_driver snd_wavefront_driver = {
.match = snd_wavefront_isa_match,
.probe = snd_wavefront_isa_probe,
- .remove = snd_wavefront_isa_remove,
/* FIXME: suspend, resume */
.driver = {
.name = DEV_NAME
@@ -606,7 +586,6 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) {
if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
snd_printk (KERN_ERR "isapnp detection failed\n");
- snd_card_free (card);
return -ENODEV;
}
}
@@ -620,18 +599,11 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
return 0;
}
-static void snd_wavefront_pnp_remove(struct pnp_card_link *pcard)
-{
- snd_card_free(pnp_get_card_drvdata(pcard));
- pnp_set_card_drvdata(pcard, NULL);
-}
-
static struct pnp_card_driver wavefront_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "wavefront",
.id_table = snd_wavefront_pnpids,
.probe = snd_wavefront_pnp_detect,
- .remove = snd_wavefront_pnp_remove,
/* FIXME: suspend,resume */
};
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 743e0f05e335..026061b55ee9 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -1655,36 +1655,6 @@ static void snd_wss_resume(struct snd_wss *chip)
}
#endif /* CONFIG_PM */
-static int snd_wss_free(struct snd_wss *chip)
-{
- release_and_free_resource(chip->res_port);
- release_and_free_resource(chip->res_cport);
- if (chip->irq >= 0) {
- disable_irq(chip->irq);
- if (!(chip->hwshare & WSS_HWSHARE_IRQ))
- free_irq(chip->irq, (void *) chip);
- }
- if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
- snd_dma_disable(chip->dma1);
- free_dma(chip->dma1);
- }
- if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
- chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
- snd_dma_disable(chip->dma2);
- free_dma(chip->dma2);
- }
- if (chip->timer)
- snd_device_free(chip->card, chip->timer);
- kfree(chip);
- return 0;
-}
-
-static int snd_wss_dev_free(struct snd_device *device)
-{
- struct snd_wss *chip = device->device_data;
- return snd_wss_free(chip);
-}
-
const char *snd_wss_chip_id(struct snd_wss *chip)
{
switch (chip->hardware) {
@@ -1738,7 +1708,7 @@ static int snd_wss_new(struct snd_card *card,
struct snd_wss *chip;
*rchip = NULL;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ chip = devm_kzalloc(card->dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->hardware = hardware;
@@ -1774,9 +1744,6 @@ int snd_wss_create(struct snd_card *card,
unsigned short hwshare,
struct snd_wss **rchip)
{
- static const struct snd_device_ops ops = {
- .dev_free = snd_wss_dev_free,
- };
struct snd_wss *chip;
int err;
@@ -1788,42 +1755,39 @@ int snd_wss_create(struct snd_card *card,
chip->dma1 = -1;
chip->dma2 = -1;
- chip->res_port = request_region(port, 4, "WSS");
+ chip->res_port = devm_request_region(card->dev, port, 4, "WSS");
if (!chip->res_port) {
snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
- snd_wss_free(chip);
return -EBUSY;
}
chip->port = port;
if ((long)cport >= 0) {
- chip->res_cport = request_region(cport, 8, "CS4232 Control");
+ chip->res_cport = devm_request_region(card->dev, cport, 8,
+ "CS4232 Control");
if (!chip->res_cport) {
snd_printk(KERN_ERR
"wss: can't grab control port 0x%lx\n", cport);
- snd_wss_free(chip);
return -ENODEV;
}
}
chip->cport = cport;
if (!(hwshare & WSS_HWSHARE_IRQ))
- if (request_irq(irq, snd_wss_interrupt, 0,
- "WSS", (void *) chip)) {
+ if (devm_request_irq(card->dev, irq, snd_wss_interrupt, 0,
+ "WSS", (void *) chip)) {
snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
- snd_wss_free(chip);
return -EBUSY;
}
chip->irq = irq;
card->sync_irq = chip->irq;
- if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
+ if (!(hwshare & WSS_HWSHARE_DMA1) &&
+ snd_devm_request_dma(card->dev, dma1, "WSS - 1")) {
snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
- snd_wss_free(chip);
return -EBUSY;
}
chip->dma1 = dma1;
- if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
- dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
+ if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 &&
+ snd_devm_request_dma(card->dev, dma2, "WSS - 2")) {
snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
- snd_wss_free(chip);
return -EBUSY;
}
if (dma1 == dma2 || dma2 < 0) {
@@ -1839,10 +1803,8 @@ int snd_wss_create(struct snd_card *card,
}
/* global setup */
- if (snd_wss_probe(chip) < 0) {
- snd_wss_free(chip);
+ if (snd_wss_probe(chip) < 0)
return -ENODEV;
- }
snd_wss_init(chip);
#if 0
@@ -1853,13 +1815,6 @@ int snd_wss_create(struct snd_card *card,
}
#endif
- /* Register device */
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_wss_free(chip);
- return err;
- }
-
#ifdef CONFIG_PM
/* Power Management */
chip->suspend = snd_wss_suspend;
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index 1440db8b4177..db9c296dd688 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -563,22 +563,9 @@ snd_harmony_capture_close(struct snd_pcm_substream *ss)
return 0;
}
-static int
-snd_harmony_hw_params(struct snd_pcm_substream *ss,
- struct snd_pcm_hw_params *hw)
-{
- struct snd_harmony *h = snd_pcm_substream_chip(ss);
-
- if (h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS)
- ss->runtime->dma_addr = __pa(ss->runtime->dma_area);
-
- return 0;
-}
-
static const struct snd_pcm_ops snd_harmony_playback_ops = {
.open = snd_harmony_playback_open,
.close = snd_harmony_playback_close,
- .hw_params = snd_harmony_hw_params,
.prepare = snd_harmony_playback_prepare,
.trigger = snd_harmony_playback_trigger,
.pointer = snd_harmony_playback_pointer,
@@ -587,7 +574,6 @@ static const struct snd_pcm_ops snd_harmony_playback_ops = {
static const struct snd_pcm_ops snd_harmony_capture_ops = {
.open = snd_harmony_capture_open,
.close = snd_harmony_capture_close,
- .hw_params = snd_harmony_hw_params,
.prepare = snd_harmony_capture_prepare,
.trigger = snd_harmony_capture_trigger,
.pointer = snd_harmony_capture_pointer,
@@ -968,11 +954,10 @@ free_and_ret:
return err;
}
-static int __exit
+static void __exit
snd_harmony_remove(struct parisc_device *padev)
{
snd_card_free(parisc_get_drvdata(padev));
- return 0;
}
static struct parisc_driver snd_harmony_driver __refdata = {
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 5c78951dd596..bba4dae8dcc7 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -740,20 +740,6 @@ snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
}
-static void
-snd_ad1889_ac97_bus_free(struct snd_ac97_bus *bus)
-{
- struct snd_ad1889 *chip = bus->private_data;
- chip->ac97_bus = NULL;
-}
-
-static void
-snd_ad1889_ac97_free(struct snd_ac97 *ac97)
-{
- struct snd_ad1889 *chip = ac97->private_data;
- chip->ac97 = NULL;
-}
-
static int
snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
{
@@ -771,11 +757,8 @@ snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
if (err < 0)
return err;
- chip->ac97_bus->private_free = snd_ad1889_ac97_bus_free;
-
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
- ac97.private_free = snd_ad1889_ac97_free;
ac97.pci = chip->pci;
err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
@@ -787,11 +770,10 @@ snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
return 0;
}
-static int
-snd_ad1889_free(struct snd_ad1889 *chip)
+static void
+snd_ad1889_free(struct snd_card *card)
{
- if (chip->irq < 0)
- goto skip_hw;
+ struct snd_ad1889 *chip = card->private_data;
spin_lock_irq(&chip->lock);
@@ -805,125 +787,60 @@ snd_ad1889_free(struct snd_ad1889 *chip)
ad1889_readl(chip, AD_DMA_DISR); /* flush, dammit! */
spin_unlock_irq(&chip->lock);
-
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
-
-skip_hw:
- iounmap(chip->iobase);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int
-snd_ad1889_dev_free(struct snd_device *device)
-{
- struct snd_ad1889 *chip = device->device_data;
- return snd_ad1889_free(chip);
-}
-
-static int
-snd_ad1889_init(struct snd_ad1889 *chip)
-{
- ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
- ad1889_readw(chip, AD_DS_CCS); /* flush posted write */
-
- usleep_range(10000, 11000);
-
- /* enable Master and Target abort interrupts */
- ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
-
- return 0;
}
static int
-snd_ad1889_create(struct snd_card *card,
- struct pci_dev *pci,
- struct snd_ad1889 **rchip)
+snd_ad1889_create(struct snd_card *card, struct pci_dev *pci)
{
+ struct snd_ad1889 *chip = card->private_data;
int err;
- struct snd_ad1889 *chip;
- static const struct snd_device_ops ops = {
- .dev_free = snd_ad1889_dev_free,
- };
-
- *rchip = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check PCI availability (32bit DMA) */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_err(card->dev, "error setting 32-bit DMA mask.\n");
- pci_disable_device(pci);
return -ENXIO;
}
- /* allocate chip specific data with zero-filled memory */
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
chip->card = card;
- card->private_data = chip;
chip->pci = pci;
chip->irq = -1;
/* (1) PCI resource allocation */
- err = pci_request_regions(pci, card->driver);
+ err = pcim_iomap_regions(pci, 1 << 0, card->driver);
if (err < 0)
- goto free_and_ret;
+ return err;
chip->bar = pci_resource_start(pci, 0);
- chip->iobase = pci_ioremap_bar(pci, 0);
- if (chip->iobase == NULL) {
- dev_err(card->dev, "unable to reserve region.\n");
- err = -EBUSY;
- goto free_and_ret;
- }
+ chip->iobase = pcim_iomap_table(pci)[0];
pci_set_master(pci);
spin_lock_init(&chip->lock); /* only now can we call ad1889_free */
- if (request_irq(pci->irq, snd_ad1889_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_ad1889_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "cannot obtain IRQ %d\n", pci->irq);
- snd_ad1889_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_ad1889_free;
/* (2) initialization of the chip hardware */
- err = snd_ad1889_init(chip);
- if (err < 0) {
- snd_ad1889_free(chip);
- return err;
- }
+ ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
+ ad1889_readw(chip, AD_DS_CCS); /* flush posted write */
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_ad1889_free(chip);
- return err;
- }
+ usleep_range(10000, 11000);
- *rchip = chip;
+ /* enable Master and Target abort interrupts */
+ ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
return 0;
-
-free_and_ret:
- kfree(chip);
- pci_disable_device(pci);
-
- return err;
}
static int
@@ -944,19 +861,19 @@ snd_ad1889_probe(struct pci_dev *pci,
}
/* (2) */
- err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
- 0, &card);
- /* XXX REVISIT: we can probably allocate chip in this call */
+ err = snd_devm_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
strcpy(card->driver, "AD1889");
strcpy(card->shortname, "Analog Devices AD1889");
/* (3) */
- err = snd_ad1889_create(card, pci, &chip);
+ err = snd_ad1889_create(card, pci);
if (err < 0)
- goto free_and_ret;
+ return err;
/* (4) */
sprintf(card->longname, "%s at 0x%lx irq %i",
@@ -966,11 +883,11 @@ snd_ad1889_probe(struct pci_dev *pci,
/* register AC97 mixer */
err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]);
if (err < 0)
- goto free_and_ret;
+ return err;
err = snd_ad1889_pcm_init(chip, 0);
if (err < 0)
- goto free_and_ret;
+ return err;
/* register proc interface */
snd_ad1889_proc_init(chip);
@@ -978,23 +895,13 @@ snd_ad1889_probe(struct pci_dev *pci,
/* (6) */
err = snd_card_register(card);
if (err < 0)
- goto free_and_ret;
+ return err;
/* (7) */
pci_set_drvdata(pci, card);
devno++;
return 0;
-
-free_and_ret:
- snd_card_free(card);
- return err;
-}
-
-static void
-snd_ad1889_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static const struct pci_device_id snd_ad1889_ids[] = {
@@ -1007,7 +914,6 @@ static struct pci_driver ad1889_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ad1889_ids,
.probe = snd_ad1889_probe,
- .remove = snd_ad1889_remove,
};
module_pci_driver(ad1889_pci_driver);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 0d66b92466d5..92eb59db106d 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1914,22 +1914,14 @@ static SIMPLE_DEV_PM_OPS(ali_pm, ali_suspend, ali_resume);
#define ALI_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
-static int snd_ali_free(struct snd_ali * codec)
+static void snd_ali_free(struct snd_card *card)
{
+ struct snd_ali *codec = card->private_data;
+
if (codec->hw_initialized)
snd_ali_disable_address_interrupt(codec);
- if (codec->irq >= 0)
- free_irq(codec->irq, codec);
- if (codec->port)
- pci_release_regions(codec->pci);
- pci_disable_device(codec->pci);
-#ifdef CONFIG_PM_SLEEP
- kfree(codec->image);
-#endif
pci_dev_put(codec->pci_m1533);
pci_dev_put(codec->pci_m7101);
- kfree(codec);
- return 0;
}
static int snd_ali_chip_init(struct snd_ali *codec)
@@ -2017,8 +2009,9 @@ static int snd_ali_resources(struct snd_ali *codec)
return err;
codec->port = pci_resource_start(codec->pci, 0);
- if (request_irq(codec->pci->irq, snd_ali_card_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, codec)) {
+ if (devm_request_irq(&codec->pci->dev, codec->pci->irq,
+ snd_ali_card_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, codec)) {
dev_err(codec->card->dev, "Unable to request irq.\n");
return -EBUSY;
}
@@ -2027,48 +2020,29 @@ static int snd_ali_resources(struct snd_ali *codec)
dev_dbg(codec->card->dev, "resources allocated.\n");
return 0;
}
-static int snd_ali_dev_free(struct snd_device *device)
-{
- struct snd_ali *codec = device->device_data;
- snd_ali_free(codec);
- return 0;
-}
static int snd_ali_create(struct snd_card *card,
struct pci_dev *pci,
int pcm_streams,
- int spdif_support,
- struct snd_ali **r_ali)
+ int spdif_support)
{
- struct snd_ali *codec;
+ struct snd_ali *codec = card->private_data;
int i, err;
unsigned short cmdw;
- static const struct snd_device_ops ops = {
- .dev_free = snd_ali_dev_free,
- };
-
- *r_ali = NULL;
dev_dbg(card->dev, "creating ...\n");
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 31 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31))) {
dev_err(card->dev,
"architecture does not support 31bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- codec = kzalloc(sizeof(*codec), GFP_KERNEL);
- if (!codec) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
spin_lock_init(&codec->reg_lock);
spin_lock_init(&codec->voice_alloc);
@@ -2089,12 +2063,10 @@ static int snd_ali_create(struct snd_card *card,
cmdw |= PCI_COMMAND_IO;
pci_write_config_word(pci, PCI_COMMAND, cmdw);
}
- pci_set_master(pci);
- if (snd_ali_resources(codec)) {
- snd_ali_free(codec);
+ if (snd_ali_resources(codec))
return -EBUSY;
- }
+ card->private_free = snd_ali_free;
codec->synth.chmap = 0;
codec->synth.chcnt = 0;
@@ -2121,24 +2093,15 @@ static int snd_ali_create(struct snd_card *card,
codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL);
if (!codec->pci_m1533) {
dev_err(card->dev, "cannot find ALi 1533 chip.\n");
- snd_ali_free(codec);
return -ENODEV;
}
/* M7101: power management */
codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL);
if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) {
dev_err(card->dev, "cannot find ALi 7101 chip.\n");
- snd_ali_free(codec);
return -ENODEV;
}
- dev_dbg(card->dev, "snd_device_new is called.\n");
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops);
- if (err < 0) {
- snd_ali_free(codec);
- return err;
- }
-
/* initialise synth voices*/
for (i = 0; i < ALI_CHANNELS; i++)
codec->synth.voices[i].number = i;
@@ -2150,16 +2113,14 @@ static int snd_ali_create(struct snd_card *card,
}
#ifdef CONFIG_PM_SLEEP
- codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL);
+ codec->image = devm_kmalloc(&pci->dev, sizeof(*codec->image),
+ GFP_KERNEL);
if (!codec->image)
dev_warn(card->dev, "can't allocate apm buffer\n");
#endif
snd_ali_enable_address_interrupt(codec);
codec->hw_initialized = 1;
-
- *r_ali = codec;
- dev_dbg(card->dev, "created.\n");
return 0;
}
@@ -2172,24 +2133,25 @@ static int snd_ali_probe(struct pci_dev *pci,
dev_dbg(&pci->dev, "probe ...\n");
- err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*codec), &card);
if (err < 0)
return err;
+ codec = card->private_data;
- err = snd_ali_create(card, pci, pcm_channels, spdif, &codec);
+ err = snd_ali_create(card, pci, pcm_channels, spdif);
if (err < 0)
- goto error;
- card->private_data = codec;
+ return err;
dev_dbg(&pci->dev, "mixer building ...\n");
err = snd_ali_mixer(codec);
if (err < 0)
- goto error;
+ return err;
dev_dbg(&pci->dev, "pcm building ...\n");
err = snd_ali_build_pcms(codec);
if (err < 0)
- goto error;
+ return err;
snd_ali_proc_init(codec);
@@ -2202,26 +2164,16 @@ static int snd_ali_probe(struct pci_dev *pci,
dev_dbg(&pci->dev, "register card.\n");
err = snd_card_register(card);
if (err < 0)
- goto error;
+ return err;
pci_set_drvdata(pci, card);
return 0;
-
- error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_ali_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver ali5451_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ali_ids,
.probe = snd_ali_probe,
- .remove = snd_ali_remove,
.driver = {
.pm = ALI_PM_OPS,
},
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 668008fc21f7..b86565dcdbe4 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -163,21 +163,11 @@ static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd)
snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp);
}
-static int snd_als300_free(struct snd_als300 *chip)
+static void snd_als300_free(struct snd_card *card)
{
- snd_als300_set_irq_flag(chip, IRQ_DISABLE);
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
+ struct snd_als300 *chip = card->private_data;
-static int snd_als300_dev_free(struct snd_device *device)
-{
- struct snd_als300 *chip = device->device_data;
- return snd_als300_free(chip);
+ snd_als300_set_irq_flag(chip, IRQ_DISABLE);
}
static irqreturn_t snd_als300_interrupt(int irq, void *dev_id)
@@ -248,11 +238,6 @@ static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void snd_als300_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
@@ -610,35 +595,22 @@ static void snd_als300_init(struct snd_als300 *chip)
}
static int snd_als300_create(struct snd_card *card,
- struct pci_dev *pci, int chip_type,
- struct snd_als300 **rchip)
+ struct pci_dev *pci, int chip_type)
{
- struct snd_als300 *chip;
+ struct snd_als300 *chip = card->private_data;
void *irq_handler;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_als300_dev_free,
- };
- *rchip = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
dev_err(card->dev, "error setting 28bit DMA mask\n");
- pci_disable_device(pci);
return -ENXIO;
}
pci_set_master(pci);
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
chip->card = card;
chip->pci = pci;
chip->irq = -1;
@@ -646,11 +618,9 @@ static int snd_als300_create(struct snd_card *card,
spin_lock_init(&chip->reg_lock);
err = pci_request_regions(pci, "ALS300");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
+
chip->port = pci_resource_start(pci, 0);
if (chip->chip_type == DEVICE_ALS300_PLUS)
@@ -658,38 +628,29 @@ static int snd_als300_create(struct snd_card *card,
else
irq_handler = snd_als300_interrupt;
- if (request_irq(pci->irq, irq_handler, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, irq_handler, IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_als300_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_als300_free;
snd_als300_init(chip);
err = snd_als300_ac97(chip);
if (err < 0) {
dev_err(card->dev, "Could not create ac97\n");
- snd_als300_free(chip);
return err;
}
err = snd_als300_new_pcm(chip);
if (err < 0) {
dev_err(card->dev, "Could not create PCM\n");
- snd_als300_free(chip);
- return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_als300_free(chip);
return err;
}
- *rchip = chip;
return 0;
}
@@ -737,20 +698,17 @@ static int snd_als300_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
-
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
chip_type = pci_id->driver_data;
- err = snd_als300_create(card, pci, chip_type, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_als300_create(card, pci, chip_type);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
strcpy(card->driver, "ALS300");
if (chip->chip_type == DEVICE_ALS300_PLUS)
@@ -764,10 +722,9 @@ static int snd_als300_probe(struct pci_dev *pci,
card->shortname, chip->port, chip->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
+
pci_set_drvdata(pci, card);
dev++;
return 0;
@@ -777,7 +734,6 @@ static struct pci_driver als300_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_als300_ids,
.probe = snd_als300_probe,
- .remove = snd_als300_remove,
.driver = {
.pm = SND_ALS300_PM_OPS,
},
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 509f317ee682..535eccd124be 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -746,13 +746,15 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
if (joystick_port[dev] == 1) { /* auto-detect */
for (io_port = 0x200; io_port <= 0x218; io_port += 8) {
- r = request_region(io_port, 8, "ALS4000 gameport");
+ r = devm_request_region(&acard->pci->dev, io_port, 8,
+ "ALS4000 gameport");
if (r)
break;
}
} else {
io_port = joystick_port[dev];
- r = request_region(io_port, 8, "ALS4000 gameport");
+ r = devm_request_region(&acard->pci->dev, io_port, 8,
+ "ALS4000 gameport");
}
if (!r) {
@@ -763,7 +765,6 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
acard->gameport = gp = gameport_allocate_port();
if (!gp) {
dev_err(&acard->pci->dev, "cannot allocate memory for gameport\n");
- release_and_free_resource(r);
return -ENOMEM;
}
@@ -771,7 +772,6 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci));
gameport_set_dev_parent(gp, &acard->pci->dev);
gp->io = io_port;
- gameport_set_port_data(gp, r);
/* Enable legacy joystick port */
snd_als4000_set_addr(acard->iobase, 0, 0, 0, 1);
@@ -784,15 +784,11 @@ static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
static void snd_als4000_free_gameport(struct snd_card_als4000 *acard)
{
if (acard->gameport) {
- struct resource *r = gameport_get_port_data(acard->gameport);
-
gameport_unregister_port(acard->gameport);
acard->gameport = NULL;
/* disable joystick */
snd_als4000_set_addr(acard->iobase, 0, 0, 0, 0);
-
- release_and_free_resource(r);
}
}
#else
@@ -808,8 +804,6 @@ static void snd_card_als4000_free( struct snd_card *card )
snd_als4k_gcr_write_addr(acard->iobase, ALS4K_GCR8C_MISC_CTRL, 0);
/* free resources */
snd_als4000_free_gameport(acard);
- pci_release_regions(acard->pci);
- pci_disable_device(acard->pci);
}
static int snd_card_als4000_probe(struct pci_dev *pci,
@@ -832,36 +826,30 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
}
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
err = pci_request_regions(pci, "ALS4000");
- if (err < 0) {
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
iobase = pci_resource_start(pci, 0);
pci_read_config_word(pci, PCI_COMMAND, &word);
pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO);
pci_set_master(pci);
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(*acard) /* private_data: acard */,
- &card);
- if (err < 0) {
- pci_release_regions(pci);
- pci_disable_device(pci);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*acard) /* private_data: acard */,
+ &card);
+ if (err < 0)
return err;
- }
acard = card->private_data;
acard->pci = pci;
@@ -881,7 +869,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
SB_HW_ALS4000,
&chip);
if (err < 0)
- goto out_err;
+ return err;
acard->chip = chip;
chip->pci = pci;
@@ -902,7 +890,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
if (err < 0) {
dev_err(&pci->dev, "no MPU-401 device at 0x%lx?\n",
iobase + ALS4K_IOB_30_MIDI_DATA);
- goto out_err;
+ return err;
}
/* FIXME: ALS4000 has interesting MPU401 configuration features
* at ALS4K_CR1A_MPU401_UART_MODE_CONTROL
@@ -912,11 +900,11 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
err = snd_als4000_pcm(chip, 0);
if (err < 0)
- goto out_err;
+ return err;
err = snd_sbmixer_new(chip);
if (err < 0)
- goto out_err;
+ return err;
if (snd_opl3_create(card,
iobase + ALS4K_IOB_10_ADLIB_ADDR0,
@@ -928,30 +916,18 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
} else {
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
- goto out_err;
+ return err;
}
snd_als4000_create_gameport(acard, dev);
err = snd_card_register(card);
if (err < 0)
- goto out_err;
+ return err;
pci_set_drvdata(pci, card);
dev++;
- err = 0;
- goto out;
-
-out_err:
- snd_card_free(card);
-
-out:
- return err;
-}
-
-static void snd_card_als4000_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
+ return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -996,7 +972,6 @@ static struct pci_driver als4000_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_als4000_ids,
.probe = snd_card_als4000_probe,
- .remove = snd_card_als4000_remove,
.driver = {
.pm = SND_ALS4000_PM_OPS,
},
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 5f8aa35c4bea..b8e035d5930d 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1530,87 +1530,44 @@ static void snd_atiixp_proc_init(struct atiixp *chip)
* destructor
*/
-static int snd_atiixp_free(struct atiixp *chip)
+static void snd_atiixp_free(struct snd_card *card)
{
- if (chip->irq < 0)
- goto __hw_end;
- snd_atiixp_chip_stop(chip);
-
- __hw_end:
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- iounmap(chip->remap_addr);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_atiixp_dev_free(struct snd_device *device)
-{
- struct atiixp *chip = device->device_data;
- return snd_atiixp_free(chip);
+ snd_atiixp_chip_stop(card->private_data);
}
/*
* constructor for chip instance
*/
-static int snd_atiixp_create(struct snd_card *card,
- struct pci_dev *pci,
- struct atiixp **r_chip)
+static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
{
- static const struct snd_device_ops ops = {
- .dev_free = snd_atiixp_dev_free,
- };
- struct atiixp *chip;
+ struct atiixp *chip = card->private_data;
int err;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
spin_lock_init(&chip->reg_lock);
mutex_init(&chip->open_mutex);
chip->card = card;
chip->pci = pci;
chip->irq = -1;
- err = pci_request_regions(pci, "ATI IXP AC97");
- if (err < 0) {
- pci_disable_device(pci);
- kfree(chip);
+ err = pcim_iomap_regions(pci, 1 << 0, "ATI IXP AC97");
+ if (err < 0)
return err;
- }
chip->addr = pci_resource_start(pci, 0);
- chip->remap_addr = pci_ioremap_bar(pci, 0);
- if (chip->remap_addr == NULL) {
- dev_err(card->dev, "AC'97 space ioremap problem\n");
- snd_atiixp_free(chip);
- return -EIO;
- }
+ chip->remap_addr = pcim_iomap_table(pci)[0];
- if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_atiixp_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_atiixp_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_atiixp_free;
pci_set_master(pci);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_atiixp_free(chip);
- return err;
- }
-
- *r_chip = chip;
return 0;
}
@@ -1622,30 +1579,31 @@ static int snd_atiixp_probe(struct pci_dev *pci,
struct atiixp *chip;
int err;
- err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
strcpy(card->shortname, "ATI IXP");
- err = snd_atiixp_create(card, pci, &chip);
+ err = snd_atiixp_init(card, pci);
if (err < 0)
- goto __error;
- card->private_data = chip;
+ return err;
err = snd_atiixp_aclink_reset(chip);
if (err < 0)
- goto __error;
+ return err;
chip->spdif_over_aclink = spdif_aclink;
err = snd_atiixp_mixer_new(chip, ac97_clock, ac97_quirk);
if (err < 0)
- goto __error;
+ return err;
err = snd_atiixp_pcm_new(chip);
if (err < 0)
- goto __error;
+ return err;
snd_atiixp_proc_init(chip);
@@ -1659,26 +1617,16 @@ static int snd_atiixp_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto __error;
+ return err;
pci_set_drvdata(pci, card);
return 0;
-
- __error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_atiixp_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver atiixp_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
- .remove = snd_atiixp_remove,
.driver = {
.pm = SND_ATIIXP_PM_OPS,
},
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 9739c3a82777..178dce8ef1e9 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1159,87 +1159,44 @@ static void snd_atiixp_proc_init(struct atiixp_modem *chip)
* destructor
*/
-static int snd_atiixp_free(struct atiixp_modem *chip)
+static void snd_atiixp_free(struct snd_card *card)
{
- if (chip->irq < 0)
- goto __hw_end;
- snd_atiixp_chip_stop(chip);
-
- __hw_end:
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- iounmap(chip->remap_addr);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_atiixp_dev_free(struct snd_device *device)
-{
- struct atiixp_modem *chip = device->device_data;
- return snd_atiixp_free(chip);
+ snd_atiixp_chip_stop(card->private_data);
}
/*
* constructor for chip instance
*/
-static int snd_atiixp_create(struct snd_card *card,
- struct pci_dev *pci,
- struct atiixp_modem **r_chip)
+static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
{
- static const struct snd_device_ops ops = {
- .dev_free = snd_atiixp_dev_free,
- };
- struct atiixp_modem *chip;
+ struct atiixp_modem *chip = card->private_data;
int err;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
spin_lock_init(&chip->reg_lock);
mutex_init(&chip->open_mutex);
chip->card = card;
chip->pci = pci;
chip->irq = -1;
- err = pci_request_regions(pci, "ATI IXP MC97");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ err = pcim_iomap_regions(pci, 1 << 0, "ATI IXP MC97");
+ if (err < 0)
return err;
- }
chip->addr = pci_resource_start(pci, 0);
- chip->remap_addr = pci_ioremap_bar(pci, 0);
- if (chip->remap_addr == NULL) {
- dev_err(card->dev, "AC'97 space ioremap problem\n");
- snd_atiixp_free(chip);
- return -EIO;
- }
+ chip->remap_addr = pcim_iomap_table(pci)[0];
- if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_atiixp_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_atiixp_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_atiixp_free;
pci_set_master(pci);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_atiixp_free(chip);
- return err;
- }
-
- *r_chip = chip;
return 0;
}
@@ -1251,28 +1208,29 @@ static int snd_atiixp_probe(struct pci_dev *pci,
struct atiixp_modem *chip;
int err;
- err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
strcpy(card->driver, "ATIIXP-MODEM");
strcpy(card->shortname, "ATI IXP Modem");
- err = snd_atiixp_create(card, pci, &chip);
+ err = snd_atiixp_init(card, pci);
if (err < 0)
- goto __error;
- card->private_data = chip;
+ return err;
err = snd_atiixp_aclink_reset(chip);
if (err < 0)
- goto __error;
+ return err;
err = snd_atiixp_mixer_new(chip, ac97_clock);
if (err < 0)
- goto __error;
+ return err;
err = snd_atiixp_pcm_new(chip);
if (err < 0)
- goto __error;
+ return err;
snd_atiixp_proc_init(chip);
@@ -1283,26 +1241,16 @@ static int snd_atiixp_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto __error;
+ return err;
pci_set_drvdata(pci, card);
return 0;
-
- __error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_atiixp_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver atiixp_modem_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
- .remove = snd_atiixp_remove,
.driver = {
.pm = SND_ATIIXP_PM_OPS,
},
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 1f7fee470266..342ef2a6655e 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -123,56 +123,35 @@ static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
// component-destructor
// (see "Management of Cards and Components")
-static int snd_vortex_dev_free(struct snd_device *device)
+static void snd_vortex_free(struct snd_card *card)
{
- vortex_t *vortex = device->device_data;
+ vortex_t *vortex = card->private_data;
vortex_gameport_unregister(vortex);
vortex_core_shutdown(vortex);
- // Take down PCI interface.
- free_irq(vortex->irq, vortex);
- iounmap(vortex->mmio);
- pci_release_regions(vortex->pci_dev);
- pci_disable_device(vortex->pci_dev);
- kfree(vortex);
-
- return 0;
}
// chip-specific constructor
// (see "Management of Cards and Components")
static int
-snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
+snd_vortex_create(struct snd_card *card, struct pci_dev *pci)
{
- vortex_t *chip;
+ vortex_t *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_vortex_dev_free,
- };
-
- *rchip = NULL;
// check PCI availability (DMA).
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_err(card->dev, "error to set DMA mask\n");
- pci_disable_device(pci);
return -ENXIO;
}
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
chip->card = card;
// initialize the stuff
chip->pci_dev = pci;
- chip->io = pci_resource_start(pci, 0);
chip->vendor = pci->vendor;
chip->device = pci->device;
chip->card = card;
@@ -181,16 +160,12 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
// (1) PCI resource allocation
// Get MMIO area
//
- err = pci_request_regions(pci, CARD_NAME_SHORT);
+ err = pcim_iomap_regions(pci, 1 << 0, CARD_NAME_SHORT);
if (err)
- goto regions_out;
+ return err;
- chip->mmio = pci_ioremap_bar(pci, 0);
- if (!chip->mmio) {
- dev_err(card->dev, "MMIO area remap failed.\n");
- err = -ENOMEM;
- goto ioremap_out;
- }
+ chip->io = pci_resource_start(pci, 0);
+ chip->mmio = pcim_iomap_table(pci)[0];
/* Init audio core.
* This must be done before we do request_irq otherwise we can get spurious
@@ -198,44 +173,22 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
err = vortex_core_init(chip);
if (err) {
dev_err(card->dev, "hw core init failed\n");
- goto core_out;
+ return err;
}
- err = request_irq(pci->irq, vortex_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip);
+ err = devm_request_irq(&pci->dev, pci->irq, vortex_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip);
if (err) {
dev_err(card->dev, "cannot grab irq\n");
- goto irq_out;
+ return err;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_vortex_free;
pci_set_master(pci);
// End of PCI setup.
-
- // Register alsa root device.
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0)
- goto alloc_out;
-
- *rchip = chip;
-
return 0;
-
- alloc_out:
- free_irq(chip->irq, chip);
- irq_out:
- vortex_core_shutdown(chip);
- core_out:
- iounmap(chip->mmio);
- ioremap_out:
- pci_release_regions(chip->pci_dev);
- regions_out:
- pci_disable_device(chip->pci_dev);
- //FIXME: this not the right place to unregister the gameport
- vortex_gameport_unregister(chip);
- kfree(chip);
- return err;
}
// constructor -- see "Constructor" sub-section
@@ -255,17 +208,16 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return -ENOENT;
}
// (2)
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
// (3)
- err = snd_vortex_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_vortex_create(card, pci);
+ if (err < 0)
return err;
- }
snd_vortex_workaround(pci, pcifix[dev]);
// Card details needed in snd_vortex_midi
@@ -276,50 +228,37 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
// (4) Alloc components.
err = snd_vortex_mixer(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
// ADB pcm.
err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
#ifndef CHIP_AU8820
// ADB SPDIF
err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
// A3D
err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
#endif
/*
// ADB I2S
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) {
- snd_card_free(card);
return err;
}
*/
#ifndef CHIP_AU8810
// WT pcm.
err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
#endif
err = snd_vortex_midi(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
vortex_gameport_register(chip);
@@ -342,15 +281,11 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
// (5)
err = pci_read_config_word(pci, PCI_DEVICE_ID, &chip->device);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = pci_read_config_word(pci, PCI_VENDOR_ID, &chip->vendor);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
chip->rev = pci->revision;
#ifdef CHIP_AU8830
if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
@@ -359,18 +294,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
chip->rev);
dev_alert(card->dev,
"Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n");
- snd_card_free(card);
- err = -ENODEV;
- return err;
+ return -ENODEV;
}
#endif
// (6)
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
// (7)
pci_set_drvdata(pci, card);
dev++;
@@ -379,18 +310,11 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return 0;
}
-// destructor -- see "Destructor" sub-section
-static void snd_vortex_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
// pci_driver definition
static struct pci_driver vortex_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vortex_ids,
.probe = snd_vortex_probe,
- .remove = snd_vortex_remove,
};
module_pci_driver(vortex_driver);
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 43396849a01c..d56f126d6fdd 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -99,12 +99,9 @@ struct aw2 {
/*********************************
* FUNCTION DECLARATIONS
********************************/
-static int snd_aw2_dev_free(struct snd_device *device);
-static int snd_aw2_create(struct snd_card *card,
- struct pci_dev *pci, struct aw2 **rchip);
+static int snd_aw2_create(struct snd_card *card, struct pci_dev *pci);
static int snd_aw2_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id);
-static void snd_aw2_remove(struct pci_dev *pci);
static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
@@ -157,7 +154,6 @@ static struct pci_driver aw2_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_aw2_ids,
.probe = snd_aw2_probe,
- .remove = snd_aw2_remove,
};
module_pci_driver(aw2_driver);
@@ -196,41 +192,23 @@ static const struct snd_kcontrol_new aw2_control = {
********************************/
/* component-destructor */
-static int snd_aw2_dev_free(struct snd_device *device)
+static void snd_aw2_free(struct snd_card *card)
{
- struct aw2 *chip = device->device_data;
+ struct aw2 *chip = card->private_data;
/* Free hardware */
snd_aw2_saa7146_free(&chip->saa7146);
-
- /* release the irq */
- if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
- /* release the i/o ports & memory */
- iounmap(chip->iobase_virt);
- pci_release_regions(chip->pci);
- /* disable the PCI entry */
- pci_disable_device(chip->pci);
- /* release the data */
- kfree(chip);
-
- return 0;
}
/* chip-specific constructor */
static int snd_aw2_create(struct snd_card *card,
- struct pci_dev *pci, struct aw2 **rchip)
+ struct pci_dev *pci)
{
- struct aw2 *chip;
+ struct aw2 *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_aw2_dev_free,
- };
-
- *rchip = NULL;
/* initialize the PCI entry */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
pci_set_master(pci);
@@ -238,14 +216,8 @@ static int snd_aw2_create(struct snd_card *card,
/* check PCI availability (32bit DMA) */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_err(card->dev, "Impossible to set 32bit mask DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
/* initialize the stuff */
chip->card = card;
@@ -253,52 +225,23 @@ static int snd_aw2_create(struct snd_card *card,
chip->irq = -1;
/* (1) PCI resource allocation */
- err = pci_request_regions(pci, "Audiowerk2");
- if (err < 0) {
- pci_disable_device(pci);
- kfree(chip);
+ err = pcim_iomap_regions(pci, 1 << 0, "Audiowerk2");
+ if (err < 0)
return err;
- }
chip->iobase_phys = pci_resource_start(pci, 0);
- chip->iobase_virt =
- ioremap(chip->iobase_phys,
- pci_resource_len(pci, 0));
-
- if (chip->iobase_virt == NULL) {
- dev_err(card->dev, "unable to remap memory region");
- pci_release_regions(pci);
- pci_disable_device(pci);
- kfree(chip);
- return -ENOMEM;
- }
+ chip->iobase_virt = pcim_iomap_table(pci)[0];
/* (2) initialization of the chip hardware */
snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
- if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_aw2_saa7146_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "Cannot grab irq %d\n", pci->irq);
-
- iounmap(chip->iobase_virt);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- free_irq(chip->irq, (void *)chip);
- iounmap(chip->iobase_virt);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return err;
- }
-
- *rchip = chip;
+ card->private_free = snd_aw2_free;
dev_info(card->dev,
"Audiowerk 2 sound card (saa7146 chipset) detected and managed\n");
@@ -323,17 +266,16 @@ static int snd_aw2_probe(struct pci_dev *pci,
}
/* (2) Create card instance */
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
/* (3) Create main component */
- err = snd_aw2_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_aw2_create(card, pci);
+ if (err < 0)
return err;
- }
/* initialize mutex */
mutex_init(&chip->mtx);
@@ -351,10 +293,8 @@ static int snd_aw2_probe(struct pci_dev *pci,
/* (6) Register card instance */
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
/* (7) Set PCI driver data */
pci_set_drvdata(pci, card);
@@ -363,12 +303,6 @@ static int snd_aw2_probe(struct pci_dev *pci,
return 0;
}
-/* destructor */
-static void snd_aw2_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
/* open callback */
static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
{
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 4ee7ab409807..089050470ff2 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -2244,32 +2244,15 @@ out:
/******************************************************************/
-static int
-snd_azf3328_free(struct snd_azf3328 *chip)
+static void
+snd_azf3328_free(struct snd_card *card)
{
- if (chip->irq < 0)
- goto __end_hw;
+ struct snd_azf3328 *chip = card->private_data;
snd_azf3328_mixer_reset(chip);
snd_azf3328_timer_stop(chip->timer);
snd_azf3328_gameport_free(chip);
-
-__end_hw:
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
-
- kfree(chip);
- return 0;
-}
-
-static int
-snd_azf3328_dev_free(struct snd_device *device)
-{
- struct snd_azf3328 *chip = device->device_data;
- return snd_azf3328_free(chip);
}
#if 0
@@ -2350,29 +2333,18 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
static int
snd_azf3328_create(struct snd_card *card,
struct pci_dev *pci,
- unsigned long device_type,
- struct snd_azf3328 **rchip)
+ unsigned long device_type)
{
- struct snd_azf3328 *chip;
+ struct snd_azf3328 *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_azf3328_dev_free,
- };
u8 dma_init;
enum snd_azf3328_codec_type codec_type;
struct snd_azf3328_codec_data *codec_setup;
- *rchip = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- err = -ENOMEM;
- goto out_err;
- }
spin_lock_init(&chip->reg_lock);
chip->card = card;
chip->pci = pci;
@@ -2383,13 +2355,12 @@ snd_azf3328_create(struct snd_card *card,
dev_err(card->dev,
"architecture does not support 24bit PCI busmaster DMA\n"
);
- err = -ENXIO;
- goto out_err;
+ return -ENXIO;
}
err = pci_request_regions(pci, "Aztech AZF3328");
if (err < 0)
- goto out_err;
+ return err;
chip->ctrl_io = pci_resource_start(pci, 0);
chip->game_io = pci_resource_start(pci, 1);
@@ -2415,26 +2386,22 @@ snd_azf3328_create(struct snd_card *card,
codec_setup->type = AZF_CODEC_I2S_OUT;
codec_setup->name = "I2S_OUT";
- if (request_irq(pci->irq, snd_azf3328_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_azf3328_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- err = -EBUSY;
- goto out_err;
+ return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_azf3328_free;
pci_set_master(pci);
snd_azf3328_debug_show_ports(chip);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0)
- goto out_err;
-
/* create mixer interface & switches */
err = snd_azf3328_mixer_new(chip);
if (err < 0)
- goto out_err;
+ return err;
/* standard codec init stuff */
/* default DMA init value */
@@ -2456,18 +2423,7 @@ snd_azf3328_create(struct snd_card *card,
spin_unlock_irq(codec->lock);
}
- *rchip = chip;
-
- err = 0;
- goto out;
-
-out_err:
- if (chip)
- snd_azf3328_free(chip);
- pci_disable_device(pci);
-
-out:
- return err;
+ return 0;
}
static int
@@ -2479,29 +2435,25 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
struct snd_opl3 *opl3;
int err;
- if (dev >= SNDRV_CARDS) {
- err = -ENODEV;
- goto out;
- }
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
if (!enable[dev]) {
dev++;
- err = -ENOENT;
- goto out;
+ return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
- goto out;
+ return err;
+ chip = card->private_data;
strcpy(card->driver, "AZF3328");
strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
- err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip);
+ err = snd_azf3328_create(card, pci, pci_id->driver_data);
if (err < 0)
- goto out_err;
-
- card->private_data = chip;
+ return err;
/* chose to use MPU401_HW_AZT2320 ID instead of MPU401_HW_MPU401,
since our hardware ought to be similar, thus use same ID. */
@@ -2515,16 +2467,16 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
dev_err(card->dev, "no MPU-401 device at 0x%lx?\n",
chip->mpu_io
);
- goto out_err;
+ return err;
}
err = snd_azf3328_timer(chip, 0);
if (err < 0)
- goto out_err;
+ return err;
err = snd_azf3328_pcm(chip);
if (err < 0)
- goto out_err;
+ return err;
if (snd_opl3_create(card, chip->opl3_io, chip->opl3_io+2,
OPL3_HW_AUTO, 1, &opl3) < 0) {
@@ -2535,10 +2487,10 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
/* need to use IDs 1, 2 since ID 0 is snd_azf3328_timer above */
err = snd_opl3_timer_new(opl3, 1, 2);
if (err < 0)
- goto out_err;
+ return err;
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
- goto out_err;
+ return err;
opl3->private_data = chip;
}
@@ -2547,7 +2499,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
err = snd_card_register(card);
if (err < 0)
- goto out_err;
+ return err;
#ifdef MODULE
dev_info(card->dev,
@@ -2565,22 +2517,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
pci_set_drvdata(pci, card);
dev++;
-
- err = 0;
- goto out;
-
-out_err:
- dev_err(card->dev, "something failed, exiting\n");
- snd_card_free(card);
-
-out:
- return err;
-}
-
-static void
-snd_azf3328_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
+ return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -2709,7 +2646,6 @@ static struct pci_driver azf3328_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_azf3328_ids,
.probe = snd_azf3328_probe,
- .remove = snd_azf3328_remove,
.driver = {
.pm = SND_AZF3328_PM_OPS,
},
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 39bcfb81e81c..d23f93163841 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -656,23 +656,11 @@ static const struct snd_kcontrol_new snd_bt87x_capture_source = {
.put = snd_bt87x_capture_source_put,
};
-static int snd_bt87x_free(struct snd_bt87x *chip)
-{
- if (chip->mmio)
- snd_bt87x_stop(chip);
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- iounmap(chip->mmio);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_bt87x_dev_free(struct snd_device *device)
+static void snd_bt87x_free(struct snd_card *card)
{
- struct snd_bt87x *chip = device->device_data;
- return snd_bt87x_free(chip);
+ struct snd_bt87x *chip = card->private_data;
+
+ snd_bt87x_stop(chip);
}
static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
@@ -694,43 +682,24 @@ static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
}
static int snd_bt87x_create(struct snd_card *card,
- struct pci_dev *pci,
- struct snd_bt87x **rchip)
+ struct pci_dev *pci)
{
- struct snd_bt87x *chip;
+ struct snd_bt87x *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_bt87x_dev_free
- };
-
- *rchip = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
chip->card = card;
chip->pci = pci;
chip->irq = -1;
spin_lock_init(&chip->reg_lock);
- err = pci_request_regions(pci, "Bt87x audio");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ err = pcim_iomap_regions(pci, 1 << 0, "Bt87x audio");
+ if (err < 0)
return err;
- }
- chip->mmio = pci_ioremap_bar(pci, 0);
- if (!chip->mmio) {
- dev_err(card->dev, "cannot remap io memory\n");
- err = -ENOMEM;
- goto fail;
- }
+ chip->mmio = pcim_iomap_table(pci)[0];
chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 |
CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT);
@@ -739,26 +708,18 @@ static int snd_bt87x_create(struct snd_card *card,
snd_bt87x_writel(chip, REG_INT_MASK, 0);
snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);
- err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip);
+ err = devm_request_irq(&pci->dev, pci->irq, snd_bt87x_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip);
if (err < 0) {
dev_err(card->dev, "cannot grab irq %d\n", pci->irq);
- goto fail;
+ return err;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_bt87x_free;
pci_set_master(pci);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0)
- goto fail;
-
- *rchip = chip;
return 0;
-
-fail:
- snd_bt87x_free(chip);
- return err;
}
#define BT_DEVICE(chip, subvend, subdev, id) \
@@ -868,14 +829,15 @@ static int snd_bt87x_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
- err = snd_bt87x_create(card, pci, &chip);
+ err = snd_bt87x_create(card, pci);
if (err < 0)
- goto _error;
+ return err;
memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board));
@@ -887,24 +849,24 @@ static int snd_bt87x_probe(struct pci_dev *pci,
err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital");
if (err < 0)
- goto _error;
+ return err;
}
if (!chip->board.no_analog) {
err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog");
if (err < 0)
- goto _error;
+ return err;
err = snd_ctl_add(card, snd_ctl_new1(
&snd_bt87x_capture_volume, chip));
if (err < 0)
- goto _error;
+ return err;
err = snd_ctl_add(card, snd_ctl_new1(
&snd_bt87x_capture_boost, chip));
if (err < 0)
- goto _error;
+ return err;
err = snd_ctl_add(card, snd_ctl_new1(
&snd_bt87x_capture_source, chip));
if (err < 0)
- goto _error;
+ return err;
}
dev_info(card->dev, "bt87x%d: Using board %d, %sanalog, %sdigital "
"(rate %d Hz)\n", dev, boardid,
@@ -920,20 +882,11 @@ static int snd_bt87x_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto _error;
+ return err;
pci_set_drvdata(pci, card);
++dev;
return 0;
-
-_error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_bt87x_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
/* default entries for all Bt87x cards - it's not exported */
@@ -948,7 +901,6 @@ static struct pci_driver driver = {
.name = KBUILD_MODNAME,
.id_table = snd_bt87x_ids,
.probe = snd_bt87x_probe,
- .remove = snd_bt87x_remove,
};
static int __init alsa_card_bt87x_init(void)
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index 62a22ca3b9de..f246e6094289 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -667,7 +667,6 @@ struct snd_ca0106 {
struct pci_dev *pci;
unsigned long port;
- struct resource *res_port;
int irq;
unsigned int serial; /* serial number */
@@ -688,7 +687,7 @@ struct snd_ca0106 {
u8 i2c_capture_volume[4][2];
int capture_mic_line_in;
- struct snd_dma_buffer buffer;
+ struct snd_dma_buffer *buffer;
struct snd_ca_midi midi;
struct snd_ca_midi midi2;
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 99778711006a..36fb150b72fb 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -718,7 +718,7 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ca0106_pcm *epcm = runtime->private_data;
int channel = epcm->channel_id;
- u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
+ u32 *table_base = (u32 *)(emu->buffer->area+(8*16*channel));
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
u32 hcfg_set = 0x00000000;
@@ -746,7 +746,7 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
runtime->dma_addr, runtime->dma_area, table_base);
dev_dbg(emu->card->dev,
"dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
- emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+ emu->buffer->addr, emu->buffer->area, emu->buffer->bytes);
#endif /* debug */
/* Rate can be set per channel. */
/* reg40 control host to fifo */
@@ -796,13 +796,13 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
reg71 = (reg71 & ~reg71_mask) | reg71_set;
snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
- /* FIXME: Check emu->buffer.size before actually writing to it. */
+ /* FIXME: Check emu->buffer->size before actually writing to it. */
for(i=0; i < runtime->periods; i++) {
table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
table_base[i*2+1] = period_size_bytes << 16;
}
- snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
+ snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer->addr+(8*16*channel));
snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
@@ -853,7 +853,7 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
runtime->dma_addr, runtime->dma_area, table_base);
dev_dbg(emu->card->dev,
"dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
- emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+ emu->buffer->addr, emu->buffer->area, emu->buffer->bytes);
#endif /* debug */
/* reg71 controls ADC rate. */
switch (runtime->rate) {
@@ -1183,32 +1183,11 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip)
static void ca0106_stop_chip(struct snd_ca0106 *chip);
-static int snd_ca0106_free(struct snd_ca0106 *chip)
+static void snd_ca0106_free(struct snd_card *card)
{
- if (chip->res_port != NULL) {
- /* avoid access to already used hardware */
- ca0106_stop_chip(chip);
- }
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- // release the data
-#if 1
- if (chip->buffer.area)
- snd_dma_free_pages(&chip->buffer);
-#endif
-
- // release the i/o port
- release_and_free_resource(chip->res_port);
-
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
+ struct snd_ca0106 *chip = card->private_data;
-static int snd_ca0106_dev_free(struct snd_device *device)
-{
- struct snd_ca0106 *chip = device->device_data;
- return snd_ca0106_free(chip);
+ ca0106_stop_chip(chip);
}
static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
@@ -1594,50 +1573,33 @@ static void ca0106_stop_chip(struct snd_ca0106 *chip)
}
static int snd_ca0106_create(int dev, struct snd_card *card,
- struct pci_dev *pci,
- struct snd_ca0106 **rchip)
+ struct pci_dev *pci)
{
- struct snd_ca0106 *chip;
+ struct snd_ca0106 *chip = card->private_data;
const struct snd_ca0106_details *c;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_ca0106_dev_free,
- };
-
- *rchip = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_err(card->dev, "error to set 32bit mask DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
chip->card = card;
chip->pci = pci;
chip->irq = -1;
spin_lock_init(&chip->emu_lock);
+ err = pci_request_regions(pci, "snd_ca0106");
+ if (err < 0)
+ return err;
chip->port = pci_resource_start(pci, 0);
- chip->res_port = request_region(chip->port, 0x20, "snd_ca0106");
- if (!chip->res_port) {
- snd_ca0106_free(chip);
- dev_err(card->dev, "cannot allocate the port\n");
- return -EBUSY;
- }
- if (request_irq(pci->irq, snd_ca0106_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip)) {
- snd_ca0106_free(chip);
+ if (devm_request_irq(&pci->dev, pci->irq, snd_ca0106_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "cannot grab irq\n");
return -EBUSY;
}
@@ -1645,11 +1607,9 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
card->sync_irq = chip->irq;
/* This stores the periods table. */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- 1024, &chip->buffer) < 0) {
- snd_ca0106_free(chip);
+ chip->buffer = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024);
+ if (!chip->buffer)
return -ENOMEM;
- }
pci_set_master(pci);
/* read serial */
@@ -1678,13 +1638,6 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
c->name, chip->port, chip->irq);
ca0106_init_chip(chip, 0);
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_ca0106_free(chip);
- return err;
- }
- *rchip = chip;
return 0;
}
@@ -1787,36 +1740,37 @@ static int snd_ca0106_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
- err = snd_ca0106_create(dev, card, pci, &chip);
+ err = snd_ca0106_create(dev, card, pci);
if (err < 0)
- goto error;
- card->private_data = chip;
+ return err;
+ card->private_free = snd_ca0106_free;
for (i = 0; i < 4; i++) {
err = snd_ca0106_pcm(chip, i);
if (err < 0)
- goto error;
+ return err;
}
if (chip->details->ac97 == 1) {
/* The SB0410 and SB0413 do not have an AC97 chip. */
err = snd_ca0106_ac97(chip);
if (err < 0)
- goto error;
+ return err;
}
err = snd_ca0106_mixer(chip);
if (err < 0)
- goto error;
+ return err;
dev_dbg(card->dev, "probe for MIDI channel A ...");
err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A);
if (err < 0)
- goto error;
+ return err;
dev_dbg(card->dev, " done.\n");
#ifdef CONFIG_SND_PROC_FS
@@ -1825,20 +1779,11 @@ static int snd_ca0106_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto error;
+ return err;
pci_set_drvdata(pci, card);
dev++;
return 0;
-
- error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_ca0106_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
#ifdef CONFIG_PM_SLEEP
@@ -1894,7 +1839,6 @@ static struct pci_driver ca0106_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ca0106_ids,
.probe = snd_ca0106_probe,
- .remove = snd_ca0106_remove,
.driver = {
.pm = SND_CA0106_PM_OPS,
},
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index f44f118aacad..ea20236f35db 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2852,13 +2852,15 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
if (joystick_port[dev] == 1) { /* auto-detect */
for (i = 0; ports[i]; i++) {
io_port = ports[i];
- r = request_region(io_port, 1, "CMIPCI gameport");
+ r = devm_request_region(&cm->pci->dev, io_port, 1,
+ "CMIPCI gameport");
if (r)
break;
}
} else {
io_port = joystick_port[dev];
- r = request_region(io_port, 1, "CMIPCI gameport");
+ r = devm_request_region(&cm->pci->dev, io_port, 1,
+ "CMIPCI gameport");
}
if (!r) {
@@ -2869,14 +2871,12 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
cm->gameport = gp = gameport_allocate_port();
if (!gp) {
dev_err(cm->card->dev, "cannot allocate memory for gameport\n");
- release_and_free_resource(r);
return -ENOMEM;
}
gameport_set_name(gp, "C-Media Gameport");
gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci));
gameport_set_dev_parent(gp, &cm->pci->dev);
gp->io = io_port;
- gameport_set_port_data(gp, r);
snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
@@ -2888,13 +2888,10 @@ static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
static void snd_cmipci_free_gameport(struct cmipci *cm)
{
if (cm->gameport) {
- struct resource *r = gameport_get_port_data(cm->gameport);
-
gameport_unregister_port(cm->gameport);
cm->gameport = NULL;
snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
- release_and_free_resource(r);
}
}
#else
@@ -2902,34 +2899,22 @@ static inline int snd_cmipci_create_gameport(struct cmipci *cm, int dev) { retur
static inline void snd_cmipci_free_gameport(struct cmipci *cm) { }
#endif
-static int snd_cmipci_free(struct cmipci *cm)
+static void snd_cmipci_free(struct snd_card *card)
{
- if (cm->irq >= 0) {
- snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
- snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT);
- snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */
- snd_cmipci_ch_reset(cm, CM_CH_PLAY);
- snd_cmipci_ch_reset(cm, CM_CH_CAPT);
- snd_cmipci_write(cm, CM_REG_FUNCTRL0, 0); /* disable channels */
- snd_cmipci_write(cm, CM_REG_FUNCTRL1, 0);
+ struct cmipci *cm = card->private_data;
- /* reset mixer */
- snd_cmipci_mixer_write(cm, 0, 0);
+ snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
+ snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT);
+ snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */
+ snd_cmipci_ch_reset(cm, CM_CH_PLAY);
+ snd_cmipci_ch_reset(cm, CM_CH_CAPT);
+ snd_cmipci_write(cm, CM_REG_FUNCTRL0, 0); /* disable channels */
+ snd_cmipci_write(cm, CM_REG_FUNCTRL1, 0);
- free_irq(cm->irq, cm);
- }
+ /* reset mixer */
+ snd_cmipci_mixer_write(cm, 0, 0);
snd_cmipci_free_gameport(cm);
- pci_release_regions(cm->pci);
- pci_disable_device(cm->pci);
- kfree(cm);
- return 0;
-}
-
-static int snd_cmipci_dev_free(struct snd_device *device)
-{
- struct cmipci *cm = device->device_data;
- return snd_cmipci_free(cm);
}
static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
@@ -2988,13 +2973,10 @@ static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
}
static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
- int dev, struct cmipci **rcmipci)
+ int dev)
{
- struct cmipci *cm;
+ struct cmipci *cm = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_cmipci_dev_free,
- };
unsigned int val;
long iomidi = 0;
int integrated_midi = 0;
@@ -3005,18 +2987,10 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
{ },
};
- *rcmipci = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- cm = kzalloc(sizeof(*cm), GFP_KERNEL);
- if (cm == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
spin_lock_init(&cm->reg_lock);
mutex_init(&cm->open_mutex);
cm->device = pci->device;
@@ -3028,21 +3002,18 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
cm->channel[0].is_dac = cm->channel[1].is_dac = 1; /* dual DAC mode */
err = pci_request_regions(pci, card->driver);
- if (err < 0) {
- kfree(cm);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
cm->iobase = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_cmipci_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, cm)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_cmipci_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, cm)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_cmipci_free(cm);
return -EBUSY;
}
cm->irq = pci->irq;
card->sync_irq = cm->irq;
+ card->private_free = snd_cmipci_free;
pci_set_master(cm->pci);
@@ -3142,12 +3113,6 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
sprintf(card->longname, "%s%s at %#lx, irq %i",
card->shortname, modelstr, cm->iobase, cm->irq);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops);
- if (err < 0) {
- snd_cmipci_free(cm);
- return err;
- }
-
if (cm->chip_version >= 39) {
val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1);
if (val != 0x00 && val != 0xff) {
@@ -3240,7 +3205,6 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
if (snd_cmipci_create_gameport(cm, dev) < 0)
snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
- *rcmipci = cm;
return 0;
}
@@ -3264,10 +3228,11 @@ static int snd_cmipci_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*cm), &card);
if (err < 0)
return err;
+ cm = card->private_data;
switch (pci->device) {
case PCI_DEVICE_ID_CMEDIA_CM8738:
@@ -3283,31 +3248,19 @@ static int snd_cmipci_probe(struct pci_dev *pci,
break;
}
- err = snd_cmipci_create(card, pci, dev, &cm);
+ err = snd_cmipci_create(card, pci, dev);
if (err < 0)
- goto free_card;
-
- card->private_data = cm;
+ return err;
err = snd_card_register(card);
if (err < 0)
- goto free_card;
+ return err;
pci_set_drvdata(pci, card);
dev++;
return 0;
-
-free_card:
- snd_card_free(card);
- return err;
}
-static void snd_cmipci_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
-
#ifdef CONFIG_PM_SLEEP
/*
* power management
@@ -3382,7 +3335,6 @@ static struct pci_driver cmipci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cmipci_ids,
.probe = snd_cmipci_probe,
- .remove = snd_cmipci_remove,
.driver = {
.pm = SND_CMIPCI_PM_OPS,
},
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index e122a168c148..e7367402b84a 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1268,8 +1268,10 @@ static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOS
static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { }
#endif /* IS_REACHABLE(CONFIG_GAMEPORT) */
-static int snd_cs4281_free(struct cs4281 *chip)
+static void snd_cs4281_free(struct snd_card *card)
{
+ struct cs4281 *chip = card->private_data;
+
snd_cs4281_free_gameport(chip);
/* Mask interrupts */
@@ -1278,49 +1280,20 @@ static int snd_cs4281_free(struct cs4281 *chip)
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0);
/* Sound System Power Management - Turn Everything OFF */
snd_cs4281_pokeBA0(chip, BA0_SSPM, 0);
- /* PCI interface - D3 state */
- pci_set_power_state(chip->pci, PCI_D3hot);
-
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- iounmap(chip->ba0);
- iounmap(chip->ba1);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
-
- kfree(chip);
- return 0;
-}
-
-static int snd_cs4281_dev_free(struct snd_device *device)
-{
- struct cs4281 *chip = device->device_data;
- return snd_cs4281_free(chip);
}
static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */
static int snd_cs4281_create(struct snd_card *card,
struct pci_dev *pci,
- struct cs4281 **rchip,
int dual_codec)
{
- struct cs4281 *chip;
- unsigned int tmp;
+ struct cs4281 *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_cs4281_dev_free,
- };
- *rchip = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
spin_lock_init(&chip->reg_lock);
chip->card = card;
chip->pci = pci;
@@ -1332,46 +1305,29 @@ static int snd_cs4281_create(struct snd_card *card,
}
chip->dual_codec = dual_codec;
- err = pci_request_regions(pci, "CS4281");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ err = pcim_iomap_regions(pci, 0x03, "CS4281"); /* 2 BARs */
+ if (err < 0)
return err;
- }
chip->ba0_addr = pci_resource_start(pci, 0);
chip->ba1_addr = pci_resource_start(pci, 1);
- chip->ba0 = pci_ioremap_bar(pci, 0);
- chip->ba1 = pci_ioremap_bar(pci, 1);
- if (!chip->ba0 || !chip->ba1) {
- snd_cs4281_free(chip);
- return -ENOMEM;
- }
+ chip->ba0 = pcim_iomap_table(pci)[0];
+ chip->ba1 = pcim_iomap_table(pci)[1];
- if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_cs4281_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_cs4281_free(chip);
return -ENOMEM;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_cs4281_free;
- tmp = snd_cs4281_chip_init(chip);
- if (tmp) {
- snd_cs4281_free(chip);
- return tmp;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_cs4281_free(chip);
+ err = snd_cs4281_chip_init(chip);
+ if (err)
return err;
- }
snd_cs4281_proc_init(chip);
-
- *rchip = chip;
return 0;
}
@@ -1887,46 +1843,34 @@ static int snd_cs4281_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
- err = snd_cs4281_create(card, pci, &chip, dual_codec[dev]);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_cs4281_create(card, pci, dual_codec[dev]);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
err = snd_cs4281_mixer(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_cs4281_pcm(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_cs4281_midi(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
opl3->private_data = chip;
opl3->command = snd_cs4281_opl3_command;
snd_opl3_init(opl3);
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
snd_cs4281_create_gameport(chip);
strcpy(card->driver, "CS4281");
strcpy(card->shortname, "Cirrus Logic CS4281");
@@ -1936,21 +1880,14 @@ static int snd_cs4281_probe(struct pci_dev *pci,
chip->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_cs4281_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
/*
* Power Management
*/
@@ -2054,7 +1991,6 @@ static struct pci_driver cs4281_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs4281_ids,
.probe = snd_cs4281_probe,
- .remove = snd_cs4281_remove,
.driver = {
.pm = CS4281_PM_OPS,
},
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 358ca84cbdea..bd60308769ff 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -66,61 +66,44 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
err = snd_cs46xx_create(card, pci,
- external_amp[dev], thinkpad[dev],
- &chip);
- if (err < 0) {
- snd_card_free(card);
+ external_amp[dev], thinkpad[dev]);
+ if (err < 0)
return err;
- }
card->private_data = chip;
chip->accept_valid = mmap_valid[dev];
err = snd_cs46xx_pcm(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
#ifdef CONFIG_SND_CS46XX_NEW_DSP
err = snd_cs46xx_pcm_rear(chip, 1);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_cs46xx_pcm_iec958(chip, 2);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
#endif
err = snd_cs46xx_mixer(chip, 2);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
#ifdef CONFIG_SND_CS46XX_NEW_DSP
if (chip->nr_ac97_codecs ==2) {
err = snd_cs46xx_pcm_center_lfe(chip, 3);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
#endif
err = snd_cs46xx_midi(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_cs46xx_start_dsp(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
-
snd_cs46xx_gameport(chip);
@@ -133,26 +116,18 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
chip->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_card_cs46xx_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver cs46xx_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs46xx_ids,
.probe = snd_card_cs46xx_probe,
- .remove = snd_card_cs46xx_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_cs46xx_pm,
diff --git a/sound/pci/cs46xx/cs46xx.h b/sound/pci/cs46xx/cs46xx.h
index b275df883d06..c4f0a0b94270 100644
--- a/sound/pci/cs46xx/cs46xx.h
+++ b/sound/pci/cs46xx/cs46xx.h
@@ -1635,7 +1635,6 @@ struct snd_cs46xx_region {
unsigned long base;
void __iomem *remap_addr;
unsigned long size;
- struct resource *resource;
};
struct snd_cs46xx {
@@ -1718,8 +1717,7 @@ struct snd_cs46xx {
int snd_cs46xx_create(struct snd_card *card,
struct pci_dev *pci,
- int external_amp, int thinkpad,
- struct snd_cs46xx **rcodec);
+ int external_amp, int thinkpad);
extern const struct dev_pm_ops snd_cs46xx_pm;
int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device);
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 1e1eb17f8e07..62f45847b351 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1121,9 +1121,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
if (params_periods(hw_params) == CS46XX_FRAGS) {
if (runtime->dma_area != cpcm->hw_buf.area)
snd_pcm_lib_free_pages(substream);
- runtime->dma_area = cpcm->hw_buf.area;
- runtime->dma_addr = cpcm->hw_buf.addr;
- runtime->dma_bytes = cpcm->hw_buf.bytes;
+ snd_pcm_set_runtime_buffer(substream, &cpcm->hw_buf);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1143,11 +1141,8 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
#endif
} else {
- if (runtime->dma_area == cpcm->hw_buf.area) {
- runtime->dma_area = NULL;
- runtime->dma_addr = 0;
- runtime->dma_bytes = 0;
- }
+ if (runtime->dma_area == cpcm->hw_buf.area)
+ snd_pcm_set_runtime_buffer(substream, NULL);
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
if (err < 0) {
#ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1196,9 +1191,7 @@ static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream)
if (runtime->dma_area != cpcm->hw_buf.area)
snd_pcm_lib_free_pages(substream);
- runtime->dma_area = NULL;
- runtime->dma_addr = 0;
- runtime->dma_bytes = 0;
+ snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
@@ -1287,16 +1280,11 @@ static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream,
if (runtime->periods == CS46XX_FRAGS) {
if (runtime->dma_area != chip->capt.hw_buf.area)
snd_pcm_lib_free_pages(substream);
- runtime->dma_area = chip->capt.hw_buf.area;
- runtime->dma_addr = chip->capt.hw_buf.addr;
- runtime->dma_bytes = chip->capt.hw_buf.bytes;
+ snd_pcm_set_runtime_buffer(substream, &chip->capt.hw_buf);
substream->ops = &snd_cs46xx_capture_ops;
} else {
- if (runtime->dma_area == chip->capt.hw_buf.area) {
- runtime->dma_area = NULL;
- runtime->dma_addr = 0;
- runtime->dma_bytes = 0;
- }
+ if (runtime->dma_area == chip->capt.hw_buf.area)
+ snd_pcm_set_runtime_buffer(substream, NULL);
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
if (err < 0)
return err;
@@ -1313,9 +1301,7 @@ static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream)
if (runtime->dma_area != chip->capt.hw_buf.area)
snd_pcm_lib_free_pages(substream);
- runtime->dma_area = NULL;
- runtime->dma_addr = 0;
- runtime->dma_bytes = 0;
+ snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
@@ -1865,13 +1851,6 @@ int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device)
/*
* Mixer routines
*/
-static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
-{
- struct snd_cs46xx *chip = bus->private_data;
-
- chip->ac97_bus = NULL;
-}
-
static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97)
{
struct snd_cs46xx *chip = ac97->private_data;
@@ -2487,7 +2466,6 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
if (err < 0)
return err;
- chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
return -ENXIO;
@@ -2913,12 +2891,12 @@ static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip)
}
-static int snd_cs46xx_free(struct snd_cs46xx *chip)
+static void snd_cs46xx_free(struct snd_card *card)
{
+ struct snd_cs46xx *chip = card->private_data;
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
int idx;
-
- if (snd_BUG_ON(!chip))
- return -EINVAL;
+#endif
if (chip->active_ctrl)
chip->active_ctrl(chip, 1);
@@ -2930,22 +2908,11 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
snd_cs46xx_proc_done(chip);
- if (chip->region.idx[0].resource)
- snd_cs46xx_hw_stop(chip);
-
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
+ snd_cs46xx_hw_stop(chip);
if (chip->active_ctrl)
chip->active_ctrl(chip, -chip->amplifier);
- for (idx = 0; idx < 5; idx++) {
- struct snd_cs46xx_region *region = &chip->region.idx[idx];
-
- iounmap(region->remap_addr);
- release_and_free_resource(region->resource);
- }
-
#ifdef CONFIG_SND_CS46XX_NEW_DSP
if (chip->dsp_spos_instance) {
cs46xx_dsp_spos_destroy(chip);
@@ -2956,20 +2923,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
#else
vfree(chip->ba1);
#endif
-
-#ifdef CONFIG_PM_SLEEP
- kfree(chip->saved_regs);
-#endif
-
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_cs46xx_dev_free(struct snd_device *device)
-{
- struct snd_cs46xx *chip = device->device_data;
- return snd_cs46xx_free(chip);
}
/*
@@ -3868,30 +3821,19 @@ SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume);
int snd_cs46xx_create(struct snd_card *card,
struct pci_dev *pci,
- int external_amp, int thinkpad,
- struct snd_cs46xx **rchip)
+ int external_amp, int thinkpad)
{
- struct snd_cs46xx *chip;
+ struct snd_cs46xx *chip = card->private_data;
int err, idx;
struct snd_cs46xx_region *region;
struct cs_card_type *cp;
u16 ss_card, ss_vendor;
- static const struct snd_device_ops ops = {
- .dev_free = snd_cs46xx_dev_free,
- };
- *rchip = NULL;
-
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
spin_lock_init(&chip->reg_lock);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
mutex_init(&chip->spos_mutex);
@@ -3899,6 +3841,10 @@ int snd_cs46xx_create(struct snd_card *card,
chip->card = card;
chip->pci = pci;
chip->irq = -1;
+
+ err = pci_request_regions(pci, "CS46xx");
+ if (err < 0)
+ return err;
chip->ba0_addr = pci_resource_start(pci, 0);
chip->ba1_addr = pci_resource_start(pci, 1);
if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
@@ -3906,7 +3852,6 @@ int snd_cs46xx_create(struct snd_card *card,
dev_err(chip->card->dev,
"wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n",
chip->ba0_addr, chip->ba1_addr);
- snd_cs46xx_free(chip);
return -ENOMEM;
}
@@ -3978,67 +3923,45 @@ int snd_cs46xx_create(struct snd_card *card,
for (idx = 0; idx < 5; idx++) {
region = &chip->region.idx[idx];
- region->resource = request_mem_region(region->base, region->size,
- region->name);
- if (!region->resource) {
- dev_err(chip->card->dev,
- "unable to request memory region 0x%lx-0x%lx\n",
- region->base, region->base + region->size - 1);
- snd_cs46xx_free(chip);
- return -EBUSY;
- }
- region->remap_addr = ioremap(region->base, region->size);
+ region->remap_addr = devm_ioremap(&pci->dev, region->base,
+ region->size);
if (region->remap_addr == NULL) {
dev_err(chip->card->dev,
"%s ioremap problem\n", region->name);
- snd_cs46xx_free(chip);
return -ENOMEM;
}
}
- if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_cs46xx_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_cs46xx_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_cs46xx_free;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
- if (chip->dsp_spos_instance == NULL) {
- snd_cs46xx_free(chip);
+ if (!chip->dsp_spos_instance)
return -ENOMEM;
- }
#endif
err = snd_cs46xx_chip_init(chip);
- if (err < 0) {
- snd_cs46xx_free(chip);
- return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_cs46xx_free(chip);
+ if (err < 0)
return err;
- }
snd_cs46xx_proc_init(card, chip);
#ifdef CONFIG_PM_SLEEP
- chip->saved_regs = kmalloc_array(ARRAY_SIZE(saved_regs),
- sizeof(*chip->saved_regs),
- GFP_KERNEL);
- if (!chip->saved_regs) {
- snd_cs46xx_free(chip);
+ chip->saved_regs = devm_kmalloc_array(&pci->dev,
+ ARRAY_SIZE(saved_regs),
+ sizeof(*chip->saved_regs),
+ GFP_KERNEL);
+ if (!chip->saved_regs)
return -ENOMEM;
- }
#endif
chip->active_ctrl(chip, -1); /* disable CLKRUN */
-
- *rchip = chip;
return 0;
}
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index 20b4faea50a6..93ff029e6583 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -65,25 +65,6 @@ static const struct pci_device_id snd_cs5530_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_cs5530_ids);
-static int snd_cs5530_free(struct snd_cs5530 *chip)
-{
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_cs5530_dev_free(struct snd_device *device)
-{
- struct snd_cs5530 *chip = device->device_data;
- return snd_cs5530_free(chip);
-}
-
-static void snd_cs5530_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
{
outb(reg, io + 4);
@@ -94,50 +75,28 @@ static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
}
static int snd_cs5530_create(struct snd_card *card,
- struct pci_dev *pci,
- struct snd_cs5530 **rchip)
+ struct pci_dev *pci)
{
- struct snd_cs5530 *chip;
+ struct snd_cs5530 *chip = card->private_data;
unsigned long sb_base;
u8 irq, dma8, dma16 = 0;
u16 map;
void __iomem *mem;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_cs5530_dev_free,
- };
- *rchip = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
chip->card = card;
chip->pci = pci;
- err = pci_request_regions(pci, "CS5530");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ err = pcim_iomap_regions(pci, 1 << 0, "CS5530");
+ if (err < 0)
return err;
- }
chip->pci_base = pci_resource_start(pci, 0);
-
- mem = pci_ioremap_bar(pci, 0);
- if (mem == NULL) {
- snd_cs5530_free(chip);
- return -EBUSY;
- }
-
+ mem = pcim_iomap_table(pci)[0];
map = readw(mem + 0x18);
- iounmap(mem);
/* Map bits
0:1 * 0x20 + 0x200 = sb base
@@ -154,7 +113,6 @@ static int snd_cs5530_create(struct snd_card *card,
dev_info(card->dev, "XpressAudio at 0x%lx\n", sb_base);
else {
dev_err(card->dev, "Could not find XpressAudio!\n");
- snd_cs5530_free(chip);
return -ENODEV;
}
@@ -174,7 +132,6 @@ static int snd_cs5530_create(struct snd_card *card,
dma16 = 7;
else {
dev_err(card->dev, "No 16bit DMA enabled\n");
- snd_cs5530_free(chip);
return -ENODEV;
}
@@ -186,7 +143,6 @@ static int snd_cs5530_create(struct snd_card *card,
dma8 = 3;
else {
dev_err(card->dev, "No 8bit DMA enabled\n");
- snd_cs5530_free(chip);
return -ENODEV;
}
@@ -200,7 +156,6 @@ static int snd_cs5530_create(struct snd_card *card,
irq = 10;
else {
dev_err(card->dev, "SoundBlaster IRQ not set\n");
- snd_cs5530_free(chip);
return -ENODEV;
}
@@ -210,31 +165,21 @@ static int snd_cs5530_create(struct snd_card *card,
dma16, SB_HW_CS5530, &chip->sb);
if (err < 0) {
dev_err(card->dev, "Could not create SoundBlaster\n");
- snd_cs5530_free(chip);
return err;
}
err = snd_sb16dsp_pcm(chip->sb, 0);
if (err < 0) {
dev_err(card->dev, "Could not create PCM\n");
- snd_cs5530_free(chip);
return err;
}
err = snd_sbmixer_new(chip->sb);
if (err < 0) {
dev_err(card->dev, "Could not create Mixer\n");
- snd_cs5530_free(chip);
- return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_cs5530_free(chip);
return err;
}
- *rchip = chip;
return 0;
}
@@ -243,7 +188,7 @@ static int snd_cs5530_probe(struct pci_dev *pci,
{
static int dev;
struct snd_card *card;
- struct snd_cs5530 *chip = NULL;
+ struct snd_cs5530 *chip;
int err;
if (dev >= SNDRV_CARDS)
@@ -253,27 +198,23 @@ static int snd_cs5530_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
-
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
- err = snd_cs5530_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_cs5530_create(card, pci);
+ if (err < 0)
return err;
- }
strcpy(card->driver, "CS5530");
strcpy(card->shortname, "CS5530 Audio");
sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
@@ -283,7 +224,6 @@ static struct pci_driver cs5530_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5530_ids,
.probe = snd_cs5530_probe,
- .remove = snd_cs5530_remove,
};
module_pci_driver(cs5530_driver);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index e048b45d9e7e..499fa0148f9a 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -237,51 +237,24 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
+static void snd_cs5535audio_free(struct snd_card *card)
{
- pci_set_power_state(cs5535au->pci, PCI_D3hot);
-
- if (cs5535au->irq >= 0)
- free_irq(cs5535au->irq, cs5535au);
-
- pci_release_regions(cs5535au->pci);
- pci_disable_device(cs5535au->pci);
- kfree(cs5535au);
- return 0;
-}
-
-static int snd_cs5535audio_dev_free(struct snd_device *device)
-{
- struct cs5535audio *cs5535au = device->device_data;
- return snd_cs5535audio_free(cs5535au);
+ olpc_quirks_cleanup();
}
static int snd_cs5535audio_create(struct snd_card *card,
- struct pci_dev *pci,
- struct cs5535audio **rcs5535au)
+ struct pci_dev *pci)
{
- struct cs5535audio *cs5535au;
-
+ struct cs5535audio *cs5535au = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_cs5535audio_dev_free,
- };
- *rcs5535au = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_warn(card->dev, "unable to get 32bit dma\n");
- err = -ENXIO;
- goto pcifail;
- }
-
- cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL);
- if (cs5535au == NULL) {
- err = -ENOMEM;
- goto pcifail;
+ return -ENXIO;
}
spin_lock_init(&cs5535au->reg_lock);
@@ -290,38 +263,22 @@ static int snd_cs5535audio_create(struct snd_card *card,
cs5535au->irq = -1;
err = pci_request_regions(pci, "CS5535 Audio");
- if (err < 0) {
- kfree(cs5535au);
- goto pcifail;
- }
+ if (err < 0)
+ return err;
cs5535au->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_cs5535audio_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_cs5535audio_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- err = -EBUSY;
- goto sndfail;
+ return -EBUSY;
}
cs5535au->irq = pci->irq;
card->sync_irq = cs5535au->irq;
pci_set_master(pci);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cs5535au, &ops);
- if (err < 0)
- goto sndfail;
-
- *rcs5535au = cs5535au;
return 0;
-
-sndfail: /* leave the device alive, just kill the snd */
- snd_cs5535audio_free(cs5535au);
- return err;
-
-pcifail:
- pci_disable_device(pci);
- return err;
}
static int snd_cs5535audio_probe(struct pci_dev *pci,
@@ -339,24 +296,24 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*cs5535au), &card);
if (err < 0)
return err;
+ cs5535au = card->private_data;
+ card->private_free = snd_cs5535audio_free;
- err = snd_cs5535audio_create(card, pci, &cs5535au);
+ err = snd_cs5535audio_create(card, pci);
if (err < 0)
- goto probefail_out;
-
- card->private_data = cs5535au;
+ return err;
err = snd_cs5535audio_mixer(cs5535au);
if (err < 0)
- goto probefail_out;
+ return err;
err = snd_cs5535audio_pcm(cs5535au);
if (err < 0)
- goto probefail_out;
+ return err;
strcpy(card->driver, DRIVER_NAME);
@@ -367,28 +324,17 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto probefail_out;
+ return err;
pci_set_drvdata(pci, card);
dev++;
return 0;
-
-probefail_out:
- snd_card_free(card);
- return err;
-}
-
-static void snd_cs5535audio_remove(struct pci_dev *pci)
-{
- olpc_quirks_cleanup();
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver cs5535audio_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_cs5535audio_ids,
.probe = snd_cs5535audio_probe,
- .remove = snd_cs5535audio_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_cs5535audio_pm,
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c
index 110d3209441b..122170a410d9 100644
--- a/sound/pci/cs5535audio/cs5535audio_olpc.c
+++ b/sound/pci/cs5535audio/cs5535audio_olpc.c
@@ -171,10 +171,8 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) {
err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i],
ac97->private_data));
- if (err < 0) {
- gpio_free(OLPC_GPIO_MIC_AC);
+ if (err < 0)
return err;
- }
}
/* turn off the mic by default */
@@ -184,5 +182,6 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
void olpc_quirks_cleanup(void)
{
- gpio_free(OLPC_GPIO_MIC_AC);
+ if (machine_is_olpc())
+ gpio_free(OLPC_GPIO_MIC_AC);
}
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index a62e5581ad14..25b012ef5c3e 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1882,105 +1882,63 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
Module construction / destruction
******************************************************************************/
-static int snd_echo_free(struct echoaudio *chip)
+static void snd_echo_free(struct snd_card *card)
{
+ struct echoaudio *chip = card->private_data;
+
if (chip->comm_page)
rest_in_peace(chip);
if (chip->irq >= 0)
free_irq(chip->irq, chip);
- if (chip->comm_page)
- snd_dma_free_pages(&chip->commpage_dma_buf);
-
- iounmap(chip->dsp_registers);
- release_and_free_resource(chip->iores);
- pci_disable_device(chip->pci);
-
/* release chip data */
free_firmware_cache(chip);
- kfree(chip);
- return 0;
-}
-
-
-
-static int snd_echo_dev_free(struct snd_device *device)
-{
- struct echoaudio *chip = device->device_data;
-
- return snd_echo_free(chip);
}
-
-
/* <--snd_echo_probe() */
static int snd_echo_create(struct snd_card *card,
- struct pci_dev *pci,
- struct echoaudio **rchip)
+ struct pci_dev *pci)
{
- struct echoaudio *chip;
+ struct echoaudio *chip = card->private_data;
int err;
size_t sz;
- static const struct snd_device_ops ops = {
- .dev_free = snd_echo_dev_free,
- };
-
- *rchip = NULL;
pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0);
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
pci_set_master(pci);
/* Allocate chip if needed */
- if (!*rchip) {
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
- dev_dbg(card->dev, "chip=%p\n", chip);
- spin_lock_init(&chip->lock);
- chip->card = card;
- chip->pci = pci;
- chip->irq = -1;
- chip->opencount = 0;
- mutex_init(&chip->mode_mutex);
- chip->can_set_rate = 1;
- } else {
- /* If this was called from the resume function, chip is
- * already allocated and it contains current card settings.
- */
- chip = *rchip;
- }
+ spin_lock_init(&chip->lock);
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+ chip->opencount = 0;
+ mutex_init(&chip->mode_mutex);
+ chip->can_set_rate = 1;
/* PCI resource allocation */
+ err = pci_request_regions(pci, ECHOCARD_NAME);
+ if (err < 0)
+ return err;
+
chip->dsp_registers_phys = pci_resource_start(pci, 0);
sz = pci_resource_len(pci, 0);
if (sz > PAGE_SIZE)
sz = PAGE_SIZE; /* We map only the required part */
- chip->iores = request_mem_region(chip->dsp_registers_phys, sz,
- ECHOCARD_NAME);
- if (!chip->iores) {
- dev_err(chip->card->dev, "cannot get memory region\n");
- snd_echo_free(chip);
- return -EBUSY;
- }
- chip->dsp_registers = ioremap(chip->dsp_registers_phys, sz);
+ chip->dsp_registers = devm_ioremap(&pci->dev, chip->dsp_registers_phys, sz);
if (!chip->dsp_registers) {
dev_err(chip->card->dev, "ioremap failed\n");
- snd_echo_free(chip);
return -ENOMEM;
}
if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
KBUILD_MODNAME, chip)) {
dev_err(chip->card->dev, "cannot grab irq\n");
- snd_echo_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
@@ -1988,39 +1946,29 @@ static int snd_echo_create(struct snd_card *card,
dev_dbg(card->dev, "pci=%p irq=%d subdev=%04x Init hardware...\n",
chip->pci, chip->irq, chip->pci->subsystem_device);
+ card->private_free = snd_echo_free;
+
/* Create the DSP comm page - this is the area of memory used for most
of the communication with the DSP, which accesses it via bus mastering */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
- sizeof(struct comm_page),
- &chip->commpage_dma_buf) < 0) {
- dev_err(chip->card->dev, "cannot allocate the comm page\n");
- snd_echo_free(chip);
+ chip->commpage_dma_buf =
+ snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+ sizeof(struct comm_page));
+ if (!chip->commpage_dma_buf)
return -ENOMEM;
- }
- chip->comm_page_phys = chip->commpage_dma_buf.addr;
- chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area;
+ chip->comm_page_phys = chip->commpage_dma_buf->addr;
+ chip->comm_page = (struct comm_page *)chip->commpage_dma_buf->area;
err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
if (err >= 0)
err = set_mixer_defaults(chip);
if (err < 0) {
dev_err(card->dev, "init_hw err=%d\n", err);
- snd_echo_free(chip);
return err;
}
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_echo_free(chip);
- return err;
- }
- *rchip = chip;
- /* Init done ! */
return 0;
}
-
-
/* constructor */
static int snd_echo_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
@@ -2040,17 +1988,15 @@ static int snd_echo_probe(struct pci_dev *pci,
}
i = 0;
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
- chip = NULL; /* Tells snd_echo_create to allocate chip */
- err = snd_echo_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_echo_create(card, pci);
+ if (err < 0)
return err;
- }
strcpy(card->driver, "Echo_" ECHOCARD_NAME);
strcpy(card->shortname, chip->card_name);
@@ -2066,7 +2012,6 @@ static int snd_echo_probe(struct pci_dev *pci,
err = snd_echo_new_pcm(chip);
if (err < 0) {
dev_err(chip->card->dev, "new pcm error %d\n", err);
- snd_card_free(card);
return err;
}
@@ -2075,7 +2020,6 @@ static int snd_echo_probe(struct pci_dev *pci,
err = snd_echo_midi_create(card, chip);
if (err < 0) {
dev_err(chip->card->dev, "new midi error %d\n", err);
- snd_card_free(card);
return err;
}
}
@@ -2085,64 +2029,64 @@ static int snd_echo_probe(struct pci_dev *pci,
snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip);
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#ifdef ECHOCARD_HAS_LINE_OUT_GAIN
err = snd_ctl_add(chip->card,
snd_ctl_new1(&snd_echo_line_output_gain, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#endif
#else /* ECHOCARD_HAS_VMIXER */
err = snd_ctl_add(chip->card,
snd_ctl_new1(&snd_echo_pcm_output_gain, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#endif /* ECHOCARD_HAS_VMIXER */
#ifdef ECHOCARD_HAS_INPUT_GAIN
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#endif
#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
if (!chip->hasnt_input_nominal_level) {
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip));
if (err < 0)
- goto ctl_error;
+ return err;
}
#endif
#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#endif
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip));
if (err < 0)
- goto ctl_error;
+ return err;
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#ifdef ECHOCARD_HAS_MONITOR
snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip);
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#endif
#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#endif
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
/* Creates a list of available digital modes */
@@ -2153,7 +2097,7 @@ static int snd_echo_probe(struct pci_dev *pci,
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */
#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
@@ -2167,37 +2111,32 @@ static int snd_echo_probe(struct pci_dev *pci,
chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip);
err = snd_ctl_add(chip->card, chip->clock_src_ctl);
if (err < 0)
- goto ctl_error;
+ return err;
}
#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */
#ifdef ECHOCARD_HAS_DIGITAL_IO
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip));
if (err < 0)
- goto ctl_error;
+ return err;
#endif
#ifdef ECHOCARD_HAS_PHANTOM_POWER
if (chip->has_phantom_power) {
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip));
if (err < 0)
- goto ctl_error;
+ return err;
}
#endif
err = snd_card_register(card);
if (err < 0)
- goto ctl_error;
+ return err;
dev_info(card->dev, "Card registered: %s\n", card->longname);
pci_set_drvdata(pci, chip);
dev++;
return 0;
-
-ctl_error:
- dev_err(card->dev, "new control error %d\n", err);
- snd_card_free(card);
- return err;
}
@@ -2299,18 +2238,6 @@ static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume);
#define SND_ECHO_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
-
-static void snd_echo_remove(struct pci_dev *pci)
-{
- struct echoaudio *chip;
-
- chip = pci_get_drvdata(pci);
- if (chip)
- snd_card_free(chip->card);
-}
-
-
-
/******************************************************************************
Everything starts and ends here
******************************************************************************/
@@ -2320,7 +2247,6 @@ static struct pci_driver echo_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_echo_ids,
.probe = snd_echo_probe,
- .remove = snd_echo_remove,
.driver = {
.pm = SND_ECHO_PM_OPS,
},
diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h
index 0afe13f7b6e5..d51de3e4edfa 100644
--- a/sound/pci/echoaudio/echoaudio.h
+++ b/sound/pci/echoaudio/echoaudio.h
@@ -348,7 +348,7 @@ struct echoaudio {
struct pci_dev *pci;
unsigned long dsp_registers_phys;
struct resource *iores;
- struct snd_dma_buffer commpage_dma_buf;
+ struct snd_dma_buffer *commpage_dma_buf;
int irq;
#ifdef ECHOCARD_HAS_MIDI
struct snd_rawmidi *rmidi;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 887bfb3c1e17..672af4b9597b 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -99,67 +99,67 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*emu), &card);
if (err < 0)
return err;
+ emu = card->private_data;
+
if (max_buffer_size[dev] < 32)
max_buffer_size[dev] = 32;
else if (max_buffer_size[dev] > 1024)
max_buffer_size[dev] = 1024;
err = snd_emu10k1_create(card, pci, extin[dev], extout[dev],
(long)max_buffer_size[dev] * 1024 * 1024,
- enable_ir[dev], subsystem[dev],
- &emu);
+ enable_ir[dev], subsystem[dev]);
if (err < 0)
- goto error;
- card->private_data = emu;
+ return err;
emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f;
err = snd_emu10k1_pcm(emu, 0);
if (err < 0)
- goto error;
+ return err;
err = snd_emu10k1_pcm_mic(emu, 1);
if (err < 0)
- goto error;
+ return err;
err = snd_emu10k1_pcm_efx(emu, 2);
if (err < 0)
- goto error;
+ return err;
/* This stores the periods table. */
if (emu->card_capabilities->ca0151_chip) { /* P16V */
- err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- 1024, &emu->p16v_buffer);
- if (err < 0)
- goto error;
+ emu->p16v_buffer =
+ snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024);
+ if (!emu->p16v_buffer)
+ return -ENOMEM;
}
err = snd_emu10k1_mixer(emu, 0, 3);
if (err < 0)
- goto error;
+ return err;
err = snd_emu10k1_timer(emu, 0);
if (err < 0)
- goto error;
+ return err;
err = snd_emu10k1_pcm_multi(emu, 3);
if (err < 0)
- goto error;
+ return err;
if (emu->card_capabilities->ca0151_chip) { /* P16V */
err = snd_p16v_pcm(emu, 4);
if (err < 0)
- goto error;
+ return err;
}
if (emu->audigy) {
err = snd_emu10k1_audigy_midi(emu);
if (err < 0)
- goto error;
+ return err;
} else {
err = snd_emu10k1_midi(emu);
if (err < 0)
- goto error;
+ return err;
}
err = snd_emu10k1_fx8010_new(emu, 0);
if (err < 0)
- goto error;
+ return err;
#ifdef ENABLE_SYNTH
if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 ||
@@ -187,7 +187,7 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto error;
+ return err;
if (emu->card_capabilities->emu_model)
schedule_delayed_work(&emu->emu1010.firmware_work, 0);
@@ -195,18 +195,8 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
pci_set_drvdata(pci, card);
dev++;
return 0;
-
- error:
- snd_card_free(card);
- return err;
}
-static void snd_card_emu10k1_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
-
#ifdef CONFIG_PM_SLEEP
static int snd_emu10k1_suspend(struct device *dev)
{
@@ -263,7 +253,6 @@ static struct pci_driver emu10k1_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe,
- .remove = snd_card_emu10k1_remove,
.driver = {
.pm = SND_EMU10K1_PM_OPS,
},
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 24a2fd706d69..86cc1ca025e4 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1242,8 +1242,10 @@ static int alloc_pm_buffer(struct snd_emu10k1 *emu);
static void free_pm_buffer(struct snd_emu10k1 *emu);
#endif
-static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+static void snd_emu10k1_free(struct snd_card *card)
{
+ struct snd_emu10k1 *emu = card->private_data;
+
if (emu->port) { /* avoid access to already used hardware */
snd_emu10k1_fx8010_tram_setup(emu, 0);
snd_emu10k1_done(emu);
@@ -1256,8 +1258,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
cancel_delayed_work_sync(&emu->emu1010.firmware_work);
release_firmware(emu->firmware);
release_firmware(emu->dock_fw);
- if (emu->irq >= 0)
- free_irq(emu->irq, emu);
snd_util_memhdr_free(emu->memhdr);
if (emu->silent_page.area)
snd_dma_free_pages(&emu->silent_page);
@@ -1268,19 +1268,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
#ifdef CONFIG_PM_SLEEP
free_pm_buffer(emu);
#endif
- if (emu->port)
- pci_release_regions(emu->pci);
- if (emu->card_capabilities->ca0151_chip) /* P16V */
- snd_p16v_free(emu);
- pci_disable_device(emu->pci);
- kfree(emu);
- return 0;
-}
-
-static int snd_emu10k1_dev_free(struct snd_device *device)
-{
- struct snd_emu10k1 *emu = device->device_data;
- return snd_emu10k1_free(emu);
}
static const struct snd_emu_chip_details emu_chip_details[] = {
@@ -1782,32 +1769,22 @@ int snd_emu10k1_create(struct snd_card *card,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
- uint subsystem,
- struct snd_emu10k1 **remu)
+ uint subsystem)
{
- struct snd_emu10k1 *emu;
+ struct snd_emu10k1 *emu = card->private_data;
int idx, err;
int is_audigy;
size_t page_table_size;
__le32 *pgtbl;
unsigned int silent_page;
const struct snd_emu_chip_details *c;
- static const struct snd_device_ops ops = {
- .dev_free = snd_emu10k1_dev_free,
- };
-
- *remu = NULL;
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- emu = kzalloc(sizeof(*emu), GFP_KERNEL);
- if (emu == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
+ card->private_free = snd_emu10k1_free;
emu->card = card;
spin_lock_init(&emu->reg_lock);
spin_lock_init(&emu->emu_lock);
@@ -1850,8 +1827,6 @@ int snd_emu10k1_create(struct snd_card *card,
}
if (c->vendor == 0) {
dev_err(card->dev, "emu10k1: Card not recognised\n");
- kfree(emu);
- pci_disable_device(pci);
return -ENOENT;
}
emu->card_capabilities = c;
@@ -1883,8 +1858,6 @@ int snd_emu10k1_create(struct snd_card *card,
dev_err(card->dev,
"architecture does not support PCI busmaster DMA with mask 0x%lx\n",
emu->dma_mask);
- kfree(emu);
- pci_disable_device(pci);
return -ENXIO;
}
if (is_audigy)
@@ -1893,11 +1866,8 @@ int snd_emu10k1_create(struct snd_card *card,
emu->gpr_base = FXGPREGBASE;
err = pci_request_regions(pci, "EMU10K1");
- if (err < 0) {
- kfree(emu);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
emu->port = pci_resource_start(pci, 0);
emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
@@ -1905,10 +1875,8 @@ int snd_emu10k1_create(struct snd_card *card,
page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 :
MAXPAGES0);
if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size,
- &emu->ptb_pages) < 0) {
- err = -ENOMEM;
- goto error;
- }
+ &emu->ptb_pages) < 0)
+ return -ENOMEM;
dev_dbg(card->dev, "page table address range is %.8lx:%.8lx\n",
(unsigned long)emu->ptb_pages.addr,
(unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes));
@@ -1917,26 +1885,20 @@ int snd_emu10k1_create(struct snd_card *card,
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;
- }
+ if (!emu->page_ptr_table || !emu->page_addr_table)
+ return -ENOMEM;
if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE,
- &emu->silent_page) < 0) {
- err = -ENOMEM;
- goto error;
- }
+ &emu->silent_page) < 0)
+ return -ENOMEM;
dev_dbg(card->dev, "silent page range is %.8lx:%.8lx\n",
(unsigned long)emu->silent_page.addr,
(unsigned long)(emu->silent_page.addr +
emu->silent_page.bytes));
emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE);
- if (emu->memhdr == NULL) {
- err = -ENOMEM;
- goto error;
- }
+ if (!emu->memhdr)
+ return -ENOMEM;
emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) -
sizeof(struct snd_util_memblk);
@@ -1954,18 +1916,16 @@ int snd_emu10k1_create(struct snd_card *card,
if (emu->card_capabilities->ca_cardbus_chip) {
err = snd_emu10k1_cardbus_init(emu);
if (err < 0)
- goto error;
+ return err;
}
if (emu->card_capabilities->ecard) {
err = snd_emu10k1_ecard_init(emu);
if (err < 0)
- goto error;
+ return err;
} else if (emu->card_capabilities->emu_model) {
err = snd_emu10k1_emu1010_init(emu);
- if (err < 0) {
- snd_emu10k1_free(emu);
+ if (err < 0)
return err;
- }
} else {
/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
does not support this, it shouldn't do any harm */
@@ -1979,11 +1939,9 @@ int snd_emu10k1_create(struct snd_card *card,
emu->fx8010.etram_pages.bytes = 0;
/* irq handler must be registered after I/O ports are activated */
- if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, emu)) {
- err = -EBUSY;
- goto error;
- }
+ if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, emu))
+ return -EBUSY;
emu->irq = pci->irq;
card->sync_irq = emu->irq;
@@ -2022,33 +1980,23 @@ int snd_emu10k1_create(struct snd_card *card,
err = snd_emu10k1_init(emu, enable_ir, 0);
if (err < 0)
- goto error;
+ return err;
#ifdef CONFIG_PM_SLEEP
err = alloc_pm_buffer(emu);
if (err < 0)
- goto error;
+ return err;
#endif
/* Initialize the effect engine */
err = snd_emu10k1_init_efx(emu);
if (err < 0)
- goto error;
+ return err;
snd_emu10k1_audio_enable(emu);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops);
- if (err < 0)
- goto error;
-
#ifdef CONFIG_SND_PROC_FS
snd_emu10k1_proc_init(emu);
#endif
-
- *remu = emu;
return 0;
-
- error:
- snd_emu10k1_free(emu);
- return err;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 89b0f3884067..c49c44dc1082 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -216,7 +216,6 @@ struct emu10k1x {
struct pci_dev *pci;
unsigned long port;
- struct resource *res_port;
int irq;
unsigned char revision; /* chip revision */
@@ -233,7 +232,7 @@ struct emu10k1x {
struct emu10k1x_voice capture_voice;
u32 spdif_bits[3]; // SPDIF out setup
- struct snd_dma_buffer dma_buffer;
+ struct snd_dma_buffer *dma_buffer;
struct emu10k1x_midi midi;
};
@@ -442,7 +441,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct emu10k1x_pcm *epcm = runtime->private_data;
int voice = epcm->voice->number;
- u32 *table_base = (u32 *)(emu->dma_buffer.area+1024*voice);
+ u32 *table_base = (u32 *)(emu->dma_buffer->area+1024*voice);
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
int i;
@@ -451,7 +450,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
*table_base++=period_size_bytes<<16;
}
- snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer.addr+1024*voice);
+ snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer->addr+1024*voice);
snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_SIZE, voice, (runtime->periods - 1) << 19);
snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_PTR, voice, 0);
snd_emu10k1x_ptr_write(emu, PLAYBACK_POINTER, voice, 0);
@@ -737,37 +736,15 @@ static int snd_emu10k1x_ac97(struct emu10k1x *chip)
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
-static int snd_emu10k1x_free(struct emu10k1x *chip)
+static void snd_emu10k1x_free(struct snd_card *card)
{
+ struct emu10k1x *chip = card->private_data;
+
snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0);
// disable interrupts
outl(0, chip->port + INTE);
// disable audio
outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
-
- /* release the irq */
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
-
- // release the i/o port
- release_and_free_resource(chip->res_port);
-
- // release the DMA
- if (chip->dma_buffer.area) {
- snd_dma_free_pages(&chip->dma_buffer);
- }
-
- pci_disable_device(chip->pci);
-
- // release the data
- kfree(chip);
- return 0;
-}
-
-static int snd_emu10k1x_dev_free(struct snd_device *device)
-{
- struct emu10k1x *chip = device->device_data;
- return snd_emu10k1x_free(chip);
}
static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
@@ -885,34 +862,21 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device)
}
static int snd_emu10k1x_create(struct snd_card *card,
- struct pci_dev *pci,
- struct emu10k1x **rchip)
+ struct pci_dev *pci)
{
- struct emu10k1x *chip;
+ struct emu10k1x *chip = card->private_data;
int err;
int ch;
- static const struct snd_device_ops ops = {
- .dev_free = snd_emu10k1x_dev_free,
- };
-
- *rchip = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28)) < 0) {
dev_err(card->dev, "error to set 28bit mask DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
chip->card = card;
chip->pci = pci;
chip->irq = -1;
@@ -920,29 +884,24 @@ static int snd_emu10k1x_create(struct snd_card *card,
spin_lock_init(&chip->emu_lock);
spin_lock_init(&chip->voice_lock);
+ err = pci_request_regions(pci, "EMU10K1X");
+ if (err < 0)
+ return err;
chip->port = pci_resource_start(pci, 0);
- chip->res_port = request_region(chip->port, 8, "EMU10K1X");
- if (!chip->res_port) {
- dev_err(card->dev, "cannot allocate the port 0x%lx\n",
- chip->port);
- snd_emu10k1x_free(chip);
- return -EBUSY;
- }
- if (request_irq(pci->irq, snd_emu10k1x_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1x_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "cannot grab irq %d\n", pci->irq);
- snd_emu10k1x_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_emu10k1x_free;
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- 4 * 1024, &chip->dma_buffer) < 0) {
- snd_emu10k1x_free(chip);
+ chip->dma_buffer = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+ 4 * 1024);
+ if (!chip->dma_buffer)
return -ENOMEM;
- }
pci_set_master(pci);
/* read revision & serial */
@@ -998,12 +957,6 @@ static int snd_emu10k1x_create(struct snd_card *card,
outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_emu10k1x_free(chip);
- return err;
- }
- *rchip = chip;
return 0;
}
@@ -1553,50 +1506,37 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
- err = snd_emu10k1x_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_emu10k1x_create(card, pci);
+ if (err < 0)
return err;
- }
err = snd_emu10k1x_pcm(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_emu10k1x_pcm(chip, 1);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_emu10k1x_pcm(chip, 2);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_emu10k1x_ac97(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_emu10k1x_mixer(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_emu10k1x_midi(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
snd_emu10k1x_proc_init(chip);
@@ -1606,21 +1546,14 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
card->shortname, chip->port, chip->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_emu10k1x_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
// PCI IDs
static const struct pci_device_id snd_emu10k1x_ids[] = {
{ PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */
@@ -1633,7 +1566,6 @@ static struct pci_driver emu10k1x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1x_ids,
.probe = snd_emu10k1x_probe,
- .remove = snd_emu10k1x_remove,
};
module_pci_driver(emu10k1x_driver);
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index ff2a3974c824..18a1b0740e6b 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -290,7 +290,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int channel = substream->pcm->device - emu->p16v_device_offset;
- u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
+ u32 *table_base = (u32 *)(emu->p16v_buffer->area+(8*16*channel));
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
int i;
u32 tmp;
@@ -308,8 +308,8 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
runtime->dma_addr, runtime->dma_area, table_base);
dev_dbg(emu->card->dev,
"dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
- emu->p16v_buffer.addr, emu->p16v_buffer.area,
- emu->p16v_buffer.bytes);
+ emu->p16v_buffer->addr, emu->p16v_buffer->area,
+ emu->p16v_buffer->bytes);
#endif /* debug */
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
switch (runtime->rate) {
@@ -333,7 +333,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
table_base[(i*2)+1]=period_size_bytes<<16;
}
- snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer->addr+(8*16*channel));
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
@@ -567,20 +567,6 @@ static const struct snd_pcm_ops snd_p16v_capture_ops = {
.pointer = snd_p16v_pcm_pointer_capture,
};
-
-int snd_p16v_free(struct snd_emu10k1 *chip)
-{
- // release the data
- if (chip->p16v_buffer.area) {
- snd_dma_free_pages(&chip->p16v_buffer);
- /*
- dev_dbg(chip->card->dev, "period lables free: %p\n",
- &chip->p16v_buffer);
- */
- }
- return 0;
-}
-
int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
{
struct snd_pcm *pcm;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 728b69dad21b..2651f0c64c06 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -414,7 +414,7 @@ struct ensoniq {
unsigned int spdif_stream;
#ifdef CHIP1370
- struct snd_dma_buffer dma_bug;
+ struct snd_dma_buffer *dma_bug;
#endif
#ifdef SUPPORT_JOYSTICK
@@ -1872,11 +1872,11 @@ static void snd_ensoniq_proc_init(struct ensoniq *ensoniq)
*/
-static int snd_ensoniq_free(struct ensoniq *ensoniq)
+static void snd_ensoniq_free(struct snd_card *card)
{
+ struct ensoniq *ensoniq = card->private_data;
+
snd_ensoniq_free_gameport(ensoniq);
- if (ensoniq->irq < 0)
- goto __hw_end;
#ifdef CHIP1370
outl(ES_1370_SERR_DISABLE, ES_REG(ensoniq, CONTROL)); /* switch everything off */
outl(0, ES_REG(ensoniq, SERIAL)); /* clear serial interface */
@@ -1884,24 +1884,6 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq)
outl(0, ES_REG(ensoniq, CONTROL)); /* switch everything off */
outl(0, ES_REG(ensoniq, SERIAL)); /* clear serial interface */
#endif
- pci_set_power_state(ensoniq->pci, PCI_D3hot);
- __hw_end:
-#ifdef CHIP1370
- if (ensoniq->dma_bug.area)
- snd_dma_free_pages(&ensoniq->dma_bug);
-#endif
- if (ensoniq->irq >= 0)
- free_irq(ensoniq->irq, ensoniq);
- pci_release_regions(ensoniq->pci);
- pci_disable_device(ensoniq->pci);
- kfree(ensoniq);
- return 0;
-}
-
-static int snd_ensoniq_dev_free(struct snd_device *device)
-{
- struct ensoniq *ensoniq = device->device_data;
- return snd_ensoniq_free(ensoniq);
}
#ifdef CHIP1371
@@ -1935,7 +1917,7 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
- outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME));
+ outl(ensoniq->dma_bug->addr, ES_REG(ensoniq, PHANTOM_FRAME));
outl(0, ES_REG(ensoniq, PHANTOM_COUNT));
#else
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
@@ -2032,51 +2014,35 @@ static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume
#endif /* CONFIG_PM_SLEEP */
static int snd_ensoniq_create(struct snd_card *card,
- struct pci_dev *pci,
- struct ensoniq **rensoniq)
+ struct pci_dev *pci)
{
- struct ensoniq *ensoniq;
+ struct ensoniq *ensoniq = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_ensoniq_dev_free,
- };
- *rensoniq = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- ensoniq = kzalloc(sizeof(*ensoniq), GFP_KERNEL);
- if (ensoniq == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
spin_lock_init(&ensoniq->reg_lock);
mutex_init(&ensoniq->src_mutex);
ensoniq->card = card;
ensoniq->pci = pci;
ensoniq->irq = -1;
err = pci_request_regions(pci, "Ensoniq AudioPCI");
- if (err < 0) {
- kfree(ensoniq);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
ensoniq->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, ensoniq)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_audiopci_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, ensoniq)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_ensoniq_free(ensoniq);
return -EBUSY;
}
ensoniq->irq = pci->irq;
card->sync_irq = ensoniq->irq;
#ifdef CHIP1370
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- 16, &ensoniq->dma_bug) < 0) {
- dev_err(card->dev, "unable to allocate space for phantom area - dma_bug\n");
- snd_ensoniq_free(ensoniq);
- return -EBUSY;
- }
+ ensoniq->dma_bug =
+ snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 16);
+ if (!ensoniq->dma_bug)
+ return -ENOMEM;
#endif
pci_set_master(pci);
ensoniq->rev = pci->revision;
@@ -2099,17 +2065,10 @@ static int snd_ensoniq_create(struct snd_card *card,
ensoniq->cssr |= ES_1371_ST_AC97_RST;
#endif
+ card->private_free = snd_ensoniq_free;
snd_ensoniq_chip_init(ensoniq);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops);
- if (err < 0) {
- snd_ensoniq_free(ensoniq);
- return err;
- }
-
snd_ensoniq_proc_init(ensoniq);
-
- *rensoniq = ensoniq;
return 0;
}
@@ -2360,47 +2319,35 @@ static int snd_audiopci_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*ensoniq), &card);
if (err < 0)
return err;
+ ensoniq = card->private_data;
- err = snd_ensoniq_create(card, pci, &ensoniq);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_ensoniq_create(card, pci);
+ if (err < 0)
return err;
- }
- card->private_data = ensoniq;
#ifdef CHIP1370
err = snd_ensoniq_1370_mixer(ensoniq);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
#endif
#ifdef CHIP1371
err = snd_ensoniq_1371_mixer(ensoniq, spdif[dev], lineio[dev]);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
#endif
err = snd_ensoniq_pcm(ensoniq, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_ensoniq_pcm2(ensoniq, 1);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_ensoniq_midi(ensoniq, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
snd_ensoniq_create_gameport(ensoniq, dev);
@@ -2414,26 +2361,18 @@ static int snd_audiopci_probe(struct pci_dev *pci,
ensoniq->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_audiopci_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver ens137x_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_audiopci_ids,
.probe = snd_audiopci_probe,
- .remove = snd_audiopci_remove,
.driver = {
.pm = SND_ENSONIQ_PM_OPS,
},
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 33b1eb347a27..00b976f42a3d 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1521,8 +1521,10 @@ static inline int snd_es1938_create_gameport(struct es1938 *chip) { return -ENOS
static inline void snd_es1938_free_gameport(struct es1938 *chip) { }
#endif /* SUPPORT_JOYSTICK */
-static int snd_es1938_free(struct es1938 *chip)
+static void snd_es1938_free(struct snd_card *card)
{
+ struct es1938 *chip = card->private_data;
+
/* disable irqs */
outb(0x00, SLIO_REG(chip, IRQCONTROL));
if (chip->rmidi)
@@ -1532,71 +1534,47 @@ static int snd_es1938_free(struct es1938 *chip)
if (chip->irq >= 0)
free_irq(chip->irq, chip);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_es1938_dev_free(struct snd_device *device)
-{
- struct es1938 *chip = device->device_data;
- return snd_es1938_free(chip);
}
static int snd_es1938_create(struct snd_card *card,
- struct pci_dev *pci,
- struct es1938 **rchip)
+ struct pci_dev *pci)
{
- struct es1938 *chip;
+ struct es1938 *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_es1938_dev_free,
- };
-
- *rchip = NULL;
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
dev_err(card->dev,
"architecture does not support 24bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
spin_lock_init(&chip->reg_lock);
spin_lock_init(&chip->mixer_lock);
chip->card = card;
chip->pci = pci;
chip->irq = -1;
err = pci_request_regions(pci, "ESS Solo-1");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
chip->io_port = pci_resource_start(pci, 0);
chip->sb_port = pci_resource_start(pci, 1);
chip->vc_port = pci_resource_start(pci, 2);
chip->mpu_port = pci_resource_start(pci, 3);
chip->game_port = pci_resource_start(pci, 4);
+ /* still use non-managed irq handler as it's re-acquired at PM resume */
if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED,
KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_es1938_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_es1938_free;
dev_dbg(card->dev,
"create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n",
chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port);
@@ -1604,14 +1582,6 @@ static int snd_es1938_create(struct snd_card *card,
chip->ddma_port = chip->vc_port + 0x00; /* fix from Thomas Sailer */
snd_es1938_chip_init(chip);
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_es1938_free(chip);
- return err;
- }
-
- *rchip = chip;
return 0;
}
@@ -1762,23 +1732,20 @@ static int snd_es1938_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
- for (idx = 0; idx < 5; idx++) {
+ chip = card->private_data;
+
+ for (idx = 0; idx < 5; idx++)
if (pci_resource_start(pci, idx) == 0 ||
- !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
- snd_card_free(card);
- return -ENODEV;
- }
- }
- err = snd_es1938_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
+ !(pci_resource_flags(pci, idx) & IORESOURCE_IO))
+ return -ENODEV;
+
+ err = snd_es1938_create(card, pci);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
strcpy(card->driver, "ES1938");
strcpy(card->shortname, "ESS ES1938 (Solo-1)");
@@ -1788,15 +1755,11 @@ static int snd_es1938_probe(struct pci_dev *pci,
chip->irq);
err = snd_es1938_new_pcm(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_es1938_mixer(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
if (snd_opl3_create(card,
SLSB_REG(chip, FMLOWADDR),
SLSB_REG(chip, FMHIGHADDR),
@@ -1805,15 +1768,11 @@ static int snd_es1938_probe(struct pci_dev *pci,
SLSB_REG(chip, FMLOWADDR));
} else {
err = snd_opl3_timer_new(opl3, 0, 1);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
chip->mpu_port,
@@ -1829,26 +1788,18 @@ static int snd_es1938_probe(struct pci_dev *pci,
snd_es1938_create_gameport(chip);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_es1938_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver es1938_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_es1938_ids,
.probe = snd_es1938_probe,
- .remove = snd_es1938_remove,
.driver = {
.pm = ES1938_PM_OPS,
},
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index c038c1035c39..6a8a02a9ecf4 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2442,7 +2442,8 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
if (!joystick[dev])
return -ENODEV;
- r = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport");
+ r = devm_request_region(&chip->pci->dev, JOYSTICK_ADDR, 8,
+ "ES1968 gameport");
if (!r)
return -EBUSY;
@@ -2450,7 +2451,6 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
if (!gp) {
dev_err(chip->card->dev,
"cannot allocate memory for gameport\n");
- release_and_free_resource(r);
return -ENOMEM;
}
@@ -2461,7 +2461,6 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
gameport_set_dev_parent(gp, &chip->pci->dev);
gp->io = JOYSTICK_ADDR;
- gameport_set_port_data(gp, r);
gameport_register_port(gp);
@@ -2471,12 +2470,8 @@ static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
static void snd_es1968_free_gameport(struct es1968 *chip)
{
if (chip->gameport) {
- struct resource *r = gameport_get_port_data(chip->gameport);
-
gameport_unregister_port(chip->gameport);
chip->gameport = NULL;
-
- release_and_free_resource(r);
}
}
#else
@@ -2490,7 +2485,7 @@ static int snd_es1968_input_register(struct es1968 *chip)
struct input_dev *input_dev;
int err;
- input_dev = input_allocate_device();
+ input_dev = devm_input_allocate_device(&chip->pci->dev);
if (!input_dev)
return -ENOMEM;
@@ -2510,10 +2505,8 @@ static int snd_es1968_input_register(struct es1968 *chip)
__set_bit(KEY_VOLUMEUP, input_dev->keybit);
err = input_register_device(input_dev);
- if (err) {
- input_free_device(input_dev);
+ if (err)
return err;
- }
chip->input_dev = input_dev;
return 0;
@@ -2597,13 +2590,11 @@ static const struct snd_tea575x_ops snd_es1968_tea_ops = {
};
#endif
-static int snd_es1968_free(struct es1968 *chip)
+static void snd_es1968_free(struct snd_card *card)
{
+ struct es1968 *chip = card->private_data;
+
cancel_work_sync(&chip->hwvol_work);
-#ifdef CONFIG_SND_ES1968_INPUT
- if (chip->input_dev)
- input_unregister_device(chip->input_dev);
-#endif
if (chip->io_port) {
outw(1, chip->io_port + 0x04); /* clear WP interrupts */
@@ -2615,19 +2606,7 @@ static int snd_es1968_free(struct es1968 *chip)
v4l2_device_unregister(&chip->v4l2_dev);
#endif
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
snd_es1968_free_gameport(chip);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_es1968_dev_free(struct snd_device *device)
-{
- struct es1968 *chip = device->device_data;
- return snd_es1968_free(chip);
}
struct ess_device_list {
@@ -2657,35 +2636,22 @@ static int snd_es1968_create(struct snd_card *card,
int capt_streams,
int chip_type,
int do_pm,
- int radio_nr,
- struct es1968 **chip_ret)
+ int radio_nr)
{
- static const struct snd_device_ops ops = {
- .dev_free = snd_es1968_dev_free,
- };
- struct es1968 *chip;
+ struct es1968 *chip = card->private_data;
int i, err;
- *chip_ret = NULL;
-
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 28 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
dev_err(card->dev,
"architecture does not support 28bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (! chip) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
/* Set Vars */
chip->type = chip_type;
spin_lock_init(&chip->reg_lock);
@@ -2702,20 +2668,17 @@ static int snd_es1968_create(struct snd_card *card,
chip->capture_streams = capt_streams;
err = pci_request_regions(pci, "ESS Maestro");
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
chip->io_port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_es1968_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_es1968_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_es1968_free;
/* Clear Maestro_map */
for (i = 0; i < 32; i++)
@@ -2749,21 +2712,13 @@ static int snd_es1968_create(struct snd_card *card,
snd_es1968_chip_init(chip);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_es1968_free(chip);
- return err;
- }
-
#ifdef CONFIG_SND_ES1968_RADIO
/* don't play with GPIOs on laptops */
if (chip->pci->subsystem_vendor != 0x125d)
- goto no_radio;
+ return 0;
err = v4l2_device_register(&pci->dev, &chip->v4l2_dev);
- if (err < 0) {
- snd_es1968_free(chip);
+ if (err < 0)
return err;
- }
chip->tea.v4l2_dev = &chip->v4l2_dev;
chip->tea.private_data = chip;
chip->tea.radio_nr = radio_nr;
@@ -2779,11 +2734,7 @@ static int snd_es1968_create(struct snd_card *card,
break;
}
}
-no_radio:
#endif
-
- *chip_ret = chip;
-
return 0;
}
@@ -2806,10 +2757,11 @@ static int snd_es1968_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
if (total_bufsize[dev] < 128)
total_bufsize[dev] = 128;
@@ -2821,13 +2773,9 @@ static int snd_es1968_probe(struct pci_dev *pci,
pcm_substreams_c[dev],
pci_id->driver_data,
use_pm[dev],
- radio_nr[dev],
- &chip);
- if (err < 0) {
- snd_card_free(card);
+ radio_nr[dev]);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
switch (chip->type) {
case TYPE_MAESTRO2E:
@@ -2845,16 +2793,12 @@ static int snd_es1968_probe(struct pci_dev *pci,
}
err = snd_es1968_pcm(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_es1968_mixer(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
if (enable_mpu[dev] == 2) {
/* check the deny list */
@@ -2897,25 +2841,17 @@ static int snd_es1968_probe(struct pci_dev *pci,
card->shortname, chip->io_port, chip->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_es1968_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver es1968_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_es1968_ids,
.probe = snd_es1968_probe,
- .remove = snd_es1968_remove,
.driver = {
.pm = ES1968_PM_OPS,
},
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index ed9dae87145b..9c22ff19e56d 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1028,22 +1028,6 @@ FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",CAPTURE,SWITCH), FM801_I2S_MODE,
FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), FM801_GEN_CTRL, 2, 1, 0),
};
-static void snd_fm801_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
-{
- struct fm801 *chip = bus->private_data;
- chip->ac97_bus = NULL;
-}
-
-static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97)
-{
- struct fm801 *chip = ac97->private_data;
- if (ac97->num == 0) {
- chip->ac97 = NULL;
- } else {
- chip->ac97_sec = NULL;
- }
-}
-
static int snd_fm801_mixer(struct fm801 *chip)
{
struct snd_ac97_template ac97;
@@ -1057,11 +1041,9 @@ static int snd_fm801_mixer(struct fm801 *chip)
err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus);
if (err < 0)
return err;
- chip->ac97_bus->private_free = snd_fm801_mixer_free_ac97_bus;
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
- ac97.private_free = snd_fm801_mixer_free_ac97;
err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
if (err < 0)
return err;
@@ -1177,55 +1159,35 @@ static void snd_fm801_chip_init(struct fm801 *chip)
FM801_IRQ_PLAYBACK | FM801_IRQ_CAPTURE | FM801_IRQ_MPU);
}
-static int snd_fm801_free(struct fm801 *chip)
+static void snd_fm801_free(struct snd_card *card)
{
+ struct fm801 *chip = card->private_data;
unsigned short cmdw;
- if (chip->irq < 0)
- goto __end_hw;
-
/* interrupt setup - mask everything */
cmdw = fm801_readw(chip, IRQ_MASK);
cmdw |= 0x00c3;
fm801_writew(chip, IRQ_MASK, cmdw);
- devm_free_irq(chip->dev, chip->irq, chip);
-
- __end_hw:
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
snd_tea575x_exit(&chip->tea);
v4l2_device_unregister(&chip->v4l2_dev);
}
#endif
- return 0;
-}
-
-static int snd_fm801_dev_free(struct snd_device *device)
-{
- struct fm801 *chip = device->device_data;
- return snd_fm801_free(chip);
}
static int snd_fm801_create(struct snd_card *card,
struct pci_dev *pci,
int tea575x_tuner,
- int radio_nr,
- struct fm801 **rchip)
+ int radio_nr)
{
- struct fm801 *chip;
+ struct fm801 *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_fm801_dev_free,
- };
- *rchip = NULL;
err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
spin_lock_init(&chip->reg_lock);
chip->card = card;
chip->dev = &pci->dev;
@@ -1253,7 +1215,6 @@ static int snd_fm801_create(struct snd_card *card,
if (devm_request_irq(&pci->dev, pci->irq, snd_fm801_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_fm801_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
@@ -1261,20 +1222,13 @@ static int snd_fm801_create(struct snd_card *card,
pci_set_master(pci);
}
+ card->private_free = snd_fm801_free;
snd_fm801_chip_init(chip);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_fm801_free(chip);
- return err;
- }
-
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
err = v4l2_device_register(&pci->dev, &chip->v4l2_dev);
- if (err < 0) {
- snd_fm801_free(chip);
+ if (err < 0)
return err;
- }
chip->tea.v4l2_dev = &chip->v4l2_dev;
chip->tea.radio_nr = radio_nr;
chip->tea.private_data = chip;
@@ -1284,7 +1238,6 @@ static int snd_fm801_create(struct snd_card *card,
(chip->tea575x_tuner & TUNER_TYPE_MASK) < 4) {
if (snd_tea575x_init(&chip->tea, THIS_MODULE)) {
dev_err(card->dev, "TEA575x radio not found\n");
- snd_fm801_free(chip);
return -ENODEV;
}
} else if ((chip->tea575x_tuner & TUNER_TYPE_MASK) == 0) {
@@ -1312,8 +1265,6 @@ static int snd_fm801_create(struct snd_card *card,
sizeof(chip->tea.card));
}
#endif
-
- *rchip = chip;
return 0;
}
@@ -1333,16 +1284,14 @@ static int snd_card_fm801_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
- err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip);
- if (err < 0) {
- snd_card_free(card);
+ chip = card->private_data;
+ err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev]);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
strcpy(card->driver, "FM801");
strcpy(card->shortname, "ForteMedia FM801-");
@@ -1354,53 +1303,36 @@ static int snd_card_fm801_probe(struct pci_dev *pci,
goto __fm801_tuner_only;
err = snd_fm801_pcm(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_fm801_mixer(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801,
chip->port + FM801_MPU401_DATA,
MPU401_INFO_INTEGRATED |
MPU401_INFO_IRQ_HOOK,
-1, &chip->rmidi);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_opl3_create(card, chip->port + FM801_OPL3_BANK0,
chip->port + FM801_OPL3_BANK1,
OPL3_HW_OPL3_FM801, 1, &opl3);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
__fm801_tuner_only:
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_card_fm801_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
#ifdef CONFIG_PM_SLEEP
static const unsigned char saved_regs[] = {
FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC,
@@ -1468,7 +1400,6 @@ static struct pci_driver fm801_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_fm801_ids,
.probe = snd_card_fm801_probe,
- .remove = snd_card_fm801_remove,
.driver = {
.pm = SND_FM801_PM_OPS,
},
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index c4360cdbc728..ab9d2746e804 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -157,6 +157,16 @@ config SND_HDA_CODEC_CIRRUS
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA=y && SND_HDA_CODEC_CIRRUS=m
+config SND_HDA_CODEC_CS8409
+ tristate "Build Cirrus Logic HDA bridge support"
+ select SND_HDA_GENERIC
+ help
+ Say Y or M here to include Cirrus Logic HDA bridge support in
+ snd-hda-intel driver, such as CS8409.
+
+comment "Set to Y if you want auto-loading the codec driver"
+ depends on SND_HDA=y && SND_HDA_CODEC_CS8409=m
+
config SND_HDA_CODEC_CONEXANT
tristate "Build Conexant HD-audio codec support"
select SND_HDA_GENERIC
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index b57432f00056..b8fa682ce66a 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -20,6 +20,7 @@ snd-hda-codec-analog-objs := patch_analog.o
snd-hda-codec-idt-objs := patch_sigmatel.o
snd-hda-codec-si3054-objs := patch_si3054.o
snd-hda-codec-cirrus-objs := patch_cirrus.o
+snd-hda-codec-cs8409-objs := patch_cs8409.o patch_cs8409-tables.o
snd-hda-codec-ca0110-objs := patch_ca0110.o
snd-hda-codec-ca0132-objs := patch_ca0132.o
snd-hda-codec-conexant-objs := patch_conexant.o
@@ -37,6 +38,7 @@ obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o
obj-$(CONFIG_SND_HDA_CODEC_CIRRUS) += snd-hda-codec-cirrus.o
+obj-$(CONFIG_SND_HDA_CODEC_CS8409) += snd-hda-codec-cs8409.o
obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 1a001ecf7f63..4a854475a0e6 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -971,6 +971,8 @@ EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);
* When a special model string "nofixup" is given, also no fixup is applied.
*
* The function tries to find the matching model name at first, if given.
+ * If the model string contains the SSID alias, try to look up with the given
+ * alias ID.
* If nothing matched, try to look up the PCI SSID.
* If still nothing matched, try to look up the codec SSID.
*/
@@ -982,65 +984,77 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
const struct snd_pci_quirk *q;
int id = HDA_FIXUP_ID_NOT_SET;
const char *name = NULL;
+ const char *type = NULL;
+ int vendor, device;
if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
return;
/* when model=nofixup is given, don't pick up any fixups */
if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
- codec->fixup_list = NULL;
- codec->fixup_name = NULL;
- codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
+ id = HDA_FIXUP_ID_NO_FIXUP;
+ fixlist = NULL;
codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n",
codec->core.chip_name);
- return;
+ goto found;
}
+ /* match with the model name string */
if (codec->modelname && models) {
while (models->name) {
if (!strcmp(codec->modelname, models->name)) {
- codec->fixup_id = models->id;
- codec->fixup_name = models->name;
- codec->fixup_list = fixlist;
+ id = models->id;
+ name = models->name;
codec_dbg(codec, "%s: picked fixup %s (model specified)\n",
codec->core.chip_name, codec->fixup_name);
- return;
+ goto found;
}
models++;
}
}
- if (quirk) {
- q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+
+ if (!quirk)
+ return;
+
+ /* match with the SSID alias given by the model string "XXXX:YYYY" */
+ if (codec->modelname &&
+ sscanf(codec->modelname, "%04x:%04x", &vendor, &device) == 2) {
+ q = snd_pci_quirk_lookup_id(vendor, device, quirk);
if (q) {
- id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- name = q->name;
- codec_dbg(codec, "%s: picked fixup %s (PCI SSID%s)\n",
- codec->core.chip_name, name, q->subdevice_mask ? "" : " - vendor generic");
-#endif
+ type = "alias SSID";
+ goto found_device;
}
}
- if (id < 0 && quirk) {
- for (q = quirk; q->subvendor || q->subdevice; q++) {
- unsigned int vendorid =
- q->subdevice | (q->subvendor << 16);
- unsigned int mask = 0xffff0000 | q->subdevice_mask;
- if ((codec->core.subsystem_id & mask) == (vendorid & mask)) {
- id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- name = q->name;
- codec_dbg(codec, "%s: picked fixup %s (codec SSID)\n",
- codec->core.chip_name, name);
-#endif
- break;
- }
- }
+
+ /* match with the PCI SSID */
+ q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+ if (q) {
+ type = "PCI SSID";
+ goto found_device;
}
- codec->fixup_id = id;
- if (id >= 0) {
- codec->fixup_list = fixlist;
- codec->fixup_name = name;
+ /* match with the codec SSID */
+ q = snd_pci_quirk_lookup_id(codec->core.subsystem_id >> 16,
+ codec->core.subsystem_id & 0xffff,
+ quirk);
+ if (q) {
+ type = "codec SSID";
+ goto found_device;
}
+
+ return; /* no matching */
+
+ found_device:
+ id = q->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ name = q->name;
+#endif
+ codec_dbg(codec, "%s: picked fixup %s for %s %04x:%04x\n",
+ codec->core.chip_name, name ? name : "",
+ type, q->subvendor, q->subdevice);
+ found:
+ codec->fixup_id = id;
+ codec->fixup_list = fixlist;
+ codec->fixup_name = name;
}
EXPORT_SYMBOL_GPL(snd_hda_pick_fixup);
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index e8dee24c309d..2523b23389e9 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -165,13 +165,7 @@ static int hda_codec_driver_remove(struct device *dev)
static void hda_codec_driver_shutdown(struct device *dev)
{
- struct hda_codec *codec = dev_to_hda_codec(dev);
-
- if (!pm_runtime_suspended(dev)) {
- if (codec->patch_ops.reboot_notify)
- codec->patch_ops.reboot_notify(codec);
- snd_hda_codec_display_power(codec, false);
- }
+ snd_hda_codec_shutdown(dev_to_hda_codec(dev));
}
int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 7a717e151156..a9ebefd60cf6 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2981,6 +2981,18 @@ const struct dev_pm_ops hda_codec_driver_pm = {
NULL)
};
+/* suspend the codec at shutdown; called from driver's shutdown callback */
+void snd_hda_codec_shutdown(struct hda_codec *codec)
+{
+ struct hda_pcm *cpcm;
+
+ list_for_each_entry(cpcm, &codec->pcm_list_head, list)
+ snd_pcm_suspend_all(cpcm->pcm);
+
+ pm_runtime_force_suspend(hda_codec_dev(codec));
+ pm_runtime_disable(hda_codec_dev(codec));
+}
+
/*
* add standard channel maps if not specified
*/
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index ca2f2ecd1488..7cd452831fd3 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -669,16 +669,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
return err;
}
-static int azx_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *area)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct azx *chip = apcm->chip;
- if (chip->ops->pcm_mmap_prepare)
- chip->ops->pcm_mmap_prepare(substream, area);
- return snd_pcm_lib_default_mmap(substream, area);
-}
-
static const struct snd_pcm_ops azx_pcm_ops = {
.open = azx_pcm_open,
.close = azx_pcm_close,
@@ -688,7 +678,6 @@ static const struct snd_pcm_ops azx_pcm_ops = {
.trigger = azx_pcm_trigger,
.pointer = azx_pcm_pointer,
.get_time_info = azx_get_time_info,
- .mmap = azx_pcm_mmap,
};
static void azx_pcm_free(struct snd_pcm *pcm)
@@ -753,7 +742,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
if (size > MAX_PREALLOC_SIZE)
size = MAX_PREALLOC_SIZE;
if (chip->uc_buffer)
- type = SNDRV_DMA_TYPE_DEV_UC_SG;
+ type = SNDRV_DMA_TYPE_DEV_WC_SG;
snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev,
size, MAX_PREALLOC_SIZE);
return 0;
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index 68f9668788ea..3062f87380b1 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -74,8 +74,6 @@ struct azx;
struct hda_controller_ops {
/* Disable msi if supported, PCI only */
int (*disable_msi_reset_irq)(struct azx *);
- void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream,
- struct vm_area_struct *area);
/* Check if current position is acceptable */
int (*position_check)(struct azx *chip, struct azx_dev *azx_dev);
/* enable/disable the link power */
@@ -141,7 +139,6 @@ struct azx {
unsigned int snoop:1;
unsigned int uc_buffer:1; /* non-cached pages for stream buffers */
unsigned int align_buffer_size:1;
- unsigned int region_requested:1;
unsigned int disabled:1; /* disabled by vga_switcheroo */
unsigned int pm_prepared:1;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 481d8f8d3396..3bf5e3410703 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -6004,24 +6004,6 @@ void snd_hda_gen_free(struct hda_codec *codec)
}
EXPORT_SYMBOL_GPL(snd_hda_gen_free);
-/**
- * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
- * @codec: the HDA codec
- *
- * This can be put as patch_ops reboot_notify function.
- */
-void snd_hda_gen_reboot_notify(struct hda_codec *codec)
-{
- /* Make the codec enter D3 to avoid spurious noises from the internal
- * speaker during (and after) reboot
- */
- snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- msleep(10);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
-
#ifdef CONFIG_PM
/**
* snd_hda_gen_check_power_status - check the loopback power save state
@@ -6049,7 +6031,6 @@ static const struct hda_codec_ops generic_patch_ops = {
.init = snd_hda_gen_init,
.free = snd_hda_gen_free,
.unsol_event = snd_hda_jack_unsol_event,
- .reboot_notify = snd_hda_gen_reboot_notify,
#ifdef CONFIG_PM
.check_power_status = snd_hda_gen_check_power_status,
#endif
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index d4dd1b8a2e7e..c43bd0f0338e 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -324,7 +324,6 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
struct auto_pin_cfg *cfg);
int snd_hda_gen_build_controls(struct hda_codec *codec);
int snd_hda_gen_build_pcms(struct hda_codec *codec);
-void snd_hda_gen_reboot_notify(struct hda_codec *codec);
/* standard jack event callbacks */
void snd_hda_gen_hp_automute(struct hda_codec *codec,
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 0062c18b646a..3aa432d814a2 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -883,11 +883,10 @@ static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev)
return azx_get_pos_posbuf(chip, azx_dev);
}
-static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
+static void azx_shutdown_chip(struct azx *chip)
{
azx_stop_chip(chip);
- if (!skip_link_reset)
- azx_enter_link_reset(chip);
+ azx_enter_link_reset(chip);
azx_clear_irq_pending(chip);
display_power(chip, false);
}
@@ -896,11 +895,6 @@ static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
static DEFINE_MUTEX(card_list_lock);
static LIST_HEAD(card_list);
-static void azx_shutdown_chip(struct azx *chip)
-{
- __azx_shutdown_chip(chip, false);
-}
-
static void azx_add_card_list(struct azx *chip)
{
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
@@ -1373,18 +1367,11 @@ static void azx_free(struct azx *chip)
if (bus->irq >= 0)
free_irq(bus->irq, (void*)chip);
- if (chip->msi)
- pci_disable_msi(chip->pci);
- iounmap(bus->remap_addr);
azx_free_stream_pages(chip);
azx_free_streams(chip);
snd_hdac_bus_exit(bus);
- if (chip->region_requested)
- pci_release_regions(chip->pci);
-
- pci_disable_device(chip->pci);
#ifdef CONFIG_SND_HDA_PATCH_LOADER
release_firmware(chip->fw);
#endif
@@ -1773,15 +1760,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
*rchip = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
hda = devm_kzalloc(&pci->dev, sizeof(*hda), GFP_KERNEL);
- if (!hda) {
- pci_disable_device(pci);
+ if (!hda)
return -ENOMEM;
- }
chip = &hda->chip;
mutex_init(&chip->open_mutex);
@@ -1817,14 +1802,12 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
chip->bdl_pos_adj = bdl_pos_adj[dev];
err = azx_bus_init(chip, model[dev]);
- if (err < 0) {
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
/* use the non-cached pages in non-snoop mode */
if (!azx_snoop(chip))
- azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC;
+ azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC;
if (chip->driver_type == AZX_DRIVER_NVIDIA) {
dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
@@ -1866,17 +1849,12 @@ static int azx_first_init(struct azx *chip)
}
#endif
- err = pci_request_regions(pci, "ICH HD audio");
+ err = pcim_iomap_regions(pci, 1 << 0, "ICH HD audio");
if (err < 0)
return err;
- chip->region_requested = 1;
bus->addr = pci_resource_start(pci, 0);
- bus->remap_addr = pci_ioremap_bar(pci, 0);
- if (bus->remap_addr == NULL) {
- dev_err(card->dev, "ioremap error\n");
- return -ENXIO;
- }
+ bus->remap_addr = pcim_iomap_table(pci)[0];
if (chip->driver_type == AZX_DRIVER_SKL)
snd_hdac_bus_parse_capabilities(bus);
@@ -2059,17 +2037,6 @@ static int disable_msi_reset_irq(struct azx *chip)
return 0;
}
-static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
- struct vm_area_struct *area)
-{
-#ifdef CONFIG_X86
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct azx *chip = apcm->chip;
- if (chip->uc_buffer)
- area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
-#endif
-}
-
/* Denylist for skipping the whole probe:
* some HD-audio PCI entries are exposed without any codecs, and such devices
* should be ignored from the beginning.
@@ -2083,7 +2050,6 @@ static const struct pci_device_id driver_denylist[] = {
static const struct hda_controller_ops pci_hda_ops = {
.disable_msi_reset_irq = disable_msi_reset_irq,
- .pcm_mmap_prepare = pcm_mmap_prepare,
.position_check = azx_position_check,
};
@@ -2391,7 +2357,7 @@ static void azx_shutdown(struct pci_dev *pci)
return;
chip = card->private_data;
if (chip && chip->running)
- __azx_shutdown_chip(chip, true);
+ azx_shutdown_chip(chip);
}
/* PCI IDs */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 8d2503e8dad8..ea8ab8b43337 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -615,6 +615,8 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state);
+void snd_hda_codec_shutdown(struct hda_codec *codec);
+
/*
* AMP control callbacks
*/
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2132b2acec4d..8afe6000f7da 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -72,7 +72,7 @@ static int create_beep_ctls(struct hda_codec *codec)
#define create_beep_ctls(codec) 0
#endif
-
+#ifdef CONFIG_PM
static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
hda_nid_t hp)
{
@@ -112,16 +112,10 @@ static void ad198x_power_eapd(struct hda_codec *codec)
}
}
-static void ad198x_shutup(struct hda_codec *codec)
+static int ad198x_suspend(struct hda_codec *codec)
{
snd_hda_shutup_pins(codec);
ad198x_power_eapd(codec);
-}
-
-#ifdef CONFIG_PM
-static int ad198x_suspend(struct hda_codec *codec)
-{
- ad198x_shutup(codec);
return 0;
}
#endif
@@ -168,7 +162,6 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = {
.check_power_status = snd_hda_gen_check_power_status,
.suspend = ad198x_suspend,
#endif
- .reboot_notify = ad198x_shutup,
};
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index b66e7bdbf483..208933792787 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -2270,7 +2270,7 @@ static int dspio_send_scp_message(struct hda_codec *codec,
unsigned int *bytes_returned)
{
struct ca0132_spec *spec = codec->spec;
- int status = -1;
+ int status;
unsigned int scp_send_size = 0;
unsigned int total_size;
bool waiting_for_resp = false;
@@ -9682,11 +9682,6 @@ static void dbpro_free(struct hda_codec *codec)
kfree(codec->spec);
}
-static void ca0132_reboot_notify(struct hda_codec *codec)
-{
- codec->patch_ops.free(codec);
-}
-
#ifdef CONFIG_PM
static int ca0132_suspend(struct hda_codec *codec)
{
@@ -9706,7 +9701,6 @@ static const struct hda_codec_ops ca0132_patch_ops = {
#ifdef CONFIG_PM
.suspend = ca0132_suspend,
#endif
- .reboot_notify = ca0132_reboot_notify,
};
static const struct hda_codec_ops dbpro_patch_ops = {
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 8629e84fef23..678fbcaf2a3b 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -9,7 +9,6 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/core.h>
-#include <linux/mutex.h>
#include <linux/pci.h>
#include <sound/tlv.h>
#include <sound/hda_codec.h>
@@ -21,9 +20,6 @@
/*
*/
-#define CS42L42_HP_CH (2U)
-#define CS42L42_HS_MIC_CH (1U)
-
struct cs_spec {
struct hda_gen_spec gen;
@@ -42,18 +38,6 @@ struct cs_spec {
/* for MBP SPDIF control */
int (*spdif_sw_put)(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
-
- unsigned int cs42l42_hp_jack_in:1;
- unsigned int cs42l42_mic_jack_in:1;
- unsigned int cs42l42_volume_init:1;
- char cs42l42_hp_volume[CS42L42_HP_CH];
- char cs42l42_hs_mic_volume[CS42L42_HS_MIC_CH];
-
- struct mutex cs8409_i2c_mux;
-
- /* verb exec op override */
- int (*exec_verb)(struct hdac_device *dev, unsigned int cmd,
- unsigned int flags, unsigned int *res);
};
/* available models with CS420x */
@@ -1239,1063 +1223,6 @@ static int patch_cs4213(struct hda_codec *codec)
return err;
}
-/* Cirrus Logic CS8409 HDA bridge with
- * companion codec CS42L42
- */
-#define CS8409_VENDOR_NID 0x47
-
-#define CS8409_CS42L42_HP_PIN_NID 0x24
-#define CS8409_CS42L42_SPK_PIN_NID 0x2c
-#define CS8409_CS42L42_AMIC_PIN_NID 0x34
-#define CS8409_CS42L42_DMIC_PIN_NID 0x44
-#define CS8409_CS42L42_DMIC_ADC_PIN_NID 0x22
-
-#define CS42L42_HSDET_AUTO_DONE 0x02
-#define CS42L42_HSTYPE_MASK 0x03
-
-#define CS42L42_JACK_INSERTED 0x0C
-#define CS42L42_JACK_REMOVED 0x00
-
-#define GPIO3_INT (1 << 3)
-#define GPIO4_INT (1 << 4)
-#define GPIO5_INT (1 << 5)
-
-#define CS42L42_I2C_ADDR (0x48 << 1)
-
-#define CIR_I2C_ADDR 0x0059
-#define CIR_I2C_DATA 0x005A
-#define CIR_I2C_CTRL 0x005B
-#define CIR_I2C_STATUS 0x005C
-#define CIR_I2C_QWRITE 0x005D
-#define CIR_I2C_QREAD 0x005E
-
-#define CS8409_CS42L42_HP_VOL_REAL_MIN (-63)
-#define CS8409_CS42L42_HP_VOL_REAL_MAX (0)
-#define CS8409_CS42L42_AMIC_VOL_REAL_MIN (-97)
-#define CS8409_CS42L42_AMIC_VOL_REAL_MAX (12)
-#define CS8409_CS42L42_REG_HS_VOLUME_CHA (0x2301)
-#define CS8409_CS42L42_REG_HS_VOLUME_CHB (0x2303)
-#define CS8409_CS42L42_REG_AMIC_VOLUME (0x1D03)
-
-struct cs8409_i2c_param {
- unsigned int addr;
- unsigned int reg;
-};
-
-struct cs8409_cir_param {
- unsigned int nid;
- unsigned int cir;
- unsigned int coeff;
-};
-
-enum {
- CS8409_BULLSEYE,
- CS8409_WARLOCK,
- CS8409_CYBORG,
- CS8409_FIXUPS,
-};
-
-static void cs8409_cs42l42_fixups(struct hda_codec *codec,
- const struct hda_fixup *fix, int action);
-static int cs8409_cs42l42_exec_verb(struct hdac_device *dev,
- unsigned int cmd, unsigned int flags, unsigned int *res);
-
-/* Dell Inspiron models with cs8409/cs42l42 */
-static const struct hda_model_fixup cs8409_models[] = {
- { .id = CS8409_BULLSEYE, .name = "bullseye" },
- { .id = CS8409_WARLOCK, .name = "warlock" },
- { .id = CS8409_CYBORG, .name = "cyborg" },
- {}
-};
-
-/* Dell Inspiron platforms
- * with cs8409 bridge and cs42l42 codec
- */
-static const struct snd_pci_quirk cs8409_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1028, 0x0A11, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A12, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A23, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A24, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A25, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A29, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A2A, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A2B, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0AB0, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB2, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB1, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB3, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB4, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB5, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AD9, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0ADA, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0ADB, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0ADC, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AF4, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AF5, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0A77, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A78, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A79, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A7A, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A7D, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A7E, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A7F, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A80, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0ADF, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AE0, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AE1, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AE2, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AE9, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEA, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEB, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEC, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AED, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEE, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEF, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AF0, "Cyborg", CS8409_CYBORG),
- {} /* terminator */
-};
-
-static const struct hda_verb cs8409_cs42l42_init_verbs[] = {
- { 0x01, AC_VERB_SET_GPIO_WAKE_MASK, 0x0018 }, /* WAKE from GPIO 3,4 */
- { 0x47, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing */
- { 0x47, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
- { 0x47, AC_VERB_SET_PROC_COEF, 0x0080 }, /* I2C mode */
- { 0x47, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
- { 0x47, AC_VERB_SET_PROC_COEF, 0x0200 }, /* 100kHz I2C_STO = 2 */
- {} /* terminator */
-};
-
-static const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
- { 0x24, 0x042120f0 }, /* ASP-1-TX */
- { 0x34, 0x04a12050 }, /* ASP-1-RX */
- { 0x2c, 0x901000f0 }, /* ASP-2-TX */
- { 0x44, 0x90a00090 }, /* DMIC-1 */
- {} /* terminator */
-};
-
-static const struct hda_fixup cs8409_fixups[] = {
- [CS8409_BULLSEYE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
- [CS8409_WARLOCK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
- [CS8409_CYBORG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
- [CS8409_FIXUPS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs8409_cs42l42_fixups,
- },
-};
-
-/* Vendor specific HW configuration for CS42L42 */
-static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
- { 0x1010, 0xB0 },
- { 0x1D01, 0x00 },
- { 0x1D02, 0x06 },
- { 0x1D03, 0x00 },
- { 0x1107, 0x01 },
- { 0x1009, 0x02 },
- { 0x1007, 0x03 },
- { 0x1201, 0x00 },
- { 0x1208, 0x13 },
- { 0x1205, 0xFF },
- { 0x1206, 0x00 },
- { 0x1207, 0x20 },
- { 0x1202, 0x0D },
- { 0x2A02, 0x02 },
- { 0x2A03, 0x00 },
- { 0x2A04, 0x00 },
- { 0x2A05, 0x02 },
- { 0x2A06, 0x00 },
- { 0x2A07, 0x20 },
- { 0x2A08, 0x02 },
- { 0x2A09, 0x00 },
- { 0x2A0A, 0x80 },
- { 0x2A0B, 0x02 },
- { 0x2A0C, 0x00 },
- { 0x2A0D, 0xA0 },
- { 0x2A01, 0x0C },
- { 0x2902, 0x01 },
- { 0x2903, 0x02 },
- { 0x2904, 0x00 },
- { 0x2905, 0x00 },
- { 0x2901, 0x01 },
- { 0x1101, 0x0A },
- { 0x1102, 0x84 },
- { 0x2301, 0x00 },
- { 0x2303, 0x00 },
- { 0x2302, 0x3f },
- { 0x2001, 0x03 },
- { 0x1B75, 0xB6 },
- { 0x1B73, 0xC2 },
- { 0x1129, 0x01 },
- { 0x1121, 0xF3 },
- { 0x1103, 0x20 },
- { 0x1105, 0x00 },
- { 0x1112, 0xC0 },
- { 0x1113, 0x80 },
- { 0x1C03, 0xC0 },
- { 0x1105, 0x00 },
- { 0x1112, 0xC0 },
- { 0x1101, 0x02 },
- {} /* Terminator */
-};
-
-/* Vendor specific hw configuration for CS8409 */
-static const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[] = {
- { 0x47, 0x00, 0xb008 }, /* +PLL1/2_EN, +I2C_EN */
- { 0x47, 0x01, 0x0002 }, /* ASP1/2_EN=0, ASP1_STP=1 */
- { 0x47, 0x02, 0x0a80 }, /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
- { 0x47, 0x19, 0x0800 }, /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
- { 0x47, 0x1a, 0x0820 }, /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
- { 0x47, 0x29, 0x0800 }, /* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
- { 0x47, 0x2a, 0x2800 }, /* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
- { 0x47, 0x39, 0x0800 }, /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
- { 0x47, 0x3a, 0x0800 }, /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
- { 0x47, 0x03, 0x8000 }, /* ASP1: LCHI = 00h */
- { 0x47, 0x04, 0x28ff }, /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
- { 0x47, 0x05, 0x0062 }, /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
- { 0x47, 0x06, 0x801f }, /* ASP2: LCHI=1Fh */
- { 0x47, 0x07, 0x283f }, /* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
- { 0x47, 0x08, 0x805c }, /* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
- { 0x47, 0x09, 0x0023 }, /* DMIC1_MO=10b, DMIC1/2_SR=1 */
- { 0x47, 0x0a, 0x0000 }, /* ASP1/2_BEEP=0 */
- { 0x47, 0x01, 0x0062 }, /* ASP1/2_EN=1, ASP1_STP=1 */
- { 0x47, 0x00, 0x9008 }, /* -PLL2_EN */
- { 0x47, 0x68, 0x0000 }, /* TX2.A: pre-scale att.=0 dB */
- { 0x47, 0x82, 0xfc03 }, /* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
- { 0x47, 0xc0, 0x9999 }, /* test mode on */
- { 0x47, 0xc5, 0x0000 }, /* GPIO hysteresis = 30 us */
- { 0x47, 0xc0, 0x0000 }, /* test mode off */
- {} /* Terminator */
-};
-
-static const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[] = {
- { 0x47, 0x65, 0x4000 }, /* EQ_SEL=1, EQ1/2_EN=0 */
- { 0x47, 0x64, 0x4000 }, /* +EQ_ACC */
- { 0x47, 0x65, 0x4010 }, /* +EQ2_EN */
- { 0x47, 0x63, 0x0647 }, /* EQ_DATA_HI=0x0647 */
- { 0x47, 0x64, 0xc0c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=0, EQ_DATA_LO=0x67 */
- { 0x47, 0x63, 0x0647 }, /* EQ_DATA_HI=0x0647 */
- { 0x47, 0x64, 0xc1c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=1, EQ_DATA_LO=0x67 */
- { 0x47, 0x63, 0xf370 }, /* EQ_DATA_HI=0xf370 */
- { 0x47, 0x64, 0xc271 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=2, EQ_DATA_LO=0x71 */
- { 0x47, 0x63, 0x1ef8 }, /* EQ_DATA_HI=0x1ef8 */
- { 0x47, 0x64, 0xc348 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=3, EQ_DATA_LO=0x48 */
- { 0x47, 0x63, 0xc110 }, /* EQ_DATA_HI=0xc110 */
- { 0x47, 0x64, 0xc45a }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=4, EQ_DATA_LO=0x5a */
- { 0x47, 0x63, 0x1f29 }, /* EQ_DATA_HI=0x1f29 */
- { 0x47, 0x64, 0xc574 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=5, EQ_DATA_LO=0x74 */
- { 0x47, 0x63, 0x1d7a }, /* EQ_DATA_HI=0x1d7a */
- { 0x47, 0x64, 0xc653 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=6, EQ_DATA_LO=0x53 */
- { 0x47, 0x63, 0xc38c }, /* EQ_DATA_HI=0xc38c */
- { 0x47, 0x64, 0xc714 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=7, EQ_DATA_LO=0x14 */
- { 0x47, 0x63, 0x1ca3 }, /* EQ_DATA_HI=0x1ca3 */
- { 0x47, 0x64, 0xc8c7 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=8, EQ_DATA_LO=0xc7 */
- { 0x47, 0x63, 0xc38c }, /* EQ_DATA_HI=0xc38c */
- { 0x47, 0x64, 0xc914 }, /* +EQ_WRT, +EQ_ACC, EQ_ADR=9, EQ_DATA_LO=0x14 */
- { 0x47, 0x64, 0x0000 }, /* -EQ_ACC, -EQ_WRT */
- {} /* Terminator */
-};
-
-/**
- * cs8409_enable_i2c_clock - Enable I2C clocks
- * @codec: the codec instance
- * @enable: Enable or disable I2C clocks
- *
- * Enable or Disable I2C clocks.
- */
-static void cs8409_enable_i2c_clock(struct hda_codec *codec, unsigned int enable)
-{
- unsigned int retval;
- unsigned int newval;
-
- retval = cs_vendor_coef_get(codec, 0x0);
- newval = (enable) ? (retval | 0x8) : (retval & 0xfffffff7);
- cs_vendor_coef_set(codec, 0x0, newval);
-}
-
-/**
- * cs8409_i2c_wait_complete - Wait for I2C transaction
- * @codec: the codec instance
- *
- * Wait for I2C transaction to complete.
- * Return -1 if transaction wait times out.
- */
-static int cs8409_i2c_wait_complete(struct hda_codec *codec)
-{
- int repeat = 5;
- unsigned int retval;
-
- do {
- retval = cs_vendor_coef_get(codec, CIR_I2C_STATUS);
- if ((retval & 0x18) != 0x18) {
- usleep_range(2000, 4000);
- --repeat;
- } else
- return 0;
-
- } while (repeat);
-
- return -1;
-}
-
-/**
- * cs8409_i2c_read - CS8409 I2C Read.
- * @codec: the codec instance
- * @i2c_address: I2C Address
- * @i2c_reg: Register to read
- * @paged: Is a paged transaction
- *
- * CS8409 I2C Read.
- * Returns negative on error, otherwise returns read value in bits 0-7.
- */
-static int cs8409_i2c_read(struct hda_codec *codec,
- unsigned int i2c_address,
- unsigned int i2c_reg,
- unsigned int paged)
-{
- unsigned int i2c_reg_data;
- unsigned int read_data;
-
- cs8409_enable_i2c_clock(codec, 1);
- cs_vendor_coef_set(codec, CIR_I2C_ADDR, i2c_address);
-
- if (paged) {
- cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg >> 8);
- if (cs8409_i2c_wait_complete(codec) < 0) {
- codec_err(codec,
- "%s() Paged Transaction Failed 0x%02x : 0x%04x\n",
- __func__, i2c_address, i2c_reg);
- return -EIO;
- }
- }
-
- i2c_reg_data = (i2c_reg << 8) & 0x0ffff;
- cs_vendor_coef_set(codec, CIR_I2C_QREAD, i2c_reg_data);
- if (cs8409_i2c_wait_complete(codec) < 0) {
- codec_err(codec, "%s() Transaction Failed 0x%02x : 0x%04x\n",
- __func__, i2c_address, i2c_reg);
- return -EIO;
- }
-
- /* Register in bits 15-8 and the data in 7-0 */
- read_data = cs_vendor_coef_get(codec, CIR_I2C_QREAD);
-
- cs8409_enable_i2c_clock(codec, 0);
-
- return read_data & 0x0ff;
-}
-
-/**
- * cs8409_i2c_write - CS8409 I2C Write.
- * @codec: the codec instance
- * @i2c_address: I2C Address
- * @i2c_reg: Register to write to
- * @i2c_data: Data to write
- * @paged: Is a paged transaction
- *
- * CS8409 I2C Write.
- * Returns negative on error, otherwise returns 0.
- */
-static int cs8409_i2c_write(struct hda_codec *codec,
- unsigned int i2c_address, unsigned int i2c_reg,
- unsigned int i2c_data,
- unsigned int paged)
-{
- unsigned int i2c_reg_data;
-
- cs8409_enable_i2c_clock(codec, 1);
- cs_vendor_coef_set(codec, CIR_I2C_ADDR, i2c_address);
-
- if (paged) {
- cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg >> 8);
- if (cs8409_i2c_wait_complete(codec) < 0) {
- codec_err(codec,
- "%s() Paged Transaction Failed 0x%02x : 0x%04x\n",
- __func__, i2c_address, i2c_reg);
- return -EIO;
- }
- }
-
- i2c_reg_data = ((i2c_reg << 8) & 0x0ff00) | (i2c_data & 0x0ff);
- cs_vendor_coef_set(codec, CIR_I2C_QWRITE, i2c_reg_data);
-
- if (cs8409_i2c_wait_complete(codec) < 0) {
- codec_err(codec, "%s() Transaction Failed 0x%02x : 0x%04x\n",
- __func__, i2c_address, i2c_reg);
- return -EIO;
- }
-
- cs8409_enable_i2c_clock(codec, 0);
-
- return 0;
-}
-
-static int cs8409_cs42l42_volume_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- u16 nid = get_amp_nid(kcontrol);
- u8 chs = get_amp_channels(kcontrol);
-
- codec_dbg(codec, "%s() nid: %d\n", __func__, nid);
- switch (nid) {
- case CS8409_CS42L42_HP_PIN_NID:
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = chs == 3 ? 2 : 1;
- uinfo->value.integer.min = CS8409_CS42L42_HP_VOL_REAL_MIN;
- uinfo->value.integer.max = CS8409_CS42L42_HP_VOL_REAL_MAX;
- break;
- case CS8409_CS42L42_AMIC_PIN_NID:
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = chs == 3 ? 2 : 1;
- uinfo->value.integer.min = CS8409_CS42L42_AMIC_VOL_REAL_MIN;
- uinfo->value.integer.max = CS8409_CS42L42_AMIC_VOL_REAL_MAX;
- break;
- default:
- break;
- }
- return 0;
-}
-
-static void cs8409_cs42l42_update_volume(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
- int data;
-
- mutex_lock(&spec->cs8409_i2c_mux);
- data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_HS_VOLUME_CHA, 1);
- if (data >= 0)
- spec->cs42l42_hp_volume[0] = -data;
- else
- spec->cs42l42_hp_volume[0] = CS8409_CS42L42_HP_VOL_REAL_MIN;
- data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_HS_VOLUME_CHB, 1);
- if (data >= 0)
- spec->cs42l42_hp_volume[1] = -data;
- else
- spec->cs42l42_hp_volume[1] = CS8409_CS42L42_HP_VOL_REAL_MIN;
- data = cs8409_i2c_read(codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_AMIC_VOLUME, 1);
- if (data >= 0)
- spec->cs42l42_hs_mic_volume[0] = -data;
- else
- spec->cs42l42_hs_mic_volume[0] = CS8409_CS42L42_AMIC_VOL_REAL_MIN;
- mutex_unlock(&spec->cs8409_i2c_mux);
- spec->cs42l42_volume_init = 1;
-}
-
-static int cs8409_cs42l42_volume_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct cs_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int chs = get_amp_channels(kcontrol);
- long *valp = ucontrol->value.integer.value;
-
- if (!spec->cs42l42_volume_init) {
- snd_hda_power_up(codec);
- cs8409_cs42l42_update_volume(codec);
- snd_hda_power_down(codec);
- }
- switch (nid) {
- case CS8409_CS42L42_HP_PIN_NID:
- if (chs & BIT(0))
- *valp++ = spec->cs42l42_hp_volume[0];
- if (chs & BIT(1))
- *valp++ = spec->cs42l42_hp_volume[1];
- break;
- case CS8409_CS42L42_AMIC_PIN_NID:
- if (chs & BIT(0))
- *valp++ = spec->cs42l42_hs_mic_volume[0];
- break;
- default:
- break;
- }
- return 0;
-}
-
-static int cs8409_cs42l42_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct cs_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int chs = get_amp_channels(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change = 0;
- char vol;
-
- snd_hda_power_up(codec);
- switch (nid) {
- case CS8409_CS42L42_HP_PIN_NID:
- mutex_lock(&spec->cs8409_i2c_mux);
- if (chs & BIT(0)) {
- vol = -(*valp);
- change = cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_HS_VOLUME_CHA, vol, 1);
- valp++;
- }
- if (chs & BIT(1)) {
- vol = -(*valp);
- change |= cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_HS_VOLUME_CHB, vol, 1);
- }
- mutex_unlock(&spec->cs8409_i2c_mux);
- break;
- case CS8409_CS42L42_AMIC_PIN_NID:
- mutex_lock(&spec->cs8409_i2c_mux);
- if (chs & BIT(0)) {
- change = cs8409_i2c_write(
- codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_AMIC_VOLUME, (char)*valp, 1);
- valp++;
- }
- mutex_unlock(&spec->cs8409_i2c_mux);
- break;
- default:
- break;
- }
- cs8409_cs42l42_update_volume(codec);
- snd_hda_power_down(codec);
- return change;
-}
-
-static const DECLARE_TLV_DB_SCALE(
- cs8409_cs42l42_hp_db_scale,
- CS8409_CS42L42_HP_VOL_REAL_MIN * 100, 100, 1);
-
-static const DECLARE_TLV_DB_SCALE(
- cs8409_cs42l42_amic_db_scale,
- CS8409_CS42L42_AMIC_VOL_REAL_MIN * 100, 100, 1);
-
-static const struct snd_kcontrol_new cs8409_cs42l42_hp_volume_mixer = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .index = 0,
- .name = "Headphone Playback Volume",
- .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE
- | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .info = cs8409_cs42l42_volume_info,
- .get = cs8409_cs42l42_volume_get,
- .put = cs8409_cs42l42_volume_put,
- .tlv = { .p = cs8409_cs42l42_hp_db_scale },
- .private_value = HDA_COMPOSE_AMP_VAL(
- CS8409_CS42L42_HP_PIN_NID, 3, 0, HDA_OUTPUT)
- | HDA_AMP_VAL_MIN_MUTE
-};
-
-static const struct snd_kcontrol_new cs8409_cs42l42_amic_volume_mixer = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .index = 0,
- .name = "Mic Capture Volume",
- .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE
- | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .info = cs8409_cs42l42_volume_info,
- .get = cs8409_cs42l42_volume_get,
- .put = cs8409_cs42l42_volume_put,
- .tlv = { .p = cs8409_cs42l42_amic_db_scale },
- .private_value = HDA_COMPOSE_AMP_VAL(
- CS8409_CS42L42_AMIC_PIN_NID, 1, 0, HDA_INPUT)
- | HDA_AMP_VAL_MIN_MUTE
-};
-
-/* Assert/release RTS# line to CS42L42 */
-static void cs8409_cs42l42_reset(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
-
- /* Assert RTS# line */
- snd_hda_codec_write(codec,
- codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, 0);
- /* wait ~10ms */
- usleep_range(10000, 15000);
- /* Release RTS# line */
- snd_hda_codec_write(codec,
- codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, GPIO5_INT);
- /* wait ~10ms */
- usleep_range(10000, 15000);
-
- mutex_lock(&spec->cs8409_i2c_mux);
-
- /* Clear interrupts, by reading interrupt status registers */
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1309, 1);
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130A, 1);
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130F, 1);
-
- mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-/* Configure CS42L42 slave codec for jack autodetect */
-static void cs8409_cs42l42_enable_jack_detect(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
-
- mutex_lock(&spec->cs8409_i2c_mux);
-
- /* Set TIP_SENSE_EN for analog front-end of tip sense. */
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x0020, 1);
- /* Clear WAKE# */
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x0001, 1);
- /* Wait ~2.5ms */
- usleep_range(2500, 3000);
- /* Set mode WAKE# output follows the combination logic directly */
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x0020, 1);
- /* Clear interrupts status */
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1);
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b7b, 1);
- /* Enable interrupt */
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0x03, 1);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b79, 0x00, 1);
-
- mutex_unlock(&spec->cs8409_i2c_mux);
-}
-
-/* Enable and run CS42L42 slave codec jack auto detect */
-static void cs8409_cs42l42_run_jack_detect(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
-
- mutex_lock(&spec->cs8409_i2c_mux);
-
- /* Clear interrupts */
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b77, 1);
-
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1102, 0x87, 1);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1f06, 0x86, 1);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b74, 0x07, 1);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0x01, 1);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0x80, 1);
- /* Wait ~110ms*/
- usleep_range(110000, 200000);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x111f, 0x77, 1);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0xc0, 1);
- /* Wait ~10ms */
- usleep_range(10000, 25000);
-
- mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-static void cs8409_cs42l42_reg_setup(struct hda_codec *codec)
-{
- const struct cs8409_i2c_param *seq = cs42l42_init_reg_seq;
- struct cs_spec *spec = codec->spec;
-
- mutex_lock(&spec->cs8409_i2c_mux);
-
- for (; seq->addr; seq++)
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, seq->addr, seq->reg, 1);
-
- mutex_unlock(&spec->cs8409_i2c_mux);
-
-}
-
-/*
- * In the case of CS8409 we do not have unsolicited events from NID's 0x24
- * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will
- * generate interrupt via gpio 4 to notify jack events. We have to overwrite
- * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
- * and then notify status via generic snd_hda_jack_unsol_event() call.
- */
-static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- struct cs_spec *spec = codec->spec;
- int status_changed = 0;
- int reg_cdc_status;
- int reg_hs_status;
- int reg_ts_status;
- int type;
- struct hda_jack_tbl *jk;
-
- /* jack_unsol_event() will be called every time gpio line changing state.
- * In this case gpio4 line goes up as a result of reading interrupt status
- * registers in previous cs8409_jack_unsol_event() call.
- * We don't need to handle this event, ignoring...
- */
- if ((res & (1 << 4)))
- return;
-
- mutex_lock(&spec->cs8409_i2c_mux);
-
- /* Read jack detect status registers */
- reg_cdc_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1);
- reg_hs_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1124, 1);
- reg_ts_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1);
-
- /* Clear interrupts, by reading interrupt status registers */
- cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b7b, 1);
-
- mutex_unlock(&spec->cs8409_i2c_mux);
-
- /* If status values are < 0, read error has occurred. */
- if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0)
- return;
-
- /* HSDET_AUTO_DONE */
- if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) {
-
- type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1);
- /* CS42L42 reports optical jack as type 4
- * We don't handle optical jack
- */
- if (type != 4) {
- if (!spec->cs42l42_hp_jack_in) {
- status_changed = 1;
- spec->cs42l42_hp_jack_in = 1;
- }
- /* type = 3 has no mic */
- if ((!spec->cs42l42_mic_jack_in) && (type != 3)) {
- status_changed = 1;
- spec->cs42l42_mic_jack_in = 1;
- }
- } else {
- if (spec->cs42l42_hp_jack_in || spec->cs42l42_mic_jack_in) {
- status_changed = 1;
- spec->cs42l42_hp_jack_in = 0;
- spec->cs42l42_mic_jack_in = 0;
- }
- }
-
- } else {
- /* TIP_SENSE INSERT/REMOVE */
- switch (reg_ts_status) {
- case CS42L42_JACK_INSERTED:
- cs8409_cs42l42_run_jack_detect(codec);
- break;
-
- case CS42L42_JACK_REMOVED:
- if (spec->cs42l42_hp_jack_in || spec->cs42l42_mic_jack_in) {
- status_changed = 1;
- spec->cs42l42_hp_jack_in = 0;
- spec->cs42l42_mic_jack_in = 0;
- }
- break;
-
- default:
- /* jack in transition */
- status_changed = 0;
- break;
- }
- }
-
- if (status_changed) {
-
- snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID,
- spec->cs42l42_hp_jack_in ? 0 : PIN_OUT);
-
- /* Report jack*/
- jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0);
- if (jk) {
- snd_hda_jack_unsol_event(codec,
- (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & AC_UNSOL_RES_TAG);
- }
- /* Report jack*/
- jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0);
- if (jk) {
- snd_hda_jack_unsol_event(codec,
- (jk->tag << AC_UNSOL_RES_TAG_SHIFT) & AC_UNSOL_RES_TAG);
- }
- }
-}
-
-#ifdef CONFIG_PM
-/* Manage PDREF, when transition to D3hot */
-static int cs8409_suspend(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
-
- mutex_lock(&spec->cs8409_i2c_mux);
- /* Power down CS42L42 ASP/EQ/MIX/HP */
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1101, 0xfe, 1);
- mutex_unlock(&spec->cs8409_i2c_mux);
- /* Assert CS42L42 RTS# line */
- snd_hda_codec_write(codec,
- codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, 0);
-
- snd_hda_shutup_pins(codec);
-
- return 0;
-}
-#endif
-
-/* Enable/Disable Unsolicited Response for gpio(s) 3,4 */
-static void cs8409_enable_ur(struct hda_codec *codec, int flag)
-{
- /* GPIO4 INT# and GPIO3 WAKE# */
- snd_hda_codec_write(codec, codec->core.afg,
- 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK,
- flag ? (GPIO3_INT | GPIO4_INT) : 0);
-
- snd_hda_codec_write(codec, codec->core.afg,
- 0, AC_VERB_SET_UNSOLICITED_ENABLE,
- flag ? AC_UNSOL_ENABLED : 0);
-
-}
-
-/* Vendor specific HW configuration
- * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
- */
-static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
-{
- const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg;
- const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn;
- struct cs_spec *spec = codec->spec;
-
- if (spec->gpio_mask) {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
- spec->gpio_mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
- spec->gpio_dir);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_data);
- }
-
- for (; seq->nid; seq++)
- cs_vendor_coef_set(codec, seq->cir, seq->coeff);
-
- if (codec->fixup_id == CS8409_BULLSEYE)
- for (; seq_bullseye->nid; seq_bullseye++)
- cs_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff);
-
- /* Disable Unsolicited Response during boot */
- cs8409_enable_ur(codec, 0);
-
- /* Reset CS42L42 */
- cs8409_cs42l42_reset(codec);
-
- /* Initialise CS42L42 companion codec */
- cs8409_cs42l42_reg_setup(codec);
-
- if (codec->fixup_id == CS8409_WARLOCK ||
- codec->fixup_id == CS8409_CYBORG) {
- /* FULL_SCALE_VOL = 0 for Warlock / Cyborg */
- mutex_lock(&spec->cs8409_i2c_mux);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x2001, 0x01, 1);
- mutex_unlock(&spec->cs8409_i2c_mux);
- /* DMIC1_MO=00b, DMIC1/2_SR=1 */
- cs_vendor_coef_set(codec, 0x09, 0x0003);
- }
-
- /* Restore Volumes after Resume */
- if (spec->cs42l42_volume_init) {
- mutex_lock(&spec->cs8409_i2c_mux);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_HS_VOLUME_CHA,
- -spec->cs42l42_hp_volume[0],
- 1);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_HS_VOLUME_CHB,
- -spec->cs42l42_hp_volume[1],
- 1);
- cs8409_i2c_write(codec, CS42L42_I2C_ADDR,
- CS8409_CS42L42_REG_AMIC_VOLUME,
- spec->cs42l42_hs_mic_volume[0],
- 1);
- mutex_unlock(&spec->cs8409_i2c_mux);
- }
-
- cs8409_cs42l42_update_volume(codec);
-
- cs8409_cs42l42_enable_jack_detect(codec);
-
- /* Enable Unsolicited Response */
- cs8409_enable_ur(codec, 1);
-}
-
-static int cs8409_cs42l42_init(struct hda_codec *codec)
-{
- int ret = snd_hda_gen_init(codec);
-
- if (!ret)
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
-
- return ret;
-}
-
-static const struct hda_codec_ops cs8409_cs42l42_patch_ops = {
- .build_controls = cs_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = cs8409_cs42l42_init,
- .free = cs_free,
- .unsol_event = cs8409_jack_unsol_event,
-#ifdef CONFIG_PM
- .suspend = cs8409_suspend,
-#endif
-};
-
-static void cs8409_cs42l42_fixups(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct cs_spec *spec = codec->spec;
- int caps;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs);
- /* verb exec op override */
- spec->exec_verb = codec->core.exec_verb;
- codec->core.exec_verb = cs8409_cs42l42_exec_verb;
-
- mutex_init(&spec->cs8409_i2c_mux);
-
- codec->patch_ops = cs8409_cs42l42_patch_ops;
-
- spec->gen.suppress_auto_mute = 1;
- spec->gen.no_primary_hp = 1;
- spec->gen.suppress_vmaster = 1;
-
- /* GPIO 5 out, 3,4 in */
- spec->gpio_dir = GPIO5_INT;
- spec->gpio_data = 0;
- spec->gpio_mask = 0x03f;
-
- spec->cs42l42_hp_jack_in = 0;
- spec->cs42l42_mic_jack_in = 0;
-
- /* Basic initial sequence for specific hw configuration */
- snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);
-
- /* CS8409 is simple HDA bridge and intended to be used with a remote
- * companion codec. Most of input/output PIN(s) have only basic
- * capabilities. NID(s) 0x24 and 0x34 have only OUTC and INC
- * capabilities and no presence detect capable (PDC) and call to
- * snd_hda_gen_build_controls() will mark them as non detectable
- * phantom jacks. However, in this configuration companion codec
- * CS42L42 is connected to these pins and it has jack detect
- * capabilities. We have to override pin capabilities,
- * otherwise they will not be created as input devices.
- */
- caps = snd_hdac_read_parm(&codec->core, CS8409_CS42L42_HP_PIN_NID,
- AC_PAR_PIN_CAP);
- if (caps >= 0)
- snd_hdac_override_parm(&codec->core,
- CS8409_CS42L42_HP_PIN_NID, AC_PAR_PIN_CAP,
- (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
-
- caps = snd_hdac_read_parm(&codec->core, CS8409_CS42L42_AMIC_PIN_NID,
- AC_PAR_PIN_CAP);
- if (caps >= 0)
- snd_hdac_override_parm(&codec->core,
- CS8409_CS42L42_AMIC_PIN_NID, AC_PAR_PIN_CAP,
- (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
-
- snd_hda_override_wcaps(codec, CS8409_CS42L42_HP_PIN_NID,
- (get_wcaps(codec, CS8409_CS42L42_HP_PIN_NID) | AC_WCAP_UNSOL_CAP));
-
- snd_hda_override_wcaps(codec, CS8409_CS42L42_AMIC_PIN_NID,
- (get_wcaps(codec, CS8409_CS42L42_AMIC_PIN_NID) | AC_WCAP_UNSOL_CAP));
- break;
- case HDA_FIXUP_ACT_PROBE:
-
- /* Set initial DMIC volume to -26 dB */
- snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
- HDA_INPUT, 0, 0xff, 0x19);
- snd_hda_gen_add_kctl(&spec->gen,
- NULL, &cs8409_cs42l42_hp_volume_mixer);
- snd_hda_gen_add_kctl(&spec->gen,
- NULL, &cs8409_cs42l42_amic_volume_mixer);
- cs8409_cs42l42_hw_init(codec);
- snd_hda_codec_set_name(codec, "CS8409/CS42L42");
- break;
- case HDA_FIXUP_ACT_INIT:
- cs8409_cs42l42_hw_init(codec);
- fallthrough;
- case HDA_FIXUP_ACT_BUILD:
- /* Run jack auto detect first time on boot
- * after controls have been added, to check if jack has
- * been already plugged in.
- * Run immediately after init.
- */
- cs8409_cs42l42_run_jack_detect(codec);
- usleep_range(100000, 150000);
- break;
- default:
- break;
- }
-}
-
-static int cs8409_cs42l42_exec_verb(struct hdac_device *dev,
- unsigned int cmd, unsigned int flags, unsigned int *res)
-{
- struct hda_codec *codec = container_of(dev, struct hda_codec, core);
- struct cs_spec *spec = codec->spec;
-
- unsigned int nid = ((cmd >> 20) & 0x07f);
- unsigned int verb = ((cmd >> 8) & 0x0fff);
-
- /* CS8409 pins have no AC_PINSENSE_PRESENCE
- * capabilities. We have to intercept 2 calls for pins 0x24 and 0x34
- * and return correct pin sense values for read_pin_sense() call from
- * hda_jack based on CS42L42 jack detect status.
- */
- switch (nid) {
- case CS8409_CS42L42_HP_PIN_NID:
- if (verb == AC_VERB_GET_PIN_SENSE) {
- *res = (spec->cs42l42_hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
- return 0;
- }
- break;
-
- case CS8409_CS42L42_AMIC_PIN_NID:
- if (verb == AC_VERB_GET_PIN_SENSE) {
- *res = (spec->cs42l42_mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
- return 0;
- }
- break;
-
- default:
- break;
- }
-
- return spec->exec_verb(dev, cmd, flags, res);
-}
-
-static int patch_cs8409(struct hda_codec *codec)
-{
- int err;
-
- if (!cs_alloc_spec(codec, CS8409_VENDOR_NID))
- return -ENOMEM;
-
- snd_hda_pick_fixup(codec,
- cs8409_models, cs8409_fixup_tbl, cs8409_fixups);
-
- codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n",
- codec->fixup_id,
- codec->bus->pci->subsystem_vendor,
- codec->bus->pci->subsystem_device);
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = cs_parse_auto_config(codec);
- if (err < 0) {
- cs_free(codec);
- return err;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
- return 0;
-}
-
/*
* patch entries
*/
@@ -2305,7 +1232,6 @@ static const struct hda_device_id snd_hda_id_cirrus[] = {
HDA_CODEC_ENTRY(0x10134208, "CS4208", patch_cs4208),
HDA_CODEC_ENTRY(0x10134210, "CS4210", patch_cs4210),
HDA_CODEC_ENTRY(0x10134213, "CS4213", patch_cs4213),
- HDA_CODEC_ENTRY(0x10138409, "CS8409", patch_cs8409),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cirrus);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index d111258c6f45..0515137a75b0 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -177,30 +177,37 @@ static int cx_auto_init(struct hda_codec *codec)
return 0;
}
-static void cx_auto_reboot_notify(struct hda_codec *codec)
+static void cx_auto_shutdown(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
/* Turn the problematic codec into D3 to avoid spurious noises
from the internal speaker during (and after) reboot */
cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
- snd_hda_gen_reboot_notify(codec);
}
static void cx_auto_free(struct hda_codec *codec)
{
- cx_auto_reboot_notify(codec);
+ cx_auto_shutdown(codec);
snd_hda_gen_free(codec);
}
+#ifdef CONFIG_PM
+static int cx_auto_suspend(struct hda_codec *codec)
+{
+ cx_auto_shutdown(codec);
+ return 0;
+}
+#endif
+
static const struct hda_codec_ops cx_auto_patch_ops = {
.build_controls = snd_hda_gen_build_controls,
.build_pcms = snd_hda_gen_build_pcms,
.init = cx_auto_init,
- .reboot_notify = cx_auto_reboot_notify,
.free = cx_auto_free,
.unsol_event = snd_hda_jack_unsol_event,
#ifdef CONFIG_PM
+ .suspend = cx_auto_suspend,
.check_power_status = snd_hda_gen_check_power_status,
#endif
};
diff --git a/sound/pci/hda/patch_cs8409-tables.c b/sound/pci/hda/patch_cs8409-tables.c
new file mode 100644
index 000000000000..0fb0a428428b
--- /dev/null
+++ b/sound/pci/hda/patch_cs8409-tables.c
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * patch_cs8409-tables.c -- HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ * Cirrus Logic International Semiconductor Ltd.
+ *
+ * Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+ */
+
+#include "patch_cs8409.h"
+
+/******************************************************************************
+ * CS42L42 Specific Data
+ *
+ ******************************************************************************/
+
+static const DECLARE_TLV_DB_SCALE(cs42l42_dac_db_scale, CS42L42_HP_VOL_REAL_MIN * 100, 100, 1);
+
+static const DECLARE_TLV_DB_SCALE(cs42l42_adc_db_scale, CS42L42_AMIC_VOL_REAL_MIN * 100, 100, 1);
+
+const struct snd_kcontrol_new cs42l42_dac_volume_mixer = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .index = 0,
+ .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+ .info = cs42l42_volume_info,
+ .get = cs42l42_volume_get,
+ .put = cs42l42_volume_put,
+ .tlv = { .p = cs42l42_dac_db_scale },
+ .private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_TRANSMITTER_A, 3, CS8409_CODEC0,
+ HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE
+};
+
+const struct snd_kcontrol_new cs42l42_adc_volume_mixer = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .index = 0,
+ .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+ .info = cs42l42_volume_info,
+ .get = cs42l42_volume_get,
+ .put = cs42l42_volume_put,
+ .tlv = { .p = cs42l42_adc_db_scale },
+ .private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_RECEIVER_A, 1, CS8409_CODEC0,
+ HDA_INPUT, CS42L42_VOL_ADC) | HDA_AMP_VAL_MIN_MUTE
+};
+
+const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback = {
+ .rates = SNDRV_PCM_RATE_48000, /* fixed rate */
+};
+
+const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture = {
+ .rates = SNDRV_PCM_RATE_48000, /* fixed rate */
+};
+
+/******************************************************************************
+ * BULLSEYE / WARLOCK / CYBORG Specific Arrays
+ * CS8409/CS42L42
+ ******************************************************************************/
+
+const struct hda_verb cs8409_cs42l42_init_verbs[] = {
+ { CS8409_PIN_AFG, AC_VERB_SET_GPIO_WAKE_MASK, 0x0018 }, /* WAKE from GPIO 3,4 */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0080 }, /* I2C mode */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0200 }, /* 100kHz I2C_STO = 2 */
+ {} /* terminator */
+};
+
+const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
+ { CS8409_PIN_ASP1_TRANSMITTER_A, 0x042120f0 }, /* ASP-1-TX */
+ { CS8409_PIN_ASP1_RECEIVER_A, 0x04a12050 }, /* ASP-1-RX */
+ { CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 }, /* ASP-2-TX */
+ { CS8409_PIN_DMIC1_IN, 0x90a00090 }, /* DMIC-1 */
+ {} /* terminator */
+};
+
+/* Vendor specific HW configuration for CS42L42 */
+static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
+ { 0x1010, 0xB0 },
+ { 0x1D01, 0x00 },
+ { 0x1D02, 0x06 },
+ { 0x1D03, 0x9F },
+ { 0x1107, 0x01 },
+ { 0x1009, 0x02 },
+ { 0x1007, 0x03 },
+ { 0x1201, 0x00 },
+ { 0x1208, 0x13 },
+ { 0x1205, 0xFF },
+ { 0x1206, 0x00 },
+ { 0x1207, 0x20 },
+ { 0x1202, 0x0D },
+ { 0x2A02, 0x02 },
+ { 0x2A03, 0x00 },
+ { 0x2A04, 0x00 },
+ { 0x2A05, 0x02 },
+ { 0x2A06, 0x00 },
+ { 0x2A07, 0x20 },
+ { 0x2A08, 0x02 },
+ { 0x2A09, 0x00 },
+ { 0x2A0A, 0x80 },
+ { 0x2A0B, 0x02 },
+ { 0x2A0C, 0x00 },
+ { 0x2A0D, 0xA0 },
+ { 0x2A01, 0x0C },
+ { 0x2902, 0x01 },
+ { 0x2903, 0x02 },
+ { 0x2904, 0x00 },
+ { 0x2905, 0x00 },
+ { 0x2901, 0x01 },
+ { 0x1101, 0x0A },
+ { 0x1102, 0x84 },
+ { 0x2301, 0x3F },
+ { 0x2303, 0x3F },
+ { 0x2302, 0x3f },
+ { 0x2001, 0x03 },
+ { 0x1B75, 0xB6 },
+ { 0x1B73, 0xC2 },
+ { 0x1129, 0x01 },
+ { 0x1121, 0xF3 },
+ { 0x1103, 0x20 },
+ { 0x1105, 0x00 },
+ { 0x1112, 0x00 },
+ { 0x1113, 0x80 },
+ { 0x1C03, 0xC0 },
+ { 0x1101, 0x02 },
+ { 0x1316, 0xff },
+ { 0x1317, 0xff },
+ { 0x1318, 0xff },
+ { 0x1319, 0xff },
+ { 0x131a, 0xff },
+ { 0x131b, 0xff },
+ { 0x131c, 0xff },
+ { 0x131e, 0xff },
+ { 0x131f, 0xff },
+ { 0x1320, 0xff },
+ { 0x1b79, 0xff },
+ { 0x1b7a, 0xff },
+};
+
+/* Vendor specific hw configuration for CS8409 */
+const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[] = {
+ /* +PLL1/2_EN, +I2C_EN */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
+ /* ASP1/2_EN=0, ASP1_STP=1 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
+ /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
+ /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
+ /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
+ /* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL1, 0x0800 },
+ /* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL2, 0x2800 },
+ /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
+ /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
+ /* ASP1: LCHI = 00h */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
+ /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
+ /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
+ /* ASP2: LCHI=1Fh */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL1, 0x801f },
+ /* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL2, 0x283f },
+ /* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL3, 0x805c },
+ /* DMIC1_MO=10b, DMIC1/2_SR=1 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DMIC_CFG, 0x0023 },
+ /* ASP1/2_BEEP=0 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
+ /* ASP1/2_EN=1, ASP1_STP=1 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0062 },
+ /* -PLL2_EN */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
+ /* TX2.A: pre-scale att.=0 dB */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PRE_SCALE_ATTN2, 0x0000 },
+ /* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0xfc03 },
+ /* test mode on */
+ { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
+ /* GPIO hysteresis = 30 us */
+ { CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
+ /* test mode off */
+ { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
+ {} /* Terminator */
+};
+
+const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[] = {
+ /* EQ_SEL=1, EQ1/2_EN=0 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4000 },
+ /* +EQ_ACC */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x4000 },
+ /* +EQ2_EN */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4010 },
+ /* EQ_DATA_HI=0x0647 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=0, EQ_DATA_LO=0x67 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc0c7 },
+ /* EQ_DATA_HI=0x0647 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=1, EQ_DATA_LO=0x67 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc1c7 },
+ /* EQ_DATA_HI=0xf370 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xf370 },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=2, EQ_DATA_LO=0x71 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc271 },
+ /* EQ_DATA_HI=0x1ef8 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ef8 },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=3, EQ_DATA_LO=0x48 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc348 },
+ /* EQ_DATA_HI=0xc110 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc110 },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=4, EQ_DATA_LO=0x5a */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc45a },
+ /* EQ_DATA_HI=0x1f29 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1f29 },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=5, EQ_DATA_LO=0x74 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc574 },
+ /* EQ_DATA_HI=0x1d7a */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1d7a },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=6, EQ_DATA_LO=0x53 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc653 },
+ /* EQ_DATA_HI=0xc38c */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=7, EQ_DATA_LO=0x14 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc714 },
+ /* EQ_DATA_HI=0x1ca3 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ca3 },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=8, EQ_DATA_LO=0xc7 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc8c7 },
+ /* EQ_DATA_HI=0xc38c */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
+ /* +EQ_WRT, +EQ_ACC, EQ_ADR=9, EQ_DATA_LO=0x14 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc914 },
+ /* -EQ_ACC, -EQ_WRT */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x0000 },
+ {} /* Terminator */
+};
+
+struct sub_codec cs8409_cs42l42_codec = {
+ .addr = CS42L42_I2C_ADDR,
+ .reset_gpio = CS8409_CS42L42_RESET,
+ .irq_mask = CS8409_CS42L42_INT,
+ .init_seq = cs42l42_init_reg_seq,
+ .init_seq_num = ARRAY_SIZE(cs42l42_init_reg_seq),
+ .hp_jack_in = 0,
+ .mic_jack_in = 0,
+ .paged = 1,
+ .suspended = 1,
+ .no_type_dect = 0,
+};
+
+/******************************************************************************
+ * Dolphin Specific Arrays
+ * CS8409/ 2 X CS42L42
+ ******************************************************************************/
+
+const struct hda_verb dolphin_init_verbs[] = {
+ { 0x01, AC_VERB_SET_GPIO_WAKE_MASK, DOLPHIN_WAKE }, /* WAKE from GPIO 0,4 */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0080 }, /* I2C mode */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
+ { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0200 }, /* 100kHz I2C_STO = 2 */
+ {} /* terminator */
+};
+
+const struct hda_pintbl dolphin_pincfgs[] = {
+ { 0x24, 0x022210f0 }, /* ASP-1-TX-A */
+ { 0x25, 0x010240f0 }, /* ASP-1-TX-B */
+ { 0x34, 0x02a21050 }, /* ASP-1-RX */
+ {} /* terminator */
+};
+
+/* Vendor specific HW configuration for CS42L42 */
+static const struct cs8409_i2c_param dolphin_c0_init_reg_seq[] = {
+ { 0x1010, 0xB0 },
+ { 0x1D01, 0x00 },
+ { 0x1D02, 0x06 },
+ { 0x1D03, 0x9F },
+ { 0x1107, 0x01 },
+ { 0x1009, 0x02 },
+ { 0x1007, 0x03 },
+ { 0x1201, 0x00 },
+ { 0x1208, 0x13 },
+ { 0x1205, 0xFF },
+ { 0x1206, 0x00 },
+ { 0x1207, 0x20 },
+ { 0x1202, 0x0D },
+ { 0x2A02, 0x02 },
+ { 0x2A03, 0x00 },
+ { 0x2A04, 0x00 },
+ { 0x2A05, 0x02 },
+ { 0x2A06, 0x00 },
+ { 0x2A07, 0x20 },
+ { 0x2A01, 0x0C },
+ { 0x2902, 0x01 },
+ { 0x2903, 0x02 },
+ { 0x2904, 0x00 },
+ { 0x2905, 0x00 },
+ { 0x2901, 0x01 },
+ { 0x1101, 0x0A },
+ { 0x1102, 0x84 },
+ { 0x2001, 0x03 },
+ { 0x2301, 0x3F },
+ { 0x2303, 0x3F },
+ { 0x2302, 0x3f },
+ { 0x1B75, 0xB6 },
+ { 0x1B73, 0xC2 },
+ { 0x1129, 0x01 },
+ { 0x1121, 0xF3 },
+ { 0x1103, 0x20 },
+ { 0x1105, 0x00 },
+ { 0x1112, 0x00 },
+ { 0x1113, 0x80 },
+ { 0x1C03, 0xC0 },
+ { 0x1101, 0x02 },
+ { 0x1316, 0xff },
+ { 0x1317, 0xff },
+ { 0x1318, 0xff },
+ { 0x1319, 0xff },
+ { 0x131a, 0xff },
+ { 0x131b, 0xff },
+ { 0x131c, 0xff },
+ { 0x131e, 0xff },
+ { 0x131f, 0xff },
+ { 0x1320, 0xff },
+ { 0x1b79, 0xff },
+ { 0x1b7a, 0xff }
+};
+
+static const struct cs8409_i2c_param dolphin_c1_init_reg_seq[] = {
+ { 0x1010, 0xB0 },
+ { 0x1D01, 0x00 },
+ { 0x1D02, 0x06 },
+ { 0x1D03, 0x9F },
+ { 0x1107, 0x01 },
+ { 0x1009, 0x02 },
+ { 0x1007, 0x03 },
+ { 0x1201, 0x00 },
+ { 0x1208, 0x13 },
+ { 0x1205, 0xFF },
+ { 0x1206, 0x00 },
+ { 0x1207, 0x20 },
+ { 0x1202, 0x0D },
+ { 0x2A02, 0x02 },
+ { 0x2A03, 0x00 },
+ { 0x2A04, 0x80 },
+ { 0x2A05, 0x02 },
+ { 0x2A06, 0x00 },
+ { 0x2A07, 0xA0 },
+ { 0x2A01, 0x0C },
+ { 0x2902, 0x00 },
+ { 0x2903, 0x02 },
+ { 0x2904, 0x00 },
+ { 0x2905, 0x00 },
+ { 0x2901, 0x00 },
+ { 0x1101, 0x0E },
+ { 0x1102, 0x84 },
+ { 0x2001, 0x01 },
+ { 0x2301, 0x3F },
+ { 0x2303, 0x3F },
+ { 0x2302, 0x3f },
+ { 0x1B75, 0xB6 },
+ { 0x1B73, 0xC2 },
+ { 0x1129, 0x01 },
+ { 0x1121, 0xF3 },
+ { 0x1103, 0x20 },
+ { 0x1105, 0x00 },
+ { 0x1112, 0x00 },
+ { 0x1113, 0x80 },
+ { 0x1C03, 0xC0 },
+ { 0x1101, 0x06 },
+ { 0x1316, 0xff },
+ { 0x1317, 0xff },
+ { 0x1318, 0xff },
+ { 0x1319, 0xff },
+ { 0x131a, 0xff },
+ { 0x131b, 0xff },
+ { 0x131c, 0xff },
+ { 0x131e, 0xff },
+ { 0x131f, 0xff },
+ { 0x1320, 0xff },
+ { 0x1b79, 0xff },
+ { 0x1b7a, 0xff }
+};
+
+/* Vendor specific hw configuration for CS8409 */
+const struct cs8409_cir_param dolphin_hw_cfg[] = {
+ /* +PLL1/2_EN, +I2C_EN */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
+ /* ASP1_EN=0, ASP1_STP=1 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
+ /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
+ /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
+ /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
+ /* ASP1.B: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=128 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL1, 0x0880 },
+ /* ASP1.B: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=160 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL2, 0x08a0 },
+ /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
+ /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
+ { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
+ /* ASP1: LCHI = 00h */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
+ /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
+ /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
+ /* ASP1/2_BEEP=0 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
+ /* ASP1_EN=1, ASP1_STP=1 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0022 },
+ /* -PLL2_EN */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
+ /* ASP1_xxx_EN=1, ASP1_MCLK_EN=0 */
+ { CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0x5400 },
+ /* test mode on */
+ { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
+ /* GPIO hysteresis = 30 us */
+ { CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
+ /* test mode off */
+ { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
+ {} /* Terminator */
+};
+
+struct sub_codec dolphin_cs42l42_0 = {
+ .addr = DOLPHIN_C0_I2C_ADDR,
+ .reset_gpio = DOLPHIN_C0_RESET,
+ .irq_mask = DOLPHIN_C0_INT,
+ .init_seq = dolphin_c0_init_reg_seq,
+ .init_seq_num = ARRAY_SIZE(dolphin_c0_init_reg_seq),
+ .hp_jack_in = 0,
+ .mic_jack_in = 0,
+ .paged = 1,
+ .suspended = 1,
+ .no_type_dect = 0,
+};
+
+struct sub_codec dolphin_cs42l42_1 = {
+ .addr = DOLPHIN_C1_I2C_ADDR,
+ .reset_gpio = DOLPHIN_C1_RESET,
+ .irq_mask = DOLPHIN_C1_INT,
+ .init_seq = dolphin_c1_init_reg_seq,
+ .init_seq_num = ARRAY_SIZE(dolphin_c1_init_reg_seq),
+ .hp_jack_in = 0,
+ .mic_jack_in = 0,
+ .paged = 1,
+ .suspended = 1,
+ .no_type_dect = 1,
+};
+
+/******************************************************************************
+ * CS8409 Patch Driver Structs
+ * Arrays Used for all projects using CS8409
+ ******************************************************************************/
+
+const struct snd_pci_quirk cs8409_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1028, 0x0A11, "Bullseye", CS8409_BULLSEYE),
+ SND_PCI_QUIRK(0x1028, 0x0A12, "Bullseye", CS8409_BULLSEYE),
+ SND_PCI_QUIRK(0x1028, 0x0A23, "Bullseye", CS8409_BULLSEYE),
+ SND_PCI_QUIRK(0x1028, 0x0A24, "Bullseye", CS8409_BULLSEYE),
+ SND_PCI_QUIRK(0x1028, 0x0A25, "Bullseye", CS8409_BULLSEYE),
+ SND_PCI_QUIRK(0x1028, 0x0A29, "Bullseye", CS8409_BULLSEYE),
+ SND_PCI_QUIRK(0x1028, 0x0A2A, "Bullseye", CS8409_BULLSEYE),
+ SND_PCI_QUIRK(0x1028, 0x0A2B, "Bullseye", CS8409_BULLSEYE),
+ SND_PCI_QUIRK(0x1028, 0x0AB0, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0AB2, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0AB1, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0AB3, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0AB4, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0AB5, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0AD9, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0ADA, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0ADB, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0ADC, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0AF4, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0AF5, "Warlock", CS8409_WARLOCK),
+ SND_PCI_QUIRK(0x1028, 0x0A77, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0A78, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0A79, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0A7A, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0A7D, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0A7E, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0A7F, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0A80, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0ADF, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AE0, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AE1, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AE2, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AE9, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AEA, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AEB, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AEC, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AED, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AEE, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AEF, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AF0, "Cyborg", CS8409_CYBORG),
+ SND_PCI_QUIRK(0x1028, 0x0AD0, "Dolphin", CS8409_DOLPHIN),
+ SND_PCI_QUIRK(0x1028, 0x0AD1, "Dolphin", CS8409_DOLPHIN),
+ SND_PCI_QUIRK(0x1028, 0x0AD2, "Dolphin", CS8409_DOLPHIN),
+ SND_PCI_QUIRK(0x1028, 0x0AD3, "Dolphin", CS8409_DOLPHIN),
+ SND_PCI_QUIRK(0x1028, 0x0ACF, "Dolphin", CS8409_DOLPHIN),
+ {} /* terminator */
+};
+
+/* Dell Inspiron models with cs8409/cs42l42 */
+const struct hda_model_fixup cs8409_models[] = {
+ { .id = CS8409_BULLSEYE, .name = "bullseye" },
+ { .id = CS8409_WARLOCK, .name = "warlock" },
+ { .id = CS8409_CYBORG, .name = "cyborg" },
+ { .id = CS8409_DOLPHIN, .name = "dolphin" },
+ {}
+};
+
+const struct hda_fixup cs8409_fixups[] = {
+ [CS8409_BULLSEYE] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = cs8409_cs42l42_pincfgs,
+ .chained = true,
+ .chain_id = CS8409_FIXUPS,
+ },
+ [CS8409_WARLOCK] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = cs8409_cs42l42_pincfgs,
+ .chained = true,
+ .chain_id = CS8409_FIXUPS,
+ },
+ [CS8409_CYBORG] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = cs8409_cs42l42_pincfgs,
+ .chained = true,
+ .chain_id = CS8409_FIXUPS,
+ },
+ [CS8409_FIXUPS] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cs8409_cs42l42_fixups,
+ },
+ [CS8409_DOLPHIN] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = dolphin_pincfgs,
+ .chained = true,
+ .chain_id = CS8409_DOLPHIN_FIXUPS,
+ },
+ [CS8409_DOLPHIN_FIXUPS] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = dolphin_fixups,
+ },
+};
diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c
new file mode 100644
index 000000000000..3c7ef55d016e
--- /dev/null
+++ b/sound/pci/hda/patch_cs8409.c
@@ -0,0 +1,1299 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ * Cirrus Logic International Semiconductor Ltd.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <linux/mutex.h>
+#include <linux/iopoll.h>
+
+#include "patch_cs8409.h"
+
+/******************************************************************************
+ * CS8409 Specific Functions
+ ******************************************************************************/
+
+static int cs8409_parse_auto_config(struct hda_codec *codec)
+{
+ struct cs8409_spec *spec = codec->spec;
+ int err;
+ int i;
+
+ err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
+ if (err < 0)
+ return err;
+
+ err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
+ if (err < 0)
+ return err;
+
+ /* keep the ADCs powered up when it's dynamically switchable */
+ if (spec->gen.dyn_adc_switch) {
+ unsigned int done = 0;
+
+ for (i = 0; i < spec->gen.input_mux.num_items; i++) {
+ int idx = spec->gen.dyn_adc_idx[i];
+
+ if (done & (1 << idx))
+ continue;
+ snd_hda_gen_fix_pin_power(codec, spec->gen.adc_nids[idx]);
+ done |= 1 << idx;
+ }
+ }
+
+ return 0;
+}
+
+static void cs8409_disable_i2c_clock_worker(struct work_struct *work);
+
+static struct cs8409_spec *cs8409_alloc_spec(struct hda_codec *codec)
+{
+ struct cs8409_spec *spec;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec)
+ return NULL;
+ codec->spec = spec;
+ spec->codec = codec;
+ codec->power_save_node = 1;
+ mutex_init(&spec->i2c_mux);
+ INIT_DELAYED_WORK(&spec->i2c_clk_work, cs8409_disable_i2c_clock_worker);
+ snd_hda_gen_spec_init(&spec->gen);
+
+ return spec;
+}
+
+static inline int cs8409_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
+{
+ snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_COEF_INDEX, idx);
+ return snd_hda_codec_read(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_GET_PROC_COEF, 0);
+}
+
+static inline void cs8409_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
+ unsigned int coef)
+{
+ snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_COEF_INDEX, idx);
+ snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_PROC_COEF, coef);
+}
+
+/*
+ * cs8409_enable_i2c_clock - Disable I2C clocks
+ * @codec: the codec instance
+ * Disable I2C clocks.
+ * This must be called when the i2c mutex is unlocked.
+ */
+static void cs8409_disable_i2c_clock(struct hda_codec *codec)
+{
+ struct cs8409_spec *spec = codec->spec;
+
+ mutex_lock(&spec->i2c_mux);
+ if (spec->i2c_clck_enabled) {
+ cs8409_vendor_coef_set(spec->codec, 0x0,
+ cs8409_vendor_coef_get(spec->codec, 0x0) & 0xfffffff7);
+ spec->i2c_clck_enabled = 0;
+ }
+ mutex_unlock(&spec->i2c_mux);
+}
+
+/*
+ * cs8409_disable_i2c_clock_worker - Worker that disable the I2C Clock after 25ms without use
+ */
+static void cs8409_disable_i2c_clock_worker(struct work_struct *work)
+{
+ struct cs8409_spec *spec = container_of(work, struct cs8409_spec, i2c_clk_work.work);
+
+ cs8409_disable_i2c_clock(spec->codec);
+}
+
+/*
+ * cs8409_enable_i2c_clock - Enable I2C clocks
+ * @codec: the codec instance
+ * Enable I2C clocks.
+ * This must be called when the i2c mutex is locked.
+ */
+static void cs8409_enable_i2c_clock(struct hda_codec *codec)
+{
+ struct cs8409_spec *spec = codec->spec;
+
+ /* Cancel the disable timer, but do not wait for any running disable functions to finish.
+ * If the disable timer runs out before cancel, the delayed work thread will be blocked,
+ * waiting for the mutex to become unlocked. This mutex will be locked for the duration of
+ * any i2c transaction, so the disable function will run to completion immediately
+ * afterwards in the scenario. The next enable call will re-enable the clock, regardless.
+ */
+ cancel_delayed_work(&spec->i2c_clk_work);
+
+ if (!spec->i2c_clck_enabled) {
+ cs8409_vendor_coef_set(codec, 0x0, cs8409_vendor_coef_get(codec, 0x0) | 0x8);
+ spec->i2c_clck_enabled = 1;
+ }
+ queue_delayed_work(system_power_efficient_wq, &spec->i2c_clk_work, msecs_to_jiffies(25));
+}
+
+/**
+ * cs8409_i2c_wait_complete - Wait for I2C transaction
+ * @codec: the codec instance
+ *
+ * Wait for I2C transaction to complete.
+ * Return -ETIMEDOUT if transaction wait times out.
+ */
+static int cs8409_i2c_wait_complete(struct hda_codec *codec)
+{
+ unsigned int retval;
+
+ return read_poll_timeout(cs8409_vendor_coef_get, retval, retval & 0x18,
+ CS42L42_I2C_SLEEP_US, CS42L42_I2C_TIMEOUT_US, false, codec, CS8409_I2C_STS);
+}
+
+/**
+ * cs8409_set_i2c_dev_addr - Set i2c address for transaction
+ * @codec: the codec instance
+ * @addr: I2C Address
+ */
+static void cs8409_set_i2c_dev_addr(struct hda_codec *codec, unsigned int addr)
+{
+ struct cs8409_spec *spec = codec->spec;
+
+ if (spec->dev_addr != addr) {
+ cs8409_vendor_coef_set(codec, CS8409_I2C_ADDR, addr);
+ spec->dev_addr = addr;
+ }
+}
+
+/**
+ * cs8409_i2c_set_page - CS8409 I2C set page register.
+ * @scodec: the codec instance
+ * @i2c_reg: Page register
+ *
+ * Returns negative on error.
+ */
+static int cs8409_i2c_set_page(struct sub_codec *scodec, unsigned int i2c_reg)
+{
+ struct hda_codec *codec = scodec->codec;
+
+ if (scodec->paged && (scodec->last_page != (i2c_reg >> 8))) {
+ cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg >> 8);
+ if (cs8409_i2c_wait_complete(codec) < 0)
+ return -EIO;
+ scodec->last_page = i2c_reg >> 8;
+ }
+
+ return 0;
+}
+
+/**
+ * cs8409_i2c_read - CS8409 I2C Read.
+ * @scodec: the codec instance
+ * @addr: Register to read
+ *
+ * Returns negative on error, otherwise returns read value in bits 0-7.
+ */
+static int cs8409_i2c_read(struct sub_codec *scodec, unsigned int addr)
+{
+ struct hda_codec *codec = scodec->codec;
+ struct cs8409_spec *spec = codec->spec;
+ unsigned int i2c_reg_data;
+ unsigned int read_data;
+
+ if (scodec->suspended)
+ return -EPERM;
+
+ mutex_lock(&spec->i2c_mux);
+ cs8409_enable_i2c_clock(codec);
+ cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+ if (cs8409_i2c_set_page(scodec, addr))
+ goto error;
+
+ i2c_reg_data = (addr << 8) & 0x0ffff;
+ cs8409_vendor_coef_set(codec, CS8409_I2C_QREAD, i2c_reg_data);
+ if (cs8409_i2c_wait_complete(codec) < 0)
+ goto error;
+
+ /* Register in bits 15-8 and the data in 7-0 */
+ read_data = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD);
+
+ mutex_unlock(&spec->i2c_mux);
+
+ return read_data & 0x0ff;
+
+error:
+ mutex_unlock(&spec->i2c_mux);
+ codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr);
+ return -EIO;
+}
+
+/**
+ * cs8409_i2c_bulk_read - CS8409 I2C Read Sequence.
+ * @scodec: the codec instance
+ * @seq: Register Sequence to read
+ * @count: Number of registeres to read
+ *
+ * Returns negative on error, values are read into value element of cs8409_i2c_param sequence.
+ */
+static int cs8409_i2c_bulk_read(struct sub_codec *scodec, struct cs8409_i2c_param *seq, int count)
+{
+ struct hda_codec *codec = scodec->codec;
+ struct cs8409_spec *spec = codec->spec;
+ unsigned int i2c_reg_data;
+ int i;
+
+ if (scodec->suspended)
+ return -EPERM;
+
+ mutex_lock(&spec->i2c_mux);
+ cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+ for (i = 0; i < count; i++) {
+ cs8409_enable_i2c_clock(codec);
+ if (cs8409_i2c_set_page(scodec, seq[i].addr))
+ goto error;
+
+ i2c_reg_data = (seq[i].addr << 8) & 0x0ffff;
+ cs8409_vendor_coef_set(codec, CS8409_I2C_QREAD, i2c_reg_data);
+
+ if (cs8409_i2c_wait_complete(codec) < 0)
+ goto error;
+
+ seq[i].value = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD) & 0xff;
+ }
+
+ mutex_unlock(&spec->i2c_mux);
+
+ return 0;
+
+error:
+ mutex_unlock(&spec->i2c_mux);
+ codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr);
+ return -EIO;
+}
+
+/**
+ * cs8409_i2c_write - CS8409 I2C Write.
+ * @scodec: the codec instance
+ * @addr: Register to write to
+ * @value: Data to write
+ *
+ * Returns negative on error, otherwise returns 0.
+ */
+static int cs8409_i2c_write(struct sub_codec *scodec, unsigned int addr, unsigned int value)
+{
+ struct hda_codec *codec = scodec->codec;
+ struct cs8409_spec *spec = codec->spec;
+ unsigned int i2c_reg_data;
+
+ if (scodec->suspended)
+ return -EPERM;
+
+ mutex_lock(&spec->i2c_mux);
+
+ cs8409_enable_i2c_clock(codec);
+ cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+ if (cs8409_i2c_set_page(scodec, addr))
+ goto error;
+
+ i2c_reg_data = ((addr << 8) & 0x0ff00) | (value & 0x0ff);
+ cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg_data);
+
+ if (cs8409_i2c_wait_complete(codec) < 0)
+ goto error;
+
+ mutex_unlock(&spec->i2c_mux);
+ return 0;
+
+error:
+ mutex_unlock(&spec->i2c_mux);
+ codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr);
+ return -EIO;
+}
+
+/**
+ * cs8409_i2c_bulk_write - CS8409 I2C Write Sequence.
+ * @scodec: the codec instance
+ * @seq: Register Sequence to write
+ * @count: Number of registeres to write
+ *
+ * Returns negative on error.
+ */
+static int cs8409_i2c_bulk_write(struct sub_codec *scodec, const struct cs8409_i2c_param *seq,
+ int count)
+{
+ struct hda_codec *codec = scodec->codec;
+ struct cs8409_spec *spec = codec->spec;
+ unsigned int i2c_reg_data;
+ int i;
+
+ if (scodec->suspended)
+ return -EPERM;
+
+ mutex_lock(&spec->i2c_mux);
+ cs8409_set_i2c_dev_addr(codec, scodec->addr);
+
+ for (i = 0; i < count; i++) {
+ cs8409_enable_i2c_clock(codec);
+ if (cs8409_i2c_set_page(scodec, seq[i].addr))
+ goto error;
+
+ i2c_reg_data = ((seq[i].addr << 8) & 0x0ff00) | (seq[i].value & 0x0ff);
+ cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg_data);
+
+ if (cs8409_i2c_wait_complete(codec) < 0)
+ goto error;
+ }
+
+ mutex_unlock(&spec->i2c_mux);
+
+ return 0;
+
+error:
+ mutex_unlock(&spec->i2c_mux);
+ codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr);
+ return -EIO;
+}
+
+static int cs8409_init(struct hda_codec *codec)
+{
+ int ret = snd_hda_gen_init(codec);
+
+ if (!ret)
+ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
+
+ return ret;
+}
+
+static int cs8409_build_controls(struct hda_codec *codec)
+{
+ int err;
+
+ err = snd_hda_gen_build_controls(codec);
+ if (err < 0)
+ return err;
+ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
+
+ return 0;
+}
+
+/* Enable/Disable Unsolicited Response */
+static void cs8409_enable_ur(struct hda_codec *codec, int flag)
+{
+ struct cs8409_spec *spec = codec->spec;
+ unsigned int ur_gpios = 0;
+ int i;
+
+ for (i = 0; i < spec->num_scodecs; i++)
+ ur_gpios |= spec->scodecs[i]->irq_mask;
+
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK,
+ flag ? ur_gpios : 0);
+
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE,
+ flag ? AC_UNSOL_ENABLED : 0);
+}
+
+static void cs8409_fix_caps(struct hda_codec *codec, unsigned int nid)
+{
+ int caps;
+
+ /* CS8409 is simple HDA bridge and intended to be used with a remote
+ * companion codec. Most of input/output PIN(s) have only basic
+ * capabilities. Receive and Transmit NID(s) have only OUTC and INC
+ * capabilities and no presence detect capable (PDC) and call to
+ * snd_hda_gen_build_controls() will mark them as non detectable
+ * phantom jacks. However, a companion codec may be
+ * connected to these pins which supports jack detect
+ * capabilities. We have to override pin capabilities,
+ * otherwise they will not be created as input devices.
+ */
+ caps = snd_hdac_read_parm(&codec->core, nid, AC_PAR_PIN_CAP);
+ if (caps >= 0)
+ snd_hdac_override_parm(&codec->core, nid, AC_PAR_PIN_CAP,
+ (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
+
+ snd_hda_override_wcaps(codec, nid, (get_wcaps(codec, nid) | AC_WCAP_UNSOL_CAP));
+}
+
+/******************************************************************************
+ * CS42L42 Specific Functions
+ ******************************************************************************/
+
+int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo)
+{
+ unsigned int ofs = get_amp_offset(kctrl);
+ u8 chs = get_amp_channels(kctrl);
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->value.integer.step = 1;
+ uinfo->count = chs == 3 ? 2 : 1;
+
+ switch (ofs) {
+ case CS42L42_VOL_DAC:
+ uinfo->value.integer.min = CS42L42_HP_VOL_REAL_MIN;
+ uinfo->value.integer.max = CS42L42_HP_VOL_REAL_MAX;
+ break;
+ case CS42L42_VOL_ADC:
+ uinfo->value.integer.min = CS42L42_AMIC_VOL_REAL_MIN;
+ uinfo->value.integer.max = CS42L42_AMIC_VOL_REAL_MAX;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kctrl);
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
+ int chs = get_amp_channels(kctrl);
+ unsigned int ofs = get_amp_offset(kctrl);
+ long *valp = uctrl->value.integer.value;
+
+ switch (ofs) {
+ case CS42L42_VOL_DAC:
+ if (chs & BIT(0))
+ *valp++ = cs42l42->vol[ofs];
+ if (chs & BIT(1))
+ *valp = cs42l42->vol[ofs+1];
+ break;
+ case CS42L42_VOL_ADC:
+ if (chs & BIT(0))
+ *valp = cs42l42->vol[ofs];
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void cs42l42_mute(struct sub_codec *cs42l42, int vol_type,
+ unsigned int chs, bool mute)
+{
+ if (mute) {
+ if (vol_type == CS42L42_VOL_DAC) {
+ if (chs & BIT(0))
+ cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHA, 0x3f);
+ if (chs & BIT(1))
+ cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHB, 0x3f);
+ } else if (vol_type == CS42L42_VOL_ADC) {
+ if (chs & BIT(0))
+ cs8409_i2c_write(cs42l42, CS42L42_REG_AMIC_VOL, 0x9f);
+ }
+ } else {
+ if (vol_type == CS42L42_VOL_DAC) {
+ if (chs & BIT(0))
+ cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHA,
+ -(cs42l42->vol[CS42L42_DAC_CH0_VOL_OFFSET])
+ & CS42L42_REG_HS_VOL_MASK);
+ if (chs & BIT(1))
+ cs8409_i2c_write(cs42l42, CS42L42_REG_HS_VOL_CHB,
+ -(cs42l42->vol[CS42L42_DAC_CH1_VOL_OFFSET])
+ & CS42L42_REG_HS_VOL_MASK);
+ } else if (vol_type == CS42L42_VOL_ADC) {
+ if (chs & BIT(0))
+ cs8409_i2c_write(cs42l42, CS42L42_REG_AMIC_VOL,
+ cs42l42->vol[CS42L42_ADC_VOL_OFFSET]
+ & CS42L42_REG_AMIC_VOL_MASK);
+ }
+ }
+}
+
+int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kctrl);
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
+ int chs = get_amp_channels(kctrl);
+ unsigned int ofs = get_amp_offset(kctrl);
+ long *valp = uctrl->value.integer.value;
+
+ switch (ofs) {
+ case CS42L42_VOL_DAC:
+ if (chs & BIT(0))
+ cs42l42->vol[ofs] = *valp;
+ if (chs & BIT(1)) {
+ valp++;
+ cs42l42->vol[ofs + 1] = *valp;
+ }
+ if (spec->playback_started)
+ cs42l42_mute(cs42l42, CS42L42_VOL_DAC, chs, false);
+ break;
+ case CS42L42_VOL_ADC:
+ if (chs & BIT(0))
+ cs42l42->vol[ofs] = *valp;
+ if (spec->capture_started)
+ cs42l42_mute(cs42l42, CS42L42_VOL_ADC, chs, false);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void cs42l42_playback_pcm_hook(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream,
+ int action)
+{
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42;
+ int i;
+ bool mute;
+
+ switch (action) {
+ case HDA_GEN_PCM_ACT_PREPARE:
+ mute = false;
+ spec->playback_started = 1;
+ break;
+ case HDA_GEN_PCM_ACT_CLEANUP:
+ mute = true;
+ spec->playback_started = 0;
+ break;
+ default:
+ return;
+ }
+
+ for (i = 0; i < spec->num_scodecs; i++) {
+ cs42l42 = spec->scodecs[i];
+ cs42l42_mute(cs42l42, CS42L42_VOL_DAC, 0x3, mute);
+ }
+}
+
+static void cs42l42_capture_pcm_hook(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream,
+ int action)
+{
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42;
+ int i;
+ bool mute;
+
+ switch (action) {
+ case HDA_GEN_PCM_ACT_PREPARE:
+ mute = false;
+ spec->capture_started = 1;
+ break;
+ case HDA_GEN_PCM_ACT_CLEANUP:
+ mute = true;
+ spec->capture_started = 0;
+ break;
+ default:
+ return;
+ }
+
+ for (i = 0; i < spec->num_scodecs; i++) {
+ cs42l42 = spec->scodecs[i];
+ cs42l42_mute(cs42l42, CS42L42_VOL_ADC, 0x3, mute);
+ }
+}
+
+/* Configure CS42L42 slave codec for jack autodetect */
+static void cs42l42_enable_jack_detect(struct sub_codec *cs42l42)
+{
+ cs8409_i2c_write(cs42l42, 0x1b70, cs42l42->hsbias_hiz);
+ /* Clear WAKE# */
+ cs8409_i2c_write(cs42l42, 0x1b71, 0x00C1);
+ /* Wait ~2.5ms */
+ usleep_range(2500, 3000);
+ /* Set mode WAKE# output follows the combination logic directly */
+ cs8409_i2c_write(cs42l42, 0x1b71, 0x00C0);
+ /* Clear interrupts status */
+ cs8409_i2c_read(cs42l42, 0x130f);
+ /* Enable interrupt */
+ cs8409_i2c_write(cs42l42, 0x1320, 0xF3);
+}
+
+/* Enable and run CS42L42 slave codec jack auto detect */
+static void cs42l42_run_jack_detect(struct sub_codec *cs42l42)
+{
+ /* Clear interrupts */
+ cs8409_i2c_read(cs42l42, 0x1308);
+ cs8409_i2c_read(cs42l42, 0x1b77);
+ cs8409_i2c_write(cs42l42, 0x1320, 0xFF);
+ cs8409_i2c_read(cs42l42, 0x130f);
+
+ cs8409_i2c_write(cs42l42, 0x1102, 0x87);
+ cs8409_i2c_write(cs42l42, 0x1f06, 0x86);
+ cs8409_i2c_write(cs42l42, 0x1b74, 0x07);
+ cs8409_i2c_write(cs42l42, 0x131b, 0xFD);
+ cs8409_i2c_write(cs42l42, 0x1120, 0x80);
+ /* Wait ~100us*/
+ usleep_range(100, 200);
+ cs8409_i2c_write(cs42l42, 0x111f, 0x77);
+ cs8409_i2c_write(cs42l42, 0x1120, 0xc0);
+}
+
+static int cs42l42_handle_tip_sense(struct sub_codec *cs42l42, unsigned int reg_ts_status)
+{
+ int status_changed = 0;
+
+ /* TIP_SENSE INSERT/REMOVE */
+ switch (reg_ts_status) {
+ case CS42L42_JACK_INSERTED:
+ if (!cs42l42->hp_jack_in) {
+ if (cs42l42->no_type_dect) {
+ status_changed = 1;
+ cs42l42->hp_jack_in = 1;
+ cs42l42->mic_jack_in = 0;
+ } else {
+ cs42l42_run_jack_detect(cs42l42);
+ }
+ }
+ break;
+
+ case CS42L42_JACK_REMOVED:
+ if (cs42l42->hp_jack_in || cs42l42->mic_jack_in) {
+ status_changed = 1;
+ cs42l42->hp_jack_in = 0;
+ cs42l42->mic_jack_in = 0;
+ }
+ break;
+ default:
+ /* jack in transition */
+ break;
+ }
+
+ return status_changed;
+}
+
+static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42)
+{
+ int status_changed = 0;
+ int reg_cdc_status;
+ int reg_hs_status;
+ int reg_ts_status;
+ int type;
+
+ /* Read jack detect status registers */
+ reg_cdc_status = cs8409_i2c_read(cs42l42, 0x1308);
+ reg_hs_status = cs8409_i2c_read(cs42l42, 0x1124);
+ reg_ts_status = cs8409_i2c_read(cs42l42, 0x130f);
+
+ /* If status values are < 0, read error has occurred. */
+ if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0)
+ return -EIO;
+
+ /* HSDET_AUTO_DONE */
+ if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE) {
+
+ /* Disable HSDET_AUTO_DONE */
+ cs8409_i2c_write(cs42l42, 0x131b, 0xFF);
+
+ type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1);
+
+ if (cs42l42->no_type_dect) {
+ status_changed = cs42l42_handle_tip_sense(cs42l42, reg_ts_status);
+ } else if (type == 4) {
+ /* Type 4 not supported */
+ status_changed = cs42l42_handle_tip_sense(cs42l42, CS42L42_JACK_REMOVED);
+ } else {
+ if (!cs42l42->hp_jack_in) {
+ status_changed = 1;
+ cs42l42->hp_jack_in = 1;
+ }
+ /* type = 3 has no mic */
+ if ((!cs42l42->mic_jack_in) && (type != 3)) {
+ status_changed = 1;
+ cs42l42->mic_jack_in = 1;
+ }
+ }
+ /* Configure the HSDET mode. */
+ cs8409_i2c_write(cs42l42, 0x1120, 0x80);
+ /* Enable the HPOUT ground clamp and configure the HP pull-down */
+ cs8409_i2c_write(cs42l42, 0x1F06, 0x02);
+ /* Re-Enable Tip Sense Interrupt */
+ cs8409_i2c_write(cs42l42, 0x1320, 0xF3);
+ } else {
+ status_changed = cs42l42_handle_tip_sense(cs42l42, reg_ts_status);
+ }
+
+ return status_changed;
+}
+
+static void cs42l42_resume(struct sub_codec *cs42l42)
+{
+ struct hda_codec *codec = cs42l42->codec;
+ unsigned int gpio_data;
+ struct cs8409_i2c_param irq_regs[] = {
+ { 0x1308, 0x00 },
+ { 0x1309, 0x00 },
+ { 0x130A, 0x00 },
+ { 0x130F, 0x00 },
+ };
+
+ /* Bring CS42L42 out of Reset */
+ gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
+ gpio_data |= cs42l42->reset_gpio;
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+ usleep_range(10000, 15000);
+
+ cs42l42->suspended = 0;
+
+ /* Initialize CS42L42 companion codec */
+ cs8409_i2c_bulk_write(cs42l42, cs42l42->init_seq, cs42l42->init_seq_num);
+ usleep_range(20000, 25000);
+
+ /* Clear interrupts, by reading interrupt status registers */
+ cs8409_i2c_bulk_read(cs42l42, irq_regs, ARRAY_SIZE(irq_regs));
+
+ if (cs42l42->full_scale_vol)
+ cs8409_i2c_write(cs42l42, 0x2001, 0x01);
+
+ cs42l42_enable_jack_detect(cs42l42);
+}
+
+#ifdef CONFIG_PM
+static void cs42l42_suspend(struct sub_codec *cs42l42)
+{
+ struct hda_codec *codec = cs42l42->codec;
+ unsigned int gpio_data;
+ int reg_cdc_status = 0;
+ const struct cs8409_i2c_param cs42l42_pwr_down_seq[] = {
+ { 0x1F06, 0x02 },
+ { 0x1129, 0x00 },
+ { 0x2301, 0x3F },
+ { 0x2302, 0x3F },
+ { 0x2303, 0x3F },
+ { 0x2001, 0x0F },
+ { 0x2A01, 0x00 },
+ { 0x1207, 0x00 },
+ { 0x1101, 0xFE },
+ { 0x1102, 0x8C },
+ { 0x1101, 0xFF },
+ };
+
+ cs8409_i2c_bulk_write(cs42l42, cs42l42_pwr_down_seq, ARRAY_SIZE(cs42l42_pwr_down_seq));
+
+ if (read_poll_timeout(cs8409_i2c_read, reg_cdc_status,
+ (reg_cdc_status & 0x1), CS42L42_PDN_SLEEP_US, CS42L42_PDN_TIMEOUT_US,
+ true, cs42l42, 0x1308) < 0)
+ codec_warn(codec, "Timeout waiting for PDN_DONE for CS42L42\n");
+
+ /* Power down CS42L42 ASP/EQ/MIX/HP */
+ cs8409_i2c_write(cs42l42, 0x1102, 0x9C);
+ cs42l42->suspended = 1;
+ cs42l42->last_page = 0;
+ cs42l42->hp_jack_in = 0;
+ cs42l42->mic_jack_in = 0;
+
+ /* Put CS42L42 into Reset */
+ gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
+ gpio_data &= ~cs42l42->reset_gpio;
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+}
+#endif
+
+static void cs8409_free(struct hda_codec *codec)
+{
+ struct cs8409_spec *spec = codec->spec;
+
+ /* Cancel i2c clock disable timer, and disable clock if left enabled */
+ cancel_delayed_work_sync(&spec->i2c_clk_work);
+ cs8409_disable_i2c_clock(codec);
+
+ snd_hda_gen_free(codec);
+}
+
+/******************************************************************************
+ * BULLSEYE / WARLOCK / CYBORG Specific Functions
+ * CS8409/CS42L42
+ ******************************************************************************/
+
+/*
+ * In the case of CS8409 we do not have unsolicited events from NID's 0x24
+ * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will
+ * generate interrupt via gpio 4 to notify jack events. We have to overwrite
+ * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
+ * and then notify status via generic snd_hda_jack_unsol_event() call.
+ */
+static void cs8409_cs42l42_jack_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+ struct hda_jack_tbl *jk;
+
+ /* jack_unsol_event() will be called every time gpio line changing state.
+ * In this case gpio4 line goes up as a result of reading interrupt status
+ * registers in previous cs8409_jack_unsol_event() call.
+ * We don't need to handle this event, ignoring...
+ */
+ if (res & cs42l42->irq_mask)
+ return;
+
+ if (cs42l42_jack_unsol_event(cs42l42)) {
+ snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID,
+ cs42l42->hp_jack_in ? 0 : PIN_OUT);
+ /* Report jack*/
+ jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0);
+ if (jk)
+ snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+ AC_UNSOL_RES_TAG);
+ /* Report jack*/
+ jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0);
+ if (jk)
+ snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+ AC_UNSOL_RES_TAG);
+ }
+}
+
+#ifdef CONFIG_PM
+/* Manage PDREF, when transition to D3hot */
+static int cs8409_cs42l42_suspend(struct hda_codec *codec)
+{
+ struct cs8409_spec *spec = codec->spec;
+ int i;
+
+ spec->init_done = 0;
+
+ cs8409_enable_ur(codec, 0);
+
+ for (i = 0; i < spec->num_scodecs; i++)
+ cs42l42_suspend(spec->scodecs[i]);
+
+ /* Cancel i2c clock disable timer, and disable clock if left enabled */
+ cancel_delayed_work_sync(&spec->i2c_clk_work);
+ cs8409_disable_i2c_clock(codec);
+
+ snd_hda_shutup_pins(codec);
+
+ return 0;
+}
+#endif
+
+/* Vendor specific HW configuration
+ * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
+ */
+static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
+{
+ const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg;
+ const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn;
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+ if (spec->gpio_mask) {
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_MASK,
+ spec->gpio_mask);
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DIRECTION,
+ spec->gpio_dir);
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA,
+ spec->gpio_data);
+ }
+
+ for (; seq->nid; seq++)
+ cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
+
+ if (codec->fixup_id == CS8409_BULLSEYE) {
+ for (; seq_bullseye->nid; seq_bullseye++)
+ cs8409_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff);
+ }
+
+ /* DMIC1_MO=00b, DMIC1/2_SR=1 */
+ if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG)
+ cs8409_vendor_coef_set(codec, 0x09, 0x0003);
+
+ cs42l42_resume(cs42l42);
+
+ /* Enable Unsolicited Response */
+ cs8409_enable_ur(codec, 1);
+}
+
+static const struct hda_codec_ops cs8409_cs42l42_patch_ops = {
+ .build_controls = cs8409_build_controls,
+ .build_pcms = snd_hda_gen_build_pcms,
+ .init = cs8409_init,
+ .free = cs8409_free,
+ .unsol_event = cs8409_cs42l42_jack_unsol_event,
+#ifdef CONFIG_PM
+ .suspend = cs8409_cs42l42_suspend,
+#endif
+};
+
+static int cs8409_cs42l42_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+ unsigned int *res)
+{
+ struct hda_codec *codec = container_of(dev, struct hda_codec, core);
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+ unsigned int nid = ((cmd >> 20) & 0x07f);
+ unsigned int verb = ((cmd >> 8) & 0x0fff);
+
+ /* CS8409 pins have no AC_PINSENSE_PRESENCE
+ * capabilities. We have to intercept 2 calls for pins 0x24 and 0x34
+ * and return correct pin sense values for read_pin_sense() call from
+ * hda_jack based on CS42L42 jack detect status.
+ */
+ switch (nid) {
+ case CS8409_CS42L42_HP_PIN_NID:
+ if (verb == AC_VERB_GET_PIN_SENSE) {
+ *res = (cs42l42->hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+ return 0;
+ }
+ break;
+ case CS8409_CS42L42_AMIC_PIN_NID:
+ if (verb == AC_VERB_GET_PIN_SENSE) {
+ *res = (cs42l42->mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return spec->exec_verb(dev, cmd, flags, res);
+}
+
+void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action)
+{
+ struct cs8409_spec *spec = codec->spec;
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs);
+ /* verb exec op override */
+ spec->exec_verb = codec->core.exec_verb;
+ codec->core.exec_verb = cs8409_cs42l42_exec_verb;
+
+ spec->scodecs[CS8409_CODEC0] = &cs8409_cs42l42_codec;
+ spec->num_scodecs = 1;
+ spec->scodecs[CS8409_CODEC0]->codec = codec;
+ codec->patch_ops = cs8409_cs42l42_patch_ops;
+
+ spec->gen.suppress_auto_mute = 1;
+ spec->gen.no_primary_hp = 1;
+ spec->gen.suppress_vmaster = 1;
+
+ /* GPIO 5 out, 3,4 in */
+ spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio;
+ spec->gpio_data = 0;
+ spec->gpio_mask = 0x03f;
+
+ /* Basic initial sequence for specific hw configuration */
+ snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);
+
+ cs8409_fix_caps(codec, CS8409_CS42L42_HP_PIN_NID);
+ cs8409_fix_caps(codec, CS8409_CS42L42_AMIC_PIN_NID);
+
+ /* Set TIP_SENSE_EN for analog front-end of tip sense.
+ * Additionally set HSBIAS_SENSE_EN and Full Scale volume for some variants.
+ */
+ switch (codec->fixup_id) {
+ case CS8409_WARLOCK:
+ spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
+ spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+ break;
+ case CS8409_BULLSEYE:
+ spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
+ spec->scodecs[CS8409_CODEC0]->full_scale_vol = 0;
+ break;
+ case CS8409_CYBORG:
+ spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x00a0;
+ spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+ break;
+ default:
+ spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0003;
+ spec->scodecs[CS8409_CODEC0]->full_scale_vol = 1;
+ break;
+ }
+
+ break;
+ case HDA_FIXUP_ACT_PROBE:
+ /* Fix Sample Rate to 48kHz */
+ spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
+ spec->gen.stream_analog_capture = &cs42l42_48k_pcm_analog_capture;
+ /* add hooks */
+ spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
+ spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
+ /* Set initial DMIC volume to -26 dB */
+ snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
+ HDA_INPUT, 0, 0xff, 0x19);
+ snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
+ &cs42l42_dac_volume_mixer);
+ snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume",
+ &cs42l42_adc_volume_mixer);
+ /* Disable Unsolicited Response during boot */
+ cs8409_enable_ur(codec, 0);
+ snd_hda_codec_set_name(codec, "CS8409/CS42L42");
+ break;
+ case HDA_FIXUP_ACT_INIT:
+ cs8409_cs42l42_hw_init(codec);
+ spec->init_done = 1;
+ if (spec->init_done && spec->build_ctrl_done
+ && !spec->scodecs[CS8409_CODEC0]->hp_jack_in)
+ cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]);
+ break;
+ case HDA_FIXUP_ACT_BUILD:
+ spec->build_ctrl_done = 1;
+ /* Run jack auto detect first time on boot
+ * after controls have been added, to check if jack has
+ * been already plugged in.
+ * Run immediately after init.
+ */
+ if (spec->init_done && spec->build_ctrl_done
+ && !spec->scodecs[CS8409_CODEC0]->hp_jack_in)
+ cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]);
+ break;
+ default:
+ break;
+ }
+}
+
+/******************************************************************************
+ * Dolphin Specific Functions
+ * CS8409/ 2 X CS42L42
+ ******************************************************************************/
+
+/*
+ * In the case of CS8409 we do not have unsolicited events when
+ * hs mic and hp are connected. Companion codec CS42L42 will
+ * generate interrupt via irq_mask to notify jack events. We have to overwrite
+ * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
+ * and then notify status via generic snd_hda_jack_unsol_event() call.
+ */
+static void dolphin_jack_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42;
+ struct hda_jack_tbl *jk;
+
+ cs42l42 = spec->scodecs[CS8409_CODEC0];
+ if (!cs42l42->suspended && (~res & cs42l42->irq_mask) &&
+ cs42l42_jack_unsol_event(cs42l42)) {
+ jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_HP_PIN_NID, 0);
+ if (jk)
+ snd_hda_jack_unsol_event(codec,
+ (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+ AC_UNSOL_RES_TAG);
+
+ jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_AMIC_PIN_NID, 0);
+ if (jk)
+ snd_hda_jack_unsol_event(codec,
+ (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+ AC_UNSOL_RES_TAG);
+ }
+
+ cs42l42 = spec->scodecs[CS8409_CODEC1];
+ if (!cs42l42->suspended && (~res & cs42l42->irq_mask) &&
+ cs42l42_jack_unsol_event(cs42l42)) {
+ jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_LO_PIN_NID, 0);
+ if (jk)
+ snd_hda_jack_unsol_event(codec,
+ (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
+ AC_UNSOL_RES_TAG);
+ }
+}
+
+/* Vendor specific HW configuration
+ * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
+ */
+static void dolphin_hw_init(struct hda_codec *codec)
+{
+ const struct cs8409_cir_param *seq = dolphin_hw_cfg;
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42;
+ int i;
+
+ if (spec->gpio_mask) {
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_MASK,
+ spec->gpio_mask);
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DIRECTION,
+ spec->gpio_dir);
+ snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA,
+ spec->gpio_data);
+ }
+
+ for (; seq->nid; seq++)
+ cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
+
+ for (i = 0; i < spec->num_scodecs; i++) {
+ cs42l42 = spec->scodecs[i];
+ cs42l42_resume(cs42l42);
+ }
+
+ /* Enable Unsolicited Response */
+ cs8409_enable_ur(codec, 1);
+}
+
+static const struct hda_codec_ops cs8409_dolphin_patch_ops = {
+ .build_controls = cs8409_build_controls,
+ .build_pcms = snd_hda_gen_build_pcms,
+ .init = cs8409_init,
+ .free = cs8409_free,
+ .unsol_event = dolphin_jack_unsol_event,
+#ifdef CONFIG_PM
+ .suspend = cs8409_cs42l42_suspend,
+#endif
+};
+
+static int dolphin_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+ unsigned int *res)
+{
+ struct hda_codec *codec = container_of(dev, struct hda_codec, core);
+ struct cs8409_spec *spec = codec->spec;
+ struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
+
+ unsigned int nid = ((cmd >> 20) & 0x07f);
+ unsigned int verb = ((cmd >> 8) & 0x0fff);
+
+ /* CS8409 pins have no AC_PINSENSE_PRESENCE
+ * capabilities. We have to intercept calls for CS42L42 pins
+ * and return correct pin sense values for read_pin_sense() call from
+ * hda_jack based on CS42L42 jack detect status.
+ */
+ switch (nid) {
+ case DOLPHIN_HP_PIN_NID:
+ case DOLPHIN_LO_PIN_NID:
+ if (nid == DOLPHIN_LO_PIN_NID)
+ cs42l42 = spec->scodecs[CS8409_CODEC1];
+ if (verb == AC_VERB_GET_PIN_SENSE) {
+ *res = (cs42l42->hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+ return 0;
+ }
+ break;
+ case DOLPHIN_AMIC_PIN_NID:
+ if (verb == AC_VERB_GET_PIN_SENSE) {
+ *res = (cs42l42->mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return spec->exec_verb(dev, cmd, flags, res);
+}
+
+void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action)
+{
+ struct cs8409_spec *spec = codec->spec;
+ struct snd_kcontrol_new *kctrl;
+ int i;
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ snd_hda_add_verbs(codec, dolphin_init_verbs);
+ /* verb exec op override */
+ spec->exec_verb = codec->core.exec_verb;
+ codec->core.exec_verb = dolphin_exec_verb;
+
+ spec->scodecs[CS8409_CODEC0] = &dolphin_cs42l42_0;
+ spec->scodecs[CS8409_CODEC0]->codec = codec;
+ spec->scodecs[CS8409_CODEC1] = &dolphin_cs42l42_1;
+ spec->scodecs[CS8409_CODEC1]->codec = codec;
+ spec->num_scodecs = 2;
+
+ codec->patch_ops = cs8409_dolphin_patch_ops;
+
+ /* GPIO 1,5 out, 0,4 in */
+ spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio |
+ spec->scodecs[CS8409_CODEC1]->reset_gpio;
+ spec->gpio_data = 0;
+ spec->gpio_mask = 0x03f;
+
+ /* Basic initial sequence for specific hw configuration */
+ snd_hda_sequence_write(codec, dolphin_init_verbs);
+
+ snd_hda_jack_add_kctl(codec, DOLPHIN_LO_PIN_NID, "Line Out", true,
+ SND_JACK_HEADPHONE, NULL);
+
+ cs8409_fix_caps(codec, DOLPHIN_HP_PIN_NID);
+ cs8409_fix_caps(codec, DOLPHIN_LO_PIN_NID);
+ cs8409_fix_caps(codec, DOLPHIN_AMIC_PIN_NID);
+
+ break;
+ case HDA_FIXUP_ACT_PROBE:
+ /* Fix Sample Rate to 48kHz */
+ spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
+ spec->gen.stream_analog_capture = &cs42l42_48k_pcm_analog_capture;
+ /* add hooks */
+ spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
+ spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
+ snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
+ &cs42l42_dac_volume_mixer);
+ snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume", &cs42l42_adc_volume_mixer);
+ kctrl = snd_hda_gen_add_kctl(&spec->gen, "Line Out Playback Volume",
+ &cs42l42_dac_volume_mixer);
+ /* Update Line Out kcontrol template */
+ kctrl->private_value = HDA_COMPOSE_AMP_VAL_OFS(DOLPHIN_HP_PIN_NID, 3, CS8409_CODEC1,
+ HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE;
+ cs8409_enable_ur(codec, 0);
+ snd_hda_codec_set_name(codec, "CS8409/CS42L42");
+ break;
+ case HDA_FIXUP_ACT_INIT:
+ dolphin_hw_init(codec);
+ spec->init_done = 1;
+ if (spec->init_done && spec->build_ctrl_done) {
+ for (i = 0; i < spec->num_scodecs; i++) {
+ if (!spec->scodecs[i]->hp_jack_in)
+ cs42l42_run_jack_detect(spec->scodecs[i]);
+ }
+ }
+ break;
+ case HDA_FIXUP_ACT_BUILD:
+ spec->build_ctrl_done = 1;
+ /* Run jack auto detect first time on boot
+ * after controls have been added, to check if jack has
+ * been already plugged in.
+ * Run immediately after init.
+ */
+ if (spec->init_done && spec->build_ctrl_done) {
+ for (i = 0; i < spec->num_scodecs; i++) {
+ if (!spec->scodecs[i]->hp_jack_in)
+ cs42l42_run_jack_detect(spec->scodecs[i]);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static int patch_cs8409(struct hda_codec *codec)
+{
+ int err;
+
+ if (!cs8409_alloc_spec(codec))
+ return -ENOMEM;
+
+ snd_hda_pick_fixup(codec, cs8409_models, cs8409_fixup_tbl, cs8409_fixups);
+
+ codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n", codec->fixup_id,
+ codec->bus->pci->subsystem_vendor,
+ codec->bus->pci->subsystem_device);
+
+ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
+
+ err = cs8409_parse_auto_config(codec);
+ if (err < 0) {
+ cs8409_free(codec);
+ return err;
+ }
+
+ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
+ return 0;
+}
+
+static const struct hda_device_id snd_hda_id_cs8409[] = {
+ HDA_CODEC_ENTRY(0x10138409, "CS8409", patch_cs8409),
+ {} /* terminator */
+};
+MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cs8409);
+
+static struct hda_codec_driver cs8409_driver = {
+ .id = snd_hda_id_cs8409,
+};
+module_hda_codec_driver(cs8409_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cirrus Logic HDA bridge");
diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h
new file mode 100644
index 000000000000..ade2b838590c
--- /dev/null
+++ b/sound/pci/hda/patch_cs8409.h
@@ -0,0 +1,371 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ * Cirrus Logic International Semiconductor Ltd.
+ */
+
+#ifndef __CS8409_PATCH_H
+#define __CS8409_PATCH_H
+
+#include <linux/pci.h>
+#include <sound/tlv.h>
+#include <linux/workqueue.h>
+#include <sound/hda_codec.h>
+#include "hda_local.h"
+#include "hda_auto_parser.h"
+#include "hda_jack.h"
+#include "hda_generic.h"
+
+/* CS8409 Specific Definitions */
+
+enum cs8409_pins {
+ CS8409_PIN_ROOT,
+ CS8409_PIN_AFG,
+ CS8409_PIN_ASP1_OUT_A,
+ CS8409_PIN_ASP1_OUT_B,
+ CS8409_PIN_ASP1_OUT_C,
+ CS8409_PIN_ASP1_OUT_D,
+ CS8409_PIN_ASP1_OUT_E,
+ CS8409_PIN_ASP1_OUT_F,
+ CS8409_PIN_ASP1_OUT_G,
+ CS8409_PIN_ASP1_OUT_H,
+ CS8409_PIN_ASP2_OUT_A,
+ CS8409_PIN_ASP2_OUT_B,
+ CS8409_PIN_ASP2_OUT_C,
+ CS8409_PIN_ASP2_OUT_D,
+ CS8409_PIN_ASP2_OUT_E,
+ CS8409_PIN_ASP2_OUT_F,
+ CS8409_PIN_ASP2_OUT_G,
+ CS8409_PIN_ASP2_OUT_H,
+ CS8409_PIN_ASP1_IN_A,
+ CS8409_PIN_ASP1_IN_B,
+ CS8409_PIN_ASP1_IN_C,
+ CS8409_PIN_ASP1_IN_D,
+ CS8409_PIN_ASP1_IN_E,
+ CS8409_PIN_ASP1_IN_F,
+ CS8409_PIN_ASP1_IN_G,
+ CS8409_PIN_ASP1_IN_H,
+ CS8409_PIN_ASP2_IN_A,
+ CS8409_PIN_ASP2_IN_B,
+ CS8409_PIN_ASP2_IN_C,
+ CS8409_PIN_ASP2_IN_D,
+ CS8409_PIN_ASP2_IN_E,
+ CS8409_PIN_ASP2_IN_F,
+ CS8409_PIN_ASP2_IN_G,
+ CS8409_PIN_ASP2_IN_H,
+ CS8409_PIN_DMIC1,
+ CS8409_PIN_DMIC2,
+ CS8409_PIN_ASP1_TRANSMITTER_A,
+ CS8409_PIN_ASP1_TRANSMITTER_B,
+ CS8409_PIN_ASP1_TRANSMITTER_C,
+ CS8409_PIN_ASP1_TRANSMITTER_D,
+ CS8409_PIN_ASP1_TRANSMITTER_E,
+ CS8409_PIN_ASP1_TRANSMITTER_F,
+ CS8409_PIN_ASP1_TRANSMITTER_G,
+ CS8409_PIN_ASP1_TRANSMITTER_H,
+ CS8409_PIN_ASP2_TRANSMITTER_A,
+ CS8409_PIN_ASP2_TRANSMITTER_B,
+ CS8409_PIN_ASP2_TRANSMITTER_C,
+ CS8409_PIN_ASP2_TRANSMITTER_D,
+ CS8409_PIN_ASP2_TRANSMITTER_E,
+ CS8409_PIN_ASP2_TRANSMITTER_F,
+ CS8409_PIN_ASP2_TRANSMITTER_G,
+ CS8409_PIN_ASP2_TRANSMITTER_H,
+ CS8409_PIN_ASP1_RECEIVER_A,
+ CS8409_PIN_ASP1_RECEIVER_B,
+ CS8409_PIN_ASP1_RECEIVER_C,
+ CS8409_PIN_ASP1_RECEIVER_D,
+ CS8409_PIN_ASP1_RECEIVER_E,
+ CS8409_PIN_ASP1_RECEIVER_F,
+ CS8409_PIN_ASP1_RECEIVER_G,
+ CS8409_PIN_ASP1_RECEIVER_H,
+ CS8409_PIN_ASP2_RECEIVER_A,
+ CS8409_PIN_ASP2_RECEIVER_B,
+ CS8409_PIN_ASP2_RECEIVER_C,
+ CS8409_PIN_ASP2_RECEIVER_D,
+ CS8409_PIN_ASP2_RECEIVER_E,
+ CS8409_PIN_ASP2_RECEIVER_F,
+ CS8409_PIN_ASP2_RECEIVER_G,
+ CS8409_PIN_ASP2_RECEIVER_H,
+ CS8409_PIN_DMIC1_IN,
+ CS8409_PIN_DMIC2_IN,
+ CS8409_PIN_BEEP_GEN,
+ CS8409_PIN_VENDOR_WIDGET
+};
+
+enum cs8409_coefficient_index_registers {
+ CS8409_DEV_CFG1,
+ CS8409_DEV_CFG2,
+ CS8409_DEV_CFG3,
+ CS8409_ASP1_CLK_CTRL1,
+ CS8409_ASP1_CLK_CTRL2,
+ CS8409_ASP1_CLK_CTRL3,
+ CS8409_ASP2_CLK_CTRL1,
+ CS8409_ASP2_CLK_CTRL2,
+ CS8409_ASP2_CLK_CTRL3,
+ CS8409_DMIC_CFG,
+ CS8409_BEEP_CFG,
+ ASP1_RX_NULL_INS_RMV,
+ ASP1_Rx_RATE1,
+ ASP1_Rx_RATE2,
+ ASP1_Tx_NULL_INS_RMV,
+ ASP1_Tx_RATE1,
+ ASP1_Tx_RATE2,
+ ASP2_Rx_NULL_INS_RMV,
+ ASP2_Rx_RATE1,
+ ASP2_Rx_RATE2,
+ ASP2_Tx_NULL_INS_RMV,
+ ASP2_Tx_RATE1,
+ ASP2_Tx_RATE2,
+ ASP1_SYNC_CTRL,
+ ASP2_SYNC_CTRL,
+ ASP1_A_TX_CTRL1,
+ ASP1_A_TX_CTRL2,
+ ASP1_B_TX_CTRL1,
+ ASP1_B_TX_CTRL2,
+ ASP1_C_TX_CTRL1,
+ ASP1_C_TX_CTRL2,
+ ASP1_D_TX_CTRL1,
+ ASP1_D_TX_CTRL2,
+ ASP1_E_TX_CTRL1,
+ ASP1_E_TX_CTRL2,
+ ASP1_F_TX_CTRL1,
+ ASP1_F_TX_CTRL2,
+ ASP1_G_TX_CTRL1,
+ ASP1_G_TX_CTRL2,
+ ASP1_H_TX_CTRL1,
+ ASP1_H_TX_CTRL2,
+ ASP2_A_TX_CTRL1,
+ ASP2_A_TX_CTRL2,
+ ASP2_B_TX_CTRL1,
+ ASP2_B_TX_CTRL2,
+ ASP2_C_TX_CTRL1,
+ ASP2_C_TX_CTRL2,
+ ASP2_D_TX_CTRL1,
+ ASP2_D_TX_CTRL2,
+ ASP2_E_TX_CTRL1,
+ ASP2_E_TX_CTRL2,
+ ASP2_F_TX_CTRL1,
+ ASP2_F_TX_CTRL2,
+ ASP2_G_TX_CTRL1,
+ ASP2_G_TX_CTRL2,
+ ASP2_H_TX_CTRL1,
+ ASP2_H_TX_CTRL2,
+ ASP1_A_RX_CTRL1,
+ ASP1_A_RX_CTRL2,
+ ASP1_B_RX_CTRL1,
+ ASP1_B_RX_CTRL2,
+ ASP1_C_RX_CTRL1,
+ ASP1_C_RX_CTRL2,
+ ASP1_D_RX_CTRL1,
+ ASP1_D_RX_CTRL2,
+ ASP1_E_RX_CTRL1,
+ ASP1_E_RX_CTRL2,
+ ASP1_F_RX_CTRL1,
+ ASP1_F_RX_CTRL2,
+ ASP1_G_RX_CTRL1,
+ ASP1_G_RX_CTRL2,
+ ASP1_H_RX_CTRL1,
+ ASP1_H_RX_CTRL2,
+ ASP2_A_RX_CTRL1,
+ ASP2_A_RX_CTRL2,
+ ASP2_B_RX_CTRL1,
+ ASP2_B_RX_CTRL2,
+ ASP2_C_RX_CTRL1,
+ ASP2_C_RX_CTRL2,
+ ASP2_D_RX_CTRL1,
+ ASP2_D_RX_CTRL2,
+ ASP2_E_RX_CTRL1,
+ ASP2_E_RX_CTRL2,
+ ASP2_F_RX_CTRL1,
+ ASP2_F_RX_CTRL2,
+ ASP2_G_RX_CTRL1,
+ ASP2_G_RX_CTRL2,
+ ASP2_H_RX_CTRL1,
+ ASP2_H_RX_CTRL2,
+ CS8409_I2C_ADDR,
+ CS8409_I2C_DATA,
+ CS8409_I2C_CTRL,
+ CS8409_I2C_STS,
+ CS8409_I2C_QWRITE,
+ CS8409_I2C_QREAD,
+ CS8409_SPI_CTRL,
+ CS8409_SPI_TX_DATA,
+ CS8409_SPI_RX_DATA,
+ CS8409_SPI_STS,
+ CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/
+ CS8409_PFE_COEF_W2,
+ CS8409_PFE_CTRL1,
+ CS8409_PFE_CTRL2,
+ CS8409_PRE_SCALE_ATTN1,
+ CS8409_PRE_SCALE_ATTN2,
+ CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/
+ CS8409_PFE_COEF_MON2,
+ CS8409_ASP1_INTRN_STS,
+ CS8409_ASP2_INTRN_STS,
+ CS8409_ASP1_RX_SCLK_COUNT,
+ CS8409_ASP1_TX_SCLK_COUNT,
+ CS8409_ASP2_RX_SCLK_COUNT,
+ CS8409_ASP2_TX_SCLK_COUNT,
+ CS8409_ASP_UNS_RESP_MASK,
+ CS8409_LOOPBACK_CTRL = 0x80,
+ CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */
+};
+
+/* CS42L42 Specific Definitions */
+
+#define CS8409_MAX_CODECS 8
+#define CS42L42_VOLUMES (4U)
+#define CS42L42_HP_VOL_REAL_MIN (-63)
+#define CS42L42_HP_VOL_REAL_MAX (0)
+#define CS42L42_AMIC_VOL_REAL_MIN (-97)
+#define CS42L42_AMIC_VOL_REAL_MAX (12)
+#define CS42L42_REG_HS_VOL_CHA (0x2301)
+#define CS42L42_REG_HS_VOL_CHB (0x2303)
+#define CS42L42_REG_HS_VOL_MASK (0x003F)
+#define CS42L42_REG_AMIC_VOL (0x1D03)
+#define CS42L42_REG_AMIC_VOL_MASK (0x00FF)
+#define CS42L42_HSDET_AUTO_DONE (0x02)
+#define CS42L42_HSTYPE_MASK (0x03)
+#define CS42L42_JACK_INSERTED (0x0C)
+#define CS42L42_JACK_REMOVED (0x00)
+#define CS42L42_I2C_TIMEOUT_US (20000)
+#define CS42L42_I2C_SLEEP_US (2000)
+#define CS42L42_PDN_TIMEOUT_US (250000)
+#define CS42L42_PDN_SLEEP_US (2000)
+
+/* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */
+
+#define CS42L42_I2C_ADDR (0x48 << 1)
+#define CS8409_CS42L42_RESET GENMASK(5, 5) /* CS8409_GPIO5 */
+#define CS8409_CS42L42_INT GENMASK(4, 4) /* CS8409_GPIO4 */
+#define CS8409_CS42L42_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A
+#define CS8409_CS42L42_SPK_PIN_NID CS8409_PIN_ASP2_TRANSMITTER_A
+#define CS8409_CS42L42_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A
+#define CS8409_CS42L42_DMIC_PIN_NID CS8409_PIN_DMIC1_IN
+#define CS8409_CS42L42_DMIC_ADC_PIN_NID CS8409_PIN_DMIC1
+
+/* Dolphin */
+
+#define DOLPHIN_C0_I2C_ADDR (0x48 << 1)
+#define DOLPHIN_C1_I2C_ADDR (0x49 << 1)
+#define DOLPHIN_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A
+#define DOLPHIN_LO_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_B
+#define DOLPHIN_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A
+
+#define DOLPHIN_C0_INT GENMASK(4, 4)
+#define DOLPHIN_C1_INT GENMASK(0, 0)
+#define DOLPHIN_C0_RESET GENMASK(5, 5)
+#define DOLPHIN_C1_RESET GENMASK(1, 1)
+#define DOLPHIN_WAKE (DOLPHIN_C0_INT | DOLPHIN_C1_INT)
+
+enum {
+ CS8409_BULLSEYE,
+ CS8409_WARLOCK,
+ CS8409_CYBORG,
+ CS8409_FIXUPS,
+ CS8409_DOLPHIN,
+ CS8409_DOLPHIN_FIXUPS,
+};
+
+enum {
+ CS8409_CODEC0,
+ CS8409_CODEC1
+};
+
+enum {
+ CS42L42_VOL_ADC,
+ CS42L42_VOL_DAC,
+};
+
+#define CS42L42_ADC_VOL_OFFSET (CS42L42_VOL_ADC)
+#define CS42L42_DAC_CH0_VOL_OFFSET (CS42L42_VOL_DAC)
+#define CS42L42_DAC_CH1_VOL_OFFSET (CS42L42_VOL_DAC + 1)
+
+struct cs8409_i2c_param {
+ unsigned int addr;
+ unsigned int value;
+};
+
+struct cs8409_cir_param {
+ unsigned int nid;
+ unsigned int cir;
+ unsigned int coeff;
+};
+
+struct sub_codec {
+ struct hda_codec *codec;
+ unsigned int addr;
+ unsigned int reset_gpio;
+ unsigned int irq_mask;
+ const struct cs8409_i2c_param *init_seq;
+ unsigned int init_seq_num;
+
+ unsigned int hp_jack_in:1;
+ unsigned int mic_jack_in:1;
+ unsigned int suspended:1;
+ unsigned int paged:1;
+ unsigned int last_page;
+ unsigned int hsbias_hiz;
+ unsigned int full_scale_vol:1;
+ unsigned int no_type_dect:1;
+
+ s8 vol[CS42L42_VOLUMES];
+};
+
+struct cs8409_spec {
+ struct hda_gen_spec gen;
+ struct hda_codec *codec;
+
+ struct sub_codec *scodecs[CS8409_MAX_CODECS];
+ unsigned int num_scodecs;
+
+ unsigned int gpio_mask;
+ unsigned int gpio_dir;
+ unsigned int gpio_data;
+
+ struct mutex i2c_mux;
+ unsigned int i2c_clck_enabled;
+ unsigned int dev_addr;
+ struct delayed_work i2c_clk_work;
+
+ unsigned int playback_started:1;
+ unsigned int capture_started:1;
+ unsigned int init_done:1;
+ unsigned int build_ctrl_done:1;
+
+ /* verb exec op override */
+ int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
+ unsigned int *res);
+};
+
+extern const struct snd_kcontrol_new cs42l42_dac_volume_mixer;
+extern const struct snd_kcontrol_new cs42l42_adc_volume_mixer;
+
+int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo);
+int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
+int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
+
+extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback;
+extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture;
+extern const struct snd_pci_quirk cs8409_fixup_tbl[];
+extern const struct hda_model_fixup cs8409_models[];
+extern const struct hda_fixup cs8409_fixups[];
+extern const struct hda_verb cs8409_cs42l42_init_verbs[];
+extern const struct hda_pintbl cs8409_cs42l42_pincfgs[];
+extern const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[];
+extern const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[];
+extern struct sub_codec cs8409_cs42l42_codec;
+
+extern const struct hda_verb dolphin_init_verbs[];
+extern const struct hda_pintbl dolphin_pincfgs[];
+extern const struct cs8409_cir_param dolphin_hw_cfg[];
+extern struct sub_codec dolphin_cs42l42_0;
+extern struct sub_codec dolphin_cs42l42_1;
+
+void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
+void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
+
+#endif
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index e143e69d8184..65d2c5539919 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -47,6 +47,10 @@ IS_ENABLED(CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM);
module_param(enable_silent_stream, bool, 0644);
MODULE_PARM_DESC(enable_silent_stream, "Enable Silent Stream for HDMI devices");
+static bool enable_all_pins;
+module_param(enable_all_pins, bool, 0444);
+MODULE_PARM_DESC(enable_all_pins, "Forcibly enable all pins");
+
struct hdmi_spec_per_cvt {
hda_nid_t cvt_nid;
int assigned;
@@ -1959,6 +1963,9 @@ static int hdmi_parse_codec(struct hda_codec *codec)
return -EINVAL;
}
+ if (enable_all_pins)
+ spec->force_connect = true;
+
q = snd_pci_quirk_lookup(codec->bus->pci, force_connect_list);
if (q && q->value)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 7ad689f991e7..8b7a389b6aed 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -109,7 +109,6 @@ struct alc_spec {
void (*power_hook)(struct hda_codec *codec);
#endif
void (*shutup)(struct hda_codec *codec);
- void (*reboot_notify)(struct hda_codec *codec);
int init_amp;
int codec_variant; /* flag for other variants */
@@ -897,16 +896,6 @@ static inline void alc_shutup(struct hda_codec *codec)
alc_shutup_pins(codec);
}
-static void alc_reboot_notify(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (spec && spec->reboot_notify)
- spec->reboot_notify(codec);
- else
- alc_shutup(codec);
-}
-
#define alc_free snd_hda_gen_free
#ifdef CONFIG_PM
@@ -952,7 +941,6 @@ static const struct hda_codec_ops alc_patch_ops = {
.suspend = alc_suspend,
.check_power_status = snd_hda_gen_check_power_status,
#endif
- .reboot_notify = alc_reboot_notify,
};
@@ -5773,7 +5761,6 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->reboot_notify = snd_hda_gen_reboot_notify; /* reduce noise */
spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
codec->power_save_node = 0; /* avoid click noises */
snd_hda_apply_pincfgs(codec, pincfgs);
@@ -8438,6 +8425,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x87f2, "HP ProBook 640 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x87f6, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
SND_PCI_QUIRK(0x103c, 0x8805, "HP ProBook 650 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
@@ -9521,6 +9509,16 @@ static int patch_alc269(struct hda_codec *codec)
snd_hda_pick_fixup(codec, alc269_fixup_models,
alc269_fixup_tbl, alc269_fixups);
+ /* FIXME: both TX300 and ROG Strix G17 have the same SSID, and
+ * the quirk breaks the latter (bko#214101).
+ * Clear the wrong entry.
+ */
+ if (codec->fixup_id == ALC282_FIXUP_ASUS_TX300 &&
+ codec->core.vendor_id == 0x10ec0294) {
+ codec_dbg(codec, "Clear wrong fixup for ASUS ROG Strix G17\n");
+ codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
+ }
+
snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups, true);
snd_hda_pick_pin_fixup(codec, alc269_fallback_pin_fixup_tbl, alc269_fixups, false);
snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3bd592e126a3..61df4d33c48f 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -4380,18 +4380,6 @@ static int stac_init(struct hda_codec *codec)
return 0;
}
-static void stac_shutup(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- snd_hda_shutup_pins(codec);
-
- if (spec->eapd_mask)
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data &
- ~spec->eapd_mask);
-}
-
#define stac_free snd_hda_gen_free
#ifdef CONFIG_SND_PROC_FS
@@ -4444,7 +4432,15 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
#ifdef CONFIG_PM
static int stac_suspend(struct hda_codec *codec)
{
- stac_shutup(codec);
+ struct sigmatel_spec *spec = codec->spec;
+
+ snd_hda_shutup_pins(codec);
+
+ if (spec->eapd_mask)
+ stac_gpio_set(codec, spec->gpio_mask,
+ spec->gpio_dir, spec->gpio_data &
+ ~spec->eapd_mask);
+
return 0;
}
#else
@@ -4460,7 +4456,6 @@ static const struct hda_codec_ops stac_patch_ops = {
#ifdef CONFIG_PM
.suspend = stac_suspend,
#endif
- .reboot_notify = stac_shutup,
};
static int alloc_stac_spec(struct hda_codec *codec)
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index d54cd5143e9f..a5241a287851 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2432,31 +2432,18 @@ static int snd_ice1712_build_controls(struct snd_ice1712 *ice)
snd_ctl_new1(&snd_ice1712_mixer_pro_peak, ice));
}
-static int snd_ice1712_free(struct snd_ice1712 *ice)
+static void snd_ice1712_free(struct snd_card *card)
{
- if (!ice->port)
- goto __hw_end;
+ struct snd_ice1712 *ice = card->private_data;
+
+ if (ice->card_info && ice->card_info->chip_exit)
+ ice->card_info->chip_exit(ice);
+
/* mask all interrupts */
outb(ICE1712_MULTI_CAPTURE | ICE1712_MULTI_PLAYBACK, ICEMT(ice, IRQ));
outb(0xff, ICEREG(ice, IRQMASK));
- /* --- */
-__hw_end:
- if (ice->irq >= 0)
- free_irq(ice->irq, ice);
- if (ice->port)
- pci_release_regions(ice->pci);
snd_ice1712_akm4xxx_free(ice);
- pci_disable_device(ice->pci);
- kfree(ice->spec);
- kfree(ice);
- return 0;
-}
-
-static int snd_ice1712_dev_free(struct snd_device *device)
-{
- struct snd_ice1712 *ice = device->device_data;
- return snd_ice1712_free(ice);
}
static int snd_ice1712_create(struct snd_card *card,
@@ -2464,34 +2451,22 @@ static int snd_ice1712_create(struct snd_card *card,
const char *modelname,
int omni,
int cs8427_timeout,
- int dxr_enable,
- struct snd_ice1712 **r_ice1712)
+ int dxr_enable)
{
- struct snd_ice1712 *ice;
+ struct snd_ice1712 *ice = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_ice1712_dev_free,
- };
-
- *r_ice1712 = NULL;
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 28 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
dev_err(card->dev,
"architecture does not support 28bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- ice = kzalloc(sizeof(*ice), GFP_KERNEL);
- if (ice == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
ice->omni = omni ? 1 : 0;
if (cs8427_timeout < 1)
cs8427_timeout = 1;
@@ -2523,45 +2498,29 @@ static int snd_ice1712_create(struct snd_card *card,
pci_write_config_word(ice->pci, 0x42, 0x0006);
snd_ice1712_proc_init(ice);
- card->private_data = ice;
-
err = pci_request_regions(pci, "ICE1712");
- if (err < 0) {
- kfree(ice);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
ice->port = pci_resource_start(pci, 0);
ice->ddma_port = pci_resource_start(pci, 1);
ice->dmapath_port = pci_resource_start(pci, 2);
ice->profi_port = pci_resource_start(pci, 3);
- if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, ice)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_ice1712_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, ice)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_ice1712_free(ice);
return -EIO;
}
ice->irq = pci->irq;
card->sync_irq = ice->irq;
+ card->private_free = snd_ice1712_free;
- if (snd_ice1712_read_eeprom(ice, modelname) < 0) {
- snd_ice1712_free(ice);
+ if (snd_ice1712_read_eeprom(ice, modelname) < 0)
return -EIO;
- }
- if (snd_ice1712_chip_init(ice) < 0) {
- snd_ice1712_free(ice);
+ if (snd_ice1712_chip_init(ice) < 0)
return -EIO;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops);
- if (err < 0) {
- snd_ice1712_free(ice);
- return err;
- }
- *r_ice1712 = ice;
return 0;
}
@@ -2591,34 +2550,31 @@ static int snd_ice1712_probe(struct pci_dev *pci,
}
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ sizeof(*ice), &card);
if (err < 0)
return err;
+ ice = card->private_data;
strcpy(card->driver, "ICE1712");
strcpy(card->shortname, "ICEnsemble ICE1712");
err = snd_ice1712_create(card, pci, model[dev], omni[dev],
- cs8427_timeout[dev], dxr_enable[dev], &ice);
- if (err < 0) {
- snd_card_free(card);
+ cs8427_timeout[dev], dxr_enable[dev]);
+ if (err < 0)
return err;
- }
for (tbl = card_tables; *tbl; tbl++) {
for (c = *tbl; c->subvendor; c++) {
if (c->subvendor == ice->eeprom.subvendor) {
- ice->card_info = c;
strcpy(card->shortname, c->name);
if (c->driver) /* specific driver? */
strcpy(card->driver, c->driver);
if (c->chip_init) {
err = c->chip_init(ice);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
+ ice->card_info = c;
goto __found;
}
}
@@ -2627,45 +2583,33 @@ static int snd_ice1712_probe(struct pci_dev *pci,
__found:
err = snd_ice1712_pcm_profi(ice, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
if (ice_has_con_ac97(ice)) {
err = snd_ice1712_pcm(ice, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
err = snd_ice1712_ac97_mixer(ice);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_ice1712_build_controls(ice);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
if (c->build_controls) {
err = c->build_controls(ice);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
if (ice_has_con_ac97(ice)) {
err = snd_ice1712_pcm_ds(ice, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
if (!c->no_mpu401) {
@@ -2674,10 +2618,8 @@ static int snd_ice1712_probe(struct pci_dev *pci,
c->mpu401_1_info_flags |
MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
-1, &ice->rmidi[0]);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
if (c->mpu401_1_name)
/* Preferred name available in card_info */
snprintf(ice->rmidi[0]->name,
@@ -2692,10 +2634,8 @@ static int snd_ice1712_probe(struct pci_dev *pci,
MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
-1, &ice->rmidi[1]);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
if (c->mpu401_2_name)
/* Preferred name available in card_info */
snprintf(ice->rmidi[1]->name,
@@ -2711,25 +2651,13 @@ static int snd_ice1712_probe(struct pci_dev *pci,
card->shortname, ice->port, ice->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_ice1712_remove(struct pci_dev *pci)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct snd_ice1712 *ice = card->private_data;
-
- if (ice->card_info && ice->card_info->chip_exit)
- ice->card_info->chip_exit(ice);
- snd_card_free(card);
-}
-
#ifdef CONFIG_PM_SLEEP
static int snd_ice1712_suspend(struct device *dev)
{
@@ -2810,7 +2738,6 @@ static struct pci_driver ice1712_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ice1712_ids,
.probe = snd_ice1712_probe,
- .remove = snd_ice1712_remove,
.driver = {
.pm = SND_VT1712_PM_OPS,
},
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index ef2367d86148..f6275868877a 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2151,13 +2151,6 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak = {
};
/*
- *
- */
-
-static const struct snd_ice1712_card_info no_matched;
-
-
-/*
ooAoo cards with no controls
*/
static const unsigned char ooaoo_sq210_eeprom[] = {
@@ -2454,54 +2447,29 @@ static int snd_vt1724_build_controls(struct snd_ice1712 *ice)
snd_ctl_new1(&snd_vt1724_mixer_pro_peak, ice));
}
-static int snd_vt1724_free(struct snd_ice1712 *ice)
+static void snd_vt1724_free(struct snd_card *card)
{
- if (!ice->port)
- goto __hw_end;
+ struct snd_ice1712 *ice = card->private_data;
+
/* mask all interrupts */
outb(0xff, ICEMT1724(ice, DMA_INT_MASK));
outb(0xff, ICEREG1724(ice, IRQMASK));
- /* --- */
-__hw_end:
- if (ice->irq >= 0)
- free_irq(ice->irq, ice);
- pci_release_regions(ice->pci);
- snd_ice1712_akm4xxx_free(ice);
- pci_disable_device(ice->pci);
- kfree(ice->spec);
- kfree(ice);
- return 0;
-}
-static int snd_vt1724_dev_free(struct snd_device *device)
-{
- struct snd_ice1712 *ice = device->device_data;
- return snd_vt1724_free(ice);
+ snd_ice1712_akm4xxx_free(ice);
}
static int snd_vt1724_create(struct snd_card *card,
struct pci_dev *pci,
- const char *modelname,
- struct snd_ice1712 **r_ice1712)
+ const char *modelname)
{
- struct snd_ice1712 *ice;
+ struct snd_ice1712 *ice = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_vt1724_dev_free,
- };
-
- *r_ice1712 = NULL;
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- ice = kzalloc(sizeof(*ice), GFP_KERNEL);
- if (ice == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
ice->vt1724 = 1;
spin_lock_init(&ice->reg_lock);
mutex_init(&ice->gpio_mutex);
@@ -2519,44 +2487,28 @@ static int snd_vt1724_create(struct snd_card *card,
pci_set_master(pci);
snd_vt1724_proc_init(ice);
- card->private_data = ice;
-
err = pci_request_regions(pci, "ICE1724");
- if (err < 0) {
- kfree(ice);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
ice->port = pci_resource_start(pci, 0);
ice->profi_port = pci_resource_start(pci, 1);
- if (request_irq(pci->irq, snd_vt1724_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, ice)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_vt1724_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, ice)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_vt1724_free(ice);
return -EIO;
}
ice->irq = pci->irq;
card->sync_irq = ice->irq;
+ card->private_free = snd_vt1724_free;
snd_vt1724_chip_reset(ice);
- if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
- snd_vt1724_free(ice);
+ if (snd_vt1724_read_eeprom(ice, modelname) < 0)
return -EIO;
- }
- if (snd_vt1724_chip_init(ice) < 0) {
- snd_vt1724_free(ice);
+ if (snd_vt1724_chip_init(ice) < 0)
return -EIO;
- }
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops);
- if (err < 0) {
- snd_vt1724_free(ice);
- return err;
- }
-
- *r_ice1712 = ice;
return 0;
}
@@ -2574,7 +2526,7 @@ static int snd_vt1724_probe(struct pci_dev *pci,
struct snd_card *card;
struct snd_ice1712 *ice;
int pcm_dev = 0, err;
- const struct snd_ice1712_card_info * const *tbl, *c;
+ const struct snd_ice1712_card_info *c;
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -2583,44 +2535,34 @@ static int snd_vt1724_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*ice), &card);
if (err < 0)
return err;
+ ice = card->private_data;
strcpy(card->driver, "ICE1724");
strcpy(card->shortname, "ICEnsemble ICE1724");
- err = snd_vt1724_create(card, pci, model[dev], &ice);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_vt1724_create(card, pci, model[dev]);
+ if (err < 0)
return err;
- }
/* field init before calling chip_init */
ice->ext_clock_count = 0;
- for (tbl = card_tables; *tbl; tbl++) {
- for (c = *tbl; c->name; c++) {
- if ((model[dev] && c->model &&
- !strcmp(model[dev], c->model)) ||
- (c->subvendor == ice->eeprom.subvendor)) {
- strcpy(card->shortname, c->name);
- if (c->driver) /* specific driver? */
- strcpy(card->driver, c->driver);
- if (c->chip_init) {
- err = c->chip_init(ice);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
- }
- goto __found;
- }
+ c = ice->card_info;
+ if (c) {
+ strcpy(card->shortname, c->name);
+ if (c->driver) /* specific driver? */
+ strcpy(card->driver, c->driver);
+ if (c->chip_init) {
+ err = c->chip_init(ice);
+ if (err < 0)
+ return err;
}
}
- c = &no_matched;
-__found:
+
/*
* VT1724 has separate DMAs for the analog and the SPDIF streams while
* ICE1712 has only one for both (mixed up).
@@ -2651,60 +2593,44 @@ __found:
set_std_hw_rates(ice);
err = snd_vt1724_pcm_profi(ice, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_vt1724_pcm_spdif(ice, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_vt1724_pcm_indep(ice, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_vt1724_ac97_mixer(ice);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_vt1724_build_controls(ice);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
if (ice->pcm && ice->has_spdif) { /* has SPDIF I/O */
err = snd_vt1724_spdif_build_controls(ice);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
- if (c->build_controls) {
+ if (c && c->build_controls) {
err = c->build_controls(ice);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
- if (!c->no_mpu401) {
+ if (!c || !c->no_mpu401) {
if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
struct snd_rawmidi *rmidi;
err = snd_rawmidi_new(card, "MIDI", 0, 1, 1, &rmidi);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
ice->rmidi[0] = rmidi;
rmidi->private_data = ice;
strcpy(rmidi->name, "ICE1724 MIDI");
@@ -2729,25 +2655,13 @@ __found:
card->shortname, ice->port, ice->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_vt1724_remove(struct pci_dev *pci)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct snd_ice1712 *ice = card->private_data;
-
- if (ice->card_info && ice->card_info->chip_exit)
- ice->card_info->chip_exit(ice);
- snd_card_free(card);
-}
-
#ifdef CONFIG_PM_SLEEP
static int snd_vt1724_suspend(struct device *dev)
{
@@ -2825,7 +2739,6 @@ static struct pci_driver vt1724_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vt1724_ids,
.probe = snd_vt1724_probe,
- .remove = snd_vt1724_remove,
.driver = {
.pm = SND_VT1724_PM_OPS,
},
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index df3ba5c70de9..a51032b3ac4d 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -378,7 +378,7 @@ struct intel8x0 {
spinlock_t reg_lock;
u32 bdbars_count;
- struct snd_dma_buffer bdbars;
+ struct snd_dma_buffer *bdbars;
u32 int_sta_reg; /* interrupt status register */
u32 int_sta_mask; /* interrupt status mask */
};
@@ -1427,7 +1427,7 @@ struct ich_pcm_table {
};
#define intel8x0_dma_type(chip) \
- ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_UC : SNDRV_DMA_TYPE_DEV)
+ ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_WC : SNDRV_DMA_TYPE_DEV)
static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
const struct ich_pcm_table *rec)
@@ -2528,8 +2528,9 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing)
return 0;
}
-static int snd_intel8x0_free(struct intel8x0 *chip)
+static void snd_intel8x0_free(struct snd_card *card)
{
+ struct intel8x0 *chip = card->private_data;
unsigned int i;
if (chip->irq < 0)
@@ -2552,16 +2553,6 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
__hw_end:
if (chip->irq >= 0)
free_irq(chip->irq, chip);
- if (chip->bdbars.area)
- snd_dma_free_pages(&chip->bdbars);
- if (chip->addr)
- pci_iounmap(chip->pci, chip->addr);
- if (chip->bmaddr)
- pci_iounmap(chip->pci, chip->bmaddr);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -2656,6 +2647,8 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
if (chip->ac97_bus->clock != 48000)
return; /* specified in module option */
+ if (chip->inside_vm && !ac97_clock)
+ return; /* no measurement on VM */
__again:
subs = chip->pcm[0]->streams[0].substream;
@@ -2829,12 +2822,6 @@ static void snd_intel8x0_proc_init(struct intel8x0 *chip)
snd_intel8x0_proc_read);
}
-static int snd_intel8x0_dev_free(struct snd_device *device)
-{
- struct intel8x0 *chip = device->device_data;
- return snd_intel8x0_free(chip);
-}
-
struct ich_reg_info {
unsigned int int_sta_mask;
unsigned int offset;
@@ -2878,19 +2865,15 @@ fini:
return result;
}
-static int snd_intel8x0_create(struct snd_card *card,
- struct pci_dev *pci,
- unsigned long device_type,
- struct intel8x0 **r_intel8x0)
+static int snd_intel8x0_init(struct snd_card *card,
+ struct pci_dev *pci,
+ unsigned long device_type)
{
- struct intel8x0 *chip;
+ struct intel8x0 *chip = card->private_data;
int err;
unsigned int i;
unsigned int int_sta_masks;
struct ichdev *ichdev;
- static const struct snd_device_ops ops = {
- .dev_free = snd_intel8x0_dev_free,
- };
static const unsigned int bdbars[] = {
3, /* DEVICE_INTEL */
@@ -2923,17 +2906,10 @@ static int snd_intel8x0_create(struct snd_card *card,
};
const struct ich_reg_info *tbl;
- *r_intel8x0 = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
spin_lock_init(&chip->reg_lock);
chip->device_type = device_type;
chip->card = card;
@@ -2959,38 +2935,23 @@ static int snd_intel8x0_create(struct snd_card *card,
chip->fix_nocache = 1; /* enable workaround */
err = pci_request_regions(pci, card->shortname);
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
if (device_type == DEVICE_ALI) {
/* ALI5455 has no ac97 region */
- chip->bmaddr = pci_iomap(pci, 0, 0);
- goto port_inited;
- }
-
- if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
- chip->addr = pci_iomap(pci, 2, 0);
- else
- chip->addr = pci_iomap(pci, 0, 0);
- if (!chip->addr) {
- dev_err(card->dev, "AC'97 space ioremap problem\n");
- snd_intel8x0_free(chip);
- return -EIO;
+ chip->bmaddr = pcim_iomap(pci, 0, 0);
+ } else {
+ if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+ chip->addr = pcim_iomap(pci, 2, 0);
+ else
+ chip->addr = pcim_iomap(pci, 0, 0);
+ if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+ chip->bmaddr = pcim_iomap(pci, 3, 0);
+ else
+ chip->bmaddr = pcim_iomap(pci, 1, 0);
}
- if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
- chip->bmaddr = pci_iomap(pci, 3, 0);
- else
- chip->bmaddr = pci_iomap(pci, 1, 0);
- port_inited:
- if (!chip->bmaddr) {
- dev_err(card->dev, "Controller space ioremap problem\n");
- snd_intel8x0_free(chip);
- return -EIO;
- }
chip->bdbars_count = bdbars[device_type];
/* initialize offsets */
@@ -3026,21 +2987,20 @@ static int snd_intel8x0_create(struct snd_card *card,
/* allocate buffer descriptor lists */
/* the start of each lists must be aligned to 8 bytes */
- if (snd_dma_alloc_pages(intel8x0_dma_type(chip), &pci->dev,
- chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
- &chip->bdbars) < 0) {
- snd_intel8x0_free(chip);
- dev_err(card->dev, "cannot allocate buffer descriptors\n");
+ chip->bdbars = snd_devm_alloc_pages(&pci->dev, intel8x0_dma_type(chip),
+ chip->bdbars_count * sizeof(u32) *
+ ICH_MAX_FRAGS * 2);
+ if (!chip->bdbars)
return -ENOMEM;
- }
+
/* tables must be aligned to 8 bytes here, but the kernel pages
are much bigger, so we don't care (on i386) */
int_sta_masks = 0;
for (i = 0; i < chip->bdbars_count; i++) {
ichdev = &chip->ichd[i];
- ichdev->bdbar = ((__le32 *)chip->bdbars.area) +
+ ichdev->bdbar = ((__le32 *)chip->bdbars->area) +
(i * ICH_MAX_FRAGS * 2);
- ichdev->bdbar_addr = chip->bdbars.addr +
+ ichdev->bdbar_addr = chip->bdbars->addr +
(i * sizeof(u32) * ICH_MAX_FRAGS * 2);
int_sta_masks |= ichdev->int_sta_mask;
}
@@ -3074,28 +3034,24 @@ static int snd_intel8x0_create(struct snd_card *card,
chip->codec_isr_bits |= chip->codec_bit[i];
err = snd_intel8x0_chip_init(chip, 1);
- if (err < 0) {
- snd_intel8x0_free(chip);
+ if (err < 0)
return err;
- }
/* request irq after initializaing int_sta_mask, etc */
+ /* NOTE: we don't use devm version here since it's released /
+ * re-acquired in PM callbacks.
+ * It's released explicitly in snd_intel8x0_free(), too.
+ */
if (request_irq(pci->irq, snd_intel8x0_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_intel8x0_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_intel8x0_free(chip);
- return err;
- }
+ card->private_free = snd_intel8x0_free;
- *r_intel8x0 = chip;
return 0;
}
@@ -3161,9 +3117,11 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
int err;
struct shortname_table *name;
- err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
if (spdif_aclink < 0)
spdif_aclink = check_default_spdif_aclink(pci);
@@ -3197,23 +3155,16 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
buggy_irq = 0;
}
- err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_intel8x0_init(card, pci, pci_id->driver_data);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_intel8x0_pcm(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
snd_intel8x0_proc_init(chip);
@@ -3231,24 +3182,17 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
}
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
+
pci_set_drvdata(pci, card);
return 0;
}
-static void snd_intel8x0_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver intel8x0_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_intel8x0_ids,
.probe = snd_intel8x0_probe,
- .remove = snd_intel8x0_remove,
.driver = {
.pm = INTEL8X0_PM_OPS,
},
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index b96fce6cbd83..7de3cb2f17b5 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -182,7 +182,7 @@ struct intel8x0m {
spinlock_t reg_lock;
- struct snd_dma_buffer bdbars;
+ struct snd_dma_buffer *bdbars;
u32 bdbars_count;
u32 int_sta_reg; /* interrupt status register */
u32 int_sta_mask; /* interrupt status mask */
@@ -947,8 +947,9 @@ static int snd_intel8x0m_chip_init(struct intel8x0m *chip, int probing)
return 0;
}
-static int snd_intel8x0m_free(struct intel8x0m *chip)
+static void snd_intel8x0m_free(struct snd_card *card)
{
+ struct intel8x0m *chip = card->private_data;
unsigned int i;
if (chip->irq < 0)
@@ -962,16 +963,6 @@ static int snd_intel8x0m_free(struct intel8x0m *chip)
__hw_end:
if (chip->irq >= 0)
free_irq(chip->irq, chip);
- if (chip->bdbars.area)
- snd_dma_free_pages(&chip->bdbars);
- if (chip->addr)
- pci_iounmap(chip->pci, chip->addr);
- if (chip->bmaddr)
- pci_iounmap(chip->pci, chip->bmaddr);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1047,47 +1038,30 @@ static void snd_intel8x0m_proc_init(struct intel8x0m *chip)
snd_intel8x0m_proc_read);
}
-static int snd_intel8x0m_dev_free(struct snd_device *device)
-{
- struct intel8x0m *chip = device->device_data;
- return snd_intel8x0m_free(chip);
-}
-
struct ich_reg_info {
unsigned int int_sta_mask;
unsigned int offset;
};
-static int snd_intel8x0m_create(struct snd_card *card,
- struct pci_dev *pci,
- unsigned long device_type,
- struct intel8x0m **r_intel8x0m)
+static int snd_intel8x0m_init(struct snd_card *card,
+ struct pci_dev *pci,
+ unsigned long device_type)
{
- struct intel8x0m *chip;
+ struct intel8x0m *chip = card->private_data;
int err;
unsigned int i;
unsigned int int_sta_masks;
struct ichdev *ichdev;
- static const struct snd_device_ops ops = {
- .dev_free = snd_intel8x0m_dev_free,
- };
static const struct ich_reg_info intel_regs[2] = {
{ ICH_MIINT, 0 },
{ ICH_MOINT, 0x10 },
};
const struct ich_reg_info *tbl;
- *r_intel8x0m = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
spin_lock_init(&chip->reg_lock);
chip->device_type = device_type;
chip->card = card;
@@ -1095,37 +1069,21 @@ static int snd_intel8x0m_create(struct snd_card *card,
chip->irq = -1;
err = pci_request_regions(pci, card->shortname);
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
if (device_type == DEVICE_ALI) {
/* ALI5455 has no ac97 region */
- chip->bmaddr = pci_iomap(pci, 0, 0);
- goto port_inited;
- }
-
- if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
- chip->addr = pci_iomap(pci, 2, 0);
- else
- chip->addr = pci_iomap(pci, 0, 0);
- if (!chip->addr) {
- dev_err(card->dev, "AC'97 space ioremap problem\n");
- snd_intel8x0m_free(chip);
- return -EIO;
- }
- if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
- chip->bmaddr = pci_iomap(pci, 3, 0);
- else
- chip->bmaddr = pci_iomap(pci, 1, 0);
-
-port_inited:
- if (!chip->bmaddr) {
- dev_err(card->dev, "Controller space ioremap problem\n");
- snd_intel8x0m_free(chip);
- return -EIO;
+ chip->bmaddr = pcim_iomap(pci, 0, 0);
+ } else {
+ if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+ chip->addr = pcim_iomap(pci, 2, 0);
+ else
+ chip->addr = pcim_iomap(pci, 0, 0);
+ if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+ chip->bmaddr = pcim_iomap(pci, 3, 0);
+ else
+ chip->bmaddr = pcim_iomap(pci, 1, 0);
}
/* initialize offsets */
@@ -1153,19 +1111,19 @@ port_inited:
/* allocate buffer descriptor lists */
/* the start of each lists must be aligned to 8 bytes */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
- &chip->bdbars) < 0) {
- snd_intel8x0m_free(chip);
+ chip->bdbars = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+ chip->bdbars_count * sizeof(u32) *
+ ICH_MAX_FRAGS * 2);
+ if (!chip->bdbars)
return -ENOMEM;
- }
+
/* tables must be aligned to 8 bytes here, but the kernel pages
are much bigger, so we don't care (on i386) */
int_sta_masks = 0;
for (i = 0; i < chip->bdbars_count; i++) {
ichdev = &chip->ichd[i];
- ichdev->bdbar = ((__le32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2);
- ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
+ ichdev->bdbar = ((__le32 *)chip->bdbars->area) + (i * ICH_MAX_FRAGS * 2);
+ ichdev->bdbar_addr = chip->bdbars->addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
int_sta_masks |= ichdev->int_sta_mask;
}
chip->int_sta_reg = ICH_REG_GLOB_STA;
@@ -1174,27 +1132,23 @@ port_inited:
pci_set_master(pci);
err = snd_intel8x0m_chip_init(chip, 1);
- if (err < 0) {
- snd_intel8x0m_free(chip);
+ if (err < 0)
return err;
- }
+ /* NOTE: we don't use devm version here since it's released /
+ * re-acquired in PM callbacks.
+ * It's released explicitly in snd_intel8x0m_free(), too.
+ */
if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED,
KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_intel8x0m_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_intel8x0m_free(chip);
- return err;
- }
+ card->private_free = snd_intel8x0m_free;
- *r_intel8x0m = chip;
return 0;
}
@@ -1232,9 +1186,11 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
int err;
struct shortname_table *name;
- err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
strcpy(card->driver, "ICH-MODEM");
strcpy(card->shortname, "Intel ICH");
@@ -1246,23 +1202,16 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
}
strcat(card->shortname," Modem");
- err = snd_intel8x0m_create(card, pci, pci_id->driver_data, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_intel8x0m_init(card, pci, pci_id->driver_data);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
err = snd_intel8x0m_mixer(chip, ac97_clock);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_intel8x0m_pcm(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
snd_intel8x0m_proc_init(chip);
@@ -1270,24 +1219,16 @@ static int snd_intel8x0m_probe(struct pci_dev *pci,
card->shortname, chip->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
return 0;
}
-static void snd_intel8x0m_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver intel8x0m_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_intel8x0m_ids,
.probe = snd_intel8x0m_probe,
- .remove = snd_intel8x0m_remove,
.driver = {
.pm = INTEL8X0M_PM_OPS,
},
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 030e01b062e4..5c9e240ff6a9 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -320,10 +320,10 @@ struct snd_korg1212 {
unsigned long inIRQ;
void __iomem *iobase;
- struct snd_dma_buffer dma_dsp;
- struct snd_dma_buffer dma_play;
- struct snd_dma_buffer dma_rec;
- struct snd_dma_buffer dma_shared;
+ struct snd_dma_buffer *dma_dsp;
+ struct snd_dma_buffer *dma_play;
+ struct snd_dma_buffer *dma_rec;
+ struct snd_dma_buffer *dma_shared;
u32 DataBufsSize;
@@ -1200,8 +1200,8 @@ static int snd_korg1212_downloadDSPCode(struct snd_korg1212 *korg1212)
snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS);
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload,
- UpperWordSwap(korg1212->dma_dsp.addr),
- 0, 0, 0);
+ UpperWordSwap(korg1212->dma_dsp->addr),
+ 0, 0, 0);
if (rc)
K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n",
rc, stateName[korg1212->cardState]);
@@ -1382,7 +1382,7 @@ static int snd_korg1212_playback_open(struct snd_pcm_substream *substream)
snd_korg1212_OpenCard(korg1212);
runtime->hw = snd_korg1212_playback_info;
- snd_pcm_set_runtime_buffer(substream, &korg1212->dma_play);
+ snd_pcm_set_runtime_buffer(substream, korg1212->dma_play);
spin_lock_irqsave(&korg1212->lock, flags);
@@ -1413,7 +1413,7 @@ static int snd_korg1212_capture_open(struct snd_pcm_substream *substream)
snd_korg1212_OpenCard(korg1212);
runtime->hw = snd_korg1212_capture_info;
- snd_pcm_set_runtime_buffer(substream, &korg1212->dma_rec);
+ snd_pcm_set_runtime_buffer(substream, korg1212->dma_rec);
spin_lock_irqsave(&korg1212->lock, flags);
@@ -2080,96 +2080,30 @@ static void snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
snd_korg1212_proc_read);
}
-static int
-snd_korg1212_free(struct snd_korg1212 *korg1212)
+static void
+snd_korg1212_free(struct snd_card *card)
{
- snd_korg1212_TurnOffIdleMonitor(korg1212);
-
- if (korg1212->irq >= 0) {
- snd_korg1212_DisableCardInterrupts(korg1212);
- free_irq(korg1212->irq, korg1212);
- korg1212->irq = -1;
- }
-
- if (korg1212->iobase != NULL) {
- iounmap(korg1212->iobase);
- korg1212->iobase = NULL;
- }
-
- pci_release_regions(korg1212->pci);
-
- // ----------------------------------------------------
- // free up memory resources used for the DSP download.
- // ----------------------------------------------------
- if (korg1212->dma_dsp.area) {
- snd_dma_free_pages(&korg1212->dma_dsp);
- korg1212->dma_dsp.area = NULL;
- }
-
-#ifndef K1212_LARGEALLOC
-
- // ------------------------------------------------------
- // free up memory resources used for the Play/Rec Buffers
- // ------------------------------------------------------
- if (korg1212->dma_play.area) {
- snd_dma_free_pages(&korg1212->dma_play);
- korg1212->dma_play.area = NULL;
- }
+ struct snd_korg1212 *korg1212 = card->private_data;
- if (korg1212->dma_rec.area) {
- snd_dma_free_pages(&korg1212->dma_rec);
- korg1212->dma_rec.area = NULL;
- }
-
-#endif
-
- // ----------------------------------------------------
- // free up memory resources used for the Shared Buffers
- // ----------------------------------------------------
- if (korg1212->dma_shared.area) {
- snd_dma_free_pages(&korg1212->dma_shared);
- korg1212->dma_shared.area = NULL;
- }
-
- pci_disable_device(korg1212->pci);
- kfree(korg1212);
- return 0;
+ snd_korg1212_TurnOffIdleMonitor(korg1212);
+ snd_korg1212_DisableCardInterrupts(korg1212);
}
-static int snd_korg1212_dev_free(struct snd_device *device)
-{
- struct snd_korg1212 *korg1212 = device->device_data;
- K1212_DEBUG_PRINTK("K1212_DEBUG: Freeing device\n");
- return snd_korg1212_free(korg1212);
-}
-
-static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
- struct snd_korg1212 **rchip)
+static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
{
int err, rc;
unsigned int i;
- unsigned iomem_size;
+ __maybe_unused unsigned iomem_size;
__maybe_unused unsigned ioport_size;
__maybe_unused unsigned iomem2_size;
- struct snd_korg1212 * korg1212;
+ struct snd_korg1212 *korg1212 = card->private_data;
const struct firmware *dsp_code;
- static const struct snd_device_ops ops = {
- .dev_free = snd_korg1212_dev_free,
- };
-
- * rchip = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL);
- if (korg1212 == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
korg1212->card = card;
korg1212->pci = pci;
@@ -2198,12 +2132,9 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
for (i=0; i<kAudioChannels; i++)
korg1212->volumePhase[i] = 0;
- err = pci_request_regions(pci, "korg1212");
- if (err < 0) {
- kfree(korg1212);
- pci_disable_device(pci);
+ err = pcim_iomap_regions_request_all(pci, 1 << 0, "korg1212");
+ if (err < 0)
return err;
- }
korg1212->iomem = pci_resource_start(korg1212->pci, 0);
korg1212->ioport = pci_resource_start(korg1212->pci, 1);
@@ -2223,26 +2154,20 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
korg1212->iomem2, iomem2_size,
stateName[korg1212->cardState]);
- korg1212->iobase = ioremap(korg1212->iomem, iomem_size);
- if (!korg1212->iobase) {
- snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
- korg1212->iomem + iomem_size - 1);
- snd_korg1212_free(korg1212);
- return -EBUSY;
- }
+ korg1212->iobase = pcim_iomap_table(pci)[0];
- err = request_irq(pci->irq, snd_korg1212_interrupt,
+ err = devm_request_irq(&pci->dev, pci->irq, snd_korg1212_interrupt,
IRQF_SHARED,
KBUILD_MODNAME, korg1212);
if (err) {
snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq);
- snd_korg1212_free(korg1212);
return -EBUSY;
}
korg1212->irq = pci->irq;
card->sync_irq = korg1212->irq;
+ card->private_free = snd_korg1212_free;
pci_set_master(korg1212->pci);
@@ -2281,41 +2206,36 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
korg1212->idRegPtr,
stateName[korg1212->cardState]);
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- sizeof(struct KorgSharedBuffer), &korg1212->dma_shared) < 0) {
- snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%zd bytes)\n", sizeof(struct KorgSharedBuffer));
- snd_korg1212_free(korg1212);
- return -ENOMEM;
- }
- korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared.area;
- korg1212->sharedBufferPhy = korg1212->dma_shared.addr;
+ korg1212->dma_shared = snd_devm_alloc_pages(&pci->dev,
+ SNDRV_DMA_TYPE_DEV,
+ sizeof(struct KorgSharedBuffer));
+ if (!korg1212->dma_shared)
+ return -ENOMEM;
+ korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared->area;
+ korg1212->sharedBufferPhy = korg1212->dma_shared->addr;
K1212_DEBUG_PRINTK("K1212_DEBUG: Shared Buffer Area = 0x%p (0x%08lx), %d bytes\n", korg1212->sharedBufferPtr, korg1212->sharedBufferPhy, sizeof(struct KorgSharedBuffer));
#ifndef K1212_LARGEALLOC
-
korg1212->DataBufsSize = sizeof(struct KorgAudioBuffer) * kNumBuffers;
+ korg1212->dma_play = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+ korg1212->DataBufsSize);
+ if (!korg1212->dma_play)
+ return -ENOMEM;
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
- snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
- snd_korg1212_free(korg1212);
- return -ENOMEM;
- }
- korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play.area;
- korg1212->PlayDataPhy = korg1212->dma_play.addr;
+ korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play->area;
+ korg1212->PlayDataPhy = korg1212->dma_play->addr;
K1212_DEBUG_PRINTK("K1212_DEBUG: Play Data Area = 0x%p (0x%08x), %d bytes\n",
korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize);
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
- snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
- snd_korg1212_free(korg1212);
- return -ENOMEM;
- }
- korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec.area;
- korg1212->RecDataPhy = korg1212->dma_rec.addr;
+ korg1212->dma_rec = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+ korg1212->DataBufsSize);
+ if (!korg1212->dma_rec)
+ return -ENOMEM;
+
+ korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec->area;
+ korg1212->RecDataPhy = korg1212->dma_rec->addr;
K1212_DEBUG_PRINTK("K1212_DEBUG: Record Data Area = 0x%p (0x%08x), %d bytes\n",
korg1212->recordDataBufsPtr, korg1212->RecDataPhy, korg1212->DataBufsSize);
@@ -2339,23 +2259,21 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev);
if (err < 0) {
snd_printk(KERN_ERR "firmware not available\n");
- snd_korg1212_free(korg1212);
return err;
}
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
- dsp_code->size, &korg1212->dma_dsp) < 0) {
- snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size);
- snd_korg1212_free(korg1212);
+ korg1212->dma_dsp = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
+ dsp_code->size);
+ if (!korg1212->dma_dsp) {
release_firmware(dsp_code);
- return -ENOMEM;
- }
+ return -ENOMEM;
+ }
K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n",
- korg1212->dma_dsp.area, korg1212->dma_dsp.addr, dsp_code->size,
+ korg1212->dma_dsp->area, korg1212->dma_dsp->addr, dsp_code->size,
stateName[korg1212->cardState]);
- memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size);
+ memcpy(korg1212->dma_dsp->area, dsp_code->data, dsp_code->size);
release_firmware(dsp_code);
@@ -2364,12 +2282,6 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
if (rc)
K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, korg1212, &ops);
- if (err < 0) {
- snd_korg1212_free(korg1212);
- return err;
- }
-
snd_korg1212_EnableCardInterrupts(korg1212);
mdelay(CARD_BOOT_DELAY_IN_MS);
@@ -2411,10 +2323,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
}
snd_korg1212_proc_init(korg1212);
-
- * rchip = korg1212;
- return 0;
+ return 0;
}
/*
@@ -2437,16 +2347,15 @@ snd_korg1212_probe(struct pci_dev *pci,
dev++;
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*korg1212), &card);
if (err < 0)
return err;
+ korg1212 = card->private_data;
- err = snd_korg1212_create(card, pci, &korg1212);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_korg1212_create(card, pci);
+ if (err < 0)
return err;
- }
strcpy(card->driver, "korg1212");
strcpy(card->shortname, "korg1212");
@@ -2456,25 +2365,17 @@ snd_korg1212_probe(struct pci_dev *pci,
K1212_DEBUG_PRINTK("K1212_DEBUG: %s\n", card->longname);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_korg1212_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver korg1212_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_korg1212_ids,
.probe = snd_korg1212_probe,
- .remove = snd_korg1212_remove,
};
module_pci_driver(korg1212_driver);
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 03b4be44bb26..5269a1d396a5 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -344,20 +344,18 @@ static void lola_irq_disable(struct lola *chip)
static int setup_corb_rirb(struct lola *chip)
{
- int err;
unsigned char tmp;
unsigned long end_time;
- err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
- &chip->pci->dev,
- PAGE_SIZE, &chip->rb);
- if (err < 0)
- return err;
+ chip->rb = snd_devm_alloc_pages(&chip->pci->dev, SNDRV_DMA_TYPE_DEV,
+ PAGE_SIZE);
+ if (!chip->rb)
+ return -ENOMEM;
- chip->corb.addr = chip->rb.addr;
- chip->corb.buf = (__le32 *)chip->rb.area;
- chip->rirb.addr = chip->rb.addr + 2048;
- chip->rirb.buf = (__le32 *)(chip->rb.area + 2048);
+ chip->corb.addr = chip->rb->addr;
+ chip->corb.buf = (__le32 *)chip->rb->area;
+ chip->rirb.addr = chip->rb->addr + 2048;
+ chip->rirb.buf = (__le32 *)(chip->rb->area + 2048);
/* disable ringbuffer DMAs */
lola_writeb(chip, BAR0, RIRBCTL, 0);
@@ -529,56 +527,31 @@ static void lola_stop_hw(struct lola *chip)
lola_irq_disable(chip);
}
-static void lola_free(struct lola *chip)
+static void lola_free(struct snd_card *card)
{
+ struct lola *chip = card->private_data;
+
if (chip->initialized)
lola_stop_hw(chip);
- lola_free_pcm(chip);
lola_free_mixer(chip);
- if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
- iounmap(chip->bar[0].remap_addr);
- iounmap(chip->bar[1].remap_addr);
- if (chip->rb.area)
- snd_dma_free_pages(&chip->rb);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
}
-static int lola_dev_free(struct snd_device *device)
+static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
{
- lola_free(device->device_data);
- return 0;
-}
-
-static int lola_create(struct snd_card *card, struct pci_dev *pci,
- int dev, struct lola **rchip)
-{
- struct lola *chip;
+ struct lola *chip = card->private_data;
int err;
unsigned int dever;
- static const struct snd_device_ops ops = {
- .dev_free = lola_dev_free,
- };
- *rchip = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
spin_lock_init(&chip->reg_lock);
mutex_init(&chip->open_mutex);
chip->card = card;
chip->pci = pci;
chip->irq = -1;
+ card->private_free = lola_free;
chip->granularity = granularity[dev];
switch (chip->granularity) {
@@ -607,34 +580,25 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
chip->sample_rate_min = 16000;
}
- err = pci_request_regions(pci, DRVNAME);
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ err = pcim_iomap_regions(pci, (1 << 0) | (1 << 2), DRVNAME);
+ if (err < 0)
return err;
- }
chip->bar[0].addr = pci_resource_start(pci, 0);
- chip->bar[0].remap_addr = pci_ioremap_bar(pci, 0);
+ chip->bar[0].remap_addr = pcim_iomap_table(pci)[0];
chip->bar[1].addr = pci_resource_start(pci, 2);
- chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2);
- if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) {
- dev_err(chip->card->dev, "ioremap error\n");
- err = -ENXIO;
- goto errout;
- }
+ chip->bar[1].remap_addr = pcim_iomap_table(pci)[2];
pci_set_master(pci);
err = reset_controller(chip);
if (err < 0)
- goto errout;
+ return err;
- if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, lola_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
- err = -EBUSY;
- goto errout;
+ return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
@@ -653,19 +617,12 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
(!chip->pcm[CAPT].num_streams &&
!chip->pcm[PLAY].num_streams)) {
dev_err(chip->card->dev, "invalid DEVER = %x\n", dever);
- err = -EINVAL;
- goto errout;
+ return -EINVAL;
}
err = setup_corb_rirb(chip);
if (err < 0)
- goto errout;
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- dev_err(chip->card->dev, "Error creating device [card]!\n");
- goto errout;
- }
+ return err;
strcpy(card->driver, "Lola");
strscpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
@@ -677,12 +634,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
lola_irq_enable(chip);
chip->initialized = 1;
- *rchip = chip;
return 0;
-
- errout:
- lola_free(chip);
- return err;
}
static int lola_probe(struct pci_dev *pci,
@@ -700,47 +652,39 @@ static int lola_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0) {
dev_err(&pci->dev, "Error creating card!\n");
return err;
}
+ chip = card->private_data;
- err = lola_create(card, pci, dev, &chip);
+ err = lola_create(card, pci, dev);
if (err < 0)
- goto out_free;
- card->private_data = chip;
+ return err;
err = lola_parse_tree(chip);
if (err < 0)
- goto out_free;
+ return err;
err = lola_create_pcm(chip);
if (err < 0)
- goto out_free;
+ return err;
err = lola_create_mixer(chip);
if (err < 0)
- goto out_free;
+ return err;
lola_proc_debug_new(chip);
err = snd_card_register(card);
if (err < 0)
- goto out_free;
+ return err;
pci_set_drvdata(pci, card);
dev++;
- return err;
-out_free:
- snd_card_free(card);
- return err;
-}
-
-static void lola_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
+ return 0;
}
/* PCI IDs */
@@ -755,7 +699,6 @@ static struct pci_driver lola_driver = {
.name = KBUILD_MODNAME,
.id_table = lola_ids,
.probe = lola_probe,
- .remove = lola_remove,
};
module_pci_driver(lola_driver);
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h
index 8a598aa40bf3..0ff772cf66e6 100644
--- a/sound/pci/lola/lola.h
+++ b/sound/pci/lola/lola.h
@@ -303,7 +303,7 @@ struct lola_stream {
struct lola_pcm {
unsigned int num_streams;
- struct snd_dma_buffer bdl; /* BDL buffer */
+ struct snd_dma_buffer *bdl; /* BDL buffer */
struct lola_stream streams[MAX_STREAM_COUNT];
};
@@ -328,7 +328,7 @@ struct lola {
unsigned int last_cmd_nid, last_verb, last_data, last_extdata;
/* CORB/RIRB buffers */
- struct snd_dma_buffer rb;
+ struct snd_dma_buffer *rb;
/* unsolicited events */
unsigned int last_unsol_res;
@@ -480,7 +480,6 @@ int lola_codec_flush(struct lola *chip);
/* PCM */
int lola_create_pcm(struct lola *chip);
-void lola_free_pcm(struct lola *chip);
int lola_init_pcm(struct lola *chip, int dir, int *nidp);
void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits);
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
index 684faaf40f31..738ec987000a 100644
--- a/sound/pci/lola/lola_pcm.c
+++ b/sound/pci/lola/lola_pcm.c
@@ -348,7 +348,7 @@ static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm,
periods = str->bufsize / period_bytes;
/* program the initial BDL entries */
- bdl = (__le32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index);
+ bdl = (__le32 *)(pcm->bdl->area + LOLA_BDL_ENTRY_SIZE * str->index);
ofs = 0;
str->frags = 0;
for (i = 0; i < periods; i++) {
@@ -433,7 +433,7 @@ static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
return -EINVAL;
/* set up BDL */
- bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index;
+ bdl = pcm->bdl->addr + LOLA_BDL_ENTRY_SIZE * str->index;
lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl);
lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl));
/* program the stream LVI (last valid index) of the BDL */
@@ -588,11 +588,11 @@ int lola_create_pcm(struct lola *chip)
int i, err;
for (i = 0; i < 2; i++) {
- err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
- &chip->pci->dev,
- PAGE_SIZE, &chip->pcm[i].bdl);
- if (err < 0)
- return err;
+ chip->pcm[i].bdl =
+ snd_devm_alloc_pages(&chip->pci->dev, SNDRV_DMA_TYPE_DEV,
+ PAGE_SIZE);
+ if (!chip->pcm[i].bdl)
+ return -ENOMEM;
}
err = snd_pcm_new(chip->card, "Digigram Lola", 0,
@@ -614,12 +614,6 @@ int lola_create_pcm(struct lola *chip)
return 0;
}
-void lola_free_pcm(struct lola *chip)
-{
- snd_dma_free_pages(&chip->pcm[0].bdl);
- snd_dma_free_pages(&chip->pcm[1].bdl);
-}
-
/*
*/
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 1be97c38bc71..168a1084f730 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -524,29 +524,11 @@ static int lx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return lx_pcm_trigger_dispatch(chip, stream, cmd);
}
-static int snd_lx6464es_free(struct lx6464es *chip)
+static void snd_lx6464es_free(struct snd_card *card)
{
- dev_dbg(chip->card->dev, "->snd_lx6464es_free\n");
+ struct lx6464es *chip = card->private_data;
lx_irq_disable(chip);
-
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
-
- iounmap(chip->port_dsp_bar);
- ioport_unmap(chip->port_plx_remapped);
-
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
-
- kfree(chip);
-
- return 0;
-}
-
-static int snd_lx6464es_dev_free(struct snd_device *device)
-{
- return snd_lx6464es_free(device->device_data);
}
/* reset the dsp during initialization */
@@ -930,22 +912,15 @@ static int lx_proc_create(struct snd_card *card, struct lx6464es *chip)
static int snd_lx6464es_create(struct snd_card *card,
- struct pci_dev *pci,
- struct lx6464es **rchip)
+ struct pci_dev *pci)
{
- struct lx6464es *chip;
+ struct lx6464es *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_lx6464es_dev_free,
- };
-
dev_dbg(card->dev, "->snd_lx6464es_create\n");
- *rchip = NULL;
-
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
@@ -956,16 +931,9 @@ static int snd_lx6464es_create(struct snd_card *card,
if (err < 0) {
dev_err(card->dev,
"architecture does not support 32bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- err = -ENOMEM;
- goto alloc_failed;
- }
-
chip->card = card;
chip->pci = pci;
chip->irq = -1;
@@ -978,33 +946,30 @@ static int snd_lx6464es_create(struct snd_card *card,
/* request resources */
err = pci_request_regions(pci, card_name);
if (err < 0)
- goto request_regions_failed;
+ return err;
/* plx port */
chip->port_plx = pci_resource_start(pci, 1);
- chip->port_plx_remapped = ioport_map(chip->port_plx,
- pci_resource_len(pci, 1));
+ chip->port_plx_remapped = devm_ioport_map(&pci->dev, chip->port_plx,
+ pci_resource_len(pci, 1));
+ if (!chip->port_plx_remapped)
+ return -ENOMEM;
/* 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");
- err = -ENOMEM;
- goto remap_pci_failed;
- }
+ chip->port_dsp_bar = pcim_iomap(pci, 2, 0);
+ if (!chip->port_dsp_bar)
+ return -ENOMEM;
- err = request_threaded_irq(pci->irq, lx_interrupt, lx_threaded_irq,
- IRQF_SHARED, KBUILD_MODNAME, chip);
+ err = devm_request_threaded_irq(&pci->dev, pci->irq, lx_interrupt,
+ lx_threaded_irq, IRQF_SHARED,
+ KBUILD_MODNAME, chip);
if (err) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- goto request_irq_failed;
+ return err;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0)
- goto device_new_failed;
+ card->private_free = snd_lx6464es_free;
err = lx_init_dsp(chip);
if (err < 0) {
@@ -1025,25 +990,7 @@ static int snd_lx6464es_create(struct snd_card *card,
if (err < 0)
return err;
- *rchip = chip;
return 0;
-
-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:
- kfree(chip);
-
-alloc_failed:
- pci_disable_device(pci);
-
- return err;
}
static int snd_lx6464es_probe(struct pci_dev *pci,
@@ -1063,15 +1010,16 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
- err = snd_lx6464es_create(card, pci, &chip);
+ err = snd_lx6464es_create(card, pci);
if (err < 0) {
dev_err(card->dev, "error during snd_lx6464es_create\n");
- goto out_free;
+ return err;
}
strcpy(card->driver, "LX6464ES");
@@ -1088,30 +1036,18 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto out_free;
+ return err;
dev_dbg(chip->card->dev, "initialization successful\n");
pci_set_drvdata(pci, card);
dev++;
return 0;
-
-out_free:
- snd_card_free(card);
- return err;
-
}
-static void snd_lx6464es_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
-
static struct pci_driver lx6464es_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_lx6464es_ids,
.probe = snd_lx6464es_probe,
- .remove = snd_lx6464es_remove,
};
module_pci_driver(lx6464es_driver);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 77a484bc8c0d..056838ead21d 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2339,16 +2339,13 @@ snd_m3_enable_ints(struct snd_m3 *chip)
/*
*/
-static int snd_m3_free(struct snd_m3 *chip)
+static void snd_m3_free(struct snd_card *card)
{
+ struct snd_m3 *chip = card->private_data;
struct m3_dma *s;
int i;
cancel_work_sync(&chip->hwvol_work);
-#ifdef CONFIG_SND_MAESTRO3_INPUT
- if (chip->input_dev)
- input_unregister_device(chip->input_dev);
-#endif
if (chip->substreams) {
spin_lock_irq(&chip->reg_lock);
@@ -2359,7 +2356,6 @@ static int snd_m3_free(struct snd_m3 *chip)
snd_m3_pcm_stop(chip, s, s->substream);
}
spin_unlock_irq(&chip->reg_lock);
- kfree(chip->substreams);
}
if (chip->iobase) {
outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */
@@ -2368,19 +2364,8 @@ static int snd_m3_free(struct snd_m3 *chip)
#ifdef CONFIG_PM_SLEEP
vfree(chip->suspend_mem);
#endif
-
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
-
- if (chip->iobase)
- pci_release_regions(chip->pci);
-
release_firmware(chip->assp_kernel_image);
release_firmware(chip->assp_minisrc_image);
-
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
}
@@ -2473,7 +2458,7 @@ static int snd_m3_input_register(struct snd_m3 *chip)
struct input_dev *input_dev;
int err;
- input_dev = input_allocate_device();
+ input_dev = devm_input_allocate_device(&chip->pci->dev);
if (!input_dev)
return -ENOMEM;
@@ -2493,10 +2478,8 @@ static int snd_m3_input_register(struct snd_m3 *chip)
__set_bit(KEY_VOLUMEUP, input_dev->keybit);
err = input_register_device(input_dev);
- if (err) {
- input_free_device(input_dev);
+ if (err)
return err;
- }
chip->input_dev = input_dev;
return 0;
@@ -2506,44 +2489,25 @@ static int snd_m3_input_register(struct snd_m3 *chip)
/*
*/
-static int snd_m3_dev_free(struct snd_device *device)
-{
- struct snd_m3 *chip = device->device_data;
- return snd_m3_free(chip);
-}
-
static int
snd_m3_create(struct snd_card *card, struct pci_dev *pci,
int enable_amp,
- int amp_gpio,
- struct snd_m3 **chip_ret)
+ int amp_gpio)
{
- struct snd_m3 *chip;
+ struct snd_m3 *chip = card->private_data;
int i, err;
const struct snd_pci_quirk *quirk;
- static const struct snd_device_ops ops = {
- .dev_free = snd_m3_dev_free,
- };
- *chip_ret = NULL;
-
- if (pci_enable_device(pci))
+ if (pcim_enable_device(pci))
return -EIO;
/* check, if we can restrict PCI DMA transfers to 28 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
dev_err(card->dev,
"architecture does not support 28bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
spin_lock_init(&chip->reg_lock);
switch (pci->device) {
@@ -2559,6 +2523,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
chip->pci = pci;
chip->irq = -1;
INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume);
+ card->private_free = snd_m3_free;
chip->external_amp = enable_amp;
if (amp_gpio >= 0 && amp_gpio <= 0x0f)
@@ -2588,27 +2553,24 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
chip->is_omnibook = 1;
chip->num_substreams = NR_DSPS;
- chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma),
- GFP_KERNEL);
- if (chip->substreams == NULL) {
- kfree(chip);
- pci_disable_device(pci);
+ chip->substreams = devm_kcalloc(&pci->dev, chip->num_substreams,
+ sizeof(struct m3_dma), GFP_KERNEL);
+ if (!chip->substreams)
return -ENOMEM;
- }
err = request_firmware(&chip->assp_kernel_image,
"ess/maestro3_assp_kernel.fw", &pci->dev);
if (err < 0)
- goto free_chip;
+ return err;
err = request_firmware(&chip->assp_minisrc_image,
"ess/maestro3_assp_minisrc.fw", &pci->dev);
if (err < 0)
- goto free_chip;
+ return err;
err = pci_request_regions(pci, card->driver);
if (err < 0)
- goto free_chip;
+ return err;
chip->iobase = pci_resource_start(pci, 0);
@@ -2624,11 +2586,10 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
snd_m3_hv_init(chip);
- if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_m3_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- err = -ENOMEM;
- goto free_chip;
+ return -ENOMEM;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
@@ -2642,10 +2603,6 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
dev_warn(card->dev, "can't allocate apm buffer\n");
#endif
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0)
- goto free_chip;
-
err = snd_m3_mixer(chip);
if (err < 0)
return err;
@@ -2674,13 +2631,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
snd_m3_enable_ints(chip);
snd_m3_assp_continue(chip);
- *chip_ret = chip;
-
return 0;
-
-free_chip:
- snd_m3_free(chip);
- return err;
}
/*
@@ -2704,10 +2655,11 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
switch (pci->device) {
case PCI_DEVICE_ID_ESS_ALLEGRO:
@@ -2723,11 +2675,9 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
break;
}
- err = snd_m3_create(card, pci, external_amp[dev], amp_gpio[dev], &chip);
+ err = snd_m3_create(card, pci, external_amp[dev], amp_gpio[dev]);
if (err < 0)
- goto free_card;
-
- card->private_data = chip;
+ return err;
sprintf(card->shortname, "ESS %s PCI", card->driver);
sprintf(card->longname, "%s at 0x%lx, irq %d",
@@ -2735,7 +2685,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
err = snd_card_register(card);
if (err < 0)
- goto free_card;
+ return err;
#if 0 /* TODO: not supported yet */
/* TODO enable MIDI IRQ and I/O */
@@ -2750,22 +2700,12 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
pci_set_drvdata(pci, card);
dev++;
return 0;
-
-free_card:
- snd_card_free(card);
- return err;
-}
-
-static void snd_m3_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver m3_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_m3_ids,
.probe = snd_m3_probe,
- .remove = snd_m3_remove,
.driver = {
.pm = M3_PM_OPS,
},
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 12d02d7d3b51..c9c178504959 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -193,11 +193,9 @@ struct nm256 {
struct snd_card *card;
void __iomem *cport; /* control port */
- struct resource *res_cport; /* its resource */
unsigned long cport_addr; /* physical address */
void __iomem *buffer; /* buffer */
- struct resource *res_buffer; /* its resource */
unsigned long buffer_addr; /* buffer phyiscal address */
u32 buffer_start; /* start offset from pci resource 0 */
@@ -1313,8 +1311,9 @@ snd_nm256_mixer(struct nm256 *chip)
.read = snd_nm256_ac97_read,
};
- chip->ac97_regs = kcalloc(ARRAY_SIZE(nm256_ac97_init_val),
- sizeof(short), GFP_KERNEL);
+ chip->ac97_regs = devm_kcalloc(chip->card->dev,
+ ARRAY_SIZE(nm256_ac97_init_val),
+ sizeof(short), GFP_KERNEL);
if (! chip->ac97_regs)
return -ENOMEM;
@@ -1437,56 +1436,27 @@ static SIMPLE_DEV_PM_OPS(nm256_pm, nm256_suspend, nm256_resume);
#define NM256_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
-static int snd_nm256_free(struct nm256 *chip)
+static void snd_nm256_free(struct snd_card *card)
{
+ struct nm256 *chip = card->private_data;
+
if (chip->streams[SNDRV_PCM_STREAM_PLAYBACK].running)
snd_nm256_playback_stop(chip);
if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running)
snd_nm256_capture_stop(chip);
-
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
-
- iounmap(chip->cport);
- iounmap(chip->buffer);
- release_and_free_resource(chip->res_cport);
- release_and_free_resource(chip->res_buffer);
-
- pci_disable_device(chip->pci);
- kfree(chip->ac97_regs);
- kfree(chip);
- return 0;
-}
-
-static int snd_nm256_dev_free(struct snd_device *device)
-{
- struct nm256 *chip = device->device_data;
- return snd_nm256_free(chip);
}
static int
-snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
- struct nm256 **chip_ret)
+snd_nm256_create(struct snd_card *card, struct pci_dev *pci)
{
- struct nm256 *chip;
+ struct nm256 *chip = card->private_data;
int err, pval;
- static const struct snd_device_ops ops = {
- .dev_free = snd_nm256_dev_free,
- };
u32 addr;
- *chip_ret = NULL;
-
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
chip->card = card;
chip->pci = pci;
chip->use_cache = use_cache;
@@ -1508,22 +1478,17 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
chip->buffer_addr = pci_resource_start(pci, 0);
chip->cport_addr = pci_resource_start(pci, 1);
+ err = pci_request_regions(pci, card->driver);
+ if (err < 0)
+ return err;
+
/* Init the memory port info. */
/* remap control port (#2) */
- chip->res_cport = request_mem_region(chip->cport_addr, NM_PORT2_SIZE,
- card->driver);
- if (chip->res_cport == NULL) {
- dev_err(card->dev, "memory region 0x%lx (size 0x%x) busy\n",
- chip->cport_addr, NM_PORT2_SIZE);
- err = -EBUSY;
- goto __error;
- }
- chip->cport = ioremap(chip->cport_addr, NM_PORT2_SIZE);
- if (chip->cport == NULL) {
+ chip->cport = devm_ioremap(&pci->dev, chip->cport_addr, NM_PORT2_SIZE);
+ if (!chip->cport) {
dev_err(card->dev, "unable to map control port %lx\n",
chip->cport_addr);
- err = -ENOMEM;
- goto __error;
+ return -ENOMEM;
}
if (!strcmp(card->driver, "NM256AV")) {
@@ -1539,8 +1504,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
" force_ac97=1\n");
dev_err(card->dev,
"or try sb16, opl3sa2, or cs423x drivers instead.\n");
- err = -ENXIO;
- goto __error;
+ return -ENXIO;
}
}
chip->buffer_end = 2560 * 1024;
@@ -1572,7 +1536,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
/* get buffer end pointer from signature */
err = snd_nm256_peek_for_sig(chip);
if (err < 0)
- goto __error;
+ return err;
}
chip->buffer_start = chip->buffer_end - chip->buffer_size;
@@ -1581,21 +1545,12 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
dev_info(card->dev, "Mapping port 1 from 0x%x - 0x%x\n",
chip->buffer_start, chip->buffer_end);
- chip->res_buffer = request_mem_region(chip->buffer_addr,
- chip->buffer_size,
- card->driver);
- if (chip->res_buffer == NULL) {
- dev_err(card->dev, "buffer 0x%lx (size 0x%x) busy\n",
- chip->buffer_addr, chip->buffer_size);
- err = -EBUSY;
- goto __error;
- }
- chip->buffer = ioremap(chip->buffer_addr, chip->buffer_size);
- if (chip->buffer == NULL) {
- err = -ENOMEM;
+ chip->buffer = devm_ioremap(&pci->dev, chip->buffer_addr,
+ chip->buffer_size);
+ if (!chip->buffer) {
dev_err(card->dev, "unable to map ring buffer at %lx\n",
chip->buffer_addr);
- goto __error;
+ return -ENOMEM;
}
/* set offsets */
@@ -1618,19 +1573,10 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
chip->coeffs_current = 0;
snd_nm256_init_chip(chip);
+ card->private_free = snd_nm256_free;
// pci_set_master(pci); /* needed? */
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0)
- goto __error;
-
- *chip_ret = chip;
return 0;
-
-__error:
- snd_nm256_free(chip);
- return err;
}
@@ -1673,9 +1619,11 @@ static int snd_nm256_probe(struct pci_dev *pci,
}
}
- err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
switch (pci->device) {
case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO:
@@ -1689,7 +1637,6 @@ static int snd_nm256_probe(struct pci_dev *pci,
break;
default:
dev_err(&pci->dev, "invalid device id 0x%x\n", pci->device);
- snd_card_free(card);
return -EINVAL;
}
@@ -1704,12 +1651,9 @@ static int snd_nm256_probe(struct pci_dev *pci,
capture_bufsize = 4;
if (capture_bufsize > 128)
capture_bufsize = 128;
- err = snd_nm256_create(card, pci, &chip);
- if (err < 0) {
- snd_card_free(card);
+ err = snd_nm256_create(card, pci);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
if (reset_workaround) {
dev_dbg(&pci->dev, "reset_workaround activated\n");
@@ -1722,15 +1666,11 @@ static int snd_nm256_probe(struct pci_dev *pci,
}
err = snd_nm256_pcm(chip, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_nm256_mixer(chip);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
sprintf(card->shortname, "NeoMagic %s", card->driver);
sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d",
@@ -1738,26 +1678,17 @@ static int snd_nm256_probe(struct pci_dev *pci,
chip->buffer_addr, chip->cport_addr, chip->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
return 0;
}
-static void snd_nm256_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
-
static struct pci_driver nm256_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_nm256_ids,
.probe = snd_nm256_probe,
- .remove = snd_nm256_remove,
.driver = {
.pm = NM256_PM_OPS,
},
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index e335c4b5b381..c346f42befc2 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -854,7 +854,6 @@ static struct pci_driver oxygen_driver = {
.name = KBUILD_MODNAME,
.id_table = oxygen_ids,
.probe = generic_oxygen_probe,
- .remove = oxygen_pci_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &oxygen_pci_pm,
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 06bf7e5744d0..0cae640708f3 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -161,7 +161,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
const struct pci_device_id *id
)
);
-void oxygen_pci_remove(struct pci_dev *pci);
#ifdef CONFIG_PM_SLEEP
extern const struct dev_pm_ops oxygen_pci_pm;
#endif
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index afc6dd329c09..4fb3f2484fdb 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -570,15 +570,10 @@ static void oxygen_card_free(struct snd_card *card)
struct oxygen *chip = card->private_data;
oxygen_shutdown(chip);
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
flush_work(&chip->spdif_input_bits_work);
flush_work(&chip->gpio_work);
chip->model.cleanup(chip);
- kfree(chip->model_data);
mutex_destroy(&chip->mutex);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
}
int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
@@ -594,8 +589,8 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
const struct pci_device_id *pci_id;
int err;
- err = snd_card_new(&pci->dev, index, id, owner,
- sizeof(*chip), &card);
+ err = snd_devm_card_new(&pci->dev, index, id, owner,
+ sizeof(*chip), &card);
if (err < 0)
return err;
@@ -610,41 +605,38 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
INIT_WORK(&chip->gpio_work, oxygen_gpio_changed);
init_waitqueue_head(&chip->ac97_waitqueue);
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
- goto err_card;
+ return err;
err = pci_request_regions(pci, DRIVER);
if (err < 0) {
dev_err(card->dev, "cannot reserve PCI resources\n");
- goto err_pci_enable;
+ return err;
}
if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) ||
pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) {
dev_err(card->dev, "invalid PCI I/O range\n");
- err = -ENXIO;
- goto err_pci_regions;
+ return -ENXIO;
}
chip->addr = pci_resource_start(pci, 0);
pci_id = oxygen_search_pci_id(chip, ids);
- if (!pci_id) {
- err = -ENODEV;
- goto err_pci_regions;
- }
+ if (!pci_id)
+ return -ENODEV;
+
oxygen_restore_eeprom(chip, pci_id);
err = get_model(chip, pci_id);
if (err < 0)
- goto err_pci_regions;
+ return err;
if (chip->model.model_data_size) {
- chip->model_data = kzalloc(chip->model.model_data_size,
- GFP_KERNEL);
- if (!chip->model_data) {
- err = -ENOMEM;
- goto err_pci_regions;
- }
+ chip->model_data = devm_kzalloc(&pci->dev,
+ chip->model.model_data_size,
+ GFP_KERNEL);
+ if (!chip->model_data)
+ return -ENOMEM;
}
pci_set_master(pci);
@@ -654,11 +646,11 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
oxygen_init(chip);
chip->model.init(chip);
- err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip);
+ err = devm_request_irq(&pci->dev, pci->irq, oxygen_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip);
if (err < 0) {
dev_err(card->dev, "cannot grab interrupt %d\n", pci->irq);
- goto err_card;
+ return err;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
@@ -672,11 +664,11 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
err = oxygen_pcm_init(chip);
if (err < 0)
- goto err_card;
+ return err;
err = oxygen_mixer_init(chip);
if (err < 0)
- goto err_card;
+ return err;
if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) {
unsigned int info_flags =
@@ -689,7 +681,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
chip->addr + OXYGEN_MPU401,
info_flags, -1, &chip->midi);
if (err < 0)
- goto err_card;
+ return err;
}
oxygen_proc_init(chip);
@@ -704,27 +696,13 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
err = snd_card_register(card);
if (err < 0)
- goto err_card;
+ return err;
pci_set_drvdata(pci, card);
return 0;
-
-err_pci_regions:
- pci_release_regions(pci);
-err_pci_enable:
- pci_disable_device(pci);
-err_card:
- snd_card_free(card);
- return err;
}
EXPORT_SYMBOL(oxygen_pci_probe);
-void oxygen_pci_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-EXPORT_SYMBOL(oxygen_pci_remove);
-
#ifdef CONFIG_PM_SLEEP
static int oxygen_pci_suspend(struct device *dev)
{
diff --git a/sound/pci/oxygen/se6x.c b/sound/pci/oxygen/se6x.c
index 434f885f6f91..17650a5b1bfa 100644
--- a/sound/pci/oxygen/se6x.c
+++ b/sound/pci/oxygen/se6x.c
@@ -137,7 +137,6 @@ static struct pci_driver se6x_driver = {
.name = KBUILD_MODNAME,
.id_table = se6x_ids,
.probe = se6x_probe,
- .remove = oxygen_pci_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &oxygen_pci_pm,
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index baa3244d4dab..2e405133371f 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -82,7 +82,6 @@ static struct pci_driver xonar_driver = {
.name = KBUILD_MODNAME,
.id_table = xonar_ids,
.probe = xonar_probe,
- .remove = oxygen_pci_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &oxygen_pci_pm,
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 96b9371c201a..242bd7e04b3e 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -366,7 +366,7 @@ static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
mgr->codec_speed = speed; /* save new codec speed */
}
- dev_dbg(&mgr->pci->dev, "pcxhr_sub_set_clock to %dHz (realfreq=%d)\n",
+ dev_dbg(&mgr->pci->dev, "%s to %dHz (realfreq=%d)\n", __func__,
rate, realfreq);
return 0;
}
@@ -499,7 +499,7 @@ static int pcxhr_set_stream_state(struct snd_pcxhr *chip,
else {
if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) {
dev_err(chip->card->dev,
- "pcxhr_set_stream_state CANNOT be stopped\n");
+ "%s CANNOT be stopped\n", __func__);
return -EINVAL;
}
start = 0;
@@ -524,7 +524,7 @@ static int pcxhr_set_stream_state(struct snd_pcxhr *chip,
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
dev_err(chip->card->dev,
- "ERROR pcxhr_set_stream_state err=%x;\n", err);
+ "ERROR %s err=%x;\n", __func__, err);
stream->status =
start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
return err;
@@ -570,7 +570,7 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
break;
default:
dev_err(chip->card->dev,
- "error pcxhr_set_format() : unknown format\n");
+ "error %s() : unknown format\n", __func__);
return -EINVAL;
}
@@ -615,7 +615,7 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
dev_err(chip->card->dev,
- "ERROR pcxhr_set_format err=%x;\n", err);
+ "ERROR %s err=%x;\n", __func__, err);
return err;
}
@@ -630,7 +630,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
stream_num = is_capture ? 0 : subs->number;
dev_dbg(chip->card->dev,
- "pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
+ "%s(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n", __func__,
is_capture ? 'c' : 'p',
chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
subs->runtime->dma_bytes, subs->number);
@@ -721,21 +721,20 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
}
if (capture_mask == 0 && playback_mask == 0) {
mutex_unlock(&mgr->setup_mutex);
- dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : no pipes\n");
+ dev_err(&mgr->pci->dev, "%s : no pipes\n", __func__);
return;
}
- dev_dbg(&mgr->pci->dev, "pcxhr_start_linked_stream : "
- "playback_mask=%x capture_mask=%x\n",
- playback_mask, capture_mask);
+ dev_dbg(&mgr->pci->dev, "%s : playback_mask=%x capture_mask=%x\n",
+ __func__, playback_mask, capture_mask);
/* synchronous stop of all the pipes concerned */
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
if (err) {
mutex_unlock(&mgr->setup_mutex);
- dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
+ dev_err(&mgr->pci->dev, "%s : "
"error stop pipes (P%x C%x)\n",
- playback_mask, capture_mask);
+ __func__, playback_mask, capture_mask);
return;
}
@@ -778,9 +777,9 @@ static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
if (err) {
mutex_unlock(&mgr->setup_mutex);
- dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
+ dev_err(&mgr->pci->dev, "%s : "
"error start pipes (P%x C%x)\n",
- playback_mask, capture_mask);
+ __func__, playback_mask, capture_mask);
return;
}
@@ -889,7 +888,7 @@ static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start)
}
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0)
- dev_err(&mgr->pci->dev, "error pcxhr_hardware_timer err(%x)\n",
+ dev_err(&mgr->pci->dev, "error %s err(%x)\n", __func__,
err);
return err;
}
@@ -904,7 +903,7 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs)
int err = 0;
dev_dbg(chip->card->dev,
- "pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n",
+ "%s : period_size(%lx) periods(%x) buffer_size(%lx)\n", __func__,
subs->runtime->period_size, subs->runtime->periods,
subs->runtime->buffer_size);
@@ -997,12 +996,12 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
runtime->hw = pcxhr_caps;
if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
- dev_dbg(chip->card->dev, "pcxhr_open playback chip%d subs%d\n",
- chip->chip_idx, subs->number);
+ dev_dbg(chip->card->dev, "%s playback chip%d subs%d\n",
+ __func__, chip->chip_idx, subs->number);
stream = &chip->playback_stream[subs->number];
} else {
- dev_dbg(chip->card->dev, "pcxhr_open capture chip%d subs%d\n",
- chip->chip_idx, subs->number);
+ dev_dbg(chip->card->dev, "%s capture chip%d subs%d\n",
+ __func__, chip->chip_idx, subs->number);
if (mgr->mono_capture)
runtime->hw.channels_max = 1;
else
@@ -1011,8 +1010,8 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
}
if (stream->status != PCXHR_STREAM_STATUS_FREE){
/* streams in use */
- dev_err(chip->card->dev, "pcxhr_open chip%d subs%d in use\n",
- chip->chip_idx, subs->number);
+ dev_err(chip->card->dev, "%s chip%d subs%d in use\n",
+ __func__, chip->chip_idx, subs->number);
mutex_unlock(&mgr->setup_mutex);
return -EBUSY;
}
@@ -1077,7 +1076,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs)
mutex_lock(&mgr->setup_mutex);
- dev_dbg(chip->card->dev, "pcxhr_close chip%d subs%d\n",
+ dev_dbg(chip->card->dev, "%s chip%d subs%d\n", __func__,
chip->chip_idx, subs->number);
/* sample rate released */
@@ -1572,7 +1571,7 @@ static int pcxhr_probe(struct pci_dev *pci,
/* init setup mutex*/
mutex_init(&mgr->setup_mutex);
- mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
+ mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
PCXHR_SIZE_MAX_STATUS),
GFP_KERNEL);
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 709a1a2cde20..5a987c683c41 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1798,13 +1798,11 @@ static int snd_riptide_initialize(struct snd_riptide *chip)
return err;
}
-static int snd_riptide_free(struct snd_riptide *chip)
+static void snd_riptide_free(struct snd_card *card)
{
+ struct snd_riptide *chip = card->private_data;
struct cmdif *cif;
- if (!chip)
- return 0;
-
cif = chip->cif;
if (cif) {
SET_GRESET(cif->hwport);
@@ -1812,39 +1810,19 @@ static int snd_riptide_free(struct snd_riptide *chip)
UNSET_GRESET(cif->hwport);
kfree(chip->cif);
}
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
release_firmware(chip->fw_entry);
- release_and_free_resource(chip->res_port);
- kfree(chip);
- return 0;
-}
-
-static int snd_riptide_dev_free(struct snd_device *device)
-{
- struct snd_riptide *chip = device->device_data;
-
- return snd_riptide_free(chip);
}
static int
-snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
- struct snd_riptide **rchip)
+snd_riptide_create(struct snd_card *card, struct pci_dev *pci)
{
- struct snd_riptide *chip;
+ struct snd_riptide *chip = card->private_data;
struct riptideport *hwport;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_riptide_dev_free,
- };
- *rchip = NULL;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
spin_lock_init(&chip->lock);
chip->card = card;
@@ -1855,24 +1833,20 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
chip->received_irqs = 0;
chip->handled_irqs = 0;
chip->cif = NULL;
+ card->private_free = snd_riptide_free;
- chip->res_port = request_region(chip->port, 64, "RIPTIDE");
- if (!chip->res_port) {
- snd_printk(KERN_ERR
- "Riptide: unable to grab region 0x%lx-0x%lx\n",
- chip->port, chip->port + 64 - 1);
- snd_riptide_free(chip);
- return -EBUSY;
- }
+ err = pci_request_regions(pci, "RIPTIDE");
+ if (err < 0)
+ return err;
hwport = (struct riptideport *)chip->port;
UNSET_AIE(hwport);
- if (request_threaded_irq(pci->irq, snd_riptide_interrupt,
- riptide_handleirq, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_threaded_irq(&pci->dev, pci->irq,
+ snd_riptide_interrupt,
+ riptide_handleirq, IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
pci->irq);
- snd_riptide_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
@@ -1880,18 +1854,9 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
chip->device_id = pci->device;
pci_set_master(pci);
err = snd_riptide_initialize(chip);
- if (err < 0) {
- snd_riptide_free(chip);
- return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_riptide_free(chip);
+ if (err < 0)
return err;
- }
- *rchip = chip;
return 0;
}
@@ -2073,20 +2038,20 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
- err = snd_riptide_create(card, pci, &chip);
+ chip = card->private_data;
+ err = snd_riptide_create(card, pci);
if (err < 0)
- goto error;
- card->private_data = chip;
+ return err;
err = snd_riptide_pcm(chip, 0);
if (err < 0)
- goto error;
+ return err;
err = snd_riptide_mixer(chip);
if (err < 0)
- goto error;
+ return err;
val = LEGACY_ENABLE_ALL;
if (opl3_port[dev])
@@ -2153,26 +2118,16 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
snd_riptide_proc_init(chip);
err = snd_card_register(card);
if (err < 0)
- goto error;
+ return err;
pci_set_drvdata(pci, card);
dev++;
return 0;
-
- error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_card_riptide_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver driver = {
.name = KBUILD_MODNAME,
.id_table = snd_riptide_ids,
.probe = snd_card_riptide_probe,
- .remove = snd_card_riptide_remove,
.driver = {
.pm = RIPTIDE_PM_OPS,
},
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index b5b357853c94..5b6bd9f0b2f7 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1278,27 +1278,10 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = {
.ack = snd_rme32_capture_fd_ack,
};
-static void snd_rme32_free(void *private_data)
+static void snd_rme32_free(struct rme32 *rme32)
{
- struct rme32 *rme32 = (struct rme32 *) private_data;
-
- if (rme32 == NULL) {
- return;
- }
- if (rme32->irq >= 0) {
+ if (rme32->irq >= 0)
snd_rme32_pcm_stop(rme32, 0);
- free_irq(rme32->irq, (void *) rme32);
- rme32->irq = -1;
- }
- if (rme32->iobase) {
- iounmap(rme32->iobase);
- rme32->iobase = NULL;
- }
- if (rme32->port) {
- pci_release_regions(rme32->pci);
- rme32->port = 0;
- }
- pci_disable_device(rme32->pci);
}
static void snd_rme32_free_spdif_pcm(struct snd_pcm *pcm)
@@ -1322,7 +1305,7 @@ static int snd_rme32_create(struct rme32 *rme32)
rme32->irq = -1;
spin_lock_init(&rme32->lock);
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
@@ -1331,16 +1314,16 @@ static int snd_rme32_create(struct rme32 *rme32)
return err;
rme32->port = pci_resource_start(rme32->pci, 0);
- rme32->iobase = ioremap(rme32->port, RME32_IO_SIZE);
+ rme32->iobase = devm_ioremap(&pci->dev, rme32->port, RME32_IO_SIZE);
if (!rme32->iobase) {
dev_err(rme32->card->dev,
"unable to remap memory region 0x%lx-0x%lx\n",
- rme32->port, rme32->port + RME32_IO_SIZE - 1);
+ rme32->port, rme32->port + RME32_IO_SIZE - 1);
return -ENOMEM;
}
- if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, rme32)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_rme32_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, rme32)) {
dev_err(rme32->card->dev, "unable to grab IRQ %d\n", pci->irq);
return -EBUSY;
}
@@ -1907,8 +1890,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct rme32), &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*rme32), &card);
if (err < 0)
return err;
card->private_free = snd_rme32_card_free;
@@ -1918,10 +1901,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
if (fullduplex[dev])
rme32->fullduplex_mode = 1;
err = snd_rme32_create(rme32);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
strcpy(card->driver, "Digi32");
switch (rme32->pci->device) {
@@ -1939,25 +1920,17 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
card->shortname, rme32->rev, rme32->port, rme32->irq);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_rme32_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver rme32_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme32_ids,
.probe = snd_rme32_probe,
- .remove = snd_rme32_remove,
};
module_pci_driver(rme32_driver);
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index fc7ac077559c..8fc811504920 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1562,33 +1562,17 @@ static const struct snd_pcm_ops snd_rme96_capture_adat_ops = {
};
static void
-snd_rme96_free(void *private_data)
+snd_rme96_free(struct rme96 *rme96)
{
- struct rme96 *rme96 = (struct rme96 *)private_data;
-
- if (!rme96)
- return;
-
if (rme96->irq >= 0) {
snd_rme96_trigger(rme96, RME96_STOP_BOTH);
rme96->areg &= ~RME96_AR_DAC_EN;
writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
- free_irq(rme96->irq, (void *)rme96);
- rme96->irq = -1;
- }
- if (rme96->iobase) {
- iounmap(rme96->iobase);
- rme96->iobase = NULL;
- }
- if (rme96->port) {
- pci_release_regions(rme96->pci);
- rme96->port = 0;
}
#ifdef CONFIG_PM_SLEEP
vfree(rme96->playback_suspend_buffer);
vfree(rme96->capture_suspend_buffer);
#endif
- pci_disable_device(rme96->pci);
}
static void
@@ -1614,7 +1598,7 @@ snd_rme96_create(struct rme96 *rme96)
rme96->irq = -1;
spin_lock_init(&rme96->lock);
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
@@ -1623,16 +1607,16 @@ snd_rme96_create(struct rme96 *rme96)
return err;
rme96->port = pci_resource_start(rme96->pci, 0);
- rme96->iobase = ioremap(rme96->port, RME96_IO_SIZE);
+ rme96->iobase = devm_ioremap(&pci->dev, rme96->port, RME96_IO_SIZE);
if (!rme96->iobase) {
dev_err(rme96->card->dev,
"unable to remap memory region 0x%lx-0x%lx\n",
rme96->port, rme96->port + RME96_IO_SIZE - 1);
- return -ENOMEM;
+ return -EBUSY;
}
- if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, rme96)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_rme96_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, rme96)) {
dev_err(rme96->card->dev, "unable to grab IRQ %d\n", pci->irq);
return -EBUSY;
}
@@ -2462,8 +2446,8 @@ snd_rme96_probe(struct pci_dev *pci,
dev++;
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct rme96), &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*rme96), &card);
if (err < 0)
return err;
card->private_free = snd_rme96_card_free;
@@ -2472,19 +2456,15 @@ snd_rme96_probe(struct pci_dev *pci,
rme96->pci = pci;
err = snd_rme96_create(rme96);
if (err)
- goto free_card;
+ return err;
#ifdef CONFIG_PM_SLEEP
rme96->playback_suspend_buffer = vmalloc(RME96_BUFFER_SIZE);
- if (!rme96->playback_suspend_buffer) {
- err = -ENOMEM;
- goto free_card;
- }
+ if (!rme96->playback_suspend_buffer)
+ return -ENOMEM;
rme96->capture_suspend_buffer = vmalloc(RME96_BUFFER_SIZE);
- if (!rme96->capture_suspend_buffer) {
- err = -ENOMEM;
- goto free_card;
- }
+ if (!rme96->capture_suspend_buffer)
+ return -ENOMEM;
#endif
strcpy(card->driver, "Digi96");
@@ -2511,26 +2491,17 @@ snd_rme96_probe(struct pci_dev *pci,
rme96->port, rme96->irq);
err = snd_card_register(card);
if (err)
- goto free_card;
+ return err;
pci_set_drvdata(pci, card);
dev++;
return 0;
-free_card:
- snd_card_free(card);
- return err;
-}
-
-static void snd_rme96_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver rme96_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme96_ids,
.probe = snd_rme96_probe,
- .remove = snd_rme96_remove,
.driver = {
.pm = RME96_PM_OPS,
},
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 8457a4bbc3df..75aa2ea733a5 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -468,8 +468,8 @@ struct hdsp {
unsigned char ss_out_channels;
u32 io_loopback; /* output loopback channel states*/
- struct snd_dma_buffer capture_dma_buf;
- struct snd_dma_buffer playback_dma_buf;
+ struct snd_dma_buffer *capture_dma_buf;
+ struct snd_dma_buffer *playback_dma_buf;
unsigned char *capture_buffer; /* suitably aligned address */
unsigned char *playback_buffer; /* suitably aligned address */
@@ -565,18 +565,12 @@ static const char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
-1, -1
};
-static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
+static struct snd_dma_buffer *
+snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size)
{
- return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, size, dmab);
+ return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size);
}
-static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
-{
- if (dmab->area)
- snd_dma_free_pages(dmab);
-}
-
-
static const struct pci_device_id snd_hdsp_ids[] = {
{
.vendor = PCI_VENDOR_ID_XILINX,
@@ -3768,20 +3762,15 @@ static void snd_hdsp_proc_init(struct hdsp *hdsp)
snd_card_ro_proc_new(hdsp->card, "hdsp", hdsp, snd_hdsp_proc_read);
}
-static void snd_hdsp_free_buffers(struct hdsp *hdsp)
-{
- snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
- snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
-}
-
static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
{
unsigned long pb_bus, cb_bus;
- if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
- snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
- if (hdsp->capture_dma_buf.area)
- snd_dma_free_pages(&hdsp->capture_dma_buf);
+ hdsp->capture_dma_buf =
+ snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES);
+ hdsp->playback_dma_buf =
+ snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES);
+ if (!hdsp->capture_dma_buf || !hdsp->playback_dma_buf) {
dev_err(hdsp->card->dev,
"%s: no buffers available\n", hdsp->card_name);
return -ENOMEM;
@@ -3789,16 +3778,16 @@ static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
/* Align to bus-space 64K boundary */
- cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
- pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
+ cb_bus = ALIGN(hdsp->capture_dma_buf->addr, 0x10000ul);
+ pb_bus = ALIGN(hdsp->playback_dma_buf->addr, 0x10000ul);
/* Tell the card where it is */
hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
- hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
- hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
+ hdsp->capture_buffer = hdsp->capture_dma_buf->area + (cb_bus - hdsp->capture_dma_buf->addr);
+ hdsp->playback_buffer = hdsp->playback_dma_buf->area + (pb_bus - hdsp->playback_dma_buf->addr);
return 0;
}
@@ -4518,8 +4507,7 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
snd_pcm_set_sync(substream);
runtime->hw = snd_hdsp_playback_subinfo;
- runtime->dma_area = hdsp->playback_buffer;
- runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
+ snd_pcm_set_runtime_buffer(substream, hdsp->playback_dma_buf);
hdsp->playback_pid = current->pid;
hdsp->playback_substream = substream;
@@ -4595,8 +4583,7 @@ static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
snd_pcm_set_sync(substream);
runtime->hw = snd_hdsp_capture_subinfo;
- runtime->dma_area = hdsp->capture_buffer;
- runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
+ snd_pcm_set_runtime_buffer(substream, hdsp->capture_dma_buf);
hdsp->capture_pid = current->pid;
hdsp->capture_substream = substream;
@@ -5313,7 +5300,7 @@ static int snd_hdsp_create(struct snd_card *card,
is_9632 = 1;
}
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
@@ -5323,15 +5310,15 @@ static int snd_hdsp_create(struct snd_card *card,
if (err < 0)
return err;
hdsp->port = pci_resource_start(pci, 0);
- hdsp->iobase = ioremap(hdsp->port, HDSP_IO_EXTENT);
+ hdsp->iobase = devm_ioremap(&pci->dev, hdsp->port, HDSP_IO_EXTENT);
if (!hdsp->iobase) {
dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n",
hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
return -EBUSY;
}
- if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, hdsp)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_hdsp_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, hdsp)) {
dev_err(hdsp->card->dev, "unable to use IRQ %d\n", pci->irq);
return -EBUSY;
}
@@ -5411,8 +5398,10 @@ static int snd_hdsp_create(struct snd_card *card,
return 0;
}
-static int snd_hdsp_free(struct hdsp *hdsp)
+static void snd_hdsp_card_free(struct snd_card *card)
{
+ struct hdsp *hdsp = card->private_data;
+
if (hdsp->port) {
/* stop the audio, and cancel all interrupts */
cancel_work_sync(&hdsp->midi_work);
@@ -5420,29 +5409,8 @@ static int snd_hdsp_free(struct hdsp *hdsp)
hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
}
- if (hdsp->irq >= 0)
- free_irq(hdsp->irq, (void *)hdsp);
-
- snd_hdsp_free_buffers(hdsp);
-
release_firmware(hdsp->firmware);
vfree(hdsp->fw_uploaded);
- iounmap(hdsp->iobase);
-
- if (hdsp->port)
- pci_release_regions(hdsp->pci);
-
- if (pci_is_enabled(hdsp->pci))
- pci_disable_device(hdsp->pci);
- return 0;
-}
-
-static void snd_hdsp_card_free(struct snd_card *card)
-{
- struct hdsp *hdsp = card->private_data;
-
- if (hdsp)
- snd_hdsp_free(hdsp);
}
static int snd_hdsp_probe(struct pci_dev *pci,
@@ -5460,8 +5428,8 @@ static int snd_hdsp_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct hdsp), &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct hdsp), &card);
if (err < 0)
return err;
@@ -5471,32 +5439,23 @@ static int snd_hdsp_probe(struct pci_dev *pci,
hdsp->pci = pci;
err = snd_hdsp_create(card, hdsp);
if (err)
- goto free_card;
+ return err;
strcpy(card->shortname, "Hammerfall DSP");
sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
hdsp->port, hdsp->irq);
err = snd_card_register(card);
- if (err) {
-free_card:
- snd_card_free(card);
+ if (err)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_hdsp_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver hdsp_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_hdsp_ids,
.probe = snd_hdsp_probe,
- .remove = snd_hdsp_remove,
};
module_pci_driver(hdsp_driver);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 97a0bff96b28..ff06ee82607c 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6575,34 +6575,25 @@ static int snd_hdspm_create(struct snd_card *card,
}
}
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
pci_set_master(hdspm->pci);
- err = pci_request_regions(pci, "hdspm");
+ err = pcim_iomap_regions(pci, 1 << 0, "hdspm");
if (err < 0)
return err;
hdspm->port = pci_resource_start(pci, 0);
io_extent = pci_resource_len(pci, 0);
-
- dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n",
- hdspm->port, hdspm->port + io_extent - 1);
-
- hdspm->iobase = ioremap(hdspm->port, io_extent);
- if (!hdspm->iobase) {
- dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
- hdspm->port, hdspm->port + io_extent - 1);
- return -EBUSY;
- }
+ hdspm->iobase = pcim_iomap_table(pci)[0];
dev_dbg(card->dev, "remapped region (0x%lx) 0x%lx-0x%lx\n",
(unsigned long)hdspm->iobase, hdspm->port,
hdspm->port + io_extent - 1);
- if (request_irq(pci->irq, snd_hdspm_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_hdspm_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
dev_err(card->dev, "unable to use IRQ %d\n", pci->irq);
return -EBUSY;
}
@@ -6614,7 +6605,7 @@ static int snd_hdspm_create(struct snd_card *card,
dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n",
sizeof(*hdspm->mixer));
- hdspm->mixer = kzalloc(sizeof(*hdspm->mixer), GFP_KERNEL);
+ hdspm->mixer = devm_kzalloc(&pci->dev, sizeof(*hdspm->mixer), GFP_KERNEL);
if (!hdspm->mixer)
return -ENOMEM;
@@ -6859,8 +6850,9 @@ static int snd_hdspm_create(struct snd_card *card,
}
-static int snd_hdspm_free(struct hdspm * hdspm)
+static void snd_hdspm_card_free(struct snd_card *card)
{
+ struct hdspm *hdspm = card->private_data;
if (hdspm->port) {
cancel_work_sync(&hdspm->midi_work);
@@ -6873,28 +6865,6 @@ static int snd_hdspm_free(struct hdspm * hdspm)
hdspm_write(hdspm, HDSPM_controlRegister,
hdspm->control_register);
}
-
- if (hdspm->irq >= 0)
- free_irq(hdspm->irq, (void *) hdspm);
-
- kfree(hdspm->mixer);
- iounmap(hdspm->iobase);
-
- if (hdspm->port)
- pci_release_regions(hdspm->pci);
-
- if (pci_is_enabled(hdspm->pci))
- pci_disable_device(hdspm->pci);
- return 0;
-}
-
-
-static void snd_hdspm_card_free(struct snd_card *card)
-{
- struct hdspm *hdspm = card->private_data;
-
- if (hdspm)
- snd_hdspm_free(hdspm);
}
@@ -6913,8 +6883,8 @@ static int snd_hdspm_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev],
- THIS_MODULE, sizeof(*hdspm), &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev],
+ THIS_MODULE, sizeof(*hdspm), &card);
if (err < 0)
return err;
@@ -6925,7 +6895,7 @@ static int snd_hdspm_probe(struct pci_dev *pci,
err = snd_hdspm_create(card, hdspm);
if (err < 0)
- goto free_card;
+ return err;
if (hdspm->io_type != MADIface) {
snprintf(card->shortname, sizeof(card->shortname), "%s_%x",
@@ -6944,28 +6914,18 @@ static int snd_hdspm_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto free_card;
+ return err;
pci_set_drvdata(pci, card);
dev++;
return 0;
-
-free_card:
- snd_card_free(card);
- return err;
-}
-
-static void snd_hdspm_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver hdspm_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_hdspm_ids,
.probe = snd_hdspm_probe,
- .remove = snd_hdspm_remove,
};
module_pci_driver(hdspm_driver);
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index f1aad38760d6..e76f737ac9e8 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -208,8 +208,8 @@ struct snd_rme9652 {
unsigned char ds_channels;
unsigned char ss_channels; /* different for hammerfall/hammerfall-light */
- struct snd_dma_buffer playback_dma_buf;
- struct snd_dma_buffer capture_dma_buf;
+ struct snd_dma_buffer *playback_dma_buf;
+ struct snd_dma_buffer *capture_dma_buf;
unsigned char *capture_buffer; /* suitably aligned address */
unsigned char *playback_buffer; /* suitably aligned address */
@@ -275,18 +275,12 @@ static const char channel_map_9636_ds[26] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
-static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
+static struct snd_dma_buffer *
+snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size)
{
- return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, size, dmab);
+ return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size);
}
-static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
-{
- if (dmab->area)
- snd_dma_free_pages(dmab);
-}
-
-
static const struct pci_device_id snd_rme9652_ids[] = {
{
.vendor = 0x10ee,
@@ -1715,37 +1709,23 @@ static void snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
snd_rme9652_proc_read);
}
-static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652)
+static void snd_rme9652_card_free(struct snd_card *card)
{
- snd_hammerfall_free_buffer(&rme9652->capture_dma_buf, rme9652->pci);
- snd_hammerfall_free_buffer(&rme9652->playback_dma_buf, rme9652->pci);
-}
+ struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data;
-static int snd_rme9652_free(struct snd_rme9652 *rme9652)
-{
if (rme9652->irq >= 0)
rme9652_stop(rme9652);
- snd_rme9652_free_buffers(rme9652);
-
- if (rme9652->irq >= 0)
- free_irq(rme9652->irq, (void *)rme9652);
- iounmap(rme9652->iobase);
- if (rme9652->port)
- pci_release_regions(rme9652->pci);
-
- if (pci_is_enabled(rme9652->pci))
- pci_disable_device(rme9652->pci);
- return 0;
}
static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
{
unsigned long pb_bus, cb_bus;
- if (snd_hammerfall_get_buffer(rme9652->pci, &rme9652->capture_dma_buf, RME9652_DMA_AREA_BYTES) < 0 ||
- snd_hammerfall_get_buffer(rme9652->pci, &rme9652->playback_dma_buf, RME9652_DMA_AREA_BYTES) < 0) {
- if (rme9652->capture_dma_buf.area)
- snd_dma_free_pages(&rme9652->capture_dma_buf);
+ rme9652->capture_dma_buf =
+ snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES);
+ rme9652->playback_dma_buf =
+ snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES);
+ if (!rme9652->capture_dma_buf || !rme9652->playback_dma_buf) {
dev_err(rme9652->card->dev,
"%s: no buffers available\n", rme9652->card_name);
return -ENOMEM;
@@ -1753,16 +1733,16 @@ static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
/* Align to bus-space 64K boundary */
- cb_bus = ALIGN(rme9652->capture_dma_buf.addr, 0x10000ul);
- pb_bus = ALIGN(rme9652->playback_dma_buf.addr, 0x10000ul);
+ cb_bus = ALIGN(rme9652->capture_dma_buf->addr, 0x10000ul);
+ pb_bus = ALIGN(rme9652->playback_dma_buf->addr, 0x10000ul);
/* Tell the card where it is */
rme9652_write(rme9652, RME9652_rec_buffer, cb_bus);
rme9652_write(rme9652, RME9652_play_buffer, pb_bus);
- rme9652->capture_buffer = rme9652->capture_dma_buf.area + (cb_bus - rme9652->capture_dma_buf.addr);
- rme9652->playback_buffer = rme9652->playback_dma_buf.area + (pb_bus - rme9652->playback_dma_buf.addr);
+ rme9652->capture_buffer = rme9652->capture_dma_buf->area + (cb_bus - rme9652->capture_dma_buf->addr);
+ rme9652->playback_buffer = rme9652->playback_dma_buf->area + (pb_bus - rme9652->playback_dma_buf->addr);
return 0;
}
@@ -2279,8 +2259,7 @@ static int snd_rme9652_playback_open(struct snd_pcm_substream *substream)
snd_pcm_set_sync(substream);
runtime->hw = snd_rme9652_playback_subinfo;
- runtime->dma_area = rme9652->playback_buffer;
- runtime->dma_bytes = RME9652_DMA_AREA_BYTES;
+ snd_pcm_set_runtime_buffer(substream, rme9652->playback_dma_buf);
if (rme9652->capture_substream == NULL) {
rme9652_stop(rme9652);
@@ -2339,8 +2318,7 @@ static int snd_rme9652_capture_open(struct snd_pcm_substream *substream)
snd_pcm_set_sync(substream);
runtime->hw = snd_rme9652_capture_subinfo;
- runtime->dma_area = rme9652->capture_buffer;
- runtime->dma_bytes = RME9652_DMA_AREA_BYTES;
+ snd_pcm_set_runtime_buffer(substream, rme9652->capture_dma_buf);
if (rme9652->playback_substream == NULL) {
rme9652_stop(rme9652);
@@ -2452,7 +2430,7 @@ static int snd_rme9652_create(struct snd_card *card,
return -ENODEV;
}
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
@@ -2462,15 +2440,15 @@ static int snd_rme9652_create(struct snd_card *card,
if (err < 0)
return err;
rme9652->port = pci_resource_start(pci, 0);
- rme9652->iobase = ioremap(rme9652->port, RME9652_IO_EXTENT);
+ rme9652->iobase = devm_ioremap(&pci->dev, rme9652->port, RME9652_IO_EXTENT);
if (rme9652->iobase == NULL) {
dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
return -EBUSY;
}
- if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, rme9652)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_rme9652_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, rme9652)) {
dev_err(card->dev, "unable to request IRQ %d\n", pci->irq);
return -EBUSY;
}
@@ -2562,14 +2540,6 @@ static int snd_rme9652_create(struct snd_card *card,
return 0;
}
-static void snd_rme9652_card_free(struct snd_card *card)
-{
- struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data;
-
- if (rme9652)
- snd_rme9652_free(rme9652);
-}
-
static int snd_rme9652_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -2585,8 +2555,8 @@ static int snd_rme9652_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_rme9652), &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_rme9652), &card);
if (err < 0)
return err;
@@ -2597,33 +2567,24 @@ static int snd_rme9652_probe(struct pci_dev *pci,
rme9652->pci = pci;
err = snd_rme9652_create(card, rme9652, precise_ptr[dev]);
if (err)
- goto free_card;
+ return err;
strcpy(card->shortname, rme9652->card_name);
sprintf(card->longname, "%s at 0x%lx, irq %d",
card->shortname, rme9652->port, rme9652->irq);
err = snd_card_register(card);
- if (err) {
-free_card:
- snd_card_free(card);
+ if (err)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_rme9652_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver rme9652_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_rme9652_ids,
.probe = snd_rme9652_probe,
- .remove = snd_rme9652_remove,
};
module_pci_driver(rme9652_driver);
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 00ab51c889da..0b722b0e0604 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -1007,16 +1007,10 @@ static int sis_mixer_create(struct sis7019 *sis)
return rc;
}
-static void sis_free_suspend(struct sis7019 *sis)
+static void sis_chip_free(struct snd_card *card)
{
- int i;
-
- for (i = 0; i < SIS_SUSPEND_PAGES; i++)
- kfree(sis->suspend_state[i]);
-}
+ struct sis7019 *sis = card->private_data;
-static int sis_chip_free(struct sis7019 *sis)
-{
/* Reset the chip, and disable all interrputs.
*/
outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
@@ -1028,18 +1022,6 @@ static int sis_chip_free(struct sis7019 *sis)
*/
if (sis->irq >= 0)
free_irq(sis->irq, sis);
-
- iounmap(sis->ioaddr);
- pci_release_regions(sis->pci);
- pci_disable_device(sis->pci);
- sis_free_suspend(sis);
- return 0;
-}
-
-static int sis_dev_free(struct snd_device *dev)
-{
- struct sis7019 *sis = dev->device_data;
- return sis_chip_free(sis);
}
static int sis_chip_init(struct sis7019 *sis)
@@ -1265,7 +1247,8 @@ static int sis_alloc_suspend(struct sis7019 *sis)
* buffer.
*/
for (i = 0; i < SIS_SUSPEND_PAGES; i++) {
- sis->suspend_state[i] = kmalloc(4096, GFP_KERNEL);
+ sis->suspend_state[i] = devm_kmalloc(&sis->pci->dev, 4096,
+ GFP_KERNEL);
if (!sis->suspend_state[i])
return -ENOMEM;
}
@@ -1279,23 +1262,19 @@ static int sis_chip_create(struct snd_card *card,
{
struct sis7019 *sis = card->private_data;
struct voice *voice;
- static const struct snd_device_ops ops = {
- .dev_free = sis_dev_free,
- };
int rc;
int i;
- rc = pci_enable_device(pci);
+ rc = pcim_enable_device(pci);
if (rc)
- goto error_out;
+ return rc;
rc = dma_set_mask(&pci->dev, DMA_BIT_MASK(30));
if (rc < 0) {
dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA");
- goto error_out_enabled;
+ return -ENXIO;
}
- memset(sis, 0, sizeof(*sis));
mutex_init(&sis->ac97_mutex);
spin_lock_init(&sis->voice_lock);
sis->card = card;
@@ -1306,31 +1285,31 @@ static int sis_chip_create(struct snd_card *card,
rc = pci_request_regions(pci, "SiS7019");
if (rc) {
dev_err(&pci->dev, "unable request regions\n");
- goto error_out_enabled;
+ return rc;
}
- rc = -EIO;
- sis->ioaddr = ioremap(pci_resource_start(pci, 1), 0x4000);
+ sis->ioaddr = devm_ioremap(&pci->dev, pci_resource_start(pci, 1), 0x4000);
if (!sis->ioaddr) {
dev_err(&pci->dev, "unable to remap MMIO, aborting\n");
- goto error_out_cleanup;
+ return -EIO;
}
rc = sis_alloc_suspend(sis);
if (rc < 0) {
dev_err(&pci->dev, "unable to allocate state storage\n");
- goto error_out_cleanup;
+ return rc;
}
rc = sis_chip_init(sis);
if (rc)
- goto error_out_cleanup;
+ return rc;
+ card->private_free = sis_chip_free;
rc = request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME,
sis);
if (rc) {
dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq);
- goto error_out_cleanup;
+ return rc;
}
sis->irq = pci->irq;
@@ -1349,20 +1328,7 @@ static int sis_chip_create(struct snd_card *card,
voice->num = SIS_CAPTURE_CHAN_AC97_PCM_IN;
voice->ctrl_base = SIS_CAPTURE_DMA_ADDR(sis->ioaddr, voice->num);
- rc = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sis, &ops);
- if (rc)
- goto error_out_cleanup;
-
return 0;
-
-error_out_cleanup:
- sis_chip_free(sis);
-
-error_out_enabled:
- pci_disable_device(pci);
-
-error_out:
- return rc;
}
static int snd_sis7019_probe(struct pci_dev *pci,
@@ -1372,9 +1338,8 @@ static int snd_sis7019_probe(struct pci_dev *pci,
struct sis7019 *sis;
int rc;
- rc = -ENOENT;
if (!enable)
- goto error_out;
+ return -ENOENT;
/* The user can specify which codecs should be present so that we
* can wait for them to show up if they are slow to recover from
@@ -1390,23 +1355,23 @@ static int snd_sis7019_probe(struct pci_dev *pci,
rc = snd_card_new(&pci->dev, index, id, THIS_MODULE,
sizeof(*sis), &card);
if (rc < 0)
- goto error_out;
+ return rc;
strcpy(card->driver, "SiS7019");
strcpy(card->shortname, "SiS7019");
rc = sis_chip_create(card, pci);
if (rc)
- goto card_error_out;
+ return rc;
sis = card->private_data;
rc = sis_mixer_create(sis);
if (rc)
- goto card_error_out;
+ return rc;
rc = sis_pcm_create(sis);
if (rc)
- goto card_error_out;
+ return rc;
snprintf(card->longname, sizeof(card->longname),
"%s Audio Accelerator with %s at 0x%lx, irq %d",
@@ -1415,28 +1380,16 @@ static int snd_sis7019_probe(struct pci_dev *pci,
rc = snd_card_register(card);
if (rc)
- goto card_error_out;
+ return rc;
pci_set_drvdata(pci, card);
return 0;
-
-card_error_out:
- snd_card_free(card);
-
-error_out:
- return rc;
-}
-
-static void snd_sis7019_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver sis7019_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_sis7019_ids,
.probe = snd_sis7019_probe,
- .remove = snd_sis7019_remove,
.driver = {
.pm = SIS_PM_OPS,
},
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 03a48da897e3..c8c49881008f 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1193,69 +1193,43 @@ static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { ret
static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { }
#endif
-static int snd_sonicvibes_free(struct sonicvibes *sonic)
+static void snd_sonicvibes_free(struct snd_card *card)
{
+ struct sonicvibes *sonic = card->private_data;
+
snd_sonicvibes_free_gameport(sonic);
pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
- if (sonic->irq >= 0)
- free_irq(sonic->irq, sonic);
- release_and_free_resource(sonic->res_dmaa);
- release_and_free_resource(sonic->res_dmac);
- pci_release_regions(sonic->pci);
- pci_disable_device(sonic->pci);
- kfree(sonic);
- return 0;
-}
-
-static int snd_sonicvibes_dev_free(struct snd_device *device)
-{
- struct sonicvibes *sonic = device->device_data;
- return snd_sonicvibes_free(sonic);
}
static int snd_sonicvibes_create(struct snd_card *card,
struct pci_dev *pci,
int reverb,
- int mge,
- struct sonicvibes **rsonic)
+ int mge)
{
- struct sonicvibes *sonic;
+ struct sonicvibes *sonic = card->private_data;
unsigned int dmaa, dmac;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_sonicvibes_dev_free,
- };
- *rsonic = NULL;
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
dev_err(card->dev,
"architecture does not support 24bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
- if (sonic == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
spin_lock_init(&sonic->reg_lock);
sonic->card = card;
sonic->pci = pci;
sonic->irq = -1;
err = pci_request_regions(pci, "S3 SonicVibes");
- if (err < 0) {
- kfree(sonic);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
sonic->sb_port = pci_resource_start(pci, 0);
sonic->enh_port = pci_resource_start(pci, 1);
@@ -1263,14 +1237,14 @@ static int snd_sonicvibes_create(struct snd_card *card,
sonic->midi_port = pci_resource_start(pci, 3);
sonic->game_port = pci_resource_start(pci, 4);
- if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, sonic)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_sonicvibes_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, sonic)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_sonicvibes_free(sonic);
return -EBUSY;
}
sonic->irq = pci->irq;
card->sync_irq = sonic->irq;
+ card->private_free = snd_sonicvibes_free;
pci_read_config_dword(pci, 0x40, &dmaa);
pci_read_config_dword(pci, 0x48, &dmac);
@@ -1294,17 +1268,17 @@ static int snd_sonicvibes_create(struct snd_card *card,
pci_write_config_dword(pci, 0x40, dmaa);
pci_write_config_dword(pci, 0x48, dmac);
- sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A");
+ sonic->res_dmaa = devm_request_region(&pci->dev, dmaa, 0x10,
+ "S3 SonicVibes DDMA-A");
if (!sonic->res_dmaa) {
- snd_sonicvibes_free(sonic);
dev_err(card->dev,
"unable to grab DDMA-A port at 0x%x-0x%x\n",
dmaa, dmaa + 0x10 - 1);
return -EBUSY;
}
- sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C");
+ sonic->res_dmac = devm_request_region(&pci->dev, dmac, 0x10,
+ "S3 SonicVibes DDMA-C");
if (!sonic->res_dmac) {
- snd_sonicvibes_free(sonic);
dev_err(card->dev,
"unable to grab DDMA-C port at 0x%x-0x%x\n",
dmac, dmac + 0x10 - 1);
@@ -1365,15 +1339,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
#endif
sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops);
- if (err < 0) {
- snd_sonicvibes_free(sonic);
- return err;
- }
-
snd_sonicvibes_proc_init(sonic);
-
- *rsonic = sonic;
return 0;
}
@@ -1429,7 +1395,7 @@ static int snd_sonic_probe(struct pci_dev *pci,
struct sonicvibes *sonic;
struct snd_rawmidi *midi_uart;
struct snd_opl3 *opl3;
- int idx, err;
+ int err;
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -1438,25 +1404,16 @@ static int snd_sonic_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*sonic), &card);
if (err < 0)
return err;
- for (idx = 0; idx < 5; idx++) {
- if (pci_resource_start(pci, idx) == 0 ||
- !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
- snd_card_free(card);
- return -ENODEV;
- }
- }
+ sonic = card->private_data;
err = snd_sonicvibes_create(card, pci,
reverb[dev] ? 1 : 0,
- mge[dev] ? 1 : 0,
- &sonic);
- if (err < 0) {
- snd_card_free(card);
+ mge[dev] ? 1 : 0);
+ if (err < 0)
return err;
- }
strcpy(card->driver, "SonicVibes");
strcpy(card->shortname, "S3 SonicVibes");
@@ -1467,65 +1424,45 @@ static int snd_sonic_probe(struct pci_dev *pci,
sonic->irq);
err = snd_sonicvibes_pcm(sonic, 0);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_sonicvibes_mixer(sonic);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
sonic->midi_port,
MPU401_INFO_INTEGRATED |
MPU401_INFO_IRQ_HOOK,
-1, &midi_uart);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
snd_sonicvibes_midi(sonic, midi_uart);
err = snd_opl3_create(card, sonic->synth_port,
sonic->synth_port + 2,
OPL3_HW_OPL3_SV, 1, &opl3);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_sonicvibes_create_gameport(sonic);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_sonic_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver sonicvibes_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_sonic_ids,
.probe = snd_sonic_probe,
- .remove = snd_sonic_remove,
};
module_pci_driver(sonicvibes_driver);
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 60e4dca28c2b..9922ab40798c 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -62,21 +62,18 @@ static int snd_trident_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(*trident), &card);
if (err < 0)
return err;
+ trident = card->private_data;
err = snd_trident_create(card, pci,
pcm_channels[dev],
((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2,
- wavetable_size[dev],
- &trident);
- if (err < 0) {
- snd_card_free(card);
+ wavetable_size[dev]);
+ if (err < 0)
return err;
- }
- card->private_data = trident;
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
@@ -102,26 +99,20 @@ static int snd_trident_probe(struct pci_dev *pci,
card->shortname, trident->port, trident->irq);
err = snd_trident_pcm(trident, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
case TRIDENT_DEVICE_ID_NX:
err = snd_trident_foldback_pcm(trident, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
break;
}
if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
err = snd_trident_spdif_pcm(trident, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
@@ -129,34 +120,24 @@ static int snd_trident_probe(struct pci_dev *pci,
MPU401_INFO_INTEGRATED |
MPU401_INFO_IRQ_HOOK,
-1, &trident->rmidi);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
snd_trident_create_gameport(trident);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_trident_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver trident_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_trident_ids,
.probe = snd_trident_probe,
- .remove = snd_trident_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_trident_pm,
diff --git a/sound/pci/trident/trident.h b/sound/pci/trident/trident.h
index c579a44bb9ae..9768a7fc2349 100644
--- a/sound/pci/trident/trident.h
+++ b/sound/pci/trident/trident.h
@@ -251,9 +251,9 @@ struct snd_trident_memblk_arg {
struct snd_trident_tlb {
__le32 *entries; /* 16k-aligned TLB table */
dma_addr_t entries_dmaaddr; /* 16k-aligned PCI address to TLB table */
- struct snd_dma_buffer buffer;
+ struct snd_dma_buffer *buffer;
struct snd_util_memhdr * memhdr; /* page allocation list */
- struct snd_dma_buffer silent_page;
+ struct snd_dma_buffer *silent_page;
};
struct snd_trident_voice {
@@ -400,8 +400,7 @@ int snd_trident_create(struct snd_card *card,
struct pci_dev *pci,
int pcm_streams,
int pcm_spdif_device,
- int max_wavetable_size,
- struct snd_trident ** rtrident);
+ int max_wavetable_size);
int snd_trident_create_gameport(struct snd_trident *trident);
int snd_trident_pcm(struct snd_trident *trident, int device);
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index cfbca3bd60ed..e98eea1e6d81 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -42,7 +42,7 @@ static int snd_trident_sis_reset(struct snd_trident *trident);
static void snd_trident_clear_voices(struct snd_trident * trident,
unsigned short v_min, unsigned short v_max);
-static int snd_trident_free(struct snd_trident *trident);
+static void snd_trident_free(struct snd_card *card);
/*
* common I/O routines
@@ -3299,12 +3299,6 @@ static void snd_trident_proc_init(struct snd_trident *trident)
snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read);
}
-static int snd_trident_dev_free(struct snd_device *device)
-{
- struct snd_trident *trident = device->device_data;
- return snd_trident_free(trident);
-}
-
/*---------------------------------------------------------------------------
snd_trident_tlb_alloc
@@ -3324,23 +3318,27 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident)
/* TLB array must be aligned to 16kB !!! so we allocate
32kB region and correct offset when necessary */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
- 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
+ trident->tlb.buffer =
+ snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,
+ 2 * SNDRV_TRIDENT_MAX_PAGES * 4);
+ if (!trident->tlb.buffer) {
dev_err(trident->card->dev, "unable to allocate TLB buffer\n");
return -ENOMEM;
}
- trident->tlb.entries = (__le32 *)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);
+ trident->tlb.entries = (__le32 *)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 and setup silent page and initialise TLB entries */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
- SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
+ trident->tlb.silent_page =
+ snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,
+ SNDRV_TRIDENT_PAGE_SIZE);
+ if (!trident->tlb.silent_page) {
dev_err(trident->card->dev, "unable to allocate silent page\n");
return -ENOMEM;
}
- memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE);
+ memset(trident->tlb.silent_page->area, 0, SNDRV_TRIDENT_PAGE_SIZE);
for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++)
- trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
+ trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page->addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
/* use emu memory block manager code to manage tlb page allocation */
trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);
@@ -3497,36 +3495,24 @@ int snd_trident_create(struct snd_card *card,
struct pci_dev *pci,
int pcm_streams,
int pcm_spdif_device,
- int max_wavetable_size,
- struct snd_trident ** rtrident)
+ int max_wavetable_size)
{
- struct snd_trident *trident;
+ struct snd_trident *trident = card->private_data;
int i, err;
struct snd_trident_voice *voice;
struct snd_trident_pcm_mixer *tmix;
- static const struct snd_device_ops ops = {
- .dev_free = snd_trident_dev_free,
- };
-
- *rtrident = NULL;
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 30 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) {
dev_err(card->dev,
"architecture does not support 30bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- trident = kzalloc(sizeof(*trident), GFP_KERNEL);
- if (trident == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
trident->device = (pci->vendor << 16) | pci->device;
trident->card = card;
trident->pci = pci;
@@ -3542,22 +3528,19 @@ int snd_trident_create(struct snd_card *card,
max_wavetable_size = 0;
trident->synth.max_size = max_wavetable_size * 1024;
trident->irq = -1;
+ card->private_free = snd_trident_free;
trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
pci_set_master(pci);
err = pci_request_regions(pci, "Trident Audio");
- if (err < 0) {
- kfree(trident);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
trident->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, trident)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_trident_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, trident)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_trident_free(trident);
return -EBUSY;
}
trident->irq = pci->irq;
@@ -3565,13 +3548,10 @@ int snd_trident_create(struct snd_card *card,
/* allocate 16k-aligned TLB for NX cards */
trident->tlb.entries = NULL;
- trident->tlb.buffer.area = NULL;
if (trident->device == TRIDENT_DEVICE_ID_NX) {
err = snd_trident_tlb_alloc(trident);
- if (err < 0) {
- snd_trident_free(trident);
+ if (err < 0)
return err;
- }
}
trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -3591,16 +3571,8 @@ int snd_trident_create(struct snd_card *card,
snd_BUG();
break;
}
- if (err < 0) {
- snd_trident_free(trident);
- return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops);
- if (err < 0) {
- snd_trident_free(trident);
+ if (err < 0)
return err;
- }
err = snd_trident_mixer(trident, pcm_spdif_device);
if (err < 0)
@@ -3624,7 +3596,6 @@ int snd_trident_create(struct snd_card *card,
snd_trident_enable_eso(trident);
snd_trident_proc_init(trident);
- *rtrident = trident;
return 0;
}
@@ -3634,14 +3605,16 @@ int snd_trident_create(struct snd_card *card,
Description: This routine will free the device specific class for
the 4DWave card.
- Parameters: trident - device specific private data for 4DWave card
+ Parameters: card - card to release
Returns: None.
---------------------------------------------------------------------------*/
-static int snd_trident_free(struct snd_trident *trident)
+static void snd_trident_free(struct snd_card *card)
{
+ struct snd_trident *trident = card->private_data;
+
snd_trident_free_gameport(trident);
snd_trident_disable_eso(trident);
// Disable S/PDIF out
@@ -3650,19 +3623,10 @@ static int snd_trident_free(struct snd_trident *trident)
else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
}
- if (trident->irq >= 0)
- free_irq(trident->irq, trident);
- if (trident->tlb.buffer.area) {
+ if (trident->tlb.buffer) {
outl(0, TRID_REG(trident, NX_TLBC));
snd_util_memhdr_free(trident->tlb.memhdr);
- if (trident->tlb.silent_page.area)
- snd_dma_free_pages(&trident->tlb.silent_page);
- snd_dma_free_pages(&trident->tlb.buffer);
}
- pci_release_regions(trident->pci);
- pci_disable_device(trident->pci);
- kfree(trident);
- return 0;
}
/*---------------------------------------------------------------------------
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 4ad3855101c9..05de2b9f4ed7 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -31,7 +31,7 @@
/* fill TLB entrie(s) corresponding to page with ptr */
#define set_tlb_bus(trident,page,addr) __set_tlb_bus(trident,page,addr)
/* fill TLB entrie(s) corresponding to page with silence pointer */
-#define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, trident->tlb.silent_page.addr)
+#define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, trident->tlb.silent_page->addr)
/* get aligned page from offset address */
#define get_aligned_page(offset) ((offset) >> 12)
/* get offset address from aligned page */
@@ -58,8 +58,8 @@ static inline void set_tlb_bus(struct snd_trident *trident, int page,
static inline void set_silent_tlb(struct snd_trident *trident, int page)
{
page <<= 1;
- __set_tlb_bus(trident, page, trident->tlb.silent_page.addr);
- __set_tlb_bus(trident, page+1, trident->tlb.silent_page.addr);
+ __set_tlb_bus(trident, page, trident->tlb.silent_page->addr);
+ __set_tlb_bus(trident, page+1, trident->tlb.silent_page->addr);
}
#else
@@ -92,7 +92,7 @@ static inline void set_silent_tlb(struct snd_trident *trident, int page)
int i;
page *= UNIT_PAGES;
for (i = 0; i < UNIT_PAGES; i++, page++)
- __set_tlb_bus(trident, page, trident->tlb.silent_page.addr);
+ __set_tlb_bus(trident, page, trident->tlb.silent_page->addr);
}
#endif /* PAGE_SIZE */
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 943813a06abc..65514f7e42d7 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1911,13 +1911,12 @@ static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_overrid
static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
{
struct gameport *gp;
- struct resource *r;
if (!joystick)
return -ENODEV;
- r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport");
- if (!r) {
+ if (!devm_request_region(chip->card->dev, JOYSTICK_ADDR, 8,
+ "VIA686 gameport")) {
dev_warn(chip->card->dev, "cannot reserve joystick port %#x\n",
JOYSTICK_ADDR);
return -EBUSY;
@@ -1927,7 +1926,6 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
if (!gp) {
dev_err(chip->card->dev,
"cannot allocate memory for gameport\n");
- release_and_free_resource(r);
return -ENOMEM;
}
@@ -1935,7 +1933,6 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
gameport_set_dev_parent(gp, &chip->pci->dev);
gp->io = JOYSTICK_ADDR;
- gameport_set_port_data(gp, r);
/* Enable legacy joystick port */
*legacy |= VIA_FUNC_ENABLE_GAME;
@@ -1949,11 +1946,8 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac
static void snd_via686_free_gameport(struct via82xx *chip)
{
if (chip->gameport) {
- struct resource *r = gameport_get_port_data(chip->gameport);
-
gameport_unregister_port(chip->gameport);
chip->gameport = NULL;
- release_and_free_resource(r);
}
}
#else
@@ -2063,7 +2057,8 @@ static int snd_via686_init_misc(struct via82xx *chip)
}
}
if (mpu_port >= 0x200)
- chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401");
+ chip->mpu_res = devm_request_region(&chip->pci->dev, mpu_port,
+ 2, "VIA82xx MPU401");
if (chip->mpu_res) {
if (rev_h)
legacy |= VIA_FUNC_MIDI_PNP; /* enable PCI I/O 2 */
@@ -2302,61 +2297,35 @@ static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume
#define SND_VIA82XX_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
-static int snd_via82xx_free(struct via82xx *chip)
+static void snd_via82xx_free(struct snd_card *card)
{
+ struct via82xx *chip = card->private_data;
unsigned int i;
- if (chip->irq < 0)
- goto __end_hw;
/* disable interrupts */
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- __end_hw:
- release_and_free_resource(chip->mpu_res);
- pci_release_regions(chip->pci);
-
if (chip->chip_type == TYPE_VIA686) {
snd_via686_free_gameport(chip);
pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy);
pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg);
}
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_via82xx_dev_free(struct snd_device *device)
-{
- struct via82xx *chip = device->device_data;
- return snd_via82xx_free(chip);
}
static int snd_via82xx_create(struct snd_card *card,
struct pci_dev *pci,
int chip_type,
int revision,
- unsigned int ac97_clock,
- struct via82xx **r_via)
+ unsigned int ac97_clock)
{
- struct via82xx *chip;
+ struct via82xx *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_via82xx_dev_free,
- };
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
chip->chip_type = chip_type;
chip->revision = revision;
@@ -2373,44 +2342,31 @@ static int snd_via82xx_create(struct snd_card *card,
chip->old_legacy & ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM));
err = pci_request_regions(pci, card->driver);
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
chip->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq,
- chip_type == TYPE_VIA8233 ?
- snd_via8233_interrupt : snd_via686_interrupt,
- IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq,
+ chip_type == TYPE_VIA8233 ?
+ snd_via8233_interrupt : snd_via686_interrupt,
+ IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_via82xx_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_via82xx_free;
if (ac97_clock >= 8000 && ac97_clock <= 48000)
chip->ac97_clock = ac97_clock;
err = snd_via82xx_chip_init(chip);
- if (err < 0) {
- snd_via82xx_free(chip);
- return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_via82xx_free(chip);
+ if (err < 0)
return err;
- }
/* The 8233 ac97 controller does not implement the master bit
* in the pci command register. IMHO this is a violation of the PCI spec.
* We call pci_set_master here because it does not hurt. */
pci_set_master(pci);
-
- *r_via = chip;
return 0;
}
@@ -2511,9 +2467,11 @@ static int snd_via82xx_probe(struct pci_dev *pci,
unsigned int i;
int err;
- err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
card_type = pci_id->driver_data;
switch (card_type) {
@@ -2552,36 +2510,34 @@ static int snd_via82xx_probe(struct pci_dev *pci,
break;
default:
dev_err(card->dev, "invalid card type %d\n", card_type);
- err = -EINVAL;
- goto __error;
+ return -EINVAL;
}
err = snd_via82xx_create(card, pci, chip_type, pci->revision,
- ac97_clock, &chip);
+ ac97_clock);
if (err < 0)
- goto __error;
- card->private_data = chip;
+ return err;
err = snd_via82xx_mixer_new(chip, ac97_quirk);
if (err < 0)
- goto __error;
+ return err;
if (chip_type == TYPE_VIA686) {
err = snd_via686_pcm_new(chip);
if (err < 0)
- goto __error;
+ return err;
err = snd_via686_init_misc(chip);
if (err < 0)
- goto __error;
+ return err;
} else {
if (chip_type == TYPE_VIA8233A) {
err = snd_via8233a_pcm_new(chip);
if (err < 0)
- goto __error;
+ return err;
// chip->dxs_fixed = 1; /* FIXME: use 48k for DXS #3? */
} else {
err = snd_via8233_pcm_new(chip);
if (err < 0)
- goto __error;
+ return err;
if (dxs_support == VIA_DXS_48K)
chip->dxs_fixed = 1;
else if (dxs_support == VIA_DXS_NO_VRA)
@@ -2593,7 +2549,7 @@ static int snd_via82xx_probe(struct pci_dev *pci,
}
err = snd_via8233_init_misc(chip);
if (err < 0)
- goto __error;
+ return err;
}
/* disable interrupts */
@@ -2607,28 +2563,16 @@ static int snd_via82xx_probe(struct pci_dev *pci,
snd_via82xx_proc_init(chip);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
return 0;
-
- __error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_via82xx_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver via82xx_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_via82xx_ids,
.probe = snd_via82xx_probe,
- .remove = snd_via82xx_remove,
.driver = {
.pm = SND_VIA82XX_PM_OPS,
},
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 07278a3dc8c1..234f7fbed236 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1048,95 +1048,57 @@ static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume
#define SND_VIA82XX_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
-static int snd_via82xx_free(struct via82xx_modem *chip)
+static void snd_via82xx_free(struct snd_card *card)
{
+ struct via82xx_modem *chip = card->private_data;
unsigned int i;
- if (chip->irq < 0)
- goto __end_hw;
/* disable interrupts */
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
-
- __end_hw:
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_via82xx_dev_free(struct snd_device *device)
-{
- struct via82xx_modem *chip = device->device_data;
- return snd_via82xx_free(chip);
}
static int snd_via82xx_create(struct snd_card *card,
struct pci_dev *pci,
int chip_type,
int revision,
- unsigned int ac97_clock,
- struct via82xx_modem **r_via)
+ unsigned int ac97_clock)
{
- struct via82xx_modem *chip;
+ struct via82xx_modem *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_via82xx_dev_free,
- };
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
spin_lock_init(&chip->reg_lock);
chip->card = card;
chip->pci = pci;
chip->irq = -1;
err = pci_request_regions(pci, card->driver);
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
chip->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_via82xx_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_via82xx_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_via82xx_free;
if (ac97_clock >= 8000 && ac97_clock <= 48000)
chip->ac97_clock = ac97_clock;
err = snd_via82xx_chip_init(chip);
- if (err < 0) {
- snd_via82xx_free(chip);
- return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_via82xx_free(chip);
+ if (err < 0)
return err;
- }
/* The 8233 ac97 controller does not implement the master bit
* in the pci command register. IMHO this is a violation of the PCI spec.
* We call pci_set_master here because it does not hurt. */
pci_set_master(pci);
-
- *r_via = chip;
return 0;
}
@@ -1150,9 +1112,11 @@ static int snd_via82xx_probe(struct pci_dev *pci,
unsigned int i;
int err;
- err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
card_type = pci_id->driver_data;
switch (card_type) {
@@ -1162,22 +1126,20 @@ static int snd_via82xx_probe(struct pci_dev *pci,
break;
default:
dev_err(card->dev, "invalid card type %d\n", card_type);
- err = -EINVAL;
- goto __error;
+ return -EINVAL;
}
err = snd_via82xx_create(card, pci, chip_type, pci->revision,
- ac97_clock, &chip);
+ ac97_clock);
if (err < 0)
- goto __error;
- card->private_data = chip;
+ return err;
err = snd_via82xx_mixer_new(chip);
if (err < 0)
- goto __error;
+ return err;
err = snd_via686_pcm_new(chip);
if (err < 0)
- goto __error;
+ return err;
/* disable interrupts */
for (i = 0; i < chip->num_devs; i++)
@@ -1189,28 +1151,16 @@ static int snd_via82xx_probe(struct pci_dev *pci,
snd_via82xx_proc_init(chip);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
return 0;
-
- __error:
- snd_card_free(card);
- return err;
-}
-
-static void snd_via82xx_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver via82xx_modem_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_via82xx_modem_ids,
.probe = snd_via82xx_probe,
- .remove = snd_via82xx_remove,
.driver = {
.pm = SND_VIA82XX_PM_OPS,
},
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 04c7204cb7bc..f48cc20b9e8a 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -100,26 +100,6 @@ static const struct snd_vx_hardware vx222_mic_hw = {
/*
*/
-static int snd_vx222_free(struct vx_core *chip)
-{
- struct snd_vx222 *vx = to_vx222(chip);
-
- if (chip->irq >= 0)
- free_irq(chip->irq, (void*)chip);
- if (vx->port[0])
- pci_release_regions(vx->pci);
- pci_disable_device(vx->pci);
- kfree(chip);
- return 0;
-}
-
-static int snd_vx222_dev_free(struct snd_device *device)
-{
- struct vx_core *chip = device->device_data;
- return snd_vx222_free(chip);
-}
-
-
static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
const struct snd_vx_hardware *hw,
struct snd_vx222 **rchip)
@@ -127,13 +107,10 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
struct vx_core *chip;
struct snd_vx222 *vx;
int i, err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_vx222_dev_free,
- };
const struct snd_vx_ops *vx_ops;
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
pci_set_master(pci);
@@ -141,38 +118,26 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
vx_ops = hw->type == VX_TYPE_BOARD ? &vx222_old_ops : &vx222_ops;
chip = snd_vx_create(card, hw, vx_ops,
sizeof(struct snd_vx222) - sizeof(struct vx_core));
- if (! chip) {
- pci_disable_device(pci);
+ if (!chip)
return -ENOMEM;
- }
vx = to_vx222(chip);
vx->pci = pci;
err = pci_request_regions(pci, CARD_NAME);
- if (err < 0) {
- snd_vx222_free(chip);
+ if (err < 0)
return err;
- }
for (i = 0; i < 2; i++)
vx->port[i] = pci_resource_start(pci, i + 1);
- if (request_threaded_irq(pci->irq, snd_vx_irq_handler,
- snd_vx_threaded_irq_handler, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (devm_request_threaded_irq(&pci->dev, pci->irq, snd_vx_irq_handler,
+ snd_vx_threaded_irq_handler, IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_vx222_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_vx222_free(chip);
- return err;
- }
-
- *rchip = vx;
return 0;
}
@@ -193,8 +158,8 @@ static int snd_vx222_probe(struct pci_dev *pci,
return -ENOENT;
}
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+ 0, &card);
if (err < 0)
return err;
@@ -211,10 +176,8 @@ static int snd_vx222_probe(struct pci_dev *pci,
break;
}
err = snd_vx222_create(card, pci, hw, &vx);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
card->private_data = vx;
vx->core.ibl.size = ibl[dev];
@@ -228,27 +191,18 @@ static int snd_vx222_probe(struct pci_dev *pci,
#endif
err = snd_vx_setup_firmware(&vx->core);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_vx222_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
#ifdef CONFIG_PM_SLEEP
static int snd_vx222_suspend(struct device *dev)
{
@@ -276,7 +230,6 @@ static struct pci_driver vx222_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_vx222_ids,
.probe = snd_vx222_probe,
- .remove = snd_vx222_remove,
.driver = {
.pm = SND_VX222_PM_OPS,
},
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 7e32d57147ff..1e198e4d57b8 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -105,7 +105,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
}
if (!r) {
- r = request_region(io_port, 1, "YMFPCI gameport");
+ r = devm_request_region(&chip->pci->dev, io_port, 1,
+ "YMFPCI gameport");
if (!r) {
dev_err(chip->card->dev,
"joystick port %#x is in use.\n", io_port);
@@ -117,7 +118,6 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
if (!gp) {
dev_err(chip->card->dev,
"cannot allocate memory for gameport\n");
- release_and_free_resource(r);
return -ENOMEM;
}
@@ -126,7 +126,6 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
gameport_set_dev_parent(gp, &chip->pci->dev);
gp->io = io_port;
- gameport_set_port_data(gp, r);
if (chip->pci->device >= 0x0010) /* YMF 744/754 */
pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
@@ -142,12 +141,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
void snd_ymfpci_free_gameport(struct snd_ymfpci *chip)
{
if (chip->gameport) {
- struct resource *r = gameport_get_port_data(chip->gameport);
-
gameport_unregister_port(chip->gameport);
chip->gameport = NULL;
-
- release_and_free_resource(r);
}
}
#else
@@ -176,9 +171,10 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
}
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
switch (pci_id->device) {
case 0x0004: str = "YMF724"; model = "DS-1"; break;
@@ -199,7 +195,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
fm_port[dev] = pci_resource_start(pci, 1);
}
if (fm_port[dev] > 0)
- fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3");
+ fm_res = devm_request_region(&pci->dev, fm_port[dev],
+ 4, "YMFPCI OPL3");
if (fm_res) {
legacy_ctrl |= YMFPCI_LEGACY_FMEN;
pci_write_config_word(pci, PCIR_DSXG_FMBASE, fm_port[dev]);
@@ -209,7 +206,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
mpu_port[dev] = pci_resource_start(pci, 1) + 0x20;
}
if (mpu_port[dev] > 0)
- mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401");
+ mpu_res = devm_request_region(&pci->dev, mpu_port[dev],
+ 2, "YMFPCI MPU401");
if (mpu_res) {
legacy_ctrl |= YMFPCI_LEGACY_MEN;
pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]);
@@ -223,7 +221,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
default: fm_port[dev] = 0; break;
}
if (fm_port[dev] > 0)
- fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3");
+ fm_res = devm_request_region(&pci->dev, fm_port[dev],
+ 4, "YMFPCI OPL3");
if (fm_res) {
legacy_ctrl |= YMFPCI_LEGACY_FMEN;
} else {
@@ -238,7 +237,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
default: mpu_port[dev] = 0; break;
}
if (mpu_port[dev] > 0)
- mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401");
+ mpu_res = devm_request_region(&pci->dev, mpu_port[dev],
+ 2, "YMFPCI MPU401");
if (mpu_res) {
legacy_ctrl |= YMFPCI_LEGACY_MEN;
} else {
@@ -253,15 +253,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
pci_read_config_word(pci, PCIR_DSXG_LEGACY, &old_legacy_ctrl);
pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
pci_write_config_word(pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
- err = snd_ymfpci_create(card, pci, old_legacy_ctrl, &chip);
- if (err < 0) {
- release_and_free_resource(mpu_res);
- release_and_free_resource(fm_res);
- goto free_card;
- }
- chip->fm_res = fm_res;
- chip->mpu_res = mpu_res;
- card->private_data = chip;
+ err = snd_ymfpci_create(card, pci, old_legacy_ctrl);
+ if (err < 0)
+ return err;
strcpy(card->driver, str);
sprintf(card->shortname, "Yamaha %s (%s)", model, str);
@@ -271,30 +265,30 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
chip->irq);
err = snd_ymfpci_pcm(chip, 0);
if (err < 0)
- goto free_card;
+ return err;
err = snd_ymfpci_pcm_spdif(chip, 1);
if (err < 0)
- goto free_card;
+ return err;
err = snd_ymfpci_mixer(chip, rear_switch[dev]);
if (err < 0)
- goto free_card;
+ return err;
if (chip->ac97->ext_id & AC97_EI_SDAC) {
err = snd_ymfpci_pcm_4ch(chip, 2);
if (err < 0)
- goto free_card;
+ return err;
err = snd_ymfpci_pcm2(chip, 3);
if (err < 0)
- goto free_card;
+ return err;
}
err = snd_ymfpci_timer(chip, 0);
if (err < 0)
- goto free_card;
+ return err;
- if (chip->mpu_res) {
+ if (mpu_res) {
err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
mpu_port[dev],
MPU401_INFO_INTEGRATED |
@@ -308,7 +302,7 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
}
}
- if (chip->fm_res) {
+ if (fm_res) {
err = snd_opl3_create(card,
fm_port[dev],
fm_port[dev] + 2,
@@ -323,7 +317,7 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0) {
dev_err(card->dev, "cannot create opl3 hwdep\n");
- goto free_card;
+ return err;
}
}
}
@@ -332,27 +326,17 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
- goto free_card;
+ return err;
pci_set_drvdata(pci, card);
dev++;
return 0;
-
-free_card:
- snd_card_free(card);
- return err;
-}
-
-static void snd_card_ymfpci_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
}
static struct pci_driver ymfpci_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_ymfpci_ids,
.probe = snd_card_ymfpci_probe,
- .remove = snd_card_ymfpci_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_ymfpci_pm,
diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h
index c73d8a5f4d0b..66968776478a 100644
--- a/sound/pci/ymfpci/ymfpci.h
+++ b/sound/pci/ymfpci/ymfpci.h
@@ -275,16 +275,13 @@ struct snd_ymfpci {
unsigned char rev; /* PCI revision */
unsigned long reg_area_phys;
void __iomem *reg_area_virt;
- struct resource *res_reg_area;
- struct resource *fm_res;
- struct resource *mpu_res;
unsigned short old_legacy_ctrl;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
#endif
- struct snd_dma_buffer work_ptr;
+ struct snd_dma_buffer *work_ptr;
unsigned int bank_size_playback;
unsigned int bank_size_capture;
@@ -358,8 +355,7 @@ struct snd_ymfpci {
int snd_ymfpci_create(struct snd_card *card,
struct pci_dev *pci,
- unsigned short old_legacy_ctrl,
- struct snd_ymfpci ** rcodec);
+ unsigned short old_legacy_ctrl);
void snd_ymfpci_free_gameport(struct snd_ymfpci *chip);
extern const struct dev_pm_ops snd_ymfpci_pm;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 8fd060769882..c80114c0ad7b 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2116,11 +2116,12 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
chip->work_size;
/* work_ptr must be aligned to 256 bytes, but it's already
covered with the kernel page allocation mechanism */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
- size, &chip->work_ptr) < 0)
+ chip->work_ptr = snd_devm_alloc_pages(&chip->pci->dev,
+ SNDRV_DMA_TYPE_DEV, size);
+ if (!chip->work_ptr)
return -ENOMEM;
- ptr = chip->work_ptr.area;
- ptr_addr = chip->work_ptr.addr;
+ ptr = chip->work_ptr->area;
+ ptr_addr = chip->work_ptr->addr;
memset(ptr, 0, size); /* for sure */
chip->bank_base_playback = ptr;
@@ -2165,7 +2166,7 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
chip->work_base_addr = ptr_addr;
snd_BUG_ON(ptr + chip->work_size !=
- chip->work_ptr.area + chip->work_ptr.bytes);
+ chip->work_ptr->area + chip->work_ptr->bytes);
snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, chip->bank_base_playback_addr);
snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, chip->bank_base_capture_addr);
@@ -2196,65 +2197,32 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
return 0;
}
-static int snd_ymfpci_free(struct snd_ymfpci *chip)
+static void snd_ymfpci_free(struct snd_card *card)
{
+ struct snd_ymfpci *chip = card->private_data;
u16 ctrl;
- if (snd_BUG_ON(!chip))
- return -EINVAL;
-
- if (chip->res_reg_area) { /* don't touch busy hardware */
- snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
- snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
- snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0);
- snd_ymfpci_writel(chip, YDSXGR_STATUS, ~0);
- snd_ymfpci_disable_dsp(chip);
- snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0);
- snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0);
- snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0);
- snd_ymfpci_writel(chip, YDSXGR_WORKBASE, 0);
- snd_ymfpci_writel(chip, YDSXGR_WORKSIZE, 0);
- ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
- snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
- }
+ snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
+ snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
+ snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0);
+ snd_ymfpci_writel(chip, YDSXGR_STATUS, ~0);
+ snd_ymfpci_disable_dsp(chip);
+ snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0);
+ snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0);
+ snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0);
+ snd_ymfpci_writel(chip, YDSXGR_WORKBASE, 0);
+ snd_ymfpci_writel(chip, YDSXGR_WORKSIZE, 0);
+ ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
+ snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
snd_ymfpci_ac3_done(chip);
- /* Set PCI device to D3 state */
-#if 0
- /* FIXME: temporarily disabled, otherwise we cannot fire up
- * the chip again unless reboot. ACPI bug?
- */
- pci_set_power_state(chip->pci, PCI_D3hot);
-#endif
-
-#ifdef CONFIG_PM_SLEEP
- kfree(chip->saved_regs);
-#endif
- if (chip->irq >= 0)
- free_irq(chip->irq, chip);
- release_and_free_resource(chip->mpu_res);
- release_and_free_resource(chip->fm_res);
snd_ymfpci_free_gameport(chip);
- iounmap(chip->reg_area_virt);
- if (chip->work_ptr.area)
- snd_dma_free_pages(&chip->work_ptr);
- release_and_free_resource(chip->res_reg_area);
-
pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
- pci_disable_device(chip->pci);
release_firmware(chip->dsp_microcode);
release_firmware(chip->controller_microcode);
- kfree(chip);
- return 0;
-}
-
-static int snd_ymfpci_dev_free(struct snd_device *device)
-{
- struct snd_ymfpci *chip = device->device_data;
- return snd_ymfpci_free(chip);
}
#ifdef CONFIG_PM_SLEEP
@@ -2346,27 +2314,16 @@ SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume);
int snd_ymfpci_create(struct snd_card *card,
struct pci_dev *pci,
- unsigned short old_legacy_ctrl,
- struct snd_ymfpci **rchip)
+ unsigned short old_legacy_ctrl)
{
- struct snd_ymfpci *chip;
+ struct snd_ymfpci *chip = card->private_data;
int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_ymfpci_dev_free,
- };
- *rchip = NULL;
-
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
chip->old_legacy_ctrl = old_legacy_ctrl;
spin_lock_init(&chip->reg_lock);
spin_lock_init(&chip->voice_lock);
@@ -2377,71 +2334,59 @@ int snd_ymfpci_create(struct snd_card *card,
chip->irq = -1;
chip->device_id = pci->device;
chip->rev = pci->revision;
- chip->reg_area_phys = pci_resource_start(pci, 0);
- chip->reg_area_virt = ioremap(chip->reg_area_phys, 0x8000);
- pci_set_master(pci);
- chip->src441_used = -1;
- chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI");
- if (!chip->res_reg_area) {
+ err = pci_request_regions(pci, "YMFPCI");
+ if (err < 0)
+ return err;
+
+ chip->reg_area_phys = pci_resource_start(pci, 0);
+ chip->reg_area_virt = devm_ioremap(&pci->dev, chip->reg_area_phys, 0x8000);
+ if (!chip->reg_area_virt) {
dev_err(chip->card->dev,
"unable to grab memory region 0x%lx-0x%lx\n",
chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1);
- err = -EBUSY;
- goto free_chip;
+ return -EBUSY;
}
- if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED,
+ pci_set_master(pci);
+ chip->src441_used = -1;
+
+ if (devm_request_irq(&pci->dev, pci->irq, snd_ymfpci_interrupt, IRQF_SHARED,
KBUILD_MODNAME, chip)) {
dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
- err = -EBUSY;
- goto free_chip;
+ return -EBUSY;
}
chip->irq = pci->irq;
card->sync_irq = chip->irq;
+ card->private_free = snd_ymfpci_free;
snd_ymfpci_aclink_reset(pci);
- if (snd_ymfpci_codec_ready(chip, 0) < 0) {
- err = -EIO;
- goto free_chip;
- }
+ if (snd_ymfpci_codec_ready(chip, 0) < 0)
+ return -EIO;
err = snd_ymfpci_request_firmware(chip);
if (err < 0) {
dev_err(chip->card->dev, "firmware request failed: %d\n", err);
- goto free_chip;
+ return err;
}
snd_ymfpci_download_image(chip);
udelay(100); /* seems we need a delay after downloading image.. */
- if (snd_ymfpci_memalloc(chip) < 0) {
- err = -EIO;
- goto free_chip;
- }
+ if (snd_ymfpci_memalloc(chip) < 0)
+ return -EIO;
err = snd_ymfpci_ac3_init(chip);
if (err < 0)
- goto free_chip;
+ return err;
#ifdef CONFIG_PM_SLEEP
- chip->saved_regs = kmalloc_array(YDSXGR_NUM_SAVED_REGS, sizeof(u32),
- GFP_KERNEL);
- if (chip->saved_regs == NULL) {
- err = -ENOMEM;
- goto free_chip;
- }
+ chip->saved_regs = devm_kmalloc_array(&pci->dev, YDSXGR_NUM_SAVED_REGS,
+ sizeof(u32), GFP_KERNEL);
+ if (!chip->saved_regs)
+ return -ENOMEM;
#endif
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0)
- goto free_chip;
-
snd_ymfpci_proc_init(card, chip);
- *rchip = chip;
return 0;
-
-free_chip:
- snd_ymfpci_free(chip);
- return err;
}
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 0dfb6a943b60..7a0f0e73ceb2 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -51,19 +51,6 @@ static void vxpocket_release(struct pcmcia_device *link)
}
/*
- * destructor, called from snd_card_free_when_closed()
- */
-static int snd_vxpocket_dev_free(struct snd_device *device)
-{
- struct vx_core *chip = device->device_data;
-
- snd_vx_free_firmware(chip);
- kfree(chip);
- return 0;
-}
-
-
-/*
* Hardware information
*/
@@ -122,21 +109,12 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
{
struct vx_core *chip;
struct snd_vxpocket *vxp;
- static const struct snd_device_ops ops = {
- .dev_free = snd_vxpocket_dev_free,
- };
- int err;
chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops,
sizeof(struct snd_vxpocket) - sizeof(struct vx_core));
if (!chip)
return -ENOMEM;
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- kfree(chip);
- return err;
- }
chip->ibl.size = ibl;
vxp = to_vxpocket(chip);
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index ba5a85bf7412..49ff5e73e9ba 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -52,3 +52,12 @@ config SND_SOC_AMD_RENOIR_MACH
depends on SND_SOC_AMD_RENOIR
help
This option enables machine driver for DMIC
+
+config SND_SOC_AMD_ACP5x
+ tristate "AMD Audio Coprocessor-v5.x I2S support"
+ depends on X86 && PCI
+ help
+ This option enables ACP v5.x support on AMD platform
+
+ By enabling this flag build will trigger for ACP PCI driver,
+ ACP DMA driver, CPU DAI driver.
diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
index e6df2f72a2a1..07150d26f315 100644
--- a/sound/soc/amd/Makefile
+++ b/sound/soc/amd/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/
obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o
obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/
+obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/
diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c
index 3c60c5f96dcb..b3df98a9f9f3 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -756,15 +756,9 @@ static int cz_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev,
- "devm_snd_soc_register_card(%s) failed: %d\n",
- card->name, ret);
- else
- dev_dbg(&pdev->dev,
- "devm_snd_soc_register_card(%s) probe deferred: %d\n",
- card->name, ret);
- return ret;
+ return dev_err_probe(&pdev->dev, ret,
+ "devm_snd_soc_register_card(%s) failed\n",
+ card->name);
}
bt_uart_enable = !device_property_read_bool(&pdev->dev,
"bt-pad-enable");
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index cc1ce6f22caa..11b3c4f39eba 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -156,7 +156,7 @@ static void config_acp_dma_channel(void __iomem *acp_mmio, u8 ch_num,
acp_reg_write(priority_level, acp_mmio, mmACP_DMA_PRIO_0 + ch_num);
}
-/* Initialize a dma descriptor in SRAM based on descritor information passed */
+/* Initialize a dma descriptor in SRAM based on descriptor information passed */
static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
u16 descr_idx,
acp_dma_dscr_transfer_t *descr_info)
@@ -288,7 +288,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
&dmadscr[i]);
}
pre_config_reset(acp_mmio, ch);
- /* Configure the DMA channel with the above descriptore */
+ /* Configure the DMA channel with the above descriptor */
config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
NUM_DSCRS_PER_CHANNEL,
ACP_DMA_PRIORITY_LEVEL_NORMAL);
@@ -322,7 +322,7 @@ static void acp_pte_config(void __iomem *acp_mmio, dma_addr_t addr,
high |= BIT(31);
acp_reg_write(high, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
- /* Move to next physically contiguos page */
+ /* Move to next physically contiguous page */
addr += PAGE_SIZE;
}
}
@@ -602,11 +602,11 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
acp_reg_write(val, acp_mmio, mmACP_BT_UART_PAD_SEL);
}
- /* initiailize Onion control DAGB register */
+ /* initialize Onion control DAGB register */
acp_reg_write(ACP_ONION_CNTL_DEFAULT, acp_mmio,
mmACP_AXI2DAGB_ONION_CNTL);
- /* initiailize Garlic control DAGB registers */
+ /* initialize Garlic control DAGB registers */
acp_reg_write(ACP_GARLIC_CNTL_DEFAULT, acp_mmio,
mmACP_AXI2DAGB_GARLIC_CNTL);
@@ -621,7 +621,7 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
acp_reg_write(ACP_SRAM_BASE_ADDRESS, acp_mmio,
mmACP_DMA_DESC_BASE_ADDR);
- /* Num of descriptiors in SRAM 0x4, means 256 descriptors;(64 * 4) */
+ /* Num of descriptors in SRAM 0x4, means 256 descriptors;(64 * 4) */
acp_reg_write(0x4, acp_mmio, mmACP_DMA_DESC_MAX_NUM_DSCR);
acp_reg_write(ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK,
acp_mmio, mmACP_EXTERNAL_INTR_CNTL);
@@ -1035,13 +1035,6 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
return bytes_to_frames(runtime, pos);
}
-static int acp_dma_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return snd_pcm_lib_default_mmap(substream, vma);
-}
-
static int acp_dma_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -1205,7 +1198,6 @@ static const struct snd_soc_component_driver acp_asoc_platform = {
.hw_params = acp_dma_hw_params,
.trigger = acp_dma_trigger,
.pointer = acp_dma_pointer,
- .mmap = acp_dma_mmap,
.prepare = acp_dma_prepare,
.pcm_construct = acp_dma_new,
};
diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c
index d9980aba2910..e561464f7d60 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -512,17 +512,11 @@ static int acp3x_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev,
- "devm_snd_soc_register_card(%s) failed: %d\n",
- card->name, ret);
- else
- dev_dbg(&pdev->dev,
- "devm_snd_soc_register_card(%s) probe deferred: %d\n",
- card->name, ret);
+ return dev_err_probe(&pdev->dev, ret,
+ "devm_snd_soc_register_card(%s) failed\n",
+ card->name);
}
-
- return ret;
+ return 0;
}
static const struct acpi_device_id acp3x_audio_acpi_match[] = {
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 597d7c4b2a6b..75c06697fa09 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -147,7 +147,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
high |= BIT(31);
rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val
+ 4);
- /* Move to next physically contiguos page */
+ /* Move to next physically contiguous page */
val += 8;
addr += PAGE_SIZE;
}
@@ -320,13 +320,6 @@ static int acp3x_dma_new(struct snd_soc_component *component,
return 0;
}
-static int acp3x_dma_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return snd_pcm_lib_default_mmap(substream, vma);
-}
-
static int acp3x_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -370,7 +363,6 @@ static const struct snd_soc_component_driver acp3x_i2s_component = {
.close = acp3x_dma_close,
.hw_params = acp3x_dma_hw_params,
.pointer = acp3x_dma_pointer,
- .mmap = acp3x_dma_mmap,
.pcm_construct = acp3x_dma_new,
};
diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c
index 0391c28dd078..9dd22a2fa2e5 100644
--- a/sound/soc/amd/renoir/acp3x-pdm-dma.c
+++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c
@@ -291,13 +291,6 @@ static int acp_pdm_dma_new(struct snd_soc_component *component,
return 0;
}
-static int acp_pdm_dma_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return snd_pcm_lib_default_mmap(substream, vma);
-}
-
static int acp_pdm_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -375,7 +368,6 @@ static const struct snd_soc_component_driver acp_pdm_component = {
.close = acp_pdm_dma_close,
.hw_params = acp_pdm_dma_hw_params,
.pointer = acp_pdm_dma_pointer,
- .mmap = acp_pdm_dma_mmap,
.pcm_construct = acp_pdm_dma_new,
};
diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c
index 306134b89a82..5d979a7b77fb 100644
--- a/sound/soc/amd/renoir/acp3x-rn.c
+++ b/sound/soc/amd/renoir/acp3x-rn.c
@@ -54,10 +54,9 @@ static int acp_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
- dev_err(&pdev->dev,
- "snd_soc_register_card(%s) failed: %d\n",
- acp_card.name, ret);
- return ret;
+ return dev_err_probe(&pdev->dev, ret,
+ "snd_soc_register_card(%s) failed\n",
+ card->name);
}
return 0;
}
diff --git a/sound/soc/amd/vangogh/Makefile b/sound/soc/amd/vangogh/Makefile
new file mode 100644
index 000000000000..3353f93dc610
--- /dev/null
+++ b/sound/soc/amd/vangogh/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Vangogh platform Support
+snd-pci-acp5x-objs := pci-acp5x.o
+snd-acp5x-i2s-objs := acp5x-i2s.o
+snd-acp5x-pcm-dma-objs := acp5x-pcm-dma.o
+
+obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-pci-acp5x.o
+obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-i2s.o
+obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-pcm-dma.o
diff --git a/sound/soc/amd/vangogh/acp5x-i2s.c b/sound/soc/amd/vangogh/acp5x-i2s.c
new file mode 100644
index 000000000000..2705e57eb713
--- /dev/null
+++ b/sound/soc/amd/vangogh/acp5x-i2s.c
@@ -0,0 +1,427 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// AMD ALSA SoC PCM Driver
+//
+// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/dma-mapping.h>
+
+#include "acp5x.h"
+
+#define DRV_NAME "acp5x_i2s_playcap"
+
+static int acp5x_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct i2s_dev_data *adata;
+ int mode;
+
+ adata = snd_soc_dai_get_drvdata(cpu_dai);
+ mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ switch (mode) {
+ case SND_SOC_DAIFMT_I2S:
+ adata->tdm_mode = TDM_DISABLE;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ adata->tdm_mode = TDM_ENABLE;
+ break;
+ default:
+ return -EINVAL;
+ }
+ mode = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
+ switch (mode) {
+ case SND_SOC_DAIFMT_CBC_CFC:
+ adata->master_mode = I2S_MASTER_MODE_ENABLE;
+ break;
+ case SND_SOC_DAIFMT_CBP_CFP:
+ adata->master_mode = I2S_MASTER_MODE_DISABLE;
+ break;
+ }
+ return 0;
+}
+
+static int acp5x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
+ u32 tx_mask, u32 rx_mask,
+ int slots, int slot_width)
+{
+ struct i2s_dev_data *adata;
+ u32 frm_len;
+ u16 slot_len;
+
+ adata = snd_soc_dai_get_drvdata(cpu_dai);
+
+ /* These values are as per Hardware Spec */
+ switch (slot_width) {
+ case SLOT_WIDTH_8:
+ slot_len = 8;
+ break;
+ case SLOT_WIDTH_16:
+ slot_len = 16;
+ break;
+ case SLOT_WIDTH_24:
+ slot_len = 24;
+ break;
+ case SLOT_WIDTH_32:
+ slot_len = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ frm_len = FRM_LEN | (slots << 15) | (slot_len << 18);
+ adata->tdm_fmt = frm_len;
+ return 0;
+}
+
+static int acp5x_i2s_hwparams(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct i2s_stream_instance *rtd;
+ struct snd_soc_pcm_runtime *prtd;
+ struct snd_soc_card *card;
+ struct acp5x_platform_info *pinfo;
+ struct i2s_dev_data *adata;
+ union acp_i2stdm_mstrclkgen mclkgen;
+
+ u32 val;
+ u32 reg_val, frmt_reg, master_reg;
+ u32 lrclk_div_val, bclk_div_val;
+
+ lrclk_div_val = 0;
+ bclk_div_val = 0;
+ prtd = asoc_substream_to_rtd(substream);
+ rtd = substream->runtime->private_data;
+ card = prtd->card;
+ adata = snd_soc_dai_get_drvdata(dai);
+ pinfo = snd_soc_card_get_drvdata(card);
+ if (pinfo) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rtd->i2s_instance = pinfo->play_i2s_instance;
+ else
+ rtd->i2s_instance = pinfo->cap_i2s_instance;
+ }
+
+ /* These values are as per Hardware Spec */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_U8:
+ case SNDRV_PCM_FORMAT_S8:
+ rtd->xfer_resolution = 0x0;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ rtd->xfer_resolution = 0x02;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ rtd->xfer_resolution = 0x04;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ rtd->xfer_resolution = 0x05;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ reg_val = ACP_HSTDM_ITER;
+ frmt_reg = ACP_HSTDM_TXFRMT;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ reg_val = ACP_I2STDM_ITER;
+ frmt_reg = ACP_I2STDM_TXFRMT;
+ }
+ } else {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ reg_val = ACP_HSTDM_IRER;
+ frmt_reg = ACP_HSTDM_RXFRMT;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ reg_val = ACP_I2STDM_IRER;
+ frmt_reg = ACP_I2STDM_RXFRMT;
+ }
+ }
+ if (adata->tdm_mode) {
+ val = acp_readl(rtd->acp5x_base + reg_val);
+ acp_writel(val | 0x2, rtd->acp5x_base + reg_val);
+ acp_writel(adata->tdm_fmt, rtd->acp5x_base + frmt_reg);
+ }
+ val = acp_readl(rtd->acp5x_base + reg_val);
+ val &= ~ACP5x_ITER_IRER_SAMP_LEN_MASK;
+ val = val | (rtd->xfer_resolution << 3);
+ acp_writel(val, rtd->acp5x_base + reg_val);
+
+ if (adata->master_mode) {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ master_reg = ACP_I2STDM2_MSTRCLKGEN;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ master_reg = ACP_I2STDM0_MSTRCLKGEN;
+ break;
+ }
+ mclkgen.bits.i2stdm_master_mode = 0x1;
+ if (adata->tdm_mode)
+ mclkgen.bits.i2stdm_format_mode = 0x01;
+ else
+ mclkgen.bits.i2stdm_format_mode = 0x0;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ switch (params_rate(params)) {
+ case 8000:
+ bclk_div_val = 768;
+ break;
+ case 16000:
+ bclk_div_val = 384;
+ break;
+ case 24000:
+ bclk_div_val = 256;
+ break;
+ case 32000:
+ bclk_div_val = 192;
+ break;
+ case 44100:
+ case 48000:
+ bclk_div_val = 128;
+ break;
+ case 88200:
+ case 96000:
+ bclk_div_val = 64;
+ break;
+ case 192000:
+ bclk_div_val = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+ lrclk_div_val = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ switch (params_rate(params)) {
+ case 8000:
+ bclk_div_val = 384;
+ break;
+ case 16000:
+ bclk_div_val = 192;
+ break;
+ case 24000:
+ bclk_div_val = 128;
+ break;
+ case 32000:
+ bclk_div_val = 96;
+ break;
+ case 44100:
+ case 48000:
+ bclk_div_val = 64;
+ break;
+ case 88200:
+ case 96000:
+ bclk_div_val = 32;
+ break;
+ case 192000:
+ bclk_div_val = 16;
+ break;
+ default:
+ return -EINVAL;
+ }
+ lrclk_div_val = 64;
+ break;
+ default:
+ return -EINVAL;
+ }
+ mclkgen.bits.i2stdm_bclk_div_val = bclk_div_val;
+ mclkgen.bits.i2stdm_lrclk_div_val = lrclk_div_val;
+ acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg);
+ }
+ return 0;
+}
+
+static int acp5x_i2s_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct i2s_stream_instance *rtd;
+ u32 ret, val, period_bytes, reg_val, ier_val, water_val;
+ u32 buf_size, buf_reg;
+
+ rtd = substream->runtime->private_data;
+ period_bytes = frames_to_bytes(substream->runtime,
+ substream->runtime->period_size);
+ buf_size = frames_to_bytes(substream->runtime,
+ substream->runtime->buffer_size);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ rtd->bytescount = acp_get_byte_count(rtd,
+ substream->stream);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ water_val =
+ ACP_HS_TX_INTR_WATERMARK_SIZE;
+ reg_val = ACP_HSTDM_ITER;
+ ier_val = ACP_HSTDM_IER;
+ buf_reg = ACP_HS_TX_RINGBUFSIZE;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ water_val =
+ ACP_I2S_TX_INTR_WATERMARK_SIZE;
+ reg_val = ACP_I2STDM_ITER;
+ ier_val = ACP_I2STDM_IER;
+ buf_reg = ACP_I2S_TX_RINGBUFSIZE;
+ }
+ } else {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ water_val =
+ ACP_HS_RX_INTR_WATERMARK_SIZE;
+ reg_val = ACP_HSTDM_IRER;
+ ier_val = ACP_HSTDM_IER;
+ buf_reg = ACP_HS_RX_RINGBUFSIZE;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ water_val =
+ ACP_I2S_RX_INTR_WATERMARK_SIZE;
+ reg_val = ACP_I2STDM_IRER;
+ ier_val = ACP_I2STDM_IER;
+ buf_reg = ACP_I2S_RX_RINGBUFSIZE;
+ }
+ }
+ acp_writel(period_bytes, rtd->acp5x_base + water_val);
+ acp_writel(buf_size, rtd->acp5x_base + buf_reg);
+ val = acp_readl(rtd->acp5x_base + reg_val);
+ val = val | BIT(0);
+ acp_writel(val, rtd->acp5x_base + reg_val);
+ acp_writel(1, rtd->acp5x_base + ier_val);
+ ret = 0;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ reg_val = ACP_HSTDM_ITER;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ reg_val = ACP_I2STDM_ITER;
+ }
+
+ } else {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ reg_val = ACP_HSTDM_IRER;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ reg_val = ACP_I2STDM_IRER;
+ }
+ }
+ val = acp_readl(rtd->acp5x_base + reg_val);
+ val = val & ~BIT(0);
+ acp_writel(val, rtd->acp5x_base + reg_val);
+
+ if (!(acp_readl(rtd->acp5x_base + ACP_HSTDM_ITER) & BIT(0)) &&
+ !(acp_readl(rtd->acp5x_base + ACP_HSTDM_IRER) & BIT(0)))
+ acp_writel(0, rtd->acp5x_base + ACP_HSTDM_IER);
+ if (!(acp_readl(rtd->acp5x_base + ACP_I2STDM_ITER) & BIT(0)) &&
+ !(acp_readl(rtd->acp5x_base + ACP_I2STDM_IRER) & BIT(0)))
+ acp_writel(0, rtd->acp5x_base + ACP_I2STDM_IER);
+ ret = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static struct snd_soc_dai_ops acp5x_i2s_dai_ops = {
+ .hw_params = acp5x_i2s_hwparams,
+ .trigger = acp5x_i2s_trigger,
+ .set_fmt = acp5x_i2s_set_fmt,
+ .set_tdm_slot = acp5x_i2s_set_tdm_slot,
+};
+
+static const struct snd_soc_component_driver acp5x_dai_component = {
+ .name = "acp5x-i2s",
+};
+
+static struct snd_soc_dai_driver acp5x_i2s_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 96000,
+ },
+ .capture = {
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 96000,
+ },
+ .ops = &acp5x_i2s_dai_ops,
+};
+
+static int acp5x_dai_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct i2s_dev_data *adata;
+ int ret;
+
+ adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
+ GFP_KERNEL);
+ if (!adata)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+ return -ENOMEM;
+ }
+ adata->acp5x_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!adata->acp5x_base)
+ return -ENOMEM;
+
+ adata->master_mode = I2S_MASTER_MODE_ENABLE;
+ dev_set_drvdata(&pdev->dev, adata);
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &acp5x_dai_component,
+ &acp5x_i2s_dai, 1);
+ if (ret)
+ dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
+ return ret;
+}
+
+static struct platform_driver acp5x_dai_driver = {
+ .probe = acp5x_dai_probe,
+ .driver = {
+ .name = "acp5x_i2s_playcap",
+ },
+};
+
+module_platform_driver(acp5x_dai_driver);
+
+MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD ACP5.x CPU DAI Driver");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c
new file mode 100644
index 000000000000..f10de38976cb
--- /dev/null
+++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c
@@ -0,0 +1,517 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// AMD ALSA SoC PCM Driver
+//
+// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "acp5x.h"
+
+#define DRV_NAME "acp5x_i2s_dma"
+
+static const struct snd_pcm_hardware acp5x_pcm_hardware_playback = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .rate_min = 8000,
+ .rate_max = 96000,
+ .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
+ .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
+ .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
+ .periods_min = PLAYBACK_MIN_NUM_PERIODS,
+ .periods_max = PLAYBACK_MAX_NUM_PERIODS,
+};
+
+static const struct snd_pcm_hardware acp5x_pcm_hardware_capture = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .rate_min = 8000,
+ .rate_max = 96000,
+ .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
+ .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
+ .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
+ .periods_min = CAPTURE_MIN_NUM_PERIODS,
+ .periods_max = CAPTURE_MAX_NUM_PERIODS,
+};
+
+static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
+{
+ struct i2s_dev_data *vg_i2s_data;
+ u16 irq_flag;
+ u32 val;
+
+ vg_i2s_data = dev_id;
+ if (!vg_i2s_data)
+ return IRQ_NONE;
+
+ irq_flag = 0;
+ val = acp_readl(vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
+ if ((val & BIT(HS_TX_THRESHOLD)) && vg_i2s_data->play_stream) {
+ acp_writel(BIT(HS_TX_THRESHOLD), vg_i2s_data->acp5x_base +
+ ACP_EXTERNAL_INTR_STAT);
+ snd_pcm_period_elapsed(vg_i2s_data->play_stream);
+ irq_flag = 1;
+ }
+ if ((val & BIT(I2S_TX_THRESHOLD)) && vg_i2s_data->i2ssp_play_stream) {
+ acp_writel(BIT(I2S_TX_THRESHOLD),
+ vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
+ snd_pcm_period_elapsed(vg_i2s_data->i2ssp_play_stream);
+ irq_flag = 1;
+ }
+
+ if ((val & BIT(HS_RX_THRESHOLD)) && vg_i2s_data->capture_stream) {
+ acp_writel(BIT(HS_RX_THRESHOLD), vg_i2s_data->acp5x_base +
+ ACP_EXTERNAL_INTR_STAT);
+ snd_pcm_period_elapsed(vg_i2s_data->capture_stream);
+ irq_flag = 1;
+ }
+ if ((val & BIT(I2S_RX_THRESHOLD)) && vg_i2s_data->i2ssp_capture_stream) {
+ acp_writel(BIT(I2S_RX_THRESHOLD),
+ vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
+ snd_pcm_period_elapsed(vg_i2s_data->i2ssp_capture_stream);
+ irq_flag = 1;
+ }
+
+ if (irq_flag)
+ return IRQ_HANDLED;
+ else
+ return IRQ_NONE;
+}
+
+static void config_acp5x_dma(struct i2s_stream_instance *rtd, int direction)
+{
+ u16 page_idx;
+ u32 low, high, val, acp_fifo_addr, reg_fifo_addr;
+ u32 reg_dma_size, reg_fifo_size;
+ dma_addr_t addr;
+
+ addr = rtd->dma_addr;
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ val = ACP_SRAM_HS_PB_PTE_OFFSET;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ val = ACP_SRAM_SP_PB_PTE_OFFSET;
+ }
+ } else {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ val = ACP_SRAM_HS_CP_PTE_OFFSET;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ val = ACP_SRAM_SP_CP_PTE_OFFSET;
+ }
+ }
+ /* Group Enable */
+ acp_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp5x_base +
+ ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
+ acp_writel(PAGE_SIZE_4K_ENABLE, rtd->acp5x_base +
+ ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
+
+ for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
+ /* Load the low address of page int ACP SRAM through SRBM */
+ low = lower_32_bits(addr);
+ high = upper_32_bits(addr);
+
+ acp_writel(low, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val);
+ high |= BIT(31);
+ acp_writel(high, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val + 4);
+ /* Move to next physically contiguous page */
+ val += 8;
+ addr += PAGE_SIZE;
+ }
+
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ reg_dma_size = ACP_HS_TX_DMA_SIZE;
+ acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+ HS_PB_FIFO_ADDR_OFFSET;
+ reg_fifo_addr = ACP_HS_TX_FIFOADDR;
+ reg_fifo_size = ACP_HS_TX_FIFOSIZE;
+ acp_writel(I2S_HS_TX_MEM_WINDOW_START,
+ rtd->acp5x_base + ACP_HS_TX_RINGBUFADDR);
+ break;
+
+ case I2S_SP_INSTANCE:
+ default:
+ reg_dma_size = ACP_I2S_TX_DMA_SIZE;
+ acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+ SP_PB_FIFO_ADDR_OFFSET;
+ reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
+ reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
+ acp_writel(I2S_SP_TX_MEM_WINDOW_START,
+ rtd->acp5x_base + ACP_I2S_TX_RINGBUFADDR);
+ }
+ } else {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ reg_dma_size = ACP_HS_RX_DMA_SIZE;
+ acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+ HS_CAPT_FIFO_ADDR_OFFSET;
+ reg_fifo_addr = ACP_HS_RX_FIFOADDR;
+ reg_fifo_size = ACP_HS_RX_FIFOSIZE;
+ acp_writel(I2S_HS_RX_MEM_WINDOW_START,
+ rtd->acp5x_base + ACP_HS_RX_RINGBUFADDR);
+ break;
+
+ case I2S_SP_INSTANCE:
+ default:
+ reg_dma_size = ACP_I2S_RX_DMA_SIZE;
+ acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+ SP_CAPT_FIFO_ADDR_OFFSET;
+ reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
+ reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
+ acp_writel(I2S_SP_RX_MEM_WINDOW_START,
+ rtd->acp5x_base + ACP_I2S_RX_RINGBUFADDR);
+ }
+ }
+ acp_writel(DMA_SIZE, rtd->acp5x_base + reg_dma_size);
+ acp_writel(acp_fifo_addr, rtd->acp5x_base + reg_fifo_addr);
+ acp_writel(FIFO_SIZE, rtd->acp5x_base + reg_fifo_size);
+ acp_writel(BIT(I2S_RX_THRESHOLD) | BIT(HS_RX_THRESHOLD)
+ | BIT(I2S_TX_THRESHOLD) | BIT(HS_TX_THRESHOLD),
+ rtd->acp5x_base + ACP_EXTERNAL_INTR_CNTL);
+}
+
+static int acp5x_dma_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime;
+ struct snd_soc_pcm_runtime *prtd;
+ struct i2s_dev_data *adata;
+ struct i2s_stream_instance *i2s_data;
+ int ret;
+
+ runtime = substream->runtime;
+ prtd = asoc_substream_to_rtd(substream);
+ component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+ adata = dev_get_drvdata(component->dev);
+
+ i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL);
+ if (!i2s_data)
+ return -ENOMEM;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ runtime->hw = acp5x_pcm_hardware_playback;
+ else
+ runtime->hw = acp5x_pcm_hardware_capture;
+
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0) {
+ dev_err(component->dev, "set integer constraint failed\n");
+ kfree(i2s_data);
+ return ret;
+ }
+ i2s_data->acp5x_base = adata->acp5x_base;
+ runtime->private_data = i2s_data;
+ return ret;
+}
+
+static int acp5x_dma_hw_params(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct i2s_stream_instance *rtd;
+ struct snd_soc_pcm_runtime *prtd;
+ struct snd_soc_card *card;
+ struct acp5x_platform_info *pinfo;
+ struct i2s_dev_data *adata;
+ u64 size;
+
+ prtd = asoc_substream_to_rtd(substream);
+ card = prtd->card;
+ pinfo = snd_soc_card_get_drvdata(card);
+ adata = dev_get_drvdata(component->dev);
+ rtd = substream->runtime->private_data;
+
+ if (!rtd)
+ return -EINVAL;
+
+ if (pinfo) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ rtd->i2s_instance = pinfo->play_i2s_instance;
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ adata->play_stream = substream;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ adata->i2ssp_play_stream = substream;
+ }
+ } else {
+ rtd->i2s_instance = pinfo->cap_i2s_instance;
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ adata->capture_stream = substream;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ adata->i2ssp_capture_stream = substream;
+ }
+ }
+ } else {
+ dev_err(component->dev, "pinfo failed\n");
+ return -EINVAL;
+ }
+ size = params_buffer_bytes(params);
+ rtd->dma_addr = substream->dma_buffer.addr;
+ rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
+ config_acp5x_dma(rtd, substream->stream);
+ return 0;
+}
+
+static snd_pcm_uframes_t acp5x_dma_pointer(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct i2s_stream_instance *rtd;
+ u32 pos;
+ u32 buffersize;
+ u64 bytescount;
+
+ rtd = substream->runtime->private_data;
+ buffersize = frames_to_bytes(substream->runtime,
+ substream->runtime->buffer_size);
+ bytescount = acp_get_byte_count(rtd, substream->stream);
+ if (bytescount > rtd->bytescount)
+ bytescount -= rtd->bytescount;
+ pos = do_div(bytescount, buffersize);
+ return bytes_to_frames(substream->runtime, pos);
+}
+
+static int acp5x_dma_new(struct snd_soc_component *component,
+ struct snd_soc_pcm_runtime *rtd)
+{
+ struct device *parent = component->dev->parent;
+
+ snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ parent, MIN_BUFFER, MAX_BUFFER);
+ return 0;
+}
+
+static int acp5x_dma_close(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *prtd;
+ struct i2s_dev_data *adata;
+ struct i2s_stream_instance *ins;
+
+ prtd = asoc_substream_to_rtd(substream);
+ component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+ adata = dev_get_drvdata(component->dev);
+ ins = substream->runtime->private_data;
+ if (!ins)
+ return -EINVAL;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (ins->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ adata->play_stream = NULL;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ adata->i2ssp_play_stream = NULL;
+ }
+ } else {
+ switch (ins->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ adata->capture_stream = NULL;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ adata->i2ssp_capture_stream = NULL;
+ }
+ }
+ kfree(ins);
+ return 0;
+}
+
+static const struct snd_soc_component_driver acp5x_i2s_component = {
+ .name = DRV_NAME,
+ .open = acp5x_dma_open,
+ .close = acp5x_dma_close,
+ .hw_params = acp5x_dma_hw_params,
+ .pointer = acp5x_dma_pointer,
+ .pcm_construct = acp5x_dma_new,
+};
+
+static int acp5x_audio_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct i2s_dev_data *adata;
+ unsigned int irqflags;
+ int status;
+
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "platform_data not retrieved\n");
+ return -ENODEV;
+ }
+ irqflags = *((unsigned int *)(pdev->dev.platform_data));
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+ return -ENODEV;
+ }
+
+ adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
+ if (!adata)
+ return -ENOMEM;
+
+ adata->acp5x_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!adata->acp5x_base)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+ return -ENODEV;
+ }
+
+ adata->i2s_irq = res->start;
+ dev_set_drvdata(&pdev->dev, adata);
+ status = devm_snd_soc_register_component(&pdev->dev,
+ &acp5x_i2s_component,
+ NULL, 0);
+ if (status) {
+ dev_err(&pdev->dev, "Fail to register acp i2s component\n");
+ return status;
+ }
+ status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
+ irqflags, "ACP5x_I2S_IRQ", adata);
+ if (status) {
+ dev_err(&pdev->dev, "ACP5x I2S IRQ request failed\n");
+ return status;
+ }
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_allow(&pdev->dev);
+
+ return 0;
+}
+
+static int acp5x_audio_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+}
+
+static int __maybe_unused acp5x_pcm_resume(struct device *dev)
+{
+ struct i2s_dev_data *adata;
+ u32 val, reg_val, frmt_val;
+
+ reg_val = 0;
+ frmt_val = 0;
+ adata = dev_get_drvdata(dev);
+
+ if (adata->play_stream && adata->play_stream->runtime) {
+ struct i2s_stream_instance *rtd =
+ adata->play_stream->runtime->private_data;
+ config_acp5x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ reg_val = ACP_HSTDM_ITER;
+ frmt_val = ACP_HSTDM_TXFRMT;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ reg_val = ACP_I2STDM_ITER;
+ frmt_val = ACP_I2STDM_TXFRMT;
+ }
+ acp_writel((rtd->xfer_resolution << 3),
+ rtd->acp5x_base + reg_val);
+ }
+
+ if (adata->capture_stream && adata->capture_stream->runtime) {
+ struct i2s_stream_instance *rtd =
+ adata->capture_stream->runtime->private_data;
+ config_acp5x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ reg_val = ACP_HSTDM_IRER;
+ frmt_val = ACP_HSTDM_RXFRMT;
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ reg_val = ACP_I2STDM_IRER;
+ frmt_val = ACP_I2STDM_RXFRMT;
+ }
+ acp_writel((rtd->xfer_resolution << 3),
+ rtd->acp5x_base + reg_val);
+ }
+ if (adata->tdm_mode == TDM_ENABLE) {
+ acp_writel(adata->tdm_fmt, adata->acp5x_base + frmt_val);
+ val = acp_readl(adata->acp5x_base + reg_val);
+ acp_writel(val | 0x2, adata->acp5x_base + reg_val);
+ }
+ acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
+ return 0;
+}
+
+static int __maybe_unused acp5x_pcm_suspend(struct device *dev)
+{
+ struct i2s_dev_data *adata;
+
+ adata = dev_get_drvdata(dev);
+ acp_writel(0, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
+ return 0;
+}
+
+static int __maybe_unused acp5x_pcm_runtime_resume(struct device *dev)
+{
+ struct i2s_dev_data *adata;
+
+ adata = dev_get_drvdata(dev);
+ acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
+ return 0;
+}
+
+static const struct dev_pm_ops acp5x_pm_ops = {
+ SET_RUNTIME_PM_OPS(acp5x_pcm_suspend,
+ acp5x_pcm_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_resume)
+};
+
+static struct platform_driver acp5x_dma_driver = {
+ .probe = acp5x_audio_probe,
+ .remove = acp5x_audio_remove,
+ .driver = {
+ .name = "acp5x_i2s_dma",
+ .pm = &acp5x_pm_ops,
+ },
+};
+
+module_platform_driver(acp5x_dma_driver);
+
+MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD ACP 5.x PCM Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/vangogh/acp5x.h b/sound/soc/amd/vangogh/acp5x.h
new file mode 100644
index 000000000000..a808635f9740
--- /dev/null
+++ b/sound/soc/amd/vangogh/acp5x.h
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * AMD ALSA SoC PCM Driver
+ *
+ * Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+ */
+
+#include "vg_chip_offset_byte.h"
+#include <sound/pcm.h>
+
+#define ACP5x_PHY_BASE_ADDRESS 0x1240000
+#define ACP_DEVICE_ID 0x15E2
+#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
+
+#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01
+#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00
+#define ACP_PGFSM_STATUS_MASK 0x03
+#define ACP_POWERED_ON 0x00
+#define ACP_POWER_ON_IN_PROGRESS 0x01
+#define ACP_POWERED_OFF 0x02
+#define ACP_POWER_OFF_IN_PROGRESS 0x03
+
+#define ACP_ERR_INTR_MASK 0x20000000
+#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
+
+#define ACP5x_DEVS 3
+#define ACP5x_REG_START 0x1240000
+#define ACP5x_REG_END 0x1250200
+#define ACP5x_I2STDM_REG_START 0x1242400
+#define ACP5x_I2STDM_REG_END 0x1242410
+#define ACP5x_HS_TDM_REG_START 0x1242814
+#define ACP5x_HS_TDM_REG_END 0x1242824
+#define I2S_MODE 0
+#define ACP5x_I2S_MODE 1
+#define ACP5x_RES 4
+#define I2S_RX_THRESHOLD 27
+#define I2S_TX_THRESHOLD 28
+#define HS_TX_THRESHOLD 24
+#define HS_RX_THRESHOLD 23
+
+#define I2S_SP_INSTANCE 1
+#define I2S_HS_INSTANCE 2
+
+#define ACP_SRAM_PTE_OFFSET 0x02050000
+#define ACP_SRAM_SP_PB_PTE_OFFSET 0x0
+#define ACP_SRAM_SP_CP_PTE_OFFSET 0x100
+#define ACP_SRAM_HS_PB_PTE_OFFSET 0x200
+#define ACP_SRAM_HS_CP_PTE_OFFSET 0x300
+#define PAGE_SIZE_4K_ENABLE 0x2
+#define I2S_SP_TX_MEM_WINDOW_START 0x4000000
+#define I2S_SP_RX_MEM_WINDOW_START 0x4020000
+#define I2S_HS_TX_MEM_WINDOW_START 0x4040000
+#define I2S_HS_RX_MEM_WINDOW_START 0x4060000
+
+#define SP_PB_FIFO_ADDR_OFFSET 0x500
+#define SP_CAPT_FIFO_ADDR_OFFSET 0x700
+#define HS_PB_FIFO_ADDR_OFFSET 0x900
+#define HS_CAPT_FIFO_ADDR_OFFSET 0xB00
+#define PLAYBACK_MIN_NUM_PERIODS 2
+#define PLAYBACK_MAX_NUM_PERIODS 8
+#define PLAYBACK_MAX_PERIOD_SIZE 8192
+#define PLAYBACK_MIN_PERIOD_SIZE 1024
+#define CAPTURE_MIN_NUM_PERIODS 2
+#define CAPTURE_MAX_NUM_PERIODS 8
+#define CAPTURE_MAX_PERIOD_SIZE 8192
+#define CAPTURE_MIN_PERIOD_SIZE 1024
+
+#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
+#define MIN_BUFFER MAX_BUFFER
+#define FIFO_SIZE 0x100
+#define DMA_SIZE 0x40
+#define FRM_LEN 0x100
+
+#define I2S_MASTER_MODE_ENABLE 1
+#define I2S_MASTER_MODE_DISABLE 0
+
+#define SLOT_WIDTH_8 8
+#define SLOT_WIDTH_16 16
+#define SLOT_WIDTH_24 24
+#define SLOT_WIDTH_32 32
+#define TDM_ENABLE 1
+#define TDM_DISABLE 0
+#define ACP5x_ITER_IRER_SAMP_LEN_MASK 0x38
+
+struct i2s_dev_data {
+ bool tdm_mode;
+ bool master_mode;
+ unsigned int i2s_irq;
+ u16 i2s_instance;
+ u32 tdm_fmt;
+ void __iomem *acp5x_base;
+ struct snd_pcm_substream *play_stream;
+ struct snd_pcm_substream *capture_stream;
+ struct snd_pcm_substream *i2ssp_play_stream;
+ struct snd_pcm_substream *i2ssp_capture_stream;
+};
+
+struct i2s_stream_instance {
+ u16 num_pages;
+ u16 i2s_instance;
+ u16 direction;
+ u16 channels;
+ u32 xfer_resolution;
+ u32 val;
+ dma_addr_t dma_addr;
+ u64 bytescount;
+ void __iomem *acp5x_base;
+};
+
+union acp_dma_count {
+ struct {
+ u32 low;
+ u32 high;
+ } bcount;
+ u64 bytescount;
+};
+
+struct acp5x_platform_info {
+ u16 play_i2s_instance;
+ u16 cap_i2s_instance;
+};
+
+union acp_i2stdm_mstrclkgen {
+ struct {
+ u32 i2stdm_master_mode : 1;
+ u32 i2stdm_format_mode : 1;
+ u32 i2stdm_lrclk_div_val : 9;
+ u32 i2stdm_bclk_div_val : 11;
+ u32:10;
+ } bitfields, bits;
+ u32 u32_all;
+};
+
+/* common header file uses exact offset rather than relative
+ * offset which requires subtraction logic from base_addr
+ * for accessing ACP5x MMIO space registers
+ */
+static inline u32 acp_readl(void __iomem *base_addr)
+{
+ return readl(base_addr - ACP5x_PHY_BASE_ADDRESS);
+}
+
+static inline void acp_writel(u32 val, void __iomem *base_addr)
+{
+ writel(val, base_addr - ACP5x_PHY_BASE_ADDRESS);
+}
+
+static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd,
+ int direction)
+{
+ union acp_dma_count byte_count;
+
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ byte_count.bcount.high =
+ acp_readl(rtd->acp5x_base +
+ ACP_HS_TX_LINEARPOSCNTR_HIGH);
+ byte_count.bcount.low =
+ acp_readl(rtd->acp5x_base +
+ ACP_HS_TX_LINEARPOSCNTR_LOW);
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ byte_count.bcount.high =
+ acp_readl(rtd->acp5x_base +
+ ACP_I2S_TX_LINEARPOSCNTR_HIGH);
+ byte_count.bcount.low =
+ acp_readl(rtd->acp5x_base +
+ ACP_I2S_TX_LINEARPOSCNTR_LOW);
+ }
+ } else {
+ switch (rtd->i2s_instance) {
+ case I2S_HS_INSTANCE:
+ byte_count.bcount.high =
+ acp_readl(rtd->acp5x_base +
+ ACP_HS_RX_LINEARPOSCNTR_HIGH);
+ byte_count.bcount.low =
+ acp_readl(rtd->acp5x_base +
+ ACP_HS_RX_LINEARPOSCNTR_LOW);
+ break;
+ case I2S_SP_INSTANCE:
+ default:
+ byte_count.bcount.high =
+ acp_readl(rtd->acp5x_base +
+ ACP_I2S_RX_LINEARPOSCNTR_HIGH);
+ byte_count.bcount.low =
+ acp_readl(rtd->acp5x_base +
+ ACP_I2S_RX_LINEARPOSCNTR_LOW);
+ }
+ }
+ return byte_count.bytescount;
+}
diff --git a/sound/soc/amd/vangogh/pci-acp5x.c b/sound/soc/amd/vangogh/pci-acp5x.c
new file mode 100644
index 000000000000..a57b762d9f2e
--- /dev/null
+++ b/sound/soc/amd/vangogh/pci-acp5x.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// AMD Vangogh ACP PCI Driver
+//
+// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+
+#include "acp5x.h"
+
+struct acp5x_dev_data {
+ void __iomem *acp5x_base;
+ bool acp5x_audio_mode;
+ struct resource *res;
+ struct platform_device *pdev[ACP5x_DEVS];
+};
+
+static int acp5x_power_on(void __iomem *acp5x_base)
+{
+ u32 val;
+ int timeout;
+
+ val = acp_readl(acp5x_base + ACP_PGFSM_STATUS);
+
+ if (val == 0)
+ return val;
+
+ if ((val & ACP_PGFSM_STATUS_MASK) !=
+ ACP_POWER_ON_IN_PROGRESS)
+ acp_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
+ acp5x_base + ACP_PGFSM_CONTROL);
+ timeout = 0;
+ while (++timeout < 500) {
+ val = acp_readl(acp5x_base + ACP_PGFSM_STATUS);
+ if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_ON)
+ return 0;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
+}
+
+static int acp5x_reset(void __iomem *acp5x_base)
+{
+ u32 val;
+ int timeout;
+
+ acp_writel(1, acp5x_base + ACP_SOFT_RESET);
+ timeout = 0;
+ while (++timeout < 500) {
+ val = acp_readl(acp5x_base + ACP_SOFT_RESET);
+ if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
+ break;
+ cpu_relax();
+ }
+ acp_writel(0, acp5x_base + ACP_SOFT_RESET);
+ timeout = 0;
+ while (++timeout < 500) {
+ val = acp_readl(acp5x_base + ACP_SOFT_RESET);
+ if (!val)
+ return 0;
+ cpu_relax();
+ }
+ return -ETIMEDOUT;
+}
+
+static void acp5x_enable_interrupts(void __iomem *acp5x_base)
+{
+ acp_writel(0x01, acp5x_base + ACP_EXTERNAL_INTR_ENB);
+}
+
+static void acp5x_disable_interrupts(void __iomem *acp5x_base)
+{
+ acp_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp5x_base +
+ ACP_EXTERNAL_INTR_STAT);
+ acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_CNTL);
+ acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_ENB);
+}
+
+static int acp5x_init(void __iomem *acp5x_base)
+{
+ int ret;
+
+ /* power on */
+ ret = acp5x_power_on(acp5x_base);
+ if (ret) {
+ pr_err("ACP5x power on failed\n");
+ return ret;
+ }
+ /* Reset */
+ ret = acp5x_reset(acp5x_base);
+ if (ret) {
+ pr_err("ACP5x reset failed\n");
+ return ret;
+ }
+ acp5x_enable_interrupts(acp5x_base);
+ return 0;
+}
+
+static int acp5x_deinit(void __iomem *acp5x_base)
+{
+ int ret;
+
+ acp5x_disable_interrupts(acp5x_base);
+ /* Reset */
+ ret = acp5x_reset(acp5x_base);
+ if (ret) {
+ pr_err("ACP5x reset failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int snd_acp5x_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ struct acp5x_dev_data *adata;
+ struct platform_device_info pdevinfo[ACP5x_DEVS];
+ unsigned int irqflags;
+ int ret, i;
+ u32 addr, val;
+
+ irqflags = IRQF_SHARED;
+ if (pci->revision != 0x50)
+ return -ENODEV;
+
+ if (pci_enable_device(pci)) {
+ dev_err(&pci->dev, "pci_enable_device failed\n");
+ return -ENODEV;
+ }
+
+ ret = pci_request_regions(pci, "AMD ACP5x audio");
+ if (ret < 0) {
+ dev_err(&pci->dev, "pci_request_regions failed\n");
+ goto disable_pci;
+ }
+
+ adata = devm_kzalloc(&pci->dev, sizeof(struct acp5x_dev_data),
+ GFP_KERNEL);
+ if (!adata) {
+ ret = -ENOMEM;
+ goto release_regions;
+ }
+ addr = pci_resource_start(pci, 0);
+ adata->acp5x_base = devm_ioremap(&pci->dev, addr,
+ pci_resource_len(pci, 0));
+ if (!adata->acp5x_base) {
+ ret = -ENOMEM;
+ goto release_regions;
+ }
+ pci_set_master(pci);
+ pci_set_drvdata(pci, adata);
+ ret = acp5x_init(adata->acp5x_base);
+ if (ret)
+ goto release_regions;
+
+ val = acp_readl(adata->acp5x_base + ACP_PIN_CONFIG);
+ switch (val) {
+ case I2S_MODE:
+ adata->res = devm_kzalloc(&pci->dev,
+ sizeof(struct resource) * ACP5x_RES,
+ GFP_KERNEL);
+ if (!adata->res) {
+ ret = -ENOMEM;
+ goto de_init;
+ }
+
+ adata->res[0].name = "acp5x_i2s_iomem";
+ adata->res[0].flags = IORESOURCE_MEM;
+ adata->res[0].start = addr;
+ adata->res[0].end = addr + (ACP5x_REG_END - ACP5x_REG_START);
+
+ adata->res[1].name = "acp5x_i2s_sp";
+ adata->res[1].flags = IORESOURCE_MEM;
+ adata->res[1].start = addr + ACP5x_I2STDM_REG_START;
+ adata->res[1].end = addr + ACP5x_I2STDM_REG_END;
+
+ adata->res[2].name = "acp5x_i2s_hs";
+ adata->res[2].flags = IORESOURCE_MEM;
+ adata->res[2].start = addr + ACP5x_HS_TDM_REG_START;
+ adata->res[2].end = addr + ACP5x_HS_TDM_REG_END;
+
+ adata->res[3].name = "acp5x_i2s_irq";
+ adata->res[3].flags = IORESOURCE_IRQ;
+ adata->res[3].start = pci->irq;
+ adata->res[3].end = adata->res[3].start;
+
+ adata->acp5x_audio_mode = ACP5x_I2S_MODE;
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ pdevinfo[0].name = "acp5x_i2s_dma";
+ pdevinfo[0].id = 0;
+ pdevinfo[0].parent = &pci->dev;
+ pdevinfo[0].num_res = 4;
+ pdevinfo[0].res = &adata->res[0];
+ pdevinfo[0].data = &irqflags;
+ pdevinfo[0].size_data = sizeof(irqflags);
+
+ pdevinfo[1].name = "acp5x_i2s_playcap";
+ pdevinfo[1].id = 0;
+ pdevinfo[1].parent = &pci->dev;
+ pdevinfo[1].num_res = 1;
+ pdevinfo[1].res = &adata->res[1];
+
+ pdevinfo[2].name = "acp5x_i2s_playcap";
+ pdevinfo[2].id = 1;
+ pdevinfo[2].parent = &pci->dev;
+ pdevinfo[2].num_res = 1;
+ pdevinfo[2].res = &adata->res[2];
+
+ for (i = 0; i < ACP5x_DEVS; i++) {
+ adata->pdev[i] =
+ platform_device_register_full(&pdevinfo[i]);
+ if (IS_ERR(adata->pdev[i])) {
+ dev_err(&pci->dev, "cannot register %s device\n",
+ pdevinfo[i].name);
+ ret = PTR_ERR(adata->pdev[i]);
+ goto unregister_devs;
+ }
+ }
+ break;
+ default:
+ dev_info(&pci->dev, "ACP audio mode : %d\n", val);
+ }
+ pm_runtime_set_autosuspend_delay(&pci->dev, 2000);
+ pm_runtime_use_autosuspend(&pci->dev);
+ pm_runtime_put_noidle(&pci->dev);
+ pm_runtime_allow(&pci->dev);
+ return 0;
+
+unregister_devs:
+ for (--i; i >= 0; i--)
+ platform_device_unregister(adata->pdev[i]);
+de_init:
+ if (acp5x_deinit(adata->acp5x_base))
+ dev_err(&pci->dev, "ACP de-init failed\n");
+release_regions:
+ pci_release_regions(pci);
+disable_pci:
+ pci_disable_device(pci);
+
+ return ret;
+}
+
+static int __maybe_unused snd_acp5x_suspend(struct device *dev)
+{
+ int ret;
+ struct acp5x_dev_data *adata;
+
+ adata = dev_get_drvdata(dev);
+ ret = acp5x_deinit(adata->acp5x_base);
+ if (ret)
+ dev_err(dev, "ACP de-init failed\n");
+ else
+ dev_dbg(dev, "ACP de-initialized\n");
+
+ return ret;
+}
+
+static int __maybe_unused snd_acp5x_resume(struct device *dev)
+{
+ int ret;
+ struct acp5x_dev_data *adata;
+
+ adata = dev_get_drvdata(dev);
+ ret = acp5x_init(adata->acp5x_base);
+ if (ret) {
+ dev_err(dev, "ACP init failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+static const struct dev_pm_ops acp5x_pm = {
+ SET_RUNTIME_PM_OPS(snd_acp5x_suspend,
+ snd_acp5x_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(snd_acp5x_suspend, snd_acp5x_resume)
+};
+
+static void snd_acp5x_remove(struct pci_dev *pci)
+{
+ struct acp5x_dev_data *adata;
+ int i, ret;
+
+ adata = pci_get_drvdata(pci);
+ if (adata->acp5x_audio_mode == ACP5x_I2S_MODE) {
+ for (i = 0; i < ACP5x_DEVS; i++)
+ platform_device_unregister(adata->pdev[i]);
+ }
+ ret = acp5x_deinit(adata->acp5x_base);
+ if (ret)
+ dev_err(&pci->dev, "ACP de-init failed\n");
+ pm_runtime_forbid(&pci->dev);
+ pm_runtime_get_noresume(&pci->dev);
+ pci_release_regions(pci);
+ pci_disable_device(pci);
+}
+
+static const struct pci_device_id snd_acp5x_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID),
+ .class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
+ .class_mask = 0xffffff },
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, snd_acp5x_ids);
+
+static struct pci_driver acp5x_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_acp5x_ids,
+ .probe = snd_acp5x_probe,
+ .remove = snd_acp5x_remove,
+ .driver = {
+ .pm = &acp5x_pm,
+ }
+};
+
+module_pci_driver(acp5x_driver);
+
+MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD Vangogh ACP PCI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/vangogh/vg_chip_offset_byte.h b/sound/soc/amd/vangogh/vg_chip_offset_byte.h
new file mode 100644
index 000000000000..b1165ae142b7
--- /dev/null
+++ b/sound/soc/amd/vangogh/vg_chip_offset_byte.h
@@ -0,0 +1,337 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * AMD ACP 5.x Register Documentation
+ *
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _acp_ip_OFFSET_HEADER
+#define _acp_ip_OFFSET_HEADER
+
+/* Registers from ACP_DMA block */
+#define ACP_DMA_CNTL_0 0x1240000
+#define ACP_DMA_CNTL_1 0x1240004
+#define ACP_DMA_CNTL_2 0x1240008
+#define ACP_DMA_CNTL_3 0x124000C
+#define ACP_DMA_CNTL_4 0x1240010
+#define ACP_DMA_CNTL_5 0x1240014
+#define ACP_DMA_CNTL_6 0x1240018
+#define ACP_DMA_CNTL_7 0x124001C
+#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020
+#define ACP_DMA_DSCR_STRT_IDX_1 0x1240024
+#define ACP_DMA_DSCR_STRT_IDX_2 0x1240028
+#define ACP_DMA_DSCR_STRT_IDX_3 0x124002C
+#define ACP_DMA_DSCR_STRT_IDX_4 0x1240030
+#define ACP_DMA_DSCR_STRT_IDX_5 0x1240034
+#define ACP_DMA_DSCR_STRT_IDX_6 0x1240038
+#define ACP_DMA_DSCR_STRT_IDX_7 0x124003C
+#define ACP_DMA_DSCR_CNT_0 0x1240040
+#define ACP_DMA_DSCR_CNT_1 0x1240044
+#define ACP_DMA_DSCR_CNT_2 0x1240048
+#define ACP_DMA_DSCR_CNT_3 0x124004C
+#define ACP_DMA_DSCR_CNT_4 0x1240050
+#define ACP_DMA_DSCR_CNT_5 0x1240054
+#define ACP_DMA_DSCR_CNT_6 0x1240058
+#define ACP_DMA_DSCR_CNT_7 0x124005C
+#define ACP_DMA_PRIO_0 0x1240060
+#define ACP_DMA_PRIO_1 0x1240064
+#define ACP_DMA_PRIO_2 0x1240068
+#define ACP_DMA_PRIO_3 0x124006C
+#define ACP_DMA_PRIO_4 0x1240070
+#define ACP_DMA_PRIO_5 0x1240074
+#define ACP_DMA_PRIO_6 0x1240078
+#define ACP_DMA_PRIO_7 0x124007C
+#define ACP_DMA_CUR_DSCR_0 0x1240080
+#define ACP_DMA_CUR_DSCR_1 0x1240084
+#define ACP_DMA_CUR_DSCR_2 0x1240088
+#define ACP_DMA_CUR_DSCR_3 0x124008C
+#define ACP_DMA_CUR_DSCR_4 0x1240090
+#define ACP_DMA_CUR_DSCR_5 0x1240094
+#define ACP_DMA_CUR_DSCR_6 0x1240098
+#define ACP_DMA_CUR_DSCR_7 0x124009C
+#define ACP_DMA_CUR_TRANS_CNT_0 0x12400A0
+#define ACP_DMA_CUR_TRANS_CNT_1 0x12400A4
+#define ACP_DMA_CUR_TRANS_CNT_2 0x12400A8
+#define ACP_DMA_CUR_TRANS_CNT_3 0x12400AC
+#define ACP_DMA_CUR_TRANS_CNT_4 0x12400B0
+#define ACP_DMA_CUR_TRANS_CNT_5 0x12400B4
+#define ACP_DMA_CUR_TRANS_CNT_6 0x12400B8
+#define ACP_DMA_CUR_TRANS_CNT_7 0x12400BC
+#define ACP_DMA_ERR_STS_0 0x12400C0
+#define ACP_DMA_ERR_STS_1 0x12400C4
+#define ACP_DMA_ERR_STS_2 0x12400C8
+#define ACP_DMA_ERR_STS_3 0x12400CC
+#define ACP_DMA_ERR_STS_4 0x12400D0
+#define ACP_DMA_ERR_STS_5 0x12400D4
+#define ACP_DMA_ERR_STS_6 0x12400D8
+#define ACP_DMA_ERR_STS_7 0x12400DC
+#define ACP_DMA_DESC_BASE_ADDR 0x12400E0
+#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4
+#define ACP_DMA_CH_STS 0x12400E8
+#define ACP_DMA_CH_GROUP 0x12400EC
+#define ACP_DMA_CH_RST_STS 0x12400F0
+
+/* Registers from ACP_AXI2AXIATU block */
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34
+#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38
+#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C
+#define ACPAXI2AXI_ATU_CTRL 0x1240C40
+
+/* Registers from ACP_CLKRST block */
+#define ACP_SOFT_RESET 0x1241000
+#define ACP_CONTROL 0x1241004
+#define ACP_STATUS 0x1241008
+#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010
+
+/* Registers from ACP_MISC block */
+#define ACP_EXTERNAL_INTR_ENB 0x1241800
+#define ACP_EXTERNAL_INTR_CNTL 0x1241804
+#define ACP_EXTERNAL_INTR_STAT 0x1241808
+#define ACP_ERROR_STATUS 0x12418C4
+#define ACP_SW_I2S_ERROR_REASON 0x12418C8
+#define ACP_MEM_PG_STS 0x12418CC
+#define ACP_PGMEM_DEEP_SLEEP_CTRL 0x12418D0
+#define ACP_PGMEM_SHUT_DOWN_CTRL 0x12418D4
+
+/* Registers from ACP_PGFSM block */
+#define ACP_PIN_CONFIG 0x1241400
+#define ACP_PAD_PULLUP_CTRL 0x1241404
+#define ACP_PAD_PULLDOWN_CTRL 0x1241408
+#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x124140C
+#define ACP_PAD_SCHMEN_CTRL 0x1241410
+#define ACP_SW_PAD_KEEPER_EN 0x1241414
+#define ACP_SW_WAKE_EN 0x1241418
+#define ACP_I2S_WAKE_EN 0x124141C
+#define ACP_PME_EN 0x1241420
+#define ACP_PGFSM_CONTROL 0x1241424
+#define ACP_PGFSM_STATUS 0x1241428
+#define ACP_CLKMUX_SEL 0x124142C
+#define ACP_DEVICE_STATE 0x1241430
+#define AZ_DEVICE_STATE 0x1241434
+#define ACP_INTR_URGENCY_TIMER 0x1241438
+#define AZ_INTR_URGENCY_TIMER 0x124143C
+#define ACP_AON_SW_INTR_TRIG 0x1241440
+
+/* Registers from ACP_SCRATCH block */
+#define ACP_SCRATCH_REG_0 0x1250000
+#define ACP_SCRATCH_REG_1 0x1250004
+#define ACP_SCRATCH_REG_2 0x1250008
+#define ACP_SCRATCH_REG_3 0x125000C
+#define ACP_SCRATCH_REG_4 0x1250010
+#define ACP_SCRATCH_REG_5 0x1250014
+#define ACP_SCRATCH_REG_6 0x1250018
+#define ACP_SCRATCH_REG_7 0x125001C
+#define ACP_SCRATCH_REG_8 0x1250020
+#define ACP_SCRATCH_REG_9 0x1250024
+#define ACP_SCRATCH_REG_10 0x1250028
+#define ACP_SCRATCH_REG_11 0x125002C
+#define ACP_SCRATCH_REG_12 0x1250030
+#define ACP_SCRATCH_REG_13 0x1250034
+#define ACP_SCRATCH_REG_14 0x1250038
+#define ACP_SCRATCH_REG_15 0x125003C
+#define ACP_SCRATCH_REG_16 0x1250040
+#define ACP_SCRATCH_REG_17 0x1250044
+#define ACP_SCRATCH_REG_18 0x1250048
+#define ACP_SCRATCH_REG_19 0x125004C
+#define ACP_SCRATCH_REG_20 0x1250050
+#define ACP_SCRATCH_REG_21 0x1250054
+#define ACP_SCRATCH_REG_22 0x1250058
+#define ACP_SCRATCH_REG_23 0x125005C
+#define ACP_SCRATCH_REG_24 0x1250060
+#define ACP_SCRATCH_REG_25 0x1250064
+#define ACP_SCRATCH_REG_26 0x1250068
+#define ACP_SCRATCH_REG_27 0x125006C
+#define ACP_SCRATCH_REG_28 0x1250070
+#define ACP_SCRATCH_REG_29 0x1250074
+#define ACP_SCRATCH_REG_30 0x1250078
+#define ACP_SCRATCH_REG_31 0x125007C
+#define ACP_SCRATCH_REG_32 0x1250080
+#define ACP_SCRATCH_REG_33 0x1250084
+#define ACP_SCRATCH_REG_34 0x1250088
+#define ACP_SCRATCH_REG_35 0x125008C
+#define ACP_SCRATCH_REG_36 0x1250090
+#define ACP_SCRATCH_REG_37 0x1250094
+#define ACP_SCRATCH_REG_38 0x1250098
+#define ACP_SCRATCH_REG_39 0x125009C
+#define ACP_SCRATCH_REG_40 0x12500A0
+#define ACP_SCRATCH_REG_41 0x12500A4
+#define ACP_SCRATCH_REG_42 0x12500A8
+#define ACP_SCRATCH_REG_43 0x12500AC
+#define ACP_SCRATCH_REG_44 0x12500B0
+#define ACP_SCRATCH_REG_45 0x12500B4
+#define ACP_SCRATCH_REG_46 0x12500B8
+#define ACP_SCRATCH_REG_47 0x12500BC
+#define ACP_SCRATCH_REG_48 0x12500C0
+#define ACP_SCRATCH_REG_49 0x12500C4
+#define ACP_SCRATCH_REG_50 0x12500C8
+#define ACP_SCRATCH_REG_51 0x12500CC
+#define ACP_SCRATCH_REG_52 0x12500D0
+#define ACP_SCRATCH_REG_53 0x12500D4
+#define ACP_SCRATCH_REG_54 0x12500D8
+#define ACP_SCRATCH_REG_55 0x12500DC
+#define ACP_SCRATCH_REG_56 0x12500E0
+#define ACP_SCRATCH_REG_57 0x12500E4
+#define ACP_SCRATCH_REG_58 0x12500E8
+#define ACP_SCRATCH_REG_59 0x12500EC
+#define ACP_SCRATCH_REG_60 0x12500F0
+#define ACP_SCRATCH_REG_61 0x12500F4
+#define ACP_SCRATCH_REG_62 0x12500F8
+#define ACP_SCRATCH_REG_63 0x12500FC
+#define ACP_SCRATCH_REG_64 0x1250100
+#define ACP_SCRATCH_REG_65 0x1250104
+#define ACP_SCRATCH_REG_66 0x1250108
+#define ACP_SCRATCH_REG_67 0x125010C
+#define ACP_SCRATCH_REG_68 0x1250110
+#define ACP_SCRATCH_REG_69 0x1250114
+#define ACP_SCRATCH_REG_70 0x1250118
+#define ACP_SCRATCH_REG_71 0x125011C
+#define ACP_SCRATCH_REG_72 0x1250120
+#define ACP_SCRATCH_REG_73 0x1250124
+#define ACP_SCRATCH_REG_74 0x1250128
+#define ACP_SCRATCH_REG_75 0x125012C
+#define ACP_SCRATCH_REG_76 0x1250130
+#define ACP_SCRATCH_REG_77 0x1250134
+#define ACP_SCRATCH_REG_78 0x1250138
+#define ACP_SCRATCH_REG_79 0x125013C
+#define ACP_SCRATCH_REG_80 0x1250140
+#define ACP_SCRATCH_REG_81 0x1250144
+#define ACP_SCRATCH_REG_82 0x1250148
+#define ACP_SCRATCH_REG_83 0x125014C
+#define ACP_SCRATCH_REG_84 0x1250150
+#define ACP_SCRATCH_REG_85 0x1250154
+#define ACP_SCRATCH_REG_86 0x1250158
+#define ACP_SCRATCH_REG_87 0x125015C
+#define ACP_SCRATCH_REG_88 0x1250160
+#define ACP_SCRATCH_REG_89 0x1250164
+#define ACP_SCRATCH_REG_90 0x1250168
+#define ACP_SCRATCH_REG_91 0x125016C
+#define ACP_SCRATCH_REG_92 0x1250170
+#define ACP_SCRATCH_REG_93 0x1250174
+#define ACP_SCRATCH_REG_94 0x1250178
+#define ACP_SCRATCH_REG_95 0x125017C
+#define ACP_SCRATCH_REG_96 0x1250180
+#define ACP_SCRATCH_REG_97 0x1250184
+#define ACP_SCRATCH_REG_98 0x1250188
+#define ACP_SCRATCH_REG_99 0x125018C
+#define ACP_SCRATCH_REG_100 0x1250190
+#define ACP_SCRATCH_REG_101 0x1250194
+#define ACP_SCRATCH_REG_102 0x1250198
+#define ACP_SCRATCH_REG_103 0x125019C
+#define ACP_SCRATCH_REG_104 0x12501A0
+#define ACP_SCRATCH_REG_105 0x12501A4
+#define ACP_SCRATCH_REG_106 0x12501A8
+#define ACP_SCRATCH_REG_107 0x12501AC
+#define ACP_SCRATCH_REG_108 0x12501B0
+#define ACP_SCRATCH_REG_109 0x12501B4
+#define ACP_SCRATCH_REG_110 0x12501B8
+#define ACP_SCRATCH_REG_111 0x12501BC
+#define ACP_SCRATCH_REG_112 0x12501C0
+#define ACP_SCRATCH_REG_113 0x12501C4
+#define ACP_SCRATCH_REG_114 0x12501C8
+#define ACP_SCRATCH_REG_115 0x12501CC
+#define ACP_SCRATCH_REG_116 0x12501D0
+#define ACP_SCRATCH_REG_117 0x12501D4
+#define ACP_SCRATCH_REG_118 0x12501D8
+#define ACP_SCRATCH_REG_119 0x12501DC
+#define ACP_SCRATCH_REG_120 0x12501E0
+#define ACP_SCRATCH_REG_121 0x12501E4
+#define ACP_SCRATCH_REG_122 0x12501E8
+#define ACP_SCRATCH_REG_123 0x12501EC
+#define ACP_SCRATCH_REG_124 0x12501F0
+#define ACP_SCRATCH_REG_125 0x12501F4
+#define ACP_SCRATCH_REG_126 0x12501F8
+#define ACP_SCRATCH_REG_127 0x12501FC
+#define ACP_SCRATCH_REG_128 0x1250200
+
+/* Registers from ACP_AUDIO_BUFFERS block */
+#define ACP_I2S_RX_RINGBUFADDR 0x1242000
+#define ACP_I2S_RX_RINGBUFSIZE 0x1242004
+#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008
+#define ACP_I2S_RX_FIFOADDR 0x124200C
+#define ACP_I2S_RX_FIFOSIZE 0x1242010
+#define ACP_I2S_RX_DMA_SIZE 0x1242014
+#define ACP_I2S_RX_LINEARPOSCNTR_HIGH 0x1242018
+#define ACP_I2S_RX_LINEARPOSCNTR_LOW 0x124201C
+#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020
+#define ACP_I2S_TX_RINGBUFADDR 0x1242024
+#define ACP_I2S_TX_RINGBUFSIZE 0x1242028
+#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C
+#define ACP_I2S_TX_FIFOADDR 0x1242030
+#define ACP_I2S_TX_FIFOSIZE 0x1242034
+#define ACP_I2S_TX_DMA_SIZE 0x1242038
+#define ACP_I2S_TX_LINEARPOSCNTR_HIGH 0x124203C
+#define ACP_I2S_TX_LINEARPOSCNTR_LOW 0x1242040
+#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044
+#define ACP_BT_RX_RINGBUFADDR 0x1242048
+#define ACP_BT_RX_RINGBUFSIZE 0x124204C
+#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050
+#define ACP_BT_RX_FIFOADDR 0x1242054
+#define ACP_BT_RX_FIFOSIZE 0x1242058
+#define ACP_BT_RX_DMA_SIZE 0x124205C
+#define ACP_BT_RX_LINEARPOSCNTR_HIGH 0x1242060
+#define ACP_BT_RX_LINEARPOSCNTR_LOW 0x1242064
+#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068
+#define ACP_BT_TX_RINGBUFADDR 0x124206C
+#define ACP_BT_TX_RINGBUFSIZE 0x1242070
+#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074
+#define ACP_BT_TX_FIFOADDR 0x1242078
+#define ACP_BT_TX_FIFOSIZE 0x124207C
+#define ACP_BT_TX_DMA_SIZE 0x1242080
+#define ACP_BT_TX_LINEARPOSCNTR_HIGH 0x1242084
+#define ACP_BT_TX_LINEARPOSCNTR_LOW 0x1242088
+#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C
+#define ACP_HS_RX_RINGBUFADDR 0x1242090
+#define ACP_HS_RX_RINGBUFSIZE 0x1242094
+#define ACP_HS_RX_LINKPOSITIONCNTR 0x1242098
+#define ACP_HS_RX_FIFOADDR 0x124209C
+#define ACP_HS_RX_FIFOSIZE 0x12420A0
+#define ACP_HS_RX_DMA_SIZE 0x12420A4
+#define ACP_HS_RX_LINEARPOSCNTR_HIGH 0x12420A8
+#define ACP_HS_RX_LINEARPOSCNTR_LOW 0x12420AC
+#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0
+#define ACP_HS_TX_RINGBUFADDR 0x12420B4
+#define ACP_HS_TX_RINGBUFSIZE 0x12420B8
+#define ACP_HS_TX_LINKPOSITIONCNTR 0x12420BC
+#define ACP_HS_TX_FIFOADDR 0x12420C0
+#define ACP_HS_TX_FIFOSIZE 0x12420C4
+#define ACP_HS_TX_DMA_SIZE 0x12420C8
+#define ACP_HS_TX_LINEARPOSCNTR_HIGH 0x12420CC
+#define ACP_HS_TX_LINEARPOSCNTR_LOW 0x12420D0
+#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4
+
+/* Registers from ACP_I2S_TDM block */
+#define ACP_I2STDM_IER 0x1242400
+#define ACP_I2STDM_IRER 0x1242404
+#define ACP_I2STDM_RXFRMT 0x1242408
+#define ACP_I2STDM_ITER 0x124240C
+#define ACP_I2STDM_TXFRMT 0x1242410
+#define ACP_I2STDM0_MSTRCLKGEN 0x1242414
+#define ACP_I2STDM1_MSTRCLKGEN 0x1242418
+#define ACP_I2STDM2_MSTRCLKGEN 0x124241C
+#define ACP_I2STDM_REFCLKGEN 0x1242420
+
+/* Registers from ACP_BT_TDM block */
+#define ACP_BTTDM_IER 0x1242800
+#define ACP_BTTDM_IRER 0x1242804
+#define ACP_BTTDM_RXFRMT 0x1242808
+#define ACP_BTTDM_ITER 0x124280C
+#define ACP_BTTDM_TXFRMT 0x1242810
+#define ACP_HSTDM_IER 0x1242814
+#define ACP_HSTDM_IRER 0x1242818
+#define ACP_HSTDM_RXFRMT 0x124281C
+#define ACP_HSTDM_ITER 0x1242820
+#define ACP_HSTDM_TXFRMT 0x1242824
+#endif
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index ec04e3386bc0..8617793ed955 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -11,7 +11,6 @@ if SND_ATMEL_SOC
config SND_ATMEL_SOC_PDC
bool
- depends on HAS_DMA
config SND_ATMEL_SOC_DMA
bool
diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c
index e6ded6f8453f..bcd4f3e4fb0f 100644
--- a/sound/soc/atmel/mchp-spdifrx.c
+++ b/sound/soc/atmel/mchp-spdifrx.c
@@ -56,7 +56,7 @@
/* Validity Bit Mode */
#define SPDIFRX_MR_VBMODE_MASK GENAMSK(1, 1)
#define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \
- (0 << 1) /* Load sample regardles of validity bit value */
+ (0 << 1) /* Load sample regardless of validity bit value */
#define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \
(1 << 1) /* Load sample only if validity bit is 0 */
@@ -519,7 +519,7 @@ static int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev,
/* check for new data available */
ret = wait_for_completion_interruptible_timeout(&ch_stat->done,
msecs_to_jiffies(100));
- /* IP might not be started or valid stream might not be prezent */
+ /* IP might not be started or valid stream might not be present */
if (ret < 0) {
dev_dbg(dev->dev, "channel status for channel %d timeout\n",
channel);
@@ -571,7 +571,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,
mchp_spdifrx_isr_blockend_en(dev);
ret = wait_for_completion_interruptible_timeout(&user_data->done,
msecs_to_jiffies(100));
- /* IP might not be started or valid stream might not be prezent */
+ /* IP might not be started or valid stream might not be present */
if (ret <= 0) {
dev_dbg(dev->dev, "user data for channel %d timeout\n",
channel);
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
index 3bd350afb743..d24380046435 100644
--- a/sound/soc/atmel/mchp-spdiftx.c
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -80,7 +80,7 @@
#define SPDIFTX_MR_VALID1 BIT(24)
#define SPDIFTX_MR_VALID2 BIT(25)
-/* Disable Null Frame on underrrun */
+/* Disable Null Frame on underrun */
#define SPDIFTX_MR_DNFR_MASK GENMASK(27, 27)
#define SPDIFTX_MR_DNFR_INVALID (0 << 27)
#define SPDIFTX_MR_DNFR_VALID (1 << 27)
diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c
index 59e2edb22b3a..50c3dc6936f9 100644
--- a/sound/soc/atmel/tse850-pcm5142.c
+++ b/sound/soc/atmel/tse850-pcm5142.c
@@ -23,7 +23,7 @@
// IN2 +---o--+------------+--o---+ OUT2
// loop2 relays
//
-// The 'loop1' gpio pin controlls two relays, which are either in loop
+// The 'loop1' gpio pin controls two relays, which are either in loop
// position, meaning that input and output are directly connected, or
// they are in mixer position, meaning that the signal is passed through
// the 'Sum' mixer. Similarly for 'loop2'.
diff --git a/sound/soc/bcm/bcm63xx-pcm-whistler.c b/sound/soc/bcm/bcm63xx-pcm-whistler.c
index 7ec8559d53a2..b5096f64c576 100644
--- a/sound/soc/bcm/bcm63xx-pcm-whistler.c
+++ b/sound/soc/bcm/bcm63xx-pcm-whistler.c
@@ -46,10 +46,6 @@ static int bcm63xx_pcm_hw_params(struct snd_soc_component *component,
{
struct i2s_dma_desc *dma_desc;
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
dma_desc = kzalloc(sizeof(*dma_desc), GFP_NOWAIT);
if (!dma_desc)
@@ -68,7 +64,6 @@ static int bcm63xx_pcm_hw_free(struct snd_soc_component *component,
dma_desc = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
kfree(dma_desc);
- snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
@@ -190,19 +185,6 @@ bcm63xx_pcm_pointer(struct snd_soc_component *component,
return x == substream->runtime->buffer_size ? 0 : x;
}
-static int bcm63xx_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- return dma_mmap_wc(substream->pcm->card->dev, vma,
- runtime->dma_area,
- runtime->dma_addr,
- runtime->dma_bytes);
-
-}
-
static int bcm63xx_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -362,25 +344,6 @@ static irqreturn_t i2s_dma_isr(int irq, void *bcm_i2s_priv)
return IRQ_HANDLED;
}
-static int bcm63xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = bcm63xx_pcm_hardware.buffer_bytes_max;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
-
- buf->area = dma_alloc_wc(pcm->card->dev,
- size, &buf->addr,
- GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
- buf->bytes = size;
- return 0;
-}
-
static int bcm63xx_soc_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
@@ -394,49 +357,18 @@ static int bcm63xx_soc_pcm_new(struct snd_soc_component *component,
ret = dma_coerce_mask_and_coherent(pcm->card->dev, DMA_BIT_MASK(32));
if (ret)
- goto out;
-
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = bcm63xx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
+ return ret;
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
i2s_priv->play_substream =
pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = bcm63xx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
i2s_priv->capture_substream =
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
- }
-out:
- return ret;
-}
-
-static void bcm63xx_pcm_free_dma_buffers(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- int stream;
- struct snd_dma_buffer *buf;
- struct snd_pcm_substream *substream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
- dma_free_wc(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+ pcm->card->dev,
+ bcm63xx_pcm_hardware.buffer_bytes_max);
}
static const struct snd_soc_component_driver bcm63xx_soc_platform = {
@@ -447,9 +379,7 @@ static const struct snd_soc_component_driver bcm63xx_soc_platform = {
.prepare = bcm63xx_pcm_prepare,
.trigger = bcm63xx_pcm_trigger,
.pointer = bcm63xx_pcm_pointer,
- .mmap = bcm63xx_pcm_mmap,
.pcm_construct = bcm63xx_soc_pcm_new,
- .pcm_destruct = bcm63xx_pcm_free_dma_buffers,
};
int bcm63xx_soc_platform_probe(struct platform_device *pdev,
diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c
index 56b71b965624..3abeaf0f1b1c 100644
--- a/sound/soc/bcm/cygnus-pcm.c
+++ b/sound/soc/bcm/cygnus-pcm.c
@@ -729,7 +729,7 @@ static struct snd_soc_component_driver cygnus_soc_platform = {
int cygnus_soc_platform_register(struct device *dev,
struct cygnus_audio *cygaud)
{
- int rc = 0;
+ int rc;
dev_dbg(dev, "%s Enter\n", __func__);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index db16071205ba..82ee233a269d 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -187,6 +187,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_RT715_SDCA_SDW
imply SND_SOC_RT1308_SDW
imply SND_SOC_RT1316_SDW
+ imply SND_SOC_SDW_MOCKUP
imply SND_SOC_SGTL5000
imply SND_SOC_SI476X
imply SND_SOC_SIMPLE_AMPLIFIER
@@ -847,7 +848,7 @@ config SND_SOC_HDAC_HDA
select SND_HDA
config SND_SOC_ICS43432
- tristate
+ tristate "ICS43423 and compatible i2s microphones"
config SND_SOC_INNO_RK3036
tristate "Inno codec driver for RK3036 SoC"
@@ -1287,6 +1288,23 @@ config SND_SOC_RT715_SDCA_SDW
select REGMAP_SOUNDWIRE
select REGMAP_SOUNDWIRE_MBQ
+config SND_SOC_SDW_MOCKUP
+ tristate "SoundWire mockup codec"
+ depends on EXPERT
+ depends on SOUNDWIRE
+ help
+ This option enables a SoundWire mockup codec that does not drive the
+ bus, take part in the command/command protocol or generate data on a
+ Source port.
+ This option is only intended to be used for tests on a device
+ with a connector, in combination with a bus analyzer, or to test new
+ topologies that differ from the actual hardware layout.
+ This mockup device could be totally virtual but could also be a
+ real physical one with one key restriction: it is not allowed by the
+ SoundWire specification to be configured via a sideband mechanism and
+ generate audio data for capture. However, nothing prevents such a
+ peripheral device from snooping the bus.
+
#Freescale sgtl5000 codec
config SND_SOC_SGTL5000
tristate "Freescale SGTL5000 CODEC"
@@ -1564,6 +1582,7 @@ config SND_SOC_WCD938X
config SND_SOC_WCD938X_SDW
tristate "WCD9380/WCD9385 Codec - SDW"
select SND_SOC_WCD938X
+ select SND_SOC_WCD_MBHC
depends on SOUNDWIRE
select REGMAP_SOUNDWIRE
help
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 7bb38c370842..8dcea2c4604a 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -203,6 +203,7 @@ snd-soc-rt711-objs := rt711.o rt711-sdw.o
snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o
snd-soc-rt715-objs := rt715.o rt715-sdw.o
snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o
+snd-soc-sdw-mockup-objs := sdw-mockup.o
snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
snd-soc-alc5632-objs := alc5632.o
@@ -530,6 +531,7 @@ obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o
obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o
obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o
obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o
+obj-$(CONFIG_SND_SOC_SDW_MOCKUP) += snd-soc-sdw-mockup.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index f37ab7eda615..278a55af158b 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -316,6 +316,13 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
int word_len = 0, master_rate = 0;
struct snd_soc_component *component = dai->component;
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
+ bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ u8 dacc0;
+
+ dev_dbg(dai->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
+ __func__, params_rate(params), params_format(params),
+ params_width(params), params_channels(params));
+
/* bit size */
switch (params_width(params)) {
@@ -346,6 +353,25 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
break;
}
+ if (is_playback) {
+ switch (params_rate(params)) {
+ case 48000:
+ dacc0 = AD193X_DAC_SR_48;
+ break;
+ case 96000:
+ dacc0 = AD193X_DAC_SR_96;
+ break;
+ case 192000:
+ dacc0 = AD193X_DAC_SR_192;
+ break;
+ default:
+ dev_err(dai->dev, "invalid sampling rate: %d\n", params_rate(params));
+ return -EINVAL;
+ }
+
+ regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL0, AD193X_DAC_SR_MASK, dacc0);
+ }
+
regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0,
AD193X_PLL_INPUT_MASK, master_rate);
@@ -385,7 +411,7 @@ static struct snd_soc_dai_driver ad193x_dai = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
- .rates = SNDRV_PCM_RATE_48000,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
},
@@ -407,7 +433,7 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
- .rates = SNDRV_PCM_RATE_48000,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
},
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 377854712c20..61f4648861d5 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -37,6 +37,10 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
#define AD193X_PLL_CLK_SRC_MCLK (1 << 1)
#define AD193X_DAC_CTRL0 0x02
#define AD193X_DAC_POWERDOWN 0x01
+#define AD193X_DAC_SR_MASK 0x06
+#define AD193X_DAC_SR_48 (0 << 1)
+#define AD193X_DAC_SR_96 (1 << 1)
+#define AD193X_DAC_SR_192 (2 << 1)
#define AD193X_DAC_SERFMT_MASK 0xC0
#define AD193X_DAC_SERFMT_STEREO (0 << 6)
#define AD193X_DAC_SERFMT_TDM (1 << 6)
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 99c022be94a6..fb1e4c33e27d 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -586,6 +586,7 @@ struct cs42l42_pll_params {
* Table 4-5 from the Datasheet
*/
static const struct cs42l42_pll_params pll_ratio_table[] = {
+ { 1411200, 0, 1, 0x00, 0x80, 0x000000, 0x03, 0x10, 11289600, 128, 2},
{ 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125, 2},
{ 2304000, 0, 1, 0x00, 0x55, 0xC00000, 0x02, 0x10, 12288000, 85, 2},
{ 2400000, 0, 1, 0x00, 0x50, 0x000000, 0x03, 0x10, 12000000, 80, 2},
@@ -843,6 +844,13 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
if (channels == 1)
cs42l42->bclk *= 2;
+ /*
+ * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being
+ * more than assumed (which would result in overclocking).
+ */
+ if (params_width(params) == 24)
+ cs42l42->bclk = (cs42l42->bclk / 3) * 4;
+
switch(substream->stream) {
case SNDRV_PCM_STREAM_CAPTURE:
if (channels == 2) {
@@ -890,10 +898,23 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
{
struct snd_soc_component *component = dai->component;
struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
+ int i;
- cs42l42->sclk = freq;
+ if (freq == 0) {
+ cs42l42->sclk = 0;
+ return 0;
+ }
- return 0;
+ for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
+ if (pll_ratio_table[i].sclk == freq) {
+ cs42l42->sclk = freq;
+ return 0;
+ }
+ }
+
+ dev_err(component->dev, "SCLK %u not supported\n", freq);
+
+ return -EINVAL;
}
static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
@@ -2106,4 +2127,7 @@ MODULE_DESCRIPTION("ASoC CS42L42 driver");
MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
MODULE_AUTHOR("Michael White, Cirrus Logic Inc, <michael.white@cirrus.com>");
+MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_AUTHOR("Vitaly Rodionov <vitalyr@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index ec8d6e74b467..13258f3ca9aa 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -206,7 +206,7 @@ static int cx20442_write(struct snd_soc_component *component, unsigned int reg,
*/
/* Modem init: echo off, digital speaker off, quiet off, voice mode */
-static const char *v253_init = "ate0m0q0+fclass=8\r";
+static const char v253_init[] = "ate0m0q0+fclass=8\r";
/* Line discipline .open() */
static int v253_open(struct tty_struct *tty)
@@ -279,11 +279,6 @@ static void v253_receive(struct tty_struct *tty, const unsigned char *cp,
}
}
-/* Line discipline .write_wakeup() */
-static void v253_wakeup(struct tty_struct *tty)
-{
-}
-
struct tty_ldisc_ops v253_ops = {
.name = "cx20442",
.owner = THIS_MODULE,
@@ -291,7 +286,6 @@ struct tty_ldisc_ops v253_ops = {
.close = v253_close,
.hangup = v253_hangup,
.receive_buf = v253_receive,
- .write_wakeup = v253_wakeup,
};
EXPORT_SYMBOL_GPL(v253_ops);
diff --git a/sound/soc/codecs/ics43432.c b/sound/soc/codecs/ics43432.c
index 47e749f03940..de4c8460ab3d 100644
--- a/sound/soc/codecs/ics43432.c
+++ b/sound/soc/codecs/ics43432.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * I2S MEMS microphone driver for InvenSense ICS-43432
+ * I2S MEMS microphone driver for InvenSense ICS-43432 and similar
+ * MEMS-based microphones.
*
* - Non configurable.
* - I2S interface, 64 BCLs per frame, 32 bits per channel, 24 bit data
@@ -53,6 +54,7 @@ static int ics43432_probe(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id ics43432_ids[] = {
{ .compatible = "invensense,ics43432", },
+ { .compatible = "cui,cmm-4030d-261", },
{ }
};
MODULE_DEVICE_TABLE(of, ics43432_ids);
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index 3622961f7c2c..196b06898eeb 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -1722,42 +1722,43 @@ static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
case RX_MACRO_AIF2_PB:
case RX_MACRO_AIF3_PB:
case RX_MACRO_AIF4_PB:
- for (j = 0; j < INTERP_MAX; j++) {
- reg = CDC_RX_RXn_RX_PATH_CTL(j);
- mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
- dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j);
-
- if (mute) {
- snd_soc_component_update_bits(component, reg,
- CDC_RX_PATH_PGA_MUTE_MASK,
- CDC_RX_PATH_PGA_MUTE_ENABLE);
- snd_soc_component_update_bits(component, mix_reg,
- CDC_RX_PATH_PGA_MUTE_MASK,
- CDC_RX_PATH_PGA_MUTE_ENABLE);
- } else {
- snd_soc_component_update_bits(component, reg,
- CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
- snd_soc_component_update_bits(component, mix_reg,
- CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
- }
-
- if (j == INTERP_AUX)
- dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
+ for (j = 0; j < INTERP_MAX; j++) {
+ reg = CDC_RX_RXn_RX_PATH_CTL(j);
+ mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
+ dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j);
+
+ if (mute) {
+ snd_soc_component_update_bits(component, reg,
+ CDC_RX_PATH_PGA_MUTE_MASK,
+ CDC_RX_PATH_PGA_MUTE_ENABLE);
+ snd_soc_component_update_bits(component, mix_reg,
+ CDC_RX_PATH_PGA_MUTE_MASK,
+ CDC_RX_PATH_PGA_MUTE_ENABLE);
+ } else {
+ snd_soc_component_update_bits(component, reg,
+ CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
+ snd_soc_component_update_bits(component, mix_reg,
+ CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
+ }
- int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
- int_mux_cfg1 = int_mux_cfg0 + 4;
- int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
- int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
+ if (j == INTERP_AUX)
+ dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
- if (snd_soc_component_read(component, dsm_reg) & 0x01) {
- if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0))
- snd_soc_component_update_bits(component, reg, 0x20, 0x20);
- if (int_mux_cfg1_val & 0x0F) {
- snd_soc_component_update_bits(component, reg, 0x20, 0x20);
- snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20);
+ int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
+ int_mux_cfg1 = int_mux_cfg0 + 4;
+ int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
+ int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
+
+ if (snd_soc_component_read(component, dsm_reg) & 0x01) {
+ if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0))
+ snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+ if (int_mux_cfg1_val & 0x0F) {
+ snd_soc_component_update_bits(component, reg, 0x20, 0x20);
+ snd_soc_component_update_bits(component, mix_reg, 0x20,
+ 0x20);
+ }
}
}
- }
break;
default:
break;
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index bc30a1dc7530..b45ec35cd63c 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -2158,13 +2158,11 @@ static void max98090_jack_work(struct work_struct *work)
msleep(50);
- reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
+ snd_soc_component_read(component, M98090_REG_JACK_STATUS);
/* Weak pull up allows only insertion detection */
snd_soc_component_update_bits(component, M98090_REG_JACK_DETECT,
M98090_JDWK_MASK, M98090_JDWK_MASK);
- } else {
- reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
}
reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c
index 94773ccee9d5..b392567c2b3e 100644
--- a/sound/soc/codecs/max98390.c
+++ b/sound/soc/codecs/max98390.c
@@ -765,17 +765,26 @@ static int max98390_dsm_init(struct snd_soc_component *component)
vendor = dmi_get_system_info(DMI_SYS_VENDOR);
product = dmi_get_system_info(DMI_PRODUCT_NAME);
- if (vendor && product) {
- snprintf(filename, sizeof(filename), "dsm_param_%s_%s.bin",
- vendor, product);
+ if (!strcmp(max98390->dsm_param_name, "default")) {
+ if (vendor && product) {
+ snprintf(filename, sizeof(filename),
+ "dsm_param_%s_%s.bin", vendor, product);
+ } else {
+ sprintf(filename, "dsm_param.bin");
+ }
} else {
- sprintf(filename, "dsm_param.bin");
+ snprintf(filename, sizeof(filename), "%s",
+ max98390->dsm_param_name);
}
ret = request_firmware(&fw, filename, component->dev);
if (ret) {
ret = request_firmware(&fw, "dsm_param.bin", component->dev);
- if (ret)
- goto err;
+ if (ret) {
+ ret = request_firmware(&fw, "dsmparam.bin",
+ component->dev);
+ if (ret)
+ goto err;
+ }
}
dev_dbg(component->dev,
@@ -1047,6 +1056,11 @@ static int max98390_i2c_probe(struct i2c_client *i2c,
__func__, max98390->ref_rdc_value,
max98390->ambient_temp_value);
+ ret = device_property_read_string(&i2c->dev, "maxim,dsm_param_name",
+ &max98390->dsm_param_name);
+ if (ret)
+ max98390->dsm_param_name = "default";
+
/* voltage/current slot configuration */
max98390_slot_config(i2c, max98390);
diff --git a/sound/soc/codecs/max98390.h b/sound/soc/codecs/max98390.h
index e31516717d3b..c250740f73a2 100644
--- a/sound/soc/codecs/max98390.h
+++ b/sound/soc/codecs/max98390.h
@@ -662,5 +662,6 @@ struct max98390_priv {
unsigned int i_l_slot;
unsigned int ref_rdc_value;
unsigned int ambient_temp_value;
+ const char *dsm_param_name;
};
#endif
diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c
index 78314187d37e..6d3d170144a0 100644
--- a/sound/soc/codecs/mt6359-accdet.c
+++ b/sound/soc/codecs/mt6359-accdet.c
@@ -234,7 +234,7 @@ static void recover_eint_setting(struct mt6359_accdet *priv)
static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
{
- int ret = 0;
+ int ret;
unsigned int value = 0;
regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
@@ -461,7 +461,7 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
{
struct mt6359_accdet *priv = data;
unsigned int irq_val = 0, val = 0, value = 0;
- int ret = 0;
+ int ret;
mutex_lock(&priv->res_lock);
regmap_read(priv->regmap, ACCDET_IRQ_ADDR, &irq_val);
@@ -551,7 +551,7 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
{
- int ret = 0;
+ int ret;
struct device *dev = priv->dev;
struct device_node *node = NULL;
int pwm_deb[15] = {0};
@@ -926,7 +926,7 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
{
struct mt6359_accdet *priv;
struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
- int ret = 0;
+ int ret;
dev_dbg(&pdev->dev, "%s(), dev name %s\n",
__func__, dev_name(&pdev->dev));
@@ -1057,22 +1057,7 @@ static struct platform_driver mt6359_accdet_driver = {
.probe = mt6359_accdet_probe,
};
-static int __init mt6359_accdet_driver_init(void)
-{
- int ret = 0;
-
- ret = platform_driver_register(&mt6359_accdet_driver);
- if (ret)
- return -ENODEV;
- return 0;
-}
-
-static void __exit mt6359_accdet_driver_exit(void)
-{
- platform_driver_unregister(&mt6359_accdet_driver);
-}
-module_init(mt6359_accdet_driver_init);
-module_exit(mt6359_accdet_driver_exit);
+module_platform_driver(mt6359_accdet_driver)
/* Module information */
MODULE_DESCRIPTION("MT6359 ALSA SoC codec jack driver");
diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
index 9238f12999aa..c0c5952cdff7 100644
--- a/sound/soc/codecs/rt1015.c
+++ b/sound/soc/codecs/rt1015.c
@@ -547,31 +547,6 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static void rt1015_flush_work(struct work_struct *work)
-{
- struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv,
- flush_work.work);
- struct snd_soc_component *component = rt1015->component;
- unsigned int val, i;
-
- for (i = 0; i < 200; ++i) {
- usleep_range(1000, 1500);
- dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i);
- regmap_read(rt1015->regmap, RT1015_CLK_DET, &val);
- if (val & 0x800)
- break;
- }
-
- regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597);
- regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7);
- regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028);
-
- if (val & 0x800)
- dev_dbg(component->dev, "Flush DAC completed.\n");
- else
- dev_warn(component->dev, "Fail to flush DAC data.\n");
-}
-
static const struct snd_kcontrol_new rt1015_snd_controls[] = {
SOC_SINGLE_TLV("DAC Playback Volume", RT1015_DAC1, RT1015_DAC_VOL_SFT,
127, 0, dac_vol_tlv),
@@ -630,10 +605,6 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
}
break;
- case SND_SOC_DAPM_POST_PMU:
- regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8);
- break;
-
case SND_SOC_DAPM_POST_PMD:
if (rt1015->bypass_boost == RT1015_Enable_Boost) {
snd_soc_component_write(component,
@@ -653,8 +624,6 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
RT1015_SYS_RST2, 0x0b9a);
}
rt1015->dac_is_used = 0;
-
- cancel_delayed_work_sync(&rt1015->flush_work);
break;
default:
@@ -687,8 +656,6 @@ static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w,
}
break;
case SND_SOC_DAPM_POST_PMU:
- if (rt1015->hw_config == RT1015_HW_28)
- schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10));
msleep(rt1015->pdata.power_up_delay_ms);
break;
default:
@@ -702,7 +669,7 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = {
NULL, 0),
SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
- r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ r1015_dac_event, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_OUT_DRV_E("Amp Drv", SND_SOC_NOPM, 0, 0, NULL, 0,
rt1015_amp_drv_event, SND_SOC_DAPM_PRE_PMU |
@@ -722,7 +689,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_component *component = dai->component;
struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
- int pre_div, bclk_ms, frame_size, lrck;
+ int pre_div, frame_size, lrck;
unsigned int val_len = 0;
lrck = params_rate(params);
@@ -739,10 +706,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- bclk_ms = frame_size > 32;
-
- dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
- bclk_ms, pre_div, dai->id);
+ dev_dbg(component->dev, "pre_div is %d for iis %d\n", pre_div, dai->id);
dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n",
lrck, pre_div, dai->id);
@@ -1028,7 +992,6 @@ static int rt1015_probe(struct snd_soc_component *component)
snd_soc_component_get_drvdata(component);
rt1015->component = component;
- INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work);
return 0;
}
@@ -1037,7 +1000,6 @@ static void rt1015_remove(struct snd_soc_component *component)
{
struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
- cancel_delayed_work_sync(&rt1015->flush_work);
regmap_write(rt1015->regmap, RT1015_RESET, 0);
}
@@ -1180,8 +1142,6 @@ static int rt1015_i2c_probe(struct i2c_client *i2c,
return ret;
}
- rt1015->hw_config = (i2c->addr == 0x29) ? RT1015_HW_29 : RT1015_HW_28;
-
ret = regmap_read(rt1015->regmap, RT1015_DEVICE_ID, &val);
if (ret) {
dev_err(&i2c->dev,
diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h
index 14344532048e..c9f636af7fd1 100644
--- a/sound/soc/codecs/rt1015.h
+++ b/sound/soc/codecs/rt1015.h
@@ -444,8 +444,6 @@ struct rt1015_priv {
int bypass_boost;
int dac_is_used;
int cali_done;
- int hw_config;
- struct delayed_work flush_work;
};
#endif /* __RT1015_H__ */
diff --git a/sound/soc/codecs/rt1015p.c b/sound/soc/codecs/rt1015p.c
index 40f2063aefbe..415cfb3b2f0d 100644
--- a/sound/soc/codecs/rt1015p.c
+++ b/sound/soc/codecs/rt1015p.c
@@ -127,6 +127,7 @@ static int rt1015p_platform_probe(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id rt1015p_device_id[] = {
{ .compatible = "realtek,rt1015p" },
+ { .compatible = "realtek,rt1019p" },
{}
};
MODULE_DEVICE_TABLE(of, rt1015p_device_id);
@@ -135,6 +136,7 @@ MODULE_DEVICE_TABLE(of, rt1015p_device_id);
#ifdef CONFIG_ACPI
static const struct acpi_device_id rt1015p_acpi_match[] = {
{ "RTL1015", 0},
+ { "RTL1019", 0},
{ },
};
MODULE_DEVICE_TABLE(acpi, rt1015p_acpi_match);
diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c
index 7081142a355e..4b1ad5054e8d 100644
--- a/sound/soc/codecs/rt5514.c
+++ b/sound/soc/codecs/rt5514.c
@@ -494,7 +494,7 @@ static const struct snd_kcontrol_new rt5514_sto2_dmic_mux =
*/
static int rt5514_calc_dmic_clk(struct snd_soc_component *component, int rate)
{
- int div[] = {2, 3, 4, 8, 12, 16, 24, 32};
+ static const int div[] = {2, 3, 4, 8, 12, 16, 24, 32};
int i;
if (rate < 1000000 * div[0]) {
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 9523f4b5c800..cd1db5caabad 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2093,7 +2093,7 @@ int rt5640_sel_asrc_clk_src(struct snd_soc_component *component,
}
EXPORT_SYMBOL_GPL(rt5640_sel_asrc_clk_src);
-static void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
+void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
@@ -2105,8 +2105,9 @@ static void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
}
+EXPORT_SYMBOL_GPL(rt5640_enable_micbias1_for_ovcd);
-static void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component)
+void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
@@ -2117,6 +2118,7 @@ static void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
}
+EXPORT_SYMBOL_GPL(rt5640_disable_micbias1_for_ovcd);
static void rt5640_enable_micbias1_ovcd_irq(struct snd_soc_component *component)
{
@@ -2241,7 +2243,7 @@ static void rt5640_button_press_work(struct work_struct *work)
schedule_delayed_work(&rt5640->bp_work, msecs_to_jiffies(BP_POLL_TIME));
}
-static int rt5640_detect_headset(struct snd_soc_component *component)
+int rt5640_detect_headset(struct snd_soc_component *component, struct gpio_desc *hp_det_gpio)
{
int i, headset_count = 0, headphone_count = 0;
@@ -2259,8 +2261,13 @@ static int rt5640_detect_headset(struct snd_soc_component *component)
msleep(JACK_SETTLE_TIME);
/* Check the jack is still connected before checking ovcd */
- if (!rt5640_jack_inserted(component))
- return 0;
+ if (hp_det_gpio) {
+ if (gpiod_get_value_cansleep(hp_det_gpio))
+ return 0;
+ } else {
+ if (!rt5640_jack_inserted(component))
+ return 0;
+ }
if (rt5640_micbias1_ovcd(component)) {
/*
@@ -2285,6 +2292,7 @@ static int rt5640_detect_headset(struct snd_soc_component *component)
dev_err(component->dev, "Error detecting headset vs headphones, bad contact?, assuming headphones\n");
return SND_JACK_HEADPHONE;
}
+EXPORT_SYMBOL_GPL(rt5640_detect_headset);
static void rt5640_jack_work(struct work_struct *work)
{
@@ -2309,7 +2317,7 @@ static void rt5640_jack_work(struct work_struct *work)
/* Jack inserted */
WARN_ON(rt5640->ovcd_irq_enabled);
rt5640_enable_micbias1_for_ovcd(component);
- status = rt5640_detect_headset(component);
+ status = rt5640_detect_headset(component, NULL);
if (status == SND_JACK_HEADSET) {
/* Enable ovcd IRQ for button press detect. */
rt5640_enable_micbias1_ovcd_irq(component);
@@ -2362,10 +2370,59 @@ static void rt5640_cancel_work(void *data)
cancel_delayed_work_sync(&rt5640->bp_work);
}
+void rt5640_set_ovcd_params(struct snd_soc_component *component)
+{
+ struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
+
+ snd_soc_component_write(component, RT5640_PR_BASE + RT5640_BIAS_CUR4,
+ 0xa800 | rt5640->ovcd_sf);
+
+ snd_soc_component_update_bits(component, RT5640_MICBIAS,
+ RT5640_MIC1_OVTH_MASK | RT5640_MIC1_OVCD_MASK,
+ rt5640->ovcd_th | RT5640_MIC1_OVCD_EN);
+
+ /*
+ * The over-current-detect is only reliable in detecting the absence
+ * of over-current, when the mic-contact in the jack is short-circuited,
+ * the hardware periodically retries if it can apply the bias-current
+ * leading to the ovcd status flip-flopping 1-0-1 with it being 0 about
+ * 10% of the time, as we poll the ovcd status bit we might hit that
+ * 10%, so we enable sticky mode and when checking OVCD we clear the
+ * status, msleep() a bit and then check to get a reliable reading.
+ */
+ snd_soc_component_update_bits(component, RT5640_IRQ_CTRL2,
+ RT5640_MB1_OC_STKY_MASK, RT5640_MB1_OC_STKY_EN);
+}
+EXPORT_SYMBOL_GPL(rt5640_set_ovcd_params);
+
+static void rt5640_disable_jack_detect(struct snd_soc_component *component)
+{
+ struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
+
+ /*
+ * soc_remove_component() force-disables jack and thus rt5640->jack
+ * could be NULL at the time of driver's module unloading.
+ */
+ if (!rt5640->jack)
+ return;
+
+ free_irq(rt5640->irq, rt5640);
+ rt5640_cancel_work(rt5640);
+
+ if (rt5640->jack->status & SND_JACK_MICROPHONE) {
+ rt5640_disable_micbias1_ovcd_irq(component);
+ rt5640_disable_micbias1_for_ovcd(component);
+ snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
+ }
+
+ rt5640->jack = NULL;
+}
+
static void rt5640_enable_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *jack)
{
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
+ int ret;
/* Select JD-source */
snd_soc_component_update_bits(component, RT5640_JD_CTRL,
@@ -2385,24 +2442,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
/* Enabling jd2 in general control 2 */
snd_soc_component_write(component, RT5640_DUMMY2, 0x4001);
- snd_soc_component_write(component, RT5640_PR_BASE + RT5640_BIAS_CUR4,
- 0xa800 | rt5640->ovcd_sf);
-
- snd_soc_component_update_bits(component, RT5640_MICBIAS,
- RT5640_MIC1_OVTH_MASK | RT5640_MIC1_OVCD_MASK,
- rt5640->ovcd_th | RT5640_MIC1_OVCD_EN);
-
- /*
- * The over-current-detect is only reliable in detecting the absence
- * of over-current, when the mic-contact in the jack is short-circuited,
- * the hardware periodically retries if it can apply the bias-current
- * leading to the ovcd status flip-flopping 1-0-1 with it being 0 about
- * 10% of the time, as we poll the ovcd status bit we might hit that
- * 10%, so we enable sticky mode and when checking OVCD we clear the
- * status, msleep() a bit and then check to get a reliable reading.
- */
- snd_soc_component_update_bits(component, RT5640_IRQ_CTRL2,
- RT5640_MB1_OC_STKY_MASK, RT5640_MB1_OC_STKY_EN);
+ rt5640_set_ovcd_params(component);
/*
* All IRQs get or-ed together, so we need the jack IRQ to report 0
@@ -2423,32 +2463,19 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
rt5640_enable_micbias1_ovcd_irq(component);
}
- enable_irq(rt5640->irq);
- /* sync initial jack state */
- queue_work(system_long_wq, &rt5640->jack_work);
-}
-
-static void rt5640_disable_jack_detect(struct snd_soc_component *component)
-{
- struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
-
- /*
- * soc_remove_component() force-disables jack and thus rt5640->jack
- * could be NULL at the time of driver's module unloading.
- */
- if (!rt5640->jack)
+ ret = request_irq(rt5640->irq, rt5640_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "rt5640", rt5640);
+ if (ret) {
+ dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
+ rt5640->irq = -ENXIO;
+ /* Undo above settings */
+ rt5640_disable_jack_detect(component);
return;
-
- disable_irq(rt5640->irq);
- rt5640_cancel_work(rt5640);
-
- if (rt5640->jack->status & SND_JACK_MICROPHONE) {
- rt5640_disable_micbias1_ovcd_irq(component);
- rt5640_disable_micbias1_for_ovcd(component);
- snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
}
- rt5640->jack = NULL;
+ /* sync initial jack state */
+ queue_work(system_long_wq, &rt5640->jack_work);
}
static int rt5640_set_jack(struct snd_soc_component *component,
@@ -2836,18 +2863,6 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
if (ret)
return ret;
- ret = devm_request_irq(&i2c->dev, rt5640->irq, rt5640_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
- | IRQF_ONESHOT, "rt5640", rt5640);
- if (ret == 0) {
- /* Gets re-enabled by rt5640_set_jack() */
- disable_irq(rt5640->irq);
- } else {
- dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n",
- rt5640->irq, ret);
- rt5640->irq = -ENXIO;
- }
-
return devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_rt5640,
rt5640_dai, ARRAY_SIZE(rt5640_dai));
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 4fd47f2b936b..2c28f83e338a 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -10,6 +10,7 @@
#define _RT5640_H
#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
#include <linux/workqueue.h>
#include <dt-bindings/sound/rt5640.h>
@@ -2157,4 +2158,9 @@ int rt5640_dmic_enable(struct snd_soc_component *component,
int rt5640_sel_asrc_clk_src(struct snd_soc_component *component,
unsigned int filter_mask, unsigned int clk_src);
+void rt5640_set_ovcd_params(struct snd_soc_component *component);
+void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component);
+void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component);
+int rt5640_detect_headset(struct snd_soc_component *component, struct gpio_desc *hp_det_gpio);
+
#endif
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c
index 4a56a52adab5..b9d5d7a0975b 100644
--- a/sound/soc/codecs/rt5682-i2c.c
+++ b/sound/soc/codecs/rt5682-i2c.c
@@ -117,6 +117,13 @@ static struct snd_soc_dai_driver rt5682_dai[] = {
},
};
+static void rt5682_i2c_disable_regulators(void *data)
+{
+ struct rt5682_priv *rt5682 = data;
+
+ regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies);
+}
+
static int rt5682_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -157,6 +164,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c,
return ret;
}
+ ret = devm_add_action_or_reset(&i2c->dev, rt5682_i2c_disable_regulators,
+ rt5682);
+ if (ret)
+ return ret;
+
ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies),
rt5682->supplies);
if (ret) {
@@ -282,10 +294,7 @@ static void rt5682_i2c_shutdown(struct i2c_client *client)
static int rt5682_i2c_remove(struct i2c_client *client)
{
- struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
-
rt5682_i2c_shutdown(client);
- regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies);
return 0;
}
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index 51ecaa2abcd1..e822fa1b9d4b 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -43,8 +43,9 @@ static const struct reg_sequence patch_list[] = {
{RT5682_DAC_ADC_DIG_VOL1, 0xa020},
{RT5682_I2C_CTRL, 0x000f},
{RT5682_PLL2_INTERNAL, 0x8266},
- {RT5682_SAR_IL_CMD_3, 0x8365},
- {RT5682_SAR_IL_CMD_6, 0x0180},
+ {RT5682_SAR_IL_CMD_1, 0x22b7},
+ {RT5682_SAR_IL_CMD_3, 0x0365},
+ {RT5682_SAR_IL_CMD_6, 0x0110},
};
void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev)
@@ -1727,8 +1728,6 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", RT5682_STO1_ADC_DIG_VOL,
RT5682_R_MUTE_SFT, 1, rt5682_sto1_adc_r_mix,
ARRAY_SIZE(rt5682_sto1_adc_r_mix)),
- SND_SOC_DAPM_SUPPLY("BTN Detection Mode", RT5682_SAR_IL_CMD_1,
- 14, 1, NULL, 0),
/* ADC PGA */
SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -1899,8 +1898,6 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
{"Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux"},
{"Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter"},
- {"ADC Stereo1 Filter", NULL, "BTN Detection Mode"},
-
{"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL"},
{"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR"},
@@ -2916,10 +2913,47 @@ static void rt5682_remove(struct snd_soc_component *component)
static int rt5682_suspend(struct snd_soc_component *component)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
+ unsigned int val;
if (rt5682->is_sdw)
return 0;
+ cancel_delayed_work_sync(&rt5682->jack_detect_work);
+ cancel_delayed_work_sync(&rt5682->jd_check_work);
+ if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) {
+ snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+ RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK,
+ RT5682_CTRL_MB1_REG | RT5682_CTRL_MB2_REG);
+ val = snd_soc_component_read(component,
+ RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK;
+
+ switch (val) {
+ case 0x1:
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK,
+ RT5682_SAR_SEL_MB1_NOSEL | RT5682_SAR_SEL_MB2_SEL);
+ break;
+ case 0x2:
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK,
+ RT5682_SAR_SEL_MB1_SEL | RT5682_SAR_SEL_MB2_NOSEL);
+ break;
+ default:
+ break;
+ }
+
+ snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
+ RT5682_PWR_CBJ, 0);
+
+ /* enter SAR ADC power saving mode */
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK |
+ RT5682_SAR_BUTDET_RST_MASK | RT5682_SAR_SEL_MB1_MB2_MASK, 0);
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_BUTDET_RST_MASK,
+ RT5682_SAR_BUTT_DET_EN | RT5682_SAR_BUTDET_POW_SAV | RT5682_SAR_BUTDET_RST_NORMAL);
+ }
+
regcache_cache_only(rt5682->regmap, true);
regcache_mark_dirty(rt5682->regmap);
return 0;
@@ -2935,6 +2969,17 @@ static int rt5682_resume(struct snd_soc_component *component)
regcache_cache_only(rt5682->regmap, false);
regcache_sync(rt5682->regmap);
+ if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) {
+ snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
+ RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_SEL_MB1_MB2_MASK,
+ RT5682_SAR_BUTDET_POW_NORM | RT5682_SAR_SEL_MB1_MB2_AUTO);
+ snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
+ RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK,
+ RT5682_CTRL_MB1_FSM | RT5682_CTRL_MB2_FSM);
+ snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
+ RT5682_PWR_CBJ, RT5682_PWR_CBJ);
+ }
+
mod_delayed_work(system_power_efficient_wq,
&rt5682->jack_detect_work, msecs_to_jiffies(250));
diff --git a/sound/soc/codecs/sdw-mockup.c b/sound/soc/codecs/sdw-mockup.c
new file mode 100644
index 000000000000..8ea13cfa9f8e
--- /dev/null
+++ b/sound/soc/codecs/sdw-mockup.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// sdw-mockup.c -- a mockup SoundWire codec for tests where only the host
+// drives the bus.
+//
+// Copyright(c) 2021 Intel Corporation
+//
+//
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+struct sdw_mockup_priv {
+ struct sdw_slave *slave;
+};
+
+struct sdw_stream_data {
+ struct sdw_stream_runtime *sdw_stream;
+};
+
+static int sdw_mockup_component_probe(struct snd_soc_component *component)
+{
+ return 0;
+}
+
+static void sdw_mockup_component_remove(struct snd_soc_component *component)
+{
+}
+
+static const struct snd_soc_component_driver snd_soc_sdw_mockup_component = {
+ .probe = sdw_mockup_component_probe,
+ .remove = sdw_mockup_component_remove,
+};
+
+static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
+ int direction)
+{
+ struct sdw_stream_data *stream;
+
+ if (!sdw_stream)
+ return 0;
+
+ stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+ if (!stream)
+ return -ENOMEM;
+
+ stream->sdw_stream = sdw_stream;
+
+ /* Use tx_mask or rx_mask to configure stream tag and set dma_data */
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ dai->playback_dma_data = stream;
+ else
+ dai->capture_dma_data = stream;
+
+ return 0;
+}
+
+static void sdw_mockup_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct sdw_stream_data *stream;
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+ kfree(stream);
+}
+
+static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_config stream_config;
+ struct sdw_port_config port_config;
+ enum sdw_data_direction direction;
+ struct sdw_stream_data *stream;
+ int num_channels;
+ int port;
+ int ret;
+
+ stream = snd_soc_dai_get_dma_data(dai, substream);
+ if (!stream)
+ return -EINVAL;
+
+ if (!sdw_mockup->slave)
+ return -EINVAL;
+
+ /* SoundWire specific configuration */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ direction = SDW_DATA_DIR_RX;
+ port = 1;
+ } else {
+ direction = SDW_DATA_DIR_TX;
+ port = 8;
+ }
+
+ stream_config.frame_rate = params_rate(params);
+ stream_config.ch_count = params_channels(params);
+ stream_config.bps = snd_pcm_format_width(params_format(params));
+ stream_config.direction = direction;
+
+ num_channels = params_channels(params);
+ port_config.ch_mask = (1 << num_channels) - 1;
+ port_config.num = port;
+
+ ret = sdw_stream_add_slave(sdw_mockup->slave, &stream_config,
+ &port_config, 1, stream->sdw_stream);
+ if (ret)
+ dev_err(dai->dev, "Unable to configure port\n");
+
+ return ret;
+}
+
+static int sdw_mockup_pcm_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_data *stream =
+ snd_soc_dai_get_dma_data(dai, substream);
+
+ if (!sdw_mockup->slave)
+ return -EINVAL;
+
+ sdw_stream_remove_slave(sdw_mockup->slave, stream->sdw_stream);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops sdw_mockup_ops = {
+ .hw_params = sdw_mockup_pcm_hw_params,
+ .hw_free = sdw_mockup_pcm_hw_free,
+ .set_sdw_stream = sdw_mockup_set_sdw_stream,
+ .shutdown = sdw_mockup_shutdown,
+};
+
+static struct snd_soc_dai_driver sdw_mockup_dai[] = {
+ {
+ .name = "sdw-mockup-aif1",
+ .id = 1,
+ .playback = {
+ .stream_name = "DP1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .capture = {
+ .stream_name = "DP8 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &sdw_mockup_ops,
+ },
+};
+
+static int sdw_mockup_update_status(struct sdw_slave *slave,
+ enum sdw_slave_status status)
+{
+ return 0;
+}
+
+static int sdw_mockup_read_prop(struct sdw_slave *slave)
+{
+ struct sdw_slave_prop *prop = &slave->prop;
+ int nval;
+ int i, j;
+ u32 bit;
+ unsigned long addr;
+ struct sdw_dpn_prop *dpn;
+
+ prop->paging_support = false;
+
+ /*
+ * first we need to allocate memory for set bits in port lists
+ * the port allocation is completely arbitrary:
+ * DP0 is not supported
+ * DP1 is sink
+ * DP8 is source
+ */
+ prop->source_ports = BIT(8);
+ prop->sink_ports = BIT(1);
+
+ nval = hweight32(prop->source_ports);
+ prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
+ sizeof(*prop->src_dpn_prop),
+ GFP_KERNEL);
+ if (!prop->src_dpn_prop)
+ return -ENOMEM;
+
+ i = 0;
+ dpn = prop->src_dpn_prop;
+ addr = prop->source_ports;
+ for_each_set_bit(bit, &addr, 32) {
+ dpn[i].num = bit;
+ dpn[i].type = SDW_DPN_FULL;
+ dpn[i].simple_ch_prep_sm = true;
+ i++;
+ }
+
+ /* do this again for sink now */
+ nval = hweight32(prop->sink_ports);
+ prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
+ sizeof(*prop->sink_dpn_prop),
+ GFP_KERNEL);
+ if (!prop->sink_dpn_prop)
+ return -ENOMEM;
+
+ j = 0;
+ dpn = prop->sink_dpn_prop;
+ addr = prop->sink_ports;
+ for_each_set_bit(bit, &addr, 32) {
+ dpn[j].num = bit;
+ dpn[j].type = SDW_DPN_FULL;
+ dpn[j].simple_ch_prep_sm = true;
+ j++;
+ }
+
+ prop->simple_clk_stop_capable = true;
+
+ /* wake-up event */
+ prop->wake_capable = 0;
+
+ return 0;
+}
+
+static int sdw_mockup_bus_config(struct sdw_slave *slave,
+ struct sdw_bus_params *params)
+{
+ return 0;
+}
+
+static int sdw_mockup_interrupt_callback(struct sdw_slave *slave,
+ struct sdw_slave_intr_status *status)
+{
+ return 0;
+}
+
+static const struct sdw_slave_ops sdw_mockup_slave_ops = {
+ .read_prop = sdw_mockup_read_prop,
+ .interrupt_callback = sdw_mockup_interrupt_callback,
+ .update_status = sdw_mockup_update_status,
+ .bus_config = sdw_mockup_bus_config,
+};
+
+static int sdw_mockup_sdw_probe(struct sdw_slave *slave,
+ const struct sdw_device_id *id)
+{
+ struct device *dev = &slave->dev;
+ struct sdw_mockup_priv *sdw_mockup;
+ int ret;
+
+ sdw_mockup = devm_kzalloc(dev, sizeof(*sdw_mockup), GFP_KERNEL);
+ if (!sdw_mockup)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, sdw_mockup);
+ sdw_mockup->slave = slave;
+
+ slave->is_mockup_device = true;
+
+ ret = devm_snd_soc_register_component(dev,
+ &snd_soc_sdw_mockup_component,
+ sdw_mockup_dai,
+ ARRAY_SIZE(sdw_mockup_dai));
+
+ return ret;
+}
+
+static int sdw_mockup_sdw_remove(struct sdw_slave *slave)
+{
+ return 0;
+}
+
+/*
+ * Intel reserved parts ID with the following mapping expected:
+ * 0xAAAA: generic full-duplex codec
+ * 0xAA55: headset codec (mock-up of RT711/RT5682) - full-duplex
+ * 0x55AA: amplifier (mock-up of RT1308/Maxim 98373) - playback only with
+ * IV feedback
+ * 0x5555: mic codec (mock-up of RT715) - capture-only
+ */
+static const struct sdw_device_id sdw_mockup_id[] = {
+ SDW_SLAVE_ENTRY_EXT(0x0105, 0xAAAA, 0x0, 0, 0),
+ SDW_SLAVE_ENTRY_EXT(0x0105, 0xAA55, 0x0, 0, 0),
+ SDW_SLAVE_ENTRY_EXT(0x0105, 0x55AA, 0x0, 0, 0),
+ SDW_SLAVE_ENTRY_EXT(0x0105, 0x5555, 0x0, 0, 0),
+ {},
+};
+MODULE_DEVICE_TABLE(sdw, sdw_mockup_id);
+
+static struct sdw_driver sdw_mockup_sdw_driver = {
+ .driver = {
+ .name = "sdw-mockup",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdw_mockup_sdw_probe,
+ .remove = sdw_mockup_sdw_remove,
+ .ops = &sdw_mockup_slave_ops,
+ .id_table = sdw_mockup_id,
+};
+module_sdw_driver(sdw_mockup_sdw_driver);
+
+MODULE_DESCRIPTION("ASoC SDW mockup codec driver");
+MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 2e9175b37dc9..d39c7d52ecfd 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -714,7 +714,7 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
unsigned long adc_clock_rate, dac_clock_rate;
int ret;
- struct clk_bulk_data clocks[] = {
+ static struct clk_bulk_data clocks[] = {
{ .id = "pll" },
{ .id = "nadc" },
{ .id = "madc" },
@@ -878,7 +878,7 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
{
int ret;
- struct clk_bulk_data clocks[] = {
+ static struct clk_bulk_data clocks[] = {
{ .id = "madc" },
{ .id = "mdac" },
{ .id = "bdiv" },
@@ -994,7 +994,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component)
u32 tmp_reg;
int ret;
- struct clk_bulk_data clocks[] = {
+ static struct clk_bulk_data clocks[] = {
{ .id = "codec_clkin" },
{ .id = "pll" },
{ .id = "bdiv" },
@@ -1131,7 +1131,7 @@ static struct snd_soc_dai_driver aic32x4_tas2505_dai = {
.playback = {
.stream_name = "Playback",
.channels_min = 1,
- .channels_max = 1,
+ .channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = AIC32X4_FORMATS,},
.ops = &aic32x4_ops,
@@ -1144,7 +1144,7 @@ static int aic32x4_tas2505_component_probe(struct snd_soc_component *component)
u32 tmp_reg;
int ret;
- struct clk_bulk_data clocks[] = {
+ static struct clk_bulk_data clocks[] = {
{ .id = "codec_clkin" },
{ .id = "pll" },
{ .id = "bdiv" },
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 86c92e03ea5d..d885ced34f60 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -4076,6 +4076,16 @@ static int wcd9335_setup_irqs(struct wcd9335_codec *wcd)
return ret;
}
+static void wcd9335_teardown_irqs(struct wcd9335_codec *wcd)
+{
+ int i;
+
+ /* disable interrupts on all slave ports */
+ for (i = 0; i < WCD9335_SLIM_NUM_PORT_REG; i++)
+ regmap_write(wcd->if_regmap, WCD9335_SLIM_PGD_PORT_INT_EN0 + i,
+ 0x00);
+}
+
static void wcd9335_cdc_sido_ccl_enable(struct wcd9335_codec *wcd,
bool ccl_flag)
{
@@ -4844,6 +4854,7 @@ static void wcd9335_codec_init(struct snd_soc_component *component)
static int wcd9335_codec_probe(struct snd_soc_component *component)
{
struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
+ int ret;
int i;
snd_soc_component_init_regmap(component, wcd->regmap);
@@ -4861,7 +4872,15 @@ static int wcd9335_codec_probe(struct snd_soc_component *component)
for (i = 0; i < NUM_CODEC_DAIS; i++)
INIT_LIST_HEAD(&wcd->dai[i].slim_ch_list);
- return wcd9335_setup_irqs(wcd);
+ ret = wcd9335_setup_irqs(wcd);
+ if (ret)
+ goto free_clsh_ctrl;
+
+ return 0;
+
+free_clsh_ctrl:
+ wcd_clsh_ctrl_free(wcd->clsh_ctrl);
+ return ret;
}
static void wcd9335_codec_remove(struct snd_soc_component *comp)
@@ -4869,7 +4888,7 @@ static void wcd9335_codec_remove(struct snd_soc_component *comp)
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
wcd_clsh_ctrl_free(wcd->clsh_ctrl);
- free_irq(regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS), wcd);
+ wcd9335_teardown_irqs(wcd);
}
static int wcd9335_codec_set_sysclk(struct snd_soc_component *comp,
diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
index 2fcc97370be2..f0daf8defcf1 100644
--- a/sound/soc/codecs/wcd938x.c
+++ b/sound/soc/codecs/wcd938x.c
@@ -21,6 +21,7 @@
#include <linux/regulator/consumer.h>
#include "wcd-clsh-v2.h"
+#include "wcd-mbhc-v2.h"
#include "wcd938x.h"
#define WCD938X_MAX_MICBIAS (4)
@@ -173,6 +174,11 @@ struct wcd938x_priv {
struct device *rxdev;
struct device_node *rxnode, *txnode;
struct regmap *regmap;
+ struct mutex micb_lock;
+ /* mbhc module */
+ struct wcd_mbhc *wcd_mbhc;
+ struct wcd_mbhc_config mbhc_cfg;
+ struct wcd_mbhc_intr intr_ids;
struct wcd_clsh_ctrl *clsh_info;
struct irq_domain *virq;
struct regmap_irq_chip *wcd_regmap_irq_chip;
@@ -201,24 +207,70 @@ struct wcd938x_priv {
bool bcs_dis;
};
-enum {
- MIC_BIAS_1 = 1,
- MIC_BIAS_2,
- MIC_BIAS_3,
- MIC_BIAS_4
-};
-
-enum {
- MICB_PULLUP_ENABLE,
- MICB_PULLUP_DISABLE,
- MICB_ENABLE,
- MICB_DISABLE,
-};
-
static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(line_gain, 600, -3000);
static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000);
+struct wcd938x_mbhc_zdet_param {
+ u16 ldo_ctl;
+ u16 noff;
+ u16 nshift;
+ u16 btn5;
+ u16 btn6;
+ u16 btn7;
+};
+
+static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
+ WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD938X_ANA_MBHC_MECH, 0x80),
+ WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD938X_ANA_MBHC_MECH, 0x40),
+ WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD938X_ANA_MBHC_MECH, 0x20),
+ WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x30),
+ WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, WCD938X_ANA_MBHC_ELECT, 0x08),
+ WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F),
+ WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, WCD938X_ANA_MBHC_MECH, 0x04),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x10),
+ WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x08),
+ WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, WCD938X_ANA_MBHC_MECH, 0x01),
+ WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, WCD938X_ANA_MBHC_ELECT, 0x06),
+ WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, WCD938X_ANA_MBHC_ELECT, 0x80),
+ WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F),
+ WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, WCD938X_MBHC_NEW_CTL_1, 0x03),
+ WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, WCD938X_MBHC_NEW_CTL_2, 0x03),
+ WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x08),
+ WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, WCD938X_ANA_MBHC_RESULT_3, 0x10),
+ WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x20),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x80),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x40),
+ WCD_MBHC_FIELD(WCD_MBHC_OCP_FSM_EN, WCD938X_HPH_OCP_CTL, 0x10),
+ WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x07),
+ WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, WCD938X_ANA_MBHC_ELECT, 0x70),
+ WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0xFF),
+ WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, WCD938X_ANA_MICB2, 0xC0),
+ WCD_MBHC_FIELD(WCD_MBHC_HPH_CNP_WG_TIME, WCD938X_HPH_CNP_WG_TIME, 0xFF),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, WCD938X_ANA_HPH, 0x40),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, WCD938X_ANA_HPH, 0x80),
+ WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, WCD938X_ANA_HPH, 0xC0),
+ WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, WCD938X_ANA_MBHC_RESULT_3, 0x10),
+ WCD_MBHC_FIELD(WCD_MBHC_ANC_DET_EN, WCD938X_MBHC_CTL_BCS, 0x02),
+ WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x01),
+ WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, WCD938X_MBHC_NEW_CTL_2, 0x70),
+ WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x20),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHR_GND, WCD938X_HPH_PA_CTL2, 0x40),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHL_GND, WCD938X_HPH_PA_CTL2, 0x10),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, WCD938X_HPH_L_TEST, 0x01),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, WCD938X_HPH_R_TEST, 0x01),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x80),
+ WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x20),
+ WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, WCD938X_MBHC_NEW_CTL_1, 0x08),
+ WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, WCD938X_MBHC_NEW_FSM_STATUS, 0x40),
+ WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, WCD938X_MBHC_NEW_FSM_STATUS, 0x80),
+ WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, WCD938X_MBHC_NEW_ADC_RESULT, 0xFF),
+ WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, WCD938X_ANA_MICB2, 0x3F),
+ WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, WCD938X_MBHC_NEW_CTL_1, 0x10),
+ WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, WCD938X_MBHC_NEW_CTL_1, 0x04),
+ WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD938X_ANA_MBHC_ZDET, 0x02),
+};
+
static const struct reg_default wcd938x_defaults[] = {
{WCD938X_ANA_PAGE_REGISTER, 0x00},
{WCD938X_ANA_BIAS, 0x00},
@@ -1360,7 +1412,6 @@ static int wcd938x_io_init(struct wcd938x_priv *wcd938x)
static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info,
struct sdw_port_config *port_config,
- u32 mstr_port_num,
u8 enable)
{
u8 ch_mask, port_num;
@@ -1380,14 +1431,12 @@ static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info,
static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 ch_id, u8 enable)
{
- u8 port_num, mstr_port_num;
+ u8 port_num;
port_num = wcd->ch_info[ch_id].port_num;
- mstr_port_num = wcd->port_map[port_num - 1];
return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id],
&wcd->port_config[port_num],
- mstr_port_num,
enable);
}
@@ -1623,7 +1672,6 @@ static int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
- int ret = 0;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -1651,7 +1699,7 @@ static int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 0);
break;
}
- return ret;
+ return 0;
}
@@ -1728,6 +1776,8 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
usleep_range(7000, 7100);
snd_soc_component_write_field(component, WCD938X_ANA_HPH,
WCD938X_HPHR_EN_MASK, 0);
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+ WCD_EVENT_PRE_HPHR_PA_OFF);
set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
break;
case SND_SOC_DAPM_POST_PMD:
@@ -1743,6 +1793,8 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
usleep_range(7000, 7100);
clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
}
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+ WCD_EVENT_POST_HPHR_PA_OFF);
snd_soc_component_write_field(component, WCD938X_ANA_HPH,
WCD938X_HPHR_REF_EN_MASK, 0);
snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL1,
@@ -1830,6 +1882,7 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
usleep_range(7000, 7100);
snd_soc_component_write_field(component, WCD938X_ANA_HPH,
WCD938X_HPHL_EN_MASK, 0);
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc, WCD_EVENT_PRE_HPHL_PA_OFF);
set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
break;
case SND_SOC_DAPM_POST_PMD:
@@ -1845,6 +1898,8 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
usleep_range(7000, 7100);
clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
}
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+ WCD_EVENT_POST_HPHL_PA_OFF);
snd_soc_component_write_field(component, WCD938X_ANA_HPH,
WCD938X_HPHL_REF_EN_MASK, 0);
snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0,
@@ -1866,7 +1921,6 @@ static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
int hph_mode = wcd938x->hph_mode;
- int ret = 0;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -1902,7 +1956,7 @@ static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
WCD938X_EN_CUR_DET_MASK, 1);
break;
}
- return ret;
+ return 0;
}
static int wcd938x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
@@ -2355,7 +2409,14 @@ static int wcd938x_micbias_control(struct snd_soc_component *component,
snd_soc_component_write_field(component, micb_reg,
WCD938X_MICB_EN_MASK,
WCD938X_MICB_ENABLE);
+ if (micb_num == MIC_BIAS_2)
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+ WCD_EVENT_POST_MICBIAS_2_ON);
}
+ if (micb_num == MIC_BIAS_2 && is_dapm)
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+ WCD_EVENT_POST_DAPM_MICBIAS_2_ON);
+
break;
case MICB_DISABLE:
@@ -2369,10 +2430,19 @@ static int wcd938x_micbias_control(struct snd_soc_component *component,
WCD938X_MICB_PULL_UP);
else if ((wcd938x->micb_ref[micb_index] == 0) &&
(wcd938x->pullup_ref[micb_index] == 0)) {
+ if (micb_num == MIC_BIAS_2)
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+ WCD_EVENT_PRE_MICBIAS_2_OFF);
snd_soc_component_write_field(component, micb_reg,
WCD938X_MICB_EN_MASK, 0);
+ if (micb_num == MIC_BIAS_2)
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+ WCD_EVENT_POST_MICBIAS_2_OFF);
}
+ if (is_dapm && micb_num == MIC_BIAS_2)
+ wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
+ WCD_EVENT_POST_DAPM_MICBIAS_2_OFF);
break;
}
@@ -2845,6 +2915,704 @@ static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol,
}
+/* MBHC related */
+static void wcd938x_mbhc_clk_setup(struct snd_soc_component *component,
+ bool enable)
+{
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_1,
+ WCD938X_MBHC_CTL_RCO_EN_MASK, enable);
+}
+
+static void wcd938x_mbhc_mbhc_bias_control(struct snd_soc_component *component,
+ bool enable)
+{
+ snd_soc_component_write_field(component, WCD938X_ANA_MBHC_ELECT,
+ WCD938X_ANA_MBHC_BIAS_EN, enable);
+}
+
+static void wcd938x_mbhc_program_btn_thr(struct snd_soc_component *component,
+ int *btn_low, int *btn_high,
+ int num_btn, bool is_micbias)
+{
+ int i, vth;
+
+ if (num_btn > WCD_MBHC_DEF_BUTTONS) {
+ dev_err(component->dev, "%s: invalid number of buttons: %d\n",
+ __func__, num_btn);
+ return;
+ }
+
+ for (i = 0; i < num_btn; i++) {
+ vth = ((btn_high[i] * 2) / 25) & 0x3F;
+ snd_soc_component_write_field(component, WCD938X_ANA_MBHC_BTN0 + i,
+ WCD938X_MBHC_BTN_VTH_MASK, vth);
+ dev_dbg(component->dev, "%s: btn_high[%d]: %d, vth: %d\n",
+ __func__, i, btn_high[i], vth);
+ }
+}
+
+static bool wcd938x_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num)
+{
+ u8 val;
+
+ if (micb_num == MIC_BIAS_2) {
+ val = snd_soc_component_read_field(component,
+ WCD938X_ANA_MICB2,
+ WCD938X_ANA_MICB2_ENABLE_MASK);
+ if (val == WCD938X_MICB_ENABLE)
+ return true;
+ }
+ return false;
+}
+
+static void wcd938x_mbhc_hph_l_pull_up_control(struct snd_soc_component *component,
+ int pull_up_cur)
+{
+ /* Default pull up current to 2uA */
+ if (pull_up_cur > HS_PULLUP_I_OFF || pull_up_cur < HS_PULLUP_I_3P0_UA)
+ pull_up_cur = HS_PULLUP_I_2P0_UA;
+
+ snd_soc_component_write_field(component,
+ WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT,
+ WCD938X_HSDET_PULLUP_C_MASK, pull_up_cur);
+}
+
+static int wcd938x_mbhc_request_micbias(struct snd_soc_component *component,
+ int micb_num, int req)
+{
+ return wcd938x_micbias_control(component, micb_num, req, false);
+}
+
+static void wcd938x_mbhc_micb_ramp_control(struct snd_soc_component *component,
+ bool enable)
+{
+ if (enable) {
+ snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
+ WCD938X_RAMP_SHIFT_CTRL_MASK, 0x0C);
+ snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
+ WCD938X_RAMP_EN_MASK, 1);
+ } else {
+ snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
+ WCD938X_RAMP_EN_MASK, 0);
+ snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
+ WCD938X_RAMP_SHIFT_CTRL_MASK, 0);
+ }
+}
+
+static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv)
+{
+ /* min micbias voltage is 1V and maximum is 2.85V */
+ if (micb_mv < 1000 || micb_mv > 2850)
+ return -EINVAL;
+
+ return (micb_mv - 1000) / 50;
+}
+
+static int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
+ int req_volt, int micb_num)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+ int cur_vout_ctl, req_vout_ctl, micb_reg, micb_en, ret = 0;
+
+ switch (micb_num) {
+ case MIC_BIAS_1:
+ micb_reg = WCD938X_ANA_MICB1;
+ break;
+ case MIC_BIAS_2:
+ micb_reg = WCD938X_ANA_MICB2;
+ break;
+ case MIC_BIAS_3:
+ micb_reg = WCD938X_ANA_MICB3;
+ break;
+ case MIC_BIAS_4:
+ micb_reg = WCD938X_ANA_MICB4;
+ break;
+ default:
+ return -EINVAL;
+ }
+ mutex_lock(&wcd938x->micb_lock);
+ /*
+ * If requested micbias voltage is same as current micbias
+ * voltage, then just return. Otherwise, adjust voltage as
+ * per requested value. If micbias is already enabled, then
+ * to avoid slow micbias ramp-up or down enable pull-up
+ * momentarily, change the micbias value and then re-enable
+ * micbias.
+ */
+ micb_en = snd_soc_component_read_field(component, micb_reg,
+ WCD938X_MICB_EN_MASK);
+ cur_vout_ctl = snd_soc_component_read_field(component, micb_reg,
+ WCD938X_MICB_VOUT_MASK);
+
+ req_vout_ctl = wcd938x_get_micb_vout_ctl_val(req_volt);
+ if (req_vout_ctl < 0) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (cur_vout_ctl == req_vout_ctl) {
+ ret = 0;
+ goto exit;
+ }
+
+ if (micb_en == WCD938X_MICB_ENABLE)
+ snd_soc_component_write_field(component, micb_reg,
+ WCD938X_MICB_EN_MASK,
+ WCD938X_MICB_PULL_UP);
+
+ snd_soc_component_write_field(component, micb_reg,
+ WCD938X_MICB_VOUT_MASK,
+ req_vout_ctl);
+
+ if (micb_en == WCD938X_MICB_ENABLE) {
+ snd_soc_component_write_field(component, micb_reg,
+ WCD938X_MICB_EN_MASK,
+ WCD938X_MICB_ENABLE);
+ /*
+ * Add 2ms delay as per HW requirement after enabling
+ * micbias
+ */
+ usleep_range(2000, 2100);
+ }
+exit:
+ mutex_unlock(&wcd938x->micb_lock);
+ return ret;
+}
+
+static int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *component,
+ int micb_num, bool req_en)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+ int rc, micb_mv;
+
+ if (micb_num != MIC_BIAS_2)
+ return -EINVAL;
+ /*
+ * If device tree micbias level is already above the minimum
+ * voltage needed to detect threshold microphone, then do
+ * not change the micbias, just return.
+ */
+ if (wcd938x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV)
+ return 0;
+
+ micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd938x->micb2_mv;
+
+ rc = wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);
+
+ return rc;
+}
+
+static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
+ s16 *d1_a, u16 noff,
+ int32_t *zdet)
+{
+ int i;
+ int val, val1;
+ s16 c1;
+ s32 x1, d1;
+ int32_t denom;
+ int minCode_param[] = {
+ 3277, 1639, 820, 410, 205, 103, 52, 26
+ };
+
+ regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x20);
+ for (i = 0; i < WCD938X_ZDET_NUM_MEASUREMENTS; i++) {
+ regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_2, &val);
+ if (val & 0x80)
+ break;
+ }
+ val = val << 0x8;
+ regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_1, &val1);
+ val |= val1;
+ regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x00);
+ x1 = WCD938X_MBHC_GET_X1(val);
+ c1 = WCD938X_MBHC_GET_C1(val);
+ /* If ramp is not complete, give additional 5ms */
+ if ((c1 < 2) && x1)
+ usleep_range(5000, 5050);
+
+ if (!c1 || !x1) {
+ pr_err("%s: Impedance detect ramp error, c1=%d, x1=0x%x\n",
+ __func__, c1, x1);
+ goto ramp_down;
+ }
+ d1 = d1_a[c1];
+ denom = (x1 * d1) - (1 << (14 - noff));
+ if (denom > 0)
+ *zdet = (WCD938X_MBHC_ZDET_CONST * 1000) / denom;
+ else if (x1 < minCode_param[noff])
+ *zdet = WCD938X_ZDET_FLOATING_IMPEDANCE;
+
+ pr_err("%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n",
+ __func__, d1, c1, x1, *zdet);
+ramp_down:
+ i = 0;
+ while (x1) {
+ regmap_read(wcd938x->regmap,
+ WCD938X_ANA_MBHC_RESULT_1, &val);
+ regmap_read(wcd938x->regmap,
+ WCD938X_ANA_MBHC_RESULT_2, &val1);
+ val = val << 0x08;
+ val |= val1;
+ x1 = WCD938X_MBHC_GET_X1(val);
+ i++;
+ if (i == WCD938X_ZDET_NUM_MEASUREMENTS)
+ break;
+ }
+}
+
+static void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component,
+ struct wcd938x_mbhc_zdet_param *zdet_param,
+ int32_t *zl, int32_t *zr, s16 *d1_a)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+ int32_t zdet = 0;
+
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,
+ WCD938X_ZDET_MAXV_CTL_MASK, zdet_param->ldo_ctl);
+ snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN5,
+ WCD938X_VTH_MASK, zdet_param->btn5);
+ snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN6,
+ WCD938X_VTH_MASK, zdet_param->btn6);
+ snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN7,
+ WCD938X_VTH_MASK, zdet_param->btn7);
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,
+ WCD938X_ZDET_RANGE_CTL_MASK, zdet_param->noff);
+ snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_RAMP_CTL,
+ 0x0F, zdet_param->nshift);
+
+ if (!zl)
+ goto z_right;
+ /* Start impedance measurement for HPH_L */
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_ZDET, 0x80, 0x80);
+ dev_dbg(component->dev, "%s: ramp for HPH_L, noff = %d\n",
+ __func__, zdet_param->noff);
+ wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_ZDET, 0x80, 0x00);
+
+ *zl = zdet;
+
+z_right:
+ if (!zr)
+ return;
+ /* Start impedance measurement for HPH_R */
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_ZDET, 0x40, 0x40);
+ dev_dbg(component->dev, "%s: ramp for HPH_R, noff = %d\n",
+ __func__, zdet_param->noff);
+ wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_ZDET, 0x40, 0x00);
+
+ *zr = zdet;
+}
+
+static inline void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
+ int32_t *z_val, int flag_l_r)
+{
+ s16 q1;
+ int q1_cal;
+
+ if (*z_val < (WCD938X_ZDET_VAL_400/1000))
+ q1 = snd_soc_component_read(component,
+ WCD938X_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r));
+ else
+ q1 = snd_soc_component_read(component,
+ WCD938X_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r));
+ if (q1 & 0x80)
+ q1_cal = (10000 - ((q1 & 0x7F) * 25));
+ else
+ q1_cal = (10000 + (q1 * 25));
+ if (q1_cal > 0)
+ *z_val = ((*z_val) * 10000) / q1_cal;
+}
+
+static void wcd938x_wcd_mbhc_calc_impedance(struct snd_soc_component *component,
+ uint32_t *zl, uint32_t *zr)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+ s16 reg0, reg1, reg2, reg3, reg4;
+ int32_t z1L, z1R, z1Ls;
+ int zMono, z_diff1, z_diff2;
+ bool is_fsm_disable = false;
+ struct wcd938x_mbhc_zdet_param zdet_param[] = {
+ {4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */
+ {2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */
+ {1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */
+ {1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */
+ };
+ struct wcd938x_mbhc_zdet_param *zdet_param_ptr = NULL;
+ s16 d1_a[][4] = {
+ {0, 30, 90, 30},
+ {0, 30, 30, 5},
+ {0, 30, 30, 5},
+ {0, 30, 30, 5},
+ };
+ s16 *d1 = NULL;
+
+ reg0 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN5);
+ reg1 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN6);
+ reg2 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN7);
+ reg3 = snd_soc_component_read(component, WCD938X_MBHC_CTL_CLK);
+ reg4 = snd_soc_component_read(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL);
+
+ if (snd_soc_component_read(component, WCD938X_ANA_MBHC_ELECT) & 0x80) {
+ is_fsm_disable = true;
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_ELECT, 0x80, 0x00);
+ }
+
+ /* For NO-jack, disable L_DET_EN before Z-det measurements */
+ if (wcd938x->mbhc_cfg.hphl_swh)
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_MECH, 0x80, 0x00);
+
+ /* Turn off 100k pull down on HPHL */
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_MECH, 0x01, 0x00);
+
+ /* Disable surge protection before impedance detection.
+ * This is done to give correct value for high impedance.
+ */
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00);
+ /* 1ms delay needed after disable surge protection */
+ usleep_range(1000, 1010);
+
+ /* First get impedance on Left */
+ d1 = d1_a[1];
+ zdet_param_ptr = &zdet_param[1];
+ wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
+
+ if (!WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1L))
+ goto left_ch_impedance;
+
+ /* Second ramp for left ch */
+ if (z1L < WCD938X_ZDET_VAL_32) {
+ zdet_param_ptr = &zdet_param[0];
+ d1 = d1_a[0];
+ } else if ((z1L > WCD938X_ZDET_VAL_400) &&
+ (z1L <= WCD938X_ZDET_VAL_1200)) {
+ zdet_param_ptr = &zdet_param[2];
+ d1 = d1_a[2];
+ } else if (z1L > WCD938X_ZDET_VAL_1200) {
+ zdet_param_ptr = &zdet_param[3];
+ d1 = d1_a[3];
+ }
+ wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
+
+left_ch_impedance:
+ if ((z1L == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+ (z1L > WCD938X_ZDET_VAL_100K)) {
+ *zl = WCD938X_ZDET_FLOATING_IMPEDANCE;
+ zdet_param_ptr = &zdet_param[1];
+ d1 = d1_a[1];
+ } else {
+ *zl = z1L/1000;
+ wcd938x_wcd_mbhc_qfuse_cal(component, zl, 0);
+ }
+ dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",
+ __func__, *zl);
+
+ /* Start of right impedance ramp and calculation */
+ wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
+ if (WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) {
+ if (((z1R > WCD938X_ZDET_VAL_1200) &&
+ (zdet_param_ptr->noff == 0x6)) ||
+ ((*zl) != WCD938X_ZDET_FLOATING_IMPEDANCE))
+ goto right_ch_impedance;
+ /* Second ramp for right ch */
+ if (z1R < WCD938X_ZDET_VAL_32) {
+ zdet_param_ptr = &zdet_param[0];
+ d1 = d1_a[0];
+ } else if ((z1R > WCD938X_ZDET_VAL_400) &&
+ (z1R <= WCD938X_ZDET_VAL_1200)) {
+ zdet_param_ptr = &zdet_param[2];
+ d1 = d1_a[2];
+ } else if (z1R > WCD938X_ZDET_VAL_1200) {
+ zdet_param_ptr = &zdet_param[3];
+ d1 = d1_a[3];
+ }
+ wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
+ }
+right_ch_impedance:
+ if ((z1R == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+ (z1R > WCD938X_ZDET_VAL_100K)) {
+ *zr = WCD938X_ZDET_FLOATING_IMPEDANCE;
+ } else {
+ *zr = z1R/1000;
+ wcd938x_wcd_mbhc_qfuse_cal(component, zr, 1);
+ }
+ dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",
+ __func__, *zr);
+
+ /* Mono/stereo detection */
+ if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) &&
+ (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE)) {
+ dev_dbg(component->dev,
+ "%s: plug type is invalid or extension cable\n",
+ __func__);
+ goto zdet_complete;
+ }
+ if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+ (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
+ ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) ||
+ ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) {
+ dev_dbg(component->dev,
+ "%s: Mono plug type with one ch floating or shorted to GND\n",
+ __func__);
+ wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO);
+ goto zdet_complete;
+ }
+ snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST,
+ WCD938X_HPHPA_GND_OVR_MASK, 1);
+ snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
+ WCD938X_HPHPA_GND_R_MASK, 1);
+ if (*zl < (WCD938X_ZDET_VAL_32/1000))
+ wcd938x_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, NULL, d1);
+ else
+ wcd938x_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, NULL, d1);
+ snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
+ WCD938X_HPHPA_GND_R_MASK, 0);
+ snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST,
+ WCD938X_HPHPA_GND_OVR_MASK, 0);
+ z1Ls /= 1000;
+ wcd938x_wcd_mbhc_qfuse_cal(component, &z1Ls, 0);
+ /* Parallel of left Z and 9 ohm pull down resistor */
+ zMono = ((*zl) * 9) / ((*zl) + 9);
+ z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls);
+ z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl));
+ if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) {
+ dev_dbg(component->dev, "%s: stereo plug type detected\n",
+ __func__);
+ wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_STEREO);
+ } else {
+ dev_dbg(component->dev, "%s: MONO plug type detected\n",
+ __func__);
+ wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO);
+ }
+
+ /* Enable surge protection again after impedance detection */
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0);
+zdet_complete:
+ snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN5, reg0);
+ snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN6, reg1);
+ snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN7, reg2);
+ /* Turn on 100k pull down on HPHL */
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_MECH, 0x01, 0x01);
+
+ /* For NO-jack, re-enable L_DET_EN after Z-det measurements */
+ if (wcd938x->mbhc_cfg.hphl_swh)
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_MECH, 0x80, 0x80);
+
+ snd_soc_component_write(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, reg4);
+ snd_soc_component_write(component, WCD938X_MBHC_CTL_CLK, reg3);
+ if (is_fsm_disable)
+ regmap_update_bits(wcd938x->regmap,
+ WCD938X_ANA_MBHC_ELECT, 0x80, 0x80);
+}
+
+static void wcd938x_mbhc_gnd_det_ctrl(struct snd_soc_component *component,
+ bool enable)
+{
+ if (enable) {
+ snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
+ WCD938X_MBHC_HSG_PULLUP_COMP_EN, 1);
+ snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
+ WCD938X_MBHC_GND_DET_EN_MASK, 1);
+ } else {
+ snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
+ WCD938X_MBHC_GND_DET_EN_MASK, 0);
+ snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
+ WCD938X_MBHC_HSG_PULLUP_COMP_EN, 0);
+ }
+}
+
+static void wcd938x_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component,
+ bool enable)
+{
+ snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
+ WCD938X_HPHPA_GND_R_MASK, enable);
+ snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
+ WCD938X_HPHPA_GND_L_MASK, enable);
+}
+
+static void wcd938x_mbhc_moisture_config(struct snd_soc_component *component)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+ if (wcd938x->mbhc_cfg.moist_rref == R_OFF) {
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+ WCD938X_M_RTH_CTL_MASK, R_OFF);
+ return;
+ }
+
+ /* Do not enable moisture detection if jack type is NC */
+ if (!wcd938x->mbhc_cfg.hphl_swh) {
+ dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
+ __func__);
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+ WCD938X_M_RTH_CTL_MASK, R_OFF);
+ return;
+ }
+
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+ WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref);
+}
+
+static void wcd938x_mbhc_moisture_detect_en(struct snd_soc_component *component, bool enable)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+ if (enable)
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+ WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref);
+ else
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+ WCD938X_M_RTH_CTL_MASK, R_OFF);
+}
+
+static bool wcd938x_mbhc_get_moisture_status(struct snd_soc_component *component)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+ bool ret = false;
+
+ if (wcd938x->mbhc_cfg.moist_rref == R_OFF) {
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+ WCD938X_M_RTH_CTL_MASK, R_OFF);
+ goto done;
+ }
+
+ /* Do not enable moisture detection if jack type is NC */
+ if (!wcd938x->mbhc_cfg.hphl_swh) {
+ dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
+ __func__);
+ snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
+ WCD938X_M_RTH_CTL_MASK, R_OFF);
+ goto done;
+ }
+
+ /*
+ * If moisture_en is already enabled, then skip to plug type
+ * detection.
+ */
+ if (snd_soc_component_read_field(component, WCD938X_MBHC_NEW_CTL_2, WCD938X_M_RTH_CTL_MASK))
+ goto done;
+
+ wcd938x_mbhc_moisture_detect_en(component, true);
+ /* Read moisture comparator status */
+ ret = ((snd_soc_component_read(component, WCD938X_MBHC_NEW_FSM_STATUS)
+ & 0x20) ? 0 : 1);
+
+done:
+ return ret;
+
+}
+
+static void wcd938x_mbhc_moisture_polling_ctrl(struct snd_soc_component *component,
+ bool enable)
+{
+ snd_soc_component_write_field(component,
+ WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,
+ WCD938X_MOISTURE_EN_POLLING_MASK, enable);
+}
+
+static const struct wcd_mbhc_cb mbhc_cb = {
+ .clk_setup = wcd938x_mbhc_clk_setup,
+ .mbhc_bias = wcd938x_mbhc_mbhc_bias_control,
+ .set_btn_thr = wcd938x_mbhc_program_btn_thr,
+ .micbias_enable_status = wcd938x_mbhc_micb_en_status,
+ .hph_pull_up_control_v2 = wcd938x_mbhc_hph_l_pull_up_control,
+ .mbhc_micbias_control = wcd938x_mbhc_request_micbias,
+ .mbhc_micb_ramp_control = wcd938x_mbhc_micb_ramp_control,
+ .mbhc_micb_ctrl_thr_mic = wcd938x_mbhc_micb_ctrl_threshold_mic,
+ .compute_impedance = wcd938x_wcd_mbhc_calc_impedance,
+ .mbhc_gnd_det_ctrl = wcd938x_mbhc_gnd_det_ctrl,
+ .hph_pull_down_ctrl = wcd938x_mbhc_hph_pull_down_ctrl,
+ .mbhc_moisture_config = wcd938x_mbhc_moisture_config,
+ .mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status,
+ .mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl,
+ .mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en,
+};
+
+static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = wcd_mbhc_get_hph_type(wcd938x->wcd_mbhc);
+
+ return 0;
+}
+
+static int wcd938x_hph_impedance_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ uint32_t zl, zr;
+ bool hphr;
+ struct soc_mixer_control *mc;
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+ mc = (struct soc_mixer_control *)(kcontrol->private_value);
+ hphr = mc->shift;
+ wcd_mbhc_get_impedance(wcd938x->wcd_mbhc, &zl, &zr);
+ dev_dbg(component->dev, "%s: zl=%u(ohms), zr=%u(ohms)\n", __func__, zl, zr);
+ ucontrol->value.integer.value[0] = hphr ? zr : zl;
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new hph_type_detect_controls[] = {
+ SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
+ wcd938x_get_hph_type, NULL),
+};
+
+static const struct snd_kcontrol_new impedance_detect_controls[] = {
+ SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+ wcd938x_hph_impedance_get, NULL),
+ SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+ wcd938x_hph_impedance_get, NULL),
+};
+
+static int wcd938x_mbhc_init(struct snd_soc_component *component)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+ struct wcd_mbhc_intr *intr_ids = &wcd938x->intr_ids;
+
+ intr_ids->mbhc_sw_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+ WCD938X_IRQ_MBHC_SW_DET);
+ intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+ WCD938X_IRQ_MBHC_BUTTON_PRESS_DET);
+ intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+ WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET);
+ intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+ WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET);
+ intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(wcd938x->irq_chip,
+ WCD938X_IRQ_MBHC_ELECT_INS_REM_DET);
+ intr_ids->hph_left_ocp = regmap_irq_get_virq(wcd938x->irq_chip,
+ WCD938X_IRQ_HPHL_OCP_INT);
+ intr_ids->hph_right_ocp = regmap_irq_get_virq(wcd938x->irq_chip,
+ WCD938X_IRQ_HPHR_OCP_INT);
+
+ wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true);
+
+ snd_soc_add_component_controls(component, impedance_detect_controls,
+ ARRAY_SIZE(impedance_detect_controls));
+ snd_soc_add_component_controls(component, hph_type_detect_controls,
+ ARRAY_SIZE(hph_type_detect_controls));
+
+ return 0;
+}
+/* END MBHC */
+
static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
SOC_SINGLE_EXT("HPHL_COMP Switch", WCD938X_COMP_L, 0, 1, 0,
wcd938x_get_compander, wcd938x_set_compander),
@@ -3225,15 +3993,6 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
{"EAR", NULL, "EAR PGA"},
};
-static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv)
-{
- /* min micbias voltage is 1V and maximum is 2.85V */
- if (micb_mv < 1000 || micb_mv > 2850)
- return -EINVAL;
-
- return (micb_mv - 1000) / 50;
-}
-
static int wcd938x_set_micbias_data(struct wcd938x_priv *wcd938x)
{
int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;
@@ -3372,10 +4131,27 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
default:
break;
}
+
+ ret = wcd938x_mbhc_init(component);
+ if (ret)
+ dev_err(component->dev, "mbhc initialization failed\n");
err:
return ret;
}
+static int wcd938x_codec_set_jack(struct snd_soc_component *comp,
+ struct snd_soc_jack *jack, void *data)
+{
+ struct wcd938x_priv *wcd = dev_get_drvdata(comp->dev);
+
+ if (!jack)
+ return wcd_mbhc_start(wcd->wcd_mbhc, &wcd->mbhc_cfg, jack);
+
+ wcd_mbhc_stop(wcd->wcd_mbhc);
+
+ return 0;
+}
+
static const struct snd_soc_component_driver soc_codec_dev_wcd938x = {
.name = "wcd938x_codec",
.probe = wcd938x_soc_codec_probe,
@@ -3385,6 +4161,7 @@ static const struct snd_soc_component_driver soc_codec_dev_wcd938x = {
.num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets),
.dapm_routes = wcd938x_audio_map,
.num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map),
+ .set_jack = wcd938x_codec_set_jack,
};
static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_priv *wcd)
@@ -3420,6 +4197,7 @@ static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_pri
static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device *dev)
{
+ struct wcd_mbhc_config *cfg = &wcd938x->mbhc_cfg;
int ret;
wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0);
@@ -3448,6 +4226,17 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device
wcd938x_dt_parse_micbias_info(dev, wcd938x);
+ cfg->mbhc_micbias = MIC_BIAS_2;
+ cfg->anc_micbias = MIC_BIAS_2;
+ cfg->v_hs_max = WCD_MBHC_HS_V_MAX;
+ cfg->num_btn = WCD938X_MBHC_MAX_BUTTONS;
+ cfg->micb_mv = wcd938x->micb2_mv;
+ cfg->linein_th = 5000;
+ cfg->hs_thr = 1700;
+ cfg->hph_thr = 50;
+
+ wcd_dt_parse_mbhc_data(dev, cfg);
+
return 0;
}
@@ -3679,6 +4468,7 @@ static int wcd938x_probe(struct platform_device *pdev)
return -ENOMEM;
dev_set_drvdata(dev, wcd938x);
+ mutex_init(&wcd938x->micb_lock);
ret = wcd938x_populate_dt_data(wcd938x, dev);
if (ret) {
@@ -3703,7 +4493,7 @@ static int wcd938x_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
pm_runtime_idle(dev);
- return ret;
+ return 0;
}
static int wcd938x_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/wcd938x.h b/sound/soc/codecs/wcd938x.h
index 07b08de4cebf..ea82039e7843 100644
--- a/sound/soc/codecs/wcd938x.h
+++ b/sound/soc/codecs/wcd938x.h
@@ -658,7 +658,6 @@ struct wcd938x_sdw_priv {
struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
struct wcd938x_sdw_ch_info *ch_info;
bool port_enable[WCD938X_MAX_SWR_CH_IDS];
- int port_map[WCD938X_MAX_SWR_PORTS];
int active_ports;
int num_ports;
bool is_tx;
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index fe15cbc7bcaf..f7c800927cb2 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -747,6 +747,8 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
{
wm_adsp_debugfs_clear(dsp);
+ debugfs_remove_recursive(dsp->debugfs_root);
+ dsp->debugfs_root = NULL;
}
#else
static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
@@ -2029,10 +2031,9 @@ static struct wm_coeff_ctl *wm_adsp_get_ctl(struct wm_adsp *dsp,
if (!pos->subname)
continue;
if (strncmp(pos->subname, name, pos->subname_len) == 0 &&
- strncmp(pos->fw_name, fw_txt,
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0 &&
- pos->alg_region.alg == alg &&
- pos->alg_region.type == type) {
+ pos->fw_name == fw_txt &&
+ pos->alg_region.alg == alg &&
+ pos->alg_region.type == type) {
rslt = pos;
break;
}
diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c
index 8ebf76e04702..33ce257ae198 100644
--- a/sound/soc/dwc/dwc-i2s.c
+++ b/sound/soc/dwc/dwc-i2s.c
@@ -642,7 +642,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
dev->dev = &pdev->dev;
- irq = platform_get_irq(pdev, 0);
+ irq = platform_get_irq_optional(pdev, 0);
if (irq >= 0) {
ret = devm_request_irq(&pdev->dev, irq, i2s_irq_handler, 0,
pdev->name, dev);
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index c313a26c8f95..cd9b36ec0ecb 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -284,8 +284,6 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
return ret;
}
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
return 0;
}
@@ -297,8 +295,6 @@ static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
struct fsl_asrc_pair *pair = runtime->private_data;
u8 dir = tx ? OUT : IN;
- snd_pcm_set_runtime_buffer(substream, NULL);
-
if (pair->dma_chan[!dir])
dma_release_channel(pair->dma_chan[!dir]);
@@ -423,9 +419,8 @@ static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm_substream *substream;
struct snd_pcm *pcm = rtd->pcm;
- int ret, i;
+ int ret;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret) {
@@ -433,43 +428,8 @@ static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
return ret;
}
- for_each_pcm_streams(i) {
- substream = pcm->streams[i].substream;
- if (!substream)
- continue;
-
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- FSL_ASRC_DMABUF_SIZE, &substream->dma_buffer);
- if (ret) {
- dev_err(card->dev, "failed to allocate DMA buffer\n");
- goto err;
- }
- }
-
- return 0;
-
-err:
- if (--i == 0 && pcm->streams[i].substream)
- snd_dma_free_pages(&pcm->streams[i].substream->dma_buffer);
-
- return ret;
-}
-
-static void fsl_asrc_dma_pcm_free(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- int i;
-
- for_each_pcm_streams(i) {
- substream = pcm->streams[i].substream;
- if (!substream)
- continue;
-
- snd_dma_free_pages(&substream->dma_buffer);
- substream->dma_buffer.area = NULL;
- substream->dma_buffer.addr = 0;
- }
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+ card->dev, FSL_ASRC_DMABUF_SIZE);
}
struct snd_soc_component_driver fsl_asrc_component = {
@@ -481,6 +441,5 @@ struct snd_soc_component_driver fsl_asrc_component = {
.close = fsl_asrc_dma_shutdown,
.pointer = fsl_asrc_dma_pcm_pointer,
.pcm_construct = fsl_asrc_dma_pcm_new,
- .pcm_destruct = fsl_asrc_dma_pcm_free,
};
EXPORT_SYMBOL_GPL(fsl_asrc_component);
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 84bd8a5356eb..808fb61a7a0f 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -290,32 +290,9 @@ static int fsl_dma_new(struct snd_soc_component *component,
if (ret)
return ret;
- /* Some codecs have separate DAIs for playback and capture, so we
- * should allocate a DMA buffer only for the streams that are valid.
- */
-
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
- fsl_dma_hardware.buffer_bytes_max,
- &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
- if (ret) {
- dev_err(card->dev, "can't alloc playback dma buffer\n");
- return ret;
- }
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
- fsl_dma_hardware.buffer_bytes_max,
- &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
- if (ret) {
- dev_err(card->dev, "can't alloc capture dma buffer\n");
- snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
- return ret;
- }
- }
-
- return 0;
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+ card->dev,
+ fsl_dma_hardware.buffer_bytes_max);
}
/**
@@ -442,7 +419,6 @@ static int fsl_dma_open(struct snd_soc_component *component,
dma->assigned = true;
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware);
runtime->private_data = dma_private;
@@ -815,25 +791,6 @@ static int fsl_dma_close(struct snd_soc_component *component,
return 0;
}
-/*
- * Remove this PCM driver.
- */
-static void fsl_dma_free_dma_buffers(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
- substream = pcm->streams[i].substream;
- if (substream) {
- snd_dma_free_pages(&substream->dma_buffer);
- substream->dma_buffer.area = NULL;
- substream->dma_buffer.addr = 0;
- }
- }
-}
-
/**
* find_ssi_node -- returns the SSI node that points to its DMA channel node
*
@@ -904,7 +861,6 @@ static int fsl_soc_dma_probe(struct platform_device *pdev)
dma->dai.hw_free = fsl_dma_hw_free;
dma->dai.pointer = fsl_dma_pointer;
dma->dai.pcm_construct = fsl_dma_new;
- dma->dai.pcm_destruct = fsl_dma_free_dma_buffers;
/* Store the SSI-specific information that we need */
dma->ssi_stx_phys = res.start + REG_SSI_STX0;
diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c
index ea5c973e2e84..d60f4dac6c1b 100644
--- a/sound/soc/fsl/fsl_rpmsg.c
+++ b/sound/soc/fsl/fsl_rpmsg.c
@@ -165,25 +165,25 @@ static int fsl_rpmsg_probe(struct platform_device *pdev)
}
/* Get the optional clocks */
- rpmsg->ipg = devm_clk_get(&pdev->dev, "ipg");
+ rpmsg->ipg = devm_clk_get_optional(&pdev->dev, "ipg");
if (IS_ERR(rpmsg->ipg))
- rpmsg->ipg = NULL;
+ return PTR_ERR(rpmsg->ipg);
- rpmsg->mclk = devm_clk_get(&pdev->dev, "mclk");
+ rpmsg->mclk = devm_clk_get_optional(&pdev->dev, "mclk");
if (IS_ERR(rpmsg->mclk))
- rpmsg->mclk = NULL;
+ return PTR_ERR(rpmsg->mclk);
- rpmsg->dma = devm_clk_get(&pdev->dev, "dma");
+ rpmsg->dma = devm_clk_get_optional(&pdev->dev, "dma");
if (IS_ERR(rpmsg->dma))
- rpmsg->dma = NULL;
+ return PTR_ERR(rpmsg->dma);
- rpmsg->pll8k = devm_clk_get(&pdev->dev, "pll8k");
+ rpmsg->pll8k = devm_clk_get_optional(&pdev->dev, "pll8k");
if (IS_ERR(rpmsg->pll8k))
- rpmsg->pll8k = NULL;
+ return PTR_ERR(rpmsg->pll8k);
- rpmsg->pll11k = devm_clk_get(&pdev->dev, "pll11k");
+ rpmsg->pll11k = devm_clk_get_optional(&pdev->dev, "pll11k");
if (IS_ERR(rpmsg->pll11k))
- rpmsg->pll11k = NULL;
+ return PTR_ERR(rpmsg->pll11k);
platform_set_drvdata(pdev, rpmsg);
pm_runtime_enable(&pdev->dev);
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index fb7c29fc39d7..31c5ee641fe7 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -1189,10 +1189,8 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
/* get IRQs */
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "no irq[0]: %d\n", irq);
+ if (irq < 0)
return irq;
- }
ret = devm_request_irq(dev, irq, irq0_isr, 0, pdev->name, xcvr);
if (ret) {
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index f20d5b1c3848..0d124002678e 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -81,7 +81,6 @@ static int snd_imx_pcm_hw_params(struct snd_soc_component *component,
iprtd->offset = 0;
iprtd->poll_time_ns = 1000000000 / params_rate(params) *
params_period_size(params);
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
return 0;
}
@@ -213,40 +212,6 @@ static int snd_imx_close(struct snd_soc_component *component,
return 0;
}
-static int snd_imx_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int ret;
-
- ret = dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
- runtime->dma_addr, runtime->dma_bytes);
-
- pr_debug("%s: ret: %d %p %pad 0x%08zx\n", __func__, ret,
- runtime->dma_area,
- &runtime->dma_addr,
- runtime->dma_bytes);
- return ret;
-}
-
-static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = IMX_SSI_DMABUF_SIZE;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
- buf->bytes = size;
-
- return 0;
-}
-
static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
@@ -257,21 +222,9 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (ret)
return ret;
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = imx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- return ret;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = imx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- return ret;
- }
-
- return 0;
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+ pcm->card->dev,
+ IMX_SSI_DMABUF_SIZE);
}
static int ssi_irq;
@@ -307,32 +260,11 @@ static int snd_imx_pcm_new(struct snd_soc_component *component,
return 0;
}
-static void imx_pcm_free(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
static void snd_imx_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
mxc_set_irq_fiq(ssi_irq, 0);
release_fiq(&fh);
- imx_pcm_free(pcm);
}
static const struct snd_soc_component_driver imx_soc_component_fiq = {
@@ -342,7 +274,6 @@ static const struct snd_soc_component_driver imx_soc_component_fiq = {
.prepare = snd_imx_pcm_prepare,
.trigger = snd_imx_pcm_trigger,
.pointer = snd_imx_pcm_pointer,
- .mmap = snd_imx_pcm_mmap,
.pcm_construct = snd_imx_pcm_new,
.pcm_destruct = snd_imx_pcm_free,
};
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
index 6d6c44cf3451..35049043e532 100644
--- a/sound/soc/fsl/imx-pcm-rpmsg.c
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -139,7 +139,6 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_hw_params *params)
{
struct rpmsg_info *info = dev_get_drvdata(component->dev);
- struct snd_pcm_runtime *runtime = substream->runtime;
struct rpmsg_msg *msg;
int ret = 0;
@@ -183,21 +182,11 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
break;
}
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
info->send_message(msg, info);
return ret;
}
-static int imx_rpmsg_pcm_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- snd_pcm_set_runtime_buffer(substream, NULL);
- return 0;
-}
-
static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -347,18 +336,6 @@ static int imx_rpmsg_pcm_prepare(struct snd_soc_component *component,
return 0;
}
-static int imx_rpmsg_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- return dma_mmap_wc(substream->pcm->card->dev, vma,
- runtime->dma_area,
- runtime->dma_addr,
- runtime->dma_bytes);
-}
-
static void imx_rpmsg_pcm_dma_complete(void *arg)
{
struct snd_pcm_substream *substream = arg;
@@ -609,47 +586,6 @@ static int imx_rpmsg_pcm_ack(struct snd_soc_component *component,
return 0;
}
-static int imx_rpmsg_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
- int stream, int size)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_wc(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
-
- buf->bytes = size;
- return 0;
-}
-
-static void imx_rpmsg_pcm_free_dma_buffers(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = SNDRV_PCM_STREAM_PLAYBACK;
- stream < SNDRV_PCM_STREAM_LAST; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_wc(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
static int imx_rpmsg_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
@@ -663,40 +599,19 @@ static int imx_rpmsg_pcm_new(struct snd_soc_component *component,
if (ret)
return ret;
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- rpmsg->buffer_size);
- if (ret)
- goto out;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE,
- rpmsg->buffer_size);
- if (ret)
- goto out;
- }
-
imx_rpmsg_pcm_hardware.buffer_bytes_max = rpmsg->buffer_size;
-out:
- /* free preallocated buffers in case of error */
- if (ret)
- imx_rpmsg_pcm_free_dma_buffers(component, pcm);
-
- return ret;
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
+ pcm->card->dev, rpmsg->buffer_size);
}
static const struct snd_soc_component_driver imx_rpmsg_soc_component = {
.name = IMX_PCM_DRV_NAME,
.pcm_construct = imx_rpmsg_pcm_new,
- .pcm_destruct = imx_rpmsg_pcm_free_dma_buffers,
.open = imx_rpmsg_pcm_open,
.close = imx_rpmsg_pcm_close,
.hw_params = imx_rpmsg_pcm_hw_params,
- .hw_free = imx_rpmsg_pcm_hw_free,
.trigger = imx_rpmsg_pcm_trigger,
.pointer = imx_rpmsg_pcm_pointer,
- .mmap = imx_rpmsg_pcm_mmap,
.ack = imx_rpmsg_pcm_ack,
.prepare = imx_rpmsg_pcm_prepare,
};
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
index f0cae8c59d54..f96fe4ff8425 100644
--- a/sound/soc/fsl/imx-rpmsg.c
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -125,7 +125,7 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(&data->card, data);
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
goto fail;
}
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 6c65cd858b0b..901497810020 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -98,13 +98,6 @@ static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
return IRQ_HANDLED;
}
-static int psc_dma_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- snd_pcm_set_runtime_buffer(substream, NULL);
- return 0;
-}
-
/**
* psc_dma_trigger: start and stop the DMA transfer.
*
@@ -285,15 +278,6 @@ psc_dma_pointer(struct snd_soc_component *component,
return bytes_to_frames(substream->runtime, count);
}
-static int psc_dma_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
- return 0;
-}
-
static int psc_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
@@ -310,60 +294,17 @@ static int psc_dma_new(struct snd_soc_component *component,
if (rc)
return rc;
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
- if (rc)
- goto playback_alloc_err;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
- if (rc)
- goto capture_alloc_err;
- }
-
- return 0;
-
- capture_alloc_err:
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
- snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
-
- playback_alloc_err:
- dev_err(card->dev, "Cannot allocate buffer(s)\n");
-
- return -ENOMEM;
-}
-
-static void psc_dma_free(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- int stream;
-
- dev_dbg(component->dev, "psc_dma_free(pcm=%p)\n", pcm);
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (substream) {
- snd_dma_free_pages(&substream->dma_buffer);
- substream->dma_buffer.area = NULL;
- substream->dma_buffer.addr = 0;
- }
- }
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev,
+ size);
}
static const struct snd_soc_component_driver mpc5200_audio_dma_component = {
.name = DRV_NAME,
.open = psc_dma_open,
.close = psc_dma_close,
- .hw_free = psc_dma_hw_free,
.pointer = psc_dma_pointer,
.trigger = psc_dma_trigger,
- .hw_params = psc_dma_hw_params,
.pcm_construct = psc_dma_new,
- .pcm_destruct = psc_dma_free,
};
int mpc5200_audio_dma_create(struct platform_device *op)
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 677f7da93b4b..10c63b73900c 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -640,8 +640,8 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
cnf_num += li->num[i].codecs;
}
- dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL);
- dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dai_props), GFP_KERNEL);
+ dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL);
+ dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dlcs), GFP_KERNEL);
if (!dais || !dlcs)
return -ENOMEM;
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 905c7965f653..5db2f4865bbb 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -127,7 +127,7 @@ static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
snd_pcm_uframes_t period_size;
ssize_t periodbytes;
ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
- u32 buffer_addr = virt_to_phys(substream->runtime->dma_area);
+ u32 buffer_addr = substream->runtime->dma_addr;
channels = substream->runtime->channels;
period_size = substream->runtime->period_size;
diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c
index a8a9aa0057d3..4e8382097e61 100644
--- a/sound/soc/intel/atom/sst/sst_ipc.c
+++ b/sound/soc/intel/atom/sst/sst_ipc.c
@@ -128,7 +128,7 @@ int sst_post_message_mrfld(struct intel_sst_drv *sst_drv_ctx,
while (header.p.header_high.part.busy) {
if (loop_count > 25) {
dev_err(sst_drv_ctx->dev,
- "sst: Busy wait failed, cant send this msg\n");
+ "sst: Busy wait failed, can't send this msg\n");
retval = -EBUSY;
goto out;
}
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 7e29b0d911e2..046955bf717c 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -602,6 +602,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
select SND_SOC_DMIC
select SND_SOC_INTEL_HDA_DSP_COMMON
select SND_SOC_INTEL_SOF_MAXIM_COMMON
+ select SND_SOC_SDW_MOCKUP
help
Add support for Intel SoundWire-based platforms connected to
MAX98373, RT700, RT711, RT1308 and RT715
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index a0af91580184..055248f104b2 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -37,6 +37,7 @@ struct byt_cht_es8316_private {
struct clk *mclk;
struct snd_soc_jack jack;
struct gpio_desc *speaker_en_gpio;
+ struct device *codec_dev;
bool speaker_en;
};
@@ -461,6 +462,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
const struct dmi_system_id *dmi_id;
struct device *dev = &pdev->dev;
struct snd_soc_acpi_mach *mach;
+ struct fwnode_handle *fwnode;
const char *platform_name;
struct acpi_device *adev;
struct device *codec_dev;
@@ -491,6 +493,9 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
"i2c-%s", acpi_dev_name(adev));
put_device(&adev->dev);
byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
+ } else {
+ dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ return -ENXIO;
}
/* override plaform name, if required */
@@ -535,15 +540,25 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
}
/* get speaker enable GPIO */
- codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
+ codec_dev = acpi_get_first_physical_node(adev);
if (!codec_dev)
return -EPROBE_DEFER;
+ priv->codec_dev = get_device(codec_dev);
if (quirk & BYT_CHT_ES8316_JD_INVERTED)
props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
if (cnt) {
- ret = device_add_properties(codec_dev, props);
+ fwnode = fwnode_create_software_node(props, NULL);
+ if (IS_ERR(fwnode)) {
+ put_device(codec_dev);
+ return PTR_ERR(fwnode);
+ }
+
+ ret = device_add_software_node(codec_dev, to_software_node(fwnode));
+
+ fwnode_handle_put(fwnode);
+
if (ret) {
put_device(codec_dev);
return ret;
@@ -555,7 +570,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
gpiod_get_index(codec_dev, "speaker-enable", 0,
/* see comment in byt_cht_es8316_resume */
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
- put_device(codec_dev);
if (IS_ERR(priv->speaker_en_gpio)) {
ret = PTR_ERR(priv->speaker_en_gpio);
@@ -567,7 +581,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
dev_err(dev, "get speaker GPIO failed: %d\n", ret);
fallthrough;
case -EPROBE_DEFER:
- return ret;
+ goto err_put_codec;
}
}
@@ -605,10 +619,15 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
if (ret) {
gpiod_put(priv->speaker_en_gpio);
dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
- return ret;
+ goto err_put_codec;
}
platform_set_drvdata(pdev, &byt_cht_es8316_card);
return 0;
+
+err_put_codec:
+ device_remove_software_node(priv->codec_dev);
+ put_device(priv->codec_dev);
+ return ret;
}
static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
@@ -617,6 +636,8 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
gpiod_put(priv->speaker_en_gpio);
+ device_remove_software_node(priv->codec_dev);
+ put_device(priv->codec_dev);
return 0;
}
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 91a6d712eb58..a6e837290c7d 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -18,6 +18,8 @@
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <sound/pcm.h>
@@ -73,6 +75,10 @@ enum {
#define BYT_RT5640_MCLK_EN BIT(22)
#define BYT_RT5640_MCLK_25MHZ BIT(23)
#define BYT_RT5640_NO_SPEAKERS BIT(24)
+#define BYT_RT5640_LINEOUT BIT(25)
+#define BYT_RT5640_LINEOUT_AS_HP2 BIT(26)
+#define BYT_RT5640_HSMIC2_ON_IN1 BIT(27)
+#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28)
#define BYTCR_INPUT_DEFAULTS \
(BYT_RT5640_IN3_MAP | \
@@ -86,7 +92,10 @@ enum {
struct byt_rt5640_private {
struct snd_soc_jack jack;
+ struct snd_soc_jack jack2;
+ struct gpio_desc *hsmic_detect;
struct clk *mclk;
+ struct device *codec_dev;
};
static bool is_bytcr;
@@ -125,6 +134,8 @@ static void log_quirks(struct device *dev)
dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);
break;
}
+ if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)
+ dev_info(dev, "quirk HSMIC2_ON_IN1 enabled\n");
if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
dev_info(dev, "quirk realtek,jack-detect-source %ld\n",
BYT_RT5640_JDSRC(byt_rt5640_quirk));
@@ -135,10 +146,16 @@ static void log_quirks(struct device *dev)
}
if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
dev_info(dev, "quirk JD_NOT_INV enabled\n");
+ if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
+ dev_info(dev, "quirk JD_HP_ELITEPAD_1000G2 enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
dev_info(dev, "quirk MONO_SPEAKER enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)
dev_info(dev, "quirk NO_SPEAKERS enabled\n");
+ if (byt_rt5640_quirk & BYT_RT5640_LINEOUT)
+ dev_info(dev, "quirk LINEOUT enabled\n");
+ if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)
+ dev_info(dev, "quirk LINEOUT_AS_HP2 enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
dev_info(dev, "quirk DIFF_MIC enabled\n");
if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
@@ -224,6 +241,20 @@ static int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
#define BYT_CODEC_DAI1 "rt5640-aif1"
#define BYT_CODEC_DAI2 "rt5640-aif2"
+static struct snd_soc_dai *byt_rt5640_get_codec_dai(struct snd_soc_dapm_context *dapm)
+{
+ struct snd_soc_card *card = dapm->card;
+ struct snd_soc_dai *codec_dai;
+
+ codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
+ if (!codec_dai)
+ codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
+ if (!codec_dai)
+ dev_err(card->dev, "Error codec dai not found\n");
+
+ return codec_dai;
+}
+
static int platform_clock_control(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
@@ -233,15 +264,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
int ret;
- codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
+ codec_dai = byt_rt5640_get_codec_dai(dapm);
if (!codec_dai)
- codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
-
- if (!codec_dai) {
- dev_err(card->dev,
- "Codec dai not found; Unable to set platform clock\n");
return -EIO;
- }
if (SND_SOC_DAPM_EVENT_ON(event)) {
if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
@@ -276,23 +301,48 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
return 0;
}
+static int byt_rt5640_event_lineout(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ unsigned int gpio_ctrl3_val = RT5640_GP1_PF_OUT;
+ struct snd_soc_dai *codec_dai;
+
+ if (!(byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2))
+ return 0;
+
+ /*
+ * On devices which use line-out as a second headphones output,
+ * the codec's GPIO1 pin is used to enable an external HP-amp.
+ */
+
+ codec_dai = byt_rt5640_get_codec_dai(w->dapm);
+ if (!codec_dai)
+ return -EIO;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ gpio_ctrl3_val |= RT5640_GP1_OUT_HI;
+
+ snd_soc_component_update_bits(codec_dai->component, RT5640_GPIO_CTRL3,
+ RT5640_GP1_PF_MASK | RT5640_GP1_OUT_MASK, gpio_ctrl3_val);
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic 2", NULL),
SND_SOC_DAPM_MIC("Internal Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+ SND_SOC_DAPM_LINE("Line Out", byt_rt5640_event_lineout),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
-
};
static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
{"Headphone", NULL, "Platform Clock"},
{"Headset Mic", NULL, "Platform Clock"},
- {"Internal Mic", NULL, "Platform Clock"},
- {"Speaker", NULL, "Platform Clock"},
-
{"Headset Mic", NULL, "MICBIAS1"},
{"IN2P", NULL, "Headset Mic"},
{"Headphone", NULL, "HPOL"},
@@ -300,23 +350,33 @@ static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
};
static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
+ {"Internal Mic", NULL, "Platform Clock"},
{"DMIC1", NULL, "Internal Mic"},
};
static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
+ {"Internal Mic", NULL, "Platform Clock"},
{"DMIC2", NULL, "Internal Mic"},
};
static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
+ {"Internal Mic", NULL, "Platform Clock"},
{"Internal Mic", NULL, "MICBIAS1"},
{"IN1P", NULL, "Internal Mic"},
};
static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {
+ {"Internal Mic", NULL, "Platform Clock"},
{"Internal Mic", NULL, "MICBIAS1"},
{"IN3P", NULL, "Internal Mic"},
};
+static const struct snd_soc_dapm_route byt_rt5640_hsmic2_in1_map[] = {
+ {"Headset Mic 2", NULL, "Platform Clock"},
+ {"Headset Mic 2", NULL, "MICBIAS1"},
+ {"IN1P", NULL, "Headset Mic 2"},
+};
+
static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = {
{"ssp2 Tx", NULL, "codec_out0"},
{"ssp2 Tx", NULL, "codec_out1"},
@@ -354,6 +414,7 @@ static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = {
};
static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
+ {"Speaker", NULL, "Platform Clock"},
{"Speaker", NULL, "SPOLP"},
{"Speaker", NULL, "SPOLN"},
{"Speaker", NULL, "SPORP"},
@@ -361,15 +422,24 @@ static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
};
static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {
+ {"Speaker", NULL, "Platform Clock"},
{"Speaker", NULL, "SPOLP"},
{"Speaker", NULL, "SPOLN"},
};
+static const struct snd_soc_dapm_route byt_rt5640_lineout_map[] = {
+ {"Line Out", NULL, "Platform Clock"},
+ {"Line Out", NULL, "LOUTR"},
+ {"Line Out", NULL, "LOUTL"},
+};
+
static const struct snd_kcontrol_new byt_rt5640_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic 2"),
SOC_DAPM_PIN_SWITCH("Internal Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
+ SOC_DAPM_PIN_SWITCH("Line Out"),
};
static struct snd_soc_jack_pin rt5640_pins[] = {
@@ -383,6 +453,75 @@ static struct snd_soc_jack_pin rt5640_pins[] = {
},
};
+static struct snd_soc_jack_pin rt5640_pins2[] = {
+ {
+ /* The 2nd headset jack uses lineout with an external HP-amp */
+ .pin = "Line Out",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "Headset Mic 2",
+ .mask = SND_JACK_MICROPHONE,
+ },
+};
+
+static struct snd_soc_jack_gpio rt5640_jack_gpio = {
+ .name = "hp-detect",
+ .report = SND_JACK_HEADSET,
+ .invert = true,
+ .debounce_time = 200,
+};
+
+static struct snd_soc_jack_gpio rt5640_jack2_gpio = {
+ .name = "hp2-detect",
+ .report = SND_JACK_HEADSET,
+ .invert = true,
+ .debounce_time = 200,
+};
+
+static const struct acpi_gpio_params acpi_gpio0 = { 0, 0, false };
+static const struct acpi_gpio_params acpi_gpio1 = { 1, 0, false };
+static const struct acpi_gpio_params acpi_gpio2 = { 2, 0, false };
+
+static const struct acpi_gpio_mapping byt_rt5640_hp_elitepad_1000g2_gpios[] = {
+ { "hp-detect-gpios", &acpi_gpio0, 1, },
+ { "headset-mic-detect-gpios", &acpi_gpio1, 1, },
+ { "hp2-detect-gpios", &acpi_gpio2, 1, },
+ { },
+};
+
+static int byt_rt5640_hp_elitepad_1000g2_jack1_check(void *data)
+{
+ struct byt_rt5640_private *priv = data;
+ int jack_status, mic_status;
+
+ jack_status = gpiod_get_value_cansleep(rt5640_jack_gpio.desc);
+ if (jack_status)
+ return 0;
+
+ mic_status = gpiod_get_value_cansleep(priv->hsmic_detect);
+ if (mic_status)
+ return SND_JACK_HEADPHONE;
+ else
+ return SND_JACK_HEADSET;
+}
+
+static int byt_rt5640_hp_elitepad_1000g2_jack2_check(void *data)
+{
+ struct snd_soc_component *component = data;
+ int jack_status, report;
+
+ jack_status = gpiod_get_value_cansleep(rt5640_jack2_gpio.desc);
+ if (jack_status)
+ return 0;
+
+ rt5640_enable_micbias1_for_ovcd(component);
+ report = rt5640_detect_headset(component, rt5640_jack2_gpio.desc);
+ rt5640_disable_micbias1_for_ovcd(component);
+
+ return report;
+}
+
static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -590,8 +729,12 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
},
- .driver_data = (void *)(BYT_RT5640_IN1_MAP |
- BYT_RT5640_MCLK_EN),
+ .driver_data = (void *)(BYT_RT5640_DMIC2_MAP |
+ BYT_RT5640_MCLK_EN |
+ BYT_RT5640_LINEOUT |
+ BYT_RT5640_LINEOUT_AS_HP2 |
+ BYT_RT5640_HSMIC2_ON_IN1 |
+ BYT_RT5640_JD_HP_ELITEP_1000G2),
},
{ /* HP Pavilion x2 10-k0XX, 10-n0XX */
.matches = {
@@ -912,15 +1055,13 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
* Note this MUST be called before snd_soc_register_card(), so that the props
* are in place before the codec component driver's probe function parses them.
*/
-static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
+static int byt_rt5640_add_codec_device_props(struct device *i2c_dev,
+ struct byt_rt5640_private *priv)
{
struct property_entry props[MAX_NO_PROPS] = {};
- struct device *i2c_dev;
- int ret, cnt = 0;
-
- i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name);
- if (!i2c_dev)
- return -EPROBE_DEFER;
+ struct fwnode_handle *fwnode;
+ int cnt = 0;
+ int ret;
switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
case BYT_RT5640_DMIC1_MAP:
@@ -960,8 +1101,15 @@ static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
- ret = device_add_properties(i2c_dev, props);
- put_device(i2c_dev);
+ fwnode = fwnode_create_software_node(props, NULL);
+ if (IS_ERR(fwnode)) {
+ /* put_device() is handled in caller */
+ return PTR_ERR(fwnode);
+ }
+
+ ret = device_add_software_node(i2c_dev, to_software_node(fwnode));
+
+ fwnode_handle_put(fwnode);
return ret;
}
@@ -1021,6 +1169,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
if (ret)
return ret;
+ if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) {
+ ret = snd_soc_dapm_add_routes(&card->dapm,
+ byt_rt5640_hsmic2_in1_map,
+ ARRAY_SIZE(byt_rt5640_hsmic2_in1_map));
+ if (ret)
+ return ret;
+ }
+
if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
ret = snd_soc_dapm_add_routes(&card->dapm,
byt_rt5640_ssp2_aif2_map,
@@ -1053,6 +1209,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
if (ret)
return ret;
+ if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {
+ ret = snd_soc_dapm_add_routes(&card->dapm,
+ byt_rt5640_lineout_map,
+ ARRAY_SIZE(byt_rt5640_lineout_map));
+ if (ret)
+ return ret;
+ }
+
if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
/*
* The firmware might enable the clock at
@@ -1093,9 +1257,53 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
snd_soc_component_set_jack(component, &priv->jack, NULL);
}
+ if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
+ ret = snd_soc_card_jack_new(card, "Headset",
+ SND_JACK_HEADSET,
+ &priv->jack, rt5640_pins,
+ ARRAY_SIZE(rt5640_pins));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_card_jack_new(card, "Headset 2",
+ SND_JACK_HEADSET,
+ &priv->jack2, rt5640_pins2,
+ ARRAY_SIZE(rt5640_pins2));
+ if (ret)
+ return ret;
+
+ rt5640_jack_gpio.data = priv;
+ rt5640_jack_gpio.gpiod_dev = priv->codec_dev;
+ rt5640_jack_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack1_check;
+ ret = snd_soc_jack_add_gpios(&priv->jack, 1, &rt5640_jack_gpio);
+ if (ret)
+ return ret;
+
+ rt5640_set_ovcd_params(component);
+ rt5640_jack2_gpio.data = component;
+ rt5640_jack2_gpio.gpiod_dev = priv->codec_dev;
+ rt5640_jack2_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack2_check;
+ ret = snd_soc_jack_add_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);
+ if (ret) {
+ snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);
+ return ret;
+ }
+ }
+
return 0;
}
+static void byt_rt5640_exit(struct snd_soc_pcm_runtime *runtime)
+{
+ struct snd_soc_card *card = runtime->card;
+ struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
+
+ if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
+ snd_soc_jack_free_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);
+ snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);
+ }
+}
+
static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -1208,6 +1416,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
.dpcm_playback = 1,
.dpcm_capture = 1,
.init = byt_rt5640_init,
+ .exit = byt_rt5640_exit,
.ops = &byt_rt5640_be_ssp2_ops,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
@@ -1218,7 +1427,7 @@ static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];
#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */
#endif
-static char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */
+static char byt_rt5640_components[64]; /* = "cfg-spk:* cfg-mic:* ..." */
static int byt_rt5640_suspend(struct snd_soc_card *card)
{
@@ -1288,10 +1497,13 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };
__maybe_unused const char *spk_type;
const struct dmi_system_id *dmi_id;
+ const char *headset2_string = "";
+ const char *lineout_string = "";
struct byt_rt5640_private *priv;
struct snd_soc_acpi_mach *mach;
const char *platform_name;
struct acpi_device *adev;
+ struct device *codec_dev;
bool sof_parent;
int ret_val = 0;
int dai_index = 0;
@@ -1324,6 +1536,9 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
"i2c-%s", acpi_dev_name(adev));
put_device(&adev->dev);
byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;
+ } else {
+ dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ return -ENXIO;
}
/*
@@ -1400,10 +1615,29 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
byt_rt5640_quirk = quirk_override;
}
+ codec_dev = acpi_get_first_physical_node(adev);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
+ priv->codec_dev = get_device(codec_dev);
+
+ if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
+ acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev),
+ byt_rt5640_hp_elitepad_1000g2_gpios);
+
+ priv->hsmic_detect = devm_fwnode_gpiod_get(&pdev->dev, codec_dev->fwnode,
+ "headset-mic-detect", GPIOD_IN,
+ "headset-mic-detect");
+ if (IS_ERR(priv->hsmic_detect)) {
+ ret_val = PTR_ERR(priv->hsmic_detect);
+ dev_err_probe(&pdev->dev, ret_val, "getting hsmic-detect GPIO\n");
+ goto err_device;
+ }
+ }
+
/* Must be called before register_card, also see declaration comment. */
- ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name);
+ ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv);
if (ret_val)
- return ret_val;
+ goto err_remove_gpios;
log_quirks(&pdev->dev);
@@ -1434,7 +1668,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
* for all other errors, including -EPROBE_DEFER
*/
if (ret_val != -ENOENT)
- return ret_val;
+ goto err;
byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
}
}
@@ -1450,9 +1684,20 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
spk_type = "stereo";
}
+ if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {
+ if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)
+ lineout_string = " cfg-hp2:lineout";
+ else
+ lineout_string = " cfg-lineout:2";
+ }
+
+ if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)
+ headset2_string = " cfg-hs2:in1";
+
snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),
- "cfg-spk:%d cfg-mic:%s aif:%d", cfg_spk,
- map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif);
+ "cfg-spk:%d cfg-mic:%s aif:%d%s%s", cfg_spk,
+ map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif,
+ lineout_string, headset2_string);
byt_rt5640_card.components = byt_rt5640_components;
#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),
@@ -1467,7 +1712,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,
platform_name);
if (ret_val)
- return ret_val;
+ goto err;
sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
@@ -1489,10 +1734,32 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
if (ret_val) {
dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
ret_val);
- return ret_val;
+ goto err;
}
platform_set_drvdata(pdev, &byt_rt5640_card);
return ret_val;
+
+err:
+ device_remove_software_node(priv->codec_dev);
+err_remove_gpios:
+ if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
+ acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));
+err_device:
+ put_device(priv->codec_dev);
+ return ret_val;
+}
+
+static int snd_byt_rt5640_mc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
+
+ if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
+ acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));
+
+ device_remove_software_node(priv->codec_dev);
+ put_device(priv->codec_dev);
+ return 0;
}
static struct platform_driver snd_byt_rt5640_mc_driver = {
@@ -1500,6 +1767,7 @@ static struct platform_driver snd_byt_rt5640_mc_driver = {
.name = "bytcr_rt5640",
},
.probe = snd_byt_rt5640_mc_probe,
+ .remove = snd_byt_rt5640_mc_remove,
};
module_platform_driver(snd_byt_rt5640_mc_driver);
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index e13c0c63a949..e94c9124d4f4 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -85,6 +85,7 @@ struct byt_rt5651_private {
struct gpio_desc *ext_amp_gpio;
struct gpio_desc *hp_detect;
struct snd_soc_jack jack;
+ struct device *codec_dev;
};
static const struct acpi_gpio_mapping *byt_rt5651_gpios;
@@ -527,10 +528,13 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
* Note this MUST be called before snd_soc_register_card(), so that the props
* are in place before the codec component driver's probe function parses them.
*/
-static int byt_rt5651_add_codec_device_props(struct device *i2c_dev)
+static int byt_rt5651_add_codec_device_props(struct device *i2c_dev,
+ struct byt_rt5651_private *priv)
{
struct property_entry props[MAX_NO_PROPS] = {};
+ struct fwnode_handle *fwnode;
int cnt = 0;
+ int ret;
props[cnt++] = PROPERTY_ENTRY_U32("realtek,jack-detect-source",
BYT_RT5651_JDSRC(byt_rt5651_quirk));
@@ -547,7 +551,17 @@ static int byt_rt5651_add_codec_device_props(struct device *i2c_dev)
if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV)
props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
- return device_add_properties(i2c_dev, props);
+ fwnode = fwnode_create_software_node(props, NULL);
+ if (IS_ERR(fwnode)) {
+ /* put_device(i2c_dev) is handled in caller */
+ return PTR_ERR(fwnode);
+ }
+
+ ret = device_add_software_node(i2c_dev, to_software_node(fwnode));
+
+ fwnode_handle_put(fwnode);
+
+ return ret;
}
static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
@@ -920,13 +934,13 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
} else {
dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
- return -ENODEV;
+ return -ENXIO;
}
- codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
- byt_rt5651_codec_name);
+ codec_dev = acpi_get_first_physical_node(adev);
if (!codec_dev)
return -EPROBE_DEFER;
+ priv->codec_dev = get_device(codec_dev);
/*
* swap SSP0 if bytcr is detected
@@ -994,11 +1008,9 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
}
/* Must be called before register_card, also see declaration comment. */
- ret_val = byt_rt5651_add_codec_device_props(codec_dev);
- if (ret_val) {
- put_device(codec_dev);
- return ret_val;
- }
+ ret_val = byt_rt5651_add_codec_device_props(codec_dev, priv);
+ if (ret_val)
+ goto err_device;
/* Cherry Trail devices use an external amplifier enable gpio */
if (soc_intel_is_cht() && !byt_rt5651_gpios)
@@ -1022,8 +1034,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
ret_val);
fallthrough;
case -EPROBE_DEFER:
- put_device(codec_dev);
- return ret_val;
+ goto err;
}
}
priv->hp_detect = devm_fwnode_gpiod_get(&pdev->dev,
@@ -1042,14 +1053,11 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
ret_val);
fallthrough;
case -EPROBE_DEFER:
- put_device(codec_dev);
- return ret_val;
+ goto err;
}
}
}
- put_device(codec_dev);
-
log_quirks(&pdev->dev);
if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
@@ -1073,7 +1081,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
* for all other errors, including -EPROBE_DEFER
*/
if (ret_val != -ENOENT)
- return ret_val;
+ goto err;
byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
}
}
@@ -1102,7 +1110,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card,
platform_name);
if (ret_val)
- return ret_val;
+ goto err;
sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
@@ -1124,10 +1132,26 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
if (ret_val) {
dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
ret_val);
- return ret_val;
+ goto err;
}
platform_set_drvdata(pdev, &byt_rt5651_card);
return ret_val;
+
+err:
+ device_remove_software_node(priv->codec_dev);
+err_device:
+ put_device(priv->codec_dev);
+ return ret_val;
+}
+
+static int snd_byt_rt5651_mc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
+
+ device_remove_software_node(priv->codec_dev);
+ put_device(priv->codec_dev);
+ return 0;
}
static struct platform_driver snd_byt_rt5651_mc_driver = {
@@ -1135,6 +1159,7 @@ static struct platform_driver snd_byt_rt5651_mc_driver = {
.name = "bytcr_rt5651",
},
.probe = snd_byt_rt5651_mc_probe,
+ .remove = snd_byt_rt5651_mc_remove,
};
module_platform_driver(snd_byt_rt5651_mc_driver);
diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c
index a31a7a7bbf66..2b43459adc33 100644
--- a/sound/soc/intel/boards/kbl_da7219_max98927.c
+++ b/sound/soc/intel/boards/kbl_da7219_max98927.c
@@ -199,7 +199,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
}
if (!strcmp(codec_dai->component->name, MAX98373_DEV0_NAME)) {
ret = snd_soc_dai_set_tdm_slot(codec_dai,
- 0x03, 3, 8, 24);
+ 0x30, 3, 8, 16);
if (ret < 0) {
dev_err(runtime->dev,
"DEV0 TDM slot err:%d\n", ret);
@@ -208,10 +208,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
}
if (!strcmp(codec_dai->component->name, MAX98373_DEV1_NAME)) {
ret = snd_soc_dai_set_tdm_slot(codec_dai,
- 0x0C, 3, 8, 24);
+ 0xC0, 3, 8, 16);
if (ret < 0) {
dev_err(runtime->dev,
- "DEV0 TDM slot err:%d\n", ret);
+ "DEV1 TDM slot err:%d\n", ret);
return ret;
}
}
@@ -311,24 +311,6 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
* The above 2 loops are mutually exclusive based on the stream direction,
* thus rtd_dpcm variable will never be overwritten
*/
- /*
- * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE,
- * where as kblda7219m98927 & kblmax98927 supports S16_LE by default.
- * Skipping the port wise FE and BE configuration for kblda7219m98373 &
- * kblmax98373 as the topology (FE & BE) supports S24_LE only.
- */
-
- if (!strcmp(rtd->card->name, "kblda7219m98373") ||
- !strcmp(rtd->card->name, "kblmax98373")) {
- /* The ADSP will convert the FE rate to 48k, stereo */
- rate->min = rate->max = 48000;
- chan->min = chan->max = DUAL_CHANNEL;
-
- /* set SSP to 24 bit */
- snd_mask_none(fmt);
- snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
- return 0;
- }
/*
* The ADSP will convert the FE rate to 48k, stereo, 24 bit
@@ -479,31 +461,20 @@ static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
static int kbl_fe_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream);
/*
* On this platform for PCM device we support,
* 48Khz
* stereo
+ * 16 bit audio
*/
runtime->hw.channels_max = DUAL_CHANNEL;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
- /*
- * Setup S24_LE (32 bit container and 24 bit valid data) for
- * kblda7219m98373 & kblmax98373. For kblda7219m98927 &
- * kblmax98927 keeping it as 16/16 due to topology FW dependency.
- */
- if (!strcmp(soc_rt->card->name, "kblda7219m98373") ||
- !strcmp(soc_rt->card->name, "kblmax98373")) {
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE;
- snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
-
- } else {
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
- snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
- }
+
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
@@ -536,23 +507,11 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
static int kabylake_dmic_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream);
runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels_quad);
- /*
- * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE.
- * The DMIC also configured for S24_LE. Forcing the DMIC format to
- * S24_LE due to the topology FW dependency.
- */
- if (!strcmp(soc_rt->card->name, "kblda7219m98373") ||
- !strcmp(soc_rt->card->name, "kblmax98373")) {
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE;
- snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
- }
-
return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
}
diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c
index 42aadf801f72..ce78c1879887 100644
--- a/sound/soc/intel/boards/sof_cs42l42.c
+++ b/sound/soc/intel/boards/sof_cs42l42.c
@@ -16,6 +16,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/sof.h>
#include <sound/soc-acpi.h>
#include <dt-bindings/sound/cs42l42.h>
#include "../../codecs/hdac_hdmi.h"
@@ -36,7 +37,20 @@
#define SOF_CS42L42_NUM_HDMIDEV_MASK (GENMASK(9, 7))
#define SOF_CS42L42_NUM_HDMIDEV(quirk) \
(((quirk) << SOF_CS42L42_NUM_HDMIDEV_SHIFT) & SOF_CS42L42_NUM_HDMIDEV_MASK)
-#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(10)
+#define SOF_CS42L42_DAILINK_SHIFT 10
+#define SOF_CS42L42_DAILINK_MASK (GENMASK(24, 10))
+#define SOF_CS42L42_DAILINK(link1, link2, link3, link4, link5) \
+ ((((link1) | ((link2) << 3) | ((link3) << 6) | ((link4) << 9) | ((link5) << 12)) << SOF_CS42L42_DAILINK_SHIFT) & SOF_CS42L42_DAILINK_MASK)
+#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(25)
+#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(26)
+
+enum {
+ LINK_NONE = 0,
+ LINK_HP = 1,
+ LINK_SPK = 2,
+ LINK_DMIC = 3,
+ LINK_HDMI = 4,
+};
/* Default: SSP2 */
static unsigned long sof_cs42l42_quirk = SOF_CS42L42_SSP_CODEC(2);
@@ -122,7 +136,12 @@ static int sof_cs42l42_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int clk_freq, ret;
- clk_freq = 3072000; /* BCLK freq */
+ clk_freq = sof_dai_get_bclk(rtd); /* BCLK freq */
+
+ if (clk_freq <= 0) {
+ dev_err(rtd->dev, "get bclk freq failed: %d\n", clk_freq);
+ return -EINVAL;
+ }
/* Configure sysclk for codec */
ret = snd_soc_dai_set_sysclk(codec_dai, 0,
@@ -259,133 +278,168 @@ static struct snd_soc_dai_link_component dmic_component[] = {
}
};
-static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
- int ssp_codec,
- int ssp_amp,
- int dmic_be_num,
- int hdmi_num)
+static int create_spk_amp_dai_links(struct device *dev,
+ struct snd_soc_dai_link *links,
+ struct snd_soc_dai_link_component *cpus,
+ int *id, int ssp_amp)
{
- struct snd_soc_dai_link_component *idisp_components;
- struct snd_soc_dai_link_component *cpus;
- struct snd_soc_dai_link *links;
- int i, id = 0;
-
- links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
- sof_audio_card_cs42l42.num_links, GFP_KERNEL);
- cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
- sof_audio_card_cs42l42.num_links, GFP_KERNEL);
- if (!links || !cpus)
- goto devm_err;
+ int ret = 0;
/* speaker amp */
- if (sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT) {
- links[id].name = devm_kasprintf(dev, GFP_KERNEL,
- "SSP%d-Codec", ssp_amp);
- if (!links[id].name)
- goto devm_err;
+ if (!(sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT))
+ return 0;
- links[id].id = id;
+ links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
+ ssp_amp);
+ if (!links[*id].name) {
+ ret = -ENOMEM;
+ goto devm_err;
+ }
- if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
- max_98357a_dai_link(&links[id]);
- } else {
- dev_err(dev, "no amp defined\n");
- goto devm_err;
- }
+ links[*id].id = *id;
- links[id].platforms = platform_component;
- links[id].num_platforms = ARRAY_SIZE(platform_component);
- links[id].dpcm_playback = 1;
- links[id].no_pcm = 1;
- links[id].cpus = &cpus[id];
- links[id].num_cpus = 1;
-
- links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
- "SSP%d Pin",
- ssp_amp);
- if (!links[id].cpus->dai_name)
- goto devm_err;
+ if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
+ max_98357a_dai_link(&links[*id]);
+ } else if (sof_cs42l42_quirk & SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
+ max_98360a_dai_link(&links[*id]);
+ } else {
+ dev_err(dev, "no amp defined\n");
+ ret = -EINVAL;
+ goto devm_err;
+ }
- id++;
+ links[*id].platforms = platform_component;
+ links[*id].num_platforms = ARRAY_SIZE(platform_component);
+ links[*id].dpcm_playback = 1;
+ links[*id].no_pcm = 1;
+ links[*id].cpus = &cpus[*id];
+ links[*id].num_cpus = 1;
+
+ links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+ "SSP%d Pin", ssp_amp);
+ if (!links[*id].cpus->dai_name) {
+ ret = -ENOMEM;
+ goto devm_err;
}
+ (*id)++;
+
+devm_err:
+ return ret;
+}
+
+static int create_hp_codec_dai_links(struct device *dev,
+ struct snd_soc_dai_link *links,
+ struct snd_soc_dai_link_component *cpus,
+ int *id, int ssp_codec)
+{
/* codec SSP */
- links[id].name = devm_kasprintf(dev, GFP_KERNEL,
- "SSP%d-Codec", ssp_codec);
- if (!links[id].name)
+ links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
+ ssp_codec);
+ if (!links[*id].name)
goto devm_err;
- links[id].id = id;
- links[id].codecs = cs42l42_component;
- links[id].num_codecs = ARRAY_SIZE(cs42l42_component);
- links[id].platforms = platform_component;
- links[id].num_platforms = ARRAY_SIZE(platform_component);
- links[id].init = sof_cs42l42_init;
- links[id].exit = sof_cs42l42_exit;
- links[id].ops = &sof_cs42l42_ops;
- links[id].dpcm_playback = 1;
- links[id].dpcm_capture = 1;
- links[id].no_pcm = 1;
- links[id].cpus = &cpus[id];
- links[id].num_cpus = 1;
-
- links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
- "SSP%d Pin",
- ssp_codec);
- if (!links[id].cpus->dai_name)
+ links[*id].id = *id;
+ links[*id].codecs = cs42l42_component;
+ links[*id].num_codecs = ARRAY_SIZE(cs42l42_component);
+ links[*id].platforms = platform_component;
+ links[*id].num_platforms = ARRAY_SIZE(platform_component);
+ links[*id].init = sof_cs42l42_init;
+ links[*id].exit = sof_cs42l42_exit;
+ links[*id].ops = &sof_cs42l42_ops;
+ links[*id].dpcm_playback = 1;
+ links[*id].dpcm_capture = 1;
+ links[*id].no_pcm = 1;
+ links[*id].cpus = &cpus[*id];
+ links[*id].num_cpus = 1;
+
+ links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+ "SSP%d Pin",
+ ssp_codec);
+ if (!links[*id].cpus->dai_name)
goto devm_err;
- id++;
+ (*id)++;
+
+ return 0;
+
+devm_err:
+ return -ENOMEM;
+}
+
+static int create_dmic_dai_links(struct device *dev,
+ struct snd_soc_dai_link *links,
+ struct snd_soc_dai_link_component *cpus,
+ int *id, int dmic_be_num)
+{
+ int i;
/* dmic */
- if (dmic_be_num > 0) {
- /* at least we have dmic01 */
- links[id].name = "dmic01";
- links[id].cpus = &cpus[id];
- links[id].cpus->dai_name = "DMIC01 Pin";
- links[id].init = dmic_init;
- if (dmic_be_num > 1) {
- /* set up 2 BE links at most */
- links[id + 1].name = "dmic16k";
- links[id + 1].cpus = &cpus[id + 1];
- links[id + 1].cpus->dai_name = "DMIC16k Pin";
- dmic_be_num = 2;
- }
+ if (dmic_be_num <= 0)
+ return 0;
+
+ /* at least we have dmic01 */
+ links[*id].name = "dmic01";
+ links[*id].cpus = &cpus[*id];
+ links[*id].cpus->dai_name = "DMIC01 Pin";
+ links[*id].init = dmic_init;
+ if (dmic_be_num > 1) {
+ /* set up 2 BE links at most */
+ links[*id + 1].name = "dmic16k";
+ links[*id + 1].cpus = &cpus[*id + 1];
+ links[*id + 1].cpus->dai_name = "DMIC16k Pin";
+ dmic_be_num = 2;
}
for (i = 0; i < dmic_be_num; i++) {
- links[id].id = id;
- links[id].num_cpus = 1;
- links[id].codecs = dmic_component;
- links[id].num_codecs = ARRAY_SIZE(dmic_component);
- links[id].platforms = platform_component;
- links[id].num_platforms = ARRAY_SIZE(platform_component);
- links[id].ignore_suspend = 1;
- links[id].dpcm_capture = 1;
- links[id].no_pcm = 1;
- id++;
+ links[*id].id = *id;
+ links[*id].num_cpus = 1;
+ links[*id].codecs = dmic_component;
+ links[*id].num_codecs = ARRAY_SIZE(dmic_component);
+ links[*id].platforms = platform_component;
+ links[*id].num_platforms = ARRAY_SIZE(platform_component);
+ links[*id].ignore_suspend = 1;
+ links[*id].dpcm_capture = 1;
+ links[*id].no_pcm = 1;
+
+ (*id)++;
}
+ return 0;
+}
+
+static int create_hdmi_dai_links(struct device *dev,
+ struct snd_soc_dai_link *links,
+ struct snd_soc_dai_link_component *cpus,
+ int *id, int hdmi_num)
+{
+ struct snd_soc_dai_link_component *idisp_components;
+ int i;
+
/* HDMI */
- if (hdmi_num > 0) {
- idisp_components = devm_kzalloc(dev,
- sizeof(struct snd_soc_dai_link_component) *
- hdmi_num, GFP_KERNEL);
- if (!idisp_components)
- goto devm_err;
- }
+ if (hdmi_num <= 0)
+ return 0;
+
+ idisp_components = devm_kzalloc(dev,
+ sizeof(struct snd_soc_dai_link_component) *
+ hdmi_num, GFP_KERNEL);
+ if (!idisp_components)
+ goto devm_err;
+
for (i = 1; i <= hdmi_num; i++) {
- links[id].name = devm_kasprintf(dev, GFP_KERNEL,
- "iDisp%d", i);
- if (!links[id].name)
+ links[*id].name = devm_kasprintf(dev, GFP_KERNEL,
+ "iDisp%d", i);
+ if (!links[*id].name)
goto devm_err;
- links[id].id = id;
- links[id].cpus = &cpus[id];
- links[id].num_cpus = 1;
- links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
- "iDisp%d Pin", i);
- if (!links[id].cpus->dai_name)
+ links[*id].id = *id;
+ links[*id].cpus = &cpus[*id];
+ links[*id].num_cpus = 1;
+ links[*id].cpus->dai_name = devm_kasprintf(dev,
+ GFP_KERNEL,
+ "iDisp%d Pin",
+ i);
+ if (!links[*id].cpus->dai_name)
goto devm_err;
idisp_components[i - 1].name = "ehdaudio0D2";
@@ -396,14 +450,86 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
if (!idisp_components[i - 1].dai_name)
goto devm_err;
- links[id].codecs = &idisp_components[i - 1];
- links[id].num_codecs = 1;
- links[id].platforms = platform_component;
- links[id].num_platforms = ARRAY_SIZE(platform_component);
- links[id].init = sof_hdmi_init;
- links[id].dpcm_playback = 1;
- links[id].no_pcm = 1;
- id++;
+ links[*id].codecs = &idisp_components[i - 1];
+ links[*id].num_codecs = 1;
+ links[*id].platforms = platform_component;
+ links[*id].num_platforms = ARRAY_SIZE(platform_component);
+ links[*id].init = sof_hdmi_init;
+ links[*id].dpcm_playback = 1;
+ links[*id].no_pcm = 1;
+
+ (*id)++;
+ }
+
+ return 0;
+
+devm_err:
+ return -ENOMEM;
+}
+
+static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
+ int ssp_codec,
+ int ssp_amp,
+ int dmic_be_num,
+ int hdmi_num)
+{
+ struct snd_soc_dai_link_component *cpus;
+ struct snd_soc_dai_link *links;
+ int ret, id = 0, link_seq;
+
+ links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
+ sof_audio_card_cs42l42.num_links, GFP_KERNEL);
+ cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
+ sof_audio_card_cs42l42.num_links, GFP_KERNEL);
+ if (!links || !cpus)
+ goto devm_err;
+
+ link_seq = (sof_cs42l42_quirk & SOF_CS42L42_DAILINK_MASK) >> SOF_CS42L42_DAILINK_SHIFT;
+
+ while (link_seq) {
+ int link_type = link_seq & 0x07;
+
+ switch (link_type) {
+ case LINK_HP:
+ ret = create_hp_codec_dai_links(dev, links, cpus, &id, ssp_codec);
+ if (ret < 0) {
+ dev_err(dev, "fail to create hp codec dai links, ret %d\n",
+ ret);
+ goto devm_err;
+ }
+ break;
+ case LINK_SPK:
+ ret = create_spk_amp_dai_links(dev, links, cpus, &id, ssp_amp);
+ if (ret < 0) {
+ dev_err(dev, "fail to create spk amp dai links, ret %d\n",
+ ret);
+ goto devm_err;
+ }
+ break;
+ case LINK_DMIC:
+ ret = create_dmic_dai_links(dev, links, cpus, &id, dmic_be_num);
+ if (ret < 0) {
+ dev_err(dev, "fail to create dmic dai links, ret %d\n",
+ ret);
+ goto devm_err;
+ }
+ break;
+ case LINK_HDMI:
+ ret = create_hdmi_dai_links(dev, links, cpus, &id, hdmi_num);
+ if (ret < 0) {
+ dev_err(dev, "fail to create hdmi dai links, ret %d\n",
+ ret);
+ goto devm_err;
+ }
+ break;
+ case LINK_NONE:
+ /* caught here if it's not used as terminator in macro */
+ default:
+ dev_err(dev, "invalid link type %d\n", link_type);
+ goto devm_err;
+ }
+
+ link_seq >>= 3;
}
return links;
@@ -484,7 +610,16 @@ static const struct platform_device_id board_ids[] = {
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(2) |
SOF_SPEAKER_AMP_PRESENT |
SOF_MAX98357A_SPEAKER_AMP_PRESENT |
- SOF_CS42L42_SSP_AMP(1)),
+ SOF_CS42L42_SSP_AMP(1)) |
+ SOF_CS42L42_DAILINK(LINK_SPK, LINK_HP, LINK_DMIC, LINK_HDMI, LINK_NONE),
+ },
+ {
+ .name = "jsl_cs4242_mx98360a",
+ .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) |
+ SOF_SPEAKER_AMP_PRESENT |
+ SOF_MAX98360A_SPEAKER_AMP_PRESENT |
+ SOF_CS42L42_SSP_AMP(1)) |
+ SOF_CS42L42_DAILINK(LINK_HP, LINK_DMIC, LINK_HDMI, LINK_SPK, LINK_NONE),
},
{ }
};
diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c
index e9c52f8b6428..e66dfe666915 100644
--- a/sound/soc/intel/boards/sof_maxim_common.c
+++ b/sound/soc/intel/boards/sof_maxim_common.c
@@ -134,7 +134,7 @@ void max_98373_set_codec_conf(struct snd_soc_card *card)
EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
/*
- * Maxim MAX98357A
+ * Maxim MAX98357A/MAX98360A
*/
static const struct snd_kcontrol_new max_98357a_kcontrols[] = {
SOC_DAPM_PIN_SWITCH("Spk"),
@@ -156,6 +156,13 @@ static struct snd_soc_dai_link_component max_98357a_components[] = {
}
};
+static struct snd_soc_dai_link_component max_98360a_components[] = {
+ {
+ .name = MAX_98360A_DEV0_NAME,
+ .dai_name = MAX_98357A_CODEC_DAI,
+ }
+};
+
static int max_98357a_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
@@ -193,5 +200,13 @@ void max_98357a_dai_link(struct snd_soc_dai_link *link)
}
EXPORT_SYMBOL_NS(max_98357a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+void max_98360a_dai_link(struct snd_soc_dai_link *link)
+{
+ link->codecs = max_98360a_components;
+ link->num_codecs = ARRAY_SIZE(max_98360a_components);
+ link->init = max_98357a_init;
+}
+EXPORT_SYMBOL_NS(max_98360a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+
MODULE_DESCRIPTION("ASoC Intel SOF Maxim helpers");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h
index 2674f1e373ef..3ff5e8fec4de 100644
--- a/sound/soc/intel/boards/sof_maxim_common.h
+++ b/sound/soc/intel/boards/sof_maxim_common.h
@@ -25,11 +25,13 @@ void max_98373_set_codec_conf(struct snd_soc_card *card);
int max_98373_trigger(struct snd_pcm_substream *substream, int cmd);
/*
- * Maxim MAX98357A
+ * Maxim MAX98357A/MAX98360A
*/
#define MAX_98357A_CODEC_DAI "HiFi"
#define MAX_98357A_DEV0_NAME "MX98357A:00"
+#define MAX_98360A_DEV0_NAME "MX98360A:00"
void max_98357a_dai_link(struct snd_soc_dai_link *link);
+void max_98360a_dai_link(struct snd_soc_dai_link *link);
#endif /* __SOF_MAXIM_COMMON_H */
diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c
index 2ec9c62366e2..6815204e58d5 100644
--- a/sound/soc/intel/boards/sof_pcm512x.c
+++ b/sound/soc/intel/boards/sof_pcm512x.c
@@ -26,11 +26,16 @@
#define SOF_PCM512X_SSP_CODEC(quirk) ((quirk) & GENMASK(3, 0))
#define SOF_PCM512X_SSP_CODEC_MASK (GENMASK(3, 0))
+#define SOF_PCM512X_ENABLE_SSP_CAPTURE BIT(4)
+#define SOF_PCM512X_ENABLE_DMIC BIT(5)
#define IDISP_CODEC_MASK 0x4
/* Default: SSP5 */
-static unsigned long sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(5);
+static unsigned long sof_pcm512x_quirk =
+ SOF_PCM512X_SSP_CODEC(5) |
+ SOF_PCM512X_ENABLE_SSP_CAPTURE |
+ SOF_PCM512X_ENABLE_DMIC;
static bool is_legacy_cpu;
@@ -244,8 +249,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].dpcm_playback = 1;
/*
* capture only supported with specific versions of the Hifiberry DAC+
- * links[id].dpcm_capture = 1;
*/
+ if (sof_pcm512x_quirk & SOF_PCM512X_ENABLE_SSP_CAPTURE)
+ links[id].dpcm_capture = 1;
links[id].no_pcm = 1;
links[id].cpus = &cpus[id];
links[id].num_cpus = 1;
@@ -380,6 +386,9 @@ static int sof_audio_probe(struct platform_device *pdev)
ssp_codec = sof_pcm512x_quirk & SOF_PCM512X_SSP_CODEC_MASK;
+ if (!(sof_pcm512x_quirk & SOF_PCM512X_ENABLE_DMIC))
+ dmic_be_num = 0;
+
/* compute number of dai links */
sof_audio_card_pcm512x.num_links = 1 + dmic_be_num + hdmi_num;
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 39217223d50c..f096bd6d69be 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -162,6 +162,20 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
SOF_RT5682_SSP_AMP(2) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
+ {
+ .callback = sof_rt5682_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
+ DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
+ },
+ .driver_data = (void *)(SOF_RT5682_MCLK_EN |
+ SOF_RT5682_SSP_CODEC(0) |
+ SOF_SPEAKER_AMP_PRESENT |
+ SOF_MAX98373_SPEAKER_AMP_PRESENT |
+ SOF_RT5682_SSP_AMP(2) |
+ SOF_RT5682_NUM_HDMIDEV(4)),
+ },
{}
};
@@ -456,10 +470,6 @@ static const struct snd_kcontrol_new sof_controls[] = {
};
-static const struct snd_kcontrol_new speaker_controls[] = {
- SOC_DAPM_PIN_SWITCH("Spk"),
-};
-
static const struct snd_soc_dapm_widget sof_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
@@ -467,10 +477,6 @@ static const struct snd_soc_dapm_widget sof_widgets[] = {
SND_SOC_DAPM_SPK("Right Spk", NULL),
};
-static const struct snd_soc_dapm_widget speaker_widgets[] = {
- SND_SOC_DAPM_SPK("Spk", NULL),
-};
-
static const struct snd_soc_dapm_widget dmic_widgets[] = {
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
};
@@ -484,11 +490,6 @@ static const struct snd_soc_dapm_route sof_map[] = {
{ "IN1P", NULL, "Headset Mic" },
};
-static const struct snd_soc_dapm_route speaker_map[] = {
- /* speaker */
- { "Spk", NULL, "Speaker" },
-};
-
static const struct snd_soc_dapm_route speaker_map_lr[] = {
{ "Left Spk", NULL, "Left SPO" },
{ "Right Spk", NULL, "Right SPO" },
@@ -505,34 +506,6 @@ static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
ARRAY_SIZE(speaker_map_lr));
}
-static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
- int ret;
-
- ret = snd_soc_dapm_new_controls(&card->dapm, speaker_widgets,
- ARRAY_SIZE(speaker_widgets));
- if (ret) {
- dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret);
- /* Don't need to add routes if widget addition failed */
- return ret;
- }
-
- ret = snd_soc_add_card_controls(card, speaker_controls,
- ARRAY_SIZE(speaker_controls));
- if (ret) {
- dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
- return ret;
- }
-
- ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map,
- ARRAY_SIZE(speaker_map));
-
- if (ret)
- dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
- return ret;
-}
-
static int dmic_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
@@ -594,13 +567,6 @@ static struct snd_soc_dai_link_component dmic_component[] = {
}
};
-static struct snd_soc_dai_link_component max98360a_component[] = {
- {
- .name = "MX98360A:00",
- .dai_name = "HiFi",
- }
-};
-
static struct snd_soc_dai_link_component rt1015_components[] = {
{
.name = "i2c-10EC1015:00",
@@ -775,9 +741,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].dpcm_capture = 1;
} else if (sof_rt5682_quirk &
SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
- links[id].codecs = max98360a_component;
- links[id].num_codecs = ARRAY_SIZE(max98360a_component);
- links[id].init = speaker_codec_init;
+ max_98360a_dai_link(&links[id]);
} else if (sof_rt5682_quirk &
SOF_RT1011_SPEAKER_AMP_PRESENT) {
sof_rt1011_dai_link(&links[id]);
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 1a867c73a48e..6602eda89e8e 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -13,8 +13,9 @@
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include "sof_sdw_common.h"
+#include "../../codecs/rt711.h"
-unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1;
+unsigned long sof_sdw_quirk = RT711_JD1;
static int quirk_override = -1;
module_param_named(quirk, quirk_override, int, 0444);
MODULE_PARM_DESC(quirk, "Board-specific quirk override");
@@ -63,7 +64,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
},
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
+ .driver_data = (void *)(RT711_JD2 |
SOF_RT715_DAI_ID_FIX),
},
{
@@ -73,7 +74,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
},
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
+ .driver_data = (void *)(RT711_JD2 |
SOF_RT715_DAI_ID_FIX),
},
{
@@ -82,7 +83,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
},
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
+ .driver_data = (void *)(RT711_JD2 |
SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK),
},
@@ -92,7 +93,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
},
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
+ .driver_data = (void *)(RT711_JD2 |
SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK),
},
@@ -114,7 +115,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
"Tiger Lake Client Platform"),
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOF_RT711_JD_SRC_JD1 |
+ RT711_JD1 |
SOF_SDW_PCH_DMIC |
SOF_SSP_PORT(SOF_I2S_SSP2)),
},
@@ -125,17 +126,29 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOF_RT711_JD_SRC_JD2 |
+ RT711_JD2 |
SOF_RT715_DAI_ID_FIX),
},
{
+ /* Dell XPS 9710 */
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
+ },
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ RT711_JD2 |
+ SOF_RT715_DAI_ID_FIX |
+ SOF_SDW_FOUR_SPK),
+ },
+ {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOF_RT711_JD_SRC_JD2 |
+ RT711_JD2 |
SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK),
},
@@ -175,7 +188,18 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
SOF_SDW_PCH_DMIC |
- SOF_RT711_JD_SRC_JD2),
+ RT711_JD2),
+ },
+ {
+ /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
+ },
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_SDW_PCH_DMIC |
+ RT711_JD1),
},
/* TigerLake-SDCA devices */
{
@@ -185,7 +209,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
},
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOF_RT711_JD_SRC_JD2 |
+ RT711_JD2 |
SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK),
},
@@ -196,7 +220,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
},
- .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
+ .driver_data = (void *)(RT711_JD2_100K |
SOF_SDW_TGL_HDMI |
SOF_RT715_DAI_ID_FIX |
SOF_BT_OFFLOAD_SSP(2) |
@@ -328,6 +352,20 @@ static const struct snd_soc_ops sdw_ops = {
.shutdown = sdw_shutdown,
};
+static int sof_sdw_mic_codec_mockup_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
+ struct snd_soc_dai_link *dai_links,
+ struct sof_sdw_codec_info *info,
+ bool playback)
+{
+ /*
+ * force DAI link to use same ID as RT715 and DMIC
+ * to reuse topologies
+ */
+ dai_links->id = SDW_DMIC_DAI_ID;
+ return 0;
+}
+
static struct sof_sdw_codec_info codec_info_list[] = {
{
.part_id = 0x700,
@@ -410,6 +448,34 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt5682-sdw",
.init = sof_sdw_rt5682_init,
},
+ {
+ .part_id = 0xaaaa, /* generic codec mockup */
+ .version_id = 0,
+ .direction = {true, true},
+ .dai_name = "sdw-mockup-aif1",
+ .init = NULL,
+ },
+ {
+ .part_id = 0xaa55, /* headset codec mockup */
+ .version_id = 0,
+ .direction = {true, true},
+ .dai_name = "sdw-mockup-aif1",
+ .init = NULL,
+ },
+ {
+ .part_id = 0x55aa, /* amplifier mockup */
+ .version_id = 0,
+ .direction = {true, false},
+ .dai_name = "sdw-mockup-aif1",
+ .init = NULL,
+ },
+ {
+ .part_id = 0x5555,
+ .version_id = 0,
+ .direction = {false, true},
+ .dai_name = "sdw-mockup-aif1",
+ .init = sof_sdw_mic_codec_mockup_init,
+ },
};
static inline int find_codec_info_part(u64 adr)
@@ -632,7 +698,8 @@ static int create_codec_dai_name(struct device *dev,
return 0;
}
-static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
+static int set_codec_init_func(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
bool playback, int group_id)
{
@@ -655,7 +722,8 @@ static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
if (link->adr_d[i].endpoints->group_id != group_id)
continue;
if (codec_info_list[codec_index].init)
- codec_info_list[codec_index].init(link,
+ codec_info_list[codec_index].init(card,
+ link,
dai_links,
&codec_info_list[codec_index],
playback);
@@ -740,7 +808,8 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
return 0;
}
-static int create_sdw_dailink(struct device *dev, int *be_index,
+static int create_sdw_dailink(struct snd_soc_card *card,
+ struct device *dev, int *be_index,
struct snd_soc_dai_link *dai_links,
int sdw_be_num, int sdw_cpu_dai_num,
struct snd_soc_dai_link_component *cpus,
@@ -861,7 +930,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
codecs, codec_num,
NULL, &sdw_ops);
- ret = set_codec_init_func(link, dai_links + (*be_index)++,
+ ret = set_codec_init_func(card, link, dai_links + (*be_index)++,
playback, group_id);
if (ret < 0) {
dev_err(dev, "failed to init codec %d", codec_index);
@@ -1042,7 +1111,7 @@ static int sof_card_dai_links_create(struct device *dev,
group_generated[endpoint->group_id])
continue;
- ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num,
+ ret = create_sdw_dailink(card, dev, &be_id, links, sdw_be_num,
sdw_cpu_dai_num, cpus, adr_link,
&cpu_id, group_generated,
codec_conf, codec_conf_count,
@@ -1105,7 +1174,7 @@ SSP:
ssp_components, 1,
NULL, info->ops);
- ret = info->init(NULL, links + link_id, info, 0);
+ ret = info->init(card, NULL, links + link_id, info, 0);
if (ret < 0)
return ret;
@@ -1328,7 +1397,7 @@ static int mc_remove(struct platform_device *pdev)
for_each_card_prelinks(card, j, link) {
if (!strcmp(link->codecs[0].dai_name,
codec_info_list[i].dai_name)) {
- ret = codec_info_list[i].exit(&pdev->dev, link);
+ ret = codec_info_list[i].exit(card, link);
if (ret)
dev_warn(&pdev->dev,
"codec exit failed %d\n",
diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h
index ec5740486b75..b35f5a9b96f5 100644
--- a/sound/soc/intel/boards/sof_sdw_common.h
+++ b/sound/soc/intel/boards/sof_sdw_common.h
@@ -23,11 +23,6 @@
#define SDW_MAX_GROUPS 9
enum {
- SOF_RT711_JD_SRC_JD1 = 1,
- SOF_RT711_JD_SRC_JD2 = 2,
-};
-
-enum {
SOF_PRE_TGL_HDMI_COUNT = 3,
SOF_TGL_HDMI_COUNT = 4,
};
@@ -41,21 +36,21 @@ enum {
SOF_I2S_SSP5 = BIT(5),
};
-#define SOF_RT711_JDSRC(quirk) ((quirk) & GENMASK(1, 0))
-#define SOF_SDW_FOUR_SPK BIT(2)
-#define SOF_SDW_TGL_HDMI BIT(3)
-#define SOF_SDW_PCH_DMIC BIT(4)
-#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 5)
-#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 5) & GENMASK(5, 0))
-#define SOF_RT715_DAI_ID_FIX BIT(11)
-#define SOF_SDW_NO_AGGREGATION BIT(12)
+#define SOF_RT711_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
+#define SOF_SDW_FOUR_SPK BIT(4)
+#define SOF_SDW_TGL_HDMI BIT(5)
+#define SOF_SDW_PCH_DMIC BIT(6)
+#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7)
+#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0))
+#define SOF_RT715_DAI_ID_FIX BIT(13)
+#define SOF_SDW_NO_AGGREGATION BIT(14)
/* BT audio offload: reserve 3 bits for future */
-#define SOF_BT_OFFLOAD_SSP_SHIFT 13
-#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(15, 13))
+#define SOF_BT_OFFLOAD_SSP_SHIFT 15
+#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(17, 15))
#define SOF_BT_OFFLOAD_SSP(quirk) \
(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
-#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(16)
+#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(18)
struct sof_sdw_codec_info {
const int part_id;
@@ -67,12 +62,13 @@ struct sof_sdw_codec_info {
const char *dai_name;
const struct snd_soc_ops *ops;
- int (*init)(const struct snd_soc_acpi_link_adr *link,
+ int (*init)(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
- int (*exit)(struct device *dev, struct snd_soc_dai_link *dai_link);
+ int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
bool late_probe;
int (*codec_card_late_probe)(struct snd_soc_card *card);
};
@@ -81,6 +77,7 @@ struct mc_private {
struct list_head hdmi_pcm_list;
bool idisp_codec;
struct snd_soc_jack sdw_headset;
+ struct device *headset_codec_dev; /* only one headset per card */
};
extern unsigned long sof_sdw_quirk;
@@ -100,21 +97,24 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card);
int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd);
/* RT711 support */
-int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt711_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
-int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link);
+int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
/* RT711-SDCA support */
-int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
-int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link);
+int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
/* RT700 support */
-int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt700_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
@@ -122,31 +122,36 @@ int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
/* RT1308 support */
extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops;
-int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt1308_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
/* RT1316 support */
-int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt1316_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
/* RT715 support */
-int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt715_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
/* RT715-SDCA support */
-int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
/* MAX98373 support */
-int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_mx8373_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
@@ -154,7 +159,8 @@ int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
int sof_sdw_mx8373_late_probe(struct snd_soc_card *card);
/* RT5682 support */
-int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt5682_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c
index 25daef910aee..77a3f32db11e 100644
--- a/sound/soc/intel/boards/sof_sdw_max98373.c
+++ b/sound/soc/intel/boards/sof_sdw_max98373.c
@@ -90,7 +90,7 @@ static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enabl
static int mx8373_sdw_prepare(struct snd_pcm_substream *substream)
{
- int ret = 0;
+ int ret;
/* according to soc_pcm_prepare dai link prepare is called first */
ret = sdw_prepare(substream);
@@ -102,7 +102,7 @@ static int mx8373_sdw_prepare(struct snd_pcm_substream *substream)
static int mx8373_sdw_hw_free(struct snd_pcm_substream *substream)
{
- int ret = 0;
+ int ret;
/* according to soc_pcm_hw_free dai link free is called first */
ret = sdw_hw_free(substream);
@@ -120,7 +120,8 @@ static const struct snd_soc_ops max_98373_sdw_ops = {
.shutdown = sdw_shutdown,
};
-int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_mx8373_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c
index 0d476f6f6313..f078fb1aad02 100644
--- a/sound/soc/intel/boards/sof_sdw_rt1308.c
+++ b/sound/soc/intel/boards/sof_sdw_rt1308.c
@@ -127,7 +127,8 @@ struct snd_soc_ops sof_sdw_rt1308_i2s_ops = {
.hw_params = rt1308_i2s_hw_params,
};
-int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt1308_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt1316.c b/sound/soc/intel/boards/sof_sdw_rt1316.c
index d6e1ebf18d57..58194b380232 100644
--- a/sound/soc/intel/boards/sof_sdw_rt1316.c
+++ b/sound/soc/intel/boards/sof_sdw_rt1316.c
@@ -89,7 +89,8 @@ static int all_spk_init(struct snd_soc_pcm_runtime *rtd)
return second_spk_init(rtd);
}
-int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt1316_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c
index 5fa1a59615b6..ea55479609a8 100644
--- a/sound/soc/intel/boards/sof_sdw_rt5682.c
+++ b/sound/soc/intel/boards/sof_sdw_rt5682.c
@@ -111,7 +111,8 @@ static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt5682_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c
index 21e7e4a81779..bb9584c8f866 100644
--- a/sound/soc/intel/boards/sof_sdw_rt700.c
+++ b/sound/soc/intel/boards/sof_sdw_rt700.c
@@ -110,7 +110,8 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt700_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c
index 04074c09dded..c38b70c9fac3 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711.c
@@ -21,23 +21,23 @@
* Note this MUST be called before snd_soc_register_card(), so that the props
* are in place before the codec component driver's probe function parses them.
*/
-static int rt711_add_codec_device_props(const char *sdw_dev_name)
+static int rt711_add_codec_device_props(struct device *sdw_dev)
{
struct property_entry props[MAX_NO_PROPS] = {};
- struct device *sdw_dev;
+ struct fwnode_handle *fwnode;
int ret;
- sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name);
- if (!sdw_dev)
- return -EPROBE_DEFER;
+ if (!SOF_RT711_JDSRC(sof_sdw_quirk))
+ return 0;
+ props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
- if (SOF_RT711_JDSRC(sof_sdw_quirk)) {
- props[0] = PROPERTY_ENTRY_U32("realtek,jd-src",
- SOF_RT711_JDSRC(sof_sdw_quirk));
- }
+ fwnode = fwnode_create_software_node(props, NULL);
+ if (IS_ERR(fwnode))
+ return PTR_ERR(fwnode);
+
+ ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
- ret = device_add_properties(sdw_dev, props);
- put_device(sdw_dev);
+ fwnode_handle_put(fwnode);
return ret;
}
@@ -135,26 +135,24 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link)
+int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
- struct device *sdw_dev;
-
- sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL,
- dai_link->codecs[0].name);
- if (!sdw_dev)
- return -EINVAL;
+ struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- device_remove_properties(sdw_dev);
- put_device(sdw_dev);
+ device_remove_software_node(ctx->headset_codec_dev);
+ put_device(ctx->headset_codec_dev);
return 0;
}
-int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt711_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
{
+ struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct device *sdw_dev;
int ret;
/*
@@ -164,9 +162,16 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
if (!playback)
return 0;
- ret = rt711_add_codec_device_props(dai_links->codecs[0].name);
- if (ret < 0)
+ sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
+ if (!sdw_dev)
+ return -EPROBE_DEFER;
+
+ ret = rt711_add_codec_device_props(sdw_dev);
+ if (ret < 0) {
+ put_device(sdw_dev);
return ret;
+ }
+ ctx->headset_codec_dev = sdw_dev;
dai_links->init = rt711_rtd_init;
diff --git a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
index 19496f0f9110..4215ddc36419 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c
@@ -21,23 +21,24 @@
* Note this MUST be called before snd_soc_register_card(), so that the props
* are in place before the codec component driver's probe function parses them.
*/
-static int rt711_sdca_add_codec_device_props(const char *sdw_dev_name)
+static int rt711_sdca_add_codec_device_props(struct device *sdw_dev)
{
struct property_entry props[MAX_NO_PROPS] = {};
- struct device *sdw_dev;
+ struct fwnode_handle *fwnode;
int ret;
- sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name);
- if (!sdw_dev)
- return -EPROBE_DEFER;
+ if (!SOF_RT711_JDSRC(sof_sdw_quirk))
+ return 0;
- if (SOF_RT711_JDSRC(sof_sdw_quirk)) {
- props[0] = PROPERTY_ENTRY_U32("realtek,jd-src",
- SOF_RT711_JDSRC(sof_sdw_quirk));
- }
+ props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
- ret = device_add_properties(sdw_dev, props);
- put_device(sdw_dev);
+ fwnode = fwnode_create_software_node(props, NULL);
+ if (IS_ERR(fwnode))
+ return PTR_ERR(fwnode);
+
+ ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
+
+ fwnode_handle_put(fwnode);
return ret;
}
@@ -135,26 +136,24 @@ static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link)
+int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
- struct device *sdw_dev;
-
- sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL,
- dai_link->codecs[0].name);
- if (!sdw_dev)
- return -EINVAL;
+ struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- device_remove_properties(sdw_dev);
- put_device(sdw_dev);
+ device_remove_software_node(ctx->headset_codec_dev);
+ put_device(ctx->headset_codec_dev);
return 0;
}
-int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
{
+ struct mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct device *sdw_dev;
int ret;
/*
@@ -164,9 +163,16 @@ int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
if (!playback)
return 0;
- ret = rt711_sdca_add_codec_device_props(dai_links->codecs[0].name);
- if (ret < 0)
+ sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
+ if (!sdw_dev)
+ return -EPROBE_DEFER;
+
+ ret = rt711_sdca_add_codec_device_props(sdw_dev);
+ if (ret < 0) {
+ put_device(sdw_dev);
return ret;
+ }
+ ctx->headset_codec_dev = sdw_dev;
dai_links->init = rt711_sdca_rtd_init;
diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c
index 9b298f79e784..c8af3780cbc3 100644
--- a/sound/soc/intel/boards/sof_sdw_rt715.c
+++ b/sound/soc/intel/boards/sof_sdw_rt715.c
@@ -24,7 +24,8 @@ static int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt715_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
index c056e56a139b..85d3d8c355cc 100644
--- a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
@@ -24,7 +24,8 @@ static int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link,
+int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
+ const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback)
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
index 12a205ccdeeb..fef0b2d1de68 100644
--- a/sound/soc/intel/common/Makefile
+++ b/sound/soc/intel/common/Makefile
@@ -9,7 +9,8 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m
soc-acpi-intel-cml-match.o soc-acpi-intel-icl-match.o \
soc-acpi-intel-tgl-match.o soc-acpi-intel-ehl-match.o \
soc-acpi-intel-jsl-match.o soc-acpi-intel-adl-match.o \
- soc-acpi-intel-hda-match.o
+ soc-acpi-intel-hda-match.o \
+ soc-acpi-intel-sdw-mockup-match.o
obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o
diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
index 42ef51c3fb4f..b591c6fd13fd 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
@@ -75,7 +75,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
},
{
.id = "DLGS7219",
- .drv_name = "cml_da7219_max98357a",
+ .drv_name = "cml_da7219_mx98357a",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &max98390_spk_codecs,
.sof_fw_filename = "sof-cml.ri",
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index 39dad32564e6..94b650767e11 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -9,6 +9,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
#include "../skylake/skl.h"
+#include "soc-acpi-intel-sdw-mockup-match.h"
static struct skl_machine_pdata cnl_pdata = {
.use_tplg_pcm = true,
@@ -60,6 +61,20 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[] = {
.sof_fw_filename = "sof-cnl.ri",
.sof_tplg_filename = "sof-cnl-rt5682-sdw2.tplg"
},
+ {
+ .link_mask = GENMASK(3, 0),
+ .links = sdw_mockup_headset_2amps_mic,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-cnl.ri",
+ .sof_tplg_filename = "sof-cml-rt711-rt1308-rt715.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1) | BIT(3),
+ .links = sdw_mockup_headset_1amp_mic,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-cnl.ri",
+ .sof_tplg_filename = "sof-cml-rt711-rt1308-mono-rt715.tplg",
+ },
{}
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_sdw_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 3586ce72c42c..69ff7286d357 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -73,6 +73,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
.quirk_data = &mx98360a_spk,
.sof_tplg_filename = "sof-jsl-rt5682-mx98360a.tplg",
},
+ {
+ .id = "10134242",
+ .drv_name = "jsl_cs4242_mx98360a",
+ .sof_fw_filename = "sof-jsl.ri",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &mx98360a_spk,
+ .sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
index ba5ff468c265..741bf2f9e081 100644
--- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c
@@ -87,7 +87,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = {
},
{
.id = "DLGS7219",
- .drv_name = "kbl_da7219_max98357a",
+ .drv_name = "kbl_da7219_mx98357a",
.fw_filename = "intel/dsp_fw_kbl.bin",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &kbl_7219_98357_codecs,
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c
new file mode 100644
index 000000000000..a3d33997736a
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// soc-acpi-intel-sdw-mockup-match.c - tables and support for SoundWire
+// mockup device ACPI enumeration.
+//
+// Copyright (c) 2021, Intel Corporation.
+//
+
+#include <sound/soc-acpi.h>
+#include <sound/soc-acpi-intel-match.h>
+#include "soc-acpi-intel-sdw-mockup-match.h"
+
+static const struct snd_soc_acpi_endpoint sdw_mockup_single_endpoint = {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+};
+
+static const struct snd_soc_acpi_endpoint sdw_mockup_l_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 0,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_endpoint sdw_mockup_r_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 1,
+ .group_id = 1,
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_headset_0_adr[] = {
+ {
+ .adr = 0x0000000105AA5500ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_headset0"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_headset_1_adr[] = {
+ {
+ .adr = 0x0001000105AA5500ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_headset1"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_amp_1_adr[] = {
+ {
+ .adr = 0x000100010555AA00ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_amp1"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_adr[] = {
+ {
+ .adr = 0x000200010555AA00ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_amp2"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_mic_0_adr[] = {
+ {
+ .adr = 0x0000000105555500ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_mic0"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_mic_3_adr[] = {
+ {
+ .adr = 0x0003000105555500ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_single_endpoint,
+ .name_prefix = "sdw_mockup_mic3"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_amp_1_group1_adr[] = {
+ {
+ .adr = 0x000100010555AA00ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_l_endpoint,
+ .name_prefix = "sdw_mockup_amp1_l"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_group1_adr[] = {
+ {
+ .adr = 0x000200010555AA00ull,
+ .num_endpoints = 1,
+ .endpoints = &sdw_mockup_r_endpoint,
+ .name_prefix = "sdw_mockup_amp2_r"
+ }
+};
+
+const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(sdw_mockup_headset_0_adr),
+ .adr_d = sdw_mockup_headset_0_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(sdw_mockup_amp_1_adr),
+ .adr_d = sdw_mockup_amp_1_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(sdw_mockup_mic_3_adr),
+ .adr_d = sdw_mockup_mic_3_adr,
+ },
+ {}
+};
+
+const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(sdw_mockup_headset_0_adr),
+ .adr_d = sdw_mockup_headset_0_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(sdw_mockup_amp_1_group1_adr),
+ .adr_d = sdw_mockup_amp_1_group1_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(sdw_mockup_amp_2_group1_adr),
+ .adr_d = sdw_mockup_amp_2_group1_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(sdw_mockup_mic_3_adr),
+ .adr_d = sdw_mockup_mic_3_adr,
+ },
+ {}
+};
+
+const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[] = {
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(sdw_mockup_headset_1_adr),
+ .adr_d = sdw_mockup_headset_1_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(sdw_mockup_amp_2_adr),
+ .adr_d = sdw_mockup_amp_2_adr,
+ },
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(sdw_mockup_mic_0_adr),
+ .adr_d = sdw_mockup_mic_0_adr,
+ },
+ {}
+};
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h
new file mode 100644
index 000000000000..c99eecd19e03
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * soc-acpi-intel-sdw-mockup-match.h - tables and support for SoundWire
+ * mockup device ACPI enumeration.
+ *
+ * Copyright (c) 2021, Intel Corporation.
+ *
+ */
+
+#ifndef _SND_SOC_ACPI_INTEL_SDW_MOCKUP_MATCH
+#define _SND_SOC_ACPI_INTEL_SDW_MOCKUP_MATCH
+
+extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[];
+extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[];
+extern const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[];
+
+#endif
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index 66595e3ab13f..785d5f5f8a9c 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -8,6 +8,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
+#include "soc-acpi-intel-sdw-mockup-match.h"
static const struct snd_soc_acpi_codecs tgl_codecs = {
.num_codecs = 1,
@@ -196,6 +197,15 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = {
{}
};
+static const struct snd_soc_acpi_link_adr tgl_rvp_headset_only[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt711_0_adr),
+ .adr_d = rt711_0_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr tgl_hp[] = {
{
.mask = BIT(0),
@@ -351,6 +361,28 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
+ /* mockup tests need to be first */
+ {
+ .link_mask = GENMASK(3, 0),
+ .links = sdw_mockup_headset_2amps_mic,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-tgl.ri",
+ .sof_tplg_filename = "sof-tgl-rt711-rt1308-rt715.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1) | BIT(3),
+ .links = sdw_mockup_headset_1amp_mic,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-tgl.ri",
+ .sof_tplg_filename = "sof-tgl-rt711-rt1308-mono-rt715.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1) | BIT(2),
+ .links = sdw_mockup_mic_headset_1amp,
+ .drv_name = "sof_sdw",
+ .sof_fw_filename = "sof-tgl.ri",
+ .sof_tplg_filename = "sof-tgl-rt715-rt711-rt1308-mono.tplg",
+ },
{
.link_mask = 0x7,
.links = tgl_sdw_rt711_link1_rt1308_link2_rt715_link0,
@@ -398,6 +430,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg",
},
+ {
+ .link_mask = 0x1, /* rt711 on link 0 */
+ .links = tgl_rvp_headset_only,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-tgl-rt711.tplg",
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines);
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c
index 476ef1897961..eaad180af42e 100644
--- a/sound/soc/intel/skylake/skl-messages.c
+++ b/sound/soc/intel/skylake/skl-messages.c
@@ -472,6 +472,75 @@ static void skl_set_base_module_format(struct skl_dev *skl,
base_cfg->is_pages = res->is_pages;
}
+static void fill_pin_params(struct skl_audio_data_format *pin_fmt,
+ struct skl_module_fmt *format)
+{
+ pin_fmt->number_of_channels = format->channels;
+ pin_fmt->s_freq = format->s_freq;
+ pin_fmt->bit_depth = format->bit_depth;
+ pin_fmt->valid_bit_depth = format->valid_bit_depth;
+ pin_fmt->ch_cfg = format->ch_cfg;
+ pin_fmt->sample_type = format->sample_type;
+ pin_fmt->channel_map = format->ch_map;
+ pin_fmt->interleaving = format->interleaving_style;
+}
+
+/*
+ * Any module configuration begins with a base module configuration but
+ * can be followed by a generic extension containing audio format for all
+ * module's pins that are in use.
+ */
+static void skl_set_base_ext_module_format(struct skl_dev *skl,
+ struct skl_module_cfg *mconfig,
+ struct skl_base_cfg_ext *base_cfg_ext)
+{
+ struct skl_module *module = mconfig->module;
+ struct skl_module_pin_resources *pin_res;
+ struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx];
+ struct skl_module_res *res = &module->resources[mconfig->res_idx];
+ struct skl_module_fmt *format;
+ struct skl_pin_format *pin_fmt;
+ char *params;
+ int i;
+
+ base_cfg_ext->nr_input_pins = res->nr_input_pins;
+ base_cfg_ext->nr_output_pins = res->nr_output_pins;
+ base_cfg_ext->priv_param_length =
+ mconfig->formats_config[SKL_PARAM_INIT].caps_size;
+
+ for (i = 0; i < res->nr_input_pins; i++) {
+ pin_res = &res->input[i];
+ pin_fmt = &base_cfg_ext->pins_fmt[i];
+
+ pin_fmt->pin_idx = pin_res->pin_index;
+ pin_fmt->buf_size = pin_res->buf_size;
+
+ format = &fmt->inputs[pin_res->pin_index].fmt;
+ fill_pin_params(&pin_fmt->audio_fmt, format);
+ }
+
+ for (i = 0; i < res->nr_output_pins; i++) {
+ pin_res = &res->output[i];
+ pin_fmt = &base_cfg_ext->pins_fmt[res->nr_input_pins + i];
+
+ pin_fmt->pin_idx = pin_res->pin_index;
+ pin_fmt->buf_size = pin_res->buf_size;
+
+ format = &fmt->outputs[pin_res->pin_index].fmt;
+ fill_pin_params(&pin_fmt->audio_fmt, format);
+ }
+
+ if (!base_cfg_ext->priv_param_length)
+ return;
+
+ params = (char *)base_cfg_ext + sizeof(struct skl_base_cfg_ext);
+ params += (base_cfg_ext->nr_input_pins + base_cfg_ext->nr_output_pins) *
+ sizeof(struct skl_pin_format);
+
+ memcpy(params, mconfig->formats_config[SKL_PARAM_INIT].caps,
+ mconfig->formats_config[SKL_PARAM_INIT].caps_size);
+}
+
/*
* Copies copier capabilities into copier module and updates copier module
* config size.
@@ -479,15 +548,15 @@ static void skl_set_base_module_format(struct skl_dev *skl,
static void skl_copy_copier_caps(struct skl_module_cfg *mconfig,
struct skl_cpr_cfg *cpr_mconfig)
{
- if (mconfig->formats_config.caps_size == 0)
+ if (mconfig->formats_config[SKL_PARAM_INIT].caps_size == 0)
return;
memcpy(cpr_mconfig->gtw_cfg.config_data,
- mconfig->formats_config.caps,
- mconfig->formats_config.caps_size);
+ mconfig->formats_config[SKL_PARAM_INIT].caps,
+ mconfig->formats_config[SKL_PARAM_INIT].caps_size);
cpr_mconfig->gtw_cfg.config_length =
- (mconfig->formats_config.caps_size) / 4;
+ (mconfig->formats_config[SKL_PARAM_INIT].caps_size) / 4;
}
#define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF
@@ -738,28 +807,6 @@ static void skl_set_copier_format(struct skl_dev *skl,
}
/*
- * Algo module are DSP pre processing modules. Algo module take base module
- * configuration and params
- */
-
-static void skl_set_algo_format(struct skl_dev *skl,
- struct skl_module_cfg *mconfig,
- struct skl_algo_cfg *algo_mcfg)
-{
- struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg;
-
- skl_set_base_module_format(skl, mconfig, base_cfg);
-
- if (mconfig->formats_config.caps_size == 0)
- return;
-
- memcpy(algo_mcfg->params,
- mconfig->formats_config.caps,
- mconfig->formats_config.caps_size);
-
-}
-
-/*
* Mic select module allows selecting one or many input channels, thus
* acting as a demux.
*
@@ -781,12 +828,14 @@ static void skl_set_base_outfmt_format(struct skl_dev *skl,
static u16 skl_get_module_param_size(struct skl_dev *skl,
struct skl_module_cfg *mconfig)
{
+ struct skl_module_res *res;
+ struct skl_module *module = mconfig->module;
u16 param_size;
switch (mconfig->m_type) {
case SKL_MODULE_TYPE_COPIER:
param_size = sizeof(struct skl_cpr_cfg);
- param_size += mconfig->formats_config.caps_size;
+ param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size;
return param_size;
case SKL_MODULE_TYPE_SRCINT:
@@ -795,22 +844,24 @@ static u16 skl_get_module_param_size(struct skl_dev *skl,
case SKL_MODULE_TYPE_UPDWMIX:
return sizeof(struct skl_up_down_mixer_cfg);
- case SKL_MODULE_TYPE_ALGO:
- param_size = sizeof(struct skl_base_cfg);
- param_size += mconfig->formats_config.caps_size;
- return param_size;
-
case SKL_MODULE_TYPE_BASE_OUTFMT:
case SKL_MODULE_TYPE_MIC_SELECT:
- case SKL_MODULE_TYPE_KPB:
return sizeof(struct skl_base_outfmt_cfg);
- default:
- /*
- * return only base cfg when no specific module type is
- * specified
- */
+ case SKL_MODULE_TYPE_MIXER:
+ case SKL_MODULE_TYPE_KPB:
return sizeof(struct skl_base_cfg);
+
+ case SKL_MODULE_TYPE_ALGO:
+ default:
+ res = &module->resources[mconfig->res_idx];
+
+ param_size = sizeof(struct skl_base_cfg) + sizeof(struct skl_base_cfg_ext);
+ param_size += (res->nr_input_pins + res->nr_output_pins) *
+ sizeof(struct skl_pin_format);
+ param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size;
+
+ return param_size;
}
return 0;
@@ -851,20 +902,23 @@ static int skl_set_module_format(struct skl_dev *skl,
skl_set_updown_mixer_format(skl, module_config, *param_data);
break;
- case SKL_MODULE_TYPE_ALGO:
- skl_set_algo_format(skl, module_config, *param_data);
- break;
-
case SKL_MODULE_TYPE_BASE_OUTFMT:
case SKL_MODULE_TYPE_MIC_SELECT:
- case SKL_MODULE_TYPE_KPB:
skl_set_base_outfmt_format(skl, module_config, *param_data);
break;
- default:
+ case SKL_MODULE_TYPE_MIXER:
+ case SKL_MODULE_TYPE_KPB:
skl_set_base_module_format(skl, module_config, *param_data);
break;
+ case SKL_MODULE_TYPE_ALGO:
+ default:
+ skl_set_base_module_format(skl, module_config, *param_data);
+ skl_set_base_ext_module_format(skl, module_config,
+ *param_data +
+ sizeof(struct skl_base_cfg));
+ break;
}
dev_dbg(skl->dev, "Module type=%d id=%d config size: %d bytes\n",
@@ -1085,19 +1139,6 @@ int skl_unbind_modules(struct skl_dev *skl,
return ret;
}
-static void fill_pin_params(struct skl_audio_data_format *pin_fmt,
- struct skl_module_fmt *format)
-{
- pin_fmt->number_of_channels = format->channels;
- pin_fmt->s_freq = format->s_freq;
- pin_fmt->bit_depth = format->bit_depth;
- pin_fmt->valid_bit_depth = format->valid_bit_depth;
- pin_fmt->ch_cfg = format->ch_cfg;
- pin_fmt->sample_type = format->sample_type;
- pin_fmt->channel_map = format->ch_map;
- pin_fmt->interleaving = format->interleaving_style;
-}
-
#define CPR_SINK_FMT_PARAM_ID 2
/*
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index b1ca64d2f7ea..9ecaf6a1e847 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -1214,13 +1214,6 @@ static snd_pcm_uframes_t skl_platform_soc_pointer(
return bytes_to_frames(substream->runtime, pos);
}
-static int skl_platform_soc_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *area)
-{
- return snd_pcm_lib_default_mmap(substream, area);
-}
-
static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
u64 nsec)
{
@@ -1317,21 +1310,6 @@ static int skl_get_module_info(struct skl_dev *skl,
return -EIO;
}
- list_for_each_entry(module, &skl->uuid_list, list) {
- if (guid_equal(uuid_mod, &module->uuid)) {
- mconfig->id.module_id = module->id;
- if (mconfig->module)
- mconfig->module->loadable = module->is_loadable;
- ret = 0;
- break;
- }
- }
-
- if (ret)
- return ret;
-
- uuid_mod = &module->uuid;
- ret = -EIO;
for (i = 0; i < skl->nr_modules; i++) {
skl_module = skl->modules[i];
uuid_tplg = &skl_module->uuid;
@@ -1341,10 +1319,18 @@ static int skl_get_module_info(struct skl_dev *skl,
break;
}
}
+
if (skl->nr_modules && ret)
return ret;
+ ret = -EIO;
list_for_each_entry(module, &skl->uuid_list, list) {
+ if (guid_equal(uuid_mod, &module->uuid)) {
+ mconfig->id.module_id = module->id;
+ mconfig->module->loadable = module->is_loadable;
+ ret = 0;
+ }
+
for (i = 0; i < MAX_IN_QUEUE; i++) {
pin_id = &mconfig->m_in_pin[i].id;
if (guid_equal(&pin_id->mod_uuid, &module->uuid))
@@ -1358,7 +1344,7 @@ static int skl_get_module_info(struct skl_dev *skl,
}
}
- return 0;
+ return ret;
}
static int skl_populate_modules(struct skl_dev *skl)
@@ -1460,7 +1446,6 @@ static const struct snd_soc_component_driver skl_component = {
.trigger = skl_platform_soc_trigger,
.pointer = skl_platform_soc_pointer,
.get_time_info = skl_platform_soc_get_time_info,
- .mmap = skl_platform_soc_mmap,
.pcm_construct = skl_platform_soc_new,
.module_get_upon_open = 1, /* increment refcount when a pcm is opened */
};
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index c0fdab39e7c2..b036852d6889 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -113,7 +113,7 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w,
static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg)
{
- struct skl_module_iface *iface = &mcfg->module->formats[0];
+ struct skl_module_iface *iface = &mcfg->module->formats[mcfg->fmt_idx];
dev_dbg(skl->dev, "Dumping config\n");
dev_dbg(skl->dev, "Input Format:\n");
@@ -195,8 +195,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg,
struct skl_module_fmt *in_fmt, *out_fmt;
/* Fixups will be applied to pin 0 only */
- in_fmt = &m_cfg->module->formats[0].inputs[0].fmt;
- out_fmt = &m_cfg->module->formats[0].outputs[0].fmt;
+ in_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].inputs[0].fmt;
+ out_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].outputs[0].fmt;
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (is_fe) {
@@ -239,9 +239,9 @@ static void skl_tplg_update_buffer_size(struct skl_dev *skl,
/* Since fixups is applied to pin 0 only, ibs, obs needs
* change for pin 0 only
*/
- res = &mcfg->module->resources[0];
- in_fmt = &mcfg->module->formats[0].inputs[0].fmt;
- out_fmt = &mcfg->module->formats[0].outputs[0].fmt;
+ res = &mcfg->module->resources[mcfg->res_idx];
+ in_fmt = &mcfg->module->formats[mcfg->fmt_idx].inputs[0].fmt;
+ out_fmt = &mcfg->module->formats[mcfg->fmt_idx].outputs[0].fmt;
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
multiplier = 5;
@@ -292,7 +292,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx];
/* check if we already have blob */
- if (m_cfg->formats_config.caps_size > 0)
+ if (m_cfg->formats_config[SKL_PARAM_INIT].caps_size > 0)
return 0;
dev_dbg(skl->dev, "Applying default cfg blob\n");
@@ -328,8 +328,8 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type,
s_fmt, ch, s_freq, dir, dev_type);
if (cfg) {
- m_cfg->formats_config.caps_size = cfg->size;
- m_cfg->formats_config.caps = (u32 *) &cfg->caps;
+ m_cfg->formats_config[SKL_PARAM_INIT].caps_size = cfg->size;
+ m_cfg->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps;
} else {
dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n",
m_cfg->vbus_id, link_type, dir);
@@ -386,9 +386,9 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w,
struct skl_algo_data *bc;
struct skl_specific_cfg *sp_cfg;
- if (mconfig->formats_config.caps_size > 0 &&
- mconfig->formats_config.set_params == SKL_PARAM_SET) {
- sp_cfg = &mconfig->formats_config;
+ if (mconfig->formats_config[SKL_PARAM_SET].caps_size > 0 &&
+ mconfig->formats_config[SKL_PARAM_SET].set_params == SKL_PARAM_SET) {
+ sp_cfg = &mconfig->formats_config[SKL_PARAM_SET];
ret = skl_set_module_params(skl, sp_cfg->caps,
sp_cfg->caps_size,
sp_cfg->param_id, mconfig);
@@ -438,8 +438,10 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
if (bc->set_params != SKL_PARAM_INIT)
continue;
- mconfig->formats_config.caps = (u32 *)bc->params;
- mconfig->formats_config.caps_size = bc->size;
+ mconfig->formats_config[SKL_PARAM_INIT].caps =
+ (u32 *)bc->params;
+ mconfig->formats_config[SKL_PARAM_INIT].caps_size =
+ bc->size;
break;
}
@@ -498,8 +500,6 @@ skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe)
mconfig->id.module_id, mconfig->guid);
if (ret < 0)
return ret;
-
- mconfig->m_state = SKL_MODULE_LOADED;
}
/* prepare the DMA if the module is gateway cpr */
@@ -558,8 +558,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl,
mconfig = w_module->w->priv;
uuid_mod = (guid_t *)mconfig->guid;
- if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod &&
- mconfig->m_state > SKL_MODULE_UNINIT) {
+ if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod) {
ret = skl->dsp->fw_ops.unload_mod(skl->dsp,
mconfig->id.module_id);
if (ret < 0)
@@ -641,8 +640,9 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig)
return 0;
}
- if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) {
- dev_dbg(skl->dev, "No conn_type detected, take 0th config\n");
+ if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE || pipe->nr_cfgs == 1) {
+ dev_dbg(skl->dev, "No conn_type or just 1 pathcfg, taking 0th for %d\n",
+ pipe->ppl_id);
pipe->cur_config_idx = 0;
pipe->memory_pages = pconfig->mem_pages;
@@ -801,9 +801,10 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
return 0;
}
- if (mconfig->formats_config.caps_size > 0 &&
- mconfig->formats_config.set_params == SKL_PARAM_BIND) {
- sp_cfg = &mconfig->formats_config;
+ if (mconfig->formats_config[SKL_PARAM_BIND].caps_size > 0 &&
+ mconfig->formats_config[SKL_PARAM_BIND].set_params ==
+ SKL_PARAM_BIND) {
+ sp_cfg = &mconfig->formats_config[SKL_PARAM_BIND];
ret = skl_set_module_params(skl, sp_cfg->caps,
sp_cfg->caps_size,
sp_cfg->param_id, mconfig);
@@ -1463,12 +1464,6 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
struct skl_dev *skl = get_skl_ctx(w->dapm->dev);
if (ac->params) {
- /*
- * Widget data is expected to be stripped of T and L
- */
- size -= 2 * sizeof(unsigned int);
- data += 2;
-
if (size > ac->max)
return -EINVAL;
ac->size = size;
@@ -1505,7 +1500,8 @@ static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol,
static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig,
struct skl_mic_sel_config *mic_cfg, struct device *dev)
{
- struct skl_specific_cfg *sp_cfg = &mconfig->formats_config;
+ struct skl_specific_cfg *sp_cfg =
+ &mconfig->formats_config[SKL_PARAM_INIT];
sp_cfg->caps_size = sizeof(struct skl_mic_sel_config);
sp_cfg->set_params = SKL_PARAM_SET;
@@ -1637,11 +1633,12 @@ int skl_tplg_update_pipe_params(struct device *dev,
struct skl_module_cfg *mconfig,
struct skl_pipe_params *params)
{
- struct skl_module_res *res = &mconfig->module->resources[0];
+ struct skl_module_res *res;
struct skl_dev *skl = get_skl_ctx(dev);
struct skl_module_fmt *format = NULL;
u8 cfg_idx = mconfig->pipe->cur_config_idx;
+ res = &mconfig->module->resources[mconfig->res_idx];
skl_tplg_fill_dma_id(mconfig, params);
mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx;
mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx;
@@ -1650,9 +1647,9 @@ int skl_tplg_update_pipe_params(struct device *dev,
return 0;
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
- format = &mconfig->module->formats[0].inputs[0].fmt;
+ format = &mconfig->module->formats[mconfig->fmt_idx].inputs[0].fmt;
else
- format = &mconfig->module->formats[0].outputs[0].fmt;
+ format = &mconfig->module->formats[mconfig->fmt_idx].outputs[0].fmt;
/* set the hw_params */
format->s_freq = params->s_freq;
@@ -1827,7 +1824,7 @@ static u8 skl_tplg_be_link_type(int dev_type)
* Fill the BE gateway parameters
* The BE gateway expects a blob of parameters which are kept in the ACPI
* NHLT blob, so query the blob for interface type (i2s/pdm) and instance.
- * The port can have multiple settings so pick based on the PCM
+ * The port can have multiple settings so pick based on the pipeline
* parameters
*/
static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
@@ -1835,6 +1832,8 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
struct skl_pipe_params *params)
{
struct nhlt_specific_cfg *cfg;
+ struct skl_pipe *pipe = mconfig->pipe;
+ struct skl_pipe_fmt *pipe_fmt;
struct skl_dev *skl = get_skl_ctx(dai->dev);
int link_type = skl_tplg_be_link_type(mconfig->dev_type);
u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type);
@@ -1844,20 +1843,23 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
if (link_type == NHLT_LINK_HDA)
return 0;
+ if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK)
+ pipe_fmt = &pipe->configs[pipe->pipe_config_idx].out_fmt;
+ else
+ pipe_fmt = &pipe->configs[pipe->pipe_config_idx].in_fmt;
+
/* update the blob based on virtual bus_id*/
cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type,
- params->s_fmt, params->ch,
- params->s_freq, params->stream,
+ pipe_fmt->bps, pipe_fmt->channels,
+ pipe_fmt->freq, pipe->direction,
dev_type);
if (cfg) {
- mconfig->formats_config.caps_size = cfg->size;
- mconfig->formats_config.caps = (u32 *) &cfg->caps;
+ mconfig->formats_config[SKL_PARAM_INIT].caps_size = cfg->size;
+ mconfig->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps;
} else {
- dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n",
- mconfig->vbus_id, link_type,
- params->stream);
- dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n",
- params->ch, params->s_freq, params->s_fmt);
+ dev_err(dai->dev, "Blob NULL for id:%d type:%d dirn:%d ch:%d, freq:%d, fmt:%d\n",
+ mconfig->vbus_id, link_type, params->stream,
+ params->ch, params->s_freq, params->s_fmt);
return -EINVAL;
}
@@ -2570,19 +2572,26 @@ static int skl_tplg_get_token(struct device *dev,
break;
+ case SKL_TKN_U32_FMT_CFG_IDX:
+ if (tkn_elem->value > SKL_MAX_PARAMS_TYPES)
+ return -EINVAL;
+
+ mconfig->fmt_cfg_idx = tkn_elem->value;
+ break;
+
case SKL_TKN_U32_CAPS_SIZE:
- mconfig->formats_config.caps_size =
+ mconfig->formats_config[mconfig->fmt_cfg_idx].caps_size =
tkn_elem->value;
break;
case SKL_TKN_U32_CAPS_SET_PARAMS:
- mconfig->formats_config.set_params =
+ mconfig->formats_config[mconfig->fmt_cfg_idx].set_params =
tkn_elem->value;
break;
case SKL_TKN_U32_CAPS_PARAMS_ID:
- mconfig->formats_config.param_id =
+ mconfig->formats_config[mconfig->fmt_cfg_idx].param_id =
tkn_elem->value;
break;
@@ -2796,6 +2805,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
struct skl_dfw_v4_module *dfw =
(struct skl_dfw_v4_module *)tplg_w->priv.data;
int ret;
+ int idx = mconfig->fmt_cfg_idx;
dev_dbg(dev, "Parsing Skylake v4 widget topology data\n");
@@ -2829,7 +2839,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
mconfig->dev_type = dfw->dev_type;
mconfig->hw_conn_type = dfw->hw_conn_type;
mconfig->time_slot = dfw->time_slot;
- mconfig->formats_config.caps_size = dfw->caps.caps_size;
+ mconfig->formats_config[idx].caps_size = dfw->caps.caps_size;
mconfig->m_in_pin = devm_kcalloc(dev,
MAX_IN_QUEUE, sizeof(*mconfig->m_in_pin),
@@ -2850,21 +2860,39 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
dfw->is_dynamic_out_pin,
mconfig->module->max_output_pins);
- if (mconfig->formats_config.caps_size) {
- mconfig->formats_config.set_params = dfw->caps.set_params;
- mconfig->formats_config.param_id = dfw->caps.param_id;
- mconfig->formats_config.caps =
- devm_kzalloc(dev, mconfig->formats_config.caps_size,
+ if (mconfig->formats_config[idx].caps_size) {
+ mconfig->formats_config[idx].set_params = dfw->caps.set_params;
+ mconfig->formats_config[idx].param_id = dfw->caps.param_id;
+ mconfig->formats_config[idx].caps =
+ devm_kzalloc(dev, mconfig->formats_config[idx].caps_size,
GFP_KERNEL);
- if (!mconfig->formats_config.caps)
+ if (!mconfig->formats_config[idx].caps)
return -ENOMEM;
- memcpy(mconfig->formats_config.caps, dfw->caps.caps,
+ memcpy(mconfig->formats_config[idx].caps, dfw->caps.caps,
dfw->caps.caps_size);
}
return 0;
}
+static int skl_tplg_get_caps_data(struct device *dev, char *data,
+ struct skl_module_cfg *mconfig)
+{
+ int idx = mconfig->fmt_cfg_idx;
+
+ if (mconfig->formats_config[idx].caps_size > 0) {
+ mconfig->formats_config[idx].caps =
+ devm_kzalloc(dev, mconfig->formats_config[idx].caps_size,
+ GFP_KERNEL);
+ if (!mconfig->formats_config[idx].caps)
+ return -ENOMEM;
+ memcpy(mconfig->formats_config[idx].caps, data,
+ mconfig->formats_config[idx].caps_size);
+ }
+
+ return mconfig->formats_config[idx].caps_size;
+}
+
/*
* Parse the private data for the token and corresponding value.
* The private data can have multiple data blocks. So, a data block
@@ -2925,18 +2953,14 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
if (block_type == SKL_TYPE_TUPLE) {
ret = skl_tplg_get_tokens(dev, data,
skl, mconfig, block_size);
-
- if (ret < 0)
- return ret;
-
- --num_blocks;
} else {
- if (mconfig->formats_config.caps_size > 0)
- memcpy(mconfig->formats_config.caps, data,
- mconfig->formats_config.caps_size);
- --num_blocks;
- ret = mconfig->formats_config.caps_size;
+ ret = skl_tplg_get_caps_data(dev, data, mconfig);
}
+
+ if (ret < 0)
+ return ret;
+
+ --num_blocks;
off += ret;
}
@@ -3027,6 +3051,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index,
*/
mconfig->id.module_id = -1;
+ /* To provide backward compatibility, set default as SKL_PARAM_INIT */
+ mconfig->fmt_cfg_idx = SKL_PARAM_INIT;
+
/* Parse private data for tuples */
ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig);
if (ret < 0)
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h
index fb011862fb24..f0695b2ac5dd 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -81,6 +81,8 @@ enum skl_s_freq {
SKL_FS_INVALID
};
+#define SKL_MAX_PARAMS_TYPES 4
+
enum skl_widget_type {
SKL_WIDGET_VMIXER = 1,
SKL_WIDGET_MIXER = 2,
@@ -150,6 +152,21 @@ struct skl_up_down_mixer_cfg {
u32 ch_map;
} __packed;
+struct skl_pin_format {
+ u32 pin_idx;
+ u32 buf_size;
+ struct skl_audio_data_format audio_fmt;
+} __packed;
+
+struct skl_base_cfg_ext {
+ u16 nr_input_pins;
+ u16 nr_output_pins;
+ u8 reserved[8];
+ u32 priv_param_length;
+ /* Input pin formats followed by output ones. */
+ struct skl_pin_format pins_fmt[0];
+} __packed;
+
struct skl_algo_cfg {
struct skl_base_cfg base_cfg;
char params[];
@@ -311,10 +328,8 @@ struct skl_pipe {
enum skl_module_state {
SKL_MODULE_UNINIT = 0,
- SKL_MODULE_LOADED = 1,
- SKL_MODULE_INIT_DONE = 2,
- SKL_MODULE_BIND_DONE = 3,
- SKL_MODULE_UNLOADED = 4,
+ SKL_MODULE_INIT_DONE = 1,
+ SKL_MODULE_BIND_DONE = 2,
};
enum d0i3_capability {
@@ -373,6 +388,7 @@ struct skl_module_cfg {
struct skl_module *module;
int res_idx;
int fmt_idx;
+ int fmt_cfg_idx;
u8 domain;
bool homogenous_inputs;
bool homogenous_outputs;
@@ -403,7 +419,7 @@ struct skl_module_cfg {
enum skl_hw_conn_type hw_conn_type;
enum skl_module_state m_state;
struct skl_pipe *pipe;
- struct skl_specific_cfg formats_config;
+ struct skl_specific_cfg formats_config[SKL_MAX_PARAMS_TYPES];
struct skl_pipe_mcfg mod_cfg[SKL_MAX_MODULES_IN_PIPE];
};
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 74dae4332d17..cf567a89f421 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -184,3 +184,27 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682
with the MT6359 RT1015 RT5682 audio codec.
Select Y if you have such device.
If unsure select "N".
+
+config SND_SOC_MT8195
+ tristate "ASoC support for Mediatek MT8195 chip"
+ select SND_SOC_MEDIATEK
+ help
+ This adds ASoC platform driver support for Mediatek MT8195 chip
+ that can be used with other codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
+config SND_SOC_MT8195_MT6359_RT1019_RT5682
+ tristate "ASoC Audio driver for MT8195 with MT6359 RT1019 RT5682 codec"
+ depends on I2C
+ depends on SND_SOC_MT8195
+ select SND_SOC_MT6359
+ select SND_SOC_RT1015P
+ select SND_SOC_RT5682_I2C
+ select SND_SOC_DMIC
+ select SND_SOC_HDMI_CODEC
+ help
+ This adds ASoC driver for Mediatek MT8195 boards
+ with the MT6359 RT1019 RT5682 audio codec.
+ Select Y if you have such device.
+ If unsure select "N".
diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
index f6cb6b8508e3..34778ca12106 100644
--- a/sound/soc/mediatek/Makefile
+++ b/sound/soc/mediatek/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
+obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
index 3cb2adf420bb..baaa5881b1d4 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
@@ -139,7 +139,7 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
substream->runtime->dma_area,
substream->runtime->dma_bytes);
- memset_io(substream->runtime->dma_area, 0,
+ memset_io((void __force __iomem *)substream->runtime->dma_area, 0,
substream->runtime->dma_bytes);
/* set addr */
@@ -433,11 +433,20 @@ int mtk_memif_set_addr(struct mtk_base_afe *afe, int id,
phys_buf_addr_upper_32);
}
- /* set MSB to 33-bit */
- if (memif->data->msb_reg >= 0)
+ /*
+ * set MSB to 33-bit, for memif address
+ * only for memif base address, if msb_end_reg exists
+ */
+ if (memif->data->msb_reg)
mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
1, msb_at_bit33, memif->data->msb_shift);
+ /* set MSB to 33-bit, for memif end address */
+ if (memif->data->msb_end_reg)
+ mtk_regmap_update_bits(afe->regmap, memif->data->msb_end_reg,
+ 1, msb_at_bit33,
+ memif->data->msb_end_shift);
+
return 0;
}
EXPORT_SYMBOL_GPL(mtk_memif_set_addr);
@@ -464,6 +473,13 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
else
mono = (channel == 1) ? 1 : 0;
+ /* for specific configuration of memif mono mode */
+ if (memif->data->int_odd_flag_reg)
+ mtk_regmap_update_bits(afe->regmap,
+ memif->data->int_odd_flag_reg,
+ 1, mono,
+ memif->data->int_odd_flag_shift);
+
return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
1, mono, memif->data->mono_shift);
}
diff --git a/sound/soc/mediatek/common/mtk-base-afe.h b/sound/soc/mediatek/common/mtk-base-afe.h
index a6f68c68581c..ef83e78c22a8 100644
--- a/sound/soc/mediatek/common/mtk-base-afe.h
+++ b/sound/soc/mediatek/common/mtk-base-afe.h
@@ -29,6 +29,8 @@ struct mtk_base_memif_data {
int quad_ch_reg;
int quad_ch_mask;
int quad_ch_shift;
+ int int_odd_flag_reg;
+ int int_odd_flag_shift;
int enable_reg;
int enable_shift;
int hd_reg;
@@ -37,10 +39,13 @@ struct mtk_base_memif_data {
int hd_align_mshift;
int msb_reg;
int msb_shift;
- int msb2_reg;
- int msb2_shift;
+ int msb_end_reg;
+ int msb_end_shift;
int agent_disable_reg;
int agent_disable_shift;
+ int ch_num_reg;
+ int ch_num_shift;
+ int ch_num_maskbit;
/* playback memif only */
int pbuf_reg;
int pbuf_mask;
@@ -62,6 +67,7 @@ struct mtk_base_irq_data {
int irq_en_shift;
int irq_clr_reg;
int irq_clr_shift;
+ int irq_status_shift;
};
struct device;
diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
index c4a598cbbdaa..14e77df06b01 100644
--- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
@@ -1119,25 +1119,26 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
afe->regmap = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(afe->regmap)) {
dev_err(dev, "could not get regmap from parent\n");
- return PTR_ERR(afe->regmap);
+ ret = PTR_ERR(afe->regmap);
+ goto err_pm_disable;
}
ret = regmap_attach_dev(dev, afe->regmap, &mt8183_afe_regmap_config);
if (ret) {
dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret);
- return ret;
+ goto err_pm_disable;
}
rstc = devm_reset_control_get(dev, "audiosys");
if (IS_ERR(rstc)) {
ret = PTR_ERR(rstc);
dev_err(dev, "could not get audiosys reset:%d\n", ret);
- return ret;
+ goto err_pm_disable;
}
ret = reset_control_reset(rstc);
if (ret) {
dev_err(dev, "failed to trigger audio reset:%d\n", ret);
- return ret;
+ goto err_pm_disable;
}
/* enable clock for regcache get default value from hw */
@@ -1147,7 +1148,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config);
if (ret) {
dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
- return ret;
+ goto err_pm_disable;
}
pm_runtime_put_sync(&pdev->dev);
@@ -1160,8 +1161,10 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
afe->memif_size = MT8183_MEMIF_NUM;
afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
GFP_KERNEL);
- if (!afe->memif)
- return -ENOMEM;
+ if (!afe->memif) {
+ ret = -ENOMEM;
+ goto err_pm_disable;
+ }
for (i = 0; i < afe->memif_size; i++) {
afe->memif[i].data = &memif_data[i];
@@ -1178,22 +1181,26 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
afe->irqs_size = MT8183_IRQ_NUM;
afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
GFP_KERNEL);
- if (!afe->irqs)
- return -ENOMEM;
+ if (!afe->irqs) {
+ ret = -ENOMEM;
+ goto err_pm_disable;
+ }
for (i = 0; i < afe->irqs_size; i++)
afe->irqs[i].irq_data = &irq_data[i];
/* request irq */
irq_id = platform_get_irq(pdev, 0);
- if (irq_id < 0)
- return irq_id;
+ if (irq_id < 0) {
+ ret = irq_id;
+ goto err_pm_disable;
+ }
ret = devm_request_irq(dev, irq_id, mt8183_afe_irq_handler,
IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
if (ret) {
dev_err(dev, "could not request_irq for asys-isr\n");
- return ret;
+ goto err_pm_disable;
}
/* init sub_dais */
@@ -1204,7 +1211,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
if (ret) {
dev_warn(afe->dev, "dai register i %d fail, ret %d\n",
i, ret);
- return ret;
+ goto err_pm_disable;
}
}
@@ -1213,7 +1220,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
if (ret) {
dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
ret);
- return ret;
+ goto err_pm_disable;
}
afe->mtk_afe_hardware = &mt8183_afe_hardware;
@@ -1229,7 +1236,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
NULL, 0);
if (ret) {
dev_warn(dev, "err_platform\n");
- return ret;
+ goto err_pm_disable;
}
ret = devm_snd_soc_register_component(afe->dev,
@@ -1238,10 +1245,14 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
afe->num_dai_drivers);
if (ret) {
dev_warn(dev, "err_dai_component\n");
- return ret;
+ goto err_pm_disable;
}
return ret;
+
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ return ret;
}
static int mt8183_afe_pcm_dev_remove(struct platform_device *pdev)
diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
index 7a1724f5ff4c..31c280339c50 100644
--- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
@@ -2229,12 +2229,13 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
afe->regmap = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(afe->regmap)) {
dev_err(dev, "could not get regmap from parent\n");
- return PTR_ERR(afe->regmap);
+ ret = PTR_ERR(afe->regmap);
+ goto err_pm_disable;
}
ret = regmap_attach_dev(dev, afe->regmap, &mt8192_afe_regmap_config);
if (ret) {
dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret);
- return ret;
+ goto err_pm_disable;
}
/* enable clock for regcache get default value from hw */
@@ -2244,7 +2245,7 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config);
if (ret) {
dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
- return ret;
+ goto err_pm_disable;
}
pm_runtime_put_sync(&pdev->dev);
@@ -2257,8 +2258,10 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
afe->memif_size = MT8192_MEMIF_NUM;
afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
GFP_KERNEL);
- if (!afe->memif)
- return -ENOMEM;
+ if (!afe->memif) {
+ ret = -ENOMEM;
+ goto err_pm_disable;
+ }
for (i = 0; i < afe->memif_size; i++) {
afe->memif[i].data = &memif_data[i];
@@ -2272,22 +2275,26 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
afe->irqs_size = MT8192_IRQ_NUM;
afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
GFP_KERNEL);
- if (!afe->irqs)
- return -ENOMEM;
+ if (!afe->irqs) {
+ ret = -ENOMEM;
+ goto err_pm_disable;
+ }
for (i = 0; i < afe->irqs_size; i++)
afe->irqs[i].irq_data = &irq_data[i];
/* request irq */
irq_id = platform_get_irq(pdev, 0);
- if (irq_id < 0)
- return irq_id;
+ if (irq_id < 0) {
+ ret = irq_id;
+ goto err_pm_disable;
+ }
ret = devm_request_irq(dev, irq_id, mt8192_afe_irq_handler,
IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
if (ret) {
dev_err(dev, "could not request_irq for Afe_ISR_Handle\n");
- return ret;
+ goto err_pm_disable;
}
/* init sub_dais */
diff --git a/sound/soc/mediatek/mt8195/Makefile b/sound/soc/mediatek/mt8195/Makefile
new file mode 100644
index 000000000000..44775f400b40
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/Makefile
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# platform driver
+snd-soc-mt8195-afe-objs := \
+ mt8195-audsys-clk.o \
+ mt8195-afe-clk.o \
+ mt8195-afe-pcm.o \
+ mt8195-dai-adda.o \
+ mt8195-dai-etdm.o \
+ mt8195-dai-pcm.o
+
+obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
+
+# machine driver
+obj-$(CONFIG_SND_SOC_MT8195_MT6359_RT1019_RT5682) += mt8195-mt6359-rt1019-rt5682.o
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
new file mode 100644
index 000000000000..8420b2c71332
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt8195-afe-clk.c -- Mediatek 8195 afe clock ctrl
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ * Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/clk.h>
+
+#include "mt8195-afe-common.h"
+#include "mt8195-afe-clk.h"
+#include "mt8195-reg.h"
+#include "mt8195-audsys-clk.h"
+
+static const char *aud_clks[MT8195_CLK_NUM] = {
+ /* xtal */
+ [MT8195_CLK_XTAL_26M] = "clk26m",
+ /* divider */
+ [MT8195_CLK_TOP_APLL1] = "apll1_ck",
+ [MT8195_CLK_TOP_APLL2] = "apll2_ck",
+ [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
+ [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
+ [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
+ [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
+ [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
+ /* mux */
+ [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
+ [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
+ [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
+ [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] = "audio_local_bus_sel",
+ [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
+ [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
+ [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
+ [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
+ [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
+ /* clock gate */
+ [MT8195_CLK_INFRA_AO_AUDIO_26M_B] = "infra_ao_audio_26m_b",
+ [MT8195_CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp",
+ /* afe clock gate */
+ [MT8195_CLK_AUD_AFE] = "aud_afe",
+ [MT8195_CLK_AUD_APLL] = "aud_apll",
+ [MT8195_CLK_AUD_APLL2] = "aud_apll2",
+ [MT8195_CLK_AUD_DAC] = "aud_dac",
+ [MT8195_CLK_AUD_ADC] = "aud_adc",
+ [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
+ [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
+ [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
+ [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
+ [MT8195_CLK_AUD_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
+ [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
+ [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
+ [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
+ [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
+ [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
+ [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
+ [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
+ [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
+ [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
+ [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
+ [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
+ [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
+ [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
+ [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
+ [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
+ [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
+ [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
+ [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
+ [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
+ [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
+ [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
+ [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
+ [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
+ [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
+ [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
+ [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
+};
+
+int mt8195_afe_get_mclk_source_clk_id(int sel)
+{
+ switch (sel) {
+ case MT8195_MCK_SEL_26M:
+ return MT8195_CLK_XTAL_26M;
+ case MT8195_MCK_SEL_APLL1:
+ return MT8195_CLK_TOP_APLL1;
+ case MT8195_MCK_SEL_APLL2:
+ return MT8195_CLK_TOP_APLL2;
+ default:
+ return -EINVAL;
+ }
+}
+
+int mt8195_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int clk_id = mt8195_afe_get_mclk_source_clk_id(apll);
+
+ if (clk_id < 0) {
+ dev_dbg(afe->dev, "invalid clk id\n");
+ return 0;
+ }
+
+ return clk_get_rate(afe_priv->clk[clk_id]);
+}
+
+int mt8195_afe_get_default_mclk_source_by_rate(int rate)
+{
+ return ((rate % 8000) == 0) ?
+ MT8195_MCK_SEL_APLL1 : MT8195_MCK_SEL_APLL2;
+}
+
+int mt8195_afe_init_clock(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int i;
+
+ mt8195_audsys_clk_register(afe);
+
+ afe_priv->clk =
+ devm_kcalloc(afe->dev, MT8195_CLK_NUM, sizeof(*afe_priv->clk),
+ GFP_KERNEL);
+ if (!afe_priv->clk)
+ return -ENOMEM;
+
+ for (i = 0; i < MT8195_CLK_NUM; i++) {
+ afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
+ if (IS_ERR(afe_priv->clk[i])) {
+ dev_dbg(afe->dev, "%s(), devm_clk_get %s fail, ret %ld\n",
+ __func__, aud_clks[i],
+ PTR_ERR(afe_priv->clk[i]));
+ return PTR_ERR(afe_priv->clk[i]);
+ }
+ }
+
+ return 0;
+}
+
+void mt8195_afe_deinit_clock(struct mtk_base_afe *afe)
+{
+ mt8195_audsys_clk_unregister(afe);
+}
+
+int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+ int ret;
+
+ if (clk) {
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_dbg(afe->dev, "%s(), failed to enable clk\n",
+ __func__);
+ return ret;
+ }
+ } else {
+ dev_dbg(afe->dev, "NULL clk\n");
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt8195_afe_enable_clk);
+
+void mt8195_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+ if (clk)
+ clk_disable_unprepare(clk);
+ else
+ dev_dbg(afe->dev, "NULL clk\n");
+}
+EXPORT_SYMBOL_GPL(mt8195_afe_disable_clk);
+
+int mt8195_afe_prepare_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+ int ret;
+
+ if (clk) {
+ ret = clk_prepare(clk);
+ if (ret) {
+ dev_dbg(afe->dev, "%s(), failed to prepare clk\n",
+ __func__);
+ return ret;
+ }
+ } else {
+ dev_dbg(afe->dev, "NULL clk\n");
+ }
+ return 0;
+}
+
+void mt8195_afe_unprepare_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+ if (clk)
+ clk_unprepare(clk);
+ else
+ dev_dbg(afe->dev, "NULL clk\n");
+}
+
+int mt8195_afe_enable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk)
+{
+ int ret;
+
+ if (clk) {
+ ret = clk_enable(clk);
+ if (ret) {
+ dev_dbg(afe->dev, "%s(), failed to clk enable\n",
+ __func__);
+ return ret;
+ }
+ } else {
+ dev_dbg(afe->dev, "NULL clk\n");
+ }
+ return 0;
+}
+
+void mt8195_afe_disable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk)
+{
+ if (clk)
+ clk_disable(clk);
+ else
+ dev_dbg(afe->dev, "NULL clk\n");
+}
+
+int mt8195_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
+ unsigned int rate)
+{
+ int ret;
+
+ if (clk) {
+ ret = clk_set_rate(clk, rate);
+ if (ret) {
+ dev_dbg(afe->dev, "%s(), failed to set clk rate\n",
+ __func__);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int mt8195_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
+ struct clk *parent)
+{
+ int ret;
+
+ if (clk && parent) {
+ ret = clk_set_parent(clk, parent);
+ if (ret) {
+ dev_dbg(afe->dev, "%s(), failed to set clk parent\n",
+ __func__);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int get_top_cg_reg(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8195_TOP_CG_A1SYS_TIMING:
+ case MT8195_TOP_CG_A2SYS_TIMING:
+ case MT8195_TOP_CG_26M_TIMING:
+ return ASYS_TOP_CON;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_mask(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8195_TOP_CG_A1SYS_TIMING:
+ return ASYS_TOP_CON_A1SYS_TIMING_ON;
+ case MT8195_TOP_CG_A2SYS_TIMING:
+ return ASYS_TOP_CON_A2SYS_TIMING_ON;
+ case MT8195_TOP_CG_26M_TIMING:
+ return ASYS_TOP_CON_26M_TIMING_ON;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_on_val(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8195_TOP_CG_A1SYS_TIMING:
+ case MT8195_TOP_CG_A2SYS_TIMING:
+ case MT8195_TOP_CG_26M_TIMING:
+ return get_top_cg_mask(cg_type);
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_off_val(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8195_TOP_CG_A1SYS_TIMING:
+ case MT8195_TOP_CG_A2SYS_TIMING:
+ case MT8195_TOP_CG_26M_TIMING:
+ return 0;
+ default:
+ return get_top_cg_mask(cg_type);
+ }
+}
+
+static int mt8195_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+ unsigned int reg = get_top_cg_reg(cg_type);
+ unsigned int mask = get_top_cg_mask(cg_type);
+ unsigned int val = get_top_cg_on_val(cg_type);
+
+ regmap_update_bits(afe->regmap, reg, mask, val);
+ return 0;
+}
+
+static int mt8195_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+ unsigned int reg = get_top_cg_reg(cg_type);
+ unsigned int mask = get_top_cg_mask(cg_type);
+ unsigned int val = get_top_cg_off_val(cg_type);
+
+ regmap_update_bits(afe->regmap, reg, mask, val);
+ return 0;
+}
+
+int mt8195_afe_enable_reg_rw_clk(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int i;
+ unsigned int clk_array[] = {
+ MT8195_CLK_SCP_ADSP_AUDIODSP, /* bus clock for infra */
+ MT8195_CLK_TOP_AUDIO_H_SEL, /* clock for ADSP bus */
+ MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL, /* bus clock for DRAM access */
+ MT8195_CLK_TOP_AUD_INTBUS_SEL, /* bus clock for AFE SRAM access */
+ MT8195_CLK_INFRA_AO_AUDIO_26M_B, /* audio 26M clock */
+ MT8195_CLK_AUD_AFE, /* AFE HW master switch */
+ MT8195_CLK_AUD_A1SYS_HP, /* AFE HW clock*/
+ MT8195_CLK_AUD_A1SYS, /* AFE HW clock */
+ };
+
+ for (i = 0; i < ARRAY_SIZE(clk_array); i++)
+ mt8195_afe_enable_clk(afe, afe_priv->clk[clk_array[i]]);
+
+ return 0;
+}
+
+int mt8195_afe_disable_reg_rw_clk(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int i;
+ unsigned int clk_array[] = {
+ MT8195_CLK_AUD_A1SYS,
+ MT8195_CLK_AUD_A1SYS_HP,
+ MT8195_CLK_AUD_AFE,
+ MT8195_CLK_INFRA_AO_AUDIO_26M_B,
+ MT8195_CLK_TOP_AUD_INTBUS_SEL,
+ MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
+ MT8195_CLK_TOP_AUDIO_H_SEL,
+ MT8195_CLK_SCP_ADSP_AUDIODSP,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(clk_array); i++)
+ mt8195_afe_disable_clk(afe, afe_priv->clk[clk_array[i]]);
+
+ return 0;
+}
+
+static int mt8195_afe_enable_afe_on(struct mtk_base_afe *afe)
+{
+ regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
+ return 0;
+}
+
+static int mt8195_afe_disable_afe_on(struct mtk_base_afe *afe)
+{
+ regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x0);
+ return 0;
+}
+
+static int mt8195_afe_enable_timing_sys(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int i;
+ unsigned int clk_array[] = {
+ MT8195_CLK_AUD_A1SYS,
+ MT8195_CLK_AUD_A2SYS,
+ };
+ unsigned int cg_array[] = {
+ MT8195_TOP_CG_A1SYS_TIMING,
+ MT8195_TOP_CG_A2SYS_TIMING,
+ MT8195_TOP_CG_26M_TIMING,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(clk_array); i++)
+ mt8195_afe_enable_clk(afe, afe_priv->clk[clk_array[i]]);
+
+ for (i = 0; i < ARRAY_SIZE(cg_array); i++)
+ mt8195_afe_enable_top_cg(afe, cg_array[i]);
+
+ return 0;
+}
+
+static int mt8195_afe_disable_timing_sys(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int i;
+ unsigned int clk_array[] = {
+ MT8195_CLK_AUD_A2SYS,
+ MT8195_CLK_AUD_A1SYS,
+ };
+ unsigned int cg_array[] = {
+ MT8195_TOP_CG_26M_TIMING,
+ MT8195_TOP_CG_A2SYS_TIMING,
+ MT8195_TOP_CG_A1SYS_TIMING,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(cg_array); i++)
+ mt8195_afe_disable_top_cg(afe, cg_array[i]);
+
+ for (i = 0; i < ARRAY_SIZE(clk_array); i++)
+ mt8195_afe_disable_clk(afe, afe_priv->clk[clk_array[i]]);
+
+ return 0;
+}
+
+int mt8195_afe_enable_main_clock(struct mtk_base_afe *afe)
+{
+ mt8195_afe_enable_timing_sys(afe);
+
+ mt8195_afe_enable_afe_on(afe);
+
+ return 0;
+}
+
+int mt8195_afe_disable_main_clock(struct mtk_base_afe *afe)
+{
+ mt8195_afe_disable_afe_on(afe);
+
+ mt8195_afe_disable_timing_sys(afe);
+
+ return 0;
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.h b/sound/soc/mediatek/mt8195/mt8195-afe-clk.h
new file mode 100644
index 000000000000..f8e6eeb29a89
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-afe-clk.h -- Mediatek 8195 afe clock ctrl definition
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ * Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8195_AFE_CLK_H_
+#define _MT8195_AFE_CLK_H_
+
+enum {
+ /* xtal */
+ MT8195_CLK_XTAL_26M,
+ /* divider */
+ MT8195_CLK_TOP_APLL1,
+ MT8195_CLK_TOP_APLL2,
+ MT8195_CLK_TOP_APLL12_DIV0,
+ MT8195_CLK_TOP_APLL12_DIV1,
+ MT8195_CLK_TOP_APLL12_DIV2,
+ MT8195_CLK_TOP_APLL12_DIV3,
+ MT8195_CLK_TOP_APLL12_DIV9,
+ /* mux */
+ MT8195_CLK_TOP_A1SYS_HP_SEL,
+ MT8195_CLK_TOP_AUD_INTBUS_SEL,
+ MT8195_CLK_TOP_AUDIO_H_SEL,
+ MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
+ MT8195_CLK_TOP_DPTX_M_SEL,
+ MT8195_CLK_TOP_I2SO1_M_SEL,
+ MT8195_CLK_TOP_I2SO2_M_SEL,
+ MT8195_CLK_TOP_I2SI1_M_SEL,
+ MT8195_CLK_TOP_I2SI2_M_SEL,
+ /* clock gate */
+ MT8195_CLK_INFRA_AO_AUDIO_26M_B,
+ MT8195_CLK_SCP_ADSP_AUDIODSP,
+ MT8195_CLK_AUD_AFE,
+ MT8195_CLK_AUD_APLL,
+ MT8195_CLK_AUD_APLL2,
+ MT8195_CLK_AUD_DAC,
+ MT8195_CLK_AUD_ADC,
+ MT8195_CLK_AUD_DAC_HIRES,
+ MT8195_CLK_AUD_A1SYS_HP,
+ MT8195_CLK_AUD_ADC_HIRES,
+ MT8195_CLK_AUD_ADDA6_ADC,
+ MT8195_CLK_AUD_ADDA6_ADC_HIRES,
+ MT8195_CLK_AUD_I2SIN,
+ MT8195_CLK_AUD_TDM_IN,
+ MT8195_CLK_AUD_I2S_OUT,
+ MT8195_CLK_AUD_TDM_OUT,
+ MT8195_CLK_AUD_HDMI_OUT,
+ MT8195_CLK_AUD_ASRC11,
+ MT8195_CLK_AUD_ASRC12,
+ MT8195_CLK_AUD_A1SYS,
+ MT8195_CLK_AUD_A2SYS,
+ MT8195_CLK_AUD_PCMIF,
+ MT8195_CLK_AUD_MEMIF_UL1,
+ MT8195_CLK_AUD_MEMIF_UL2,
+ MT8195_CLK_AUD_MEMIF_UL3,
+ MT8195_CLK_AUD_MEMIF_UL4,
+ MT8195_CLK_AUD_MEMIF_UL5,
+ MT8195_CLK_AUD_MEMIF_UL6,
+ MT8195_CLK_AUD_MEMIF_UL8,
+ MT8195_CLK_AUD_MEMIF_UL9,
+ MT8195_CLK_AUD_MEMIF_UL10,
+ MT8195_CLK_AUD_MEMIF_DL2,
+ MT8195_CLK_AUD_MEMIF_DL3,
+ MT8195_CLK_AUD_MEMIF_DL6,
+ MT8195_CLK_AUD_MEMIF_DL7,
+ MT8195_CLK_AUD_MEMIF_DL8,
+ MT8195_CLK_AUD_MEMIF_DL10,
+ MT8195_CLK_AUD_MEMIF_DL11,
+ MT8195_CLK_NUM,
+};
+
+enum {
+ MT8195_MCK_SEL_26M,
+ MT8195_MCK_SEL_APLL1,
+ MT8195_MCK_SEL_APLL2,
+ MT8195_MCK_SEL_APLL3,
+ MT8195_MCK_SEL_APLL4,
+ MT8195_MCK_SEL_APLL5,
+ MT8195_MCK_SEL_HDMIRX_APLL,
+ MT8195_MCK_SEL_NUM,
+};
+
+struct mtk_base_afe;
+
+int mt8195_afe_get_mclk_source_clk_id(int sel);
+int mt8195_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll);
+int mt8195_afe_get_default_mclk_source_by_rate(int rate);
+int mt8195_afe_init_clock(struct mtk_base_afe *afe);
+void mt8195_afe_deinit_clock(struct mtk_base_afe *afe);
+int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk);
+void mt8195_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
+int mt8195_afe_prepare_clk(struct mtk_base_afe *afe, struct clk *clk);
+void mt8195_afe_unprepare_clk(struct mtk_base_afe *afe, struct clk *clk);
+int mt8195_afe_enable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk);
+void mt8195_afe_disable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk);
+int mt8195_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
+ unsigned int rate);
+int mt8195_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
+ struct clk *parent);
+int mt8195_afe_enable_main_clock(struct mtk_base_afe *afe);
+int mt8195_afe_disable_main_clock(struct mtk_base_afe *afe);
+int mt8195_afe_enable_reg_rw_clk(struct mtk_base_afe *afe);
+int mt8195_afe_disable_reg_rw_clk(struct mtk_base_afe *afe);
+
+#endif
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-common.h b/sound/soc/mediatek/mt8195/mt8195-afe-common.h
new file mode 100644
index 000000000000..f93f439e2bd9
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-common.h
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-afe-common.h -- Mediatek 8195 audio driver definitions
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ * Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT_8195_AFE_COMMON_H_
+#define _MT_8195_AFE_COMMON_H_
+
+#include <sound/soc.h>
+#include <linux/list.h>
+#include <linux/regmap.h>
+#include "../common/mtk-base-afe.h"
+
+enum {
+ MT8195_DAI_START,
+ MT8195_AFE_MEMIF_START = MT8195_DAI_START,
+ MT8195_AFE_MEMIF_DL2 = MT8195_AFE_MEMIF_START,
+ MT8195_AFE_MEMIF_DL3,
+ MT8195_AFE_MEMIF_DL6,
+ MT8195_AFE_MEMIF_DL7,
+ MT8195_AFE_MEMIF_DL8,
+ MT8195_AFE_MEMIF_DL10,
+ MT8195_AFE_MEMIF_DL11,
+ MT8195_AFE_MEMIF_UL_START,
+ MT8195_AFE_MEMIF_UL1 = MT8195_AFE_MEMIF_UL_START,
+ MT8195_AFE_MEMIF_UL2,
+ MT8195_AFE_MEMIF_UL3,
+ MT8195_AFE_MEMIF_UL4,
+ MT8195_AFE_MEMIF_UL5,
+ MT8195_AFE_MEMIF_UL6,
+ MT8195_AFE_MEMIF_UL8,
+ MT8195_AFE_MEMIF_UL9,
+ MT8195_AFE_MEMIF_UL10,
+ MT8195_AFE_MEMIF_END,
+ MT8195_AFE_MEMIF_NUM = (MT8195_AFE_MEMIF_END - MT8195_AFE_MEMIF_START),
+ MT8195_AFE_IO_START = MT8195_AFE_MEMIF_END,
+ MT8195_AFE_IO_DL_SRC = MT8195_AFE_IO_START,
+ MT8195_AFE_IO_DPTX,
+ MT8195_AFE_IO_ETDM_START,
+ MT8195_AFE_IO_ETDM1_IN = MT8195_AFE_IO_ETDM_START,
+ MT8195_AFE_IO_ETDM2_IN,
+ MT8195_AFE_IO_ETDM1_OUT,
+ MT8195_AFE_IO_ETDM2_OUT,
+ MT8195_AFE_IO_ETDM3_OUT,
+ MT8195_AFE_IO_ETDM_END,
+ MT8195_AFE_IO_ETDM_NUM =
+ (MT8195_AFE_IO_ETDM_END - MT8195_AFE_IO_ETDM_START),
+ MT8195_AFE_IO_PCM = MT8195_AFE_IO_ETDM_END,
+ MT8195_AFE_IO_UL_SRC1,
+ MT8195_AFE_IO_UL_SRC2,
+ MT8195_AFE_IO_END,
+ MT8195_AFE_IO_NUM = (MT8195_AFE_IO_END - MT8195_AFE_IO_START),
+ MT8195_DAI_END = MT8195_AFE_IO_END,
+ MT8195_DAI_NUM = (MT8195_DAI_END - MT8195_DAI_START),
+};
+
+enum {
+ MT8195_TOP_CG_A1SYS_TIMING,
+ MT8195_TOP_CG_A2SYS_TIMING,
+ MT8195_TOP_CG_26M_TIMING,
+ MT8195_TOP_CG_NUM,
+};
+
+enum {
+ MT8195_AFE_IRQ_1,
+ MT8195_AFE_IRQ_2,
+ MT8195_AFE_IRQ_3,
+ MT8195_AFE_IRQ_8,
+ MT8195_AFE_IRQ_9,
+ MT8195_AFE_IRQ_10,
+ MT8195_AFE_IRQ_13,
+ MT8195_AFE_IRQ_14,
+ MT8195_AFE_IRQ_15,
+ MT8195_AFE_IRQ_16,
+ MT8195_AFE_IRQ_17,
+ MT8195_AFE_IRQ_18,
+ MT8195_AFE_IRQ_19,
+ MT8195_AFE_IRQ_20,
+ MT8195_AFE_IRQ_21,
+ MT8195_AFE_IRQ_22,
+ MT8195_AFE_IRQ_23,
+ MT8195_AFE_IRQ_24,
+ MT8195_AFE_IRQ_25,
+ MT8195_AFE_IRQ_26,
+ MT8195_AFE_IRQ_27,
+ MT8195_AFE_IRQ_28,
+ MT8195_AFE_IRQ_NUM,
+};
+
+enum {
+ MT8195_ETDM_OUT1_1X_EN = 9,
+ MT8195_ETDM_OUT2_1X_EN = 10,
+ MT8195_ETDM_OUT3_1X_EN = 11,
+ MT8195_ETDM_IN1_1X_EN = 12,
+ MT8195_ETDM_IN2_1X_EN = 13,
+ MT8195_ETDM_IN1_NX_EN = 25,
+ MT8195_ETDM_IN2_NX_EN = 26,
+};
+
+enum {
+ MT8195_MTKAIF_MISO_0,
+ MT8195_MTKAIF_MISO_1,
+ MT8195_MTKAIF_MISO_2,
+ MT8195_MTKAIF_MISO_NUM,
+};
+
+struct mtk_dai_memif_irq_priv {
+ unsigned int asys_timing_sel;
+};
+
+struct mtkaif_param {
+ bool mtkaif_calibration_ok;
+ int mtkaif_chosen_phase[MT8195_MTKAIF_MISO_NUM];
+ int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM];
+ int mtkaif_dmic_on;
+ int mtkaif_adda6_only;
+};
+
+struct clk;
+
+struct mt8195_afe_private {
+ struct clk **clk;
+ struct clk_lookup **lookup;
+ struct regmap *topckgen;
+ int pm_runtime_bypass_reg_ctl;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry **debugfs_dentry;
+#endif
+ int afe_on_ref_cnt;
+ int top_cg_ref_cnt[MT8195_TOP_CG_NUM];
+ spinlock_t afe_ctrl_lock; /* Lock for afe control */
+ struct mtk_dai_memif_irq_priv irq_priv[MT8195_AFE_IRQ_NUM];
+ struct mtkaif_param mtkaif_params;
+
+ /* dai */
+ void *dai_priv[MT8195_DAI_NUM];
+};
+
+int mt8195_afe_fs_timing(unsigned int rate);
+/* dai register */
+int mt8195_dai_adda_register(struct mtk_base_afe *afe);
+int mt8195_dai_etdm_register(struct mtk_base_afe *afe);
+int mt8195_dai_pcm_register(struct mtk_base_afe *afe);
+
+#define MT8195_SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put, id) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_info_enum_double, \
+ .get = xhandler_get, .put = xhandler_put, \
+ .device = id, \
+ .private_value = (unsigned long)&xenum, \
+}
+
+#endif
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
new file mode 100644
index 000000000000..6635c3f72ecc
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
@@ -0,0 +1,3281 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek ALSA SoC AFE platform driver for 8195
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ * Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include "mt8195-afe-common.h"
+#include "mt8195-afe-clk.h"
+#include "mt8195-reg.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "../common/mtk-afe-fe-dai.h"
+
+#define MT8195_MEMIF_BUFFER_BYTES_ALIGN (0x40)
+#define MT8195_MEMIF_DL7_MAX_PERIOD_SIZE (0x3fff)
+
+struct mtk_dai_memif_priv {
+ unsigned int asys_timing_sel;
+};
+
+static const struct snd_pcm_hardware mt8195_afe_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .period_bytes_min = 64,
+ .period_bytes_max = 256 * 1024,
+ .periods_min = 2,
+ .periods_max = 256,
+ .buffer_bytes_max = 256 * 2 * 1024,
+};
+
+struct mt8195_afe_rate {
+ unsigned int rate;
+ unsigned int reg_value;
+};
+
+static const struct mt8195_afe_rate mt8195_afe_rates[] = {
+ { .rate = 8000, .reg_value = 0, },
+ { .rate = 12000, .reg_value = 1, },
+ { .rate = 16000, .reg_value = 2, },
+ { .rate = 24000, .reg_value = 3, },
+ { .rate = 32000, .reg_value = 4, },
+ { .rate = 48000, .reg_value = 5, },
+ { .rate = 96000, .reg_value = 6, },
+ { .rate = 192000, .reg_value = 7, },
+ { .rate = 384000, .reg_value = 8, },
+ { .rate = 7350, .reg_value = 16, },
+ { .rate = 11025, .reg_value = 17, },
+ { .rate = 14700, .reg_value = 18, },
+ { .rate = 22050, .reg_value = 19, },
+ { .rate = 29400, .reg_value = 20, },
+ { .rate = 44100, .reg_value = 21, },
+ { .rate = 88200, .reg_value = 22, },
+ { .rate = 176400, .reg_value = 23, },
+ { .rate = 352800, .reg_value = 24, },
+};
+
+int mt8195_afe_fs_timing(unsigned int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mt8195_afe_rates); i++)
+ if (mt8195_afe_rates[i].rate == rate)
+ return mt8195_afe_rates[i].reg_value;
+
+ return -EINVAL;
+}
+
+static int mt8195_memif_fs(struct snd_pcm_substream *substream,
+ unsigned int rate)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component =
+ snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[id];
+ int fs = mt8195_afe_fs_timing(rate);
+
+ switch (memif->data->id) {
+ case MT8195_AFE_MEMIF_DL10:
+ fs = MT8195_ETDM_OUT3_1X_EN;
+ break;
+ case MT8195_AFE_MEMIF_UL8:
+ fs = MT8195_ETDM_IN1_NX_EN;
+ break;
+ case MT8195_AFE_MEMIF_UL3:
+ fs = MT8195_ETDM_IN2_NX_EN;
+ break;
+ default:
+ break;
+ }
+
+ return fs;
+}
+
+static int mt8195_irq_fs(struct snd_pcm_substream *substream,
+ unsigned int rate)
+{
+ int fs = mt8195_memif_fs(substream, rate);
+
+ switch (fs) {
+ case MT8195_ETDM_IN1_NX_EN:
+ fs = MT8195_ETDM_IN1_1X_EN;
+ break;
+ case MT8195_ETDM_IN2_NX_EN:
+ fs = MT8195_ETDM_IN2_1X_EN;
+ break;
+ default:
+ break;
+ }
+
+ return fs;
+}
+
+enum {
+ MT8195_AFE_CM0,
+ MT8195_AFE_CM1,
+ MT8195_AFE_CM2,
+ MT8195_AFE_CM_NUM,
+};
+
+struct mt8195_afe_channel_merge {
+ int id;
+ int reg;
+ unsigned int sel_shift;
+ unsigned int sel_maskbit;
+ unsigned int sel_default;
+ unsigned int ch_num_shift;
+ unsigned int ch_num_maskbit;
+ unsigned int en_shift;
+ unsigned int en_maskbit;
+ unsigned int update_cnt_shift;
+ unsigned int update_cnt_maskbit;
+ unsigned int update_cnt_default;
+};
+
+static const struct mt8195_afe_channel_merge
+ mt8195_afe_cm[MT8195_AFE_CM_NUM] = {
+ [MT8195_AFE_CM0] = {
+ .id = MT8195_AFE_CM0,
+ .reg = AFE_CM0_CON,
+ .sel_shift = 30,
+ .sel_maskbit = 0x1,
+ .sel_default = 1,
+ .ch_num_shift = 2,
+ .ch_num_maskbit = 0x3f,
+ .en_shift = 0,
+ .en_maskbit = 0x1,
+ .update_cnt_shift = 16,
+ .update_cnt_maskbit = 0x1fff,
+ .update_cnt_default = 0x3,
+ },
+ [MT8195_AFE_CM1] = {
+ .id = MT8195_AFE_CM1,
+ .reg = AFE_CM1_CON,
+ .sel_shift = 30,
+ .sel_maskbit = 0x1,
+ .sel_default = 1,
+ .ch_num_shift = 2,
+ .ch_num_maskbit = 0x1f,
+ .en_shift = 0,
+ .en_maskbit = 0x1,
+ .update_cnt_shift = 16,
+ .update_cnt_maskbit = 0x1fff,
+ .update_cnt_default = 0x3,
+ },
+ [MT8195_AFE_CM2] = {
+ .id = MT8195_AFE_CM2,
+ .reg = AFE_CM2_CON,
+ .sel_shift = 30,
+ .sel_maskbit = 0x1,
+ .sel_default = 1,
+ .ch_num_shift = 2,
+ .ch_num_maskbit = 0x1f,
+ .en_shift = 0,
+ .en_maskbit = 0x1,
+ .update_cnt_shift = 16,
+ .update_cnt_maskbit = 0x1fff,
+ .update_cnt_default = 0x3,
+ },
+};
+
+static int mt8195_afe_memif_is_ul(int id)
+{
+ if (id >= MT8195_AFE_MEMIF_UL_START && id < MT8195_AFE_MEMIF_END)
+ return 1;
+ else
+ return 0;
+}
+
+static const struct mt8195_afe_channel_merge*
+mt8195_afe_found_cm(struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int id = -EINVAL;
+
+ if (mt8195_afe_memif_is_ul(dai->id) == 0)
+ return NULL;
+
+ switch (dai->id) {
+ case MT8195_AFE_MEMIF_UL9:
+ id = MT8195_AFE_CM0;
+ break;
+ case MT8195_AFE_MEMIF_UL2:
+ id = MT8195_AFE_CM1;
+ break;
+ case MT8195_AFE_MEMIF_UL10:
+ id = MT8195_AFE_CM2;
+ break;
+ default:
+ break;
+ }
+
+ if (id < 0) {
+ dev_dbg(afe->dev, "%s, memif %d cannot find CM!\n",
+ __func__, dai->id);
+ return NULL;
+ }
+
+ return &mt8195_afe_cm[id];
+}
+
+static int mt8195_afe_config_cm(struct mtk_base_afe *afe,
+ const struct mt8195_afe_channel_merge *cm,
+ unsigned int channels)
+{
+ if (!cm)
+ return -EINVAL;
+
+ regmap_update_bits(afe->regmap,
+ cm->reg,
+ cm->sel_maskbit << cm->sel_shift,
+ cm->sel_default << cm->sel_shift);
+
+ regmap_update_bits(afe->regmap,
+ cm->reg,
+ cm->ch_num_maskbit << cm->ch_num_shift,
+ (channels - 1) << cm->ch_num_shift);
+
+ regmap_update_bits(afe->regmap,
+ cm->reg,
+ cm->update_cnt_maskbit << cm->update_cnt_shift,
+ cm->update_cnt_default << cm->update_cnt_shift);
+
+ return 0;
+}
+
+static int mt8195_afe_enable_cm(struct mtk_base_afe *afe,
+ const struct mt8195_afe_channel_merge *cm,
+ bool enable)
+{
+ if (!cm)
+ return -EINVAL;
+
+ regmap_update_bits(afe->regmap,
+ cm->reg,
+ cm->en_maskbit << cm->en_shift,
+ enable << cm->en_shift);
+
+ return 0;
+}
+
+static int
+mt8195_afe_paired_memif_clk_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai,
+ int enable)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ int clk_id;
+
+ if (id != MT8195_AFE_MEMIF_DL8 && id != MT8195_AFE_MEMIF_DL10)
+ return 0;
+
+ if (enable) {
+ clk_id = MT8195_CLK_AUD_MEMIF_DL10;
+ mt8195_afe_prepare_clk(afe, afe_priv->clk[clk_id]);
+ clk_id = MT8195_CLK_AUD_MEMIF_DL8;
+ mt8195_afe_prepare_clk(afe, afe_priv->clk[clk_id]);
+ } else {
+ clk_id = MT8195_CLK_AUD_MEMIF_DL8;
+ mt8195_afe_unprepare_clk(afe, afe_priv->clk[clk_id]);
+ clk_id = MT8195_CLK_AUD_MEMIF_DL10;
+ mt8195_afe_unprepare_clk(afe, afe_priv->clk[clk_id]);
+ }
+
+ return 0;
+}
+
+static int
+mt8195_afe_paired_memif_clk_enable(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai,
+ int enable)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ int clk_id;
+
+ if (id != MT8195_AFE_MEMIF_DL8 && id != MT8195_AFE_MEMIF_DL10)
+ return 0;
+
+ if (enable) {
+ /* DL8_DL10_MEM */
+ clk_id = MT8195_CLK_AUD_MEMIF_DL10;
+ mt8195_afe_enable_clk_atomic(afe, afe_priv->clk[clk_id]);
+ udelay(1);
+ /* DL8_DL10_AGENT */
+ clk_id = MT8195_CLK_AUD_MEMIF_DL8;
+ mt8195_afe_enable_clk_atomic(afe, afe_priv->clk[clk_id]);
+ } else {
+ /* DL8_DL10_AGENT */
+ clk_id = MT8195_CLK_AUD_MEMIF_DL8;
+ mt8195_afe_disable_clk_atomic(afe, afe_priv->clk[clk_id]);
+ /* DL8_DL10_MEM */
+ clk_id = MT8195_CLK_AUD_MEMIF_DL10;
+ mt8195_afe_disable_clk_atomic(afe, afe_priv->clk[clk_id]);
+ }
+
+ return 0;
+}
+
+static int mt8195_afe_fe_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ int ret = 0;
+
+ mt8195_afe_paired_memif_clk_prepare(substream, dai, 1);
+
+ ret = mtk_afe_fe_startup(substream, dai);
+
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ MT8195_MEMIF_BUFFER_BYTES_ALIGN);
+
+ if (id != MT8195_AFE_MEMIF_DL7)
+ goto out;
+
+ ret = snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 1,
+ MT8195_MEMIF_DL7_MAX_PERIOD_SIZE);
+ if (ret < 0)
+ dev_dbg(afe->dev, "hw_constraint_minmax failed\n");
+out:
+ return ret;
+}
+
+static void mt8195_afe_fe_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ mtk_afe_fe_shutdown(substream, dai);
+ mt8195_afe_paired_memif_clk_prepare(substream, dai, 0);
+}
+
+static int mt8195_afe_fe_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int id = asoc_rtd_to_cpu(rtd, 0)->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[id];
+ const struct mtk_base_memif_data *data = memif->data;
+ const struct mt8195_afe_channel_merge *cm = mt8195_afe_found_cm(dai);
+ unsigned int ch_num = params_channels(params);
+
+ mt8195_afe_config_cm(afe, cm, params_channels(params));
+
+ if (data->ch_num_reg >= 0) {
+ regmap_update_bits(afe->regmap, data->ch_num_reg,
+ data->ch_num_maskbit << data->ch_num_shift,
+ ch_num << data->ch_num_shift);
+ }
+
+ return mtk_afe_fe_hw_params(substream, params, dai);
+}
+
+static int mt8195_afe_fe_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ return mtk_afe_fe_hw_free(substream, dai);
+}
+
+static int mt8195_afe_fe_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ return mtk_afe_fe_prepare(substream, dai);
+}
+
+static int mt8195_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ int ret = 0;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ const struct mt8195_afe_channel_merge *cm = mt8195_afe_found_cm(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ mt8195_afe_enable_cm(afe, cm, true);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ mt8195_afe_enable_cm(afe, cm, false);
+ break;
+ default:
+ break;
+ }
+
+ ret = mtk_afe_fe_trigger(substream, cmd, dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ mt8195_afe_paired_memif_clk_enable(substream, dai, 1);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ mt8195_afe_paired_memif_clk_enable(substream, dai, 0);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int mt8195_afe_fe_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ return 0;
+}
+
+static const struct snd_soc_dai_ops mt8195_afe_fe_dai_ops = {
+ .startup = mt8195_afe_fe_startup,
+ .shutdown = mt8195_afe_fe_shutdown,
+ .hw_params = mt8195_afe_fe_hw_params,
+ .hw_free = mt8195_afe_fe_hw_free,
+ .prepare = mt8195_afe_fe_prepare,
+ .trigger = mt8195_afe_fe_trigger,
+ .set_fmt = mt8195_afe_fe_set_fmt,
+};
+
+#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\
+ SNDRV_PCM_RATE_88200 |\
+ SNDRV_PCM_RATE_96000 |\
+ SNDRV_PCM_RATE_176400 |\
+ SNDRV_PCM_RATE_192000 |\
+ SNDRV_PCM_RATE_352800 |\
+ SNDRV_PCM_RATE_384000)
+
+#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mt8195_memif_dai_driver[] = {
+ /* FE DAIs: memory intefaces to CPU */
+ {
+ .name = "DL2",
+ .id = MT8195_AFE_MEMIF_DL2,
+ .playback = {
+ .stream_name = "DL2",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "DL3",
+ .id = MT8195_AFE_MEMIF_DL3,
+ .playback = {
+ .stream_name = "DL3",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "DL6",
+ .id = MT8195_AFE_MEMIF_DL6,
+ .playback = {
+ .stream_name = "DL6",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "DL7",
+ .id = MT8195_AFE_MEMIF_DL7,
+ .playback = {
+ .stream_name = "DL7",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "DL8",
+ .id = MT8195_AFE_MEMIF_DL8,
+ .playback = {
+ .stream_name = "DL8",
+ .channels_min = 1,
+ .channels_max = 24,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "DL10",
+ .id = MT8195_AFE_MEMIF_DL10,
+ .playback = {
+ .stream_name = "DL10",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "DL11",
+ .id = MT8195_AFE_MEMIF_DL11,
+ .playback = {
+ .stream_name = "DL11",
+ .channels_min = 1,
+ .channels_max = 48,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL1",
+ .id = MT8195_AFE_MEMIF_UL1,
+ .capture = {
+ .stream_name = "UL1",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL2",
+ .id = MT8195_AFE_MEMIF_UL2,
+ .capture = {
+ .stream_name = "UL2",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL3",
+ .id = MT8195_AFE_MEMIF_UL3,
+ .capture = {
+ .stream_name = "UL3",
+ .channels_min = 1,
+ .channels_max = 16,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL4",
+ .id = MT8195_AFE_MEMIF_UL4,
+ .capture = {
+ .stream_name = "UL4",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL5",
+ .id = MT8195_AFE_MEMIF_UL5,
+ .capture = {
+ .stream_name = "UL5",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL6",
+ .id = MT8195_AFE_MEMIF_UL6,
+ .capture = {
+ .stream_name = "UL6",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL8",
+ .id = MT8195_AFE_MEMIF_UL8,
+ .capture = {
+ .stream_name = "UL8",
+ .channels_min = 1,
+ .channels_max = 24,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL9",
+ .id = MT8195_AFE_MEMIF_UL9,
+ .capture = {
+ .stream_name = "UL9",
+ .channels_min = 1,
+ .channels_max = 32,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+ {
+ .name = "UL10",
+ .id = MT8195_AFE_MEMIF_UL10,
+ .capture = {
+ .stream_name = "UL10",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mt8195_afe_fe_dai_ops,
+ },
+};
+
+static const struct snd_kcontrol_new o002_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN2, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN2, 12, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN2, 20, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN2, 22, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN2_2, 6, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN2_2, 8, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN2_5, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new o003_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN3, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN3, 13, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN3, 21, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN3, 23, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN3_2, 7, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN3_2, 9, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN3_5, 9, 1, 0),
+};
+
+static const struct snd_kcontrol_new o004_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN4, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I014 Switch", AFE_CONN4, 14, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN4, 24, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I074 Switch", AFE_CONN4_2, 10, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN4_5, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new o005_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN5, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I015 Switch", AFE_CONN5, 15, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN5, 25, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I075 Switch", AFE_CONN5_2, 11, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN5_5, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new o006_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN6, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I016 Switch", AFE_CONN6, 16, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN6, 26, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I076 Switch", AFE_CONN6_2, 12, 1, 0),
+};
+
+static const struct snd_kcontrol_new o007_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN7, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I017 Switch", AFE_CONN7, 17, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN7, 27, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I077 Switch", AFE_CONN7_2, 13, 1, 0),
+};
+
+static const struct snd_kcontrol_new o008_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I018 Switch", AFE_CONN8, 18, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN8, 28, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I078 Switch", AFE_CONN8_2, 14, 1, 0),
+};
+
+static const struct snd_kcontrol_new o009_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I019 Switch", AFE_CONN9, 19, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN9, 29, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I079 Switch", AFE_CONN9_2, 15, 1, 0),
+};
+
+static const struct snd_kcontrol_new o010_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN10, 22, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN10, 30, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN10_1, 14, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN10_2, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new o011_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN11, 23, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN11, 31, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN11_1, 15, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN11_2, 9, 1, 0),
+};
+
+static const struct snd_kcontrol_new o012_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN12, 24, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN12_1, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN12_1, 16, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I074 Switch", AFE_CONN12_2, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new o013_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN13, 25, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN13_1, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN13_1, 17, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I075 Switch", AFE_CONN13_2, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new o014_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN14, 26, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN14_1, 2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN14_1, 18, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I076 Switch", AFE_CONN14_2, 12, 1, 0),
+};
+
+static const struct snd_kcontrol_new o015_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN15, 27, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN15_1, 3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN15_1, 19, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I077 Switch", AFE_CONN15_2, 13, 1, 0),
+};
+
+static const struct snd_kcontrol_new o016_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN16, 28, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN16_1, 4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN16_1, 20, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I078 Switch", AFE_CONN16_2, 14, 1, 0),
+};
+
+static const struct snd_kcontrol_new o017_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN17, 29, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN17_1, 5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN17_1, 21, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I079 Switch", AFE_CONN17_2, 15, 1, 0),
+};
+
+static const struct snd_kcontrol_new o018_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN18_1, 6, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I080 Switch", AFE_CONN18_2, 16, 1, 0),
+};
+
+static const struct snd_kcontrol_new o019_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN19_1, 7, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I081 Switch", AFE_CONN19_2, 17, 1, 0),
+};
+
+static const struct snd_kcontrol_new o020_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN20_1, 8, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I082 Switch", AFE_CONN20_2, 18, 1, 0),
+};
+
+static const struct snd_kcontrol_new o021_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN21_1, 9, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I083 Switch", AFE_CONN21_2, 19, 1, 0),
+};
+
+static const struct snd_kcontrol_new o022_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN22_1, 10, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I084 Switch", AFE_CONN22_2, 20, 1, 0),
+};
+
+static const struct snd_kcontrol_new o023_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN23_1, 11, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I085 Switch", AFE_CONN23_2, 21, 1, 0),
+};
+
+static const struct snd_kcontrol_new o024_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN24_1, 12, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I086 Switch", AFE_CONN24_2, 22, 1, 0),
+};
+
+static const struct snd_kcontrol_new o025_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN25_1, 13, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I087 Switch", AFE_CONN25_2, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new o026_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN26_1, 14, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I088 Switch", AFE_CONN26_2, 24, 1, 0),
+};
+
+static const struct snd_kcontrol_new o027_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN27_1, 15, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I089 Switch", AFE_CONN27_2, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new o028_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN28_1, 16, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I090 Switch", AFE_CONN28_2, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new o029_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN29_1, 17, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I091 Switch", AFE_CONN29_2, 27, 1, 0),
+};
+
+static const struct snd_kcontrol_new o030_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN30_1, 18, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I092 Switch", AFE_CONN30_2, 28, 1, 0),
+};
+
+static const struct snd_kcontrol_new o031_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN31_1, 19, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I093 Switch", AFE_CONN31_2, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new o032_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN32_1, 20, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I094 Switch", AFE_CONN32_2, 30, 1, 0),
+};
+
+static const struct snd_kcontrol_new o033_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN33_1, 21, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I095 Switch", AFE_CONN33_2, 31, 1, 0),
+};
+
+static const struct snd_kcontrol_new o034_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN34, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN34, 2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN34, 12, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN34, 20, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN34_2, 6, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN34_2, 8, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN34_5, 8, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN34_5, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new o035_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN35, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN35, 3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN35, 13, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN35, 21, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN35_2, 7, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN35_2, 9, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I137 Switch", AFE_CONN35_4, 9, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I139 Switch", AFE_CONN35_4, 11, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN35_5, 8, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN35_5, 9, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN35_5, 10, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN35_5, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new o036_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN36, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN36, 12, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN36, 20, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN36_2, 6, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN36_5, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new o037_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN37, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN37, 13, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN37, 21, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN37_2, 7, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN37_5, 9, 1, 0),
+};
+
+static const struct snd_kcontrol_new o038_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN38, 22, 1, 0),
+};
+
+static const struct snd_kcontrol_new o039_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN39, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new o040_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN40, 2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN40, 12, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN40, 22, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN40_5, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new o041_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN41, 3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN41, 13, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN41, 23, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN41_5, 9, 1, 0),
+};
+
+static const struct snd_kcontrol_new o042_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I014 Switch", AFE_CONN42, 14, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN42, 24, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN42_5, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new o043_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I015 Switch", AFE_CONN43, 15, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN43, 25, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN43_5, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new o044_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I016 Switch", AFE_CONN44, 16, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN44, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new o045_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I017 Switch", AFE_CONN45, 17, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN45, 27, 1, 0),
+};
+
+static const struct snd_kcontrol_new o046_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I018 Switch", AFE_CONN46, 18, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN46, 28, 1, 0),
+};
+
+static const struct snd_kcontrol_new o047_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I019 Switch", AFE_CONN47, 19, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN47, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new o182_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN182, 24, 1, 0),
+};
+
+static const struct snd_kcontrol_new o183_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN183, 25, 1, 0),
+};
+
+static const char * const dl8_dl11_data_sel_mux_text[] = {
+ "dl8", "dl11",
+};
+
+static SOC_ENUM_SINGLE_DECL(dl8_dl11_data_sel_mux_enum,
+ AFE_DAC_CON2, 0, dl8_dl11_data_sel_mux_text);
+
+static const struct snd_kcontrol_new dl8_dl11_data_sel_mux =
+ SOC_DAPM_ENUM("DL8_DL11 Sink", dl8_dl11_data_sel_mux_enum);
+
+static const struct snd_soc_dapm_widget mt8195_memif_widgets[] = {
+ /* DL6 */
+ SND_SOC_DAPM_MIXER("I000", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I001", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DL3 */
+ SND_SOC_DAPM_MIXER("I020", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I021", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DL11 */
+ SND_SOC_DAPM_MIXER("I022", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I023", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I024", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I025", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I026", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I027", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I028", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I029", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I030", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I031", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I032", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I033", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I034", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I035", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I036", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I037", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I038", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I039", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I040", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I041", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I042", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I043", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I044", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I045", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DL11/DL8 */
+ SND_SOC_DAPM_MIXER("I046", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I047", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I048", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I049", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I050", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I051", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I052", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I053", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I054", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I055", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I056", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I057", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I058", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I059", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I060", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I061", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I062", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I063", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I064", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I065", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I066", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I067", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I068", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I069", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DL2 */
+ SND_SOC_DAPM_MIXER("I070", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I071", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("DL8_DL11 Mux",
+ SND_SOC_NOPM, 0, 0, &dl8_dl11_data_sel_mux),
+
+ /* UL9 */
+ SND_SOC_DAPM_MIXER("O002", SND_SOC_NOPM, 0, 0,
+ o002_mix, ARRAY_SIZE(o002_mix)),
+ SND_SOC_DAPM_MIXER("O003", SND_SOC_NOPM, 0, 0,
+ o003_mix, ARRAY_SIZE(o003_mix)),
+ SND_SOC_DAPM_MIXER("O004", SND_SOC_NOPM, 0, 0,
+ o004_mix, ARRAY_SIZE(o004_mix)),
+ SND_SOC_DAPM_MIXER("O005", SND_SOC_NOPM, 0, 0,
+ o005_mix, ARRAY_SIZE(o005_mix)),
+ SND_SOC_DAPM_MIXER("O006", SND_SOC_NOPM, 0, 0,
+ o006_mix, ARRAY_SIZE(o006_mix)),
+ SND_SOC_DAPM_MIXER("O007", SND_SOC_NOPM, 0, 0,
+ o007_mix, ARRAY_SIZE(o007_mix)),
+ SND_SOC_DAPM_MIXER("O008", SND_SOC_NOPM, 0, 0,
+ o008_mix, ARRAY_SIZE(o008_mix)),
+ SND_SOC_DAPM_MIXER("O009", SND_SOC_NOPM, 0, 0,
+ o009_mix, ARRAY_SIZE(o009_mix)),
+ SND_SOC_DAPM_MIXER("O010", SND_SOC_NOPM, 0, 0,
+ o010_mix, ARRAY_SIZE(o010_mix)),
+ SND_SOC_DAPM_MIXER("O011", SND_SOC_NOPM, 0, 0,
+ o011_mix, ARRAY_SIZE(o011_mix)),
+ SND_SOC_DAPM_MIXER("O012", SND_SOC_NOPM, 0, 0,
+ o012_mix, ARRAY_SIZE(o012_mix)),
+ SND_SOC_DAPM_MIXER("O013", SND_SOC_NOPM, 0, 0,
+ o013_mix, ARRAY_SIZE(o013_mix)),
+ SND_SOC_DAPM_MIXER("O014", SND_SOC_NOPM, 0, 0,
+ o014_mix, ARRAY_SIZE(o014_mix)),
+ SND_SOC_DAPM_MIXER("O015", SND_SOC_NOPM, 0, 0,
+ o015_mix, ARRAY_SIZE(o015_mix)),
+ SND_SOC_DAPM_MIXER("O016", SND_SOC_NOPM, 0, 0,
+ o016_mix, ARRAY_SIZE(o016_mix)),
+ SND_SOC_DAPM_MIXER("O017", SND_SOC_NOPM, 0, 0,
+ o017_mix, ARRAY_SIZE(o017_mix)),
+ SND_SOC_DAPM_MIXER("O018", SND_SOC_NOPM, 0, 0,
+ o018_mix, ARRAY_SIZE(o018_mix)),
+ SND_SOC_DAPM_MIXER("O019", SND_SOC_NOPM, 0, 0,
+ o019_mix, ARRAY_SIZE(o019_mix)),
+ SND_SOC_DAPM_MIXER("O020", SND_SOC_NOPM, 0, 0,
+ o020_mix, ARRAY_SIZE(o020_mix)),
+ SND_SOC_DAPM_MIXER("O021", SND_SOC_NOPM, 0, 0,
+ o021_mix, ARRAY_SIZE(o021_mix)),
+ SND_SOC_DAPM_MIXER("O022", SND_SOC_NOPM, 0, 0,
+ o022_mix, ARRAY_SIZE(o022_mix)),
+ SND_SOC_DAPM_MIXER("O023", SND_SOC_NOPM, 0, 0,
+ o023_mix, ARRAY_SIZE(o023_mix)),
+ SND_SOC_DAPM_MIXER("O024", SND_SOC_NOPM, 0, 0,
+ o024_mix, ARRAY_SIZE(o024_mix)),
+ SND_SOC_DAPM_MIXER("O025", SND_SOC_NOPM, 0, 0,
+ o025_mix, ARRAY_SIZE(o025_mix)),
+ SND_SOC_DAPM_MIXER("O026", SND_SOC_NOPM, 0, 0,
+ o026_mix, ARRAY_SIZE(o026_mix)),
+ SND_SOC_DAPM_MIXER("O027", SND_SOC_NOPM, 0, 0,
+ o027_mix, ARRAY_SIZE(o027_mix)),
+ SND_SOC_DAPM_MIXER("O028", SND_SOC_NOPM, 0, 0,
+ o028_mix, ARRAY_SIZE(o028_mix)),
+ SND_SOC_DAPM_MIXER("O029", SND_SOC_NOPM, 0, 0,
+ o029_mix, ARRAY_SIZE(o029_mix)),
+ SND_SOC_DAPM_MIXER("O030", SND_SOC_NOPM, 0, 0,
+ o030_mix, ARRAY_SIZE(o030_mix)),
+ SND_SOC_DAPM_MIXER("O031", SND_SOC_NOPM, 0, 0,
+ o031_mix, ARRAY_SIZE(o031_mix)),
+ SND_SOC_DAPM_MIXER("O032", SND_SOC_NOPM, 0, 0,
+ o032_mix, ARRAY_SIZE(o032_mix)),
+ SND_SOC_DAPM_MIXER("O033", SND_SOC_NOPM, 0, 0,
+ o033_mix, ARRAY_SIZE(o033_mix)),
+
+ /* UL4 */
+ SND_SOC_DAPM_MIXER("O034", SND_SOC_NOPM, 0, 0,
+ o034_mix, ARRAY_SIZE(o034_mix)),
+ SND_SOC_DAPM_MIXER("O035", SND_SOC_NOPM, 0, 0,
+ o035_mix, ARRAY_SIZE(o035_mix)),
+
+ /* UL5 */
+ SND_SOC_DAPM_MIXER("O036", SND_SOC_NOPM, 0, 0,
+ o036_mix, ARRAY_SIZE(o036_mix)),
+ SND_SOC_DAPM_MIXER("O037", SND_SOC_NOPM, 0, 0,
+ o037_mix, ARRAY_SIZE(o037_mix)),
+
+ /* UL10 */
+ SND_SOC_DAPM_MIXER("O038", SND_SOC_NOPM, 0, 0,
+ o038_mix, ARRAY_SIZE(o038_mix)),
+ SND_SOC_DAPM_MIXER("O039", SND_SOC_NOPM, 0, 0,
+ o039_mix, ARRAY_SIZE(o039_mix)),
+ SND_SOC_DAPM_MIXER("O182", SND_SOC_NOPM, 0, 0,
+ o182_mix, ARRAY_SIZE(o182_mix)),
+ SND_SOC_DAPM_MIXER("O183", SND_SOC_NOPM, 0, 0,
+ o183_mix, ARRAY_SIZE(o183_mix)),
+
+ /* UL2 */
+ SND_SOC_DAPM_MIXER("O040", SND_SOC_NOPM, 0, 0,
+ o040_mix, ARRAY_SIZE(o040_mix)),
+ SND_SOC_DAPM_MIXER("O041", SND_SOC_NOPM, 0, 0,
+ o041_mix, ARRAY_SIZE(o041_mix)),
+ SND_SOC_DAPM_MIXER("O042", SND_SOC_NOPM, 0, 0,
+ o042_mix, ARRAY_SIZE(o042_mix)),
+ SND_SOC_DAPM_MIXER("O043", SND_SOC_NOPM, 0, 0,
+ o043_mix, ARRAY_SIZE(o043_mix)),
+ SND_SOC_DAPM_MIXER("O044", SND_SOC_NOPM, 0, 0,
+ o044_mix, ARRAY_SIZE(o044_mix)),
+ SND_SOC_DAPM_MIXER("O045", SND_SOC_NOPM, 0, 0,
+ o045_mix, ARRAY_SIZE(o045_mix)),
+ SND_SOC_DAPM_MIXER("O046", SND_SOC_NOPM, 0, 0,
+ o046_mix, ARRAY_SIZE(o046_mix)),
+ SND_SOC_DAPM_MIXER("O047", SND_SOC_NOPM, 0, 0,
+ o047_mix, ARRAY_SIZE(o047_mix)),
+};
+
+static const struct snd_soc_dapm_route mt8195_memif_routes[] = {
+ {"I000", NULL, "DL6"},
+ {"I001", NULL, "DL6"},
+
+ {"I020", NULL, "DL3"},
+ {"I021", NULL, "DL3"},
+
+ {"I022", NULL, "DL11"},
+ {"I023", NULL, "DL11"},
+ {"I024", NULL, "DL11"},
+ {"I025", NULL, "DL11"},
+ {"I026", NULL, "DL11"},
+ {"I027", NULL, "DL11"},
+ {"I028", NULL, "DL11"},
+ {"I029", NULL, "DL11"},
+ {"I030", NULL, "DL11"},
+ {"I031", NULL, "DL11"},
+ {"I032", NULL, "DL11"},
+ {"I033", NULL, "DL11"},
+ {"I034", NULL, "DL11"},
+ {"I035", NULL, "DL11"},
+ {"I036", NULL, "DL11"},
+ {"I037", NULL, "DL11"},
+ {"I038", NULL, "DL11"},
+ {"I039", NULL, "DL11"},
+ {"I040", NULL, "DL11"},
+ {"I041", NULL, "DL11"},
+ {"I042", NULL, "DL11"},
+ {"I043", NULL, "DL11"},
+ {"I044", NULL, "DL11"},
+ {"I045", NULL, "DL11"},
+
+ {"DL8_DL11 Mux", "dl8", "DL8"},
+ {"DL8_DL11 Mux", "dl11", "DL11"},
+
+ {"I046", NULL, "DL8_DL11 Mux"},
+ {"I047", NULL, "DL8_DL11 Mux"},
+ {"I048", NULL, "DL8_DL11 Mux"},
+ {"I049", NULL, "DL8_DL11 Mux"},
+ {"I050", NULL, "DL8_DL11 Mux"},
+ {"I051", NULL, "DL8_DL11 Mux"},
+ {"I052", NULL, "DL8_DL11 Mux"},
+ {"I053", NULL, "DL8_DL11 Mux"},
+ {"I054", NULL, "DL8_DL11 Mux"},
+ {"I055", NULL, "DL8_DL11 Mux"},
+ {"I056", NULL, "DL8_DL11 Mux"},
+ {"I057", NULL, "DL8_DL11 Mux"},
+ {"I058", NULL, "DL8_DL11 Mux"},
+ {"I059", NULL, "DL8_DL11 Mux"},
+ {"I060", NULL, "DL8_DL11 Mux"},
+ {"I061", NULL, "DL8_DL11 Mux"},
+ {"I062", NULL, "DL8_DL11 Mux"},
+ {"I063", NULL, "DL8_DL11 Mux"},
+ {"I064", NULL, "DL8_DL11 Mux"},
+ {"I065", NULL, "DL8_DL11 Mux"},
+ {"I066", NULL, "DL8_DL11 Mux"},
+ {"I067", NULL, "DL8_DL11 Mux"},
+ {"I068", NULL, "DL8_DL11 Mux"},
+ {"I069", NULL, "DL8_DL11 Mux"},
+
+ {"I070", NULL, "DL2"},
+ {"I071", NULL, "DL2"},
+
+ {"UL9", NULL, "O002"},
+ {"UL9", NULL, "O003"},
+ {"UL9", NULL, "O004"},
+ {"UL9", NULL, "O005"},
+ {"UL9", NULL, "O006"},
+ {"UL9", NULL, "O007"},
+ {"UL9", NULL, "O008"},
+ {"UL9", NULL, "O009"},
+ {"UL9", NULL, "O010"},
+ {"UL9", NULL, "O011"},
+ {"UL9", NULL, "O012"},
+ {"UL9", NULL, "O013"},
+ {"UL9", NULL, "O014"},
+ {"UL9", NULL, "O015"},
+ {"UL9", NULL, "O016"},
+ {"UL9", NULL, "O017"},
+ {"UL9", NULL, "O018"},
+ {"UL9", NULL, "O019"},
+ {"UL9", NULL, "O020"},
+ {"UL9", NULL, "O021"},
+ {"UL9", NULL, "O022"},
+ {"UL9", NULL, "O023"},
+ {"UL9", NULL, "O024"},
+ {"UL9", NULL, "O025"},
+ {"UL9", NULL, "O026"},
+ {"UL9", NULL, "O027"},
+ {"UL9", NULL, "O028"},
+ {"UL9", NULL, "O029"},
+ {"UL9", NULL, "O030"},
+ {"UL9", NULL, "O031"},
+ {"UL9", NULL, "O032"},
+ {"UL9", NULL, "O033"},
+
+ {"UL4", NULL, "O034"},
+ {"UL4", NULL, "O035"},
+
+ {"UL5", NULL, "O036"},
+ {"UL5", NULL, "O037"},
+
+ {"UL10", NULL, "O038"},
+ {"UL10", NULL, "O039"},
+ {"UL10", NULL, "O182"},
+ {"UL10", NULL, "O183"},
+
+ {"UL2", NULL, "O040"},
+ {"UL2", NULL, "O041"},
+ {"UL2", NULL, "O042"},
+ {"UL2", NULL, "O043"},
+ {"UL2", NULL, "O044"},
+ {"UL2", NULL, "O045"},
+ {"UL2", NULL, "O046"},
+ {"UL2", NULL, "O047"},
+
+ {"O004", "I000 Switch", "I000"},
+ {"O005", "I001 Switch", "I001"},
+
+ {"O006", "I000 Switch", "I000"},
+ {"O007", "I001 Switch", "I001"},
+
+ {"O010", "I022 Switch", "I022"},
+ {"O011", "I023 Switch", "I023"},
+ {"O012", "I024 Switch", "I024"},
+ {"O013", "I025 Switch", "I025"},
+ {"O014", "I026 Switch", "I026"},
+ {"O015", "I027 Switch", "I027"},
+ {"O016", "I028 Switch", "I028"},
+ {"O017", "I029 Switch", "I029"},
+
+ {"O010", "I046 Switch", "I046"},
+ {"O011", "I047 Switch", "I047"},
+ {"O012", "I048 Switch", "I048"},
+ {"O013", "I049 Switch", "I049"},
+ {"O014", "I050 Switch", "I050"},
+ {"O015", "I051 Switch", "I051"},
+ {"O016", "I052 Switch", "I052"},
+ {"O017", "I053 Switch", "I053"},
+ {"O002", "I022 Switch", "I022"},
+ {"O003", "I023 Switch", "I023"},
+ {"O004", "I024 Switch", "I024"},
+ {"O005", "I025 Switch", "I025"},
+ {"O006", "I026 Switch", "I026"},
+ {"O007", "I027 Switch", "I027"},
+ {"O008", "I028 Switch", "I028"},
+ {"O009", "I029 Switch", "I029"},
+ {"O010", "I030 Switch", "I030"},
+ {"O011", "I031 Switch", "I031"},
+ {"O012", "I032 Switch", "I032"},
+ {"O013", "I033 Switch", "I033"},
+ {"O014", "I034 Switch", "I034"},
+ {"O015", "I035 Switch", "I035"},
+ {"O016", "I036 Switch", "I036"},
+ {"O017", "I037 Switch", "I037"},
+ {"O018", "I038 Switch", "I038"},
+ {"O019", "I039 Switch", "I039"},
+ {"O020", "I040 Switch", "I040"},
+ {"O021", "I041 Switch", "I041"},
+ {"O022", "I042 Switch", "I042"},
+ {"O023", "I043 Switch", "I043"},
+ {"O024", "I044 Switch", "I044"},
+ {"O025", "I045 Switch", "I045"},
+ {"O026", "I046 Switch", "I046"},
+ {"O027", "I047 Switch", "I047"},
+ {"O028", "I048 Switch", "I048"},
+ {"O029", "I049 Switch", "I049"},
+ {"O030", "I050 Switch", "I050"},
+ {"O031", "I051 Switch", "I051"},
+ {"O032", "I052 Switch", "I052"},
+ {"O033", "I053 Switch", "I053"},
+
+ {"O002", "I000 Switch", "I000"},
+ {"O003", "I001 Switch", "I001"},
+ {"O002", "I020 Switch", "I020"},
+ {"O003", "I021 Switch", "I021"},
+ {"O002", "I070 Switch", "I070"},
+ {"O003", "I071 Switch", "I071"},
+
+ {"O034", "I000 Switch", "I000"},
+ {"O035", "I001 Switch", "I001"},
+ {"O034", "I002 Switch", "I002"},
+ {"O035", "I003 Switch", "I003"},
+ {"O034", "I012 Switch", "I012"},
+ {"O035", "I013 Switch", "I013"},
+ {"O034", "I020 Switch", "I020"},
+ {"O035", "I021 Switch", "I021"},
+ {"O034", "I070 Switch", "I070"},
+ {"O035", "I071 Switch", "I071"},
+ {"O034", "I072 Switch", "I072"},
+ {"O035", "I073 Switch", "I073"},
+
+ {"O036", "I000 Switch", "I000"},
+ {"O037", "I001 Switch", "I001"},
+ {"O036", "I012 Switch", "I012"},
+ {"O037", "I013 Switch", "I013"},
+ {"O036", "I020 Switch", "I020"},
+ {"O037", "I021 Switch", "I021"},
+ {"O036", "I070 Switch", "I070"},
+ {"O037", "I071 Switch", "I071"},
+ {"O036", "I168 Switch", "I168"},
+ {"O037", "I169 Switch", "I169"},
+
+ {"O038", "I022 Switch", "I022"},
+ {"O039", "I023 Switch", "I023"},
+ {"O182", "I024 Switch", "I024"},
+ {"O183", "I025 Switch", "I025"},
+
+ {"O040", "I022 Switch", "I022"},
+ {"O041", "I023 Switch", "I023"},
+ {"O042", "I024 Switch", "I024"},
+ {"O043", "I025 Switch", "I025"},
+ {"O044", "I026 Switch", "I026"},
+ {"O045", "I027 Switch", "I027"},
+ {"O046", "I028 Switch", "I028"},
+ {"O047", "I029 Switch", "I029"},
+
+ {"O040", "I002 Switch", "I002"},
+ {"O041", "I003 Switch", "I003"},
+ {"O002", "I012 Switch", "I012"},
+ {"O003", "I013 Switch", "I013"},
+ {"O004", "I014 Switch", "I014"},
+ {"O005", "I015 Switch", "I015"},
+ {"O006", "I016 Switch", "I016"},
+ {"O007", "I017 Switch", "I017"},
+ {"O008", "I018 Switch", "I018"},
+ {"O009", "I019 Switch", "I019"},
+
+ {"O040", "I012 Switch", "I012"},
+ {"O041", "I013 Switch", "I013"},
+ {"O042", "I014 Switch", "I014"},
+ {"O043", "I015 Switch", "I015"},
+ {"O044", "I016 Switch", "I016"},
+ {"O045", "I017 Switch", "I017"},
+ {"O046", "I018 Switch", "I018"},
+ {"O047", "I019 Switch", "I019"},
+
+ {"O002", "I072 Switch", "I072"},
+ {"O003", "I073 Switch", "I073"},
+ {"O004", "I074 Switch", "I074"},
+ {"O005", "I075 Switch", "I075"},
+ {"O006", "I076 Switch", "I076"},
+ {"O007", "I077 Switch", "I077"},
+ {"O008", "I078 Switch", "I078"},
+ {"O009", "I079 Switch", "I079"},
+
+ {"O010", "I072 Switch", "I072"},
+ {"O011", "I073 Switch", "I073"},
+ {"O012", "I074 Switch", "I074"},
+ {"O013", "I075 Switch", "I075"},
+ {"O014", "I076 Switch", "I076"},
+ {"O015", "I077 Switch", "I077"},
+ {"O016", "I078 Switch", "I078"},
+ {"O017", "I079 Switch", "I079"},
+ {"O018", "I080 Switch", "I080"},
+ {"O019", "I081 Switch", "I081"},
+ {"O020", "I082 Switch", "I082"},
+ {"O021", "I083 Switch", "I083"},
+ {"O022", "I084 Switch", "I084"},
+ {"O023", "I085 Switch", "I085"},
+ {"O024", "I086 Switch", "I086"},
+ {"O025", "I087 Switch", "I087"},
+ {"O026", "I088 Switch", "I088"},
+ {"O027", "I089 Switch", "I089"},
+ {"O028", "I090 Switch", "I090"},
+ {"O029", "I091 Switch", "I091"},
+ {"O030", "I092 Switch", "I092"},
+ {"O031", "I093 Switch", "I093"},
+ {"O032", "I094 Switch", "I094"},
+ {"O033", "I095 Switch", "I095"},
+
+ {"O002", "I168 Switch", "I168"},
+ {"O003", "I169 Switch", "I169"},
+ {"O004", "I170 Switch", "I170"},
+ {"O005", "I171 Switch", "I171"},
+
+ {"O034", "I168 Switch", "I168"},
+ {"O035", "I168 Switch", "I168"},
+ {"O035", "I169 Switch", "I169"},
+
+ {"O034", "I170 Switch", "I170"},
+ {"O035", "I170 Switch", "I170"},
+ {"O035", "I171 Switch", "I171"},
+
+ {"O040", "I168 Switch", "I168"},
+ {"O041", "I169 Switch", "I169"},
+ {"O042", "I170 Switch", "I170"},
+ {"O043", "I171 Switch", "I171"},
+};
+
+static const char * const mt8195_afe_1x_en_sel_text[] = {
+ "a1sys_a2sys", "a3sys", "a4sys",
+};
+
+static const unsigned int mt8195_afe_1x_en_sel_values[] = {
+ 0, 1, 2,
+};
+
+static int mt8195_memif_1x_en_sel_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_memif_priv *memif_priv;
+ unsigned int dai_id = kcontrol->id.device;
+ long val = ucontrol->value.integer.value[0];
+ int ret = 0;
+
+ memif_priv = afe_priv->dai_priv[dai_id];
+
+ if (val == memif_priv->asys_timing_sel)
+ return 0;
+
+ ret = snd_soc_put_enum_double(kcontrol, ucontrol);
+
+ memif_priv->asys_timing_sel = val;
+
+ return ret;
+}
+
+static int mt8195_asys_irq_1x_en_sel_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ unsigned int id = kcontrol->id.device;
+ long val = ucontrol->value.integer.value[0];
+ int ret = 0;
+
+ if (val == afe_priv->irq_priv[id].asys_timing_sel)
+ return 0;
+
+ ret = snd_soc_put_enum_double(kcontrol, ucontrol);
+
+ afe_priv->irq_priv[id].asys_timing_sel = val;
+
+ return ret;
+}
+
+static SOC_VALUE_ENUM_SINGLE_DECL(dl2_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 18, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl3_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 20, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl6_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 22, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl7_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 24, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl8_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 26, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl10_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 28, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(dl11_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 30, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul1_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 0, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul2_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 2, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul3_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 4, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul4_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 6, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul5_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 8, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul6_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 10, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul8_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 12, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul9_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 14, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(ul10_1x_en_sel_enum,
+ A3_A4_TIMING_SEL1, 16, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq1_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 0, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq2_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 2, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq3_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 4, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq4_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 6, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq5_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 8, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq6_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 10, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq7_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 12, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq8_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 14, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq9_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 16, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq10_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 18, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq11_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 20, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq12_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 22, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq13_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 24, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq14_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 26, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq15_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 28, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq16_1x_en_sel_enum,
+ A3_A4_TIMING_SEL6, 30, 0x3,
+ mt8195_afe_1x_en_sel_text,
+ mt8195_afe_1x_en_sel_values);
+
+static const struct snd_kcontrol_new mt8195_memif_controls[] = {
+ MT8195_SOC_ENUM_EXT("dl2_1x_en_sel",
+ dl2_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_DL2),
+ MT8195_SOC_ENUM_EXT("dl3_1x_en_sel",
+ dl3_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_DL3),
+ MT8195_SOC_ENUM_EXT("dl6_1x_en_sel",
+ dl6_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_DL6),
+ MT8195_SOC_ENUM_EXT("dl7_1x_en_sel",
+ dl7_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_DL7),
+ MT8195_SOC_ENUM_EXT("dl8_1x_en_sel",
+ dl8_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_DL8),
+ MT8195_SOC_ENUM_EXT("dl10_1x_en_sel",
+ dl10_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_DL10),
+ MT8195_SOC_ENUM_EXT("dl11_1x_en_sel",
+ dl11_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_DL11),
+ MT8195_SOC_ENUM_EXT("ul1_1x_en_sel",
+ ul1_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL1),
+ MT8195_SOC_ENUM_EXT("ul2_1x_en_sel",
+ ul2_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL2),
+ MT8195_SOC_ENUM_EXT("ul3_1x_en_sel",
+ ul3_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL3),
+ MT8195_SOC_ENUM_EXT("ul4_1x_en_sel",
+ ul4_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL4),
+ MT8195_SOC_ENUM_EXT("ul5_1x_en_sel",
+ ul5_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL5),
+ MT8195_SOC_ENUM_EXT("ul6_1x_en_sel",
+ ul6_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL6),
+ MT8195_SOC_ENUM_EXT("ul8_1x_en_sel",
+ ul8_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL8),
+ MT8195_SOC_ENUM_EXT("ul9_1x_en_sel",
+ ul9_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL9),
+ MT8195_SOC_ENUM_EXT("ul10_1x_en_sel",
+ ul10_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_memif_1x_en_sel_put,
+ MT8195_AFE_MEMIF_UL10),
+ MT8195_SOC_ENUM_EXT("asys_irq1_1x_en_sel",
+ asys_irq1_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_13),
+ MT8195_SOC_ENUM_EXT("asys_irq2_1x_en_sel",
+ asys_irq2_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_14),
+ MT8195_SOC_ENUM_EXT("asys_irq3_1x_en_sel",
+ asys_irq3_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_15),
+ MT8195_SOC_ENUM_EXT("asys_irq4_1x_en_sel",
+ asys_irq4_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_16),
+ MT8195_SOC_ENUM_EXT("asys_irq5_1x_en_sel",
+ asys_irq5_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_17),
+ MT8195_SOC_ENUM_EXT("asys_irq6_1x_en_sel",
+ asys_irq6_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_18),
+ MT8195_SOC_ENUM_EXT("asys_irq7_1x_en_sel",
+ asys_irq7_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_19),
+ MT8195_SOC_ENUM_EXT("asys_irq8_1x_en_sel",
+ asys_irq8_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_20),
+ MT8195_SOC_ENUM_EXT("asys_irq9_1x_en_sel",
+ asys_irq9_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_21),
+ MT8195_SOC_ENUM_EXT("asys_irq10_1x_en_sel",
+ asys_irq10_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_22),
+ MT8195_SOC_ENUM_EXT("asys_irq11_1x_en_sel",
+ asys_irq11_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_23),
+ MT8195_SOC_ENUM_EXT("asys_irq12_1x_en_sel",
+ asys_irq12_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_24),
+ MT8195_SOC_ENUM_EXT("asys_irq13_1x_en_sel",
+ asys_irq13_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_25),
+ MT8195_SOC_ENUM_EXT("asys_irq14_1x_en_sel",
+ asys_irq14_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_26),
+ MT8195_SOC_ENUM_EXT("asys_irq15_1x_en_sel",
+ asys_irq15_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_27),
+ MT8195_SOC_ENUM_EXT("asys_irq16_1x_en_sel",
+ asys_irq16_1x_en_sel_enum,
+ snd_soc_get_enum_double,
+ mt8195_asys_irq_1x_en_sel_put,
+ MT8195_AFE_IRQ_28),
+};
+
+static const struct snd_soc_component_driver mt8195_afe_pcm_dai_component = {
+ .name = "mt8195-afe-pcm-dai",
+};
+
+static const struct mtk_base_memif_data memif_data[MT8195_AFE_MEMIF_NUM] = {
+ [MT8195_AFE_MEMIF_DL2] = {
+ .name = "DL2",
+ .id = MT8195_AFE_MEMIF_DL2,
+ .reg_ofs_base = AFE_DL2_BASE,
+ .reg_ofs_cur = AFE_DL2_CUR,
+ .reg_ofs_end = AFE_DL2_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON0,
+ .fs_shift = 10,
+ .fs_maskbit = 0x1f,
+ .mono_reg = -1,
+ .mono_shift = 0,
+ .int_odd_flag_reg = -1,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 18,
+ .hd_reg = AFE_DL2_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 18,
+ .ch_num_reg = AFE_DL2_CON0,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0x1f,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 18,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 18,
+ },
+ [MT8195_AFE_MEMIF_DL3] = {
+ .name = "DL3",
+ .id = MT8195_AFE_MEMIF_DL3,
+ .reg_ofs_base = AFE_DL3_BASE,
+ .reg_ofs_cur = AFE_DL3_CUR,
+ .reg_ofs_end = AFE_DL3_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON0,
+ .fs_shift = 15,
+ .fs_maskbit = 0x1f,
+ .mono_reg = -1,
+ .mono_shift = 0,
+ .int_odd_flag_reg = -1,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 19,
+ .hd_reg = AFE_DL3_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 19,
+ .ch_num_reg = AFE_DL3_CON0,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0x1f,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 19,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 19,
+ },
+ [MT8195_AFE_MEMIF_DL6] = {
+ .name = "DL6",
+ .id = MT8195_AFE_MEMIF_DL6,
+ .reg_ofs_base = AFE_DL6_BASE,
+ .reg_ofs_cur = AFE_DL6_CUR,
+ .reg_ofs_end = AFE_DL6_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON1,
+ .fs_shift = 0,
+ .fs_maskbit = 0x1f,
+ .mono_reg = -1,
+ .mono_shift = 0,
+ .int_odd_flag_reg = -1,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 22,
+ .hd_reg = AFE_DL6_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 22,
+ .ch_num_reg = AFE_DL6_CON0,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0x1f,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 22,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 22,
+ },
+ [MT8195_AFE_MEMIF_DL7] = {
+ .name = "DL7",
+ .id = MT8195_AFE_MEMIF_DL7,
+ .reg_ofs_base = AFE_DL7_BASE,
+ .reg_ofs_cur = AFE_DL7_CUR,
+ .reg_ofs_end = AFE_DL7_END,
+ .fs_reg = -1,
+ .fs_shift = 0,
+ .fs_maskbit = 0,
+ .mono_reg = -1,
+ .mono_shift = 0,
+ .int_odd_flag_reg = -1,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 23,
+ .hd_reg = AFE_DL7_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 23,
+ .ch_num_reg = AFE_DL7_CON0,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0x1f,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 23,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 23,
+ },
+ [MT8195_AFE_MEMIF_DL8] = {
+ .name = "DL8",
+ .id = MT8195_AFE_MEMIF_DL8,
+ .reg_ofs_base = AFE_DL8_BASE,
+ .reg_ofs_cur = AFE_DL8_CUR,
+ .reg_ofs_end = AFE_DL8_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON1,
+ .fs_shift = 10,
+ .fs_maskbit = 0x1f,
+ .mono_reg = -1,
+ .mono_shift = 0,
+ .int_odd_flag_reg = -1,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 24,
+ .hd_reg = AFE_DL8_CON0,
+ .hd_shift = 6,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = 0,
+ .ch_num_reg = AFE_DL8_CON0,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0x3f,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 24,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 24,
+ },
+ [MT8195_AFE_MEMIF_DL10] = {
+ .name = "DL10",
+ .id = MT8195_AFE_MEMIF_DL10,
+ .reg_ofs_base = AFE_DL10_BASE,
+ .reg_ofs_cur = AFE_DL10_CUR,
+ .reg_ofs_end = AFE_DL10_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON1,
+ .fs_shift = 20,
+ .fs_maskbit = 0x1f,
+ .mono_reg = -1,
+ .mono_shift = 0,
+ .int_odd_flag_reg = -1,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 26,
+ .hd_reg = AFE_DL10_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = 0,
+ .ch_num_reg = AFE_DL10_CON0,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0x1f,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 26,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 26,
+ },
+ [MT8195_AFE_MEMIF_DL11] = {
+ .name = "DL11",
+ .id = MT8195_AFE_MEMIF_DL11,
+ .reg_ofs_base = AFE_DL11_BASE,
+ .reg_ofs_cur = AFE_DL11_CUR,
+ .reg_ofs_end = AFE_DL11_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON1,
+ .fs_shift = 25,
+ .fs_maskbit = 0x1f,
+ .mono_reg = -1,
+ .mono_shift = 0,
+ .int_odd_flag_reg = -1,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 27,
+ .hd_reg = AFE_DL11_CON0,
+ .hd_shift = 7,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 27,
+ .ch_num_reg = AFE_DL11_CON0,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0x7f,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 27,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 27,
+ },
+ [MT8195_AFE_MEMIF_UL1] = {
+ .name = "UL1",
+ .id = MT8195_AFE_MEMIF_UL1,
+ .reg_ofs_base = AFE_UL1_BASE,
+ .reg_ofs_cur = AFE_UL1_CUR,
+ .reg_ofs_end = AFE_UL1_END,
+ .fs_reg = -1,
+ .fs_shift = 0,
+ .fs_maskbit = 0,
+ .mono_reg = AFE_UL1_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL1_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 1,
+ .hd_reg = AFE_UL1_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 0,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 0,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 0,
+ },
+ [MT8195_AFE_MEMIF_UL2] = {
+ .name = "UL2",
+ .id = MT8195_AFE_MEMIF_UL2,
+ .reg_ofs_base = AFE_UL2_BASE,
+ .reg_ofs_cur = AFE_UL2_CUR,
+ .reg_ofs_end = AFE_UL2_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON2,
+ .fs_shift = 5,
+ .fs_maskbit = 0x1f,
+ .mono_reg = AFE_UL2_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL2_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 2,
+ .hd_reg = AFE_UL2_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 1,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 1,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 1,
+ },
+ [MT8195_AFE_MEMIF_UL3] = {
+ .name = "UL3",
+ .id = MT8195_AFE_MEMIF_UL3,
+ .reg_ofs_base = AFE_UL3_BASE,
+ .reg_ofs_cur = AFE_UL3_CUR,
+ .reg_ofs_end = AFE_UL3_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON2,
+ .fs_shift = 10,
+ .fs_maskbit = 0x1f,
+ .mono_reg = AFE_UL3_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL3_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 3,
+ .hd_reg = AFE_UL3_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 2,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 2,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 2,
+ },
+ [MT8195_AFE_MEMIF_UL4] = {
+ .name = "UL4",
+ .id = MT8195_AFE_MEMIF_UL4,
+ .reg_ofs_base = AFE_UL4_BASE,
+ .reg_ofs_cur = AFE_UL4_CUR,
+ .reg_ofs_end = AFE_UL4_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON2,
+ .fs_shift = 15,
+ .fs_maskbit = 0x1f,
+ .mono_reg = AFE_UL4_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL4_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 4,
+ .hd_reg = AFE_UL4_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 3,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 3,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 3,
+ },
+ [MT8195_AFE_MEMIF_UL5] = {
+ .name = "UL5",
+ .id = MT8195_AFE_MEMIF_UL5,
+ .reg_ofs_base = AFE_UL5_BASE,
+ .reg_ofs_cur = AFE_UL5_CUR,
+ .reg_ofs_end = AFE_UL5_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON2,
+ .fs_shift = 20,
+ .fs_maskbit = 0x1f,
+ .mono_reg = AFE_UL5_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL5_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 5,
+ .hd_reg = AFE_UL5_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 4,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 4,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 4,
+ },
+ [MT8195_AFE_MEMIF_UL6] = {
+ .name = "UL6",
+ .id = MT8195_AFE_MEMIF_UL6,
+ .reg_ofs_base = AFE_UL6_BASE,
+ .reg_ofs_cur = AFE_UL6_CUR,
+ .reg_ofs_end = AFE_UL6_END,
+ .fs_reg = -1,
+ .fs_shift = 0,
+ .fs_maskbit = 0,
+ .mono_reg = AFE_UL6_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL6_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 6,
+ .hd_reg = AFE_UL6_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 5,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 5,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 5,
+ },
+ [MT8195_AFE_MEMIF_UL8] = {
+ .name = "UL8",
+ .id = MT8195_AFE_MEMIF_UL8,
+ .reg_ofs_base = AFE_UL8_BASE,
+ .reg_ofs_cur = AFE_UL8_CUR,
+ .reg_ofs_end = AFE_UL8_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON3,
+ .fs_shift = 5,
+ .fs_maskbit = 0x1f,
+ .mono_reg = AFE_UL8_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL8_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 8,
+ .hd_reg = AFE_UL8_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 7,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 7,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 7,
+ },
+ [MT8195_AFE_MEMIF_UL9] = {
+ .name = "UL9",
+ .id = MT8195_AFE_MEMIF_UL9,
+ .reg_ofs_base = AFE_UL9_BASE,
+ .reg_ofs_cur = AFE_UL9_CUR,
+ .reg_ofs_end = AFE_UL9_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON3,
+ .fs_shift = 10,
+ .fs_maskbit = 0x1f,
+ .mono_reg = AFE_UL9_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL9_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 9,
+ .hd_reg = AFE_UL9_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 8,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 8,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 8,
+ },
+ [MT8195_AFE_MEMIF_UL10] = {
+ .name = "UL10",
+ .id = MT8195_AFE_MEMIF_UL10,
+ .reg_ofs_base = AFE_UL10_BASE,
+ .reg_ofs_cur = AFE_UL10_CUR,
+ .reg_ofs_end = AFE_UL10_END,
+ .fs_reg = AFE_MEMIF_AGENT_FS_CON3,
+ .fs_shift = 15,
+ .fs_maskbit = 0x1f,
+ .mono_reg = AFE_UL10_CON0,
+ .mono_shift = 1,
+ .int_odd_flag_reg = AFE_UL10_CON0,
+ .int_odd_flag_shift = 0,
+ .enable_reg = AFE_DAC_CON0,
+ .enable_shift = 10,
+ .hd_reg = AFE_UL10_CON0,
+ .hd_shift = 5,
+ .agent_disable_reg = AUDIO_TOP_CON5,
+ .agent_disable_shift = 9,
+ .ch_num_reg = -1,
+ .ch_num_shift = 0,
+ .ch_num_maskbit = 0,
+ .msb_reg = AFE_NORMAL_BASE_ADR_MSB,
+ .msb_shift = 9,
+ .msb_end_reg = AFE_NORMAL_END_ADR_MSB,
+ .msb_end_shift = 9,
+ },
+};
+
+static const struct mtk_base_irq_data irq_data[MT8195_AFE_IRQ_NUM] = {
+ [MT8195_AFE_IRQ_1] = {
+ .id = MT8195_AFE_IRQ_1,
+ .irq_cnt_reg = -1,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0,
+ .irq_fs_reg = -1,
+ .irq_fs_shift = 0,
+ .irq_fs_maskbit = 0,
+ .irq_en_reg = AFE_IRQ1_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = 0,
+ .irq_status_shift = 16,
+ },
+ [MT8195_AFE_IRQ_2] = {
+ .id = MT8195_AFE_IRQ_2,
+ .irq_cnt_reg = -1,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0,
+ .irq_fs_reg = -1,
+ .irq_fs_shift = 0,
+ .irq_fs_maskbit = 0,
+ .irq_en_reg = AFE_IRQ2_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = 1,
+ .irq_status_shift = 17,
+ },
+ [MT8195_AFE_IRQ_3] = {
+ .id = MT8195_AFE_IRQ_3,
+ .irq_cnt_reg = AFE_IRQ3_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = -1,
+ .irq_fs_shift = 0,
+ .irq_fs_maskbit = 0,
+ .irq_en_reg = AFE_IRQ3_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = 2,
+ .irq_status_shift = 18,
+ },
+ [MT8195_AFE_IRQ_8] = {
+ .id = MT8195_AFE_IRQ_8,
+ .irq_cnt_reg = -1,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0,
+ .irq_fs_reg = -1,
+ .irq_fs_shift = 0,
+ .irq_fs_maskbit = 0,
+ .irq_en_reg = AFE_IRQ8_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = 7,
+ .irq_status_shift = 23,
+ },
+ [MT8195_AFE_IRQ_9] = {
+ .id = MT8195_AFE_IRQ_9,
+ .irq_cnt_reg = AFE_IRQ9_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = -1,
+ .irq_fs_shift = 0,
+ .irq_fs_maskbit = 0,
+ .irq_en_reg = AFE_IRQ9_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = 8,
+ .irq_status_shift = 24,
+ },
+ [MT8195_AFE_IRQ_10] = {
+ .id = MT8195_AFE_IRQ_10,
+ .irq_cnt_reg = -1,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0,
+ .irq_fs_reg = -1,
+ .irq_fs_shift = 0,
+ .irq_fs_maskbit = 0,
+ .irq_en_reg = AFE_IRQ10_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = AFE_IRQ_MCU_CLR,
+ .irq_clr_shift = 9,
+ .irq_status_shift = 25,
+ },
+ [MT8195_AFE_IRQ_13] = {
+ .id = MT8195_AFE_IRQ_13,
+ .irq_cnt_reg = ASYS_IRQ1_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ1_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ1_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 0,
+ .irq_status_shift = 0,
+ },
+ [MT8195_AFE_IRQ_14] = {
+ .id = MT8195_AFE_IRQ_14,
+ .irq_cnt_reg = ASYS_IRQ2_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ2_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ2_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 1,
+ .irq_status_shift = 1,
+ },
+ [MT8195_AFE_IRQ_15] = {
+ .id = MT8195_AFE_IRQ_15,
+ .irq_cnt_reg = ASYS_IRQ3_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ3_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ3_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 2,
+ .irq_status_shift = 2,
+ },
+ [MT8195_AFE_IRQ_16] = {
+ .id = MT8195_AFE_IRQ_16,
+ .irq_cnt_reg = ASYS_IRQ4_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ4_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ4_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 3,
+ .irq_status_shift = 3,
+ },
+ [MT8195_AFE_IRQ_17] = {
+ .id = MT8195_AFE_IRQ_17,
+ .irq_cnt_reg = ASYS_IRQ5_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ5_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ5_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 4,
+ .irq_status_shift = 4,
+ },
+ [MT8195_AFE_IRQ_18] = {
+ .id = MT8195_AFE_IRQ_18,
+ .irq_cnt_reg = ASYS_IRQ6_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ6_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ6_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 5,
+ .irq_status_shift = 5,
+ },
+ [MT8195_AFE_IRQ_19] = {
+ .id = MT8195_AFE_IRQ_19,
+ .irq_cnt_reg = ASYS_IRQ7_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ7_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ7_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 6,
+ .irq_status_shift = 6,
+ },
+ [MT8195_AFE_IRQ_20] = {
+ .id = MT8195_AFE_IRQ_20,
+ .irq_cnt_reg = ASYS_IRQ8_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ8_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ8_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 7,
+ .irq_status_shift = 7,
+ },
+ [MT8195_AFE_IRQ_21] = {
+ .id = MT8195_AFE_IRQ_21,
+ .irq_cnt_reg = ASYS_IRQ9_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ9_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ9_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 8,
+ .irq_status_shift = 8,
+ },
+ [MT8195_AFE_IRQ_22] = {
+ .id = MT8195_AFE_IRQ_22,
+ .irq_cnt_reg = ASYS_IRQ10_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ10_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ10_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 9,
+ .irq_status_shift = 9,
+ },
+ [MT8195_AFE_IRQ_23] = {
+ .id = MT8195_AFE_IRQ_23,
+ .irq_cnt_reg = ASYS_IRQ11_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ11_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ11_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 10,
+ .irq_status_shift = 10,
+ },
+ [MT8195_AFE_IRQ_24] = {
+ .id = MT8195_AFE_IRQ_24,
+ .irq_cnt_reg = ASYS_IRQ12_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ12_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ12_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 11,
+ .irq_status_shift = 11,
+ },
+ [MT8195_AFE_IRQ_25] = {
+ .id = MT8195_AFE_IRQ_25,
+ .irq_cnt_reg = ASYS_IRQ13_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ13_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ13_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 12,
+ .irq_status_shift = 12,
+ },
+ [MT8195_AFE_IRQ_26] = {
+ .id = MT8195_AFE_IRQ_26,
+ .irq_cnt_reg = ASYS_IRQ14_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ14_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ14_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 13,
+ .irq_status_shift = 13,
+ },
+ [MT8195_AFE_IRQ_27] = {
+ .id = MT8195_AFE_IRQ_27,
+ .irq_cnt_reg = ASYS_IRQ15_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ15_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ15_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 14,
+ .irq_status_shift = 14,
+ },
+ [MT8195_AFE_IRQ_28] = {
+ .id = MT8195_AFE_IRQ_28,
+ .irq_cnt_reg = ASYS_IRQ16_CON,
+ .irq_cnt_shift = 0,
+ .irq_cnt_maskbit = 0xffffff,
+ .irq_fs_reg = ASYS_IRQ16_CON,
+ .irq_fs_shift = 24,
+ .irq_fs_maskbit = 0x1ffff,
+ .irq_en_reg = ASYS_IRQ16_CON,
+ .irq_en_shift = 31,
+ .irq_clr_reg = ASYS_IRQ_CLR,
+ .irq_clr_shift = 15,
+ .irq_status_shift = 15,
+ },
+};
+
+static const int mt8195_afe_memif_const_irqs[MT8195_AFE_MEMIF_NUM] = {
+ [MT8195_AFE_MEMIF_DL2] = MT8195_AFE_IRQ_13,
+ [MT8195_AFE_MEMIF_DL3] = MT8195_AFE_IRQ_14,
+ [MT8195_AFE_MEMIF_DL6] = MT8195_AFE_IRQ_15,
+ [MT8195_AFE_MEMIF_DL7] = MT8195_AFE_IRQ_1,
+ [MT8195_AFE_MEMIF_DL8] = MT8195_AFE_IRQ_16,
+ [MT8195_AFE_MEMIF_DL10] = MT8195_AFE_IRQ_17,
+ [MT8195_AFE_MEMIF_DL11] = MT8195_AFE_IRQ_18,
+ [MT8195_AFE_MEMIF_UL1] = MT8195_AFE_IRQ_3,
+ [MT8195_AFE_MEMIF_UL2] = MT8195_AFE_IRQ_19,
+ [MT8195_AFE_MEMIF_UL3] = MT8195_AFE_IRQ_20,
+ [MT8195_AFE_MEMIF_UL4] = MT8195_AFE_IRQ_21,
+ [MT8195_AFE_MEMIF_UL5] = MT8195_AFE_IRQ_22,
+ [MT8195_AFE_MEMIF_UL6] = MT8195_AFE_IRQ_9,
+ [MT8195_AFE_MEMIF_UL8] = MT8195_AFE_IRQ_23,
+ [MT8195_AFE_MEMIF_UL9] = MT8195_AFE_IRQ_24,
+ [MT8195_AFE_MEMIF_UL10] = MT8195_AFE_IRQ_25,
+};
+
+static bool mt8195_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ /* these auto-gen reg has read-only bit, so put it as volatile */
+ /* volatile reg cannot be cached, so cannot be set when power off */
+ switch (reg) {
+ case AUDIO_TOP_CON0:
+ case AUDIO_TOP_CON1:
+ case AUDIO_TOP_CON3:
+ case AUDIO_TOP_CON4:
+ case AUDIO_TOP_CON5:
+ case AUDIO_TOP_CON6:
+ case ASYS_IRQ_CLR:
+ case ASYS_IRQ_STATUS:
+ case ASYS_IRQ_MON1:
+ case ASYS_IRQ_MON2:
+ case AFE_IRQ_MCU_CLR:
+ case AFE_IRQ_STATUS:
+ case AFE_IRQ3_CON_MON:
+ case AFE_IRQ_MCU_MON2:
+ case ADSP_IRQ_STATUS:
+ case AFE_APLL_TUNER_CFG:
+ case AFE_APLL_TUNER_CFG1:
+ case AUDIO_TOP_STA0:
+ case AUDIO_TOP_STA1:
+ case AFE_GAIN1_CUR:
+ case AFE_GAIN2_CUR:
+ case AFE_IEC_BURST_INFO:
+ case AFE_IEC_CHL_STAT0:
+ case AFE_IEC_CHL_STAT1:
+ case AFE_IEC_CHR_STAT0:
+ case AFE_IEC_CHR_STAT1:
+ case AFE_SPDIFIN_CHSTS1:
+ case AFE_SPDIFIN_CHSTS2:
+ case AFE_SPDIFIN_CHSTS3:
+ case AFE_SPDIFIN_CHSTS4:
+ case AFE_SPDIFIN_CHSTS5:
+ case AFE_SPDIFIN_CHSTS6:
+ case AFE_SPDIFIN_DEBUG1:
+ case AFE_SPDIFIN_DEBUG2:
+ case AFE_SPDIFIN_DEBUG3:
+ case AFE_SPDIFIN_DEBUG4:
+ case AFE_SPDIFIN_EC:
+ case AFE_SPDIFIN_CKLOCK_CFG:
+ case AFE_SPDIFIN_BR_DBG1:
+ case AFE_SPDIFIN_CKFBDIV:
+ case AFE_SPDIFIN_INT_EXT:
+ case AFE_SPDIFIN_INT_EXT2:
+ case SPDIFIN_FREQ_STATUS:
+ case SPDIFIN_USERCODE1:
+ case SPDIFIN_USERCODE2:
+ case SPDIFIN_USERCODE3:
+ case SPDIFIN_USERCODE4:
+ case SPDIFIN_USERCODE5:
+ case SPDIFIN_USERCODE6:
+ case SPDIFIN_USERCODE7:
+ case SPDIFIN_USERCODE8:
+ case SPDIFIN_USERCODE9:
+ case SPDIFIN_USERCODE10:
+ case SPDIFIN_USERCODE11:
+ case SPDIFIN_USERCODE12:
+ case AFE_SPDIFIN_APLL_TUNER_CFG:
+ case AFE_LINEIN_APLL_TUNER_MON:
+ case AFE_EARC_APLL_TUNER_MON:
+ case AFE_CM0_MON:
+ case AFE_CM1_MON:
+ case AFE_CM2_MON:
+ case AFE_MPHONE_MULTI_DET_MON0:
+ case AFE_MPHONE_MULTI_DET_MON1:
+ case AFE_MPHONE_MULTI_DET_MON2:
+ case AFE_MPHONE_MULTI2_DET_MON0:
+ case AFE_MPHONE_MULTI2_DET_MON1:
+ case AFE_MPHONE_MULTI2_DET_MON2:
+ case AFE_ADDA_MTKAIF_MON0:
+ case AFE_ADDA_MTKAIF_MON1:
+ case AFE_AUD_PAD_TOP:
+ case AFE_ADDA6_MTKAIF_MON0:
+ case AFE_ADDA6_MTKAIF_MON1:
+ case AFE_ADDA6_SRC_DEBUG_MON0:
+ case AFE_ADDA6_UL_SRC_MON0:
+ case AFE_ADDA6_UL_SRC_MON1:
+ case AFE_ASRC11_NEW_CON8:
+ case AFE_ASRC11_NEW_CON9:
+ case AFE_ASRC12_NEW_CON8:
+ case AFE_ASRC12_NEW_CON9:
+ case AFE_LRCK_CNT:
+ case AFE_DAC_MON0:
+ case AFE_DL2_CUR:
+ case AFE_DL3_CUR:
+ case AFE_DL6_CUR:
+ case AFE_DL7_CUR:
+ case AFE_DL8_CUR:
+ case AFE_DL10_CUR:
+ case AFE_DL11_CUR:
+ case AFE_UL1_CUR:
+ case AFE_UL2_CUR:
+ case AFE_UL3_CUR:
+ case AFE_UL4_CUR:
+ case AFE_UL5_CUR:
+ case AFE_UL6_CUR:
+ case AFE_UL8_CUR:
+ case AFE_UL9_CUR:
+ case AFE_UL10_CUR:
+ case AFE_DL8_CHK_SUM1:
+ case AFE_DL8_CHK_SUM2:
+ case AFE_DL8_CHK_SUM3:
+ case AFE_DL8_CHK_SUM4:
+ case AFE_DL8_CHK_SUM5:
+ case AFE_DL8_CHK_SUM6:
+ case AFE_DL10_CHK_SUM1:
+ case AFE_DL10_CHK_SUM2:
+ case AFE_DL10_CHK_SUM3:
+ case AFE_DL10_CHK_SUM4:
+ case AFE_DL10_CHK_SUM5:
+ case AFE_DL10_CHK_SUM6:
+ case AFE_DL11_CHK_SUM1:
+ case AFE_DL11_CHK_SUM2:
+ case AFE_DL11_CHK_SUM3:
+ case AFE_DL11_CHK_SUM4:
+ case AFE_DL11_CHK_SUM5:
+ case AFE_DL11_CHK_SUM6:
+ case AFE_UL1_CHK_SUM1:
+ case AFE_UL1_CHK_SUM2:
+ case AFE_UL2_CHK_SUM1:
+ case AFE_UL2_CHK_SUM2:
+ case AFE_UL3_CHK_SUM1:
+ case AFE_UL3_CHK_SUM2:
+ case AFE_UL4_CHK_SUM1:
+ case AFE_UL4_CHK_SUM2:
+ case AFE_UL5_CHK_SUM1:
+ case AFE_UL5_CHK_SUM2:
+ case AFE_UL6_CHK_SUM1:
+ case AFE_UL6_CHK_SUM2:
+ case AFE_UL8_CHK_SUM1:
+ case AFE_UL8_CHK_SUM2:
+ case AFE_DL2_CHK_SUM1:
+ case AFE_DL2_CHK_SUM2:
+ case AFE_DL3_CHK_SUM1:
+ case AFE_DL3_CHK_SUM2:
+ case AFE_DL6_CHK_SUM1:
+ case AFE_DL6_CHK_SUM2:
+ case AFE_DL7_CHK_SUM1:
+ case AFE_DL7_CHK_SUM2:
+ case AFE_UL9_CHK_SUM1:
+ case AFE_UL9_CHK_SUM2:
+ case AFE_BUS_MON1:
+ case UL1_MOD2AGT_CNT_LAT:
+ case UL2_MOD2AGT_CNT_LAT:
+ case UL3_MOD2AGT_CNT_LAT:
+ case UL4_MOD2AGT_CNT_LAT:
+ case UL5_MOD2AGT_CNT_LAT:
+ case UL6_MOD2AGT_CNT_LAT:
+ case UL8_MOD2AGT_CNT_LAT:
+ case UL9_MOD2AGT_CNT_LAT:
+ case UL10_MOD2AGT_CNT_LAT:
+ case AFE_MEMIF_BUF_FULL_MON:
+ case AFE_MEMIF_BUF_MON1:
+ case AFE_MEMIF_BUF_MON3:
+ case AFE_MEMIF_BUF_MON4:
+ case AFE_MEMIF_BUF_MON5:
+ case AFE_MEMIF_BUF_MON6:
+ case AFE_MEMIF_BUF_MON7:
+ case AFE_MEMIF_BUF_MON8:
+ case AFE_MEMIF_BUF_MON9:
+ case AFE_MEMIF_BUF_MON10:
+ case DL2_AGENT2MODULE_CNT:
+ case DL3_AGENT2MODULE_CNT:
+ case DL6_AGENT2MODULE_CNT:
+ case DL7_AGENT2MODULE_CNT:
+ case DL8_AGENT2MODULE_CNT:
+ case DL10_AGENT2MODULE_CNT:
+ case DL11_AGENT2MODULE_CNT:
+ case UL1_MODULE2AGENT_CNT:
+ case UL2_MODULE2AGENT_CNT:
+ case UL3_MODULE2AGENT_CNT:
+ case UL4_MODULE2AGENT_CNT:
+ case UL5_MODULE2AGENT_CNT:
+ case UL6_MODULE2AGENT_CNT:
+ case UL8_MODULE2AGENT_CNT:
+ case UL9_MODULE2AGENT_CNT:
+ case UL10_MODULE2AGENT_CNT:
+ case AFE_DMIC0_SRC_DEBUG_MON0:
+ case AFE_DMIC0_UL_SRC_MON0:
+ case AFE_DMIC0_UL_SRC_MON1:
+ case AFE_DMIC1_SRC_DEBUG_MON0:
+ case AFE_DMIC1_UL_SRC_MON0:
+ case AFE_DMIC1_UL_SRC_MON1:
+ case AFE_DMIC2_SRC_DEBUG_MON0:
+ case AFE_DMIC2_UL_SRC_MON0:
+ case AFE_DMIC2_UL_SRC_MON1:
+ case AFE_DMIC3_SRC_DEBUG_MON0:
+ case AFE_DMIC3_UL_SRC_MON0:
+ case AFE_DMIC3_UL_SRC_MON1:
+ case DMIC_GAIN1_CUR:
+ case DMIC_GAIN2_CUR:
+ case DMIC_GAIN3_CUR:
+ case DMIC_GAIN4_CUR:
+ case ETDM_IN1_MONITOR:
+ case ETDM_IN2_MONITOR:
+ case ETDM_OUT1_MONITOR:
+ case ETDM_OUT2_MONITOR:
+ case ETDM_OUT3_MONITOR:
+ case AFE_ADDA_SRC_DEBUG_MON0:
+ case AFE_ADDA_SRC_DEBUG_MON1:
+ case AFE_ADDA_DL_SDM_FIFO_MON:
+ case AFE_ADDA_DL_SRC_LCH_MON:
+ case AFE_ADDA_DL_SRC_RCH_MON:
+ case AFE_ADDA_DL_SDM_OUT_MON:
+ case AFE_GASRC0_NEW_CON8:
+ case AFE_GASRC0_NEW_CON9:
+ case AFE_GASRC0_NEW_CON12:
+ case AFE_GASRC1_NEW_CON8:
+ case AFE_GASRC1_NEW_CON9:
+ case AFE_GASRC1_NEW_CON12:
+ case AFE_GASRC2_NEW_CON8:
+ case AFE_GASRC2_NEW_CON9:
+ case AFE_GASRC2_NEW_CON12:
+ case AFE_GASRC3_NEW_CON8:
+ case AFE_GASRC3_NEW_CON9:
+ case AFE_GASRC3_NEW_CON12:
+ case AFE_GASRC4_NEW_CON8:
+ case AFE_GASRC4_NEW_CON9:
+ case AFE_GASRC4_NEW_CON12:
+ case AFE_GASRC5_NEW_CON8:
+ case AFE_GASRC5_NEW_CON9:
+ case AFE_GASRC5_NEW_CON12:
+ case AFE_GASRC6_NEW_CON8:
+ case AFE_GASRC6_NEW_CON9:
+ case AFE_GASRC6_NEW_CON12:
+ case AFE_GASRC7_NEW_CON8:
+ case AFE_GASRC7_NEW_CON9:
+ case AFE_GASRC7_NEW_CON12:
+ case AFE_GASRC8_NEW_CON8:
+ case AFE_GASRC8_NEW_CON9:
+ case AFE_GASRC8_NEW_CON12:
+ case AFE_GASRC9_NEW_CON8:
+ case AFE_GASRC9_NEW_CON9:
+ case AFE_GASRC9_NEW_CON12:
+ case AFE_GASRC10_NEW_CON8:
+ case AFE_GASRC10_NEW_CON9:
+ case AFE_GASRC10_NEW_CON12:
+ case AFE_GASRC11_NEW_CON8:
+ case AFE_GASRC11_NEW_CON9:
+ case AFE_GASRC11_NEW_CON12:
+ case AFE_GASRC12_NEW_CON8:
+ case AFE_GASRC12_NEW_CON9:
+ case AFE_GASRC12_NEW_CON12:
+ case AFE_GASRC13_NEW_CON8:
+ case AFE_GASRC13_NEW_CON9:
+ case AFE_GASRC13_NEW_CON12:
+ case AFE_GASRC14_NEW_CON8:
+ case AFE_GASRC14_NEW_CON9:
+ case AFE_GASRC14_NEW_CON12:
+ case AFE_GASRC15_NEW_CON8:
+ case AFE_GASRC15_NEW_CON9:
+ case AFE_GASRC15_NEW_CON12:
+ case AFE_GASRC16_NEW_CON8:
+ case AFE_GASRC16_NEW_CON9:
+ case AFE_GASRC16_NEW_CON12:
+ case AFE_GASRC17_NEW_CON8:
+ case AFE_GASRC17_NEW_CON9:
+ case AFE_GASRC17_NEW_CON12:
+ case AFE_GASRC18_NEW_CON8:
+ case AFE_GASRC18_NEW_CON9:
+ case AFE_GASRC18_NEW_CON12:
+ case AFE_GASRC19_NEW_CON8:
+ case AFE_GASRC19_NEW_CON9:
+ case AFE_GASRC19_NEW_CON12:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static const struct regmap_config mt8195_afe_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .volatile_reg = mt8195_is_volatile_reg,
+ .max_register = AFE_MAX_REGISTER,
+ .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1),
+ .cache_type = REGCACHE_FLAT,
+};
+
+#define AFE_IRQ_CLR_BITS (0x387)
+#define ASYS_IRQ_CLR_BITS (0xffff)
+
+static irqreturn_t mt8195_afe_irq_handler(int irq_id, void *dev_id)
+{
+ struct mtk_base_afe *afe = dev_id;
+ unsigned int val = 0;
+ unsigned int asys_irq_clr_bits = 0;
+ unsigned int afe_irq_clr_bits = 0;
+ unsigned int irq_status_bits = 0;
+ unsigned int irq_clr_bits = 0;
+ unsigned int mcu_irq_mask = 0;
+ int i = 0;
+ int ret = 0;
+
+ ret = regmap_read(afe->regmap, AFE_IRQ_STATUS, &val);
+ if (ret) {
+ dev_info(afe->dev, "%s irq status err\n", __func__);
+ afe_irq_clr_bits = AFE_IRQ_CLR_BITS;
+ asys_irq_clr_bits = ASYS_IRQ_CLR_BITS;
+ goto err_irq;
+ }
+
+ ret = regmap_read(afe->regmap, AFE_IRQ_MASK, &mcu_irq_mask);
+ if (ret) {
+ dev_info(afe->dev, "%s read irq mask err\n", __func__);
+ afe_irq_clr_bits = AFE_IRQ_CLR_BITS;
+ asys_irq_clr_bits = ASYS_IRQ_CLR_BITS;
+ goto err_irq;
+ }
+
+ /* only clr cpu irq */
+ val &= mcu_irq_mask;
+
+ for (i = 0; i < MT8195_AFE_MEMIF_NUM; i++) {
+ struct mtk_base_afe_memif *memif = &afe->memif[i];
+ struct mtk_base_irq_data const *irq_data;
+
+ if (memif->irq_usage < 0)
+ continue;
+
+ irq_data = afe->irqs[memif->irq_usage].irq_data;
+
+ irq_status_bits = BIT(irq_data->irq_status_shift);
+ irq_clr_bits = BIT(irq_data->irq_clr_shift);
+
+ if (!(val & irq_status_bits))
+ continue;
+
+ if (irq_data->irq_clr_reg == ASYS_IRQ_CLR)
+ asys_irq_clr_bits |= irq_clr_bits;
+ else
+ afe_irq_clr_bits |= irq_clr_bits;
+
+ snd_pcm_period_elapsed(memif->substream);
+ }
+
+err_irq:
+ /* clear irq */
+ if (asys_irq_clr_bits)
+ regmap_write(afe->regmap, ASYS_IRQ_CLR, asys_irq_clr_bits);
+ if (afe_irq_clr_bits)
+ regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, afe_irq_clr_bits);
+
+ return IRQ_HANDLED;
+}
+
+static int mt8195_afe_runtime_suspend(struct device *dev)
+{
+ struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+ if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
+ goto skip_regmap;
+
+ mt8195_afe_disable_main_clock(afe);
+
+ regcache_cache_only(afe->regmap, true);
+ regcache_mark_dirty(afe->regmap);
+
+skip_regmap:
+ mt8195_afe_disable_reg_rw_clk(afe);
+
+ return 0;
+}
+
+static int mt8195_afe_runtime_resume(struct device *dev)
+{
+ struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+ mt8195_afe_enable_reg_rw_clk(afe);
+
+ if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
+ goto skip_regmap;
+
+ regcache_cache_only(afe->regmap, false);
+ regcache_sync(afe->regmap);
+
+ mt8195_afe_enable_main_clock(afe);
+skip_regmap:
+ return 0;
+}
+
+static int mt8195_afe_component_probe(struct snd_soc_component *component)
+{
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ int ret = 0;
+
+ snd_soc_component_init_regmap(component, afe->regmap);
+
+ ret = mtk_afe_add_sub_dai_control(component);
+
+ return ret;
+}
+
+static const struct snd_soc_component_driver mt8195_afe_component = {
+ .name = AFE_PCM_NAME,
+ .pointer = mtk_afe_pcm_pointer,
+ .pcm_construct = mtk_afe_pcm_new,
+ .probe = mt8195_afe_component_probe,
+};
+
+static int init_memif_priv_data(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_memif_priv *memif_priv;
+ int i;
+
+ for (i = MT8195_AFE_MEMIF_START; i < MT8195_AFE_MEMIF_END; i++) {
+ memif_priv = devm_kzalloc(afe->dev,
+ sizeof(struct mtk_dai_memif_priv),
+ GFP_KERNEL);
+ if (!memif_priv)
+ return -ENOMEM;
+
+ afe_priv->dai_priv[i] = memif_priv;
+ }
+
+ return 0;
+}
+
+static int mt8195_dai_memif_register(struct mtk_base_afe *afe)
+{
+ struct mtk_base_afe_dai *dai;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ dai->dai_drivers = mt8195_memif_dai_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mt8195_memif_dai_driver);
+
+ dai->dapm_widgets = mt8195_memif_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mt8195_memif_widgets);
+ dai->dapm_routes = mt8195_memif_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mt8195_memif_routes);
+ dai->controls = mt8195_memif_controls;
+ dai->num_controls = ARRAY_SIZE(mt8195_memif_controls);
+
+ return init_memif_priv_data(afe);
+}
+
+typedef int (*dai_register_cb)(struct mtk_base_afe *);
+static const dai_register_cb dai_register_cbs[] = {
+ mt8195_dai_adda_register,
+ mt8195_dai_etdm_register,
+ mt8195_dai_pcm_register,
+ mt8195_dai_memif_register,
+};
+
+static const struct reg_sequence mt8195_afe_reg_defaults[] = {
+ { AFE_IRQ_MASK, 0x387ffff },
+ { AFE_IRQ3_CON, BIT(30) },
+ { AFE_IRQ9_CON, BIT(30) },
+ { ETDM_IN1_CON4, 0x12000100 },
+ { ETDM_IN2_CON4, 0x12000100 },
+};
+
+static const struct reg_sequence mt8195_cg_patch[] = {
+ { AUDIO_TOP_CON0, 0xfffffffb },
+ { AUDIO_TOP_CON1, 0xfffffffa },
+};
+
+static int mt8195_afe_init_registers(struct mtk_base_afe *afe)
+{
+ return regmap_multi_reg_write(afe->regmap,
+ mt8195_afe_reg_defaults,
+ ARRAY_SIZE(mt8195_afe_reg_defaults));
+}
+
+static void mt8195_afe_parse_of(struct mtk_base_afe *afe,
+ struct device_node *np)
+{
+#if IS_ENABLED(CONFIG_SND_SOC_MT6359)
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+ afe_priv->topckgen = syscon_regmap_lookup_by_phandle(afe->dev->of_node,
+ "mediatek,topckgen");
+ if (IS_ERR(afe_priv->topckgen)) {
+ dev_info(afe->dev, "%s() Cannot find topckgen controller: %ld\n",
+ __func__, PTR_ERR(afe_priv->topckgen));
+ }
+#endif
+}
+
+static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
+{
+ struct mtk_base_afe *afe;
+ struct mt8195_afe_private *afe_priv;
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ int i, irq_id, ret;
+ struct snd_soc_component *component;
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33));
+ if (ret)
+ return ret;
+
+ afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
+ if (!afe)
+ return -ENOMEM;
+
+ afe->platform_priv = devm_kzalloc(dev, sizeof(*afe_priv),
+ GFP_KERNEL);
+ if (!afe->platform_priv)
+ return -ENOMEM;
+
+ afe_priv = afe->platform_priv;
+ afe->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ afe->base_addr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(afe->base_addr))
+ return PTR_ERR(afe->base_addr);
+
+ /* initial audio related clock */
+ ret = mt8195_afe_init_clock(afe);
+ if (ret) {
+ dev_err(dev, "init clock error\n");
+ return ret;
+ }
+
+ spin_lock_init(&afe_priv->afe_ctrl_lock);
+
+ mutex_init(&afe->irq_alloc_lock);
+
+ /* irq initialize */
+ afe->irqs_size = MT8195_AFE_IRQ_NUM;
+ afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
+ GFP_KERNEL);
+ if (!afe->irqs)
+ return -ENOMEM;
+
+ for (i = 0; i < afe->irqs_size; i++)
+ afe->irqs[i].irq_data = &irq_data[i];
+
+ /* init memif */
+ afe->memif_size = MT8195_AFE_MEMIF_NUM;
+ afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
+ GFP_KERNEL);
+ if (!afe->memif)
+ return -ENOMEM;
+
+ for (i = 0; i < afe->memif_size; i++) {
+ afe->memif[i].data = &memif_data[i];
+ afe->memif[i].irq_usage = mt8195_afe_memif_const_irqs[i];
+ afe->memif[i].const_irq = 1;
+ afe->irqs[afe->memif[i].irq_usage].irq_occupyed = true;
+ }
+
+ /* request irq */
+ irq_id = platform_get_irq(pdev, 0);
+ if (irq_id < 0) {
+ dev_err(dev, "%s no irq found\n", dev->of_node->name);
+ return -ENXIO;
+ }
+
+ ret = devm_request_irq(dev, irq_id, mt8195_afe_irq_handler,
+ IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
+ if (ret) {
+ dev_err(dev, "could not request_irq for asys-isr\n");
+ return ret;
+ }
+
+ /* init sub_dais */
+ INIT_LIST_HEAD(&afe->sub_dais);
+
+ for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
+ ret = dai_register_cbs[i](afe);
+ if (ret) {
+ dev_warn(dev, "dai register i %d fail, ret %d\n",
+ i, ret);
+ return ret;
+ }
+ }
+
+ /* init dai_driver and component_driver */
+ ret = mtk_afe_combine_sub_dai(afe);
+ if (ret) {
+ dev_warn(dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ afe->mtk_afe_hardware = &mt8195_afe_hardware;
+ afe->memif_fs = mt8195_memif_fs;
+ afe->irq_fs = mt8195_irq_fs;
+
+ afe->runtime_resume = mt8195_afe_runtime_resume;
+ afe->runtime_suspend = mt8195_afe_runtime_suspend;
+
+ platform_set_drvdata(pdev, afe);
+
+ mt8195_afe_parse_of(afe, pdev->dev.of_node);
+
+ pm_runtime_enable(dev);
+ if (!pm_runtime_enabled(dev)) {
+ ret = mt8195_afe_runtime_resume(dev);
+ if (ret)
+ return ret;
+ }
+
+ /* enable clock for regcache get default value from hw */
+ afe_priv->pm_runtime_bypass_reg_ctl = true;
+ pm_runtime_get_sync(dev);
+
+ afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr,
+ &mt8195_afe_regmap_config);
+ if (IS_ERR(afe->regmap)) {
+ ret = PTR_ERR(afe->regmap);
+ goto err_pm_put;
+ }
+
+ ret = regmap_register_patch(afe->regmap, mt8195_cg_patch,
+ ARRAY_SIZE(mt8195_cg_patch));
+ if (ret < 0) {
+ dev_err(dev, "Failed to apply cg patch\n");
+ goto err_pm_put;
+ }
+
+ /* register component */
+ ret = devm_snd_soc_register_component(dev, &mt8195_afe_component,
+ NULL, 0);
+ if (ret) {
+ dev_warn(dev, "err_platform\n");
+ goto err_pm_put;
+ }
+
+ component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL);
+ if (!component) {
+ ret = -ENOMEM;
+ goto err_pm_put;
+ }
+
+ ret = snd_soc_component_initialize(component,
+ &mt8195_afe_pcm_dai_component,
+ dev);
+ if (ret)
+ goto err_pm_put;
+
+#ifdef CONFIG_DEBUG_FS
+ component->debugfs_prefix = "pcm";
+#endif
+
+ ret = snd_soc_add_component(component,
+ afe->dai_drivers,
+ afe->num_dai_drivers);
+ if (ret) {
+ dev_warn(dev, "err_dai_component\n");
+ goto err_pm_put;
+ }
+
+ mt8195_afe_init_registers(afe);
+
+ pm_runtime_put_sync(dev);
+ afe_priv->pm_runtime_bypass_reg_ctl = false;
+
+ regcache_cache_only(afe->regmap, true);
+ regcache_mark_dirty(afe->regmap);
+
+ return 0;
+
+err_pm_put:
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+
+ return ret;
+}
+
+static int mt8195_afe_pcm_dev_remove(struct platform_device *pdev)
+{
+ struct mtk_base_afe *afe = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_component(&pdev->dev);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ mt8195_afe_runtime_suspend(&pdev->dev);
+
+ mt8195_afe_deinit_clock(afe);
+ return 0;
+}
+
+static const struct of_device_id mt8195_afe_pcm_dt_match[] = {
+ {.compatible = "mediatek,mt8195-audio", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt8195_afe_pcm_dt_match);
+
+static const struct dev_pm_ops mt8195_afe_pm_ops = {
+ SET_RUNTIME_PM_OPS(mt8195_afe_runtime_suspend,
+ mt8195_afe_runtime_resume, NULL)
+};
+
+static struct platform_driver mt8195_afe_pcm_driver = {
+ .driver = {
+ .name = "mt8195-audio",
+ .of_match_table = mt8195_afe_pcm_dt_match,
+#ifdef CONFIG_PM
+ .pm = &mt8195_afe_pm_ops,
+#endif
+ },
+ .probe = mt8195_afe_pcm_dev_probe,
+ .remove = mt8195_afe_pcm_dev_remove,
+};
+
+module_platform_driver(mt8195_afe_pcm_driver);
+
+MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 8195");
+MODULE_AUTHOR("Bicycle Tsai <bicycle.tsai@mediatek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c
new file mode 100644
index 000000000000..740aa6ddda0e
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt8195-audsys-clk.h -- Mediatek 8195 audsys clock control
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include "mt8195-afe-common.h"
+#include "mt8195-audsys-clk.h"
+#include "mt8195-audsys-clkid.h"
+#include "mt8195-reg.h"
+
+struct afe_gate {
+ int id;
+ const char *name;
+ const char *parent_name;
+ int reg;
+ u8 bit;
+ const struct clk_ops *ops;
+ unsigned long flags;
+ u8 cg_flags;
+};
+
+#define GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, _flags, _cgflags) {\
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .reg = _reg, \
+ .bit = _bit, \
+ .flags = _flags, \
+ .cg_flags = _cgflags, \
+ }
+
+#define GATE_AFE(_id, _name, _parent, _reg, _bit) \
+ GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, \
+ CLK_SET_RATE_PARENT, CLK_GATE_SET_TO_DISABLE)
+
+#define GATE_AUD0(_id, _name, _parent, _bit) \
+ GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON0, _bit)
+
+#define GATE_AUD1(_id, _name, _parent, _bit) \
+ GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON1, _bit)
+
+#define GATE_AUD3(_id, _name, _parent, _bit) \
+ GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON3, _bit)
+
+#define GATE_AUD4(_id, _name, _parent, _bit) \
+ GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON4, _bit)
+
+#define GATE_AUD5(_id, _name, _parent, _bit) \
+ GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON5, _bit)
+
+#define GATE_AUD6(_id, _name, _parent, _bit) \
+ GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON6, _bit)
+
+static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = {
+ /* AUD0 */
+ GATE_AUD0(CLK_AUD_AFE, "aud_afe", "a1sys_hp_sel", 2),
+ GATE_AUD0(CLK_AUD_LRCK_CNT, "aud_lrck_cnt", "a1sys_hp_sel", 4),
+ GATE_AUD0(CLK_AUD_SPDIFIN_TUNER_APLL, "aud_spdifin_tuner_apll", "apll4_sel", 10),
+ GATE_AUD0(CLK_AUD_SPDIFIN_TUNER_DBG, "aud_spdifin_tuner_dbg", "apll4_sel", 11),
+ GATE_AUD0(CLK_AUD_UL_TML, "aud_ul_tml", "a1sys_hp_sel", 18),
+ GATE_AUD0(CLK_AUD_APLL1_TUNER, "aud_apll1_tuner", "apll1_sel", 19),
+ GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "apll2_sel", 20),
+ GATE_AUD0(CLK_AUD_TOP0_SPDF, "aud_top0_spdf", "aud_iec_sel", 21),
+ GATE_AUD0(CLK_AUD_APLL, "aud_apll", "apll1_sel", 23),
+ GATE_AUD0(CLK_AUD_APLL2, "aud_apll2", "apll2_sel", 24),
+ GATE_AUD0(CLK_AUD_DAC, "aud_dac", "a1sys_hp_sel", 25),
+ GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "a1sys_hp_sel", 26),
+ GATE_AUD0(CLK_AUD_TML, "aud_tml", "a1sys_hp_sel", 27),
+ GATE_AUD0(CLK_AUD_ADC, "aud_adc", "a1sys_hp_sel", 28),
+ GATE_AUD0(CLK_AUD_DAC_HIRES, "aud_dac_hires", "audio_h_sel", 31),
+
+ /* AUD1 */
+ GATE_AUD1(CLK_AUD_A1SYS_HP, "aud_a1sys_hp", "a1sys_hp_sel", 2),
+ GATE_AUD1(CLK_AUD_AFE_DMIC1, "aud_afe_dmic1", "a1sys_hp_sel", 10),
+ GATE_AUD1(CLK_AUD_AFE_DMIC2, "aud_afe_dmic2", "a1sys_hp_sel", 11),
+ GATE_AUD1(CLK_AUD_AFE_DMIC3, "aud_afe_dmic3", "a1sys_hp_sel", 12),
+ GATE_AUD1(CLK_AUD_AFE_DMIC4, "aud_afe_dmic4", "a1sys_hp_sel", 13),
+ GATE_AUD1(CLK_AUD_AFE_26M_DMIC_TM, "aud_afe_26m_dmic_tm", "a1sys_hp_sel", 14),
+ GATE_AUD1(CLK_AUD_UL_TML_HIRES, "aud_ul_tml_hires", "audio_h_sel", 16),
+ GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires", "audio_h_sel", 17),
+ GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc", "a1sys_hp_sel", 18),
+ GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", "audio_h_sel", 19),
+
+ /* AUD3 */
+ GATE_AUD3(CLK_AUD_LINEIN_TUNER, "aud_linein_tuner", "apll5_sel", 5),
+ GATE_AUD3(CLK_AUD_EARC_TUNER, "aud_earc_tuner", "apll3_sel", 7),
+
+ /* AUD4 */
+ GATE_AUD4(CLK_AUD_I2SIN, "aud_i2sin", "a1sys_hp_sel", 0),
+ GATE_AUD4(CLK_AUD_TDM_IN, "aud_tdm_in", "a1sys_hp_sel", 1),
+ GATE_AUD4(CLK_AUD_I2S_OUT, "aud_i2s_out", "a1sys_hp_sel", 6),
+ GATE_AUD4(CLK_AUD_TDM_OUT, "aud_tdm_out", "a1sys_hp_sel", 7),
+ GATE_AUD4(CLK_AUD_HDMI_OUT, "aud_hdmi_out", "a1sys_hp_sel", 8),
+ GATE_AUD4(CLK_AUD_ASRC11, "aud_asrc11", "a1sys_hp_sel", 16),
+ GATE_AUD4(CLK_AUD_ASRC12, "aud_asrc12", "a1sys_hp_sel", 17),
+ GATE_AUD4(CLK_AUD_MULTI_IN, "aud_multi_in", "mphone_slave_b", 19),
+ GATE_AUD4(CLK_AUD_INTDIR, "aud_intdir", "intdir_sel", 20),
+ GATE_AUD4(CLK_AUD_A1SYS, "aud_a1sys", "a1sys_hp_sel", 21),
+ GATE_AUD4(CLK_AUD_A2SYS, "aud_a2sys", "a2sys_sel", 22),
+ GATE_AUD4(CLK_AUD_PCMIF, "aud_pcmif", "a1sys_hp_sel", 24),
+ GATE_AUD4(CLK_AUD_A3SYS, "aud_a3sys", "a3sys_sel", 30),
+ GATE_AUD4(CLK_AUD_A4SYS, "aud_a4sys", "a4sys_sel", 31),
+
+ /* AUD5 */
+ GATE_AUD5(CLK_AUD_MEMIF_UL1, "aud_memif_ul1", "a1sys_hp_sel", 0),
+ GATE_AUD5(CLK_AUD_MEMIF_UL2, "aud_memif_ul2", "a1sys_hp_sel", 1),
+ GATE_AUD5(CLK_AUD_MEMIF_UL3, "aud_memif_ul3", "a1sys_hp_sel", 2),
+ GATE_AUD5(CLK_AUD_MEMIF_UL4, "aud_memif_ul4", "a1sys_hp_sel", 3),
+ GATE_AUD5(CLK_AUD_MEMIF_UL5, "aud_memif_ul5", "a1sys_hp_sel", 4),
+ GATE_AUD5(CLK_AUD_MEMIF_UL6, "aud_memif_ul6", "a1sys_hp_sel", 5),
+ GATE_AUD5(CLK_AUD_MEMIF_UL8, "aud_memif_ul8", "a1sys_hp_sel", 7),
+ GATE_AUD5(CLK_AUD_MEMIF_UL9, "aud_memif_ul9", "a1sys_hp_sel", 8),
+ GATE_AUD5(CLK_AUD_MEMIF_UL10, "aud_memif_ul10", "a1sys_hp_sel", 9),
+ GATE_AUD5(CLK_AUD_MEMIF_DL2, "aud_memif_dl2", "a1sys_hp_sel", 18),
+ GATE_AUD5(CLK_AUD_MEMIF_DL3, "aud_memif_dl3", "a1sys_hp_sel", 19),
+ GATE_AUD5(CLK_AUD_MEMIF_DL6, "aud_memif_dl6", "a1sys_hp_sel", 22),
+ GATE_AUD5(CLK_AUD_MEMIF_DL7, "aud_memif_dl7", "a1sys_hp_sel", 23),
+ GATE_AUD5(CLK_AUD_MEMIF_DL8, "aud_memif_dl8", "a1sys_hp_sel", 24),
+ GATE_AUD5(CLK_AUD_MEMIF_DL10, "aud_memif_dl10", "a1sys_hp_sel", 26),
+ GATE_AUD5(CLK_AUD_MEMIF_DL11, "aud_memif_dl11", "a1sys_hp_sel", 27),
+
+ /* AUD6 */
+ GATE_AUD6(CLK_AUD_GASRC0, "aud_gasrc0", "asm_h_sel", 0),
+ GATE_AUD6(CLK_AUD_GASRC1, "aud_gasrc1", "asm_h_sel", 1),
+ GATE_AUD6(CLK_AUD_GASRC2, "aud_gasrc2", "asm_h_sel", 2),
+ GATE_AUD6(CLK_AUD_GASRC3, "aud_gasrc3", "asm_h_sel", 3),
+ GATE_AUD6(CLK_AUD_GASRC4, "aud_gasrc4", "asm_h_sel", 4),
+ GATE_AUD6(CLK_AUD_GASRC5, "aud_gasrc5", "asm_h_sel", 5),
+ GATE_AUD6(CLK_AUD_GASRC6, "aud_gasrc6", "asm_h_sel", 6),
+ GATE_AUD6(CLK_AUD_GASRC7, "aud_gasrc7", "asm_h_sel", 7),
+ GATE_AUD6(CLK_AUD_GASRC8, "aud_gasrc8", "asm_h_sel", 8),
+ GATE_AUD6(CLK_AUD_GASRC9, "aud_gasrc9", "asm_h_sel", 9),
+ GATE_AUD6(CLK_AUD_GASRC10, "aud_gasrc10", "asm_h_sel", 10),
+ GATE_AUD6(CLK_AUD_GASRC11, "aud_gasrc11", "asm_h_sel", 11),
+ GATE_AUD6(CLK_AUD_GASRC12, "aud_gasrc12", "asm_h_sel", 12),
+ GATE_AUD6(CLK_AUD_GASRC13, "aud_gasrc13", "asm_h_sel", 13),
+ GATE_AUD6(CLK_AUD_GASRC14, "aud_gasrc14", "asm_h_sel", 14),
+ GATE_AUD6(CLK_AUD_GASRC15, "aud_gasrc15", "asm_h_sel", 15),
+ GATE_AUD6(CLK_AUD_GASRC16, "aud_gasrc16", "asm_h_sel", 16),
+ GATE_AUD6(CLK_AUD_GASRC17, "aud_gasrc17", "asm_h_sel", 17),
+ GATE_AUD6(CLK_AUD_GASRC18, "aud_gasrc18", "asm_h_sel", 18),
+ GATE_AUD6(CLK_AUD_GASRC19, "aud_gasrc19", "asm_h_sel", 19),
+};
+
+int mt8195_audsys_clk_register(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct clk *clk;
+ struct clk_lookup *cl;
+ int i;
+
+ afe_priv->lookup = devm_kcalloc(afe->dev, CLK_AUD_NR_CLK,
+ sizeof(*afe_priv->lookup),
+ GFP_KERNEL);
+
+ if (!afe_priv->lookup)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
+ const struct afe_gate *gate = &aud_clks[i];
+
+ clk = clk_register_gate(afe->dev, gate->name, gate->parent_name,
+ gate->flags, afe->base_addr + gate->reg,
+ gate->bit, gate->cg_flags, NULL);
+
+ if (IS_ERR(clk)) {
+ dev_err(afe->dev, "Failed to register clk %s: %ld\n",
+ gate->name, PTR_ERR(clk));
+ continue;
+ }
+
+ /* add clk_lookup for devm_clk_get(SND_SOC_DAPM_CLOCK_SUPPLY) */
+ cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+ if (!cl)
+ return -ENOMEM;
+
+ cl->clk = clk;
+ cl->con_id = gate->name;
+ cl->dev_id = dev_name(afe->dev);
+ clkdev_add(cl);
+
+ afe_priv->lookup[i] = cl;
+ }
+
+ return 0;
+}
+
+void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct clk *clk;
+ struct clk_lookup *cl;
+ int i;
+
+ if (!afe_priv)
+ return;
+
+ for (i = 0; i < CLK_AUD_NR_CLK; i++) {
+ cl = afe_priv->lookup[i];
+ if (!cl)
+ continue;
+
+ clk = cl->clk;
+ clk_unregister_gate(clk);
+
+ clkdev_drop(cl);
+ }
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h
new file mode 100644
index 000000000000..239d31016ba7
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-audsys-clk.h -- Mediatek 8195 audsys clock definition
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8195_AUDSYS_CLK_H_
+#define _MT8195_AUDSYS_CLK_H_
+
+int mt8195_audsys_clk_register(struct mtk_base_afe *afe);
+void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe);
+
+#endif
diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h b/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h
new file mode 100644
index 000000000000..4dd0a5c8b8fa
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-audsys-clkid.h -- Mediatek 8195 audsys clock id definition
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8195_AUDSYS_CLKID_H_
+#define _MT8195_AUDSYS_CLKID_H_
+
+enum{
+ CLK_AUD_AFE,
+ CLK_AUD_LRCK_CNT,
+ CLK_AUD_SPDIFIN_TUNER_APLL,
+ CLK_AUD_SPDIFIN_TUNER_DBG,
+ CLK_AUD_UL_TML,
+ CLK_AUD_APLL1_TUNER,
+ CLK_AUD_APLL2_TUNER,
+ CLK_AUD_TOP0_SPDF,
+ CLK_AUD_APLL,
+ CLK_AUD_APLL2,
+ CLK_AUD_DAC,
+ CLK_AUD_DAC_PREDIS,
+ CLK_AUD_TML,
+ CLK_AUD_ADC,
+ CLK_AUD_DAC_HIRES,
+ CLK_AUD_A1SYS_HP,
+ CLK_AUD_AFE_DMIC1,
+ CLK_AUD_AFE_DMIC2,
+ CLK_AUD_AFE_DMIC3,
+ CLK_AUD_AFE_DMIC4,
+ CLK_AUD_AFE_26M_DMIC_TM,
+ CLK_AUD_UL_TML_HIRES,
+ CLK_AUD_ADC_HIRES,
+ CLK_AUD_ADDA6_ADC,
+ CLK_AUD_ADDA6_ADC_HIRES,
+ CLK_AUD_LINEIN_TUNER,
+ CLK_AUD_EARC_TUNER,
+ CLK_AUD_I2SIN,
+ CLK_AUD_TDM_IN,
+ CLK_AUD_I2S_OUT,
+ CLK_AUD_TDM_OUT,
+ CLK_AUD_HDMI_OUT,
+ CLK_AUD_ASRC11,
+ CLK_AUD_ASRC12,
+ CLK_AUD_MULTI_IN,
+ CLK_AUD_INTDIR,
+ CLK_AUD_A1SYS,
+ CLK_AUD_A2SYS,
+ CLK_AUD_PCMIF,
+ CLK_AUD_A3SYS,
+ CLK_AUD_A4SYS,
+ CLK_AUD_MEMIF_UL1,
+ CLK_AUD_MEMIF_UL2,
+ CLK_AUD_MEMIF_UL3,
+ CLK_AUD_MEMIF_UL4,
+ CLK_AUD_MEMIF_UL5,
+ CLK_AUD_MEMIF_UL6,
+ CLK_AUD_MEMIF_UL8,
+ CLK_AUD_MEMIF_UL9,
+ CLK_AUD_MEMIF_UL10,
+ CLK_AUD_MEMIF_DL2,
+ CLK_AUD_MEMIF_DL3,
+ CLK_AUD_MEMIF_DL6,
+ CLK_AUD_MEMIF_DL7,
+ CLK_AUD_MEMIF_DL8,
+ CLK_AUD_MEMIF_DL10,
+ CLK_AUD_MEMIF_DL11,
+ CLK_AUD_GASRC0,
+ CLK_AUD_GASRC1,
+ CLK_AUD_GASRC2,
+ CLK_AUD_GASRC3,
+ CLK_AUD_GASRC4,
+ CLK_AUD_GASRC5,
+ CLK_AUD_GASRC6,
+ CLK_AUD_GASRC7,
+ CLK_AUD_GASRC8,
+ CLK_AUD_GASRC9,
+ CLK_AUD_GASRC10,
+ CLK_AUD_GASRC11,
+ CLK_AUD_GASRC12,
+ CLK_AUD_GASRC13,
+ CLK_AUD_GASRC14,
+ CLK_AUD_GASRC15,
+ CLK_AUD_GASRC16,
+ CLK_AUD_GASRC17,
+ CLK_AUD_GASRC18,
+ CLK_AUD_GASRC19,
+ CLK_AUD_NR_CLK,
+};
+
+#endif
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c
new file mode 100644
index 000000000000..878dec0b69ed
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c
@@ -0,0 +1,830 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI ADDA Control
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ * Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include "mt8195-afe-clk.h"
+#include "mt8195-afe-common.h"
+#include "mt8195-reg.h"
+
+#define ADDA_DL_GAIN_LOOPBACK 0x1800
+#define ADDA_HIRES_THRES 48000
+
+enum {
+ SUPPLY_SEQ_CLOCK_SEL,
+ SUPPLY_SEQ_CLOCK_ON,
+ SUPPLY_SEQ_ADDA_DL_ON,
+ SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+ SUPPLY_SEQ_ADDA_UL_ON,
+ SUPPLY_SEQ_ADDA_AFE_ON,
+};
+
+enum {
+ MTK_AFE_ADDA_DL_RATE_8K = 0,
+ MTK_AFE_ADDA_DL_RATE_11K = 1,
+ MTK_AFE_ADDA_DL_RATE_12K = 2,
+ MTK_AFE_ADDA_DL_RATE_16K = 3,
+ MTK_AFE_ADDA_DL_RATE_22K = 4,
+ MTK_AFE_ADDA_DL_RATE_24K = 5,
+ MTK_AFE_ADDA_DL_RATE_32K = 6,
+ MTK_AFE_ADDA_DL_RATE_44K = 7,
+ MTK_AFE_ADDA_DL_RATE_48K = 8,
+ MTK_AFE_ADDA_DL_RATE_96K = 9,
+ MTK_AFE_ADDA_DL_RATE_192K = 10,
+};
+
+enum {
+ MTK_AFE_ADDA_UL_RATE_8K = 0,
+ MTK_AFE_ADDA_UL_RATE_16K = 1,
+ MTK_AFE_ADDA_UL_RATE_32K = 2,
+ MTK_AFE_ADDA_UL_RATE_48K = 3,
+ MTK_AFE_ADDA_UL_RATE_96K = 4,
+ MTK_AFE_ADDA_UL_RATE_192K = 5,
+};
+
+enum {
+ DELAY_DATA_MISO1 = 0,
+ DELAY_DATA_MISO0 = 1,
+ DELAY_DATA_MISO2 = 1,
+};
+
+enum {
+ MTK_AFE_ADDA,
+ MTK_AFE_ADDA6,
+};
+
+struct mtk_dai_adda_priv {
+ bool hires_required;
+};
+
+static unsigned int afe_adda_dl_rate_transform(struct mtk_base_afe *afe,
+ unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_ADDA_DL_RATE_8K;
+ case 11025:
+ return MTK_AFE_ADDA_DL_RATE_11K;
+ case 12000:
+ return MTK_AFE_ADDA_DL_RATE_12K;
+ case 16000:
+ return MTK_AFE_ADDA_DL_RATE_16K;
+ case 22050:
+ return MTK_AFE_ADDA_DL_RATE_22K;
+ case 24000:
+ return MTK_AFE_ADDA_DL_RATE_24K;
+ case 32000:
+ return MTK_AFE_ADDA_DL_RATE_32K;
+ case 44100:
+ return MTK_AFE_ADDA_DL_RATE_44K;
+ case 48000:
+ return MTK_AFE_ADDA_DL_RATE_48K;
+ case 96000:
+ return MTK_AFE_ADDA_DL_RATE_96K;
+ case 192000:
+ return MTK_AFE_ADDA_DL_RATE_192K;
+ default:
+ dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+ __func__, rate);
+ return MTK_AFE_ADDA_DL_RATE_48K;
+ }
+}
+
+static unsigned int afe_adda_ul_rate_transform(struct mtk_base_afe *afe,
+ unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_ADDA_UL_RATE_8K;
+ case 16000:
+ return MTK_AFE_ADDA_UL_RATE_16K;
+ case 32000:
+ return MTK_AFE_ADDA_UL_RATE_32K;
+ case 48000:
+ return MTK_AFE_ADDA_UL_RATE_48K;
+ case 96000:
+ return MTK_AFE_ADDA_UL_RATE_96K;
+ case 192000:
+ return MTK_AFE_ADDA_UL_RATE_192K;
+ default:
+ dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+ __func__, rate);
+ return MTK_AFE_ADDA_UL_RATE_48K;
+ }
+}
+
+static int mt8195_adda_mtkaif_init(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtkaif_param *param = &afe_priv->mtkaif_params;
+ int delay_data;
+ int delay_cycle;
+ unsigned int mask = 0;
+ unsigned int val = 0;
+
+ /* set rx protocol 2 & mtkaif_rxif_clkinv_adc inverse */
+ mask = (MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2);
+ val = (MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2);
+
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0, mask, val);
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_CFG0, mask, val);
+
+ mask = RG_RX_PROTOCOL2;
+ val = RG_RX_PROTOCOL2;
+ regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, mask, val);
+
+ if (!param->mtkaif_calibration_ok) {
+ dev_info(afe->dev, "%s(), calibration fail\n", __func__);
+ return 0;
+ }
+
+ /* set delay for ch1, ch2 */
+ if (param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] >=
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]) {
+ delay_data = DELAY_DATA_MISO1;
+ delay_cycle =
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] -
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1];
+ } else {
+ delay_data = DELAY_DATA_MISO0;
+ delay_cycle =
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] -
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0];
+ }
+
+ val = 0;
+ mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK);
+ val |= MTKAIF_RXIF_DELAY_CYCLE(delay_cycle) &
+ MTKAIF_RXIF_DELAY_CYCLE_MASK;
+ val |= delay_data << MTKAIF_RXIF_DELAY_DATA_SHIFT;
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG2, mask, val);
+
+ /* set delay between ch3 and ch2 */
+ if (param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] >=
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]) {
+ delay_data = DELAY_DATA_MISO1;
+ delay_cycle =
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] -
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1];
+ } else {
+ delay_data = DELAY_DATA_MISO2;
+ delay_cycle =
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] -
+ param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2];
+ }
+
+ val = 0;
+ mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK);
+ val |= MTKAIF_RXIF_DELAY_CYCLE(delay_cycle) &
+ MTKAIF_RXIF_DELAY_CYCLE_MASK;
+ val |= delay_data << MTKAIF_RXIF_DELAY_DATA_SHIFT;
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_RX_CFG2, mask, val);
+
+ return 0;
+}
+
+static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+ dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8195_adda_mtkaif_init(afe);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+ dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMD:
+ /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+ usleep_range(125, 135);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void mtk_adda_ul_mictype(struct mtk_base_afe *afe, int adda, bool dmic)
+{
+ unsigned int reg = 0;
+ unsigned int mask = 0;
+ unsigned int val = 0;
+
+ switch (adda) {
+ case MTK_AFE_ADDA:
+ reg = AFE_ADDA_UL_SRC_CON0;
+ break;
+ case MTK_AFE_ADDA6:
+ reg = AFE_ADDA6_UL_SRC_CON0;
+ break;
+ default:
+ dev_info(afe->dev, "%s(), wrong parameter\n", __func__);
+ return;
+ }
+
+ mask = (UL_SDM3_LEVEL_CTL | UL_MODE_3P25M_CH1_CTL |
+ UL_MODE_3P25M_CH2_CTL);
+
+ /* turn on dmic, ch1, ch2 */
+ if (dmic)
+ val = mask;
+
+ regmap_update_bits(afe->regmap, reg, mask, val);
+}
+
+static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+ dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mtk_adda_ul_mictype(afe, MTK_AFE_ADDA, param->mtkaif_dmic_on);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+ usleep_range(125, 135);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_adda6_ul_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtkaif_param *param = &afe_priv->mtkaif_params;
+ unsigned int val;
+
+ dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mtk_adda_ul_mictype(afe, MTK_AFE_ADDA6, param->mtkaif_dmic_on);
+
+ val = (param->mtkaif_adda6_only ?
+ ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE : 0);
+
+ regmap_update_bits(afe->regmap,
+ AFE_ADDA_MTKAIF_SYNCWORD_CFG,
+ ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE,
+ val);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+ usleep_range(125, 135);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_audio_hires_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct clk *clk = afe_priv->clk[MT8195_CLK_TOP_AUDIO_H_SEL];
+ struct clk *clk_parent;
+
+ dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+ __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ clk_parent = afe_priv->clk[MT8195_CLK_TOP_APLL1];
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ clk_parent = afe_priv->clk[MT8195_CLK_XTAL_26M];
+ break;
+ default:
+ return 0;
+ }
+ mt8195_afe_set_clk_parent(afe, clk, clk_parent);
+
+ return 0;
+}
+
+static struct mtk_dai_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,
+ const char *name)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int dai_id;
+
+ if (strstr(name, "aud_adc_hires"))
+ dai_id = MT8195_AFE_IO_UL_SRC1;
+ else if (strstr(name, "aud_adda6_adc_hires"))
+ dai_id = MT8195_AFE_IO_UL_SRC2;
+ else if (strstr(name, "aud_dac_hires"))
+ dai_id = MT8195_AFE_IO_DL_SRC;
+ else
+ return NULL;
+
+ return afe_priv->dai_priv[dai_id];
+}
+
+static int mtk_afe_adda_hires_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_dapm_widget *w = source;
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mtk_dai_adda_priv *adda_priv;
+
+ adda_priv = get_adda_priv_by_name(afe, w->name);
+
+ if (!adda_priv) {
+ dev_info(afe->dev, "adda_priv == NULL");
+ return 0;
+ }
+
+ return (adda_priv->hires_required) ? 1 : 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_adda_o176_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN176, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN176, 2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN176, 20, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN176, 22, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN176_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_adda_o177_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN177, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN177, 3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN177, 21, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN177, 23, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN177_2, 7, 1, 0),
+};
+
+static const char * const adda_dlgain_mux_map[] = {
+ "Bypass", "Connect",
+};
+
+static SOC_ENUM_SINGLE_DECL(adda_dlgain_mux_map_enum,
+ SND_SOC_NOPM, 0,
+ adda_dlgain_mux_map);
+
+static const struct snd_kcontrol_new adda_dlgain_mux_control =
+ SOC_DAPM_ENUM("DL_GAIN_MUX", adda_dlgain_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
+ SND_SOC_DAPM_MIXER("I168", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I169", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I170", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I171", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("O176", SND_SOC_NOPM, 0, 0,
+ mtk_dai_adda_o176_mix,
+ ARRAY_SIZE(mtk_dai_adda_o176_mix)),
+ SND_SOC_DAPM_MIXER("O177", SND_SOC_NOPM, 0, 0,
+ mtk_dai_adda_o177_mix,
+ ARRAY_SIZE(mtk_dai_adda_o177_mix)),
+
+ SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
+ AFE_ADDA_UL_DL_CON0,
+ ADDA_AFE_ON_SHIFT, 0,
+ NULL,
+ 0),
+
+ SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,
+ AFE_ADDA_DL_SRC2_CON0,
+ DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT, 0,
+ mtk_adda_dl_event,
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+ AFE_ADDA_UL_SRC_CON0,
+ UL_SRC_ON_TMP_CTL_SHIFT, 0,
+ mtk_adda_ul_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("ADDA6 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+ AFE_ADDA6_UL_SRC_CON0,
+ UL_SRC_ON_TMP_CTL_SHIFT, 0,
+ mtk_adda6_ul_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("AUDIO_HIRES", SUPPLY_SEQ_CLOCK_SEL,
+ SND_SOC_NOPM,
+ 0, 0,
+ mtk_audio_hires_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+ SND_SOC_NOPM,
+ 0, 0,
+ mtk_adda_mtkaif_cfg_event,
+ SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX("DL_GAIN_MUX", SND_SOC_NOPM, 0, 0,
+ &adda_dlgain_mux_control),
+
+ SND_SOC_DAPM_PGA("DL_GAIN", AFE_ADDA_DL_SRC2_CON0,
+ DL_2_GAIN_ON_CTL_PRE_SHIFT, 0, NULL, 0),
+
+ SND_SOC_DAPM_INPUT("ADDA_INPUT"),
+ SND_SOC_DAPM_OUTPUT("ADDA_OUTPUT"),
+
+ SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac"),
+ SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc"),
+ SND_SOC_DAPM_CLOCK_SUPPLY("aud_adda6_adc"),
+ SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_hires"),
+ SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_hires"),
+ SND_SOC_DAPM_CLOCK_SUPPLY("aud_adda6_adc_hires"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
+ {"ADDA Capture", NULL, "ADDA Enable"},
+ {"ADDA Capture", NULL, "ADDA Capture Enable"},
+ {"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"},
+ {"ADDA Capture", NULL, "aud_adc"},
+ {"ADDA Capture", NULL, "aud_adc_hires", mtk_afe_adda_hires_connect},
+ {"aud_adc_hires", NULL, "AUDIO_HIRES"},
+
+ {"ADDA6 Capture", NULL, "ADDA Enable"},
+ {"ADDA6 Capture", NULL, "ADDA6 Capture Enable"},
+ {"ADDA6 Capture", NULL, "ADDA_MTKAIF_CFG"},
+ {"ADDA6 Capture", NULL, "aud_adda6_adc"},
+ {"ADDA6 Capture", NULL, "aud_adda6_adc_hires",
+ mtk_afe_adda_hires_connect},
+ {"aud_adda6_adc_hires", NULL, "AUDIO_HIRES"},
+
+ {"I168", NULL, "ADDA Capture"},
+ {"I169", NULL, "ADDA Capture"},
+ {"I170", NULL, "ADDA6 Capture"},
+ {"I171", NULL, "ADDA6 Capture"},
+
+ {"ADDA Playback", NULL, "ADDA Enable"},
+ {"ADDA Playback", NULL, "ADDA Playback Enable"},
+ {"ADDA Playback", NULL, "aud_dac"},
+ {"ADDA Playback", NULL, "aud_dac_hires", mtk_afe_adda_hires_connect},
+ {"aud_dac_hires", NULL, "AUDIO_HIRES"},
+
+ {"DL_GAIN", NULL, "O176"},
+ {"DL_GAIN", NULL, "O177"},
+
+ {"DL_GAIN_MUX", "Bypass", "O176"},
+ {"DL_GAIN_MUX", "Bypass", "O177"},
+ {"DL_GAIN_MUX", "Connect", "DL_GAIN"},
+
+ {"ADDA Playback", NULL, "DL_GAIN_MUX"},
+
+ {"O176", "I000 Switch", "I000"},
+ {"O177", "I001 Switch", "I001"},
+
+ {"O176", "I002 Switch", "I002"},
+ {"O177", "I003 Switch", "I003"},
+
+ {"O176", "I020 Switch", "I020"},
+ {"O177", "I021 Switch", "I021"},
+
+ {"O176", "I022 Switch", "I022"},
+ {"O177", "I023 Switch", "I023"},
+
+ {"O176", "I070 Switch", "I070"},
+ {"O177", "I071 Switch", "I071"},
+
+ {"ADDA Capture", NULL, "ADDA_INPUT"},
+ {"ADDA6 Capture", NULL, "ADDA_INPUT"},
+ {"ADDA_OUTPUT", NULL, "ADDA Playback"},
+};
+
+static int mt8195_adda_dl_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ unsigned int reg = AFE_ADDA_DL_SRC2_CON1;
+ unsigned int mask = DL_2_GAIN_CTL_PRE_MASK;
+ unsigned int value = (unsigned int)(ucontrol->value.integer.value[0]);
+
+ regmap_update_bits(afe->regmap, reg, mask, DL_2_GAIN_CTL_PRE(value));
+ return 0;
+}
+
+static int mt8195_adda_dl_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ unsigned int reg = AFE_ADDA_DL_SRC2_CON1;
+ unsigned int mask = DL_2_GAIN_CTL_PRE_MASK;
+ unsigned int value = 0;
+
+ regmap_read(afe->regmap, reg, &value);
+
+ ucontrol->value.integer.value[0] = ((value & mask) >>
+ DL_2_GAIN_CTL_PRE_SHIFT);
+ return 0;
+}
+
+static int mt8195_adda6_only_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+ ucontrol->value.integer.value[0] = param->mtkaif_adda6_only;
+ return 0;
+}
+
+static int mt8195_adda6_only_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtkaif_param *param = &afe_priv->mtkaif_params;
+ int mtkaif_adda6_only;
+
+ mtkaif_adda6_only = ucontrol->value.integer.value[0];
+
+ dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_adda6_only %d\n",
+ __func__, kcontrol->id.name, mtkaif_adda6_only);
+
+ param->mtkaif_adda6_only = mtkaif_adda6_only;
+
+ return 0;
+}
+
+static int mt8195_adda_dmic_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+ ucontrol->value.integer.value[0] = param->mtkaif_dmic_on;
+ return 0;
+}
+
+static int mt8195_adda_dmic_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtkaif_param *param = &afe_priv->mtkaif_params;
+ int dmic_on;
+
+ dmic_on = ucontrol->value.integer.value[0];
+
+ dev_dbg(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",
+ __func__, kcontrol->id.name, dmic_on);
+
+ param->mtkaif_dmic_on = dmic_on;
+ return 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_adda_controls[] = {
+ SOC_SINGLE_EXT("ADDA_DL_Gain", SND_SOC_NOPM, 0, 65535, 0,
+ mt8195_adda_dl_gain_get, mt8195_adda_dl_gain_put),
+ SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC", 0,
+ mt8195_adda_dmic_get, mt8195_adda_dmic_set),
+ SOC_SINGLE_BOOL_EXT("MTKAIF_ADDA6_ONLY", 0,
+ mt8195_adda6_only_get,
+ mt8195_adda6_only_set),
+};
+
+static int mtk_dai_da_configure(struct mtk_base_afe *afe,
+ unsigned int rate, int id)
+{
+ unsigned int val = 0;
+ unsigned int mask = 0;
+
+ /* set sampling rate */
+ mask |= DL_2_INPUT_MODE_CTL_MASK;
+ val |= DL_2_INPUT_MODE_CTL(afe_adda_dl_rate_transform(afe, rate));
+
+ /* turn off saturation */
+ mask |= DL_2_CH1_SATURATION_EN_CTL;
+ mask |= DL_2_CH2_SATURATION_EN_CTL;
+
+ /* turn off mute function */
+ mask |= DL_2_MUTE_CH1_OFF_CTL_PRE;
+ mask |= DL_2_MUTE_CH2_OFF_CTL_PRE;
+ val |= DL_2_MUTE_CH1_OFF_CTL_PRE;
+ val |= DL_2_MUTE_CH2_OFF_CTL_PRE;
+
+ /* set voice input data if input sample rate is 8k or 16k */
+ mask |= DL_2_VOICE_MODE_CTL_PRE;
+ if (rate == 8000 || rate == 16000)
+ val |= DL_2_VOICE_MODE_CTL_PRE;
+
+ regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, mask, val);
+
+ mask = 0;
+ val = 0;
+
+ /* new 2nd sdm */
+ mask |= DL_USE_NEW_2ND_SDM;
+ val |= DL_USE_NEW_2ND_SDM;
+ regmap_update_bits(afe->regmap, AFE_ADDA_DL_SDM_DCCOMP_CON, mask, val);
+
+ return 0;
+}
+
+static int mtk_dai_ad_configure(struct mtk_base_afe *afe,
+ unsigned int rate, int id)
+{
+ unsigned int val = 0;
+ unsigned int mask = 0;
+
+ mask |= UL_VOICE_MODE_CTL_MASK;
+ val |= UL_VOICE_MODE_CTL(afe_adda_ul_rate_transform(afe, rate));
+
+ switch (id) {
+ case MT8195_AFE_IO_UL_SRC1:
+ regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
+ mask, val);
+ break;
+ case MT8195_AFE_IO_UL_SRC2:
+ regmap_update_bits(afe->regmap, AFE_ADDA6_UL_SRC_CON0,
+ mask, val);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_adda_priv *adda_priv = afe_priv->dai_priv[dai->id];
+ unsigned int rate = params_rate(params);
+ int id = dai->id;
+ int ret = 0;
+
+ dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
+ __func__, id, substream->stream, rate);
+
+ if (rate > ADDA_HIRES_THRES)
+ adda_priv->hires_required = 1;
+ else
+ adda_priv->hires_required = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = mtk_dai_da_configure(afe, rate, id);
+ else
+ ret = mtk_dai_ad_configure(afe, rate, id);
+
+ return ret;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
+ .hw_params = mtk_dai_adda_hw_params,
+};
+
+/* dai driver */
+#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
+ SNDRV_PCM_RATE_96000 |\
+ SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
+ SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 |\
+ SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_96000 |\
+ SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
+ {
+ .name = "DL_SRC",
+ .id = MT8195_AFE_IO_DL_SRC,
+ .playback = {
+ .stream_name = "ADDA Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_PLAYBACK_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+ {
+ .name = "UL_SRC1",
+ .id = MT8195_AFE_IO_UL_SRC1,
+ .capture = {
+ .stream_name = "ADDA Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_CAPTURE_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+ {
+ .name = "UL_SRC2",
+ .id = MT8195_AFE_IO_UL_SRC2,
+ .capture = {
+ .stream_name = "ADDA6 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_CAPTURE_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+};
+
+static int init_adda_priv_data(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_adda_priv *adda_priv;
+ int adda_dai_list[] = { MT8195_AFE_IO_DL_SRC,
+ MT8195_AFE_IO_UL_SRC1,
+ MT8195_AFE_IO_UL_SRC2};
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) {
+ adda_priv = devm_kzalloc(afe->dev,
+ sizeof(struct mtk_dai_adda_priv),
+ GFP_KERNEL);
+ if (!adda_priv)
+ return -ENOMEM;
+
+ afe_priv->dai_priv[adda_dai_list[i]] = adda_priv;
+ }
+
+ return 0;
+}
+
+int mt8195_dai_adda_register(struct mtk_base_afe *afe)
+{
+ struct mtk_base_afe_dai *dai;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ dai->dai_drivers = mtk_dai_adda_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
+
+ dai->dapm_widgets = mtk_dai_adda_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
+ dai->dapm_routes = mtk_dai_adda_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
+ dai->controls = mtk_dai_adda_controls;
+ dai->num_controls = ARRAY_SIZE(mtk_dai_adda_controls);
+
+ return init_adda_priv_data(afe);
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
new file mode 100644
index 000000000000..7378e42f2766
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
@@ -0,0 +1,2639 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI eTDM Control
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ * Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8195-afe-clk.h"
+#include "mt8195-afe-common.h"
+#include "mt8195-reg.h"
+
+#define MT8195_ETDM_MAX_CHANNELS 24
+#define MT8195_ETDM_NORMAL_MAX_BCK_RATE 24576000
+#define ETDM_TO_DAI_ID(x) ((x) + MT8195_AFE_IO_ETDM_START)
+#define ENUM_TO_STR(x) #x
+
+enum {
+ MTK_DAI_ETDM_FORMAT_I2S = 0,
+ MTK_DAI_ETDM_FORMAT_LJ,
+ MTK_DAI_ETDM_FORMAT_RJ,
+ MTK_DAI_ETDM_FORMAT_EIAJ,
+ MTK_DAI_ETDM_FORMAT_DSPA,
+ MTK_DAI_ETDM_FORMAT_DSPB,
+};
+
+enum {
+ MTK_DAI_ETDM_DATA_ONE_PIN = 0,
+ MTK_DAI_ETDM_DATA_MULTI_PIN,
+};
+
+enum {
+ ETDM_IN,
+ ETDM_OUT,
+};
+
+enum {
+ ETDM_IN_FROM_PAD,
+ ETDM_IN_FROM_ETDM_OUT1,
+ ETDM_IN_FROM_ETDM_OUT2,
+};
+
+enum {
+ ETDM_IN_SLAVE_FROM_PAD,
+ ETDM_IN_SLAVE_FROM_ETDM_OUT1,
+ ETDM_IN_SLAVE_FROM_ETDM_OUT2,
+};
+
+enum {
+ ETDM_OUT_SLAVE_FROM_PAD,
+ ETDM_OUT_SLAVE_FROM_ETDM_IN1,
+ ETDM_OUT_SLAVE_FROM_ETDM_IN2,
+};
+
+enum {
+ COWORK_ETDM_NONE = 0,
+ COWORK_ETDM_IN1_M = 2,
+ COWORK_ETDM_IN1_S = 3,
+ COWORK_ETDM_IN2_M = 4,
+ COWORK_ETDM_IN2_S = 5,
+ COWORK_ETDM_OUT1_M = 10,
+ COWORK_ETDM_OUT1_S = 11,
+ COWORK_ETDM_OUT2_M = 12,
+ COWORK_ETDM_OUT2_S = 13,
+ COWORK_ETDM_OUT3_M = 14,
+ COWORK_ETDM_OUT3_S = 15,
+};
+
+enum {
+ ETDM_RELATCH_TIMING_A1A2SYS,
+ ETDM_RELATCH_TIMING_A3SYS,
+ ETDM_RELATCH_TIMING_A4SYS,
+};
+
+enum {
+ ETDM_SYNC_NONE,
+ ETDM_SYNC_FROM_IN1,
+ ETDM_SYNC_FROM_IN2,
+ ETDM_SYNC_FROM_OUT1,
+ ETDM_SYNC_FROM_OUT2,
+ ETDM_SYNC_FROM_OUT3,
+};
+
+struct etdm_con_reg {
+ unsigned int con0;
+ unsigned int con1;
+ unsigned int con2;
+ unsigned int con3;
+ unsigned int con4;
+ unsigned int con5;
+};
+
+struct mtk_dai_etdm_rate {
+ unsigned int rate;
+ unsigned int reg_value;
+};
+
+struct mtk_dai_etdm_priv {
+ unsigned int clock_mode;
+ unsigned int data_mode;
+ bool slave_mode;
+ bool lrck_inv;
+ bool bck_inv;
+ unsigned int format;
+ unsigned int slots;
+ unsigned int lrck_width;
+ unsigned int mclk_freq;
+ unsigned int mclk_apll;
+ unsigned int mclk_dir;
+ int cowork_source_id; //dai id
+ unsigned int cowork_slv_count;
+ int cowork_slv_id[MT8195_AFE_IO_ETDM_NUM - 1]; //dai_id
+ bool in_disable_ch[MT8195_ETDM_MAX_CHANNELS];
+ unsigned int en_ref_cnt;
+};
+
+static const struct mtk_dai_etdm_rate mt8195_etdm_rates[] = {
+ { .rate = 8000, .reg_value = 0, },
+ { .rate = 12000, .reg_value = 1, },
+ { .rate = 16000, .reg_value = 2, },
+ { .rate = 24000, .reg_value = 3, },
+ { .rate = 32000, .reg_value = 4, },
+ { .rate = 48000, .reg_value = 5, },
+ { .rate = 96000, .reg_value = 7, },
+ { .rate = 192000, .reg_value = 9, },
+ { .rate = 384000, .reg_value = 11, },
+ { .rate = 11025, .reg_value = 16, },
+ { .rate = 22050, .reg_value = 17, },
+ { .rate = 44100, .reg_value = 18, },
+ { .rate = 88200, .reg_value = 19, },
+ { .rate = 176400, .reg_value = 20, },
+ { .rate = 352800, .reg_value = 21, },
+};
+
+static int get_etdm_fs_timing(unsigned int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mt8195_etdm_rates); i++)
+ if (mt8195_etdm_rates[i].rate == rate)
+ return mt8195_etdm_rates[i].reg_value;
+
+ return -EINVAL;
+}
+
+static unsigned int get_etdm_ch_fixup(unsigned int channels)
+{
+ if (channels > 16)
+ return 24;
+ else if (channels > 8)
+ return 16;
+ else if (channels > 4)
+ return 8;
+ else if (channels > 2)
+ return 4;
+ else
+ return 2;
+}
+
+static int get_etdm_reg(unsigned int dai_id, struct etdm_con_reg *etdm_reg)
+{
+ switch (dai_id) {
+ case MT8195_AFE_IO_ETDM1_IN:
+ etdm_reg->con0 = ETDM_IN1_CON0;
+ etdm_reg->con1 = ETDM_IN1_CON1;
+ etdm_reg->con2 = ETDM_IN1_CON2;
+ etdm_reg->con3 = ETDM_IN1_CON3;
+ etdm_reg->con4 = ETDM_IN1_CON4;
+ etdm_reg->con5 = ETDM_IN1_CON5;
+ break;
+ case MT8195_AFE_IO_ETDM2_IN:
+ etdm_reg->con0 = ETDM_IN2_CON0;
+ etdm_reg->con1 = ETDM_IN2_CON1;
+ etdm_reg->con2 = ETDM_IN2_CON2;
+ etdm_reg->con3 = ETDM_IN2_CON3;
+ etdm_reg->con4 = ETDM_IN2_CON4;
+ etdm_reg->con5 = ETDM_IN2_CON5;
+ break;
+ case MT8195_AFE_IO_ETDM1_OUT:
+ etdm_reg->con0 = ETDM_OUT1_CON0;
+ etdm_reg->con1 = ETDM_OUT1_CON1;
+ etdm_reg->con2 = ETDM_OUT1_CON2;
+ etdm_reg->con3 = ETDM_OUT1_CON3;
+ etdm_reg->con4 = ETDM_OUT1_CON4;
+ etdm_reg->con5 = ETDM_OUT1_CON5;
+ break;
+ case MT8195_AFE_IO_ETDM2_OUT:
+ etdm_reg->con0 = ETDM_OUT2_CON0;
+ etdm_reg->con1 = ETDM_OUT2_CON1;
+ etdm_reg->con2 = ETDM_OUT2_CON2;
+ etdm_reg->con3 = ETDM_OUT2_CON3;
+ etdm_reg->con4 = ETDM_OUT2_CON4;
+ etdm_reg->con5 = ETDM_OUT2_CON5;
+ break;
+ case MT8195_AFE_IO_ETDM3_OUT:
+ case MT8195_AFE_IO_DPTX:
+ etdm_reg->con0 = ETDM_OUT3_CON0;
+ etdm_reg->con1 = ETDM_OUT3_CON1;
+ etdm_reg->con2 = ETDM_OUT3_CON2;
+ etdm_reg->con3 = ETDM_OUT3_CON3;
+ etdm_reg->con4 = ETDM_OUT3_CON4;
+ etdm_reg->con5 = ETDM_OUT3_CON5;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int get_etdm_dir(unsigned int dai_id)
+{
+ switch (dai_id) {
+ case MT8195_AFE_IO_ETDM1_IN:
+ case MT8195_AFE_IO_ETDM2_IN:
+ return ETDM_IN;
+ case MT8195_AFE_IO_ETDM1_OUT:
+ case MT8195_AFE_IO_ETDM2_OUT:
+ case MT8195_AFE_IO_ETDM3_OUT:
+ return ETDM_OUT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int get_etdm_wlen(unsigned int bitwidth)
+{
+ return bitwidth <= 16 ? 16 : 32;
+}
+
+static int is_cowork_mode(struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+ return (etdm_data->cowork_slv_count > 0 ||
+ etdm_data->cowork_source_id != COWORK_ETDM_NONE);
+}
+
+static int sync_to_dai_id(int source_sel)
+{
+ switch (source_sel) {
+ case ETDM_SYNC_FROM_IN1:
+ return MT8195_AFE_IO_ETDM1_IN;
+ case ETDM_SYNC_FROM_IN2:
+ return MT8195_AFE_IO_ETDM2_IN;
+ case ETDM_SYNC_FROM_OUT1:
+ return MT8195_AFE_IO_ETDM1_OUT;
+ case ETDM_SYNC_FROM_OUT2:
+ return MT8195_AFE_IO_ETDM2_OUT;
+ case ETDM_SYNC_FROM_OUT3:
+ return MT8195_AFE_IO_ETDM3_OUT;
+ default:
+ return 0;
+ }
+}
+
+static int get_etdm_cowork_master_id(struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+ int dai_id = etdm_data->cowork_source_id;
+
+ if (dai_id == COWORK_ETDM_NONE)
+ dai_id = dai->id;
+
+ return dai_id;
+}
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o048_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN48, 20, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN48, 22, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN48_1, 14, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN48_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o049_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN49, 21, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN49, 23, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN49_1, 15, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN49_2, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o050_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN50, 24, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN50_1, 16, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o051_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN51, 25, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN51_1, 17, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o052_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN52, 26, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN52_1, 18, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o053_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN53, 27, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN53_1, 19, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o054_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN54, 28, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN54_1, 20, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o055_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN55, 29, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN55_1, 21, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o056_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN56, 30, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I054 Switch", AFE_CONN56_1, 22, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o057_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN57, 31, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I055 Switch", AFE_CONN57_1, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o058_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN58_1, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I056 Switch", AFE_CONN58_1, 24, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o059_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN59_1, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I057 Switch", AFE_CONN59_1, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o060_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN60_1, 2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I058 Switch", AFE_CONN60_1, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o061_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN61_1, 3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I059 Switch", AFE_CONN61_1, 27, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o062_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN62_1, 4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I060 Switch", AFE_CONN62_1, 28, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o063_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN63_1, 5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I061 Switch", AFE_CONN63_1, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o064_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN64_1, 6, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I062 Switch", AFE_CONN64_1, 30, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o065_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN65_1, 7, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I063 Switch", AFE_CONN65_1, 31, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o066_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN66_1, 8, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I064 Switch", AFE_CONN66_2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o067_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN67_1, 9, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I065 Switch", AFE_CONN67_2, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o068_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN68_1, 10, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I066 Switch", AFE_CONN68_2, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o069_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN69_1, 11, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I067 Switch", AFE_CONN69_2, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o070_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN70_1, 12, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I068 Switch", AFE_CONN70_2, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o071_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN71_1, 13, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I069 Switch", AFE_CONN71_2, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o072_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN72, 20, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN72, 22, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN72_1, 14, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN72_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o073_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN73, 21, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN73, 23, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN73_1, 15, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN73_2, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o074_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN74, 24, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN74_1, 16, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o075_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN75, 25, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN75_1, 17, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o076_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN76, 26, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN76_1, 18, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o077_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN77, 27, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN77_1, 19, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o078_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN78, 28, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN78_1, 20, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o079_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN79, 29, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN79_1, 21, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o080_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN80, 30, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I054 Switch", AFE_CONN80_1, 22, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o081_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN81, 31, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I055 Switch", AFE_CONN81_1, 23, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o082_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN82_1, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I056 Switch", AFE_CONN82_1, 24, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o083_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN83_1, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I057 Switch", AFE_CONN83_1, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o084_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN84_1, 2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I058 Switch", AFE_CONN84_1, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o085_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN85_1, 3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I059 Switch", AFE_CONN85_1, 27, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o086_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN86_1, 4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I060 Switch", AFE_CONN86_1, 28, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o087_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN87_1, 5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I061 Switch", AFE_CONN87_1, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o088_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN88_1, 6, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I062 Switch", AFE_CONN88_1, 30, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o089_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN89_1, 7, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I063 Switch", AFE_CONN89_1, 31, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o090_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN90_1, 8, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I064 Switch", AFE_CONN90_2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o091_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN91_1, 9, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I065 Switch", AFE_CONN91_2, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o092_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN92_1, 10, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I066 Switch", AFE_CONN92_2, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o093_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN93_1, 11, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I067 Switch", AFE_CONN93_2, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o094_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN94_1, 12, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I068 Switch", AFE_CONN94_2, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_etdm_o095_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN95_1, 13, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I069 Switch", AFE_CONN95_2, 5, 1, 0),
+};
+
+static const char * const mt8195_etdm_clk_src_sel_text[] = {
+ "26m",
+ "a1sys_a2sys",
+ "a3sys",
+ "a4sys",
+};
+
+static SOC_ENUM_SINGLE_EXT_DECL(etdmout_clk_src_enum,
+ mt8195_etdm_clk_src_sel_text);
+
+static const char * const hdmitx_dptx_mux_map[] = {
+ "Disconnect", "Connect",
+};
+
+static int hdmitx_dptx_mux_map_value[] = {
+ 0, 1,
+};
+
+/* HDMI_OUT_MUX */
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(hdmi_out_mux_map_enum,
+ SND_SOC_NOPM,
+ 0,
+ 1,
+ hdmitx_dptx_mux_map,
+ hdmitx_dptx_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_out_mux_control =
+ SOC_DAPM_ENUM("HDMI_OUT_MUX", hdmi_out_mux_map_enum);
+
+/* DPTX_OUT_MUX */
+static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(dptx_out_mux_map_enum,
+ SND_SOC_NOPM,
+ 0,
+ 1,
+ hdmitx_dptx_mux_map,
+ hdmitx_dptx_mux_map_value);
+
+static const struct snd_kcontrol_new dptx_out_mux_control =
+ SOC_DAPM_ENUM("DPTX_OUT_MUX", dptx_out_mux_map_enum);
+
+/* HDMI_CH0_MUX ~ HDMI_CH7_MUX */
+static const char *const afe_conn_hdmi_mux_map[] = {
+ "CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7",
+};
+
+static int afe_conn_hdmi_mux_map_value[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
+ AFE_TDMOUT_CONN0,
+ 0,
+ 0xf,
+ afe_conn_hdmi_mux_map,
+ afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch0_mux_control =
+ SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
+ AFE_TDMOUT_CONN0,
+ 4,
+ 0xf,
+ afe_conn_hdmi_mux_map,
+ afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch1_mux_control =
+ SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
+ AFE_TDMOUT_CONN0,
+ 8,
+ 0xf,
+ afe_conn_hdmi_mux_map,
+ afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch2_mux_control =
+ SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
+ AFE_TDMOUT_CONN0,
+ 12,
+ 0xf,
+ afe_conn_hdmi_mux_map,
+ afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch3_mux_control =
+ SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
+ AFE_TDMOUT_CONN0,
+ 16,
+ 0xf,
+ afe_conn_hdmi_mux_map,
+ afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch4_mux_control =
+ SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
+ AFE_TDMOUT_CONN0,
+ 20,
+ 0xf,
+ afe_conn_hdmi_mux_map,
+ afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch5_mux_control =
+ SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
+ AFE_TDMOUT_CONN0,
+ 24,
+ 0xf,
+ afe_conn_hdmi_mux_map,
+ afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch6_mux_control =
+ SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
+ AFE_TDMOUT_CONN0,
+ 28,
+ 0xf,
+ afe_conn_hdmi_mux_map,
+ afe_conn_hdmi_mux_map_value);
+
+static const struct snd_kcontrol_new hdmi_ch7_mux_control =
+ SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
+
+static int mt8195_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ unsigned int source = ucontrol->value.enumerated.item[0];
+ unsigned int val;
+ unsigned int mask;
+ unsigned int reg;
+
+ if (source >= e->items)
+ return -EINVAL;
+
+ reg = 0;
+ if (!strcmp(kcontrol->id.name, "ETDM_OUT1_Clock_Source")) {
+ reg = ETDM_OUT1_CON4;
+ mask = ETDM_OUT_CON4_CLOCK_MASK;
+ val = ETDM_OUT_CON4_CLOCK(source);
+ } else if (!strcmp(kcontrol->id.name, "ETDM_OUT2_Clock_Source")) {
+ reg = ETDM_OUT2_CON4;
+ mask = ETDM_OUT_CON4_CLOCK_MASK;
+ val = ETDM_OUT_CON4_CLOCK(source);
+ } else if (!strcmp(kcontrol->id.name, "ETDM_OUT3_Clock_Source")) {
+ reg = ETDM_OUT3_CON4;
+ mask = ETDM_OUT_CON4_CLOCK_MASK;
+ val = ETDM_OUT_CON4_CLOCK(source);
+ } else if (!strcmp(kcontrol->id.name, "ETDM_IN1_Clock_Source")) {
+ reg = ETDM_IN1_CON2;
+ mask = ETDM_IN_CON2_CLOCK_MASK;
+ val = ETDM_IN_CON2_CLOCK(source);
+ } else if (!strcmp(kcontrol->id.name, "ETDM_IN2_Clock_Source")) {
+ reg = ETDM_IN2_CON2;
+ mask = ETDM_IN_CON2_CLOCK_MASK;
+ val = ETDM_IN_CON2_CLOCK(source);
+ }
+
+ if (reg)
+ regmap_update_bits(afe->regmap, reg, mask, val);
+
+ return 0;
+}
+
+static int mt8195_etdm_clk_src_sel_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ unsigned int value = 0;
+ unsigned int reg = 0;
+ unsigned int mask = 0;
+ unsigned int shift = 0;
+
+ if (!strcmp(kcontrol->id.name, "ETDM_OUT1_Clock_Source")) {
+ reg = ETDM_OUT1_CON4;
+ mask = ETDM_OUT_CON4_CLOCK_MASK;
+ shift = ETDM_OUT_CON4_CLOCK_SHIFT;
+ } else if (!strcmp(kcontrol->id.name, "ETDM_OUT2_Clock_Source")) {
+ reg = ETDM_OUT2_CON4;
+ mask = ETDM_OUT_CON4_CLOCK_MASK;
+ shift = ETDM_OUT_CON4_CLOCK_SHIFT;
+ } else if (!strcmp(kcontrol->id.name, "ETDM_OUT3_Clock_Source")) {
+ reg = ETDM_OUT3_CON4;
+ mask = ETDM_OUT_CON4_CLOCK_MASK;
+ shift = ETDM_OUT_CON4_CLOCK_SHIFT;
+ } else if (!strcmp(kcontrol->id.name, "ETDM_IN1_Clock_Source")) {
+ reg = ETDM_IN1_CON2;
+ mask = ETDM_IN_CON2_CLOCK_MASK;
+ shift = ETDM_IN_CON2_CLOCK_SHIFT;
+ } else if (!strcmp(kcontrol->id.name, "ETDM_IN2_Clock_Source")) {
+ reg = ETDM_IN2_CON2;
+ mask = ETDM_IN_CON2_CLOCK_MASK;
+ shift = ETDM_IN_CON2_CLOCK_SHIFT;
+ }
+
+ if (reg)
+ regmap_read(afe->regmap, reg, &value);
+
+ value &= mask;
+ value >>= shift;
+ ucontrol->value.enumerated.item[0] = value;
+ return 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_etdm_controls[] = {
+ SOC_ENUM_EXT("ETDM_OUT1_Clock_Source",
+ etdmout_clk_src_enum,
+ mt8195_etdm_clk_src_sel_get,
+ mt8195_etdm_clk_src_sel_put),
+ SOC_ENUM_EXT("ETDM_OUT2_Clock_Source",
+ etdmout_clk_src_enum,
+ mt8195_etdm_clk_src_sel_get,
+ mt8195_etdm_clk_src_sel_put),
+ SOC_ENUM_EXT("ETDM_OUT3_Clock_Source",
+ etdmout_clk_src_enum,
+ mt8195_etdm_clk_src_sel_get,
+ mt8195_etdm_clk_src_sel_put),
+ SOC_ENUM_EXT("ETDM_IN1_Clock_Source",
+ etdmout_clk_src_enum,
+ mt8195_etdm_clk_src_sel_get,
+ mt8195_etdm_clk_src_sel_put),
+ SOC_ENUM_EXT("ETDM_IN2_Clock_Source",
+ etdmout_clk_src_enum,
+ mt8195_etdm_clk_src_sel_get,
+ mt8195_etdm_clk_src_sel_put),
+};
+
+static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = {
+ /* eTDM_IN2 */
+ SND_SOC_DAPM_MIXER("I012", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I013", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I014", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I015", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I016", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I017", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I018", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I019", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* eTDM_IN1 */
+ SND_SOC_DAPM_MIXER("I072", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I073", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I074", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I075", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I076", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I077", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I078", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I079", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I080", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I081", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I082", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I083", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I084", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I085", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I086", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I087", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I088", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I089", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I090", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I091", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I092", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I093", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I094", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I095", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* eTDM_OUT2 */
+ SND_SOC_DAPM_MIXER("O048", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o048_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o048_mix)),
+ SND_SOC_DAPM_MIXER("O049", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o049_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o049_mix)),
+ SND_SOC_DAPM_MIXER("O050", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o050_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o050_mix)),
+ SND_SOC_DAPM_MIXER("O051", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o051_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o051_mix)),
+ SND_SOC_DAPM_MIXER("O052", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o052_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o052_mix)),
+ SND_SOC_DAPM_MIXER("O053", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o053_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o053_mix)),
+ SND_SOC_DAPM_MIXER("O054", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o054_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o054_mix)),
+ SND_SOC_DAPM_MIXER("O055", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o055_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o055_mix)),
+ SND_SOC_DAPM_MIXER("O056", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o056_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o056_mix)),
+ SND_SOC_DAPM_MIXER("O057", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o057_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o057_mix)),
+ SND_SOC_DAPM_MIXER("O058", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o058_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o058_mix)),
+ SND_SOC_DAPM_MIXER("O059", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o059_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o059_mix)),
+ SND_SOC_DAPM_MIXER("O060", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o060_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o060_mix)),
+ SND_SOC_DAPM_MIXER("O061", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o061_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o061_mix)),
+ SND_SOC_DAPM_MIXER("O062", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o062_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o062_mix)),
+ SND_SOC_DAPM_MIXER("O063", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o063_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o063_mix)),
+ SND_SOC_DAPM_MIXER("O064", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o064_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o064_mix)),
+ SND_SOC_DAPM_MIXER("O065", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o065_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o065_mix)),
+ SND_SOC_DAPM_MIXER("O066", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o066_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o066_mix)),
+ SND_SOC_DAPM_MIXER("O067", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o067_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o067_mix)),
+ SND_SOC_DAPM_MIXER("O068", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o068_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o068_mix)),
+ SND_SOC_DAPM_MIXER("O069", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o069_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o069_mix)),
+ SND_SOC_DAPM_MIXER("O070", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o070_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o070_mix)),
+ SND_SOC_DAPM_MIXER("O071", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o071_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o071_mix)),
+
+ /* eTDM_OUT1 */
+ SND_SOC_DAPM_MIXER("O072", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o072_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o072_mix)),
+ SND_SOC_DAPM_MIXER("O073", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o073_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o073_mix)),
+ SND_SOC_DAPM_MIXER("O074", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o074_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o074_mix)),
+ SND_SOC_DAPM_MIXER("O075", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o075_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o075_mix)),
+ SND_SOC_DAPM_MIXER("O076", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o076_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o076_mix)),
+ SND_SOC_DAPM_MIXER("O077", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o077_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o077_mix)),
+ SND_SOC_DAPM_MIXER("O078", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o078_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o078_mix)),
+ SND_SOC_DAPM_MIXER("O079", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o079_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o079_mix)),
+ SND_SOC_DAPM_MIXER("O080", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o080_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o080_mix)),
+ SND_SOC_DAPM_MIXER("O081", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o081_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o081_mix)),
+ SND_SOC_DAPM_MIXER("O082", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o082_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o082_mix)),
+ SND_SOC_DAPM_MIXER("O083", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o083_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o083_mix)),
+ SND_SOC_DAPM_MIXER("O084", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o084_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o084_mix)),
+ SND_SOC_DAPM_MIXER("O085", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o085_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o085_mix)),
+ SND_SOC_DAPM_MIXER("O086", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o086_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o086_mix)),
+ SND_SOC_DAPM_MIXER("O087", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o087_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o087_mix)),
+ SND_SOC_DAPM_MIXER("O088", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o088_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o088_mix)),
+ SND_SOC_DAPM_MIXER("O089", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o089_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o089_mix)),
+ SND_SOC_DAPM_MIXER("O090", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o090_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o090_mix)),
+ SND_SOC_DAPM_MIXER("O091", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o091_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o091_mix)),
+ SND_SOC_DAPM_MIXER("O092", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o092_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o092_mix)),
+ SND_SOC_DAPM_MIXER("O093", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o093_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o093_mix)),
+ SND_SOC_DAPM_MIXER("O094", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o094_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o094_mix)),
+ SND_SOC_DAPM_MIXER("O095", SND_SOC_NOPM, 0, 0,
+ mtk_dai_etdm_o095_mix,
+ ARRAY_SIZE(mtk_dai_etdm_o095_mix)),
+
+ /* eTDM_OUT3 */
+ SND_SOC_DAPM_MUX("HDMI_OUT_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_out_mux_control),
+ SND_SOC_DAPM_MUX("DPTX_OUT_MUX", SND_SOC_NOPM, 0, 0,
+ &dptx_out_mux_control),
+
+ SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_ch0_mux_control),
+ SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_ch1_mux_control),
+ SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_ch2_mux_control),
+ SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_ch3_mux_control),
+ SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_ch4_mux_control),
+ SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_ch5_mux_control),
+ SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_ch6_mux_control),
+ SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
+ &hdmi_ch7_mux_control),
+
+ SND_SOC_DAPM_INPUT("ETDM_INPUT"),
+ SND_SOC_DAPM_OUTPUT("ETDM_OUTPUT"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = {
+ {"I012", NULL, "ETDM2 Capture"},
+ {"I013", NULL, "ETDM2 Capture"},
+ {"I014", NULL, "ETDM2 Capture"},
+ {"I015", NULL, "ETDM2 Capture"},
+ {"I016", NULL, "ETDM2 Capture"},
+ {"I017", NULL, "ETDM2 Capture"},
+ {"I018", NULL, "ETDM2 Capture"},
+ {"I019", NULL, "ETDM2 Capture"},
+
+ {"I072", NULL, "ETDM1 Capture"},
+ {"I073", NULL, "ETDM1 Capture"},
+ {"I074", NULL, "ETDM1 Capture"},
+ {"I075", NULL, "ETDM1 Capture"},
+ {"I076", NULL, "ETDM1 Capture"},
+ {"I077", NULL, "ETDM1 Capture"},
+ {"I078", NULL, "ETDM1 Capture"},
+ {"I079", NULL, "ETDM1 Capture"},
+ {"I080", NULL, "ETDM1 Capture"},
+ {"I081", NULL, "ETDM1 Capture"},
+ {"I082", NULL, "ETDM1 Capture"},
+ {"I083", NULL, "ETDM1 Capture"},
+ {"I084", NULL, "ETDM1 Capture"},
+ {"I085", NULL, "ETDM1 Capture"},
+ {"I086", NULL, "ETDM1 Capture"},
+ {"I087", NULL, "ETDM1 Capture"},
+ {"I088", NULL, "ETDM1 Capture"},
+ {"I089", NULL, "ETDM1 Capture"},
+ {"I090", NULL, "ETDM1 Capture"},
+ {"I091", NULL, "ETDM1 Capture"},
+ {"I092", NULL, "ETDM1 Capture"},
+ {"I093", NULL, "ETDM1 Capture"},
+ {"I094", NULL, "ETDM1 Capture"},
+ {"I095", NULL, "ETDM1 Capture"},
+
+ {"UL8", NULL, "ETDM1 Capture"},
+ {"UL3", NULL, "ETDM2 Capture"},
+
+ {"ETDM2 Playback", NULL, "O048"},
+ {"ETDM2 Playback", NULL, "O049"},
+ {"ETDM2 Playback", NULL, "O050"},
+ {"ETDM2 Playback", NULL, "O051"},
+ {"ETDM2 Playback", NULL, "O052"},
+ {"ETDM2 Playback", NULL, "O053"},
+ {"ETDM2 Playback", NULL, "O054"},
+ {"ETDM2 Playback", NULL, "O055"},
+ {"ETDM2 Playback", NULL, "O056"},
+ {"ETDM2 Playback", NULL, "O057"},
+ {"ETDM2 Playback", NULL, "O058"},
+ {"ETDM2 Playback", NULL, "O059"},
+ {"ETDM2 Playback", NULL, "O060"},
+ {"ETDM2 Playback", NULL, "O061"},
+ {"ETDM2 Playback", NULL, "O062"},
+ {"ETDM2 Playback", NULL, "O063"},
+ {"ETDM2 Playback", NULL, "O064"},
+ {"ETDM2 Playback", NULL, "O065"},
+ {"ETDM2 Playback", NULL, "O066"},
+ {"ETDM2 Playback", NULL, "O067"},
+ {"ETDM2 Playback", NULL, "O068"},
+ {"ETDM2 Playback", NULL, "O069"},
+ {"ETDM2 Playback", NULL, "O070"},
+ {"ETDM2 Playback", NULL, "O071"},
+
+ {"ETDM1 Playback", NULL, "O072"},
+ {"ETDM1 Playback", NULL, "O073"},
+ {"ETDM1 Playback", NULL, "O074"},
+ {"ETDM1 Playback", NULL, "O075"},
+ {"ETDM1 Playback", NULL, "O076"},
+ {"ETDM1 Playback", NULL, "O077"},
+ {"ETDM1 Playback", NULL, "O078"},
+ {"ETDM1 Playback", NULL, "O079"},
+ {"ETDM1 Playback", NULL, "O080"},
+ {"ETDM1 Playback", NULL, "O081"},
+ {"ETDM1 Playback", NULL, "O082"},
+ {"ETDM1 Playback", NULL, "O083"},
+ {"ETDM1 Playback", NULL, "O084"},
+ {"ETDM1 Playback", NULL, "O085"},
+ {"ETDM1 Playback", NULL, "O086"},
+ {"ETDM1 Playback", NULL, "O087"},
+ {"ETDM1 Playback", NULL, "O088"},
+ {"ETDM1 Playback", NULL, "O089"},
+ {"ETDM1 Playback", NULL, "O090"},
+ {"ETDM1 Playback", NULL, "O091"},
+ {"ETDM1 Playback", NULL, "O092"},
+ {"ETDM1 Playback", NULL, "O093"},
+ {"ETDM1 Playback", NULL, "O094"},
+ {"ETDM1 Playback", NULL, "O095"},
+
+ {"O048", "I020 Switch", "I020"},
+ {"O049", "I021 Switch", "I021"},
+
+ {"O048", "I022 Switch", "I022"},
+ {"O049", "I023 Switch", "I023"},
+ {"O050", "I024 Switch", "I024"},
+ {"O051", "I025 Switch", "I025"},
+ {"O052", "I026 Switch", "I026"},
+ {"O053", "I027 Switch", "I027"},
+ {"O054", "I028 Switch", "I028"},
+ {"O055", "I029 Switch", "I029"},
+ {"O056", "I030 Switch", "I030"},
+ {"O057", "I031 Switch", "I031"},
+ {"O058", "I032 Switch", "I032"},
+ {"O059", "I033 Switch", "I033"},
+ {"O060", "I034 Switch", "I034"},
+ {"O061", "I035 Switch", "I035"},
+ {"O062", "I036 Switch", "I036"},
+ {"O063", "I037 Switch", "I037"},
+ {"O064", "I038 Switch", "I038"},
+ {"O065", "I039 Switch", "I039"},
+ {"O066", "I040 Switch", "I040"},
+ {"O067", "I041 Switch", "I041"},
+ {"O068", "I042 Switch", "I042"},
+ {"O069", "I043 Switch", "I043"},
+ {"O070", "I044 Switch", "I044"},
+ {"O071", "I045 Switch", "I045"},
+
+ {"O048", "I046 Switch", "I046"},
+ {"O049", "I047 Switch", "I047"},
+ {"O050", "I048 Switch", "I048"},
+ {"O051", "I049 Switch", "I049"},
+ {"O052", "I050 Switch", "I050"},
+ {"O053", "I051 Switch", "I051"},
+ {"O054", "I052 Switch", "I052"},
+ {"O055", "I053 Switch", "I053"},
+ {"O056", "I054 Switch", "I054"},
+ {"O057", "I055 Switch", "I055"},
+ {"O058", "I056 Switch", "I056"},
+ {"O059", "I057 Switch", "I057"},
+ {"O060", "I058 Switch", "I058"},
+ {"O061", "I059 Switch", "I059"},
+ {"O062", "I060 Switch", "I060"},
+ {"O063", "I061 Switch", "I061"},
+ {"O064", "I062 Switch", "I062"},
+ {"O065", "I063 Switch", "I063"},
+ {"O066", "I064 Switch", "I064"},
+ {"O067", "I065 Switch", "I065"},
+ {"O068", "I066 Switch", "I066"},
+ {"O069", "I067 Switch", "I067"},
+ {"O070", "I068 Switch", "I068"},
+ {"O071", "I069 Switch", "I069"},
+
+ {"O048", "I070 Switch", "I070"},
+ {"O049", "I071 Switch", "I071"},
+
+ {"O072", "I020 Switch", "I020"},
+ {"O073", "I021 Switch", "I021"},
+
+ {"O072", "I022 Switch", "I022"},
+ {"O073", "I023 Switch", "I023"},
+ {"O074", "I024 Switch", "I024"},
+ {"O075", "I025 Switch", "I025"},
+ {"O076", "I026 Switch", "I026"},
+ {"O077", "I027 Switch", "I027"},
+ {"O078", "I028 Switch", "I028"},
+ {"O079", "I029 Switch", "I029"},
+ {"O080", "I030 Switch", "I030"},
+ {"O081", "I031 Switch", "I031"},
+ {"O082", "I032 Switch", "I032"},
+ {"O083", "I033 Switch", "I033"},
+ {"O084", "I034 Switch", "I034"},
+ {"O085", "I035 Switch", "I035"},
+ {"O086", "I036 Switch", "I036"},
+ {"O087", "I037 Switch", "I037"},
+ {"O088", "I038 Switch", "I038"},
+ {"O089", "I039 Switch", "I039"},
+ {"O090", "I040 Switch", "I040"},
+ {"O091", "I041 Switch", "I041"},
+ {"O092", "I042 Switch", "I042"},
+ {"O093", "I043 Switch", "I043"},
+ {"O094", "I044 Switch", "I044"},
+ {"O095", "I045 Switch", "I045"},
+
+ {"O072", "I046 Switch", "I046"},
+ {"O073", "I047 Switch", "I047"},
+ {"O074", "I048 Switch", "I048"},
+ {"O075", "I049 Switch", "I049"},
+ {"O076", "I050 Switch", "I050"},
+ {"O077", "I051 Switch", "I051"},
+ {"O078", "I052 Switch", "I052"},
+ {"O079", "I053 Switch", "I053"},
+ {"O080", "I054 Switch", "I054"},
+ {"O081", "I055 Switch", "I055"},
+ {"O082", "I056 Switch", "I056"},
+ {"O083", "I057 Switch", "I057"},
+ {"O084", "I058 Switch", "I058"},
+ {"O085", "I059 Switch", "I059"},
+ {"O086", "I060 Switch", "I060"},
+ {"O087", "I061 Switch", "I061"},
+ {"O088", "I062 Switch", "I062"},
+ {"O089", "I063 Switch", "I063"},
+ {"O090", "I064 Switch", "I064"},
+ {"O091", "I065 Switch", "I065"},
+ {"O092", "I066 Switch", "I066"},
+ {"O093", "I067 Switch", "I067"},
+ {"O094", "I068 Switch", "I068"},
+ {"O095", "I069 Switch", "I069"},
+
+ {"O072", "I070 Switch", "I070"},
+ {"O073", "I071 Switch", "I071"},
+
+ {"HDMI_CH0_MUX", "CH0", "DL10"},
+ {"HDMI_CH0_MUX", "CH1", "DL10"},
+ {"HDMI_CH0_MUX", "CH2", "DL10"},
+ {"HDMI_CH0_MUX", "CH3", "DL10"},
+ {"HDMI_CH0_MUX", "CH4", "DL10"},
+ {"HDMI_CH0_MUX", "CH5", "DL10"},
+ {"HDMI_CH0_MUX", "CH6", "DL10"},
+ {"HDMI_CH0_MUX", "CH7", "DL10"},
+
+ {"HDMI_CH1_MUX", "CH0", "DL10"},
+ {"HDMI_CH1_MUX", "CH1", "DL10"},
+ {"HDMI_CH1_MUX", "CH2", "DL10"},
+ {"HDMI_CH1_MUX", "CH3", "DL10"},
+ {"HDMI_CH1_MUX", "CH4", "DL10"},
+ {"HDMI_CH1_MUX", "CH5", "DL10"},
+ {"HDMI_CH1_MUX", "CH6", "DL10"},
+ {"HDMI_CH1_MUX", "CH7", "DL10"},
+
+ {"HDMI_CH2_MUX", "CH0", "DL10"},
+ {"HDMI_CH2_MUX", "CH1", "DL10"},
+ {"HDMI_CH2_MUX", "CH2", "DL10"},
+ {"HDMI_CH2_MUX", "CH3", "DL10"},
+ {"HDMI_CH2_MUX", "CH4", "DL10"},
+ {"HDMI_CH2_MUX", "CH5", "DL10"},
+ {"HDMI_CH2_MUX", "CH6", "DL10"},
+ {"HDMI_CH2_MUX", "CH7", "DL10"},
+
+ {"HDMI_CH3_MUX", "CH0", "DL10"},
+ {"HDMI_CH3_MUX", "CH1", "DL10"},
+ {"HDMI_CH3_MUX", "CH2", "DL10"},
+ {"HDMI_CH3_MUX", "CH3", "DL10"},
+ {"HDMI_CH3_MUX", "CH4", "DL10"},
+ {"HDMI_CH3_MUX", "CH5", "DL10"},
+ {"HDMI_CH3_MUX", "CH6", "DL10"},
+ {"HDMI_CH3_MUX", "CH7", "DL10"},
+
+ {"HDMI_CH4_MUX", "CH0", "DL10"},
+ {"HDMI_CH4_MUX", "CH1", "DL10"},
+ {"HDMI_CH4_MUX", "CH2", "DL10"},
+ {"HDMI_CH4_MUX", "CH3", "DL10"},
+ {"HDMI_CH4_MUX", "CH4", "DL10"},
+ {"HDMI_CH4_MUX", "CH5", "DL10"},
+ {"HDMI_CH4_MUX", "CH6", "DL10"},
+ {"HDMI_CH4_MUX", "CH7", "DL10"},
+
+ {"HDMI_CH5_MUX", "CH0", "DL10"},
+ {"HDMI_CH5_MUX", "CH1", "DL10"},
+ {"HDMI_CH5_MUX", "CH2", "DL10"},
+ {"HDMI_CH5_MUX", "CH3", "DL10"},
+ {"HDMI_CH5_MUX", "CH4", "DL10"},
+ {"HDMI_CH5_MUX", "CH5", "DL10"},
+ {"HDMI_CH5_MUX", "CH6", "DL10"},
+ {"HDMI_CH5_MUX", "CH7", "DL10"},
+
+ {"HDMI_CH6_MUX", "CH0", "DL10"},
+ {"HDMI_CH6_MUX", "CH1", "DL10"},
+ {"HDMI_CH6_MUX", "CH2", "DL10"},
+ {"HDMI_CH6_MUX", "CH3", "DL10"},
+ {"HDMI_CH6_MUX", "CH4", "DL10"},
+ {"HDMI_CH6_MUX", "CH5", "DL10"},
+ {"HDMI_CH6_MUX", "CH6", "DL10"},
+ {"HDMI_CH6_MUX", "CH7", "DL10"},
+
+ {"HDMI_CH7_MUX", "CH0", "DL10"},
+ {"HDMI_CH7_MUX", "CH1", "DL10"},
+ {"HDMI_CH7_MUX", "CH2", "DL10"},
+ {"HDMI_CH7_MUX", "CH3", "DL10"},
+ {"HDMI_CH7_MUX", "CH4", "DL10"},
+ {"HDMI_CH7_MUX", "CH5", "DL10"},
+ {"HDMI_CH7_MUX", "CH6", "DL10"},
+ {"HDMI_CH7_MUX", "CH7", "DL10"},
+
+ {"HDMI_OUT_MUX", "Connect", "HDMI_CH0_MUX"},
+ {"HDMI_OUT_MUX", "Connect", "HDMI_CH1_MUX"},
+ {"HDMI_OUT_MUX", "Connect", "HDMI_CH2_MUX"},
+ {"HDMI_OUT_MUX", "Connect", "HDMI_CH3_MUX"},
+ {"HDMI_OUT_MUX", "Connect", "HDMI_CH4_MUX"},
+ {"HDMI_OUT_MUX", "Connect", "HDMI_CH5_MUX"},
+ {"HDMI_OUT_MUX", "Connect", "HDMI_CH6_MUX"},
+ {"HDMI_OUT_MUX", "Connect", "HDMI_CH7_MUX"},
+
+ {"DPTX_OUT_MUX", "Connect", "HDMI_CH0_MUX"},
+ {"DPTX_OUT_MUX", "Connect", "HDMI_CH1_MUX"},
+ {"DPTX_OUT_MUX", "Connect", "HDMI_CH2_MUX"},
+ {"DPTX_OUT_MUX", "Connect", "HDMI_CH3_MUX"},
+ {"DPTX_OUT_MUX", "Connect", "HDMI_CH4_MUX"},
+ {"DPTX_OUT_MUX", "Connect", "HDMI_CH5_MUX"},
+ {"DPTX_OUT_MUX", "Connect", "HDMI_CH6_MUX"},
+ {"DPTX_OUT_MUX", "Connect", "HDMI_CH7_MUX"},
+
+ {"ETDM3 Playback", NULL, "HDMI_OUT_MUX"},
+ {"DPTX Playback", NULL, "DPTX_OUT_MUX"},
+
+ {"ETDM_OUTPUT", NULL, "DPTX Playback"},
+ {"ETDM_OUTPUT", NULL, "ETDM1 Playback"},
+ {"ETDM_OUTPUT", NULL, "ETDM2 Playback"},
+ {"ETDM_OUTPUT", NULL, "ETDM3 Playback"},
+ {"ETDM1 Capture", NULL, "ETDM_INPUT"},
+ {"ETDM2 Capture", NULL, "ETDM_INPUT"},
+};
+
+static int mt8195_afe_enable_etdm(struct mtk_base_afe *afe, int dai_id)
+{
+ int ret = 0;
+ struct etdm_con_reg etdm_reg;
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+ unsigned long flags;
+
+ spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ etdm_data->en_ref_cnt++;
+ if (etdm_data->en_ref_cnt == 1) {
+ ret = get_etdm_reg(dai_id, &etdm_reg);
+ if (ret < 0)
+ goto out;
+
+ regmap_update_bits(afe->regmap, etdm_reg.con0,
+ ETDM_CON0_EN, ETDM_CON0_EN);
+ }
+out:
+ spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+ return ret;
+}
+
+static int mt8195_afe_disable_etdm(struct mtk_base_afe *afe, int dai_id)
+{
+ int ret = 0;
+ struct etdm_con_reg etdm_reg;
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+ unsigned long flags;
+
+ spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ if (etdm_data->en_ref_cnt > 0) {
+ etdm_data->en_ref_cnt--;
+ if (etdm_data->en_ref_cnt == 0) {
+ ret = get_etdm_reg(dai_id, &etdm_reg);
+ if (ret < 0)
+ goto out;
+
+ regmap_update_bits(afe->regmap, etdm_reg.con0,
+ ETDM_CON0_EN, 0);
+ }
+ }
+out:
+ spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+ return 0;
+}
+
+static int etdm_cowork_slv_sel(int id, int slave_mode)
+{
+ if (slave_mode) {
+ switch (id) {
+ case MT8195_AFE_IO_ETDM1_IN:
+ return COWORK_ETDM_IN1_S;
+ case MT8195_AFE_IO_ETDM2_IN:
+ return COWORK_ETDM_IN2_S;
+ case MT8195_AFE_IO_ETDM1_OUT:
+ return COWORK_ETDM_OUT1_S;
+ case MT8195_AFE_IO_ETDM2_OUT:
+ return COWORK_ETDM_OUT2_S;
+ case MT8195_AFE_IO_ETDM3_OUT:
+ return COWORK_ETDM_OUT3_S;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (id) {
+ case MT8195_AFE_IO_ETDM1_IN:
+ return COWORK_ETDM_IN1_M;
+ case MT8195_AFE_IO_ETDM2_IN:
+ return COWORK_ETDM_IN2_M;
+ case MT8195_AFE_IO_ETDM1_OUT:
+ return COWORK_ETDM_OUT1_M;
+ case MT8195_AFE_IO_ETDM2_OUT:
+ return COWORK_ETDM_OUT2_M;
+ case MT8195_AFE_IO_ETDM3_OUT:
+ return COWORK_ETDM_OUT3_M;
+ default:
+ return -EINVAL;
+ }
+ }
+}
+
+static int mt8195_etdm_sync_mode_configure(struct mtk_base_afe *afe, int dai_id)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+ unsigned int reg = 0;
+ unsigned int mask;
+ unsigned int val;
+ int cowork_source_sel;
+
+ if (etdm_data->cowork_source_id == COWORK_ETDM_NONE)
+ return 0;
+
+ cowork_source_sel = etdm_cowork_slv_sel(etdm_data->cowork_source_id,
+ etdm_data->slave_mode);
+ if (cowork_source_sel < 0)
+ return cowork_source_sel;
+
+ switch (dai_id) {
+ case MT8195_AFE_IO_ETDM1_IN:
+ reg = ETDM_COWORK_CON1;
+ mask = ETDM_IN1_SLAVE_SEL_MASK;
+ val = ETDM_IN1_SLAVE_SEL(cowork_source_sel);
+ break;
+ case MT8195_AFE_IO_ETDM2_IN:
+ reg = ETDM_COWORK_CON2;
+ mask = ETDM_IN2_SLAVE_SEL_MASK;
+ val = ETDM_IN2_SLAVE_SEL(cowork_source_sel);
+ break;
+ case MT8195_AFE_IO_ETDM1_OUT:
+ reg = ETDM_COWORK_CON0;
+ mask = ETDM_OUT1_SLAVE_SEL_MASK;
+ val = ETDM_OUT1_SLAVE_SEL(cowork_source_sel);
+ break;
+ case MT8195_AFE_IO_ETDM2_OUT:
+ reg = ETDM_COWORK_CON2;
+ mask = ETDM_OUT2_SLAVE_SEL_MASK;
+ val = ETDM_OUT2_SLAVE_SEL(cowork_source_sel);
+ break;
+ case MT8195_AFE_IO_ETDM3_OUT:
+ reg = ETDM_COWORK_CON2;
+ mask = ETDM_OUT3_SLAVE_SEL_MASK;
+ val = ETDM_OUT3_SLAVE_SEL(cowork_source_sel);
+ break;
+ default:
+ return 0;
+ }
+
+ regmap_update_bits(afe->regmap, reg, mask, val);
+
+ return 0;
+}
+
+static int mtk_dai_etdm_get_cg_id_by_dai_id(int dai_id)
+{
+ int cg_id = -1;
+
+ switch (dai_id) {
+ case MT8195_AFE_IO_DPTX:
+ cg_id = MT8195_CLK_AUD_HDMI_OUT;
+ break;
+ case MT8195_AFE_IO_ETDM1_IN:
+ cg_id = MT8195_CLK_AUD_TDM_IN;
+ break;
+ case MT8195_AFE_IO_ETDM2_IN:
+ cg_id = MT8195_CLK_AUD_I2SIN;
+ break;
+ case MT8195_AFE_IO_ETDM1_OUT:
+ cg_id = MT8195_CLK_AUD_TDM_OUT;
+ break;
+ case MT8195_AFE_IO_ETDM2_OUT:
+ cg_id = MT8195_CLK_AUD_I2S_OUT;
+ break;
+ case MT8195_AFE_IO_ETDM3_OUT:
+ cg_id = MT8195_CLK_AUD_HDMI_OUT;
+ break;
+ default:
+ break;
+ }
+
+ return cg_id;
+}
+
+static int mtk_dai_etdm_get_clk_id_by_dai_id(int dai_id)
+{
+ int clk_id = -1;
+
+ switch (dai_id) {
+ case MT8195_AFE_IO_DPTX:
+ clk_id = MT8195_CLK_TOP_DPTX_M_SEL;
+ break;
+ case MT8195_AFE_IO_ETDM1_IN:
+ clk_id = MT8195_CLK_TOP_I2SI1_M_SEL;
+ break;
+ case MT8195_AFE_IO_ETDM2_IN:
+ clk_id = MT8195_CLK_TOP_I2SI2_M_SEL;
+ break;
+ case MT8195_AFE_IO_ETDM1_OUT:
+ clk_id = MT8195_CLK_TOP_I2SO1_M_SEL;
+ break;
+ case MT8195_AFE_IO_ETDM2_OUT:
+ clk_id = MT8195_CLK_TOP_I2SO2_M_SEL;
+ break;
+ case MT8195_AFE_IO_ETDM3_OUT:
+ default:
+ break;
+ }
+
+ return clk_id;
+}
+
+static int mtk_dai_etdm_get_clkdiv_id_by_dai_id(int dai_id)
+{
+ int clk_id = -1;
+
+ switch (dai_id) {
+ case MT8195_AFE_IO_DPTX:
+ clk_id = MT8195_CLK_TOP_APLL12_DIV9;
+ break;
+ case MT8195_AFE_IO_ETDM1_IN:
+ clk_id = MT8195_CLK_TOP_APLL12_DIV0;
+ break;
+ case MT8195_AFE_IO_ETDM2_IN:
+ clk_id = MT8195_CLK_TOP_APLL12_DIV1;
+ break;
+ case MT8195_AFE_IO_ETDM1_OUT:
+ clk_id = MT8195_CLK_TOP_APLL12_DIV2;
+ break;
+ case MT8195_AFE_IO_ETDM2_OUT:
+ clk_id = MT8195_CLK_TOP_APLL12_DIV3;
+ break;
+ case MT8195_AFE_IO_ETDM3_OUT:
+ default:
+ break;
+ }
+
+ return clk_id;
+}
+
+static int mtk_dai_etdm_enable_mclk(struct mtk_base_afe *afe, int dai_id)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
+
+ if (clkdiv_id < 0)
+ return -EINVAL;
+
+ mt8195_afe_enable_clk(afe, afe_priv->clk[clkdiv_id]);
+
+ return 0;
+}
+
+static int mtk_dai_etdm_disable_mclk(struct mtk_base_afe *afe, int dai_id)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
+
+ if (clkdiv_id < 0)
+ return -EINVAL;
+
+ mt8195_afe_disable_clk(afe, afe_priv->clk[clkdiv_id]);
+
+ return 0;
+}
+
+/* dai ops */
+static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *mst_etdm_data;
+ int cg_id;
+ int mst_dai_id;
+ int slv_dai_id;
+ int i;
+
+ if (is_cowork_mode(dai)) {
+ mst_dai_id = get_etdm_cowork_master_id(dai);
+ mtk_dai_etdm_enable_mclk(afe, mst_dai_id);
+
+ cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id);
+ if (cg_id >= 0)
+ mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]);
+
+ mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+
+ for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+ slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+ cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(slv_dai_id);
+ if (cg_id >= 0)
+ mt8195_afe_enable_clk(afe,
+ afe_priv->clk[cg_id]);
+ }
+ } else {
+ mtk_dai_etdm_enable_mclk(afe, dai->id);
+
+ cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
+ if (cg_id >= 0)
+ mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]);
+ }
+
+ return 0;
+}
+
+static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *mst_etdm_data;
+ int cg_id;
+ int mst_dai_id;
+ int slv_dai_id;
+ int i;
+
+ if (is_cowork_mode(dai)) {
+ mst_dai_id = get_etdm_cowork_master_id(dai);
+ cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id);
+ if (cg_id >= 0)
+ mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]);
+
+ mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+ for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+ slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+ cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(slv_dai_id);
+ if (cg_id >= 0)
+ mt8195_afe_disable_clk(afe,
+ afe_priv->clk[cg_id]);
+ }
+ mtk_dai_etdm_disable_mclk(afe, mst_dai_id);
+ } else {
+ cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
+ if (cg_id >= 0)
+ mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]);
+
+ mtk_dai_etdm_disable_mclk(afe, dai->id);
+ }
+}
+
+static int mtk_dai_etdm_fifo_mode(struct mtk_base_afe *afe,
+ int dai_id, unsigned int rate)
+{
+ unsigned int mode = 0;
+ unsigned int reg = 0;
+ unsigned int val = 0;
+ unsigned int mask = (ETDM_IN_AFIFO_MODE_MASK | ETDM_IN_USE_AFIFO);
+
+ if (rate != 0)
+ mode = mt8195_afe_fs_timing(rate);
+
+ switch (dai_id) {
+ case MT8195_AFE_IO_ETDM1_IN:
+ reg = ETDM_IN1_AFIFO_CON;
+ if (rate == 0)
+ mode = MT8195_ETDM_IN1_1X_EN;
+ break;
+ case MT8195_AFE_IO_ETDM2_IN:
+ reg = ETDM_IN2_AFIFO_CON;
+ if (rate == 0)
+ mode = MT8195_ETDM_IN2_1X_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val = (mode | ETDM_IN_USE_AFIFO);
+
+ regmap_update_bits(afe->regmap, reg, mask, val);
+ return 0;
+}
+
+static int mtk_dai_etdm_in_configure(struct mtk_base_afe *afe,
+ unsigned int rate,
+ unsigned int channels,
+ int dai_id)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+ struct etdm_con_reg etdm_reg;
+ bool slave_mode = etdm_data->slave_mode;
+ unsigned int data_mode = etdm_data->data_mode;
+ unsigned int lrck_width = etdm_data->lrck_width;
+ unsigned int val = 0;
+ unsigned int mask = 0;
+ int i;
+ int ret;
+
+ dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n",
+ __func__, rate, channels, dai_id);
+
+ ret = get_etdm_reg(dai_id, &etdm_reg);
+ if (ret < 0)
+ return ret;
+
+ if (etdm_data->cowork_source_id != COWORK_ETDM_NONE)
+ slave_mode = true;
+
+ /* afifo */
+ if (slave_mode)
+ mtk_dai_etdm_fifo_mode(afe, dai_id, 0);
+ else
+ mtk_dai_etdm_fifo_mode(afe, dai_id, rate);
+
+ /* con1 */
+ if (lrck_width > 0) {
+ mask |= (ETDM_IN_CON1_LRCK_AUTO_MODE |
+ ETDM_IN_CON1_LRCK_WIDTH_MASK);
+ val |= ETDM_IN_CON1_LRCK_WIDTH(lrck_width);
+ }
+ regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val);
+
+ mask = 0;
+ val = 0;
+
+ /* con2 */
+ if (!slave_mode) {
+ mask |= ETDM_IN_CON2_UPDATE_GAP_MASK;
+ if (rate == 352800 || rate == 384000)
+ val |= ETDM_IN_CON2_UPDATE_GAP(4);
+ else
+ val |= ETDM_IN_CON2_UPDATE_GAP(3);
+ }
+ mask |= (ETDM_IN_CON2_MULTI_IP_2CH_MODE |
+ ETDM_IN_CON2_MULTI_IP_TOTAL_CH_MASK);
+ if (data_mode == MTK_DAI_ETDM_DATA_MULTI_PIN) {
+ val |= ETDM_IN_CON2_MULTI_IP_2CH_MODE |
+ ETDM_IN_CON2_MULTI_IP_TOTAL_CH(channels);
+ }
+ regmap_update_bits(afe->regmap, etdm_reg.con2, mask, val);
+
+ mask = 0;
+ val = 0;
+
+ /* con3 */
+ mask |= ETDM_IN_CON3_DISABLE_OUT_MASK;
+ for (i = 0; i < channels; i += 2) {
+ if (etdm_data->in_disable_ch[i] &&
+ etdm_data->in_disable_ch[i + 1])
+ val |= ETDM_IN_CON3_DISABLE_OUT(i >> 1);
+ }
+ if (!slave_mode) {
+ mask |= ETDM_IN_CON3_FS_MASK;
+ val |= ETDM_IN_CON3_FS(get_etdm_fs_timing(rate));
+ }
+ regmap_update_bits(afe->regmap, etdm_reg.con3, mask, val);
+
+ mask = 0;
+ val = 0;
+
+ /* con4 */
+ mask |= (ETDM_IN_CON4_MASTER_LRCK_INV | ETDM_IN_CON4_MASTER_BCK_INV |
+ ETDM_IN_CON4_SLAVE_LRCK_INV | ETDM_IN_CON4_SLAVE_BCK_INV);
+ if (slave_mode) {
+ if (etdm_data->lrck_inv)
+ val |= ETDM_IN_CON4_SLAVE_LRCK_INV;
+ if (etdm_data->bck_inv)
+ val |= ETDM_IN_CON4_SLAVE_BCK_INV;
+ } else {
+ if (etdm_data->lrck_inv)
+ val |= ETDM_IN_CON4_MASTER_LRCK_INV;
+ if (etdm_data->bck_inv)
+ val |= ETDM_IN_CON4_MASTER_BCK_INV;
+ }
+ regmap_update_bits(afe->regmap, etdm_reg.con4, mask, val);
+
+ mask = 0;
+ val = 0;
+
+ /* con5 */
+ mask |= ETDM_IN_CON5_LR_SWAP_MASK;
+ mask |= ETDM_IN_CON5_ENABLE_ODD_MASK;
+ for (i = 0; i < channels; i += 2) {
+ if (etdm_data->in_disable_ch[i] &&
+ !etdm_data->in_disable_ch[i + 1]) {
+ if (i == (channels - 2))
+ val |= ETDM_IN_CON5_LR_SWAP(15);
+ else
+ val |= ETDM_IN_CON5_LR_SWAP(i >> 1);
+ val |= ETDM_IN_CON5_ENABLE_ODD(i >> 1);
+ } else if (!etdm_data->in_disable_ch[i] &&
+ etdm_data->in_disable_ch[i + 1]) {
+ val |= ETDM_IN_CON5_ENABLE_ODD(i >> 1);
+ }
+ }
+ regmap_update_bits(afe->regmap, etdm_reg.con5, mask, val);
+ return 0;
+}
+
+static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe,
+ unsigned int rate,
+ unsigned int channels,
+ int dai_id)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+ struct etdm_con_reg etdm_reg;
+ bool slave_mode = etdm_data->slave_mode;
+ unsigned int lrck_width = etdm_data->lrck_width;
+ unsigned int val = 0;
+ unsigned int mask = 0;
+ int ret;
+ int fs = 0;
+
+ dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n",
+ __func__, rate, channels, dai_id);
+
+ ret = get_etdm_reg(dai_id, &etdm_reg);
+ if (ret < 0)
+ return ret;
+
+ if (etdm_data->cowork_source_id != COWORK_ETDM_NONE)
+ slave_mode = true;
+
+ /* con0 */
+ mask = ETDM_OUT_CON0_RELATCH_DOMAIN_MASK;
+ val = ETDM_OUT_CON0_RELATCH_DOMAIN(ETDM_RELATCH_TIMING_A1A2SYS);
+ regmap_update_bits(afe->regmap, etdm_reg.con0, mask, val);
+
+ mask = 0;
+ val = 0;
+
+ /* con1 */
+ if (lrck_width > 0) {
+ mask |= (ETDM_OUT_CON1_LRCK_AUTO_MODE |
+ ETDM_OUT_CON1_LRCK_WIDTH_MASK);
+ val |= ETDM_OUT_CON1_LRCK_WIDTH(lrck_width);
+ }
+ regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val);
+
+ mask = 0;
+ val = 0;
+
+ if (slave_mode) {
+ /* con2 */
+ mask = (ETDM_OUT_CON2_LRCK_DELAY_BCK_INV |
+ ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN);
+ val = (ETDM_OUT_CON2_LRCK_DELAY_BCK_INV |
+ ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN);
+ regmap_update_bits(afe->regmap, etdm_reg.con2,
+ mask, val);
+ mask = 0;
+ val = 0;
+ } else {
+ /* con4 */
+ mask |= ETDM_OUT_CON4_FS_MASK;
+ val |= ETDM_OUT_CON4_FS(get_etdm_fs_timing(rate));
+ }
+
+ mask |= ETDM_OUT_CON4_RELATCH_EN_MASK;
+ if (dai_id == MT8195_AFE_IO_ETDM1_OUT)
+ fs = MT8195_ETDM_OUT1_1X_EN;
+ else if (dai_id == MT8195_AFE_IO_ETDM2_OUT)
+ fs = MT8195_ETDM_OUT2_1X_EN;
+
+ val |= ETDM_OUT_CON4_RELATCH_EN(fs);
+
+ regmap_update_bits(afe->regmap, etdm_reg.con4, mask, val);
+
+ mask = 0;
+ val = 0;
+
+ /* con5 */
+ mask |= (ETDM_OUT_CON5_MASTER_LRCK_INV | ETDM_OUT_CON5_MASTER_BCK_INV |
+ ETDM_OUT_CON5_SLAVE_LRCK_INV | ETDM_OUT_CON5_SLAVE_BCK_INV);
+ if (slave_mode) {
+ if (etdm_data->lrck_inv)
+ val |= ETDM_OUT_CON5_SLAVE_LRCK_INV;
+ if (etdm_data->bck_inv)
+ val |= ETDM_OUT_CON5_SLAVE_BCK_INV;
+ } else {
+ if (etdm_data->lrck_inv)
+ val |= ETDM_OUT_CON5_MASTER_LRCK_INV;
+ if (etdm_data->bck_inv)
+ val |= ETDM_OUT_CON5_MASTER_BCK_INV;
+ }
+ regmap_update_bits(afe->regmap, etdm_reg.con5, mask, val);
+
+ return 0;
+}
+
+static int mtk_dai_etdm_mclk_configure(struct mtk_base_afe *afe, int dai_id)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+ int clk_id = mtk_dai_etdm_get_clk_id_by_dai_id(dai_id);
+ int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id);
+ int apll;
+ int apll_clk_id;
+ struct etdm_con_reg etdm_reg;
+ unsigned int val = 0;
+ unsigned int mask = 0;
+ int ret = 0;
+
+ if (clk_id < 0 || clkdiv_id < 0)
+ return 0;
+
+ ret = get_etdm_reg(dai_id, &etdm_reg);
+ if (ret < 0)
+ return ret;
+
+ mask |= ETDM_CON1_MCLK_OUTPUT;
+ if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT)
+ val |= ETDM_CON1_MCLK_OUTPUT;
+ regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val);
+
+ if (etdm_data->mclk_freq) {
+ apll = etdm_data->mclk_apll;
+ apll_clk_id = mt8195_afe_get_mclk_source_clk_id(apll);
+ if (apll_clk_id < 0)
+ return apll_clk_id;
+
+ /* select apll */
+ ret = mt8195_afe_set_clk_parent(afe, afe_priv->clk[clk_id],
+ afe_priv->clk[apll_clk_id]);
+ if (ret)
+ return ret;
+
+ /* set rate */
+ ret = mt8195_afe_set_clk_rate(afe, afe_priv->clk[clkdiv_id],
+ etdm_data->mclk_freq);
+ } else {
+ if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT)
+ dev_dbg(afe->dev, "%s mclk freq = 0\n", __func__);
+ }
+ return ret;
+}
+
+static int mtk_dai_etdm_configure(struct mtk_base_afe *afe,
+ unsigned int rate,
+ unsigned int channels,
+ unsigned int bit_width,
+ int dai_id)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+ struct etdm_con_reg etdm_reg;
+ bool slave_mode = etdm_data->slave_mode;
+ unsigned int etdm_channels;
+ unsigned int val = 0;
+ unsigned int mask = 0;
+ unsigned int bck;
+ unsigned int wlen = get_etdm_wlen(bit_width);
+ int ret;
+
+ ret = get_etdm_reg(dai_id, &etdm_reg);
+ if (ret < 0)
+ return ret;
+
+ if (etdm_data->cowork_source_id != COWORK_ETDM_NONE)
+ slave_mode = true;
+
+ dev_dbg(afe->dev, "%s fmt %u data %u lrck %d-%u bck %d, clock %u slv %u\n",
+ __func__, etdm_data->format, etdm_data->data_mode,
+ etdm_data->lrck_inv, etdm_data->lrck_width, etdm_data->bck_inv,
+ etdm_data->clock_mode, etdm_data->slave_mode);
+ dev_dbg(afe->dev, "%s rate %u channels %u bitwidth %u, id %d\n",
+ __func__, rate, channels, bit_width, dai_id);
+
+ etdm_channels = (etdm_data->data_mode == MTK_DAI_ETDM_DATA_ONE_PIN) ?
+ get_etdm_ch_fixup(channels) : 2;
+
+ bck = rate * etdm_channels * wlen;
+ if (bck > MT8195_ETDM_NORMAL_MAX_BCK_RATE) {
+ dev_info(afe->dev, "%s bck rate %u not support\n",
+ __func__, bck);
+ return -EINVAL;
+ }
+
+ /* con0 */
+ mask |= ETDM_CON0_BIT_LEN_MASK;
+ val |= ETDM_CON0_BIT_LEN(bit_width);
+ mask |= ETDM_CON0_WORD_LEN_MASK;
+ val |= ETDM_CON0_WORD_LEN(wlen);
+ mask |= ETDM_CON0_FORMAT_MASK;
+ val |= ETDM_CON0_FORMAT(etdm_data->format);
+ mask |= ETDM_CON0_CH_NUM_MASK;
+ val |= ETDM_CON0_CH_NUM(etdm_channels);
+
+ mask |= ETDM_CON0_SLAVE_MODE;
+ if (slave_mode) {
+ if (dai_id == MT8195_AFE_IO_ETDM1_OUT &&
+ etdm_data->cowork_source_id == COWORK_ETDM_NONE) {
+ dev_info(afe->dev, "%s id %d only support master mode\n",
+ __func__, dai_id);
+ return -EINVAL;
+ }
+ val |= ETDM_CON0_SLAVE_MODE;
+ }
+ regmap_update_bits(afe->regmap, etdm_reg.con0, mask, val);
+
+ if (get_etdm_dir(dai_id) == ETDM_IN)
+ mtk_dai_etdm_in_configure(afe, rate, channels, dai_id);
+ else
+ mtk_dai_etdm_out_configure(afe, rate, channels, dai_id);
+
+ return 0;
+}
+
+static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ int ret = 0;
+ unsigned int rate = params_rate(params);
+ unsigned int bit_width = params_width(params);
+ unsigned int channels = params_channels(params);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *mst_etdm_data;
+ int mst_dai_id;
+ int slv_dai_id;
+ int i;
+
+ dev_dbg(afe->dev, "%s '%s' period %u-%u\n",
+ __func__, snd_pcm_stream_str(substream),
+ params_period_size(params), params_periods(params));
+
+ if (is_cowork_mode(dai)) {
+ mst_dai_id = get_etdm_cowork_master_id(dai);
+
+ ret = mtk_dai_etdm_mclk_configure(afe, mst_dai_id);
+ if (ret)
+ return ret;
+
+ ret = mtk_dai_etdm_configure(afe, rate, channels,
+ bit_width, mst_dai_id);
+ if (ret)
+ return ret;
+
+ mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+ for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+ slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+ ret = mtk_dai_etdm_configure(afe, rate, channels,
+ bit_width, slv_dai_id);
+ if (ret)
+ return ret;
+
+ ret = mt8195_etdm_sync_mode_configure(afe, slv_dai_id);
+ if (ret)
+ return ret;
+ }
+ } else {
+ ret = mtk_dai_etdm_mclk_configure(afe, dai->id);
+ if (ret)
+ return ret;
+
+ ret = mtk_dai_etdm_configure(afe, rate, channels,
+ bit_width, dai->id);
+ }
+
+ return ret;
+}
+
+static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ int ret = 0;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *mst_etdm_data;
+ int mst_dai_id;
+ int slv_dai_id;
+ int i;
+
+ dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ if (is_cowork_mode(dai)) {
+ mst_dai_id = get_etdm_cowork_master_id(dai);
+ mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+
+ //open master first
+ ret |= mt8195_afe_enable_etdm(afe, mst_dai_id);
+ for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+ slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+ ret |= mt8195_afe_enable_etdm(afe, slv_dai_id);
+ }
+ } else {
+ ret = mt8195_afe_enable_etdm(afe, dai->id);
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (is_cowork_mode(dai)) {
+ mst_dai_id = get_etdm_cowork_master_id(dai);
+ mst_etdm_data = afe_priv->dai_priv[mst_dai_id];
+
+ for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) {
+ slv_dai_id = mst_etdm_data->cowork_slv_id[i];
+ ret |= mt8195_afe_disable_etdm(afe, slv_dai_id);
+ }
+ // close master at last
+ ret |= mt8195_afe_disable_etdm(afe, mst_dai_id);
+ } else {
+ ret = mt8195_afe_disable_etdm(afe, dai->id);
+ }
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static int mtk_dai_etdm_cal_mclk(struct mtk_base_afe *afe, int freq, int dai_id)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id];
+ int apll;
+ int apll_rate;
+
+ if (freq == 0) {
+ etdm_data->mclk_freq = freq;
+ return 0;
+ }
+
+ apll = mt8195_afe_get_default_mclk_source_by_rate(freq);
+ apll_rate = mt8195_afe_get_mclk_source_rate(afe, apll);
+
+ if (freq > apll_rate) {
+ dev_info(afe->dev, "freq %d > apll rate %d\n", freq, apll_rate);
+ return -EINVAL;
+ }
+
+ if (apll_rate % freq != 0) {
+ dev_info(afe->dev, "APLL%d cannot generate freq Hz\n", apll);
+ return -EINVAL;
+ }
+
+ etdm_data->mclk_apll = apll;
+ etdm_data->mclk_freq = freq;
+
+ return 0;
+}
+
+static int mtk_dai_etdm_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+ int dai_id;
+
+ dev_dbg(dai->dev, "%s id %d freq %u, dir %d\n",
+ __func__, dai->id, freq, dir);
+ if (is_cowork_mode(dai))
+ dai_id = get_etdm_cowork_master_id(dai);
+ else
+ dai_id = dai->id;
+
+ etdm_data = afe_priv->dai_priv[dai_id];
+ etdm_data->mclk_dir = dir;
+ return mtk_dai_etdm_cal_mclk(afe, freq, dai_id);
+}
+
+static int mtk_dai_etdm_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+ dev_dbg(dai->dev, "%s id %d slot_width %d\n",
+ __func__, dai->id, slot_width);
+
+ etdm_data->slots = slots;
+ etdm_data->lrck_width = slot_width;
+ return 0;
+}
+
+static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ etdm_data->format = MTK_DAI_ETDM_FORMAT_LJ;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ etdm_data->format = MTK_DAI_ETDM_FORMAT_RJ;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPA;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPB;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ etdm_data->bck_inv = false;
+ etdm_data->lrck_inv = false;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ etdm_data->bck_inv = false;
+ etdm_data->lrck_inv = true;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ etdm_data->bck_inv = true;
+ etdm_data->lrck_inv = false;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ etdm_data->bck_inv = true;
+ etdm_data->lrck_inv = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ etdm_data->slave_mode = true;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ etdm_data->slave_mode = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mtk_dai_hdmitx_dptx_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
+
+ if (cg_id >= 0)
+ mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]);
+
+ mtk_dai_etdm_enable_mclk(afe, dai->id);
+
+ return 0;
+}
+
+static void mtk_dai_hdmitx_dptx_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ int cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id);
+
+ mtk_dai_etdm_disable_mclk(afe, dai->id);
+
+ if (cg_id >= 0)
+ mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]);
+}
+
+static unsigned int mtk_dai_get_dptx_ch_en(unsigned int channel)
+{
+ switch (channel) {
+ case 1 ... 2:
+ return AFE_DPTX_CON_CH_EN_2CH;
+ case 3 ... 4:
+ return AFE_DPTX_CON_CH_EN_4CH;
+ case 5 ... 6:
+ return AFE_DPTX_CON_CH_EN_6CH;
+ case 7 ... 8:
+ return AFE_DPTX_CON_CH_EN_8CH;
+ default:
+ return AFE_DPTX_CON_CH_EN_2CH;
+ }
+}
+
+static unsigned int mtk_dai_get_dptx_ch(unsigned int ch)
+{
+ return (ch > 2) ?
+ AFE_DPTX_CON_CH_NUM_8CH : AFE_DPTX_CON_CH_NUM_2CH;
+}
+
+static unsigned int mtk_dai_get_dptx_wlen(snd_pcm_format_t format)
+{
+ return snd_pcm_format_physical_width(format) <= 16 ?
+ AFE_DPTX_CON_16BIT : AFE_DPTX_CON_24BIT;
+}
+
+static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+ unsigned int rate = params_rate(params);
+ unsigned int channels = params_channels(params);
+ snd_pcm_format_t format = params_format(params);
+ int width = snd_pcm_format_physical_width(format);
+ int ret = 0;
+
+ /* dptx configure */
+ if (dai->id == MT8195_AFE_IO_DPTX) {
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ AFE_DPTX_CON_CH_EN_MASK,
+ mtk_dai_get_dptx_ch_en(channels));
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ AFE_DPTX_CON_CH_NUM_MASK,
+ mtk_dai_get_dptx_ch(channels));
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ AFE_DPTX_CON_16BIT_MASK,
+ mtk_dai_get_dptx_wlen(format));
+
+ if (mtk_dai_get_dptx_ch(channels) == AFE_DPTX_CON_CH_NUM_8CH) {
+ etdm_data->data_mode = MTK_DAI_ETDM_DATA_ONE_PIN;
+ channels = 8;
+ } else {
+ channels = 2;
+ }
+ } else {
+ etdm_data->data_mode = MTK_DAI_ETDM_DATA_MULTI_PIN;
+ }
+
+ ret = mtk_dai_etdm_mclk_configure(afe, dai->id);
+ if (ret)
+ return ret;
+
+ ret = mtk_dai_etdm_configure(afe, rate, channels, width, dai->id);
+
+ return ret;
+}
+
+static int mtk_dai_hdmitx_dptx_trigger(struct snd_pcm_substream *substream,
+ int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+
+ dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ /* enable dptx interface */
+ if (dai->id == MT8195_AFE_IO_DPTX)
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ AFE_DPTX_CON_ON_MASK,
+ AFE_DPTX_CON_ON);
+
+ /* enable etdm_out3 */
+ ret = mt8195_afe_enable_etdm(afe, dai->id);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ /* disable etdm_out3 */
+ ret = mt8195_afe_disable_etdm(afe, dai->id);
+
+ /* disable dptx interface */
+ if (dai->id == MT8195_AFE_IO_DPTX)
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ AFE_DPTX_CON_ON_MASK, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id,
+ unsigned int freq,
+ int dir)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+ dev_dbg(dai->dev, "%s id %d freq %u, dir %d\n",
+ __func__, dai->id, freq, dir);
+
+ etdm_data->mclk_dir = dir;
+ return mtk_dai_etdm_cal_mclk(afe, freq, dai->id);
+}
+
+static const struct snd_soc_dai_ops mtk_dai_etdm_ops = {
+ .startup = mtk_dai_etdm_startup,
+ .shutdown = mtk_dai_etdm_shutdown,
+ .hw_params = mtk_dai_etdm_hw_params,
+ .trigger = mtk_dai_etdm_trigger,
+ .set_sysclk = mtk_dai_etdm_set_sysclk,
+ .set_fmt = mtk_dai_etdm_set_fmt,
+ .set_tdm_slot = mtk_dai_etdm_set_tdm_slot,
+};
+
+static const struct snd_soc_dai_ops mtk_dai_hdmitx_dptx_ops = {
+ .startup = mtk_dai_hdmitx_dptx_startup,
+ .shutdown = mtk_dai_hdmitx_dptx_shutdown,
+ .hw_params = mtk_dai_hdmitx_dptx_hw_params,
+ .trigger = mtk_dai_hdmitx_dptx_trigger,
+ .set_sysclk = mtk_dai_hdmitx_dptx_set_sysclk,
+ .set_fmt = mtk_dai_etdm_set_fmt,
+};
+
+/* dai driver */
+#define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_384000)
+
+#define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static int mtk_dai_etdm_probe(struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
+
+ dev_dbg(dai->dev, "%s id %d\n", __func__, dai->id);
+
+ if (etdm_data->mclk_freq) {
+ dev_dbg(afe->dev, "MCLK always on, rate %d\n",
+ etdm_data->mclk_freq);
+ pm_runtime_get_sync(afe->dev);
+ mtk_dai_etdm_mclk_configure(afe, dai->id);
+ mtk_dai_etdm_enable_mclk(afe, dai->id);
+ pm_runtime_put_sync(afe->dev);
+ }
+ return 0;
+}
+
+static struct snd_soc_dai_driver mtk_dai_etdm_driver[] = {
+ {
+ .name = "DPTX",
+ .id = MT8195_AFE_IO_DPTX,
+ .playback = {
+ .stream_name = "DPTX Playback",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = MTK_ETDM_RATES,
+ .formats = MTK_ETDM_FORMATS,
+ },
+ .ops = &mtk_dai_hdmitx_dptx_ops,
+ },
+ {
+ .name = "ETDM1_IN",
+ .id = MT8195_AFE_IO_ETDM1_IN,
+ .capture = {
+ .stream_name = "ETDM1 Capture",
+ .channels_min = 1,
+ .channels_max = 24,
+ .rates = MTK_ETDM_RATES,
+ .formats = MTK_ETDM_FORMATS,
+ },
+ .ops = &mtk_dai_etdm_ops,
+ .probe = mtk_dai_etdm_probe,
+ },
+ {
+ .name = "ETDM2_IN",
+ .id = MT8195_AFE_IO_ETDM2_IN,
+ .capture = {
+ .stream_name = "ETDM2 Capture",
+ .channels_min = 1,
+ .channels_max = 16,
+ .rates = MTK_ETDM_RATES,
+ .formats = MTK_ETDM_FORMATS,
+ },
+ .ops = &mtk_dai_etdm_ops,
+ .probe = mtk_dai_etdm_probe,
+ },
+ {
+ .name = "ETDM1_OUT",
+ .id = MT8195_AFE_IO_ETDM1_OUT,
+ .playback = {
+ .stream_name = "ETDM1 Playback",
+ .channels_min = 1,
+ .channels_max = 24,
+ .rates = MTK_ETDM_RATES,
+ .formats = MTK_ETDM_FORMATS,
+ },
+ .ops = &mtk_dai_etdm_ops,
+ .probe = mtk_dai_etdm_probe,
+ },
+ {
+ .name = "ETDM2_OUT",
+ .id = MT8195_AFE_IO_ETDM2_OUT,
+ .playback = {
+ .stream_name = "ETDM2 Playback",
+ .channels_min = 1,
+ .channels_max = 24,
+ .rates = MTK_ETDM_RATES,
+ .formats = MTK_ETDM_FORMATS,
+ },
+ .ops = &mtk_dai_etdm_ops,
+ .probe = mtk_dai_etdm_probe,
+ },
+ {
+ .name = "ETDM3_OUT",
+ .id = MT8195_AFE_IO_ETDM3_OUT,
+ .playback = {
+ .stream_name = "ETDM3 Playback",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = MTK_ETDM_RATES,
+ .formats = MTK_ETDM_FORMATS,
+ },
+ .ops = &mtk_dai_hdmitx_dptx_ops,
+ .probe = mtk_dai_etdm_probe,
+ },
+};
+
+static void mt8195_etdm_update_sync_info(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data;
+ struct mtk_dai_etdm_priv *mst_data;
+ int i;
+ int mst_dai_id;
+
+ for (i = MT8195_AFE_IO_ETDM_START; i < MT8195_AFE_IO_ETDM_END; i++) {
+ etdm_data = afe_priv->dai_priv[i];
+ if (etdm_data->cowork_source_id != COWORK_ETDM_NONE) {
+ mst_dai_id = etdm_data->cowork_source_id;
+ mst_data = afe_priv->dai_priv[mst_dai_id];
+ if (mst_data->cowork_source_id != COWORK_ETDM_NONE)
+ dev_info(afe->dev, "%s [%d] wrong sync source\n"
+ , __func__, i);
+ mst_data->cowork_slv_id[mst_data->cowork_slv_count] = i;
+ mst_data->cowork_slv_count++;
+ }
+ }
+}
+
+static void mt8195_dai_etdm_parse_of(struct mtk_base_afe *afe)
+{
+ const struct device_node *of_node = afe->dev->of_node;
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_data;
+ int i, j;
+ char prop[48];
+ u8 disable_chn[MT8195_ETDM_MAX_CHANNELS];
+ int max_chn = MT8195_ETDM_MAX_CHANNELS;
+ u32 sel;
+ int ret;
+ int dai_id;
+ unsigned int sync_id;
+ struct {
+ const char *name;
+ const unsigned int sync_id;
+ } of_afe_etdms[MT8195_AFE_IO_ETDM_NUM] = {
+ {"etdm-in1", ETDM_SYNC_FROM_IN1},
+ {"etdm-in2", ETDM_SYNC_FROM_IN2},
+ {"etdm-out1", ETDM_SYNC_FROM_OUT1},
+ {"etdm-out2", ETDM_SYNC_FROM_OUT2},
+ {"etdm-out3", ETDM_SYNC_FROM_OUT3},
+ };
+
+ for (i = 0; i < MT8195_AFE_IO_ETDM_NUM; i++) {
+ dai_id = ETDM_TO_DAI_ID(i);
+ etdm_data = afe_priv->dai_priv[dai_id];
+
+ ret = snprintf(prop, sizeof(prop),
+ "mediatek,%s-mclk-always-on-rate",
+ of_afe_etdms[i].name);
+ if (ret < 0) {
+ dev_info(afe->dev, "%s snprintf err=%d\n",
+ __func__, ret);
+ return;
+ }
+ ret = of_property_read_u32(of_node, prop, &sel);
+ if (ret == 0) {
+ etdm_data->mclk_dir = SND_SOC_CLOCK_OUT;
+ if (mtk_dai_etdm_cal_mclk(afe, sel, dai_id))
+ dev_info(afe->dev, "%s unsupported mclk %uHz\n",
+ __func__, sel);
+ }
+
+ ret = snprintf(prop, sizeof(prop),
+ "mediatek,%s-multi-pin-mode",
+ of_afe_etdms[i].name);
+ if (ret < 0) {
+ dev_info(afe->dev, "%s snprintf err=%d\n",
+ __func__, ret);
+ return;
+ }
+ etdm_data->data_mode = of_property_read_bool(of_node, prop);
+
+ ret = snprintf(prop, sizeof(prop),
+ "mediatek,%s-cowork-source",
+ of_afe_etdms[i].name);
+ if (ret < 0) {
+ dev_info(afe->dev, "%s snprintf err=%d\n",
+ __func__, ret);
+ return;
+ }
+ ret = of_property_read_u32(of_node, prop, &sel);
+ if (ret == 0) {
+ if (sel >= MT8195_AFE_IO_ETDM_NUM) {
+ dev_info(afe->dev, "%s invalid id=%d\n",
+ __func__, sel);
+ etdm_data->cowork_source_id = COWORK_ETDM_NONE;
+ } else {
+ sync_id = of_afe_etdms[sel].sync_id;
+ etdm_data->cowork_source_id =
+ sync_to_dai_id(sync_id);
+ }
+ } else {
+ etdm_data->cowork_source_id = COWORK_ETDM_NONE;
+ }
+ }
+
+ /* etdm in only */
+ for (i = 0; i < 2; i++) {
+ ret = snprintf(prop, sizeof(prop),
+ "mediatek,%s-chn-disabled",
+ of_afe_etdms[i].name);
+ if (ret < 0) {
+ dev_info(afe->dev, "%s snprintf err=%d\n",
+ __func__, ret);
+ return;
+ }
+ ret = of_property_read_variable_u8_array(of_node, prop,
+ disable_chn,
+ 1, max_chn);
+ if (ret < 0)
+ continue;
+
+ for (j = 0; j < ret; j++) {
+ if (disable_chn[j] >= MT8195_ETDM_MAX_CHANNELS)
+ dev_info(afe->dev, "%s [%d] invalid chn %u\n",
+ __func__, j, disable_chn[j]);
+ else
+ etdm_data->in_disable_ch[disable_chn[j]] = true;
+ }
+ }
+ mt8195_etdm_update_sync_info(afe);
+}
+
+static int init_etdm_priv_data(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_etdm_priv *etdm_priv;
+ int i;
+
+ for (i = MT8195_AFE_IO_ETDM_START; i < MT8195_AFE_IO_ETDM_END; i++) {
+ etdm_priv = devm_kzalloc(afe->dev,
+ sizeof(struct mtk_dai_etdm_priv),
+ GFP_KERNEL);
+ if (!etdm_priv)
+ return -ENOMEM;
+
+ afe_priv->dai_priv[i] = etdm_priv;
+ }
+
+ afe_priv->dai_priv[MT8195_AFE_IO_DPTX] =
+ afe_priv->dai_priv[MT8195_AFE_IO_ETDM3_OUT];
+
+ mt8195_dai_etdm_parse_of(afe);
+ return 0;
+}
+
+int mt8195_dai_etdm_register(struct mtk_base_afe *afe)
+{
+ struct mtk_base_afe_dai *dai;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ dai->dai_drivers = mtk_dai_etdm_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_etdm_driver);
+
+ dai->dapm_widgets = mtk_dai_etdm_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_etdm_widgets);
+ dai->dapm_routes = mtk_dai_etdm_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_etdm_routes);
+ dai->controls = mtk_dai_etdm_controls;
+ dai->num_controls = ARRAY_SIZE(mtk_dai_etdm_controls);
+
+ return init_etdm_priv_data(afe);
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
new file mode 100644
index 000000000000..5d10d2c4c991
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI PCM I/F Control
+ *
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ * Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8195-afe-clk.h"
+#include "mt8195-afe-common.h"
+#include "mt8195-reg.h"
+
+enum {
+ MTK_DAI_PCM_FMT_I2S,
+ MTK_DAI_PCM_FMT_EIAJ,
+ MTK_DAI_PCM_FMT_MODEA,
+ MTK_DAI_PCM_FMT_MODEB,
+};
+
+enum {
+ MTK_DAI_PCM_CLK_A1SYS,
+ MTK_DAI_PCM_CLK_A2SYS,
+ MTK_DAI_PCM_CLK_26M_48K,
+ MTK_DAI_PCM_CLK_26M_441K,
+};
+
+struct mtk_dai_pcm_rate {
+ unsigned int rate;
+ unsigned int reg_value;
+};
+
+struct mtk_dai_pcmif_priv {
+ unsigned int slave_mode;
+ unsigned int lrck_inv;
+ unsigned int bck_inv;
+ unsigned int format;
+};
+
+static const struct mtk_dai_pcm_rate mtk_dai_pcm_rates[] = {
+ { .rate = 8000, .reg_value = 0, },
+ { .rate = 16000, .reg_value = 1, },
+ { .rate = 32000, .reg_value = 2, },
+ { .rate = 48000, .reg_value = 3, },
+ { .rate = 11025, .reg_value = 1, },
+ { .rate = 22050, .reg_value = 2, },
+ { .rate = 44100, .reg_value = 3, },
+};
+
+static int mtk_dai_pcm_mode(unsigned int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mtk_dai_pcm_rates); i++)
+ if (mtk_dai_pcm_rates[i].rate == rate)
+ return mtk_dai_pcm_rates[i].reg_value;
+
+ return -EINVAL;
+}
+
+static const struct snd_kcontrol_new mtk_dai_pcm_o000_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN0, 0, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN0_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_pcm_o001_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN1, 1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN1_2, 7, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
+ SND_SOC_DAPM_MIXER("I002", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I003", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("O000", SND_SOC_NOPM, 0, 0,
+ mtk_dai_pcm_o000_mix,
+ ARRAY_SIZE(mtk_dai_pcm_o000_mix)),
+ SND_SOC_DAPM_MIXER("O001", SND_SOC_NOPM, 0, 0,
+ mtk_dai_pcm_o001_mix,
+ ARRAY_SIZE(mtk_dai_pcm_o001_mix)),
+
+ SND_SOC_DAPM_INPUT("PCM1_INPUT"),
+ SND_SOC_DAPM_OUTPUT("PCM1_OUTPUT"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
+ {"I002", NULL, "PCM1 Capture"},
+ {"I003", NULL, "PCM1 Capture"},
+
+ {"O000", "I000 Switch", "I000"},
+ {"O001", "I001 Switch", "I001"},
+
+ {"O000", "I070 Switch", "I070"},
+ {"O001", "I071 Switch", "I071"},
+
+ {"PCM1 Playback", NULL, "O000"},
+ {"PCM1 Playback", NULL, "O001"},
+
+ {"PCM1_OUTPUT", NULL, "PCM1 Playback"},
+ {"PCM1 Capture", NULL, "PCM1_INPUT"},
+};
+
+static void mtk_dai_pcm_enable(struct mtk_base_afe *afe)
+{
+ regmap_update_bits(afe->regmap, PCM_INTF_CON1,
+ PCM_INTF_CON1_PCM_EN, PCM_INTF_CON1_PCM_EN);
+}
+
+static void mtk_dai_pcm_disable(struct mtk_base_afe *afe)
+{
+ regmap_update_bits(afe->regmap, PCM_INTF_CON1,
+ PCM_INTF_CON1_PCM_EN, 0x0);
+}
+
+static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime * const runtime = substream->runtime;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id];
+ unsigned int slave_mode = pcmif_priv->slave_mode;
+ unsigned int lrck_inv = pcmif_priv->lrck_inv;
+ unsigned int bck_inv = pcmif_priv->bck_inv;
+ unsigned int fmt = pcmif_priv->format;
+ unsigned int bit_width = dai->sample_bits;
+ unsigned int val = 0;
+ unsigned int mask = 0;
+ int fs = 0;
+ int mode = 0;
+
+ /* sync freq mode */
+ fs = mt8195_afe_fs_timing(runtime->rate);
+ if (fs < 0)
+ return -EINVAL;
+ val |= PCM_INTF_CON2_SYNC_FREQ_MODE(fs);
+ mask |= PCM_INTF_CON2_SYNC_FREQ_MODE_MASK;
+
+ /* clk domain sel */
+ if (runtime->rate % 8000)
+ val |= PCM_INTF_CON2_CLK_DOMAIN_SEL(MTK_DAI_PCM_CLK_26M_441K);
+ else
+ val |= PCM_INTF_CON2_CLK_DOMAIN_SEL(MTK_DAI_PCM_CLK_26M_48K);
+ mask |= PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK;
+
+ regmap_update_bits(afe->regmap, PCM_INTF_CON2, mask, val);
+
+ val = 0;
+ mask = 0;
+
+ /* pcm mode */
+ mode = mtk_dai_pcm_mode(runtime->rate);
+ if (mode < 0)
+ return -EINVAL;
+ val |= PCM_INTF_CON1_PCM_MODE(mode);
+ mask |= PCM_INTF_CON1_PCM_MODE_MASK;
+
+ /* pcm format */
+ val |= PCM_INTF_CON1_PCM_FMT(fmt);
+ mask |= PCM_INTF_CON1_PCM_FMT_MASK;
+
+ /* pcm sync length */
+ if (fmt == MTK_DAI_PCM_FMT_MODEA ||
+ fmt == MTK_DAI_PCM_FMT_MODEB)
+ val |= PCM_INTF_CON1_SYNC_LENGTH(1);
+ else
+ val |= PCM_INTF_CON1_SYNC_LENGTH(bit_width);
+ mask |= PCM_INTF_CON1_SYNC_LENGTH_MASK;
+
+ /* pcm bits, word length */
+ if (bit_width > 16) {
+ val |= PCM_INTF_CON1_PCM_24BIT;
+ val |= PCM_INTF_CON1_PCM_WLEN_64BCK;
+ } else {
+ val |= PCM_INTF_CON1_PCM_16BIT;
+ val |= PCM_INTF_CON1_PCM_WLEN_32BCK;
+ }
+ mask |= PCM_INTF_CON1_PCM_BIT_MASK;
+ mask |= PCM_INTF_CON1_PCM_WLEN_MASK;
+
+ /* master/slave */
+ if (!slave_mode) {
+ val |= PCM_INTF_CON1_PCM_MASTER;
+
+ if (lrck_inv)
+ val |= PCM_INTF_CON1_SYNC_OUT_INV;
+ if (bck_inv)
+ val |= PCM_INTF_CON1_BCLK_OUT_INV;
+ mask |= PCM_INTF_CON1_CLK_OUT_INV_MASK;
+ } else {
+ val |= PCM_INTF_CON1_PCM_SLAVE;
+
+ if (lrck_inv)
+ val |= PCM_INTF_CON1_SYNC_IN_INV;
+ if (bck_inv)
+ val |= PCM_INTF_CON1_BCLK_IN_INV;
+ mask |= PCM_INTF_CON1_CLK_IN_INV_MASK;
+
+ /* TODO: add asrc setting for slave mode */
+ }
+ mask |= PCM_INTF_CON1_PCM_M_S_MASK;
+
+ regmap_update_bits(afe->regmap, PCM_INTF_CON1, mask, val);
+
+ return 0;
+}
+
+/* dai ops */
+static int mtk_dai_pcm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+ if (dai->component->active)
+ return 0;
+
+ mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]);
+ mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]);
+ mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]);
+
+ return 0;
+}
+
+static void mtk_dai_pcm_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+ if (dai->component->active)
+ return;
+
+ mtk_dai_pcm_disable(afe);
+
+ mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]);
+ mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]);
+ mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]);
+}
+
+static int mtk_dai_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+
+ if (snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK) &&
+ snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE))
+ return 0;
+
+ ret = mtk_dai_pcm_configure(substream, dai);
+ if (ret)
+ return ret;
+
+ mtk_dai_pcm_enable(afe);
+
+ return 0;
+}
+
+static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id];
+
+ dev_dbg(dai->dev, "%s fmt 0x%x\n", __func__, fmt);
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ pcmif_priv->format = MTK_DAI_PCM_FMT_I2S;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ pcmif_priv->format = MTK_DAI_PCM_FMT_MODEA;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ pcmif_priv->format = MTK_DAI_PCM_FMT_MODEB;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ pcmif_priv->bck_inv = 0;
+ pcmif_priv->lrck_inv = 0;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ pcmif_priv->bck_inv = 0;
+ pcmif_priv->lrck_inv = 1;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ pcmif_priv->bck_inv = 1;
+ pcmif_priv->lrck_inv = 0;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ pcmif_priv->bck_inv = 1;
+ pcmif_priv->lrck_inv = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ pcmif_priv->slave_mode = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ pcmif_priv->slave_mode = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
+ .startup = mtk_dai_pcm_startup,
+ .shutdown = mtk_dai_pcm_shutdown,
+ .prepare = mtk_dai_pcm_prepare,
+ .set_fmt = mtk_dai_pcm_set_fmt,
+};
+
+/* dai driver */
+#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000)
+
+#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
+ {
+ .name = "PCM1",
+ .id = MT8195_AFE_IO_PCM,
+ .playback = {
+ .stream_name = "PCM1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .capture = {
+ .stream_name = "PCM1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_PCM_RATES,
+ .formats = MTK_PCM_FORMATS,
+ },
+ .ops = &mtk_dai_pcm_ops,
+ .symmetric_rate = 1,
+ .symmetric_sample_bits = 1,
+ },
+};
+
+static int init_pcmif_priv_data(struct mtk_base_afe *afe)
+{
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_dai_pcmif_priv *pcmif_priv;
+
+ pcmif_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_pcmif_priv),
+ GFP_KERNEL);
+ if (!pcmif_priv)
+ return -ENOMEM;
+
+ afe_priv->dai_priv[MT8195_AFE_IO_PCM] = pcmif_priv;
+ return 0;
+}
+
+int mt8195_dai_pcm_register(struct mtk_base_afe *afe)
+{
+ struct mtk_base_afe_dai *dai;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ dai->dai_drivers = mtk_dai_pcm_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
+
+ dai->dapm_widgets = mtk_dai_pcm_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
+ dai->dapm_routes = mtk_dai_pcm_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
+
+ return init_pcmif_priv_data(afe);
+}
diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c
new file mode 100644
index 000000000000..5dc217f59bd6
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c
@@ -0,0 +1,1087 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8195-mt6359-rt1019-rt5682.c --
+// MT8195-MT6359-RT1019-RT6358 ALSA SoC machine driver
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Trevor Wu <trevor.wu@mediatek.com>
+//
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/rt5682.h>
+#include <sound/soc.h>
+#include "../../codecs/mt6359.h"
+#include "../../codecs/rt5682.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "mt8195-afe-common.h"
+
+#define RT1019_CODEC_DAI "HiFi"
+#define RT1019_DEV0_NAME "rt1019p"
+
+#define RT5682_CODEC_DAI "rt5682-aif1"
+#define RT5682_DEV0_NAME "rt5682.2-001a"
+
+struct mt8195_mt6359_rt1019_rt5682_priv {
+ struct snd_soc_jack headset_jack;
+ struct snd_soc_jack dp_jack;
+ struct snd_soc_jack hdmi_jack;
+};
+
+static const struct snd_soc_dapm_widget
+ mt8195_mt6359_rt1019_rt5682_widgets[] = {
+ SND_SOC_DAPM_SPK("Speakers", NULL),
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route mt8195_mt6359_rt1019_rt5682_routes[] = {
+ /* speaker */
+ { "Speakers", NULL, "Speaker" },
+ /* headset */
+ { "Headphone Jack", NULL, "HPOL" },
+ { "Headphone Jack", NULL, "HPOR" },
+ { "IN1P", NULL, "Headset Mic" },
+};
+
+static const struct snd_kcontrol_new mt8195_mt6359_rt1019_rt5682_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Speakers"),
+ SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+};
+
+static int mt8195_rt5682_etdm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ unsigned int rate = params_rate(params);
+ unsigned int mclk_fs_ratio = 128;
+ unsigned int mclk_fs = rate * mclk_fs_ratio;
+ int bitwidth;
+ int ret;
+
+ bitwidth = snd_pcm_format_width(params_format(params));
+ if (bitwidth < 0) {
+ dev_err(card->dev, "invalid bit width: %d\n", bitwidth);
+ return bitwidth;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth);
+ if (ret) {
+ dev_err(card->dev, "failed to set tdm slot\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1,
+ RT5682_PLL1_S_BCLK1,
+ params_rate(params) * 64,
+ params_rate(params) * 512);
+ if (ret) {
+ dev_err(card->dev, "failed to set pll\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ RT5682_SCLK_S_PLL1,
+ params_rate(params) * 512,
+ SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(card->dev, "failed to set sysclk\n");
+ return ret;
+ }
+
+ return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8195_rt5682_etdm_ops = {
+ .hw_params = mt8195_rt5682_etdm_hw_params,
+};
+
+#define CKSYS_AUD_TOP_CFG 0x032c
+#define CKSYS_AUD_TOP_MON 0x0330
+
+static int mt8195_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *cmpnt_afe =
+ snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
+ struct mt8195_afe_private *afe_priv = afe->platform_priv;
+ struct mtkaif_param *param = &afe_priv->mtkaif_params;
+ int phase;
+ unsigned int monitor;
+ int mtkaif_calibration_num_phase;
+ int test_done_1, test_done_2, test_done_3;
+ int cycle_1, cycle_2, cycle_3;
+ int prev_cycle_1, prev_cycle_2, prev_cycle_3;
+ int chosen_phase_1, chosen_phase_2, chosen_phase_3;
+ int counter;
+ bool mtkaif_calibration_ok;
+ int mtkaif_chosen_phase[MT8195_MTKAIF_MISO_NUM];
+ int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM];
+ int i;
+
+ dev_info(afe->dev, "%s(), start\n", __func__);
+
+ param->mtkaif_calibration_ok = false;
+ for (i = 0; i < MT8195_MTKAIF_MISO_NUM; i++) {
+ param->mtkaif_chosen_phase[i] = -1;
+ param->mtkaif_phase_cycle[i] = 0;
+ mtkaif_chosen_phase[i] = -1;
+ mtkaif_phase_cycle[i] = 0;
+ }
+
+ if (IS_ERR(afe_priv->topckgen)) {
+ dev_info(afe->dev, "%s() Cannot find topckgen controller\n",
+ __func__);
+ return 0;
+ }
+
+ pm_runtime_get_sync(afe->dev);
+ mt6359_mtkaif_calibration_enable(cmpnt_codec);
+
+ /* set test type to synchronizer pulse */
+ regmap_update_bits(afe_priv->topckgen,
+ CKSYS_AUD_TOP_CFG, 0xffff, 0x4);
+ mtkaif_calibration_num_phase = 42; /* mt6359: 0 ~ 42 */
+ mtkaif_calibration_ok = true;
+
+ for (phase = 0;
+ phase <= mtkaif_calibration_num_phase && mtkaif_calibration_ok;
+ phase++) {
+ mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
+ phase, phase, phase);
+
+ regmap_update_bits(afe_priv->topckgen,
+ CKSYS_AUD_TOP_CFG, 0x1, 0x1);
+
+ test_done_1 = 0;
+ test_done_2 = 0;
+ test_done_3 = 0;
+ cycle_1 = -1;
+ cycle_2 = -1;
+ cycle_3 = -1;
+ counter = 0;
+ while (!(test_done_1 & test_done_2 & test_done_3)) {
+ regmap_read(afe_priv->topckgen,
+ CKSYS_AUD_TOP_MON, &monitor);
+ test_done_1 = (monitor >> 28) & 0x1;
+ test_done_2 = (monitor >> 29) & 0x1;
+ test_done_3 = (monitor >> 30) & 0x1;
+ if (test_done_1 == 1)
+ cycle_1 = monitor & 0xf;
+
+ if (test_done_2 == 1)
+ cycle_2 = (monitor >> 4) & 0xf;
+
+ if (test_done_3 == 1)
+ cycle_3 = (monitor >> 8) & 0xf;
+
+ /* handle if never test done */
+ if (++counter > 10000) {
+ dev_info(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, cycle_3 %d, monitor 0x%x\n",
+ __func__,
+ cycle_1, cycle_2, cycle_3, monitor);
+ mtkaif_calibration_ok = false;
+ break;
+ }
+ }
+
+ if (phase == 0) {
+ prev_cycle_1 = cycle_1;
+ prev_cycle_2 = cycle_2;
+ prev_cycle_3 = cycle_3;
+ }
+
+ if (cycle_1 != prev_cycle_1 &&
+ mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] < 0) {
+ mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] = phase - 1;
+ mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] = prev_cycle_1;
+ }
+
+ if (cycle_2 != prev_cycle_2 &&
+ mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] < 0) {
+ mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] = phase - 1;
+ mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] = prev_cycle_2;
+ }
+
+ if (cycle_3 != prev_cycle_3 &&
+ mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] < 0) {
+ mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] = phase - 1;
+ mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] = prev_cycle_3;
+ }
+
+ regmap_update_bits(afe_priv->topckgen,
+ CKSYS_AUD_TOP_CFG, 0x1, 0x0);
+
+ if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] >= 0 &&
+ mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] >= 0 &&
+ mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] >= 0)
+ break;
+ }
+
+ if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] < 0) {
+ mtkaif_calibration_ok = false;
+ chosen_phase_1 = 0;
+ } else {
+ chosen_phase_1 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0];
+ }
+
+ if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] < 0) {
+ mtkaif_calibration_ok = false;
+ chosen_phase_2 = 0;
+ } else {
+ chosen_phase_2 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1];
+ }
+
+ if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] < 0) {
+ mtkaif_calibration_ok = false;
+ chosen_phase_3 = 0;
+ } else {
+ chosen_phase_3 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2];
+ }
+
+ mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
+ chosen_phase_1,
+ chosen_phase_2,
+ chosen_phase_3);
+
+ mt6359_mtkaif_calibration_disable(cmpnt_codec);
+ pm_runtime_put(afe->dev);
+
+ param->mtkaif_calibration_ok = mtkaif_calibration_ok;
+ param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] = chosen_phase_1;
+ param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] = chosen_phase_2;
+ param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] = chosen_phase_3;
+ for (i = 0; i < MT8195_MTKAIF_MISO_NUM; i++)
+ param->mtkaif_phase_cycle[i] = mtkaif_phase_cycle[i];
+
+ dev_info(afe->dev, "%s(), end, calibration ok %d\n",
+ __func__, param->mtkaif_calibration_ok);
+
+ return 0;
+}
+
+static int mt8195_mt6359_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+
+ /* set mtkaif protocol */
+ mt6359_set_mtkaif_protocol(cmpnt_codec,
+ MT6359_MTKAIF_PROTOCOL_2_CLK_P2);
+
+ /* mtkaif calibration */
+ mt8195_mt6359_mtkaif_calibration(rtd);
+
+ return 0;
+}
+
+static int mt8195_rt5682_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ struct mt8195_mt6359_rt1019_rt5682_priv *priv =
+ snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_jack *jack = &priv->headset_jack;
+ int ret;
+
+ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 |
+ SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+ SND_JACK_BTN_3,
+ jack, NULL, 0);
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
+ return ret;
+ }
+
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+
+ ret = snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack set failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+};
+
+static int mt8195_etdm_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ /* fix BE i2s format to 32bit, clean param mask first */
+ snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+ 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+ return 0;
+}
+
+static int mt8195_hdmitx_dptx_startup(struct snd_pcm_substream *substream)
+{
+ static const unsigned int rates[] = {
+ 48000
+ };
+ static const unsigned int channels[] = {
+ 2, 4, 6, 8
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+ };
+
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_rates);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8195_hdmitx_dptx_playback_ops = {
+ .startup = mt8195_hdmitx_dptx_startup,
+};
+
+static int mt8195_dptx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ unsigned int rate = params_rate(params);
+ unsigned int mclk_fs_ratio = 256;
+ unsigned int mclk_fs = rate * mclk_fs_ratio;
+
+ return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs,
+ SND_SOC_CLOCK_OUT);
+}
+
+static struct snd_soc_ops mt8195_dptx_ops = {
+ .hw_params = mt8195_dptx_hw_params,
+};
+
+static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct mt8195_mt6359_rt1019_rt5682_priv *priv =
+ snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ int ret = 0;
+
+ ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT,
+ &priv->dp_jack, NULL, 0);
+ if (ret)
+ return ret;
+
+ return snd_soc_component_set_jack(cmpnt_codec, &priv->dp_jack, NULL);
+}
+
+static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct mt8195_mt6359_rt1019_rt5682_priv *priv =
+ snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_component *cmpnt_codec =
+ asoc_rtd_to_codec(rtd, 0)->component;
+ int ret = 0;
+
+ ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
+ &priv->hdmi_jack, NULL, 0);
+ if (ret)
+ return ret;
+
+ return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
+}
+
+static int mt8195_hdmitx_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+
+{
+ /* fix BE i2s format to 32bit, clean param mask first */
+ snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+ 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+ return 0;
+}
+
+static int mt8195_playback_startup(struct snd_pcm_substream *substream)
+{
+ static const unsigned int rates[] = {
+ 48000
+ };
+ static const unsigned int channels[] = {
+ 2
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+ };
+
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_rates);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8195_playback_ops = {
+ .startup = mt8195_playback_startup,
+};
+
+static int mt8195_capture_startup(struct snd_pcm_substream *substream)
+{
+ static const unsigned int rates[] = {
+ 48000
+ };
+ static const unsigned int channels[] = {
+ 1, 2
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+ };
+ static const struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+ };
+
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_rates);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+ if (ret < 0) {
+ dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8195_capture_ops = {
+ .startup = mt8195_capture_startup,
+};
+
+enum {
+ DAI_LINK_DL2_FE,
+ DAI_LINK_DL3_FE,
+ DAI_LINK_DL6_FE,
+ DAI_LINK_DL7_FE,
+ DAI_LINK_DL8_FE,
+ DAI_LINK_DL10_FE,
+ DAI_LINK_DL11_FE,
+ DAI_LINK_UL1_FE,
+ DAI_LINK_UL2_FE,
+ DAI_LINK_UL3_FE,
+ DAI_LINK_UL4_FE,
+ DAI_LINK_UL5_FE,
+ DAI_LINK_UL6_FE,
+ DAI_LINK_UL8_FE,
+ DAI_LINK_UL9_FE,
+ DAI_LINK_UL10_FE,
+ DAI_LINK_DL_SRC_BE,
+ DAI_LINK_DPTX_BE,
+ DAI_LINK_ETDM1_IN_BE,
+ DAI_LINK_ETDM2_IN_BE,
+ DAI_LINK_ETDM1_OUT_BE,
+ DAI_LINK_ETDM2_OUT_BE,
+ DAI_LINK_ETDM3_OUT_BE,
+ DAI_LINK_PCM1_BE,
+ DAI_LINK_UL_SRC1_BE,
+ DAI_LINK_UL_SRC2_BE,
+};
+
+/* FE */
+SND_SOC_DAILINK_DEFS(DL2_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL3_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL6_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL7_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL8_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL10_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL10")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL11_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL11")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL1_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL2_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL3_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL4_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL5_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL6_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL8_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL8")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL9_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL9")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL10_FE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL10")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* BE */
+SND_SOC_DAILINK_DEFS(DL_SRC_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL_SRC")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+ "mt6359-snd-codec-aif1")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DPTX_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("DPTX")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM1_IN_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_IN")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM2_IN_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_IN")),
+ DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
+ RT5682_CODEC_DAI)),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM1_OUT_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_OUT")),
+ DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
+ RT5682_CODEC_DAI)),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM2_OUT_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_OUT")),
+ DAILINK_COMP_ARRAY(COMP_CODEC(RT1019_DEV0_NAME,
+ RT1019_CODEC_DAI)),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM3_OUT_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("ETDM3_OUT")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(PCM1_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("PCM1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL_SRC1_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC1")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+ "mt6359-snd-codec-aif1"),
+ COMP_CODEC("dmic-codec",
+ "dmic-hifi")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL_SRC2_BE,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC2")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+ "mt6359-snd-codec-aif2")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link mt8195_mt6359_rt1019_rt5682_dai_links[] = {
+ /* FE */
+ [DAI_LINK_DL2_FE] = {
+ .name = "DL2_FE",
+ .stream_name = "DL2 Playback",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &mt8195_playback_ops,
+ SND_SOC_DAILINK_REG(DL2_FE),
+ },
+ [DAI_LINK_DL3_FE] = {
+ .name = "DL3_FE",
+ .stream_name = "DL3 Playback",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &mt8195_playback_ops,
+ SND_SOC_DAILINK_REG(DL3_FE),
+ },
+ [DAI_LINK_DL6_FE] = {
+ .name = "DL6_FE",
+ .stream_name = "DL6 Playback",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &mt8195_playback_ops,
+ SND_SOC_DAILINK_REG(DL6_FE),
+ },
+ [DAI_LINK_DL7_FE] = {
+ .name = "DL7_FE",
+ .stream_name = "DL7 Playback",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE,
+ },
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(DL7_FE),
+ },
+ [DAI_LINK_DL8_FE] = {
+ .name = "DL8_FE",
+ .stream_name = "DL8 Playback",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &mt8195_playback_ops,
+ SND_SOC_DAILINK_REG(DL8_FE),
+ },
+ [DAI_LINK_DL10_FE] = {
+ .name = "DL10_FE",
+ .stream_name = "DL10 Playback",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &mt8195_hdmitx_dptx_playback_ops,
+ SND_SOC_DAILINK_REG(DL10_FE),
+ },
+ [DAI_LINK_DL11_FE] = {
+ .name = "DL11_FE",
+ .stream_name = "DL11 Playback",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &mt8195_playback_ops,
+ SND_SOC_DAILINK_REG(DL11_FE),
+ },
+ [DAI_LINK_UL1_FE] = {
+ .name = "UL1_FE",
+ .stream_name = "UL1 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(UL1_FE),
+ },
+ [DAI_LINK_UL2_FE] = {
+ .name = "UL2_FE",
+ .stream_name = "UL2 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ops = &mt8195_capture_ops,
+ SND_SOC_DAILINK_REG(UL2_FE),
+ },
+ [DAI_LINK_UL3_FE] = {
+ .name = "UL3_FE",
+ .stream_name = "UL3 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ops = &mt8195_capture_ops,
+ SND_SOC_DAILINK_REG(UL3_FE),
+ },
+ [DAI_LINK_UL4_FE] = {
+ .name = "UL4_FE",
+ .stream_name = "UL4 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ops = &mt8195_capture_ops,
+ SND_SOC_DAILINK_REG(UL4_FE),
+ },
+ [DAI_LINK_UL5_FE] = {
+ .name = "UL5_FE",
+ .stream_name = "UL5 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ops = &mt8195_capture_ops,
+ SND_SOC_DAILINK_REG(UL5_FE),
+ },
+ [DAI_LINK_UL6_FE] = {
+ .name = "UL6_FE",
+ .stream_name = "UL6 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(UL6_FE),
+ },
+ [DAI_LINK_UL8_FE] = {
+ .name = "UL8_FE",
+ .stream_name = "UL8 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ops = &mt8195_capture_ops,
+ SND_SOC_DAILINK_REG(UL8_FE),
+ },
+ [DAI_LINK_UL9_FE] = {
+ .name = "UL9_FE",
+ .stream_name = "UL9 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ops = &mt8195_capture_ops,
+ SND_SOC_DAILINK_REG(UL9_FE),
+ },
+ [DAI_LINK_UL10_FE] = {
+ .name = "UL10_FE",
+ .stream_name = "UL10 Capture",
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST,
+ },
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .ops = &mt8195_capture_ops,
+ SND_SOC_DAILINK_REG(UL10_FE),
+ },
+ /* BE */
+ [DAI_LINK_DL_SRC_BE] = {
+ .name = "DL_SRC_BE",
+ .init = mt8195_mt6359_init,
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(DL_SRC_BE),
+ },
+ [DAI_LINK_DPTX_BE] = {
+ .name = "DPTX_BE",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .ops = &mt8195_dptx_ops,
+ .be_hw_params_fixup = mt8195_hdmitx_dptx_hw_params_fixup,
+ SND_SOC_DAILINK_REG(DPTX_BE),
+ },
+ [DAI_LINK_ETDM1_IN_BE] = {
+ .name = "ETDM1_IN_BE",
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(ETDM1_IN_BE),
+ },
+ [DAI_LINK_ETDM2_IN_BE] = {
+ .name = "ETDM2_IN_BE",
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .dpcm_capture = 1,
+ .init = mt8195_rt5682_init,
+ .ops = &mt8195_rt5682_etdm_ops,
+ .be_hw_params_fixup = mt8195_etdm_hw_params_fixup,
+ SND_SOC_DAILINK_REG(ETDM2_IN_BE),
+ },
+ [DAI_LINK_ETDM1_OUT_BE] = {
+ .name = "ETDM1_OUT_BE",
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .dpcm_playback = 1,
+ .ops = &mt8195_rt5682_etdm_ops,
+ .be_hw_params_fixup = mt8195_etdm_hw_params_fixup,
+ SND_SOC_DAILINK_REG(ETDM1_OUT_BE),
+ },
+ [DAI_LINK_ETDM2_OUT_BE] = {
+ .name = "ETDM2_OUT_BE",
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .dpcm_playback = 1,
+ SND_SOC_DAILINK_REG(ETDM2_OUT_BE),
+ },
+ [DAI_LINK_ETDM3_OUT_BE] = {
+ .name = "ETDM3_OUT_BE",
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .dpcm_playback = 1,
+ .be_hw_params_fixup = mt8195_hdmitx_dptx_hw_params_fixup,
+ SND_SOC_DAILINK_REG(ETDM3_OUT_BE),
+ },
+ [DAI_LINK_PCM1_BE] = {
+ .name = "PCM1_BE",
+ .no_pcm = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(PCM1_BE),
+ },
+ [DAI_LINK_UL_SRC1_BE] = {
+ .name = "UL_SRC1_BE",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(UL_SRC1_BE),
+ },
+ [DAI_LINK_UL_SRC2_BE] = {
+ .name = "UL_SRC2_BE",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ SND_SOC_DAILINK_REG(UL_SRC2_BE),
+ },
+};
+
+static struct snd_soc_card mt8195_mt6359_rt1019_rt5682_soc_card = {
+ .name = "mt8195_r1019_5682",
+ .owner = THIS_MODULE,
+ .dai_link = mt8195_mt6359_rt1019_rt5682_dai_links,
+ .num_links = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_dai_links),
+ .controls = mt8195_mt6359_rt1019_rt5682_controls,
+ .num_controls = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_controls),
+ .dapm_widgets = mt8195_mt6359_rt1019_rt5682_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_widgets),
+ .dapm_routes = mt8195_mt6359_rt1019_rt5682_routes,
+ .num_dapm_routes = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_routes),
+};
+
+static int mt8195_mt6359_rt1019_rt5682_dev_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &mt8195_mt6359_rt1019_rt5682_soc_card;
+ struct device_node *platform_node;
+ struct snd_soc_dai_link *dai_link;
+ struct mt8195_mt6359_rt1019_rt5682_priv *priv = NULL;
+ int ret, i;
+
+ card->dev = &pdev->dev;
+
+ platform_node = of_parse_phandle(pdev->dev.of_node,
+ "mediatek,platform", 0);
+ if (!platform_node) {
+ dev_dbg(&pdev->dev, "Property 'platform' missing or invalid\n");
+ return -EINVAL;
+ }
+
+ for_each_card_prelinks(card, i, dai_link) {
+ if (!dai_link->platforms->name)
+ dai_link->platforms->of_node = platform_node;
+
+ if (strcmp(dai_link->name, "DPTX_BE") == 0) {
+ dai_link->codecs->of_node =
+ of_parse_phandle(pdev->dev.of_node,
+ "mediatek,dptx-codec", 0);
+ if (!dai_link->codecs->of_node) {
+ dev_err(&pdev->dev, "Property 'dptx-codec' missing or invalid\n");
+ return -EINVAL;
+ }
+
+ dai_link->codecs->name = NULL;
+ dai_link->codecs->dai_name = "i2s-hifi";
+ dai_link->init = mt8195_dptx_codec_init;
+ }
+
+ if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) {
+ dai_link->codecs->of_node =
+ of_parse_phandle(pdev->dev.of_node,
+ "mediatek,hdmi-codec", 0);
+ if (!dai_link->codecs->of_node) {
+ dev_err(&pdev->dev, "Property 'hdmi-codec' missing or invalid\n");
+ return -EINVAL;
+ }
+
+ dai_link->codecs->name = NULL;
+ dai_link->codecs->dai_name = "i2s-hifi";
+ dai_link->init = mt8195_hdmi_codec_init;
+ }
+ }
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ snd_soc_card_set_drvdata(card, priv);
+
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret)
+ dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+ __func__, ret);
+ return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id mt8195_mt6359_rt1019_rt5682_dt_match[] = {
+ {.compatible = "mediatek,mt8195_mt6359_rt1019_rt5682",},
+ {}
+};
+#endif
+
+static const struct dev_pm_ops mt8195_mt6359_rt1019_rt5682_pm_ops = {
+ .poweroff = snd_soc_poweroff,
+ .restore = snd_soc_resume,
+};
+
+static struct platform_driver mt8195_mt6359_rt1019_rt5682_driver = {
+ .driver = {
+ .name = "mt8195_mt6359_rt1019_rt5682",
+#ifdef CONFIG_OF
+ .of_match_table = mt8195_mt6359_rt1019_rt5682_dt_match,
+#endif
+ .pm = &mt8195_mt6359_rt1019_rt5682_pm_ops,
+ },
+ .probe = mt8195_mt6359_rt1019_rt5682_dev_probe,
+};
+
+module_platform_driver(mt8195_mt6359_rt1019_rt5682_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8195-MT6359-RT1019-RT5682 ALSA SoC machine driver");
+MODULE_AUTHOR("Trevor Wu <trevor.wu@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("mt8195_mt6359_rt1019_rt5682 soc card");
diff --git a/sound/soc/mediatek/mt8195/mt8195-reg.h b/sound/soc/mediatek/mt8195/mt8195-reg.h
new file mode 100644
index 000000000000..d06f9cf85a4e
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-reg.h
@@ -0,0 +1,2796 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8195-reg.h -- Mediatek 8195 audio driver reg definition
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ * Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#ifndef _MT8195_REG_H_
+#define _MT8195_REG_H_
+
+#define AFE_SRAM_BASE (0x10880000)
+#define AFE_SRAM_SIZE (0x10000)
+
+#define AUDIO_TOP_CON0 (0x0000)
+#define AUDIO_TOP_CON1 (0x0004)
+#define AUDIO_TOP_CON2 (0x0008)
+#define AUDIO_TOP_CON3 (0x000c)
+#define AUDIO_TOP_CON4 (0x0010)
+#define AUDIO_TOP_CON5 (0x0014)
+#define AUDIO_TOP_CON6 (0x0018)
+#define AFE_MAS_HADDR_MSB (0x0020)
+#define PWR1_ASM_CON1 (0x0108)
+#define ASYS_IRQ_CONFIG (0x0110)
+#define ASYS_IRQ1_CON (0x0114)
+#define ASYS_IRQ2_CON (0x0118)
+#define ASYS_IRQ3_CON (0x011c)
+#define ASYS_IRQ4_CON (0x0120)
+#define ASYS_IRQ5_CON (0x0124)
+#define ASYS_IRQ6_CON (0x0128)
+#define ASYS_IRQ7_CON (0x012c)
+#define ASYS_IRQ8_CON (0x0130)
+#define ASYS_IRQ9_CON (0x0134)
+#define ASYS_IRQ10_CON (0x0138)
+#define ASYS_IRQ11_CON (0x013c)
+#define ASYS_IRQ12_CON (0x0140)
+#define ASYS_IRQ13_CON (0x0144)
+#define ASYS_IRQ14_CON (0x0148)
+#define ASYS_IRQ15_CON (0x014c)
+#define ASYS_IRQ16_CON (0x0150)
+#define ASYS_IRQ_CLR (0x0154)
+#define ASYS_IRQ_STATUS (0x0158)
+#define ASYS_IRQ_MON1 (0x015c)
+#define ASYS_IRQ_MON2 (0x0160)
+#define AFE_IRQ1_CON (0x0164)
+#define AFE_IRQ2_CON (0x0168)
+#define AFE_IRQ3_CON (0x016c)
+#define AFE_IRQ_MCU_CLR (0x0170)
+#define AFE_IRQ_STATUS (0x0174)
+#define AFE_IRQ_MASK (0x0178)
+#define ASYS_IRQ_MASK (0x017c)
+#define AFE_IRQ3_CON_MON (0x01b0)
+#define AFE_IRQ_MCU_MON2 (0x01b4)
+#define AFE_IRQ8_CON (0x01b8)
+#define AFE_IRQ9_CON (0x01bc)
+#define AFE_IRQ10_CON (0x01c0)
+#define AFE_IRQ9_CON_MON (0x01c4)
+#define ADSP_IRQ_MASK (0x01c8)
+#define ADSP_IRQ_STATUS (0x01cc)
+#define AFE_SINEGEN_CON0 (0x01f0)
+#define AFE_SINEGEN_CON1 (0x01f4)
+#define AFE_SINEGEN_CON2 (0x01f8)
+#define AFE_SINEGEN_CON3 (0x01fc)
+#define AFE_SPDIF_OUT_CON0 (0x0380)
+#define AFE_TDMOUT_CONN0 (0x0390)
+#define PWR1_ASM_CON2 (0x03b0)
+#define PWR1_ASM_CON3 (0x03b4)
+#define PWR1_ASM_CON4 (0x03b8)
+#define AFE_APLL_TUNER_CFG (0x03f8)
+#define AFE_APLL_TUNER_CFG1 (0x03fc)
+#define AUDIO_TOP_STA0 (0x0400)
+#define AUDIO_TOP_STA1 (0x0404)
+#define AFE_GAIN1_CON0 (0x0410)
+#define AFE_GAIN1_CON1 (0x0414)
+#define AFE_GAIN1_CON2 (0x0418)
+#define AFE_GAIN1_CON3 (0x041c)
+#define AFE_GAIN1_CUR (0x0424)
+#define AFE_GAIN2_CON0 (0x0428)
+#define AFE_GAIN2_CON1 (0x042c)
+#define AFE_GAIN2_CON2 (0x0430)
+#define AFE_GAIN2_CON3 (0x0434)
+#define AFE_GAIN2_CUR (0x043c)
+#define AFE_IEC_CFG (0x0480)
+#define AFE_IEC_NSNUM (0x0484)
+#define AFE_IEC_BURST_INFO (0x0488)
+#define AFE_IEC_BURST_LEN (0x048c)
+#define AFE_IEC_NSADR (0x0490)
+#define AFE_IEC_CHL_STAT0 (0x04a0)
+#define AFE_IEC_CHL_STAT1 (0x04a4)
+#define AFE_IEC_CHR_STAT0 (0x04a8)
+#define AFE_IEC_CHR_STAT1 (0x04ac)
+#define AFE_SPDIFIN_CFG0 (0x0500)
+#define AFE_SPDIFIN_CFG1 (0x0504)
+#define AFE_SPDIFIN_CHSTS1 (0x0508)
+#define AFE_SPDIFIN_CHSTS2 (0x050c)
+#define AFE_SPDIFIN_CHSTS3 (0x0510)
+#define AFE_SPDIFIN_CHSTS4 (0x0514)
+#define AFE_SPDIFIN_CHSTS5 (0x0518)
+#define AFE_SPDIFIN_CHSTS6 (0x051c)
+#define AFE_SPDIFIN_DEBUG1 (0x0520)
+#define AFE_SPDIFIN_DEBUG2 (0x0524)
+#define AFE_SPDIFIN_DEBUG3 (0x0528)
+#define AFE_SPDIFIN_DEBUG4 (0x052c)
+#define AFE_SPDIFIN_EC (0x0530)
+#define AFE_SPDIFIN_CKLOCK_CFG (0x0534)
+#define AFE_SPDIFIN_BR (0x053c)
+#define AFE_SPDIFIN_BR_DBG1 (0x0540)
+#define AFE_SPDIFIN_CKFBDIV (0x0544)
+#define AFE_SPDIFIN_INT_EXT (0x0548)
+#define AFE_SPDIFIN_INT_EXT2 (0x054c)
+#define SPDIFIN_FREQ_INFO (0x0550)
+#define SPDIFIN_FREQ_INFO_2 (0x0554)
+#define SPDIFIN_FREQ_INFO_3 (0x0558)
+#define SPDIFIN_FREQ_STATUS (0x055c)
+#define SPDIFIN_USERCODE1 (0x0560)
+#define SPDIFIN_USERCODE2 (0x0564)
+#define SPDIFIN_USERCODE3 (0x0568)
+#define SPDIFIN_USERCODE4 (0x056c)
+#define SPDIFIN_USERCODE5 (0x0570)
+#define SPDIFIN_USERCODE6 (0x0574)
+#define SPDIFIN_USERCODE7 (0x0578)
+#define SPDIFIN_USERCODE8 (0x057c)
+#define SPDIFIN_USERCODE9 (0x0580)
+#define SPDIFIN_USERCODE10 (0x0584)
+#define SPDIFIN_USERCODE11 (0x0588)
+#define SPDIFIN_USERCODE12 (0x058c)
+#define AFE_SPDIFIN_APLL_TUNER_CFG (0x0594)
+#define AFE_SPDIFIN_APLL_TUNER_CFG1 (0x0598)
+#define ASYS_TOP_CON (0x0600)
+#define AFE_LINEIN_APLL_TUNER_CFG (0x0610)
+#define AFE_LINEIN_APLL_TUNER_MON (0x0614)
+#define AFE_EARC_APLL_TUNER_CFG (0x0618)
+#define AFE_EARC_APLL_TUNER_MON (0x061c)
+#define PWR2_TOP_CON0 (0x0634)
+#define PWR2_TOP_CON1 (0x0638)
+#define PCM_INTF_CON1 (0x063c)
+#define PCM_INTF_CON2 (0x0640)
+#define AFE_CM0_CON (0x0660)
+#define AFE_CM1_CON (0x0664)
+#define AFE_CM2_CON (0x0668)
+#define AFE_CM0_MON (0x0670)
+#define AFE_CM1_MON (0x0674)
+#define AFE_CM2_MON (0x0678)
+#define AFE_MPHONE_MULTI_CON0 (0x06a4)
+#define AFE_MPHONE_MULTI_CON1 (0x06a8)
+#define AFE_MPHONE_MULTI_CON2 (0x06ac)
+#define AFE_MPHONE_MULTI_MON (0x06b0)
+#define AFE_MPHONE_MULTI_DET_REG_CON0 (0x06b4)
+#define AFE_MPHONE_MULTI_DET_REG_CON1 (0x06b8)
+#define AFE_MPHONE_MULTI_DET_REG_CON2 (0x06bc)
+#define AFE_MPHONE_MULTI_DET_REG_CON3 (0x06c0)
+#define AFE_MPHONE_MULTI_DET_MON0 (0x06c4)
+#define AFE_MPHONE_MULTI_DET_MON1 (0x06c8)
+#define AFE_MPHONE_MULTI_DET_MON2 (0x06d0)
+#define AFE_MPHONE_MULTI2_CON0 (0x06d4)
+#define AFE_MPHONE_MULTI2_CON1 (0x06d8)
+#define AFE_MPHONE_MULTI2_CON2 (0x06dc)
+#define AFE_MPHONE_MULTI2_MON (0x06e0)
+#define AFE_MPHONE_MULTI2_DET_REG_CON0 (0x06e4)
+#define AFE_MPHONE_MULTI2_DET_REG_CON1 (0x06e8)
+#define AFE_MPHONE_MULTI2_DET_REG_CON2 (0x06ec)
+#define AFE_MPHONE_MULTI2_DET_REG_CON3 (0x06f0)
+#define AFE_MPHONE_MULTI2_DET_MON0 (0x06f4)
+#define AFE_MPHONE_MULTI2_DET_MON1 (0x06f8)
+#define AFE_MPHONE_MULTI2_DET_MON2 (0x06fc)
+#define AFE_ADDA_IIR_COEF_02_01 (0x0700)
+#define AFE_ADDA_IIR_COEF_04_03 (0x0704)
+#define AFE_ADDA_IIR_COEF_06_05 (0x0708)
+#define AFE_ADDA_IIR_COEF_08_07 (0x070c)
+#define AFE_ADDA_IIR_COEF_10_09 (0x0710)
+#define AFE_ADDA_ULCF_CFG_02_01 (0x0714)
+#define AFE_ADDA_ULCF_CFG_04_03 (0x0718)
+#define AFE_ADDA_ULCF_CFG_06_05 (0x071c)
+#define AFE_ADDA_ULCF_CFG_08_07 (0x0720)
+#define AFE_ADDA_ULCF_CFG_10_09 (0x0724)
+#define AFE_ADDA_ULCF_CFG_12_11 (0x0728)
+#define AFE_ADDA_ULCF_CFG_14_13 (0x072c)
+#define AFE_ADDA_ULCF_CFG_16_15 (0x0730)
+#define AFE_ADDA_ULCF_CFG_18_17 (0x0734)
+#define AFE_ADDA_ULCF_CFG_20_19 (0x0738)
+#define AFE_ADDA_ULCF_CFG_22_21 (0x073c)
+#define AFE_ADDA_ULCF_CFG_24_23 (0x0740)
+#define AFE_ADDA_ULCF_CFG_26_25 (0x0744)
+#define AFE_ADDA_ULCF_CFG_28_27 (0x0748)
+#define AFE_ADDA_ULCF_CFG_30_29 (0x074c)
+#define AFE_ADDA6_IIR_COEF_02_01 (0x0750)
+#define AFE_ADDA6_IIR_COEF_04_03 (0x0754)
+#define AFE_ADDA6_IIR_COEF_06_05 (0x0758)
+#define AFE_ADDA6_IIR_COEF_08_07 (0x075c)
+#define AFE_ADDA6_IIR_COEF_10_09 (0x0760)
+#define AFE_ADDA6_ULCF_CFG_02_01 (0x0764)
+#define AFE_ADDA6_ULCF_CFG_04_03 (0x0768)
+#define AFE_ADDA6_ULCF_CFG_06_05 (0x076c)
+#define AFE_ADDA6_ULCF_CFG_08_07 (0x0770)
+#define AFE_ADDA6_ULCF_CFG_10_09 (0x0774)
+#define AFE_ADDA6_ULCF_CFG_12_11 (0x0778)
+#define AFE_ADDA6_ULCF_CFG_14_13 (0x077c)
+#define AFE_ADDA6_ULCF_CFG_16_15 (0x0780)
+#define AFE_ADDA6_ULCF_CFG_18_17 (0x0784)
+#define AFE_ADDA6_ULCF_CFG_20_19 (0x0788)
+#define AFE_ADDA6_ULCF_CFG_22_21 (0x078c)
+#define AFE_ADDA6_ULCF_CFG_24_23 (0x0790)
+#define AFE_ADDA6_ULCF_CFG_26_25 (0x0794)
+#define AFE_ADDA6_ULCF_CFG_28_27 (0x0798)
+#define AFE_ADDA6_ULCF_CFG_30_29 (0x079c)
+#define AFE_ADDA_MTKAIF_CFG0 (0x07a0)
+#define AFE_ADDA_MTKAIF_SYNCWORD_CFG (0x07a8)
+#define AFE_ADDA_MTKAIF_RX_CFG0 (0x07b4)
+#define AFE_ADDA_MTKAIF_RX_CFG1 (0x07b8)
+#define AFE_ADDA_MTKAIF_RX_CFG2 (0x07bc)
+#define AFE_ADDA_MTKAIF_MON0 (0x07c8)
+#define AFE_ADDA_MTKAIF_MON1 (0x07cc)
+#define AFE_AUD_PAD_TOP (0x07d4)
+#define AFE_ADDA6_MTKAIF_MON0 (0x07d8)
+#define AFE_ADDA6_MTKAIF_MON1 (0x07dc)
+#define AFE_ADDA6_MTKAIF_CFG0 (0x07e0)
+#define AFE_ADDA6_MTKAIF_RX_CFG0 (0x07e4)
+#define AFE_ADDA6_MTKAIF_RX_CFG1 (0x07e8)
+#define AFE_ADDA6_MTKAIF_RX_CFG2 (0x07ec)
+#define AFE_ADDA6_TOP_CON0 (0x07f0)
+#define AFE_ADDA6_UL_SRC_CON0 (0x07f4)
+#define AFE_ADDA6_UL_SRC_CON1 (0x07f8)
+#define AFE_ADDA6_SRC_DEBUG (0x0800)
+#define AFE_ADDA6_SRC_DEBUG_MON0 (0x0804)
+#define AFE_ADDA6_UL_SRC_MON0 (0x0818)
+#define AFE_ADDA6_UL_SRC_MON1 (0x081c)
+#define AFE_CONN0_5 (0x0830)
+#define AFE_CONN1_5 (0x0834)
+#define AFE_CONN2_5 (0x0838)
+#define AFE_CONN3_5 (0x083c)
+#define AFE_CONN4_5 (0x0840)
+#define AFE_CONN5_5 (0x0844)
+#define AFE_CONN6_5 (0x0848)
+#define AFE_CONN7_5 (0x084c)
+#define AFE_CONN8_5 (0x0850)
+#define AFE_CONN9_5 (0x0854)
+#define AFE_CONN10_5 (0x0858)
+#define AFE_CONN11_5 (0x085c)
+#define AFE_CONN12_5 (0x0860)
+#define AFE_CONN13_5 (0x0864)
+#define AFE_CONN14_5 (0x0868)
+#define AFE_CONN15_5 (0x086c)
+#define AFE_CONN16_5 (0x0870)
+#define AFE_CONN17_5 (0x0874)
+#define AFE_CONN18_5 (0x0878)
+#define AFE_CONN19_5 (0x087c)
+#define AFE_CONN20_5 (0x0880)
+#define AFE_CONN21_5 (0x0884)
+#define AFE_CONN22_5 (0x0888)
+#define AFE_CONN23_5 (0x088c)
+#define AFE_CONN24_5 (0x0890)
+#define AFE_CONN25_5 (0x0894)
+#define AFE_CONN26_5 (0x0898)
+#define AFE_CONN27_5 (0x089c)
+#define AFE_CONN28_5 (0x08a0)
+#define AFE_CONN29_5 (0x08a4)
+#define AFE_CONN30_5 (0x08a8)
+#define AFE_CONN31_5 (0x08ac)
+#define AFE_CONN32_5 (0x08b0)
+#define AFE_CONN33_5 (0x08b4)
+#define AFE_CONN34_5 (0x08b8)
+#define AFE_CONN35_5 (0x08bc)
+#define AFE_CONN36_5 (0x08c0)
+#define AFE_CONN37_5 (0x08c4)
+#define AFE_CONN38_5 (0x08c8)
+#define AFE_CONN39_5 (0x08cc)
+#define AFE_CONN40_5 (0x08d0)
+#define AFE_CONN41_5 (0x08d4)
+#define AFE_CONN42_5 (0x08d8)
+#define AFE_CONN43_5 (0x08dc)
+#define AFE_CONN44_5 (0x08e0)
+#define AFE_CONN45_5 (0x08e4)
+#define AFE_CONN46_5 (0x08e8)
+#define AFE_CONN47_5 (0x08ec)
+#define AFE_CONN48_5 (0x08f0)
+#define AFE_CONN49_5 (0x08f4)
+#define AFE_CONN50_5 (0x08f8)
+#define AFE_CONN51_5 (0x08fc)
+#define AFE_CONN52_5 (0x0900)
+#define AFE_CONN53_5 (0x0904)
+#define AFE_CONN54_5 (0x0908)
+#define AFE_CONN55_5 (0x090c)
+#define AFE_CONN56_5 (0x0910)
+#define AFE_CONN57_5 (0x0914)
+#define AFE_CONN58_5 (0x0918)
+#define AFE_CONN59_5 (0x091c)
+#define AFE_CONN60_5 (0x0920)
+#define AFE_CONN61_5 (0x0924)
+#define AFE_CONN62_5 (0x0928)
+#define AFE_CONN63_5 (0x092c)
+#define AFE_CONN64_5 (0x0930)
+#define AFE_CONN65_5 (0x0934)
+#define AFE_CONN66_5 (0x0938)
+#define AFE_CONN67_5 (0x093c)
+#define AFE_CONN68_5 (0x0940)
+#define AFE_CONN69_5 (0x0944)
+#define AFE_CONN70_5 (0x0948)
+#define AFE_CONN71_5 (0x094c)
+#define AFE_CONN72_5 (0x0950)
+#define AFE_CONN73_5 (0x0954)
+#define AFE_CONN74_5 (0x0958)
+#define AFE_CONN75_5 (0x095c)
+#define AFE_CONN76_5 (0x0960)
+#define AFE_CONN77_5 (0x0964)
+#define AFE_CONN78_5 (0x0968)
+#define AFE_CONN79_5 (0x096c)
+#define AFE_CONN80_5 (0x0970)
+#define AFE_CONN81_5 (0x0974)
+#define AFE_CONN82_5 (0x0978)
+#define AFE_CONN83_5 (0x097c)
+#define AFE_CONN84_5 (0x0980)
+#define AFE_CONN85_5 (0x0984)
+#define AFE_CONN86_5 (0x0988)
+#define AFE_CONN87_5 (0x098c)
+#define AFE_CONN88_5 (0x0990)
+#define AFE_CONN89_5 (0x0994)
+#define AFE_CONN90_5 (0x0998)
+#define AFE_CONN91_5 (0x099c)
+#define AFE_CONN92_5 (0x09a0)
+#define AFE_CONN93_5 (0x09a4)
+#define AFE_CONN94_5 (0x09a8)
+#define AFE_CONN95_5 (0x09ac)
+#define AFE_CONN96_5 (0x09b0)
+#define AFE_CONN97_5 (0x09b4)
+#define AFE_CONN98_5 (0x09b8)
+#define AFE_CONN99_5 (0x09bc)
+#define AFE_CONN100_5 (0x09c0)
+#define AFE_CONN101_5 (0x09c4)
+#define AFE_CONN102_5 (0x09c8)
+#define AFE_CONN103_5 (0x09cc)
+#define AFE_CONN104_5 (0x09d0)
+#define AFE_CONN105_5 (0x09d4)
+#define AFE_CONN106_5 (0x09d8)
+#define AFE_CONN107_5 (0x09dc)
+#define AFE_CONN108_5 (0x09e0)
+#define AFE_CONN109_5 (0x09e4)
+#define AFE_CONN110_5 (0x09e8)
+#define AFE_CONN111_5 (0x09ec)
+#define AFE_CONN112_5 (0x09f0)
+#define AFE_CONN113_5 (0x09f4)
+#define AFE_CONN114_5 (0x09f8)
+#define AFE_CONN115_5 (0x09fc)
+#define AFE_CONN116_5 (0x0a00)
+#define AFE_CONN117_5 (0x0a04)
+#define AFE_CONN118_5 (0x0a08)
+#define AFE_CONN119_5 (0x0a0c)
+#define AFE_CONN120_5 (0x0a10)
+#define AFE_CONN121_5 (0x0a14)
+#define AFE_CONN122_5 (0x0a18)
+#define AFE_CONN123_5 (0x0a1c)
+#define AFE_CONN124_5 (0x0a20)
+#define AFE_CONN125_5 (0x0a24)
+#define AFE_CONN126_5 (0x0a28)
+#define AFE_CONN127_5 (0x0a2c)
+#define AFE_CONN128_5 (0x0a30)
+#define AFE_CONN129_5 (0x0a34)
+#define AFE_CONN130_5 (0x0a38)
+#define AFE_CONN131_5 (0x0a3c)
+#define AFE_CONN132_5 (0x0a40)
+#define AFE_CONN133_5 (0x0a44)
+#define AFE_CONN134_5 (0x0a48)
+#define AFE_CONN135_5 (0x0a4c)
+#define AFE_CONN136_5 (0x0a50)
+#define AFE_CONN137_5 (0x0a54)
+#define AFE_CONN138_5 (0x0a58)
+#define AFE_CONN139_5 (0x0a5c)
+#define AFE_CONN_RS_5 (0x0a60)
+#define AFE_CONN_DI_5 (0x0a64)
+#define AFE_CONN_16BIT_5 (0x0a68)
+#define AFE_CONN_24BIT_5 (0x0a6c)
+#define AFE_ASRC11_NEW_CON0 (0x0d80)
+#define AFE_ASRC11_NEW_CON1 (0x0d84)
+#define AFE_ASRC11_NEW_CON2 (0x0d88)
+#define AFE_ASRC11_NEW_CON3 (0x0d8c)
+#define AFE_ASRC11_NEW_CON4 (0x0d90)
+#define AFE_ASRC11_NEW_CON5 (0x0d94)
+#define AFE_ASRC11_NEW_CON6 (0x0d98)
+#define AFE_ASRC11_NEW_CON7 (0x0d9c)
+#define AFE_ASRC11_NEW_CON8 (0x0da0)
+#define AFE_ASRC11_NEW_CON9 (0x0da4)
+#define AFE_ASRC11_NEW_CON10 (0x0da8)
+#define AFE_ASRC11_NEW_CON11 (0x0dac)
+#define AFE_ASRC11_NEW_CON13 (0x0db4)
+#define AFE_ASRC11_NEW_CON14 (0x0db8)
+#define AFE_ASRC12_NEW_CON0 (0x0dc0)
+#define AFE_ASRC12_NEW_CON1 (0x0dc4)
+#define AFE_ASRC12_NEW_CON2 (0x0dc8)
+#define AFE_ASRC12_NEW_CON3 (0x0dcc)
+#define AFE_ASRC12_NEW_CON4 (0x0dd0)
+#define AFE_ASRC12_NEW_CON5 (0x0dd4)
+#define AFE_ASRC12_NEW_CON6 (0x0dd8)
+#define AFE_ASRC12_NEW_CON7 (0x0ddc)
+#define AFE_ASRC12_NEW_CON8 (0x0de0)
+#define AFE_ASRC12_NEW_CON9 (0x0de4)
+#define AFE_ASRC12_NEW_CON10 (0x0de8)
+#define AFE_ASRC12_NEW_CON11 (0x0dec)
+#define AFE_ASRC12_NEW_CON13 (0x0df4)
+#define AFE_ASRC12_NEW_CON14 (0x0df8)
+#define AFE_LRCK_CNT (0x1018)
+#define AFE_DAC_CON0 (0x1200)
+#define AFE_DAC_CON1 (0x1204)
+#define AFE_DAC_CON2 (0x1208)
+#define AFE_DAC_MON0 (0x1218)
+#define AFE_DL2_BASE (0x1250)
+#define AFE_DL2_CUR (0x1254)
+#define AFE_DL2_END (0x1258)
+#define AFE_DL2_CON0 (0x125c)
+#define AFE_DL3_BASE (0x1260)
+#define AFE_DL3_CUR (0x1264)
+#define AFE_DL3_END (0x1268)
+#define AFE_DL3_CON0 (0x126c)
+#define AFE_DL6_BASE (0x1290)
+#define AFE_DL6_CUR (0x1294)
+#define AFE_DL6_END (0x1298)
+#define AFE_DL6_CON0 (0x129c)
+#define AFE_DL7_BASE (0x12a0)
+#define AFE_DL7_CUR (0x12a4)
+#define AFE_DL7_END (0x12a8)
+#define AFE_DL7_CON0 (0x12ac)
+#define AFE_DL8_BASE (0x12b0)
+#define AFE_DL8_CUR (0x12b4)
+#define AFE_DL8_END (0x12b8)
+#define AFE_DL8_CON0 (0x12bc)
+#define AFE_DL10_BASE (0x12d0)
+#define AFE_DL10_CUR (0x12d4)
+#define AFE_DL10_END (0x12d8)
+#define AFE_DL10_CON0 (0x12dc)
+#define AFE_DL11_BASE (0x12e0)
+#define AFE_DL11_CUR (0x12e4)
+#define AFE_DL11_END (0x12e8)
+#define AFE_DL11_CON0 (0x12ec)
+#define AFE_UL1_BASE (0x1300)
+#define AFE_UL1_CUR (0x1304)
+#define AFE_UL1_END (0x1308)
+#define AFE_UL1_CON0 (0x130c)
+#define AFE_UL2_BASE (0x1310)
+#define AFE_UL2_CUR (0x1314)
+#define AFE_UL2_END (0x1318)
+#define AFE_UL2_CON0 (0x131c)
+#define AFE_UL3_BASE (0x1320)
+#define AFE_UL3_CUR (0x1324)
+#define AFE_UL3_END (0x1328)
+#define AFE_UL3_CON0 (0x132c)
+#define AFE_UL4_BASE (0x1330)
+#define AFE_UL4_CUR (0x1334)
+#define AFE_UL4_END (0x1338)
+#define AFE_UL4_CON0 (0x133c)
+#define AFE_UL5_BASE (0x1340)
+#define AFE_UL5_CUR (0x1344)
+#define AFE_UL5_END (0x1348)
+#define AFE_UL5_CON0 (0x134c)
+#define AFE_UL6_BASE (0x1350)
+#define AFE_UL6_CUR (0x1354)
+#define AFE_UL6_END (0x1358)
+#define AFE_UL6_CON0 (0x135c)
+#define AFE_UL8_BASE (0x1370)
+#define AFE_UL8_CUR (0x1374)
+#define AFE_UL8_END (0x1378)
+#define AFE_UL8_CON0 (0x137c)
+#define AFE_UL9_BASE (0x1380)
+#define AFE_UL9_CUR (0x1384)
+#define AFE_UL9_END (0x1388)
+#define AFE_UL9_CON0 (0x138c)
+#define AFE_UL10_BASE (0x13d0)
+#define AFE_UL10_CUR (0x13d4)
+#define AFE_UL10_END (0x13d8)
+#define AFE_UL10_CON0 (0x13dc)
+#define AFE_DL8_CHK_SUM1 (0x1400)
+#define AFE_DL8_CHK_SUM2 (0x1404)
+#define AFE_DL8_CHK_SUM3 (0x1408)
+#define AFE_DL8_CHK_SUM4 (0x140c)
+#define AFE_DL8_CHK_SUM5 (0x1410)
+#define AFE_DL8_CHK_SUM6 (0x1414)
+#define AFE_DL10_CHK_SUM1 (0x1418)
+#define AFE_DL10_CHK_SUM2 (0x141c)
+#define AFE_DL10_CHK_SUM3 (0x1420)
+#define AFE_DL10_CHK_SUM4 (0x1424)
+#define AFE_DL10_CHK_SUM5 (0x1428)
+#define AFE_DL10_CHK_SUM6 (0x142c)
+#define AFE_DL11_CHK_SUM1 (0x1430)
+#define AFE_DL11_CHK_SUM2 (0x1434)
+#define AFE_DL11_CHK_SUM3 (0x1438)
+#define AFE_DL11_CHK_SUM4 (0x143c)
+#define AFE_DL11_CHK_SUM5 (0x1440)
+#define AFE_DL11_CHK_SUM6 (0x1444)
+#define AFE_UL1_CHK_SUM1 (0x1450)
+#define AFE_UL1_CHK_SUM2 (0x1454)
+#define AFE_UL2_CHK_SUM1 (0x1458)
+#define AFE_UL2_CHK_SUM2 (0x145c)
+#define AFE_UL3_CHK_SUM1 (0x1460)
+#define AFE_UL3_CHK_SUM2 (0x1464)
+#define AFE_UL4_CHK_SUM1 (0x1468)
+#define AFE_UL4_CHK_SUM2 (0x146c)
+#define AFE_UL5_CHK_SUM1 (0x1470)
+#define AFE_UL5_CHK_SUM2 (0x1474)
+#define AFE_UL6_CHK_SUM1 (0x1478)
+#define AFE_UL6_CHK_SUM2 (0x147c)
+#define AFE_UL8_CHK_SUM1 (0x1488)
+#define AFE_UL8_CHK_SUM2 (0x148c)
+#define AFE_DL2_CHK_SUM1 (0x14a0)
+#define AFE_DL2_CHK_SUM2 (0x14a4)
+#define AFE_DL3_CHK_SUM1 (0x14b0)
+#define AFE_DL3_CHK_SUM2 (0x14b4)
+#define AFE_DL6_CHK_SUM1 (0x14e0)
+#define AFE_DL6_CHK_SUM2 (0x14e4)
+#define AFE_DL7_CHK_SUM1 (0x14f0)
+#define AFE_DL7_CHK_SUM2 (0x14f4)
+#define AFE_UL9_CHK_SUM1 (0x1528)
+#define AFE_UL9_CHK_SUM2 (0x152c)
+#define AFE_BUS_MON1 (0x1540)
+#define UL1_MOD2AGT_CNT_LAT (0x1568)
+#define UL2_MOD2AGT_CNT_LAT (0x156c)
+#define UL3_MOD2AGT_CNT_LAT (0x1570)
+#define UL4_MOD2AGT_CNT_LAT (0x1574)
+#define UL5_MOD2AGT_CNT_LAT (0x1578)
+#define UL6_MOD2AGT_CNT_LAT (0x157c)
+#define UL8_MOD2AGT_CNT_LAT (0x1588)
+#define UL9_MOD2AGT_CNT_LAT (0x158c)
+#define UL10_MOD2AGT_CNT_LAT (0x1590)
+#define AFE_MEMIF_AGENT_FS_CON0 (0x15a0)
+#define AFE_MEMIF_AGENT_FS_CON1 (0x15a4)
+#define AFE_MEMIF_AGENT_FS_CON2 (0x15a8)
+#define AFE_MEMIF_AGENT_FS_CON3 (0x15ac)
+#define AFE_MEMIF_BURST_CFG (0x1600)
+#define AFE_MEMIF_BUF_FULL_MON (0x1610)
+#define AFE_MEMIF_BUF_MON1 (0x161c)
+#define AFE_MEMIF_BUF_MON3 (0x1624)
+#define AFE_MEMIF_BUF_MON4 (0x1628)
+#define AFE_MEMIF_BUF_MON5 (0x162c)
+#define AFE_MEMIF_BUF_MON6 (0x1630)
+#define AFE_MEMIF_BUF_MON7 (0x1634)
+#define AFE_MEMIF_BUF_MON8 (0x1638)
+#define AFE_MEMIF_BUF_MON9 (0x163c)
+#define AFE_MEMIF_BUF_MON10 (0x1640)
+#define DL2_AGENT2MODULE_CNT (0x1678)
+#define DL3_AGENT2MODULE_CNT (0x167c)
+#define DL6_AGENT2MODULE_CNT (0x1688)
+#define DL7_AGENT2MODULE_CNT (0x168c)
+#define DL8_AGENT2MODULE_CNT (0x1690)
+#define DL10_AGENT2MODULE_CNT (0x1698)
+#define DL11_AGENT2MODULE_CNT (0x169c)
+#define UL1_MODULE2AGENT_CNT (0x16a0)
+#define UL2_MODULE2AGENT_CNT (0x16a4)
+#define UL3_MODULE2AGENT_CNT (0x16a8)
+#define UL4_MODULE2AGENT_CNT (0x16ac)
+#define UL5_MODULE2AGENT_CNT (0x16b0)
+#define UL6_MODULE2AGENT_CNT (0x16b4)
+#define UL8_MODULE2AGENT_CNT (0x16bc)
+#define UL9_MODULE2AGENT_CNT (0x16c0)
+#define UL10_MODULE2AGENT_CNT (0x16c4)
+#define AFE_SECURE_CON2 (0x1798)
+#define AFE_SECURE_CON1 (0x179c)
+#define AFE_SECURE_CON (0x17a0)
+#define AFE_SRAM_BOUND (0x17a4)
+#define AFE_SE_SECURE_CON (0x17a8)
+#define AFE_SECURE_MASK_LOOPBACK (0x17bc)
+#define AFE_SECURE_SIDEBAND0 (0x1908)
+#define AFE_SECURE_SIDEBAND1 (0x190c)
+#define AFE_SECURE_SIDEBAND2 (0x1910)
+#define AFE_SECURE_SIDEBAND3 (0x1914)
+#define AFE_SECURE_MASK_BASE_ADR_MSB (0x1920)
+#define AFE_SECURE_MASK_END_ADR_MSB (0x1924)
+#define AFE_NORMAL_BASE_ADR_MSB (0x192c)
+#define AFE_NORMAL_END_ADR_MSB (0x1930)
+#define AFE_SECURE_MASK_LOOPBACK0 (0x1940)
+#define AFE_SECURE_MASK_LOOPBACK1 (0x1944)
+#define AFE_SECURE_MASK_LOOPBACK2 (0x1948)
+#define AFE_LOOPBACK_CFG0 (0x1950)
+#define AFE_LOOPBACK_CFG1 (0x1954)
+#define AFE_LOOPBACK_CFG2 (0x1958)
+#define AFE_DMIC0_UL_SRC_CON0 (0x1a00)
+#define AFE_DMIC0_UL_SRC_CON1 (0x1a04)
+#define AFE_DMIC0_SRC_DEBUG (0x1a08)
+#define AFE_DMIC0_SRC_DEBUG_MON0 (0x1a0c)
+#define AFE_DMIC0_UL_SRC_MON0 (0x1a10)
+#define AFE_DMIC0_UL_SRC_MON1 (0x1a14)
+#define AFE_DMIC0_IIR_COEF_02_01 (0x1a18)
+#define AFE_DMIC0_IIR_COEF_04_03 (0x1a1c)
+#define AFE_DMIC0_IIR_COEF_06_05 (0x1a20)
+#define AFE_DMIC0_IIR_COEF_08_07 (0x1a24)
+#define AFE_DMIC0_IIR_COEF_10_09 (0x1a28)
+#define AFE_DMIC1_UL_SRC_CON0 (0x1a68)
+#define AFE_DMIC1_UL_SRC_CON1 (0x1a6c)
+#define AFE_DMIC1_SRC_DEBUG (0x1a70)
+#define AFE_DMIC1_SRC_DEBUG_MON0 (0x1a74)
+#define AFE_DMIC1_UL_SRC_MON0 (0x1a78)
+#define AFE_DMIC1_UL_SRC_MON1 (0x1a7c)
+#define AFE_DMIC1_IIR_COEF_02_01 (0x1a80)
+#define AFE_DMIC1_IIR_COEF_04_03 (0x1a84)
+#define AFE_DMIC1_IIR_COEF_06_05 (0x1a88)
+#define AFE_DMIC1_IIR_COEF_08_07 (0x1a8c)
+#define AFE_DMIC1_IIR_COEF_10_09 (0x1a90)
+#define AFE_DMIC2_UL_SRC_CON0 (0x1ad0)
+#define AFE_DMIC2_UL_SRC_CON1 (0x1ad4)
+#define AFE_DMIC2_SRC_DEBUG (0x1ad8)
+#define AFE_DMIC2_SRC_DEBUG_MON0 (0x1adc)
+#define AFE_DMIC2_UL_SRC_MON0 (0x1ae0)
+#define AFE_DMIC2_UL_SRC_MON1 (0x1ae4)
+#define AFE_DMIC2_IIR_COEF_02_01 (0x1ae8)
+#define AFE_DMIC2_IIR_COEF_04_03 (0x1aec)
+#define AFE_DMIC2_IIR_COEF_06_05 (0x1af0)
+#define AFE_DMIC2_IIR_COEF_08_07 (0x1af4)
+#define AFE_DMIC2_IIR_COEF_10_09 (0x1af8)
+#define AFE_DMIC3_UL_SRC_CON0 (0x1b38)
+#define AFE_DMIC3_UL_SRC_CON1 (0x1b3c)
+#define AFE_DMIC3_SRC_DEBUG (0x1b40)
+#define AFE_DMIC3_SRC_DEBUG_MON0 (0x1b44)
+#define AFE_DMIC3_UL_SRC_MON0 (0x1b48)
+#define AFE_DMIC3_UL_SRC_MON1 (0x1b4c)
+#define AFE_DMIC3_IIR_COEF_02_01 (0x1b50)
+#define AFE_DMIC3_IIR_COEF_04_03 (0x1b54)
+#define AFE_DMIC3_IIR_COEF_06_05 (0x1b58)
+#define AFE_DMIC3_IIR_COEF_08_07 (0x1b5c)
+#define AFE_DMIC3_IIR_COEF_10_09 (0x1b60)
+#define DMIC_BYPASS_HW_GAIN (0x1bf0)
+#define DMIC_GAIN1_CON0 (0x1c00)
+#define DMIC_GAIN1_CON1 (0x1c04)
+#define DMIC_GAIN1_CON2 (0x1c08)
+#define DMIC_GAIN1_CON3 (0x1c0c)
+#define DMIC_GAIN1_CUR (0x1c10)
+#define DMIC_GAIN2_CON0 (0x1c20)
+#define DMIC_GAIN2_CON1 (0x1c24)
+#define DMIC_GAIN2_CON2 (0x1c28)
+#define DMIC_GAIN2_CON3 (0x1c2c)
+#define DMIC_GAIN2_CUR (0x1c30)
+#define DMIC_GAIN3_CON0 (0x1c40)
+#define DMIC_GAIN3_CON1 (0x1c44)
+#define DMIC_GAIN3_CON2 (0x1c48)
+#define DMIC_GAIN3_CON3 (0x1c4c)
+#define DMIC_GAIN3_CUR (0x1c50)
+#define DMIC_GAIN4_CON0 (0x1c60)
+#define DMIC_GAIN4_CON1 (0x1c64)
+#define DMIC_GAIN4_CON2 (0x1c68)
+#define DMIC_GAIN4_CON3 (0x1c6c)
+#define DMIC_GAIN4_CUR (0x1c70)
+#define ETDM_OUT1_DSD_FADE_CON (0x2260)
+#define ETDM_OUT1_DSD_FADE_CON1 (0x2264)
+#define ETDM_OUT3_DSD_FADE_CON (0x2280)
+#define ETDM_OUT3_DSD_FADE_CON1 (0x2284)
+#define ETDM_IN1_AFIFO_CON (0x2294)
+#define ETDM_IN2_AFIFO_CON (0x2298)
+#define ETDM_IN1_MONITOR (0x22c0)
+#define ETDM_IN2_MONITOR (0x22c4)
+#define ETDM_OUT1_MONITOR (0x22d0)
+#define ETDM_OUT2_MONITOR (0x22d4)
+#define ETDM_OUT3_MONITOR (0x22d8)
+#define ETDM_COWORK_SEC_CON0 (0x22e0)
+#define ETDM_COWORK_SEC_CON1 (0x22e4)
+#define ETDM_COWORK_SEC_CON2 (0x22e8)
+#define ETDM_COWORK_SEC_CON3 (0x22ec)
+#define ETDM_COWORK_CON0 (0x22f0)
+#define ETDM_COWORK_CON1 (0x22f4)
+#define ETDM_COWORK_CON2 (0x22f8)
+#define ETDM_COWORK_CON3 (0x22fc)
+#define ETDM_IN1_CON0 (0x2300)
+#define ETDM_IN1_CON1 (0x2304)
+#define ETDM_IN1_CON2 (0x2308)
+#define ETDM_IN1_CON3 (0x230c)
+#define ETDM_IN1_CON4 (0x2310)
+#define ETDM_IN1_CON5 (0x2314)
+#define ETDM_IN1_CON6 (0x2318)
+#define ETDM_IN1_CON7 (0x231c)
+#define ETDM_IN2_CON0 (0x2320)
+#define ETDM_IN2_CON1 (0x2324)
+#define ETDM_IN2_CON2 (0x2328)
+#define ETDM_IN2_CON3 (0x232c)
+#define ETDM_IN2_CON4 (0x2330)
+#define ETDM_IN2_CON5 (0x2334)
+#define ETDM_IN2_CON6 (0x2338)
+#define ETDM_IN2_CON7 (0x233c)
+#define ETDM_OUT1_CON0 (0x2380)
+#define ETDM_OUT1_CON1 (0x2384)
+#define ETDM_OUT1_CON2 (0x2388)
+#define ETDM_OUT1_CON3 (0x238c)
+#define ETDM_OUT1_CON4 (0x2390)
+#define ETDM_OUT1_CON5 (0x2394)
+#define ETDM_OUT1_CON6 (0x2398)
+#define ETDM_OUT1_CON7 (0x239c)
+#define ETDM_OUT2_CON0 (0x23a0)
+#define ETDM_OUT2_CON1 (0x23a4)
+#define ETDM_OUT2_CON2 (0x23a8)
+#define ETDM_OUT2_CON3 (0x23ac)
+#define ETDM_OUT2_CON4 (0x23b0)
+#define ETDM_OUT2_CON5 (0x23b4)
+#define ETDM_OUT2_CON6 (0x23b8)
+#define ETDM_OUT2_CON7 (0x23bc)
+#define ETDM_OUT3_CON0 (0x23c0)
+#define ETDM_OUT3_CON1 (0x23c4)
+#define ETDM_OUT3_CON2 (0x23c8)
+#define ETDM_OUT3_CON3 (0x23cc)
+#define ETDM_OUT3_CON4 (0x23d0)
+#define ETDM_OUT3_CON5 (0x23d4)
+#define ETDM_OUT3_CON6 (0x23d8)
+#define ETDM_OUT3_CON7 (0x23dc)
+#define ETDM_OUT3_CON8 (0x23e0)
+#define ETDM_OUT1_CON8 (0x23e4)
+#define ETDM_OUT2_CON8 (0x23e8)
+#define GASRC_TIMING_CON0 (0x2414)
+#define GASRC_TIMING_CON1 (0x2418)
+#define GASRC_TIMING_CON2 (0x241c)
+#define GASRC_TIMING_CON3 (0x2420)
+#define GASRC_TIMING_CON4 (0x2424)
+#define GASRC_TIMING_CON5 (0x2428)
+#define GASRC_TIMING_CON6 (0x242c)
+#define GASRC_TIMING_CON7 (0x2430)
+#define A3_A4_TIMING_SEL0 (0x2440)
+#define A3_A4_TIMING_SEL1 (0x2444)
+#define A3_A4_TIMING_SEL2 (0x2448)
+#define A3_A4_TIMING_SEL3 (0x244c)
+#define A3_A4_TIMING_SEL4 (0x2450)
+#define A3_A4_TIMING_SEL5 (0x2454)
+#define A3_A4_TIMING_SEL6 (0x2458)
+#define ASYS_TOP_DEBUG (0x2500)
+#define AFE_DPTX_CON (0x2558)
+#define AFE_DPTX_MON (0x255c)
+#define AFE_ADDA_DL_SRC2_CON0 (0x2d00)
+#define AFE_ADDA_DL_SRC2_CON1 (0x2d04)
+#define AFE_ADDA_TOP_CON0 (0x2d0c)
+#define AFE_ADDA_UL_DL_CON0 (0x2d10)
+#define AFE_ADDA_SRC_DEBUG (0x2d14)
+#define AFE_ADDA_SRC_DEBUG_MON0 (0x2d18)
+#define AFE_ADDA_SRC_DEBUG_MON1 (0x2d20)
+#define AFE_ADDA_PREDIS_CON0 (0x2d24)
+#define AFE_ADDA_PREDIS_CON1 (0x2d28)
+#define AFE_ADDA_PREDIS_CON2 (0x2d2c)
+#define AFE_ADDA_PREDIS_CON3 (0x2d30)
+#define AFE_ADDA_DL_SDM_DCCOMP_CON (0x2d34)
+#define AFE_ADDA_DL_SDM_TEST (0x2d38)
+#define AFE_ADDA_DL_DC_COMP_CFG0 (0x2d3c)
+#define AFE_ADDA_DL_DC_COMP_CFG1 (0x2d40)
+#define AFE_ADDA_DL_SDM_FIFO_MON (0x2d44)
+#define AFE_ADDA_DL_SRC_LCH_MON (0x2d50)
+#define AFE_ADDA_DL_SRC_RCH_MON (0x2d54)
+#define AFE_ADDA_DL_SDM_OUT_MON (0x2d58)
+#define AFE_ADDA_DL_SDM_DITHER_CON (0x2d5c)
+#define AFE_ADDA_DL_SDM_AUTO_RESET_CON (0x2d60)
+#define AFE_ADDA_UL_SRC_CON0 (0x2e3c)
+#define AFE_ADDA_UL_SRC_CON1 (0x2e40)
+#define AFE_CONN0 (0x3000)
+#define AFE_CONN0_1 (0x3004)
+#define AFE_CONN0_2 (0x3008)
+#define AFE_CONN0_3 (0x300c)
+#define AFE_CONN0_4 (0x3010)
+#define AFE_CONN1 (0x3014)
+#define AFE_CONN1_1 (0x3018)
+#define AFE_CONN1_2 (0x301c)
+#define AFE_CONN1_3 (0x3020)
+#define AFE_CONN1_4 (0x3024)
+#define AFE_CONN2 (0x3028)
+#define AFE_CONN2_1 (0x302c)
+#define AFE_CONN2_2 (0x3030)
+#define AFE_CONN2_3 (0x3034)
+#define AFE_CONN2_4 (0x3038)
+#define AFE_CONN3 (0x303c)
+#define AFE_CONN3_1 (0x3040)
+#define AFE_CONN3_2 (0x3044)
+#define AFE_CONN3_3 (0x3048)
+#define AFE_CONN3_4 (0x304c)
+#define AFE_CONN4 (0x3050)
+#define AFE_CONN4_1 (0x3054)
+#define AFE_CONN4_2 (0x3058)
+#define AFE_CONN4_3 (0x305c)
+#define AFE_CONN4_4 (0x3060)
+#define AFE_CONN5 (0x3064)
+#define AFE_CONN5_1 (0x3068)
+#define AFE_CONN5_2 (0x306c)
+#define AFE_CONN5_3 (0x3070)
+#define AFE_CONN5_4 (0x3074)
+#define AFE_CONN6 (0x3078)
+#define AFE_CONN6_1 (0x307c)
+#define AFE_CONN6_2 (0x3080)
+#define AFE_CONN6_3 (0x3084)
+#define AFE_CONN6_4 (0x3088)
+#define AFE_CONN7 (0x308c)
+#define AFE_CONN7_1 (0x3090)
+#define AFE_CONN7_2 (0x3094)
+#define AFE_CONN7_3 (0x3098)
+#define AFE_CONN7_4 (0x309c)
+#define AFE_CONN8 (0x30a0)
+#define AFE_CONN8_1 (0x30a4)
+#define AFE_CONN8_2 (0x30a8)
+#define AFE_CONN8_3 (0x30ac)
+#define AFE_CONN8_4 (0x30b0)
+#define AFE_CONN9 (0x30b4)
+#define AFE_CONN9_1 (0x30b8)
+#define AFE_CONN9_2 (0x30bc)
+#define AFE_CONN9_3 (0x30c0)
+#define AFE_CONN9_4 (0x30c4)
+#define AFE_CONN10 (0x30c8)
+#define AFE_CONN10_1 (0x30cc)
+#define AFE_CONN10_2 (0x30d0)
+#define AFE_CONN10_3 (0x30d4)
+#define AFE_CONN10_4 (0x30d8)
+#define AFE_CONN11 (0x30dc)
+#define AFE_CONN11_1 (0x30e0)
+#define AFE_CONN11_2 (0x30e4)
+#define AFE_CONN11_3 (0x30e8)
+#define AFE_CONN11_4 (0x30ec)
+#define AFE_CONN12 (0x30f0)
+#define AFE_CONN12_1 (0x30f4)
+#define AFE_CONN12_2 (0x30f8)
+#define AFE_CONN12_3 (0x30fc)
+#define AFE_CONN12_4 (0x3100)
+#define AFE_CONN13 (0x3104)
+#define AFE_CONN13_1 (0x3108)
+#define AFE_CONN13_2 (0x310c)
+#define AFE_CONN13_3 (0x3110)
+#define AFE_CONN13_4 (0x3114)
+#define AFE_CONN14 (0x3118)
+#define AFE_CONN14_1 (0x311c)
+#define AFE_CONN14_2 (0x3120)
+#define AFE_CONN14_3 (0x3124)
+#define AFE_CONN14_4 (0x3128)
+#define AFE_CONN15 (0x312c)
+#define AFE_CONN15_1 (0x3130)
+#define AFE_CONN15_2 (0x3134)
+#define AFE_CONN15_3 (0x3138)
+#define AFE_CONN15_4 (0x313c)
+#define AFE_CONN16 (0x3140)
+#define AFE_CONN16_1 (0x3144)
+#define AFE_CONN16_2 (0x3148)
+#define AFE_CONN16_3 (0x314c)
+#define AFE_CONN16_4 (0x3150)
+#define AFE_CONN17 (0x3154)
+#define AFE_CONN17_1 (0x3158)
+#define AFE_CONN17_2 (0x315c)
+#define AFE_CONN17_3 (0x3160)
+#define AFE_CONN17_4 (0x3164)
+#define AFE_CONN18 (0x3168)
+#define AFE_CONN18_1 (0x316c)
+#define AFE_CONN18_2 (0x3170)
+#define AFE_CONN18_3 (0x3174)
+#define AFE_CONN18_4 (0x3178)
+#define AFE_CONN19 (0x317c)
+#define AFE_CONN19_1 (0x3180)
+#define AFE_CONN19_2 (0x3184)
+#define AFE_CONN19_3 (0x3188)
+#define AFE_CONN19_4 (0x318c)
+#define AFE_CONN20 (0x3190)
+#define AFE_CONN20_1 (0x3194)
+#define AFE_CONN20_2 (0x3198)
+#define AFE_CONN20_3 (0x319c)
+#define AFE_CONN20_4 (0x31a0)
+#define AFE_CONN21 (0x31a4)
+#define AFE_CONN21_1 (0x31a8)
+#define AFE_CONN21_2 (0x31ac)
+#define AFE_CONN21_3 (0x31b0)
+#define AFE_CONN21_4 (0x31b4)
+#define AFE_CONN22 (0x31b8)
+#define AFE_CONN22_1 (0x31bc)
+#define AFE_CONN22_2 (0x31c0)
+#define AFE_CONN22_3 (0x31c4)
+#define AFE_CONN22_4 (0x31c8)
+#define AFE_CONN23 (0x31cc)
+#define AFE_CONN23_1 (0x31d0)
+#define AFE_CONN23_2 (0x31d4)
+#define AFE_CONN23_3 (0x31d8)
+#define AFE_CONN23_4 (0x31dc)
+#define AFE_CONN24 (0x31e0)
+#define AFE_CONN24_1 (0x31e4)
+#define AFE_CONN24_2 (0x31e8)
+#define AFE_CONN24_3 (0x31ec)
+#define AFE_CONN24_4 (0x31f0)
+#define AFE_CONN25 (0x31f4)
+#define AFE_CONN25_1 (0x31f8)
+#define AFE_CONN25_2 (0x31fc)
+#define AFE_CONN25_3 (0x3200)
+#define AFE_CONN25_4 (0x3204)
+#define AFE_CONN26 (0x3208)
+#define AFE_CONN26_1 (0x320c)
+#define AFE_CONN26_2 (0x3210)
+#define AFE_CONN26_3 (0x3214)
+#define AFE_CONN26_4 (0x3218)
+#define AFE_CONN27 (0x321c)
+#define AFE_CONN27_1 (0x3220)
+#define AFE_CONN27_2 (0x3224)
+#define AFE_CONN27_3 (0x3228)
+#define AFE_CONN27_4 (0x322c)
+#define AFE_CONN28 (0x3230)
+#define AFE_CONN28_1 (0x3234)
+#define AFE_CONN28_2 (0x3238)
+#define AFE_CONN28_3 (0x323c)
+#define AFE_CONN28_4 (0x3240)
+#define AFE_CONN29 (0x3244)
+#define AFE_CONN29_1 (0x3248)
+#define AFE_CONN29_2 (0x324c)
+#define AFE_CONN29_3 (0x3250)
+#define AFE_CONN29_4 (0x3254)
+#define AFE_CONN30 (0x3258)
+#define AFE_CONN30_1 (0x325c)
+#define AFE_CONN30_2 (0x3260)
+#define AFE_CONN30_3 (0x3264)
+#define AFE_CONN30_4 (0x3268)
+#define AFE_CONN31 (0x326c)
+#define AFE_CONN31_1 (0x3270)
+#define AFE_CONN31_2 (0x3274)
+#define AFE_CONN31_3 (0x3278)
+#define AFE_CONN31_4 (0x327c)
+#define AFE_CONN32 (0x3280)
+#define AFE_CONN32_1 (0x3284)
+#define AFE_CONN32_2 (0x3288)
+#define AFE_CONN32_3 (0x328c)
+#define AFE_CONN32_4 (0x3290)
+#define AFE_CONN33 (0x3294)
+#define AFE_CONN33_1 (0x3298)
+#define AFE_CONN33_2 (0x329c)
+#define AFE_CONN33_3 (0x32a0)
+#define AFE_CONN33_4 (0x32a4)
+#define AFE_CONN34 (0x32a8)
+#define AFE_CONN34_1 (0x32ac)
+#define AFE_CONN34_2 (0x32b0)
+#define AFE_CONN34_3 (0x32b4)
+#define AFE_CONN34_4 (0x32b8)
+#define AFE_CONN35 (0x32bc)
+#define AFE_CONN35_1 (0x32c0)
+#define AFE_CONN35_2 (0x32c4)
+#define AFE_CONN35_3 (0x32c8)
+#define AFE_CONN35_4 (0x32cc)
+#define AFE_CONN36 (0x32d0)
+#define AFE_CONN36_1 (0x32d4)
+#define AFE_CONN36_2 (0x32d8)
+#define AFE_CONN36_3 (0x32dc)
+#define AFE_CONN36_4 (0x32e0)
+#define AFE_CONN37 (0x32e4)
+#define AFE_CONN37_1 (0x32e8)
+#define AFE_CONN37_2 (0x32ec)
+#define AFE_CONN37_3 (0x32f0)
+#define AFE_CONN37_4 (0x32f4)
+#define AFE_CONN38 (0x32f8)
+#define AFE_CONN38_1 (0x32fc)
+#define AFE_CONN38_2 (0x3300)
+#define AFE_CONN38_3 (0x3304)
+#define AFE_CONN38_4 (0x3308)
+#define AFE_CONN39 (0x330c)
+#define AFE_CONN39_1 (0x3310)
+#define AFE_CONN39_2 (0x3314)
+#define AFE_CONN39_3 (0x3318)
+#define AFE_CONN39_4 (0x331c)
+#define AFE_CONN40 (0x3320)
+#define AFE_CONN40_1 (0x3324)
+#define AFE_CONN40_2 (0x3328)
+#define AFE_CONN40_3 (0x332c)
+#define AFE_CONN40_4 (0x3330)
+#define AFE_CONN41 (0x3334)
+#define AFE_CONN41_1 (0x3338)
+#define AFE_CONN41_2 (0x333c)
+#define AFE_CONN41_3 (0x3340)
+#define AFE_CONN41_4 (0x3344)
+#define AFE_CONN42 (0x3348)
+#define AFE_CONN42_1 (0x334c)
+#define AFE_CONN42_2 (0x3350)
+#define AFE_CONN42_3 (0x3354)
+#define AFE_CONN42_4 (0x3358)
+#define AFE_CONN43 (0x335c)
+#define AFE_CONN43_1 (0x3360)
+#define AFE_CONN43_2 (0x3364)
+#define AFE_CONN43_3 (0x3368)
+#define AFE_CONN43_4 (0x336c)
+#define AFE_CONN44 (0x3370)
+#define AFE_CONN44_1 (0x3374)
+#define AFE_CONN44_2 (0x3378)
+#define AFE_CONN44_3 (0x337c)
+#define AFE_CONN44_4 (0x3380)
+#define AFE_CONN45 (0x3384)
+#define AFE_CONN45_1 (0x3388)
+#define AFE_CONN45_2 (0x338c)
+#define AFE_CONN45_3 (0x3390)
+#define AFE_CONN45_4 (0x3394)
+#define AFE_CONN46 (0x3398)
+#define AFE_CONN46_1 (0x339c)
+#define AFE_CONN46_2 (0x33a0)
+#define AFE_CONN46_3 (0x33a4)
+#define AFE_CONN46_4 (0x33a8)
+#define AFE_CONN47 (0x33ac)
+#define AFE_CONN47_1 (0x33b0)
+#define AFE_CONN47_2 (0x33b4)
+#define AFE_CONN47_3 (0x33b8)
+#define AFE_CONN47_4 (0x33bc)
+#define AFE_CONN48 (0x33c0)
+#define AFE_CONN48_1 (0x33c4)
+#define AFE_CONN48_2 (0x33c8)
+#define AFE_CONN48_3 (0x33cc)
+#define AFE_CONN48_4 (0x33d0)
+#define AFE_CONN49 (0x33d4)
+#define AFE_CONN49_1 (0x33d8)
+#define AFE_CONN49_2 (0x33dc)
+#define AFE_CONN49_3 (0x33e0)
+#define AFE_CONN49_4 (0x33e4)
+#define AFE_CONN50 (0x33e8)
+#define AFE_CONN50_1 (0x33ec)
+#define AFE_CONN50_2 (0x33f0)
+#define AFE_CONN50_3 (0x33f4)
+#define AFE_CONN50_4 (0x33f8)
+#define AFE_CONN51 (0x33fc)
+#define AFE_CONN51_1 (0x3400)
+#define AFE_CONN51_2 (0x3404)
+#define AFE_CONN51_3 (0x3408)
+#define AFE_CONN51_4 (0x340c)
+#define AFE_CONN52 (0x3410)
+#define AFE_CONN52_1 (0x3414)
+#define AFE_CONN52_2 (0x3418)
+#define AFE_CONN52_3 (0x341c)
+#define AFE_CONN52_4 (0x3420)
+#define AFE_CONN53 (0x3424)
+#define AFE_CONN53_1 (0x3428)
+#define AFE_CONN53_2 (0x342c)
+#define AFE_CONN53_3 (0x3430)
+#define AFE_CONN53_4 (0x3434)
+#define AFE_CONN54 (0x3438)
+#define AFE_CONN54_1 (0x343c)
+#define AFE_CONN54_2 (0x3440)
+#define AFE_CONN54_3 (0x3444)
+#define AFE_CONN54_4 (0x3448)
+#define AFE_CONN55 (0x344c)
+#define AFE_CONN55_1 (0x3450)
+#define AFE_CONN55_2 (0x3454)
+#define AFE_CONN55_3 (0x3458)
+#define AFE_CONN55_4 (0x345c)
+#define AFE_CONN56 (0x3460)
+#define AFE_CONN56_1 (0x3464)
+#define AFE_CONN56_2 (0x3468)
+#define AFE_CONN56_3 (0x346c)
+#define AFE_CONN56_4 (0x3470)
+#define AFE_CONN57 (0x3474)
+#define AFE_CONN57_1 (0x3478)
+#define AFE_CONN57_2 (0x347c)
+#define AFE_CONN57_3 (0x3480)
+#define AFE_CONN57_4 (0x3484)
+#define AFE_CONN58 (0x3488)
+#define AFE_CONN58_1 (0x348c)
+#define AFE_CONN58_2 (0x3490)
+#define AFE_CONN58_3 (0x3494)
+#define AFE_CONN58_4 (0x3498)
+#define AFE_CONN59 (0x349c)
+#define AFE_CONN59_1 (0x34a0)
+#define AFE_CONN59_2 (0x34a4)
+#define AFE_CONN59_3 (0x34a8)
+#define AFE_CONN59_4 (0x34ac)
+#define AFE_CONN60 (0x34b0)
+#define AFE_CONN60_1 (0x34b4)
+#define AFE_CONN60_2 (0x34b8)
+#define AFE_CONN60_3 (0x34bc)
+#define AFE_CONN60_4 (0x34c0)
+#define AFE_CONN61 (0x34c4)
+#define AFE_CONN61_1 (0x34c8)
+#define AFE_CONN61_2 (0x34cc)
+#define AFE_CONN61_3 (0x34d0)
+#define AFE_CONN61_4 (0x34d4)
+#define AFE_CONN62 (0x34d8)
+#define AFE_CONN62_1 (0x34dc)
+#define AFE_CONN62_2 (0x34e0)
+#define AFE_CONN62_3 (0x34e4)
+#define AFE_CONN62_4 (0x34e8)
+#define AFE_CONN63 (0x34ec)
+#define AFE_CONN63_1 (0x34f0)
+#define AFE_CONN63_2 (0x34f4)
+#define AFE_CONN63_3 (0x34f8)
+#define AFE_CONN63_4 (0x34fc)
+#define AFE_CONN64 (0x3500)
+#define AFE_CONN64_1 (0x3504)
+#define AFE_CONN64_2 (0x3508)
+#define AFE_CONN64_3 (0x350c)
+#define AFE_CONN64_4 (0x3510)
+#define AFE_CONN65 (0x3514)
+#define AFE_CONN65_1 (0x3518)
+#define AFE_CONN65_2 (0x351c)
+#define AFE_CONN65_3 (0x3520)
+#define AFE_CONN65_4 (0x3524)
+#define AFE_CONN66 (0x3528)
+#define AFE_CONN66_1 (0x352c)
+#define AFE_CONN66_2 (0x3530)
+#define AFE_CONN66_3 (0x3534)
+#define AFE_CONN66_4 (0x3538)
+#define AFE_CONN67 (0x353c)
+#define AFE_CONN67_1 (0x3540)
+#define AFE_CONN67_2 (0x3544)
+#define AFE_CONN67_3 (0x3548)
+#define AFE_CONN67_4 (0x354c)
+#define AFE_CONN68 (0x3550)
+#define AFE_CONN68_1 (0x3554)
+#define AFE_CONN68_2 (0x3558)
+#define AFE_CONN68_3 (0x355c)
+#define AFE_CONN68_4 (0x3560)
+#define AFE_CONN69 (0x3564)
+#define AFE_CONN69_1 (0x3568)
+#define AFE_CONN69_2 (0x356c)
+#define AFE_CONN69_3 (0x3570)
+#define AFE_CONN69_4 (0x3574)
+#define AFE_CONN70 (0x3578)
+#define AFE_CONN70_1 (0x357c)
+#define AFE_CONN70_2 (0x3580)
+#define AFE_CONN70_3 (0x3584)
+#define AFE_CONN70_4 (0x3588)
+#define AFE_CONN71 (0x358c)
+#define AFE_CONN71_1 (0x3590)
+#define AFE_CONN71_2 (0x3594)
+#define AFE_CONN71_3 (0x3598)
+#define AFE_CONN71_4 (0x359c)
+#define AFE_CONN72 (0x35a0)
+#define AFE_CONN72_1 (0x35a4)
+#define AFE_CONN72_2 (0x35a8)
+#define AFE_CONN72_3 (0x35ac)
+#define AFE_CONN72_4 (0x35b0)
+#define AFE_CONN73 (0x35b4)
+#define AFE_CONN73_1 (0x35b8)
+#define AFE_CONN73_2 (0x35bc)
+#define AFE_CONN73_3 (0x35c0)
+#define AFE_CONN73_4 (0x35c4)
+#define AFE_CONN74 (0x35c8)
+#define AFE_CONN74_1 (0x35cc)
+#define AFE_CONN74_2 (0x35d0)
+#define AFE_CONN74_3 (0x35d4)
+#define AFE_CONN74_4 (0x35d8)
+#define AFE_CONN75 (0x35dc)
+#define AFE_CONN75_1 (0x35e0)
+#define AFE_CONN75_2 (0x35e4)
+#define AFE_CONN75_3 (0x35e8)
+#define AFE_CONN75_4 (0x35ec)
+#define AFE_CONN76 (0x35f0)
+#define AFE_CONN76_1 (0x35f4)
+#define AFE_CONN76_2 (0x35f8)
+#define AFE_CONN76_3 (0x35fc)
+#define AFE_CONN76_4 (0x3600)
+#define AFE_CONN77 (0x3604)
+#define AFE_CONN77_1 (0x3608)
+#define AFE_CONN77_2 (0x360c)
+#define AFE_CONN77_3 (0x3610)
+#define AFE_CONN77_4 (0x3614)
+#define AFE_CONN78 (0x3618)
+#define AFE_CONN78_1 (0x361c)
+#define AFE_CONN78_2 (0x3620)
+#define AFE_CONN78_3 (0x3624)
+#define AFE_CONN78_4 (0x3628)
+#define AFE_CONN79 (0x362c)
+#define AFE_CONN79_1 (0x3630)
+#define AFE_CONN79_2 (0x3634)
+#define AFE_CONN79_3 (0x3638)
+#define AFE_CONN79_4 (0x363c)
+#define AFE_CONN80 (0x3640)
+#define AFE_CONN80_1 (0x3644)
+#define AFE_CONN80_2 (0x3648)
+#define AFE_CONN80_3 (0x364c)
+#define AFE_CONN80_4 (0x3650)
+#define AFE_CONN81 (0x3654)
+#define AFE_CONN81_1 (0x3658)
+#define AFE_CONN81_2 (0x365c)
+#define AFE_CONN81_3 (0x3660)
+#define AFE_CONN81_4 (0x3664)
+#define AFE_CONN82 (0x3668)
+#define AFE_CONN82_1 (0x366c)
+#define AFE_CONN82_2 (0x3670)
+#define AFE_CONN82_3 (0x3674)
+#define AFE_CONN82_4 (0x3678)
+#define AFE_CONN83 (0x367c)
+#define AFE_CONN83_1 (0x3680)
+#define AFE_CONN83_2 (0x3684)
+#define AFE_CONN83_3 (0x3688)
+#define AFE_CONN83_4 (0x368c)
+#define AFE_CONN84 (0x3690)
+#define AFE_CONN84_1 (0x3694)
+#define AFE_CONN84_2 (0x3698)
+#define AFE_CONN84_3 (0x369c)
+#define AFE_CONN84_4 (0x36a0)
+#define AFE_CONN85 (0x36a4)
+#define AFE_CONN85_1 (0x36a8)
+#define AFE_CONN85_2 (0x36ac)
+#define AFE_CONN85_3 (0x36b0)
+#define AFE_CONN85_4 (0x36b4)
+#define AFE_CONN86 (0x36b8)
+#define AFE_CONN86_1 (0x36bc)
+#define AFE_CONN86_2 (0x36c0)
+#define AFE_CONN86_3 (0x36c4)
+#define AFE_CONN86_4 (0x36c8)
+#define AFE_CONN87 (0x36cc)
+#define AFE_CONN87_1 (0x36d0)
+#define AFE_CONN87_2 (0x36d4)
+#define AFE_CONN87_3 (0x36d8)
+#define AFE_CONN87_4 (0x36dc)
+#define AFE_CONN88 (0x36e0)
+#define AFE_CONN88_1 (0x36e4)
+#define AFE_CONN88_2 (0x36e8)
+#define AFE_CONN88_3 (0x36ec)
+#define AFE_CONN88_4 (0x36f0)
+#define AFE_CONN89 (0x36f4)
+#define AFE_CONN89_1 (0x36f8)
+#define AFE_CONN89_2 (0x36fc)
+#define AFE_CONN89_3 (0x3700)
+#define AFE_CONN89_4 (0x3704)
+#define AFE_CONN90 (0x3708)
+#define AFE_CONN90_1 (0x370c)
+#define AFE_CONN90_2 (0x3710)
+#define AFE_CONN90_3 (0x3714)
+#define AFE_CONN90_4 (0x3718)
+#define AFE_CONN91 (0x371c)
+#define AFE_CONN91_1 (0x3720)
+#define AFE_CONN91_2 (0x3724)
+#define AFE_CONN91_3 (0x3728)
+#define AFE_CONN91_4 (0x372c)
+#define AFE_CONN92 (0x3730)
+#define AFE_CONN92_1 (0x3734)
+#define AFE_CONN92_2 (0x3738)
+#define AFE_CONN92_3 (0x373c)
+#define AFE_CONN92_4 (0x3740)
+#define AFE_CONN93 (0x3744)
+#define AFE_CONN93_1 (0x3748)
+#define AFE_CONN93_2 (0x374c)
+#define AFE_CONN93_3 (0x3750)
+#define AFE_CONN93_4 (0x3754)
+#define AFE_CONN94 (0x3758)
+#define AFE_CONN94_1 (0x375c)
+#define AFE_CONN94_2 (0x3760)
+#define AFE_CONN94_3 (0x3764)
+#define AFE_CONN94_4 (0x3768)
+#define AFE_CONN95 (0x376c)
+#define AFE_CONN95_1 (0x3770)
+#define AFE_CONN95_2 (0x3774)
+#define AFE_CONN95_3 (0x3778)
+#define AFE_CONN95_4 (0x377c)
+#define AFE_CONN96 (0x3780)
+#define AFE_CONN96_1 (0x3784)
+#define AFE_CONN96_2 (0x3788)
+#define AFE_CONN96_3 (0x378c)
+#define AFE_CONN96_4 (0x3790)
+#define AFE_CONN97 (0x3794)
+#define AFE_CONN97_1 (0x3798)
+#define AFE_CONN97_2 (0x379c)
+#define AFE_CONN97_3 (0x37a0)
+#define AFE_CONN97_4 (0x37a4)
+#define AFE_CONN98 (0x37a8)
+#define AFE_CONN98_1 (0x37ac)
+#define AFE_CONN98_2 (0x37b0)
+#define AFE_CONN98_3 (0x37b4)
+#define AFE_CONN98_4 (0x37b8)
+#define AFE_CONN99 (0x37bc)
+#define AFE_CONN99_1 (0x37c0)
+#define AFE_CONN99_2 (0x37c4)
+#define AFE_CONN99_3 (0x37c8)
+#define AFE_CONN99_4 (0x37cc)
+#define AFE_CONN100 (0x37d0)
+#define AFE_CONN100_1 (0x37d4)
+#define AFE_CONN100_2 (0x37d8)
+#define AFE_CONN100_3 (0x37dc)
+#define AFE_CONN100_4 (0x37e0)
+#define AFE_CONN101 (0x37e4)
+#define AFE_CONN101_1 (0x37e8)
+#define AFE_CONN101_2 (0x37ec)
+#define AFE_CONN101_3 (0x37f0)
+#define AFE_CONN101_4 (0x37f4)
+#define AFE_CONN102 (0x37f8)
+#define AFE_CONN102_1 (0x37fc)
+#define AFE_CONN102_2 (0x3800)
+#define AFE_CONN102_3 (0x3804)
+#define AFE_CONN102_4 (0x3808)
+#define AFE_CONN103 (0x380c)
+#define AFE_CONN103_1 (0x3810)
+#define AFE_CONN103_2 (0x3814)
+#define AFE_CONN103_3 (0x3818)
+#define AFE_CONN103_4 (0x381c)
+#define AFE_CONN104 (0x3820)
+#define AFE_CONN104_1 (0x3824)
+#define AFE_CONN104_2 (0x3828)
+#define AFE_CONN104_3 (0x382c)
+#define AFE_CONN104_4 (0x3830)
+#define AFE_CONN105 (0x3834)
+#define AFE_CONN105_1 (0x3838)
+#define AFE_CONN105_2 (0x383c)
+#define AFE_CONN105_3 (0x3840)
+#define AFE_CONN105_4 (0x3844)
+#define AFE_CONN106 (0x3848)
+#define AFE_CONN106_1 (0x384c)
+#define AFE_CONN106_2 (0x3850)
+#define AFE_CONN106_3 (0x3854)
+#define AFE_CONN106_4 (0x3858)
+#define AFE_CONN107 (0x385c)
+#define AFE_CONN107_1 (0x3860)
+#define AFE_CONN107_2 (0x3864)
+#define AFE_CONN107_3 (0x3868)
+#define AFE_CONN107_4 (0x386c)
+#define AFE_CONN108 (0x3870)
+#define AFE_CONN108_1 (0x3874)
+#define AFE_CONN108_2 (0x3878)
+#define AFE_CONN108_3 (0x387c)
+#define AFE_CONN108_4 (0x3880)
+#define AFE_CONN109 (0x3884)
+#define AFE_CONN109_1 (0x3888)
+#define AFE_CONN109_2 (0x388c)
+#define AFE_CONN109_3 (0x3890)
+#define AFE_CONN109_4 (0x3894)
+#define AFE_CONN110 (0x3898)
+#define AFE_CONN110_1 (0x389c)
+#define AFE_CONN110_2 (0x38a0)
+#define AFE_CONN110_3 (0x38a4)
+#define AFE_CONN110_4 (0x38a8)
+#define AFE_CONN111 (0x38ac)
+#define AFE_CONN111_1 (0x38b0)
+#define AFE_CONN111_2 (0x38b4)
+#define AFE_CONN111_3 (0x38b8)
+#define AFE_CONN111_4 (0x38bc)
+#define AFE_CONN112 (0x38c0)
+#define AFE_CONN112_1 (0x38c4)
+#define AFE_CONN112_2 (0x38c8)
+#define AFE_CONN112_3 (0x38cc)
+#define AFE_CONN112_4 (0x38d0)
+#define AFE_CONN113 (0x38d4)
+#define AFE_CONN113_1 (0x38d8)
+#define AFE_CONN113_2 (0x38dc)
+#define AFE_CONN113_3 (0x38e0)
+#define AFE_CONN113_4 (0x38e4)
+#define AFE_CONN114 (0x38e8)
+#define AFE_CONN114_1 (0x38ec)
+#define AFE_CONN114_2 (0x38f0)
+#define AFE_CONN114_3 (0x38f4)
+#define AFE_CONN114_4 (0x38f8)
+#define AFE_CONN115 (0x38fc)
+#define AFE_CONN115_1 (0x3900)
+#define AFE_CONN115_2 (0x3904)
+#define AFE_CONN115_3 (0x3908)
+#define AFE_CONN115_4 (0x390c)
+#define AFE_CONN116 (0x3910)
+#define AFE_CONN116_1 (0x3914)
+#define AFE_CONN116_2 (0x3918)
+#define AFE_CONN116_3 (0x391c)
+#define AFE_CONN116_4 (0x3920)
+#define AFE_CONN117 (0x3924)
+#define AFE_CONN117_1 (0x3928)
+#define AFE_CONN117_2 (0x392c)
+#define AFE_CONN117_3 (0x3930)
+#define AFE_CONN117_4 (0x3934)
+#define AFE_CONN118 (0x3938)
+#define AFE_CONN118_1 (0x393c)
+#define AFE_CONN118_2 (0x3940)
+#define AFE_CONN118_3 (0x3944)
+#define AFE_CONN118_4 (0x3948)
+#define AFE_CONN119 (0x394c)
+#define AFE_CONN119_1 (0x3950)
+#define AFE_CONN119_2 (0x3954)
+#define AFE_CONN119_3 (0x3958)
+#define AFE_CONN119_4 (0x395c)
+#define AFE_CONN120 (0x3960)
+#define AFE_CONN120_1 (0x3964)
+#define AFE_CONN120_2 (0x3968)
+#define AFE_CONN120_3 (0x396c)
+#define AFE_CONN120_4 (0x3970)
+#define AFE_CONN121 (0x3974)
+#define AFE_CONN121_1 (0x3978)
+#define AFE_CONN121_2 (0x397c)
+#define AFE_CONN121_3 (0x3980)
+#define AFE_CONN121_4 (0x3984)
+#define AFE_CONN122 (0x3988)
+#define AFE_CONN122_1 (0x398c)
+#define AFE_CONN122_2 (0x3990)
+#define AFE_CONN122_3 (0x3994)
+#define AFE_CONN122_4 (0x3998)
+#define AFE_CONN123 (0x399c)
+#define AFE_CONN123_1 (0x39a0)
+#define AFE_CONN123_2 (0x39a4)
+#define AFE_CONN123_3 (0x39a8)
+#define AFE_CONN123_4 (0x39ac)
+#define AFE_CONN124 (0x39b0)
+#define AFE_CONN124_1 (0x39b4)
+#define AFE_CONN124_2 (0x39b8)
+#define AFE_CONN124_3 (0x39bc)
+#define AFE_CONN124_4 (0x39c0)
+#define AFE_CONN125 (0x39c4)
+#define AFE_CONN125_1 (0x39c8)
+#define AFE_CONN125_2 (0x39cc)
+#define AFE_CONN125_3 (0x39d0)
+#define AFE_CONN125_4 (0x39d4)
+#define AFE_CONN126 (0x39d8)
+#define AFE_CONN126_1 (0x39dc)
+#define AFE_CONN126_2 (0x39e0)
+#define AFE_CONN126_3 (0x39e4)
+#define AFE_CONN126_4 (0x39e8)
+#define AFE_CONN127 (0x39ec)
+#define AFE_CONN127_1 (0x39f0)
+#define AFE_CONN127_2 (0x39f4)
+#define AFE_CONN127_3 (0x39f8)
+#define AFE_CONN127_4 (0x39fc)
+#define AFE_CONN128 (0x3a00)
+#define AFE_CONN128_1 (0x3a04)
+#define AFE_CONN128_2 (0x3a08)
+#define AFE_CONN128_3 (0x3a0c)
+#define AFE_CONN128_4 (0x3a10)
+#define AFE_CONN129 (0x3a14)
+#define AFE_CONN129_1 (0x3a18)
+#define AFE_CONN129_2 (0x3a1c)
+#define AFE_CONN129_3 (0x3a20)
+#define AFE_CONN129_4 (0x3a24)
+#define AFE_CONN130 (0x3a28)
+#define AFE_CONN130_1 (0x3a2c)
+#define AFE_CONN130_2 (0x3a30)
+#define AFE_CONN130_3 (0x3a34)
+#define AFE_CONN130_4 (0x3a38)
+#define AFE_CONN131 (0x3a3c)
+#define AFE_CONN131_1 (0x3a40)
+#define AFE_CONN131_2 (0x3a44)
+#define AFE_CONN131_3 (0x3a48)
+#define AFE_CONN131_4 (0x3a4c)
+#define AFE_CONN132 (0x3a50)
+#define AFE_CONN132_1 (0x3a54)
+#define AFE_CONN132_2 (0x3a58)
+#define AFE_CONN132_3 (0x3a5c)
+#define AFE_CONN132_4 (0x3a60)
+#define AFE_CONN133 (0x3a64)
+#define AFE_CONN133_1 (0x3a68)
+#define AFE_CONN133_2 (0x3a6c)
+#define AFE_CONN133_3 (0x3a70)
+#define AFE_CONN133_4 (0x3a74)
+#define AFE_CONN134 (0x3a78)
+#define AFE_CONN134_1 (0x3a7c)
+#define AFE_CONN134_2 (0x3a80)
+#define AFE_CONN134_3 (0x3a84)
+#define AFE_CONN134_4 (0x3a88)
+#define AFE_CONN135 (0x3a8c)
+#define AFE_CONN135_1 (0x3a90)
+#define AFE_CONN135_2 (0x3a94)
+#define AFE_CONN135_3 (0x3a98)
+#define AFE_CONN135_4 (0x3a9c)
+#define AFE_CONN136 (0x3aa0)
+#define AFE_CONN136_1 (0x3aa4)
+#define AFE_CONN136_2 (0x3aa8)
+#define AFE_CONN136_3 (0x3aac)
+#define AFE_CONN136_4 (0x3ab0)
+#define AFE_CONN137 (0x3ab4)
+#define AFE_CONN137_1 (0x3ab8)
+#define AFE_CONN137_2 (0x3abc)
+#define AFE_CONN137_3 (0x3ac0)
+#define AFE_CONN137_4 (0x3ac4)
+#define AFE_CONN138 (0x3ac8)
+#define AFE_CONN138_1 (0x3acc)
+#define AFE_CONN138_2 (0x3ad0)
+#define AFE_CONN138_3 (0x3ad4)
+#define AFE_CONN138_4 (0x3ad8)
+#define AFE_CONN139 (0x3adc)
+#define AFE_CONN139_1 (0x3ae0)
+#define AFE_CONN139_2 (0x3ae4)
+#define AFE_CONN139_3 (0x3ae8)
+#define AFE_CONN139_4 (0x3aec)
+#define AFE_CONN_RS (0x3af0)
+#define AFE_CONN_RS_1 (0x3af4)
+#define AFE_CONN_RS_2 (0x3af8)
+#define AFE_CONN_RS_3 (0x3afc)
+#define AFE_CONN_RS_4 (0x3b00)
+#define AFE_CONN_16BIT (0x3b04)
+#define AFE_CONN_16BIT_1 (0x3b08)
+#define AFE_CONN_16BIT_2 (0x3b0c)
+#define AFE_CONN_16BIT_3 (0x3b10)
+#define AFE_CONN_16BIT_4 (0x3b14)
+#define AFE_CONN_24BIT (0x3b18)
+#define AFE_CONN_24BIT_1 (0x3b1c)
+#define AFE_CONN_24BIT_2 (0x3b20)
+#define AFE_CONN_24BIT_3 (0x3b24)
+#define AFE_CONN_24BIT_4 (0x3b28)
+#define AFE_CONN_DI (0x3b2c)
+#define AFE_CONN_DI_1 (0x3b30)
+#define AFE_CONN_DI_2 (0x3b34)
+#define AFE_CONN_DI_3 (0x3b38)
+#define AFE_CONN_DI_4 (0x3b3c)
+#define AFE_CONN176 (0x3ea0)
+#define AFE_CONN176_1 (0x3ea4)
+#define AFE_CONN176_2 (0x3ea8)
+#define AFE_CONN176_3 (0x3eac)
+#define AFE_CONN176_4 (0x3eb0)
+#define AFE_CONN176_5 (0x3eb4)
+#define AFE_CONN177 (0x3eb8)
+#define AFE_CONN177_1 (0x3ebc)
+#define AFE_CONN177_2 (0x3ec0)
+#define AFE_CONN177_3 (0x3ec4)
+#define AFE_CONN177_4 (0x3ec8)
+#define AFE_CONN177_5 (0x3ecc)
+#define AFE_CONN182 (0x3f30)
+#define AFE_CONN182_1 (0x3f34)
+#define AFE_CONN182_2 (0x3f38)
+#define AFE_CONN182_3 (0x3f3c)
+#define AFE_CONN182_4 (0x3f40)
+#define AFE_CONN182_5 (0x3f44)
+#define AFE_CONN183 (0x3f48)
+#define AFE_CONN183_1 (0x3f4c)
+#define AFE_CONN183_2 (0x3f50)
+#define AFE_CONN183_3 (0x3f54)
+#define AFE_CONN183_4 (0x3f58)
+#define AFE_CONN183_5 (0x3f5c)
+#define AFE_SECURE_MASK_CONN0 (0x4000)
+#define AFE_SECURE_MASK_CONN0_1 (0x4004)
+#define AFE_SECURE_MASK_CONN0_2 (0x4008)
+#define AFE_SECURE_MASK_CONN0_3 (0x400c)
+#define AFE_SECURE_MASK_CONN0_4 (0x4010)
+#define AFE_SECURE_MASK_CONN1 (0x4014)
+#define AFE_SECURE_MASK_CONN1_1 (0x4018)
+#define AFE_SECURE_MASK_CONN1_2 (0x401c)
+#define AFE_SECURE_MASK_CONN1_3 (0x4020)
+#define AFE_SECURE_MASK_CONN1_4 (0x4024)
+#define AFE_SECURE_MASK_CONN2 (0x4028)
+#define AFE_SECURE_MASK_CONN2_1 (0x402c)
+#define AFE_SECURE_MASK_CONN2_2 (0x4030)
+#define AFE_SECURE_MASK_CONN2_3 (0x4034)
+#define AFE_SECURE_MASK_CONN2_4 (0x4038)
+#define AFE_SECURE_MASK_CONN3 (0x403c)
+#define AFE_SECURE_MASK_CONN3_1 (0x4040)
+#define AFE_SECURE_MASK_CONN3_2 (0x4044)
+#define AFE_SECURE_MASK_CONN3_3 (0x4048)
+#define AFE_SECURE_MASK_CONN3_4 (0x404c)
+#define AFE_SECURE_MASK_CONN4 (0x4050)
+#define AFE_SECURE_MASK_CONN4_1 (0x4054)
+#define AFE_SECURE_MASK_CONN4_2 (0x4058)
+#define AFE_SECURE_MASK_CONN4_3 (0x405c)
+#define AFE_SECURE_MASK_CONN4_4 (0x4060)
+#define AFE_SECURE_MASK_CONN5 (0x4064)
+#define AFE_SECURE_MASK_CONN5_1 (0x4068)
+#define AFE_SECURE_MASK_CONN5_2 (0x406c)
+#define AFE_SECURE_MASK_CONN5_3 (0x4070)
+#define AFE_SECURE_MASK_CONN5_4 (0x4074)
+#define AFE_SECURE_MASK_CONN6 (0x4078)
+#define AFE_SECURE_MASK_CONN6_1 (0x407c)
+#define AFE_SECURE_MASK_CONN6_2 (0x4080)
+#define AFE_SECURE_MASK_CONN6_3 (0x4084)
+#define AFE_SECURE_MASK_CONN6_4 (0x4088)
+#define AFE_SECURE_MASK_CONN7 (0x408c)
+#define AFE_SECURE_MASK_CONN7_1 (0x4090)
+#define AFE_SECURE_MASK_CONN7_2 (0x4094)
+#define AFE_SECURE_MASK_CONN7_3 (0x4098)
+#define AFE_SECURE_MASK_CONN7_4 (0x409c)
+#define AFE_SECURE_MASK_CONN8 (0x40a0)
+#define AFE_SECURE_MASK_CONN8_1 (0x40a4)
+#define AFE_SECURE_MASK_CONN8_2 (0x40a8)
+#define AFE_SECURE_MASK_CONN8_3 (0x40ac)
+#define AFE_SECURE_MASK_CONN8_4 (0x40b0)
+#define AFE_SECURE_MASK_CONN9 (0x40b4)
+#define AFE_SECURE_MASK_CONN9_1 (0x40b8)
+#define AFE_SECURE_MASK_CONN9_2 (0x40bc)
+#define AFE_SECURE_MASK_CONN9_3 (0x40c0)
+#define AFE_SECURE_MASK_CONN9_4 (0x40c4)
+#define AFE_SECURE_MASK_CONN10 (0x40c8)
+#define AFE_SECURE_MASK_CONN10_1 (0x40cc)
+#define AFE_SECURE_MASK_CONN10_2 (0x40d0)
+#define AFE_SECURE_MASK_CONN10_3 (0x40d4)
+#define AFE_SECURE_MASK_CONN10_4 (0x40d8)
+#define AFE_SECURE_MASK_CONN11 (0x40dc)
+#define AFE_SECURE_MASK_CONN11_1 (0x40e0)
+#define AFE_SECURE_MASK_CONN11_2 (0x40e4)
+#define AFE_SECURE_MASK_CONN11_3 (0x40e8)
+#define AFE_SECURE_MASK_CONN11_4 (0x40ec)
+#define AFE_SECURE_MASK_CONN12 (0x40f0)
+#define AFE_SECURE_MASK_CONN12_1 (0x40f4)
+#define AFE_SECURE_MASK_CONN12_2 (0x40f8)
+#define AFE_SECURE_MASK_CONN12_3 (0x40fc)
+#define AFE_SECURE_MASK_CONN12_4 (0x4100)
+#define AFE_SECURE_MASK_CONN13 (0x4104)
+#define AFE_SECURE_MASK_CONN13_1 (0x4108)
+#define AFE_SECURE_MASK_CONN13_2 (0x410c)
+#define AFE_SECURE_MASK_CONN13_3 (0x4110)
+#define AFE_SECURE_MASK_CONN13_4 (0x4114)
+#define AFE_SECURE_MASK_CONN14 (0x4118)
+#define AFE_SECURE_MASK_CONN14_1 (0x411c)
+#define AFE_SECURE_MASK_CONN14_2 (0x4120)
+#define AFE_SECURE_MASK_CONN14_3 (0x4124)
+#define AFE_SECURE_MASK_CONN14_4 (0x4128)
+#define AFE_SECURE_MASK_CONN15 (0x412c)
+#define AFE_SECURE_MASK_CONN15_1 (0x4130)
+#define AFE_SECURE_MASK_CONN15_2 (0x4134)
+#define AFE_SECURE_MASK_CONN15_3 (0x4138)
+#define AFE_SECURE_MASK_CONN15_4 (0x413c)
+#define AFE_SECURE_MASK_CONN16 (0x4140)
+#define AFE_SECURE_MASK_CONN16_1 (0x4144)
+#define AFE_SECURE_MASK_CONN16_2 (0x4148)
+#define AFE_SECURE_MASK_CONN16_3 (0x414c)
+#define AFE_SECURE_MASK_CONN16_4 (0x4150)
+#define AFE_SECURE_MASK_CONN17 (0x4154)
+#define AFE_SECURE_MASK_CONN17_1 (0x4158)
+#define AFE_SECURE_MASK_CONN17_2 (0x415c)
+#define AFE_SECURE_MASK_CONN17_3 (0x4160)
+#define AFE_SECURE_MASK_CONN17_4 (0x4164)
+#define AFE_SECURE_MASK_CONN18 (0x4168)
+#define AFE_SECURE_MASK_CONN18_1 (0x416c)
+#define AFE_SECURE_MASK_CONN18_2 (0x4170)
+#define AFE_SECURE_MASK_CONN18_3 (0x4174)
+#define AFE_SECURE_MASK_CONN18_4 (0x4178)
+#define AFE_SECURE_MASK_CONN19 (0x417c)
+#define AFE_SECURE_MASK_CONN19_1 (0x4180)
+#define AFE_SECURE_MASK_CONN19_2 (0x4184)
+#define AFE_SECURE_MASK_CONN19_3 (0x4188)
+#define AFE_SECURE_MASK_CONN19_4 (0x418c)
+#define AFE_SECURE_MASK_CONN20 (0x4190)
+#define AFE_SECURE_MASK_CONN20_1 (0x4194)
+#define AFE_SECURE_MASK_CONN20_2 (0x4198)
+#define AFE_SECURE_MASK_CONN20_3 (0x419c)
+#define AFE_SECURE_MASK_CONN20_4 (0x41a0)
+#define AFE_SECURE_MASK_CONN21 (0x41a4)
+#define AFE_SECURE_MASK_CONN21_1 (0x41a8)
+#define AFE_SECURE_MASK_CONN21_2 (0x41ac)
+#define AFE_SECURE_MASK_CONN21_3 (0x41b0)
+#define AFE_SECURE_MASK_CONN21_4 (0x41b4)
+#define AFE_SECURE_MASK_CONN22 (0x41b8)
+#define AFE_SECURE_MASK_CONN22_1 (0x41bc)
+#define AFE_SECURE_MASK_CONN22_2 (0x41c0)
+#define AFE_SECURE_MASK_CONN22_3 (0x41c4)
+#define AFE_SECURE_MASK_CONN22_4 (0x41c8)
+#define AFE_SECURE_MASK_CONN23 (0x41cc)
+#define AFE_SECURE_MASK_CONN23_1 (0x41d0)
+#define AFE_SECURE_MASK_CONN23_2 (0x41d4)
+#define AFE_SECURE_MASK_CONN23_3 (0x41d8)
+#define AFE_SECURE_MASK_CONN23_4 (0x41dc)
+#define AFE_SECURE_MASK_CONN24 (0x41e0)
+#define AFE_SECURE_MASK_CONN24_1 (0x41e4)
+#define AFE_SECURE_MASK_CONN24_2 (0x41e8)
+#define AFE_SECURE_MASK_CONN24_3 (0x41ec)
+#define AFE_SECURE_MASK_CONN24_4 (0x41f0)
+#define AFE_SECURE_MASK_CONN25 (0x41f4)
+#define AFE_SECURE_MASK_CONN25_1 (0x41f8)
+#define AFE_SECURE_MASK_CONN25_2 (0x41fc)
+#define AFE_SECURE_MASK_CONN25_3 (0x4200)
+#define AFE_SECURE_MASK_CONN25_4 (0x4204)
+#define AFE_SECURE_MASK_CONN26 (0x4208)
+#define AFE_SECURE_MASK_CONN26_1 (0x420c)
+#define AFE_SECURE_MASK_CONN26_2 (0x4210)
+#define AFE_SECURE_MASK_CONN26_3 (0x4214)
+#define AFE_SECURE_MASK_CONN26_4 (0x4218)
+#define AFE_SECURE_MASK_CONN27 (0x421c)
+#define AFE_SECURE_MASK_CONN27_1 (0x4220)
+#define AFE_SECURE_MASK_CONN27_2 (0x4224)
+#define AFE_SECURE_MASK_CONN27_3 (0x4228)
+#define AFE_SECURE_MASK_CONN27_4 (0x422c)
+#define AFE_SECURE_MASK_CONN28 (0x4230)
+#define AFE_SECURE_MASK_CONN28_1 (0x4234)
+#define AFE_SECURE_MASK_CONN28_2 (0x4238)
+#define AFE_SECURE_MASK_CONN28_3 (0x423c)
+#define AFE_SECURE_MASK_CONN28_4 (0x4240)
+#define AFE_SECURE_MASK_CONN29 (0x4244)
+#define AFE_SECURE_MASK_CONN29_1 (0x4248)
+#define AFE_SECURE_MASK_CONN29_2 (0x424c)
+#define AFE_SECURE_MASK_CONN29_3 (0x4250)
+#define AFE_SECURE_MASK_CONN29_4 (0x4254)
+#define AFE_SECURE_MASK_CONN30 (0x4258)
+#define AFE_SECURE_MASK_CONN30_1 (0x425c)
+#define AFE_SECURE_MASK_CONN30_2 (0x4260)
+#define AFE_SECURE_MASK_CONN30_3 (0x4264)
+#define AFE_SECURE_MASK_CONN30_4 (0x4268)
+#define AFE_SECURE_MASK_CONN31 (0x426c)
+#define AFE_SECURE_MASK_CONN31_1 (0x4270)
+#define AFE_SECURE_MASK_CONN31_2 (0x4274)
+#define AFE_SECURE_MASK_CONN31_3 (0x4278)
+#define AFE_SECURE_MASK_CONN31_4 (0x427c)
+#define AFE_SECURE_MASK_CONN32 (0x4280)
+#define AFE_SECURE_MASK_CONN32_1 (0x4284)
+#define AFE_SECURE_MASK_CONN32_2 (0x4288)
+#define AFE_SECURE_MASK_CONN32_3 (0x428c)
+#define AFE_SECURE_MASK_CONN32_4 (0x4290)
+#define AFE_SECURE_MASK_CONN33 (0x4294)
+#define AFE_SECURE_MASK_CONN33_1 (0x4298)
+#define AFE_SECURE_MASK_CONN33_2 (0x429c)
+#define AFE_SECURE_MASK_CONN33_3 (0x42a0)
+#define AFE_SECURE_MASK_CONN33_4 (0x42a4)
+#define AFE_SECURE_MASK_CONN34 (0x42a8)
+#define AFE_SECURE_MASK_CONN34_1 (0x42ac)
+#define AFE_SECURE_MASK_CONN34_2 (0x42b0)
+#define AFE_SECURE_MASK_CONN34_3 (0x42b4)
+#define AFE_SECURE_MASK_CONN34_4 (0x42b8)
+#define AFE_SECURE_MASK_CONN35 (0x42bc)
+#define AFE_SECURE_MASK_CONN35_1 (0x42c0)
+#define AFE_SECURE_MASK_CONN35_2 (0x42c4)
+#define AFE_SECURE_MASK_CONN35_3 (0x42c8)
+#define AFE_SECURE_MASK_CONN35_4 (0x42cc)
+#define AFE_SECURE_MASK_CONN36 (0x42d0)
+#define AFE_SECURE_MASK_CONN36_1 (0x42d4)
+#define AFE_SECURE_MASK_CONN36_2 (0x42d8)
+#define AFE_SECURE_MASK_CONN36_3 (0x42dc)
+#define AFE_SECURE_MASK_CONN36_4 (0x42e0)
+#define AFE_SECURE_MASK_CONN37 (0x42e4)
+#define AFE_SECURE_MASK_CONN37_1 (0x42e8)
+#define AFE_SECURE_MASK_CONN37_2 (0x42ec)
+#define AFE_SECURE_MASK_CONN37_3 (0x42f0)
+#define AFE_SECURE_MASK_CONN37_4 (0x42f4)
+#define AFE_SECURE_MASK_CONN38 (0x42f8)
+#define AFE_SECURE_MASK_CONN38_1 (0x42fc)
+#define AFE_SECURE_MASK_CONN38_2 (0x4300)
+#define AFE_SECURE_MASK_CONN38_3 (0x4304)
+#define AFE_SECURE_MASK_CONN38_4 (0x4308)
+#define AFE_SECURE_MASK_CONN39 (0x430c)
+#define AFE_SECURE_MASK_CONN39_1 (0x4310)
+#define AFE_SECURE_MASK_CONN39_2 (0x4314)
+#define AFE_SECURE_MASK_CONN39_3 (0x4318)
+#define AFE_SECURE_MASK_CONN39_4 (0x431c)
+#define AFE_SECURE_MASK_CONN40 (0x4320)
+#define AFE_SECURE_MASK_CONN40_1 (0x4324)
+#define AFE_SECURE_MASK_CONN40_2 (0x4328)
+#define AFE_SECURE_MASK_CONN40_3 (0x432c)
+#define AFE_SECURE_MASK_CONN40_4 (0x4330)
+#define AFE_SECURE_MASK_CONN41 (0x4334)
+#define AFE_SECURE_MASK_CONN41_1 (0x4338)
+#define AFE_SECURE_MASK_CONN41_2 (0x433c)
+#define AFE_SECURE_MASK_CONN41_3 (0x4340)
+#define AFE_SECURE_MASK_CONN41_4 (0x4344)
+#define AFE_SECURE_MASK_CONN42 (0x4348)
+#define AFE_SECURE_MASK_CONN42_1 (0x434c)
+#define AFE_SECURE_MASK_CONN42_2 (0x4350)
+#define AFE_SECURE_MASK_CONN42_3 (0x4354)
+#define AFE_SECURE_MASK_CONN42_4 (0x4358)
+#define AFE_SECURE_MASK_CONN43 (0x435c)
+#define AFE_SECURE_MASK_CONN43_1 (0x4360)
+#define AFE_SECURE_MASK_CONN43_2 (0x4364)
+#define AFE_SECURE_MASK_CONN43_3 (0x4368)
+#define AFE_SECURE_MASK_CONN43_4 (0x436c)
+#define AFE_SECURE_MASK_CONN44 (0x4370)
+#define AFE_SECURE_MASK_CONN44_1 (0x4374)
+#define AFE_SECURE_MASK_CONN44_2 (0x4378)
+#define AFE_SECURE_MASK_CONN44_3 (0x437c)
+#define AFE_SECURE_MASK_CONN44_4 (0x4380)
+#define AFE_SECURE_MASK_CONN45 (0x4384)
+#define AFE_SECURE_MASK_CONN45_1 (0x4388)
+#define AFE_SECURE_MASK_CONN45_2 (0x438c)
+#define AFE_SECURE_MASK_CONN45_3 (0x4390)
+#define AFE_SECURE_MASK_CONN45_4 (0x4394)
+#define AFE_SECURE_MASK_CONN46 (0x4398)
+#define AFE_SECURE_MASK_CONN46_1 (0x439c)
+#define AFE_SECURE_MASK_CONN46_2 (0x43a0)
+#define AFE_SECURE_MASK_CONN46_3 (0x43a4)
+#define AFE_SECURE_MASK_CONN46_4 (0x43a8)
+#define AFE_SECURE_MASK_CONN47 (0x43ac)
+#define AFE_SECURE_MASK_CONN47_1 (0x43b0)
+#define AFE_SECURE_MASK_CONN47_2 (0x43b4)
+#define AFE_SECURE_MASK_CONN47_3 (0x43b8)
+#define AFE_SECURE_MASK_CONN47_4 (0x43bc)
+#define AFE_SECURE_MASK_CONN48 (0x43c0)
+#define AFE_SECURE_MASK_CONN48_1 (0x43c4)
+#define AFE_SECURE_MASK_CONN48_2 (0x43c8)
+#define AFE_SECURE_MASK_CONN48_3 (0x43cc)
+#define AFE_SECURE_MASK_CONN48_4 (0x43d0)
+#define AFE_SECURE_MASK_CONN49 (0x43d4)
+#define AFE_SECURE_MASK_CONN49_1 (0x43d8)
+#define AFE_SECURE_MASK_CONN49_2 (0x43dc)
+#define AFE_SECURE_MASK_CONN49_3 (0x43e0)
+#define AFE_SECURE_MASK_CONN49_4 (0x43e4)
+#define AFE_SECURE_MASK_CONN50 (0x43e8)
+#define AFE_SECURE_MASK_CONN50_1 (0x43ec)
+#define AFE_SECURE_MASK_CONN50_2 (0x43f0)
+#define AFE_SECURE_MASK_CONN50_3 (0x43f4)
+#define AFE_SECURE_MASK_CONN50_4 (0x43f8)
+#define AFE_SECURE_MASK_CONN51 (0x43fc)
+#define AFE_SECURE_MASK_CONN51_1 (0x4400)
+#define AFE_SECURE_MASK_CONN51_2 (0x4404)
+#define AFE_SECURE_MASK_CONN51_3 (0x4408)
+#define AFE_SECURE_MASK_CONN51_4 (0x440c)
+#define AFE_SECURE_MASK_CONN52 (0x4410)
+#define AFE_SECURE_MASK_CONN52_1 (0x4414)
+#define AFE_SECURE_MASK_CONN52_2 (0x4418)
+#define AFE_SECURE_MASK_CONN52_3 (0x441c)
+#define AFE_SECURE_MASK_CONN52_4 (0x4420)
+#define AFE_SECURE_MASK_CONN53 (0x4424)
+#define AFE_SECURE_MASK_CONN53_1 (0x4428)
+#define AFE_SECURE_MASK_CONN53_2 (0x442c)
+#define AFE_SECURE_MASK_CONN53_3 (0x4430)
+#define AFE_SECURE_MASK_CONN53_4 (0x4434)
+#define AFE_SECURE_MASK_CONN54 (0x4438)
+#define AFE_SECURE_MASK_CONN54_1 (0x443c)
+#define AFE_SECURE_MASK_CONN54_2 (0x4440)
+#define AFE_SECURE_MASK_CONN54_3 (0x4444)
+#define AFE_SECURE_MASK_CONN54_4 (0x4448)
+#define AFE_SECURE_MASK_CONN55 (0x444c)
+#define AFE_SECURE_MASK_CONN55_1 (0x4450)
+#define AFE_SECURE_MASK_CONN55_2 (0x4454)
+#define AFE_SECURE_MASK_CONN55_3 (0x4458)
+#define AFE_SECURE_MASK_CONN55_4 (0x445c)
+#define AFE_SECURE_MASK_CONN56 (0x4460)
+#define AFE_SECURE_MASK_CONN56_1 (0x4464)
+#define AFE_SECURE_MASK_CONN56_2 (0x4468)
+#define AFE_SECURE_MASK_CONN56_3 (0x446c)
+#define AFE_SECURE_MASK_CONN56_4 (0x4470)
+#define AFE_SECURE_MASK_CONN57 (0x4474)
+#define AFE_SECURE_MASK_CONN57_1 (0x4478)
+#define AFE_SECURE_MASK_CONN57_2 (0x447c)
+#define AFE_SECURE_MASK_CONN57_3 (0x4480)
+#define AFE_SECURE_MASK_CONN57_4 (0x4484)
+#define AFE_SECURE_MASK_CONN58 (0x4488)
+#define AFE_SECURE_MASK_CONN58_1 (0x448c)
+#define AFE_SECURE_MASK_CONN58_2 (0x4490)
+#define AFE_SECURE_MASK_CONN58_3 (0x4494)
+#define AFE_SECURE_MASK_CONN58_4 (0x4498)
+#define AFE_SECURE_MASK_CONN59 (0x449c)
+#define AFE_SECURE_MASK_CONN59_1 (0x44a0)
+#define AFE_SECURE_MASK_CONN59_2 (0x44a4)
+#define AFE_SECURE_MASK_CONN59_3 (0x44a8)
+#define AFE_SECURE_MASK_CONN59_4 (0x44ac)
+#define AFE_SECURE_MASK_CONN60 (0x44b0)
+#define AFE_SECURE_MASK_CONN60_1 (0x44b4)
+#define AFE_SECURE_MASK_CONN60_2 (0x44b8)
+#define AFE_SECURE_MASK_CONN60_3 (0x44bc)
+#define AFE_SECURE_MASK_CONN60_4 (0x44c0)
+#define AFE_SECURE_MASK_CONN61 (0x44c4)
+#define AFE_SECURE_MASK_CONN61_1 (0x44c8)
+#define AFE_SECURE_MASK_CONN61_2 (0x44cc)
+#define AFE_SECURE_MASK_CONN61_3 (0x44d0)
+#define AFE_SECURE_MASK_CONN61_4 (0x44d4)
+#define AFE_SECURE_MASK_CONN62 (0x44d8)
+#define AFE_SECURE_MASK_CONN62_1 (0x44dc)
+#define AFE_SECURE_MASK_CONN62_2 (0x44e0)
+#define AFE_SECURE_MASK_CONN62_3 (0x44e4)
+#define AFE_SECURE_MASK_CONN62_4 (0x44e8)
+#define AFE_SECURE_MASK_CONN63 (0x44ec)
+#define AFE_SECURE_MASK_CONN63_1 (0x44f0)
+#define AFE_SECURE_MASK_CONN63_2 (0x44f4)
+#define AFE_SECURE_MASK_CONN63_3 (0x44f8)
+#define AFE_SECURE_MASK_CONN63_4 (0x44fc)
+#define AFE_SECURE_MASK_CONN64 (0x4500)
+#define AFE_SECURE_MASK_CONN64_1 (0x4504)
+#define AFE_SECURE_MASK_CONN64_2 (0x4508)
+#define AFE_SECURE_MASK_CONN64_3 (0x450c)
+#define AFE_SECURE_MASK_CONN64_4 (0x4510)
+#define AFE_SECURE_MASK_CONN65 (0x4514)
+#define AFE_SECURE_MASK_CONN65_1 (0x4518)
+#define AFE_SECURE_MASK_CONN65_2 (0x451c)
+#define AFE_SECURE_MASK_CONN65_3 (0x4520)
+#define AFE_SECURE_MASK_CONN65_4 (0x4524)
+#define AFE_SECURE_MASK_CONN66 (0x4528)
+#define AFE_SECURE_MASK_CONN66_1 (0x452c)
+#define AFE_SECURE_MASK_CONN66_2 (0x4530)
+#define AFE_SECURE_MASK_CONN66_3 (0x4534)
+#define AFE_SECURE_MASK_CONN66_4 (0x4538)
+#define AFE_SECURE_MASK_CONN67 (0x453c)
+#define AFE_SECURE_MASK_CONN67_1 (0x4540)
+#define AFE_SECURE_MASK_CONN67_2 (0x4544)
+#define AFE_SECURE_MASK_CONN67_3 (0x4548)
+#define AFE_SECURE_MASK_CONN67_4 (0x454c)
+#define AFE_SECURE_MASK_CONN68 (0x4550)
+#define AFE_SECURE_MASK_CONN68_1 (0x4554)
+#define AFE_SECURE_MASK_CONN68_2 (0x4558)
+#define AFE_SECURE_MASK_CONN68_3 (0x455c)
+#define AFE_SECURE_MASK_CONN68_4 (0x4560)
+#define AFE_SECURE_MASK_CONN69 (0x4564)
+#define AFE_SECURE_MASK_CONN69_1 (0x4568)
+#define AFE_SECURE_MASK_CONN69_2 (0x456c)
+#define AFE_SECURE_MASK_CONN69_3 (0x4570)
+#define AFE_SECURE_MASK_CONN69_4 (0x4574)
+#define AFE_SECURE_MASK_CONN70 (0x4578)
+#define AFE_SECURE_MASK_CONN70_1 (0x457c)
+#define AFE_SECURE_MASK_CONN70_2 (0x4580)
+#define AFE_SECURE_MASK_CONN70_3 (0x4584)
+#define AFE_SECURE_MASK_CONN70_4 (0x4588)
+#define AFE_SECURE_MASK_CONN71 (0x458c)
+#define AFE_SECURE_MASK_CONN71_1 (0x4590)
+#define AFE_SECURE_MASK_CONN71_2 (0x4594)
+#define AFE_SECURE_MASK_CONN71_3 (0x4598)
+#define AFE_SECURE_MASK_CONN71_4 (0x459c)
+#define AFE_SECURE_MASK_CONN72 (0x45a0)
+#define AFE_SECURE_MASK_CONN72_1 (0x45a4)
+#define AFE_SECURE_MASK_CONN72_2 (0x45a8)
+#define AFE_SECURE_MASK_CONN72_3 (0x45ac)
+#define AFE_SECURE_MASK_CONN72_4 (0x45b0)
+#define AFE_SECURE_MASK_CONN73 (0x45b4)
+#define AFE_SECURE_MASK_CONN73_1 (0x45b8)
+#define AFE_SECURE_MASK_CONN73_2 (0x45bc)
+#define AFE_SECURE_MASK_CONN73_3 (0x45c0)
+#define AFE_SECURE_MASK_CONN73_4 (0x45c4)
+#define AFE_SECURE_MASK_CONN74 (0x45c8)
+#define AFE_SECURE_MASK_CONN74_1 (0x45cc)
+#define AFE_SECURE_MASK_CONN74_2 (0x45d0)
+#define AFE_SECURE_MASK_CONN74_3 (0x45d4)
+#define AFE_SECURE_MASK_CONN74_4 (0x45d8)
+#define AFE_SECURE_MASK_CONN75 (0x45dc)
+#define AFE_SECURE_MASK_CONN75_1 (0x45e0)
+#define AFE_SECURE_MASK_CONN75_2 (0x45e4)
+#define AFE_SECURE_MASK_CONN75_3 (0x45e8)
+#define AFE_SECURE_MASK_CONN75_4 (0x45ec)
+#define AFE_SECURE_MASK_CONN76 (0x45f0)
+#define AFE_SECURE_MASK_CONN76_1 (0x45f4)
+#define AFE_SECURE_MASK_CONN76_2 (0x45f8)
+#define AFE_SECURE_MASK_CONN76_3 (0x45fc)
+#define AFE_SECURE_MASK_CONN76_4 (0x4600)
+#define AFE_SECURE_MASK_CONN77 (0x4604)
+#define AFE_SECURE_MASK_CONN77_1 (0x4608)
+#define AFE_SECURE_MASK_CONN77_2 (0x460c)
+#define AFE_SECURE_MASK_CONN77_3 (0x4610)
+#define AFE_SECURE_MASK_CONN77_4 (0x4614)
+#define AFE_SECURE_MASK_CONN78 (0x4618)
+#define AFE_SECURE_MASK_CONN78_1 (0x461c)
+#define AFE_SECURE_MASK_CONN78_2 (0x4620)
+#define AFE_SECURE_MASK_CONN78_3 (0x4624)
+#define AFE_SECURE_MASK_CONN78_4 (0x4628)
+#define AFE_SECURE_MASK_CONN79 (0x462c)
+#define AFE_SECURE_MASK_CONN79_1 (0x4630)
+#define AFE_SECURE_MASK_CONN79_2 (0x4634)
+#define AFE_SECURE_MASK_CONN79_3 (0x4638)
+#define AFE_SECURE_MASK_CONN79_4 (0x463c)
+#define AFE_SECURE_MASK_CONN80 (0x4640)
+#define AFE_SECURE_MASK_CONN80_1 (0x4644)
+#define AFE_SECURE_MASK_CONN80_2 (0x4648)
+#define AFE_SECURE_MASK_CONN80_3 (0x464c)
+#define AFE_SECURE_MASK_CONN80_4 (0x4650)
+#define AFE_SECURE_MASK_CONN81 (0x4654)
+#define AFE_SECURE_MASK_CONN81_1 (0x4658)
+#define AFE_SECURE_MASK_CONN81_2 (0x465c)
+#define AFE_SECURE_MASK_CONN81_3 (0x4660)
+#define AFE_SECURE_MASK_CONN81_4 (0x4664)
+#define AFE_SECURE_MASK_CONN82 (0x4668)
+#define AFE_SECURE_MASK_CONN82_1 (0x466c)
+#define AFE_SECURE_MASK_CONN82_2 (0x4670)
+#define AFE_SECURE_MASK_CONN82_3 (0x4674)
+#define AFE_SECURE_MASK_CONN82_4 (0x4678)
+#define AFE_SECURE_MASK_CONN83 (0x467c)
+#define AFE_SECURE_MASK_CONN83_1 (0x4680)
+#define AFE_SECURE_MASK_CONN83_2 (0x4684)
+#define AFE_SECURE_MASK_CONN83_3 (0x4688)
+#define AFE_SECURE_MASK_CONN83_4 (0x468c)
+#define AFE_SECURE_MASK_CONN84 (0x4690)
+#define AFE_SECURE_MASK_CONN84_1 (0x4694)
+#define AFE_SECURE_MASK_CONN84_2 (0x4698)
+#define AFE_SECURE_MASK_CONN84_3 (0x469c)
+#define AFE_SECURE_MASK_CONN84_4 (0x46a0)
+#define AFE_SECURE_MASK_CONN85 (0x46a4)
+#define AFE_SECURE_MASK_CONN85_1 (0x46a8)
+#define AFE_SECURE_MASK_CONN85_2 (0x46ac)
+#define AFE_SECURE_MASK_CONN85_3 (0x46b0)
+#define AFE_SECURE_MASK_CONN85_4 (0x46b4)
+#define AFE_SECURE_MASK_CONN86 (0x46b8)
+#define AFE_SECURE_MASK_CONN86_1 (0x46bc)
+#define AFE_SECURE_MASK_CONN86_2 (0x46c0)
+#define AFE_SECURE_MASK_CONN86_3 (0x46c4)
+#define AFE_SECURE_MASK_CONN86_4 (0x46c8)
+#define AFE_SECURE_MASK_CONN87 (0x46cc)
+#define AFE_SECURE_MASK_CONN87_1 (0x46d0)
+#define AFE_SECURE_MASK_CONN87_2 (0x46d4)
+#define AFE_SECURE_MASK_CONN87_3 (0x46d8)
+#define AFE_SECURE_MASK_CONN87_4 (0x46dc)
+#define AFE_SECURE_MASK_CONN88 (0x46e0)
+#define AFE_SECURE_MASK_CONN88_1 (0x46e4)
+#define AFE_SECURE_MASK_CONN88_2 (0x46e8)
+#define AFE_SECURE_MASK_CONN88_3 (0x46ec)
+#define AFE_SECURE_MASK_CONN88_4 (0x46f0)
+#define AFE_SECURE_MASK_CONN89 (0x46f4)
+#define AFE_SECURE_MASK_CONN89_1 (0x46f8)
+#define AFE_SECURE_MASK_CONN89_2 (0x46fc)
+#define AFE_SECURE_MASK_CONN89_3 (0x4700)
+#define AFE_SECURE_MASK_CONN89_4 (0x4704)
+#define AFE_SECURE_MASK_CONN90 (0x4708)
+#define AFE_SECURE_MASK_CONN90_1 (0x470c)
+#define AFE_SECURE_MASK_CONN90_2 (0x4710)
+#define AFE_SECURE_MASK_CONN90_3 (0x4714)
+#define AFE_SECURE_MASK_CONN90_4 (0x4718)
+#define AFE_SECURE_MASK_CONN91 (0x471c)
+#define AFE_SECURE_MASK_CONN91_1 (0x4720)
+#define AFE_SECURE_MASK_CONN91_2 (0x4724)
+#define AFE_SECURE_MASK_CONN91_3 (0x4728)
+#define AFE_SECURE_MASK_CONN91_4 (0x472c)
+#define AFE_SECURE_MASK_CONN92 (0x4730)
+#define AFE_SECURE_MASK_CONN92_1 (0x4734)
+#define AFE_SECURE_MASK_CONN92_2 (0x4738)
+#define AFE_SECURE_MASK_CONN92_3 (0x473c)
+#define AFE_SECURE_MASK_CONN92_4 (0x4740)
+#define AFE_SECURE_MASK_CONN93 (0x4744)
+#define AFE_SECURE_MASK_CONN93_1 (0x4748)
+#define AFE_SECURE_MASK_CONN93_2 (0x474c)
+#define AFE_SECURE_MASK_CONN93_3 (0x4750)
+#define AFE_SECURE_MASK_CONN93_4 (0x4754)
+#define AFE_SECURE_MASK_CONN94 (0x4758)
+#define AFE_SECURE_MASK_CONN94_1 (0x475c)
+#define AFE_SECURE_MASK_CONN94_2 (0x4760)
+#define AFE_SECURE_MASK_CONN94_3 (0x4764)
+#define AFE_SECURE_MASK_CONN94_4 (0x4768)
+#define AFE_SECURE_MASK_CONN95 (0x476c)
+#define AFE_SECURE_MASK_CONN95_1 (0x4770)
+#define AFE_SECURE_MASK_CONN95_2 (0x4774)
+#define AFE_SECURE_MASK_CONN95_3 (0x4778)
+#define AFE_SECURE_MASK_CONN95_4 (0x477c)
+#define AFE_SECURE_MASK_CONN96 (0x4780)
+#define AFE_SECURE_MASK_CONN96_1 (0x4784)
+#define AFE_SECURE_MASK_CONN96_2 (0x4788)
+#define AFE_SECURE_MASK_CONN96_3 (0x478c)
+#define AFE_SECURE_MASK_CONN96_4 (0x4790)
+#define AFE_SECURE_MASK_CONN97 (0x4794)
+#define AFE_SECURE_MASK_CONN97_1 (0x4798)
+#define AFE_SECURE_MASK_CONN97_2 (0x479c)
+#define AFE_SECURE_MASK_CONN97_3 (0x47a0)
+#define AFE_SECURE_MASK_CONN97_4 (0x47a4)
+#define AFE_SECURE_MASK_CONN98 (0x47a8)
+#define AFE_SECURE_MASK_CONN98_1 (0x47ac)
+#define AFE_SECURE_MASK_CONN98_2 (0x47b0)
+#define AFE_SECURE_MASK_CONN98_3 (0x47b4)
+#define AFE_SECURE_MASK_CONN98_4 (0x47b8)
+#define AFE_SECURE_MASK_CONN99 (0x47bc)
+#define AFE_SECURE_MASK_CONN99_1 (0x47c0)
+#define AFE_SECURE_MASK_CONN99_2 (0x47c4)
+#define AFE_SECURE_MASK_CONN99_3 (0x47c8)
+#define AFE_SECURE_MASK_CONN99_4 (0x47cc)
+#define AFE_SECURE_MASK_CONN100 (0x47d0)
+#define AFE_SECURE_MASK_CONN100_1 (0x47d4)
+#define AFE_SECURE_MASK_CONN100_2 (0x47d8)
+#define AFE_SECURE_MASK_CONN100_3 (0x47dc)
+#define AFE_SECURE_MASK_CONN100_4 (0x47e0)
+#define AFE_SECURE_MASK_CONN101 (0x47e4)
+#define AFE_SECURE_MASK_CONN101_1 (0x47e8)
+#define AFE_SECURE_MASK_CONN101_2 (0x47ec)
+#define AFE_SECURE_MASK_CONN101_3 (0x47f0)
+#define AFE_SECURE_MASK_CONN101_4 (0x47f4)
+#define AFE_SECURE_MASK_CONN102 (0x47f8)
+#define AFE_SECURE_MASK_CONN102_1 (0x47fc)
+#define AFE_SECURE_MASK_CONN102_2 (0x4800)
+#define AFE_SECURE_MASK_CONN102_3 (0x4804)
+#define AFE_SECURE_MASK_CONN102_4 (0x4808)
+#define AFE_SECURE_MASK_CONN103 (0x480c)
+#define AFE_SECURE_MASK_CONN103_1 (0x4810)
+#define AFE_SECURE_MASK_CONN103_2 (0x4814)
+#define AFE_SECURE_MASK_CONN103_3 (0x4818)
+#define AFE_SECURE_MASK_CONN103_4 (0x481c)
+#define AFE_SECURE_MASK_CONN104 (0x4820)
+#define AFE_SECURE_MASK_CONN104_1 (0x4824)
+#define AFE_SECURE_MASK_CONN104_2 (0x4828)
+#define AFE_SECURE_MASK_CONN104_3 (0x482c)
+#define AFE_SECURE_MASK_CONN104_4 (0x4830)
+#define AFE_SECURE_MASK_CONN105 (0x4834)
+#define AFE_SECURE_MASK_CONN105_1 (0x4838)
+#define AFE_SECURE_MASK_CONN105_2 (0x483c)
+#define AFE_SECURE_MASK_CONN105_3 (0x4840)
+#define AFE_SECURE_MASK_CONN105_4 (0x4844)
+#define AFE_SECURE_MASK_CONN106 (0x4848)
+#define AFE_SECURE_MASK_CONN106_1 (0x484c)
+#define AFE_SECURE_MASK_CONN106_2 (0x4850)
+#define AFE_SECURE_MASK_CONN106_3 (0x4854)
+#define AFE_SECURE_MASK_CONN106_4 (0x4858)
+#define AFE_SECURE_MASK_CONN107 (0x485c)
+#define AFE_SECURE_MASK_CONN107_1 (0x4860)
+#define AFE_SECURE_MASK_CONN107_2 (0x4864)
+#define AFE_SECURE_MASK_CONN107_3 (0x4868)
+#define AFE_SECURE_MASK_CONN107_4 (0x486c)
+#define AFE_SECURE_MASK_CONN108 (0x4870)
+#define AFE_SECURE_MASK_CONN108_1 (0x4874)
+#define AFE_SECURE_MASK_CONN108_2 (0x4878)
+#define AFE_SECURE_MASK_CONN108_3 (0x487c)
+#define AFE_SECURE_MASK_CONN108_4 (0x4880)
+#define AFE_SECURE_MASK_CONN109 (0x4884)
+#define AFE_SECURE_MASK_CONN109_1 (0x4888)
+#define AFE_SECURE_MASK_CONN109_2 (0x488c)
+#define AFE_SECURE_MASK_CONN109_3 (0x4890)
+#define AFE_SECURE_MASK_CONN109_4 (0x4894)
+#define AFE_SECURE_MASK_CONN110 (0x4898)
+#define AFE_SECURE_MASK_CONN110_1 (0x489c)
+#define AFE_SECURE_MASK_CONN110_2 (0x48a0)
+#define AFE_SECURE_MASK_CONN110_3 (0x48a4)
+#define AFE_SECURE_MASK_CONN110_4 (0x48a8)
+#define AFE_SECURE_MASK_CONN111 (0x48ac)
+#define AFE_SECURE_MASK_CONN111_1 (0x48b0)
+#define AFE_SECURE_MASK_CONN111_2 (0x48b4)
+#define AFE_SECURE_MASK_CONN111_3 (0x48b8)
+#define AFE_SECURE_MASK_CONN111_4 (0x48bc)
+#define AFE_SECURE_MASK_CONN112 (0x48c0)
+#define AFE_SECURE_MASK_CONN112_1 (0x48c4)
+#define AFE_SECURE_MASK_CONN112_2 (0x48c8)
+#define AFE_SECURE_MASK_CONN112_3 (0x48cc)
+#define AFE_SECURE_MASK_CONN112_4 (0x48d0)
+#define AFE_SECURE_MASK_CONN113 (0x48d4)
+#define AFE_SECURE_MASK_CONN113_1 (0x48d8)
+#define AFE_SECURE_MASK_CONN113_2 (0x48dc)
+#define AFE_SECURE_MASK_CONN113_3 (0x48e0)
+#define AFE_SECURE_MASK_CONN113_4 (0x48e4)
+#define AFE_SECURE_MASK_CONN114 (0x48e8)
+#define AFE_SECURE_MASK_CONN114_1 (0x48ec)
+#define AFE_SECURE_MASK_CONN114_2 (0x48f0)
+#define AFE_SECURE_MASK_CONN114_3 (0x48f4)
+#define AFE_SECURE_MASK_CONN114_4 (0x48f8)
+#define AFE_SECURE_MASK_CONN115 (0x48fc)
+#define AFE_SECURE_MASK_CONN115_1 (0x4900)
+#define AFE_SECURE_MASK_CONN115_2 (0x4904)
+#define AFE_SECURE_MASK_CONN115_3 (0x4908)
+#define AFE_SECURE_MASK_CONN115_4 (0x490c)
+#define AFE_SECURE_MASK_CONN116 (0x4910)
+#define AFE_SECURE_MASK_CONN116_1 (0x4914)
+#define AFE_SECURE_MASK_CONN116_2 (0x4918)
+#define AFE_SECURE_MASK_CONN116_3 (0x491c)
+#define AFE_SECURE_MASK_CONN116_4 (0x4920)
+#define AFE_SECURE_MASK_CONN117 (0x4924)
+#define AFE_SECURE_MASK_CONN117_1 (0x4928)
+#define AFE_SECURE_MASK_CONN117_2 (0x492c)
+#define AFE_SECURE_MASK_CONN117_3 (0x4930)
+#define AFE_SECURE_MASK_CONN117_4 (0x4934)
+#define AFE_SECURE_MASK_CONN118 (0x4938)
+#define AFE_SECURE_MASK_CONN118_1 (0x493c)
+#define AFE_SECURE_MASK_CONN118_2 (0x4940)
+#define AFE_SECURE_MASK_CONN118_3 (0x4944)
+#define AFE_SECURE_MASK_CONN118_4 (0x4948)
+#define AFE_SECURE_MASK_CONN119 (0x494c)
+#define AFE_SECURE_MASK_CONN119_1 (0x4950)
+#define AFE_SECURE_MASK_CONN119_2 (0x4954)
+#define AFE_SECURE_MASK_CONN119_3 (0x4958)
+#define AFE_SECURE_MASK_CONN119_4 (0x495c)
+#define AFE_SECURE_MASK_CONN120 (0x4960)
+#define AFE_SECURE_MASK_CONN120_1 (0x4964)
+#define AFE_SECURE_MASK_CONN120_2 (0x4968)
+#define AFE_SECURE_MASK_CONN120_3 (0x496c)
+#define AFE_SECURE_MASK_CONN120_4 (0x4970)
+#define AFE_SECURE_MASK_CONN121 (0x4974)
+#define AFE_SECURE_MASK_CONN121_1 (0x4978)
+#define AFE_SECURE_MASK_CONN121_2 (0x497c)
+#define AFE_SECURE_MASK_CONN121_3 (0x4980)
+#define AFE_SECURE_MASK_CONN121_4 (0x4984)
+#define AFE_SECURE_MASK_CONN122 (0x4988)
+#define AFE_SECURE_MASK_CONN122_1 (0x498c)
+#define AFE_SECURE_MASK_CONN122_2 (0x4990)
+#define AFE_SECURE_MASK_CONN122_3 (0x4994)
+#define AFE_SECURE_MASK_CONN122_4 (0x4998)
+#define AFE_SECURE_MASK_CONN123 (0x499c)
+#define AFE_SECURE_MASK_CONN123_1 (0x49a0)
+#define AFE_SECURE_MASK_CONN123_2 (0x49a4)
+#define AFE_SECURE_MASK_CONN123_3 (0x49a8)
+#define AFE_SECURE_MASK_CONN123_4 (0x49ac)
+#define AFE_SECURE_MASK_CONN124 (0x49b0)
+#define AFE_SECURE_MASK_CONN124_1 (0x49b4)
+#define AFE_SECURE_MASK_CONN124_2 (0x49b8)
+#define AFE_SECURE_MASK_CONN124_3 (0x49bc)
+#define AFE_SECURE_MASK_CONN124_4 (0x49c0)
+#define AFE_SECURE_MASK_CONN125 (0x49c4)
+#define AFE_SECURE_MASK_CONN125_1 (0x49c8)
+#define AFE_SECURE_MASK_CONN125_2 (0x49cc)
+#define AFE_SECURE_MASK_CONN125_3 (0x49d0)
+#define AFE_SECURE_MASK_CONN125_4 (0x49d4)
+#define AFE_SECURE_MASK_CONN126 (0x49d8)
+#define AFE_SECURE_MASK_CONN126_1 (0x49dc)
+#define AFE_SECURE_MASK_CONN126_2 (0x49e0)
+#define AFE_SECURE_MASK_CONN126_3 (0x49e4)
+#define AFE_SECURE_MASK_CONN126_4 (0x49e8)
+#define AFE_SECURE_MASK_CONN127 (0x49ec)
+#define AFE_SECURE_MASK_CONN127_1 (0x49f0)
+#define AFE_SECURE_MASK_CONN127_2 (0x49f4)
+#define AFE_SECURE_MASK_CONN127_3 (0x49f8)
+#define AFE_SECURE_MASK_CONN127_4 (0x49fc)
+#define AFE_SECURE_MASK_CONN128 (0x4a00)
+#define AFE_SECURE_MASK_CONN128_1 (0x4a04)
+#define AFE_SECURE_MASK_CONN128_2 (0x4a08)
+#define AFE_SECURE_MASK_CONN128_3 (0x4a0c)
+#define AFE_SECURE_MASK_CONN128_4 (0x4a10)
+#define AFE_SECURE_MASK_CONN129 (0x4a14)
+#define AFE_SECURE_MASK_CONN129_1 (0x4a18)
+#define AFE_SECURE_MASK_CONN129_2 (0x4a1c)
+#define AFE_SECURE_MASK_CONN129_3 (0x4a20)
+#define AFE_SECURE_MASK_CONN129_4 (0x4a24)
+#define AFE_SECURE_MASK_CONN130 (0x4a28)
+#define AFE_SECURE_MASK_CONN130_1 (0x4a2c)
+#define AFE_SECURE_MASK_CONN130_2 (0x4a30)
+#define AFE_SECURE_MASK_CONN130_3 (0x4a34)
+#define AFE_SECURE_MASK_CONN130_4 (0x4a38)
+#define AFE_SECURE_MASK_CONN131 (0x4a3c)
+#define AFE_SECURE_MASK_CONN131_1 (0x4a40)
+#define AFE_SECURE_MASK_CONN131_2 (0x4a44)
+#define AFE_SECURE_MASK_CONN131_3 (0x4a48)
+#define AFE_SECURE_MASK_CONN131_4 (0x4a4c)
+#define AFE_SECURE_MASK_CONN132 (0x4a50)
+#define AFE_SECURE_MASK_CONN132_1 (0x4a54)
+#define AFE_SECURE_MASK_CONN132_2 (0x4a58)
+#define AFE_SECURE_MASK_CONN132_3 (0x4a5c)
+#define AFE_SECURE_MASK_CONN132_4 (0x4a60)
+#define AFE_SECURE_MASK_CONN133 (0x4a64)
+#define AFE_SECURE_MASK_CONN133_1 (0x4a68)
+#define AFE_SECURE_MASK_CONN133_2 (0x4a6c)
+#define AFE_SECURE_MASK_CONN133_3 (0x4a70)
+#define AFE_SECURE_MASK_CONN133_4 (0x4a74)
+#define AFE_SECURE_MASK_CONN134 (0x4a78)
+#define AFE_SECURE_MASK_CONN134_1 (0x4a7c)
+#define AFE_SECURE_MASK_CONN134_2 (0x4a80)
+#define AFE_SECURE_MASK_CONN134_3 (0x4a84)
+#define AFE_SECURE_MASK_CONN134_4 (0x4a88)
+#define AFE_SECURE_MASK_CONN135 (0x4a8c)
+#define AFE_SECURE_MASK_CONN135_1 (0x4a90)
+#define AFE_SECURE_MASK_CONN135_2 (0x4a94)
+#define AFE_SECURE_MASK_CONN135_3 (0x4a98)
+#define AFE_SECURE_MASK_CONN135_4 (0x4a9c)
+#define AFE_SECURE_MASK_CONN136 (0x4aa0)
+#define AFE_SECURE_MASK_CONN136_1 (0x4aa4)
+#define AFE_SECURE_MASK_CONN136_2 (0x4aa8)
+#define AFE_SECURE_MASK_CONN136_3 (0x4aac)
+#define AFE_SECURE_MASK_CONN136_4 (0x4ab0)
+#define AFE_SECURE_MASK_CONN137 (0x4ab4)
+#define AFE_SECURE_MASK_CONN137_1 (0x4ab8)
+#define AFE_SECURE_MASK_CONN137_2 (0x4abc)
+#define AFE_SECURE_MASK_CONN137_3 (0x4ac0)
+#define AFE_SECURE_MASK_CONN137_4 (0x4ac4)
+#define AFE_SECURE_MASK_CONN138 (0x4ac8)
+#define AFE_SECURE_MASK_CONN138_1 (0x4acc)
+#define AFE_SECURE_MASK_CONN138_2 (0x4ad0)
+#define AFE_SECURE_MASK_CONN138_3 (0x4ad4)
+#define AFE_SECURE_MASK_CONN138_4 (0x4ad8)
+#define AFE_SECURE_MASK_CONN139 (0x4adc)
+#define AFE_SECURE_MASK_CONN139_1 (0x4ae0)
+#define AFE_SECURE_MASK_CONN139_2 (0x4ae4)
+#define AFE_SECURE_MASK_CONN139_3 (0x4ae8)
+#define AFE_SECURE_MASK_CONN139_4 (0x4aec)
+#define AFE_SECURE_MASK_CONN_RS (0x4af0)
+#define AFE_SECURE_MASK_CONN_RS_1 (0x4af4)
+#define AFE_SECURE_MASK_CONN_RS_2 (0x4af8)
+#define AFE_SECURE_MASK_CONN_RS_3 (0x4afc)
+#define AFE_SECURE_MASK_CONN_RS_4 (0x4b00)
+#define AFE_SECURE_MASK_CONN_16BIT (0x4b04)
+#define AFE_SECURE_MASK_CONN_16BIT_1 (0x4b08)
+#define AFE_SECURE_MASK_CONN_16BIT_2 (0x4b0c)
+#define AFE_SECURE_MASK_CONN_16BIT_3 (0x4b10)
+#define AFE_SECURE_MASK_CONN_16BIT_4 (0x4b14)
+#define AFE_SECURE_MASK_CONN_24BIT (0x4b18)
+#define AFE_SECURE_MASK_CONN_24BIT_1 (0x4b1c)
+#define AFE_SECURE_MASK_CONN_24BIT_2 (0x4b20)
+#define AFE_SECURE_MASK_CONN_24BIT_3 (0x4b24)
+#define AFE_SECURE_MASK_CONN_24BIT_4 (0x4b28)
+#define AFE_GASRC0_NEW_CON0 (0x4c40)
+#define AFE_GASRC0_NEW_CON1 (0x4c44)
+#define AFE_GASRC0_NEW_CON2 (0x4c48)
+#define AFE_GASRC0_NEW_CON3 (0x4c4c)
+#define AFE_GASRC0_NEW_CON4 (0x4c50)
+#define AFE_GASRC0_NEW_CON5 (0x4c54)
+#define AFE_GASRC0_NEW_CON6 (0x4c58)
+#define AFE_GASRC0_NEW_CON7 (0x4c5c)
+#define AFE_GASRC0_NEW_CON8 (0x4c60)
+#define AFE_GASRC0_NEW_CON9 (0x4c64)
+#define AFE_GASRC0_NEW_CON10 (0x4c68)
+#define AFE_GASRC0_NEW_CON11 (0x4c6c)
+#define AFE_GASRC0_NEW_CON12 (0x4c70)
+#define AFE_GASRC0_NEW_CON13 (0x4c74)
+#define AFE_GASRC0_NEW_CON14 (0x4c78)
+#define AFE_GASRC1_NEW_CON0 (0x4c80)
+#define AFE_GASRC1_NEW_CON1 (0x4c84)
+#define AFE_GASRC1_NEW_CON2 (0x4c88)
+#define AFE_GASRC1_NEW_CON3 (0x4c8c)
+#define AFE_GASRC1_NEW_CON4 (0x4c90)
+#define AFE_GASRC1_NEW_CON5 (0x4c94)
+#define AFE_GASRC1_NEW_CON6 (0x4c98)
+#define AFE_GASRC1_NEW_CON7 (0x4c9c)
+#define AFE_GASRC1_NEW_CON8 (0x4ca0)
+#define AFE_GASRC1_NEW_CON9 (0x4ca4)
+#define AFE_GASRC1_NEW_CON10 (0x4ca8)
+#define AFE_GASRC1_NEW_CON11 (0x4cac)
+#define AFE_GASRC1_NEW_CON12 (0x4cb0)
+#define AFE_GASRC1_NEW_CON13 (0x4cb4)
+#define AFE_GASRC1_NEW_CON14 (0x4cb8)
+#define AFE_GASRC2_NEW_CON0 (0x4cc0)
+#define AFE_GASRC2_NEW_CON1 (0x4cc4)
+#define AFE_GASRC2_NEW_CON2 (0x4cc8)
+#define AFE_GASRC2_NEW_CON3 (0x4ccc)
+#define AFE_GASRC2_NEW_CON4 (0x4cd0)
+#define AFE_GASRC2_NEW_CON5 (0x4cd4)
+#define AFE_GASRC2_NEW_CON6 (0x4cd8)
+#define AFE_GASRC2_NEW_CON7 (0x4cdc)
+#define AFE_GASRC2_NEW_CON8 (0x4ce0)
+#define AFE_GASRC2_NEW_CON9 (0x4ce4)
+#define AFE_GASRC2_NEW_CON10 (0x4ce8)
+#define AFE_GASRC2_NEW_CON11 (0x4cec)
+#define AFE_GASRC2_NEW_CON12 (0x4cf0)
+#define AFE_GASRC2_NEW_CON13 (0x4cf4)
+#define AFE_GASRC2_NEW_CON14 (0x4cf8)
+#define AFE_GASRC3_NEW_CON0 (0x4d00)
+#define AFE_GASRC3_NEW_CON1 (0x4d04)
+#define AFE_GASRC3_NEW_CON2 (0x4d08)
+#define AFE_GASRC3_NEW_CON3 (0x4d0c)
+#define AFE_GASRC3_NEW_CON4 (0x4d10)
+#define AFE_GASRC3_NEW_CON5 (0x4d14)
+#define AFE_GASRC3_NEW_CON6 (0x4d18)
+#define AFE_GASRC3_NEW_CON7 (0x4d1c)
+#define AFE_GASRC3_NEW_CON8 (0x4d20)
+#define AFE_GASRC3_NEW_CON9 (0x4d24)
+#define AFE_GASRC3_NEW_CON10 (0x4d28)
+#define AFE_GASRC3_NEW_CON11 (0x4d2c)
+#define AFE_GASRC3_NEW_CON12 (0x4d30)
+#define AFE_GASRC3_NEW_CON13 (0x4d34)
+#define AFE_GASRC3_NEW_CON14 (0x4d38)
+#define AFE_GASRC4_NEW_CON0 (0x4d40)
+#define AFE_GASRC4_NEW_CON1 (0x4d44)
+#define AFE_GASRC4_NEW_CON2 (0x4d48)
+#define AFE_GASRC4_NEW_CON3 (0x4d4c)
+#define AFE_GASRC4_NEW_CON4 (0x4d50)
+#define AFE_GASRC4_NEW_CON5 (0x4d54)
+#define AFE_GASRC4_NEW_CON6 (0x4d58)
+#define AFE_GASRC4_NEW_CON7 (0x4d5c)
+#define AFE_GASRC4_NEW_CON8 (0x4d60)
+#define AFE_GASRC4_NEW_CON9 (0x4d64)
+#define AFE_GASRC4_NEW_CON10 (0x4d68)
+#define AFE_GASRC4_NEW_CON11 (0x4d6c)
+#define AFE_GASRC4_NEW_CON12 (0x4d70)
+#define AFE_GASRC4_NEW_CON13 (0x4d74)
+#define AFE_GASRC4_NEW_CON14 (0x4d78)
+#define AFE_GASRC5_NEW_CON0 (0x4d80)
+#define AFE_GASRC5_NEW_CON1 (0x4d84)
+#define AFE_GASRC5_NEW_CON2 (0x4d88)
+#define AFE_GASRC5_NEW_CON3 (0x4d8c)
+#define AFE_GASRC5_NEW_CON4 (0x4d90)
+#define AFE_GASRC5_NEW_CON5 (0x4d94)
+#define AFE_GASRC5_NEW_CON6 (0x4d98)
+#define AFE_GASRC5_NEW_CON7 (0x4d9c)
+#define AFE_GASRC5_NEW_CON8 (0x4da0)
+#define AFE_GASRC5_NEW_CON9 (0x4da4)
+#define AFE_GASRC5_NEW_CON10 (0x4da8)
+#define AFE_GASRC5_NEW_CON11 (0x4dac)
+#define AFE_GASRC5_NEW_CON12 (0x4db0)
+#define AFE_GASRC5_NEW_CON13 (0x4db4)
+#define AFE_GASRC5_NEW_CON14 (0x4db8)
+#define AFE_GASRC6_NEW_CON0 (0x4dc0)
+#define AFE_GASRC6_NEW_CON1 (0x4dc4)
+#define AFE_GASRC6_NEW_CON2 (0x4dc8)
+#define AFE_GASRC6_NEW_CON3 (0x4dcc)
+#define AFE_GASRC6_NEW_CON4 (0x4dd0)
+#define AFE_GASRC6_NEW_CON5 (0x4dd4)
+#define AFE_GASRC6_NEW_CON6 (0x4dd8)
+#define AFE_GASRC6_NEW_CON7 (0x4ddc)
+#define AFE_GASRC6_NEW_CON8 (0x4de0)
+#define AFE_GASRC6_NEW_CON9 (0x4de4)
+#define AFE_GASRC6_NEW_CON10 (0x4de8)
+#define AFE_GASRC6_NEW_CON11 (0x4dec)
+#define AFE_GASRC6_NEW_CON12 (0x4df0)
+#define AFE_GASRC6_NEW_CON13 (0x4df4)
+#define AFE_GASRC6_NEW_CON14 (0x4df8)
+#define AFE_GASRC7_NEW_CON0 (0x4e00)
+#define AFE_GASRC7_NEW_CON1 (0x4e04)
+#define AFE_GASRC7_NEW_CON2 (0x4e08)
+#define AFE_GASRC7_NEW_CON3 (0x4e0c)
+#define AFE_GASRC7_NEW_CON4 (0x4e10)
+#define AFE_GASRC7_NEW_CON5 (0x4e14)
+#define AFE_GASRC7_NEW_CON6 (0x4e18)
+#define AFE_GASRC7_NEW_CON7 (0x4e1c)
+#define AFE_GASRC7_NEW_CON8 (0x4e20)
+#define AFE_GASRC7_NEW_CON9 (0x4e24)
+#define AFE_GASRC7_NEW_CON10 (0x4e28)
+#define AFE_GASRC7_NEW_CON11 (0x4e2c)
+#define AFE_GASRC7_NEW_CON12 (0x4e30)
+#define AFE_GASRC7_NEW_CON13 (0x4e34)
+#define AFE_GASRC7_NEW_CON14 (0x4e38)
+#define AFE_GASRC8_NEW_CON0 (0x4e40)
+#define AFE_GASRC8_NEW_CON1 (0x4e44)
+#define AFE_GASRC8_NEW_CON2 (0x4e48)
+#define AFE_GASRC8_NEW_CON3 (0x4e4c)
+#define AFE_GASRC8_NEW_CON4 (0x4e50)
+#define AFE_GASRC8_NEW_CON5 (0x4e54)
+#define AFE_GASRC8_NEW_CON6 (0x4e58)
+#define AFE_GASRC8_NEW_CON7 (0x4e5c)
+#define AFE_GASRC8_NEW_CON8 (0x4e60)
+#define AFE_GASRC8_NEW_CON9 (0x4e64)
+#define AFE_GASRC8_NEW_CON10 (0x4e68)
+#define AFE_GASRC8_NEW_CON11 (0x4e6c)
+#define AFE_GASRC8_NEW_CON12 (0x4e70)
+#define AFE_GASRC8_NEW_CON13 (0x4e74)
+#define AFE_GASRC8_NEW_CON14 (0x4e78)
+#define AFE_GASRC9_NEW_CON0 (0x4e80)
+#define AFE_GASRC9_NEW_CON1 (0x4e84)
+#define AFE_GASRC9_NEW_CON2 (0x4e88)
+#define AFE_GASRC9_NEW_CON3 (0x4e8c)
+#define AFE_GASRC9_NEW_CON4 (0x4e90)
+#define AFE_GASRC9_NEW_CON5 (0x4e94)
+#define AFE_GASRC9_NEW_CON6 (0x4e98)
+#define AFE_GASRC9_NEW_CON7 (0x4e9c)
+#define AFE_GASRC9_NEW_CON8 (0x4ea0)
+#define AFE_GASRC9_NEW_CON9 (0x4ea4)
+#define AFE_GASRC9_NEW_CON10 (0x4ea8)
+#define AFE_GASRC9_NEW_CON11 (0x4eac)
+#define AFE_GASRC9_NEW_CON12 (0x4eb0)
+#define AFE_GASRC9_NEW_CON13 (0x4eb4)
+#define AFE_GASRC9_NEW_CON14 (0x4eb8)
+#define AFE_GASRC10_NEW_CON0 (0x4ec0)
+#define AFE_GASRC10_NEW_CON1 (0x4ec4)
+#define AFE_GASRC10_NEW_CON2 (0x4ec8)
+#define AFE_GASRC10_NEW_CON3 (0x4ecc)
+#define AFE_GASRC10_NEW_CON4 (0x4ed0)
+#define AFE_GASRC10_NEW_CON5 (0x4ed4)
+#define AFE_GASRC10_NEW_CON6 (0x4ed8)
+#define AFE_GASRC10_NEW_CON7 (0x4edc)
+#define AFE_GASRC10_NEW_CON8 (0x4ee0)
+#define AFE_GASRC10_NEW_CON9 (0x4ee4)
+#define AFE_GASRC10_NEW_CON10 (0x4ee8)
+#define AFE_GASRC10_NEW_CON11 (0x4eec)
+#define AFE_GASRC10_NEW_CON12 (0x4ef0)
+#define AFE_GASRC10_NEW_CON13 (0x4ef4)
+#define AFE_GASRC10_NEW_CON14 (0x4ef8)
+#define AFE_GASRC11_NEW_CON0 (0x4f00)
+#define AFE_GASRC11_NEW_CON1 (0x4f04)
+#define AFE_GASRC11_NEW_CON2 (0x4f08)
+#define AFE_GASRC11_NEW_CON3 (0x4f0c)
+#define AFE_GASRC11_NEW_CON4 (0x4f10)
+#define AFE_GASRC11_NEW_CON5 (0x4f14)
+#define AFE_GASRC11_NEW_CON6 (0x4f18)
+#define AFE_GASRC11_NEW_CON7 (0x4f1c)
+#define AFE_GASRC11_NEW_CON8 (0x4f20)
+#define AFE_GASRC11_NEW_CON9 (0x4f24)
+#define AFE_GASRC11_NEW_CON10 (0x4f28)
+#define AFE_GASRC11_NEW_CON11 (0x4f2c)
+#define AFE_GASRC11_NEW_CON12 (0x4f30)
+#define AFE_GASRC11_NEW_CON13 (0x4f34)
+#define AFE_GASRC11_NEW_CON14 (0x4f38)
+#define AFE_GASRC12_NEW_CON0 (0x4f40)
+#define AFE_GASRC12_NEW_CON1 (0x4f44)
+#define AFE_GASRC12_NEW_CON2 (0x4f48)
+#define AFE_GASRC12_NEW_CON3 (0x4f4c)
+#define AFE_GASRC12_NEW_CON4 (0x4f50)
+#define AFE_GASRC12_NEW_CON5 (0x4f54)
+#define AFE_GASRC12_NEW_CON6 (0x4f58)
+#define AFE_GASRC12_NEW_CON7 (0x4f5c)
+#define AFE_GASRC12_NEW_CON8 (0x4f60)
+#define AFE_GASRC12_NEW_CON9 (0x4f64)
+#define AFE_GASRC12_NEW_CON10 (0x4f68)
+#define AFE_GASRC12_NEW_CON11 (0x4f6c)
+#define AFE_GASRC12_NEW_CON12 (0x4f70)
+#define AFE_GASRC12_NEW_CON13 (0x4f74)
+#define AFE_GASRC12_NEW_CON14 (0x4f78)
+#define AFE_GASRC13_NEW_CON0 (0x4f80)
+#define AFE_GASRC13_NEW_CON1 (0x4f84)
+#define AFE_GASRC13_NEW_CON2 (0x4f88)
+#define AFE_GASRC13_NEW_CON3 (0x4f8c)
+#define AFE_GASRC13_NEW_CON4 (0x4f90)
+#define AFE_GASRC13_NEW_CON5 (0x4f94)
+#define AFE_GASRC13_NEW_CON6 (0x4f98)
+#define AFE_GASRC13_NEW_CON7 (0x4f9c)
+#define AFE_GASRC13_NEW_CON8 (0x4fa0)
+#define AFE_GASRC13_NEW_CON9 (0x4fa4)
+#define AFE_GASRC13_NEW_CON10 (0x4fa8)
+#define AFE_GASRC13_NEW_CON11 (0x4fac)
+#define AFE_GASRC13_NEW_CON12 (0x4fb0)
+#define AFE_GASRC13_NEW_CON13 (0x4fb4)
+#define AFE_GASRC13_NEW_CON14 (0x4fb8)
+#define AFE_GASRC14_NEW_CON0 (0x4fc0)
+#define AFE_GASRC14_NEW_CON1 (0x4fc4)
+#define AFE_GASRC14_NEW_CON2 (0x4fc8)
+#define AFE_GASRC14_NEW_CON3 (0x4fcc)
+#define AFE_GASRC14_NEW_CON4 (0x4fd0)
+#define AFE_GASRC14_NEW_CON5 (0x4fd4)
+#define AFE_GASRC14_NEW_CON6 (0x4fd8)
+#define AFE_GASRC14_NEW_CON7 (0x4fdc)
+#define AFE_GASRC14_NEW_CON8 (0x4fe0)
+#define AFE_GASRC14_NEW_CON9 (0x4fe4)
+#define AFE_GASRC14_NEW_CON10 (0x4fe8)
+#define AFE_GASRC14_NEW_CON11 (0x4fec)
+#define AFE_GASRC14_NEW_CON12 (0x4ff0)
+#define AFE_GASRC14_NEW_CON13 (0x4ff4)
+#define AFE_GASRC14_NEW_CON14 (0x4ff8)
+#define AFE_GASRC15_NEW_CON0 (0x5000)
+#define AFE_GASRC15_NEW_CON1 (0x5004)
+#define AFE_GASRC15_NEW_CON2 (0x5008)
+#define AFE_GASRC15_NEW_CON3 (0x500c)
+#define AFE_GASRC15_NEW_CON4 (0x5010)
+#define AFE_GASRC15_NEW_CON5 (0x5014)
+#define AFE_GASRC15_NEW_CON6 (0x5018)
+#define AFE_GASRC15_NEW_CON7 (0x501c)
+#define AFE_GASRC15_NEW_CON8 (0x5020)
+#define AFE_GASRC15_NEW_CON9 (0x5024)
+#define AFE_GASRC15_NEW_CON10 (0x5028)
+#define AFE_GASRC15_NEW_CON11 (0x502c)
+#define AFE_GASRC15_NEW_CON12 (0x5030)
+#define AFE_GASRC15_NEW_CON13 (0x5034)
+#define AFE_GASRC15_NEW_CON14 (0x5038)
+#define AFE_GASRC16_NEW_CON0 (0x5040)
+#define AFE_GASRC16_NEW_CON1 (0x5044)
+#define AFE_GASRC16_NEW_CON2 (0x5048)
+#define AFE_GASRC16_NEW_CON3 (0x504c)
+#define AFE_GASRC16_NEW_CON4 (0x5050)
+#define AFE_GASRC16_NEW_CON5 (0x5054)
+#define AFE_GASRC16_NEW_CON6 (0x5058)
+#define AFE_GASRC16_NEW_CON7 (0x505c)
+#define AFE_GASRC16_NEW_CON8 (0x5060)
+#define AFE_GASRC16_NEW_CON9 (0x5064)
+#define AFE_GASRC16_NEW_CON10 (0x5068)
+#define AFE_GASRC16_NEW_CON11 (0x506c)
+#define AFE_GASRC16_NEW_CON12 (0x5070)
+#define AFE_GASRC16_NEW_CON13 (0x5074)
+#define AFE_GASRC16_NEW_CON14 (0x5078)
+#define AFE_GASRC17_NEW_CON0 (0x5080)
+#define AFE_GASRC17_NEW_CON1 (0x5084)
+#define AFE_GASRC17_NEW_CON2 (0x5088)
+#define AFE_GASRC17_NEW_CON3 (0x508c)
+#define AFE_GASRC17_NEW_CON4 (0x5090)
+#define AFE_GASRC17_NEW_CON5 (0x5094)
+#define AFE_GASRC17_NEW_CON6 (0x5098)
+#define AFE_GASRC17_NEW_CON7 (0x509c)
+#define AFE_GASRC17_NEW_CON8 (0x50a0)
+#define AFE_GASRC17_NEW_CON9 (0x50a4)
+#define AFE_GASRC17_NEW_CON10 (0x50a8)
+#define AFE_GASRC17_NEW_CON11 (0x50ac)
+#define AFE_GASRC17_NEW_CON12 (0x50b0)
+#define AFE_GASRC17_NEW_CON13 (0x50b4)
+#define AFE_GASRC17_NEW_CON14 (0x50b8)
+#define AFE_GASRC18_NEW_CON0 (0x50c0)
+#define AFE_GASRC18_NEW_CON1 (0x50c4)
+#define AFE_GASRC18_NEW_CON2 (0x50c8)
+#define AFE_GASRC18_NEW_CON3 (0x50cc)
+#define AFE_GASRC18_NEW_CON4 (0x50d0)
+#define AFE_GASRC18_NEW_CON5 (0x50d4)
+#define AFE_GASRC18_NEW_CON6 (0x50d8)
+#define AFE_GASRC18_NEW_CON7 (0x50dc)
+#define AFE_GASRC18_NEW_CON8 (0x50e0)
+#define AFE_GASRC18_NEW_CON9 (0x50e4)
+#define AFE_GASRC18_NEW_CON10 (0x50e8)
+#define AFE_GASRC18_NEW_CON11 (0x50ec)
+#define AFE_GASRC18_NEW_CON12 (0x50f0)
+#define AFE_GASRC18_NEW_CON13 (0x50f4)
+#define AFE_GASRC18_NEW_CON14 (0x50f8)
+#define AFE_GASRC19_NEW_CON0 (0x5100)
+#define AFE_GASRC19_NEW_CON1 (0x5104)
+#define AFE_GASRC19_NEW_CON2 (0x5108)
+#define AFE_GASRC19_NEW_CON3 (0x510c)
+#define AFE_GASRC19_NEW_CON4 (0x5110)
+#define AFE_GASRC19_NEW_CON5 (0x5114)
+#define AFE_GASRC19_NEW_CON6 (0x5118)
+#define AFE_GASRC19_NEW_CON7 (0x511c)
+#define AFE_GASRC19_NEW_CON8 (0x5120)
+#define AFE_GASRC19_NEW_CON9 (0x5124)
+#define AFE_GASRC19_NEW_CON10 (0x5128)
+#define AFE_GASRC19_NEW_CON11 (0x512c)
+#define AFE_GASRC19_NEW_CON12 (0x5130)
+#define AFE_GASRC19_NEW_CON13 (0x5134)
+#define AFE_GASRC19_NEW_CON14 (0x5138)
+
+#define AFE_MAX_REGISTER (AFE_GASRC19_NEW_CON14)
+
+/* ASYS_TOP_CON */
+#define ASYS_TOP_CON_A1SYS_TIMING_ON BIT(0)
+#define ASYS_TOP_CON_A2SYS_TIMING_ON BIT(1)
+#define ASYS_TOP_CON_A3SYS_TIMING_ON BIT(4)
+#define ASYS_TOP_CON_A4SYS_TIMING_ON BIT(5)
+#define ASYS_TOP_CON_26M_TIMING_ON BIT(2)
+
+/* PWR2_TOP_CON0 */
+#define PWR2_TOP_CON_DMIC8_SRC_SEL_MASK GENMASK(31, 29)
+#define PWR2_TOP_CON_DMIC7_SRC_SEL_MASK GENMASK(28, 26)
+#define PWR2_TOP_CON_DMIC6_SRC_SEL_MASK GENMASK(25, 23)
+#define PWR2_TOP_CON_DMIC5_SRC_SEL_MASK GENMASK(22, 20)
+#define PWR2_TOP_CON_DMIC4_SRC_SEL_MASK GENMASK(19, 17)
+#define PWR2_TOP_CON_DMIC3_SRC_SEL_MASK GENMASK(16, 14)
+#define PWR2_TOP_CON_DMIC2_SRC_SEL_MASK GENMASK(13, 11)
+#define PWR2_TOP_CON_DMIC1_SRC_SEL_MASK GENMASK(10, 8)
+#define PWR2_TOP_CON_DMIC8_SRC_SEL_VAL(x) ((x) << 29)
+#define PWR2_TOP_CON_DMIC7_SRC_SEL_VAL(x) ((x) << 26)
+#define PWR2_TOP_CON_DMIC6_SRC_SEL_VAL(x) ((x) << 23)
+#define PWR2_TOP_CON_DMIC5_SRC_SEL_VAL(x) ((x) << 20)
+#define PWR2_TOP_CON_DMIC4_SRC_SEL_VAL(x) ((x) << 17)
+#define PWR2_TOP_CON_DMIC3_SRC_SEL_VAL(x) ((x) << 14)
+#define PWR2_TOP_CON_DMIC2_SRC_SEL_VAL(x) ((x) << 11)
+#define PWR2_TOP_CON_DMIC1_SRC_SEL_VAL(x) ((x) << 8)
+
+/* PWR2_TOP_CON1 */
+#define PWR2_TOP_CON1_DMIC_CKDIV_ON BIT(1)
+
+/* PCM_INTF_CON1 */
+#define PCM_INTF_CON1_SYNC_OUT_INV BIT(23)
+#define PCM_INTF_CON1_BCLK_OUT_INV BIT(22)
+#define PCM_INTF_CON1_CLK_OUT_INV_MASK GENMASK(23, 22)
+#define PCM_INTF_CON1_SYNC_IN_INV BIT(21)
+#define PCM_INTF_CON1_BCLK_IN_INV BIT(20)
+#define PCM_INTF_CON1_CLK_IN_INV_MASK GENMASK(21, 20)
+#define PCM_INTF_CON1_PCM_24BIT (0x1 << 16)
+#define PCM_INTF_CON1_PCM_16BIT (0x0 << 16)
+#define PCM_INTF_CON1_PCM_BIT_MASK BIT(16)
+#define PCM_INTF_CON1_PCM_WLEN_32BCK (0x0 << 14)
+#define PCM_INTF_CON1_PCM_WLEN_64BCK (0x1 << 14)
+#define PCM_INTF_CON1_PCM_WLEN_MASK BIT(14)
+#define PCM_INTF_CON1_SYNC_LENGTH(x) (((x) & 0x1f) << 9)
+#define PCM_INTF_CON1_SYNC_LENGTH_MASK (0x1f << 9)
+#define PCM_INTF_CON1_PCM_SLAVE (0x1 << 5)
+#define PCM_INTF_CON1_PCM_MASTER (0x0 << 5)
+#define PCM_INTF_CON1_PCM_M_S_MASK BIT(5)
+#define PCM_INTF_CON1_PCM_MODE(x) (((x) & 0x3) << 3)
+#define PCM_INTF_CON1_PCM_MODE_MASK (0x3 << 3)
+#define PCM_INTF_CON1_PCM_FMT(x) (((x) & 0x3) << 1)
+#define PCM_INTF_CON1_PCM_FMT_MASK (0x3 << 1)
+#define PCM_INTF_CON1_PCM_EN BIT(0)
+
+/* PCM_INTF_CON2 */
+#define PCM_INTF_CON2_CLK_DOMAIN_SEL(x) (((x) & 0x3) << 23)
+#define PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK (0x3 << 23)
+#define PCM_INTF_CON2_SYNC_FREQ_MODE(x) (((x) & 0x1f) << 12)
+#define PCM_INTF_CON2_SYNC_FREQ_MODE_MASK (0x1f << 12)
+#define PCM_INTF_CON2_PCM_TX2RX_LPBK BIT(8)
+
+/* AFE_MPHONE_MULTIx_CON0 */
+#define AFE_MPHONE_MULTI_CON0_16BIT_SWAP BIT(3)
+#define AFE_MPHONE_MULTI_CON0_16BIT_SWAP_MASK BIT(3)
+#define AFE_MPHONE_MULTI_CON0_24BIT_DATA (0x1 << 1)
+#define AFE_MPHONE_MULTI_CON0_16BIT_DATA (0x0 << 1)
+#define AFE_MPHONE_MULIT_CON0_24BIT_DATA_MASK BIT(1)
+#define AFE_MPHONE_MULTI_CON0_EN BIT(0)
+#define AFE_MPHONE_MULTI_CON0_EN_MASK BIT(0)
+
+/* AFE_MPHONE_MULTIx_CON1 */
+#define AFE_MPHONE_MULTI_CON1_SYNC_ON BIT(24)
+#define AFE_MPHONE_MULTI_CON1_SYNC_ON_MASK BIT(24)
+#define AFE_MPHONE_MULTI_CON1_24BIT_SWAP_BYPASS BIT(22)
+#define AFE_MPHONE_MULTI_CON1_24BIT_SWAP_BYPASS_MASK BIT(22)
+#define AFE_MPHONE_MULTI_CON1_NON_COMPACT_MODE (0x1 << 19)
+#define AFE_MPHONE_MULTI_CON1_COMPACT_MODE (0x0 << 19)
+#define AFE_MPHONE_MULTI_CON1_NON_COMPACT_MODE_MASK BIT(19)
+#define AFE_MPHONE_MULTI_CON1_HBR_MODE BIT(18)
+#define AFE_MPHONE_MULTI_CON1_HBR_MODE_MASK BIT(18)
+#define AFE_MPHONE_MULTI_CON1_LRCK_32_CYCLE (0x2 << 16)
+#define AFE_MPHONE_MULTI_CON1_LRCK_24_CYCLE (0x1 << 16)
+#define AFE_MPHONE_MULTI_CON1_LRCK_16_CYCLE (0x0 << 16)
+#define AFE_MPHONE_MULTI_CON1_LRCK_CYCLE_SEL_MASK GENMASK(17, 16)
+#define AFE_MPHONE_MULTI_CON1_LRCK_INV BIT(15)
+#define AFE_MPHONE_MULTI_CON1_LRCK_INV_MASK BIT(15)
+#define AFE_MPHONE_MULTI_CON1_DELAY_DATA BIT(14)
+#define AFE_MPHONE_MULTI_CON1_DELAY_DATA_MASK BIT(14)
+#define AFE_MPHONE_MULTI_CON1_LEFT_ALIGN BIT(13)
+#define AFE_MPHONE_MULTI_CON1_LEFT_ALIGN_MASK BIT(13)
+#define AFE_MPHONE_MULTI_CON1_BIT_NUM(x) ((((x) - 1) & 0x1f) << 8)
+#define AFE_MPHONE_MULTI_CON1_BIT_NUM_MASK GENMASK(12, 8)
+#define AFE_MPHONE_MULTI_CON1_BCK_INV BIT(6)
+#define AFE_MPHONE_MULTI_CON1_BCK_INV_MASK BIT(6)
+#define AFE_MPHONE_MULTI_CON1_CH_NUM(x) ((((x) >> 1) - 1) & 0x3)
+#define AFE_MPHONE_MULTI_CON1_CH_NUM_MASK GENMASK(1, 0)
+
+/* AFE_MPHONE_MULTIx_CON2 */
+#define AFE_MPHONE_MULTI_CON2_SEL_SPDIFIN BIT(19)
+#define AFE_MPHONE_MULTI_CON2_SEL_SPDIFIN_MASK BIT(19)
+
+/* AFE_AUD_PAD_TOP */
+#define RG_RX_PROTOCOL2 BIT(3)
+#define RG_RX_FIFO_ON BIT(0)
+
+/* AFE_ADDA_MTKAIF_CFG0 */
+#define MTKAIF_RXIF_CLKINV_ADC BIT(31)
+#define MTKAIF_RXIF_PROTOCOL2 BIT(16)
+#define MTKAIF_TXIF_PROTOCOL2 BIT(4)
+#define MTKAIF_TXIF_8TO5 BIT(2)
+#define MTKAIF_RXIF_8TO5 BIT(1)
+#define MTKAIF_IF_LOOPBACK1 BIT(0)
+
+/* AFE_ADDA_MTKAIF_RX_CFG2 */
+#define MTKAIF_RXIF_DELAY_CYCLE(x) ((x) << 12)
+#define MTKAIF_RXIF_DELAY_CYCLE_MASK GENMASK(15, 12)
+#define MTKAIF_RXIF_DELAY_DATA BIT(8)
+#define MTKAIF_RXIF_DELAY_DATA_SHIFT 8
+
+/* AFE_ADDA_MTKAIF_SYNCWORD_CFG */
+#define ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE BIT(23)
+
+/* AFE_DMICx_UL_SRC_CON0 */
+#define AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH1(x) (((x) & 0x7) << 27)
+#define AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH2(x) (((x) & 0x7) << 24)
+#define AFE_DMIC_UL_SRC_CON0_UL_TWO_WIRE_MODE_CTL BIT(23)
+#define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL BIT(22)
+#define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL BIT(21)
+#define AFE_DMIC_UL_VOICE_MODE(x) (((x) & 0x7) << 17)
+#define AFE_DMIC_UL_CON0_VOCIE_MODE_8K AFE_DMIC_UL_VOICE_MODE(0)
+#define AFE_DMIC_UL_CON0_VOCIE_MODE_16K AFE_DMIC_UL_VOICE_MODE(1)
+#define AFE_DMIC_UL_CON0_VOCIE_MODE_32K AFE_DMIC_UL_VOICE_MODE(2)
+#define AFE_DMIC_UL_CON0_VOCIE_MODE_48K AFE_DMIC_UL_VOICE_MODE(3)
+#define AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL(x) (((x) & 0x7) << 7)
+#define AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL BIT(10)
+#define AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL BIT(1)
+#define AFE_DMIC_UL_SRC_CON0_UL_SRC_ON_TMP_CTL BIT(0)
+
+/* ETDM_INx_AFIFO_CON */
+#define ETDM_IN_USE_AFIFO BIT(8)
+#define ETDM_IN_AFIFO_CLOCK(x) ((x) << 5)
+#define ETDM_IN_AFIFO_CLOCK_MASK GENMASK(7, 5)
+#define ETDM_IN_AFIFO_MODE(x) ((x) << 0)
+#define ETDM_IN_AFIFO_MODE_MASK GENMASK(4, 0)
+
+/* ETDM_COWORK_CON0 */
+#define ETDM_OUT1_SLAVE_SEL(x) ((x) << 20)
+#define ETDM_OUT1_SLAVE_SEL_MASK GENMASK(23, 20)
+#define ETDM_OUT1_SLAVE_SEL_SHIFT 20
+
+/* ETDM_COWORK_CON1 */
+#define ETDM_IN1_SDATA_SEL(x) ((x) << 20)
+#define ETDM_IN1_SDATA_SEL_MASK GENMASK(23, 20)
+#define ETDM_IN1_SDATA_SEL_SHIFT 20
+#define ETDM_IN1_SDATA0_SEL(x) ((x) << 16)
+#define ETDM_IN1_SDATA0_SEL_MASK GENMASK(19, 16)
+#define ETDM_IN1_SDATA0_SEL_SHIFT 16
+#define ETDM_IN1_SLAVE_SEL(x) ((x) << 8)
+#define ETDM_IN1_SLAVE_SEL_MASK GENMASK(11, 8)
+#define ETDM_IN1_SLAVE_SEL_SHIFT 8
+
+/* ETDM_COWORK_CON2 */
+#define ETDM_IN2_SLAVE_SEL(x) ((x) << 24)
+#define ETDM_IN2_SLAVE_SEL_MASK GENMASK(27, 24)
+#define ETDM_IN2_SLAVE_SEL_SHIFT 24
+#define ETDM_OUT3_SLAVE_SEL(x) ((x) << 20)
+#define ETDM_OUT3_SLAVE_SEL_MASK GENMASK(23, 20)
+#define ETDM_OUT3_SLAVE_SEL_SHIFT 20
+#define ETDM_OUT2_SLAVE_SEL(x) ((x) << 8)
+#define ETDM_OUT2_SLAVE_SEL_MASK GENMASK(11, 8)
+#define ETDM_OUT2_SLAVE_SEL_SHIFT 8
+
+/* ETDM_COWORK_CON3 */
+#define ETDM_IN2_SDATA_SEL(x) ((x) << 4)
+#define ETDM_IN2_SDATA_SEL_MASK GENMASK(7, 4)
+#define ETDM_IN2_SDATA_SEL_SHIFT 4
+#define ETDM_IN2_SDATA0_SEL(x) ((x) << 0)
+#define ETDM_IN2_SDATA0_SEL_MASK GENMASK(3, 0)
+#define ETDM_IN2_SDATA0_SEL_SHIFT 0
+
+/* ETDM_x_CONx */
+#define ETDM_CON0_CH_NUM(x) (((x) - 1) << 23)
+#define ETDM_CON0_CH_NUM_MASK GENMASK(27, 23)
+#define ETDM_CON0_WORD_LEN(x) (((x) - 1) << 16)
+#define ETDM_CON0_WORD_LEN_MASK GENMASK(20, 16)
+#define ETDM_CON0_BIT_LEN(x) (((x) - 1) << 11)
+#define ETDM_CON0_BIT_LEN_MASK GENMASK(15, 11)
+#define ETDM_CON0_FORMAT(x) ((x) << 6)
+#define ETDM_CON0_FORMAT_MASK GENMASK(8, 6)
+#define ETDM_CON0_SLAVE_MODE BIT(5)
+#define ETDM_CON0_EN BIT(0)
+
+#define ETDM_OUT_CON0_RELATCH_DOMAIN(x) ((x) << 28)
+#define ETDM_OUT_CON0_RELATCH_DOMAIN_MASK GENMASK(29, 28)
+
+#define ETDM_CON1_MCLK_OUTPUT BIT(16)
+#define ETDM_IN_CON1_LRCK_AUTO_MODE BIT(31)
+#define ETDM_IN_CON1_LRCK_WIDTH(x) (((x) - 1) << 20)
+#define ETDM_IN_CON1_LRCK_WIDTH_MASK GENMASK(29, 20)
+#define ETDM_OUT_CON1_LRCK_AUTO_MODE BIT(29)
+#define ETDM_OUT_CON1_LRCK_WIDTH(x) (((x) - 1) << 19)
+#define ETDM_OUT_CON1_LRCK_WIDTH_MASK GENMASK(28, 19)
+
+#define ETDM_IN_CON2_MULTI_IP_2CH_MODE BIT(31)
+#define ETDM_IN_CON2_MULTI_IP_TOTAL_CH(x) (((x) - 1) << 15)
+#define ETDM_IN_CON2_MULTI_IP_TOTAL_CH_MASK GENMASK(19, 15)
+#define ETDM_IN_CON2_CLOCK(x) ((x) << 10)
+#define ETDM_IN_CON2_CLOCK_MASK GENMASK(12, 10)
+#define ETDM_IN_CON2_CLOCK_SHIFT 10
+#define ETDM_IN_CON2_UPDATE_GAP(x) ((x) << 5)
+#define ETDM_IN_CON2_UPDATE_GAP_MASK GENMASK(9, 5)
+
+#define ETDM_OUT_CON2_LRCK_DELAY_BCK_INV BIT(30)
+#define ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN BIT(29)
+
+#define ETDM_IN_CON3_FS(x) ((x) << 26)
+#define ETDM_IN_CON3_FS_MASK GENMASK(30, 26)
+#define ETDM_IN_CON3_DISABLE_OUT(x) BIT(((x) & 0xf))
+#define ETDM_IN_CON3_DISABLE_OUT_MASK GENMASK(15, 0)
+
+#define ETDM_IN_CON4_MASTER_LRCK_INV BIT(19)
+#define ETDM_IN_CON4_MASTER_BCK_INV BIT(18)
+#define ETDM_IN_CON4_SLAVE_LRCK_INV BIT(17)
+#define ETDM_IN_CON4_SLAVE_BCK_INV BIT(16)
+
+#define ETDM_OUT_CON4_RELATCH_EN(x) ((x) << 24)
+#define ETDM_OUT_CON4_RELATCH_EN_MASK GENMASK(28, 24)
+#define ETDM_OUT_CON4_CLOCK(x) ((x) << 6)
+#define ETDM_OUT_CON4_CLOCK_MASK GENMASK(8, 6)
+#define ETDM_OUT_CON4_CLOCK_SHIFT 6
+#define ETDM_OUT_CON4_FS(x) ((x) << 0)
+#define ETDM_OUT_CON4_FS_MASK GENMASK(4, 0)
+
+#define ETDM_IN_CON5_LR_SWAP(x) BIT(((x) & 0xf) + 16)
+#define ETDM_IN_CON5_LR_SWAP_MASK GENMASK(31, 16)
+#define ETDM_IN_CON5_ENABLE_ODD(x) BIT(((x) & 0xf))
+#define ETDM_IN_CON5_ENABLE_ODD_MASK GENMASK(15, 0)
+
+#define ETDM_OUT_CON5_MASTER_LRCK_INV BIT(10)
+#define ETDM_OUT_CON5_MASTER_BCK_INV BIT(9)
+#define ETDM_OUT_CON5_SLAVE_LRCK_INV BIT(8)
+#define ETDM_OUT_CON5_SLAVE_BCK_INV BIT(7)
+
+/* AFE_DPTX_CON */
+#define AFE_DPTX_CON_CH_EN(x) (((x) & 0xff) << 8)
+#define AFE_DPTX_CON_CH_EN_2CH (AFE_DPTX_CON_CH_EN(GENMASK(1, 0)))
+#define AFE_DPTX_CON_CH_EN_4CH (AFE_DPTX_CON_CH_EN(GENMASK(3, 0)))
+#define AFE_DPTX_CON_CH_EN_6CH (AFE_DPTX_CON_CH_EN(GENMASK(5, 0)))
+#define AFE_DPTX_CON_CH_EN_8CH (AFE_DPTX_CON_CH_EN(GENMASK(7, 0)))
+#define AFE_DPTX_CON_CH_EN_MASK GENMASK(15, 8)
+#define AFE_DPTX_CON_16BIT (0x1 << 2)
+#define AFE_DPTX_CON_24BIT (0x0 << 2)
+#define AFE_DPTX_CON_16BIT_MASK BIT(2)
+#define AFE_DPTX_CON_CH_NUM(x) (((x) & 0x1) << 1)
+#define AFE_DPTX_CON_CH_NUM_2CH (AFE_DPTX_CON_CH_NUM(0))
+#define AFE_DPTX_CON_CH_NUM_8CH (AFE_DPTX_CON_CH_NUM(1))
+#define AFE_DPTX_CON_CH_NUM_MASK (0x1 << 1)
+#define AFE_DPTX_CON_ON BIT(0)
+#define AFE_DPTX_CON_ON_MASK BIT(0)
+
+/* AFE_ADDA_UL_DL_CON0 */
+#define ADDA_AFE_ON_SHIFT 0
+
+/* AFE_ADDA_DL_SRC2_CON0 */
+#define DL_2_INPUT_MODE_CTL(x) ((x) << 28)
+#define DL_2_INPUT_MODE_CTL_MASK GENMASK(31, 28)
+#define DL_2_CH1_SATURATION_EN_CTL BIT(27)
+#define DL_2_CH2_SATURATION_EN_CTL BIT(26)
+#define DL_2_MUTE_CH1_OFF_CTL_PRE BIT(12)
+#define DL_2_MUTE_CH2_OFF_CTL_PRE BIT(11)
+#define DL_2_VOICE_MODE_CTL_PRE BIT(5)
+#define DL_2_GAIN_ON_CTL_PRE_SHIFT 1
+#define DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT 0
+
+/* AFE_ADDA_DL_SRC2_CON1 */
+#define DL_2_GAIN_CTL_PRE(x) ((x) << 16)
+#define DL_2_GAIN_CTL_PRE_MASK GENMASK(31, 16)
+#define DL_2_GAIN_CTL_PRE_SHIFT 16
+
+/* AFE_ADDA_TOP_CON0 */
+#define C_LOOPBACK_MODE_CTL_MASK GENMASK(15, 12)
+#define DL_INPUT_FROM_SINEGEN (4 << 12)
+
+/* AFE_ADDA_DL_SDM_DCCOMP_CON */
+#define DL_USE_NEW_2ND_SDM BIT(30)
+#define ATTGAIN_CTL_MASK GENMASK(5, 0)
+
+/* AFE_ADDA_UL_SRC_CON0 */
+#define UL_MODE_3P25M_CH2_CTL BIT(22)
+#define UL_MODE_3P25M_CH1_CTL BIT(21)
+#define UL_VOICE_MODE_CTL(x) ((x) << 17)
+#define UL_VOICE_MODE_CTL_MASK GENMASK(19, 17)
+#define UL_LOOPBACK_MODE_CTL BIT(2)
+#define UL_SDM3_LEVEL_CTL BIT(1)
+#define UL_SRC_ON_TMP_CTL_SHIFT 0
+
+#endif
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 939e7e28486a..7f13a35e9cc1 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -850,15 +850,12 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
static const struct snd_soc_component_driver pxa_ssp_component = {
.name = "pxa-ssp",
.pcm_construct = pxa2xx_soc_pcm_new,
- .pcm_destruct = pxa2xx_soc_pcm_free,
.open = pxa2xx_soc_pcm_open,
.close = pxa2xx_soc_pcm_close,
.hw_params = pxa2xx_soc_pcm_hw_params,
- .hw_free = pxa2xx_soc_pcm_hw_free,
.prepare = pxa2xx_soc_pcm_prepare,
.trigger = pxa2xx_soc_pcm_trigger,
.pointer = pxa2xx_soc_pcm_pointer,
- .mmap = pxa2xx_soc_pcm_mmap,
.suspend = pxa_ssp_suspend,
.resume = pxa_ssp_resume,
};
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 4240fde6aae8..58f8541ba55c 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -202,15 +202,12 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
static const struct snd_soc_component_driver pxa_ac97_component = {
.name = "pxa-ac97",
.pcm_construct = pxa2xx_soc_pcm_new,
- .pcm_destruct = pxa2xx_soc_pcm_free,
.open = pxa2xx_soc_pcm_open,
.close = pxa2xx_soc_pcm_close,
.hw_params = pxa2xx_soc_pcm_hw_params,
- .hw_free = pxa2xx_soc_pcm_hw_free,
.prepare = pxa2xx_soc_pcm_prepare,
.trigger = pxa2xx_soc_pcm_trigger,
.pointer = pxa2xx_soc_pcm_pointer,
- .mmap = pxa2xx_soc_pcm_mmap,
};
#ifdef CONFIG_OF
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index bcde4a96c168..5bfc1a966532 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -359,15 +359,12 @@ static struct snd_soc_dai_driver pxa_i2s_dai = {
static const struct snd_soc_component_driver pxa_i2s_component = {
.name = "pxa-i2s",
.pcm_construct = pxa2xx_soc_pcm_new,
- .pcm_destruct = pxa2xx_soc_pcm_free,
.open = pxa2xx_soc_pcm_open,
.close = pxa2xx_soc_pcm_close,
.hw_params = pxa2xx_soc_pcm_hw_params,
- .hw_free = pxa2xx_soc_pcm_hw_free,
.prepare = pxa2xx_soc_pcm_prepare,
.trigger = pxa2xx_soc_pcm_trigger,
.pointer = pxa2xx_soc_pcm_pointer,
- .mmap = pxa2xx_soc_pcm_mmap,
.suspend = pxa2xx_soc_pcm_suspend,
.resume = pxa2xx_soc_pcm_resume,
};
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 2b7839715dd5..9d6c41f775e5 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -19,15 +19,12 @@
static const struct snd_soc_component_driver pxa2xx_soc_platform = {
.pcm_construct = pxa2xx_soc_pcm_new,
- .pcm_destruct = pxa2xx_soc_pcm_free,
.open = pxa2xx_soc_pcm_open,
.close = pxa2xx_soc_pcm_close,
.hw_params = pxa2xx_soc_pcm_hw_params,
- .hw_free = pxa2xx_soc_pcm_hw_free,
.prepare = pxa2xx_soc_pcm_prepare,
.trigger = pxa2xx_soc_pcm_trigger,
.pointer = pxa2xx_soc_pcm_pointer,
- .mmap = pxa2xx_soc_pcm_mmap,
};
static int pxa2xx_soc_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c
index 08a05f0ecad7..ba2a98268ee4 100644
--- a/sound/soc/qcom/apq8016_sbc.c
+++ b/sound/soc/qcom/apq8016_sbc.c
@@ -30,6 +30,13 @@ struct apq8016_sbc_data {
#define MIC_CTRL_QUA_WS_SLAVE_SEL_10 BIT(17)
#define MIC_CTRL_TLMM_SCLK_EN BIT(1)
#define SPKR_CTL_PRI_WS_SLAVE_SEL_11 (BIT(17) | BIT(16))
+#define SPKR_CTL_TLMM_MCLK_EN BIT(1)
+#define SPKR_CTL_TLMM_SCLK_EN BIT(2)
+#define SPKR_CTL_TLMM_DATA1_EN BIT(3)
+#define SPKR_CTL_TLMM_WS_OUT_SEL_MASK GENMASK(7, 6)
+#define SPKR_CTL_TLMM_WS_OUT_SEL_SEC BIT(6)
+#define SPKR_CTL_TLMM_WS_EN_SEL_MASK GENMASK(19, 18)
+#define SPKR_CTL_TLMM_WS_EN_SEL_SEC BIT(18)
#define DEFAULT_MCLK_RATE 9600000
static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
@@ -40,6 +47,7 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_card *card = rtd->card;
struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card);
int i, rval;
+ u32 value;
switch (cpu_dai->id) {
case MI2S_PRIMARY:
@@ -53,6 +61,15 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
MIC_CTRL_TLMM_SCLK_EN,
pdata->mic_iomux);
break;
+ case MI2S_SECONDARY:
+ /* Clear TLMM_WS_OUT_SEL and TLMM_WS_EN_SEL fields */
+ value = readl(pdata->spkr_iomux) &
+ ~(SPKR_CTL_TLMM_WS_OUT_SEL_MASK | SPKR_CTL_TLMM_WS_EN_SEL_MASK);
+ /* Configure the Sec MI2S to TLMM */
+ writel(value | SPKR_CTL_TLMM_MCLK_EN | SPKR_CTL_TLMM_SCLK_EN |
+ SPKR_CTL_TLMM_DATA1_EN | SPKR_CTL_TLMM_WS_OUT_SEL_SEC |
+ SPKR_CTL_TLMM_WS_EN_SEL_SEC, pdata->spkr_iomux);
+ break;
case MI2S_TERTIARY:
writel(readl(pdata->mic_iomux) | MIC_CTRL_TER_WS_SLAVE_SEL |
MIC_CTRL_TLMM_SCLK_EN,
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index f9df76d37858..a59e9d20cb46 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -156,8 +156,6 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component,
return -EINVAL;
}
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
return 0;
}
@@ -630,16 +628,6 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
return bytes_to_frames(substream->runtime, curr_addr - base_addr);
}
-static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- return dma_mmap_coherent(component->dev, vma, runtime->dma_area,
- runtime->dma_addr, runtime->dma_bytes);
-}
-
static irqreturn_t lpass_dma_interrupt_handler(
struct snd_pcm_substream *substream,
struct lpass_data *drvdata,
@@ -787,52 +775,10 @@ static int lpass_platform_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *soc_runtime)
{
struct snd_pcm *pcm = soc_runtime->pcm;
- struct snd_pcm_substream *psubstream, *csubstream;
- int ret;
size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
- psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- if (psubstream) {
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
- component->dev,
- size, &psubstream->dma_buffer);
- if (ret) {
- dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
- return ret;
- }
- }
-
- csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
- if (csubstream) {
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
- component->dev,
- size, &csubstream->dma_buffer);
- if (ret) {
- dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
- if (psubstream)
- snd_dma_free_pages(&psubstream->dma_buffer);
- return ret;
- }
-
- }
-
- return 0;
-}
-
-static void lpass_platform_pcm_free(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- int i;
-
- for_each_pcm_streams(i) {
- substream = pcm->streams[i].substream;
- if (substream) {
- snd_dma_free_pages(&substream->dma_buffer);
- substream->dma_buffer.area = NULL;
- substream->dma_buffer.addr = 0;
- }
- }
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+ component->dev, size);
}
static int lpass_platform_pcmops_suspend(struct snd_soc_component *component)
@@ -877,9 +823,7 @@ static const struct snd_soc_component_driver lpass_component_driver = {
.prepare = lpass_platform_pcmops_prepare,
.trigger = lpass_platform_pcmops_trigger,
.pointer = lpass_platform_pcmops_pointer,
- .mmap = lpass_platform_pcmops_mmap,
.pcm_construct = lpass_platform_pcm_new,
- .pcm_destruct = lpass_platform_pcm_free,
.suspend = lpass_platform_pcmops_suspend,
.resume = lpass_platform_pcmops_resume,
diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c
index 1855b805eba2..3d831b635524 100644
--- a/sound/soc/qcom/qdsp6/q6adm.c
+++ b/sound/soc/qcom/qdsp6/q6adm.c
@@ -465,7 +465,7 @@ int q6adm_matrix_map(struct device *dev, int path,
struct apr_pkt *pkt;
uint16_t *copps_list;
int pkt_size, ret, i, copp_idx;
- void *matrix_map = NULL;
+ void *matrix_map;
struct q6copp *copp;
/* Assumes port_ids have already been validated during adm_open */
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 5ff56a735419..46f365528d50 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -429,8 +429,6 @@ static int q6asm_dai_open(struct snd_soc_component *component,
else
prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
return 0;
}
@@ -470,18 +468,6 @@ static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
}
-static int q6asm_dai_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct device *dev = component->dev;
-
- return dma_mmap_coherent(dev, vma,
- runtime->dma_area, runtime->dma_addr,
- runtime->dma_bytes);
-}
-
static int q6asm_dai_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -1185,52 +1171,11 @@ static const struct snd_compress_ops q6asm_dai_compress_ops = {
static int q6asm_dai_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
- struct snd_pcm_substream *psubstream, *csubstream;
struct snd_pcm *pcm = rtd->pcm;
- struct device *dev;
- int size, ret;
-
- dev = component->dev;
- size = q6asm_dai_hardware_playback.buffer_bytes_max;
- psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- if (psubstream) {
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
- &psubstream->dma_buffer);
- if (ret) {
- dev_err(dev, "Cannot allocate buffer(s)\n");
- return ret;
- }
- }
+ size_t size = q6asm_dai_hardware_playback.buffer_bytes_max;
- csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
- if (csubstream) {
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
- &csubstream->dma_buffer);
- if (ret) {
- dev_err(dev, "Cannot allocate buffer(s)\n");
- if (psubstream)
- snd_dma_free_pages(&psubstream->dma_buffer);
- return ret;
- }
- }
-
- return 0;
-}
-
-static void q6asm_dai_pcm_free(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
- substream = pcm->streams[i].substream;
- if (substream) {
- snd_dma_free_pages(&substream->dma_buffer);
- substream->dma_buffer.area = NULL;
- substream->dma_buffer.addr = 0;
- }
- }
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+ component->dev, size);
}
static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = {
@@ -1260,9 +1205,7 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = {
.prepare = q6asm_dai_prepare,
.trigger = q6asm_dai_trigger,
.pointer = q6asm_dai_pointer,
- .mmap = q6asm_dai_mmap,
.pcm_construct = q6asm_dai_pcm_new,
- .pcm_destruct = q6asm_dai_pcm_free,
.compress_ops = &q6asm_dai_compress_ops,
.dapm_widgets = q6asm_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets),
diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c
index 36bf8bd4edd7..9251d8548965 100644
--- a/sound/soc/qcom/qdsp6/q6asm.c
+++ b/sound/soc/qcom/qdsp6/q6asm.c
@@ -1624,7 +1624,7 @@ EXPORT_SYMBOL_GPL(q6asm_write_async);
static void q6asm_reset_buf_state(struct audio_client *ac)
{
- struct audio_port_data *port = NULL;
+ struct audio_port_data *port;
unsigned long flags;
spin_lock_irqsave(&ac->lock, flags);
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index c7dc3509bceb..53e0b4a1c7d2 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -40,6 +40,9 @@ struct rk_i2s_dev {
struct regmap *regmap;
struct regmap *grf;
+ bool has_capture;
+ bool has_playback;
+
/*
* Used to indicate the tx/rx status.
* I2S controller hopes to start the tx and rx together,
@@ -49,6 +52,7 @@ struct rk_i2s_dev {
bool rx_start;
bool is_master_mode;
const struct rk_i2s_pins *pins;
+ unsigned int bclk_ratio;
};
static int i2s_runtime_suspend(struct device *dev)
@@ -186,7 +190,9 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
{
struct rk_i2s_dev *i2s = to_info(cpu_dai);
unsigned int mask = 0, val = 0;
+ int ret = 0;
+ pm_runtime_get_sync(cpu_dai->dev);
mask = I2S_CKR_MSS_MASK;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
@@ -199,21 +205,37 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
i2s->is_master_mode = false;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_pm_put;
}
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
- mask = I2S_CKR_CKP_MASK;
+ mask = I2S_CKR_CKP_MASK | I2S_CKR_TLP_MASK | I2S_CKR_RLP_MASK;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
- val = I2S_CKR_CKP_NEG;
+ val = I2S_CKR_CKP_NORMAL |
+ I2S_CKR_TLP_NORMAL |
+ I2S_CKR_RLP_NORMAL;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ val = I2S_CKR_CKP_NORMAL |
+ I2S_CKR_TLP_INVERTED |
+ I2S_CKR_RLP_INVERTED;
break;
case SND_SOC_DAIFMT_IB_NF:
- val = I2S_CKR_CKP_POS;
+ val = I2S_CKR_CKP_INVERTED |
+ I2S_CKR_TLP_NORMAL |
+ I2S_CKR_RLP_NORMAL;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ val = I2S_CKR_CKP_INVERTED |
+ I2S_CKR_TLP_INVERTED |
+ I2S_CKR_RLP_INVERTED;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_pm_put;
}
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
@@ -229,14 +251,15 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_I2S:
val = I2S_TXCR_IBM_NORMAL;
break;
- case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
- val = I2S_TXCR_TFS_PCM;
- break;
- case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+ case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);
break;
+ case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
+ val = I2S_TXCR_TFS_PCM;
+ break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_pm_put;
}
regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
@@ -252,19 +275,23 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_I2S:
val = I2S_RXCR_IBM_NORMAL;
break;
- case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
- val = I2S_RXCR_TFS_PCM;
- break;
- case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
+ case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);
break;
+ case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
+ val = I2S_RXCR_TFS_PCM;
+ break;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_pm_put;
}
regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
- return 0;
+err_pm_put:
+ pm_runtime_put(cpu_dai->dev);
+
+ return ret;
}
static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
@@ -278,11 +305,11 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
if (i2s->is_master_mode) {
mclk_rate = clk_get_rate(i2s->mclk);
- bclk_rate = 2 * 32 * params_rate(params);
- if (bclk_rate == 0 || mclk_rate % bclk_rate)
+ bclk_rate = i2s->bclk_ratio * params_rate(params);
+ if (!bclk_rate)
return -EINVAL;
- div_bclk = mclk_rate / bclk_rate;
+ div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
div_lrck = bclk_rate / params_rate(params);
regmap_update_bits(i2s->regmap, I2S_CKR,
I2S_CKR_MDIV_MASK,
@@ -413,6 +440,16 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
return ret;
}
+static int rockchip_i2s_set_bclk_ratio(struct snd_soc_dai *dai,
+ unsigned int ratio)
+{
+ struct rk_i2s_dev *i2s = to_info(dai);
+
+ i2s->bclk_ratio = ratio;
+
+ return 0;
+}
+
static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
unsigned int freq, int dir)
{
@@ -433,14 +470,16 @@ static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
{
struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
- dai->capture_dma_data = &i2s->capture_dma_data;
- dai->playback_dma_data = &i2s->playback_dma_data;
+ snd_soc_dai_init_dma_data(dai,
+ i2s->has_playback ? &i2s->playback_dma_data : NULL,
+ i2s->has_capture ? &i2s->capture_dma_data : NULL);
return 0;
}
static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
.hw_params = rockchip_i2s_hw_params,
+ .set_bclk_ratio = rockchip_i2s_set_bclk_ratio,
.set_sysclk = rockchip_i2s_set_sysclk,
.set_fmt = rockchip_i2s_set_fmt,
.trigger = rockchip_i2s_trigger,
@@ -448,28 +487,6 @@ static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
static struct snd_soc_dai_driver rockchip_i2s_dai = {
.probe = rockchip_i2s_dai_probe,
- .playback = {
- .stream_name = "Playback",
- .channels_min = 2,
- .channels_max = 8,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = (SNDRV_PCM_FMTBIT_S8 |
- SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S20_3LE |
- SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE),
- },
- .capture = {
- .stream_name = "Capture",
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = (SNDRV_PCM_FMTBIT_S8 |
- SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S20_3LE |
- SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE),
- },
.ops = &rockchip_i2s_dai_ops,
.symmetric_rate = 1,
};
@@ -567,23 +584,101 @@ static const struct rk_i2s_pins rk3399_i2s_pins = {
};
static const struct of_device_id rockchip_i2s_match[] __maybe_unused = {
+ { .compatible = "rockchip,px30-i2s", },
+ { .compatible = "rockchip,rk1808-i2s", },
+ { .compatible = "rockchip,rk3036-i2s", },
{ .compatible = "rockchip,rk3066-i2s", },
+ { .compatible = "rockchip,rk3128-i2s", },
{ .compatible = "rockchip,rk3188-i2s", },
+ { .compatible = "rockchip,rk3228-i2s", },
{ .compatible = "rockchip,rk3288-i2s", },
+ { .compatible = "rockchip,rk3308-i2s", },
+ { .compatible = "rockchip,rk3328-i2s", },
+ { .compatible = "rockchip,rk3366-i2s", },
+ { .compatible = "rockchip,rk3368-i2s", },
{ .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins },
+ { .compatible = "rockchip,rv1126-i2s", },
{},
};
+static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res,
+ struct snd_soc_dai_driver **dp)
+{
+ struct device_node *node = i2s->dev->of_node;
+ struct snd_soc_dai_driver *dai;
+ struct property *dma_names;
+ const char *dma_name;
+ unsigned int val;
+
+ of_property_for_each_string(node, "dma-names", dma_names, dma_name) {
+ if (!strcmp(dma_name, "tx"))
+ i2s->has_playback = true;
+ if (!strcmp(dma_name, "rx"))
+ i2s->has_capture = true;
+ }
+
+ dai = devm_kmemdup(i2s->dev, &rockchip_i2s_dai,
+ sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ if (i2s->has_playback) {
+ dai->playback.stream_name = "Playback";
+ dai->playback.channels_min = 2;
+ dai->playback.channels_max = 8;
+ dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
+ dai->playback.formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE;
+
+ i2s->playback_dma_data.addr = res->start + I2S_TXDR;
+ i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ i2s->playback_dma_data.maxburst = 8;
+
+ if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
+ if (val >= 2 && val <= 8)
+ dai->playback.channels_max = val;
+ }
+ }
+
+ if (i2s->has_capture) {
+ dai->capture.stream_name = "Capture";
+ dai->capture.channels_min = 2;
+ dai->capture.channels_max = 8;
+ dai->capture.rates = SNDRV_PCM_RATE_8000_192000;
+ dai->capture.formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE;
+
+ i2s->capture_dma_data.addr = res->start + I2S_RXDR;
+ i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ i2s->capture_dma_data.maxburst = 8;
+
+ if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
+ if (val >= 2 && val <= 8)
+ dai->capture.channels_max = val;
+ }
+ }
+
+ if (dp)
+ *dp = dai;
+
+ return 0;
+}
+
static int rockchip_i2s_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
const struct of_device_id *of_id;
struct rk_i2s_dev *i2s;
- struct snd_soc_dai_driver *soc_dai;
+ struct snd_soc_dai_driver *dai;
struct resource *res;
void __iomem *regs;
int ret;
- int val;
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
if (!i2s)
@@ -630,13 +725,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
return PTR_ERR(i2s->regmap);
}
- i2s->playback_dma_data.addr = res->start + I2S_TXDR;
- i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- i2s->playback_dma_data.maxburst = 4;
-
- i2s->capture_dma_data.addr = res->start + I2S_RXDR;
- i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- i2s->capture_dma_data.maxburst = 4;
+ i2s->bclk_ratio = 64;
dev_set_drvdata(&pdev->dev, i2s);
@@ -647,26 +736,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
goto err_pm_disable;
}
- soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai,
- sizeof(*soc_dai), GFP_KERNEL);
- if (!soc_dai) {
- ret = -ENOMEM;
+ ret = rockchip_i2s_init_dai(i2s, res, &dai);
+ if (ret)
goto err_pm_disable;
- }
-
- if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
- if (val >= 2 && val <= 8)
- soc_dai->playback.channels_max = val;
- }
-
- if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
- if (val >= 2 && val <= 8)
- soc_dai->capture.channels_max = val;
- }
ret = devm_snd_soc_register_component(&pdev->dev,
&rockchip_i2s_component,
- soc_dai, 1);
+ dai, 1);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI\n");
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h
index fcaae24e40af..251851bf4f2c 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -88,15 +88,17 @@
#define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT)
#define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT)
#define I2S_CKR_CKP_SHIFT 26
-#define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT)
-#define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT)
+#define I2S_CKR_CKP_NORMAL (0 << I2S_CKR_CKP_SHIFT)
+#define I2S_CKR_CKP_INVERTED (1 << I2S_CKR_CKP_SHIFT)
#define I2S_CKR_CKP_MASK (1 << I2S_CKR_CKP_SHIFT)
#define I2S_CKR_RLP_SHIFT 25
#define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT)
-#define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT)
+#define I2S_CKR_RLP_INVERTED (1 << I2S_CKR_RLP_SHIFT)
+#define I2S_CKR_RLP_MASK (1 << I2S_CKR_RLP_SHIFT)
#define I2S_CKR_TLP_SHIFT 24
#define I2S_CKR_TLP_NORMAL (0 << I2S_CKR_TLP_SHIFT)
-#define I2S_CKR_TLP_OPPSITE (1 << I2S_CKR_TLP_SHIFT)
+#define I2S_CKR_TLP_INVERTED (1 << I2S_CKR_TLP_SHIFT)
+#define I2S_CKR_TLP_MASK (1 << I2S_CKR_TLP_SHIFT)
#define I2S_CKR_MDIV_SHIFT 16
#define I2S_CKR_MDIV(x) ((x - 1) << I2S_CKR_MDIV_SHIFT)
#define I2S_CKR_MDIV_MASK (0xff << I2S_CKR_MDIV_SHIFT)
diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c
index 73226a46d489..d027ca4b1796 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -58,6 +58,8 @@ static const struct of_device_id rk_spdif_match[] __maybe_unused = {
.data = (void *)RK_SPDIF_RK3366 },
{ .compatible = "rockchip,rk3399-spdif",
.data = (void *)RK_SPDIF_RK3366 },
+ { .compatible = "rockchip,rk3568-spdif",
+ .data = (void *)RK_SPDIF_RK3366 },
{},
};
MODULE_DEVICE_TABLE(of, rk_spdif_match);
@@ -103,8 +105,8 @@ static int __maybe_unused rk_spdif_runtime_resume(struct device *dev)
}
static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE;
@@ -137,15 +139,15 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
}
ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR,
- SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE |
- SDPIF_CFGR_VDW_MASK,
- val);
+ SPDIF_CFGR_CLK_DIV_MASK |
+ SPDIF_CFGR_HALFWORD_ENABLE |
+ SDPIF_CFGR_VDW_MASK, val);
return ret;
}
static int rk_spdif_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_soc_dai *dai)
+ int cmd, struct snd_soc_dai *dai)
{
struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
int ret;
@@ -155,31 +157,31 @@ static int rk_spdif_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR,
- SPDIF_DMACR_TDE_ENABLE |
- SPDIF_DMACR_TDL_MASK,
- SPDIF_DMACR_TDE_ENABLE |
- SPDIF_DMACR_TDL(16));
+ SPDIF_DMACR_TDE_ENABLE |
+ SPDIF_DMACR_TDL_MASK,
+ SPDIF_DMACR_TDE_ENABLE |
+ SPDIF_DMACR_TDL(16));
if (ret != 0)
return ret;
ret = regmap_update_bits(spdif->regmap, SPDIF_XFER,
- SPDIF_XFER_TXS_START,
- SPDIF_XFER_TXS_START);
+ SPDIF_XFER_TXS_START,
+ SPDIF_XFER_TXS_START);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR,
- SPDIF_DMACR_TDE_ENABLE,
- SPDIF_DMACR_TDE_DISABLE);
+ SPDIF_DMACR_TDE_ENABLE,
+ SPDIF_DMACR_TDE_DISABLE);
if (ret != 0)
return ret;
ret = regmap_update_bits(spdif->regmap, SPDIF_XFER,
- SPDIF_XFER_TXS_START,
- SPDIF_XFER_TXS_STOP);
+ SPDIF_XFER_TXS_START,
+ SPDIF_XFER_TXS_STOP);
break;
default:
ret = -EINVAL;
@@ -247,6 +249,7 @@ static bool rk_spdif_rd_reg(struct device *dev, unsigned int reg)
case SPDIF_INTCR:
case SPDIF_INTSR:
case SPDIF_XFER:
+ case SPDIF_SMPDR:
return true;
default:
return false;
@@ -258,6 +261,7 @@ static bool rk_spdif_volatile_reg(struct device *dev, unsigned int reg)
switch (reg) {
case SPDIF_INTSR:
case SPDIF_SDBLR:
+ case SPDIF_SMPDR:
return true;
default:
return false;
@@ -291,7 +295,7 @@ static int rk_spdif_probe(struct platform_device *pdev)
grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
if (IS_ERR(grf)) {
dev_err(&pdev->dev,
- "rockchip_spdif missing 'rockchip,grf' \n");
+ "rockchip_spdif missing 'rockchip,grf'\n");
return PTR_ERR(grf);
}
diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c
index 0ac5956ba270..313ab650f8d9 100644
--- a/sound/soc/samsung/aries_wm8994.c
+++ b/sound/soc/samsung/aries_wm8994.c
@@ -310,7 +310,7 @@ static int aries_hw_free(struct snd_pcm_substream *substream)
/*
* Main DAI operations
*/
-static struct snd_soc_ops aries_ops = {
+static const struct snd_soc_ops aries_ops = {
.hw_params = aries_hw_params,
.hw_free = aries_hw_free,
};
diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c
index 28587375813a..606ac5e33a8e 100644
--- a/sound/soc/samsung/arndale.c
+++ b/sound/soc/samsung/arndale.c
@@ -48,7 +48,7 @@ static int arndale_rt5631_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_ops arndale_rt5631_ops = {
+static const struct snd_soc_ops arndale_rt5631_ops = {
.hw_params = arndale_rt5631_hw_params,
};
@@ -80,7 +80,7 @@ static int arndale_wm1811_hw_params(struct snd_pcm_substream *substream,
rclk + 1, SND_SOC_CLOCK_IN);
}
-static struct snd_soc_ops arndale_wm1811_ops = {
+static const struct snd_soc_ops arndale_wm1811_ops = {
.hw_params = arndale_wm1811_hw_params,
};
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index 8aa78ff640f5..c994e67d1eaf 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -112,7 +112,7 @@ static int h1940_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_ops h1940_ops = {
+static const struct snd_soc_ops h1940_ops = {
.startup = h1940_startup,
.hw_params = h1940_hw_params,
};
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index a1ff1400857e..390f2dd735ad 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -130,7 +130,7 @@ static int littlemill_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_ops littlemill_ops = {
+static const struct snd_soc_ops littlemill_ops = {
.hw_params = littlemill_hw_params,
};
diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c
index 1f9a553edf19..a2019535a0b1 100644
--- a/sound/soc/samsung/midas_wm1811.c
+++ b/sound/soc/samsung/midas_wm1811.c
@@ -129,7 +129,7 @@ static int midas_aif1_hw_params(struct snd_pcm_substream *substream,
return midas_start_fll1(rtd, pll_out);
}
-static struct snd_soc_ops midas_aif1_ops = {
+static const struct snd_soc_ops midas_aif1_ops = {
.hw_params = midas_aif1_hw_params,
};
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 9266070e0181..c98b68567a89 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -106,7 +106,7 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
/*
* Neo1973 WM8753 HiFi DAI opserations.
*/
-static struct snd_soc_ops neo1973_hifi_ops = {
+static const struct snd_soc_ops neo1973_hifi_ops = {
.hw_params = neo1973_hifi_hw_params,
.hw_free = neo1973_hifi_hw_free,
};
@@ -158,7 +158,7 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
}
-static struct snd_soc_ops neo1973_voice_ops = {
+static const struct snd_soc_ops neo1973_voice_ops = {
.hw_params = neo1973_voice_hw_params,
.hw_free = neo1973_voice_hw_free,
};
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index 400a7f77c711..6ea1c8cc9167 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -62,7 +62,7 @@ static struct snd_soc_jack_gpio hp_jack_gpios[] = {
},
};
-static struct snd_soc_ops rx1950_ops = {
+static const struct snd_soc_ops rx1950_ops = {
.startup = rx1950_startup,
.hw_params = rx1950_hw_params,
};
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c
index c95629becbc3..cee39ad16667 100644
--- a/sound/soc/samsung/smartq_wm8987.c
+++ b/sound/soc/samsung/smartq_wm8987.c
@@ -70,7 +70,7 @@ static int smartq_hifi_hw_params(struct snd_pcm_substream *substream,
/*
* SmartQ WM8987 HiFi DAI operations.
*/
-static struct snd_soc_ops smartq_hifi_ops = {
+static const struct snd_soc_ops smartq_hifi_ops = {
.hw_params = smartq_hifi_hw_params,
};
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index ed753a2f202e..78703d095a6f 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -86,7 +86,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
/*
* SMDK WM8580 DAI operations.
*/
-static struct snd_soc_ops smdk_ops = {
+static const struct snd_soc_ops smdk_ops = {
.hw_params = smdk_hw_params,
};
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 39a7a449f554..7661b637946d 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -73,7 +73,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
/*
* SMDK WM8994 DAI operations.
*/
-static struct snd_soc_ops smdk_ops = {
+static const struct snd_soc_ops smdk_ops = {
.hw_params = smdk_hw_params,
};
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c
index a01640576f71..029448f5bedb 100644
--- a/sound/soc/samsung/smdk_wm8994pcm.c
+++ b/sound/soc/samsung/smdk_wm8994pcm.c
@@ -85,7 +85,7 @@ static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_ops smdk_wm8994_pcm_ops = {
+static const struct snd_soc_ops smdk_wm8994_pcm_ops = {
.hw_params = smdk_wm8994_pcm_hw_params,
};
diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c
index 84c2c63d5a87..a2c77e6defec 100644
--- a/sound/soc/samsung/tm2_wm5110.c
+++ b/sound/soc/samsung/tm2_wm5110.c
@@ -126,7 +126,7 @@ static int tm2_aif1_hw_params(struct snd_pcm_substream *substream,
return tm2_start_sysclk(rtd->card);
}
-static struct snd_soc_ops tm2_aif1_ops = {
+static const struct snd_soc_ops tm2_aif1_ops = {
.hw_params = tm2_aif1_hw_params,
};
@@ -200,7 +200,7 @@ static int tm2_aif2_hw_free(struct snd_pcm_substream *substream)
return ret;
}
-static struct snd_soc_ops tm2_aif2_ops = {
+static const struct snd_soc_ops tm2_aif2_ops = {
.hw_params = tm2_aif2_hw_params,
.hw_free = tm2_aif2_hw_free,
};
@@ -254,7 +254,7 @@ static int tm2_hdmi_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_ops tm2_hdmi_ops = {
+static const struct snd_soc_ops tm2_hdmi_ops = {
.hw_params = tm2_hdmi_hw_params,
};
diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
index c962d2c2a7f7..15223d860cb7 100644
--- a/sound/soc/samsung/tobermory.c
+++ b/sound/soc/samsung/tobermory.c
@@ -105,7 +105,7 @@ static int tobermory_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_ops tobermory_ops = {
+static const struct snd_soc_ops tobermory_ops = {
.hw_params = tobermory_hw_params,
};
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 346c806ba390..ae46f187cc2a 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -45,6 +45,12 @@ config SND_SOC_RCAR
help
This option enables R-Car SRU/SCU/SSIU/SSI sound support
+config SND_SOC_RZ
+ tristate "RZ/G2L series SSIF-2 support"
+ depends on ARCH_R9A07G044 || COMPILE_TEST
+ help
+ This option enables RZ/G2L SSIF-2 sound support.
+
##
## Boards
##
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index 51bd7c81671c..f6fd79948f6a 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -22,3 +22,7 @@ snd-soc-migor-objs := migor.o
obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
+
+# RZ/G2L
+snd-soc-rz-ssi-objs := rz-ssi.o
+obj-$(CONFIG_SND_SOC_RZ) += snd-soc-rz-ssi.o
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 0ebee1ed06a9..5f1e72edfee0 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -391,9 +391,9 @@ static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
struct clk *clk;
clk = clk_register_fixed_rate(dev, name, parent, 0, 0);
- if (IS_ERR(clk)) {
+ if (IS_ERR_OR_NULL(clk)) {
dev_err(dev, "create null clk error\n");
- return NULL;
+ return ERR_CAST(clk);
}
return clk;
@@ -430,9 +430,9 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
for (i = 0; i < CLKMAX; i++) {
clk = devm_clk_get(dev, clk_name[i]);
- if (IS_ERR(clk))
+ if (IS_ERR_OR_NULL(clk))
clk = rsnd_adg_null_clk_get(priv);
- if (IS_ERR(clk))
+ if (IS_ERR_OR_NULL(clk))
goto err;
adg->clk[i] = clk;
@@ -582,7 +582,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
if (!count) {
clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
parent_clk_name, 0, req_rate[0]);
- if (IS_ERR(clk))
+ if (IS_ERR_OR_NULL(clk))
goto err;
adg->clkout[CLKOUT] = clk;
@@ -596,7 +596,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
clk = clk_register_fixed_rate(dev, clkout_name[i],
parent_clk_name, 0,
req_rate[0]);
- if (IS_ERR(clk))
+ if (IS_ERR_OR_NULL(clk))
goto err;
adg->clkout[i] = clk;
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 5e382b5c9d45..978bd0406729 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -426,19 +426,19 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
{
- enum rsnd_mod_type playback_mods[] = {
+ static const enum rsnd_mod_type playback_mods[] = {
RSND_MOD_SRC,
RSND_MOD_CMD,
RSND_MOD_SSIU,
};
- enum rsnd_mod_type capture_mods[] = {
+ static const enum rsnd_mod_type capture_mods[] = {
RSND_MOD_CMD,
RSND_MOD_SRC,
RSND_MOD_SSIU,
};
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct rsnd_mod *tmod = NULL;
- enum rsnd_mod_type *mods =
+ const enum rsnd_mod_type *mods =
rsnd_io_is_play(io) ?
playback_mods : capture_mods;
int i;
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 82d16e037d9a..16c6e0265749 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -102,7 +102,7 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod,
struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
if (dmaen->chan)
- dmaengine_terminate_all(dmaen->chan);
+ dmaengine_terminate_sync(dmaen->chan);
return 0;
}
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 27f34ca6059d..87e606f688d3 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -165,7 +165,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod,
static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io)
{
- enum rsnd_mod_type types[] = {
+ static const enum rsnd_mod_type types[] = {
RSND_MOD_SSIM1,
RSND_MOD_SSIM2,
RSND_MOD_SSIM3,
@@ -228,7 +228,7 @@ unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai,
int param1, int param2, int *idx)
{
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- int ssi_clk_mul_table[] = {
+ static const int ssi_clk_mul_table[] = {
1, 2, 4, 8, 16, 6, 12,
};
int j, ret;
@@ -1079,7 +1079,7 @@ static void rsnd_ssi_connect(struct rsnd_mod *mod,
struct rsnd_dai_stream *io)
{
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- enum rsnd_mod_type types[] = {
+ static const enum rsnd_mod_type types[] = {
RSND_MOD_SSI,
RSND_MOD_SSIM1,
RSND_MOD_SSIM2,
diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
new file mode 100644
index 000000000000..fa0cc08f70ec
--- /dev/null
+++ b/sound/soc/sh/rz-ssi.c
@@ -0,0 +1,1074 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Renesas RZ/G2L ASoC Serial Sound Interface (SSIF-2) Driver
+//
+// Copyright (C) 2021 Renesas Electronics Corp.
+// Copyright (C) 2019 Chris Brandt.
+//
+
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <sound/soc.h>
+
+/* REGISTER OFFSET */
+#define SSICR 0x000
+#define SSISR 0x004
+#define SSIFCR 0x010
+#define SSIFSR 0x014
+#define SSIFTDR 0x018
+#define SSIFRDR 0x01c
+#define SSIOFR 0x020
+#define SSISCR 0x024
+
+/* SSI REGISTER BITS */
+#define SSICR_DWL(x) (((x) & 0x7) << 19)
+#define SSICR_SWL(x) (((x) & 0x7) << 16)
+#define SSICR_MST BIT(14)
+#define SSICR_CKDV(x) (((x) & 0xf) << 4)
+
+#define SSICR_CKS BIT(30)
+#define SSICR_TUIEN BIT(29)
+#define SSICR_TOIEN BIT(28)
+#define SSICR_RUIEN BIT(27)
+#define SSICR_ROIEN BIT(26)
+#define SSICR_MST BIT(14)
+#define SSICR_BCKP BIT(13)
+#define SSICR_LRCKP BIT(12)
+#define SSICR_CKDV(x) (((x) & 0xf) << 4)
+#define SSICR_TEN BIT(1)
+#define SSICR_REN BIT(0)
+
+#define SSISR_TUIRQ BIT(29)
+#define SSISR_TOIRQ BIT(28)
+#define SSISR_RUIRQ BIT(27)
+#define SSISR_ROIRQ BIT(26)
+#define SSISR_IIRQ BIT(25)
+
+#define SSIFCR_AUCKE BIT(31)
+#define SSIFCR_SSIRST BIT(16)
+#define SSIFCR_TIE BIT(3)
+#define SSIFCR_RIE BIT(2)
+#define SSIFCR_TFRST BIT(1)
+#define SSIFCR_RFRST BIT(0)
+
+#define SSIFSR_TDC_MASK 0x3f
+#define SSIFSR_TDC_SHIFT 24
+#define SSIFSR_RDC_MASK 0x3f
+#define SSIFSR_RDC_SHIFT 8
+
+#define SSIFSR_TDC(x) (((x) & 0x1f) << 24)
+#define SSIFSR_TDE BIT(16)
+#define SSIFSR_RDC(x) (((x) & 0x1f) << 8)
+#define SSIFSR_RDF BIT(0)
+
+#define SSIOFR_LRCONT BIT(8)
+
+#define SSISCR_TDES(x) (((x) & 0x1f) << 8)
+#define SSISCR_RDFS(x) (((x) & 0x1f) << 0)
+
+/* Pre allocated buffers sizes */
+#define PREALLOC_BUFFER (SZ_32K)
+#define PREALLOC_BUFFER_MAX (SZ_32K)
+
+#define SSI_RATES SNDRV_PCM_RATE_8000_48000 /* 8k-44.1kHz */
+#define SSI_FMTS SNDRV_PCM_FMTBIT_S16_LE
+#define SSI_CHAN_MIN 2
+#define SSI_CHAN_MAX 2
+#define SSI_FIFO_DEPTH 32
+
+struct rz_ssi_priv;
+
+struct rz_ssi_stream {
+ struct rz_ssi_priv *priv;
+ struct snd_pcm_substream *substream;
+ int fifo_sample_size; /* sample capacity of SSI FIFO */
+ int dma_buffer_pos; /* The address for the next DMA descriptor */
+ int period_counter; /* for keeping track of periods transferred */
+ int sample_width;
+ int buffer_pos; /* current frame position in the buffer */
+ int running; /* 0=stopped, 1=running */
+
+ int uerr_num;
+ int oerr_num;
+
+ struct dma_chan *dma_ch;
+
+ int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm);
+};
+
+struct rz_ssi_priv {
+ void __iomem *base;
+ struct platform_device *pdev;
+ struct reset_control *rstc;
+ struct device *dev;
+ struct clk *sfr_clk;
+ struct clk *clk;
+
+ phys_addr_t phys;
+ int irq_int;
+ int irq_tx;
+ int irq_rx;
+
+ spinlock_t lock;
+
+ /*
+ * The SSI supports full-duplex transmission and reception.
+ * However, if an error occurs, channel reset (both transmission
+ * and reception reset) is required.
+ * So it is better to use as half-duplex (playing and recording
+ * should be done on separate channels).
+ */
+ struct rz_ssi_stream playback;
+ struct rz_ssi_stream capture;
+
+ /* clock */
+ unsigned long audio_mck;
+ unsigned long audio_clk_1;
+ unsigned long audio_clk_2;
+
+ bool lrckp_fsync_fall; /* LR clock polarity (SSICR.LRCKP) */
+ bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */
+ bool dma_rt;
+};
+
+static void rz_ssi_dma_complete(void *data);
+
+static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data)
+{
+ writel(data, (priv->base + reg));
+}
+
+static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg)
+{
+ return readl(priv->base + reg);
+}
+
+static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg,
+ u32 bclr, u32 bset)
+{
+ u32 val;
+
+ val = readl(priv->base + reg);
+ val = (val & ~bclr) | bset;
+ writel(val, (priv->base + reg));
+}
+
+static inline struct snd_soc_dai *
+rz_ssi_get_dai(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+
+ return asoc_rtd_to_cpu(rtd, 0);
+}
+
+static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi,
+ struct snd_pcm_substream *substream)
+{
+ return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
+static inline struct rz_ssi_stream *
+rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
+{
+ struct rz_ssi_stream *stream = &ssi->playback;
+
+ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+ stream = &ssi->capture;
+
+ return stream;
+}
+
+static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
+{
+ return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch));
+}
+
+static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
+ struct rz_ssi_stream *strm)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&ssi->lock, flags);
+ ret = !!(strm->substream && strm->substream->runtime);
+ spin_unlock_irqrestore(&ssi->lock, flags);
+
+ return ret;
+}
+
+static int rz_ssi_stream_init(struct rz_ssi_priv *ssi,
+ struct rz_ssi_stream *strm,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ strm->substream = substream;
+ strm->sample_width = samples_to_bytes(runtime, 1);
+ strm->dma_buffer_pos = 0;
+ strm->period_counter = 0;
+ strm->buffer_pos = 0;
+
+ strm->oerr_num = 0;
+ strm->uerr_num = 0;
+ strm->running = 0;
+
+ /* fifo init */
+ strm->fifo_sample_size = SSI_FIFO_DEPTH;
+
+ return 0;
+}
+
+static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi,
+ struct rz_ssi_stream *strm)
+{
+ struct snd_soc_dai *dai = rz_ssi_get_dai(strm->substream);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ssi->lock, flags);
+ strm->substream = NULL;
+ spin_unlock_irqrestore(&ssi->lock, flags);
+
+ if (strm->oerr_num > 0)
+ dev_info(dai->dev, "overrun = %d\n", strm->oerr_num);
+
+ if (strm->uerr_num > 0)
+ dev_info(dai->dev, "underrun = %d\n", strm->uerr_num);
+}
+
+static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
+ unsigned int channels)
+{
+ static s8 ckdv[16] = { 1, 2, 4, 8, 16, 32, 64, 128,
+ 6, 12, 24, 48, 96, -1, -1, -1 };
+ unsigned int channel_bits = 32; /* System Word Length */
+ unsigned long bclk_rate = rate * channels * channel_bits;
+ unsigned int div;
+ unsigned int i;
+ u32 ssicr = 0;
+ u32 clk_ckdv;
+
+ /* Clear AUCKE so we can set MST */
+ rz_ssi_reg_writel(ssi, SSIFCR, 0);
+
+ /* Continue to output LRCK pin even when idle */
+ rz_ssi_reg_writel(ssi, SSIOFR, SSIOFR_LRCONT);
+ if (ssi->audio_clk_1 && ssi->audio_clk_2) {
+ if (ssi->audio_clk_1 % bclk_rate)
+ ssi->audio_mck = ssi->audio_clk_2;
+ else
+ ssi->audio_mck = ssi->audio_clk_1;
+ }
+
+ /* Clock setting */
+ ssicr |= SSICR_MST;
+ if (ssi->audio_mck == ssi->audio_clk_1)
+ ssicr |= SSICR_CKS;
+ if (ssi->bckp_rise)
+ ssicr |= SSICR_BCKP;
+ if (ssi->lrckp_fsync_fall)
+ ssicr |= SSICR_LRCKP;
+
+ /* Determine the clock divider */
+ clk_ckdv = 0;
+ div = ssi->audio_mck / bclk_rate;
+ /* try to find an match */
+ for (i = 0; i < ARRAY_SIZE(ckdv); i++) {
+ if (ckdv[i] == div) {
+ clk_ckdv = i;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(ckdv)) {
+ dev_err(ssi->dev, "Rate not divisible by audio clock source\n");
+ return -EINVAL;
+ }
+
+ /*
+ * DWL: Data Word Length = 16 bits
+ * SWL: System Word Length = 32 bits
+ */
+ ssicr |= SSICR_CKDV(clk_ckdv);
+ ssicr |= SSICR_DWL(1) | SSICR_SWL(3);
+ rz_ssi_reg_writel(ssi, SSICR, ssicr);
+ rz_ssi_reg_writel(ssi, SSIFCR,
+ (SSIFCR_AUCKE | SSIFCR_TFRST | SSIFCR_RFRST));
+
+ return 0;
+}
+
+static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+ bool is_play = rz_ssi_stream_is_play(ssi, strm->substream);
+ u32 ssicr, ssifcr;
+
+ ssicr = rz_ssi_reg_readl(ssi, SSICR);
+ ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF;
+
+ /* FIFO interrupt thresholds */
+ if (rz_ssi_is_dma_enabled(ssi))
+ rz_ssi_reg_writel(ssi, SSISCR, 0);
+ else
+ rz_ssi_reg_writel(ssi, SSISCR,
+ SSISCR_TDES(strm->fifo_sample_size / 2 - 1) |
+ SSISCR_RDFS(0));
+
+ /* enable IRQ */
+ if (is_play) {
+ ssicr |= SSICR_TUIEN | SSICR_TOIEN;
+ ssifcr |= SSIFCR_TIE | SSIFCR_RFRST;
+ } else {
+ ssicr |= SSICR_RUIEN | SSICR_ROIEN;
+ ssifcr |= SSIFCR_RIE | SSIFCR_TFRST;
+ }
+
+ rz_ssi_reg_writel(ssi, SSICR, ssicr);
+ rz_ssi_reg_writel(ssi, SSIFCR, ssifcr);
+
+ /* Clear all error flags */
+ rz_ssi_reg_mask_setl(ssi, SSISR,
+ (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
+ SSISR_RUIRQ), 0);
+
+ strm->running = 1;
+ ssicr |= is_play ? SSICR_TEN : SSICR_REN;
+ rz_ssi_reg_writel(ssi, SSICR, ssicr);
+
+ return 0;
+}
+
+static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+ int timeout;
+
+ strm->running = 0;
+
+ /* Disable TX/RX */
+ rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
+
+ /* Cancel all remaining DMA transactions */
+ if (rz_ssi_is_dma_enabled(ssi))
+ dmaengine_terminate_async(strm->dma_ch);
+
+ /* Disable irqs */
+ rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN |
+ SSICR_RUIEN | SSICR_ROIEN, 0);
+ rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0);
+
+ /* Clear all error flags */
+ rz_ssi_reg_mask_setl(ssi, SSISR,
+ (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
+ SSISR_RUIRQ), 0);
+
+ /* Wait for idle */
+ timeout = 100;
+ while (--timeout) {
+ if (rz_ssi_reg_readl(ssi, SSISR) & SSISR_IIRQ)
+ break;
+ udelay(1);
+ }
+
+ if (!timeout)
+ dev_info(ssi->dev, "timeout waiting for SSI idle\n");
+
+ /* Hold FIFOs in reset */
+ rz_ssi_reg_mask_setl(ssi, SSIFCR, 0,
+ SSIFCR_TFRST | SSIFCR_RFRST);
+
+ return 0;
+}
+
+static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames)
+{
+ struct snd_pcm_substream *substream = strm->substream;
+ struct snd_pcm_runtime *runtime;
+ int current_period;
+
+ if (!strm->running || !substream || !substream->runtime)
+ return;
+
+ runtime = substream->runtime;
+ strm->buffer_pos += frames;
+ WARN_ON(strm->buffer_pos > runtime->buffer_size);
+
+ /* ring buffer */
+ if (strm->buffer_pos == runtime->buffer_size)
+ strm->buffer_pos = 0;
+
+ current_period = strm->buffer_pos / runtime->period_size;
+ if (strm->period_counter != current_period) {
+ snd_pcm_period_elapsed(strm->substream);
+ strm->period_counter = current_period;
+ }
+}
+
+static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+ struct snd_pcm_substream *substream = strm->substream;
+ struct snd_pcm_runtime *runtime;
+ u16 *buf;
+ int fifo_samples;
+ int frames_left;
+ int samples = 0;
+ int i;
+
+ if (!rz_ssi_stream_is_valid(ssi, strm))
+ return -EINVAL;
+
+ runtime = substream->runtime;
+ /* frames left in this period */
+ frames_left = runtime->period_size - (strm->buffer_pos %
+ runtime->period_size);
+ if (frames_left == 0)
+ frames_left = runtime->period_size;
+
+ /* Samples in RX FIFO */
+ fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
+ SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
+
+ /* Only read full frames at a time */
+ while (frames_left && (fifo_samples >= runtime->channels)) {
+ samples += runtime->channels;
+ fifo_samples -= runtime->channels;
+ frames_left--;
+ }
+
+ /* not enough samples yet */
+ if (samples == 0)
+ return 0;
+
+ /* calculate new buffer index */
+ buf = (u16 *)(runtime->dma_area);
+ buf += strm->buffer_pos * runtime->channels;
+
+ /* Note, only supports 16-bit samples */
+ for (i = 0; i < samples; i++)
+ *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
+
+ rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
+ rz_ssi_pointer_update(strm, samples / runtime->channels);
+
+ /*
+ * If we finished this period, but there are more samples in
+ * the RX FIFO, call this function again
+ */
+ if (frames_left == 0 && fifo_samples >= runtime->channels)
+ rz_ssi_pio_recv(ssi, strm);
+
+ return 0;
+}
+
+static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+ struct snd_pcm_substream *substream = strm->substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int sample_space;
+ int samples = 0;
+ int frames_left;
+ int i;
+ u32 ssifsr;
+ u16 *buf;
+
+ if (!rz_ssi_stream_is_valid(ssi, strm))
+ return -EINVAL;
+
+ /* frames left in this period */
+ frames_left = runtime->period_size - (strm->buffer_pos %
+ runtime->period_size);
+ if (frames_left == 0)
+ frames_left = runtime->period_size;
+
+ sample_space = strm->fifo_sample_size;
+ ssifsr = rz_ssi_reg_readl(ssi, SSIFSR);
+ sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) & SSIFSR_TDC_MASK;
+
+ /* Only add full frames at a time */
+ while (frames_left && (sample_space >= runtime->channels)) {
+ samples += runtime->channels;
+ sample_space -= runtime->channels;
+ frames_left--;
+ }
+
+ /* no space to send anything right now */
+ if (samples == 0)
+ return 0;
+
+ /* calculate new buffer index */
+ buf = (u16 *)(runtime->dma_area);
+ buf += strm->buffer_pos * runtime->channels;
+
+ /* Note, only supports 16-bit samples */
+ for (i = 0; i < samples; i++)
+ rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16));
+
+ rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0);
+ rz_ssi_pointer_update(strm, samples / runtime->channels);
+
+ return 0;
+}
+
+static irqreturn_t rz_ssi_interrupt(int irq, void *data)
+{
+ struct rz_ssi_stream *strm = NULL;
+ struct rz_ssi_priv *ssi = data;
+ u32 ssisr = rz_ssi_reg_readl(ssi, SSISR);
+
+ if (ssi->playback.substream)
+ strm = &ssi->playback;
+ else if (ssi->capture.substream)
+ strm = &ssi->capture;
+ else
+ return IRQ_HANDLED; /* Left over TX/RX interrupt */
+
+ if (irq == ssi->irq_int) { /* error or idle */
+ if (ssisr & SSISR_TUIRQ)
+ strm->uerr_num++;
+ if (ssisr & SSISR_TOIRQ)
+ strm->oerr_num++;
+ if (ssisr & SSISR_RUIRQ)
+ strm->uerr_num++;
+ if (ssisr & SSISR_ROIRQ)
+ strm->oerr_num++;
+
+ if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ |
+ SSISR_ROIRQ)) {
+ /* Error handling */
+ /* You must reset (stop/restart) after each interrupt */
+ rz_ssi_stop(ssi, strm);
+
+ /* Clear all flags */
+ rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ |
+ SSISR_TUIRQ | SSISR_ROIRQ |
+ SSISR_RUIRQ, 0);
+
+ /* Add/remove more data */
+ strm->transfer(ssi, strm);
+
+ /* Resume */
+ rz_ssi_start(ssi, strm);
+ }
+ }
+
+ if (!strm->running)
+ return IRQ_HANDLED;
+
+ /* tx data empty */
+ if (irq == ssi->irq_tx)
+ strm->transfer(ssi, &ssi->playback);
+
+ /* rx data full */
+ if (irq == ssi->irq_rx) {
+ strm->transfer(ssi, &ssi->capture);
+ rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi,
+ struct dma_chan *dma_ch, bool is_play)
+{
+ struct dma_slave_config cfg;
+
+ memset(&cfg, 0, sizeof(cfg));
+
+ cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+ cfg.dst_addr = ssi->phys + SSIFTDR;
+ cfg.src_addr = ssi->phys + SSIFRDR;
+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+ return dmaengine_slave_config(dma_ch, &cfg);
+}
+
+static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi,
+ struct rz_ssi_stream *strm)
+{
+ struct snd_pcm_substream *substream = strm->substream;
+ struct dma_async_tx_descriptor *desc;
+ struct snd_pcm_runtime *runtime;
+ enum dma_transfer_direction dir;
+ u32 dma_paddr, dma_size;
+ int amount;
+
+ if (!rz_ssi_stream_is_valid(ssi, strm))
+ return -EINVAL;
+
+ runtime = substream->runtime;
+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+ /*
+ * Stream is ending, so do not queue up any more DMA
+ * transfers otherwise we play partial sound clips
+ * because we can't shut off the DMA quick enough.
+ */
+ return 0;
+
+ dir = rz_ssi_stream_is_play(ssi, substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+
+ /* Always transfer 1 period */
+ amount = runtime->period_size;
+
+ /* DMA physical address and size */
+ dma_paddr = runtime->dma_addr + frames_to_bytes(runtime,
+ strm->dma_buffer_pos);
+ dma_size = frames_to_bytes(runtime, amount);
+ desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size,
+ dir,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n");
+ return -ENOMEM;
+ }
+
+ desc->callback = rz_ssi_dma_complete;
+ desc->callback_param = strm;
+
+ if (dmaengine_submit(desc) < 0) {
+ dev_err(ssi->dev, "dmaengine_submit() fail\n");
+ return -EIO;
+ }
+
+ /* Update DMA pointer */
+ strm->dma_buffer_pos += amount;
+ if (strm->dma_buffer_pos >= runtime->buffer_size)
+ strm->dma_buffer_pos = 0;
+
+ /* Start DMA */
+ dma_async_issue_pending(strm->dma_ch);
+
+ return 0;
+}
+
+static void rz_ssi_dma_complete(void *data)
+{
+ struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data;
+
+ if (!strm->running || !strm->substream || !strm->substream->runtime)
+ return;
+
+ /* Note that next DMA transaction has probably already started */
+ rz_ssi_pointer_update(strm, strm->substream->runtime->period_size);
+
+ /* Queue up another DMA transaction */
+ rz_ssi_dma_transfer(strm->priv, strm);
+}
+
+static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi)
+{
+ if (ssi->playback.dma_ch) {
+ dma_release_channel(ssi->playback.dma_ch);
+ ssi->playback.dma_ch = NULL;
+ if (ssi->dma_rt)
+ ssi->dma_rt = false;
+ }
+
+ if (ssi->capture.dma_ch) {
+ dma_release_channel(ssi->capture.dma_ch);
+ ssi->capture.dma_ch = NULL;
+ }
+}
+
+static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev)
+{
+ ssi->playback.dma_ch = dma_request_chan(dev, "tx");
+ if (IS_ERR(ssi->playback.dma_ch))
+ ssi->playback.dma_ch = NULL;
+
+ ssi->capture.dma_ch = dma_request_chan(dev, "rx");
+ if (IS_ERR(ssi->capture.dma_ch))
+ ssi->capture.dma_ch = NULL;
+
+ if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) {
+ ssi->playback.dma_ch = dma_request_chan(dev, "rt");
+ if (IS_ERR(ssi->playback.dma_ch)) {
+ ssi->playback.dma_ch = NULL;
+ goto no_dma;
+ }
+
+ ssi->dma_rt = true;
+ }
+
+ if (!rz_ssi_is_dma_enabled(ssi))
+ goto no_dma;
+
+ if (ssi->playback.dma_ch &&
+ (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0))
+ goto no_dma;
+
+ if (ssi->capture.dma_ch &&
+ (rz_ssi_dma_slave_config(ssi, ssi->capture.dma_ch, false) < 0))
+ goto no_dma;
+
+ return 0;
+
+no_dma:
+ rz_ssi_release_dma_channels(ssi);
+
+ return -ENODEV;
+}
+
+static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+ struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
+ int ret = 0, i, num_transfer = 1;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* Soft Reset */
+ rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST);
+ rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0);
+ udelay(5);
+
+ ret = rz_ssi_stream_init(ssi, strm, substream);
+ if (ret)
+ goto done;
+
+ if (ssi->dma_rt) {
+ bool is_playback;
+
+ is_playback = rz_ssi_stream_is_play(ssi, substream);
+ ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch,
+ is_playback);
+ /* Fallback to pio */
+ if (ret < 0) {
+ ssi->playback.transfer = rz_ssi_pio_send;
+ ssi->capture.transfer = rz_ssi_pio_recv;
+ rz_ssi_release_dma_channels(ssi);
+ }
+ }
+
+ /* For DMA, queue up multiple DMA descriptors */
+ if (rz_ssi_is_dma_enabled(ssi))
+ num_transfer = 4;
+
+ for (i = 0; i < num_transfer; i++) {
+ ret = strm->transfer(ssi, strm);
+ if (ret)
+ goto done;
+ }
+
+ ret = rz_ssi_start(ssi, strm);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ rz_ssi_stop(ssi, strm);
+ rz_ssi_stream_quit(ssi, strm);
+ break;
+ }
+
+done:
+ return ret;
+}
+
+static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+
+ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
+ case SND_SOC_DAIFMT_CBC_CFC:
+ break;
+ default:
+ dev_err(ssi->dev, "Codec should be clk and frame consumer\n");
+ return -EINVAL;
+ }
+
+ /*
+ * set clock polarity
+ *
+ * "normal" BCLK = Signal is available at rising edge of BCLK
+ * "normal" FSYNC = (I2S) Left ch starts with falling FSYNC edge
+ */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ ssi->bckp_rise = false;
+ ssi->lrckp_fsync_fall = false;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ ssi->bckp_rise = false;
+ ssi->lrckp_fsync_fall = true;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ ssi->bckp_rise = true;
+ ssi->lrckp_fsync_fall = false;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ ssi->bckp_rise = true;
+ ssi->lrckp_fsync_fall = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* only i2s support */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ default:
+ dev_err(ssi->dev, "Only I2S mode is supported.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+ unsigned int sample_bits = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
+ unsigned int channels = params_channels(params);
+
+ if (sample_bits != 16) {
+ dev_err(ssi->dev, "Unsupported sample width: %d\n",
+ sample_bits);
+ return -EINVAL;
+ }
+
+ if (channels != 2) {
+ dev_err(ssi->dev, "Number of channels not matched: %d\n",
+ channels);
+ return -EINVAL;
+ }
+
+ return rz_ssi_clk_setup(ssi, params_rate(params),
+ params_channels(params));
+}
+
+static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
+ .trigger = rz_ssi_dai_trigger,
+ .set_fmt = rz_ssi_dai_set_fmt,
+ .hw_params = rz_ssi_dai_hw_params,
+};
+
+static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .buffer_bytes_max = PREALLOC_BUFFER,
+ .period_bytes_min = 32,
+ .period_bytes_max = 8192,
+ .channels_min = SSI_CHAN_MIN,
+ .channels_max = SSI_CHAN_MAX,
+ .periods_min = 1,
+ .periods_max = 32,
+ .fifo_size = 32 * 2,
+};
+
+static int rz_ssi_pcm_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ snd_soc_set_runtime_hwparams(substream, &rz_ssi_pcm_hardware);
+
+ return snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_soc_dai *dai = rz_ssi_get_dai(substream);
+ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+ struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
+
+ return strm->buffer_pos;
+}
+
+static int rz_ssi_pcm_new(struct snd_soc_component *component,
+ struct snd_soc_pcm_runtime *rtd)
+{
+ snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ rtd->card->snd_card->dev,
+ PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
+ return 0;
+}
+
+static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
+ {
+ .name = "rz-ssi-dai",
+ .playback = {
+ .rates = SSI_RATES,
+ .formats = SSI_FMTS,
+ .channels_min = SSI_CHAN_MIN,
+ .channels_max = SSI_CHAN_MAX,
+ },
+ .capture = {
+ .rates = SSI_RATES,
+ .formats = SSI_FMTS,
+ .channels_min = SSI_CHAN_MIN,
+ .channels_max = SSI_CHAN_MAX,
+ },
+ .ops = &rz_ssi_dai_ops,
+ },
+};
+
+static const struct snd_soc_component_driver rz_ssi_soc_component = {
+ .name = "rz-ssi",
+ .open = rz_ssi_pcm_open,
+ .pointer = rz_ssi_pcm_pointer,
+ .pcm_construct = rz_ssi_pcm_new,
+};
+
+static int rz_ssi_probe(struct platform_device *pdev)
+{
+ struct rz_ssi_priv *ssi;
+ struct clk *audio_clk;
+ struct resource *res;
+ int ret;
+
+ ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL);
+ if (!ssi)
+ return -ENOMEM;
+
+ ssi->pdev = pdev;
+ ssi->dev = &pdev->dev;
+ ssi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(ssi->base))
+ return PTR_ERR(ssi->base);
+
+ ssi->phys = res->start;
+ ssi->clk = devm_clk_get(&pdev->dev, "ssi");
+ if (IS_ERR(ssi->clk))
+ return PTR_ERR(ssi->clk);
+
+ ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr");
+ if (IS_ERR(ssi->sfr_clk))
+ return PTR_ERR(ssi->sfr_clk);
+
+ audio_clk = devm_clk_get(&pdev->dev, "audio_clk1");
+ if (IS_ERR(audio_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk),
+ "no audio clk1");
+
+ ssi->audio_clk_1 = clk_get_rate(audio_clk);
+ audio_clk = devm_clk_get(&pdev->dev, "audio_clk2");
+ if (IS_ERR(audio_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk),
+ "no audio clk2");
+
+ ssi->audio_clk_2 = clk_get_rate(audio_clk);
+ if (!(ssi->audio_clk_1 || ssi->audio_clk_2))
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "no audio clk1 or audio clk2");
+
+ ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
+
+ /* Detect DMA support */
+ ret = rz_ssi_dma_request(ssi, &pdev->dev);
+ if (ret < 0) {
+ dev_warn(&pdev->dev, "DMA not available, using PIO\n");
+ ssi->playback.transfer = rz_ssi_pio_send;
+ ssi->capture.transfer = rz_ssi_pio_recv;
+ } else {
+ dev_info(&pdev->dev, "DMA enabled");
+ ssi->playback.transfer = rz_ssi_dma_transfer;
+ ssi->capture.transfer = rz_ssi_dma_transfer;
+ }
+
+ ssi->playback.priv = ssi;
+ ssi->capture.priv = ssi;
+
+ /* Error Interrupt */
+ ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
+ if (ssi->irq_int < 0)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "Unable to get SSI int_req IRQ\n");
+
+ ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt,
+ 0, dev_name(&pdev->dev), ssi);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "irq request error (int_req)\n");
+
+ if (!rz_ssi_is_dma_enabled(ssi)) {
+ /* Tx and Rx interrupts (pio only) */
+ ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx");
+ if (ssi->irq_tx < 0)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "Unable to get SSI dma_tx IRQ\n");
+
+ ret = devm_request_irq(&pdev->dev, ssi->irq_tx,
+ &rz_ssi_interrupt, 0,
+ dev_name(&pdev->dev), ssi);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "irq request error (dma_tx)\n");
+
+ ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx");
+ if (ssi->irq_rx < 0)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "Unable to get SSI dma_rx IRQ\n");
+
+ ret = devm_request_irq(&pdev->dev, ssi->irq_rx,
+ &rz_ssi_interrupt, 0,
+ dev_name(&pdev->dev), ssi);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "irq request error (dma_rx)\n");
+ }
+
+ ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(ssi->rstc))
+ return PTR_ERR(ssi->rstc);
+
+ reset_control_deassert(ssi->rstc);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_resume_and_get(&pdev->dev);
+
+ spin_lock_init(&ssi->lock);
+ dev_set_drvdata(&pdev->dev, ssi);
+ ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component,
+ rz_ssi_soc_dai,
+ ARRAY_SIZE(rz_ssi_soc_dai));
+ if (ret < 0) {
+ rz_ssi_release_dma_channels(ssi);
+
+ pm_runtime_put(ssi->dev);
+ pm_runtime_disable(ssi->dev);
+ reset_control_assert(ssi->rstc);
+ dev_err(&pdev->dev, "failed to register snd component\n");
+ }
+
+ return ret;
+}
+
+static int rz_ssi_remove(struct platform_device *pdev)
+{
+ struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
+
+ rz_ssi_release_dma_channels(ssi);
+
+ pm_runtime_put(ssi->dev);
+ pm_runtime_disable(ssi->dev);
+ reset_control_assert(ssi->rstc);
+
+ return 0;
+}
+
+static const struct of_device_id rz_ssi_of_match[] = {
+ { .compatible = "renesas,rz-ssi", },
+ {/* Sentinel */},
+};
+MODULE_DEVICE_TABLE(of, rz_ssi_of_match);
+
+static struct platform_driver rz_ssi_driver = {
+ .driver = {
+ .name = "rz-ssi-pcm-audio",
+ .of_match_table = rz_ssi_of_match,
+ },
+ .probe = rz_ssi_probe,
+ .remove = rz_ssi_remove,
+};
+
+module_platform_driver(rz_ssi_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas RZ/G2L ASoC Serial Sound Interface Driver");
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c
index 65db083e242b..5f49e3dec3fc 100644
--- a/sound/soc/soc-ac97.c
+++ b/sound/soc/soc-ac97.c
@@ -34,14 +34,6 @@ struct snd_ac97_reset_cfg {
int gpio_reset;
};
-struct snd_ac97_gpio_priv {
-#ifdef CONFIG_GPIOLIB
- struct gpio_chip gpio_chip;
-#endif
- unsigned int gpios_set;
- struct snd_soc_component *component;
-};
-
static struct snd_ac97_bus soc_ac97_bus = {
.ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */
};
@@ -52,6 +44,12 @@ static void soc_ac97_device_release(struct device *dev)
}
#ifdef CONFIG_GPIOLIB
+struct snd_ac97_gpio_priv {
+ struct gpio_chip gpio_chip;
+ unsigned int gpios_set;
+ struct snd_soc_component *component;
+};
+
static inline struct snd_soc_component *gpio_to_component(struct gpio_chip *chip)
{
struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip);
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index c8dfd0de30e4..8e8d917d22f8 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -1171,10 +1171,10 @@ int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
void *stream)
{
struct snd_soc_component *component;
- int i, ret;
+ int i;
for_each_rtd_components(rtd, i, component) {
- ret = pm_runtime_get_sync(component->dev);
+ int ret = pm_runtime_get_sync(component->dev);
if (ret < 0 && ret != -EACCES) {
pm_runtime_put_noidle(component->dev);
return soc_component_ret(component, ret);
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index b4f59350a5a8..36060800e9bd 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -604,7 +604,6 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
break;
}
- mutex_init(&compr->lock);
ret = snd_compress_new(rtd->card->snd_card, num, direction,
new_name, compr);
if (ret < 0) {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 583f2381cfc8..c830e96afba2 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1718,7 +1718,7 @@ static void append_dmi_string(struct snd_soc_card *card, const char *str)
*/
int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
{
- const char *vendor, *product, *product_version, *board;
+ const char *vendor, *product, *board;
if (card->long_name)
return 0; /* long name already set by driver or from DMI */
@@ -1738,13 +1738,14 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
product = dmi_get_system_info(DMI_PRODUCT_NAME);
if (product && is_dmi_valid(product)) {
+ const char *product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
+
append_dmi_string(card, product);
/*
* some vendors like Lenovo may only put a self-explanatory
* name in the product version field
*/
- product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
if (product_version && is_dmi_valid(product_version))
append_dmi_string(card, product_version);
}
@@ -2236,13 +2237,12 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
const struct snd_kcontrol_new *controls, int num_controls,
const char *prefix, void *data)
{
- int err, i;
+ int i;
for (i = 0; i < num_controls; i++) {
const struct snd_kcontrol_new *control = &controls[i];
-
- err = snd_ctl_add(card, snd_soc_cnew(control, data,
- control->name, prefix));
+ int err = snd_ctl_add(card, snd_soc_cnew(control, data,
+ control->name, prefix));
if (err < 0) {
dev_err(dev, "ASoC: Failed to add %s: %d\n",
control->name, err);
@@ -2716,11 +2716,10 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver);
*/
void snd_soc_unregister_component(struct device *dev)
{
- struct snd_soc_component *component;
-
mutex_lock(&client_mutex);
while (1) {
- component = snd_soc_lookup_component_nolocked(dev, NULL);
+ struct snd_soc_component *component = snd_soc_lookup_component_nolocked(dev, NULL);
+
if (!component)
break;
@@ -2774,7 +2773,7 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
struct device_node *np = card->dev->of_node;
struct snd_soc_dapm_widget *widgets;
const char *template, *wname;
- int i, j, num_widgets, ret;
+ int i, j, num_widgets;
num_widgets = of_property_count_strings(np, propname);
if (num_widgets < 0) {
@@ -2804,8 +2803,8 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
}
for (i = 0; i < num_widgets; i++) {
- ret = of_property_read_string_index(np, propname,
- 2 * i, &template);
+ int ret = of_property_read_string_index(np, propname,
+ 2 * i, &template);
if (ret) {
dev_err(card->dev,
"ASoC: Property '%s' index %d read error:%d\n",
@@ -2928,7 +2927,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
struct device_node *np = card->dev->of_node;
int num_routes;
struct snd_soc_dapm_route *routes;
- int i, ret;
+ int i;
num_routes = of_property_count_strings(np, propname);
if (num_routes < 0 || num_routes & 1) {
@@ -2948,8 +2947,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
}
for (i = 0; i < num_routes; i++) {
- ret = of_property_read_string_index(np, propname,
- 2 * i, &routes[i].sink);
+ int ret = of_property_read_string_index(np, propname,
+ 2 * i, &routes[i].sink);
if (ret) {
dev_err(card->dev,
"ASoC: Property '%s' index %d could not be read: %d\n",
@@ -3053,7 +3052,7 @@ EXPORT_SYMBOL_GPL(snd_soc_daifmt_clock_provider_from_bitmap);
unsigned int snd_soc_daifmt_parse_format(struct device_node *np,
const char *prefix)
{
- int ret, i;
+ int ret;
char prop[128];
unsigned int format = 0;
int bit, frame;
@@ -3087,6 +3086,8 @@ unsigned int snd_soc_daifmt_parse_format(struct device_node *np,
ret = of_property_read_string(np, prop, &str);
}
if (ret == 0) {
+ int i;
+
for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) {
if (strcmp(str, of_fmt_table[i].name) == 0) {
format |= of_fmt_table[i].val;
@@ -3200,12 +3201,11 @@ int snd_soc_get_dai_name(const struct of_phandle_args *args,
const char **dai_name)
{
struct snd_soc_component *pos;
- struct device_node *component_of_node;
int ret = -EPROBE_DEFER;
mutex_lock(&client_mutex);
for_each_component(pos) {
- component_of_node = soc_component_to_node(pos);
+ struct device_node *component_of_node = soc_component_to_node(pos);
if (component_of_node != args->np)
continue;
diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c
index a56dcc8d6fb7..3db0fcf24385 100644
--- a/sound/soc/soc-dai.c
+++ b/sound/soc/soc-dai.c
@@ -492,18 +492,16 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir)
*/
void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
{
- struct snd_soc_dai_link_component *cpu;
- struct snd_soc_dai_link_component *codec;
- struct snd_soc_dai *dai;
bool supported[SNDRV_PCM_STREAM_LAST + 1];
- bool supported_cpu;
- bool supported_codec;
int direction;
- int i;
for_each_pcm_streams(direction) {
- supported_cpu = false;
- supported_codec = false;
+ struct snd_soc_dai_link_component *cpu;
+ struct snd_soc_dai_link_component *codec;
+ struct snd_soc_dai *dai;
+ bool supported_cpu = false;
+ bool supported_codec = false;
+ int i;
for_each_link_cpus(dai_link, i, cpu) {
dai = snd_soc_find_dai_with_mutex(cpu);
@@ -597,11 +595,11 @@ int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)
int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai;
- int i, ret = 0;
+ int i;
for_each_rtd_dais(rtd, i, dai) {
if (dai->driver->pcm_new) {
- ret = dai->driver->pcm_new(rtd, dai);
+ int ret = dai->driver->pcm_new(rtd, dai);
if (ret < 0)
return soc_dai_ret(dai, ret);
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 91bf939d5233..7b67f1e19ae9 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -650,12 +650,11 @@ static struct snd_soc_dapm_widget *
dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name)
{
struct snd_soc_dapm_widget *w = wcache->widget;
- struct list_head *wlist;
- const int depth = 2;
- int i = 0;
if (w) {
- wlist = &w->dapm->card->widgets;
+ struct list_head *wlist = &w->dapm->card->widgets;
+ const int depth = 2;
+ int i = 0;
list_for_each_entry_from(w, wlist, list) {
if (!strcmp(name, w->name))
@@ -748,10 +747,11 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
{
const struct snd_kcontrol_new *kcontrol = &w->kcontrol_news[0];
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned int val, item;
+ unsigned int item;
int i;
if (e->reg != SND_SOC_NOPM) {
+ unsigned int val;
val = soc_dapm_read(dapm, e->reg);
val = (val >> e->shift_l) & e->mask;
item = snd_soc_enum_val_to_item(e, val);
@@ -782,14 +782,14 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i,
struct soc_mixer_control *mc = (struct soc_mixer_control *)
p->sink->kcontrol_news[i].private_value;
unsigned int reg = mc->reg;
- unsigned int shift = mc->shift;
- unsigned int max = mc->max;
- unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
- unsigned int val;
if (reg != SND_SOC_NOPM) {
- val = soc_dapm_read(p->sink->dapm, reg);
+ unsigned int shift = mc->shift;
+ unsigned int max = mc->max;
+ unsigned int mask = (1 << fls(max)) - 1;
+ unsigned int val = soc_dapm_read(p->sink->dapm, reg);
+
/*
* The nth_path argument allows this function to know
* which path of a kcontrol it is setting the initial
@@ -1060,10 +1060,10 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
/* create new dapm volume control */
static int dapm_new_pga(struct snd_soc_dapm_widget *w)
{
- int i, ret;
+ int i;
for (i = 0; i < w->num_kcontrols; i++) {
- ret = dapm_create_or_share_kcontrol(w, i);
+ int ret = dapm_create_or_share_kcontrol(w, i);
if (ret < 0)
return ret;
}
@@ -1074,10 +1074,7 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w)
/* create new dapm dai link control */
static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)
{
- int i, ret;
- struct snd_kcontrol *kcontrol;
- struct snd_soc_dapm_context *dapm = w->dapm;
- struct snd_card *card = dapm->card->snd_card;
+ int i;
struct snd_soc_pcm_runtime *rtd = w->priv;
/* create control for links with > 1 config */
@@ -1086,9 +1083,12 @@ static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)
/* add kcontrol */
for (i = 0; i < w->num_kcontrols; i++) {
- kcontrol = snd_soc_cnew(&w->kcontrol_news[i], w,
- w->name, NULL);
- ret = snd_ctl_add(card, kcontrol);
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_card *card = dapm->card->snd_card;
+ struct snd_kcontrol *kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
+ w, w->name, NULL);
+ int ret = snd_ctl_add(card, kcontrol);
+
if (ret < 0) {
dev_err(dapm->dev,
"ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
@@ -1528,7 +1528,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
struct snd_soc_dapm_widget *w, int event)
{
const char *ev_name;
- int power, ret;
+ int power;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -1564,6 +1564,8 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
return;
if (w->event && (w->event_flags & event)) {
+ int ret;
+
pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
w->name, ev_name);
soc_dapm_async_complete(w->dapm);
@@ -1645,7 +1647,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
int cur_subseq = -1;
int cur_reg = SND_SOC_NOPM;
struct snd_soc_dapm_context *cur_dapm = NULL;
- int ret, i;
+ int i;
int *sort;
if (power_up)
@@ -1654,7 +1656,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
sort = dapm_down_seq;
list_for_each_entry_safe(w, n, list, power_list) {
- ret = 0;
+ int ret = 0;
/* Do we need to apply any queued changes? */
if (sort[w->id] != cur_sort || w->reg != cur_reg ||
@@ -3004,7 +3006,6 @@ err:
static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route)
{
- struct snd_soc_dapm_widget *wsource, *wsink;
struct snd_soc_dapm_path *path, *p;
const char *sink;
const char *source;
@@ -3042,8 +3043,8 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
}
if (path) {
- wsource = path->source;
- wsink = path->sink;
+ struct snd_soc_dapm_widget *wsource = path->source;
+ struct snd_soc_dapm_widget *wsink = path->sink;
dapm_mark_dirty(wsource, "Route removed");
dapm_mark_dirty(wsink, "Route removed");
@@ -3079,11 +3080,11 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num)
{
- int i, r, ret = 0;
+ int i, ret = 0;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
for (i = 0; i < num; i++) {
- r = snd_soc_dapm_add_route(dapm, route);
+ int r = snd_soc_dapm_add_route(dapm, route);
if (r < 0) {
dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
route->source,
@@ -3187,12 +3188,12 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num)
{
- int i, err;
+ int i;
int ret = 0;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
- err = snd_soc_dapm_weak_route(dapm, route);
+ int err = snd_soc_dapm_weak_route(dapm, route);
if (err)
ret = err;
route++;
@@ -3783,13 +3784,12 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_widget *widget,
int num)
{
- struct snd_soc_dapm_widget *w;
int i;
int ret = 0;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
- w = snd_soc_dapm_new_control_unlocked(dapm, widget);
+ struct snd_soc_dapm_widget *w = snd_soc_dapm_new_control_unlocked(dapm, widget);
if (IS_ERR(w)) {
ret = PTR_ERR(w);
break;
@@ -4365,11 +4365,12 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
int event)
{
struct snd_soc_dapm_widget *w;
- unsigned int ep;
w = snd_soc_dai_get_widget(dai, stream);
if (w) {
+ unsigned int ep;
+
dapm_mark_dirty(w, "stream event");
if (w->id == snd_soc_dapm_dai_in) {
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index 9ef80a48707e..4aa48c74f21a 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -79,7 +79,6 @@ static int dmaengine_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_hw_params *params,
struct dma_slave_config *slave_config);
struct dma_slave_config slave_config;
- int ret;
memset(&slave_config, 0, sizeof(slave_config));
@@ -89,7 +88,7 @@ static int dmaengine_pcm_hw_params(struct snd_soc_component *component,
prepare_slave_config = pcm->config->prepare_slave_config;
if (prepare_slave_config) {
- ret = prepare_slave_config(substream, params, &slave_config);
+ int ret = prepare_slave_config(substream, params, &slave_config);
if (ret)
return ret;
@@ -230,7 +229,6 @@ static int dmaengine_pcm_new(struct snd_soc_component *component,
struct dmaengine_pcm *pcm = soc_component_to_pcm(component);
const struct snd_dmaengine_pcm_config *config = pcm->config;
struct device *dev = component->dev;
- struct snd_pcm_substream *substream;
size_t prealloc_buffer_size;
size_t max_buffer_size;
unsigned int i;
@@ -244,7 +242,7 @@ static int dmaengine_pcm_new(struct snd_soc_component *component,
}
for_each_pcm_streams(i) {
- substream = rtd->pcm->streams[i].substream;
+ struct snd_pcm_substream *substream = rtd->pcm->streams[i].substream;
if (!substream)
continue;
@@ -307,14 +305,13 @@ static int dmaengine_copy_user(struct snd_soc_component *component,
bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
void *dma_ptr = runtime->dma_area + hwoff +
channel * (runtime->dma_bytes / runtime->channels);
- int ret;
if (is_playback)
if (copy_from_user(dma_ptr, buf, bytes))
return -EFAULT;
if (process) {
- ret = process(substream, channel, hwoff, (__force void *)buf, bytes);
+ int ret = process(substream, channel, hwoff, (__force void *)buf, bytes);
if (ret < 0)
return ret;
}
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 0f1820f36b4d..d798765d168c 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -17,12 +17,6 @@
#include <linux/suspend.h>
#include <trace/events/asoc.h>
-struct jack_gpio_tbl {
- int count;
- struct snd_soc_jack *jack;
- struct snd_soc_jack_gpio *gpios;
-};
-
/**
* snd_soc_jack_report - Report the current status for a jack
*
@@ -42,7 +36,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
struct snd_soc_dapm_context *dapm;
struct snd_soc_jack_pin *pin;
unsigned int sync = 0;
- int enable;
if (!jack)
return;
@@ -58,7 +51,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
trace_snd_soc_jack_notify(jack, status);
list_for_each_entry(pin, &jack->pins, list) {
- enable = pin->mask & jack->status;
+ int enable = pin->mask & jack->status;
if (pin->invert)
enable = !enable;
@@ -208,6 +201,12 @@ void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack,
EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_unregister);
#ifdef CONFIG_GPIOLIB
+struct jack_gpio_tbl {
+ int count;
+ struct snd_soc_jack *jack;
+ struct snd_soc_jack_gpio *gpios;
+};
+
/* gpio detect */
static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
{
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 58527247df83..08eaa9ddf191 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -407,7 +407,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
int min = mc->min;
unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
int err = 0;
- unsigned int val, val_mask, val2;
+ unsigned int val, val_mask;
val_mask = mask << shift;
val = (ucontrol->value.integer.value[0] + min) & mask;
@@ -418,6 +418,8 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
return err;
if (snd_soc_volsw_is_stereo(mc)) {
+ unsigned int val2;
+
val_mask = mask << rshift;
val2 = (ucontrol->value.integer.value[1] + min) & mask;
val2 = val2 << rshift;
@@ -573,7 +575,6 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
const char *name, int max)
{
struct snd_kcontrol *kctl;
- struct soc_mixer_control *mc;
int ret = -EINVAL;
/* Sanity check for name and max */
@@ -582,7 +583,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
kctl = snd_soc_card_get_kcontrol(card, name);
if (kctl) {
- mc = (struct soc_mixer_control *)kctl->private_value;
+ struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
if (max <= mc->max) {
mc->platform_max = max;
ret = 0;
@@ -811,11 +812,10 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
long min = mc->min;
long max = mc->max;
long val = 0;
- unsigned int regval;
unsigned int i;
for (i = 0; i < regcount; i++) {
- regval = snd_soc_component_read(component, regbase+i);
+ unsigned int regval = snd_soc_component_read(component, regbase+i);
val |= (regval & regwmask) << (regwshift*(regcount-i-1));
}
val &= mask;
@@ -856,17 +856,16 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
unsigned long mask = (1UL<<mc->nbits)-1;
long max = mc->max;
long val = ucontrol->value.integer.value[0];
- unsigned int i, regval, regmask;
- int err;
+ unsigned int i;
if (invert)
val = max - val;
val &= mask;
for (i = 0; i < regcount; i++) {
- regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
- regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
- err = snd_soc_component_update_bits(component, regbase+i,
- regmask, regval);
+ unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
+ unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
+ int err = snd_soc_component_update_bits(component, regbase+i,
+ regmask, regval);
if (err < 0)
return err;
}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index d1c570ca21ea..48f71bb81a2f 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -449,13 +449,12 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai;
struct snd_soc_dai *codec_dai;
- struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu;
int stream = substream->stream;
int i;
unsigned int bits = 0, cpu_bits = 0;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
- pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream);
+ struct snd_soc_pcm_stream *pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream);
if (pcm_codec->sig_bits == 0) {
bits = 0;
@@ -465,7 +464,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
}
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
- pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
+ struct snd_soc_pcm_stream *pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
if (pcm_cpu->sig_bits == 0) {
cpu_bits = 0;
@@ -634,10 +633,10 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component;
- int i, r, ret = 0;
+ int i, ret = 0;
for_each_rtd_components(rtd, i, component) {
- r = snd_soc_component_close(component, substream, rollback);
+ int r = snd_soc_component_close(component, substream, rollback);
if (r < 0)
ret = r; /* use last ret */
@@ -1318,13 +1317,12 @@ void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
static bool dpcm_be_is_active(struct snd_soc_dpcm *dpcm, int stream,
struct snd_soc_dapm_widget_list *list)
{
- struct snd_soc_dapm_widget *widget;
struct snd_soc_dai *dai;
unsigned int i;
/* is there a valid DAI widget for this BE */
for_each_rtd_dais(dpcm->be, i, dai) {
- widget = snd_soc_dai_get_widget(dai, stream);
+ struct snd_soc_dapm_widget *widget = snd_soc_dai_get_widget(dai, stream);
/*
* The BE is pruned only if none of the dai
@@ -1637,7 +1635,6 @@ static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream)
for_each_dpcm_be(fe, stream, dpcm) {
struct snd_soc_pcm_runtime *be = dpcm->be;
- struct snd_soc_pcm_stream *codec_stream;
struct snd_soc_pcm_stream *cpu_stream;
struct snd_soc_dai *dai;
int i;
@@ -1660,7 +1657,8 @@ static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream)
* DAIs connected to a single CPU DAI, use CPU DAI's directly
*/
if (be->num_codecs == 1) {
- codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream);
+ struct snd_soc_pcm_stream *codec_stream = snd_soc_dai_get_pcm_stream(
+ asoc_rtd_to_codec(be, 0), stream);
soc_pcm_hw_update_chan(hw, codec_stream);
}
@@ -2591,9 +2589,7 @@ open_end:
static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
int *playback, int *capture)
{
- struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
- int stream;
int i;
if (rtd->dai_link->dynamic && rtd->num_cpus > 1) {
@@ -2603,6 +2599,8 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
}
if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
+ int stream;
+
if (rtd->dai_link->dpcm_playback) {
stream = SNDRV_PCM_STREAM_PLAYBACK;
@@ -2637,6 +2635,8 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
}
}
} else {
+ struct snd_soc_dai *codec_dai;
+
/* Adapt stream for codec2codec links */
int cpu_capture = rtd->dai_link->params ?
SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 0a24d0d409d2..f6e5ac3e0314 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1035,7 +1035,6 @@ err_denum:
static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
struct snd_soc_tplg_hdr *hdr)
{
- struct snd_soc_tplg_ctl_hdr *control_hdr;
int ret;
int i;
@@ -1043,8 +1042,7 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
soc_tplg_get_offset(tplg));
for (i = 0; i < le32_to_cpu(hdr->count); i++) {
-
- control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
+ struct snd_soc_tplg_ctl_hdr *control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) {
dev_err(tplg->dev, "ASoC: invalid control size\n");
@@ -1583,15 +1581,16 @@ err:
static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
struct snd_soc_tplg_hdr *hdr)
{
- struct snd_soc_tplg_dapm_widget *widget;
- int ret, count, i;
+ int count, i;
count = le32_to_cpu(hdr->count);
dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count);
for (i = 0; i < count; i++) {
- widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
+ struct snd_soc_tplg_dapm_widget *widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
+ int ret;
+
if (le32_to_cpu(widget->size) != sizeof(*widget)) {
dev_err(tplg->dev, "ASoC: invalid widget size\n");
return -EINVAL;
@@ -2125,10 +2124,9 @@ static struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,
const char *stream_name)
{
struct snd_soc_pcm_runtime *rtd;
- struct snd_soc_dai_link *link;
for_each_card_rtds(card, rtd) {
- link = rtd->dai_link;
+ struct snd_soc_dai_link *link = rtd->dai_link;
if (link->id != id)
continue;
@@ -2346,15 +2344,16 @@ err:
static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
struct snd_soc_tplg_hdr *hdr)
{
- struct snd_soc_tplg_dai *dai;
int count;
- int i, ret;
+ int i;
count = le32_to_cpu(hdr->count);
/* config the existing BE DAIs */
for (i = 0; i < count; i++) {
- dai = (struct snd_soc_tplg_dai *)tplg->pos;
+ struct snd_soc_tplg_dai *dai = (struct snd_soc_tplg_dai *)tplg->pos;
+ int ret;
+
if (le32_to_cpu(dai->size) != sizeof(*dai)) {
dev_err(tplg->dev, "ASoC: invalid physical DAI size\n");
return -EINVAL;
@@ -2572,13 +2571,13 @@ static int soc_tplg_load_header(struct soc_tplg *tplg,
/* process the topology file headers */
static int soc_tplg_process_headers(struct soc_tplg *tplg)
{
- struct snd_soc_tplg_hdr *hdr;
int ret;
tplg->pass = SOC_TPLG_PASS_START;
/* process the header types from start to end */
while (tplg->pass <= SOC_TPLG_PASS_END) {
+ struct snd_soc_tplg_hdr *hdr;
tplg->hdr_pos = tplg->fw->data;
hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig
index 4447f515e8b1..88b6176af021 100644
--- a/sound/soc/sof/intel/Kconfig
+++ b/sound/soc/sof/intel/Kconfig
@@ -249,16 +249,6 @@ config SND_SOC_SOF_HDA_PROBES
Say Y if you want to enable probes.
If unsure, select "N".
-config SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1
- bool "SOF enable DMI Link L1"
- help
- This option enables DMI L1 for both playback and capture
- and disables known workarounds for specific HDAudio platforms.
- Only use to look into power optimizations on platforms not
- affected by DMI L1 issues. This option is not recommended.
- Say Y if you want to enable DMI Link L1.
- If unsure, select "N".
-
endif ## SND_SOC_SOF_HDA_COMMON
config SND_SOC_SOF_HDA_LINK_BASELINE
diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c
index 821f25fbcf08..e115e12a856f 100644
--- a/sound/soc/sof/intel/cnl.c
+++ b/sound/soc/sof/intel/cnl.c
@@ -347,6 +347,9 @@ const struct sof_intel_dsp_desc cnl_chip_info = {
.rom_init_timeout = 300,
.ssp_count = CNL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
+ .sdw_shim_base = SDW_SHIM_BASE,
+ .sdw_alh_base = SDW_ALH_BASE,
+ .check_sdw_irq = hda_common_check_sdw_irq,
};
EXPORT_SYMBOL_NS(cnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
@@ -363,5 +366,8 @@ const struct sof_intel_dsp_desc jsl_chip_info = {
.rom_init_timeout = 300,
.ssp_count = ICL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
+ .sdw_shim_base = SDW_SHIM_BASE,
+ .sdw_alh_base = SDW_ALH_BASE,
+ .check_sdw_irq = hda_common_check_sdw_irq,
};
EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index df00db8369c7..cc8ddef37f37 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -15,6 +15,7 @@
* Hardware interface for generic Intel audio DSP HDA IP
*/
+#include <linux/moduleparam.h>
#include <sound/hda_register.h>
#include <sound/pcm_params.h>
#include "../sof-audio.h"
@@ -27,6 +28,10 @@
#define SDnFMT_BITS(x) ((x) << 4)
#define SDnFMT_CHAN(x) ((x) << 0)
+static bool hda_always_enable_dmi_l1;
+module_param_named(always_enable_dmi_l1, hda_always_enable_dmi_l1, bool, 0444);
+MODULE_PARM_DESC(always_enable_dmi_l1, "SOF HDA always enable DMI l1");
+
u32 hda_dsp_get_mult_div(struct snd_sof_dev *sdev, int rate)
{
switch (rate) {
@@ -216,6 +221,7 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_component *scomp = sdev->component;
struct hdac_ext_stream *dsp_stream;
struct snd_sof_pcm *spcm;
@@ -228,8 +234,14 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
return -EINVAL;
}
- /* All playback and D0i3 compatible streams are DMI L1 capable */
- if (direction == SNDRV_PCM_STREAM_PLAYBACK ||
+ /*
+ * All playback streams are DMI L1 capable, capture streams need
+ * pause push/release to be disabled
+ */
+ if (hda_always_enable_dmi_l1 && direction == SNDRV_PCM_STREAM_CAPTURE)
+ runtime->hw.info &= ~SNDRV_PCM_INFO_PAUSE;
+
+ if (hda_always_enable_dmi_l1 ||
spcm->stream[substream->stream].d0i3_compatible)
flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE;
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 40a3993ae2cb..63c367478f1c 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -197,11 +197,10 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags)
* Workaround to address a known issue with host DMA that results
* in xruns during pause/release in capture scenarios.
*/
- if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
- if (stream && !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE))
- snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
- HDA_VS_INTEL_EM2,
- HDA_VS_INTEL_EM2_L1SEN, 0);
+ if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE))
+ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
+ HDA_VS_INTEL_EM2,
+ HDA_VS_INTEL_EM2_L1SEN, 0);
return stream;
}
@@ -240,7 +239,7 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
spin_unlock_irq(&bus->reg_lock);
/* Enable DMI L1 if permitted */
- if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1) && dmi_l1_enable)
+ if (dmi_l1_enable)
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 891e6e1b9121..f60e2c57d3d0 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -41,6 +41,17 @@
#define EXCEPT_MAX_HDR_SIZE 0x400
#define HDA_EXT_ROM_STATUS_SIZE 8
+static const struct sof_intel_dsp_desc
+ *get_chip_info(struct snd_sof_pdata *pdata)
+{
+ const struct sof_dev_desc *desc = pdata->desc;
+ const struct sof_intel_dsp_desc *chip_info;
+
+ chip_info = desc->chip_info;
+
+ return chip_info;
+}
+
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
/*
@@ -155,6 +166,8 @@ static int hda_sdw_probe(struct snd_sof_dev *sdev)
memset(&res, 0, sizeof(res));
res.mmio_base = sdev->bar[HDA_DSP_BAR];
+ res.shim_base = hdev->desc->sdw_shim_base;
+ res.alh_base = hdev->desc->sdw_alh_base;
res.irq = sdev->ipc_irq;
res.handle = hdev->info.handle;
res.parent = sdev->dev;
@@ -215,7 +228,7 @@ static int hda_sdw_exit(struct snd_sof_dev *sdev)
return 0;
}
-static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
+bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev)
{
struct sof_intel_hda_dev *hdev;
bool ret = false;
@@ -241,6 +254,17 @@ out:
return ret;
}
+static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
+{
+ const struct sof_intel_dsp_desc *chip;
+
+ chip = get_chip_info(sdev->pdata);
+ if (chip && chip->check_sdw_irq)
+ return chip->check_sdw_irq(sdev);
+
+ return false;
+}
+
static irqreturn_t hda_dsp_sdw_thread(int irq, void *context)
{
return sdw_intel_thread(irq, context);
@@ -253,7 +277,7 @@ static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
hdev = sdev->pdata->hw_pdata;
if (hdev->sdw &&
snd_sof_dsp_read(sdev, HDA_DSP_BAR,
- HDA_DSP_REG_SNDW_WAKE_STS))
+ hdev->desc->sdw_shim_base + SDW_SHIM_WAKESTS))
return true;
return false;
@@ -672,17 +696,6 @@ skip_soundwire:
return 0;
}
-static const struct sof_intel_dsp_desc
- *get_chip_info(struct snd_sof_pdata *pdata)
-{
- const struct sof_dev_desc *desc = pdata->desc;
- const struct sof_intel_dsp_desc *chip_info;
-
- chip_info = desc->chip_info;
-
- return chip_info;
-}
-
static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context)
{
struct snd_sof_dev *sdev = context;
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index 4d44f8910393..4fdfb108645c 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -233,7 +233,6 @@
#define HDA_DSP_REG_ADSPIS2 (HDA_DSP_GEN_BASE + 0x14)
#define HDA_DSP_REG_ADSPIS2_SNDW BIT(5)
-#define HDA_DSP_REG_SNDW_WAKE_STS 0x2C192
/* Intel HD Audio Inter-Processor Communication Registers */
#define HDA_DSP_IPC_BASE 0x40
@@ -692,6 +691,7 @@ int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd);
int hda_sdw_startup(struct snd_sof_dev *sdev);
void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable);
void hda_sdw_process_wakeen(struct snd_sof_dev *sdev);
+bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev);
#else
@@ -737,6 +737,12 @@ static inline bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
static inline void hda_sdw_process_wakeen(struct snd_sof_dev *sdev)
{
}
+
+static inline bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev)
+{
+ return false;
+}
+
#endif
/* common dai driver */
diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c
index 88a74be8a0c1..ee095b8f2d01 100644
--- a/sound/soc/sof/intel/icl.c
+++ b/sound/soc/sof/intel/icl.c
@@ -142,5 +142,8 @@ const struct sof_intel_dsp_desc icl_chip_info = {
.rom_init_timeout = 300,
.ssp_count = ICL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
+ .sdw_shim_base = SDW_SHIM_BASE,
+ .sdw_alh_base = SDW_ALH_BASE,
+ .check_sdw_irq = hda_common_check_sdw_irq,
};
EXPORT_SYMBOL_NS(icl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c
index 4ee1da397d4e..4bded668b672 100644
--- a/sound/soc/sof/intel/pci-tng.c
+++ b/sound/soc/sof/intel/pci-tng.c
@@ -15,7 +15,6 @@
#include <sound/sof.h>
#include "../ops.h"
#include "atom.h"
-#include "shim.h"
#include "../sof-pci-dev.h"
#include "../sof-audio.h"
diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h
index 529f68d0ca47..e9f7d4d7fcce 100644
--- a/sound/soc/sof/intel/shim.h
+++ b/sound/soc/sof/intel/shim.h
@@ -164,6 +164,9 @@ struct sof_intel_dsp_desc {
int rom_init_timeout;
int ssp_count; /* ssp count of the platform */
int ssp_base_offset; /* base address of the SSPs */
+ u32 sdw_shim_base;
+ u32 sdw_alh_base;
+ bool (*check_sdw_irq)(struct snd_sof_dev *sdev);
};
extern const struct snd_sof_dsp_ops sof_tng_ops;
diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c
index 2ed788304414..199d41a7dc9b 100644
--- a/sound/soc/sof/intel/tgl.c
+++ b/sound/soc/sof/intel/tgl.c
@@ -137,6 +137,9 @@ const struct sof_intel_dsp_desc tgl_chip_info = {
.rom_init_timeout = 300,
.ssp_count = ICL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
+ .sdw_shim_base = SDW_SHIM_BASE,
+ .sdw_alh_base = SDW_ALH_BASE,
+ .check_sdw_irq = hda_common_check_sdw_irq,
};
EXPORT_SYMBOL_NS(tgl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
@@ -153,6 +156,9 @@ const struct sof_intel_dsp_desc tglh_chip_info = {
.rom_init_timeout = 300,
.ssp_count = ICL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
+ .sdw_shim_base = SDW_SHIM_BASE,
+ .sdw_alh_base = SDW_ALH_BASE,
+ .check_sdw_irq = hda_common_check_sdw_irq,
};
EXPORT_SYMBOL_NS(tglh_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
@@ -169,6 +175,9 @@ const struct sof_intel_dsp_desc ehl_chip_info = {
.rom_init_timeout = 300,
.ssp_count = ICL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
+ .sdw_shim_base = SDW_SHIM_BASE,
+ .sdw_alh_base = SDW_ALH_BASE,
+ .check_sdw_irq = hda_common_check_sdw_irq,
};
EXPORT_SYMBOL_NS(ehl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
@@ -185,5 +194,8 @@ const struct sof_intel_dsp_desc adls_chip_info = {
.rom_init_timeout = 300,
.ssp_count = ICL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
+ .sdw_shim_base = SDW_SHIM_BASE,
+ .sdw_alh_base = SDW_ALH_BASE,
+ .check_sdw_irq = hda_common_check_sdw_irq,
};
EXPORT_SYMBOL_NS(adls_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 510883cd9107..989912f2b739 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -433,11 +433,10 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp,
return NULL;
}
-/*
- * Helper to get SSP MCLK from a pcm_runtime.
- * Return 0 if not exist.
- */
-int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd)
+#define SOF_DAI_CLK_INTEL_SSP_MCLK 0
+#define SOF_DAI_CLK_INTEL_SSP_BCLK 1
+
+static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type)
{
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
@@ -450,17 +449,46 @@ int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd)
switch (dai->dai_config->type) {
case SOF_DAI_INTEL_SSP:
- return dai->dai_config->ssp.mclk_rate;
+ switch (clk_type) {
+ case SOF_DAI_CLK_INTEL_SSP_MCLK:
+ return dai->dai_config->ssp.mclk_rate;
+ case SOF_DAI_CLK_INTEL_SSP_BCLK:
+ return dai->dai_config->ssp.bclk_rate;
+ default:
+ dev_err(rtd->dev, "fail to get SSP clk %d rate\n",
+ clk_type);
+ return -EINVAL;
+ }
+ break;
default:
/* not yet implemented for platforms other than the above */
- dev_err(rtd->dev, "mclk for dai_config->type %d not supported yet!\n",
+ dev_err(rtd->dev, "DAI type %d not supported yet!\n",
dai->dai_config->type);
return -EINVAL;
}
}
+
+/*
+ * Helper to get SSP MCLK from a pcm_runtime.
+ * Return 0 if not exist.
+ */
+int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd)
+{
+ return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_MCLK);
+}
EXPORT_SYMBOL(sof_dai_get_mclk);
/*
+ * Helper to get SSP BCLK from a pcm_runtime.
+ * Return 0 if not exist.
+ */
+int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd)
+{
+ return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_BCLK);
+}
+EXPORT_SYMBOL(sof_dai_get_bclk);
+
+/*
* SOF Driver enumeration.
*/
int sof_machine_check(struct snd_sof_dev *sdev)
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index 03119462f9e2..bc9e70765678 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -50,6 +50,15 @@ static const struct dmi_system_id sof_tplg_table[] = {
},
.driver_data = "sof-tgl-rt5682-ssp0-max98373-ssp2.tplg",
},
+ {
+ .callback = sof_tplg_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
+ DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
+ },
+ .driver_data = "sof-adl-rt5682-ssp0-max98373-ssp2.tplg",
+ },
{}
};
diff --git a/sound/soc/sprd/sprd-pcm-dma.c b/sound/soc/sprd/sprd-pcm-dma.c
index 5e3a96d4793c..48d90616b23f 100644
--- a/sound/soc/sprd/sprd-pcm-dma.c
+++ b/sound/soc/sprd/sprd-pcm-dma.c
@@ -204,8 +204,6 @@ static int sprd_pcm_hw_params(struct snd_soc_component *component,
if (!dma_params) {
dev_warn(component->dev, "no dma parameters setting\n");
dma_private->params = NULL;
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = totsize;
return 0;
}
@@ -217,9 +215,6 @@ static int sprd_pcm_hw_params(struct snd_soc_component *component,
return ret;
}
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
- runtime->dma_bytes = totsize;
sg_num = totsize / period;
dma_private->dma_addr_offset = totsize / channels;
@@ -310,7 +305,6 @@ sg_err:
static int sprd_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
- snd_pcm_set_runtime_buffer(substream, NULL);
sprd_pcm_release_dma_channel(substream);
return 0;
@@ -435,73 +429,20 @@ static snd_pcm_uframes_t sprd_pcm_pointer(struct snd_soc_component *component,
return x;
}
-static int sprd_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- return remap_pfn_range(vma, vma->vm_start,
- runtime->dma_addr >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
-}
-
static int sprd_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
- struct snd_pcm_substream *substream;
int ret;
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
- substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- if (substream) {
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
- sprd_pcm_hardware.buffer_bytes_max,
- &substream->dma_buffer);
- if (ret) {
- dev_err(card->dev,
- "can't alloc playback dma buffer: %d\n", ret);
- return ret;
- }
- }
-
- substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
- if (substream) {
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
- sprd_pcm_hardware.buffer_bytes_max,
- &substream->dma_buffer);
- if (ret) {
- dev_err(card->dev,
- "can't alloc capture dma buffer: %d\n", ret);
- snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
- return ret;
- }
- }
-
- return 0;
-}
-
-static void sprd_pcm_free(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
- substream = pcm->streams[i].substream;
- if (substream) {
- snd_dma_free_pages(&substream->dma_buffer);
- substream->dma_buffer.area = NULL;
- substream->dma_buffer.addr = 0;
- }
- }
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+ card->dev,
+ sprd_pcm_hardware.buffer_bytes_max);
}
static const struct snd_soc_component_driver sprd_soc_component = {
@@ -512,9 +453,7 @@ static const struct snd_soc_component_driver sprd_soc_component = {
.hw_free = sprd_pcm_hw_free,
.trigger = sprd_pcm_trigger,
.pointer = sprd_pcm_pointer,
- .mmap = sprd_pcm_mmap,
.pcm_construct = sprd_pcm_new,
- .pcm_destruct = sprd_pcm_free,
.compress_ops = &sprd_platform_compress_ops,
};
diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c
index 0f9beef429a2..bcccdf3ddc52 100644
--- a/sound/soc/tegra/tegra210_admaif.c
+++ b/sound/soc/tegra/tegra210_admaif.c
@@ -612,12 +612,9 @@ static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
.controls = tegra210_admaif_controls,
.num_controls = ARRAY_SIZE(tegra210_admaif_controls),
.pcm_construct = tegra_pcm_construct,
- .pcm_destruct = tegra_pcm_destruct,
.open = tegra_pcm_open,
.close = tegra_pcm_close,
.hw_params = tegra_pcm_hw_params,
- .hw_free = tegra_pcm_hw_free,
- .mmap = tegra_pcm_mmap,
.pointer = tegra_pcm_pointer,
};
@@ -625,12 +622,9 @@ static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
.controls = tegra186_admaif_controls,
.num_controls = ARRAY_SIZE(tegra186_admaif_controls),
.pcm_construct = tegra_pcm_construct,
- .pcm_destruct = tegra_pcm_destruct,
.open = tegra_pcm_open,
.close = tegra_pcm_close,
.hw_params = tegra_pcm_hw_params,
- .hw_free = tegra_pcm_hw_free,
- .mmap = tegra_pcm_mmap,
.pointer = tegra_pcm_pointer,
};
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index b3e1df693381..ef011a488ceb 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -512,16 +512,14 @@ static const struct of_device_id tegra30_ahub_of_match[] = {
static int tegra30_ahub_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
const struct tegra30_ahub_soc_data *soc_data;
struct resource *res0;
void __iomem *regs_apbif, *regs_ahub;
int ret = 0;
- match = of_match_device(tegra30_ahub_of_match, &pdev->dev);
- if (!match)
+ soc_data = of_device_get_match_data(&pdev->dev);
+ if (!soc_data)
return -EINVAL;
- soc_data = match->data;
ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
GFP_KERNEL);
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 36344f0a64c1..084a533bf4f2 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -406,7 +406,7 @@ static const struct of_device_id tegra30_i2s_of_match[] = {
static int tegra30_i2s_platform_probe(struct platform_device *pdev)
{
struct tegra30_i2s *i2s;
- const struct of_device_id *match;
+ const struct tegra30_i2s_soc_data *soc_data;
u32 cif_ids[2];
void __iomem *regs;
int ret;
@@ -418,13 +418,13 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
}
dev_set_drvdata(&pdev->dev, i2s);
- match = of_match_device(tegra30_i2s_of_match, &pdev->dev);
- if (!match) {
+ soc_data = of_device_get_match_data(&pdev->dev);
+ if (!soc_data) {
dev_err(&pdev->dev, "Error: No device match found\n");
ret = -ENODEV;
goto err;
}
- i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data;
+ i2s->soc_data = soc_data;
i2s->dai = tegra30_i2s_dai_template;
i2s->dai.name = dev_name(&pdev->dev);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index d3276b4595af..ef1e74d95236 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -171,41 +171,10 @@ int tegra_pcm_hw_params(struct snd_soc_component *component,
return ret;
}
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-
return 0;
}
EXPORT_SYMBOL_GPL(tegra_pcm_hw_params);
-int tegra_pcm_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- if (rtd->dai_link->no_pcm)
- return 0;
-
- snd_pcm_set_runtime_buffer(substream, NULL);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_hw_free);
-
-int tegra_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- if (rtd->dai_link->no_pcm)
- return 0;
-
- return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
- runtime->dma_addr, runtime->dma_bytes);
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_mmap);
-
snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -213,41 +182,6 @@ snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
}
EXPORT_SYMBOL_GPL(tegra_pcm_pointer);
-static int tegra_pcm_preallocate_dma_buffer(struct device *dev, struct snd_pcm *pcm, int stream,
- size_t size)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
-
- buf->area = dma_alloc_wc(dev, size, &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
-
- buf->private_data = NULL;
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = dev;
- buf->bytes = size;
-
- return 0;
-}
-
-static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
-
- substream = pcm->streams[stream].substream;
- if (!substream)
- return;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- return;
-
- dma_free_wc(buf->dev.dev, buf->bytes, buf->area, buf->addr);
- buf->area = NULL;
-}
-
static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime *rtd,
size_t size)
{
@@ -258,24 +192,7 @@ static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime
if (ret < 0)
return ret;
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_PLAYBACK, size);
- if (ret)
- goto err;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_CAPTURE, size);
- if (ret)
- goto err_free_play;
- }
-
- return 0;
-
-err_free_play:
- tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
-err:
- return ret;
+ return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC, dev, size);
}
int tegra_pcm_construct(struct snd_soc_component *component,
@@ -294,14 +211,6 @@ int tegra_pcm_construct(struct snd_soc_component *component,
}
EXPORT_SYMBOL_GPL(tegra_pcm_construct);
-void tegra_pcm_destruct(struct snd_soc_component *component,
- struct snd_pcm *pcm)
-{
- tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
- tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
-}
-EXPORT_SYMBOL_GPL(tegra_pcm_destruct);
-
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra PCM ASoC driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index 4838cdcee20e..d602126c65b7 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -22,8 +22,6 @@
int tegra_pcm_construct(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd);
-void tegra_pcm_destruct(struct snd_soc_component *component,
- struct snd_pcm *pcm);
int tegra_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int tegra_pcm_close(struct snd_soc_component *component,
@@ -31,11 +29,6 @@ int tegra_pcm_close(struct snd_soc_component *component,
int tegra_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
-int tegra_pcm_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream);
-int tegra_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma);
snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int tegra_pcm_platform_register(struct device *dev);
diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig
index 698d7bc84dcf..1d9fe3fca193 100644
--- a/sound/soc/ti/Kconfig
+++ b/sound/soc/ti/Kconfig
@@ -35,6 +35,7 @@ config SND_SOC_DAVINCI_MCASP
various Texas Instruments SoCs like:
- daVinci devices
- Sitara line of SoCs (AM335x, AM438x, etc)
+ - OMAP4
- DRA7x devices
- Keystone devices
- K3 devices (am654, j721e)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index 017a5a5e56cd..56a19eeec5c7 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -83,6 +83,8 @@ struct davinci_mcasp {
struct snd_pcm_substream *substreams[2];
unsigned int dai_fmt;
+ u32 iec958_status;
+
/* Audio can not be enabled due to missing parameter(s) */
bool missing_audio_param;
@@ -757,6 +759,9 @@ static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai,
{
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
+ if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
+ return 0;
+
dev_dbg(mcasp->dev,
"%s() tx_mask 0x%08x rx_mask 0x%08x slots %d width %d\n",
__func__, tx_mask, rx_mask, slots, slot_width);
@@ -827,6 +832,20 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),
RXROT(7));
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
+ } else {
+ /*
+ * according to the TRM it should be TXROT=0, this one works:
+ * 16 bit to 23-8 (TXROT=6, rotate 24 bits)
+ * 24 bit to 23-0 (TXROT=0, rotate 0 bits)
+ *
+ * TXROT = 0 only works with 24bit samples
+ */
+ tx_rotate = (sample_width / 4 + 2) & 0x7;
+
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
+ TXROT(7));
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15),
+ TXSSZ(0x0F));
}
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
@@ -842,10 +861,16 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
u8 tx_ser = 0;
u8 rx_ser = 0;
u8 slots = mcasp->tdm_slots;
- u8 max_active_serializers = (channels + slots - 1) / slots;
- u8 max_rx_serializers, max_tx_serializers;
+ u8 max_active_serializers, max_rx_serializers, max_tx_serializers;
int active_serializers, numevt;
u32 reg;
+
+ /* In DIT mode we only allow maximum of one serializers for now */
+ if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
+ max_active_serializers = 1;
+ else
+ max_active_serializers = (channels + slots - 1) / slots;
+
/* Default configuration */
if (mcasp->version < MCASP_VERSION_3)
mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
@@ -1031,16 +1056,18 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
unsigned int rate)
{
- u32 cs_value = 0;
- u8 *cs_bytes = (u8*) &cs_value;
+ u8 *cs_bytes = (u8 *)&mcasp->iec958_status;
- /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
- and LSB first */
- mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15));
+ if (!mcasp->dat_port)
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSEL);
+ else
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSEL);
/* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180));
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, 0xFFFF);
+
/* Set the TX tdm : for all the slots */
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
@@ -1049,16 +1076,8 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
- /* Only 44100 and 48000 are valid, both have the same setting */
- mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
-
- /* Enable the DIT */
- mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
-
/* Set S/PDIF channel status bits */
- cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
- cs_bytes[1] = IEC958_AES1_CON_PCM_CODER;
-
+ cs_bytes[3] &= ~IEC958_AES3_CON_FS;
switch (rate) {
case 22050:
cs_bytes[3] |= IEC958_AES3_CON_FS_22050;
@@ -1088,12 +1107,15 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
cs_bytes[3] |= IEC958_AES3_CON_FS_192000;
break;
default:
- printk(KERN_WARNING "unsupported sampling rate: %d\n", rate);
+ dev_err(mcasp->dev, "unsupported sampling rate: %d\n", rate);
return -EINVAL;
}
- mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value);
- mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value);
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, mcasp->iec958_status);
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, mcasp->iec958_status);
+
+ /* Enable the DIT */
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
return 0;
}
@@ -1237,12 +1259,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
int slots = mcasp->tdm_slots;
int rate = params_rate(params);
int sbits = params_width(params);
+ unsigned int bclk_target;
if (mcasp->slot_width)
sbits = mcasp->slot_width;
+ if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
+ bclk_target = rate * sbits * slots;
+ else
+ bclk_target = rate * 128;
+
davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq,
- rate * sbits * slots, true);
+ bclk_target, true);
}
ret = mcasp_common_hw_param(mcasp, substream->stream,
@@ -1598,6 +1626,77 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
.set_tdm_slot = davinci_mcasp_set_tdm_slot,
};
+static int davinci_mcasp_iec958_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+static int davinci_mcasp_iec958_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uctl)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+
+ memcpy(uctl->value.iec958.status, &mcasp->iec958_status,
+ sizeof(mcasp->iec958_status));
+
+ return 0;
+}
+
+static int davinci_mcasp_iec958_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uctl)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+
+ memcpy(&mcasp->iec958_status, uctl->value.iec958.status,
+ sizeof(mcasp->iec958_status));
+
+ return 0;
+}
+
+static int davinci_mcasp_iec958_con_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+
+ memset(ucontrol->value.iec958.status, 0xff, sizeof(mcasp->iec958_status));
+ return 0;
+}
+
+static const struct snd_kcontrol_new davinci_mcasp_iec958_ctls[] = {
+ {
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE),
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+ .info = davinci_mcasp_iec958_info,
+ .get = davinci_mcasp_iec958_get,
+ .put = davinci_mcasp_iec958_put,
+ }, {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
+ .info = davinci_mcasp_iec958_info,
+ .get = davinci_mcasp_iec958_con_mask_get,
+ },
+};
+
+static void davinci_mcasp_init_iec958_status(struct davinci_mcasp *mcasp)
+{
+ unsigned char *cs = (u8 *)&mcasp->iec958_status;
+
+ cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
+ cs[1] = IEC958_AES1_CON_PCM_CODER;
+ cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
+ cs[3] = IEC958_AES3_CON_CLOCK_1000PPM;
+}
+
static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
{
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
@@ -1605,6 +1704,12 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
+ if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) {
+ davinci_mcasp_init_iec958_status(mcasp);
+ snd_soc_add_dai_controls(dai, davinci_mcasp_iec958_ctls,
+ ARRAY_SIZE(davinci_mcasp_iec958_ctls));
+ }
+
return 0;
}
@@ -1651,7 +1756,8 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
.channels_min = 1,
.channels_max = 384,
.rates = DAVINCI_MCASP_RATES,
- .formats = DAVINCI_MCASP_PCM_FMTS,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &davinci_mcasp_dai_ops,
},
@@ -1688,6 +1794,12 @@ static struct davinci_mcasp_pdata dra7_mcasp_pdata = {
.version = MCASP_VERSION_4,
};
+static struct davinci_mcasp_pdata omap_mcasp_pdata = {
+ .tx_dma_offset = 0x200,
+ .rx_dma_offset = 0,
+ .version = MCASP_VERSION_OMAP,
+};
+
static const struct of_device_id mcasp_dt_ids[] = {
{
.compatible = "ti,dm646x-mcasp-audio",
@@ -1705,6 +1817,10 @@ static const struct of_device_id mcasp_dt_ids[] = {
.compatible = "ti,dra7-mcasp-audio",
.data = &dra7_mcasp_pdata,
},
+ {
+ .compatible = "ti,omap4-mcasp-audio",
+ .data = &omap_mcasp_pdata,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mcasp_dt_ids);
@@ -1871,6 +1987,8 @@ out:
} else {
mcasp->tdm_slots = pdata->tdm_slots;
}
+ } else {
+ mcasp->tdm_slots = 32;
}
mcasp->num_serializer = pdata->num_serializer;
@@ -2242,10 +2360,17 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
dma_data->filter_data = "tx";
- if (dat)
+ if (dat) {
dma_data->addr = dat->start;
- else
+ /*
+ * According to the TRM there should be 0x200 offset added to
+ * the DAT port address
+ */
+ if (mcasp->version == MCASP_VERSION_OMAP)
+ dma_data->addr += davinci_mcasp_txdma_offset(mcasp->pdata);
+ } else {
dma_data->addr = mem->start + davinci_mcasp_txdma_offset(mcasp->pdata);
+ }
/* RX is not valid in DIT mode */
@@ -2310,7 +2435,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
ret = edma_pcm_platform_register(&pdev->dev);
break;
case PCM_SDMA:
- ret = sdma_pcm_platform_register(&pdev->dev, "tx", "rx");
+ if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
+ ret = sdma_pcm_platform_register(&pdev->dev, "tx", "rx");
+ else
+ ret = sdma_pcm_platform_register(&pdev->dev, "tx", NULL);
break;
case PCM_UDMA:
ret = udma_pcm_platform_register(&pdev->dev);
diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c
index 265bbc5a2f96..9347f982c3e1 100644
--- a/sound/soc/ti/j721e-evm.c
+++ b/sound/soc/ti/j721e-evm.c
@@ -23,8 +23,11 @@
*/
#define J721E_CODEC_CONF_COUNT 5
-#define J721E_AUDIO_DOMAIN_CPB 0
-#define J721E_AUDIO_DOMAIN_IVI 1
+enum j721e_audio_domain_id {
+ J721E_AUDIO_DOMAIN_CPB = 0,
+ J721E_AUDIO_DOMAIN_IVI,
+ J721E_AUDIO_DOMAIN_LAST,
+};
#define J721E_CLK_PARENT_48000 0
#define J721E_CLK_PARENT_44100 1
@@ -78,7 +81,7 @@ struct j721e_priv {
u32 pll_rates[2];
unsigned int hsdiv_rates[2];
- struct j721e_audio_domain audio_domains[2];
+ struct j721e_audio_domain audio_domains[J721E_AUDIO_DOMAIN_LAST];
struct mutex mutex;
};
@@ -199,9 +202,8 @@ static int j721e_configure_refclk(struct j721e_priv *priv,
if (domain->parent_clk_id == -1 || priv->hsdiv_rates[domain->parent_clk_id] != scki) {
dev_dbg(priv->dev,
- "%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n",
- audio_domain == J721E_AUDIO_DOMAIN_CPB ? "CPB" : "IVI",
- rate,
+ "domain%u configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n",
+ audio_domain, rate,
clk_id == J721E_CLK_PARENT_48000 ? "PLL4" : "PLL15",
ratios_for_pcm3168a[i], scki);
@@ -263,10 +265,11 @@ static int j721e_audio_startup(struct snd_pcm_substream *substream)
domain->active++;
- if (priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate)
- active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate;
- else
- active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].rate;
+ for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++) {
+ active_rate = priv->audio_domains[i].rate;
+ if (active_rate)
+ break;
+ }
if (active_rate)
ret = snd_pcm_hw_constraint_single(substream->runtime,
@@ -825,7 +828,7 @@ static int j721e_soc_probe(struct platform_device *pdev)
struct snd_soc_card *card;
const struct of_device_id *match;
struct j721e_priv *priv;
- int link_cnt, conf_cnt, ret;
+ int link_cnt, conf_cnt, ret, i;
if (!node) {
dev_err(&pdev->dev, "of node is missing.\n");
@@ -849,8 +852,9 @@ static int j721e_soc_probe(struct platform_device *pdev)
if (!priv->dai_links)
return -ENOMEM;
- priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].parent_clk_id = -1;
- priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].parent_clk_id = -1;
+ for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++)
+ priv->audio_domains[i].parent_clk_id = -1;
+
priv->dev = &pdev->dev;
card = &priv->card;
card->dev = &pdev->dev;
diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c
index 91cc9a4f44d7..2e3d1eea77c1 100644
--- a/sound/soc/ti/omap-abe-twl6040.c
+++ b/sound/soc/ti/omap-abe-twl6040.c
@@ -292,11 +292,6 @@ static int omap_abe_probe(struct platform_device *pdev)
card->fully_routed = 1;
- if (!priv->mclk_freq) {
- dev_err(&pdev->dev, "MCLK frequency missing\n");
- return -ENODEV;
- }
-
card->dai_link = priv->dai_links;
card->num_links = num_links;
diff --git a/sound/soc/uniphier/aio-cpu.c b/sound/soc/uniphier/aio-cpu.c
index cf9814130067..4e8d5f7532ba 100644
--- a/sound/soc/uniphier/aio-cpu.c
+++ b/sound/soc/uniphier/aio-cpu.c
@@ -128,8 +128,8 @@ static const struct uniphier_aio_spec *find_spec(struct uniphier_aio *aio,
static int find_divider(struct uniphier_aio *aio, int pll_id, unsigned int freq)
{
struct uniphier_aio_pll *pll;
- int mul[] = { 1, 1, 1, 2, };
- int div[] = { 2, 3, 1, 3, };
+ static const int mul[] = { 1, 1, 1, 2, };
+ static const int div[] = { 2, 3, 1, 3, };
int i;
if (!is_valid_pll(aio->chip, pll_id))
diff --git a/sound/usb/card.c b/sound/usb/card.c
index a1f8c3a026f5..fd570a42f043 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -68,9 +68,11 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
static bool ignore_ctl_error;
static bool autoclock = true;
+static bool lowlatency = true;
static char *quirk_alias[SNDRV_CARDS];
static char *delayed_register[SNDRV_CARDS];
static bool implicit_fb[SNDRV_CARDS];
+static unsigned int quirk_flags[SNDRV_CARDS];
bool snd_usb_use_vmalloc = true;
bool snd_usb_skip_validation;
@@ -92,12 +94,16 @@ MODULE_PARM_DESC(ignore_ctl_error,
"Ignore errors from USB controller for mixer interfaces.");
module_param(autoclock, bool, 0444);
MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");
+module_param(lowlatency, bool, 0444);
+MODULE_PARM_DESC(lowlatency, "Enable low latency playback (default: yes).");
module_param_array(quirk_alias, charp, NULL, 0444);
MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");
module_param_array(delayed_register, charp, NULL, 0444);
MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4.");
module_param_array(implicit_fb, bool, NULL, 0444);
MODULE_PARM_DESC(implicit_fb, "Apply generic implicit feedback sync mode.");
+module_param_array(quirk_flags, uint, NULL, 0444);
+MODULE_PARM_DESC(quirk_flags, "Driver quirk bit flags.");
module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444);
MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes).");
module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444);
@@ -378,6 +384,9 @@ static const struct usb_audio_device_name usb_audio_names[] = {
DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
+ DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"),
+ DEVICE_NAME(0x05e1, 0x0480, "Hauppauge", "Woodbury"),
+
/* ASUS ROG Strix */
PROFILE_NAME(0x0b05, 0x1917,
"Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
@@ -406,6 +415,8 @@ static const struct usb_audio_device_name usb_audio_names[] = {
PROFILE_NAME(0x0db0, 0x543d,
"Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
+ DEVICE_NAME(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"),
+
/* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */
DEVICE_NAME(0x103d, 0x0100, "Stanton", "ScratchAmp"),
DEVICE_NAME(0x103d, 0x0101, "Stanton", "ScratchAmp"),
@@ -424,6 +435,22 @@ static const struct usb_audio_device_name usb_audio_names[] = {
PROFILE_NAME(0x26ce, 0x0a01,
"Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
+ DEVICE_NAME(0x2040, 0x7200, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"),
+ DEVICE_NAME(0x2040, 0x7210, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"),
+ DEVICE_NAME(0x2040, 0x7213, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x7217, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x721b, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x721e, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x721f, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x7240, "Hauppauge", "HVR-850"),
+ DEVICE_NAME(0x2040, 0x7260, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x7280, "Hauppauge", "HVR-950Q"),
+ DEVICE_NAME(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"),
+ DEVICE_NAME(0x2040, 0x8200, "Hauppauge", "Woodbury"),
+
{ } /* terminator */
};
@@ -599,6 +626,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
chip->setup = device_setup[idx];
chip->generic_implicit_fb = implicit_fb[idx];
chip->autoclock = autoclock;
+ chip->lowlatency = lowlatency;
atomic_set(&chip->active, 1); /* avoid autopm during probing */
atomic_set(&chip->usage_count, 0);
atomic_set(&chip->shutdown, 0);
@@ -610,6 +638,11 @@ static int snd_usb_audio_create(struct usb_interface *intf,
INIT_LIST_HEAD(&chip->midi_list);
INIT_LIST_HEAD(&chip->mixer_list);
+ if (quirk_flags[idx])
+ chip->quirk_flags = quirk_flags[idx];
+ else
+ snd_usb_init_quirk_flags(chip);
+
card->private_free = snd_usb_audio_free;
strcpy(card->driver, "USB-Audio");
@@ -781,6 +814,12 @@ static int usb_audio_probe(struct usb_interface *intf,
dev_set_drvdata(&dev->dev, chip);
+ if (ignore_ctl_error)
+ chip->quirk_flags |= QUIRK_FLAG_IGNORE_CTL_ERROR;
+
+ if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND)
+ usb_disable_autosuspend(interface_to_usbdev(intf));
+
/*
* For devices with more than one control interface, we assume the
* first contains the audio controls. We might need a more specific
@@ -789,7 +828,6 @@ static int usb_audio_probe(struct usb_interface *intf,
if (!chip->ctrl_intf)
chip->ctrl_intf = alts;
- chip->txfr_quirk = 0;
err = 1; /* continue */
if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
/* need some special handlings */
@@ -803,7 +841,7 @@ static int usb_audio_probe(struct usb_interface *intf,
err = snd_usb_create_streams(chip, ifnum);
if (err < 0)
goto __error;
- err = snd_usb_create_mixer(chip, ifnum, ignore_ctl_error);
+ err = snd_usb_create_mixer(chip, ifnum);
if (err < 0)
goto __error;
}
@@ -825,7 +863,7 @@ static int usb_audio_probe(struct usb_interface *intf,
goto __error;
}
- if (quirk && quirk->shares_media_device) {
+ if (chip->quirk_flags & QUIRK_FLAG_SHARE_MEDIA_DEVICE) {
/* don't want to fail when snd_media_device_create() fails */
snd_media_device_create(chip, intf);
}
@@ -907,7 +945,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
}
}
- if (chip->quirk_type == QUIRK_SETUP_DISABLE_AUTOSUSPEND)
+ if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND)
usb_enable_autosuspend(interface_to_usbdev(intf));
chip->num_interfaces--;
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 6c0a052a28f9..5b19901f305a 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -94,6 +94,7 @@ struct snd_usb_endpoint {
struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */
unsigned int nurbs; /* # urbs */
+ unsigned int nominal_queue_size; /* total buffer sizes in URBs */
unsigned long active_mask; /* bitmask of active urbs */
unsigned long unlink_mask; /* bitmask of unlinked urbs */
char *syncbuf; /* sync buffer for all sync URBs */
@@ -187,6 +188,7 @@ struct snd_usb_substream {
} dsd_dop;
bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */
+ bool early_playback_start; /* early start needed for playback? */
struct media_ctl *media_ctl;
};
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 14456f61539e..81d5ce07d548 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -324,11 +324,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
sources[ret - 1],
visited, validate);
if (ret > 0) {
- /*
- * For Samsung USBC Headset (AKG), setting clock selector again
- * will result in incorrect default clock setting problems
- */
- if (chip->usb_id == USB_ID(0x04e8, 0xa051))
+ /* Skip setting clock selector again for some devices */
+ if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR)
return ret;
err = uac_clock_selector_set_val(chip, entity_id, cur);
if (err < 0)
@@ -426,7 +423,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
/* Don't check the sample rate for devices which we know don't
* support reading */
- if (snd_usb_get_sample_rate_quirk(chip))
+ if (chip->quirk_flags & QUIRK_FLAG_GET_SAMPLE_RATE)
return 0;
/* the firmware is likely buggy, don't repeat to fail too many times */
if (chip->sample_rate_read_error > 2)
@@ -541,10 +538,8 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
*/
clock = snd_usb_clock_find_source(chip, fmt, false);
- /* Denon DN-X1600 hardcoded
- * Sample rate seems to be set on the hardware itself
- */
- if (chip->usb_id == USB_ID(0x154e, 0x500e))
+ /* Hardcoded sample rates */
+ if (chip->quirk_flags & QUIRK_FLAG_IGNORE_CLOCK_SOURCE)
return 0;
if (clock < 0)
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 4f856771216b..533919a28856 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -240,6 +240,11 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
call_retire_callback(ep, urb);
}
+static inline bool has_tx_length_quirk(struct snd_usb_audio *chip)
+{
+ return chip->quirk_flags & QUIRK_FLAG_TX_LENGTH;
+}
+
static void prepare_silent_urb(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *ctx)
{
@@ -250,7 +255,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep,
int i;
/* For tx_length_quirk, put packet length at start of packet */
- if (ep->chip->tx_length_quirk)
+ if (has_tx_length_quirk(ep->chip))
extra = sizeof(packet_length);
for (i = 0; i < ctx->packets; ++i) {
@@ -803,7 +808,8 @@ static int endpoint_set_interface(struct snd_usb_audio *chip,
return err;
}
- snd_usb_set_interface_quirk(chip);
+ if (chip->quirk_flags & QUIRK_FLAG_IFACE_DELAY)
+ msleep(50);
return 0;
}
@@ -952,7 +958,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
unsigned int max_urbs, i;
const struct audioformat *fmt = ep->cur_audiofmt;
int frame_bits = ep->cur_frame_bytes * 8;
- int tx_length_quirk = (chip->tx_length_quirk &&
+ int tx_length_quirk = (has_tx_length_quirk(chip) &&
usb_pipeout(ep->pipe));
usb_audio_dbg(chip, "Setting params for data EP 0x%x, pipe 0x%x\n",
@@ -1126,6 +1132,10 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
INIT_LIST_HEAD(&u->ready_list);
}
+ /* total buffer bytes of all URBs plus the next queue;
+ * referred in pcm.c
+ */
+ ep->nominal_queue_size = maxsize * urb_packs * (ep->nurbs + 1);
return 0;
out_of_memory:
@@ -1287,6 +1297,9 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
* to be set up before parameter setups
*/
iface_first = ep->cur_audiofmt->protocol == UAC_VERSION_1;
+ /* Workaround for devices that require the interface setup at first like UAC1 */
+ if (chip->quirk_flags & QUIRK_FLAG_SET_IFACE_FIRST)
+ iface_first = true;
if (iface_first) {
err = endpoint_set_interface(chip, ep, true);
if (err < 0)
@@ -1377,7 +1390,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
goto __error;
if (snd_usb_endpoint_implicit_feedback_sink(ep) &&
- !ep->chip->playback_first) {
+ !(ep->chip->quirk_flags & QUIRK_FLAG_PLAYBACK_FIRST)) {
for (i = 0; i < ep->nurbs; i++) {
struct snd_urb_ctx *ctx = ep->urb + i;
list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
diff --git a/sound/usb/format.c b/sound/usb/format.c
index eb216fef4ba7..50efccbffb8a 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -472,12 +472,8 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
* behavior afterwards by some unknown reason. Do this only for the
* known devices.
*/
- switch (USB_ID_VENDOR(chip->usb_id)) {
- case 0x07fd: /* MOTU */
- break;
- default:
+ if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES))
return 0; /* don't perform the validation as default */
- }
table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL);
if (!table)
diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index 590a0dbba7a2..23767a14d126 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -171,7 +171,7 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip,
if (!usb_endpoint_is_isoc_in(epd) ||
(epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
return 0;
- chip->playback_first = 1;
+ chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
alts->desc.bInterfaceNumber, alts);
}
@@ -320,7 +320,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
case IMPLICIT_FB_FIXED:
return 0; /* no quirk */
case IMPLICIT_FB_BOTH:
- chip->playback_first = 1;
+ chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
return add_generic_implicit_fb(chip, fmt, alts);
}
}
@@ -344,7 +344,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
/* Pioneer devices with vendor spec class */
if (is_pioneer_implicit_fb(chip, alts)) {
- chip->playback_first = 1;
+ chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST;
return add_implicit_fb_sync_ep(chip, fmt,
get_endpoint(alts, 1)->bEndpointAddress,
1, alts->desc.bInterfaceNumber,
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 9b713b4a5ec4..43bc59575a6e 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1572,9 +1572,9 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
struct snd_card *card)
{
- const char *names_to_check[] = {
+ static const char * const names_to_check[] = {
"Headset", "headset", "Headphone", "headphone", NULL};
- const char **s;
+ const char * const *s;
bool found = false;
if (strcmp("Speaker", kctl->id.name))
@@ -3183,7 +3183,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
state.map = map->map;
state.selector_map = map->selector_map;
mixer->connector_map = map->connector_map;
- mixer->ignore_ctl_error |= map->ignore_ctl_error;
break;
}
}
@@ -3508,8 +3507,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
return 0;
}
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
- int ignore_error)
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif)
{
static const struct snd_device_ops dev_ops = {
.dev_free = snd_usb_mixer_dev_free
@@ -3523,7 +3521,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
if (!mixer)
return -ENOMEM;
mixer->chip = chip;
- mixer->ignore_ctl_error = ignore_error;
+ mixer->ignore_ctl_error = !!(chip->quirk_flags & QUIRK_FLAG_IGNORE_CTL_ERROR);
mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems),
GFP_KERNEL);
if (!mixer->id_elems) {
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index ea41e7a1f7bf..876bbc9a71ad 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -97,8 +97,7 @@ struct usb_mixer_elem_info {
void *private_data;
};
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
- int ignore_error);
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif);
void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer);
void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index c5794e83fd80..55eea90ee993 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -28,7 +28,6 @@ struct usbmix_ctl_map {
const struct usbmix_name_map *map;
const struct usbmix_selector_map *selector_map;
const struct usbmix_connector_map *connector_map;
- int ignore_ctl_error;
};
/*
@@ -432,7 +431,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
{
.id = USB_ID(0x041e, 0x3000),
.map = extigy_map,
- .ignore_ctl_error = 1,
},
{
.id = USB_ID(0x041e, 0x3010),
@@ -452,29 +450,11 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
.map = audigy2nx_map,
.selector_map = audigy2nx_selectors,
},
- { /* Logitech, Inc. QuickCam Pro for Notebooks */
- .id = USB_ID(0x046d, 0x0991),
- .ignore_ctl_error = 1,
- },
- { /* Logitech, Inc. QuickCam E 3500 */
- .id = USB_ID(0x046d, 0x09a4),
- .ignore_ctl_error = 1,
- },
{ /* Plantronics GameCom 780 */
.id = USB_ID(0x047f, 0xc010),
.map = gamecom780_map,
},
{
- /* Hercules DJ Console (Windows Edition) */
- .id = USB_ID(0x06f8, 0xb000),
- .ignore_ctl_error = 1,
- },
- {
- /* Hercules DJ Console (Macintosh Edition) */
- .id = USB_ID(0x06f8, 0xd002),
- .ignore_ctl_error = 1,
- },
- {
/* Hercules Gamesurround Muse Pocket LT
* (USB 5.1 Channel Audio Adapter)
*/
@@ -492,7 +472,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
{
.id = USB_ID(0x08bb, 0x2702),
.map = linex_map,
- .ignore_ctl_error = 1,
},
{
.id = USB_ID(0x0a92, 0x0091),
@@ -517,7 +496,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
{
.id = USB_ID(0x13e5, 0x0001),
.map = scratch_live_map,
- .ignore_ctl_error = 1,
},
{
.id = USB_ID(0x200c, 0x1018),
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 0a3cb8fd7d00..a66ce0375fd9 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -594,85 +594,208 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
&snd_xonar_u1_output_switch, NULL);
}
+/* Digidesign Mbox 1 helper functions */
+
+static int snd_mbox1_is_spdif_synced(struct snd_usb_audio *chip)
+{
+ unsigned char buff[3];
+ int err;
+ int is_spdif_synced;
+
+ /* Read clock source */
+ err = snd_usb_ctl_msg(chip->dev,
+ usb_rcvctrlpipe(chip->dev, 0), 0x81,
+ USB_DIR_IN |
+ USB_TYPE_CLASS |
+ USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+ if (err < 0)
+ return err;
+
+ /* spdif sync: buff is all zeroes */
+ is_spdif_synced = !(buff[0] | buff[1] | buff[2]);
+ return is_spdif_synced;
+}
+
+static int snd_mbox1_set_clk_source(struct snd_usb_audio *chip, int rate_or_zero)
+{
+ /* 2 possibilities: Internal -> expects sample rate
+ * S/PDIF sync -> expects rate = 0
+ */
+ unsigned char buff[3];
+
+ buff[0] = (rate_or_zero >> 0) & 0xff;
+ buff[1] = (rate_or_zero >> 8) & 0xff;
+ buff[2] = (rate_or_zero >> 16) & 0xff;
+
+ /* Set clock source */
+ return snd_usb_ctl_msg(chip->dev,
+ usb_sndctrlpipe(chip->dev, 0), 0x1,
+ USB_TYPE_CLASS |
+ USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+}
+
+static int snd_mbox1_is_spdif_input(struct snd_usb_audio *chip)
+{
+ /* Hardware gives 2 possibilities: ANALOG Source -> 0x01
+ * S/PDIF Source -> 0x02
+ */
+ int err;
+ unsigned char source[1];
+
+ /* Read input source */
+ err = snd_usb_ctl_msg(chip->dev,
+ usb_rcvctrlpipe(chip->dev, 0), 0x81,
+ USB_DIR_IN |
+ USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE, 0x00, 0x500, source, 1);
+ if (err < 0)
+ return err;
+
+ return (source[0] == 2);
+}
+
+static int snd_mbox1_set_input_source(struct snd_usb_audio *chip, int is_spdif)
+{
+ /* NB: Setting the input source to S/PDIF resets the clock source to S/PDIF
+ * Hardware expects 2 possibilities: ANALOG Source -> 0x01
+ * S/PDIF Source -> 0x02
+ */
+ unsigned char buff[1];
+
+ buff[0] = (is_spdif & 1) + 1;
+
+ /* Set input source */
+ return snd_usb_ctl_msg(chip->dev,
+ usb_sndctrlpipe(chip->dev, 0), 0x1,
+ USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE, 0x00, 0x500, buff, 1);
+}
+
/* Digidesign Mbox 1 clock source switch (internal/spdif) */
-static int snd_mbox1_switch_get(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *ucontrol)
+static int snd_mbox1_clk_switch_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
{
+ struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+ struct snd_usb_audio *chip = list->mixer->chip;
+ int err;
+
+ err = snd_usb_lock_shutdown(chip);
+ if (err < 0)
+ goto err;
+
+ err = snd_mbox1_is_spdif_synced(chip);
+ if (err < 0)
+ goto err;
+
+ kctl->private_value = err;
+ err = 0;
ucontrol->value.enumerated.item[0] = kctl->private_value;
- return 0;
+err:
+ snd_usb_unlock_shutdown(chip);
+ return err;
}
-static int snd_mbox1_switch_update(struct usb_mixer_interface *mixer, int val)
+static int snd_mbox1_clk_switch_update(struct usb_mixer_interface *mixer, int is_spdif_sync)
{
struct snd_usb_audio *chip = mixer->chip;
int err;
- unsigned char buff[3];
err = snd_usb_lock_shutdown(chip);
if (err < 0)
return err;
- /* Prepare for magic command to toggle clock source */
- err = snd_usb_ctl_msg(chip->dev,
- usb_rcvctrlpipe(chip->dev, 0), 0x81,
- USB_DIR_IN |
- USB_TYPE_CLASS |
- USB_RECIP_INTERFACE, 0x00, 0x500, buff, 1);
+ err = snd_mbox1_is_spdif_input(chip);
if (err < 0)
goto err;
- err = snd_usb_ctl_msg(chip->dev,
- usb_rcvctrlpipe(chip->dev, 0), 0x81,
- USB_DIR_IN |
- USB_TYPE_CLASS |
- USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+
+ err = snd_mbox1_is_spdif_synced(chip);
if (err < 0)
goto err;
- /* 2 possibilities: Internal -> send sample rate
- * S/PDIF sync -> send zeroes
- * NB: Sample rate locked to 48kHz on purpose to
- * prevent user from resetting the sample rate
- * while S/PDIF sync is enabled and confusing
- * this configuration.
- */
- if (val == 0) {
- buff[0] = 0x80;
- buff[1] = 0xbb;
- buff[2] = 0x00;
- } else {
- buff[0] = buff[1] = buff[2] = 0x00;
- }
+ /* FIXME: hardcoded sample rate */
+ err = snd_mbox1_set_clk_source(chip, is_spdif_sync ? 0 : 48000);
+ if (err < 0)
+ goto err;
- /* Send the magic command to toggle the clock source */
- err = snd_usb_ctl_msg(chip->dev,
- usb_sndctrlpipe(chip->dev, 0), 0x1,
- USB_TYPE_CLASS |
- USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+ err = snd_mbox1_is_spdif_synced(chip);
+err:
+ snd_usb_unlock_shutdown(chip);
+ return err;
+}
+
+static int snd_mbox1_clk_switch_put(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+ struct usb_mixer_interface *mixer = list->mixer;
+ int err;
+ bool cur_val, new_val;
+
+ cur_val = kctl->private_value;
+ new_val = ucontrol->value.enumerated.item[0];
+ if (cur_val == new_val)
+ return 0;
+
+ kctl->private_value = new_val;
+ err = snd_mbox1_clk_switch_update(mixer, new_val);
+ return err < 0 ? err : 1;
+}
+
+static int snd_mbox1_clk_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char *const texts[2] = {
+ "Internal",
+ "S/PDIF"
+ };
+
+ return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
+}
+
+static int snd_mbox1_clk_switch_resume(struct usb_mixer_elem_list *list)
+{
+ return snd_mbox1_clk_switch_update(list->mixer, list->kctl->private_value);
+}
+
+/* Digidesign Mbox 1 input source switch (analog/spdif) */
+
+static int snd_mbox1_src_switch_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] = kctl->private_value;
+ return 0;
+}
+
+static int snd_mbox1_src_switch_update(struct usb_mixer_interface *mixer, int is_spdif_input)
+{
+ struct snd_usb_audio *chip = mixer->chip;
+ int err;
+
+ err = snd_usb_lock_shutdown(chip);
+ if (err < 0)
+ return err;
+
+ err = snd_mbox1_is_spdif_input(chip);
if (err < 0)
goto err;
- err = snd_usb_ctl_msg(chip->dev,
- usb_rcvctrlpipe(chip->dev, 0), 0x81,
- USB_DIR_IN |
- USB_TYPE_CLASS |
- USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);
+
+ err = snd_mbox1_set_input_source(chip, is_spdif_input);
if (err < 0)
goto err;
- err = snd_usb_ctl_msg(chip->dev,
- usb_rcvctrlpipe(chip->dev, 0), 0x81,
- USB_DIR_IN |
- USB_TYPE_CLASS |
- USB_RECIP_ENDPOINT, 0x100, 0x2, buff, 3);
+
+ err = snd_mbox1_is_spdif_input(chip);
if (err < 0)
goto err;
+ err = snd_mbox1_is_spdif_synced(chip);
err:
snd_usb_unlock_shutdown(chip);
return err;
}
-static int snd_mbox1_switch_put(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *ucontrol)
+static int snd_mbox1_src_switch_put(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
struct usb_mixer_interface *mixer = list->mixer;
@@ -685,42 +808,60 @@ static int snd_mbox1_switch_put(struct snd_kcontrol *kctl,
return 0;
kctl->private_value = new_val;
- err = snd_mbox1_switch_update(mixer, new_val);
+ err = snd_mbox1_src_switch_update(mixer, new_val);
return err < 0 ? err : 1;
}
-static int snd_mbox1_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
+static int snd_mbox1_src_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static const char *const texts[2] = {
- "Internal",
+ "Analog",
"S/PDIF"
};
return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
}
-static int snd_mbox1_switch_resume(struct usb_mixer_elem_list *list)
+static int snd_mbox1_src_switch_resume(struct usb_mixer_elem_list *list)
{
- return snd_mbox1_switch_update(list->mixer, list->kctl->private_value);
+ return snd_mbox1_src_switch_update(list->mixer, list->kctl->private_value);
}
-static const struct snd_kcontrol_new snd_mbox1_switch = {
+static const struct snd_kcontrol_new snd_mbox1_clk_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Clock Source",
.index = 0,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = snd_mbox1_switch_info,
- .get = snd_mbox1_switch_get,
- .put = snd_mbox1_switch_put,
+ .info = snd_mbox1_clk_switch_info,
+ .get = snd_mbox1_clk_switch_get,
+ .put = snd_mbox1_clk_switch_put,
+ .private_value = 0
+};
+
+static const struct snd_kcontrol_new snd_mbox1_src_switch = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Input Source",
+ .index = 1,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_mbox1_src_switch_info,
+ .get = snd_mbox1_src_switch_get,
+ .put = snd_mbox1_src_switch_put,
.private_value = 0
};
-static int snd_mbox1_create_sync_switch(struct usb_mixer_interface *mixer)
+static int snd_mbox1_controls_create(struct usb_mixer_interface *mixer)
{
- return add_single_ctl_with_resume(mixer, 0,
- snd_mbox1_switch_resume,
- &snd_mbox1_switch, NULL);
+ int err;
+ err = add_single_ctl_with_resume(mixer, 0,
+ snd_mbox1_clk_switch_resume,
+ &snd_mbox1_clk_switch, NULL);
+ if (err < 0)
+ return err;
+
+ return add_single_ctl_with_resume(mixer, 1,
+ snd_mbox1_src_switch_resume,
+ &snd_mbox1_src_switch, NULL);
}
/* Native Instruments device quirks */
@@ -3029,7 +3170,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
break;
case USB_ID(0x0dba, 0x1000): /* Digidesign Mbox 1 */
- err = snd_mbox1_create_sync_switch(mixer);
+ err = snd_mbox1_controls_create(mixer);
break;
case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 4e5031a68064..5dc9266180e3 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -614,6 +614,15 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
subs->period_elapsed_pending = 0;
runtime->delay = 0;
+ /* check whether early start is needed for playback stream */
+ subs->early_playback_start =
+ subs->direction == SNDRV_PCM_STREAM_PLAYBACK &&
+ (!chip->lowlatency ||
+ (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes));
+
+ if (subs->early_playback_start)
+ ret = start_endpoints(subs);
+
unlock:
snd_usb_unlock_shutdown(chip);
return ret;
@@ -1394,7 +1403,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
subs->trigger_tstamp_pending_update = false;
}
- if (period_elapsed && !subs->running) {
+ if (period_elapsed && !subs->running && !subs->early_playback_start) {
subs->period_elapsed_pending = 1;
period_elapsed = 0;
}
@@ -1448,7 +1457,8 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
prepare_playback_urb,
retire_playback_urb,
subs);
- if (cmd == SNDRV_PCM_TRIGGER_START) {
+ if (!subs->early_playback_start &&
+ cmd == SNDRV_PCM_TRIGGER_START) {
err = start_endpoints(subs);
if (err < 0) {
snd_usb_endpoint_set_callback(subs->data_endpoint,
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 19bb499c17da..e03043f7dad3 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2730,23 +2730,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
-/* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
-{
- USB_DEVICE(0x17aa, 0x1046),
- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_SETUP_DISABLE_AUTOSUSPEND
- }
-},
-/* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
-{
- USB_DEVICE(0x17aa, 0x104d),
- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_SETUP_DISABLE_AUTOSUSPEND
- }
-},
-
/* Native Instruments MK2 series */
{
/* Komplete Audio 6 */
@@ -2802,53 +2785,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
-/*
- * Auvitek au0828 devices with audio interface.
- * This should be kept in sync with drivers/media/usb/au0828/au0828-cards.c
- * Please notice that some drivers are DVB only, and don't need to be
- * here. That's the case, for example, of DVICO_FUSIONHDTV7.
- */
-
-#define AU0828_DEVICE(vid, pid, vname, pname) { \
- USB_AUDIO_DEVICE(vid, pid), \
- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { \
- .vendor_name = vname, \
- .product_name = pname, \
- .ifnum = QUIRK_ANY_INTERFACE, \
- .type = QUIRK_AUDIO_ALIGN_TRANSFER, \
- .shares_media_device = 1, \
- } \
-}
-
-AU0828_DEVICE(0x2040, 0x7200, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7240, "Hauppauge", "HVR-850"),
-AU0828_DEVICE(0x2040, 0x7210, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7217, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721b, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721e, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x721f, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7280, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"),
-AU0828_DEVICE(0x05e1, 0x0480, "Hauppauge", "Woodbury"),
-AU0828_DEVICE(0x2040, 0x8200, "Hauppauge", "Woodbury"),
-AU0828_DEVICE(0x2040, 0x7260, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7213, "Hauppauge", "HVR-950Q"),
-AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
-
-/* Syntek STK1160 */
-{
- USB_AUDIO_DEVICE(0x05e1, 0x0408),
- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
- .vendor_name = "Syntek",
- .product_name = "STK1160",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_AUDIO_ALIGN_TRANSFER
- }
-},
-
/* Digidesign Mbox */
{
/* Thanks to Clemens Ladisch <clemens@ladisch.de> */
@@ -3811,7 +3747,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
* MacroSilicon MS2109 based HDMI capture cards
*
* These claim 96kHz 1ch in the descriptors, but are actually 48kHz 2ch.
- * They also need QUIRK_AUDIO_ALIGN_TRANSFER, which makes one wonder if
+ * They also need QUIRK_FLAG_ALIGN_TRANSFER, which makes one wonder if
* they pretend to be 96kHz mono as a workaround for stereo being broken
* by that...
*
@@ -3828,10 +3764,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
.data = &(const struct snd_usb_audio_quirk[]) {
{
.ifnum = 2,
- .type = QUIRK_AUDIO_ALIGN_TRANSFER,
- },
- {
- .ifnum = 2,
.type = QUIRK_AUDIO_STANDARD_MIXER,
},
{
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 326d1b0ea5e6..4479a590194f 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -75,19 +75,6 @@ static int ignore_interface_quirk(struct snd_usb_audio *chip,
}
-/*
- * Allow alignment on audio sub-slot (channel samples) rather than
- * on audio slots (audio frames)
- */
-static int create_align_transfer_quirk(struct snd_usb_audio *chip,
- struct usb_interface *iface,
- struct usb_driver *driver,
- const struct snd_usb_audio_quirk *quirk)
-{
- chip->txfr_quirk = 1;
- return 1; /* Continue with creating streams and mixer */
-}
-
static int create_any_midi_quirk(struct snd_usb_audio *chip,
struct usb_interface *intf,
struct usb_driver *driver,
@@ -108,9 +95,6 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
struct usb_interface_descriptor *altsd;
int err;
- if (chip->usb_id == USB_ID(0x1686, 0x00dd)) /* Zoom R16/24 */
- chip->tx_length_quirk = 1;
-
alts = &iface->altsetting[0];
altsd = get_iface_desc(alts);
err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
@@ -547,16 +531,7 @@ static int create_standard_mixer_quirk(struct snd_usb_audio *chip,
if (quirk->ifnum < 0)
return 0;
- return snd_usb_create_mixer(chip, quirk->ifnum, 0);
-}
-
-static int setup_disable_autosuspend(struct snd_usb_audio *chip,
- struct usb_interface *iface,
- struct usb_driver *driver,
- const struct snd_usb_audio_quirk *quirk)
-{
- usb_disable_autosuspend(interface_to_usbdev(iface));
- return 1; /* Continue with creating streams and mixer */
+ return snd_usb_create_mixer(chip, quirk->ifnum);
}
/*
@@ -595,9 +570,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
- [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
[QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
- [QUIRK_SETUP_DISABLE_AUTOSUSPEND] = setup_disable_autosuspend,
};
if (quirk->type < QUIRK_TYPE_COUNT) {
@@ -1518,62 +1491,13 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
}
}
-bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
-{
- /* devices which do not support reading the sample rate. */
- switch (chip->usb_id) {
- case USB_ID(0x041e, 0x4080): /* Creative Live Cam VF0610 */
- case USB_ID(0x04d8, 0xfeea): /* Benchmark DAC1 Pre */
- case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
- case USB_ID(0x05a3, 0x9420): /* ELP HD USB Camera */
- case USB_ID(0x05a7, 0x1020): /* Bose Companion 5 */
- case USB_ID(0x074d, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
- case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
- case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
- case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
- case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */
- case USB_ID(0x413c, 0xa506): /* Dell AE515 sound bar */
- case USB_ID(0x046d, 0x084c): /* Logitech ConferenceCam Connect */
- return true;
- }
-
- /* devices of these vendors don't support reading rate, either */
- switch (USB_ID_VENDOR(chip->usb_id)) {
- case 0x045e: /* MS Lifecam */
- case 0x047f: /* Plantronics */
- case 0x1de7: /* Phoenix Audio */
- return true;
- }
-
- return false;
-}
-
-/* ITF-USB DSD based DACs need a vendor cmd to switch
- * between PCM and native DSD mode
- */
-static bool is_itf_usb_dsd_dac(unsigned int id)
-{
- switch (id) {
- case USB_ID(0x154e, 0x1002): /* Denon DCD-1500RE */
- case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */
- case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
- case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
- case USB_ID(0x1852, 0x5065): /* Luxman DA-06 */
- case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-501V2/UD-503/NT-503 */
- case USB_ID(0x0644, 0x8044): /* Esoteric D-05X */
- case USB_ID(0x0644, 0x804a): /* TEAC UD-301 */
- return true;
- }
- return false;
-}
-
int snd_usb_select_mode_quirk(struct snd_usb_audio *chip,
const struct audioformat *fmt)
{
struct usb_device *dev = chip->dev;
int err;
- if (is_itf_usb_dsd_dac(chip->usb_id)) {
+ if (chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) {
/* First switch to alt set 0, otherwise the mode switch cmd
* will not be accepted by the DAC
*/
@@ -1636,22 +1560,6 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
ep->tenor_fb_quirk = 1;
}
-void snd_usb_set_interface_quirk(struct snd_usb_audio *chip)
-{
- if (!chip)
- return;
- /*
- * "Playback Design" products need a 50ms delay after setting the
- * USB interface.
- */
- switch (USB_ID_VENDOR(chip->usb_id)) {
- case 0x23ba: /* Playback Design */
- case 0x0644: /* TEAC Corp. */
- msleep(50);
- break;
- }
-}
-
/* quirk applied after snd_usb_ctl_msg(); not applied during boot quirks */
void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
__u8 request, __u8 requesttype, __u16 value,
@@ -1659,57 +1567,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
{
struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev);
- if (!chip)
+ if (!chip || (requesttype & USB_TYPE_MASK) != USB_TYPE_CLASS)
return;
- /*
- * "Playback Design" products need a 20ms delay after each
- * class compliant request
- */
- if (USB_ID_VENDOR(chip->usb_id) == 0x23ba &&
- (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
- msleep(20);
-
- /*
- * "TEAC Corp." products need a 20ms delay after each
- * class compliant request
- */
- if (USB_ID_VENDOR(chip->usb_id) == 0x0644 &&
- (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
- msleep(20);
-
- /* ITF-USB DSD based DACs functionality need a delay
- * after each class compliant request
- */
- if (is_itf_usb_dsd_dac(chip->usb_id)
- && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
- msleep(20);
- /*
- * Plantronics headsets (C320, C320-M, etc) need a delay to avoid
- * random microhpone failures.
- */
- if (USB_ID_VENDOR(chip->usb_id) == 0x047f &&
- (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+ if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY)
msleep(20);
-
- /* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950),
- * Jabra 550a, Kingston HyperX needs a tiny delay here,
- * otherwise requests like get/set frequency return
- * as failed despite actually succeeding.
- */
- if ((chip->usb_id == USB_ID(0x1686, 0x00dd) ||
- USB_ID_VENDOR(chip->usb_id) == 0x046d || /* Logitech */
- chip->usb_id == USB_ID(0x0b0e, 0x0349) ||
- chip->usb_id == USB_ID(0x0951, 0x16ad)) &&
- (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+ else if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY_1M)
usleep_range(1000, 2000);
-
- /*
- * Samsung USBC Headset (AKG) need a tiny delay after each
- * class compliant request. (Model number: AAM625R or AAM627R)
- */
- if (chip->usb_id == USB_ID(0x04e8, 0xa051) &&
- (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+ else if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY_5M)
usleep_range(5000, 6000);
}
@@ -1796,7 +1661,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
}
/* ITF-USB DSD based DACs */
- if (is_itf_usb_dsd_dac(chip->usb_id)) {
+ if (chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) {
iface = usb_ifnum_to_if(chip->dev, fp->iface);
/* Altsetting 2 support native DSD if the num of altsets is
@@ -1808,29 +1673,9 @@ 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 0x152a: /* Thesycon devices */
- case 0x20b1: /* XMOS based devices */
- case 0x22d9: /* Oppo */
- case 0x23ba: /* Playback Designs */
- case 0x25ce: /* Mytek devices */
- case 0x278b: /* Rotel? */
- case 0x292b: /* Gustard/Ess based devices */
- case 0x2972: /* FiiO devices */
- case 0x2ab6: /* T+A devices */
- case 0x3353: /* Khadas devices */
- case 0x3842: /* EVGA */
- case 0xc502: /* HiBy devices */
- if (fp->dsd_raw)
- return SNDRV_PCM_FMTBIT_DSD_U32_BE;
- break;
- default:
- break;
-
- }
+ /* Mostly generic method to detect many DSD-capable implementations */
+ if ((chip->quirk_flags & QUIRK_FLAG_DSD_RAW) && fp->dsd_raw)
+ return SNDRV_PCM_FMTBIT_DSD_U32_BE;
return 0;
}
@@ -1916,3 +1761,189 @@ bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
/* Register as normal */
return false;
}
+
+/*
+ * driver behavior quirk flags
+ */
+struct usb_audio_quirk_flags_table {
+ u32 id;
+ u32 flags;
+};
+
+#define DEVICE_FLG(vid, pid, _flags) \
+ { .id = USB_ID(vid, pid), .flags = (_flags) }
+#define VENDOR_FLG(vid, _flags) DEVICE_FLG(vid, 0, _flags)
+
+static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ /* Device matches */
+ DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */
+ QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M),
+ DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */
+ QUIRK_FLAG_SKIP_CLOCK_SELECTOR | QUIRK_FLAG_CTL_MSG_DELAY_5M),
+ DEVICE_FLG(0x054c, 0x0b8c, /* Sony WALKMAN NW-A45 DAC */
+ QUIRK_FLAG_SET_IFACE_FIRST),
+ DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x05a3, 0x9420, /* ELP HD USB Camera */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x05a7, 0x1020, /* Bose Companion 5 */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x05e1, 0x0408, /* Syntek STK1160 */
+ QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x0644, 0x8043, /* TEAC UD-501/UD-501V2/UD-503/NT-503 */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+ QUIRK_FLAG_IFACE_DELAY),
+ DEVICE_FLG(0x0644, 0x8044, /* Esoteric D-05X */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+ QUIRK_FLAG_IFACE_DELAY),
+ DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+ QUIRK_FLAG_IFACE_DELAY),
+ DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */
+ QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */
+ QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */
+ QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M),
+ DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M),
+ DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */
+ QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+ DEVICE_FLG(0x154e, 0x1003, /* Denon DA-300USB */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+ DEVICE_FLG(0x154e, 0x3005, /* Marantz HD-DAC1 */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+ DEVICE_FLG(0x154e, 0x3006, /* Marantz SA-14S1 */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+ DEVICE_FLG(0x154e, 0x500e, /* Denon DN-X1600 */
+ QUIRK_FLAG_IGNORE_CLOCK_SOURCE),
+ DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */
+ QUIRK_FLAG_TX_LENGTH | QUIRK_FLAG_CTL_MSG_DELAY_1M),
+ DEVICE_FLG(0x17aa, 0x1046, /* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
+ QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+ DEVICE_FLG(0x17aa, 0x104d, /* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
+ QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+ DEVICE_FLG(0x1852, 0x5065, /* Luxman DA-06 */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+ DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7210, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7211, /* Hauppauge HVR-950Q-MXL */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7213, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7217, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x721b, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x721e, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x721f, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7240, /* Hauppauge HVR-850 */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7260, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7270, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7280, /* Hauppauge HVR-950Q */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x7281, /* Hauppauge HVR-950Q-MXL */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x2040, 0x8200, /* Hauppauge Woodbury */
+ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
+ QUIRK_FLAG_ALIGN_TRANSFER),
+
+ /* Vendor matches */
+ VENDOR_FLG(0x045e, /* MS Lifecam */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ VENDOR_FLG(0x046d, /* Logitech */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M),
+ VENDOR_FLG(0x047f, /* Plantronics */
+ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY),
+ VENDOR_FLG(0x0644, /* TEAC Corp. */
+ QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY),
+ VENDOR_FLG(0x07fd, /* MOTU */
+ QUIRK_FLAG_VALIDATE_RATES),
+ VENDOR_FLG(0x152a, /* Thesycon devices */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x1de7, /* Phoenix Audio */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
+ VENDOR_FLG(0x20b1, /* XMOS based devices */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x22d9, /* Oppo */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x23ba, /* Playback Design */
+ QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY |
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x25ce, /* Mytek devices */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x278b, /* Rotel? */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x292b, /* Gustard/Ess based devices */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x2972, /* FiiO devices */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x2ab6, /* T+A devices */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x3353, /* Khadas devices */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x3842, /* EVGA */
+ QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0xc502, /* HiBy devices */
+ QUIRK_FLAG_DSD_RAW),
+
+ {} /* terminator */
+};
+
+void snd_usb_init_quirk_flags(struct snd_usb_audio *chip)
+{
+ const struct usb_audio_quirk_flags_table *p;
+
+ for (p = quirk_flags_table; p->id; p++) {
+ if (chip->usb_id == p->id ||
+ (!USB_ID_PRODUCT(p->id) &&
+ USB_ID_VENDOR(chip->usb_id) == USB_ID_VENDOR(p->id))) {
+ usb_audio_dbg(chip,
+ "Set quirk_flags 0x%x for device %04x:%04x\n",
+ p->flags, USB_ID_VENDOR(chip->usb_id),
+ USB_ID_PRODUCT(chip->usb_id));
+ chip->quirk_flags |= p->flags;
+ return;
+ }
+ }
+}
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 67a02303c820..31abb7cb01a5 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -28,14 +28,11 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
const struct audioformat *fmt);
-bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip);
-
int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
const struct audioformat *fp);
void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
-void snd_usb_set_interface_quirk(struct snd_usb_audio *chip);
void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
__u8 request, __u8 requesttype, __u16 value,
__u16 index, void *data, __u16 size);
@@ -53,4 +50,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface);
+void snd_usb_init_quirk_flags(struct snd_usb_audio *chip);
+
#endif /* __USBAUDIO_QUIRKS_H */
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index ee9aa1dcf0d8..ceb93d798182 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -89,8 +89,8 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
subs->stream = as;
subs->direction = stream;
subs->dev = as->chip->dev;
- subs->txfr_quirk = as->chip->txfr_quirk;
- subs->tx_length_quirk = as->chip->tx_length_quirk;
+ subs->txfr_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_ALIGN_TRANSFER);
+ subs->tx_length_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_TX_LENGTH);
subs->speed = snd_usb_get_speed(subs->dev);
subs->pkt_offset_adj = 0;
subs->stream_offset_adj = 0;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 538831cbd925..167834133b9b 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -34,10 +34,8 @@ struct snd_usb_audio {
atomic_t shutdown;
atomic_t usage_count;
wait_queue_head_t shutdown_wait;
- unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
- unsigned int tx_length_quirk:1; /* Put length specifier in transfers */
+ unsigned int quirk_flags;
unsigned int need_delayed_register:1; /* warn for delayed registration */
- unsigned int playback_first:1; /* for implicit fb: don't wait for the first capture URBs */
int num_interfaces;
int num_suspended_intf;
int sample_rate_read_error;
@@ -57,6 +55,7 @@ struct snd_usb_audio {
bool generic_implicit_fb; /* from the 'implicit_fb' module param */
bool autoclock; /* from the 'autoclock' module param */
+ bool lowlatency; /* from the 'lowlatency' module param */
struct usb_host_interface *ctrl_intf; /* the audio control interface */
struct media_device *media_dev;
struct media_intf_devnode *ctl_intf_media_devnode;
@@ -102,10 +101,7 @@ enum quirk_type {
QUIRK_AUDIO_STANDARD_INTERFACE,
QUIRK_AUDIO_FIXED_ENDPOINT,
QUIRK_AUDIO_EDIROL_UAXX,
- QUIRK_AUDIO_ALIGN_TRANSFER,
QUIRK_AUDIO_STANDARD_MIXER,
- QUIRK_SETUP_FMT_AFTER_RESUME,
- QUIRK_SETUP_DISABLE_AUTOSUSPEND,
QUIRK_TYPE_COUNT
};
@@ -115,7 +111,6 @@ struct snd_usb_audio_quirk {
const char *product_name;
int16_t ifnum;
uint16_t type;
- bool shares_media_device;
const void *data;
};
@@ -129,4 +124,64 @@ void snd_usb_unlock_shutdown(struct snd_usb_audio *chip);
extern bool snd_usb_use_vmalloc;
extern bool snd_usb_skip_validation;
+/*
+ * Driver behavior quirk flags, stored in chip->quirk_flags
+ *
+ * QUIRK_FLAG_GET_SAMPLE_RATE:
+ * Skip reading sample rate for devices, as some devices behave inconsistently
+ * or return error
+ * QUIRK_FLAG_SHARE_MEDIA_DEVICE:
+ * Create Media Controller API entries
+ * QUIRK_FLAG_ALIGN_TRANSFER:
+ * Allow alignment on audio sub-slot (channel samples) rather than on audio
+ * slots (audio frames)
+ * QUIRK_TX_LENGTH:
+ * Add length specifier to transfers
+ * QUIRK_FLAG_PLAYBACK_FIRST:
+ * Start playback stream at first even in implement feedback mode
+ * QUIRK_FLAG_SKIP_CLOCK_SELECTOR:
+ * Skip clock selector setup; the device may reset to invalid state
+ * QUIRK_FLAG_IGNORE_CLOCK_SOURCE:
+ * Ignore errors from clock source search; i.e. hardcoded clock
+ * QUIRK_FLAG_ITF_USB_DSD_DAC:
+ * Indicates the device is for ITF-USB DSD based DACs that need a vendor cmd
+ * to switch between PCM and native DSD mode
+ * QUIRK_FLAG_CTL_MSG_DELAY:
+ * Add a delay of 20ms at each control message handling
+ * QUIRK_FLAG_CTL_MSG_DELAY_1M:
+ * Add a delay of 1-2ms at each control message handling
+ * QUIRK_FLAG_CTL_MSG_DELAY_5M:
+ * Add a delay of 5-6ms at each control message handling
+ * QUIRK_FLAG_IFACE_DELAY:
+ * Add a delay of 50ms at each interface setup
+ * QUIRK_FLAG_VALIDATE_RATES:
+ * Perform sample rate validations at probe
+ * QUIRK_FLAG_DISABLE_AUTOSUSPEND:
+ * Disable runtime PM autosuspend
+ * QUIRK_FLAG_IGNORE_CTL_ERROR:
+ * Ignore errors for mixer access
+ * QUIRK_FLAG_DSD_RAW:
+ * Support generic DSD raw U32_BE format
+ * QUIRK_FLAG_SET_IFACE_FIRST:
+ * Set up the interface at first like UAC1
+ */
+
+#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0)
+#define QUIRK_FLAG_SHARE_MEDIA_DEVICE (1U << 1)
+#define QUIRK_FLAG_ALIGN_TRANSFER (1U << 2)
+#define QUIRK_FLAG_TX_LENGTH (1U << 3)
+#define QUIRK_FLAG_PLAYBACK_FIRST (1U << 4)
+#define QUIRK_FLAG_SKIP_CLOCK_SELECTOR (1U << 5)
+#define QUIRK_FLAG_IGNORE_CLOCK_SOURCE (1U << 6)
+#define QUIRK_FLAG_ITF_USB_DSD_DAC (1U << 7)
+#define QUIRK_FLAG_CTL_MSG_DELAY (1U << 8)
+#define QUIRK_FLAG_CTL_MSG_DELAY_1M (1U << 9)
+#define QUIRK_FLAG_CTL_MSG_DELAY_5M (1U << 10)
+#define QUIRK_FLAG_IFACE_DELAY (1U << 11)
+#define QUIRK_FLAG_VALIDATE_RATES (1U << 12)
+#define QUIRK_FLAG_DISABLE_AUTOSUSPEND (1U << 13)
+#define QUIRK_FLAG_IGNORE_CTL_ERROR (1U << 14)
+#define QUIRK_FLAG_DSD_RAW (1U << 15)
+#define QUIRK_FLAG_SET_IFACE_FIRST (1U << 16)
+
#endif /* __USBAUDIO_H */
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index a34d7d9c2a57..378826312abe 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -1024,19 +1024,21 @@ static void wait_clear_underrun_bit(struct snd_intelhad *intelhaddata)
dev_err(intelhaddata->dev, "Unable to clear UNDERRUN bits\n");
}
-/* Perform some reset procedure but only when need_reset is set;
+/* Perform some reset procedure after stopping the stream;
* this is called from prepare or hw_free callbacks once after trigger STOP
* or underrun has been processed in order to settle down the h/w state.
*/
-static void had_do_reset(struct snd_intelhad *intelhaddata)
+static int had_pcm_sync_stop(struct snd_pcm_substream *substream)
{
- if (!intelhaddata->need_reset || !intelhaddata->connected)
- return;
+ struct snd_intelhad *intelhaddata = snd_pcm_substream_chip(substream);
+
+ if (!intelhaddata->connected)
+ return 0;
/* Reset buffer pointers */
had_reset_audio(intelhaddata);
wait_clear_underrun_bit(intelhaddata);
- intelhaddata->need_reset = false;
+ return 0;
}
/* called from irq handler */
@@ -1050,7 +1052,6 @@ static void had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
snd_pcm_stop_xrun(substream);
had_substream_put(intelhaddata);
}
- intelhaddata->need_reset = true;
}
/*
@@ -1142,19 +1143,6 @@ static int had_pcm_hw_params(struct snd_pcm_substream *substream,
}
/*
- * ALSA PCM hw_free callback
- */
-static int had_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_intelhad *intelhaddata;
-
- intelhaddata = snd_pcm_substream_chip(substream);
- had_do_reset(intelhaddata);
-
- return 0;
-}
-
-/*
* ALSA PCM trigger callback
*/
static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -1178,7 +1166,6 @@ static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* Disable Audio */
had_enable_audio(intelhaddata, false);
- intelhaddata->need_reset = true;
break;
default:
@@ -1210,8 +1197,6 @@ static int had_pcm_prepare(struct snd_pcm_substream *substream)
dev_dbg(intelhaddata->dev, "rate=%d\n", runtime->rate);
dev_dbg(intelhaddata->dev, "channels=%d\n", runtime->channels);
- had_do_reset(intelhaddata);
-
/* Get N value in KHz */
disp_samp_freq = intelhaddata->tmds_clock_speed;
@@ -1287,9 +1272,9 @@ static const struct snd_pcm_ops had_pcm_ops = {
.open = had_pcm_open,
.close = had_pcm_close,
.hw_params = had_pcm_hw_params,
- .hw_free = had_pcm_hw_free,
.prepare = had_pcm_prepare,
.trigger = had_pcm_trigger,
+ .sync_stop = had_pcm_sync_stop,
.pointer = had_pcm_pointer,
.mmap = had_pcm_mmap,
};
@@ -1672,11 +1657,6 @@ static void hdmi_lpe_audio_free(struct snd_card *card)
cancel_work_sync(&ctx->hdmi_audio_wq);
}
-
- if (card_ctx->mmio_start)
- iounmap(card_ctx->mmio_start);
- if (card_ctx->irq >= 0)
- free_irq(card_ctx->irq, card_ctx);
}
/*
@@ -1714,8 +1694,8 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
}
/* create a card instance with ALSA framework */
- ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
- THIS_MODULE, sizeof(*card_ctx), &card);
+ ret = snd_devm_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
+ THIS_MODULE, sizeof(*card_ctx), &card);
if (ret)
return ret;
@@ -1751,20 +1731,20 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
__func__, (unsigned int)res_mmio->start,
(unsigned int)res_mmio->end);
- card_ctx->mmio_start = ioremap(res_mmio->start,
- (size_t)(resource_size(res_mmio)));
+ card_ctx->mmio_start =
+ devm_ioremap(&pdev->dev, res_mmio->start,
+ (size_t)(resource_size(res_mmio)));
if (!card_ctx->mmio_start) {
dev_err(&pdev->dev, "Could not get ioremap\n");
- ret = -EACCES;
- goto err;
+ return -EACCES;
}
/* setup interrupt handler */
- ret = request_irq(irq, display_pipe_interrupt_handler, 0,
- pdev->name, card_ctx);
+ ret = devm_request_irq(&pdev->dev, irq, display_pipe_interrupt_handler,
+ 0, pdev->name, card_ctx);
if (ret < 0) {
dev_err(&pdev->dev, "request_irq failed\n");
- goto err;
+ return ret;
}
card_ctx->irq = irq;
@@ -1784,7 +1764,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS,
MAX_CAP_STREAMS, &pcm);
if (ret)
- goto err;
+ return ret;
/* setup private data which can be retrieved when required */
pcm->private_data = ctx;
@@ -1796,7 +1776,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
/* allocate dma pages;
* try to allocate 600k buffer as default which is large enough
*/
- snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_UC,
+ snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
card->dev, HAD_DEFAULT_BUFFER,
HAD_MAX_BUFFER);
@@ -1805,31 +1785,29 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&had_controls[i], ctx);
- if (!kctl) {
- ret = -ENOMEM;
- goto err;
- }
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = pcm->device;
ret = snd_ctl_add(card, kctl);
if (ret < 0)
- goto err;
+ return ret;
}
/* Register channel map controls */
ret = had_register_chmap_ctls(ctx, pcm);
if (ret < 0)
- goto err;
+ return ret;
ret = had_create_jack(ctx, pcm);
if (ret < 0)
- goto err;
+ return ret;
}
ret = snd_card_register(card);
if (ret)
- goto err;
+ return ret;
spin_lock_irq(&pdata->lpe_audio_slock);
pdata->notify_audio_lpe = notify_audio_lpe;
@@ -1846,23 +1824,6 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
}
return 0;
-
-err:
- snd_card_free(card);
- return ret;
-}
-
-/*
- * hdmi_lpe_audio_remove - stop bridge with i915
- *
- * This function is called when the platform device is destroyed.
- */
-static int hdmi_lpe_audio_remove(struct platform_device *pdev)
-{
- struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev);
-
- snd_card_free(card_ctx->card);
- return 0;
}
static const struct dev_pm_ops hdmi_lpe_audio_pm = {
@@ -1875,7 +1836,6 @@ static struct platform_driver hdmi_lpe_audio_driver = {
.pm = &hdmi_lpe_audio_pm,
},
.probe = hdmi_lpe_audio_probe,
- .remove = hdmi_lpe_audio_remove,
};
module_platform_driver(hdmi_lpe_audio_driver);
diff --git a/sound/x86/intel_hdmi_audio.h b/sound/x86/intel_hdmi_audio.h
index bb3853195922..7ce8c2a7d714 100644
--- a/sound/x86/intel_hdmi_audio.h
+++ b/sound/x86/intel_hdmi_audio.h
@@ -127,7 +127,6 @@ struct snd_intelhad {
union aud_cfg aud_config; /* AUD_CONFIG reg value cache */
struct work_struct hdmi_audio_wq;
struct mutex mutex; /* for protecting chmap and eld */
- bool need_reset;
struct snd_jack *jack;
};
diff --git a/tools/bootconfig/scripts/bconf2ftrace.sh b/tools/bootconfig/scripts/bconf2ftrace.sh
index feb30c2c7881..850c2073433e 100755
--- a/tools/bootconfig/scripts/bconf2ftrace.sh
+++ b/tools/bootconfig/scripts/bconf2ftrace.sh
@@ -94,6 +94,92 @@ compose_synth() { # event_name branch
xbc_get_val $2 | while read field; do echo -n "$field; "; done
}
+print_hist_array() { # prefix key
+ __sep="="
+ if xbc_has_key ${1}.${2}; then
+ echo -n ":$2"
+ xbc_get_val ${1}.${2} | while read field; do
+ echo -n "$__sep$field"; __sep=","
+ done
+ fi
+}
+
+print_hist_action_array() { # prefix key
+ __sep="("
+ echo -n ".$2"
+ xbc_get_val ${1}.${2} | while read field; do
+ echo -n "$__sep$field"; __sep=","
+ done
+ echo -n ")"
+}
+
+print_hist_one_action() { # prefix handler param
+ echo -n ":${2}("`xbc_get_val ${1}.${3}`")"
+ if xbc_has_key "${1}.trace"; then
+ print_hist_action_array ${1} "trace"
+ elif xbc_has_key "${1}.save"; then
+ print_hist_action_array ${1} "save"
+ elif xbc_has_key "${1}.snapshot"; then
+ echo -n ".snapshot()"
+ fi
+}
+
+print_hist_actions() { # prefix handler param
+ for __hdr in `xbc_subkeys ${1}.${2} 1 ".[0-9]"`; do
+ print_hist_one_action ${1}.${2}.$__hdr ${2} ${3}
+ done
+ if xbc_has_key ${1}.${2}.${3} ; then
+ print_hist_one_action ${1}.${2} ${2} ${3}
+ fi
+}
+
+print_hist_var() { # prefix varname
+ echo -n ":${2}="`xbc_get_val ${1}.var.${2} | tr -d [:space:]`
+}
+
+print_one_histogram() { # prefix
+ echo -n "hist"
+ print_hist_array $1 "keys"
+ print_hist_array $1 "values"
+ print_hist_array $1 "sort"
+ if xbc_has_key "${1}.size"; then
+ echo -n ":size="`xbc_get_val ${1}.size`
+ fi
+ if xbc_has_key "${1}.name"; then
+ echo -n ":name="`xbc_get_val ${1}.name`
+ fi
+ for __var in `xbc_subkeys "${1}.var" 1`; do
+ print_hist_var ${1} ${__var}
+ done
+ if xbc_has_key "${1}.pause"; then
+ echo -n ":pause"
+ elif xbc_has_key "${1}.continue"; then
+ echo -n ":continue"
+ elif xbc_has_key "${1}.clear"; then
+ echo -n ":clear"
+ fi
+ print_hist_actions ${1} "onmax" "var"
+ print_hist_actions ${1} "onchange" "var"
+ print_hist_actions ${1} "onmatch" "event"
+
+ if xbc_has_key "${1}.filter"; then
+ echo -n " if "`xbc_get_val ${1}.filter`
+ fi
+}
+
+setup_one_histogram() { # prefix trigger-file
+ run_cmd "echo '`print_one_histogram ${1}`' >> ${2}"
+}
+
+setup_histograms() { # prefix trigger-file
+ for __hist in `xbc_subkeys ${1} 1 ".[0-9]"`; do
+ setup_one_histogram ${1}.$__hist ${2}
+ done
+ if xbc_has_key ${1}.keys; then
+ setup_one_histogram ${1} ${2}
+ fi
+}
+
setup_event() { # prefix group event [instance]
branch=$1.$2.$3
if [ "$4" ]; then
@@ -101,6 +187,12 @@ setup_event() { # prefix group event [instance]
else
eventdir="$TRACEFS/events/$2/$3"
fi
+ # group enable
+ if [ "$3" = "enable" ]; then
+ run_cmd "echo 1 > ${eventdir}"
+ return
+ fi
+
case $2 in
kprobes)
xbc_get_val ${branch}.probes | while read line; do
@@ -115,6 +207,8 @@ setup_event() { # prefix group event [instance]
set_value_of ${branch}.filter ${eventdir}/filter
set_array_of ${branch}.actions ${eventdir}/trigger
+ setup_histograms ${branch}.hist ${eventdir}/trigger
+
if xbc_has_key ${branch}.enable; then
run_cmd "echo 1 > ${eventdir}/enable"
fi
@@ -127,6 +221,13 @@ setup_events() { # prefix("ftrace" or "ftrace.instance.INSTANCE") [instance]
setup_event $prefix ${grpev%.*} ${grpev#*.} $2
done
fi
+ if xbc_has_branch ${1}.event.enable; then
+ if [ "$2" ]; then
+ run_cmd "echo 1 > $TRACEFS/instances/$2/events/enable"
+ else
+ run_cmd "echo 1 > $TRACEFS/events/enable"
+ fi
+ fi
}
size2kb() { # size[KB|MB]
diff --git a/tools/bootconfig/scripts/ftrace2bconf.sh b/tools/bootconfig/scripts/ftrace2bconf.sh
index a0c3bcc6da4f..fbaf07dc91bf 100755
--- a/tools/bootconfig/scripts/ftrace2bconf.sh
+++ b/tools/bootconfig/scripts/ftrace2bconf.sh
@@ -92,6 +92,10 @@ referred_vars() {
grep "^hist" $1/trigger | grep -o '$[a-zA-Z0-9]*'
}
+event_is_enabled() { # enable-file
+ test -f $1 & grep -q "1" $1
+}
+
per_event_options() { # event-dir
evdir=$1
# Check the special event which has no filter and no trigger
@@ -113,7 +117,9 @@ per_event_options() { # event-dir
emit_kv $PREFIX.event.$group.$event.actions += \'$action\'
done
- # enable is not checked; this is done by set_event in the instance.
+ if [ $GROUP_ENABLED -eq 0 ] && event_is_enabled $evdir/enable; then
+ emit_kv $PREFIX.event.$group.$event.enable
+ fi
val=`cat $evdir/filter`
if [ "$val" != "none" ]; then
emit_kv $PREFIX.event.$group.$event.filter = "$val"
@@ -137,8 +143,19 @@ event_options() {
kprobe_event_options
synth_event_options
fi
+ ALL_ENABLED=0
+ if event_is_enabled $INSTANCE/events/enable; then
+ emit_kv $PREFIX.event.enable
+ ALL_ENABLED=1
+ fi
for group in `ls $INSTANCE/events/` ; do
[ ! -d $INSTANCE/events/$group ] && continue
+ GROUP_ENABLED=$ALL_ENABLED
+ if [ $ALL_ENABLED -eq 0 ] && \
+ event_is_enabled $INSTANCE/events/$group/enable ;then
+ emit_kv $PREFIX.event.$group.enable
+ GROUP_ENABLED=1
+ fi
for event in `ls $INSTANCE/events/$group/` ;do
[ ! -d $INSTANCE/events/$group/$event ] && continue
per_event_options $INSTANCE/events/$group/$event
@@ -226,11 +243,6 @@ instance_options() { # [instance-name]
emit_kv $PREFIX.tracing_on = $val
fi
- val=
- for i in `cat $INSTANCE/set_event`; do
- val="$val, $i"
- done
- [ "$val" ] && emit_kv $PREFIX.events = "${val#,}"
val=`cat $INSTANCE/current_tracer`
[ $val != nop ] && emit_kv $PREFIX.tracer = $val
if grep -qv "^#" $INSTANCE/set_ftrace_filter $INSTANCE/set_ftrace_notrace; then
diff --git a/tools/bootconfig/scripts/xbc.sh b/tools/bootconfig/scripts/xbc.sh
index b8c84e654556..1f0ebf50dd2d 100644
--- a/tools/bootconfig/scripts/xbc.sh
+++ b/tools/bootconfig/scripts/xbc.sh
@@ -49,8 +49,8 @@ xbc_has_branch() { # prefix-key
grep -q "^$1" $XBC_TMPFILE
}
-xbc_subkeys() { # prefix-key depth
+xbc_subkeys() { # prefix-key depth [subkey-pattern]
__keys=`echo $1 | sed "s/\./ /g"`
__s=`nr_args $__keys`
- grep "^$1" $XBC_TMPFILE | cut -d= -f1| cut -d. -f$((__s + 1))-$((__s + $2)) | uniq
+ grep "^$1$3" $XBC_TMPFILE | cut -d= -f1| cut -d. -f$((__s + 1))-$((__s + $2)) | uniq
}
diff --git a/tools/build/Makefile b/tools/build/Makefile
index 5ed41b96fcde..6f11e6fc9ffe 100644
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -32,7 +32,7 @@ all: $(OUTPUT)fixdep
# Make sure there's anything to clean,
# feature contains check for existing OUTPUT
-TMP_O := $(if $(OUTPUT),$(OUTPUT)/feature,./)
+TMP_O := $(if $(OUTPUT),$(OUTPUT)feature/,./)
clean:
$(call QUIET_CLEAN, fixdep)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 04a8e3db8a54..3dd2f68366f9 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -34,7 +34,6 @@ FEATURE_TESTS_BASIC := \
dwarf_getlocations \
eventfd \
fortify-source \
- sync-compare-and-swap \
get_current_dir_name \
gettid \
glibc \
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index ec203e28407f..eff55d287db1 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -9,7 +9,6 @@ FILES= \
test-dwarf_getlocations.bin \
test-eventfd.bin \
test-fortify-source.bin \
- test-sync-compare-and-swap.bin \
test-get_current_dir_name.bin \
test-glibc.bin \
test-gtk2.bin \
@@ -260,9 +259,6 @@ $(OUTPUT)test-libdw-dwarf-unwind.bin:
$(OUTPUT)test-libbabeltrace.bin:
$(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
-$(OUTPUT)test-sync-compare-and-swap.bin:
- $(BUILD)
-
$(OUTPUT)test-compile-32.bin:
$(CC) -m32 -o $@ test-compile.c
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index 464873883396..920439527291 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -106,10 +106,6 @@
# include "test-libdw-dwarf-unwind.c"
#undef main
-#define main main_test_sync_compare_and_swap
-# include "test-sync-compare-and-swap.c"
-#undef main
-
#define main main_test_zlib
# include "test-zlib.c"
#undef main
diff --git a/tools/build/feature/test-libopencsd.c b/tools/build/feature/test-libopencsd.c
index 52c790b0317b..eb6303ff446e 100644
--- a/tools/build/feature/test-libopencsd.c
+++ b/tools/build/feature/test-libopencsd.c
@@ -4,9 +4,9 @@
/*
* Check OpenCSD library version is sufficient to provide required features
*/
-#define OCSD_MIN_VER ((1 << 16) | (0 << 8) | (0))
+#define OCSD_MIN_VER ((1 << 16) | (1 << 8) | (1))
#if !defined(OCSD_VER_NUM) || (OCSD_VER_NUM < OCSD_MIN_VER)
-#error "OpenCSD >= 1.0.0 is required"
+#error "OpenCSD >= 1.1.1 is required"
#endif
int main(void)
diff --git a/tools/build/feature/test-sync-compare-and-swap.c b/tools/build/feature/test-sync-compare-and-swap.c
deleted file mode 100644
index 3bc6b0768a53..000000000000
--- a/tools/build/feature/test-sync-compare-and-swap.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <stdint.h>
-
-volatile uint64_t x;
-
-int main(int argc, char *argv[])
-{
- uint64_t old, new = argc;
-
- (void)argv;
- do {
- old = __sync_val_compare_and_swap(&x, 0, 0);
- } while (!__sync_bool_compare_and_swap(&x, old, new));
- return old == new;
-}
diff --git a/tools/include/linux/compiler_types.h b/tools/include/linux/compiler_types.h
index feea09029f61..24ae3054f304 100644
--- a/tools/include/linux/compiler_types.h
+++ b/tools/include/linux/compiler_types.h
@@ -13,6 +13,24 @@
#define __has_builtin(x) (0)
#endif
+#ifdef __CHECKER__
+/* context/locking */
+# define __must_hold(x) __attribute__((context(x,1,1)))
+# define __acquires(x) __attribute__((context(x,0,1)))
+# define __releases(x) __attribute__((context(x,1,0)))
+# define __acquire(x) __context__(x,1)
+# define __release(x) __context__(x,-1)
+# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
+#else /* __CHECKER__ */
+/* context/locking */
+# define __must_hold(x)
+# define __acquires(x)
+# define __releases(x)
+# define __acquire(x) (void)0
+# define __release(x) (void)0
+# define __cond_lock(x,c) (c)
+#endif /* __CHECKER__ */
+
/* Compiler specific macros. */
#ifdef __GNUC__
#include <linux/compiler-gcc.h>
diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c
index ca0215047c32..6d8e521c59e1 100644
--- a/tools/lib/perf/cpumap.c
+++ b/tools/lib/perf/cpumap.c
@@ -68,6 +68,11 @@ static struct perf_cpu_map *cpu_map__default_new(void)
return cpus;
}
+struct perf_cpu_map *perf_cpu_map__default_new(void)
+{
+ return cpu_map__default_new();
+}
+
static int cmp_int(const void *a, const void *b)
{
return *(const int *)a - *(const int*)b;
@@ -277,14 +282,8 @@ int perf_cpu_map__idx(struct perf_cpu_map *cpus, int cpu)
int perf_cpu_map__max(struct perf_cpu_map *map)
{
- int i, max = -1;
-
- for (i = 0; i < map->nr; i++) {
- if (map->map[i] > max)
- max = map->map[i];
- }
-
- return max;
+ // cpu_map__trim_new() qsort()s it, cpu_map__default_new() sorts it as well.
+ return map->nr > 0 ? map->map[map->nr - 1] : -1;
}
/*
diff --git a/tools/lib/perf/include/internal/tests.h b/tools/lib/perf/include/internal/tests.h
index 61052099225b..b130a6663ff8 100644
--- a/tools/lib/perf/include/internal/tests.h
+++ b/tools/lib/perf/include/internal/tests.h
@@ -23,6 +23,8 @@ static inline int get_verbose(char **argv, int argc)
break;
}
}
+ optind = 1;
+
return verbose;
}
diff --git a/tools/lib/perf/include/perf/cpumap.h b/tools/lib/perf/include/perf/cpumap.h
index 6a17ad730cbc..7c27766ea0bf 100644
--- a/tools/lib/perf/include/perf/cpumap.h
+++ b/tools/lib/perf/include/perf/cpumap.h
@@ -9,6 +9,7 @@
struct perf_cpu_map;
LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void);
+LIBPERF_API struct perf_cpu_map *perf_cpu_map__default_new(void);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index d2414144eb8c..41b9b942504d 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -133,6 +133,7 @@ struct option {
#define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
+#define OPT_UINTEGER_OPTARG(s, l, v, d, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
#define OPT_ULONG(s, l, v, h) { .type = OPTION_ULONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned long *), .help = (h) }
#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
diff --git a/tools/memory-model/Documentation/access-marking.txt b/tools/memory-model/Documentation/access-marking.txt
index 1ab189f51f55..65778222183e 100644
--- a/tools/memory-model/Documentation/access-marking.txt
+++ b/tools/memory-model/Documentation/access-marking.txt
@@ -37,7 +37,9 @@ compiler's use of code-motion and common-subexpression optimizations.
Therefore, if a given access is involved in an intentional data race,
using READ_ONCE() for loads and WRITE_ONCE() for stores is usually
preferable to data_race(), which in turn is usually preferable to plain
-C-language accesses.
+C-language accesses. It is permissible to combine #2 and #3, for example,
+data_race(READ_ONCE(a)), which will both restrict compiler optimizations
+and disable KCSAN diagnostics.
KCSAN will complain about many types of data races involving plain
C-language accesses, but marking all accesses involved in a given data
@@ -86,6 +88,10 @@ that fail to exclude the updates. In this case, it is important to use
data_race() for the diagnostic reads because otherwise KCSAN would give
false-positive warnings about these diagnostic reads.
+If it is necessary to both restrict compiler optimizations and disable
+KCSAN diagnostics, use both data_race() and READ_ONCE(), for example,
+data_race(READ_ONCE(a)).
+
In theory, plain C-language loads can also be used for this use case.
However, in practice this will have the disadvantage of causing KCSAN
to generate false positives because KCSAN will have no way of knowing
@@ -126,6 +132,11 @@ consistent errors, which in turn are quite capable of breaking heuristics.
Therefore use of data_race() should be limited to cases where some other
code (such as a barrier() call) will force the occasional reload.
+Note that this use case requires that the heuristic be able to handle
+any possible error. In contrast, if the heuristics might be fatally
+confused by one or more of the possible erroneous values, use READ_ONCE()
+instead of data_race().
+
In theory, plain C-language loads can also be used for this use case.
However, in practice this will have the disadvantage of causing KCSAN
to generate false positives because KCSAN will have no way of knowing
@@ -259,9 +270,9 @@ diagnostic purposes. The code might look as follows:
return ret;
}
- int read_foo_diagnostic(void)
+ void read_foo_diagnostic(void)
{
- return data_race(foo);
+ pr_info("Current value of foo: %d\n", data_race(foo));
}
The reader-writer lock prevents the compiler from introducing concurrency
@@ -274,19 +285,34 @@ tells KCSAN that data races are expected, and should be silently
ignored. This data_race() also tells the human reading the code that
read_foo_diagnostic() might sometimes return a bogus value.
-However, please note that your kernel must be built with
-CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC=n in order for KCSAN to
-detect a buggy lockless write. If you need KCSAN to detect such a
-write even if that write did not change the value of foo, you also
-need CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY=n. If you need KCSAN to
-detect such a write happening in an interrupt handler running on the
-same CPU doing the legitimate lock-protected write, you also need
-CONFIG_KCSAN_INTERRUPT_WATCHER=y. With some or all of these Kconfig
-options set properly, KCSAN can be quite helpful, although it is not
-necessarily a full replacement for hardware watchpoints. On the other
-hand, neither are hardware watchpoints a full replacement for KCSAN
-because it is not always easy to tell hardware watchpoint to conditionally
-trap on accesses.
+If it is necessary to suppress compiler optimization and also detect
+buggy lockless writes, read_foo_diagnostic() can be updated as follows:
+
+ void read_foo_diagnostic(void)
+ {
+ pr_info("Current value of foo: %d\n", data_race(READ_ONCE(foo)));
+ }
+
+Alternatively, given that KCSAN is to ignore all accesses in this function,
+this function can be marked __no_kcsan and the data_race() can be dropped:
+
+ void __no_kcsan read_foo_diagnostic(void)
+ {
+ pr_info("Current value of foo: %d\n", READ_ONCE(foo));
+ }
+
+However, in order for KCSAN to detect buggy lockless writes, your kernel
+must be built with CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC=n. If you
+need KCSAN to detect such a write even if that write did not change
+the value of foo, you also need CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY=n.
+If you need KCSAN to detect such a write happening in an interrupt handler
+running on the same CPU doing the legitimate lock-protected write, you
+also need CONFIG_KCSAN_INTERRUPT_WATCHER=y. With some or all of these
+Kconfig options set properly, KCSAN can be quite helpful, although
+it is not necessarily a full replacement for hardware watchpoints.
+On the other hand, neither are hardware watchpoints a full replacement
+for KCSAN because it is not always easy to tell hardware watchpoint to
+conditionally trap on accesses.
Lock-Protected Writes With Lockless Reads
@@ -319,6 +345,99 @@ of the ASSERT_EXCLUSIVE_WRITER() is to allow KCSAN to check for a buggy
concurrent lockless write.
+Lock-Protected Writes With Heuristic Lockless Reads
+---------------------------------------------------
+
+For another example, suppose that the code can normally make use of
+a per-data-structure lock, but there are times when a global lock
+is required. These times are indicated via a global flag. The code
+might look as follows, and is based loosely on nf_conntrack_lock(),
+nf_conntrack_all_lock(), and nf_conntrack_all_unlock():
+
+ bool global_flag;
+ DEFINE_SPINLOCK(global_lock);
+ struct foo {
+ spinlock_t f_lock;
+ int f_data;
+ };
+
+ /* All foo structures are in the following array. */
+ int nfoo;
+ struct foo *foo_array;
+
+ void do_something_locked(struct foo *fp)
+ {
+ /* This works even if data_race() returns nonsense. */
+ if (!data_race(global_flag)) {
+ spin_lock(&fp->f_lock);
+ if (!smp_load_acquire(&global_flag)) {
+ do_something(fp);
+ spin_unlock(&fp->f_lock);
+ return;
+ }
+ spin_unlock(&fp->f_lock);
+ }
+ spin_lock(&global_lock);
+ /* global_lock held, thus global flag cannot be set. */
+ spin_lock(&fp->f_lock);
+ spin_unlock(&global_lock);
+ /*
+ * global_flag might be set here, but begin_global()
+ * will wait for ->f_lock to be released.
+ */
+ do_something(fp);
+ spin_unlock(&fp->f_lock);
+ }
+
+ void begin_global(void)
+ {
+ int i;
+
+ spin_lock(&global_lock);
+ WRITE_ONCE(global_flag, true);
+ for (i = 0; i < nfoo; i++) {
+ /*
+ * Wait for pre-existing local locks. One at
+ * a time to avoid lockdep limitations.
+ */
+ spin_lock(&fp->f_lock);
+ spin_unlock(&fp->f_lock);
+ }
+ }
+
+ void end_global(void)
+ {
+ smp_store_release(&global_flag, false);
+ spin_unlock(&global_lock);
+ }
+
+All code paths leading from the do_something_locked() function's first
+read from global_flag acquire a lock, so endless load fusing cannot
+happen.
+
+If the value read from global_flag is true, then global_flag is
+rechecked while holding ->f_lock, which, if global_flag is now false,
+prevents begin_global() from completing. It is therefore safe to invoke
+do_something().
+
+Otherwise, if either value read from global_flag is true, then after
+global_lock is acquired global_flag must be false. The acquisition of
+->f_lock will prevent any call to begin_global() from returning, which
+means that it is safe to release global_lock and invoke do_something().
+
+For this to work, only those foo structures in foo_array[] may be passed
+to do_something_locked(). The reason for this is that the synchronization
+with begin_global() relies on momentarily holding the lock of each and
+every foo structure.
+
+The smp_load_acquire() and smp_store_release() are required because
+changes to a foo structure between calls to begin_global() and
+end_global() are carried out without holding that structure's ->f_lock.
+The smp_load_acquire() and smp_store_release() ensure that the next
+invocation of do_something() from do_something_locked() will see those
+changes.
+
+
Lockless Reads and Writes
-------------------------
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 6e54979c2124..6e7b88917ca0 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -2,6 +2,10 @@
include ../../scripts/Makefile.include
include ../../scripts/utilities.mak
+ARTICLES =
+# with their own formatting rules.
+SP_ARTICLES =
+
MAN1_TXT= \
$(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \
$(wildcard perf-*.txt)) \
@@ -16,13 +20,6 @@ _MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT))
MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML))
MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML))
-ARTICLES =
-# with their own formatting rules.
-SP_ARTICLES =
-API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
-SP_ARTICLES += $(API_DOCS)
-SP_ARTICLES += technical/api-index
-
_DOC_HTML = $(_MAN_HTML)
_DOC_HTML+=$(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES))
DOC_HTML=$(addprefix $(OUTPUT),$(_DOC_HTML))
@@ -173,7 +170,7 @@ ifneq ($(V),1)
endif
endif
-all: html man
+all: html man info
html: $(DOC_HTML)
@@ -186,8 +183,6 @@ man7: $(DOC_MAN7)
info: $(OUTPUT)perf.info $(OUTPUT)perfman.info
-pdf: $(OUTPUT)user-manual.pdf
-
install: install-man
check-man-tools:
@@ -225,11 +220,6 @@ install-info: info
echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \
fi
-install-pdf: pdf
- $(call QUIET_INSTALL, Documentation-pdf) \
- $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir); \
- $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir)
-
#install-html: html
# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
@@ -244,33 +234,13 @@ $(OUTPUT)doc.dep : $(wildcard *.txt) build-docdep.perl
-include $(OUTPUT)doc.dep
-_cmds_txt = cmds-ancillaryinterrogators.txt \
- cmds-ancillarymanipulators.txt \
- cmds-mainporcelain.txt \
- cmds-plumbinginterrogators.txt \
- cmds-plumbingmanipulators.txt \
- cmds-synchingrepositories.txt \
- cmds-synchelpers.txt \
- cmds-purehelpers.txt \
- cmds-foreignscminterface.txt
-cmds_txt=$(addprefix $(OUTPUT),$(_cmds_txt))
-
-$(cmds_txt): $(OUTPUT)cmd-list.made
-
-$(OUTPUT)cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
- $(QUIET_GEN)$(RM) $@ && \
- $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
- date >$@
-
CLEAN_FILES = \
$(MAN_XML) $(addsuffix +,$(MAN_XML)) \
$(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \
$(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7) \
$(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++ \
- $(OUTPUT)perf.info $(OUTPUT)perfman.info \
- $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep \
- $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt \
- $(cmds_txt) $(OUTPUT)*.made
+ $(OUTPUT)perf.info $(OUTPUT)perfman.info $(OUTPUT)doc.dep \
+ $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt
clean:
$(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES)
@@ -304,24 +274,6 @@ $(OUTPUT)%.xml : %.txt
XSLT = docbook.xsl
XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css
-$(OUTPUT)user-manual.html: $(OUTPUT)user-manual.xml
- $(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
-
-$(OUTPUT)perf.info: $(OUTPUT)user-manual.texi
- $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ $(OUTPUT)user-manual.texi
-
-$(OUTPUT)user-manual.texi: $(OUTPUT)user-manual.xml
- $(QUIET_DB2TEXI)$(RM) $@+ $@ && \
- $(DOCBOOK2X_TEXI) $(OUTPUT)user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \
- $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \
- rm $@++ && \
- mv $@+ $@
-
-$(OUTPUT)user-manual.pdf: $(OUTPUT)user-manual.xml
- $(QUIET_DBLATEX)$(RM) $@+ $@ && \
- $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \
- mv $@+ $@
-
$(OUTPUT)perfman.texi: $(MAN_XML) cat-texi.perl
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
@@ -331,28 +283,18 @@ $(OUTPUT)perfman.texi: $(MAN_XML) cat-texi.perl
mv $@+ $@
$(OUTPUT)perfman.info: $(OUTPUT)perfman.texi
- $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi
+ $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate -o $@ $*.texi
$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
$(QUIET_DB2TEXI)$(RM) $@+ $@ && \
$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \
mv $@+ $@
-howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
- $(QUIET_GEN)$(RM) $@+ $@ && \
- '$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \
- mv $@+ $@
-
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
$(QUIET_ASCIIDOC)$(ASCIIDOC) -b $(ASCIIDOC_HTML) $*.txt
WEBDOC_DEST = /pub/software/tools/perf/docs
-$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
- $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
- sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b $(ASCIIDOC_HTML) - >$@+ && \
- mv $@+ $@
-
# UNIMPLEMENTED
#install-webdoc : html
# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST)
diff --git a/tools/perf/Documentation/build-docdep.perl b/tools/perf/Documentation/build-docdep.perl
new file mode 100755
index 000000000000..ba4205e0302a
--- /dev/null
+++ b/tools/perf/Documentation/build-docdep.perl
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+
+my %include = ();
+my %included = ();
+
+for my $text (<*.txt>) {
+ open I, '<', $text || die "cannot read: $text";
+ while (<I>) {
+ if (/^include::/) {
+ chomp;
+ s/^include::\s*//;
+ s/\[\]//;
+ $include{$text}{$_} = 1;
+ $included{$_} = 1;
+ }
+ }
+ close I;
+}
+
+# Do we care about chained includes???
+my $changed = 1;
+while ($changed) {
+ $changed = 0;
+ while (my ($text, $included) = each %include) {
+ for my $i (keys %$included) {
+ # $text has include::$i; if $i includes $j
+ # $text indirectly includes $j.
+ if (exists $include{$i}) {
+ for my $j (keys %{$include{$i}}) {
+ if (!exists $include{$text}{$j}) {
+ $include{$text}{$j} = 1;
+ $included{$j} = 1;
+ $changed = 1;
+ }
+ }
+ }
+ }
+ }
+}
+
+while (my ($text, $included) = each %include) {
+ if (! exists $included{$text} &&
+ (my $base = $text) =~ s/\.txt$//) {
+ print "$base.html $base.xml : ", join(" ", keys %$included), "\n";
+ }
+}
diff --git a/tools/perf/Documentation/cat-texi.perl b/tools/perf/Documentation/cat-texi.perl
new file mode 100755
index 000000000000..14d2f8341517
--- /dev/null
+++ b/tools/perf/Documentation/cat-texi.perl
@@ -0,0 +1,46 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+
+my @menu = ();
+my $output = $ARGV[0];
+
+open my $tmp, '>', "$output.tmp";
+
+while (<STDIN>) {
+ next if (/^\\input texinfo/../\@node Top/);
+ next if (/^\@bye/ || /^\.ft/);
+ if (s/^\@top (.*)/\@node $1,,,Top/) {
+ push @menu, $1;
+ }
+ s/\(\@pxref\{\[(URLS|REMOTES)\]}\)//;
+ s/\@anchor\{[^{}]*\}//g;
+ print $tmp $_;
+}
+close $tmp;
+
+print '\input texinfo
+@setfilename gitman.info
+@documentencoding UTF-8
+@dircategory Development
+@direntry
+* Git Man Pages: (gitman). Manual pages for Git revision control system
+@end direntry
+@node Top,,, (dir)
+@top Git Manual Pages
+@documentlanguage en
+@menu
+';
+
+for (@menu) {
+ print "* ${_}::\n";
+}
+print "\@end menu\n";
+open $tmp, '<', "$output.tmp";
+while (<$tmp>) {
+ print;
+}
+close $tmp;
+print "\@bye\n";
+unlink "$output.tmp";
diff --git a/tools/perf/Documentation/intel-hybrid.txt b/tools/perf/Documentation/intel-hybrid.txt
index 07f0aa3bf682..c9302096dc46 100644
--- a/tools/perf/Documentation/intel-hybrid.txt
+++ b/tools/perf/Documentation/intel-hybrid.txt
@@ -140,7 +140,7 @@ displayed. The percentage is the event's running time/enabling time.
One example, 'triad_loop' runs on cpu16 (atom core), while we can see the
scaled value for core cycles is 160,444,092 and the percentage is 0.47%.
-perf stat -e cycles -- taskset -c 16 ./triad_loop
+perf stat -e cycles \-- taskset -c 16 ./triad_loop
As previous, two events are created.
diff --git a/tools/perf/Documentation/perf-c2c.txt b/tools/perf/Documentation/perf-c2c.txt
index c81d72e3eecf..de6beedb7283 100644
--- a/tools/perf/Documentation/perf-c2c.txt
+++ b/tools/perf/Documentation/perf-c2c.txt
@@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'perf c2c record' [<options>] <command>
-'perf c2c record' [<options>] -- [<record command options>] <command>
+'perf c2c record' [<options>] \-- [<record command options>] <command>
'perf c2c report' [<options>]
DESCRIPTION
diff --git a/tools/perf/Documentation/perf-dlfilter.txt b/tools/perf/Documentation/perf-dlfilter.txt
index 02842cb4cf90..594f5a5a0c9e 100644
--- a/tools/perf/Documentation/perf-dlfilter.txt
+++ b/tools/perf/Documentation/perf-dlfilter.txt
@@ -32,7 +32,7 @@ The API for filtering consists of the following:
----
#include <perf/perf_dlfilter.h>
-const struct perf_dlfilter_fns perf_dlfilter_fns;
+struct perf_dlfilter_fns perf_dlfilter_fns;
int start(void **data, void *ctx);
int stop(void *data, void *ctx);
@@ -214,7 +214,7 @@ Filter out everything except branches from "foo" to "bar":
#include <perf/perf_dlfilter.h>
#include <string.h>
-const struct perf_dlfilter_fns perf_dlfilter_fns;
+struct perf_dlfilter_fns perf_dlfilter_fns;
int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
{
@@ -246,6 +246,14 @@ To use the filter with perf script:
perf script --dlfilter dlfilter-example.so
+NOTES
+-----
+
+The dlfilter .so file will be dependent on shared libraries. If those change,
+it may be necessary to rebuild the .so. Also there may be unexpected results
+if the .so uses different versions of the shared libraries that perf uses.
+Versions can be checked using the ldd command.
+
SEE ALSO
--------
linkperf:perf-script[1]
diff --git a/tools/perf/Documentation/perf-iostat.txt b/tools/perf/Documentation/perf-iostat.txt
index 165176944031..04d510364384 100644
--- a/tools/perf/Documentation/perf-iostat.txt
+++ b/tools/perf/Documentation/perf-iostat.txt
@@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'perf iostat' list
-'perf iostat' <ports> -- <command> [<options>]
+'perf iostat' <ports> \-- <command> [<options>]
DESCRIPTION
-----------
@@ -85,4 +85,4 @@ EXAMPLES
SEE ALSO
--------
-linkperf:perf-stat[1] \ No newline at end of file
+linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index d71bac847936..f1079ee7f2ec 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'perf record' [-e <EVENT> | --event=EVENT] [-a] <command>
-'perf record' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
+'perf record' [-e <EVENT> | --event=EVENT] [-a] \-- <command> [<options>]
DESCRIPTION
-----------
diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 5e43cfa5ea1e..0250dc61cf98 100644
--- a/tools/perf/Documentation/perf-script-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -167,7 +167,7 @@ below).
Following those are the 'event handler' functions generated one for
every event in the 'perf record' output. The handler functions take
-the form subsystem__event_name, and contain named parameters, one for
+the form subsystem\__event_name, and contain named parameters, one for
each field in the event; in this case, there's only one event,
raw_syscalls__sys_enter(). (see the EVENT HANDLERS section below for
more info on event handlers).
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index aa3a0b2c29a2..c80515243560 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -106,7 +106,7 @@ OPTIONS
Pass 'arg' as an argument to the dlfilter. --dlarg may be repeated
to add more arguments.
---list-dlfilters=::
+--list-dlfilters::
Display a list of available dlfilters. Use with option -v (must come
before option --list-dlfilters) to show long descriptions.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 45c2467e4eb2..4c9310be6acc 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -9,8 +9,8 @@ SYNOPSIS
--------
[verse]
'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
-'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
-'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] -- <command> [<options>]
+'perf stat' [-e <EVENT> | --event=EVENT] [-a] \-- <command> [<options>]
+'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] \-- <command> [<options>]
'perf stat' report [-i file]
DESCRIPTION
@@ -217,8 +217,8 @@ Append to the output file designated with the -o option. Ignored if -o is not sp
Log output to fd, instead of stderr. Complementary to --output, and mutually exclusive
with it. --append may be used here. Examples:
- 3>results perf stat --log-fd 3 -- $cmd
- 3>>results perf stat --log-fd 3 --append -- $cmd
+ 3>results perf stat --log-fd 3 \-- $cmd
+ 3>>results perf stat --log-fd 3 --append \-- $cmd
--control=fifo:ctl-fifo[,ack-fifo]::
--control=fd:ctl-fd[,ack-fd]::
@@ -245,7 +245,7 @@ disable events during measurements:
perf stat -D -1 -e cpu-cycles -a -I 1000 \
--control fd:${ctl_fd},${ctl_fd_ack} \
- -- sleep 30 &
+ \-- sleep 30 &
perf_pid=$!
sleep 5 && echo 'enable' >&${ctl_fd} && read -u ${ctl_fd_ack} e1 && echo "enabled(${e1})"
@@ -265,7 +265,7 @@ disable events during measurements:
--post::
Pre and post measurement hooks, e.g.:
-perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- make -s -j64 O=defconfig-build/ bzImage
+perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' \-- make -s -j64 O=defconfig-build/ bzImage
-I msecs::
--interval-print msecs::
@@ -496,7 +496,7 @@ $ perf config stat.no-csv-summary=true
EXAMPLES
--------
-$ perf stat -- make
+$ perf stat \-- make
Performance counter stats for 'make':
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index eb8e487ef90b..b66cf128cbc7 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -133,10 +133,10 @@ FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS)
FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS)
-FEATURE_CHECK_LDFLAGS-libunwind-arm = -lunwind -lunwind-arm
-FEATURE_CHECK_LDFLAGS-libunwind-aarch64 = -lunwind -lunwind-aarch64
-FEATURE_CHECK_LDFLAGS-libunwind-x86 = -lunwind -llzma -lunwind-x86
-FEATURE_CHECK_LDFLAGS-libunwind-x86_64 = -lunwind -llzma -lunwind-x86_64
+FEATURE_CHECK_LDFLAGS-libunwind-arm += -lunwind -lunwind-arm
+FEATURE_CHECK_LDFLAGS-libunwind-aarch64 += -lunwind -lunwind-aarch64
+FEATURE_CHECK_LDFLAGS-libunwind-x86 += -lunwind -llzma -lunwind-x86
+FEATURE_CHECK_LDFLAGS-libunwind-x86_64 += -lunwind -llzma -lunwind-x86_64
FEATURE_CHECK_LDFLAGS-libcrypto = -lcrypto
@@ -349,10 +349,6 @@ CXXFLAGS += $(INC_FLAGS)
LIBPERF_CFLAGS := $(CORE_CFLAGS) $(EXTRA_CFLAGS)
-ifeq ($(feature-sync-compare-and-swap), 1)
- CFLAGS += -DHAVE_SYNC_COMPARE_AND_SWAP_SUPPORT
-endif
-
ifeq ($(feature-pthread-attr-setaffinity-np), 1)
CFLAGS += -DHAVE_PTHREAD_ATTR_SETAFFINITY_NP
endif
@@ -493,6 +489,8 @@ ifdef CORESIGHT
CFLAGS += -DCS_RAW_PACKED
endif
endif
+ else
+ dummy := $(error Error: No libopencsd library found or the version is not up-to-date. Please install recent libopencsd to build with CORESIGHT=1)
endif
endif
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 77e7f18c0bd0..e04313c4d840 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -360,8 +360,11 @@ ifndef NO_JVMTI
PROGRAMS += $(OUTPUT)$(LIBJVMTI)
endif
+DLFILTERS := dlfilter-test-api-v0.so
+DLFILTERS := $(patsubst %,$(OUTPUT)dlfilters/%,$(DLFILTERS))
+
# what 'all' will build and 'install' will install, in perfexecdir
-ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
+ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) $(DLFILTERS)
# what 'all' will build but not install in perfexecdir
OTHER_PROGRAMS = $(OUTPUT)perf
@@ -780,6 +783,13 @@ $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-map.c
$(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
endif
+$(OUTPUT)dlfilters/%.o: dlfilters/%.c include/perf/perf_dlfilter.h
+ $(Q)$(MKDIR) -p $(OUTPUT)dlfilters
+ $(QUIET_CC)$(CC) -c -Iinclude $(EXTRA_CFLAGS) -o $@ -fpic $<
+
+$(OUTPUT)dlfilters/%.so: $(OUTPUT)dlfilters/%.o
+ $(QUIET_LINK)$(CC) $(EXTRA_CFLAGS) -shared -o $@ $<
+
ifndef NO_JVMTI
LIBJVMTI_IN := $(OUTPUT)jvmti/jvmti-in.o
@@ -925,7 +935,7 @@ install-tools: all install-gtk
$(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
$(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'; \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(includedir_SQ)/perf'; \
- $(INSTALL) util/perf_dlfilter.h -t '$(DESTDIR_SQ)$(includedir_SQ)/perf'
+ $(INSTALL) -m 644 include/perf/perf_dlfilter.h -t '$(DESTDIR_SQ)$(includedir_SQ)/perf'
ifndef NO_PERF_READ_VDSO32
$(call QUIET_INSTALL, perf-read-vdso32) \
$(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(bindir_SQ)';
@@ -978,6 +988,9 @@ ifndef NO_LIBPYTHON
$(INSTALL) scripts/python/*.py -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
$(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
endif
+ $(call QUIET_INSTALL, dlfilters) \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/dlfilters'; \
+ $(INSTALL) $(DLFILTERS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/dlfilters';
$(call QUIET_INSTALL, perf_completion-script) \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
$(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
index b187bddbd01a..c7c7ec0812d5 100644
--- a/tools/perf/arch/arm/util/auxtrace.c
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -107,3 +107,35 @@ struct auxtrace_record
*err = 0;
return NULL;
}
+
+#if defined(__arm__)
+u64 compat_auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
+{
+ struct perf_event_mmap_page *pc = mm->userpg;
+ u64 result;
+
+ __asm__ __volatile__(
+" ldrd %0, %H0, [%1]"
+ : "=&r" (result)
+ : "r" (&pc->aux_head), "Qo" (pc->aux_head)
+ );
+
+ return result;
+}
+
+int compat_auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail)
+{
+ struct perf_event_mmap_page *pc = mm->userpg;
+
+ /* Ensure all reads are done before we write the tail out */
+ smp_mb();
+
+ __asm__ __volatile__(
+" strd %2, %H2, [%1]"
+ : "=Qo" (pc->aux_tail)
+ : "r" (&pc->aux_tail), "r" (tail)
+ );
+
+ return 0;
+}
+#endif
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index 85168d87b2d7..515aae470e23 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -47,15 +47,17 @@ static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
[CS_ETM_ETMIDR] = "mgmt/etmidr",
};
-static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
+static const char * const metadata_etmv4_ro[] = {
[CS_ETMV4_TRCIDR0] = "trcidr/trcidr0",
[CS_ETMV4_TRCIDR1] = "trcidr/trcidr1",
[CS_ETMV4_TRCIDR2] = "trcidr/trcidr2",
[CS_ETMV4_TRCIDR8] = "trcidr/trcidr8",
[CS_ETMV4_TRCAUTHSTATUS] = "mgmt/trcauthstatus",
+ [CS_ETE_TRCDEVARCH] = "mgmt/trcdevarch"
};
static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
+static bool cs_etm_is_ete(struct auxtrace_record *itr, int cpu);
static int cs_etm_set_context_id(struct auxtrace_record *itr,
struct evsel *evsel, int cpu)
@@ -73,7 +75,7 @@ static int cs_etm_set_context_id(struct auxtrace_record *itr,
if (!cs_etm_is_etmv4(itr, cpu))
goto out;
- /* Get a handle on TRCIRD2 */
+ /* Get a handle on TRCIDR2 */
snprintf(path, PATH_MAX, "cpu%d/%s",
cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
err = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
@@ -533,7 +535,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
struct evlist *evlist __maybe_unused)
{
int i;
- int etmv3 = 0, etmv4 = 0;
+ int etmv3 = 0, etmv4 = 0, ete = 0;
struct perf_cpu_map *event_cpus = evlist->core.cpus;
struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
@@ -544,7 +546,9 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
!cpu_map__has(online_cpus, i))
continue;
- if (cs_etm_is_etmv4(itr, i))
+ if (cs_etm_is_ete(itr, i))
+ ete++;
+ else if (cs_etm_is_etmv4(itr, i))
etmv4++;
else
etmv3++;
@@ -555,7 +559,9 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
if (!cpu_map__has(online_cpus, i))
continue;
- if (cs_etm_is_etmv4(itr, i))
+ if (cs_etm_is_ete(itr, i))
+ ete++;
+ else if (cs_etm_is_etmv4(itr, i))
etmv4++;
else
etmv3++;
@@ -565,6 +571,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
perf_cpu_map__put(online_cpus);
return (CS_ETM_HEADER_SIZE +
+ (ete * CS_ETE_PRIV_SIZE) +
(etmv4 * CS_ETMV4_PRIV_SIZE) +
(etmv3 * CS_ETMV3_PRIV_SIZE));
}
@@ -607,6 +614,49 @@ static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu, const char *path)
return val;
}
+#define TRCDEVARCH_ARCHPART_SHIFT 0
+#define TRCDEVARCH_ARCHPART_MASK GENMASK(11, 0)
+#define TRCDEVARCH_ARCHPART(x) (((x) & TRCDEVARCH_ARCHPART_MASK) >> TRCDEVARCH_ARCHPART_SHIFT)
+
+#define TRCDEVARCH_ARCHVER_SHIFT 12
+#define TRCDEVARCH_ARCHVER_MASK GENMASK(15, 12)
+#define TRCDEVARCH_ARCHVER(x) (((x) & TRCDEVARCH_ARCHVER_MASK) >> TRCDEVARCH_ARCHVER_SHIFT)
+
+static bool cs_etm_is_ete(struct auxtrace_record *itr, int cpu)
+{
+ struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr);
+ struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+ int trcdevarch = cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETE_TRCDEVARCH]);
+
+ /*
+ * ETE if ARCHVER is 5 (ARCHVER is 4 for ETM) and ARCHPART is 0xA13.
+ * See ETM_DEVARCH_ETE_ARCH in coresight-etm4x.h
+ */
+ return TRCDEVARCH_ARCHVER(trcdevarch) == 5 && TRCDEVARCH_ARCHPART(trcdevarch) == 0xA13;
+}
+
+static void cs_etm_save_etmv4_header(__u64 data[], struct auxtrace_record *itr, int cpu)
+{
+ struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr);
+ struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+
+ /* Get trace configuration register */
+ data[CS_ETMV4_TRCCONFIGR] = cs_etmv4_get_config(itr);
+ /* Get traceID from the framework */
+ data[CS_ETMV4_TRCTRACEIDR] = coresight_get_trace_id(cpu);
+ /* Get read-only information from sysFS */
+ data[CS_ETMV4_TRCIDR0] = cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
+ data[CS_ETMV4_TRCIDR1] = cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCIDR1]);
+ data[CS_ETMV4_TRCIDR2] = cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
+ data[CS_ETMV4_TRCIDR8] = cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCIDR8]);
+ data[CS_ETMV4_TRCAUTHSTATUS] = cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCAUTHSTATUS]);
+}
+
static void cs_etm_get_metadata(int cpu, u32 *offset,
struct auxtrace_record *itr,
struct perf_record_auxtrace_info *info)
@@ -618,31 +668,20 @@ static void cs_etm_get_metadata(int cpu, u32 *offset,
struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
/* first see what kind of tracer this cpu is affined to */
- if (cs_etm_is_etmv4(itr, cpu)) {
- magic = __perf_cs_etmv4_magic;
- /* Get trace configuration register */
- info->priv[*offset + CS_ETMV4_TRCCONFIGR] =
- cs_etmv4_get_config(itr);
- /* Get traceID from the framework */
- info->priv[*offset + CS_ETMV4_TRCTRACEIDR] =
- coresight_get_trace_id(cpu);
- /* Get read-only information from sysFS */
- info->priv[*offset + CS_ETMV4_TRCIDR0] =
- cs_etm_get_ro(cs_etm_pmu, cpu,
- metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
- info->priv[*offset + CS_ETMV4_TRCIDR1] =
+ if (cs_etm_is_ete(itr, cpu)) {
+ magic = __perf_cs_ete_magic;
+ /* ETE uses the same registers as ETMv4 plus TRCDEVARCH */
+ cs_etm_save_etmv4_header(&info->priv[*offset], itr, cpu);
+ info->priv[*offset + CS_ETE_TRCDEVARCH] =
cs_etm_get_ro(cs_etm_pmu, cpu,
- metadata_etmv4_ro[CS_ETMV4_TRCIDR1]);
- info->priv[*offset + CS_ETMV4_TRCIDR2] =
- cs_etm_get_ro(cs_etm_pmu, cpu,
- metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
- info->priv[*offset + CS_ETMV4_TRCIDR8] =
- cs_etm_get_ro(cs_etm_pmu, cpu,
- metadata_etmv4_ro[CS_ETMV4_TRCIDR8]);
- info->priv[*offset + CS_ETMV4_TRCAUTHSTATUS] =
- cs_etm_get_ro(cs_etm_pmu, cpu,
- metadata_etmv4_ro
- [CS_ETMV4_TRCAUTHSTATUS]);
+ metadata_etmv4_ro[CS_ETE_TRCDEVARCH]);
+
+ /* How much space was used */
+ increment = CS_ETE_PRIV_MAX;
+ nr_trc_params = CS_ETE_PRIV_MAX - CS_ETM_COMMON_BLK_MAX_V1;
+ } else if (cs_etm_is_etmv4(itr, cpu)) {
+ magic = __perf_cs_etmv4_magic;
+ cs_etm_save_etmv4_header(&info->priv[*offset], itr, cpu);
/* How much space was used */
increment = CS_ETMV4_PRIV_MAX;
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
index aef2a290e71a..6f3953f2a0d5 100644
--- a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
@@ -176,7 +176,7 @@
131 nospu quotactl sys_quotactl
132 common getpgid sys_getpgid
133 common fchdir sys_fchdir
-134 common bdflush sys_bdflush
+134 common bdflush sys_ni_syscall
135 common sysfs sys_sysfs
136 32 personality sys_personality ppc64_personality
136 64 personality ppc64_personality
diff --git a/tools/perf/arch/s390/entry/syscalls/syscall.tbl b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
index 64d51ab5a8b4..8d619ec86dcc 100644
--- a/tools/perf/arch/s390/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
@@ -122,7 +122,7 @@
131 common quotactl sys_quotactl sys_quotactl
132 common getpgid sys_getpgid sys_getpgid
133 common fchdir sys_fchdir sys_fchdir
-134 common bdflush sys_bdflush sys_bdflush
+134 common bdflush - -
135 common sysfs sys_sysfs sys_sysfs
136 common personality sys_s390_personality sys_s390_personality
137 common afs_syscall - -
diff --git a/tools/perf/arch/x86/util/pmu.c b/tools/perf/arch/x86/util/pmu.c
index d48d608517fd..74d69db1ea99 100644
--- a/tools/perf/arch/x86/util/pmu.c
+++ b/tools/perf/arch/x86/util/pmu.c
@@ -1,12 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
#include <string.h>
-
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
#include <linux/stddef.h>
#include <linux/perf_event.h>
+#include <linux/zalloc.h>
+#include <api/fs/fs.h>
+#include <errno.h>
#include "../../../util/intel-pt.h"
#include "../../../util/intel-bts.h"
#include "../../../util/pmu.h"
+#include "../../../util/fncache.h"
+
+#define TEMPLATE_ALIAS "%s/bus/event_source/devices/%s/alias"
+
+struct pmu_alias {
+ char *name;
+ char *alias;
+ struct list_head list;
+};
+
+static LIST_HEAD(pmu_alias_name_list);
+static bool cached_list;
struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
{
@@ -18,3 +36,138 @@ struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu __mayb
#endif
return NULL;
}
+
+static void pmu_alias__delete(struct pmu_alias *pmu_alias)
+{
+ if (!pmu_alias)
+ return;
+
+ zfree(&pmu_alias->name);
+ zfree(&pmu_alias->alias);
+ free(pmu_alias);
+}
+
+static struct pmu_alias *pmu_alias__new(char *name, char *alias)
+{
+ struct pmu_alias *pmu_alias = zalloc(sizeof(*pmu_alias));
+
+ if (pmu_alias) {
+ pmu_alias->name = strdup(name);
+ if (!pmu_alias->name)
+ goto out_delete;
+
+ pmu_alias->alias = strdup(alias);
+ if (!pmu_alias->alias)
+ goto out_delete;
+ }
+ return pmu_alias;
+
+out_delete:
+ pmu_alias__delete(pmu_alias);
+ return NULL;
+}
+
+static int setup_pmu_alias_list(void)
+{
+ char path[PATH_MAX];
+ DIR *dir;
+ struct dirent *dent;
+ const char *sysfs = sysfs__mountpoint();
+ struct pmu_alias *pmu_alias;
+ char buf[MAX_PMU_NAME_LEN];
+ FILE *file;
+ int ret = -ENOMEM;
+
+ if (!sysfs)
+ return -1;
+
+ snprintf(path, PATH_MAX,
+ "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
+
+ dir = opendir(path);
+ if (!dir)
+ return -errno;
+
+ while ((dent = readdir(dir))) {
+ if (!strcmp(dent->d_name, ".") ||
+ !strcmp(dent->d_name, ".."))
+ continue;
+
+ snprintf(path, PATH_MAX,
+ TEMPLATE_ALIAS, sysfs, dent->d_name);
+
+ if (!file_available(path))
+ continue;
+
+ file = fopen(path, "r");
+ if (!file)
+ continue;
+
+ if (!fgets(buf, sizeof(buf), file)) {
+ fclose(file);
+ continue;
+ }
+
+ fclose(file);
+
+ /* Remove the last '\n' */
+ buf[strlen(buf) - 1] = 0;
+
+ pmu_alias = pmu_alias__new(dent->d_name, buf);
+ if (!pmu_alias)
+ goto close_dir;
+
+ list_add_tail(&pmu_alias->list, &pmu_alias_name_list);
+ }
+
+ ret = 0;
+
+close_dir:
+ closedir(dir);
+ return ret;
+}
+
+static char *__pmu_find_real_name(const char *name)
+{
+ struct pmu_alias *pmu_alias;
+
+ list_for_each_entry(pmu_alias, &pmu_alias_name_list, list) {
+ if (!strcmp(name, pmu_alias->alias))
+ return pmu_alias->name;
+ }
+
+ return (char *)name;
+}
+
+char *pmu_find_real_name(const char *name)
+{
+ if (cached_list)
+ return __pmu_find_real_name(name);
+
+ setup_pmu_alias_list();
+ cached_list = true;
+
+ return __pmu_find_real_name(name);
+}
+
+static char *__pmu_find_alias_name(const char *name)
+{
+ struct pmu_alias *pmu_alias;
+
+ list_for_each_entry(pmu_alias, &pmu_alias_name_list, list) {
+ if (!strcmp(name, pmu_alias->name))
+ return pmu_alias->alias;
+ }
+ return NULL;
+}
+
+char *pmu_find_alias_name(const char *name)
+{
+ if (cached_list)
+ return __pmu_find_alias_name(name);
+
+ setup_pmu_alias_list();
+ cached_list = true;
+
+ return __pmu_find_alias_name(name);
+}
diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build
index e43f46931b41..61d45fcb4057 100644
--- a/tools/perf/bench/Build
+++ b/tools/perf/bench/Build
@@ -13,6 +13,7 @@ perf-y += synthesize.o
perf-y += kallsyms-parse.o
perf-y += find-bit-bench.o
perf-y += inject-buildid.o
+perf-y += evlist-open-close.o
perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o
perf-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index eac36afab2b3..b3480bc33fe8 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -48,6 +48,7 @@ int bench_epoll_ctl(int argc, const char **argv);
int bench_synthesize(int argc, const char **argv);
int bench_kallsyms_parse(int argc, const char **argv);
int bench_inject_build_id(int argc, const char **argv);
+int bench_evlist_open_close(int argc, const char **argv);
#define BENCH_FORMAT_DEFAULT_STR "default"
#define BENCH_FORMAT_DEFAULT 0
diff --git a/tools/perf/bench/evlist-open-close.c b/tools/perf/bench/evlist-open-close.c
new file mode 100644
index 000000000000..83e9897c64a1
--- /dev/null
+++ b/tools/perf/bench/evlist-open-close.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "bench.h"
+#include "../util/debug.h"
+#include "../util/stat.h"
+#include "../util/evlist.h"
+#include "../util/evsel.h"
+#include "../util/strbuf.h"
+#include "../util/record.h"
+#include "../util/parse-events.h"
+#include "internal/threadmap.h"
+#include "internal/cpumap.h"
+#include <linux/perf_event.h>
+#include <linux/kernel.h>
+#include <linux/time64.h>
+#include <linux/string.h>
+#include <subcmd/parse-options.h>
+
+#define MMAP_FLUSH_DEFAULT 1
+
+static int iterations = 100;
+static int nr_events = 1;
+static const char *event_string = "dummy";
+
+static struct record_opts opts = {
+ .sample_time = true,
+ .mmap_pages = UINT_MAX,
+ .user_freq = UINT_MAX,
+ .user_interval = ULLONG_MAX,
+ .freq = 4000,
+ .target = {
+ .uses_mmap = true,
+ .default_per_cpu = true,
+ },
+ .mmap_flush = MMAP_FLUSH_DEFAULT,
+ .nr_threads_synthesize = 1,
+ .ctl_fd = -1,
+ .ctl_fd_ack = -1,
+};
+
+static const struct option options[] = {
+ OPT_STRING('e', "event", &event_string, "event", "event selector. use 'perf list' to list available events"),
+ OPT_INTEGER('n', "nr-events", &nr_events,
+ "number of dummy events to create (default 1). If used with -e, it clones those events n times (1 = no change)"),
+ OPT_INTEGER('i', "iterations", &iterations, "Number of iterations used to compute average (default=100)"),
+ OPT_BOOLEAN('a', "all-cpus", &opts.target.system_wide, "system-wide collection from all CPUs"),
+ OPT_STRING('C', "cpu", &opts.target.cpu_list, "cpu", "list of cpus where to open events"),
+ OPT_STRING('p', "pid", &opts.target.pid, "pid", "record events on existing process id"),
+ OPT_STRING('t', "tid", &opts.target.tid, "tid", "record events on existing thread id"),
+ OPT_STRING('u', "uid", &opts.target.uid_str, "user", "user to profile"),
+ OPT_BOOLEAN(0, "per-thread", &opts.target.per_thread, "use per-thread mmaps"),
+ OPT_END()
+};
+
+static const char *const bench_usage[] = {
+ "perf bench internals evlist-open-close <options>",
+ NULL
+};
+
+static int evlist__count_evsel_fds(struct evlist *evlist)
+{
+ struct evsel *evsel;
+ int cnt = 0;
+
+ evlist__for_each_entry(evlist, evsel)
+ cnt += evsel->core.threads->nr * evsel->core.cpus->nr;
+
+ return cnt;
+}
+
+static struct evlist *bench__create_evlist(char *evstr)
+{
+ struct parse_events_error err = { .idx = 0, };
+ struct evlist *evlist = evlist__new();
+ int ret;
+
+ if (!evlist) {
+ pr_err("Not enough memory to create evlist\n");
+ return NULL;
+ }
+
+ ret = parse_events(evlist, evstr, &err);
+ if (ret) {
+ parse_events_print_error(&err, evstr);
+ pr_err("Run 'perf list' for a list of valid events\n");
+ ret = 1;
+ goto out_delete_evlist;
+ }
+
+ ret = evlist__create_maps(evlist, &opts.target);
+ if (ret < 0) {
+ pr_err("Not enough memory to create thread/cpu maps\n");
+ goto out_delete_evlist;
+ }
+
+ evlist__config(evlist, &opts, NULL);
+
+ return evlist;
+
+out_delete_evlist:
+ evlist__delete(evlist);
+ return NULL;
+}
+
+static int bench__do_evlist_open_close(struct evlist *evlist)
+{
+ char sbuf[STRERR_BUFSIZE];
+ int err = evlist__open(evlist);
+
+ if (err < 0) {
+ pr_err("evlist__open: %s\n", str_error_r(errno, sbuf, sizeof(sbuf)));
+ return err;
+ }
+
+ err = evlist__mmap(evlist, opts.mmap_pages);
+ if (err < 0) {
+ pr_err("evlist__mmap: %s\n", str_error_r(errno, sbuf, sizeof(sbuf)));
+ return err;
+ }
+
+ evlist__enable(evlist);
+ evlist__disable(evlist);
+ evlist__munmap(evlist);
+ evlist__close(evlist);
+
+ return 0;
+}
+
+static int bench_evlist_open_close__run(char *evstr)
+{
+ // used to print statistics only
+ struct evlist *evlist = bench__create_evlist(evstr);
+ double time_average, time_stddev;
+ struct timeval start, end, diff;
+ struct stats time_stats;
+ u64 runtime_us;
+ int i, err;
+
+ if (!evlist)
+ return -ENOMEM;
+
+ init_stats(&time_stats);
+
+ printf(" Number of cpus:\t%d\n", evlist->core.cpus->nr);
+ printf(" Number of threads:\t%d\n", evlist->core.threads->nr);
+ printf(" Number of events:\t%d (%d fds)\n",
+ evlist->core.nr_entries, evlist__count_evsel_fds(evlist));
+ printf(" Number of iterations:\t%d\n", iterations);
+
+ evlist__delete(evlist);
+
+ for (i = 0; i < iterations; i++) {
+ pr_debug("Started iteration %d\n", i);
+ evlist = bench__create_evlist(evstr);
+ if (!evlist)
+ return -ENOMEM;
+
+ gettimeofday(&start, NULL);
+ err = bench__do_evlist_open_close(evlist);
+ if (err) {
+ evlist__delete(evlist);
+ return err;
+ }
+
+ gettimeofday(&end, NULL);
+ timersub(&end, &start, &diff);
+ runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
+ update_stats(&time_stats, runtime_us);
+
+ evlist__delete(evlist);
+ pr_debug("Iteration %d took:\t%" PRIu64 "us\n", i, runtime_us);
+ }
+
+ time_average = avg_stats(&time_stats);
+ time_stddev = stddev_stats(&time_stats);
+ printf(" Average open-close took: %.3f usec (+- %.3f usec)\n", time_average, time_stddev);
+
+ return 0;
+}
+
+static char *bench__repeat_event_string(const char *evstr, int n)
+{
+ char sbuf[STRERR_BUFSIZE];
+ struct strbuf buf;
+ int i, str_size = strlen(evstr),
+ final_size = str_size * n + n,
+ err = strbuf_init(&buf, final_size);
+
+ if (err) {
+ pr_err("strbuf_init: %s\n", str_error_r(err, sbuf, sizeof(sbuf)));
+ goto out_error;
+ }
+
+ for (i = 0; i < n; i++) {
+ err = strbuf_add(&buf, evstr, str_size);
+ if (err) {
+ pr_err("strbuf_add: %s\n", str_error_r(err, sbuf, sizeof(sbuf)));
+ goto out_error;
+ }
+
+ err = strbuf_addch(&buf, i == n-1 ? '\0' : ',');
+ if (err) {
+ pr_err("strbuf_addch: %s\n", str_error_r(err, sbuf, sizeof(sbuf)));
+ goto out_error;
+ }
+ }
+
+ return strbuf_detach(&buf, NULL);
+
+out_error:
+ strbuf_release(&buf);
+ return NULL;
+}
+
+
+int bench_evlist_open_close(int argc, const char **argv)
+{
+ char *evstr, errbuf[BUFSIZ];
+ int err;
+
+ argc = parse_options(argc, argv, options, bench_usage, 0);
+ if (argc) {
+ usage_with_options(bench_usage, options);
+ exit(EXIT_FAILURE);
+ }
+
+ err = target__validate(&opts.target);
+ if (err) {
+ target__strerror(&opts.target, err, errbuf, sizeof(errbuf));
+ pr_err("%s\n", errbuf);
+ goto out;
+ }
+
+ err = target__parse_uid(&opts.target);
+ if (err) {
+ target__strerror(&opts.target, err, errbuf, sizeof(errbuf));
+ pr_err("%s", errbuf);
+ goto out;
+ }
+
+ /* Enable ignoring missing threads when -u/-p option is defined. */
+ opts.ignore_missing_thread = opts.target.uid != UINT_MAX || opts.target.pid;
+
+ evstr = bench__repeat_event_string(event_string, nr_events);
+ if (!evstr) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = bench_evlist_open_close__run(evstr);
+
+ free(evstr);
+out:
+ return err;
+}
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index b65373ce5c4f..fcdea3e44937 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/zalloc.h>
#include <sys/time.h>
+#include <sys/mman.h>
#include <perf/cpumap.h>
#include "../util/stat.h"
@@ -29,11 +30,7 @@
#include <err.h>
-static unsigned int nthreads = 0;
-static unsigned int nsecs = 10;
-/* amount of futexes per thread */
-static unsigned int nfutexes = 1024;
-static bool fshared = false, done = false, silent = false;
+static bool done = false;
static int futex_flag = 0;
struct timeval bench__start, bench__end, bench__runtime;
@@ -49,12 +46,18 @@ struct worker {
unsigned long ops;
};
+static struct bench_futex_parameters params = {
+ .nfutexes = 1024,
+ .runtime = 10,
+};
+
static const struct option options[] = {
- OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
- OPT_UINTEGER('r', "runtime", &nsecs, "Specify runtime (in seconds)"),
- OPT_UINTEGER('f', "futexes", &nfutexes, "Specify amount of futexes per threads"),
- OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
- OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
+ OPT_UINTEGER('t', "threads", &params.nthreads, "Specify amount of threads"),
+ OPT_UINTEGER('r', "runtime", &params.runtime, "Specify runtime (in seconds)"),
+ OPT_UINTEGER('f', "futexes", &params.nfutexes, "Specify amount of futexes per threads"),
+ OPT_BOOLEAN( 's', "silent", &params.silent, "Silent mode: do not display data/details"),
+ OPT_BOOLEAN( 'S', "shared", &params.fshared, "Use shared futexes instead of private ones"),
+ OPT_BOOLEAN( 'm', "mlockall", &params.mlockall, "Lock all current and future memory"),
OPT_END()
};
@@ -78,7 +81,7 @@ static void *workerfn(void *arg)
pthread_mutex_unlock(&thread_lock);
do {
- for (i = 0; i < nfutexes; i++, ops++) {
+ for (i = 0; i < params.nfutexes; i++, ops++) {
/*
* We want the futex calls to fail in order to stress
* the hashing of uaddr and not measure other steps,
@@ -86,7 +89,7 @@ static void *workerfn(void *arg)
* the critical region protected by hb->lock.
*/
ret = futex_wait(&w->futex[i], 1234, NULL, futex_flag);
- if (!silent &&
+ if (!params.silent &&
(!ret || errno != EAGAIN || errno != EWOULDBLOCK))
warn("Non-expected futex return call");
}
@@ -112,7 +115,7 @@ static void print_summary(void)
double stddev = stddev_stats(&throughput_stats);
printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
- !silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
+ !params.silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
(int)bench__runtime.tv_sec);
}
@@ -141,30 +144,35 @@ int bench_futex_hash(int argc, const char **argv)
act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL);
- if (!nthreads) /* default to the number of CPUs */
- nthreads = cpu->nr;
+ if (params.mlockall) {
+ if (mlockall(MCL_CURRENT | MCL_FUTURE))
+ err(EXIT_FAILURE, "mlockall");
+ }
+
+ if (!params.nthreads) /* default to the number of CPUs */
+ params.nthreads = cpu->nr;
- worker = calloc(nthreads, sizeof(*worker));
+ worker = calloc(params.nthreads, sizeof(*worker));
if (!worker)
goto errmem;
- if (!fshared)
+ if (!params.fshared)
futex_flag = FUTEX_PRIVATE_FLAG;
printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n",
- getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs);
+ getpid(), params.nthreads, params.nfutexes, params.fshared ? "shared":"private", params.runtime);
init_stats(&throughput_stats);
pthread_mutex_init(&thread_lock, NULL);
pthread_cond_init(&thread_parent, NULL);
pthread_cond_init(&thread_worker, NULL);
- threads_starting = nthreads;
+ threads_starting = params.nthreads;
pthread_attr_init(&thread_attr);
gettimeofday(&bench__start, NULL);
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
worker[i].tid = i;
- worker[i].futex = calloc(nfutexes, sizeof(*worker[i].futex));
+ worker[i].futex = calloc(params.nfutexes, sizeof(*worker[i].futex));
if (!worker[i].futex)
goto errmem;
@@ -189,10 +197,10 @@ int bench_futex_hash(int argc, const char **argv)
pthread_cond_broadcast(&thread_worker);
pthread_mutex_unlock(&thread_lock);
- sleep(nsecs);
+ sleep(params.runtime);
toggle_done(0, NULL, NULL);
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
ret = pthread_join(worker[i].thread, NULL);
if (ret)
err(EXIT_FAILURE, "pthread_join");
@@ -203,18 +211,18 @@ int bench_futex_hash(int argc, const char **argv)
pthread_cond_destroy(&thread_worker);
pthread_mutex_destroy(&thread_lock);
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
unsigned long t = bench__runtime.tv_sec > 0 ?
worker[i].ops / bench__runtime.tv_sec : 0;
update_stats(&throughput_stats, t);
- if (!silent) {
- if (nfutexes == 1)
+ if (!params.silent) {
+ if (params.nfutexes == 1)
printf("[thread %2d] futex: %p [ %ld ops/sec ]\n",
worker[i].tid, &worker[i].futex[0], t);
else
printf("[thread %2d] futexes: %p ... %p [ %ld ops/sec ]\n",
worker[i].tid, &worker[i].futex[0],
- &worker[i].futex[nfutexes-1], t);
+ &worker[i].futex[params.nfutexes-1], t);
}
zfree(&worker[i].futex);
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 89c6d160379c..5d1fe9c35807 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -21,6 +21,7 @@
#include <err.h>
#include <stdlib.h>
#include <sys/time.h>
+#include <sys/mman.h>
struct worker {
int tid;
@@ -31,22 +32,24 @@ struct worker {
static u_int32_t global_futex = 0;
static struct worker *worker;
-static unsigned int nsecs = 10;
-static bool silent = false, multi = false;
-static bool done = false, fshared = false;
-static unsigned int nthreads = 0;
+static bool done = false;
static int futex_flag = 0;
static pthread_mutex_t thread_lock;
static unsigned int threads_starting;
static struct stats throughput_stats;
static pthread_cond_t thread_parent, thread_worker;
+static struct bench_futex_parameters params = {
+ .runtime = 10,
+};
+
static const struct option options[] = {
- OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
- OPT_UINTEGER('r', "runtime", &nsecs, "Specify runtime (in seconds)"),
- OPT_BOOLEAN( 'M', "multi", &multi, "Use multiple futexes"),
- OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
- OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
+ OPT_UINTEGER('t', "threads", &params.nthreads, "Specify amount of threads"),
+ OPT_UINTEGER('r', "runtime", &params.runtime, "Specify runtime (in seconds)"),
+ OPT_BOOLEAN( 'M', "multi", &params.multi, "Use multiple futexes"),
+ OPT_BOOLEAN( 's', "silent", &params.silent, "Silent mode: do not display data/details"),
+ OPT_BOOLEAN( 'S', "shared", &params.fshared, "Use shared futexes instead of private ones"),
+ OPT_BOOLEAN( 'm', "mlockall", &params.mlockall, "Lock all current and future memory"),
OPT_END()
};
@@ -61,7 +64,7 @@ static void print_summary(void)
double stddev = stddev_stats(&throughput_stats);
printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
- !silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
+ !params.silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
(int)bench__runtime.tv_sec);
}
@@ -93,7 +96,7 @@ static void *workerfn(void *arg)
ret = futex_lock_pi(w->futex, NULL, futex_flag);
if (ret) { /* handle lock acquisition */
- if (!silent)
+ if (!params.silent)
warn("thread %d: Could not lock pi-lock for %p (%d)",
w->tid, w->futex, ret);
if (done)
@@ -104,7 +107,7 @@ static void *workerfn(void *arg)
usleep(1);
ret = futex_unlock_pi(w->futex, futex_flag);
- if (ret && !silent)
+ if (ret && !params.silent)
warn("thread %d: Could not unlock pi-lock for %p (%d)",
w->tid, w->futex, ret);
ops++; /* account for thread's share of work */
@@ -120,12 +123,12 @@ static void create_threads(struct worker *w, pthread_attr_t thread_attr,
cpu_set_t cpuset;
unsigned int i;
- threads_starting = nthreads;
+ threads_starting = params.nthreads;
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
worker[i].tid = i;
- if (multi) {
+ if (params.multi) {
worker[i].futex = calloc(1, sizeof(u_int32_t));
if (!worker[i].futex)
err(EXIT_FAILURE, "calloc");
@@ -164,25 +167,30 @@ int bench_futex_lock_pi(int argc, const char **argv)
act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL);
- if (!nthreads)
- nthreads = cpu->nr;
+ if (params.mlockall) {
+ if (mlockall(MCL_CURRENT | MCL_FUTURE))
+ err(EXIT_FAILURE, "mlockall");
+ }
+
+ if (!params.nthreads)
+ params.nthreads = cpu->nr;
- worker = calloc(nthreads, sizeof(*worker));
+ worker = calloc(params.nthreads, sizeof(*worker));
if (!worker)
err(EXIT_FAILURE, "calloc");
- if (!fshared)
+ if (!params.fshared)
futex_flag = FUTEX_PRIVATE_FLAG;
printf("Run summary [PID %d]: %d threads doing pi lock/unlock pairing for %d secs.\n\n",
- getpid(), nthreads, nsecs);
+ getpid(), params.nthreads, params.runtime);
init_stats(&throughput_stats);
pthread_mutex_init(&thread_lock, NULL);
pthread_cond_init(&thread_parent, NULL);
pthread_cond_init(&thread_worker, NULL);
- threads_starting = nthreads;
+ threads_starting = params.nthreads;
pthread_attr_init(&thread_attr);
gettimeofday(&bench__start, NULL);
@@ -195,10 +203,10 @@ int bench_futex_lock_pi(int argc, const char **argv)
pthread_cond_broadcast(&thread_worker);
pthread_mutex_unlock(&thread_lock);
- sleep(nsecs);
+ sleep(params.runtime);
toggle_done(0, NULL, NULL);
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
ret = pthread_join(worker[i].thread, NULL);
if (ret)
err(EXIT_FAILURE, "pthread_join");
@@ -209,16 +217,16 @@ int bench_futex_lock_pi(int argc, const char **argv)
pthread_cond_destroy(&thread_worker);
pthread_mutex_destroy(&thread_lock);
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
unsigned long t = bench__runtime.tv_sec > 0 ?
worker[i].ops / bench__runtime.tv_sec : 0;
update_stats(&throughput_stats, t);
- if (!silent)
+ if (!params.silent)
printf("[thread %3d] futex: %p [ %ld ops/sec ]\n",
worker[i].tid, worker[i].futex, t);
- if (multi)
+ if (params.multi)
zfree(&worker[i].futex);
}
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 5fa23295ee5f..97fe31fd3a23 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -6,7 +6,8 @@
* on futex2, N at a time.
*
* This program is particularly useful to measure the latency of nthread
- * requeues without waking up any tasks -- thus mimicking a regular futex_wait.
+ * requeues without waking up any tasks (in the non-pi case) -- thus
+ * mimicking a regular futex_wait.
*/
/* For the CLR_() macros */
@@ -27,28 +28,35 @@
#include <err.h>
#include <stdlib.h>
#include <sys/time.h>
+#include <sys/mman.h>
static u_int32_t futex1 = 0, futex2 = 0;
-/*
- * How many tasks to requeue at a time.
- * Default to 1 in order to make the kernel work more.
- */
-static unsigned int nrequeue = 1;
-
static pthread_t *worker;
-static bool done = false, silent = false, fshared = false;
+static bool done = false;
static pthread_mutex_t thread_lock;
static pthread_cond_t thread_parent, thread_worker;
static struct stats requeuetime_stats, requeued_stats;
-static unsigned int threads_starting, nthreads = 0;
+static unsigned int threads_starting;
static int futex_flag = 0;
+static struct bench_futex_parameters params = {
+ /*
+ * How many tasks to requeue at a time.
+ * Default to 1 in order to make the kernel work more.
+ */
+ .nrequeue = 1,
+};
+
static const struct option options[] = {
- OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
- OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"),
- OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
- OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
+ OPT_UINTEGER('t', "threads", &params.nthreads, "Specify amount of threads"),
+ OPT_UINTEGER('q', "nrequeue", &params.nrequeue, "Specify amount of threads to requeue at once"),
+ OPT_BOOLEAN( 's', "silent", &params.silent, "Silent mode: do not display data/details"),
+ OPT_BOOLEAN( 'S', "shared", &params.fshared, "Use shared futexes instead of private ones"),
+ OPT_BOOLEAN( 'm', "mlockall", &params.mlockall, "Lock all current and future memory"),
+ OPT_BOOLEAN( 'B', "broadcast", &params.broadcast, "Requeue all threads at once"),
+ OPT_BOOLEAN( 'p', "pi", &params.pi, "Use PI-aware variants of FUTEX_CMP_REQUEUE"),
+
OPT_END()
};
@@ -65,13 +73,15 @@ static void print_summary(void)
printf("Requeued %d of %d threads in %.4f ms (+-%.2f%%)\n",
requeued_avg,
- nthreads,
+ params.nthreads,
requeuetime_avg / USEC_PER_MSEC,
rel_stddev_stats(requeuetime_stddev, requeuetime_avg));
}
static void *workerfn(void *arg __maybe_unused)
{
+ int ret;
+
pthread_mutex_lock(&thread_lock);
threads_starting--;
if (!threads_starting)
@@ -79,7 +89,34 @@ static void *workerfn(void *arg __maybe_unused)
pthread_cond_wait(&thread_worker, &thread_lock);
pthread_mutex_unlock(&thread_lock);
- futex_wait(&futex1, 0, NULL, futex_flag);
+ while (1) {
+ if (!params.pi) {
+ ret = futex_wait(&futex1, 0, NULL, futex_flag);
+ if (!ret)
+ break;
+
+ if (ret && errno != EAGAIN) {
+ if (!params.silent)
+ warnx("futex_wait");
+ break;
+ }
+ } else {
+ ret = futex_wait_requeue_pi(&futex1, 0, &futex2,
+ NULL, futex_flag);
+ if (!ret) {
+ /* got the lock at futex2 */
+ futex_unlock_pi(&futex2, futex_flag);
+ break;
+ }
+
+ if (ret && errno != EAGAIN) {
+ if (!params.silent)
+ warnx("futex_wait_requeue_pi");
+ break;
+ }
+ }
+ }
+
return NULL;
}
@@ -89,10 +126,10 @@ static void block_threads(pthread_t *w,
cpu_set_t cpuset;
unsigned int i;
- threads_starting = nthreads;
+ threads_starting = params.nthreads;
/* create and block all threads */
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
CPU_ZERO(&cpuset);
CPU_SET(cpu->map[i % cpu->nr], &cpuset);
@@ -132,22 +169,31 @@ int bench_futex_requeue(int argc, const char **argv)
act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL);
- if (!nthreads)
- nthreads = cpu->nr;
+ if (params.mlockall) {
+ if (mlockall(MCL_CURRENT | MCL_FUTURE))
+ err(EXIT_FAILURE, "mlockall");
+ }
+
+ if (!params.nthreads)
+ params.nthreads = cpu->nr;
- worker = calloc(nthreads, sizeof(*worker));
+ worker = calloc(params.nthreads, sizeof(*worker));
if (!worker)
err(EXIT_FAILURE, "calloc");
- if (!fshared)
+ if (!params.fshared)
futex_flag = FUTEX_PRIVATE_FLAG;
- if (nrequeue > nthreads)
- nrequeue = nthreads;
+ if (params.nrequeue > params.nthreads)
+ params.nrequeue = params.nthreads;
- printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
- "%d at a time.\n\n", getpid(), nthreads,
- fshared ? "shared":"private", &futex1, &futex2, nrequeue);
+ if (params.broadcast)
+ params.nrequeue = params.nthreads;
+
+ printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %s%p), "
+ "%d at a time.\n\n", getpid(), params.nthreads,
+ params.fshared ? "shared":"private", &futex1,
+ params.pi ? "PI ": "", &futex2, params.nrequeue);
init_stats(&requeued_stats);
init_stats(&requeuetime_stats);
@@ -157,7 +203,7 @@ int bench_futex_requeue(int argc, const char **argv)
pthread_cond_init(&thread_worker, NULL);
for (j = 0; j < bench_repeat && !done; j++) {
- unsigned int nrequeued = 0;
+ unsigned int nrequeued = 0, wakeups = 0;
struct timeval start, end, runtime;
/* create, launch & block all threads */
@@ -174,13 +220,31 @@ int bench_futex_requeue(int argc, const char **argv)
/* Ok, all threads are patiently blocked, start requeueing */
gettimeofday(&start, NULL);
- while (nrequeued < nthreads) {
+ while (nrequeued < params.nthreads) {
+ int r;
+
/*
- * Do not wakeup any tasks blocked on futex1, allowing
- * us to really measure futex_wait functionality.
+ * For the regular non-pi case, do not wakeup any tasks
+ * blocked on futex1, allowing us to really measure
+ * futex_wait functionality. For the PI case the first
+ * waiter is always awoken.
*/
- nrequeued += futex_cmp_requeue(&futex1, 0, &futex2, 0,
- nrequeue, futex_flag);
+ if (!params.pi) {
+ r = futex_cmp_requeue(&futex1, 0, &futex2, 0,
+ params.nrequeue,
+ futex_flag);
+ } else {
+ r = futex_cmp_requeue_pi(&futex1, 0, &futex2,
+ params.nrequeue,
+ futex_flag);
+ wakeups++; /* assume no error */
+ }
+
+ if (r < 0)
+ err(EXIT_FAILURE, "couldn't requeue from %p to %p",
+ &futex1, &futex2);
+
+ nrequeued += r;
}
gettimeofday(&end, NULL);
@@ -189,17 +253,32 @@ int bench_futex_requeue(int argc, const char **argv)
update_stats(&requeued_stats, nrequeued);
update_stats(&requeuetime_stats, runtime.tv_usec);
- if (!silent) {
- printf("[Run %d]: Requeued %d of %d threads in %.4f ms\n",
- j + 1, nrequeued, nthreads, runtime.tv_usec / (double)USEC_PER_MSEC);
+ if (!params.silent) {
+ if (!params.pi)
+ printf("[Run %d]: Requeued %d of %d threads in "
+ "%.4f ms\n", j + 1, nrequeued,
+ params.nthreads,
+ runtime.tv_usec / (double)USEC_PER_MSEC);
+ else {
+ nrequeued -= wakeups;
+ printf("[Run %d]: Awoke and Requeued (%d+%d) of "
+ "%d threads in %.4f ms\n",
+ j + 1, wakeups, nrequeued,
+ params.nthreads,
+ runtime.tv_usec / (double)USEC_PER_MSEC);
+ }
+
}
- /* everybody should be blocked on futex2, wake'em up */
- nrequeued = futex_wake(&futex2, nrequeued, futex_flag);
- if (nthreads != nrequeued)
- warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
+ if (!params.pi) {
+ /* everybody should be blocked on futex2, wake'em up */
+ nrequeued = futex_wake(&futex2, nrequeued, futex_flag);
+ if (params.nthreads != nrequeued)
+ warnx("couldn't wakeup all tasks (%d/%d)",
+ nrequeued, params.nthreads);
+ }
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
ret = pthread_join(worker[i], NULL);
if (ret)
err(EXIT_FAILURE, "pthread_join");
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 6e6f5247e1fe..e970e6b9ad53 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -34,6 +34,7 @@ int bench_futex_wake_parallel(int argc __maybe_unused, const char **argv __maybe
#include <err.h>
#include <stdlib.h>
#include <sys/time.h>
+#include <sys/mman.h>
struct thread_data {
pthread_t worker;
@@ -47,8 +48,7 @@ static unsigned int nwakes = 1;
static u_int32_t futex = 0;
static pthread_t *blocked_worker;
-static bool done = false, silent = false, fshared = false;
-static unsigned int nblocked_threads = 0, nwaking_threads = 0;
+static bool done = false;
static pthread_mutex_t thread_lock;
static pthread_cond_t thread_parent, thread_worker;
static pthread_barrier_t barrier;
@@ -56,11 +56,15 @@ static struct stats waketime_stats, wakeup_stats;
static unsigned int threads_starting;
static int futex_flag = 0;
+static struct bench_futex_parameters params;
+
static const struct option options[] = {
- OPT_UINTEGER('t', "threads", &nblocked_threads, "Specify amount of threads"),
- OPT_UINTEGER('w', "nwakers", &nwaking_threads, "Specify amount of waking threads"),
- OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
- OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
+ OPT_UINTEGER('t', "threads", &params.nthreads, "Specify amount of threads"),
+ OPT_UINTEGER('w', "nwakers", &params.nwakes, "Specify amount of waking threads"),
+ OPT_BOOLEAN( 's', "silent", &params.silent, "Silent mode: do not display data/details"),
+ OPT_BOOLEAN( 'S', "shared", &params.fshared, "Use shared futexes instead of private ones"),
+ OPT_BOOLEAN( 'm', "mlockall", &params.mlockall, "Lock all current and future memory"),
+
OPT_END()
};
@@ -96,10 +100,10 @@ static void wakeup_threads(struct thread_data *td, pthread_attr_t thread_attr)
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
- pthread_barrier_init(&barrier, NULL, nwaking_threads + 1);
+ pthread_barrier_init(&barrier, NULL, params.nwakes + 1);
/* create and block all threads */
- for (i = 0; i < nwaking_threads; i++) {
+ for (i = 0; i < params.nwakes; i++) {
/*
* Thread creation order will impact per-thread latency
* as it will affect the order to acquire the hb spinlock.
@@ -112,7 +116,7 @@ static void wakeup_threads(struct thread_data *td, pthread_attr_t thread_attr)
pthread_barrier_wait(&barrier);
- for (i = 0; i < nwaking_threads; i++)
+ for (i = 0; i < params.nwakes; i++)
if (pthread_join(td[i].worker, NULL))
err(EXIT_FAILURE, "pthread_join");
@@ -143,10 +147,10 @@ static void block_threads(pthread_t *w, pthread_attr_t thread_attr,
cpu_set_t cpuset;
unsigned int i;
- threads_starting = nblocked_threads;
+ threads_starting = params.nthreads;
/* create and block all threads */
- for (i = 0; i < nblocked_threads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
CPU_ZERO(&cpuset);
CPU_SET(cpu->map[i % cpu->nr], &cpuset);
@@ -167,7 +171,7 @@ static void print_run(struct thread_data *waking_worker, unsigned int run_num)
init_stats(&__wakeup_stats);
init_stats(&__waketime_stats);
- for (i = 0; i < nwaking_threads; i++) {
+ for (i = 0; i < params.nwakes; i++) {
update_stats(&__waketime_stats, waking_worker[i].runtime.tv_usec);
update_stats(&__wakeup_stats, waking_worker[i].nwoken);
}
@@ -178,7 +182,7 @@ static void print_run(struct thread_data *waking_worker, unsigned int run_num)
printf("[Run %d]: Avg per-thread latency (waking %d/%d threads) "
"in %.4f ms (+-%.2f%%)\n", run_num + 1, wakeup_avg,
- nblocked_threads, waketime_avg / USEC_PER_MSEC,
+ params.nthreads, waketime_avg / USEC_PER_MSEC,
rel_stddev_stats(waketime_stddev, waketime_avg));
}
@@ -193,7 +197,7 @@ static void print_summary(void)
printf("Avg per-thread latency (waking %d/%d threads) in %.4f ms (+-%.2f%%)\n",
wakeup_avg,
- nblocked_threads,
+ params.nthreads,
waketime_avg / USEC_PER_MSEC,
rel_stddev_stats(waketime_stddev, waketime_avg));
}
@@ -203,7 +207,7 @@ static void do_run_stats(struct thread_data *waking_worker)
{
unsigned int i;
- for (i = 0; i < nwaking_threads; i++) {
+ for (i = 0; i < params.nwakes; i++) {
update_stats(&waketime_stats, waking_worker[i].runtime.tv_usec);
update_stats(&wakeup_stats, waking_worker[i].nwoken);
}
@@ -238,36 +242,42 @@ int bench_futex_wake_parallel(int argc, const char **argv)
act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL);
+ if (params.mlockall) {
+ if (mlockall(MCL_CURRENT | MCL_FUTURE))
+ err(EXIT_FAILURE, "mlockall");
+ }
+
cpu = perf_cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "calloc");
- if (!nblocked_threads)
- nblocked_threads = cpu->nr;
+ if (!params.nthreads)
+ params.nthreads = cpu->nr;
/* some sanity checks */
- if (nwaking_threads > nblocked_threads || !nwaking_threads)
- nwaking_threads = nblocked_threads;
+ if (params.nwakes > params.nthreads ||
+ !params.nwakes)
+ params.nwakes = params.nthreads;
- if (nblocked_threads % nwaking_threads)
+ if (params.nthreads % params.nwakes)
errx(EXIT_FAILURE, "Must be perfectly divisible");
/*
* Each thread will wakeup nwakes tasks in
* a single futex_wait call.
*/
- nwakes = nblocked_threads/nwaking_threads;
+ nwakes = params.nthreads/params.nwakes;
- blocked_worker = calloc(nblocked_threads, sizeof(*blocked_worker));
+ blocked_worker = calloc(params.nthreads, sizeof(*blocked_worker));
if (!blocked_worker)
err(EXIT_FAILURE, "calloc");
- if (!fshared)
+ if (!params.fshared)
futex_flag = FUTEX_PRIVATE_FLAG;
printf("Run summary [PID %d]: blocking on %d threads (at [%s] "
"futex %p), %d threads waking up %d at a time.\n\n",
- getpid(), nblocked_threads, fshared ? "shared":"private",
- &futex, nwaking_threads, nwakes);
+ getpid(), params.nthreads, params.fshared ? "shared":"private",
+ &futex, params.nwakes, nwakes);
init_stats(&wakeup_stats);
init_stats(&waketime_stats);
@@ -278,7 +288,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
pthread_cond_init(&thread_worker, NULL);
for (j = 0; j < bench_repeat && !done; j++) {
- waking_worker = calloc(nwaking_threads, sizeof(*waking_worker));
+ waking_worker = calloc(params.nwakes, sizeof(*waking_worker));
if (!waking_worker)
err(EXIT_FAILURE, "calloc");
@@ -297,14 +307,14 @@ int bench_futex_wake_parallel(int argc, const char **argv)
/* Ok, all threads are patiently blocked, start waking folks up */
wakeup_threads(waking_worker, thread_attr);
- for (i = 0; i < nblocked_threads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
ret = pthread_join(blocked_worker[i], NULL);
if (ret)
err(EXIT_FAILURE, "pthread_join");
}
do_run_stats(waking_worker);
- if (!silent)
+ if (!params.silent)
print_run(waking_worker, j);
free(waking_worker);
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 6d217868f53c..77f058a47790 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -27,29 +27,34 @@
#include <err.h>
#include <stdlib.h>
#include <sys/time.h>
+#include <sys/mman.h>
/* all threads will block on the same futex */
static u_int32_t futex1 = 0;
-/*
- * How many wakeups to do at a time.
- * Default to 1 in order to make the kernel work more.
- */
-static unsigned int nwakes = 1;
-
-pthread_t *worker;
-static bool done = false, silent = false, fshared = false;
+static pthread_t *worker;
+static bool done = false;
static pthread_mutex_t thread_lock;
static pthread_cond_t thread_parent, thread_worker;
static struct stats waketime_stats, wakeup_stats;
-static unsigned int threads_starting, nthreads = 0;
+static unsigned int threads_starting;
static int futex_flag = 0;
+static struct bench_futex_parameters params = {
+ /*
+ * How many wakeups to do at a time.
+ * Default to 1 in order to make the kernel work more.
+ */
+ .nwakes = 1,
+};
+
static const struct option options[] = {
- OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
- OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"),
- OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
- OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
+ OPT_UINTEGER('t', "threads", &params.nthreads, "Specify amount of threads"),
+ OPT_UINTEGER('w', "nwakes", &params.nwakes, "Specify amount of threads to wake at once"),
+ OPT_BOOLEAN( 's', "silent", &params.silent, "Silent mode: do not display data/details"),
+ OPT_BOOLEAN( 'S', "shared", &params.fshared, "Use shared futexes instead of private ones"),
+ OPT_BOOLEAN( 'm', "mlockall", &params.mlockall, "Lock all current and future memory"),
+
OPT_END()
};
@@ -84,7 +89,7 @@ static void print_summary(void)
printf("Wokeup %d of %d threads in %.4f ms (+-%.2f%%)\n",
wakeup_avg,
- nthreads,
+ params.nthreads,
waketime_avg / USEC_PER_MSEC,
rel_stddev_stats(waketime_stddev, waketime_avg));
}
@@ -95,10 +100,10 @@ static void block_threads(pthread_t *w,
cpu_set_t cpuset;
unsigned int i;
- threads_starting = nthreads;
+ threads_starting = params.nthreads;
/* create and block all threads */
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
CPU_ZERO(&cpuset);
CPU_SET(cpu->map[i % cpu->nr], &cpuset);
@@ -140,19 +145,25 @@ int bench_futex_wake(int argc, const char **argv)
act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL);
- if (!nthreads)
- nthreads = cpu->nr;
+ if (params.mlockall) {
+ if (mlockall(MCL_CURRENT | MCL_FUTURE))
+ err(EXIT_FAILURE, "mlockall");
+ }
+
+ if (!params.nthreads)
+ params.nthreads = cpu->nr;
- worker = calloc(nthreads, sizeof(*worker));
+ worker = calloc(params.nthreads, sizeof(*worker));
if (!worker)
err(EXIT_FAILURE, "calloc");
- if (!fshared)
+ if (!params.fshared)
futex_flag = FUTEX_PRIVATE_FLAG;
printf("Run summary [PID %d]: blocking on %d threads (at [%s] futex %p), "
"waking up %d at a time.\n\n",
- getpid(), nthreads, fshared ? "shared":"private", &futex1, nwakes);
+ getpid(), params.nthreads, params.fshared ? "shared":"private",
+ &futex1, params.nwakes);
init_stats(&wakeup_stats);
init_stats(&waketime_stats);
@@ -179,20 +190,22 @@ int bench_futex_wake(int argc, const char **argv)
/* Ok, all threads are patiently blocked, start waking folks up */
gettimeofday(&start, NULL);
- while (nwoken != nthreads)
- nwoken += futex_wake(&futex1, nwakes, futex_flag);
+ while (nwoken != params.nthreads)
+ nwoken += futex_wake(&futex1,
+ params.nwakes, futex_flag);
gettimeofday(&end, NULL);
timersub(&end, &start, &runtime);
update_stats(&wakeup_stats, nwoken);
update_stats(&waketime_stats, runtime.tv_usec);
- if (!silent) {
+ if (!params.silent) {
printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n",
- j + 1, nwoken, nthreads, runtime.tv_usec / (double)USEC_PER_MSEC);
+ j + 1, nwoken, params.nthreads,
+ runtime.tv_usec / (double)USEC_PER_MSEC);
}
- for (i = 0; i < nthreads; i++) {
+ for (i = 0; i < params.nthreads; i++) {
ret = pthread_join(worker[i], NULL);
if (ret)
err(EXIT_FAILURE, "pthread_join");
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index 31b53cc7d5bc..b3853aac3021 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -13,6 +13,20 @@
#include <sys/types.h>
#include <linux/futex.h>
+struct bench_futex_parameters {
+ bool silent;
+ bool fshared;
+ bool mlockall;
+ bool multi; /* lock-pi */
+ bool pi; /* requeue-pi */
+ bool broadcast; /* requeue */
+ unsigned int runtime; /* seconds*/
+ unsigned int nthreads;
+ unsigned int nfutexes;
+ unsigned int nwakes;
+ unsigned int nrequeue;
+};
+
/**
* futex() - SYS_futex syscall wrapper
* @uaddr: address of first futex
@@ -20,7 +34,7 @@
* @val: typically expected value of uaddr, but varies by op
* @timeout: typically an absolute struct timespec (except where noted
* otherwise). Overloaded by some ops
- * @uaddr2: address of second futex for some ops\
+ * @uaddr2: address of second futex for some ops
* @val3: varies by op
* @opflags: flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG
*
@@ -77,7 +91,7 @@ futex_unlock_pi(u_int32_t *uaddr, int opflags)
/**
* futex_cmp_requeue() - requeue tasks from uaddr to uaddr2
* @nr_wake: wake up to this many tasks
-* @nr_requeue: requeue up to this many tasks
+* @nr_requeue: requeue up to this many tasks
*/
static inline int
futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wake,
@@ -86,4 +100,38 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
val, opflags);
}
+
+/**
+ * futex_wait_requeue_pi() - block on uaddr and prepare to requeue to uaddr2
+ * @uaddr: non-PI futex source
+ * @uaddr2: PI futex target
+ *
+ * This is the first half of the requeue_pi mechanism. It shall always be
+ * paired with futex_cmp_requeue_pi().
+ */
+static inline int
+futex_wait_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2,
+ struct timespec *timeout, int opflags)
+{
+ return futex(uaddr, FUTEX_WAIT_REQUEUE_PI, val, timeout, uaddr2, 0,
+ opflags);
+}
+
+/**
+ * futex_cmp_requeue_pi() - requeue tasks from uaddr to uaddr2
+ * @uaddr: non-PI futex source
+ * @uaddr2: PI futex target
+ * @nr_requeue: requeue up to this many tasks
+ *
+ * This is the second half of the requeue_pi mechanism. It shall always be
+ * paired with futex_wait_requeue_pi(). The first waker is always awoken.
+ */
+static inline int
+futex_cmp_requeue_pi(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2,
+ int nr_requeue, int opflags)
+{
+ return futex(uaddr, FUTEX_CMP_REQUEUE_PI, 1, nr_requeue, uaddr2,
+ val, opflags);
+}
+
#endif /* _FUTEX_H */
diff --git a/tools/perf/bench/inject-buildid.c b/tools/perf/bench/inject-buildid.c
index 55d373b75791..17672790f123 100644
--- a/tools/perf/bench/inject-buildid.c
+++ b/tools/perf/bench/inject-buildid.c
@@ -133,7 +133,7 @@ static u64 dso_map_addr(struct bench_dso *dso)
return 0x400000ULL + dso->ino * 8192ULL;
}
-static u32 synthesize_attr(struct bench_data *data)
+static ssize_t synthesize_attr(struct bench_data *data)
{
union perf_event event;
@@ -151,7 +151,7 @@ static u32 synthesize_attr(struct bench_data *data)
return writen(data->input_pipe[1], &event, event.header.size);
}
-static u32 synthesize_fork(struct bench_data *data)
+static ssize_t synthesize_fork(struct bench_data *data)
{
union perf_event event;
@@ -169,8 +169,7 @@ static u32 synthesize_fork(struct bench_data *data)
return writen(data->input_pipe[1], &event, event.header.size);
}
-static u32 synthesize_mmap(struct bench_data *data, struct bench_dso *dso,
- u64 timestamp)
+static ssize_t synthesize_mmap(struct bench_data *data, struct bench_dso *dso, u64 timestamp)
{
union perf_event event;
size_t len = offsetof(struct perf_record_mmap2, filename);
@@ -198,23 +197,25 @@ static u32 synthesize_mmap(struct bench_data *data, struct bench_dso *dso,
if (len > sizeof(event.mmap2)) {
/* write mmap2 event first */
- writen(data->input_pipe[1], &event, len - bench_id_hdr_size);
+ if (writen(data->input_pipe[1], &event, len - bench_id_hdr_size) < 0)
+ return -1;
/* zero-fill sample id header */
memset(id_hdr_ptr, 0, bench_id_hdr_size);
/* put timestamp in the right position */
ts_idx = (bench_id_hdr_size / sizeof(u64)) - 2;
id_hdr_ptr[ts_idx] = timestamp;
- writen(data->input_pipe[1], id_hdr_ptr, bench_id_hdr_size);
- } else {
- ts_idx = (len / sizeof(u64)) - 2;
- id_hdr_ptr[ts_idx] = timestamp;
- writen(data->input_pipe[1], &event, len);
+ if (writen(data->input_pipe[1], id_hdr_ptr, bench_id_hdr_size) < 0)
+ return -1;
+
+ return len;
}
- return len;
+
+ ts_idx = (len / sizeof(u64)) - 2;
+ id_hdr_ptr[ts_idx] = timestamp;
+ return writen(data->input_pipe[1], &event, len);
}
-static u32 synthesize_sample(struct bench_data *data, struct bench_dso *dso,
- u64 timestamp)
+static ssize_t synthesize_sample(struct bench_data *data, struct bench_dso *dso, u64 timestamp)
{
union perf_event event;
struct perf_sample sample = {
@@ -233,7 +234,7 @@ static u32 synthesize_sample(struct bench_data *data, struct bench_dso *dso,
return writen(data->input_pipe[1], &event, event.header.size);
}
-static u32 synthesize_flush(struct bench_data *data)
+static ssize_t synthesize_flush(struct bench_data *data)
{
struct perf_event_header header = {
.size = sizeof(header),
@@ -348,14 +349,16 @@ static int inject_build_id(struct bench_data *data, u64 *max_rss)
int status;
unsigned int i, k;
struct rusage rusage;
- u64 len = 0;
/* this makes the child to run */
if (perf_header__write_pipe(data->input_pipe[1]) < 0)
return -1;
- len += synthesize_attr(data);
- len += synthesize_fork(data);
+ if (synthesize_attr(data) < 0)
+ return -1;
+
+ if (synthesize_fork(data) < 0)
+ return -1;
for (i = 0; i < nr_mmaps; i++) {
int idx = rand() % (nr_dsos - 1);
@@ -363,13 +366,18 @@ static int inject_build_id(struct bench_data *data, u64 *max_rss)
u64 timestamp = rand() % 1000000;
pr_debug2(" [%d] injecting: %s\n", i+1, dso->name);
- len += synthesize_mmap(data, dso, timestamp);
+ if (synthesize_mmap(data, dso, timestamp) < 0)
+ return -1;
- for (k = 0; k < nr_samples; k++)
- len += synthesize_sample(data, dso, timestamp + k * 1000);
+ for (k = 0; k < nr_samples; k++) {
+ if (synthesize_sample(data, dso, timestamp + k * 1000) < 0)
+ return -1;
+ }
- if ((i + 1) % 10 == 0)
- len += synthesize_flush(data);
+ if ((i + 1) % 10 == 0) {
+ if (synthesize_flush(data) < 0)
+ return -1;
+ }
}
/* this makes the child to finish */
diff --git a/tools/perf/bench/synthesize.c b/tools/perf/bench/synthesize.c
index b2924e3181dc..05f7c923c745 100644
--- a/tools/perf/bench/synthesize.c
+++ b/tools/perf/bench/synthesize.c
@@ -117,7 +117,7 @@ static int run_single_threaded(void)
int err;
perf_set_singlethreaded();
- session = perf_session__new(NULL, false, NULL);
+ session = perf_session__new(NULL, NULL);
if (IS_ERR(session)) {
pr_err("Session creation failed.\n");
return PTR_ERR(session);
@@ -161,7 +161,7 @@ static int do_run_multi_threaded(struct target *target,
init_stats(&time_stats);
init_stats(&event_stats);
for (i = 0; i < multi_iterations; i++) {
- session = perf_session__new(NULL, false, NULL);
+ session = perf_session__new(NULL, NULL);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index cebb861be3e3..05eb098cb0e3 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -596,7 +596,7 @@ int cmd_annotate(int argc, const char **argv)
data.path = input_name;
- annotate.session = perf_session__new(&data, false, &annotate.tool);
+ annotate.session = perf_session__new(&data, &annotate.tool);
if (IS_ERR(annotate.session))
return PTR_ERR(annotate.session);
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 62a7b7420a44..d0895162c2ba 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -88,6 +88,7 @@ static struct bench internals_benchmarks[] = {
{ "synthesize", "Benchmark perf event synthesis", bench_synthesize },
{ "kallsyms-parse", "Benchmark kallsyms parsing", bench_kallsyms_parse },
{ "inject-build-id", "Benchmark build-id injection", bench_inject_build_id },
+ { "evlist-open-close", "Benchmark evlist open and close", bench_evlist_open_close },
{ NULL, NULL, NULL }
};
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index ecd0d3cb6f5c..0db3cfc04c47 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -443,7 +443,7 @@ int cmd_buildid_cache(int argc, const char **argv)
data.path = missing_filename;
data.force = force;
- session = perf_session__new(&data, false, NULL);
+ session = perf_session__new(&data, NULL);
if (IS_ERR(session))
return PTR_ERR(session);
}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 833405c27dae..cebadd632234 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -65,7 +65,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
if (filename__fprintf_build_id(input_name, stdout) > 0)
goto out;
- session = perf_session__new(&data, false, &build_id__mark_dso_hit_ops);
+ session = perf_session__new(&data, &build_id__mark_dso_hit_ops);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 6dea37f141b2..a812f32cf5d9 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -2790,7 +2790,7 @@ static int perf_c2c__report(int argc, const char **argv)
goto out;
}
- session = perf_session__new(&data, 0, &c2c.tool);
+ session = perf_session__new(&data, &c2c.tool);
if (IS_ERR(session)) {
err = PTR_ERR(session);
pr_debug("Error creating perf session\n");
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index 15ca23675ef0..b7f9dc85a407 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -21,46 +21,21 @@ static struct data_cmd data_cmds[];
#define for_each_cmd(cmd) \
for (cmd = data_cmds; cmd && cmd->name; cmd++)
-static const struct option data_options[] = {
- OPT_END()
-};
-
static const char * const data_subcommands[] = { "convert", NULL };
static const char *data_usage[] = {
- "perf data [<common options>] <command> [<options>]",
+ "perf data convert [<options>]",
NULL
};
-static void print_usage(void)
-{
- struct data_cmd *cmd;
-
- printf("Usage:\n");
- printf("\t%s\n\n", data_usage[0]);
- printf("\tAvailable commands:\n");
-
- for_each_cmd(cmd) {
- printf("\t %s\t- %s\n", cmd->name, cmd->summary);
- }
-
- printf("\n");
-}
-
-static const char * const data_convert_usage[] = {
- "perf data convert [<options>]",
- NULL
+const char *to_json;
+const char *to_ctf;
+struct perf_data_convert_opts opts = {
+ .force = false,
+ .all = false,
};
-static int cmd_data_convert(int argc, const char **argv)
-{
- const char *to_json = NULL;
- const char *to_ctf = NULL;
- struct perf_data_convert_opts opts = {
- .force = false,
- .all = false,
- };
- const struct option options[] = {
+const struct option data_options[] = {
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
OPT_STRING('i', "input", &input_name, "file", "input file name"),
OPT_STRING(0, "to-json", &to_json, NULL, "Convert to JSON format"),
@@ -73,10 +48,13 @@ static int cmd_data_convert(int argc, const char **argv)
OPT_END()
};
- argc = parse_options(argc, argv, options,
- data_convert_usage, 0);
+static int cmd_data_convert(int argc, const char **argv)
+{
+
+ argc = parse_options(argc, argv, data_options,
+ data_usage, 0);
if (argc) {
- usage_with_options(data_convert_usage, options);
+ usage_with_options(data_usage, data_options);
return -1;
}
@@ -116,14 +94,13 @@ int cmd_data(int argc, const char **argv)
struct data_cmd *cmd;
const char *cmdstr;
- /* No command specified. */
- if (argc < 2)
- goto usage;
-
argc = parse_options_subcommand(argc, argv, data_options, data_subcommands, data_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
- if (argc < 1)
- goto usage;
+
+ if (!argc) {
+ usage_with_options(data_usage, data_options);
+ return -1;
+ }
cmdstr = argv[0];
@@ -135,7 +112,6 @@ int cmd_data(int argc, const char **argv)
}
pr_err("Unknown command: %s\n", cmdstr);
-usage:
- print_usage();
+ usage_with_options(data_usage, data_options);
return -1;
}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 80450c0e8f36..d925096dd7f0 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -1156,7 +1156,7 @@ static int check_file_brstack(void)
int i;
data__for_each_file(i, d) {
- d->session = perf_session__new(&d->data, false, &pdiff.tool);
+ d->session = perf_session__new(&d->data, &pdiff.tool);
if (IS_ERR(d->session)) {
pr_err("Failed to open %s\n", d->data.path);
return PTR_ERR(d->session);
@@ -1188,7 +1188,7 @@ static int __cmd_diff(void)
ret = -EINVAL;
data__for_each_file(i, d) {
- d->session = perf_session__new(&d->data, false, &pdiff.tool);
+ d->session = perf_session__new(&d->data, &pdiff.tool);
if (IS_ERR(d->session)) {
ret = PTR_ERR(d->session);
pr_err("Failed to open %s\n", d->data.path);
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 4617b32c9c97..b1076177c37f 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -42,7 +42,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
};
bool has_tracepoint = false;
- session = perf_session__new(&data, 0, &tool);
+ session = perf_session__new(&data, &tool);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index c88c61e7f8cc..6ad191e731fc 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -46,6 +46,7 @@ struct perf_inject {
bool jit_mode;
bool in_place_update;
bool in_place_update_dry_run;
+ bool is_pipe;
const char *input_name;
struct perf_data output;
u64 bytes_written;
@@ -126,7 +127,7 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
if (ret)
return ret;
- if (!inject->output.is_pipe)
+ if (!inject->is_pipe)
return 0;
return perf_event__repipe_synth(tool, event);
@@ -826,14 +827,14 @@ static int __cmd_inject(struct perf_inject *inject)
if (!inject->itrace_synth_opts.set)
auxtrace_index__free(&session->auxtrace_index);
- if (!data_out->is_pipe && !inject->in_place_update)
+ if (!inject->is_pipe && !inject->in_place_update)
lseek(fd, output_data_offset, SEEK_SET);
ret = perf_session__process_events(session);
if (ret)
return ret;
- if (!data_out->is_pipe && !inject->in_place_update) {
+ if (!inject->is_pipe && !inject->in_place_update) {
if (inject->build_ids)
perf_header__set_feat(&session->header,
HEADER_BUILD_ID);
@@ -918,6 +919,7 @@ int cmd_inject(int argc, const char **argv)
.use_stdio = true,
};
int ret;
+ bool repipe = true;
struct option options[] = {
OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
@@ -992,7 +994,20 @@ int cmd_inject(int argc, const char **argv)
}
data.path = inject.input_name;
- inject.session = perf_session__new(&data, inject.output.is_pipe, &inject.tool);
+ if (!strcmp(inject.input_name, "-") || inject.output.is_pipe) {
+ inject.is_pipe = true;
+ /*
+ * Do not repipe header when input is a regular file
+ * since either it can rewrite the header at the end
+ * or write a new pipe header.
+ */
+ if (strcmp(inject.input_name, "-"))
+ repipe = false;
+ }
+
+ inject.session = __perf_session__new(&data, repipe,
+ perf_data__fd(&inject.output),
+ &inject.tool);
if (IS_ERR(inject.session)) {
ret = PTR_ERR(inject.session);
goto out_close_output;
@@ -1001,6 +1016,21 @@ int cmd_inject(int argc, const char **argv)
if (zstd_init(&(inject.session->zstd_data), 0) < 0)
pr_warning("Decompression initialization failed.\n");
+ if (!data.is_pipe && inject.output.is_pipe) {
+ ret = perf_header__write_pipe(perf_data__fd(&inject.output));
+ if (ret < 0) {
+ pr_err("Couldn't write a new pipe header.\n");
+ goto out_delete;
+ }
+
+ ret = perf_event__synthesize_for_pipe(&inject.tool,
+ inject.session,
+ &inject.output,
+ perf_event__repipe);
+ if (ret < 0)
+ goto out_delete;
+ }
+
if (inject.build_ids && !inject.build_id_all) {
/*
* to make sure the mmap records are ordered correctly
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 0062445e8ead..da03a341c63c 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1953,7 +1953,7 @@ int cmd_kmem(int argc, const char **argv)
data.path = input_name;
- kmem_session = session = perf_session__new(&data, false, &perf_kmem);
+ kmem_session = session = perf_session__new(&data, &perf_kmem);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 1105c9e40a80..aa1b127ffb5b 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1093,7 +1093,7 @@ static int read_events(struct perf_kvm_stat *kvm)
};
kvm->tool = eops;
- kvm->session = perf_session__new(&file, false, &kvm->tool);
+ kvm->session = perf_session__new(&file, &kvm->tool);
if (IS_ERR(kvm->session)) {
pr_err("Initializing perf session failed\n");
return PTR_ERR(kvm->session);
@@ -1447,7 +1447,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
/*
* perf session
*/
- kvm->session = perf_session__new(&data, false, &kvm->tool);
+ kvm->session = perf_session__new(&data, &kvm->tool);
if (IS_ERR(kvm->session)) {
err = PTR_ERR(kvm->session);
goto out;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 01326e370009..d70131b7b1b1 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -868,7 +868,7 @@ static int __cmd_report(bool display_info)
.force = force,
};
- session = perf_session__new(&data, false, &eops);
+ session = perf_session__new(&data, &eops);
if (IS_ERR(session)) {
pr_err("Initializing perf session failed\n");
return PTR_ERR(session);
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 0fd2a74dbaca..fcf65a59bea2 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -271,8 +271,7 @@ static int report_raw_events(struct perf_mem *mem)
.force = mem->force,
};
int ret;
- struct perf_session *session = perf_session__new(&data, false,
- &mem->tool);
+ struct perf_session *session = perf_session__new(&data, &mem->tool);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 671a21c9ee4d..06c4dca0c466 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -910,7 +910,8 @@ static int record__open(struct record *rec)
* Enable the dummy event when the process is forked for
* initial_delay, immediately for system wide.
*/
- if (opts->initial_delay && !pos->immediate)
+ if (opts->initial_delay && !pos->immediate &&
+ !target__has_cpu(&opts->target))
pos->core.attr.enable_on_exec = 1;
else
pos->immediate = 1;
@@ -1387,7 +1388,6 @@ static int record__synthesize(struct record *rec, bool tail)
struct perf_data *data = &rec->data;
struct record_opts *opts = &rec->opts;
struct perf_tool *tool = &rec->tool;
- int fd = perf_data__fd(data);
int err = 0;
event_op f = process_synthesized_event;
@@ -1395,41 +1395,12 @@ static int record__synthesize(struct record *rec, bool tail)
return 0;
if (data->is_pipe) {
- /*
- * We need to synthesize events first, because some
- * features works on top of them (on report side).
- */
- err = perf_event__synthesize_attrs(tool, rec->evlist,
- process_synthesized_event);
- if (err < 0) {
- pr_err("Couldn't synthesize attrs.\n");
- goto out;
- }
-
- err = perf_event__synthesize_features(tool, session, rec->evlist,
+ err = perf_event__synthesize_for_pipe(tool, session, data,
process_synthesized_event);
- if (err < 0) {
- pr_err("Couldn't synthesize features.\n");
- return err;
- }
+ if (err < 0)
+ goto out;
- if (have_tracepoints(&rec->evlist->core.entries)) {
- /*
- * FIXME err <= 0 here actually means that
- * there were no tracepoints so its not really
- * an error, just that we don't need to
- * synthesize anything. We really have to
- * return this more properly and also
- * propagate errors that now are calling die()
- */
- err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist,
- process_synthesized_event);
- if (err <= 0) {
- pr_err("Couldn't record tracing data.\n");
- goto out;
- }
- rec->bytes_written += err;
- }
+ rec->bytes_written += err;
}
err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
@@ -1681,7 +1652,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
signal(SIGUSR2, SIG_IGN);
}
- session = perf_session__new(data, false, tool);
+ session = perf_session__new(data, tool);
if (IS_ERR(session)) {
pr_err("Perf session creation failed.\n");
return PTR_ERR(session);
@@ -2884,6 +2855,13 @@ int cmd_record(int argc, const char **argv)
/* Enable ignoring missing threads when -u/-p option is defined. */
rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
+ if (evlist__fix_hybrid_cpus(rec->evlist, rec->opts.target.cpu_list)) {
+ pr_err("failed to use cpu list %s\n",
+ rec->opts.target.cpu_list);
+ goto out;
+ }
+
+ rec->opts.target.hybrid = perf_pmu__has_hybrid();
err = -ENOMEM;
if (evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
usage_with_options(record_usage, record_options);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index dc0364f671b9..a0316ce910db 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1411,7 +1411,7 @@ int cmd_report(int argc, const char **argv)
data.force = symbol_conf.force;
repeat:
- session = perf_session__new(&data, false, &report.tool);
+ session = perf_session__new(&data, &report.tool);
if (IS_ERR(session)) {
ret = PTR_ERR(session);
goto exit;
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 1ff10d4bccf3..635a6b5a9ec9 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1804,7 +1804,7 @@ static int perf_sched__read_events(struct perf_sched *sched)
};
int rc = -1;
- session = perf_session__new(&data, false, &sched->tool);
+ session = perf_session__new(&data, &sched->tool);
if (IS_ERR(session)) {
pr_debug("Error creating perf session");
return PTR_ERR(session);
@@ -3011,7 +3011,7 @@ static int perf_sched__timehist(struct perf_sched *sched)
symbol_conf.use_callchain = sched->show_callchain;
- session = perf_session__new(&data, false, &sched->tool);
+ session = perf_session__new(&data, &sched->tool);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 064da7f3618d..0e824f7d8b19 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2212,7 +2212,7 @@ static int process_sample_event(struct perf_tool *tool,
if (filter_cpu(sample))
goto out_put;
- if (machine__resolve(machine, &al, sample) < 0) {
+ if (!al.thread && machine__resolve(machine, &al, sample) < 0) {
pr_err("problem processing %d event, skipping it.\n",
event->header.type);
ret = -1;
@@ -2493,6 +2493,17 @@ process_lost_event(struct perf_tool *tool,
}
static int
+process_throttle_event(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ if (scripting_ops && scripting_ops->process_throttle)
+ scripting_ops->process_throttle(event, sample, machine);
+ return 0;
+}
+
+static int
process_finished_round_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct ordered_events *oe __maybe_unused)
@@ -3294,7 +3305,7 @@ int find_scripts(char **scripts_array, char **scripts_path_array, int num,
char *temp;
int i = 0;
- session = perf_session__new(&data, false, NULL);
+ session = perf_session__new(&data, NULL);
if (IS_ERR(session))
return PTR_ERR(session);
@@ -3652,6 +3663,8 @@ int cmd_script(int argc, const char **argv)
.stat_config = process_stat_config_event,
.thread_map = process_thread_map_event,
.cpu_map = process_cpu_map_event,
+ .throttle = process_throttle_event,
+ .unthrottle = process_throttle_event,
.ordered_events = true,
.ordering_requires_timestamps = true,
},
@@ -4007,7 +4020,7 @@ script_found:
use_browser = 0;
}
- session = perf_session__new(&data, false, &script.tool);
+ session = perf_session__new(&data, &script.tool);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 634375937db9..f6e87b7be5fa 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1996,7 +1996,7 @@ static int __cmd_record(int argc, const char **argv)
return -1;
}
- session = perf_session__new(data, false, NULL);
+ session = perf_session__new(data, NULL);
if (IS_ERR(session)) {
pr_err("Perf session creation failed\n");
return PTR_ERR(session);
@@ -2168,7 +2168,7 @@ static int __cmd_report(int argc, const char **argv)
perf_stat.data.path = input_name;
perf_stat.data.mode = PERF_DATA_MODE_READ;
- session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
+ session = perf_session__new(&perf_stat.data, &perf_stat.tool);
if (IS_ERR(session))
return PTR_ERR(session);
@@ -2386,7 +2386,8 @@ int cmd_stat(int argc, const char **argv)
* --per-thread is aggregated per thread, we dont mix it with cpu mode
*/
if (((stat_config.aggr_mode != AGGR_GLOBAL &&
- stat_config.aggr_mode != AGGR_THREAD) || nr_cgroups) &&
+ stat_config.aggr_mode != AGGR_THREAD) ||
+ (nr_cgroups || stat_config.cgroup_list)) &&
!target__has_cpu(&target)) {
fprintf(stderr, "both cgroup and no-aggregation "
"modes only available in system-wide mode\n");
@@ -2394,6 +2395,7 @@ int cmd_stat(int argc, const char **argv)
parse_options_usage(stat_usage, stat_options, "G", 1);
parse_options_usage(NULL, stat_options, "A", 1);
parse_options_usage(NULL, stat_options, "a", 1);
+ parse_options_usage(NULL, stat_options, "for-each-cgroup", 0);
goto out;
}
@@ -2430,6 +2432,12 @@ int cmd_stat(int argc, const char **argv)
if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
target.per_thread = true;
+ if (evlist__fix_hybrid_cpus(evsel_list, target.cpu_list)) {
+ pr_err("failed to use cpu list %s\n", target.cpu_list);
+ goto out;
+ }
+
+ target.hybrid = perf_pmu__has_hybrid();
if (evlist__create_maps(evsel_list, &target) < 0) {
if (target__has_task(&target)) {
pr_err("Problems finding threads of monitor\n");
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 4e380e7b5230..43bf4d67edb0 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1598,8 +1598,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
.force = tchart->force,
};
- struct perf_session *session = perf_session__new(&data, false,
- &tchart->tool);
+ struct perf_session *session = perf_session__new(&data, &tchart->tool);
int ret = -EINVAL;
if (IS_ERR(session))
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 02f8bb5dbc0f..a3ae9176a83e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1740,7 +1740,7 @@ int cmd_top(int argc, const char **argv)
signal(SIGWINCH, winch_sig);
}
- top.session = perf_session__new(NULL, false, NULL);
+ top.session = perf_session__new(NULL, NULL);
if (IS_ERR(top.session)) {
status = PTR_ERR(top.session);
goto out_delete_evlist;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 9c265fa96011..2bf21194c7b3 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -707,7 +707,15 @@ static size_t syscall_arg__scnprintf_char_array(char *bf, size_t size, struct sy
static const char *bpf_cmd[] = {
"MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
- "MAP_GET_NEXT_KEY", "PROG_LOAD",
+ "MAP_GET_NEXT_KEY", "PROG_LOAD", "OBJ_PIN", "OBJ_GET", "PROG_ATTACH",
+ "PROG_DETACH", "PROG_TEST_RUN", "PROG_GET_NEXT_ID", "MAP_GET_NEXT_ID",
+ "PROG_GET_FD_BY_ID", "MAP_GET_FD_BY_ID", "OBJ_GET_INFO_BY_FD",
+ "PROG_QUERY", "RAW_TRACEPOINT_OPEN", "BTF_LOAD", "BTF_GET_FD_BY_ID",
+ "TASK_FD_QUERY", "MAP_LOOKUP_AND_DELETE_ELEM", "MAP_FREEZE",
+ "BTF_GET_NEXT_ID", "MAP_LOOKUP_BATCH", "MAP_LOOKUP_AND_DELETE_BATCH",
+ "MAP_UPDATE_BATCH", "MAP_DELETE_BATCH", "LINK_CREATE", "LINK_UPDATE",
+ "LINK_GET_FD_BY_ID", "LINK_GET_NEXT_ID", "ENABLE_STATS", "ITER_CREATE",
+ "LINK_DETACH", "PROG_BIND_MAP",
};
static DEFINE_STRARRAY(bpf_cmd, "BPF_");
@@ -4228,7 +4236,7 @@ static int trace__replay(struct trace *trace)
/* add tid to output */
trace->multiple_threads = true;
- session = perf_session__new(&data, false, &trace->tool);
+ session = perf_session__new(&data, &trace->tool);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/dlfilters/dlfilter-test-api-v0.c b/tools/perf/dlfilters/dlfilter-test-api-v0.c
new file mode 100644
index 000000000000..7565a1852c74
--- /dev/null
+++ b/tools/perf/dlfilters/dlfilter-test-api-v0.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dlfilter-test-api-v0.c: test original (v0) API for perf --dlfilter shared object
+ * Copyright (c) 2021, Intel Corporation.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+/*
+ * Copy original (v0) API instead of including current API
+ */
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+/* Definitions for perf_dlfilter_sample flags */
+enum {
+ PERF_DLFILTER_FLAG_BRANCH = 1ULL << 0,
+ PERF_DLFILTER_FLAG_CALL = 1ULL << 1,
+ PERF_DLFILTER_FLAG_RETURN = 1ULL << 2,
+ PERF_DLFILTER_FLAG_CONDITIONAL = 1ULL << 3,
+ PERF_DLFILTER_FLAG_SYSCALLRET = 1ULL << 4,
+ PERF_DLFILTER_FLAG_ASYNC = 1ULL << 5,
+ PERF_DLFILTER_FLAG_INTERRUPT = 1ULL << 6,
+ PERF_DLFILTER_FLAG_TX_ABORT = 1ULL << 7,
+ PERF_DLFILTER_FLAG_TRACE_BEGIN = 1ULL << 8,
+ PERF_DLFILTER_FLAG_TRACE_END = 1ULL << 9,
+ PERF_DLFILTER_FLAG_IN_TX = 1ULL << 10,
+ PERF_DLFILTER_FLAG_VMENTRY = 1ULL << 11,
+ PERF_DLFILTER_FLAG_VMEXIT = 1ULL << 12,
+};
+
+/*
+ * perf sample event information (as per perf script and <linux/perf_event.h>)
+ */
+struct perf_dlfilter_sample {
+ __u32 size; /* Size of this structure (for compatibility checking) */
+ __u16 ins_lat; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
+ __u16 p_stage_cyc; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
+ __u64 ip;
+ __s32 pid;
+ __s32 tid;
+ __u64 time;
+ __u64 addr;
+ __u64 id;
+ __u64 stream_id;
+ __u64 period;
+ __u64 weight; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
+ __u64 transaction; /* Refer PERF_SAMPLE_TRANSACTION in <linux/perf_event.h> */
+ __u64 insn_cnt; /* For instructions-per-cycle (IPC) */
+ __u64 cyc_cnt; /* For instructions-per-cycle (IPC) */
+ __s32 cpu;
+ __u32 flags; /* Refer PERF_DLFILTER_FLAG_* above */
+ __u64 data_src; /* Refer PERF_SAMPLE_DATA_SRC in <linux/perf_event.h> */
+ __u64 phys_addr; /* Refer PERF_SAMPLE_PHYS_ADDR in <linux/perf_event.h> */
+ __u64 data_page_size; /* Refer PERF_SAMPLE_DATA_PAGE_SIZE in <linux/perf_event.h> */
+ __u64 code_page_size; /* Refer PERF_SAMPLE_CODE_PAGE_SIZE in <linux/perf_event.h> */
+ __u64 cgroup; /* Refer PERF_SAMPLE_CGROUP in <linux/perf_event.h> */
+ __u8 cpumode; /* Refer CPUMODE_MASK etc in <linux/perf_event.h> */
+ __u8 addr_correlates_sym; /* True => resolve_addr() can be called */
+ __u16 misc; /* Refer perf_event_header in <linux/perf_event.h> */
+ __u32 raw_size; /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
+ const void *raw_data; /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
+ __u64 brstack_nr; /* Number of brstack entries */
+ const struct perf_branch_entry *brstack; /* Refer <linux/perf_event.h> */
+ __u64 raw_callchain_nr; /* Number of raw_callchain entries */
+ const __u64 *raw_callchain; /* Refer <linux/perf_event.h> */
+ const char *event;
+};
+
+/*
+ * Address location (as per perf script)
+ */
+struct perf_dlfilter_al {
+ __u32 size; /* Size of this structure (for compatibility checking) */
+ __u32 symoff;
+ const char *sym;
+ __u64 addr; /* Mapped address (from dso) */
+ __u64 sym_start;
+ __u64 sym_end;
+ const char *dso;
+ __u8 sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */
+ __u8 is_64_bit; /* Only valid if dso is not NULL */
+ __u8 is_kernel_ip; /* True if in kernel space */
+ __u32 buildid_size;
+ __u8 *buildid;
+ /* Below members are only populated by resolve_ip() */
+ __u8 filtered; /* True if this sample event will be filtered out */
+ const char *comm;
+};
+
+struct perf_dlfilter_fns {
+ /* Return information about ip */
+ const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);
+ /* Return information about addr (if addr_correlates_sym) */
+ const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);
+ /* Return arguments from --dlarg option */
+ char **(*args)(void *ctx, int *dlargc);
+ /*
+ * Return information about address (al->size must be set before
+ * calling). Returns 0 on success, -1 otherwise.
+ */
+ __s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);
+ /* Return instruction bytes and length */
+ const __u8 *(*insn)(void *ctx, __u32 *length);
+ /* Return source file name and line number */
+ const char *(*srcline)(void *ctx, __u32 *line_number);
+ /* Return perf_event_attr, refer <linux/perf_event.h> */
+ struct perf_event_attr *(*attr)(void *ctx);
+ /* Read object code, return numbers of bytes read */
+ __s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);
+ /* Reserved */
+ void *(*reserved[120])(void *);
+};
+
+struct perf_dlfilter_fns perf_dlfilter_fns;
+
+static int verbose;
+
+#define pr_debug(fmt, ...) do { \
+ if (verbose) \
+ fprintf(stderr, fmt, ##__VA_ARGS__); \
+ } while (0)
+
+static int test_fail(const char *msg)
+{
+ pr_debug("%s\n", msg);
+ return -1;
+}
+
+#define CHECK(x) do { \
+ if (!(x)) \
+ return test_fail("Check '" #x "' failed\n"); \
+ } while (0)
+
+struct filter_data {
+ __u64 ip;
+ __u64 addr;
+ int do_early;
+ int early_filter_cnt;
+ int filter_cnt;
+};
+
+static struct filter_data *filt_dat;
+
+int start(void **data, void *ctx)
+{
+ int dlargc;
+ char **dlargv;
+ struct filter_data *d;
+ static bool called;
+
+ verbose = 1;
+
+ CHECK(!filt_dat && !called);
+ called = true;
+
+ d = calloc(1, sizeof(*d));
+ if (!d)
+ test_fail("Failed to allocate memory");
+ filt_dat = d;
+ *data = d;
+
+ dlargv = perf_dlfilter_fns.args(ctx, &dlargc);
+
+ CHECK(dlargc == 6);
+ CHECK(!strcmp(dlargv[0], "first"));
+ verbose = strtol(dlargv[1], NULL, 0);
+ d->ip = strtoull(dlargv[2], NULL, 0);
+ d->addr = strtoull(dlargv[3], NULL, 0);
+ d->do_early = strtol(dlargv[4], NULL, 0);
+ CHECK(!strcmp(dlargv[5], "last"));
+
+ pr_debug("%s API\n", __func__);
+
+ return 0;
+}
+
+#define CHECK_SAMPLE(x) do { \
+ if (sample->x != expected.x) \
+ return test_fail("'" #x "' not expected value\n"); \
+ } while (0)
+
+static int check_sample(struct filter_data *d, const struct perf_dlfilter_sample *sample)
+{
+ struct perf_dlfilter_sample expected = {
+ .ip = d->ip,
+ .pid = 12345,
+ .tid = 12346,
+ .time = 1234567890,
+ .addr = d->addr,
+ .id = 99,
+ .stream_id = 101,
+ .period = 543212345,
+ .cpu = 31,
+ .cpumode = PERF_RECORD_MISC_USER,
+ .addr_correlates_sym = 1,
+ .misc = PERF_RECORD_MISC_USER,
+ };
+
+ CHECK(sample->size >= sizeof(struct perf_dlfilter_sample));
+
+ CHECK_SAMPLE(ip);
+ CHECK_SAMPLE(pid);
+ CHECK_SAMPLE(tid);
+ CHECK_SAMPLE(time);
+ CHECK_SAMPLE(addr);
+ CHECK_SAMPLE(id);
+ CHECK_SAMPLE(stream_id);
+ CHECK_SAMPLE(period);
+ CHECK_SAMPLE(cpu);
+ CHECK_SAMPLE(cpumode);
+ CHECK_SAMPLE(addr_correlates_sym);
+ CHECK_SAMPLE(misc);
+
+ CHECK(!sample->raw_data);
+ CHECK_SAMPLE(brstack_nr);
+ CHECK(!sample->brstack);
+ CHECK_SAMPLE(raw_callchain_nr);
+ CHECK(!sample->raw_callchain);
+
+#define EVENT_NAME "branches:"
+ CHECK(!strncmp(sample->event, EVENT_NAME, strlen(EVENT_NAME)));
+
+ return 0;
+}
+
+static int check_al(void *ctx)
+{
+ const struct perf_dlfilter_al *al;
+
+ al = perf_dlfilter_fns.resolve_ip(ctx);
+ if (!al)
+ return test_fail("resolve_ip() failed");
+
+ CHECK(al->sym && !strcmp("foo", al->sym));
+ CHECK(!al->symoff);
+
+ return 0;
+}
+
+static int check_addr_al(void *ctx)
+{
+ const struct perf_dlfilter_al *addr_al;
+
+ addr_al = perf_dlfilter_fns.resolve_addr(ctx);
+ if (!addr_al)
+ return test_fail("resolve_addr() failed");
+
+ CHECK(addr_al->sym && !strcmp("bar", addr_al->sym));
+ CHECK(!addr_al->symoff);
+
+ return 0;
+}
+
+static int check_attr(void *ctx)
+{
+ struct perf_event_attr *attr = perf_dlfilter_fns.attr(ctx);
+
+ CHECK(attr);
+ CHECK(attr->type == PERF_TYPE_HARDWARE);
+ CHECK(attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
+
+ return 0;
+}
+
+static int do_checks(void *data, const struct perf_dlfilter_sample *sample, void *ctx, bool early)
+{
+ struct filter_data *d = data;
+
+ CHECK(data && filt_dat == data);
+
+ if (early) {
+ CHECK(!d->early_filter_cnt);
+ d->early_filter_cnt += 1;
+ } else {
+ CHECK(!d->filter_cnt);
+ CHECK(d->early_filter_cnt);
+ CHECK(d->do_early != 2);
+ d->filter_cnt += 1;
+ }
+
+ if (check_sample(data, sample))
+ return -1;
+
+ if (check_attr(ctx))
+ return -1;
+
+ if (early && !d->do_early)
+ return 0;
+
+ if (check_al(ctx) || check_addr_al(ctx))
+ return -1;
+
+ if (early)
+ return d->do_early == 2;
+
+ return 1;
+}
+
+int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
+{
+ pr_debug("%s API\n", __func__);
+
+ return do_checks(data, sample, ctx, true);
+}
+
+int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
+{
+ struct filter_data *d = data;
+
+ pr_debug("%s API\n", __func__);
+
+ return do_checks(data, sample, ctx, false);
+}
+
+int stop(void *data, void *ctx)
+{
+ static bool called;
+
+ pr_debug("%s API\n", __func__);
+
+ CHECK(data && filt_dat == data && !called);
+ called = true;
+
+ free(data);
+ filt_dat = NULL;
+ return 0;
+}
+
+const char *filter_description(const char **long_description)
+{
+ *long_description = "Filter used by the 'dlfilter C API' perf test";
+ return "dlfilter to test v0 C API";
+}
diff --git a/tools/perf/util/perf_dlfilter.h b/tools/perf/include/perf/perf_dlfilter.h
index 3eef03d661b4..3eef03d661b4 100644
--- a/tools/perf/util/perf_dlfilter.h
+++ b/tools/perf/include/perf/perf_dlfilter.h
diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
index 215ba30b8534..a055dee6a46a 100644
--- a/tools/perf/pmu-events/Build
+++ b/tools/perf/pmu-events/Build
@@ -6,10 +6,13 @@ pmu-events-y += pmu-events.o
JDIR = pmu-events/arch/$(SRCARCH)
JSON = $(shell [ -d $(JDIR) ] && \
find $(JDIR) -name '*.json' -o -name 'mapfile.csv')
+JDIR_TEST = pmu-events/arch/test
+JSON_TEST = $(shell [ -d $(JDIR_TEST) ] && \
+ find $(JDIR_TEST) -name '*.json')
#
# Locate/process JSON files in pmu-events/arch/
# directory and create tables in pmu-events.c.
#
-$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JEVENTS)
+$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JSON_TEST) $(JEVENTS)
$(Q)$(call echo-cmd,gen)$(JEVENTS) $(SRCARCH) pmu-events/arch $(OUTPUT)pmu-events/pmu-events.c $(V)
diff --git a/tools/perf/pmu-events/arch/test/test_cpu/branch.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/branch.json
index 93ddfd8053ca..93ddfd8053ca 100644
--- a/tools/perf/pmu-events/arch/test/test_cpu/branch.json
+++ b/tools/perf/pmu-events/arch/test/test_soc/cpu/branch.json
diff --git a/tools/perf/pmu-events/arch/test/test_cpu/cache.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/cache.json
index 036d0efdb2bb..036d0efdb2bb 100644
--- a/tools/perf/pmu-events/arch/test/test_cpu/cache.json
+++ b/tools/perf/pmu-events/arch/test/test_soc/cpu/cache.json
diff --git a/tools/perf/pmu-events/arch/test/test_cpu/other.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/other.json
index 7d53d7ecd723..7d53d7ecd723 100644
--- a/tools/perf/pmu-events/arch/test/test_cpu/other.json
+++ b/tools/perf/pmu-events/arch/test/test_soc/cpu/other.json
diff --git a/tools/perf/pmu-events/arch/test/test_cpu/uncore.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json
index d0a890cc814d..788766f45dbc 100644
--- a/tools/perf/pmu-events/arch/test/test_cpu/uncore.json
+++ b/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json
@@ -17,5 +17,26 @@
"CounterMask": "0",
"Invert": "0",
"EdgeDetect": "0"
- }
+ },
+ {
+ "EventCode": "0x7",
+ "EventName": "uncore_hisi_l3c.rd_hit_cpipe",
+ "BriefDescription": "Total read hits",
+ "PublicDescription": "Total read hits",
+ "Unit": "hisi_sccl,l3c"
+ },
+ {
+ "EventCode": "0x12",
+ "EventName": "uncore_imc_free_running.cache_miss",
+ "BriefDescription": "Total cache misses",
+ "PublicDescription": "Total cache misses",
+ "Unit": "imc_free_running"
+ },
+ {
+ "EventCode": "0x34",
+ "EventName": "uncore_imc.cache_hits",
+ "BriefDescription": "Total cache hits",
+ "PublicDescription": "Total cache hits",
+ "Unit": "imc"
+ },
]
diff --git a/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json b/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json
new file mode 100644
index 000000000000..0f681a6e10ea
--- /dev/null
+++ b/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json
@@ -0,0 +1,9 @@
+[
+ {
+ "BriefDescription": "ddr write-cycles event",
+ "EventCode": "0x2b",
+ "EventName": "sys_ddr_pmu.write_cycles",
+ "Unit": "sys_ddr_pmu",
+ "Compat": "v8"
+ },
+]
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/cache.json b/tools/perf/pmu-events/arch/x86/cascadelakex/cache.json
index 3c0f5837480f..ffafb9f284d2 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/cache.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/cache.json
@@ -1,61 +1,125 @@
[
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "L1D data line replacements",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400028000",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x51",
+ "EventName": "L1D.REPLACEMENT",
+ "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Number of times a request needed a FB entry but there was no entry available for it. That is the FB unavailability was dominant reason for blocking the request. A request includes cacheable/uncacheable demands that is load, store or SW prefetch.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400002",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "PublicDescription": "Number of times a request needed a FB (Fill Buffer) entry but there was no entry available for it. A request includes cacheable/uncacheable demands that are load, store or SW prefetch instructions.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "L1D miss outstandings duration in cycles",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "PublicDescription": "Counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch.Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0004",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "PublicDescription": "Counts duration of L1D miss outstanding in cycles.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "AnyThread": "1",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200491",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "L2 cache lines filling L2",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF1",
+ "EventName": "L2_LINES_IN.ALL",
+ "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
"SampleAfterValue": "100003",
+ "UMask": "0x1f"
+ },
+ {
+ "BriefDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF2",
+ "EventName": "L2_LINES_OUT.NON_SILENT",
+ "PublicDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of lines that are silently dropped by L2 cache when triggered by an L2 cache fill. These lines are typically in Shared state. A non-threaded event.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF2",
+ "EventName": "L2_LINES_OUT.SILENT",
+ "SampleAfterValue": "200003",
"UMask": "0x1"
},
{
+ "BriefDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF2",
+ "EventName": "L2_LINES_OUT.USELESS_HWPF",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event L2_LINES_OUT.USELESS_HWPF",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Deprecated": "1",
+ "EventCode": "0xF2",
+ "EventName": "L2_LINES_OUT.USELESS_PREF",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "L2 code requests",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "PublicDescription": "Counts the total number of L2 code requests.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe4"
+ },
+ {
+ "BriefDescription": "Demand Data Read requests",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "PublicDescription": "Counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe1"
+ },
+ {
"BriefDescription": "Demand requests that miss L2 cache",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -66,34 +130,427 @@
"UMask": "0x27"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Demand requests to L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "PublicDescription": "Demand requests to L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe7"
+ },
+ {
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "PublicDescription": "Counts the total number of requests from the L2 hardware prefetchers.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xf8"
+ },
+ {
+ "BriefDescription": "RFO requests to L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe2"
+ },
+ {
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc4"
+ },
+ {
+ "BriefDescription": "L2 cache misses when fetching instructions",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "PublicDescription": "Counts L2 cache misses when fetching instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x24"
+ },
+ {
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "PublicDescription": "Counts the number of demand Data Read requests, initiated by load instructions, that hit L2 cache",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc1"
+ },
+ {
+ "BriefDescription": "Demand Data Read miss L2, no rejects",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "PublicDescription": "Counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x21"
+ },
+ {
+ "BriefDescription": "All requests that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.MISS",
+ "PublicDescription": "All requests that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x3f"
+ },
+ {
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.PF_HIT",
+ "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xd8"
+ },
+ {
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.PF_MISS",
+ "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x38"
+ },
+ {
+ "BriefDescription": "All L2 requests",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "PublicDescription": "All L2 requests.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xff"
+ },
+ {
+ "BriefDescription": "RFO requests that hit L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc2"
+ },
+ {
+ "BriefDescription": "RFO requests that miss L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x22"
+ },
+ {
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF0",
+ "EventName": "L2_TRANS.L2_WB",
+ "PublicDescription": "Counts L2 writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Core-originated cacheable demand requests missed L3",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Errata": "SKL057",
+ "EventCode": "0x2E",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "PublicDescription": "Counts core-originated cacheable requests that miss the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches from L1 and L2. It does not include all misses to the L3.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x41"
+ },
+ {
+ "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Errata": "SKL057",
+ "EventCode": "0x2E",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "PublicDescription": "Counts core-originated cacheable requests to the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches from L1 and L2. It does not include all accesses to the L3.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4f"
+ },
+ {
+ "BriefDescription": "All retired load instructions.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040491",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.ALL_LOADS",
+ "PEBS": "1",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x81"
+ },
+ {
+ "BriefDescription": "All retired store instructions.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.ALL_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x82"
+ },
+ {
+ "BriefDescription": "Retired load instructions with locked access.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.LOCK_LOADS",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "UMask": "0x21"
+ },
+ {
+ "BriefDescription": "Retired load instructions that split across a cacheline boundary.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.SPLIT_LOADS",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.",
"SampleAfterValue": "100003",
+ "UMask": "0x41"
+ },
+ {
+ "BriefDescription": "Retired store instructions that split across a cacheline boundary.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.SPLIT_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x42"
+ },
+ {
+ "BriefDescription": "Retired load instructions that miss the STLB.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
+ "PEBS": "1",
+ "SampleAfterValue": "100003",
+ "UMask": "0x11"
+ },
+ {
+ "BriefDescription": "Retired store instructions that miss the STLB.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "SampleAfterValue": "100003",
+ "UMask": "0x12"
+ },
+ {
+ "BriefDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "SampleAfterValue": "20011",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Retired load instructions which data sources were HitM responses from shared L3",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were HitM responses from shared L3.",
+ "SampleAfterValue": "20011",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Retired load instructions which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS",
+ "PEBS": "1",
+ "SampleAfterValue": "20011",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "Retired load instructions which data sources were hits in L3 without snoops required",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.SNOOP_MISS",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040010",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xD2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were hits in L3 without snoops required.",
"SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from local dram",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD3",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.LOCAL_DRAM",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources missed L3 but serviced from local DRAM.",
+ "SampleAfterValue": "100007",
"UMask": "0x1"
},
{
+ "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from remote dram",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD3",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_DRAM",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Retired load instructions whose data sources was forwarded from a remote cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD3",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_FWD",
+ "PublicDescription": "Retired load instructions whose data sources was forwarded from a remote cache.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Retired load instructions whose data sources was remote HITM",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD3",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_HITM",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions whose data sources was remote HITM.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Retired load instructions with remote Intel Optane DC persistent memory as the data source where the data request missed all caches. Precise event.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "ELLC": "1",
+ "EventCode": "0xD3",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_PMM",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with remote Intel Optane DC persistent memory as the data source and the data request missed L3 (AppDirect or Memory Mode) and DRAM cache(Memory Mode). Precise event",
+ "SampleAfterValue": "100007",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Retired instructions with at least 1 uncacheable load or lock.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD4",
+ "EventName": "MEM_LOAD_MISC_RETIRED.UC",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Retired load instructions which data sources were load missed L1 but hit FB due to preceding miss to the same cache line with data not ready",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.FB_HIT",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Retired load instructions with L1 cache hits as data sources",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L1_HIT",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired load instructions missed L1 cache as data sources",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L1_MISS",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L1 cache.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Retired load instructions with L2 cache hits as data sources",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions with L2 cache hits as data sources.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Retired load instructions missed L2 cache as data sources",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L2_MISS",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions missed L2 cache as data sources.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x10"
+ },
+ {
"BriefDescription": "Retired load instructions with L3 cache hits as data sources",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
@@ -106,2157 +563,2121 @@
"UMask": "0x4"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Retired load instructions missed L3 cache as data sources",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400001",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L3_MISS",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Retired load instructions with local Intel Optane DC persistent memory as the data source where the data request missed all caches. Precise event.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "ELLC": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.LOCAL_PMM",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with local Intel Optane DC persistent memory as the data source and the data request missed L3 (AppDirect or Memory Mode) and DRAM cache(Memory Mode). Precise event",
+ "SampleAfterValue": "100003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Demand and prefetch data reads",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Any memory transaction that reached the SQ.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS",
+ "PublicDescription": "Counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, etc..",
+ "SampleAfterValue": "100003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "PublicDescription": "Counts both cacheable and non-cacheable code read requests.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0491",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "PublicDescription": "Counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
"SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB2",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "PublicDescription": "Counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.Note: Writeback pending FIFO has six entries.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "L2 writebacks that access L2 cache",
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF0",
- "EventName": "L2_TRANS.L2_WB",
- "PublicDescription": "Counts L2 writebacks that access L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0x40"
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "PublicDescription": "Counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "L2 cache lines filling L2",
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF1",
- "EventName": "L2_LINES_IN.ALL",
- "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
- "SampleAfterValue": "100003",
- "UMask": "0x1f"
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "PublicDescription": "Counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "Cycles with offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_CODE_RD",
+ "PublicDescription": "Counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "PublicDescription": "Counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "PublicDescription": "Counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore, every cycle.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "PublicDescription": "Counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "PublicDescription": "Counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.Note: A prefetch promoted to Demand is counted from the promotion point.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "6",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "PublicDescription": "Counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.SNOOP_NONE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200002",
- "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0010",
+ "MSRValue": "0x0000010491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020004",
+ "MSRValue": "0x3F803C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040080",
+ "MSRValue": "0x10003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08000807F7",
+ "MSRValue": "0x08003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts the number of lines that are silently dropped by L2 cache when triggered by an L2 cache fill. These lines are typically in Shared state. A non-threaded event.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF2",
- "EventName": "L2_LINES_OUT.SILENT",
- "SampleAfterValue": "200003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080080",
+ "MSRValue": "0x04003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100020",
+ "MSRValue": "0x01003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080004",
+ "MSRValue": "0x08007C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0080",
+ "MSRValue": "0x02003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200001",
+ "MSRValue": "0x00803C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020491",
+ "MSRValue": "0x3F80080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100001",
+ "MSRValue": "0x1000080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200004",
+ "MSRValue": "0x0800080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0100",
+ "MSRValue": "0x0400080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100080",
+ "MSRValue": "0x0100080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200020",
+ "MSRValue": "0x0200080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200100",
+ "MSRValue": "0x0080080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040020",
+ "MSRValue": "0x3F80200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020490",
+ "MSRValue": "0x1000200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200490",
+ "MSRValue": "0x0800200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80028000",
+ "MSRValue": "0x0400200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F804007F7",
+ "MSRValue": "0x0100200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100400",
+ "MSRValue": "0x0200200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020400",
+ "MSRValue": "0x0080200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040400",
+ "MSRValue": "0x3F80040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "All requests that miss L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.MISS",
- "PublicDescription": "All requests that miss L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0x3f"
- },
- {
- "BriefDescription": "Retired load instructions whose data sources was forwarded from a remote cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_FWD",
- "PublicDescription": "Retired load instructions whose data sources was forwarded from a remote cache.",
- "SampleAfterValue": "100007",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400490",
+ "MSRValue": "0x1000040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0400",
+ "MSRValue": "0x0800040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400490",
+ "MSRValue": "0x0400040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020491",
+ "MSRValue": "0x0100040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD2",
- "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
- "SampleAfterValue": "20011",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040001",
+ "MSRValue": "0x0200040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100122",
+ "MSRValue": "0x0080040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0080",
+ "MSRValue": "0x3F80100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions missed L1 cache as data sources",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L1_MISS",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L1 cache.",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x1000100491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x8"
+ "UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800108000",
+ "MSRValue": "0x0800100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020122",
+ "MSRValue": "0x0400100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020080",
+ "MSRValue": "0x0100100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200010",
+ "MSRValue": "0x0200100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100002",
+ "MSRValue": "0x0080100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100020",
+ "MSRValue": "0x3F80400491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400002",
+ "MSRValue": "0x0080400491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200048000",
+ "MSRValue": "0x0100400491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080400",
+ "MSRValue": "0x3F80020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200122",
+ "MSRValue": "0x1000020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040001",
+ "MSRValue": "0x0800020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080122",
+ "MSRValue": "0x0400020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020122",
+ "MSRValue": "0x0100020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200122",
+ "MSRValue": "0x0200020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "AnyThread": "1",
- "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x48",
- "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400208000",
+ "MSRValue": "0x0080020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100010",
+ "MSRValue": "0x0000010490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020080",
+ "MSRValue": "0x3F803C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100491",
+ "MSRValue": "0x10003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200020",
+ "MSRValue": "0x08003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Any memory transaction that reached the SQ.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS",
- "PublicDescription": "Counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, etc..",
- "SampleAfterValue": "100003",
- "UMask": "0x80"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200010",
+ "MSRValue": "0x04003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200120",
+ "MSRValue": "0x01003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040120",
+ "MSRValue": "0x08007C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100048000",
+ "MSRValue": "0x02003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000028000",
+ "MSRValue": "0x00803C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200400",
+ "MSRValue": "0x3F80080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0010",
+ "MSRValue": "0x1000080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions with at least 1 uncacheable load or lock.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD4",
- "EventName": "MEM_LOAD_MISC_RETIRED.UC",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Retired load instructions with remote Intel\u00ae Optane\u2122 DC persistent memory as the data source where the data request missed all caches. Precise event.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "ELLC": "1",
- "EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_PMM",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with remote Intel\u00ae Optane\u2122 DC persistent memory as the data source and the data request missed L3 (AppDirect or Memory Mode) and DRAM cache(Memory Mode). Precise event",
- "SampleAfterValue": "100007",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080122",
+ "MSRValue": "0x0800080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080400",
+ "MSRValue": "0x0400080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02000807F7",
+ "MSRValue": "0x0100080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0490",
+ "MSRValue": "0x0200080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080002",
+ "MSRValue": "0x0080080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080010",
+ "MSRValue": "0x3F80200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400001",
+ "MSRValue": "0x1000200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010490",
+ "MSRValue": "0x0800200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources were hits in L3 without snoops required",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD2",
- "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions which data sources were hits in L3 without snoops required.",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0400200490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x8"
+ "UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400122",
+ "MSRValue": "0x0100200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read requests",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
- "PublicDescription": "Counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
- "SampleAfterValue": "200003",
- "UMask": "0xe1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200020",
+ "MSRValue": "0x0200200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040491",
+ "MSRValue": "0x0080200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040010",
+ "MSRValue": "0x3F80040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0001",
+ "MSRValue": "0x1000040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200028000",
+ "MSRValue": "0x0800040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
- "PublicDescription": "Counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100001",
+ "MSRValue": "0x0400040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of cache line split locks sent to uncore.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF4",
- "EventName": "SQ_MISC.SPLIT_LOCK",
- "PublicDescription": "Counts the number of cache line split locks sent to the uncore.",
- "SampleAfterValue": "100003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200100",
+ "MSRValue": "0x0100040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100002",
+ "MSRValue": "0x0200040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.CODE_RD_HIT",
- "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.",
- "SampleAfterValue": "200003",
- "UMask": "0xc4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200120",
+ "MSRValue": "0x0080040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020010",
+ "MSRValue": "0x3F80100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10001007F7",
+ "MSRValue": "0x1000100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040122",
+ "MSRValue": "0x0800100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100010",
+ "MSRValue": "0x0400100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02001007F7",
+ "MSRValue": "0x0100100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020120",
+ "MSRValue": "0x0200100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040120",
+ "MSRValue": "0x0080100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040020",
+ "MSRValue": "0x3F80400490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08001007F7",
+ "MSRValue": "0x0080400490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C07F7",
+ "MSRValue": "0x0100400490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0004",
+ "MSRValue": "0x3F80020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources were HitM responses from shared L3",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD2",
- "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions which data sources were HitM responses from shared L3.",
- "SampleAfterValue": "20011",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200020",
+ "MSRValue": "0x1000020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200080",
+ "MSRValue": "0x0800020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400048000",
+ "MSRValue": "0x0400020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired store instructions that split across a cacheline boundary.",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.SPLIT_STORES",
- "L1_Hit_Indication": "1",
- "PEBS": "1",
- "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0100020490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x42"
+ "UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010122",
+ "MSRValue": "0x0200020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100120",
+ "MSRValue": "0x0080020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010002",
+ "MSRValue": "0x0000010120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020491",
+ "MSRValue": "0x3F803C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100120",
+ "MSRValue": "0x10003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010001",
+ "MSRValue": "0x08003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080400",
+ "MSRValue": "0x04003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400080",
+ "MSRValue": "0x01003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0122",
+ "MSRValue": "0x08007C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400080",
+ "MSRValue": "0x02003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080120",
+ "MSRValue": "0x00803C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080001",
+ "MSRValue": "0x3F80080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100491",
+ "MSRValue": "0x1000080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100002",
+ "MSRValue": "0x0800080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400100",
+ "MSRValue": "0x0400080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080001",
+ "MSRValue": "0x0100080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010004",
+ "MSRValue": "0x0200080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100490",
+ "MSRValue": "0x0080080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040004",
+ "MSRValue": "0x3F80200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400020",
+ "MSRValue": "0x1000200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C8000",
+ "MSRValue": "0x0800200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020100",
+ "MSRValue": "0x0400200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200020",
+ "MSRValue": "0x0100200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200400",
+ "MSRValue": "0x0200200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040120",
+ "MSRValue": "0x0080200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0400",
+ "MSRValue": "0x3F80040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040020",
+ "MSRValue": "0x1000040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100120",
+ "MSRValue": "0x0800040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400002",
+ "MSRValue": "0x0400040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040491",
+ "MSRValue": "0x0100040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times a request needed a FB entry but there was no entry available for it. That is the FB unavailability was dominant reason for blocking the request. A request includes cacheable/uncacheable demands that is load, store or SW prefetch.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x48",
- "EventName": "L1D_PEND_MISS.FB_FULL",
- "PublicDescription": "Number of times a request needed a FB (Fill Buffer) entry but there was no entry available for it. A request includes cacheable/uncacheable demands that are load, store or SW prefetch instructions.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0200040120",
+ "Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020020",
+ "MSRValue": "0x0080040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0120",
+ "MSRValue": "0x3F80100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020010",
+ "MSRValue": "0x1000100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200490",
+ "MSRValue": "0x0800100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0100",
+ "MSRValue": "0x0400100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040001",
+ "MSRValue": "0x0100100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB2",
- "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
- "PublicDescription": "Counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.Note: Writeback pending FIFO has six entries.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200020",
+ "MSRValue": "0x0200100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200490",
+ "MSRValue": "0x0080100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0100",
+ "MSRValue": "0x3F80400120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400491",
+ "MSRValue": "0x0080400120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10000207F7",
+ "MSRValue": "0x0100400120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080120",
+ "MSRValue": "0x3F80020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions missed L2 cache as data sources",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L2_MISS",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions missed L2 cache as data sources.",
- "SampleAfterValue": "50021",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0122",
+ "MSRValue": "0x1000020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200400",
+ "MSRValue": "0x0800020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400004",
+ "MSRValue": "0x0400020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -2277,3204 +2698,3038 @@
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200100",
+ "MSRValue": "0x0200020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040080",
+ "MSRValue": "0x0080020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200088000",
+ "MSRValue": "0x00000107F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C8000",
+ "MSRValue": "0x3F803C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200001",
+ "MSRValue": "0x10003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080020",
+ "MSRValue": "0x08003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400490",
+ "MSRValue": "0x04003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400400",
+ "MSRValue": "0x01003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400020",
+ "MSRValue": "0x08007C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.PF_MISS",
- "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0x38"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08000407F7",
+ "MSRValue": "0x02003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200100",
+ "MSRValue": "0x00803C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080004",
+ "MSRValue": "0x3F800807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040400",
+ "MSRValue": "0x10000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100004",
+ "MSRValue": "0x08000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080080",
+ "MSRValue": "0x04000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10000407F7",
+ "MSRValue": "0x01000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00800207F7",
+ "MSRValue": "0x02000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0491",
+ "MSRValue": "0x00800807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010080",
+ "MSRValue": "0x3F802007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020122",
+ "MSRValue": "0x10002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0122",
+ "MSRValue": "0x08002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080001",
+ "MSRValue": "0x04002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020491",
+ "MSRValue": "0x01002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040001",
+ "MSRValue": "0x02002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400122",
+ "MSRValue": "0x00802007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010020",
+ "MSRValue": "0x3F800407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0490",
+ "MSRValue": "0x10000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020020",
+ "MSRValue": "0x08000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100122",
+ "MSRValue": "0x04000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200001",
+ "MSRValue": "0x01000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020080",
+ "MSRValue": "0x02000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040010",
+ "MSRValue": "0x00800407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080100",
+ "MSRValue": "0x3F801007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020490",
+ "MSRValue": "0x10001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08000207F7",
+ "MSRValue": "0x08001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions missed L3 cache as data sources",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L3_MISS",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache.",
- "SampleAfterValue": "100007",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200100",
+ "MSRValue": "0x04001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020002",
+ "MSRValue": "0x01001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080028000",
+ "MSRValue": "0x02001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020491",
+ "MSRValue": "0x00801007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080120",
+ "MSRValue": "0x3F804007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0120",
+ "MSRValue": "0x00804007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0010",
+ "MSRValue": "0x01004007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020020",
+ "MSRValue": "0x3F800207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020100",
+ "MSRValue": "0x10000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core-originated cacheable demand requests missed L3",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL057",
- "EventCode": "0x2E",
- "EventName": "LONGEST_LAT_CACHE.MISS",
- "PublicDescription": "Counts core-originated cacheable requests that miss the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches from L1 and L2. It does not include all misses to the L3.",
- "SampleAfterValue": "100003",
- "UMask": "0x41"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200490",
+ "MSRValue": "0x08000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200080",
+ "MSRValue": "0x04000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080120",
+ "MSRValue": "0x01000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020010",
+ "MSRValue": "0x02000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0120",
+ "MSRValue": "0x00800207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020400",
+ "MSRValue": "0x0000010122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100400",
+ "MSRValue": "0x3F803C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C8000",
+ "MSRValue": "0x10003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0400",
+ "MSRValue": "0x08003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040120",
+ "MSRValue": "0x04003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0100",
+ "MSRValue": "0x01003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200002",
+ "MSRValue": "0x08007C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0490",
+ "MSRValue": "0x02003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200100",
+ "MSRValue": "0x00803C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01004007F7",
+ "MSRValue": "0x3F80080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080120",
+ "MSRValue": "0x1000080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
- "PublicDescription": "Counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0491",
+ "MSRValue": "0x0800080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100100",
+ "MSRValue": "0x0400080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020100",
+ "MSRValue": "0x0100080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080010",
+ "MSRValue": "0x0200080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400010",
+ "MSRValue": "0x0080080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF2",
- "EventName": "L2_LINES_OUT.NON_SILENT",
- "PublicDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped.",
- "SampleAfterValue": "200003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040010",
+ "MSRValue": "0x3F80200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00804007F7",
+ "MSRValue": "0x1000200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0020",
+ "MSRValue": "0x0800200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100100",
+ "MSRValue": "0x0400200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "RFO requests that hit L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.RFO_HIT",
- "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0xc2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100080",
+ "MSRValue": "0x0100200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200001",
+ "MSRValue": "0x0200200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020100",
+ "MSRValue": "0x0080200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
- "PublicDescription": "Counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400108000",
+ "MSRValue": "0x3F80040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00000107F7",
+ "MSRValue": "0x1000040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F800807F7",
+ "MSRValue": "0x0800040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040004",
+ "MSRValue": "0x0400040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020001",
+ "MSRValue": "0x0100040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100122",
+ "MSRValue": "0x0200040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100122",
+ "MSRValue": "0x0080040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0001",
+ "MSRValue": "0x3F80100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080002",
+ "MSRValue": "0x1000100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040010",
+ "MSRValue": "0x0800100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200010",
+ "MSRValue": "0x0400100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100100",
+ "MSRValue": "0x0100100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200001",
+ "MSRValue": "0x0200100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080408000",
+ "MSRValue": "0x0080100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040400",
+ "MSRValue": "0x3F80400122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040400",
+ "MSRValue": "0x0080400122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080491",
+ "MSRValue": "0x0100400122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0491",
+ "MSRValue": "0x3F80020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200080",
+ "MSRValue": "0x1000020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040122",
+ "MSRValue": "0x0800020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080088000",
+ "MSRValue": "0x0400020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040490",
+ "MSRValue": "0x0100020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0080",
+ "MSRValue": "0x0200020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100122",
+ "MSRValue": "0x0080020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020004",
+ "MSRValue": "0x0000010004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100080",
+ "MSRValue": "0x3F803C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200080",
+ "MSRValue": "0x10003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0002",
+ "MSRValue": "0x08003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080100",
+ "MSRValue": "0x04003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F801007F7",
+ "MSRValue": "0x01003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100400",
+ "MSRValue": "0x08007C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020400",
+ "MSRValue": "0x02003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040490",
+ "MSRValue": "0x00803C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100002",
+ "MSRValue": "0x3F80080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0002",
+ "MSRValue": "0x1000080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080048000",
+ "MSRValue": "0x0800080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "L1D data line replacements",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x51",
- "EventName": "L1D.REPLACEMENT",
- "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020010",
+ "MSRValue": "0x0400080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0010",
+ "MSRValue": "0x0100080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200010",
+ "MSRValue": "0x0200080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080122",
+ "MSRValue": "0x0080080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200010",
+ "MSRValue": "0x3F80200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200122",
+ "MSRValue": "0x1000200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040490",
+ "MSRValue": "0x0800200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100002",
+ "MSRValue": "0x0400200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080491",
+ "MSRValue": "0x0100200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read requests that hit L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
- "PublicDescription": "Counts the number of demand Data Read requests, initiated by load instructions, that hit L2 cache",
- "SampleAfterValue": "200003",
- "UMask": "0xc1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C07F7",
+ "MSRValue": "0x0200200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100010",
+ "MSRValue": "0x0080200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "All retired load instructions.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.ALL_LOADS",
- "PEBS": "1",
- "SampleAfterValue": "2000003",
- "UMask": "0x81"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200400",
+ "MSRValue": "0x3F80040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0080",
+ "MSRValue": "0x1000040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000108000",
+ "MSRValue": "0x0800040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020010",
+ "MSRValue": "0x0400040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080010",
+ "MSRValue": "0x0100040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040491",
+ "MSRValue": "0x0200040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800208000",
+ "MSRValue": "0x0080040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010010",
+ "MSRValue": "0x3F80100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020080",
+ "MSRValue": "0x1000100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080208000",
+ "MSRValue": "0x0800100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100002",
+ "MSRValue": "0x0400100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100020",
+ "MSRValue": "0x0100100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100020",
+ "MSRValue": "0x0200100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080100",
+ "MSRValue": "0x0080100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200002",
+ "MSRValue": "0x3F80400004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100120",
+ "MSRValue": "0x0080400004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200490",
+ "MSRValue": "0x0100400004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0100",
+ "MSRValue": "0x3F80020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080491",
+ "MSRValue": "0x1000020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100122",
+ "MSRValue": "0x0800020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040004",
+ "MSRValue": "0x0400020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040100",
+ "MSRValue": "0x0100020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080020",
+ "MSRValue": "0x0200020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0001",
+ "MSRValue": "0x0080020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020080",
+ "MSRValue": "0x0000010001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080100",
+ "MSRValue": "0x3F803C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200010",
+ "MSRValue": "0x10003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80108000",
+ "MSRValue": "0x08003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0490",
+ "MSRValue": "0x04003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080490",
+ "MSRValue": "0x01003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10000807F7",
+ "MSRValue": "0x08007C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020004",
+ "MSRValue": "0x02003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020002",
+ "MSRValue": "0x00803C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040400",
+ "MSRValue": "0x3F80080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
- "PublicDescription": "Counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080020",
+ "MSRValue": "0x1000080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0002",
+ "MSRValue": "0x0800080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0400",
+ "MSRValue": "0x0400080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200001",
+ "MSRValue": "0x0100080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200010",
+ "MSRValue": "0x0200080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010400",
+ "MSRValue": "0x0080080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000088000",
+ "MSRValue": "0x3F80200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0004",
+ "MSRValue": "0x1000200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
- "PublicDescription": "Counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200020",
+ "MSRValue": "0x0800200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080490",
+ "MSRValue": "0x0400200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080122",
+ "MSRValue": "0x0100200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400010",
+ "MSRValue": "0x0200200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040490",
+ "MSRValue": "0x0080200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040120",
+ "MSRValue": "0x3F80040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions that split across a cacheline boundary.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.SPLIT_LOADS",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.",
- "SampleAfterValue": "100003",
- "UMask": "0x41"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040080",
+ "MSRValue": "0x1000040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "6",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100491",
+ "MSRValue": "0x0800040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040100",
+ "MSRValue": "0x0400040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0122",
+ "MSRValue": "0x0100040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired store instructions that miss the STLB.",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
- "L1_Hit_Indication": "1",
- "PEBS": "1",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0200040001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x12"
+ "UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400001",
+ "MSRValue": "0x0080040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "RFO requests to L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_RFO",
- "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
- "SampleAfterValue": "200003",
- "UMask": "0xe2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400120",
+ "MSRValue": "0x3F80100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C07F7",
+ "MSRValue": "0x1000100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0004",
+ "MSRValue": "0x0800100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100010",
+ "MSRValue": "0x0400100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080122",
+ "MSRValue": "0x0100100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040080",
+ "MSRValue": "0x0200100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0020",
+ "MSRValue": "0x0080100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0004",
+ "MSRValue": "0x3F80400001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040491",
+ "MSRValue": "0x0080400001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0080",
+ "MSRValue": "0x0100400001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100120",
+ "MSRValue": "0x3F80020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0020",
+ "MSRValue": "0x1000020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100490",
+ "MSRValue": "0x0800020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C07F7",
+ "MSRValue": "0x0400020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040020",
+ "MSRValue": "0x0100020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01001007F7",
+ "MSRValue": "0x0200020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040122",
+ "MSRValue": "0x0080020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100028000",
+ "MSRValue": "0x0000010002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02000407F7",
+ "MSRValue": "0x3F803C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020122",
+ "MSRValue": "0x10003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080490",
+ "MSRValue": "0x08003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080400",
+ "MSRValue": "0x04003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080004",
+ "MSRValue": "0x01003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0001",
+ "MSRValue": "0x08007C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100004",
+ "MSRValue": "0x02003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400491",
+ "MSRValue": "0x00803C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080004",
+ "MSRValue": "0x3F80080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020001",
+ "MSRValue": "0x1000080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200004",
+ "MSRValue": "0x0800080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400088000",
+ "MSRValue": "0x0400080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040010",
+ "MSRValue": "0x0100080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100400",
+ "MSRValue": "0x0200080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020400",
+ "MSRValue": "0x0080080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040100",
+ "MSRValue": "0x3F80200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100088000",
+ "MSRValue": "0x1000200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100491",
+ "MSRValue": "0x0800200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200080",
+ "MSRValue": "0x0400200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020020",
+ "MSRValue": "0x0100200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_PF",
- "PublicDescription": "Counts the total number of requests from the L2 hardware prefetchers.",
- "SampleAfterValue": "200003",
- "UMask": "0xf8"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200122",
+ "MSRValue": "0x0200200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100004",
+ "MSRValue": "0x0080200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080001",
+ "MSRValue": "0x3F80040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200400",
+ "MSRValue": "0x1000040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080491",
+ "MSRValue": "0x0800040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080490",
+ "MSRValue": "0x0400040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -5495,4482 +5750,4227 @@
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080080",
+ "MSRValue": "0x0200040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200400",
+ "MSRValue": "0x0080040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "L2 code requests",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_CODE_RD",
- "PublicDescription": "Counts the total number of L2 code requests.",
- "SampleAfterValue": "200003",
- "UMask": "0xe4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100010",
+ "MSRValue": "0x3F80100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020001",
+ "MSRValue": "0x1000100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080100",
+ "MSRValue": "0x0800100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0491",
+ "MSRValue": "0x0400100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040002",
+ "MSRValue": "0x0100100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand requests to L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
- "PublicDescription": "Demand requests to L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0xe7"
- },
- {
- "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from remote dram",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_DRAM",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F800207F7",
+ "MSRValue": "0x0200100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01000407F7",
+ "MSRValue": "0x0080100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080490",
+ "MSRValue": "0x3F80400002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100100",
+ "MSRValue": "0x0080400002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "L2 cache misses when fetching instructions",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.CODE_RD_MISS",
- "PublicDescription": "Counts L2 cache misses when fetching instructions.",
- "SampleAfterValue": "200003",
- "UMask": "0x24"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100080",
+ "MSRValue": "0x0100400002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080120",
+ "MSRValue": "0x3F80020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040100",
+ "MSRValue": "0x1000020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080491",
+ "MSRValue": "0x0800020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
- "PublicDescription": "Counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.Note: A prefetch promoted to Demand is counted from the promotion point.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0122",
+ "MSRValue": "0x0400020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200004",
+ "MSRValue": "0x0100020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04000407F7",
+ "MSRValue": "0x0200020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100020",
+ "MSRValue": "0x0080020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_CODE_RD",
- "PublicDescription": "Counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01000207F7",
+ "MSRValue": "0x0000018000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020122",
+ "MSRValue": "0x3F803C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040002",
+ "MSRValue": "0x10003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0100",
+ "MSRValue": "0x08003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040080",
+ "MSRValue": "0x04003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020490",
+ "MSRValue": "0x01003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100001",
+ "MSRValue": "0x08007C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040100",
+ "MSRValue": "0x02003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100490",
+ "MSRValue": "0x00803C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100004",
+ "MSRValue": "0x3F80088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL057",
- "EventCode": "0x2E",
- "EventName": "LONGEST_LAT_CACHE.REFERENCE",
- "PublicDescription": "Counts core-originated cacheable requests to the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches from L1 and L2. It does not include all accesses to the L3.",
- "SampleAfterValue": "100003",
- "UMask": "0x4f"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040002",
+ "MSRValue": "0x1000088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0002",
+ "MSRValue": "0x0800088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080020",
+ "MSRValue": "0x0400088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020001",
+ "MSRValue": "0x0100088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000208000",
+ "MSRValue": "0x0200088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080020",
+ "MSRValue": "0x0080088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0122",
+ "MSRValue": "0x3F80208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200002",
+ "MSRValue": "0x1000208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400100",
+ "MSRValue": "0x0800208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040491",
+ "MSRValue": "0x0400208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions that miss the STLB.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
- "PEBS": "1",
- "SampleAfterValue": "100003",
- "UMask": "0x11"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020100",
+ "MSRValue": "0x0100208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200122",
+ "MSRValue": "0x0200208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400010",
+ "MSRValue": "0x0080208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400080",
+ "MSRValue": "0x3F80048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0010",
+ "MSRValue": "0x1000048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200004",
+ "MSRValue": "0x0800048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions with local Intel\u00ae Optane\u2122 DC persistent memory as the data source where the data request missed all caches. Precise event.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "ELLC": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.LOCAL_PMM",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with local Intel\u00ae Optane\u2122 DC persistent memory as the data source and the data request missed L3 (AppDirect or Memory Mode) and DRAM cache(Memory Mode). Precise event",
- "SampleAfterValue": "100003",
- "UMask": "0x80"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0002",
+ "MSRValue": "0x0400048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040010",
+ "MSRValue": "0x0100048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010491",
+ "MSRValue": "0x0200048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0400",
+ "MSRValue": "0x0080048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200120",
+ "MSRValue": "0x3F80108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100490",
+ "MSRValue": "0x1000108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event L2_LINES_OUT.USELESS_HWPF",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Deprecated": "1",
- "EventCode": "0xF2",
- "EventName": "L2_LINES_OUT.USELESS_PREF",
- "SampleAfterValue": "200003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0122",
+ "MSRValue": "0x0800108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100491",
+ "MSRValue": "0x0400108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read miss L2, no rejects",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
- "PublicDescription": "Counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
- "SampleAfterValue": "200003",
- "UMask": "0x21"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080001",
+ "MSRValue": "0x0100108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020002",
+ "MSRValue": "0x0200108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD2",
- "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS",
- "PEBS": "1",
- "SampleAfterValue": "20011",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800028000",
+ "MSRValue": "0x0080108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0080",
+ "MSRValue": "0x3F80408000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0400",
+ "MSRValue": "0x0080408000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "All L2 requests",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.REFERENCES",
- "PublicDescription": "All L2 requests.",
- "SampleAfterValue": "200003",
- "UMask": "0xff"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100400",
+ "MSRValue": "0x0100408000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020400",
+ "MSRValue": "0x3F80028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with L1D load Misses outstanding.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x48",
- "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
- "PublicDescription": "Counts duration of L1D miss outstanding in cycles.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100020",
+ "MSRValue": "0x1000028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080108000",
+ "MSRValue": "0x0800028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080080",
+ "MSRValue": "0x0400028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100120",
+ "MSRValue": "0x0100028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0001",
+ "MSRValue": "0x0200028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040490",
+ "MSRValue": "0x0080028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020002",
+ "MSRValue": "0x0000010400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0120",
+ "MSRValue": "0x3F803C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080100",
+ "MSRValue": "0x10003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020120",
+ "MSRValue": "0x08003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040122",
+ "MSRValue": "0x04003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0491",
+ "MSRValue": "0x01003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C8000",
+ "MSRValue": "0x08007C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100491",
+ "MSRValue": "0x02003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0100",
+ "MSRValue": "0x00803C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02002007F7",
+ "MSRValue": "0x3F80080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200080",
+ "MSRValue": "0x1000080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400400",
+ "MSRValue": "0x0800080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020020",
+ "MSRValue": "0x0400080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020004",
+ "MSRValue": "0x0100080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00801007F7",
+ "MSRValue": "0x0200080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100100",
+ "MSRValue": "0x0080080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0010",
+ "MSRValue": "0x3F80200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0120",
+ "MSRValue": "0x1000200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020120",
+ "MSRValue": "0x0800200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100002",
+ "MSRValue": "0x0400200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200108000",
+ "MSRValue": "0x0100200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0080",
+ "MSRValue": "0x0200200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040120",
+ "MSRValue": "0x0080200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200491",
+ "MSRValue": "0x3F80040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080080",
+ "MSRValue": "0x1000040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020002",
+ "MSRValue": "0x0800040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200491",
+ "MSRValue": "0x0400040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400122",
+ "MSRValue": "0x0100040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800088000",
+ "MSRValue": "0x0200040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040122",
+ "MSRValue": "0x0080040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0490",
+ "MSRValue": "0x3F80100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01002007F7",
+ "MSRValue": "0x1000100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0400",
+ "MSRValue": "0x0800100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0491",
+ "MSRValue": "0x0400100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040002",
+ "MSRValue": "0x0100100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080002",
+ "MSRValue": "0x0200100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions with locked access.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.LOCK_LOADS",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "UMask": "0x21"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0002",
+ "MSRValue": "0x0080100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0001",
+ "MSRValue": "0x3F80400400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080100",
+ "MSRValue": "0x0080400400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040020",
+ "MSRValue": "0x0100400400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200400",
+ "MSRValue": "0x3F80020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "All retired store instructions.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.ALL_STORES",
- "L1_Hit_Indication": "1",
- "PEBS": "1",
- "SampleAfterValue": "2000003",
- "UMask": "0x82"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080400",
+ "MSRValue": "0x1000020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0001",
+ "MSRValue": "0x0800020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080004",
+ "MSRValue": "0x0400020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100120",
+ "MSRValue": "0x0100020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from local dram",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.LOCAL_DRAM",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions which data sources missed L3 but serviced from local DRAM.",
- "SampleAfterValue": "100007",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0200020400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020491",
+ "MSRValue": "0x0080020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040004",
+ "MSRValue": "0x0000010010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100080",
+ "MSRValue": "0x3F803C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400120",
+ "MSRValue": "0x10003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040004",
+ "MSRValue": "0x08003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04000207F7",
+ "MSRValue": "0x04003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020490",
+ "MSRValue": "0x01003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040490",
+ "MSRValue": "0x08007C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080002",
+ "MSRValue": "0x02003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100108000",
+ "MSRValue": "0x00803C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040400",
+ "MSRValue": "0x3F80080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200002",
+ "MSRValue": "0x1000080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040001",
+ "MSRValue": "0x0800080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080020",
+ "MSRValue": "0x0400080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0020",
+ "MSRValue": "0x0100080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080122",
+ "MSRValue": "0x0200080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040002",
+ "MSRValue": "0x0080080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000048000",
+ "MSRValue": "0x3F80200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01000807F7",
+ "MSRValue": "0x1000200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020004",
+ "MSRValue": "0x0800200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020001",
+ "MSRValue": "0x0400200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
- "PublicDescription": "Counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
- "SampleAfterValue": "100003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040491",
+ "MSRValue": "0x0100200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020010",
+ "MSRValue": "0x0200200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200100",
+ "MSRValue": "0x0080200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100080",
+ "MSRValue": "0x3F80040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040004",
+ "MSRValue": "0x1000040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040080",
+ "MSRValue": "0x0800040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040001",
+ "MSRValue": "0x0400040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020120",
+ "MSRValue": "0x0100040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02000207F7",
+ "MSRValue": "0x0200040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100001",
+ "MSRValue": "0x0080040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080400",
+ "MSRValue": "0x3F80100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read requests sent to uncore",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
- "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
+ "CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x1000100010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04001007F7",
+ "MSRValue": "0x0800100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0010",
+ "MSRValue": "0x0400100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200004",
+ "MSRValue": "0x0100100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040001",
+ "MSRValue": "0x0200100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0100",
+ "MSRValue": "0x0080100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100100",
+ "MSRValue": "0x3F80400010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0010",
+ "MSRValue": "0x0080400010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020490",
+ "MSRValue": "0x0100400010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040004",
+ "MSRValue": "0x3F80020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200080",
+ "MSRValue": "0x1000020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200120",
+ "MSRValue": "0x0800020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions whose data sources was remote HITM",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_HITM",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions whose data sources was remote HITM.",
- "SampleAfterValue": "100007",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080010",
+ "MSRValue": "0x0400020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020100",
+ "MSRValue": "0x0100020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040100",
+ "MSRValue": "0x0200020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000018000",
+ "MSRValue": "0x0080020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020020",
+ "MSRValue": "0x0000010020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200491",
+ "MSRValue": "0x3F803C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "RFO requests that miss L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.RFO_MISS",
- "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0x22"
- },
- {
- "BriefDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF2",
- "EventName": "L2_LINES_OUT.USELESS_HWPF",
- "SampleAfterValue": "200003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100010",
+ "MSRValue": "0x10003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080010",
+ "MSRValue": "0x08003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.PF_HIT",
- "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0xd8"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0080",
+ "MSRValue": "0x04003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100020",
+ "MSRValue": "0x01003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020002",
+ "MSRValue": "0x08007C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0020",
+ "MSRValue": "0x02003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020004",
+ "MSRValue": "0x00803C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100490",
+ "MSRValue": "0x3F80080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020001",
+ "MSRValue": "0x1000080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cacheable and noncachaeble code read requests",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
- "PublicDescription": "Counts both cacheable and non-cacheable code read requests.",
- "SampleAfterValue": "100003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400120",
+ "MSRValue": "0x0800080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100010",
+ "MSRValue": "0x0400080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040122",
+ "MSRValue": "0x0100080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020122",
+ "MSRValue": "0x0200080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100408000",
+ "MSRValue": "0x0080080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0122",
+ "MSRValue": "0x3F80200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200004",
+ "MSRValue": "0x1000200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80088000",
+ "MSRValue": "0x0800200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080004",
+ "MSRValue": "0x0400200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100001",
+ "MSRValue": "0x0100200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08002007F7",
+ "MSRValue": "0x0200200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100100",
+ "MSRValue": "0x0080200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020001",
+ "MSRValue": "0x3F80040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080080",
+ "MSRValue": "0x1000040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020002",
+ "MSRValue": "0x0800040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0120",
+ "MSRValue": "0x0400040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020004",
+ "MSRValue": "0x0100040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400100",
+ "MSRValue": "0x0200040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0020",
+ "MSRValue": "0x0080040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040020",
+ "MSRValue": "0x3F80100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020122",
+ "MSRValue": "0x1000100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040080",
+ "MSRValue": "0x0800100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080010",
+ "MSRValue": "0x0400100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040002",
+ "MSRValue": "0x0100100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80408000",
+ "MSRValue": "0x0200100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040120",
+ "MSRValue": "0x0080100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200122",
+ "MSRValue": "0x3F80400020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200001",
+ "MSRValue": "0x0080400020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100001",
+ "MSRValue": "0x0100400020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C07F7",
+ "MSRValue": "0x3F80020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C07F7",
+ "MSRValue": "0x1000020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0002",
+ "MSRValue": "0x0800020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040490",
+ "MSRValue": "0x0400020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100004",
+ "MSRValue": "0x0100020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080001",
+ "MSRValue": "0x0200020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010120",
+ "MSRValue": "0x0080020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00800407F7",
+ "MSRValue": "0x0000010080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080001",
+ "MSRValue": "0x3F803C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C07F7",
+ "MSRValue": "0x10003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020400",
+ "MSRValue": "0x08003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00800807F7",
+ "MSRValue": "0x04003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020491",
+ "MSRValue": "0x01003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100004",
+ "MSRValue": "0x08007C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100400",
+ "MSRValue": "0x02003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources were load missed L1 but hit FB due to preceding miss to the same cache line with data not ready",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.FB_HIT",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready.",
- "SampleAfterValue": "100007",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200120",
+ "MSRValue": "0x00803C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080010",
+ "MSRValue": "0x3F80080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080002",
+ "MSRValue": "0x1000080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080490",
+ "MSRValue": "0x0800080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100004",
+ "MSRValue": "0x0400080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080120",
+ "MSRValue": "0x0100080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020100",
+ "MSRValue": "0x0200080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F800407F7",
+ "MSRValue": "0x0080080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040400",
+ "MSRValue": "0x3F80200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080020",
+ "MSRValue": "0x1000200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200208000",
+ "MSRValue": "0x0800200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020490",
+ "MSRValue": "0x0400200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200122",
+ "MSRValue": "0x0100200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080002",
+ "MSRValue": "0x0200200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0001",
+ "MSRValue": "0x0080200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200491",
+ "MSRValue": "0x3F80040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080490",
+ "MSRValue": "0x1000040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80048000",
+ "MSRValue": "0x0800040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020080",
+ "MSRValue": "0x0400040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0490",
+ "MSRValue": "0x0100040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions with L2 cache hits as data sources",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L2_HIT",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions with L2 cache hits as data sources.",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0200040080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0020",
+ "MSRValue": "0x0080040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200490",
+ "MSRValue": "0x3F80100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400020",
+ "MSRValue": "0x1000100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00802007F7",
+ "MSRValue": "0x0800100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "L1D miss outstandings duration in cycles",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x48",
- "EventName": "L1D_PEND_MISS.PENDING",
- "PublicDescription": "Counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch.Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080002",
+ "MSRValue": "0x0400100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200004",
+ "MSRValue": "0x0100100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0004",
+ "MSRValue": "0x0200100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0002",
+ "MSRValue": "0x0080100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0120",
+ "MSRValue": "0x3F80400080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100490",
+ "MSRValue": "0x0080400080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200490",
+ "MSRValue": "0x0100400080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200120",
+ "MSRValue": "0x3F80020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080400",
+ "MSRValue": "0x1000020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0120",
+ "MSRValue": "0x0800020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400400",
+ "MSRValue": "0x0400020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200120",
+ "MSRValue": "0x0100020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020120",
+ "MSRValue": "0x0200020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200002",
+ "MSRValue": "0x0080020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.ANY_RESPONSE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0490",
+ "MSRValue": "0x0000010100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0491",
+ "MSRValue": "0x3F803C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080491",
+ "MSRValue": "0x10003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0020",
+ "MSRValue": "0x08003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0490",
+ "MSRValue": "0x04003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0004",
+ "MSRValue": "0x01003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C07F7",
+ "MSRValue": "0x08007C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020010",
+ "MSRValue": "0x02003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100491",
+ "MSRValue": "0x00803C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80208000",
+ "MSRValue": "0x3F80080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04000807F7",
+ "MSRValue": "0x1000080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0004",
+ "MSRValue": "0x0800080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C8000",
+ "MSRValue": "0x0400080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400004",
+ "MSRValue": "0x0100080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100080",
+ "MSRValue": "0x0200080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020020",
+ "MSRValue": "0x0080080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020120",
+ "MSRValue": "0x3F80200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400004",
+ "MSRValue": "0x1000200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400491",
+ "MSRValue": "0x0800200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10002007F7",
+ "MSRValue": "0x0400200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C8000",
+ "MSRValue": "0x0100200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080080",
+ "MSRValue": "0x0200200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020490",
+ "MSRValue": "0x0080200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100400",
+ "MSRValue": "0x3F80040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020400",
+ "MSRValue": "0x1000040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040020",
+ "MSRValue": "0x0800040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080122",
+ "MSRValue": "0x0400040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions with L1 cache hits as data sources",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L1_HIT",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Demand and prefetch data reads",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
- "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0100040100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x8"
+ "UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800048000",
+ "MSRValue": "0x0200040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100208000",
+ "MSRValue": "0x0080040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020080",
+ "MSRValue": "0x3F80100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0400",
+ "MSRValue": "0x1000100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200491",
+ "MSRValue": "0x0800100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C8000",
+ "MSRValue": "0x0400100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200002",
+ "MSRValue": "0x0100100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040122",
+ "MSRValue": "0x0200100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080491",
+ "MSRValue": "0x0080100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore, every cycle.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
- "PublicDescription": "Counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200491",
+ "MSRValue": "0x3F80400100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100490",
+ "MSRValue": "0x0080400100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040100",
+ "MSRValue": "0x0100400100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C8000",
+ "MSRValue": "0x3F80020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F802007F7",
+ "MSRValue": "0x1000020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100001",
+ "MSRValue": "0x0800020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100122",
+ "MSRValue": "0x0400020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04002007F7",
+ "MSRValue": "0x0100020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.ANY_RESPONSE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010100",
+ "MSRValue": "0x0200020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080004",
+ "MSRValue": "0x0080020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of cache line split locks sent to uncore.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF4",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "PublicDescription": "Counts the number of cache line split locks sent to the uncore.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json b/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
index 00f4fcffa815..5d6b2e6fcb7b 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
@@ -1,62 +1,5 @@
[
{
- "BriefDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend",
- "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * cycles)",
- "MetricGroup": "TopdownL1",
- "MetricName": "Frontend_Bound",
- "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Machine_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound."
- },
- {
- "BriefDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. SMT version; use when SMT is enabled and measuring per logical CPU.",
- "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
- "MetricGroup": "TopdownL1_SMT",
- "MetricName": "Frontend_Bound_SMT",
- "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Machine_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. SMT version; use when SMT is enabled and measuring per logical CPU."
- },
- {
- "BriefDescription": "This category represents fraction of slots wasted due to incorrect speculations",
- "MetricExpr": "( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * cycles)",
- "MetricGroup": "TopdownL1",
- "MetricName": "Bad_Speculation",
- "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example."
- },
- {
- "BriefDescription": "This category represents fraction of slots wasted due to incorrect speculations. SMT version; use when SMT is enabled and measuring per logical CPU.",
- "MetricExpr": "( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
- "MetricGroup": "TopdownL1_SMT",
- "MetricName": "Bad_Speculation_SMT",
- "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example. SMT version; use when SMT is enabled and measuring per logical CPU."
- },
- {
- "BriefDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend",
- "MetricConstraint": "NO_NMI_WATCHDOG",
- "MetricExpr": "1 - ( (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * cycles)) + (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * cycles)) + (UOPS_RETIRED.RETIRE_SLOTS / (4 * cycles)) )",
- "MetricGroup": "TopdownL1",
- "MetricName": "Backend_Bound",
- "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound."
- },
- {
- "BriefDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. SMT version; use when SMT is enabled and measuring per logical CPU.",
- "MetricExpr": "1 - ( (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) + (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) )",
- "MetricGroup": "TopdownL1_SMT",
- "MetricName": "Backend_Bound_SMT",
- "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. SMT version; use when SMT is enabled and measuring per logical CPU."
- },
- {
- "BriefDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired",
- "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / (4 * cycles)",
- "MetricGroup": "TopdownL1",
- "MetricName": "Retiring",
- "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category. Retiring of 100% would indicate the maximum 4 uops retired per cycle has been achieved. Maximizing Retiring typically increases the Instruction-Per-Cycle metric. Note that a high Retiring value does not necessary mean there is no room for more performance. For example; Microcode assists are categorized under Retiring. They hurt performance and can often be avoided. "
- },
- {
- "BriefDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. SMT version; use when SMT is enabled and measuring per logical CPU.",
- "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
- "MetricGroup": "TopdownL1_SMT",
- "MetricName": "Retiring_SMT",
- "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category. Retiring of 100% would indicate the maximum 4 uops retired per cycle has been achieved. Maximizing Retiring typically increases the Instruction-Per-Cycle metric. Note that a high Retiring value does not necessary mean there is no room for more performance. For example; Microcode assists are categorized under Retiring. They hurt performance and can often be avoided. SMT version; use when SMT is enabled and measuring per logical CPU."
- },
- {
"BriefDescription": "Instructions Per Cycle (per Logical Processor)",
"MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
"MetricGroup": "Summary",
@@ -71,49 +14,79 @@
{
"BriefDescription": "Instruction per taken branch",
"MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_TAKEN",
- "MetricGroup": "Branches;Fetch_BW;PGO",
+ "MetricGroup": "Branches;FetchBW;PGO",
"MetricName": "IpTB"
},
{
"BriefDescription": "Cycles Per Instruction (per Logical Processor)",
- "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
- "MetricGroup": "Pipeline;Summary",
+ "MetricExpr": "1 / (INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD)",
+ "MetricGroup": "Pipeline",
"MetricName": "CPI"
},
{
"BriefDescription": "Per-Logical Processor actual clocks when the Logical Processor is active.",
"MetricExpr": "CPU_CLK_UNHALTED.THREAD",
- "MetricGroup": "Summary",
+ "MetricGroup": "Pipeline",
"MetricName": "CLKS"
},
{
- "BriefDescription": "Total issue-pipeline slots (per-Physical Core till ICL; per-Logical Processor ICL onward)",
- "MetricExpr": "4 * cycles",
- "MetricGroup": "TopDownL1",
- "MetricName": "SLOTS"
+ "BriefDescription": "Instructions Per Cycle (per physical core)",
+ "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "SMT;TmaL1",
+ "MetricName": "CoreIPC"
},
{
- "BriefDescription": "Total issue-pipeline slots (per-Physical Core till ICL; per-Logical Processor ICL onward)",
- "MetricExpr": "4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
- "MetricGroup": "TopDownL1_SMT",
- "MetricName": "SLOTS_SMT"
+ "BriefDescription": "Instructions Per Cycle (per physical core)",
+ "MetricExpr": "INST_RETIRED.ANY / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
+ "MetricGroup": "SMT;TmaL1",
+ "MetricName": "CoreIPC_SMT"
+ },
+ {
+ "BriefDescription": "Floating Point Operations Per Cycle",
+ "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "Flops",
+ "MetricName": "FLOPc"
+ },
+ {
+ "BriefDescription": "Floating Point Operations Per Cycle",
+ "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
+ "MetricGroup": "Flops_SMT",
+ "MetricName": "FLOPc_SMT"
+ },
+ {
+ "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
+ "MetricExpr": "UOPS_EXECUTED.THREAD / (( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2 ) if #SMT_on else UOPS_EXECUTED.CORE_CYCLES_GE_1)",
+ "MetricGroup": "Pipeline;PortsUtil",
+ "MetricName": "ILP"
+ },
+ {
+ "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES",
+ "MetricGroup": "BrMispredicts",
+ "MetricName": "IpMispredict"
+ },
+ {
+ "BriefDescription": "Core actual clocks when any Logical Processor is active on the Physical Core",
+ "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "SMT",
+ "MetricName": "CORE_CLKS"
},
{
"BriefDescription": "Instructions per Load (lower number means higher occurrence rate)",
"MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_LOADS",
- "MetricGroup": "Instruction_Type",
+ "MetricGroup": "InsType",
"MetricName": "IpLoad"
},
{
"BriefDescription": "Instructions per Store (lower number means higher occurrence rate)",
"MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_STORES",
- "MetricGroup": "Instruction_Type",
+ "MetricGroup": "InsType",
"MetricName": "IpStore"
},
{
"BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)",
"MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES",
- "MetricGroup": "Branches;Instruction_Type",
+ "MetricGroup": "Branches;InsType",
"MetricName": "IpBranch"
},
{
@@ -131,13 +104,13 @@
{
"BriefDescription": "Instructions per Floating Point (FP) Operation (lower number means higher occurrence rate)",
"MetricExpr": "INST_RETIRED.ANY / ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE )",
- "MetricGroup": "FLOPS;FP_Arith;Instruction_Type",
+ "MetricGroup": "Flops;FpArith;InsType",
"MetricName": "IpFLOP"
},
{
- "BriefDescription": "Total number of retired Instructions",
+ "BriefDescription": "Total number of retired Instructions, Sample with: INST_RETIRED.PREC_DIST",
"MetricExpr": "INST_RETIRED.ANY",
- "MetricGroup": "Summary;TopDownL1",
+ "MetricGroup": "Summary;TmaL1",
"MetricName": "Instructions"
},
{
@@ -149,164 +122,110 @@
{
"BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded ICache; or Uop Cache)",
"MetricExpr": "IDQ.DSB_UOPS / (IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS)",
- "MetricGroup": "DSB;Fetch_BW",
+ "MetricGroup": "DSB;FetchBW",
"MetricName": "DSB_Coverage"
},
{
- "BriefDescription": "Instructions Per Cycle (per physical core)",
- "MetricExpr": "INST_RETIRED.ANY / cycles",
- "MetricGroup": "SMT;TopDownL1",
- "MetricName": "CoreIPC"
- },
- {
- "BriefDescription": "Instructions Per Cycle (per physical core)",
- "MetricExpr": "INST_RETIRED.ANY / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
- "MetricGroup": "SMT;TopDownL1",
- "MetricName": "CoreIPC_SMT"
- },
- {
- "BriefDescription": "Floating Point Operations Per Cycle",
- "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / cycles",
- "MetricGroup": "FLOPS",
- "MetricName": "FLOPc"
- },
- {
- "BriefDescription": "Floating Point Operations Per Cycle",
- "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
- "MetricGroup": "FLOPS_SMT",
- "MetricName": "FLOPc_SMT"
- },
- {
- "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
- "MetricExpr": "UOPS_EXECUTED.THREAD / ( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2 )",
- "MetricGroup": "Pipeline;Ports_Utilization",
- "MetricName": "ILP"
- },
- {
- "BriefDescription": "Branch Misprediction Cost: Fraction of TopDown slots wasted per non-speculative branch misprediction (jeclear)",
- "MetricExpr": "( ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * cycles))) + (4 * ( IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE - ( FRONTEND_RETIRED.LATENCY_GE_1 - FRONTEND_RETIRED.LATENCY_GE_2 ) / (UOPS_RETIRED.RETIRE_SLOTS / UOPS_ISSUED.ANY) ) / (4 * cycles)) * (( INT_MISC.CLEAR_RESTEER_CYCLES + 9 * BACLEARS.ANY ) / cycles) / (4 * ( IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE - ( FRONTEND_RETIRED.LATENCY_GE_1 - FRONTEND_RETIRED.LATENCY_GE_2 ) / (UOPS_RETIRED.RETIRE_SLOTS / UOPS_ISSUED.ANY) ) / (4 * cycles)) ) * (4 * cycles) / BR_MISP_RETIRED.ALL_BRANCHES",
- "MetricGroup": "BrMispredicts",
- "MetricName": "Branch_Misprediction_Cost"
- },
- {
- "BriefDescription": "Branch Misprediction Cost: Fraction of TopDown slots wasted per non-speculative branch misprediction (jeclear)",
- "MetricExpr": "( ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) + (4 * ( IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE - ( FRONTEND_RETIRED.LATENCY_GE_1 - FRONTEND_RETIRED.LATENCY_GE_2 ) / (UOPS_RETIRED.RETIRE_SLOTS / UOPS_ISSUED.ANY) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * (( INT_MISC.CLEAR_RESTEER_CYCLES + 9 * BACLEARS.ANY ) / cycles) / (4 * ( IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE - ( FRONTEND_RETIRED.LATENCY_GE_1 - FRONTEND_RETIRED.LATENCY_GE_2 ) / (UOPS_RETIRED.RETIRE_SLOTS / UOPS_ISSUED.ANY) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) ) * (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )) / BR_MISP_RETIRED.ALL_BRANCHES",
- "MetricGroup": "BrMispredicts_SMT",
- "MetricName": "Branch_Misprediction_Cost_SMT"
- },
- {
- "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear)",
- "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES",
- "MetricGroup": "BrMispredicts",
- "MetricName": "IpMispredict"
- },
- {
- "BriefDescription": "Core actual clocks when any Logical Processor is active on the Physical Core",
- "MetricExpr": "( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
- "MetricGroup": "SMT",
- "MetricName": "CORE_CLKS"
- },
- {
"BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads (in core cycles)",
"MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT )",
- "MetricGroup": "Memory_Bound;Memory_Lat",
+ "MetricGroup": "MemoryBound;MemoryLat",
"MetricName": "Load_Miss_Real_Latency"
},
{
"BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least one such miss. Per-Logical Processor)",
"MetricExpr": "L1D_PEND_MISS.PENDING / L1D_PEND_MISS.PENDING_CYCLES",
- "MetricGroup": "Memory_Bound;Memory_BW",
+ "MetricGroup": "MemoryBound;MemoryBW",
"MetricName": "MLP"
},
{
"BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
"MetricConstraint": "NO_NMI_WATCHDOG",
- "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * cycles )",
- "MetricGroup": "TLB",
+ "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * CORE_CLKS )",
+ "MetricGroup": "MemoryTLB",
"MetricName": "Page_Walks_Utilization"
},
{
- "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
- "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ) )",
- "MetricGroup": "TLB_SMT",
- "MetricName": "Page_Walks_Utilization_SMT"
- },
- {
"BriefDescription": "Average data fill bandwidth to the L1 data cache [GB / sec]",
"MetricExpr": "64 * L1D.REPLACEMENT / 1000000000 / duration_time",
- "MetricGroup": "Memory_BW",
+ "MetricGroup": "MemoryBW",
"MetricName": "L1D_Cache_Fill_BW"
},
{
"BriefDescription": "Average data fill bandwidth to the L2 cache [GB / sec]",
"MetricExpr": "64 * L2_LINES_IN.ALL / 1000000000 / duration_time",
- "MetricGroup": "Memory_BW",
+ "MetricGroup": "MemoryBW",
"MetricName": "L2_Cache_Fill_BW"
},
{
"BriefDescription": "Average per-core data fill bandwidth to the L3 cache [GB / sec]",
"MetricExpr": "64 * LONGEST_LAT_CACHE.MISS / 1000000000 / duration_time",
- "MetricGroup": "Memory_BW",
+ "MetricGroup": "MemoryBW",
"MetricName": "L3_Cache_Fill_BW"
},
{
- "BriefDescription": "Average per-core data fill bandwidth to the L3 cache [GB / sec]",
+ "BriefDescription": "Average per-core data access bandwidth to the L3 cache [GB / sec]",
"MetricExpr": "64 * OFFCORE_REQUESTS.ALL_REQUESTS / 1000000000 / duration_time",
- "MetricGroup": "Memory_BW;Offcore",
+ "MetricGroup": "MemoryBW;Offcore",
"MetricName": "L3_Cache_Access_BW"
},
{
"BriefDescription": "L1 cache true misses per kilo instruction for retired demand loads",
"MetricExpr": "1000 * MEM_LOAD_RETIRED.L1_MISS / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses",
+ "MetricGroup": "CacheMisses",
"MetricName": "L1MPKI"
},
{
"BriefDescription": "L2 cache true misses per kilo instruction for retired demand loads",
"MetricExpr": "1000 * MEM_LOAD_RETIRED.L2_MISS / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses",
+ "MetricGroup": "CacheMisses",
"MetricName": "L2MPKI"
},
{
"BriefDescription": "L2 cache misses per kilo instruction for all request types (including speculative)",
"MetricExpr": "1000 * L2_RQSTS.MISS / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses;Offcore",
+ "MetricGroup": "CacheMisses;Offcore",
"MetricName": "L2MPKI_All"
},
{
"BriefDescription": "L2 cache hits per kilo instruction for all request types (including speculative)",
"MetricExpr": "1000 * ( L2_RQSTS.REFERENCES - L2_RQSTS.MISS ) / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses",
+ "MetricGroup": "CacheMisses",
"MetricName": "L2HPKI_All"
},
{
"BriefDescription": "L3 cache true misses per kilo instruction for retired demand loads",
"MetricExpr": "1000 * MEM_LOAD_RETIRED.L3_MISS / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses",
+ "MetricGroup": "CacheMisses",
"MetricName": "L3MPKI"
},
{
"BriefDescription": "Rate of silent evictions from the L2 cache per Kilo instruction where the evicted lines are dropped (no writeback to L3 or memory)",
"MetricExpr": "1000 * L2_LINES_OUT.SILENT / INST_RETIRED.ANY",
- "MetricGroup": "",
+ "MetricGroup": "L2Evicts;Server",
"MetricName": "L2_Evictions_Silent_PKI"
},
{
"BriefDescription": "Rate of non silent evictions from the L2 cache per Kilo instruction",
"MetricExpr": "1000 * L2_LINES_OUT.NON_SILENT / INST_RETIRED.ANY",
- "MetricGroup": "",
+ "MetricGroup": "L2Evicts;Server",
"MetricName": "L2_Evictions_NonSilent_PKI"
},
{
"BriefDescription": "Average CPU Utilization",
"MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
- "MetricGroup": "Summary",
+ "MetricGroup": "HPC;Summary",
"MetricName": "CPU_Utilization"
},
{
+ "BriefDescription": "Measured Average Frequency for unhalted processors [GHz]",
+ "MetricExpr": "(CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 / duration_time",
+ "MetricGroup": "Summary;Power",
+ "MetricName": "Average_Frequency"
+ },
+ {
"BriefDescription": "Giga Floating Point Operations Per Second",
"MetricExpr": "( ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / 1000000000 ) / duration_time",
- "MetricGroup": "FLOPS;Summary",
+ "MetricGroup": "Flops;HPC",
"MetricName": "GFLOPs"
},
{
@@ -317,62 +236,62 @@
},
{
"BriefDescription": "Fraction of cycles where both hardware Logical Processors were active",
- "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 )",
- "MetricGroup": "SMT;Summary",
+ "MetricExpr": "1 - CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
+ "MetricGroup": "SMT",
"MetricName": "SMT_2T_Utilization"
},
{
"BriefDescription": "Fraction of cycles spent in the Operating System (OS) Kernel mode",
- "MetricExpr": "CPU_CLK_UNHALTED.THREAD:k / CPU_CLK_UNHALTED.THREAD",
+ "MetricExpr": "CPU_CLK_UNHALTED.THREAD_P:k / CPU_CLK_UNHALTED.THREAD",
"MetricGroup": "OS",
"MetricName": "Kernel_Utilization"
},
{
"BriefDescription": "Average external Memory Bandwidth Use for reads and writes [GB / sec]",
- "MetricExpr": "( ( ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) * 1048576 ) / 1000000000 ) / duration_time",
- "MetricGroup": "Memory_BW;SoC",
+ "MetricExpr": "( 64 * ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) / 1000000000 ) / duration_time",
+ "MetricGroup": "HPC;MemoryBW;SoC",
"MetricName": "DRAM_BW_Use"
},
{
"BriefDescription": "Average latency of data read request to external memory (in nanoseconds). Accounts for demand loads and L1/L2 prefetches",
"MetricExpr": "1000000000 * ( cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433@ / cha@event\\=0x35\\,umask\\=0x21\\,config\\=0x40433@ ) / ( cha_0@event\\=0x0@ / duration_time )",
- "MetricGroup": "Memory_Lat;SoC",
+ "MetricGroup": "MemoryLat;SoC",
"MetricName": "MEM_Read_Latency"
},
{
"BriefDescription": "Average number of parallel data read requests to external memory. Accounts for demand loads and L1/L2 prefetches",
"MetricExpr": "cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433@ / cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433\\,thresh\\=1@",
- "MetricGroup": "Memory_BW;SoC",
+ "MetricGroup": "MemoryBW;SoC",
"MetricName": "MEM_Parallel_Reads"
},
{
"BriefDescription": "Average latency of data read request to external 3D X-Point memory [in nanoseconds]. Accounts for demand loads and L1/L2 data-read prefetches",
"MetricExpr": "( 1000000000 * ( imc@event\\=0xe0\\,umask\\=0x1@ / imc@event\\=0xe3@ ) / imc_0@event\\=0x0@ )",
- "MetricGroup": "Memory_Lat;SoC;Server",
+ "MetricGroup": "MemoryLat;SoC;Server",
"MetricName": "MEM_PMM_Read_Latency"
},
{
"BriefDescription": "Average 3DXP Memory Bandwidth Use for reads [GB / sec]",
"MetricExpr": "( ( 64 * imc@event\\=0xe3@ / 1000000000 ) / duration_time )",
- "MetricGroup": "Memory_BW;SoC;Server",
+ "MetricGroup": "MemoryBW;SoC;Server",
"MetricName": "PMM_Read_BW"
},
{
"BriefDescription": "Average 3DXP Memory Bandwidth Use for Writes [GB / sec]",
"MetricExpr": "( ( 64 * imc@event\\=0xe7@ / 1000000000 ) / duration_time )",
- "MetricGroup": "Memory_BW;SoC;Server",
+ "MetricGroup": "MemoryBW;SoC;Server",
"MetricName": "PMM_Write_BW"
},
{
"BriefDescription": "Average IO (network or disk) Bandwidth Use for Writes [GB / sec]",
"MetricExpr": "( UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3 ) * 4 / 1000000000 / duration_time",
- "MetricGroup": "IO_BW;SoC;Server",
+ "MetricGroup": "IoBW;SoC;Server",
"MetricName": "IO_Write_BW"
},
{
"BriefDescription": "Average IO (network or disk) Bandwidth Use for Reads [GB / sec]",
"MetricExpr": "( UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3 ) * 4 / 1000000000 / duration_time",
- "MetricGroup": "IO_BW;SoC;Server",
+ "MetricGroup": "IoBW;SoC;Server",
"MetricName": "IO_Read_BW"
},
{
@@ -383,7 +302,7 @@
},
{
"BriefDescription": "Instructions per Far Branch ( Far Branches apply upon transition from application to operating system, handling interrupts, exceptions) [lower number means higher occurrence rate]",
- "MetricExpr": "INST_RETIRED.ANY / ( BR_INST_RETIRED.FAR_BRANCH / 2 )",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.FAR_BRANCH:u",
"MetricGroup": "Branches;OS",
"MetricName": "IpFarBranch"
},
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/floating-point.json b/tools/perf/pmu-events/arch/x86/cascadelakex/floating-point.json
index 3c0b95fd60ad..ade925d7a68c 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/floating-point.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/floating-point.json
@@ -1,12 +1,12 @@
[
{
- "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT14 RCP14 DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x4"
},
{
"BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
@@ -18,13 +18,13 @@
"UMask": "0x8"
},
{
- "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
"SampleAfterValue": "2000003",
- "UMask": "0x40"
+ "UMask": "0x10"
},
{
"BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
@@ -36,13 +36,13 @@
"UMask": "0x20"
},
{
- "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x40"
},
{
"BriefDescription": "Number of SSE/AVX computational 512-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
@@ -54,32 +54,32 @@
"UMask": "0x80"
},
{
- "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xCA",
- "EventName": "FP_ASSIST.ANY",
- "PublicDescription": "Counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
- "SampleAfterValue": "100003",
- "UMask": "0x1e"
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT14 RCP14 DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
"SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "CounterMask": "1",
+ "EventCode": "0xCA",
+ "EventName": "FP_ASSIST.ANY",
+ "PublicDescription": "Counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1e"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/frontend.json b/tools/perf/pmu-events/arch/x86/cascadelakex/frontend.json
index 0716b2e3ff75..078706a50091 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/frontend.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/frontend.json
@@ -1,210 +1,125 @@
[
{
- "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
- "PublicDescription": "Counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
- "SampleAfterValue": "2000003",
+ "EventCode": "0xE6",
+ "EventName": "BACLEARS.ANY",
+ "PublicDescription": "Counts the number of times the front-end is resteered when it finds a branch instruction in a fetch line. This occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switches",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.L2_MISS",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x13",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xAB",
+ "EventName": "DSB2MITE_SWITCHES.COUNT",
+ "PublicDescription": "This event counts the number of the Decode Stream Buffer (DSB)-to-MITE switches including all misses because of missing Decode Stream Buffer (DSB) cache and u-arch forced misses.\nNote: Invoking MITE requires two or three cycles delay.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x79",
- "EventName": "IDQ.MS_MITE_UOPS",
- "PublicDescription": "Counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
+ "EventCode": "0xAB",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "PublicDescription": "Counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. MM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.Penalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 02 cycles.",
"SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 2 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired Instructions who experienced decode stream buffer (DSB - the decoded instruction-cache) miss.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_2",
+ "EventName": "FRONTEND_RETIRED.DSB_MISS",
"MSRIndex": "0x3F7",
- "MSRValue": "0x200206",
+ "MSRValue": "0x11",
"PEBS": "1",
+ "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 3 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired Instructions who experienced iTLB true miss.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_3",
+ "EventName": "FRONTEND_RETIRED.ITLB_MISS",
"MSRIndex": "0x3F7",
- "MSRValue": "0x300206",
+ "MSRValue": "0x14",
"PEBS": "1",
+ "PublicDescription": "Counts retired Instructions that experienced iTLB (Instruction TLB) true miss.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1",
+ "EventName": "FRONTEND_RETIRED.L1I_MISS",
"MSRIndex": "0x3F7",
- "MSRValue": "0x100206",
+ "MSRValue": "0x12",
"PEBS": "1",
- "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
- "Invert": "1",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x79",
- "EventName": "IDQ.MS_UOPS",
- "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS). Any instruction over 4 uops will be delivered by the MS. Some instructions such as transcendentals may additionally generate uops from the MS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x30"
- },
- {
- "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.",
+ "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.L1I_MISS",
+ "EventName": "FRONTEND_RETIRED.L2_MISS",
"MSRIndex": "0x3F7",
- "MSRValue": "0x12",
+ "MSRValue": "0x13",
"PEBS": "1",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "BriefDescription": "Retired instructions after front-end starvation of at least 1 cycle",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
- "PublicDescription": "Cycles with less than 3 uops delivered by the front-end.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_1",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x400106",
+ "PEBS": "2",
+ "PublicDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of at least 1 cycle which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.DSB_CYCLES",
- "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Retired Instructions who experienced decode stream buffer (DSB - the decoded instruction-cache) miss.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.DSB_MISS",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_128",
"MSRIndex": "0x3F7",
- "MSRValue": "0x11",
+ "MSRValue": "0x408006",
"PEBS": "1",
- "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x79",
- "EventName": "IDQ.MITE_UOPS",
- "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.MS_CYCLES",
- "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
- "SampleAfterValue": "2000003",
- "UMask": "0x30"
- },
- {
- "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.MITE_CYCLES",
- "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
- "PublicDescription": "Counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding 4 x when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when: a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread. b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions). c. Instruction Decode Queue (IDQ) delivers four uops.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xAB",
- "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
- "PublicDescription": "Counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. MM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.Penalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 02 cycles.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_8",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_16",
"MSRIndex": "0x3F7",
- "MSRValue": "0x400806",
+ "MSRValue": "0x401006",
"PEBS": "1",
- "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
@@ -223,93 +138,96 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_4",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_256",
"MSRIndex": "0x3F7",
- "MSRValue": "0x400406",
+ "MSRValue": "0x410006",
"PEBS": "1",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.MS_DSB_CYCLES",
- "PublicDescription": "Counts cycles during which uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switches",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xAB",
- "EventName": "DSB2MITE_SWITCHES.COUNT",
- "PublicDescription": "This event counts the number of the Decode Stream Buffer (DSB)-to-MITE switches including all misses because of missing Decode Stream Buffer (DSB) cache and u-arch forced misses.\nNote: Invoking MITE requires two or three cycles delay.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x100206",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions after front-end starvation of at least 1 cycle",
- "Counter": "0,1,2,3,4,5,6,7",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xc6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_1",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 2 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_2",
"MSRIndex": "0x3F7",
- "MSRValue": "0x400106",
- "PEBS": "2",
- "PublicDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of at least 1 cycle which was not interrupted by a back-end stall.",
+ "MSRValue": "0x200206",
+ "PEBS": "1",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 3 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x83",
- "EventName": "ICACHE_64B.IFTAG_MISS",
- "SampleAfterValue": "200003",
- "UMask": "0x2"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_3",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x300206",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_128",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_32",
"MSRIndex": "0x3F7",
- "MSRValue": "0x408006",
+ "MSRValue": "0x402006",
"PEBS": "1",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "3",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
- "PublicDescription": "Counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >= 3.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_4",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x400406",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x83",
- "EventName": "ICACHE_64B.IFTAG_HIT",
- "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_512",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x420006",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
@@ -326,38 +244,29 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.STLB_MISS",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_8",
"MSRIndex": "0x3F7",
- "MSRValue": "0x15",
+ "MSRValue": "0x400806",
"PEBS": "1",
- "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss.",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x79",
- "EventName": "IDQ.DSB_UOPS",
- "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_256",
+ "EventName": "FRONTEND_RETIRED.STLB_MISS",
"MSRIndex": "0x3F7",
- "MSRValue": "0x410006",
+ "MSRValue": "0x15",
"PEBS": "1",
+ "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
@@ -373,6 +282,66 @@
"UMask": "0x4"
},
{
+ "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x83",
+ "EventName": "ICACHE_64B.IFTAG_HIT",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x83",
+ "EventName": "ICACHE_64B.IFTAG_MISS",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x83",
+ "EventName": "ICACHE_64B.IFTAG_STALL",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "4",
+ "EventCode": "0x79",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "PublicDescription": "Counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Count includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x18"
+ },
+ {
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
+ "PublicDescription": "Counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Count includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x18"
+ },
+ {
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "4",
+ "EventCode": "0x79",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "PublicDescription": "Counts the number of cycles 4 uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. Counting includes uops that may 'bypass' the IDQ. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x24"
+ },
+ {
"BriefDescription": "Cycles MITE is delivering any Uop",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -384,53 +353,78 @@
"UMask": "0x24"
},
{
- "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xE6",
- "EventName": "BACLEARS.ANY",
- "PublicDescription": "Counts the number of times the front-end is resteered when it finds a branch instruction in a fetch line. This occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.DSB_CYCLES",
+ "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_16",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x401006",
- "PEBS": "1",
- "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x79",
+ "EventName": "IDQ.DSB_UOPS",
+ "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "2",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
- "PublicDescription": "Cycles with less than 2 uops delivered by the front-end.",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MITE_CYCLES",
+ "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x4"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_32",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x402006",
- "PEBS": "1",
- "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MITE_UOPS",
+ "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MS_CYCLES",
+ "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x30"
+ },
+ {
+ "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MS_DSB_CYCLES",
+ "PublicDescription": "Counts cycles during which uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "PublicDescription": "Counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
},
{
"BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer",
@@ -445,72 +439,78 @@
"UMask": "0x30"
},
{
- "BriefDescription": "Retired Instructions who experienced iTLB true miss.",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.ITLB_MISS",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x14",
- "PEBS": "1",
- "PublicDescription": "Counts retired Instructions that experienced iTLB (Instruction TLB) true miss.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MS_UOPS",
+ "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS). Any instruction over 4 uops will be delivered by the MS. Some instructions such as transcendentals may additionally generate uops from the MS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x30"
+ },
+ {
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "PublicDescription": "Counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding 4 x when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when: a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread. b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions). c. Instruction Decode Queue (IDQ) delivers four uops.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.ALL_DSB_CYCLES_ANY_UOPS",
- "PublicDescription": "Counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Count includes uops that may 'bypass' the IDQ.",
+ "CounterMask": "4",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "PublicDescription": "Counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
"SampleAfterValue": "2000003",
- "UMask": "0x18"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Counts cycles FE delivered 4 uops or Resource Allocation Table (RAT) was stalling FE.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_512",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x420006",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "Invert": "1",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0x79",
- "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
- "PublicDescription": "Counts the number of cycles 4 uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. Counting includes uops that may 'bypass' the IDQ. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "CounterMask": "3",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "PublicDescription": "Counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >= 3.",
"SampleAfterValue": "2000003",
- "UMask": "0x24"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0x79",
- "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
- "PublicDescription": "Counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Count includes uops that may 'bypass' the IDQ.",
+ "CounterMask": "2",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "PublicDescription": "Cycles with less than 2 uops delivered by the front-end.",
"SampleAfterValue": "2000003",
- "UMask": "0x18"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss.",
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x83",
- "EventName": "ICACHE_64B.IFTAG_STALL",
- "SampleAfterValue": "200003",
- "UMask": "0x4"
+ "CounterMask": "1",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "PublicDescription": "Cycles with less than 3 uops delivered by the front-end.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/memory.json b/tools/perf/pmu-events/arch/x86/cascadelakex/memory.json
index 0c07cb4fbf58..7c2adadca87e 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/memory.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/memory.json
@@ -1,1338 +1,1358 @@
[
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Cycles while L3 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x06040007F7",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "2",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L3_MISS",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "6",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x6"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "PEBS": "1",
+ "PublicDescription": "Number of times HLE abort was triggered.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to unfriendly events (such as interrupts).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_EVENTS",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_MEM",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_MEMTYPE",
+ "PublicDescription": "Number of times an HLE execution aborted due to incompatible memory type.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to hardware timer expiration.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_TIMER",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_UNFRIENDLY",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution successfully committed",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "PublicDescription": "Number of times HLE commit succeeded.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution started.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.START",
+ "PublicDescription": "Number of times we entered an HLE region. Does not count nested transactions.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Errata": "SKL089",
+ "EventCode": "0xC3",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "PublicDescription": "Counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:a. memory disambiguation,b. external snoop, orc. cross SMT-HW-thread snoop (stores) hitting load buffer.",
"SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x80",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "1009",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800491",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x10",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "20011",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000100",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x100",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "503",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000490",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x20",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000020",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x4",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.",
"SampleAfterValue": "100003",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x200",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "101",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x40",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "2003",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x8",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "50021",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000100",
+ "MSRValue": "0x3FBC000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000400",
+ "MSRValue": "0x103C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000490",
+ "MSRValue": "0x083C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000010",
+ "MSRValue": "0x043C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00490",
+ "MSRValue": "0x013C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.REMOTE_HITM OCR.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000120",
+ "MSRValue": "0x103FC00491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000100",
+ "MSRValue": "0x083FC00491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.SNOOP_MISS OCR.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000100",
+ "MSRValue": "0x023C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.SNOOP_NONE OCR.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000100",
+ "MSRValue": "0x00BC000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804008000",
+ "MSRValue": "0x3F84000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x06040007F7",
+ "MSRValue": "0x1004000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000491",
+ "MSRValue": "0x0804000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000010",
+ "MSRValue": "0x0404000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000080",
+ "MSRValue": "0x0104000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000010",
+ "MSRValue": "0x0204000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01040007F7",
+ "MSRValue": "0x0604000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000400",
+ "MSRValue": "0x0084000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000004",
+ "MSRValue": "0x063B800491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000010",
+ "MSRValue": "0x3F90000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000491",
+ "MSRValue": "0x1010000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_MEM",
- "PublicDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000010",
+ "MSRValue": "0x0810000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10040007F7",
+ "MSRValue": "0x0410000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000002",
+ "MSRValue": "0x0110000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000004",
+ "MSRValue": "0x0210000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP OCR.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000400",
+ "MSRValue": "0x0090000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000120",
+ "MSRValue": "0x3FBC000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08100007F7",
+ "MSRValue": "0x103C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000100",
+ "MSRValue": "0x083C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000120",
+ "MSRValue": "0x043C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000020",
+ "MSRValue": "0x013C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000020",
+ "MSRValue": "0x103FC00490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000400",
+ "MSRValue": "0x083FC00490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000120",
+ "MSRValue": "0x023C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000002",
+ "MSRValue": "0x00BC000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000020",
+ "MSRValue": "0x3F84000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410008000",
+ "MSRValue": "0x1004000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000002",
+ "MSRValue": "0x0804000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800002",
+ "MSRValue": "0x0404000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F840007F7",
+ "MSRValue": "0x0104000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000491",
+ "MSRValue": "0x0204000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000400",
+ "MSRValue": "0x0604000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000004",
+ "MSRValue": "0x0084000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000100",
+ "MSRValue": "0x063B800490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000490",
+ "MSRValue": "0x3F90000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000004",
+ "MSRValue": "0x1010000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000010",
+ "MSRValue": "0x0810000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000100",
+ "MSRValue": "0x0410000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
- "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000004",
+ "MSRValue": "0x0110000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000020",
+ "MSRValue": "0x0210000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_CONFLICT",
- "PublicDescription": "Number of times a TSX line had a cache conflict.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000400",
+ "MSRValue": "0x0090000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000120",
+ "MSRValue": "0x3FBC000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000002",
+ "MSRValue": "0x103C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000004",
+ "MSRValue": "0x083C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800100",
+ "MSRValue": "0x043C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000120",
+ "MSRValue": "0x013C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.REMOTE_HITM OCR.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000122",
+ "MSRValue": "0x103FC00120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000122",
+ "MSRValue": "0x083FC00120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.SNOOP_MISS OCR.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104008000",
+ "MSRValue": "0x023C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC5",
- "PublicDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC4",
- "PublicDescription": "RTM region detected inside HLE.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC3",
- "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC2",
- "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC1",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.SNOOP_NONE OCR.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000122",
+ "MSRValue": "0x00BC000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000002",
+ "MSRValue": "0x3F84000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00490",
+ "MSRValue": "0x1004000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800010",
+ "MSRValue": "0x0804000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000400",
+ "MSRValue": "0x0404000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000400",
+ "MSRValue": "0x0104000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000001",
+ "MSRValue": "0x0204000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000010",
+ "MSRValue": "0x0604000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00490",
+ "MSRValue": "0x0084000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800122",
+ "MSRValue": "0x063B800120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000400",
+ "MSRValue": "0x3F90000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000020",
+ "MSRValue": "0x1010000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000400",
+ "MSRValue": "0x0810000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B8007F7",
+ "MSRValue": "0x0410000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000491",
+ "MSRValue": "0x0110000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000001",
+ "MSRValue": "0x0210000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000002",
+ "MSRValue": "0x0090000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.ANY_SNOOP OCR.ALL_READS.L3_MISS.ANY_SNOOP OCR.ALL_READS.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00840007F7",
+ "MSRValue": "0x3FBC0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000490",
+ "MSRValue": "0x103C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000100",
+ "MSRValue": "0x083C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10100007F7",
+ "MSRValue": "0x043C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000004",
+ "MSRValue": "0x013C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to uncommon conditions.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_TIMER",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.REMOTE_HITM OCR.ALL_READS.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000002",
+ "MSRValue": "0x103FC007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00004",
+ "MSRValue": "0x083FC007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.SNOOP_MISS OCR.ALL_READS.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000002",
+ "MSRValue": "0x023C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS.SNOOP_NONE OCR.ALL_READS.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F900007F7",
+ "MSRValue": "0x00BC0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000100",
+ "MSRValue": "0x3F840007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000010",
+ "MSRValue": "0x10040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000001",
+ "MSRValue": "0x08040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -1352,360 +1372,338 @@
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000010",
+ "MSRValue": "0x01040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000004",
+ "MSRValue": "0x02040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000010",
+ "MSRValue": "0x06040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000002",
+ "MSRValue": "0x00840007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000080",
+ "MSRValue": "0x063B8007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00490",
+ "MSRValue": "0x3F900007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000004",
+ "MSRValue": "0x10100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000004",
+ "MSRValue": "0x08100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000080",
+ "MSRValue": "0x04100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000400",
+ "MSRValue": "0x01100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000080",
+ "MSRValue": "0x02100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000010",
+ "MSRValue": "0x00900007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.ANY_SNOOP OCR.ALL_RFO.L3_MISS.ANY_SNOOP OCR.ALL_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000400",
+ "MSRValue": "0x3FBC000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000004",
+ "MSRValue": "0x103C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00400",
+ "MSRValue": "0x083C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000100",
+ "MSRValue": "0x043C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution successfully committed",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.COMMIT",
- "PublicDescription": "Number of times HLE commit succeeded.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000122",
+ "MSRValue": "0x013C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.REMOTE_HITM OCR.ALL_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000002",
+ "MSRValue": "0x103FC00122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000002",
+ "MSRValue": "0x083FC00122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.SNOOP_MISS OCR.ALL_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000491",
+ "MSRValue": "0x023C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS.SNOOP_NONE OCR.ALL_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000010",
+ "MSRValue": "0x00BC000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000491",
+ "MSRValue": "0x3F84000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000001",
+ "MSRValue": "0x1004000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000010",
+ "MSRValue": "0x0804000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00100",
+ "MSRValue": "0x0404000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000490",
+ "MSRValue": "0x0104000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -1725,389 +1723,375 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000002",
+ "MSRValue": "0x0604000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000080",
+ "MSRValue": "0x0084000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000100",
+ "MSRValue": "0x063B800122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.SNOOP_MISS OCR.ALL_READS.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C0007F7",
+ "MSRValue": "0x3F90000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000004",
+ "MSRValue": "0x1010000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00122",
+ "MSRValue": "0x0810000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C0007F7",
+ "MSRValue": "0x0410000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000120",
+ "MSRValue": "0x0110000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00020",
+ "MSRValue": "0x0210000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84008000",
+ "MSRValue": "0x0090000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP OCR.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000002",
+ "MSRValue": "0x3FBC000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE OCR.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000004",
+ "MSRValue": "0x103C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000120",
+ "MSRValue": "0x083C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000122",
+ "MSRValue": "0x043C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED OCR.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000080",
+ "MSRValue": "0x013C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000004",
+ "MSRValue": "0x103FC00004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000010",
+ "MSRValue": "0x083FC00004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800490",
+ "MSRValue": "0x023C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000490",
+ "MSRValue": "0x00BC000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110008000",
+ "MSRValue": "0x3F84000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800100",
+ "MSRValue": "0x1004000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC008000",
+ "MSRValue": "0x0804000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000122",
+ "MSRValue": "0x0404000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00080",
+ "MSRValue": "0x0104000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00002",
+ "MSRValue": "0x0204000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000020",
+ "MSRValue": "0x0604000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000120",
+ "MSRValue": "0x0084000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F840007F7",
+ "MSRValue": "0x063B800004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
"MSRValue": "0x3F90000004",
"Offcore": "1",
@@ -2116,1002 +2100,949 @@
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C0007F7",
+ "MSRValue": "0x1010000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000122",
+ "MSRValue": "0x0810000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000490",
+ "MSRValue": "0x0410000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000001",
+ "MSRValue": "0x0110000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00491",
+ "MSRValue": "0x0210000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10040007F7",
+ "MSRValue": "0x0090000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP OCR.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C0007F7",
+ "MSRValue": "0x3FBC000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000002",
+ "MSRValue": "0x103C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004008000",
+ "MSRValue": "0x083C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x80",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "1009",
- "TakenAlone": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x043C000001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C0007F7",
+ "MSRValue": "0x013C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
- "PublicDescription": "Number of times we could not allocate Lock Buffer.",
- "SampleAfterValue": "2000003",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204008000",
+ "MSRValue": "0x103FC00001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000010",
+ "MSRValue": "0x083FC00001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000491",
+ "MSRValue": "0x023C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000020",
+ "MSRValue": "0x00BC000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000122",
+ "MSRValue": "0x3F84000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000400",
+ "MSRValue": "0x1004000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000122",
+ "MSRValue": "0x0804000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000491",
+ "MSRValue": "0x0404000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000120",
+ "MSRValue": "0x0104000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000490",
+ "MSRValue": "0x0204000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000490",
+ "MSRValue": "0x0604000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000490",
+ "MSRValue": "0x0084000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000002",
+ "MSRValue": "0x063B800001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000491",
+ "MSRValue": "0x3F90000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000080",
+ "MSRValue": "0x1010000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000491",
+ "MSRValue": "0x0810000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000100",
+ "MSRValue": "0x0410000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000120",
+ "MSRValue": "0x0110000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000120",
+ "MSRValue": "0x0210000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC008000",
+ "MSRValue": "0x0090000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.ANY_SNOOP OCR.DEMAND_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000100",
+ "MSRValue": "0x3FBC000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE OCR.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000002",
+ "MSRValue": "0x103C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090008000",
+ "MSRValue": "0x083C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000122",
+ "MSRValue": "0x043C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000490",
+ "MSRValue": "0x013C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000122",
+ "MSRValue": "0x103FC00002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000080",
+ "MSRValue": "0x083FC00002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000490",
+ "MSRValue": "0x023C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000120",
+ "MSRValue": "0x00BC000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000490",
+ "MSRValue": "0x3F84000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000001",
+ "MSRValue": "0x1004000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000120",
+ "MSRValue": "0x0804000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP OCR.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000001",
+ "MSRValue": "0x0404000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_MEMTYPE",
- "PublicDescription": "Number of times an RTM execution aborted due to incompatible memory type.",
- "SampleAfterValue": "2000003",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000120",
+ "MSRValue": "0x0104000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000490",
+ "MSRValue": "0x0204000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00010",
+ "MSRValue": "0x0604000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000122",
+ "MSRValue": "0x0084000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00900007F7",
+ "MSRValue": "0x063B800002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000010",
+ "MSRValue": "0x3F90000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000400",
+ "MSRValue": "0x1010000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02040007F7",
+ "MSRValue": "0x0810000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000122",
+ "MSRValue": "0x0410000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000001",
+ "MSRValue": "0x0110000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000080",
+ "MSRValue": "0x0210000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00122",
+ "MSRValue": "0x0090000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.ANY_SNOOP OCR.OTHER.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000010",
+ "MSRValue": "0x3FBC008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.HITM_OTHER_CORE OCR.OTHER.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.OTHER.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B8007F7",
+ "MSRValue": "0x103C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.HIT_OTHER_CORE_FWD OCR.OTHER.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000122",
+ "MSRValue": "0x083C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000010",
+ "MSRValue": "0x043C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.NO_SNOOP_NEEDED OCR.OTHER.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000020",
+ "MSRValue": "0x013C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000002",
+ "MSRValue": "0x103FC08000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000004",
+ "MSRValue": "0x083FC08000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.OTHER.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000490",
+ "MSRValue": "0x023C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.OTHER.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800080",
+ "MSRValue": "0x00BC008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000122",
+ "MSRValue": "0x3F84008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000100",
+ "MSRValue": "0x1004008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404008000",
+ "MSRValue": "0x0804008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000100",
+ "MSRValue": "0x0404008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000490",
+ "MSRValue": "0x0104008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000001",
+ "MSRValue": "0x0204008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000400",
+ "MSRValue": "0x0604008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE OCR.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000100",
+ "MSRValue": "0x0084008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -3131,1426 +3062,1326 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
- "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084008000",
+ "MSRValue": "0x3F90008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000001",
+ "MSRValue": "0x1010008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000100",
+ "MSRValue": "0x0810008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000002",
+ "MSRValue": "0x0410008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000491",
+ "MSRValue": "0x0110008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000120",
+ "MSRValue": "0x0210008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000490",
+ "MSRValue": "0x0090008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP OCR.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000001",
+ "MSRValue": "0x3FBC000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE OCR.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000004",
+ "MSRValue": "0x103C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000491",
+ "MSRValue": "0x083C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000490",
+ "MSRValue": "0x043C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000010",
+ "MSRValue": "0x013C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC007F7",
+ "MSRValue": "0x103FC00400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604008000",
+ "MSRValue": "0x083FC00400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000010",
+ "MSRValue": "0x023C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000002",
+ "MSRValue": "0x00BC000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC007F7",
+ "MSRValue": "0x3F84000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000001",
+ "MSRValue": "0x1004000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000122",
+ "MSRValue": "0x0804000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000080",
+ "MSRValue": "0x0404000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000100",
+ "MSRValue": "0x0104000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000004",
+ "MSRValue": "0x0204000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000491",
+ "MSRValue": "0x0604000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000002",
+ "MSRValue": "0x0084000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B808000",
+ "MSRValue": "0x063B800400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000002",
+ "MSRValue": "0x3F90000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000002",
+ "MSRValue": "0x1010000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000010",
+ "MSRValue": "0x0810000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000490",
+ "MSRValue": "0x0410000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC08000",
+ "MSRValue": "0x0110000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800002",
+ "MSRValue": "0x0210000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000020",
+ "MSRValue": "0x0090000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP OCR.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000001",
+ "MSRValue": "0x3FBC000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000002",
+ "MSRValue": "0x103C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000120",
+ "MSRValue": "0x083C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10100007F7",
+ "MSRValue": "0x043C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000400",
+ "MSRValue": "0x013C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000100",
+ "MSRValue": "0x103FC00010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000002",
+ "MSRValue": "0x083FC00010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000002",
+ "MSRValue": "0x023C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00080",
+ "MSRValue": "0x00BC000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08040007F7",
+ "MSRValue": "0x3F84000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000100",
+ "MSRValue": "0x1004000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000400",
+ "MSRValue": "0x0804000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000020",
+ "MSRValue": "0x0404000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90008000",
+ "MSRValue": "0x0104000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00491",
+ "MSRValue": "0x0204000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000004",
+ "MSRValue": "0x0604000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410008000",
+ "MSRValue": "0x0084000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000004",
+ "MSRValue": "0x063B800010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000120",
+ "MSRValue": "0x3F90000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000001",
+ "MSRValue": "0x1010000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01100007F7",
+ "MSRValue": "0x0810000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000001",
+ "MSRValue": "0x0410000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000010",
+ "MSRValue": "0x0110000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000080",
+ "MSRValue": "0x0210000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804008000",
+ "MSRValue": "0x0090000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.ANY_SNOOP OCR.PF_L2_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000001",
+ "MSRValue": "0x3FBC000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE OCR.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000020",
+ "MSRValue": "0x103C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000080",
+ "MSRValue": "0x083C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000490",
+ "MSRValue": "0x043C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000020",
+ "MSRValue": "0x013C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000100",
+ "MSRValue": "0x103FC00020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000001",
+ "MSRValue": "0x083FC00020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000100",
+ "MSRValue": "0x023C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000100",
+ "MSRValue": "0x00BC000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY",
- "PublicDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions.",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.SNOOP_MISS OCR.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000120",
+ "MSRValue": "0x3F84000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000020",
+ "MSRValue": "0x1004000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000080",
+ "MSRValue": "0x0804000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000080",
+ "MSRValue": "0x0404000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000002",
+ "MSRValue": "0x0104000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000080",
+ "MSRValue": "0x0204000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000490",
+ "MSRValue": "0x0604000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000120",
+ "MSRValue": "0x0084000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP OCR.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000004",
+ "MSRValue": "0x063B800020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.ANY_SNOOP OCR.ALL_READS.L3_MISS.ANY_SNOOP OCR.ALL_READS.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC0007F7",
+ "MSRValue": "0x3F90000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000490",
+ "MSRValue": "0x1010000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00400",
+ "MSRValue": "0x0810000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000020",
+ "MSRValue": "0x0410000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000002",
+ "MSRValue": "0x0110000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to any reasons (multiple categories may count as one).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED",
- "PEBS": "1",
- "PublicDescription": "Number of times RTM abort was triggered.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000020",
+ "MSRValue": "0x0210000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000490",
+ "MSRValue": "0x0090000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP OCR.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000020",
+ "MSRValue": "0x3FBC000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000020",
+ "MSRValue": "0x103C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000100",
+ "MSRValue": "0x083C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010008000",
+ "MSRValue": "0x043C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000491",
+ "MSRValue": "0x013C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800490",
+ "MSRValue": "0x103FC00080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000100",
+ "MSRValue": "0x083FC00080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP OCR.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000080",
+ "MSRValue": "0x023C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000020",
+ "MSRValue": "0x00BC000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000001",
+ "MSRValue": "0x3F84000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000490",
+ "MSRValue": "0x1004000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with at least 1 Demand Data Read requests who miss L3 cache in the superQ.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_L3_MISS_DEMAND_DATA_RD",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000010",
+ "MSRValue": "0x0804000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL089",
- "EventCode": "0xC3",
- "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
- "PublicDescription": "Counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:a. memory disambiguation,b. external snoop, orc. cross SMT-HW-thread snoop (stores) hitting load buffer.",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0404000080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
- "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000010",
+ "MSRValue": "0x0104000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000020",
+ "MSRValue": "0x0204000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000002",
+ "MSRValue": "0x0604000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000080",
+ "MSRValue": "0x0084000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000010",
+ "MSRValue": "0x063B800080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000122",
+ "MSRValue": "0x3F90000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000122",
+ "MSRValue": "0x1010000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -4570,52 +4401,50 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000001",
+ "MSRValue": "0x0410000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810008000",
+ "MSRValue": "0x0110000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00122",
+ "MSRValue": "0x0210000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
"MSRValue": "0x0090000080",
"Offcore": "1",
@@ -4624,526 +4453,544 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE OCR.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.ANY_SNOOP OCR.PF_L3_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000020",
+ "MSRValue": "0x3FBC000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE OCR.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000002",
+ "MSRValue": "0x103C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C0007F7",
+ "MSRValue": "0x083C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000001",
+ "MSRValue": "0x043C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_EVENTS",
- "PublicDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).",
- "SampleAfterValue": "2000003",
- "UMask": "0x80"
- },
- {
- "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04100007F7",
+ "MSRValue": "0x013C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.SNOOP_NONE OCR.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000120",
+ "MSRValue": "0x103FC00100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000001",
+ "MSRValue": "0x083FC00100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.SNOOP_MISS OCR.ALL_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000122",
+ "MSRValue": "0x023C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110008000",
+ "MSRValue": "0x00BC000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010008000",
+ "MSRValue": "0x3F84000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000400",
+ "MSRValue": "0x1004000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "6",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS",
- "SampleAfterValue": "2000003",
- "UMask": "0x6"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000122",
+ "MSRValue": "0x0804000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000400",
+ "MSRValue": "0x0404000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000100",
+ "MSRValue": "0x0104000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000001",
+ "MSRValue": "0x0204000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00400",
+ "MSRValue": "0x0604000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000400",
+ "MSRValue": "0x0084000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204008000",
+ "MSRValue": "0x063B800100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090008000",
+ "MSRValue": "0x3F90000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08100007F7",
+ "MSRValue": "0x1010000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000004",
+ "MSRValue": "0x0810000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000491",
+ "MSRValue": "0x0410000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00002",
+ "MSRValue": "0x0110000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000004",
+ "MSRValue": "0x0210000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800122",
+ "MSRValue": "0x0090000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "Demand Data Read requests who miss L3 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD",
+ "PublicDescription": "Demand Data Read requests who miss L3 cache.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Cycles with at least 1 Demand Data Read requests who miss L3 cache in the superQ.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_L3_MISS_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts number of Offcore outstanding Demand Data Read requests that miss L3 cache in the superQ every cycle.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Cycles with at least 6 Demand Data Read requests that miss L3 cache in the superQ.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "6",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC007F7",
+ "MSRValue": "0x3FBC000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000122",
+ "MSRValue": "0x103C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000100",
+ "MSRValue": "0x083C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000004",
+ "MSRValue": "0x043C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000120",
+ "MSRValue": "0x013C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02100007F7",
+ "MSRValue": "0x103FC00491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.REMOTE_HITM OCR.ALL_READS.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC007F7",
+ "MSRValue": "0x083FC00491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000490",
+ "MSRValue": "0x023C000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.ANY_SNOOP OCR.PF_L3_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000100",
+ "MSRValue": "0x00BC000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000004",
+ "MSRValue": "0x3F84000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000490",
+ "MSRValue": "0x1004000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000491",
+ "MSRValue": "0x0804000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
"MSRValue": "0x0404000491",
"Offcore": "1",
@@ -5152,2707 +4999,2702 @@
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00002",
+ "MSRValue": "0x0104000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to hardware timer expiration.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_TIMER",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.REMOTE_HITM OCR.ALL_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00122",
+ "MSRValue": "0x0204000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000491",
+ "MSRValue": "0x0604000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00080",
+ "MSRValue": "0x0084000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800004",
+ "MSRValue": "0x063B800491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000490",
+ "MSRValue": "0x3F90000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90008000",
+ "MSRValue": "0x1010000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000490",
+ "MSRValue": "0x0810000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000010",
+ "MSRValue": "0x0410000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000020",
+ "MSRValue": "0x0110000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000001",
+ "MSRValue": "0x0210000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000100",
+ "MSRValue": "0x0090000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C008000",
+ "MSRValue": "0x3FBC000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000400",
+ "MSRValue": "0x103C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800491",
+ "MSRValue": "0x083C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000020",
+ "MSRValue": "0x043C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604008000",
+ "MSRValue": "0x013C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000100",
+ "MSRValue": "0x103FC00490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x20",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000080",
+ "MSRValue": "0x083FC00490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000122",
+ "MSRValue": "0x023C000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000020",
+ "MSRValue": "0x00BC000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00080",
+ "MSRValue": "0x3F84000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000004",
+ "MSRValue": "0x1004000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000080",
+ "MSRValue": "0x0804000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000122",
+ "MSRValue": "0x0404000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000100",
+ "MSRValue": "0x0104000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000002",
+ "MSRValue": "0x0204000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000001",
+ "MSRValue": "0x0604000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_MEM",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000080",
+ "MSRValue": "0x0084000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.SNOOP_NONE OCR.ALL_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000122",
+ "MSRValue": "0x063B800490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800120",
+ "MSRValue": "0x3F90000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC08000",
+ "MSRValue": "0x1010000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000490",
+ "MSRValue": "0x0810000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000004",
+ "MSRValue": "0x0410000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000002",
+ "MSRValue": "0x0110000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000010",
+ "MSRValue": "0x0210000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000491",
+ "MSRValue": "0x0090000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000010",
+ "MSRValue": "0x3FBC000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C008000",
+ "MSRValue": "0x103C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210008000",
+ "MSRValue": "0x083C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000080",
+ "MSRValue": "0x043C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00001",
+ "MSRValue": "0x013C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.SNOOP_NONE OCR.ALL_READS.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC0007F7",
+ "MSRValue": "0x103FC00120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000491",
+ "MSRValue": "0x083FC00120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC0007F7",
+ "MSRValue": "0x023C000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000491",
+ "MSRValue": "0x00BC000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00001",
+ "MSRValue": "0x3F84000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000020",
+ "MSRValue": "0x1004000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000001",
+ "MSRValue": "0x0804000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000491",
+ "MSRValue": "0x0404000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000010",
+ "MSRValue": "0x0104000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000491",
+ "MSRValue": "0x0204000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084008000",
+ "MSRValue": "0x0604000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000020",
+ "MSRValue": "0x0084000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000020",
+ "MSRValue": "0x063B800120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000120",
+ "MSRValue": "0x3F90000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000120",
+ "MSRValue": "0x1010000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00100",
+ "MSRValue": "0x0810000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.SNOOP_MISS OCR.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000491",
+ "MSRValue": "0x0410000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800020",
+ "MSRValue": "0x0110000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000490",
+ "MSRValue": "0x0210000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000004",
+ "MSRValue": "0x0090000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000001",
+ "MSRValue": "0x3FBC0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000080",
+ "MSRValue": "0x103C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000122",
+ "MSRValue": "0x083C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000020",
+ "MSRValue": "0x043C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000001",
+ "MSRValue": "0x013C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000122",
+ "MSRValue": "0x103FC007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC008000",
+ "MSRValue": "0x083FC007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000491",
+ "MSRValue": "0x023C0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000120",
+ "MSRValue": "0x00BC0007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000020",
+ "MSRValue": "0x3F840007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000080",
+ "MSRValue": "0x10040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000120",
+ "MSRValue": "0x08040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000120",
+ "MSRValue": "0x04040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000400",
+ "MSRValue": "0x01040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000001",
+ "MSRValue": "0x02040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.ANY_SNOOP OCR.PF_L2_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000020",
+ "MSRValue": "0x06040007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC0007F7",
+ "MSRValue": "0x00840007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000020",
+ "MSRValue": "0x063B8007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000001",
+ "MSRValue": "0x3F900007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000100",
+ "MSRValue": "0x10100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000001",
+ "MSRValue": "0x08100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000080",
+ "MSRValue": "0x04100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000004",
+ "MSRValue": "0x01100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000001",
+ "MSRValue": "0x02100007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000491",
+ "MSRValue": "0x00900007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000122",
+ "MSRValue": "0x3FBC000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000020",
+ "MSRValue": "0x103C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000400",
+ "MSRValue": "0x083C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000002",
+ "MSRValue": "0x043C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000020",
+ "MSRValue": "0x013C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000120",
+ "MSRValue": "0x103FC00122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.HITM_OTHER_CORE OCR.OTHER.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C008000",
+ "MSRValue": "0x083FC00122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000004",
+ "MSRValue": "0x023C000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104008000",
+ "MSRValue": "0x00BC000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x100",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "503",
- "TakenAlone": "1",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3F84000122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000004",
+ "MSRValue": "0x1004000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000100",
+ "MSRValue": "0x0804000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000100",
+ "MSRValue": "0x0404000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000002",
+ "MSRValue": "0x0104000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800004",
+ "MSRValue": "0x0204000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000080",
+ "MSRValue": "0x0604000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x10",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "20011",
- "TakenAlone": "1",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0084000122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000400",
+ "MSRValue": "0x063B800122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000020",
+ "MSRValue": "0x3F90000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
- "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000080",
+ "MSRValue": "0x1010000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000491",
+ "MSRValue": "0x0810000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000400",
+ "MSRValue": "0x0410000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000001",
+ "MSRValue": "0x0110000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000010",
+ "MSRValue": "0x0210000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000002",
+ "MSRValue": "0x0090000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800400",
+ "MSRValue": "0x3FBC000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times a transactional abort was signaled due to a data capacity limitation for transactional reads or writes.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_CAPACITY",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_MEMTYPE",
- "PublicDescription": "Number of times an HLE execution aborted due to incompatible memory type.",
- "SampleAfterValue": "2000003",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "Number of times an RTM execution started.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.START",
- "PublicDescription": "Number of times we entered an RTM region. Does not count nested transactions.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000122",
+ "MSRValue": "0x103C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000490",
+ "MSRValue": "0x083C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404008000",
+ "MSRValue": "0x043C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000100",
+ "MSRValue": "0x013C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000001",
+ "MSRValue": "0x103FC00004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000490",
+ "MSRValue": "0x083FC00004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000490",
+ "MSRValue": "0x023C000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000080",
+ "MSRValue": "0x00BC000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x200",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "101",
- "TakenAlone": "1",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3F84000004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_UNFRIENDLY",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000010",
+ "MSRValue": "0x1004000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000020",
+ "MSRValue": "0x0804000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000080",
+ "MSRValue": "0x0404000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000120",
+ "MSRValue": "0x0104000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000490",
+ "MSRValue": "0x0204000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000010",
+ "MSRValue": "0x0604000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02100007F7",
+ "MSRValue": "0x0084000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C0007F7",
+ "MSRValue": "0x063B800004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000020",
+ "MSRValue": "0x3F90000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED OCR.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000004",
+ "MSRValue": "0x1010000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE OCR.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000400",
+ "MSRValue": "0x0810000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000002",
+ "MSRValue": "0x0410000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000122",
+ "MSRValue": "0x0110000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00001",
+ "MSRValue": "0x0210000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000001",
+ "MSRValue": "0x0090000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800020",
+ "MSRValue": "0x3FBC000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04100007F7",
+ "MSRValue": "0x103C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000080",
+ "MSRValue": "0x083C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.ANY_SNOOP OCR.ALL_RFO.L3_MISS.ANY_SNOOP OCR.ALL_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000122",
+ "MSRValue": "0x043C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000490",
+ "MSRValue": "0x013C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000490",
+ "MSRValue": "0x103FC00001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000004",
+ "MSRValue": "0x083FC00001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00120",
+ "MSRValue": "0x023C000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000004",
+ "MSRValue": "0x00BC000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00010",
+ "MSRValue": "0x3F84000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with at least 6 Demand Data Read requests that miss L3 cache in the superQ.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "6",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD_GE_6",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x40",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "2003",
- "TakenAlone": "1",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x1004000001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000122",
+ "MSRValue": "0x0804000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000002",
+ "MSRValue": "0x0404000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000010",
+ "MSRValue": "0x0104000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000490",
+ "MSRValue": "0x0204000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00120",
+ "MSRValue": "0x0604000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000122",
+ "MSRValue": "0x0084000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.NO_SNOOP_NEEDED OCR.OTHER.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C008000",
+ "MSRValue": "0x063B800001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000120",
+ "MSRValue": "0x3F90000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800010",
+ "MSRValue": "0x1010000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000491",
+ "MSRValue": "0x0810000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00020",
+ "MSRValue": "0x0410000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800400",
+ "MSRValue": "0x0110000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.ANY_SNOOP OCR.OTHER.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC008000",
+ "MSRValue": "0x0210000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000004",
+ "MSRValue": "0x0090000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000122",
+ "MSRValue": "0x3FBC000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000122",
+ "MSRValue": "0x103C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000080",
+ "MSRValue": "0x083C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000490",
+ "MSRValue": "0x043C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000080",
+ "MSRValue": "0x013C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00020",
+ "MSRValue": "0x103FC00002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00120",
+ "MSRValue": "0x083FC00002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000080",
+ "MSRValue": "0x023C000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000120",
+ "MSRValue": "0x00BC000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84008000",
+ "MSRValue": "0x3F84000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000100",
+ "MSRValue": "0x1004000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C008000",
+ "MSRValue": "0x0804000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000002",
+ "MSRValue": "0x0404000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE OCR.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000002",
+ "MSRValue": "0x0104000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00400",
+ "MSRValue": "0x0204000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000120",
+ "MSRValue": "0x0604000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000491",
+ "MSRValue": "0x0084000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles while L3 cache miss demand load is outstanding.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "2",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.CYCLES_L3_MISS",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC08000",
+ "MSRValue": "0x063B800002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000122",
+ "MSRValue": "0x3F90000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800001",
+ "MSRValue": "0x1010000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C008000",
+ "MSRValue": "0x0810000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000080",
+ "MSRValue": "0x0410000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000122",
+ "MSRValue": "0x0110000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000120",
+ "MSRValue": "0x0210000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C0007F7",
+ "MSRValue": "0x0090000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000002",
+ "MSRValue": "0x3FBC008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.SNOOP_NONE OCR.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000491",
+ "MSRValue": "0x103C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000491",
+ "MSRValue": "0x083C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000122",
+ "MSRValue": "0x043C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000490",
+ "MSRValue": "0x013C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000001",
+ "MSRValue": "0x103FC08000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -7873,490 +7715,476 @@
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000120",
+ "MSRValue": "0x023C008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000491",
+ "MSRValue": "0x00BC008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000020",
+ "MSRValue": "0x3F84008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000080",
+ "MSRValue": "0x1004008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000001",
+ "MSRValue": "0x0804008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000491",
+ "MSRValue": "0x0404008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004008000",
+ "MSRValue": "0x0104008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000010",
+ "MSRValue": "0x0204008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000010",
+ "MSRValue": "0x0604008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution successfully committed",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.COMMIT",
- "PublicDescription": "Number of times RTM commit succeeded.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000400",
+ "MSRValue": "0x0084008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000491",
+ "MSRValue": "0x063B808000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to unfriendly events (such as interrupts).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_EVENTS",
- "SampleAfterValue": "2000003",
- "UMask": "0x80"
- },
- {
- "BriefDescription": "Counts number of Offcore outstanding Demand Data Read requests that miss L3 cache in the superQ every cycle.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.ANY_SNOOP OCR.DEMAND_RFO.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000002",
+ "MSRValue": "0x3F90008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000490",
+ "MSRValue": "0x1010008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04040007F7",
+ "MSRValue": "0x0810008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000080",
+ "MSRValue": "0x0410008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000001",
+ "MSRValue": "0x0110008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F900007F7",
+ "MSRValue": "0x0210008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000004",
+ "MSRValue": "0x0090008000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000120",
+ "MSRValue": "0x3FBC000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000010",
+ "MSRValue": "0x103C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C008000",
+ "MSRValue": "0x083C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000020",
+ "MSRValue": "0x043C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00004",
+ "MSRValue": "0x013C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED OCR.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01040007F7",
+ "MSRValue": "0x103FC00400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000004",
+ "MSRValue": "0x083FC00400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800080",
+ "MSRValue": "0x023C000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000400",
+ "MSRValue": "0x00BC000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000120",
+ "MSRValue": "0x3F84000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000020",
+ "MSRValue": "0x1004000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000080",
+ "MSRValue": "0x0804000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000010",
+ "MSRValue": "0x0404000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.REMOTE_HITM OCR.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00491",
+ "MSRValue": "0x0104000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000122",
+ "MSRValue": "0x0204000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000001",
+ "MSRValue": "0x0604000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -8377,1541 +8205,1713 @@
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00001",
+ "MSRValue": "0x063B800400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000120",
+ "MSRValue": "0x3F90000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00004",
+ "MSRValue": "0x1010000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000491",
+ "MSRValue": "0x0810000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00002",
+ "MSRValue": "0x0410000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000120",
+ "MSRValue": "0x0110000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000490",
+ "MSRValue": "0x0210000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00100",
+ "MSRValue": "0x0090000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000002",
+ "MSRValue": "0x3FBC000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00100",
+ "MSRValue": "0x103C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800001",
+ "MSRValue": "0x083C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000002",
+ "MSRValue": "0x043C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000080",
+ "MSRValue": "0x013C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000122",
+ "MSRValue": "0x103FC00010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000002",
+ "MSRValue": "0x083FC00010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000080",
+ "MSRValue": "0x023C000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000400",
+ "MSRValue": "0x00BC000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED OCR.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000080",
+ "MSRValue": "0x3F84000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000010",
+ "MSRValue": "0x1004000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000400",
+ "MSRValue": "0x0804000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C008000",
+ "MSRValue": "0x0404000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000004",
+ "MSRValue": "0x0104000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000001",
+ "MSRValue": "0x0204000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000400",
+ "MSRValue": "0x0604000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000080",
+ "MSRValue": "0x0084000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210008000",
+ "MSRValue": "0x063B800010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000100",
+ "MSRValue": "0x3F90000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD OCR.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00491",
+ "MSRValue": "0x1010000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000491",
+ "MSRValue": "0x0810000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read requests who miss L3 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD",
- "PublicDescription": "Demand Data Read requests who miss L3 cache.",
- "SampleAfterValue": "100003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01100007F7",
+ "MSRValue": "0x0410000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000010",
+ "MSRValue": "0x0110000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000400",
+ "MSRValue": "0x0210000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02040007F7",
+ "MSRValue": "0x0090000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000120",
+ "MSRValue": "0x3FBC000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000400",
+ "MSRValue": "0x103C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_READS.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00900007F7",
+ "MSRValue": "0x083C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000120",
+ "MSRValue": "0x043C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000100",
+ "MSRValue": "0x013C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00BC000122",
+ "MSRValue": "0x103FC00020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000490",
+ "MSRValue": "0x083FC00020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000080",
+ "MSRValue": "0x023C000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000400",
+ "MSRValue": "0x00BC000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE OCR.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000004",
+ "MSRValue": "0x3F84000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000491",
+ "MSRValue": "0x1004000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000400",
+ "MSRValue": "0x0804000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000020",
+ "MSRValue": "0x0404000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000020",
+ "MSRValue": "0x0104000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000491",
+ "MSRValue": "0x0204000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08040007F7",
+ "MSRValue": "0x0604000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000100",
+ "MSRValue": "0x0084000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000004",
+ "MSRValue": "0x063B800020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000122",
+ "MSRValue": "0x3F90000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00010",
+ "MSRValue": "0x1010000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000002",
+ "MSRValue": "0x0810000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0084000004",
+ "MSRValue": "0x0410000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000120",
+ "MSRValue": "0x0110000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000001",
+ "MSRValue": "0x0210000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED",
- "PEBS": "1",
- "PublicDescription": "Number of times HLE abort was triggered.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C008000",
+ "MSRValue": "0x0090000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x013C000010",
+ "MSRValue": "0x3FBC000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000120",
+ "MSRValue": "0x103C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000020",
+ "MSRValue": "0x083C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000010",
+ "MSRValue": "0x043C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000004",
+ "MSRValue": "0x013C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000491",
+ "MSRValue": "0x103FC00080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000491",
+ "MSRValue": "0x083FC00080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000400",
+ "MSRValue": "0x023C000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800120",
+ "MSRValue": "0x00BC000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000490",
+ "MSRValue": "0x3F84000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F84000491",
+ "MSRValue": "0x1004000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000400",
+ "MSRValue": "0x0804000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP OCR.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000010",
+ "MSRValue": "0x0404000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000122",
+ "MSRValue": "0x0104000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000004",
+ "MSRValue": "0x0204000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000004",
+ "MSRValue": "0x0604000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000400",
+ "MSRValue": "0x0084000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000080",
+ "MSRValue": "0x063B800080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000491",
+ "MSRValue": "0x3F90000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000001",
+ "MSRValue": "0x1010000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0104000001",
+ "MSRValue": "0x0810000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00010",
+ "MSRValue": "0x0410000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C000491",
+ "MSRValue": "0x0110000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_MISS.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x043C000010",
+ "MSRValue": "0x0210000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000100",
+ "MSRValue": "0x0090000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0804000400",
+ "MSRValue": "0x3FBC000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000020",
+ "MSRValue": "0x103C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0210000122",
+ "MSRValue": "0x083C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810000001",
+ "MSRValue": "0x043C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F90000400",
+ "MSRValue": "0x013C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.REMOTE_HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0090000490",
+ "MSRValue": "0x103FC00100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000400",
+ "MSRValue": "0x083FC00100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000120",
+ "MSRValue": "0x023C000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00020",
+ "MSRValue": "0x00BC000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution started.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.START",
- "PublicDescription": "Number of times we entered an HLE region. Does not count nested transactions.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1004000020",
+ "MSRValue": "0x3F84000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000400",
+ "MSRValue": "0x1004000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00004",
+ "MSRValue": "0x0804000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000491",
+ "MSRValue": "0x0404000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C000120",
+ "MSRValue": "0x0104000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0410000400",
+ "MSRValue": "0x0204000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103C0007F7",
+ "MSRValue": "0x0604000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0404000100",
+ "MSRValue": "0x0084000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1010000100",
+ "MSRValue": "0x063B800100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_MISS.HIT_OTHER_CORE_FWD OCR.OTHER.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_MISS.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C008000",
+ "MSRValue": "0x3F90000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.OTHER.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0810008000",
+ "MSRValue": "0x1010000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_MISS.REMOTE_HITM OCR.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00120",
+ "MSRValue": "0x0810000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0204000010",
+ "MSRValue": "0x0410000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
+ "Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS_LOCAL_DRAM.SNOOP_NONE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00840007F7",
+ "MSRValue": "0x0110000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x4",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.",
+ "Deprecated": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0210000100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS.SNOOP_MISS",
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Deprecated": "1",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_MISS",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_HOP1_DRAM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x023C000100",
+ "MSRValue": "0x0090000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.",
+ "BriefDescription": "Number of times an RTM execution aborted due to any reasons (multiple categories may count as one).",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x8",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "50021",
- "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "PEBS": "1",
+ "PublicDescription": "Number of times RTM abort was triggered.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_EVENTS",
+ "PublicDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_MEM",
+ "PublicDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_MEMTYPE",
+ "PublicDescription": "Number of times an RTM execution aborted due to incompatible memory type.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to uncommon conditions.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_TIMER",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY",
+ "PublicDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution successfully committed",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "PublicDescription": "Number of times RTM commit succeeded.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution started.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.START",
+ "PublicDescription": "Number of times we entered an RTM region. Does not count nested transactions.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_MISS.HIT_OTHER_CORE_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083C0007F7",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC1",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Deprecated": "1",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_REMOTE_HOP1_DRAM.NO_SNOOP_NEEDED",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0110000001",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC2",
+ "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC3",
+ "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC4",
+ "PublicDescription": "RTM region detected inside HLE.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC5",
+ "PublicDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data capacity limitation for transactional reads or writes.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_CAPACITY",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "PublicDescription": "Number of times a TSX line had a cache conflict.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "PublicDescription": "Number of times we could not allocate Lock Buffer.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/other.json b/tools/perf/pmu-events/arch/x86/cascadelakex/other.json
index f77d78e90954..2f111a22d81f 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/other.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/other.json
@@ -1,1335 +1,1382 @@
[
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the Non-AVX turbo schedule.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100010",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.LVL0_TURBO_LICENSE",
+ "PublicDescription": "Core cycles where the core was running with power-delivery for baseline license level 0. This includes non-AVX codes, SSE, AVX 128-bit, and low-current AVX 256-bit codes.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x7"
+ },
+ {
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX2 turbo schedule.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.LVL1_TURBO_LICENSE",
+ "PublicDescription": "Core cycles where the core was running with power-delivery for license level 1. This includes high current AVX 256-bit instructions as well as low current AVX 512-bit instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x18"
+ },
+ {
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX512 turbo schedule.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.LVL2_TURBO_LICENSE",
+ "PublicDescription": "Core cycles where the core was running with power-delivery for license level 2 (introduced in Skylake Server michroarchtecture). This includes high current AVX 512-bit instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Core cycles the core was throttled due to a pending power level request.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.THROTTLE",
+ "PublicDescription": "Core cycles the out-of-order engine was throttled due to a pending power level request.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Number of hardware interrupts received by the processor.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xCB",
+ "EventName": "HW_INTERRUPTS.RECEIVED",
+ "PublicDescription": "Counts the number of hardware interruptions received by the processor.",
+ "SampleAfterValue": "203",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xFE",
+ "EventName": "IDI_MISC.WB_DOWNGRADE",
+ "PublicDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xFE",
+ "EventName": "IDI_MISC.WB_UPGRADE",
+ "PublicDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "OCR.ALL_DATA_RD.ANY_RESPONSE have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100120",
+ "MSRValue": "0x0000010491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01002007F7",
+ "MSRValue": "0x3F803C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0491",
+ "MSRValue": "0x10003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020122",
+ "MSRValue": "0x08003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08000407F7",
+ "MSRValue": "0x04003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100004",
+ "MSRValue": "0x01003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080088000",
+ "MSRValue": "0x08007C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_MISS OCR.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100001",
+ "MSRValue": "0x02003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_NONE OCR.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100122",
+ "MSRValue": "0x00803C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000028000",
+ "MSRValue": "0x3F80080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040002",
+ "MSRValue": "0x1000080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200020",
+ "MSRValue": "0x0800080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100120",
+ "MSRValue": "0x0400080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080004",
+ "MSRValue": "0x0100080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0120",
+ "MSRValue": "0x0200080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100491",
+ "MSRValue": "0x0080080491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100120",
+ "MSRValue": "0x3F80200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100001",
+ "MSRValue": "0x1000200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0001",
+ "MSRValue": "0x0800200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000048000",
+ "MSRValue": "0x0400200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020020",
+ "MSRValue": "0x0100200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100002",
+ "MSRValue": "0x0200200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080080",
+ "MSRValue": "0x0080200491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200080",
+ "MSRValue": "0x3F80040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01000407F7",
+ "MSRValue": "0x1000040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80088000",
+ "MSRValue": "0x0800040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0020",
+ "MSRValue": "0x0400040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080120",
+ "MSRValue": "0x0100040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0490",
+ "MSRValue": "0x0200040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020122",
+ "MSRValue": "0x0080040491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200491",
+ "MSRValue": "0x3F80100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80408000",
+ "MSRValue": "0x1000100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020490",
+ "MSRValue": "0x0800100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F804007F7",
+ "MSRValue": "0x0400100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xFE",
- "EventName": "IDI_MISC.WB_DOWNGRADE",
- "PublicDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly.",
- "SampleAfterValue": "100003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080002",
+ "MSRValue": "0x0100100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE OCR.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0004",
+ "MSRValue": "0x0200100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080120",
+ "MSRValue": "0x0080100491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200001",
+ "MSRValue": "0x3F80400491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040004",
+ "MSRValue": "0x0080400491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80108000",
+ "MSRValue": "0x0100400491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C8000",
+ "MSRValue": "0x3F80020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400491",
+ "MSRValue": "0x1000020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0010",
+ "MSRValue": "0x0800020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100108000",
+ "MSRValue": "0x0400020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02002007F7",
+ "MSRValue": "0x0100020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0400",
+ "MSRValue": "0x0200020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040490",
+ "MSRValue": "0x0080020491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.ANY_RESPONSE have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080020",
+ "MSRValue": "0x0000010490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020004",
+ "MSRValue": "0x3F803C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080120",
+ "MSRValue": "0x10003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100122",
+ "MSRValue": "0x08003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0100",
+ "MSRValue": "0x04003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100490",
+ "MSRValue": "0x01003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C8000",
+ "MSRValue": "0x08007C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080400",
+ "MSRValue": "0x02003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100001",
+ "MSRValue": "0x00803C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT.SNOOP_MISS OCR.ALL_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0122",
+ "MSRValue": "0x3F80080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040002",
+ "MSRValue": "0x1000080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100080",
+ "MSRValue": "0x0800080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200122",
+ "MSRValue": "0x0400080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800088000",
+ "MSRValue": "0x0100080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020491",
+ "MSRValue": "0x0200080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080010",
+ "MSRValue": "0x0080080490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0400",
+ "MSRValue": "0x3F80200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080002",
+ "MSRValue": "0x1000200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040122",
+ "MSRValue": "0x0800200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0122",
+ "MSRValue": "0x0400200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0080",
+ "MSRValue": "0x0100200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080001",
+ "MSRValue": "0x0200200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040400",
+ "MSRValue": "0x0080200490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs have any response type.",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.ANY_RESPONSE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010020",
+ "MSRValue": "0x3F80040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020002",
+ "MSRValue": "0x1000040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200004",
+ "MSRValue": "0x0800040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200028000",
+ "MSRValue": "0x0400040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080100",
+ "MSRValue": "0x0100040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400080",
+ "MSRValue": "0x0200040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08000807F7",
+ "MSRValue": "0x0080040490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200122",
+ "MSRValue": "0x3F80100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040020",
+ "MSRValue": "0x1000100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200001",
+ "MSRValue": "0x0800100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040001",
+ "MSRValue": "0x0400100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400400",
+ "MSRValue": "0x0100100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE OCR.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0100",
+ "MSRValue": "0x0200100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040010",
+ "MSRValue": "0x0080100490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800048000",
+ "MSRValue": "0x3F80400490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080001",
+ "MSRValue": "0x0080400490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080491",
+ "MSRValue": "0x0100400490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100020",
+ "MSRValue": "0x3F80020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080020",
+ "MSRValue": "0x1000020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.ANY_SNOOP OCR.DEMAND_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0002",
+ "MSRValue": "0x0800020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020491",
+ "MSRValue": "0x0400020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020010",
+ "MSRValue": "0x0100020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020490",
+ "MSRValue": "0x0200020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0122",
+ "MSRValue": "0x0080020490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.ANY_RESPONSE have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020001",
+ "MSRValue": "0x0000010120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0001",
+ "MSRValue": "0x3F803C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020100",
+ "MSRValue": "0x10003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200010",
+ "MSRValue": "0x08003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100490",
+ "MSRValue": "0x04003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.ANY_RESPONSE have any response type.",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.ANY_RESPONSE",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010490",
+ "MSRValue": "0x01003C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800108000",
+ "MSRValue": "0x08007C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -1349,2756 +1396,2717 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.SNOOP_NONE OCR.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040400",
+ "MSRValue": "0x00803C0120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020010",
+ "MSRValue": "0x3F80080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200048000",
+ "MSRValue": "0x1000080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100491",
+ "MSRValue": "0x0800080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.ANY_SNOOP OCR.ALL_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040122",
+ "MSRValue": "0x0400080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200002",
+ "MSRValue": "0x0100080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020100",
+ "MSRValue": "0x0200080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_E.ANY_SNOOP OCR.ALL_READS.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F800807F7",
+ "MSRValue": "0x0080080120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080400",
+ "MSRValue": "0x3F80200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020100",
+ "MSRValue": "0x1000200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200490",
+ "MSRValue": "0x0800200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08000207F7",
+ "MSRValue": "0x0400200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04000207F7",
+ "MSRValue": "0x0100200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080490",
+ "MSRValue": "0x0200200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200491",
+ "MSRValue": "0x0080200120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080120",
+ "MSRValue": "0x3F80040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080122",
+ "MSRValue": "0x1000040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200491",
+ "MSRValue": "0x0800040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0100",
+ "MSRValue": "0x0400040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080001",
+ "MSRValue": "0x0100040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080001",
+ "MSRValue": "0x0200040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400088000",
+ "MSRValue": "0x0080040120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040122",
+ "MSRValue": "0x3F80100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040001",
+ "MSRValue": "0x1000100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.ANY_RESPONSE have any response type.",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.ANY_RESPONSE",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010122",
+ "MSRValue": "0x0800100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads have any response type.",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.ANY_RESPONSE",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010004",
+ "MSRValue": "0x0400100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080004",
+ "MSRValue": "0x0100100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040100",
+ "MSRValue": "0x0200100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0002",
+ "MSRValue": "0x0080100120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400400",
+ "MSRValue": "0x3F80400120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0001",
+ "MSRValue": "0x0080400120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.ANY_SNOOP OCR.PF_L2_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0020",
+ "MSRValue": "0x0100400120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080020",
+ "MSRValue": "0x3F80020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400020",
+ "MSRValue": "0x1000020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200020",
+ "MSRValue": "0x0800020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020080",
+ "MSRValue": "0x0400020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT.SNOOP_MISS OCR.ALL_READS.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C07F7",
+ "MSRValue": "0x0100020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020490",
+ "MSRValue": "0x0200020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200001",
+ "MSRValue": "0x0080020120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_READS.ANY_RESPONSE have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400010",
+ "MSRValue": "0x00000107F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT.ANY_SNOOP OCR.ALL_READS.L3_HIT.ANY_SNOOP OCR.ALL_READS.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080100",
+ "MSRValue": "0x3F803C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200002",
+ "MSRValue": "0x10003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020020",
+ "MSRValue": "0x08003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100088000",
+ "MSRValue": "0x04003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200100",
+ "MSRValue": "0x01003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200490",
+ "MSRValue": "0x08007C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT.SNOOP_MISS OCR.ALL_READS.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040120",
+ "MSRValue": "0x02003C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_READS.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT.SNOOP_NONE OCR.ALL_READS.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F800207F7",
+ "MSRValue": "0x00803C07F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_E.ANY_SNOOP OCR.ALL_READS.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200080",
+ "MSRValue": "0x3F800807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0010",
+ "MSRValue": "0x10000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100491",
+ "MSRValue": "0x08000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020120",
+ "MSRValue": "0x04000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040122",
+ "MSRValue": "0x01000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00800207F7",
+ "MSRValue": "0x02000807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100491",
+ "MSRValue": "0x00800807F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_F.ANY_SNOOP OCR.ALL_READS.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020400",
+ "MSRValue": "0x3F802007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400122",
+ "MSRValue": "0x10002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020490",
+ "MSRValue": "0x08002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02000807F7",
+ "MSRValue": "0x04002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.ALL_READS.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400100",
+ "MSRValue": "0x01002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040491",
+ "MSRValue": "0x02002007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400122",
+ "MSRValue": "0x00802007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_M.ANY_SNOOP OCR.ALL_READS.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040122",
+ "MSRValue": "0x3F800407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040004",
+ "MSRValue": "0x10000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200010",
+ "MSRValue": "0x08000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040010",
+ "MSRValue": "0x04000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0001",
+ "MSRValue": "0x01000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0120",
+ "MSRValue": "0x02000407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200100",
+ "MSRValue": "0x00800407F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_S.ANY_SNOOP OCR.ALL_READS.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100080",
+ "MSRValue": "0x3F801007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080001",
+ "MSRValue": "0x10001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200400",
+ "MSRValue": "0x08001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100010",
+ "MSRValue": "0x04001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200001",
+ "MSRValue": "0x01001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.ALL_READS.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080004",
+ "MSRValue": "0x02001007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "OCR.ALL_READS.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020010",
+ "MSRValue": "0x00801007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200490",
+ "MSRValue": "0x3F804007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040490",
+ "MSRValue": "0x00804007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020004",
+ "MSRValue": "0x01004007F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_READS.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0004",
+ "MSRValue": "0x3F800207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020004",
+ "MSRValue": "0x10000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100020",
+ "MSRValue": "0x08000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.ALL_READS.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040002",
+ "MSRValue": "0x04000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200122",
+ "MSRValue": "0x01000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_READS.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080122",
+ "MSRValue": "0x02000207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_READS.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020002",
+ "MSRValue": "0x00800207F7",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the Non-AVX turbo schedule.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x28",
- "EventName": "CORE_POWER.LVL0_TURBO_LICENSE",
- "PublicDescription": "Core cycles where the core was running with power-delivery for baseline license level 0. This includes non-AVX codes, SSE, AVX 128-bit, and low-current AVX 256-bit codes.",
- "SampleAfterValue": "200003",
- "UMask": "0x7"
- },
- {
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "OCR.ALL_RFO.ANY_RESPONSE have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080028000",
+ "MSRValue": "0x0000010122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT.ANY_SNOOP OCR.ALL_RFO.L3_HIT.ANY_SNOOP OCR.ALL_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400490",
+ "MSRValue": "0x3F803C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040002",
+ "MSRValue": "0x10003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200002",
+ "MSRValue": "0x08003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020122",
+ "MSRValue": "0x04003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400020",
+ "MSRValue": "0x01003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080004",
+ "MSRValue": "0x08007C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT.SNOOP_MISS OCR.ALL_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100491",
+ "MSRValue": "0x02003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT.SNOOP_NONE OCR.ALL_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08002007F7",
+ "MSRValue": "0x00803C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.ANY_SNOOP OCR.ALL_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200491",
+ "MSRValue": "0x3F80080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020120",
+ "MSRValue": "0x1000080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.ANY_RESPONSE have any response type.",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.ANY_RESPONSE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010120",
+ "MSRValue": "0x0800080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0122",
+ "MSRValue": "0x0400080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040100",
+ "MSRValue": "0x0100080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200004",
+ "MSRValue": "0x0200080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080010",
+ "MSRValue": "0x0080080122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.ANY_SNOOP OCR.ALL_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02000407F7",
+ "MSRValue": "0x3F80200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0020",
+ "MSRValue": "0x1000200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040080",
+ "MSRValue": "0x0800200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0002",
+ "MSRValue": "0x0400200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core cycles the core was throttled due to a pending power level request.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x28",
- "EventName": "CORE_POWER.THROTTLE",
- "PublicDescription": "Core cycles the out-of-order engine was throttled due to a pending power level request.",
- "SampleAfterValue": "200003",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE OCR.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0002",
+ "MSRValue": "0x0100200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200020",
+ "MSRValue": "0x0200200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080004",
+ "MSRValue": "0x0080200122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.ANY_SNOOP OCR.ALL_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020004",
+ "MSRValue": "0x3F80040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040400",
+ "MSRValue": "0x1000040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040120",
+ "MSRValue": "0x0800040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100001",
+ "MSRValue": "0x0400040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040002",
+ "MSRValue": "0x0100040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0001",
+ "MSRValue": "0x0200040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040400",
+ "MSRValue": "0x0080040122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.ANY_SNOOP OCR.ALL_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100010",
+ "MSRValue": "0x3F80100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020122",
+ "MSRValue": "0x1000100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests have any response type.",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.ANY_RESPONSE",
+ "EventName": "OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000018000",
+ "MSRValue": "0x0800100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100004",
+ "MSRValue": "0x0400100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.ALL_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020004",
+ "MSRValue": "0x0100100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080020",
+ "MSRValue": "0x0200100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020010",
+ "MSRValue": "0x0080100122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020002",
+ "MSRValue": "0x3F80400122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080010",
+ "MSRValue": "0x0080400122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0120",
+ "MSRValue": "0x0100400122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads have any response type.",
+ "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.ANY_RESPONSE",
+ "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010001",
+ "MSRValue": "0x3F80020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0004",
+ "MSRValue": "0x1000020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080208000",
+ "MSRValue": "0x0800020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020020",
+ "MSRValue": "0x0400020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100080",
+ "MSRValue": "0x0100020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400002",
+ "MSRValue": "0x0200020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100002",
+ "MSRValue": "0x0080020122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040120",
+ "MSRValue": "0x0000010004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP OCR.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080120",
+ "MSRValue": "0x3F803C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE OCR.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020001",
+ "MSRValue": "0x10003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.ANY_RESPONSE have any response type.",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.ANY_RESPONSE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010491",
+ "MSRValue": "0x08003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080100",
+ "MSRValue": "0x04003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED OCR.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100122",
+ "MSRValue": "0x01003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080020",
+ "MSRValue": "0x08007C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200004",
+ "MSRValue": "0x02003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400120",
+ "MSRValue": "0x00803C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020080",
+ "MSRValue": "0x3F80080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040002",
+ "MSRValue": "0x1000080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200120",
+ "MSRValue": "0x0800080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200100",
+ "MSRValue": "0x0400080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080120",
+ "MSRValue": "0x0100080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.HIT_OTHER_CORE_FWD OCR.OTHER.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C8000",
+ "MSRValue": "0x0200080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040100",
+ "MSRValue": "0x0080080004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040490",
+ "MSRValue": "0x3F80200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020100",
+ "MSRValue": "0x1000200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080490",
+ "MSRValue": "0x0800200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200020",
+ "MSRValue": "0x0400200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020400",
+ "MSRValue": "0x0100200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040100",
+ "MSRValue": "0x0200200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200100",
+ "MSRValue": "0x0080200004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020100",
+ "MSRValue": "0x3F80040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100100",
+ "MSRValue": "0x1000040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0491",
+ "MSRValue": "0x0800040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C07F7",
+ "MSRValue": "0x0400040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0004",
+ "MSRValue": "0x0100040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400491",
+ "MSRValue": "0x0200040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020491",
+ "MSRValue": "0x0080040004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400002",
+ "MSRValue": "0x3F80100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0490",
+ "MSRValue": "0x1000100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0491",
+ "MSRValue": "0x0800100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040400",
+ "MSRValue": "0x0400100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040001",
+ "MSRValue": "0x0100100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200400",
+ "MSRValue": "0x0200100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0491",
+ "MSRValue": "0x0080100004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0100",
+ "MSRValue": "0x3F80400004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100010",
+ "MSRValue": "0x0080400004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100100",
+ "MSRValue": "0x0100400004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080491",
+ "MSRValue": "0x3F80020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400100",
+ "MSRValue": "0x1000020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10002007F7",
+ "MSRValue": "0x0800020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0400",
+ "MSRValue": "0x0400020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0120",
+ "MSRValue": "0x0100020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200108000",
+ "MSRValue": "0x0200020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand code reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0100",
+ "MSRValue": "0x0080020004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020400",
+ "MSRValue": "0x0000010001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads have any response type.",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP OCR.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.ANY_RESPONSE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010010",
+ "MSRValue": "0x3F803C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100002",
+ "MSRValue": "0x10003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040491",
+ "MSRValue": "0x08003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xFE",
- "EventName": "IDI_MISC.WB_UPGRADE",
- "PublicDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly.",
- "SampleAfterValue": "100003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200010",
+ "MSRValue": "0x04003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0004",
+ "MSRValue": "0x01003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100048000",
+ "MSRValue": "0x08007C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0490",
+ "MSRValue": "0x02003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040490",
+ "MSRValue": "0x00803C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200400",
+ "MSRValue": "0x3F80080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200491",
+ "MSRValue": "0x1000080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100010",
+ "MSRValue": "0x0800080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200120",
+ "MSRValue": "0x0400080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100004",
+ "MSRValue": "0x0100080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040010",
+ "MSRValue": "0x0200080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0020",
+ "MSRValue": "0x0080080001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0010",
+ "MSRValue": "0x3F80200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400400",
+ "MSRValue": "0x1000200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400020",
+ "MSRValue": "0x0800200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C07F7",
+ "MSRValue": "0x0400200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100400",
+ "MSRValue": "0x0100200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040004",
+ "MSRValue": "0x0200200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C07F7",
+ "MSRValue": "0x0080200001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200490",
+ "MSRValue": "0x3F80040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100028000",
+ "MSRValue": "0x1000040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080080",
+ "MSRValue": "0x0800040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080408000",
+ "MSRValue": "0x0400040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08001007F7",
+ "MSRValue": "0x0100040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x32",
- "EventName": "SW_PREFETCH_ACCESS.T1_T2",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400010",
+ "MSRValue": "0x0200040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -4109,945 +4117,945 @@
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020001",
+ "MSRValue": "0x0080040001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040020",
+ "MSRValue": "0x3F80100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020020",
+ "MSRValue": "0x1000100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040491",
+ "MSRValue": "0x0800100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200020",
+ "MSRValue": "0x0400100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200122",
+ "MSRValue": "0x0100100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200020",
+ "MSRValue": "0x0200100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020400",
+ "MSRValue": "0x0080100001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0120",
+ "MSRValue": "0x3F80400001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads have any response type.",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.ANY_RESPONSE",
+ "EventName": "OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010080",
+ "MSRValue": "0x0080400001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020490",
+ "MSRValue": "0x0100400001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040100",
+ "MSRValue": "0x3F80020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020122",
+ "MSRValue": "0x1000020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0010",
+ "MSRValue": "0x0800020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.ANY_SNOOP OCR.ALL_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200122",
+ "MSRValue": "0x0400020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100490",
+ "MSRValue": "0x0100020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.ANY_SNOOP OCR.ALL_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100122",
+ "MSRValue": "0x0200020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts demand data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100408000",
+ "MSRValue": "0x0080020001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Counts all demand data writes (RFOs) have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0020",
+ "MSRValue": "0x0000010002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.ANY_SNOOP OCR.DEMAND_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0002",
+ "MSRValue": "0x3F803C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE OCR.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04001007F7",
+ "MSRValue": "0x10003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80048000",
+ "MSRValue": "0x08003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100490",
+ "MSRValue": "0x04003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200002",
+ "MSRValue": "0x01003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080491",
+ "MSRValue": "0x08007C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01000807F7",
+ "MSRValue": "0x02003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100400",
+ "MSRValue": "0x00803C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200002",
+ "MSRValue": "0x3F80080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100004",
+ "MSRValue": "0x1000080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests have any response type.",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.ANY_RESPONSE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010400",
+ "MSRValue": "0x0800080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200001",
+ "MSRValue": "0x0400080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C8000",
+ "MSRValue": "0x0100080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100120",
+ "MSRValue": "0x0200080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040010",
+ "MSRValue": "0x0080080002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100080",
+ "MSRValue": "0x3F80200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020122",
+ "MSRValue": "0x1000200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000088000",
+ "MSRValue": "0x0800200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT.ANY_SNOOP OCR.ALL_READS.L3_HIT.ANY_SNOOP OCR.ALL_READS.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C07F7",
+ "MSRValue": "0x0400200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00804007F7",
+ "MSRValue": "0x0100200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400028000",
+ "MSRValue": "0x0200200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0490",
+ "MSRValue": "0x0080200002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400004",
+ "MSRValue": "0x3F80040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0001",
+ "MSRValue": "0x1000040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020002",
+ "MSRValue": "0x0800040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C07F7",
+ "MSRValue": "0x0400040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400004",
+ "MSRValue": "0x0100040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100001",
+ "MSRValue": "0x0200040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT.SNOOP_NONE OCR.ALL_READS.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C07F7",
+ "MSRValue": "0x0080040002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080080",
+ "MSRValue": "0x3F80100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020490",
+ "MSRValue": "0x1000100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80028000",
+ "MSRValue": "0x0800100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0490",
+ "MSRValue": "0x0400100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200020",
+ "MSRValue": "0x0100100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01001007F7",
+ "MSRValue": "0x0200100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100122",
+ "MSRValue": "0x0080100002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0122",
+ "MSRValue": "0x3F80400002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_M.ANY_SNOOP OCR.ALL_READS.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F800407F7",
+ "MSRValue": "0x0080400002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C07F7",
+ "MSRValue": "0x0100400002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.ANY_RESPONSE have any response type.",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.ANY_RESPONSE",
+ "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00000107F7",
+ "MSRValue": "0x3F80020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0491",
+ "MSRValue": "0x1000020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040491",
+ "MSRValue": "0x0800020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020080",
+ "MSRValue": "0x0400020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000208000",
+ "MSRValue": "0x0100020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0491",
+ "MSRValue": "0x0200020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all demand data writes (RFOs)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040400",
+ "MSRValue": "0x0080020002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080010",
+ "MSRValue": "0x0000018000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.ANY_SNOOP OCR.OTHER.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400100",
+ "MSRValue": "0x3F803C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.HITM_OTHER_CORE OCR.OTHER.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100080",
+ "MSRValue": "0x10003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.HIT_OTHER_CORE_FWD OCR.OTHER.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080100",
+ "MSRValue": "0x08003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.OTHER.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080010",
+ "MSRValue": "0x04003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.NO_SNOOP_NEEDED OCR.OTHER.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.OTHER.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400120",
+ "MSRValue": "0x01003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080400",
+ "MSRValue": "0x08007C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.OTHER.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0490",
+ "MSRValue": "0x02003C8000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -5067,1111 +5075,1092 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800028000",
+ "MSRValue": "0x3F80088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080491",
+ "MSRValue": "0x1000088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100002",
+ "MSRValue": "0x0800088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_S.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10001007F7",
+ "MSRValue": "0x0400088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_F.ANY_SNOOP OCR.ALL_READS.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.OTHER.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F802007F7",
+ "MSRValue": "0x0100088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04000407F7",
+ "MSRValue": "0x0200088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00801007F7",
+ "MSRValue": "0x0080088000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.OTHER.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0080",
+ "MSRValue": "0x3F80208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080490",
+ "MSRValue": "0x1000208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020400",
+ "MSRValue": "0x0800208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100400",
+ "MSRValue": "0x0400208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04000807F7",
+ "MSRValue": "0x0100208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.OTHER.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100004",
+ "MSRValue": "0x0200208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100491",
+ "MSRValue": "0x0080208000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.OTHER.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020002",
+ "MSRValue": "0x3F80048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP OCR.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.OTHER.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0080",
+ "MSRValue": "0x1000048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT.SNOOP_NONE OCR.ALL_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0122",
+ "MSRValue": "0x0800048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040490",
+ "MSRValue": "0x0400048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0002",
+ "MSRValue": "0x0100048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020100",
+ "MSRValue": "0x0200048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040120",
+ "MSRValue": "0x0080048000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.OTHER.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00800807F7",
+ "MSRValue": "0x3F80108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020001",
+ "MSRValue": "0x1000108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.SNOOP_MISS",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02000207F7",
+ "MSRValue": "0x0800108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200080",
+ "MSRValue": "0x0400108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of PREFETCHT0 instructions executed.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x32",
- "EventName": "SW_PREFETCH_ACCESS.T0",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0122",
+ "MSRValue": "0x0100108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200001",
+ "MSRValue": "0x0200108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100491",
+ "MSRValue": "0x0080108000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.OTHER.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00800407F7",
+ "MSRValue": "0x3F80408000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "Counts any other requests OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100020",
+ "MSRValue": "0x0080408000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX512 turbo schedule.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x28",
- "EventName": "CORE_POWER.LVL2_TURBO_LICENSE",
- "PublicDescription": "Core cycles where the core was running with power-delivery for license level 2 (introduced in Skylake Server michroarchtecture). This includes high current AVX 512-bit instructions.",
- "SampleAfterValue": "200003",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE OCR.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0400",
+ "MSRValue": "0x0100408000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.OTHER.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0020",
+ "MSRValue": "0x3F80028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.OTHER.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080400",
+ "MSRValue": "0x1000028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200120",
+ "MSRValue": "0x0800028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.OTHER.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400080",
+ "MSRValue": "0x0400028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests OCR.OTHER.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.OTHER.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020004",
+ "MSRValue": "0x0100028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.OTHER.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100400",
+ "MSRValue": "0x0200028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts any other requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.OTHER.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080002",
+ "MSRValue": "0x0080028000",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_MISS",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200120",
+ "MSRValue": "0x0000010400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP OCR.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0004",
+ "MSRValue": "0x3F803C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE OCR.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200490",
+ "MSRValue": "0x10003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80208000",
+ "MSRValue": "0x08003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100400",
+ "MSRValue": "0x04003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01000207F7",
+ "MSRValue": "0x01003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200490",
+ "MSRValue": "0x08007C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100002",
+ "MSRValue": "0x02003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00802007F7",
+ "MSRValue": "0x00803C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP OCR.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0400",
+ "MSRValue": "0x3F80080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0080",
+ "MSRValue": "0x1000080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100100",
+ "MSRValue": "0x0800080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200010",
+ "MSRValue": "0x0400080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040120",
+ "MSRValue": "0x0100080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200004",
+ "MSRValue": "0x0200080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0002",
+ "MSRValue": "0x0080080400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200080",
+ "MSRValue": "0x3F80200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040080",
+ "MSRValue": "0x1000200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400490",
+ "MSRValue": "0x0800200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020400",
+ "MSRValue": "0x0400200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_NONE OCR.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0491",
+ "MSRValue": "0x0100200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100002",
+ "MSRValue": "0x0200200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100122",
+ "MSRValue": "0x0080200400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP OCR.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080490",
+ "MSRValue": "0x3F80040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080080",
+ "MSRValue": "0x1000040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040020",
+ "MSRValue": "0x0800040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.ANY_SNOOP OCR.PF_L3_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0100",
+ "MSRValue": "0x0400040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040491",
+ "MSRValue": "0x0100040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040080",
+ "MSRValue": "0x0200040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0100",
+ "MSRValue": "0x0080040400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400080",
+ "MSRValue": "0x3F80100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200120",
+ "MSRValue": "0x1000100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080120",
+ "MSRValue": "0x0800100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080002",
+ "MSRValue": "0x0400100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040490",
+ "MSRValue": "0x0100100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080002",
+ "MSRValue": "0x0200100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020020",
+ "MSRValue": "0x0080100400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080048000",
+ "MSRValue": "0x3F80400400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080002",
+ "MSRValue": "0x0080400400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080001",
+ "MSRValue": "0x0100400400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200122",
+ "MSRValue": "0x3F80020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080490",
+ "MSRValue": "0x1000020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040004",
+ "MSRValue": "0x0800020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040002",
+ "MSRValue": "0x0400020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040001",
+ "MSRValue": "0x0100020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200400",
+ "MSRValue": "0x0200020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -6182,1325 +6171,1309 @@
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100400",
+ "MSRValue": "0x0080020400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400001",
+ "MSRValue": "0x0000010010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP OCR.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040122",
+ "MSRValue": "0x3F803C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400001",
+ "MSRValue": "0x10003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200491",
+ "MSRValue": "0x08003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400002",
+ "MSRValue": "0x04003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400010",
+ "MSRValue": "0x01003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.ANY_SNOOP OCR.OTHER.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C8000",
+ "MSRValue": "0x08007C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200080",
+ "MSRValue": "0x02003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100120",
+ "MSRValue": "0x00803C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0010",
+ "MSRValue": "0x3F80080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10000807F7",
+ "MSRValue": "0x1000080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100010",
+ "MSRValue": "0x0800080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80400004",
+ "MSRValue": "0x0400080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080491",
+ "MSRValue": "0x0100080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020001",
+ "MSRValue": "0x0200080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800208000",
+ "MSRValue": "0x0080080010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020100",
+ "MSRValue": "0x3F80200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP OCR.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0001",
+ "MSRValue": "0x1000200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040080",
+ "MSRValue": "0x0800200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0400",
+ "MSRValue": "0x0400200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0120",
+ "MSRValue": "0x0100200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020120",
+ "MSRValue": "0x0200200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400108000",
+ "MSRValue": "0x0080200010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0490",
+ "MSRValue": "0x3F80040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080108000",
+ "MSRValue": "0x1000040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020080",
+ "MSRValue": "0x0800040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01004007F7",
+ "MSRValue": "0x0400040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040010",
+ "MSRValue": "0x0100040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200010",
+ "MSRValue": "0x0200040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED OCR.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0004",
+ "MSRValue": "0x0080040010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200100",
+ "MSRValue": "0x3F80100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200080",
+ "MSRValue": "0x1000100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040020",
+ "MSRValue": "0x0800100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020080",
+ "MSRValue": "0x0400100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_READS.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10000407F7",
+ "MSRValue": "0x0100100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100080",
+ "MSRValue": "0x0200100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10000207F7",
+ "MSRValue": "0x0080100010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP OCR.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040491",
+ "MSRValue": "0x3F80400010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED OCR.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080122",
+ "MSRValue": "0x0080400010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200400",
+ "MSRValue": "0x0100400010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200100",
+ "MSRValue": "0x3F80020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040010",
+ "MSRValue": "0x1000020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080080",
+ "MSRValue": "0x0800020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200004",
+ "MSRValue": "0x0400020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.NO_SNOOP_NEEDED OCR.OTHER.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C8000",
+ "MSRValue": "0x0100020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE OCR.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200120",
+ "MSRValue": "0x0200020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100100",
+ "MSRValue": "0x0080020010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.PF_L2_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0001",
+ "MSRValue": "0x0000010020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT.ANY_SNOOP OCR.ALL_RFO.L3_HIT.ANY_SNOOP OCR.ALL_RFO.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.ANY_SNOOP OCR.PF_L2_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0122",
+ "MSRValue": "0x3F803C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE OCR.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0100",
+ "MSRValue": "0x10003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080010",
+ "MSRValue": "0x08003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200088000",
+ "MSRValue": "0x04003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080400",
+ "MSRValue": "0x01003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020491",
+ "MSRValue": "0x08007C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_M.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040122",
+ "MSRValue": "0x02003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020020",
+ "MSRValue": "0x00803C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400490",
+ "MSRValue": "0x3F80080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020002",
+ "MSRValue": "0x1000080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100002",
+ "MSRValue": "0x0800080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020122",
+ "MSRValue": "0x0400080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020080",
+ "MSRValue": "0x0100080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020001",
+ "MSRValue": "0x0200080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE OCR.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040490",
+ "MSRValue": "0x0080080020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of PREFETCHW instructions executed.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x32",
- "EventName": "SW_PREFETCH_ACCESS.PREFETCHW",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100490",
+ "MSRValue": "0x3F80200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100020",
+ "MSRValue": "0x1000200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080491",
+ "MSRValue": "0x0800200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040120",
+ "MSRValue": "0x0400200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_M.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200040120",
+ "MSRValue": "0x0100200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020010",
+ "MSRValue": "0x0200200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020490",
+ "MSRValue": "0x0080200020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP OCR.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0004",
+ "MSRValue": "0x3F80040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200490",
+ "MSRValue": "0x1000040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080122",
+ "MSRValue": "0x0800040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040001",
+ "MSRValue": "0x0400040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0010",
+ "MSRValue": "0x0100040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100100",
+ "MSRValue": "0x0200040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0080",
+ "MSRValue": "0x0080040020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040080",
+ "MSRValue": "0x3F80100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080010",
+ "MSRValue": "0x1000100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_PF_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020120",
+ "MSRValue": "0x0800100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100122",
+ "MSRValue": "0x0400100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020120",
+ "MSRValue": "0x0100100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX2 turbo schedule.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x28",
- "EventName": "CORE_POWER.LVL1_TURBO_LICENSE",
- "PublicDescription": "Core cycles where the core was running with power-delivery for license level 1. This includes high current AVX 256-bit instructions as well as low current AVX 512-bit instructions.",
- "SampleAfterValue": "200003",
- "UMask": "0x18"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040020",
+ "MSRValue": "0x0200100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200004",
+ "MSRValue": "0x0080100020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020080",
+ "MSRValue": "0x3F80400020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040020",
+ "MSRValue": "0x0080400020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080400001",
+ "MSRValue": "0x0100400020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080004",
+ "MSRValue": "0x3F80020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080100",
+ "MSRValue": "0x1000020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100490",
+ "MSRValue": "0x0800020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100020",
+ "MSRValue": "0x0400020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.ANY_SNOOP OCR.ALL_RFO.L3_HIT_E.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_E.ANY_SNOOP",
+ "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80080122",
+ "MSRValue": "0x0100020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400100120",
+ "MSRValue": "0x0200020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400491",
+ "MSRValue": "0x0080020020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100080080",
+ "MSRValue": "0x0000010080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP OCR.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200002",
+ "MSRValue": "0x3F803C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT.SNOOP_NONE OCR.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE OCR.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0120",
+ "MSRValue": "0x10003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of hardware interrupts received by the processor.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xCB",
- "EventName": "HW_INTERRUPTS.RECEIVED",
- "PublicDescription": "Counts the number of hardware interruptions received by the processor.",
- "SampleAfterValue": "203",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x08003C0080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200080",
+ "MSRValue": "0x04003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020020",
+ "MSRValue": "0x01003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -7520,1143 +7493,1170 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE OCR.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0020",
+ "MSRValue": "0x02003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000108000",
+ "MSRValue": "0x00803C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100080",
+ "MSRValue": "0x3F80080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040001",
+ "MSRValue": "0x1000080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0002",
+ "MSRValue": "0x0800080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040491",
+ "MSRValue": "0x0400080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020120",
+ "MSRValue": "0x0100080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED OCR.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100490",
+ "MSRValue": "0x0200080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) have any response type.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.ANY_RESPONSE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010002",
+ "MSRValue": "0x0080080080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040004",
+ "MSRValue": "0x3F80200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020004",
+ "MSRValue": "0x1000200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100001",
+ "MSRValue": "0x0800200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400020002",
+ "MSRValue": "0x0400200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100004",
+ "MSRValue": "0x0100200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400208000",
+ "MSRValue": "0x0200200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs have any response type.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.ANY_RESPONSE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010100",
+ "MSRValue": "0x0080200080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080491",
+ "MSRValue": "0x3F80040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080490",
+ "MSRValue": "0x1000040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040100",
+ "MSRValue": "0x0800040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100001",
+ "MSRValue": "0x0400040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_MISS OCR.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02003C0491",
+ "MSRValue": "0x0100040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400048000",
+ "MSRValue": "0x0200040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP OCR.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0010",
+ "MSRValue": "0x0080040080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200208000",
+ "MSRValue": "0x3F80100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x00803C0490",
+ "MSRValue": "0x1000100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP OCR.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.SUPPLIER_NONE.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80020120",
+ "MSRValue": "0x0800100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0010",
+ "MSRValue": "0x0400100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200400",
+ "MSRValue": "0x0100100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080020",
+ "MSRValue": "0x0200100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800200491",
+ "MSRValue": "0x0080100080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_S.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_S.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000100400",
+ "MSRValue": "0x3F80400080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020010",
+ "MSRValue": "0x0080400080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_DATA_RD.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080040004",
+ "MSRValue": "0x0100400080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080004",
+ "MSRValue": "0x3F80020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080100",
+ "MSRValue": "0x1000020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_M.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000040010",
+ "MSRValue": "0x0800020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200020001",
+ "MSRValue": "0x0400020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080001",
+ "MSRValue": "0x0100020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04002007F7",
+ "MSRValue": "0x0200020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE OCR.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_E.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_DATA_RD.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000080122",
+ "MSRValue": "0x0080020080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OCR.PF_L3_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08007C0020",
+ "MSRValue": "0x0000010100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.ANY_SNOOP OCR.PF_L3_RFO.L3_HIT.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200002",
+ "MSRValue": "0x3F803C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE OCR.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080020",
+ "MSRValue": "0x10003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.SUPPLIER_NONE.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080020400",
+ "MSRValue": "0x08003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED OCR.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100020491",
+ "MSRValue": "0x04003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100100",
+ "MSRValue": "0x01003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP OCR.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_F.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80200120",
+ "MSRValue": "0x08007C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED OCR.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.SNOOP_MISS",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0400",
+ "MSRValue": "0x02003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400040080",
+ "MSRValue": "0x00803C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_E.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200010",
+ "MSRValue": "0x3F80080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_E.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040020",
+ "MSRValue": "0x1000080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT.HITM_OTHER_CORE OCR.OTHER.L3_HIT.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C8000",
+ "MSRValue": "0x0800080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040100",
+ "MSRValue": "0x0400080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_E.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200100100",
+ "MSRValue": "0x0100080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_E.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400080400",
+ "MSRValue": "0x0200080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_F.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_E.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000200001",
+ "MSRValue": "0x0080080100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of PREFETCHNTA instructions executed.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x32",
- "EventName": "SW_PREFETCH_ACCESS.NTA",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_F.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100200004",
+ "MSRValue": "0x3F80200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_M.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_F.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800040004",
+ "MSRValue": "0x1000200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100120",
+ "MSRValue": "0x0800200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_CODE_RD.L3_HIT_S.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080100004",
+ "MSRValue": "0x0400200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_F.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040400",
+ "MSRValue": "0x0100200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_F.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0400",
+ "MSRValue": "0x0200200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_F.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_F.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200200400",
+ "MSRValue": "0x0080200100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_E.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_E.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_M.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080080122",
+ "MSRValue": "0x3F80040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_M.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80100020",
+ "MSRValue": "0x1000040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs OCR.PF_L2_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100100020",
+ "MSRValue": "0x0800040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.L3_HIT_F.SNOOP_NONE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_M.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200122",
+ "MSRValue": "0x0400040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_M.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0080",
+ "MSRValue": "0x0100040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads OCR.DEMAND_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_DATA_RD.L3_HIT_M.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_M.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100040001",
+ "MSRValue": "0x0200040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_S.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_M.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800100010",
+ "MSRValue": "0x0080040100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE OCR.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HITM_OTHER_CORE",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_S.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x1000020491",
+ "MSRValue": "0x3F80100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_S.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080490",
+ "MSRValue": "0x1000100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts any other requests OCR.OTHER.L3_HIT_F.NO_SNOOP_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.OTHER.L3_HIT_F.NO_SNOOP_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100208000",
+ "MSRValue": "0x0800100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_S.ANY_SNOOP OCR.ALL_READS.L3_HIT_S.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_S.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_S.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F801007F7",
+ "MSRValue": "0x0400100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs)",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.DEMAND_RFO.L3_HIT_E.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_S.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0200080002",
+ "MSRValue": "0x0100100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_S.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020010",
+ "MSRValue": "0x0200100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.L3_HIT_S.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0080",
+ "MSRValue": "0x0080100100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_F.SNOOP_NONE",
+ "EventName": "OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0080200100",
+ "MSRValue": "0x3F80400100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080080",
+ "MSRValue": "0x0080400100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400122",
+ "MSRValue": "0x0100400100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_RFO.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080100",
+ "MSRValue": "0x3F80020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads OCR.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L3_DATA_RD.L3_HIT_M.ANY_SNOOP",
+ "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F80040080",
+ "MSRValue": "0x1000020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_PF_RFO.PMM_HIT_LOCAL_PMM.SNOOP_NOT_NEEDED",
+ "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0100400120",
+ "MSRValue": "0x0800020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_DATA_RD.SUPPLIER_NONE.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800020491",
+ "MSRValue": "0x0400020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs OCR.PF_L3_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L1D_AND_SW.L3_HIT_E.HIT_OTHER_CORE_FWD",
+ "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0800080400",
+ "MSRValue": "0x0100020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.PF_L2_DATA_RD.L3_HIT_F.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.SNOOP_MISS",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0400200010",
+ "MSRValue": "0x0200020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OCR.ALL_READS.L3_HIT_S.SNOOP_MISS",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OCR.ALL_READS.L3_HIT_S.SNOOP_MISS",
+ "EventName": "OCR.PF_L3_RFO.SUPPLIER_NONE.SNOOP_NONE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x02001007F7",
+ "MSRValue": "0x0080020100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of PREFETCHNTA instructions executed.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.NTA",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of PREFETCHW instructions executed.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.PREFETCHW",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Number of PREFETCHT0 instructions executed.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.T0",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.T1_T2",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/pipeline.json b/tools/perf/pmu-events/arch/x86/cascadelakex/pipeline.json
index 023f31c72a42..ca5748120666 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/pipeline.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/pipeline.json
@@ -1,148 +1,158 @@
[
{
- "BriefDescription": "Far branch instructions retired.",
+ "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x14",
+ "EventName": "ARITH.DIVIDER_ACTIVE",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "All (macro) branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"Errata": "SKL091",
"EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.FAR_BRANCH",
- "PEBS": "1",
- "PublicDescription": "This event counts far branch instructions retired.",
- "SampleAfterValue": "100007",
- "UMask": "0x40"
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "Counts all (macro) branch instructions retired.",
+ "SampleAfterValue": "400009"
},
{
- "BriefDescription": "Total execution stalls.",
+ "BriefDescription": "All (macro) branch instructions retired.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
+ "SampleAfterValue": "400009",
"UMask": "0x4"
},
{
- "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "BriefDescription": "Conditional branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0E",
- "EventName": "UOPS_ISSUED.SLOW_LEA",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "PEBS": "1",
+ "PublicDescription": "This event counts conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "BriefDescription": "Not taken branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "10",
- "EventCode": "0xC2",
- "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
- "Invert": "1",
- "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "Errata": "SKL091",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.COND_NTAKEN",
+ "PublicDescription": "This event counts not taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x10"
},
{
- "BriefDescription": "Thread cycles when thread is not in halt state",
+ "BriefDescription": "Far branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.THREAD_P",
- "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
- "SampleAfterValue": "2000003"
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "PEBS": "1",
+ "PublicDescription": "This event counts far branch instructions retired.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x40"
},
{
- "BriefDescription": "Cycles without actually retired uops.",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xC2",
- "EventName": "UOPS_RETIRED.STALL_CYCLES",
- "Invert": "1",
- "PublicDescription": "This event counts cycles without actually retired uops.",
- "SampleAfterValue": "2000003",
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "PEBS": "1",
+ "PublicDescription": "This event counts both direct and indirect near call instructions retired.",
+ "SampleAfterValue": "100007",
"UMask": "0x2"
},
{
- "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "BriefDescription": "Return instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
- "Invert": "1",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "PEBS": "1",
+ "PublicDescription": "This event counts return instructions retired.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x8"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
+ "BriefDescription": "Taken branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0D",
- "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "PEBS": "1",
+ "PublicDescription": "This event counts taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x20"
},
{
- "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "BriefDescription": "Not taken branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0xA8",
- "EventName": "LSD.CYCLES_4_UOPS",
- "PublicDescription": "Counts the cycles when 4 uops are delivered by the LSD (Loop-stream detector).",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Core cycles when the thread is not in halt state",
- "Counter": "Fixed counter 1",
- "CounterHTOff": "Fixed counter 1",
- "EventName": "CPU_CLK_UNHALTED.THREAD",
- "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "PublicDescription": "This event counts not taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x10"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
- "SampleAfterValue": "25003",
- "UMask": "0x1"
+ "EventCode": "0xC5",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "SampleAfterValue": "400009"
},
{
- "BriefDescription": "Direct and indirect near call instructions retired.",
+ "BriefDescription": "Mispredicted macro branch instructions retired.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.NEAR_CALL",
- "PEBS": "1",
- "PublicDescription": "This event counts both direct and indirect near call instructions retired.",
- "SampleAfterValue": "100007",
- "UMask": "0x2"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC5",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x4"
},
{
- "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.",
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x14",
- "EventName": "ARITH.DIVIDER_ACTIVE",
- "SampleAfterValue": "2000003",
+ "EventCode": "0xC5",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "PEBS": "1",
+ "PublicDescription": "This event counts mispredicted conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
"UMask": "0x1"
},
{
- "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
+ "BriefDescription": "Mispredicted direct and indirect near call instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
- "SampleAfterValue": "25003",
+ "EventCode": "0xC5",
+ "EventName": "BR_MISP_RETIRED.NEAR_CALL",
+ "PEBS": "1",
+ "PublicDescription": "Counts both taken and not taken retired mispredicted direct and indirect near calls, including both register and memory indirect.",
+ "SampleAfterValue": "400009",
"UMask": "0x2"
},
{
@@ -156,217 +166,206 @@
"UMask": "0x20"
},
{
- "BriefDescription": "Increments whenever there is an update to the LBR array.",
+ "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xCC",
- "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
- "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "25003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Instructions retired from execution.",
- "Counter": "Fixed counter 0",
- "CounterHTOff": "Fixed counter 0",
- "EventName": "INST_RETIRED.ANY",
- "PublicDescription": "Counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, Counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. Counting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
- "SampleAfterValue": "2000003",
+ "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "25003",
"UMask": "0x1"
},
{
- "BriefDescription": "Conditional branch instructions retired.",
+ "AnyThread": "1",
+ "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.CONDITIONAL",
- "PEBS": "1",
- "PublicDescription": "This event counts conditional branch instructions retired.",
- "SampleAfterValue": "400009",
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "25003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles the issue-stage is waiting for front-end to fetch from resteered path following branch misprediction or machine clear events.",
+ "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0D",
- "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES",
- "SampleAfterValue": "2000003",
- "UMask": "0x80"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "25003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
- "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "Counter": "Fixed counter 2",
+ "CounterHTOff": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x3"
},
{
- "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.STALL_CYCLES",
- "Invert": "1",
- "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
- "SampleAfterValue": "2000003",
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "25003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station was not empty.",
+ "AnyThread": "1",
+ "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.4_PORTS_UTIL",
- "PublicDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station (RS) was not empty.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "25003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "BriefDescription": "Counts when there is a transition from ring 1, 2 or 3 to ring 0.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "5",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
- "SampleAfterValue": "2000003",
- "UMask": "0x5"
+ "CounterMask": "1",
+ "EdgeDetect": "1",
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_UNHALTED.RING0_TRANS",
+ "PublicDescription": "Counts when the Current Privilege Level (CPL) transitions from ring 1, 2 or 3 to ring 0 (Kernel).",
+ "SampleAfterValue": "100007"
},
{
- "BriefDescription": "Mispredicted macro branch instructions retired.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC5",
- "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
- "PEBS": "2",
- "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x4"
+ "BriefDescription": "Core cycles when the thread is not in halt state",
+ "Counter": "Fixed counter 1",
+ "CounterHTOff": "Fixed counter 1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "2",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
- "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "AnyThread": "1",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "Counter": "Fixed counter 1",
+ "CounterHTOff": "Fixed counter 1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x3C",
- "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
- "SampleAfterValue": "25003",
- "UMask": "0x1"
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
+ "SampleAfterValue": "2000003"
},
{
- "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
+ "AnyThread": "1",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x3C",
- "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
- "SampleAfterValue": "25003",
- "UMask": "0x2"
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003"
},
{
- "BriefDescription": "All (macro) branch instructions retired.",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
- "PublicDescription": "Counts all (macro) branch instructions retired.",
- "SampleAfterValue": "400009"
+ "CounterMask": "8",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 0.",
+ "CounterMask": "1",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 1.",
+ "CounterMask": "16",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x10"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 2.",
+ "CounterMask": "12",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
"SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "UMask": "0xc"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 3.",
+ "CounterMask": "5",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
"SampleAfterValue": "2000003",
- "UMask": "0x8"
+ "UMask": "0x5"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 4.",
+ "CounterHTOff": "0,1,2,3",
+ "CounterMask": "20",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
"SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "UMask": "0x14"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "BriefDescription": "Total execution stalls.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 5.",
+ "CounterMask": "4",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
"SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "UMask": "0x4"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 6.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.1_PORTS_UTIL",
+ "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
- "UMask": "0x40"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 7.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.2_PORTS_UTIL",
+ "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
- "UMask": "0x80"
+ "UMask": "0x4"
},
{
"BriefDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station was not empty.",
@@ -379,37 +378,31 @@
"UMask": "0x8"
},
{
- "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "BriefDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station was not empty.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EdgeDetect": "1",
- "EventCode": "0x5E",
- "EventName": "RS_EVENTS.EMPTY_END",
- "Invert": "1",
- "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate front-end Latency Bound issues.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.4_PORTS_UTIL",
+ "PublicDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x10"
},
{
- "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
+ "BriefDescription": "Cycles where the Store Buffer was full and no outstanding load.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x0E",
- "EventName": "UOPS_ISSUED.STALL_CYCLES",
- "Invert": "1",
- "PublicDescription": "Counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.BOUND_ON_STORES",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x40"
},
{
- "BriefDescription": "Number of Uops delivered by the LSD.",
+ "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA8",
- "EventName": "LSD.UOPS",
- "PublicDescription": "Number of uops delivered to the back-end by the LSD(Loop Stream Detector).",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS",
+ "PublicDescription": "Counts cycles during which no uops were executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
@@ -424,117 +417,108 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Taken branch instructions retired.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
- "PEBS": "1",
- "PublicDescription": "This event counts taken branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0E",
- "EventName": "UOPS_ISSUED.ANY",
- "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).",
+ "BriefDescription": "Instructions retired from execution.",
+ "Counter": "Fixed counter 0",
+ "CounterHTOff": "Fixed counter 0",
+ "EventName": "INST_RETIRED.ANY",
+ "PublicDescription": "Counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, Counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. Counting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Resource-related stall cycles",
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xa2",
- "EventName": "RESOURCE_STALLS.ANY",
- "PublicDescription": "Counts resource-related stall cycles.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "Errata": "SKL091, SKL044",
+ "EventCode": "0xC0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "PublicDescription": "Counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
+ "SampleAfterValue": "2000003"
},
{
- "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "CounterMask": "20",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
+ "Counter": "1",
+ "CounterHTOff": "1",
+ "Errata": "SKL091, SKL044",
+ "EventCode": "0xC0",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "PEBS": "2",
+ "PublicDescription": "A version of INST_RETIRED that allows for a more unbiased distribution of samples across instructions retired. It utilizes the Precise Distribution of Instructions Retired (PDIR) feature to mitigate some bias in how retired instructions get sampled.",
"SampleAfterValue": "2000003",
- "UMask": "0x14"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS",
- "PublicDescription": "Counts cycles during which no uops were executed on all ports and Reservation Station (RS) was not empty.",
+ "BriefDescription": "Number of cycles using always true condition applied to PEBS instructions retired event.",
+ "Counter": "0,2,3",
+ "CounterHTOff": "0,2,3",
+ "CounterMask": "10",
+ "Errata": "SKL091, SKL044",
+ "EventCode": "0xC0",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
+ "Invert": "1",
+ "PEBS": "2",
+ "PublicDescription": "Number of cycles using an always true condition applied to PEBS instructions retired event. (inst_ret< 16)",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "BriefDescription": "Cycles the issue-stage is waiting for front-end to fetch from resteered path following branch misprediction or machine clear events.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA2",
- "EventName": "RESOURCE_STALLS.SB",
- "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.",
+ "EventCode": "0x0D",
+ "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES",
"SampleAfterValue": "2000003",
- "UMask": "0x8"
+ "UMask": "0x80"
},
{
- "BriefDescription": "Not taken branch instructions retired.",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread (e.g. misprediction or memory nuke)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.NOT_TAKEN",
- "PublicDescription": "This event counts not taken branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x10"
+ "EventCode": "0x0D",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "PublicDescription": "Core cycles the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "AnyThread": "1",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "12",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "EventCode": "0x0D",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
"SampleAfterValue": "2000003",
- "UMask": "0xc"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty.",
+ "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.2_PORTS_UTIL",
- "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "EventCode": "0x03",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "BriefDescription": "Loads blocked due to overlapping with a preceding store that cannot be forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091, SKL044",
- "EventCode": "0xC0",
- "EventName": "INST_RETIRED.ANY_P",
- "PublicDescription": "Counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
- "SampleAfterValue": "2000003"
+ "EventCode": "0x03",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "PublicDescription": "Counts the number of times where store forwarding was prevented for a load operation. The most common case is a load blocked due to the address of memory access (partially) overlapping with a preceding uncompleted store. Note: See the table of not supported store forwards in the Optimization Guide.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Counts the number of x87 uops dispatched.",
+ "BriefDescription": "False dependencies in MOB due to partial compare on address.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.X87",
- "PublicDescription": "Counts the number of x87 uops executed.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "EventCode": "0x07",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "PublicDescription": "Counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
"BriefDescription": "Demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch.",
@@ -547,219 +531,238 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Mispredicted direct and indirect near call instructions retired.",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC5",
- "EventName": "BR_MISP_RETIRED.NEAR_CALL",
- "PEBS": "1",
- "PublicDescription": "Counts both taken and not taken retired mispredicted direct and indirect near calls, including both register and memory indirect.",
- "SampleAfterValue": "400009",
- "UMask": "0x2"
+ "CounterMask": "4",
+ "EventCode": "0xA8",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "PublicDescription": "Counts the cycles when 4 uops are delivered by the LSD (Loop-stream detector).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.THREAD",
- "PublicDescription": "Number of uops to be executed per-thread each cycle.",
+ "CounterMask": "1",
+ "EventCode": "0xA8",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "3",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
- "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "EventCode": "0xA8",
+ "EventName": "LSD.UOPS",
+ "PublicDescription": "Number of uops delivered to the back-end by the LSD(Loop Stream Detector).",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
- "EventCode": "0xA8",
- "EventName": "LSD.CYCLES_ACTIVE",
- "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).",
- "SampleAfterValue": "2000003",
+ "EdgeDetect": "1",
+ "EventCode": "0xC3",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread (e.g. misprediction or memory nuke)",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0D",
- "EventName": "INT_MISC.RECOVERY_CYCLES",
- "PublicDescription": "Core cycles the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.",
+ "EventCode": "0xC3",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of times a microcode assist is invoked by HW other than FP-assist. Examples include AD (page Access Dirty) and AVX* related assists.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC1",
+ "EventName": "OTHER_ASSISTS.ANY",
+ "SampleAfterValue": "100003",
+ "UMask": "0x3f"
+ },
+ {
+ "BriefDescription": "Cycles where the pipeline is stalled due to serializing operations.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x59",
+ "EventName": "PARTIAL_RAT_STALLS.SCOREBOARD",
+ "PublicDescription": "This event counts cycles during which the microcode scoreboard stalls happen.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
+ "BriefDescription": "Resource-related stall cycles",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
- "SampleAfterValue": "25003",
+ "EventCode": "0xa2",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "PublicDescription": "Counts resource-related stall cycles.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "8",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "EventCode": "0xA2",
+ "EventName": "RESOURCE_STALLS.SB",
+ "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.",
"SampleAfterValue": "2000003",
"UMask": "0x8"
},
{
- "BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
- "Counter": "1",
- "CounterHTOff": "1",
- "Errata": "SKL091, SKL044",
- "EventCode": "0xC0",
- "EventName": "INST_RETIRED.PREC_DIST",
- "PEBS": "2",
- "PublicDescription": "A version of INST_RETIRED that allows for a more unbiased distribution of samples across instructions retired. It utilizes the Precise Distribution of Instructions Retired (PDIR) feature to mitigate some bias in how retired instructions get sampled.",
+ "BriefDescription": "Increments whenever there is an update to the LBR array.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xCC",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x20"
},
{
- "BriefDescription": "Not taken branch instructions retired.",
+ "BriefDescription": "Number of retired PAUSE instructions (that do not end up with a VMExit to the VMM; TSX aborted Instructions may be counted). This event is not supported on first SKL and KBL products.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xc4",
- "EventName": "BR_INST_RETIRED.COND_NTAKEN",
- "PublicDescription": "This event counts not taken branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x10"
+ "EventCode": "0xCC",
+ "EventName": "ROB_MISC_EVENTS.PAUSE_INST",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
},
{
- "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "3",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "EventCode": "0x5E",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for the thread.; Note: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "EdgeDetect": "1",
+ "EventCode": "0x5E",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "Invert": "1",
+ "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate front-end Latency Bound issues.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 0.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Number of times a microcode assist is invoked by HW other than FP-assist. Examples include AD (page Access Dirty) and AVX* related assists.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC1",
- "EventName": "OTHER_ASSISTS.ANY",
- "SampleAfterValue": "100003",
- "UMask": "0x3f"
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 1.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles where the Store Buffer was full and no outstanding load.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.BOUND_ON_STORES",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 2.",
"SampleAfterValue": "2000003",
- "UMask": "0x40"
+ "UMask": "0x4"
},
{
- "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "16",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 3.",
"SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Number of retired PAUSE instructions (that do not end up with a VMExit to the VMM; TSX aborted Instructions may be counted). This event is not supported on first SKL and KBL products.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xCC",
- "EventName": "ROB_MISC_EVENTS.PAUSE_INST",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 4.",
"SampleAfterValue": "2000003",
- "UMask": "0x40"
+ "UMask": "0x10"
},
{
- "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
- "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 5.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x20"
},
{
- "BriefDescription": "Cycles where the pipeline is stalled due to serializing operations.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x59",
- "EventName": "PARTIAL_RAT_STALLS.SCOREBOARD",
- "PublicDescription": "This event counts cycles during which the microcode scoreboard stalls happen.",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 6.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x40"
},
{
- "BriefDescription": "Retirement slots used.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC2",
- "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
- "PublicDescription": "Counts the retirement slots used.",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 7.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x80"
},
{
- "BriefDescription": "Uops inserted at issue-stage in order to preserve upper bits of vector registers.",
+ "BriefDescription": "Number of uops executed on the core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0E",
- "EventName": "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH",
- "PublicDescription": "Counts the number of Blend Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS) in order to preserve upper bits of vector registers. Starting with the Skylake microarchitecture, these Blend uops are needed since every Intel SSE instruction executed in Dirty Upper State needs to preserve bits 128-255 of the destination register. For more information, refer to Mixing Intel AVX and Intel SSE Code section of the Optimization Guide.",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "PublicDescription": "Number of uops executed from any thread.",
"SampleAfterValue": "2000003",
"UMask": "0x2"
},
{
- "BriefDescription": "Return instructions retired.",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.NEAR_RETURN",
- "PEBS": "1",
- "PublicDescription": "This event counts return instructions retired.",
- "SampleAfterValue": "100007",
- "UMask": "0x8"
+ "CounterMask": "1",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
"BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
@@ -772,188 +775,195 @@
"UMask": "0x2"
},
{
- "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC5",
- "EventName": "BR_MISP_RETIRED.CONDITIONAL",
- "PEBS": "1",
- "PublicDescription": "This event counts mispredicted conditional branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x1"
+ "CounterMask": "3",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Number of cycles using always true condition applied to PEBS instructions retired event.",
- "Counter": "0,2,3",
- "CounterHTOff": "0,2,3",
- "CounterMask": "10",
- "Errata": "SKL091, SKL044",
- "EventCode": "0xC0",
- "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
- "Invert": "1",
- "PEBS": "2",
- "PublicDescription": "Number of cycles using an always true condition applied to PEBS instructions retired event. (inst_ret< 16)",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "4",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x2"
},
{
- "BriefDescription": "False dependencies in MOB due to partial compare on address.",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x07",
- "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
- "PublicDescription": "Counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterMask": "1",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "Invert": "1",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
- "EdgeDetect": "1",
- "EventCode": "0xC3",
- "EventName": "MACHINE_CLEARS.COUNT",
- "SampleAfterValue": "100003",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
- "Counter": "Fixed counter 1",
- "CounterHTOff": "Fixed counter 1",
- "EventName": "CPU_CLK_UNHALTED.THREAD_ANY",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "2",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Loads blocked due to overlapping with a preceding store that cannot be forwarded.",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x03",
- "EventName": "LD_BLOCKS.STORE_FORWARD",
- "PublicDescription": "Counts the number of times where store forwarding was prevented for a load operation. The most common case is a load blocked due to the address of memory access (partially) overlapping with a preceding uncompleted store. Note: See the table of not supported store forwards in the Optimization Guide.",
- "SampleAfterValue": "100003",
- "UMask": "0x2"
+ "CounterMask": "3",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
- "SampleAfterValue": "25003",
+ "CounterMask": "4",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Reference cycles when the core is not in halt state.",
- "Counter": "Fixed counter 2",
- "CounterHTOff": "Fixed counter 2",
- "EventName": "CPU_CLK_UNHALTED.REF_TSC",
- "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "Invert": "1",
+ "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
"SampleAfterValue": "2000003",
- "UMask": "0x3"
+ "UMask": "0x1"
},
{
- "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC5",
- "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
- "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
- "SampleAfterValue": "400009"
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "PublicDescription": "Number of uops to be executed per-thread each cycle.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use",
+ "BriefDescription": "Counts the number of x87 uops dispatched.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x03",
- "EventName": "LD_BLOCKS.NO_SR",
- "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
- "SampleAfterValue": "100003",
- "UMask": "0x8"
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.X87",
+ "PublicDescription": "Counts the number of x87 uops executed.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
},
{
- "BriefDescription": "Self-modifying code (SMC) detected.",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC3",
- "EventName": "MACHINE_CLEARS.SMC",
- "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.",
- "SampleAfterValue": "100003",
- "UMask": "0x4"
+ "EventCode": "0x0E",
+ "EventName": "UOPS_ISSUED.ANY",
+ "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
- "SampleAfterValue": "2000003"
+ "EventCode": "0x0E",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
},
{
- "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5E",
- "EventName": "RS_EVENTS.EMPTY_CYCLES",
- "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for the thread.; Note: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
+ "CounterMask": "1",
+ "EventCode": "0x0E",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "Invert": "1",
+ "PublicDescription": "Counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts when there is a transition from ring 1, 2 or 3 to ring 0.",
+ "BriefDescription": "Uops inserted at issue-stage in order to preserve upper bits of vector registers.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EdgeDetect": "1",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.RING0_TRANS",
- "PublicDescription": "Counts when the Current Privilege Level (CPL) transitions from ring 1, 2 or 3 to ring 0 (Kernel).",
- "SampleAfterValue": "100007"
+ "EventCode": "0x0E",
+ "EventName": "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH",
+ "PublicDescription": "Counts the number of Blend Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS) in order to preserve upper bits of vector registers. Starting with the Skylake microarchitecture, these Blend uops are needed since every Intel SSE instruction executed in Dirty Upper State needs to preserve bits 128-255 of the destination register. For more information, refer to Mixing Intel AVX and Intel SSE Code section of the Optimization Guide.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "All (macro) branch instructions retired.",
+ "BriefDescription": "Number of macro-fused uops retired. (non precise)",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
- "PEBS": "2",
- "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
- "SampleAfterValue": "400009",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc2",
+ "EventName": "UOPS_RETIRED.MACRO_FUSED",
+ "PublicDescription": "Counts the number of macro-fused uops retired. (non precise)",
+ "SampleAfterValue": "2000003",
"UMask": "0x4"
},
{
- "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty.",
+ "BriefDescription": "Retirement slots used.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.1_PORTS_UTIL",
- "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.",
+ "EventCode": "0xC2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "PublicDescription": "Counts the retirement slots used.",
"SampleAfterValue": "2000003",
"UMask": "0x2"
},
{
- "BriefDescription": "Number of uops executed on the core.",
+ "BriefDescription": "Cycles without actually retired uops.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE",
- "PublicDescription": "Number of uops executed from any thread.",
+ "CounterMask": "1",
+ "EventCode": "0xC2",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "Invert": "1",
+ "PublicDescription": "This event counts cycles without actually retired uops.",
"SampleAfterValue": "2000003",
"UMask": "0x2"
},
{
- "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "CounterMask": "10",
+ "EventCode": "0xC2",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "Invert": "1",
+ "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x2"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json b/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json
index 4ba9e6d9f25e..2600fd8d7a54 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-memory.json
@@ -65,15 +65,6 @@
"Unit": "iMC"
},
{
- "BriefDescription": "Pre-charge for writes",
- "Counter": "0,1,2,3",
- "EventCode": "0x2",
- "EventName": "UNC_M_PRE_COUNT.WR",
- "PerPkg": "1",
- "UMask": "0x8",
- "Unit": "iMC"
- },
- {
"BriefDescription": "Write requests allocated in the PMM Write Pending Queue for Intel Optane DC persistent memory",
"Counter": "0,1,2,3",
"EventCode": "0xE3",
@@ -90,32 +81,32 @@
"Unit": "iMC"
},
{
- "BriefDescription": "Intel Optane DC persistent memory bandwidth read (MB). Derived from unc_m_pmm_rpq_inserts",
+ "BriefDescription": "Intel Optane DC persistent memory bandwidth read (MB/sec). Derived from unc_m_pmm_rpq_inserts",
"Counter": "0,1,2,3",
"EventCode": "0xE3",
"EventName": "UNC_M_PMM_BANDWIDTH.READ",
"PerPkg": "1",
- "ScaleUnit": "6.103515625E-5MB",
+ "ScaleUnit": "6.103515625E-5MB/sec",
"Unit": "iMC"
},
{
- "BriefDescription": "Intel Optane DC persistent memory bandwidth write (MB). Derived from unc_m_pmm_wpq_inserts",
+ "BriefDescription": "Intel Optane DC persistent memory bandwidth write (MB/sec). Derived from unc_m_pmm_wpq_inserts",
"Counter": "0,1,2,3",
"EventCode": "0xE7",
"EventName": "UNC_M_PMM_BANDWIDTH.WRITE",
"PerPkg": "1",
- "ScaleUnit": "6.103515625E-5MB",
+ "ScaleUnit": "6.103515625E-5MB/sec",
"Unit": "iMC"
},
{
- "BriefDescription": "Intel Optane DC persistent memory bandwidth total (MB). Derived from unc_m_pmm_rpq_inserts",
+ "BriefDescription": "Intel Optane DC persistent memory bandwidth total (MB/sec). Derived from unc_m_pmm_rpq_inserts",
"Counter": "0,1,2,3",
"EventCode": "0xE3",
"EventName": "UNC_M_PMM_BANDWIDTH.TOTAL",
"MetricExpr": "UNC_M_PMM_RPQ_INSERTS + UNC_M_PMM_WPQ_INSERTS",
"MetricName": "UNC_M_PMM_BANDWIDTH.TOTAL",
"PerPkg": "1",
- "ScaleUnit": "6.103515625E-5MB",
+ "ScaleUnit": "6.103515625E-5MB/sec",
"Unit": "iMC"
},
{
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-other.json b/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-other.json
index 0cd083839e75..3be09986ce8b 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-other.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/uncore-other.json
@@ -104,15 +104,6 @@
"Unit": "CHA"
},
{
- "BriefDescription": "write requests from remote home agent",
- "Counter": "0,1,2,3",
- "EventCode": "0x50",
- "EventName": "UNC_CHA_REQUESTS.WRITES_REMOTE",
- "PerPkg": "1",
- "UMask": "0x08",
- "Unit": "CHA"
- },
- {
"BriefDescription": "UPI interconnect send bandwidth for payload. Derived from unc_upi_txl_flits.all_data",
"Counter": "0,1,2,3",
"EventCode": "0x2",
@@ -544,7 +535,7 @@
"EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD",
"Filter": "config1=0x40433",
"PerPkg": "1",
- "PublicDescription": "TOR Inserts : DRds issued by iA Cores that Missed the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.",
+ "PublicDescription": "TOR Inserts : DRds issued by iA Cores that Missed the LLC : Counts the number of entries successfuly inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.",
"UMask": "0x21",
"Unit": "CHA"
},
@@ -568,6 +559,98 @@
"Unit": "IIO"
},
{
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xC2",
+ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART0",
+ "FCMask": "0x4",
+ "PerPkg": "1",
+ "PortMask": "0x01",
+ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0",
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 1",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xC2",
+ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART1",
+ "FCMask": "0x4",
+ "PerPkg": "1",
+ "PortMask": "0x02",
+ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 1",
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xC2",
+ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART2",
+ "FCMask": "0x4",
+ "PerPkg": "1",
+ "PortMask": "0x04",
+ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 2",
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 3",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xC2",
+ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART3",
+ "FCMask": "0x4",
+ "PerPkg": "1",
+ "PortMask": "0x08",
+ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 3",
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 0",
+ "Counter": "2,3",
+ "EventCode": "0xD5",
+ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART0",
+ "FCMask": "0x04",
+ "PerPkg": "1",
+ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 0",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 1",
+ "Counter": "2,3",
+ "EventCode": "0xD5",
+ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART1",
+ "FCMask": "0x04",
+ "PerPkg": "1",
+ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 1",
+ "UMask": "0x02",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 2",
+ "Counter": "2,3",
+ "EventCode": "0xD5",
+ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART2",
+ "FCMask": "0x04",
+ "PerPkg": "1",
+ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 2",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 3",
+ "Counter": "2,3",
+ "EventCode": "0xD5",
+ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART3",
+ "FCMask": "0x04",
+ "PerPkg": "1",
+ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 3",
+ "UMask": "0x08",
+ "Unit": "IIO"
+ },
+ {
"BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part0",
"Counter": "2,3",
"EventCode": "0xC0",
@@ -1240,6 +1323,64 @@
"Unit": "IIO"
},
{
+ "BriefDescription": "Total IRP occupancy of inbound read and write requests.",
+ "Counter": "0,1",
+ "EventCode": "0xF",
+ "EventName": "UNC_I_CACHE_TOTAL_OCCUPANCY.MEM",
+ "PerPkg": "1",
+ "PublicDescription": "Total IRP occupancy of inbound read and write requests. This is effectively the sum of read occupancy and write occupancy.",
+ "UMask": "0x4",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "PCIITOM request issued by the IRP unit to the mesh with the intention of writing a full cacheline.",
+ "Counter": "0,1",
+ "EventCode": "0x10",
+ "EventName": "UNC_I_COHERENT_OPS.PCITOM",
+ "PerPkg": "1",
+ "PublicDescription": "PCIITOM request issued by the IRP unit to the mesh with the intention of writing a full cacheline to coherent memory, without a RFO. PCIITOM is a speculative Invalidate to Modified command that requests ownership of the cacheline and does not move data from the mesh to IRP cache.",
+ "UMask": "0x10",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "RFO request issued by the IRP unit to the mesh with the intention of writing a partial cacheline.",
+ "Counter": "0,1",
+ "EventCode": "0x10",
+ "EventName": "UNC_I_COHERENT_OPS.RFO",
+ "PerPkg": "1",
+ "PublicDescription": "RFO request issued by the IRP unit to the mesh with the intention of writing a partial cacheline to coherent memory. RFO is a Read For Ownership command that requests ownership of the cacheline and moves data from the mesh to IRP cache.",
+ "UMask": "0x8",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "Inbound read requests received by the IRP and inserted into the FAF queue.",
+ "Counter": "0,1",
+ "EventCode": "0x18",
+ "EventName": "UNC_I_FAF_INSERTS",
+ "PerPkg": "1",
+ "PublicDescription": "Inbound read requests to coherent memory, received by the IRP and inserted into the Fire and Forget queue (FAF), a queue used for processing inbound reads in the IRP.",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "Occupancy of the IRP FAF queue.",
+ "Counter": "0,1",
+ "EventCode": "0x19",
+ "EventName": "UNC_I_FAF_OCCUPANCY",
+ "PerPkg": "1",
+ "PublicDescription": "Occupancy of the IRP Fire and Forget (FAF) queue, a queue used for processing inbound reads in the IRP.",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "Inbound write (fast path) requests received by the IRP.",
+ "Counter": "0,1",
+ "EventCode": "0x11",
+ "EventName": "UNC_I_TRANSACTIONS.WR_PREF",
+ "PerPkg": "1",
+ "PublicDescription": "Inbound write (fast path) requests to coherent memory, received by the IRP resulting in write ownership requests issued by IRP to the mesh.",
+ "UMask": "0x8",
+ "Unit": "IRP"
+ },
+ {
"BriefDescription": "Traffic in which the M2M to iMC Bypass was not taken",
"Counter": "0,1,2,3",
"EventCode": "0x22",
diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/virtual-memory.json b/tools/perf/pmu-events/arch/x86/cascadelakex/virtual-memory.json
index d13b4111eb52..792ca39f013a 100644
--- a/tools/perf/pmu-events/arch/x86/cascadelakex/virtual-memory.json
+++ b/tools/perf/pmu-events/arch/x86/cascadelakex/virtual-memory.json
@@ -1,35 +1,5 @@
[
{
- "BriefDescription": "Page walk completed due to a demand data store to a 2M/4M page",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
- "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.",
- "SampleAfterValue": "100003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_PENDING",
- "PublicDescription": "Counts 1 per cycle for each PMH (Page Miss Handler) that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake michroarchitecture.",
- "SampleAfterValue": "100003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_COMPLETED",
- "PublicDescription": "Counts completed page walks (2M and 4M page sizes) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.",
- "SampleAfterValue": "100003",
- "UMask": "0xe"
- },
- {
"BriefDescription": "Load misses in all DTLB levels that cause page walks",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -40,13 +10,13 @@
"UMask": "0x1"
},
{
- "BriefDescription": "STLB flush attempts",
+ "BriefDescription": "Loads that miss the DTLB and hit the STLB.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xBD",
- "EventName": "TLB_FLUSH.STLB_ANY",
- "PublicDescription": "Counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, etc.).",
- "SampleAfterValue": "100007",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).",
+ "SampleAfterValue": "2000003",
"UMask": "0x20"
},
{
@@ -61,44 +31,34 @@
"UMask": "0x10"
},
{
- "BriefDescription": "Page walk completed due to a demand data store to a 1G page",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
- "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 1G pages. The page walks can end with or without a page fault.",
- "SampleAfterValue": "100003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
- "PublicDescription": "Counts demand data stores that caused a page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels, but the walk need not have completed.",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data loads. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0x1"
+ "UMask": "0xe"
},
{
- "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "BriefDescription": "Page walk completed due to a demand data load to a 1G page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xAE",
- "EventName": "ITLB.ITLB_FLUSH",
- "PublicDescription": "Counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
- "SampleAfterValue": "100007",
- "UMask": "0x1"
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
+ "PublicDescription": "Counts completed page walks (1G sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake.",
+ "BriefDescription": "Page walk completed due to a demand data load to a 2M/4M page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
- "PublicDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake microarchitecture.",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "PublicDescription": "Counts completed page walks (2M/4M sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "UMask": "0x4"
},
{
"BriefDescription": "Page walk completed due to a demand data load to a 4K page",
@@ -106,21 +66,11 @@
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x08",
"EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
- "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "PublicDescription": "Counts completed page walks (4K sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "2000003",
"UMask": "0x2"
},
{
- "BriefDescription": "Page walk completed due to a demand data load to a 2M/4M page",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
- "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
"BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a load. EPT page walk duration are excluded in Skylake.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -131,14 +81,24 @@
"UMask": "0x10"
},
{
- "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a EPT (Extended Page Table) walk for any request type.",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x4F",
- "EventName": "EPT.WALK_PENDING",
- "PublicDescription": "Counts cycles for each PMH (Page Miss Handler) that is busy with an EPT (Extended Page Table) walk for any request type.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "PublicDescription": "Counts demand data stores that caused a page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels, but the walk need not have completed.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Stores that miss the DTLB and hit the STLB.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "PublicDescription": "Stores that miss the DTLB (Data TLB) and hit the STLB (2nd Level TLB).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x20"
},
{
"BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store. EPT page walk duration are excluded in Skylake.",
@@ -152,34 +112,34 @@
"UMask": "0x10"
},
{
- "BriefDescription": "Misses at all ITLB levels that cause page walks",
+ "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
- "PublicDescription": "Counts page walks of any page size (4K/2M/4M/1G) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB, but the walk need not have completed.",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data stores. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0x1"
+ "UMask": "0xe"
},
{
- "BriefDescription": "Stores that miss the DTLB and hit the STLB.",
+ "BriefDescription": "Page walk completed due to a demand data store to a 1G page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.STLB_HIT",
- "PublicDescription": "Stores that miss the DTLB (Data TLB) and hit the STLB (2nd Level TLB).",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
+ "PublicDescription": "Counts completed page walks (1G sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0x20"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)",
+ "BriefDescription": "Page walk completed due to a demand data store to a 2M/4M page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
- "PublicDescription": "Counts demand data loads that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "PublicDescription": "Counts completed page walks (2M/4M sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0xe"
+ "UMask": "0x4"
},
{
"BriefDescription": "Page walk completed due to a demand data store to a 4K page",
@@ -187,29 +147,49 @@
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x49",
"EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
- "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "PublicDescription": "Counts completed page walks (4K sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
"UMask": "0x2"
},
{
- "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
- "PublicDescription": "Counts completed page walks (4K page size) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.",
- "SampleAfterValue": "100003",
- "UMask": "0x2"
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
+ "PublicDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake microarchitecture.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
},
{
- "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (1G)",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a EPT (Extended Page Table) walk for any request type.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x4f",
+ "EventName": "EPT.WALK_PENDING",
+ "PublicDescription": "Counts cycles for each PMH (Page Miss Handler) that is busy with an EPT (Extended Page Table) walk for any request type.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xAE",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "PublicDescription": "Counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
+ "SampleAfterValue": "100007",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
- "PublicDescription": "Counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "PublicDescription": "Counts page walks of any page size (4K/2M/4M/1G) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB, but the walk need not have completed.",
"SampleAfterValue": "100003",
- "UMask": "0x8"
+ "UMask": "0x1"
},
{
"BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB.",
@@ -221,13 +201,34 @@
"UMask": "0x20"
},
{
- "BriefDescription": "Page walk completed due to a demand data load to a 1G page",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
- "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
- "SampleAfterValue": "2000003",
+ "CounterMask": "1",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_ACTIVE",
+ "PublicDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake microarchitecture.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0xe"
+ },
+ {
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (1G)",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
+ "PublicDescription": "Counts completed page walks (1G page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
"UMask": "0x8"
},
{
@@ -236,42 +237,31 @@
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x85",
"EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
- "PublicDescription": "Counts code misses in all ITLB levels that caused a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "PublicDescription": "Counts completed page walks (2M/4M page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
"UMask": "0x4"
},
{
- "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
- "PublicDescription": "Counts demand data stores that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "PublicDescription": "Counts completed page walks (4K page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0xe"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake.",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
"EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_ACTIVE",
- "PublicDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake microarchitecture.",
+ "EventName": "ITLB_MISSES.WALK_PENDING",
+ "PublicDescription": "Counts 1 per cycle for each PMH (Page Miss Handler) that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake michroarchitecture.",
"SampleAfterValue": "100003",
"UMask": "0x10"
},
{
- "BriefDescription": "Loads that miss the DTLB and hit the STLB.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
- "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
- },
- {
"BriefDescription": "DTLB flush attempts of the thread-specific entries",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -280,5 +270,15 @@
"PublicDescription": "Counts the number of DTLB flush attempts of the thread-specific entries.",
"SampleAfterValue": "100007",
"UMask": "0x1"
+ },
+ {
+ "BriefDescription": "STLB flush attempts",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xBD",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "PublicDescription": "Counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, etc.).",
+ "SampleAfterValue": "100007",
+ "UMask": "0x20"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/elkhartlake/cache.json b/tools/perf/pmu-events/arch/x86/elkhartlake/cache.json
new file mode 100644
index 000000000000..734be4ea095f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/elkhartlake/cache.json
@@ -0,0 +1,226 @@
+[
+ {
+ "BriefDescription": "Counts the number of first level data cacheline (dirty) evictions caused by misses, stores, and prefetches.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x51",
+ "EventName": "DL1.DIRTY_EVICTION",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of first level data cacheline (dirty) evictions caused by misses, stores, and prefetches. Does not count evictions or dirty writebacks caused by snoops. Does not count a replacement unless a (dirty) line was written back.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of cacheable memory requests that miss in the LLC. Counts on a per core basis.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x2e",
+ "EventName": "LONGEST_LAT_CACHE.MISS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cacheable memory requests that miss in the Last Level Cache (LLC). If the platform has an L3 cache, the LLC is the L3 cache, otherwise it is the L2 cache. Counts on a per core basis.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x41"
+ },
+ {
+ "BriefDescription": "Counts the number of cacheable memory requests that access the LLC. Counts on a per core basis.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x2e",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cacheable memory requests that access the Last Level Cache (LLC). Requests include demand loads, reads for ownership (RFO), instruction fetches and L1 HW prefetches. If the platform has an L3 cache, the LLC is the L3 cache, otherwise it is the L2 cache. Counts on a per core basis.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4f"
+ },
+ {
+ "BriefDescription": "Counts the number of cycles the core is stalled due to an instruction cache or TLB miss which hit in DRAM or MMIO (Non-DRAM).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "MEM_BOUND_STALLS.IFETCH_DRAM_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles a core is stalled due to an instruction cache or translation lookaside buffer (TLB) access which hit in DRAM or MMIO (non-DRAM).",
+ "SampleAfterValue": "200003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Counts the number of cycles the core is stalled due to an instruction cache or TLB miss which hit in the L2 cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "MEM_BOUND_STALLS.IFETCH_L2_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles a core is stalled due to an instruction cache or Translation Lookaside Buffer (TLB) access which hit in the L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts the number of cycles the core is stalled due to an instruction cache or TLB miss which hit in the LLC or other core with HITE/F/M.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "MEM_BOUND_STALLS.IFETCH_LLC_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles a core is stalled due to an instruction cache or Translation Lookaside Buffer (TLB) access which hit in the Last Level Cache (LLC) or other core with HITE/F/M.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts the number of cycles the core is stalled due to a demand load miss which hit in DRAM or MMIO (Non-DRAM).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "MEM_BOUND_STALLS.LOAD_DRAM_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of cycles the core is stalled due to a demand load which hit in the L2 cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "MEM_BOUND_STALLS.LOAD_L2_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles a core is stalled due to a demand load which hit in the L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of cycles the core is stalled due to a demand load which hit in the LLC or other core with HITE/F/M.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "MEM_BOUND_STALLS.LOAD_LLC_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles a core is stalled due to a demand load which hit in the Last Level Cache (LLC) or other core with HITE/F/M.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of cycles a core is stalled due to a store buffer being full.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "MEM_BOUND_STALLS.STORE_BUFFER_FULL",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Counts the number of load ops retired that hit in DRAM.",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.DRAM_HIT",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Counts the number of load uops retired that hit in the L1 data cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of load uops retired that miss in the L1 data cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts the number of load uops retired that hit in the L2 cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of load uops retired that miss in the L2 cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts the number of load uops retired that hit in the L3 cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of load uops retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_UOPS_RETIRED.ALL_LOADS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of load uops retired.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x81"
+ },
+ {
+ "BriefDescription": "Counts the number of store uops retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_UOPS_RETIRED.ALL_STORES",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of store uops retired.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x82"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to instruction cache misses.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.ICACHE",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x20"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/elkhartlake/ehl-metrics.json b/tools/perf/pmu-events/arch/x86/elkhartlake/ehl-metrics.json
new file mode 100644
index 000000000000..b6f7126be1fd
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/elkhartlake/ehl-metrics.json
@@ -0,0 +1,57 @@
+[
+ {
+ "MetricExpr": "INST_RETIRED.ANY / cycles",
+ "BriefDescription": "Instructions Per Cycle (per Logical Processor)",
+ "MetricName": "IPC"
+ },
+ {
+ "MetricExpr": "1 / IPC",
+ "BriefDescription": "Cycles Per Instruction (per Logical Processor)",
+ "MetricName": "CPI"
+ },
+ {
+ "MetricExpr": "cycles",
+ "BriefDescription": "Per-Logical Processor actual clocks when the Logical Processor is active.",
+ "MetricName": "CLKS"
+ },
+ {
+ "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES",
+ "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear)",
+ "MetricName": "IpMispredict"
+ },
+ {
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES",
+ "BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)",
+ "MetricName": "IpBranch"
+ },
+ {
+ "MetricExpr": "INST_RETIRED.ANY",
+ "BriefDescription": "Total number of retired Instructions",
+ "MetricName": "Instructions"
+ },
+ {
+ "MetricExpr": "64 * LONGEST_LAT_CACHE.MISS / 1000000000 ",
+ "BriefDescription": "Average per-core data fill bandwidth to the L3 cache [GB / sec]",
+ "MetricName": "L3_Cache_Fill_BW"
+ },
+ {
+ "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
+ "BriefDescription": "Average CPU Utilization",
+ "MetricName": "CPU_Utilization"
+ },
+ {
+ "MetricExpr": "(cycles / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 ",
+ "BriefDescription": "Measured Average Frequency for unhalted processors [GHz]",
+ "MetricName": "Average_Frequency"
+ },
+ {
+ "MetricExpr": "cycles / CPU_CLK_UNHALTED.REF_TSC",
+ "BriefDescription": "Average Frequency Utilization relative nominal frequency",
+ "MetricName": "Turbo_Utilization"
+ },
+ {
+ "MetricExpr": "cycles:k / cycles",
+ "BriefDescription": "Fraction of cycles spent in the Operating System (OS) Kernel mode",
+ "MetricName": "Kernel_Utilization"
+ }
+]
diff --git a/tools/perf/pmu-events/arch/x86/elkhartlake/floating-point.json b/tools/perf/pmu-events/arch/x86/elkhartlake/floating-point.json
new file mode 100644
index 000000000000..2515b9aa6e66
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/elkhartlake/floating-point.json
@@ -0,0 +1,24 @@
+[
+ {
+ "BriefDescription": "Counts the number of cycles the floating point divider is busy. Does not imply a stall waiting for the divider.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xcd",
+ "EventName": "CYCLES_DIV_BUSY.FPDIV",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of floating point divide uops retired (x87 and SSE, including x87 sqrt).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc2",
+ "EventName": "UOPS_RETIRED.FPDIV",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/elkhartlake/frontend.json b/tools/perf/pmu-events/arch/x86/elkhartlake/frontend.json
new file mode 100644
index 000000000000..b7b8cb7bd868
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/elkhartlake/frontend.json
@@ -0,0 +1,93 @@
+[
+ {
+ "BriefDescription": "Counts the total number of BACLEARS.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xe6",
+ "EventName": "BACLEARS.ANY",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of BACLEARS, which occur when the Branch Target Buffer (BTB) prediction or lack thereof, was corrected by a later branch predictor in the frontend. Includes BACLEARS due to all branch types including conditional and unconditional jumps, returns, and indirect branches.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of BACLEARS due to a conditional jump.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xe6",
+ "EventName": "BACLEARS.COND",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts the number of BACLEARS due to an indirect branch.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xe6",
+ "EventName": "BACLEARS.INDIRECT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of BACLEARS due to a return branch.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xe6",
+ "EventName": "BACLEARS.RETURN",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts the number of BACLEARS due to a non-indirect, non-conditional jump.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xe6",
+ "EventName": "BACLEARS.UNCOND",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of times a decode restriction reduces the decode throughput due to wrong instruction length prediction.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xe9",
+ "EventName": "DECODE_RESTRICTION.PREDECODE_WRONG",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of requests to the instruction cache for one or more bytes of a cache line.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x80",
+ "EventName": "ICACHE.ACCESSES",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of requests to the instruction cache. The event only counts new cache line accesses, so that multiple back to back fetches to the exact same cache line or byte chunk count as one. Specifically, the event counts when accesses from sequential code crosses the cache line boundary, or when a branch target is moved to a new line or to a non-sequential byte chunk of the same line.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x3"
+ },
+ {
+ "BriefDescription": "Counts the number of instruction cache misses.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x80",
+ "EventName": "ICACHE.MISSES",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of missed requests to the instruction cache. The event only counts new cache line accesses, so that multiple back to back fetches to the exact same cache line and byte chunk count as one. Specifically, the event counts when accesses from sequential code crosses the cache line boundary, or when a branch target is moved to a new line or to a non-sequential byte chunk of the same line.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/elkhartlake/memory.json b/tools/perf/pmu-events/arch/x86/elkhartlake/memory.json
new file mode 100644
index 000000000000..4e4eab23a300
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/elkhartlake/memory.json
@@ -0,0 +1,86 @@
+[
+ {
+ "BriefDescription": "Counts the number of memory ordering machine clears triggered by a snoop from an external agent.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc3",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of memory ordering machine clears triggered by a snoop from an external agent. Does not count internally generated machine clears such as those due to disambiguations.",
+ "SampleAfterValue": "20003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts cacheable demand data reads, L1 data cache hardware prefetches and software prefetches (except PREFETCHW) that were not supplied by the L3 cache.",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_DATA_AND_L1PF_RD.L3_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x2104000001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts cacheable demand data reads, L1 data cache hardware prefetches and software prefetches (except PREFETCHW) that were not supplied by the L3 cache.",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_DATA_AND_L1PF_RD.L3_MISS_LOCAL",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x2104000001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_AND_L1PF_RD.L3_MISS",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x2104000001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_AND_L1PF_RD.L3_MISS_LOCAL",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x2104000001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts demand reads for ownership (RFO) and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the L3 cache.",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x2104000002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts demand reads for ownership (RFO) and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the L3 cache.",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x2104000002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/elkhartlake/other.json b/tools/perf/pmu-events/arch/x86/elkhartlake/other.json
new file mode 100644
index 000000000000..627691404155
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/elkhartlake/other.json
@@ -0,0 +1,424 @@
+[
+ {
+ "BriefDescription": "Counts the total number of BTCLEARS.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xe8",
+ "EventName": "BTCLEAR.ANY",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of BTCLEARS which occurs when the Branch Target Buffer (BTB) predicts a taken branch.",
+ "SampleAfterValue": "200003"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event BUS_LOCK.SELF_LOCKS",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EdgeDetect": "1",
+ "EventCode": "0x63",
+ "EventName": "BUS_LOCK.ALL",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003"
+ },
+ {
+ "BriefDescription": "Counts the number of unhalted cycles a core is blocked due to an accepted lock issued by other cores.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x63",
+ "EventName": "BUS_LOCK.BLOCK_CYCLES",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of unhalted cycles a core is blocked due to an accepted lock issued by other cores. Counts on a per core basis.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event BUS_LOCK.BLOCK_CYCLES",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x63",
+ "EventName": "BUS_LOCK.CYCLES_OTHER_BLOCK",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event BUS_LOCK.LOCK_CYCLES",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x63",
+ "EventName": "BUS_LOCK.CYCLES_SELF_BLOCK",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of unhalted cycles a core is blocked due to an accepted lock it issued.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x63",
+ "EventName": "BUS_LOCK.LOCK_CYCLES",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of unhalted cycles a core is blocked due to an accepted lock it issued. Counts on a per core basis.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of bus locks a core issued its self (e.g. lock to UC or Split Lock) and does not include cache locks.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EdgeDetect": "1",
+ "EventCode": "0x63",
+ "EventName": "BUS_LOCK.SELF_LOCKS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of bus locks a core issued its self (e.g. lock to UC or Split Lock) and does not include cache locks. Counts on a per core basis.",
+ "SampleAfterValue": "200003"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event MEM_BOUND_STALLS.LOAD_DRAM_HIT",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "C0_STALLS.LOAD_DRAM_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event MEM_BOUND_STALLS.LOAD_L2_HIT",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "C0_STALLS.LOAD_L2_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event MEM_BOUND_STALLS.LOAD_LLC_HIT",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x34",
+ "EventName": "C0_STALLS.LOAD_LLC_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of core cycles during which interrupts are masked (disabled).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xcb",
+ "EventName": "HW_INTERRUPTS.MASKED",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of core cycles during which interrupts are masked (disabled). Increments by 1 each core cycle that EFLAGS.IF is 0, regardless of whether interrupts are pending or not.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of core cycles during which there are pending interrupts while interrupts are masked (disabled).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xcb",
+ "EventName": "HW_INTERRUPTS.PENDING_AND_MASKED",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of core cycles during which there are pending interrupts while interrupts are masked (disabled). Increments by 1 each core cycle that both EFLAGS.IF is 0 and an INTR is pending (which means the APIC is telling the ROB to cause an INTR). This event does not increment if EFLAGS.IF is 0 but all interrupt in the APICs Interrupt Request Register (IRR) are inhibited by the PPR (thus either by ISRV or TPR) because in these cases the interrupts would be held up in the APIC and would not be pended to the ROB. This event does count when an interrupt is only inhibited by MOV/POP SS state machines or the STI state machine. These extra inhibits only last for a single instructions and would not be important.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of hardware interrupts received by the processor.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xcb",
+ "EventName": "HW_INTERRUPTS.RECEIVED",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "203",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts cacheable demand data reads, L1 data cache hardware prefetches and software prefetches (except PREFETCHW) that have any type of response.",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_DATA_AND_L1PF_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x10001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event OCR.DEMAND_DATA_AND_L1PF_RD.ANY_RESPONSE",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x10001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts demand reads for ownership (RFO) and software prefetches for exclusive ownership (PREFETCHW) that have any type of response.",
+ "Counter": "0,1,2,3",
+ "EventCode": "0XB7",
+ "EventName": "OCR.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x10002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the total number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x73",
+ "EventName": "TOPDOWN_BAD_SPECULATION.ALL",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear. Only issue slots wasted due to fast nukes such as memory ordering nukes are counted. Other nukes are not accounted for. Counts all issue slots blocked during this recovery window including relevant microcode flows and while uops are not yet available in the instruction queue (IQ). Also includes the issue slots that were consumed by the backend but were thrown away because they were younger than the mispredict or machine clear.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x6"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to fast nukes such as memory ordering and memory disambiguation machine clears.",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x73",
+ "EventName": "TOPDOWN_BAD_SPECULATION.FASTNUKE",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the total number of issue slots that were not consumed by the backend because allocation is stalled due to a machine clear (nuke) of any kind including memory ordering and memory disambiguation.",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x73",
+ "EventName": "TOPDOWN_BAD_SPECULATION.MACHINE_CLEARS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to branch mispredicts.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x73",
+ "EventName": "TOPDOWN_BAD_SPECULATION.MISPREDICT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event TOPDOWN_BAD_SPECULATION.FASTNUKE",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x73",
+ "EventName": "TOPDOWN_BAD_SPECULATION.MONUKE",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the total number of issue slots every cycle that were not consumed by the backend due to backend stalls.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x74",
+ "EventName": "TOPDOWN_BE_BOUND.ALL",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to certain allocation restrictions.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x74",
+ "EventName": "TOPDOWN_BE_BOUND.ALLOC_RESTRICTIONS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to memory reservation stalls in which a scheduler is not able to accept uops.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x74",
+ "EventName": "TOPDOWN_BE_BOUND.MEM_SCHEDULER",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to IEC or FPC RAT stalls, which can be due to FIQ or IEC reservation stalls in which the integer, floating point or SIMD scheduler is not able to accept uops.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x74",
+ "EventName": "TOPDOWN_BE_BOUND.NON_MEM_SCHEDULER",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to the physical register file unable to accept an entry (marble stalls).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x74",
+ "EventName": "TOPDOWN_BE_BOUND.REGISTER",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to the reorder buffer being full (ROB stalls).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x74",
+ "EventName": "TOPDOWN_BE_BOUND.REORDER_BUFFER",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to scoreboards from the instruction queue (IQ), jump execution unit (JEU), or microcode sequencer (MS).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x74",
+ "EventName": "TOPDOWN_BE_BOUND.SERIALIZATION",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "This event is deprecated.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x74",
+ "EventName": "TOPDOWN_BE_BOUND.STORE_BUFFER",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to frontend stalls.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.ALL",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to BACLEARS.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.BRANCH_DETECT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to BACLEARS, which occurs when the Branch Target Buffer (BTB) prediction or lack thereof, was corrected by a later branch predictor in the frontend. Includes BACLEARS due to all branch types including conditional and unconditional jumps, returns, and indirect branches.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to BTCLEARS.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.BRANCH_RESTEER",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to BTCLEARS, which occurs when the Branch Target Buffer (BTB) predicts a taken branch.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to the microcode sequencer (MS).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.CISC",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to decode stalls.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.DECODE",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to ITLB misses.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.ITLB",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to Instruction Table Lookaside Buffer (ITLB) misses.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to other common frontend stalls not categorized.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.OTHER",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to wrong predecodes.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x71",
+ "EventName": "TOPDOWN_FE_BOUND.PREDECODE",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the total number of consumed retirement slots.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc2",
+ "EventName": "TOPDOWN_RETIRING.ALL",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/elkhartlake/pipeline.json b/tools/perf/pmu-events/arch/x86/elkhartlake/pipeline.json
new file mode 100644
index 000000000000..41e5dfad8f51
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/elkhartlake/pipeline.json
@@ -0,0 +1,278 @@
+[
+ {
+ "BriefDescription": "Counts the total number of branch instructions retired for all branch types.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of instructions in which the instruction pointer (IP) of the processor is resteered due to a branch instruction and the branch instruction successfully retires. All branch type instructions are accounted for.",
+ "SampleAfterValue": "200003"
+ },
+ {
+ "BriefDescription": "Counts the number of near CALL branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.CALL",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xf9"
+ },
+ {
+ "BriefDescription": "Counts the number of far branch instructions retired, includes far jump, far call and return, and interrupt call and return.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xbf"
+ },
+ {
+ "BriefDescription": "Counts the number of near indirect CALL branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.IND_CALL",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xfb"
+ },
+ {
+ "BriefDescription": "Counts the number of retired JCC (Jump on Conditional Code) branch instructions retired, includes both taken and not taken branches.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.JCC",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x7e"
+ },
+ {
+ "BriefDescription": "Counts the number of near indirect JMP and near indirect CALL branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.NON_RETURN_IND",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xeb"
+ },
+ {
+ "BriefDescription": "Counts the number of near relative CALL branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.REL_CALL",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xfd"
+ },
+ {
+ "BriefDescription": "Counts the number of near RET branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.RETURN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xf7"
+ },
+ {
+ "BriefDescription": "Counts the number of taken JCC (Jump on Conditional Code) branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.TAKEN_JCC",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xfe"
+ },
+ {
+ "BriefDescription": "Counts the total number of mispredicted branch instructions retired for all branch types.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of mispredicted branch instructions retired. All branch type instructions are accounted for. Prediction of the branch target address enables the processor to begin executing instructions before the non-speculative execution path is known. The branch prediction unit (BPU) predicts the target address based on the instruction pointer (IP) of the branch and on the execution path through which execution reached this IP. A branch misprediction occurs when the prediction is wrong, and results in discarding all instructions executed in the speculative path and re-fetching from the correct path.",
+ "SampleAfterValue": "200003"
+ },
+ {
+ "BriefDescription": "Counts the number of mispredicted near indirect CALL branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.IND_CALL",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xfb"
+ },
+ {
+ "BriefDescription": "Counts the number of mispredicted JCC (Jump on Conditional Code) branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.JCC",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x7e"
+ },
+ {
+ "BriefDescription": "Counts the number of mispredicted near RET branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.RETURN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xf7"
+ },
+ {
+ "BriefDescription": "Counts the number of mispredicted taken JCC (Jump on Conditional Code) branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.TAKEN_JCC",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0xfe"
+ },
+ {
+ "BriefDescription": "Counts the number of unhalted core clock cycles. (Fixed event)",
+ "CollectPEBSRecord": "2",
+ "Counter": "Fixed counter 1",
+ "EventName": "CPU_CLK_UNHALTED.CORE",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "33",
+ "PublicDescription": "Counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. The core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time. This event uses fixed counter 1.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of unhalted core clock cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x3c",
+ "EventName": "CPU_CLK_UNHALTED.CORE_P",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. The core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time. This event uses a programmable general purpose performance counter.",
+ "SampleAfterValue": "2000003"
+ },
+ {
+ "BriefDescription": "Counts the number of unhalted reference clock cycles at TSC frequency.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x3c",
+ "EventName": "CPU_CLK_UNHALTED.REF",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. This event is not affected by core frequency changes and increments at a fixed frequency that is also used for the Time Stamp Counter (TSC). This event uses fixed counter 2.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of unhalted reference clock cycles at TSC frequency. (Fixed event)",
+ "CollectPEBSRecord": "2",
+ "Counter": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "34",
+ "PublicDescription": "Counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. This event is not affected by core frequency changes and increments at a fixed frequency that is also used for the Time Stamp Counter (TSC). This event uses fixed counter 2.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x3"
+ },
+ {
+ "BriefDescription": "Counts the number of unhalted reference clock cycles at TSC frequency.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x3c",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC_P",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. This event is not affected by core frequency changes and increments at a fixed frequency that is also used for the Time Stamp Counter (TSC). This event uses a programmable general purpose performance counter.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "This event is deprecated.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xcd",
+ "EventName": "CYCLES_DIV_BUSY.ANY",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "2000003"
+ },
+ {
+ "BriefDescription": "Counts the number of cycles the integer divider is busy. Does not imply a stall waiting for the divider.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xcd",
+ "EventName": "CYCLES_DIV_BUSY.IDIV",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the total number of instructions retired. (Fixed event)",
+ "CollectPEBSRecord": "2",
+ "Counter": "Fixed counter 0",
+ "EventName": "INST_RETIRED.ANY",
+ "PEBS": "1",
+ "PEBScounters": "32",
+ "PublicDescription": "Counts the total number of instructions that retired. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. This event continues counting during hardware interrupts, traps, and inside interrupt handlers. This event uses fixed counter 0.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the total number of instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of instructions that retired. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. This event continues counting during hardware interrupts, traps, and inside interrupt handlers. This event uses a programmable general purpose performance counter.",
+ "SampleAfterValue": "2000003"
+ },
+ {
+ "BriefDescription": "Counts the total number of machine clears including memory ordering, memory disambiguation, self-modifying code, page faults and floating point assist.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc3",
+ "EventName": "MACHINE_CLEARS.ANY",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "20003"
+ },
+ {
+ "BriefDescription": "Counts the number of uops that are from complex flows issued by the micro-sequencer (MS).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xc2",
+ "EventName": "UOPS_RETIRED.MS",
+ "PDIR_COUNTER": "na",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of uops that are from complex flows issued by the Microcode Sequencer (MS). This includes uops from flows due to complex instructions, faults, assists, and inserted flows.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/elkhartlake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/elkhartlake/virtual-memory.json
new file mode 100644
index 000000000000..c58b589ff80f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/elkhartlake/virtual-memory.json
@@ -0,0 +1,273 @@
+[
+ {
+ "BriefDescription": "Counts the number of page walks due to loads that miss the PDE (Page Directory Entry) cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.PDE_CACHE_MISS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Counts the number of first level TLB misses but second level hits due to loads that did not start a page walk. Account for all pages sizes. Will result in a DTLB write from STLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks completed due to load DTLB misses to any page size.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks completed due to loads (including SW prefetches) whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to any page size. Includes page walks that page fault.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks completed due to load DTLB misses to a 2M or 4M page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks completed due to loads (including SW prefetches) whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 2M or 4M pages. Includes page walks that page fault.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks completed due to load DTLB misses to a 4K page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks completed due to loads (including SW prefetches) whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 4K pages. Includes page walks that page fault.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks outstanding in the page miss handler (PMH) for loads every cycle.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_PENDING",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks outstanding in the page miss handler (PMH) for loads every cycle. A page walk is outstanding from start till PMH becomes idle again (ready to serve next walk). Includes EPT-walk intervals.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks due to stores that miss the PDE (Page Directory Entry) cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.PDE_CACHE_MISS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks due to storse that miss the PDE (Page Directory Entry) cache.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks completed due to store DTLB misses to a 2M or 4M page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks completed due to stores whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 2M or 4M pages. Includes page walks that page fault.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks completed due to store DTLB misses to a 4K page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks completed due to stores whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 4K pages. Includes page walks that page fault.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks outstanding in the page miss handler (PMH) for stores every cycle.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks outstanding in the page miss handler (PMH) for stores every cycle. A page walk is outstanding from start till PMH becomes idle again (ready to serve next walk). Includes EPT-walk intervals.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts the number of Extended Page Directory Entry hits.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x4f",
+ "EventName": "EPT.EPDE_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of Extended Page Directory Entry hits. The Extended Page Directory cache is used by Virtual Machine operating systems while the guest operating systems use the standard TLB caches.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of Extended Page Directory Entry misses.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x4f",
+ "EventName": "EPT.EPDE_MISS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number Extended Page Directory Entry misses. The Extended Page Directory cache is used by Virtual Machine operating systems while the guest operating systems use the standard TLB caches.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of Extended Page Directory Pointer Entry hits.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x4f",
+ "EventName": "EPT.EPDPE_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number Extended Page Directory Pointer Entry hits. The Extended Page Directory cache is used by Virtual Machine operating systems while the guest operating systems use the standard TLB caches.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of Extended Page Directory Pointer Entry misses.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x4f",
+ "EventName": "EPT.EPDPE_MISS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number Extended Page Directory Pointer Entry misses. The Extended Page Directory cache is used by Virtual Machine operating systems while the guest operating systems use the standard TLB caches.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts the number of times there was an ITLB miss and a new translation was filled into the ITLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x81",
+ "EventName": "ITLB.FILLS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of times the machine was unable to find a translation in the Instruction Translation Lookaside Buffer (ITLB) and a new translation was filled into the ITLB. The event is speculative in nature, but will not count translations (page walks) that are begun and not finished, or translations that are finished but not filled into the ITLB.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks due to an instruction fetch that miss the PDE (Page Directory Entry) cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.PDE_CACHE_MISS",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Counts the number of first level TLB misses but second level hits due to an instruction fetch that did not start a page walk. Account for all pages sizes. Will results in a DTLB write from STLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks completed due to instruction fetch misses to a 2M or 4M page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks completed due to instruction fetches whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 2M or 4M pages. Includes page walks that page fault.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks completed due to instruction fetch misses to a 4K page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks completed due to instruction fetches whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 4K pages. Includes page walks that page fault.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of page walks outstanding in the page miss handler (PMH) for instruction fetches every cycle.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_PENDING",
+ "PDIR_COUNTER": "na",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks outstanding in the page miss handler (PMH) for instruction fetches every cycle. A page walk is outstanding from start till PMH becomes idle again (ready to serve next walk).",
+ "SampleAfterValue": "200003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts the number of memory retired ops that missed in the second level TLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_UOPS_RETIRED.DTLB_MISS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x13"
+ },
+ {
+ "BriefDescription": "Counts the number of load ops retired that miss in the second Level TLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_LOADS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x11"
+ },
+ {
+ "BriefDescription": "Counts the number of store ops retired that miss in the second level TLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_STORES",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x12"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json b/tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json
new file mode 100644
index 000000000000..57ddbb9f9b31
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json
@@ -0,0 +1,315 @@
+[
+ {
+ "BriefDescription": "Instructions Per Cycle (per Logical Processor)",
+ "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "Summary",
+ "MetricName": "IPC"
+ },
+ {
+ "BriefDescription": "Uops Per Instruction",
+ "MetricExpr": "UOPS_RETIRED.SLOTS / INST_RETIRED.ANY",
+ "MetricGroup": "Pipeline;Retire",
+ "MetricName": "UPI"
+ },
+ {
+ "BriefDescription": "Instruction per taken branch",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_TAKEN",
+ "MetricGroup": "Branches;FetchBW;PGO",
+ "MetricName": "IpTB"
+ },
+ {
+ "BriefDescription": "Cycles Per Instruction (per Logical Processor)",
+ "MetricExpr": "1 / (INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD)",
+ "MetricGroup": "Pipeline",
+ "MetricName": "CPI"
+ },
+ {
+ "BriefDescription": "Per-Logical Processor actual clocks when the Logical Processor is active.",
+ "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "Pipeline",
+ "MetricName": "CLKS"
+ },
+ {
+ "BriefDescription": "Instructions Per Cycle (per physical core)",
+ "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.DISTRIBUTED",
+ "MetricGroup": "SMT;TmaL1",
+ "MetricName": "CoreIPC"
+ },
+ {
+ "BriefDescription": "Floating Point Operations Per Cycle",
+ "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / CPU_CLK_UNHALTED.DISTRIBUTED",
+ "MetricGroup": "Flops",
+ "MetricName": "FLOPc"
+ },
+ {
+ "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
+ "MetricExpr": "UOPS_EXECUTED.THREAD / (( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2 ) if #SMT_on else UOPS_EXECUTED.CORE_CYCLES_GE_1)",
+ "MetricGroup": "Pipeline;PortsUtil",
+ "MetricName": "ILP"
+ },
+ {
+ "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES",
+ "MetricGroup": "BrMispredicts",
+ "MetricName": "IpMispredict"
+ },
+ {
+ "BriefDescription": "Core actual clocks when any Logical Processor is active on the Physical Core",
+ "MetricExpr": "CPU_CLK_UNHALTED.DISTRIBUTED",
+ "MetricGroup": "SMT",
+ "MetricName": "CORE_CLKS"
+ },
+ {
+ "BriefDescription": "Instructions per Load (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_LOADS",
+ "MetricGroup": "InsType",
+ "MetricName": "IpLoad"
+ },
+ {
+ "BriefDescription": "Instructions per Store (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_STORES",
+ "MetricGroup": "InsType",
+ "MetricName": "IpStore"
+ },
+ {
+ "BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES",
+ "MetricGroup": "Branches;InsType",
+ "MetricName": "IpBranch"
+ },
+ {
+ "BriefDescription": "Instructions per (near) call (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_CALL",
+ "MetricGroup": "Branches",
+ "MetricName": "IpCall"
+ },
+ {
+ "BriefDescription": "Branch instructions per taken branch. ",
+ "MetricExpr": "BR_INST_RETIRED.ALL_BRANCHES / BR_INST_RETIRED.NEAR_TAKEN",
+ "MetricGroup": "Branches;PGO",
+ "MetricName": "BpTkBranch"
+ },
+ {
+ "BriefDescription": "Instructions per Floating Point (FP) Operation (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE )",
+ "MetricGroup": "Flops;FpArith;InsType",
+ "MetricName": "IpFLOP"
+ },
+ {
+ "BriefDescription": "Total number of retired Instructions, Sample with: INST_RETIRED.PREC_DIST",
+ "MetricExpr": "INST_RETIRED.ANY",
+ "MetricGroup": "Summary;TmaL1",
+ "MetricName": "Instructions"
+ },
+ {
+ "BriefDescription": "Fraction of Uops delivered by the LSD (Loop Stream Detector; aka Loop Cache)",
+ "MetricExpr": "LSD.UOPS / (IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS)",
+ "MetricGroup": "LSD",
+ "MetricName": "LSD_Coverage"
+ },
+ {
+ "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded ICache; or Uop Cache)",
+ "MetricExpr": "IDQ.DSB_UOPS / (IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS)",
+ "MetricGroup": "DSB;FetchBW",
+ "MetricName": "DSB_Coverage"
+ },
+ {
+ "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads (in core cycles)",
+ "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT )",
+ "MetricGroup": "MemoryBound;MemoryLat",
+ "MetricName": "Load_Miss_Real_Latency"
+ },
+ {
+ "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least one such miss. Per-Logical Processor)",
+ "MetricExpr": "L1D_PEND_MISS.PENDING / L1D_PEND_MISS.PENDING_CYCLES",
+ "MetricGroup": "MemoryBound;MemoryBW",
+ "MetricName": "MLP"
+ },
+ {
+ "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
+ "MetricConstraint": "NO_NMI_WATCHDOG",
+ "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING ) / ( 2 * CPU_CLK_UNHALTED.DISTRIBUTED )",
+ "MetricGroup": "MemoryTLB",
+ "MetricName": "Page_Walks_Utilization"
+ },
+ {
+ "BriefDescription": "Average data fill bandwidth to the L1 data cache [GB / sec]",
+ "MetricExpr": "64 * L1D.REPLACEMENT / 1000000000 / duration_time",
+ "MetricGroup": "MemoryBW",
+ "MetricName": "L1D_Cache_Fill_BW"
+ },
+ {
+ "BriefDescription": "Average data fill bandwidth to the L2 cache [GB / sec]",
+ "MetricExpr": "64 * L2_LINES_IN.ALL / 1000000000 / duration_time",
+ "MetricGroup": "MemoryBW",
+ "MetricName": "L2_Cache_Fill_BW"
+ },
+ {
+ "BriefDescription": "Average per-core data fill bandwidth to the L3 cache [GB / sec]",
+ "MetricExpr": "64 * LONGEST_LAT_CACHE.MISS / 1000000000 / duration_time",
+ "MetricGroup": "MemoryBW",
+ "MetricName": "L3_Cache_Fill_BW"
+ },
+ {
+ "BriefDescription": "Average per-core data access bandwidth to the L3 cache [GB / sec]",
+ "MetricExpr": "64 * OFFCORE_REQUESTS.ALL_REQUESTS / 1000000000 / duration_time",
+ "MetricGroup": "MemoryBW;Offcore",
+ "MetricName": "L3_Cache_Access_BW"
+ },
+ {
+ "BriefDescription": "L1 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L1_MISS / INST_RETIRED.ANY",
+ "MetricGroup": "CacheMisses",
+ "MetricName": "L1MPKI"
+ },
+ {
+ "BriefDescription": "L2 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L2_MISS / INST_RETIRED.ANY",
+ "MetricGroup": "CacheMisses",
+ "MetricName": "L2MPKI"
+ },
+ {
+ "BriefDescription": "L2 cache misses per kilo instruction for all request types (including speculative)",
+ "MetricExpr": "1000 * ( ( OFFCORE_REQUESTS.ALL_DATA_RD - OFFCORE_REQUESTS.DEMAND_DATA_RD ) + L2_RQSTS.ALL_DEMAND_MISS + L2_RQSTS.SWPF_MISS ) / INST_RETIRED.ANY",
+ "MetricGroup": "CacheMisses;Offcore",
+ "MetricName": "L2MPKI_All"
+ },
+ {
+ "BriefDescription": "L3 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L3_MISS / INST_RETIRED.ANY",
+ "MetricGroup": "CacheMisses",
+ "MetricName": "L3MPKI"
+ },
+ {
+ "BriefDescription": "Rate of silent evictions from the L2 cache per Kilo instruction where the evicted lines are dropped (no writeback to L3 or memory)",
+ "MetricExpr": "1000 * L2_LINES_OUT.SILENT / INST_RETIRED.ANY",
+ "MetricGroup": "L2Evicts;Server",
+ "MetricName": "L2_Evictions_Silent_PKI"
+ },
+ {
+ "BriefDescription": "Rate of non silent evictions from the L2 cache per Kilo instruction",
+ "MetricExpr": "1000 * L2_LINES_OUT.NON_SILENT / INST_RETIRED.ANY",
+ "MetricGroup": "L2Evicts;Server",
+ "MetricName": "L2_Evictions_NonSilent_PKI"
+ },
+ {
+ "BriefDescription": "Average CPU Utilization",
+ "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
+ "MetricGroup": "HPC;Summary",
+ "MetricName": "CPU_Utilization"
+ },
+ {
+ "BriefDescription": "Measured Average Frequency for unhalted processors [GHz]",
+ "MetricExpr": "(CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 / duration_time",
+ "MetricGroup": "Summary;Power",
+ "MetricName": "Average_Frequency"
+ },
+ {
+ "BriefDescription": "Giga Floating Point Operations Per Second",
+ "MetricExpr": "( ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / 1000000000 ) / duration_time",
+ "MetricGroup": "Flops;HPC",
+ "MetricName": "GFLOPs"
+ },
+ {
+ "BriefDescription": "Average Frequency Utilization relative nominal frequency",
+ "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
+ "MetricGroup": "Power",
+ "MetricName": "Turbo_Utilization"
+ },
+ {
+ "BriefDescription": "Fraction of cycles where both hardware Logical Processors were active",
+ "MetricExpr": "1 - CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_DISTRIBUTED if #SMT_on else 0",
+ "MetricGroup": "SMT",
+ "MetricName": "SMT_2T_Utilization"
+ },
+ {
+ "BriefDescription": "Fraction of cycles spent in the Operating System (OS) Kernel mode",
+ "MetricExpr": "CPU_CLK_UNHALTED.THREAD_P:k / CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "OS",
+ "MetricName": "Kernel_Utilization"
+ },
+ {
+ "BriefDescription": "Average external Memory Bandwidth Use for reads and writes [GB / sec]",
+ "MetricExpr": "( 64 * ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) / 1000000000 ) / duration_time",
+ "MetricGroup": "HPC;MemoryBW;SoC",
+ "MetricName": "DRAM_BW_Use"
+ },
+ {
+ "BriefDescription": "Average latency of data read request to external memory (in nanoseconds). Accounts for demand loads and L1/L2 prefetches",
+ "MetricExpr": "1000000000 * ( UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD / UNC_CHA_TOR_INSERTS.IA_MISS_DRD ) / ( cha_0@event\\=0x0@ / duration_time )",
+ "MetricGroup": "MemoryLat;SoC",
+ "MetricName": "MEM_Read_Latency"
+ },
+ {
+ "BriefDescription": "Average number of parallel data read requests to external memory. Accounts for demand loads and L1/L2 prefetches",
+ "MetricExpr": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD / cha@event\\=0x36\\,umask\\=0xC817FE01\\,thresh\\=1@",
+ "MetricGroup": "MemoryBW;SoC",
+ "MetricName": "MEM_Parallel_Reads"
+ },
+ {
+ "BriefDescription": "Average latency of data read request to external 3D X-Point memory [in nanoseconds]. Accounts for demand loads and L1/L2 data-read prefetches",
+ "MetricExpr": "( 1000000000 * ( UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PMM / UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PMM ) / cha_0@event\\=0x0@ )",
+ "MetricGroup": "MemoryLat;SoC;Server",
+ "MetricName": "MEM_PMM_Read_Latency"
+ },
+ {
+ "BriefDescription": "Average 3DXP Memory Bandwidth Use for reads [GB / sec]",
+ "MetricExpr": "( ( 64 * imc@event\\=0xe3@ / 1000000000 ) / duration_time )",
+ "MetricGroup": "MemoryBW;SoC;Server",
+ "MetricName": "PMM_Read_BW"
+ },
+ {
+ "BriefDescription": "Average 3DXP Memory Bandwidth Use for Writes [GB / sec]",
+ "MetricExpr": "( ( 64 * imc@event\\=0xe7@ / 1000000000 ) / duration_time )",
+ "MetricGroup": "MemoryBW;SoC;Server",
+ "MetricName": "PMM_Write_BW"
+ },
+ {
+ "BriefDescription": "Average IO (network or disk) Bandwidth Use for Writes [GB / sec]",
+ "MetricExpr": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR * 64 / 1000000000 / duration_time",
+ "MetricGroup": "IoBW;SoC;Server",
+ "MetricName": "IO_Write_BW"
+ },
+ {
+ "BriefDescription": "Average IO (network or disk) Bandwidth Use for Reads [GB / sec]",
+ "MetricExpr": "( UNC_CHA_TOR_INSERTS.IO_HIT_ITOM + UNC_CHA_TOR_INSERTS.IO_MISS_ITOM + UNC_CHA_TOR_INSERTS.IO_HIT_ITOMCACHENEAR + UNC_CHA_TOR_INSERTS.IO_MISS_ITOMCACHENEAR ) * 64 / 1000000000 / duration_time",
+ "MetricGroup": "IoBW;SoC;Server",
+ "MetricName": "IO_Read_BW"
+ },
+ {
+ "BriefDescription": "Socket actual clocks when any core is active on that socket",
+ "MetricExpr": "cha_0@event\\=0x0@",
+ "MetricGroup": "SoC",
+ "MetricName": "Socket_CLKS"
+ },
+ {
+ "BriefDescription": "Instructions per Far Branch ( Far Branches apply upon transition from application to operating system, handling interrupts, exceptions) [lower number means higher occurrence rate]",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.FAR_BRANCH:u",
+ "MetricGroup": "Branches;OS",
+ "MetricName": "IpFarBranch"
+ },
+ {
+ "BriefDescription": "C1 residency percent per core",
+ "MetricExpr": "(cstate_core@c1\\-residency@ / msr@tsc@) * 100",
+ "MetricGroup": "Power",
+ "MetricName": "C1_Core_Residency"
+ },
+ {
+ "BriefDescription": "C6 residency percent per core",
+ "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
+ "MetricGroup": "Power",
+ "MetricName": "C6_Core_Residency"
+ },
+ {
+ "BriefDescription": "C2 residency percent per package",
+ "MetricExpr": "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100",
+ "MetricGroup": "Power",
+ "MetricName": "C2_Pkg_Residency"
+ },
+ {
+ "BriefDescription": "C6 residency percent per package",
+ "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
+ "MetricGroup": "Power",
+ "MetricName": "C6_Pkg_Residency"
+ },
+]
diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
index 5f5df6560202..0cf2d1fa6b76 100644
--- a/tools/perf/pmu-events/arch/x86/mapfile.csv
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -36,11 +36,12 @@ GenuineIntel-6-55-[01234],v1,skylakex,core
GenuineIntel-6-55-[56789ABCDEF],v1,cascadelakex,core
GenuineIntel-6-7D,v1,icelake,core
GenuineIntel-6-7E,v1,icelake,core
-GenuineIntel-6-8[CD],v1,icelake,core
+GenuineIntel-6-8[CD],v1,tigerlake,core
GenuineIntel-6-A7,v1,icelake,core
GenuineIntel-6-6A,v1,icelakex,core
GenuineIntel-6-6C,v1,icelakex,core
GenuineIntel-6-86,v1,tremontx,core
+GenuineIntel-6-96,v1,elkhartlake,core
AuthenticAMD-23-([12][0-9A-F]|[0-9A-F]),v2,amdzen1,core
AuthenticAMD-23-[[:xdigit:]]+,v1,amdzen2,core
AuthenticAMD-25-[[:xdigit:]]+,v1,amdzen3,core
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/cache.json b/tools/perf/pmu-events/arch/x86/skylakex/cache.json
index e750a21976f1..9ff67206ade4 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/cache.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/cache.json
@@ -1,49 +1,123 @@
[
{
- "BriefDescription": "Counts all demand code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "L1D data line replacements",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0004",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x51",
+ "EventName": "L1D.REPLACEMENT",
+ "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "BriefDescription": "Number of times a request needed a FB entry but there was no entry available for it. That is the FB unavailability was dominant reason for blocking the request. A request includes cacheable/uncacheable demands that is load, store or SW prefetch.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
- "PublicDescription": "Counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
- "SampleAfterValue": "100003",
- "UMask": "0x4"
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "PublicDescription": "Number of times a request needed a FB (Fill Buffer) entry but there was no entry available for it. A request includes cacheable/uncacheable demands that are load, store or SW prefetch instructions.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Counts all demand code reads that have any response type.",
+ "BriefDescription": "L1D miss outstandings duration in cycles",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010004",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "PublicDescription": "Counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch.Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "PublicDescription": "Counts duration of L1D miss outstanding in cycles.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "AnyThread": "1",
+ "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "L2 cache lines filling L2",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF1",
+ "EventName": "L2_LINES_IN.ALL",
+ "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
"SampleAfterValue": "100003",
+ "UMask": "0x1f"
+ },
+ {
+ "BriefDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF2",
+ "EventName": "L2_LINES_OUT.NON_SILENT",
+ "PublicDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts the number of lines that are silently dropped by L2 cache when triggered by an L2 cache fill. These lines are typically in Shared state. A non-threaded event.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF2",
+ "EventName": "L2_LINES_OUT.SILENT",
+ "SampleAfterValue": "200003",
"UMask": "0x1"
},
{
- "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache",
+ "BriefDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF2",
+ "EventName": "L2_LINES_OUT.USELESS_HWPF",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "This event is deprecated. Refer to new event L2_LINES_OUT.USELESS_HWPF",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Deprecated": "1",
+ "EventCode": "0xF2",
+ "EventName": "L2_LINES_OUT.USELESS_PREF",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "L2 code requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
- "EventName": "L2_RQSTS.PF_MISS",
- "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache.",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "PublicDescription": "Counts the total number of L2 code requests.",
"SampleAfterValue": "200003",
- "UMask": "0x38"
+ "UMask": "0xe4"
+ },
+ {
+ "BriefDescription": "Demand Data Read requests",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
+ "PublicDescription": "Counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe1"
},
{
"BriefDescription": "Demand requests that miss L2 cache",
@@ -56,157 +130,144 @@
"UMask": "0x27"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Demand requests to L2 cache",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0002",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
+ "PublicDescription": "Demand requests to L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe7"
},
{
- "BriefDescription": "Retired load instructions with L3 cache hits as data sources",
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L3_HIT",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L3 cache.",
- "SampleAfterValue": "50021",
- "UMask": "0x4"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_PF",
+ "PublicDescription": "Counts the total number of requests from the L2 hardware prefetchers.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xf8"
},
{
- "BriefDescription": "L2 writebacks that access L2 cache",
+ "BriefDescription": "RFO requests to L2 cache",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF0",
- "EventName": "L2_TRANS.L2_WB",
- "PublicDescription": "Counts L2 writebacks that access L2 cache.",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
"SampleAfterValue": "200003",
- "UMask": "0x40"
+ "UMask": "0xe2"
},
{
- "BriefDescription": "L2 cache lines filling L2",
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF1",
- "EventName": "L2_LINES_IN.ALL",
- "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
- "SampleAfterValue": "100003",
- "UMask": "0x1f"
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc4"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "L2 cache misses when fetching instructions",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0400",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "PublicDescription": "Counts L2 cache misses when fetching instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x24"
},
{
- "BriefDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Demand Data Read requests that hit L2 cache",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0001",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
+ "PublicDescription": "Counts the number of demand Data Read requests, initiated by load instructions, that hit L2 cache",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3.",
+ "BriefDescription": "Demand Data Read miss L2, no rejects",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0100",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
+ "PublicDescription": "Counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x21"
},
{
- "BriefDescription": "Demand Data Read requests sent to uncore",
+ "BriefDescription": "All requests that miss L2 cache",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
- "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.MISS",
+ "PublicDescription": "All requests that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x3f"
},
{
- "BriefDescription": "Retired load instructions missed L3 cache as data sources",
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L3_MISS",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache.",
- "SampleAfterValue": "100007",
- "UMask": "0x20"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.PF_HIT",
+ "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xd8"
},
{
- "BriefDescription": "All retired store instructions.",
+ "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.ALL_STORES",
- "L1_Hit_Indication": "1",
- "PEBS": "1",
- "SampleAfterValue": "2000003",
- "UMask": "0x82"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.PF_MISS",
+ "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x38"
},
{
- "BriefDescription": "Counts the number of lines that are silently dropped by L2 cache when triggered by an L2 cache fill. These lines are typically in Shared state. A non-threaded event.",
+ "BriefDescription": "All L2 requests",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF2",
- "EventName": "L2_LINES_OUT.SILENT",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.REFERENCES",
+ "PublicDescription": "All L2 requests.",
"SampleAfterValue": "200003",
- "UMask": "0x1"
+ "UMask": "0xff"
},
{
- "BriefDescription": "Counts all prefetch data reads that hit in the L3.",
+ "BriefDescription": "RFO requests that hit L2 cache",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0490",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc2"
},
{
- "BriefDescription": "Counts all prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "RFO requests that miss L2 cache",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0490",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x22"
+ },
+ {
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF0",
+ "EventName": "L2_TRANS.L2_WB",
+ "PublicDescription": "Counts L2 writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x40"
},
{
"BriefDescription": "Core-originated cacheable demand requests missed L3",
@@ -220,223 +281,225 @@
"UMask": "0x41"
},
{
- "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches",
+ "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_PF",
- "PublicDescription": "Counts the total number of requests from the L2 hardware prefetchers.",
- "SampleAfterValue": "200003",
- "UMask": "0xf8"
+ "Errata": "SKL057",
+ "EventCode": "0x2E",
+ "EventName": "LONGEST_LAT_CACHE.REFERENCE",
+ "PublicDescription": "Counts core-originated cacheable requests to the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches from L1 and L2. It does not include all accesses to the L3.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4f"
},
{
- "BriefDescription": "Retired load instructions whose data sources was remote HITM",
+ "BriefDescription": "All retired load instructions.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Data_LA": "1",
- "EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_HITM",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.ALL_LOADS",
"PEBS": "1",
- "PublicDescription": "Retired load instructions whose data sources was remote HITM.",
- "SampleAfterValue": "100007",
- "UMask": "0x4"
+ "SampleAfterValue": "2000003",
+ "UMask": "0x81"
},
{
- "BriefDescription": "Counts all prefetch data reads that have any response type.",
+ "BriefDescription": "All retired store instructions.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.ANY_RESPONSE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010490",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.ALL_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x82"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Retired load instructions with locked access.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0122",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.LOCK_LOADS",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "UMask": "0x21"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Retired load instructions that split across a cacheline boundary.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0100",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.SPLIT_LOADS",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.",
"SampleAfterValue": "100003",
- "UMask": "0x1"
+ "UMask": "0x41"
},
{
- "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "BriefDescription": "Retired store instructions that split across a cacheline boundary.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
- "PublicDescription": "Counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.SPLIT_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x42"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Retired load instructions that miss the STLB.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0491",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
+ "PEBS": "1",
"SampleAfterValue": "100003",
- "UMask": "0x1"
+ "UMask": "0x11"
},
{
- "BriefDescription": "RFO requests that miss L2 cache",
+ "BriefDescription": "Retired store instructions that miss the STLB.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.RFO_MISS",
- "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0x22"
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD0",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "SampleAfterValue": "100003",
+ "UMask": "0x12"
},
{
- "BriefDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped",
+ "BriefDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF2",
- "EventName": "L2_LINES_OUT.NON_SILENT",
- "PublicDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines can be either in modified state or clean state. Modified lines may either be written back to L3 or directly written to memory and not allocated in L3. Clean lines may either be allocated in L3 or dropped.",
- "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
+ "SampleAfterValue": "20011",
"UMask": "0x2"
},
{
- "BriefDescription": "Counts the number of lines that have been hardware prefetched but not used and now evicted by L2 cache",
+ "BriefDescription": "Retired load instructions which data sources were HitM responses from shared L3",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF2",
- "EventName": "L2_LINES_OUT.USELESS_HWPF",
- "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were HitM responses from shared L3.",
+ "SampleAfterValue": "20011",
"UMask": "0x4"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) that have any response type.",
+ "BriefDescription": "Retired load instructions which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010002",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "Data_LA": "1",
+ "EventCode": "0xD2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS",
+ "PEBS": "1",
+ "SampleAfterValue": "20011",
"UMask": "0x1"
},
{
- "BriefDescription": "All requests that miss L2 cache",
+ "BriefDescription": "Retired load instructions which data sources were hits in L3 without snoops required",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.MISS",
- "PublicDescription": "All requests that miss L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0x3f"
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources were hits in L3 without snoops required.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "L2 code requests",
+ "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from local dram",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_CODE_RD",
- "PublicDescription": "Counts the total number of L2 code requests.",
- "SampleAfterValue": "200003",
- "UMask": "0xe4"
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD3",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.LOCAL_DRAM",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions which data sources missed L3 but serviced from local DRAM.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions whose data sources was forwarded from a remote cache",
+ "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from remote dram",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Data_LA": "1",
"EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_FWD",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_DRAM",
"PEBS": "1",
- "PublicDescription": "Retired load instructions whose data sources was forwarded from a remote cache.",
"SampleAfterValue": "100007",
- "UMask": "0x8"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Retired load instructions whose data sources was forwarded from a remote cache",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0020",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "Data_LA": "1",
+ "EventCode": "0xD3",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_FWD",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions whose data sources was forwarded from a remote cache.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that have any response type.",
+ "BriefDescription": "Retired load instructions whose data sources was remote HITM",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010491",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "Data_LA": "1",
+ "EventCode": "0xD3",
+ "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_HITM",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions whose data sources was remote HITM.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x4"
},
{
- "BriefDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache",
+ "BriefDescription": "Retired instructions with at least 1 uncacheable load or lock.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Data_LA": "1",
- "EventCode": "0xD2",
- "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT",
+ "EventCode": "0xD4",
+ "EventName": "MEM_LOAD_MISC_RETIRED.UC",
"PEBS": "1",
- "PublicDescription": "Retired load instructions which data sources were L3 and cross-core snoop hits in on-pkg core cache.",
- "SampleAfterValue": "20011",
- "UMask": "0x2"
+ "SampleAfterValue": "100007",
+ "UMask": "0x4"
},
{
- "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from remote dram",
+ "BriefDescription": "Retired load instructions which data sources were load missed L1 but hit FB due to preceding miss to the same cache line with data not ready",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"Data_LA": "1",
- "EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_DRAM",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.FB_HIT",
"PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready.",
"SampleAfterValue": "100007",
- "UMask": "0x2"
+ "UMask": "0x40"
},
{
- "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "Retired load instructions with L1 cache hits as data sources",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0122",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L1_HIT",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
@@ -452,104 +515,135 @@
"UMask": "0x8"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "Retired load instructions with L2 cache hits as data sources",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0020",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions with L2 cache hits as data sources.",
"SampleAfterValue": "100003",
- "UMask": "0x1"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Retired load instructions missed L2 cache as data sources",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0400",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L2_MISS",
+ "PEBS": "1",
+ "PublicDescription": "Retired load instructions missed L2 cache as data sources.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x10"
},
{
- "BriefDescription": "L2 cache misses when fetching instructions",
+ "BriefDescription": "Retired load instructions with L3 cache hits as data sources",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.CODE_RD_MISS",
- "PublicDescription": "Counts L2 cache misses when fetching instructions.",
- "SampleAfterValue": "200003",
- "UMask": "0x24"
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L3_HIT",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L3 cache.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x4"
},
{
- "BriefDescription": "Counts all prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Retired load instructions missed L3 cache as data sources",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0490",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xD1",
+ "EventName": "MEM_LOAD_RETIRED.L3_MISS",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Demand and prefetch data reads",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
"SampleAfterValue": "100003",
- "UMask": "0x1"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "BriefDescription": "Any memory transaction that reached the SQ.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
- "PublicDescription": "Counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.Note: A prefetch promoted to Demand is counted from the promotion point.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS",
+ "PublicDescription": "Counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, etc..",
+ "SampleAfterValue": "100003",
+ "UMask": "0x80"
},
{
- "BriefDescription": "Counts demand data reads that hit in the L3.",
+ "BriefDescription": "Cacheable and noncachaeble code read requests",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0001",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
+ "PublicDescription": "Counts both cacheable and non-cacheable code read requests.",
"SampleAfterValue": "100003",
- "UMask": "0x1"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Counts prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "Demand Data Read requests sent to uncore",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0120",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0120",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "PublicDescription": "Counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
"SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB2",
+ "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
+ "PublicDescription": "Counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.Note: Writeback pending FIFO has six entries.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "PublicDescription": "Counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "PublicDescription": "Counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
"BriefDescription": "Cycles with offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -561,212 +655,257 @@
"UMask": "0x2"
},
{
- "BriefDescription": "Demand requests to L2 cache",
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES",
- "PublicDescription": "Demand requests to L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0xe7"
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "PublicDescription": "Counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3.",
+ "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "PublicDescription": "Counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore, every cycle.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
+ "PublicDescription": "Counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "PublicDescription": "Counts the number of offcore outstanding Demand Data Read transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor. See the corresponding Umask under OFFCORE_REQUESTS.Note: A prefetch promoted to Demand is counted from the promotion point.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "6",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore, every cycle",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "PublicDescription": "Counts the number of offcore outstanding RFO (store) transactions in the super queue (SQ) every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0080",
- "Offcore": "1",
+ "EventName": "OFFCORE_RESPONSE",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts all demand & prefetch data reads that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0491",
+ "MSRValue": "0x0000010491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that have any response type.",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010020",
+ "MSRValue": "0x3F803C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3.",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0122",
+ "MSRValue": "0x10003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0001",
+ "MSRValue": "0x04003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0080",
+ "MSRValue": "0x01003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "AnyThread": "1",
- "BriefDescription": "Cycles with L1D load Misses outstanding from any thread on physical core.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x48",
- "EventName": "L1D_PEND_MISS.PENDING_CYCLES_ANY",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Counts all prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0490",
+ "MSRValue": "0x08003C0491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core-originated cacheable demand requests that refer to L3",
+ "BriefDescription": "Counts all prefetch data reads that have any response type.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL057",
- "EventCode": "0x2E",
- "EventName": "LONGEST_LAT_CACHE.REFERENCE",
- "PublicDescription": "Counts core-originated cacheable requests to the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches from L1 and L2. It does not include all accesses to the L3.",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0000010490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x4f"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that have any response type.",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010080",
+ "MSRValue": "0x3F803C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0120",
+ "MSRValue": "0x10003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3.",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0491",
+ "MSRValue": "0x04003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions that miss the STLB.",
+ "BriefDescription": "Counts all prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
- "PEBS": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x01003C0490",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x11"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads that have any response type.",
+ "BriefDescription": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010001",
+ "MSRValue": "0x08003C0490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3.",
+ "BriefDescription": "Counts prefetch RFOs that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0020",
+ "MSRValue": "0x0000010120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "L1D data line replacements",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x51",
- "EventName": "L1D.REPLACEMENT",
- "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3F803C0120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
@@ -783,47 +922,43 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions with at least 1 uncacheable load or lock.",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD4",
- "EventName": "MEM_LOAD_MISC_RETIRED.UC",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "UMask": "0x4"
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x04003C0120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources were load missed L1 but hit FB due to preceding miss to the same cache line with data not ready",
+ "BriefDescription": "Counts prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.FB_HIT",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready.",
- "SampleAfterValue": "100007",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "This event is deprecated. Refer to new event L2_LINES_OUT.USELESS_HWPF",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Deprecated": "1",
- "EventCode": "0xF2",
- "EventName": "L2_LINES_OUT.USELESS_PREF",
- "SampleAfterValue": "200003",
- "UMask": "0x4"
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x01003C0120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache",
+ "BriefDescription": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.PF_HIT",
- "PublicDescription": "Counts requests from the L1/L2/L3 hardware prefetchers or Load software prefetches that hit L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0xd8"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x08003C0120",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
"BriefDescription": "Counts all demand & prefetch RFOs that have any response type.",
@@ -839,14 +974,17 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read miss L2, no rejects",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
- "PublicDescription": "Counts the number of demand Data Read requests that miss L2 cache. Only not rejected loads are counted.",
- "SampleAfterValue": "200003",
- "UMask": "0x21"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3F803C0122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
"BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
@@ -862,293 +1000,247 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that have any response type.",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010100",
+ "MSRValue": "0x04003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources were hits in L3 without snoops required",
+ "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD2",
- "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions which data sources were hits in L3 without snoops required.",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x01003C0122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x8"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0080",
+ "MSRValue": "0x08003C0122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "Counts all demand code reads that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0491",
+ "MSRValue": "0x0000010004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "All retired load instructions.",
+ "BriefDescription": "Counts all demand code reads that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.ALL_LOADS",
- "PEBS": "1",
- "SampleAfterValue": "2000003",
- "UMask": "0x81"
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3F803C0004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions which data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD2",
- "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS",
- "PEBS": "1",
- "SampleAfterValue": "20011",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x10003C0004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read requests",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD",
- "PublicDescription": "Counts the number of demand Data Read requests (including requests from L1D hardware prefetchers). These loads may hit or miss L2 cache. Only non rejected loads are counted.",
- "SampleAfterValue": "200003",
- "UMask": "0xe1"
- },
- {
- "BriefDescription": "All L2 requests",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.REFERENCES",
- "PublicDescription": "All L2 requests.",
- "SampleAfterValue": "200003",
- "UMask": "0xff"
- },
- {
- "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x48",
- "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
- "PublicDescription": "Counts duration of L1D miss outstanding in cycles.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x04003C0004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
- "PublicDescription": "Counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "Counts all demand code reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0100",
+ "MSRValue": "0x01003C0004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of cache line split locks sent to uncore.",
+ "BriefDescription": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xF4",
- "EventName": "SQ_MISC.SPLIT_LOCK",
- "PublicDescription": "Counts the number of cache line split locks sent to the uncore.",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x08003C0004",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x10"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3.",
+ "BriefDescription": "Counts demand data reads that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0002",
+ "MSRValue": "0x0000010001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts demand data reads that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0100",
+ "MSRValue": "0x3F803C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.CODE_RD_HIT",
- "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.",
- "SampleAfterValue": "200003",
- "UMask": "0xc4"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3.",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0400",
+ "MSRValue": "0x10003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that have any response type.",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010010",
+ "MSRValue": "0x04003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions with L2 cache hits as data sources",
+ "BriefDescription": "Counts demand data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L2_HIT",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions with L2 cache hits as data sources.",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x01003C0001",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "RFO requests that hit L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.RFO_HIT",
- "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.",
- "SampleAfterValue": "200003",
- "UMask": "0xc2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0080",
+ "MSRValue": "0x08003C0001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "L1D miss outstandings duration in cycles",
+ "BriefDescription": "Counts all demand data writes (RFOs) that have any response type.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x48",
- "EventName": "L1D_PEND_MISS.PENDING",
- "PublicDescription": "Counts duration of L1D miss outstanding, that is each cycle number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch.Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0000010002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0491",
+ "MSRValue": "0x3F803C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read requests that hit L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT",
- "PublicDescription": "Counts the number of demand Data Read requests, initiated by load instructions, that hit L2 cache",
- "SampleAfterValue": "200003",
- "UMask": "0xc1"
- },
- {
- "BriefDescription": "Retired load instructions which data sources were HitM responses from shared L3",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD2",
- "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions which data sources were HitM responses from shared L3.",
- "SampleAfterValue": "20011",
- "UMask": "0x4"
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x10003C0002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0001",
+ "MSRValue": "0x04003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -1168,508 +1260,416 @@
"UMask": "0x1"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0080",
+ "MSRValue": "0x08003C0002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0010",
+ "MSRValue": "0x0000010400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired store instructions that split across a cacheline boundary.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.SPLIT_STORES",
- "L1_Hit_Indication": "1",
- "PEBS": "1",
- "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3F803C0400",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x42"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0010",
+ "MSRValue": "0x10003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Any memory transaction that reached the SQ.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS",
- "PublicDescription": "Counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, etc..",
- "SampleAfterValue": "100003",
- "UMask": "0x80"
- },
- {
- "BriefDescription": "Cacheable and noncachaeble code read requests",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD",
- "PublicDescription": "Counts both cacheable and non-cacheable code read requests.",
- "SampleAfterValue": "100003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0100",
+ "MSRValue": "0x04003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0004",
+ "MSRValue": "0x01003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
- "PublicDescription": "Counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that have any response type.",
+ "BriefDescription": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010400",
+ "MSRValue": "0x08003C0400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0004",
+ "MSRValue": "0x0000010010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0004",
+ "MSRValue": "0x3F803C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times a request needed a FB entry but there was no entry available for it. That is the FB unavailability was dominant reason for blocking the request. A request includes cacheable/uncacheable demands that is load, store or SW prefetch.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x48",
- "EventName": "L1D_PEND_MISS.FB_FULL",
- "PublicDescription": "Number of times a request needed a FB (Fill Buffer) entry but there was no entry available for it. A request includes cacheable/uncacheable demands that are load, store or SW prefetch instructions.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0020",
+ "MSRValue": "0x10003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads that hit in the L3.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0004",
+ "MSRValue": "0x04003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch RFOs that hit in the L3.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0120",
+ "MSRValue": "0x01003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0020",
+ "MSRValue": "0x08003C0010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0400",
+ "MSRValue": "0x0000010020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions with L1 cache hits as data sources",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L1_HIT",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.",
- "SampleAfterValue": "2000003",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3F803C0020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
- "PublicDescription": "Counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0490",
+ "MSRValue": "0x10003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions with locked access.",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.LOCK_LOADS",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "UMask": "0x21"
- },
- {
- "BriefDescription": "Demand and prefetch data reads",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
- "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x04003C0020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from local dram",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD3",
- "EventName": "MEM_LOAD_L3_MISS_RETIRED.LOCAL_DRAM",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions which data sources missed L3 but serviced from local DRAM.",
- "SampleAfterValue": "100007",
"UMask": "0x1"
},
{
- "BriefDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.NO_SNOOP_NEEDED",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x01003C0020",
+ "Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0400",
+ "MSRValue": "0x08003C0020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions that split across a cacheline boundary.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.SPLIT_LOADS",
- "PEBS": "1",
- "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0000010080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x41"
- },
- {
- "BriefDescription": "Offcore requests buffer cannot take more entries for this thread core.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB2",
- "EventName": "OFFCORE_REQUESTS_BUFFER.SQ_FULL",
- "PublicDescription": "Counts the number of cases when the offcore requests buffer cannot take more entries for the core. This can happen when the superqueue does not contain eligible entries, or when L1D writeback pending FIFO requests is full.Note: Writeback pending FIFO has six entries.",
- "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "6",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3F803C0080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Offcore outstanding Code Reads transactions in the SuperQueue (SQ), queue to uncore, every cycle.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD",
- "PublicDescription": "Counts the number of offcore outstanding Code Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0002",
+ "MSRValue": "0x10003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3F803C0010",
+ "MSRValue": "0x04003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch RFOs that have any response type.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.ANY_RESPONSE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0000010120",
+ "MSRValue": "0x01003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_HIT.HITM_OTHER_CORE",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x10003C0002",
+ "MSRValue": "0x08003C0080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired store instructions that miss the STLB.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that have any response type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD0",
- "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
- "L1_Hit_Indication": "1",
- "PEBS": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0000010100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x12"
- },
- {
- "BriefDescription": "RFO requests to L2 cache",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x24",
- "EventName": "L2_RQSTS.ALL_RFO",
- "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
- "SampleAfterValue": "200003",
- "UMask": "0xe2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x08003C0010",
+ "MSRValue": "0x3F803C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HITM_OTHER_CORE",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0010",
+ "MSRValue": "0x10003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired load instructions missed L2 cache as data sources",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xD1",
- "EventName": "MEM_LOAD_RETIRED.L2_MISS",
- "PEBS": "1",
- "PublicDescription": "Retired load instructions missed L2 cache as data sources.",
- "SampleAfterValue": "50021",
- "UMask": "0x10"
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x04003C0100",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that hit in the L3 and sibling core snoops are not needed as either the core-valid bit is not set or the shared line is present in multiple cores.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_HIT.NO_SNOOP_NEEDED",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.NO_SNOOP_NEEDED",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x01003C0001",
+ "MSRValue": "0x01003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
- "PublicDescription": "Counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Counts all demand & prefetch RFOs that hit in the L3 and the snoop to one of the sibling cores hits the line in M state and the line is forwarded.",
+ "BriefDescription": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_HIT.HIT_OTHER_CORE_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_HIT.SNOOP_HIT_WITH_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x04003C0122",
+ "MSRValue": "0x08003C0100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of cache line split locks sent to uncore.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xF4",
+ "EventName": "SQ_MISC.SPLIT_LOCK",
+ "PublicDescription": "Counts the number of cache line split locks sent to the uncore.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json b/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json
index e197cde15047..503737ed3a83 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/floating-point.json
@@ -9,22 +9,13 @@
"UMask": "0x4"
},
{
- "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 8 calculations per element.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
- "SampleAfterValue": "2000003",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x8"
},
{
"BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
@@ -36,33 +27,31 @@
"UMask": "0x10"
},
{
- "BriefDescription": "Number of SSE/AVX computational 512-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 16 calculations per element.",
+ "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
"SampleAfterValue": "2000003",
- "UMask": "0x80"
+ "UMask": "0x20"
},
{
- "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "BriefDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 8 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
"SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "UMask": "0x40"
},
{
- "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "BriefDescription": "Number of SSE/AVX computational 512-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 16 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xCA",
- "EventName": "FP_ASSIST.ANY",
- "PublicDescription": "Counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
- "SampleAfterValue": "100003",
- "UMask": "0x1e"
+ "EventCode": "0xC7",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
},
{
"BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
@@ -74,12 +63,23 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
- "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
"SampleAfterValue": "2000003",
- "UMask": "0x8"
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles with any input/output SSE or FP assist",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0xCA",
+ "EventName": "FP_ASSIST.ANY",
+ "PublicDescription": "Counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1e"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/frontend.json b/tools/perf/pmu-events/arch/x86/skylakex/frontend.json
index cdf95bd2a73d..078706a50091 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/frontend.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/frontend.json
@@ -1,13 +1,47 @@
[
{
- "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache miss.",
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x80",
- "EventName": "ICACHE_16B.IFDATA_STALL",
- "PublicDescription": "Cycles where a code line fetch is stalled due to an L1 instruction cache miss. The legacy decode pipeline works at a 16 Byte granularity.",
+ "EventCode": "0xE6",
+ "EventName": "BACLEARS.ANY",
+ "PublicDescription": "Counts the number of times the front-end is resteered when it finds a branch instruction in a fetch line. This occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switches",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xAB",
+ "EventName": "DSB2MITE_SWITCHES.COUNT",
+ "PublicDescription": "This event counts the number of the Decode Stream Buffer (DSB)-to-MITE switches including all misses because of missing Decode Stream Buffer (DSB) cache and u-arch forced misses.\nNote: Invoking MITE requires two or three cycles delay.",
"SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xAB",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "PublicDescription": "Counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. MM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.Penalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 02 cycles.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Retired Instructions who experienced decode stream buffer (DSB - the decoded instruction-cache) miss.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.DSB_MISS",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x11",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
},
{
"BriefDescription": "Retired Instructions who experienced iTLB true miss.",
@@ -24,220 +58,246 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_128",
+ "EventName": "FRONTEND_RETIRED.L1I_MISS",
"MSRIndex": "0x3F7",
- "MSRValue": "0x408006",
+ "MSRValue": "0x12",
"PEBS": "1",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
- "PublicDescription": "Cycles with less than 3 uops delivered by the front-end.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.L2_MISS",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x13",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.DSB_CYCLES",
- "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "BriefDescription": "Retired instructions after front-end starvation of at least 1 cycle",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "3",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
- "PublicDescription": "Counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >= 3.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_1",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x400106",
+ "PEBS": "2",
+ "PublicDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of at least 1 cycle which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xE6",
- "EventName": "BACLEARS.ANY",
- "PublicDescription": "Counts the number of times the front-end is resteered when it finds a branch instruction in a fetch line. This occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_128",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x408006",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired Instructions who experienced decode stream buffer (DSB - the decoded instruction-cache) miss.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.DSB_MISS",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_16",
"MSRIndex": "0x3F7",
- "MSRValue": "0x11",
+ "MSRValue": "0x401006",
"PEBS": "1",
- "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 2 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
- "PublicDescription": "Counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x400206",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_16",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_256",
"MSRIndex": "0x3F7",
- "MSRValue": "0x401006",
+ "MSRValue": "0x410006",
"PEBS": "1",
- "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x79",
- "EventName": "IDQ.MITE_UOPS",
- "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x100206",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 2 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "2",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
- "PublicDescription": "Cycles with less than 2 uops delivered by the front-end.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_2",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x200206",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 3 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.MS_CYCLES",
- "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
- "SampleAfterValue": "2000003",
- "UMask": "0x30"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_3",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x300206",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles MITE is delivering any Uop",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
- "PublicDescription": "Counts the number of cycles uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. Counting includes uops that may 'bypass' the IDQ. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
- "SampleAfterValue": "2000003",
- "UMask": "0x24"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_32",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x402006",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x83",
- "EventName": "ICACHE_64B.IFTAG_HIT",
- "SampleAfterValue": "200003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_4",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x400406",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EdgeDetect": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.MS_SWITCHES",
- "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
- "SampleAfterValue": "2000003",
- "UMask": "0x30"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_512",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x420006",
+ "PEBS": "1",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.L2_MISS",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_64",
"MSRIndex": "0x3F7",
- "MSRValue": "0x13",
+ "MSRValue": "0x404006",
"PEBS": "1",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x79",
- "EventName": "IDQ.MITE_CYCLES",
- "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_8",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x400806",
+ "PEBS": "1",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_64",
+ "EventName": "FRONTEND_RETIRED.STLB_MISS",
"MSRIndex": "0x3F7",
- "MSRValue": "0x404006",
+ "MSRValue": "0x15",
"PEBS": "1",
+ "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss.",
"SampleAfterValue": "100007",
"TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache miss.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x9C",
- "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
- "PublicDescription": "Counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding 4 x when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when: a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread. b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions). c. Instruction Decode Queue (IDQ) delivers four uops.",
+ "EventCode": "0x80",
+ "EventName": "ICACHE_16B.IFDATA_STALL",
+ "PublicDescription": "Cycles where a code line fetch is stalled due to an L1 instruction cache miss. The legacy decode pipeline works at a 16 Byte granularity.",
"SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x83",
+ "EventName": "ICACHE_64B.IFTAG_HIT",
+ "SampleAfterValue": "200003",
"UMask": "0x1"
},
{
- "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x79",
- "EventName": "IDQ.MS_MITE_UOPS",
- "PublicDescription": "Counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "EventCode": "0x83",
+ "EventName": "ICACHE_64B.IFTAG_MISS",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
},
{
"BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss.",
@@ -249,14 +309,15 @@
"UMask": "0x4"
},
{
- "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles.",
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xAB",
- "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
- "PublicDescription": "Counts Decode Stream Buffer (DSB)-to-MITE switch true penalty cycles. These cycles do not include uops routed through because of the switch itself, for example, when Instruction Decode Queue (IDQ) pre-allocation is unavailable, or Instruction Decode Queue (IDQ) is full. SBD-to-MITE switch true penalty cycles happen after the merge mux (MM) receives Decode Stream Buffer (DSB) Sync-indication until receiving the first MITE uop. MM is placed before Instruction Decode Queue (IDQ) to merge uops being fed from the MITE and Decode Stream Buffer (DSB) paths. Decode Stream Buffer (DSB) inserts the Sync-indication whenever a Decode Stream Buffer (DSB)-to-MITE switch occurs.Penalty: A Decode Stream Buffer (DSB) hit followed by a Decode Stream Buffer (DSB) miss can cost up to six cycles in which no uops are delivered to the IDQ. Most often, such switches from the Decode Stream Buffer (DSB) to the legacy pipeline cost 02 cycles.",
+ "CounterMask": "4",
+ "EventCode": "0x79",
+ "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
+ "PublicDescription": "Counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Count includes uops that may 'bypass' the IDQ.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x18"
},
{
"BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
@@ -270,106 +331,79 @@
"UMask": "0x18"
},
{
- "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.",
+ "BriefDescription": "Cycles MITE is delivering 4 Uops",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.STLB_MISS",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x15",
- "PEBS": "1",
- "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "4",
+ "EventCode": "0x79",
+ "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
+ "PublicDescription": "Counts the number of cycles 4 uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. Counting includes uops that may 'bypass' the IDQ. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x24"
},
{
- "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "BriefDescription": "Cycles MITE is delivering any Uop",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
"EventCode": "0x79",
- "EventName": "IDQ.DSB_UOPS",
- "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "EventName": "IDQ.ALL_MITE_CYCLES_ANY_UOPS",
+ "PublicDescription": "Counts the number of cycles uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. Counting includes uops that may 'bypass' the IDQ. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
"SampleAfterValue": "2000003",
- "UMask": "0x8"
+ "UMask": "0x24"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from Decode Stream Buffer (DSB) path",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_512",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x420006",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.DSB_CYCLES",
+ "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_8",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x400806",
- "PEBS": "1",
- "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Retired instructions after front-end starvation of at least 1 cycle",
- "Counter": "0,1,2,3,4,5,6,7",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xc6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_1",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x400106",
- "PEBS": "2",
- "PublicDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of at least 1 cycle which was not interrupted by a back-end stall.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "EventCode": "0x79",
+ "EventName": "IDQ.DSB_UOPS",
+ "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Counting includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) from MITE path",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_2",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x400206",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MITE_CYCLES",
+ "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_4",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x400406",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MITE_UOPS",
+ "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. Counting includes uops that may 'bypass' the IDQ. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
},
{
- "BriefDescription": "Cycles MITE is delivering 4 Uops",
+ "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
+ "CounterMask": "1",
"EventCode": "0x79",
- "EventName": "IDQ.ALL_MITE_CYCLES_4_UOPS",
- "PublicDescription": "Counts the number of cycles 4 uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. Counting includes uops that may 'bypass' the IDQ. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "EventName": "IDQ.MS_CYCLES",
+ "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
"SampleAfterValue": "2000003",
- "UMask": "0x24"
+ "UMask": "0x30"
},
{
"BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
@@ -383,101 +417,56 @@
"UMask": "0x10"
},
{
- "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
+ "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x79",
- "EventName": "IDQ.MS_UOPS",
- "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS). Any instruction over 4 uops will be delivered by the MS. Some instructions such as transcendentals may additionally generate uops from the MS.",
+ "EventName": "IDQ.MS_MITE_UOPS",
+ "PublicDescription": "Counts the number of uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Counting includes uops that may 'bypass' the IDQ.",
"SampleAfterValue": "2000003",
- "UMask": "0x30"
- },
- {
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_256",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x410006",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 2 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_2",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x200206",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 3 bubble-slots for a period of 2 cycles which was not interrupted by a back-end stall.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_3",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x300206",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "UMask": "0x20"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x100206",
- "PEBS": "1",
- "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EdgeDetect": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MS_SWITCHES",
+ "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x30"
},
{
- "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering 4 Uops",
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
"EventCode": "0x79",
- "EventName": "IDQ.ALL_DSB_CYCLES_4_UOPS",
- "PublicDescription": "Counts the number of cycles 4 uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path. Count includes uops that may 'bypass' the IDQ.",
+ "EventName": "IDQ.MS_UOPS",
+ "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS). Any instruction over 4 uops will be delivered by the MS. Some instructions such as transcendentals may additionally generate uops from the MS.",
"SampleAfterValue": "2000003",
- "UMask": "0x18"
+ "UMask": "0x30"
},
{
- "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE switches",
+ "BriefDescription": "Uops not delivered to Resource Allocation Table (RAT) per thread when backend of the machine is not stalled",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xAB",
- "EventName": "DSB2MITE_SWITCHES.COUNT",
- "PublicDescription": "This event counts the number of the Decode Stream Buffer (DSB)-to-MITE switches including all misses because of missing Decode Stream Buffer (DSB) cache and u-arch forced misses.\nNote: Invoking MITE requires two or three cycles delay.",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "PublicDescription": "Counts the number of uops not delivered to Resource Allocation Table (RAT) per thread adding 4 x when Resource Allocation Table (RAT) is not stalled and Instruction Decode Queue (IDQ) delivers x uops to Resource Allocation Table (RAT) (where x belongs to {0,1,2,3}). Counting does not cover cases when: a. IDQ-Resource Allocation Table (RAT) pipe serves the other thread. b. Resource Allocation Table (RAT) is stalled for the thread (including uop drops and clear BE conditions). c. Instruction Decode Queue (IDQ) delivers four uops.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.",
+ "BriefDescription": "Cycles per thread when 4 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.LATENCY_GE_32",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x402006",
- "PEBS": "1",
- "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "4",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "PublicDescription": "Counts, on the per-thread basis, cycles when no uops are delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core =4.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
@@ -492,25 +481,36 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "BriefDescription": "Cycles per thread when 3 or more uops are not delivered to Resource Allocation Table (RAT) when backend of the machine is not stalled",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x83",
- "EventName": "ICACHE_64B.IFTAG_MISS",
- "SampleAfterValue": "200003",
- "UMask": "0x2"
+ "CounterMask": "3",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_1_UOP_DELIV.CORE",
+ "PublicDescription": "Counts, on the per-thread basis, cycles when less than 1 uop is delivered to Resource Allocation Table (RAT). IDQ_Uops_Not_Delivered.core >= 3.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.",
+ "BriefDescription": "Cycles with less than 2 uops delivered by the front end.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC6",
- "EventName": "FRONTEND_RETIRED.L1I_MISS",
- "MSRIndex": "0x3F7",
- "MSRValue": "0x12",
- "PEBS": "1",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "2",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_2_UOP_DELIV.CORE",
+ "PublicDescription": "Cycles with less than 2 uops delivered by the front-end.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles with less than 3 uops delivered by the front end.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x9C",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_LE_3_UOP_DELIV.CORE",
+ "PublicDescription": "Cycles with less than 3 uops delivered by the front-end.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/memory.json b/tools/perf/pmu-events/arch/x86/skylakex/memory.json
index 6c3fd89d204d..6f29b02fa320 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/memory.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/memory.json
@@ -1,31 +1,262 @@
[
{
- "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Cycles while L3 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800122",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "2",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L3_MISS",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "6",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x6"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED",
+ "PEBS": "1",
+ "PublicDescription": "Number of times HLE abort was triggered.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to unfriendly events (such as interrupts).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_EVENTS",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_MEM",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_MEMTYPE",
+ "PublicDescription": "Number of times an HLE execution aborted due to incompatible memory type.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to hardware timer expiration.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_TIMER",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.ABORTED_UNFRIENDLY",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution successfully committed",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.COMMIT",
+ "PublicDescription": "Number of times HLE commit succeeded.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of times an HLE execution started.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC8",
+ "EventName": "HLE_RETIRED.START",
+ "PublicDescription": "Number of times we entered an HLE region. Does not count nested transactions.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Errata": "SKL089",
+ "EventCode": "0xC3",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "PublicDescription": "Counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:a. memory disambiguation,b. external snoop, orc. cross SMT-HW-thread snoop (stores) hitting load buffer.",
"SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x80",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "1009",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch RFOs that miss in the L3.",
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000122",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x10",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "20011",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x100",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "503",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x20",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x4",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.",
"SampleAfterValue": "100003",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x200",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "101",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x40",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "2003",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x8",
+ "PEBS": "2",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "50021",
+ "TakenAlone": "1",
"UMask": "0x1"
},
{
+ "BriefDescription": "Demand Data Read requests who miss L3 cache",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xB0",
+ "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD",
+ "PublicDescription": "Demand Data Read requests who miss L3 cache.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Cycles with at least 1 Demand Data Read requests who miss L3 cache in the superQ.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_L3_MISS_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts number of Offcore outstanding Demand Data Read requests that miss L3 cache in the superQ every cycle.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
"BriefDescription": "Cycles with at least 6 Demand Data Read requests that miss L3 cache in the superQ.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -36,146 +267,130 @@
"UMask": "0x10"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800020",
+ "MSRValue": "0x3FBC000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss in the L3.",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000100",
+ "MSRValue": "0x103FC00491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00002",
+ "MSRValue": "0x083FC00491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to hardware timer expiration.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_TIMER",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800490",
+ "MSRValue": "0x063FC00491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_MEM",
- "PublicDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800004",
+ "MSRValue": "0x0604000491",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
+ "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_MEMTYPE",
- "PublicDescription": "Number of times an RTM execution aborted due to incompatible memory type.",
- "SampleAfterValue": "2000003",
- "UMask": "0x40"
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x063B800491",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) that miss in the L3.",
+ "BriefDescription": "Counts all prefetch data reads that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000002",
+ "MSRValue": "0x3FBC000490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts all prefetch data reads that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00120",
+ "MSRValue": "0x103FC00490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch data reads that miss in the L3.",
+ "BriefDescription": "Counts all prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000490",
+ "MSRValue": "0x083FC00490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000120",
+ "MSRValue": "0x063FC00490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -195,464 +410,312 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles while L3 cache miss demand load is outstanding.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "2",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.CYCLES_L3_MISS",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000491",
+ "MSRValue": "0x063B800490",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts prefetch RFOs that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00004",
+ "MSRValue": "0x3FBC000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts prefetch RFOs that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00004",
+ "MSRValue": "0x103FC00120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x20",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "100007",
- "TakenAlone": "1",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts prefetch RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00020",
+ "MSRValue": "0x083FC00120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch data reads that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00490",
+ "MSRValue": "0x063FC00120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss in the L3.",
+ "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000020",
+ "MSRValue": "0x0604000120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
- "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_CONFLICT",
- "PublicDescription": "Number of times a TSX line had a cache conflict.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss in the L3.",
+ "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000400",
+ "MSRValue": "0x063B800120",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x40",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "2003",
- "TakenAlone": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3FBC000122",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00002",
+ "MSRValue": "0x103FC00122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to various memory events (e.g., read/write capacity and conflicts).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_MEM",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
- "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00080",
+ "MSRValue": "0x083FC00122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC5",
- "PublicDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC4",
- "PublicDescription": "RTM region detected inside HLE.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC3",
- "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC2",
- "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5d",
- "EventName": "TX_EXEC.MISC1",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Number of times an RTM execution successfully committed",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.COMMIT",
- "PublicDescription": "Number of times RTM commit succeeded.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts prefetch RFOs that miss in the L3.",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000120",
+ "MSRValue": "0x063FC00122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts number of Offcore outstanding Demand Data Read requests that miss L3 cache in the superQ every cycle.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800491",
+ "MSRValue": "0x0604000122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800080",
+ "MSRValue": "0x063B800122",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts all demand code reads that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00490",
+ "MSRValue": "0x3FBC000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts all demand code reads that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000010",
+ "MSRValue": "0x103FC00004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to uncommon conditions.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_TIMER",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts all demand code reads that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00020",
+ "MSRValue": "0x083FC00004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00002",
+ "MSRValue": "0x063FC00004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch data reads that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00490",
+ "MSRValue": "0x0604000004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800100",
+ "MSRValue": "0x063B800004",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts demand data reads that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00010",
+ "MSRValue": "0x3FBC000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts demand data reads that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00010",
+ "MSRValue": "0x103FC00001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to HLE-unfriendly instructions and certain unfriendly events (such as AD assists etc.).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_UNFRIENDLY",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts demand data reads that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800400",
+ "MSRValue": "0x083FC00001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00122",
+ "MSRValue": "0x063FC00001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00122",
+ "MSRValue": "0x0604000001",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -672,541 +735,442 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000001",
+ "MSRValue": "0x3FBC000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution successfully committed",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.COMMIT",
- "PublicDescription": "Number of times HLE commit succeeded.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
- "PublicDescription": "Number of times we could not allocate Lock Buffer.",
- "SampleAfterValue": "2000003",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00100",
+ "MSRValue": "0x103FC00002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00001",
+ "MSRValue": "0x083FC00002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000020",
+ "MSRValue": "0x063FC00002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00080",
+ "MSRValue": "0x0604000002",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Demand Data Read requests who miss L3 cache",
+ "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB0",
- "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD",
- "PublicDescription": "Demand Data Read requests who miss L3 cache.",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x063B800002",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x10"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00080",
+ "MSRValue": "0x3FBC000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads that miss in the L3.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000001",
+ "MSRValue": "0x103FC00400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY",
- "PublicDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions.",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00010",
+ "MSRValue": "0x083FC00400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00120",
+ "MSRValue": "0x063FC00400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00004",
+ "MSRValue": "0x0604000400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00100",
+ "MSRValue": "0x063B800400",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x100",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "503",
- "TakenAlone": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x3FBC000010",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00122",
+ "MSRValue": "0x103FC00010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00001",
+ "MSRValue": "0x083FC00010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00020",
+ "MSRValue": "0x063FC00010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800002",
+ "MSRValue": "0x0604000010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00491",
+ "MSRValue": "0x063B800010",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an RTM execution aborted due to any reasons (multiple categories may count as one).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.ABORTED",
- "PEBS": "1",
- "PublicDescription": "Number of times RTM abort was triggered.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00400",
+ "MSRValue": "0x3FBC000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to any reasons (multiple categories may count as one).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED",
- "PEBS": "1",
- "PublicDescription": "Number of times HLE abort was triggered.",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x10",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "20011",
- "TakenAlone": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x103FC00020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
- "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00400",
+ "MSRValue": "0x083FC00020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800010",
+ "MSRValue": "0x063FC00020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles with at least 1 Demand Data Read requests who miss L3 cache in the superQ.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x60",
- "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_L3_MISS_DEMAND_DATA_RD",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Counts all demand data writes (RFOs) that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000002",
+ "MSRValue": "0x0604000020",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.",
+ "BriefDescription": "Counts all prefetch (that bring data to L2) RFOs that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x200",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "101",
- "TakenAlone": "1",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x063B800020",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS.REMOTE_HITM",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00400",
+ "MSRValue": "0x3FBC000080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts prefetch (that bring data to L2) data reads that miss in the L3.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000010",
+ "MSRValue": "0x103FC00080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand code reads that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000004",
+ "MSRValue": "0x083FC00080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times a transactional abort was signaled due to a data capacity limitation for transactional reads or writes.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_CAPACITY",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Counts prefetch RFOs that miss the L3 and the data is returned from remote dram.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063B800120",
+ "MSRValue": "0x063FC00080",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to incompatible memory type",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_MEMTYPE",
- "PublicDescription": "Number of times an HLE execution aborted due to incompatible memory type.",
- "SampleAfterValue": "2000003",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "Number of times an RTM execution started.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from local dram.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC9",
- "EventName": "RTM_RETIRED.START",
- "PublicDescription": "Number of times we entered an RTM region. Does not count nested transactions.",
- "SampleAfterValue": "2000003",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x0604000080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts the number of machine clears due to memory order conflicts.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL089",
- "EventCode": "0xC3",
- "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
- "PublicDescription": "Counts the number of memory ordering Machine Clears detected. Memory Ordering Machine Clears can result from one of the following:a. memory disambiguation,b. external snoop, orc. cross SMT-HW-thread snoop (stores) hitting load buffer.",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x063B800080",
+ "Offcore": "1",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x54",
- "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
- "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss in the L3.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.ANY_SNOOP",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00491",
+ "MSRValue": "0x3FBC000100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that miss in the L3.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the modified data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HITM",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000491",
+ "MSRValue": "0x103FC00100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts demand data reads that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and clean or shared data is transferred from remote cache.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.REMOTE_HIT_FORWARD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00001",
+ "MSRValue": "0x083FC00100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss in the L3.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from local or remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS.ANY_SNOOP",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000080",
+ "MSRValue": "0x063FC00100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
@@ -1226,19 +1190,30 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) data reads that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from remote dram.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3",
"EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_DATA_RD.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
+ "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS_REMOTE_DRAM.SNOOP_MISS_OR_NO_FWD",
"MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000080",
+ "MSRValue": "0x063B800100",
"Offcore": "1",
"PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
+ "BriefDescription": "Number of times an RTM execution aborted due to any reasons (multiple categories may count as one).",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "PEBS": "1",
+ "PublicDescription": "Number of times RTM abort was triggered.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
"BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -1249,155 +1224,180 @@
"UMask": "0x80"
},
{
- "BriefDescription": "Number of times an HLE execution started.",
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.START",
- "PublicDescription": "Number of times we entered an HLE region. Does not count nested transactions.",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_MEM",
+ "PublicDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Counts all demand code reads that miss in the L3.",
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L3_MISS.ANY_SNOOP",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x3FBC000004",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_MEMTYPE",
+ "PublicDescription": "Number of times an RTM execution aborted due to incompatible memory type.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.",
+ "BriefDescription": "Number of times an RTM execution aborted due to uncommon conditions.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x80",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "1009",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_TIMER",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
},
{
- "BriefDescription": "Counts all demand & prefetch data reads that miss the L3 and clean or shared data is transferred from remote cache.",
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_DATA_RD.L3_MISS.REMOTE_HIT_FORWARD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x083FC00491",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY",
+ "PublicDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
},
{
- "BriefDescription": "Counts prefetch RFOs that miss the L3 and the modified data is transferred from remote cache.",
+ "BriefDescription": "Number of times an RTM execution successfully committed",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_PF_RFO.L3_MISS.REMOTE_HITM",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x103FC00120",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "PublicDescription": "Number of times RTM commit succeeded.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution started.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC9",
+ "EventName": "RTM_RETIRED.START",
+ "PublicDescription": "Number of times we entered an RTM region. Does not count nested transactions.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts all prefetch (that bring data to LLC only) RFOs that miss the L3 and the data is returned from local or remote dram.",
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed. Since this is the count of execution, it may not always cause a transactional abort.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L3_RFO.L3_MISS.SNOOP_MISS_OR_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x063FC00100",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC1",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.",
+ "BriefDescription": "Counts the number of times a class of instructions (e.g., vzeroupper) that may cause a transactional abort was executed inside a transactional region",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "6",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC2",
+ "PublicDescription": "Unfriendly TSX abort triggered by a vzeroupper instruction.",
"SampleAfterValue": "2000003",
- "UMask": "0x6"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Number of times an HLE execution aborted due to unfriendly events (such as interrupts).",
+ "BriefDescription": "Counts the number of times an instruction execution caused the transactional nest count supported to be exceeded",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC8",
- "EventName": "HLE_RETIRED.ABORTED_EVENTS",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC3",
+ "PublicDescription": "Unfriendly TSX abort triggered by a nest count that is too deep.",
"SampleAfterValue": "2000003",
- "UMask": "0x80"
+ "UMask": "0x4"
},
{
- "BriefDescription": "Counts all demand & prefetch RFOs that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Counts the number of times a XBEGIN instruction was executed inside an HLE transactional region.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.ALL_RFO.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000122",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC4",
+ "PublicDescription": "RTM region detected inside HLE.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.",
+ "BriefDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x4",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "100003",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC5",
+ "PublicDescription": "Counts the number of times an HLE XACQUIRE instruction was executed inside an RTM transactional region.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
},
{
- "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data capacity limitation for transactional reads or writes.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Data_LA": "1",
- "EventCode": "0xcd",
- "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
- "MSRIndex": "0x3F6",
- "MSRValue": "0x8",
- "PEBS": "2",
- "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.",
- "SampleAfterValue": "50021",
- "TakenAlone": "1",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_CAPACITY",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Counts L1 data cache hardware prefetch requests and software prefetch requests that miss the L3 and the data is returned from local dram.",
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xB7, 0xBB",
- "EventName": "OFFCORE_RESPONSE.PF_L1D_AND_SW.L3_MISS_LOCAL_DRAM.SNOOP_MISS_OR_NO_FWD",
- "MSRIndex": "0x1a6,0x1a7",
- "MSRValue": "0x0604000400",
- "Offcore": "1",
- "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
- "SampleAfterValue": "100003",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "PublicDescription": "Number of times a TSX line had a cache conflict.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to XRELEASE lock not satisfying the address and value requirements in the elision buffer",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_MISMATCH",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to release/commit but data and address mismatch.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to NoAllocatedElisionBuffer being non-zero.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_NOT_EMPTY",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to commit but Lock Buffer not empty.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Number of times an HLE transactional execution aborted due to an unsupported read alignment from the elision buffer.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_HLE_ELISION_BUFFER_UNSUPPORTED_ALIGNMENT",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to attempting an unsupported alignment from Lock Buffer.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Number of times a HLE transactional region aborted due to a non XRELEASE prefixed instruction writing to an elided lock in the elision buffer",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_HLE_STORE_TO_ELIDED_LOCK",
+ "PublicDescription": "Number of times a TSX Abort was triggered due to a non-release/commit store to lock.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of times HLE lock could not be elided due to ElisionBufferAvailable being zero.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.HLE_ELISION_BUFFER_FULL",
+ "PublicDescription": "Number of times we could not allocate Lock Buffer.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/other.json b/tools/perf/pmu-events/arch/x86/skylakex/other.json
index f6b147ba8ef6..8b344259176f 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/other.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/other.json
@@ -1,34 +1,5 @@
[
{
- "BriefDescription": "Core cycles the core was throttled due to a pending power level request.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x28",
- "EventName": "CORE_POWER.THROTTLE",
- "PublicDescription": "Core cycles the out-of-order engine was throttled due to a pending power level request.",
- "SampleAfterValue": "200003",
- "UMask": "0x40"
- },
- {
- "BriefDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xFE",
- "EventName": "IDI_MISC.WB_DOWNGRADE",
- "PublicDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly.",
- "SampleAfterValue": "100003",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Number of PREFETCHW instructions executed.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x32",
- "EventName": "SW_PREFETCH_ACCESS.PREFETCHW",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
- },
- {
"BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the Non-AVX turbo schedule.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
@@ -49,13 +20,24 @@
"UMask": "0x18"
},
{
- "BriefDescription": "Number of PREFETCHT0 instructions executed.",
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX512 turbo schedule.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x32",
- "EventName": "SW_PREFETCH_ACCESS.T0",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.LVL2_TURBO_LICENSE",
+ "PublicDescription": "Core cycles where the core was running with power-delivery for license level 2 (introduced in Skylake Server michroarchtecture). This includes high current AVX 512-bit instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Core cycles the core was throttled due to a pending power level request.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.THROTTLE",
+ "PublicDescription": "Core cycles the out-of-order engine was throttled due to a pending power level request.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x40"
},
{
"BriefDescription": "Number of hardware interrupts received by the processor.",
@@ -68,14 +50,32 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX512 turbo schedule.",
+ "BriefDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x28",
- "EventName": "CORE_POWER.LVL2_TURBO_LICENSE",
- "PublicDescription": "Core cycles where the core was running with power-delivery for license level 2 (introduced in Skylake Server michroarchtecture). This includes high current AVX 512-bit instructions.",
- "SampleAfterValue": "200003",
- "UMask": "0x20"
+ "EventCode": "0xFE",
+ "EventName": "IDI_MISC.WB_DOWNGRADE",
+ "PublicDescription": "Counts number of cache lines that are dropped and not written back to L3 as they are deemed to be less likely to be reused shortly.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xFE",
+ "EventName": "IDI_MISC.WB_UPGRADE",
+ "PublicDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x09",
+ "EventName": "MEMORY_DISAMBIGUATION.HISTORY_RESET",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
"BriefDescription": "Number of PREFETCHNTA instructions executed.",
@@ -87,30 +87,30 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed.",
+ "BriefDescription": "Number of PREFETCHW instructions executed.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x32",
- "EventName": "SW_PREFETCH_ACCESS.T1_T2",
+ "EventName": "SW_PREFETCH_ACCESS.PREFETCHW",
"SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "UMask": "0x8"
},
{
+ "BriefDescription": "Number of PREFETCHT0 instructions executed.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x09",
- "EventName": "MEMORY_DISAMBIGUATION.HISTORY_RESET",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.T0",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly",
+ "BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xFE",
- "EventName": "IDI_MISC.WB_UPGRADE",
- "PublicDescription": "Counts number of cache lines that are allocated and written back to L3 with the intention that they are more likely to be reused shortly.",
- "SampleAfterValue": "100003",
- "UMask": "0x2"
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.T1_T2",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json b/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json
index 3bfc6943ddf9..ca5748120666 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/pipeline.json
@@ -1,55 +1,58 @@
[
{
- "BriefDescription": "Number of instructions retired. General Counter - architectural event",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091, SKL044",
- "EventCode": "0xC0",
- "EventName": "INST_RETIRED.ANY_P",
- "PublicDescription": "Counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
- "SampleAfterValue": "2000003"
- },
- {
- "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.STALL_CYCLES",
- "Invert": "1",
- "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
+ "EventCode": "0x14",
+ "EventName": "ARITH.DIVIDER_ACTIVE",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station was not empty.",
+ "BriefDescription": "All (macro) branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.4_PORTS_UTIL",
- "PublicDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station (RS) was not empty.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "Counts all (macro) branch instructions retired.",
+ "SampleAfterValue": "400009"
},
{
- "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.",
+ "BriefDescription": "All (macro) branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Conditional branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x14",
- "EventName": "ARITH.DIVIDER_ACTIVE",
- "SampleAfterValue": "2000003",
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.CONDITIONAL",
+ "PEBS": "1",
+ "PublicDescription": "This event counts conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
"UMask": "0x1"
},
{
- "BriefDescription": "False dependencies in MOB due to partial compare on address.",
+ "BriefDescription": "Not taken branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x07",
- "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
- "PublicDescription": "Counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "Errata": "SKL091",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.COND_NTAKEN",
+ "PublicDescription": "This event counts not taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x10"
},
{
"BriefDescription": "Far branch instructions retired.",
@@ -64,23 +67,81 @@
"UMask": "0x40"
},
{
- "BriefDescription": "Counts the number of x87 uops dispatched.",
+ "BriefDescription": "Direct and indirect near call instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.X87",
- "PublicDescription": "Counts the number of x87 uops executed.",
- "SampleAfterValue": "2000003",
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "PEBS": "1",
+ "PublicDescription": "This event counts both direct and indirect near call instructions retired.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Return instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "PEBS": "1",
+ "PublicDescription": "This event counts return instructions retired.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Taken branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "PEBS": "1",
+ "PublicDescription": "This event counts taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Not taken branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Errata": "SKL091",
+ "EventCode": "0xC4",
+ "EventName": "BR_INST_RETIRED.NOT_TAKEN",
+ "PublicDescription": "This event counts not taken branch instructions retired.",
+ "SampleAfterValue": "400009",
"UMask": "0x10"
},
{
- "BriefDescription": "Demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch.",
+ "BriefDescription": "All mispredicted macro branch instructions retired.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x4C",
- "EventName": "LOAD_HIT_PRE.SW_PF",
- "PublicDescription": "Counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by ASM (Assembly File) inspection of the nearby instructions.",
- "SampleAfterValue": "100003",
+ "EventCode": "0xC5",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "SampleAfterValue": "400009"
+ },
+ {
+ "BriefDescription": "Mispredicted macro branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3",
+ "EventCode": "0xC5",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
+ "PEBS": "2",
+ "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xC5",
+ "EventName": "BR_MISP_RETIRED.CONDITIONAL",
+ "PEBS": "1",
+ "PublicDescription": "This event counts mispredicted conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
"UMask": "0x1"
},
{
@@ -95,85 +156,99 @@
"UMask": "0x2"
},
{
- "BriefDescription": "Total execution stalls.",
+ "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
- "SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "EventCode": "0xC5",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "PEBS": "1",
+ "SampleAfterValue": "400009",
+ "UMask": "0x20"
},
{
- "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "5",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
- "SampleAfterValue": "2000003",
- "UMask": "0x5"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "25003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
+ "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0E",
- "EventName": "UOPS_ISSUED.SLOW_LEA",
- "SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "25003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "AnyThread": "1",
+ "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "10",
- "EventCode": "0xC2",
- "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
- "Invert": "1",
- "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
+ "SampleAfterValue": "25003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Thread cycles when thread is not in halt state",
+ "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.THREAD_P",
- "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
- "SampleAfterValue": "2000003"
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "SampleAfterValue": "25003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "Counter": "Fixed counter 2",
+ "CounterHTOff": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x3"
+ },
+ {
+ "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "2",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
- "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
- "SampleAfterValue": "2000003",
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "SampleAfterValue": "25003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
+ "AnyThread": "1",
+ "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x3C",
- "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
"SampleAfterValue": "25003",
"UMask": "0x1"
},
{
- "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "BriefDescription": "Counts when there is a transition from ring 1, 2 or 3 to ring 0.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
"EdgeDetect": "1",
- "EventCode": "0xC3",
- "EventName": "MACHINE_CLEARS.COUNT",
- "SampleAfterValue": "100003",
- "UMask": "0x1"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_UNHALTED.RING0_TRANS",
+ "PublicDescription": "Counts when the Current Privilege Level (CPL) transitions from ring 1, 2 or 3 to ring 0 (Kernel).",
+ "SampleAfterValue": "100007"
+ },
+ {
+ "BriefDescription": "Core cycles when the thread is not in halt state",
+ "Counter": "Fixed counter 1",
+ "CounterHTOff": "Fixed counter 1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
"AnyThread": "1",
@@ -185,177 +260,182 @@
"UMask": "0x2"
},
{
- "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "BriefDescription": "Thread cycles when thread is not in halt state",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.THREAD",
- "PublicDescription": "Number of uops to be executed per-thread each cycle.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
+ "SampleAfterValue": "2000003"
},
{
- "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "AnyThread": "1",
+ "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "3",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
- "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
- "SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "EventCode": "0x3C",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
+ "SampleAfterValue": "2000003"
},
{
- "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
- "Invert": "1",
+ "CounterMask": "8",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Cycles where the Store Buffer was full and no outstanding load.",
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.BOUND_ON_STORES",
+ "CounterMask": "1",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
"SampleAfterValue": "2000003",
- "UMask": "0x40"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "8",
+ "CounterMask": "16",
"EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
"SampleAfterValue": "2000003",
- "UMask": "0x8"
+ "UMask": "0x10"
},
{
- "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xA8",
- "EventName": "LSD.CYCLES_ACTIVE",
- "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).",
+ "CounterMask": "12",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0xc"
},
{
- "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread (e.g. misprediction or memory nuke)",
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0D",
- "EventName": "INT_MISC.RECOVERY_CYCLES",
- "PublicDescription": "Core cycles the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.",
+ "CounterMask": "5",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x5"
},
{
- "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
"Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
- "SampleAfterValue": "25003",
- "UMask": "0x1"
+ "CounterHTOff": "0,1,2,3",
+ "CounterMask": "20",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x14"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 0",
+ "BriefDescription": "Total execution stalls.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 0.",
+ "CounterMask": "4",
+ "EventCode": "0xA3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x4"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 1",
+ "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 1.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.1_PORTS_UTIL",
+ "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
"UMask": "0x2"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 2",
+ "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 2.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.2_PORTS_UTIL",
+ "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
"UMask": "0x4"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 3",
+ "BriefDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station was not empty.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 3.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.3_PORTS_UTIL",
+ "PublicDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
"UMask": "0x8"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 4",
+ "BriefDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station was not empty.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 4.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.4_PORTS_UTIL",
+ "PublicDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
"UMask": "0x10"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 5",
+ "BriefDescription": "Cycles where the Store Buffer was full and no outstanding load.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 5.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.BOUND_ON_STORES",
"SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "UMask": "0x40"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 6",
+ "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 6.",
+ "EventCode": "0xA6",
+ "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS",
+ "PublicDescription": "Counts cycles during which no uops were executed on all ports and Reservation Station (RS) was not empty.",
"SampleAfterValue": "2000003",
- "UMask": "0x40"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles per thread when uops are executed in port 7",
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA1",
- "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
- "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 7.",
+ "EventCode": "0x87",
+ "EventName": "ILD_STALL.LCP",
+ "PublicDescription": "Counts cycles that the Instruction Length decoder (ILD) stalls occurred due to dynamically changing prefix length of the decoded instruction (by operand size prefix instruction 0x66, address size prefix instruction 0x67 or REX.W for Intel64). Count is proportional to the number of prefixes in a 16B-line. This may result in a three-cycle penalty for each LCP (Length changing prefix) in a 16-byte chunk.",
"SampleAfterValue": "2000003",
- "UMask": "0x80"
+ "UMask": "0x1"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0D",
- "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
+ "BriefDescription": "Instructions retired from execution.",
+ "Counter": "Fixed counter 0",
+ "CounterHTOff": "Fixed counter 0",
+ "EventName": "INST_RETIRED.ANY",
+ "PublicDescription": "Counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, Counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. Counting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "Errata": "SKL091, SKL044",
+ "EventCode": "0xC0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "PublicDescription": "Counts the number of instructions (EOMs) retired. Counting covers macro-fused instructions individually (that is, increments by two).",
+ "SampleAfterValue": "2000003"
+ },
+ {
"BriefDescription": "Precise instruction retired event with HW to reduce effect of PEBS shadow in IP distribution",
"Counter": "1",
"CounterHTOff": "1",
@@ -368,24 +448,56 @@
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
+ "BriefDescription": "Number of cycles using always true condition applied to PEBS instructions retired event.",
+ "Counter": "0,2,3",
+ "CounterHTOff": "0,2,3",
+ "CounterMask": "10",
+ "Errata": "SKL091, SKL044",
+ "EventCode": "0xC0",
+ "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
+ "Invert": "1",
+ "PEBS": "2",
+ "PublicDescription": "Number of cycles using an always true condition applied to PEBS instructions retired event. (inst_ret< 16)",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles the issue-stage is waiting for front-end to fetch from resteered path following branch misprediction or machine clear events.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0xA8",
- "EventName": "LSD.CYCLES_4_UOPS",
- "PublicDescription": "Counts the cycles when 4 uops are delivered by the LSD (Loop-stream detector).",
+ "EventCode": "0x0D",
+ "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread (e.g. misprediction or memory nuke)",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x0D",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "PublicDescription": "Core cycles the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station was not empty.",
+ "AnyThread": "1",
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for any thread running on the physical core (e.g. misprediction or memory nuke).",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.3_PORTS_UTIL",
- "PublicDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station (RS) was not empty.",
+ "EventCode": "0x0D",
+ "EventName": "INT_MISC.RECOVERY_CYCLES_ANY",
"SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x03",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "SampleAfterValue": "100003",
"UMask": "0x8"
},
{
@@ -399,108 +511,77 @@
"UMask": "0x2"
},
{
- "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "BriefDescription": "False dependencies in MOB due to partial compare on address.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EdgeDetect": "1",
- "EventCode": "0x5E",
- "EventName": "RS_EVENTS.EMPTY_END",
- "Invert": "1",
- "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate front-end Latency Bound issues.",
- "SampleAfterValue": "2000003",
+ "EventCode": "0x07",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "PublicDescription": "Counts false dependencies in MOB when the partial comparison upon loose net check and dependency was resolved by the Enhanced Loose net mechanism. This may not result in high performance penalties. Loose net checks can fail when loads and stores are 4k aliased.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
+ "BriefDescription": "Demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY",
- "SampleAfterValue": "25003",
+ "EventCode": "0x4C",
+ "EventName": "LOAD_HIT_PRE.SW_PF",
+ "PublicDescription": "Counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by ASM (Assembly File) inspection of the nearby instructions.",
+ "SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles where the pipeline is stalled due to serializing operations.",
+ "BriefDescription": "Cycles 4 Uops delivered by the LSD, but didn't come from the decoder.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x59",
- "EventName": "PARTIAL_RAT_STALLS.SCOREBOARD",
- "PublicDescription": "This event counts cycles during which the microcode scoreboard stalls happen.",
+ "CounterMask": "4",
+ "EventCode": "0xA8",
+ "EventName": "LSD.CYCLES_4_UOPS",
+ "PublicDescription": "Counts the cycles when 4 uops are delivered by the LSD (Loop-stream detector).",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
- "EventCode": "0x0E",
- "EventName": "UOPS_ISSUED.STALL_CYCLES",
- "Invert": "1",
- "PublicDescription": "Counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
+ "EventCode": "0xA8",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Not taken branch instructions retired.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xc4",
- "EventName": "BR_INST_RETIRED.COND_NTAKEN",
- "PublicDescription": "This event counts not taken branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "BriefDescription": "Number of Uops delivered by the LSD.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "3",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "EventCode": "0xA8",
+ "EventName": "LSD.UOPS",
+ "PublicDescription": "Number of uops delivered to the back-end by the LSD(Loop Stream Detector).",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Reference cycles when the core is not in halt state.",
- "Counter": "Fixed counter 2",
- "CounterHTOff": "Fixed counter 2",
- "EventName": "CPU_CLK_UNHALTED.REF_TSC",
- "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
- "SampleAfterValue": "2000003",
- "UMask": "0x3"
+ "EdgeDetect": "1",
+ "EventCode": "0xC3",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "All mispredicted macro branch instructions retired.",
+ "BriefDescription": "Self-modifying code (SMC) detected.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC5",
- "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
- "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
- "SampleAfterValue": "400009"
+ "EventCode": "0xC3",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
},
{
"BriefDescription": "Number of times a microcode assist is invoked by HW other than FP-assist. Examples include AD (page Access Dirty) and AVX* related assists.",
@@ -512,448 +593,377 @@
"UMask": "0x3f"
},
{
- "BriefDescription": "Cycles without actually retired uops.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xC2",
- "EventName": "UOPS_RETIRED.STALL_CYCLES",
- "Invert": "1",
- "PublicDescription": "This event counts cycles without actually retired uops.",
- "SampleAfterValue": "2000003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Number of Uops delivered by the LSD.",
+ "BriefDescription": "Cycles where the pipeline is stalled due to serializing operations.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA8",
- "EventName": "LSD.UOPS",
- "PublicDescription": "Number of uops delivered to the back-end by the LSD(Loop Stream Detector).",
+ "EventCode": "0x59",
+ "EventName": "PARTIAL_RAT_STALLS.SCOREBOARD",
+ "PublicDescription": "This event counts cycles during which the microcode scoreboard stalls happen.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE",
- "SampleAfterValue": "25003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "BriefDescription": "Resource-related stall cycles",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x87",
- "EventName": "ILD_STALL.LCP",
- "PublicDescription": "Counts cycles that the Instruction Length decoder (ILD) stalls occurred due to dynamically changing prefix length of the decoded instruction (by operand size prefix instruction 0x66, address size prefix instruction 0x67 or REX.W for Intel64). Count is proportional to the number of prefixes in a 16B-line. This may result in a three-cycle penalty for each LCP (Length changing prefix) in a 16-byte chunk.",
+ "EventCode": "0xa2",
+ "EventName": "RESOURCE_STALLS.ANY",
+ "PublicDescription": "Counts resource-related stall cycles.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "16",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "EventCode": "0xA2",
+ "EventName": "RESOURCE_STALLS.SB",
+ "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.",
"SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Taken branch instructions retired.",
+ "BriefDescription": "Increments whenever there is an update to the LBR array.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
- "PEBS": "1",
- "PublicDescription": "This event counts taken branch instructions retired.",
- "SampleAfterValue": "400009",
+ "EventCode": "0xCC",
+ "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
+ "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.",
+ "SampleAfterValue": "2000003",
"UMask": "0x20"
},
{
- "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use",
+ "BriefDescription": "Number of retired PAUSE instructions (that do not end up with a VMExit to the VMM; TSX aborted Instructions may be counted). This event is not supported on first SKL and KBL products.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x03",
- "EventName": "LD_BLOCKS.NO_SR",
- "PublicDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
- "SampleAfterValue": "100003",
- "UMask": "0x8"
+ "EventCode": "0xCC",
+ "EventName": "ROB_MISC_EVENTS.PAUSE_INST",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
},
{
- "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0E",
- "EventName": "UOPS_ISSUED.ANY",
- "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).",
+ "EventCode": "0x5E",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for the thread.; Note: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Core cycles when the thread is not in halt state",
- "Counter": "Fixed counter 1",
- "CounterHTOff": "Fixed counter 1",
- "EventName": "CPU_CLK_UNHALTED.THREAD",
- "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events.",
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate Frontend Latency Bound issues.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EdgeDetect": "1",
+ "EventCode": "0x5E",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "Invert": "1",
+ "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to precisely locate front-end Latency Bound issues.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core crystal clock cycles when at least one thread on the physical core is unhalted.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 0",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.REF_XCLK_ANY",
- "SampleAfterValue": "25003",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_0",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 0.",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Direct and indirect near call instructions retired.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 1",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.NEAR_CALL",
- "PEBS": "1",
- "PublicDescription": "This event counts both direct and indirect near call instructions retired.",
- "SampleAfterValue": "100007",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_1",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 1.",
+ "SampleAfterValue": "2000003",
"UMask": "0x2"
},
{
- "BriefDescription": "Number of retired PAUSE instructions (that do not end up with a VMExit to the VMM; TSX aborted Instructions may be counted). This event is not supported on first SKL and KBL products.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 2",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xCC",
- "EventName": "ROB_MISC_EVENTS.PAUSE_INST",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_2",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 2.",
"SampleAfterValue": "2000003",
- "UMask": "0x40"
+ "UMask": "0x4"
},
{
- "BriefDescription": "Resource-related stall cycles",
+ "BriefDescription": "Cycles per thread when uops are executed in port 3",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xa2",
- "EventName": "RESOURCE_STALLS.ANY",
- "PublicDescription": "Counts resource-related stall cycles.",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_3",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 3.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Self-modifying code (SMC) detected.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 4",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC3",
- "EventName": "MACHINE_CLEARS.SMC",
- "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.",
- "SampleAfterValue": "100003",
- "UMask": "0x4"
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_4",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 4.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
},
{
- "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 5",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
- "SampleAfterValue": "25003",
- "UMask": "0x2"
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_5",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 5.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
},
{
- "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
+ "BriefDescription": "Cycles per thread when uops are executed in port 6",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "4",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
- "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_6",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 6.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x40"
},
{
- "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.",
+ "BriefDescription": "Cycles per thread when uops are executed in port 7",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC5",
- "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
- "PEBS": "1",
- "SampleAfterValue": "400009",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "CounterMask": "20",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "EventCode": "0xA1",
+ "EventName": "UOPS_DISPATCHED_PORT.PORT_7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 7.",
"SampleAfterValue": "2000003",
- "UMask": "0x14"
+ "UMask": "0x80"
},
{
- "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load.",
+ "BriefDescription": "Number of uops executed on the core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS",
- "PublicDescription": "Counts cycles during which no uops were executed on all ports and Reservation Station (RS) was not empty.",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "PublicDescription": "Number of uops executed from any thread.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Number of cycles using always true condition applied to PEBS instructions retired event.",
- "Counter": "0,2,3",
- "CounterHTOff": "0,2,3",
- "CounterMask": "10",
- "Errata": "SKL091, SKL044",
- "EventCode": "0xC0",
- "EventName": "INST_RETIRED.TOTAL_CYCLES_PS",
- "Invert": "1",
- "PEBS": "2",
- "PublicDescription": "Number of cycles using an always true condition applied to PEBS instructions retired event. (inst_ret< 16)",
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Retirement slots used.",
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC2",
- "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
- "PublicDescription": "Counts the retirement slots used.",
+ "CounterMask": "2",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
"SampleAfterValue": "2000003",
"UMask": "0x2"
},
{
- "AnyThread": "1",
- "BriefDescription": "Core cycles when at least one thread on the physical core is not in halt state.",
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.THREAD_P_ANY",
- "SampleAfterValue": "2000003"
+ "CounterMask": "3",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
- "BriefDescription": "Uops inserted at issue-stage in order to preserve upper bits of vector registers.",
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0E",
- "EventName": "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH",
- "PublicDescription": "Counts the number of Blend Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS) in order to preserve upper bits of vector registers. Starting with the Skylake microarchitecture, these Blend uops are needed since every Intel SSE instruction executed in Dirty Upper State needs to preserve bits 128-255 of the destination register. For more information, refer to Mixing Intel AVX and Intel SSE Code section of the Optimization Guide.",
+ "CounterMask": "4",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
"SampleAfterValue": "2000003",
"UMask": "0x2"
},
{
- "BriefDescription": "Increments whenever there is an update to the LBR array.",
+ "BriefDescription": "Cycles with no micro-ops executed from any thread on physical core.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xCC",
- "EventName": "ROB_MISC_EVENTS.LBR_INSERTS",
- "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.",
+ "CounterMask": "1",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_NONE",
+ "Invert": "1",
"SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x5E",
- "EventName": "RS_EVENTS.EMPTY_CYCLES",
- "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for the thread.; Note: In ST-mode, not active thread should drive 0. This is usually caused by severely costly branch mispredictions, or allocator/FE issues.",
+ "CounterMask": "1",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
+ "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Return instructions retired.",
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.NEAR_RETURN",
- "PEBS": "1",
- "PublicDescription": "This event counts return instructions retired.",
- "SampleAfterValue": "100007",
- "UMask": "0x8"
- },
- {
- "BriefDescription": "Instructions retired from execution.",
- "Counter": "Fixed counter 0",
- "CounterHTOff": "Fixed counter 0",
- "EventName": "INST_RETIRED.ANY",
- "PublicDescription": "Counts the number of instructions retired from execution. For instructions that consist of multiple micro-ops, Counts the retirement of the last micro-op of the instruction. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. INST_RETIRED.ANY_P is counted by a programmable counter and it is an architectural performance event. Counting: Faulting executions of GETSEC/VM entry/VM Exit/MWait will not count as retired instructions.",
+ "CounterMask": "2",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2_UOPS_EXEC",
+ "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "2",
+ "CounterMask": "3",
"EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3_UOPS_EXEC",
+ "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA2",
- "EventName": "RESOURCE_STALLS.SB",
- "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.",
+ "CounterMask": "4",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4_UOPS_EXEC",
+ "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
"SampleAfterValue": "2000003",
- "UMask": "0x8"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Counts when there is a transition from ring 1, 2 or 3 to ring 0.",
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
- "EdgeDetect": "1",
- "EventCode": "0x3C",
- "EventName": "CPU_CLK_UNHALTED.RING0_TRANS",
- "PublicDescription": "Counts when the Current Privilege Level (CPL) transitions from ring 1, 2 or 3 to ring 0 (Kernel).",
- "SampleAfterValue": "100007"
- },
- {
- "BriefDescription": "All (macro) branch instructions retired.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.ALL_BRANCHES_PEBS",
- "PEBS": "2",
- "PublicDescription": "This is a precise version of BR_INST_RETIRED.ALL_BRANCHES that counts all (macro) branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x4"
- },
- {
- "BriefDescription": "Mispredicted macro branch instructions retired.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3",
- "EventCode": "0xC5",
- "EventName": "BR_MISP_RETIRED.ALL_BRANCHES_PEBS",
- "PEBS": "2",
- "PublicDescription": "This is a precise version of BR_MISP_RETIRED.ALL_BRANCHES that counts all mispredicted macro branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x4"
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "Invert": "1",
+ "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty.",
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.1_PORTS_UTIL",
- "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "PublicDescription": "Number of uops to be executed per-thread each cycle.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Not taken branch instructions retired.",
+ "BriefDescription": "Counts the number of x87 uops dispatched.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.NOT_TAKEN",
- "PublicDescription": "This event counts not taken branch instructions retired.",
- "SampleAfterValue": "400009",
+ "EventCode": "0xB1",
+ "EventName": "UOPS_EXECUTED.X87",
+ "PublicDescription": "Counts the number of x87 uops executed.",
+ "SampleAfterValue": "2000003",
"UMask": "0x10"
},
{
- "BriefDescription": "Conditional branch instructions retired.",
+ "BriefDescription": "Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.CONDITIONAL",
- "PEBS": "1",
- "PublicDescription": "This event counts conditional branch instructions retired.",
- "SampleAfterValue": "400009",
+ "EventCode": "0x0E",
+ "EventName": "UOPS_ISSUED.ANY",
+ "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).",
+ "SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
- "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "BriefDescription": "Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xC5",
- "EventName": "BR_MISP_RETIRED.CONDITIONAL",
- "PEBS": "1",
- "PublicDescription": "This event counts mispredicted conditional branch instructions retired.",
- "SampleAfterValue": "400009",
- "UMask": "0x1"
+ "EventCode": "0x0E",
+ "EventName": "UOPS_ISSUED.SLOW_LEA",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
},
{
- "BriefDescription": "Number of uops executed on the core.",
+ "BriefDescription": "Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CORE",
- "PublicDescription": "Number of uops executed from any thread.",
+ "CounterMask": "1",
+ "EventCode": "0x0E",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "Invert": "1",
+ "PublicDescription": "Counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x1"
},
{
- "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "BriefDescription": "Uops inserted at issue-stage in order to preserve upper bits of vector registers.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "12",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "EventCode": "0x0E",
+ "EventName": "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH",
+ "PublicDescription": "Counts the number of Blend Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS) in order to preserve upper bits of vector registers. Starting with the Skylake microarchitecture, these Blend uops are needed since every Intel SSE instruction executed in Dirty Upper State needs to preserve bits 128-255 of the destination register. For more information, refer to Mixing Intel AVX and Intel SSE Code section of the Optimization Guide.",
"SampleAfterValue": "2000003",
- "UMask": "0xc"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty.",
+ "BriefDescription": "Number of macro-fused uops retired. (non precise)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xA6",
- "EventName": "EXE_ACTIVITY.2_PORTS_UTIL",
- "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.",
+ "EventCode": "0xc2",
+ "EventName": "UOPS_RETIRED.MACRO_FUSED",
+ "PublicDescription": "Counts the number of macro-fused uops retired. (non precise)",
"SampleAfterValue": "2000003",
"UMask": "0x4"
},
{
- "BriefDescription": "Cycles the issue-stage is waiting for front-end to fetch from resteered path following branch misprediction or machine clear events.",
+ "BriefDescription": "Retirement slots used.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x0D",
- "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES",
+ "EventCode": "0xC2",
+ "EventName": "UOPS_RETIRED.RETIRE_SLOTS",
+ "PublicDescription": "Counts the retirement slots used.",
"SampleAfterValue": "2000003",
- "UMask": "0x80"
- },
- {
- "BriefDescription": "All (macro) branch instructions retired.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "Errata": "SKL091",
- "EventCode": "0xC4",
- "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
- "PublicDescription": "Counts all (macro) branch instructions retired.",
- "SampleAfterValue": "400009"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
+ "BriefDescription": "Cycles without actually retired uops.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
- "EventCode": "0xB1",
- "EventName": "UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC",
- "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "EventCode": "0xC2",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "Invert": "1",
+ "PublicDescription": "This event counts cycles without actually retired uops.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0xA3",
- "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "CounterMask": "10",
+ "EventCode": "0xC2",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "Invert": "1",
+ "PublicDescription": "Number of cycles using always true condition (uops_ret < 16) applied to non PEBS uops retired event.",
"SampleAfterValue": "2000003",
- "UMask": "0x1"
+ "UMask": "0x2"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
index 0dd8b13b5cfb..863c9e103969 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
@@ -1,62 +1,5 @@
[
{
- "BriefDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend",
- "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * cycles)",
- "MetricGroup": "TopdownL1",
- "MetricName": "Frontend_Bound",
- "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Machine_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound."
- },
- {
- "BriefDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. SMT version; use when SMT is enabled and measuring per logical CPU.",
- "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
- "MetricGroup": "TopdownL1_SMT",
- "MetricName": "Frontend_Bound_SMT",
- "PublicDescription": "This category represents fraction of slots where the processor's Frontend undersupplies its Backend. Frontend denotes the first part of the processor core responsible to fetch operations that are executed later on by the Backend part. Within the Frontend; a branch predictor predicts the next address to fetch; cache-lines are fetched from the memory subsystem; parsed into instructions; and lastly decoded into micro-operations (uops). Ideally the Frontend can issue Machine_Width uops every cycle to the Backend. Frontend Bound denotes unutilized issue-slots when there is no Backend stall; i.e. bubbles where Frontend delivered no uops while Backend could have accepted them. For example; stalls due to instruction-cache misses would be categorized under Frontend Bound. SMT version; use when SMT is enabled and measuring per logical CPU."
- },
- {
- "BriefDescription": "This category represents fraction of slots wasted due to incorrect speculations",
- "MetricExpr": "( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * cycles)",
- "MetricGroup": "TopdownL1",
- "MetricName": "Bad_Speculation",
- "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example."
- },
- {
- "BriefDescription": "This category represents fraction of slots wasted due to incorrect speculations. SMT version; use when SMT is enabled and measuring per logical CPU.",
- "MetricExpr": "( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
- "MetricGroup": "TopdownL1_SMT",
- "MetricName": "Bad_Speculation_SMT",
- "PublicDescription": "This category represents fraction of slots wasted due to incorrect speculations. This include slots used to issue uops that do not eventually get retired and slots for which the issue-pipeline was blocked due to recovery from earlier incorrect speculation. For example; wasted work due to miss-predicted branches are categorized under Bad Speculation category. Incorrect data speculation followed by Memory Ordering Nukes is another example. SMT version; use when SMT is enabled and measuring per logical CPU."
- },
- {
- "BriefDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend",
- "MetricConstraint": "NO_NMI_WATCHDOG",
- "MetricExpr": "1 - ( (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * cycles)) + (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * cycles)) + (UOPS_RETIRED.RETIRE_SLOTS / (4 * cycles)) )",
- "MetricGroup": "TopdownL1",
- "MetricName": "Backend_Bound",
- "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound."
- },
- {
- "BriefDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. SMT version; use when SMT is enabled and measuring per logical CPU.",
- "MetricExpr": "1 - ( (IDQ_UOPS_NOT_DELIVERED.CORE / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) + (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) + (UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) )",
- "MetricGroup": "TopdownL1_SMT",
- "MetricName": "Backend_Bound_SMT",
- "PublicDescription": "This category represents fraction of slots where no uops are being delivered due to a lack of required resources for accepting new uops in the Backend. Backend is the portion of the processor core where the out-of-order scheduler dispatches ready uops into their respective execution units; and once completed these uops get retired according to program order. For example; stalls due to data-cache misses or stalls due to the divider unit being overloaded are both categorized under Backend Bound. Backend Bound is further divided into two main categories: Memory Bound and Core Bound. SMT version; use when SMT is enabled and measuring per logical CPU."
- },
- {
- "BriefDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired",
- "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / (4 * cycles)",
- "MetricGroup": "TopdownL1",
- "MetricName": "Retiring",
- "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category. Retiring of 100% would indicate the maximum 4 uops retired per cycle has been achieved. Maximizing Retiring typically increases the Instruction-Per-Cycle metric. Note that a high Retiring value does not necessary mean there is no room for more performance. For example; Microcode assists are categorized under Retiring. They hurt performance and can often be avoided. "
- },
- {
- "BriefDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. SMT version; use when SMT is enabled and measuring per logical CPU.",
- "MetricExpr": "UOPS_RETIRED.RETIRE_SLOTS / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))",
- "MetricGroup": "TopdownL1_SMT",
- "MetricName": "Retiring_SMT",
- "PublicDescription": "This category represents fraction of slots utilized by useful work i.e. issued uops that eventually get retired. Ideally; all pipeline slots would be attributed to the Retiring category. Retiring of 100% would indicate the maximum 4 uops retired per cycle has been achieved. Maximizing Retiring typically increases the Instruction-Per-Cycle metric. Note that a high Retiring value does not necessary mean there is no room for more performance. For example; Microcode assists are categorized under Retiring. They hurt performance and can often be avoided. SMT version; use when SMT is enabled and measuring per logical CPU."
- },
- {
"BriefDescription": "Instructions Per Cycle (per Logical Processor)",
"MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
"MetricGroup": "Summary",
@@ -71,49 +14,79 @@
{
"BriefDescription": "Instruction per taken branch",
"MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_TAKEN",
- "MetricGroup": "Branches;Fetch_BW;PGO",
+ "MetricGroup": "Branches;FetchBW;PGO",
"MetricName": "IpTB"
},
{
"BriefDescription": "Cycles Per Instruction (per Logical Processor)",
- "MetricExpr": "1 / (INST_RETIRED.ANY / cycles)",
- "MetricGroup": "Pipeline;Summary",
+ "MetricExpr": "1 / (INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD)",
+ "MetricGroup": "Pipeline",
"MetricName": "CPI"
},
{
"BriefDescription": "Per-Logical Processor actual clocks when the Logical Processor is active.",
"MetricExpr": "CPU_CLK_UNHALTED.THREAD",
- "MetricGroup": "Summary",
+ "MetricGroup": "Pipeline",
"MetricName": "CLKS"
},
{
- "BriefDescription": "Total issue-pipeline slots (per-Physical Core till ICL; per-Logical Processor ICL onward)",
- "MetricExpr": "4 * cycles",
- "MetricGroup": "TopDownL1",
- "MetricName": "SLOTS"
+ "BriefDescription": "Instructions Per Cycle (per physical core)",
+ "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "SMT;TmaL1",
+ "MetricName": "CoreIPC"
},
{
- "BriefDescription": "Total issue-pipeline slots (per-Physical Core till ICL; per-Logical Processor ICL onward)",
- "MetricExpr": "4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
- "MetricGroup": "TopDownL1_SMT",
- "MetricName": "SLOTS_SMT"
+ "BriefDescription": "Instructions Per Cycle (per physical core)",
+ "MetricExpr": "INST_RETIRED.ANY / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
+ "MetricGroup": "SMT;TmaL1",
+ "MetricName": "CoreIPC_SMT"
+ },
+ {
+ "BriefDescription": "Floating Point Operations Per Cycle",
+ "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "Flops",
+ "MetricName": "FLOPc"
+ },
+ {
+ "BriefDescription": "Floating Point Operations Per Cycle",
+ "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
+ "MetricGroup": "Flops_SMT",
+ "MetricName": "FLOPc_SMT"
+ },
+ {
+ "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
+ "MetricExpr": "UOPS_EXECUTED.THREAD / (( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2 ) if #SMT_on else UOPS_EXECUTED.CORE_CYCLES_GE_1)",
+ "MetricGroup": "Pipeline;PortsUtil",
+ "MetricName": "ILP"
+ },
+ {
+ "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES",
+ "MetricGroup": "BrMispredicts",
+ "MetricName": "IpMispredict"
+ },
+ {
+ "BriefDescription": "Core actual clocks when any Logical Processor is active on the Physical Core",
+ "MetricExpr": "( CPU_CLK_UNHALTED.THREAD_ANY / 2 ) if #SMT_on else CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "SMT",
+ "MetricName": "CORE_CLKS"
},
{
"BriefDescription": "Instructions per Load (lower number means higher occurrence rate)",
"MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_LOADS",
- "MetricGroup": "Instruction_Type",
+ "MetricGroup": "InsType",
"MetricName": "IpLoad"
},
{
"BriefDescription": "Instructions per Store (lower number means higher occurrence rate)",
"MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_STORES",
- "MetricGroup": "Instruction_Type",
+ "MetricGroup": "InsType",
"MetricName": "IpStore"
},
{
"BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)",
"MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES",
- "MetricGroup": "Branches;Instruction_Type",
+ "MetricGroup": "Branches;InsType",
"MetricName": "IpBranch"
},
{
@@ -131,176 +104,122 @@
{
"BriefDescription": "Instructions per Floating Point (FP) Operation (lower number means higher occurrence rate)",
"MetricExpr": "INST_RETIRED.ANY / ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE )",
- "MetricGroup": "FLOPS;FP_Arith;Instruction_Type",
+ "MetricGroup": "Flops;FpArith;InsType",
"MetricName": "IpFLOP"
},
{
- "BriefDescription": "Total number of retired Instructions",
+ "BriefDescription": "Total number of retired Instructions, Sample with: INST_RETIRED.PREC_DIST",
"MetricExpr": "INST_RETIRED.ANY",
- "MetricGroup": "Summary;TopDownL1",
+ "MetricGroup": "Summary;TmaL1",
"MetricName": "Instructions"
},
{
"BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded ICache; or Uop Cache)",
"MetricExpr": "IDQ.DSB_UOPS / (IDQ.DSB_UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS)",
- "MetricGroup": "DSB;Fetch_BW",
+ "MetricGroup": "DSB;FetchBW",
"MetricName": "DSB_Coverage"
},
{
- "BriefDescription": "Instructions Per Cycle (per physical core)",
- "MetricExpr": "INST_RETIRED.ANY / cycles",
- "MetricGroup": "SMT;TopDownL1",
- "MetricName": "CoreIPC"
- },
- {
- "BriefDescription": "Instructions Per Cycle (per physical core)",
- "MetricExpr": "INST_RETIRED.ANY / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
- "MetricGroup": "SMT;TopDownL1",
- "MetricName": "CoreIPC_SMT"
- },
- {
- "BriefDescription": "Floating Point Operations Per Cycle",
- "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / cycles",
- "MetricGroup": "FLOPS",
- "MetricName": "FLOPc"
- },
- {
- "BriefDescription": "Floating Point Operations Per Cycle",
- "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
- "MetricGroup": "FLOPS_SMT",
- "MetricName": "FLOPc_SMT"
- },
- {
- "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
- "MetricExpr": "UOPS_EXECUTED.THREAD / ( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2 )",
- "MetricGroup": "Pipeline;Ports_Utilization",
- "MetricName": "ILP"
- },
- {
- "BriefDescription": "Branch Misprediction Cost: Fraction of TopDown slots wasted per non-speculative branch misprediction (jeclear)",
- "MetricExpr": "( ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / (4 * cycles))) + (4 * ( IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE - ( FRONTEND_RETIRED.LATENCY_GE_1 - FRONTEND_RETIRED.LATENCY_GE_2 ) / (UOPS_RETIRED.RETIRE_SLOTS / UOPS_ISSUED.ANY) ) / (4 * cycles)) * (( INT_MISC.CLEAR_RESTEER_CYCLES + 9 * BACLEARS.ANY ) / cycles) / (4 * ( IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE - ( FRONTEND_RETIRED.LATENCY_GE_1 - FRONTEND_RETIRED.LATENCY_GE_2 ) / (UOPS_RETIRED.RETIRE_SLOTS / UOPS_ISSUED.ANY) ) / (4 * cycles)) ) * (4 * cycles) / BR_MISP_RETIRED.ALL_BRANCHES",
- "MetricGroup": "BrMispredicts",
- "MetricName": "Branch_Misprediction_Cost"
- },
- {
- "BriefDescription": "Branch Misprediction Cost: Fraction of TopDown slots wasted per non-speculative branch misprediction (jeclear)",
- "MetricExpr": "( ((BR_MISP_RETIRED.ALL_BRANCHES / ( BR_MISP_RETIRED.ALL_BRANCHES + MACHINE_CLEARS.COUNT )) * (( UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * ( INT_MISC.RECOVERY_CYCLES_ANY / 2 ) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )))) + (4 * ( IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE - ( FRONTEND_RETIRED.LATENCY_GE_1 - FRONTEND_RETIRED.LATENCY_GE_2 ) / (UOPS_RETIRED.RETIRE_SLOTS / UOPS_ISSUED.ANY) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) * (( INT_MISC.CLEAR_RESTEER_CYCLES + 9 * BACLEARS.ANY ) / cycles) / (4 * ( IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE - ( FRONTEND_RETIRED.LATENCY_GE_1 - FRONTEND_RETIRED.LATENCY_GE_2 ) / (UOPS_RETIRED.RETIRE_SLOTS / UOPS_ISSUED.ANY) ) / (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ))) ) * (4 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )) / BR_MISP_RETIRED.ALL_BRANCHES",
- "MetricGroup": "BrMispredicts_SMT",
- "MetricName": "Branch_Misprediction_Cost_SMT"
- },
- {
- "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear)",
- "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES",
- "MetricGroup": "BrMispredicts",
- "MetricName": "IpMispredict"
- },
- {
- "BriefDescription": "Core actual clocks when any Logical Processor is active on the Physical Core",
- "MetricExpr": "( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) )",
- "MetricGroup": "SMT",
- "MetricName": "CORE_CLKS"
- },
- {
"BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads (in core cycles)",
"MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT )",
- "MetricGroup": "Memory_Bound;Memory_Lat",
+ "MetricGroup": "MemoryBound;MemoryLat",
"MetricName": "Load_Miss_Real_Latency"
},
{
"BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least one such miss. Per-Logical Processor)",
"MetricExpr": "L1D_PEND_MISS.PENDING / L1D_PEND_MISS.PENDING_CYCLES",
- "MetricGroup": "Memory_Bound;Memory_BW",
+ "MetricGroup": "MemoryBound;MemoryBW",
"MetricName": "MLP"
},
{
"BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
"MetricConstraint": "NO_NMI_WATCHDOG",
- "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * cycles )",
- "MetricGroup": "TLB",
+ "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * CORE_CLKS )",
+ "MetricGroup": "MemoryTLB",
"MetricName": "Page_Walks_Utilization"
},
{
- "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
- "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * ( ( CPU_CLK_UNHALTED.THREAD / 2 ) * ( 1 + CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_XCLK ) ) )",
- "MetricGroup": "TLB_SMT",
- "MetricName": "Page_Walks_Utilization_SMT"
- },
- {
"BriefDescription": "Average data fill bandwidth to the L1 data cache [GB / sec]",
"MetricExpr": "64 * L1D.REPLACEMENT / 1000000000 / duration_time",
- "MetricGroup": "Memory_BW",
+ "MetricGroup": "MemoryBW",
"MetricName": "L1D_Cache_Fill_BW"
},
{
"BriefDescription": "Average data fill bandwidth to the L2 cache [GB / sec]",
"MetricExpr": "64 * L2_LINES_IN.ALL / 1000000000 / duration_time",
- "MetricGroup": "Memory_BW",
+ "MetricGroup": "MemoryBW",
"MetricName": "L2_Cache_Fill_BW"
},
{
"BriefDescription": "Average per-core data fill bandwidth to the L3 cache [GB / sec]",
"MetricExpr": "64 * LONGEST_LAT_CACHE.MISS / 1000000000 / duration_time",
- "MetricGroup": "Memory_BW",
+ "MetricGroup": "MemoryBW",
"MetricName": "L3_Cache_Fill_BW"
},
{
- "BriefDescription": "Average per-core data fill bandwidth to the L3 cache [GB / sec]",
+ "BriefDescription": "Average per-core data access bandwidth to the L3 cache [GB / sec]",
"MetricExpr": "64 * OFFCORE_REQUESTS.ALL_REQUESTS / 1000000000 / duration_time",
- "MetricGroup": "Memory_BW;Offcore",
+ "MetricGroup": "MemoryBW;Offcore",
"MetricName": "L3_Cache_Access_BW"
},
{
"BriefDescription": "L1 cache true misses per kilo instruction for retired demand loads",
"MetricExpr": "1000 * MEM_LOAD_RETIRED.L1_MISS / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses",
+ "MetricGroup": "CacheMisses",
"MetricName": "L1MPKI"
},
{
"BriefDescription": "L2 cache true misses per kilo instruction for retired demand loads",
"MetricExpr": "1000 * MEM_LOAD_RETIRED.L2_MISS / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses",
+ "MetricGroup": "CacheMisses",
"MetricName": "L2MPKI"
},
{
"BriefDescription": "L2 cache misses per kilo instruction for all request types (including speculative)",
"MetricExpr": "1000 * L2_RQSTS.MISS / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses;Offcore",
+ "MetricGroup": "CacheMisses;Offcore",
"MetricName": "L2MPKI_All"
},
{
"BriefDescription": "L2 cache hits per kilo instruction for all request types (including speculative)",
"MetricExpr": "1000 * ( L2_RQSTS.REFERENCES - L2_RQSTS.MISS ) / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses",
+ "MetricGroup": "CacheMisses",
"MetricName": "L2HPKI_All"
},
{
"BriefDescription": "L3 cache true misses per kilo instruction for retired demand loads",
"MetricExpr": "1000 * MEM_LOAD_RETIRED.L3_MISS / INST_RETIRED.ANY",
- "MetricGroup": "Cache_Misses",
+ "MetricGroup": "CacheMisses",
"MetricName": "L3MPKI"
},
{
"BriefDescription": "Rate of silent evictions from the L2 cache per Kilo instruction where the evicted lines are dropped (no writeback to L3 or memory)",
"MetricExpr": "1000 * L2_LINES_OUT.SILENT / INST_RETIRED.ANY",
- "MetricGroup": "",
+ "MetricGroup": "L2Evicts;Server",
"MetricName": "L2_Evictions_Silent_PKI"
},
{
"BriefDescription": "Rate of non silent evictions from the L2 cache per Kilo instruction",
"MetricExpr": "1000 * L2_LINES_OUT.NON_SILENT / INST_RETIRED.ANY",
- "MetricGroup": "",
+ "MetricGroup": "L2Evicts;Server",
"MetricName": "L2_Evictions_NonSilent_PKI"
},
{
"BriefDescription": "Average CPU Utilization",
"MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
- "MetricGroup": "Summary",
+ "MetricGroup": "HPC;Summary",
"MetricName": "CPU_Utilization"
},
{
+ "BriefDescription": "Measured Average Frequency for unhalted processors [GHz]",
+ "MetricExpr": "(CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 / duration_time",
+ "MetricGroup": "Summary;Power",
+ "MetricName": "Average_Frequency"
+ },
+ {
"BriefDescription": "Giga Floating Point Operations Per Second",
"MetricExpr": "( ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / 1000000000 ) / duration_time",
- "MetricGroup": "FLOPS;Summary",
+ "MetricGroup": "Flops;HPC",
"MetricName": "GFLOPs"
},
{
@@ -311,44 +230,44 @@
},
{
"BriefDescription": "Fraction of cycles where both hardware Logical Processors were active",
- "MetricExpr": "1 - CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_THREAD_UNHALTED.REF_XCLK_ANY / 2 )",
- "MetricGroup": "SMT;Summary",
+ "MetricExpr": "1 - CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / ( CPU_CLK_UNHALTED.REF_XCLK_ANY / 2 ) if #SMT_on else 0",
+ "MetricGroup": "SMT",
"MetricName": "SMT_2T_Utilization"
},
{
"BriefDescription": "Fraction of cycles spent in the Operating System (OS) Kernel mode",
- "MetricExpr": "CPU_CLK_UNHALTED.THREAD:k / CPU_CLK_UNHALTED.THREAD",
+ "MetricExpr": "CPU_CLK_UNHALTED.THREAD_P:k / CPU_CLK_UNHALTED.THREAD",
"MetricGroup": "OS",
"MetricName": "Kernel_Utilization"
},
{
"BriefDescription": "Average external Memory Bandwidth Use for reads and writes [GB / sec]",
- "MetricExpr": "( ( ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) * 1048576 ) / 1000000000 ) / duration_time",
- "MetricGroup": "Memory_BW;SoC",
+ "MetricExpr": "( 64 * ( uncore_imc@cas_count_read@ + uncore_imc@cas_count_write@ ) / 1000000000 ) / duration_time",
+ "MetricGroup": "HPC;MemoryBW;SoC",
"MetricName": "DRAM_BW_Use"
},
{
"BriefDescription": "Average latency of data read request to external memory (in nanoseconds). Accounts for demand loads and L1/L2 prefetches",
"MetricExpr": "1000000000 * ( cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433@ / cha@event\\=0x35\\,umask\\=0x21\\,config\\=0x40433@ ) / ( cha_0@event\\=0x0@ / duration_time )",
- "MetricGroup": "Memory_Lat;SoC",
+ "MetricGroup": "MemoryLat;SoC",
"MetricName": "MEM_Read_Latency"
},
{
"BriefDescription": "Average number of parallel data read requests to external memory. Accounts for demand loads and L1/L2 prefetches",
"MetricExpr": "cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433@ / cha@event\\=0x36\\,umask\\=0x21\\,config\\=0x40433\\,thresh\\=1@",
- "MetricGroup": "Memory_BW;SoC",
+ "MetricGroup": "MemoryBW;SoC",
"MetricName": "MEM_Parallel_Reads"
},
{
"BriefDescription": "Average IO (network or disk) Bandwidth Use for Writes [GB / sec]",
"MetricExpr": "( UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2 + UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3 ) * 4 / 1000000000 / duration_time",
- "MetricGroup": "IO_BW;SoC;Server",
+ "MetricGroup": "IoBW;SoC;Server",
"MetricName": "IO_Write_BW"
},
{
"BriefDescription": "Average IO (network or disk) Bandwidth Use for Reads [GB / sec]",
"MetricExpr": "( UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2 + UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3 ) * 4 / 1000000000 / duration_time",
- "MetricGroup": "IO_BW;SoC;Server",
+ "MetricGroup": "IoBW;SoC;Server",
"MetricName": "IO_Read_BW"
},
{
@@ -359,7 +278,7 @@
},
{
"BriefDescription": "Instructions per Far Branch ( Far Branches apply upon transition from application to operating system, handling interrupts, exceptions) [lower number means higher occurrence rate]",
- "MetricExpr": "INST_RETIRED.ANY / ( BR_INST_RETIRED.FAR_BRANCH / 2 )",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.FAR_BRANCH:u",
"MetricGroup": "Branches;OS",
"MetricName": "IpFarBranch"
},
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json b/tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json
index b80b5d66385d..0b66e6af8177 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/uncore-memory.json
@@ -65,15 +65,6 @@
"Unit": "iMC"
},
{
- "BriefDescription": "Pre-charge for writes",
- "Counter": "0,1,2,3",
- "EventCode": "0x2",
- "EventName": "UNC_M_PRE_COUNT.WR",
- "PerPkg": "1",
- "UMask": "0x8",
- "Unit": "iMC"
- },
- {
"BriefDescription": "DRAM Page Activate commands sent due to a write request",
"Counter": "0,1,2,3",
"EventCode": "0x1",
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json b/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json
index d7a0270de983..6ed92bc5c129 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/uncore-other.json
@@ -104,15 +104,6 @@
"Unit": "CHA"
},
{
- "BriefDescription": "write requests from remote home agent",
- "Counter": "0,1,2,3",
- "EventCode": "0x50",
- "EventName": "UNC_CHA_REQUESTS.WRITES_REMOTE",
- "PerPkg": "1",
- "UMask": "0x08",
- "Unit": "CHA"
- },
- {
"BriefDescription": "UPI interconnect send bandwidth for payload. Derived from unc_upi_txl_flits.all_data",
"Counter": "0,1,2,3",
"EventCode": "0x2",
@@ -533,7 +524,7 @@
"EventCode": "0x5C",
"EventName": "UNC_CHA_SNOOP_RESP.RSP_WBWB",
"PerPkg": "1",
- "PublicDescription": "Counts when a transaction with the opcode type Rsp*WB Snoop Response was received which indicates which indicates the data was written back to it's home. This is returned when a non-RFO request hits a cacheline in the Modified state. The Cache can either downgrade the cacheline to a S (Shared) or I (Invalid) state depending on how the system has been configured. This response will also be sent when a cache requests E (Exclusive) ownership of a cache line without receiving data, because the cache must acquire ownership.",
+ "PublicDescription": "Counts when a transaction with the opcode type Rsp*WB Snoop Response was received which indicates which indicates the data was written back to it's home. This is returned when a non-RFO request hits a cacheline in the Modified state. The Cache can either downgrade the cacheline to a S (Shared) or I (Invalid) state depending on how the system has been configured. This reponse will also be sent when a cache requests E (Exclusive) ownership of a cache line without receiving data, because the cache must acquire ownership.",
"UMask": "0x10",
"Unit": "CHA"
},
@@ -547,6 +538,98 @@
"Unit": "IIO"
},
{
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xC2",
+ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART0",
+ "FCMask": "0x4",
+ "PerPkg": "1",
+ "PortMask": "0x01",
+ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0",
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 1",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xC2",
+ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART1",
+ "FCMask": "0x4",
+ "PerPkg": "1",
+ "PortMask": "0x02",
+ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 1",
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xC2",
+ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART2",
+ "FCMask": "0x4",
+ "PerPkg": "1",
+ "PortMask": "0x04",
+ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 2",
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 3",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xC2",
+ "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART3",
+ "FCMask": "0x4",
+ "PerPkg": "1",
+ "PortMask": "0x08",
+ "PublicDescription": "PCIe Completion Buffer Inserts of completions with data: Part 3",
+ "UMask": "0x03",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 0",
+ "Counter": "2,3",
+ "EventCode": "0xD5",
+ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART0",
+ "FCMask": "0x04",
+ "PerPkg": "1",
+ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 0",
+ "UMask": "0x01",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 1",
+ "Counter": "2,3",
+ "EventCode": "0xD5",
+ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART1",
+ "FCMask": "0x04",
+ "PerPkg": "1",
+ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 1",
+ "UMask": "0x02",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 2",
+ "Counter": "2,3",
+ "EventCode": "0xD5",
+ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART2",
+ "FCMask": "0x04",
+ "PerPkg": "1",
+ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 2",
+ "UMask": "0x04",
+ "Unit": "IIO"
+ },
+ {
+ "BriefDescription": "PCIe Completion Buffer occupancy of completions with data: Part 3",
+ "Counter": "2,3",
+ "EventCode": "0xD5",
+ "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART3",
+ "FCMask": "0x04",
+ "PerPkg": "1",
+ "PublicDescription": "PCIe Completion Buffer occupancy of completions with data: Part 3",
+ "UMask": "0x08",
+ "Unit": "IIO"
+ },
+ {
"BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part0",
"Counter": "2,3",
"EventCode": "0xC0",
@@ -1219,6 +1302,64 @@
"Unit": "IIO"
},
{
+ "BriefDescription": "Total IRP occupancy of inbound read and write requests.",
+ "Counter": "0,1",
+ "EventCode": "0xF",
+ "EventName": "UNC_I_CACHE_TOTAL_OCCUPANCY.MEM",
+ "PerPkg": "1",
+ "PublicDescription": "Total IRP occupancy of inbound read and write requests. This is effectively the sum of read occupancy and write occupancy.",
+ "UMask": "0x4",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "PCIITOM request issued by the IRP unit to the mesh with the intention of writing a full cacheline.",
+ "Counter": "0,1",
+ "EventCode": "0x10",
+ "EventName": "UNC_I_COHERENT_OPS.PCITOM",
+ "PerPkg": "1",
+ "PublicDescription": "PCIITOM request issued by the IRP unit to the mesh with the intention of writing a full cacheline to coherent memory, without a RFO. PCIITOM is a speculative Invalidate to Modified command that requests ownership of the cacheline and does not move data from the mesh to IRP cache.",
+ "UMask": "0x10",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "RFO request issued by the IRP unit to the mesh with the intention of writing a partial cacheline.",
+ "Counter": "0,1",
+ "EventCode": "0x10",
+ "EventName": "UNC_I_COHERENT_OPS.RFO",
+ "PerPkg": "1",
+ "PublicDescription": "RFO request issued by the IRP unit to the mesh with the intention of writing a partial cacheline to coherent memory. RFO is a Read For Ownership command that requests ownership of the cacheline and moves data from the mesh to IRP cache.",
+ "UMask": "0x8",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "Inbound read requests received by the IRP and inserted into the FAF queue.",
+ "Counter": "0,1",
+ "EventCode": "0x18",
+ "EventName": "UNC_I_FAF_INSERTS",
+ "PerPkg": "1",
+ "PublicDescription": "Inbound read requests to coherent memory, received by the IRP and inserted into the Fire and Forget queue (FAF), a queue used for processing inbound reads in the IRP.",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "Occupancy of the IRP FAF queue.",
+ "Counter": "0,1",
+ "EventCode": "0x19",
+ "EventName": "UNC_I_FAF_OCCUPANCY",
+ "PerPkg": "1",
+ "PublicDescription": "Occupancy of the IRP Fire and Forget (FAF) queue, a queue used for processing inbound reads in the IRP.",
+ "Unit": "IRP"
+ },
+ {
+ "BriefDescription": "Inbound write (fast path) requests received by the IRP.",
+ "Counter": "0,1",
+ "EventCode": "0x11",
+ "EventName": "UNC_I_TRANSACTIONS.WR_PREF",
+ "PerPkg": "1",
+ "PublicDescription": "Inbound write (fast path) requests to coherent memory, received by the IRP resulting in write ownership requests issued by IRP to the mesh.",
+ "UMask": "0x8",
+ "Unit": "IRP"
+ },
+ {
"BriefDescription": "Traffic in which the M2M to iMC Bypass was not taken",
"Counter": "0,1,2,3",
"EventCode": "0x22",
@@ -1466,7 +1607,7 @@
"EventCode": "0x57",
"EventName": "UNC_M2M_PREFCAM_INSERTS",
"PerPkg": "1",
- "PublicDescription": "Counts when the M2M (Mesh to Memory) receives a prefetch request and inserts it into its outstanding prefetch queue. Explanatory Side Note: the prefect queue is made from CAM: Content Addressable Memory",
+ "PublicDescription": "Counts when the M2M (Mesh to Memory) recieves a prefetch request and inserts it into its outstanding prefetch queue. Explanatory Side Note: the prefect queue is made from CAM: Content Addressable Memory",
"Unit": "M2M"
},
{
@@ -1605,7 +1746,7 @@
"EventCode": "0x31",
"EventName": "UNC_UPI_RxL_BYPASSED.SLOT0",
"PerPkg": "1",
- "PublicDescription": "Counts incoming FLITs (FLow control unITs) which bypassed the slot0 RxQ buffer (Receive Queue) and passed directly to the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transferred, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
+ "PublicDescription": "Counts incoming FLITs (FLow control unITs) which bypassed the slot0 RxQ buffer (Receive Queue) and passed directly to the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transfered, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
"UMask": "0x1",
"Unit": "UPI LL"
},
@@ -1615,17 +1756,17 @@
"EventCode": "0x31",
"EventName": "UNC_UPI_RxL_BYPASSED.SLOT1",
"PerPkg": "1",
- "PublicDescription": "Counts incoming FLITs (FLow control unITs) which bypassed the slot1 RxQ buffer (Receive Queue) and passed directly across the BGF and into the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transferred, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
+ "PublicDescription": "Counts incoming FLITs (FLow control unITs) which bypassed the slot1 RxQ buffer (Receive Queue) and passed directly across the BGF and into the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transfered, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
"UMask": "0x2",
"Unit": "UPI LL"
},
{
- "BriefDescription": "FLITs received which bypassed the Slot0 Receive Buffer",
+ "BriefDescription": "FLITs received which bypassed the Slot0 Recieve Buffer",
"Counter": "0,1,2,3",
"EventCode": "0x31",
"EventName": "UNC_UPI_RxL_BYPASSED.SLOT2",
"PerPkg": "1",
- "PublicDescription": "Counts incoming FLITs (FLow control unITs) which bypassed the slot2 RxQ buffer (Receive Queue) and passed directly to the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transferred, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
+ "PublicDescription": "Counts incoming FLITs (FLow control unITs) whcih bypassed the slot2 RxQ buffer (Receive Queue) and passed directly to the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of FLITs transfered, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
"UMask": "0x4",
"Unit": "UPI LL"
},
diff --git a/tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json b/tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json
index bbeee1058096..792ca39f013a 100644
--- a/tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json
+++ b/tools/perf/pmu-events/arch/x86/skylakex/virtual-memory.json
@@ -1,103 +1,74 @@
[
{
- "BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.STLB_HIT",
- "SampleAfterValue": "100003",
- "UMask": "0x20"
- },
- {
- "BriefDescription": "Store misses in all DTLB levels that cause page walks",
+ "BriefDescription": "Load misses in all DTLB levels that cause page walks",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
- "PublicDescription": "Counts demand data stores that caused a page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels, but the walk need not have completed.",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
+ "PublicDescription": "Counts demand data loads that caused a page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels, but the walk need not have completed.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
- "BriefDescription": "Page walk completed due to a demand data store to a 2M/4M page",
+ "BriefDescription": "Loads that miss the DTLB and hit the STLB.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
- "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.",
- "SampleAfterValue": "100003",
- "UMask": "0x4"
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
},
{
- "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake.",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a load. EPT page walk duration are excluded in Skylake.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_PENDING",
- "PublicDescription": "Counts 1 per cycle for each PMH (Page Miss Handler) that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake michroarchitecture.",
+ "CounterMask": "1",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_ACTIVE",
+ "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a load.",
"SampleAfterValue": "100003",
"UMask": "0x10"
},
{
- "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
- "PublicDescription": "Counts completed page walks (4K page size) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.",
- "SampleAfterValue": "100003",
- "UMask": "0x2"
- },
- {
- "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xAE",
- "EventName": "ITLB.ITLB_FLUSH",
- "PublicDescription": "Counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
- "SampleAfterValue": "100007",
- "UMask": "0x1"
- },
- {
- "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake.",
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_ACTIVE",
- "PublicDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake microarchitecture.",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data loads. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0x10"
+ "UMask": "0xe"
},
{
- "BriefDescription": "Loads that miss the DTLB and hit the STLB.",
+ "BriefDescription": "Page walk completed due to a demand data load to a 1G page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
- "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
+ "PublicDescription": "Counts completed page walks (1G sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "2000003",
- "UMask": "0x20"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake.",
+ "BriefDescription": "Page walk completed due to a demand data load to a 2M/4M page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
- "PublicDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake microarchitecture.",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "PublicDescription": "Counts completed page walks (2M/4M sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "UMask": "0x4"
},
{
- "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "BriefDescription": "Page walk completed due to a demand data load to a 4K page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xBD",
- "EventName": "TLB_FLUSH.DTLB_THREAD",
- "PublicDescription": "Counts the number of DTLB flush attempts of the thread-specific entries.",
- "SampleAfterValue": "100007",
- "UMask": "0x1"
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "PublicDescription": "Counts completed page walks (4K sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
},
{
"BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a load. EPT page walk duration are excluded in Skylake.",
@@ -110,23 +81,12 @@
"UMask": "0x10"
},
{
- "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store. EPT page walk duration are excluded in Skylake.",
+ "BriefDescription": "Store misses in all DTLB levels that cause page walks",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
"EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_ACTIVE",
- "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a store.",
- "SampleAfterValue": "100003",
- "UMask": "0x10"
- },
- {
- "BriefDescription": "Misses at all ITLB levels that cause page walks",
- "Counter": "0,1,2,3",
- "CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
- "PublicDescription": "Counts page walks of any page size (4K/2M/4M/1G) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB, but the walk need not have completed.",
+ "EventName": "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK",
+ "PublicDescription": "Counts demand data stores that caused a page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels, but the walk need not have completed.",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
@@ -141,125 +101,135 @@
"UMask": "0x20"
},
{
- "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store. EPT page walk duration are excluded in Skylake.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
"EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
- "PublicDescription": "Counts demand data stores that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
+ "EventName": "DTLB_STORE_MISSES.WALK_ACTIVE",
+ "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a store.",
"SampleAfterValue": "100003",
- "UMask": "0xe"
+ "UMask": "0x10"
},
{
- "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)",
+ "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
- "PublicDescription": "Counts demand data loads that caused a completed page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels. The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data stores. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
"UMask": "0xe"
},
{
- "BriefDescription": "Page walk completed due to a demand data store to a 4K page",
+ "BriefDescription": "Page walk completed due to a demand data store to a 1G page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
- "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
+ "PublicDescription": "Counts completed page walks (1G sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0x2"
+ "UMask": "0x8"
},
{
- "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (1G)",
+ "BriefDescription": "Page walk completed due to a demand data store to a 2M/4M page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
- "PublicDescription": "Counts store misses in all DTLB levels that cause a completed page walk (1G page size). The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "PublicDescription": "Counts completed page walks (2M/4M sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0x8"
+ "UMask": "0x4"
},
{
- "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)",
+ "BriefDescription": "Page walk completed due to a demand data store to a 4K page",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x85",
- "EventName": "ITLB_MISSES.WALK_COMPLETED",
- "PublicDescription": "Counts completed page walks (2M and 4M page sizes) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB. The page walk can end with or without a fault.",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "PublicDescription": "Counts completed page walks (4K sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0xe"
+ "UMask": "0x2"
},
{
- "BriefDescription": "Page walk completed due to a demand data load to a 4K page",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
- "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
+ "PublicDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for a store. EPT page walk duration are excluded in Skylake microarchitecture.",
"SampleAfterValue": "2000003",
- "UMask": "0x2"
+ "UMask": "0x10"
},
{
- "BriefDescription": "Page walk completed due to a demand data load to a 2M/4M page",
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a EPT (Extended Page Table) walk for any request type.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
- "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x4f",
+ "EventName": "EPT.WALK_PENDING",
+ "PublicDescription": "Counts cycles for each PMH (Page Miss Handler) that is busy with an EPT (Extended Page Table) walk for any request type.",
"SampleAfterValue": "2000003",
- "UMask": "0x4"
+ "UMask": "0x10"
},
{
- "BriefDescription": "Load misses in all DTLB levels that cause page walks",
+ "BriefDescription": "Flushing of the Instruction TLB (ITLB) pages, includes 4k/2M/4M pages.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK",
- "PublicDescription": "Counts demand data loads that caused a page walk of any page size (4K/2M/4M/1G). This implies it missed in all TLB levels, but the walk need not have completed.",
- "SampleAfterValue": "100003",
+ "EventCode": "0xAE",
+ "EventName": "ITLB.ITLB_FLUSH",
+ "PublicDescription": "Counts the number of flushes of the big or small ITLB pages. Counting include both TLB Flush (covering all sets) and TLB Set Clear (set-specific).",
+ "SampleAfterValue": "100007",
"UMask": "0x1"
},
{
- "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a EPT (Extended Page Table) walk for any request type.",
+ "BriefDescription": "Misses at all ITLB levels that cause page walks",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x4F",
- "EventName": "EPT.WALK_PENDING",
- "PublicDescription": "Counts cycles for each PMH (Page Miss Handler) that is busy with an EPT (Extended Page Table) walk for any request type.",
- "SampleAfterValue": "2000003",
- "UMask": "0x10"
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.MISS_CAUSES_A_WALK",
+ "PublicDescription": "Counts page walks of any page size (4K/2M/4M/1G) caused by a code fetch. This implies it missed in the ITLB and further levels of TLB, but the walk need not have completed.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
},
{
- "BriefDescription": "STLB flush attempts",
+ "BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0xBD",
- "EventName": "TLB_FLUSH.STLB_ANY",
- "PublicDescription": "Counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, etc.).",
- "SampleAfterValue": "100007",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "SampleAfterValue": "100003",
"UMask": "0x20"
},
{
- "BriefDescription": "Page walk completed due to a demand data load to a 1G page",
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G",
- "PublicDescription": "Counts page walks completed due to demand data loads whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
- "SampleAfterValue": "2000003",
- "UMask": "0x8"
+ "CounterMask": "1",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_ACTIVE",
+ "PublicDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request. EPT page walk duration are excluded in Skylake microarchitecture.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
},
{
- "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a load. EPT page walk duration are excluded in Skylake.",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "CounterMask": "1",
- "EventCode": "0x08",
- "EventName": "DTLB_LOAD_MISSES.WALK_ACTIVE",
- "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a load.",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0x10"
+ "UMask": "0xe"
+ },
+ {
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (1G)",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_1G",
+ "PublicDescription": "Counts completed page walks (1G page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
},
{
"BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
@@ -267,18 +237,48 @@
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x85",
"EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
- "PublicDescription": "Counts code misses in all ITLB levels that caused a completed page walk (2M and 4M page sizes). The page walk can end with or without a fault.",
+ "PublicDescription": "Counts completed page walks (2M/4M page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
"UMask": "0x4"
},
{
- "BriefDescription": "Page walk completed due to a demand data store to a 1G page",
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
- "EventCode": "0x49",
- "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G",
- "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 1G pages. The page walks can end with or without a page fault.",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "PublicDescription": "Counts completed page walks (4K page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
"SampleAfterValue": "100003",
- "UMask": "0x8"
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts 1 per cycle for each PMH that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake.",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_PENDING",
+ "PublicDescription": "Counts 1 per cycle for each PMH (Page Miss Handler) that is busy with a page walk for an instruction fetch request. EPT page walk duration are excluded in Skylake michroarchitecture.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xBD",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "PublicDescription": "Counts the number of DTLB flush attempts of the thread-specific entries.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "STLB flush attempts",
+ "Counter": "0,1,2,3",
+ "CounterHTOff": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xBD",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "PublicDescription": "Counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, etc.).",
+ "SampleAfterValue": "100007",
+ "UMask": "0x20"
}
] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/cache.json b/tools/perf/pmu-events/arch/x86/tigerlake/cache.json
new file mode 100644
index 000000000000..8d767b8932b0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tigerlake/cache.json
@@ -0,0 +1,595 @@
+[
+ {
+ "BriefDescription": "Counts the number of cache lines replaced in L1 data cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x51",
+ "EventName": "L1D.REPLACEMENT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of cycles a demand request has waited due to L1D Fill Buffer (FB) unavailability.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.FB_FULL",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts number of cycles a demand request has waited due to L1D Fill Buffer (FB) unavailablability. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of phases a demand request has waited due to L1D Fill Buffer (FB) unavailablability.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EdgeDetect": "1",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.FB_FULL_PERIODS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts number of phases a demand request has waited due to L1D Fill Buffer (FB) unavailablability. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of cycles a demand request has waited due to L1D due to lack of L2 resources.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.L2_STALL",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts number of cycles a demand request has waited due to L1D due to lack of L2 resources. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of L1D misses that are outstanding",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.PENDING",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts number of L1D misses that are outstanding in each cycle, that is each cycle the number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch. Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles with L1D load Misses outstanding.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x48",
+ "EventName": "L1D_PEND_MISS.PENDING_CYCLES",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts duration of L1D miss outstanding in cycles.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "L2 cache lines filling L2",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xf1",
+ "EventName": "L2_LINES_IN.ALL",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1f"
+ },
+ {
+ "BriefDescription": "Modified cache lines that are evicted by L2 cache when triggered by an L2 cache fill.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xf2",
+ "EventName": "L2_LINES_OUT.NON_SILENT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of lines that are evicted by L2 cache when triggered by an L2 cache fill. Those lines are in Modified state. Modified lines are written back to L3",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Non-modified cache lines that are silently dropped by L2 cache when triggered by an L2 cache fill.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xf2",
+ "EventName": "L2_LINES_OUT.SILENT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of lines that are silently dropped by L2 cache when triggered by an L2 cache fill. These lines are typically in Shared or Exclusive state. A non-threaded event.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "L2 code requests",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_CODE_RD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of L2 code requests.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe4"
+ },
+ {
+ "BriefDescription": "RFO requests to L2 cache",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.ALL_RFO",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xe2"
+ },
+ {
+ "BriefDescription": "L2 cache hits when fetching instructions, code reads.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_HIT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc4"
+ },
+ {
+ "BriefDescription": "L2 cache misses when fetching instructions",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.CODE_RD_MISS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts L2 cache misses when fetching instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x24"
+ },
+ {
+ "BriefDescription": "All requests that miss L2 cache",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.MISS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts all requests that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x3f"
+ },
+ {
+ "BriefDescription": "RFO requests that hit L2 cache",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.RFO_HIT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc2"
+ },
+ {
+ "BriefDescription": "RFO requests that miss L2 cache",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.RFO_MISS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x22"
+ },
+ {
+ "BriefDescription": "SW prefetch requests that hit L2 cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.SWPF_HIT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts Software prefetch requests that hit the L2 cache. This event accounts for PREFETCHNTA and PREFETCHT0/1/2 instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0xc8"
+ },
+ {
+ "BriefDescription": "SW prefetch requests that miss L2 cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x24",
+ "EventName": "L2_RQSTS.SWPF_MISS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts Software prefetch requests that miss the L2 cache. This event accounts for PREFETCHNTA and PREFETCHT0/1/2 instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x28"
+ },
+ {
+ "BriefDescription": "L2 writebacks that access L2 cache",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xf0",
+ "EventName": "L2_TRANS.L2_WB",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts L2 writebacks that access L2 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Cycles when L1D is locked",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x63",
+ "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "This event counts the number of cycles when the L1D is locked. It is a superset of the 0x1 mask (BUS_LOCK_CLOCKS.BUS_LOCK_DURATION).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "All retired load instructions.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_INST_RETIRED.ALL_LOADS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts all retired load instructions. This event accounts for SW prefetch instructions for loads.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x81"
+ },
+ {
+ "BriefDescription": "All retired store instructions.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_INST_RETIRED.ALL_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts all retired store instructions. This event account for SW prefetch instructions and PREFETCHW instruction for stores.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x82"
+ },
+ {
+ "BriefDescription": "Retired load instructions with locked access.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_INST_RETIRED.LOCK_LOADS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions with locked access.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x21"
+ },
+ {
+ "BriefDescription": "Retired load instructions that split across a cacheline boundary.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_INST_RETIRED.SPLIT_LOADS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x41"
+ },
+ {
+ "BriefDescription": "Retired store instructions that split across a cacheline boundary.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_INST_RETIRED.SPLIT_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x42"
+ },
+ {
+ "BriefDescription": "Retired load instructions that miss the STLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions that true miss the STLB.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x11"
+ },
+ {
+ "BriefDescription": "Retired store instructions that miss the STLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd0",
+ "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES",
+ "L1_Hit_Indication": "1",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired store instructions that true miss the STLB.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x12"
+ },
+ {
+ "BriefDescription": "TBD",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_FWD",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "20011",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Retired load instructions whose data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the retired load instructions whose data sources were L3 hit and cross-core snoop missed in on-pkg core cache.",
+ "SampleAfterValue": "20011",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired load instructions whose data sources were hits in L3 without snoops required",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions whose data sources were hits in L3 without snoops required.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "TBD",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd2",
+ "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NO_FWD",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "20011",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of completed demand load requests that missed the L1, but hit the FB(fill buffer), because a preceding miss to the same cacheline initiated the line to be brought into L1, but data is not yet ready in L1.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_RETIRED.FB_HIT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Retired load instructions with L1 cache hits as data sources",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_RETIRED.L1_HIT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired load instructions missed L1 cache as data sources",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_RETIRED.L1_MISS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L1 cache.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Retired load instructions with L2 cache hits as data sources",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_RETIRED.L2_HIT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions with L2 cache hits as data sources.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Retired load instructions missed L2 cache as data sources",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_RETIRED.L2_MISS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions missed L2 cache as data sources.",
+ "SampleAfterValue": "100021",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Retired load instructions with L3 cache hits as data sources",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_RETIRED.L3_HIT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L3 cache.",
+ "SampleAfterValue": "100021",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Retired load instructions missed L3 cache as data sources",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "Data_LA": "1",
+ "EventCode": "0xd1",
+ "EventName": "MEM_LOAD_RETIRED.L3_MISS",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Demand and prefetch data reads",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xb0",
+ "EventName": "OFFCORE_REQUESTS.ALL_DATA_RD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Any memory transaction that reached the SQ.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xb0",
+ "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts memory transactions reached the super queue including requests initiated by the core, all L3 prefetches, page walks, etc..",
+ "SampleAfterValue": "100003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Demand Data Read requests sent to uncore",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xb0",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Demand RFO requests including regular RFOs, locks, ItoM",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xb0",
+ "EventName": "OFFCORE_REQUESTS.DEMAND_RFO",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the demand RFO (read for ownership) requests including regular RFOs, locks, ItoM.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Offcore outstanding cacheable Core Data Read transactions in SuperQueue (SQ), queue to uncore",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of offcore outstanding cacheable Core Data Read transactions in the super queue every cycle. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Cycles when offcore outstanding cacheable Core Data Read transactions are present in SuperQueue (SQ), queue to uncore.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles when offcore outstanding cacheable Core Data Read transactions are present in the super queue. A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation). See corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Cycles when offcore outstanding Demand Data Read transactions are present in SuperQueue (SQ), queue to uncore",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles when offcore outstanding Demand Data Read transactions are present in the super queue (SQ). A transaction is considered to be in the Offcore outstanding state between L2 miss and transaction completion sent to requestor (SQ de-allocation).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles with offcore outstanding demand rfo reads transactions in SuperQueue (SQ), queue to uncore.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of offcore outstanding demand rfo Reads transactions in the super queue every cycle. The 'Offcore outstanding' state of the transaction lasts from the L2 miss until the sending transaction completion to requestor (SQ deallocation). See the corresponding Umask under OFFCORE_REQUESTS.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Demand Data Read transactions pending for off-core. Highly correlated.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of off-core outstanding Demand Data Read transactions every cycle. A transaction is considered to be in the Off-core outstanding state between L2 cache miss and data-return to the core.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles with at least 6 offcore outstanding Demand Data Read transactions in uncore queue.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "6",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD_GE_6",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Store Read transactions pending for off-core. Highly correlated.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x60",
+ "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of off-core outstanding read-for-ownership (RFO) store transactions every cycle. An RFO transaction is considered to be in the Off-core outstanding state between L2 cache miss and transaction completion.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Cycles the superQ cannot take any more entries.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xf4",
+ "EventName": "SQ_MISC.SQ_FULL",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the cycles for which the thread is active and the superQ cannot take any more entries.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/floating-point.json b/tools/perf/pmu-events/arch/x86/tigerlake/floating-point.json
new file mode 100644
index 000000000000..402f01851313
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tigerlake/floating-point.json
@@ -0,0 +1,94 @@
+[
+ {
+ "BriefDescription": "Counts all microcode FP assists.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc1",
+ "EventName": "ASSISTS.FP",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts all microcode Floating Point assists.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc7",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc7",
+ "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc7",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Counts number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc7",
+ "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "100003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc7",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "100003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc7",
+ "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "100003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Counts number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc7",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT RCP FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc7",
+ "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/frontend.json b/tools/perf/pmu-events/arch/x86/tigerlake/frontend.json
new file mode 100644
index 000000000000..24c736ac8f8e
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tigerlake/frontend.json
@@ -0,0 +1,463 @@
+[
+ {
+ "BriefDescription": "Counts the total number when the front end is resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xe6",
+ "EventName": "BACLEARS.ANY",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of times the front-end is resteered when it finds a branch instruction in a fetch line. This occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Decode Stream Buffer (DSB)-to-MITE transitions count.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EdgeDetect": "1",
+ "EventCode": "0xab",
+ "EventName": "DSB2MITE_SWITCHES.COUNT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of Decode Stream Buffer (DSB a.k.a. Uop Cache)-to-MITE speculative transitions.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "DSB-to-MITE switch true penalty cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xab",
+ "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Decode Stream Buffer (DSB) is a Uop-cache that holds translations of previously fetched instructions that were decoded by the legacy x86 decode pipeline (MITE). This event counts fetch penalty cycles when a transition occurs from DSB to MITE.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Retired Instructions who experienced DSB miss.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.DSB_MISS",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x11",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired Instructions who experienced iTLB true miss.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.ITLB_MISS",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x14",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired Instructions that experienced iTLB (Instruction TLB) true miss.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.L1I_MISS",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x12",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired Instructions who experienced Instruction L1 Cache true miss.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.L2_MISS",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x13",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired Instructions who experienced Instruction L2 Cache true miss.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions after front-end starvation of at least 1 cycle",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_1",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x500106",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of at least 1 cycle which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_128",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x508006",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_16",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x501006",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions after front-end starvation of at least 2 cycles",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x500206",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of at least 2 cycles which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_256",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x510006",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x100206",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_32",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x502006",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_4",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x500406",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_512",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x520006",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_64",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x504006",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.LATENCY_GE_8",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x500806",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc6",
+ "EventName": "FRONTEND_RETIRED.STLB_MISS",
+ "MSRIndex": "0x3F7",
+ "MSRValue": "0x15",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache miss.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x80",
+ "EventName": "ICACHE_16B.IFDATA_STALL",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles where a code line fetch is stalled due to an L1 instruction cache miss. The legacy decode pipeline works at a 16 Byte granularity.",
+ "SampleAfterValue": "500009",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x83",
+ "EventName": "ICACHE_64B.IFTAG_HIT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts instruction fetch tag lookups that hit in the instruction cache (L1I). Counts at 64-byte cache-line granularity. Accounts for both cacheable and uncacheable accesses.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x83",
+ "EventName": "ICACHE_64B.IFTAG_MISS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts instruction fetch tag lookups that miss in the instruction cache (L1I). Counts at 64-byte cache-line granularity. Accounts for both cacheable and uncacheable accesses.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x83",
+ "EventName": "ICACHE_64B.IFTAG_STALL",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles where a code fetch is stalled due to L1 instruction cache tag miss.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.DSB_CYCLES_ANY",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Cycles DSB is delivering optimal number of Uops",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "5",
+ "EventCode": "0x79",
+ "EventName": "IDQ.DSB_CYCLES_OK",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles where optimal number of uops was delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x79",
+ "EventName": "IDQ.DSB_UOPS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Cycles MITE is delivering any Uop",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MITE_CYCLES_ANY",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Cycles MITE is delivering optimal number of Uops",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "5",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MITE_CYCLES_OK",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of cycles where optimal number of uops was delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MITE_UOPS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Cycles when uops are being delivered to IDQ while MS is busy",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MS_CYCLES_ANY",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x30"
+ },
+ {
+ "BriefDescription": "Number of switches from DSB or MITE to the MS",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EdgeDetect": "1",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MS_SWITCHES",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x30"
+ },
+ {
+ "BriefDescription": "Uops delivered to IDQ while MS is busy",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x79",
+ "EventName": "IDQ.MS_UOPS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS). Any instruction over 4 uops will be delivered by the MS. Some instructions such as transcendentals may additionally generate uops from the MS.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x30"
+ },
+ {
+ "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x9c",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "5",
+ "EventCode": "0x9c",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x9c",
+ "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK",
+ "Invert": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/memory.json b/tools/perf/pmu-events/arch/x86/tigerlake/memory.json
new file mode 100644
index 000000000000..0948de0b160c
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tigerlake/memory.json
@@ -0,0 +1,295 @@
+[
+ {
+ "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "6",
+ "EventCode": "0xa3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x6"
+ },
+ {
+ "BriefDescription": "Number of machine clears due to memory ordering conflicts.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc3",
+ "EventName": "MACHINE_CLEARS.MEMORY_ORDERING",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of Machine Clears detected dye to memory ordering. Memory Ordering Machine Clears may apply when a memory read may not conform to the memory ordering rules of the x86 architecture",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x80",
+ "PEBS": "2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "1009",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x10",
+ "PEBS": "2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "20011",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x100",
+ "PEBS": "2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "503",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x20",
+ "PEBS": "2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "100007",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x4",
+ "PEBS": "2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "100003",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x200",
+ "PEBS": "2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "101",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x40",
+ "PEBS": "2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "2003",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "Data_LA": "1",
+ "EventCode": "0xcd",
+ "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8",
+ "MSRIndex": "0x3F6",
+ "MSRValue": "0x8",
+ "PEBS": "2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.",
+ "SampleAfterValue": "50021",
+ "TakenAlone": "1",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Demand Data Read requests who miss L3 cache",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xb0",
+ "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Demand Data Read requests who miss L3 cache.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc9",
+ "EventName": "RTM_RETIRED.ABORTED",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of times RTM abort was triggered.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc9",
+ "EventName": "RTM_RETIRED.ABORTED_EVENTS",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc9",
+ "EventName": "RTM_RETIRED.ABORTED_MEM",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc9",
+ "EventName": "RTM_RETIRED.ABORTED_MEMTYPE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of times an RTM execution aborted due to incompatible memory type.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc9",
+ "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of times an RTM execution aborted due to HLE-unfriendly instructions.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution successfully committed",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc9",
+ "EventName": "RTM_RETIRED.COMMIT",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of times RTM commit succeeded.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of times an RTM execution started.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc9",
+ "EventName": "RTM_RETIRED.START",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of times we entered an RTM region. Does not count nested transactions.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of times a class of instructions that may cause a transactional abort was executed inside a transactional region",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts Unfriendly TSX abort triggered by a vzeroupper instruction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of times an instruction execution caused the transactional nest count supported to be exceeded",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5d",
+ "EventName": "TX_EXEC.MISC3",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts Unfriendly TSX abort triggered by a nest count that is too deep.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Speculatively counts the number of TSX aborts due to a data capacity limitation for transactional reads",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_CAPACITY_READ",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Speculatively counts the number of Transactional Synchronization Extensions (TSX) aborts due to a data capacity limitation for transactional reads",
+ "SampleAfterValue": "100003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Speculatively counts the number of TSX aborts due to a data capacity limitation for transactional writes.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_CAPACITY_WRITE",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Speculatively counts the number of Transactional Synchronization Extensions (TSX) aborts due to a data capacity limitation for transactional writes.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x54",
+ "EventName": "TX_MEM.ABORT_CONFLICT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of times a TSX line had a cache conflict.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/other.json b/tools/perf/pmu-events/arch/x86/tigerlake/other.json
new file mode 100644
index 000000000000..b1143fe74246
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tigerlake/other.json
@@ -0,0 +1,189 @@
+[
+ {
+ "BriefDescription": "Number of occurrences where a microcode assist is invoked by hardware.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc1",
+ "EventName": "ASSISTS.ANY",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of occurrences where a microcode assist is invoked by hardware Examples include AD (page Access Dirty), FP and AVX related assists.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x7"
+ },
+ {
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the Non-AVX turbo schedule.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.LVL0_TURBO_LICENSE",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts Core cycles where the core was running with power-delivery for baseline license level 0. This includes non-AVX codes, SSE, AVX 128-bit, and low-current AVX 256-bit codes.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x7"
+ },
+ {
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX2 turbo schedule.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.LVL1_TURBO_LICENSE",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts Core cycles where the core was running with power-delivery for license level 1. This includes high current AVX 256-bit instructions as well as low current AVX 512-bit instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x18"
+ },
+ {
+ "BriefDescription": "Core cycles where the core was running in a manner where Turbo may be clipped to the AVX512 turbo schedule.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x28",
+ "EventName": "CORE_POWER.LVL2_TURBO_LICENSE",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Core cycles where the core was running with power-delivery for license level 2 (introduced in Skylake Server microarchtecture). This includes high current AVX 512-bit instructions.",
+ "SampleAfterValue": "200003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Counts demand data reads that hit a cacheline in the L3 where a snoop hit in another cores caches, data forwarding is required as the data is modified.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x10003C0001",
+ "Offcore": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x8003C0001",
+ "Offcore": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that hit a cacheline in the L3 where a snoop hit in another cores caches, data forwarding is required as the data is modified.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_HITM",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x10003C0002",
+ "Offcore": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts streaming stores that have any type of response.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xB7, 0xBB",
+ "EventName": "OCR.STREAMING_WR.ANY_RESPONSE",
+ "MSRIndex": "0x1a6,0x1a7",
+ "MSRValue": "0x10800",
+ "Offcore": "1",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Offcore response can be programmed only with a specific pair of event select and counter MSR, and with specific event codes and predefine mask bit value in a dedicated MSR to specify attributes of the offcore transaction.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of PREFETCHNTA instructions executed.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.NTA",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of PREFETCHNTA instructions executed.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of PREFETCHW instructions executed.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.PREFETCHW",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of PREFETCHW instructions executed.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Number of PREFETCHT0 instructions executed.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.T0",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of PREFETCHT0 instructions executed.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x32",
+ "EventName": "SW_PREFETCH_ACCESS.T1_T2",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of PREFETCHT1 or PREFETCHT2 instructions executed.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "TMA slots where no uops were being issued due to lack of back-end resources.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa4",
+ "EventName": "TOPDOWN.BACKEND_BOUND_SLOTS",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of Top-down Microarchitecture Analysis (TMA) method's slots where no micro-operations were being issued from front-end to back-end of the machine due to lack of back-end resources.",
+ "SampleAfterValue": "10000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "TMA slots wasted due to incorrect speculation by branch mispredictions",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa4",
+ "EventName": "TOPDOWN.BR_MISPREDICT_SLOTS",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Number of TMA slots that were wasted due to incorrect speculation by branch mispredictions. This event estimates number of operations that were issued but not retired from the specualtive path as well as the out-of-order engine recovery past a branch misprediction.",
+ "SampleAfterValue": "10000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "TMA slots available for an unhalted logical processor. Fixed counter - architectural event",
+ "CollectPEBSRecord": "2",
+ "Counter": "Fixed counter 3",
+ "EventName": "TOPDOWN.SLOTS",
+ "PEBScounters": "35",
+ "PublicDescription": "Number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method (TMA). The count is distributed among unhalted logical processors (hyper-threads) who share the same physical core. Software can use this event as the denominator for the top-level metrics of the TMA method. This architectural event is counted on a designated fixed counter (Fixed Counter 3).",
+ "SampleAfterValue": "10000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "TMA slots available for an unhalted logical processor. General counter - architectural event",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa4",
+ "EventName": "TOPDOWN.SLOTS_P",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method. The count is distributed among unhalted logical processors (hyper-threads) who share the same physical core.",
+ "SampleAfterValue": "10000003",
+ "UMask": "0x1"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/pipeline.json b/tools/perf/pmu-events/arch/x86/tigerlake/pipeline.json
new file mode 100644
index 000000000000..d0d8a09bc470
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tigerlake/pipeline.json
@@ -0,0 +1,982 @@
+[
+ {
+ "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x14",
+ "EventName": "ARITH.DIVIDER_ACTIVE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x9"
+ },
+ {
+ "BriefDescription": "All branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.ALL_BRANCHES",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts all branch instructions retired.",
+ "SampleAfterValue": "400009"
+ },
+ {
+ "BriefDescription": "Conditional branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.COND",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x11"
+ },
+ {
+ "BriefDescription": "Not taken branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.COND_NTAKEN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts not taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Taken conditional branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.COND_TAKEN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts taken conditional branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Far branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.FAR_BRANCH",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts far branch instructions retired.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "All indirect branch instructions retired (excluding RETs. TSX aborts are considered indirect branch).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.INDIRECT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts all indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Direct and indirect near call instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.NEAR_CALL",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts both direct and indirect near call instructions retired.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Return instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.NEAR_RETURN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts return instructions retired.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Taken branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc4",
+ "EventName": "BR_INST_RETIRED.NEAR_TAKEN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts taken branch instructions retired.",
+ "SampleAfterValue": "400009",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "All mispredicted branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.ALL_BRANCHES",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.",
+ "SampleAfterValue": "50021"
+ },
+ {
+ "BriefDescription": "Mispredicted conditional branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.COND",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts mispredicted conditional branch instructions retired.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x11"
+ },
+ {
+ "BriefDescription": "Mispredicted non-taken conditional branch instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.COND_NTAKEN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of conditional branch instructions retired that were mispredicted and the branch direction was not taken.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "number of branch instructions retired that were mispredicted and taken. Non PEBS",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.COND_TAKEN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts taken conditional mispredicted branch instructions retired.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "All miss-predicted indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.INDIRECT",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts all miss-predicted indirect branch instructions retired (excluding RETs. TSX aborts is considered indirect branch).",
+ "SampleAfterValue": "50021",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Mispredicted indirect CALL instructions retired.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.INDIRECT_CALL",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts retired mispredicted indirect (near taken) CALL instructions, including both register and memory indirect.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc5",
+ "EventName": "BR_MISP_RETIRED.NEAR_TAKEN",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts number of near branch instructions retired that were mispredicted and taken.",
+ "SampleAfterValue": "50021",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Cycle counts are evenly distributed between active threads in the Core.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xec",
+ "EventName": "CPU_CLK_UNHALTED.DISTRIBUTED",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "This event distributes cycle counts between active hyperthreads, i.e., those in C0. A hyperthread becomes inactive when it executes the HLT or MWAIT instructions. If all other hyperthreads are inactive (or disabled or do not exist), all counts are attributed to this hyperthread. To obtain the full count when the Core is active, sum the counts from each hyperthread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x3c",
+ "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts Core crystal clock cycles when current thread is unhalted and the other thread is halted.",
+ "SampleAfterValue": "25003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Core crystal clock cycles. Cycle counts are evenly distributed between active threads in the Core.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x3c",
+ "EventName": "CPU_CLK_UNHALTED.REF_DISTRIBUTED",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "This event distributes Core crystal clock cycle counts between active hyperthreads, i.e., those in C0 sleep-state. A hyperthread becomes inactive when it executes the HLT or MWAIT instructions. If one thread is active in a core, all counts are attributed to this hyperthread. To obtain the full count when the Core is active, sum the counts from each hyperthread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Reference cycles when the core is not in halt state.",
+ "CollectPEBSRecord": "2",
+ "Counter": "Fixed counter 2",
+ "EventName": "CPU_CLK_UNHALTED.REF_TSC",
+ "PEBScounters": "34",
+ "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. This event has a constant ratio with the CPU_CLK_UNHALTED.REF_XCLK event. It is counted on a dedicated fixed counter, leaving the eight programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x3"
+ },
+ {
+ "BriefDescription": "Core crystal clock cycles when the thread is unhalted.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x3c",
+ "EventName": "CPU_CLK_UNHALTED.REF_XCLK",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts core crystal clock cycles when the thread is unhalted.",
+ "SampleAfterValue": "25003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Core cycles when the thread is not in halt state",
+ "CollectPEBSRecord": "2",
+ "Counter": "Fixed counter 1",
+ "EventName": "CPU_CLK_UNHALTED.THREAD",
+ "PEBScounters": "33",
+ "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the eight programmable counters available for other events.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Thread cycles when thread is not in halt state",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x3c",
+ "EventName": "CPU_CLK_UNHALTED.THREAD_P",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.",
+ "SampleAfterValue": "2000003"
+ },
+ {
+ "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "8",
+ "EventCode": "0xa3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0xa3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles while memory subsystem has an outstanding load.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "16",
+ "EventCode": "0xa3",
+ "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "12",
+ "EventCode": "0xa3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0xc"
+ },
+ {
+ "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "5",
+ "EventCode": "0xa3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS",
+ "PEBScounters": "0,1,2,3",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x5"
+ },
+ {
+ "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "20",
+ "EventCode": "0xa3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_MEM_ANY",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x14"
+ },
+ {
+ "BriefDescription": "Total execution stalls.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "4",
+ "EventCode": "0xa3",
+ "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa6",
+ "EventName": "EXE_ACTIVITY.1_PORTS_UTIL",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa6",
+ "EventName": "EXE_ACTIVITY.2_PORTS_UTIL",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station was not empty.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa6",
+ "EventName": "EXE_ACTIVITY.3_PORTS_UTIL",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station (RS) was not empty.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station was not empty.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa6",
+ "EventName": "EXE_ACTIVITY.4_PORTS_UTIL",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station (RS) was not empty.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Cycles when the memory subsystem has an outstanding load. Increments by 4 for every such cycle.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "5",
+ "EventCode": "0xa6",
+ "EventName": "EXE_ACTIVITY.BOUND_ON_LOADS",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles when the memory subsystem has an outstanding load. Increments by 4 for every such cycle.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x21"
+ },
+ {
+ "BriefDescription": "Cycles where the Store Buffer was full and no loads caused an execution stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "2",
+ "EventCode": "0xa6",
+ "EventName": "EXE_ACTIVITY.BOUND_ON_STORES",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles where the Store Buffer was full and no loads caused an execution stall.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Cycles where no uops were executed, the Reservation Station was not empty, the Store Buffer was full and there was no outstanding load.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa6",
+ "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles during which no uops were executed on all ports and Reservation Station (RS) was not empty.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Stalls caused by changing prefix length of the instruction.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x87",
+ "EventName": "ILD_STALL.LCP",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles that the Instruction Length decoder (ILD) stalls occurred due to dynamically changing prefix length of the decoded instruction (by operand size prefix instruction 0x66, address size prefix instruction 0x67 or REX.W for Intel64). Count is proportional to the number of prefixes in a 16B-line. This may result in a three-cycle penalty for each LCP (Length changing prefix) in a 16-byte chunk.",
+ "SampleAfterValue": "500009",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of instructions retired. Fixed Counter - architectural event",
+ "CollectPEBSRecord": "2",
+ "Counter": "Fixed counter 0",
+ "EventName": "INST_RETIRED.ANY",
+ "PEBS": "1",
+ "PEBScounters": "32",
+ "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of instructions retired. General Counter - architectural event",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc0",
+ "EventName": "INST_RETIRED.ANY_P",
+ "PEBS": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.",
+ "SampleAfterValue": "2000003"
+ },
+ {
+ "BriefDescription": "Precise instruction retired event with a reduced effect of PEBS shadow in IP distribution",
+ "CollectPEBSRecord": "2",
+ "Counter": "Fixed counter 0",
+ "EventName": "INST_RETIRED.PREC_DIST",
+ "PEBS": "1",
+ "PEBScounters": "32",
+ "PublicDescription": "A version of INST_RETIRED that allows for a more unbiased distribution of samples across instructions retired. It utilizes the Precise Distribution of Instructions Retired (PDIR) feature to mitigate some bias in how retired instructions get sampled. Use on Fixed Counter 0.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles the Backend cluster is recovering after a miss-speculation or a Store Buffer or Load Buffer drain stall.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x0d",
+ "EventName": "INT_MISC.ALL_RECOVERY_CYCLES",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles the Backend cluster is recovering after a miss-speculation or a Store Buffer or Load Buffer drain stall.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x3"
+ },
+ {
+ "BriefDescription": "Counts cycles after recovery from a branch misprediction or machine clear till the first uop is issued from the resteered path.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x0d",
+ "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Cycles after recovery from a branch misprediction or machine clear till the first uop is issued from the resteered path.",
+ "SampleAfterValue": "500009",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x0d",
+ "EventName": "INT_MISC.RECOVERY_CYCLES",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts core cycles when the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.",
+ "SampleAfterValue": "500009",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "TMA slots where uops got dropped",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x0d",
+ "EventName": "INT_MISC.UOP_DROPPING",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Estimated number of Top-down Microarchitecture Analysis slots that got dropped due to non front-end reasons",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x03",
+ "EventName": "LD_BLOCKS.NO_SR",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Loads blocked due to overlapping with a preceding store that cannot be forwarded.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x03",
+ "EventName": "LD_BLOCKS.STORE_FORWARD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of times where store forwarding was prevented for a load operation. The most common case is a load blocked due to the address of memory access (partially) overlapping with a preceding uncompleted store. Note: See the table of not supported store forwards in the Optimization Guide.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "False dependencies in MOB due to partial compare on address.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x07",
+ "EventName": "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of times a load got blocked due to false dependencies in MOB due to partial compare on address.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x4c",
+ "EventName": "LOAD_HIT_PREFETCH.SWPF",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by ASM (Assembly File) inspection of the nearby instructions.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0xa8",
+ "EventName": "LSD.CYCLES_ACTIVE",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles optimal number of Uops delivered by the LSD, but did not come from the decoder.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "5",
+ "EventCode": "0xa8",
+ "EventName": "LSD.CYCLES_OK",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the cycles when optimal number of uops is delivered by the LSD (Loop-stream detector).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of Uops delivered by the LSD.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xa8",
+ "EventName": "LSD.UOPS",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of uops delivered to the back-end by the LSD(Loop Stream Detector).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of machine clears (nukes) of any type.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EdgeDetect": "1",
+ "EventCode": "0xc3",
+ "EventName": "MACHINE_CLEARS.COUNT",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of machine clears (nukes) of any type.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Self-modifying code (SMC) detected.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc3",
+ "EventName": "MACHINE_CLEARS.SMC",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Increments whenever there is an update to the LBR array.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xcc",
+ "EventName": "MISC_RETIRED.LBR_INSERTS",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Number of retired PAUSE instructions. This event is not supported on first SKL and KBL products.",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xcc",
+ "EventName": "MISC_RETIRED.PAUSE_INST",
+ "PublicDescription": "Counts number of retired PAUSE instructions. This event is not supported on first SKL and KBL products.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa2",
+ "EventName": "RESOURCE_STALLS.SB",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x8"
+ },
+ {
+ "BriefDescription": "Counts cycles where the pipeline is stalled due to serializing operations.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa2",
+ "EventName": "RESOURCE_STALLS.SCOREBOARD",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x5e",
+ "EventName": "RS_EVENTS.EMPTY_CYCLES",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for this logical processor. This is usually caused when the front-end pipeline runs into stravation periods (e.g. branch mispredictions or i-cache misses)",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EdgeDetect": "1",
+ "EventCode": "0x5e",
+ "EventName": "RS_EVENTS.EMPTY_END",
+ "Invert": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to closely sample on front-end latency issues (see the FRONTEND_RETIRED event of designated precise events)",
+ "SampleAfterValue": "100003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of uops executed on port 0",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa1",
+ "EventName": "UOPS_DISPATCHED.PORT_0",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 0.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Number of uops executed on port 1",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa1",
+ "EventName": "UOPS_DISPATCHED.PORT_1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 1.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of uops executed on port 2 and 3",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa1",
+ "EventName": "UOPS_DISPATCHED.PORT_2_3",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 2 and 3.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Number of uops executed on port 4 and 9",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa1",
+ "EventName": "UOPS_DISPATCHED.PORT_4_9",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 5 and 9.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Number of uops executed on port 5",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa1",
+ "EventName": "UOPS_DISPATCHED.PORT_5",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 5.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Number of uops executed on port 6",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa1",
+ "EventName": "UOPS_DISPATCHED.PORT_6",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to port 6.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x40"
+ },
+ {
+ "BriefDescription": "Number of uops executed on port 7 and 8",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xa1",
+ "EventName": "UOPS_DISPATCHED.PORT_7_8",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts, on the per-thread basis, cycles during which at least one uop is dispatched from the Reservation Station (RS) to ports 7 and 8.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x80"
+ },
+ {
+ "BriefDescription": "Number of uops executed on the core.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CORE",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of uops executed from any thread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles when at least 1 micro-op is executed from any thread on physical core.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "2",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles when at least 2 micro-ops are executed from any thread on physical core.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "3",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles when at least 3 micro-ops are executed from any thread on physical core.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "4",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles when at least 4 micro-ops are executed from any thread on physical core.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles where at least 1 uop was executed per-thread",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Cycles where at least 1 uop was executed per-thread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles where at least 2 uops were executed per-thread",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "2",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_2",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Cycles where at least 2 uops were executed per-thread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles where at least 3 uops were executed per-thread",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "3",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_3",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Cycles where at least 3 uops were executed per-thread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles where at least 4 uops were executed per-thread",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "4",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.CYCLES_GE_4",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Cycles where at least 4 uops were executed per-thread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.STALL_CYCLES",
+ "Invert": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.THREAD",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Counts the number of x87 uops dispatched.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xb1",
+ "EventName": "UOPS_EXECUTED.X87",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of x87 uops executed.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Uops that RAT issues to RS",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x0e",
+ "EventName": "UOPS_ISSUED.ANY",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Cycles when RAT does not issue Uops to RS for the thread",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0x0e",
+ "EventName": "UOPS_ISSUED.STALL_CYCLES",
+ "Invert": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts cycles during which the Resource Allocation Table (RAT) does not issue any Uops to the reservation station (RS) for the current thread.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "Uops inserted at issue-stage in order to preserve upper bits of vector registers.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0x0e",
+ "EventName": "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of Blend Uops issued by the Resource Allocation Table (RAT) to the reservation station (RS) in order to preserve upper bits of vector registers. Starting with the Skylake microarchitecture, these Blend uops are needed since every Intel SSE instruction executed in Dirty Upper State needs to preserve bits 128-255 of the destination register. For more information, refer to Mixing Intel AVX and Intel SSE Code section of the Optimization Guide.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Retirement slots used.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "EventCode": "0xc2",
+ "EventName": "UOPS_RETIRED.SLOTS",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the retirement slots used each cycle.",
+ "SampleAfterValue": "2000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles without actually retired uops.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "1",
+ "EventCode": "0xc2",
+ "EventName": "UOPS_RETIRED.STALL_CYCLES",
+ "Invert": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "This event counts cycles without actually retired uops.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Cycles with less than 10 actually retired uops.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3,4,5,6,7",
+ "CounterMask": "10",
+ "EventCode": "0xc2",
+ "EventName": "UOPS_RETIRED.TOTAL_CYCLES",
+ "Invert": "1",
+ "PEBScounters": "0,1,2,3,4,5,6,7",
+ "PublicDescription": "Counts the number of cycles using always true condition (uops_ret &amp;lt; 16) applied to non PEBS uops retired event.",
+ "SampleAfterValue": "1000003",
+ "UMask": "0x2"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json b/tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json
new file mode 100644
index 000000000000..00a16f1a0f44
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json
@@ -0,0 +1,231 @@
+[
+ {
+ "BriefDescription": "Instructions Per Cycle (per Logical Processor)",
+ "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "Summary",
+ "MetricName": "IPC"
+ },
+ {
+ "BriefDescription": "Instruction per taken branch",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_TAKEN",
+ "MetricGroup": "Branches;FetchBW;PGO",
+ "MetricName": "IpTB"
+ },
+ {
+ "BriefDescription": "Cycles Per Instruction (per Logical Processor)",
+ "MetricExpr": "1 / IPC",
+ "MetricGroup": "Pipeline",
+ "MetricName": "CPI"
+ },
+ {
+ "BriefDescription": "Per-Logical Processor actual clocks when the Logical Processor is active.",
+ "MetricExpr": "CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "Pipeline",
+ "MetricName": "CLKS"
+ },
+ {
+ "BriefDescription": "Instructions Per Cycle (per physical core)",
+ "MetricExpr": "INST_RETIRED.ANY / CPU_CLK_UNHALTED.DISTRIBUTED",
+ "MetricGroup": "SMT;TmaL1",
+ "MetricName": "CoreIPC"
+ },
+ {
+ "BriefDescription": "Floating Point Operations Per Cycle",
+ "MetricExpr": "( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / CPU_CLK_UNHALTED.DISTRIBUTED",
+ "MetricGroup": "Flops",
+ "MetricName": "FLOPc"
+ },
+ {
+ "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is at least 1 uop executed)",
+ "MetricExpr": "UOPS_EXECUTED.THREAD / ( UOPS_EXECUTED.CORE_CYCLES_GE_1 / 2 )",
+ "MetricGroup": "Pipeline;PortsUtil",
+ "MetricName": "ILP"
+ },
+ {
+ "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES",
+ "MetricGroup": "BrMispredicts",
+ "MetricName": "IpMispredict"
+ },
+ {
+ "BriefDescription": "Core actual clocks when any Logical Processor is active on the Physical Core",
+ "MetricExpr": "CPU_CLK_UNHALTED.DISTRIBUTED",
+ "MetricGroup": "SMT",
+ "MetricName": "CORE_CLKS"
+ },
+ {
+ "BriefDescription": "Instructions per Load (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_LOADS",
+ "MetricGroup": "InsType",
+ "MetricName": "IpLoad"
+ },
+ {
+ "BriefDescription": "Instructions per Store (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_STORES",
+ "MetricGroup": "InsType",
+ "MetricName": "IpStore"
+ },
+ {
+ "BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES",
+ "MetricGroup": "Branches;InsType",
+ "MetricName": "IpBranch"
+ },
+ {
+ "BriefDescription": "Instructions per (near) call (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_CALL",
+ "MetricGroup": "Branches",
+ "MetricName": "IpCall"
+ },
+ {
+ "BriefDescription": "Branch instructions per taken branch. ",
+ "MetricExpr": "BR_INST_RETIRED.ALL_BRANCHES / BR_INST_RETIRED.NEAR_TAKEN",
+ "MetricGroup": "Branches;PGO",
+ "MetricName": "BpTkBranch"
+ },
+ {
+ "BriefDescription": "Instructions per Floating Point (FP) Operation (lower number means higher occurrence rate)",
+ "MetricExpr": "INST_RETIRED.ANY / ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE )",
+ "MetricGroup": "Flops;FpArith;InsType",
+ "MetricName": "IpFLOP"
+ },
+ {
+ "BriefDescription": "Total number of retired Instructions, Sample with: INST_RETIRED.PREC_DIST",
+ "MetricExpr": "INST_RETIRED.ANY",
+ "MetricGroup": "Summary;TmaL1",
+ "MetricName": "Instructions"
+ },
+ {
+ "BriefDescription": "Fraction of Uops delivered by the LSD (Loop Stream Detector; aka Loop Cache)",
+ "MetricExpr": "LSD.UOPS / (IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS)",
+ "MetricGroup": "LSD",
+ "MetricName": "LSD_Coverage"
+ },
+ {
+ "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded ICache; or Uop Cache)",
+ "MetricExpr": "IDQ.DSB_UOPS / (IDQ.DSB_UOPS + LSD.UOPS + IDQ.MITE_UOPS + IDQ.MS_UOPS)",
+ "MetricGroup": "DSB;FetchBW",
+ "MetricName": "DSB_Coverage"
+ },
+ {
+ "BriefDescription": "Actual Average Latency for L1 data-cache miss demand loads (in core cycles)",
+ "MetricExpr": "L1D_PEND_MISS.PENDING / ( MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT )",
+ "MetricGroup": "MemoryBound;MemoryLat",
+ "MetricName": "Load_Miss_Real_Latency"
+ },
+ {
+ "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least one such miss. Per-Logical Processor)",
+ "MetricExpr": "L1D_PEND_MISS.PENDING / L1D_PEND_MISS.PENDING_CYCLES",
+ "MetricGroup": "MemoryBound;MemoryBW",
+ "MetricName": "MLP"
+ },
+ {
+ "BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
+ "MetricConstraint": "NO_NMI_WATCHDOG",
+ "MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING ) / ( 2 * CORE_CLKS )",
+ "MetricGroup": "MemoryTLB",
+ "MetricName": "Page_Walks_Utilization"
+ },
+ {
+ "BriefDescription": "Average data fill bandwidth to the L1 data cache [GB / sec]",
+ "MetricExpr": "64 * L1D.REPLACEMENT / 1000000000 / duration_time",
+ "MetricGroup": "MemoryBW",
+ "MetricName": "L1D_Cache_Fill_BW"
+ },
+ {
+ "BriefDescription": "Average data fill bandwidth to the L2 cache [GB / sec]",
+ "MetricExpr": "64 * L2_LINES_IN.ALL / 1000000000 / duration_time",
+ "MetricGroup": "MemoryBW",
+ "MetricName": "L2_Cache_Fill_BW"
+ },
+ {
+ "BriefDescription": "Average per-core data access bandwidth to the L3 cache [GB / sec]",
+ "MetricExpr": "64 * OFFCORE_REQUESTS.ALL_REQUESTS / 1000000000 / duration_time",
+ "MetricGroup": "MemoryBW;Offcore",
+ "MetricName": "L3_Cache_Access_BW"
+ },
+ {
+ "BriefDescription": "L1 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L1_MISS / INST_RETIRED.ANY",
+ "MetricGroup": "CacheMisses",
+ "MetricName": "L1MPKI"
+ },
+ {
+ "BriefDescription": "L2 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L2_MISS / INST_RETIRED.ANY",
+ "MetricGroup": "CacheMisses",
+ "MetricName": "L2MPKI"
+ },
+ {
+ "BriefDescription": "L3 cache true misses per kilo instruction for retired demand loads",
+ "MetricExpr": "1000 * MEM_LOAD_RETIRED.L3_MISS / INST_RETIRED.ANY",
+ "MetricGroup": "CacheMisses",
+ "MetricName": "L3MPKI"
+ },
+ {
+ "BriefDescription": "Average CPU Utilization",
+ "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
+ "MetricGroup": "HPC;Summary",
+ "MetricName": "CPU_Utilization"
+ },
+ {
+ "BriefDescription": "Measured Average Frequency for unhalted processors [GHz]",
+ "MetricExpr": "(CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC) * msr@tsc@ / 1000000000 / duration_time",
+ "MetricGroup": "Summary;Power",
+ "MetricName": "Average_Frequency"
+ },
+ {
+ "BriefDescription": "Giga Floating Point Operations Per Second",
+ "MetricExpr": "( ( 1 * ( FP_ARITH_INST_RETIRED.SCALAR_SINGLE + FP_ARITH_INST_RETIRED.SCALAR_DOUBLE ) + 2 * FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE + 4 * ( FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE ) + 8 * ( FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE + FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE ) + 16 * FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE ) / 1000000000 ) / duration_time",
+ "MetricGroup": "Flops;HPC",
+ "MetricName": "GFLOPs"
+ },
+ {
+ "BriefDescription": "Average Frequency Utilization relative nominal frequency",
+ "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC",
+ "MetricGroup": "Power",
+ "MetricName": "Turbo_Utilization"
+ },
+ {
+ "BriefDescription": "Fraction of cycles where both hardware Logical Processors were active",
+ "MetricExpr": "1 - CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE / CPU_CLK_UNHALTED.REF_DISTRIBUTED",
+ "MetricGroup": "SMT",
+ "MetricName": "SMT_2T_Utilization"
+ },
+ {
+ "BriefDescription": "Fraction of cycles spent in the Operating System (OS) Kernel mode",
+ "MetricExpr": "CPU_CLK_UNHALTED.THREAD_P:k / CPU_CLK_UNHALTED.THREAD",
+ "MetricGroup": "OS",
+ "MetricName": "Kernel_Utilization"
+ },
+ {
+ "BriefDescription": "Instructions per Far Branch ( Far Branches apply upon transition from application to operating system, handling interrupts, exceptions) [lower number means higher occurrence rate]",
+ "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.FAR_BRANCH:u",
+ "MetricGroup": "Branches;OS",
+ "MetricName": "IpFarBranch"
+ },
+ {
+ "BriefDescription": "C6 residency percent per core",
+ "MetricExpr": "(cstate_core@c6\\-residency@ / msr@tsc@) * 100",
+ "MetricGroup": "Power",
+ "MetricName": "C6_Core_Residency"
+ },
+ {
+ "BriefDescription": "C7 residency percent per core",
+ "MetricExpr": "(cstate_core@c7\\-residency@ / msr@tsc@) * 100",
+ "MetricGroup": "Power",
+ "MetricName": "C7_Core_Residency"
+ },
+ {
+ "BriefDescription": "C6 residency percent per package",
+ "MetricExpr": "(cstate_pkg@c6\\-residency@ / msr@tsc@) * 100",
+ "MetricGroup": "Power",
+ "MetricName": "C6_Pkg_Residency"
+ },
+ {
+ "BriefDescription": "C7 residency percent per package",
+ "MetricExpr": "(cstate_pkg@c7\\-residency@ / msr@tsc@) * 100",
+ "MetricGroup": "Power",
+ "MetricName": "C7_Pkg_Residency"
+ }
+]
diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/tigerlake/virtual-memory.json
new file mode 100644
index 000000000000..3ebec78969b0
--- /dev/null
+++ b/tools/perf/pmu-events/arch/x86/tigerlake/virtual-memory.json
@@ -0,0 +1,225 @@
+[
+ {
+ "BriefDescription": "Loads that miss the DTLB and hit the STLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.STLB_HIT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a demand load.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_ACTIVE",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a demand load.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data loads. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0xe"
+ },
+ {
+ "BriefDescription": "Page walks completed due to a demand data load to a 2M/4M page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts completed page walks (2M/4M sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Page walks completed due to a demand data load to a 4K page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts completed page walks (4K sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of page walks outstanding for a demand load in the PMH each cycle.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x08",
+ "EventName": "DTLB_LOAD_MISSES.WALK_PENDING",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks outstanding for a demand load in the PMH (Page Miss Handler) each cycle.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Stores that miss the DTLB and hit the STLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.STLB_HIT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts stores that miss the DTLB (Data TLB) and hit the STLB (2nd Level TLB).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_ACTIVE",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a store.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data stores. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0xe"
+ },
+ {
+ "BriefDescription": "Page walks completed due to a demand data store to a 2M/4M page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 2M/4M pages. The page walks can end with or without a page fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Page walks completed due to a demand data store to a 4K page.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of page walks outstanding for a store in the PMH each cycle.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x49",
+ "EventName": "DTLB_STORE_MISSES.WALK_PENDING",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks outstanding for a store in the PMH (Page Miss Handler) each cycle.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.STLB_HIT",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts instruction fetch requests that miss the ITLB (Instruction TLB) and hit the STLB (Second-level TLB).",
+ "SampleAfterValue": "100003",
+ "UMask": "0x20"
+ },
+ {
+ "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "CounterMask": "1",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_ACTIVE",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a code (instruction fetch) request.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts completed page walks (all page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0xe"
+ },
+ {
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts completed page walks (2M/4M page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x4"
+ },
+ {
+ "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_COMPLETED_4K",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts completed page walks (4K page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x2"
+ },
+ {
+ "BriefDescription": "Number of page walks outstanding for an outstanding code request in the PMH each cycle.",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0x85",
+ "EventName": "ITLB_MISSES.WALK_PENDING",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of page walks outstanding for an outstanding code (instruction fetch) request in the PMH (Page Miss Handler) each cycle.",
+ "SampleAfterValue": "100003",
+ "UMask": "0x10"
+ },
+ {
+ "BriefDescription": "DTLB flush attempts of the thread-specific entries",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xbd",
+ "EventName": "TLB_FLUSH.DTLB_THREAD",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of DTLB flush attempts of the thread-specific entries.",
+ "SampleAfterValue": "100007",
+ "UMask": "0x1"
+ },
+ {
+ "BriefDescription": "STLB flush attempts",
+ "CollectPEBSRecord": "2",
+ "Counter": "0,1,2,3",
+ "EventCode": "0xbd",
+ "EventName": "TLB_FLUSH.STLB_ANY",
+ "PEBScounters": "0,1,2,3",
+ "PublicDescription": "Counts the number of any STLB flush attempts (such as entire, VPID, PCID, InvPage, CR3 write, etc.).",
+ "SampleAfterValue": "100007",
+ "UMask": "0x20"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index 9604446f8360..6731b3cf0c2f 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -814,7 +814,7 @@ static void print_mapping_test_table(FILE *outfp)
fprintf(outfp, "\t.cpuid = \"testcpu\",\n");
fprintf(outfp, "\t.version = \"v1\",\n");
fprintf(outfp, "\t.type = \"core\",\n");
- fprintf(outfp, "\t.table = pme_test_cpu,\n");
+ fprintf(outfp, "\t.table = pme_test_soc_cpu,\n");
fprintf(outfp, "},\n");
}
@@ -836,7 +836,8 @@ static int process_system_event_tables(FILE *outfp)
print_system_event_mapping_table_prefix(outfp);
list_for_each_entry(sys_event_table, &sys_event_tables, list) {
- fprintf(outfp, "\n\t{\n\t\t.table = %s,\n\t},",
+ fprintf(outfp, "\n\t{\n\t\t.table = %s,\n\t\t.name = \"%s\",\n\t},",
+ sys_event_table->soc_id,
sys_event_table->soc_id);
}
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index d1172f6aebf1..5c2bf7275c1c 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -45,6 +45,7 @@ struct pmu_events_map {
};
struct pmu_sys_events {
+ const char *name;
struct pmu_event *table;
};
diff --git a/tools/perf/scripts/python/flamegraph.py b/tools/perf/scripts/python/flamegraph.py
index 65780013f745..b6af1dd5f816 100755
--- a/tools/perf/scripts/python/flamegraph.py
+++ b/tools/perf/scripts/python/flamegraph.py
@@ -13,6 +13,10 @@
# Written by Andreas Gerstmayr <agerstmayr@redhat.com>
# Flame Graphs invented by Brendan Gregg <bgregg@netflix.com>
# Works in tandem with d3-flame-graph by Martin Spier <mspier@netflix.com>
+#
+# pylint: disable=missing-module-docstring
+# pylint: disable=missing-class-docstring
+# pylint: disable=missing-function-docstring
from __future__ import print_function
import sys
@@ -20,16 +24,19 @@ import os
import io
import argparse
import json
+import subprocess
-
+# pylint: disable=too-few-public-methods
class Node:
- def __init__(self, name, libtype=""):
+ def __init__(self, name, libtype):
self.name = name
+ # "root" | "kernel" | ""
+ # "" indicates user space
self.libtype = libtype
self.value = 0
self.children = []
- def toJSON(self):
+ def to_json(self):
return {
"n": self.name,
"l": self.libtype,
@@ -41,7 +48,7 @@ class Node:
class FlameGraphCLI:
def __init__(self, args):
self.args = args
- self.stack = Node("root")
+ self.stack = Node("all", "root")
if self.args.format == "html" and \
not os.path.isfile(self.args.template):
@@ -53,13 +60,21 @@ class FlameGraphCLI:
file=sys.stderr)
sys.exit(1)
- def find_or_create_node(self, node, name, dso):
- libtype = "kernel" if dso == "[kernel.kallsyms]" else ""
- if name is None:
- name = "[unknown]"
+ @staticmethod
+ def get_libtype_from_dso(dso):
+ """
+ when kernel-debuginfo is installed,
+ dso points to /usr/lib/debug/lib/modules/*/vmlinux
+ """
+ if dso and (dso == "[kernel.kallsyms]" or dso.endswith("/vmlinux")):
+ return "kernel"
+ return ""
+
+ @staticmethod
+ def find_or_create_node(node, name, libtype):
for child in node.children:
- if child.name == name and child.libtype == libtype:
+ if child.name == name:
return child
child = Node(name, libtype)
@@ -67,30 +82,65 @@ class FlameGraphCLI:
return child
def process_event(self, event):
- node = self.find_or_create_node(self.stack, event["comm"], None)
+ pid = event.get("sample", {}).get("pid", 0)
+ # event["dso"] sometimes contains /usr/lib/debug/lib/modules/*/vmlinux
+ # for user-space processes; let's use pid for kernel or user-space distinction
+ if pid == 0:
+ comm = event["comm"]
+ libtype = "kernel"
+ else:
+ comm = "{} ({})".format(event["comm"], pid)
+ libtype = ""
+ node = self.find_or_create_node(self.stack, comm, libtype)
+
if "callchain" in event:
- for entry in reversed(event['callchain']):
- node = self.find_or_create_node(
- node, entry.get("sym", {}).get("name"), event.get("dso"))
+ for entry in reversed(event["callchain"]):
+ name = entry.get("sym", {}).get("name", "[unknown]")
+ libtype = self.get_libtype_from_dso(entry.get("dso"))
+ node = self.find_or_create_node(node, name, libtype)
else:
- node = self.find_or_create_node(
- node, entry.get("symbol"), event.get("dso"))
+ name = event.get("symbol", "[unknown]")
+ libtype = self.get_libtype_from_dso(event.get("dso"))
+ node = self.find_or_create_node(node, name, libtype)
node.value += 1
+ def get_report_header(self):
+ if self.args.input == "-":
+ # when this script is invoked with "perf script flamegraph",
+ # no perf.data is created and we cannot read the header of it
+ return ""
+
+ try:
+ output = subprocess.check_output(["perf", "report", "--header-only"])
+ return output.decode("utf-8")
+ except Exception as err: # pylint: disable=broad-except
+ print("Error reading report header: {}".format(err), file=sys.stderr)
+ return ""
+
def trace_end(self):
- json_str = json.dumps(self.stack, default=lambda x: x.toJSON())
+ stacks_json = json.dumps(self.stack, default=lambda x: x.to_json())
if self.args.format == "html":
+ report_header = self.get_report_header()
+ options = {
+ "colorscheme": self.args.colorscheme,
+ "context": report_header
+ }
+ options_json = json.dumps(options)
+
try:
- with io.open(self.args.template, encoding="utf-8") as f:
- output_str = f.read().replace("/** @flamegraph_json **/",
- json_str)
- except IOError as e:
- print("Error reading template file: {}".format(e), file=sys.stderr)
+ with io.open(self.args.template, encoding="utf-8") as template:
+ output_str = (
+ template.read()
+ .replace("/** @options_json **/", options_json)
+ .replace("/** @flamegraph_json **/", stacks_json)
+ )
+ except IOError as err:
+ print("Error reading template file: {}".format(err), file=sys.stderr)
sys.exit(1)
output_fn = self.args.output or "flamegraph.html"
else:
- output_str = json_str
+ output_str = stacks_json
output_fn = self.args.output or "stacks.json"
if output_fn == "-":
@@ -101,8 +151,8 @@ class FlameGraphCLI:
try:
with io.open(output_fn, "w", encoding="utf-8") as out:
out.write(output_str)
- except IOError as e:
- print("Error writing output file: {}".format(e), file=sys.stderr)
+ except IOError as err:
+ print("Error writing output file: {}".format(err), file=sys.stderr)
sys.exit(1)
@@ -115,12 +165,16 @@ if __name__ == "__main__":
help="output file name")
parser.add_argument("--template",
default="/usr/share/d3-flame-graph/d3-flamegraph-base.html",
- help="path to flamegraph HTML template")
+ help="path to flame graph HTML template")
+ parser.add_argument("--colorscheme",
+ default="blue-green",
+ help="flame graph color scheme",
+ choices=["blue-green", "orange"])
parser.add_argument("-i", "--input",
help=argparse.SUPPRESS)
- args = parser.parse_args()
- cli = FlameGraphCLI(args)
+ cli_args = parser.parse_args()
+ cli = FlameGraphCLI(cli_args)
process_event = cli.process_event
trace_end = cli.trace_end
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 650aec19d490..803ca426f8e6 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -64,6 +64,7 @@ perf-y += parse-metric.o
perf-y += pe-file-parsing.o
perf-y += expand-cgroup.o
perf-y += perf-time-to-tsc.o
+perf-y += dlfilter-test.o
$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 5e6242576236..da7dc5e45d0c 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -361,6 +361,10 @@ static struct test generic_tests[] = {
.is_supported = test__tsc_is_supported,
},
{
+ .desc = "dlfilter C API",
+ .func = test__dlfilter,
+ },
+ {
.func = NULL,
},
};
@@ -594,7 +598,8 @@ static int shell_test__run(struct test *test, int subdir __maybe_unused)
return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL;
}
-static int run_shell_tests(int argc, const char *argv[], int i, int width)
+static int run_shell_tests(int argc, const char *argv[], int i, int width,
+ struct intlist *skiplist)
{
struct dirent **entlist;
struct dirent *ent;
@@ -628,6 +633,12 @@ static int run_shell_tests(int argc, const char *argv[], int i, int width)
st.file = ent->d_name;
pr_info("%2d: %-*s:", i, width, test.desc);
+
+ if (intlist__find(skiplist, i)) {
+ color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
+ continue;
+ }
+
test_and_print(&test, false, -1);
}
@@ -727,7 +738,7 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
}
}
- return run_shell_tests(argc, argv, i, width);
+ return run_shell_tests(argc, argv, i, width, skiplist);
}
static int perf_test__list_shell(int argc, const char **argv, int i)
diff --git a/tools/perf/tests/dlfilter-test.c b/tools/perf/tests/dlfilter-test.c
new file mode 100644
index 000000000000..bc03b5df6828
--- /dev/null
+++ b/tools/perf/tests/dlfilter-test.c
@@ -0,0 +1,416 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test dlfilter C API. A perf.data file is synthesized and then processed
+ * by perf script with a dlfilter named dlfilter-test-api-v0.so. Also a C file
+ * is compiled to provide a dso to match the synthesized perf.data file.
+ */
+
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/perf_event.h>
+#include <internal/lib.h>
+#include <subcmd/exec-cmd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <string.h>
+#include <errno.h>
+#include "debug.h"
+#include "tool.h"
+#include "event.h"
+#include "header.h"
+#include "machine.h"
+#include "dso.h"
+#include "map.h"
+#include "symbol.h"
+#include "synthetic-events.h"
+#include "util.h"
+#include "archinsn.h"
+#include "dlfilter.h"
+#include "tests.h"
+
+#define MAP_START 0x400000
+
+struct test_data {
+ struct perf_tool tool;
+ struct machine *machine;
+ int fd;
+ u64 foo;
+ u64 bar;
+ u64 ip;
+ u64 addr;
+ char perf[PATH_MAX];
+ char perf_data_file_name[PATH_MAX];
+ char c_file_name[PATH_MAX];
+ char prog_file_name[PATH_MAX];
+ char dlfilters[PATH_MAX];
+};
+
+static int test_result(const char *msg, int ret)
+{
+ pr_debug("%s\n", msg);
+ return ret;
+}
+
+static int process(struct perf_tool *tool, union perf_event *event,
+ struct perf_sample *sample __maybe_unused,
+ struct machine *machine __maybe_unused)
+{
+ struct test_data *td = container_of(tool, struct test_data, tool);
+ int fd = td->fd;
+
+ if (writen(fd, event, event->header.size) != event->header.size)
+ return -1;
+
+ return 0;
+}
+
+#define MAXCMD 4096
+#define REDIRECT_TO_DEV_NULL " >/dev/null 2>&1"
+
+static __printf(1, 2) int system_cmd(const char *fmt, ...)
+{
+ char cmd[MAXCMD + sizeof(REDIRECT_TO_DEV_NULL)];
+ int ret;
+
+ va_list args;
+
+ va_start(args, fmt);
+ ret = vsnprintf(cmd, MAXCMD, fmt, args);
+ va_end(args);
+
+ if (ret <= 0 || ret >= MAXCMD)
+ return -1;
+
+ if (!verbose)
+ strcat(cmd, REDIRECT_TO_DEV_NULL);
+
+ pr_debug("Command: %s\n", cmd);
+ ret = system(cmd);
+ if (ret)
+ pr_debug("Failed with return value %d\n", ret);
+
+ return ret;
+}
+
+static bool have_gcc(void)
+{
+ pr_debug("Checking for gcc\n");
+ return !system_cmd("gcc --version");
+}
+
+static int write_attr(struct test_data *td, u64 sample_type, u64 *id)
+{
+ struct perf_event_attr attr = {
+ .size = sizeof(attr),
+ .type = PERF_TYPE_HARDWARE,
+ .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS,
+ .sample_type = sample_type,
+ .sample_period = 1,
+ };
+
+ return perf_event__synthesize_attr(&td->tool, &attr, 1, id, process);
+}
+
+static int write_comm(int fd, pid_t pid, pid_t tid, const char *comm_str)
+{
+ struct perf_record_comm comm;
+ ssize_t sz = sizeof(comm);
+
+ comm.header.type = PERF_RECORD_COMM;
+ comm.header.misc = PERF_RECORD_MISC_USER;
+ comm.header.size = sz;
+
+ comm.pid = pid;
+ comm.tid = tid;
+ strncpy(comm.comm, comm_str, 16);
+
+ if (writen(fd, &comm, sz) != sz) {
+ pr_debug("%s failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_mmap(int fd, pid_t pid, pid_t tid, u64 start, u64 len, u64 pgoff,
+ const char *filename)
+{
+ char buf[PERF_SAMPLE_MAX_SIZE];
+ struct perf_record_mmap *mmap = (struct perf_record_mmap *)buf;
+ size_t fsz = roundup(strlen(filename) + 1, 8);
+ ssize_t sz = sizeof(*mmap) - sizeof(mmap->filename) + fsz;
+
+ mmap->header.type = PERF_RECORD_MMAP;
+ mmap->header.misc = PERF_RECORD_MISC_USER;
+ mmap->header.size = sz;
+
+ mmap->pid = pid;
+ mmap->tid = tid;
+ mmap->start = start;
+ mmap->len = len;
+ mmap->pgoff = pgoff;
+ strncpy(mmap->filename, filename, sizeof(mmap->filename));
+
+ if (writen(fd, mmap, sz) != sz) {
+ pr_debug("%s failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_sample(struct test_data *td, u64 sample_type, u64 id, pid_t pid, pid_t tid)
+{
+ char buf[PERF_SAMPLE_MAX_SIZE];
+ union perf_event *event = (union perf_event *)buf;
+ struct perf_sample sample = {
+ .ip = td->ip,
+ .addr = td->addr,
+ .id = id,
+ .time = 1234567890,
+ .cpu = 31,
+ .pid = pid,
+ .tid = tid,
+ .period = 543212345,
+ .stream_id = 101,
+ };
+ int err;
+
+ event->header.type = PERF_RECORD_SAMPLE;
+ event->header.misc = PERF_RECORD_MISC_USER;
+ event->header.size = perf_event__sample_event_size(&sample, sample_type, 0);
+ err = perf_event__synthesize_sample(event, sample_type, 0, &sample);
+ if (err)
+ return test_result("perf_event__synthesize_sample() failed", TEST_FAIL);
+
+ err = process(&td->tool, event, &sample, td->machine);
+ if (err)
+ return test_result("Failed to write sample", TEST_FAIL);
+
+ return TEST_OK;
+}
+
+static void close_fd(int fd)
+{
+ if (fd >= 0)
+ close(fd);
+}
+
+static const char *prog = "int bar(){};int foo(){bar();};int main(){foo();return 0;}";
+
+static int write_prog(char *file_name)
+{
+ int fd = creat(file_name, 0644);
+ ssize_t n = strlen(prog);
+ bool err = fd < 0 || writen(fd, prog, n) != n;
+
+ close_fd(fd);
+ return err ? -1 : 0;
+}
+
+static int get_dlfilters_path(char *buf, size_t sz)
+{
+ char perf[PATH_MAX];
+ char path[PATH_MAX];
+ char *perf_path;
+ char *exec_path;
+
+ perf_exe(perf, sizeof(perf));
+ perf_path = dirname(perf);
+ snprintf(path, sizeof(path), "%s/dlfilters/dlfilter-test-api-v0.so", perf_path);
+ if (access(path, R_OK)) {
+ exec_path = get_argv_exec_path();
+ if (!exec_path)
+ return -1;
+ snprintf(path, sizeof(path), "%s/dlfilters/dlfilter-test-api-v0.so", exec_path);
+ free(exec_path);
+ if (access(path, R_OK))
+ return -1;
+ }
+ strlcpy(buf, dirname(path), sz);
+ return 0;
+}
+
+static int check_filter_desc(struct test_data *td)
+{
+ char *long_desc = NULL;
+ char *desc = NULL;
+ int ret;
+
+ if (get_filter_desc(td->dlfilters, "dlfilter-test-api-v0.so", &desc, &long_desc) &&
+ long_desc && !strcmp(long_desc, "Filter used by the 'dlfilter C API' perf test") &&
+ desc && !strcmp(desc, "dlfilter to test v0 C API"))
+ ret = 0;
+ else
+ ret = -1;
+
+ free(desc);
+ free(long_desc);
+ return ret;
+}
+
+static int get_ip_addr(struct test_data *td)
+{
+ struct map *map;
+ struct symbol *sym;
+
+ map = dso__new_map(td->prog_file_name);
+ if (!map)
+ return -1;
+
+ sym = map__find_symbol_by_name(map, "foo");
+ if (sym)
+ td->foo = sym->start;
+
+ sym = map__find_symbol_by_name(map, "bar");
+ if (sym)
+ td->bar = sym->start;
+
+ map__put(map);
+
+ td->ip = MAP_START + td->foo;
+ td->addr = MAP_START + td->bar;
+
+ return td->foo && td->bar ? 0 : -1;
+}
+
+static int do_run_perf_script(struct test_data *td, int do_early)
+{
+ return system_cmd("%s script -i %s "
+ "--dlfilter %s/dlfilter-test-api-v0.so "
+ "--dlarg first "
+ "--dlarg %d "
+ "--dlarg %" PRIu64 " "
+ "--dlarg %" PRIu64 " "
+ "--dlarg %d "
+ "--dlarg last",
+ td->perf, td->perf_data_file_name, td->dlfilters,
+ verbose, td->ip, td->addr, do_early);
+}
+
+static int run_perf_script(struct test_data *td)
+{
+ int do_early;
+ int err;
+
+ for (do_early = 0; do_early < 3; do_early++) {
+ err = do_run_perf_script(td, do_early);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+#define TEST_SAMPLE_TYPE (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
+ PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_TIME | \
+ PERF_SAMPLE_ADDR | PERF_SAMPLE_CPU | \
+ PERF_SAMPLE_PERIOD | PERF_SAMPLE_STREAM_ID)
+
+static int test__dlfilter_test(struct test_data *td)
+{
+ u64 sample_type = TEST_SAMPLE_TYPE;
+ pid_t pid = 12345;
+ pid_t tid = 12346;
+ u64 id = 99;
+ int err;
+
+ if (get_dlfilters_path(td->dlfilters, PATH_MAX))
+ return test_result("dlfilters not found", TEST_SKIP);
+
+ if (check_filter_desc(td))
+ return test_result("Failed to get expected filter description", TEST_FAIL);
+
+ if (!have_gcc())
+ return test_result("gcc not found", TEST_SKIP);
+
+ pr_debug("dlfilters path: %s\n", td->dlfilters);
+
+ if (write_prog(td->c_file_name))
+ return test_result("Failed to write test C file", TEST_FAIL);
+
+ if (verbose > 1)
+ system_cmd("cat %s ; echo", td->c_file_name);
+
+ if (system_cmd("gcc -g -o %s %s", td->prog_file_name, td->c_file_name))
+ return TEST_FAIL;
+
+ if (verbose > 2)
+ system_cmd("objdump -x -dS %s", td->prog_file_name);
+
+ if (get_ip_addr(td))
+ return test_result("Failed to find program symbols", TEST_FAIL);
+
+ pr_debug("Creating new host machine structure\n");
+ td->machine = machine__new_host();
+ td->machine->env = &perf_env;
+
+ td->fd = creat(td->perf_data_file_name, 0644);
+ if (td->fd < 0)
+ return test_result("Failed to create test perf.data file", TEST_FAIL);
+
+ err = perf_header__write_pipe(td->fd);
+ if (err < 0)
+ return test_result("perf_header__write_pipe() failed", TEST_FAIL);
+
+ err = write_attr(td, sample_type, &id);
+ if (err)
+ return test_result("perf_event__synthesize_attr() failed", TEST_FAIL);
+
+ if (write_comm(td->fd, pid, tid, "test-prog"))
+ return TEST_FAIL;
+
+ if (write_mmap(td->fd, pid, tid, MAP_START, 0x10000, 0, td->prog_file_name))
+ return TEST_FAIL;
+
+ if (write_sample(td, sample_type, id, pid, tid) != TEST_OK)
+ return TEST_FAIL;
+
+ if (verbose > 1)
+ system_cmd("%s script -i %s -D", td->perf, td->perf_data_file_name);
+
+ err = run_perf_script(td);
+ if (err)
+ return TEST_FAIL;
+
+ return TEST_OK;
+}
+
+static void unlink_path(const char *path)
+{
+ if (*path)
+ unlink(path);
+}
+
+static void test_data__free(struct test_data *td)
+{
+ machine__delete(td->machine);
+ close_fd(td->fd);
+ if (verbose <= 2) {
+ unlink_path(td->c_file_name);
+ unlink_path(td->prog_file_name);
+ unlink_path(td->perf_data_file_name);
+ }
+}
+
+int test__dlfilter(struct test *test __maybe_unused, int subtest __maybe_unused)
+{
+ struct test_data td = {.fd = -1};
+ int pid = getpid();
+ int err;
+
+ perf_exe(td.perf, sizeof(td.perf));
+
+ snprintf(td.perf_data_file_name, PATH_MAX, "/tmp/dlfilter-test-%u-perf-data", pid);
+ snprintf(td.c_file_name, PATH_MAX, "/tmp/dlfilter-test-%u-prog.c", pid);
+ snprintf(td.prog_file_name, PATH_MAX, "/tmp/dlfilter-test-%u-prog", pid);
+
+ err = test__dlfilter_test(&td);
+ test_data__free(&td);
+ return err;
+}
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 627c1aaf1c9e..43e1b01e5afc 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -308,10 +308,20 @@ int test__dso_data_cache(struct test *test __maybe_unused, int subtest __maybe_u
return 0;
}
+static long new_limit(int count)
+{
+ int fd = open("/dev/null", O_RDONLY);
+ long ret = fd;
+ if (count > 0)
+ ret = new_limit(--count);
+ close(fd);
+ return ret;
+}
+
int test__dso_data_reopen(struct test *test __maybe_unused, int subtest __maybe_unused)
{
struct machine machine;
- long nr_end, nr = open_files_cnt();
+ long nr_end, nr = open_files_cnt(), lim = new_limit(3);
int fd, fd_extra;
#define dso_0 (dsos[0])
@@ -334,7 +344,7 @@ int test__dso_data_reopen(struct test *test __maybe_unused, int subtest __maybe_
/* Make sure we are able to open 3 fds anyway */
TEST_ASSERT_VAL("failed to set file limit",
- !set_fd_limit((nr + 3)));
+ !set_fd_limit((lim)));
TEST_ASSERT_VAL("failed to create dsos\n", !dsos__create(3, TEST_FILE_SIZE));
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index 98da8a8757ab..33e43cce9064 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -67,12 +67,11 @@ test_llvm__fetch_bpf_obj(void **p_obj_buf,
/*
* Skip this test if user's .perfconfig doesn't set [llvm] section
- * and clang is not found in $PATH, and this is not perf test -v
+ * and clang is not found in $PATH
*/
- if (!force && (verbose <= 0 &&
- !llvm_param.user_set_param &&
+ if (!force && (!llvm_param.user_set_param &&
llvm__search_clang())) {
- pr_debug("No clang and no verbosive, skip this test\n");
+ pr_debug("No clang, skip this test\n");
return TEST_SKIP;
}
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 8d4866739255..fd3556cc9ad4 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -9,6 +9,7 @@
#include "pmu-hybrid.h"
#include <dirent.h>
#include <errno.h>
+#include "fncache.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -2194,9 +2195,91 @@ static int test_pmu_events(void)
return ret;
}
+static bool test_alias(char **event, char **alias)
+{
+ char path[PATH_MAX];
+ DIR *dir;
+ struct dirent *dent;
+ const char *sysfs = sysfs__mountpoint();
+ char buf[128];
+ FILE *file;
+
+ if (!sysfs)
+ return false;
+
+ snprintf(path, PATH_MAX, "%s/bus/event_source/devices/", sysfs);
+ dir = opendir(path);
+ if (!dir)
+ return false;
+
+ while ((dent = readdir(dir))) {
+ if (!strcmp(dent->d_name, ".") ||
+ !strcmp(dent->d_name, ".."))
+ continue;
+
+ snprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/alias",
+ sysfs, dent->d_name);
+
+ if (!file_available(path))
+ continue;
+
+ file = fopen(path, "r");
+ if (!file)
+ continue;
+
+ if (!fgets(buf, sizeof(buf), file)) {
+ fclose(file);
+ continue;
+ }
+
+ /* Remove the last '\n' */
+ buf[strlen(buf) - 1] = 0;
+
+ fclose(file);
+ *event = strdup(dent->d_name);
+ *alias = strdup(buf);
+ closedir(dir);
+
+ if (*event == NULL || *alias == NULL) {
+ free(*event);
+ free(*alias);
+ return false;
+ }
+
+ return true;
+ }
+
+ closedir(dir);
+ return false;
+}
+
+static int test__checkevent_pmu_events_alias(struct evlist *evlist)
+{
+ struct evsel *evsel1 = evlist__first(evlist);
+ struct evsel *evsel2 = evlist__last(evlist);
+
+ TEST_ASSERT_VAL("wrong type", evsel1->core.attr.type == evsel2->core.attr.type);
+ TEST_ASSERT_VAL("wrong config", evsel1->core.attr.config == evsel2->core.attr.config);
+ return 0;
+}
+
+static int test_pmu_events_alias(char *event, char *alias)
+{
+ struct evlist_test e = { .id = 0, };
+ char name[2 * NAME_MAX + 20];
+
+ snprintf(name, sizeof(name), "%s/event=1/,%s/event=1/",
+ event, alias);
+
+ e.name = name;
+ e.check = test__checkevent_pmu_events_alias;
+ return test_event(&e);
+}
+
int test__parse_events(struct test *test __maybe_unused, int subtest __maybe_unused)
{
int ret1, ret2 = 0;
+ char *event, *alias;
#define TEST_EVENTS(tests) \
do { \
@@ -2221,6 +2304,15 @@ do { \
return ret;
}
+ if (test_alias(&event, &alias)) {
+ int ret = test_pmu_events_alias(event, alias);
+
+ free(event);
+ free(alias);
+ if (ret)
+ return ret;
+ }
+
ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
if (!ret2)
ret2 = ret1;
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index b8aff8fb50d8..43743cf719ef 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -28,110 +28,190 @@ struct perf_pmu_test_event {
* be set in the alias.
*/
const char *alias_long_desc;
+
+ /* PMU which we should match against */
+ const char *matching_pmu;
};
-static struct perf_pmu_test_event test_cpu_events[] = {
- {
- .event = {
- .name = "bp_l1_btb_correct",
- .event = "event=0x8a",
- .desc = "L1 BTB Correction",
- .topic = "branch",
- },
- .alias_str = "event=0x8a",
- .alias_long_desc = "L1 BTB Correction",
+struct perf_pmu_test_pmu {
+ struct perf_pmu pmu;
+ struct perf_pmu_test_event const *aliases[10];
+};
+
+static const struct perf_pmu_test_event bp_l1_btb_correct = {
+ .event = {
+ .name = "bp_l1_btb_correct",
+ .event = "event=0x8a",
+ .desc = "L1 BTB Correction",
+ .topic = "branch",
},
- {
- .event = {
- .name = "bp_l2_btb_correct",
- .event = "event=0x8b",
- .desc = "L2 BTB Correction",
- .topic = "branch",
- },
- .alias_str = "event=0x8b",
- .alias_long_desc = "L2 BTB Correction",
+ .alias_str = "event=0x8a",
+ .alias_long_desc = "L1 BTB Correction",
+};
+
+static const struct perf_pmu_test_event bp_l2_btb_correct = {
+ .event = {
+ .name = "bp_l2_btb_correct",
+ .event = "event=0x8b",
+ .desc = "L2 BTB Correction",
+ .topic = "branch",
},
- {
- .event = {
- .name = "segment_reg_loads.any",
- .event = "umask=0x80,period=200000,event=0x6",
- .desc = "Number of segment register loads",
- .topic = "other",
- },
- .alias_str = "umask=0x80,(null)=0x30d40,event=0x6",
- .alias_long_desc = "Number of segment register loads",
+ .alias_str = "event=0x8b",
+ .alias_long_desc = "L2 BTB Correction",
+};
+
+static const struct perf_pmu_test_event segment_reg_loads_any = {
+ .event = {
+ .name = "segment_reg_loads.any",
+ .event = "umask=0x80,period=200000,event=0x6",
+ .desc = "Number of segment register loads",
+ .topic = "other",
},
- {
- .event = {
- .name = "dispatch_blocked.any",
- .event = "umask=0x20,period=200000,event=0x9",
- .desc = "Memory cluster signals to block micro-op dispatch for any reason",
- .topic = "other",
- },
- .alias_str = "umask=0x20,(null)=0x30d40,event=0x9",
- .alias_long_desc = "Memory cluster signals to block micro-op dispatch for any reason",
+ .alias_str = "umask=0x80,(null)=0x30d40,event=0x6",
+ .alias_long_desc = "Number of segment register loads",
+};
+
+static const struct perf_pmu_test_event dispatch_blocked_any = {
+ .event = {
+ .name = "dispatch_blocked.any",
+ .event = "umask=0x20,period=200000,event=0x9",
+ .desc = "Memory cluster signals to block micro-op dispatch for any reason",
+ .topic = "other",
},
- {
- .event = {
- .name = "eist_trans",
- .event = "umask=0x0,period=200000,event=0x3a",
- .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
- .topic = "other",
- },
- .alias_str = "umask=0,(null)=0x30d40,event=0x3a",
- .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
+ .alias_str = "umask=0x20,(null)=0x30d40,event=0x9",
+ .alias_long_desc = "Memory cluster signals to block micro-op dispatch for any reason",
+};
+
+static const struct perf_pmu_test_event eist_trans = {
+ .event = {
+ .name = "eist_trans",
+ .event = "umask=0x0,period=200000,event=0x3a",
+ .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
+ .topic = "other",
},
- {
- .event = {
- .name = "l3_cache_rd",
- .event = "event=0x40",
- .desc = "L3 cache access, read",
- .long_desc = "Attributable Level 3 cache access, read",
- .topic = "cache",
- },
- .alias_str = "event=0x40",
- .alias_long_desc = "Attributable Level 3 cache access, read",
+ .alias_str = "umask=0,(null)=0x30d40,event=0x3a",
+ .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
+};
+
+static const struct perf_pmu_test_event l3_cache_rd = {
+ .event = {
+ .name = "l3_cache_rd",
+ .event = "event=0x40",
+ .desc = "L3 cache access, read",
+ .long_desc = "Attributable Level 3 cache access, read",
+ .topic = "cache",
},
- { /* sentinel */
- .event = {
- .name = NULL,
- },
+ .alias_str = "event=0x40",
+ .alias_long_desc = "Attributable Level 3 cache access, read",
+};
+
+static const struct perf_pmu_test_event *core_events[] = {
+ &bp_l1_btb_correct,
+ &bp_l2_btb_correct,
+ &segment_reg_loads_any,
+ &dispatch_blocked_any,
+ &eist_trans,
+ &l3_cache_rd,
+ NULL
+};
+
+static const struct perf_pmu_test_event uncore_hisi_ddrc_flux_wcmd = {
+ .event = {
+ .name = "uncore_hisi_ddrc.flux_wcmd",
+ .event = "event=0x2",
+ .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
+ .topic = "uncore",
+ .long_desc = "DDRC write commands",
+ .pmu = "hisi_sccl,ddrc",
},
+ .alias_str = "event=0x2",
+ .alias_long_desc = "DDRC write commands",
+ .matching_pmu = "hisi_sccl1_ddrc2",
};
-static struct perf_pmu_test_event test_uncore_events[] = {
- {
- .event = {
- .name = "uncore_hisi_ddrc.flux_wcmd",
- .event = "event=0x2",
- .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
- .topic = "uncore",
- .long_desc = "DDRC write commands",
- .pmu = "hisi_sccl,ddrc",
- },
- .alias_str = "event=0x2",
- .alias_long_desc = "DDRC write commands",
+static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = {
+ .event = {
+ .name = "unc_cbo_xsnp_response.miss_eviction",
+ .event = "umask=0x81,event=0x22",
+ .desc = "Unit: uncore_cbox A cross-core snoop resulted from L3 Eviction which misses in some processor core",
+ .topic = "uncore",
+ .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
+ .pmu = "uncore_cbox",
},
- {
- .event = {
- .name = "unc_cbo_xsnp_response.miss_eviction",
- .event = "umask=0x81,event=0x22",
- .desc = "Unit: uncore_cbox A cross-core snoop resulted from L3 Eviction which misses in some processor core",
- .topic = "uncore",
- .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
- .pmu = "uncore_cbox",
- },
- .alias_str = "umask=0x81,event=0x22",
- .alias_long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
+ .alias_str = "umask=0x81,event=0x22",
+ .alias_long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
+ .matching_pmu = "uncore_cbox_0",
+};
+
+static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = {
+ .event = {
+ .name = "uncore_hisi_l3c.rd_hit_cpipe",
+ .event = "event=0x2",
+ .desc = "Total read hits. Unit: hisi_sccl,l3c ",
+ .topic = "uncore",
+ .long_desc = "Total read hits",
+ .pmu = "hisi_sccl,l3c",
},
- { /* sentinel */
- .event = {
- .name = NULL,
- },
- }
+ .alias_str = "event=0x7",
+ .alias_long_desc = "Total read hits",
+ .matching_pmu = "hisi_sccl3_l3c7",
+};
+
+static const struct perf_pmu_test_event uncore_imc_free_running_cache_miss = {
+ .event = {
+ .name = "uncore_imc_free_running.cache_miss",
+ .event = "event=0x12",
+ .desc = "Total cache misses. Unit: uncore_imc_free_running ",
+ .topic = "uncore",
+ .long_desc = "Total cache misses",
+ .pmu = "uncore_imc_free_running",
+ },
+ .alias_str = "event=0x12",
+ .alias_long_desc = "Total cache misses",
+ .matching_pmu = "uncore_imc_free_running_0",
+};
+
+static const struct perf_pmu_test_event uncore_imc_cache_hits = {
+ .event = {
+ .name = "uncore_imc.cache_hits",
+ .event = "event=0x34",
+ .desc = "Total cache hits. Unit: uncore_imc ",
+ .topic = "uncore",
+ .long_desc = "Total cache hits",
+ .pmu = "uncore_imc",
+ },
+ .alias_str = "event=0x34",
+ .alias_long_desc = "Total cache hits",
+ .matching_pmu = "uncore_imc_0",
+};
+
+static const struct perf_pmu_test_event *uncore_events[] = {
+ &uncore_hisi_ddrc_flux_wcmd,
+ &unc_cbo_xsnp_response_miss_eviction,
+ &uncore_hisi_l3c_rd_hit_cpipe,
+ &uncore_imc_free_running_cache_miss,
+ &uncore_imc_cache_hits,
+ NULL
};
-const int total_test_events_size = ARRAY_SIZE(test_uncore_events);
+static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = {
+ .event = {
+ .name = "sys_ddr_pmu.write_cycles",
+ .event = "event=0x2b",
+ .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
+ .topic = "uncore",
+ .pmu = "uncore_sys_ddr_pmu",
+ .compat = "v8",
+ },
+ .alias_str = "event=0x2b",
+ .alias_long_desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
+ .matching_pmu = "uncore_sys_ddr_pmu",
+};
+
+static const struct perf_pmu_test_event *sys_events[] = {
+ &sys_ddr_pmu_write_cycles,
+ NULL
+};
static bool is_same(const char *reference, const char *test)
{
@@ -161,99 +241,207 @@ static struct pmu_events_map *__test_pmu_get_events_map(void)
return NULL;
}
-/* Verify generated events from pmu-events.c is as expected */
+static struct pmu_event *__test_pmu_get_sys_events_table(void)
+{
+ struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
+
+ for ( ; tables->name; tables++) {
+ if (!strcmp("pme_test_soc_sys", tables->name))
+ return tables->table;
+ }
+
+ return NULL;
+}
+
+static int compare_pmu_events(struct pmu_event *e1, const struct pmu_event *e2)
+{
+ if (!is_same(e1->desc, e2->desc)) {
+ pr_debug2("testing event e1 %s: mismatched desc, %s vs %s\n",
+ e1->name, e1->desc, e2->desc);
+ return -1;
+ }
+
+ if (!is_same(e1->topic, e2->topic)) {
+ pr_debug2("testing event e1 %s: mismatched topic, %s vs %s\n",
+ e1->name, e1->topic, e2->topic);
+ return -1;
+ }
+
+ if (!is_same(e1->long_desc, e2->long_desc)) {
+ pr_debug2("testing event e1 %s: mismatched long_desc, %s vs %s\n",
+ e1->name, e1->long_desc, e2->long_desc);
+ return -1;
+ }
+
+ if (!is_same(e1->unit, e2->unit)) {
+ pr_debug2("testing event e1 %s: mismatched unit, %s vs %s\n",
+ e1->name, e1->unit, e2->unit);
+ return -1;
+ }
+
+ if (!is_same(e1->perpkg, e2->perpkg)) {
+ pr_debug2("testing event e1 %s: mismatched perpkg, %s vs %s\n",
+ e1->name, e1->perpkg, e2->perpkg);
+ return -1;
+ }
+
+ if (!is_same(e1->metric_expr, e2->metric_expr)) {
+ pr_debug2("testing event e1 %s: mismatched metric_expr, %s vs %s\n",
+ e1->name, e1->metric_expr, e2->metric_expr);
+ return -1;
+ }
+
+ if (!is_same(e1->metric_name, e2->metric_name)) {
+ pr_debug2("testing event e1 %s: mismatched metric_name, %s vs %s\n",
+ e1->name, e1->metric_name, e2->metric_name);
+ return -1;
+ }
+
+ if (!is_same(e1->deprecated, e2->deprecated)) {
+ pr_debug2("testing event e1 %s: mismatched deprecated, %s vs %s\n",
+ e1->name, e1->deprecated, e2->deprecated);
+ return -1;
+ }
+
+ if (!is_same(e1->pmu, e2->pmu)) {
+ pr_debug2("testing event e1 %s: mismatched pmu string, %s vs %s\n",
+ e1->name, e1->pmu, e2->pmu);
+ return -1;
+ }
+
+ if (!is_same(e1->compat, e2->compat)) {
+ pr_debug2("testing event e1 %s: mismatched compat string, %s vs %s\n",
+ e1->name, e1->compat, e2->compat);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int compare_alias_to_test_event(struct perf_pmu_alias *alias,
+ struct perf_pmu_test_event const *test_event,
+ char const *pmu_name)
+{
+ struct pmu_event const *event = &test_event->event;
+
+ /* An alias was found, ensure everything is in order */
+ if (!is_same(alias->name, event->name)) {
+ pr_debug("testing aliases PMU %s: mismatched name, %s vs %s\n",
+ pmu_name, alias->name, event->name);
+ return -1;
+ }
+
+ if (!is_same(alias->desc, event->desc)) {
+ pr_debug("testing aliases PMU %s: mismatched desc, %s vs %s\n",
+ pmu_name, alias->desc, event->desc);
+ return -1;
+ }
+
+ if (!is_same(alias->long_desc, test_event->alias_long_desc)) {
+ pr_debug("testing aliases PMU %s: mismatched long_desc, %s vs %s\n",
+ pmu_name, alias->long_desc,
+ test_event->alias_long_desc);
+ return -1;
+ }
+
+ if (!is_same(alias->topic, event->topic)) {
+ pr_debug("testing aliases PMU %s: mismatched topic, %s vs %s\n",
+ pmu_name, alias->topic, event->topic);
+ return -1;
+ }
+
+ if (!is_same(alias->str, test_event->alias_str)) {
+ pr_debug("testing aliases PMU %s: mismatched str, %s vs %s\n",
+ pmu_name, alias->str, test_event->alias_str);
+ return -1;
+ }
+
+ if (!is_same(alias->long_desc, test_event->alias_long_desc)) {
+ pr_debug("testing aliases PMU %s: mismatched long desc, %s vs %s\n",
+ pmu_name, alias->str, test_event->alias_long_desc);
+ return -1;
+ }
+
+
+ if (!is_same(alias->pmu_name, test_event->event.pmu)) {
+ pr_debug("testing aliases PMU %s: mismatched pmu_name, %s vs %s\n",
+ pmu_name, alias->pmu_name, test_event->event.pmu);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Verify generated events from pmu-events.c are as expected */
static int test_pmu_event_table(void)
{
+ struct pmu_event *sys_event_tables = __test_pmu_get_sys_events_table();
struct pmu_events_map *map = __test_pmu_get_events_map();
struct pmu_event *table;
int map_events = 0, expected_events;
- /* ignore 2x sentinels */
- expected_events = ARRAY_SIZE(test_cpu_events) +
- ARRAY_SIZE(test_uncore_events) - 2;
+ /* ignore 3x sentinels */
+ expected_events = ARRAY_SIZE(core_events) +
+ ARRAY_SIZE(uncore_events) +
+ ARRAY_SIZE(sys_events) - 3;
- if (!map)
+ if (!map || !sys_event_tables)
return -1;
for (table = map->table; table->name; table++) {
- struct perf_pmu_test_event *test;
- struct pmu_event *te;
+ struct perf_pmu_test_event const **test_event_table;
bool found = false;
if (table->pmu)
- test = &test_uncore_events[0];
+ test_event_table = &uncore_events[0];
else
- test = &test_cpu_events[0];
+ test_event_table = &core_events[0];
- te = &test->event;
+ for (; *test_event_table; test_event_table++) {
+ struct perf_pmu_test_event const *test_event = *test_event_table;
+ struct pmu_event const *event = &test_event->event;
- for (; te->name; test++, te = &test->event) {
- if (strcmp(table->name, te->name))
+ if (strcmp(table->name, event->name))
continue;
found = true;
map_events++;
- if (!is_same(table->desc, te->desc)) {
- pr_debug2("testing event table %s: mismatched desc, %s vs %s\n",
- table->name, table->desc, te->desc);
+ if (compare_pmu_events(table, event))
return -1;
- }
- if (!is_same(table->topic, te->topic)) {
- pr_debug2("testing event table %s: mismatched topic, %s vs %s\n",
- table->name, table->topic,
- te->topic);
- return -1;
- }
+ pr_debug("testing event table %s: pass\n", table->name);
+ }
- if (!is_same(table->long_desc, te->long_desc)) {
- pr_debug2("testing event table %s: mismatched long_desc, %s vs %s\n",
- table->name, table->long_desc,
- te->long_desc);
- return -1;
- }
+ if (!found) {
+ pr_err("testing event table: could not find event %s\n",
+ table->name);
+ return -1;
+ }
+ }
- if (!is_same(table->unit, te->unit)) {
- pr_debug2("testing event table %s: mismatched unit, %s vs %s\n",
- table->name, table->unit,
- te->unit);
- return -1;
- }
+ for (table = sys_event_tables; table->name; table++) {
+ struct perf_pmu_test_event const **test_event_table;
+ bool found = false;
- if (!is_same(table->perpkg, te->perpkg)) {
- pr_debug2("testing event table %s: mismatched perpkg, %s vs %s\n",
- table->name, table->perpkg,
- te->perpkg);
- return -1;
- }
+ test_event_table = &sys_events[0];
- if (!is_same(table->metric_expr, te->metric_expr)) {
- pr_debug2("testing event table %s: mismatched metric_expr, %s vs %s\n",
- table->name, table->metric_expr,
- te->metric_expr);
- return -1;
- }
+ for (; *test_event_table; test_event_table++) {
+ struct perf_pmu_test_event const *test_event = *test_event_table;
+ struct pmu_event const *event = &test_event->event;
- if (!is_same(table->metric_name, te->metric_name)) {
- pr_debug2("testing event table %s: mismatched metric_name, %s vs %s\n",
- table->name, table->metric_name,
- te->metric_name);
- return -1;
- }
+ if (strcmp(table->name, event->name))
+ continue;
+ found = true;
+ map_events++;
- if (!is_same(table->deprecated, te->deprecated)) {
- pr_debug2("testing event table %s: mismatched deprecated, %s vs %s\n",
- table->name, table->deprecated,
- te->deprecated);
+ if (compare_pmu_events(table, event))
return -1;
- }
- pr_debug("testing event table %s: pass\n", table->name);
+ pr_debug("testing sys event table %s: pass\n", table->name);
}
-
if (!found) {
- pr_err("testing event table: could not find event %s\n",
- table->name);
+ pr_debug("testing event table: could not find event %s\n",
+ table->name);
return -1;
}
}
@@ -279,27 +467,19 @@ static struct perf_pmu_alias *find_alias(const char *test_event, struct list_hea
}
/* Verify aliases are as expected */
-static int __test__pmu_event_aliases(char *pmu_name, int *count)
+static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
{
- struct perf_pmu_test_event *test;
- struct pmu_event *te;
+ struct perf_pmu_test_event const **test_event_table;
struct perf_pmu *pmu;
LIST_HEAD(aliases);
int res = 0;
- bool use_uncore_table;
struct pmu_events_map *map = __test_pmu_get_events_map();
struct perf_pmu_alias *a, *tmp;
if (!map)
return -1;
- if (is_pmu_core(pmu_name)) {
- test = &test_cpu_events[0];
- use_uncore_table = false;
- } else {
- test = &test_uncore_events[0];
- use_uncore_table = true;
- }
+ test_event_table = &core_events[0];
pmu = zalloc(sizeof(*pmu));
if (!pmu)
@@ -309,91 +489,202 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count)
pmu_add_cpu_aliases_map(&aliases, pmu, map);
- for (te = &test->event; te->name; test++, te = &test->event) {
- struct perf_pmu_alias *alias = find_alias(te->name, &aliases);
+ for (; *test_event_table; test_event_table++) {
+ struct perf_pmu_test_event const *test_event = *test_event_table;
+ struct pmu_event const *event = &test_event->event;
+ struct perf_pmu_alias *alias = find_alias(event->name, &aliases);
if (!alias) {
- bool uncore_match = pmu_uncore_alias_match(pmu_name,
- te->pmu);
-
- if (use_uncore_table && !uncore_match) {
- pr_debug3("testing aliases PMU %s: skip matching alias %s\n",
- pmu_name, te->name);
- continue;
- }
-
- pr_debug2("testing aliases PMU %s: no alias, alias_table->name=%s\n",
- pmu_name, te->name);
+ pr_debug("testing aliases core PMU %s: no alias, alias_table->name=%s\n",
+ pmu_name, event->name);
res = -1;
break;
}
- if (!is_same(alias->desc, te->desc)) {
- pr_debug2("testing aliases PMU %s: mismatched desc, %s vs %s\n",
- pmu_name, alias->desc, te->desc);
+ if (compare_alias_to_test_event(alias, test_event, pmu_name)) {
res = -1;
break;
}
- if (!is_same(alias->long_desc, test->alias_long_desc)) {
- pr_debug2("testing aliases PMU %s: mismatched long_desc, %s vs %s\n",
- pmu_name, alias->long_desc,
- test->alias_long_desc);
- res = -1;
- break;
- }
+ (*count)++;
+ pr_debug2("testing aliases core PMU %s: matched event %s\n",
+ pmu_name, alias->name);
+ }
- if (!is_same(alias->str, test->alias_str)) {
- pr_debug2("testing aliases PMU %s: mismatched str, %s vs %s\n",
- pmu_name, alias->str, test->alias_str);
- res = -1;
- break;
+ list_for_each_entry_safe(a, tmp, &aliases, list) {
+ list_del(&a->list);
+ perf_pmu_free_alias(a);
+ }
+ free(pmu);
+ return res;
+}
+
+static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
+{
+ int alias_count = 0, to_match_count = 0, matched_count = 0;
+ struct perf_pmu_test_event const **table;
+ struct perf_pmu *pmu = &test_pmu->pmu;
+ const char *pmu_name = pmu->name;
+ struct perf_pmu_alias *a, *tmp, *alias;
+ struct pmu_events_map *map;
+ LIST_HEAD(aliases);
+ int res = 0;
+
+ map = __test_pmu_get_events_map();
+ if (!map)
+ return -1;
+ pmu_add_cpu_aliases_map(&aliases, pmu, map);
+ pmu_add_sys_aliases(&aliases, pmu);
+
+ /* Count how many aliases we generated */
+ list_for_each_entry(alias, &aliases, list)
+ alias_count++;
+
+ /* Count how many aliases we expect from the known table */
+ for (table = &test_pmu->aliases[0]; *table; table++)
+ to_match_count++;
+
+ if (alias_count != to_match_count) {
+ pr_debug("testing aliases uncore PMU %s: mismatch expected aliases (%d) vs found (%d)\n",
+ pmu_name, to_match_count, alias_count);
+ res = -1;
+ goto out;
+ }
+
+ list_for_each_entry(alias, &aliases, list) {
+ bool matched = false;
+
+ for (table = &test_pmu->aliases[0]; *table; table++) {
+ struct perf_pmu_test_event const *test_event = *table;
+ struct pmu_event const *event = &test_event->event;
+
+ if (!strcmp(event->name, alias->name)) {
+ if (compare_alias_to_test_event(alias,
+ test_event,
+ pmu_name)) {
+ continue;
+ }
+ matched = true;
+ matched_count++;
+ }
}
- if (!is_same(alias->topic, te->topic)) {
- pr_debug2("testing aliases PMU %s: mismatched topic, %s vs %s\n",
- pmu_name, alias->topic, te->topic);
+ if (matched == false) {
+ pr_debug("testing aliases uncore PMU %s: could not match alias %s\n",
+ pmu_name, alias->name);
res = -1;
- break;
+ goto out;
}
+ }
- (*count)++;
- pr_debug2("testing aliases PMU %s: matched event %s\n",
- pmu_name, alias->name);
+ if (alias_count != matched_count) {
+ pr_debug("testing aliases uncore PMU %s: mismatch found aliases (%d) vs matched (%d)\n",
+ pmu_name, matched_count, alias_count);
+ res = -1;
}
+out:
list_for_each_entry_safe(a, tmp, &aliases, list) {
list_del(&a->list);
perf_pmu_free_alias(a);
}
- free(pmu);
return res;
}
+static struct perf_pmu_test_pmu test_pmus[] = {
+ {
+ .pmu = {
+ .name = (char *)"hisi_sccl1_ddrc2",
+ .is_uncore = 1,
+ },
+ .aliases = {
+ &uncore_hisi_ddrc_flux_wcmd,
+ },
+ },
+ {
+ .pmu = {
+ .name = (char *)"uncore_cbox_0",
+ .is_uncore = 1,
+ },
+ .aliases = {
+ &unc_cbo_xsnp_response_miss_eviction,
+ },
+ },
+ {
+ .pmu = {
+ .name = (char *)"hisi_sccl3_l3c7",
+ .is_uncore = 1,
+ },
+ .aliases = {
+ &uncore_hisi_l3c_rd_hit_cpipe,
+ },
+ },
+ {
+ .pmu = {
+ .name = (char *)"uncore_imc_free_running_0",
+ .is_uncore = 1,
+ },
+ .aliases = {
+ &uncore_imc_free_running_cache_miss,
+ },
+ },
+ {
+ .pmu = {
+ .name = (char *)"uncore_imc_0",
+ .is_uncore = 1,
+ },
+ .aliases = {
+ &uncore_imc_cache_hits,
+ },
+ },
+ {
+ .pmu = {
+ .name = (char *)"uncore_sys_ddr_pmu0",
+ .is_uncore = 1,
+ .id = (char *)"v8",
+ },
+ .aliases = {
+ &sys_ddr_pmu_write_cycles,
+ },
+ },
+};
/* Test that aliases generated are as expected */
static int test_aliases(void)
{
struct perf_pmu *pmu = NULL;
+ unsigned long i;
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
int count = 0;
+ if (!is_pmu_core(pmu->name))
+ continue;
+
if (list_empty(&pmu->format)) {
- pr_debug2("skipping testing PMU %s\n", pmu->name);
+ pr_debug2("skipping testing core PMU %s\n", pmu->name);
continue;
}
- if (__test__pmu_event_aliases(pmu->name, &count)) {
- pr_debug("testing PMU %s aliases: failed\n", pmu->name);
+ if (__test_core_pmu_event_aliases(pmu->name, &count)) {
+ pr_debug("testing core PMU %s aliases: failed\n", pmu->name);
return -1;
}
- if (count == 0)
- pr_debug3("testing PMU %s aliases: no events to match\n",
+ if (count == 0) {
+ pr_debug("testing core PMU %s aliases: no events to match\n",
pmu->name);
- else
- pr_debug("testing PMU %s aliases: pass\n", pmu->name);
+ return -1;
+ }
+
+ pr_debug("testing core PMU %s aliases: pass\n", pmu->name);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(test_pmus); i++) {
+ int res = __test_uncore_pmu_event_aliases(&test_pmus[i]);
+
+ if (res)
+ return res;
}
return 0;
diff --git a/tools/perf/tests/shell/lib/probe_vfs_getname.sh b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
index c2cc42daf924..5b17d916c555 100644
--- a/tools/perf/tests/shell/lib/probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
@@ -19,6 +19,6 @@ add_probe_vfs_getname() {
}
skip_if_no_debuginfo() {
- add_probe_vfs_getname -v 2>&1 | egrep -q "^(Failed to find the path for kernel|Debuginfo-analysis is not supported)" && return 2
+ add_probe_vfs_getname -v 2>&1 | egrep -q "^(Failed to find the path for the kernel|Debuginfo-analysis is not supported)" && return 2
return 1
}
diff --git a/tools/perf/tests/shell/pipe_test.sh b/tools/perf/tests/shell/pipe_test.sh
new file mode 100755
index 000000000000..1b32b4f28391
--- /dev/null
+++ b/tools/perf/tests/shell/pipe_test.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+# perf pipe recording and injection test
+# SPDX-License-Identifier: GPL-2.0
+
+# skip if there's no compiler
+if ! [ -x "$(command -v cc)" ]; then
+ echo "failed: no compiler, install gcc"
+ exit 2
+fi
+
+file=$(mktemp /tmp/test.file.XXXXXX)
+data=$(mktemp /tmp/perf.data.XXXXXX)
+
+cat <<EOF | cc -o ${file} -x c -
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+volatile int done;
+
+void sigalrm(int sig) {
+ done = 1;
+}
+
+__attribute__((noinline)) void noploop(void) {
+ while (!done)
+ continue;
+}
+
+int main(int argc, char *argv[]) {
+ int sec = 1;
+
+ if (argc > 1)
+ sec = atoi(argv[1]);
+
+ signal(SIGALRM, sigalrm);
+ alarm(sec);
+
+ noploop();
+ return 0;
+}
+EOF
+
+
+if ! perf record -e task-clock:u -o - ${file} | perf report -i - --task | grep test.file; then
+ echo "cannot find the test file in the perf report"
+ exit 1
+fi
+
+if ! perf record -e task-clock:u -o - ${file} | perf inject -b | perf report -i - | grep noploop; then
+ echo "cannot find noploop function in pipe #1"
+ exit 1
+fi
+
+perf record -e task-clock:u -o - ${file} | perf inject -b -o ${data}
+if ! perf report -i ${data} | grep noploop; then
+ echo "cannot find noploop function in pipe #2"
+ exit 1
+fi
+
+perf record -e task-clock:u -o ${data} ${file}
+if ! perf inject -b -i ${data} | perf report -i - | grep noploop; then
+ echo "cannot find noploop function in pipe #3"
+ exit 1
+fi
+
+
+rm -f ${file} ${data} ${data}.old
+exit 0
diff --git a/tools/perf/tests/shell/record+zstd_comp_decomp.sh b/tools/perf/tests/shell/record+zstd_comp_decomp.sh
index 045723b3d992..8a168cf8bacc 100755
--- a/tools/perf/tests/shell/record+zstd_comp_decomp.sh
+++ b/tools/perf/tests/shell/record+zstd_comp_decomp.sh
@@ -25,8 +25,8 @@ check_compressed_stats() {
check_compressed_output() {
$perf_tool inject -i $trace_file -o $trace_file.decomp &&
- $perf_tool report -i $trace_file --stdio | head -n -3 > $trace_file.comp.output &&
- $perf_tool report -i $trace_file.decomp --stdio | head -n -3 > $trace_file.decomp.output &&
+ $perf_tool report -i $trace_file --stdio -F comm,dso,sym | head -n -3 > $trace_file.comp.output &&
+ $perf_tool report -i $trace_file.decomp --stdio -F comm,dso,sym | head -n -3 > $trace_file.decomp.output &&
diff $trace_file.comp.output $trace_file.decomp.output
}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 1100dd55b657..fe1306f58495 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -127,6 +127,7 @@ int test__parse_metric(struct test *test, int subtest);
int test__pe_file_parsing(struct test *test, int subtest);
int test__expand_cgroup_events(struct test *test, int subtest);
int test__perf_time_to_tsc(struct test *test, int subtest);
+int test__dlfilter(struct test *test, int subtest);
bool test__bp_signal_is_supported(void);
bool test__bp_account_is_supported(void);
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index b5efe675b321..b9028e304ddd 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -38,7 +38,7 @@ static int session_write_header(char *path)
.mode = PERF_DATA_MODE_WRITE,
};
- session = perf_session__new(&data, false, NULL);
+ session = perf_session__new(&data, NULL);
TEST_ASSERT_VAL("can't get session", !IS_ERR(session));
if (!perf_pmu__has_hybrid()) {
@@ -77,7 +77,7 @@ static int check_cpu_topology(char *path, struct perf_cpu_map *map)
int i;
struct aggr_cpu_id id;
- session = perf_session__new(&data, false, NULL);
+ session = perf_session__new(&data, NULL);
TEST_ASSERT_VAL("can't get session", !IS_ERR(session));
cpu__setup_cpunode_map();
diff --git a/tools/perf/trace/beauty/arch_errno_names.sh b/tools/perf/trace/beauty/arch_errno_names.sh
index 9f9ea45cddc4..2c5f72fa8108 100755
--- a/tools/perf/trace/beauty/arch_errno_names.sh
+++ b/tools/perf/trace/beauty/arch_errno_names.sh
@@ -87,14 +87,13 @@ cat <<EoHEADER
EoHEADER
-# Create list of architectures and ignore those that do not appear
-# in tools/perf/arch
+# Create list of architectures that have a specific errno.h.
archlist=""
-for arch in $(find $toolsdir/arch -maxdepth 1 -mindepth 1 -type d -printf "%f\n" | grep -v x86 | sort); do
- test -d $toolsdir/perf/arch/$arch && archlist="$archlist $arch"
+for arch in $(find $toolsdir/arch -maxdepth 1 -mindepth 1 -type d -printf "%f\n" | sort -r); do
+ test -f $toolsdir/arch/$arch/include/uapi/asm/errno.h && archlist="$archlist $arch"
done
-for arch in x86 $archlist generic; do
+for arch in generic $archlist; do
process_arch "$arch"
done
-create_arch_errno_table_func "x86 $archlist" "generic"
+create_arch_errno_table_func "$archlist" "generic"
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 701130ad43a2..ef4da4295bf7 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -966,6 +966,7 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
err = symbol__annotate2(ms, evsel, opts, &browser.arch);
if (err) {
char msg[BUFSIZ];
+ ms->map->dso->annotate_warned = true;
symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
goto out_free_offsets;
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index 94167bfed722..0a50e962f9a3 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -177,6 +177,7 @@ static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel,
err = symbol__annotate(ms, evsel, &annotation__default_options, NULL);
if (err) {
char msg[BUFSIZ];
+ ms->map->dso->annotate_warned = true;
symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
ui__error("Couldn't annotate %s: %s\n", sym->name, msg);
return -1;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index aa04a3655236..0bae061b2d6d 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1833,7 +1833,7 @@ static int symbol__disassemble_bpf(struct symbol *sym,
ret = 0;
out:
free(prog_linfo);
- free(btf);
+ btf__free(btf);
fclose(s);
bfd_close(bfdf);
return ret;
@@ -2192,8 +2192,10 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
return errno;
args.arch = arch = arch__find(arch_name);
- if (arch == NULL)
+ if (arch == NULL) {
+ pr_err("%s: unsupported arch %s\n", __func__, arch_name);
return ENOTSUP;
+ }
if (parch)
*parch = arch;
@@ -2787,9 +2789,17 @@ int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel,
struct rb_root source_line = RB_ROOT;
struct hists *hists = evsel__hists(evsel);
char buf[1024];
+ int err;
- if (symbol__annotate2(ms, evsel, opts, NULL) < 0)
+ err = symbol__annotate2(ms, evsel, opts, NULL);
+ if (err) {
+ char msg[BUFSIZ];
+
+ dso->annotate_warned = true;
+ symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
+ ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
return -1;
+ }
if (opts->print_lines) {
srcline_full_filename = opts->full_path;
@@ -2813,9 +2823,17 @@ int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
struct dso *dso = ms->map->dso;
struct symbol *sym = ms->sym;
struct rb_root source_line = RB_ROOT;
+ int err;
+
+ err = symbol__annotate(ms, evsel, opts, NULL);
+ if (err) {
+ char msg[BUFSIZ];
- if (symbol__annotate(ms, evsel, opts, NULL) < 0)
+ dso->annotate_warned = true;
+ symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
+ ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
return -1;
+ }
symbol__calc_percent(sym, evsel);
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index cb19669d2a5b..8d2865b9ade2 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -130,11 +130,6 @@ int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
return 0;
}
-#if BITS_PER_LONG != 64 && !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
- pr_err("Cannot use AUX area tracing mmaps\n");
- return -1;
-#endif
-
pc->aux_offset = mp->offset;
pc->aux_size = mp->len;
@@ -1674,6 +1669,82 @@ int perf_event__process_auxtrace_error(struct perf_session *session,
return 0;
}
+/*
+ * In the compat mode kernel runs in 64-bit and perf tool runs in 32-bit mode,
+ * 32-bit perf tool cannot access 64-bit value atomically, which might lead to
+ * the issues caused by the below sequence on multiple CPUs: when perf tool
+ * accesses either the load operation or the store operation for 64-bit value,
+ * on some architectures the operation is divided into two instructions, one
+ * is for accessing the low 32-bit value and another is for the high 32-bit;
+ * thus these two user operations can give the kernel chances to access the
+ * 64-bit value, and thus leads to the unexpected load values.
+ *
+ * kernel (64-bit) user (32-bit)
+ *
+ * if (LOAD ->aux_tail) { --, LOAD ->aux_head_lo
+ * STORE $aux_data | ,--->
+ * FLUSH $aux_data | | LOAD ->aux_head_hi
+ * STORE ->aux_head --|-------` smp_rmb()
+ * } | LOAD $data
+ * | smp_mb()
+ * | STORE ->aux_tail_lo
+ * `----------->
+ * STORE ->aux_tail_hi
+ *
+ * For this reason, it's impossible for the perf tool to work correctly when
+ * the AUX head or tail is bigger than 4GB (more than 32 bits length); and we
+ * can not simply limit the AUX ring buffer to less than 4GB, the reason is
+ * the pointers can be increased monotonically, whatever the buffer size it is,
+ * at the end the head and tail can be bigger than 4GB and carry out to the
+ * high 32-bit.
+ *
+ * To mitigate the issues and improve the user experience, we can allow the
+ * perf tool working in certain conditions and bail out with error if detect
+ * any overflow cannot be handled.
+ *
+ * For reading the AUX head, it reads out the values for three times, and
+ * compares the high 4 bytes of the values between the first time and the last
+ * time, if there has no change for high 4 bytes injected by the kernel during
+ * the user reading sequence, it's safe for use the second value.
+ *
+ * When compat_auxtrace_mmap__write_tail() detects any carrying in the high
+ * 32 bits, it means there have two store operations in user space and it cannot
+ * promise the atomicity for 64-bit write, so return '-1' in this case to tell
+ * the caller an overflow error has happened.
+ */
+u64 __weak compat_auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
+{
+ struct perf_event_mmap_page *pc = mm->userpg;
+ u64 first, second, last;
+ u64 mask = (u64)(UINT32_MAX) << 32;
+
+ do {
+ first = READ_ONCE(pc->aux_head);
+ /* Ensure all reads are done after we read the head */
+ smp_rmb();
+ second = READ_ONCE(pc->aux_head);
+ /* Ensure all reads are done after we read the head */
+ smp_rmb();
+ last = READ_ONCE(pc->aux_head);
+ } while ((first & mask) != (last & mask));
+
+ return second;
+}
+
+int __weak compat_auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail)
+{
+ struct perf_event_mmap_page *pc = mm->userpg;
+ u64 mask = (u64)(UINT32_MAX) << 32;
+
+ if (tail & mask)
+ return -1;
+
+ /* Ensure all reads are done before we write the tail out */
+ smp_mb();
+ WRITE_ONCE(pc->aux_tail, tail);
+ return 0;
+}
+
static int __auxtrace_mmap__read(struct mmap *map,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
@@ -1685,15 +1756,13 @@ static int __auxtrace_mmap__read(struct mmap *map,
size_t size, head_off, old_off, len1, len2, padding;
union perf_event ev;
void *data1, *data2;
+ int kernel_is_64_bit = perf_env__kernel_is_64_bit(evsel__env(NULL));
- if (snapshot) {
- head = auxtrace_mmap__read_snapshot_head(mm);
- if (auxtrace_record__find_snapshot(itr, mm->idx, mm, data,
- &head, &old))
- return -1;
- } else {
- head = auxtrace_mmap__read_head(mm);
- }
+ head = auxtrace_mmap__read_head(mm, kernel_is_64_bit);
+
+ if (snapshot &&
+ auxtrace_record__find_snapshot(itr, mm->idx, mm, data, &head, &old))
+ return -1;
if (old == head)
return 0;
@@ -1772,10 +1841,13 @@ static int __auxtrace_mmap__read(struct mmap *map,
mm->prev = head;
if (!snapshot) {
- auxtrace_mmap__write_tail(mm, head);
- if (itr->read_finish) {
- int err;
+ int err;
+ err = auxtrace_mmap__write_tail(mm, head, kernel_is_64_bit);
+ if (err < 0)
+ return err;
+
+ if (itr->read_finish) {
err = itr->read_finish(itr, mm->idx);
if (err < 0)
return err;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index cc1c1b9cec9c..5f383908ca6e 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -440,52 +440,39 @@ struct auxtrace_cache;
#ifdef HAVE_AUXTRACE_SUPPORT
-/*
- * In snapshot mode the mmapped page is read-only which makes using
- * __sync_val_compare_and_swap() problematic. However, snapshot mode expects
- * the buffer is not updated while the snapshot is made (e.g. Intel PT disables
- * the event) so there is not a race anyway.
- */
-static inline u64 auxtrace_mmap__read_snapshot_head(struct auxtrace_mmap *mm)
-{
- struct perf_event_mmap_page *pc = mm->userpg;
- u64 head = READ_ONCE(pc->aux_head);
-
- /* Ensure all reads are done after we read the head */
- smp_rmb();
- return head;
-}
+u64 compat_auxtrace_mmap__read_head(struct auxtrace_mmap *mm);
+int compat_auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail);
-static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
+static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm,
+ int kernel_is_64_bit __maybe_unused)
{
struct perf_event_mmap_page *pc = mm->userpg;
-#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
- u64 head = READ_ONCE(pc->aux_head);
-#else
- u64 head = __sync_val_compare_and_swap(&pc->aux_head, 0, 0);
+ u64 head;
+
+#if BITS_PER_LONG == 32
+ if (kernel_is_64_bit)
+ return compat_auxtrace_mmap__read_head(mm);
#endif
+ head = READ_ONCE(pc->aux_head);
/* Ensure all reads are done after we read the head */
smp_rmb();
return head;
}
-static inline void auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail)
+static inline int auxtrace_mmap__write_tail(struct auxtrace_mmap *mm, u64 tail,
+ int kernel_is_64_bit __maybe_unused)
{
struct perf_event_mmap_page *pc = mm->userpg;
-#if BITS_PER_LONG != 64 && defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
- u64 old_tail;
-#endif
+#if BITS_PER_LONG == 32
+ if (kernel_is_64_bit)
+ return compat_auxtrace_mmap__write_tail(mm, tail);
+#endif
/* Ensure all reads are done before we write the tail out */
smp_mb();
-#if BITS_PER_LONG == 64 || !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
- pc->aux_tail = tail;
-#else
- do {
- old_tail = __sync_val_compare_and_swap(&pc->aux_tail, 0, 0);
- } while (!__sync_bool_compare_and_swap(&pc->aux_tail, old_tail, tail));
-#endif
+ WRITE_ONCE(pc->aux_tail, tail);
+ return 0;
}
int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 63d472b336de..4fb5e90d7a57 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -581,7 +581,10 @@ const char *perf_home_perfconfig(void)
static const char *config;
static bool failed;
- config = failed ? NULL : home_perfconfig();
+ if (failed || config)
+ return config;
+
+ config = home_perfconfig();
if (!config)
failed = true;
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index 3e1a05bc82cc..31fa3b45134a 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -13,8 +13,6 @@
#include <linux/zalloc.h>
#include <stdlib.h>
#include <opencsd/c_api/opencsd_c_api.h>
-#include <opencsd/etmv4/trc_pkt_types_etmv4.h>
-#include <opencsd/ocsd_if_types.h>
#include "cs-etm.h"
#include "cs-etm-decoder.h"
@@ -35,9 +33,11 @@
struct cs_etm_decoder {
void *data;
void (*packet_printer)(const char *msg);
+ bool suppress_printing;
dcd_tree_handle_t dcd_tree;
cs_etm_mem_cb_type mem_access;
ocsd_datapath_resp_t prev_return;
+ const char *decoder_name;
};
static u32
@@ -74,9 +74,10 @@ int cs_etm_decoder__reset(struct cs_etm_decoder *decoder)
ocsd_datapath_resp_t dp_ret;
decoder->prev_return = OCSD_RESP_CONT;
-
+ decoder->suppress_printing = true;
dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET,
0, 0, NULL, NULL);
+ decoder->suppress_printing = false;
if (OCSD_DATA_RESP_IS_FATAL(dp_ret))
return -1;
@@ -124,6 +125,21 @@ static int cs_etm_decoder__gen_etmv3_config(struct cs_etm_trace_params *params,
return 0;
}
+#define TRCIDR1_TRCARCHMIN_SHIFT 4
+#define TRCIDR1_TRCARCHMIN_MASK GENMASK(7, 4)
+#define TRCIDR1_TRCARCHMIN(x) (((x) & TRCIDR1_TRCARCHMIN_MASK) >> TRCIDR1_TRCARCHMIN_SHIFT)
+
+static enum _ocsd_arch_version cs_etm_decoder__get_etmv4_arch_ver(u32 reg_idr1)
+{
+ /*
+ * For ETMv4 if the trace minor version is 4 or more then we can assume
+ * the architecture is ARCH_AA64 rather than just V8.
+ * ARCH_V8 = V8 architecture
+ * ARCH_AA64 = Min v8r3 plus additional AA64 PE features
+ */
+ return TRCIDR1_TRCARCHMIN(reg_idr1) >= 4 ? ARCH_AA64 : ARCH_V8;
+}
+
static void cs_etm_decoder__gen_etmv4_config(struct cs_etm_trace_params *params,
ocsd_etmv4_cfg *config)
{
@@ -138,7 +154,21 @@ static void cs_etm_decoder__gen_etmv4_config(struct cs_etm_trace_params *params,
config->reg_idr11 = 0;
config->reg_idr12 = 0;
config->reg_idr13 = 0;
- config->arch_ver = ARCH_V8;
+ config->arch_ver = cs_etm_decoder__get_etmv4_arch_ver(params->etmv4.reg_idr1);
+ config->core_prof = profile_CortexA;
+}
+
+static void cs_etm_decoder__gen_ete_config(struct cs_etm_trace_params *params,
+ ocsd_ete_cfg *config)
+{
+ config->reg_configr = params->ete.reg_configr;
+ config->reg_traceidr = params->ete.reg_traceidr;
+ config->reg_idr0 = params->ete.reg_idr0;
+ config->reg_idr1 = params->ete.reg_idr1;
+ config->reg_idr2 = params->ete.reg_idr2;
+ config->reg_idr8 = params->ete.reg_idr8;
+ config->reg_devarch = params->ete.reg_devarch;
+ config->arch_ver = ARCH_AA64;
config->core_prof = profile_CortexA;
}
@@ -146,8 +176,10 @@ static void cs_etm_decoder__print_str_cb(const void *p_context,
const char *msg,
const int str_len)
{
- if (p_context && str_len)
- ((struct cs_etm_decoder *)p_context)->packet_printer(msg);
+ const struct cs_etm_decoder *decoder = p_context;
+
+ if (p_context && str_len && !decoder->suppress_printing)
+ decoder->packet_printer(msg);
}
static int
@@ -223,55 +255,6 @@ cs_etm_decoder__init_raw_frame_logging(
}
#endif
-static int cs_etm_decoder__create_packet_printer(struct cs_etm_decoder *decoder,
- const char *decoder_name,
- void *trace_config)
-{
- u8 csid;
-
- if (ocsd_dt_create_decoder(decoder->dcd_tree, decoder_name,
- OCSD_CREATE_FLG_PACKET_PROC,
- trace_config, &csid))
- return -1;
-
- if (ocsd_dt_set_pkt_protocol_printer(decoder->dcd_tree, csid, 0))
- return -1;
-
- return 0;
-}
-
-static int
-cs_etm_decoder__create_etm_packet_printer(struct cs_etm_trace_params *t_params,
- struct cs_etm_decoder *decoder)
-{
- const char *decoder_name;
- ocsd_etmv3_cfg config_etmv3;
- ocsd_etmv4_cfg trace_config_etmv4;
- void *trace_config;
-
- switch (t_params->protocol) {
- case CS_ETM_PROTO_ETMV3:
- case CS_ETM_PROTO_PTM:
- cs_etm_decoder__gen_etmv3_config(t_params, &config_etmv3);
- decoder_name = (t_params->protocol == CS_ETM_PROTO_ETMV3) ?
- OCSD_BUILTIN_DCD_ETMV3 :
- OCSD_BUILTIN_DCD_PTM;
- trace_config = &config_etmv3;
- break;
- case CS_ETM_PROTO_ETMV4i:
- cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
- decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
- trace_config = &trace_config_etmv4;
- break;
- default:
- return -1;
- }
-
- return cs_etm_decoder__create_packet_printer(decoder,
- decoder_name,
- trace_config);
-}
-
static ocsd_datapath_resp_t
cs_etm_decoder__do_soft_timestamp(struct cs_etm_queue *etmq,
struct cs_etm_packet_queue *packet_queue,
@@ -324,8 +307,11 @@ cs_etm_decoder__do_hard_timestamp(struct cs_etm_queue *etmq,
* underflow.
*/
packet_queue->cs_timestamp = 0;
- WARN_ONCE(true, "Zero Coresight timestamp found at Idx:%" OCSD_TRC_IDX_STR
- ". Decoding may be improved with --itrace=Z...\n", indx);
+ if (!cs_etm__etmq_is_timeless(etmq))
+ pr_warning_once("Zero Coresight timestamp found at Idx:%" OCSD_TRC_IDX_STR
+ ". Decoding may be improved by prepending 'Z' to your current --itrace arguments.\n",
+ indx);
+
} else if (packet_queue->instr_count > elem->timestamp) {
/*
* Sanity check that the elem->timestamp - packet_queue->instr_count would not
@@ -625,13 +611,14 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
return resp;
}
-static int cs_etm_decoder__create_etm_packet_decoder(
- struct cs_etm_trace_params *t_params,
- struct cs_etm_decoder *decoder)
+static int
+cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
+ struct cs_etm_trace_params *t_params,
+ struct cs_etm_decoder *decoder)
{
- const char *decoder_name;
ocsd_etmv3_cfg config_etmv3;
ocsd_etmv4_cfg trace_config_etmv4;
+ ocsd_ete_cfg trace_config_ete;
void *trace_config;
u8 csid;
@@ -639,51 +626,55 @@ static int cs_etm_decoder__create_etm_packet_decoder(
case CS_ETM_PROTO_ETMV3:
case CS_ETM_PROTO_PTM:
cs_etm_decoder__gen_etmv3_config(t_params, &config_etmv3);
- decoder_name = (t_params->protocol == CS_ETM_PROTO_ETMV3) ?
+ decoder->decoder_name = (t_params->protocol == CS_ETM_PROTO_ETMV3) ?
OCSD_BUILTIN_DCD_ETMV3 :
OCSD_BUILTIN_DCD_PTM;
trace_config = &config_etmv3;
break;
case CS_ETM_PROTO_ETMV4i:
cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
- decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
+ decoder->decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
trace_config = &trace_config_etmv4;
break;
+ case CS_ETM_PROTO_ETE:
+ cs_etm_decoder__gen_ete_config(t_params, &trace_config_ete);
+ decoder->decoder_name = OCSD_BUILTIN_DCD_ETE;
+ trace_config = &trace_config_ete;
+ break;
default:
return -1;
}
- if (ocsd_dt_create_decoder(decoder->dcd_tree,
- decoder_name,
- OCSD_CREATE_FLG_FULL_DECODER,
- trace_config, &csid))
- return -1;
+ if (d_params->operation == CS_ETM_OPERATION_DECODE) {
+ if (ocsd_dt_create_decoder(decoder->dcd_tree,
+ decoder->decoder_name,
+ OCSD_CREATE_FLG_FULL_DECODER,
+ trace_config, &csid))
+ return -1;
- if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
- cs_etm_decoder__gen_trace_elem_printer,
- decoder))
- return -1;
+ if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
+ cs_etm_decoder__gen_trace_elem_printer,
+ decoder))
+ return -1;
- return 0;
-}
+ return 0;
+ } else if (d_params->operation == CS_ETM_OPERATION_PRINT) {
+ if (ocsd_dt_create_decoder(decoder->dcd_tree, decoder->decoder_name,
+ OCSD_CREATE_FLG_PACKET_PROC,
+ trace_config, &csid))
+ return -1;
-static int
-cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
- struct cs_etm_trace_params *t_params,
- struct cs_etm_decoder *decoder)
-{
- if (d_params->operation == CS_ETM_OPERATION_PRINT)
- return cs_etm_decoder__create_etm_packet_printer(t_params,
- decoder);
- else if (d_params->operation == CS_ETM_OPERATION_DECODE)
- return cs_etm_decoder__create_etm_packet_decoder(t_params,
- decoder);
+ if (ocsd_dt_set_pkt_protocol_printer(decoder->dcd_tree, csid, 0))
+ return -1;
+
+ return 0;
+ }
return -1;
}
struct cs_etm_decoder *
-cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
+cs_etm_decoder__new(int decoders, struct cs_etm_decoder_params *d_params,
struct cs_etm_trace_params t_params[])
{
struct cs_etm_decoder *decoder;
@@ -728,7 +719,7 @@ cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
/* init raw frame logging if required */
cs_etm_decoder__init_raw_frame_logging(d_params, decoder);
- for (i = 0; i < num_cpu; i++) {
+ for (i = 0; i < decoders; i++) {
ret = cs_etm_decoder__create_etm_decoder(d_params,
&t_params[i],
decoder);
@@ -800,3 +791,8 @@ void cs_etm_decoder__free(struct cs_etm_decoder *decoder)
decoder->dcd_tree = NULL;
free(decoder);
}
+
+const char *cs_etm_decoder__get_name(struct cs_etm_decoder *decoder)
+{
+ return decoder->decoder_name;
+}
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
index 11f3391d06f2..92a855fbe5b8 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
@@ -37,11 +37,22 @@ struct cs_etmv4_trace_params {
u32 reg_traceidr;
};
+struct cs_ete_trace_params {
+ u32 reg_idr0;
+ u32 reg_idr1;
+ u32 reg_idr2;
+ u32 reg_idr8;
+ u32 reg_configr;
+ u32 reg_traceidr;
+ u32 reg_devarch;
+};
+
struct cs_etm_trace_params {
int protocol;
union {
struct cs_etmv3_trace_params etmv3;
struct cs_etmv4_trace_params etmv4;
+ struct cs_ete_trace_params ete;
};
};
@@ -65,6 +76,7 @@ enum {
CS_ETM_PROTO_ETMV4i,
CS_ETM_PROTO_ETMV4d,
CS_ETM_PROTO_PTM,
+ CS_ETM_PROTO_ETE
};
enum cs_etm_decoder_operation {
@@ -92,5 +104,6 @@ int cs_etm_decoder__get_packet(struct cs_etm_packet_queue *packet_queue,
struct cs_etm_packet *packet);
int cs_etm_decoder__reset(struct cs_etm_decoder *decoder);
+const char *cs_etm_decoder__get_name(struct cs_etm_decoder *decoder);
#endif /* INCLUDE__CS_ETM_DECODER_H__ */
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index bc1f64873c8f..f323adb1af85 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -62,7 +62,6 @@ struct cs_etm_auxtrace {
u64 instructions_sample_period;
u64 instructions_id;
u64 **metadata;
- u64 kernel_start;
unsigned int pmu_type;
};
@@ -97,7 +96,6 @@ struct cs_etm_queue {
/* RB tree for quick conversion between traceID and metadata pointers */
static struct intlist *traceid_list;
-static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
static int cs_etm__process_queues(struct cs_etm_auxtrace *etm);
static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
pid_t tid);
@@ -462,14 +460,30 @@ static void cs_etm__set_trace_param_etmv4(struct cs_etm_trace_params *t_params,
t_params[idx].etmv4.reg_traceidr = metadata[idx][CS_ETMV4_TRCTRACEIDR];
}
+static void cs_etm__set_trace_param_ete(struct cs_etm_trace_params *t_params,
+ struct cs_etm_auxtrace *etm, int idx)
+{
+ u64 **metadata = etm->metadata;
+
+ t_params[idx].protocol = CS_ETM_PROTO_ETE;
+ t_params[idx].ete.reg_idr0 = metadata[idx][CS_ETMV4_TRCIDR0];
+ t_params[idx].ete.reg_idr1 = metadata[idx][CS_ETMV4_TRCIDR1];
+ t_params[idx].ete.reg_idr2 = metadata[idx][CS_ETMV4_TRCIDR2];
+ t_params[idx].ete.reg_idr8 = metadata[idx][CS_ETMV4_TRCIDR8];
+ t_params[idx].ete.reg_configr = metadata[idx][CS_ETMV4_TRCCONFIGR];
+ t_params[idx].ete.reg_traceidr = metadata[idx][CS_ETMV4_TRCTRACEIDR];
+ t_params[idx].ete.reg_devarch = metadata[idx][CS_ETE_TRCDEVARCH];
+}
+
static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params,
- struct cs_etm_auxtrace *etm)
+ struct cs_etm_auxtrace *etm,
+ int decoders)
{
int i;
u32 etmidr;
u64 architecture;
- for (i = 0; i < etm->num_cpu; i++) {
+ for (i = 0; i < decoders; i++) {
architecture = etm->metadata[i][CS_ETM_MAGIC];
switch (architecture) {
@@ -480,6 +494,9 @@ static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params,
case __perf_cs_etmv4_magic:
cs_etm__set_trace_param_etmv4(t_params, etm, i);
break;
+ case __perf_cs_ete_magic:
+ cs_etm__set_trace_param_ete(t_params, etm, i);
+ break;
default:
return -EINVAL;
}
@@ -490,7 +507,8 @@ static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params,
static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
struct cs_etm_queue *etmq,
- enum cs_etm_decoder_operation mode)
+ enum cs_etm_decoder_operation mode,
+ bool formatted)
{
int ret = -EINVAL;
@@ -500,7 +518,7 @@ static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
d_params->packet_printer = cs_etm__packet_dump;
d_params->operation = mode;
d_params->data = etmq;
- d_params->formatted = true;
+ d_params->formatted = formatted;
d_params->fsyncs = false;
d_params->hsyncs = false;
d_params->frame_aligned = true;
@@ -510,44 +528,23 @@ out:
return ret;
}
-static void cs_etm__dump_event(struct cs_etm_auxtrace *etm,
+static void cs_etm__dump_event(struct cs_etm_queue *etmq,
struct auxtrace_buffer *buffer)
{
int ret;
const char *color = PERF_COLOR_BLUE;
- struct cs_etm_decoder_params d_params;
- struct cs_etm_trace_params *t_params;
- struct cs_etm_decoder *decoder;
size_t buffer_used = 0;
fprintf(stdout, "\n");
color_fprintf(stdout, color,
- ". ... CoreSight ETM Trace data: size %zu bytes\n",
- buffer->size);
-
- /* Use metadata to fill in trace parameters for trace decoder */
- t_params = zalloc(sizeof(*t_params) * etm->num_cpu);
-
- if (!t_params)
- return;
-
- if (cs_etm__init_trace_params(t_params, etm))
- goto out_free;
+ ". ... CoreSight %s Trace data: size %zu bytes\n",
+ cs_etm_decoder__get_name(etmq->decoder), buffer->size);
- /* Set decoder parameters to simply print the trace packets */
- if (cs_etm__init_decoder_params(&d_params, NULL,
- CS_ETM_OPERATION_PRINT))
- goto out_free;
-
- decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
-
- if (!decoder)
- goto out_free;
do {
size_t consumed;
ret = cs_etm_decoder__process_data_block(
- decoder, buffer->offset,
+ etmq->decoder, buffer->offset,
&((u8 *)buffer->data)[buffer_used],
buffer->size - buffer_used, &consumed);
if (ret)
@@ -556,16 +553,12 @@ static void cs_etm__dump_event(struct cs_etm_auxtrace *etm,
buffer_used += consumed;
} while (buffer_used < buffer->size);
- cs_etm_decoder__free(decoder);
-
-out_free:
- zfree(&t_params);
+ cs_etm_decoder__reset(etmq->decoder);
}
static int cs_etm__flush_events(struct perf_session *session,
struct perf_tool *tool)
{
- int ret;
struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
struct cs_etm_auxtrace,
auxtrace);
@@ -575,11 +568,6 @@ static int cs_etm__flush_events(struct perf_session *session,
if (!tool->ordered_events)
return -EINVAL;
- ret = cs_etm__update_queues(etm);
-
- if (ret < 0)
- return ret;
-
if (etm->timeless_decoding)
return cs_etm__process_timeless_queues(etm, -1);
@@ -691,7 +679,7 @@ static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
machine = etmq->etm->machine;
- if (address >= etmq->etm->kernel_start) {
+ if (address >= machine__kernel_start(machine)) {
if (machine__is_host(machine))
return PERF_RECORD_MISC_KERNEL;
else
@@ -746,17 +734,32 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
len = dso__data_read_offset(al.map->dso, machine, offset, buffer, size);
- if (len <= 0)
+ if (len <= 0) {
+ ui__warning_once("CS ETM Trace: Missing DSO. Use 'perf archive' or debuginfod to export data from the traced system.\n"
+ " Enable CONFIG_PROC_KCORE or use option '-k /path/to/vmlinux' for kernel symbols.\n");
+ if (!al.map->dso->auxtrace_warned) {
+ pr_err("CS ETM Trace: Debug data not found for address %#"PRIx64" in %s\n",
+ address,
+ al.map->dso->long_name ? al.map->dso->long_name : "Unknown");
+ al.map->dso->auxtrace_warned = true;
+ }
return 0;
+ }
return len;
}
-static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
+static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
+ bool formatted)
{
struct cs_etm_decoder_params d_params;
struct cs_etm_trace_params *t_params = NULL;
struct cs_etm_queue *etmq;
+ /*
+ * Each queue can only contain data from one CPU when unformatted, so only one decoder is
+ * needed.
+ */
+ int decoders = formatted ? etm->num_cpu : 1;
etmq = zalloc(sizeof(*etmq));
if (!etmq)
@@ -767,20 +770,23 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
goto out_free;
/* Use metadata to fill in trace parameters for trace decoder */
- t_params = zalloc(sizeof(*t_params) * etm->num_cpu);
+ t_params = zalloc(sizeof(*t_params) * decoders);
if (!t_params)
goto out_free;
- if (cs_etm__init_trace_params(t_params, etm))
+ if (cs_etm__init_trace_params(t_params, etm, decoders))
goto out_free;
/* Set decoder parameters to decode trace packets */
if (cs_etm__init_decoder_params(&d_params, etmq,
- CS_ETM_OPERATION_DECODE))
+ dump_trace ? CS_ETM_OPERATION_PRINT :
+ CS_ETM_OPERATION_DECODE,
+ formatted))
goto out_free;
- etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
+ etmq->decoder = cs_etm_decoder__new(decoders, &d_params,
+ t_params);
if (!etmq->decoder)
goto out_free;
@@ -808,31 +814,35 @@ out_free:
static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
struct auxtrace_queue *queue,
- unsigned int queue_nr)
+ unsigned int queue_nr,
+ bool formatted)
{
- int ret = 0;
- unsigned int cs_queue_nr;
- u8 trace_chan_id;
- u64 cs_timestamp;
struct cs_etm_queue *etmq = queue->priv;
if (list_empty(&queue->head) || etmq)
- goto out;
+ return 0;
- etmq = cs_etm__alloc_queue(etm);
+ etmq = cs_etm__alloc_queue(etm, formatted);
- if (!etmq) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!etmq)
+ return -ENOMEM;
queue->priv = etmq;
etmq->etm = etm;
etmq->queue_nr = queue_nr;
etmq->offset = 0;
- if (etm->timeless_decoding)
- goto out;
+ return 0;
+}
+
+static int cs_etm__queue_first_cs_timestamp(struct cs_etm_auxtrace *etm,
+ struct cs_etm_queue *etmq,
+ unsigned int queue_nr)
+{
+ int ret = 0;
+ unsigned int cs_queue_nr;
+ u8 trace_chan_id;
+ u64 cs_timestamp;
/*
* We are under a CPU-wide trace scenario. As such we need to know
@@ -896,33 +906,6 @@ out:
return ret;
}
-static int cs_etm__setup_queues(struct cs_etm_auxtrace *etm)
-{
- unsigned int i;
- int ret;
-
- if (!etm->kernel_start)
- etm->kernel_start = machine__kernel_start(etm->machine);
-
- for (i = 0; i < etm->queues.nr_queues; i++) {
- ret = cs_etm__setup_queue(etm, &etm->queues.queue_array[i], i);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
-{
- if (etm->queues.new_data) {
- etm->queues.new_data = false;
- return cs_etm__setup_queues(etm);
- }
-
- return 0;
-}
-
static inline
void cs_etm__copy_last_branch_rb(struct cs_etm_queue *etmq,
struct cs_etm_traceid_queue *tidq)
@@ -2222,13 +2205,27 @@ static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
static int cs_etm__process_queues(struct cs_etm_auxtrace *etm)
{
int ret = 0;
- unsigned int cs_queue_nr, queue_nr;
+ unsigned int cs_queue_nr, queue_nr, i;
u8 trace_chan_id;
u64 cs_timestamp;
struct auxtrace_queue *queue;
struct cs_etm_queue *etmq;
struct cs_etm_traceid_queue *tidq;
+ /*
+ * Pre-populate the heap with one entry from each queue so that we can
+ * start processing in time order across all queues.
+ */
+ for (i = 0; i < etm->queues.nr_queues; i++) {
+ etmq = etm->queues.queue_array[i].priv;
+ if (!etmq)
+ continue;
+
+ ret = cs_etm__queue_first_cs_timestamp(etm, etmq, i);
+ if (ret)
+ return ret;
+ }
+
while (1) {
if (!etm->heap.heap_cnt)
goto out;
@@ -2382,7 +2379,6 @@ static int cs_etm__process_event(struct perf_session *session,
struct perf_sample *sample,
struct perf_tool *tool)
{
- int err = 0;
u64 sample_kernel_timestamp;
struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
struct cs_etm_auxtrace,
@@ -2401,12 +2397,6 @@ static int cs_etm__process_event(struct perf_session *session,
else
sample_kernel_timestamp = 0;
- if (sample_kernel_timestamp || etm->timeless_decoding) {
- err = cs_etm__update_queues(etm);
- if (err)
- return err;
- }
-
/*
* Don't wait for cs_etm__flush_events() in per-thread/timeless mode to start the decode. We
* need the tid of the PERF_RECORD_EXIT event to assign to the synthesised samples because
@@ -2447,7 +2437,7 @@ static void dump_queued_data(struct cs_etm_auxtrace *etm,
for (i = 0; i < etm->queues.nr_queues; ++i)
list_for_each_entry(buf, &etm->queues.queue_array[i].head, list)
if (buf->reference == event->reference)
- cs_etm__dump_event(etm, buf);
+ cs_etm__dump_event(etm->queues.queue_array[i].priv, buf);
}
static int cs_etm__process_auxtrace_event(struct perf_session *session,
@@ -2463,6 +2453,7 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session,
int fd = perf_data__fd(session->data);
bool is_pipe = perf_data__is_pipe(session->data);
int err;
+ int idx = event->auxtrace.idx;
if (is_pipe)
data_offset = 0;
@@ -2477,9 +2468,20 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session,
if (err)
return err;
+ /*
+ * Knowing if the trace is formatted or not requires a lookup of
+ * the aux record so only works in non-piped mode where data is
+ * queued in cs_etm__queue_aux_records(). Always assume
+ * formatted in piped mode (true).
+ */
+ err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
+ idx, true);
+ if (err)
+ return err;
+
if (dump_trace)
if (auxtrace_buffer__get_data(buffer, fd)) {
- cs_etm__dump_event(etm, buffer);
+ cs_etm__dump_event(etm->queues.queue_array[idx].priv, buffer);
auxtrace_buffer__put_data(buffer);
}
} else if (dump_trace)
@@ -2537,6 +2539,7 @@ static const char * const cs_etmv4_priv_fmts[] = {
[CS_ETMV4_TRCIDR2] = " TRCIDR2 %llx\n",
[CS_ETMV4_TRCIDR8] = " TRCIDR8 %llx\n",
[CS_ETMV4_TRCAUTHSTATUS] = " TRCAUTHSTATUS %llx\n",
+ [CS_ETE_TRCDEVARCH] = " TRCDEVARCH %llx\n"
};
static const char * const param_unk_fmt =
@@ -2596,10 +2599,15 @@ static int cs_etm__print_cpu_metadata_v1(__u64 *val, int *offset)
else
fprintf(stdout, cs_etm_priv_fmts[j], val[i]);
}
- } else if (magic == __perf_cs_etmv4_magic) {
+ } else if (magic == __perf_cs_etmv4_magic || magic == __perf_cs_ete_magic) {
+ /*
+ * ETE and ETMv4 can be printed in the same block because the number of parameters
+ * is saved and they share the list of parameter names. ETE is also only supported
+ * in V1 files.
+ */
for (j = 0; j < total_params; j++, i++) {
/* if newer record - could be excess params */
- if (j >= CS_ETMV4_PRIV_MAX)
+ if (j >= CS_ETE_PRIV_MAX)
fprintf(stdout, param_unk_fmt, j, val[i]);
else
fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);
@@ -2719,6 +2727,8 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
struct perf_record_auxtrace *auxtrace_event;
union perf_event auxtrace_fragment;
__u64 aux_offset, aux_size;
+ __u32 idx;
+ bool formatted;
struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
struct cs_etm_auxtrace,
@@ -2780,8 +2790,15 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
pr_debug3("CS ETM: Queue buffer size: %#"PRI_lx64" offset: %#"PRI_lx64
" tid: %d cpu: %d\n", aux_size, aux_offset, sample->tid, sample->cpu);
- return auxtrace_queues__add_event(&etm->queues, session, &auxtrace_fragment,
- file_offset, NULL);
+ err = auxtrace_queues__add_event(&etm->queues, session, &auxtrace_fragment,
+ file_offset, NULL);
+ if (err)
+ return err;
+
+ idx = auxtrace_event->idx;
+ formatted = !(aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW);
+ return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
+ idx, formatted);
}
/* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */
@@ -2959,6 +2976,16 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
/* The traceID is our handle */
trcidr_idx = CS_ETMV4_TRCTRACEIDR;
+ } else if (ptr[i] == __perf_cs_ete_magic) {
+ metadata[j] = cs_etm__create_meta_blk(ptr, &i, CS_ETE_PRIV_MAX, -1);
+
+ /* ETE shares first part of metadata with ETMv4 */
+ trcidr_idx = CS_ETMV4_TRCTRACEIDR;
+ } else {
+ ui__error("CS ETM Trace: Unrecognised magic number %#"PRIx64". File could be from a newer version of perf.\n",
+ ptr[i]);
+ err = -EINVAL;
+ goto err_free_metadata;
}
if (!metadata[j]) {
@@ -3070,6 +3097,13 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
goto err_delete_thread;
etm->data_queued = etm->queues.populated;
+ /*
+ * Print warning in pipe mode, see cs_etm__process_auxtrace_event() and
+ * cs_etm__queue_aux_fragment() for details relating to limitations.
+ */
+ if (!etm->data_queued)
+ pr_warning("CS ETM warning: Coresight decode and TRBE support requires random file access.\n"
+ "Continuing with best effort decoding in piped mode.\n\n");
return 0;
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
index d65c7b19407d..90c83f932d9a 100644
--- a/tools/perf/util/cs-etm.h
+++ b/tools/perf/util/cs-etm.h
@@ -77,6 +77,15 @@ enum {
#define CS_ETMV4_NR_TRC_PARAMS_V0 (CS_ETMV4_TRCAUTHSTATUS - CS_ETMV4_TRCCONFIGR + 1)
/*
+ * ETE metadata is ETMv4 plus TRCDEVARCH register and doesn't support header V0 since it was
+ * added in header V1
+ */
+enum {
+ CS_ETE_TRCDEVARCH = CS_ETMV4_PRIV_MAX,
+ CS_ETE_PRIV_MAX
+};
+
+/*
* ETMv3 exception encoding number:
* See Embedded Trace Macrocell specification (ARM IHI 0014Q)
* table 7-12 Encoding of Exception[3:0] for non-ARMv7-M processors.
@@ -187,8 +196,10 @@ struct cs_etm_packet_queue {
#define __perf_cs_etmv3_magic 0x3030303030303030ULL
#define __perf_cs_etmv4_magic 0x4040404040404040ULL
+#define __perf_cs_ete_magic 0x5050505050505050ULL
#define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64))
#define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
+#define CS_ETE_PRIV_SIZE (CS_ETE_PRIV_MAX * sizeof(u64))
#ifdef HAVE_CSTRACE_SUPPORT
int cs_etm__process_auxtrace_info(union perf_event *event,
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index cace349fb700..aa862a26d95c 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1634,7 +1634,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
err = -1;
/* perf.data session */
- session = perf_session__new(&data, 0, &c.tool);
+ session = perf_session__new(&data, &c.tool);
if (IS_ERR(session))
return PTR_ERR(session);
diff --git a/tools/perf/util/data-convert-json.c b/tools/perf/util/data-convert-json.c
index 355cd1948bdf..f1ab6edba446 100644
--- a/tools/perf/util/data-convert-json.c
+++ b/tools/perf/util/data-convert-json.c
@@ -334,7 +334,7 @@ int bt_convert__perf2json(const char *input_name, const char *output_name,
goto err;
}
- session = perf_session__new(&data, false, &c.tool);
+ session = perf_session__new(&data, &c.tool);
if (IS_ERR(session)) {
fprintf(stderr, "Error creating perf session!\n");
goto err_fclose;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 48f631966067..f99468a7f681 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -22,6 +22,13 @@ extern int debug_data_convert;
eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warning(fmt, ...) \
eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warning_once(fmt, ...) ({ \
+ static int __warned; \
+ if (unlikely(!__warned)) { \
+ pr_warning(fmt, ##__VA_ARGS__); \
+ __warned = 1; \
+ } \
+})
#define pr_info(fmt, ...) \
eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_debug(fmt, ...) \
@@ -55,6 +62,13 @@ void trace_event(union perf_event *event);
int ui__error(const char *format, ...) __printf(1, 2);
int ui__warning(const char *format, ...) __printf(1, 2);
+#define ui__warning_once(format, ...) ({ \
+ static int __warned; \
+ if (unlikely(!__warned)) { \
+ ui__warning(format, ##__VA_ARGS__); \
+ __warned = 1; \
+ } \
+})
void pr_stat(const char *fmt, ...);
diff --git a/tools/perf/util/dlfilter.c b/tools/perf/util/dlfilter.c
index ca33fbc5efde..db964d5a52af 100644
--- a/tools/perf/util/dlfilter.c
+++ b/tools/perf/util/dlfilter.c
@@ -21,7 +21,7 @@
#include "symbol.h"
#include "srcline.h"
#include "dlfilter.h"
-#include "perf_dlfilter.h"
+#include "../include/perf/perf_dlfilter.h"
static void al_to_d_al(struct addr_location *al, struct perf_dlfilter_al *d_al)
{
@@ -530,8 +530,8 @@ int dlfilter__do_filter_event(struct dlfilter *d,
return ret;
}
-static bool get_filter_desc(const char *dirname, const char *name,
- char **desc, char **long_desc)
+bool get_filter_desc(const char *dirname, const char *name, char **desc,
+ char **long_desc)
{
char path[PATH_MAX];
void *handle;
diff --git a/tools/perf/util/dlfilter.h b/tools/perf/util/dlfilter.h
index 505980442360..cc4bb9657d05 100644
--- a/tools/perf/util/dlfilter.h
+++ b/tools/perf/util/dlfilter.h
@@ -93,5 +93,7 @@ static inline int dlfilter__filter_event_early(struct dlfilter *d,
}
int list_available_dlfilters(const struct option *opt, const char *s, int unset);
+bool get_filter_desc(const char *dirname, const char *name, char **desc,
+ char **long_desc);
#endif
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 52e7101c5609..83723ba11dc8 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -170,6 +170,7 @@ struct dso {
u8 has_srcline:1;
u8 hit:1;
u8 annotate_warned:1;
+ u8 auxtrace_warned:1;
u8 short_name_allocated:1;
u8 long_name_allocated:1;
u8 is_64_bit:1;
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index cec2e6cad8aa..8f7ff0035c41 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -219,13 +219,35 @@ void perf_env__exit(struct perf_env *env)
zfree(&env->hybrid_cpc_nodes);
}
-void perf_env__init(struct perf_env *env __maybe_unused)
+void perf_env__init(struct perf_env *env)
{
#ifdef HAVE_LIBBPF_SUPPORT
env->bpf_progs.infos = RB_ROOT;
env->bpf_progs.btfs = RB_ROOT;
init_rwsem(&env->bpf_progs.lock);
#endif
+ env->kernel_is_64_bit = -1;
+}
+
+static void perf_env__init_kernel_mode(struct perf_env *env)
+{
+ const char *arch = perf_env__raw_arch(env);
+
+ if (!strncmp(arch, "x86_64", 6) || !strncmp(arch, "aarch64", 7) ||
+ !strncmp(arch, "arm64", 5) || !strncmp(arch, "mips64", 6) ||
+ !strncmp(arch, "parisc64", 8) || !strncmp(arch, "riscv64", 7) ||
+ !strncmp(arch, "s390x", 5) || !strncmp(arch, "sparc64", 7))
+ env->kernel_is_64_bit = 1;
+ else
+ env->kernel_is_64_bit = 0;
+}
+
+int perf_env__kernel_is_64_bit(struct perf_env *env)
+{
+ if (env->kernel_is_64_bit == -1)
+ perf_env__init_kernel_mode(env);
+
+ return env->kernel_is_64_bit;
}
int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
@@ -349,7 +371,7 @@ static const char *normalize_arch(char *arch)
return "x86";
if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5))
return "sparc";
- if (!strcmp(arch, "aarch64") || !strcmp(arch, "arm64"))
+ if (!strncmp(arch, "aarch64", 7) || !strncmp(arch, "arm64", 5))
return "arm64";
if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110"))
return "arm";
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 6824a7423a2d..1f5175820a05 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -61,6 +61,7 @@ struct perf_env {
unsigned long long total_mem;
unsigned int msr_pmu_type;
unsigned int max_branches;
+ int kernel_is_64_bit;
int nr_cmdline;
int nr_sibling_cores;
@@ -143,6 +144,8 @@ extern struct perf_env perf_env;
void perf_env__exit(struct perf_env *env);
+int perf_env__kernel_is_64_bit(struct perf_env *env);
+
int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);
int perf_env__read_cpuid(struct perf_env *env);
diff --git a/tools/perf/util/events_stats.h b/tools/perf/util/events_stats.h
index 3480bafd414b..1b0006092265 100644
--- a/tools/perf/util/events_stats.h
+++ b/tools/perf/util/events_stats.h
@@ -30,6 +30,7 @@ struct events_stats {
u64 total_lost_samples;
u64 total_aux_lost;
u64 total_aux_partial;
+ u64 total_aux_collision;
u64 total_invalid_chains;
u32 nr_events[PERF_RECORD_HEADER_MAX];
u32 nr_lost_warned;
diff --git a/tools/perf/util/evlist-hybrid.c b/tools/perf/util/evlist-hybrid.c
index db3f5fbdebe1..7c554234b43d 100644
--- a/tools/perf/util/evlist-hybrid.c
+++ b/tools/perf/util/evlist-hybrid.c
@@ -86,3 +86,76 @@ bool evlist__has_hybrid(struct evlist *evlist)
return false;
}
+
+int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list)
+{
+ struct perf_cpu_map *cpus;
+ struct evsel *evsel, *tmp;
+ struct perf_pmu *pmu;
+ int ret, unmatched_count = 0, events_nr = 0;
+
+ if (!perf_pmu__has_hybrid() || !cpu_list)
+ return 0;
+
+ cpus = perf_cpu_map__new(cpu_list);
+ if (!cpus)
+ return -1;
+
+ /*
+ * The evsels are created with hybrid pmu's cpus. But now we
+ * need to check and adjust the cpus of evsel by cpu_list because
+ * cpu_list may cause conflicts with cpus of evsel. For example,
+ * cpus of evsel is cpu0-7, but the cpu_list is cpu6-8, we need
+ * to adjust the cpus of evsel to cpu6-7. And then propatate maps
+ * in evlist__create_maps().
+ */
+ evlist__for_each_entry_safe(evlist, tmp, evsel) {
+ struct perf_cpu_map *matched_cpus, *unmatched_cpus;
+ char buf1[128], buf2[128];
+
+ pmu = perf_pmu__find_hybrid_pmu(evsel->pmu_name);
+ if (!pmu)
+ continue;
+
+ ret = perf_pmu__cpus_match(pmu, cpus, &matched_cpus,
+ &unmatched_cpus);
+ if (ret)
+ goto out;
+
+ events_nr++;
+
+ if (matched_cpus->nr > 0 && (unmatched_cpus->nr > 0 ||
+ matched_cpus->nr < cpus->nr ||
+ matched_cpus->nr < pmu->cpus->nr)) {
+ perf_cpu_map__put(evsel->core.cpus);
+ perf_cpu_map__put(evsel->core.own_cpus);
+ evsel->core.cpus = perf_cpu_map__get(matched_cpus);
+ evsel->core.own_cpus = perf_cpu_map__get(matched_cpus);
+
+ if (unmatched_cpus->nr > 0) {
+ cpu_map__snprint(matched_cpus, buf1, sizeof(buf1));
+ pr_warning("WARNING: use %s in '%s' for '%s', skip other cpus in list.\n",
+ buf1, pmu->name, evsel->name);
+ }
+ }
+
+ if (matched_cpus->nr == 0) {
+ evlist__remove(evlist, evsel);
+ evsel__delete(evsel);
+
+ cpu_map__snprint(cpus, buf1, sizeof(buf1));
+ cpu_map__snprint(pmu->cpus, buf2, sizeof(buf2));
+ pr_warning("WARNING: %s isn't a '%s', please use a CPU list in the '%s' range (%s)\n",
+ buf1, pmu->name, pmu->name, buf2);
+ unmatched_count++;
+ }
+
+ perf_cpu_map__put(matched_cpus);
+ perf_cpu_map__put(unmatched_cpus);
+ }
+
+ ret = (unmatched_count == events_nr) ? -1 : 0;
+out:
+ perf_cpu_map__put(cpus);
+ return ret;
+}
diff --git a/tools/perf/util/evlist-hybrid.h b/tools/perf/util/evlist-hybrid.h
index 19f74b4c340a..aacdb1b0f948 100644
--- a/tools/perf/util/evlist-hybrid.h
+++ b/tools/perf/util/evlist-hybrid.h
@@ -10,5 +10,6 @@
int evlist__add_default_hybrid(struct evlist *evlist, bool precise);
void evlist__warn_hybrid_group(struct evlist *evlist);
bool evlist__has_hybrid(struct evlist *evlist);
+int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list);
#endif /* __PERF_EVLIST_HYBRID_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 47581a237c7a..5f92319ce258 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -27,6 +27,7 @@
#include "util/perf_api_probe.h"
#include "util/evsel_fprintf.h"
#include "util/evlist-hybrid.h"
+#include "util/pmu.h"
#include <signal.h>
#include <unistd.h>
#include <sched.h>
@@ -1002,7 +1003,7 @@ int evlist__create_maps(struct evlist *evlist, struct target *target)
if (!cpus)
goto out_delete_threads;
- evlist->core.has_user_cpus = !!target->cpu_list;
+ evlist->core.has_user_cpus = !!target->cpu_list && !target->hybrid;
perf_evlist__set_maps(&evlist->core, cpus, threads);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 5c22383489ae..97bfb8d0be4f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -276,6 +276,22 @@ void evlist__to_front(struct evlist *evlist, struct evsel *move_evsel);
__evlist__for_each_entry_continue(&(evlist)->core.entries, evsel)
/**
+ * __evlist__for_each_entry_from - continue iteration from @evsel (included)
+ * @list: list_head instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define __evlist__for_each_entry_from(list, evsel) \
+ list_for_each_entry_from(evsel, list, core.node)
+
+/**
+ * evlist__for_each_entry_from - continue iteration from @evsel (included)
+ * @evlist: evlist instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define evlist__for_each_entry_from(evlist, evsel) \
+ __evlist__for_each_entry_from(&(evlist)->core.entries, evsel)
+
+/**
* __evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
* @list: list_head instance to iterate
* @evsel: struct evsel iterator
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index f61e5dd53f5d..54d251327b5b 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1656,7 +1656,7 @@ static int update_fds(struct evsel *evsel,
return 0;
}
-static bool ignore_missing_thread(struct evsel *evsel,
+bool evsel__ignore_missing_thread(struct evsel *evsel,
int nr_cpus, int cpu,
struct perf_thread_map *threads,
int thread, int err)
@@ -1709,59 +1709,43 @@ static void display_attr(struct perf_event_attr *attr)
}
}
-static int perf_event_open(struct evsel *evsel,
- pid_t pid, int cpu, int group_fd,
- unsigned long flags)
+bool evsel__precise_ip_fallback(struct evsel *evsel)
{
- int precise_ip = evsel->core.attr.precise_ip;
- int fd;
-
- while (1) {
- pr_debug2_peo("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
- pid, cpu, group_fd, flags);
-
- fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, group_fd, flags);
- if (fd >= 0)
- break;
-
- /* Do not try less precise if not requested. */
- if (!evsel->precise_max)
- break;
-
- /*
- * We tried all the precise_ip values, and it's
- * still failing, so leave it to standard fallback.
- */
- if (!evsel->core.attr.precise_ip) {
- evsel->core.attr.precise_ip = precise_ip;
- break;
- }
+ /* Do not try less precise if not requested. */
+ if (!evsel->precise_max)
+ return false;
- pr_debug2_peo("\nsys_perf_event_open failed, error %d\n", -ENOTSUP);
- evsel->core.attr.precise_ip--;
- pr_debug2_peo("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip);
- display_attr(&evsel->core.attr);
+ /*
+ * We tried all the precise_ip values, and it's
+ * still failing, so leave it to standard fallback.
+ */
+ if (!evsel->core.attr.precise_ip) {
+ evsel->core.attr.precise_ip = evsel->precise_ip_original;
+ return false;
}
- return fd;
+ if (!evsel->precise_ip_original)
+ evsel->precise_ip_original = evsel->core.attr.precise_ip;
+
+ evsel->core.attr.precise_ip--;
+ pr_debug2_peo("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip);
+ display_attr(&evsel->core.attr);
+ return true;
}
-static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
- struct perf_thread_map *threads,
- int start_cpu, int end_cpu)
+static struct perf_cpu_map *empty_cpu_map;
+static struct perf_thread_map *empty_thread_map;
+
+static int __evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads)
{
- int cpu, thread, nthreads;
- unsigned long flags = PERF_FLAG_FD_CLOEXEC;
- int pid = -1, err, old_errno;
- enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
+ int nthreads;
if ((perf_missing_features.write_backward && evsel->core.attr.write_backward) ||
(perf_missing_features.aux_output && evsel->core.attr.aux_output))
return -EINVAL;
if (cpus == NULL) {
- static struct perf_cpu_map *empty_cpu_map;
-
if (empty_cpu_map == NULL) {
empty_cpu_map = perf_cpu_map__dummy_new();
if (empty_cpu_map == NULL)
@@ -1772,8 +1756,6 @@ static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
}
if (threads == NULL) {
- static struct perf_thread_map *empty_thread_map;
-
if (empty_thread_map == NULL) {
empty_thread_map = thread_map__new_by_tid(-1);
if (empty_thread_map == NULL)
@@ -1792,12 +1774,15 @@ static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
perf_evsel__alloc_fd(&evsel->core, cpus->nr, nthreads) < 0)
return -ENOMEM;
- if (evsel->cgrp) {
- flags |= PERF_FLAG_PID_CGROUP;
- pid = evsel->cgrp->fd;
- }
+ evsel->open_flags = PERF_FLAG_FD_CLOEXEC;
+ if (evsel->cgrp)
+ evsel->open_flags |= PERF_FLAG_PID_CGROUP;
-fallback_missing_features:
+ return 0;
+}
+
+static void evsel__disable_missing_features(struct evsel *evsel)
+{
if (perf_missing_features.weight_struct) {
evsel__set_sample_bit(evsel, WEIGHT);
evsel__reset_sample_bit(evsel, WEIGHT_STRUCT);
@@ -1809,7 +1794,7 @@ fallback_missing_features:
evsel->core.attr.clockid = 0;
}
if (perf_missing_features.cloexec)
- flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
+ evsel->open_flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
if (perf_missing_features.mmap2)
evsel->core.attr.mmap2 = 0;
if (perf_missing_features.exclude_guest)
@@ -1825,119 +1810,26 @@ fallback_missing_features:
evsel->core.attr.bpf_event = 0;
if (perf_missing_features.branch_hw_idx)
evsel->core.attr.branch_sample_type &= ~PERF_SAMPLE_BRANCH_HW_INDEX;
-retry_sample_id:
if (perf_missing_features.sample_id_all)
evsel->core.attr.sample_id_all = 0;
+}
- display_attr(&evsel->core.attr);
-
- for (cpu = start_cpu; cpu < end_cpu; cpu++) {
-
- for (thread = 0; thread < nthreads; thread++) {
- int fd, group_fd;
-
- if (!evsel->cgrp && !evsel->core.system_wide)
- pid = perf_thread_map__pid(threads, thread);
-
- group_fd = get_group_fd(evsel, cpu, thread);
-retry_open:
- test_attr__ready();
-
- fd = perf_event_open(evsel, pid, cpus->map[cpu],
- group_fd, flags);
-
- FD(evsel, cpu, thread) = fd;
-
- bpf_counter__install_pe(evsel, cpu, fd);
-
- if (unlikely(test_attr__enabled)) {
- test_attr__open(&evsel->core.attr, pid, cpus->map[cpu],
- fd, group_fd, flags);
- }
-
- if (fd < 0) {
- err = -errno;
-
- if (ignore_missing_thread(evsel, cpus->nr, cpu, threads, thread, err)) {
- /*
- * We just removed 1 thread, so take a step
- * back on thread index and lower the upper
- * nthreads limit.
- */
- nthreads--;
- thread--;
-
- /* ... and pretend like nothing have happened. */
- err = 0;
- continue;
- }
-
- pr_debug2_peo("\nsys_perf_event_open failed, error %d\n",
- err);
- goto try_fallback;
- }
-
- pr_debug2_peo(" = %d\n", fd);
-
- if (evsel->bpf_fd >= 0) {
- int evt_fd = fd;
- int bpf_fd = evsel->bpf_fd;
-
- err = ioctl(evt_fd,
- PERF_EVENT_IOC_SET_BPF,
- bpf_fd);
- if (err && errno != EEXIST) {
- pr_err("failed to attach bpf fd %d: %s\n",
- bpf_fd, strerror(errno));
- err = -EINVAL;
- goto out_close;
- }
- }
-
- set_rlimit = NO_CHANGE;
-
- /*
- * If we succeeded but had to kill clockid, fail and
- * have evsel__open_strerror() print us a nice error.
- */
- if (perf_missing_features.clockid ||
- perf_missing_features.clockid_wrong) {
- err = -EINVAL;
- goto out_close;
- }
- }
- }
-
- return 0;
+int evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads)
+{
+ int err;
-try_fallback:
- /*
- * perf stat needs between 5 and 22 fds per CPU. When we run out
- * of them try to increase the limits.
- */
- if (err == -EMFILE && set_rlimit < INCREASED_MAX) {
- struct rlimit l;
+ err = __evsel__prepare_open(evsel, cpus, threads);
+ if (err)
+ return err;
- old_errno = errno;
- if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
- if (set_rlimit == NO_CHANGE)
- l.rlim_cur = l.rlim_max;
- else {
- l.rlim_cur = l.rlim_max + 1000;
- l.rlim_max = l.rlim_cur;
- }
- if (setrlimit(RLIMIT_NOFILE, &l) == 0) {
- set_rlimit++;
- errno = old_errno;
- goto retry_open;
- }
- }
- errno = old_errno;
- }
+ evsel__disable_missing_features(evsel);
- if (err != -EINVAL || cpu > 0 || thread > 0)
- goto out_close;
+ return err;
+}
+bool evsel__detect_missing_features(struct evsel *evsel)
+{
/*
* Must probe features in the order they were added to the
* perf_event_attr interface.
@@ -1946,82 +1838,239 @@ try_fallback:
(evsel->core.attr.sample_type & PERF_SAMPLE_WEIGHT_STRUCT)) {
perf_missing_features.weight_struct = true;
pr_debug2("switching off weight struct support\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.code_page_size &&
(evsel->core.attr.sample_type & PERF_SAMPLE_CODE_PAGE_SIZE)) {
perf_missing_features.code_page_size = true;
pr_debug2_peo("Kernel has no PERF_SAMPLE_CODE_PAGE_SIZE support, bailing out\n");
- goto out_close;
+ return false;
} else if (!perf_missing_features.data_page_size &&
(evsel->core.attr.sample_type & PERF_SAMPLE_DATA_PAGE_SIZE)) {
perf_missing_features.data_page_size = true;
pr_debug2_peo("Kernel has no PERF_SAMPLE_DATA_PAGE_SIZE support, bailing out\n");
- goto out_close;
+ return false;
} else if (!perf_missing_features.cgroup && evsel->core.attr.cgroup) {
perf_missing_features.cgroup = true;
pr_debug2_peo("Kernel has no cgroup sampling support, bailing out\n");
- goto out_close;
- } else if (!perf_missing_features.branch_hw_idx &&
+ return false;
+ } else if (!perf_missing_features.branch_hw_idx &&
(evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX)) {
perf_missing_features.branch_hw_idx = true;
pr_debug2("switching off branch HW index support\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) {
perf_missing_features.aux_output = true;
pr_debug2_peo("Kernel has no attr.aux_output support, bailing out\n");
- goto out_close;
+ return false;
} else if (!perf_missing_features.bpf && evsel->core.attr.bpf_event) {
perf_missing_features.bpf = true;
pr_debug2_peo("switching off bpf_event\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) {
perf_missing_features.ksymbol = true;
pr_debug2_peo("switching off ksymbol\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) {
perf_missing_features.write_backward = true;
pr_debug2_peo("switching off write_backward\n");
- goto out_close;
+ return false;
} else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) {
perf_missing_features.clockid_wrong = true;
pr_debug2_peo("switching off clockid\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) {
perf_missing_features.clockid = true;
pr_debug2_peo("switching off use_clockid\n");
- goto fallback_missing_features;
- } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
+ return true;
+ } else if (!perf_missing_features.cloexec && (evsel->open_flags & PERF_FLAG_FD_CLOEXEC)) {
perf_missing_features.cloexec = true;
pr_debug2_peo("switching off cloexec flag\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) {
perf_missing_features.mmap2 = true;
pr_debug2_peo("switching off mmap2\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.exclude_guest &&
(evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host)) {
perf_missing_features.exclude_guest = true;
pr_debug2_peo("switching off exclude_guest, exclude_host\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.sample_id_all) {
perf_missing_features.sample_id_all = true;
pr_debug2_peo("switching off sample_id_all\n");
- goto retry_sample_id;
+ return true;
} else if (!perf_missing_features.lbr_flags &&
(evsel->core.attr.branch_sample_type &
(PERF_SAMPLE_BRANCH_NO_CYCLES |
PERF_SAMPLE_BRANCH_NO_FLAGS))) {
perf_missing_features.lbr_flags = true;
pr_debug2_peo("switching off branch sample type no (cycles/flags)\n");
- goto fallback_missing_features;
+ return true;
} else if (!perf_missing_features.group_read &&
evsel->core.attr.inherit &&
(evsel->core.attr.read_format & PERF_FORMAT_GROUP) &&
evsel__is_group_leader(evsel)) {
perf_missing_features.group_read = true;
pr_debug2_peo("switching off group read\n");
- goto fallback_missing_features;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool evsel__increase_rlimit(enum rlimit_action *set_rlimit)
+{
+ int old_errno;
+ struct rlimit l;
+
+ if (*set_rlimit < INCREASED_MAX) {
+ old_errno = errno;
+
+ if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
+ if (*set_rlimit == NO_CHANGE) {
+ l.rlim_cur = l.rlim_max;
+ } else {
+ l.rlim_cur = l.rlim_max + 1000;
+ l.rlim_max = l.rlim_cur;
+ }
+ if (setrlimit(RLIMIT_NOFILE, &l) == 0) {
+ (*set_rlimit) += 1;
+ errno = old_errno;
+ return true;
+ }
+ }
+ errno = old_errno;
}
+
+ return false;
+}
+
+static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads,
+ int start_cpu, int end_cpu)
+{
+ int cpu, thread, nthreads;
+ int pid = -1, err, old_errno;
+ enum rlimit_action set_rlimit = NO_CHANGE;
+
+ err = __evsel__prepare_open(evsel, cpus, threads);
+ if (err)
+ return err;
+
+ if (cpus == NULL)
+ cpus = empty_cpu_map;
+
+ if (threads == NULL)
+ threads = empty_thread_map;
+
+ if (evsel->core.system_wide)
+ nthreads = 1;
+ else
+ nthreads = threads->nr;
+
+ if (evsel->cgrp)
+ pid = evsel->cgrp->fd;
+
+fallback_missing_features:
+ evsel__disable_missing_features(evsel);
+
+ display_attr(&evsel->core.attr);
+
+ for (cpu = start_cpu; cpu < end_cpu; cpu++) {
+
+ for (thread = 0; thread < nthreads; thread++) {
+ int fd, group_fd;
+retry_open:
+ if (thread >= nthreads)
+ break;
+
+ if (!evsel->cgrp && !evsel->core.system_wide)
+ pid = perf_thread_map__pid(threads, thread);
+
+ group_fd = get_group_fd(evsel, cpu, thread);
+
+ test_attr__ready();
+
+ pr_debug2_peo("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
+ pid, cpus->map[cpu], group_fd, evsel->open_flags);
+
+ fd = sys_perf_event_open(&evsel->core.attr, pid, cpus->map[cpu],
+ group_fd, evsel->open_flags);
+
+ FD(evsel, cpu, thread) = fd;
+
+ if (fd < 0) {
+ err = -errno;
+
+ pr_debug2_peo("\nsys_perf_event_open failed, error %d\n",
+ err);
+ goto try_fallback;
+ }
+
+ bpf_counter__install_pe(evsel, cpu, fd);
+
+ if (unlikely(test_attr__enabled)) {
+ test_attr__open(&evsel->core.attr, pid, cpus->map[cpu],
+ fd, group_fd, evsel->open_flags);
+ }
+
+ pr_debug2_peo(" = %d\n", fd);
+
+ if (evsel->bpf_fd >= 0) {
+ int evt_fd = fd;
+ int bpf_fd = evsel->bpf_fd;
+
+ err = ioctl(evt_fd,
+ PERF_EVENT_IOC_SET_BPF,
+ bpf_fd);
+ if (err && errno != EEXIST) {
+ pr_err("failed to attach bpf fd %d: %s\n",
+ bpf_fd, strerror(errno));
+ err = -EINVAL;
+ goto out_close;
+ }
+ }
+
+ set_rlimit = NO_CHANGE;
+
+ /*
+ * If we succeeded but had to kill clockid, fail and
+ * have evsel__open_strerror() print us a nice error.
+ */
+ if (perf_missing_features.clockid ||
+ perf_missing_features.clockid_wrong) {
+ err = -EINVAL;
+ goto out_close;
+ }
+ }
+ }
+
+ return 0;
+
+try_fallback:
+ if (evsel__precise_ip_fallback(evsel))
+ goto retry_open;
+
+ if (evsel__ignore_missing_thread(evsel, cpus->nr, cpu, threads, thread, err)) {
+ /* We just removed 1 thread, so lower the upper nthreads limit. */
+ nthreads--;
+
+ /* ... and pretend like nothing have happened. */
+ err = 0;
+ goto retry_open;
+ }
+ /*
+ * perf stat needs between 5 and 22 fds per CPU. When we run out
+ * of them try to increase the limits.
+ */
+ if (err == -EMFILE && evsel__increase_rlimit(&set_rlimit))
+ goto retry_open;
+
+ if (err != -EINVAL || cpu > 0 || thread > 0)
+ goto out_close;
+
+ if (evsel__detect_missing_features(evsel))
+ goto fallback_missing_features;
out_close:
if (err)
threads->err_thread = thread;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 80383096d51c..1b3eeab5f188 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -150,6 +150,8 @@ struct evsel {
struct bperf_leader_bpf *leader_skel;
struct bperf_follower_bpf *follower_skel;
};
+ unsigned long open_flags;
+ int precise_ip_original;
};
struct perf_missing_features {
@@ -286,6 +288,18 @@ int evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads)
int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
struct perf_thread_map *threads);
void evsel__close(struct evsel *evsel);
+int evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads);
+bool evsel__detect_missing_features(struct evsel *evsel);
+
+enum rlimit_action { NO_CHANGE, SET_TO_MAX, INCREASED_MAX };
+bool evsel__increase_rlimit(enum rlimit_action *set_rlimit);
+
+bool evsel__ignore_missing_thread(struct evsel *evsel,
+ int nr_cpus, int cpu,
+ struct perf_thread_map *threads,
+ int thread, int err);
+bool evsel__precise_ip_fallback(struct evsel *evsel);
struct perf_sample;
diff --git a/tools/perf/util/get_current_dir_name.c b/tools/perf/util/get_current_dir_name.c
index b205d929245f..e68935e9ac8c 100644
--- a/tools/perf/util/get_current_dir_name.c
+++ b/tools/perf/util/get_current_dir_name.c
@@ -3,8 +3,9 @@
//
#ifndef HAVE_GET_CURRENT_DIR_NAME
#include "get_current_dir_name.h"
+#include <limits.h>
+#include <string.h>
#include <unistd.h>
-#include <stdlib.h>
/* Android's 'bionic' library, for one, doesn't have this */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 44249027507a..d2231cb7c4f7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1284,7 +1284,7 @@ static int memory_node__read(struct memory_node *n, unsigned long idx)
dir = opendir(path);
if (!dir) {
- pr_warning("failed: cant' open memory sysfs data\n");
+ pr_warning("failed: can't open memory sysfs data\n");
return -1;
}
@@ -3865,10 +3865,10 @@ static int perf_file_section__process(struct perf_file_section *section,
static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
struct perf_header *ph,
struct perf_data* data,
- bool repipe)
+ bool repipe, int repipe_fd)
{
struct feat_fd ff = {
- .fd = STDOUT_FILENO,
+ .fd = repipe_fd,
.ph = ph,
};
ssize_t ret;
@@ -3891,13 +3891,13 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
return 0;
}
-static int perf_header__read_pipe(struct perf_session *session)
+static int perf_header__read_pipe(struct perf_session *session, int repipe_fd)
{
struct perf_header *header = &session->header;
struct perf_pipe_file_header f_header;
if (perf_file_header__read_pipe(&f_header, header, session->data,
- session->repipe) < 0) {
+ session->repipe, repipe_fd) < 0) {
pr_debug("incompatible file format\n");
return -EINVAL;
}
@@ -3995,7 +3995,7 @@ static int evlist__prepare_tracepoint_events(struct evlist *evlist, struct tep_h
return 0;
}
-int perf_session__read_header(struct perf_session *session)
+int perf_session__read_header(struct perf_session *session, int repipe_fd)
{
struct perf_data *data = session->data;
struct perf_header *header = &session->header;
@@ -4016,7 +4016,7 @@ int perf_session__read_header(struct perf_session *session)
* We can read 'pipe' data event from regular file,
* check for the pipe header regardless of source.
*/
- err = perf_header__read_pipe(session);
+ err = perf_header__read_pipe(session, repipe_fd);
if (!err || perf_data__is_pipe(data)) {
data->is_pipe = true;
return err;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index ae6b1cf19a7d..c9e3265832d9 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -115,7 +115,7 @@ struct perf_session;
struct perf_tool;
union perf_event;
-int perf_session__read_header(struct perf_session *session);
+int perf_session__read_header(struct perf_session *session, int repipe_fd);
int perf_session__write_header(struct perf_session *session,
struct evlist *evlist,
int fd, bool at_exit);
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index cbd9b268f168..96c8ef60f4f8 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -38,6 +38,8 @@ struct llvm_param llvm_param = {
.user_set_param = false,
};
+static void version_notice(void);
+
int perf_llvm_config(const char *var, const char *value)
{
if (!strstarts(var, "llvm."))
@@ -108,6 +110,21 @@ search_program(const char *def, const char *name,
return ret;
}
+static int search_program_and_warn(const char *def, const char *name,
+ char *output)
+{
+ int ret = search_program(def, name, output);
+
+ if (ret) {
+ pr_err("ERROR:\tunable to find %s.\n"
+ "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
+ " \tand '%s-path' option in [llvm] section of ~/.perfconfig.\n",
+ name, name);
+ version_notice();
+ }
+ return ret;
+}
+
#define READ_SIZE 4096
static int
read_from_pipe(const char *cmd, void **p_buf, size_t *p_read_sz)
@@ -217,7 +234,7 @@ version_notice(void)
" \t\tgit clone http://llvm.org/git/clang.git\n\n"
" \tOr fetch the latest clang/llvm 3.7 from pre-built llvm packages for\n"
" \tdebian/ubuntu:\n"
-" \t\thttp://llvm.org/apt\n\n"
+" \t\thttps://apt.llvm.org/\n\n"
" \tIf you are using old version of clang, change 'clang-bpf-cmd-template'\n"
" \toption in [llvm] section of ~/.perfconfig to:\n\n"
" \t \"$CLANG_EXEC $CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS \\\n"
@@ -458,16 +475,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
if (!template)
template = CLANG_BPF_CMD_DEFAULT_TEMPLATE;
- err = search_program(llvm_param.clang_path,
+ err = search_program_and_warn(llvm_param.clang_path,
"clang", clang_path);
- if (err) {
- pr_err(
-"ERROR:\tunable to find clang.\n"
-"Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
-" \tand 'clang-path' option in [llvm] section of ~/.perfconfig.\n");
- version_notice();
+ if (err)
return -ENOENT;
- }
/*
* This is an optional work. Even it fail we can continue our
@@ -495,14 +506,9 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
force_set_env("WORKING_DIR", kbuild_dir ? : ".");
if (opts) {
- err = search_program(llvm_param.llc_path, "llc", llc_path);
- if (err) {
- pr_err("ERROR:\tunable to find llc.\n"
- "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
- " \tand 'llc-path' option in [llvm] section of ~/.perfconfig.\n");
- version_notice();
+ err = search_program_and_warn(llvm_param.llc_path, "llc", llc_path);
+ if (err)
goto errout;
- }
err = -ENOMEM;
if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
@@ -579,5 +585,5 @@ int llvm__search_clang(void)
{
char clang_path[PATH_MAX];
- return search_program(llvm_param.clang_path, "clang", clang_path);
+ return search_program_and_warn(llvm_param.clang_path, "clang", clang_path);
}
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index 9d5f589f02ae..af33118354dd 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -6,6 +6,7 @@
#include <linux/refcount.h>
#include <linux/types.h>
#include <linux/ring_buffer.h>
+#include <linux/bitops.h>
#include <stdbool.h>
#include <pthread.h> // for cpu_set_t
#ifdef HAVE_AIO_SUPPORT
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 9321bd0e2f76..d94e48e1ff9b 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -316,7 +316,8 @@ event_pmu_name opt_pmu_config
if (!strncmp(name, "uncore_", 7) &&
strncmp($1, "uncore_", 7))
name += 7;
- if (!perf_pmu__match(pattern, name, $1)) {
+ if (!perf_pmu__match(pattern, name, $1) ||
+ !perf_pmu__match(pattern, pmu->alias_name, $1)) {
if (parse_events_copy_term_list(orig_terms, &terms))
CLEANUP_YYABORT;
if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false))
diff --git a/tools/perf/util/parse-sublevel-options.h b/tools/perf/util/parse-sublevel-options.h
index 9b9efcc2aaad..578b18ef03bb 100644
--- a/tools/perf/util/parse-sublevel-options.h
+++ b/tools/perf/util/parse-sublevel-options.h
@@ -8,4 +8,4 @@ struct sublevel_option {
int perf_parse_sublevel_options(const char *str, struct sublevel_option *opts);
-#endif \ No newline at end of file
+#endif
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index fc683bc41715..bdabd62170d2 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -843,8 +843,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu,
break;
}
- if (pmu_is_uncore(name) &&
- pmu_uncore_alias_match(pname, name))
+ if (pmu->is_uncore && pmu_uncore_alias_match(pname, name))
goto new_alias;
if (strcmp(pname, name))
@@ -927,7 +926,7 @@ static int pmu_add_sys_aliases_iter_fn(struct pmu_event *pe, void *data)
return 0;
}
-static void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu)
+void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu)
{
struct pmu_sys_event_iter_data idata = {
.head = head,
@@ -946,6 +945,18 @@ perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
return NULL;
}
+char * __weak
+pmu_find_real_name(const char *name)
+{
+ return (char *)name;
+}
+
+char * __weak
+pmu_find_alias_name(const char *name __maybe_unused)
+{
+ return NULL;
+}
+
static int pmu_max_precise(const char *name)
{
char path[PATH_MAX];
@@ -959,13 +970,15 @@ static int pmu_max_precise(const char *name)
return max_precise;
}
-static struct perf_pmu *pmu_lookup(const char *name)
+static struct perf_pmu *pmu_lookup(const char *lookup_name)
{
struct perf_pmu *pmu;
LIST_HEAD(format);
LIST_HEAD(aliases);
__u32 type;
+ char *name = pmu_find_real_name(lookup_name);
bool is_hybrid = perf_pmu__hybrid_mounted(name);
+ char *alias_name;
/*
* Check pmu name for hybrid and the pmu may be invalid in sysfs
@@ -996,6 +1009,16 @@ static struct perf_pmu *pmu_lookup(const char *name)
pmu->cpus = pmu_cpumask(name);
pmu->name = strdup(name);
+ if (!pmu->name)
+ goto err;
+
+ alias_name = pmu_find_alias_name(name);
+ if (alias_name) {
+ pmu->alias_name = strdup(alias_name);
+ if (!pmu->alias_name)
+ goto err;
+ }
+
pmu->type = type;
pmu->is_uncore = pmu_is_uncore(name);
if (pmu->is_uncore)
@@ -1018,15 +1041,22 @@ static struct perf_pmu *pmu_lookup(const char *name)
pmu->default_config = perf_pmu__get_default_config(pmu);
return pmu;
+err:
+ if (pmu->name)
+ free(pmu->name);
+ free(pmu);
+ return NULL;
}
static struct perf_pmu *pmu_find(const char *name)
{
struct perf_pmu *pmu;
- list_for_each_entry(pmu, &pmus, list)
- if (!strcmp(pmu->name, name))
+ list_for_each_entry(pmu, &pmus, list) {
+ if (!strcmp(pmu->name, name) ||
+ (pmu->alias_name && !strcmp(pmu->alias_name, name)))
return pmu;
+ }
return NULL;
}
@@ -1920,6 +1950,9 @@ bool perf_pmu__has_hybrid(void)
int perf_pmu__match(char *pattern, char *name, char *tok)
{
+ if (!name)
+ return -1;
+
if (fnmatch(pattern, name, 0))
return -1;
@@ -1928,3 +1961,38 @@ int perf_pmu__match(char *pattern, char *name, char *tok)
return 0;
}
+
+int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
+ struct perf_cpu_map **mcpus_ptr,
+ struct perf_cpu_map **ucpus_ptr)
+{
+ struct perf_cpu_map *pmu_cpus = pmu->cpus;
+ struct perf_cpu_map *matched_cpus, *unmatched_cpus;
+ int matched_nr = 0, unmatched_nr = 0;
+
+ matched_cpus = perf_cpu_map__default_new();
+ if (!matched_cpus)
+ return -1;
+
+ unmatched_cpus = perf_cpu_map__default_new();
+ if (!unmatched_cpus) {
+ perf_cpu_map__put(matched_cpus);
+ return -1;
+ }
+
+ for (int i = 0; i < cpus->nr; i++) {
+ int cpu;
+
+ cpu = perf_cpu_map__idx(pmu_cpus, cpus->map[i]);
+ if (cpu == -1)
+ unmatched_cpus->map[unmatched_nr++] = cpus->map[i];
+ else
+ matched_cpus->map[matched_nr++] = cpus->map[i];
+ }
+
+ unmatched_cpus->nr = unmatched_nr;
+ matched_cpus->nr = matched_nr;
+ *mcpus_ptr = matched_cpus;
+ *ucpus_ptr = unmatched_cpus;
+ return 0;
+}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 926da483a141..394898b07fd9 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -11,6 +11,7 @@
#include "pmu-events/pmu-events.h"
struct evsel_config_term;
+struct perf_cpu_map;
enum {
PERF_PMU_FORMAT_VALUE_CONFIG,
@@ -21,6 +22,7 @@ enum {
#define PERF_PMU_FORMAT_BITS 64
#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
#define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus"
+#define MAX_PMU_NAME_LEN 128
struct perf_event_attr;
@@ -32,6 +34,7 @@ struct perf_pmu_caps {
struct perf_pmu {
char *name;
+ char *alias_name;
char *id;
__u32 type;
bool selectable;
@@ -81,6 +84,7 @@ struct perf_pmu_alias {
struct perf_pmu *perf_pmu__find(const char *name);
struct perf_pmu *perf_pmu__find_by_type(unsigned int type);
+void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu);
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
struct list_head *head_terms,
struct parse_events_error *error);
@@ -135,4 +139,10 @@ void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
bool perf_pmu__has_hybrid(void);
int perf_pmu__match(char *pattern, char *name, char *tok);
+int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
+ struct perf_cpu_map **mcpus_ptr,
+ struct perf_cpu_map **ucpus_ptr);
+
+char *pmu_find_real_name(const char *name);
+char *pmu_find_alias_name(const char *name);
#endif /* __PMU_H */
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 69129e2aa7a1..c0c010350bc2 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1422,6 +1422,37 @@ static void python_process_event(union perf_event *event,
}
}
+static void python_process_throttle(union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ const char *handler_name;
+ PyObject *handler, *t;
+
+ if (event->header.type == PERF_RECORD_THROTTLE)
+ handler_name = "throttle";
+ else
+ handler_name = "unthrottle";
+ handler = get_handler(handler_name);
+ if (!handler)
+ return;
+
+ t = tuple_new(6);
+ if (!t)
+ return;
+
+ tuple_set_u64(t, 0, event->throttle.time);
+ tuple_set_u64(t, 1, event->throttle.id);
+ tuple_set_u64(t, 2, event->throttle.stream_id);
+ tuple_set_s32(t, 3, sample->cpu);
+ tuple_set_s32(t, 4, sample->pid);
+ tuple_set_s32(t, 5, sample->tid);
+
+ call_object(handler, t, handler_name);
+
+ Py_DECREF(t);
+}
+
static void python_do_process_switch(union perf_event *event,
struct perf_sample *sample,
struct machine *machine)
@@ -2079,5 +2110,6 @@ struct scripting_ops python_scripting_ops = {
.process_auxtrace_error = python_process_auxtrace_error,
.process_stat = python_process_stat,
.process_stat_interval = python_process_stat_interval,
+ .process_throttle = python_process_throttle,
.generate_script = python_generate_script,
};
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 51f727402912..069c2cfdd3be 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -102,11 +102,11 @@ static int perf_session__deliver_event(struct perf_session *session,
struct perf_tool *tool,
u64 file_offset);
-static int perf_session__open(struct perf_session *session)
+static int perf_session__open(struct perf_session *session, int repipe_fd)
{
struct perf_data *data = session->data;
- if (perf_session__read_header(session) < 0) {
+ if (perf_session__read_header(session, repipe_fd) < 0) {
pr_err("incompatible file format (rerun with -v to learn more)\n");
return -1;
}
@@ -185,8 +185,9 @@ static int ordered_events__deliver_event(struct ordered_events *oe,
session->tool, event->file_offset);
}
-struct perf_session *perf_session__new(struct perf_data *data,
- bool repipe, struct perf_tool *tool)
+struct perf_session *__perf_session__new(struct perf_data *data,
+ bool repipe, int repipe_fd,
+ struct perf_tool *tool)
{
int ret = -ENOMEM;
struct perf_session *session = zalloc(sizeof(*session));
@@ -210,7 +211,7 @@ struct perf_session *perf_session__new(struct perf_data *data,
session->data = data;
if (perf_data__is_read(data)) {
- ret = perf_session__open(session);
+ ret = perf_session__open(session, repipe_fd);
if (ret < 0)
goto out_delete;
@@ -1540,6 +1541,8 @@ static int machines__deliver_event(struct machines *machines,
evlist->stats.total_aux_lost += 1;
if (event->aux.flags & PERF_AUX_FLAG_PARTIAL)
evlist->stats.total_aux_partial += 1;
+ if (event->aux.flags & PERF_AUX_FLAG_COLLISION)
+ evlist->stats.total_aux_collision += 1;
}
return tool->aux(tool, event, sample, machine);
case PERF_RECORD_ITRACE_START:
@@ -1895,6 +1898,13 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
"");
}
+ if (session->tool->aux == perf_event__process_aux &&
+ stats->total_aux_collision != 0) {
+ ui__warning("AUX data detected collision %" PRIu64 " times out of %u!\n\n",
+ stats->total_aux_collision,
+ stats->nr_events[PERF_RECORD_AUX]);
+ }
+
if (stats->nr_unknown_events != 0) {
ui__warning("Found %u unknown events!\n\n"
"Is this an older tool processing a perf.data "
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index e31ba4c92a6c..5d8bd14a0a39 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -54,8 +54,16 @@ struct decomp {
struct perf_tool;
-struct perf_session *perf_session__new(struct perf_data *data,
- bool repipe, struct perf_tool *tool);
+struct perf_session *__perf_session__new(struct perf_data *data,
+ bool repipe, int repipe_fd,
+ struct perf_tool *tool);
+
+static inline struct perf_session *perf_session__new(struct perf_data *data,
+ struct perf_tool *tool)
+{
+ return __perf_session__new(data, false, -1, tool);
+}
+
void perf_session__delete(struct perf_session *session);
void perf_event_header__bswap(struct perf_event_header *hdr);
diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c
index 35aa0c0f7cd9..a7e981b2d7de 100644
--- a/tools/perf/util/synthetic-events.c
+++ b/tools/perf/util/synthetic-events.c
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include "util/cgroup.h"
+#include "util/data.h"
#include "util/debug.h"
#include "util/dso.h"
#include "util/event.h"
@@ -16,7 +18,6 @@
#include "util/synthetic-events.h"
#include "util/target.h"
#include "util/time-utils.h"
-#include "util/cgroup.h"
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -2179,3 +2180,53 @@ int perf_event__synthesize_features(struct perf_tool *tool, struct perf_session
free(ff.buf);
return ret;
}
+
+int perf_event__synthesize_for_pipe(struct perf_tool *tool,
+ struct perf_session *session,
+ struct perf_data *data,
+ perf_event__handler_t process)
+{
+ int err;
+ int ret = 0;
+ struct evlist *evlist = session->evlist;
+
+ /*
+ * We need to synthesize events first, because some
+ * features works on top of them (on report side).
+ */
+ err = perf_event__synthesize_attrs(tool, evlist, process);
+ if (err < 0) {
+ pr_err("Couldn't synthesize attrs.\n");
+ return err;
+ }
+ ret += err;
+
+ err = perf_event__synthesize_features(tool, session, evlist, process);
+ if (err < 0) {
+ pr_err("Couldn't synthesize features.\n");
+ return err;
+ }
+ ret += err;
+
+ if (have_tracepoints(&evlist->core.entries)) {
+ int fd = perf_data__fd(data);
+
+ /*
+ * FIXME err <= 0 here actually means that
+ * there were no tracepoints so its not really
+ * an error, just that we don't need to
+ * synthesize anything. We really have to
+ * return this more properly and also
+ * propagate errors that now are calling die()
+ */
+ err = perf_event__synthesize_tracing_data(tool, fd, evlist,
+ process);
+ if (err <= 0) {
+ pr_err("Couldn't record tracing data.\n");
+ return err;
+ }
+ ret += err;
+ }
+
+ return ret;
+}
diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic-events.h
index e7a3e9589738..c845e2b9b444 100644
--- a/tools/perf/util/synthetic-events.h
+++ b/tools/perf/util/synthetic-events.h
@@ -14,6 +14,7 @@ struct evsel;
struct machine;
struct perf_counts_values;
struct perf_cpu_map;
+struct perf_data;
struct perf_event_attr;
struct perf_event_mmap_page;
struct perf_sample;
@@ -101,4 +102,9 @@ static inline int perf_event__synthesize_bpf_events(struct perf_session *session
}
#endif // HAVE_LIBBPF_SUPPORT
+int perf_event__synthesize_for_pipe(struct perf_tool *tool,
+ struct perf_session *session,
+ struct perf_data *data,
+ perf_event__handler_t process);
+
#endif // __PERF_SYNTHETIC_EVENTS_H
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 4ff56217f2a6..daec6cba500d 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -17,6 +17,7 @@ struct target {
bool default_per_cpu;
bool per_thread;
bool use_bpf;
+ bool hybrid;
const char *attr_map;
};
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 54aadeedf28c..640981105788 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -90,6 +90,9 @@ struct scripting_ops {
void (*process_stat)(struct perf_stat_config *config,
struct evsel *evsel, u64 tstamp);
void (*process_stat_interval)(u64 tstamp);
+ void (*process_throttle)(union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine);
int (*generate_script) (struct tep_handle *pevent, const char *outfile);
};
diff --git a/tools/testing/ktest/examples/bootconfigs/boottrace.bconf b/tools/testing/ktest/examples/bootconfigs/boottrace.bconf
index 9db64ec589d5..7aa706cccb3b 100644
--- a/tools/testing/ktest/examples/bootconfigs/boottrace.bconf
+++ b/tools/testing/ktest/examples/bootconfigs/boottrace.bconf
@@ -10,13 +10,23 @@ ftrace.event {
}
synthetic.initcall_latency {
fields = "unsigned long func", "u64 lat"
- actions = "hist:keys=func.sym,lat:vals=lat:sort=lat"
+ hist {
+ keys = func.sym,lat
+ values = lat
+ sort = lat
+ }
}
- initcall.initcall_start {
- actions = "hist:keys=func:ts0=common_timestamp.usecs"
+ initcall.initcall_start.hist {
+ keys = func;
+ var.ts0 = common_timestamp.usecs
}
- initcall.initcall_finish {
- actions = "hist:keys=func:lat=common_timestamp.usecs-$ts0:onmatch(initcall.initcall_start).initcall_latency(func,$lat)"
+ initcall.initcall_finish.hist {
+ keys = func
+ var.lat = common_timestamp.usecs - $ts0
+ onmatch {
+ event = initcall.initcall_start
+ trace = initcall_latency, func, $lat
+ }
}
}
diff --git a/tools/testing/ktest/examples/bootconfigs/verify-boottrace.sh b/tools/testing/ktest/examples/bootconfigs/verify-boottrace.sh
index f271940ce7fb..233e95cfcf20 100755
--- a/tools/testing/ktest/examples/bootconfigs/verify-boottrace.sh
+++ b/tools/testing/ktest/examples/bootconfigs/verify-boottrace.sh
@@ -58,7 +58,7 @@ compare_file_partial "events/synthetic/initcall_latency/enable" "0"
compare_file_partial "events/initcall/initcall_start/trigger" "hist:keys=func:vals=hitcount:ts0=common_timestamp.usecs"
compare_file_partial "events/initcall/initcall_start/enable" "1"
-compare_file_partial "events/initcall/initcall_finish/trigger" 'hist:keys=func:vals=hitcount:lat=common_timestamp.usecs-\$ts0:sort=hitcount:size=2048:clock=global:onmatch(initcall.initcall_start).initcall_latency(func,\$lat)'
+compare_file_partial "events/initcall/initcall_finish/trigger" 'hist:keys=func:vals=hitcount:lat=common_timestamp.usecs-\$ts0:sort=hitcount:size=2048:clock=global:onmatch(initcall.initcall_start).trace(initcall_latency,func,\$lat)'
compare_file_partial "events/initcall/initcall_finish/enable" "1"
compare_file "instances/foo/current_tracer" "function"
diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 6276ce0c0196..5a931456e718 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -16,6 +16,7 @@ assert sys.version_info >= (3, 7), "Python version is too old"
from collections import namedtuple
from enum import Enum, auto
+from typing import Iterable
import kunit_config
import kunit_json
@@ -30,12 +31,13 @@ KunitBuildRequest = namedtuple('KunitBuildRequest',
['jobs', 'build_dir', 'alltests',
'make_options'])
KunitExecRequest = namedtuple('KunitExecRequest',
- ['timeout', 'build_dir', 'alltests', 'filter_glob'])
+ ['timeout', 'build_dir', 'alltests',
+ 'filter_glob', 'kernel_args'])
KunitParseRequest = namedtuple('KunitParseRequest',
['raw_output', 'input_data', 'build_dir', 'json'])
KunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs',
'build_dir', 'alltests', 'filter_glob',
- 'json', 'make_options'])
+ 'kernel_args', 'json', 'make_options'])
KernelDirectoryPath = sys.argv[0].split('tools/testing/kunit/')[0]
@@ -94,6 +96,7 @@ def exec_tests(linux: kunit_kernel.LinuxSourceTree,
kunit_parser.print_with_timestamp('Starting KUnit Kernel ...')
test_start = time.time()
result = linux.run_kernel(
+ args=request.kernel_args,
timeout=None if request.alltests else request.timeout,
filter_glob=request.filter_glob,
build_dir=request.build_dir)
@@ -112,7 +115,16 @@ def parse_tests(request: KunitParseRequest) -> KunitResult:
'Tests not Parsed.')
if request.raw_output:
- kunit_parser.raw_output(request.input_data)
+ output: Iterable[str] = request.input_data
+ if request.raw_output == 'all':
+ pass
+ elif request.raw_output == 'kunit':
+ output = kunit_parser.extract_tap_lines(output)
+ else:
+ print(f'Unknown --raw_output option "{request.raw_output}"', file=sys.stderr)
+ for line in output:
+ print(line.rstrip())
+
else:
test_result = kunit_parser.parse_run_tests(request.input_data)
parse_end = time.time()
@@ -133,7 +145,6 @@ def parse_tests(request: KunitParseRequest) -> KunitResult:
return KunitResult(KunitStatus.SUCCESS, test_result,
parse_end - parse_start)
-
def run_tests(linux: kunit_kernel.LinuxSourceTree,
request: KunitRequest) -> KunitResult:
run_start = time.time()
@@ -152,7 +163,8 @@ def run_tests(linux: kunit_kernel.LinuxSourceTree,
return build_result
exec_request = KunitExecRequest(request.timeout, request.build_dir,
- request.alltests, request.filter_glob)
+ request.alltests, request.filter_glob,
+ request.kernel_args)
exec_result = exec_tests(linux, exec_request)
if exec_result.status != KunitStatus.SUCCESS:
return exec_result
@@ -178,7 +190,7 @@ def add_common_opts(parser) -> None:
parser.add_argument('--build_dir',
help='As in the make command, it specifies the build '
'directory.',
- type=str, default='.kunit', metavar='build_dir')
+ type=str, default='.kunit', metavar='build_dir')
parser.add_argument('--make_options',
help='X=Y make option, can be repeated.',
action='append')
@@ -238,10 +250,14 @@ def add_exec_opts(parser) -> None:
nargs='?',
default='',
metavar='filter_glob')
+ parser.add_argument('--kernel_args',
+ help='Kernel command-line parameters. Maybe be repeated',
+ action='append')
def add_parse_opts(parser) -> None:
- parser.add_argument('--raw_output', help='don\'t format output from kernel',
- action='store_true')
+ parser.add_argument('--raw_output', help='If set don\'t format output from kernel. '
+ 'If set to --raw_output=kunit, filters to just KUnit output.',
+ type=str, nargs='?', const='all', default=None)
parser.add_argument('--json',
nargs='?',
help='Stores test results in a JSON, and either '
@@ -309,6 +325,7 @@ def main(argv, linux=None):
cli_args.build_dir,
cli_args.alltests,
cli_args.filter_glob,
+ cli_args.kernel_args,
cli_args.json,
cli_args.make_options)
result = run_tests(linux, request)
@@ -363,7 +380,8 @@ def main(argv, linux=None):
exec_request = KunitExecRequest(cli_args.timeout,
cli_args.build_dir,
cli_args.alltests,
- cli_args.filter_glob)
+ cli_args.filter_glob,
+ cli_args.kernel_args)
exec_result = exec_tests(linux, exec_request)
parse_request = KunitParseRequest(cli_args.raw_output,
exec_result.result,
diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py
index b88db3f51dc5..6310a641b151 100644
--- a/tools/testing/kunit/kunit_parser.py
+++ b/tools/testing/kunit/kunit_parser.py
@@ -106,10 +106,6 @@ def extract_tap_lines(kernel_output: Iterable[str]) -> LineStream:
yield line_num, line[prefix_len:]
return LineStream(lines=isolate_kunit_output(kernel_output))
-def raw_output(kernel_output) -> None:
- for line in kernel_output:
- print(line.rstrip())
-
DIVIDER = '=' * 60
RESET = '\033[0;0m'
@@ -137,7 +133,7 @@ def print_log(log) -> None:
for m in log:
print_with_timestamp(m)
-TAP_ENTRIES = re.compile(r'^(TAP|[\s]*ok|[\s]*not ok|[\s]*[0-9]+\.\.[0-9]+|[\s]*#).*$')
+TAP_ENTRIES = re.compile(r'^(TAP|[\s]*ok|[\s]*not ok|[\s]*[0-9]+\.\.[0-9]+|[\s]*# (Subtest:|.*: kunit test case crashed!)).*$')
def consume_non_diagnostic(lines: LineStream) -> None:
while lines and not TAP_ENTRIES.match(lines.peek()):
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py
index 75045aa0f8a1..619c4554cbff 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -356,7 +356,7 @@ class KUnitMainTest(unittest.TestCase):
self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 0)
self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
self.linux_source_mock.run_kernel.assert_called_once_with(
- build_dir='.kunit', filter_glob='', timeout=300)
+ args=None, build_dir='.kunit', filter_glob='', timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_run_passes_args_pass(self):
@@ -364,7 +364,7 @@ class KUnitMainTest(unittest.TestCase):
self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
self.linux_source_mock.run_kernel.assert_called_once_with(
- build_dir='.kunit', filter_glob='', timeout=300)
+ args=None, build_dir='.kunit', filter_glob='', timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_exec_passes_args_fail(self):
@@ -399,11 +399,20 @@ class KUnitMainTest(unittest.TestCase):
self.assertNotEqual(call, mock.call(StrContains('Testing complete.')))
self.assertNotEqual(call, mock.call(StrContains(' 0 tests run')))
+ def test_run_raw_output_kunit(self):
+ self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
+ kunit.main(['run', '--raw_output=kunit'], self.linux_source_mock)
+ self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
+ self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
+ for call in self.print_mock.call_args_list:
+ self.assertNotEqual(call, mock.call(StrContains('Testing complete.')))
+ self.assertNotEqual(call, mock.call(StrContains(' 0 tests run')))
+
def test_exec_timeout(self):
timeout = 3453
kunit.main(['exec', '--timeout', str(timeout)], self.linux_source_mock)
self.linux_source_mock.run_kernel.assert_called_once_with(
- build_dir='.kunit', filter_glob='', timeout=timeout)
+ args=None, build_dir='.kunit', filter_glob='', timeout=timeout)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_run_timeout(self):
@@ -411,7 +420,7 @@ class KUnitMainTest(unittest.TestCase):
kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock)
self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
self.linux_source_mock.run_kernel.assert_called_once_with(
- build_dir='.kunit', filter_glob='', timeout=timeout)
+ args=None, build_dir='.kunit', filter_glob='', timeout=timeout)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_run_builddir(self):
@@ -419,7 +428,7 @@ class KUnitMainTest(unittest.TestCase):
kunit.main(['run', '--build_dir=.kunit'], self.linux_source_mock)
self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
self.linux_source_mock.run_kernel.assert_called_once_with(
- build_dir=build_dir, filter_glob='', timeout=300)
+ args=None, build_dir=build_dir, filter_glob='', timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_config_builddir(self):
@@ -436,7 +445,7 @@ class KUnitMainTest(unittest.TestCase):
build_dir = '.kunit'
kunit.main(['exec', '--build_dir', build_dir], self.linux_source_mock)
self.linux_source_mock.run_kernel.assert_called_once_with(
- build_dir=build_dir, filter_glob='', timeout=300)
+ args=None, build_dir=build_dir, filter_glob='', timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
@mock.patch.object(kunit_kernel, 'LinuxSourceTree')
@@ -461,5 +470,13 @@ class KUnitMainTest(unittest.TestCase):
cross_compile=None,
qemu_config_path=None)
+ def test_run_kernel_args(self):
+ kunit.main(['run', '--kernel_args=a=1', '--kernel_args=b=2'], self.linux_source_mock)
+ self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
+ self.linux_source_mock.run_kernel.assert_called_once_with(
+ args=['a=1','b=2'], build_dir='.kunit', filter_glob='', timeout=300)
+ self.print_mock.assert_any_call(StrContains('Testing complete.'))
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tools/testing/scatterlist/linux/mm.h b/tools/testing/scatterlist/linux/mm.h
index f9a12005fcea..16ec895bbe5f 100644
--- a/tools/testing/scatterlist/linux/mm.h
+++ b/tools/testing/scatterlist/linux/mm.h
@@ -127,7 +127,6 @@ kmalloc_array(unsigned int n, unsigned int size, unsigned int flags)
#define kmemleak_free(a)
#define PageSlab(p) (0)
-#define flush_kernel_dcache_page(p)
#define MAX_ERRNO 4095
diff --git a/tools/testing/scatterlist/main.c b/tools/testing/scatterlist/main.c
index 652254754b4c..08465a701cd5 100644
--- a/tools/testing/scatterlist/main.c
+++ b/tools/testing/scatterlist/main.c
@@ -85,32 +85,46 @@ int main(void)
for (i = 0, test = tests; test->expected_segments; test++, i++) {
int left_pages = test->pfn_app ? test->num_pages : 0;
+ struct sg_append_table append = {};
struct page *pages[MAX_PAGES];
- struct sg_table st;
- struct scatterlist *sg;
+ int ret;
set_pages(pages, test->pfn, test->num_pages);
- sg = __sg_alloc_table_from_pages(&st, pages, test->num_pages, 0,
- test->size, test->max_seg, NULL, left_pages, GFP_KERNEL);
- assert(PTR_ERR_OR_ZERO(sg) == test->alloc_ret);
+ if (test->pfn_app)
+ ret = sg_alloc_append_table_from_pages(
+ &append, pages, test->num_pages, 0, test->size,
+ test->max_seg, left_pages, GFP_KERNEL);
+ else
+ ret = sg_alloc_table_from_pages_segment(
+ &append.sgt, pages, test->num_pages, 0,
+ test->size, test->max_seg, GFP_KERNEL);
+
+ assert(ret == test->alloc_ret);
if (test->alloc_ret)
continue;
if (test->pfn_app) {
set_pages(pages, test->pfn_app, test->num_pages);
- sg = __sg_alloc_table_from_pages(&st, pages, test->num_pages, 0,
- test->size, test->max_seg, sg, 0, GFP_KERNEL);
+ ret = sg_alloc_append_table_from_pages(
+ &append, pages, test->num_pages, 0, test->size,
+ test->max_seg, 0, GFP_KERNEL);
- assert(PTR_ERR_OR_ZERO(sg) == test->alloc_ret);
+ assert(ret == test->alloc_ret);
}
- VALIDATE(st.nents == test->expected_segments, &st, test);
+ VALIDATE(append.sgt.nents == test->expected_segments,
+ &append.sgt, test);
if (!test->pfn_app)
- VALIDATE(st.orig_nents == test->expected_segments, &st, test);
-
- sg_free_table(&st);
+ VALIDATE(append.sgt.orig_nents ==
+ test->expected_segments,
+ &append.sgt, test);
+
+ if (test->pfn_app)
+ sg_free_append_table(&append);
+ else
+ sg_free_table(&append.sgt);
}
assert(i == (sizeof(tests) / sizeof(tests[0])) - 1);
diff --git a/tools/testing/selftests/arm64/fp/.gitignore b/tools/testing/selftests/arm64/fp/.gitignore
index d66f76d2a650..b67395903b9b 100644
--- a/tools/testing/selftests/arm64/fp/.gitignore
+++ b/tools/testing/selftests/arm64/fp/.gitignore
@@ -1,5 +1,7 @@
fpsimd-test
+rdvl-sve
sve-probe-vls
sve-ptrace
sve-test
+vec-syscfg
vlset
diff --git a/tools/testing/selftests/arm64/fp/Makefile b/tools/testing/selftests/arm64/fp/Makefile
index a57009d3a0dc..f2abdd6ba12e 100644
--- a/tools/testing/selftests/arm64/fp/Makefile
+++ b/tools/testing/selftests/arm64/fp/Makefile
@@ -1,17 +1,22 @@
# SPDX-License-Identifier: GPL-2.0
CFLAGS += -I../../../../../usr/include/
-TEST_GEN_PROGS := sve-ptrace sve-probe-vls
-TEST_PROGS_EXTENDED := fpsimd-test fpsimd-stress sve-test sve-stress vlset
+TEST_GEN_PROGS := sve-ptrace sve-probe-vls vec-syscfg
+TEST_PROGS_EXTENDED := fpsimd-test fpsimd-stress \
+ rdvl-sve \
+ sve-test sve-stress \
+ vlset
all: $(TEST_GEN_PROGS) $(TEST_PROGS_EXTENDED)
fpsimd-test: fpsimd-test.o
$(CC) -nostdlib $^ -o $@
+rdvl-sve: rdvl-sve.o rdvl.o
sve-ptrace: sve-ptrace.o sve-ptrace-asm.o
-sve-probe-vls: sve-probe-vls.o
+sve-probe-vls: sve-probe-vls.o rdvl.o
sve-test: sve-test.o
$(CC) -nostdlib $^ -o $@
+vec-syscfg: vec-syscfg.o rdvl.o
vlset: vlset.o
include ../../lib.mk
diff --git a/tools/testing/selftests/arm64/fp/TODO b/tools/testing/selftests/arm64/fp/TODO
new file mode 100644
index 000000000000..b6b7ebfcf362
--- /dev/null
+++ b/tools/testing/selftests/arm64/fp/TODO
@@ -0,0 +1,4 @@
+- Test unsupported values in the ABIs.
+- More coverage for ptrace (eg, vector length conversions).
+- Coverage for signals.
+- Test PR_SVE_VL_INHERITY after a double fork.
diff --git a/tools/testing/selftests/arm64/fp/rdvl-sve.c b/tools/testing/selftests/arm64/fp/rdvl-sve.c
new file mode 100644
index 000000000000..7f8a13a18f5d
--- /dev/null
+++ b/tools/testing/selftests/arm64/fp/rdvl-sve.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <stdio.h>
+
+#include "rdvl.h"
+
+int main(void)
+{
+ int vl = rdvl_sve();
+
+ printf("%d\n", vl);
+
+ return 0;
+}
diff --git a/tools/testing/selftests/arm64/fp/rdvl.S b/tools/testing/selftests/arm64/fp/rdvl.S
new file mode 100644
index 000000000000..c916c1c9defd
--- /dev/null
+++ b/tools/testing/selftests/arm64/fp/rdvl.S
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2021 ARM Limited.
+
+.arch_extension sve
+
+.globl rdvl_sve
+rdvl_sve:
+ hint 34 // BTI C
+ rdvl x0, #1
+ ret
diff --git a/tools/testing/selftests/arm64/fp/rdvl.h b/tools/testing/selftests/arm64/fp/rdvl.h
new file mode 100644
index 000000000000..7c9d953fc9e7
--- /dev/null
+++ b/tools/testing/selftests/arm64/fp/rdvl.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef RDVL_H
+#define RDVL_H
+
+int rdvl_sve(void);
+
+#endif
diff --git a/tools/testing/selftests/arm64/fp/sve-probe-vls.c b/tools/testing/selftests/arm64/fp/sve-probe-vls.c
index 76e138525d55..a24eca7a4ecb 100644
--- a/tools/testing/selftests/arm64/fp/sve-probe-vls.c
+++ b/tools/testing/selftests/arm64/fp/sve-probe-vls.c
@@ -13,6 +13,7 @@
#include <asm/sigcontext.h>
#include "../../kselftest.h"
+#include "rdvl.h"
int main(int argc, char **argv)
{
@@ -38,6 +39,10 @@ int main(int argc, char **argv)
vl &= PR_SVE_VL_LEN_MASK;
+ if (rdvl_sve() != vl)
+ ksft_exit_fail_msg("PR_SVE_SET_VL reports %d, RDVL %d\n",
+ vl, rdvl_sve());
+
if (!sve_vl_valid(vl))
ksft_exit_fail_msg("VL %d invalid\n", vl);
vq = sve_vq_from_vl(vl);
diff --git a/tools/testing/selftests/arm64/fp/vec-syscfg.c b/tools/testing/selftests/arm64/fp/vec-syscfg.c
new file mode 100644
index 000000000000..c02071dcb563
--- /dev/null
+++ b/tools/testing/selftests/arm64/fp/vec-syscfg.c
@@ -0,0 +1,593 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 ARM Limited.
+ * Original author: Mark Brown <broonie@kernel.org>
+ */
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <asm/sigcontext.h>
+#include <asm/hwcap.h>
+
+#include "../../kselftest.h"
+#include "rdvl.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#define ARCH_MIN_VL SVE_VL_MIN
+
+struct vec_data {
+ const char *name;
+ unsigned long hwcap_type;
+ unsigned long hwcap;
+ const char *rdvl_binary;
+ int (*rdvl)(void);
+
+ int prctl_get;
+ int prctl_set;
+ const char *default_vl_file;
+
+ int default_vl;
+ int min_vl;
+ int max_vl;
+};
+
+
+static struct vec_data vec_data[] = {
+ {
+ .name = "SVE",
+ .hwcap_type = AT_HWCAP,
+ .hwcap = HWCAP_SVE,
+ .rdvl = rdvl_sve,
+ .rdvl_binary = "./rdvl-sve",
+ .prctl_get = PR_SVE_GET_VL,
+ .prctl_set = PR_SVE_SET_VL,
+ .default_vl_file = "/proc/sys/abi/sve_default_vector_length",
+ },
+};
+
+static int stdio_read_integer(FILE *f, const char *what, int *val)
+{
+ int n = 0;
+ int ret;
+
+ ret = fscanf(f, "%d%*1[\n]%n", val, &n);
+ if (ret < 1 || n < 1) {
+ ksft_print_msg("failed to parse integer from %s\n", what);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Start a new process and return the vector length it sees */
+static int get_child_rdvl(struct vec_data *data)
+{
+ FILE *out;
+ int pipefd[2];
+ pid_t pid, child;
+ int read_vl, ret;
+
+ ret = pipe(pipefd);
+ if (ret == -1) {
+ ksft_print_msg("pipe() failed: %d (%s)\n",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ fflush(stdout);
+
+ child = fork();
+ if (child == -1) {
+ ksft_print_msg("fork() failed: %d (%s)\n",
+ errno, strerror(errno));
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return -1;
+ }
+
+ /* Child: put vector length on the pipe */
+ if (child == 0) {
+ /*
+ * Replace stdout with the pipe, errors to stderr from
+ * here as kselftest prints to stdout.
+ */
+ ret = dup2(pipefd[1], 1);
+ if (ret == -1) {
+ fprintf(stderr, "dup2() %d\n", errno);
+ exit(EXIT_FAILURE);
+ }
+
+ /* exec() a new binary which puts the VL on stdout */
+ ret = execl(data->rdvl_binary, data->rdvl_binary, NULL);
+ fprintf(stderr, "execl(%s) failed: %d\n",
+ data->rdvl_binary, errno, strerror(errno));
+
+ exit(EXIT_FAILURE);
+ }
+
+ close(pipefd[1]);
+
+ /* Parent; wait for the exit status from the child & verify it */
+ do {
+ pid = wait(&ret);
+ if (pid == -1) {
+ ksft_print_msg("wait() failed: %d (%s)\n",
+ errno, strerror(errno));
+ close(pipefd[0]);
+ return -1;
+ }
+ } while (pid != child);
+
+ assert(pid == child);
+
+ if (!WIFEXITED(ret)) {
+ ksft_print_msg("child exited abnormally\n");
+ close(pipefd[0]);
+ return -1;
+ }
+
+ if (WEXITSTATUS(ret) != 0) {
+ ksft_print_msg("child returned error %d\n",
+ WEXITSTATUS(ret));
+ close(pipefd[0]);
+ return -1;
+ }
+
+ out = fdopen(pipefd[0], "r");
+ if (!out) {
+ ksft_print_msg("failed to open child stdout\n");
+ close(pipefd[0]);
+ return -1;
+ }
+
+ ret = stdio_read_integer(out, "child", &read_vl);
+ fclose(out);
+ if (ret != 0)
+ return ret;
+
+ return read_vl;
+}
+
+static int file_read_integer(const char *name, int *val)
+{
+ FILE *f;
+ int ret;
+
+ f = fopen(name, "r");
+ if (!f) {
+ ksft_test_result_fail("Unable to open %s: %d (%s)\n",
+ name, errno,
+ strerror(errno));
+ return -1;
+ }
+
+ ret = stdio_read_integer(f, name, val);
+ fclose(f);
+
+ return ret;
+}
+
+static int file_write_integer(const char *name, int val)
+{
+ FILE *f;
+ int ret;
+
+ f = fopen(name, "w");
+ if (!f) {
+ ksft_test_result_fail("Unable to open %s: %d (%s)\n",
+ name, errno,
+ strerror(errno));
+ return -1;
+ }
+
+ fprintf(f, "%d", val);
+ fclose(f);
+ if (ret < 0) {
+ ksft_test_result_fail("Error writing %d to %s\n",
+ val, name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Verify that we can read the default VL via proc, checking that it
+ * is set in a freshly spawned child.
+ */
+static void proc_read_default(struct vec_data *data)
+{
+ int default_vl, child_vl, ret;
+
+ ret = file_read_integer(data->default_vl_file, &default_vl);
+ if (ret != 0)
+ return;
+
+ /* Is this the actual default seen by new processes? */
+ child_vl = get_child_rdvl(data);
+ if (child_vl != default_vl) {
+ ksft_test_result_fail("%s is %d but child VL is %d\n",
+ data->default_vl_file,
+ default_vl, child_vl);
+ return;
+ }
+
+ ksft_test_result_pass("%s default vector length %d\n", data->name,
+ default_vl);
+ data->default_vl = default_vl;
+}
+
+/* Verify that we can write a minimum value and have it take effect */
+static void proc_write_min(struct vec_data *data)
+{
+ int ret, new_default, child_vl;
+
+ if (geteuid() != 0) {
+ ksft_test_result_skip("Need to be root to write to /proc\n");
+ return;
+ }
+
+ ret = file_write_integer(data->default_vl_file, ARCH_MIN_VL);
+ if (ret != 0)
+ return;
+
+ /* What was the new value? */
+ ret = file_read_integer(data->default_vl_file, &new_default);
+ if (ret != 0)
+ return;
+
+ /* Did it take effect in a new process? */
+ child_vl = get_child_rdvl(data);
+ if (child_vl != new_default) {
+ ksft_test_result_fail("%s is %d but child VL is %d\n",
+ data->default_vl_file,
+ new_default, child_vl);
+ return;
+ }
+
+ ksft_test_result_pass("%s minimum vector length %d\n", data->name,
+ new_default);
+ data->min_vl = new_default;
+
+ file_write_integer(data->default_vl_file, data->default_vl);
+}
+
+/* Verify that we can write a maximum value and have it take effect */
+static void proc_write_max(struct vec_data *data)
+{
+ int ret, new_default, child_vl;
+
+ if (geteuid() != 0) {
+ ksft_test_result_skip("Need to be root to write to /proc\n");
+ return;
+ }
+
+ /* -1 is accepted by the /proc interface as the maximum VL */
+ ret = file_write_integer(data->default_vl_file, -1);
+ if (ret != 0)
+ return;
+
+ /* What was the new value? */
+ ret = file_read_integer(data->default_vl_file, &new_default);
+ if (ret != 0)
+ return;
+
+ /* Did it take effect in a new process? */
+ child_vl = get_child_rdvl(data);
+ if (child_vl != new_default) {
+ ksft_test_result_fail("%s is %d but child VL is %d\n",
+ data->default_vl_file,
+ new_default, child_vl);
+ return;
+ }
+
+ ksft_test_result_pass("%s maximum vector length %d\n", data->name,
+ new_default);
+ data->max_vl = new_default;
+
+ file_write_integer(data->default_vl_file, data->default_vl);
+}
+
+/* Can we read back a VL from prctl? */
+static void prctl_get(struct vec_data *data)
+{
+ int ret;
+
+ ret = prctl(data->prctl_get);
+ if (ret == -1) {
+ ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
+ data->name, errno, strerror(errno));
+ return;
+ }
+
+ /* Mask out any flags */
+ ret &= PR_SVE_VL_LEN_MASK;
+
+ /* Is that what we can read back directly? */
+ if (ret == data->rdvl())
+ ksft_test_result_pass("%s current VL is %d\n",
+ data->name, ret);
+ else
+ ksft_test_result_fail("%s prctl() VL %d but RDVL is %d\n",
+ data->name, ret, data->rdvl());
+}
+
+/* Does the prctl let us set the VL we already have? */
+static void prctl_set_same(struct vec_data *data)
+{
+ int cur_vl = data->rdvl();
+ int ret;
+
+ ret = prctl(data->prctl_set, cur_vl);
+ if (ret < 0) {
+ ksft_test_result_fail("%s prctl set failed: %d (%s)\n",
+ data->name, errno, strerror(errno));
+ return;
+ }
+
+ if (cur_vl != data->rdvl())
+ ksft_test_result_pass("%s current VL is %d\n",
+ data->name, ret);
+ else
+ ksft_test_result_fail("%s prctl() VL %d but RDVL is %d\n",
+ data->name, ret, data->rdvl());
+}
+
+/* Can we set a new VL for this process? */
+static void prctl_set(struct vec_data *data)
+{
+ int ret;
+
+ if (data->min_vl == data->max_vl) {
+ ksft_test_result_skip("%s only one VL supported\n",
+ data->name);
+ return;
+ }
+
+ /* Try to set the minimum VL */
+ ret = prctl(data->prctl_set, data->min_vl);
+ if (ret < 0) {
+ ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
+ data->name, data->min_vl,
+ errno, strerror(errno));
+ return;
+ }
+
+ if ((ret & PR_SVE_VL_LEN_MASK) != data->min_vl) {
+ ksft_test_result_fail("%s prctl set %d but return value is %d\n",
+ data->name, data->min_vl, data->rdvl());
+ return;
+ }
+
+ if (data->rdvl() != data->min_vl) {
+ ksft_test_result_fail("%s set %d but RDVL is %d\n",
+ data->name, data->min_vl, data->rdvl());
+ return;
+ }
+
+ /* Try to set the maximum VL */
+ ret = prctl(data->prctl_set, data->max_vl);
+ if (ret < 0) {
+ ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
+ data->name, data->max_vl,
+ errno, strerror(errno));
+ return;
+ }
+
+ if ((ret & PR_SVE_VL_LEN_MASK) != data->max_vl) {
+ ksft_test_result_fail("%s prctl() set %d but return value is %d\n",
+ data->name, data->max_vl, data->rdvl());
+ return;
+ }
+
+ /* The _INHERIT flag should not be present when we read the VL */
+ ret = prctl(data->prctl_get);
+ if (ret == -1) {
+ ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
+ data->name, errno, strerror(errno));
+ return;
+ }
+
+ if (ret & PR_SVE_VL_INHERIT) {
+ ksft_test_result_fail("%s prctl() reports _INHERIT\n",
+ data->name);
+ return;
+ }
+
+ ksft_test_result_pass("%s prctl() set min/max\n", data->name);
+}
+
+/* If we didn't request it a new VL shouldn't affect the child */
+static void prctl_set_no_child(struct vec_data *data)
+{
+ int ret, child_vl;
+
+ if (data->min_vl == data->max_vl) {
+ ksft_test_result_skip("%s only one VL supported\n",
+ data->name);
+ return;
+ }
+
+ ret = prctl(data->prctl_set, data->min_vl);
+ if (ret < 0) {
+ ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
+ data->name, data->min_vl,
+ errno, strerror(errno));
+ return;
+ }
+
+ /* Ensure the default VL is different */
+ ret = file_write_integer(data->default_vl_file, data->max_vl);
+ if (ret != 0)
+ return;
+
+ /* Check that the child has the default we just set */
+ child_vl = get_child_rdvl(data);
+ if (child_vl != data->max_vl) {
+ ksft_test_result_fail("%s is %d but child VL is %d\n",
+ data->default_vl_file,
+ data->max_vl, child_vl);
+ return;
+ }
+
+ ksft_test_result_pass("%s vector length used default\n", data->name);
+
+ file_write_integer(data->default_vl_file, data->default_vl);
+}
+
+/* If we didn't request it a new VL shouldn't affect the child */
+static void prctl_set_for_child(struct vec_data *data)
+{
+ int ret, child_vl;
+
+ if (data->min_vl == data->max_vl) {
+ ksft_test_result_skip("%s only one VL supported\n",
+ data->name);
+ return;
+ }
+
+ ret = prctl(data->prctl_set, data->min_vl | PR_SVE_VL_INHERIT);
+ if (ret < 0) {
+ ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
+ data->name, data->min_vl,
+ errno, strerror(errno));
+ return;
+ }
+
+ /* The _INHERIT flag should be present when we read the VL */
+ ret = prctl(data->prctl_get);
+ if (ret == -1) {
+ ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
+ data->name, errno, strerror(errno));
+ return;
+ }
+ if (!(ret & PR_SVE_VL_INHERIT)) {
+ ksft_test_result_fail("%s prctl() does not report _INHERIT\n",
+ data->name);
+ return;
+ }
+
+ /* Ensure the default VL is different */
+ ret = file_write_integer(data->default_vl_file, data->max_vl);
+ if (ret != 0)
+ return;
+
+ /* Check that the child inherited our VL */
+ child_vl = get_child_rdvl(data);
+ if (child_vl != data->min_vl) {
+ ksft_test_result_fail("%s is %d but child VL is %d\n",
+ data->default_vl_file,
+ data->min_vl, child_vl);
+ return;
+ }
+
+ ksft_test_result_pass("%s vector length was inherited\n", data->name);
+
+ file_write_integer(data->default_vl_file, data->default_vl);
+}
+
+/* _ONEXEC takes effect only in the child process */
+static void prctl_set_onexec(struct vec_data *data)
+{
+ int ret, child_vl;
+
+ if (data->min_vl == data->max_vl) {
+ ksft_test_result_skip("%s only one VL supported\n",
+ data->name);
+ return;
+ }
+
+ /* Set a known value for the default and our current VL */
+ ret = file_write_integer(data->default_vl_file, data->max_vl);
+ if (ret != 0)
+ return;
+
+ ret = prctl(data->prctl_set, data->max_vl);
+ if (ret < 0) {
+ ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
+ data->name, data->min_vl,
+ errno, strerror(errno));
+ return;
+ }
+
+ /* Set a different value for the child to have on exec */
+ ret = prctl(data->prctl_set, data->min_vl | PR_SVE_SET_VL_ONEXEC);
+ if (ret < 0) {
+ ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
+ data->name, data->min_vl,
+ errno, strerror(errno));
+ return;
+ }
+
+ /* Our current VL should stay the same */
+ if (data->rdvl() != data->max_vl) {
+ ksft_test_result_fail("%s VL changed by _ONEXEC prctl()\n",
+ data->name);
+ return;
+ }
+
+ /* Check that the child inherited our VL */
+ child_vl = get_child_rdvl(data);
+ if (child_vl != data->min_vl) {
+ ksft_test_result_fail("Set %d _ONEXEC but child VL is %d\n",
+ data->min_vl, child_vl);
+ return;
+ }
+
+ ksft_test_result_pass("%s vector length set on exec\n", data->name);
+
+ file_write_integer(data->default_vl_file, data->default_vl);
+}
+
+typedef void (*test_type)(struct vec_data *);
+
+static const test_type tests[] = {
+ /*
+ * The default/min/max tests must be first and in this order
+ * to provide data for other tests.
+ */
+ proc_read_default,
+ proc_write_min,
+ proc_write_max,
+
+ prctl_get,
+ prctl_set,
+ prctl_set_no_child,
+ prctl_set_for_child,
+ prctl_set_onexec,
+};
+
+int main(void)
+{
+ int i, j;
+
+ ksft_print_header();
+ ksft_set_plan(ARRAY_SIZE(tests) * ARRAY_SIZE(vec_data));
+
+ for (i = 0; i < ARRAY_SIZE(vec_data); i++) {
+ struct vec_data *data = &vec_data[i];
+ unsigned long supported;
+
+ supported = getauxval(data->hwcap_type) & data->hwcap;
+
+ for (j = 0; j < ARRAY_SIZE(tests); j++) {
+ if (supported)
+ tests[j](data);
+ else
+ ksft_test_result_skip("%s not supported\n",
+ data->name);
+ }
+ }
+
+ ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/arm64/mte/.gitignore b/tools/testing/selftests/arm64/mte/.gitignore
index bc3ac63f3314..d1fe4ddf1669 100644
--- a/tools/testing/selftests/arm64/mte/.gitignore
+++ b/tools/testing/selftests/arm64/mte/.gitignore
@@ -1,4 +1,5 @@
check_buffer_fill
+check_gcr_el1_cswitch
check_tags_inclusion
check_child_memory
check_mmap_options
diff --git a/tools/testing/selftests/arm64/mte/mte_common_util.c b/tools/testing/selftests/arm64/mte/mte_common_util.c
index f50ac31920d1..0328a1e08f65 100644
--- a/tools/testing/selftests/arm64/mte/mte_common_util.c
+++ b/tools/testing/selftests/arm64/mte/mte_common_util.c
@@ -298,7 +298,7 @@ int mte_default_setup(void)
int ret;
if (!(hwcaps2 & HWCAP2_MTE)) {
- ksft_print_msg("FAIL: MTE features unavailable\n");
+ ksft_print_msg("SKIP: MTE features unavailable\n");
return KSFT_SKIP;
}
/* Get current mte mode */
diff --git a/tools/testing/selftests/arm64/pauth/pac.c b/tools/testing/selftests/arm64/pauth/pac.c
index 592fe538506e..b743daa772f5 100644
--- a/tools/testing/selftests/arm64/pauth/pac.c
+++ b/tools/testing/selftests/arm64/pauth/pac.c
@@ -25,13 +25,15 @@
do { \
unsigned long hwcaps = getauxval(AT_HWCAP); \
/* data key instructions are not in NOP space. This prevents a SIGILL */ \
- ASSERT_NE(0, hwcaps & HWCAP_PACA) TH_LOG("PAUTH not enabled"); \
+ if (!(hwcaps & HWCAP_PACA)) \
+ SKIP(return, "PAUTH not enabled"); \
} while (0)
#define ASSERT_GENERIC_PAUTH_ENABLED() \
do { \
unsigned long hwcaps = getauxval(AT_HWCAP); \
/* generic key instructions are not in NOP space. This prevents a SIGILL */ \
- ASSERT_NE(0, hwcaps & HWCAP_PACG) TH_LOG("Generic PAUTH not enabled"); \
+ if (!(hwcaps & HWCAP_PACG)) \
+ SKIP(return, "Generic PAUTH not enabled"); \
} while (0)
void sign_specific(struct signatures *sign, size_t val)
@@ -256,7 +258,7 @@ TEST(single_thread_different_keys)
unsigned long hwcaps = getauxval(AT_HWCAP);
/* generic and data key instructions are not in NOP space. This prevents a SIGILL */
- ASSERT_NE(0, hwcaps & HWCAP_PACA) TH_LOG("PAUTH not enabled");
+ ASSERT_PAUTH_ENABLED();
if (!(hwcaps & HWCAP_PACG)) {
TH_LOG("WARNING: Generic PAUTH not enabled. Skipping generic key checks");
nkeys = NKEYS - 1;
@@ -299,7 +301,7 @@ TEST(exec_changed_keys)
unsigned long hwcaps = getauxval(AT_HWCAP);
/* generic and data key instructions are not in NOP space. This prevents a SIGILL */
- ASSERT_NE(0, hwcaps & HWCAP_PACA) TH_LOG("PAUTH not enabled");
+ ASSERT_PAUTH_ENABLED();
if (!(hwcaps & HWCAP_PACG)) {
TH_LOG("WARNING: Generic PAUTH not enabled. Skipping generic key checks");
nkeys = NKEYS - 1;
diff --git a/tools/testing/selftests/arm64/signal/.gitignore b/tools/testing/selftests/arm64/signal/.gitignore
index 78c902045ca7..c1742755abb9 100644
--- a/tools/testing/selftests/arm64/signal/.gitignore
+++ b/tools/testing/selftests/arm64/signal/.gitignore
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
mangle_*
fake_sigreturn_*
+sve_*
!*.[ch]
diff --git a/tools/testing/selftests/arm64/signal/test_signals.h b/tools/testing/selftests/arm64/signal/test_signals.h
index f96baf1cef1a..ebe8694dbef0 100644
--- a/tools/testing/selftests/arm64/signal/test_signals.h
+++ b/tools/testing/selftests/arm64/signal/test_signals.h
@@ -33,10 +33,12 @@
*/
enum {
FSSBS_BIT,
+ FSVE_BIT,
FMAX_END
};
#define FEAT_SSBS (1UL << FSSBS_BIT)
+#define FEAT_SVE (1UL << FSVE_BIT)
/*
* A descriptor used to describe and configure a test case.
diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.c b/tools/testing/selftests/arm64/signal/test_signals_utils.c
index 2de6e5ed5e25..6836510a522f 100644
--- a/tools/testing/selftests/arm64/signal/test_signals_utils.c
+++ b/tools/testing/selftests/arm64/signal/test_signals_utils.c
@@ -26,6 +26,7 @@ static int sig_copyctx = SIGTRAP;
static char const *const feats_names[FMAX_END] = {
" SSBS ",
+ " SVE ",
};
#define MAX_FEATS_SZ 128
@@ -263,6 +264,8 @@ int test_init(struct tdescr *td)
*/
if (getauxval(AT_HWCAP) & HWCAP_SSBS)
td->feats_supported |= FEAT_SSBS;
+ if (getauxval(AT_HWCAP) & HWCAP_SVE)
+ td->feats_supported |= FEAT_SVE;
if (feats_ok(td))
fprintf(stderr,
"Required Features: [%s] supported\n",
diff --git a/tools/testing/selftests/arm64/signal/testcases/TODO b/tools/testing/selftests/arm64/signal/testcases/TODO
new file mode 100644
index 000000000000..110ff9fd195d
--- /dev/null
+++ b/tools/testing/selftests/arm64/signal/testcases/TODO
@@ -0,0 +1,2 @@
+- Validate that register contents are saved and restored as expected.
+- Support and validate extra_context.
diff --git a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
new file mode 100644
index 000000000000..bb50b5adbf10
--- /dev/null
+++ b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 ARM Limited
+ *
+ * Attempt to change the SVE vector length in a signal hander, this is not
+ * supported and is expected to segfault.
+ */
+
+#include <signal.h>
+#include <ucontext.h>
+#include <sys/prctl.h>
+
+#include "test_signals_utils.h"
+#include "testcases.h"
+
+struct fake_sigframe sf;
+static unsigned int vls[SVE_VQ_MAX];
+unsigned int nvls = 0;
+
+static bool sve_get_vls(struct tdescr *td)
+{
+ int vq, vl;
+
+ /*
+ * Enumerate up to SVE_VQ_MAX vector lengths
+ */
+ for (vq = SVE_VQ_MAX; vq > 0; --vq) {
+ vl = prctl(PR_SVE_SET_VL, vq * 16);
+ if (vl == -1)
+ return false;
+
+ vl &= PR_SVE_VL_LEN_MASK;
+
+ /* Skip missing VLs */
+ vq = sve_vq_from_vl(vl);
+
+ vls[nvls++] = vl;
+ }
+
+ /* We need at least two VLs */
+ if (nvls < 2) {
+ fprintf(stderr, "Only %d VL supported\n", nvls);
+ return false;
+ }
+
+ return true;
+}
+
+static int fake_sigreturn_sve_change_vl(struct tdescr *td,
+ siginfo_t *si, ucontext_t *uc)
+{
+ size_t resv_sz, offset;
+ struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
+ struct sve_context *sve;
+
+ /* Get a signal context with a SVE frame in it */
+ if (!get_current_context(td, &sf.uc))
+ return 1;
+
+ resv_sz = GET_SF_RESV_SIZE(sf);
+ head = get_header(head, SVE_MAGIC, resv_sz, &offset);
+ if (!head) {
+ fprintf(stderr, "No SVE context\n");
+ return 1;
+ }
+
+ if (head->size != sizeof(struct sve_context)) {
+ fprintf(stderr, "SVE register state active, skipping\n");
+ return 1;
+ }
+
+ sve = (struct sve_context *)head;
+
+ /* No changes are supported; init left us at minimum VL so go to max */
+ fprintf(stderr, "Attempting to change VL from %d to %d\n",
+ sve->vl, vls[0]);
+ sve->vl = vls[0];
+
+ fake_sigreturn(&sf, sizeof(sf), 0);
+
+ return 1;
+}
+
+struct tdescr tde = {
+ .name = "FAKE_SIGRETURN_SVE_CHANGE",
+ .descr = "Attempt to change SVE VL",
+ .feats_required = FEAT_SVE,
+ .sig_ok = SIGSEGV,
+ .timeout = 3,
+ .init = sve_get_vls,
+ .run = fake_sigreturn_sve_change_vl,
+};
diff --git a/tools/testing/selftests/arm64/signal/testcases/sve_regs.c b/tools/testing/selftests/arm64/signal/testcases/sve_regs.c
new file mode 100644
index 000000000000..4b2418aa08a9
--- /dev/null
+++ b/tools/testing/selftests/arm64/signal/testcases/sve_regs.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 ARM Limited
+ *
+ * Verify that the SVE register context in signal frames is set up as
+ * expected.
+ */
+
+#include <signal.h>
+#include <ucontext.h>
+#include <sys/prctl.h>
+
+#include "test_signals_utils.h"
+#include "testcases.h"
+
+struct fake_sigframe sf;
+static unsigned int vls[SVE_VQ_MAX];
+unsigned int nvls = 0;
+
+static bool sve_get_vls(struct tdescr *td)
+{
+ int vq, vl;
+
+ /*
+ * Enumerate up to SVE_VQ_MAX vector lengths
+ */
+ for (vq = SVE_VQ_MAX; vq > 0; --vq) {
+ vl = prctl(PR_SVE_SET_VL, vq * 16);
+ if (vl == -1)
+ return false;
+
+ vl &= PR_SVE_VL_LEN_MASK;
+
+ /* Skip missing VLs */
+ vq = sve_vq_from_vl(vl);
+
+ vls[nvls++] = vl;
+ }
+
+ /* We need at least one VL */
+ if (nvls < 1) {
+ fprintf(stderr, "Only %d VL supported\n", nvls);
+ return false;
+ }
+
+ return true;
+}
+
+static void setup_sve_regs(void)
+{
+ /* RDVL x16, #1 so we should have SVE regs; real data is TODO */
+ asm volatile(".inst 0x04bf5030" : : : "x16" );
+}
+
+static int do_one_sve_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,
+ unsigned int vl)
+{
+ size_t resv_sz, offset;
+ struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
+ struct sve_context *sve;
+
+ fprintf(stderr, "Testing VL %d\n", vl);
+
+ if (prctl(PR_SVE_SET_VL, vl) == -1) {
+ fprintf(stderr, "Failed to set VL\n");
+ return 1;
+ }
+
+ /*
+ * Get a signal context which should have a SVE frame and registers
+ * in it.
+ */
+ setup_sve_regs();
+ if (!get_current_context(td, &sf.uc))
+ return 1;
+
+ resv_sz = GET_SF_RESV_SIZE(sf);
+ head = get_header(head, SVE_MAGIC, resv_sz, &offset);
+ if (!head) {
+ fprintf(stderr, "No SVE context\n");
+ return 1;
+ }
+
+ sve = (struct sve_context *)head;
+ if (sve->vl != vl) {
+ fprintf(stderr, "Got VL %d, expected %d\n", sve->vl, vl);
+ return 1;
+ }
+
+ /* The actual size validation is done in get_current_context() */
+ fprintf(stderr, "Got expected size %u and VL %d\n",
+ head->size, sve->vl);
+
+ return 0;
+}
+
+static int sve_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
+{
+ int i;
+
+ for (i = 0; i < nvls; i++) {
+ /*
+ * TODO: the signal test helpers can't currently cope
+ * with signal frames bigger than struct sigcontext,
+ * skip VLs that will trigger that.
+ */
+ if (vls[i] > 64)
+ continue;
+
+ if (do_one_sve_vl(td, si, uc, vls[i]))
+ return 1;
+ }
+
+ td->pass = 1;
+
+ return 0;
+}
+
+struct tdescr tde = {
+ .name = "SVE registers",
+ .descr = "Check that we get the right SVE registers reported",
+ .feats_required = FEAT_SVE,
+ .timeout = 3,
+ .init = sve_get_vls,
+ .run = sve_regs,
+};
diff --git a/tools/testing/selftests/arm64/signal/testcases/sve_vl.c b/tools/testing/selftests/arm64/signal/testcases/sve_vl.c
new file mode 100644
index 000000000000..92904653add1
--- /dev/null
+++ b/tools/testing/selftests/arm64/signal/testcases/sve_vl.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 ARM Limited
+ *
+ * Check that the SVE vector length reported in signal contexts is the
+ * expected one.
+ */
+
+#include <signal.h>
+#include <ucontext.h>
+#include <sys/prctl.h>
+
+#include "test_signals_utils.h"
+#include "testcases.h"
+
+struct fake_sigframe sf;
+unsigned int vl;
+
+static bool get_sve_vl(struct tdescr *td)
+{
+ int ret = prctl(PR_SVE_GET_VL);
+ if (ret == -1)
+ return false;
+
+ vl = ret;
+
+ return true;
+}
+
+static int sve_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
+{
+ size_t resv_sz, offset;
+ struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
+ struct sve_context *sve;
+
+ /* Get a signal context which should have a SVE frame in it */
+ if (!get_current_context(td, &sf.uc))
+ return 1;
+
+ resv_sz = GET_SF_RESV_SIZE(sf);
+ head = get_header(head, SVE_MAGIC, resv_sz, &offset);
+ if (!head) {
+ fprintf(stderr, "No SVE context\n");
+ return 1;
+ }
+ sve = (struct sve_context *)head;
+
+ if (sve->vl != vl) {
+ fprintf(stderr, "sigframe VL %u, expected %u\n",
+ sve->vl, vl);
+ return 1;
+ } else {
+ fprintf(stderr, "got expected VL %u\n", vl);
+ }
+
+ td->pass = 1;
+
+ return 0;
+}
+
+struct tdescr tde = {
+ .name = "SVE VL",
+ .descr = "Check that we get the right SVE VL reported",
+ .feats_required = FEAT_SVE,
+ .timeout = 3,
+ .init = get_sve_vl,
+ .run = sve_vl,
+};
diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c
index 61ebcdf63831..8c2a57fc2f9c 100644
--- a/tools/testing/selftests/arm64/signal/testcases/testcases.c
+++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c
@@ -50,12 +50,38 @@ bool validate_extra_context(struct extra_context *extra, char **err)
return true;
}
+bool validate_sve_context(struct sve_context *sve, char **err)
+{
+ /* Size will be rounded up to a multiple of 16 bytes */
+ size_t regs_size
+ = ((SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl(sve->vl)) + 15) / 16) * 16;
+
+ if (!sve || !err)
+ return false;
+
+ /* Either a bare sve_context or a sve_context followed by regs data */
+ if ((sve->head.size != sizeof(struct sve_context)) &&
+ (sve->head.size != regs_size)) {
+ *err = "bad size for SVE context";
+ return false;
+ }
+
+ if (!sve_vl_valid(sve->vl)) {
+ *err = "SVE VL invalid";
+
+ return false;
+ }
+
+ return true;
+}
+
bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
{
bool terminated = false;
size_t offs = 0;
int flags = 0;
struct extra_context *extra = NULL;
+ struct sve_context *sve = NULL;
struct _aarch64_ctx *head =
(struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
@@ -90,9 +116,8 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
case SVE_MAGIC:
if (flags & SVE_CTX)
*err = "Multiple SVE_MAGIC";
- else if (head->size !=
- sizeof(struct sve_context))
- *err = "Bad size for sve_context";
+ /* Size is validated in validate_sve_context() */
+ sve = (struct sve_context *)head;
flags |= SVE_CTX;
break;
case EXTRA_MAGIC:
@@ -137,6 +162,9 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
if (flags & EXTRA_CTX)
if (!validate_extra_context(extra, err))
return false;
+ if (flags & SVE_CTX)
+ if (!validate_sve_context(sve, err))
+ return false;
head = GET_RESV_NEXT_HEAD(head);
}
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c b/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
index 370d220288a6..ad3ba81b4048 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
@@ -384,8 +384,7 @@ static void test_xdp_bonding_attach(struct skeletons *skeletons)
{
struct bpf_link *link = NULL;
struct bpf_link *link2 = NULL;
- int veth, bond;
- int err;
+ int veth, bond, err;
if (!ASSERT_OK(system("ip link add veth type veth"), "add veth"))
goto out;
@@ -399,22 +398,18 @@ static void test_xdp_bonding_attach(struct skeletons *skeletons)
if (!ASSERT_GE(bond, 0, "if_nametoindex bond"))
goto out;
- /* enslaving with a XDP program loaded fails */
+ /* enslaving with a XDP program loaded is allowed */
link = bpf_program__attach_xdp(skeletons->xdp_dummy->progs.xdp_dummy_prog, veth);
if (!ASSERT_OK_PTR(link, "attach program to veth"))
goto out;
err = system("ip link set veth master bond");
- if (!ASSERT_NEQ(err, 0, "attaching slave with xdp program expected to fail"))
+ if (!ASSERT_OK(err, "set veth master"))
goto out;
bpf_link__destroy(link);
link = NULL;
- err = system("ip link set veth master bond");
- if (!ASSERT_OK(err, "set veth master"))
- goto out;
-
/* attaching to slave when master has no program is allowed */
link = bpf_program__attach_xdp(skeletons->xdp_dummy->progs.xdp_dummy_prog, veth);
if (!ASSERT_OK_PTR(link, "attach program to slave when enslaved"))
@@ -434,8 +429,26 @@ static void test_xdp_bonding_attach(struct skeletons *skeletons)
goto out;
/* attaching to slave not allowed when master has program loaded */
- link2 = bpf_program__attach_xdp(skeletons->xdp_dummy->progs.xdp_dummy_prog, bond);
- ASSERT_ERR_PTR(link2, "attach program to slave when master has program");
+ link2 = bpf_program__attach_xdp(skeletons->xdp_dummy->progs.xdp_dummy_prog, veth);
+ if (!ASSERT_ERR_PTR(link2, "attach program to slave when master has program"))
+ goto out;
+
+ bpf_link__destroy(link);
+ link = NULL;
+
+ /* test program unwinding with a non-XDP slave */
+ if (!ASSERT_OK(system("ip link add vxlan type vxlan id 1 remote 1.2.3.4 dstport 0 dev lo"),
+ "add vxlan"))
+ goto out;
+
+ err = system("ip link set vxlan master bond");
+ if (!ASSERT_OK(err, "set vxlan master"))
+ goto out;
+
+ /* attaching not allowed when one slave does not support XDP */
+ link = bpf_program__attach_xdp(skeletons->xdp_dummy->progs.xdp_dummy_prog, bond);
+ if (!ASSERT_ERR_PTR(link, "attach program to master when slave does not support XDP"))
+ goto out;
out:
bpf_link__destroy(link);
@@ -443,6 +456,44 @@ out:
system("ip link del veth");
system("ip link del bond");
+ system("ip link del vxlan");
+}
+
+/* Test with nested bonding devices to catch issue with negative jump label count */
+static void test_xdp_bonding_nested(struct skeletons *skeletons)
+{
+ struct bpf_link *link = NULL;
+ int bond, err;
+
+ if (!ASSERT_OK(system("ip link add bond type bond"), "add bond"))
+ goto out;
+
+ bond = if_nametoindex("bond");
+ if (!ASSERT_GE(bond, 0, "if_nametoindex bond"))
+ goto out;
+
+ if (!ASSERT_OK(system("ip link add bond_nest1 type bond"), "add bond_nest1"))
+ goto out;
+
+ err = system("ip link set bond_nest1 master bond");
+ if (!ASSERT_OK(err, "set bond_nest1 master"))
+ goto out;
+
+ if (!ASSERT_OK(system("ip link add bond_nest2 type bond"), "add bond_nest1"))
+ goto out;
+
+ err = system("ip link set bond_nest2 master bond_nest1");
+ if (!ASSERT_OK(err, "set bond_nest2 master"))
+ goto out;
+
+ link = bpf_program__attach_xdp(skeletons->xdp_dummy->progs.xdp_dummy_prog, bond);
+ ASSERT_OK_PTR(link, "attach program to master");
+
+out:
+ bpf_link__destroy(link);
+ system("ip link del bond");
+ system("ip link del bond_nest1");
+ system("ip link del bond_nest2");
}
static int libbpf_debug_print(enum libbpf_print_level level,
@@ -496,6 +547,9 @@ void test_xdp_bonding(void)
if (test__start_subtest("xdp_bonding_attach"))
test_xdp_bonding_attach(&skeletons);
+ if (test__start_subtest("xdp_bonding_nested"))
+ test_xdp_bonding_nested(&skeletons);
+
for (i = 0; i < ARRAY_SIZE(bond_test_cases); i++) {
struct bond_test_case *test_case = &bond_test_cases[i];
diff --git a/tools/testing/selftests/cpufreq/config b/tools/testing/selftests/cpufreq/config
index 27ff72ebd0f5..75e900793e8a 100644
--- a/tools/testing/selftests/cpufreq/config
+++ b/tools/testing/selftests/cpufreq/config
@@ -6,7 +6,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_PI_LIST=y
+CONFIG_DEBUG_PLIST=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
index 477cbb042f5b..0315955ff0f4 100644
--- a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
+++ b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
@@ -62,6 +62,9 @@ static int __do_binderfs_test(struct __test_metadata *_metadata)
struct binder_version version = { 0 };
char binderfs_mntpt[] = P_tmpdir "/binderfs_XXXXXX",
device_path[sizeof(P_tmpdir "/binderfs_XXXXXX/") + BINDERFS_MAX_NAME];
+ static const char * const binder_features[] = {
+ "oneway_spam_detection",
+ };
change_mountns(_metadata);
@@ -150,6 +153,20 @@ static int __do_binderfs_test(struct __test_metadata *_metadata)
}
/* success: binder-control device removal failed as expected */
+
+ for (int i = 0; i < ARRAY_SIZE(binder_features); i++) {
+ snprintf(device_path, sizeof(device_path), "%s/features/%s",
+ binderfs_mntpt, binder_features[i]);
+ fd = open(device_path, O_CLOEXEC | O_RDONLY);
+ EXPECT_GE(fd, 0) {
+ TH_LOG("%s - Failed to open binder feature: %s",
+ strerror(errno), binder_features[i]);
+ goto umount;
+ }
+ close(fd);
+ }
+
+ /* success: binder feature files found */
result = 0;
umount:
diff --git a/tools/testing/selftests/firmware/fw_namespace.c b/tools/testing/selftests/firmware/fw_namespace.c
index 0e393cb5f42d..4c6f0cd83c5b 100644
--- a/tools/testing/selftests/firmware/fw_namespace.c
+++ b/tools/testing/selftests/firmware/fw_namespace.c
@@ -129,7 +129,8 @@ int main(int argc, char **argv)
die("mounting tmpfs to /lib/firmware failed\n");
sys_path = argv[1];
- asprintf(&fw_path, "/lib/firmware/%s", fw_name);
+ if (asprintf(&fw_path, "/lib/firmware/%s", fw_name) < 0)
+ die("error: failed to build full fw_path\n");
setup_fw(fw_path);
diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
new file mode 100644
index 000000000000..25a3da4eaa44
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc
@@ -0,0 +1,40 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: Generic dynamic event - add/remove eprobe events
+# requires: dynamic_events events/syscalls/sys_enter_openat "e[:[<group>/]<event>] <attached-group>.<attached-event> [<args>]":README
+
+echo 0 > events/enable
+
+clear_dynamic_events
+
+SYSTEM="syscalls"
+EVENT="sys_enter_openat"
+FIELD="filename"
+EPROBE="eprobe_open"
+
+echo "e:$EPROBE $SYSTEM/$EVENT file=+0(\$filename):ustring" >> dynamic_events
+
+grep -q "$EPROBE" dynamic_events
+test -d events/eprobes/$EPROBE
+
+echo 1 > events/eprobes/$EPROBE/enable
+ls
+echo 0 > events/eprobes/$EPROBE/enable
+
+content=`grep '^ *ls-' trace | grep 'file='`
+nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."'` || true
+
+if [ -z "$content" ]; then
+ exit_fail
+fi
+
+if [ ! -z "$nocontent" ]; then
+ exit_fail
+fi
+
+echo "-:$EPROBE" >> dynamic_events
+
+! grep -q "$EPROBE" dynamic_events
+! test -d events/eprobes/$EPROBE
+
+clear_trace
diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc b/tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc
new file mode 100644
index 000000000000..db522577ff78
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc
@@ -0,0 +1,38 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: Generic dynamic event - check if duplicate events are caught
+# requires: dynamic_events "e[:[<group>/]<event>] <attached-group>.<attached-event> [<args>]":README
+
+echo 0 > events/enable
+
+HAVE_KPROBES=0
+
+if [ -f kprobe_events ]; then
+ HAVE_KPROBES=1
+fi
+
+clear_dynamic_events
+
+# first create dynamic events for eprobes and kprobes.
+
+echo 'e:egroup/eevent syscalls/sys_enter_openat file=+0($filename):ustring' >> dynamic_events
+
+# Test eprobe for same eprobe, existing kprobe and existing event
+! echo 'e:egroup/eevent syscalls/sys_enter_openat file=+0($filename):ustring' >> dynamic_events
+! echo 'e:syscalls/sys_enter_open syscalls/sys_enter_openat file=+0($filename):ustring' >> dynamic_events
+
+if [ $HAVE_KPROBES -eq 1 ]; then
+ echo 'p:kgroup/kevent vfs_open file=+0($arg2)' >> dynamic_events
+ ! echo 'e:kgroup/kevent syscalls/sys_enter_openat file=+0($filename):ustring' >> dynamic_events
+
+# Test kprobe for same kprobe, existing eprobe and existing event
+ ! echo 'p:kgroup/kevent vfs_open file=+0($arg2)' >> dynamic_events
+ ! echo 'p:egroup/eevent vfs_open file=+0($arg2)' >> dynamic_events
+ ! echo 'p:syscalls/sys_enter_open vfs_open file=+0($arg2)' >> dynamic_events
+
+ echo '-:kgroup/kevent' >> dynamic_events
+fi
+
+echo '-:egroup/eevent' >> dynamic_events
+
+clear_trace
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
index a6fac927ee82..000fd05e84b1 100644
--- a/tools/testing/selftests/ftrace/test.d/functions
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -83,6 +83,27 @@ clear_synthetic_events() { # reset all current synthetic events
done
}
+clear_dynamic_events() { # reset all current dynamic events
+ again=1
+ stop=1
+ # loop mulitple times as some events require other to be removed first
+ while [ $again -eq 1 ]; do
+ stop=$((stop+1))
+ # Prevent infinite loops
+ if [ $stop -gt 10 ]; then
+ break;
+ fi
+ again=2
+ grep -v '^#' dynamic_events|
+ while read line; do
+ del=`echo $line | sed -e 's/^.\([^ ]*\).*/-\1/'`
+ if ! echo "$del" >> dynamic_events; then
+ again=1
+ fi
+ done
+ done
+}
+
initialize_ftrace() { # Reset ftrace to initial-state
# As the initial state, ftrace will be set to nop tracer,
# no events, no triggers, no filters, no function filters,
@@ -93,6 +114,7 @@ initialize_ftrace() { # Reset ftrace to initial-state
reset_events_filter
reset_ftrace_filter
disable_events
+ clear_dynamic_events
[ -f set_event_pid ] && echo > set_event_pid
[ -f set_ftrace_pid ] && echo > set_ftrace_pid
[ -f set_ftrace_notrace ] && echo > set_ftrace_notrace
@@ -115,7 +137,7 @@ check_requires() { # Check required files and tracers
echo "Required tracer $t is not configured."
exit_unsupported
fi
- elif [ $r != $i ]; then
+ elif [ "$r" != "$i" ]; then
if ! grep -Fq "$r" README ; then
echo "Required feature pattern \"$r\" is not in README."
exit_unsupported
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc
new file mode 100644
index 000000000000..914fe2e5d030
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc
@@ -0,0 +1,53 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: event trigger - test inter-event histogram trigger eprobe on synthetic event
+# requires: dynamic_events synthetic_events events/syscalls/sys_enter_openat/hist "e[:[<group>/]<event>] <attached-group>.<attached-event> [<args>]":README
+
+echo 0 > events/enable
+
+clear_dynamic_events
+
+SYSTEM="syscalls"
+START="sys_enter_openat"
+END="sys_exit_openat"
+FIELD="filename"
+SYNTH="synth_open"
+EPROBE="eprobe_open"
+
+echo "$SYNTH u64 filename; s64 ret;" > synthetic_events
+echo "hist:keys=common_pid:__arg__1=$FIELD" > events/$SYSTEM/$START/trigger
+echo "hist:keys=common_pid:filename=\$__arg__1,ret=ret:onmatch($SYSTEM.$START).trace($SYNTH,\$filename,\$ret)" > events/$SYSTEM/$END/trigger
+
+echo "e:$EPROBE synthetic/$SYNTH file=+0(\$filename):ustring ret=\$ret:s64" >> dynamic_events
+
+grep -q "$SYNTH" dynamic_events
+grep -q "$EPROBE" dynamic_events
+test -d events/synthetic/$SYNTH
+test -d events/eprobes/$EPROBE
+
+echo 1 > events/eprobes/$EPROBE/enable
+ls
+echo 0 > events/eprobes/$EPROBE/enable
+
+content=`grep '^ *ls-' trace | grep 'file='`
+nocontent=`grep '^ *ls-' trace | grep 'file=' | grep -v -e '"/' -e '"."'` || true
+
+if [ -z "$content" ]; then
+ exit_fail
+fi
+
+if [ ! -z "$nocontent" ]; then
+ exit_fail
+fi
+
+echo "-:$EPROBE" >> dynamic_events
+echo '!'"hist:keys=common_pid:filename=\$__arg__1,ret=ret:onmatch($SYSTEM.$START).trace($SYNTH,\$filename,\$ret)" > events/$SYSTEM/$END/trigger
+echo '!'"hist:keys=common_pid:__arg__1=$FIELD" > events/$SYSTEM/$START/trigger
+echo '!'"$SYNTH u64 filename; s64 ret;" >> synthetic_events
+
+! grep -q "$SYNTH" dynamic_events
+! grep -q "$EPROBE" dynamic_events
+! test -d events/synthetic/$SYNTH
+! test -d events/eprobes/$EPROBE
+
+clear_trace
diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
index 0709af0144c8..98053d3afbda 100644
--- a/tools/testing/selftests/kvm/.gitignore
+++ b/tools/testing/selftests/kvm/.gitignore
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
/aarch64/debug-exceptions
/aarch64/get-reg-list
+/aarch64/psci_cpu_on_test
/aarch64/vgic_init
/s390x/memop
/s390x/resets
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 5832f510a16c..5d05801ab816 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -86,6 +86,7 @@ TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test
TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions
TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list
+TEST_GEN_PROGS_aarch64 += aarch64/psci_cpu_on_test
TEST_GEN_PROGS_aarch64 += aarch64/vgic_init
TEST_GEN_PROGS_aarch64 += demand_paging_test
TEST_GEN_PROGS_aarch64 += dirty_log_test
diff --git a/tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c b/tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c
new file mode 100644
index 000000000000..018c269990e1
--- /dev/null
+++ b/tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * psci_cpu_on_test - Test that the observable state of a vCPU targeted by the
+ * CPU_ON PSCI call matches what the caller requested.
+ *
+ * Copyright (c) 2021 Google LLC.
+ *
+ * This is a regression test for a race between KVM servicing the PSCI call and
+ * userspace reading the vCPUs registers.
+ */
+
+#define _GNU_SOURCE
+
+#include <linux/psci.h>
+
+#include "kvm_util.h"
+#include "processor.h"
+#include "test_util.h"
+
+#define VCPU_ID_SOURCE 0
+#define VCPU_ID_TARGET 1
+
+#define CPU_ON_ENTRY_ADDR 0xfeedf00dul
+#define CPU_ON_CONTEXT_ID 0xdeadc0deul
+
+static uint64_t psci_cpu_on(uint64_t target_cpu, uint64_t entry_addr,
+ uint64_t context_id)
+{
+ register uint64_t x0 asm("x0") = PSCI_0_2_FN64_CPU_ON;
+ register uint64_t x1 asm("x1") = target_cpu;
+ register uint64_t x2 asm("x2") = entry_addr;
+ register uint64_t x3 asm("x3") = context_id;
+
+ asm("hvc #0"
+ : "=r"(x0)
+ : "r"(x0), "r"(x1), "r"(x2), "r"(x3)
+ : "memory");
+
+ return x0;
+}
+
+static uint64_t psci_affinity_info(uint64_t target_affinity,
+ uint64_t lowest_affinity_level)
+{
+ register uint64_t x0 asm("x0") = PSCI_0_2_FN64_AFFINITY_INFO;
+ register uint64_t x1 asm("x1") = target_affinity;
+ register uint64_t x2 asm("x2") = lowest_affinity_level;
+
+ asm("hvc #0"
+ : "=r"(x0)
+ : "r"(x0), "r"(x1), "r"(x2)
+ : "memory");
+
+ return x0;
+}
+
+static void guest_main(uint64_t target_cpu)
+{
+ GUEST_ASSERT(!psci_cpu_on(target_cpu, CPU_ON_ENTRY_ADDR, CPU_ON_CONTEXT_ID));
+ uint64_t target_state;
+
+ do {
+ target_state = psci_affinity_info(target_cpu, 0);
+
+ GUEST_ASSERT((target_state == PSCI_0_2_AFFINITY_LEVEL_ON) ||
+ (target_state == PSCI_0_2_AFFINITY_LEVEL_OFF));
+ } while (target_state != PSCI_0_2_AFFINITY_LEVEL_ON);
+
+ GUEST_DONE();
+}
+
+int main(void)
+{
+ uint64_t target_mpidr, obs_pc, obs_x0;
+ struct kvm_vcpu_init init;
+ struct kvm_vm *vm;
+ struct ucall uc;
+
+ vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR);
+ kvm_vm_elf_load(vm, program_invocation_name);
+ ucall_init(vm, NULL);
+
+ vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
+ init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
+
+ aarch64_vcpu_add_default(vm, VCPU_ID_SOURCE, &init, guest_main);
+
+ /*
+ * make sure the target is already off when executing the test.
+ */
+ init.features[0] |= (1 << KVM_ARM_VCPU_POWER_OFF);
+ aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_main);
+
+ get_reg(vm, VCPU_ID_TARGET, ARM64_SYS_REG(MPIDR_EL1), &target_mpidr);
+ vcpu_args_set(vm, VCPU_ID_SOURCE, 1, target_mpidr & MPIDR_HWID_BITMASK);
+ vcpu_run(vm, VCPU_ID_SOURCE);
+
+ switch (get_ucall(vm, VCPU_ID_SOURCE, &uc)) {
+ case UCALL_DONE:
+ break;
+ case UCALL_ABORT:
+ TEST_FAIL("%s at %s:%ld", (const char *)uc.args[0], __FILE__,
+ uc.args[1]);
+ break;
+ default:
+ TEST_FAIL("Unhandled ucall: %lu", uc.cmd);
+ }
+
+ get_reg(vm, VCPU_ID_TARGET, ARM64_CORE_REG(regs.pc), &obs_pc);
+ get_reg(vm, VCPU_ID_TARGET, ARM64_CORE_REG(regs.regs[0]), &obs_x0);
+
+ TEST_ASSERT(obs_pc == CPU_ON_ENTRY_ADDR,
+ "unexpected target cpu pc: %lx (expected: %lx)",
+ obs_pc, CPU_ON_ENTRY_ADDR);
+ TEST_ASSERT(obs_x0 == CPU_ON_CONTEXT_ID,
+ "unexpected target context id: %lx (expected: %lx)",
+ obs_x0, CPU_ON_CONTEXT_ID);
+
+ kvm_vm_free(vm);
+ return 0;
+}
diff --git a/tools/testing/selftests/kvm/access_tracking_perf_test.c b/tools/testing/selftests/kvm/access_tracking_perf_test.c
index e2baa187a21e..71e277c7c3f3 100644
--- a/tools/testing/selftests/kvm/access_tracking_perf_test.c
+++ b/tools/testing/selftests/kvm/access_tracking_perf_test.c
@@ -222,8 +222,6 @@ static void *vcpu_thread_main(void *arg)
int vcpu_id = vcpu_args->vcpu_id;
int current_iteration = -1;
- vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
-
while (spin_wait_for_next_iteration(&current_iteration)) {
switch (READ_ONCE(iteration_work)) {
case ITERATION_ACCESS_MEMORY:
@@ -333,7 +331,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
pthread_t *vcpu_threads;
int vcpus = params->vcpus;
- vm = perf_test_create_vm(mode, vcpus, params->vcpu_memory_bytes,
+ vm = perf_test_create_vm(mode, vcpus, params->vcpu_memory_bytes, 1,
params->backing_src);
perf_test_setup_vcpus(vm, vcpus, params->vcpu_memory_bytes,
diff --git a/tools/testing/selftests/kvm/demand_paging_test.c b/tools/testing/selftests/kvm/demand_paging_test.c
index b74704305835..e79c1b64977f 100644
--- a/tools/testing/selftests/kvm/demand_paging_test.c
+++ b/tools/testing/selftests/kvm/demand_paging_test.c
@@ -52,7 +52,6 @@ static void *vcpu_worker(void *data)
struct timespec start;
struct timespec ts_diff;
- vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
run = vcpu_state(vm, vcpu_id);
clock_gettime(CLOCK_MONOTONIC, &start);
@@ -293,7 +292,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
int vcpu_id;
int r;
- vm = perf_test_create_vm(mode, nr_vcpus, guest_percpu_mem_size,
+ vm = perf_test_create_vm(mode, nr_vcpus, guest_percpu_mem_size, 1,
p->src_type);
perf_test_args.wr_fract = 1;
diff --git a/tools/testing/selftests/kvm/dirty_log_perf_test.c b/tools/testing/selftests/kvm/dirty_log_perf_test.c
index 80cbd3a748c0..3c30d0045d8d 100644
--- a/tools/testing/selftests/kvm/dirty_log_perf_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_perf_test.c
@@ -44,7 +44,6 @@ static void *vcpu_worker(void *data)
struct perf_test_vcpu_args *vcpu_args = (struct perf_test_vcpu_args *)data;
int vcpu_id = vcpu_args->vcpu_id;
- vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
run = vcpu_state(vm, vcpu_id);
while (!READ_ONCE(host_quit)) {
@@ -94,8 +93,59 @@ struct test_params {
int wr_fract;
bool partition_vcpu_memory_access;
enum vm_mem_backing_src_type backing_src;
+ int slots;
};
+static void toggle_dirty_logging(struct kvm_vm *vm, int slots, bool enable)
+{
+ int i;
+
+ for (i = 0; i < slots; i++) {
+ int slot = PERF_TEST_MEM_SLOT_INDEX + i;
+ int flags = enable ? KVM_MEM_LOG_DIRTY_PAGES : 0;
+
+ vm_mem_region_set_flags(vm, slot, flags);
+ }
+}
+
+static inline void enable_dirty_logging(struct kvm_vm *vm, int slots)
+{
+ toggle_dirty_logging(vm, slots, true);
+}
+
+static inline void disable_dirty_logging(struct kvm_vm *vm, int slots)
+{
+ toggle_dirty_logging(vm, slots, false);
+}
+
+static void get_dirty_log(struct kvm_vm *vm, int slots, unsigned long *bitmap,
+ uint64_t nr_pages)
+{
+ uint64_t slot_pages = nr_pages / slots;
+ int i;
+
+ for (i = 0; i < slots; i++) {
+ int slot = PERF_TEST_MEM_SLOT_INDEX + i;
+ unsigned long *slot_bitmap = bitmap + i * slot_pages;
+
+ kvm_vm_get_dirty_log(vm, slot, slot_bitmap);
+ }
+}
+
+static void clear_dirty_log(struct kvm_vm *vm, int slots, unsigned long *bitmap,
+ uint64_t nr_pages)
+{
+ uint64_t slot_pages = nr_pages / slots;
+ int i;
+
+ for (i = 0; i < slots; i++) {
+ int slot = PERF_TEST_MEM_SLOT_INDEX + i;
+ unsigned long *slot_bitmap = bitmap + i * slot_pages;
+
+ kvm_vm_clear_dirty_log(vm, slot, slot_bitmap, 0, slot_pages);
+ }
+}
+
static void run_test(enum vm_guest_mode mode, void *arg)
{
struct test_params *p = arg;
@@ -114,7 +164,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
struct timespec clear_dirty_log_total = (struct timespec){0};
vm = perf_test_create_vm(mode, nr_vcpus, guest_percpu_mem_size,
- p->backing_src);
+ p->slots, p->backing_src);
perf_test_args.wr_fract = p->wr_fract;
@@ -163,8 +213,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
/* Enable dirty logging */
clock_gettime(CLOCK_MONOTONIC, &start);
- vm_mem_region_set_flags(vm, PERF_TEST_MEM_SLOT_INDEX,
- KVM_MEM_LOG_DIRTY_PAGES);
+ enable_dirty_logging(vm, p->slots);
ts_diff = timespec_elapsed(start);
pr_info("Enabling dirty logging time: %ld.%.9lds\n\n",
ts_diff.tv_sec, ts_diff.tv_nsec);
@@ -190,8 +239,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
iteration, ts_diff.tv_sec, ts_diff.tv_nsec);
clock_gettime(CLOCK_MONOTONIC, &start);
- kvm_vm_get_dirty_log(vm, PERF_TEST_MEM_SLOT_INDEX, bmap);
-
+ get_dirty_log(vm, p->slots, bmap, host_num_pages);
ts_diff = timespec_elapsed(start);
get_dirty_log_total = timespec_add(get_dirty_log_total,
ts_diff);
@@ -200,9 +248,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
if (dirty_log_manual_caps) {
clock_gettime(CLOCK_MONOTONIC, &start);
- kvm_vm_clear_dirty_log(vm, PERF_TEST_MEM_SLOT_INDEX, bmap, 0,
- host_num_pages);
-
+ clear_dirty_log(vm, p->slots, bmap, host_num_pages);
ts_diff = timespec_elapsed(start);
clear_dirty_log_total = timespec_add(clear_dirty_log_total,
ts_diff);
@@ -213,7 +259,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
/* Disable dirty logging */
clock_gettime(CLOCK_MONOTONIC, &start);
- vm_mem_region_set_flags(vm, PERF_TEST_MEM_SLOT_INDEX, 0);
+ disable_dirty_logging(vm, p->slots);
ts_diff = timespec_elapsed(start);
pr_info("Disabling dirty logging time: %ld.%.9lds\n",
ts_diff.tv_sec, ts_diff.tv_nsec);
@@ -244,7 +290,8 @@ static void help(char *name)
{
puts("");
printf("usage: %s [-h] [-i iterations] [-p offset] "
- "[-m mode] [-b vcpu bytes] [-v vcpus] [-o] [-s mem type]\n", name);
+ "[-m mode] [-b vcpu bytes] [-v vcpus] [-o] [-s mem type]"
+ "[-x memslots]\n", name);
puts("");
printf(" -i: specify iteration counts (default: %"PRIu64")\n",
TEST_HOST_LOOP_N);
@@ -263,6 +310,8 @@ static void help(char *name)
" them into a separate region of memory for each vCPU.\n");
printf(" -s: specify the type of memory that should be used to\n"
" back the guest data region.\n\n");
+ printf(" -x: Split the memory region into this number of memslots.\n"
+ " (default: 1)");
backing_src_help();
puts("");
exit(0);
@@ -276,6 +325,7 @@ int main(int argc, char *argv[])
.wr_fract = 1,
.partition_vcpu_memory_access = true,
.backing_src = VM_MEM_SRC_ANONYMOUS,
+ .slots = 1,
};
int opt;
@@ -286,7 +336,7 @@ int main(int argc, char *argv[])
guest_modes_append_default();
- while ((opt = getopt(argc, argv, "hi:p:m:b:f:v:os:")) != -1) {
+ while ((opt = getopt(argc, argv, "hi:p:m:b:f:v:os:x:")) != -1) {
switch (opt) {
case 'i':
p.iterations = atoi(optarg);
@@ -316,6 +366,9 @@ int main(int argc, char *argv[])
case 's':
p.backing_src = parse_backing_src_type(optarg);
break;
+ case 'x':
+ p.slots = atoi(optarg);
+ break;
case 'h':
default:
help(argv[0]);
diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h
index 27dc5c2e56b9..c0273aefa63d 100644
--- a/tools/testing/selftests/kvm/include/aarch64/processor.h
+++ b/tools/testing/selftests/kvm/include/aarch64/processor.h
@@ -17,6 +17,7 @@
#define CPACR_EL1 3, 0, 1, 0, 2
#define TCR_EL1 3, 0, 2, 0, 2
#define MAIR_EL1 3, 0, 10, 2, 0
+#define MPIDR_EL1 3, 0, 0, 0, 5
#define TTBR0_EL1 3, 0, 2, 0, 0
#define SCTLR_EL1 3, 0, 1, 0, 0
#define VBAR_EL1 3, 0, 12, 0, 0
@@ -40,6 +41,8 @@
(0xfful << (4 * 8)) | \
(0xbbul << (5 * 8)))
+#define MPIDR_HWID_BITMASK (0xff00fffffful)
+
static inline void get_reg(struct kvm_vm *vm, uint32_t vcpuid, uint64_t id, uint64_t *addr)
{
struct kvm_one_reg reg;
diff --git a/tools/testing/selftests/kvm/include/perf_test_util.h b/tools/testing/selftests/kvm/include/perf_test_util.h
index 005f2143adeb..df9f1a3a3ffb 100644
--- a/tools/testing/selftests/kvm/include/perf_test_util.h
+++ b/tools/testing/selftests/kvm/include/perf_test_util.h
@@ -44,7 +44,7 @@ extern struct perf_test_args perf_test_args;
extern uint64_t guest_test_phys_mem;
struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
- uint64_t vcpu_memory_bytes,
+ uint64_t vcpu_memory_bytes, int slots,
enum vm_mem_backing_src_type backing_src);
void perf_test_destroy_vm(struct kvm_vm *vm);
void perf_test_setup_vcpus(struct kvm_vm *vm, int vcpus,
diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
index 5906bbc08483..17f65d514915 100644
--- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c
+++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
@@ -109,6 +109,18 @@ static void stats_test(int stats_fd)
/* Check size field, which should not be zero */
TEST_ASSERT(pdesc->size, "KVM descriptor(%s) with size of 0",
pdesc->name);
+ /* Check bucket_size field */
+ switch (pdesc->flags & KVM_STATS_TYPE_MASK) {
+ case KVM_STATS_TYPE_LINEAR_HIST:
+ TEST_ASSERT(pdesc->bucket_size,
+ "Bucket size of Linear Histogram stats (%s) is zero",
+ pdesc->name);
+ break;
+ default:
+ TEST_ASSERT(!pdesc->bucket_size,
+ "Bucket size of stats (%s) is not zero",
+ pdesc->name);
+ }
size_data += pdesc->size * sizeof(*stats_data);
}
/* Check overlap */
diff --git a/tools/testing/selftests/kvm/lib/perf_test_util.c b/tools/testing/selftests/kvm/lib/perf_test_util.c
index b488f4aefea8..0ef80dbdc116 100644
--- a/tools/testing/selftests/kvm/lib/perf_test_util.c
+++ b/tools/testing/selftests/kvm/lib/perf_test_util.c
@@ -50,11 +50,12 @@ static void guest_code(uint32_t vcpu_id)
}
struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
- uint64_t vcpu_memory_bytes,
+ uint64_t vcpu_memory_bytes, int slots,
enum vm_mem_backing_src_type backing_src)
{
struct kvm_vm *vm;
uint64_t guest_num_pages;
+ int i;
pr_info("Testing guest mode: %s\n", vm_guest_mode_string(mode));
@@ -68,6 +69,9 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
"Guest memory size is not host page size aligned.");
TEST_ASSERT(vcpu_memory_bytes % perf_test_args.guest_page_size == 0,
"Guest memory size is not guest page size aligned.");
+ TEST_ASSERT(guest_num_pages % slots == 0,
+ "Guest memory cannot be evenly divided into %d slots.",
+ slots);
vm = vm_create_with_vcpus(mode, vcpus, DEFAULT_GUEST_PHY_PAGES,
(vcpus * vcpu_memory_bytes) / perf_test_args.guest_page_size,
@@ -95,10 +99,16 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
#endif
pr_info("guest physical test memory offset: 0x%lx\n", guest_test_phys_mem);
- /* Add an extra memory slot for testing */
- vm_userspace_mem_region_add(vm, backing_src, guest_test_phys_mem,
- PERF_TEST_MEM_SLOT_INDEX,
- guest_num_pages, 0);
+ /* Add extra memory slots for testing */
+ for (i = 0; i < slots; i++) {
+ uint64_t region_pages = guest_num_pages / slots;
+ vm_paddr_t region_start = guest_test_phys_mem +
+ region_pages * perf_test_args.guest_page_size * i;
+
+ vm_userspace_mem_region_add(vm, backing_src, region_start,
+ PERF_TEST_MEM_SLOT_INDEX + i,
+ region_pages, 0);
+ }
/* Do mapping for the demand paging memory slot */
virt_map(vm, guest_test_virt_mem, guest_test_phys_mem, guest_num_pages);
@@ -140,6 +150,8 @@ void perf_test_setup_vcpus(struct kvm_vm *vm, int vcpus,
vcpu_gpa = guest_test_phys_mem;
}
+ vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
+
pr_debug("Added VCPU %d with test mem gpa [%lx, %lx)\n",
vcpu_id, vcpu_gpa, vcpu_gpa +
(vcpu_args->pages * perf_test_args.guest_page_size));
diff --git a/tools/testing/selftests/kvm/memslot_modification_stress_test.c b/tools/testing/selftests/kvm/memslot_modification_stress_test.c
index 98351ba0933c..4cfcafea9f5a 100644
--- a/tools/testing/selftests/kvm/memslot_modification_stress_test.c
+++ b/tools/testing/selftests/kvm/memslot_modification_stress_test.c
@@ -45,7 +45,6 @@ static void *vcpu_worker(void *data)
struct kvm_vm *vm = perf_test_args.vm;
struct kvm_run *run;
- vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
run = vcpu_state(vm, vcpu_id);
/* Let the guest access its memory until a stop signal is received */
@@ -105,7 +104,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
struct kvm_vm *vm;
int vcpu_id;
- vm = perf_test_create_vm(mode, nr_vcpus, guest_percpu_mem_size,
+ vm = perf_test_create_vm(mode, nr_vcpus, guest_percpu_mem_size, 1,
VM_MEM_SRC_ANONYMOUS);
perf_test_args.wr_fract = 1;
diff --git a/tools/testing/selftests/kvm/x86_64/debug_regs.c b/tools/testing/selftests/kvm/x86_64/debug_regs.c
index 6097a8283377..5f078db1bcba 100644
--- a/tools/testing/selftests/kvm/x86_64/debug_regs.c
+++ b/tools/testing/selftests/kvm/x86_64/debug_regs.c
@@ -8,12 +8,15 @@
#include <string.h>
#include "kvm_util.h"
#include "processor.h"
+#include "apic.h"
#define VCPU_ID 0
#define DR6_BD (1 << 13)
#define DR7_GD (1 << 13)
+#define IRQ_VECTOR 0xAA
+
/* For testing data access debug BP */
uint32_t guest_value;
@@ -21,6 +24,11 @@ extern unsigned char sw_bp, hw_bp, write_data, ss_start, bd_start;
static void guest_code(void)
{
+ /* Create a pending interrupt on current vCPU */
+ x2apic_enable();
+ x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
+ APIC_DM_FIXED | IRQ_VECTOR);
+
/*
* Software BP tests.
*
@@ -38,12 +46,19 @@ static void guest_code(void)
"mov %%rax,%0;\n\t write_data:"
: "=m" (guest_value) : : "rax");
- /* Single step test, covers 2 basic instructions and 2 emulated */
+ /*
+ * Single step test, covers 2 basic instructions and 2 emulated
+ *
+ * Enable interrupts during the single stepping to see that
+ * pending interrupt we raised is not handled due to KVM_GUESTDBG_BLOCKIRQ
+ */
asm volatile("ss_start: "
+ "sti\n\t"
"xor %%eax,%%eax\n\t"
"cpuid\n\t"
"movl $0x1a0,%%ecx\n\t"
"rdmsr\n\t"
+ "cli\n\t"
: : : "eax", "ebx", "ecx", "edx");
/* DR6.BD test */
@@ -72,11 +87,13 @@ int main(void)
uint64_t cmd;
int i;
/* Instruction lengths starting at ss_start */
- int ss_size[4] = {
+ int ss_size[6] = {
+ 1, /* sti*/
2, /* xor */
2, /* cpuid */
5, /* mov */
2, /* rdmsr */
+ 1, /* cli */
};
if (!kvm_check_cap(KVM_CAP_SET_GUEST_DEBUG)) {
@@ -154,7 +171,8 @@ int main(void)
for (i = 0; i < (sizeof(ss_size) / sizeof(ss_size[0])); i++) {
target_rip += ss_size[i];
CLEAR_DEBUG();
- debug.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
+ debug.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP |
+ KVM_GUESTDBG_BLOCKIRQ;
debug.arch.debugreg[7] = 0x00000400;
APPLY_DEBUG();
vcpu_run(vm, VCPU_ID);
diff --git a/tools/testing/selftests/lkdtm/config b/tools/testing/selftests/lkdtm/config
index 013446e87f1f..38edea25631b 100644
--- a/tools/testing/selftests/lkdtm/config
+++ b/tools/testing/selftests/lkdtm/config
@@ -6,3 +6,5 @@ CONFIG_HARDENED_USERCOPY=y
# CONFIG_HARDENED_USERCOPY_FALLBACK is not set
CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
+CONFIG_UBSAN_BOUNDS=y
+CONFIG_UBSAN_TRAP=y
diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt
index 846cfd508d3c..09f7bfa383cc 100644
--- a/tools/testing/selftests/lkdtm/tests.txt
+++ b/tools/testing/selftests/lkdtm/tests.txt
@@ -7,6 +7,7 @@ EXCEPTION
#EXHAUST_STACK Corrupts memory on failure
#CORRUPT_STACK Crashes entire system on success
#CORRUPT_STACK_STRONG Crashes entire system on success
+ARRAY_BOUNDS
CORRUPT_LIST_ADD list_add corruption
CORRUPT_LIST_DEL list_del corruption
STACK_GUARD_PAGE_LEADING
@@ -72,4 +73,6 @@ USERCOPY_KERNEL
STACKLEAK_ERASING OK: the rest of the thread stack is properly erased
CFI_FORWARD_PROTO
FORTIFIED_STRSCPY
+FORTIFIED_OBJECT
+FORTIFIED_SUBOBJECT
PPC_SLB_MULTIHIT Recovered
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 378c0aac5a1a..492b273743b4 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -27,6 +27,7 @@ TEST_PROGS += udpgro_fwd.sh
TEST_PROGS += veth.sh
TEST_PROGS += ioam6.sh
TEST_PROGS += gro.sh
+TEST_PROGS += gre_gso.sh
TEST_PROGS_EXTENDED := in_netns.sh
TEST_GEN_FILES = socket nettest
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any
diff --git a/tools/testing/selftests/net/altnames.sh b/tools/testing/selftests/net/altnames.sh
index 4254ddc3f70b..1ef9e4159bba 100755
--- a/tools/testing/selftests/net/altnames.sh
+++ b/tools/testing/selftests/net/altnames.sh
@@ -45,7 +45,7 @@ altnames_test()
check_err $? "Got unexpected long alternative name from link show JSON"
ip link property del $DUMMY_DEV altname $SHORT_NAME
- check_err $? "Failed to add short alternative name"
+ check_err $? "Failed to delete short alternative name"
ip -j -p link show $SHORT_NAME &>/dev/null
check_fail $? "Unexpected success while trying to do link show with deleted short alternative name"
diff --git a/tools/testing/selftests/net/gre_gso.sh b/tools/testing/selftests/net/gre_gso.sh
new file mode 100755
index 000000000000..facbb0c80443
--- /dev/null
+++ b/tools/testing/selftests/net/gre_gso.sh
@@ -0,0 +1,236 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# This test is for checking GRE GSO.
+
+ret=0
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+# all tests in this script. Can be overridden with -t option
+TESTS="gre_gso"
+
+VERBOSE=0
+PAUSE_ON_FAIL=no
+PAUSE=no
+IP="ip -netns ns1"
+NS_EXEC="ip netns exec ns1"
+TMPFILE=`mktemp`
+PID=
+
+log_test()
+{
+ local rc=$1
+ local expected=$2
+ local msg="$3"
+
+ if [ ${rc} -eq ${expected} ]; then
+ printf " TEST: %-60s [ OK ]\n" "${msg}"
+ nsuccess=$((nsuccess+1))
+ else
+ ret=1
+ nfail=$((nfail+1))
+ printf " TEST: %-60s [FAIL]\n" "${msg}"
+ if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
+ echo
+ echo "hit enter to continue, 'q' to quit"
+ read a
+ [ "$a" = "q" ] && exit 1
+ fi
+ fi
+
+ if [ "${PAUSE}" = "yes" ]; then
+ echo
+ echo "hit enter to continue, 'q' to quit"
+ read a
+ [ "$a" = "q" ] && exit 1
+ fi
+}
+
+setup()
+{
+ set -e
+ ip netns add ns1
+ ip netns set ns1 auto
+ $IP link set dev lo up
+
+ ip link add veth0 type veth peer name veth1
+ ip link set veth0 up
+ ip link set veth1 netns ns1
+ $IP link set veth1 name veth0
+ $IP link set veth0 up
+
+ dd if=/dev/urandom of=$TMPFILE bs=1024 count=2048 &>/dev/null
+ set +e
+}
+
+cleanup()
+{
+ rm -rf $TMPFILE
+ [ -n "$PID" ] && kill $PID
+ ip link del dev gre1 &> /dev/null
+ ip link del dev veth0 &> /dev/null
+ ip netns del ns1
+}
+
+get_linklocal()
+{
+ local dev=$1
+ local ns=$2
+ local addr
+
+ [ -n "$ns" ] && ns="-netns $ns"
+
+ addr=$(ip -6 -br $ns addr show dev ${dev} | \
+ awk '{
+ for (i = 3; i <= NF; ++i) {
+ if ($i ~ /^fe80/)
+ print $i
+ }
+ }'
+ )
+ addr=${addr/\/*}
+
+ [ -z "$addr" ] && return 1
+
+ echo $addr
+
+ return 0
+}
+
+gre_create_tun()
+{
+ local a1=$1
+ local a2=$2
+ local mode
+
+ [[ $a1 =~ ^[0-9.]*$ ]] && mode=gre || mode=ip6gre
+
+ ip tunnel add gre1 mode $mode local $a1 remote $a2 dev veth0
+ ip link set gre1 up
+ $IP tunnel add gre1 mode $mode local $a2 remote $a1 dev veth0
+ $IP link set gre1 up
+}
+
+gre_gst_test_checks()
+{
+ local name=$1
+ local addr=$2
+
+ $NS_EXEC nc -kl $port >/dev/null &
+ PID=$!
+ while ! $NS_EXEC ss -ltn | grep -q $port; do ((i++)); sleep 0.01; done
+
+ cat $TMPFILE | timeout 1 nc $addr $port
+ log_test $? 0 "$name - copy file w/ TSO"
+
+ ethtool -K veth0 tso off
+
+ cat $TMPFILE | timeout 1 nc $addr $port
+ log_test $? 0 "$name - copy file w/ GSO"
+
+ ethtool -K veth0 tso on
+
+ kill $PID
+ PID=
+}
+
+gre6_gso_test()
+{
+ local port=7777
+
+ setup
+
+ a1=$(get_linklocal veth0)
+ a2=$(get_linklocal veth0 ns1)
+
+ gre_create_tun $a1 $a2
+
+ ip addr add 172.16.2.1/24 dev gre1
+ $IP addr add 172.16.2.2/24 dev gre1
+
+ ip -6 addr add 2001:db8:1::1/64 dev gre1 nodad
+ $IP -6 addr add 2001:db8:1::2/64 dev gre1 nodad
+
+ sleep 2
+
+ gre_gst_test_checks GREv6/v4 172.16.2.2
+ gre_gst_test_checks GREv6/v6 2001:db8:1::2
+
+ cleanup
+}
+
+gre_gso_test()
+{
+ gre6_gso_test
+}
+
+################################################################################
+# usage
+
+usage()
+{
+ cat <<EOF
+usage: ${0##*/} OPTS
+
+ -t <test> Test(s) to run (default: all)
+ (options: $TESTS)
+ -p Pause on fail
+ -P Pause after each test before cleanup
+ -v verbose mode (show commands and output)
+EOF
+}
+
+################################################################################
+# main
+
+while getopts :t:pPhv o
+do
+ case $o in
+ t) TESTS=$OPTARG;;
+ p) PAUSE_ON_FAIL=yes;;
+ P) PAUSE=yes;;
+ v) VERBOSE=$(($VERBOSE + 1));;
+ h) usage; exit 0;;
+ *) usage; exit 1;;
+ esac
+done
+
+PEER_CMD="ip netns exec ${PEER_NS}"
+
+# make sure we don't pause twice
+[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
+
+if [ "$(id -u)" -ne 0 ];then
+ echo "SKIP: Need root privileges"
+ exit $ksft_skip;
+fi
+
+if [ ! -x "$(command -v ip)" ]; then
+ echo "SKIP: Could not run test without ip tool"
+ exit $ksft_skip
+fi
+
+if [ ! -x "$(command -v nc)" ]; then
+ echo "SKIP: Could not run test without nc tool"
+ exit $ksft_skip
+fi
+
+# start clean
+cleanup &> /dev/null
+
+for t in $TESTS
+do
+ case $t in
+ gre_gso) gre_gso_test;;
+
+ help) echo "Test names: $TESTS"; exit 0;;
+ esac
+done
+
+if [ "$TESTS" != "none" ]; then
+ printf "\nTests passed: %3d\n" ${nsuccess}
+ printf "Tests failed: %3d\n" ${nfail}
+fi
+
+exit $ret
diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh
index fd63ebfe9a2b..910d8126af8f 100755
--- a/tools/testing/selftests/net/mptcp/simult_flows.sh
+++ b/tools/testing/selftests/net/mptcp/simult_flows.sh
@@ -22,8 +22,8 @@ usage() {
cleanup()
{
- rm -f "$cin" "$cout"
- rm -f "$sin" "$sout"
+ rm -f "$cout" "$sout"
+ rm -f "$large" "$small"
rm -f "$capout"
local netns
diff --git a/tools/testing/selftests/openat2/openat2_test.c b/tools/testing/selftests/openat2/openat2_test.c
index d7ec1e7da0d0..1bddbe934204 100644
--- a/tools/testing/selftests/openat2/openat2_test.c
+++ b/tools/testing/selftests/openat2/openat2_test.c
@@ -22,7 +22,11 @@
* XXX: This is wrong on {mips, parisc, powerpc, sparc}.
*/
#undef O_LARGEFILE
+#ifdef __aarch64__
+#define O_LARGEFILE 0x20000
+#else
#define O_LARGEFILE 0x8000
+#endif
struct open_how_ext {
struct open_how inner;
diff --git a/tools/testing/selftests/powerpc/primitives/asm/extable.h b/tools/testing/selftests/powerpc/primitives/asm/extable.h
new file mode 120000
index 000000000000..6385f059a951
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/asm/extable.h
@@ -0,0 +1 @@
+../../../../../../arch/powerpc/include/asm/extable.h \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c
index 82f7bdc2e5e6..67ca297c5cca 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c
@@ -57,7 +57,7 @@ trans:
: [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2),
[sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "b" (&a),
[flt_2] "b" (&b), [cptr1] "b" (&cptr[1])
- : "memory", "r7", "r8", "r9", "r10",
+ : "memory", "r0", "r7", "r8", "r9", "r10",
"r11", "r12", "r13", "r14", "r15", "r16",
"r17", "r18", "r19", "r20", "r21", "r22",
"r23", "r24", "r25", "r26", "r27", "r28",
@@ -113,6 +113,7 @@ int ptrace_tm_gpr(void)
int ret, status;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
pid = fork();
if (pid < 0) {
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c
index ad65be6e8e85..6f2bce1b6c5d 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c
@@ -65,7 +65,7 @@ trans:
: [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2), [gpr_4]"i"(GPR_4),
[sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "b" (&a),
[flt_4] "b" (&d)
- : "memory", "r5", "r6", "r7",
+ : "memory", "r0", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
@@ -119,6 +119,7 @@ int ptrace_tm_spd_gpr(void)
int ret, status;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
pid = fork();
if (pid < 0) {
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c
index 2ecfa1158e2b..e112a34fbe59 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c
@@ -129,6 +129,7 @@ int ptrace_tm_spd_tar(void)
int ret, status;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
pid = fork();
if (pid == 0)
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
index 6f7fb51f0809..40133d49fe39 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
@@ -129,6 +129,7 @@ int ptrace_tm_spd_vsx(void)
int ret, status, i;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
for (i = 0; i < 128; i++) {
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
index 068bfed2e606..880ba6a29a48 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
@@ -114,6 +114,7 @@ int ptrace_tm_spr(void)
int ret, status;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
pid = fork();
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c
index 46ef378a15ec..d0db6df0f0ea 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c
@@ -117,6 +117,7 @@ int ptrace_tm_tar(void)
int ret, status;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
pid = fork();
if (pid == 0)
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
index 70ca01234f79..4f05ce4fd282 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c
@@ -113,6 +113,7 @@ int ptrace_tm_vsx(void)
int ret, status, i;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
for (i = 0; i < 128; i++) {
diff --git a/tools/testing/selftests/powerpc/signal/signal_tm.c b/tools/testing/selftests/powerpc/signal/signal_tm.c
index 5bf2224ef7f2..c9cf66a3daa2 100644
--- a/tools/testing/selftests/powerpc/signal/signal_tm.c
+++ b/tools/testing/selftests/powerpc/signal/signal_tm.c
@@ -56,6 +56,7 @@ static int test_signal_tm()
}
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
for (i = 0; i < MAX_ATTEMPT; i++) {
/*
diff --git a/tools/testing/selftests/powerpc/tm/tm-exec.c b/tools/testing/selftests/powerpc/tm/tm-exec.c
index 260cfdb97d23..c59919d6710d 100644
--- a/tools/testing/selftests/powerpc/tm/tm-exec.c
+++ b/tools/testing/selftests/powerpc/tm/tm-exec.c
@@ -27,6 +27,7 @@ static char *path;
static int test_exec(void)
{
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
asm __volatile__(
"tbegin.;"
diff --git a/tools/testing/selftests/powerpc/tm/tm-fork.c b/tools/testing/selftests/powerpc/tm/tm-fork.c
index 6efa5a685a77..c27b935f0e9f 100644
--- a/tools/testing/selftests/powerpc/tm/tm-fork.c
+++ b/tools/testing/selftests/powerpc/tm/tm-fork.c
@@ -21,6 +21,7 @@
int test_fork(void)
{
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
asm __volatile__(
"tbegin.;"
diff --git a/tools/testing/selftests/powerpc/tm/tm-poison.c b/tools/testing/selftests/powerpc/tm/tm-poison.c
index 29e5f26af7b9..a7bbf034b5bb 100644
--- a/tools/testing/selftests/powerpc/tm/tm-poison.c
+++ b/tools/testing/selftests/powerpc/tm/tm-poison.c
@@ -20,7 +20,6 @@
#include <sched.h>
#include <sys/types.h>
#include <signal.h>
-#include <inttypes.h>
#include "tm.h"
@@ -34,6 +33,7 @@ int tm_poison_test(void)
bool fail_vr = false;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
cpu = pick_online_cpu();
FAIL_IF(cpu < 0);
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index 4cdb83964bb3..85c940ae6ff8 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -40,6 +40,7 @@ int test_body(void)
uint64_t rv, dscr1 = 1, dscr2, texasr;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
printf("Check DSCR TM context switch: ");
fflush(stdout);
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
index 254f912ad611..657d755b2905 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
@@ -79,6 +79,7 @@ static int tm_signal_context_chk_fpu()
pid_t pid = getpid();
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
act.sa_sigaction = signal_usr1;
sigemptyset(&act.sa_mask);
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
index 0cc680f61828..400fa70ca71e 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
@@ -81,6 +81,7 @@ static int tm_signal_context_chk_gpr()
pid_t pid = getpid();
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
act.sa_sigaction = signal_usr1;
sigemptyset(&act.sa_mask);
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
index b6d52730a0d8..d628fd302b28 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
@@ -104,6 +104,7 @@ static int tm_signal_context_chk()
pid_t pid = getpid();
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
act.sa_sigaction = signal_usr1;
sigemptyset(&act.sa_mask);
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
index 8e25e2072ecd..9bd869245bad 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
@@ -153,6 +153,7 @@ static int tm_signal_context_chk()
pid_t pid = getpid();
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
act.sa_sigaction = signal_usr1;
sigemptyset(&act.sa_mask);
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c b/tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c
index 5908bc6abe60..0b84c9208d62 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c
@@ -226,6 +226,7 @@ int tm_signal_pagefault(void)
stack_t ss;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
SKIP_IF(!have_userfaultfd());
setup_uf_mem();
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-sigreturn-nt.c b/tools/testing/selftests/powerpc/tm/tm-signal-sigreturn-nt.c
index 07c388147b75..06b801906f27 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-sigreturn-nt.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-sigreturn-nt.c
@@ -32,6 +32,7 @@ int tm_signal_sigreturn_nt(void)
struct sigaction trap_sa;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
trap_sa.sa_flags = SA_SIGINFO;
trap_sa.sa_sigaction = trap_signal_handler;
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
index cdcf8c5bbbc7..68807aac8dd3 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
@@ -35,6 +35,7 @@ int tm_signal_stack()
int pid;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
pid = fork();
if (pid < 0)
diff --git a/tools/testing/selftests/powerpc/tm/tm-sigreturn.c b/tools/testing/selftests/powerpc/tm/tm-sigreturn.c
index 9a6017a1d769..ffe4e5515f33 100644
--- a/tools/testing/selftests/powerpc/tm/tm-sigreturn.c
+++ b/tools/testing/selftests/powerpc/tm/tm-sigreturn.c
@@ -55,6 +55,7 @@ int tm_sigreturn(void)
uint64_t ret = 0;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
SKIP_IF(!is_ppc64le());
memset(&sa, 0, sizeof(sa));
diff --git a/tools/testing/selftests/powerpc/tm/tm-syscall.c b/tools/testing/selftests/powerpc/tm/tm-syscall.c
index becb8207b432..467a6b3134b2 100644
--- a/tools/testing/selftests/powerpc/tm/tm-syscall.c
+++ b/tools/testing/selftests/powerpc/tm/tm-syscall.c
@@ -25,7 +25,6 @@ extern int getppid_tm_suspended(void);
unsigned retries = 0;
#define TEST_DURATION 10 /* seconds */
-#define TM_RETRIES 100
pid_t getppid_tm(bool suspend)
{
@@ -67,6 +66,7 @@ int tm_syscall(void)
struct timeval end, now;
SKIP_IF(!have_htm_nosc());
+ SKIP_IF(htm_is_synthetic());
setbuf(stdout, NULL);
diff --git a/tools/testing/selftests/powerpc/tm/tm-tar.c b/tools/testing/selftests/powerpc/tm/tm-tar.c
index 03be8c47292b..f2a9137f3c1e 100644
--- a/tools/testing/selftests/powerpc/tm/tm-tar.c
+++ b/tools/testing/selftests/powerpc/tm/tm-tar.c
@@ -26,6 +26,7 @@ int test_tar(void)
int i;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
SKIP_IF(!is_ppc64le());
for (i = 0; i < num_loops; i++)
diff --git a/tools/testing/selftests/powerpc/tm/tm-tmspr.c b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
index 794d574db784..dd5ddffa28b7 100644
--- a/tools/testing/selftests/powerpc/tm/tm-tmspr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
@@ -96,6 +96,7 @@ int test_tmspr()
unsigned long i;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
/* To cause some context switching */
thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
diff --git a/tools/testing/selftests/powerpc/tm/tm-trap.c b/tools/testing/selftests/powerpc/tm/tm-trap.c
index 11521077f915..97cb74768e30 100644
--- a/tools/testing/selftests/powerpc/tm/tm-trap.c
+++ b/tools/testing/selftests/powerpc/tm/tm-trap.c
@@ -255,6 +255,7 @@ int tm_trap_test(void)
struct sigaction trap_sa;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
trap_sa.sa_flags = SA_SIGINFO;
trap_sa.sa_sigaction = trap_signal_handler;
diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
index a1348a5f721a..6bf1b65b020d 100644
--- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c
+++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c
@@ -344,6 +344,7 @@ int tm_unavailable_test(void)
cpu_set_t cpuset;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
cpu = pick_online_cpu();
FAIL_IF(cpu < 0);
diff --git a/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c b/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
index 9ef37a9836ac..34364ed2b6b7 100644
--- a/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
+++ b/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
@@ -91,6 +91,7 @@ int tm_vmx_unavail_test()
pthread_t *thread;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
passed = 1;
diff --git a/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c b/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c
index c1e788a6df47..1640e7ead69b 100644
--- a/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c
+++ b/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c
@@ -46,6 +46,7 @@ int test_vmxcopy()
uint64_t aborted = 0;
SKIP_IF(!have_htm());
+ SKIP_IF(htm_is_synthetic());
SKIP_IF(!is_ppc64le());
fd = mkstemp(tmpfile);
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h
index c5a1e5c163fc..c03c6e778876 100644
--- a/tools/testing/selftests/powerpc/tm/tm.h
+++ b/tools/testing/selftests/powerpc/tm/tm.h
@@ -10,6 +10,9 @@
#include <asm/tm.h>
#include "utils.h"
+#include "reg.h"
+
+#define TM_RETRIES 100
static inline bool have_htm(void)
{
@@ -31,6 +34,39 @@ static inline bool have_htm_nosc(void)
#endif
}
+/*
+ * Transactional Memory was removed in ISA 3.1. A synthetic TM implementation
+ * is provided on P10 for threads running in P8/P9 compatibility mode. The
+ * synthetic implementation immediately fails after tbegin. This failure sets
+ * Bit 7 (Failure Persistent) and Bit 15 (Implementation-specific).
+ */
+static inline bool htm_is_synthetic(void)
+{
+ int i;
+
+ /*
+ * Per the ISA, the Failure Persistent bit may be incorrect. Try a few
+ * times in case we got an Implementation-specific failure on a non ISA
+ * v3.1 system. On these systems the Implementation-specific failure
+ * should not be persistent.
+ */
+ for (i = 0; i < TM_RETRIES; i++) {
+ asm volatile(
+ "tbegin.;"
+ "beq 1f;"
+ "tend.;"
+ "1:"
+ :
+ :
+ : "memory");
+
+ if ((__builtin_get_texasr() & (TEXASR_FP | TEXASR_IC)) !=
+ (TEXASR_FP | TEXASR_IC))
+ break;
+ }
+ return i == TM_RETRIES;
+}
+
static inline long failure_code(void)
{
return __builtin_get_texasru() >> 24;
diff --git a/tools/testing/selftests/safesetid/safesetid-test.c b/tools/testing/selftests/safesetid/safesetid-test.c
index 0c4d50644c13..4b809c93ba36 100644
--- a/tools/testing/selftests/safesetid/safesetid-test.c
+++ b/tools/testing/selftests/safesetid/safesetid-test.c
@@ -152,7 +152,7 @@ static void write_policies(void)
fd = open(add_whitelist_policy_file, O_WRONLY);
if (fd < 0)
- die("cant open add_whitelist_policy file\n");
+ die("can't open add_whitelist_policy file\n");
written = write(fd, policy_str, strlen(policy_str));
if (written != strlen(policy_str)) {
if (written >= 0) {
diff --git a/tools/testing/selftests/sched/cs_prctl_test.c b/tools/testing/selftests/sched/cs_prctl_test.c
index 63fe6521c56d..7db9cf822dc7 100644
--- a/tools/testing/selftests/sched/cs_prctl_test.c
+++ b/tools/testing/selftests/sched/cs_prctl_test.c
@@ -25,8 +25,6 @@
#include <sys/types.h>
#include <sched.h>
#include <sys/prctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
diff --git a/tools/testing/selftests/sync/config b/tools/testing/selftests/sync/config
index 1ab7e8130db2..47ff5afc3727 100644
--- a/tools/testing/selftests/sync/config
+++ b/tools/testing/selftests/sync/config
@@ -1,4 +1,3 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
-CONFIG_SYNC=y
CONFIG_SW_SYNC=y
diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore
index f0fd80ef17df..b02eac613fdd 100644
--- a/tools/testing/selftests/vm/.gitignore
+++ b/tools/testing/selftests/vm/.gitignore
@@ -27,3 +27,4 @@ hmm-tests
memfd_secret
local_config.*
split_huge_page_test
+ksm_tests
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index 521243770f26..d9605bd10f2d 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -45,6 +45,7 @@ TEST_GEN_FILES += thuge-gen
TEST_GEN_FILES += transhuge-stress
TEST_GEN_FILES += userfaultfd
TEST_GEN_FILES += split_huge_page_test
+TEST_GEN_FILES += ksm_tests
ifeq ($(MACHINE),x86_64)
CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_32bit_program.c -m32)
@@ -145,6 +146,8 @@ $(OUTPUT)/hmm-tests: local_config.h
# HMM_EXTRA_LIBS may get set in local_config.mk, or it may be left empty.
$(OUTPUT)/hmm-tests: LDLIBS += $(HMM_EXTRA_LIBS)
+$(OUTPUT)/ksm_tests: LDLIBS += -lnuma
+
local_config.mk local_config.h: check_config.sh
/bin/sh ./check_config.sh $(CC)
diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
index 18d33684faad..fe8fcfb334e0 100644
--- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
@@ -1,11 +1,14 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
set -e
if [[ $(id -u) -ne 0 ]]; then
echo "This test must be run as root. Skipping..."
- exit 0
+ exit $ksft_skip
fi
fault_limit_file=limit_in_bytes
diff --git a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
index d11d1febccc3..4a9a3afe9fd4 100644
--- a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
+++ b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
@@ -1,11 +1,14 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
set -e
if [[ $(id -u) -ne 0 ]]; then
echo "This test must be run as root. Skipping..."
- exit 0
+ exit $ksft_skip
fi
usage_file=usage_in_bytes
diff --git a/tools/testing/selftests/vm/ksm_tests.c b/tools/testing/selftests/vm/ksm_tests.c
new file mode 100644
index 000000000000..b61dcdb44c5b
--- /dev/null
+++ b/tools/testing/selftests/vm/ksm_tests.c
@@ -0,0 +1,662 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <sys/mman.h>
+#include <stdbool.h>
+#include <time.h>
+#include <string.h>
+#include <numa.h>
+
+#include "../kselftest.h"
+#include "../../../../include/vdso/time64.h"
+
+#define KSM_SYSFS_PATH "/sys/kernel/mm/ksm/"
+#define KSM_FP(s) (KSM_SYSFS_PATH s)
+#define KSM_SCAN_LIMIT_SEC_DEFAULT 120
+#define KSM_PAGE_COUNT_DEFAULT 10l
+#define KSM_PROT_STR_DEFAULT "rw"
+#define KSM_USE_ZERO_PAGES_DEFAULT false
+#define KSM_MERGE_ACROSS_NODES_DEFAULT true
+#define MB (1ul << 20)
+
+struct ksm_sysfs {
+ unsigned long max_page_sharing;
+ unsigned long merge_across_nodes;
+ unsigned long pages_to_scan;
+ unsigned long run;
+ unsigned long sleep_millisecs;
+ unsigned long stable_node_chains_prune_millisecs;
+ unsigned long use_zero_pages;
+};
+
+enum ksm_test_name {
+ CHECK_KSM_MERGE,
+ CHECK_KSM_UNMERGE,
+ CHECK_KSM_ZERO_PAGE_MERGE,
+ CHECK_KSM_NUMA_MERGE,
+ KSM_MERGE_TIME,
+ KSM_COW_TIME
+};
+
+static int ksm_write_sysfs(const char *file_path, unsigned long val)
+{
+ FILE *f = fopen(file_path, "w");
+
+ if (!f) {
+ fprintf(stderr, "f %s\n", file_path);
+ perror("fopen");
+ return 1;
+ }
+ if (fprintf(f, "%lu", val) < 0) {
+ perror("fprintf");
+ return 1;
+ }
+ fclose(f);
+
+ return 0;
+}
+
+static int ksm_read_sysfs(const char *file_path, unsigned long *val)
+{
+ FILE *f = fopen(file_path, "r");
+
+ if (!f) {
+ fprintf(stderr, "f %s\n", file_path);
+ perror("fopen");
+ return 1;
+ }
+ if (fscanf(f, "%lu", val) != 1) {
+ perror("fscanf");
+ return 1;
+ }
+ fclose(f);
+
+ return 0;
+}
+
+static int str_to_prot(char *prot_str)
+{
+ int prot = 0;
+
+ if ((strchr(prot_str, 'r')) != NULL)
+ prot |= PROT_READ;
+ if ((strchr(prot_str, 'w')) != NULL)
+ prot |= PROT_WRITE;
+ if ((strchr(prot_str, 'x')) != NULL)
+ prot |= PROT_EXEC;
+
+ return prot;
+}
+
+static void print_help(void)
+{
+ printf("usage: ksm_tests [-h] <test type> [-a prot] [-p page_count] [-l timeout]\n"
+ "[-z use_zero_pages] [-m merge_across_nodes] [-s size]\n");
+
+ printf("Supported <test type>:\n"
+ " -M (page merging)\n"
+ " -Z (zero pages merging)\n"
+ " -N (merging of pages in different NUMA nodes)\n"
+ " -U (page unmerging)\n"
+ " -P evaluate merging time and speed.\n"
+ " For this test, the size of duplicated memory area (in MiB)\n"
+ " must be provided using -s option\n"
+ " -C evaluate the time required to break COW of merged pages.\n\n");
+
+ printf(" -a: specify the access protections of pages.\n"
+ " <prot> must be of the form [rwx].\n"
+ " Default: %s\n", KSM_PROT_STR_DEFAULT);
+ printf(" -p: specify the number of pages to test.\n"
+ " Default: %ld\n", KSM_PAGE_COUNT_DEFAULT);
+ printf(" -l: limit the maximum running time (in seconds) for a test.\n"
+ " Default: %d seconds\n", KSM_SCAN_LIMIT_SEC_DEFAULT);
+ printf(" -z: change use_zero_pages tunable\n"
+ " Default: %d\n", KSM_USE_ZERO_PAGES_DEFAULT);
+ printf(" -m: change merge_across_nodes tunable\n"
+ " Default: %d\n", KSM_MERGE_ACROSS_NODES_DEFAULT);
+ printf(" -s: the size of duplicated memory area (in MiB)\n");
+
+ exit(0);
+}
+
+static void *allocate_memory(void *ptr, int prot, int mapping, char data, size_t map_size)
+{
+ void *map_ptr = mmap(ptr, map_size, PROT_WRITE, mapping, -1, 0);
+
+ if (!map_ptr) {
+ perror("mmap");
+ return NULL;
+ }
+ memset(map_ptr, data, map_size);
+ if (mprotect(map_ptr, map_size, prot)) {
+ perror("mprotect");
+ munmap(map_ptr, map_size);
+ return NULL;
+ }
+
+ return map_ptr;
+}
+
+static int ksm_do_scan(int scan_count, struct timespec start_time, int timeout)
+{
+ struct timespec cur_time;
+ unsigned long cur_scan, init_scan;
+
+ if (ksm_read_sysfs(KSM_FP("full_scans"), &init_scan))
+ return 1;
+ cur_scan = init_scan;
+
+ while (cur_scan < init_scan + scan_count) {
+ if (ksm_read_sysfs(KSM_FP("full_scans"), &cur_scan))
+ return 1;
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &cur_time)) {
+ perror("clock_gettime");
+ return 1;
+ }
+ if ((cur_time.tv_sec - start_time.tv_sec) > timeout) {
+ printf("Scan time limit exceeded\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int ksm_merge_pages(void *addr, size_t size, struct timespec start_time, int timeout)
+{
+ if (madvise(addr, size, MADV_MERGEABLE)) {
+ perror("madvise");
+ return 1;
+ }
+ if (ksm_write_sysfs(KSM_FP("run"), 1))
+ return 1;
+
+ /* Since merging occurs only after 2 scans, make sure to get at least 2 full scans */
+ if (ksm_do_scan(2, start_time, timeout))
+ return 1;
+
+ return 0;
+}
+
+static bool assert_ksm_pages_count(long dupl_page_count)
+{
+ unsigned long max_page_sharing, pages_sharing, pages_shared;
+
+ if (ksm_read_sysfs(KSM_FP("pages_shared"), &pages_shared) ||
+ ksm_read_sysfs(KSM_FP("pages_sharing"), &pages_sharing) ||
+ ksm_read_sysfs(KSM_FP("max_page_sharing"), &max_page_sharing))
+ return false;
+
+ /*
+ * Since there must be at least 2 pages for merging and 1 page can be
+ * shared with the limited number of pages (max_page_sharing), sometimes
+ * there are 'leftover' pages that cannot be merged. For example, if there
+ * are 11 pages and max_page_sharing = 10, then only 10 pages will be
+ * merged and the 11th page won't be affected. As a result, when the number
+ * of duplicate pages is divided by max_page_sharing and the remainder is 1,
+ * pages_shared and pages_sharing values will be equal between dupl_page_count
+ * and dupl_page_count - 1.
+ */
+ if (dupl_page_count % max_page_sharing == 1 || dupl_page_count % max_page_sharing == 0) {
+ if (pages_shared == dupl_page_count / max_page_sharing &&
+ pages_sharing == pages_shared * (max_page_sharing - 1))
+ return true;
+ } else {
+ if (pages_shared == (dupl_page_count / max_page_sharing + 1) &&
+ pages_sharing == dupl_page_count - pages_shared)
+ return true;
+ }
+
+ return false;
+}
+
+static int ksm_save_def(struct ksm_sysfs *ksm_sysfs)
+{
+ if (ksm_read_sysfs(KSM_FP("max_page_sharing"), &ksm_sysfs->max_page_sharing) ||
+ ksm_read_sysfs(KSM_FP("merge_across_nodes"), &ksm_sysfs->merge_across_nodes) ||
+ ksm_read_sysfs(KSM_FP("sleep_millisecs"), &ksm_sysfs->sleep_millisecs) ||
+ ksm_read_sysfs(KSM_FP("pages_to_scan"), &ksm_sysfs->pages_to_scan) ||
+ ksm_read_sysfs(KSM_FP("run"), &ksm_sysfs->run) ||
+ ksm_read_sysfs(KSM_FP("stable_node_chains_prune_millisecs"),
+ &ksm_sysfs->stable_node_chains_prune_millisecs) ||
+ ksm_read_sysfs(KSM_FP("use_zero_pages"), &ksm_sysfs->use_zero_pages))
+ return 1;
+
+ return 0;
+}
+
+static int ksm_restore(struct ksm_sysfs *ksm_sysfs)
+{
+ if (ksm_write_sysfs(KSM_FP("max_page_sharing"), ksm_sysfs->max_page_sharing) ||
+ ksm_write_sysfs(KSM_FP("merge_across_nodes"), ksm_sysfs->merge_across_nodes) ||
+ ksm_write_sysfs(KSM_FP("pages_to_scan"), ksm_sysfs->pages_to_scan) ||
+ ksm_write_sysfs(KSM_FP("run"), ksm_sysfs->run) ||
+ ksm_write_sysfs(KSM_FP("sleep_millisecs"), ksm_sysfs->sleep_millisecs) ||
+ ksm_write_sysfs(KSM_FP("stable_node_chains_prune_millisecs"),
+ ksm_sysfs->stable_node_chains_prune_millisecs) ||
+ ksm_write_sysfs(KSM_FP("use_zero_pages"), ksm_sysfs->use_zero_pages))
+ return 1;
+
+ return 0;
+}
+
+static int check_ksm_merge(int mapping, int prot, long page_count, int timeout, size_t page_size)
+{
+ void *map_ptr;
+ struct timespec start_time;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
+ perror("clock_gettime");
+ return KSFT_FAIL;
+ }
+
+ /* fill pages with the same data and merge them */
+ map_ptr = allocate_memory(NULL, prot, mapping, '*', page_size * page_count);
+ if (!map_ptr)
+ return KSFT_FAIL;
+
+ if (ksm_merge_pages(map_ptr, page_size * page_count, start_time, timeout))
+ goto err_out;
+
+ /* verify that the right number of pages are merged */
+ if (assert_ksm_pages_count(page_count)) {
+ printf("OK\n");
+ munmap(map_ptr, page_size * page_count);
+ return KSFT_PASS;
+ }
+
+err_out:
+ printf("Not OK\n");
+ munmap(map_ptr, page_size * page_count);
+ return KSFT_FAIL;
+}
+
+static int check_ksm_unmerge(int mapping, int prot, int timeout, size_t page_size)
+{
+ void *map_ptr;
+ struct timespec start_time;
+ int page_count = 2;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
+ perror("clock_gettime");
+ return KSFT_FAIL;
+ }
+
+ /* fill pages with the same data and merge them */
+ map_ptr = allocate_memory(NULL, prot, mapping, '*', page_size * page_count);
+ if (!map_ptr)
+ return KSFT_FAIL;
+
+ if (ksm_merge_pages(map_ptr, page_size * page_count, start_time, timeout))
+ goto err_out;
+
+ /* change 1 byte in each of the 2 pages -- KSM must automatically unmerge them */
+ memset(map_ptr, '-', 1);
+ memset(map_ptr + page_size, '+', 1);
+
+ /* get at least 1 scan, so KSM can detect that the pages were modified */
+ if (ksm_do_scan(1, start_time, timeout))
+ goto err_out;
+
+ /* check that unmerging was successful and 0 pages are currently merged */
+ if (assert_ksm_pages_count(0)) {
+ printf("OK\n");
+ munmap(map_ptr, page_size * page_count);
+ return KSFT_PASS;
+ }
+
+err_out:
+ printf("Not OK\n");
+ munmap(map_ptr, page_size * page_count);
+ return KSFT_FAIL;
+}
+
+static int check_ksm_zero_page_merge(int mapping, int prot, long page_count, int timeout,
+ bool use_zero_pages, size_t page_size)
+{
+ void *map_ptr;
+ struct timespec start_time;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
+ perror("clock_gettime");
+ return KSFT_FAIL;
+ }
+
+ if (ksm_write_sysfs(KSM_FP("use_zero_pages"), use_zero_pages))
+ return KSFT_FAIL;
+
+ /* fill pages with zero and try to merge them */
+ map_ptr = allocate_memory(NULL, prot, mapping, 0, page_size * page_count);
+ if (!map_ptr)
+ return KSFT_FAIL;
+
+ if (ksm_merge_pages(map_ptr, page_size * page_count, start_time, timeout))
+ goto err_out;
+
+ /*
+ * verify that the right number of pages are merged:
+ * 1) if use_zero_pages is set to 1, empty pages are merged
+ * with the kernel zero page instead of with each other;
+ * 2) if use_zero_pages is set to 0, empty pages are not treated specially
+ * and merged as usual.
+ */
+ if (use_zero_pages && !assert_ksm_pages_count(0))
+ goto err_out;
+ else if (!use_zero_pages && !assert_ksm_pages_count(page_count))
+ goto err_out;
+
+ printf("OK\n");
+ munmap(map_ptr, page_size * page_count);
+ return KSFT_PASS;
+
+err_out:
+ printf("Not OK\n");
+ munmap(map_ptr, page_size * page_count);
+ return KSFT_FAIL;
+}
+
+static int check_ksm_numa_merge(int mapping, int prot, int timeout, bool merge_across_nodes,
+ size_t page_size)
+{
+ void *numa1_map_ptr, *numa2_map_ptr;
+ struct timespec start_time;
+ int page_count = 2;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
+ perror("clock_gettime");
+ return KSFT_FAIL;
+ }
+
+ if (numa_available() < 0) {
+ perror("NUMA support not enabled");
+ return KSFT_SKIP;
+ }
+ if (numa_max_node() < 1) {
+ printf("At least 2 NUMA nodes must be available\n");
+ return KSFT_SKIP;
+ }
+ if (ksm_write_sysfs(KSM_FP("merge_across_nodes"), merge_across_nodes))
+ return KSFT_FAIL;
+
+ /* allocate 2 pages in 2 different NUMA nodes and fill them with the same data */
+ numa1_map_ptr = numa_alloc_onnode(page_size, 0);
+ numa2_map_ptr = numa_alloc_onnode(page_size, 1);
+ if (!numa1_map_ptr || !numa2_map_ptr) {
+ perror("numa_alloc_onnode");
+ return KSFT_FAIL;
+ }
+
+ memset(numa1_map_ptr, '*', page_size);
+ memset(numa2_map_ptr, '*', page_size);
+
+ /* try to merge the pages */
+ if (ksm_merge_pages(numa1_map_ptr, page_size, start_time, timeout) ||
+ ksm_merge_pages(numa2_map_ptr, page_size, start_time, timeout))
+ goto err_out;
+
+ /*
+ * verify that the right number of pages are merged:
+ * 1) if merge_across_nodes was enabled, 2 duplicate pages will be merged;
+ * 2) if merge_across_nodes = 0, there must be 0 merged pages, since there is
+ * only 1 unique page in each node and they can't be shared.
+ */
+ if (merge_across_nodes && !assert_ksm_pages_count(page_count))
+ goto err_out;
+ else if (!merge_across_nodes && !assert_ksm_pages_count(0))
+ goto err_out;
+
+ numa_free(numa1_map_ptr, page_size);
+ numa_free(numa2_map_ptr, page_size);
+ printf("OK\n");
+ return KSFT_PASS;
+
+err_out:
+ numa_free(numa1_map_ptr, page_size);
+ numa_free(numa2_map_ptr, page_size);
+ printf("Not OK\n");
+ return KSFT_FAIL;
+}
+
+static int ksm_merge_time(int mapping, int prot, int timeout, size_t map_size)
+{
+ void *map_ptr;
+ struct timespec start_time, end_time;
+ unsigned long scan_time_ns;
+
+ map_size *= MB;
+
+ map_ptr = allocate_memory(NULL, prot, mapping, '*', map_size);
+ if (!map_ptr)
+ return KSFT_FAIL;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
+ perror("clock_gettime");
+ goto err_out;
+ }
+ if (ksm_merge_pages(map_ptr, map_size, start_time, timeout))
+ goto err_out;
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
+ perror("clock_gettime");
+ goto err_out;
+ }
+
+ scan_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
+ (end_time.tv_nsec - start_time.tv_nsec);
+
+ printf("Total size: %lu MiB\n", map_size / MB);
+ printf("Total time: %ld.%09ld s\n", scan_time_ns / NSEC_PER_SEC,
+ scan_time_ns % NSEC_PER_SEC);
+ printf("Average speed: %.3f MiB/s\n", (map_size / MB) /
+ ((double)scan_time_ns / NSEC_PER_SEC));
+
+ munmap(map_ptr, map_size);
+ return KSFT_PASS;
+
+err_out:
+ printf("Not OK\n");
+ munmap(map_ptr, map_size);
+ return KSFT_FAIL;
+}
+
+static int ksm_cow_time(int mapping, int prot, int timeout, size_t page_size)
+{
+ void *map_ptr;
+ struct timespec start_time, end_time;
+ unsigned long cow_time_ns;
+
+ /* page_count must be less than 2*page_size */
+ size_t page_count = 4000;
+
+ map_ptr = allocate_memory(NULL, prot, mapping, '*', page_size * page_count);
+ if (!map_ptr)
+ return KSFT_FAIL;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
+ perror("clock_gettime");
+ return KSFT_FAIL;
+ }
+ for (size_t i = 0; i < page_count - 1; i = i + 2)
+ memset(map_ptr + page_size * i, '-', 1);
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
+ perror("clock_gettime");
+ return KSFT_FAIL;
+ }
+
+ cow_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
+ (end_time.tv_nsec - start_time.tv_nsec);
+
+ printf("Total size: %lu MiB\n\n", (page_size * page_count) / MB);
+ printf("Not merged pages:\n");
+ printf("Total time: %ld.%09ld s\n", cow_time_ns / NSEC_PER_SEC,
+ cow_time_ns % NSEC_PER_SEC);
+ printf("Average speed: %.3f MiB/s\n\n", ((page_size * (page_count / 2)) / MB) /
+ ((double)cow_time_ns / NSEC_PER_SEC));
+
+ /* Create 2000 pairs of duplicate pages */
+ for (size_t i = 0; i < page_count - 1; i = i + 2) {
+ memset(map_ptr + page_size * i, '+', i / 2 + 1);
+ memset(map_ptr + page_size * (i + 1), '+', i / 2 + 1);
+ }
+ if (ksm_merge_pages(map_ptr, page_size * page_count, start_time, timeout))
+ goto err_out;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
+ perror("clock_gettime");
+ goto err_out;
+ }
+ for (size_t i = 0; i < page_count - 1; i = i + 2)
+ memset(map_ptr + page_size * i, '-', 1);
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
+ perror("clock_gettime");
+ goto err_out;
+ }
+
+ cow_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
+ (end_time.tv_nsec - start_time.tv_nsec);
+
+ printf("Merged pages:\n");
+ printf("Total time: %ld.%09ld s\n", cow_time_ns / NSEC_PER_SEC,
+ cow_time_ns % NSEC_PER_SEC);
+ printf("Average speed: %.3f MiB/s\n", ((page_size * (page_count / 2)) / MB) /
+ ((double)cow_time_ns / NSEC_PER_SEC));
+
+ munmap(map_ptr, page_size * page_count);
+ return KSFT_PASS;
+
+err_out:
+ printf("Not OK\n");
+ munmap(map_ptr, page_size * page_count);
+ return KSFT_FAIL;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret, opt;
+ int prot = 0;
+ int ksm_scan_limit_sec = KSM_SCAN_LIMIT_SEC_DEFAULT;
+ long page_count = KSM_PAGE_COUNT_DEFAULT;
+ size_t page_size = sysconf(_SC_PAGESIZE);
+ struct ksm_sysfs ksm_sysfs_old;
+ int test_name = CHECK_KSM_MERGE;
+ bool use_zero_pages = KSM_USE_ZERO_PAGES_DEFAULT;
+ bool merge_across_nodes = KSM_MERGE_ACROSS_NODES_DEFAULT;
+ long size_MB = 0;
+
+ while ((opt = getopt(argc, argv, "ha:p:l:z:m:s:MUZNPC")) != -1) {
+ switch (opt) {
+ case 'a':
+ prot = str_to_prot(optarg);
+ break;
+ case 'p':
+ page_count = atol(optarg);
+ if (page_count <= 0) {
+ printf("The number of pages must be greater than 0\n");
+ return KSFT_FAIL;
+ }
+ break;
+ case 'l':
+ ksm_scan_limit_sec = atoi(optarg);
+ if (ksm_scan_limit_sec <= 0) {
+ printf("Timeout value must be greater than 0\n");
+ return KSFT_FAIL;
+ }
+ break;
+ case 'h':
+ print_help();
+ break;
+ case 'z':
+ if (strcmp(optarg, "0") == 0)
+ use_zero_pages = 0;
+ else
+ use_zero_pages = 1;
+ break;
+ case 'm':
+ if (strcmp(optarg, "0") == 0)
+ merge_across_nodes = 0;
+ else
+ merge_across_nodes = 1;
+ break;
+ case 's':
+ size_MB = atoi(optarg);
+ if (size_MB <= 0) {
+ printf("Size must be greater than 0\n");
+ return KSFT_FAIL;
+ }
+ case 'M':
+ break;
+ case 'U':
+ test_name = CHECK_KSM_UNMERGE;
+ break;
+ case 'Z':
+ test_name = CHECK_KSM_ZERO_PAGE_MERGE;
+ break;
+ case 'N':
+ test_name = CHECK_KSM_NUMA_MERGE;
+ break;
+ case 'P':
+ test_name = KSM_MERGE_TIME;
+ break;
+ case 'C':
+ test_name = KSM_COW_TIME;
+ break;
+ default:
+ return KSFT_FAIL;
+ }
+ }
+
+ if (prot == 0)
+ prot = str_to_prot(KSM_PROT_STR_DEFAULT);
+
+ if (access(KSM_SYSFS_PATH, F_OK)) {
+ printf("Config KSM not enabled\n");
+ return KSFT_SKIP;
+ }
+
+ if (ksm_save_def(&ksm_sysfs_old)) {
+ printf("Cannot save default tunables\n");
+ return KSFT_FAIL;
+ }
+
+ if (ksm_write_sysfs(KSM_FP("run"), 2) ||
+ ksm_write_sysfs(KSM_FP("sleep_millisecs"), 0) ||
+ ksm_write_sysfs(KSM_FP("merge_across_nodes"), 1) ||
+ ksm_write_sysfs(KSM_FP("pages_to_scan"), page_count))
+ return KSFT_FAIL;
+
+ switch (test_name) {
+ case CHECK_KSM_MERGE:
+ ret = check_ksm_merge(MAP_PRIVATE | MAP_ANONYMOUS, prot, page_count,
+ ksm_scan_limit_sec, page_size);
+ break;
+ case CHECK_KSM_UNMERGE:
+ ret = check_ksm_unmerge(MAP_PRIVATE | MAP_ANONYMOUS, prot, ksm_scan_limit_sec,
+ page_size);
+ break;
+ case CHECK_KSM_ZERO_PAGE_MERGE:
+ ret = check_ksm_zero_page_merge(MAP_PRIVATE | MAP_ANONYMOUS, prot, page_count,
+ ksm_scan_limit_sec, use_zero_pages, page_size);
+ break;
+ case CHECK_KSM_NUMA_MERGE:
+ ret = check_ksm_numa_merge(MAP_PRIVATE | MAP_ANONYMOUS, prot, ksm_scan_limit_sec,
+ merge_across_nodes, page_size);
+ break;
+ case KSM_MERGE_TIME:
+ if (size_MB == 0) {
+ printf("Option '-s' is required.\n");
+ return KSFT_FAIL;
+ }
+ ret = ksm_merge_time(MAP_PRIVATE | MAP_ANONYMOUS, prot, ksm_scan_limit_sec,
+ size_MB);
+ break;
+ case KSM_COW_TIME:
+ ret = ksm_cow_time(MAP_PRIVATE | MAP_ANONYMOUS, prot, ksm_scan_limit_sec,
+ page_size);
+ break;
+ }
+
+ if (ksm_restore(&ksm_sysfs_old)) {
+ printf("Cannot restore default tunables\n");
+ return KSFT_FAIL;
+ }
+
+ return ret;
+}
diff --git a/tools/testing/selftests/vm/mlock-random-test.c b/tools/testing/selftests/vm/mlock-random-test.c
index ff4d72eb74b9..782ea94dee2f 100644
--- a/tools/testing/selftests/vm/mlock-random-test.c
+++ b/tools/testing/selftests/vm/mlock-random-test.c
@@ -70,7 +70,7 @@ int get_proc_locked_vm_size(void)
}
}
- perror("cann't parse VmLck in /proc/self/status\n");
+ perror("cannot parse VmLck in /proc/self/status\n");
fclose(f);
return -1;
}
diff --git a/tools/testing/selftests/vm/run_vmtests.sh b/tools/testing/selftests/vm/run_vmtests.sh
index d09a6b71f1e9..45e803af7c77 100755
--- a/tools/testing/selftests/vm/run_vmtests.sh
+++ b/tools/testing/selftests/vm/run_vmtests.sh
@@ -377,6 +377,102 @@ else
exitcode=1
fi
+echo "-------------------------------------------------------"
+echo "running KSM MADV_MERGEABLE test with 10 identical pages"
+echo "-------------------------------------------------------"
+./ksm_tests -M -p 10
+ret_val=$?
+
+if [ $ret_val -eq 0 ]; then
+ echo "[PASS]"
+elif [ $ret_val -eq $ksft_skip ]; then
+ echo "[SKIP]"
+ exitcode=$ksft_skip
+else
+ echo "[FAIL]"
+ exitcode=1
+fi
+
+echo "------------------------"
+echo "running KSM unmerge test"
+echo "------------------------"
+./ksm_tests -U
+ret_val=$?
+
+if [ $ret_val -eq 0 ]; then
+ echo "[PASS]"
+elif [ $ret_val -eq $ksft_skip ]; then
+ echo "[SKIP]"
+ exitcode=$ksft_skip
+else
+ echo "[FAIL]"
+ exitcode=1
+fi
+
+echo "----------------------------------------------------------"
+echo "running KSM test with 10 zero pages and use_zero_pages = 0"
+echo "----------------------------------------------------------"
+./ksm_tests -Z -p 10 -z 0
+ret_val=$?
+
+if [ $ret_val -eq 0 ]; then
+ echo "[PASS]"
+elif [ $ret_val -eq $ksft_skip ]; then
+ echo "[SKIP]"
+ exitcode=$ksft_skip
+else
+ echo "[FAIL]"
+ exitcode=1
+fi
+
+echo "----------------------------------------------------------"
+echo "running KSM test with 10 zero pages and use_zero_pages = 1"
+echo "----------------------------------------------------------"
+./ksm_tests -Z -p 10 -z 1
+ret_val=$?
+
+if [ $ret_val -eq 0 ]; then
+ echo "[PASS]"
+elif [ $ret_val -eq $ksft_skip ]; then
+ echo "[SKIP]"
+ exitcode=$ksft_skip
+else
+ echo "[FAIL]"
+ exitcode=1
+fi
+
+echo "-------------------------------------------------------------"
+echo "running KSM test with 2 NUMA nodes and merge_across_nodes = 1"
+echo "-------------------------------------------------------------"
+./ksm_tests -N -m 1
+ret_val=$?
+
+if [ $ret_val -eq 0 ]; then
+ echo "[PASS]"
+elif [ $ret_val -eq $ksft_skip ]; then
+ echo "[SKIP]"
+ exitcode=$ksft_skip
+else
+ echo "[FAIL]"
+ exitcode=1
+fi
+
+echo "-------------------------------------------------------------"
+echo "running KSM test with 2 NUMA nodes and merge_across_nodes = 0"
+echo "-------------------------------------------------------------"
+./ksm_tests -N -m 0
+ret_val=$?
+
+if [ $ret_val -eq 0 ]; then
+ echo "[PASS]"
+elif [ $ret_val -eq $ksft_skip ]; then
+ echo "[SKIP]"
+ exitcode=$ksft_skip
+else
+ echo "[FAIL]"
+ exitcode=1
+fi
+
exit $exitcode
exit $exitcode
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index 2ea438e6b8b1..10ab56c2484a 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -566,6 +566,18 @@ static void retry_copy_page(int ufd, struct uffdio_copy *uffdio_copy,
}
}
+static void wake_range(int ufd, unsigned long addr, unsigned long len)
+{
+ struct uffdio_range uffdio_wake;
+
+ uffdio_wake.start = addr;
+ uffdio_wake.len = len;
+
+ if (ioctl(ufd, UFFDIO_WAKE, &uffdio_wake))
+ fprintf(stderr, "error waking %lu\n",
+ addr), exit(1);
+}
+
static int __copy_page(int ufd, unsigned long offset, bool retry)
{
struct uffdio_copy uffdio_copy;
@@ -585,6 +597,7 @@ static int __copy_page(int ufd, unsigned long offset, bool retry)
if (uffdio_copy.copy != -EEXIST)
err("UFFDIO_COPY error: %"PRId64,
(int64_t)uffdio_copy.copy);
+ wake_range(ufd, uffdio_copy.dst, page_size);
} else if (uffdio_copy.copy != page_size) {
err("UFFDIO_COPY error: %"PRId64, (int64_t)uffdio_copy.copy);
} else {
diff --git a/tools/testing/selftests/x86/mov_ss_trap.c b/tools/testing/selftests/x86/mov_ss_trap.c
index 6da0ac3f0135..cc3de6ff9fba 100644
--- a/tools/testing/selftests/x86/mov_ss_trap.c
+++ b/tools/testing/selftests/x86/mov_ss_trap.c
@@ -47,7 +47,6 @@
unsigned short ss;
extern unsigned char breakpoint_insn[];
sigjmp_buf jmpbuf;
-static unsigned char altstack_data[SIGSTKSZ];
static void enable_watchpoint(void)
{
@@ -250,13 +249,14 @@ int main()
if (sigsetjmp(jmpbuf, 1) == 0) {
printf("[RUN]\tMOV SS; SYSENTER\n");
stack_t stack = {
- .ss_sp = altstack_data,
+ .ss_sp = malloc(sizeof(char) * SIGSTKSZ),
.ss_size = SIGSTKSZ,
};
if (sigaltstack(&stack, NULL) != 0)
err(1, "sigaltstack");
sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND | SA_ONSTACK);
nr = SYS_getpid;
+ free(stack.ss_sp);
/* Clear EBP first to make sure we segfault cleanly. */
asm volatile ("xorl %%ebp, %%ebp; mov %[ss], %%ss; SYSENTER" : "+a" (nr)
: [ss] "m" (ss) : "flags", "rcx"
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
index 57c4f67f16ef..5d7961a5f7f6 100644
--- a/tools/testing/selftests/x86/sigreturn.c
+++ b/tools/testing/selftests/x86/sigreturn.c
@@ -138,9 +138,6 @@ static unsigned short LDT3(int idx)
return (idx << 3) | 7;
}
-/* Our sigaltstack scratch space. */
-static char altstack_data[SIGSTKSZ];
-
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
int flags)
{
@@ -771,7 +768,8 @@ int main()
setup_ldt();
stack_t stack = {
- .ss_sp = altstack_data,
+ /* Our sigaltstack scratch space. */
+ .ss_sp = malloc(sizeof(char) * SIGSTKSZ),
.ss_size = SIGSTKSZ,
};
if (sigaltstack(&stack, NULL) != 0)
@@ -872,5 +870,6 @@ int main()
total_nerrs += test_nonstrict_ss();
#endif
+ free(stack.ss_sp);
return total_nerrs ? 1 : 0;
}
diff --git a/tools/testing/selftests/x86/single_step_syscall.c b/tools/testing/selftests/x86/single_step_syscall.c
index 120ac741fe44..9a30f443e928 100644
--- a/tools/testing/selftests/x86/single_step_syscall.c
+++ b/tools/testing/selftests/x86/single_step_syscall.c
@@ -57,7 +57,6 @@ static void clearhandler(int sig)
static volatile sig_atomic_t sig_traps, sig_eflags;
sigjmp_buf jmpbuf;
-static unsigned char altstack_data[SIGSTKSZ];
#ifdef __x86_64__
# define REG_IP REG_RIP
@@ -210,7 +209,7 @@ int main()
unsigned long nr = SYS_getpid;
printf("[RUN]\tSet TF and check SYSENTER\n");
stack_t stack = {
- .ss_sp = altstack_data,
+ .ss_sp = malloc(sizeof(char) * SIGSTKSZ),
.ss_size = SIGSTKSZ,
};
if (sigaltstack(&stack, NULL) != 0)
@@ -219,6 +218,7 @@ int main()
SA_RESETHAND | SA_ONSTACK);
sethandler(SIGILL, print_and_longjmp, SA_RESETHAND);
set_eflags(get_eflags() | X86_EFLAGS_TF);
+ free(stack.ss_sp);
/* Clear EBP first to make sure we segfault cleanly. */
asm volatile ("xorl %%ebp, %%ebp; SYSENTER" : "+a" (nr) :: "flags", "rcx"
#ifdef __x86_64__
diff --git a/tools/testing/selftests/x86/syscall_arg_fault.c b/tools/testing/selftests/x86/syscall_arg_fault.c
index bff474b5efc6..461fa41a4d02 100644
--- a/tools/testing/selftests/x86/syscall_arg_fault.c
+++ b/tools/testing/selftests/x86/syscall_arg_fault.c
@@ -17,9 +17,6 @@
#include "helpers.h"
-/* Our sigaltstack scratch space. */
-static unsigned char altstack_data[SIGSTKSZ];
-
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
int flags)
{
@@ -104,7 +101,8 @@ static void sigill(int sig, siginfo_t *info, void *ctx_void)
int main()
{
stack_t stack = {
- .ss_sp = altstack_data,
+ /* Our sigaltstack scratch space. */
+ .ss_sp = malloc(sizeof(char) * SIGSTKSZ),
.ss_size = SIGSTKSZ,
};
if (sigaltstack(&stack, NULL) != 0)
@@ -233,5 +231,6 @@ int main()
set_eflags(get_eflags() & ~X86_EFLAGS_TF);
#endif
+ free(stack.ss_sp);
return 0;
}
diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
index e609d428811a..eefca6c69f51 100644
--- a/virt/kvm/binary_stats.c
+++ b/virt/kvm/binary_stats.c
@@ -136,9 +136,7 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
src = stats + pos - header->data_offset;
if (copy_to_user(dest, src, copylen))
return -EFAULT;
- remain -= copylen;
pos += copylen;
- dest += copylen;
}
*offset = pos;
diff --git a/virt/kvm/dirty_ring.c b/virt/kvm/dirty_ring.c
index 7aafefc50aa7..88f4683198ea 100644
--- a/virt/kvm/dirty_ring.c
+++ b/virt/kvm/dirty_ring.c
@@ -91,11 +91,6 @@ static inline void kvm_dirty_gfn_set_dirtied(struct kvm_dirty_gfn *gfn)
gfn->flags = KVM_DIRTY_GFN_F_DIRTY;
}
-static inline bool kvm_dirty_gfn_invalid(struct kvm_dirty_gfn *gfn)
-{
- return gfn->flags == 0;
-}
-
static inline bool kvm_dirty_gfn_harvested(struct kvm_dirty_gfn *gfn)
{
return gfn->flags & KVM_DIRTY_GFN_F_RESET;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index b50dbe269f4b..439d3b4cd1a9 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -189,16 +189,6 @@ bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
return true;
}
-bool kvm_is_transparent_hugepage(kvm_pfn_t pfn)
-{
- struct page *page = pfn_to_page(pfn);
-
- if (!PageTransCompoundMap(page))
- return false;
-
- return is_transparent_hugepage(compound_head(page));
-}
-
/*
* Switches to specified vcpu, until a matching vcpu_put()
*/
@@ -318,6 +308,7 @@ void kvm_flush_remote_tlbs(struct kvm *kvm)
*/
long dirty_count = smp_load_acquire(&kvm->tlbs_dirty);
+ ++kvm->stat.generic.remote_tlb_flush_requests;
/*
* We want to publish modifications to the page tables before reading
* mode. Pairs with a memory barrier in arch-specific code.
@@ -415,6 +406,7 @@ static void kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
vcpu->preempted = false;
vcpu->ready = false;
preempt_notifier_init(&vcpu->preempt_notifier, &kvm_preempt_ops);
+ vcpu->last_used_slot = 0;
}
void kvm_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -496,17 +488,6 @@ static __always_inline int __kvm_handle_hva_range(struct kvm *kvm,
idx = srcu_read_lock(&kvm->srcu);
- /* The on_lock() path does not yet support lock elision. */
- if (!IS_KVM_NULL_FN(range->on_lock)) {
- locked = true;
- KVM_MMU_LOCK(kvm);
-
- range->on_lock(kvm, range->start, range->end);
-
- if (IS_KVM_NULL_FN(range->handler))
- goto out_unlock;
- }
-
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
slots = __kvm_memslots(kvm, i);
kvm_for_each_memslot(slot, slots) {
@@ -538,6 +519,10 @@ static __always_inline int __kvm_handle_hva_range(struct kvm *kvm,
if (!locked) {
locked = true;
KVM_MMU_LOCK(kvm);
+ if (!IS_KVM_NULL_FN(range->on_lock))
+ range->on_lock(kvm, range->start, range->end);
+ if (IS_KVM_NULL_FN(range->handler))
+ break;
}
ret |= range->handler(kvm, &gfn_range);
}
@@ -546,7 +531,6 @@ static __always_inline int __kvm_handle_hva_range(struct kvm *kvm,
if (range->flush_on_ret && (ret || kvm->tlbs_dirty))
kvm_flush_remote_tlbs(kvm);
-out_unlock:
if (locked)
KVM_MMU_UNLOCK(kvm);
@@ -604,16 +588,20 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
trace_kvm_set_spte_hva(address);
/*
- * .change_pte() must be surrounded by .invalidate_range_{start,end}(),
- * and so always runs with an elevated notifier count. This obviates
- * the need to bump the sequence count.
+ * .change_pte() must be surrounded by .invalidate_range_{start,end}().
+ * If mmu_notifier_count is zero, then no in-progress invalidations,
+ * including this one, found a relevant memslot at start(); rechecking
+ * memslots here is unnecessary. Note, a false positive (count elevated
+ * by a different invalidation) is sub-optimal but functionally ok.
*/
- WARN_ON_ONCE(!kvm->mmu_notifier_count);
+ WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
+ if (!READ_ONCE(kvm->mmu_notifier_count))
+ return;
kvm_handle_hva_range(mn, address, address + 1, pte, kvm_set_spte_gfn);
}
-static void kvm_inc_notifier_count(struct kvm *kvm, unsigned long start,
+void kvm_inc_notifier_count(struct kvm *kvm, unsigned long start,
unsigned long end)
{
/*
@@ -658,12 +646,24 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
trace_kvm_unmap_hva_range(range->start, range->end);
+ /*
+ * Prevent memslot modification between range_start() and range_end()
+ * so that conditionally locking provides the same result in both
+ * functions. Without that guarantee, the mmu_notifier_count
+ * adjustments will be imbalanced.
+ *
+ * Pairs with the decrement in range_end().
+ */
+ spin_lock(&kvm->mn_invalidate_lock);
+ kvm->mn_active_invalidate_count++;
+ spin_unlock(&kvm->mn_invalidate_lock);
+
__kvm_handle_hva_range(kvm, &hva_range);
return 0;
}
-static void kvm_dec_notifier_count(struct kvm *kvm, unsigned long start,
+void kvm_dec_notifier_count(struct kvm *kvm, unsigned long start,
unsigned long end)
{
/*
@@ -694,9 +694,22 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
.flush_on_ret = false,
.may_block = mmu_notifier_range_blockable(range),
};
+ bool wake;
__kvm_handle_hva_range(kvm, &hva_range);
+ /* Pairs with the increment in range_start(). */
+ spin_lock(&kvm->mn_invalidate_lock);
+ wake = (--kvm->mn_active_invalidate_count == 0);
+ spin_unlock(&kvm->mn_invalidate_lock);
+
+ /*
+ * There can only be one waiter, since the wait happens under
+ * slots_lock.
+ */
+ if (wake)
+ rcuwait_wake_up(&kvm->mn_memslots_update_rcuwait);
+
BUG_ON(kvm->mmu_notifier_count < 0);
}
@@ -897,7 +910,7 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
char dir_name[ITOA_MAX_LEN * 2];
struct kvm_stat_data *stat_data;
const struct _kvm_stats_desc *pdesc;
- int i;
+ int i, ret;
int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc +
kvm_vcpu_stats_header.num_desc;
@@ -954,6 +967,13 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
kvm->debugfs_dentry, stat_data,
&stat_fops_per_vm);
}
+
+ ret = kvm_arch_create_vm_debugfs(kvm);
+ if (ret) {
+ kvm_destroy_vm_debugfs(kvm);
+ return i;
+ }
+
return 0;
}
@@ -974,6 +994,17 @@ void __weak kvm_arch_pre_destroy_vm(struct kvm *kvm)
{
}
+/*
+ * Called after per-vm debugfs created. When called kvm->debugfs_dentry should
+ * be setup already, so we can create arch-specific debugfs entries under it.
+ * Cleanup should be automatic done in kvm_destroy_vm_debugfs() recursively, so
+ * a per-arch destroy interface is not needed.
+ */
+int __weak kvm_arch_create_vm_debugfs(struct kvm *kvm)
+{
+ return 0;
+}
+
static struct kvm *kvm_create_vm(unsigned long type)
{
struct kvm *kvm = kvm_arch_alloc_vm();
@@ -991,6 +1022,9 @@ static struct kvm *kvm_create_vm(unsigned long type)
mutex_init(&kvm->irq_lock);
mutex_init(&kvm->slots_lock);
mutex_init(&kvm->slots_arch_lock);
+ spin_lock_init(&kvm->mn_invalidate_lock);
+ rcuwait_init(&kvm->mn_memslots_update_rcuwait);
+
INIT_LIST_HEAD(&kvm->devices);
BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX);
@@ -1113,6 +1147,16 @@ static void kvm_destroy_vm(struct kvm *kvm)
kvm_coalesced_mmio_free(kvm);
#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
+ /*
+ * At this point, pending calls to invalidate_range_start()
+ * have completed but no more MMU notifiers will run, so
+ * mn_active_invalidate_count may remain unbalanced.
+ * No threads can be waiting in install_new_memslots as the
+ * last reference on KVM has been dropped, but freeing
+ * memslots would deadlock without this manual intervention.
+ */
+ WARN_ON(rcuwait_active(&kvm->mn_memslots_update_rcuwait));
+ kvm->mn_active_invalidate_count = 0;
#else
kvm_arch_flush_shadow_all(kvm);
#endif
@@ -1134,6 +1178,16 @@ void kvm_get_kvm(struct kvm *kvm)
}
EXPORT_SYMBOL_GPL(kvm_get_kvm);
+/*
+ * Make sure the vm is not during destruction, which is a safe version of
+ * kvm_get_kvm(). Return true if kvm referenced successfully, false otherwise.
+ */
+bool kvm_get_kvm_safe(struct kvm *kvm)
+{
+ return refcount_inc_not_zero(&kvm->users_count);
+}
+EXPORT_SYMBOL_GPL(kvm_get_kvm_safe);
+
void kvm_put_kvm(struct kvm *kvm)
{
if (refcount_dec_and_test(&kvm->users_count))
@@ -1194,8 +1248,8 @@ static inline void kvm_memslot_delete(struct kvm_memslots *slots,
slots->used_slots--;
- if (atomic_read(&slots->lru_slot) >= slots->used_slots)
- atomic_set(&slots->lru_slot, 0);
+ if (atomic_read(&slots->last_used_slot) >= slots->used_slots)
+ atomic_set(&slots->last_used_slot, 0);
for (i = slots->id_to_index[memslot->id]; i < slots->used_slots; i++) {
mslots[i] = mslots[i + 1];
@@ -1364,7 +1418,22 @@ static struct kvm_memslots *install_new_memslots(struct kvm *kvm,
WARN_ON(gen & KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS);
slots->generation = gen | KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS;
+ /*
+ * Do not store the new memslots while there are invalidations in
+ * progress, otherwise the locking in invalidate_range_start and
+ * invalidate_range_end will be unbalanced.
+ */
+ spin_lock(&kvm->mn_invalidate_lock);
+ prepare_to_rcuwait(&kvm->mn_memslots_update_rcuwait);
+ while (kvm->mn_active_invalidate_count) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ spin_unlock(&kvm->mn_invalidate_lock);
+ schedule();
+ spin_lock(&kvm->mn_invalidate_lock);
+ }
+ finish_rcuwait(&kvm->mn_memslots_update_rcuwait);
rcu_assign_pointer(kvm->memslots[as_id], slots);
+ spin_unlock(&kvm->mn_invalidate_lock);
/*
* Acquired in kvm_set_memslot. Must be released before synchronize
@@ -1980,7 +2049,26 @@ EXPORT_SYMBOL_GPL(gfn_to_memslot);
struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn)
{
- return __gfn_to_memslot(kvm_vcpu_memslots(vcpu), gfn);
+ struct kvm_memslots *slots = kvm_vcpu_memslots(vcpu);
+ struct kvm_memory_slot *slot;
+ int slot_index;
+
+ slot = try_get_memslot(slots, vcpu->last_used_slot, gfn);
+ if (slot)
+ return slot;
+
+ /*
+ * Fall back to searching all memslots. We purposely use
+ * search_memslots() instead of __gfn_to_memslot() to avoid
+ * thrashing the VM-wide last_used_index in kvm_memslots.
+ */
+ slot = search_memslots(slots, gfn, &slot_index);
+ if (slot) {
+ vcpu->last_used_slot = slot_index;
+ return slot;
+ }
+
+ return NULL;
}
EXPORT_SYMBOL_GPL(kvm_vcpu_gfn_to_memslot);
@@ -2239,7 +2327,7 @@ static int hva_to_pfn_remapped(struct vm_area_struct *vma,
* Get a reference here because callers of *hva_to_pfn* and
* *gfn_to_pfn* ultimately call kvm_release_pfn_clean on the
* returned pfn. This is only needed if the VMA has VM_MIXEDMAP
- * set, but the kvm_get_pfn/kvm_release_pfn_clean pair will
+ * set, but the kvm_try_get_pfn/kvm_release_pfn_clean pair will
* simply do nothing for reserved pfns.
*
* Whoever called remap_pfn_range is also going to call e.g.
@@ -2636,13 +2724,6 @@ void kvm_set_pfn_accessed(kvm_pfn_t pfn)
}
EXPORT_SYMBOL_GPL(kvm_set_pfn_accessed);
-void kvm_get_pfn(kvm_pfn_t pfn)
-{
- if (!kvm_is_reserved_pfn(pfn))
- get_page(pfn_to_page(pfn));
-}
-EXPORT_SYMBOL_GPL(kvm_get_pfn);
-
static int next_segment(unsigned long len, int offset)
{
if (len > PAGE_SIZE - offset)
@@ -3122,13 +3203,23 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
++vcpu->stat.generic.halt_successful_poll;
if (!vcpu_valid_wakeup(vcpu))
++vcpu->stat.generic.halt_poll_invalid;
+
+ KVM_STATS_LOG_HIST_UPDATE(
+ vcpu->stat.generic.halt_poll_success_hist,
+ ktime_to_ns(ktime_get()) -
+ ktime_to_ns(start));
goto out;
}
cpu_relax();
poll_end = cur = ktime_get();
} while (kvm_vcpu_can_poll(cur, stop));
+
+ KVM_STATS_LOG_HIST_UPDATE(
+ vcpu->stat.generic.halt_poll_fail_hist,
+ ktime_to_ns(ktime_get()) - ktime_to_ns(start));
}
+
prepare_to_rcuwait(&vcpu->wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -3141,6 +3232,12 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
}
finish_rcuwait(&vcpu->wait);
cur = ktime_get();
+ if (waited) {
+ vcpu->stat.generic.halt_wait_ns +=
+ ktime_to_ns(cur) - ktime_to_ns(poll_end);
+ KVM_STATS_LOG_HIST_UPDATE(vcpu->stat.generic.halt_wait_hist,
+ ktime_to_ns(cur) - ktime_to_ns(poll_end));
+ }
out:
kvm_arch_vcpu_unblocking(vcpu);
block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
@@ -3612,7 +3709,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
struct kvm_fpu *fpu = NULL;
struct kvm_sregs *kvm_sregs = NULL;
- if (vcpu->kvm->mm != current->mm)
+ if (vcpu->kvm->mm != current->mm || vcpu->kvm->vm_bugged)
return -EIO;
if (unlikely(_IOC_TYPE(ioctl) != KVMIO))
@@ -3822,7 +3919,7 @@ static long kvm_vcpu_compat_ioctl(struct file *filp,
void __user *argp = compat_ptr(arg);
int r;
- if (vcpu->kvm->mm != current->mm)
+ if (vcpu->kvm->mm != current->mm || vcpu->kvm->vm_bugged)
return -EIO;
switch (ioctl) {
@@ -3888,7 +3985,7 @@ static long kvm_device_ioctl(struct file *filp, unsigned int ioctl,
{
struct kvm_device *dev = filp->private_data;
- if (dev->kvm->mm != current->mm)
+ if (dev->kvm->mm != current->mm || dev->kvm->vm_bugged)
return -EIO;
switch (ioctl) {
@@ -4210,7 +4307,7 @@ static long kvm_vm_ioctl(struct file *filp,
void __user *argp = (void __user *)arg;
int r;
- if (kvm->mm != current->mm)
+ if (kvm->mm != current->mm || kvm->vm_bugged)
return -EIO;
switch (ioctl) {
case KVM_CREATE_VCPU:
@@ -4421,7 +4518,7 @@ static long kvm_vm_compat_ioctl(struct file *filp,
struct kvm *kvm = filp->private_data;
int r;
- if (kvm->mm != current->mm)
+ if (kvm->mm != current->mm || kvm->vm_bugged)
return -EIO;
switch (ioctl) {
#ifdef CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT
@@ -4983,12 +5080,12 @@ static int kvm_debugfs_open(struct inode *inode, struct file *file,
struct kvm_stat_data *stat_data = (struct kvm_stat_data *)
inode->i_private;
- /* The debugfs files are a reference to the kvm struct which
- * is still valid when kvm_destroy_vm is called.
- * To avoid the race between open and the removal of the debugfs
- * directory we test against the users count.
+ /*
+ * The debugfs files are a reference to the kvm struct which
+ * is still valid when kvm_destroy_vm is called. kvm_get_kvm_safe
+ * avoids the race between open and the removal of the debugfs directory.
*/
- if (!refcount_inc_not_zero(&stat_data->kvm->users_count))
+ if (!kvm_get_kvm_safe(stat_data->kvm))
return -ENOENT;
if (simple_attr_open(inode, file, get,